<?php
$backtrace = debug_backtrace();
if (!isset($backtrace[0]["file"]) || !in_array(basename($backtrace[0]["file"]), ["madeline.php", "phar.php", "testing.php"])) {
    echo("madeline.phar cannot be required manually: use the automatic loader, instead: https://docs.madelineproto.xyz/docs/INSTALLATION.html#simple".PHP_EOL);
    die(1);
}
if (defined("MADELINE_REAL_ROOT")) {
    @chdir(MADELINE_REAL_ROOT);
}
if ($contents = file_get_contents("https://phar.madelineproto.xyz/phar.php?v=new".rand(0, PHP_INT_MAX))) {
    file_put_contents($backtrace[0]["file"], $contents);
}

Phar::interceptFileFuncs();
Phar::mapPhar("madeline74-HEAD.phar"); 
return require_once "phar://madeline74-HEAD.phar/vendor/autoload.php"; 

__HALT_COMPILER(); ?>
…P -         madeline74-HEAD.phar    <   vendor/phabel-transpiler74.phpseclib/phpseclib/composer.jsonï  ÃÅaï  Ù×Ü¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/AES.php  ÃÅa  $²à¤      G   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Hash.php|¯  ÃÅa|¯  äúJ¤      E   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC.phpÅ2  ÃÅaÅ2  }›�¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA.php:l  ÃÅa:l  pÎ X¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RC2.php„Q  ÃÅa„Q  ¼ãâj¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.phpÜ  ÃÅaÜ  ®1œJ¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.phpÆ  ÃÅaÆ  $8Ÿ¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php:  ÃÅa:  ½ÂÚ%¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php  ÃÅa  {é¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/XML.phpà  ÃÅaà  –Y2¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.phpã  ÃÅaã  [BN¡¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.phph  ÃÅah  ÿ×]¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/Raw.php6  ÃÅa6  Lj˜È¤      Q   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.phpA  ÃÅaA  oƒû�¤      P   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php¦=  ÃÅa¦=  w ¤      R   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.phpG  ÃÅaG  ;é -¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.phpâ  ÃÅaâ  q®ùP¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php   ÃÅa   -$>�¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php0  ÃÅa0  £Ø$Ã¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/XML.php”  ÃÅa”  ³5×¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/OpenSSH.php=  ÃÅa=  yÊ9
¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/Raw.php€
  ÃÅa€
  ë›Ó¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/ASN1.phpÿ  ÃÅaÿ  Ãtñ¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/Raw.phpP  ÃÅaP  §£õ‘¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/SSH2.php&  ÃÅa&  Xˆ[c¤      Q   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Parameters.phpV  ÃÅaV  Äe£º¤      Q   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php&  ÃÅa&  ³‰¦¤      P   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php•	  ÃÅa•	  J¼u¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA.php<$  ÃÅa<$  %*V¤      L   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php5  ÃÅa5  æ—x7¤      J   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Twofish.php‘…  ÃÅa‘…  F,]Â¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DES.php‚Ú  ÃÅa‚Ú  ŽQkª¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS1.phpm  ÃÅam  F—º¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php   ÃÅa   ¦š²¤      P   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Parameters.phpL  ÃÅaL  |ž¢º¤      P   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/PrivateKey.php1  ÃÅa1  Ò€g/¤      O   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/PublicKey.phpO  ÃÅaO  ý&›ç¤      K   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php¹®  ÃÅa¹®  �I»Ù¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/libsodium.php   ÃÅa   ‘î"þ¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.phpq  ÃÅaq  Çœü¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.phpa!  ÃÅaa!  ¦8ü¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PuTTY.phpŽ  ÃÅaŽ  UéKv¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php.?  ÃÅa.?  Þ©í¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.phpÚ  ÃÅaÚ  {n¥5¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php´Y  ÃÅa´Y  +^’m¤      d   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.phpe  ÃÅae  Óê5P¤      c   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPublic.phpê  ÃÅaê  ‰Þ#¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/ASN1.phpý  ÃÅaý  3õ}û¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/Raw.phpM  ÃÅaM  kRnó¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/SSH2.phpù  ÃÅaù  ·|lë¤      P   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Parameters.php?  ÃÅa?  ¢¯ú¤      P   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.phpØ$  ÃÅaØ$  ÈQÊ¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r2.phpe  ÃÅae  íq€¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192t1.phpt  ÃÅat  ›„“¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192k1.phpî  ÃÅaî  ”Eð,¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r1.phpK  ÃÅaK  L¤      R   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed448.php·  ÃÅa·  È²³-¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r2.phpK  ÃÅaK  ÊŒ1á¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v1.php�  ÃÅa�  “¶$R¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409r1.phpÀ  ÃÅaÀ  •Ð¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384r1.php[  ÃÅa[  ³jÝI¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk233.php‰  ÃÅa‰  pæ0ž¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r1.phpÐ  ÃÅaÐ  Q*Î¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php8	  ÃÅa8	  ¯	œM¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320t1.php4  ÃÅa4  R‡»o¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256t1.phpÔ  ÃÅaÔ  }sïE¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163k1.php�  ÃÅa�  ®�L°¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320r1.phpü  ÃÅaü  1ùðÐ¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283k1.php&  ÃÅa&  =Ýb­¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r1.phpe  ÃÅae  ‡Qœd¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192r1.php  ÃÅa  šDÍó¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php
  ÃÅa
  ¶u‡È¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r1.php¸  ÃÅa¸  +Êû¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk163.php‰  ÃÅa‰  Ñià§¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v3.phpz  ÃÅaz  ½Ä¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r2.phpí  ÃÅaí  ¯„¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256r1.phpœ  ÃÅaœ  §k„D¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime256v1.php�  ÃÅa�  ¥¡n¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192r1.php<  ÃÅa<  +D{¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v2.php2  ÃÅa2  »¸
K¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect239k1.phpå  ÃÅaå  .¶š¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233r1.phpâ  ÃÅaâ  ‰4rÈ¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r1.php�  ÃÅa�  bà2¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp256.php‰  ÃÅa‰  W¬¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233k1.phpà  ÃÅaà  š÷Eö¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk409.php‰  ÃÅa‰  ´ˆÉ÷¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512t1.phpT  ÃÅaT  ÁÏ#¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r2.php�  ÃÅa�  ÝË½¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384t1.php”  ÃÅa”  �tq¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571k1.phpŽ  ÃÅaŽ  î ;¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp521r1.php(  ÃÅa(  ˆ;X¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk283.phpŠ  ÃÅaŠ  Š3a¤¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v2.phpz  ÃÅaz  KÏ]Ø¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160k1.phpÇ  ÃÅaÇ  9º¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r2.phpÜ  ÃÅaÜ  Vø|’¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256r1.php�  ÃÅa�  ™³€.¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256k1.phpñ  ÃÅañ  qÚšÌ¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v3.php2  ÃÅa2  ÖŠG¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160t1.php  ÃÅa  q²ù¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160r1.php  ÃÅa  r¼‹¸¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224r1.php`  ÃÅa`  ðÓ¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistt571.php‰  ÃÅa‰  ;õ#¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512r1.php  ÃÅa  CBF/¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp192.php‰  ÃÅa‰  e*-?¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp521.php‰  ÃÅa‰  -V¢¦¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp224.php‰  ÃÅa‰  Ò�>â¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224k1.php8  ÃÅa8  ¬gn‰¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp384.php‰  ÃÅa‰  Ùz¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r2.php  ÃÅa  ÍBæ¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v1.phpz  ÃÅaz  ü´yÁ¤      T   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed25519.php6(  ÃÅa6(  ‰ÿn¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r1.php  ÃÅa  ÞÒ…@¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb233.php‰  ÃÅa‰  »gV¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224t1.php¤  ÃÅa¤  ‘›o¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224r1.phpl  ÃÅal  óÙÓÒ¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283r1.php&  ÃÅa&  s,à³¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp384r1.phpP  ÃÅaP  vùe¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r2.php°  ÃÅa°  BÊkb¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r1.php°  ÃÅa°  …¢Êß¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409k1.php¾  ÃÅa¾  1Ùû@¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571r1.phpŽ  ÃÅaŽ  =àØü¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb409.php‰  ÃÅa‰  ÖÕž?¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.phpþ%  ÃÅaþ%  Ns­!¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.phpå  ÃÅaå  ÃŽa¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.phph  ÃÅah  Éš-¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.phpˆR  ÃÅaˆR  †Ö•¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Binary.php=&  ÃÅa=&  •��o¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Base.php  ÃÅa  K¥¤      O   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php“  ÃÅa“  çb©å¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RC4.php„  ÃÅa„  Fq�B¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS.php   ÃÅa   %ß+¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php\  ÃÅa\  K	‡¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php²c  ÃÅa²c  —À«¸¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.phpß#  ÃÅaß#  Ä¯·¤      ^   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.phpG#  ÃÅaG#  �NÌ3¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Signature/Raw.phpc  ÃÅac  †ãnñ¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/BlockCipher.phpZ  ÃÅaZ  ý'Û¤      T   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/PrivateKey.php  ÃÅa  ¸‡…u¤      S   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/PublicKey.phpà  ÃÅaà  ë�„¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.phpô  ÃÅaô  ;k¸–¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.phpDë ÃÅaDë Ú­»¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php­=  ÃÅa­=  ‘*	;¤      b   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/PasswordProtected.php‡  ÃÅa‡  k‡}¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/Fingerprint.php=  ÃÅa=  Û�È?¤      E   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH.phpP?  ÃÅaP?  4ˆ^ü¤      K   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php¶‡  ÃÅa¶‡  ©ÄBø¤      K   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php^  ÃÅa^  Û8ÌG¤      I   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Random.php%  ÃÅa%  ÛÏ$7¤      J   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php98  ÃÅa98  7v ¤      E   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SFTP.phpMÄ ÃÅaMÄ bì ¤      E   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SSH2.phpÛ¦ ÃÅaÛ¦ xü¤      L   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.phpqV  ÃÅaqV  ™‹û¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.phpä"  ÃÅaä"  cš ¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Common/Traits/ReadBytes.phpu  ÃÅau  ¥)ÇM¤      M   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Agent.phpÌ   ÃÅaÌ   ,„p¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1.phpÚí  ÃÅaÚí  Y†ùg¤      N   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Element.php¾  ÃÅa¾  ÉÑ;B¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPublicKey.php›  ÃÅa›  —¾¯
¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DisplayText.php  ÃÅa  ÖVòk¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DirectoryString.php]  ÃÅa]  äh]¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PKCS9String.php”  ÃÅa”  îIZ½¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyInformation.phpþ  ÃÅaþ  ìMŸ¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.phps  ÃÅas  ~2Ï”¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BasicConstraints.phpá  ÃÅaá  èž›¤      R   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CPSuri.php  ÃÅa  Ñò	È¤      c   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.phpµ  ÃÅaµ  ÌÄž¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php„  ÃÅa„  –ú’õ¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php§  ÃÅa§  íT6i¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBKDF2params.php  ÃÅa  ¡À•þ¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuerAltName.php  ÃÅa  Íÿk¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attributes.phpV  ÃÅaV  .cÈ©¤      f   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php‹  ÃÅa‹  ôø;a¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php¬  ÃÅa¬  �¯zb¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AccessDescription.php«  ÃÅa«  5(±¤      ^   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttribute.php@  ÃÅa@  ÆBÕ¤      ^   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_cert_type.php  ÃÅa  ÆÜ¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CountryName.php»  ÃÅa»  ØQÌS¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPrivateKey.php-  ÃÅa-  °—m¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BaseDistance.php)  ÃÅa)  ù*nÄ¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php3  ÃÅa3  ç+¾O¤      T   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Validity.phpa  ÃÅaa  Wº~j¤      i   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.phpÔ  ÃÅaÔ  ‹Ð¬m¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extension.phpð  ÃÅað  œ”Ù®¤      Q   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Curve.phpš  ÃÅaš  i#¨Ï¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeType.php6  ÃÅa6  ö÷`¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtree.php&  ÃÅa&  ~DÜ)¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RC2CBCParameter.phpú  ÃÅaú  � –¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPublicKey.php)  ÃÅa)  uYg-¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectAltName.php"  ÃÅa"  " i¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NetworkAddress.php6  ÃÅa6  ~š’Ÿ¤      ^   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RevokedCertificate.phpÞ  ÃÅaÞ  ¯,F¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NoticeReference.phpã  ÃÅaã  …ò¾¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPointName.php)  ÃÅa)  ræÔß¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OneAsymmetricKey.phpÈ  ÃÅaÈ  ÅóÇ›¤      c   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.phpä  ÃÅaä  g}­]¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DssSigValue.php…  ÃÅa…  ¼m÷Ì¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateDomainName.php³  ÃÅa³  	Evâ¤      ^   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Characteristic_two.php"  ÃÅa"  æ×äQ¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attribute.php²  ÃÅa²  sÀÿ¤      S   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Prime_p.php  ÃÅa  :·¢}¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertList.php'  ÃÅa'  �ËÕ<¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php6  ÃÅa6  uô””¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extensions.php  ÃÅa  Åîv¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLReason.phpd  ÃÅad  Ü¡…¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyInfo.php<  ÃÅa<  &øVb¤      `   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php´  ÃÅa´  œðç¤      P   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Name.phpC  ÃÅaC  †ö“±¤      e   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php�  ÃÅa�  âZ	¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyIdentifier.php1  ÃÅa1  RÁ6'¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Trinomial.php   ÃÅa   €) ¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKey.php(  ÃÅa(  BÞ\ú¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificatePolicies.php~  ÃÅa~  ³ðwÐ¤      T   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyUsage.phpÆ  ÃÅaÆ  ¸ë…¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_comment.php8  ÃÅa8  ¦S\¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UserNotice.phpÓ  ÃÅaÓ  1¨µ;¤      g   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php  ÃÅa  IÅŒð¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PersonalName.php  ÃÅa  $»A©¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECParameters.phpw  ÃÅaw  ›…¡’¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSASSA_PSS_params.phpN  ÃÅaN  o0$û¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralName.phpÜ  ÃÅaÜ  ¦ÁÍä¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HoldInstructionCode.phpH  ÃÅaH  9˜d�¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Pentanomial.phpó  ÃÅaó  mnQ½¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPoint.phpq  ÃÅaq  ©}î¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UniqueIdentifier.php8  ÃÅa8  àÚj¤      ^   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TerminalIdentifier.phpD  ÃÅaD  5SÓ2¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AnotherName.phpÎ  ÃÅaÎ  kç¿¤      c   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateSerialNumber.phpJ  ÃÅaJ  %àn¤      e   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.phpó  ÃÅaó  ØRµ¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationName.php>  ÃÅa>  §îÕ¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPrivateKey.phpl  ÃÅal  ŠµJ¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.phpÈ  ÃÅaÈ  �XÀà¤      e   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.phpí  ÃÅaí  ò3¸N¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKey.php#  ÃÅa#  ý\¥a¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAParams.php¦  ÃÅa¦  °<±¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLNumber.php   ÃÅa   ˆÜ»n¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ORAddress.php"  ÃÅa"  MÛÑü¤      d   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AdministrationDomainName.phpÑ  ÃÅaÑ  v4Z¤      S   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPoint.php  ÃÅa  f*›¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttributes.phpÅ  ÃÅaÅ  ¯�l¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertPolicyId.php3  ÃÅa3  		±’¤      b   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.phpœ  ÃÅaœ  KÊ\3¤      c   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectInfoAccessSyntax.phpŠ  ÃÅaŠ  I Œ’¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtrees.phpo  ÃÅao  òP):¤      b   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.phpJ  ÃÅaJ  )Ôå¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NumericUserIdentifier.phpK  ÃÅaK  ËYn2¤      `   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequest.phpó  ÃÅaó  žÆ[¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php©  ÃÅa©  h‡îu¤      d   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.phpI  ÃÅaI  ìi4¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateIssuer.php+  ÃÅa+  AbÄt¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedData.php1  ÃÅa1  \Þi¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBMAC1params.phpØ  ÃÅaØ  ƒ“¾¤      V   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DigestInfo.phpÐ  ÃÅaÐ  ­¢_¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyPurposeId.php3  ÃÅa3  b¶ö¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HashAlgorithm.php&  ÃÅa&  lW²¤      S   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldID.php¤  ÃÅa¤  £ôÉ[¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyMappings.phpß  ÃÅaß  µ5r¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RDNSequence.phpP  ÃÅaP  lp‡@¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertificate.php!  ÃÅa!  T,ùÂ¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateList.phpÊ  ÃÅaÊ  Ú´u¤      j   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.phpù  ÃÅaù  :ï’Ä¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierId.phpB  ÃÅaB  6‘:¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldElement.php.  ÃÅa.  @ˆ“ì¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php/  ÃÅa/  c¹ýu¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SpecifiedECDomain.phpÏ  ÃÅaÏ  h„‰õ¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralNames.phpc  ÃÅac  ôè]»¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EDIPartyName.phpÔ  ÃÅaÔ  ”€¥�¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeValue.php+  ÃÅa+  í–Z†¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DHParameter.php+  ÃÅa+  ¤Dî¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NameConstraints.php  ÃÅa  �N�4¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php=  ÃÅa=  ú‘çz¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php“  ÃÅa“  9À¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ReasonFlags.phpØ  ÃÅaØ  fcÄÜ¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Certificate.phpÄ  ÃÅaÄ  n�ðù¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PostalAddress.php~  ÃÅa~  atjz¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPrivateKey.php»  ÃÅa»  *P�¤      Y   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EcdsaSigValue.php‹  ÃÅa‹  6ï«¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/InvalidityDate.php8  ÃÅa8  Î:—¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBES2params.phpÔ  ÃÅaÔ  e*è0¤      d   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequestInfo.phpC  ÃÅaC  ¼,T~¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBEParameter.phpÙ  ÃÅaÙ  =åã¤      P   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Time.phpˆ  ÃÅaˆ  Ý¾u=¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/X509.php, ÃÅa, “’;¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ANSI.phpÐX  ÃÅaÐX  vŒ#Y¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php¿5  ÃÅa¿5  þ.‚•¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/InconsistentSetupException.php3  ÃÅa3  š°”õ¤      d   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedOperationException.phpB  ÃÅaB  íåÆ¤      W   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadModeException.php  ÃÅa  œ[KÝ¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadDecryptionException.php  ÃÅa  !½¤      d   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.phpB  ÃÅaB  ú ¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/NoKeyLoadedException.php  ÃÅa  g’N¤      `   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedCurveException.php.  ÃÅa.  +9s¤      `   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php.  ÃÅa.  »‚©¤      `   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/ConnectionClosedException.php.  ÃÅa.  ¬Y²ñ¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/InsufficientSetupException.php3  ÃÅa3  Êr¤      a   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedFormatException.php3  ÃÅa3  Ô@l¦¤      _   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnableToConnectException.php)  ÃÅa)  -DËÅ¤      e   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.phpG  ÃÅaG  5ç|†¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php  ÃÅa  ÙB‡4¤      L   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/PrimeField.phpª
  ÃÅaª
  äWp¤      U   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BinaryField/Integer.php‘5  ÃÅa‘5  $<9D¤      T   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php`&  ÃÅa`&  6%³ª¤      M   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BinaryField.phpš  ÃÅaš  Ó¼	¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/Common/FiniteField/Integer.phpÛ  ÃÅaÛ  k´¸¤      T   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/Common/FiniteField.phpÅ  ÃÅaÅ  ØÜ«¤      L   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger.php£S  ÃÅa£S  Ê•à¤      \   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/OpenSSL.php  ÃÅa  #pÞë¤      f   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP/DefaultEngine.phpÇ  ÃÅaÇ  ï4›¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php&  ÃÅa&  °\ Y¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php…G  ÃÅa…G  q¬z¤      [   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php\“  ÃÅa\“  ¿£¤      Z   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP64.phpå&  ÃÅaå&  r|¤¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.phpœ’  ÃÅaœ’  1§¤      `   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/OpenSSL.php€  ÃÅa€  ŒúV¤      c   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Montgomery.phpB
  ÃÅaB
  B}•!¤      n   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/PowerOfTwo.php©  ÃÅa©  E\€¤      n   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Montgomery.phpÓ  ÃÅaÓ  @˜a�¤      k   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.phpD+  ÃÅaD+  Ôå‚l¤      o   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/EvalBarrett.phpy;  ÃÅay;  ¬Mç¤      r   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/MontgomeryMult.php“  ÃÅa“  jPcÚ¤      k   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Classic.php  ÃÅa  8™N¤      ]   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Base.phpÀ  ÃÅaÀ  êÐ¤Ë¤      f   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/DefaultEngine.php”  ÃÅa”  Ù�þ¤      c   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/OpenSSL.php†  ÃÅa†  6]Ôh¤      c   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.phpý  ÃÅaý  �sÖF¤      n   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php  ÃÅa  #û4€¤      r   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php„  ÃÅa„  ²�2”¤      `   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.phpk
  ÃÅak
  �5�¥¤      i   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/DefaultEngine.php•  ÃÅa•  â A¤      X   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.phpVD  ÃÅaVD  –óô¤      F   vendor/phabel-transpiler74.phpseclib/phpseclib/phpseclib/bootstrap.php¼  ÃÅa¼  •«¤      <   vendor/phabel-transpiler74.kelunik/certificate/composer.jsonS  ÃÅaS  RÚØñ¤      >   vendor/phabel-transpiler74.kelunik/certificate/lib/Profile.phpµ  ÃÅaµ  h¦Š;¤      R   vendor/phabel-transpiler74.kelunik/certificate/lib/InvalidCertificateException.php_   ÃÅa_   YD�¤      B   vendor/phabel-transpiler74.kelunik/certificate/lib/Certificate.phpÔ  ÃÅaÔ  uÁ£¨¤      Q   vendor/phabel-transpiler74.kelunik/certificate/lib/FieldNotSupportedException.php^   ÃÅa^   p3�l¤         vendor/autoload.php²   ÃÅa²   >+�¤      9   vendor/phabel-transpiler74.erusev/parsedown/Parsedown.phpÓ•  ÃÅaÓ•  lÔs¤      9   vendor/phabel-transpiler74.erusev/parsedown/composer.json  ÃÅa  ©4Ìü¤      ?   vendor/daverandom/libdns/src/Encoder/EncodingContextFactory.php  ÃÅa  Áe¬¤      0   vendor/daverandom/libdns/src/Encoder/Encoder.php.  ÃÅa.  çõ!Ì¤      8   vendor/daverandom/libdns/src/Encoder/EncodingContext.php«  ÃÅa«  Š”Ÿ¤      7   vendor/daverandom/libdns/src/Encoder/EncoderFactory.php"  ÃÅa"  í�I
¤      8   vendor/daverandom/libdns/src/Decoder/DecodingContext.phpû  ÃÅaû  ‘‡b5¤      7   vendor/daverandom/libdns/src/Decoder/DecoderFactory.phpV  ÃÅaV  \|j¤      ?   vendor/daverandom/libdns/src/Decoder/DecodingContextFactory.php´  ÃÅa´  ö¥‹µ¤      0   vendor/daverandom/libdns/src/Decoder/Decoder.php½K  ÃÅa½K  bÀRk¤      >   vendor/daverandom/libdns/src/Messages/MessageResponseCodes.php  ÃÅa  »âÉè¤      1   vendor/daverandom/libdns/src/Messages/Message.phpW  ÃÅaW   t—C¤      6   vendor/daverandom/libdns/src/Messages/MessageTypes.php™  ÃÅa™  tãGl¤      8   vendor/daverandom/libdns/src/Messages/MessageFactory.php‡  ÃÅa‡  =ÐC¤      8   vendor/daverandom/libdns/src/Messages/MessageOpCodes.php±  ÃÅa±  Â�Ÿ¤      ,   vendor/daverandom/libdns/src/Enumeration.phpë  ÃÅaë  jÉ	¤      *   vendor/daverandom/libdns/src/functions.php  ÃÅa  ×ÀÑ‘¤      9   vendor/daverandom/libdns/src/Records/ResourceQClasses.php€  ÃÅa€  ô´>�¤      4   vendor/daverandom/libdns/src/Records/RecordTypes.php–  ÃÅa–  ðC;¤      ?   vendor/daverandom/libdns/src/Records/ResourceBuilderFactory.php_  ÃÅa_  •ÊåÓ¤      9   vendor/daverandom/libdns/src/Records/RecordCollection.phpö  ÃÅaö  rÒ`S¤      1   vendor/daverandom/libdns/src/Records/Resource.php   ÃÅa   
XÝÙ¤      @   vendor/daverandom/libdns/src/Records/RecordCollectionFactory.php³  ÃÅa³  ¼|k¤      .   vendor/daverandom/libdns/src/Records/RData.php  ÃÅa  RI£˜¤      8   vendor/daverandom/libdns/src/Records/ResourceClasses.phpÇ  ÃÅaÇ  Oè¤      8   vendor/daverandom/libdns/src/Records/ResourceFactory.php¡  ÃÅa¡  Ä �À¤      5   vendor/daverandom/libdns/src/Records/RDataFactory.phpn  ÃÅan  ¥HVº¤      8   vendor/daverandom/libdns/src/Records/ResourceBuilder.phpŸ  ÃÅaŸ  Z ¤      H   vendor/daverandom/libdns/src/Records/TypeDefinitions/FieldDefinition.phpF  ÃÅaF  B«—·¤      G   vendor/daverandom/libdns/src/Records/TypeDefinitions/TypeDefinition.php   ÃÅa   pÂQ«¤      N   vendor/daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionManager.phpû%  ÃÅaû%  ùŽ?›¤      N   vendor/daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionFactory.phpc  ÃÅac  èI+¤      U   vendor/daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionManagerFactory.phpš  ÃÅaš  ®§‰P¤      O   vendor/daverandom/libdns/src/Records/TypeDefinitions/FieldDefinitionFactory.phpI  ÃÅaI  ‡±æ¤      6   vendor/daverandom/libdns/src/Records/ResourceTypes.php5  ÃÅa5  i“[¤      8   vendor/daverandom/libdns/src/Records/QuestionFactory.phpG  ÃÅaG  ëÚD‹¤      4   vendor/daverandom/libdns/src/Records/Types/Types.phpn  ÃÅan  þ�³Ò¤      :   vendor/daverandom/libdns/src/Records/Types/IPv4Address.phpŒ	  ÃÅaŒ	  p{Õ¤¤      3   vendor/daverandom/libdns/src/Records/Types/Char.phpî  ÃÅaî  GçÅ¼¤      5   vendor/daverandom/libdns/src/Records/Types/BitMap.phpŸ  ÃÅaŸ  0*V¤      :   vendor/daverandom/libdns/src/Records/Types/IPv6Address.php½  ÃÅa½  Am¡¤      3   vendor/daverandom/libdns/src/Records/Types/Type.php¿  ÃÅa¿  ì´)Û¤      :   vendor/daverandom/libdns/src/Records/Types/TypeFactory.phpš
  ÃÅaš
  —$Ä´¤      >   vendor/daverandom/libdns/src/Records/Types/CharacterString.phpY  ÃÅaY  ç¯²¤      4   vendor/daverandom/libdns/src/Records/Types/Short.php
  ÃÅa
  %—¤      7   vendor/daverandom/libdns/src/Records/Types/Anything.php\  ÃÅa\  �öm›¤      3   vendor/daverandom/libdns/src/Records/Types/Long.php  ÃÅa  T=ù¤      9   vendor/daverandom/libdns/src/Records/Types/DomainName.php+  ÃÅa+  G®ªí¤      :   vendor/daverandom/libdns/src/Records/Types/TypeBuilder.phpš  ÃÅaš  }å×±¤      7   vendor/daverandom/libdns/src/Records/ResourceQTypes.php¾  ÃÅa¾  :›¤      5   vendor/daverandom/libdns/src/Records/RDataBuilder.phpn  ÃÅan  <õÐ¤      1   vendor/daverandom/libdns/src/Records/Question.phpÄ  ÃÅaÄ  4T¤      /   vendor/daverandom/libdns/src/Records/Record.php	  ÃÅa	  ;=¼¹¤      6   vendor/daverandom/libdns/src/Packets/PacketFactory.phpù  ÃÅaù  ÕÀ¶<¤      /   vendor/daverandom/libdns/src/Packets/Packet.php7  ÃÅa7  ØEEÿ¤      6   vendor/daverandom/libdns/src/Packets/LabelRegistry.phpH  ÃÅaH  Œö¤      .   vendor/daverandom/libdns/examples/autoload.phpG  ÃÅaG  wNeà¤      ,   vendor/daverandom/libdns/examples/AQuery.phpÊ  ÃÅaÊ  BÁ\|¤      .   vendor/daverandom/libdns/examples/SOAQuery.php]
  ÃÅa]
  “šMÚ¤      5   vendor/daverandom/libdns/tools/autoload_generator.php&
  ÃÅa&
    Ùì¤      &   vendor/daverandom/libdns/composer.jsonþ  ÃÅaþ  xeÎz¤      O   vendor/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/Attribute.php  ÃÅa  Le¹¤      Y   vendor/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php2   ÃÅa2   yrû+¤      P   vendor/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/Stringable.php¤   ÃÅa¤   Ï0Èò¤      P   vendor/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/ValueError.php)   ÃÅa)   ×AÄ‘¤      ;   vendor/phabel-transpiler74.symfony/polyfill-php80/Php80.phpq  ÃÅaq  N[ŽÜ¤      ?   vendor/phabel-transpiler74.symfony/polyfill-php80/composer.json=  ÃÅa=  Ïzû>¤      ?   vendor/phabel-transpiler74.symfony/polyfill-php80/bootstrap.php  ÃÅa  �jÿ ¤      D   vendor/phabel-transpiler74.symfony/polyfill-mbstring/bootstrap80.phpWz  ÃÅaWz  @k’È¤      Z   vendor/phabel-transpiler74.symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.phpö  ÃÅaö  Ž37�¤      T   vendor/phabel-transpiler74.symfony/polyfill-mbstring/Resources/unidata/lowerCase.phpôT  ÃÅaôT  Ø–×¬¤      T   vendor/phabel-transpiler74.symfony/polyfill-mbstring/Resources/unidata/upperCase.php3[  ÃÅa3[  ©bñ—¤      A   vendor/phabel-transpiler74.symfony/polyfill-mbstring/Mbstring.php¿u  ÃÅa¿u  zÔáI¤      B   vendor/phabel-transpiler74.symfony/polyfill-mbstring/composer.jsonì  ÃÅaì  ]ñ¤      B   vendor/phabel-transpiler74.symfony/polyfill-mbstring/bootstrap.php"  ÃÅa"  ±œŠ¤      %   vendor/erusev/parsedown/Parsedown.phpÓ•  ÃÅaÓ•  lÔs¤      %   vendor/erusev/parsedown/composer.json  ÃÅa  ©4Ìü¤      ;   vendor/symfony/polyfill-php80/Resources/stubs/Attribute.php  ÃÅa  Le¹¤      E   vendor/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php2   ÃÅa2   yrû+¤      <   vendor/symfony/polyfill-php80/Resources/stubs/Stringable.php¤   ÃÅa¤   Ï0Èò¤      <   vendor/symfony/polyfill-php80/Resources/stubs/ValueError.php)   ÃÅa)   ×AÄ‘¤      '   vendor/symfony/polyfill-php80/Php80.phpq  ÃÅaq  N[ŽÜ¤      +   vendor/symfony/polyfill-php80/composer.json=  ÃÅa=  Ïzû>¤      +   vendor/symfony/polyfill-php80/bootstrap.php  ÃÅa  �jÿ ¤      0   vendor/symfony/polyfill-mbstring/bootstrap80.phpWz  ÃÅaWz  @k’È¤      F   vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.phpö  ÃÅaö  Ž37�¤      @   vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.phpôT  ÃÅaôT  Ø–×¬¤      @   vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php3[  ÃÅa3[  ©bñ—¤      -   vendor/symfony/polyfill-mbstring/Mbstring.php¿u  ÃÅa¿u  zÔáI¤      .   vendor/symfony/polyfill-mbstring/composer.jsonì  ÃÅaì  ]ñ¤      .   vendor/symfony/polyfill-mbstring/bootstrap.php"  ÃÅa"  ±œŠ¤      >   vendor/phabel-transpiler74.cash/lrucache/src/cash/LRUCache.php¤  ÃÅa¤  ½êÐ­¤      6   vendor/phabel-transpiler74.cash/lrucache/composer.json  ÃÅa  >8ßÑ¤      7   vendor/amphp/websocket-client/src/ConnectionFactory.php"  ÃÅa"  çcw¤      7   vendor/amphp/websocket-client/src/Rfc6455Connection.php˜  ÃÅa˜  Nà
¤      /   vendor/amphp/websocket-client/src/Handshake.php	  ÃÅa	  ‹$C¤      9   vendor/amphp/websocket-client/src/ConnectionException.php"  ÃÅa"  PÉåâ¤      6   vendor/amphp/websocket-client/src/Rfc6455Connector.phpC  ÃÅaC  c
Ìä¤      /   vendor/amphp/websocket-client/src/Connector.phpJ  ÃÅaJ  /Ïú'¤      0   vendor/amphp/websocket-client/src/Connection.php  ÃÅa  l„´�¤      /   vendor/amphp/websocket-client/src/functions.php
  ÃÅa
  ½R–ì¤      >   vendor/amphp/websocket-client/src/Rfc6455ConnectionFactory.phpL  ÃÅaL  ½:k2¤      6   vendor/amphp/websocket-client/test-autobahn/runner.php  ÃÅa  44µ¤      E   vendor/amphp/websocket-client/test-autobahn/config/fuzzingserver.jsonË   ÃÅaË   ÇtB½¤      +   vendor/amphp/websocket-client/composer.json'  ÃÅa'  ‘¯T÷¤      +   vendor/amphp/http/src/Http2/Http2Parser.phpT  ÃÅaT  e{o¤      8   vendor/amphp/http/src/Http2/Http2ConnectionException.php  ÃÅa  ÀÝ ¤      .   vendor/amphp/http/src/Http2/Http2Processor.php³  ÃÅa³  ÿî¥¤      4   vendor/amphp/http/src/Http2/Http2StreamException.phpÙ  ÃÅaÙ  ž€�é¤      !   vendor/amphp/http/src/Rfc7230.phpè  ÃÅaè  j"àç¤      !   vendor/amphp/http/src/Message.phpF  ÃÅaF  I8¤          vendor/amphp/http/src/Status.php¨  ÃÅa¨  `òZ¤      7   vendor/amphp/http/src/Cookie/InvalidCookieException.php×   ÃÅa×   ¼`ºû¤      /   vendor/amphp/http/src/Cookie/ResponseCookie.phpŠ*  ÃÅaŠ*  Óž½¤      .   vendor/amphp/http/src/Cookie/RequestCookie.phpå  ÃÅaå  ^q
¤      1   vendor/amphp/http/src/Cookie/CookieAttributes.phpë"  ÃÅaë"  Ù*#¤      #   vendor/amphp/http/src/functions.phpN	  ÃÅaN	  õt¤      0   vendor/amphp/http/src/InvalidHeaderException.phpH  ÃÅaH  Å™¤         vendor/amphp/http/composer.json›  ÃÅa›  �Ú€ß¤      <   vendor/amphp/http-client-cookies/composer-require-check.json�  ÃÅa�  8fa¤      :   vendor/amphp/http-client-cookies/src/InMemoryCookieJar.php€  ÃÅa€  VU¸¤      6   vendor/amphp/http-client-cookies/src/NullCookieJar.phpÚ  ÃÅaÚ  àR²9¤      B   vendor/amphp/http-client-cookies/src/Internal/PublicSuffixList.php1  ÃÅa1  ¿Ã“±¤      6   vendor/amphp/http-client-cookies/src/FileCookieJar.php$  ÃÅa$  ÞWÍ¤      2   vendor/amphp/http-client-cookies/src/CookieJar.phpÊ  ÃÅaÊ  *Y)·¤      :   vendor/amphp/http-client-cookies/src/CookieInterceptor.php®  ÃÅa®  ƒ†ï'¤      8   vendor/amphp/http-client-cookies/examples/basic-file.php`  ÃÅa`  ÊKƒ�¤      3   vendor/amphp/http-client-cookies/examples/basic.php@  ÃÅa@  ¡‰;9¤      ;   vendor/amphp/http-client-cookies/res/public_suffix_list.datm� ÃÅam� s¿tK¤      .   vendor/amphp/http-client-cookies/composer.json²  ÃÅa²  ·â×u¤      G   vendor/amphp/http-client-cookies/test/Internal/PublicSuffixListTest.phpô  ÃÅaô  ´ßÍ§¤      ;   vendor/amphp/http-client-cookies/test/FileCookieJarTest.phpF  ÃÅaF  ZËÞ½¤      7   vendor/amphp/http-client-cookies/test/CookieJarTest.phpG	  ÃÅaG	  ©XX¤      4   vendor/amphp/http-client-cookies/test/CookieTest.php  ÃÅa  /ÀwG¤      ?   vendor/amphp/http-client-cookies/test/InMemoryCookieJarTest.php  ÃÅa  “t«¤      :   vendor/amphp/http-client-cookies/test/ClientCookieTest.php  ÃÅa  ª2 Y¤      "   vendor/amphp/process/composer.jsont  ÃÅat  û@¼Ô¤      5   vendor/amphp/process/bin/windows/ProcessWrapper64.exe H ÃÅa H &Ó;‰¤      3   vendor/amphp/process/bin/windows/ProcessWrapper.exe 4 ÃÅa 4 %P§¤      3   vendor/amphp/process/lib/Internal/ProcessStatus.php  ÃÅa  ðFÞ>¤      3   vendor/amphp/process/lib/Internal/ProcessHandle.phpÜ  ÃÅaÜ   Ï<2¤      2   vendor/amphp/process/lib/Internal/Posix/Handle.php±  ÃÅa±  ÃmpÓ¤      2   vendor/amphp/process/lib/Internal/Posix/Runner.phpJ   ÃÅaJ   ¬í¤      =   vendor/amphp/process/lib/Internal/Windows/SocketConnector.phpn0  ÃÅan0  ;mï¤      A   vendor/amphp/process/lib/Internal/Windows/PendingSocketClient.php.  ÃÅa.  ©ˆŒ¤      8   vendor/amphp/process/lib/Internal/Windows/SignalCode.phpn  ÃÅan  œNƒ¤      4   vendor/amphp/process/lib/Internal/Windows/Handle.php±  ÃÅa±  j‹<¤      =   vendor/amphp/process/lib/Internal/Windows/HandshakeStatus.phpÏ  ÃÅaÏ  àûh}¤      4   vendor/amphp/process/lib/Internal/Windows/Runner.phpU  ÃÅaU   ÏÜÒ¤      3   vendor/amphp/process/lib/Internal/ProcessRunner.phpÆ  ÃÅaÆ  clg¤      (   vendor/amphp/process/lib/StatusError.phpC   ÃÅaC   +4«R¤      0   vendor/amphp/process/lib/ProcessOutputStream.phpp  ÃÅap  ”E%«¤      &   vendor/amphp/process/lib/functions.php  ÃÅa  —¥S¤      $   vendor/amphp/process/lib/Process.php‡  ÃÅa‡  ¼±ä‰¤      /   vendor/amphp/process/lib/ProcessInputStream.php€  ÃÅa€  ›Úò¤      -   vendor/amphp/process/lib/ProcessException.phpL   ÃÅaL   ´÷ŠA¤      #   vendor/amphp/parallel/composer.json\  ÃÅa\  œ@�ví      ;   vendor/amphp/parallel/lib/Worker/BootstrapWorkerFactory.phpm  ÃÅam  ÞCÑ¤      9   vendor/amphp/parallel/lib/Worker/TaskFailureThrowable.phpÄ  ÃÅaÄ  QV1Â¤      2   vendor/amphp/parallel/lib/Worker/WorkerFactory.php  ÃÅa  	s¸¤      1   vendor/amphp/parallel/lib/Worker/CallableTask.php³  ÃÅa³  ·5¢é¤      9   vendor/amphp/parallel/lib/Worker/TaskFailureException.phpý  ÃÅaý  Ý“•E¤      5   vendor/amphp/parallel/lib/Worker/TaskFailureError.phpõ  ÃÅaõ  ×÷¤L¤      0   vendor/amphp/parallel/lib/Worker/DefaultPool.phpà  ÃÅaà  W�}¤      4   vendor/amphp/parallel/lib/Worker/WorkerException.phpS   ÃÅaS   �òÆ¤      5   vendor/amphp/parallel/lib/Worker/BasicEnvironment.php  ÃÅa  ×¶›Ï¤      1   vendor/amphp/parallel/lib/Worker/Internal/Job.php]  ÃÅa]  DKbß¤      9   vendor/amphp/parallel/lib/Worker/Internal/TaskFailure.phpó  ÃÅaó   ¤N¤      :   vendor/amphp/parallel/lib/Worker/Internal/PooledWorker.phpA  ÃÅaA  ñ:ð´¤      ;   vendor/amphp/parallel/lib/Worker/Internal/WorkerProcess.php%  ÃÅa%  é6)Ô¤      <   vendor/amphp/parallel/lib/Worker/Internal/worker-process.php’  ÃÅa’  …)Mh¤      8   vendor/amphp/parallel/lib/Worker/Internal/TaskResult.phpF  ÃÅaF  §3-À¤      9   vendor/amphp/parallel/lib/Worker/Internal/TaskSuccess.phpô  ÃÅaô  €ÀËt¤      )   vendor/amphp/parallel/lib/Worker/Pool.php�  ÃÅa�  î‘?þ¤      2   vendor/amphp/parallel/lib/Worker/TaskException.php  ÃÅa  ô6Y¤      1   vendor/amphp/parallel/lib/Worker/WorkerThread.php¡  ÃÅa¡  è¾]€¤      0   vendor/amphp/parallel/lib/Worker/Environment.php  ÃÅa  µ+ÄÏ¤      /   vendor/amphp/parallel/lib/Worker/TaskRunner.php  ÃÅa  ú0¬-¤      /   vendor/amphp/parallel/lib/Worker/TaskWorker.phpÊ  ÃÅaÊ  œ›R¤      .   vendor/amphp/parallel/lib/Worker/functions.php¶  ÃÅa¶  ™‚¤      +   vendor/amphp/parallel/lib/Worker/Worker.php  ÃÅa  l==¤      2   vendor/amphp/parallel/lib/Worker/WorkerProcess.phpã  ÃÅaã  ž¾Ùš¤      3   vendor/amphp/parallel/lib/Worker/WorkerParallel.phpŒ  ÃÅaŒ  »è7¤      )   vendor/amphp/parallel/lib/Worker/Task.php¨  ÃÅa¨  ½$®Y¤      9   vendor/amphp/parallel/lib/Worker/DefaultWorkerFactory.phpŒ  ÃÅaŒ  Ô]Y+¤      .   vendor/amphp/parallel/lib/Worker/TaskError.phpc  ÃÅac  ¸Ö¤      4   vendor/amphp/parallel/lib/Sync/ContextPanicError.php’  ÃÅa’  (CO¤      8   vendor/amphp/parallel/lib/Sync/SharedMemoryException.php\   ÃÅa\   U"ÌO¤      .   vendor/amphp/parallel/lib/Sync/ExitFailure.phpb  ÃÅab  “ïÀ¤      .   vendor/amphp/parallel/lib/Sync/ExitSuccess.php]  ÃÅa]  ÚÂþž¤      5   vendor/amphp/parallel/lib/Sync/SharedMemoryParcel.phpÞ6  ÃÅaÞ6  õÁÔ¤      3   vendor/amphp/parallel/lib/Sync/ChannelledSocket.php	  ÃÅa	  æú�;¤      2   vendor/amphp/parallel/lib/Sync/ParcelException.phpQ   ÃÅaQ   �…pö¤      3   vendor/amphp/parallel/lib/Sync/ChannelException.phpR   ÃÅaR   ï÷X¤      )   vendor/amphp/parallel/lib/Sync/Parcel.php¨  ÃÅa¨  Jw¤      9   vendor/amphp/parallel/lib/Sync/Internal/ParcelStorage.phpê  ÃÅaê  ¶±ÿ¾¤      7   vendor/amphp/parallel/lib/Sync/SynchronizationError.phpR   ÃÅaR   â›iä¤      1   vendor/amphp/parallel/lib/Sync/ThreadedParcel.phpÈ  ÃÅaÈ  ? ÑJ¤      *   vendor/amphp/parallel/lib/Sync/Channel.phpð  ÃÅað  ,åû¤      ,   vendor/amphp/parallel/lib/Sync/functions.phpÒ  ÃÅaÒ  ó¥µÀ¤      -   vendor/amphp/parallel/lib/Sync/PanicError.php‡  ÃÅa‡  Ç8¤      0   vendor/amphp/parallel/lib/Sync/ChannelParser.phpö  ÃÅaö  JGÜ=¤      -   vendor/amphp/parallel/lib/Sync/ExitResult.php&  ÃÅa&   '55¤      3   vendor/amphp/parallel/lib/Sync/ChannelledStream.php	  ÃÅa	  £�¤      4   vendor/amphp/parallel/lib/Context/ContextFactory.php  ÃÅa  Õ�ž¤      ,   vendor/amphp/parallel/lib/Context/Thread.phpó#  ÃÅaó#  0ÙÄÙ¤      6   vendor/amphp/parallel/lib/Context/ContextException.phpU   ÃÅaU   ØŽ­¤      9   vendor/amphp/parallel/lib/Context/Internal/ProcessHub.phpÿ  ÃÅaÿ  ÒØ—ð¤      =   vendor/amphp/parallel/lib/Context/Internal/process-runner.phpM  ÃÅaM  ö…�¤      5   vendor/amphp/parallel/lib/Context/Internal/Thread.phpG  ÃÅaG  çuÎË¤      :   vendor/amphp/parallel/lib/Context/Internal/ParallelHub.php¡  ÃÅa¡  ©ŠÎ¤      1   vendor/amphp/parallel/lib/Context/StatusError.phpL   ÃÅaL   k1¥¤      ;   vendor/amphp/parallel/lib/Context/DefaultContextFactory.php!  ÃÅa!  ¸¼N¤      /   vendor/amphp/parallel/lib/Context/functions.php=  ÃÅa=  k¤      -   vendor/amphp/parallel/lib/Context/Process.phpJ0  ÃÅaJ0  Ä‰7¥¤      .   vendor/amphp/parallel/lib/Context/Parallel.php3  ÃÅa3  fŠƒÁ¤      -   vendor/amphp/parallel/lib/Context/Context.php  ÃÅa  ©Ú€¤      )   vendor/amphp/redis/src/RedisException.phpV   ÃÅaV   '‚ÂX¤      +   vendor/amphp/redis/src/RedisHyperLogLog.phpW  ÃÅaW  ‹‘S¤      %   vendor/amphp/redis/src/RespParser.php  ÃÅa  –H9ø¤      *   vendor/amphp/redis/src/SocketException.phpM   ÃÅaM   e¯-¤      *   vendor/amphp/redis/src/ParserException.phpM   ÃÅaM   û}à¤          vendor/amphp/redis/src/Redis.phpèj  ÃÅaèj  {ç$¥¤      '   vendor/amphp/redis/src/Subscription.phpî  ÃÅaî  "	¤      9   vendor/amphp/redis/src/Mutex/ConnectionLimitException.php\   ÃÅa\   ¼ÜØ¤      .   vendor/amphp/redis/src/Mutex/LockException.phpQ   ÃÅaQ   FEüý¤      -   vendor/amphp/redis/src/Mutex/MutexOptions.phpÁ  ÃÅaÁ  ±;z¤      /   vendor/amphp/redis/src/Mutex/MutexException.phpp   ÃÅap   ÆoG”¤      &   vendor/amphp/redis/src/Mutex/Mutex.php~!  ÃÅa~!  í�ý§¤      )   vendor/amphp/redis/src/QueryException.phpL   ÃÅaL   Ix×h¤      #   vendor/amphp/redis/src/RedisSet.php»  ÃÅa»  ÞBcû¤      %   vendor/amphp/redis/src/Subscriber.phpé  ÃÅaé  æ=¦¤      #   vendor/amphp/redis/src/RedisMap.php²  ÃÅa²  )ŠPé¤      !   vendor/amphp/redis/src/Config.phpD  ÃÅaD  ÄvË¤      )   vendor/amphp/redis/src/RemoteExecutor.php  ÃÅa  }­0´¤      )   vendor/amphp/redis/src/RedisSortedSet.php<  ÃÅa<  ßª‚Ä¤      /   vendor/amphp/redis/src/QueryExecutorFactory.phpÃ   ÃÅaÃ   lJH¤      &   vendor/amphp/redis/src/SortOptions.php¤  ÃÅa¤  ¾ðy!¤      (   vendor/amphp/redis/src/QueryExecutor.php|  ÃÅa|  jL˜¤      $   vendor/amphp/redis/src/functions.phpQ	  ÃÅaQ	  {²o&¤      0   vendor/amphp/redis/src/RemoteExecutorFactory.php  ÃÅa  Šu•¤      $   vendor/amphp/redis/src/RedisList.phpP  ÃÅaP  á!e¤      %   vendor/amphp/redis/src/RespSocket.phpA  ÃÅaA  |ä‰¤          vendor/amphp/redis/src/Cache.phpy  ÃÅay   ¿DÄ¤      %   vendor/amphp/redis/src/SetOptions.php  ÃÅa  8�¼Ò¤          vendor/amphp/redis/composer.jsonr  ÃÅar  ˜š¬¿¤      +   vendor/amphp/windows-registry/composer.jsont  ÃÅat  ¢´J;¤      5   vendor/amphp/windows-registry/lib/WindowsRegistry.phpÖ	  ÃÅaÖ	  �Úc¯¤      :   vendor/amphp/windows-registry/lib/KeyNotFoundException.phpX   ÃÅaX   Ö»E±¤         vendor/amphp/amp/composer.json  ÃÅa  ŽÔ¤          vendor/amphp/amp/lib/Emitter.php  ÃÅa  ±±«,¤      .   vendor/amphp/amp/lib/NullCancellationToken.php¿  ÃÅa¿  ¤ÃAt¤          vendor/amphp/amp/lib/Success.phpÕ  ÃÅaÕ  ý>¢¤      1   vendor/amphp/amp/lib/TimeoutCancellationToken.php  ÃÅa  
˜ŒY¤      !   vendor/amphp/amp/lib/Producer.phpê  ÃÅaê  ¬†íK¤          vendor/amphp/amp/lib/Promise.php”  ÃÅa”  Ê¤}º¤      -   vendor/amphp/amp/lib/Internal/Placeholder.php€  ÃÅa€  Óÿî“¤      *   vendor/amphp/amp/lib/Internal/Producer.phpi  ÃÅai  ¡–k¸¤      0   vendor/amphp/amp/lib/Internal/PrivatePromise.php0  ÃÅa0  Æ²¶¤      +   vendor/amphp/amp/lib/Internal/functions.php¢  ÃÅa¢  cÇÆ×¤      1   vendor/amphp/amp/lib/Internal/PrivateIterator.phpv  ÃÅav  …ýÙ¤      1   vendor/amphp/amp/lib/Internal/ResolutionQueue.php*  ÃÅa*  Kâ¼¤      0   vendor/amphp/amp/lib/CancellationTokenSource.phpå  ÃÅaå  |1ò~¤      %   vendor/amphp/amp/lib/Loop/Watcher.phpÎ  ÃÅaÎ  ¨
R¤      )   vendor/amphp/amp/lib/Loop/EventDriver.phpï$  ÃÅaï$  ËÁh6¤      $   vendor/amphp/amp/lib/Loop/Driver.phpe  ÃÅae  îœýè¤      +   vendor/amphp/amp/lib/Loop/DriverFactory.phpì  ÃÅaì  ö¤      *   vendor/amphp/amp/lib/Loop/NativeDriver.php8  ÃÅa8  Ž_@F¤      1   vendor/amphp/amp/lib/Loop/Internal/TimerQueue.php3  ÃÅa3  àbâ´¤      9   vendor/amphp/amp/lib/Loop/UnsupportedFeatureException.php  ÃÅa  3µ¢g¤      &   vendor/amphp/amp/lib/Loop/EvDriver.phpÓ   ÃÅaÓ   A	‚;¤      &   vendor/amphp/amp/lib/Loop/UvDriver.php(  ÃÅa(  ±ÍöU¤      1   vendor/amphp/amp/lib/Loop/InvalidWatcherError.php  ÃÅa  Æ^Ë—¤      +   vendor/amphp/amp/lib/Loop/TracingDriver.phpD  ÃÅaD  † z¤      "   vendor/amphp/amp/lib/Coroutine.phpï  ÃÅaï  vÂ¤      *   vendor/amphp/amp/lib/CancellationToken.phpß  ÃÅaß  ™a ¤      !   vendor/amphp/amp/lib/Deferred.php,  ÃÅa,  Õà¨½¤          vendor/amphp/amp/lib/Failure.php¦  ÃÅa¦  ’¯ÜS¤      -   vendor/amphp/amp/lib/MultiReasonException.php’  ÃÅa’  }ÍÏˆ¤      "   vendor/amphp/amp/lib/functions.phpµY  ÃÅaµY  DN·ï¤      *   vendor/amphp/amp/lib/InvalidYieldError.phpì  ÃÅaì  væFê¤      2   vendor/amphp/amp/lib/CombinedCancellationToken.phpÎ  ÃÅaÎ  q2>³¤      )   vendor/amphp/amp/lib/TimeoutException.phpn  ÃÅan  Õ>Š¤         vendor/amphp/amp/lib/Loop.phpD  ÃÅaD  Ï¤          vendor/amphp/amp/lib/Delayed.php�  ÃÅa�  j5‘ý¤      !   vendor/amphp/amp/lib/Iterator.php8  ÃÅa8  ¦öõ¤      &   vendor/amphp/amp/lib/CallableMaker.php{
  ÃÅa{
  àA¤      +   vendor/amphp/amp/lib/CancelledException.phpj  ÃÅaj  o|kÒ¤      $   vendor/amphp/amp/lib/LazyPromise.php¡  ÃÅa¡  [–\c¤         vendor/amphp/amp/lib/Struct.php¤  ÃÅa¤  B*#,¤      6   vendor/amphp/http-client/src/MissingAttributeError.phpÒ   ÃÅaÒ   ‚¢¤      )   vendor/amphp/http-client/src/Response.php  ÃÅa  áÿC¤      0   vendor/amphp/http-client/src/SocketException.phpX   ÃÅaX   <’…í      /   vendor/amphp/http-client/src/ParseException.php‚  ÃÅa‚  <*–�¤      B   vendor/amphp/http-client/src/EventListener/RecordHarAttributes.phpä  ÃÅaä  EBP9¤      (   vendor/amphp/http-client/src/Request.php€<  ÃÅa€<  ‡Õ^¤      1   vendor/amphp/http-client/src/PooledHttpClient.phpÅ  ÃÅaÅ  )È<¤      2   vendor/amphp/http-client/src/HttpClientBuilder.php—  ÃÅa—  êÿº‹¤      =   vendor/amphp/http-client/src/Internal/ForbidSerialization.phpê   ÃÅaê   €eqp¤      7   vendor/amphp/http-client/src/Internal/ForbidCloning.php1  ÃÅa1  Œ“'¤      7   vendor/amphp/http-client/src/Internal/HarAttributes.php  ÃÅa  x®[…¤      <   vendor/amphp/http-client/src/Internal/ResponseBodyStream.php^  ÃÅa^  ËÌÓv¤      3   vendor/amphp/http-client/src/Internal/functions.php¨  ÃÅa¨  ¡ÎR¤      A   vendor/amphp/http-client/src/Internal/SizeLimitingInputStream.php§  ÃÅa§  )„›¤      ,   vendor/amphp/http-client/src/RequestBody.phpf  ÃÅaf  8´§Þ¤      6   vendor/amphp/http-client/src/InterceptedHttpClient.phpM  ÃÅaM  Oå.Ÿ¤      3   vendor/amphp/http-client/src/DelegateHttpClient.phpz  ÃÅaz  L¾À¸¤      +   vendor/amphp/http-client/src/HttpClient.phpÏ  ÃÅaÏ  Êå3¤      8   vendor/amphp/http-client/src/Interceptor/MatchOrigin.phpU  ÃÅaU  Ê»¤      ;   vendor/amphp/http-client/src/Interceptor/ModifyResponse.php   ÃÅa   CÏR‹¤      =   vendor/amphp/http-client/src/Interceptor/SetRequestHeader.php  ÃÅa  ¸Œh�¤      D   vendor/amphp/http-client/src/Interceptor/SetRequestHeaderIfUnset.phpQ  ÃÅaQ  ?±•ó¤      =   vendor/amphp/http-client/src/Interceptor/AddRequestHeader.php¹  ÃÅa¹  j"˜<¤      F   vendor/amphp/http-client/src/Interceptor/TooManyRedirectsException.php  ÃÅa  xxú6í      ?   vendor/amphp/http-client/src/Interceptor/DecompressResponse.phpq  ÃÅaq  Òy¡¤      ;   vendor/amphp/http-client/src/Interceptor/LogHttpArchive.php3  ÃÅa3  ?m›!¤      >   vendor/amphp/http-client/src/Interceptor/AddResponseHeader.phpÀ  ÃÅaÀ  ô¤À¤      <   vendor/amphp/http-client/src/Interceptor/FollowRedirects.phpb&  ÃÅab&  {ø¯´¤      >   vendor/amphp/http-client/src/Interceptor/SetResponseHeader.php
  ÃÅa
  Kjko¤      A   vendor/amphp/http-client/src/Interceptor/RemoveResponseHeader.php�  ÃÅa�  ÞÀ'®¤      @   vendor/amphp/http-client/src/Interceptor/RemoveRequestHeader.phpˆ  ÃÅaˆ  aäç`¤      E   vendor/amphp/http-client/src/Interceptor/SetResponseHeaderIfUnset.phpY  ÃÅaY  âµCH¤      :   vendor/amphp/http-client/src/Interceptor/ModifyRequest.php4  ÃÅa4  @Ú\¤      >   vendor/amphp/http-client/src/Interceptor/SetRequestTimeout.php�  ÃÅa�  Q’ûp¤      >   vendor/amphp/http-client/src/Interceptor/ForbidUriUserInfo.php  ÃÅa  §§`·¤      :   vendor/amphp/http-client/src/Interceptor/RetryRequests.phpz  ÃÅaz  Ë>Ó¤      7   vendor/amphp/http-client/src/ApplicationInterceptor.php�  ÃÅa�  Ä·-A¤      .   vendor/amphp/http-client/src/Body/FileBody.phpú  ÃÅaú  <1Vs¤      0   vendor/amphp/http-client/src/Body/StringBody.phpõ  ÃÅaõ  ;i3ª¤      .   vendor/amphp/http-client/src/Body/FormBody.php—  ÃÅa—  çi¤      .   vendor/amphp/http-client/src/Body/JsonBody.phpÐ  ÃÅaÐ  dÛKÆ¤      .   vendor/amphp/http-client/src/EventListener.phpŒ  ÃÅaŒ  UI]¤      1   vendor/amphp/http-client/src/TimeoutException.phpY   ÃÅaY   \Ió6í      =   vendor/amphp/http-client/src/Connection/ConnectionFactory.phpm  ÃÅam  YÆ}¤      2   vendor/amphp/http-client/src/Connection/Stream.php“  ÃÅa“  Õ˜\+¤      A   vendor/amphp/http-client/src/Connection/LimitedConnectionPool.php™   ÃÅa™   âÉ·¤      D   vendor/amphp/http-client/src/Connection/Http2ConnectionException.php³  ÃÅa³  m @¤      @   vendor/amphp/http-client/src/Connection/Internal/Http2Stream.phpø  ÃÅaø  âï±¤      M   vendor/amphp/http-client/src/Connection/Internal/Http2ConnectionProcessor.php¥Ø  ÃÅa¥Ø  ¤ô¤      F   vendor/amphp/http-client/src/Connection/Internal/RequestNormalizer.php]  ÃÅa]  “……¤      @   vendor/amphp/http-client/src/Connection/Internal/Http1Parser.php�3  ÃÅa�3  –lcó¤      :   vendor/amphp/http-client/src/Connection/ConnectionPool.php«  ÃÅa«  v8û‹¤      G   vendor/amphp/http-client/src/Connection/UnprocessedRequestException.phpT  ÃÅaT  Égzð¤      6   vendor/amphp/http-client/src/Connection/HttpStream.php  ÃÅa  `Âµ°¤      6   vendor/amphp/http-client/src/Connection/Connection.php  ÃÅa  ký3‹¤      B   vendor/amphp/http-client/src/Connection/ConnectionLimitingPool.php…1  ÃÅa…1  �ól×¤      C   vendor/amphp/http-client/src/Connection/UnlimitedConnectionPool.phpã  ÃÅaã  n[wé¤      :   vendor/amphp/http-client/src/Connection/UpgradedSocket.phpÅ
  ÃÅaÅ
  ÜøwV¤      >   vendor/amphp/http-client/src/Connection/StreamLimitingPool.phpo  ÃÅao  íö¤      D   vendor/amphp/http-client/src/Connection/DefaultConnectionFactory.phpx!  ÃÅax!  ®°ìF¤      =   vendor/amphp/http-client/src/Connection/InterceptedStream.php|  ÃÅa|  ŠvÎb¤      ;   vendor/amphp/http-client/src/Connection/Http1Connection.php*c  ÃÅa*c  ²þ’†¤      ;   vendor/amphp/http-client/src/Connection/Http2Connection.phpç
  ÃÅaç
  |Ýk¤      @   vendor/amphp/http-client/src/Connection/Http2StreamException.phpy  ÃÅay  ”#�z¤      3   vendor/amphp/http-client/src/NetworkInterceptor.phpW  ÃÅaW  Ëá•u¤      )   vendor/amphp/http-client/src/Trailers.php‹  ÃÅa‹  7»ó�¤      8   vendor/amphp/http-client/src/InvalidRequestException.phpé  ÃÅaé  bØÍ²¤      .   vendor/amphp/http-client/src/HttpException.phpM   ÃÅaM   ‹HV%í      &   vendor/amphp/http-client/composer.json�	  ÃÅa�	  †­Ð¤      +   vendor/amphp/mysql/src/ConnectionConfig.phpÛ  ÃÅaÛ  Šù…Ž¤      0   vendor/amphp/mysql/src/ConnectionTransaction.php®  ÃÅa®  :—¤      *   vendor/amphp/mysql/src/PooledStatement.php   ÃÅa   „½È¢¤      /   vendor/amphp/mysql/src/CancellableConnector.phpD  ÃÅaD  Fòp{¤      .   vendor/amphp/mysql/src/ConnectionStatement.php‰  ÃÅa‰  tË\¦¤      $   vendor/amphp/mysql/src/DataTypes.php¢>  ÃÅa¢>  Û4¿x¤      +   vendor/amphp/mysql/src/TransactionError.phpY   ÃÅaY   ‡m»ï¤      2   vendor/amphp/mysql/src/InitializationException.phpu   ÃÅau   ªs¡9¤      -   vendor/amphp/mysql/src/Internal/Processor.php½é  ÃÅa½é  \-³¤      3   vendor/amphp/mysql/src/Internal/ConnectionState.phpÎ  ÃÅaÎ  \8ö¤      /   vendor/amphp/mysql/src/Internal/ResultProxy.phpG	  ÃÅaG	  Ú0U¤         vendor/amphp/mysql/src/Pool.phpƒ  ÃÅaƒ  µa¾¤      (   vendor/amphp/mysql/src/StatementPool.php¸  ÃÅa¸  ¶	`%¤      %   vendor/amphp/mysql/src/Connection.phpâ  ÃÅaâ  s}ch¤      $   vendor/amphp/mysql/src/ResultSet.php  ÃÅa  ½:¤      $   vendor/amphp/mysql/src/functions.phpñ  ÃÅañ  æfÛz¤      ,   vendor/amphp/mysql/src/PooledTransaction.phpÉ  ÃÅaÉ  
»Ä&¤      .   vendor/amphp/mysql/src/ConnectionResultSet.php‚  ÃÅa‚  ".Ëd¤      (   vendor/amphp/mysql/src/CommandResult.php  ÃÅa  ÝÂ9—¤      $   vendor/amphp/mysql/src/Statement.php€  ÃÅa€  µì¤      *   vendor/amphp/mysql/src/PooledResultSet.php1	  ÃÅa1	  
fÉ¤      '   vendor/amphp/mysql/src/RefreshTypes.php8  ÃÅa8  ~iœp¤      /   vendor/amphp/mysql/benchmarks/AbstractBench.phpÚ   ÃÅaÚ   ,þ}ø¤      ,   vendor/amphp/mysql/benchmarks/QueryBench.php¡  ÃÅa¡  ÂR3l¤      ,   vendor/amphp/mysql/examples/4-multi-rows.php"  ÃÅa"  ¶-/¤      5   vendor/amphp/mysql/examples/support/generic-table.php  ÃÅa  ‘†I¤      1   vendor/amphp/mysql/examples/support/bootstrap.phpš  ÃÅaš  D±…Ý¤      -   vendor/amphp/mysql/examples/5-multi-stmts.phpµ  ÃÅaµ  M ã«¤      4   vendor/amphp/mysql/examples/3-generic-with-yield.phpr  ÃÅar  GX¦¤      )   vendor/amphp/mysql/examples/1-connect.php  ÃÅa  OÃ‰a¤      -   vendor/amphp/mysql/examples/6-transaction.phpS  ÃÅaS  à¼*ò¤      .   vendor/amphp/mysql/examples/2-simple-query.phpÈ  ÃÅaÈ  Àx¤          vendor/amphp/mysql/phpbench.jsonh   ÃÅah   #”š¼¤          vendor/amphp/mysql/composer.jsons  ÃÅas   * ¤      -   vendor/amphp/file/src/Sync/AsyncFileMutex.php^  ÃÅa^  ÿ\ôª¤          vendor/amphp/file/src/Driver.phpÇ  ÃÅaÇ  ±Â¿¸¤      +   vendor/amphp/file/src/Internal/FileTask.phpù  ÃÅaù  ªëž*¤      *   vendor/amphp/file/src/Internal/EioPoll.php‚  ÃÅa‚  iM–>¤      )   vendor/amphp/file/src/Internal/UvPoll.phpF  ÃÅaF  Ónì¤      (   vendor/amphp/file/src/Internal/Cache.phpÁ  ÃÅaÁ  ö”¹±¤      -   vendor/amphp/file/src/Driver/BlockingFile.php}  ÃÅa}  æ&!Y¤      -   vendor/amphp/file/src/Driver/ParallelFile.php<  ÃÅa<  cp¤      *   vendor/amphp/file/src/Driver/EioDriver.phpÿ;  ÃÅaÿ;  Q´âž¤      '   vendor/amphp/file/src/Driver/UvFile.php«"  ÃÅa«"  ÷³­�¤      4   vendor/amphp/file/src/Driver/StatusCachingDriver.php’  ÃÅa’  Ìû€7¤      (   vendor/amphp/file/src/Driver/EioFile.php[!  ÃÅa[!  ƒ/æR¤      /   vendor/amphp/file/src/Driver/ParallelDriver.php�  ÃÅa�  lÌÈ…¤      /   vendor/amphp/file/src/Driver/BlockingDriver.php×-  ÃÅa×-  Mv¦à¤      2   vendor/amphp/file/src/Driver/StatusCachingFile.php  ÃÅa  bf ¤      )   vendor/amphp/file/src/Driver/UvDriver.phpF  ÃÅaF  å˜°¤         vendor/amphp/file/src/File.phpâ	  ÃÅaâ	  ŽRO»¤      /   vendor/amphp/file/src/PendingOperationError.phpU  ÃÅaU  �Úb�¤      -   vendor/amphp/file/src/FilesystemException.phpò   ÃÅaò   a%ê¤      #   vendor/amphp/file/src/functions.phpF&  ÃÅaF&  aàª¤      $   vendor/amphp/file/src/Filesystem.phpM-  ÃÅaM-  rHI¤         vendor/amphp/file/composer.jsoni  ÃÅai  š¶ø�¤      2   vendor/amphp/file/test/Sync/AsyncFileMutexTest.phpz  ÃÅaz  ÒY!•¤      )   vendor/amphp/file/test/FilesystemTest.phpt  ÃÅat  ´¤~½¤      (   vendor/amphp/file/test/AsyncFileTest.php¬  ÃÅa¬  lAÓ¦¤      7   vendor/amphp/file/test/Driver/StatusCachingFileTest.phpG  ÃÅaG  Ò¹¼¤      -   vendor/amphp/file/test/Driver/EioFileTest.php¤  ÃÅa¤  „JÑ}¤      9   vendor/amphp/file/test/Driver/StatusCachingDriverTest.phpM  ÃÅaM  `é½Q¤      /   vendor/amphp/file/test/Driver/EioDriverTest.php   ÃÅa   ™,Z¤      2   vendor/amphp/file/test/Driver/ParallelFileTest.php8  ÃÅa8  Ÿ¸2¤      4   vendor/amphp/file/test/Driver/ParallelDriverTest.php4  ÃÅa4  i11C¤      .   vendor/amphp/file/test/Driver/UvDriverTest.phps  ÃÅas  ÍW¤¤      4   vendor/amphp/file/test/Driver/BlockingDriverTest.php#  ÃÅa#  °IU9¤      2   vendor/amphp/file/test/Driver/BlockingFileTest.php  ÃÅa  Kl¦¤      ,   vendor/amphp/file/test/Driver/UvFileTest.phpÜ  ÃÅaÜ  Æ;à¤      #   vendor/amphp/file/test/FileTest.php£!  ÃÅa£!  é�´¤      %   vendor/amphp/file/test/DriverTest.phpdE  ÃÅadE  i	·*¤      "   vendor/amphp/file/test/Fixture.php¬	  ÃÅa¬	  ®| ¤      )   vendor/amphp/sql/src/ConnectionConfig.phpý  ÃÅaý  6´µ¶¤      "   vendor/amphp/sql/src/PoolError.php=   ÃÅa=   �Lø¤      )   vendor/amphp/sql/src/FailureException.phpH   ÃÅaH   ˆXd¼¤      *   vendor/amphp/sql/src/TransientResource.phpi  ÃÅai  ÁØM­¤      )   vendor/amphp/sql/src/TransactionError.phpD   ÃÅaD   ŠIf¨¤      #   vendor/amphp/sql/src/QueryError.php&  ÃÅa&  €•pÇ¤         vendor/amphp/sql/src/Pool.phpÜ  ÃÅaÜ  S§G¤      ,   vendor/amphp/sql/src/ConnectionException.phpQ   ÃÅaQ   ZX›"¤      "   vendor/amphp/sql/src/Connector.phpå   ÃÅaå   •xk¤      "   vendor/amphp/sql/src/ResultSet.phpÜ   ÃÅaÜ   W·Wº¤      !   vendor/amphp/sql/src/Executor.phpF  ÃÅaF  À„ï¤         vendor/amphp/sql/src/Link.phpb  ÃÅab  SdÆ¤      $   vendor/amphp/sql/src/Transaction.phpÆ  ÃÅaÆ  /îÊª¤      &   vendor/amphp/sql/src/CommandResult.phpÊ   ÃÅaÊ   ÆÝž¼¤      "   vendor/amphp/sql/src/Statement.php~  ÃÅa~  ¹N“ø¤         vendor/amphp/sql/composer.jsonÐ  ÃÅaÐ  nYö¤      (   vendor/amphp/sql/test/QueryErrorTest.phpÐ  ÃÅaÐ  ®Ê
¤      ,   vendor/amphp/websocket/src/Rfc6455Client.phpƒ  ÃÅaƒ  áÛ~á¤      8   vendor/amphp/websocket/src/Rfc7692CompressionFactory.php|  ÃÅa|  Ùâ¬¤      8   vendor/amphp/websocket/src/CompressionContextFactory.php}  ÃÅa}  S[aY¤      &   vendor/amphp/websocket/src/Message.php™  ÃÅa™  T�7[¤      &   vendor/amphp/websocket/src/Options.php/  ÃÅa/  Ã=¤      -   vendor/amphp/websocket/src/ClientMetadata.php´  ÃÅa´  Ç Ÿ¤      %   vendor/amphp/websocket/src/Client.phpr  ÃÅar  6:nˆ¤      1   vendor/amphp/websocket/src/CompressionContext.php8  ÃÅa8  3wGò¤      (   vendor/amphp/websocket/src/functions.phpÛ  ÃÅaÛ  tE¤      #   vendor/amphp/websocket/src/Code.php4  ÃÅa4  ÈEŒ6¤      .   vendor/amphp/websocket/src/ClosedException.php  ÃÅa  ¢à<¤      %   vendor/amphp/websocket/src/Opcode.phpw  ÃÅaw  ¯ k¤      1   vendor/amphp/websocket/src/Rfc7692Compression.phpÒ  ÃÅaÒ  0îÒÛ¤      $   vendor/amphp/websocket/composer.jsonÇ  ÃÅaÇ  1»Šö¤      3   vendor/amphp/serialization/src/NativeSerializer.php!  ÃÅa!  òÄü¶¤      1   vendor/amphp/serialization/src/JsonSerializer.phpu
  ÃÅau
  œÜ *¤      -   vendor/amphp/serialization/src/Serializer.phpš  ÃÅaš  Æ¼p7¤      8   vendor/amphp/serialization/src/CompressingSerializer.php  ÃÅa  Å¥›w¤      8   vendor/amphp/serialization/src/PassthroughSerializer.phpÂ  ÃÅaÂ  óq&J¤      ,   vendor/amphp/serialization/src/functions.php]  ÃÅa]  Wá/2¤      9   vendor/amphp/serialization/src/SerializationException.phpX   ÃÅaX   V¸¹!¤      (   vendor/amphp/serialization/composer.jsonÀ  ÃÅaÀ  òq4¤      &   vendor/amphp/byte-stream/composer.jsonq  ÃÅaq  �Räß¤      A   vendor/amphp/byte-stream/lib/Base64/Base64DecodingInputStream.phpB  ÃÅaB  ­ÍR¤      B   vendor/amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.php  ÃÅa  e¦ö¤      B   vendor/amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php  ÃÅa  °AìU¤      A   vendor/amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php–  ÃÅa–  ¤      /   vendor/amphp/byte-stream/lib/IteratorStream.php¤  ÃÅa¤  ¼�¤      5   vendor/amphp/byte-stream/lib/ResourceOutputStream.php*  ÃÅa*  %Ñô¤      -   vendor/amphp/byte-stream/lib/OutputStream.php  ÃÅa  TsŠÕ¤      1   vendor/amphp/byte-stream/lib/InputStreamChain.phpr  ÃÅar  ý:Ö¤      (   vendor/amphp/byte-stream/lib/Message.php  ÃÅa  µƒâd¤      ,   vendor/amphp/byte-stream/lib/InputStream.php$  ÃÅa$  ÅmŠ¤      4   vendor/amphp/byte-stream/lib/ResourceInputStream.phpà  ÃÅaà  •y ß¤      0   vendor/amphp/byte-stream/lib/ZlibInputStream.phpD  ÃÅaD  y!d¤      0   vendor/amphp/byte-stream/lib/StreamException.phpN   ÃÅaN   C)Ì«¤      +   vendor/amphp/byte-stream/lib/LineReader.phpõ  ÃÅaõ  hf„¤      *   vendor/amphp/byte-stream/lib/functions.php  ÃÅa  ‘Ûûd¤      0   vendor/amphp/byte-stream/lib/ClosedException.phpY   ÃÅaY   �vJI¤      (   vendor/amphp/byte-stream/lib/Payload.php¯	  ÃÅa¯	  MØÏÅ¤      1   vendor/amphp/byte-stream/lib/PendingReadError.phpÆ  ÃÅaÆ  M-€‡¤      1   vendor/amphp/byte-stream/lib/ZlibOutputStream.php=  ÃÅa=  ’±¤Õ¤      -   vendor/amphp/byte-stream/lib/OutputBuffer.phpÕ  ÃÅaÕ  áq¤      /   vendor/amphp/byte-stream/lib/InMemoryStream.phpG  ÃÅaG  ë„ê¤         vendor/amphp/dns/composer.json@  ÃÅa@  ƒœð¤      +   vendor/amphp/dns/lib/Internal/TcpSocket.php  ÃÅa  n¢–D¤      +   vendor/amphp/dns/lib/Internal/UdpSocket.phpK  ÃÅaK  Ò¶Úñ¤      (   vendor/amphp/dns/lib/Internal/Socket.php§  ÃÅa§  +‚kÃ¤      )   vendor/amphp/dns/lib/UnixConfigLoader.php   ÃÅa   µÿ@J¤         vendor/amphp/dns/lib/Config.php*  ÃÅa*  G•�¤      %   vendor/amphp/dns/lib/ConfigLoader.php‰   ÃÅa‰   Q`Þ¤      (   vendor/amphp/dns/lib/ConfigException.phpV  ÃÅaV  i÷û¤      !   vendor/amphp/dns/lib/Resolver.php  ÃÅa  ËÏE¤      ,   vendor/amphp/dns/lib/WindowsConfigLoader.php  ÃÅa  sŠm¤      *   vendor/amphp/dns/lib/NoRecordException.phpK   ÃÅaK   ºq=´¤      1   vendor/amphp/dns/lib/BlockingFallbackResolver.php  ÃÅa  Ä>õ¤      "   vendor/amphp/dns/lib/functions.php¹
  ÃÅa¹
  év#Î¤      %   vendor/amphp/dns/lib/DnsException.phpD   ÃÅaD   ®Äú¤      )   vendor/amphp/dns/lib/TimeoutException.phpJ   ÃÅaJ   ¯._w¤      -   vendor/amphp/dns/lib/InvalidNameException.phpN   ÃÅaN   Lš3¤         vendor/amphp/dns/lib/Record.php±  ÃÅa±  kƒi¤      #   vendor/amphp/dns/lib/HostLoader.phpt	  ÃÅat	  ¬€L¤      ,   vendor/amphp/dns/lib/Rfc1035StubResolver.php«L  ÃÅa«L  ŸMçó¤      .   vendor/amphp/postgres/src/ConnectionConfig.phpå
  ÃÅaå
  v‡w-¤      3   vendor/amphp/postgres/src/ConnectionTransaction.php·   ÃÅa·   �9æ¤      )   vendor/amphp/postgres/src/PqStatement.php  ÃÅa  ÏTPù¤      -   vendor/amphp/postgres/src/PooledStatement.php¬  ÃÅa¬  Oêˆ£¤      ,   vendor/amphp/postgres/src/PgSqlResultSet.php™  ÃÅa™  vï}¤      1   vendor/amphp/postgres/src/PqBufferedResultSet.phpŸ  ÃÅaŸ  ¡û»_¤      0   vendor/amphp/postgres/src/PgSqlCommandResult.php0  ÃÅa0  #ÇB ¤      ,   vendor/amphp/postgres/src/ParseException.phpR  ÃÅaR  ïª~Ã¤      &   vendor/amphp/postgres/src/Receiver.php  ÃÅa  -3f7¤      *   vendor/amphp/postgres/src/PqConnection.php›  ÃÅa›  U@ Ž¤      0   vendor/amphp/postgres/src/ConnectionListener.phpë  ÃÅaë  Û#®ò¤      .   vendor/amphp/postgres/src/TimeoutConnector.php_  ÃÅa_  s7aÜ¤      -   vendor/amphp/postgres/src/PgSqlConnection.php±  ÃÅa±  íy{e¤      &   vendor/amphp/postgres/src/PqHandle.phpG>  ÃÅaG>  ö�2¤      $   vendor/amphp/postgres/src/Quoter.phpU  ÃÅaU  •’�º¤      -   vendor/amphp/postgres/src/PqCommandResult.php;  ÃÅa;  }e>¤      0   vendor/amphp/postgres/src/Internal/functions.phpF
  ÃÅaF
  Ýê`<¤      2   vendor/amphp/postgres/src/Internal/ArrayParser.php¸  ÃÅa¸  cd„Ë¤      ,   vendor/amphp/postgres/src/PgSqlStatement.php´  ÃÅa´  Ëp/¤      "   vendor/amphp/postgres/src/Pool.php×  ÃÅa×  b°g§¤      +   vendor/amphp/postgres/src/StatementPool.php†  ÃÅa†  z¸Y¤      (   vendor/amphp/postgres/src/Connection.phpž  ÃÅaž  õ;™Ó¤      ,   vendor/amphp/postgres/src/PooledListener.phpû  ÃÅaû  ¶±äM¤      '   vendor/amphp/postgres/src/ResultSet.php  ÃÅa  ÎÁlî¤      &   vendor/amphp/postgres/src/Executor.php.  ÃÅa.  Ã�®ý¤      "   vendor/amphp/postgres/src/Link.phpi   ÃÅai   R3‹£¤      )   vendor/amphp/postgres/src/Transaction.php  ÃÅa  ×²E¤      '   vendor/amphp/postgres/src/functions.phpŽ  ÃÅaŽ  Ïì#&¤      /   vendor/amphp/postgres/src/PooledTransaction.phpÙ  ÃÅaÙ  X°M?¤      1   vendor/amphp/postgres/src/QueryExecutionError.php  ÃÅa  Mñè<¤      $   vendor/amphp/postgres/src/Handle.phpw   ÃÅaw   GMö¤      &   vendor/amphp/postgres/src/Listener.php!  ÃÅa!  ž—¤      -   vendor/amphp/postgres/src/PooledResultSet.phpG  ÃÅaG  òš-Ÿ¤      3   vendor/amphp/postgres/src/PqUnbufferedResultSet.phpN	  ÃÅaN	  #îÀ¤      )   vendor/amphp/postgres/src/PgSqlHandle.php…B  ÃÅa…B  X E¡¤      *   vendor/amphp/postgres/src/Notification.php  ÃÅa  :õ’Ì¤      .   vendor/amphp/postgres/examples/transaction.php¾  ÃÅa¾  ž0¤      /   vendor/amphp/postgres/examples/multi-listen.php‰  ÃÅa‰  (÷?¤      )   vendor/amphp/postgres/examples/listen.php¾  ÃÅa¾  Vˆt÷¤      (   vendor/amphp/postgres/examples/basic.phpS  ÃÅaS  VHc¤      #   vendor/amphp/postgres/composer.jsonX  ÃÅaX  �ø{î¤      /   vendor/amphp/sql-common/src/PooledStatement.php	  ÃÅa	  Öw•¤      .   vendor/amphp/sql-common/src/RetryConnector.php@  ÃÅa@  õ}úÕ¤      .   vendor/amphp/sql-common/src/ConnectionPool.php¯1  ÃÅa¯1  �™§¤      -   vendor/amphp/sql-common/src/StatementPool.phpS  ÃÅaS  )�¤      1   vendor/amphp/sql-common/src/PooledTransaction.phpâ  ÃÅaâ  rF;Ÿ¤      /   vendor/amphp/sql-common/src/PooledResultSet.php7  ÃÅa7  £ù�S¤      %   vendor/amphp/sql-common/composer.jsonØ  ÃÅaØ  �)Û¤      3   vendor/amphp/sql-common/test/RetryConnectorTest.phpz  ÃÅaz  á(†¤      4   vendor/amphp/sql-common/test/PooledResultSetTest.php8  ÃÅa8  "TEq¤      3   vendor/amphp/sql-common/test/ConnectionPoolTest.phpÂ  ÃÅaÂ  å~�7¤      2   vendor/amphp/sql-common/test/StatementPoolTest.phpC  ÃÅaC  ýÔâ¦¤      !   vendor/amphp/parser/composer.json›  ÃÅa›  Ørá¤      1   vendor/amphp/parser/lib/InvalidDelimiterError.php÷  ÃÅa÷  ý4Ô´¤      "   vendor/amphp/parser/lib/Parser.php„  ÃÅa„  IZ€¤      /   vendor/amphp/hpack/src/Internal/HPackNative.phpôk  ÃÅaôk   N+¤      0   vendor/amphp/hpack/src/Internal/HPackNghttp2.php"  ÃÅa"  EÌl¤      2   vendor/amphp/hpack/src/Internal/huffman-lookup.php‘ ÃÅa‘ Äè�—¤      +   vendor/amphp/hpack/src/Internal/amp-hpack.hŸ  ÃÅaŸ  ÆF=a¤      1   vendor/amphp/hpack/src/Internal/huffman-codes.php¬ ÃÅa¬ -ÁÓ0¤      )   vendor/amphp/hpack/src/HPackException.phpM   ÃÅaM   ð �¤          vendor/amphp/hpack/src/HPack.php@  ÃÅa@  ¹¤      %   vendor/amphp/hpack/examples/bench.php'  ÃÅa'  ›:Ê¤      .   vendor/amphp/hpack/tools/php-fuzzer/decode.php¿   ÃÅa¿   ´êª¼¤      4   vendor/amphp/hpack/tools/php-fuzzer/decode-crash.php…   ÃÅa…   Ô— À¤      %   vendor/amphp/hpack/tools/compress.php  ÃÅa  Ó|ô`¤          vendor/amphp/hpack/composer.jsonÑ  ÃÅaÑ  7OÇæ¤      +   vendor/amphp/socket/src/SocketException.phps   ÃÅas   N>—¤      *   vendor/amphp/socket/src/DatagramSocket.phpM  ÃÅaM  pV­­¤      /   vendor/amphp/socket/src/UnlimitedSocketPool.php˜  ÃÅa˜  ZÌ•8¤      .   vendor/amphp/socket/src/Internal/functions.php­  ÃÅa­  Trwn¤      #   vendor/amphp/socket/src/TlsInfo.phpt  ÃÅat  8ân2¤      *   vendor/amphp/socket/src/ConnectContext.php©  ÃÅa©  *eP=¤      (   vendor/amphp/socket/src/TlsException.php«   ÃÅa«   Ð£#¤      %   vendor/amphp/socket/src/Connector.php¸  ÃÅa¸  Çæ¶W¤      /   vendor/amphp/socket/src/PendingReceiveError.phpÎ  ÃÅaÎ  gJX¤      ,   vendor/amphp/socket/src/ServerTlsContext.phpÐ3  ÃÅaÐ3  '·l�¤      '   vendor/amphp/socket/src/BindContext.php™  ÃÅa™  Ãäµ¤      .   vendor/amphp/socket/src/PendingAcceptError.phpÈ  ÃÅaÈ  ýÆ¤      ,   vendor/amphp/socket/src/ConnectException.phpw   ÃÅaw   Ì“"!¤      +   vendor/amphp/socket/src/StaticConnector.php¡  ÃÅa¡  êžÂž¤      *   vendor/amphp/socket/src/ResourceSocket.php  ÃÅa  X“„&¤      )   vendor/amphp/socket/src/SocketAddress.php 
  ÃÅa 
  ¾(œ€¤      %   vendor/amphp/socket/src/functions.php-  ÃÅa-  z Ñž¤      ,   vendor/amphp/socket/src/ClientTlsContext.phpö/  ÃÅaö/  �Â¹Ô¤      -   vendor/amphp/socket/src/EncryptableSocket.php   ÃÅa   Ö>–¤      "   vendor/amphp/socket/src/Socket.php  ÃÅa  ãA¤      (   vendor/amphp/socket/src/DnsConnector.php.  ÃÅa.  À‘…¤      '   vendor/amphp/socket/src/Certificate.php  ÃÅa  ¿\Ã¤      &   vendor/amphp/socket/src/SocketPool.php5  ÃÅa5  ö›�¤      "   vendor/amphp/socket/src/Server.php€  ÃÅa€  íÅ¤      !   vendor/amphp/socket/composer.jsont  ÃÅat  ™«ß¤      -   vendor/amphp/sync/composer-require-check.jsonû  ÃÅaû  *×ÀX¤      0   vendor/amphp/sync/src/PrefixedKeyedSemaphore.php  ÃÅa  +é„/¤      -   vendor/amphp/sync/src/LocalKeyedSemaphore.phpC  ÃÅaC  �þ'¤      #   vendor/amphp/sync/src/Semaphore.php×  ÃÅa×  äù5b¤      3   vendor/amphp/sync/src/Internal/SemaphoreStorage.phpZ  ÃÅaZ  ÚÆ!¤      /   vendor/amphp/sync/src/Internal/MutexStorage.phpX  ÃÅaX  .òf¤      '   vendor/amphp/sync/src/SyncException.phpF   ÃÅaF   =rE¤      6   vendor/amphp/sync/src/ConcurrentIterator/functions.phpç  ÃÅaç  ôü¤         vendor/amphp/sync/src/Mutex.php¢  ÃÅa¢  qšÏs¤      +   vendor/amphp/sync/src/ThreadedSemaphore.php©  ÃÅa©  Üæ�¤      (   vendor/amphp/sync/src/StaticKeyMutex.phpÎ  ÃÅaÎ  u¤ëŠ¤      (   vendor/amphp/sync/src/PosixSemaphore.phpr  ÃÅar  3'‰
¤      )   vendor/amphp/sync/src/LocalKeyedMutex.phpn  ÃÅan  b»UÃ¤      !   vendor/amphp/sync/src/Barrier.phpþ  ÃÅaþ  -¼ºˆ¤      (   vendor/amphp/sync/src/LocalSemaphore.phpÊ  ÃÅaÊ  –Í+d¤      ,   vendor/amphp/sync/src/PrefixedKeyedMutex.phpø  ÃÅaø  È[dY¤      '   vendor/amphp/sync/src/ThreadedMutex.php¤  ÃÅa¤  ï¤      (   vendor/amphp/sync/src/KeyedSemaphore.php  ÃÅa  �;“©¤      #   vendor/amphp/sync/src/FileMutex.php­  ÃÅa­  ¦ÀÀ¤         vendor/amphp/sync/src/Lock.phpÏ  ÃÅaÏ  Õõ¡°¤      (   vendor/amphp/sync/src/SemaphoreMutex.php   ÃÅa   2£()¤      #   vendor/amphp/sync/src/functions.phph  ÃÅah  Ôël¤¤      $   vendor/amphp/sync/src/LocalMutex.php®  ÃÅa®   å£È¤      $   vendor/amphp/sync/src/KeyedMutex.phpí  ÃÅaí  Ž¶nŸ¤         vendor/amphp/sync/composer.json5  ÃÅa5  ;îí          vendor/amphp/cache/composer.jsonc  ÃÅac  |œi¤      %   vendor/amphp/cache/lib/ArrayCache.php…  ÃÅa…  $Ô¨Ä¤      *   vendor/amphp/cache/lib/SerializedCache.php*
  ÃÅa*
  â ‘S¤      &   vendor/amphp/cache/lib/AtomicCache.phpG#  ÃÅaG#  ¶®Œ®¤      $   vendor/amphp/cache/lib/NullCache.php�  ÃÅa�  J5ž¤      $   vendor/amphp/cache/lib/FileCache.phpÂ  ÃÅaÂ  V¤À;¤      &   vendor/amphp/cache/lib/PrefixCache.phpÛ  ÃÅaÛ  ­Aå¤      )   vendor/amphp/cache/lib/CacheException.phpƒ   ÃÅaƒ   †æºq¤          vendor/amphp/cache/lib/Cache.phpw  ÃÅaw  )åÖ¤      &   vendor/amphp/log/src/StreamHandler.phpÒ  ÃÅaÒ  ëª´¿¤      "   vendor/amphp/log/src/functions.phpA  ÃÅaA  %ê—ø¤      )   vendor/amphp/log/src/ConsoleFormatter.phpÛ	  ÃÅaÛ	  ¨w×Œ¤      )   vendor/amphp/log/examples/hello-world.php
  ÃÅa
  2Kåº¤         vendor/amphp/log/composer.jsonó  ÃÅaó  6¨W¤         vendor/league/uri/src/Http.phpq  ÃÅaq  ‰$WÏ¤      !   vendor/league/uri/src/UriInfo.php'  ÃÅa'  FÙ8¤      %   vendor/league/uri/src/UriResolver.phpÇ*  ÃÅaÇ*  a1Úñ¤         vendor/league/uri/src/Uri.php –  ÃÅa –  [rŒ¤      =   vendor/league/uri/src/Exceptions/TemplateCanNotBeExpanded.phpu  ÃÅau  ›ÐC&¤      0   vendor/league/uri/src/UriTemplate/Expression.phpW(  ÃÅaW(  ñc#†¤      2   vendor/league/uri/src/UriTemplate/VarSpecifier.php™
  ÃÅa™
  �qé0¤      1   vendor/league/uri/src/UriTemplate/VariableBag.phpS  ÃÅaS  ^Ü ¤      .   vendor/league/uri/src/UriTemplate/Template.php™  ÃÅa™  =™¨¤      #   vendor/league/uri/src/UriString.php:  ÃÅa:  5§V¤      %   vendor/league/uri/src/HttpFactory.php=  ÃÅa=  Z�¤      %   vendor/league/uri/src/UriTemplate.phpê  ÃÅaê  ³®c¤      #   vendor/league/uri/.php-cs-fixer.php;  ÃÅa;  .†€¤         vendor/league/uri/composer.json$  ÃÅa$  §²!¤      2   vendor/league/uri-parser/src/MissingIdnSupport.phpú  ÃÅaú  ¹%>¤      *   vendor/league/uri-parser/src/Exception.php‘	  ÃÅa‘	  OÀ]¤      *   vendor/league/uri-parser/src/functions.php  ÃÅa  êIuò¤      2   vendor/league/uri-parser/src/functions_include.phpõ  ÃÅaõ  [iœ¤      '   vendor/league/uri-parser/src/Parser.phpZ  ÃÅaZ  „<üL¤      &   vendor/league/uri-parser/composer.json>  ÃÅa>  Ò'¤      2   vendor/league/uri-interfaces/src/Idna/IdnaInfo.php[  ÃÅa[  JYùþ¤      .   vendor/league/uri-interfaces/src/Idna/Idna.php4  ÃÅa4  ¢D{ñ¤      F   vendor/league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php«  ÃÅa«  GA\Ã¤      ;   vendor/league/uri-interfaces/src/Exceptions/SyntaxError.php¨  ÃÅa¨  |cÔú¤      A   vendor/league/uri-interfaces/src/Exceptions/IdnSupportMissing.php¦  ÃÅa¦  ª%¥¤      D   vendor/league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php”  ÃÅa”  ¹�h?¤      B   vendor/league/uri-interfaces/src/Contracts/DomainHostInterface.phpý
  ÃÅaý
  ¥�£.¤      <   vendor/league/uri-interfaces/src/Contracts/PortInterface.phpÕ  ÃÅaÕ  Ù_”¤      ;   vendor/league/uri-interfaces/src/Contracts/UriInterface.php'  ÃÅa'  6ùI¤      @   vendor/league/uri-interfaces/src/Contracts/UserInfoInterface.phpÖ  ÃÅaÖ  õ_Ê¤      ;   vendor/league/uri-interfaces/src/Contracts/UriException.phpl  ÃÅal  ³Ì]¤      D   vendor/league/uri-interfaces/src/Contracts/UriComponentInterface.phpr  ÃÅar  S•¦g¤      @   vendor/league/uri-interfaces/src/Contracts/DataPathInterface.phpw
  ÃÅaw
  ’ò—¤      A   vendor/league/uri-interfaces/src/Contracts/AuthorityInterface.php
  ÃÅa
  ªÖî½¤      >   vendor/league/uri-interfaces/src/Contracts/IpHostInterface.phpÖ  ÃÅaÖ  ›3½¤      <   vendor/league/uri-interfaces/src/Contracts/HostInterface.phpZ  ÃÅaZ  ¾ö¥o¤      E   vendor/league/uri-interfaces/src/Contracts/SegmentedPathInterface.php  ÃÅa  i¤TÆ¤      =   vendor/league/uri-interfaces/src/Contracts/QueryInterface.phpá  ÃÅaá  ]}èä¤      @   vendor/league/uri-interfaces/src/Contracts/FragmentInterface.phpÌ  ÃÅaÌ  qIQ¸¤      <   vendor/league/uri-interfaces/src/Contracts/PathInterface.php£
  ÃÅa£
  ©�Rª¤      *   vendor/league/uri-interfaces/composer.json   ÃÅa   ›Ôm‡¤      !   vendor/composer/autoload_real.phpõ	  ÃÅaõ	  M[Wç¤      "   vendor/composer/platform_check.php�  ÃÅa�  >¢¨L¤      !   vendor/composer/autoload_psr4.php|  ÃÅa|  Ž}Žp¤      %   vendor/composer/autoload_classmap.php1X ÃÅa1X 9È`¤         vendor/composer/ClassLoader.php8  ÃÅa8  4ˆ)Å¤      '   vendor/composer/autoload_namespaces.phpÅ  ÃÅaÅ  >´—À¤      "   vendor/composer/autoload_files.php¿  ÃÅa¿  ÄËA}¤      #   vendor/composer/autoload_static.phpî ÃÅaî ~ïÕX¤         vendor/composer/installed.jsonó4 ÃÅaó4 —øXÑ¤         vendor/composer/installed.phpqE  ÃÅaqE  uÀþž¤      %   vendor/composer/InstalledVersions.phpÁj  ÃÅaÁj  |<áP¤      3   vendor/danog/loop/examples/1. Basic/GenericLoop.php_  ÃÅa_  8�¢Y¤      4   vendor/danog/loop/examples/1. Basic/PeriodicLoop.phpN  ÃÅaN  ‰da¤      8   vendor/danog/loop/examples/2. Advanced/ResumableLoop.php…  ÃÅa…  àû½¤      5   vendor/danog/loop/examples/2. Advanced/SignalLoop.php  ÃÅa  �…­z¤      >   vendor/danog/loop/examples/2. Advanced/ResumableSignalLoop.php  ÃÅa  Ï·aç¤      /   vendor/danog/loop/examples/2. Advanced/Loop.php:  ÃÅa:  »j³ß¤         vendor/danog/loop/composer.json˜  ÃÅa˜  ¢f¿è¤      -   vendor/danog/loop/lib/Generic/GenericLoop.php+  ÃÅa+  n¶Þ¢¤      .   vendor/danog/loop/lib/Generic/PeriodicLoop.phpö
  ÃÅaö
  Ìþ¤      '   vendor/danog/loop/lib/ResumableLoop.php	  ÃÅa	  7Ù“ñ¤      $   vendor/danog/loop/lib/SignalLoop.php  ÃÅa  Zr±¤      -   vendor/danog/loop/lib/ResumableSignalLoop.phpz  ÃÅaz  ?kNô¤         vendor/danog/loop/lib/Loop.php¿  ÃÅa¿  =ê©¤      2   vendor/danog/loop/lib/Interfaces/LoopInterface.php[  ÃÅa[  ¹¿º!¤      ;   vendor/danog/loop/lib/Interfaces/ResumableLoopInterface.php  ÃÅa  ¡ZO¤      8   vendor/danog/loop/lib/Interfaces/SignalLoopInterface.php$  ÃÅa$  ÿwÊ¤      .   vendor/danog/loop/lib/Traits/ResumableLoop.phpç  ÃÅaç   "Ê¤      +   vendor/danog/loop/lib/Traits/SignalLoop.php  ÃÅa  Ûl¤      %   vendor/danog/loop/lib/Traits/Loop.php  ÃÅa  ÞÃbÌ¤      %   vendor/danog/loop/test/SignalTest.php0	  ÃÅa0	  Ke•‘¤      '   vendor/danog/loop/test/PeriodicTest.php#  ÃÅa#  *.¤      (   vendor/danog/loop/test/ResumableTest.php'  ÃÅa'  T°ð~¤      #   vendor/danog/loop/test/Fixtures.phpª	  ÃÅaª	  ÒdÆ»¤      6   vendor/danog/loop/test/Interfaces/LoggingInterface.phpŠ  ÃÅaŠ  _¡Z¤      7   vendor/danog/loop/test/Interfaces/IntervalInterface.php  ÃÅa  7­HÀ¤      4   vendor/danog/loop/test/Interfaces/BasicInterface.php¦  ÃÅa¦  gÛó¤      ;   vendor/danog/loop/test/Interfaces/LoggingPauseInterface.phpµ  ÃÅaµ  ºì¦¤      5   vendor/danog/loop/test/Interfaces/SignalInterface.phpÈ  ÃÅaÈ  Pî²C¤      8   vendor/danog/loop/test/Interfaces/ResumableInterface.phpé  ÃÅaé  ©åûQ¤      &   vendor/danog/loop/test/GenericTest.phpZ!  ÃÅaZ!  ?š’ ¤      0   vendor/danog/loop/test/Traits/BasicException.php  ÃÅa  "o"¤      '   vendor/danog/loop/test/Traits/Basic.phpÊ  ÃÅaÊ  &o¤      (   vendor/danog/loop/test/Traits/Signal.phpH  ÃÅaH  *�"¤      )   vendor/danog/loop/test/Traits/Logging.phpŠ  ÃÅaŠ  ÍoÈf¤      .   vendor/danog/loop/test/Traits/LoggingPause.phpŽ  ÃÅaŽ  ^$Úm¤      +   vendor/danog/loop/test/Traits/Resumable.php=  ÃÅa=  ‰�â¤      #   vendor/danog/loop/test/LoopTest.phpŽ
  ÃÅaŽ
  o�è¤      )   vendor/danog/dns-over-https/composer.jsonÀ  ÃÅaÀ  zb¤      -   vendor/danog/dns-over-https/lib/DoHConfig.phpz	  ÃÅaz	  ü>&¤      0   vendor/danog/dns-over-https/lib/DoHException.phpp   ÃÅap   ·Z_/¤      8   vendor/danog/dns-over-https/lib/Internal/HttpsSocket.phpç  ÃÅaç  í�m¤      3   vendor/danog/dns-over-https/lib/Internal/Socket.phpÕ  ÃÅaÕ  € ˜¤      7   vendor/danog/dns-over-https/lib/Rfc8484StubResolver.phpð>  ÃÅað>  Y¼¤      .   vendor/danog/dns-over-https/lib/Nameserver.phpÒ  ÃÅaÒ  3¢ò¤      3   vendor/danog/tg-file-decoder/.php-cs-fixer.dist.php  ÃÅa  s�ÕÔ¤      M   vendor/danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceThumbnail.php£	  ÃÅa£	  }Åœ¤      ^   vendor/danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceStickersetThumbnailVersion.phpm  ÃÅam  �~¤      O   vendor/danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceDialogPhoto.phpO
  ÃÅaO
  ol¬®¤      J   vendor/danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceLegacy.php€  ÃÅa€  »«EL¤      W   vendor/danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceStickersetThumbnail.php	  ÃÅa	  �¤å{¤      +   vendor/danog/tg-file-decoder/src/FileId.php<  ÃÅa<  õ«ŽÍ¤      )   vendor/danog/tg-file-decoder/src/type.php²D  ÃÅa²D  X$˜¤      4   vendor/danog/tg-file-decoder/src/PhotoSizeSource.php¯  ÃÅa¯  ‹-÷µ¤      1   vendor/danog/tg-file-decoder/src/UniqueFileId.php,  ÃÅa,  Mcô¤      *   vendor/danog/tg-file-decoder/composer.json“  ÃÅa“  	¾¾S¤      &   vendor/danog/libdns-json/composer.json:  ÃÅa:  9Kÿ…¤      ,   vendor/danog/libdns-json/lib/JsonDecoder.phpž2  ÃÅaž2  ×ÝW¢¤      -   vendor/danog/libdns-json/lib/QueryEncoder.phpõ  ÃÅaõ  ƒ{‘¤      4   vendor/danog/libdns-json/lib/QueryEncoderFactory.php5  ÃÅa5  Z|ùÄ¤      3   vendor/danog/libdns-json/lib/JsonDecoderFactory.phpÿ  ÃÅaÿ  N&L´¤      8   vendor/danog/libdns-json/test/JsonDecoderFactoryTest.phpu  ÃÅau  *¯¤      1   vendor/danog/libdns-json/test/JsonDecoderTest.php‹  ÃÅa‹  ð‚><¤      9   vendor/danog/libdns-json/test/QueryEncoderFactoryTest.php{  ÃÅa{  š(¿¤      2   vendor/danog/libdns-json/test/QueryEncoderTest.phpï  ÃÅaï  Õö7¤      &   vendor/danog/primemodule/composer.jsonb  ÃÅab  ½úv¤      /   vendor/danog/primemodule/lib/danog/alt_prime.py±  ÃÅa±  _3î{¤      2   vendor/danog/primemodule/lib/danog/PrimeModule.phpL<  ÃÅaL<  M‚ü+¤      +   vendor/danog/primemodule/lib/danog/prime.pyÜ-  ÃÅaÜ-  ò™B¤      1   vendor/danog/madelineproto/.php-cs-fixer.dist.php4  ÃÅa4  „��Y¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/Serialization.php37  ÃÅa37  AûÖ©¤      E   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Ogg/Ogg.php*/  ÃÅa*/  âVç¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/WssStream.phpN  ÃÅaN  ¾Æsp¤      U   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/DefaultStream.phpt  ÃÅat  ð¨¹Â¤      U   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/PremadeStream.php(  ÃÅa(  ˜^ž¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/WsStream.phpŒ  ÃÅaŒ  ßGt¨¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Async/RawStream.phpj  ÃÅaj  âaèÇ¤      J   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Async/Buffer.php  ÃÅa  ­že€¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Async/BufferedStream.phpÍ  ÃÅaÍ  /ýi3¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/ConnectionContext.phpÖ+  ÃÅaÖ+  útâo¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Proxy/SocksProxy.phpa  ÃÅaa  sz9%¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Proxy/HttpProxy.phpÁ  ÃÅaÁ  î’Î¤      Z   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/BufferedProxyStreamInterface.php²  ÃÅa²  ü¤      V   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/ADNLTransport/ADNLStream.phpl  ÃÅal  gž÷w¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/ProxyStreamInterface.php  ÃÅa  Tsý`¤      \   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Common/SimpleBufferedRawStream.php>
  ÃÅa>
  ¨¹›¤      W   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Common/FileBufferedStream.php`  ÃÅa`  e(Ñ¤      Y   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Common/HashedBufferedStream.phpÊ#  ÃÅaÊ#  Á1™Ä¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Common/CtrStream.php¶  ÃÅa¶  Íy™¤      V   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Common/BufferedRawStream.php2  ÃÅa2  ÓjÄž¤      V   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/Common/UdpBufferedStream.phpÿ  ÃÅaÿ  \ät¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/RawStreamInterface.phpÐ  ÃÅaÐ  Ú”A¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/WriteBufferInterface.php&  ÃÅa&  	Øôb¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/StreamInterface.php€  ÃÅa€  Ú�ö¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/ReadBufferInterface.php(  ÃÅa(  ˆÌË¤      U   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/BufferedStreamInterface.phpØ  ÃÅaØ  ™EHÓ¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/BufferInterface.phpƒ  ÃÅaƒ  ú}bX¤      U   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/RawProxyStreamInterface.phpž  ÃÅaž  ò*í¤      T   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoBufferInterface.php“  ÃÅa“  %A${¤      ]   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/AbridgedStream.phpe  ÃÅae  øÀ¤      _   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/ObfuscatedStream.php[  ÃÅa[  ç–»¤      a   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/IntermediateStream.phpV  ÃÅaV  z.V[¤      Y   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/HttpStream.php¤  ÃÅa¤  Äâ+•¤      Z   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/HttpsStream.php‚  ÃÅa‚  Xçºù¤      Y   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/FullStream.php(  ÃÅa(  3¾–©¤      g   vendor/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/IntermediatePaddedStream.php  ÃÅa  xy~?¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/EventHandler.phpÌ  ÃÅaÌ  .Ý‰k¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/APIWrapper.php}  ÃÅa}  †mˆ‰¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/VoIPServerConfig.php_	  ÃÅa_	  vÖ‰¬¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/LightState.php   ÃÅa   NÓ³¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/DoHConnector.phpŸ!  ÃÅaŸ!  Â8_�¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/ExitFailure.phpŽ  ÃÅaŽ  ÓÜL±¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/IpcState.phpœ  ÃÅaœ  L!ü¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/ServerCallback.phpX  ÃÅaX  JÒPô¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Client.php¿2  ÃÅa¿2  ¬X›s¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/OutputStream.phpð  ÃÅað  ë„Á¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableTrait.php–  ÃÅa–  ö„¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/InputStream.php�  ÃÅa�  îc&3¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/FileCallback.phpª  ÃÅaª  ¨LA¤      V   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableInputStream.php{   ÃÅa{   Ž_&–¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/Obj.phpz  ÃÅaz  •m¤      W   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableOutputStream.php}   ÃÅa}   ›ƒ™¯¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/WrapMethodTrait.phpô  ÃÅaô  !5¡—¤      B   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper.phpÜ  ÃÅaÜ  Í°‡¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/ClientAbstract.phpz  ÃÅaz  ,à÷‰¤      K   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/WebRunner.php  ÃÅa  `)ë¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/entry.php7  ÃÅa7  �Ö ¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/ProcessRunner.phpQ  ÃÅaQ  ª :¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/RunnerAbstract.php
  ÃÅa
  š²i-¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Server.php�$  ÃÅa�$  ÊMÆ¤      B   vendor/danog/madelineproto/src/danog/MadelineProto/InternalDoc.php�Y ÃÅa�Y VxB¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/TL_telegram_v135.tln ÃÅan ¥²¦f¤      :   vendor/danog/madelineproto/src/danog/MadelineProto/RSA.phpœ  ÃÅaœ  æ}Z¤      @   vendor/danog/madelineproto/src/danog/MadelineProto/Exception.phpQ  ÃÅaQ  š™W4¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/Reliable.php×  ÃÅa×  #º«Ï¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/Session.php;  ÃÅa;  ìj ×¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/SeqNoHandler.phpD  ÃÅaD  Æ‘ÖÞ¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/CallHandler.php4$  ÃÅa4$  É³O¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/AckHandler.php  ÃÅa  
>	ó¤      a   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/MsgIdHandler/MsgIdHandler64.php  ÃÅa  7]9¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/MsgIdHandler.php‰  ÃÅa‰  E#ò'¤      U   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/ResponseHandler.phpW  ÃÅaW  ÝS]¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/MTProto/Container.phpþ  ÃÅaþ  ‚�Îx¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/MTProto/OutgoingMessage.phpA6  ÃÅaA6  G ¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/MTProto/IncomingMessage.php<  ÃÅa<  a‚¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/MTProto/Message.phpð  ÃÅað  ,e•ô¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/MTProto/AuthKey.php  ÃÅa  Ä¤k¤      J   vendor/danog/madelineproto/src/danog/MadelineProto/MTProto/PermAuthKey.phpj	  ÃÅaj	  ÔO}L¤      J   vendor/danog/madelineproto/src/danog/MadelineProto/MTProto/TempAuthKey.phpm  ÃÅam  Ç£Q¨¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/RPCErrorException.php‚  ÃÅa‚  j)œÛ¤      :   vendor/danog/madelineproto/src/danog/MadelineProto/API.phpMN  ÃÅaMN  "»@¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/SessionPaths.phpÙ  ÃÅaÙ  0Øî1¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/SettingsAbstract.php‘
  ÃÅa‘
  ‡6¤      K   vendor/danog/madelineproto/src/danog/MadelineProto/Async/AsyncConstruct.phpO
  ÃÅaO
  ?�0¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/TON/InternalDoc.php÷Œ  ÃÅa÷Œ  ºc²¤      >   vendor/danog/madelineproto/src/danog/MadelineProto/TON/API.phpl  ÃÅal  ß(
=¤      E   vendor/danog/madelineproto/src/danog/MadelineProto/TON/APIFactory.phpÑ  ÃÅaÑ  £ŠAô¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/TON/ADNLConnection.php9  ÃÅa9  ×9h¤      ?   vendor/danog/madelineproto/src/danog/MadelineProto/TON/Lite.phpo  ÃÅao  	U‹Ú¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/Bug74586Exception.php  ÃÅa  ƒû)¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/DataCenter.phpl  ÃÅal  W¬ÆÞ¤      T   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGEOpenssl.php
  ÃÅa
  6¹¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGE.php|  ÃÅa|  8RŠX¤      V   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGEPhpseclib.php$
  ÃÅa$
  K�Ò¤      X   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/CombinedUpdatesState.phpo  ÃÅao  ë¡L¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/UpdatesState.phpr  ÃÅar  õí®µ¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/CallHandler.phpÕ  ÃÅaÕ  pœ‡Ü¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/PeerHandler.phpêæ  ÃÅaêæ  Ñv3¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.phpê   ÃÅaê   hä|¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/ResponseInfo.phpP  ÃÅaP  á�E¤      U   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/ReferenceDatabase.php c  ÃÅa c  Á\ùÚ¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/MinDatabase.phpX   ÃÅaX   $ìë;¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt.phpÌ%  ÃÅaÌ%  “àÕ1¤      V   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/PasswordCalculator.phpH*  ÃÅaH*  ‹lók¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Files.phpUÈ  ÃÅaUÈ  ‚ôÐ¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/FilesLogic.php¤7  ÃÅa¤7  x÷›ž¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/UpdateHandler.phpK  ÃÅaK  w0=5¤      >   vendor/danog/madelineproto/src/danog/MadelineProto/FastAPI.php  ÃÅa  óþ¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/ResponseException.php|  ÃÅa|  ÔâU¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/APIFactory.phpš  ÃÅaš  må…¤      ?   vendor/danog/madelineproto/src/danog/MadelineProto/TL_botAPI.tlB  ÃÅaB  –¶_¤      ;   vendor/danog/madelineproto/src/danog/MadelineProto/VoIP.phpþI  ÃÅaþI  &ÏŒU¤      ?   vendor/danog/madelineproto/src/danog/MadelineProto/TL_secret.tl¼  ÃÅa¼  Ô7¤      X   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/PeriodicLoopInternal.php¼  ÃÅa¼  œD’¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/GenericLoop.php
  ÃÅa
  gXÌ¸¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/PeriodicLoop.phpæ  ÃÅaæ  èlS
¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/LoggerLoop.phpñ  ÃÅañ  S}’-¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/InternalLoop.phpz  ÃÅaz  µÉÃt¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/APILoop.phpþ  ÃÅaþ  ô‡"<¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/ReadLoop.phpü+  ÃÅaü+  P˜þ¤      S   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/HttpWaitLoop.phpã
  ÃÅaã
  n ¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/CleanupLoop.phpÏ  ÃÅaÏ  \Êˆ­¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/Common.phpË  ÃÅaË  $ÿEò¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/PingLoop.phpç	  ÃÅaç	  éq1ø¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/WriteLoop.phpQF  ÃÅaQF  â¬¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/CheckLoop.php#  ÃÅa#  G¤¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Update/SecretFeedLoop.php0  ÃÅa0  Móz¤      K   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Update/FeedLoop.phpË,  ÃÅaË,  �Í-¤      J   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Update/SeqLoop.phpþ  ÃÅaþ  Äúm‘¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Loop/Update/UpdateLoop.phpš-  ÃÅaš-  ¡àÍ¤      =   vendor/danog/madelineproto/src/danog/MadelineProto/Logger.phpŸ1  ÃÅaŸ1  µŒóJ¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/PTSException.phpû  ÃÅaû  ·R@T¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/ApiWrappers/Start.php"  ÃÅa"  gãÜ¤      L   vendor/danog/madelineproto/src/danog/MadelineProto/ApiWrappers/Templates.phpŠ  ÃÅaŠ  ³IÐ¤      :   vendor/danog/madelineproto/src/danog/MadelineProto/Lua.phpƒ  ÃÅaƒ  ¤Dþ¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/Files/Server.phpŒ  ÃÅaŒ  ¹^)B¤      B   vendor/danog/madelineproto/src/danog/MadelineProto/DocsBuilder.phpµ  ÃÅaµ  ÒË¤      @   vendor/danog/madelineproto/src/danog/MadelineProto/Coroutine.php‰-  ÃÅa‰-  1§'¤      ?   vendor/danog/madelineproto/src/danog/MadelineProto/StrTools.phpt
  ÃÅat
  œÙè¤      B   vendor/danog/madelineproto/src/danog/MadelineProto/Db/SqlArray.php&!  ÃÅa&!  §YKS¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Redis.phpP  ÃÅaP  ’” F¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Mysql.phpe  ÃÅae  Ä ¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Postgres.php•  ÃÅa•  ¨µ¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Db/DbPropertiesFactory.phpŒ
  ÃÅaŒ
  …í¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/PostgresArray.phpú   ÃÅaú   \jçj¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/MysqlArray.phpë   ÃÅaë   {3¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/NullCacheTrait.phpÿ  ÃÅaÿ  ¦õk¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/RedisArray.phpë   ÃÅaë   h¨‹ù¤      K   vendor/danog/madelineproto/src/danog/MadelineProto/Db/DbPropertiesTrait.php5  ÃÅa5  Ÿ4ï¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/Db/PostgresArray.php‹  ÃÅa‹  2TIñ¤      @   vendor/danog/madelineproto/src/danog/MadelineProto/Db/DbType.php‹  ÃÅa‹  9Ç7ÿ¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/Db/MysqlArray.phpÐ  ÃÅaÐ  Ÿh~´¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/Db/DbArray.phpØ  ÃÅaØ  Ýá¶ý¤      E   vendor/danog/madelineproto/src/danog/MadelineProto/Db/DriverArray.php  ÃÅa  îwß„¤      E   vendor/danog/madelineproto/src/danog/MadelineProto/Db/MemoryArray.php™  ÃÅa™  ñ&KÔ¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/Db/RedisArray.php8#  ÃÅa8#  =,šC¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/Db/ArrayCacheTrait.phpd  ÃÅad  s­#¬¤      ?   vendor/danog/madelineproto/src/danog/MadelineProto/Settings.php
<  ÃÅa
<  ù[¬¤      ?   vendor/danog/madelineproto/src/danog/MadelineProto/Shutdown.php£
  ÃÅa£
  ‹ÜCê¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/Connection.php%M  ÃÅa%M  Ýƒ¦	¤      ;   vendor/danog/madelineproto/src/danog/MadelineProto/Lang.phpìs  ÃÅaìs  ½„Ák¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/TL_mtproto_v1.tlW  ÃÅaW  rnÝÖ¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/FileCallback.phpÙ  ÃÅaÙ  '¡Aß¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/NothingInTheSocketException.php*  ÃÅa*  WÞ±¤      K   vendor/danog/madelineproto/src/danog/MadelineProto/DataCenterConnection.phphK  ÃÅahK  ®ŠÍã¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/DocsBuilder/Constructors.phpÐ5  ÃÅaÐ5  _	:¤      J   vendor/danog/madelineproto/src/danog/MadelineProto/DocsBuilder/Methods.php=  ÃÅa=  Z¢Ì¤      <   vendor/danog/madelineproto/src/danog/MadelineProto/Tools.phpvz  ÃÅavz  v]™š¤      L   vendor/danog/madelineproto/src/danog/MadelineProto/FileCallbackInterface.php~  ÃÅa~  Û;¯¤      K   vendor/danog/madelineproto/src/danog/MadelineProto/MyTelegramOrgWrapper.phpp5  ÃÅap5  É²®¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Serialization.phpÚ  ÃÅaÚ  Ï‰æz¤      K   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/SecretChats.phpU  ÃÅaU  ™í‰Ž¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/RPC.phpú  ÃÅaú  ˜Šº¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Auth.phpg
  ÃÅag
  æòŒÔ¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/AppInfo.phpQ  ÃÅaQ  @/žH¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Ipc.php7  ÃÅa7  #V¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/VoIP.php÷  ÃÅa÷  +=]G¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Logger.phpd  ÃÅad  EbÖD¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Pwr.phpÂ  ÃÅaÂ  Ûvqµ¤      J   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Connection.phpµJ  ÃÅaµJ  áY¶b¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Templates.phpñ  ÃÅañ  ¸ÉæU¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Peer.phpA
  ÃÅaA
  €Ú±¤      T   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Database/SqlAbstract.php  ÃÅa  8¦ï¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Redis.phpt  ÃÅat  %ê›Š¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Memory.php)  ÃÅa)  Ÿè¯¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Mysql.php  ÃÅa  ˆŸ6¢¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Postgres.phpä  ÃÅaä  ~Æ¤      Y   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Database/DatabaseAbstract.phpß  ÃÅaß  ÁÃ‘Ó¤      E   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/Files.php=  ÃÅa=  `öJu¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/DatabaseAbstract.php…  ÃÅa…  #0‰^¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/Settings/TLSchema.phpÏ  ÃÅaÏ  È_Ì¤      <   vendor/danog/madelineproto/src/danog/MadelineProto/Magic.phpˆT  ÃÅaˆT  ÂŸ¸¤      O   vendor/danog/madelineproto/src/danog/MadelineProto/SecretChats/SeqNoHandler.php_  ÃÅa_  Û´¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/SecretChats/AuthKeyHandler.phpHG  ÃÅaHG  )¤      Q   vendor/danog/madelineproto/src/danog/MadelineProto/SecretChats/MessageHandler.phpk2  ÃÅak2  ¯ZÂ—¤      R   vendor/danog/madelineproto/src/danog/MadelineProto/SecretChats/ResponseHandler.phpA  ÃÅaA  .¸çÃ¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Noop.php~  ÃÅa~  µûó¤      M   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/DialogHandler.phpb  ÃÅab  	F¤      E   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Start.php}  ÃÅa}  tÞý¤      E   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Login.phpï2  ÃÅaï2  ÜÁÔ„¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/TOS.php[  ÃÅa[  *ct³¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Ads.php[
  ÃÅa[
  4*¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Callback.php.  ÃÅa.  ìTTY¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Templates.phpò  ÃÅaò  MôÚ¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Button.php{  ÃÅa{  R
A8¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Webhook.phpÐ  ÃÅaÐ  ¹;gD¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Loop.phpy  ÃÅay  Ë6ïp¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/Wrappers/Events.phpk  ÃÅak  …� ¤      =   vendor/danog/madelineproto/src/danog/MadelineProto/Snitch.php`  ÃÅa`  4¼…Æ¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/GarbageCollector.phpI  ÃÅaI  eãž¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/SecurityException.php=  ÃÅa=  È‘	i¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/SettingsEmpty.php±   ÃÅa±   wèà¤      @   vendor/danog/madelineproto/src/danog/MadelineProto/PsrLogger.php‰  ÃÅa‰  Þæ\6¤      A   vendor/danog/madelineproto/src/danog/MadelineProto/Conversion.php¸F  ÃÅa¸F  &J¬Ó¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/AnnotationsBuilder.php[G  ÃÅa[G  fuÐ¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/TL/Exception.phpÚ  ÃÅaÚ  )n]š¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/TL/PrettyException.php  ÃÅa  zRp¤      C   vendor/danog/madelineproto/src/danog/MadelineProto/TL/TLMethods.phpH	  ÃÅaH	  .Þº5¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/TL/Types/Button.php½  ÃÅa½  µ>‡ü¤      E   vendor/danog/madelineproto/src/danog/MadelineProto/TL/Types/Bytes.phpM  ÃÅaM  ×�àb¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/TL/TLCallback.php³  ÃÅa³  ²H¬2¤      <   vendor/danog/madelineproto/src/danog/MadelineProto/TL/TL.phpÄ¹  ÃÅaÄ¹  ™Î{¤      B   vendor/danog/madelineproto/src/danog/MadelineProto/TL/TLParams.php=  ÃÅa=  ìÍð¤      H   vendor/danog/madelineproto/src/danog/MadelineProto/TL/TLConstructors.php�  ÃÅa�  F.F¤      P   vendor/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.phpõ#  ÃÅaõ#  š—D¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/Extension.php7!  ÃÅa7!  ˆu|i¤      K   vendor/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/BotAPI.phpŽˆ  ÃÅaŽˆ  Z�#x¤      N   vendor/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/Exception.phpø  ÃÅaø  h‹k¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/TD.php’"  ÃÅa’"  Š0s¤      F   vendor/danog/madelineproto/src/danog/MadelineProto/VoIP/AckHandler.php”  ÃÅa”  ¿�É!¤      D   vendor/danog/madelineproto/src/danog/MadelineProto/VoIP/Endpoint.php4  ÃÅa4  ¸ q–¤      J   vendor/danog/madelineproto/src/danog/MadelineProto/VoIP/AuthKeyHandler.phpàD  ÃÅaàD  ùÓ‡À¤      J   vendor/danog/madelineproto/src/danog/MadelineProto/VoIP/MessageHandler.php‰W  ÃÅa‰W  ¥îó§¤      I   vendor/danog/madelineproto/src/danog/MadelineProto/AbstractAPIFactory.phpŽ  ÃÅaŽ  îXµn¤      >   vendor/danog/madelineproto/src/danog/MadelineProto/MTProto.phpŒ ÃÅaŒ (¾>¤      G   vendor/danog/madelineproto/src/danog/MadelineProto/ContextConnector.phpÁ  ÃÅaÁ  ÖÇX¸¤      +   vendor/danog/madelineproto/src/polyfill.php,  ÃÅa,  ¤Á9¤      -   vendor/danog/madelineproto/src/BigIntegor.php´	  ÃÅa´	  _çäk¤      3   vendor/danog/madelineproto/src/YieldReturnValue.phpÈ  ÃÅaÈ  MÝdŸ¤      F   vendor/danog/madelineproto/examples/database-config-examples/redis.php  ÃÅa  á*¾¤      G   vendor/danog/madelineproto/examples/database-config-examples/memory.php#  ÃÅa#  mö¸¤      I   vendor/danog/madelineproto/examples/database-config-examples/postgres.phpd  ÃÅad  N‰·¤      F   vendor/danog/madelineproto/examples/database-config-examples/mysql.phph  ÃÅah  D�¤      =   vendor/danog/madelineproto/examples/pwrtelegram_debug_bot.php….  ÃÅa….  È»Ž+í      3   vendor/danog/madelineproto/examples/combinedBot.phpÎ  ÃÅaÎ  ©Õ¼í      6   vendor/danog/madelineproto/examples/botAllMessages.php°	  ÃÅa°	  ÷v€È¤      .   vendor/danog/madelineproto/examples/lua/td.phpc  ÃÅac  é¤éÚí      2   vendor/danog/madelineproto/examples/secret_bot.php¤  ÃÅa¤  ˜Þ¨7í      -   vendor/danog/madelineproto/examples/index.php  ÃÅa  ,Õ8ê¤      +   vendor/danog/madelineproto/examples/bot.phpK  ÃÅaK  a=÷òí      9   vendor/danog/madelineproto/examples/downloadRenameBot.php“$  ÃÅa“$  Èb�í      6   vendor/danog/madelineproto/___transpiledWithPhabel.php   ÃÅa   ÇóN¤      9   vendor/danog/madelineproto/vendor-bin/check/composer.jsonò   ÃÅaò    ª™¤      :   vendor/danog/madelineproto/.devcontainer/devcontainer.jsonÇ  ÃÅaÇ  ‹a¤      -   vendor/danog/madelineproto/tools/makephar.php�  ÃÅa�  ?ÚäAí      (   vendor/danog/madelineproto/tools/std.php‘  ÃÅa‘  `Gq�¤      /   vendor/danog/madelineproto/tools/translator.phpÐ  ÃÅaÐ  äjN¤      )   vendor/danog/madelineproto/tools/phar.phpu!  ÃÅau!  žìj*¤      +   vendor/danog/madelineproto/tools/static.php¸  ÃÅa¸  ‡å�ü¤      +   vendor/danog/madelineproto/tools/phpdoc.php^  ÃÅa^  ‡¼”¤      .   vendor/danog/madelineproto/tools/layerdiff.phpá  ÃÅaá  ¼C�¤      /   vendor/danog/madelineproto/tools/build_docs.phpG  ÃÅaG  ¯�Öí      <   vendor/danog/madelineproto/tools/build_docs/layerUpgrade.php  ÃÅa  	Ú¤      7   vendor/danog/madelineproto/tools/build_docs/schemas.phpË  ÃÅaË  r[Ó-¤      5   vendor/danog/madelineproto/tools/build_docs/merge.php"  ÃÅa"  +­OÔ¤      -   vendor/danog/madelineproto/tools/asyncify.phpé  ÃÅaé  ìÛë¤      -   vendor/danog/madelineproto/ton/toncustom.json  ÃÅa  ?Ð¤      @   vendor/danog/madelineproto/ton/ton-lite-client-test1.config.jsonõ  ÃÅaõ  t¢í¤      .   vendor/danog/madelineproto/ton/lite-client.phpc  ÃÅac  "¾*~¤      (   vendor/danog/madelineproto/composer.jsonH  ÃÅaH  KðÖ¤      $   vendor/danog/ipc/examples/server.php  ÃÅa  Â5+¤      $   vendor/danog/ipc/examples/client.phpO  ÃÅaO  sm/•¤         vendor/danog/ipc/composer.jsonÑ  ÃÅaÑ  .s÷s¤      .   vendor/danog/ipc/lib/Sync/ChannelledSocket.php   ÃÅa   jñCR¤      .   vendor/danog/ipc/lib/Sync/ChannelException.phpM   ÃÅaM   ¸›Ñ¤      $   vendor/danog/ipc/lib/Sync/Parcel.php£  ÃÅa£  8h©Ì¤      -   vendor/danog/ipc/lib/Sync/ChannelCloseReq.phpZ   ÃÅaZ   ðg{¤      -   vendor/danog/ipc/lib/Sync/ChannelCloseMsg.php=   ÃÅa=   ¨Ì„¤      2   vendor/danog/ipc/lib/Sync/SynchronizationError.phpM   ÃÅaM   EïO­¤      -   vendor/danog/ipc/lib/Sync/ChannelCloseAck.phpZ   ÃÅaZ   ‹ÛðC¤      %   vendor/danog/ipc/lib/Sync/Channel.phpÃ  ÃÅaÃ  �‘¤¨¤      (   vendor/danog/ipc/lib/Sync/PanicError.phpW  ÃÅaW  -Æe¤      +   vendor/danog/ipc/lib/Sync/ChannelParser.php~	  ÃÅa~	  J¹ÃÂ¤      4   vendor/danog/ipc/lib/Sync/SerializationException.phpS   ÃÅaS   Ù�(=¤      .   vendor/danog/ipc/lib/Sync/ChannelledStream.php®  ÃÅa®  ®³†7¤      "   vendor/danog/ipc/lib/IpcServer.phpÔ   ÃÅaÔ   êyÐ—¤      +   vendor/danog/ipc/lib/IpcServerException.phph  ÃÅah  ­îÝ¸¤      +   vendor/danog/ipc/lib/PendingAcceptError.phpÅ  ÃÅaÅ   "ni¤      "   vendor/danog/ipc/lib/functions.php  ÃÅa  Ýqˆ¤      !   vendor/danog/ipc/test/IpcTest.php	  ÃÅa	  »R´¤      )   vendor/danog/ipc/test/Fixtures/server.phpk  ÃÅak  Óþw¤      -   vendor/danog/ipc/test/Fixtures/echoServer.phpã  ÃÅaã  3)é>¤      $   vendor/danog/magicalserializer/a.phpL  ÃÅaL  á´<¤      :   vendor/danog/magicalserializer/src/danog/Serialization.phpv  ÃÅav  Œ×î¤      9   vendor/danog/magicalserializer/src/danog/Serializable.php%	  ÃÅa%	  �«J•¤      8   vendor/danog/magicalserializer/src/danog/PlaceHolder.phpè  ÃÅaè  MÞ´W¤      ,   vendor/danog/magicalserializer/composer.json  ÃÅa  ½Þ‡‡¤      $   vendor/danog/magicalserializer/b.phpý  ÃÅaý  ¿!¼ ¤      +   vendor/phabel/phabel/.php-cs-fixer.dist.php  ÃÅa  YÄw­¤      /   vendor/phabel/phabel/vendor-bundle/autoload.php¨   ÃÅa¨   ±pÏË¤      M   vendor/phabel/phabel/vendor-bundle/symfony/deprecation-contracts/function.phpD   ÃÅaD   +Œ q¤      S   vendor/phabel/phabel/vendor-bundle/symfony/deprecation-contracts/guard.function.phpŽ  ÃÅaŽ  $,:¤      A   vendor/phabel/phabel/vendor-bundle/symfony/process/PhpProcess.php·	  ÃÅa·	  êc'Î¤      J   vendor/phabel/phabel/vendor-bundle/symfony/process/PhpExecutableFinder.phpø	  ÃÅaø	  |€„¤      G   vendor/phabel/phabel/vendor-bundle/symfony/process/ExecutableFinder.phpÓ	  ÃÅaÓ	  P'ÈH¤      B   vendor/phabel/phabel/vendor-bundle/symfony/process/InputStream.phpF	  ÃÅaF	  ù–	L¤      W   vendor/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessFailedException.phpb  ÃÅab  :fôë¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessSignaledException.php  ÃÅa  »]ÁY¤      Q   vendor/phabel/phabel/vendor-bundle/symfony/process/Exception/RuntimeException.phpí  ÃÅaí  +¸�ˆ¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessTimedOutException.phpã  ÃÅaã  °oGò¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/process/Exception/InvalidArgumentException.phpü  ÃÅaü  	õ[Q¤      O   vendor/phabel/phabel/vendor-bundle/symfony/process/Exception/LogicException.phpÞ  ÃÅaÞ  t'ÓÒ¤      S   vendor/phabel/phabel/vendor-bundle/symfony/process/Exception/ExceptionInterface.phpÎ  ÃÅaÎ  ¡÷T÷¤      J   vendor/phabel/phabel/vendor-bundle/symfony/process/Pipes/AbstractPipes.phpü  ÃÅaü  ¦Îbœ¤      K   vendor/phabel/phabel/vendor-bundle/symfony/process/Pipes/PipesInterface.phpá  ÃÅaá  ¾¥vž¤      I   vendor/phabel/phabel/vendor-bundle/symfony/process/Pipes/WindowsPipes.php±  ÃÅa±  ˜Ýl¤      F   vendor/phabel/phabel/vendor-bundle/symfony/process/Pipes/UnixPipes.php  ÃÅa  ãÿó¤      >   vendor/phabel/phabel/vendor-bundle/symfony/process/Process.phpË  ÃÅaË  TØ?¤      C   vendor/phabel/phabel/vendor-bundle/symfony/process/ProcessUtils.phpN  ÃÅaN  <UÂa¤      R   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Normalizer.php¸%  ÃÅa¸%  Ä&úO¤      S   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/bootstrap80.phpÅ  ÃÅaÅ  Ãî¤      p   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalDecomposition.php\ˆ  ÃÅa\ˆ  Ò­-Ï¤      h   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Resources/unidata/combiningClass.phpo.  ÃÅao.  —7c¤      t   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Resources/unidata/compatibilityDecomposition.php”è  ÃÅa”è  ú0p¤      n   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Resources/unidata/canonicalComposition.php„=  ÃÅa„=  ¦2ÿê¤      b   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php“  ÃÅa“  ž^w§¤      W   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/guard.bootstrap.php!  ÃÅa!  =…‹¤      Q   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/composer.jsonC  ÃÅaC  ÍïÙ¤      Q   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/bootstrap.phpE   ÃÅaE   `48$¤      W   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php80/Resources/stubs/Attribute.php  ÃÅa  Le¹¤      a   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php2   ÃÅa2   yrû+¤      X   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php80/Resources/stubs/Stringable.php¤   ÃÅa¤   Ï0Èò¤      X   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php80/Resources/stubs/ValueError.php)   ÃÅa)   ×AÄ‘¤      C   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php80/Php80.phpq  ÃÅaq  N[ŽÜ¤      M   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php80/guard.bootstrap.php  ÃÅa  �jÿ ¤      G   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php80/composer.json=  ÃÅa=  Ïzû>¤      G   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php80/bootstrap.phpE   ÃÅaE   `48$¤      [   vendor/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceSubscriberInterface.phpŸ  ÃÅaŸ  u¤      T   vendor/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceLocatorTrait.php!  ÃÅa!  ŸkÞ¤      X   vendor/phabel/phabel/vendor-bundle/symfony/service-contracts/Test/ServiceLocatorTest.php7  ÃÅa7  @m`Œ¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceProviderInterface.php¾  ÃÅa¾  øsùÂ¤      S   vendor/phabel/phabel/vendor-bundle/symfony/service-contracts/Attribute/Required.php�  ÃÅa�  ¼GÊ.¤      \   vendor/phabel/phabel/vendor-bundle/symfony/service-contracts/Attribute/SubscribedService.phpY  ÃÅaY  lwôÝ¤      O   vendor/phabel/phabel/vendor-bundle/symfony/service-contracts/ResetInterface.php
  ÃÅa
  	é#¤      W   vendor/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceSubscriberTrait.phpv
  ÃÅav
  ÊMw—¤      [   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php73/Resources/stubs/JsonException.php  ÃÅa   ÈÙ¤      C   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php73/Php73.php“  ÃÅa“  Ù˜J¬¤      M   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php73/guard.bootstrap.php¡  ÃÅa¡  z�Fn¤      G   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php73/composer.jsonÜ  ÃÅaÜ  Tiú¤      G   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-php73/bootstrap.phpE   ÃÅaE   `48$¤      T   vendor/phabel/phabel/vendor-bundle/symfony/console/Command/DumpCompletionCommand.php}  ÃÅa}  ÍN¹ê¤      J   vendor/phabel/phabel/vendor-bundle/symfony/console/Command/LazyCommand.phpU  ÃÅaU  —Rs¤      J   vendor/phabel/phabel/vendor-bundle/symfony/console/Command/HelpCommand.php  ÃÅa  ~Ü4¤      F   vendor/phabel/phabel/vendor-bundle/symfony/console/Command/Command.phpÿO  ÃÅaÿO  ¶
ÍV¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/console/Command/SignalableCommandInterface.php·  ÃÅa·  öäì¤      L   vendor/phabel/phabel/vendor-bundle/symfony/console/Command/LockableTrait.phpÿ  ÃÅaÿ  ZÚA¤      J   vendor/phabel/phabel/vendor-bundle/symfony/console/Command/ListCommand.phpö  ÃÅaö  ‰W:‡¤      N   vendor/phabel/phabel/vendor-bundle/symfony/console/Command/CompleteCommand.phpã   ÃÅaã   P’w¤      <   vendor/phabel/phabel/vendor-bundle/symfony/console/Color.php$  ÃÅa$  ³1øÚ¤      R   vendor/phabel/phabel/vendor-bundle/symfony/console/EventListener/ErrorListener.php¦  ÃÅa¦  Ãï£¤      P   vendor/phabel/phabel/vendor-bundle/symfony/console/Resources/bin/hiddeninput.exe $  ÃÅa $  •�¥v¤      P   vendor/phabel/phabel/vendor-bundle/symfony/console/Descriptor/JsonDescriptor.php  ÃÅa  D©´¤      T   vendor/phabel/phabel/vendor-bundle/symfony/console/Descriptor/MarkdownDescriptor.php  ÃÅa  ß‡ëc¤      L   vendor/phabel/phabel/vendor-bundle/symfony/console/Descriptor/Descriptor.phpê  ÃÅaê  }`�¤      O   vendor/phabel/phabel/vendor-bundle/symfony/console/Descriptor/XmlDescriptor.phpš'  ÃÅaš'  ?‹É¤      U   vendor/phabel/phabel/vendor-bundle/symfony/console/Descriptor/DescriptorInterface.php\  ÃÅa\  ¦:§^¤      P   vendor/phabel/phabel/vendor-bundle/symfony/console/Descriptor/TextDescriptor.php 2  ÃÅa 2  Õš‚W¤      X   vendor/phabel/phabel/vendor-bundle/symfony/console/Descriptor/ApplicationDescription.phpZ  ÃÅaZ  ªo4î¤      B   vendor/phabel/phabel/vendor-bundle/symfony/console/Application.phpp¬  ÃÅap¬  zB`j¤      `   vendor/phabel/phabel/vendor-bundle/symfony/console/DependencyInjection/AddConsoleCommandPass.phpZ  ÃÅaZ  º:J¤      T   vendor/phabel/phabel/vendor-bundle/symfony/console/SignalRegistry/SignalRegistry.php¡  ÃÅa¡  Ô�ºþ¤      H   vendor/phabel/phabel/vendor-bundle/symfony/console/Style/OutputStyle.php\  ÃÅa\  9n6å¤      I   vendor/phabel/phabel/vendor-bundle/symfony/console/Style/SymfonyStyle.phpI:  ÃÅaI:  •Õ!(¤      K   vendor/phabel/phabel/vendor-bundle/symfony/console/Style/StyleInterface.phpg
  ÃÅag
  C:í«¤      K   vendor/phabel/phabel/vendor-bundle/symfony/console/Logger/ConsoleLogger.php§  ÃÅa§  _1e°¤      T   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleOutputInterface.phpY  ÃÅaY  Î8U¾¤      D   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/Output.phpL  ÃÅaL  ”©s¬¤      R   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleSectionOutput.php²  ÃÅa²  Î‘hÉ¤      L   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/BufferedOutput.php]  ÃÅa]  ÚmÿŠ¤      Q   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/TrimmedBufferOutput.php‘  ÃÅa‘  ”ÛŒb¤      M   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/OutputInterface.phpa  ÃÅaa  Î{Î¤      J   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/StreamOutput.phpY  ÃÅaY  ùX…®¤      H   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/NullOutput.php&	  ÃÅa&	  Ö´™8¤      K   vendor/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleOutput.php�  ÃÅa�  Géy¤      I   vendor/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleEvent.phpÉ  ÃÅaÉ  ,™FC¤      N   vendor/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleErrorEvent.php|  ÃÅa|  ZXŸ¤      O   vendor/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleSignalEvent.phpï  ÃÅaï  Ã—ì”¤      R   vendor/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleTerminateEvent.php—  ÃÅa—  §ì]¤      P   vendor/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleCommandEvent.phpì  ÃÅaì  èÁâ/¤      N   vendor/phabel/phabel/vendor-bundle/symfony/console/CI/GithubActionReporter.phpP  ÃÅaP  	d~�¤      J   vendor/phabel/phabel/vendor-bundle/symfony/console/Attribute/AsCommand.php  ÃÅa  ¹Pÿ¼¤      ?   vendor/phabel/phabel/vendor-bundle/symfony/console/Terminal.php¦  ÃÅa¦  Y=ˆ—¤      T   vendor/phabel/phabel/vendor-bundle/symfony/console/Question/ConfirmationQuestion.php  ÃÅa  pH!ç¤      H   vendor/phabel/phabel/vendor-bundle/symfony/console/Question/Question.php§  ÃÅa§  O½ž¤      N   vendor/phabel/phabel/vendor-bundle/symfony/console/Question/ChoiceQuestion.phpÖ  ÃÅaÖ  s.‰º¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/console/Exception/CommandNotFoundException.phpŸ  ÃÅaŸ  Ã^©c¤      Q   vendor/phabel/phabel/vendor-bundle/symfony/console/Exception/RuntimeException.phpº  ÃÅaº  ÎœgŒ¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/console/Exception/InvalidArgumentException.phpÊ  ÃÅaÊ  {i	m¤      [   vendor/phabel/phabel/vendor-bundle/symfony/console/Exception/NamespaceNotFoundException.phpæ  ÃÅaæ  €}“µ¤      V   vendor/phabel/phabel/vendor-bundle/symfony/console/Exception/MissingInputException.phpú  ÃÅaú  !Ë¤      W   vendor/phabel/phabel/vendor-bundle/symfony/console/Exception/InvalidOptionException.php  ÃÅa  œ2ÃÞ¤      O   vendor/phabel/phabel/vendor-bundle/symfony/console/Exception/LogicException.php¶  ÃÅa¶  Á“oð¤      S   vendor/phabel/phabel/vendor-bundle/symfony/console/Exception/ExceptionInterface.phpµ  ÃÅaµ  ®E ñ¤      I   vendor/phabel/phabel/vendor-bundle/symfony/console/Tester/TesterTrait.phpš  ÃÅaš  W	pó¤      K   vendor/phabel/phabel/vendor-bundle/symfony/console/Tester/CommandTester.php/	  ÃÅa/	  îû÷i¤      O   vendor/phabel/phabel/vendor-bundle/symfony/console/Tester/ApplicationTester.phpñ  ÃÅañ  U£(¤      \   vendor/phabel/phabel/vendor-bundle/symfony/console/Tester/Constraint/CommandIsSuccessful.php¹  ÃÅa¹  µ˜¤      U   vendor/phabel/phabel/vendor-bundle/symfony/console/Tester/CommandCompletionTester.phpK  ÃÅaK  œòÄß¤      O   vendor/phabel/phabel/vendor-bundle/symfony/console/SingleCommandApplication.php6  ÃÅa6  äòÁö¤      D   vendor/phabel/phabel/vendor-bundle/symfony/console/ConsoleEvents.php’  ÃÅa’  ~Òßõ¤      =   vendor/phabel/phabel/vendor-bundle/symfony/console/Cursor.php7  ÃÅa7  |^Y¤      ^   vendor/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyleInterface.phpa  ÃÅaa  @to¤      b   vendor/phabel/phabel/vendor-bundle/symfony/console/Formatter/WrappableOutputFormatterInterface.php¹  ÃÅa¹  6Ÿ¤      T   vendor/phabel/phabel/vendor-bundle/symfony/console/Formatter/NullOutputFormatter.phpi  ÃÅai  �X²¤      U   vendor/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyle.phpv  ÃÅav  �À€™¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterInterface.phpB  ÃÅaB  ªË¼¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/console/Formatter/NullOutputFormatterStyle.php°  ÃÅa°  .P¤      P   vendor/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatter.php»  ÃÅa»  5!;¤      Z   vendor/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyleStack.php.
  ÃÅa.
  s(¤      [   vendor/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/CommandLoaderInterface.phpp  ÃÅap  íæ€j¤      Y   vendor/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/FactoryCommandLoader.phpY  ÃÅaY  ·»»¤      [   vendor/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/ContainerCommandLoader.php  ÃÅa  �cXz¤      S   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/SymfonyQuestionHelper.php4  ÃÅa4  Éœÿ¤      L   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/TableSeparator.php6  ÃÅa6  ïÖb0¤      L   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/QuestionHelper.phplL  ÃÅalL  ôUà¥¤      K   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/ProcessHelper.php¬  ÃÅa¬  Ÿ$/+¤      D   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/Helper.php±  ÃÅa±  KpS¤      R   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/DebugFormatterHelper.phpm  ÃÅam  Ÿ‚òm¤      H   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/TableStyle.php0  ÃÅa0  l¸£Z¤      M   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/HelperInterface.php[  ÃÅa[  ‘¼¯è¤      N   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/InputAwareHelper.php  ÃÅa  #ÈY¤      I   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/ProgressBar.phpxJ  ÃÅaxJ  ™;æï¤      C   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/Table.phpúo  ÃÅaúo  ]Âm×¤      L   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/TableCellStyle.php�  ÃÅa�  %[S’¤      O   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/ProgressIndicator.php  ÃÅa  æ©ºJ¤      G   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/TableRows.php~  ÃÅa~  •£,¤      M   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/FormatterHelper.phpx	  ÃÅax	  .Y7S¤      G   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/HelperSet.phpH
  ÃÅaH
  E×µ”¤      N   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/DescriptorHelper.phpÝ	  ÃÅaÝ	  –,¤c¤      G   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/TableCell.php7  ÃÅa7  Áó8F¤      D   vendor/phabel/phabel/vendor-bundle/symfony/console/Helper/Dumper.phpf  ÃÅaf  5SÂº¤      ]   vendor/phabel/phabel/vendor-bundle/symfony/console/Completion/Output/BashCompletionOutput.php¨  ÃÅa¨  ›À“¤      b   vendor/phabel/phabel/vendor-bundle/symfony/console/Completion/Output/CompletionOutputInterface.phpý  ÃÅaý  @Ëä³¤      Q   vendor/phabel/phabel/vendor-bundle/symfony/console/Completion/CompletionInput.php{   ÃÅa{   ª8xÒ¤      L   vendor/phabel/phabel/vendor-bundle/symfony/console/Completion/Suggestion.phpý  ÃÅaý  LƒE¤      W   vendor/phabel/phabel/vendor-bundle/symfony/console/Completion/CompletionSuggestions.phpj  ÃÅaj  ÔªëB¤      J   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/InputArgument.phpD  ÃÅaD  3CUG¤      P   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/InputAwareInterface.phpF  ÃÅaF  XNè¤      U   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/StreamableInputInterface.phpx  ÃÅax  DŒx>¤      B   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/Input.phpA  ÃÅaA  vx÷ ¤      H   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/StringInput.php[	  ÃÅa[	  r¯Ï¤      K   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/InputInterface.phpO  ÃÅaO  !Ä�!¤      G   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/ArrayInput.phpý  ÃÅaý  ôçÕ9¤      L   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/InputDefinition.phpY.  ÃÅaY.  &ïo7¤      H   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/InputOption.phpR  ÃÅaR  F�hK¤      F   vendor/phabel/phabel/vendor-bundle/symfony/console/Input/ArgvInput.php2  ÃÅa2  ÉÄË»¤      J   vendor/phabel/phabel/vendor-bundle/symfony/string/Slugger/AsciiSlugger.php3  ÃÅa3  �ÿ¤      N   vendor/phabel/phabel/vendor-bundle/symfony/string/Slugger/SluggerInterface.phpä  ÃÅaä  ú[ ô¤      @   vendor/phabel/phabel/vendor-bundle/symfony/string/ByteString.php‹h  ÃÅa‹h  bú)î¤      O   vendor/phabel/phabel/vendor-bundle/symfony/string/Resources/guard.functions.phpœ  ÃÅaœ  >š ¤      X   vendor/phabel/phabel/vendor-bundle/symfony/string/Resources/data/wcswidth_table_zero.phpî  ÃÅaî  ì4÷ ¤      X   vendor/phabel/phabel/vendor-bundle/symfony/string/Resources/data/wcswidth_table_wide.phpÁ  ÃÅaÁ  –²)¤      I   vendor/phabel/phabel/vendor-bundle/symfony/string/Resources/functions.phpE   ÃÅaE   ÎØûñ¤      K   vendor/phabel/phabel/vendor-bundle/symfony/string/AbstractUnicodeString.phpŽ  ÃÅaŽ  Ö&°_¤      @   vendor/phabel/phabel/vendor-bundle/symfony/string/LazyString.phpä%  ÃÅaä%  �ª,¤      P   vendor/phabel/phabel/vendor-bundle/symfony/string/Exception/RuntimeException.php|  ÃÅa|  ÀnO¤      X   vendor/phabel/phabel/vendor-bundle/symfony/string/Exception/InvalidArgumentException.phpŒ  ÃÅaŒ  Åí`½¤      R   vendor/phabel/phabel/vendor-bundle/symfony/string/Exception/ExceptionInterface.php]  ÃÅa]  Òë\r¤      E   vendor/phabel/phabel/vendor-bundle/symfony/string/CodePointString.phpa5  ÃÅaa5  òÜ¤      D   vendor/phabel/phabel/vendor-bundle/symfony/string/AbstractString.phpÑŠ  ÃÅaÑŠ  �Â¨d¤      C   vendor/phabel/phabel/vendor-bundle/symfony/string/UnicodeString.php–L  ÃÅa–L  ×—Nà¤      O   vendor/phabel/phabel/vendor-bundle/symfony/string/Inflector/FrenchInflector.php  ÃÅa  ÉX6¤      R   vendor/phabel/phabel/vendor-bundle/symfony/string/Inflector/InflectorInterface.phpP  ÃÅaP  „‡}A¤      P   vendor/phabel/phabel/vendor-bundle/symfony/string/Inflector/EnglishInflector.phpX=  ÃÅaX=  ~
ò·¤      L   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/bootstrap80.phpWz  ÃÅaWz  @k’È¤      b   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.phpö  ÃÅaö  Ž37�¤      \   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/Resources/unidata/lowerCase.phpôT  ÃÅaôT  Ø–×¬¤      \   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/Resources/unidata/upperCase.php3[  ÃÅa3[  ©bñ—¤      I   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/Mbstring.php¿u  ÃÅa¿u  zÔáI¤      P   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/guard.bootstrap.php"  ÃÅa"  ±œŠ¤      J   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/composer.jsonì  ÃÅaì  ]ñ¤      J   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/bootstrap.phpE   ÃÅaE   `48$¤      Q   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/bootstrap80.phpš!  ÃÅaš!  šRyM¤      N   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/Grapheme.phpÿ&  ÃÅaÿ&  _�ê³¤      U   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/guard.bootstrap.php@
  ÃÅa@
  öNã"¤      O   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/composer.json   ÃÅa   p93¤      O   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/bootstrap.phpE   ÃÅaE   `48$¤      I   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/bootstrap80.phpt  ÃÅat  öÔç¤      M   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/guard.bootstrap.phpë  ÃÅaë  ’–;¤      C   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/Ctype.php‰  ÃÅa‰  Ã…K¤      G   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/composer.jsonØ  ÃÅaØ  ¸/:ß¤      G   vendor/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/bootstrap.phpE   ÃÅaE   `48$¤      Q   vendor/phabel/phabel/vendor-bundle/amphp/process/bin/windows/ProcessWrapper64.exe H ÃÅa H &Ó;‰¤      O   vendor/phabel/phabel/vendor-bundle/amphp/process/bin/windows/ProcessWrapper.exe 4 ÃÅa 4 %P§¤      H   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/guard.functions.php%  ÃÅa%  “ÉøL¤      O   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessStatus.php  ÃÅa  $k·W¤      O   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessHandle.php  ÃÅa  f#«¤      N   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Posix/Handle.phpÙ  ÃÅaÙ  …gÙ¤      N   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Posix/Runner.phpé   ÃÅaé   q‘é¤      Y   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/SocketConnector.phpÄ0  ÃÅaÄ0  1jð¤      ]   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/PendingSocketClient.phpI  ÃÅaI  ¼»¤      T   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/SignalCode.php|  ÃÅa|  `¨ñ¤      P   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/Handle.phpÚ  ÃÅaÚ  Þ�¤      Y   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/HandshakeStatus.phpÝ  ÃÅaÝ  bÕÛÁ¤      P   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/Runner.phpë  ÃÅaë  @KR¤      O   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessRunner.phpî  ÃÅaî  ¼nŒ¤      D   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/StatusError.phpQ   ÃÅaQ   QUû¤      L   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessOutputStream.phpÜ  ÃÅaÜ  ¨oïH¤      B   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/functions.phpE   ÃÅaE   ÎØûñ¤      @   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/Process.phpý  ÃÅaý  »>´a¤      K   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessInputStream.phpû  ÃÅaû  Ý™¤      I   vendor/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessException.phpZ   ÃÅaZ   ôXù£¤      W   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/BootstrapWorkerFactory.php•  ÃÅa•  o¶u¤      U   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureThrowable.phpÒ  ÃÅaÒ  Fn'©¤      N   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerFactory.php#  ÃÅa#  Fì»h¤      M   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/CallableTask.phpÁ  ÃÅaÁ  “?•¤      U   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureException.php	  ÃÅa	  ¼„L*¤      Q   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureError.php	  ÃÅa	  `r<¤      L   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/DefaultPool.php  ÃÅa  ó}¤      P   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/guard.functions.phpÞ  ÃÅaÞ  Àj*¤      P   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerException.phpa   ÃÅaa   %Ñë‚¤      Q   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/BasicEnvironment.php.  ÃÅa.  ÿ¤      M   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/Job.phpx  ÃÅax  #†ã¤      U   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskFailure.phpO  ÃÅaO  ~`™^¤      V   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/PooledWorker.phpv  ÃÅav  ÒØöö¤      W   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/WorkerProcess.phpt  ÃÅat  ö‹!N¤      X   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/worker-process.phpÇ  ÃÅaÇ  €›¿¤      T   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskResult.phpa  ÃÅaa  ¼Å“ô¤      U   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskSuccess.php6  ÃÅa6  åûJ¤      E   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Pool.php�  ÃÅa�  âÏ®¤      N   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskException.php�  ÃÅa�  o é^¤      M   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerThread.phpÖ  ÃÅaÖ  $4
Ë¤      L   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Environment.php(  ÃÅa(  )W|¯¤      K   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskRunner.phpW  ÃÅaW  –¦º¤      K   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskWorker.phpB  ÃÅaB  Sk
¤      J   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/functions.phpE   ÃÅaE   ÎØûñ¤      G   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Worker.php!  ÃÅa!  ’•Y«¤      N   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerProcess.phpñ  ÃÅañ  N
š¤      O   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerParallel.php§  ÃÅa§  ÓÝ¤      E   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Task.php¶  ÃÅa¶  0“þú¤      U   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/DefaultWorkerFactory.php´  ÃÅa´  æýëx¤      J   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskError.phpq  ÃÅaq  ¥R,¤      P   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ContextPanicError.php   ÃÅa   oS_·¤      T   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SharedMemoryException.phpj   ÃÅaj   }ëå:¤      J   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitFailure.phpp  ÃÅap  Qw€¤      J   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitSuccess.phpk  ÃÅak  ëò‰“¤      Q   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SharedMemoryParcel.phpL7  ÃÅaL7  ÷³Ð¤      N   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/guard.functions.phpí  ÃÅaí  Id˜Ä¤      O   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelledSocket.phpK  ÃÅaK  ‹…m8¤      N   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ParcelException.php_   ÃÅa_   pæ’s¤      O   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelException.php`   ÃÅa`   rm:•¤      E   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Parcel.phpÃ  ÃÅaÃ  P¼óÐ¤      U   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Internal/ParcelStorage.phpø  ÃÅaø  ŒÃª¤      S   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SynchronizationError.php`   ÃÅa`   §}ŠV¤      M   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ThreadedParcel.php
  ÃÅa
  ‚Æ¤      F   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Channel.php  ÃÅa  /	)¤      H   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/functions.phpE   ÃÅaE   ÎØûñ¤      I   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/PanicError.php•  ÃÅa•  t;)¤      L   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelParser.php9  ÃÅa9  ýµªB¤      I   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitResult.php4  ÃÅa4  7PŠ¤¤      O   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelledStream.phpa	  ÃÅaa	  EH
^¤      P   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/ContextFactory.php'  ÃÅa'  E"º¤      H   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Thread.phpn$  ÃÅan$  €“Œ¤      Q   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/guard.functions.phpe  ÃÅae   Ü¤      R   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/ContextException.phpc   ÃÅac   ŠÖÞ¤      U   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/ProcessHub.phpw  ÃÅaw  âò¤      Y   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/process-runner.php¢  ÃÅa¢  �¾¤      Q   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/Thread.php¿  ÃÅa¿  iÐ«‹¤      V   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/ParallelHub.phpÊ  ÃÅaÊ  ¼Z¡¤      M   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/StatusError.phpZ   ÃÅaZ   w	qµ¤      W   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/DefaultContextFactory.php<  ÃÅa<  ß™Ÿ¤¤      K   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/functions.phpE   ÃÅaE   ÎØûñ¤      I   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Process.phpì0  ÃÅaì0  öq„¤      J   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Parallel.phpª3  ÃÅaª3  ý±Á¤      I   vendor/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Context.php)  ÃÅa)  bÔ¤      <   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Emitter.php  ÃÅa  C¹¤      J   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/NullCancellationToken.phpÎ  ÃÅaÎ  su?4¤      <   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Success.phpð  ÃÅað   f¸¤      M   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/TimeoutCancellationToken.php  ÃÅa  k‚G¤      =   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Producer.phpø  ÃÅaø  ’úÔÆ¤      <   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Promise.php¢  ÃÅa¢  J<Fƒ¤      D   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/guard.functions.phpÍZ  ÃÅaÍZ  û ¤      I   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/Placeholder.phpÒ  ÃÅaÒ  hcwÔ¤      F   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/Producer.php¼  ÃÅa¼  òél€¤      M   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/guard.functions.phpµ  ÃÅaµ  ¸m:¤      L   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/PrivatePromise.phpK  ÃÅaK  9—˜¤      G   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/functions.phpE   ÃÅaE   ÎØûñ¤      M   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/PrivateIterator.phpž  ÃÅaž  CNã¤      M   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/ResolutionQueue.phpl  ÃÅal  ƒ—‚+¤      L   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/CancellationTokenSource.php  ÃÅa  ÖÏç¿¤      A   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Watcher.phpë  ÃÅaë  ÚÃ"¤      E   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/EventDriver.php>%  ÃÅa>%  0ŸvQ¤      @   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Driver.php`e  ÃÅa`e  0c@¤      G   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/DriverFactory.phpú  ÃÅaú  u¾”Ä¤      F   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/NativeDriver.phpo8  ÃÅao8  ëôºL¤      M   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Internal/TimerQueue.phpN  ÃÅaN  È?÷½¤      U   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/UnsupportedFeatureException.php  ÃÅa  ƒ«=¤      B   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/EvDriver.php/!  ÃÅa/!  ÷Ë5‡¤      B   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/UvDriver.php†(  ÃÅa†(  ±ðÙÿ¤      M   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/InvalidWatcherError.php   ÃÅa   N\‡Ã¤      G   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/TracingDriver.phpg  ÃÅag  mŠ!�¤      >   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Coroutine.php  ÃÅa  M ®Ð¤      F   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/CancellationToken.phpí  ÃÅaí  ­«Z¤      =   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Deferred.php:  ÃÅa:  3çQ^¤      <   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Failure.phpÁ  ÃÅaÁ  dÇì“¤      I   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/MultiReasonException.php   ÃÅa   ;ã›]¤      >   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/functions.phpE   ÃÅaE   ÎØûñ¤      F   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/InvalidYieldError.phpû  ÃÅaû  ‰¼à¤      N   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/CombinedCancellationToken.phpÞ  ÃÅaÞ  ¥gŒ)¤      E   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/TimeoutException.php|  ÃÅa|  gJË‹¤      9   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop.phplD  ÃÅalD  ¾+Ã¤      <   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Delayed.php�  ÃÅa�  )û¤      =   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Iterator.phpF  ÃÅaF  Zá?
¤      B   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/CallableMaker.php‰
  ÃÅa‰
  »?`Ë¤      G   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/CancelledException.phpx  ÃÅax  "ä	¤      @   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/LazyPromise.php¯  ÃÅa¯  HÎÿ�¤      ;   vendor/phabel/phabel/vendor-bundle/amphp/amp/lib/Struct.php²  ÃÅa²  ô6œ¤      O   vendor/phabel/phabel/vendor-bundle/amphp/serialization/src/NativeSerializer.php2  ÃÅa2  d>Eü¤      M   vendor/phabel/phabel/vendor-bundle/amphp/serialization/src/JsonSerializer.php…
  ÃÅa…
  ÁÙôs¤      N   vendor/phabel/phabel/vendor-bundle/amphp/serialization/src/guard.functions.phpk  ÃÅak  UÜ, ¤      I   vendor/phabel/phabel/vendor-bundle/amphp/serialization/src/Serializer.php¨  ÃÅa¨  ï}LÎ¤      T   vendor/phabel/phabel/vendor-bundle/amphp/serialization/src/CompressingSerializer.php  ÃÅa  D€óÍ¤      T   vendor/phabel/phabel/vendor-bundle/amphp/serialization/src/PassthroughSerializer.phpÐ  ÃÅaÐ  ­d’u¤      H   vendor/phabel/phabel/vendor-bundle/amphp/serialization/src/functions.phpE   ÃÅaE   ÎØûñ¤      U   vendor/phabel/phabel/vendor-bundle/amphp/serialization/src/SerializationException.phpf   ÃÅaf   áùù¤      ]   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64DecodingInputStream.phpˆ  ÃÅaˆ  la½¤      ^   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.phpC  ÃÅaC  D³&X¤      ^   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.phpL  ÃÅaL  "Ü6y¤      ]   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64EncodingInputStream.phpË  ÃÅaË  <Âä¤      K   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/IteratorStream.phpé  ÃÅaé  h#
¤      Q   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ResourceOutputStream.phpf*  ÃÅaf*  J†þ¤      I   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/OutputStream.php'  ÃÅa'  >þ,¤      M   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InputStreamChain.phpª  ÃÅaª  É¤      L   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/guard.functions.phpo  ÃÅao  :{õ›¤      D   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Message.phpZ  ÃÅaZ  _PF¤      H   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InputStream.php?  ÃÅa?  •Î¤      P   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ResourceInputStream.php,  ÃÅa,  i‘Hó¤      L   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ZlibInputStream.phpo  ÃÅao  ÕÇ*4¤      L   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/StreamException.php\   ÃÅa\   ä�ï¤      G   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/LineReader.php  ÃÅa  ±e{N¤      F   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/functions.phpE   ÃÅaE   ÎØûñ¤      L   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ClosedException.phpg   ÃÅag   &‹»+¤      D   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Payload.phpä	  ÃÅaä	  °DÕ_¤      M   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/PendingReadError.phpÔ  ÃÅaÔ  •4mî¤      M   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ZlibOutputStream.php[  ÃÅa[  Ã´æK¤      I   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/OutputBuffer.php  ÃÅa  ²,Ç*¤      K   vendor/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InMemoryStream.phpo  ÃÅao  Ú_¬¤      M   vendor/phabel/phabel/vendor-bundle/amphp/parser/lib/InvalidDelimiterError.php  ÃÅa  Á{â›¤      >   vendor/phabel/phabel/vendor-bundle/amphp/parser/lib/Parser.php–  ÃÅa–  –¹%ˆ¤      I   vendor/phabel/phabel/vendor-bundle/amphp/sync/composer-require-check.jsonû  ÃÅaû  *×ÀX¤      L   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/PrefixedKeyedSemaphore.php7  ÃÅa7  t®‚¤      I   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/LocalKeyedSemaphore.phpk  ÃÅak  ªú¬×¤      E   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/guard.functions.php�  ÃÅa�  ?¶Ã¤      ?   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/Semaphore.phpò  ÃÅaò  ‚ÉA¤      O   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/Internal/SemaphoreStorage.phpœ  ÃÅaœ  ÜS„F¤      K   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/Internal/MutexStorage.phpŸ  ÃÅaŸ  ®2Ÿ€¤      C   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/SyncException.phpT   ÃÅaT   Ç¤      X   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/ConcurrentIterator/guard.functions.php}  ÃÅa}  £õÀ^¤      R   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/ConcurrentIterator/functions.phpE   ÃÅaE   ÎØûñ¤      ;   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/Mutex.php½  ÃÅa½  Ï²jÙ¤      G   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/ThreadedSemaphore.phpÄ  ÃÅaÄ  9žø/¤      D   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/StaticKeyMutex.phpé  ÃÅaé  kAü¤      D   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/PosixSemaphore.php¬  ÃÅa¬  8ÇÍÏ¤      E   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/LocalKeyedMutex.php–  ÃÅa–  ªò'À¤      =   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/Barrier.php&  ÃÅa&  ú£«B¤      D   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/LocalSemaphore.php  ÃÅa  “DG ¤      H   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/PrefixedKeyedMutex.php  ÃÅa  ñ”Zº¤      C   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/ThreadedMutex.php¿  ÃÅa¿  1"Ë ¤      D   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/KeyedSemaphore.php8  ÃÅa8  ™7‰µ¤      ?   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/FileMutex.phpã  ÃÅaã  w¾b¤      :   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/Lock.phpÝ  ÃÅaÝ  ä™Ù¤      D   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/SemaphoreMutex.phpH  ÃÅaH  ¾R ¤      ?   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/functions.phpE   ÃÅaE   ÎØûñ¤      @   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/LocalMutex.phpó  ÃÅaó  Ñ½¾¤      @   vendor/phabel/phabel/vendor-bundle/amphp/sync/src/KeyedMutex.php  ÃÅa  ôDbS¤      L   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/tools/convertPhabel.phpt  ÃÅat  üáC¤      O   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/grammar/rebuildParsers.phpê  ÃÅaê  Ò‡û¤      I   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/grammar/phpyLang.phpS  ÃÅaS  �(�Ä¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/BuilderFactory.php2+  ÃÅa2+  �qS¤      R   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/JsonDecoder.phpÆ  ÃÅaÆ  C­V¤      \   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/PrettyPrinterAbstract.phpÝÜ  ÃÅaÝÜ  ¸Ë
¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ParserAbstract.php³š  ÃÅa³š  Dê×ƒ¤      L   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Error.php’  ÃÅa’  «¾Y¤      N   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder.phpÙ   ÃÅaÙ   h¥ÿ–¤      S   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeAbstract.phpÖ  ÃÅaÖ  7XM¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/Differ.phpT  ÃÅaT  å‰õö¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/DiffElem.phpS  ÃÅaS  §¨È<¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/TokenStream.php^#  ÃÅa^#  �u¼´¤      i   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php�  ÃÅa�  ÙËÎ¤      R   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Comment/Doc.php‚   ÃÅa‚   ,¤}b¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ConstExprEvaluationException.phpd   ÃÅad   I‘D!¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/BuilderHelpers.php2$  ÃÅa2$  1ëåU¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/PrettyPrinter/Standard.php$³  ÃÅa$³  µR©	¤      K   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node.php‡  ÃÅa‡  &‡ì`¤      Q   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeDumper.php•  ÃÅa•  öÿ,¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Declaration.php  ÃÅa  õ¬Á¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Param.php¸  ÃÅa¸  gh¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/EnumCase.php�  ÃÅa�  ¥Õ7¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/ClassConst.phpˆ  ÃÅaˆ  �Èïi¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Enum_.php¿  ÃÅa¿  ZíÑ¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Trait_.php÷  ÃÅa÷  R™I€¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/FunctionLike.php  ÃÅa  öƒÕ¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Function_.phpg  ÃÅag  [,‡¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Interface_.phpò	  ÃÅaò	  	Ës¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/TraitUse.php|  ÃÅa|  KšN}¤      S   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Use_.phpï  ÃÅaï  R„ü¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Namespace_.php]  ÃÅa]  ˆÒF ¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Class_.php  ÃÅa  Â%×,¤      a   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.phpÊ  ÃÅaÊ  «ÙD‚¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Property.php´  ÃÅa´  ç};6¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Method.php±  ÃÅa±  "Èº¤      R   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NameContext.php¯&  ÃÅa¯&  EIÑ¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/Emulative.phpÇ$  ÃÅaÇ$  ªüÓB¤      p   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php  ÃÅa  È¾r¤      t   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php'
  ÃÅa'
  ‚Ú´9¤      z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.phpñ  ÃÅañ  6¢S!¤      l   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php‚  ÃÅa‚  •)ÑB¤      m   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/AwaitTokenEmulator.php  ÃÅa  ›[ê¤      j   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.phpÛ
  ÃÅaÛ
  XìÒ¤      m   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php  ÃÅa  ÿ£:ë¤      j   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.phpü  ÃÅaü  {=˜¤      j   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.phpw  ÃÅaw  Åˆ¯ó¤      l   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php  ÃÅa  Ëu”{¤      h   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php¿  ÃÅa¿  fP#¤      p   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.phpu  ÃÅau  Ÿçš¤      t   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php�  ÃÅa�   žéU¤      p   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php<  ÃÅa<  oè#¹¤      N   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Comment.php³  ÃÅa³  ;0¶¾¤      Q   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeFinder.phpË	  ÃÅaË	  4á#«¤      _   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/VariadicPlaceholder.phpÒ  ÃÅaÒ  mF¤      \   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/IntersectionType.phpö  ÃÅaö  Ì²ú¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Identifier.php  ÃÅa  D2ž¶¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/ComplexType.php]  ÃÅa]  â»I©¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Closure.phpƒ
  ÃÅaƒ
  ‰u'ˆ¤      ^   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.phpÕ  ÃÅaÕ  uÎ“Ø¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php‰  ÃÅa‰  ¸è7¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.phpz  ÃÅaz  BBS[¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php‰  ÃÅa‰  üÞŒX¤      f   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.phpŽ  ÃÅaŽ  Qí¬ ¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.phpˆ  ÃÅaˆ  ç…¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php‡  ÃÅa‡  †j$¤      b   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php…  ÃÅa…  „C3{¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php†  ÃÅa†  sÏ¢«¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php‡  ÃÅa‡  zYH,¤      a   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php‚  ÃÅa‚  ì¸eo¤      `   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php€  ÃÅa€  @ì±¤      _   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php  ÃÅa  ³C0¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.phpˆ  ÃÅaˆ  Ä�S<¤      h   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php‘  ÃÅa‘  ŸZ­¤      b   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php…  ÃÅa…  BI¢¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php‡  ÃÅa‡  �”–¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.phpˆ  ÃÅaˆ  y>÷0¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php{  ÃÅa{  §éþ³¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.phpz  ÃÅaz  +†Ç¤¤      _   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php~  ÃÅa~  þ5¤      ^   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php|  ÃÅa|  öò×³¤      h   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php‘  ÃÅa‘  Æ0m¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.phpz  ÃÅaz  �t¬¾¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.phpˆ  ÃÅaˆ  ¦€û:¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.phpŠ  ÃÅaŠ  Œ;Oç¤      a   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php‚  ÃÅa‚  |O¨É¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.phpŠ  ÃÅaŠ  ØÃ7L¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PreInc.php»  ÃÅa»  Gš¯¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php€  ÃÅa€  ¤Ãâ�¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Error.php:  ÃÅa:  …N\Â¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Ternary.phpù  ÃÅaù  èrÚð¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Match_.phpç  ÃÅaç  ¬zøº¤      `   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php  ÃÅa  ÍùE¼¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/CallLike.php7  ÃÅa7  œB®>¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp.phpz  ÃÅaz  ˆá¤      f   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php  ÃÅa  m	ò¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.phpË  ÃÅaË  yrÙI¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Exit_.php(  ÃÅa(  �›¤      ^   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.phpê  ÃÅaê  CšP¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ShellExec.phpò  ÃÅaò  pC”¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php;  ÃÅa;  ¬ƒ‘¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php•  ÃÅa•  –úS_¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/YieldFrom.phpÙ  ÃÅaÙ  k×þ¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Eval_.php¼  ÃÅa¼  »-”œ¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/List_.php  ÃÅa  Í¯øj¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Print_.php¿  ÃÅa¿  £Y€¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php  ÃÅa  Ý�c¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php!  ÃÅa!  ®*¸E¤      b   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php  ÃÅa  "}¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php  ÃÅa  �
L¤      `   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php  ÃÅa  2IûÁ¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php!  ÃÅa!   Oí­¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php  ÃÅa  “/øZ¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php!  ÃÅa!  ØêÜ‡¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php  ÃÅa  Äòô¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php  ÃÅa  ›C-ø¤      _   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php  ÃÅa  u­Í–¤      ^   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php  ÃÅa  ÞB°¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php  ÃÅa  ßK6¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/StaticCall.php”  ÃÅa”  ¿F9—¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Array_.phpg  ÃÅag  Áïµ¤      \   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Instanceof_.phpŽ  ÃÅaŽ  §ªKˆ¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/FuncCall.phpF  ÃÅaF  Ñaˆè¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BooleanNot.phpË  ÃÅaË  |Yñ<¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php¢  ÃÅa¢  v°x‚¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PostDec.php¾  ÃÅa¾  ‹öwõ¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Throw_.phpÖ  ÃÅaÖ    ^¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Clone_.php¼  ÃÅa¼  ÀORd¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php÷  ÃÅa÷  ñS}R¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Isset_.phpÀ  ÃÅaÀ  ìÂ(¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignRef.phpq  ÃÅaq  óÍVÞ¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PostInc.php¾  ÃÅa¾  ^©jd¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Empty_.php¿  ÃÅa¿  1ªµÐ¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.phpÈ  ÃÅaÈ  Ø¬£s¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Include_.phpË  ÃÅaË  _Ïþº¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast.php[  ÃÅa[  N¤TÞ¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.phpË  ÃÅaË   Ÿjé¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php  ÃÅa  ;]'#¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php  ÃÅa  ?eG?¤      \   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php¼  ÃÅa¼  þ+qR¤      \   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php  ÃÅa  ÞÙ"£¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php
  ÃÅa
  CÃ•Õ¤      \   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php  ÃÅa  `i9¼¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php
  ÃÅa
  ·¾Š–¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/MethodCall.phpi  ÃÅai  R?¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/New_.phpÍ  ÃÅaÍ  R2Ã¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PreDec.php»  ÃÅa»  íÝÔÖ¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp.phpõ  ÃÅaõ  '™ê¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Assign.php@  ÃÅa@  ´§re¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Yield_.phpŒ  ÃÅaŒ  y�Ì¤      ^   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.phpr  ÃÅar  K�:Î¤      ^   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.phpy	  ÃÅay	  |Ç»B¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Variable.phpÅ  ÃÅaÅ  g3Š¤      O   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Arg.php`  ÃÅa`  ôÖB¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.phpŒ  ÃÅaŒ  ØPUÅ¤      b   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.phpˆ  ÃÅaˆ  b%&¤      g   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php•  ÃÅa•  xvÎ6¤      b   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.phpˆ  ÃÅaˆ  0ÒIO¤      a   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php…  ÃÅa…  -m¡L¤      h   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php˜  ÃÅa˜  ”Bú¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.phpŒ  ÃÅaŒ  ±7²”¤      d   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.phpŽ  ÃÅaŽ  o-Ïå¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php„  ÃÅa„  q”Û¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php  ÃÅa  ô¡`?¤      e   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php  ÃÅa  :Úð”¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/String_.phpá  ÃÅaá  OÖC¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/DNumber.phpÀ  ÃÅaÀ  ÝÌ°‡¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/LNumber.phpÆ	  ÃÅaÆ	  D6¤      Q   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Param.phpÀ  ÃÅaÀ  .Ì§¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/NullableType.phpù  ÃÅaù  XÝJØ¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/AttributeGroup.phpæ  ÃÅaæ  ˆ¸×p¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Attribute.phpq  ÃÅaq  6ÊL¬¤      P   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt.phpŸ   ÃÅaŸ   ”j2¤      P   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name.phpæ  ÃÅaæ  ûdi`¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/UnionType.php·  ÃÅa·  ’ÕÉÒ¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/FunctionLike.php  ÃÅa  HukÉ¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/MatchArm.phpï  ÃÅaï  '��¤      R   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Const_.phpü  ÃÅaü  X±?¤      P   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr.phpŸ   ÃÅaŸ   CÖÐŸ¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Do_.phpg  ÃÅag  �\}v¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Break_.phpö  ÃÅaö  §W+¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php.  ÃÅa.  �\äl¤      a   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.phpí  ÃÅaí  [{^¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/For_.phpÿ  ÃÅaÿ  q\„¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/EnumCase.phpÁ  ÃÅaÁ  ç³6-¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Declare_.php°  ÃÅa°  |›$¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/UseUse.phpe  ÃÅae  -¢Ê�¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php¿  ÃÅa¿  Œú@K¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Echo_.phpÑ  ÃÅaÑ  —ïäæ¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Label.php  ÃÅa  KØI³¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Enum_.php{  ÃÅa{  e7]–¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/StaticVar.phpÃ  ÃÅaÃ  �I6Ð¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Expression.php  ÃÅa  £ÌþB¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Trait_.phpû  ÃÅaû  ’g~
¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php+  ÃÅa+  My(¤      \   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.phpÏ  ÃÅaÏ  u™[¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Catch_.php…  ÃÅa…  _é’ä¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Static_.phpñ  ÃÅañ  .;œ¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Goto_.php?  ÃÅa?  …–w’¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php®  ÃÅa®  %Ö%»¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Switch_.php\  ÃÅa\  Ùj¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Return_.phpã  ÃÅaã  “�‚Ÿ¤      _   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php¨  ÃÅa¨  ñ¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Function_.php:
  ÃÅa:
  ”&»å¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Interface_.phpÁ  ÃÅaÁ  &
¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Const_.phpö  ÃÅaö  t“ÖT¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Throw_.phpÜ  ÃÅaÜ  ®Ú ¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php±  ÃÅa±  ¸#°v¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Unset_.phpÜ  ÃÅaÜ  †\'¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Nop.phpx  ÃÅax  8ƒe¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/While_.phpj  ÃÅaj  7’zÙ¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TryCatch.phpF  ÃÅaF  ©zn¤      U   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Use_.php�  ÃÅa�  Z"‘ƒ¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Continue_.php  ÃÅa  Û®í¢¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Namespace_.phpç  ÃÅaç  ªö}a¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/If_.phpü  ÃÅaü  ö;¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Global_.phpä  ÃÅaä  :Ê^š¤      W   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Class_.phpÆ  ÃÅaÆ  ˜ÒYŸ¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Finally_.phpÜ  ÃÅaÜ  Ž²ü¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php=  ÃÅa=  _‘w¤      n   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php_  ÃÅa_  5š³Ó¤      i   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php@  ÃÅa@  ë'r¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Case_.php‘  ÃÅa‘  s=š¤      [   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.phpÐ  ÃÅaÐ  …&´¤      c   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php$  ÃÅa$  ä{=!¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Else_.phpÔ  ÃÅaÔ  ˆ¾ø¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Property.php#
  ÃÅa#
  Å[^ö¤      X   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.phpn  ÃÅan   N]N¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name/Relative.phpõ  ÃÅaõ  ìÚ:¤      _   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name/FullyQualified.phpø  ÃÅaø  rOÜ“¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php   ÃÅa   Ê–‚?¤      R   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar.phpp   ÃÅap   âÙª¤      Y   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ConstExprEvaluator.php½%  ÃÅa½%  ³¬XG¤      ^   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler/Collecting.phpº  ÃÅaº  Œs‹¤      \   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler/Throwing.php¬  ÃÅa¬  2è¤      R   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor.phpC  ÃÅaC  ó�…Ö¤      L   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer.phpw[  ÃÅaw[  pÖ½¤¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Tokens.php+  ÃÅa+  Íƒä\¤      R   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Php7.php]A ÃÅa]A H Ðå¤      R   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Php5.phpê+ ÃÅaê+ 0òýñ¤      V   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Multiple.phpÜ  ÃÅaÜ  0~{¤      S   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler.php4  ÃÅa4  Ïnª†¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ParserFactory.phpä  ÃÅaä  ú\-¤      Z   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitorAbstract.php-  ÃÅa-  ö×À[¤      ]   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeTraverserInterface.php�  ÃÅa�  ÑÈì¤      T   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeTraverser.php†'  ÃÅa†'  ÚÂ6ï¤      f   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.phpY  ÃÅaY  óºÂ¤      j   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.phpÉ  ÃÅaÉ  õ³Ù~¤      _   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php+'  ÃÅa+'  ×Â¤      a   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.phpØ  ÃÅaØ  Qìi¤      a   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php8  ÃÅa8  ëjöß¤      h   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.phpà  ÃÅaà  É1MF¤      M   vendor/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser.php=  ÃÅa=  .[¤      T   vendor/phabel/phabel/vendor-bundle/psr/container/src/ContainerExceptionInterface.phpÄ   ÃÅaÄ   –óQ¤      K   vendor/phabel/phabel/vendor-bundle/psr/container/src/ContainerInterface.php  ÃÅa  ‘àáp¤      S   vendor/phabel/phabel/vendor-bundle/psr/container/src/NotFoundExceptionInterface.php«   ÃÅa«   sò«;¤      A   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/NullLogger.phpÎ  ÃÅaÎ  9=:¤      G   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerAwareTrait.phpž  ÃÅaž  Ü¢’¤      E   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/DummyTest.php  ÃÅa  ó*ˆò¤      F   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/TestLogger.php=  ÃÅa=  ÷Ð¤      O   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/LoggerInterfaceTest.phpÛ  ÃÅaÛ  zËje¤      E   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/AbstractLogger.phpü  ÃÅaü  ç�s¤      F   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerInterface.php  ÃÅa  Ÿ<Vm¤      ?   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LogLevel.phpF  ÃÅaF  ]sñ¤      B   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerTrait.php0  ÃÅa0  Qµ
¤      O   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/InvalidArgumentException.phpm   ÃÅam   þ ÷¤      K   vendor/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerAwareInterface.php6  ÃÅa6  *ATM¤      L   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Lexer/Lexer.phpU  ÃÅaU  Åý
¤      W   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/ParserException.php  ÃÅa  =èù¶¤      R   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/TypeParser.php×:  ÃÅa×:  å�<á¤      T   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/PhpDocParser.phpÌA  ÃÅaÌA  4±¤      W   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/ConstExprParser.phpð  ÃÅað  >eÌ�¤      U   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/TokenIterator.php  ÃÅa  •ÍÏ¤      a   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.phpJ  ÃÅaJ  $Q� ¤      c   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.phpì  ÃÅaì  Eƒòu¤      b   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.phpë  ÃÅaë  ú�­‹¤      e   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.phpÆ  ÃÅaÆ  g…7¤      \   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php¶   ÃÅa¶   „Ä:Ï¤      ]   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.phpù  ÃÅaù  ÷B~™¤      `   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.phpH  ÃÅaH   þ Ä¤      `   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.phpH  ÃÅaH  Aµ_è¤      a   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php>  ÃÅa>  ì)�û¤      a   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.phpê  ÃÅaê  ª*/¤¤      S   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/NodeAttributes.phpç  ÃÅaç  Zø}á¤      I   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Node.phpæ  ÃÅaæ  ú¨ûW¤      Z   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php`  ÃÅa`  ÖÜÄª¤      R   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php¬   ÃÅa¬   öaË=¤      \   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.phpŠ  ÃÅaŠ  &�z¤      X   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php
  ÃÅa
  2ÖzM¤      V   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php:  ÃÅa:  GIÅ{¤      \   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.phpÛ  ÃÅaÛ  QÜÅ¤      W   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.phpû  ÃÅaû  !ØJs¤      W   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.phpá  ÃÅaá  Êµ[T¤      c   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.phpÖ  ÃÅaÖ  ÖÀ³�¤      ^   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php  ÃÅa  Äê+ì¤      Z   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.phpã  ÃÅaã  ÿÝ5&¤      Y   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php™  ÃÅa™  ¸í÷‹¤      W   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.phpN  ÃÅaN  ’+¤      ]   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.phpÂ  ÃÅaÂ  1]—¤      b   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.phpÜ  ÃÅaÜ  X—æ”¤      `   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.phpo  ÃÅao  "1>Ä¤      [   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.phpe  ÃÅae  µWšª¤      ]   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php­  ÃÅa­  
.‰.¤      Z   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.phpà  ÃÅaà  šw¤      _   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php½  ÃÅa½  c$¥y¤      V   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.phpe  ÃÅae  éJW$¤      b   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php$  ÃÅa$  2µÝ÷¤      `   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.phpO  ÃÅaO  "¾‡¤      ^   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.phpÃ  ÃÅaÃ  y¡fÁ¤      a   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php™  ÃÅa™  Üšì;¤      \   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.phpÖ  ÃÅaÖ  šuü9¤      ^   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php¸   ÃÅa¸   ËxS ¤      g   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.phpÄ  ÃÅaÄ  ;¸�Ú¤      g   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php¢  ÃÅa¢  �Ì—Ä¤      _   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.phpÙ  ÃÅaÙ  µY¯$¤      ^   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.phpZ  ÃÅaZ  P¨öÿ¤      _   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.phpü  ÃÅaü  ƒ6†¤      [   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.phpµ   ÃÅaµ   g˜!û¤      ^   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.phpÃ  ÃÅaÃ  yu˜º¤      Y   vendor/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.phpi  ÃÅai  g«¤      )   vendor/phabel/phabel/src/EventHandler.php¬  ÃÅa¬  á	¥×¤      &   vendor/phabel/phabel/src/Traverser.php½o  ÃÅa½o  IËRŸ¤      )   vendor/phabel/phabel/src/ClassStorage.phps  ÃÅas  {i"’¤      2   vendor/phabel/phabel/src/EventHandlerInterface.phpÝ  ÃÅaÝ  °ÒŠ¤      #   vendor/phabel/phabel/src/phabel.phpa  ÃÅaa  ùHLf¤      %   vendor/phabel/phabel/src/RootNode.php·  ÃÅa·  §..¤      &   vendor/phabel/phabel/src/Tasks/Run.php}  ÃÅa}  ÏÖž(¤      '   vendor/phabel/phabel/src/Tasks/Init.php²  ÃÅa²  îá$¤      +   vendor/phabel/phabel/src/Tasks/Shutdown.phpÍ  ÃÅaÍ  »ñ–¤      ,   vendor/phabel/phabel/src/PluginInterface.php¶  ÃÅa¶  “ÝöÅ¤      &   vendor/phabel/phabel/src/Exception.php*  ÃÅa*  ¬`¯¤      (   vendor/phabel/phabel/src/guard.guard.phpm   ÃÅam   ¸UÝC¤      1   vendor/phabel/phabel/src/ClassStorage/Storage.phpC  ÃÅaC  ájSß¤      9   vendor/phabel/phabel/src/ClassStorage/FunctionStorage.phpO  ÃÅaO  õÄ’¤      1   vendor/phabel/phabel/src/ClassStorage/Builder.phpy  ÃÅay  ¼
3F¤      "   vendor/phabel/phabel/src/guard.phpA   ÃÅaA   ›ßÝ¤      )   vendor/phabel/phabel/src/PhpDocParser.phpQ  ÃÅaQ  zˆ,ó¤      1   vendor/phabel/phabel/src/ClassStorageProvider.phpß  ÃÅaß  ; &¤      8   vendor/phabel/phabel/src/Plugin/IssetExpressionFixer.php'  ÃÅa'  ™ïu:¤      5   vendor/phabel/phabel/src/Plugin/GeneratorDetector.phpS  ÃÅaS  ²Ên¤      0   vendor/phabel/phabel/src/Plugin/ListSplitter.php4  ÃÅa4  z~x_¤      1   vendor/phabel/phabel/src/Plugin/YieldDetector.phpn  ÃÅan  ™ŽTx¤      9   vendor/phabel/phabel/src/Plugin/NestedExpressionFixer.phpÙ  ÃÅaÙ  õ,/á¤      7   vendor/phabel/phabel/src/Plugin/PhabelTestGenerator.php;  ÃÅa;  Ý<—¤      3   vendor/phabel/phabel/src/Plugin/StmtExprWrapper.php  ÃÅa  G¤      4   vendor/phabel/phabel/src/Plugin/TypeHintReplacer.php,h  ÃÅa,h  ã‡þæ¤      7   vendor/phabel/phabel/src/Plugin/ReGeneratorInternal.php  ÃÅa  „Œb¤      /   vendor/phabel/phabel/src/Plugin/ReGenerator.php¸  ÃÅa¸  £çm¤      9   vendor/phabel/phabel/src/Plugin/StringConcatOptimizer.php[  ÃÅa[  ™z–‰¤      /   vendor/phabel/phabel/src/Plugin/Memoization.php:  ÃÅa:  ÈI½¤      ,   vendor/phabel/phabel/src/Plugin/NewFixer.php	  ÃÅa	  ó0¤      2   vendor/phabel/phabel/src/Plugin/VariableFinder.php(  ÃÅa(  ‡Ú1Ä¤      5   vendor/phabel/phabel/src/Plugin/ComposerSanitizer.php	  ÃÅa	  *AÛ�¤      ;   vendor/phabel/phabel/src/Plugin/ReGenerator/ReGenerator.php‚  ÃÅa‚  »RÃ ¤      6   vendor/phabel/phabel/src/Plugin/ClassStoragePlugin.php2  ÃÅa2  )14ç¤      ,   vendor/phabel/phabel/src/VariableContext.php  ÃÅa  Å“G—¤      )   vendor/phabel/phabel/src/Commands/Run.php  ÃÅa  ÇEÜŒ¤      1   vendor/phabel/phabel/src/Commands/BaseCommand.php[  ÃÅa[  lÕ¥ˆ¤      -   vendor/phabel/phabel/src/Commands/Publish.php²  ÃÅa²  v/W¤      #   vendor/phabel/phabel/src/Plugin.php¤  ÃÅa¤  ¬�Ðº¤      "   vendor/phabel/phabel/src/Tools.phpÏA  ÃÅaÏA  1r¡¤      2   vendor/phabel/phabel/src/Composer/EventHandler.php®  ÃÅa®  ÆÜ´Ë¤      ,   vendor/phabel/phabel/src/Composer/Plugin.php†  ÃÅa†  ³Ô^1¤      0   vendor/phabel/phabel/src/Composer/Repository.phpƒ  ÃÅaƒ  „‡¼Ÿ¤      1   vendor/phabel/phabel/src/Composer/Transformer.php:9  ÃÅa:9  »˜3÷¤      .   vendor/phabel/phabel/src/PluginGraph/Graph.phpZ  ÃÅaZ  ‹Ó¤      :   vendor/phabel/phabel/src/PluginGraph/CircularException.php‘  ÃÅa‘  ü"L¤      0   vendor/phabel/phabel/src/PluginGraph/Plugins.phpö  ÃÅaö  BTþ¤      6   vendor/phabel/phabel/src/PluginGraph/ResolvedGraph.php·  ÃÅa·  `Çâ"¤      -   vendor/phabel/phabel/src/PluginGraph/Node.phpJ)  ÃÅaJ)  ëŠ€È¤      7   vendor/phabel/phabel/src/PluginGraph/PackageContext.php¨  ÃÅa¨  ©˜»ÿ¤      6   vendor/phabel/phabel/src/PluginGraph/GraphInternal.phpw  ÃÅaw  "´ÀŽ¤      8   vendor/phabel/phabel/src/Target/Php71/VoidReturnType.phpˆ  ÃÅaˆ  ÐÞj½¤      1   vendor/phabel/phabel/src/Target/Php71/ListKey.php?  ÃÅa?  b fÒ¤      >   vendor/phabel/phabel/src/Target/Php71/IssetExpressionFixer.phph   ÃÅah   MÎ±}¤      ?   vendor/phabel/phabel/src/Target/Php71/MultipleCatchReplacer.php~  ÃÅa~  Õ»]¤      =   vendor/phabel/phabel/src/Target/Php71/ClosureFromCallable.php  ÃÅa  ’Q£¤      6   vendor/phabel/phabel/src/Target/Php71/NullableType.phpŠ  ÃÅaŠ  ¦¤      ?   vendor/phabel/phabel/src/Target/Php71/NestedExpressionFixer.phpi   ÃÅai   ô¦åb¤      Q   vendor/phabel/phabel/src/Target/Php71/ClassConstantVisibilityModifiersRemover.php  ÃÅa  ƒ†s¤      2   vendor/phabel/phabel/src/Target/Php71/Polyfill.php==  ÃÅa==  	aÏ¤      8   vendor/phabel/phabel/src/Target/Php71/ListExpression.phpT  ÃÅaT  Ô I³¤      3   vendor/phabel/phabel/src/Target/Php71/ArrayList.php0  ÃÅa0  Ó0ÒÒ¤      6   vendor/phabel/phabel/src/Target/Php71/IterableHint.phpn  ÃÅan  pÜð"¤      >   vendor/phabel/phabel/src/Target/Php74/TypeContracovariance.php¼  ÃÅa¼  çNã˜¤      >   vendor/phabel/phabel/src/Target/Php74/IssetExpressionFixer.phph   ÃÅah   COCJ¤      5   vendor/phabel/phabel/src/Target/Php74/ArrayUnpack.php  ÃÅa  ¤çÊƒ¤      ?   vendor/phabel/phabel/src/Target/Php74/NestedExpressionFixer.phpi   ÃÅai   ryj…¤      6   vendor/phabel/phabel/src/Target/Php74/Serializable.phpF  ÃÅaF  –ðÏù¤      2   vendor/phabel/phabel/src/Target/Php74/Polyfill.phpº  ÃÅaº  <cO`¤      7   vendor/phabel/phabel/src/Target/Php74/TypedProperty.php[  ÃÅa[  F†¼¦¤      S   vendor/phabel/phabel/src/Target/Php74/TypeContracovariance/TypeContracovariance.phpã	  ÃÅaã	  ©zðÃ¤      6   vendor/phabel/phabel/src/Target/Php74/ArrowClosure.phpÀ  ÃÅaÀ  „Ú¾Œ¤      @   vendor/phabel/phabel/src/Target/Php74/NullCoalesceAssignment.php8  ÃÅa8  |w]¬¤      '   vendor/phabel/phabel/src/Target/Php.php¬  ÃÅa¬  mê9P¤      >   vendor/phabel/phabel/src/Target/Php56/IssetExpressionFixer.phph   ÃÅah   ,Áô‰¤      ?   vendor/phabel/phabel/src/Target/Php56/NestedExpressionFixer.phpi   ÃÅai   5²¤X¤      >   vendor/phabel/phabel/src/Target/Php73/IssetExpressionFixer.phph   ÃÅah   ô0Ê¤      ?   vendor/phabel/phabel/src/Target/Php73/NestedExpressionFixer.phps  ÃÅas  á¢<¤      2   vendor/phabel/phabel/src/Target/Php73/Polyfill.phpÌ  ÃÅaÌ  #ö¡ò¤      7   vendor/phabel/phabel/src/Target/Php73/ListReference.phpN  ÃÅaN  Ò¢’¿¤      ,   vendor/phabel/phabel/src/Target/Polyfill.phpn  ÃÅan  oƒÓ¤      >   vendor/phabel/phabel/src/Target/Php72/IssetExpressionFixer.phph   ÃÅah   ˆLÏÙ¤      ?   vendor/phabel/phabel/src/Target/Php72/NestedExpressionFixer.phpi   ÃÅai   IîO‰¤      O   vendor/phabel/phabel/src/Target/Php72/TypeContravariance/TypeContravariance.php£  ÃÅa£  uªÊ½¤      <   vendor/phabel/phabel/src/Target/Php72/TypeContravariance.php¶  ÃÅa¶  pK©3¤      2   vendor/phabel/phabel/src/Target/Php72/Polyfill.phph  ÃÅah  éGÒ`¤      @   vendor/phabel/phabel/src/Target/Php72/ObjectTypeHintReplacer.phpv  ÃÅav  hhÍ¤      >   vendor/phabel/phabel/src/Target/Php80/ConstructorPromotion.php  ÃÅa  ®õP�¤      =   vendor/phabel/phabel/src/Target/Php80/NullSafeTransformer.php…  ÃÅa…  é.'O¤      >   vendor/phabel/phabel/src/Target/Php80/IssetExpressionFixer.php  ÃÅa  ,…Û^¤      ;   vendor/phabel/phabel/src/Target/Php80/ThrowExprReplacer.php   ÃÅa   õµ³¤      ?   vendor/phabel/phabel/src/Target/Php80/NestedExpressionFixer.phpÞK  ÃÅaÞK  Æ‹Vs¤      4   vendor/phabel/phabel/src/Target/Php80/CatchEmpty.phpŒ  ÃÅaŒ  B4hì¤      B   vendor/phabel/phabel/src/Target/Php80/StaticMixedFalseReplacer.php»  ÃÅa»  Š“¢„¤      :   vendor/phabel/phabel/src/Target/Php80/MatchTransformer.phpß  ÃÅaß  ™°¾"¤      2   vendor/phabel/phabel/src/Target/Php80/Polyfill.php¶–  ÃÅa¶–  b?PÃ¤      ;   vendor/phabel/phabel/src/Target/Php80/NullSafe/NullSafe.phpÍ  ÃÅaÍ  ØÅå»¤      3   vendor/phabel/phabel/src/Target/Php80/ClassName.php�  ÃÅa�  e7ø¤      ;   vendor/phabel/phabel/src/Target/Php80/UnionTypeStripper.phpl  ÃÅal  yKðé¤      >   vendor/phabel/phabel/src/Target/Php70/IssetExpressionFixer.phpúR  ÃÅaúR  _Pá�¤      C   vendor/phabel/phabel/src/Target/Php70/SpaceshipOperatorReplacer.php%  ÃÅa%  ÊÍ^¤      ?   vendor/phabel/phabel/src/Target/Php70/NestedExpressionFixer.php<�  ÃÅa<�  �¢À’¤      P   vendor/phabel/phabel/src/Target/Php70/AnonymousClass/AnonymousClassInterface.php×   ÃÅa×   ö1y¤      @   vendor/phabel/phabel/src/Target/Php70/AnonymousClassReplacer.phpÌ  ÃÅaÌ  §Fm¤      >   vendor/phabel/phabel/src/Target/Php70/ReservedNameReplacer.php  ÃÅa  ´2úî¤      9   vendor/phabel/phabel/src/Target/Php70/ScalarTypeHints.php‡  ÃÅa‡  ¬'m:¤      ;   vendor/phabel/phabel/src/Target/Php70/ThrowableReplacer.php4  ÃÅa4  [0¤      2   vendor/phabel/phabel/src/Target/Php70/Polyfill.phpz  ÃÅaz  Ùf¤      :   vendor/phabel/phabel/src/Target/Php70/GroupUseReplacer.php¥  ÃÅa¥  rÉ¨¯¤      L   vendor/phabel/phabel/src/Target/Php70/StrictTypesDeclareStatementRemover.php�  ÃÅa�  /¬“È¤      =   vendor/phabel/phabel/src/Target/Php70/DefineArrayReplacer.phpþ  ÃÅaþ  CÂˆ¦¤      L   vendor/phabel/phabel/src/Target/Php70/NullCoalesce/DisallowedExpressions.php  ÃÅa  ã9¤      >   vendor/phabel/phabel/src/Target/Php70/NullCoalesceReplacer.phpm  ÃÅam  i¬H¤      9   vendor/phabel/phabel/src/Target/Php70/ReturnTypeHints.phpk  ÃÅak  †<Ã‘¤      $   vendor/phabel/phabel/src/Version.phpn  ÃÅan  ‘C£¤      (   vendor/phabel/phabel/src/PluginCache.php�  ÃÅa�  8!r�¤      4   vendor/phabel/phabel/src/UnresolvedNameException.phpä   ÃÅaä   ¯�Ñ)¤      -   vendor/phabel/phabel/src/Cli/EventHandler.phpT  ÃÅaT  Ci2û¤      4   vendor/phabel/phabel/src/Cli/SimpleConsoleLogger.phps  ÃÅas  IƒÙ¤      *   vendor/phabel/phabel/src/Cli/Formatter.phpQ  ÃÅaQ  8$ë'¤      $   vendor/phabel/phabel/src/Context.phpº6  ÃÅaº6  „ÒÚ¤      -   vendor/phabel/phabel/src/ExceptionWrapper.php
  ÃÅa
  tÌ}¤      3   vendor/phabel/phabel/vendor-bin/check/composer.json  ÃÅa  ÞÙæU¤      "   vendor/phabel/phabel/tools/tag.phpÆ  ÃÅaÆ  mWIb¤      *   vendor/phabel/phabel/tools/typeHintGen.php  ÃÅa  ;t¤      *   vendor/phabel/phabel/tools/testExprGen.php£
  ÃÅa£
  ³¨„¤      #   vendor/phabel/phabel/tools/dump.php  ÃÅa  ¢LÂA¤      &   vendor/phabel/phabel/tools/exprGen.php^B  ÃÅa^B  <—Bo¤      ,   vendor/phabel/phabel/tools/convertPhabel.php¶"  ÃÅa¶"  KŒr¤      &   vendor/phabel/phabel/tools/testGen.php9  ÃÅa9  èTí¤      (   vendor/phabel/phabel/tools/ci/matrix.phpS  ÃÅaS  ÄQ*‘¤      /   vendor/phabel/phabel/tools/ci/coverageMerge.php_  ÃÅa_  [ÔçÛ¤      *   vendor/phabel/phabel/tools/ci/versions.php$   ÃÅa$   g£)&¤      -   vendor/phabel/phabel/tools/ci/prepareDeps.php4  ÃÅa4  ”,¤      +   vendor/phabel/phabel/tools/ci/functions.phpÍ   ÃÅaÍ   Øp!ë¤      "   vendor/phabel/phabel/composer.json[  ÃÅa[  iÃn2¤      #   vendor/phabel/phabel/scoper.inc.phpz  ÃÅaz  €‹©¤      S   vendor/phabel-transpiler74.daverandom/libdns/src/Encoder/EncodingContextFactory.php  ÃÅa  Áe¬¤      D   vendor/phabel-transpiler74.daverandom/libdns/src/Encoder/Encoder.php.  ÃÅa.  çõ!Ì¤      L   vendor/phabel-transpiler74.daverandom/libdns/src/Encoder/EncodingContext.php«  ÃÅa«  Š”Ÿ¤      K   vendor/phabel-transpiler74.daverandom/libdns/src/Encoder/EncoderFactory.php"  ÃÅa"  í�I
¤      L   vendor/phabel-transpiler74.daverandom/libdns/src/Decoder/DecodingContext.phpû  ÃÅaû  ‘‡b5¤      K   vendor/phabel-transpiler74.daverandom/libdns/src/Decoder/DecoderFactory.phpV  ÃÅaV  \|j¤      S   vendor/phabel-transpiler74.daverandom/libdns/src/Decoder/DecodingContextFactory.php´  ÃÅa´  ö¥‹µ¤      D   vendor/phabel-transpiler74.daverandom/libdns/src/Decoder/Decoder.php½K  ÃÅa½K  bÀRk¤      R   vendor/phabel-transpiler74.daverandom/libdns/src/Messages/MessageResponseCodes.php  ÃÅa  »âÉè¤      E   vendor/phabel-transpiler74.daverandom/libdns/src/Messages/Message.phpW  ÃÅaW   t—C¤      J   vendor/phabel-transpiler74.daverandom/libdns/src/Messages/MessageTypes.php™  ÃÅa™  tãGl¤      L   vendor/phabel-transpiler74.daverandom/libdns/src/Messages/MessageFactory.php‡  ÃÅa‡  =ÐC¤      L   vendor/phabel-transpiler74.daverandom/libdns/src/Messages/MessageOpCodes.php±  ÃÅa±  Â�Ÿ¤      @   vendor/phabel-transpiler74.daverandom/libdns/src/Enumeration.phpë  ÃÅaë  jÉ	¤      >   vendor/phabel-transpiler74.daverandom/libdns/src/functions.php  ÃÅa  ×ÀÑ‘¤      M   vendor/phabel-transpiler74.daverandom/libdns/src/Records/ResourceQClasses.php€  ÃÅa€  ô´>�¤      H   vendor/phabel-transpiler74.daverandom/libdns/src/Records/RecordTypes.php–  ÃÅa–  ðC;¤      S   vendor/phabel-transpiler74.daverandom/libdns/src/Records/ResourceBuilderFactory.php_  ÃÅa_  •ÊåÓ¤      M   vendor/phabel-transpiler74.daverandom/libdns/src/Records/RecordCollection.phpö  ÃÅaö  rÒ`S¤      E   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Resource.php   ÃÅa   
XÝÙ¤      T   vendor/phabel-transpiler74.daverandom/libdns/src/Records/RecordCollectionFactory.php³  ÃÅa³  ¼|k¤      B   vendor/phabel-transpiler74.daverandom/libdns/src/Records/RData.php  ÃÅa  RI£˜¤      L   vendor/phabel-transpiler74.daverandom/libdns/src/Records/ResourceClasses.phpÇ  ÃÅaÇ  Oè¤      L   vendor/phabel-transpiler74.daverandom/libdns/src/Records/ResourceFactory.php¡  ÃÅa¡  Ä �À¤      I   vendor/phabel-transpiler74.daverandom/libdns/src/Records/RDataFactory.phpn  ÃÅan  ¥HVº¤      L   vendor/phabel-transpiler74.daverandom/libdns/src/Records/ResourceBuilder.phpŸ  ÃÅaŸ  Z ¤      \   vendor/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/FieldDefinition.phpF  ÃÅaF  B«—·¤      [   vendor/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinition.php   ÃÅa   pÂQ«¤      b   vendor/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionManager.phpû%  ÃÅaû%  ùŽ?›¤      b   vendor/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionFactory.phpc  ÃÅac  èI+¤      i   vendor/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionManagerFactory.phpš  ÃÅaš  ®§‰P¤      c   vendor/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/FieldDefinitionFactory.phpI  ÃÅaI  ‡±æ¤      J   vendor/phabel-transpiler74.daverandom/libdns/src/Records/ResourceTypes.php5  ÃÅa5  i“[¤      L   vendor/phabel-transpiler74.daverandom/libdns/src/Records/QuestionFactory.phpG  ÃÅaG  ëÚD‹¤      H   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/Types.phpn  ÃÅan  þ�³Ò¤      N   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/IPv4Address.phpŒ	  ÃÅaŒ	  p{Õ¤¤      G   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/Char.phpî  ÃÅaî  GçÅ¼¤      I   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/BitMap.phpŸ  ÃÅaŸ  0*V¤      N   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/IPv6Address.php½  ÃÅa½  Am¡¤      G   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/Type.php¿  ÃÅa¿  ì´)Û¤      N   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/TypeFactory.phpš
  ÃÅaš
  —$Ä´¤      R   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/CharacterString.phpY  ÃÅaY  ç¯²¤      H   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/Short.php
  ÃÅa
  %—¤      K   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/Anything.php\  ÃÅa\  �öm›¤      G   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/Long.php  ÃÅa  T=ù¤      M   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/DomainName.php+  ÃÅa+  G®ªí¤      N   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Types/TypeBuilder.phpš  ÃÅaš  }å×±¤      K   vendor/phabel-transpiler74.daverandom/libdns/src/Records/ResourceQTypes.php¾  ÃÅa¾  :›¤      I   vendor/phabel-transpiler74.daverandom/libdns/src/Records/RDataBuilder.phpn  ÃÅan  <õÐ¤      E   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Question.phpÄ  ÃÅaÄ  4T¤      C   vendor/phabel-transpiler74.daverandom/libdns/src/Records/Record.php	  ÃÅa	  ;=¼¹¤      J   vendor/phabel-transpiler74.daverandom/libdns/src/Packets/PacketFactory.phpù  ÃÅaù  ÕÀ¶<¤      C   vendor/phabel-transpiler74.daverandom/libdns/src/Packets/Packet.php7  ÃÅa7  ØEEÿ¤      J   vendor/phabel-transpiler74.daverandom/libdns/src/Packets/LabelRegistry.phpH  ÃÅaH  Œö¤      B   vendor/phabel-transpiler74.daverandom/libdns/examples/autoload.phpG  ÃÅaG  wNeà¤      @   vendor/phabel-transpiler74.daverandom/libdns/examples/AQuery.phpÊ  ÃÅaÊ  BÁ\|¤      B   vendor/phabel-transpiler74.daverandom/libdns/examples/SOAQuery.php]
  ÃÅa]
  “šMÚ¤      I   vendor/phabel-transpiler74.daverandom/libdns/tools/autoload_generator.php&
  ÃÅa&
    Ùì¤      :   vendor/phabel-transpiler74.daverandom/libdns/composer.jsonþ  ÃÅaþ  xeÎz¤      2   vendor/phabel-transpiler74.league/uri/src/Http.phpq  ÃÅaq  ‰$WÏ¤      5   vendor/phabel-transpiler74.league/uri/src/UriInfo.php'  ÃÅa'  FÙ8¤      9   vendor/phabel-transpiler74.league/uri/src/UriResolver.phpÇ*  ÃÅaÇ*  a1Úñ¤      1   vendor/phabel-transpiler74.league/uri/src/Uri.php –  ÃÅa –  [rŒ¤      Q   vendor/phabel-transpiler74.league/uri/src/Exceptions/TemplateCanNotBeExpanded.phpu  ÃÅau  ›ÐC&¤      D   vendor/phabel-transpiler74.league/uri/src/UriTemplate/Expression.phpW(  ÃÅaW(  ñc#†¤      F   vendor/phabel-transpiler74.league/uri/src/UriTemplate/VarSpecifier.php™
  ÃÅa™
  �qé0¤      E   vendor/phabel-transpiler74.league/uri/src/UriTemplate/VariableBag.phpS  ÃÅaS  ^Ü ¤      B   vendor/phabel-transpiler74.league/uri/src/UriTemplate/Template.php™  ÃÅa™  =™¨¤      7   vendor/phabel-transpiler74.league/uri/src/UriString.php:  ÃÅa:  5§V¤      9   vendor/phabel-transpiler74.league/uri/src/HttpFactory.php=  ÃÅa=  Z�¤      9   vendor/phabel-transpiler74.league/uri/src/UriTemplate.phpê  ÃÅaê  ³®c¤      7   vendor/phabel-transpiler74.league/uri/.php-cs-fixer.php;  ÃÅa;  .†€¤      3   vendor/phabel-transpiler74.league/uri/composer.json$  ÃÅa$  §²!¤      F   vendor/phabel-transpiler74.league/uri-parser/src/MissingIdnSupport.phpú  ÃÅaú  ¹%>¤      >   vendor/phabel-transpiler74.league/uri-parser/src/Exception.php‘	  ÃÅa‘	  OÀ]¤      >   vendor/phabel-transpiler74.league/uri-parser/src/functions.php  ÃÅa  êIuò¤      F   vendor/phabel-transpiler74.league/uri-parser/src/functions_include.phpõ  ÃÅaõ  [iœ¤      ;   vendor/phabel-transpiler74.league/uri-parser/src/Parser.phpZ  ÃÅaZ  „<üL¤      :   vendor/phabel-transpiler74.league/uri-parser/composer.json>  ÃÅa>  Ò'¤      F   vendor/phabel-transpiler74.league/uri-interfaces/src/Idna/IdnaInfo.php[  ÃÅa[  JYùþ¤      B   vendor/phabel-transpiler74.league/uri-interfaces/src/Idna/Idna.php4  ÃÅa4  ¢D{ñ¤      Z   vendor/phabel-transpiler74.league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php«  ÃÅa«  GA\Ã¤      O   vendor/phabel-transpiler74.league/uri-interfaces/src/Exceptions/SyntaxError.php¨  ÃÅa¨  |cÔú¤      U   vendor/phabel-transpiler74.league/uri-interfaces/src/Exceptions/IdnSupportMissing.php¦  ÃÅa¦  ª%¥¤      X   vendor/phabel-transpiler74.league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php”  ÃÅa”  ¹�h?¤      V   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/DomainHostInterface.phpý
  ÃÅaý
  ¥�£.¤      P   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/PortInterface.phpÕ  ÃÅaÕ  Ù_”¤      O   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriInterface.php'  ÃÅa'  6ùI¤      T   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/UserInfoInterface.phpÖ  ÃÅaÖ  õ_Ê¤      O   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriException.phpl  ÃÅal  ³Ì]¤      X   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriComponentInterface.phpr  ÃÅar  S•¦g¤      T   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/DataPathInterface.phpw
  ÃÅaw
  ’ò—¤      U   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/AuthorityInterface.php
  ÃÅa
  ªÖî½¤      R   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/IpHostInterface.phpÖ  ÃÅaÖ  ›3½¤      P   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/HostInterface.phpZ  ÃÅaZ  ¾ö¥o¤      Y   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/SegmentedPathInterface.php  ÃÅa  i¤TÆ¤      Q   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/QueryInterface.phpá  ÃÅaá  ]}èä¤      T   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/FragmentInterface.phpÌ  ÃÅaÌ  qIQ¸¤      P   vendor/phabel-transpiler74.league/uri-interfaces/src/Contracts/PathInterface.php£
  ÃÅa£
  ©�Rª¤      >   vendor/phabel-transpiler74.league/uri-interfaces/composer.json   ÃÅa   ›Ôm‡¤      G   vendor/phabel-transpiler74.paragonie/random_compat/other/build_phar.php  ÃÅa  ñó¤      E   vendor/phabel-transpiler74.paragonie/random_compat/psalm-autoload.phpå   ÃÅaå   [âÏE¤      @   vendor/phabel-transpiler74.paragonie/random_compat/composer.jsonf  ÃÅaf  P|*�¤      A   vendor/phabel-transpiler74.paragonie/random_compat/lib/random.php.  ÃÅa.  ò¹û¤      J   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Base32.phpÓ6  ÃÅaÓ6  �òÇò¤      G   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Hex.phpt  ÃÅat  -ÆL¤      R   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64DotSlash.php“  ÃÅa“  á¤Fž¤      L   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Encoding.php\  ÃÅa\  N2~µ¤      M   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Base32Hex.php  ÃÅa  8¬U¤      Q   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64UrlSafe.phpE  ÃÅaE  (Ù»ã¤      T   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/EncoderInterface.php°  ÃÅa°  ¦–ò¤      J   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64.phpN   ÃÅaN   5sìñ¤      Y   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php¢
  ÃÅa¢
  'o©¤      K   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/RFC4648.php�  ÃÅa�  'êm`¤      J   vendor/phabel-transpiler74.paragonie/constant_time_encoding/src/Binary.phpK
  ÃÅaK
  ýZ%Ã¤      I   vendor/phabel-transpiler74.paragonie/constant_time_encoding/composer.jsonÐ  ÃÅaÐ  ½îHÞ¤      (   vendor/kelunik/certificate/composer.jsonS  ÃÅaS  RÚØñ¤      *   vendor/kelunik/certificate/lib/Profile.phpµ  ÃÅaµ  h¦Š;¤      >   vendor/kelunik/certificate/lib/InvalidCertificateException.php_   ÃÅa_   YD�¤      .   vendor/kelunik/certificate/lib/Certificate.phpÔ  ÃÅaÔ  uÁ£¨¤      =   vendor/kelunik/certificate/lib/FieldNotSupportedException.php^   ÃÅa^   p3�l¤      3   vendor/paragonie/random_compat/other/build_phar.php  ÃÅa  ñó¤      1   vendor/paragonie/random_compat/psalm-autoload.phpå   ÃÅaå   [âÏE¤      ,   vendor/paragonie/random_compat/composer.jsonf  ÃÅaf  P|*�¤      -   vendor/paragonie/random_compat/lib/random.php.  ÃÅa.  ò¹û¤      6   vendor/paragonie/constant_time_encoding/src/Base32.phpÓ6  ÃÅaÓ6  �òÇò¤      3   vendor/paragonie/constant_time_encoding/src/Hex.phpt  ÃÅat  -ÆL¤      >   vendor/paragonie/constant_time_encoding/src/Base64DotSlash.php“  ÃÅa“  á¤Fž¤      8   vendor/paragonie/constant_time_encoding/src/Encoding.php\  ÃÅa\  N2~µ¤      9   vendor/paragonie/constant_time_encoding/src/Base32Hex.php  ÃÅa  8¬U¤      =   vendor/paragonie/constant_time_encoding/src/Base64UrlSafe.phpE  ÃÅaE  (Ù»ã¤      @   vendor/paragonie/constant_time_encoding/src/EncoderInterface.php°  ÃÅa°  ¦–ò¤      6   vendor/paragonie/constant_time_encoding/src/Base64.phpN   ÃÅaN   5sìñ¤      E   vendor/paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php¢
  ÃÅa¢
  'o©¤      7   vendor/paragonie/constant_time_encoding/src/RFC4648.php�  ÃÅa�  'êm`¤      6   vendor/paragonie/constant_time_encoding/src/Binary.phpK
  ÃÅaK
  ýZ%Ã¤      5   vendor/paragonie/constant_time_encoding/composer.jsonÐ  ÃÅaÐ  ½îHÞ¤      (   vendor/phpseclib/phpseclib/composer.jsonï  ÃÅaï  Ù×Ü¤      2   vendor/phpseclib/phpseclib/phpseclib/Crypt/AES.php  ÃÅa  $²à¤      3   vendor/phpseclib/phpseclib/phpseclib/Crypt/Hash.php|¯  ÃÅa|¯  äúJ¤      1   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC.phpÅ2  ÃÅaÅ2  }›�¤      2   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA.php:l  ÃÅa:l  pÎ X¤      2   vendor/phpseclib/phpseclib/phpseclib/Crypt/RC2.php„Q  ÃÅa„Q  ¼ãâj¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.phpÜ  ÃÅaÜ  ®1œJ¤      E   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.phpÆ  ÃÅaÆ  $8Ÿ¤      E   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php:  ÃÅa:  ½ÂÚ%¤      E   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php  ÃÅa  {é¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/XML.phpà  ÃÅaà  –Y2¤      G   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.phpã  ÃÅaã  [BN¡¤      F   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.phph  ÃÅah  ÿ×]¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/Raw.php6  ÃÅa6  Lj˜È¤      =   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.phpA  ÃÅaA  oƒû�¤      <   vendor/phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php¦=  ÃÅa¦=  w ¤      >   vendor/phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.phpG  ÃÅaG  ;é -¤      E   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.phpâ  ÃÅaâ  q®ùP¤      E   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php   ÃÅa   -$>�¤      E   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php0  ÃÅa0  £Ø$Ã¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/XML.php”  ÃÅa”  ³5×¤      G   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/OpenSSH.php=  ÃÅa=  yÊ9
¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/Raw.php€
  ÃÅa€
  ë›Ó¤      I   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/ASN1.phpÿ  ÃÅaÿ  Ãtñ¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/Raw.phpP  ÃÅaP  §£õ‘¤      I   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/SSH2.php&  ÃÅa&  Xˆ[c¤      =   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/Parameters.phpV  ÃÅaV  Äe£º¤      =   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php&  ÃÅa&  ³‰¦¤      <   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php•	  ÃÅa•	  J¼u¤      2   vendor/phpseclib/phpseclib/phpseclib/Crypt/DSA.php<$  ÃÅa<$  %*V¤      8   vendor/phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php5  ÃÅa5  æ—x7¤      6   vendor/phpseclib/phpseclib/phpseclib/Crypt/Twofish.php‘…  ÃÅa‘…  F,]Â¤      2   vendor/phpseclib/phpseclib/phpseclib/Crypt/DES.php‚Ú  ÃÅa‚Ú  ŽQkª¤      D   vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS1.phpm  ÃÅam  F—º¤      D   vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php   ÃÅa   ¦š²¤      <   vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/Parameters.phpL  ÃÅaL  |ž¢º¤      <   vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/PrivateKey.php1  ÃÅa1  Ò€g/¤      ;   vendor/phpseclib/phpseclib/phpseclib/Crypt/DH/PublicKey.phpO  ÃÅaO  ý&›ç¤      7   vendor/phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php¹®  ÃÅa¹®  �I»Ù¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/libsodium.php   ÃÅa   ‘î"þ¤      D   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.phpq  ÃÅaq  Çœü¤      D   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.phpa!  ÃÅaa!  ¦8ü¤      D   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PuTTY.phpŽ  ÃÅaŽ  UéKv¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php.?  ÃÅa.?  Þ©í¤      F   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.phpÚ  ÃÅaÚ  {n¥5¤      E   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php´Y  ÃÅa´Y  +^’m¤      P   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.phpe  ÃÅae  Óê5P¤      O   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPublic.phpê  ÃÅaê  ‰Þ#¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/ASN1.phpý  ÃÅaý  3õ}û¤      G   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/Raw.phpM  ÃÅaM  kRnó¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/SSH2.phpù  ÃÅaù  ·|lë¤      <   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Parameters.php?  ÃÅa?  ¢¯ú¤      <   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.phpØ$  ÃÅaØ$  ÈQÊ¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r2.phpe  ÃÅae  íq€¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192t1.phpt  ÃÅat  ›„“¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192k1.phpî  ÃÅaî  ”Eð,¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r1.phpK  ÃÅaK  L¤      >   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed448.php·  ÃÅa·  È²³-¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r2.phpK  ÃÅaK  ÊŒ1á¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v1.php�  ÃÅa�  “¶$R¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409r1.phpÀ  ÃÅaÀ  •Ð¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384r1.php[  ÃÅa[  ³jÝI¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk233.php‰  ÃÅa‰  pæ0ž¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r1.phpÐ  ÃÅaÐ  Q*Î¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php8	  ÃÅa8	  ¯	œM¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320t1.php4  ÃÅa4  R‡»o¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256t1.phpÔ  ÃÅaÔ  }sïE¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163k1.php�  ÃÅa�  ®�L°¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320r1.phpü  ÃÅaü  1ùðÐ¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283k1.php&  ÃÅa&  =Ýb­¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r1.phpe  ÃÅae  ‡Qœd¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192r1.php  ÃÅa  šDÍó¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php
  ÃÅa
  ¶u‡È¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r1.php¸  ÃÅa¸  +Êû¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk163.php‰  ÃÅa‰  Ñià§¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v3.phpz  ÃÅaz  ½Ä¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r2.phpí  ÃÅaí  ¯„¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256r1.phpœ  ÃÅaœ  §k„D¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime256v1.php�  ÃÅa�  ¥¡n¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192r1.php<  ÃÅa<  +D{¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v2.php2  ÃÅa2  »¸
K¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect239k1.phpå  ÃÅaå  .¶š¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233r1.phpâ  ÃÅaâ  ‰4rÈ¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r1.php�  ÃÅa�  bà2¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp256.php‰  ÃÅa‰  W¬¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233k1.phpà  ÃÅaà  š÷Eö¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk409.php‰  ÃÅa‰  ´ˆÉ÷¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512t1.phpT  ÃÅaT  ÁÏ#¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r2.php�  ÃÅa�  ÝË½¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384t1.php”  ÃÅa”  �tq¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571k1.phpŽ  ÃÅaŽ  î ;¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp521r1.php(  ÃÅa(  ˆ;X¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk283.phpŠ  ÃÅaŠ  Š3a¤¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v2.phpz  ÃÅaz  KÏ]Ø¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160k1.phpÇ  ÃÅaÇ  9º¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r2.phpÜ  ÃÅaÜ  Vø|’¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256r1.php�  ÃÅa�  ™³€.¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256k1.phpñ  ÃÅañ  qÚšÌ¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v3.php2  ÃÅa2  ÖŠG¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160t1.php  ÃÅa  q²ù¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160r1.php  ÃÅa  r¼‹¸¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224r1.php`  ÃÅa`  ðÓ¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistt571.php‰  ÃÅa‰  ;õ#¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512r1.php  ÃÅa  CBF/¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp192.php‰  ÃÅa‰  e*-?¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp521.php‰  ÃÅa‰  -V¢¦¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp224.php‰  ÃÅa‰  Ò�>â¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224k1.php8  ÃÅa8  ¬gn‰¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp384.php‰  ÃÅa‰  Ùz¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r2.php  ÃÅa  ÍBæ¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v1.phpz  ÃÅaz  ü´yÁ¤      @   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed25519.php6(  ÃÅa6(  ‰ÿn¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r1.php  ÃÅa  ÞÒ…@¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb233.php‰  ÃÅa‰  »gV¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224t1.php¤  ÃÅa¤  ‘›o¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224r1.phpl  ÃÅal  óÙÓÒ¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283r1.php&  ÃÅa&  s,à³¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp384r1.phpP  ÃÅaP  vùe¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r2.php°  ÃÅa°  BÊkb¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r1.php°  ÃÅa°  …¢Êß¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409k1.php¾  ÃÅa¾  1Ùû@¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571r1.phpŽ  ÃÅaŽ  =àØü¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb409.php‰  ÃÅa‰  ÖÕž?¤      I   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.phpþ%  ÃÅaþ%  Ns­!¤      G   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.phpå  ÃÅaå  ÃŽa¤      K   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.phph  ÃÅah  Éš-¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.phpˆR  ÃÅaˆR  †Ö•¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Binary.php=&  ÃÅa=&  •��o¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Base.php  ÃÅa  K¥¤      ;   vendor/phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php“  ÃÅa“  çb©å¤      2   vendor/phpseclib/phpseclib/phpseclib/Crypt/RC4.php„  ÃÅa„  Fq�B¤      G   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS.php   ÃÅa   %ß+¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php\  ÃÅa\  K	‡¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php²c  ÃÅa²c  —À«¸¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.phpß#  ÃÅaß#  Ä¯·¤      J   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.phpG#  ÃÅaG#  �NÌ3¤      K   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Signature/Raw.phpc  ÃÅac  †ãnñ¤      A   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/BlockCipher.phpZ  ÃÅaZ  ý'Û¤      @   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/PrivateKey.php  ÃÅa  ¸‡…u¤      ?   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/PublicKey.phpà  ÃÅaà  ë�„¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.phpô  ÃÅaô  ;k¸–¤      B   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.phpDë ÃÅaDë Ú­»¤      C   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php­=  ÃÅa­=  ‘*	;¤      N   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/PasswordProtected.php‡  ÃÅa‡  k‡}¤      H   vendor/phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/Fingerprint.php=  ÃÅa=  Û�È?¤      1   vendor/phpseclib/phpseclib/phpseclib/Crypt/DH.phpP?  ÃÅaP?  4ˆ^ü¤      7   vendor/phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php¶‡  ÃÅa¶‡  ©ÄBø¤      7   vendor/phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php^  ÃÅa^  Û8ÌG¤      5   vendor/phpseclib/phpseclib/phpseclib/Crypt/Random.php%  ÃÅa%  ÛÏ$7¤      6   vendor/phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php98  ÃÅa98  7v ¤      1   vendor/phpseclib/phpseclib/phpseclib/Net/SFTP.phpMÄ ÃÅaMÄ bì ¤      1   vendor/phpseclib/phpseclib/phpseclib/Net/SSH2.phpÛ¦ ÃÅaÛ¦ xü¤      8   vendor/phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.phpqV  ÃÅaqV  ™‹û¤      B   vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.phpä"  ÃÅaä"  cš ¤      K   vendor/phpseclib/phpseclib/phpseclib/System/SSH/Common/Traits/ReadBytes.phpu  ÃÅau  ¥)ÇM¤      9   vendor/phpseclib/phpseclib/phpseclib/System/SSH/Agent.phpÌ   ÃÅaÌ   ,„p¤      2   vendor/phpseclib/phpseclib/phpseclib/File/ASN1.phpÚí  ÃÅaÚí  Y†ùg¤      :   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Element.php¾  ÃÅa¾  ÉÑ;B¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPublicKey.php›  ÃÅa›  —¾¯
¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DisplayText.php  ÃÅa  ÖVòk¤      G   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DirectoryString.php]  ÃÅa]  äh]¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PKCS9String.php”  ÃÅa”  îIZ½¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyInformation.phpþ  ÃÅaþ  ìMŸ¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.phps  ÃÅas  ~2Ï”¤      H   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BasicConstraints.phpá  ÃÅaá  èž›¤      >   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CPSuri.php  ÃÅa  Ñò	È¤      O   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.phpµ  ÃÅaµ  ÌÄž¤      M   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php„  ÃÅa„  –ú’õ¤      G   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php§  ÃÅa§  íT6i¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBKDF2params.php  ÃÅa  ¡À•þ¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuerAltName.php  ÃÅa  Íÿk¤      B   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attributes.phpV  ÃÅaV  .cÈ©¤      R   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php‹  ÃÅa‹  ôø;a¤      M   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php¬  ÃÅa¬  �¯zb¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AccessDescription.php«  ÃÅa«  5(±¤      J   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttribute.php@  ÃÅa@  ÆBÕ¤      J   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_cert_type.php  ÃÅa  ÆÜ¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CountryName.php»  ÃÅa»  ØQÌS¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPrivateKey.php-  ÃÅa-  °—m¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BaseDistance.php)  ÃÅa)  ù*nÄ¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php3  ÃÅa3  ç+¾O¤      @   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Validity.phpa  ÃÅaa  Wº~j¤      U   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.phpÔ  ÃÅaÔ  ‹Ð¬m¤      A   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extension.phpð  ÃÅað  œ”Ù®¤      =   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Curve.phpš  ÃÅaš  i#¨Ï¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeType.php6  ÃÅa6  ö÷`¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtree.php&  ÃÅa&  ~DÜ)¤      G   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RC2CBCParameter.phpú  ÃÅaú  � –¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPublicKey.php)  ÃÅa)  uYg-¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectAltName.php"  ÃÅa"  " i¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NetworkAddress.php6  ÃÅa6  ~š’Ÿ¤      J   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RevokedCertificate.phpÞ  ÃÅaÞ  ¯,F¤      G   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NoticeReference.phpã  ÃÅaã  …ò¾¤      M   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPointName.php)  ÃÅa)  ræÔß¤      H   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OneAsymmetricKey.phpÈ  ÃÅaÈ  ÅóÇ›¤      O   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.phpä  ÃÅaä  g}­]¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DssSigValue.php…  ÃÅa…  ¼m÷Ì¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateDomainName.php³  ÃÅa³  	Evâ¤      J   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Characteristic_two.php"  ÃÅa"  æ×äQ¤      A   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attribute.php²  ÃÅa²  sÀÿ¤      ?   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Prime_p.php  ÃÅa  :·¢}¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertList.php'  ÃÅa'  �ËÕ<¤      M   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php6  ÃÅa6  uô””¤      B   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extensions.php  ÃÅa  Åîv¤      A   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLReason.phpd  ÃÅad  Ü¡…¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyInfo.php<  ÃÅa<  &øVb¤      L   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php´  ÃÅa´  œðç¤      <   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Name.phpC  ÃÅaC  †ö“±¤      Q   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php�  ÃÅa�  âZ	¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyIdentifier.php1  ÃÅa1  RÁ6'¤      A   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Trinomial.php   ÃÅa   €) ¤      B   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKey.php(  ÃÅa(  BÞ\ú¤      K   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificatePolicies.php~  ÃÅa~  ³ðwÐ¤      @   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyUsage.phpÆ  ÃÅaÆ  ¸ë…¤      H   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_comment.php8  ÃÅa8  ¦S\¤      B   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UserNotice.phpÓ  ÃÅaÓ  1¨µ;¤      S   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php  ÃÅa  IÅŒð¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PersonalName.php  ÃÅa  $»A©¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECParameters.phpw  ÃÅaw  ›…¡’¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSASSA_PSS_params.phpN  ÃÅaN  o0$û¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralName.phpÜ  ÃÅaÜ  ¦ÁÍä¤      K   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HoldInstructionCode.phpH  ÃÅaH  9˜d�¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Pentanomial.phpó  ÃÅaó  mnQ½¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPoint.phpq  ÃÅaq  ©}î¤      H   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UniqueIdentifier.php8  ÃÅa8  àÚj¤      J   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TerminalIdentifier.phpD  ÃÅaD  5SÓ2¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AnotherName.phpÎ  ÃÅaÎ  kç¿¤      O   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateSerialNumber.phpJ  ÃÅaJ  %àn¤      Q   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.phpó  ÃÅaó  ØRµ¤      H   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationName.php>  ÃÅa>  §îÕ¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPrivateKey.phpl  ÃÅal  ŠµJ¤      K   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.phpÈ  ÃÅaÈ  �XÀà¤      Q   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.phpí  ÃÅaí  ò3¸N¤      A   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKey.php#  ÃÅa#  ý\¥a¤      A   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAParams.php¦  ÃÅa¦  °<±¤      A   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLNumber.php   ÃÅa   ˆÜ»n¤      A   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ORAddress.php"  ÃÅa"  MÛÑü¤      P   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AdministrationDomainName.phpÑ  ÃÅaÑ  v4Z¤      ?   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPoint.php  ÃÅa  f*›¤      K   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttributes.phpÅ  ÃÅaÅ  ¯�l¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertPolicyId.php3  ÃÅa3  		±’¤      N   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.phpœ  ÃÅaœ  KÊ\3¤      O   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectInfoAccessSyntax.phpŠ  ÃÅaŠ  I Œ’¤      G   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtrees.phpo  ÃÅao  òP):¤      N   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.phpJ  ÃÅaJ  )Ôå¤      M   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NumericUserIdentifier.phpK  ÃÅaK  ËYn2¤      L   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequest.phpó  ÃÅaó  žÆ[¤      K   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php©  ÃÅa©  h‡îu¤      P   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.phpI  ÃÅaI  ìi4¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateIssuer.php+  ÃÅa+  AbÄt¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedData.php1  ÃÅa1  \Þi¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBMAC1params.phpØ  ÃÅaØ  ƒ“¾¤      B   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DigestInfo.phpÐ  ÃÅaÐ  ­¢_¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyPurposeId.php3  ÃÅa3  b¶ö¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HashAlgorithm.php&  ÃÅa&  lW²¤      ?   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldID.php¤  ÃÅa¤  £ôÉ[¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyMappings.phpß  ÃÅaß  µ5r¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RDNSequence.phpP  ÃÅaP  lp‡@¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertificate.php!  ÃÅa!  T,ùÂ¤      G   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateList.phpÊ  ÃÅaÊ  Ú´u¤      V   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.phpù  ÃÅaù  :ï’Ä¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierId.phpB  ÃÅaB  6‘:¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldElement.php.  ÃÅa.  @ˆ“ì¤      H   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php/  ÃÅa/  c¹ýu¤      I   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SpecifiedECDomain.phpÏ  ÃÅaÏ  h„‰õ¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralNames.phpc  ÃÅac  ôè]»¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EDIPartyName.phpÔ  ÃÅaÔ  ”€¥�¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeValue.php+  ÃÅa+  í–Z†¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DHParameter.php+  ÃÅa+  ¤Dî¤      G   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NameConstraints.php  ÃÅa  �N�4¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php=  ÃÅa=  ú‘çz¤      M   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php“  ÃÅa“  9À¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ReasonFlags.phpØ  ÃÅaØ  fcÄÜ¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Certificate.phpÄ  ÃÅaÄ  n�ðù¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PostalAddress.php~  ÃÅa~  atjz¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPrivateKey.php»  ÃÅa»  *P�¤      E   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EcdsaSigValue.php‹  ÃÅa‹  6ï«¤      F   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/InvalidityDate.php8  ÃÅa8  Î:—¤      C   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBES2params.phpÔ  ÃÅaÔ  e*è0¤      P   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequestInfo.phpC  ÃÅaC  ¼,T~¤      D   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBEParameter.phpÙ  ÃÅaÙ  =åã¤      <   vendor/phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Time.phpˆ  ÃÅaˆ  Ý¾u=¤      2   vendor/phpseclib/phpseclib/phpseclib/File/X509.php, ÃÅa, “’;¤      2   vendor/phpseclib/phpseclib/phpseclib/File/ANSI.phpÐX  ÃÅaÐX  vŒ#Y¤      A   vendor/phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php¿5  ÃÅa¿5  þ.‚•¤      M   vendor/phpseclib/phpseclib/phpseclib/Exception/InconsistentSetupException.php3  ÃÅa3  š°”õ¤      P   vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedOperationException.phpB  ÃÅaB  íåÆ¤      C   vendor/phpseclib/phpseclib/phpseclib/Exception/BadModeException.php  ÃÅa  œ[KÝ¤      I   vendor/phpseclib/phpseclib/phpseclib/Exception/BadDecryptionException.php  ÃÅa  !½¤      P   vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.phpB  ÃÅaB  ú ¤      G   vendor/phpseclib/phpseclib/phpseclib/Exception/NoKeyLoadedException.php  ÃÅa  g’N¤      L   vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedCurveException.php.  ÃÅa.  +9s¤      L   vendor/phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php.  ÃÅa.  »‚©¤      L   vendor/phpseclib/phpseclib/phpseclib/Exception/ConnectionClosedException.php.  ÃÅa.  ¬Y²ñ¤      M   vendor/phpseclib/phpseclib/phpseclib/Exception/InsufficientSetupException.php3  ÃÅa3  Êr¤      M   vendor/phpseclib/phpseclib/phpseclib/Exception/UnsupportedFormatException.php3  ÃÅa3  Ô@l¦¤      K   vendor/phpseclib/phpseclib/phpseclib/Exception/UnableToConnectException.php)  ÃÅa)  -DËÅ¤      Q   vendor/phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.phpG  ÃÅaG  5ç|†¤      H   vendor/phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php  ÃÅa  ÙB‡4¤      8   vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField.phpª
  ÃÅaª
  äWp¤      A   vendor/phpseclib/phpseclib/phpseclib/Math/BinaryField/Integer.php‘5  ÃÅa‘5  $<9D¤      @   vendor/phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php`&  ÃÅa`&  6%³ª¤      9   vendor/phpseclib/phpseclib/phpseclib/Math/BinaryField.phpš  ÃÅaš  Ó¼	¤      H   vendor/phpseclib/phpseclib/phpseclib/Math/Common/FiniteField/Integer.phpÛ  ÃÅaÛ  k´¸¤      @   vendor/phpseclib/phpseclib/phpseclib/Math/Common/FiniteField.phpÅ  ÃÅaÅ  ØÜ«¤      8   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger.php£S  ÃÅa£S  Ê•à¤      H   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/OpenSSL.php  ÃÅa  #pÞë¤      R   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP/DefaultEngine.phpÇ  ÃÅaÇ  ï4›¤      F   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php&  ÃÅa&  °\ Y¤      G   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php…G  ÃÅa…G  q¬z¤      G   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php\“  ÃÅa\“  ¿£¤      F   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP64.phpå&  ÃÅaå&  r|¤¤      D   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.phpœ’  ÃÅaœ’  1§¤      L   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/OpenSSL.php€  ÃÅa€  ŒúV¤      O   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Montgomery.phpB
  ÃÅaB
  B}•!¤      Z   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/PowerOfTwo.php©  ÃÅa©  E\€¤      Z   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Montgomery.phpÓ  ÃÅaÓ  @˜a�¤      W   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.phpD+  ÃÅaD+  Ôå‚l¤      [   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/EvalBarrett.phpy;  ÃÅay;  ¬Mç¤      ^   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/MontgomeryMult.php“  ÃÅa“  jPcÚ¤      W   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Classic.php  ÃÅa  8™N¤      I   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Base.phpÀ  ÃÅaÀ  êÐ¤Ë¤      R   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/DefaultEngine.php”  ÃÅa”  Ù�þ¤      O   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/OpenSSL.php†  ÃÅa†  6]Ôh¤      O   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.phpý  ÃÅaý  �sÖF¤      Z   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php  ÃÅa  #û4€¤      ^   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php„  ÃÅa„  ²�2”¤      L   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.phpk
  ÃÅak
  �5�¥¤      U   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/DefaultEngine.php•  ÃÅa•  â A¤      D   vendor/phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.phpVD  ÃÅaVD  –óô¤      2   vendor/phpseclib/phpseclib/phpseclib/bootstrap.php¼  ÃÅa¼  •«¤      K   vendor/phabel-transpiler74.amphp/websocket-client/src/ConnectionFactory.php"  ÃÅa"  çcw¤      K   vendor/phabel-transpiler74.amphp/websocket-client/src/Rfc6455Connection.php˜  ÃÅa˜  Nà
¤      C   vendor/phabel-transpiler74.amphp/websocket-client/src/Handshake.php	  ÃÅa	  ‹$C¤      M   vendor/phabel-transpiler74.amphp/websocket-client/src/ConnectionException.php"  ÃÅa"  PÉåâ¤      J   vendor/phabel-transpiler74.amphp/websocket-client/src/Rfc6455Connector.phpC  ÃÅaC  c
Ìä¤      C   vendor/phabel-transpiler74.amphp/websocket-client/src/Connector.phpJ  ÃÅaJ  /Ïú'¤      D   vendor/phabel-transpiler74.amphp/websocket-client/src/Connection.php  ÃÅa  l„´�¤      C   vendor/phabel-transpiler74.amphp/websocket-client/src/functions.php
  ÃÅa
  ½R–ì¤      R   vendor/phabel-transpiler74.amphp/websocket-client/src/Rfc6455ConnectionFactory.phpL  ÃÅaL  ½:k2¤      J   vendor/phabel-transpiler74.amphp/websocket-client/test-autobahn/runner.php  ÃÅa  44µ¤      Y   vendor/phabel-transpiler74.amphp/websocket-client/test-autobahn/config/fuzzingserver.jsonË   ÃÅaË   ÇtB½¤      ?   vendor/phabel-transpiler74.amphp/websocket-client/composer.json'  ÃÅa'  ‘¯T÷¤      ?   vendor/phabel-transpiler74.amphp/http/src/Http2/Http2Parser.phpT  ÃÅaT  e{o¤      L   vendor/phabel-transpiler74.amphp/http/src/Http2/Http2ConnectionException.php  ÃÅa  ÀÝ ¤      B   vendor/phabel-transpiler74.amphp/http/src/Http2/Http2Processor.php³  ÃÅa³  ÿî¥¤      H   vendor/phabel-transpiler74.amphp/http/src/Http2/Http2StreamException.phpÙ  ÃÅaÙ  ž€�é¤      5   vendor/phabel-transpiler74.amphp/http/src/Rfc7230.phpè  ÃÅaè  j"àç¤      5   vendor/phabel-transpiler74.amphp/http/src/Message.phpF  ÃÅaF  I8¤      4   vendor/phabel-transpiler74.amphp/http/src/Status.php¨  ÃÅa¨  `òZ¤      K   vendor/phabel-transpiler74.amphp/http/src/Cookie/InvalidCookieException.php×   ÃÅa×   ¼`ºû¤      C   vendor/phabel-transpiler74.amphp/http/src/Cookie/ResponseCookie.phpŠ*  ÃÅaŠ*  Óž½¤      B   vendor/phabel-transpiler74.amphp/http/src/Cookie/RequestCookie.phpå  ÃÅaå  ^q
¤      E   vendor/phabel-transpiler74.amphp/http/src/Cookie/CookieAttributes.phpë"  ÃÅaë"  Ù*#¤      7   vendor/phabel-transpiler74.amphp/http/src/functions.phpN	  ÃÅaN	  õt¤      D   vendor/phabel-transpiler74.amphp/http/src/InvalidHeaderException.phpH  ÃÅaH  Å™¤      3   vendor/phabel-transpiler74.amphp/http/composer.json›  ÃÅa›  �Ú€ß¤      P   vendor/phabel-transpiler74.amphp/http-client-cookies/composer-require-check.json�  ÃÅa�  8fa¤      N   vendor/phabel-transpiler74.amphp/http-client-cookies/src/InMemoryCookieJar.php€  ÃÅa€  VU¸¤      J   vendor/phabel-transpiler74.amphp/http-client-cookies/src/NullCookieJar.phpÚ  ÃÅaÚ  àR²9¤      V   vendor/phabel-transpiler74.amphp/http-client-cookies/src/Internal/PublicSuffixList.php1  ÃÅa1  ¿Ã“±¤      J   vendor/phabel-transpiler74.amphp/http-client-cookies/src/FileCookieJar.php$  ÃÅa$  ÞWÍ¤      F   vendor/phabel-transpiler74.amphp/http-client-cookies/src/CookieJar.phpÊ  ÃÅaÊ  *Y)·¤      N   vendor/phabel-transpiler74.amphp/http-client-cookies/src/CookieInterceptor.php®  ÃÅa®  ƒ†ï'¤      L   vendor/phabel-transpiler74.amphp/http-client-cookies/examples/basic-file.php`  ÃÅa`  ÊKƒ�¤      G   vendor/phabel-transpiler74.amphp/http-client-cookies/examples/basic.php@  ÃÅa@  ¡‰;9¤      O   vendor/phabel-transpiler74.amphp/http-client-cookies/res/public_suffix_list.datm� ÃÅam� s¿tK¤      B   vendor/phabel-transpiler74.amphp/http-client-cookies/composer.json²  ÃÅa²  ·â×u¤      [   vendor/phabel-transpiler74.amphp/http-client-cookies/test/Internal/PublicSuffixListTest.phpô  ÃÅaô  ´ßÍ§¤      O   vendor/phabel-transpiler74.amphp/http-client-cookies/test/FileCookieJarTest.phpF  ÃÅaF  ZËÞ½¤      K   vendor/phabel-transpiler74.amphp/http-client-cookies/test/CookieJarTest.phpG	  ÃÅaG	  ©XX¤      H   vendor/phabel-transpiler74.amphp/http-client-cookies/test/CookieTest.php  ÃÅa  /ÀwG¤      S   vendor/phabel-transpiler74.amphp/http-client-cookies/test/InMemoryCookieJarTest.php  ÃÅa  “t«¤      N   vendor/phabel-transpiler74.amphp/http-client-cookies/test/ClientCookieTest.php  ÃÅa  ª2 Y¤      6   vendor/phabel-transpiler74.amphp/process/composer.jsont  ÃÅat  û@¼Ô¤      I   vendor/phabel-transpiler74.amphp/process/bin/windows/ProcessWrapper64.exe H ÃÅa H &Ó;‰¤      G   vendor/phabel-transpiler74.amphp/process/bin/windows/ProcessWrapper.exe 4 ÃÅa 4 %P§¤      G   vendor/phabel-transpiler74.amphp/process/lib/Internal/ProcessStatus.php  ÃÅa  ðFÞ>¤      G   vendor/phabel-transpiler74.amphp/process/lib/Internal/ProcessHandle.phpÜ  ÃÅaÜ   Ï<2¤      F   vendor/phabel-transpiler74.amphp/process/lib/Internal/Posix/Handle.php±  ÃÅa±  ÃmpÓ¤      F   vendor/phabel-transpiler74.amphp/process/lib/Internal/Posix/Runner.phpJ   ÃÅaJ   ¬í¤      Q   vendor/phabel-transpiler74.amphp/process/lib/Internal/Windows/SocketConnector.phpn0  ÃÅan0  ;mï¤      U   vendor/phabel-transpiler74.amphp/process/lib/Internal/Windows/PendingSocketClient.php.  ÃÅa.  ©ˆŒ¤      L   vendor/phabel-transpiler74.amphp/process/lib/Internal/Windows/SignalCode.phpn  ÃÅan  œNƒ¤      H   vendor/phabel-transpiler74.amphp/process/lib/Internal/Windows/Handle.php±  ÃÅa±  j‹<¤      Q   vendor/phabel-transpiler74.amphp/process/lib/Internal/Windows/HandshakeStatus.phpÏ  ÃÅaÏ  àûh}¤      H   vendor/phabel-transpiler74.amphp/process/lib/Internal/Windows/Runner.phpU  ÃÅaU   ÏÜÒ¤      G   vendor/phabel-transpiler74.amphp/process/lib/Internal/ProcessRunner.phpÆ  ÃÅaÆ  clg¤      <   vendor/phabel-transpiler74.amphp/process/lib/StatusError.phpC   ÃÅaC   +4«R¤      D   vendor/phabel-transpiler74.amphp/process/lib/ProcessOutputStream.phpp  ÃÅap  ”E%«¤      :   vendor/phabel-transpiler74.amphp/process/lib/functions.php  ÃÅa  —¥S¤      8   vendor/phabel-transpiler74.amphp/process/lib/Process.php‡  ÃÅa‡  ¼±ä‰¤      C   vendor/phabel-transpiler74.amphp/process/lib/ProcessInputStream.php€  ÃÅa€  ›Úò¤      A   vendor/phabel-transpiler74.amphp/process/lib/ProcessException.phpL   ÃÅaL   ´÷ŠA¤      7   vendor/phabel-transpiler74.amphp/parallel/composer.json\  ÃÅa\  œ@�ví      O   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/BootstrapWorkerFactory.phpm  ÃÅam  ÞCÑ¤      M   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureThrowable.phpÄ  ÃÅaÄ  QV1Â¤      F   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerFactory.php  ÃÅa  	s¸¤      E   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/CallableTask.php³  ÃÅa³  ·5¢é¤      M   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureException.phpý  ÃÅaý  Ý“•E¤      I   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureError.phpõ  ÃÅaõ  ×÷¤L¤      D   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/DefaultPool.phpà  ÃÅaà  W�}¤      H   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerException.phpS   ÃÅaS   �òÆ¤      I   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/BasicEnvironment.php  ÃÅa  ×¶›Ï¤      E   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/Job.php]  ÃÅa]  DKbß¤      M   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskFailure.phpó  ÃÅaó   ¤N¤      N   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/PooledWorker.phpA  ÃÅaA  ñ:ð´¤      O   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/WorkerProcess.php%  ÃÅa%  é6)Ô¤      P   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/worker-process.php’  ÃÅa’  …)Mh¤      L   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskResult.phpF  ÃÅaF  §3-À¤      M   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskSuccess.phpô  ÃÅaô  €ÀËt¤      =   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Pool.php�  ÃÅa�  î‘?þ¤      F   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/TaskException.php  ÃÅa  ô6Y¤      E   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerThread.php¡  ÃÅa¡  è¾]€¤      D   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Environment.php  ÃÅa  µ+ÄÏ¤      C   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/TaskRunner.php  ÃÅa  ú0¬-¤      C   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/TaskWorker.phpÊ  ÃÅaÊ  œ›R¤      B   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/functions.php¶  ÃÅa¶  ™‚¤      ?   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Worker.php  ÃÅa  l==¤      F   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerProcess.phpã  ÃÅaã  ž¾Ùš¤      G   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerParallel.phpŒ  ÃÅaŒ  »è7¤      =   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/Task.php¨  ÃÅa¨  ½$®Y¤      M   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/DefaultWorkerFactory.phpŒ  ÃÅaŒ  Ô]Y+¤      B   vendor/phabel-transpiler74.amphp/parallel/lib/Worker/TaskError.phpc  ÃÅac  ¸Ö¤      H   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ContextPanicError.php’  ÃÅa’  (CO¤      L   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/SharedMemoryException.php\   ÃÅa\   U"ÌO¤      B   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ExitFailure.phpb  ÃÅab  “ïÀ¤      B   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ExitSuccess.php]  ÃÅa]  ÚÂþž¤      I   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/SharedMemoryParcel.phpÞ6  ÃÅaÞ6  õÁÔ¤      G   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelledSocket.php	  ÃÅa	  æú�;¤      F   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ParcelException.phpQ   ÃÅaQ   �…pö¤      G   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelException.phpR   ÃÅaR   ï÷X¤      =   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/Parcel.php¨  ÃÅa¨  Jw¤      M   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/Internal/ParcelStorage.phpê  ÃÅaê  ¶±ÿ¾¤      K   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/SynchronizationError.phpR   ÃÅaR   â›iä¤      E   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ThreadedParcel.phpÈ  ÃÅaÈ  ? ÑJ¤      >   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/Channel.phpð  ÃÅað  ,åû¤      @   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/functions.phpÒ  ÃÅaÒ  ó¥µÀ¤      A   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/PanicError.php‡  ÃÅa‡  Ç8¤      D   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelParser.phpö  ÃÅaö  JGÜ=¤      A   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ExitResult.php&  ÃÅa&   '55¤      G   vendor/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelledStream.php	  ÃÅa	  £�¤      H   vendor/phabel-transpiler74.amphp/parallel/lib/Context/ContextFactory.php  ÃÅa  Õ�ž¤      @   vendor/phabel-transpiler74.amphp/parallel/lib/Context/Thread.phpó#  ÃÅaó#  0ÙÄÙ¤      J   vendor/phabel-transpiler74.amphp/parallel/lib/Context/ContextException.phpU   ÃÅaU   ØŽ­¤      M   vendor/phabel-transpiler74.amphp/parallel/lib/Context/Internal/ProcessHub.phpÿ  ÃÅaÿ  ÒØ—ð¤      Q   vendor/phabel-transpiler74.amphp/parallel/lib/Context/Internal/process-runner.phpM  ÃÅaM  ö…�¤      I   vendor/phabel-transpiler74.amphp/parallel/lib/Context/Internal/Thread.phpG  ÃÅaG  çuÎË¤      N   vendor/phabel-transpiler74.amphp/parallel/lib/Context/Internal/ParallelHub.php¡  ÃÅa¡  ©ŠÎ¤      E   vendor/phabel-transpiler74.amphp/parallel/lib/Context/StatusError.phpL   ÃÅaL   k1¥¤      O   vendor/phabel-transpiler74.amphp/parallel/lib/Context/DefaultContextFactory.php!  ÃÅa!  ¸¼N¤      C   vendor/phabel-transpiler74.amphp/parallel/lib/Context/functions.php=  ÃÅa=  k¤      A   vendor/phabel-transpiler74.amphp/parallel/lib/Context/Process.phpJ0  ÃÅaJ0  Ä‰7¥¤      B   vendor/phabel-transpiler74.amphp/parallel/lib/Context/Parallel.php3  ÃÅa3  fŠƒÁ¤      A   vendor/phabel-transpiler74.amphp/parallel/lib/Context/Context.php  ÃÅa  ©Ú€¤      =   vendor/phabel-transpiler74.amphp/redis/src/RedisException.phpV   ÃÅaV   '‚ÂX¤      ?   vendor/phabel-transpiler74.amphp/redis/src/RedisHyperLogLog.phpW  ÃÅaW  ‹‘S¤      9   vendor/phabel-transpiler74.amphp/redis/src/RespParser.php  ÃÅa  –H9ø¤      >   vendor/phabel-transpiler74.amphp/redis/src/SocketException.phpM   ÃÅaM   e¯-¤      >   vendor/phabel-transpiler74.amphp/redis/src/ParserException.phpM   ÃÅaM   û}à¤      4   vendor/phabel-transpiler74.amphp/redis/src/Redis.phpèj  ÃÅaèj  {ç$¥¤      ;   vendor/phabel-transpiler74.amphp/redis/src/Subscription.phpî  ÃÅaî  "	¤      M   vendor/phabel-transpiler74.amphp/redis/src/Mutex/ConnectionLimitException.php\   ÃÅa\   ¼ÜØ¤      B   vendor/phabel-transpiler74.amphp/redis/src/Mutex/LockException.phpQ   ÃÅaQ   FEüý¤      A   vendor/phabel-transpiler74.amphp/redis/src/Mutex/MutexOptions.phpÁ  ÃÅaÁ  ±;z¤      C   vendor/phabel-transpiler74.amphp/redis/src/Mutex/MutexException.phpp   ÃÅap   ÆoG”¤      :   vendor/phabel-transpiler74.amphp/redis/src/Mutex/Mutex.php~!  ÃÅa~!  í�ý§¤      =   vendor/phabel-transpiler74.amphp/redis/src/QueryException.phpL   ÃÅaL   Ix×h¤      7   vendor/phabel-transpiler74.amphp/redis/src/RedisSet.php»  ÃÅa»  ÞBcû¤      9   vendor/phabel-transpiler74.amphp/redis/src/Subscriber.phpé  ÃÅaé  æ=¦¤      7   vendor/phabel-transpiler74.amphp/redis/src/RedisMap.php²  ÃÅa²  )ŠPé¤      5   vendor/phabel-transpiler74.amphp/redis/src/Config.phpD  ÃÅaD  ÄvË¤      =   vendor/phabel-transpiler74.amphp/redis/src/RemoteExecutor.php  ÃÅa  }­0´¤      =   vendor/phabel-transpiler74.amphp/redis/src/RedisSortedSet.php<  ÃÅa<  ßª‚Ä¤      C   vendor/phabel-transpiler74.amphp/redis/src/QueryExecutorFactory.phpÃ   ÃÅaÃ   lJH¤      :   vendor/phabel-transpiler74.amphp/redis/src/SortOptions.php¤  ÃÅa¤  ¾ðy!¤      <   vendor/phabel-transpiler74.amphp/redis/src/QueryExecutor.php|  ÃÅa|  jL˜¤      8   vendor/phabel-transpiler74.amphp/redis/src/functions.phpQ	  ÃÅaQ	  {²o&¤      D   vendor/phabel-transpiler74.amphp/redis/src/RemoteExecutorFactory.php  ÃÅa  Šu•¤      8   vendor/phabel-transpiler74.amphp/redis/src/RedisList.phpP  ÃÅaP  á!e¤      9   vendor/phabel-transpiler74.amphp/redis/src/RespSocket.phpA  ÃÅaA  |ä‰¤      4   vendor/phabel-transpiler74.amphp/redis/src/Cache.phpy  ÃÅay   ¿DÄ¤      9   vendor/phabel-transpiler74.amphp/redis/src/SetOptions.php  ÃÅa  8�¼Ò¤      4   vendor/phabel-transpiler74.amphp/redis/composer.jsonr  ÃÅar  ˜š¬¿¤      ?   vendor/phabel-transpiler74.amphp/windows-registry/composer.jsont  ÃÅat  ¢´J;¤      I   vendor/phabel-transpiler74.amphp/windows-registry/lib/WindowsRegistry.phpÖ	  ÃÅaÖ	  �Úc¯¤      N   vendor/phabel-transpiler74.amphp/windows-registry/lib/KeyNotFoundException.phpX   ÃÅaX   Ö»E±¤      2   vendor/phabel-transpiler74.amphp/amp/composer.json  ÃÅa  ŽÔ¤      4   vendor/phabel-transpiler74.amphp/amp/lib/Emitter.php  ÃÅa  ±±«,¤      B   vendor/phabel-transpiler74.amphp/amp/lib/NullCancellationToken.php¿  ÃÅa¿  ¤ÃAt¤      4   vendor/phabel-transpiler74.amphp/amp/lib/Success.phpÕ  ÃÅaÕ  ý>¢¤      E   vendor/phabel-transpiler74.amphp/amp/lib/TimeoutCancellationToken.php  ÃÅa  
˜ŒY¤      5   vendor/phabel-transpiler74.amphp/amp/lib/Producer.phpê  ÃÅaê  ¬†íK¤      4   vendor/phabel-transpiler74.amphp/amp/lib/Promise.php”  ÃÅa”  Ê¤}º¤      A   vendor/phabel-transpiler74.amphp/amp/lib/Internal/Placeholder.php€  ÃÅa€  Óÿî“¤      >   vendor/phabel-transpiler74.amphp/amp/lib/Internal/Producer.phpi  ÃÅai  ¡–k¸¤      D   vendor/phabel-transpiler74.amphp/amp/lib/Internal/PrivatePromise.php0  ÃÅa0  Æ²¶¤      ?   vendor/phabel-transpiler74.amphp/amp/lib/Internal/functions.php¢  ÃÅa¢  cÇÆ×¤      E   vendor/phabel-transpiler74.amphp/amp/lib/Internal/PrivateIterator.phpv  ÃÅav  …ýÙ¤      E   vendor/phabel-transpiler74.amphp/amp/lib/Internal/ResolutionQueue.php*  ÃÅa*  Kâ¼¤      D   vendor/phabel-transpiler74.amphp/amp/lib/CancellationTokenSource.phpå  ÃÅaå  |1ò~¤      9   vendor/phabel-transpiler74.amphp/amp/lib/Loop/Watcher.phpÎ  ÃÅaÎ  ¨
R¤      =   vendor/phabel-transpiler74.amphp/amp/lib/Loop/EventDriver.phpï$  ÃÅaï$  ËÁh6¤      8   vendor/phabel-transpiler74.amphp/amp/lib/Loop/Driver.phpe  ÃÅae  îœýè¤      ?   vendor/phabel-transpiler74.amphp/amp/lib/Loop/DriverFactory.phpì  ÃÅaì  ö¤      >   vendor/phabel-transpiler74.amphp/amp/lib/Loop/NativeDriver.php8  ÃÅa8  Ž_@F¤      E   vendor/phabel-transpiler74.amphp/amp/lib/Loop/Internal/TimerQueue.php3  ÃÅa3  àbâ´¤      M   vendor/phabel-transpiler74.amphp/amp/lib/Loop/UnsupportedFeatureException.php  ÃÅa  3µ¢g¤      :   vendor/phabel-transpiler74.amphp/amp/lib/Loop/EvDriver.phpÓ   ÃÅaÓ   A	‚;¤      :   vendor/phabel-transpiler74.amphp/amp/lib/Loop/UvDriver.php(  ÃÅa(  ±ÍöU¤      E   vendor/phabel-transpiler74.amphp/amp/lib/Loop/InvalidWatcherError.php  ÃÅa  Æ^Ë—¤      ?   vendor/phabel-transpiler74.amphp/amp/lib/Loop/TracingDriver.phpD  ÃÅaD  † z¤      6   vendor/phabel-transpiler74.amphp/amp/lib/Coroutine.phpï  ÃÅaï  vÂ¤      >   vendor/phabel-transpiler74.amphp/amp/lib/CancellationToken.phpß  ÃÅaß  ™a ¤      5   vendor/phabel-transpiler74.amphp/amp/lib/Deferred.php,  ÃÅa,  Õà¨½¤      4   vendor/phabel-transpiler74.amphp/amp/lib/Failure.php¦  ÃÅa¦  ’¯ÜS¤      A   vendor/phabel-transpiler74.amphp/amp/lib/MultiReasonException.php’  ÃÅa’  }ÍÏˆ¤      6   vendor/phabel-transpiler74.amphp/amp/lib/functions.phpµY  ÃÅaµY  DN·ï¤      >   vendor/phabel-transpiler74.amphp/amp/lib/InvalidYieldError.phpì  ÃÅaì  væFê¤      F   vendor/phabel-transpiler74.amphp/amp/lib/CombinedCancellationToken.phpÎ  ÃÅaÎ  q2>³¤      =   vendor/phabel-transpiler74.amphp/amp/lib/TimeoutException.phpn  ÃÅan  Õ>Š¤      1   vendor/phabel-transpiler74.amphp/amp/lib/Loop.phpD  ÃÅaD  Ï¤      4   vendor/phabel-transpiler74.amphp/amp/lib/Delayed.php�  ÃÅa�  j5‘ý¤      5   vendor/phabel-transpiler74.amphp/amp/lib/Iterator.php8  ÃÅa8  ¦öõ¤      :   vendor/phabel-transpiler74.amphp/amp/lib/CallableMaker.php{
  ÃÅa{
  àA¤      ?   vendor/phabel-transpiler74.amphp/amp/lib/CancelledException.phpj  ÃÅaj  o|kÒ¤      8   vendor/phabel-transpiler74.amphp/amp/lib/LazyPromise.php¡  ÃÅa¡  [–\c¤      3   vendor/phabel-transpiler74.amphp/amp/lib/Struct.php¤  ÃÅa¤  B*#,¤      J   vendor/phabel-transpiler74.amphp/http-client/src/MissingAttributeError.phpÒ   ÃÅaÒ   ‚¢¤      =   vendor/phabel-transpiler74.amphp/http-client/src/Response.php  ÃÅa  áÿC¤      D   vendor/phabel-transpiler74.amphp/http-client/src/SocketException.phpX   ÃÅaX   <’…í      C   vendor/phabel-transpiler74.amphp/http-client/src/ParseException.php‚  ÃÅa‚  <*–�¤      V   vendor/phabel-transpiler74.amphp/http-client/src/EventListener/RecordHarAttributes.phpä  ÃÅaä  EBP9¤      <   vendor/phabel-transpiler74.amphp/http-client/src/Request.php€<  ÃÅa€<  ‡Õ^¤      E   vendor/phabel-transpiler74.amphp/http-client/src/PooledHttpClient.phpÅ  ÃÅaÅ  )È<¤      F   vendor/phabel-transpiler74.amphp/http-client/src/HttpClientBuilder.php—  ÃÅa—  êÿº‹¤      Q   vendor/phabel-transpiler74.amphp/http-client/src/Internal/ForbidSerialization.phpê   ÃÅaê   €eqp¤      K   vendor/phabel-transpiler74.amphp/http-client/src/Internal/ForbidCloning.php1  ÃÅa1  Œ“'¤      K   vendor/phabel-transpiler74.amphp/http-client/src/Internal/HarAttributes.php  ÃÅa  x®[…¤      P   vendor/phabel-transpiler74.amphp/http-client/src/Internal/ResponseBodyStream.php^  ÃÅa^  ËÌÓv¤      G   vendor/phabel-transpiler74.amphp/http-client/src/Internal/functions.php¨  ÃÅa¨  ¡ÎR¤      U   vendor/phabel-transpiler74.amphp/http-client/src/Internal/SizeLimitingInputStream.php§  ÃÅa§  )„›¤      @   vendor/phabel-transpiler74.amphp/http-client/src/RequestBody.phpf  ÃÅaf  8´§Þ¤      J   vendor/phabel-transpiler74.amphp/http-client/src/InterceptedHttpClient.phpM  ÃÅaM  Oå.Ÿ¤      G   vendor/phabel-transpiler74.amphp/http-client/src/DelegateHttpClient.phpz  ÃÅaz  L¾À¸¤      ?   vendor/phabel-transpiler74.amphp/http-client/src/HttpClient.phpÏ  ÃÅaÏ  Êå3¤      L   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/MatchOrigin.phpU  ÃÅaU  Ê»¤      O   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/ModifyResponse.php   ÃÅa   CÏR‹¤      Q   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestHeader.php  ÃÅa  ¸Œh�¤      X   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestHeaderIfUnset.phpQ  ÃÅaQ  ?±•ó¤      Q   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/AddRequestHeader.php¹  ÃÅa¹  j"˜<¤      Z   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/TooManyRedirectsException.php  ÃÅa  xxú6í      S   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/DecompressResponse.phpq  ÃÅaq  Òy¡¤      O   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/LogHttpArchive.php3  ÃÅa3  ?m›!¤      R   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/AddResponseHeader.phpÀ  ÃÅaÀ  ô¤À¤      P   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/FollowRedirects.phpb&  ÃÅab&  {ø¯´¤      R   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/SetResponseHeader.php
  ÃÅa
  Kjko¤      U   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/RemoveResponseHeader.php�  ÃÅa�  ÞÀ'®¤      T   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/RemoveRequestHeader.phpˆ  ÃÅaˆ  aäç`¤      Y   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/SetResponseHeaderIfUnset.phpY  ÃÅaY  âµCH¤      N   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/ModifyRequest.php4  ÃÅa4  @Ú\¤      R   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestTimeout.php�  ÃÅa�  Q’ûp¤      R   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/ForbidUriUserInfo.php  ÃÅa  §§`·¤      N   vendor/phabel-transpiler74.amphp/http-client/src/Interceptor/RetryRequests.phpz  ÃÅaz  Ë>Ó¤      K   vendor/phabel-transpiler74.amphp/http-client/src/ApplicationInterceptor.php�  ÃÅa�  Ä·-A¤      B   vendor/phabel-transpiler74.amphp/http-client/src/Body/FileBody.phpú  ÃÅaú  <1Vs¤      D   vendor/phabel-transpiler74.amphp/http-client/src/Body/StringBody.phpõ  ÃÅaõ  ;i3ª¤      B   vendor/phabel-transpiler74.amphp/http-client/src/Body/FormBody.php—  ÃÅa—  çi¤      B   vendor/phabel-transpiler74.amphp/http-client/src/Body/JsonBody.phpÐ  ÃÅaÐ  dÛKÆ¤      B   vendor/phabel-transpiler74.amphp/http-client/src/EventListener.phpŒ  ÃÅaŒ  UI]¤      E   vendor/phabel-transpiler74.amphp/http-client/src/TimeoutException.phpY   ÃÅaY   \Ió6í      Q   vendor/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionFactory.phpm  ÃÅam  YÆ}¤      F   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Stream.php“  ÃÅa“  Õ˜\+¤      U   vendor/phabel-transpiler74.amphp/http-client/src/Connection/LimitedConnectionPool.php™   ÃÅa™   âÉ·¤      X   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Http2ConnectionException.php³  ÃÅa³  m @¤      T   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http2Stream.phpø  ÃÅaø  âï±¤      a   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http2ConnectionProcessor.php¥Ø  ÃÅa¥Ø  ¤ô¤      Z   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Internal/RequestNormalizer.php]  ÃÅa]  “……¤      T   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http1Parser.php�3  ÃÅa�3  –lcó¤      N   vendor/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionPool.php«  ÃÅa«  v8û‹¤      [   vendor/phabel-transpiler74.amphp/http-client/src/Connection/UnprocessedRequestException.phpT  ÃÅaT  Égzð¤      J   vendor/phabel-transpiler74.amphp/http-client/src/Connection/HttpStream.php  ÃÅa  `Âµ°¤      J   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Connection.php  ÃÅa  ký3‹¤      V   vendor/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionLimitingPool.php…1  ÃÅa…1  �ól×¤      W   vendor/phabel-transpiler74.amphp/http-client/src/Connection/UnlimitedConnectionPool.phpã  ÃÅaã  n[wé¤      N   vendor/phabel-transpiler74.amphp/http-client/src/Connection/UpgradedSocket.phpÅ
  ÃÅaÅ
  ÜøwV¤      R   vendor/phabel-transpiler74.amphp/http-client/src/Connection/StreamLimitingPool.phpo  ÃÅao  íö¤      X   vendor/phabel-transpiler74.amphp/http-client/src/Connection/DefaultConnectionFactory.phpx!  ÃÅax!  ®°ìF¤      Q   vendor/phabel-transpiler74.amphp/http-client/src/Connection/InterceptedStream.php|  ÃÅa|  ŠvÎb¤      O   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Http1Connection.php*c  ÃÅa*c  ²þ’†¤      O   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Http2Connection.phpç
  ÃÅaç
  |Ýk¤      T   vendor/phabel-transpiler74.amphp/http-client/src/Connection/Http2StreamException.phpy  ÃÅay  ”#�z¤      G   vendor/phabel-transpiler74.amphp/http-client/src/NetworkInterceptor.phpW  ÃÅaW  Ëá•u¤      =   vendor/phabel-transpiler74.amphp/http-client/src/Trailers.php‹  ÃÅa‹  7»ó�¤      L   vendor/phabel-transpiler74.amphp/http-client/src/InvalidRequestException.phpé  ÃÅaé  bØÍ²¤      B   vendor/phabel-transpiler74.amphp/http-client/src/HttpException.phpM   ÃÅaM   ‹HV%í      :   vendor/phabel-transpiler74.amphp/http-client/composer.json�	  ÃÅa�	  †­Ð¤      ?   vendor/phabel-transpiler74.amphp/mysql/src/ConnectionConfig.phpÛ  ÃÅaÛ  Šù…Ž¤      D   vendor/phabel-transpiler74.amphp/mysql/src/ConnectionTransaction.php®  ÃÅa®  :—¤      >   vendor/phabel-transpiler74.amphp/mysql/src/PooledStatement.php   ÃÅa   „½È¢¤      C   vendor/phabel-transpiler74.amphp/mysql/src/CancellableConnector.phpD  ÃÅaD  Fòp{¤      B   vendor/phabel-transpiler74.amphp/mysql/src/ConnectionStatement.php‰  ÃÅa‰  tË\¦¤      8   vendor/phabel-transpiler74.amphp/mysql/src/DataTypes.php¢>  ÃÅa¢>  Û4¿x¤      ?   vendor/phabel-transpiler74.amphp/mysql/src/TransactionError.phpY   ÃÅaY   ‡m»ï¤      F   vendor/phabel-transpiler74.amphp/mysql/src/InitializationException.phpu   ÃÅau   ªs¡9¤      A   vendor/phabel-transpiler74.amphp/mysql/src/Internal/Processor.php½é  ÃÅa½é  \-³¤      G   vendor/phabel-transpiler74.amphp/mysql/src/Internal/ConnectionState.phpÎ  ÃÅaÎ  \8ö¤      C   vendor/phabel-transpiler74.amphp/mysql/src/Internal/ResultProxy.phpG	  ÃÅaG	  Ú0U¤      3   vendor/phabel-transpiler74.amphp/mysql/src/Pool.phpƒ  ÃÅaƒ  µa¾¤      <   vendor/phabel-transpiler74.amphp/mysql/src/StatementPool.php¸  ÃÅa¸  ¶	`%¤      9   vendor/phabel-transpiler74.amphp/mysql/src/Connection.phpâ  ÃÅaâ  s}ch¤      8   vendor/phabel-transpiler74.amphp/mysql/src/ResultSet.php  ÃÅa  ½:¤      8   vendor/phabel-transpiler74.amphp/mysql/src/functions.phpñ  ÃÅañ  æfÛz¤      @   vendor/phabel-transpiler74.amphp/mysql/src/PooledTransaction.phpÉ  ÃÅaÉ  
»Ä&¤      B   vendor/phabel-transpiler74.amphp/mysql/src/ConnectionResultSet.php‚  ÃÅa‚  ".Ëd¤      <   vendor/phabel-transpiler74.amphp/mysql/src/CommandResult.php  ÃÅa  ÝÂ9—¤      8   vendor/phabel-transpiler74.amphp/mysql/src/Statement.php€  ÃÅa€  µì¤      >   vendor/phabel-transpiler74.amphp/mysql/src/PooledResultSet.php1	  ÃÅa1	  
fÉ¤      ;   vendor/phabel-transpiler74.amphp/mysql/src/RefreshTypes.php8  ÃÅa8  ~iœp¤      C   vendor/phabel-transpiler74.amphp/mysql/benchmarks/AbstractBench.phpÚ   ÃÅaÚ   ,þ}ø¤      @   vendor/phabel-transpiler74.amphp/mysql/benchmarks/QueryBench.php¡  ÃÅa¡  ÂR3l¤      @   vendor/phabel-transpiler74.amphp/mysql/examples/4-multi-rows.php"  ÃÅa"  ¶-/¤      I   vendor/phabel-transpiler74.amphp/mysql/examples/support/generic-table.php  ÃÅa  ‘†I¤      E   vendor/phabel-transpiler74.amphp/mysql/examples/support/bootstrap.phpš  ÃÅaš  D±…Ý¤      A   vendor/phabel-transpiler74.amphp/mysql/examples/5-multi-stmts.phpµ  ÃÅaµ  M ã«¤      H   vendor/phabel-transpiler74.amphp/mysql/examples/3-generic-with-yield.phpr  ÃÅar  GX¦¤      =   vendor/phabel-transpiler74.amphp/mysql/examples/1-connect.php  ÃÅa  OÃ‰a¤      A   vendor/phabel-transpiler74.amphp/mysql/examples/6-transaction.phpS  ÃÅaS  à¼*ò¤      B   vendor/phabel-transpiler74.amphp/mysql/examples/2-simple-query.phpÈ  ÃÅaÈ  Àx¤      4   vendor/phabel-transpiler74.amphp/mysql/phpbench.jsonh   ÃÅah   #”š¼¤      4   vendor/phabel-transpiler74.amphp/mysql/composer.jsons  ÃÅas   * ¤      A   vendor/phabel-transpiler74.amphp/file/src/Sync/AsyncFileMutex.php^  ÃÅa^  ÿ\ôª¤      4   vendor/phabel-transpiler74.amphp/file/src/Driver.phpÇ  ÃÅaÇ  ±Â¿¸¤      ?   vendor/phabel-transpiler74.amphp/file/src/Internal/FileTask.phpù  ÃÅaù  ªëž*¤      >   vendor/phabel-transpiler74.amphp/file/src/Internal/EioPoll.php‚  ÃÅa‚  iM–>¤      =   vendor/phabel-transpiler74.amphp/file/src/Internal/UvPoll.phpF  ÃÅaF  Ónì¤      <   vendor/phabel-transpiler74.amphp/file/src/Internal/Cache.phpÁ  ÃÅaÁ  ö”¹±¤      A   vendor/phabel-transpiler74.amphp/file/src/Driver/BlockingFile.php}  ÃÅa}  æ&!Y¤      A   vendor/phabel-transpiler74.amphp/file/src/Driver/ParallelFile.php<  ÃÅa<  cp¤      >   vendor/phabel-transpiler74.amphp/file/src/Driver/EioDriver.phpÿ;  ÃÅaÿ;  Q´âž¤      ;   vendor/phabel-transpiler74.amphp/file/src/Driver/UvFile.php«"  ÃÅa«"  ÷³­�¤      H   vendor/phabel-transpiler74.amphp/file/src/Driver/StatusCachingDriver.php’  ÃÅa’  Ìû€7¤      <   vendor/phabel-transpiler74.amphp/file/src/Driver/EioFile.php[!  ÃÅa[!  ƒ/æR¤      C   vendor/phabel-transpiler74.amphp/file/src/Driver/ParallelDriver.php�  ÃÅa�  lÌÈ…¤      C   vendor/phabel-transpiler74.amphp/file/src/Driver/BlockingDriver.php×-  ÃÅa×-  Mv¦à¤      F   vendor/phabel-transpiler74.amphp/file/src/Driver/StatusCachingFile.php  ÃÅa  bf ¤      =   vendor/phabel-transpiler74.amphp/file/src/Driver/UvDriver.phpF  ÃÅaF  å˜°¤      2   vendor/phabel-transpiler74.amphp/file/src/File.phpâ	  ÃÅaâ	  ŽRO»¤      C   vendor/phabel-transpiler74.amphp/file/src/PendingOperationError.phpU  ÃÅaU  �Úb�¤      A   vendor/phabel-transpiler74.amphp/file/src/FilesystemException.phpò   ÃÅaò   a%ê¤      7   vendor/phabel-transpiler74.amphp/file/src/functions.phpF&  ÃÅaF&  aàª¤      8   vendor/phabel-transpiler74.amphp/file/src/Filesystem.phpM-  ÃÅaM-  rHI¤      3   vendor/phabel-transpiler74.amphp/file/composer.jsoni  ÃÅai  š¶ø�¤      F   vendor/phabel-transpiler74.amphp/file/test/Sync/AsyncFileMutexTest.phpz  ÃÅaz  ÒY!•¤      =   vendor/phabel-transpiler74.amphp/file/test/FilesystemTest.phpt  ÃÅat  ´¤~½¤      <   vendor/phabel-transpiler74.amphp/file/test/AsyncFileTest.php¬  ÃÅa¬  lAÓ¦¤      K   vendor/phabel-transpiler74.amphp/file/test/Driver/StatusCachingFileTest.phpG  ÃÅaG  Ò¹¼¤      A   vendor/phabel-transpiler74.amphp/file/test/Driver/EioFileTest.php¤  ÃÅa¤  „JÑ}¤      M   vendor/phabel-transpiler74.amphp/file/test/Driver/StatusCachingDriverTest.phpM  ÃÅaM  `é½Q¤      C   vendor/phabel-transpiler74.amphp/file/test/Driver/EioDriverTest.php   ÃÅa   ™,Z¤      F   vendor/phabel-transpiler74.amphp/file/test/Driver/ParallelFileTest.php8  ÃÅa8  Ÿ¸2¤      H   vendor/phabel-transpiler74.amphp/file/test/Driver/ParallelDriverTest.php4  ÃÅa4  i11C¤      B   vendor/phabel-transpiler74.amphp/file/test/Driver/UvDriverTest.phps  ÃÅas  ÍW¤¤      H   vendor/phabel-transpiler74.amphp/file/test/Driver/BlockingDriverTest.php#  ÃÅa#  °IU9¤      F   vendor/phabel-transpiler74.amphp/file/test/Driver/BlockingFileTest.php  ÃÅa  Kl¦¤      @   vendor/phabel-transpiler74.amphp/file/test/Driver/UvFileTest.phpÜ  ÃÅaÜ  Æ;à¤      7   vendor/phabel-transpiler74.amphp/file/test/FileTest.php£!  ÃÅa£!  é�´¤      9   vendor/phabel-transpiler74.amphp/file/test/DriverTest.phpdE  ÃÅadE  i	·*¤      6   vendor/phabel-transpiler74.amphp/file/test/Fixture.php¬	  ÃÅa¬	  ®| ¤      =   vendor/phabel-transpiler74.amphp/sql/src/ConnectionConfig.phpý  ÃÅaý  6´µ¶¤      6   vendor/phabel-transpiler74.amphp/sql/src/PoolError.php=   ÃÅa=   �Lø¤      =   vendor/phabel-transpiler74.amphp/sql/src/FailureException.phpH   ÃÅaH   ˆXd¼¤      >   vendor/phabel-transpiler74.amphp/sql/src/TransientResource.phpi  ÃÅai  ÁØM­¤      =   vendor/phabel-transpiler74.amphp/sql/src/TransactionError.phpD   ÃÅaD   ŠIf¨¤      7   vendor/phabel-transpiler74.amphp/sql/src/QueryError.php&  ÃÅa&  €•pÇ¤      1   vendor/phabel-transpiler74.amphp/sql/src/Pool.phpÜ  ÃÅaÜ  S§G¤      @   vendor/phabel-transpiler74.amphp/sql/src/ConnectionException.phpQ   ÃÅaQ   ZX›"¤      6   vendor/phabel-transpiler74.amphp/sql/src/Connector.phpå   ÃÅaå   •xk¤      6   vendor/phabel-transpiler74.amphp/sql/src/ResultSet.phpÜ   ÃÅaÜ   W·Wº¤      5   vendor/phabel-transpiler74.amphp/sql/src/Executor.phpF  ÃÅaF  À„ï¤      1   vendor/phabel-transpiler74.amphp/sql/src/Link.phpb  ÃÅab  SdÆ¤      8   vendor/phabel-transpiler74.amphp/sql/src/Transaction.phpÆ  ÃÅaÆ  /îÊª¤      :   vendor/phabel-transpiler74.amphp/sql/src/CommandResult.phpÊ   ÃÅaÊ   ÆÝž¼¤      6   vendor/phabel-transpiler74.amphp/sql/src/Statement.php~  ÃÅa~  ¹N“ø¤      2   vendor/phabel-transpiler74.amphp/sql/composer.jsonÐ  ÃÅaÐ  nYö¤      <   vendor/phabel-transpiler74.amphp/sql/test/QueryErrorTest.phpÐ  ÃÅaÐ  ®Ê
¤      @   vendor/phabel-transpiler74.amphp/websocket/src/Rfc6455Client.phpƒ  ÃÅaƒ  áÛ~á¤      L   vendor/phabel-transpiler74.amphp/websocket/src/Rfc7692CompressionFactory.php|  ÃÅa|  Ùâ¬¤      L   vendor/phabel-transpiler74.amphp/websocket/src/CompressionContextFactory.php}  ÃÅa}  S[aY¤      :   vendor/phabel-transpiler74.amphp/websocket/src/Message.php™  ÃÅa™  T�7[¤      :   vendor/phabel-transpiler74.amphp/websocket/src/Options.php/  ÃÅa/  Ã=¤      A   vendor/phabel-transpiler74.amphp/websocket/src/ClientMetadata.php´  ÃÅa´  Ç Ÿ¤      9   vendor/phabel-transpiler74.amphp/websocket/src/Client.phpr  ÃÅar  6:nˆ¤      E   vendor/phabel-transpiler74.amphp/websocket/src/CompressionContext.php8  ÃÅa8  3wGò¤      <   vendor/phabel-transpiler74.amphp/websocket/src/functions.phpÛ  ÃÅaÛ  tE¤      7   vendor/phabel-transpiler74.amphp/websocket/src/Code.php4  ÃÅa4  ÈEŒ6¤      B   vendor/phabel-transpiler74.amphp/websocket/src/ClosedException.php  ÃÅa  ¢à<¤      9   vendor/phabel-transpiler74.amphp/websocket/src/Opcode.phpw  ÃÅaw  ¯ k¤      E   vendor/phabel-transpiler74.amphp/websocket/src/Rfc7692Compression.phpÒ  ÃÅaÒ  0îÒÛ¤      8   vendor/phabel-transpiler74.amphp/websocket/composer.jsonÇ  ÃÅaÇ  1»Šö¤      G   vendor/phabel-transpiler74.amphp/serialization/src/NativeSerializer.php!  ÃÅa!  òÄü¶¤      E   vendor/phabel-transpiler74.amphp/serialization/src/JsonSerializer.phpu
  ÃÅau
  œÜ *¤      A   vendor/phabel-transpiler74.amphp/serialization/src/Serializer.phpš  ÃÅaš  Æ¼p7¤      L   vendor/phabel-transpiler74.amphp/serialization/src/CompressingSerializer.php  ÃÅa  Å¥›w¤      L   vendor/phabel-transpiler74.amphp/serialization/src/PassthroughSerializer.phpÂ  ÃÅaÂ  óq&J¤      @   vendor/phabel-transpiler74.amphp/serialization/src/functions.php]  ÃÅa]  Wá/2¤      M   vendor/phabel-transpiler74.amphp/serialization/src/SerializationException.phpX   ÃÅaX   V¸¹!¤      <   vendor/phabel-transpiler74.amphp/serialization/composer.jsonÀ  ÃÅaÀ  òq4¤      :   vendor/phabel-transpiler74.amphp/byte-stream/composer.jsonq  ÃÅaq  �Räß¤      U   vendor/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64DecodingInputStream.phpB  ÃÅaB  ­ÍR¤      V   vendor/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.php  ÃÅa  e¦ö¤      V   vendor/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php  ÃÅa  °AìU¤      U   vendor/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php–  ÃÅa–  ¤      C   vendor/phabel-transpiler74.amphp/byte-stream/lib/IteratorStream.php¤  ÃÅa¤  ¼�¤      I   vendor/phabel-transpiler74.amphp/byte-stream/lib/ResourceOutputStream.php*  ÃÅa*  %Ñô¤      A   vendor/phabel-transpiler74.amphp/byte-stream/lib/OutputStream.php  ÃÅa  TsŠÕ¤      E   vendor/phabel-transpiler74.amphp/byte-stream/lib/InputStreamChain.phpr  ÃÅar  ý:Ö¤      <   vendor/phabel-transpiler74.amphp/byte-stream/lib/Message.php  ÃÅa  µƒâd¤      @   vendor/phabel-transpiler74.amphp/byte-stream/lib/InputStream.php$  ÃÅa$  ÅmŠ¤      H   vendor/phabel-transpiler74.amphp/byte-stream/lib/ResourceInputStream.phpà  ÃÅaà  •y ß¤      D   vendor/phabel-transpiler74.amphp/byte-stream/lib/ZlibInputStream.phpD  ÃÅaD  y!d¤      D   vendor/phabel-transpiler74.amphp/byte-stream/lib/StreamException.phpN   ÃÅaN   C)Ì«¤      ?   vendor/phabel-transpiler74.amphp/byte-stream/lib/LineReader.phpõ  ÃÅaõ  hf„¤      >   vendor/phabel-transpiler74.amphp/byte-stream/lib/functions.php  ÃÅa  ‘Ûûd¤      D   vendor/phabel-transpiler74.amphp/byte-stream/lib/ClosedException.phpY   ÃÅaY   �vJI¤      <   vendor/phabel-transpiler74.amphp/byte-stream/lib/Payload.php¯	  ÃÅa¯	  MØÏÅ¤      E   vendor/phabel-transpiler74.amphp/byte-stream/lib/PendingReadError.phpÆ  ÃÅaÆ  M-€‡¤      E   vendor/phabel-transpiler74.amphp/byte-stream/lib/ZlibOutputStream.php=  ÃÅa=  ’±¤Õ¤      A   vendor/phabel-transpiler74.amphp/byte-stream/lib/OutputBuffer.phpÕ  ÃÅaÕ  áq¤      C   vendor/phabel-transpiler74.amphp/byte-stream/lib/InMemoryStream.phpG  ÃÅaG  ë„ê¤      2   vendor/phabel-transpiler74.amphp/dns/composer.json@  ÃÅa@  ƒœð¤      ?   vendor/phabel-transpiler74.amphp/dns/lib/Internal/TcpSocket.php  ÃÅa  n¢–D¤      ?   vendor/phabel-transpiler74.amphp/dns/lib/Internal/UdpSocket.phpK  ÃÅaK  Ò¶Úñ¤      <   vendor/phabel-transpiler74.amphp/dns/lib/Internal/Socket.php§  ÃÅa§  +‚kÃ¤      =   vendor/phabel-transpiler74.amphp/dns/lib/UnixConfigLoader.php   ÃÅa   µÿ@J¤      3   vendor/phabel-transpiler74.amphp/dns/lib/Config.php*  ÃÅa*  G•�¤      9   vendor/phabel-transpiler74.amphp/dns/lib/ConfigLoader.php‰   ÃÅa‰   Q`Þ¤      <   vendor/phabel-transpiler74.amphp/dns/lib/ConfigException.phpV  ÃÅaV  i÷û¤      5   vendor/phabel-transpiler74.amphp/dns/lib/Resolver.php  ÃÅa  ËÏE¤      @   vendor/phabel-transpiler74.amphp/dns/lib/WindowsConfigLoader.php  ÃÅa  sŠm¤      >   vendor/phabel-transpiler74.amphp/dns/lib/NoRecordException.phpK   ÃÅaK   ºq=´¤      E   vendor/phabel-transpiler74.amphp/dns/lib/BlockingFallbackResolver.php  ÃÅa  Ä>õ¤      6   vendor/phabel-transpiler74.amphp/dns/lib/functions.php¹
  ÃÅa¹
  év#Î¤      9   vendor/phabel-transpiler74.amphp/dns/lib/DnsException.phpD   ÃÅaD   ®Äú¤      =   vendor/phabel-transpiler74.amphp/dns/lib/TimeoutException.phpJ   ÃÅaJ   ¯._w¤      A   vendor/phabel-transpiler74.amphp/dns/lib/InvalidNameException.phpN   ÃÅaN   Lš3¤      3   vendor/phabel-transpiler74.amphp/dns/lib/Record.php±  ÃÅa±  kƒi¤      7   vendor/phabel-transpiler74.amphp/dns/lib/HostLoader.phpt	  ÃÅat	  ¬€L¤      @   vendor/phabel-transpiler74.amphp/dns/lib/Rfc1035StubResolver.php«L  ÃÅa«L  ŸMçó¤      B   vendor/phabel-transpiler74.amphp/postgres/src/ConnectionConfig.phpå
  ÃÅaå
  v‡w-¤      G   vendor/phabel-transpiler74.amphp/postgres/src/ConnectionTransaction.php·   ÃÅa·   �9æ¤      =   vendor/phabel-transpiler74.amphp/postgres/src/PqStatement.php  ÃÅa  ÏTPù¤      A   vendor/phabel-transpiler74.amphp/postgres/src/PooledStatement.php¬  ÃÅa¬  Oêˆ£¤      @   vendor/phabel-transpiler74.amphp/postgres/src/PgSqlResultSet.php™  ÃÅa™  vï}¤      E   vendor/phabel-transpiler74.amphp/postgres/src/PqBufferedResultSet.phpŸ  ÃÅaŸ  ¡û»_¤      D   vendor/phabel-transpiler74.amphp/postgres/src/PgSqlCommandResult.php0  ÃÅa0  #ÇB ¤      @   vendor/phabel-transpiler74.amphp/postgres/src/ParseException.phpR  ÃÅaR  ïª~Ã¤      :   vendor/phabel-transpiler74.amphp/postgres/src/Receiver.php  ÃÅa  -3f7¤      >   vendor/phabel-transpiler74.amphp/postgres/src/PqConnection.php›  ÃÅa›  U@ Ž¤      D   vendor/phabel-transpiler74.amphp/postgres/src/ConnectionListener.phpë  ÃÅaë  Û#®ò¤      B   vendor/phabel-transpiler74.amphp/postgres/src/TimeoutConnector.php_  ÃÅa_  s7aÜ¤      A   vendor/phabel-transpiler74.amphp/postgres/src/PgSqlConnection.php±  ÃÅa±  íy{e¤      :   vendor/phabel-transpiler74.amphp/postgres/src/PqHandle.phpG>  ÃÅaG>  ö�2¤      8   vendor/phabel-transpiler74.amphp/postgres/src/Quoter.phpU  ÃÅaU  •’�º¤      A   vendor/phabel-transpiler74.amphp/postgres/src/PqCommandResult.php;  ÃÅa;  }e>¤      D   vendor/phabel-transpiler74.amphp/postgres/src/Internal/functions.phpF
  ÃÅaF
  Ýê`<¤      F   vendor/phabel-transpiler74.amphp/postgres/src/Internal/ArrayParser.php¸  ÃÅa¸  cd„Ë¤      @   vendor/phabel-transpiler74.amphp/postgres/src/PgSqlStatement.php´  ÃÅa´  Ëp/¤      6   vendor/phabel-transpiler74.amphp/postgres/src/Pool.php×  ÃÅa×  b°g§¤      ?   vendor/phabel-transpiler74.amphp/postgres/src/StatementPool.php†  ÃÅa†  z¸Y¤      <   vendor/phabel-transpiler74.amphp/postgres/src/Connection.phpž  ÃÅaž  õ;™Ó¤      @   vendor/phabel-transpiler74.amphp/postgres/src/PooledListener.phpû  ÃÅaû  ¶±äM¤      ;   vendor/phabel-transpiler74.amphp/postgres/src/ResultSet.php  ÃÅa  ÎÁlî¤      :   vendor/phabel-transpiler74.amphp/postgres/src/Executor.php.  ÃÅa.  Ã�®ý¤      6   vendor/phabel-transpiler74.amphp/postgres/src/Link.phpi   ÃÅai   R3‹£¤      =   vendor/phabel-transpiler74.amphp/postgres/src/Transaction.php  ÃÅa  ×²E¤      ;   vendor/phabel-transpiler74.amphp/postgres/src/functions.phpŽ  ÃÅaŽ  Ïì#&¤      C   vendor/phabel-transpiler74.amphp/postgres/src/PooledTransaction.phpÙ  ÃÅaÙ  X°M?¤      E   vendor/phabel-transpiler74.amphp/postgres/src/QueryExecutionError.php  ÃÅa  Mñè<¤      8   vendor/phabel-transpiler74.amphp/postgres/src/Handle.phpw   ÃÅaw   GMö¤      :   vendor/phabel-transpiler74.amphp/postgres/src/Listener.php!  ÃÅa!  ž—¤      A   vendor/phabel-transpiler74.amphp/postgres/src/PooledResultSet.phpG  ÃÅaG  òš-Ÿ¤      G   vendor/phabel-transpiler74.amphp/postgres/src/PqUnbufferedResultSet.phpN	  ÃÅaN	  #îÀ¤      =   vendor/phabel-transpiler74.amphp/postgres/src/PgSqlHandle.php…B  ÃÅa…B  X E¡¤      >   vendor/phabel-transpiler74.amphp/postgres/src/Notification.php  ÃÅa  :õ’Ì¤      B   vendor/phabel-transpiler74.amphp/postgres/examples/transaction.php¾  ÃÅa¾  ž0¤      C   vendor/phabel-transpiler74.amphp/postgres/examples/multi-listen.php‰  ÃÅa‰  (÷?¤      =   vendor/phabel-transpiler74.amphp/postgres/examples/listen.php¾  ÃÅa¾  Vˆt÷¤      <   vendor/phabel-transpiler74.amphp/postgres/examples/basic.phpS  ÃÅaS  VHc¤      7   vendor/phabel-transpiler74.amphp/postgres/composer.jsonX  ÃÅaX  �ø{î¤      C   vendor/phabel-transpiler74.amphp/sql-common/src/PooledStatement.php	  ÃÅa	  Öw•¤      B   vendor/phabel-transpiler74.amphp/sql-common/src/RetryConnector.php@  ÃÅa@  õ}úÕ¤      B   vendor/phabel-transpiler74.amphp/sql-common/src/ConnectionPool.php¯1  ÃÅa¯1  �™§¤      A   vendor/phabel-transpiler74.amphp/sql-common/src/StatementPool.phpS  ÃÅaS  )�¤      E   vendor/phabel-transpiler74.amphp/sql-common/src/PooledTransaction.phpâ  ÃÅaâ  rF;Ÿ¤      C   vendor/phabel-transpiler74.amphp/sql-common/src/PooledResultSet.php7  ÃÅa7  £ù�S¤      9   vendor/phabel-transpiler74.amphp/sql-common/composer.jsonØ  ÃÅaØ  �)Û¤      G   vendor/phabel-transpiler74.amphp/sql-common/test/RetryConnectorTest.phpz  ÃÅaz  á(†¤      H   vendor/phabel-transpiler74.amphp/sql-common/test/PooledResultSetTest.php8  ÃÅa8  "TEq¤      G   vendor/phabel-transpiler74.amphp/sql-common/test/ConnectionPoolTest.phpÂ  ÃÅaÂ  å~�7¤      F   vendor/phabel-transpiler74.amphp/sql-common/test/StatementPoolTest.phpC  ÃÅaC  ýÔâ¦¤      5   vendor/phabel-transpiler74.amphp/parser/composer.json›  ÃÅa›  Ørá¤      E   vendor/phabel-transpiler74.amphp/parser/lib/InvalidDelimiterError.php÷  ÃÅa÷  ý4Ô´¤      6   vendor/phabel-transpiler74.amphp/parser/lib/Parser.php„  ÃÅa„  IZ€¤      C   vendor/phabel-transpiler74.amphp/hpack/src/Internal/HPackNative.phpôk  ÃÅaôk   N+¤      D   vendor/phabel-transpiler74.amphp/hpack/src/Internal/HPackNghttp2.php"  ÃÅa"  EÌl¤      F   vendor/phabel-transpiler74.amphp/hpack/src/Internal/huffman-lookup.php‘ ÃÅa‘ Äè�—¤      ?   vendor/phabel-transpiler74.amphp/hpack/src/Internal/amp-hpack.hŸ  ÃÅaŸ  ÆF=a¤      E   vendor/phabel-transpiler74.amphp/hpack/src/Internal/huffman-codes.php¬ ÃÅa¬ -ÁÓ0¤      =   vendor/phabel-transpiler74.amphp/hpack/src/HPackException.phpM   ÃÅaM   ð �¤      4   vendor/phabel-transpiler74.amphp/hpack/src/HPack.php@  ÃÅa@  ¹¤      9   vendor/phabel-transpiler74.amphp/hpack/examples/bench.php'  ÃÅa'  ›:Ê¤      B   vendor/phabel-transpiler74.amphp/hpack/tools/php-fuzzer/decode.php¿   ÃÅa¿   ´êª¼¤      H   vendor/phabel-transpiler74.amphp/hpack/tools/php-fuzzer/decode-crash.php…   ÃÅa…   Ô— À¤      9   vendor/phabel-transpiler74.amphp/hpack/tools/compress.php  ÃÅa  Ó|ô`¤      4   vendor/phabel-transpiler74.amphp/hpack/composer.jsonÑ  ÃÅaÑ  7OÇæ¤      ?   vendor/phabel-transpiler74.amphp/socket/src/SocketException.phps   ÃÅas   N>—¤      >   vendor/phabel-transpiler74.amphp/socket/src/DatagramSocket.phpM  ÃÅaM  pV­­¤      C   vendor/phabel-transpiler74.amphp/socket/src/UnlimitedSocketPool.php˜  ÃÅa˜  ZÌ•8¤      B   vendor/phabel-transpiler74.amphp/socket/src/Internal/functions.php­  ÃÅa­  Trwn¤      7   vendor/phabel-transpiler74.amphp/socket/src/TlsInfo.phpt  ÃÅat  8ân2¤      >   vendor/phabel-transpiler74.amphp/socket/src/ConnectContext.php©  ÃÅa©  *eP=¤      <   vendor/phabel-transpiler74.amphp/socket/src/TlsException.php«   ÃÅa«   Ð£#¤      9   vendor/phabel-transpiler74.amphp/socket/src/Connector.php¸  ÃÅa¸  Çæ¶W¤      C   vendor/phabel-transpiler74.amphp/socket/src/PendingReceiveError.phpÎ  ÃÅaÎ  gJX¤      @   vendor/phabel-transpiler74.amphp/socket/src/ServerTlsContext.phpÐ3  ÃÅaÐ3  '·l�¤      ;   vendor/phabel-transpiler74.amphp/socket/src/BindContext.php™  ÃÅa™  Ãäµ¤      B   vendor/phabel-transpiler74.amphp/socket/src/PendingAcceptError.phpÈ  ÃÅaÈ  ýÆ¤      @   vendor/phabel-transpiler74.amphp/socket/src/ConnectException.phpw   ÃÅaw   Ì“"!¤      ?   vendor/phabel-transpiler74.amphp/socket/src/StaticConnector.php¡  ÃÅa¡  êžÂž¤      >   vendor/phabel-transpiler74.amphp/socket/src/ResourceSocket.php  ÃÅa  X“„&¤      =   vendor/phabel-transpiler74.amphp/socket/src/SocketAddress.php 
  ÃÅa 
  ¾(œ€¤      9   vendor/phabel-transpiler74.amphp/socket/src/functions.php-  ÃÅa-  z Ñž¤      @   vendor/phabel-transpiler74.amphp/socket/src/ClientTlsContext.phpö/  ÃÅaö/  �Â¹Ô¤      A   vendor/phabel-transpiler74.amphp/socket/src/EncryptableSocket.php   ÃÅa   Ö>–¤      6   vendor/phabel-transpiler74.amphp/socket/src/Socket.php  ÃÅa  ãA¤      <   vendor/phabel-transpiler74.amphp/socket/src/DnsConnector.php.  ÃÅa.  À‘…¤      ;   vendor/phabel-transpiler74.amphp/socket/src/Certificate.php  ÃÅa  ¿\Ã¤      :   vendor/phabel-transpiler74.amphp/socket/src/SocketPool.php5  ÃÅa5  ö›�¤      6   vendor/phabel-transpiler74.amphp/socket/src/Server.php€  ÃÅa€  íÅ¤      5   vendor/phabel-transpiler74.amphp/socket/composer.jsont  ÃÅat  ™«ß¤      A   vendor/phabel-transpiler74.amphp/sync/composer-require-check.jsonû  ÃÅaû  *×ÀX¤      D   vendor/phabel-transpiler74.amphp/sync/src/PrefixedKeyedSemaphore.php  ÃÅa  +é„/¤      A   vendor/phabel-transpiler74.amphp/sync/src/LocalKeyedSemaphore.phpC  ÃÅaC  �þ'¤      7   vendor/phabel-transpiler74.amphp/sync/src/Semaphore.php×  ÃÅa×  äù5b¤      G   vendor/phabel-transpiler74.amphp/sync/src/Internal/SemaphoreStorage.phpZ  ÃÅaZ  ÚÆ!¤      C   vendor/phabel-transpiler74.amphp/sync/src/Internal/MutexStorage.phpX  ÃÅaX  .òf¤      ;   vendor/phabel-transpiler74.amphp/sync/src/SyncException.phpF   ÃÅaF   =rE¤      J   vendor/phabel-transpiler74.amphp/sync/src/ConcurrentIterator/functions.phpç  ÃÅaç  ôü¤      3   vendor/phabel-transpiler74.amphp/sync/src/Mutex.php¢  ÃÅa¢  qšÏs¤      ?   vendor/phabel-transpiler74.amphp/sync/src/ThreadedSemaphore.php©  ÃÅa©  Üæ�¤      <   vendor/phabel-transpiler74.amphp/sync/src/StaticKeyMutex.phpÎ  ÃÅaÎ  u¤ëŠ¤      <   vendor/phabel-transpiler74.amphp/sync/src/PosixSemaphore.phpr  ÃÅar  3'‰
¤      =   vendor/phabel-transpiler74.amphp/sync/src/LocalKeyedMutex.phpn  ÃÅan  b»UÃ¤      5   vendor/phabel-transpiler74.amphp/sync/src/Barrier.phpþ  ÃÅaþ  -¼ºˆ¤      <   vendor/phabel-transpiler74.amphp/sync/src/LocalSemaphore.phpÊ  ÃÅaÊ  –Í+d¤      @   vendor/phabel-transpiler74.amphp/sync/src/PrefixedKeyedMutex.phpø  ÃÅaø  È[dY¤      ;   vendor/phabel-transpiler74.amphp/sync/src/ThreadedMutex.php¤  ÃÅa¤  ï¤      <   vendor/phabel-transpiler74.amphp/sync/src/KeyedSemaphore.php  ÃÅa  �;“©¤      7   vendor/phabel-transpiler74.amphp/sync/src/FileMutex.php­  ÃÅa­  ¦ÀÀ¤      2   vendor/phabel-transpiler74.amphp/sync/src/Lock.phpÏ  ÃÅaÏ  Õõ¡°¤      <   vendor/phabel-transpiler74.amphp/sync/src/SemaphoreMutex.php   ÃÅa   2£()¤      7   vendor/phabel-transpiler74.amphp/sync/src/functions.phph  ÃÅah  Ôël¤¤      8   vendor/phabel-transpiler74.amphp/sync/src/LocalMutex.php®  ÃÅa®   å£È¤      8   vendor/phabel-transpiler74.amphp/sync/src/KeyedMutex.phpí  ÃÅaí  Ž¶nŸ¤      3   vendor/phabel-transpiler74.amphp/sync/composer.json5  ÃÅa5  ;îí      4   vendor/phabel-transpiler74.amphp/cache/composer.jsonc  ÃÅac  |œi¤      9   vendor/phabel-transpiler74.amphp/cache/lib/ArrayCache.php…  ÃÅa…  $Ô¨Ä¤      >   vendor/phabel-transpiler74.amphp/cache/lib/SerializedCache.php*
  ÃÅa*
  â ‘S¤      :   vendor/phabel-transpiler74.amphp/cache/lib/AtomicCache.phpG#  ÃÅaG#  ¶®Œ®¤      8   vendor/phabel-transpiler74.amphp/cache/lib/NullCache.php�  ÃÅa�  J5ž¤      8   vendor/phabel-transpiler74.amphp/cache/lib/FileCache.phpÂ  ÃÅaÂ  V¤À;¤      :   vendor/phabel-transpiler74.amphp/cache/lib/PrefixCache.phpÛ  ÃÅaÛ  ­Aå¤      =   vendor/phabel-transpiler74.amphp/cache/lib/CacheException.phpƒ   ÃÅaƒ   †æºq¤      4   vendor/phabel-transpiler74.amphp/cache/lib/Cache.phpw  ÃÅaw  )åÖ¤      :   vendor/phabel-transpiler74.amphp/log/src/StreamHandler.phpÒ  ÃÅaÒ  ëª´¿¤      6   vendor/phabel-transpiler74.amphp/log/src/functions.phpA  ÃÅaA  %ê—ø¤      =   vendor/phabel-transpiler74.amphp/log/src/ConsoleFormatter.phpÛ	  ÃÅaÛ	  ¨w×Œ¤      =   vendor/phabel-transpiler74.amphp/log/examples/hello-world.php
  ÃÅa
  2Kåº¤      2   vendor/phabel-transpiler74.amphp/log/composer.jsonó  ÃÅaó  6¨W¤      0   vendor/psr/http-message/src/RequestInterface.php(  ÃÅa(  c—"¤      5   vendor/psr/http-message/src/UploadedFileInterface.php¢  ÃÅa¢  ×ƒ%¤      6   vendor/psr/http-message/src/ServerRequestInterface.php;&  ÃÅa;&  åô¤      ,   vendor/psr/http-message/src/UriInterface.php /  ÃÅa /  îÑžì¤      0   vendor/psr/http-message/src/MessageInterface.php×  ÃÅa×  ªƒù¤      1   vendor/psr/http-message/src/ResponseInterface.phpØ	  ÃÅaØ	  jçôË¤      /   vendor/psr/http-message/src/StreamInterface.php
  ÃÅa
  >OÊ¤      %   vendor/psr/http-message/composer.jsonm  ÃÅam  ™Š„¤      3   vendor/psr/http-factory/src/UriFactoryInterface.phpE  ÃÅaE  Ý”—"¤      7   vendor/psr/http-factory/src/RequestFactoryInterface.phpâ  ÃÅaâ  Ð÷hO¤      8   vendor/psr/http-factory/src/ResponseFactoryInterface.php  ÃÅa  Gðrm¤      =   vendor/psr/http-factory/src/ServerRequestFactoryInterface.php~  ÃÅa~  ±XôÒ¤      6   vendor/psr/http-factory/src/StreamFactoryInterface.phpz  ÃÅaz  Ó}ôl¤      <   vendor/psr/http-factory/src/UploadedFileFactoryInterface.php  ÃÅa  (>o-¤      %   vendor/psr/http-factory/composer.json¼  ÃÅa¼  2Ðd=¤         vendor/psr/log/composer.json2  ÃÅa2  çÕžÚ¤      %   vendor/psr/log/Psr/Log/NullLogger.phpÀ  ÃÅaÀ  Ô$²{¤      +   vendor/psr/log/Psr/Log/LoggerAwareTrait.php�  ÃÅa�  rÖ?ã¤      )   vendor/psr/log/Psr/Log/Test/DummyTest.php  ÃÅa  Ì£"U¤      *   vendor/psr/log/Psr/Log/Test/TestLogger.php  ÃÅa  dó…*¤      3   vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.phpw  ÃÅaw  D—z¤      )   vendor/psr/log/Psr/Log/AbstractLogger.phpî  ÃÅaî  *!]4¤      *   vendor/psr/log/Psr/Log/LoggerInterface.phpô  ÃÅaô  „)Å ¤      #   vendor/psr/log/Psr/Log/LogLevel.php8  ÃÅa8  ˆo–ë¤      &   vendor/psr/log/Psr/Log/LoggerTrait.php"  ÃÅa"  2Çì…¤      3   vendor/psr/log/Psr/Log/InvalidArgumentException.php_   ÃÅa_   ‚¿l9¤      /   vendor/psr/log/Psr/Log/LoggerAwareInterface.php(  ÃÅa(  œé¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogmaticHandler.phpå  ÃÅaå  ¨ í>¤      N   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NoopHandler.phpp  ÃÅap  o¿p�¤      N   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AmqpHandler.php  ÃÅa  Fe°¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DynamoDbHandler.phpŸ	  ÃÅaŸ	  Ê\ÇV¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/CouchDBHandler.phpb  ÃÅab  kx,Ò¤      W   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.phpµ  ÃÅaµ  ŸQ:¤      X   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php�   ÃÅa�   Uõ§¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RollbarHandler.phpÅ  ÃÅaÅ  /XJÕ¤      Y   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php•  ÃÅa•  §¿Úz¤      \   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php  ÃÅa  )®ò¤      U   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.phpø  ÃÅaø  :øVî¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SendGridHandler.php#  ÃÅa#  Al+Í¤      N   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/GelfHandler.phps  ÃÅas  v_q¤      P   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/BufferHandler.php9  ÃÅa9  Úêô«¤      N   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NullHandler.php@  ÃÅa@  ÏVµÊ¤      \   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MissingExtensionException.phpØ  ÃÅaØ  7ñÉT¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ErrorLogHandler.phpî	  ÃÅaî	  7š1¼¤      P   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogglyHandler.phpW  ÃÅaW  i÷èÉ¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FirePHPHandler.phpD  ÃÅaD   ºüï¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.phpO  ÃÅaO  ;³§”¤      M   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PsrHandler.php	  ÃÅa	  ù›Œ�¤      U   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.phpX  ÃÅaX  Ej5u¤      ^   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.phpI  ÃÅaI  ¸˜ÕD¤      n   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.phpl  ÃÅal  Ðqì¤      p   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php‘	  ÃÅa‘	  ¿3¤      m   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.phpÐ  ÃÅaÐ  @â¤      N   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/TestHandler.phpn  ÃÅan  ˆ¨˜¤      Z   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.phpý  ÃÅaý  ÌÕ–„¤      P   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FilterHandler.phpª  ÃÅaª  ÇòP¤      P   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogHandler.php-  ÃÅa-  à!éû¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RotatingFileHandler.phpÝ  ÃÅaÝ   [á¤      Z   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.phpÚ  ÃÅaÚ  EL«¶¤      T   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php)  ÃÅa)  ÐÿK¤      P   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SocketHandler.php,  ÃÅa,  ²4Ë=¤      S   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php  ÃÅa  UQË¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessHandler.php»  ÃÅa»  ²°uã¤      T   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogEntriesHandler.phpä  ÃÅaä  Æ	P¤      O   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/GroupHandler.php³  ÃÅa³  €�Õ¤      T   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php‚  ÃÅa‚  “ <¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SamplingHandler.php   ÃÅa   jãåÄ¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NativeMailerHandler.phpg  ÃÅag  ¿‡š£¤      S   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ChromePHPHandler.phpÙ  ÃÅaÙ  Îr˜r¤      S   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FleepHookHandler.phpM  ÃÅaM  3“4ò¤      N   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MailHandler.php7	  ÃÅa7	  qmjÜ¤      U   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/TelegramBotHandler.phpr  ÃÅar  Ò GX¤      J   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Handler.php0  ÃÅa0  >HŠâ¤      M   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SqsHandler.php�  ÃÅa�  (UfÕ¤      O   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RedisHandler.phpG  ÃÅaG  ABêè¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MongoDBHandler.phpø	  ÃÅaø	  ëËs<¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FlowdockHandler.php>  ÃÅa>  EÎ¤      N   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/CubeHandler.php  ÃÅa  J�K¤      ^   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php¦  ÃÅa¦  Ýd,æ¤      P   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/StreamHandler.phpã  ÃÅaã  "¯Ùõ¤      L   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Curl/Util.phpð  ÃÅað  O2¤ù¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ElasticaHandler.php–  ÃÅa–  LÔá‰¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/OverflowHandler.php)  ÃÅa)  @6ÂD¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NewRelicHandler.phpø  ÃÅaø  R�ž§¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PushoverHandler.php!  ÃÅa!  fNü¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractHandler.php+
  ÃÅa+
  \‘Éº¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php%  ÃÅa%  A9‹¤      S   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/HandlerInterface.phpƒ  ÃÅaƒ  Aâä¤      O   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/IFTTTHandler.php:  ÃÅa:  Ü/§¤      W   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.phpÞ  ÃÅaÞ  öëud¤      \   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.phps  ÃÅas  <:'È¤      U   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.phpç  ÃÅaç  úHz¤      O   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SlackHandler.php  ÃÅa  Ðméê¤      X   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.phpR  ÃÅaR  É¾ö¤      Z   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php‚  ÃÅa‚  Ö€ôÈ¤      W   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DeduplicationHandler.phpÂ  ÃÅaÂ  -•Ã¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MandrillHandler.phpi	  ÃÅai	  i·%ä¤      T   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php€'  ÃÅa€'  —êj¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/HandlerWrapper.phpB  ÃÅaB  rý|V¤      X   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php�   ÃÅa�   \æO|¤      N   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/ResettableInterface.phpë  ÃÅaë  ã7–¤      @   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Utils.phpP"  ÃÅaP"  ,­ÆÕ¤      H   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Test/TestCase.phpq  ÃÅaq  @W×Ì¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/WebProcessor.phpX  ÃÅaX  >_¤      Y   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php.  ÃÅa.  r`Ü{¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/UidProcessor.phpŽ  ÃÅaŽ  ´F˜›¤      T   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryProcessor.php  ÃÅa  šƒU"¤      W   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/ProcessorInterface.php   ÃÅa   T.�¶¤      W   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php^  ÃÅa^  ùœøV¤      ]   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.phpA  ÃÅaA  pÛÜ¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/HostnameProcessor.phpè  ÃÅaè  Q=ó¤      [   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php5  ÃÅa5  J0Ñ¤      W   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MercurialProcessor.php?  ÃÅa?  !Žå¬¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/GitProcessor.phpp  ÃÅap  €J(7¤      Q   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/TagProcessor.php]  ÃÅa]  ë+z—¤      [   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php  ÃÅa  g¤Ÿ¤      A   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Logger.php)G  ÃÅa)G  Ý—˜¤      L   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/DateTimeImmutable.php  ÃÅa  0É(¤      H   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/SignalHandler.phpü  ÃÅaü  gÐ·¤      C   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Registry.php  ÃÅa  ªÃ¸¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.phpQ	  ÃÅaQ	  TU»L¤      U   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FluentdFormatter.phpÕ  ÃÅaÕ  NÃË¤      T   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ScalarFormatter.phpv  ÃÅav  N³¿.¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php  ÃÅa  =Ä_Ê¤      U   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.phpã  ÃÅaã  «^Ça¤      X   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php¿  ÃÅa¿  é²à¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LineFormatter.php   ÃÅa   '‰ÿ¤      W   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.phpÃ  ÃÅaÃ  ã“Ï¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/JsonFormatter.phpª  ÃÅaª  AåžÛ¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php&  ÃÅa&  —&JA¤      W   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FormatterInterface.phpº  ÃÅaº  ¨¬Ô/¤      Y   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.phpþ  ÃÅaþ  Ö¤      R   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php>  ÃÅa>  ZVÍ±¤      T   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php  ÃÅa  8î:ù¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/WildfireFormatter.phpg  ÃÅag  T?Q/¤      [   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php;  ÃÅa;  Û£TÝ¤      V   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.phpó  ÃÅaó  @Š¯¤      G   vendor/phabel-transpiler74.monolog/monolog/src/Monolog/ErrorHandler.php%'  ÃÅa%'  ÿ°"¤      8   vendor/phabel-transpiler74.monolog/monolog/composer.jsoné  ÃÅaé  ·Lß�¤      D   vendor/phabel-transpiler74.psr/http-message/src/RequestInterface.php(  ÃÅa(  c—"¤      I   vendor/phabel-transpiler74.psr/http-message/src/UploadedFileInterface.php¢  ÃÅa¢  ×ƒ%¤      J   vendor/phabel-transpiler74.psr/http-message/src/ServerRequestInterface.php;&  ÃÅa;&  åô¤      @   vendor/phabel-transpiler74.psr/http-message/src/UriInterface.php /  ÃÅa /  îÑžì¤      D   vendor/phabel-transpiler74.psr/http-message/src/MessageInterface.php×  ÃÅa×  ªƒù¤      E   vendor/phabel-transpiler74.psr/http-message/src/ResponseInterface.phpØ	  ÃÅaØ	  jçôË¤      C   vendor/phabel-transpiler74.psr/http-message/src/StreamInterface.php
  ÃÅa
  >OÊ¤      9   vendor/phabel-transpiler74.psr/http-message/composer.jsonm  ÃÅam  ™Š„¤      G   vendor/phabel-transpiler74.psr/http-factory/src/UriFactoryInterface.phpE  ÃÅaE  Ý”—"¤      K   vendor/phabel-transpiler74.psr/http-factory/src/RequestFactoryInterface.phpâ  ÃÅaâ  Ð÷hO¤      L   vendor/phabel-transpiler74.psr/http-factory/src/ResponseFactoryInterface.php  ÃÅa  Gðrm¤      Q   vendor/phabel-transpiler74.psr/http-factory/src/ServerRequestFactoryInterface.php~  ÃÅa~  ±XôÒ¤      J   vendor/phabel-transpiler74.psr/http-factory/src/StreamFactoryInterface.phpz  ÃÅaz  Ó}ôl¤      P   vendor/phabel-transpiler74.psr/http-factory/src/UploadedFileFactoryInterface.php  ÃÅa  (>o-¤      9   vendor/phabel-transpiler74.psr/http-factory/composer.json¼  ÃÅa¼  2Ðd=¤      0   vendor/phabel-transpiler74.psr/log/composer.json2  ÃÅa2  çÕžÚ¤      9   vendor/phabel-transpiler74.psr/log/Psr/Log/NullLogger.phpÀ  ÃÅaÀ  Ô$²{¤      ?   vendor/phabel-transpiler74.psr/log/Psr/Log/LoggerAwareTrait.php�  ÃÅa�  rÖ?ã¤      =   vendor/phabel-transpiler74.psr/log/Psr/Log/Test/DummyTest.php  ÃÅa  Ì£"U¤      >   vendor/phabel-transpiler74.psr/log/Psr/Log/Test/TestLogger.php  ÃÅa  dó…*¤      G   vendor/phabel-transpiler74.psr/log/Psr/Log/Test/LoggerInterfaceTest.phpw  ÃÅaw  D—z¤      =   vendor/phabel-transpiler74.psr/log/Psr/Log/AbstractLogger.phpî  ÃÅaî  *!]4¤      >   vendor/phabel-transpiler74.psr/log/Psr/Log/LoggerInterface.phpô  ÃÅaô  „)Å ¤      7   vendor/phabel-transpiler74.psr/log/Psr/Log/LogLevel.php8  ÃÅa8  ˆo–ë¤      :   vendor/phabel-transpiler74.psr/log/Psr/Log/LoggerTrait.php"  ÃÅa"  2Çì…¤      G   vendor/phabel-transpiler74.psr/log/Psr/Log/InvalidArgumentException.php_   ÃÅa_   ‚¿l9¤      C   vendor/phabel-transpiler74.psr/log/Psr/Log/LoggerAwareInterface.php(  ÃÅa(  œé¤      G   vendor/phabel-transpiler74.danog/loop/examples/1. Basic/GenericLoop.php_  ÃÅa_  8�¢Y¤      H   vendor/phabel-transpiler74.danog/loop/examples/1. Basic/PeriodicLoop.phpN  ÃÅaN  ‰da¤      L   vendor/phabel-transpiler74.danog/loop/examples/2. Advanced/ResumableLoop.php…  ÃÅa…  àû½¤      I   vendor/phabel-transpiler74.danog/loop/examples/2. Advanced/SignalLoop.php  ÃÅa  �…­z¤      R   vendor/phabel-transpiler74.danog/loop/examples/2. Advanced/ResumableSignalLoop.php  ÃÅa  Ï·aç¤      C   vendor/phabel-transpiler74.danog/loop/examples/2. Advanced/Loop.php:  ÃÅa:  »j³ß¤      3   vendor/phabel-transpiler74.danog/loop/composer.json˜  ÃÅa˜  ¢f¿è¤      A   vendor/phabel-transpiler74.danog/loop/lib/Generic/GenericLoop.php+  ÃÅa+  n¶Þ¢¤      B   vendor/phabel-transpiler74.danog/loop/lib/Generic/PeriodicLoop.phpö
  ÃÅaö
  Ìþ¤      ;   vendor/phabel-transpiler74.danog/loop/lib/ResumableLoop.php	  ÃÅa	  7Ù“ñ¤      8   vendor/phabel-transpiler74.danog/loop/lib/SignalLoop.php  ÃÅa  Zr±¤      A   vendor/phabel-transpiler74.danog/loop/lib/ResumableSignalLoop.phpz  ÃÅaz  ?kNô¤      2   vendor/phabel-transpiler74.danog/loop/lib/Loop.php¿  ÃÅa¿  =ê©¤      F   vendor/phabel-transpiler74.danog/loop/lib/Interfaces/LoopInterface.php[  ÃÅa[  ¹¿º!¤      O   vendor/phabel-transpiler74.danog/loop/lib/Interfaces/ResumableLoopInterface.php  ÃÅa  ¡ZO¤      L   vendor/phabel-transpiler74.danog/loop/lib/Interfaces/SignalLoopInterface.php$  ÃÅa$  ÿwÊ¤      B   vendor/phabel-transpiler74.danog/loop/lib/Traits/ResumableLoop.phpç  ÃÅaç   "Ê¤      ?   vendor/phabel-transpiler74.danog/loop/lib/Traits/SignalLoop.php  ÃÅa  Ûl¤      9   vendor/phabel-transpiler74.danog/loop/lib/Traits/Loop.php  ÃÅa  ÞÃbÌ¤      9   vendor/phabel-transpiler74.danog/loop/test/SignalTest.php0	  ÃÅa0	  Ke•‘¤      ;   vendor/phabel-transpiler74.danog/loop/test/PeriodicTest.php#  ÃÅa#  *.¤      <   vendor/phabel-transpiler74.danog/loop/test/ResumableTest.php'  ÃÅa'  T°ð~¤      7   vendor/phabel-transpiler74.danog/loop/test/Fixtures.phpª	  ÃÅaª	  ÒdÆ»¤      J   vendor/phabel-transpiler74.danog/loop/test/Interfaces/LoggingInterface.phpŠ  ÃÅaŠ  _¡Z¤      K   vendor/phabel-transpiler74.danog/loop/test/Interfaces/IntervalInterface.php  ÃÅa  7­HÀ¤      H   vendor/phabel-transpiler74.danog/loop/test/Interfaces/BasicInterface.php¦  ÃÅa¦  gÛó¤      O   vendor/phabel-transpiler74.danog/loop/test/Interfaces/LoggingPauseInterface.phpµ  ÃÅaµ  ºì¦¤      I   vendor/phabel-transpiler74.danog/loop/test/Interfaces/SignalInterface.phpÈ  ÃÅaÈ  Pî²C¤      L   vendor/phabel-transpiler74.danog/loop/test/Interfaces/ResumableInterface.phpé  ÃÅaé  ©åûQ¤      :   vendor/phabel-transpiler74.danog/loop/test/GenericTest.phpZ!  ÃÅaZ!  ?š’ ¤      D   vendor/phabel-transpiler74.danog/loop/test/Traits/BasicException.php  ÃÅa  "o"¤      ;   vendor/phabel-transpiler74.danog/loop/test/Traits/Basic.phpÊ  ÃÅaÊ  &o¤      <   vendor/phabel-transpiler74.danog/loop/test/Traits/Signal.phpH  ÃÅaH  *�"¤      =   vendor/phabel-transpiler74.danog/loop/test/Traits/Logging.phpŠ  ÃÅaŠ  ÍoÈf¤      B   vendor/phabel-transpiler74.danog/loop/test/Traits/LoggingPause.phpŽ  ÃÅaŽ  ^$Úm¤      ?   vendor/phabel-transpiler74.danog/loop/test/Traits/Resumable.php=  ÃÅa=  ‰�â¤      7   vendor/phabel-transpiler74.danog/loop/test/LoopTest.phpŽ
  ÃÅaŽ
  o�è¤      =   vendor/phabel-transpiler74.danog/dns-over-https/composer.jsonÀ  ÃÅaÀ  zb¤      A   vendor/phabel-transpiler74.danog/dns-over-https/lib/DoHConfig.phpz	  ÃÅaz	  ü>&¤      D   vendor/phabel-transpiler74.danog/dns-over-https/lib/DoHException.phpp   ÃÅap   ·Z_/¤      L   vendor/phabel-transpiler74.danog/dns-over-https/lib/Internal/HttpsSocket.phpç  ÃÅaç  í�m¤      G   vendor/phabel-transpiler74.danog/dns-over-https/lib/Internal/Socket.phpÕ  ÃÅaÕ  € ˜¤      K   vendor/phabel-transpiler74.danog/dns-over-https/lib/Rfc8484StubResolver.phpð>  ÃÅað>  Y¼¤      B   vendor/phabel-transpiler74.danog/dns-over-https/lib/Nameserver.phpÒ  ÃÅaÒ  3¢ò¤      G   vendor/phabel-transpiler74.danog/tg-file-decoder/.php-cs-fixer.dist.php  ÃÅa  s�ÕÔ¤      a   vendor/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceThumbnail.php£	  ÃÅa£	  }Åœ¤      r   vendor/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceStickersetThumbnailVersion.phpm  ÃÅam  �~¤      c   vendor/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceDialogPhoto.phpO
  ÃÅaO
  ol¬®¤      ^   vendor/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceLegacy.php€  ÃÅa€  »«EL¤      k   vendor/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceStickersetThumbnail.php	  ÃÅa	  �¤å{¤      ?   vendor/phabel-transpiler74.danog/tg-file-decoder/src/FileId.php<  ÃÅa<  õ«ŽÍ¤      =   vendor/phabel-transpiler74.danog/tg-file-decoder/src/type.php²D  ÃÅa²D  X$˜¤      H   vendor/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource.php¯  ÃÅa¯  ‹-÷µ¤      E   vendor/phabel-transpiler74.danog/tg-file-decoder/src/UniqueFileId.php,  ÃÅa,  Mcô¤      >   vendor/phabel-transpiler74.danog/tg-file-decoder/composer.json“  ÃÅa“  	¾¾S¤      :   vendor/phabel-transpiler74.danog/libdns-json/composer.json:  ÃÅa:  9Kÿ…¤      @   vendor/phabel-transpiler74.danog/libdns-json/lib/JsonDecoder.phpž2  ÃÅaž2  ×ÝW¢¤      A   vendor/phabel-transpiler74.danog/libdns-json/lib/QueryEncoder.phpõ  ÃÅaõ  ƒ{‘¤      H   vendor/phabel-transpiler74.danog/libdns-json/lib/QueryEncoderFactory.php5  ÃÅa5  Z|ùÄ¤      G   vendor/phabel-transpiler74.danog/libdns-json/lib/JsonDecoderFactory.phpÿ  ÃÅaÿ  N&L´¤      L   vendor/phabel-transpiler74.danog/libdns-json/test/JsonDecoderFactoryTest.phpu  ÃÅau  *¯¤      E   vendor/phabel-transpiler74.danog/libdns-json/test/JsonDecoderTest.php‹  ÃÅa‹  ð‚><¤      M   vendor/phabel-transpiler74.danog/libdns-json/test/QueryEncoderFactoryTest.php{  ÃÅa{  š(¿¤      F   vendor/phabel-transpiler74.danog/libdns-json/test/QueryEncoderTest.phpï  ÃÅaï  Õö7¤      :   vendor/phabel-transpiler74.danog/primemodule/composer.jsonb  ÃÅab  ½úv¤      C   vendor/phabel-transpiler74.danog/primemodule/lib/danog/alt_prime.py±  ÃÅa±  _3î{¤      F   vendor/phabel-transpiler74.danog/primemodule/lib/danog/PrimeModule.phpL<  ÃÅaL<  M‚ü+¤      ?   vendor/phabel-transpiler74.danog/primemodule/lib/danog/prime.pyÜ-  ÃÅaÜ-  ò™B¤      8   vendor/phabel-transpiler74.danog/ipc/examples/server.php  ÃÅa  Â5+¤      8   vendor/phabel-transpiler74.danog/ipc/examples/client.phpO  ÃÅaO  sm/•¤      2   vendor/phabel-transpiler74.danog/ipc/composer.jsonÑ  ÃÅaÑ  .s÷s¤      B   vendor/phabel-transpiler74.danog/ipc/lib/Sync/ChannelledSocket.php   ÃÅa   jñCR¤      B   vendor/phabel-transpiler74.danog/ipc/lib/Sync/ChannelException.phpM   ÃÅaM   ¸›Ñ¤      8   vendor/phabel-transpiler74.danog/ipc/lib/Sync/Parcel.php£  ÃÅa£  8h©Ì¤      A   vendor/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseReq.phpZ   ÃÅaZ   ðg{¤      A   vendor/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseMsg.php=   ÃÅa=   ¨Ì„¤      F   vendor/phabel-transpiler74.danog/ipc/lib/Sync/SynchronizationError.phpM   ÃÅaM   EïO­¤      A   vendor/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseAck.phpZ   ÃÅaZ   ‹ÛðC¤      9   vendor/phabel-transpiler74.danog/ipc/lib/Sync/Channel.phpÃ  ÃÅaÃ  �‘¤¨¤      <   vendor/phabel-transpiler74.danog/ipc/lib/Sync/PanicError.phpW  ÃÅaW  -Æe¤      ?   vendor/phabel-transpiler74.danog/ipc/lib/Sync/ChannelParser.php~	  ÃÅa~	  J¹ÃÂ¤      H   vendor/phabel-transpiler74.danog/ipc/lib/Sync/SerializationException.phpS   ÃÅaS   Ù�(=¤      B   vendor/phabel-transpiler74.danog/ipc/lib/Sync/ChannelledStream.php®  ÃÅa®  ®³†7¤      6   vendor/phabel-transpiler74.danog/ipc/lib/IpcServer.phpÔ   ÃÅaÔ   êyÐ—¤      ?   vendor/phabel-transpiler74.danog/ipc/lib/IpcServerException.phph  ÃÅah  ­îÝ¸¤      ?   vendor/phabel-transpiler74.danog/ipc/lib/PendingAcceptError.phpÅ  ÃÅaÅ   "ni¤      6   vendor/phabel-transpiler74.danog/ipc/lib/functions.php  ÃÅa  Ýqˆ¤      5   vendor/phabel-transpiler74.danog/ipc/test/IpcTest.php	  ÃÅa	  »R´¤      =   vendor/phabel-transpiler74.danog/ipc/test/Fixtures/server.phpk  ÃÅak  Óþw¤      A   vendor/phabel-transpiler74.danog/ipc/test/Fixtures/echoServer.phpã  ÃÅaã  3)é>¤      8   vendor/phabel-transpiler74.danog/magicalserializer/a.phpL  ÃÅaL  á´<¤      N   vendor/phabel-transpiler74.danog/magicalserializer/src/danog/Serialization.phpv  ÃÅav  Œ×î¤      M   vendor/phabel-transpiler74.danog/magicalserializer/src/danog/Serializable.php%	  ÃÅa%	  �«J•¤      L   vendor/phabel-transpiler74.danog/magicalserializer/src/danog/PlaceHolder.phpè  ÃÅaè  MÞ´W¤      @   vendor/phabel-transpiler74.danog/magicalserializer/composer.json  ÃÅa  ½Þ‡‡¤      8   vendor/phabel-transpiler74.danog/magicalserializer/b.phpý  ÃÅaý  ¿!¼ ¤      *   vendor/cash/lrucache/src/cash/LRUCache.php¤  ÃÅa¤  ½êÐ­¤      "   vendor/cash/lrucache/composer.json  ÃÅa  >8ßÑ¤      >   vendor/monolog/monolog/src/Monolog/Handler/LogmaticHandler.phpå  ÃÅaå  ¨ í>¤      :   vendor/monolog/monolog/src/Monolog/Handler/NoopHandler.phpp  ÃÅap  o¿p�¤      :   vendor/monolog/monolog/src/Monolog/Handler/AmqpHandler.php  ÃÅa  Fe°¤      >   vendor/monolog/monolog/src/Monolog/Handler/DynamoDbHandler.phpŸ	  ÃÅaŸ	  Ê\ÇV¤      =   vendor/monolog/monolog/src/Monolog/Handler/CouchDBHandler.phpb  ÃÅab  kx,Ò¤      C   vendor/monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.phpµ  ÃÅaµ  ŸQ:¤      D   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php�   ÃÅa�   Uõ§¤      =   vendor/monolog/monolog/src/Monolog/Handler/RollbarHandler.phpÅ  ÃÅaÅ  /XJÕ¤      E   vendor/monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php•  ÃÅa•  §¿Úz¤      H   vendor/monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php  ÃÅa  )®ò¤      A   vendor/monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.phpø  ÃÅaø  :øVî¤      >   vendor/monolog/monolog/src/Monolog/Handler/SendGridHandler.php#  ÃÅa#  Al+Í¤      :   vendor/monolog/monolog/src/Monolog/Handler/GelfHandler.phps  ÃÅas  v_q¤      <   vendor/monolog/monolog/src/Monolog/Handler/BufferHandler.php9  ÃÅa9  Úêô«¤      :   vendor/monolog/monolog/src/Monolog/Handler/NullHandler.php@  ÃÅa@  ÏVµÊ¤      H   vendor/monolog/monolog/src/Monolog/Handler/MissingExtensionException.phpØ  ÃÅaØ  7ñÉT¤      >   vendor/monolog/monolog/src/Monolog/Handler/ErrorLogHandler.phpî	  ÃÅaî	  7š1¼¤      <   vendor/monolog/monolog/src/Monolog/Handler/LogglyHandler.phpW  ÃÅaW  i÷èÉ¤      =   vendor/monolog/monolog/src/Monolog/Handler/FirePHPHandler.phpD  ÃÅaD   ºüï¤      B   vendor/monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.phpO  ÃÅaO  ;³§”¤      9   vendor/monolog/monolog/src/Monolog/Handler/PsrHandler.php	  ÃÅa	  ù›Œ�¤      A   vendor/monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.phpX  ÃÅaX  Ej5u¤      J   vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.phpI  ÃÅaI  ¸˜ÕD¤      Z   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.phpl  ÃÅal  Ðqì¤      \   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php‘	  ÃÅa‘	  ¿3¤      Y   vendor/monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.phpÐ  ÃÅaÐ  @â¤      :   vendor/monolog/monolog/src/Monolog/Handler/TestHandler.phpn  ÃÅan  ˆ¨˜¤      F   vendor/monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.phpý  ÃÅaý  ÌÕ–„¤      <   vendor/monolog/monolog/src/Monolog/Handler/FilterHandler.phpª  ÃÅaª  ÇòP¤      <   vendor/monolog/monolog/src/Monolog/Handler/SyslogHandler.php-  ÃÅa-  à!éû¤      B   vendor/monolog/monolog/src/Monolog/Handler/RotatingFileHandler.phpÝ  ÃÅaÝ   [á¤      F   vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.phpÚ  ÃÅaÚ  EL«¶¤      @   vendor/monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php)  ÃÅa)  ÐÿK¤      <   vendor/monolog/monolog/src/Monolog/Handler/SocketHandler.php,  ÃÅa,  ²4Ë=¤      ?   vendor/monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php  ÃÅa  UQË¤      =   vendor/monolog/monolog/src/Monolog/Handler/ProcessHandler.php»  ÃÅa»  ²°uã¤      @   vendor/monolog/monolog/src/Monolog/Handler/LogEntriesHandler.phpä  ÃÅaä  Æ	P¤      ;   vendor/monolog/monolog/src/Monolog/Handler/GroupHandler.php³  ÃÅa³  €�Õ¤      @   vendor/monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php‚  ÃÅa‚  “ <¤      >   vendor/monolog/monolog/src/Monolog/Handler/SamplingHandler.php   ÃÅa   jãåÄ¤      B   vendor/monolog/monolog/src/Monolog/Handler/NativeMailerHandler.phpg  ÃÅag  ¿‡š£¤      ?   vendor/monolog/monolog/src/Monolog/Handler/ChromePHPHandler.phpÙ  ÃÅaÙ  Îr˜r¤      ?   vendor/monolog/monolog/src/Monolog/Handler/FleepHookHandler.phpM  ÃÅaM  3“4ò¤      :   vendor/monolog/monolog/src/Monolog/Handler/MailHandler.php7	  ÃÅa7	  qmjÜ¤      A   vendor/monolog/monolog/src/Monolog/Handler/TelegramBotHandler.phpr  ÃÅar  Ò GX¤      6   vendor/monolog/monolog/src/Monolog/Handler/Handler.php0  ÃÅa0  >HŠâ¤      9   vendor/monolog/monolog/src/Monolog/Handler/SqsHandler.php�  ÃÅa�  (UfÕ¤      ;   vendor/monolog/monolog/src/Monolog/Handler/RedisHandler.phpG  ÃÅaG  ABêè¤      =   vendor/monolog/monolog/src/Monolog/Handler/MongoDBHandler.phpø	  ÃÅaø	  ëËs<¤      >   vendor/monolog/monolog/src/Monolog/Handler/FlowdockHandler.php>  ÃÅa>  EÎ¤      :   vendor/monolog/monolog/src/Monolog/Handler/CubeHandler.php  ÃÅa  J�K¤      J   vendor/monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php¦  ÃÅa¦  Ýd,æ¤      <   vendor/monolog/monolog/src/Monolog/Handler/StreamHandler.phpã  ÃÅaã  "¯Ùõ¤      8   vendor/monolog/monolog/src/Monolog/Handler/Curl/Util.phpð  ÃÅað  O2¤ù¤      >   vendor/monolog/monolog/src/Monolog/Handler/ElasticaHandler.php–  ÃÅa–  LÔá‰¤      >   vendor/monolog/monolog/src/Monolog/Handler/OverflowHandler.php)  ÃÅa)  @6ÂD¤      >   vendor/monolog/monolog/src/Monolog/Handler/NewRelicHandler.phpø  ÃÅaø  R�ž§¤      >   vendor/monolog/monolog/src/Monolog/Handler/PushoverHandler.php!  ÃÅa!  fNü¤      >   vendor/monolog/monolog/src/Monolog/Handler/AbstractHandler.php+
  ÃÅa+
  \‘Éº¤      B   vendor/monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php%  ÃÅa%  A9‹¤      ?   vendor/monolog/monolog/src/Monolog/Handler/HandlerInterface.phpƒ  ÃÅaƒ  Aâä¤      ;   vendor/monolog/monolog/src/Monolog/Handler/IFTTTHandler.php:  ÃÅa:  Ü/§¤      C   vendor/monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.phpÞ  ÃÅaÞ  öëud¤      H   vendor/monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.phps  ÃÅas  <:'È¤      A   vendor/monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.phpç  ÃÅaç  úHz¤      ;   vendor/monolog/monolog/src/Monolog/Handler/SlackHandler.php  ÃÅa  Ðméê¤      D   vendor/monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.phpR  ÃÅaR  É¾ö¤      F   vendor/monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php‚  ÃÅa‚  Ö€ôÈ¤      C   vendor/monolog/monolog/src/Monolog/Handler/DeduplicationHandler.phpÂ  ÃÅaÂ  -•Ã¤      >   vendor/monolog/monolog/src/Monolog/Handler/MandrillHandler.phpi	  ÃÅai	  i·%ä¤      @   vendor/monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php€'  ÃÅa€'  —êj¤      =   vendor/monolog/monolog/src/Monolog/Handler/HandlerWrapper.phpB  ÃÅaB  rý|V¤      D   vendor/monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php�   ÃÅa�   \æO|¤      :   vendor/monolog/monolog/src/Monolog/ResettableInterface.phpë  ÃÅaë  ã7–¤      ,   vendor/monolog/monolog/src/Monolog/Utils.phpP"  ÃÅaP"  ,­ÆÕ¤      4   vendor/monolog/monolog/src/Monolog/Test/TestCase.phpq  ÃÅaq  @W×Ì¤      =   vendor/monolog/monolog/src/Monolog/Processor/WebProcessor.phpX  ÃÅaX  >_¤      E   vendor/monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php.  ÃÅa.  r`Ü{¤      =   vendor/monolog/monolog/src/Monolog/Processor/UidProcessor.phpŽ  ÃÅaŽ  ´F˜›¤      @   vendor/monolog/monolog/src/Monolog/Processor/MemoryProcessor.php  ÃÅa  šƒU"¤      C   vendor/monolog/monolog/src/Monolog/Processor/ProcessorInterface.php   ÃÅa   T.�¶¤      C   vendor/monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php^  ÃÅa^  ùœøV¤      I   vendor/monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.phpA  ÃÅaA  pÛÜ¤      B   vendor/monolog/monolog/src/Monolog/Processor/HostnameProcessor.phpè  ÃÅaè  Q=ó¤      G   vendor/monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php5  ÃÅa5  J0Ñ¤      C   vendor/monolog/monolog/src/Monolog/Processor/MercurialProcessor.php?  ÃÅa?  !Žå¬¤      =   vendor/monolog/monolog/src/Monolog/Processor/GitProcessor.phpp  ÃÅap  €J(7¤      =   vendor/monolog/monolog/src/Monolog/Processor/TagProcessor.php]  ÃÅa]  ë+z—¤      G   vendor/monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php  ÃÅa  g¤Ÿ¤      -   vendor/monolog/monolog/src/Monolog/Logger.php)G  ÃÅa)G  Ý—˜¤      8   vendor/monolog/monolog/src/Monolog/DateTimeImmutable.php  ÃÅa  0É(¤      4   vendor/monolog/monolog/src/Monolog/SignalHandler.phpü  ÃÅaü  gÐ·¤      /   vendor/monolog/monolog/src/Monolog/Registry.php  ÃÅa  ªÃ¸¤      B   vendor/monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.phpQ	  ÃÅaQ	  TU»L¤      A   vendor/monolog/monolog/src/Monolog/Formatter/FluentdFormatter.phpÕ  ÃÅaÕ  NÃË¤      @   vendor/monolog/monolog/src/Monolog/Formatter/ScalarFormatter.phpv  ÃÅav  N³¿.¤      B   vendor/monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php  ÃÅa  =Ä_Ê¤      A   vendor/monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.phpã  ÃÅaã  «^Ça¤      D   vendor/monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php¿  ÃÅa¿  é²à¤      >   vendor/monolog/monolog/src/Monolog/Formatter/LineFormatter.php   ÃÅa   '‰ÿ¤      C   vendor/monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.phpÃ  ÃÅaÃ  ã“Ï¤      >   vendor/monolog/monolog/src/Monolog/Formatter/JsonFormatter.phpª  ÃÅaª  AåžÛ¤      B   vendor/monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php&  ÃÅa&  —&JA¤      C   vendor/monolog/monolog/src/Monolog/Formatter/FormatterInterface.phpº  ÃÅaº  ¨¬Ô/¤      E   vendor/monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.phpþ  ÃÅaþ  Ö¤      >   vendor/monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php>  ÃÅa>  ZVÍ±¤      @   vendor/monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php  ÃÅa  8î:ù¤      B   vendor/monolog/monolog/src/Monolog/Formatter/WildfireFormatter.phpg  ÃÅag  T?Q/¤      G   vendor/monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php;  ÃÅa;  Û£TÝ¤      B   vendor/monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.phpó  ÃÅaó  @Š¯¤      3   vendor/monolog/monolog/src/Monolog/ErrorHandler.php%'  ÃÅa%'  ÿ°"¤      $   vendor/monolog/monolog/composer.jsoné  ÃÅaé  ·Lß�¤         composer.json»  ÃÅa»  oPº¯¤      1   vendor/danog/madelineproto/.git/refs/heads/master+   ÃÅa+   1NzH¤         .git/refs/heads/master+   ÃÅa+   1NzH¤      {
    "name": "phpseclib/phpseclib",
    "type": "library",
    "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
    "keywords": [
        "security",
        "crypto",
        "cryptography",
        "encryption",
        "signature",
        "signing",
        "rsa",
        "aes",
        "blowfish",
        "twofish",
        "ssh",
        "sftp",
        "x509",
        "x.509",
        "asn1",
        "asn.1",
        "BigInteger"
        ],
    "homepage": "http://phpseclib.sourceforge.net",
    "license": "MIT",
    "authors": [
        {
            "name": "Jim Wigginton",
            "email": "terrafrost@php.net",
            "role": "Lead Developer"
        },
        {
            "name": "Patrick Monnerat",
            "email": "pm@datasphere.ch",
            "role": "Developer"
        },
        {
            "name": "Andreas Fischer",
            "email": "bantu@phpbb.com",
            "role": "Developer"
        },
        {
            "name": "Hans-JÃ¼rgen Petrich",
            "email": "petrich@tronic-media.com",
            "role": "Developer"
        },
        {
            "name": "Graham Campbell",
            "email": "graham@alt-three.com",
            "role": "Developer"
        }
    ],
    "require": {
        "paragonie/constant_time_encoding": "^1|^2",
        "paragonie/random_compat": "^1.4|^2.0|^9.99.99",
        "php": ">=5.6.1"
    },
    "require-dev": {
        "phing/phing": "~2.7",
        "phpunit/phpunit": "^5.7|^6.0|^9.4",
        "squizlabs/php_codesniffer": "~2.0"
    },
    "suggest": {
        "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
        "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.",
        "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
        "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations."
    },
    "autoload": {
        "files": [
            "phpseclib/bootstrap.php"
        ],
        "psr-4": {
            "phpseclib3\\": "phpseclib/"
        }
    }
}
<?php

/**
 * Pure-PHP implementation of AES.
 *
 * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
 * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
 * to save one include_once().
 *
 * If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
 * {@link self::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's 136-bits
 * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
 * is called, again, at which point, it'll be recalculated.
 *
 * Since \phpseclib3\Crypt\AES extends \phpseclib3\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't
 * make a whole lot of sense.  {@link self::setBlockLength() setBlockLength()}, for instance.  Calling that function,
 * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $aes = new \phpseclib3\Crypt\AES('ctr');
 *
 *    $aes->setKey('abcdefghijklmnop');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $aes->decrypt($aes->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   AES
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2008 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

/**
 * Pure-PHP implementation of AES.
 *
 * @package AES
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class AES extends Rijndael
{
    /**
     * Dummy function
     *
     * Since \phpseclib3\Crypt\AES extends \phpseclib3\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything.
     *
     * @see \phpseclib3\Crypt\Rijndael::setBlockLength()
     * @access public
     * @param int $length
     * @throws \BadMethodCallException anytime it's called
     */
    public function setBlockLength($length)
    {
        throw new \BadMethodCallException('The block length cannot be set for AES.');
    }
    /**
     * Sets the key length
     *
     * Valid key lengths are 128, 192, and 256.  Set the link to bool(false) to disable a fixed key length
     *
     * @see \phpseclib3\Crypt\Rijndael:setKeyLength()
     * @access public
     * @param int $length
     * @throws \LengthException if the key length isn't supported
     */
    public function setKeyLength($length)
    {
        switch ($length) {
            case 128:
            case 192:
            case 256:
                break;
            default:
                throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported');
        }
        parent::setKeyLength($length);
    }
    /**
     * Sets the key.
     *
     * Rijndael supports five different key lengths, AES only supports three.
     *
     * @see \phpseclib3\Crypt\Rijndael:setKey()
     * @see setKeyLength()
     * @access public
     * @param string $key
     * @throws \LengthException if the key length isn't supported
     */
    public function setKey($key)
    {
        switch (strlen($key)) {
            case 16:
            case 24:
            case 32:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
        }
        parent::setKey($key);
    }
}<?php

/**
 * Wrapper around hash() and hash_hmac() functions supporting truncated hashes
 * such as sha256-96.  Any hash algorithm returned by hash_algos() (and
 * truncated versions thereof) are supported.
 *
 * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will
 * return the HMAC as opposed to the hash.
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $hash = new \phpseclib3\Crypt\Hash('sha512');
 *
 *    $hash->setKey('abcdefg');
 *
 *    echo base64_encode($hash->hash('abcdefg'));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Hash
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @author    Andreas Fischer <bantu@phpbb.com>
 * @copyright 2015 Andreas Fischer
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\AES;
use phpseclib3\Math\PrimeField;
/**
 * @package Hash
 * @author  Jim Wigginton <terrafrost@php.net>
 * @author  Andreas Fischer <bantu@phpbb.com>
 * @access  public
 */
class Hash
{
    /**
     * Padding Types
     *
     * @access private
     */
    //const PADDING_KECCAK = 1;
    /**
     * Padding Types
     *
     * @access private
     */
    const PADDING_SHA3 = 2;
    /**
     * Padding Types
     *
     * @access private
     */
    const PADDING_SHAKE = 3;
    /**
     * Padding Type
     *
     * Only used by SHA3
     *
     * @var int
     * @access private
     */
    private $paddingType = 0;
    /**
     * Hash Parameter
     *
     * @see self::setHash()
     * @var int
     * @access private
     */
    private $hashParam;
    /**
     * Byte-length of hash output (Internal HMAC)
     *
     * @see self::setHash()
     * @var int
     * @access private
     */
    private $length;
    /**
     * Hash Algorithm
     *
     * @see self::setHash()
     * @var string
     * @access private
     */
    private $algo;
    /**
     * Key
     *
     * @see self::setKey()
     * @var string
     * @access private
     */
    private $key = false;
    /**
     * Nonce
     *
     * @see self::setNonce()
     * @var string
     * @access private
     */
    private $nonce = false;
    /**
     * Hash Parameters
     *
     * @var array
     * @access private
     */
    private $parameters = [];
    /**
     * Computed Key
     *
     * @see self::_computeKey()
     * @var string
     * @access private
     */
    private $computedKey = false;
    /**
     * Outer XOR (Internal HMAC)
     *
     * Used only for sha512/*
     *
     * @see self::hash()
     * @var string
     * @access private
     */
    private $opad;
    /**
     * Inner XOR (Internal HMAC)
     *
     * Used only for sha512/*
     *
     * @see self::hash()
     * @var string
     * @access private
     */
    private $ipad;
    /**
     * Recompute AES Key
     *
     * Used only for umac
     *
     * @see self::hash()
     * @var boolean
     * @access private
     */
    private $recomputeAESKey;
    /**
     * umac cipher object
     *
     * @see self::hash()
     * @var \phpseclib3\Crypt\AES
     * @access private
     */
    private $c;
    /**
     * umac pad
     *
     * @see self::hash()
     * @var string
     * @access private
     */
    private $pad;
    /**#@+
     * UMAC variables
     *
     * @var PrimeField
     */
    private static $factory36;
    private static $factory64;
    private static $factory128;
    private static $offset64;
    private static $offset128;
    private static $marker64;
    private static $marker128;
    private static $maxwordrange64;
    private static $maxwordrange128;
    /**#@-*/
    /**
     * Default Constructor.
     *
     * @param string $hash
     * @access public
     */
    public function __construct($hash = 'sha256')
    {
        $this->setHash($hash);
    }
    /**
     * Sets the key for HMACs
     *
     * Keys can be of any length.
     *
     * @access public
     * @param string $key
     */
    public function setKey($key = false)
    {
        $this->key = $key;
        $this->computeKey();
        $this->recomputeAESKey = true;
    }
    /**
     * Sets the nonce for UMACs
     *
     * Keys can be of any length.
     *
     * @access public
     * @param string $nonce
     */
    public function setNonce($nonce = false)
    {
        switch (true) {
            case !is_string($nonce):
            case strlen($nonce) > 0 && strlen($nonce) <= 16:
                $this->recomputeAESKey = true;
                $this->nonce = $nonce;
                return;
        }
        throw new \LengthException('The nonce length must be between 1 and 16 bytes, inclusive');
    }
    /**
    * Pre-compute the key used by the HMAC
    *
    * Quoting http://tools.ietf.org/html/rfc2104#section-2, "Applications that use keys longer than B bytes
    will first hash the key using H and then use the resultant L byte string as the actual key to HMAC."
    *
    * As documented in https://www.reddit.com/r/PHP/comments/9nct2l/symfonypolyfill_hash_pbkdf2_correct_fix_for/
    when doing an HMAC multiple times it's faster to compute the hash once instead of computing it during
    every call
    *
    * @access private
    */
    private function computeKey()
    {
        if ($this->key === false) {
            $this->computedKey = false;
            return;
        }
        if (strlen($this->key) <= $this->getBlockLengthInBytes()) {
            $this->computedKey = $this->key;
            return;
        }
        $this->computedKey = is_array($this->algo) ? call_user_func($this->algo, $this->key) : hash($this->algo, $this->key, true);
    }
    /**
     * Gets the hash function.
     *
     * As set by the constructor or by the setHash() method.
     *
     * @access public
     * @return string
     */
    public function getHash()
    {
        return $this->hashParam;
    }
    /**
     * Sets the hash function.
     *
     * @access public
     * @param string $hash
     */
    public function setHash($hash)
    {
        $this->hashParam = $hash = strtolower($hash);
        switch ($hash) {
            case 'umac-32':
            case 'umac-64':
            case 'umac-96':
            case 'umac-128':
                $this->blockSize = 128;
                $this->length = abs(\Phabel\Target\Php80\Polyfill::substr($hash, -3)) >> 3;
                $this->algo = 'umac';
                return;
            case 'md2-96':
            case 'md5-96':
            case 'sha1-96':
            case 'sha224-96':
            case 'sha256-96':
            case 'sha384-96':
            case 'sha512-96':
            case 'sha512/224-96':
            case 'sha512/256-96':
                $hash = \Phabel\Target\Php80\Polyfill::substr($hash, 0, -3);
                $this->length = 12;
                // 96 / 8 = 12
                break;
            case 'md2':
            case 'md5':
                $this->length = 16;
                break;
            case 'sha1':
                $this->length = 20;
                break;
            case 'sha224':
            case 'sha512/224':
            case 'sha3-224':
                $this->length = 28;
                break;
            case 'sha256':
            case 'sha512/256':
            case 'sha3-256':
                $this->length = 32;
                break;
            case 'sha384':
            case 'sha3-384':
                $this->length = 48;
                break;
            case 'sha512':
            case 'sha3-512':
                $this->length = 64;
                break;
            default:
                if (preg_match('#^(shake(?:128|256))-(\\d+)$#', $hash, $matches)) {
                    $this->paddingType = self::PADDING_SHAKE;
                    $hash = $matches[1];
                    $this->length = $matches[2] >> 3;
                } else {
                    throw new UnsupportedAlgorithmException("{$hash} is not a supported algorithm");
                }
        }
        switch ($hash) {
            case 'md2':
            case 'md2-96':
                $this->blockSize = 128;
                break;
            case 'md5-96':
            case 'sha1-96':
            case 'sha224-96':
            case 'sha256-96':
            case 'md5':
            case 'sha1':
            case 'sha224':
            case 'sha256':
                $this->blockSize = 512;
                break;
            case 'sha3-224':
                $this->blockSize = 1152;
                // 1600 - 2*224
                break;
            case 'sha3-256':
            case 'shake256':
                $this->blockSize = 1088;
                // 1600 - 2*256
                break;
            case 'sha3-384':
                $this->blockSize = 832;
                // 1600 - 2*384
                break;
            case 'sha3-512':
                $this->blockSize = 576;
                // 1600 - 2*512
                break;
            case 'shake128':
                $this->blockSize = 1344;
                // 1600 - 2*128
                break;
            default:
                $this->blockSize = 1024;
        }
        if (in_array(\Phabel\Target\Php80\Polyfill::substr($hash, 0, 5), ['sha3-', 'shake'])) {
            // PHP 7.1.0 introduced support for "SHA3 fixed mode algorithms":
            // http://php.net/ChangeLog-7.php#7.1.0
            if (version_compare(PHP_VERSION, '7.1.0') < 0 || \Phabel\Target\Php80\Polyfill::substr($hash, 0, 5) == 'shake') {
                //preg_match('#(\d+)$#', $hash, $matches);
                //$this->parameters['capacity'] = 2 * $matches[1]; // 1600 - $this->blockSize
                //$this->parameters['rate'] = 1600 - $this->parameters['capacity']; // == $this->blockSize
                if (!$this->paddingType) {
                    $this->paddingType = self::PADDING_SHA3;
                }
                $this->parameters = ['capacity' => 1600 - $this->blockSize, 'rate' => $this->blockSize, 'length' => $this->length, 'padding' => $this->paddingType];
                $hash = ['phpseclib3\\Crypt\\Hash', PHP_INT_SIZE == 8 ? 'sha3_64' : 'sha3_32'];
            }
        }
        if ($hash == 'sha512/224' || $hash == 'sha512/256') {
            // PHP 7.1.0 introduced sha512/224 and sha512/256 support:
            // http://php.net/ChangeLog-7.php#7.1.0
            if (version_compare(PHP_VERSION, '7.1.0') < 0) {
                // from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24
                $initial = $hash == 'sha512/256' ? ['22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD', '96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2'] : ['8C3D37C819544DA2', '73E1996689DCD4D6', '1DFAB7AE32FF9C82', '679DD514582F9FCF', '0F6D2B697BD44DA8', '77E36F7304C48942', '3F9D85A86A1D36C8', '1112E6AD91D692A1'];
                for ($i = 0; $i < 8; $i++) {
                    $initial[$i] = new BigInteger($initial[$i], 16);
                    $initial[$i]->setPrecision(64);
                }
                $this->parameters = compact('initial');
                $hash = ['phpseclib3\\Crypt\\Hash', 'sha512'];
            }
        }
        if (is_array($hash)) {
            $b = $this->blockSize >> 3;
            $this->ipad = str_repeat(chr(0x36), $b);
            $this->opad = str_repeat(chr(0x5c), $b);
        }
        $this->algo = $hash;
        $this->computeKey();
    }
    /**
     * KDF: Key-Derivation Function
     *
     * The key-derivation function generates pseudorandom bits used to key the hash functions.
     *
     * @param int $index a non-negative integer less than 2^64
     * @param int $numbytes a non-negative integer less than 2^64
     * @return string string of length numbytes bytes
     */
    private function kdf($index, $numbytes)
    {
        $this->c->setIV(pack('N4', 0, $index, 0, 1));
        return $this->c->encrypt(str_repeat("\x00", $numbytes));
    }
    /**
     * PDF Algorithm
     *
     * @return string string of length taglen bytes.
     */
    private function pdf()
    {
        $k = $this->key;
        $nonce = $this->nonce;
        $taglen = $this->length;
        //
        // Extract and zero low bit(s) of Nonce if needed
        //
        if ($taglen <= 8) {
            $last = strlen($nonce) - 1;
            $mask = $taglen == 4 ? "\x03" : "\x01";
            $index = $nonce[$last] & $mask;
            $nonce[$last] = $nonce[$last] ^ $index;
        }
        //
        // Make Nonce BLOCKLEN bytes by appending zeroes if needed
        //
        $nonce = str_pad($nonce, 16, "\x00");
        //
        // Generate subkey, encipher and extract indexed substring
        //
        $kp = $this->kdf(0, 16);
        $c = new AES('ctr');
        $c->disablePadding();
        $c->setKey($kp);
        $c->setIV($nonce);
        $t = $c->encrypt("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
        // we could use ord() but per https://paragonie.com/blog/2016/06/constant-time-encoding-boring-cryptography-rfc-4648-and-you
        // unpack() doesn't leak timing info
        return $taglen <= 8 ? \Phabel\Target\Php80\Polyfill::substr($t, unpack('C', $index)[1] * $taglen, $taglen) : \Phabel\Target\Php80\Polyfill::substr($t, 0, $taglen);
    }
    /**
     * UHASH Algorithm
     *
     * @param string $m string of length less than 2^67 bits.
     * @param int $taglen the integer 4, 8, 12 or 16.
     * @return string string of length taglen bytes.
     */
    private function uhash($m, $taglen)
    {
        //
        // One internal iteration per 4 bytes of output
        //
        $iters = $taglen >> 2;
        //
        // Define total key needed for all iterations using KDF.
        // L1Key reuses most key material between iterations.
        //
        //$L1Key  = $this->kdf(1, 1024 + ($iters - 1) * 16);
        $L1Key = $this->kdf(1, (1024 + ($iters - 1)) * 16);
        $L2Key = $this->kdf(2, $iters * 24);
        $L3Key1 = $this->kdf(3, $iters * 64);
        $L3Key2 = $this->kdf(4, $iters * 4);
        //
        // For each iteration, extract key and do three-layer hash.
        // If bytelength(M) <= 1024, then skip L2-HASH.
        //
        $y = '';
        for ($i = 0; $i < $iters; $i++) {
            $L1Key_i = \Phabel\Target\Php80\Polyfill::substr($L1Key, $i * 16, 1024);
            $L2Key_i = \Phabel\Target\Php80\Polyfill::substr($L2Key, $i * 24, 24);
            $L3Key1_i = \Phabel\Target\Php80\Polyfill::substr($L3Key1, $i * 64, 64);
            $L3Key2_i = \Phabel\Target\Php80\Polyfill::substr($L3Key2, $i * 4, 4);
            $a = self::L1Hash($L1Key_i, $m);
            $b = strlen($m) <= 1024 ? "\x00\x00\x00\x00\x00\x00\x00\x00{$a}" : self::L2Hash($L2Key_i, $a);
            $c = self::L3Hash($L3Key1_i, $L3Key2_i, $b);
            $y .= $c;
        }
        return $y;
    }
    /**
    * L1-HASH Algorithm
    *
    * The first-layer hash breaks the message into 1024-byte chunks and
    hashes each with a function called NH.  Concatenating the results
    forms a string, which is up to 128 times shorter than the original.
    *
    * @param string $k string of length 1024 bytes.
    * @param string $m string of length less than 2^67 bits.
    * @return string string of length (8 * ceil(bitlength(M)/8192)) bytes.
    */
    private static function L1Hash($k, $m)
    {
        //
        // Break M into 1024 byte chunks (final chunk may be shorter)
        //
        $m = str_split($m, 1024);
        //
        // For each chunk, except the last: endian-adjust, NH hash
        // and add bit-length.  Use results to build Y.
        //
        $length = new BigInteger(1024 * 8);
        $y = '';
        for ($i = 0; $i < count($m) - 1; $i++) {
            $m[$i] = pack('N*', ...unpack('V*', $m[$i]));
            // ENDIAN-SWAP
            $y .= static::nh($k, $m[$i], $length);
        }
        //
        // For the last chunk: pad to 32-byte boundary, endian-adjust,
        // NH hash and add bit-length.  Concatenate the result to Y.
        //
        $length = strlen($m[$i]);
        $pad = 32 - $length % 32;
        $pad = max(32, $length + $pad % 32);
        $m[$i] = str_pad($m[$i], $pad, "\x00");
        // zeropad
        $m[$i] = pack('N*', ...unpack('V*', $m[$i]));
        // ENDIAN-SWAP
        $y .= static::nh($k, $m[$i], new BigInteger($length * 8));
        return $y;
    }
    /**
     * NH Algorithm
     *
     * @param string $k string of length 1024 bytes.
     * @param string $m string with length divisible by 32 bytes.
     * @return string string of length 8 bytes.
     */
    private static function nh($k, $m, $length)
    {
        $toUInt32 = function ($x) {
            $x = new BigInteger($x, 256);
            $x->setPrecision(32);
            return $x;
        };
        //
        // Break M and K into 4-byte chunks
        //
        //$t = strlen($m) >> 2;
        $m = str_split($m, 4);
        $t = count($m);
        $k = str_split($k, 4);
        $k = array_pad(array_slice($k, 0, $t), $t, 0);
        $m = array_map($toUInt32, $m);
        $k = array_map($toUInt32, $k);
        //
        // Perform NH hash on the chunks, pairing words for multiplication
        // which are 4 apart to accommodate vector-parallelism.
        //
        $y = new BigInteger();
        $y->setPrecision(64);
        $i = 0;
        while ($i < $t) {
            $temp = $m[$i]->add($k[$i]);
            $temp->setPrecision(64);
            $temp = $temp->multiply($m[$i + 4]->add($k[$i + 4]));
            $y = $y->add($temp);
            $temp = $m[$i + 1]->add($k[$i + 1]);
            $temp->setPrecision(64);
            $temp = $temp->multiply($m[$i + 5]->add($k[$i + 5]));
            $y = $y->add($temp);
            $temp = $m[$i + 2]->add($k[$i + 2]);
            $temp->setPrecision(64);
            $temp = $temp->multiply($m[$i + 6]->add($k[$i + 6]));
            $y = $y->add($temp);
            $temp = $m[$i + 3]->add($k[$i + 3]);
            $temp->setPrecision(64);
            $temp = $temp->multiply($m[$i + 7]->add($k[$i + 7]));
            $y = $y->add($temp);
            $i += 8;
        }
        return $y->add($length)->toBytes();
    }
    /**
    * L2-HASH: Second-Layer Hash
    *
    * The second-layer rehashes the L1-HASH output using a polynomial hash
    called POLY.  If the L1-HASH output is long, then POLY is called once
    on a prefix of the L1-HASH output and called using different settings
    on the remainder.  (This two-step hashing of the L1-HASH output is
    needed only if the message length is greater than 16 megabytes.)
    Careful implementation of POLY is necessary to avoid a possible
    timing attack (see Section 6.6 for more information).
    *
    * @param string $k string of length 24 bytes.
    * @param string $m string of length less than 2^64 bytes.
    * @return string string of length 16 bytes.
    */
    private static function L2Hash($k, $m)
    {
        //
        //  Extract keys and restrict to special key-sets
        //
        $k64 = $k & "\x01\xff\xff\xff\x01\xff\xff\xff";
        $k64 = new BigInteger($k64, 256);
        $k128 = \Phabel\Target\Php80\Polyfill::substr($k, 8) & "\x01\xff\xff\xff\x01\xff\xff\xff\x01\xff\xff\xff\x01\xff\xff\xff";
        $k128 = new BigInteger($k128, 256);
        //
        // If M is no more than 2^17 bytes, hash under 64-bit prime,
        // otherwise, hash first 2^17 bytes under 64-bit prime and
        // remainder under 128-bit prime.
        //
        if (strlen($m) <= 0x20000) {
            // 2^14 64-bit words
            $y = self::poly(64, self::$maxwordrange64, $k64, $m);
        } else {
            $m_1 = \Phabel\Target\Php80\Polyfill::substr($m, 0, 0x20000);
            // 1 << 17
            $m_2 = \Phabel\Target\Php80\Polyfill::substr($m, 0x20000) . "\x80";
            $length = strlen($m_2);
            $pad = 16 - $length % 16;
            $pad %= 16;
            $m_2 = str_pad($m_2, $length + $pad, "\x00");
            // zeropad
            $y = self::poly(64, self::$maxwordrange64, $k64, $m_1);
            $y = str_pad($y, 16, "\x00", STR_PAD_LEFT);
            $y = self::poly(128, self::$maxwordrange128, $k128, $y . $m_2);
        }
        return str_pad($y, 16, "\x00", STR_PAD_LEFT);
    }
    /**
     * POLY Algorithm
     *
     * @param int $wordbits the integer 64 or 128.
     * @param BigInteger $maxwordrange positive integer less than 2^wordbits.
     * @param BigInteger $k integer in the range 0 ... prime(wordbits) - 1.
     * @param string $m string with length divisible by (wordbits / 8) bytes.
     * @return integer in the range 0 ... prime(wordbits) - 1.
     */
    private static function poly($wordbits, $maxwordrange, $k, $m)
    {
        //
        // Define constants used for fixing out-of-range words
        //
        $wordbytes = $wordbits >> 3;
        if ($wordbits == 128) {
            $factory = self::$factory128;
            $offset = self::$offset128;
            $marker = self::$marker128;
        } else {
            $factory = self::$factory64;
            $offset = self::$offset64;
            $marker = self::$marker64;
        }
        $k = $factory->newInteger($k);
        //
        // Break M into chunks of length wordbytes bytes
        //
        $m_i = str_split($m, $wordbytes);
        //
        // Each input word m is compared with maxwordrange.  If not smaller
        // then 'marker' and (m - offset), both in range, are hashed.
        //
        $y = $factory->newInteger(new BigInteger(1));
        foreach ($m_i as $m) {
            $m = $factory->newInteger(new BigInteger($m, 256));
            if ($m->compare($maxwordrange) >= 0) {
                $y = $k->multiply($y)->add($marker);
                $y = $k->multiply($y)->add($m->subtract($offset));
            } else {
                $y = $k->multiply($y)->add($m);
            }
        }
        return $y->toBytes();
    }
    /**
    * L3-HASH: Third-Layer Hash
    *
    * The output from L2-HASH is 16 bytes long.  This final hash function
    hashes the 16-byte string to a fixed length of 4 bytes.
    *
    * @param string $k1 string of length 64 bytes.
    * @param string $k2 string of length 4 bytes.
    * @param string $m string of length 16 bytes.
    * @return string string of length 4 bytes.
    */
    private static function L3Hash($k1, $k2, $m)
    {
        $factory = self::$factory36;
        $y = $factory->newInteger(new BigInteger());
        for ($i = 0; $i < 8; $i++) {
            $m_i = $factory->newInteger(new BigInteger(\Phabel\Target\Php80\Polyfill::substr($m, 2 * $i, 2), 256));
            $k_i = $factory->newInteger(new BigInteger(\Phabel\Target\Php80\Polyfill::substr($k1, 8 * $i, 8), 256));
            $y = $y->add($m_i->multiply($k_i));
        }
        $y = str_pad(\Phabel\Target\Php80\Polyfill::substr($y->toBytes(), -4), 4, "\x00", STR_PAD_LEFT);
        $y = $y ^ $k2;
        return $y;
    }
    /**
     * Compute the Hash / HMAC / UMAC.
     *
     * @access public
     * @param string $text
     * @return string
     */
    public function hash($text)
    {
        $algo = $this->algo;
        if ($algo == 'umac') {
            if ($this->recomputeAESKey) {
                if (!is_string($this->nonce)) {
                    throw new InsufficientSetupException('No nonce has been set');
                }
                if (!is_string($this->key)) {
                    throw new InsufficientSetupException('No key has been set');
                }
                if (strlen($this->key) != 16) {
                    throw new \LengthException('Key must be 16 bytes long');
                }
                if (!isset(self::$maxwordrange64)) {
                    $one = new BigInteger(1);
                    $prime36 = new BigInteger("\x00\x00\x00\x0f\xff\xff\xff\xfb", 256);
                    self::$factory36 = new PrimeField($prime36);
                    $prime64 = new BigInteger("\xff\xff\xff\xff\xff\xff\xff\xc5", 256);
                    self::$factory64 = new PrimeField($prime64);
                    $prime128 = new BigInteger("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffa", 256);
                    self::$factory128 = new PrimeField($prime128);
                    self::$offset64 = new BigInteger("\x01\x00\x00\x00\x00\x00\x00\x00\x00", 256);
                    self::$offset64 = self::$factory64->newInteger(self::$offset64->subtract($prime64));
                    self::$offset128 = new BigInteger("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 256);
                    self::$offset128 = self::$factory128->newInteger(self::$offset128->subtract($prime128));
                    self::$marker64 = self::$factory64->newInteger($prime64->subtract($one));
                    self::$marker128 = self::$factory128->newInteger($prime128->subtract($one));
                    $maxwordrange64 = $one->bitwise_leftShift(64)->subtract($one->bitwise_leftShift(32));
                    self::$maxwordrange64 = self::$factory64->newInteger($maxwordrange64);
                    $maxwordrange128 = $one->bitwise_leftShift(128)->subtract($one->bitwise_leftShift(96));
                    self::$maxwordrange128 = self::$factory128->newInteger($maxwordrange128);
                }
                $this->c = new AES('ctr');
                $this->c->disablePadding();
                $this->c->setKey($this->key);
                $this->pad = $this->pdf();
                $this->recomputeAESKey = false;
            }
            $hashedmessage = $this->uhash($text, $this->length);
            return $hashedmessage ^ $this->pad;
        }
        if (is_array($algo)) {
            if (empty($this->key) || !is_string($this->key)) {
                return \Phabel\Target\Php80\Polyfill::substr($algo($text, ...array_values($this->parameters)), 0, $this->length);
            }
            // SHA3 HMACs are discussed at https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=30
            $key = str_pad($this->computedKey, $b, chr(0));
            $temp = $this->ipad ^ $key;
            $temp .= $text;
            $temp = \Phabel\Target\Php80\Polyfill::substr($algo($temp, ...array_values($this->parameters)), 0, $this->length);
            $output = $this->opad ^ $key;
            $output .= $temp;
            $output = $algo($output, ...array_values($this->parameters));
            return \Phabel\Target\Php80\Polyfill::substr($output, 0, $this->length);
        }
        $output = !empty($this->key) || is_string($this->key) ? hash_hmac($algo, $text, $this->computedKey, true) : hash($algo, $text, true);
        return strlen($output) > $this->length ? \Phabel\Target\Php80\Polyfill::substr($output, 0, $this->length) : $output;
    }
    /**
     * Returns the hash length (in bits)
     *
     * @access public
     * @return int
     */
    public function getLength()
    {
        return $this->length << 3;
    }
    /**
     * Returns the hash length (in bytes)
     *
     * @access public
     * @return int
     */
    public function getLengthInBytes()
    {
        return $this->length;
    }
    /**
     * Returns the block length (in bits)
     *
     * @access public
     * @return int
     */
    public function getBlockLength()
    {
        return $this->blockSize;
    }
    /**
     * Returns the block length (in bytes)
     *
     * @access public
     * @return int
     */
    public function getBlockLengthInBytes()
    {
        return $this->blockSize >> 3;
    }
    /**
     * Pads SHA3 based on the mode
     *
     * @access private
     * @param int $padLength
     * @param int $padType
     * @return string
     */
    private static function sha3_pad($padLength, $padType)
    {
        switch ($padType) {
            //case self::PADDING_KECCAK:
            //    $temp = chr(0x06) . str_repeat("\0", $padLength - 1);
            //    $temp[$padLength - 1] = $temp[$padLength - 1] | chr(0x80);
            //    return $temp
            case self::PADDING_SHAKE:
                $temp = chr(0x1f) . str_repeat("\x00", $padLength - 1);
                $temp[$padLength - 1] = $temp[$padLength - 1] | chr(0x80);
                return $temp;
            //case self::PADDING_SHA3:
            default:
                // from https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=36
                return $padLength == 1 ? chr(0x86) : chr(0x6) . str_repeat("\x00", $padLength - 2) . chr(0x80);
        }
    }
    /**
    * Pure-PHP 32-bit implementation of SHA3
    *
    * Whereas BigInteger.php's 32-bit engine works on PHP 64-bit this 32-bit implementation
    of SHA3 will *not* work on PHP 64-bit. This is because this implementation
    employees bitwise NOTs and bitwise left shifts. And the round constants only work
    on 32-bit PHP. eg. dechex(-2147483648) returns 80000000 on 32-bit PHP and
    FFFFFFFF80000000 on 64-bit PHP. Sure, we could do bitwise ANDs but that would slow
    things down.
    *
    * SHA512 requires BigInteger to simulate 64-bit unsigned integers because SHA2 employees
    addition whereas SHA3 just employees bitwise operators. PHP64 only supports signed
    64-bit integers, which complicates addition, whereas that limitation isn't an issue
    for SHA3.
    *
    * In https://ws680.nist.gov/publication/get_pdf.cfm?pub_id=919061#page=16 KECCAK[C] is
    defined as "the KECCAK instance with KECCAK-f[1600] as the underlying permutation and
    capacity c". This is relevant because, altho the KECCAK standard defines a mode
    (KECCAK-f[800]) designed for 32-bit machines that mode is incompatible with SHA3
    *
    * @access private
    * @param string $p
    * @param int $c
    * @param int $r
    * @param int $d
    * @param int $padType
    */
    private static function sha3_32($p, $c, $r, $d, $padType)
    {
        $block_size = $r >> 3;
        $padLength = $block_size - strlen($p) % $block_size;
        $num_ints = $block_size >> 2;
        $p .= static::sha3_pad($padLength, $padType);
        $n = strlen($p) / $r;
        // number of blocks
        $s = [[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]];
        $p = str_split($p, $block_size);
        foreach ($p as $pi) {
            $pi = unpack('V*', $pi);
            $x = $y = 0;
            for ($i = 1; $i <= $num_ints; $i += 2) {
                $s[$x][$y][0] ^= $pi[$i + 1];
                $s[$x][$y][1] ^= $pi[$i];
                if (++$y == 5) {
                    $y = 0;
                    $x++;
                }
            }
            static::processSHA3Block32($s);
        }
        $z = '';
        $i = $j = 0;
        while (strlen($z) < $d) {
            $z .= pack('V2', $s[$i][$j][1], $s[$i][$j++][0]);
            if ($j == 5) {
                $j = 0;
                $i++;
                if ($i == 5) {
                    $i = 0;
                    static::processSHA3Block32($s);
                }
            }
        }
        return $z;
    }
    /**
     * 32-bit block processing method for SHA3
     *
     * @access private
     * @param array $s
     */
    private static function processSHA3Block32(&$s)
    {
        static $rotationOffsets = [[0, 1, 62, 28, 27], [36, 44, 6, 55, 20], [3, 10, 43, 25, 39], [41, 45, 15, 21, 8], [18, 2, 61, 56, 14]];
        // the standards give these constants in hexadecimal notation. it's tempting to want to use
        // that same notation, here, however, we can't, because 0x80000000, on PHP32, is a positive
        // float - not the negative int that we need to be in PHP32. so we use -2147483648 instead
        static $roundConstants = [[0, 1], [0, 32898], [-2147483648, 32906], [-2147483648, -2147450880], [0, 32907], [0, -2147483647], [-2147483648, -2147450751], [-2147483648, 32777], [0, 138], [0, 136], [0, -2147450871], [0, -2147483638], [0, -2147450741], [-2147483648, 139], [-2147483648, 32905], [-2147483648, 32771], [-2147483648, 32770], [-2147483648, 128], [0, 32778], [-2147483648, -2147483638], [-2147483648, -2147450751], [-2147483648, 32896], [0, -2147483647], [-2147483648, -2147450872]];
        for ($round = 0; $round < 24; $round++) {
            // theta step
            $parity = $rotated = [];
            for ($i = 0; $i < 5; $i++) {
                $parity[] = [$s[0][$i][0] ^ $s[1][$i][0] ^ $s[2][$i][0] ^ $s[3][$i][0] ^ $s[4][$i][0], $s[0][$i][1] ^ $s[1][$i][1] ^ $s[2][$i][1] ^ $s[3][$i][1] ^ $s[4][$i][1]];
                $rotated[] = static::rotateLeft32($parity[$i], 1);
            }
            $temp = [[$parity[4][0] ^ $rotated[1][0], $parity[4][1] ^ $rotated[1][1]], [$parity[0][0] ^ $rotated[2][0], $parity[0][1] ^ $rotated[2][1]], [$parity[1][0] ^ $rotated[3][0], $parity[1][1] ^ $rotated[3][1]], [$parity[2][0] ^ $rotated[4][0], $parity[2][1] ^ $rotated[4][1]], [$parity[3][0] ^ $rotated[0][0], $parity[3][1] ^ $rotated[0][1]]];
            for ($i = 0; $i < 5; $i++) {
                for ($j = 0; $j < 5; $j++) {
                    $s[$i][$j][0] ^= $temp[$j][0];
                    $s[$i][$j][1] ^= $temp[$j][1];
                }
            }
            $st = $s;
            // rho and pi steps
            for ($i = 0; $i < 5; $i++) {
                for ($j = 0; $j < 5; $j++) {
                    $st[(2 * $i + 3 * $j) % 5][$j] = static::rotateLeft32($s[$j][$i], $rotationOffsets[$j][$i]);
                }
            }
            // chi step
            for ($i = 0; $i < 5; $i++) {
                $s[$i][0] = [$st[$i][0][0] ^ ~$st[$i][1][0] & $st[$i][2][0], $st[$i][0][1] ^ ~$st[$i][1][1] & $st[$i][2][1]];
                $s[$i][1] = [$st[$i][1][0] ^ ~$st[$i][2][0] & $st[$i][3][0], $st[$i][1][1] ^ ~$st[$i][2][1] & $st[$i][3][1]];
                $s[$i][2] = [$st[$i][2][0] ^ ~$st[$i][3][0] & $st[$i][4][0], $st[$i][2][1] ^ ~$st[$i][3][1] & $st[$i][4][1]];
                $s[$i][3] = [$st[$i][3][0] ^ ~$st[$i][4][0] & $st[$i][0][0], $st[$i][3][1] ^ ~$st[$i][4][1] & $st[$i][0][1]];
                $s[$i][4] = [$st[$i][4][0] ^ ~$st[$i][0][0] & $st[$i][1][0], $st[$i][4][1] ^ ~$st[$i][0][1] & $st[$i][1][1]];
            }
            // iota step
            $s[0][0][0] ^= $roundConstants[$round][0];
            $s[0][0][1] ^= $roundConstants[$round][1];
        }
    }
    /**
     * Rotate 32-bit int
     *
     * @access private
     * @param array $x
     * @param int $shift
     */
    private static function rotateLeft32($x, $shift)
    {
        if ($shift < 32) {
            list($hi, $lo) = $x;
        } else {
            $shift -= 32;
            list($lo, $hi) = $x;
        }
        return [$hi << $shift | $lo >> 32 - $shift & (1 << $shift) - 1, $lo << $shift | $hi >> 32 - $shift & (1 << $shift) - 1];
    }
    /**
     * Pure-PHP 64-bit implementation of SHA3
     *
     * @access private
     * @param string $p
     * @param int $c
     * @param int $r
     * @param int $d
     * @param int $padType
     */
    private static function sha3_64($p, $c, $r, $d, $padType)
    {
        $block_size = $r >> 3;
        $padLength = $block_size - strlen($p) % $block_size;
        $num_ints = $block_size >> 2;
        $p .= static::sha3_pad($padLength, $padType);
        $n = strlen($p) / $r;
        // number of blocks
        $s = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]];
        $p = str_split($p, $block_size);
        foreach ($p as $pi) {
            $pi = unpack('P*', $pi);
            $x = $y = 0;
            foreach ($pi as $subpi) {
                $s[$x][$y++] ^= $subpi;
                if ($y == 5) {
                    $y = 0;
                    $x++;
                }
            }
            static::processSHA3Block64($s);
        }
        $z = '';
        $i = $j = 0;
        while (strlen($z) < $d) {
            $z .= pack('P', $s[$i][$j++]);
            if ($j == 5) {
                $j = 0;
                $i++;
                if ($i == 5) {
                    $i = 0;
                    static::processSHA3Block64($s);
                }
            }
        }
        return $z;
    }
    /**
     * 64-bit block processing method for SHA3
     *
     * @access private
     * @param array $s
     */
    private static function processSHA3Block64(&$s)
    {
        static $rotationOffsets = [[0, 1, 62, 28, 27], [36, 44, 6, 55, 20], [3, 10, 43, 25, 39], [41, 45, 15, 21, 8], [18, 2, 61, 56, 14]];
        static $roundConstants = [1, 32898, -9223372036854742902, -9223372034707259392, 32907, 2147483649, -9223372034707259263, -9223372036854743031, 138, 136, 2147516425, 2147483658, 2147516555, -9223372036854775669, -9223372036854742903, -9223372036854743037, -9223372036854743038, -9223372036854775680, 32778, -9223372034707292150, -9223372034707259263, -9223372036854742912, 2147483649, -9223372034707259384];
        for ($round = 0; $round < 24; $round++) {
            // theta step
            $parity = [];
            for ($i = 0; $i < 5; $i++) {
                $parity[] = $s[0][$i] ^ $s[1][$i] ^ $s[2][$i] ^ $s[3][$i] ^ $s[4][$i];
            }
            $temp = [$parity[4] ^ static::rotateLeft64($parity[1], 1), $parity[0] ^ static::rotateLeft64($parity[2], 1), $parity[1] ^ static::rotateLeft64($parity[3], 1), $parity[2] ^ static::rotateLeft64($parity[4], 1), $parity[3] ^ static::rotateLeft64($parity[0], 1)];
            for ($i = 0; $i < 5; $i++) {
                for ($j = 0; $j < 5; $j++) {
                    $s[$i][$j] ^= $temp[$j];
                }
            }
            $st = $s;
            // rho and pi steps
            for ($i = 0; $i < 5; $i++) {
                for ($j = 0; $j < 5; $j++) {
                    $st[(2 * $i + 3 * $j) % 5][$j] = static::rotateLeft64($s[$j][$i], $rotationOffsets[$j][$i]);
                }
            }
            // chi step
            for ($i = 0; $i < 5; $i++) {
                $s[$i] = [$st[$i][0] ^ ~$st[$i][1] & $st[$i][2], $st[$i][1] ^ ~$st[$i][2] & $st[$i][3], $st[$i][2] ^ ~$st[$i][3] & $st[$i][4], $st[$i][3] ^ ~$st[$i][4] & $st[$i][0], $st[$i][4] ^ ~$st[$i][0] & $st[$i][1]];
            }
            // iota step
            $s[0][0] ^= $roundConstants[$round];
        }
    }
    /**
     * Rotate 64-bit int
     *
     * @access private
     * @param int $x
     * @param int $shift
     */
    private static function rotateLeft64($x, $shift)
    {
        return $x << $shift | $x >> 64 - $shift & (1 << $shift) - 1;
    }
    /**
     * Pure-PHP implementation of SHA512
     *
     * @access private
     * @param string $m
     * @param array $hash
     * @return string
     */
    private static function sha512($m, $hash)
    {
        static $k;
        if (!isset($k)) {
            // Initialize table of round constants
            // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
            $k = ['428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'];
            for ($i = 0; $i < 80; $i++) {
                $k[$i] = new BigInteger($k[$i], 16);
            }
        }
        // Pre-processing
        $length = strlen($m);
        // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
        $m .= str_repeat(chr(0), 128 - ($length + 16 & 0x7f));
        $m[$length] = chr(0x80);
        // we don't support hashing strings 512MB long
        $m .= pack('N4', 0, 0, 0, $length << 3);
        // Process the message in successive 1024-bit chunks
        $chunks = str_split($m, 128);
        foreach ($chunks as $chunk) {
            $w = [];
            for ($i = 0; $i < 16; $i++) {
                $temp = new BigInteger(Strings::shift($chunk, 8), 256);
                $temp->setPrecision(64);
                $w[] = $temp;
            }
            // Extend the sixteen 32-bit words into eighty 32-bit words
            for ($i = 16; $i < 80; $i++) {
                $temp = [$w[$i - 15]->bitwise_rightRotate(1), $w[$i - 15]->bitwise_rightRotate(8), $w[$i - 15]->bitwise_rightShift(7)];
                $s0 = $temp[0]->bitwise_xor($temp[1]);
                $s0 = $s0->bitwise_xor($temp[2]);
                $temp = [$w[$i - 2]->bitwise_rightRotate(19), $w[$i - 2]->bitwise_rightRotate(61), $w[$i - 2]->bitwise_rightShift(6)];
                $s1 = $temp[0]->bitwise_xor($temp[1]);
                $s1 = $s1->bitwise_xor($temp[2]);
                $w[$i] = clone $w[$i - 16];
                $w[$i] = $w[$i]->add($s0);
                $w[$i] = $w[$i]->add($w[$i - 7]);
                $w[$i] = $w[$i]->add($s1);
            }
            // Initialize hash value for this chunk
            $a = clone $hash[0];
            $b = clone $hash[1];
            $c = clone $hash[2];
            $d = clone $hash[3];
            $e = clone $hash[4];
            $f = clone $hash[5];
            $g = clone $hash[6];
            $h = clone $hash[7];
            // Main loop
            for ($i = 0; $i < 80; $i++) {
                $temp = [$a->bitwise_rightRotate(28), $a->bitwise_rightRotate(34), $a->bitwise_rightRotate(39)];
                $s0 = $temp[0]->bitwise_xor($temp[1]);
                $s0 = $s0->bitwise_xor($temp[2]);
                $temp = [$a->bitwise_and($b), $a->bitwise_and($c), $b->bitwise_and($c)];
                $maj = $temp[0]->bitwise_xor($temp[1]);
                $maj = $maj->bitwise_xor($temp[2]);
                $t2 = $s0->add($maj);
                $temp = [$e->bitwise_rightRotate(14), $e->bitwise_rightRotate(18), $e->bitwise_rightRotate(41)];
                $s1 = $temp[0]->bitwise_xor($temp[1]);
                $s1 = $s1->bitwise_xor($temp[2]);
                $temp = [$e->bitwise_and($f), $g->bitwise_and($e->bitwise_not())];
                $ch = $temp[0]->bitwise_xor($temp[1]);
                $t1 = $h->add($s1);
                $t1 = $t1->add($ch);
                $t1 = $t1->add($k[$i]);
                $t1 = $t1->add($w[$i]);
                $h = clone $g;
                $g = clone $f;
                $f = clone $e;
                $e = $d->add($t1);
                $d = clone $c;
                $c = clone $b;
                $b = clone $a;
                $a = $t1->add($t2);
            }
            // Add this chunk's hash to result so far
            $hash = [$hash[0]->add($a), $hash[1]->add($b), $hash[2]->add($c), $hash[3]->add($d), $hash[4]->add($e), $hash[5]->add($f), $hash[6]->add($g), $hash[7]->add($h)];
        }
        // Produce the final hash value (big-endian)
        // (\phpseclib3\Crypt\Hash::hash() trims the output for hashes but not for HMACs.  as such, we trim the output here)
        $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . $hash[4]->toBytes() . $hash[5]->toBytes() . $hash[6]->toBytes() . $hash[7]->toBytes();
        return $temp;
    }
    /**
     * __toString() magic method
     */
    public function __toString()
    {
        return $this->getHash();
    }
}<?php

/**
 * Pure-PHP implementation of EC.
 *
 * PHP version 5
 *
 * Here's an example of how to create signatures and verify signatures with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $private = \phpseclib3\Crypt\EC::createKey('secp256k1');
 * $public = $private->getPublicKey();
 *
 * $plaintext = 'terrafrost';
 *
 * $signature = $private->sign($plaintext);
 *
 * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\EC\PrivateKey;
use phpseclib3\Crypt\EC\PublicKey;
use phpseclib3\Crypt\EC\Parameters;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Crypt\EC\Curves\Ed448;
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
use phpseclib3\File\ASN1\Maps\ECParameters;
use phpseclib3\File\ASN1;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Exception\UnsupportedOperationException;
/**
 * Pure-PHP implementation of EC.
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EC extends AsymmetricKey
{
    /**
     * Algorithm Name
     *
     * @var string
     * @access private
     */
    const ALGORITHM = 'EC';
    /**
     * Public Key QA
     *
     * @var object[]
     */
    protected $QA;
    /**
     * Curve
     *
     * @var \phpseclib3\Crypt\EC\BaseCurves\Base
     */
    protected $curve;
    /**
     * Signature Format
     *
     * @var string
     * @access private
     */
    protected $format;
    /**
     * Signature Format (Short)
     *
     * @var string
     * @access private
     */
    protected $shortFormat;
    /**
     * Curve Name
     *
     * @var string
     */
    private $curveName;
    /**
     * Curve Order
     *
     * Used for deterministic ECDSA
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected $q;
    /**
     * Alias for the private key
     *
     * Used for deterministic ECDSA. AsymmetricKey expects $x. I don't like x because
     * with x you have x * the base point yielding an (x, y)-coordinate that is the
     * public key. But the x is different depending on which side of the equal sign
     * you're on. It's less ambiguous if you do dA * base point = (x, y)-coordinate.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected $x;
    /**
     * Context
     *
     * @var string
     */
    protected $context;
    /**
     * Create public / private key pair.
     *
     * @access public
     * @param string $curve
     * @return \phpseclib3\Crypt\EC\PrivateKey
     */
    public static function createKey($curve)
    {
        self::initialize_static_variables();
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        $curve = strtolower($curve);
        if (self::$engines['libsodium'] && $curve == 'ed25519' && function_exists('sodium_crypto_sign_keypair')) {
            $kp = sodium_crypto_sign_keypair();
            $privatekey = EC::loadFormat('libsodium', sodium_crypto_sign_secretkey($kp));
            //$publickey = EC::loadFormat('libsodium', sodium_crypto_sign_publickey($kp));
            $privatekey->curveName = 'Ed25519';
            //$publickey->curveName = $curve;
            return $privatekey;
        }
        $privatekey = new PrivateKey();
        $curveName = $curve;
        if (preg_match('#(?:^curve|^ed)\\d+$#', $curveName)) {
            $curveName = ucfirst($curveName);
        } elseif (\Phabel\Target\Php80\Polyfill::substr($curveName, 0, 10) == 'brainpoolp') {
            $curveName = 'brainpoolP' . \Phabel\Target\Php80\Polyfill::substr($curveName, 10);
        }
        $curve = '\\phpseclib3\\Crypt\\EC\\Curves\\' . $curveName;
        if (!class_exists($curve)) {
            throw new UnsupportedCurveException('Named Curve of ' . $curveName . ' is not supported');
        }
        $reflect = new \ReflectionClass($curve);
        $curveName = $reflect->isFinal() ? $reflect->getParentClass()->getShortName() : $reflect->getShortName();
        $curve = new $curve();
        $privatekey->dA = $dA = $curve->createRandomMultiplier();
        if ($curve instanceof Curve25519 && self::$engines['libsodium']) {
            //$r = pack('H*', '0900000000000000000000000000000000000000000000000000000000000000');
            //$QA = sodium_crypto_scalarmult($dA->toBytes(), $r);
            $QA = sodium_crypto_box_publickey_from_secretkey($dA->toBytes());
            $privatekey->QA = [$curve->convertInteger(new BigInteger(strrev($QA), 256))];
        } else {
            $privatekey->QA = $curve->multiplyPoint($curve->getBasePoint(), $dA);
        }
        $privatekey->curve = $curve;
        //$publickey = clone $privatekey;
        //unset($publickey->dA);
        //unset($publickey->x);
        $privatekey->curveName = $curveName;
        //$publickey->curveName = $curveName;
        if ($privatekey->curve instanceof TwistedEdwardsCurve) {
            return $privatekey->withHash($curve::HASH);
        }
        return $privatekey;
    }
    /**
     * OnLoad Handler
     *
     * @return bool
     * @access protected
     * @param array $components
     */
    protected static function onLoad($components)
    {
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        if (!isset($components['dA']) && !isset($components['QA'])) {
            $new = new Parameters();
            $new->curve = $components['curve'];
            return $new;
        }
        $new = isset($components['dA']) ? new PrivateKey() : new PublicKey();
        $new->curve = $components['curve'];
        $new->QA = $components['QA'];
        if (isset($components['dA'])) {
            $new->dA = $components['dA'];
        }
        if ($new->curve instanceof TwistedEdwardsCurve) {
            return $new->withHash($components['curve']::HASH);
        }
        return $new;
    }
    /**
     * Constructor
     *
     * PublicKey and PrivateKey objects can only be created from abstract RSA class
     */
    protected function __construct()
    {
        $this->sigFormat = self::validatePlugin('Signature', 'ASN1');
        $this->shortFormat = 'ASN1';
        parent::__construct();
    }
    /**
     * Returns the curve
     *
     * Returns a string if it's a named curve, an array if not
     *
     * @access public
     * @return (string | array)
     */
    public function getCurve()
    {
        if ($this->curveName) {
            return $this->curveName;
        }
        if ($this->curve instanceof MontgomeryCurve) {
            $this->curveName = $this->curve instanceof Curve25519 ? 'Curve25519' : 'Curve448';
            return $this->curveName;
        }
        if ($this->curve instanceof TwistedEdwardsCurve) {
            $this->curveName = $this->curve instanceof Ed25519 ? 'Ed25519' : 'Ed448';
            return $this->curveName;
        }
        $params = $this->getParameters()->toString('PKCS8', ['namedCurve' => true]);
        $decoded = ASN1::extractBER($params);
        $decoded = ASN1::decodeBER($decoded);
        $decoded = ASN1::asn1map($decoded[0], ECParameters::MAP);
        if (isset($decoded['namedCurve'])) {
            $this->curveName = $decoded['namedCurve'];
            return $decoded['namedCurve'];
        }
        if (!$namedCurves) {
            PKCS1::useSpecifiedCurve();
        }
        return $decoded;
    }
    /**
    * Returns the key size
    *
    * Quoting https://tools.ietf.org/html/rfc5656#section-2,
    *
    * "The size of a set of elliptic curve domain parameters on a prime
    curve is defined as the number of bits in the binary representation
    of the field order, commonly denoted by p.  Size on a
    characteristic-2 curve is defined as the number of bits in the binary
    representation of the field, commonly denoted by m.  A set of
    elliptic curve domain parameters defines a group of order n generated
    by a base point P"
    *
    * @access public
    * @return int
    */
    public function getLength()
    {
        return $this->curve->getLength();
    }
    /**
     * Returns the current engine being used
     *
     * @see self::useInternalEngine()
     * @see self::useBestEngine()
     * @access public
     * @return string
     */
    public function getEngine()
    {
        if ($this->curve instanceof TwistedEdwardsCurve) {
            return $this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context) ? 'libsodium' : 'PHP';
        }
        return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ? 'OpenSSL' : 'PHP';
    }
    /**
     * Returns the public key coordinates as a string
     *
     * Used by ECDH
     *
     * @return string
     */
    public function getEncodedCoordinates()
    {
        if ($this->curve instanceof MontgomeryCurve) {
            return strrev($this->QA[0]->toBytes(true));
        }
        if ($this->curve instanceof TwistedEdwardsCurve) {
            return $this->curve->encodePoint($this->QA);
        }
        return "\x04" . $this->QA[0]->toBytes(true) . $this->QA[1]->toBytes(true);
    }
    /**
     * Returns the parameters
     *
     * @see self::getPublicKey()
     * @access public
     * @param string $type optional
     * @return mixed
     */
    public function getParameters($type = 'PKCS1')
    {
        $type = self::validatePlugin('Keys', $type, 'saveParameters');
        $key = $type::saveParameters($this->curve);
        return EC::load($key, 'PKCS1')->withHash($this->hash->getHash())->withSignatureFormat($this->shortFormat);
    }
    /**
     * Determines the signature padding mode
     *
     * Valid values are: ASN1, SSH2, Raw
     *
     * @access public
     * @param string $format
     */
    public function withSignatureFormat($format)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
        }
        $new = clone $this;
        $new->shortFormat = $format;
        $new->sigFormat = self::validatePlugin('Signature', $format);
        return $new;
    }
    /**
     * Returns the signature format currently being used
     *
     * @access public
     */
    public function getSignatureFormat()
    {
        return $this->shortFormat;
    }
    /**
     * Sets the context
     *
     * Used by Ed25519 / Ed448.
     *
     * @see self::sign()
     * @see self::verify()
     * @access public
     * @param string $context optional
     */
    public function withContext($context = null)
    {
        if (!$this->curve instanceof TwistedEdwardsCurve) {
            throw new UnsupportedCurveException('Only Ed25519 and Ed448 support contexts');
        }
        $new = clone $this;
        if (!isset($context)) {
            $new->context = null;
            return $new;
        }
        if (!is_string($context)) {
            throw new \InvalidArgumentException('setContext expects a string');
        }
        if (strlen($context) > 255) {
            throw new \LengthException('The context is supposed to be, at most, 255 bytes long');
        }
        $new->context = $context;
        return $new;
    }
    /**
     * Returns the signature format currently being used
     *
     * @access public
     */
    public function getContext()
    {
        return $this->context;
    }
    /**
     * Determines which hashing function should be used
     *
     * @access public
     * @param string $hash
     */
    public function withHash($hash)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
        }
        if ($this->curve instanceof Ed25519 && $hash != 'sha512') {
            throw new UnsupportedAlgorithmException('Ed25519 only supports sha512 as a hash');
        }
        if ($this->curve instanceof Ed448 && $hash != 'shake256-912') {
            throw new UnsupportedAlgorithmException('Ed448 only supports shake256 with a length of 114 bytes');
        }
        return parent::withHash($hash);
    }
    /**
     * __toString() magic method
     *
     * @return string
     */
    public function __toString()
    {
        if ($this->curve instanceof MontgomeryCurve) {
            return '';
        }
        return parent::__toString();
    }
}<?php

/**
 * Pure-PHP PKCS#1 (v2.1) compliant implementation of RSA.
 *
 * PHP version 5
 *
 * Here's an example of how to encrypt and decrypt text with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $private = \phpseclib3\Crypt\RSA::createKey();
 * $public = $private->getPublicKey();
 *
 * $plaintext = 'terrafrost';
 *
 * $ciphertext = $public->encrypt($plaintext);
 *
 * echo $private->decrypt($ciphertext);
 * ?>
 * </code>
 *
 * Here's an example of how to create signatures and verify signatures with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $private = \phpseclib3\Crypt\RSA::createKey();
 * $public = $private->getPublicKey();
 *
 * $plaintext = 'terrafrost';
 *
 * $signature = $private->sign($plaintext);
 *
 * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
 * ?>
 * </code>
 *
 * One thing to consider when using this: so phpseclib uses PSS mode by default.
 * Technically, id-RSASSA-PSS has a different key format than rsaEncryption. So
 * should phpseclib save to the id-RSASSA-PSS format by default or the
 * rsaEncryption format? For stand-alone keys I figure rsaEncryption is better
 * because SSH doesn't use PSS and idk how many SSH servers would be able to
 * decode an id-RSASSA-PSS key. For X.509 certificates the id-RSASSA-PSS
 * format is used by default (unless you change it up to use PKCS1 instead)
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\RSA\PrivateKey;
use phpseclib3\Crypt\RSA\PublicKey;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Exception\InconsistentSetupException;
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
/**
 * Pure-PHP PKCS#1 compliant implementation of RSA.
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RSA extends AsymmetricKey
{
    /**
     * Algorithm Name
     *
     * @var string
     * @access private
     */
    const ALGORITHM = 'RSA';
    /**
     * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
     * (OAEP) for encryption / decryption.
     *
     * Uses sha256 by default
     *
     * @see self::setHash()
     * @see self::setMGFHash()
     * @access public
     * @see self::encrypt()
     * @see self::decrypt()
     */
    const ENCRYPTION_OAEP = 1;
    /**
     * Use PKCS#1 padding.
     *
     * Although self::PADDING_OAEP / self::PADDING_PSS  offers more security, including PKCS#1 padding is necessary for purposes of backwards
     * compatibility with protocols (like SSH-1) written before OAEP's introduction.
     *
     * @access public
     * @see self::encrypt()
     * @see self::decrypt()
     */
    const ENCRYPTION_PKCS1 = 2;
    /**
     * Do not use any padding
     *
     * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy
     * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc.
     *
     * @access public
     * @see self::encrypt()
     * @see self::decrypt()
     */
    const ENCRYPTION_NONE = 4;
    /**
     * Use the Probabilistic Signature Scheme for signing
     *
     * Uses sha256 and 0 as the salt length
     *
     * @see self::setSaltLength()
     * @see self::setMGFHash()
     * @see self::setHash()
     * @see self::sign()
     * @see self::verify()
     * @see self::setHash()
     * @access public
     */
    const SIGNATURE_PSS = 16;
    /**
     * Use a relaxed version of PKCS#1 padding for signature verification
     *
     * @see self::sign()
     * @see self::verify()
     * @see self::setHash()
     * @access public
     */
    const SIGNATURE_RELAXED_PKCS1 = 32;
    /**
     * Use PKCS#1 padding for signature verification
     *
     * @see self::sign()
     * @see self::verify()
     * @see self::setHash()
     * @access public
     */
    const SIGNATURE_PKCS1 = 64;
    /**
     * Encryption padding mode
     *
     * @var int
     * @access private
     */
    protected $encryptionPadding = self::ENCRYPTION_OAEP;
    /**
     * Signature padding mode
     *
     * @var int
     * @access private
     */
    protected $signaturePadding = self::SIGNATURE_PSS;
    /**
     * Length of hash function output
     *
     * @var int
     * @access private
     */
    protected $hLen;
    /**
     * Length of salt
     *
     * @var int
     * @access private
     */
    protected $sLen;
    /**
     * Label
     *
     * @var string
     * @access private
     */
    protected $label = '';
    /**
     * Hash function for the Mask Generation Function
     *
     * @var \phpseclib3\Crypt\Hash
     * @access private
     */
    protected $mgfHash;
    /**
     * Length of MGF hash function output
     *
     * @var int
     * @access private
     */
    protected $mgfHLen;
    /**
     * Modulus (ie. n)
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $modulus;
    /**
     * Modulus length
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $k;
    /**
     * Exponent (ie. e or d)
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $exponent;
    /**
     * Default public exponent
     *
     * @var int
     * @link http://en.wikipedia.org/wiki/65537_%28number%29
     * @access private
     */
    private static $defaultExponent = 65537;
    /**
     * Enable Blinding?
     *
     * @var bool
     * @access private
     */
    protected static $enableBlinding = true;
    /**
     * OpenSSL configuration file name.
     *
     * @see self::createKey()
     * @var ?string
     */
    protected static $configFile;
    /**
     * Smallest Prime
     *
     * Per <http://cseweb.ucsd.edu/~hovav/dist/survey.pdf#page=5>, this number ought not result in primes smaller
     * than 256 bits. As a consequence if the key you're trying to create is 1024 bits and you've set smallestPrime
     * to 384 bits then you're going to get a 384 bit prime and a 640 bit prime (384 + 1024 % 384). At least if
     * engine is set to self::ENGINE_INTERNAL. If Engine is set to self::ENGINE_OPENSSL then smallest Prime is
     * ignored (ie. multi-prime RSA support is more intended as a way to speed up RSA key generation when there's
     * a chance neither gmp nor OpenSSL are installed)
     *
     * @var int
     * @access private
     */
    private static $smallestPrime = 4096;
    /**
     * Sets the public exponent for key generation
     *
     * This will be 65537 unless changed.
     *
     * @access public
     * @param int $val
     */
    public static function setExponent($val)
    {
        self::$defaultExponent = $val;
    }
    /**
     * Sets the smallest prime number in bits. Used for key generation
     *
     * This will be 4096 unless changed.
     *
     * @access public
     * @param int $val
     */
    public static function setSmallestPrime($val)
    {
        self::$smallestPrime = $val;
    }
    /**
     * Sets the OpenSSL config file path
     *
     * Set to the empty string to use the default config file
     *
     * @access public
     * @param string $val
     */
    public static function setOpenSSLConfigPath($val)
    {
        self::$configFile = $val;
    }
    /**
     * Create a private key
     *
     * The public key can be extracted from the private key
     *
     * @return RSA
     * @access public
     * @param int $bits
     */
    public static function createKey($bits = 2048)
    {
        self::initialize_static_variables();
        $regSize = $bits >> 1;
        // divide by two to see how many bits P and Q would be
        if ($regSize > self::$smallestPrime) {
            $num_primes = floor($bits / self::$smallestPrime);
            $regSize = self::$smallestPrime;
        } else {
            $num_primes = 2;
        }
        if ($num_primes == 2 && $bits >= 384 && self::$defaultExponent == 65537) {
            if (!isset(self::$engines['PHP'])) {
                self::useBestEngine();
            }
            // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
            if (self::$engines['OpenSSL']) {
                $config = [];
                if (self::$configFile) {
                    $config['config'] = self::$configFile;
                }
                $rsa = openssl_pkey_new(['private_key_bits' => $bits] + $config);
                openssl_pkey_export($rsa, $privatekeystr, null, $config);
                // clear the buffer of error strings stemming from a minimalistic openssl.cnf
                while (openssl_error_string() !== false) {
                }
                return RSA::load($privatekeystr);
            }
        }
        static $e;
        if (!isset($e)) {
            $e = new BigInteger(self::$defaultExponent);
        }
        $n = clone self::$one;
        $exponents = $coefficients = $primes = [];
        $lcm = ['top' => clone self::$one, 'bottom' => false];
        do {
            for ($i = 1; $i <= $num_primes; $i++) {
                if ($i != $num_primes) {
                    $primes[$i] = BigInteger::randomPrime($regSize);
                } else {
                    extract(BigInteger::minMaxBits($bits));
                    /** @var BigInteger $min
                     *  @var BigInteger $max
                     */
                    list($min) = $min->divide($n);
                    $min = $min->add(self::$one);
                    list($max) = $max->divide($n);
                    $primes[$i] = BigInteger::randomRangePrime($min, $max);
                }
                // the first coefficient is calculated differently from the rest
                // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1])
                if ($i > 2) {
                    $coefficients[$i] = $n->modInverse($primes[$i]);
                }
                $n = $n->multiply($primes[$i]);
                $temp = $primes[$i]->subtract(self::$one);
                // textbook RSA implementations use Euler's totient function instead of the least common multiple.
                // see http://en.wikipedia.org/wiki/Euler%27s_totient_function
                $lcm['top'] = $lcm['top']->multiply($temp);
                $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp);
            }
            list($temp) = $lcm['top']->divide($lcm['bottom']);
            $gcd = $temp->gcd($e);
            $i0 = 1;
        } while (!$gcd->equals(self::$one));
        $coefficients[2] = $primes[2]->modInverse($primes[1]);
        $d = $e->modInverse($temp);
        foreach ($primes as $i => $prime) {
            $temp = $prime->subtract(self::$one);
            $exponents[$i] = $e->modInverse($temp);
        }
        // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.2>:
        // RSAPrivateKey ::= SEQUENCE {
        //     version           Version,
        //     modulus           INTEGER,  -- n
        //     publicExponent    INTEGER,  -- e
        //     privateExponent   INTEGER,  -- d
        //     prime1            INTEGER,  -- p
        //     prime2            INTEGER,  -- q
        //     exponent1         INTEGER,  -- d mod (p-1)
        //     exponent2         INTEGER,  -- d mod (q-1)
        //     coefficient       INTEGER,  -- (inverse of q) mod p
        //     otherPrimeInfos   OtherPrimeInfos OPTIONAL
        // }
        $privatekey = new PrivateKey();
        $privatekey->modulus = $n;
        $privatekey->k = $bits >> 3;
        $privatekey->publicExponent = $e;
        $privatekey->exponent = $d;
        $privatekey->primes = $primes;
        $privatekey->exponents = $exponents;
        $privatekey->coefficients = $coefficients;
        /*
        $publickey = new PublicKey;
        $publickey->modulus = $n;
        $publickey->k = $bits >> 3;
        $publickey->exponent = $e;
        $publickey->publicExponent = $e;
        $publickey->isPublic = true;
        */
        return $privatekey;
    }
    /**
     * OnLoad Handler
     *
     * @return bool
     * @access protected
     * @param array $components
     */
    protected static function onLoad($components)
    {
        $key = $components['isPublicKey'] ? new PublicKey() : new PrivateKey();
        $key->modulus = $components['modulus'];
        $key->publicExponent = $components['publicExponent'];
        $key->k = $key->modulus->getLengthInBytes();
        if ($components['isPublicKey'] || !isset($components['privateExponent'])) {
            $key->exponent = $key->publicExponent;
        } else {
            $key->privateExponent = $components['privateExponent'];
            $key->exponent = $key->privateExponent;
            $key->primes = $components['primes'];
            $key->exponents = $components['exponents'];
            $key->coefficients = $components['coefficients'];
        }
        if ($components['format'] == PSS::class) {
            // in the X509 world RSA keys are assumed to use PKCS1 padding by default. only if the key is
            // explicitly a PSS key is the use of PSS assumed. phpseclib does not work like this. phpseclib
            // uses PSS padding by default. it assumes the more secure method by default and altho it provides
            // for the less secure PKCS1 method you have to go out of your way to use it. this is consistent
            // with the latest trends in crypto. libsodium (NaCl) is actually a little more extreme in that
            // not only does it defaults to the most secure methods - it doesn't even let you choose less
            // secure methods
            //$key = $key->withPadding(self::SIGNATURE_PSS);
            if (isset($components['hash'])) {
                $key = $key->withHash($components['hash']);
            }
            if (isset($components['MGFHash'])) {
                $key = $key->withMGFHash($components['MGFHash']);
            }
            if (isset($components['saltLength'])) {
                $key = $key->withSaltLength($components['saltLength']);
            }
        }
        return $key;
    }
    /**
     * Initialize static variables
     */
    protected static function initialize_static_variables()
    {
        if (!isset(self::$configFile)) {
            self::$configFile = dirname(__FILE__) . '/../openssl.cnf';
        }
        parent::initialize_static_variables();
    }
    /**
     * Constructor
     *
     * PublicKey and PrivateKey objects can only be created from abstract RSA class
     */
    protected function __construct()
    {
        parent::__construct();
        $this->hLen = $this->hash->getLengthInBytes();
        $this->mgfHash = new Hash('sha256');
        $this->mgfHLen = $this->mgfHash->getLengthInBytes();
    }
    /**
     * Integer-to-Octet-String primitive
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}.
     *
     * @access private
     * @param (bool | \phpseclib3\Math\BigInteger) $x
     * @param int $xLen
     * @return (bool | string)
     */
    protected function i2osp($x, $xLen)
    {
        if ($x === false) {
            return false;
        }
        $x = $x->toBytes();
        if (strlen($x) > $xLen) {
            throw new \OutOfRangeException('Resultant string length out of range');
        }
        return str_pad($x, $xLen, chr(0), STR_PAD_LEFT);
    }
    /**
     * Octet-String-to-Integer primitive
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
     *
     * @access private
     * @param string $x
     * @return \phpseclib3\Math\BigInteger
     */
    protected function os2ip($x)
    {
        return new BigInteger($x, 256);
    }
    /**
     * EMSA-PKCS1-V1_5-ENCODE
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
     *
     * @access private
     * @param string $m
     * @param int $emLen
     * @throws \LengthException if the intended encoded message length is too short
     * @return string
     */
    protected function emsa_pkcs1_v1_5_encode($m, $emLen)
    {
        $h = $this->hash->hash($m);
        // see http://tools.ietf.org/html/rfc3447#page-43
        switch ($this->hash->getHash()) {
            case 'md2':
                $t = "0 0\f\x06\x08*\x86H\x86\xf7\r\x02\x02\x05\x00\x04\x10";
                break;
            case 'md5':
                $t = "0 0\f\x06\x08*\x86H\x86\xf7\r\x02\x05\x05\x00\x04\x10";
                break;
            case 'sha1':
                $t = "0!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14";
                break;
            case 'sha256':
                $t = "010\r\x06\t`\x86H\x01e\x03\x04\x02\x01\x05\x00\x04 ";
                break;
            case 'sha384':
                $t = "0A0\r\x06\t`\x86H\x01e\x03\x04\x02\x02\x05\x00\x040";
                break;
            case 'sha512':
                $t = "0Q0\r\x06\t`\x86H\x01e\x03\x04\x02\x03\x05\x00\x04@";
                break;
            // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40
            case 'sha224':
                $t = "0-0\r\x06\t`\x86H\x01e\x03\x04\x02\x04\x05\x00\x04\x1c";
                break;
            case 'sha512/224':
                $t = "0-0\r\x06\t`\x86H\x01e\x03\x04\x02\x05\x05\x00\x04\x1c";
                break;
            case 'sha512/256':
                $t = "010\r\x06\t`\x86H\x01e\x03\x04\x02\x06\x05\x00\x04 ";
        }
        $t .= $h;
        $tLen = strlen($t);
        if ($emLen < $tLen + 11) {
            throw new \LengthException('Intended encoded message length too short');
        }
        $ps = str_repeat(chr(0xff), $emLen - $tLen - 3);
        $em = "\x00\x01{$ps}\x00{$t}";
        return $em;
    }
    /**
    * EMSA-PKCS1-V1_5-ENCODE (without NULL)
    *
    * Quoting https://tools.ietf.org/html/rfc8017#page-65,
    *
    * "The parameters field associated with id-sha1, id-sha224, id-sha256,
    id-sha384, id-sha512, id-sha512/224, and id-sha512/256 should
    generally be omitted, but if present, it shall have a value of type
    NULL"
    *
    * @access private
    * @param string $m
    * @param int $emLen
    * @return string
    */
    protected function emsa_pkcs1_v1_5_encode_without_null($m, $emLen)
    {
        $h = $this->hash->hash($m);
        // see http://tools.ietf.org/html/rfc3447#page-43
        switch ($this->hash->getHash()) {
            case 'sha1':
                $t = "0\x1f0\x07\x06\x05+\x0e\x03\x02\x1a\x04\x14";
                break;
            case 'sha256':
                $t = "0/0\v\x06\t`\x86H\x01e\x03\x04\x02\x01\x04 ";
                break;
            case 'sha384':
                $t = "0?0\v\x06\t`\x86H\x01e\x03\x04\x02\x02\x040";
                break;
            case 'sha512':
                $t = "0O0\v\x06\t`\x86H\x01e\x03\x04\x02\x03\x04@";
                break;
            // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40
            case 'sha224':
                $t = "0+0\v\x06\t`\x86H\x01e\x03\x04\x02\x04\x04\x1c";
                break;
            case 'sha512/224':
                $t = "0+0\v\x06\t`\x86H\x01e\x03\x04\x02\x05\x04\x1c";
                break;
            case 'sha512/256':
                $t = "0/0\v\x06\t`\x86H\x01e\x03\x04\x02\x06\x04 ";
                break;
            default:
                throw new UnsupportedAlgorithmException('md2 and md5 require NULLs');
        }
        $t .= $h;
        $tLen = strlen($t);
        if ($emLen < $tLen + 11) {
            throw new \LengthException('Intended encoded message length too short');
        }
        $ps = str_repeat(chr(0xff), $emLen - $tLen - 3);
        $em = "\x00\x01{$ps}\x00{$t}";
        return $em;
    }
    /**
     * MGF1
     *
     * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
     *
     * @access private
     * @param string $mgfSeed
     * @param int $maskLen
     * @return string
     */
    protected function mgf1($mgfSeed, $maskLen)
    {
        // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
        $t = '';
        $count = ceil($maskLen / $this->mgfHLen);
        for ($i = 0; $i < $count; $i++) {
            $c = pack('N', $i);
            $t .= $this->mgfHash->hash($mgfSeed . $c);
        }
        return \Phabel\Target\Php80\Polyfill::substr($t, 0, $maskLen);
    }
    /**
     * Returns the key size
     *
     * More specifically, this returns the size of the modulo in bits.
     *
     * @access public
     * @return int
     */
    public function getLength()
    {
        return !isset($this->modulus) ? 0 : $this->modulus->getLength();
    }
    /**
    * Determines which hashing function should be used
    *
    * Used with signature production / verification and (if the encryption mode is self::PADDING_OAEP) encryption and
    decryption.
    *
    * @access public
    * @param string $hash
    */
    public function withHash($hash)
    {
        $new = clone $this;
        // \phpseclib3\Crypt\Hash supports algorithms that PKCS#1 doesn't support.  md5-96 and sha1-96, for example.
        switch (strtolower($hash)) {
            case 'md2':
            case 'md5':
            case 'sha1':
            case 'sha256':
            case 'sha384':
            case 'sha512':
            case 'sha224':
            case 'sha512/224':
            case 'sha512/256':
                $new->hash = new Hash($hash);
                break;
            default:
                throw new UnsupportedAlgorithmException('The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256');
        }
        $new->hLen = $new->hash->getLengthInBytes();
        return $new;
    }
    /**
    * Determines which hashing function should be used for the mask generation function
    *
    * The mask generation function is used by self::PADDING_OAEP and self::PADDING_PSS and although it's
    best if Hash and MGFHash are set to the same thing this is not a requirement.
    *
    * @access public
    * @param string $hash
    */
    public function withMGFHash($hash)
    {
        $new = clone $this;
        // \phpseclib3\Crypt\Hash supports algorithms that PKCS#1 doesn't support.  md5-96 and sha1-96, for example.
        switch (strtolower($hash)) {
            case 'md2':
            case 'md5':
            case 'sha1':
            case 'sha256':
            case 'sha384':
            case 'sha512':
            case 'sha224':
            case 'sha512/224':
            case 'sha512/256':
                $new->mgfHash = new Hash($hash);
                break;
            default:
                throw new UnsupportedAlgorithmException('The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256');
        }
        $new->mgfHLen = $new->mgfHash->getLengthInBytes();
        return $new;
    }
    /**
     * Returns the MGF hash algorithm currently being used
     *
     * @access public
     */
    public function getMGFHash()
    {
        return clone $this->mgfHash;
    }
    /**
    * Determines the salt length
    *
    * Used by RSA::PADDING_PSS
    *
    * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}:
    *
    * Typical salt lengths in octets are hLen (the length of the output
    of the hash function Hash) and 0.
    *
    * @access public
    * @param int $sLen
    */
    public function withSaltLength($sLen)
    {
        $new = clone $this;
        $new->sLen = $sLen;
        return $new;
    }
    /**
     * Returns the salt length currently being used
     *
     * @access public
     */
    public function getSaltLength()
    {
        return $this->sLen !== null ? $this->sLen : $this->hLen;
    }
    /**
    * Determines the label
    *
    * Used by RSA::PADDING_OAEP
    *
    * To quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}:
    *
    * Both the encryption and the decryption operations of RSAES-OAEP take
    the value of a label L as input.  In this version of PKCS #1, L is
    the empty string; other uses of the label are outside the scope of
    this document.
    *
    * @access public
    * @param string $label
    */
    public function withLabel($label)
    {
        $new = clone $this;
        $new->label = $label;
        return $new;
    }
    /**
     * Returns the label currently being used
     *
     * @access public
     */
    public function getLabel()
    {
        return $this->label;
    }
    /**
     * Determines the padding modes
     *
     * Example: $key->withPadding(RSA::ENCRYPTION_PKCS1 | RSA::SIGNATURE_PKCS1);
     *
     * @access public
     * @param int $padding
     */
    public function withPadding($padding)
    {
        $masks = [self::ENCRYPTION_OAEP, self::ENCRYPTION_PKCS1, self::ENCRYPTION_NONE];
        $numSelected = 0;
        $selected = 0;
        foreach ($masks as $mask) {
            if ($padding & $mask) {
                $selected = $mask;
                $numSelected++;
            }
        }
        if ($numSelected > 1) {
            throw new InconsistentSetupException('Multiple encryption padding modes have been selected; at most only one should be selected');
        }
        $encryptionPadding = $selected;
        $masks = [self::SIGNATURE_PSS, self::SIGNATURE_RELAXED_PKCS1, self::SIGNATURE_PKCS1];
        $numSelected = 0;
        $selected = 0;
        foreach ($masks as $mask) {
            if ($padding & $mask) {
                $selected = $mask;
                $numSelected++;
            }
        }
        if ($numSelected > 1) {
            throw new InconsistentSetupException('Multiple signature padding modes have been selected; at most only one should be selected');
        }
        $signaturePadding = $selected;
        $new = clone $this;
        $new->encryptionPadding = $encryptionPadding;
        $new->signaturePadding = $signaturePadding;
        return $new;
    }
    /**
     * Returns the padding currently being used
     *
     * @access public
     */
    public function getPadding()
    {
        return $this->signaturePadding | $this->encryptionPadding;
    }
    /**
    * Returns the current engine being used
    *
    * OpenSSL is only used in this class (and it's subclasses) for key generation
    Even then it depends on the parameters you're using. It's not used for
    multi-prime RSA nor is it used if the key length is outside of the range
    supported by OpenSSL
    *
    * @see self::useInternalEngine()
    * @see self::useBestEngine()
    * @access public
    * @return string
    */
    public function getEngine()
    {
        return self::$engines['OpenSSL'] && self::$defaultExponent == 65537 ? 'OpenSSL' : 'PHP';
    }
    /**
     * Enable RSA Blinding
     *
     * @access public
     */
    public static function enableBlinding()
    {
        static::$enableBlinding = true;
    }
    /**
     * Disable RSA Blinding
     *
     * @access public
     */
    public static function disableBlinding()
    {
        static::$enableBlinding = false;
    }
}<?php

/**
 * Pure-PHP implementation of RC2.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://tools.ietf.org/html/rfc2268}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $rc2 = new \phpseclib3\Crypt\RC2('ctr');
 *
 *    $rc2->setKey('abcdefgh');
 *
 *    $plaintext = str_repeat('a', 1024);
 *
 *    echo $rc2->decrypt($rc2->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category Crypt
 * @package  RC2
 * @author   Patrick Monnerat <pm@datasphere.ch>
 * @license  http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link     http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
use phpseclib3\Exception\BadModeException;
/**
 * Pure-PHP implementation of RC2.
 *
 * @package RC2
 * @access  public
 */
class RC2 extends BlockCipher
{
    /**
     * Block Length of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
     * @var int
     * @access private
     */
    protected $block_size = 8;
    /**
     * The Key
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::key
     * @see self::setKey()
     * @var string
     * @access private
     */
    protected $key;
    /**
     * The Original (unpadded) Key
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::key
     * @see self::setKey()
     * @see self::encrypt()
     * @see self::decrypt()
     * @var string
     * @access private
     */
    private $orig_key;
    /**
     * Don't truncate / null pad key
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::clearBuffers()
     * @var bool
     * @access private
     */
    private $skip_key_adjustment = true;
    /**
     * Key Length (in bytes)
     *
     * @see \phpseclib3\Crypt\RC2::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 16;
    // = 128 bits
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'rc2';
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 500;
    /**
     * The key length in bits.
     *
     * {@internal Should be in range [1..1024].}
     *
     * {@internal Changing this value after setting the key has no effect.}
     *
     * @see self::setKeyLength()
     * @see self::setKey()
     * @var int
     * @access private
     */
    private $default_key_length = 1024;
    /**
     * The key length in bits.
     *
     * {@internal Should be in range [1..1024].}
     *
     * @see self::isValidEnine()
     * @see self::setKey()
     * @var int
     * @access private
     */
    private $current_key_length;
    /**
     * The Key Schedule
     *
     * @see self::setupKey()
     * @var array
     * @access private
     */
    private $keys;
    /**
     * Key expansion randomization table.
     * Twice the same 256-value sequence to save a modulus in key expansion.
     *
     * @see self::setKey()
     * @var array
     * @access private
     */
    private static $pitable = [0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x9, 0x81, 0x7d, 0x32, 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0xb, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 0x6f, 0xbf, 0xe, 0xda, 0x46, 0x69, 0x7, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x3, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x6, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x8, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x4, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0xf, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x2, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x5, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x0, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x1, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0xd, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0xc, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0xa, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad, 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x9, 0x81, 0x7d, 0x32, 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0xb, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 0x6f, 0xbf, 0xe, 0xda, 0x46, 0x69, 0x7, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x3, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x6, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x8, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x4, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0xf, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x2, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x5, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x0, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x1, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0xd, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0xc, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0xa, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad];
    /**
     * Inverse key expansion randomization table.
     *
     * @see self::setKey()
     * @var array
     * @access private
     */
    private static $invpitable = [0xd1, 0xda, 0xb9, 0x6f, 0x9c, 0xc8, 0x78, 0x66, 0x80, 0x2c, 0xf8, 0x37, 0xea, 0xe0, 0x62, 0xa4, 0xcb, 0x71, 0x50, 0x27, 0x4b, 0x95, 0xd9, 0x20, 0x9d, 0x4, 0x91, 0xe3, 0x47, 0x6a, 0x7e, 0x53, 0xfa, 0x3a, 0x3b, 0xb4, 0xa8, 0xbc, 0x5f, 0x68, 0x8, 0xca, 0x8f, 0x14, 0xd7, 0xc0, 0xef, 0x7b, 0x5b, 0xbf, 0x2f, 0xe5, 0xe2, 0x8c, 0xba, 0x12, 0xe1, 0xaf, 0xb2, 0x54, 0x5d, 0x59, 0x76, 0xdb, 0x32, 0xa2, 0x58, 0x6e, 0x1c, 0x29, 0x64, 0xf3, 0xe9, 0x96, 0xc, 0x98, 0x19, 0x8d, 0x3e, 0x26, 0xab, 0xa5, 0x85, 0x16, 0x40, 0xbd, 0x49, 0x67, 0xdc, 0x22, 0x94, 0xbb, 0x3c, 0xc1, 0x9b, 0xeb, 0x45, 0x28, 0x18, 0xd8, 0x1a, 0x42, 0x7d, 0xcc, 0xfb, 0x65, 0x8e, 0x3d, 0xcd, 0x2a, 0xa3, 0x60, 0xae, 0x93, 0x8a, 0x48, 0x97, 0x51, 0x15, 0xf7, 0x1, 0xb, 0xb7, 0x36, 0xb1, 0x2e, 0x11, 0xfd, 0x84, 0x2d, 0x3f, 0x13, 0x88, 0xb3, 0x34, 0x24, 0x1b, 0xde, 0xc5, 0x1d, 0x4d, 0x2b, 0x17, 0x31, 0x74, 0xa9, 0xc6, 0x43, 0x6d, 0x39, 0x90, 0xbe, 0xc3, 0xb0, 0x21, 0x6b, 0xf6, 0xf, 0xd5, 0x99, 0xd, 0xac, 0x1f, 0x5c, 0x9e, 0xf5, 0xf9, 0x4c, 0xd6, 0xdf, 0x89, 0xe4, 0x8b, 0xff, 0xc7, 0xaa, 0xe7, 0xed, 0x46, 0x25, 0xb6, 0x6, 0x5e, 0x35, 0xb5, 0xec, 0xce, 0xe8, 0x6c, 0x30, 0x55, 0x61, 0x4a, 0xfe, 0xa0, 0x79, 0x3, 0xf0, 0x10, 0x72, 0x7c, 0xcf, 0x52, 0xa6, 0xa7, 0xee, 0x44, 0xd3, 0x9a, 0x57, 0x92, 0xd0, 0x5a, 0x7a, 0x41, 0x7f, 0xe, 0x0, 0x63, 0xf2, 0x4f, 0x5, 0x83, 0xc9, 0xa1, 0xd4, 0xdd, 0xc4, 0x56, 0xf4, 0xd2, 0x77, 0x81, 0x9, 0x82, 0x33, 0x9f, 0x7, 0x86, 0x75, 0x38, 0x4e, 0x69, 0xf1, 0xad, 0x23, 0x73, 0x87, 0x70, 0x2, 0xc2, 0x1e, 0xb8, 0xa, 0xfc, 0xe6];
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws \InvalidArgumentException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new BadModeException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        switch ($engine) {
            case self::ENGINE_OPENSSL:
                if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
                    return false;
                }
                $this->cipher_name_openssl_ecb = 'rc2-ecb';
                $this->cipher_name_openssl = 'rc2-' . $this->openssl_translate_mode();
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
    * Sets the key length.
    *
    * Valid key lengths are 8 to 1024.
    Calling this function after setting the key has no effect until the next
    \phpseclib3\Crypt\RC2::setKey() call.
    *
    * @access public
    * @param int $length in bits
    * @throws \LengthException if the key length isn't supported
    */
    public function setKeyLength($length)
    {
        if ($length < 8 || $length > 1024) {
            throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
        }
        $this->default_key_length = $this->current_key_length = $length;
        $this->explicit_key_length = $length >> 3;
    }
    /**
     * Returns the current key length
     *
     * @access public
     * @return int
     */
    public function getKeyLength()
    {
        return $this->current_key_length;
    }
    /**
    * Sets the key.
    *
    * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
    strlen($key) <= 128), however, we only use the first 128 bytes if $key
    has more then 128 bytes in it, and set $key to a single null byte if
    it is empty.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
    * @access public
    * @param string $key
    * @param (int | boolean) $t1 optional Effective key length in bits.
    * @throws \LengthException if the key length isn't supported
    */
    public function setKey($key, $t1 = false)
    {
        $this->orig_key = $key;
        if ($t1 === false) {
            $t1 = $this->default_key_length;
        }
        if ($t1 < 1 || $t1 > 1024) {
            throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
        }
        $this->current_key_length = $t1;
        if (strlen($key) < 1 || strlen($key) > 128) {
            throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes between 8 and 1024 bits, inclusive, are supported');
        }
        $t = strlen($key);
        // The mcrypt RC2 implementation only supports effective key length
        // of 1024 bits. It is however possible to handle effective key
        // lengths in range 1..1024 by expanding the key and applying
        // inverse pitable mapping to the first byte before submitting it
        // to mcrypt.
        // Key expansion.
        $l = array_values(unpack('C*', $key));
        $t8 = $t1 + 7 >> 3;
        $tm = 0xff >> 8 * $t8 - $t1;
        // Expand key.
        $pitable = self::$pitable;
        for ($i = $t; $i < 128; $i++) {
            $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
        }
        $i = 128 - $t8;
        $l[$i] = $pitable[$l[$i] & $tm];
        while ($i--) {
            $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
        }
        // Prepare the key for mcrypt.
        $l[0] = self::$invpitable[$l[0]];
        array_unshift($l, 'C*');
        $this->key = pack(...$l);
        $this->key_length = strlen($this->key);
        $this->changed = $this->nonIVChanged = true;
        $this->setEngine();
    }
    /**
     * Encrypts a message.
     *
     * Mostly a wrapper for \phpseclib3\Crypt\Common\SymmetricKey::encrypt, with some additional OpenSSL handling code
     *
     * @see self::decrypt()
     * @access public
     * @param string $plaintext
     * @return string $ciphertext
     */
    public function encrypt($plaintext)
    {
        if ($this->engine == self::ENGINE_OPENSSL) {
            $temp = $this->key;
            $this->key = $this->orig_key;
            $result = parent::encrypt($plaintext);
            $this->key = $temp;
            return $result;
        }
        return parent::encrypt($plaintext);
    }
    /**
     * Decrypts a message.
     *
     * Mostly a wrapper for \phpseclib3\Crypt\Common\SymmetricKey::decrypt, with some additional OpenSSL handling code
     *
     * @see self::encrypt()
     * @access public
     * @param string $ciphertext
     * @return string $plaintext
     */
    public function decrypt($ciphertext)
    {
        if ($this->engine == self::ENGINE_OPENSSL) {
            $temp = $this->key;
            $this->key = $this->orig_key;
            $result = parent::decrypt($ciphertext);
            $this->key = $temp;
            return $result;
        }
        return parent::decrypt($ciphertext);
    }
    /**
     * Encrypts a block
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
        $keys = $this->keys;
        $limit = 20;
        $actions = [$limit => 44, 44 => 64];
        $j = 0;
        for (;;) {
            // Mixing round.
            $r0 = ($r0 + $keys[$j++] + (($r1 ^ $r2) & $r3 ^ $r1) & 0xffff) << 1;
            $r0 |= $r0 >> 16;
            $r1 = ($r1 + $keys[$j++] + (($r2 ^ $r3) & $r0 ^ $r2) & 0xffff) << 2;
            $r1 |= $r1 >> 16;
            $r2 = ($r2 + $keys[$j++] + (($r3 ^ $r0) & $r1 ^ $r3) & 0xffff) << 3;
            $r2 |= $r2 >> 16;
            $r3 = ($r3 + $keys[$j++] + (($r0 ^ $r1) & $r2 ^ $r0) & 0xffff) << 5;
            $r3 |= $r3 >> 16;
            if ($j === $limit) {
                if ($limit === 64) {
                    break;
                }
                // Mashing round.
                $r0 += $keys[$r3 & 0x3f];
                $r1 += $keys[$r0 & 0x3f];
                $r2 += $keys[$r1 & 0x3f];
                $r3 += $keys[$r2 & 0x3f];
                $limit = $actions[$limit];
            }
        }
        return pack('vvvv', $r0, $r1, $r2, $r3);
    }
    /**
     * Decrypts a block
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
        $keys = $this->keys;
        $limit = 44;
        $actions = [$limit => 20, 20 => 0];
        $j = 64;
        for (;;) {
            // R-mixing round.
            $r3 = ($r3 | $r3 << 16) >> 5;
            $r3 = $r3 - $keys[--$j] - (($r0 ^ $r1) & $r2 ^ $r0) & 0xffff;
            $r2 = ($r2 | $r2 << 16) >> 3;
            $r2 = $r2 - $keys[--$j] - (($r3 ^ $r0) & $r1 ^ $r3) & 0xffff;
            $r1 = ($r1 | $r1 << 16) >> 2;
            $r1 = $r1 - $keys[--$j] - (($r2 ^ $r3) & $r0 ^ $r2) & 0xffff;
            $r0 = ($r0 | $r0 << 16) >> 1;
            $r0 = $r0 - $keys[--$j] - (($r1 ^ $r2) & $r3 ^ $r1) & 0xffff;
            if ($j === $limit) {
                if ($limit === 0) {
                    break;
                }
                // R-mashing round.
                $r3 = $r3 - $keys[$r2 & 0x3f] & 0xffff;
                $r2 = $r2 - $keys[$r1 & 0x3f] & 0xffff;
                $r1 = $r1 - $keys[$r0 & 0x3f] & 0xffff;
                $r0 = $r0 - $keys[$r3 & 0x3f] & 0xffff;
                $limit = $actions[$limit];
            }
        }
        return pack('vvvv', $r0, $r1, $r2, $r3);
    }
    /**
     * Creates the key schedule
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
     * @access private
     */
    protected function setupKey()
    {
        if (!isset($this->key)) {
            $this->setKey('');
        }
        // Key has already been expanded in \phpseclib3\Crypt\RC2::setKey():
        // Only the first value must be altered.
        $l = unpack('Ca/Cb/v*', $this->key);
        array_unshift($l, self::$pitable[$l['a']] | $l['b'] << 8);
        unset($l['a']);
        unset($l['b']);
        $this->keys = $l;
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        // Init code for both, encrypt and decrypt.
        $init_crypt = '$keys = $this->keys;';
        $keys = $this->keys;
        // $in is the current 8 bytes block which has to be en/decrypt
        $encrypt_block = $decrypt_block = '
            $in = unpack("v4", $in);
            $r0 = $in[1];
            $r1 = $in[2];
            $r2 = $in[3];
            $r3 = $in[4];
        ';
        // Create code for encryption.
        $limit = 20;
        $actions = [$limit => 44, 44 => 64];
        $j = 0;
        for (;;) {
            // Mixing round.
            $encrypt_block .= '
                $r0 = (($r0 + ' . $keys[$j++] . ' +
                       ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
                $r0 |= $r0 >> 16;
                $r1 = (($r1 + ' . $keys[$j++] . ' +
                       ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
                $r1 |= $r1 >> 16;
                $r2 = (($r2 + ' . $keys[$j++] . ' +
                       ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
                $r2 |= $r2 >> 16;
                $r3 = (($r3 + ' . $keys[$j++] . ' +
                       ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
                $r3 |= $r3 >> 16;';
            if ($j === $limit) {
                if ($limit === 64) {
                    break;
                }
                // Mashing round.
                $encrypt_block .= '
                    $r0 += $keys[$r3 & 0x3F];
                    $r1 += $keys[$r0 & 0x3F];
                    $r2 += $keys[$r1 & 0x3F];
                    $r3 += $keys[$r2 & 0x3F];';
                $limit = $actions[$limit];
            }
        }
        $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
        // Create code for decryption.
        $limit = 44;
        $actions = [$limit => 20, 20 => 0];
        $j = 64;
        for (;;) {
            // R-mixing round.
            $decrypt_block .= '
                $r3 = ($r3 | ($r3 << 16)) >> 5;
                $r3 = ($r3 - ' . $keys[--$j] . ' -
                       ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
                $r2 = ($r2 | ($r2 << 16)) >> 3;
                $r2 = ($r2 - ' . $keys[--$j] . ' -
                       ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
                $r1 = ($r1 | ($r1 << 16)) >> 2;
                $r1 = ($r1 - ' . $keys[--$j] . ' -
                       ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
                $r0 = ($r0 | ($r0 << 16)) >> 1;
                $r0 = ($r0 - ' . $keys[--$j] . ' -
                       ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
            if ($j === $limit) {
                if ($limit === 0) {
                    break;
                }
                // R-mashing round.
                $decrypt_block .= '
                    $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
                    $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
                    $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
                    $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
                $limit = $actions[$limit];
            }
        }
        $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
        // Creates the inline-crypt function
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => $init_crypt, 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block]);
    }
}<?php

/**
 * PKCS#8 Formatted RSA-PSS Key Handler
 *
 * PHP version 5
 *
 * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to "openssl genpkey -algorithm rsa-pss".
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted RSA-PSS Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PSS extends Progenitor
{
    /**
     * OID Name
     *
     * @var string
     * @access private
     */
    const OID_NAME = 'id-RSASSA-PSS';
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = '1.2.840.113549.1.1.10';
    /**
     * OIDs loaded
     *
     * @var bool
     * @access private
     */
    private static $oidsLoaded = false;
    /**
     * Child OIDs loaded
     *
     * @var bool
     * @access private
     */
    protected static $childOIDsLoaded = false;
    /**
     * Initialize static variables
     */
    private static function initialize_static_variables()
    {
        if (!self::$oidsLoaded) {
            ASN1::loadOIDs(['md2' => '1.2.840.113549.2.2', 'md4' => '1.2.840.113549.2.4', 'md5' => '1.2.840.113549.2.5', 'id-sha1' => '1.3.14.3.2.26', 'id-sha256' => '2.16.840.1.101.3.4.2.1', 'id-sha384' => '2.16.840.1.101.3.4.2.2', 'id-sha512' => '2.16.840.1.101.3.4.2.3', 'id-sha224' => '2.16.840.1.101.3.4.2.4', 'id-sha512/224' => '2.16.840.1.101.3.4.2.5', 'id-sha512/256' => '2.16.840.1.101.3.4.2.6', 'id-mgf1' => '1.2.840.113549.1.1.8']);
            self::$oidsLoaded = true;
        }
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $components = ['isPublicKey' => strpos($key, 'PUBLIC') !== false];
        $key = parent::load($key, $password);
        $type = isset($key['privateKey']) ? 'private' : 'public';
        $result = $components + PKCS1::load($key[$type . 'Key']);
        if (isset($key[$type . 'KeyAlgorithm']['parameters'])) {
            $decoded = ASN1::decodeBER($key[$type . 'KeyAlgorithm']['parameters']);
            if ($decoded === false) {
                throw new \UnexpectedValueException('Unable to decode parameters');
            }
            $params = ASN1::asn1map($decoded[0], Maps\RSASSA_PSS_params::MAP);
        } else {
            $params = [];
        }
        if (isset($params['maskGenAlgorithm']['parameters'])) {
            $decoded = ASN1::decodeBER($params['maskGenAlgorithm']['parameters']);
            if ($decoded === false) {
                throw new \UnexpectedValueException('Unable to decode parameters');
            }
            $params['maskGenAlgorithm']['parameters'] = ASN1::asn1map($decoded[0], Maps\HashAlgorithm::MAP);
        } else {
            $params['maskGenAlgorithm'] = ['algorithm' => 'id-mgf1', 'parameters' => ['algorithm' => 'id-sha1']];
        }
        if (!isset($params['hashAlgorithm']['algorithm'])) {
            $params['hashAlgorithm']['algorithm'] = 'id-sha1';
        }
        $result['hash'] = str_replace('id-', '', $params['hashAlgorithm']['algorithm']);
        $result['MGFHash'] = str_replace('id-', '', $params['maskGenAlgorithm']['parameters']['algorithm']);
        if (isset($params['saltLength'])) {
            $result['saltLength'] = (int) $params['saltLength']->toString();
        }
        if (isset($key['meta'])) {
            $result['meta'] = $key['meta'];
        }
        return $result;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        self::initialize_static_variables();
        $key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients);
        $key = ASN1::extractBER($key);
        $params = self::savePSSParams($options);
        return self::wrapPrivateKey($key, [], $params, $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = [])
    {
        self::initialize_static_variables();
        $key = PKCS1::savePublicKey($n, $e);
        $key = ASN1::extractBER($key);
        $params = self::savePSSParams($options);
        return self::wrapPublicKey($key, $params);
    }
    /**
     * Encodes PSS parameters
     *
     * @access public
     * @param array $options
     * @return string
     */
    public static function savePSSParams(array $options)
    {
        /*
         The trailerField field is an integer.  It provides
         compatibility with IEEE Std 1363a-2004 [P1363A].  The value
         MUST be 1, which represents the trailer field with hexadecimal
         value 0xBC.  Other trailer fields, including the trailer field
         composed of HashID concatenated with 0xCC that is specified in
         IEEE Std 1363a, are not supported.  Implementations that
         perform signature generation MUST omit the trailerField field,
         indicating that the default trailer field value was used.
         Implementations that perform signature validation MUST
         recognize both a present trailerField field with value 1 and an
         absent trailerField field.
        
         source: https://tools.ietf.org/html/rfc4055#page-9
        */
        $params = ['trailerField' => new BigInteger(1)];
        if (isset($options['hash'])) {
            $params['hashAlgorithm']['algorithm'] = 'id-' . $options['hash'];
        }
        if (isset($options['MGFHash'])) {
            $temp = ['algorithm' => 'id-' . $options['MGFHash']];
            $temp = ASN1::encodeDER($temp, Maps\HashAlgorithm::MAP);
            $params['maskGenAlgorithm'] = ['algorithm' => 'id-mgf1', 'parameters' => new ASN1\Element($temp)];
        }
        if (isset($options['saltLength'])) {
            $params['saltLength'] = new BigInteger($options['saltLength']);
        }
        return new ASN1\Element(ASN1::encodeDER($params, Maps\RSASSA_PSS_params::MAP));
    }
}<?php

/**
 * PKCS#1 Formatted RSA Key Handler
 *
 * PHP version 5
 *
 * Used by File/X509.php
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN RSA PRIVATE KEY-----
 * -----BEGIN RSA PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pem format (as specified by -m)
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#1 Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends Progenitor
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (strpos($key, 'PUBLIC') !== false) {
            $components = ['isPublicKey' => true];
        } elseif (strpos($key, 'PRIVATE') !== false) {
            $components = ['isPublicKey' => false];
        } else {
            $components = [];
        }
        $key = parent::load($key, $password);
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $key = ASN1::asn1map($decoded[0], Maps\RSAPrivateKey::MAP);
        if (is_array($key)) {
            $components += ['modulus' => $key['modulus'], 'publicExponent' => $key['publicExponent'], 'privateExponent' => $key['privateExponent'], 'primes' => [1 => $key['prime1'], $key['prime2']], 'exponents' => [1 => $key['exponent1'], $key['exponent2']], 'coefficients' => [2 => $key['coefficient']]];
            if ($key['version'] == 'multi') {
                foreach ($key['otherPrimeInfos'] as $primeInfo) {
                    $components['primes'][] = $primeInfo['prime'];
                    $components['exponents'][] = $primeInfo['exponent'];
                    $components['coefficients'][] = $primeInfo['coefficient'];
                }
            }
            if (!isset($components['isPublicKey'])) {
                $components['isPublicKey'] = false;
            }
            return $components;
        }
        $key = ASN1::asn1map($decoded[0], Maps\RSAPublicKey::MAP);
        if (!is_array($key)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping');
        }
        if (!isset($components['isPublicKey'])) {
            $components['isPublicKey'] = true;
        }
        return $components + $key;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        $num_primes = count($primes);
        $key = ['version' => $num_primes == 2 ? 'two-prime' : 'multi', 'modulus' => $n, 'publicExponent' => $e, 'privateExponent' => $d, 'prime1' => $primes[1], 'prime2' => $primes[2], 'exponent1' => $exponents[1], 'exponent2' => $exponents[2], 'coefficient' => $coefficients[2]];
        for ($i = 3; $i <= $num_primes; $i++) {
            $key['otherPrimeInfos'][] = ['prime' => $primes[$i], 'exponent' => $exponents[$i], 'coefficient' => $coefficients[$i]];
        }
        $key = ASN1::encodeDER($key, Maps\RSAPrivateKey::MAP);
        return self::wrapPrivateKey($key, 'RSA', $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        $key = ['modulus' => $n, 'publicExponent' => $e];
        $key = ASN1::encodeDER($key, Maps\RSAPublicKey::MAP);
        return self::wrapPublicKey($key, 'RSA');
    }
}<?php

/**
 * PKCS#8 Formatted RSA Key Handler
 *
 * PHP version 5
 *
 * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
 * is specific to private keys it's basically creating a DER-encoded wrapper
 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends Progenitor
{
    /**
     * OID Name
     *
     * @var string
     * @access private
     */
    const OID_NAME = 'rsaEncryption';
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = '1.2.840.113549.1.1.1';
    /**
     * Child OIDs loaded
     *
     * @var bool
     * @access private
     */
    protected static $childOIDsLoaded = false;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (strpos($key, 'PUBLIC') !== false) {
            $components = ['isPublicKey' => true];
        } elseif (strpos($key, 'PRIVATE') !== false) {
            $components = ['isPublicKey' => false];
        } else {
            $components = [];
        }
        $key = parent::load($key, $password);
        if (isset($key['privateKey'])) {
            if (!isset($components['isPublicKey'])) {
                $components['isPublicKey'] = false;
            }
            $type = 'private';
        } else {
            if (!isset($components['isPublicKey'])) {
                $components['isPublicKey'] = true;
            }
            $type = 'public';
        }
        $result = $components + PKCS1::load($key[$type . 'Key']);
        if (isset($key['meta'])) {
            $result['meta'] = $key['meta'];
        }
        return $result;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        $key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients);
        $key = ASN1::extractBER($key);
        return self::wrapPrivateKey($key, [], null, $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = [])
    {
        $key = PKCS1::savePublicKey($n, $e);
        $key = ASN1::extractBER($key);
        return self::wrapPublicKey($key, null);
    }
}<?php

/**
 * PuTTY Formatted RSA Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor;
/**
 * PuTTY Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PuTTY extends Progenitor
{
    /**
     * Public Handler
     *
     * @var string
     * @access private
     */
    const PUBLIC_HANDLER = 'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\OpenSSH';
    /**
     * Algorithm Identifier
     *
     * @var array
     * @access private
     */
    protected static $types = ['ssh-rsa'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        $components = parent::load($key, $password);
        if (!isset($components['private'])) {
            return $components;
        }
        extract($components);
        unset($components['public'], $components['private']);
        $isPublicKey = false;
        $result = Strings::unpackSSH2('ii', $public);
        if ($result === false) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        list($publicExponent, $modulus) = $result;
        $result = Strings::unpackSSH2('iiii', $private);
        if ($result === false) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $primes = $coefficients = [];
        list($privateExponent, $primes[1], $primes[2], $coefficients[2]) = $result;
        $temp = $primes[1]->subtract($one);
        $exponents = [1 => $publicExponent->modInverse($temp)];
        $temp = $primes[2]->subtract($one);
        $exponents[] = $publicExponent->modInverse($temp);
        return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey');
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        if (count($primes) != 2) {
            throw new \InvalidArgumentException('PuTTY does not support multi-prime RSA keys');
        }
        $public = Strings::packSSH2('ii', $e, $n);
        $private = Strings::packSSH2('iiii', $d, $primes[1], $primes[2], $coefficients[2]);
        return self::wrapPrivateKey($public, $private, 'ssh-rsa', $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        return self::wrapPublicKey(Strings::packSSH2('ii', $e, $n), 'ssh-rsa');
    }
}<?php

/**
 * XML Formatted RSA Key Handler
 *
 * More info:
 *
 * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
 * http://www.w3.org/TR/xkms2/#XKMS_2_0_Paragraph_269
 * http://en.wikipedia.org/wiki/XML_Signature
 * http://en.wikipedia.org/wiki/XKMS
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * XML Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class XML
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $components = ['isPublicKey' => false, 'primes' => [], 'exponents' => [], 'coefficients' => []];
        $use_errors = libxml_use_internal_errors(true);
        $dom = new \DOMDocument();
        if (\Phabel\Target\Php80\Polyfill::substr($key, 0, 5) != '<?xml') {
            $key = '<xml>' . $key . '</xml>';
        }
        if (!$dom->loadXML($key)) {
            throw new \UnexpectedValueException('Key does not appear to contain XML');
        }
        $xpath = new \DOMXPath($dom);
        $keys = ['modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd'];
        foreach ($keys as $key) {
            // $dom->getElementsByTagName($key) is case-sensitive
            $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='{$key}']");
            if (!$temp->length) {
                continue;
            }
            $value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256);
            switch ($key) {
                case 'modulus':
                    $components['modulus'] = $value;
                    break;
                case 'exponent':
                    $components['publicExponent'] = $value;
                    break;
                case 'p':
                    $components['primes'][1] = $value;
                    break;
                case 'q':
                    $components['primes'][2] = $value;
                    break;
                case 'dp':
                    $components['exponents'][1] = $value;
                    break;
                case 'dq':
                    $components['exponents'][2] = $value;
                    break;
                case 'inverseq':
                    $components['coefficients'][2] = $value;
                    break;
                case 'd':
                    $components['privateExponent'] = $value;
            }
        }
        libxml_use_internal_errors($use_errors);
        foreach ($components as $key => $value) {
            if (is_array($value) && !count($value)) {
                unset($components[$key]);
            }
        }
        if (isset($components['modulus']) && isset($components['publicExponent'])) {
            if (count($components) == 3) {
                $components['isPublicKey'] = true;
            }
            return $components;
        }
        throw new \UnexpectedValueException('Modulus / exponent not present');
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '')
    {
        if (count($primes) != 2) {
            throw new \InvalidArgumentException('XML does not support multi-prime RSA keys');
        }
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('XML private keys do not support encryption');
        }
        return '<RSAKeyPair>
  <Modulus>' . Base64::encode($n->toBytes()) . '</Modulus>
  <Exponent>' . Base64::encode($e->toBytes()) . '</Exponent>
  <P>' . Base64::encode($primes[1]->toBytes()) . '</P>
  <Q>' . Base64::encode($primes[2]->toBytes()) . '</Q>
  <DP>' . Base64::encode($exponents[1]->toBytes()) . '</DP>
  <DQ>' . Base64::encode($exponents[2]->toBytes()) . '</DQ>
  <InverseQ>' . Base64::encode($coefficients[2]->toBytes()) . '</InverseQ>
  <D>' . Base64::encode($d->toBytes()) . '</D>
</RSAKeyPair>';
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        return '<RSAKeyValue>
  <Modulus>' . Base64::encode($n->toBytes()) . '</Modulus>
  <Exponent>' . Base64::encode($e->toBytes()) . '</Exponent>
</RSAKeyValue>';
    }
}<?php

/**
 * OpenSSH Formatted RSA Key Handler
 *
 * PHP version 5
 *
 * Place in $HOME/.ssh/authorized_keys
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor;
/**
 * OpenSSH Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSH extends Progenitor
{
    /**
     * Supported Key Types
     *
     * @var array
     */
    protected static $types = ['ssh-rsa'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        $parsed = parent::load($key, $password);
        if (isset($parsed['paddedKey'])) {
            list($type) = Strings::unpackSSH2('s', $parsed['paddedKey']);
            if ($type != $parsed['type']) {
                throw new \RuntimeException("The public and private keys are not of the same type ({$type} vs {$parsed['type']})");
            }
            $primes = $coefficients = [];
            list($modulus, $publicExponent, $privateExponent, $coefficients[2], $primes[1], $primes[2], $comment, ) = Strings::unpackSSH2('i6s', $parsed['paddedKey']);
            $temp = $primes[1]->subtract($one);
            $exponents = [1 => $publicExponent->modInverse($temp)];
            $temp = $primes[2]->subtract($one);
            $exponents[] = $publicExponent->modInverse($temp);
            $isPublicKey = false;
            return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey');
        }
        list($publicExponent, $modulus) = Strings::unpackSSH2('ii', $parsed['publicKey']);
        return ['isPublicKey' => true, 'modulus' => $modulus, 'publicExponent' => $publicExponent, 'comment' => $parsed['comment']];
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = [])
    {
        $RSAPublicKey = Strings::packSSH2('sii', 'ssh-rsa', $e, $n);
        if (isset($options['binary']) ? $options['binary'] : self::$binary) {
            return $RSAPublicKey;
        }
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $comment;
        return $RSAPublicKey;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        $publicKey = self::savePublicKey($n, $e, ['binary' => true]);
        $privateKey = Strings::packSSH2('si6', 'ssh-rsa', $n, $e, $d, $coefficients[2], $primes[1], $primes[2]);
        return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
    }
}<?php

/**
 * Miccrosoft BLOB Formatted RSA Key Handler
 *
 * More info:
 *
 * https://msdn.microsoft.com/en-us/library/windows/desktop/aa375601(v=vs.85).aspx
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * Microsoft BLOB Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MSBLOB
{
    /**
     * Public/Private Key Pair
     *
     * @access private
     */
    const PRIVATEKEYBLOB = 0x7;
    /**
     * Public Key
     *
     * @access private
     */
    const PUBLICKEYBLOB = 0x6;
    /**
     * Public Key
     *
     * @access private
     */
    const PUBLICKEYBLOBEX = 0xa;
    /**
     * RSA public key exchange algorithm
     *
     * @access private
     */
    const CALG_RSA_KEYX = 0xa400;
    /**
     * RSA public key exchange algorithm
     *
     * @access private
     */
    const CALG_RSA_SIGN = 0x2400;
    /**
     * Public Key
     *
     * @access private
     */
    const RSA1 = 0x31415352;
    /**
     * Private Key
     *
     * @access private
     */
    const RSA2 = 0x32415352;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $key = Base64::decode($key);
        if (!is_string($key)) {
            throw new \UnexpectedValueException('Base64 decoding produced an error');
        }
        if (strlen($key) < 20) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        // PUBLICKEYSTRUC  publickeystruc
        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx
        extract(unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8)));
        /**
         * @var string $type
         * @var string $version
         * @var integer $reserved
         * @var integer $algo
         */
        switch (ord($type)) {
            case self::PUBLICKEYBLOB:
            case self::PUBLICKEYBLOBEX:
                $publickey = true;
                break;
            case self::PRIVATEKEYBLOB:
                $publickey = false;
                break;
            default:
                throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $components = ['isPublicKey' => $publickey];
        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
        switch ($algo) {
            case self::CALG_RSA_KEYX:
            case self::CALG_RSA_SIGN:
                break;
            default:
                throw new \UnexpectedValueException('Key appears to be malformed');
        }
        // RSAPUBKEY rsapubkey
        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx
        // could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit
        extract(unpack('Vmagic/Vbitlen/a4pubexp', Strings::shift($key, 12)));
        /**
         * @var integer $magic
         * @var integer $bitlen
         * @var string $pubexp
         */
        switch ($magic) {
            case self::RSA2:
                $components['isPublicKey'] = false;
            case self::RSA1:
                break;
            default:
                throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $baseLength = $bitlen / 16;
        if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256);
        // BYTE modulus[rsapubkey.bitlen/8]
        $components['modulus'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256);
        if ($publickey) {
            return $components;
        }
        $components['isPublicKey'] = false;
        // BYTE prime1[rsapubkey.bitlen/16]
        $components['primes'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
        // BYTE prime2[rsapubkey.bitlen/16]
        $components['primes'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256);
        // BYTE exponent1[rsapubkey.bitlen/16]
        $components['exponents'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
        // BYTE exponent2[rsapubkey.bitlen/16]
        $components['exponents'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256);
        // BYTE coefficient[rsapubkey.bitlen/16]
        $components['coefficients'] = [2 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
        if (isset($components['privateExponent'])) {
            $components['publicExponent'] = $components['privateExponent'];
        }
        // BYTE privateExponent[rsapubkey.bitlen/8]
        $components['privateExponent'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256);
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '')
    {
        if (count($primes) != 2) {
            throw new \InvalidArgumentException('MSBLOB does not support multi-prime RSA keys');
        }
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('MSBLOB private keys do not support encryption');
        }
        $n = strrev($n->toBytes());
        $e = str_pad(strrev($e->toBytes()), 4, "\x00");
        $key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
        $key .= pack('VVa*', self::RSA2, 8 * strlen($n), $e);
        $key .= $n;
        $key .= strrev($primes[1]->toBytes());
        $key .= strrev($primes[2]->toBytes());
        $key .= strrev($exponents[1]->toBytes());
        $key .= strrev($exponents[2]->toBytes());
        $key .= strrev($coefficients[2]->toBytes());
        $key .= strrev($d->toBytes());
        return Base64::encode($key);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        $n = strrev($n->toBytes());
        $e = str_pad(strrev($e->toBytes()), 4, "\x00");
        $key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
        $key .= pack('VVa*', self::RSA1, 8 * strlen($n), $e);
        $key .= $n;
        return Base64::encode($key);
    }
}<?php

/**
 * Raw RSA Key Handler
 *
 * PHP version 5
 *
 * An array containing two \phpseclib3\Math\BigInteger objects.
 *
 * The exponent can be indexed with any of the following:
 *
 * 0, e, exponent, publicExponent
 *
 * The modulus can be indexed with any of the following:
 *
 * 1, n, modulo, modulus
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
/**
 * Raw RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!is_array($key)) {
            throw new \UnexpectedValueException('Key should be a array - not a ' . gettype($key));
        }
        $key = array_change_key_case($key, CASE_LOWER);
        $components = ['isPublicKey' => false];
        foreach (['e', 'exponent', 'publicexponent', 0, 'privateexponent', 'd'] as $index) {
            if (isset($key[$index])) {
                $components['publicExponent'] = $key[$index];
                break;
            }
        }
        foreach (['n', 'modulo', 'modulus', 1] as $index) {
            if (isset($key[$index])) {
                $components['modulus'] = $key[$index];
                break;
            }
        }
        if (!isset($components['publicExponent']) || !isset($components['modulus'])) {
            throw new \UnexpectedValueException('Modulus / exponent not present');
        }
        if (isset($key['primes'])) {
            $components['primes'] = $key['primes'];
        } else {
            if (isset($key['p']) && isset($key['q'])) {
                $indices = [['p', 'q'], ['prime1', 'prime2']];
                foreach ($indices as $index) {
                    list($i0, $i1) = $index;
                    if (isset($key[$i0]) && isset($key[$i1])) {
                        $components['primes'] = [1 => $key[$i0], $key[$i1]];
                    }
                }
            }
        }
        if (isset($key['exponents'])) {
            $components['exponents'] = $key['exponents'];
        } else {
            $indices = [['dp', 'dq'], ['exponent1', 'exponent2']];
            foreach ($indices as $index) {
                list($i0, $i1) = $index;
                if (isset($key[$i0]) && isset($key[$i1])) {
                    $components['exponents'] = [1 => $key[$i0], $key[$i1]];
                }
            }
        }
        if (isset($key['coefficients'])) {
            $components['coefficients'] = $key['coefficients'];
        } else {
            foreach (['inverseq', 'q\'', 'coefficient'] as $index) {
                if (isset($key[$index])) {
                    $components['coefficients'] = [2 => $key[$index]];
                }
            }
        }
        if (!isset($components['primes'])) {
            $components['isPublicKey'] = true;
            return $components;
        }
        if (!isset($components['exponents'])) {
            $one = new BigInteger(1);
            $temp = $components['primes'][1]->subtract($one);
            $exponents = [1 => $components['publicExponent']->modInverse($temp)];
            $temp = $components['primes'][2]->subtract($one);
            $exponents[] = $components['publicExponent']->modInverse($temp);
            $components['exponents'] = $exponents;
        }
        if (!isset($components['coefficients'])) {
            $components['coefficients'] = [2 => $components['primes'][2]->modInverse($components['primes'][1])];
        }
        foreach (['privateexponent', 'd'] as $index) {
            if (isset($key[$index])) {
                $components['privateExponent'] = $key[$index];
                break;
            }
        }
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return array
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('Raw private keys do not support encryption');
        }
        return ['e' => clone $e, 'n' => clone $n, 'd' => clone $d, 'primes' => array_map(function ($var) {
            return clone $var;
        }, $primes), 'exponents' => array_map(function ($var) {
            return clone $var;
        }, $exponents), 'coefficients' => array_map(function ($var) {
            return clone $var;
        }, $coefficients)];
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return array
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        return ['e' => clone $e, 'n' => clone $n];
    }
}<?php

/**
 * RSA Private Key
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA;

use phpseclib3\Crypt\RSA;
use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Hash;
use phpseclib3\Exceptions\NoKeyLoadedException;
use phpseclib3\Exception\UnsupportedFormatException;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\Common;
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
/**
 * Raw RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrivateKey extends RSA implements Common\PrivateKey
{
    use Common\Traits\PasswordProtected;
    /**
     * Primes for Chinese Remainder Theorem (ie. p and q)
     *
     * @var array
     * @access private
     */
    protected $primes;
    /**
     * Exponents for Chinese Remainder Theorem (ie. dP and dQ)
     *
     * @var array
     * @access private
     */
    protected $exponents;
    /**
     * Coefficients for Chinese Remainder Theorem (ie. qInv)
     *
     * @var array
     * @access private
     */
    protected $coefficients;
    /**
     * Public Exponent
     *
     * @var mixed
     * @access private
     */
    protected $publicExponent = false;
    /**
     * RSADP
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}.
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $c
     * @return (bool | \phpseclib3\Math\BigInteger)
     */
    private function rsadp($c)
    {
        if ($c->compare(self::$zero) < 0 || $c->compare($this->modulus) > 0) {
            throw new \OutOfRangeException('Ciphertext representative out of range');
        }
        return $this->exponentiate($c);
    }
    /**
     * RSASP1
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}.
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $m
     * @return (bool | \phpseclib3\Math\BigInteger)
     */
    private function rsasp1($m)
    {
        if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) {
            throw new \OutOfRangeException('Signature representative out of range');
        }
        return $this->exponentiate($m);
    }
    /**
     * Exponentiate
     *
     * @param \phpseclib3\Math\BigInteger $x
     * @return \phpseclib3\Math\BigInteger
     */
    protected function exponentiate(BigInteger $x)
    {
        switch (true) {
            case empty($this->primes):
            case $this->primes[1]->equals(self::$zero):
            case empty($this->coefficients):
            case $this->coefficients[2]->equals(self::$zero):
            case empty($this->exponents):
            case $this->exponents[1]->equals(self::$zero):
                return $x->modPow($this->exponent, $this->modulus);
        }
        $num_primes = count($this->primes);
        if (!static::$enableBlinding) {
            $m_i = [1 => $x->modPow($this->exponents[1], $this->primes[1]), 2 => $x->modPow($this->exponents[2], $this->primes[2])];
            $h = $m_i[1]->subtract($m_i[2]);
            $h = $h->multiply($this->coefficients[2]);
            list(, $h) = $h->divide($this->primes[1]);
            $m = $m_i[2]->add($h->multiply($this->primes[2]));
            $r = $this->primes[1];
            for ($i = 3; $i <= $num_primes; $i++) {
                $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]);
                $r = $r->multiply($this->primes[$i - 1]);
                $h = $m_i->subtract($m);
                $h = $h->multiply($this->coefficients[$i]);
                list(, $h) = $h->divide($this->primes[$i]);
                $m = $m->add($r->multiply($h));
            }
        } else {
            $smallest = $this->primes[1];
            for ($i = 2; $i <= $num_primes; $i++) {
                if ($smallest->compare($this->primes[$i]) > 0) {
                    $smallest = $this->primes[$i];
                }
            }
            $r = BigInteger::randomRange(self::$one, $smallest->subtract(self::$one));
            $m_i = [1 => $this->blind($x, $r, 1), 2 => $this->blind($x, $r, 2)];
            $h = $m_i[1]->subtract($m_i[2]);
            $h = $h->multiply($this->coefficients[2]);
            list(, $h) = $h->divide($this->primes[1]);
            $m = $m_i[2]->add($h->multiply($this->primes[2]));
            $r = $this->primes[1];
            for ($i = 3; $i <= $num_primes; $i++) {
                $m_i = $this->blind($x, $r, $i);
                $r = $r->multiply($this->primes[$i - 1]);
                $h = $m_i->subtract($m);
                $h = $h->multiply($this->coefficients[$i]);
                list(, $h) = $h->divide($this->primes[$i]);
                $m = $m->add($r->multiply($h));
            }
        }
        return $m;
    }
    /**
    * Performs RSA Blinding
    *
    * Protects against timing attacks by employing RSA Blinding.
    Returns $x->modPow($this->exponents[$i], $this->primes[$i])
    *
    * @access private
    * @param \phpseclib3\Math\BigInteger $x
    * @param \phpseclib3\Math\BigInteger $r
    * @param int $i
    * @return \phpseclib3\Math\BigInteger
    */
    private function blind($x, $r, $i)
    {
        $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i]));
        $x = $x->modPow($this->exponents[$i], $this->primes[$i]);
        $r = $r->modInverse($this->primes[$i]);
        $x = $x->multiply($r);
        list(, $x) = $x->divide($this->primes[$i]);
        return $x;
    }
    /**
     * EMSA-PSS-ENCODE
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}.
     *
     * @return string
     * @access private
     * @param string $m
     * @throws \RuntimeException on encoding error
     * @param int $emBits
     */
    private function emsa_pss_encode($m, $emBits)
    {
        // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
        // be output.
        $emLen = $emBits + 1 >> 3;
        // ie. ceil($emBits / 8)
        $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
        $mHash = $this->hash->hash($m);
        if ($emLen < $this->hLen + $sLen + 2) {
            throw new \LengthException('RSA modulus too short');
        }
        $salt = Random::string($sLen);
        $m2 = "\x00\x00\x00\x00\x00\x00\x00\x00" . $mHash . $salt;
        $h = $this->hash->hash($m2);
        $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2);
        $db = $ps . chr(1) . $salt;
        $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1);
        $maskedDB = $db ^ $dbMask;
        $maskedDB[0] = ~chr(0xff << ($emBits & 7)) & $maskedDB[0];
        $em = $maskedDB . $h . chr(0xbc);
        return $em;
    }
    /**
     * RSASSA-PSS-SIGN
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}.
     *
     * @access private
     * @param string $m
     * @return (bool | string)
     */
    private function rsassa_pss_sign($m)
    {
        // EMSA-PSS encoding
        $em = $this->emsa_pss_encode($m, 8 * $this->k - 1);
        // RSA signature
        $m = $this->os2ip($em);
        $s = $this->rsasp1($m);
        $s = $this->i2osp($s, $this->k);
        // Output the signature S
        return $s;
    }
    /**
     * RSASSA-PKCS1-V1_5-SIGN
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}.
     *
     * @access private
     * @param string $m
     * @throws \LengthException if the RSA modulus is too short
     * @return (bool | string)
     */
    private function rsassa_pkcs1_v1_5_sign($m)
    {
        // EMSA-PKCS1-v1_5 encoding
        // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus
        // too short" and stop.
        try {
            $em = $this->emsa_pkcs1_v1_5_encode($m, $this->k);
        } catch (\LengthException $e) {
            throw new \LengthException('RSA modulus too short');
        }
        // RSA signature
        $m = $this->os2ip($em);
        $s = $this->rsasp1($m);
        $s = $this->i2osp($s, $this->k);
        // Output the signature S
        return $s;
    }
    /**
     * Create a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @return string
     */
    public function sign($message)
    {
        switch ($this->signaturePadding) {
            case self::SIGNATURE_PKCS1:
            case self::SIGNATURE_RELAXED_PKCS1:
                return $this->rsassa_pkcs1_v1_5_sign($message);
            //case self::SIGNATURE_PSS:
            default:
                return $this->rsassa_pss_sign($message);
        }
    }
    /**
     * RSAES-PKCS1-V1_5-DECRYPT
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}.
     *
     * @access private
     * @param string $c
     * @return (bool | string)
     */
    private function rsaes_pkcs1_v1_5_decrypt($c)
    {
        // Length checking
        if (strlen($c) != $this->k) {
            // or if k < 11
            throw new \LengthException('Ciphertext representative too long');
        }
        // RSA decryption
        $c = $this->os2ip($c);
        $m = $this->rsadp($c);
        $em = $this->i2osp($m, $this->k);
        // EME-PKCS1-v1_5 decoding
        if (ord($em[0]) != 0 || ord($em[1]) > 2) {
            throw new \RuntimeException('Decryption error');
        }
        $ps = \Phabel\Target\Php80\Polyfill::substr($em, 2, strpos($em, chr(0), 2) - 2);
        $m = \Phabel\Target\Php80\Polyfill::substr($em, strlen($ps) + 3);
        if (strlen($ps) < 8) {
            throw new \RuntimeException('Decryption error');
        }
        // Output M
        return $m;
    }
    /**
    * RSAES-OAEP-DECRYPT
    *
    * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}.  The fact that the error
    messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2:
    *
    * Note.  Care must be taken to ensure that an opponent cannot
    distinguish the different error conditions in Step 3.g, whether by
    error message or timing, or, more generally, learn partial
    information about the encoded message EM.  Otherwise an opponent may
    be able to obtain useful information about the decryption of the
    ciphertext C, leading to a chosen-ciphertext attack such as the one
    observed by Manger [36].
    *
    * @access private
    * @param string $c
    * @return (bool | string)
    */
    private function rsaes_oaep_decrypt($c)
    {
        // Length checking
        // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
        // be output.
        if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) {
            throw new \LengthException('Ciphertext representative too long');
        }
        // RSA decryption
        $c = $this->os2ip($c);
        $m = $this->rsadp($c);
        $em = $this->i2osp($m, $this->k);
        // EME-OAEP decoding
        $lHash = $this->hash->hash($this->label);
        $y = ord($em[0]);
        $maskedSeed = \Phabel\Target\Php80\Polyfill::substr($em, 1, $this->hLen);
        $maskedDB = \Phabel\Target\Php80\Polyfill::substr($em, $this->hLen + 1);
        $seedMask = $this->mgf1($maskedDB, $this->hLen);
        $seed = $maskedSeed ^ $seedMask;
        $dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1);
        $db = $maskedDB ^ $dbMask;
        $lHash2 = \Phabel\Target\Php80\Polyfill::substr($db, 0, $this->hLen);
        $m = \Phabel\Target\Php80\Polyfill::substr($db, $this->hLen);
        $hashesMatch = hash_equals($lHash, $lHash2);
        $leadingZeros = 1;
        $patternMatch = 0;
        $offset = 0;
        for ($i = 0; $i < strlen($m); $i++) {
            $patternMatch |= $leadingZeros & $m[$i] === "\x01";
            $leadingZeros &= $m[$i] === "\x00";
            $offset += $patternMatch ? 0 : 1;
        }
        // we do | instead of || to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation
        // to protect against timing attacks
        if (!$hashesMatch | !$patternMatch) {
            throw new \RuntimeException('Decryption error');
        }
        // Output the message M
        return \Phabel\Target\Php80\Polyfill::substr($m, $offset + 1);
    }
    /**
     * Raw Encryption / Decryption
     *
     * Doesn't use padding and is not recommended.
     *
     * @access private
     * @param string $m
     * @return (bool | string)
     * @throws \LengthException if strlen($m) > $this->k
     */
    private function raw_encrypt($m)
    {
        if (strlen($m) > $this->k) {
            throw new \LengthException('Ciphertext representative too long');
        }
        $temp = $this->os2ip($m);
        $temp = $this->rsadp($temp);
        return $this->i2osp($temp, $this->k);
    }
    /**
     * Decryption
     *
     * @see self::encrypt()
     * @access public
     * @param string $ciphertext
     * @return (bool | string)
     */
    public function decrypt($ciphertext)
    {
        switch ($this->encryptionPadding) {
            case self::ENCRYPTION_NONE:
                return $this->raw_encrypt($ciphertext);
            case self::ENCRYPTION_PKCS1:
                return $this->rsaes_pkcs1_v1_5_decrypt($ciphertext);
            //case self::ENCRYPTION_OAEP:
            default:
                return $this->rsaes_oaep_decrypt($ciphertext);
        }
    }
    /**
     * Returns the public key
     *
     * @access public
     * @return mixed
     */
    public function getPublicKey()
    {
        $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey');
        if (empty($this->modulus) || empty($this->publicExponent)) {
            throw new \RuntimeException('Public key components not found');
        }
        $key = $type::savePublicKey($this->modulus, $this->publicExponent);
        return RSA::loadFormat('PKCS8', $key)->withHash($this->hash->getHash())->withMGFHash($this->mgfHash->getHash())->withSaltLength($this->sLen)->withLabel($this->label)->withPadding($this->signaturePadding | $this->encryptionPadding);
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, empty($this->primes) ? 'savePublicKey' : 'savePrivateKey');
        if ($type == PSS::class) {
            if ($this->signaturePadding == self::SIGNATURE_PSS) {
                $options += ['hash' => $this->hash->getHash(), 'MGFHash' => $this->mgfHash->getHash(), 'saltLength' => $this->getSaltLength()];
            } else {
                throw new UnsupportedFormatException('The PSS format can only be used when the signature method has been explicitly set to PSS');
            }
        }
        if (empty($this->primes)) {
            return $type::savePublicKey($this->modulus, $this->exponent, $options);
        }
        return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password, $options);
        /*
        $key = $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password, $options);
        if ($key !== false || count($this->primes) == 2) {
            return $key;
        }
        
        $nSize = $this->getSize() >> 1;
        
        $primes = [1 => clone self::$one, clone self::$one];
        $i = 1;
        foreach ($this->primes as $prime) {
            $primes[$i] = $primes[$i]->multiply($prime);
            if ($primes[$i]->getLength() >= $nSize) {
                $i++;
            }
        }
        
        $exponents = [];
        $coefficients = [2 => $primes[2]->modInverse($primes[1])];
        
        foreach ($primes as $i => $prime) {
            $temp = $prime->subtract(self::$one);
            $exponents[$i] = $this->modulus->modInverse($temp);
        }
        
        return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $primes, $exponents, $coefficients, $this->password, $options);
        */
    }
}<?php

/**
 * RSA Public Key
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA;

use phpseclib3\Crypt\RSA;
use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Hash;
use phpseclib3\Exception\NoKeyLoadedException;
use phpseclib3\Exception\UnsupportedFormatException;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\Common;
use phpseclib3\File\ASN1\Maps\DigestInfo;
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
/**
 * Raw RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PublicKey extends RSA implements Common\PublicKey
{
    use Common\Traits\Fingerprint;
    /**
     * Exponentiate
     *
     * @param \phpseclib3\Math\BigInteger $x
     * @return \phpseclib3\Math\BigInteger
     */
    private function exponentiate(BigInteger $x)
    {
        return $x->modPow($this->exponent, $this->modulus);
    }
    /**
     * RSAVP1
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $s
     * @return (bool | \phpseclib3\Math\BigInteger)
     */
    private function rsavp1($s)
    {
        if ($s->compare(self::$zero) < 0 || $s->compare($this->modulus) > 0) {
            return false;
        }
        return $this->exponentiate($s);
    }
    /**
     * RSASSA-PKCS1-V1_5-VERIFY
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}.
     *
     * @access private
     * @param string $m
     * @param string $s
     * @throws \LengthException if the RSA modulus is too short
     * @return bool
     */
    private function rsassa_pkcs1_v1_5_verify($m, $s)
    {
        // Length checking
        if (strlen($s) != $this->k) {
            return false;
        }
        // RSA verification
        $s = $this->os2ip($s);
        $m2 = $this->rsavp1($s);
        if ($m2 === false) {
            return false;
        }
        $em = $this->i2osp($m2, $this->k);
        if ($em === false) {
            return false;
        }
        // EMSA-PKCS1-v1_5 encoding
        $exception = false;
        // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus
        // too short" and stop.
        try {
            $em2 = $this->emsa_pkcs1_v1_5_encode($m, $this->k);
            $r1 = hash_equals($em, $em2);
        } catch (\LengthException $e) {
            $exception = true;
        }
        try {
            $em3 = $this->emsa_pkcs1_v1_5_encode_without_null($m, $this->k);
            $r2 = hash_equals($em, $em3);
        } catch (\LengthException $e) {
            $exception = true;
        } catch (UnsupportedAlgorithmException $e) {
            $r2 = false;
        }
        if ($exception) {
            throw new \LengthException('RSA modulus too short');
        }
        // Compare
        return $r1 || $r2;
    }
    /**
    * RSASSA-PKCS1-V1_5-VERIFY (relaxed matching)
    *
    * Per {@link http://tools.ietf.org/html/rfc3447#page-43 RFC3447#page-43} PKCS1 v1.5
    specified the use BER encoding rather than DER encoding that PKCS1 v2.0 specified.
    This means that under rare conditions you can have a perfectly valid v1.5 signature
    that fails to validate with _rsassa_pkcs1_v1_5_verify(). PKCS1 v2.1 also recommends
    that if you're going to validate these types of signatures you "should indicate
    whether the underlying BER encoding is a DER encoding and hence whether the signature
    is valid with respect to the specification given in [PKCS1 v2.0+]". so if you do
    $rsa->getLastPadding() and get RSA::PADDING_RELAXED_PKCS1 back instead of
    RSA::PADDING_PKCS1... that means BER encoding was used.
    *
    * @access private
    * @param string $m
    * @param string $s
    * @return bool
    */
    private function rsassa_pkcs1_v1_5_relaxed_verify($m, $s)
    {
        // Length checking
        if (strlen($s) != $this->k) {
            return false;
        }
        // RSA verification
        $s = $this->os2ip($s);
        $m2 = $this->rsavp1($s);
        if ($m2 === false) {
            return false;
        }
        $em = $this->i2osp($m2, $this->k);
        if ($em === false) {
            return false;
        }
        if (Strings::shift($em, 2) != "\x00\x01") {
            return false;
        }
        $em = ltrim($em, "\xff");
        if (Strings::shift($em) != "\x00") {
            return false;
        }
        $decoded = ASN1::decodeBER($em);
        if (!is_array($decoded) || empty($decoded[0]) || strlen($em) > $decoded[0]['length']) {
            return false;
        }
        static $oids;
        if (!isset($oids)) {
            $oids = [
                'md2' => '1.2.840.113549.2.2',
                'md4' => '1.2.840.113549.2.4',
                // from PKCS1 v1.5
                'md5' => '1.2.840.113549.2.5',
                'id-sha1' => '1.3.14.3.2.26',
                'id-sha256' => '2.16.840.1.101.3.4.2.1',
                'id-sha384' => '2.16.840.1.101.3.4.2.2',
                'id-sha512' => '2.16.840.1.101.3.4.2.3',
                // from PKCS1 v2.2
                'id-sha224' => '2.16.840.1.101.3.4.2.4',
                'id-sha512/224' => '2.16.840.1.101.3.4.2.5',
                'id-sha512/256' => '2.16.840.1.101.3.4.2.6',
            ];
            ASN1::loadOIDs($oids);
        }
        $decoded = ASN1::asn1map($decoded[0], DigestInfo::MAP);
        if (!isset($decoded) || $decoded === false) {
            return false;
        }
        if (!isset($oids[$decoded['digestAlgorithm']['algorithm']])) {
            return false;
        }
        if (isset($decoded['digestAlgorithm']['parameters']) && $decoded['digestAlgorithm']['parameters'] !== ['null' => '']) {
            return false;
        }
        $hash = $decoded['digestAlgorithm']['algorithm'];
        $hash = \Phabel\Target\Php80\Polyfill::substr($hash, 0, 3) == 'id-' ? \Phabel\Target\Php80\Polyfill::substr($hash, 3) : $hash;
        $hash = new Hash($hash);
        $em = $hash->hash($m);
        $em2 = $decoded['digest'];
        return hash_equals($em, $em2);
    }
    /**
     * EMSA-PSS-VERIFY
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}.
     *
     * @access private
     * @param string $m
     * @param string $em
     * @param int $emBits
     * @return string
     */
    private function emsa_pss_verify($m, $em, $emBits)
    {
        // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
        // be output.
        $emLen = $emBits + 7 >> 3;
        // ie. ceil($emBits / 8);
        $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
        $mHash = $this->hash->hash($m);
        if ($emLen < $this->hLen + $sLen + 2) {
            return false;
        }
        if ($em[strlen($em) - 1] != chr(0xbc)) {
            return false;
        }
        $maskedDB = \Phabel\Target\Php80\Polyfill::substr($em, 0, -$this->hLen - 1);
        $h = \Phabel\Target\Php80\Polyfill::substr($em, -$this->hLen - 1, $this->hLen);
        $temp = chr(0xff << ($emBits & 7));
        if ((~$maskedDB[0] & $temp) != $temp) {
            return false;
        }
        $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1);
        $db = $maskedDB ^ $dbMask;
        $db[0] = ~chr(0xff << ($emBits & 7)) & $db[0];
        $temp = $emLen - $this->hLen - $sLen - 2;
        if (\Phabel\Target\Php80\Polyfill::substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) {
            return false;
        }
        $salt = \Phabel\Target\Php80\Polyfill::substr($db, $temp + 1);
        // should be $sLen long
        $m2 = "\x00\x00\x00\x00\x00\x00\x00\x00" . $mHash . $salt;
        $h2 = $this->hash->hash($m2);
        return hash_equals($h, $h2);
    }
    /**
     * RSASSA-PSS-VERIFY
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}.
     *
     * @access private
     * @param string $m
     * @param string $s
     * @return (bool | string)
     */
    private function rsassa_pss_verify($m, $s)
    {
        // Length checking
        if (strlen($s) != $this->k) {
            return false;
        }
        // RSA verification
        $modBits = strlen($this->modulus->toBits());
        $s2 = $this->os2ip($s);
        $m2 = $this->rsavp1($s2);
        $em = $this->i2osp($m2, $this->k);
        if ($em === false) {
            return false;
        }
        // EMSA-PSS verification
        return $this->emsa_pss_verify($m, $em, $modBits - 1);
    }
    /**
     * Verifies a signature
     *
     * @see self::sign()
     * @param string $message
     * @param string $signature
     * @return bool
     */
    public function verify($message, $signature)
    {
        switch ($this->signaturePadding) {
            case self::SIGNATURE_RELAXED_PKCS1:
                return $this->rsassa_pkcs1_v1_5_relaxed_verify($message, $signature);
            case self::SIGNATURE_PKCS1:
                return $this->rsassa_pkcs1_v1_5_verify($message, $signature);
            //case self::SIGNATURE_PSS:
            default:
                return $this->rsassa_pss_verify($message, $signature);
        }
    }
    /**
     * RSAES-PKCS1-V1_5-ENCRYPT
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
     *
     * @access private
     * @param string $m
     * @param bool $pkcs15_compat optional
     * @throws \LengthException if strlen($m) > $this->k - 11
     * @return (bool | string)
     */
    private function rsaes_pkcs1_v1_5_encrypt($m, $pkcs15_compat = false)
    {
        $mLen = strlen($m);
        // Length checking
        if ($mLen > $this->k - 11) {
            throw new \LengthException('Message too long');
        }
        // EME-PKCS1-v1_5 encoding
        $psLen = $this->k - $mLen - 3;
        $ps = '';
        while (strlen($ps) != $psLen) {
            $temp = Random::string($psLen - strlen($ps));
            $temp = str_replace("\x00", '', $temp);
            $ps .= $temp;
        }
        $type = 2;
        $em = chr(0) . chr($type) . $ps . chr(0) . $m;
        // RSA encryption
        $m = $this->os2ip($em);
        $c = $this->rsaep($m);
        $c = $this->i2osp($c, $this->k);
        // Output the ciphertext C
        return $c;
    }
    /**
    * RSAES-OAEP-ENCRYPT
    *
    * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and
    {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
    *
    * @access private
    * @param string $m
    * @throws \LengthException if strlen($m) > $this->k - 2 * $this->hLen - 2
    * @return string
    */
    private function rsaes_oaep_encrypt($m)
    {
        $mLen = strlen($m);
        // Length checking
        // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
        // be output.
        if ($mLen > $this->k - 2 * $this->hLen - 2) {
            throw new \LengthException('Message too long');
        }
        // EME-OAEP encoding
        $lHash = $this->hash->hash($this->label);
        $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2);
        $db = $lHash . $ps . chr(1) . $m;
        $seed = Random::string($this->hLen);
        $dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1);
        $maskedDB = $db ^ $dbMask;
        $seedMask = $this->mgf1($maskedDB, $this->hLen);
        $maskedSeed = $seed ^ $seedMask;
        $em = chr(0) . $maskedSeed . $maskedDB;
        // RSA encryption
        $m = $this->os2ip($em);
        $c = $this->rsaep($m);
        $c = $this->i2osp($c, $this->k);
        // Output the ciphertext C
        return $c;
    }
    /**
     * RSAEP
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}.
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $m
     * @return (bool | \phpseclib3\Math\BigInteger)
     */
    private function rsaep($m)
    {
        if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) {
            throw new \OutOfRangeException('Message representative out of range');
        }
        return $this->exponentiate($m);
    }
    /**
     * Raw Encryption / Decryption
     *
     * Doesn't use padding and is not recommended.
     *
     * @access private
     * @param string $m
     * @return (bool | string)
     * @throws \LengthException if strlen($m) > $this->k
     */
    private function raw_encrypt($m)
    {
        if (strlen($m) > $this->k) {
            throw new \LengthException('Message too long');
        }
        $temp = $this->os2ip($m);
        $temp = $this->rsaep($temp);
        return $this->i2osp($temp, $this->k);
    }
    /**
    * Encryption
    *
    * Both self::PADDING_OAEP and self::PADDING_PKCS1 both place limits on how long $plaintext can be.
    If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will
    be concatenated together.
    *
    * @see self::decrypt()
    * @access public
    * @param string $plaintext
    * @return (bool | string)
    * @throws \LengthException if the RSA modulus is too short
    */
    public function encrypt($plaintext)
    {
        switch ($this->encryptionPadding) {
            case self::ENCRYPTION_NONE:
                return $this->raw_encrypt($plaintext);
            case self::ENCRYPTION_PKCS1:
                return $this->rsaes_pkcs1_v1_5_encrypt($plaintext);
            //case self::ENCRYPTION_OAEP:
            default:
                return $this->rsaes_oaep_encrypt($plaintext);
        }
    }
    /**
    * Returns the public key
    *
    * The public key is only returned under two circumstances - if the private key had the public key embedded within it
    or if the public key was set via setPublicKey().  If the currently loaded key is supposed to be the public key this
    function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
    *
    * @param string $type
    * @param array $options optional
    * @return mixed
    */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePublicKey');
        if ($type == PSS::class) {
            if ($this->signaturePadding == self::SIGNATURE_PSS) {
                $options += ['hash' => $this->hash->getHash(), 'MGFHash' => $this->mgfHash->getHash(), 'saltLength' => $this->getSaltLength()];
            } else {
                throw new UnsupportedFormatException('The PSS format can only be used when the signature method has been explicitly set to PSS');
            }
        }
        return $type::savePublicKey($this->modulus, $this->publicExponent, $options);
    }
    /**
     * Converts a public key to a private key
     *
     * @return RSA
     */
    public function asPrivateKey()
    {
        $new = new PrivateKey();
        $new->exponent = $this->exponent;
        $new->modulus = $this->modulus;
        $new->k = $this->k;
        $new->format = $this->format;
        return $new->withHash($this->hash->getHash())->withMGFHash($this->mgfHash->getHash())->withSaltLength($this->sLen)->withLabel($this->label)->withPadding($this->signaturePadding | $this->encryptionPadding);
    }
}<?php

/**
 * PublicKeyLoader
 *
 * Returns a PublicKey or PrivateKey object.
 *
 * @category  Crypt
 * @package   PublicKeyLoader
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\Common\PublicKey;
use phpseclib3\Crypt\Common\PrivateKey;
use phpseclib3\Exception\NoKeyLoadedException;
use phpseclib3\File\X509;
/**
 * PublicKeyLoader
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PublicKeyLoader
{
    /**
     * Loads a public or private key
     *
     * @return AsymmetricKey
     * @access public
     * @param (string | array) $key
     * @param string $password optional
     */
    public static function load($key, $password = false)
    {
        try {
            return EC::load($key, $password);
        } catch (NoKeyLoadedException $e) {
        }
        try {
            return RSA::load($key, $password);
        } catch (NoKeyLoadedException $e) {
        }
        try {
            return DSA::load($key, $password);
        } catch (NoKeyLoadedException $e) {
        }
        try {
            $x509 = new X509();
            $x509->loadX509($key);
            $key = $x509->getPublicKey();
            if ($key) {
                return $key;
            }
        } catch (\Exception $e) {
        }
        throw new NoKeyLoadedException('Unable to read key');
    }
    /**
     * Loads a private key
     *
     * @return PrivateKey
     * @access public
     * @param (string | array) $key
     * @param string $password optional
     */
    public static function loadPrivateKey($key, $password = false)
    {
        $key = self::load($key, $password);
        if (!$key instanceof PrivateKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a private key');
        }
        return $key;
    }
    /**
     * Loads a public key
     *
     * @return PublicKey
     * @access public
     * @param (string | array) $key
     */
    public static function loadPublicKey($key)
    {
        $key = self::load($key);
        if (!$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a public key');
        }
        return $key;
    }
    /**
     * Loads parameters
     *
     * @return AsymmetricKey
     * @access public
     * @param (string | array) $key
     */
    public static function loadParameters($key)
    {
        $key = self::load($key);
        if (!$key instanceof PrivateKey && !$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a parameter');
        }
        return $key;
    }
}<?php

/**
 * PKCS#1 Formatted DSA Key Handler
 *
 * PHP version 5
 *
 * Used by File/X509.php
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN DSA PRIVATE KEY-----
 * -----BEGIN DSA PUBLIC KEY-----
 * -----BEGIN DSA PARAMETERS-----
 *
 * Analogous to ssh-keygen's pem format (as specified by -m)
 *
 * Also, technically, PKCS1 decribes RSA but I am not aware of a formal specification for DSA.
 * The DSA private key format seems to have been adapted from the RSA private key format so
 * we're just re-using that as the name.
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use ParagonIE\ConstantTime\Base64;
/**
 * PKCS#1 Formatted DSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends Progenitor
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $key = parent::load($key, $password);
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $key = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP);
        if (is_array($key)) {
            return $key;
        }
        $key = ASN1::asn1map($decoded[0], Maps\DSAPrivateKey::MAP);
        if (is_array($key)) {
            return $key;
        }
        $key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
        if (is_array($key)) {
            return $key;
        }
        throw new \RuntimeException('Unable to perform ASN1 mapping');
    }
    /**
     * Convert DSA parameters to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @return string
     */
    public static function saveParameters(BigInteger $p, BigInteger $q, BigInteger $g)
    {
        $key = ['p' => $p, 'q' => $q, 'g' => $g];
        $key = ASN1::encodeDER($key, Maps\DSAParams::MAP);
        return "-----BEGIN DSA PARAMETERS-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END DSA PARAMETERS-----\r\n";
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = [])
    {
        $key = ['version' => 0, 'p' => $p, 'q' => $q, 'g' => $g, 'y' => $y, 'x' => $x];
        $key = ASN1::encodeDER($key, Maps\DSAPrivateKey::MAP);
        return self::wrapPrivateKey($key, 'DSA', $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y)
    {
        $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP);
        return self::wrapPublicKey($key, 'DSA');
    }
}<?php

/**
 * PKCS#8 Formatted DSA Key Handler
 *
 * PHP version 5
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
 * is specific to private keys it's basically creating a DER-encoded wrapper
 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends Progenitor
{
    /**
     * OID Name
     *
     * @var string
     * @access private
     */
    const OID_NAME = 'id-dsa';
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = '1.2.840.10040.4.1';
    /**
     * Child OIDs loaded
     *
     * @var bool
     * @access private
     */
    protected static $childOIDsLoaded = false;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $isPublic = strpos($key, 'PUBLIC') !== false;
        $key = parent::load($key, $password);
        $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
        switch (true) {
            case !$isPublic && $type == 'publicKey':
                throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
            case $isPublic && $type == 'privateKey':
                throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
        }
        $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER of parameters');
        }
        $components = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP);
        if (!is_array($components)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping on parameters');
        }
        $decoded = ASN1::decodeBER($key[$type]);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $var = $type == 'privateKey' ? 'x' : 'y';
        $components[$var] = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
        if (!$components[$var] instanceof BigInteger) {
            throw new \RuntimeException('Unable to perform ASN1 mapping');
        }
        if (isset($key['meta'])) {
            $components['meta'] = $key['meta'];
        }
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = [])
    {
        $params = ['p' => $p, 'q' => $q, 'g' => $g];
        $params = ASN1::encodeDER($params, Maps\DSAParams::MAP);
        $params = new ASN1\Element($params);
        $key = ASN1::encodeDER($x, Maps\DSAPublicKey::MAP);
        return self::wrapPrivateKey($key, [], $params, $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, array $options = [])
    {
        $params = ['p' => $p, 'q' => $q, 'g' => $g];
        $params = ASN1::encodeDER($params, Maps\DSAParams::MAP);
        $params = new ASN1\Element($params);
        $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP);
        return self::wrapPublicKey($key, $params);
    }
}<?php

/**
 * PuTTY Formatted DSA Key Handler
 *
 * puttygen does not generate DSA keys with an N of anything other than 160, however,
 * it can still load them and convert them. PuTTY will load them, too, but SSH servers
 * won't accept them. Since PuTTY formatted keys are primarily used with SSH this makes
 * keys with N > 160 kinda useless, hence this handlers not supporting such keys.
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor;
/**
 * PuTTY Formatted DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PuTTY extends Progenitor
{
    /**
     * Public Handler
     *
     * @var string
     * @access private
     */
    const PUBLIC_HANDLER = 'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\OpenSSH';
    /**
     * Algorithm Identifier
     *
     * @var array
     * @access private
     */
    protected static $types = ['ssh-dss'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $components = parent::load($key, $password);
        if (!isset($components['private'])) {
            return $components;
        }
        extract($components);
        unset($components['public'], $components['private']);
        list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $public);
        list($x) = Strings::unpackSSH2('i', $private);
        return compact('p', 'q', 'g', 'y', 'x', 'comment');
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = false, array $options = [])
    {
        if ($q->getLength() != 160) {
            throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
        }
        $public = Strings::packSSH2('iiii', $p, $q, $g, $y);
        $private = Strings::packSSH2('i', $x);
        return self::wrapPrivateKey($public, $private, 'ssh-dsa', $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y)
    {
        if ($q->getLength() != 160) {
            throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
        }
        return self::wrapPublicKey(Strings::packSSH2('iiii', $p, $q, $g, $y), 'ssh-dsa');
    }
}<?php

/**
 * XML Formatted DSA Key Handler
 *
 * While XKMS defines a private key format for RSA it does not do so for DSA. Quoting that standard:
 *
 * "[XKMS] does not specify private key parameters for the DSA signature algorithm since the algorithm only
 *  supports signature modes and so the application of server generated keys and key recovery is of limited
 *  value"
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
/**
 * XML Formatted DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class XML
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $use_errors = libxml_use_internal_errors(true);
        $dom = new \DOMDocument();
        if (\Phabel\Target\Php80\Polyfill::substr($key, 0, 5) != '<?xml') {
            $key = '<xml>' . $key . '</xml>';
        }
        if (!$dom->loadXML($key)) {
            throw new \UnexpectedValueException('Key does not appear to contain XML');
        }
        $xpath = new \DOMXPath($dom);
        $keys = ['p', 'q', 'g', 'y', 'j', 'seed', 'pgencounter'];
        foreach ($keys as $key) {
            // $dom->getElementsByTagName($key) is case-sensitive
            $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='{$key}']");
            if (!$temp->length) {
                continue;
            }
            $value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256);
            switch ($key) {
                case 'p':
                    // a prime modulus meeting the [DSS] requirements
                    // Parameters P, Q, and G can be public and common to a group of users. They might be known
                    // from application context. As such, they are optional but P and Q must either both appear
                    // or both be absent
                    $components['p'] = $value;
                    break;
                case 'q':
                    // an integer in the range 2**159 < Q < 2**160 which is a prime divisor of P-1
                    $components['q'] = $value;
                    break;
                case 'g':
                    // an integer with certain properties with respect to P and Q
                    $components['g'] = $value;
                    break;
                case 'y':
                    // G**X mod P (where X is part of the private key and not made public)
                    $components['y'] = $value;
                // the remaining options do not do anything
                case 'j':
                // (P - 1) / Q
                // Parameter J is available for inclusion solely for efficiency as it is calculatable from
                // P and Q
                case 'seed':
                // a DSA prime generation seed
                // Parameters seed and pgenCounter are used in the DSA prime number generation algorithm
                // specified in [DSS]. As such, they are optional but must either both be present or both
                // be absent
                case 'pgencounter':
            }
        }
        libxml_use_internal_errors($use_errors);
        if (!isset($components['y'])) {
            throw new \UnexpectedValueException('Key is missing y component');
        }
        switch (true) {
            case !isset($components['p']):
            case !isset($components['q']):
            case !isset($components['g']):
                return ['y' => $components['y']];
        }
        return $components;
    }
    /**
     * Convert a public key to the appropriate format
     *
     * See https://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y)
    {
        return '<DSAKeyValue>
  <P>' . Base64::encode($p->toBytes()) . '</P>
  <Q>' . Base64::encode($q->toBytes()) . '</Q>
  <G>' . Base64::encode($g->toBytes()) . '</G>
  <Y>' . Base64::encode($y->toBytes()) . '</Y>
</DSAKeyValue>';
    }
}<?php

/**
 * OpenSSH Formatted DSA Key Handler
 *
 * PHP version 5
 *
 * Place in $HOME/.ssh/authorized_keys
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor;
/**
 * OpenSSH Formatted DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSH extends Progenitor
{
    /**
     * Supported Key Types
     *
     * @var array
     */
    protected static $types = ['ssh-dss'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $parsed = parent::load($key, $password);
        if (isset($parsed['paddedKey'])) {
            list($type) = Strings::unpackSSH2('s', $parsed['paddedKey']);
            if ($type != $parsed['type']) {
                throw new \RuntimeException("The public and private keys are not of the same type ({$type} vs {$parsed['type']})");
            }
            list($p, $q, $g, $y, $x, $comment) = Strings::unpackSSH2('i5s', $parsed['paddedKey']);
            return compact('p', 'q', 'g', 'y', 'x', 'comment');
        }
        list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $parsed['publicKey']);
        $comment = $parsed['comment'];
        return compact('p', 'q', 'g', 'y', 'comment');
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, array $options = [])
    {
        if ($q->getLength() != 160) {
            throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
        }
        // from <http://tools.ietf.org/html/rfc4253#page-15>:
        // string    "ssh-dss"
        // mpint     p
        // mpint     q
        // mpint     g
        // mpint     y
        $DSAPublicKey = Strings::packSSH2('siiii', 'ssh-dss', $p, $q, $g, $y);
        if (isset($options['binary']) ? $options['binary'] : self::$binary) {
            return $DSAPublicKey;
        }
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        $DSAPublicKey = 'ssh-dss ' . base64_encode($DSAPublicKey) . ' ' . $comment;
        return $DSAPublicKey;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = [])
    {
        $publicKey = self::savePublicKey($p, $q, $g, $y, ['binary' => true]);
        $privateKey = Strings::packSSH2('si5', 'ssh-dss', $p, $q, $g, $y, $x);
        return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
    }
}<?php

/**
 * Raw DSA Key Handler
 *
 * PHP version 5
 *
 * Reads and creates arrays as DSA keys
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
/**
 * Raw DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param array $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!is_array($key)) {
            throw new \UnexpectedValueException('Key should be a array - not a ' . gettype($key));
        }
        switch (true) {
            case !isset($key['p']) || !isset($key['q']) || !isset($key['g']):
            case !$key['p'] instanceof BigInteger:
            case !$key['q'] instanceof BigInteger:
            case !$key['g'] instanceof BigInteger:
            case !isset($key['x']) && !isset($key['y']):
            case isset($key['x']) && !$key['x'] instanceof BigInteger:
            case isset($key['y']) && !$key['y'] instanceof BigInteger:
                throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $options = ['p' => 1, 'q' => 1, 'g' => 1, 'x' => 1, 'y' => 1];
        return array_intersect_key($key, $options);
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '')
    {
        return compact('p', 'q', 'g', 'y', 'x');
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y)
    {
        return compact('p', 'q', 'g', 'y');
    }
}<?php

/**
 * ASN1 Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures in the format described in
 * https://tools.ietf.org/html/rfc3279#section-2.2.2
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Signature;

use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1 as Encoder;
use phpseclib3\File\ASN1\Maps;
/**
 * ASN1 Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ASN1
{
    /**
     * Loads a signature
     *
     * @access public
     * @param string $sig
     * @return (array | bool)
     */
    public static function load($sig)
    {
        if (!is_string($sig)) {
            return false;
        }
        $decoded = Encoder::decodeBER($sig);
        if (empty($decoded)) {
            return false;
        }
        $components = Encoder::asn1map($decoded[0], Maps\DssSigValue::MAP);
        return $components;
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s)
    {
        return Encoder::encodeDER(compact('r', 's'), Maps\DssSigValue::MAP);
    }
}<?php

/**
 * Raw DSA Signature Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Signature;

use phpseclib3\Crypt\Common\Formats\Signature\Raw as Progenitor;
/**
 * Raw DSA Signature Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw extends Progenitor
{
}<?php

/**
 * SSH2 Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures in the format used by SSH2
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Signature;

use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
/**
 * SSH2 Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SSH2
{
    /**
     * Loads a signature
     *
     * @access public
     * @param string $sig
     * @return mixed
     */
    public static function load($sig)
    {
        if (!is_string($sig)) {
            return false;
        }
        $result = Strings::unpackSSH2('ss', $sig);
        if ($result === false) {
            return false;
        }
        list($type, $blob) = $result;
        if ($type != 'ssh-dss' || strlen($blob) != 40) {
            return false;
        }
        return ['r' => new BigInteger(\Phabel\Target\Php80\Polyfill::substr($blob, 0, 20), 256), 's' => new BigInteger(\Phabel\Target\Php80\Polyfill::substr($blob, 20), 256)];
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s)
    {
        if ($r->getLength() > 160 || $s->getLength() > 160) {
            return false;
        }
        return Strings::packSSH2('ss', 'ssh-dss', str_pad($r->toBytes(), 20, "\x00", STR_PAD_LEFT) . str_pad($s->toBytes(), 20, "\x00", STR_PAD_LEFT));
    }
}<?php

/**
 * DSA Parameters
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA;

use phpseclib3\Crypt\DSA;
/**
 * DSA Parameters
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Parameters extends DSA
{
    /**
     * Returns the parameters
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type = 'PKCS1', array $options = [])
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        return $type::saveParameters($this->p, $this->q, $this->g, $options);
    }
}<?php

/**
 * DSA Private Key
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA;

use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common;
/**
 * DSA Private Key
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrivateKey extends DSA implements Common\PrivateKey
{
    use Common\Traits\PasswordProtected;
    /**
     * DSA secret exponent x
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $x;
    /**
    * Returns the public key
    *
    * If you do "openssl rsa -in private.rsa -pubout -outform PEM" you get a PKCS8 formatted key
    that contains a publicKeyAlgorithm AlgorithmIdentifier and a publicKey BIT STRING.
    An AlgorithmIdentifier contains an OID and a parameters field. With RSA public keys this
    parameters field is NULL. With DSA PKCS8 public keys it is not - it contains the p, q and g
    variables. The publicKey BIT STRING contains, simply, the y variable. This can be verified
    by getting a DSA PKCS8 public key:
    *
    * "openssl dsa -in private.dsa -pubout -outform PEM"
    *
    * ie. just swap out rsa with dsa in the rsa command above.
    *
    * A PKCS1 public key corresponds to the publicKey portion of the PKCS8 key. In the case of RSA
    the publicKey portion /is/ the key. In the case of DSA it is not. You cannot verify a signature
    without the parameters and the PKCS1 DSA public key format does not include the parameters.
    *
    * @see self::getPrivateKey()
    * @access public
    * @return mixed
    */
    public function getPublicKey()
    {
        $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey');
        if (!isset($this->y)) {
            $this->y = $this->g->powMod($this->x, $this->p);
        }
        $key = $type::savePublicKey($this->p, $this->q, $this->g, $this->y);
        return DSA::loadFormat('PKCS8', $key)->withHash($this->hash->getHash())->withSignatureFormat($this->shortFormat);
    }
    /**
     * Create a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @return mixed
     */
    public function sign($message)
    {
        $format = $this->sigFormat;
        if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
            $signature = '';
            $result = openssl_sign($message, $signature, $this->toString('PKCS8'), $this->hash->getHash());
            if ($result) {
                if ($this->shortFormat == 'ASN1') {
                    return $signature;
                }
                extract(ASN1Signature::load($signature));
                return $format::save($r, $s);
            }
        }
        $h = $this->hash->hash($message);
        $h = $this->bits2int($h);
        while (true) {
            $k = BigInteger::randomRange(self::$one, $this->q->subtract(self::$one));
            $r = $this->g->powMod($k, $this->p);
            list(, $r) = $r->divide($this->q);
            if ($r->equals(self::$zero)) {
                continue;
            }
            $kinv = $k->modInverse($this->q);
            $temp = $h->add($this->x->multiply($r));
            $temp = $kinv->multiply($temp);
            list(, $s) = $temp->divide($this->q);
            if (!$s->equals(self::$zero)) {
                break;
            }
        }
        // the following is an RFC6979 compliant implementation of deterministic DSA
        // it's unused because it's mainly intended for use when a good CSPRNG isn't
        // available. if phpseclib's CSPRNG isn't good then even key generation is
        // suspect
        /*
        $h1 = $this->hash->hash($message);
        $k = $this->computek($h1);
        $r = $this->g->powMod($k, $this->p);
        list(, $r) = $r->divide($this->q);
        $kinv = $k->modInverse($this->q);
        $h1 = $this->bits2int($h1);
        $temp = $h1->add($this->x->multiply($r));
        $temp = $kinv->multiply($temp);
        list(, $s) = $temp->divide($this->q);
        */
        return $format::save($r, $s);
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePrivateKey');
        if (!isset($this->y)) {
            $this->y = $this->g->powMod($this->x, $this->p);
        }
        return $type::savePrivateKey($this->p, $this->q, $this->g, $this->y, $this->x, $this->password, $options);
    }
}<?php

/**
 * DSA Public Key
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA;

use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
use phpseclib3\Crypt\Common;
/**
 * DSA Public Key
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PublicKey extends DSA implements Common\PublicKey
{
    use Common\Traits\Fingerprint;
    /**
     * Verify a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @param string $signature
     * @return mixed
     */
    public function verify($message, $signature)
    {
        $format = $this->sigFormat;
        $params = $format::load($signature);
        if ($params === false || count($params) != 2) {
            return false;
        }
        extract($params);
        if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
            $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature;
            $result = openssl_verify($message, $sig, $this->toString('PKCS8'), $this->hash->getHash());
            if ($result != -1) {
                return (bool) $result;
            }
        }
        $q_1 = $this->q->subtract(self::$one);
        if (!$r->between(self::$one, $q_1) || !$s->between(self::$one, $q_1)) {
            return false;
        }
        $w = $s->modInverse($this->q);
        $h = $this->hash->hash($message);
        $h = $this->bits2int($h);
        list(, $u1) = $h->multiply($w)->divide($this->q);
        list(, $u2) = $r->multiply($w)->divide($this->q);
        $v1 = $this->g->powMod($u1, $this->p);
        $v2 = $this->y->powMod($u2, $this->p);
        list(, $v) = $v1->multiply($v2)->divide($this->p);
        list(, $v) = $v->divide($this->q);
        return $v->equals($r);
    }
    /**
     * Returns the public key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePublicKey');
        return $type::savePublicKey($this->p, $this->q, $this->g, $this->y, $options);
    }
}<?php

/**
 * Pure-PHP FIPS 186-4 compliant implementation of DSA.
 *
 * PHP version 5
 *
 * Here's an example of how to create signatures and verify signatures with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $private = \phpseclib3\Crypt\DSA::createKey();
 * $public = $private->getPublicKey();
 *
 * $plaintext = 'terrafrost';
 *
 * $signature = $private->sign($plaintext);
 *
 * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\DSA\PrivateKey;
use phpseclib3\Crypt\DSA\PublicKey;
use phpseclib3\Crypt\DSA\Parameters;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\InsufficientSetupException;
/**
 * Pure-PHP FIPS 186-4 compliant implementation of DSA.
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DSA extends AsymmetricKey
{
    /**
     * Algorithm Name
     *
     * @var string
     * @access private
     */
    const ALGORITHM = 'DSA';
    /**
     * DSA Prime P
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $p;
    /**
     * DSA Group Order q
     *
     * Prime divisor of p-1
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $q;
    /**
     * DSA Group Generator G
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $g;
    /**
     * DSA public key value y
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $y;
    /**
     * Signature Format
     *
     * @var string
     * @access private
     */
    protected $sigFormat;
    /**
     * Signature Format (Short)
     *
     * @var string
     * @access private
     */
    protected $shortFormat;
    /**
     * Create DSA parameters
     *
     * @access public
     * @param int $L
     * @param int $N
     * @return (\phpseclib3\Crypt\DSA | bool)
     */
    public static function createParameters($L = 2048, $N = 224)
    {
        self::initialize_static_variables();
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        switch (true) {
            case $N == 160:
            /*
              in FIPS 186-1 and 186-2 N was fixed at 160 whereas K had an upper bound of 1024.
              RFC 4253 (SSH Transport Layer Protocol) references FIPS 186-2 and as such most
              SSH DSA implementations only support keys with an N of 160.
              puttygen let's you set the size of L (but not the size of N) and uses 2048 as the
              default L value. that's not really compliant with any of the FIPS standards, however,
              for the purposes of maintaining compatibility with puttygen, we'll support it 
            */
            //case ($L >= 512 || $L <= 1024) && (($L & 0x3F) == 0) && $N == 160:
            // FIPS 186-3 changed this as follows:
            //case $L == 1024 && $N == 160:
            case $L == 2048 && $N == 224:
            case $L == 2048 && $N == 256:
            case $L == 3072 && $N == 256:
                break;
            default:
                throw new \InvalidArgumentException('Invalid values for N and L');
        }
        $two = new BigInteger(2);
        $q = BigInteger::randomPrime($N);
        $divisor = $q->multiply($two);
        do {
            $x = BigInteger::random($L);
            list(, $c) = $x->divide($divisor);
            $p = $x->subtract($c->subtract(self::$one));
        } while ($p->getLength() != $L || !$p->isPrime());
        $p_1 = $p->subtract(self::$one);
        list($e) = $p_1->divide($q);
        // quoting http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#page=50 ,
        // "h could be obtained from a random number generator or from a counter that
        //  changes after each use". PuTTY (sshdssg.c) starts h off at 1 and increments
        // it on each loop. wikipedia says "commonly h = 2 is used" so we'll just do that
        $h = clone $two;
        while (true) {
            $g = $h->powMod($e, $p);
            if (!$g->equals(self::$one)) {
                break;
            }
            $h = $h->add(self::$one);
        }
        $dsa = new Parameters();
        $dsa->p = $p;
        $dsa->q = $q;
        $dsa->g = $g;
        return $dsa;
    }
    /**
    * Create public / private key pair.
    *
    * This method is a bit polymorphic. It can take a DSA/Parameters object, L / N as two distinct parameters or
    no parameters (at which point L and N will be generated with this method)
    *
    * Returns the private key, from which the publickey can be extracted
    *
    * @param int[] ...$args
    * @access public
    * @return DSA\PrivateKey
    */
    public static function createKey(...$args)
    {
        self::initialize_static_variables();
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) {
            $params = self::createParameters($args[0], $args[1]);
        } else {
            if (count($args) == 1 && $args[0] instanceof Parameters) {
                $params = $args[0];
            } else {
                if (!count($args)) {
                    $params = self::createParameters();
                } else {
                    throw new InsufficientSetupException('Valid parameters are either two integers (L and N), a single DSA object or no parameters at all.');
                }
            }
        }
        $private = new PrivateKey();
        $private->p = $params->p;
        $private->q = $params->q;
        $private->g = $params->g;
        $private->x = BigInteger::randomRange(self::$one, $private->q->subtract(self::$one));
        $private->y = $private->g->powMod($private->x, $private->p);
        //$public = clone $private;
        //unset($public->x);
        return $private->withHash($params->hash->getHash())->withSignatureFormat($params->shortFormat);
    }
    /**
     * OnLoad Handler
     *
     * @return bool
     * @access protected
     * @param array $components
     */
    protected static function onLoad($components)
    {
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        if (!isset($components['x']) && !isset($components['y'])) {
            $new = new Parameters();
        } else {
            if (isset($components['x'])) {
                $new = new PrivateKey();
                $new->x = $components['x'];
            } else {
                $new = new PublicKey();
            }
        }
        $new->p = $components['p'];
        $new->q = $components['q'];
        $new->g = $components['g'];
        if (isset($components['y'])) {
            $new->y = $components['y'];
        }
        return $new;
    }
    /**
     * Constructor
     *
     * PublicKey and PrivateKey objects can only be created from abstract RSA class
     */
    protected function __construct()
    {
        $this->sigFormat = self::validatePlugin('Signature', 'ASN1');
        $this->shortFormat = 'ASN1';
        parent::__construct();
    }
    /**
     * Returns the key size
     *
     * More specifically, this L (the length of DSA Prime P) and N (the length of DSA Group Order q)
     *
     * @access public
     * @return array
     */
    public function getLength()
    {
        return ['L' => $this->p->getLength(), 'N' => $this->q->getLength()];
    }
    /**
     * Returns the current engine being used
     *
     * @see self::useInternalEngine()
     * @see self::useBestEngine()
     * @access public
     * @return string
     */
    public function getEngine()
    {
        return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ? 'OpenSSL' : 'PHP';
    }
    /**
    * Returns the parameters
    *
    * A public / private key is only returned if the currently loaded "key" contains an x or y
    value.
    *
    * @see self::getPublicKey()
    * @access public
    * @return mixed
    */
    public function getParameters()
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        $key = $type::saveParameters($this->p, $this->q, $this->g);
        return DSA::load($key, 'PKCS1')->withHash($this->hash->getHash())->withSignatureFormat($this->shortFormat);
    }
    /**
     * Determines the signature padding mode
     *
     * Valid values are: ASN1, SSH2, Raw
     *
     * @access public
     * @param string $format
     */
    public function withSignatureFormat($format)
    {
        $new = clone $this;
        $new->shortFormat = $format;
        $new->sigFormat = self::validatePlugin('Signature', $format);
        return $new;
    }
    /**
     * Returns the signature format currently being used
     *
     * @access public
     */
    public function getSignatureFormat()
    {
        return $this->shortFormat;
    }
}<?php

/**
 * Pure-PHP implementation of Triple DES.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.  Operates in the EDE3 mode (encrypt-decrypt-encrypt).
 *
 * PHP version 5
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $des = new \phpseclib3\Crypt\TripleDES('ctr');
 *
 *    $des->setKey('abcdefghijklmnopqrstuvwx');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $des->decrypt($des->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   TripleDES
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

/**
 * Pure-PHP implementation of Triple DES.
 *
 * @package TripleDES
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class TripleDES extends DES
{
    /**
     * Encrypt / decrypt using inner chaining
     *
     * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3).
     */
    const MODE_3CBC = -2;
    /**
     * Encrypt / decrypt using outer chaining
     *
     * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib3\Crypt\Common\BlockCipher::MODE_CBC.
     */
    const MODE_CBC3 = self::MODE_CBC;
    /**
     * Key Length (in bytes)
     *
     * @see \phpseclib3\Crypt\TripleDES::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 24;
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\DES::cipher_name_mcrypt
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'tripledes';
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 750;
    /**
     * max possible size of $key
     *
     * @see self::setKey()
     * @see \phpseclib3\Crypt\DES::setKey()
     * @var string
     * @access private
     */
    protected $key_length_max = 24;
    /**
     * Internal flag whether using self::MODE_3CBC or not
     *
     * @var bool
     * @access private
     */
    private $mode_3cbc;
    /**
     * The \phpseclib3\Crypt\DES objects
     *
     * Used only if $mode_3cbc === true
     *
     * @var array
     * @access private
     */
    private $des;
    /**
     * Default Constructor.
     *
     * Determines whether or not the mcrypt or OpenSSL extensions should be used.
     *
     * $mode could be:
     *
     * - ecb
     *
     * - cbc
     *
     * - ctr
     *
     * - cfb
     *
     * - ofb
     *
     * - 3cbc
     *
     * - cbc3 (same as cbc)
     *
     * @see \phpseclib3\Crypt\DES::__construct()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param string $mode
     * @access public
     */
    public function __construct($mode)
    {
        switch (strtolower($mode)) {
            // In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
            // and additional flag us internally as 3CBC
            case '3cbc':
                parent::__construct('cbc');
                $this->mode_3cbc = true;
                // This three $des'es will do the 3CBC work (if $key > 64bits)
                $this->des = [new DES('cbc'), new DES('cbc'), new DES('cbc')];
                // we're going to be doing the padding, ourselves, so disable it in the \phpseclib3\Crypt\DES objects
                $this->des[0]->disablePadding();
                $this->des[1]->disablePadding();
                $this->des[2]->disablePadding();
                break;
            case 'cbc3':
                $mode = 'cbc';
            // If not 3CBC, we init as usual
            default:
                parent::__construct($mode);
                if ($this->mode == self::MODE_STREAM) {
                    throw new BadModeException('Block ciphers cannot be ran in stream mode');
                }
        }
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        if ($engine == self::ENGINE_OPENSSL) {
            $this->cipher_name_openssl_ecb = 'des-ede3';
            $mode = $this->openssl_translate_mode();
            $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Sets the initialization vector.
     *
     * SetIV is not required when \phpseclib3\Crypt\Common\SymmetricKey::MODE_ECB is being used.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setIV()
     * @access public
     * @param string $iv
     */
    public function setIV($iv)
    {
        parent::setIV($iv);
        if ($this->mode_3cbc) {
            $this->des[0]->setIV($iv);
            $this->des[1]->setIV($iv);
            $this->des[2]->setIV($iv);
        }
    }
    /**
     * Sets the key length.
     *
     * Valid key lengths are 128 and 192 bits.
     *
     * If you want to use a 64-bit key use DES.php
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey:setKeyLength()
     * @access public
     * @throws \LengthException if the key length is invalid
     * @param int $length
     */
    public function setKeyLength($length)
    {
        switch ($length) {
            case 128:
            case 192:
                break;
            default:
                throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128 or 192 bits are supported');
        }
        parent::setKeyLength($length);
    }
    /**
     * Sets the key.
     *
     * Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys.
     *
     * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
     *
     * @access public
     * @see \phpseclib3\Crypt\DES::setKey()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
     * @throws \LengthException if the key length is invalid
     * @param string $key
     */
    public function setKey($key)
    {
        if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
            throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
        }
        switch (strlen($key)) {
            case 16:
                $key .= \Phabel\Target\Php80\Polyfill::substr($key, 0, 8);
                break;
            case 24:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 24 are supported');
        }
        // copied from self::setKey()
        $this->key = $key;
        $this->key_length = strlen($key);
        $this->changed = $this->nonIVChanged = true;
        $this->setEngine();
        if ($this->mode_3cbc) {
            $this->des[0]->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, 8));
            $this->des[1]->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 8, 8));
            $this->des[2]->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 16, 8));
        }
    }
    /**
     * Encrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @access public
     * @param string $plaintext
     * @return string $cipertext
     */
    public function encrypt($plaintext)
    {
        // parent::en/decrypt() is able to do all the work for all modes and keylengths,
        // except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits
        // if the key is smaller then 8, do what we'd normally do
        if ($this->mode_3cbc && strlen($this->key) > 8) {
            return $this->des[2]->encrypt($this->des[1]->decrypt($this->des[0]->encrypt($this->pad($plaintext))));
        }
        return parent::encrypt($plaintext);
    }
    /**
     * Decrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @access public
     * @param string $ciphertext
     * @return string $plaintext
     */
    public function decrypt($ciphertext)
    {
        if ($this->mode_3cbc && strlen($this->key) > 8) {
            return $this->unpad($this->des[0]->decrypt($this->des[1]->encrypt($this->des[2]->decrypt(str_pad($ciphertext, strlen($ciphertext) + 7 & 0xfffffff8, "\x00")))));
        }
        return parent::decrypt($ciphertext);
    }
    /**
    * Treat consecutive "packets" as if they are a continuous buffer.
    *
    * Say you have a 16-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
    will yield different outputs:
    *
    * <code>
    echo $des->encrypt(substr($plaintext, 0, 8));
    echo $des->encrypt(substr($plaintext, 8, 8));
    </code>
    <code>
    echo $des->encrypt($plaintext);
    </code>
    *
    * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
    another, as demonstrated with the following:
    *
    * <code>
    $des->encrypt(substr($plaintext, 0, 8));
    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
    </code>
    <code>
    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
    </code>
    *
    * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
    outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
    decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
    *
    * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\DES() object changes after each
    encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
    continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
    however, they are also less intuitive and more likely to cause you problems.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::enableContinuousBuffer()
    * @see self::disableContinuousBuffer()
    * @access public
    */
    public function enableContinuousBuffer()
    {
        parent::enableContinuousBuffer();
        if ($this->mode_3cbc) {
            $this->des[0]->enableContinuousBuffer();
            $this->des[1]->enableContinuousBuffer();
            $this->des[2]->enableContinuousBuffer();
        }
    }
    /**
     * Treat consecutive packets as if they are a discontinuous buffer.
     *
     * The default behavior.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::disableContinuousBuffer()
     * @see self::enableContinuousBuffer()
     * @access public
     */
    public function disableContinuousBuffer()
    {
        parent::disableContinuousBuffer();
        if ($this->mode_3cbc) {
            $this->des[0]->disableContinuousBuffer();
            $this->des[1]->disableContinuousBuffer();
            $this->des[2]->disableContinuousBuffer();
        }
    }
    /**
     * Creates the key schedule
     *
     * @see \phpseclib3\Crypt\DES::setupKey()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
     * @access private
     */
    protected function setupKey()
    {
        switch (true) {
            // if $key <= 64bits we configure our internal pure-php cipher engine
            // to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
            case strlen($this->key) <= 8:
                $this->des_rounds = 1;
                break;
            // otherwise, if $key > 64bits, we configure our engine to work as 3DES.
            default:
                $this->des_rounds = 3;
                // (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
                if ($this->mode_3cbc) {
                    $this->des[0]->setupKey();
                    $this->des[1]->setupKey();
                    $this->des[2]->setupKey();
                    // because $des[0-2] will, now, do all the work we can return here
                    // not need unnecessary stress parent::setupKey() with our, now unused, $key.
                    return;
                }
        }
        // setup our key
        parent::setupKey();
    }
    /**
     * Sets the internal crypt engine
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setPreferredEngine()
     * @param int $engine
     * @access public
     */
    public function setPreferredEngine($engine)
    {
        if ($this->mode_3cbc) {
            $this->des[0]->setPreferredEngine($engine);
            $this->des[1]->setPreferredEngine($engine);
            $this->des[2]->setPreferredEngine($engine);
        }
        parent::setPreferredEngine($engine);
    }
}<?php

/**
 * Pure-PHP implementation of Twofish.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $twofish = new \phpseclib3\Crypt\Twofish('ctr');
 *
 *    $twofish->setKey('12345678901234567890123456789012');
 *
 *    $plaintext = str_repeat('a', 1024);
 *
 *    echo $twofish->decrypt($twofish->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Twofish
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
use phpseclib3\Exception\BadModeException;
/**
 * Pure-PHP implementation of Twofish.
 *
 * @package Twofish
 * @author  Jim Wigginton <terrafrost@php.net>
 * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
 * @access  public
 */
class Twofish extends BlockCipher
{
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'twofish';
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 800;
    /**
     * Q-Table
     *
     * @var array
     * @access private
     */
    private static $q0 = [0xa9, 0x67, 0xb3, 0xe8, 0x4, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0xd, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x1, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0xc, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0xb, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x3, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71, 0x81, 0x79, 0x9, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x8, 0x86, 0xe7, 0xa1, 0x1d, 0xaa, 0xed, 0x6, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0xa, 0xef, 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x5, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0xe, 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x2, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x7, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0xf, 0x0, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0];
    /**
     * Q-Table
     *
     * @var array
     * @access private
     */
    private static $q1 = [0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0xf, 0xf8, 0x1b, 0x87, 0xfa, 0x6, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x0, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0xe, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84, 0x7, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x3, 0x6f, 0x8, 0xbf, 0x40, 0xe7, 0x2b, 0xe2, 0x79, 0xc, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0xb, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x1, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x5, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0xa, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0xd, 0x52, 0xbb, 0x2, 0x2f, 0xa9, 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x4, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x9, 0xbe, 0x91];
    /**
     * M-Table
     *
     * @var array
     * @access private
     */
    private static $m0 = [0xbcbc3275, 0xecec21f3, 0x202043c6, 0xb3b3c9f4, 0xdada03db, 0x2028b7b, 0xe2e22bfb, 0x9e9efac8, 0xc9c9ec4a, 0xd4d409d3, 0x18186be6, 0x1e1e9f6b, 0x98980e45, 0xb2b2387d, 0xa6a6d2e8, 0x2626b74b, 0x3c3c57d6, 0x93938a32, 0x8282eed8, 0x525298fd, 0x7b7bd437, 0xbbbb3771, 0x5b5b97f1, 0x474783e1, 0x24243c30, 0x5151e20f, 0xbabac6f8, 0x4a4af31b, 0xbfbf4887, 0xd0d70fa, 0xb0b0b306, 0x7575de3f, 0xd2d2fd5e, 0x7d7d20ba, 0x666631ae, 0x3a3aa35b, 0x59591c8a, 0x0, 0xcdcd93bc, 0x1a1ae09d, 0xaeae2c6d, 0x7f7fabc1, 0x2b2bc7b1, 0xbebeb90e, 0xe0e0a080, 0x8a8a105d, 0x3b3b52d2, 0x6464bad5, 0xd8d888a0, 0xe7e7a584, 0x5f5fe807, 0x1b1b1114, 0x2c2cc2b5, 0xfcfcb490, 0x3131272c, 0x808065a3, 0x73732ab2, 0xc0c8173, 0x79795f4c, 0x6b6b4154, 0x4b4b0292, 0x53536974, 0x94948f36, 0x83831f51, 0x2a2a3638, 0xc4c49cb0, 0x2222c8bd, 0xd5d5f85a, 0xbdbdc3fc, 0x48487860, 0xffffce62, 0x4c4c0796, 0x4141776c, 0xc7c7e642, 0xebeb24f7, 0x1c1c1410, 0x5d5d637c, 0x36362228, 0x6767c027, 0xe9e9af8c, 0x4444f913, 0x1414ea95, 0xf5f5bb9c, 0xcfcf18c7, 0x3f3f2d24, 0xc0c0e346, 0x7272db3b, 0x54546c70, 0x29294cca, 0xf0f035e3, 0x808fe85, 0xc6c617cb, 0xf3f34f11, 0x8c8ce4d0, 0xa4a45993, 0xcaca96b8, 0x68683ba6, 0xb8b84d83, 0x38382820, 0xe5e52eff, 0xadad569f, 0xb0b8477, 0xc8c81dc3, 0x9999ffcc, 0x5858ed03, 0x19199a6f, 0xe0e0a08, 0x95957ebf, 0x70705040, 0xf7f730e7, 0x6e6ecf2b, 0x1f1f6ee2, 0xb5b53d79, 0x9090f0c, 0x616134aa, 0x57571682, 0x9f9f0b41, 0x9d9d803a, 0x111164ea, 0x2525cdb9, 0xafafdde4, 0x4545089a, 0xdfdf8da4, 0xa3a35c97, 0xeaead57e, 0x353558da, 0xededd07a, 0x4343fc17, 0xf8f8cb66, 0xfbfbb194, 0x3737d3a1, 0xfafa401d, 0xc2c2683d, 0xb4b4ccf0, 0x32325dde, 0x9c9c71b3, 0x5656e70b, 0xe3e3da72, 0x878760a7, 0x15151b1c, 0xf9f93aef, 0x6363bfd1, 0x3434a953, 0x9a9a853e, 0xb1b1428f, 0x7c7cd133, 0x88889b26, 0x3d3da65f, 0xa1a1d7ec, 0xe4e4df76, 0x8181942a, 0x91910149, 0xf0ffb81, 0xeeeeaa88, 0x161661ee, 0xd7d77321, 0x9797f5c4, 0xa5a5a81a, 0xfefe3feb, 0x6d6db5d9, 0x7878aec5, 0xc5c56d39, 0x1d1de599, 0x7676a4cd, 0x3e3edcad, 0xcbcb6731, 0xb6b6478b, 0xefef5b01, 0x12121e18, 0x6060c523, 0x6a6ab0dd, 0x4d4df61f, 0xcecee94e, 0xdede7c2d, 0x55559df9, 0x7e7e5a48, 0x2121b24f, 0x3037af2, 0xa0a02665, 0x5e5e198e, 0x5a5a6678, 0x65654b5c, 0x62624e58, 0xfdfd4519, 0x606f48d, 0x404086e5, 0xf2f2be98, 0x3333ac57, 0x17179067, 0x5058e7f, 0xe8e85e05, 0x4f4f7d64, 0x89896aaf, 0x10109563, 0x74742fb6, 0xa0a75fe, 0x5c5c92f5, 0x9b9b74b7, 0x2d2d333c, 0x3030d6a5, 0x2e2e49ce, 0x494989e9, 0x46467268, 0x77775544, 0xa8a8d8e0, 0x9696044d, 0x2828bd43, 0xa9a92969, 0xd9d97929, 0x8686912e, 0xd1d187ac, 0xf4f44a15, 0x8d8d1559, 0xd6d682a8, 0xb9b9bc0a, 0x42420d9e, 0xf6f6c16e, 0x2f2fb847, 0xdddd06df, 0x23233934, 0xcccc6235, 0xf1f1c46a, 0xc1c112cf, 0x8585ebdc, 0x8f8f9e22, 0x7171a1c9, 0x9090f0c0, 0xaaaa539b, 0x101f189, 0x8b8be1d4, 0x4e4e8ced, 0x8e8e6fab, 0xababa212, 0x6f6f3ea2, 0xe6e6540d, 0xdbdbf252, 0x92927bbb, 0xb7b7b602, 0x6969ca2f, 0x3939d9a9, 0xd3d30cd7, 0xa7a72361, 0xa2a2ad1e, 0xc3c399b4, 0x6c6c4450, 0x7070504, 0x4047ff6, 0x272746c2, 0xacaca716, 0xd0d07625, 0x50501386, 0xdcdcf756, 0x84841a55, 0xe1e15109, 0x7a7a25be, 0x1313ef91];
    /**
     * M-Table
     *
     * @var array
     * @access private
     */
    private static $m1 = [0xa9d93939, 0x67901717, 0xb3719c9c, 0xe8d2a6a6, 0x4050707, 0xfd985252, 0xa3658080, 0x76dfe4e4, 0x9a084545, 0x92024b4b, 0x80a0e0e0, 0x78665a5a, 0xe4ddafaf, 0xddb06a6a, 0xd1bf6363, 0x38362a2a, 0xd54e6e6, 0xc6432020, 0x3562cccc, 0x98bef2f2, 0x181e1212, 0xf724ebeb, 0xecd7a1a1, 0x6c774141, 0x43bd2828, 0x7532bcbc, 0x37d47b7b, 0x269b8888, 0xfa700d0d, 0x13f94444, 0x94b1fbfb, 0x485a7e7e, 0xf27a0303, 0xd0e48c8c, 0x8b47b6b6, 0x303c2424, 0x84a5e7e7, 0x54416b6b, 0xdf06dddd, 0x23c56060, 0x1945fdfd, 0x5ba33a3a, 0x3d68c2c2, 0x59158d8d, 0xf321ecec, 0xae316666, 0xa23e6f6f, 0x82165757, 0x63951010, 0x15befef, 0x834db8b8, 0x2e918686, 0xd9b56d6d, 0x511f8383, 0x9b53aaaa, 0x7c635d5d, 0xa63b6868, 0xeb3ffefe, 0xa5d63030, 0xbe257a7a, 0x16a7acac, 0xc0f0909, 0xe335f0f0, 0x6123a7a7, 0xc0f09090, 0x8cafe9e9, 0x3a809d9d, 0xf5925c5c, 0x73810c0c, 0x2c273131, 0x2576d0d0, 0xbe75656, 0xbb7b9292, 0x4ee9cece, 0x89f10101, 0x6b9f1e1e, 0x53a93434, 0x6ac4f1f1, 0xb499c3c3, 0xf1975b5b, 0xe1834747, 0xe66b1818, 0xbdc82222, 0x450e9898, 0xe26e1f1f, 0xf4c9b3b3, 0xb62f7474, 0x66cbf8f8, 0xccff9999, 0x95ea1414, 0x3ed5858, 0x56f7dcdc, 0xd4e18b8b, 0x1c1b1515, 0x1eada2a2, 0xd70cd3d3, 0xfb2be2e2, 0xc31dc8c8, 0x8e195e5e, 0xb5c22c2c, 0xe9894949, 0xcf12c1c1, 0xbf7e9595, 0xba207d7d, 0xea641111, 0x77840b0b, 0x396dc5c5, 0xaf6a8989, 0x33d17c7c, 0xc9a17171, 0x62ceffff, 0x7137bbbb, 0x81fb0f0f, 0x793db5b5, 0x951e1e1, 0xaddc3e3e, 0x242d3f3f, 0xcda47676, 0xf99d5555, 0xd8ee8282, 0xe5864040, 0xc5ae7878, 0xb9cd2525, 0x4d049696, 0x44557777, 0x80a0e0e, 0x86135050, 0xe730f7f7, 0xa1d33737, 0x1d40fafa, 0xaa346161, 0xed8c4e4e, 0x6b3b0b0, 0x706c5454, 0xb22a7373, 0xd2523b3b, 0x410b9f9f, 0x7b8b0202, 0xa088d8d8, 0x114ff3f3, 0x3167cbcb, 0xc2462727, 0x27c06767, 0x90b4fcfc, 0x20283838, 0xf67f0404, 0x60784848, 0xff2ee5e5, 0x96074c4c, 0x5c4b6565, 0xb1c72b2b, 0xab6f8e8e, 0x9e0d4242, 0x9cbbf5f5, 0x52f2dbdb, 0x1bf34a4a, 0x5fa63d3d, 0x9359a4a4, 0xabcb9b9, 0xef3af9f9, 0x91ef1313, 0x85fe0808, 0x49019191, 0xee611616, 0x2d7cdede, 0x4fb22121, 0x8f42b1b1, 0x3bdb7272, 0x47b82f2f, 0x8748bfbf, 0x6d2caeae, 0x46e3c0c0, 0xd6573c3c, 0x3e859a9a, 0x6929a9a9, 0x647d4f4f, 0x2a948181, 0xce492e2e, 0xcb17c6c6, 0x2fca6969, 0xfcc3bdbd, 0x975ca3a3, 0x55ee8e8, 0x7ad0eded, 0xac87d1d1, 0x7f8e0505, 0xd5ba6464, 0x1aa8a5a5, 0x4bb72626, 0xeb9bebe, 0xa7608787, 0x5af8d5d5, 0x28223636, 0x14111b1b, 0x3fde7575, 0x2979d9d9, 0x88aaeeee, 0x3c332d2d, 0x4c5f7979, 0x2b6b7b7, 0xb896caca, 0xda583535, 0xb09cc4c4, 0x17fc4343, 0x551a8484, 0x1ff64d4d, 0x8a1c5959, 0x7d38b2b2, 0x57ac3333, 0xc718cfcf, 0x8df40606, 0x74695353, 0xb7749b9b, 0xc4f59797, 0x9f56adad, 0x72dae3e3, 0x7ed5eaea, 0x154af4f4, 0x229e8f8f, 0x12a2abab, 0x584e6262, 0x7e85f5f, 0x99e51d1d, 0x34392323, 0x6ec1f6f6, 0x50446c6c, 0xde5d3232, 0x68724646, 0x6526a0a0, 0xbc93cdcd, 0xdb03dada, 0xf8c6baba, 0xc8fa9e9e, 0xa882d6d6, 0x2bcf6e6e, 0x40507070, 0xdceb8585, 0xfe750a0a, 0x328a9393, 0xa48ddfdf, 0xca4c2929, 0x10141c1c, 0x2173d7d7, 0xf0ccb4b4, 0xd309d4d4, 0x5d108a8a, 0xfe25151, 0x0, 0x6f9a1919, 0x9de01a1a, 0x368f9494, 0x42e6c7c7, 0x4aecc9c9, 0x5efdd2d2, 0xc1ab7f7f, 0xe0d8a8a8];
    /**
     * M-Table
     *
     * @var array
     * @access private
     */
    private static $m2 = [0xbc75bc32, 0xecf3ec21, 0x20c62043, 0xb3f4b3c9, 0xdadbda03, 0x27b028b, 0xe2fbe22b, 0x9ec89efa, 0xc94ac9ec, 0xd4d3d409, 0x18e6186b, 0x1e6b1e9f, 0x9845980e, 0xb27db238, 0xa6e8a6d2, 0x264b26b7, 0x3cd63c57, 0x9332938a, 0x82d882ee, 0x52fd5298, 0x7b377bd4, 0xbb71bb37, 0x5bf15b97, 0x47e14783, 0x2430243c, 0x510f51e2, 0xbaf8bac6, 0x4a1b4af3, 0xbf87bf48, 0xdfa0d70, 0xb006b0b3, 0x753f75de, 0xd25ed2fd, 0x7dba7d20, 0x66ae6631, 0x3a5b3aa3, 0x598a591c, 0x0, 0xcdbccd93, 0x1a9d1ae0, 0xae6dae2c, 0x7fc17fab, 0x2bb12bc7, 0xbe0ebeb9, 0xe080e0a0, 0x8a5d8a10, 0x3bd23b52, 0x64d564ba, 0xd8a0d888, 0xe784e7a5, 0x5f075fe8, 0x1b141b11, 0x2cb52cc2, 0xfc90fcb4, 0x312c3127, 0x80a38065, 0x73b2732a, 0xc730c81, 0x794c795f, 0x6b546b41, 0x4b924b02, 0x53745369, 0x9436948f, 0x8351831f, 0x2a382a36, 0xc4b0c49c, 0x22bd22c8, 0xd55ad5f8, 0xbdfcbdc3, 0x48604878, 0xff62ffce, 0x4c964c07, 0x416c4177, 0xc742c7e6, 0xebf7eb24, 0x1c101c14, 0x5d7c5d63, 0x36283622, 0x672767c0, 0xe98ce9af, 0x441344f9, 0x149514ea, 0xf59cf5bb, 0xcfc7cf18, 0x3f243f2d, 0xc046c0e3, 0x723b72db, 0x5470546c, 0x29ca294c, 0xf0e3f035, 0x88508fe, 0xc6cbc617, 0xf311f34f, 0x8cd08ce4, 0xa493a459, 0xcab8ca96, 0x68a6683b, 0xb883b84d, 0x38203828, 0xe5ffe52e, 0xad9fad56, 0xb770b84, 0xc8c3c81d, 0x99cc99ff, 0x580358ed, 0x196f199a, 0xe080e0a, 0x95bf957e, 0x70407050, 0xf7e7f730, 0x6e2b6ecf, 0x1fe21f6e, 0xb579b53d, 0x90c090f, 0x61aa6134, 0x57825716, 0x9f419f0b, 0x9d3a9d80, 0x11ea1164, 0x25b925cd, 0xafe4afdd, 0x459a4508, 0xdfa4df8d, 0xa397a35c, 0xea7eead5, 0x35da3558, 0xed7aedd0, 0x431743fc, 0xf866f8cb, 0xfb94fbb1, 0x37a137d3, 0xfa1dfa40, 0xc23dc268, 0xb4f0b4cc, 0x32de325d, 0x9cb39c71, 0x560b56e7, 0xe372e3da, 0x87a78760, 0x151c151b, 0xf9eff93a, 0x63d163bf, 0x345334a9, 0x9a3e9a85, 0xb18fb142, 0x7c337cd1, 0x8826889b, 0x3d5f3da6, 0xa1eca1d7, 0xe476e4df, 0x812a8194, 0x91499101, 0xf810ffb, 0xee88eeaa, 0x16ee1661, 0xd721d773, 0x97c497f5, 0xa51aa5a8, 0xfeebfe3f, 0x6dd96db5, 0x78c578ae, 0xc539c56d, 0x1d991de5, 0x76cd76a4, 0x3ead3edc, 0xcb31cb67, 0xb68bb647, 0xef01ef5b, 0x1218121e, 0x602360c5, 0x6add6ab0, 0x4d1f4df6, 0xce4ecee9, 0xde2dde7c, 0x55f9559d, 0x7e487e5a, 0x214f21b2, 0x3f2037a, 0xa065a026, 0x5e8e5e19, 0x5a785a66, 0x655c654b, 0x6258624e, 0xfd19fd45, 0x68d06f4, 0x40e54086, 0xf298f2be, 0x335733ac, 0x17671790, 0x57f058e, 0xe805e85e, 0x4f644f7d, 0x89af896a, 0x10631095, 0x74b6742f, 0xafe0a75, 0x5cf55c92, 0x9bb79b74, 0x2d3c2d33, 0x30a530d6, 0x2ece2e49, 0x49e94989, 0x46684672, 0x77447755, 0xa8e0a8d8, 0x964d9604, 0x284328bd, 0xa969a929, 0xd929d979, 0x862e8691, 0xd1acd187, 0xf415f44a, 0x8d598d15, 0xd6a8d682, 0xb90ab9bc, 0x429e420d, 0xf66ef6c1, 0x2f472fb8, 0xdddfdd06, 0x23342339, 0xcc35cc62, 0xf16af1c4, 0xc1cfc112, 0x85dc85eb, 0x8f228f9e, 0x71c971a1, 0x90c090f0, 0xaa9baa53, 0x18901f1, 0x8bd48be1, 0x4eed4e8c, 0x8eab8e6f, 0xab12aba2, 0x6fa26f3e, 0xe60de654, 0xdb52dbf2, 0x92bb927b, 0xb702b7b6, 0x692f69ca, 0x39a939d9, 0xd3d7d30c, 0xa761a723, 0xa21ea2ad, 0xc3b4c399, 0x6c506c44, 0x7040705, 0x4f6047f, 0x27c22746, 0xac16aca7, 0xd025d076, 0x50865013, 0xdc56dcf7, 0x8455841a, 0xe109e151, 0x7abe7a25, 0x139113ef];
    /**
     * M-Table
     *
     * @var array
     * @access private
     */
    private static $m3 = [0xd939a9d9, 0x90176790, 0x719cb371, 0xd2a6e8d2, 0x5070405, 0x9852fd98, 0x6580a365, 0xdfe476df, 0x8459a08, 0x24b9202, 0xa0e080a0, 0x665a7866, 0xddafe4dd, 0xb06addb0, 0xbf63d1bf, 0x362a3836, 0x54e60d54, 0x4320c643, 0x62cc3562, 0xbef298be, 0x1e12181e, 0x24ebf724, 0xd7a1ecd7, 0x77416c77, 0xbd2843bd, 0x32bc7532, 0xd47b37d4, 0x9b88269b, 0x700dfa70, 0xf94413f9, 0xb1fb94b1, 0x5a7e485a, 0x7a03f27a, 0xe48cd0e4, 0x47b68b47, 0x3c24303c, 0xa5e784a5, 0x416b5441, 0x6dddf06, 0xc56023c5, 0x45fd1945, 0xa33a5ba3, 0x68c23d68, 0x158d5915, 0x21ecf321, 0x3166ae31, 0x3e6fa23e, 0x16578216, 0x95106395, 0x5bef015b, 0x4db8834d, 0x91862e91, 0xb56dd9b5, 0x1f83511f, 0x53aa9b53, 0x635d7c63, 0x3b68a63b, 0x3ffeeb3f, 0xd630a5d6, 0x257abe25, 0xa7ac16a7, 0xf090c0f, 0x35f0e335, 0x23a76123, 0xf090c0f0, 0xafe98caf, 0x809d3a80, 0x925cf592, 0x810c7381, 0x27312c27, 0x76d02576, 0xe7560be7, 0x7b92bb7b, 0xe9ce4ee9, 0xf10189f1, 0x9f1e6b9f, 0xa93453a9, 0xc4f16ac4, 0x99c3b499, 0x975bf197, 0x8347e183, 0x6b18e66b, 0xc822bdc8, 0xe98450e, 0x6e1fe26e, 0xc9b3f4c9, 0x2f74b62f, 0xcbf866cb, 0xff99ccff, 0xea1495ea, 0xed5803ed, 0xf7dc56f7, 0xe18bd4e1, 0x1b151c1b, 0xada21ead, 0xcd3d70c, 0x2be2fb2b, 0x1dc8c31d, 0x195e8e19, 0xc22cb5c2, 0x8949e989, 0x12c1cf12, 0x7e95bf7e, 0x207dba20, 0x6411ea64, 0x840b7784, 0x6dc5396d, 0x6a89af6a, 0xd17c33d1, 0xa171c9a1, 0xceff62ce, 0x37bb7137, 0xfb0f81fb, 0x3db5793d, 0x51e10951, 0xdc3eaddc, 0x2d3f242d, 0xa476cda4, 0x9d55f99d, 0xee82d8ee, 0x8640e586, 0xae78c5ae, 0xcd25b9cd, 0x4964d04, 0x55774455, 0xa0e080a, 0x13508613, 0x30f7e730, 0xd337a1d3, 0x40fa1d40, 0x3461aa34, 0x8c4eed8c, 0xb3b006b3, 0x6c54706c, 0x2a73b22a, 0x523bd252, 0xb9f410b, 0x8b027b8b, 0x88d8a088, 0x4ff3114f, 0x67cb3167, 0x4627c246, 0xc06727c0, 0xb4fc90b4, 0x28382028, 0x7f04f67f, 0x78486078, 0x2ee5ff2e, 0x74c9607, 0x4b655c4b, 0xc72bb1c7, 0x6f8eab6f, 0xd429e0d, 0xbbf59cbb, 0xf2db52f2, 0xf34a1bf3, 0xa63d5fa6, 0x59a49359, 0xbcb90abc, 0x3af9ef3a, 0xef1391ef, 0xfe0885fe, 0x1914901, 0x6116ee61, 0x7cde2d7c, 0xb2214fb2, 0x42b18f42, 0xdb723bdb, 0xb82f47b8, 0x48bf8748, 0x2cae6d2c, 0xe3c046e3, 0x573cd657, 0x859a3e85, 0x29a96929, 0x7d4f647d, 0x94812a94, 0x492ece49, 0x17c6cb17, 0xca692fca, 0xc3bdfcc3, 0x5ca3975c, 0x5ee8055e, 0xd0ed7ad0, 0x87d1ac87, 0x8e057f8e, 0xba64d5ba, 0xa8a51aa8, 0xb7264bb7, 0xb9be0eb9, 0x6087a760, 0xf8d55af8, 0x22362822, 0x111b1411, 0xde753fde, 0x79d92979, 0xaaee88aa, 0x332d3c33, 0x5f794c5f, 0xb6b702b6, 0x96cab896, 0x5835da58, 0x9cc4b09c, 0xfc4317fc, 0x1a84551a, 0xf64d1ff6, 0x1c598a1c, 0x38b27d38, 0xac3357ac, 0x18cfc718, 0xf4068df4, 0x69537469, 0x749bb774, 0xf597c4f5, 0x56ad9f56, 0xdae372da, 0xd5ea7ed5, 0x4af4154a, 0x9e8f229e, 0xa2ab12a2, 0x4e62584e, 0xe85f07e8, 0xe51d99e5, 0x39233439, 0xc1f66ec1, 0x446c5044, 0x5d32de5d, 0x72466872, 0x26a06526, 0x93cdbc93, 0x3dadb03, 0xc6baf8c6, 0xfa9ec8fa, 0x82d6a882, 0xcf6e2bcf, 0x50704050, 0xeb85dceb, 0x750afe75, 0x8a93328a, 0x8ddfa48d, 0x4c29ca4c, 0x141c1014, 0x73d72173, 0xccb4f0cc, 0x9d4d309, 0x108a5d10, 0xe2510fe2, 0x0, 0x9a196f9a, 0xe01a9de0, 0x8f94368f, 0xe6c742e6, 0xecc94aec, 0xfdd25efd, 0xab7fc1ab, 0xd8a8e0d8];
    /**
     * The Key Schedule Array
     *
     * @var array
     * @access private
     */
    private $K = [];
    /**
     * The Key depended S-Table 0
     *
     * @var array
     * @access private
     */
    private $S0 = [];
    /**
     * The Key depended S-Table 1
     *
     * @var array
     * @access private
     */
    private $S1 = [];
    /**
     * The Key depended S-Table 2
     *
     * @var array
     * @access private
     */
    private $S2 = [];
    /**
     * The Key depended S-Table 3
     *
     * @var array
     * @access private
     */
    private $S3 = [];
    /**
     * Holds the last used key
     *
     * @var array
     * @access private
     */
    private $kl;
    /**
     * The Key Length (in bytes)
     *
     * @see Crypt_Twofish::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 16;
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws BadModeException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new BadModeException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
     * Sets the key length.
     *
     * Valid key lengths are 128, 192 or 256 bits
     *
     * @access public
     * @param int $length
     */
    public function setKeyLength($length)
    {
        switch ($length) {
            case 128:
            case 192:
            case 256:
                break;
            default:
                throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
        }
        parent::setKeyLength($length);
    }
    /**
     * Sets the key.
     *
     * Rijndael supports five different key lengths
     *
     * @see setKeyLength()
     * @access public
     * @param string $key
     * @throws \LengthException if the key length isn't supported
     */
    public function setKey($key)
    {
        switch (strlen($key)) {
            case 16:
            case 24:
            case 32:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
        }
        parent::setKey($key);
    }
    /**
     * Setup the key (expansion)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
     * @access private
     */
    protected function setupKey()
    {
        if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
            // already expanded
            return;
        }
        $this->kl = ['key' => $this->key];
        /* Key expanding and generating the key-depended s-boxes */
        $le_longs = unpack('V*', $this->key);
        $key = unpack('C*', $this->key);
        $m0 = self::$m0;
        $m1 = self::$m1;
        $m2 = self::$m2;
        $m3 = self::$m3;
        $q0 = self::$q0;
        $q1 = self::$q1;
        $K = $S0 = $S1 = $S2 = $S3 = [];
        switch (strlen($this->key)) {
            case 16:
                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[1], $le_longs[2]);
                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[3], $le_longs[4]);
                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
                    $A = $m0[$q0[$q0[$i] ^ $key[9]] ^ $key[1]] ^ $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
                    $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
                    $B = $B << 8 | $B >> 24 & 0xff;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A << 9 | $A >> 23 & 0x1ff;
                }
                for ($i = 0; $i < 256; ++$i) {
                    $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
                    $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
                    $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
                    $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
                }
                break;
            case 24:
                list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[1], $le_longs[2]);
                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[3], $le_longs[4]);
                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[5], $le_longs[6]);
                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
                    $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[9]] ^ $key[1]] ^ $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
                    $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
                    $B = $B << 8 | $B >> 24 & 0xff;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A << 9 | $A >> 23 & 0x1ff;
                }
                for ($i = 0; $i < 256; ++$i) {
                    $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
                    $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
                    $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
                    $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
                }
                break;
            default:
                // 32
                list($sf, $se, $sd, $sc) = $this->mdsrem($le_longs[1], $le_longs[2]);
                list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[3], $le_longs[4]);
                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[5], $le_longs[6]);
                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[7], $le_longs[8]);
                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
                    $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[9]] ^ $key[1]] ^ $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
                    $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
                    $B = $B << 8 | $B >> 24 & 0xff;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A << 9 | $A >> 23 & 0x1ff;
                }
                for ($i = 0; $i < 256; ++$i) {
                    $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
                    $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
                    $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
                    $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
                }
        }
        $this->K = $K;
        $this->S0 = $S0;
        $this->S1 = $S1;
        $this->S2 = $S2;
        $this->S3 = $S3;
    }
    /**
     * _mdsrem function using by the twofish cipher algorithm
     *
     * @access private
     * @param string $A
     * @param string $B
     * @return array
     */
    private function mdsrem($A, $B)
    {
        // No gain by unrolling this loop.
        for ($i = 0; $i < 8; ++$i) {
            // Get most significant coefficient.
            $t = 0xff & $B >> 24;
            // Shift the others up.
            $B = $B << 8 | 0xff & $A >> 24;
            $A <<= 8;
            $u = $t << 1;
            // Subtract the modular polynomial on overflow.
            if ($t & 0x80) {
                $u ^= 0x14d;
            }
            // Remove t * (a * x^2 + 1).
            $B ^= $t ^ $u << 16;
            // Form u = a*t + t/a = t*(a + 1/a).
            $u ^= 0x7fffffff & $t >> 1;
            // Add the modular polynomial on underflow.
            if ($t & 0x1) {
                $u ^= 0xa6;
            }
            // Remove t * (a + 1/a) * (x^3 + x).
            $B ^= $u << 24 | $u << 8;
        }
        return [0xff & $B >> 24, 0xff & $B >> 16, 0xff & $B >> 8, 0xff & $B];
    }
    /**
     * Encrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        $S0 = $this->S0;
        $S1 = $this->S1;
        $S2 = $this->S2;
        $S3 = $this->S3;
        $K = $this->K;
        $in = unpack("V4", $in);
        $R0 = $K[0] ^ $in[1];
        $R1 = $K[1] ^ $in[2];
        $R2 = $K[2] ^ $in[3];
        $R3 = $K[3] ^ $in[4];
        $ki = 7;
        while ($ki < 39) {
            $t0 = $S0[$R0 & 0xff] ^ $S1[$R0 >> 8 & 0xff] ^ $S2[$R0 >> 16 & 0xff] ^ $S3[$R0 >> 24 & 0xff];
            $t1 = $S0[$R1 >> 24 & 0xff] ^ $S1[$R1 & 0xff] ^ $S2[$R1 >> 8 & 0xff] ^ $S3[$R1 >> 16 & 0xff];
            $R2 ^= self::safe_intval($t0 + $t1 + $K[++$ki]);
            $R2 = $R2 >> 1 & 0x7fffffff | $R2 << 31;
            $R3 = ($R3 >> 31 & 1 | $R3 << 1) ^ self::safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
            $t0 = $S0[$R2 & 0xff] ^ $S1[$R2 >> 8 & 0xff] ^ $S2[$R2 >> 16 & 0xff] ^ $S3[$R2 >> 24 & 0xff];
            $t1 = $S0[$R3 >> 24 & 0xff] ^ $S1[$R3 & 0xff] ^ $S2[$R3 >> 8 & 0xff] ^ $S3[$R3 >> 16 & 0xff];
            $R0 ^= self::safe_intval($t0 + $t1 + $K[++$ki]);
            $R0 = $R0 >> 1 & 0x7fffffff | $R0 << 31;
            $R1 = ($R1 >> 31 & 1 | $R1 << 1) ^ self::safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
        }
        // @codingStandardsIgnoreStart
        return pack("V4", $K[4] ^ $R2, $K[5] ^ $R3, $K[6] ^ $R0, $K[7] ^ $R1);
        // @codingStandardsIgnoreEnd
    }
    /**
     * Decrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        $S0 = $this->S0;
        $S1 = $this->S1;
        $S2 = $this->S2;
        $S3 = $this->S3;
        $K = $this->K;
        $in = unpack("V4", $in);
        $R0 = $K[4] ^ $in[1];
        $R1 = $K[5] ^ $in[2];
        $R2 = $K[6] ^ $in[3];
        $R3 = $K[7] ^ $in[4];
        $ki = 40;
        while ($ki > 8) {
            $t0 = $S0[$R0 & 0xff] ^ $S1[$R0 >> 8 & 0xff] ^ $S2[$R0 >> 16 & 0xff] ^ $S3[$R0 >> 24 & 0xff];
            $t1 = $S0[$R1 >> 24 & 0xff] ^ $S1[$R1 & 0xff] ^ $S2[$R1 >> 8 & 0xff] ^ $S3[$R1 >> 16 & 0xff];
            $R3 ^= self::safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
            $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
            $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ self::safe_intval($t0 + $t1 + $K[--$ki]);
            $t0 = $S0[$R2 & 0xff] ^ $S1[$R2 >> 8 & 0xff] ^ $S2[$R2 >> 16 & 0xff] ^ $S3[$R2 >> 24 & 0xff];
            $t1 = $S0[$R3 >> 24 & 0xff] ^ $S1[$R3 & 0xff] ^ $S2[$R3 >> 8 & 0xff] ^ $S3[$R3 >> 16 & 0xff];
            $R1 ^= self::safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
            $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
            $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ self::safe_intval($t0 + $t1 + $K[--$ki]);
        }
        // @codingStandardsIgnoreStart
        return pack("V4", $K[0] ^ $R2, $K[1] ^ $R3, $K[2] ^ $R0, $K[3] ^ $R1);
        // @codingStandardsIgnoreEnd
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        $K = $this->K;
        $init_crypt = '
            static $S0, $S1, $S2, $S3;
            if (!$S0) {
                for ($i = 0; $i < 256; ++$i) {
                    $S0[] = (int)$this->S0[$i];
                    $S1[] = (int)$this->S1[$i];
                    $S2[] = (int)$this->S2[$i];
                    $S3[] = (int)$this->S3[$i];
                }
            }
        ';
        $safeint = self::safe_intval_inline();
        // Generating encrypt code:
        $encrypt_block = '
            $in = unpack("V4", $in);
            $R0 = ' . $K[0] . ' ^ $in[1];
            $R1 = ' . $K[1] . ' ^ $in[2];
            $R2 = ' . $K[2] . ' ^ $in[3];
            $R3 = ' . $K[3] . ' ^ $in[4];
        ';
        for ($ki = 7, $i = 0; $i < 8; ++$i) {
            $encrypt_block .= '
                $t0 = $S0[ $R0        & 0xff] ^
                      $S1[($R0 >>  8) & 0xff] ^
                      $S2[($R0 >> 16) & 0xff] ^
                      $S3[($R0 >> 24) & 0xff];
                $t1 = $S0[($R1 >> 24) & 0xff] ^
                      $S1[ $R1        & 0xff] ^
                      $S2[($R1 >>  8) & 0xff] ^
                      $S3[($R1 >> 16) & 0xff];
                    $R2^= ' . sprintf($safeint, '$t0 + $t1 + ' . $K[++$ki]) . ';
                $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
                $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';

                $t0 = $S0[ $R2        & 0xff] ^
                      $S1[($R2 >>  8) & 0xff] ^
                      $S2[($R2 >> 16) & 0xff] ^
                      $S3[($R2 >> 24) & 0xff];
                $t1 = $S0[($R3 >> 24) & 0xff] ^
                      $S1[ $R3        & 0xff] ^
                      $S2[($R3 >>  8) & 0xff] ^
                      $S3[($R3 >> 16) & 0xff];
                $R0^= ' . sprintf($safeint, '($t0 + $t1 + ' . $K[++$ki] . ')') . ';
                $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
                $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
            ';
        }
        $encrypt_block .= '
            $in = pack("V4", ' . $K[4] . ' ^ $R2,
                             ' . $K[5] . ' ^ $R3,
                             ' . $K[6] . ' ^ $R0,
                             ' . $K[7] . ' ^ $R1);
        ';
        // Generating decrypt code:
        $decrypt_block = '
            $in = unpack("V4", $in);
            $R0 = ' . $K[4] . ' ^ $in[1];
            $R1 = ' . $K[5] . ' ^ $in[2];
            $R2 = ' . $K[6] . ' ^ $in[3];
            $R3 = ' . $K[7] . ' ^ $in[4];
        ';
        for ($ki = 40, $i = 0; $i < 8; ++$i) {
            $decrypt_block .= '
                $t0 = $S0[$R0       & 0xff] ^
                      $S1[$R0 >>  8 & 0xff] ^
                      $S2[$R0 >> 16 & 0xff] ^
                      $S3[$R0 >> 24 & 0xff];
                $t1 = $S0[$R1 >> 24 & 0xff] ^
                      $S1[$R1       & 0xff] ^
                      $S2[$R1 >>  8 & 0xff] ^
                      $S3[$R1 >> 16 & 0xff];
                $R3^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
                $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
                $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + ' . $K[--$ki] . ')') . ';

                $t0 = $S0[$R2       & 0xff] ^
                      $S1[$R2 >>  8 & 0xff] ^
                      $S2[$R2 >> 16 & 0xff] ^
                      $S3[$R2 >> 24 & 0xff];
                $t1 = $S0[$R3 >> 24 & 0xff] ^
                      $S1[$R3       & 0xff] ^
                      $S2[$R3 >>  8 & 0xff] ^
                      $S3[$R3 >> 16 & 0xff];
                $R1^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
                $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
                $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + ' . $K[--$ki] . ')') . ';
            ';
        }
        $decrypt_block .= '
            $in = pack("V4", ' . $K[0] . ' ^ $R2,
                             ' . $K[1] . ' ^ $R3,
                             ' . $K[2] . ' ^ $R0,
                             ' . $K[3] . ' ^ $R1);
        ';
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => $init_crypt, 'init_encrypt' => '', 'init_decrypt' => '', 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block]);
    }
}<?php

/**
 * Pure-PHP implementation of DES.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
 *  - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
 *  - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $des = new \phpseclib3\Crypt\DES('ctr');
 *
 *    $des->setKey('abcdefgh');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $des->decrypt($des->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   DES
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
use phpseclib3\Exception\BadModeException;
/**
 * Pure-PHP implementation of DES.
 *
 * @package DES
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class DES extends BlockCipher
{
    /**
     * Contains $keys[self::ENCRYPT]
     *
     * @access private
     * @see \phpseclib3\Crypt\DES::setupKey()
     * @see \phpseclib3\Crypt\DES::processBlock()
     */
    const ENCRYPT = 0;
    /**
     * Contains $keys[self::DECRYPT]
     *
     * @access private
     * @see \phpseclib3\Crypt\DES::setupKey()
     * @see \phpseclib3\Crypt\DES::processBlock()
     */
    const DECRYPT = 1;
    /**
     * Block Length of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
     * @var int
     * @access private
     */
    protected $block_size = 8;
    /**
     * Key Length (in bytes)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 8;
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'des';
    /**
     * The OpenSSL names of the cipher / modes
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::openssl_mode_names
     * @var array
     * @access private
     */
    protected $openssl_mode_names = [self::MODE_ECB => 'des-ecb', self::MODE_CBC => 'des-cbc', self::MODE_CFB => 'des-cfb', self::MODE_OFB => 'des-ofb'];
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 500;
    /**
     * Switch for DES/3DES encryption
     *
     * Used only if $engine == self::ENGINE_INTERNAL
     *
     * @see self::setupKey()
     * @see self::processBlock()
     * @var int
     * @access private
     */
    protected $des_rounds = 1;
    /**
     * max possible size of $key
     *
     * @see self::setKey()
     * @var string
     * @access private
     */
    protected $key_length_max = 8;
    /**
     * The Key Schedule
     *
     * @see self::setupKey()
     * @var array
     * @access private
     */
    private $keys;
    /**
     * Shuffle table.
     *
     * For each byte value index, the entry holds an 8-byte string
     * with each byte containing all bits in the same state as the
     * corresponding bit in the index value.
     *
     * @see self::processBlock()
     * @see self::setupKey()
     * @var array
     * @access private
     */
    protected static $shuffle = ["\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xff", "\x00\x00\x00\x00\x00\x00\xff\x00", "\x00\x00\x00\x00\x00\x00\xff\xff", "\x00\x00\x00\x00\x00\xff\x00\x00", "\x00\x00\x00\x00\x00\xff\x00\xff", "\x00\x00\x00\x00\x00\xff\xff\x00", "\x00\x00\x00\x00\x00\xff\xff\xff", "\x00\x00\x00\x00\xff\x00\x00\x00", "\x00\x00\x00\x00\xff\x00\x00\xff", "\x00\x00\x00\x00\xff\x00\xff\x00", "\x00\x00\x00\x00\xff\x00\xff\xff", "\x00\x00\x00\x00\xff\xff\x00\x00", "\x00\x00\x00\x00\xff\xff\x00\xff", "\x00\x00\x00\x00\xff\xff\xff\x00", "\x00\x00\x00\x00\xff\xff\xff\xff", "\x00\x00\x00\xff\x00\x00\x00\x00", "\x00\x00\x00\xff\x00\x00\x00\xff", "\x00\x00\x00\xff\x00\x00\xff\x00", "\x00\x00\x00\xff\x00\x00\xff\xff", "\x00\x00\x00\xff\x00\xff\x00\x00", "\x00\x00\x00\xff\x00\xff\x00\xff", "\x00\x00\x00\xff\x00\xff\xff\x00", "\x00\x00\x00\xff\x00\xff\xff\xff", "\x00\x00\x00\xff\xff\x00\x00\x00", "\x00\x00\x00\xff\xff\x00\x00\xff", "\x00\x00\x00\xff\xff\x00\xff\x00", "\x00\x00\x00\xff\xff\x00\xff\xff", "\x00\x00\x00\xff\xff\xff\x00\x00", "\x00\x00\x00\xff\xff\xff\x00\xff", "\x00\x00\x00\xff\xff\xff\xff\x00", "\x00\x00\x00\xff\xff\xff\xff\xff", "\x00\x00\xff\x00\x00\x00\x00\x00", "\x00\x00\xff\x00\x00\x00\x00\xff", "\x00\x00\xff\x00\x00\x00\xff\x00", "\x00\x00\xff\x00\x00\x00\xff\xff", "\x00\x00\xff\x00\x00\xff\x00\x00", "\x00\x00\xff\x00\x00\xff\x00\xff", "\x00\x00\xff\x00\x00\xff\xff\x00", "\x00\x00\xff\x00\x00\xff\xff\xff", "\x00\x00\xff\x00\xff\x00\x00\x00", "\x00\x00\xff\x00\xff\x00\x00\xff", "\x00\x00\xff\x00\xff\x00\xff\x00", "\x00\x00\xff\x00\xff\x00\xff\xff", "\x00\x00\xff\x00\xff\xff\x00\x00", "\x00\x00\xff\x00\xff\xff\x00\xff", "\x00\x00\xff\x00\xff\xff\xff\x00", "\x00\x00\xff\x00\xff\xff\xff\xff", "\x00\x00\xff\xff\x00\x00\x00\x00", "\x00\x00\xff\xff\x00\x00\x00\xff", "\x00\x00\xff\xff\x00\x00\xff\x00", "\x00\x00\xff\xff\x00\x00\xff\xff", "\x00\x00\xff\xff\x00\xff\x00\x00", "\x00\x00\xff\xff\x00\xff\x00\xff", "\x00\x00\xff\xff\x00\xff\xff\x00", "\x00\x00\xff\xff\x00\xff\xff\xff", "\x00\x00\xff\xff\xff\x00\x00\x00", "\x00\x00\xff\xff\xff\x00\x00\xff", "\x00\x00\xff\xff\xff\x00\xff\x00", "\x00\x00\xff\xff\xff\x00\xff\xff", "\x00\x00\xff\xff\xff\xff\x00\x00", "\x00\x00\xff\xff\xff\xff\x00\xff", "\x00\x00\xff\xff\xff\xff\xff\x00", "\x00\x00\xff\xff\xff\xff\xff\xff", "\x00\xff\x00\x00\x00\x00\x00\x00", "\x00\xff\x00\x00\x00\x00\x00\xff", "\x00\xff\x00\x00\x00\x00\xff\x00", "\x00\xff\x00\x00\x00\x00\xff\xff", "\x00\xff\x00\x00\x00\xff\x00\x00", "\x00\xff\x00\x00\x00\xff\x00\xff", "\x00\xff\x00\x00\x00\xff\xff\x00", "\x00\xff\x00\x00\x00\xff\xff\xff", "\x00\xff\x00\x00\xff\x00\x00\x00", "\x00\xff\x00\x00\xff\x00\x00\xff", "\x00\xff\x00\x00\xff\x00\xff\x00", "\x00\xff\x00\x00\xff\x00\xff\xff", "\x00\xff\x00\x00\xff\xff\x00\x00", "\x00\xff\x00\x00\xff\xff\x00\xff", "\x00\xff\x00\x00\xff\xff\xff\x00", "\x00\xff\x00\x00\xff\xff\xff\xff", "\x00\xff\x00\xff\x00\x00\x00\x00", "\x00\xff\x00\xff\x00\x00\x00\xff", "\x00\xff\x00\xff\x00\x00\xff\x00", "\x00\xff\x00\xff\x00\x00\xff\xff", "\x00\xff\x00\xff\x00\xff\x00\x00", "\x00\xff\x00\xff\x00\xff\x00\xff", "\x00\xff\x00\xff\x00\xff\xff\x00", "\x00\xff\x00\xff\x00\xff\xff\xff", "\x00\xff\x00\xff\xff\x00\x00\x00", "\x00\xff\x00\xff\xff\x00\x00\xff", "\x00\xff\x00\xff\xff\x00\xff\x00", "\x00\xff\x00\xff\xff\x00\xff\xff", "\x00\xff\x00\xff\xff\xff\x00\x00", "\x00\xff\x00\xff\xff\xff\x00\xff", "\x00\xff\x00\xff\xff\xff\xff\x00", "\x00\xff\x00\xff\xff\xff\xff\xff", "\x00\xff\xff\x00\x00\x00\x00\x00", "\x00\xff\xff\x00\x00\x00\x00\xff", "\x00\xff\xff\x00\x00\x00\xff\x00", "\x00\xff\xff\x00\x00\x00\xff\xff", "\x00\xff\xff\x00\x00\xff\x00\x00", "\x00\xff\xff\x00\x00\xff\x00\xff", "\x00\xff\xff\x00\x00\xff\xff\x00", "\x00\xff\xff\x00\x00\xff\xff\xff", "\x00\xff\xff\x00\xff\x00\x00\x00", "\x00\xff\xff\x00\xff\x00\x00\xff", "\x00\xff\xff\x00\xff\x00\xff\x00", "\x00\xff\xff\x00\xff\x00\xff\xff", "\x00\xff\xff\x00\xff\xff\x00\x00", "\x00\xff\xff\x00\xff\xff\x00\xff", "\x00\xff\xff\x00\xff\xff\xff\x00", "\x00\xff\xff\x00\xff\xff\xff\xff", "\x00\xff\xff\xff\x00\x00\x00\x00", "\x00\xff\xff\xff\x00\x00\x00\xff", "\x00\xff\xff\xff\x00\x00\xff\x00", "\x00\xff\xff\xff\x00\x00\xff\xff", "\x00\xff\xff\xff\x00\xff\x00\x00", "\x00\xff\xff\xff\x00\xff\x00\xff", "\x00\xff\xff\xff\x00\xff\xff\x00", "\x00\xff\xff\xff\x00\xff\xff\xff", "\x00\xff\xff\xff\xff\x00\x00\x00", "\x00\xff\xff\xff\xff\x00\x00\xff", "\x00\xff\xff\xff\xff\x00\xff\x00", "\x00\xff\xff\xff\xff\x00\xff\xff", "\x00\xff\xff\xff\xff\xff\x00\x00", "\x00\xff\xff\xff\xff\xff\x00\xff", "\x00\xff\xff\xff\xff\xff\xff\x00", "\x00\xff\xff\xff\xff\xff\xff\xff", "\xff\x00\x00\x00\x00\x00\x00\x00", "\xff\x00\x00\x00\x00\x00\x00\xff", "\xff\x00\x00\x00\x00\x00\xff\x00", "\xff\x00\x00\x00\x00\x00\xff\xff", "\xff\x00\x00\x00\x00\xff\x00\x00", "\xff\x00\x00\x00\x00\xff\x00\xff", "\xff\x00\x00\x00\x00\xff\xff\x00", "\xff\x00\x00\x00\x00\xff\xff\xff", "\xff\x00\x00\x00\xff\x00\x00\x00", "\xff\x00\x00\x00\xff\x00\x00\xff", "\xff\x00\x00\x00\xff\x00\xff\x00", "\xff\x00\x00\x00\xff\x00\xff\xff", "\xff\x00\x00\x00\xff\xff\x00\x00", "\xff\x00\x00\x00\xff\xff\x00\xff", "\xff\x00\x00\x00\xff\xff\xff\x00", "\xff\x00\x00\x00\xff\xff\xff\xff", "\xff\x00\x00\xff\x00\x00\x00\x00", "\xff\x00\x00\xff\x00\x00\x00\xff", "\xff\x00\x00\xff\x00\x00\xff\x00", "\xff\x00\x00\xff\x00\x00\xff\xff", "\xff\x00\x00\xff\x00\xff\x00\x00", "\xff\x00\x00\xff\x00\xff\x00\xff", "\xff\x00\x00\xff\x00\xff\xff\x00", "\xff\x00\x00\xff\x00\xff\xff\xff", "\xff\x00\x00\xff\xff\x00\x00\x00", "\xff\x00\x00\xff\xff\x00\x00\xff", "\xff\x00\x00\xff\xff\x00\xff\x00", "\xff\x00\x00\xff\xff\x00\xff\xff", "\xff\x00\x00\xff\xff\xff\x00\x00", "\xff\x00\x00\xff\xff\xff\x00\xff", "\xff\x00\x00\xff\xff\xff\xff\x00", "\xff\x00\x00\xff\xff\xff\xff\xff", "\xff\x00\xff\x00\x00\x00\x00\x00", "\xff\x00\xff\x00\x00\x00\x00\xff", "\xff\x00\xff\x00\x00\x00\xff\x00", "\xff\x00\xff\x00\x00\x00\xff\xff", "\xff\x00\xff\x00\x00\xff\x00\x00", "\xff\x00\xff\x00\x00\xff\x00\xff", "\xff\x00\xff\x00\x00\xff\xff\x00", "\xff\x00\xff\x00\x00\xff\xff\xff", "\xff\x00\xff\x00\xff\x00\x00\x00", "\xff\x00\xff\x00\xff\x00\x00\xff", "\xff\x00\xff\x00\xff\x00\xff\x00", "\xff\x00\xff\x00\xff\x00\xff\xff", "\xff\x00\xff\x00\xff\xff\x00\x00", "\xff\x00\xff\x00\xff\xff\x00\xff", "\xff\x00\xff\x00\xff\xff\xff\x00", "\xff\x00\xff\x00\xff\xff\xff\xff", "\xff\x00\xff\xff\x00\x00\x00\x00", "\xff\x00\xff\xff\x00\x00\x00\xff", "\xff\x00\xff\xff\x00\x00\xff\x00", "\xff\x00\xff\xff\x00\x00\xff\xff", "\xff\x00\xff\xff\x00\xff\x00\x00", "\xff\x00\xff\xff\x00\xff\x00\xff", "\xff\x00\xff\xff\x00\xff\xff\x00", "\xff\x00\xff\xff\x00\xff\xff\xff", "\xff\x00\xff\xff\xff\x00\x00\x00", "\xff\x00\xff\xff\xff\x00\x00\xff", "\xff\x00\xff\xff\xff\x00\xff\x00", "\xff\x00\xff\xff\xff\x00\xff\xff", "\xff\x00\xff\xff\xff\xff\x00\x00", "\xff\x00\xff\xff\xff\xff\x00\xff", "\xff\x00\xff\xff\xff\xff\xff\x00", "\xff\x00\xff\xff\xff\xff\xff\xff", "\xff\xff\x00\x00\x00\x00\x00\x00", "\xff\xff\x00\x00\x00\x00\x00\xff", "\xff\xff\x00\x00\x00\x00\xff\x00", "\xff\xff\x00\x00\x00\x00\xff\xff", "\xff\xff\x00\x00\x00\xff\x00\x00", "\xff\xff\x00\x00\x00\xff\x00\xff", "\xff\xff\x00\x00\x00\xff\xff\x00", "\xff\xff\x00\x00\x00\xff\xff\xff", "\xff\xff\x00\x00\xff\x00\x00\x00", "\xff\xff\x00\x00\xff\x00\x00\xff", "\xff\xff\x00\x00\xff\x00\xff\x00", "\xff\xff\x00\x00\xff\x00\xff\xff", "\xff\xff\x00\x00\xff\xff\x00\x00", "\xff\xff\x00\x00\xff\xff\x00\xff", "\xff\xff\x00\x00\xff\xff\xff\x00", "\xff\xff\x00\x00\xff\xff\xff\xff", "\xff\xff\x00\xff\x00\x00\x00\x00", "\xff\xff\x00\xff\x00\x00\x00\xff", "\xff\xff\x00\xff\x00\x00\xff\x00", "\xff\xff\x00\xff\x00\x00\xff\xff", "\xff\xff\x00\xff\x00\xff\x00\x00", "\xff\xff\x00\xff\x00\xff\x00\xff", "\xff\xff\x00\xff\x00\xff\xff\x00", "\xff\xff\x00\xff\x00\xff\xff\xff", "\xff\xff\x00\xff\xff\x00\x00\x00", "\xff\xff\x00\xff\xff\x00\x00\xff", "\xff\xff\x00\xff\xff\x00\xff\x00", "\xff\xff\x00\xff\xff\x00\xff\xff", "\xff\xff\x00\xff\xff\xff\x00\x00", "\xff\xff\x00\xff\xff\xff\x00\xff", "\xff\xff\x00\xff\xff\xff\xff\x00", "\xff\xff\x00\xff\xff\xff\xff\xff", "\xff\xff\xff\x00\x00\x00\x00\x00", "\xff\xff\xff\x00\x00\x00\x00\xff", "\xff\xff\xff\x00\x00\x00\xff\x00", "\xff\xff\xff\x00\x00\x00\xff\xff", "\xff\xff\xff\x00\x00\xff\x00\x00", "\xff\xff\xff\x00\x00\xff\x00\xff", "\xff\xff\xff\x00\x00\xff\xff\x00", "\xff\xff\xff\x00\x00\xff\xff\xff", "\xff\xff\xff\x00\xff\x00\x00\x00", "\xff\xff\xff\x00\xff\x00\x00\xff", "\xff\xff\xff\x00\xff\x00\xff\x00", "\xff\xff\xff\x00\xff\x00\xff\xff", "\xff\xff\xff\x00\xff\xff\x00\x00", "\xff\xff\xff\x00\xff\xff\x00\xff", "\xff\xff\xff\x00\xff\xff\xff\x00", "\xff\xff\xff\x00\xff\xff\xff\xff", "\xff\xff\xff\xff\x00\x00\x00\x00", "\xff\xff\xff\xff\x00\x00\x00\xff", "\xff\xff\xff\xff\x00\x00\xff\x00", "\xff\xff\xff\xff\x00\x00\xff\xff", "\xff\xff\xff\xff\x00\xff\x00\x00", "\xff\xff\xff\xff\x00\xff\x00\xff", "\xff\xff\xff\xff\x00\xff\xff\x00", "\xff\xff\xff\xff\x00\xff\xff\xff", "\xff\xff\xff\xff\xff\x00\x00\x00", "\xff\xff\xff\xff\xff\x00\x00\xff", "\xff\xff\xff\xff\xff\x00\xff\x00", "\xff\xff\xff\xff\xff\x00\xff\xff", "\xff\xff\xff\xff\xff\xff\x00\x00", "\xff\xff\xff\xff\xff\xff\x00\xff", "\xff\xff\xff\xff\xff\xff\xff\x00", "\xff\xff\xff\xff\xff\xff\xff\xff"];
    /**
     * IP mapping helper table.
     *
     * Indexing this table with each source byte performs the initial bit permutation.
     *
     * @var array
     * @access private
     */
    protected static $ipmap = [0x0, 0x10, 0x1, 0x11, 0x20, 0x30, 0x21, 0x31, 0x2, 0x12, 0x3, 0x13, 0x22, 0x32, 0x23, 0x33, 0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71, 0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73, 0x4, 0x14, 0x5, 0x15, 0x24, 0x34, 0x25, 0x35, 0x6, 0x16, 0x7, 0x17, 0x26, 0x36, 0x27, 0x37, 0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75, 0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77, 0x80, 0x90, 0x81, 0x91, 0xa0, 0xb0, 0xa1, 0xb1, 0x82, 0x92, 0x83, 0x93, 0xa2, 0xb2, 0xa3, 0xb3, 0xc0, 0xd0, 0xc1, 0xd1, 0xe0, 0xf0, 0xe1, 0xf1, 0xc2, 0xd2, 0xc3, 0xd3, 0xe2, 0xf2, 0xe3, 0xf3, 0x84, 0x94, 0x85, 0x95, 0xa4, 0xb4, 0xa5, 0xb5, 0x86, 0x96, 0x87, 0x97, 0xa6, 0xb6, 0xa7, 0xb7, 0xc4, 0xd4, 0xc5, 0xd5, 0xe4, 0xf4, 0xe5, 0xf5, 0xc6, 0xd6, 0xc7, 0xd7, 0xe6, 0xf6, 0xe7, 0xf7, 0x8, 0x18, 0x9, 0x19, 0x28, 0x38, 0x29, 0x39, 0xa, 0x1a, 0xb, 0x1b, 0x2a, 0x3a, 0x2b, 0x3b, 0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79, 0x4a, 0x5a, 0x4b, 0x5b, 0x6a, 0x7a, 0x6b, 0x7b, 0xc, 0x1c, 0xd, 0x1d, 0x2c, 0x3c, 0x2d, 0x3d, 0xe, 0x1e, 0xf, 0x1f, 0x2e, 0x3e, 0x2f, 0x3f, 0x4c, 0x5c, 0x4d, 0x5d, 0x6c, 0x7c, 0x6d, 0x7d, 0x4e, 0x5e, 0x4f, 0x5f, 0x6e, 0x7e, 0x6f, 0x7f, 0x88, 0x98, 0x89, 0x99, 0xa8, 0xb8, 0xa9, 0xb9, 0x8a, 0x9a, 0x8b, 0x9b, 0xaa, 0xba, 0xab, 0xbb, 0xc8, 0xd8, 0xc9, 0xd9, 0xe8, 0xf8, 0xe9, 0xf9, 0xca, 0xda, 0xcb, 0xdb, 0xea, 0xfa, 0xeb, 0xfb, 0x8c, 0x9c, 0x8d, 0x9d, 0xac, 0xbc, 0xad, 0xbd, 0x8e, 0x9e, 0x8f, 0x9f, 0xae, 0xbe, 0xaf, 0xbf, 0xcc, 0xdc, 0xcd, 0xdd, 0xec, 0xfc, 0xed, 0xfd, 0xce, 0xde, 0xcf, 0xdf, 0xee, 0xfe, 0xef, 0xff];
    /**
     * Inverse IP mapping helper table.
     * Indexing this table with a byte value reverses the bit order.
     *
     * @var array
     * @access private
     */
    protected static $invipmap = [0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x8, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x4, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0xc, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x2, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0xa, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x6, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0xe, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x1, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x9, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x5, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0xd, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x3, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0xb, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x7, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0xf, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff];
    /**
     * Pre-permuted S-box1
     *
     * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
     * P table: concatenation can then be replaced by exclusive ORs.
     *
     * @var array
     * @access private
     */
    protected static $sbox1 = [0x808200, 0x0, 0x8000, 0x808202, 0x808002, 0x8202, 0x2, 0x8000, 0x200, 0x808200, 0x808202, 0x200, 0x800202, 0x808002, 0x800000, 0x2, 0x202, 0x800200, 0x800200, 0x8200, 0x8200, 0x808000, 0x808000, 0x800202, 0x8002, 0x800002, 0x800002, 0x8002, 0x0, 0x202, 0x8202, 0x800000, 0x8000, 0x808202, 0x2, 0x808000, 0x808200, 0x800000, 0x800000, 0x200, 0x808002, 0x8000, 0x8200, 0x800002, 0x200, 0x2, 0x800202, 0x8202, 0x808202, 0x8002, 0x808000, 0x800202, 0x800002, 0x202, 0x8202, 0x808200, 0x202, 0x800200, 0x800200, 0x0, 0x8002, 0x8200, 0x0, 0x808002];
    /**
     * Pre-permuted S-box2
     *
     * @var array
     * @access private
     */
    protected static $sbox2 = [0x40084010, 0x40004000, 0x4000, 0x84010, 0x80000, 0x10, 0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x80000, 0x10, 0x40080010, 0x84000, 0x80010, 0x40004010, 0x0, 0x40000000, 0x4000, 0x84010, 0x40080000, 0x80010, 0x40000010, 0x0, 0x84000, 0x4010, 0x40084000, 0x40080000, 0x4010, 0x0, 0x84010, 0x40080010, 0x80000, 0x40004010, 0x40080000, 0x40084000, 0x4000, 0x40080000, 0x40004000, 0x10, 0x40084010, 0x84010, 0x10, 0x4000, 0x40000000, 0x4010, 0x40084000, 0x80000, 0x40000010, 0x80010, 0x40004010, 0x40000010, 0x80010, 0x84000, 0x0, 0x40004000, 0x4010, 0x40000000, 0x40080010, 0x40084010, 0x84000];
    /**
     * Pre-permuted S-box3
     *
     * @var array
     * @access private
     */
    protected static $sbox3 = [0x104, 0x4010100, 0x0, 0x4010004, 0x4000100, 0x0, 0x10104, 0x4000100, 0x10004, 0x4000004, 0x4000004, 0x10000, 0x4010104, 0x10004, 0x4010000, 0x104, 0x4000000, 0x4, 0x4010100, 0x100, 0x10100, 0x4010000, 0x4010004, 0x10104, 0x4000104, 0x10100, 0x10000, 0x4000104, 0x4, 0x4010104, 0x100, 0x4000000, 0x4010100, 0x4000000, 0x10004, 0x104, 0x10000, 0x4010100, 0x4000100, 0x0, 0x100, 0x10004, 0x4010104, 0x4000100, 0x4000004, 0x100, 0x0, 0x4010004, 0x4000104, 0x10000, 0x4000000, 0x4010104, 0x4, 0x10104, 0x10100, 0x4000004, 0x4010000, 0x4000104, 0x104, 0x4010000, 0x10104, 0x4, 0x4010004, 0x10100];
    /**
     * Pre-permuted S-box4
     *
     * @var array
     * @access private
     */
    protected static $sbox4 = [0x80401000, 0x80001040, 0x80001040, 0x40, 0x401040, 0x80400040, 0x80400000, 0x80001000, 0x0, 0x401000, 0x401000, 0x80401040, 0x80000040, 0x0, 0x400040, 0x80400000, 0x80000000, 0x1000, 0x400000, 0x80401000, 0x40, 0x400000, 0x80001000, 0x1040, 0x80400040, 0x80000000, 0x1040, 0x400040, 0x1000, 0x401040, 0x80401040, 0x80000040, 0x400040, 0x80400000, 0x401000, 0x80401040, 0x80000040, 0x0, 0x0, 0x401000, 0x1040, 0x400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x40, 0x80401040, 0x80000040, 0x80000000, 0x1000, 0x80400000, 0x80001000, 0x401040, 0x80400040, 0x80001000, 0x1040, 0x400000, 0x80401000, 0x40, 0x400000, 0x1000, 0x401040];
    /**
     * Pre-permuted S-box5
     *
     * @var array
     * @access private
     */
    protected static $sbox5 = [0x80, 0x1040080, 0x1040000, 0x21000080, 0x40000, 0x80, 0x20000000, 0x1040000, 0x20040080, 0x40000, 0x1000080, 0x20040080, 0x21000080, 0x21040000, 0x40080, 0x20000000, 0x1000000, 0x20040000, 0x20040000, 0x0, 0x20000080, 0x21040080, 0x21040080, 0x1000080, 0x21040000, 0x20000080, 0x0, 0x21000000, 0x1040080, 0x1000000, 0x21000000, 0x40080, 0x40000, 0x21000080, 0x80, 0x1000000, 0x20000000, 0x1040000, 0x21000080, 0x20040080, 0x1000080, 0x20000000, 0x21040000, 0x1040080, 0x20040080, 0x80, 0x1000000, 0x21040000, 0x21040080, 0x40080, 0x21000000, 0x21040080, 0x1040000, 0x0, 0x20040000, 0x21000000, 0x40080, 0x1000080, 0x20000080, 0x40000, 0x0, 0x20040000, 0x1040080, 0x20000080];
    /**
     * Pre-permuted S-box6
     *
     * @var array
     * @access private
     */
    protected static $sbox6 = [0x10000008, 0x10200000, 0x2000, 0x10202008, 0x10200000, 0x8, 0x10202008, 0x200000, 0x10002000, 0x202008, 0x200000, 0x10000008, 0x200008, 0x10002000, 0x10000000, 0x2008, 0x0, 0x200008, 0x10002008, 0x2000, 0x202000, 0x10002008, 0x8, 0x10200008, 0x10200008, 0x0, 0x202008, 0x10202000, 0x2008, 0x202000, 0x10202000, 0x10000000, 0x10002000, 0x8, 0x10200008, 0x202000, 0x10202008, 0x200000, 0x2008, 0x10000008, 0x200000, 0x10002000, 0x10000000, 0x2008, 0x10000008, 0x10202008, 0x202000, 0x10200000, 0x202008, 0x10202000, 0x0, 0x10200008, 0x8, 0x2000, 0x10200000, 0x202008, 0x2000, 0x200008, 0x10002008, 0x0, 0x10202000, 0x10000000, 0x200008, 0x10002008];
    /**
     * Pre-permuted S-box7
     *
     * @var array
     * @access private
     */
    protected static $sbox7 = [0x100000, 0x2100001, 0x2000401, 0x0, 0x400, 0x2000401, 0x100401, 0x2100400, 0x2100401, 0x100000, 0x0, 0x2000001, 0x1, 0x2000000, 0x2100001, 0x401, 0x2000400, 0x100401, 0x100001, 0x2000400, 0x2000001, 0x2100000, 0x2100400, 0x100001, 0x2100000, 0x400, 0x401, 0x2100401, 0x100400, 0x1, 0x2000000, 0x100400, 0x2000000, 0x100400, 0x100000, 0x2000401, 0x2000401, 0x2100001, 0x2100001, 0x1, 0x100001, 0x2000000, 0x2000400, 0x100000, 0x2100400, 0x401, 0x100401, 0x2100400, 0x401, 0x2000001, 0x2100401, 0x2100000, 0x100400, 0x0, 0x1, 0x2100401, 0x0, 0x100401, 0x2100000, 0x400, 0x2000001, 0x2000400, 0x400, 0x100001];
    /**
     * Pre-permuted S-box8
     *
     * @var array
     * @access private
     */
    protected static $sbox8 = [0x8000820, 0x800, 0x20000, 0x8020820, 0x8000000, 0x8000820, 0x20, 0x8000000, 0x20020, 0x8020000, 0x8020820, 0x20800, 0x8020800, 0x20820, 0x800, 0x20, 0x8020000, 0x8000020, 0x8000800, 0x820, 0x20800, 0x20020, 0x8020020, 0x8020800, 0x820, 0x0, 0x0, 0x8020020, 0x8000020, 0x8000800, 0x20820, 0x20000, 0x20820, 0x20000, 0x8020800, 0x800, 0x20, 0x8020020, 0x800, 0x20820, 0x8000800, 0x20, 0x8000020, 0x8020000, 0x8020020, 0x8000000, 0x20000, 0x8000820, 0x0, 0x8020820, 0x20020, 0x8000020, 0x8020000, 0x8000800, 0x8000820, 0x0, 0x8020820, 0x20800, 0x20800, 0x820, 0x820, 0x20020, 0x8000000, 0x8020800];
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws BadModeException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new BadModeException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        if ($this->key_length_max == 8) {
            if ($engine == self::ENGINE_OPENSSL) {
                $this->cipher_name_openssl_ecb = 'des-ecb';
                $this->cipher_name_openssl = 'des-' . $this->openssl_translate_mode();
            }
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Sets the key.
     *
     * Keys must be 64-bits long or 8 bytes long.
     *
     * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
     * @access public
     * @param string $key
     */
    public function setKey($key)
    {
        if (!$this instanceof TripleDES && strlen($key) != 8) {
            throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of size 8 are supported');
        }
        // Sets the key
        parent::setKey($key);
    }
    /**
     * Encrypts a block
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see self::encrypt()
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        return $this->processBlock($in, self::ENCRYPT);
    }
    /**
     * Decrypts a block
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @see self::decrypt()
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        return $this->processBlock($in, self::DECRYPT);
    }
    /**
    * Encrypts or decrypts a 64-bit block
    *
    * $mode should be either self::ENCRYPT or self::DECRYPT.  See
    {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
    idea of what this function does.
    *
    * @see self::encryptBlock()
    * @see self::decryptBlock()
    * @access private
    * @param string $block
    * @param int $mode
    * @return string
    */
    private function processBlock($block, $mode)
    {
        static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
        if (!$sbox1) {
            $sbox1 = array_map('intval', self::$sbox1);
            $sbox2 = array_map('intval', self::$sbox2);
            $sbox3 = array_map('intval', self::$sbox3);
            $sbox4 = array_map('intval', self::$sbox4);
            $sbox5 = array_map('intval', self::$sbox5);
            $sbox6 = array_map('intval', self::$sbox6);
            $sbox7 = array_map('intval', self::$sbox7);
            $sbox8 = array_map('intval', self::$sbox8);
            /* Merge $shuffle with $[inv]ipmap */
            for ($i = 0; $i < 256; ++$i) {
                $shuffleip[] = self::$shuffle[self::$ipmap[$i]];
                $shuffleinvip[] = self::$shuffle[self::$invipmap[$i]];
            }
        }
        $keys = $this->keys[$mode];
        $ki = -1;
        // Do the initial IP permutation.
        $t = unpack('Nl/Nr', $block);
        list($l, $r) = [$t['l'], $t['r']];
        $block = $shuffleip[$r & 0xff] & "\x80\x80\x80\x80\x80\x80\x80\x80" | $shuffleip[$r >> 8 & 0xff] & "@@@@@@@@" | $shuffleip[$r >> 16 & 0xff] & "        " | $shuffleip[$r >> 24 & 0xff] & "\x10\x10\x10\x10\x10\x10\x10\x10" | $shuffleip[$l & 0xff] & "\x08\x08\x08\x08\x08\x08\x08\x08" | $shuffleip[$l >> 8 & 0xff] & "\x04\x04\x04\x04\x04\x04\x04\x04" | $shuffleip[$l >> 16 & 0xff] & "\x02\x02\x02\x02\x02\x02\x02\x02" | $shuffleip[$l >> 24 & 0xff] & "\x01\x01\x01\x01\x01\x01\x01\x01";
        // Extract L0 and R0.
        $t = unpack('Nl/Nr', $block);
        list($l, $r) = [$t['l'], $t['r']];
        for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
            // Perform the 16 steps.
            for ($i = 0; $i < 16; $i++) {
                // start of "the Feistel (F) function" - see the following URL:
                // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
                // Merge key schedule.
                $b1 = $r >> 3 & 0x1fffffff ^ $r << 29 ^ $keys[++$ki];
                $b2 = $r >> 31 & 0x1 ^ $r << 1 ^ $keys[++$ki];
                // S-box indexing.
                $t = $sbox1[$b1 >> 24 & 0x3f] ^ $sbox2[$b2 >> 24 & 0x3f] ^ $sbox3[$b1 >> 16 & 0x3f] ^ $sbox4[$b2 >> 16 & 0x3f] ^ $sbox5[$b1 >> 8 & 0x3f] ^ $sbox6[$b2 >> 8 & 0x3f] ^ $sbox7[$b1 & 0x3f] ^ $sbox8[$b2 & 0x3f] ^ $l;
                // end of "the Feistel (F) function"
                $l = $r;
                $r = $t;
            }
            // Last step should not permute L & R.
            $t = $l;
            $l = $r;
            $r = $t;
        }
        // Perform the inverse IP permutation.
        return $shuffleinvip[$r >> 24 & 0xff] & "\x80\x80\x80\x80\x80\x80\x80\x80" | $shuffleinvip[$l >> 24 & 0xff] & "@@@@@@@@" | $shuffleinvip[$r >> 16 & 0xff] & "        " | $shuffleinvip[$l >> 16 & 0xff] & "\x10\x10\x10\x10\x10\x10\x10\x10" | $shuffleinvip[$r >> 8 & 0xff] & "\x08\x08\x08\x08\x08\x08\x08\x08" | $shuffleinvip[$l >> 8 & 0xff] & "\x04\x04\x04\x04\x04\x04\x04\x04" | $shuffleinvip[$r & 0xff] & "\x02\x02\x02\x02\x02\x02\x02\x02" | $shuffleinvip[$l & 0xff] & "\x01\x01\x01\x01\x01\x01\x01\x01";
    }
    /**
     * Creates the key schedule
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
     * @access private
     */
    protected function setupKey()
    {
        if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) {
            // already expanded
            return;
        }
        $this->kl = ['key' => $this->key, 'des_rounds' => $this->des_rounds];
        static $shifts = [
            // number of key bits shifted per round
            1,
            1,
            2,
            2,
            2,
            2,
            2,
            2,
            1,
            2,
            2,
            2,
            2,
            2,
            2,
            1,
        ];
        static $pc1map = [0x0, 0x0, 0x8, 0x8, 0x4, 0x4, 0xc, 0xc, 0x2, 0x2, 0xa, 0xa, 0x6, 0x6, 0xe, 0xe, 0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1c, 0x1c, 0x12, 0x12, 0x1a, 0x1a, 0x16, 0x16, 0x1e, 0x1e, 0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2c, 0x2c, 0x22, 0x22, 0x2a, 0x2a, 0x26, 0x26, 0x2e, 0x2e, 0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3c, 0x3c, 0x32, 0x32, 0x3a, 0x3a, 0x36, 0x36, 0x3e, 0x3e, 0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4c, 0x4c, 0x42, 0x42, 0x4a, 0x4a, 0x46, 0x46, 0x4e, 0x4e, 0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5c, 0x5c, 0x52, 0x52, 0x5a, 0x5a, 0x56, 0x56, 0x5e, 0x5e, 0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6c, 0x6c, 0x62, 0x62, 0x6a, 0x6a, 0x66, 0x66, 0x6e, 0x6e, 0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7c, 0x7c, 0x72, 0x72, 0x7a, 0x7a, 0x76, 0x76, 0x7e, 0x7e, 0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8c, 0x8c, 0x82, 0x82, 0x8a, 0x8a, 0x86, 0x86, 0x8e, 0x8e, 0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9c, 0x9c, 0x92, 0x92, 0x9a, 0x9a, 0x96, 0x96, 0x9e, 0x9e, 0xa0, 0xa0, 0xa8, 0xa8, 0xa4, 0xa4, 0xac, 0xac, 0xa2, 0xa2, 0xaa, 0xaa, 0xa6, 0xa6, 0xae, 0xae, 0xb0, 0xb0, 0xb8, 0xb8, 0xb4, 0xb4, 0xbc, 0xbc, 0xb2, 0xb2, 0xba, 0xba, 0xb6, 0xb6, 0xbe, 0xbe, 0xc0, 0xc0, 0xc8, 0xc8, 0xc4, 0xc4, 0xcc, 0xcc, 0xc2, 0xc2, 0xca, 0xca, 0xc6, 0xc6, 0xce, 0xce, 0xd0, 0xd0, 0xd8, 0xd8, 0xd4, 0xd4, 0xdc, 0xdc, 0xd2, 0xd2, 0xda, 0xda, 0xd6, 0xd6, 0xde, 0xde, 0xe0, 0xe0, 0xe8, 0xe8, 0xe4, 0xe4, 0xec, 0xec, 0xe2, 0xe2, 0xea, 0xea, 0xe6, 0xe6, 0xee, 0xee, 0xf0, 0xf0, 0xf8, 0xf8, 0xf4, 0xf4, 0xfc, 0xfc, 0xf2, 0xf2, 0xfa, 0xfa, 0xf6, 0xf6, 0xfe, 0xfe];
        // Mapping tables for the PC-2 transformation.
        static $pc2mapc1 = [0x0, 0x400, 0x200000, 0x200400, 0x1, 0x401, 0x200001, 0x200401, 0x2000000, 0x2000400, 0x2200000, 0x2200400, 0x2000001, 0x2000401, 0x2200001, 0x2200401];
        static $pc2mapc2 = [0x0, 0x800, 0x8000000, 0x8000800, 0x10000, 0x10800, 0x8010000, 0x8010800, 0x0, 0x800, 0x8000000, 0x8000800, 0x10000, 0x10800, 0x8010000, 0x8010800, 0x100, 0x900, 0x8000100, 0x8000900, 0x10100, 0x10900, 0x8010100, 0x8010900, 0x100, 0x900, 0x8000100, 0x8000900, 0x10100, 0x10900, 0x8010100, 0x8010900, 0x10, 0x810, 0x8000010, 0x8000810, 0x10010, 0x10810, 0x8010010, 0x8010810, 0x10, 0x810, 0x8000010, 0x8000810, 0x10010, 0x10810, 0x8010010, 0x8010810, 0x110, 0x910, 0x8000110, 0x8000910, 0x10110, 0x10910, 0x8010110, 0x8010910, 0x110, 0x910, 0x8000110, 0x8000910, 0x10110, 0x10910, 0x8010110, 0x8010910, 0x40000, 0x40800, 0x8040000, 0x8040800, 0x50000, 0x50800, 0x8050000, 0x8050800, 0x40000, 0x40800, 0x8040000, 0x8040800, 0x50000, 0x50800, 0x8050000, 0x8050800, 0x40100, 0x40900, 0x8040100, 0x8040900, 0x50100, 0x50900, 0x8050100, 0x8050900, 0x40100, 0x40900, 0x8040100, 0x8040900, 0x50100, 0x50900, 0x8050100, 0x8050900, 0x40010, 0x40810, 0x8040010, 0x8040810, 0x50010, 0x50810, 0x8050010, 0x8050810, 0x40010, 0x40810, 0x8040010, 0x8040810, 0x50010, 0x50810, 0x8050010, 0x8050810, 0x40110, 0x40910, 0x8040110, 0x8040910, 0x50110, 0x50910, 0x8050110, 0x8050910, 0x40110, 0x40910, 0x8040110, 0x8040910, 0x50110, 0x50910, 0x8050110, 0x8050910, 0x1000000, 0x1000800, 0x9000000, 0x9000800, 0x1010000, 0x1010800, 0x9010000, 0x9010800, 0x1000000, 0x1000800, 0x9000000, 0x9000800, 0x1010000, 0x1010800, 0x9010000, 0x9010800, 0x1000100, 0x1000900, 0x9000100, 0x9000900, 0x1010100, 0x1010900, 0x9010100, 0x9010900, 0x1000100, 0x1000900, 0x9000100, 0x9000900, 0x1010100, 0x1010900, 0x9010100, 0x9010900, 0x1000010, 0x1000810, 0x9000010, 0x9000810, 0x1010010, 0x1010810, 0x9010010, 0x9010810, 0x1000010, 0x1000810, 0x9000010, 0x9000810, 0x1010010, 0x1010810, 0x9010010, 0x9010810, 0x1000110, 0x1000910, 0x9000110, 0x9000910, 0x1010110, 0x1010910, 0x9010110, 0x9010910, 0x1000110, 0x1000910, 0x9000110, 0x9000910, 0x1010110, 0x1010910, 0x9010110, 0x9010910, 0x1040000, 0x1040800, 0x9040000, 0x9040800, 0x1050000, 0x1050800, 0x9050000, 0x9050800, 0x1040000, 0x1040800, 0x9040000, 0x9040800, 0x1050000, 0x1050800, 0x9050000, 0x9050800, 0x1040100, 0x1040900, 0x9040100, 0x9040900, 0x1050100, 0x1050900, 0x9050100, 0x9050900, 0x1040100, 0x1040900, 0x9040100, 0x9040900, 0x1050100, 0x1050900, 0x9050100, 0x9050900, 0x1040010, 0x1040810, 0x9040010, 0x9040810, 0x1050010, 0x1050810, 0x9050010, 0x9050810, 0x1040010, 0x1040810, 0x9040010, 0x9040810, 0x1050010, 0x1050810, 0x9050010, 0x9050810, 0x1040110, 0x1040910, 0x9040110, 0x9040910, 0x1050110, 0x1050910, 0x9050110, 0x9050910, 0x1040110, 0x1040910, 0x9040110, 0x9040910, 0x1050110, 0x1050910, 0x9050110, 0x9050910];
        static $pc2mapc3 = [0x0, 0x4, 0x1000, 0x1004, 0x0, 0x4, 0x1000, 0x1004, 0x10000000, 0x10000004, 0x10001000, 0x10001004, 0x10000000, 0x10000004, 0x10001000, 0x10001004, 0x20, 0x24, 0x1020, 0x1024, 0x20, 0x24, 0x1020, 0x1024, 0x10000020, 0x10000024, 0x10001020, 0x10001024, 0x10000020, 0x10000024, 0x10001020, 0x10001024, 0x80000, 0x80004, 0x81000, 0x81004, 0x80000, 0x80004, 0x81000, 0x81004, 0x10080000, 0x10080004, 0x10081000, 0x10081004, 0x10080000, 0x10080004, 0x10081000, 0x10081004, 0x80020, 0x80024, 0x81020, 0x81024, 0x80020, 0x80024, 0x81020, 0x81024, 0x10080020, 0x10080024, 0x10081020, 0x10081024, 0x10080020, 0x10080024, 0x10081020, 0x10081024, 0x20000000, 0x20000004, 0x20001000, 0x20001004, 0x20000000, 0x20000004, 0x20001000, 0x20001004, 0x30000000, 0x30000004, 0x30001000, 0x30001004, 0x30000000, 0x30000004, 0x30001000, 0x30001004, 0x20000020, 0x20000024, 0x20001020, 0x20001024, 0x20000020, 0x20000024, 0x20001020, 0x20001024, 0x30000020, 0x30000024, 0x30001020, 0x30001024, 0x30000020, 0x30000024, 0x30001020, 0x30001024, 0x20080000, 0x20080004, 0x20081000, 0x20081004, 0x20080000, 0x20080004, 0x20081000, 0x20081004, 0x30080000, 0x30080004, 0x30081000, 0x30081004, 0x30080000, 0x30080004, 0x30081000, 0x30081004, 0x20080020, 0x20080024, 0x20081020, 0x20081024, 0x20080020, 0x20080024, 0x20081020, 0x20081024, 0x30080020, 0x30080024, 0x30081020, 0x30081024, 0x30080020, 0x30080024, 0x30081020, 0x30081024, 0x2, 0x6, 0x1002, 0x1006, 0x2, 0x6, 0x1002, 0x1006, 0x10000002, 0x10000006, 0x10001002, 0x10001006, 0x10000002, 0x10000006, 0x10001002, 0x10001006, 0x22, 0x26, 0x1022, 0x1026, 0x22, 0x26, 0x1022, 0x1026, 0x10000022, 0x10000026, 0x10001022, 0x10001026, 0x10000022, 0x10000026, 0x10001022, 0x10001026, 0x80002, 0x80006, 0x81002, 0x81006, 0x80002, 0x80006, 0x81002, 0x81006, 0x10080002, 0x10080006, 0x10081002, 0x10081006, 0x10080002, 0x10080006, 0x10081002, 0x10081006, 0x80022, 0x80026, 0x81022, 0x81026, 0x80022, 0x80026, 0x81022, 0x81026, 0x10080022, 0x10080026, 0x10081022, 0x10081026, 0x10080022, 0x10080026, 0x10081022, 0x10081026, 0x20000002, 0x20000006, 0x20001002, 0x20001006, 0x20000002, 0x20000006, 0x20001002, 0x20001006, 0x30000002, 0x30000006, 0x30001002, 0x30001006, 0x30000002, 0x30000006, 0x30001002, 0x30001006, 0x20000022, 0x20000026, 0x20001022, 0x20001026, 0x20000022, 0x20000026, 0x20001022, 0x20001026, 0x30000022, 0x30000026, 0x30001022, 0x30001026, 0x30000022, 0x30000026, 0x30001022, 0x30001026, 0x20080002, 0x20080006, 0x20081002, 0x20081006, 0x20080002, 0x20080006, 0x20081002, 0x20081006, 0x30080002, 0x30080006, 0x30081002, 0x30081006, 0x30080002, 0x30080006, 0x30081002, 0x30081006, 0x20080022, 0x20080026, 0x20081022, 0x20081026, 0x20080022, 0x20080026, 0x20081022, 0x20081026, 0x30080022, 0x30080026, 0x30081022, 0x30081026, 0x30080022, 0x30080026, 0x30081022, 0x30081026];
        static $pc2mapc4 = [0x0, 0x100000, 0x8, 0x100008, 0x200, 0x100200, 0x208, 0x100208, 0x0, 0x100000, 0x8, 0x100008, 0x200, 0x100200, 0x208, 0x100208, 0x4000000, 0x4100000, 0x4000008, 0x4100008, 0x4000200, 0x4100200, 0x4000208, 0x4100208, 0x4000000, 0x4100000, 0x4000008, 0x4100008, 0x4000200, 0x4100200, 0x4000208, 0x4100208, 0x2000, 0x102000, 0x2008, 0x102008, 0x2200, 0x102200, 0x2208, 0x102208, 0x2000, 0x102000, 0x2008, 0x102008, 0x2200, 0x102200, 0x2208, 0x102208, 0x4002000, 0x4102000, 0x4002008, 0x4102008, 0x4002200, 0x4102200, 0x4002208, 0x4102208, 0x4002000, 0x4102000, 0x4002008, 0x4102008, 0x4002200, 0x4102200, 0x4002208, 0x4102208, 0x0, 0x100000, 0x8, 0x100008, 0x200, 0x100200, 0x208, 0x100208, 0x0, 0x100000, 0x8, 0x100008, 0x200, 0x100200, 0x208, 0x100208, 0x4000000, 0x4100000, 0x4000008, 0x4100008, 0x4000200, 0x4100200, 0x4000208, 0x4100208, 0x4000000, 0x4100000, 0x4000008, 0x4100008, 0x4000200, 0x4100200, 0x4000208, 0x4100208, 0x2000, 0x102000, 0x2008, 0x102008, 0x2200, 0x102200, 0x2208, 0x102208, 0x2000, 0x102000, 0x2008, 0x102008, 0x2200, 0x102200, 0x2208, 0x102208, 0x4002000, 0x4102000, 0x4002008, 0x4102008, 0x4002200, 0x4102200, 0x4002208, 0x4102208, 0x4002000, 0x4102000, 0x4002008, 0x4102008, 0x4002200, 0x4102200, 0x4002208, 0x4102208, 0x20000, 0x120000, 0x20008, 0x120008, 0x20200, 0x120200, 0x20208, 0x120208, 0x20000, 0x120000, 0x20008, 0x120008, 0x20200, 0x120200, 0x20208, 0x120208, 0x4020000, 0x4120000, 0x4020008, 0x4120008, 0x4020200, 0x4120200, 0x4020208, 0x4120208, 0x4020000, 0x4120000, 0x4020008, 0x4120008, 0x4020200, 0x4120200, 0x4020208, 0x4120208, 0x22000, 0x122000, 0x22008, 0x122008, 0x22200, 0x122200, 0x22208, 0x122208, 0x22000, 0x122000, 0x22008, 0x122008, 0x22200, 0x122200, 0x22208, 0x122208, 0x4022000, 0x4122000, 0x4022008, 0x4122008, 0x4022200, 0x4122200, 0x4022208, 0x4122208, 0x4022000, 0x4122000, 0x4022008, 0x4122008, 0x4022200, 0x4122200, 0x4022208, 0x4122208, 0x20000, 0x120000, 0x20008, 0x120008, 0x20200, 0x120200, 0x20208, 0x120208, 0x20000, 0x120000, 0x20008, 0x120008, 0x20200, 0x120200, 0x20208, 0x120208, 0x4020000, 0x4120000, 0x4020008, 0x4120008, 0x4020200, 0x4120200, 0x4020208, 0x4120208, 0x4020000, 0x4120000, 0x4020008, 0x4120008, 0x4020200, 0x4120200, 0x4020208, 0x4120208, 0x22000, 0x122000, 0x22008, 0x122008, 0x22200, 0x122200, 0x22208, 0x122208, 0x22000, 0x122000, 0x22008, 0x122008, 0x22200, 0x122200, 0x22208, 0x122208, 0x4022000, 0x4122000, 0x4022008, 0x4122008, 0x4022200, 0x4122200, 0x4022208, 0x4122208, 0x4022000, 0x4122000, 0x4022008, 0x4122008, 0x4022200, 0x4122200, 0x4022208, 0x4122208];
        static $pc2mapd1 = [0x0, 0x1, 0x8000000, 0x8000001, 0x200000, 0x200001, 0x8200000, 0x8200001, 0x2, 0x3, 0x8000002, 0x8000003, 0x200002, 0x200003, 0x8200002, 0x8200003];
        static $pc2mapd2 = [0x0, 0x100000, 0x800, 0x100800, 0x0, 0x100000, 0x800, 0x100800, 0x4000000, 0x4100000, 0x4000800, 0x4100800, 0x4000000, 0x4100000, 0x4000800, 0x4100800, 0x4, 0x100004, 0x804, 0x100804, 0x4, 0x100004, 0x804, 0x100804, 0x4000004, 0x4100004, 0x4000804, 0x4100804, 0x4000004, 0x4100004, 0x4000804, 0x4100804, 0x0, 0x100000, 0x800, 0x100800, 0x0, 0x100000, 0x800, 0x100800, 0x4000000, 0x4100000, 0x4000800, 0x4100800, 0x4000000, 0x4100000, 0x4000800, 0x4100800, 0x4, 0x100004, 0x804, 0x100804, 0x4, 0x100004, 0x804, 0x100804, 0x4000004, 0x4100004, 0x4000804, 0x4100804, 0x4000004, 0x4100004, 0x4000804, 0x4100804, 0x200, 0x100200, 0xa00, 0x100a00, 0x200, 0x100200, 0xa00, 0x100a00, 0x4000200, 0x4100200, 0x4000a00, 0x4100a00, 0x4000200, 0x4100200, 0x4000a00, 0x4100a00, 0x204, 0x100204, 0xa04, 0x100a04, 0x204, 0x100204, 0xa04, 0x100a04, 0x4000204, 0x4100204, 0x4000a04, 0x4100a04, 0x4000204, 0x4100204, 0x4000a04, 0x4100a04, 0x200, 0x100200, 0xa00, 0x100a00, 0x200, 0x100200, 0xa00, 0x100a00, 0x4000200, 0x4100200, 0x4000a00, 0x4100a00, 0x4000200, 0x4100200, 0x4000a00, 0x4100a00, 0x204, 0x100204, 0xa04, 0x100a04, 0x204, 0x100204, 0xa04, 0x100a04, 0x4000204, 0x4100204, 0x4000a04, 0x4100a04, 0x4000204, 0x4100204, 0x4000a04, 0x4100a04, 0x20000, 0x120000, 0x20800, 0x120800, 0x20000, 0x120000, 0x20800, 0x120800, 0x4020000, 0x4120000, 0x4020800, 0x4120800, 0x4020000, 0x4120000, 0x4020800, 0x4120800, 0x20004, 0x120004, 0x20804, 0x120804, 0x20004, 0x120004, 0x20804, 0x120804, 0x4020004, 0x4120004, 0x4020804, 0x4120804, 0x4020004, 0x4120004, 0x4020804, 0x4120804, 0x20000, 0x120000, 0x20800, 0x120800, 0x20000, 0x120000, 0x20800, 0x120800, 0x4020000, 0x4120000, 0x4020800, 0x4120800, 0x4020000, 0x4120000, 0x4020800, 0x4120800, 0x20004, 0x120004, 0x20804, 0x120804, 0x20004, 0x120004, 0x20804, 0x120804, 0x4020004, 0x4120004, 0x4020804, 0x4120804, 0x4020004, 0x4120004, 0x4020804, 0x4120804, 0x20200, 0x120200, 0x20a00, 0x120a00, 0x20200, 0x120200, 0x20a00, 0x120a00, 0x4020200, 0x4120200, 0x4020a00, 0x4120a00, 0x4020200, 0x4120200, 0x4020a00, 0x4120a00, 0x20204, 0x120204, 0x20a04, 0x120a04, 0x20204, 0x120204, 0x20a04, 0x120a04, 0x4020204, 0x4120204, 0x4020a04, 0x4120a04, 0x4020204, 0x4120204, 0x4020a04, 0x4120a04, 0x20200, 0x120200, 0x20a00, 0x120a00, 0x20200, 0x120200, 0x20a00, 0x120a00, 0x4020200, 0x4120200, 0x4020a00, 0x4120a00, 0x4020200, 0x4120200, 0x4020a00, 0x4120a00, 0x20204, 0x120204, 0x20a04, 0x120a04, 0x20204, 0x120204, 0x20a04, 0x120a04, 0x4020204, 0x4120204, 0x4020a04, 0x4120a04, 0x4020204, 0x4120204, 0x4020a04, 0x4120a04];
        static $pc2mapd3 = [0x0, 0x10000, 0x2000000, 0x2010000, 0x20, 0x10020, 0x2000020, 0x2010020, 0x40000, 0x50000, 0x2040000, 0x2050000, 0x40020, 0x50020, 0x2040020, 0x2050020, 0x2000, 0x12000, 0x2002000, 0x2012000, 0x2020, 0x12020, 0x2002020, 0x2012020, 0x42000, 0x52000, 0x2042000, 0x2052000, 0x42020, 0x52020, 0x2042020, 0x2052020, 0x0, 0x10000, 0x2000000, 0x2010000, 0x20, 0x10020, 0x2000020, 0x2010020, 0x40000, 0x50000, 0x2040000, 0x2050000, 0x40020, 0x50020, 0x2040020, 0x2050020, 0x2000, 0x12000, 0x2002000, 0x2012000, 0x2020, 0x12020, 0x2002020, 0x2012020, 0x42000, 0x52000, 0x2042000, 0x2052000, 0x42020, 0x52020, 0x2042020, 0x2052020, 0x10, 0x10010, 0x2000010, 0x2010010, 0x30, 0x10030, 0x2000030, 0x2010030, 0x40010, 0x50010, 0x2040010, 0x2050010, 0x40030, 0x50030, 0x2040030, 0x2050030, 0x2010, 0x12010, 0x2002010, 0x2012010, 0x2030, 0x12030, 0x2002030, 0x2012030, 0x42010, 0x52010, 0x2042010, 0x2052010, 0x42030, 0x52030, 0x2042030, 0x2052030, 0x10, 0x10010, 0x2000010, 0x2010010, 0x30, 0x10030, 0x2000030, 0x2010030, 0x40010, 0x50010, 0x2040010, 0x2050010, 0x40030, 0x50030, 0x2040030, 0x2050030, 0x2010, 0x12010, 0x2002010, 0x2012010, 0x2030, 0x12030, 0x2002030, 0x2012030, 0x42010, 0x52010, 0x2042010, 0x2052010, 0x42030, 0x52030, 0x2042030, 0x2052030, 0x20000000, 0x20010000, 0x22000000, 0x22010000, 0x20000020, 0x20010020, 0x22000020, 0x22010020, 0x20040000, 0x20050000, 0x22040000, 0x22050000, 0x20040020, 0x20050020, 0x22040020, 0x22050020, 0x20002000, 0x20012000, 0x22002000, 0x22012000, 0x20002020, 0x20012020, 0x22002020, 0x22012020, 0x20042000, 0x20052000, 0x22042000, 0x22052000, 0x20042020, 0x20052020, 0x22042020, 0x22052020, 0x20000000, 0x20010000, 0x22000000, 0x22010000, 0x20000020, 0x20010020, 0x22000020, 0x22010020, 0x20040000, 0x20050000, 0x22040000, 0x22050000, 0x20040020, 0x20050020, 0x22040020, 0x22050020, 0x20002000, 0x20012000, 0x22002000, 0x22012000, 0x20002020, 0x20012020, 0x22002020, 0x22012020, 0x20042000, 0x20052000, 0x22042000, 0x22052000, 0x20042020, 0x20052020, 0x22042020, 0x22052020, 0x20000010, 0x20010010, 0x22000010, 0x22010010, 0x20000030, 0x20010030, 0x22000030, 0x22010030, 0x20040010, 0x20050010, 0x22040010, 0x22050010, 0x20040030, 0x20050030, 0x22040030, 0x22050030, 0x20002010, 0x20012010, 0x22002010, 0x22012010, 0x20002030, 0x20012030, 0x22002030, 0x22012030, 0x20042010, 0x20052010, 0x22042010, 0x22052010, 0x20042030, 0x20052030, 0x22042030, 0x22052030, 0x20000010, 0x20010010, 0x22000010, 0x22010010, 0x20000030, 0x20010030, 0x22000030, 0x22010030, 0x20040010, 0x20050010, 0x22040010, 0x22050010, 0x20040030, 0x20050030, 0x22040030, 0x22050030, 0x20002010, 0x20012010, 0x22002010, 0x22012010, 0x20002030, 0x20012030, 0x22002030, 0x22012030, 0x20042010, 0x20052010, 0x22042010, 0x22052010, 0x20042030, 0x20052030, 0x22042030, 0x22052030];
        static $pc2mapd4 = [0x0, 0x400, 0x1000000, 0x1000400, 0x0, 0x400, 0x1000000, 0x1000400, 0x100, 0x500, 0x1000100, 0x1000500, 0x100, 0x500, 0x1000100, 0x1000500, 0x10000000, 0x10000400, 0x11000000, 0x11000400, 0x10000000, 0x10000400, 0x11000000, 0x11000400, 0x10000100, 0x10000500, 0x11000100, 0x11000500, 0x10000100, 0x10000500, 0x11000100, 0x11000500, 0x80000, 0x80400, 0x1080000, 0x1080400, 0x80000, 0x80400, 0x1080000, 0x1080400, 0x80100, 0x80500, 0x1080100, 0x1080500, 0x80100, 0x80500, 0x1080100, 0x1080500, 0x10080000, 0x10080400, 0x11080000, 0x11080400, 0x10080000, 0x10080400, 0x11080000, 0x11080400, 0x10080100, 0x10080500, 0x11080100, 0x11080500, 0x10080100, 0x10080500, 0x11080100, 0x11080500, 0x8, 0x408, 0x1000008, 0x1000408, 0x8, 0x408, 0x1000008, 0x1000408, 0x108, 0x508, 0x1000108, 0x1000508, 0x108, 0x508, 0x1000108, 0x1000508, 0x10000008, 0x10000408, 0x11000008, 0x11000408, 0x10000008, 0x10000408, 0x11000008, 0x11000408, 0x10000108, 0x10000508, 0x11000108, 0x11000508, 0x10000108, 0x10000508, 0x11000108, 0x11000508, 0x80008, 0x80408, 0x1080008, 0x1080408, 0x80008, 0x80408, 0x1080008, 0x1080408, 0x80108, 0x80508, 0x1080108, 0x1080508, 0x80108, 0x80508, 0x1080108, 0x1080508, 0x10080008, 0x10080408, 0x11080008, 0x11080408, 0x10080008, 0x10080408, 0x11080008, 0x11080408, 0x10080108, 0x10080508, 0x11080108, 0x11080508, 0x10080108, 0x10080508, 0x11080108, 0x11080508, 0x1000, 0x1400, 0x1001000, 0x1001400, 0x1000, 0x1400, 0x1001000, 0x1001400, 0x1100, 0x1500, 0x1001100, 0x1001500, 0x1100, 0x1500, 0x1001100, 0x1001500, 0x10001000, 0x10001400, 0x11001000, 0x11001400, 0x10001000, 0x10001400, 0x11001000, 0x11001400, 0x10001100, 0x10001500, 0x11001100, 0x11001500, 0x10001100, 0x10001500, 0x11001100, 0x11001500, 0x81000, 0x81400, 0x1081000, 0x1081400, 0x81000, 0x81400, 0x1081000, 0x1081400, 0x81100, 0x81500, 0x1081100, 0x1081500, 0x81100, 0x81500, 0x1081100, 0x1081500, 0x10081000, 0x10081400, 0x11081000, 0x11081400, 0x10081000, 0x10081400, 0x11081000, 0x11081400, 0x10081100, 0x10081500, 0x11081100, 0x11081500, 0x10081100, 0x10081500, 0x11081100, 0x11081500, 0x1008, 0x1408, 0x1001008, 0x1001408, 0x1008, 0x1408, 0x1001008, 0x1001408, 0x1108, 0x1508, 0x1001108, 0x1001508, 0x1108, 0x1508, 0x1001108, 0x1001508, 0x10001008, 0x10001408, 0x11001008, 0x11001408, 0x10001008, 0x10001408, 0x11001008, 0x11001408, 0x10001108, 0x10001508, 0x11001108, 0x11001508, 0x10001108, 0x10001508, 0x11001108, 0x11001508, 0x81008, 0x81408, 0x1081008, 0x1081408, 0x81008, 0x81408, 0x1081008, 0x1081408, 0x81108, 0x81508, 0x1081108, 0x1081508, 0x81108, 0x81508, 0x1081108, 0x1081508, 0x10081008, 0x10081408, 0x11081008, 0x11081408, 0x10081008, 0x10081408, 0x11081008, 0x11081408, 0x10081108, 0x10081508, 0x11081108, 0x11081508, 0x10081108, 0x10081508, 0x11081108, 0x11081508];
        $keys = [];
        for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
            // pad the key and remove extra characters as appropriate.
            $key = str_pad(\Phabel\Target\Php80\Polyfill::substr($this->key, $des_round * 8, 8), 8, "\x00");
            // Perform the PC/1 transformation and compute C and D.
            $t = unpack('Nl/Nr', $key);
            list($l, $r) = [$t['l'], $t['r']];
            $key = self::$shuffle[$pc1map[$r & 0xff]] & "\x80\x80\x80\x80\x80\x80\x80\x00" | self::$shuffle[$pc1map[$r >> 8 & 0xff]] & "@@@@@@@\x00" | self::$shuffle[$pc1map[$r >> 16 & 0xff]] & "       \x00" | self::$shuffle[$pc1map[$r >> 24 & 0xff]] & "\x10\x10\x10\x10\x10\x10\x10\x00" | self::$shuffle[$pc1map[$l & 0xff]] & "\x08\x08\x08\x08\x08\x08\x08\x00" | self::$shuffle[$pc1map[$l >> 8 & 0xff]] & "\x04\x04\x04\x04\x04\x04\x04\x00" | self::$shuffle[$pc1map[$l >> 16 & 0xff]] & "\x02\x02\x02\x02\x02\x02\x02\x00" | self::$shuffle[$pc1map[$l >> 24 & 0xff]] & "\x01\x01\x01\x01\x01\x01\x01\x00";
            $key = unpack('Nc/Nd', $key);
            $c = $key['c'] >> 4 & 0xfffffff;
            $d = $key['d'] >> 4 & 0xffffff0 | $key['c'] & 0xf;
            $keys[$des_round] = [self::ENCRYPT => [], self::DECRYPT => array_fill(0, 32, 0)];
            for ($i = 0, $ki = 31; $i < 16; ++$i, $ki -= 2) {
                $c <<= $shifts[$i];
                $c = ($c | $c >> 28) & 0xfffffff;
                $d <<= $shifts[$i];
                $d = ($d | $d >> 28) & 0xfffffff;
                // Perform the PC-2 transformation.
                $cp = $pc2mapc1[$c >> 24] | $pc2mapc2[$c >> 16 & 0xff] | $pc2mapc3[$c >> 8 & 0xff] | $pc2mapc4[$c & 0xff];
                $dp = $pc2mapd1[$d >> 24] | $pc2mapd2[$d >> 16 & 0xff] | $pc2mapd3[$d >> 8 & 0xff] | $pc2mapd4[$d & 0xff];
                // Reorder: odd bytes/even bytes. Push the result in key schedule.
                $val1 = $cp & 0xff000000 | $cp << 8 & 0xff0000 | $dp >> 16 & 0xff00 | $dp >> 8 & 0xff;
                $val2 = $cp << 8 & 0xff000000 | $cp << 16 & 0xff0000 | $dp >> 8 & 0xff00 | $dp & 0xff;
                $keys[$des_round][self::ENCRYPT][] = $val1;
                $keys[$des_round][self::DECRYPT][$ki - 1] = $val1;
                $keys[$des_round][self::ENCRYPT][] = $val2;
                $keys[$des_round][self::DECRYPT][$ki] = $val2;
            }
        }
        switch ($this->des_rounds) {
            case 3:
                // 3DES keys
                $this->keys = [self::ENCRYPT => array_merge($keys[0][self::ENCRYPT], $keys[1][self::DECRYPT], $keys[2][self::ENCRYPT]), self::DECRYPT => array_merge($keys[2][self::DECRYPT], $keys[1][self::ENCRYPT], $keys[0][self::DECRYPT])];
                break;
            // case 1: // DES keys
            default:
                $this->keys = [self::ENCRYPT => $keys[0][self::ENCRYPT], self::DECRYPT => $keys[0][self::DECRYPT]];
        }
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        // Engine configuration for:
        // -  DES ($des_rounds == 1) or
        // - 3DES ($des_rounds == 3)
        $des_rounds = $this->des_rounds;
        $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
            if (!$sbox1) {
                $sbox1 = array_map("intval", self::$sbox1);
                $sbox2 = array_map("intval", self::$sbox2);
                $sbox3 = array_map("intval", self::$sbox3);
                $sbox4 = array_map("intval", self::$sbox4);
                $sbox5 = array_map("intval", self::$sbox5);
                $sbox6 = array_map("intval", self::$sbox6);
                $sbox7 = array_map("intval", self::$sbox7);
                $sbox8 = array_map("intval", self::$sbox8);
                for ($i = 0; $i < 256; ++$i) {
                    $shuffleip[]    =  self::$shuffle[self::$ipmap[$i]];
                    $shuffleinvip[] =  self::$shuffle[self::$invipmap[$i]];
                }
            }
        ';
        $k = [self::ENCRYPT => $this->keys[self::ENCRYPT], self::DECRYPT => $this->keys[self::DECRYPT]];
        $init_encrypt = '';
        $init_decrypt = '';
        // Creating code for en- and decryption.
        $crypt_block = [];
        foreach ([self::ENCRYPT, self::DECRYPT] as $c) {
            /* Do the initial IP permutation. */
            $crypt_block[$c] = '
                $in = unpack("N*", $in);
                $l  = $in[1];
                $r  = $in[2];
                $in = unpack("N*",
                    ($shuffleip[ $r        & 0xFF] & "\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80") |
                    ($shuffleip[($r >>  8) & 0xFF] & "\\x40\\x40\\x40\\x40\\x40\\x40\\x40\\x40") |
                    ($shuffleip[($r >> 16) & 0xFF] & "\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20") |
                    ($shuffleip[($r >> 24) & 0xFF] & "\\x10\\x10\\x10\\x10\\x10\\x10\\x10\\x10") |
                    ($shuffleip[ $l        & 0xFF] & "\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08") |
                    ($shuffleip[($l >>  8) & 0xFF] & "\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04") |
                    ($shuffleip[($l >> 16) & 0xFF] & "\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02") |
                    ($shuffleip[($l >> 24) & 0xFF] & "\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01")
                );
                
                $l = $in[1];
                $r = $in[2];
            ';
            $l = '$l';
            $r = '$r';
            // Perform DES or 3DES.
            for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) {
                // Perform the 16 steps.
                for ($i = 0; $i < 16; ++$i) {
                    // start of "the Feistel (F) function" - see the following URL:
                    // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
                    // Merge key schedule.
                    $crypt_block[$c] .= '
                        $b1 = ((' . $r . ' >>  3) & 0x1FFFFFFF)  ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . ';
                        $b2 = ((' . $r . ' >> 31) & 0x00000001)  ^ (' . $r . ' <<  1) ^ ' . $k[$c][++$ki] . ';' . $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
                                 $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
                                 $sbox5[($b1 >>  8) & 0x3F] ^ $sbox6[($b2 >>  8) & 0x3F] ^
                                 $sbox7[ $b1        & 0x3F] ^ $sbox8[ $b2        & 0x3F] ^ ' . $l . ';
                    ';
                    // end of "the Feistel (F) function"
                    // swap L & R
                    list($l, $r) = [$r, $l];
                }
                list($l, $r) = [$r, $l];
            }
            // Perform the inverse IP permutation.
            $crypt_block[$c] .= '$in =
                ($shuffleinvip[($l >> 24) & 0xFF] & "\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80") |
                ($shuffleinvip[($r >> 24) & 0xFF] & "\\x40\\x40\\x40\\x40\\x40\\x40\\x40\\x40") |
                ($shuffleinvip[($l >> 16) & 0xFF] & "\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20") |
                ($shuffleinvip[($r >> 16) & 0xFF] & "\\x10\\x10\\x10\\x10\\x10\\x10\\x10\\x10") |
                ($shuffleinvip[($l >>  8) & 0xFF] & "\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08") |
                ($shuffleinvip[($r >>  8) & 0xFF] & "\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04") |
                ($shuffleinvip[ $l        & 0xFF] & "\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02") |
                ($shuffleinvip[ $r        & 0xFF] & "\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01");
            ';
        }
        // Creates the inline-crypt function
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => $init_crypt, 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $crypt_block[self::ENCRYPT], 'decrypt_block' => $crypt_block[self::DECRYPT]]);
    }
}<?php

/**
 * "PKCS1" Formatted EC Key Handler
 *
 * PHP version 5
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN DH PARAMETERS-----
 *
 * Technically, PKCS1 is for RSA keys, only, but we're using PKCS1 to describe
 * DSA, whose format isn't really formally described anywhere, so might as well
 * use it to describe this, too.
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
/**
 * "PKCS1" Formatted DH Key Handler
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends Progenitor
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $key = parent::load($key, $password);
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $components = ASN1::asn1map($decoded[0], Maps\DHParameter::MAP);
        if (!is_array($components)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping on parameters');
        }
        return $components;
    }
    /**
     * Convert EC parameters to the appropriate format
     *
     * @access public
     * @return string
     */
    public static function saveParameters(BigInteger $prime, BigInteger $base, array $options = [])
    {
        $params = ['prime' => $prime, 'base' => $base];
        $params = ASN1::encodeDER($params, Maps\DHParameter::MAP);
        return "-----BEGIN DH PARAMETERS-----\r\n" . chunk_split(base64_encode($params), 64) . "-----END DH PARAMETERS-----\r\n";
    }
}<?php

/**
 * PKCS#8 Formatted DH Key Handler
 *
 * PHP version 5
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted DH Key Handler
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends Progenitor
{
    /**
     * OID Name
     *
     * @var string
     * @access private
     */
    const OID_NAME = 'dhKeyAgreement';
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = '1.2.840.113549.1.3.1';
    /**
     * Child OIDs loaded
     *
     * @var bool
     * @access private
     */
    protected static $childOIDsLoaded = false;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $isPublic = strpos($key, 'PUBLIC') !== false;
        $key = parent::load($key, $password);
        $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
        switch (true) {
            case !$isPublic && $type == 'publicKey':
                throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
            case $isPublic && $type == 'privateKey':
                throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
        }
        $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER of parameters');
        }
        $components = ASN1::asn1map($decoded[0], Maps\DHParameter::MAP);
        if (!is_array($components)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping on parameters');
        }
        $decoded = ASN1::decodeBER($key[$type]);
        switch (true) {
            case empty($decoded):
            case !is_array($decoded):
            case !isset($decoded[0]['content']):
            case !$decoded[0]['content'] instanceof BigInteger:
                throw new \RuntimeException('Unable to decode BER of parameters');
        }
        $components[$type] = $decoded[0]['content'];
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $prime
     * @param \phpseclib3\Math\BigInteger $base
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Math\BigInteger $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $prime, BigInteger $base, BigInteger $privateKey, BigInteger $publicKey, $password = '', array $options = [])
    {
        $params = ['prime' => $prime, 'base' => $base];
        $params = ASN1::encodeDER($params, Maps\DHParameter::MAP);
        $params = new ASN1\Element($params);
        $key = ASN1::encodeDER($privateKey, ['type' => ASN1::TYPE_INTEGER]);
        return self::wrapPrivateKey($key, [], $params, $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $prime
     * @param \phpseclib3\Math\BigInteger $base
     * @param \phpseclib3\Math\BigInteger $publicKey
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $prime, BigInteger $base, BigInteger $publicKey, array $options = [])
    {
        $params = ['prime' => $prime, 'base' => $base];
        $params = ASN1::encodeDER($params, Maps\DHParameter::MAP);
        $params = new ASN1\Element($params);
        $key = ASN1::encodeDER($publicKey, ['type' => ASN1::TYPE_INTEGER]);
        return self::wrapPublicKey($key, $params);
    }
}<?php

/**
 * DH Parameters
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH;

use phpseclib3\Crypt\DH;
/**
 * DH Parameters
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Parameters extends DH
{
    /**
     * Returns the parameters
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type = 'PKCS1', array $options = [])
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        return $type::saveParameters($this->prime, $this->base, $options);
    }
}<?php

/**
 * DH Private Key
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH;

use phpseclib3\Crypt\DH;
use phpseclib3\Crypt\Common;
/**
 * DH Private Key
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrivateKey extends DH
{
    use Common\Traits\PasswordProtected;
    /**
     * Private Key
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $privateKey;
    /**
     * Public Key
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $publicKey;
    /**
     * Returns the public key
     *
     * @access public
     * @return DH\PublicKey
     */
    public function getPublicKey()
    {
        $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey');
        if (!isset($this->publicKey)) {
            $this->publicKey = $this->base->powMod($this->privateKey, $this->prime);
        }
        $key = $type::savePublicKey($this->prime, $this->base, $this->publicKey);
        return DH::loadFormat('PKCS8', $key);
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePrivateKey');
        if (!isset($this->publicKey)) {
            $this->publicKey = $this->base->powMod($this->privateKey, $this->prime);
        }
        return $type::savePrivateKey($this->prime, $this->base, $this->privateKey, $this->publicKey, $this->password, $options);
    }
}<?php

/**
 * DH Public Key
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH;

use phpseclib3\Crypt\DH;
use phpseclib3\Crypt\Common;
/**
 * DH Public Key
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PublicKey extends DH
{
    use Common\Traits\Fingerprint;
    /**
     * Returns the public key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePublicKey');
        return $type::savePublicKey($this->prime, $this->base, $this->publicKey, $options);
    }
    /**
     * Returns the public key as a BigInteger
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function toBigInteger()
    {
        return $this->publicKey;
    }
}<?php

/**
 * Pure-PHP implementation of Rijndael.
 *
 * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits.  If
 * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
 * {@link self::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's
 * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
 * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
 *
 * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length.  mcrypt, for example,
 * does not.  AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
 * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224.  Indeed, 160 and 224
 * are first defined as valid key / block lengths in
 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
 * Extensions: Other block and Cipher Key lengths.
 * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
 *
 * {@internal The variable names are the same as those in
 * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $rijndael = new \phpseclib3\Crypt\Rijndael('ctr');
 *
 *    $rijndael->setKey('abcdefghijklmnop');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $rijndael->decrypt($rijndael->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Rijndael
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2008 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\BadModeException;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Exception\InconsistentSetupException;
use phpseclib3\Exception\BadDecryptionException;
/**
 * Pure-PHP implementation of Rijndael.
 *
 * @package Rijndael
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Rijndael extends BlockCipher
{
    /**
     * The mcrypt specific name of the cipher
     *
     * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
     * \phpseclib3\Crypt\Rijndael determines automatically whether mcrypt is useable
     * or not for the current $block_size/$key_length.
     * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @see \phpseclib3\Crypt\Common\SymmetricKey::engine
     * @see self::isValidEngine()
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'rijndael-128';
    /**
     * The Key Schedule
     *
     * @see self::setup()
     * @var array
     * @access private
     */
    private $w;
    /**
     * The Inverse Key Schedule
     *
     * @see self::setup()
     * @var array
     * @access private
     */
    private $dw;
    /**
     * The Block Length divided by 32
     *
     * {@internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4.  Exists in conjunction with $block_size
     *    because the encryption / decryption / key schedule creation requires this number and not $block_size.  We could
     *    derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
     *    of that, we'll just precompute it once.}
     *
     * @see self::setBlockLength()
     * @var int
     * @access private
     */
    private $Nb = 4;
    /**
     * The Key Length (in bytes)
     *
     * {@internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $Nk
     *    because the encryption / decryption / key schedule creation requires this number and not $key_length.  We could
     *    derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
     *    of that, we'll just precompute it once.}
     *
     * @see self::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 16;
    /**
     * The Key Length divided by 32
     *
     * @see self::setKeyLength()
     * @var int
     * @access private
     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
     */
    private $Nk = 4;
    /**
     * The Number of Rounds
     *
     * {@internal The max value is 14, the min value is 10.}
     *
     * @var int
     * @access private
     */
    private $Nr;
    /**
     * Shift offsets
     *
     * @var array
     * @access private
     */
    private $c;
    /**
     * Holds the last used key- and block_size information
     *
     * @var array
     * @access private
     */
    private $kl;
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws \InvalidArgumentException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new BadModeException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
    * Sets the key length.
    *
    * Valid key lengths are 128, 160, 192, 224, and 256.
    *
    * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
    and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
    192/256 bits as, for example, mcrypt will do.
    *
    * That said, if you want be compatible with other Rijndael and AES implementations,
    you should not setKeyLength(160) or setKeyLength(224).
    *
    * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
    the mcrypt php extension, even if available.
    This results then in slower encryption.
    *
    * @access public
    * @throws \LengthException if the key length is invalid
    * @param int $length
    */
    public function setKeyLength($length)
    {
        switch ($length) {
            case 128:
            case 160:
            case 192:
            case 224:
            case 256:
                $this->key_length = $length >> 3;
                break;
            default:
                throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported');
        }
        parent::setKeyLength($length);
    }
    /**
     * Sets the key.
     *
     * Rijndael supports five different key lengths
     *
     * @see setKeyLength()
     * @access public
     * @param string $key
     * @throws \LengthException if the key length isn't supported
     */
    public function setKey($key)
    {
        switch (strlen($key)) {
            case 16:
            case 20:
            case 24:
            case 28:
            case 32:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 20, 24, 28 or 32 are supported');
        }
        parent::setKey($key);
    }
    /**
     * Sets the block length
     *
     * Valid block lengths are 128, 160, 192, 224, and 256.
     *
     * @access public
     * @param int $length
     */
    public function setBlockLength($length)
    {
        switch ($length) {
            case 128:
            case 160:
            case 192:
            case 224:
            case 256:
                break;
            default:
                throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported');
        }
        $this->Nb = $length >> 5;
        $this->block_size = $length >> 3;
        $this->changed = $this->nonIVChanged = true;
        $this->setEngine();
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        switch ($engine) {
            case self::ENGINE_LIBSODIUM:
                return function_exists('sodium_crypto_aead_aes256gcm_is_available') && sodium_crypto_aead_aes256gcm_is_available() && $this->mode == self::MODE_GCM && $this->key_length == 32 && $this->nonce && strlen($this->nonce) == 12 && $this->block_size == 16;
            case self::ENGINE_OPENSSL_GCM:
                if (!extension_loaded('openssl')) {
                    return false;
                }
                $methods = openssl_get_cipher_methods();
                return $this->mode == self::MODE_GCM && version_compare(PHP_VERSION, '7.1.0', '>=') && in_array('aes-' . $this->getKeyLength() . '-gcm', $methods) && $this->block_size == 16;
            case self::ENGINE_OPENSSL:
                if ($this->block_size != 16) {
                    return false;
                }
                $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
                $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->openssl_translate_mode();
                break;
            case self::ENGINE_MCRYPT:
                $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
                if ($this->key_length % 8) {
                    // is it a 160/224-bit key?
                    // mcrypt is not usable for them, only for 128/192/256-bit keys
                    return false;
                }
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Encrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        static $tables;
        if (empty($tables)) {
            $tables =& $this->getTables();
        }
        $t0 = $tables[0];
        $t1 = $tables[1];
        $t2 = $tables[2];
        $t3 = $tables[3];
        $sbox = $tables[4];
        $state = [];
        $words = unpack('N*', $in);
        $c = $this->c;
        $w = $this->w;
        $Nb = $this->Nb;
        $Nr = $this->Nr;
        // addRoundKey
        $wc = $Nb - 1;
        foreach ($words as $word) {
            $state[] = $word ^ $w[++$wc];
        }
        // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
        // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
        // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
        // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
        // Unfortunately, the description given there is not quite correct.  Per aes.spec.v316.pdf#page=19 [1],
        // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
        // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
        $temp = [];
        for ($round = 1; $round < $Nr; ++$round) {
            $i = 0;
            // $c[0] == 0
            $j = $c[1];
            $k = $c[2];
            $l = $c[3];
            while ($i < $Nb) {
                $temp[$i] = $t0[$state[$i] >> 24 & 0xff] ^ $t1[$state[$j] >> 16 & 0xff] ^ $t2[$state[$k] >> 8 & 0xff] ^ $t3[$state[$l] & 0xff] ^ $w[++$wc];
                ++$i;
                $j = ($j + 1) % $Nb;
                $k = ($k + 1) % $Nb;
                $l = ($l + 1) % $Nb;
            }
            $state = $temp;
        }
        // subWord
        for ($i = 0; $i < $Nb; ++$i) {
            $state[$i] = $sbox[$state[$i] & 0xff] | $sbox[$state[$i] >> 8 & 0xff] << 8 | $sbox[$state[$i] >> 16 & 0xff] << 16 | $sbox[$state[$i] >> 24 & 0xff] << 24;
        }
        // shiftRows + addRoundKey
        $i = 0;
        // $c[0] == 0
        $j = $c[1];
        $k = $c[2];
        $l = $c[3];
        while ($i < $Nb) {
            $temp[$i] = $state[$i] & 0xff000000 ^ $state[$j] & 0xff0000 ^ $state[$k] & 0xff00 ^ $state[$l] & 0xff ^ $w[$i];
            ++$i;
            $j = ($j + 1) % $Nb;
            $k = ($k + 1) % $Nb;
            $l = ($l + 1) % $Nb;
        }
        return pack('N*', ...$temp);
    }
    /**
     * Decrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        static $invtables;
        if (empty($invtables)) {
            $invtables =& $this->getInvTables();
        }
        $dt0 = $invtables[0];
        $dt1 = $invtables[1];
        $dt2 = $invtables[2];
        $dt3 = $invtables[3];
        $isbox = $invtables[4];
        $state = [];
        $words = unpack('N*', $in);
        $c = $this->c;
        $dw = $this->dw;
        $Nb = $this->Nb;
        $Nr = $this->Nr;
        // addRoundKey
        $wc = $Nb - 1;
        foreach ($words as $word) {
            $state[] = $word ^ $dw[++$wc];
        }
        $temp = [];
        for ($round = $Nr - 1; $round > 0; --$round) {
            $i = 0;
            // $c[0] == 0
            $j = $Nb - $c[1];
            $k = $Nb - $c[2];
            $l = $Nb - $c[3];
            while ($i < $Nb) {
                $temp[$i] = $dt0[$state[$i] >> 24 & 0xff] ^ $dt1[$state[$j] >> 16 & 0xff] ^ $dt2[$state[$k] >> 8 & 0xff] ^ $dt3[$state[$l] & 0xff] ^ $dw[++$wc];
                ++$i;
                $j = ($j + 1) % $Nb;
                $k = ($k + 1) % $Nb;
                $l = ($l + 1) % $Nb;
            }
            $state = $temp;
        }
        // invShiftRows + invSubWord + addRoundKey
        $i = 0;
        // $c[0] == 0
        $j = $Nb - $c[1];
        $k = $Nb - $c[2];
        $l = $Nb - $c[3];
        while ($i < $Nb) {
            $word = $state[$i] & 0xff000000 | $state[$j] & 0xff0000 | $state[$k] & 0xff00 | $state[$l] & 0xff;
            $temp[$i] = $dw[$i] ^ ($isbox[$word & 0xff] | $isbox[$word >> 8 & 0xff] << 8 | $isbox[$word >> 16 & 0xff] << 16 | $isbox[$word >> 24 & 0xff] << 24);
            ++$i;
            $j = ($j + 1) % $Nb;
            $k = ($k + 1) % $Nb;
            $l = ($l + 1) % $Nb;
        }
        return pack('N*', ...$temp);
    }
    /**
    * Setup the self::ENGINE_INTERNAL $engine
    *
    * (re)init, if necessary, the internal cipher $engine and flush all $buffers
    Used (only) if $engine == self::ENGINE_INTERNAL
    *
    * _setup() will be called each time if $changed === true
    typically this happens when using one or more of following public methods:
    *
    * - setKey()
    *
    * - setIV()
    *
    * - disableContinuousBuffer()
    *
    * - First run of encrypt() / decrypt() with no init-settings
    *
    * {@internal setup() is always called before en/decryption.}
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::setKey()
    * @see self::setIV()
    * @see self::disableContinuousBuffer()
    * @access private
    */
    protected function setup()
    {
        if (!$this->changed) {
            return;
        }
        parent::setup();
        if (is_string($this->iv) && strlen($this->iv) != $this->block_size) {
            throw new InconsistentSetupException('The IV length (' . strlen($this->iv) . ') does not match the block size (' . $this->block_size . ')');
        }
    }
    /**
     * Setup the key (expansion)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
     * @access private
     */
    protected function setupKey()
    {
        // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
        // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
        static $rcon = [0, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000, 0x2f000000, 0x5e000000, 0xbc000000, 0x63000000, 0xc6000000, 0x97000000, 0x35000000, 0x6a000000, 0xd4000000, 0xb3000000, 0x7d000000, 0xfa000000, 0xef000000, 0xc5000000, 0x91000000];
        if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
            // already expanded
            return;
        }
        $this->kl = ['key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size];
        $this->Nk = $this->key_length >> 2;
        // see Rijndael-ammended.pdf#page=44
        $this->Nr = max($this->Nk, $this->Nb) + 6;
        // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
        //     "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
        // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
        //     "Table 2: Shift offsets for different block lengths"
        switch ($this->Nb) {
            case 4:
            case 5:
            case 6:
                $this->c = [0, 1, 2, 3];
                break;
            case 7:
                $this->c = [0, 1, 2, 4];
                break;
            case 8:
                $this->c = [0, 1, 3, 4];
        }
        $w = array_values(unpack('N*words', $this->key));
        $length = $this->Nb * ($this->Nr + 1);
        for ($i = $this->Nk; $i < $length; $i++) {
            $temp = $w[$i - 1];
            if ($i % $this->Nk == 0) {
                // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
                // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
                // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
                // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
                $temp = $temp << 8 & 0xffffff00 | $temp >> 24 & 0xff;
                // rotWord
                $temp = $this->subWord($temp) ^ $rcon[$i / $this->Nk];
            } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
                $temp = $this->subWord($temp);
            }
            $w[$i] = $w[$i - $this->Nk] ^ $temp;
        }
        // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
        // and generate the inverse key schedule.  more specifically,
        // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
        // "The key expansion for the Inverse Cipher is defined as follows:
        //        1. Apply the Key Expansion.
        //        2. Apply InvMixColumn to all Round Keys except the first and the last one."
        // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
        list($dt0, $dt1, $dt2, $dt3) = $this->getInvTables();
        $temp = $this->w = $this->dw = [];
        for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
            if ($col == $this->Nb) {
                if ($row == 0) {
                    $this->dw[0] = $this->w[0];
                } else {
                    // subWord + invMixColumn + invSubWord = invMixColumn
                    $j = 0;
                    while ($j < $this->Nb) {
                        $dw = $this->subWord($this->w[$row][$j]);
                        $temp[$j] = $dt0[$dw >> 24 & 0xff] ^ $dt1[$dw >> 16 & 0xff] ^ $dt2[$dw >> 8 & 0xff] ^ $dt3[$dw & 0xff];
                        $j++;
                    }
                    $this->dw[$row] = $temp;
                }
                $col = 0;
                $row++;
            }
            $this->w[$row][$col] = $w[$i];
        }
        $this->dw[$row] = $this->w[$row];
        // Converting to 1-dim key arrays (both ascending)
        $this->dw = array_reverse($this->dw);
        $w = array_pop($this->w);
        $dw = array_pop($this->dw);
        foreach ($this->w as $r => $wr) {
            foreach ($wr as $c => $wc) {
                $w[] = $wc;
                $dw[] = $this->dw[$r][$c];
            }
        }
        $this->w = $w;
        $this->dw = $dw;
    }
    /**
     * Performs S-Box substitutions
     *
     * @return array
     * @access private
     * @param int $word
     */
    private function subWord($word)
    {
        static $sbox;
        if (empty($sbox)) {
            list(, , , , $sbox) = self::getTables();
        }
        return $sbox[$word & 0xff] | $sbox[$word >> 8 & 0xff] << 8 | $sbox[$word >> 16 & 0xff] << 16 | $sbox[$word >> 24 & 0xff] << 24;
    }
    /**
     * Provides the mixColumns and sboxes tables
     *
     * @see self::encryptBlock()
     * @see self::setupInlineCrypt()
     * @see self::subWord()
     * @access private
     * @return array &$tables
     */
    protected function &getTables()
    {
        static $tables;
        if (empty($tables)) {
            // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
            // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
            // those are the names we'll use.
            $t3 = array_map('intval', [
                // with array_map('intval', ...) we ensure we have only int's and not
                // some slower floats converted by php automatically on high values
                0x6363a5c6,
                0x7c7c84f8,
                0x777799ee,
                0x7b7b8df6,
                0xf2f20dff,
                0x6b6bbdd6,
                0x6f6fb1de,
                0xc5c55491,
                0x30305060,
                0x1010302,
                0x6767a9ce,
                0x2b2b7d56,
                0xfefe19e7,
                0xd7d762b5,
                0xababe64d,
                0x76769aec,
                0xcaca458f,
                0x82829d1f,
                0xc9c94089,
                0x7d7d87fa,
                0xfafa15ef,
                0x5959ebb2,
                0x4747c98e,
                0xf0f00bfb,
                0xadadec41,
                0xd4d467b3,
                0xa2a2fd5f,
                0xafafea45,
                0x9c9cbf23,
                0xa4a4f753,
                0x727296e4,
                0xc0c05b9b,
                0xb7b7c275,
                0xfdfd1ce1,
                0x9393ae3d,
                0x26266a4c,
                0x36365a6c,
                0x3f3f417e,
                0xf7f702f5,
                0xcccc4f83,
                0x34345c68,
                0xa5a5f451,
                0xe5e534d1,
                0xf1f108f9,
                0x717193e2,
                0xd8d873ab,
                0x31315362,
                0x15153f2a,
                0x4040c08,
                0xc7c75295,
                0x23236546,
                0xc3c35e9d,
                0x18182830,
                0x9696a137,
                0x5050f0a,
                0x9a9ab52f,
                0x707090e,
                0x12123624,
                0x80809b1b,
                0xe2e23ddf,
                0xebeb26cd,
                0x2727694e,
                0xb2b2cd7f,
                0x75759fea,
                0x9091b12,
                0x83839e1d,
                0x2c2c7458,
                0x1a1a2e34,
                0x1b1b2d36,
                0x6e6eb2dc,
                0x5a5aeeb4,
                0xa0a0fb5b,
                0x5252f6a4,
                0x3b3b4d76,
                0xd6d661b7,
                0xb3b3ce7d,
                0x29297b52,
                0xe3e33edd,
                0x2f2f715e,
                0x84849713,
                0x5353f5a6,
                0xd1d168b9,
                0x0,
                0xeded2cc1,
                0x20206040,
                0xfcfc1fe3,
                0xb1b1c879,
                0x5b5bedb6,
                0x6a6abed4,
                0xcbcb468d,
                0xbebed967,
                0x39394b72,
                0x4a4ade94,
                0x4c4cd498,
                0x5858e8b0,
                0xcfcf4a85,
                0xd0d06bbb,
                0xefef2ac5,
                0xaaaae54f,
                0xfbfb16ed,
                0x4343c586,
                0x4d4dd79a,
                0x33335566,
                0x85859411,
                0x4545cf8a,
                0xf9f910e9,
                0x2020604,
                0x7f7f81fe,
                0x5050f0a0,
                0x3c3c4478,
                0x9f9fba25,
                0xa8a8e34b,
                0x5151f3a2,
                0xa3a3fe5d,
                0x4040c080,
                0x8f8f8a05,
                0x9292ad3f,
                0x9d9dbc21,
                0x38384870,
                0xf5f504f1,
                0xbcbcdf63,
                0xb6b6c177,
                0xdada75af,
                0x21216342,
                0x10103020,
                0xffff1ae5,
                0xf3f30efd,
                0xd2d26dbf,
                0xcdcd4c81,
                0xc0c1418,
                0x13133526,
                0xecec2fc3,
                0x5f5fe1be,
                0x9797a235,
                0x4444cc88,
                0x1717392e,
                0xc4c45793,
                0xa7a7f255,
                0x7e7e82fc,
                0x3d3d477a,
                0x6464acc8,
                0x5d5de7ba,
                0x19192b32,
                0x737395e6,
                0x6060a0c0,
                0x81819819,
                0x4f4fd19e,
                0xdcdc7fa3,
                0x22226644,
                0x2a2a7e54,
                0x9090ab3b,
                0x8888830b,
                0x4646ca8c,
                0xeeee29c7,
                0xb8b8d36b,
                0x14143c28,
                0xdede79a7,
                0x5e5ee2bc,
                0xb0b1d16,
                0xdbdb76ad,
                0xe0e03bdb,
                0x32325664,
                0x3a3a4e74,
                0xa0a1e14,
                0x4949db92,
                0x6060a0c,
                0x24246c48,
                0x5c5ce4b8,
                0xc2c25d9f,
                0xd3d36ebd,
                0xacacef43,
                0x6262a6c4,
                0x9191a839,
                0x9595a431,
                0xe4e437d3,
                0x79798bf2,
                0xe7e732d5,
                0xc8c8438b,
                0x3737596e,
                0x6d6db7da,
                0x8d8d8c01,
                0xd5d564b1,
                0x4e4ed29c,
                0xa9a9e049,
                0x6c6cb4d8,
                0x5656faac,
                0xf4f407f3,
                0xeaea25cf,
                0x6565afca,
                0x7a7a8ef4,
                0xaeaee947,
                0x8081810,
                0xbabad56f,
                0x787888f0,
                0x25256f4a,
                0x2e2e725c,
                0x1c1c2438,
                0xa6a6f157,
                0xb4b4c773,
                0xc6c65197,
                0xe8e823cb,
                0xdddd7ca1,
                0x74749ce8,
                0x1f1f213e,
                0x4b4bdd96,
                0xbdbddc61,
                0x8b8b860d,
                0x8a8a850f,
                0x707090e0,
                0x3e3e427c,
                0xb5b5c471,
                0x6666aacc,
                0x4848d890,
                0x3030506,
                0xf6f601f7,
                0xe0e121c,
                0x6161a3c2,
                0x35355f6a,
                0x5757f9ae,
                0xb9b9d069,
                0x86869117,
                0xc1c15899,
                0x1d1d273a,
                0x9e9eb927,
                0xe1e138d9,
                0xf8f813eb,
                0x9898b32b,
                0x11113322,
                0x6969bbd2,
                0xd9d970a9,
                0x8e8e8907,
                0x9494a733,
                0x9b9bb62d,
                0x1e1e223c,
                0x87879215,
                0xe9e920c9,
                0xcece4987,
                0x5555ffaa,
                0x28287850,
                0xdfdf7aa5,
                0x8c8c8f03,
                0xa1a1f859,
                0x89898009,
                0xd0d171a,
                0xbfbfda65,
                0xe6e631d7,
                0x4242c684,
                0x6868b8d0,
                0x4141c382,
                0x9999b029,
                0x2d2d775a,
                0xf0f111e,
                0xb0b0cb7b,
                0x5454fca8,
                0xbbbbd66d,
                0x16163a2c,
            ]);
            foreach ($t3 as $t3i) {
                $t0[] = $t3i << 24 & 0xff000000 | $t3i >> 8 & 0xffffff;
                $t1[] = $t3i << 16 & 0xffff0000 | $t3i >> 16 & 0xffff;
                $t2[] = $t3i << 8 & 0xffffff00 | $t3i >> 24 & 0xff;
            }
            $tables = [
                // The Precomputed mixColumns tables t0 - t3
                $t0,
                $t1,
                $t2,
                $t3,
                // The SubByte S-Box
                [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x1, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x4, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x5, 0x9a, 0x7, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x9, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x0, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x2, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0xc, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0xb, 0xdb, 0xe0, 0x32, 0x3a, 0xa, 0x49, 0x6, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x8, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x3, 0xf6, 0xe, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0xd, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0xf, 0xb0, 0x54, 0xbb, 0x16],
            ];
        }
        return $tables;
    }
    /**
     * Provides the inverse mixColumns and inverse sboxes tables
     *
     * @see self::decryptBlock()
     * @see self::setupInlineCrypt()
     * @see self::setupKey()
     * @access private
     * @return array &$tables
     */
    protected function &getInvTables()
    {
        static $tables;
        if (empty($tables)) {
            $dt3 = array_map('intval', [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x24c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x82b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x36aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x7f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x5bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x6d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x0, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0xefffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0xfd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0xa67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x90d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x1269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x4984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0xb412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0xd9541ff, 0xa8017139, 0xcb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0]);
            foreach ($dt3 as $dt3i) {
                $dt0[] = $dt3i << 24 & 0xff000000 | $dt3i >> 8 & 0xffffff;
                $dt1[] = $dt3i << 16 & 0xffff0000 | $dt3i >> 16 & 0xffff;
                $dt2[] = $dt3i << 8 & 0xffffff00 | $dt3i >> 24 & 0xff;
            }
            $tables = [
                // The Precomputed inverse mixColumns tables dt0 - dt3
                $dt0,
                $dt1,
                $dt2,
                $dt3,
                // The inverse SubByte S-Box
                [0x52, 0x9, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0xb, 0x42, 0xfa, 0xc3, 0x4e, 0x8, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x0, 0x8c, 0xbc, 0xd3, 0xa, 0xf7, 0xe4, 0x58, 0x5, 0xb8, 0xb3, 0x45, 0x6, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0xf, 0x2, 0xc1, 0xaf, 0xbd, 0x3, 0x1, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0xe, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x7, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0xd, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x4, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0xc, 0x7d],
            ];
        }
        return $tables;
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        $w = $this->w;
        $dw = $this->dw;
        $init_encrypt = '';
        $init_decrypt = '';
        $Nr = $this->Nr;
        $Nb = $this->Nb;
        $c = $this->c;
        // Generating encrypt code:
        $init_encrypt .= '
            static $tables;
            if (empty($tables)) {
                $tables = &$this->getTables();
            }
            $t0   = $tables[0];
            $t1   = $tables[1];
            $t2   = $tables[2];
            $t3   = $tables[3];
            $sbox = $tables[4];
        ';
        $s = 'e';
        $e = 's';
        $wc = $Nb - 1;
        // Preround: addRoundKey
        $encrypt_block = '$in = unpack("N*", $in);
';
        for ($i = 0; $i < $Nb; ++$i) {
            $encrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $w[++$wc] . ";\n";
        }
        // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
        for ($round = 1; $round < $Nr; ++$round) {
            list($s, $e) = [$e, $s];
            for ($i = 0; $i < $Nb; ++$i) {
                $encrypt_block .= '$' . $e . $i . ' =
                    $t0[($' . $s . $i . ' >> 24) & 0xff] ^
                    $t1[($' . $s . ($i + $c[1]) % $Nb . ' >> 16) & 0xff] ^
                    $t2[($' . $s . ($i + $c[2]) % $Nb . ' >>  8) & 0xff] ^
                    $t3[ $' . $s . ($i + $c[3]) % $Nb . '        & 0xff] ^
                    ' . $w[++$wc] . ";\n";
            }
        }
        // Finalround: subWord + shiftRows + addRoundKey
        for ($i = 0; $i < $Nb; ++$i) {
            $encrypt_block .= '$' . $e . $i . ' =
                 $sbox[ $' . $e . $i . '        & 0xff]        |
                ($sbox[($' . $e . $i . ' >>  8) & 0xff] <<  8) |
                ($sbox[($' . $e . $i . ' >> 16) & 0xff] << 16) |
                ($sbox[($' . $e . $i . ' >> 24) & 0xff] << 24);
';
        }
        $encrypt_block .= '$in = pack("N*"
';
        for ($i = 0; $i < $Nb; ++$i) {
            $encrypt_block .= ',
                ($' . $e . $i . ' & ' . (int) 0xff000000 . ') ^
                ($' . $e . ($i + $c[1]) % $Nb . ' &         0x00FF0000   ) ^
                ($' . $e . ($i + $c[2]) % $Nb . ' &         0x0000FF00   ) ^
                ($' . $e . ($i + $c[3]) % $Nb . ' &         0x000000FF   ) ^
                ' . $w[$i] . "\n";
        }
        $encrypt_block .= ');';
        // Generating decrypt code:
        $init_decrypt .= '
            static $invtables;
            if (empty($invtables)) {
                $invtables = &$this->getInvTables();
            }
            $dt0   = $invtables[0];
            $dt1   = $invtables[1];
            $dt2   = $invtables[2];
            $dt3   = $invtables[3];
            $isbox = $invtables[4];
        ';
        $s = 'e';
        $e = 's';
        $wc = $Nb - 1;
        // Preround: addRoundKey
        $decrypt_block = '$in = unpack("N*", $in);
';
        for ($i = 0; $i < $Nb; ++$i) {
            $decrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $dw[++$wc] . ';
';
        }
        // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
        for ($round = 1; $round < $Nr; ++$round) {
            list($s, $e) = [$e, $s];
            for ($i = 0; $i < $Nb; ++$i) {
                $decrypt_block .= '$' . $e . $i . ' =
                    $dt0[($' . $s . $i . ' >> 24) & 0xff] ^
                    $dt1[($' . $s . ($Nb + $i - $c[1]) % $Nb . ' >> 16) & 0xff] ^
                    $dt2[($' . $s . ($Nb + $i - $c[2]) % $Nb . ' >>  8) & 0xff] ^
                    $dt3[ $' . $s . ($Nb + $i - $c[3]) % $Nb . '        & 0xff] ^
                    ' . $dw[++$wc] . ";\n";
            }
        }
        // Finalround: subWord + shiftRows + addRoundKey
        for ($i = 0; $i < $Nb; ++$i) {
            $decrypt_block .= '$' . $e . $i . ' =
                 $isbox[ $' . $e . $i . '        & 0xff]        |
                ($isbox[($' . $e . $i . ' >>  8) & 0xff] <<  8) |
                ($isbox[($' . $e . $i . ' >> 16) & 0xff] << 16) |
                ($isbox[($' . $e . $i . ' >> 24) & 0xff] << 24);
';
        }
        $decrypt_block .= '$in = pack("N*"
';
        for ($i = 0; $i < $Nb; ++$i) {
            $decrypt_block .= ',
                ($' . $e . $i . ' & ' . (int) 0xff000000 . ') ^
                ($' . $e . ($Nb + $i - $c[1]) % $Nb . ' &         0x00FF0000   ) ^
                ($' . $e . ($Nb + $i - $c[2]) % $Nb . ' &         0x0000FF00   ) ^
                ($' . $e . ($Nb + $i - $c[3]) % $Nb . ' &         0x000000FF   ) ^
                ' . $dw[$i] . "\n";
        }
        $decrypt_block .= ');';
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => '', 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block]);
    }
    /**
     * Encrypts a message.
     *
     * @see self::decrypt()
     * @see parent::encrypt()
     * @access public
     * @param string $plaintext
     * @return string
     */
    public function encrypt($plaintext)
    {
        $this->setup();
        switch ($this->engine) {
            case self::ENGINE_LIBSODIUM:
                $this->newtag = sodium_crypto_aead_aes256gcm_encrypt($plaintext, $this->aad, $this->nonce, $this->key);
                return Strings::shift($this->newtag, strlen($plaintext));
            case self::ENGINE_OPENSSL_GCM:
                return openssl_encrypt($plaintext, 'aes-' . $this->getKeyLength() . '-gcm', $this->key, OPENSSL_RAW_DATA, $this->nonce, $this->newtag, $this->aad);
        }
        return parent::encrypt($plaintext);
    }
    /**
     * Decrypts a message.
     *
     * @see self::encrypt()
     * @see parent::decrypt()
     * @access public
     * @param string $ciphertext
     * @return string
     */
    public function decrypt($ciphertext)
    {
        $this->setup();
        switch ($this->engine) {
            case self::ENGINE_LIBSODIUM:
                if ($this->oldtag === false) {
                    throw new InsufficientSetupException('Authentication Tag has not been set');
                }
                if (strlen($this->oldtag) != 16) {
                    break;
                }
                $plaintext = sodium_crypto_aead_aes256gcm_decrypt($ciphertext . $this->oldtag, $this->aad, $this->nonce, $this->key);
                if ($plaintext === false) {
                    $this->oldtag = false;
                    throw new BadDecryptionException('Error decrypting ciphertext with libsodium');
                }
                return $plaintext;
            case self::ENGINE_OPENSSL_GCM:
                if ($this->oldtag === false) {
                    throw new InsufficientSetupException('Authentication Tag has not been set');
                }
                $plaintext = openssl_decrypt($ciphertext, 'aes-' . $this->getKeyLength() . '-gcm', $this->key, OPENSSL_RAW_DATA, $this->nonce, $this->oldtag, $this->aad);
                if ($plaintext === false) {
                    $this->oldtag = false;
                    throw new BadDecryptionException('Error decrypting ciphertext with OpenSSL');
                }
                return $plaintext;
        }
        return parent::decrypt($ciphertext);
    }
}<?php

/**
 * libsodium Key Handler
 *
 * Different NaCl implementations store the key differently.
 * https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/ elaborates.
 * libsodium appears to use the same format as SUPERCOP.
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * libsodium Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class libsodium
{
    use Common;
    /**
     * Is invisible flag
     *
     * @access private
     */
    const IS_INVISIBLE = true;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        switch (strlen($key)) {
            case 32:
                $public = $key;
                break;
            case 64:
                $private = \Phabel\Target\Php80\Polyfill::substr($key, 0, 32);
                $public = \Phabel\Target\Php80\Polyfill::substr($key, -32);
                break;
            case 96:
                $public = \Phabel\Target\Php80\Polyfill::substr($key, -32);
                if (\Phabel\Target\Php80\Polyfill::substr($key, 32, 32) != $public) {
                    throw new \RuntimeException('Keys with 96 bytes should have the 2nd and 3rd set of 32 bytes match');
                }
                $private = \Phabel\Target\Php80\Polyfill::substr($key, 0, 32);
                break;
            default:
                throw new \RuntimeException('libsodium keys need to either be 32 bytes long, 64 bytes long or 96 bytes long');
        }
        $curve = new Ed25519();
        $components = ['curve' => $curve];
        if (isset($private)) {
            $components['dA'] = $curve->extractSecret($private);
        }
        $components['QA'] = isset($public) ? self::extractPoint($public, $curve) : $curve->multiplyPoint($curve->getBasePoint(), $components['dA']);
        return $components;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @return string
     */
    public static function savePublicKey(Ed25519 $curve, array $publicKey)
    {
        return $curve->encodePoint($publicKey);
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, Ed25519 $curve, array $publicKey, $password = '')
    {
        if (!isset($privateKey->secret)) {
            throw new \RuntimeException('Private Key does not have a secret set');
        }
        if (strlen($privateKey->secret) != 32) {
            throw new \RuntimeException('Private Key secret is not of the correct length');
        }
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('libsodium private keys do not support encryption');
        }
        return $privateKey->secret . $curve->encodePoint($publicKey);
    }
}<?php

/**
 * "PKCS1" (RFC5915) Formatted EC Key Handler
 *
 * PHP version 5
 *
 * Used by File/X509.php
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN EC PRIVATE KEY-----
 * -----BEGIN EC PARAMETERS-----
 *
 * Technically, PKCS1 is for RSA keys, only, but we're using PKCS1 to describe
 * DSA, whose format isn't really formally described anywhere, so might as well
 * use it to describe this, too. PKCS1 is easier to remember than RFC5915, after
 * all. I suppose this could also be named IETF but idk
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Math\BigInteger;
use ParagonIE\ConstantTime\Base64;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Common\Functions\Strings;
/**
 * "PKCS1" (RFC5915) Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends Progenitor
{
    use Common;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (strpos($key, 'BEGIN EC PARAMETERS') && strpos($key, 'BEGIN EC PRIVATE KEY')) {
            $components = [];
            preg_match('#-*BEGIN EC PRIVATE KEY-*[^-]*-*END EC PRIVATE KEY-*#s', $key, $matches);
            $decoded = parent::load($matches[0], $password);
            $decoded = ASN1::decodeBER($decoded);
            if (empty($decoded)) {
                throw new \RuntimeException('Unable to decode BER');
            }
            $ecPrivate = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
            if (!is_array($ecPrivate)) {
                throw new \RuntimeException('Unable to perform ASN1 mapping');
            }
            if (isset($ecPrivate['parameters'])) {
                $components['curve'] = self::loadCurveByParam($ecPrivate['parameters']);
            }
            preg_match('#-*BEGIN EC PARAMETERS-*[^-]*-*END EC PARAMETERS-*#s', $key, $matches);
            $decoded = parent::load($matches[0], '');
            $decoded = ASN1::decodeBER($decoded);
            if (empty($decoded)) {
                throw new \RuntimeException('Unable to decode BER');
            }
            $ecParams = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
            if (!is_array($ecParams)) {
                throw new \RuntimeException('Unable to perform ASN1 mapping');
            }
            $ecParams = self::loadCurveByParam($ecParams);
            // comparing $ecParams and $components['curve'] directly won't work because they'll have different Math\Common\FiniteField classes
            // even if the modulo is the same
            if (isset($components['curve']) && self::encodeParameters($ecParams, false, []) != self::encodeParameters($components['curve'], false, [])) {
                throw new \RuntimeException('EC PARAMETERS does not correspond to EC PRIVATE KEY');
            }
            if (!isset($components['curve'])) {
                $components['curve'] = $ecParams;
            }
            $components['dA'] = new BigInteger($ecPrivate['privateKey'], 256);
            $components['curve']->rangeCheck($components['dA']);
            $components['QA'] = isset($ecPrivate['publicKey']) ? self::extractPoint($ecPrivate['publicKey'], $components['curve']) : $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
            return $components;
        }
        $key = parent::load($key, $password);
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $key = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
        if (is_array($key)) {
            return ['curve' => self::loadCurveByParam($key)];
        }
        $key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
        if (!is_array($key)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping');
        }
        if (!isset($key['parameters'])) {
            throw new \RuntimeException('Key cannot be loaded without parameters');
        }
        $components = [];
        $components['curve'] = self::loadCurveByParam($key['parameters']);
        $components['dA'] = new BigInteger($key['privateKey'], 256);
        $components['QA'] = isset($ecPrivate['publicKey']) ? self::extractPoint($ecPrivate['publicKey'], $components['curve']) : $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
        return $components;
    }
    /**
     * Convert EC parameters to the appropriate format
     *
     * @access public
     * @return string
     */
    public static function saveParameters(BaseCurve $curve, array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('TwistedEdwards and Montgomery Curves are not supported');
        }
        $key = self::encodeParameters($curve, false, $options);
        return "-----BEGIN EC PARAMETERS-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END EC PARAMETERS-----\r\n";
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = '', array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('TwistedEdwards Curves are not supported');
        }
        $publicKey = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        $key = ['version' => 'ecPrivkeyVer1', 'privateKey' => $privateKey->toBytes(), 'parameters' => new ASN1\Element(self::encodeParameters($curve)), 'publicKey' => "\x00" . $publicKey];
        $key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP);
        return self::wrapPrivateKey($key, 'EC', $password, $options);
    }
}<?php

/**
 * PKCS#8 Formatted EC Key Handler
 *
 * PHP version 5
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
 * is specific to private keys it's basically creating a DER-encoded wrapper
 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Crypt\EC\Curves\Ed448;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends Progenitor
{
    use Common;
    /**
     * OID Name
     *
     * @var array
     * @access private
     */
    const OID_NAME = ['id-ecPublicKey', 'id-Ed25519', 'id-Ed448'];
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = ['1.2.840.10045.2.1', '1.3.101.112', '1.3.101.113'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        // initialize_static_variables() is defined in both the trait and the parent class
        // when it's defined in two places it's the traits one that's called
        // the parent one is needed, as well, but the parent one is called by other methods
        // in the parent class as needed and in the context of the parent it's the parent
        // one that's called
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $isPublic = strpos($key, 'PUBLIC') !== false;
        $key = parent::load($key, $password);
        $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
        switch (true) {
            case !$isPublic && $type == 'publicKey':
                throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
            case $isPublic && $type == 'privateKey':
                throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
        }
        switch ($key[$type . 'Algorithm']['algorithm']) {
            case 'id-Ed25519':
            case 'id-Ed448':
                return self::loadEdDSA($key);
        }
        $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
        $params = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
        if (!$params) {
            throw new \RuntimeException('Unable to decode the parameters using Maps\\ECParameters');
        }
        $components = [];
        $components['curve'] = self::loadCurveByParam($params);
        if ($isPublic) {
            $components['QA'] = self::extractPoint("\x00" . $key['publicKey'], $components['curve']);
            return $components;
        }
        $decoded = ASN1::decodeBER($key['privateKey']);
        $key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
        if (isset($key['parameters']) && $params != $key['parameters']) {
            throw new \RuntimeException('The PKCS8 parameter field does not match the private key parameter field');
        }
        $components['dA'] = new BigInteger($key['privateKey'], 256);
        $components['curve']->rangeCheck($components['dA']);
        $components['QA'] = isset($key['publicKey']) ? self::extractPoint($key['publicKey'], $components['curve']) : $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
        return $components;
    }
    /**
     * Break a public or private EdDSA key down into its constituent components
     *
     * @return array
     */
    private static function loadEdDSA(array $key)
    {
        $components = [];
        if (isset($key['privateKey'])) {
            $components['curve'] = $key['privateKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448();
            // 0x04 == octet string
            // 0x20 == length (32 bytes)
            if (\Phabel\Target\Php80\Polyfill::substr($key['privateKey'], 0, 2) != "\x04 ") {
                throw new \RuntimeException('The first two bytes of the private key field should be 0x0420');
            }
            $components['dA'] = $components['curve']->extractSecret(\Phabel\Target\Php80\Polyfill::substr($key['privateKey'], 2));
        }
        if (isset($key['publicKey'])) {
            if (!isset($components['curve'])) {
                $components['curve'] = $key['publicKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448();
            }
            $components['QA'] = self::extractPoint($key['publicKey'], $components['curve']);
        }
        if (isset($key['privateKey']) && !isset($components['QA'])) {
            $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
        }
        return $components;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('Montgomery Curves are not supported');
        }
        if ($curve instanceof TwistedEdwardsCurve) {
            return self::wrapPublicKey($curve->encodePoint($publicKey), null, $curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448');
        }
        $params = new ASN1\Element(self::encodeParameters($curve, false, $options));
        $key = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        return self::wrapPublicKey($key, $params, 'id-ecPublicKey');
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = '', array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('Montgomery Curves are not supported');
        }
        if ($curve instanceof TwistedEdwardsCurve) {
            return self::wrapPrivateKey("\x04 " . $privateKey->secret, [], null, $password, $curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448', "\x00" . $curve->encodePoint($publicKey));
        }
        $publicKey = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        $params = new ASN1\Element(self::encodeParameters($curve, false, $options));
        $key = [
            'version' => 'ecPrivkeyVer1',
            'privateKey' => $privateKey->toBytes(),
            //'parameters' => $params,
            'publicKey' => "\x00" . $publicKey,
        ];
        $key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP);
        return self::wrapPrivateKey($key, [], $params, $password, 'id-ecPublicKey', '', $options);
    }
}<?php

/**
 * PuTTY Formatted EC Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
/**
 * PuTTY Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PuTTY extends Progenitor
{
    use Common;
    /**
     * Public Handler
     *
     * @var string
     * @access private
     */
    const PUBLIC_HANDLER = 'phpseclib3\\Crypt\\EC\\Formats\\Keys\\OpenSSH';
    /**
     * Supported Key Types
     *
     * @var array
     * @access private
     */
    protected static $types = ['ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $components = parent::load($key, $password);
        if (!isset($components['private'])) {
            return $components;
        }
        $private = $components['private'];
        $temp = Base64::encode(Strings::packSSH2('s', $components['type']) . $components['public']);
        $components = OpenSSH::load($components['type'] . ' ' . $temp . ' ' . $components['comment']);
        if ($components['curve'] instanceof TwistedEdwardsCurve) {
            if (Strings::shift($private, 4) != "\x00\x00\x00 ") {
                throw new \RuntimeException('Length of ssh-ed25519 key should be 32');
            }
            $components['dA'] = $components['curve']->extractSecret($private);
        } else {
            list($components['dA']) = Strings::unpackSSH2('i', $private);
            $components['curve']->rangeCheck($components['dA']);
        }
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = false, array $options = [])
    {
        self::initialize_static_variables();
        $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
        $name = $public[0];
        $public = Base64::decode($public[1]);
        list(, $length) = unpack('N', Strings::shift($public, 4));
        Strings::shift($public, $length);
        // PuTTY pads private keys with a null byte per the following:
        // https://github.com/github/putty/blob/a3d14d77f566a41fc61dfdc5c2e0e384c9e6ae8b/sshecc.c#L1926
        if (!$curve instanceof TwistedEdwardsCurve) {
            $private = $privateKey->toBytes();
            if (!(strlen($privateKey->toBits()) & 7)) {
                $private = "\x00{$private}";
            }
        }
        $private = $curve instanceof TwistedEdwardsCurve ? Strings::packSSH2('s', $privateKey->secret) : Strings::packSSH2('s', $private);
        return self::wrapPrivateKey($public, $private, $name, $password, $options);
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField[] $publicKey
     * @return string
     */
    public static function savePublicKey(BaseCurve $curve, array $publicKey)
    {
        $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
        $type = $public[0];
        $public = Base64::decode($public[1]);
        list(, $length) = unpack('N', Strings::shift($public, 4));
        Strings::shift($public, $length);
        return self::wrapPublicKey($public, $type);
    }
}<?php

/**
 * XML Formatted EC Key Handler
 *
 * More info:
 *
 * https://www.w3.org/TR/xmldsig-core/#sec-ECKeyValue
 * http://en.wikipedia.org/wiki/XML_Signature
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Crypt\EC\BaseCurves\Prime as PrimeCurve;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedCurveException;
/**
 * XML Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class XML
{
    use Common;
    /**
     * Default namespace
     *
     * @var string
     */
    private static $namespace;
    /**
     * Flag for using RFC4050 syntax
     *
     * @var bool
     */
    private static $rfc4050 = false;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $use_errors = libxml_use_internal_errors(true);
        $temp = self::isolateNamespace($key, 'http://www.w3.org/2009/xmldsig11#');
        if ($temp) {
            $key = $temp;
        }
        $temp = self::isolateNamespace($key, 'http://www.w3.org/2001/04/xmldsig-more#');
        if ($temp) {
            $key = $temp;
        }
        $dom = new \DOMDocument();
        if (\Phabel\Target\Php80\Polyfill::substr($key, 0, 5) != '<?xml') {
            $key = '<xml>' . $key . '</xml>';
        }
        if (!$dom->loadXML($key)) {
            libxml_use_internal_errors($use_errors);
            throw new \UnexpectedValueException('Key does not appear to contain XML');
        }
        $xpath = new \DOMXPath($dom);
        libxml_use_internal_errors($use_errors);
        $curve = self::loadCurveByParam($xpath);
        $pubkey = self::query($xpath, 'publickey', 'Public Key is not present');
        $QA = self::query($xpath, 'ecdsakeyvalue')->length ? self::extractPointRFC4050($xpath, $curve) : self::extractPoint("\x00" . $pubkey, $curve);
        libxml_use_internal_errors($use_errors);
        return compact('curve', 'QA');
    }
    /**
     * Case-insensitive xpath query
     *
     * @param \DOMXPath $xpath
     * @param string $name
     * @param string $error optional
     * @param bool $decode optional
     * @return \DOMNodeList
     */
    private static function query($xpath, $name, $error = null, $decode = true)
    {
        $query = '/';
        $names = explode('/', $name);
        foreach ($names as $name) {
            $query .= "/*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='{$name}']";
        }
        $result = $xpath->query($query);
        if (!isset($error)) {
            return $result;
        }
        if (!$result->length) {
            throw new \RuntimeException($error);
        }
        return $decode ? self::decodeValue($result->item(0)->textContent) : $result->item(0)->textContent;
    }
    /**
     * Finds the first element in the relevant namespace, strips the namespacing and returns the XML for that element.
     *
     * @param string $xml
     * @param string $ns
     */
    private static function isolateNamespace($xml, $ns)
    {
        $dom = new \DOMDocument();
        if (!$dom->loadXML($xml)) {
            return false;
        }
        $xpath = new \DOMXPath($dom);
        $nodes = $xpath->query("//*[namespace::*[.='{$ns}'] and not(../namespace::*[.='{$ns}'])]");
        if (!$nodes->length) {
            return false;
        }
        $node = $nodes->item(0);
        $ns_name = $node->lookupPrefix($ns);
        $node->removeAttributeNS($ns, $ns_name);
        return $dom->saveXML($node);
    }
    /**
     * Decodes the value
     *
     * @param string $value
     */
    private static function decodeValue($value)
    {
        return Base64::decode(str_replace(["\r", "\n", ' ', "\t"], '', $value));
    }
    /**
     * Extract points from an XML document
     *
     * @param \DOMXPath $xpath
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @return object[]
     */
    private static function extractPointRFC4050(\DOMXPath $xpath, BaseCurve $curve)
    {
        $x = self::query($xpath, 'publickey/x');
        $y = self::query($xpath, 'publickey/y');
        if (!$x->length || !$x->item(0)->hasAttribute('Value')) {
            throw new \RuntimeException('Public Key / X coordinate not found');
        }
        if (!$y->length || !$y->item(0)->hasAttribute('Value')) {
            throw new \RuntimeException('Public Key / Y coordinate not found');
        }
        $point = [$curve->convertInteger(new BigInteger($x->item(0)->getAttribute('Value'))), $curve->convertInteger(new BigInteger($y->item(0)->getAttribute('Value')))];
        if (!$curve->verifyPoint($point)) {
            throw new \RuntimeException('Unable to verify that point exists on curve');
        }
        return $point;
    }
    /**
    * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based
    on the curve parameters
    *
    * @param \DomXPath $xpath
    * @return (\phpseclib3\Crypt\EC\BaseCurves\Base | false)
    */
    private static function loadCurveByParam(\DOMXPath $xpath)
    {
        $namedCurve = self::query($xpath, 'namedcurve');
        if ($namedCurve->length == 1) {
            $oid = $namedCurve->item(0)->getAttribute('URN');
            $oid = preg_replace('#[^\\d.]#', '', $oid);
            $name = array_search($oid, self::$curveOIDs);
            if ($name === false) {
                throw new UnsupportedCurveException('Curve with OID of ' . $oid . ' is not supported');
            }
            $curve = '\\phpseclib3\\Crypt\\EC\\Curves\\' . $name;
            if (!class_exists($curve)) {
                throw new UnsupportedCurveException('Named Curve of ' . $name . ' is not supported');
            }
            return new $curve();
        }
        $params = self::query($xpath, 'explicitparams');
        if ($params->length) {
            return self::loadCurveByParamRFC4050($xpath);
        }
        $params = self::query($xpath, 'ecparameters');
        if (!$params->length) {
            throw new \RuntimeException('No parameters are present');
        }
        $fieldTypes = ['prime-field' => ['fieldid/prime/p'], 'gnb' => ['fieldid/gnb/m'], 'tnb' => ['fieldid/tnb/k'], 'pnb' => ['fieldid/pnb/k1', 'fieldid/pnb/k2', 'fieldid/pnb/k3'], 'unknown' => []];
        foreach ($fieldTypes as $type => $queries) {
            foreach ($queries as $query) {
                $result = self::query($xpath, $query);
                if (!$result->length) {
                    continue 2;
                }
                $param = preg_replace('#.*/#', '', $query);
                ${$param} = self::decodeValue($result->item(0)->textContent);
            }
            break;
        }
        $a = self::query($xpath, 'curve/a', 'A coefficient is not present');
        $b = self::query($xpath, 'curve/b', 'B coefficient is not present');
        $base = self::query($xpath, 'base', 'Base point is not present');
        $order = self::query($xpath, 'order', 'Order is not present');
        switch ($type) {
            case 'prime-field':
                $curve = new PrimeCurve();
                $curve->setModulo(new BigInteger($p, 256));
                $curve->setCoefficients(new BigInteger($a, 256), new BigInteger($b, 256));
                $point = self::extractPoint("\x00" . $base, $curve);
                $curve->setBasePoint(...$point);
                $curve->setOrder(new BigInteger($order, 256));
                return $curve;
            case 'gnb':
            case 'tnb':
            case 'pnb':
            default:
                throw new UnsupportedCurveException('Field Type of ' . $type . ' is not supported');
        }
    }
    /**
    * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based
    on the curve parameters
    *
    * @param \DomXPath $xpath
    * @return (\phpseclib3\Crypt\EC\BaseCurves\Base | false)
    */
    private static function loadCurveByParamRFC4050(\DOMXPath $xpath)
    {
        $fieldTypes = ['prime-field' => ['primefieldparamstype/p'], 'unknown' => []];
        foreach ($fieldTypes as $type => $queries) {
            foreach ($queries as $query) {
                $result = self::query($xpath, $query);
                if (!$result->length) {
                    continue 2;
                }
                $param = preg_replace('#.*/#', '', $query);
                ${$param} = $result->item(0)->textContent;
            }
            break;
        }
        $a = self::query($xpath, 'curveparamstype/a', 'A coefficient is not present', false);
        $b = self::query($xpath, 'curveparamstype/b', 'B coefficient is not present', false);
        $x = self::query($xpath, 'basepointparams/basepoint/ecpointtype/x', 'Base Point X is not present', false);
        $y = self::query($xpath, 'basepointparams/basepoint/ecpointtype/y', 'Base Point Y is not present', false);
        $order = self::query($xpath, 'order', 'Order is not present', false);
        switch ($type) {
            case 'prime-field':
                $curve = new PrimeCurve();
                $p = str_replace(["\r", "\n", ' ', "\t"], '', $p);
                $curve->setModulo(new BigInteger($p));
                $a = str_replace(["\r", "\n", ' ', "\t"], '', $a);
                $b = str_replace(["\r", "\n", ' ', "\t"], '', $b);
                $curve->setCoefficients(new BigInteger($a), new BigInteger($b));
                $x = str_replace(["\r", "\n", ' ', "\t"], '', $x);
                $y = str_replace(["\r", "\n", ' ', "\t"], '', $y);
                $curve->setBasePoint(new BigInteger($x), new BigInteger($y));
                $order = str_replace(["\r", "\n", ' ', "\t"], '', $order);
                $curve->setOrder(new BigInteger($order));
                return $curve;
            default:
                throw new UnsupportedCurveException('Field Type of ' . $type . ' is not supported');
        }
    }
    /**
     * Sets the namespace. dsig11 is the most common one.
     *
     * Set to null to unset. Used only for creating public keys.
     *
     * @param string $namespace
     */
    public static function setNamespace($namespace)
    {
        self::$namespace = $namespace;
    }
    /**
     * Uses the XML syntax specified in https://tools.ietf.org/html/rfc4050
     */
    public static function enableRFC4050Syntax()
    {
        self::$rfc4050 = true;
    }
    /**
     * Uses the XML syntax specified in https://www.w3.org/TR/xmldsig-core/#sec-ECParameters
     */
    public static function disableRFC4050Syntax()
    {
        self::$rfc4050 = false;
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('TwistedEdwards and Montgomery Curves are not supported');
        }
        if (empty(static::$namespace)) {
            $pre = $post = '';
        } else {
            $pre = static::$namespace . ':';
            $post = ':' . static::$namespace;
        }
        if (self::$rfc4050) {
            return '<' . $pre . 'ECDSAKeyValue xmlns' . $post . '="http://www.w3.org/2001/04/xmldsig-more#">
' . self::encodeXMLParameters($curve, $pre, $options) . '
<' . $pre . 'PublicKey>
<' . $pre . 'X Value="' . $publicKey[0] . '" />
<' . $pre . 'Y Value="' . $publicKey[1] . '" />
</' . $pre . 'PublicKey>
</' . $pre . 'ECDSAKeyValue>';
        }
        $publicKey = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        return '<' . $pre . 'ECDSAKeyValue xmlns' . $post . '="http://www.w3.org/2009/xmldsig11#">
' . self::encodeXMLParameters($curve, $pre, $options) . '
<' . $pre . 'PublicKey>' . Base64::encode($publicKey) . '</' . $pre . 'PublicKey>
</' . $pre . 'ECDSAKeyValue>';
    }
    /**
     * Encode Parameters
     *
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param string $pre
     * @param array $options optional
     * @return (string | false)
     */
    private static function encodeXMLParameters(BaseCurve $curve, $pre, array $options = [])
    {
        $result = self::encodeParameters($curve, true, $options);
        if (isset($result['namedCurve'])) {
            $namedCurve = '<' . $pre . 'NamedCurve URI="urn:oid:' . self::$curveOIDs[$result['namedCurve']] . '" />';
            return self::$rfc4050 ? '<DomainParameters>' . str_replace('URI', 'URN', $namedCurve) . '</DomainParameters>' : $namedCurve;
        }
        if (self::$rfc4050) {
            $xml = '<' . $pre . 'ExplicitParams>
<' . $pre . 'FieldParams>
';
            $temp = $result['specifiedCurve'];
            switch ($temp['fieldID']['fieldType']) {
                case 'prime-field':
                    $xml .= '<' . $pre . 'PrimeFieldParamsType>
<' . $pre . 'P>' . $temp['fieldID']['parameters'] . '</' . $pre . 'P>
</' . $pre . 'PrimeFieldParamsType>
';
                    $a = $curve->getA();
                    $b = $curve->getB();
                    list($x, $y) = $curve->getBasePoint();
                    break;
                default:
                    throw new UnsupportedCurveException('Field Type of ' . $temp['fieldID']['fieldType'] . ' is not supported');
            }
            $xml .= '</' . $pre . 'FieldParams>
<' . $pre . 'CurveParamsType>
<' . $pre . 'A>' . $a . '</' . $pre . 'A>
<' . $pre . 'B>' . $b . '</' . $pre . 'B>
</' . $pre . 'CurveParamsType>
<' . $pre . 'BasePointParams>
<' . $pre . 'BasePoint>
<' . $pre . 'ECPointType>
<' . $pre . 'X>' . $x . '</' . $pre . 'X>
<' . $pre . 'Y>' . $y . '</' . $pre . 'Y>
</' . $pre . 'ECPointType>
</' . $pre . 'BasePoint>
<' . $pre . 'Order>' . $curve->getOrder() . '</' . $pre . 'Order>
</' . $pre . 'BasePointParams>
</' . $pre . 'ExplicitParams>
';
            return $xml;
        }
        if (isset($result['specifiedCurve'])) {
            $xml = '<' . $pre . 'ECParameters>
<' . $pre . 'FieldID>
';
            $temp = $result['specifiedCurve'];
            switch ($temp['fieldID']['fieldType']) {
                case 'prime-field':
                    $xml .= '<' . $pre . 'Prime>
<' . $pre . 'P>' . Base64::encode($temp['fieldID']['parameters']->toBytes()) . '</' . $pre . 'P>
</' . $pre . 'Prime>
';
                    break;
                default:
                    throw new UnsupportedCurveException('Field Type of ' . $temp['fieldID']['fieldType'] . ' is not supported');
            }
            $xml .= '</' . $pre . 'FieldID>
<' . $pre . 'Curve>
<' . $pre . 'A>' . Base64::encode($temp['curve']['a']) . '</' . $pre . 'A>
<' . $pre . 'B>' . Base64::encode($temp['curve']['b']) . '</' . $pre . 'B>
</' . $pre . 'Curve>
<' . $pre . 'Base>' . Base64::encode($temp['base']) . '</' . $pre . 'Base>
<' . $pre . 'Order>' . Base64::encode($temp['order']) . '</' . $pre . 'Order>
</' . $pre . 'ECParameters>';
            return $xml;
        }
    }
}<?php

/**
 * OpenSSH Formatted EC Key Handler
 *
 * PHP version 5
 *
 * Place in $HOME/.ssh/authorized_keys
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Crypt\EC\Curves\Ed25519;
/**
 * OpenSSH Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSH extends Progenitor
{
    use Common;
    /**
     * Supported Key Types
     *
     * @var array
     */
    protected static $types = ['ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $parsed = parent::load($key, $password);
        if (isset($parsed['paddedKey'])) {
            $paddedKey = $parsed['paddedKey'];
            list($type) = Strings::unpackSSH2('s', $paddedKey);
            if ($type != $parsed['type']) {
                throw new \RuntimeException("The public and private keys are not of the same type ({$type} vs {$parsed['type']})");
            }
            if ($type == 'ssh-ed25519') {
                list(, $key, $comment) = Strings::unpackSSH2('sss', $paddedKey);
                $key = libsodium::load($key);
                $key['comment'] = $comment;
                return $key;
            }
            list($curveName, $publicKey, $privateKey, $comment) = Strings::unpackSSH2('ssis', $paddedKey);
            $curve = self::loadCurveByParam(['namedCurve' => $curveName]);
            $curve->rangeCheck($privateKey);
            return ['curve' => $curve, 'dA' => $privateKey, 'QA' => self::extractPoint("\x00{$publicKey}", $curve), 'comment' => $comment];
        }
        if ($parsed['type'] == 'ssh-ed25519') {
            if (Strings::shift($parsed['publicKey'], 4) != "\x00\x00\x00 ") {
                throw new \RuntimeException('Length of ssh-ed25519 key should be 32');
            }
            $curve = new Ed25519();
            $qa = self::extractPoint($parsed['publicKey'], $curve);
        } else {
            list($curveName, $publicKey) = Strings::unpackSSH2('ss', $parsed['publicKey']);
            $curveName = '\\phpseclib3\\Crypt\\EC\\Curves\\' . $curveName;
            $curve = new $curveName();
            $qa = self::extractPoint("\x00" . $publicKey, $curve);
        }
        return ['curve' => $curve, 'QA' => $qa, 'comment' => $parsed['comment']];
    }
    /**
     * Returns the alias that corresponds to a curve
     *
     * @return string
     */
    private static function getAlias(BaseCurve $curve)
    {
        self::initialize_static_variables();
        $reflect = new \ReflectionClass($curve);
        $name = $reflect->getShortName();
        $oid = self::$curveOIDs[$name];
        $aliases = array_filter(self::$curveOIDs, function ($v) use($oid) {
            return $v == $oid;
        });
        $aliases = array_keys($aliases);
        for ($i = 0; $i < count($aliases); $i++) {
            if (in_array('ecdsa-sha2-' . $aliases[$i], self::$types)) {
                $alias = $aliases[$i];
                break;
            }
        }
        if (!isset($alias)) {
            throw new UnsupportedCurveException($name . ' is not a curve that the OpenSSH plugin supports');
        }
        return $alias;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
    {
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        if ($curve instanceof Ed25519) {
            $key = Strings::packSSH2('ss', 'ssh-ed25519', $curve->encodePoint($publicKey));
            if (isset($options['binary']) ? $options['binary'] : self::$binary) {
                return $key;
            }
            $key = 'ssh-ed25519 ' . base64_encode($key) . ' ' . $comment;
            return $key;
        }
        $alias = self::getAlias($curve);
        $points = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        $key = Strings::packSSH2('sss', 'ecdsa-sha2-' . $alias, $alias, $points);
        if (isset($options['binary']) ? $options['binary'] : self::$binary) {
            return $key;
        }
        $key = 'ecdsa-sha2-' . $alias . ' ' . base64_encode($key) . ' ' . $comment;
        return $key;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = '', array $options = [])
    {
        if ($curve instanceof Ed25519) {
            if (!isset($privateKey->secret)) {
                throw new \RuntimeException('Private Key does not have a secret set');
            }
            if (strlen($privateKey->secret) != 32) {
                throw new \RuntimeException('Private Key secret is not of the correct length');
            }
            $pubKey = $curve->encodePoint($publicKey);
            $publicKey = Strings::packSSH2('ss', 'ssh-ed25519', $pubKey);
            $privateKey = Strings::packSSH2('sss', 'ssh-ed25519', $pubKey, $privateKey->secret . $pubKey);
            return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
        }
        $alias = self::getAlias($curve);
        $points = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        $publicKey = self::savePublicKey($curve, $publicKey, ['binary' => true]);
        $privateKey = Strings::packSSH2('sssi', 'ecdsa-sha2-' . $alias, $alias, $points, $privateKey);
        return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
    }
}<?php

/**
 * Generic EC Key Parsing Helper functions
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Crypt\EC\BaseCurves\Prime as PrimeCurve;
use phpseclib3\Crypt\EC\BaseCurves\Binary as BinaryCurve;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\PrimeField;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Exception\UnsupportedCurveException;
/**
 * Generic EC Key Parsing Helper functions
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
trait Common
{
    /**
     * Curve OIDs
     *
     * @var array
     */
    private static $curveOIDs = [];
    /**
     * Child OIDs loaded
     *
     * @var bool
     */
    protected static $childOIDsLoaded = false;
    /**
     * Use Named Curves
     *
     * @var bool
     */
    private static $useNamedCurves = true;
    /**
     * Initialize static variables
     */
    private static function initialize_static_variables()
    {
        if (empty(self::$curveOIDs)) {
            // the sec* curves are from the standards for efficient cryptography group
            // sect* curves are curves over binary finite fields
            // secp* curves are curves over prime finite fields
            // sec*r* curves are regular curves; sec*k* curves are koblitz curves
            // brainpool*r* curves are regular prime finite field curves
            // brainpool*t* curves are twisted versions of the brainpool*r* curves
            self::$curveOIDs = [
                'prime192v1' => '1.2.840.10045.3.1.1',
                // J.5.1, example 1 (aka secp192r1)
                'prime192v2' => '1.2.840.10045.3.1.2',
                // J.5.1, example 2
                'prime192v3' => '1.2.840.10045.3.1.3',
                // J.5.1, example 3
                'prime239v1' => '1.2.840.10045.3.1.4',
                // J.5.2, example 1
                'prime239v2' => '1.2.840.10045.3.1.5',
                // J.5.2, example 2
                'prime239v3' => '1.2.840.10045.3.1.6',
                // J.5.2, example 3
                'prime256v1' => '1.2.840.10045.3.1.7',
                // J.5.3, example 1 (aka secp256r1)
                // https://tools.ietf.org/html/rfc5656#section-10
                'nistp256' => '1.2.840.10045.3.1.7',
                // aka secp256r1
                'nistp384' => '1.3.132.0.34',
                // aka secp384r1
                'nistp521' => '1.3.132.0.35',
                // aka secp521r1
                'nistk163' => '1.3.132.0.1',
                // aka sect163k1
                'nistp192' => '1.2.840.10045.3.1.1',
                // aka secp192r1
                'nistp224' => '1.3.132.0.33',
                // aka secp224r1
                'nistk233' => '1.3.132.0.26',
                // aka sect233k1
                'nistb233' => '1.3.132.0.27',
                // aka sect233r1
                'nistk283' => '1.3.132.0.16',
                // aka sect283k1
                'nistk409' => '1.3.132.0.36',
                // aka sect409k1
                'nistb409' => '1.3.132.0.37',
                // aka sect409r1
                'nistt571' => '1.3.132.0.38',
                // aka sect571k1
                // from https://tools.ietf.org/html/rfc5915
                'secp192r1' => '1.2.840.10045.3.1.1',
                // aka prime192v1
                'sect163k1' => '1.3.132.0.1',
                'sect163r2' => '1.3.132.0.15',
                'secp224r1' => '1.3.132.0.33',
                'sect233k1' => '1.3.132.0.26',
                'sect233r1' => '1.3.132.0.27',
                'secp256r1' => '1.2.840.10045.3.1.7',
                // aka prime256v1
                'sect283k1' => '1.3.132.0.16',
                'sect283r1' => '1.3.132.0.17',
                'secp384r1' => '1.3.132.0.34',
                'sect409k1' => '1.3.132.0.36',
                'sect409r1' => '1.3.132.0.37',
                'secp521r1' => '1.3.132.0.35',
                'sect571k1' => '1.3.132.0.38',
                'sect571r1' => '1.3.132.0.39',
                // from http://www.secg.org/SEC2-Ver-1.0.pdf
                'secp112r1' => '1.3.132.0.6',
                'secp112r2' => '1.3.132.0.7',
                'secp128r1' => '1.3.132.0.28',
                'secp128r2' => '1.3.132.0.29',
                'secp160k1' => '1.3.132.0.9',
                'secp160r1' => '1.3.132.0.8',
                'secp160r2' => '1.3.132.0.30',
                'secp192k1' => '1.3.132.0.31',
                'secp224k1' => '1.3.132.0.32',
                'secp256k1' => '1.3.132.0.10',
                'sect113r1' => '1.3.132.0.4',
                'sect113r2' => '1.3.132.0.5',
                'sect131r1' => '1.3.132.0.22',
                'sect131r2' => '1.3.132.0.23',
                'sect163r1' => '1.3.132.0.2',
                'sect193r1' => '1.3.132.0.24',
                'sect193r2' => '1.3.132.0.25',
                'sect239k1' => '1.3.132.0.3',
                // from http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.202.2977&rep=rep1&type=pdf#page=36
                /*
                'c2pnb163v1' => '1.2.840.10045.3.0.1', // J.4.1, example 1
                'c2pnb163v2' => '1.2.840.10045.3.0.2', // J.4.1, example 2
                'c2pnb163v3' => '1.2.840.10045.3.0.3', // J.4.1, example 3
                'c2pnb172w1' => '1.2.840.10045.3.0.4', // J.4.2, example 1
                'c2tnb191v1' => '1.2.840.10045.3.0.5', // J.4.3, example 1
                'c2tnb191v2' => '1.2.840.10045.3.0.6', // J.4.3, example 2
                'c2tnb191v3' => '1.2.840.10045.3.0.7', // J.4.3, example 3
                'c2onb191v4' => '1.2.840.10045.3.0.8', // J.4.3, example 4
                'c2onb191v5' => '1.2.840.10045.3.0.9', // J.4.3, example 5
                'c2pnb208w1' => '1.2.840.10045.3.0.10', // J.4.4, example 1
                'c2tnb239v1' => '1.2.840.10045.3.0.11', // J.4.5, example 1
                'c2tnb239v2' => '1.2.840.10045.3.0.12', // J.4.5, example 2
                'c2tnb239v3' => '1.2.840.10045.3.0.13', // J.4.5, example 3
                'c2onb239v4' => '1.2.840.10045.3.0.14', // J.4.5, example 4
                'c2onb239v5' => '1.2.840.10045.3.0.15', // J.4.5, example 5
                'c2pnb272w1' => '1.2.840.10045.3.0.16', // J.4.6, example 1
                'c2pnb304w1' => '1.2.840.10045.3.0.17', // J.4.7, example 1
                'c2tnb359v1' => '1.2.840.10045.3.0.18', // J.4.8, example 1
                'c2pnb368w1' => '1.2.840.10045.3.0.19', // J.4.9, example 1
                'c2tnb431r1' => '1.2.840.10045.3.0.20', // J.4.10, example 1
                */
                // http://www.ecc-brainpool.org/download/Domain-parameters.pdf
                // https://tools.ietf.org/html/rfc5639
                'brainpoolP160r1' => '1.3.36.3.3.2.8.1.1.1',
                'brainpoolP160t1' => '1.3.36.3.3.2.8.1.1.2',
                'brainpoolP192r1' => '1.3.36.3.3.2.8.1.1.3',
                'brainpoolP192t1' => '1.3.36.3.3.2.8.1.1.4',
                'brainpoolP224r1' => '1.3.36.3.3.2.8.1.1.5',
                'brainpoolP224t1' => '1.3.36.3.3.2.8.1.1.6',
                'brainpoolP256r1' => '1.3.36.3.3.2.8.1.1.7',
                'brainpoolP256t1' => '1.3.36.3.3.2.8.1.1.8',
                'brainpoolP320r1' => '1.3.36.3.3.2.8.1.1.9',
                'brainpoolP320t1' => '1.3.36.3.3.2.8.1.1.10',
                'brainpoolP384r1' => '1.3.36.3.3.2.8.1.1.11',
                'brainpoolP384t1' => '1.3.36.3.3.2.8.1.1.12',
                'brainpoolP512r1' => '1.3.36.3.3.2.8.1.1.13',
                'brainpoolP512t1' => '1.3.36.3.3.2.8.1.1.14',
            ];
            ASN1::loadOIDs([
                'prime-field' => '1.2.840.10045.1.1',
                'characteristic-two-field' => '1.2.840.10045.1.2',
                'characteristic-two-basis' => '1.2.840.10045.1.2.3',
                // per http://www.secg.org/SEC1-Ver-1.0.pdf#page=84, gnBasis "not used here"
                'gnBasis' => '1.2.840.10045.1.2.3.1',
                // NULL
                'tpBasis' => '1.2.840.10045.1.2.3.2',
                // Trinomial
                'ppBasis' => '1.2.840.10045.1.2.3.3',
            ] + self::$curveOIDs);
        }
    }
    /**
    * Explicitly set the curve
    *
    * If the key contains an implicit curve phpseclib needs the curve
    to be explicitly provided
    *
    * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
    */
    public static function setImplicitCurve(BaseCurve $curve)
    {
        self::$implicitCurve = $curve;
    }
    /**
    * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based
    on the curve parameters
    *
    * @param array $params
    * @return (\phpseclib3\Crypt\EC\BaseCurves\Base | false)
    */
    protected static function loadCurveByParam(array $params)
    {
        if (count($params) > 1) {
            throw new \RuntimeException('No parameters are present');
        }
        if (isset($params['namedCurve'])) {
            $curve = '\\phpseclib3\\Crypt\\EC\\Curves\\' . $params['namedCurve'];
            if (!class_exists($curve)) {
                throw new UnsupportedCurveException('Named Curve of ' . $params['namedCurve'] . ' is not supported');
            }
            return new $curve();
        }
        if (isset($params['implicitCurve'])) {
            if (!isset(self::$implicitCurve)) {
                throw new \RuntimeException('Implicit curves can be provided by calling setImplicitCurve');
            }
            return self::$implicitCurve;
        }
        if (isset($params['specifiedCurve'])) {
            $data = $params['specifiedCurve'];
            switch ($data['fieldID']['fieldType']) {
                case 'prime-field':
                    $curve = new PrimeCurve();
                    $curve->setModulo($data['fieldID']['parameters']);
                    $curve->setCoefficients(new BigInteger($data['curve']['a'], 256), new BigInteger($data['curve']['b'], 256));
                    $point = self::extractPoint("\x00" . $data['base'], $curve);
                    $curve->setBasePoint(...$point);
                    $curve->setOrder($data['order']);
                    return $curve;
                case 'characteristic-two-field':
                    $curve = new BinaryCurve();
                    $params = ASN1::decodeBER($data['fieldID']['parameters']);
                    $params = ASN1::asn1map($params[0], Maps\Characteristic_two::MAP);
                    $modulo = [(int) $params['m']->toString()];
                    switch ($params['basis']) {
                        case 'tpBasis':
                            $modulo[] = (int) $params['parameters']->toString();
                            break;
                        case 'ppBasis':
                            $temp = ASN1::decodeBER($params['parameters']);
                            $temp = ASN1::asn1map($temp[0], Maps\Pentanomial::MAP);
                            $modulo[] = (int) $temp['k3']->toString();
                            $modulo[] = (int) $temp['k2']->toString();
                            $modulo[] = (int) $temp['k1']->toString();
                    }
                    $modulo[] = 0;
                    $curve->setModulo(...$modulo);
                    $len = ceil($modulo[0] / 8);
                    $curve->setCoefficients(Hex::encode($data['curve']['a']), Hex::encode($data['curve']['b']));
                    $point = self::extractPoint("\x00" . $data['base'], $curve);
                    $curve->setBasePoint(...$point);
                    $curve->setOrder($data['order']);
                    return $curve;
                default:
                    throw new UnsupportedCurveException('Field Type of ' . $data['fieldID']['fieldType'] . ' is not supported');
            }
        }
        throw new \RuntimeException('No valid parameters are present');
    }
    /**
     * Extract points from a string
     *
     * Supports both compressed and uncompressed points
     *
     * @param string $str
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @return object[]
     */
    public static function extractPoint($str, BaseCurve $curve)
    {
        if ($curve instanceof TwistedEdwardsCurve) {
            // first step of point deciding as discussed at the following URL's:
            // https://tools.ietf.org/html/rfc8032#section-5.1.3
            // https://tools.ietf.org/html/rfc8032#section-5.2.3
            $y = $str;
            $y = strrev($y);
            $sign = (bool) (ord($y[0]) & 0x80);
            $y[0] = $y[0] & chr(0x7f);
            $y = new BigInteger($y, 256);
            if ($y->compare($curve->getModulo()) >= 0) {
                throw new \RuntimeException('The Y coordinate should not be >= the modulo');
            }
            $point = $curve->recoverX($y, $sign);
            if (!$curve->verifyPoint($point)) {
                throw new \RuntimeException('Unable to verify that point exists on curve');
            }
            return $point;
        }
        // the first byte of a bit string represents the number of bits in the last byte that are to be ignored but,
        // currently, bit strings wanting a non-zero amount of bits trimmed are not supported
        if (($val = Strings::shift($str)) != "\x00") {
            throw new \UnexpectedValueException('extractPoint expects the first byte to be null - not ' . Hex::encode($val));
        }
        if ($str == "\x00") {
            return [];
        }
        $keylen = strlen($str);
        $order = $curve->getLengthInBytes();
        // point compression is being used
        if ($keylen == $order + 1) {
            return $curve->derivePoint($str);
        }
        // point compression is not being used
        if ($keylen == 2 * $order + 1) {
            preg_match("#(.)(.{{$order}})(.{{$order}})#s", $str, $matches);
            list(, $w, $x, $y) = $matches;
            if ($w != "\x04") {
                throw new \UnexpectedValueException('The first byte of an uncompressed point should be 04 - not ' . Hex::encode($val));
            }
            $point = [$curve->convertInteger(new BigInteger($x, 256)), $curve->convertInteger(new BigInteger($y, 256))];
            if (!$curve->verifyPoint($point)) {
                throw new \RuntimeException('Unable to verify that point exists on curve');
            }
            return $point;
        }
        throw new \UnexpectedValueException('The string representation of the points is not of an appropriate length');
    }
    /**
     * Encode Parameters
     *
     * @todo Maybe at some point this could be moved to __toString() for each of the curves?
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param bool $returnArray optional
     * @param array $options optional
     * @return (string | false)
     */
    private static function encodeParameters(BaseCurve $curve, $returnArray = false, array $options = [])
    {
        $useNamedCurves = isset($options['namedCurve']) ? $options['namedCurve'] : self::$useNamedCurves;
        $reflect = new \ReflectionClass($curve);
        $name = $reflect->getShortName();
        if ($useNamedCurves) {
            if (isset(self::$curveOIDs[$name])) {
                if ($reflect->isFinal()) {
                    $reflect = $reflect->getParentClass();
                    $name = $reflect->getShortName();
                }
                return $returnArray ? ['namedCurve' => $name] : ASN1::encodeDER(['namedCurve' => $name], Maps\ECParameters::MAP);
            }
            foreach (new \DirectoryIterator(__DIR__ . '/../../Curves/') as $file) {
                if ($file->getExtension() != 'php') {
                    continue;
                }
                $testName = $file->getBasename('.php');
                $class = 'phpseclib3\\Crypt\\EC\\Curves\\' . $testName;
                $reflect = new \ReflectionClass($class);
                if ($reflect->isFinal()) {
                    continue;
                }
                $candidate = new $class();
                switch ($name) {
                    case 'Prime':
                        if (!$candidate instanceof PrimeCurve) {
                            break;
                        }
                        if (!$candidate->getModulo()->equals($curve->getModulo())) {
                            break;
                        }
                        if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) {
                            break;
                        }
                        if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) {
                            break;
                        }
                        list($candidateX, $candidateY) = $candidate->getBasePoint();
                        list($curveX, $curveY) = $curve->getBasePoint();
                        if ($candidateX->toBytes() != $curveX->toBytes()) {
                            break;
                        }
                        if ($candidateY->toBytes() != $curveY->toBytes()) {
                            break;
                        }
                        return $returnArray ? ['namedCurve' => $testName] : ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP);
                    case 'Binary':
                        if (!$candidate instanceof BinaryCurve) {
                            break;
                        }
                        if ($candidate->getModulo() != $curve->getModulo()) {
                            break;
                        }
                        if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) {
                            break;
                        }
                        if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) {
                            break;
                        }
                        list($candidateX, $candidateY) = $candidate->getBasePoint();
                        list($curveX, $curveY) = $curve->getBasePoint();
                        if ($candidateX->toBytes() != $curveX->toBytes()) {
                            break;
                        }
                        if ($candidateY->toBytes() != $curveY->toBytes()) {
                            break;
                        }
                        return $returnArray ? ['namedCurve' => $testName] : ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP);
                }
            }
        }
        $order = $curve->getOrder();
        // we could try to calculate the order thusly:
        // https://crypto.stackexchange.com/a/27914/4520
        // https://en.wikipedia.org/wiki/Schoof%E2%80%93Elkies%E2%80%93Atkin_algorithm
        if (!$order) {
            throw new \RuntimeException('Specified Curves need the order to be specified');
        }
        $point = $curve->getBasePoint();
        $x = $point[0]->toBytes();
        $y = $point[1]->toBytes();
        if ($curve instanceof PrimeCurve) {
            /*
             * valid versions are:
             *
             * ecdpVer1:
             *   - neither the curve or the base point are generated verifiably randomly.
             * ecdpVer2:
             *   - curve and base point are generated verifiably at random and curve.seed is present
             * ecdpVer3:
             *   - base point is generated verifiably at random but curve is not. curve.seed is present
             */
            // other (optional) parameters can be calculated using the methods discused at
            // https://crypto.stackexchange.com/q/28947/4520
            $data = ['version' => 'ecdpVer1', 'fieldID' => ['fieldType' => 'prime-field', 'parameters' => $curve->getModulo()], 'curve' => ['a' => $curve->getA()->toBytes(), 'b' => $curve->getB()->toBytes()], 'base' => "\x04" . $x . $y, 'order' => $order];
            return $returnArray ? ['specifiedCurve' => $data] : ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP);
        }
        if ($curve instanceof BinaryCurve) {
            $modulo = $curve->getModulo();
            $basis = count($modulo);
            $m = array_shift($modulo);
            array_pop($modulo);
            // the last parameter should always be 0
            //rsort($modulo);
            switch ($basis) {
                case 3:
                    $basis = 'tpBasis';
                    $modulo = new BigInteger($modulo[0]);
                    break;
                case 5:
                    $basis = 'ppBasis';
                    // these should be in strictly ascending order (hence the commented out rsort above)
                    $modulo = ['k1' => new BigInteger($modulo[2]), 'k2' => new BigInteger($modulo[1]), 'k3' => new BigInteger($modulo[0])];
                    $modulo = ASN1::encodeDER($modulo, Maps\Pentanomial::MAP);
                    $modulo = new ASN1\Element($modulo);
            }
            $params = ASN1::encodeDER(['m' => new BigInteger($m), 'basis' => $basis, 'parameters' => $modulo], Maps\Characteristic_two::MAP);
            $params = new ASN1\Element($params);
            $a = ltrim($curve->getA()->toBytes(), "\x00");
            if (!strlen($a)) {
                $a = "\x00";
            }
            $b = ltrim($curve->getB()->toBytes(), "\x00");
            if (!strlen($b)) {
                $b = "\x00";
            }
            $data = ['version' => 'ecdpVer1', 'fieldID' => ['fieldType' => 'characteristic-two-field', 'parameters' => $params], 'curve' => ['a' => $a, 'b' => $b], 'base' => "\x04" . $x . $y, 'order' => $order];
            return $returnArray ? ['specifiedCurve' => $data] : ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP);
        }
        throw new UnsupportedCurveException('Curve cannot be serialized');
    }
    /**
    * Use Specified Curve
    *
    * A specified curve has all the coefficients, the base points, etc, explicitely included.
    A specified curve is a more verbose way of representing a curve
    */
    public static function useSpecifiedCurve()
    {
        self::$useNamedCurves = false;
    }
    /**
    * Use Named Curve
    *
    * A named curve does not include any parameters. It is up to the EC parameters to
    know what the coefficients, the base points, etc, are from the name of the curve.
    A named curve is a more concise way of representing a curve
    */
    public static function useNamedCurve()
    {
        self::$useNamedCurves = true;
    }
}<?php

/**
 * Montgomery Private Key Handler
 *
 * "Naked" Curve25519 private keys can pretty much be any sequence of random 32x bytes so unless
 * we have a "hidden" key handler pretty much every 32 byte string will be loaded as a curve25519
 * private key even if it probably isn't one by PublicKeyLoader.
 *
 * "Naked" Curve25519 public keys also a string of 32 bytes so distinguishing between a "naked"
 * curve25519 private key and a public key is nigh impossible, hence separate plugins for each
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\Curves\Curve448;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * Montgomery Curve Private Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MontgomeryPrivate
{
    /**
     * Is invisible flag
     *
     * @access private
     */
    const IS_INVISIBLE = true;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        switch (strlen($key)) {
            case 32:
                $curve = new Curve25519();
                break;
            case 56:
                $curve = new Curve448();
                break;
            default:
                throw new \LengthException('The only supported lengths are 32 and 56');
        }
        $components = ['curve' => $curve];
        $components['dA'] = new BigInteger($key, 256);
        $curve->rangeCheck($components['dA']);
        // note that EC::getEncodedCoordinates does some additional "magic" (it does strrev on the result)
        $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
        return $components;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @return string
     */
    public static function savePublicKey(MontgomeryCurve $curve, array $publicKey)
    {
        return strrev($publicKey[0]->toBytes());
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, MontgomeryCurve $curve, array $publicKey, $password = '')
    {
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('MontgomeryPrivate private keys do not support encryption');
        }
        return $privateKey->toBytes();
    }
}<?php

/**
 * Montgomery Public Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\Curves\Curve448;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Math\Common\FiniteField\Integer;
use phpseclib3\Math\BigInteger;
/**
 * Montgomery Public Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MontgomeryPublic
{
    /**
     * Is invisible flag
     *
     * @access private
     */
    const IS_INVISIBLE = true;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        switch (strlen($key)) {
            case 32:
                $curve = new Curve25519();
                break;
            case 56:
                $curve = new Curve448();
                break;
            default:
                throw new \LengthException('The only supported lengths are 32 and 56');
        }
        $components = ['curve' => $curve];
        $components['QA'] = [$components['curve']->convertInteger(new BigInteger(strrev($key), 256))];
        return $components;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @return string
     */
    public static function savePublicKey(MontgomeryCurve $curve, array $publicKey)
    {
        return strrev($publicKey[0]->toBytes());
    }
}<?php

/**
 * ASN1 Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures in the format described in
 * https://tools.ietf.org/html/rfc3279#section-2.2.3
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Signature;

use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1 as Encoder;
use phpseclib3\File\ASN1\Maps\EcdsaSigValue;
/**
 * ASN1 Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ASN1
{
    /**
     * Loads a signature
     *
     * @access public
     * @param string $sig
     * @return array
     */
    public static function load($sig)
    {
        if (!is_string($sig)) {
            return false;
        }
        $decoded = Encoder::decodeBER($sig);
        if (empty($decoded)) {
            return false;
        }
        $components = Encoder::asn1map($decoded[0], EcdsaSigValue::MAP);
        return $components;
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s)
    {
        return Encoder::encodeDER(compact('r', 's'), EcdsaSigValue::MAP);
    }
}<?php

/**
 * Raw EC Signature Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Signature;

use phpseclib3\Crypt\Common\Formats\Signature\Raw as Progenitor;
/**
 * Raw DSA Signature Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw extends Progenitor
{
}<?php

/**
 * SSH2 Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures in the format used by SSH2
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Signature;

use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
/**
 * SSH2 Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SSH2
{
    /**
     * Loads a signature
     *
     * @access public
     * @param string $sig
     * @return mixed
     */
    public static function load($sig)
    {
        if (!is_string($sig)) {
            return false;
        }
        $result = Strings::unpackSSH2('ss', $sig);
        if ($result === false) {
            return false;
        }
        list($type, $blob) = $result;
        switch ($type) {
            // see https://tools.ietf.org/html/rfc5656#section-3.1.2
            case 'ecdsa-sha2-nistp256':
            case 'ecdsa-sha2-nistp384':
            case 'ecdsa-sha2-nistp521':
                break;
            default:
                return false;
        }
        $result = Strings::unpackSSH2('ii', $blob);
        if ($result === false) {
            return false;
        }
        return ['r' => $result[0], 's' => $result[1]];
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @param string $curve
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s, $curve)
    {
        switch ($curve) {
            case 'secp256r1':
                $curve = 'nistp256';
                break;
            case 'secp384r1':
                $curve = 'nistp384';
                break;
            case 'secp521r1':
                $curve = 'nistp521';
                break;
            default:
                return false;
        }
        $blob = Strings::packSSH2('ii', $r, $s);
        return Strings::packSSH2('ss', 'ecdsa-sha2-' . $curve, $blob);
    }
}<?php

/**
 * EC Parameters
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC;

use phpseclib3\Crypt\EC;
/**
 * EC Parameters
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Parameters extends EC
{
    /**
     * Returns the parameters
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type = 'PKCS1', array $options = [])
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        return $type::saveParameters($this->curve, $options);
    }
}<?php

/**
 * EC Private Key
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC;

use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
use phpseclib3\Crypt\Common;
use phpseclib3\Exception\UnsupportedOperationException;
use phpseclib3\Common\Functions\Strings;
/**
 * EC Private Key
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrivateKey extends EC implements Common\PrivateKey
{
    use Common\Traits\PasswordProtected;
    /**
     * Private Key dA
     *
     * sign() converts this to a BigInteger so one might wonder why this is a FiniteFieldInteger instead of
     * a BigInteger. That's because a FiniteFieldInteger, when converted to a byte string, is null padded by
     * a certain amount whereas a BigInteger isn't.
     *
     * @var object
     */
    protected $dA;
    /**
     * Multiplies an encoded point by the private key
     *
     * Used by ECDH
     *
     * @param string $coordinates
     * @return string
     */
    public function multiply($coordinates)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            if ($this->curve instanceof Curve25519 && self::$engines['libsodium']) {
                return sodium_crypto_scalarmult($this->dA->toBytes(), $coordinates);
            }
            $point = [$this->curve->convertInteger(new BigInteger(strrev($coordinates), 256))];
            $point = $this->curve->multiplyPoint($point, $this->dA);
            return strrev($point[0]->toBytes(true));
        }
        if (!$this->curve instanceof TwistedEdwardsCurve) {
            $coordinates = "\x00{$coordinates}";
        }
        $point = PKCS1::extractPoint($coordinates, $this->curve);
        $point = $this->curve->multiplyPoint($point, $this->dA);
        if ($this->curve instanceof TwistedEdwardsCurve) {
            return $this->curve->encodePoint($point);
        }
        if (empty($point)) {
            throw new \RuntimeException('The infinity point is invalid');
        }
        return "\x04" . $point[0]->toBytes(true) . $point[1]->toBytes(true);
    }
    /**
     * Create a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @return mixed
     */
    public function sign($message)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
        }
        $dA = $this->dA;
        $order = $this->curve->getOrder();
        $shortFormat = $this->shortFormat;
        $format = $this->sigFormat;
        if ($format === false) {
            return false;
        }
        if ($this->curve instanceof TwistedEdwardsCurve) {
            if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
                $result = sodium_crypto_sign_detached($message, $this->toString('libsodium'));
                return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $result) : $result;
            }
            // contexts (Ed25519ctx) are supported but prehashing (Ed25519ph) is not.
            // quoting https://tools.ietf.org/html/rfc8032#section-8.5 ,
            // "The Ed25519ph and Ed448ph variants ... SHOULD NOT be used"
            $A = $this->curve->encodePoint($this->QA);
            $curve = $this->curve;
            $hash = new Hash($curve::HASH);
            $secret = \Phabel\Target\Php80\Polyfill::substr($hash->hash($this->dA->secret), $curve::SIZE);
            if ($curve instanceof Ed25519) {
                $dom = !isset($this->context) ? '' : 'SigEd25519 no Ed25519 collisions ' . chr(strlen($this->context)) . $this->context;
            } else {
                $context = isset($this->context) ? $this->context : '';
                $dom = 'SigEd448 ' . chr(strlen($context)) . $context;
            }
            // SHA-512(dom2(F, C) || prefix || PH(M))
            $r = $hash->hash($dom . $secret . $message);
            $r = strrev($r);
            $r = new BigInteger($r, 256);
            list(, $r) = $r->divide($order);
            $R = $curve->multiplyPoint($curve->getBasePoint(), $r);
            $R = $curve->encodePoint($R);
            $k = $hash->hash($dom . $R . $A . $message);
            $k = strrev($k);
            $k = new BigInteger($k, 256);
            list(, $k) = $k->divide($order);
            $S = $k->multiply($dA)->add($r);
            list(, $S) = $S->divide($order);
            $S = str_pad(strrev($S->toBytes()), $curve::SIZE, "\x00");
            return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $R . $S) : $R . $S;
        }
        if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
            $signature = '';
            // altho PHP's OpenSSL bindings only supported EC key creation in PHP 7.1 they've long
            // supported signing / verification
            // we use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve;
            // doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even
            // has curve-specific optimizations
            $result = openssl_sign($message, $signature, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash());
            if ($result) {
                if ($shortFormat == 'ASN1') {
                    return $signature;
                }
                extract(ASN1Signature::load($signature));
                return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s);
            }
        }
        $e = $this->hash->hash($message);
        $e = new BigInteger($e, 256);
        $Ln = $this->hash->getLength() - $order->getLength();
        $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e;
        while (true) {
            $k = BigInteger::randomRange(self::$one, $order->subtract(self::$one));
            list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $k);
            $x = $x->toBigInteger();
            list(, $r) = $x->divide($order);
            if ($r->equals(self::$zero)) {
                continue;
            }
            $kinv = $k->modInverse($order);
            $temp = $z->add($dA->multiply($r));
            $temp = $kinv->multiply($temp);
            list(, $s) = $temp->divide($order);
            if (!$s->equals(self::$zero)) {
                break;
            }
        }
        // the following is an RFC6979 compliant implementation of deterministic ECDSA
        // it's unused because it's mainly intended for use when a good CSPRNG isn't
        // available. if phpseclib's CSPRNG isn't good then even key generation is
        // suspect
        /*
        // if this were actually being used it'd probably be better if this lived in load() and createKey()
        $this->q = $this->curve->getOrder();
        $dA = $this->dA->toBigInteger();
        $this->x = $dA;
        
        $h1 = $this->hash->hash($message);
        $k = $this->computek($h1);
        list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $k);
        $x = $x->toBigInteger();
        list(, $r) = $x->divide($this->q);
        $kinv = $k->modInverse($this->q);
        $h1 = $this->bits2int($h1);
        $temp = $h1->add($dA->multiply($r));
        $temp = $kinv->multiply($temp);
        list(, $s) = $temp->divide($this->q);
        */
        return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s);
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePrivateKey');
        return $type::savePrivateKey($this->dA, $this->curve, $this->QA, $this->password, $options);
    }
    /**
     * Returns the public key
     *
     * @see self::getPrivateKey()
     * @access public
     * @return mixed
     */
    public function getPublicKey()
    {
        $format = 'PKCS8';
        if ($this->curve instanceof MontgomeryCurve) {
            $format = 'MontgomeryPublic';
        }
        $type = self::validatePlugin('Keys', $format, 'savePublicKey');
        $key = $type::savePublicKey($this->curve, $this->QA);
        $key = EC::loadFormat($format, $key);
        if ($this->curve instanceof MontgomeryCurve) {
            return $key;
        }
        $key = $key->withHash($this->hash->getHash())->withSignatureFormat($this->shortFormat);
        if ($this->curve instanceof TwistedEdwardsCurve) {
            $key = $key->withContext($this->context);
        }
        return $key;
    }
}<?php

/**
 * sect131r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect131r2 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(131, 8, 3, 2, 0);
        $this->setCoefficients('03E5A88919D7CAFCBF415F07C2176573B2', '04B8266A46C55657AC734CE38F018F2192');
        $this->setBasePoint('0356DCD8F2F95031AD652D23951BB366A8', '0648F06D867940A5366D9E265DE9EB240F');
        $this->setOrder(new BigInteger('0400000000000000016954A233049BA98F', 16));
    }
}<?php

/**
 * brainpoolP192t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP192t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297', 16));
        $this->setCoefficients(
            new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294', 16),
            // eg. -3
            new BigInteger('13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79', 16)
        );
        $this->setBasePoint(new BigInteger('3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129', 16), new BigInteger('097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9', 16));
        $this->setOrder(new BigInteger('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16));
    }
}<?php

/**
 * secp192k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime;
use phpseclib3\Math\BigInteger;
class secp192k1 extends KoblitzPrime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37', 16));
        $this->setCoefficients(new BigInteger('000000000000000000000000000000000000000000000000', 16), new BigInteger('000000000000000000000000000000000000000000000003', 16));
        $this->setBasePoint(new BigInteger('DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D', 16), new BigInteger('9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D', 16));
        $this->basis = [];
        $this->basis[] = ['a' => new BigInteger('00B3FB3400DEC5C4ADCEB8655C', -16), 'b' => new BigInteger('8EE96418CCF4CFC7124FDA0F', -16)];
        $this->basis[] = ['a' => new BigInteger('01D90D03E8F096B9948B20F0A9', -16), 'b' => new BigInteger('42E49819ABBA9474E1083F6B', -16)];
        $this->beta = $this->factory->newInteger(new BigInteger('447A96E6C647963E2F7809FEAAB46947F34B0AA3CA0BBA74', -16));
    }
}<?php

/**
 * sect113r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect113r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(113, 9, 0);
        $this->setCoefficients('003088250CA6E7C7FE649CE85820F7', '00E8BEE4D3E2260744188BE0E9C723');
        $this->setBasePoint('009D73616F35F4AB1407D73562C10F', '00A52830277958EE84D1315ED31886');
        $this->setOrder(new BigInteger('0100000000000000D9CCEC8A39E56F', 16));
    }
}<?php

/**
 * Ed448
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
class Ed448 extends TwistedEdwards
{
    const HASH = 'shake256-912';
    const SIZE = 57;
    /**
     *
     */
    public function __construct()
    {
        // 2^448 - 2^224 - 1
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(
            new BigInteger(1),
            // -39081
            new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6756', 16)
        );
        $this->setBasePoint(new BigInteger('4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E', 16), new BigInteger('693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14', 16));
        $this->setOrder(new BigInteger('3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3', 16));
    }
    /**
     * Recover X from Y
     *
     * Implements steps 2-4 at https://tools.ietf.org/html/rfc8032#section-5.2.3
     *
     * Used by EC\Keys\Common.php
     *
     * @param BigInteger $y
     * @param boolean $sign
     * @return object[]
     */
    public function recoverX(BigInteger $y, $sign)
    {
        $y = $this->factory->newInteger($y);
        $y2 = $y->multiply($y);
        $u = $y2->subtract($this->one);
        $v = $this->d->multiply($y2)->subtract($this->one);
        $x2 = $u->divide($v);
        if ($x2->equals($this->zero)) {
            if ($sign) {
                throw new \RuntimeException('Unable to recover X coordinate (x2 = 0)');
            }
            return clone $this->zero;
        }
        // find the square root
        $exp = $this->getModulo()->add(new BigInteger(1));
        $exp = $exp->bitwise_rightShift(2);
        $x = $x2->pow($exp);
        if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
            throw new \RuntimeException('Unable to recover X coordinate');
        }
        if ($x->isOdd() != $sign) {
            $x = $x->negate();
        }
        return [$x, $y];
    }
    /**
     * Extract Secret Scalar
     *
     * Implements steps 1-3 at https://tools.ietf.org/html/rfc8032#section-5.2.5
     *
     * Used by the various key handlers
     *
     * @param string $str
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function extractSecret($str)
    {
        if (strlen($str) != 57) {
            throw new \LengthException('Private Key should be 57-bytes long');
        }
        // 1.  Hash the 57-byte private key using SHAKE256(x, 114), storing the
        //     digest in a 114-octet large buffer, denoted h.  Only the lower 57
        //     bytes are used for generating the public key.
        $hash = new Hash('shake256-912');
        $h = $hash->hash($str);
        $h = \Phabel\Target\Php80\Polyfill::substr($h, 0, 57);
        // 2.  Prune the buffer: The two least significant bits of the first
        //     octet are cleared, all eight bits the last octet are cleared, and
        //     the highest bit of the second to last octet is set.
        $h[0] = $h[0] & chr(0xfc);
        $h = strrev($h);
        $h[0] = "\x00";
        $h[1] = $h[1] | chr(0x80);
        // 3.  Interpret the buffer as the little-endian integer, forming a
        //     secret scalar s.
        $dA = new BigInteger($h, 256);
        $dA->secret = $str;
        return $dA;
    }
    /**
     * Encode a point as a string
     *
     * @param array $point
     * @return string
     */
    public function encodePoint($point)
    {
        list($x, $y) = $point;
        $y = "\x00" . $y->toBytes();
        if ($x->isOdd()) {
            $y[0] = $y[0] | chr(0x80);
        }
        $y = strrev($y);
        return $y;
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function createRandomMultiplier()
    {
        return $this->extractSecret(Random::string(57));
    }
    /**
    * Converts an affine point to an extended homogeneous coordinate
    *
    * From https://tools.ietf.org/html/rfc8032#section-5.2.4 :
    *
    * A point (x,y) is represented in extended homogeneous coordinates (X, Y, Z, T),
    with x = X/Z, y = Y/Z, x * y = T/Z.
    *
    * @return \phpseclib3\Math\PrimeField\Integer[]
    */
    public function convertToInternal(array $p)
    {
        if (empty($p)) {
            return [clone $this->zero, clone $this->one, clone $this->one];
        }
        if (isset($p[2])) {
            return $p;
        }
        $p[2] = clone $this->one;
        return $p;
    }
    /**
     * Doubles a point on a curve
     *
     * @return FiniteField[]
     */
    public function doublePoint(array $p)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p)) {
            return [];
        }
        if (!isset($p[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        // from https://tools.ietf.org/html/rfc8032#page-18
        list($x1, $y1, $z1) = $p;
        $b = $x1->add($y1);
        $b = $b->multiply($b);
        $c = $x1->multiply($x1);
        $d = $y1->multiply($y1);
        $e = $c->add($d);
        $h = $z1->multiply($z1);
        $j = $e->subtract($this->two->multiply($h));
        $x3 = $b->subtract($e)->multiply($j);
        $y3 = $c->subtract($d)->multiply($e);
        $z3 = $e->multiply($j);
        return [$x3, $y3, $z3];
    }
    /**
     * Adds two points on the curve
     *
     * @return FiniteField[]
     */
    public function addPoint(array $p, array $q)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            if (count($q)) {
                return $q;
            }
            if (count($p)) {
                return $p;
            }
            return [];
        }
        if (!isset($p[2]) || !isset($q[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        if ($p[0]->equals($q[0])) {
            return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
        }
        // from https://tools.ietf.org/html/rfc8032#page-17
        list($x1, $y1, $z1) = $p;
        list($x2, $y2, $z2) = $q;
        $a = $z1->multiply($z2);
        $b = $a->multiply($a);
        $c = $x1->multiply($x2);
        $d = $y1->multiply($y2);
        $e = $this->d->multiply($c)->multiply($d);
        $f = $b->subtract($e);
        $g = $b->add($e);
        $h = $x1->add($y1)->multiply($x2->add($y2));
        $x3 = $a->multiply($f)->multiply($h->subtract($c)->subtract($d));
        $y3 = $a->multiply($g)->multiply($d->subtract($c));
        $z3 = $f->multiply($g);
        return [$x3, $y3, $z3];
    }
}<?php

/**
 * sect113r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect113r2 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(113, 9, 0);
        $this->setCoefficients('00689918DBEC7E5A0DD6DFC0AA55C7', '0095E9A9EC9B297BD4BF36E059184F');
        $this->setBasePoint('01A57A6A7B26CA5EF52FCDB8164797', '00B3ADC94ED1FE674C06E695BABA1D');
        $this->setOrder(new BigInteger('010000000000000108789B2496AF93', 16));
    }
}<?php

/**
 * prime192v1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class prime192v1 extends secp192r1
{
}<?php

/**
 * sect409r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect409r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(409, 87, 0);
        $this->setCoefficients('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', '0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F');
        $this->setBasePoint('015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7', '0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706');
        $this->setOrder(new BigInteger('010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173', 16));
    }
}<?php

/**
 * brainpoolP384r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP384r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53', 16));
        $this->setCoefficients(new BigInteger('7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826', 16), new BigInteger('4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11', 16));
        $this->setBasePoint(new BigInteger('1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E', 16), new BigInteger('8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315', 16));
        $this->setOrder(new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565', 16));
    }
}<?php

/**
 * nistk233
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistk233 extends sect233k1
{
}<?php

/**
 * secp128r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp128r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC', 16), new BigInteger('E87579C11079F43DD824993C2CEE5ED3', 16));
        $this->setBasePoint(new BigInteger('161FF7528B899B2D0C28607CA52C5B86', 16), new BigInteger('CF5AC8395BAFEB13C02DA292DDED7A83', 16));
        $this->setOrder(new BigInteger('FFFFFFFE0000000075A30D1B9038A115', 16));
    }
}<?php

/**
 * Curve25519
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Montgomery;
use phpseclib3\Math\BigInteger;
class Curve25519 extends Montgomery
{
    /**
     *
     */
    public function __construct()
    {
        // 2^255 - 19
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16));
        $this->a24 = $this->factory->newInteger(new BigInteger('121666'));
        $this->p = [$this->factory->newInteger(new BigInteger(9))];
        // 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed
        $this->setOrder(new BigInteger('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED', 16));
        /*
        $this->setCoefficients(
            new BigInteger('486662'), // a
        );
        $this->setBasePoint(
            new BigInteger(9),
            new BigInteger('14781619447589544791020593568409986887264606134616475288964881837755586237401')
        );
        */
    }
    /**
     * Multiply a point on the curve by a scalar
     *
     * Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8
     *
     * @return array
     */
    public function multiplyPoint(array $p, BigInteger $d)
    {
        //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes())));
        //return [$this->factory->newInteger(new BigInteger($r, 256))];
        $d = $d->toBytes();
        $d &= "\xf8" . str_repeat("\xff", 30) . "";
        $d = strrev($d);
        $d |= "@";
        $d = new BigInteger($d, -256);
        return parent::multiplyPoint($p, $d);
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return BigInteger
     */
    public function createRandomMultiplier()
    {
        return BigInteger::random(256);
    }
    /**
     * Performs range check
     */
    public function rangeCheck(BigInteger $x)
    {
        if ($x->getLength() > 256 || $x->isNegative()) {
            throw new \RangeException('x must be a positive integer less than 256 bytes in length');
        }
    }
}<?php

/**
 * brainpoolP320t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP320t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27', 16));
        $this->setCoefficients(
            new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24', 16),
            // eg. -3
            new BigInteger('A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353', 16)
        );
        $this->setBasePoint(new BigInteger('925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52', 16), new BigInteger('63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3', 16));
        $this->setOrder(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311', 16));
    }
}<?php

/**
 * brainpoolP256t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP256t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16));
        $this->setCoefficients(
            new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374', 16),
            // eg. -3
            new BigInteger('662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04', 16)
        );
        $this->setBasePoint(new BigInteger('A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4', 16), new BigInteger('2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE', 16));
        $this->setOrder(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16));
    }
}<?php

/**
 * sect163k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect163k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(163, 7, 6, 3, 0);
        $this->setCoefficients('000000000000000000000000000000000000000001', '000000000000000000000000000000000000000001');
        $this->setBasePoint('02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8', '0289070FB05D38FF58321F2E800536D538CCDAA3D9');
        $this->setOrder(new BigInteger('04000000000000000000020108A2E0CC0D99F8A5EF', 16));
    }
}<?php

/**
 * brainpoolP320r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP320r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27', 16));
        $this->setCoefficients(new BigInteger('3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4', 16), new BigInteger('520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6', 16));
        $this->setBasePoint(new BigInteger('43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611', 16), new BigInteger('14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1', 16));
        $this->setOrder(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311', 16));
    }
}<?php

/**
 * sect283k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect283k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(283, 12, 7, 5, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836', '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259');
        $this->setOrder(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61', 16));
    }
}<?php

/**
 * sect131r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect131r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(131, 8, 3, 2, 0);
        $this->setCoefficients('07A11B09A76B562144418FF3FF8C2570B8', '0217C05610884B63B9C6C7291678F9D341');
        $this->setBasePoint('0081BAF91FDF9833C40F9C181343638399', '078C6E7EA38C001F73C8134B1B4EF9E150');
        $this->setOrder(new BigInteger('0400000000000000023123953A9464B54D', 16));
    }
}<?php

/**
 * secp192r1
 *
 * This is the NIST P-192 curve
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp192r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $modulo = new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16);
        $this->setModulo($modulo);
        // algorithm 2.27 from http://diamond.boisestate.edu/~liljanab/MATH308/GuideToECC.pdf#page=66
        /* in theory this should be faster than regular modular reductions save for one small issue.
              to convert to / from base-2**8 with BCMath you have to call bcmul() and bcdiv() a lot.
              to convert to / from base-2**8 with PHP64 you have to call base256_rshift() a lot.
              in short, converting to / from base-2**8 is pretty expensive and that expense is
              enough to offset whatever else might be gained by a simplified reduction algorithm.
              now, if PHP supported unsigned integers things might be different. no bit-shifting
              would be required for the PHP engine and it'd be a lot faster. but as is, BigInteger
              uses base-2**31 or base-2**26 depending on whether or not the system is has a 32-bit
              or a 64-bit OS.           
           */
        /*
        $m_length = $this->getLengthInBytes();
        $this->setReduction(function($c) use ($m_length) {
            $cBytes = $c->toBytes();
            $className = $this->className;
        
            if (strlen($cBytes) > 2 * $m_length) {
                list(, $r) = $c->divide($className::$modulo);
                return $r;
            }
        
            $c = str_pad($cBytes, 48, "\0", STR_PAD_LEFT);
            $c = array_reverse(str_split($c, 8));
        
            $null = "\0\0\0\0\0\0\0\0";
            $s1 = new BigInteger($c[2] . $c[1] . $c[0], 256);
            $s2 = new BigInteger($null . $c[3] . $c[3], 256);
            $s3 = new BigInteger($c[4] . $c[4] . $null, 256);
            $s4 = new BigInteger($c[5] . $c[5] . $c[5], 256);
        
            $r = $s1->add($s2)->add($s3)->add($s4);
            while ($r->compare($className::$modulo) >= 0) {
                $r = $r->subtract($className::$modulo);
            }
        
            return $r;
        });
        */
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), new BigInteger('64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1', 16));
        $this->setBasePoint(new BigInteger('188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012', 16), new BigInteger('07192B95FFC8DA78631011ED6B24CDD573F977A11E794811', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831', 16));
    }
}<?php

/**
 * Curve448
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Montgomery;
use phpseclib3\Math\BigInteger;
class Curve448 extends Montgomery
{
    /**
     *
     */
    public function __construct()
    {
        // 2^448 - 2^224 - 1
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->a24 = $this->factory->newInteger(new BigInteger('39081'));
        $this->p = [$this->factory->newInteger(new BigInteger(5))];
        // 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
        $this->setOrder(new BigInteger('3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3', 16));
        /*
        $this->setCoefficients(
            new BigInteger('156326'), // a
        );
        $this->setBasePoint(
            new BigInteger(5),
            new BigInteger(
                '355293926785568175264127502063783334808976399387714271831880898' .
                '435169088786967410002932673765864550910142774147268105838985595290' .
                '606362')
        );
        */
    }
    /**
     * Multiply a point on the curve by a scalar
     *
     * Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8
     *
     * @return array
     */
    public function multiplyPoint(array $p, BigInteger $d)
    {
        //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes())));
        //return [$this->factory->newInteger(new BigInteger($r, 256))];
        $d = $d->toBytes();
        $d[0] = $d[0] & "\xfc";
        $d = strrev($d);
        $d |= "\x80";
        $d = new BigInteger($d, 256);
        return parent::multiplyPoint($p, $d);
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return BigInteger
     */
    public function createRandomMultiplier()
    {
        return BigInteger::random(446);
    }
    /**
     * Performs range check
     */
    public function rangeCheck(BigInteger $x)
    {
        if ($x->getLength() > 448 || $x->isNegative()) {
            throw new \RangeException('x must be a positive integer less than 446 bytes in length');
        }
    }
}<?php

/**
 * secp112r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp112r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('DB7C2ABF62E35E668076BEAD208B', 16));
        $this->setCoefficients(new BigInteger('DB7C2ABF62E35E668076BEAD2088', 16), new BigInteger('659EF8BA043916EEDE8911702B22', 16));
        $this->setBasePoint(new BigInteger('09487239995A5EE76B55F9C2F098', 16), new BigInteger('A89CE5AF8724C0A23E0E0FF77500', 16));
        $this->setOrder(new BigInteger('DB7C2ABF62E35E7628DFAC6561C5', 16));
    }
}<?php

/**
 * nistk163
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistk163 extends sect163k1
{
}<?php

/**
 * prime239v3
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime239v3 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), new BigInteger('255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E', 16));
        $this->setBasePoint(new BigInteger('6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A', 16), new BigInteger('1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3', 16));
        $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551', 16));
    }
}<?php

/**
 * secp128r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp128r2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        // same as secp128r1
        $this->setModulo(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('D6031998D1B3BBFEBF59CC9BBFF9AEE1', 16), new BigInteger('5EEEFCA380D02919DC2C6558BB6D8A5D', 16));
        $this->setBasePoint(new BigInteger('7B6AA5D85E572983E6FB32A7CDEBC140', 16), new BigInteger('27B6916A894D3AEE7106FE805FC34B44', 16));
        $this->setOrder(new BigInteger('3FFFFFFF7FFFFFFFBE0024720613B5A3', 16));
    }
}<?php

/**
 * brainpoolP256r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP256r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16));
        $this->setCoefficients(new BigInteger('7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9', 16), new BigInteger('26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6', 16));
        $this->setBasePoint(new BigInteger('8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', 16), new BigInteger('547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997', 16));
        $this->setOrder(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16));
    }
}<?php

/**
 * prime256v1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class prime256v1 extends secp256r1
{
}<?php

/**
 * brainpoolP192r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP192r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297', 16));
        $this->setCoefficients(new BigInteger('6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF', 16), new BigInteger('469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9', 16));
        $this->setBasePoint(new BigInteger('C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6', 16), new BigInteger('14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F', 16));
        $this->setOrder(new BigInteger('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16));
    }
}<?php

/**
 * prime192v2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime192v2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), new BigInteger('CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953', 16));
        $this->setBasePoint(new BigInteger('EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A', 16), new BigInteger('6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31', 16));
    }
}<?php

/**
 * sect239k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect239k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(239, 158, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC', '76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA');
        $this->setOrder(new BigInteger('2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5', 16));
    }
}<?php

/**
 * sect233r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect233r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(233, 74, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000001', '0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD');
        $this->setBasePoint('00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B', '01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052');
        $this->setOrder(new BigInteger('01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7', 16));
    }
}<?php

/**
 * sect163r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect163r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(163, 7, 6, 3, 0);
        $this->setCoefficients('07B6882CAAEFA84F9554FF8428BD88E246D2782AE2', '0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9');
        $this->setBasePoint('0369979697AB43897789566789567F787A7876A654', '00435EDB42EFAFB2989D51FEFCE3C80988F41FF883');
        $this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B', 16));
    }
}<?php

/**
 * nistp256
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp256 extends secp256r1
{
}<?php

/**
 * sect233k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect233k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(233, 74, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126', '01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3');
        $this->setOrder(new BigInteger('8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF', 16));
    }
}<?php

/**
 * nistk409
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistk409 extends sect409k1
{
}<?php

/**
 * brainpoolP512t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP512t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3', 16));
        $this->setCoefficients(
            new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0', 16),
            // eg. -3
            new BigInteger('7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E', 16)
        );
        $this->setBasePoint(new BigInteger('640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA', 16), new BigInteger('5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332', 16));
        $this->setOrder(new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069', 16));
    }
}<?php

/**
 * sect163r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect163r2 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(163, 7, 6, 3, 0);
        $this->setCoefficients('000000000000000000000000000000000000000001', '020A601907B8C953CA1481EB10512F78744A3205FD');
        $this->setBasePoint('03F0EBA16286A2D57EA0991168D4994637E8343E36', '00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1');
        $this->setOrder(new BigInteger('040000000000000000000292FE77E70C12A4234C33', 16));
    }
}<?php

/**
 * brainpoolP384t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP384t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53', 16));
        $this->setCoefficients(
            new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50', 16),
            // eg. -3
            new BigInteger('7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE', 16)
        );
        $this->setBasePoint(new BigInteger('18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC', 16), new BigInteger('25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928', 16));
        $this->setOrder(new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565', 16));
    }
}<?php

/**
 * sect571k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect571k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(571, 10, 5, 2, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972', '0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3');
        $this->setOrder(new BigInteger('020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001', 16));
    }
}<?php

/**
 * secp521r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp521r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC', 16), new BigInteger('0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00', 16));
        $this->setBasePoint(new BigInteger('00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66', 16), new BigInteger('011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650', 16));
        $this->setOrder(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409', 16));
    }
}<?php

/**
 * sect283k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistk283 extends sect283k1
{
}<?php

/**
 * prime239v2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime239v2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), new BigInteger('617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C', 16));
        $this->setBasePoint(new BigInteger('38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7', 16), new BigInteger('5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA', 16));
        $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063', 16));
    }
}<?php

/**
 * secp160k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime;
use phpseclib3\Math\BigInteger;
class secp160k1 extends KoblitzPrime
{
    /**
     *
     */
    public function __construct()
    {
        // same as secp160r2
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73', 16));
        $this->setCoefficients(new BigInteger('0000000000000000000000000000000000000000', 16), new BigInteger('0000000000000000000000000000000000000007', 16));
        $this->setBasePoint(new BigInteger('3B4C382CE37AA192A4019E763036F4F5DD4D7EBB', 16), new BigInteger('938CF935318FDCED6BC28286531733C3F03C4FEE', 16));
        $this->setOrder(new BigInteger('0100000000000000000001B8FA16DFAB9ACA16B6B3', 16));
        $this->basis = [];
        $this->basis[] = ['a' => new BigInteger('0096341F1138933BC2F505', -16), 'b' => new BigInteger('FF6E9D0418C67BB8D5F562', -16)];
        $this->basis[] = ['a' => new BigInteger('01BDCB3A09AAAABEAFF4A8', -16), 'b' => new BigInteger('04D12329FF0EF498EA67', -16)];
        $this->beta = $this->factory->newInteger(new BigInteger('645B7345A143464942CC46D7CF4D5D1E1E6CBB68', -16));
    }
}<?php

/**
 * secp112r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp112r2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        // same modulo as secp112r1
        $this->setModulo(new BigInteger('DB7C2ABF62E35E668076BEAD208B', 16));
        $this->setCoefficients(new BigInteger('6127C24C05F38A0AAAF65C0EF02C', 16), new BigInteger('51DEF1815DB5ED74FCC34C85D709', 16));
        $this->setBasePoint(new BigInteger('4BA30AB5E892B4E1649DD0928643', 16), new BigInteger('ADCD46F5882E3747DEF36E956E97', 16));
        $this->setOrder(new BigInteger('36DF0AAFD8B8D7597CA10520D04B', 16));
    }
}<?php

/**
 * secp256r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp256r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC', 16), new BigInteger('5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B', 16));
        $this->setBasePoint(new BigInteger('6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296', 16), new BigInteger('4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5', 16));
        $this->setOrder(new BigInteger('FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551', 16));
    }
}<?php

/**
 * secp256k1
 *
 * This is the curve used in Bitcoin
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

//use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime;
use phpseclib3\Math\BigInteger;
//class secp256k1 extends Prime
class secp256k1 extends KoblitzPrime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16));
        $this->setCoefficients(new BigInteger('0000000000000000000000000000000000000000000000000000000000000000', 16), new BigInteger('0000000000000000000000000000000000000000000000000000000000000007', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16));
        $this->setBasePoint(new BigInteger('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16), new BigInteger('483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 16));
        $this->basis = [];
        $this->basis[] = ['a' => new BigInteger('3086D221A7D46BCDE86C90E49284EB15', -16), 'b' => new BigInteger('FF1BBC8129FEF177D790AB8056F5401B3D', -16)];
        $this->basis[] = ['a' => new BigInteger('114CA50F7A8E2F3F657C1108D9D44CFD8', -16), 'b' => new BigInteger('3086D221A7D46BCDE86C90E49284EB15', -16)];
        $this->beta = $this->factory->newInteger(new BigInteger('7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE', -16));
    }
}<?php

/**
 * prime192v3
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime192v3 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), new BigInteger('22123DC2395A05CAA7423DAECCC94760A7D462256BD56916', 16));
        $this->setBasePoint(new BigInteger('7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896', 16), new BigInteger('38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13', 16));
    }
}<?php

/**
 * brainpoolP160t1
 *
 * This curve is a twisted version of brainpoolP160r1 with A = -3. With brainpool,
 * the curves ending in r1 are the "regular" curves and the curves ending in "t1"
 * are the twisted version of the r1 curves. Per https://tools.ietf.org/html/rfc5639#page-7
 * you can convert a point on an r1 curve to a point on a t1 curve thusly:
 *
 *     F(x,y) := (x*Z^2, y*Z^3)
 *
 * The advantage of A = -3 is that some of the point doubling and point addition can be
 * slightly optimized. See http://hyperelliptic.org/EFD/g1p/auto-shortw-projective-3.html
 * vs http://hyperelliptic.org/EFD/g1p/auto-shortw-projective.html for example.
 *
 * phpseclib does not currently take advantage of this optimization opportunity
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP160t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620F', 16));
        $this->setCoefficients(
            new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620C', 16),
            // eg. -3
            new BigInteger('7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380', 16)
        );
        $this->setBasePoint(new BigInteger('B199B13B9B34EFC1397E64BAEB05ACC265FF2378', 16), new BigInteger('ADD6718B7C7C1961F0991B842443772152C9E0AD', 16));
        $this->setOrder(new BigInteger('E95E4A5F737059DC60DF5991D45029409E60FC09', 16));
    }
}<?php

/**
 * brainpoolP160r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP160r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620F', 16));
        $this->setCoefficients(new BigInteger('340E7BE2A280EB74E2BE61BADA745D97E8F7C300', 16), new BigInteger('1E589A8595423412134FAA2DBDEC95C8D8675E58', 16));
        $this->setBasePoint(new BigInteger('BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3', 16), new BigInteger('1667CB477A1A8EC338F94741669C976316DA6321', 16));
        $this->setOrder(new BigInteger('E95E4A5F737059DC60DF5991D45029409E60FC09', 16));
    }
}<?php

/**
 * secp224r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp224r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE', 16), new BigInteger('B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4', 16));
        $this->setBasePoint(new BigInteger('B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21', 16), new BigInteger('BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D', 16));
    }
}<?php

/**
 * nistt571
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistt571 extends sect571k1
{
}<?php

/**
 * brainpoolP512r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP512r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3', 16));
        $this->setCoefficients(new BigInteger('7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA', 16), new BigInteger('3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723', 16));
        $this->setBasePoint(new BigInteger('81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', 16), new BigInteger('7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892', 16));
        $this->setOrder(new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069', 16));
    }
}<?php

/**
 * nistp192
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp192 extends secp192r1
{
}<?php

/**
 * nistp521
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp521 extends secp521r1
{
}<?php

/**
 * nistp224
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp224 extends secp224r1
{
}<?php

/**
 * secp224k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime;
use phpseclib3\Math\BigInteger;
class secp224k1 extends KoblitzPrime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D', 16));
        $this->setCoefficients(new BigInteger('00000000000000000000000000000000000000000000000000000000', 16), new BigInteger('00000000000000000000000000000000000000000000000000000005', 16));
        $this->setBasePoint(new BigInteger('A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C', 16), new BigInteger('7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5', 16));
        $this->setOrder(new BigInteger('010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7', 16));
        $this->basis = [];
        $this->basis[] = ['a' => new BigInteger('00B8ADF1378A6EB73409FA6C9C637D', -16), 'b' => new BigInteger('94730F82B358A3776A826298FA6F', -16)];
        $this->basis[] = ['a' => new BigInteger('01DCE8D2EC6184CAF0A972769FCC8B', -16), 'b' => new BigInteger('4D2100BA3DC75AAB747CCF355DEC', -16)];
        $this->beta = $this->factory->newInteger(new BigInteger('01F178FFA4B17C89E6F73AECE2AAD57AF4C0A748B63C830947B27E04', -16));
    }
}<?php

/**
 * nistp384
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp384 extends secp384r1
{
}<?php

/**
 * secp160r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp160r2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        // same as secp160k1
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70', 16), new BigInteger('B4E134D3FB59EB8BAB57274904664D5AF50388BA', 16));
        $this->setBasePoint(new BigInteger('52DCB034293A117E1F4FF11B30F7199D3144CE6D', 16), new BigInteger('FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E', 16));
        $this->setOrder(new BigInteger('0100000000000000000000351EE786A818F3A1A16B', 16));
    }
}<?php

/**
 * prime239v1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime239v1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), new BigInteger('6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A', 16));
        $this->setBasePoint(new BigInteger('0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF', 16), new BigInteger('7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE', 16));
        $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B', 16));
    }
}<?php

/**
 * Ed25519
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
class Ed25519 extends TwistedEdwards
{
    const HASH = 'sha512';
    /*
      Per https://tools.ietf.org/html/rfc8032#page-6 EdDSA has several parameters, one of which is b:
    
      2.   An integer b with 2^(b-1) > p.  EdDSA public keys have exactly b
           bits, and EdDSA signatures have exactly 2*b bits.  b is
           recommended to be a multiple of 8, so public key and signature
           lengths are an integral number of octets.
    
      SIZE corresponds to b
    */
    const SIZE = 32;
    /**
     *
     */
    public function __construct()
    {
        // 2^255 - 19
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16));
        $this->setCoefficients(
            // -1
            new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC', 16),
            // a
            // -121665/121666
            new BigInteger('52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3', 16)
        );
        $this->setBasePoint(new BigInteger('216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A', 16), new BigInteger('6666666666666666666666666666666666666666666666666666666666666658', 16));
        $this->setOrder(new BigInteger('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED', 16));
        // algorithm 14.47 from http://cacr.uwaterloo.ca/hac/about/chap14.pdf#page=16
        /*
        $this->setReduction(function($x) {
            $parts = $x->bitwise_split(255);
            $className = $this->className;
        
            if (count($parts) > 2) {
                list(, $r) = $x->divide($className::$modulo);
                return $r;
            }
        
            $zero = new BigInteger();
            $c = new BigInteger(19);
        
            switch (count($parts)) {
                case 2:
                    list($qi, $ri) = $parts;
                    break;
                case 1:
                    $qi = $zero;
                    list($ri) = $parts;
                    break;
                case 0:
                    return $zero;
            }
            $r = $ri;
        
            while ($qi->compare($zero) > 0) {
                $temp = $qi->multiply($c)->bitwise_split(255);
                if (count($temp) == 2) {
                    list($qi, $ri) = $temp;
                } else {
                    $qi = $zero;
                    list($ri) = $temp;
                }
                $r = $r->add($ri);
            }
        
            while ($r->compare($className::$modulo) > 0) {
                $r = $r->subtract($className::$modulo);
            }
            return $r;
        });
        */
    }
    /**
     * Recover X from Y
     *
     * Implements steps 2-4 at https://tools.ietf.org/html/rfc8032#section-5.1.3
     *
     * Used by EC\Keys\Common.php
     *
     * @param BigInteger $y
     * @param boolean $sign
     * @return object[]
     */
    public function recoverX(BigInteger $y, $sign)
    {
        $y = $this->factory->newInteger($y);
        $y2 = $y->multiply($y);
        $u = $y2->subtract($this->one);
        $v = $this->d->multiply($y2)->add($this->one);
        $x2 = $u->divide($v);
        if ($x2->equals($this->zero)) {
            if ($sign) {
                throw new \RuntimeException('Unable to recover X coordinate (x2 = 0)');
            }
            return clone $this->zero;
        }
        // find the square root
        /* we don't do $x2->squareRoot() because, quoting from
                   https://tools.ietf.org/html/rfc8032#section-5.1.1:
        
                   "For point decoding or "decompression", square roots modulo p are
                    needed.  They can be computed using the Tonelli-Shanks algorithm or
                    the special case for p = 5 (mod 8).  To find a square root of a,
                    first compute the candidate root x = a^((p+3)/8) (mod p)."
                 */
        $exp = $this->getModulo()->add(new BigInteger(3));
        $exp = $exp->bitwise_rightShift(3);
        $x = $x2->pow($exp);
        // If v x^2 = -u (mod p), set x <-- x * 2^((p-1)/4), which is a square root.
        if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
            $temp = $this->getModulo()->subtract(new BigInteger(1));
            $temp = $temp->bitwise_rightShift(2);
            $temp = $this->two->pow($temp);
            $x = $x->multiply($temp);
            if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
                throw new \RuntimeException('Unable to recover X coordinate');
            }
        }
        if ($x->isOdd() != $sign) {
            $x = $x->negate();
        }
        return [$x, $y];
    }
    /**
     * Extract Secret Scalar
     *
     * Implements steps 1-3 at https://tools.ietf.org/html/rfc8032#section-5.1.5
     *
     * Used by the various key handlers
     *
     * @param string $str
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function extractSecret($str)
    {
        if (strlen($str) != 32) {
            throw new \LengthException('Private Key should be 32-bytes long');
        }
        // 1.  Hash the 32-byte private key using SHA-512, storing the digest in
        //     a 64-octet large buffer, denoted h.  Only the lower 32 bytes are
        //     used for generating the public key.
        $hash = new Hash('sha512');
        $h = $hash->hash($str);
        $h = \Phabel\Target\Php80\Polyfill::substr($h, 0, 32);
        // 2.  Prune the buffer: The lowest three bits of the first octet are
        //     cleared, the highest bit of the last octet is cleared, and the
        //     second highest bit of the last octet is set.
        $h[0] = $h[0] & chr(0xf8);
        $h = strrev($h);
        $h[0] = $h[0] & chr(0x3f) | chr(0x40);
        // 3.  Interpret the buffer as the little-endian integer, forming a
        //     secret scalar s.
        $dA = new BigInteger($h, 256);
        $dA->secret = $str;
        return $dA;
    }
    /**
     * Encode a point as a string
     *
     * @param array $point
     * @return string
     */
    public function encodePoint($point)
    {
        list($x, $y) = $point;
        $y = $y->toBytes();
        $y[0] = $y[0] & chr(0x7f);
        if ($x->isOdd()) {
            $y[0] = $y[0] | chr(0x80);
        }
        $y = strrev($y);
        return $y;
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function createRandomMultiplier()
    {
        return $this->extractSecret(Random::string(32));
    }
    /**
    * Converts an affine point to an extended homogeneous coordinate
    *
    * From https://tools.ietf.org/html/rfc8032#section-5.1.4 :
    *
    * A point (x,y) is represented in extended homogeneous coordinates (X, Y, Z, T),
    with x = X/Z, y = Y/Z, x * y = T/Z.
    *
    * @return \phpseclib3\Math\PrimeField\Integer[]
    */
    public function convertToInternal(array $p)
    {
        if (empty($p)) {
            return [clone $this->zero, clone $this->one, clone $this->one, clone $this->zero];
        }
        if (isset($p[2])) {
            return $p;
        }
        $p[2] = clone $this->one;
        $p[3] = $p[0]->multiply($p[1]);
        return $p;
    }
    /**
     * Doubles a point on a curve
     *
     * @return FiniteField[]
     */
    public function doublePoint(array $p)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p)) {
            return [];
        }
        if (!isset($p[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        // from https://tools.ietf.org/html/rfc8032#page-12
        list($x1, $y1, $z1, $t1) = $p;
        $a = $x1->multiply($x1);
        $b = $y1->multiply($y1);
        $c = $this->two->multiply($z1)->multiply($z1);
        $h = $a->add($b);
        $temp = $x1->add($y1);
        $e = $h->subtract($temp->multiply($temp));
        $g = $a->subtract($b);
        $f = $c->add($g);
        $x3 = $e->multiply($f);
        $y3 = $g->multiply($h);
        $t3 = $e->multiply($h);
        $z3 = $f->multiply($g);
        return [$x3, $y3, $z3, $t3];
    }
    /**
     * Adds two points on the curve
     *
     * @return FiniteField[]
     */
    public function addPoint(array $p, array $q)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            if (count($q)) {
                return $q;
            }
            if (count($p)) {
                return $p;
            }
            return [];
        }
        if (!isset($p[2]) || !isset($q[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        if ($p[0]->equals($q[0])) {
            return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
        }
        // from https://tools.ietf.org/html/rfc8032#page-12
        list($x1, $y1, $z1, $t1) = $p;
        list($x2, $y2, $z2, $t2) = $q;
        $a = $y1->subtract($x1)->multiply($y2->subtract($x2));
        $b = $y1->add($x1)->multiply($y2->add($x2));
        $c = $t1->multiply($this->two)->multiply($this->d)->multiply($t2);
        $d = $z1->multiply($this->two)->multiply($z2);
        $e = $b->subtract($a);
        $f = $d->subtract($c);
        $g = $d->add($c);
        $h = $b->add($a);
        $x3 = $e->multiply($f);
        $y3 = $g->multiply($h);
        $t3 = $e->multiply($h);
        $z3 = $f->multiply($g);
        return [$x3, $y3, $z3, $t3];
    }
}<?php

/**
 * secp160r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp160r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC', 16), new BigInteger('1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45', 16));
        $this->setBasePoint(new BigInteger('4A96B5688EF573284664698968C38BB913CBFC82', 16), new BigInteger('23A628553168947D59DCC912042351377AC5FB32', 16));
        $this->setOrder(new BigInteger('0100000000000000000001F4C8F927AED3CA752257', 16));
    }
}<?php

/**
 * nistb233
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistb233 extends sect233r1
{
}<?php

/**
 * brainpoolP224t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP224t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF', 16));
        $this->setCoefficients(
            new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC', 16),
            // eg. -3
            new BigInteger('4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D', 16)
        );
        $this->setBasePoint(new BigInteger('6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580', 16), new BigInteger('0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C', 16));
        $this->setOrder(new BigInteger('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16));
    }
}<?php

/**
 * brainpoolP224r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP224r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF', 16));
        $this->setCoefficients(new BigInteger('68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43', 16), new BigInteger('2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B', 16));
        $this->setBasePoint(new BigInteger('0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D', 16), new BigInteger('58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD', 16));
        $this->setOrder(new BigInteger('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16));
    }
}<?php

/**
 * sect283r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect283r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(283, 12, 7, 5, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000000000000001', '027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5');
        $this->setBasePoint('05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053', '03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4');
        $this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307', 16));
    }
}<?php

/**
 * secp384r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp384r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC', 16), new BigInteger('B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF', 16));
        $this->setBasePoint(new BigInteger('AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7', 16), new BigInteger('3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973', 16));
    }
}<?php

/**
 * sect193r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect193r2 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(193, 15, 0);
        $this->setCoefficients('0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B', '00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE');
        $this->setBasePoint('00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F', '01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C');
        $this->setOrder(new BigInteger('010000000000000000000000015AAB561B005413CCD4EE99D5', 16));
    }
}<?php

/**
 * sect193r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect193r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(193, 15, 0);
        $this->setCoefficients('0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01', '00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814');
        $this->setBasePoint('01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1', '0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05');
        $this->setOrder(new BigInteger('01000000000000000000000000C7F34A778F443ACC920EBA49', 16));
    }
}<?php

/**
 * sect409k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect409k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(409, 87, 0);
        $this->setCoefficients('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746', '01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B');
        $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF', 16));
    }
}<?php

/**
 * sect571r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect571r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(571, 10, 5, 2, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', '02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A');
        $this->setBasePoint('0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19', '037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B');
        $this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47', 16));
    }
}<?php

/**
 * nistb409
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistb409 extends sect409r1
{
}<?php

/**
 * Generalized Koblitz Curves over y^2 = x^3 + b.
 *
 * According to http://www.secg.org/SEC2-Ver-1.0.pdf Koblitz curves are over the GF(2**m)
 * finite field. Both the $a$ and $b$ coefficients are either 0 or 1. However, SEC2
 * generalizes the definition to include curves over GF(P) "which possess an efficiently
 * computable endomorphism".
 *
 * For these generalized Koblitz curves $b$ doesn't have to be 0 or 1. Whether or not $a$
 * has any restrictions on it is unclear, however, for all the GF(P) Koblitz curves defined
 * in SEC2 v1.0 $a$ is $0$ so all of the methods defined herein will assume that it is.
 *
 * I suppose we could rename the $b$ coefficient to $a$, however, the documentation refers
 * to $b$ so we'll just keep it.
 *
 * If a later version of SEC2 comes out wherein some $a$ values are non-zero we can create a
 * new method for those. eg. KoblitzA1Prime.php or something.
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\PrimeField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
/**
 * Curves over y^2 = x^3 + b
 *
 * @package KoblitzPrime
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class KoblitzPrime extends Prime
{
    // don't overwrite setCoefficients() with one that only accepts one parameter so that
    // one might be able to switch between KoblitzPrime and Prime more easily (for benchmarking
    // purposes).
    /**
     * Multiply and Add Points
     *
     * Uses a efficiently computable endomorphism to achieve a slight speedup
     *
     * Adapted from https://git.io/vxbrP
     *
     * @return int[]
     */
    public function multiplyAddPoints(array $points, array $scalars)
    {
        static $zero, $one, $two;
        if (!isset($two)) {
            $two = new BigInteger(2);
            $one = new BigInteger(1);
        }
        if (!isset($this->beta)) {
            // get roots
            $inv = $this->one->divide($this->two)->negate();
            $s = $this->three->negate()->squareRoot()->multiply($inv);
            $betas = [$inv->add($s), $inv->subtract($s)];
            $this->beta = $betas[0]->compare($betas[1]) < 0 ? $betas[0] : $betas[1];
            //echo strtoupper($this->beta->toHex(true)) . "\n"; exit;
        }
        if (!isset($this->basis)) {
            $factory = new PrimeField($this->order);
            $tempOne = $factory->newInteger($one);
            $tempTwo = $factory->newInteger($two);
            $tempThree = $factory->newInteger(new BigInteger(3));
            $inv = $tempOne->divide($tempTwo)->negate();
            $s = $tempThree->negate()->squareRoot()->multiply($inv);
            $lambdas = [$inv->add($s), $inv->subtract($s)];
            $lhs = $this->multiplyPoint($this->p, $lambdas[0])[0];
            $rhs = $this->p[0]->multiply($this->beta);
            $lambda = $lhs->equals($rhs) ? $lambdas[0] : $lambdas[1];
            $this->basis = static::extendedGCD($lambda->toBigInteger(), $this->order);
            ///*
            foreach ($this->basis as $basis) {
                echo strtoupper($basis['a']->toHex(true)) . "\n";
                echo strtoupper($basis['b']->toHex(true)) . "\n\n";
            }
            exit;
            //*/
        }
        $npoints = $nscalars = [];
        for ($i = 0; $i < count($points); $i++) {
            $p = $points[$i];
            $k = $scalars[$i]->toBigInteger();
            // begin split
            list($v1, $v2) = $this->basis;
            $c1 = $v2['b']->multiply($k);
            list($c1, $r) = $c1->divide($this->order);
            if ($this->order->compare($r->multiply($two)) <= 0) {
                $c1 = $c1->add($one);
            }
            $c2 = $v1['b']->negate()->multiply($k);
            list($c2, $r) = $c2->divide($this->order);
            if ($this->order->compare($r->multiply($two)) <= 0) {
                $c2 = $c2->add($one);
            }
            $p1 = $c1->multiply($v1['a']);
            $p2 = $c2->multiply($v2['a']);
            $q1 = $c1->multiply($v1['b']);
            $q2 = $c2->multiply($v2['b']);
            $k1 = $k->subtract($p1)->subtract($p2);
            $k2 = $q1->add($q2)->negate();
            // end split
            $beta = [$p[0]->multiply($this->beta), $p[1], clone $this->one];
            if (isset($p['naf'])) {
                $beta['naf'] = array_map(function ($p) {
                    return [$p[0]->multiply($this->beta), $p[1], clone $this->one];
                }, $p['naf']);
                $beta['nafwidth'] = $p['nafwidth'];
            }
            if ($k1->isNegative()) {
                $k1 = $k1->negate();
                $p = $this->negatePoint($p);
            }
            if ($k2->isNegative()) {
                $k2 = $k2->negate();
                $beta = $this->negatePoint($beta);
            }
            $pos = 2 * $i;
            $npoints[$pos] = $p;
            $nscalars[$pos] = $this->factory->newInteger($k1);
            $pos++;
            $npoints[$pos] = $beta;
            $nscalars[$pos] = $this->factory->newInteger($k2);
        }
        return parent::multiplyAddPoints($npoints, $nscalars);
    }
    /**
     * Returns the numerator and denominator of the slope
     *
     * @return FiniteField[]
     */
    protected function doublePointHelper(array $p)
    {
        $numerator = $this->three->multiply($p[0])->multiply($p[0]);
        $denominator = $this->two->multiply($p[1]);
        return [$numerator, $denominator];
    }
    /**
     * Doubles a jacobian coordinate on the curve
     *
     * See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
     *
     * @return FiniteField[]
     */
    protected function jacobianDoublePoint(array $p)
    {
        list($x1, $y1, $z1) = $p;
        $a = $x1->multiply($x1);
        $b = $y1->multiply($y1);
        $c = $b->multiply($b);
        $d = $x1->add($b);
        $d = $d->multiply($d)->subtract($a)->subtract($c)->multiply($this->two);
        $e = $this->three->multiply($a);
        $f = $e->multiply($e);
        $x3 = $f->subtract($this->two->multiply($d));
        $y3 = $e->multiply($d->subtract($x3))->subtract($this->eight->multiply($c));
        $z3 = $this->two->multiply($y1)->multiply($z1);
        return [$x3, $y3, $z3];
    }
    /**
     * Doubles a "fresh" jacobian coordinate on the curve
     *
     * See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl
     *
     * @return FiniteField[]
     */
    protected function jacobianDoublePointMixed(array $p)
    {
        list($x1, $y1) = $p;
        $xx = $x1->multiply($x1);
        $yy = $y1->multiply($y1);
        $yyyy = $yy->multiply($yy);
        $s = $x1->add($yy);
        $s = $s->multiply($s)->subtract($xx)->subtract($yyyy)->multiply($this->two);
        $m = $this->three->multiply($xx);
        $t = $m->multiply($m)->subtract($this->two->multiply($s));
        $x3 = $t;
        $y3 = $s->subtract($t);
        $y3 = $m->multiply($y3)->subtract($this->eight->multiply($yyyy));
        $z3 = $this->two->multiply($y1);
        return [$x3, $y3, $z3];
    }
    /**
     * Tests whether or not the x / y values satisfy the equation
     *
     * @return boolean
     */
    public function verifyPoint(array $p)
    {
        list($x, $y) = $p;
        $lhs = $y->multiply($y);
        $temp = $x->multiply($x)->multiply($x);
        $rhs = $temp->add($this->b);
        return $lhs->equals($rhs);
    }
    /**
    * Calculates the parameters needed from the Euclidean algorithm as discussed at
    http://diamond.boisestate.edu/~liljanab/MATH308/GuideToECC.pdf#page=148
    *
    * @param BigInteger $u
    * @param BigInteger $v
    * @return BigInteger[]
    */
    protected static function extendedGCD(BigInteger $u, BigInteger $v)
    {
        $one = new BigInteger(1);
        $zero = new BigInteger();
        $a = clone $one;
        $b = clone $zero;
        $c = clone $zero;
        $d = clone $one;
        $stop = $v->bitwise_rightShift($v->getLength() >> 1);
        $a1 = clone $zero;
        $b1 = clone $zero;
        $a2 = clone $zero;
        $b2 = clone $zero;
        $postGreatestIndex = 0;
        while (!$v->equals($zero)) {
            list($q) = $u->divide($v);
            $temp = $u;
            $u = $v;
            $v = $temp->subtract($v->multiply($q));
            $temp = $a;
            $a = $c;
            $c = $temp->subtract($a->multiply($q));
            $temp = $b;
            $b = $d;
            $d = $temp->subtract($b->multiply($q));
            if ($v->compare($stop) > 0) {
                $a0 = $v;
                $b0 = $c;
            } else {
                $postGreatestIndex++;
            }
            if ($postGreatestIndex == 1) {
                $a1 = $v;
                $b1 = $c->negate();
            }
            if ($postGreatestIndex == 2) {
                $rhs = $a0->multiply($a0)->add($b0->multiply($b0));
                $lhs = $v->multiply($v)->add($b->multiply($b));
                if ($lhs->compare($rhs) <= 0) {
                    $a2 = $a0;
                    $b2 = $b0->negate();
                } else {
                    $a2 = $v;
                    $b2 = $c->negate();
                }
                break;
            }
        }
        return [['a' => $a1, 'b' => $b1], ['a' => $a2, 'b' => $b2]];
    }
}<?php

/**
 * Curves over y^2 = x^3 + a*x + x
 *
 * Technically, a Montgomery curve has a coefficient for y^2 but for Curve25519 and Curve448 that
 * coefficient is 1.
 *
 * Curve25519 and Curve448 do not make use of the y coordinate, which makes it unsuitable for use
 * with ECDSA / EdDSA. A few other differences between Curve25519 and Ed25519 are discussed at
 * https://crypto.stackexchange.com/a/43058/4520
 *
 * More info:
 *
 * https://en.wikipedia.org/wiki/Montgomery_curve
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\PrimeField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
/**
 * Curves over y^2 = x^3 + a*x + x
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Montgomery extends Base
{
    /**
     * Prime Field Integer factory
     *
     * @var \phpseclib3\Math\PrimeField
     */
    protected $factory;
    /**
     * Cofficient for x
     *
     * @var object
     */
    protected $a;
    /**
     * Constant used for point doubling
     *
     * @var object
     */
    protected $a24;
    /**
     * The Number Zero
     *
     * @var object
     */
    protected $zero;
    /**
     * The Number One
     *
     * @var object
     */
    protected $one;
    /**
     * Base Point
     *
     * @var object
     */
    protected $p;
    /**
     * The modulo
     *
     * @var BigInteger
     */
    protected $modulo;
    /**
     * The Order
     *
     * @var BigInteger
     */
    protected $order;
    /**
     * Sets the modulo
     */
    public function setModulo(BigInteger $modulo)
    {
        $this->modulo = $modulo;
        $this->factory = new PrimeField($modulo);
        $this->zero = $this->factory->newInteger(new BigInteger());
        $this->one = $this->factory->newInteger(new BigInteger(1));
    }
    /**
     * Set coefficients a
     */
    public function setCoefficients(BigInteger $a)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->a = $this->factory->newInteger($a);
        $two = $this->factory->newInteger(new BigInteger(2));
        $four = $this->factory->newInteger(new BigInteger(4));
        $this->a24 = $this->a->subtract($two)->divide($four);
    }
    /**
     * Set x and y coordinates for the base point
     *
     * @param (BigInteger | PrimeInteger) $x
     * @param (BigInteger | PrimeInteger) $y
     * @return PrimeInteger[]
     */
    public function setBasePoint($x, $y)
    {
        switch (true) {
            case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
            case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
        }
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->p = [$x instanceof BigInteger ? $this->factory->newInteger($x) : $x, $y instanceof BigInteger ? $this->factory->newInteger($y) : $y];
    }
    /**
     * Retrieve the base point as an array
     *
     * @return array
     */
    public function getBasePoint()
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        /*
        if (!isset($this->p)) {
            throw new \RuntimeException('setBasePoint needs to be called before this method');
        }
        */
        return $this->p;
    }
    /**
     * Doubles and adds a point on a curve
     *
     * See https://tools.ietf.org/html/draft-ietf-tls-curve25519-01#appendix-A.1.3
     *
     * @return FiniteField[][]
     */
    private function doubleAndAddPoint(array $p, array $q, PrimeInteger $x1)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            return [];
        }
        if (!isset($p[1])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to XZ coordinates');
        }
        list($x2, $z2) = $p;
        list($x3, $z3) = $q;
        $a = $x2->add($z2);
        $aa = $a->multiply($a);
        $b = $x2->subtract($z2);
        $bb = $b->multiply($b);
        $e = $aa->subtract($bb);
        $c = $x3->add($z3);
        $d = $x3->subtract($z3);
        $da = $d->multiply($a);
        $cb = $c->multiply($b);
        $temp = $da->add($cb);
        $x5 = $temp->multiply($temp);
        $temp = $da->subtract($cb);
        $z5 = $x1->multiply($temp->multiply($temp));
        $x4 = $aa->multiply($bb);
        $temp = static::class == Curve25519::class ? $bb : $aa;
        $z4 = $e->multiply($temp->add($this->a24->multiply($e)));
        return [[$x4, $z4], [$x5, $z5]];
    }
    /**
    * Multiply a point on the curve by a scalar
    *
    * Uses the montgomery ladder technique as described here:
    *
    * https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder
    https://github.com/phpecc/phpecc/issues/16#issuecomment-59176772
    *
    * @return array
    */
    public function multiplyPoint(array $p, BigInteger $d)
    {
        $p1 = [$this->one, $this->zero];
        $alreadyInternal = isset($x[1]);
        $p2 = $this->convertToInternal($p);
        $x = $p[0];
        $b = $d->toBits();
        $b = str_pad($b, 256, '0', STR_PAD_LEFT);
        for ($i = 0; $i < strlen($b); $i++) {
            $b_i = (int) $b[$i];
            if ($b_i) {
                list($p2, $p1) = $this->doubleAndAddPoint($p2, $p1, $x);
            } else {
                list($p1, $p2) = $this->doubleAndAddPoint($p1, $p2, $x);
            }
        }
        return $alreadyInternal ? $p1 : $this->convertToAffine($p1);
    }
    /**
     * Converts an affine point to an XZ coordinate
     *
     * From https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html
     *
     * XZ coordinates represent x y as X Z satsfying the following equations:
     *
     * x=X/Z
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToInternal(array $p)
    {
        if (empty($p)) {
            return [clone $this->zero, clone $this->one];
        }
        if (isset($p[1])) {
            return $p;
        }
        $p[1] = clone $this->one;
        return $p;
    }
    /**
     * Returns the affine point
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToAffine(array $p)
    {
        if (!isset($p[1])) {
            return $p;
        }
        list($x, $z) = $p;
        return [$x->divide($z)];
    }
}<?php

/**
 * Curves over a*x^2 + y^2 = 1 + d*x^2*y^2
 *
 * http://www.secg.org/SEC2-Ver-1.0.pdf provides for curves with custom parameters.
 * ie. the coefficients can be arbitrary set through specially formatted keys, etc.
 * As such, Prime.php is built very generically and it's not able to take full
 * advantage of curves with 0 coefficients to produce simplified point doubling,
 * point addition. Twisted Edwards curves, in contrast, do not have a way, currently,
 * to customize them. As such, we can omit the super generic stuff from this class
 * and let the named curves (Ed25519 and Ed448) define their own custom tailored
 * point addition and point doubling methods.
 *
 * More info:
 *
 * https://en.wikipedia.org/wiki/Twisted_Edwards_curve
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Math\PrimeField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
/**
 * Curves over a*x^2 + y^2 = 1 + d*x^2*y^2
 *
 * @package Prime
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class TwistedEdwards extends Base
{
    /**
     * The modulo
     *
     * @var BigInteger
     */
    protected $modulo;
    /**
     * Cofficient for x^2
     *
     * @var object
     */
    protected $a;
    /**
     * Cofficient for x^2*y^2
     *
     * @var object
     */
    protected $d;
    /**
     * Base Point
     *
     * @var object[]
     */
    protected $p;
    /**
     * The number zero over the specified finite field
     *
     * @var object
     */
    protected $zero;
    /**
     * The number one over the specified finite field
     *
     * @var object
     */
    protected $one;
    /**
     * The number two over the specified finite field
     *
     * @var object
     */
    protected $two;
    /**
     * Sets the modulo
     */
    public function setModulo(BigInteger $modulo)
    {
        $this->modulo = $modulo;
        $this->factory = new PrimeField($modulo);
        $this->zero = $this->factory->newInteger(new BigInteger(0));
        $this->one = $this->factory->newInteger(new BigInteger(1));
        $this->two = $this->factory->newInteger(new BigInteger(2));
    }
    /**
     * Set coefficients a and b
     */
    public function setCoefficients(BigInteger $a, BigInteger $d)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->a = $this->factory->newInteger($a);
        $this->d = $this->factory->newInteger($d);
    }
    /**
     * Set x and y coordinates for the base point
     */
    public function setBasePoint($x, $y)
    {
        switch (true) {
            case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
            case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
        }
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->p = [$x instanceof BigInteger ? $this->factory->newInteger($x) : $x, $y instanceof BigInteger ? $this->factory->newInteger($y) : $y];
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getA()
    {
        return $this->a;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getD()
    {
        return $this->d;
    }
    /**
     * Retrieve the base point as an array
     *
     * @return array
     */
    public function getBasePoint()
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        /*
        if (!isset($this->p)) {
            throw new \RuntimeException('setBasePoint needs to be called before this method');
        }
        */
        return $this->p;
    }
    /**
     * Returns the affine point
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToAffine(array $p)
    {
        if (!isset($p[2])) {
            return $p;
        }
        list($x, $y, $z) = $p;
        $z = $this->one->divide($z);
        return [$x->multiply($z), $y->multiply($z)];
    }
    /**
     * Returns the modulo
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function getModulo()
    {
        return $this->modulo;
    }
    /**
     * Tests whether or not the x / y values satisfy the equation
     *
     * @return boolean
     */
    public function verifyPoint(array $p)
    {
        list($x, $y) = $p;
        $x2 = $x->multiply($x);
        $y2 = $y->multiply($y);
        $lhs = $this->a->multiply($x2)->add($y2);
        $rhs = $this->d->multiply($x2)->multiply($y2)->add($this->one);
        return $lhs->equals($rhs);
    }
}<?php

/**
 * Curves over y^2 = x^3 + a*x + b
 *
 * These are curves used in SEC 2 over prime fields: http://www.secg.org/SEC2-Ver-1.0.pdf
 * The curve is a weierstrass curve with a[1], a[3] and a[2] set to 0.
 *
 * Uses Jacobian Coordinates for speed if able:
 *
 * https://en.wikipedia.org/wiki/Jacobian_curve
 * https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Math\Common\FiniteField\Integer;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\PrimeField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
/**
 * Curves over y^2 = x^3 + a*x + b
 *
 * @package Prime
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Prime extends Base
{
    /**
     * Prime Field Integer factory
     *
     * @var \phpseclib3\Math\PrimeFields
     */
    protected $factory;
    /**
     * Cofficient for x^1
     *
     * @var object
     */
    protected $a;
    /**
     * Cofficient for x^0
     *
     * @var object
     */
    protected $b;
    /**
     * Base Point
     *
     * @var object
     */
    protected $p;
    /**
     * The number one over the specified finite field
     *
     * @var object
     */
    protected $one;
    /**
     * The number two over the specified finite field
     *
     * @var object
     */
    protected $two;
    /**
     * The number three over the specified finite field
     *
     * @var object
     */
    protected $three;
    /**
     * The number four over the specified finite field
     *
     * @var object
     */
    protected $four;
    /**
     * The number eight over the specified finite field
     *
     * @var object
     */
    protected $eight;
    /**
     * The modulo
     *
     * @var BigInteger
     */
    protected $modulo;
    /**
     * The Order
     *
     * @var BigInteger
     */
    protected $order;
    /**
     * Sets the modulo
     */
    public function setModulo(BigInteger $modulo)
    {
        $this->modulo = $modulo;
        $this->factory = new PrimeField($modulo);
        $this->two = $this->factory->newInteger(new BigInteger(2));
        $this->three = $this->factory->newInteger(new BigInteger(3));
        // used by jacobian coordinates
        $this->one = $this->factory->newInteger(new BigInteger(1));
        $this->four = $this->factory->newInteger(new BigInteger(4));
        $this->eight = $this->factory->newInteger(new BigInteger(8));
    }
    /**
     * Set coefficients a and b
     */
    public function setCoefficients(BigInteger $a, BigInteger $b)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->a = $this->factory->newInteger($a);
        $this->b = $this->factory->newInteger($b);
    }
    /**
     * Set x and y coordinates for the base point
     *
     * @param (BigInteger | PrimeInteger) $x
     * @param (BigInteger | PrimeInteger) $y
     * @return PrimeInteger[]
     */
    public function setBasePoint($x, $y)
    {
        switch (true) {
            case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
            case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
        }
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->p = [$x instanceof BigInteger ? $this->factory->newInteger($x) : $x, $y instanceof BigInteger ? $this->factory->newInteger($y) : $y];
    }
    /**
     * Retrieve the base point as an array
     *
     * @return array
     */
    public function getBasePoint()
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        /*
        if (!isset($this->p)) {
            throw new \RuntimeException('setBasePoint needs to be called before this method');
        }
        */
        return $this->p;
    }
    /**
     * Adds two "fresh" jacobian form on the curve
     *
     * @return FiniteField[]
     */
    protected function jacobianAddPointMixedXY(array $p, array $q)
    {
        list($u1, $s1) = $p;
        list($u2, $s2) = $q;
        if ($u1->equals($u2)) {
            if (!$s1->equals($s2)) {
                return [];
            } else {
                return $this->doublePoint($p);
            }
        }
        $h = $u2->subtract($u1);
        $r = $s2->subtract($s1);
        $h2 = $h->multiply($h);
        $h3 = $h2->multiply($h);
        $v = $u1->multiply($h2);
        $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
        $y3 = $r->multiply($v->subtract($x3))->subtract($s1->multiply($h3));
        return [$x3, $y3, $h];
    }
    /**
     * Adds one "fresh" jacobian form on the curve
     *
     * The second parameter should be the "fresh" one
     *
     * @return FiniteField[]
     */
    protected function jacobianAddPointMixedX(array $p, array $q)
    {
        list($u1, $s1, $z1) = $p;
        list($x2, $y2) = $q;
        $z12 = $z1->multiply($z1);
        $u2 = $x2->multiply($z12);
        $s2 = $y2->multiply($z12->multiply($z1));
        if ($u1->equals($u2)) {
            if (!$s1->equals($s2)) {
                return [];
            } else {
                return $this->doublePoint($p);
            }
        }
        $h = $u2->subtract($u1);
        $r = $s2->subtract($s1);
        $h2 = $h->multiply($h);
        $h3 = $h2->multiply($h);
        $v = $u1->multiply($h2);
        $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
        $y3 = $r->multiply($v->subtract($x3))->subtract($s1->multiply($h3));
        $z3 = $h->multiply($z1);
        return [$x3, $y3, $z3];
    }
    /**
     * Adds two jacobian coordinates on the curve
     *
     * @return FiniteField[]
     */
    protected function jacobianAddPoint(array $p, array $q)
    {
        list($x1, $y1, $z1) = $p;
        list($x2, $y2, $z2) = $q;
        $z12 = $z1->multiply($z1);
        $z22 = $z2->multiply($z2);
        $u1 = $x1->multiply($z22);
        $u2 = $x2->multiply($z12);
        $s1 = $y1->multiply($z22->multiply($z2));
        $s2 = $y2->multiply($z12->multiply($z1));
        if ($u1->equals($u2)) {
            if (!$s1->equals($s2)) {
                return [];
            } else {
                return $this->doublePoint($p);
            }
        }
        $h = $u2->subtract($u1);
        $r = $s2->subtract($s1);
        $h2 = $h->multiply($h);
        $h3 = $h2->multiply($h);
        $v = $u1->multiply($h2);
        $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
        $y3 = $r->multiply($v->subtract($x3))->subtract($s1->multiply($h3));
        $z3 = $h->multiply($z1)->multiply($z2);
        return [$x3, $y3, $z3];
    }
    /**
     * Adds two points on the curve
     *
     * @return FiniteField[]
     */
    public function addPoint(array $p, array $q)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            if (count($q)) {
                return $q;
            }
            if (count($p)) {
                return $p;
            }
            return [];
        }
        // use jacobian coordinates
        if (isset($p[2]) && isset($q[2])) {
            if (isset($p['fresh']) && isset($q['fresh'])) {
                return $this->jacobianAddPointMixedXY($p, $q);
            }
            if (isset($p['fresh'])) {
                return $this->jacobianAddPointMixedX($q, $p);
            }
            if (isset($q['fresh'])) {
                return $this->jacobianAddPointMixedX($p, $q);
            }
            return $this->jacobianAddPoint($p, $q);
        }
        if (isset($p[2]) || isset($q[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to Jacobi coordinates or vice versa');
        }
        if ($p[0]->equals($q[0])) {
            if (!$p[1]->equals($q[1])) {
                return [];
            } else {
                // eg. doublePoint
                list($numerator, $denominator) = $this->doublePointHelper($p);
            }
        } else {
            $numerator = $q[1]->subtract($p[1]);
            $denominator = $q[0]->subtract($p[0]);
        }
        $slope = $numerator->divide($denominator);
        $x = $slope->multiply($slope)->subtract($p[0])->subtract($q[0]);
        $y = $slope->multiply($p[0]->subtract($x))->subtract($p[1]);
        return [$x, $y];
    }
    /**
     * Returns the numerator and denominator of the slope
     *
     * @return FiniteField[]
     */
    protected function doublePointHelper(array $p)
    {
        $numerator = $this->three->multiply($p[0])->multiply($p[0])->add($this->a);
        $denominator = $this->two->multiply($p[1]);
        return [$numerator, $denominator];
    }
    /**
     * Doubles a jacobian coordinate on the curve
     *
     * @return FiniteField[]
     */
    protected function jacobianDoublePoint(array $p)
    {
        list($x, $y, $z) = $p;
        $x2 = $x->multiply($x);
        $y2 = $y->multiply($y);
        $z2 = $z->multiply($z);
        $s = $this->four->multiply($x)->multiply($y2);
        $m1 = $this->three->multiply($x2);
        $m2 = $this->a->multiply($z2->multiply($z2));
        $m = $m1->add($m2);
        $x1 = $m->multiply($m)->subtract($this->two->multiply($s));
        $y1 = $m->multiply($s->subtract($x1))->subtract($this->eight->multiply($y2->multiply($y2)));
        $z1 = $this->two->multiply($y)->multiply($z);
        return [$x1, $y1, $z1];
    }
    /**
     * Doubles a "fresh" jacobian coordinate on the curve
     *
     * @return FiniteField[]
     */
    protected function jacobianDoublePointMixed(array $p)
    {
        list($x, $y) = $p;
        $x2 = $x->multiply($x);
        $y2 = $y->multiply($y);
        $s = $this->four->multiply($x)->multiply($y2);
        $m1 = $this->three->multiply($x2);
        $m = $m1->add($this->a);
        $x1 = $m->multiply($m)->subtract($this->two->multiply($s));
        $y1 = $m->multiply($s->subtract($x1))->subtract($this->eight->multiply($y2->multiply($y2)));
        $z1 = $this->two->multiply($y);
        return [$x1, $y1, $z1];
    }
    /**
     * Doubles a point on a curve
     *
     * @return FiniteField[]
     */
    public function doublePoint(array $p)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p)) {
            return [];
        }
        // use jacobian coordinates
        if (isset($p[2])) {
            if (isset($p['fresh'])) {
                return $this->jacobianDoublePointMixed($p);
            }
            return $this->jacobianDoublePoint($p);
        }
        list($numerator, $denominator) = $this->doublePointHelper($p);
        $slope = $numerator->divide($denominator);
        $x = $slope->multiply($slope)->subtract($p[0])->subtract($p[0]);
        $y = $slope->multiply($p[0]->subtract($x))->subtract($p[1]);
        return [$x, $y];
    }
    /**
     * Returns the X coordinate and the derived Y coordinate
     *
     * @return array
     */
    public function derivePoint($m)
    {
        $y = ord(Strings::shift($m));
        $x = new BigInteger($m, 256);
        $xp = $this->convertInteger($x);
        switch ($y) {
            case 2:
                $ypn = false;
                break;
            case 3:
                $ypn = true;
                break;
            default:
                throw new \RuntimeException('Coordinate not in recognized format');
        }
        $temp = $xp->multiply($this->a);
        $temp = $xp->multiply($xp)->multiply($xp)->add($temp);
        $temp = $temp->add($this->b);
        $b = $temp->squareRoot();
        if (!$b) {
            throw new \RuntimeException('Unable to derive Y coordinate');
        }
        $bn = $b->isOdd();
        $yp = $ypn == $bn ? $b : $b->negate();
        return [$xp, $yp];
    }
    /**
     * Tests whether or not the x / y values satisfy the equation
     *
     * @return boolean
     */
    public function verifyPoint(array $p)
    {
        list($x, $y) = $p;
        $lhs = $y->multiply($y);
        $temp = $x->multiply($this->a);
        $temp = $x->multiply($x)->multiply($x)->add($temp);
        $rhs = $temp->add($this->b);
        return $lhs->equals($rhs);
    }
    /**
     * Returns the modulo
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function getModulo()
    {
        return $this->modulo;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getA()
    {
        return $this->a;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getB()
    {
        return $this->b;
    }
    /**
     * Multiply and Add Points
     *
     * Adapted from https://git.io/vxPUH
     *
     * @return int[]
     */
    public function multiplyAddPoints(array $points, array $scalars)
    {
        $length = count($points);
        foreach ($points as &$point) {
            $point = $this->convertToInternal($point);
        }
        $wnd = [$this->getNAFPoints($points[0], 7)];
        $wndWidth = [isset($points[0]['nafwidth']) ? $points[0]['nafwidth'] : 7];
        for ($i = 1; $i < $length; $i++) {
            $wnd[] = $this->getNAFPoints($points[$i], 1);
            $wndWidth[] = isset($points[$i]['nafwidth']) ? $points[$i]['nafwidth'] : 1;
        }
        $naf = [];
        // comb all window NAFs
        $max = 0;
        for ($i = $length - 1; $i >= 1; $i -= 2) {
            $a = $i - 1;
            $b = $i;
            if ($wndWidth[$a] != 1 || $wndWidth[$b] != 1) {
                $naf[$a] = $scalars[$a]->getNAF($wndWidth[$a]);
                $naf[$b] = $scalars[$b]->getNAF($wndWidth[$b]);
                $max = max(count($naf[$a]), count($naf[$b]), $max);
                continue;
            }
            $comb = [
                $points[$a],
                // 1
                null,
                // 3
                null,
                // 5
                $points[$b],
            ];
            $comb[1] = $this->addPoint($points[$a], $points[$b]);
            $comb[2] = $this->addPoint($points[$a], $this->negatePoint($points[$b]));
            $index = [
                -3,
                /* -1 -1 */
                -1,
                /* -1  0 */
                -5,
                /* -1  1 */
                -7,
                /*  0 -1 */
                0,
                /*  0 -1 */
                7,
                /*  0  1 */
                5,
                /*  1 -1 */
                1,
                /*  1  0 */
                3,
            ];
            $jsf = self::getJSFPoints($scalars[$a], $scalars[$b]);
            $max = max(count($jsf[0]), $max);
            if ($max > 0) {
                $naf[$a] = array_fill(0, $max, 0);
                $naf[$b] = array_fill(0, $max, 0);
            } else {
                $naf[$a] = [];
                $naf[$b] = [];
            }
            for ($j = 0; $j < $max; $j++) {
                $ja = isset($jsf[0][$j]) ? $jsf[0][$j] : 0;
                $jb = isset($jsf[1][$j]) ? $jsf[1][$j] : 0;
                $naf[$a][$j] = $index[3 * ($ja + 1) + $jb + 1];
                $naf[$b][$j] = 0;
                $wnd[$a] = $comb;
            }
        }
        $acc = [];
        $temp = [0, 0, 0, 0];
        for ($i = $max; $i >= 0; $i--) {
            $k = 0;
            while ($i >= 0) {
                $zero = true;
                for ($j = 0; $j < $length; $j++) {
                    $temp[$j] = isset($naf[$j][$i]) ? $naf[$j][$i] : 0;
                    if ($temp[$j] != 0) {
                        $zero = false;
                    }
                }
                if (!$zero) {
                    break;
                }
                $k++;
                $i--;
            }
            if ($i >= 0) {
                $k++;
            }
            while ($k--) {
                $acc = $this->doublePoint($acc);
            }
            if ($i < 0) {
                break;
            }
            for ($j = 0; $j < $length; $j++) {
                $z = $temp[$j];
                $p = null;
                if ($z == 0) {
                    continue;
                }
                $p = $z > 0 ? $wnd[$j][$z - 1 >> 1] : $this->negatePoint($wnd[$j][-$z - 1 >> 1]);
                $acc = $this->addPoint($acc, $p);
            }
        }
        return $this->convertToAffine($acc);
    }
    /**
     * Precomputes NAF points
     *
     * Adapted from https://git.io/vxY1f
     *
     * @return int[]
     */
    private function getNAFPoints($point, $wnd)
    {
        if (isset($point['naf'])) {
            return $point['naf'];
        }
        $res = [$point];
        $max = (1 << $wnd) - 1;
        $dbl = $max == 1 ? null : $this->doublePoint($point);
        for ($i = 1; $i < $max; $i++) {
            $res[] = $this->addPoint($res[$i - 1], $dbl);
        }
        $point['naf'] = $res;
        /*
        $str = '';
        foreach ($res as $re) {
            $re[0] = bin2hex($re[0]->toBytes());
            $re[1] = bin2hex($re[1]->toBytes());
            $str.= "            ['$re[0]', '$re[1]'],\r\n";
        }
        file_put_contents('temp.txt', $str);
        exit;
        */
        return $res;
    }
    /**
     * Precomputes points in Joint Sparse Form
     *
     * Adapted from https://git.io/vxrpD
     *
     * @return int[]
     */
    private static function getJSFPoints(Integer $k1, Integer $k2)
    {
        static $three;
        if (!isset($three)) {
            $three = new BigInteger(3);
        }
        $jsf = [[], []];
        $k1 = $k1->toBigInteger();
        $k2 = $k2->toBigInteger();
        $d1 = 0;
        $d2 = 0;
        while ($k1->compare(new BigInteger(-$d1)) > 0 || $k2->compare(new BigInteger(-$d2)) > 0) {
            // first phase
            $m14 = $k1->testBit(0) + 2 * $k1->testBit(1);
            $m14 += $d1;
            $m14 &= 3;
            $m24 = $k2->testBit(0) + 2 * $k2->testBit(1);
            $m24 += $d2;
            $m24 &= 3;
            if ($m14 == 3) {
                $m14 = -1;
            }
            if ($m24 == 3) {
                $m24 = -1;
            }
            $u1 = 0;
            if ($m14 & 1) {
                // if $m14 is odd
                $m8 = $k1->testBit(0) + 2 * $k1->testBit(1) + 4 * $k1->testBit(2);
                $m8 += $d1;
                $m8 &= 7;
                $u1 = ($m8 == 3 || $m8 == 5) && $m24 == 2 ? -$m14 : $m14;
            }
            $jsf[0][] = $u1;
            $u2 = 0;
            if ($m24 & 1) {
                // if $m24 is odd
                $m8 = $k2->testBit(0) + 2 * $k2->testBit(1) + 4 * $k2->testBit(2);
                $m8 += $d2;
                $m8 &= 7;
                $u2 = ($m8 == 3 || $m8 == 5) && $m14 == 2 ? -$m24 : $m24;
            }
            $jsf[1][] = $u2;
            // second phase
            if (2 * $d1 == $u1 + 1) {
                $d1 = 1 - $d1;
            }
            if (2 * $d2 == $u2 + 1) {
                $d2 = 1 - $d2;
            }
            $k1 = $k1->bitwise_rightShift(1);
            $k2 = $k2->bitwise_rightShift(1);
        }
        return $jsf;
    }
    /**
    * Returns the affine point
    *
    * A Jacobian Coordinate is of the form (x, y, z).
    To convert a Jacobian Coordinate to an Affine Point
    you do (x / z^2, y / z^3)
    *
    * @return \phpseclib3\Math\PrimeField\Integer[]
    */
    public function convertToAffine(array $p)
    {
        if (!isset($p[2])) {
            return $p;
        }
        list($x, $y, $z) = $p;
        $z = $this->one->divide($z);
        $z2 = $z->multiply($z);
        return [$x->multiply($z2), $y->multiply($z2)->multiply($z)];
    }
    /**
     * Converts an affine point to a jacobian coordinate
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToInternal(array $p)
    {
        if (isset($p[2])) {
            return $p;
        }
        $p[2] = clone $this->one;
        $p['fresh'] = true;
        return $p;
    }
}<?php

/**
 * Curves over y^2 + x*y = x^3 + a*x^2 + b
 *
 * These are curves used in SEC 2 over prime fields: http://www.secg.org/SEC2-Ver-1.0.pdf
 * The curve is a weierstrass curve with a[3] and a[2] set to 0.
 *
 * Uses Jacobian Coordinates for speed if able:
 *
 * https://en.wikipedia.org/wiki/Jacobian_curve
 * https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\BinaryField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\BinaryField\Integer as BinaryInteger;
/**
 * Curves over y^2 + x*y = x^3 + a*x^2 + b
 *
 * @package Binary
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Binary extends Base
{
    /**
     * Binary Field Integer factory
     *
     * @var \phpseclib3\Math\BinaryField
     */
    protected $factory;
    /**
     * Cofficient for x^1
     *
     * @var object
     */
    protected $a;
    /**
     * Cofficient for x^0
     *
     * @var object
     */
    protected $b;
    /**
     * Base Point
     *
     * @var object
     */
    protected $p;
    /**
     * The number one over the specified finite field
     *
     * @var object
     */
    protected $one;
    /**
     * The modulo
     *
     * @var BigInteger
     */
    protected $modulo;
    /**
     * The Order
     *
     * @var BigInteger
     */
    protected $order;
    /**
     * Sets the modulo
     */
    public function setModulo(...$modulo)
    {
        $this->modulo = $modulo;
        $this->factory = new BinaryField(...$modulo);
        $this->one = $this->factory->newInteger("\x01");
    }
    /**
     * Set coefficients a and b
     *
     * @param string $a
     * @param string $b
     */
    public function setCoefficients($a, $b)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->a = $this->factory->newInteger(pack('H*', $a));
        $this->b = $this->factory->newInteger(pack('H*', $b));
    }
    /**
     * Set x and y coordinates for the base point
     *
     * @param (string | BinaryInteger) $x
     * @param (string | BinaryInteger) $y
     */
    public function setBasePoint($x, $y)
    {
        switch (true) {
            case !is_string($x) && !$x instanceof BinaryInteger:
                throw new \UnexpectedValueException('Argument 1 passed to Binary::setBasePoint() must be a string or an instance of BinaryField\\Integer');
            case !is_string($y) && !$y instanceof BinaryInteger:
                throw new \UnexpectedValueException('Argument 2 passed to Binary::setBasePoint() must be a string or an instance of BinaryField\\Integer');
        }
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->p = [is_string($x) ? $this->factory->newInteger(pack('H*', $x)) : $x, is_string($y) ? $this->factory->newInteger(pack('H*', $y)) : $y];
    }
    /**
     * Retrieve the base point as an array
     *
     * @return array
     */
    public function getBasePoint()
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        /*
        if (!isset($this->p)) {
            throw new \RuntimeException('setBasePoint needs to be called before this method');
        }
        */
        return $this->p;
    }
    /**
     * Adds two points on the curve
     *
     * @return FiniteField[]
     */
    public function addPoint(array $p, array $q)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            if (count($q)) {
                return $q;
            }
            if (count($p)) {
                return $p;
            }
            return [];
        }
        if (!isset($p[2]) || !isset($q[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        if ($p[0]->equals($q[0])) {
            return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
        }
        // formulas from http://hyperelliptic.org/EFD/g12o/auto-shortw-jacobian.html
        list($x1, $y1, $z1) = $p;
        list($x2, $y2, $z2) = $q;
        $o1 = $z1->multiply($z1);
        $b = $x2->multiply($o1);
        if ($z2->equals($this->one)) {
            $d = $y2->multiply($o1)->multiply($z1);
            $e = $x1->add($b);
            $f = $y1->add($d);
            $z3 = $e->multiply($z1);
            $h = $f->multiply($x2)->add($z3->multiply($y2));
            $i = $f->add($z3);
            $g = $z3->multiply($z3);
            $p1 = $this->a->multiply($g);
            $p2 = $f->multiply($i);
            $p3 = $e->multiply($e)->multiply($e);
            $x3 = $p1->add($p2)->add($p3);
            $y3 = $i->multiply($x3)->add($g->multiply($h));
            return [$x3, $y3, $z3];
        }
        $o2 = $z2->multiply($z2);
        $a = $x1->multiply($o2);
        $c = $y1->multiply($o2)->multiply($z2);
        $d = $y2->multiply($o1)->multiply($z1);
        $e = $a->add($b);
        $f = $c->add($d);
        $g = $e->multiply($z1);
        $h = $f->multiply($x2)->add($g->multiply($y2));
        $z3 = $g->multiply($z2);
        $i = $f->add($z3);
        $p1 = $this->a->multiply($z3->multiply($z3));
        $p2 = $f->multiply($i);
        $p3 = $e->multiply($e)->multiply($e);
        $x3 = $p1->add($p2)->add($p3);
        $y3 = $i->multiply($x3)->add($g->multiply($g)->multiply($h));
        return [$x3, $y3, $z3];
    }
    /**
     * Doubles a point on a curve
     *
     * @return FiniteField[]
     */
    public function doublePoint(array $p)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p)) {
            return [];
        }
        if (!isset($p[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        // formulas from http://hyperelliptic.org/EFD/g12o/auto-shortw-jacobian.html
        list($x1, $y1, $z1) = $p;
        $a = $x1->multiply($x1);
        $b = $a->multiply($a);
        if ($z1->equals($this->one)) {
            $x3 = $b->add($this->b);
            $z3 = clone $x1;
            $p1 = $a->add($y1)->add($z3)->multiply($this->b);
            $p2 = $a->add($y1)->multiply($b);
            $y3 = $p1->add($p2);
            return [$x3, $y3, $z3];
        }
        $c = $z1->multiply($z1);
        $d = $c->multiply($c);
        $x3 = $b->add($this->b->multiply($d->multiply($d)));
        $z3 = $x1->multiply($c);
        $p1 = $b->multiply($z3);
        $p2 = $a->add($y1->multiply($z1))->add($z3)->multiply($x3);
        $y3 = $p1->add($p2);
        return [$x3, $y3, $z3];
    }
    /**
    * Returns the X coordinate and the derived Y coordinate
    *
    * Not supported because it is covered by patents.
    Quoting https://www.openssl.org/docs/man1.1.0/apps/ecparam.html ,
    *
    * "Due to patent issues the compressed option is disabled by default for binary curves
    and can be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at
    compile time."
    *
    * @return array
    */
    public function derivePoint($m)
    {
        throw new \RuntimeException('Point compression on binary finite field elliptic curves is not supported');
    }
    /**
     * Tests whether or not the x / y values satisfy the equation
     *
     * @return boolean
     */
    public function verifyPoint(array $p)
    {
        list($x, $y) = $p;
        $lhs = $y->multiply($y);
        $lhs = $lhs->add($x->multiply($y));
        $x2 = $x->multiply($x);
        $x3 = $x2->multiply($x);
        $rhs = $x3->add($this->a->multiply($x2))->add($this->b);
        return $lhs->equals($rhs);
    }
    /**
     * Returns the modulo
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function getModulo()
    {
        return $this->modulo;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getA()
    {
        return $this->a;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getB()
    {
        return $this->b;
    }
    /**
    * Returns the affine point
    *
    * A Jacobian Coordinate is of the form (x, y, z).
    To convert a Jacobian Coordinate to an Affine Point
    you do (x / z^2, y / z^3)
    *
    * @return \phpseclib3\Math\PrimeField\Integer[]
    */
    public function convertToAffine(array $p)
    {
        if (!isset($p[2])) {
            return $p;
        }
        list($x, $y, $z) = $p;
        $z = $this->one->divide($z);
        $z2 = $z->multiply($z);
        return [$x->multiply($z2), $y->multiply($z2)->multiply($z)];
    }
    /**
     * Converts an affine point to a jacobian coordinate
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToInternal(array $p)
    {
        if (isset($p[2])) {
            return $p;
        }
        $p[2] = clone $this->one;
        $p['fresh'] = true;
        return $p;
    }
}<?php

/**
 * Curve methods common to all curves
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Math\BigInteger;
/**
 * Base
 *
 * @package Prime
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Base
{
    /**
     * Doubles
     *
     * @var object[]
     */
    protected $doubles;
    /**
     * NAF Points
     *
     * @var int[]
     */
    private $naf;
    /**
     * The Order
     *
     * @var BigInteger
     */
    protected $order;
    /**
     * Finite Field Integer factory
     *
     * @var \phpseclib3\Math\FiniteField\Integer
     */
    protected $factory;
    /**
     * Returns a random integer
     *
     * @return object
     */
    public function randomInteger()
    {
        return $this->factory->randomInteger();
    }
    /**
     * Converts a BigInteger to a \phpseclib3\Math\FiniteField\Integer integer
     *
     * @return object
     */
    public function convertInteger(BigInteger $x)
    {
        return $this->factory->newInteger($x);
    }
    /**
     * Returns the length, in bytes, of the modulo
     *
     * @return integer
     */
    public function getLengthInBytes()
    {
        return $this->factory->getLengthInBytes();
    }
    /**
     * Returns the length, in bits, of the modulo
     *
     * @return integer
     */
    public function getLength()
    {
        return $this->factory->getLength();
    }
    /**
    * Multiply a point on the curve by a scalar
    *
    * Uses the montgomery ladder technique as described here:
    *
    * https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder
    https://github.com/phpecc/phpecc/issues/16#issuecomment-59176772
    *
    * @return array
    */
    public function multiplyPoint(array $p, BigInteger $d)
    {
        $alreadyInternal = isset($p[2]);
        $r = $alreadyInternal ? [[], $p] : [[], $this->convertToInternal($p)];
        $d = $d->toBits();
        for ($i = 0; $i < strlen($d); $i++) {
            $d_i = (int) $d[$i];
            $r[1 - $d_i] = $this->addPoint($r[0], $r[1]);
            $r[$d_i] = $this->doublePoint($r[$d_i]);
        }
        return $alreadyInternal ? $r[0] : $this->convertToAffine($r[0]);
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return BigInteger
     */
    public function createRandomMultiplier()
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        return BigInteger::randomRange($one, $this->order->subtract($one));
    }
    /**
     * Performs range check
     */
    public function rangeCheck(BigInteger $x)
    {
        static $zero;
        if (!isset($zero)) {
            $zero = new BigInteger();
        }
        if (!isset($this->order)) {
            throw new \RuntimeException('setOrder needs to be called before this method');
        }
        if ($x->compare($this->order) > 0 || $x->compare($zero) <= 0) {
            throw new \RangeException('x must be between 1 and the order of the curve');
        }
    }
    /**
     * Sets the Order
     */
    public function setOrder(BigInteger $order)
    {
        $this->order = $order;
    }
    /**
     * Returns the Order
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function getOrder()
    {
        return $this->order;
    }
    /**
     * Use a custom defined modular reduction function
     *
     * @return object
     */
    public function setReduction(callable $func)
    {
        $this->factory->setReduction($func);
    }
    /**
     * Returns the affine point
     *
     * @return object[]
     */
    public function convertToAffine(array $p)
    {
        return $p;
    }
    /**
     * Converts an affine point to a jacobian coordinate
     *
     * @return object[]
     */
    public function convertToInternal(array $p)
    {
        return $p;
    }
    /**
     * Negates a point
     *
     * @return object[]
     */
    public function negatePoint(array $p)
    {
        $temp = [$p[0], $p[1]->negate()];
        if (isset($p[2])) {
            $temp[] = $p[2];
        }
        return $temp;
    }
    /**
     * Multiply and Add Points
     *
     * @return int[]
     */
    public function multiplyAddPoints(array $points, array $scalars)
    {
        $p1 = $this->convertToInternal($points[0]);
        $p2 = $this->convertToInternal($points[1]);
        $p1 = $this->multiplyPoint($p1, $scalars[0]);
        $p2 = $this->multiplyPoint($p2, $scalars[1]);
        $r = $this->addPoint($p1, $p2);
        return $this->convertToAffine($r);
    }
}<?php

/**
 * EC Public Key
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC;

use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\Hash;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
use phpseclib3\Crypt\Common;
use phpseclib3\Exception\UnsupportedOperationException;
use phpseclib3\Common\Functions\Strings;
/**
 * EC Public Key
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PublicKey extends EC implements Common\PublicKey
{
    use Common\Traits\Fingerprint;
    /**
     * Verify a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @param string $signature
     * @return mixed
     */
    public function verify($message, $signature)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
        }
        $shortFormat = $this->shortFormat;
        $format = $this->sigFormat;
        if ($format === false) {
            return false;
        }
        $order = $this->curve->getOrder();
        if ($this->curve instanceof TwistedEdwardsCurve) {
            if ($shortFormat == 'SSH2') {
                list(, $signature) = Strings::unpackSSH2('ss', $signature);
            }
            if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
                return sodium_crypto_sign_verify_detached($signature, $message, $this->toString('libsodium'));
            }
            $curve = $this->curve;
            if (strlen($signature) != 2 * $curve::SIZE) {
                return false;
            }
            $R = \Phabel\Target\Php80\Polyfill::substr($signature, 0, $curve::SIZE);
            $S = \Phabel\Target\Php80\Polyfill::substr($signature, $curve::SIZE);
            try {
                $R = PKCS1::extractPoint($R, $curve);
                $R = $this->curve->convertToInternal($R);
            } catch (\Exception $e) {
                return false;
            }
            $S = strrev($S);
            $S = new BigInteger($S, 256);
            if ($S->compare($order) >= 0) {
                return false;
            }
            $A = $curve->encodePoint($this->QA);
            if ($curve instanceof Ed25519) {
                $dom2 = !isset($this->context) ? '' : 'SigEd25519 no Ed25519 collisions ' . chr(strlen($this->context)) . $this->context;
            } else {
                $context = isset($this->context) ? $this->context : '';
                $dom2 = 'SigEd448 ' . chr(strlen($context)) . $context;
            }
            $hash = new Hash($curve::HASH);
            $k = $hash->hash($dom2 . \Phabel\Target\Php80\Polyfill::substr($signature, 0, $curve::SIZE) . $A . $message);
            $k = strrev($k);
            $k = new BigInteger($k, 256);
            list(, $k) = $k->divide($order);
            $qa = $curve->convertToInternal($this->QA);
            $lhs = $curve->multiplyPoint($curve->getBasePoint(), $S);
            $rhs = $curve->multiplyPoint($qa, $k);
            $rhs = $curve->addPoint($rhs, $R);
            $rhs = $curve->convertToAffine($rhs);
            return $lhs[0]->equals($rhs[0]) && $lhs[1]->equals($rhs[1]);
        }
        $params = $format::load($signature);
        if ($params === false || count($params) != 2) {
            return false;
        }
        extract($params);
        if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
            $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature;
            $result = openssl_verify($message, $sig, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash());
            if ($result != -1) {
                return (bool) $result;
            }
        }
        $n_1 = $order->subtract(self::$one);
        if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) {
            return false;
        }
        $e = $this->hash->hash($message);
        $e = new BigInteger($e, 256);
        $Ln = $this->hash->getLength() - $order->getLength();
        $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e;
        $w = $s->modInverse($order);
        list(, $u1) = $z->multiply($w)->divide($order);
        list(, $u2) = $r->multiply($w)->divide($order);
        $u1 = $this->curve->convertInteger($u1);
        $u2 = $this->curve->convertInteger($u2);
        list($x1, $y1) = $this->curve->multiplyAddPoints([$this->curve->getBasePoint(), $this->QA], [$u1, $u2]);
        $x1 = $x1->toBigInteger();
        list(, $x1) = $x1->divide($order);
        return $x1->equals($r);
    }
    /**
     * Returns the public key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePublicKey');
        return $type::savePublicKey($this->curve, $this->QA, $options);
    }
}<?php

/**
 * Pure-PHP implementation of RC4.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
 *  - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
 *
 * RC4 is also known as ARCFOUR or ARC4.  The reason is elaborated upon at Wikipedia.  This class is named RC4 and not
 * ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $rc4 = new \phpseclib3\Crypt\RC4();
 *
 *    $rc4->setKey('abcdefgh');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $rc4->decrypt($rc4->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   RC4
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\StreamCipher;
/**
 * Pure-PHP implementation of RC4.
 *
 * @package RC4
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class RC4 extends StreamCipher
{
    /**
     * @access private
     * @see \phpseclib3\Crypt\RC4::_crypt()
     */
    const ENCRYPT = 0;
    /**
     * @access private
     * @see \phpseclib3\Crypt\RC4::_crypt()
     */
    const DECRYPT = 1;
    /**
     * Key Length (in bytes)
     *
     * @see \phpseclib3\Crypt\RC4::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 128;
    // = 1024 bits
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'arcfour';
    /**
     * The Key
     *
     * @see self::setKey()
     * @var string
     * @access private
     */
    protected $key;
    /**
     * The Key Stream for decryption and encryption
     *
     * @see self::setKey()
     * @var array
     * @access private
     */
    private $stream;
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        if ($engine == self::ENGINE_OPENSSL) {
            if ($this->continuousBuffer) {
                return false;
            }
            if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
                $this->cipher_name_openssl = 'rc4-40';
            } else {
                switch (strlen($this->key)) {
                    case 5:
                        $this->cipher_name_openssl = 'rc4-40';
                        break;
                    case 8:
                        $this->cipher_name_openssl = 'rc4-64';
                        break;
                    case 16:
                        $this->cipher_name_openssl = 'rc4';
                        break;
                    default:
                        return false;
                }
            }
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Sets the key length
     *
     * Keys can be between 1 and 256 bytes long.
     *
     * @access public
     * @param int $length
     * @throws \LengthException if the key length is invalid
     */
    public function setKeyLength($length)
    {
        if ($length < 8 || $length > 2048) {
            throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 256 bytes are supported');
        }
        $this->key_length = $length >> 3;
        parent::setKeyLength($length);
    }
    /**
     * Sets the key length
     *
     * Keys can be between 1 and 256 bytes long.
     *
     * @access public
     * @param string $key
     */
    public function setKey($key)
    {
        $length = strlen($key);
        if ($length < 1 || $length > 256) {
            throw new \LengthException('Key size of ' . $length . ' bytes is not supported by RC4. Keys must be between 1 and 256 bytes long');
        }
        parent::setKey($key);
    }
    /**
     * Encrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @see self::crypt()
     * @access public
     * @param string $plaintext
     * @return string $ciphertext
     */
    public function encrypt($plaintext)
    {
        if ($this->engine != self::ENGINE_INTERNAL) {
            return parent::encrypt($plaintext);
        }
        return $this->crypt($plaintext, self::ENCRYPT);
    }
    /**
    * Decrypts a message.
    *
    * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
    At least if the continuous buffer is disabled.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
    * @see self::crypt()
    * @access public
    * @param string $ciphertext
    * @return string $plaintext
    */
    public function decrypt($ciphertext)
    {
        if ($this->engine != self::ENGINE_INTERNAL) {
            return parent::decrypt($ciphertext);
        }
        return $this->crypt($ciphertext, self::DECRYPT);
    }
    /**
     * Encrypts a block
     *
     * @access private
     * @param string $in
     */
    protected function encryptBlock($in)
    {
        // RC4 does not utilize this method
    }
    /**
     * Decrypts a block
     *
     * @access private
     * @param string $in
     */
    protected function decryptBlock($in)
    {
        // RC4 does not utilize this method
    }
    /**
     * Setup the key (expansion)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
     * @access private
     */
    protected function setupKey()
    {
        $key = $this->key;
        $keyLength = strlen($key);
        $keyStream = range(0, 255);
        $j = 0;
        for ($i = 0; $i < 256; $i++) {
            $j = $j + $keyStream[$i] + ord($key[$i % $keyLength]) & 255;
            $temp = $keyStream[$i];
            $keyStream[$i] = $keyStream[$j];
            $keyStream[$j] = $temp;
        }
        $this->stream = [];
        $this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = [
            0,
            // index $i
            0,
            // index $j
            $keyStream,
        ];
    }
    /**
     * Encrypts or decrypts a message.
     *
     * @see self::encrypt()
     * @see self::decrypt()
     * @access private
     * @param string $text
     * @param int $mode
     * @return string $text
     */
    private function crypt($text, $mode)
    {
        if ($this->changed) {
            $this->setup();
        }
        $stream =& $this->stream[$mode];
        if ($this->continuousBuffer) {
            $i =& $stream[0];
            $j =& $stream[1];
            $keyStream =& $stream[2];
        } else {
            $i = $stream[0];
            $j = $stream[1];
            $keyStream = $stream[2];
        }
        $len = strlen($text);
        for ($k = 0; $k < $len; ++$k) {
            $i = $i + 1 & 255;
            $ksi = $keyStream[$i];
            $j = $j + $ksi & 255;
            $ksj = $keyStream[$j];
            $keyStream[$i] = $ksj;
            $keyStream[$j] = $ksi;
            $text[$k] = $text[$k] ^ chr($keyStream[$ksj + $ksi & 255]);
        }
        return $text;
    }
}<?php

/**
 * PKCS Formatted Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

/**
 * PKCS1 Formatted Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS
{
    /**
     * Auto-detect the format
     */
    const MODE_ANY = 0;
    /**
     * Require base64-encoded PEM's be supplied
     */
    const MODE_PEM = 1;
    /**
     * Require raw DER's be supplied
     */
    const MODE_DER = 2;
    /**#@-*/
    /**
     * Is the key a base-64 encoded PEM, DER or should it be auto-detected?
     *
     * @access private
     * @var int
     */
    protected static $format = self::MODE_ANY;
    /**
     * Require base64-encoded PEM's be supplied
     *
     * @access public
     */
    public static function requirePEM()
    {
        self::$format = self::MODE_PEM;
    }
    /**
     * Require raw DER's be supplied
     *
     * @access public
     */
    public static function requireDER()
    {
        self::$format = self::MODE_DER;
    }
    /**
     * Accept any format and auto detect the format
     *
     * This is the default setting
     *
     * @access public
     */
    public static function requireAny()
    {
        self::$format = self::MODE_ANY;
    }
}<?php

/**
 * PKCS1 Formatted Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\AES;
use phpseclib3\Crypt\DES;
use phpseclib3\Crypt\TripleDES;
use phpseclib3\File\ASN1;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedAlgorithmException;
/**
 * PKCS1 Formatted Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends PKCS
{
    /**
     * Default encryption algorithm
     *
     * @var string
     * @access private
     */
    private static $defaultEncryptionAlgorithm = 'AES-128-CBC';
    /**
     * Sets the default encryption algorithm
     *
     * @access public
     * @param string $algo
     */
    public static function setEncryptionAlgorithm($algo)
    {
        self::$defaultEncryptionAlgorithm = $algo;
    }
    /**
     * Returns the mode constant corresponding to the mode string
     *
     * @access public
     * @param string $mode
     * @return int
     * @throws \UnexpectedValueException if the block cipher mode is unsupported
     */
    private static function getEncryptionMode($mode)
    {
        switch ($mode) {
            case 'CBC':
            case 'ECB':
            case 'CFB':
            case 'OFB':
            case 'CTR':
                return $mode;
        }
        throw new \UnexpectedValueException('Unsupported block cipher mode of operation');
    }
    /**
     * Returns a cipher object corresponding to a string
     *
     * @access public
     * @param string $algo
     * @return string
     * @throws \UnexpectedValueException if the encryption algorithm is unsupported
     */
    private static function getEncryptionObject($algo)
    {
        $modes = '(CBC|ECB|CFB|OFB|CTR)';
        switch (true) {
            case preg_match("#^AES-(128|192|256)-{$modes}\$#", $algo, $matches):
                $cipher = new AES(self::getEncryptionMode($matches[2]));
                $cipher->setKeyLength($matches[1]);
                return $cipher;
            case preg_match("#^DES-EDE3-{$modes}\$#", $algo, $matches):
                return new TripleDES(self::getEncryptionMode($matches[1]));
            case preg_match("#^DES-{$modes}\$#", $algo, $matches):
                return new DES(self::getEncryptionMode($matches[1]));
            default:
                throw new UnsupportedAlgorithmException($algo . ' is not a supported algorithm');
        }
    }
    /**
     * Generate a symmetric key for PKCS#1 keys
     *
     * @access private
     * @param string $password
     * @param string $iv
     * @param int $length
     * @return string
     */
    private static function generateSymmetricKey($password, $iv, $length)
    {
        $symkey = '';
        $iv = \Phabel\Target\Php80\Polyfill::substr($iv, 0, 8);
        while (strlen($symkey) < $length) {
            $symkey .= md5($symkey . $password . $iv, true);
        }
        return \Phabel\Target\Php80\Polyfill::substr($symkey, 0, $length);
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    protected static function load($key, $password)
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
                   "outside the scope" of PKCS#1.  PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
                   protect private keys, however, that's not what OpenSSL* does.  OpenSSL protects private keys by adding
                   two new "fields" to the key - DEK-Info and Proc-Type.  These fields are discussed here:
        
                   http://tools.ietf.org/html/rfc1421#section-4.6.1.1
                   http://tools.ietf.org/html/rfc1421#section-4.6.1.3
        
                   DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
                   DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
                   function.  As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
                   own implementation.  ie. the implementation *is* the standard and any bugs that may exist in that
                   implementation are part of the standard, as well.
        
                   * OpenSSL is the de facto standard.  It's utilized by OpenSSH and other projects */
        if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
            $iv = Hex::decode(trim($matches[2]));
            // remove the Proc-Type / DEK-Info sections as they're no longer needed
            $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key);
            $ciphertext = ASN1::extractBER($key);
            if ($ciphertext === false) {
                $ciphertext = $key;
            }
            $crypto = self::getEncryptionObject($matches[1]);
            $crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3));
            $crypto->setIV($iv);
            $key = $crypto->decrypt($ciphertext);
        } else {
            if (self::$format != self::MODE_DER) {
                $decoded = ASN1::extractBER($key);
                if ($decoded !== false) {
                    $key = $decoded;
                } elseif (self::$format == self::MODE_PEM) {
                    throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text');
                }
            }
        }
        return $key;
    }
    /**
     * Wrap a private key appropriately
     *
     * @access public
     * @param string $key
     * @param string $type
     * @param string $password
     * @param array $options optional
     * @return string
     */
    protected static function wrapPrivateKey($key, $type, $password, array $options = [])
    {
        if (empty($password) || !is_string($password)) {
            return "-----BEGIN {$type} PRIVATE KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END {$type} PRIVATE KEY-----";
        }
        $encryptionAlgorithm = isset($options['encryptionAlgorithm']) ? $options['encryptionAlgorithm'] : self::$defaultEncryptionAlgorithm;
        $cipher = self::getEncryptionObject($encryptionAlgorithm);
        $iv = Random::string($cipher->getBlockLength() >> 3);
        $cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3));
        $cipher->setIV($iv);
        $iv = strtoupper(Hex::encode($iv));
        return "-----BEGIN {$type} PRIVATE KEY-----\r\n" . 'Proc-Type: 4,ENCRYPTED
DEK-Info: ' . $encryptionAlgorithm . ",{$iv}\r\n" . "\r\n" . chunk_split(Base64::encode($cipher->encrypt($key)), 64) . "-----END {$type} PRIVATE KEY-----";
    }
    /**
     * Wrap a public key appropriately
     *
     * @access public
     * @param string $key
     * @param string $type
     * @return string
     */
    protected static function wrapPublicKey($key, $type)
    {
        return "-----BEGIN {$type} PUBLIC KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END {$type} PUBLIC KEY-----";
    }
}<?php

/**
 * PKCS#8 Formatted Key Handler
 *
 * PHP version 5
 *
 * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
 * is specific to private keys it's basically creating a DER-encoded wrapper
 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Crypt\DES;
use phpseclib3\Crypt\RC2;
use phpseclib3\Crypt\RC4;
use phpseclib3\Crypt\AES;
use phpseclib3\Crypt\TripleDES;
use phpseclib3\Crypt\Random;
use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedAlgorithmException;
/**
 * PKCS#8 Formatted Key Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends PKCS
{
    /**
     * Default encryption algorithm
     *
     * @var string
     * @access private
     */
    private static $defaultEncryptionAlgorithm = 'id-PBES2';
    /**
     * Default encryption scheme
     *
     * Only used when defaultEncryptionAlgorithm is id-PBES2
     *
     * @var string
     * @access private
     */
    private static $defaultEncryptionScheme = 'aes128-CBC-PAD';
    /**
     * Default PRF
     *
     * Only used when defaultEncryptionAlgorithm is id-PBES2
     *
     * @var string
     * @access private
     */
    private static $defaultPRF = 'id-hmacWithSHA256';
    /**
     * Default Iteration Count
     *
     * @var int
     * @access private
     */
    private static $defaultIterationCount = 2048;
    /**
     * OIDs loaded
     *
     * @var bool
     * @access private
     */
    private static $oidsLoaded = false;
    /**
     * Sets the default encryption algorithm
     *
     * @access public
     * @param string $algo
     */
    public static function setEncryptionAlgorithm($algo)
    {
        self::$defaultEncryptionAlgorithm = $algo;
    }
    /**
     * Sets the default encryption algorithm for PBES2
     *
     * @access public
     * @param string $algo
     */
    public static function setEncryptionScheme($algo)
    {
        self::$defaultEncryptionScheme = $algo;
    }
    /**
     * Sets the iteration count
     *
     * @access public
     * @param int $count
     */
    public static function setIterationCount($count)
    {
        self::$defaultIterationCount = $count;
    }
    /**
     * Sets the PRF for PBES2
     *
     * @access public
     * @param string $algo
     */
    public static function setPRF($algo)
    {
        self::$defaultPRF = $algo;
    }
    /**
     * Returns a SymmetricKey object based on a PBES1 $algo
     *
     * @return \phpseclib3\Crypt\Common\SymmetricKey
     * @access public
     * @param string $algo
     */
    private static function getPBES1EncryptionObject($algo)
    {
        $algo = preg_match('#^pbeWith(?:MD2|MD5|SHA1|SHA)And(.*?)-CBC$#', $algo, $matches) ? $matches[1] : \Phabel\Target\Php80\Polyfill::substr($algo, 13);
        // strlen('pbeWithSHAAnd') == 13
        switch ($algo) {
            case 'DES':
                $cipher = new DES('cbc');
                break;
            case 'RC2':
                $cipher = new RC2('cbc');
                break;
            case '3-KeyTripleDES':
                $cipher = new TripleDES('cbc');
                break;
            case '2-KeyTripleDES':
                $cipher = new TripleDES('cbc');
                $cipher->setKeyLength(128);
                break;
            case '128BitRC2':
                $cipher = new RC2('cbc');
                $cipher->setKeyLength(128);
                break;
            case '40BitRC2':
                $cipher = new RC2('cbc');
                $cipher->setKeyLength(40);
                break;
            case '128BitRC4':
                $cipher = new RC4();
                $cipher->setKeyLength(128);
                break;
            case '40BitRC4':
                $cipher = new RC4();
                $cipher->setKeyLength(40);
                break;
            default:
                throw new UnsupportedAlgorithmException("{$algo} is not a supported algorithm");
        }
        return $cipher;
    }
    /**
     * Returns a hash based on a PBES1 $algo
     *
     * @return string
     * @access public
     * @param string $algo
     */
    private static function getPBES1Hash($algo)
    {
        if (preg_match('#^pbeWith(MD2|MD5|SHA1|SHA)And.*?-CBC$#', $algo, $matches)) {
            return $matches[1] == 'SHA' ? 'sha1' : $matches[1];
        }
        return 'sha1';
    }
    /**
     * Returns a KDF baesd on a PBES1 $algo
     *
     * @return string
     * @access public
     * @param string $algo
     */
    private static function getPBES1KDF($algo)
    {
        switch ($algo) {
            case 'pbeWithMD2AndDES-CBC':
            case 'pbeWithMD2AndRC2-CBC':
            case 'pbeWithMD5AndDES-CBC':
            case 'pbeWithMD5AndRC2-CBC':
            case 'pbeWithSHA1AndDES-CBC':
            case 'pbeWithSHA1AndRC2-CBC':
                return 'pbkdf1';
        }
        return 'pkcs12';
    }
    /**
     * Returns a SymmetricKey object baesd on a PBES2 $algo
     *
     * @return SymmetricKey
     * @access public
     * @param string $algo
     */
    private static function getPBES2EncryptionObject($algo)
    {
        switch ($algo) {
            case 'desCBC':
                $cipher = new TripleDES('cbc');
                break;
            case 'des-EDE3-CBC':
                $cipher = new TripleDES('cbc');
                break;
            case 'rc2CBC':
                $cipher = new RC2('cbc');
                // in theory this can be changed
                $cipher->setKeyLength(128);
                break;
            case 'rc5-CBC-PAD':
                throw new UnsupportedAlgorithmException('rc5-CBC-PAD is not supported for PBES2 PKCS#8 keys');
            case 'aes128-CBC-PAD':
            case 'aes192-CBC-PAD':
            case 'aes256-CBC-PAD':
                $cipher = new AES('cbc');
                $cipher->setKeyLength(\Phabel\Target\Php80\Polyfill::substr($algo, 3, 3));
                break;
            default:
                throw new UnsupportedAlgorithmException("{$algo} is not supported");
        }
        return $cipher;
    }
    /**
     * Initialize static variables
     *
     * @access private
     */
    private static function initialize_static_variables()
    {
        if (!static::$childOIDsLoaded) {
            ASN1::loadOIDs(is_array(static::OID_NAME) ? array_combine(static::OID_NAME, static::OID_VALUE) : [static::OID_NAME => static::OID_VALUE]);
            static::$childOIDsLoaded = true;
        }
        if (!self::$oidsLoaded) {
            // from https://tools.ietf.org/html/rfc2898
            ASN1::loadOIDs([
                // PBES1 encryption schemes
                'pbeWithMD2AndDES-CBC' => '1.2.840.113549.1.5.1',
                'pbeWithMD2AndRC2-CBC' => '1.2.840.113549.1.5.4',
                'pbeWithMD5AndDES-CBC' => '1.2.840.113549.1.5.3',
                'pbeWithMD5AndRC2-CBC' => '1.2.840.113549.1.5.6',
                'pbeWithSHA1AndDES-CBC' => '1.2.840.113549.1.5.10',
                'pbeWithSHA1AndRC2-CBC' => '1.2.840.113549.1.5.11',
                // from PKCS#12:
                // https://tools.ietf.org/html/rfc7292
                'pbeWithSHAAnd128BitRC4' => '1.2.840.113549.1.12.1.1',
                'pbeWithSHAAnd40BitRC4' => '1.2.840.113549.1.12.1.2',
                'pbeWithSHAAnd3-KeyTripleDES-CBC' => '1.2.840.113549.1.12.1.3',
                'pbeWithSHAAnd2-KeyTripleDES-CBC' => '1.2.840.113549.1.12.1.4',
                'pbeWithSHAAnd128BitRC2-CBC' => '1.2.840.113549.1.12.1.5',
                'pbeWithSHAAnd40BitRC2-CBC' => '1.2.840.113549.1.12.1.6',
                'id-PBKDF2' => '1.2.840.113549.1.5.12',
                'id-PBES2' => '1.2.840.113549.1.5.13',
                'id-PBMAC1' => '1.2.840.113549.1.5.14',
                // from PKCS#5 v2.1:
                // http://www.rsa.com/rsalabs/pkcs/files/h11302-wp-pkcs5v2-1-password-based-cryptography-standard.pdf
                'id-hmacWithSHA1' => '1.2.840.113549.2.7',
                'id-hmacWithSHA224' => '1.2.840.113549.2.8',
                'id-hmacWithSHA256' => '1.2.840.113549.2.9',
                'id-hmacWithSHA384' => '1.2.840.113549.2.10',
                'id-hmacWithSHA512' => '1.2.840.113549.2.11',
                'id-hmacWithSHA512-224' => '1.2.840.113549.2.12',
                'id-hmacWithSHA512-256' => '1.2.840.113549.2.13',
                'desCBC' => '1.3.14.3.2.7',
                'des-EDE3-CBC' => '1.2.840.113549.3.7',
                'rc2CBC' => '1.2.840.113549.3.2',
                'rc5-CBC-PAD' => '1.2.840.113549.3.9',
                'aes128-CBC-PAD' => '2.16.840.1.101.3.4.1.2',
                'aes192-CBC-PAD' => '2.16.840.1.101.3.4.1.22',
                'aes256-CBC-PAD' => '2.16.840.1.101.3.4.1.42',
            ]);
            self::$oidsLoaded = true;
        }
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    protected static function load($key, $password = '')
    {
        $decoded = self::preParse($key);
        $meta = [];
        $decrypted = ASN1::asn1map($decoded[0], Maps\EncryptedPrivateKeyInfo::MAP);
        if (strlen($password) && is_array($decrypted)) {
            $algorithm = $decrypted['encryptionAlgorithm']['algorithm'];
            switch ($algorithm) {
                // PBES1
                case 'pbeWithMD2AndDES-CBC':
                case 'pbeWithMD2AndRC2-CBC':
                case 'pbeWithMD5AndDES-CBC':
                case 'pbeWithMD5AndRC2-CBC':
                case 'pbeWithSHA1AndDES-CBC':
                case 'pbeWithSHA1AndRC2-CBC':
                case 'pbeWithSHAAnd3-KeyTripleDES-CBC':
                case 'pbeWithSHAAnd2-KeyTripleDES-CBC':
                case 'pbeWithSHAAnd128BitRC2-CBC':
                case 'pbeWithSHAAnd40BitRC2-CBC':
                case 'pbeWithSHAAnd128BitRC4':
                case 'pbeWithSHAAnd40BitRC4':
                    $cipher = self::getPBES1EncryptionObject($algorithm);
                    $hash = self::getPBES1Hash($algorithm);
                    $kdf = self::getPBES1KDF($algorithm);
                    $meta['meta']['algorithm'] = $algorithm;
                    $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
                    extract(ASN1::asn1map($temp[0], Maps\PBEParameter::MAP));
                    $iterationCount = (int) $iterationCount->toString();
                    $cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount);
                    $key = $cipher->decrypt($decrypted['encryptedData']);
                    $decoded = ASN1::decodeBER($key);
                    if (empty($decoded)) {
                        throw new \RuntimeException('Unable to decode BER 2');
                    }
                    break;
                case 'id-PBES2':
                    $meta['meta']['algorithm'] = $algorithm;
                    $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
                    $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP);
                    extract($temp);
                    $cipher = self::getPBES2EncryptionObject($encryptionScheme['algorithm']);
                    $meta['meta']['cipher'] = $encryptionScheme['algorithm'];
                    $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
                    $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP);
                    extract($temp);
                    if (!$cipher instanceof RC2) {
                        $cipher->setIV($encryptionScheme['parameters']['octetString']);
                    } else {
                        $temp = ASN1::decodeBER($encryptionScheme['parameters']);
                        extract(ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP));
                        $effectiveKeyLength = (int) $rc2ParametersVersion->toString();
                        switch ($effectiveKeyLength) {
                            case 160:
                                $effectiveKeyLength = 40;
                                break;
                            case 120:
                                $effectiveKeyLength = 64;
                                break;
                            case 58:
                                $effectiveKeyLength = 128;
                                break;
                        }
                        $cipher->setIV($iv);
                        $cipher->setKeyLength($effectiveKeyLength);
                    }
                    $meta['meta']['keyDerivationFunc'] = $keyDerivationFunc['algorithm'];
                    switch ($keyDerivationFunc['algorithm']) {
                        case 'id-PBKDF2':
                            $temp = ASN1::decodeBER($keyDerivationFunc['parameters']);
                            $prf = ['algorithm' => 'id-hmacWithSHA1'];
                            $params = ASN1::asn1map($temp[0], Maps\PBKDF2params::MAP);
                            extract($params);
                            $meta['meta']['prf'] = $prf['algorithm'];
                            $hash = str_replace('-', '/', \Phabel\Target\Php80\Polyfill::substr($prf['algorithm'], 11));
                            $params = [$password, 'pbkdf2', $hash, $salt, (int) $iterationCount->toString()];
                            if (isset($keyLength)) {
                                $params[] = (int) $keyLength->toString();
                            }
                            $cipher->setPassword(...$params);
                            $key = $cipher->decrypt($decrypted['encryptedData']);
                            $decoded = ASN1::decodeBER($key);
                            if (empty($decoded)) {
                                throw new \RuntimeException('Unable to decode BER 3');
                            }
                            break;
                        default:
                            throw new UnsupportedAlgorithmException('Only PBKDF2 is supported for PBES2 PKCS#8 keys');
                    }
                    break;
                case 'id-PBMAC1':
                    //$temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
                    //$value = ASN1::asn1map($temp[0], Maps\PBMAC1params::MAP);
                    // since i can't find any implementation that does PBMAC1 it is unsupported
                    throw new UnsupportedAlgorithmException('Only PBES1 and PBES2 PKCS#8 keys are supported.');
            }
        }
        $private = ASN1::asn1map($decoded[0], Maps\OneAsymmetricKey::MAP);
        if (is_array($private)) {
            if (isset($private['privateKeyAlgorithm']['parameters']) && !$private['privateKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][1]['content'][1])) {
                $temp = $decoded[0]['content'][1]['content'][1];
                $private['privateKeyAlgorithm']['parameters'] = new ASN1\Element(\Phabel\Target\Php80\Polyfill::substr($key, $temp['start'], $temp['length']));
            }
            if (is_array(static::OID_NAME)) {
                if (!in_array($private['privateKeyAlgorithm']['algorithm'], static::OID_NAME)) {
                    throw new UnsupportedAlgorithmException($private['privateKeyAlgorithm']['algorithm'] . ' is not a supported key type');
                }
            } else {
                if ($private['privateKeyAlgorithm']['algorithm'] != static::OID_NAME) {
                    throw new UnsupportedAlgorithmException('Only ' . static::OID_NAME . ' keys are supported; this is a ' . $private['privateKeyAlgorithm']['algorithm'] . ' key');
                }
            }
            if (isset($private['publicKey'])) {
                if ($private['publicKey'][0] != "\x00") {
                    throw new \UnexpectedValueException('The first byte of the public key should be null - not ' . bin2hex($private['publicKey'][0]));
                }
                $private['publicKey'] = \Phabel\Target\Php80\Polyfill::substr($private['publicKey'], 1);
            }
            return $private + $meta;
        }
        // EncryptedPrivateKeyInfo and PublicKeyInfo have largely identical "signatures". the only difference
        // is that the former has an octet string and the later has a bit string. the first byte of a bit
        // string represents the number of bits in the last byte that are to be ignored but, currently,
        // bit strings wanting a non-zero amount of bits trimmed are not supported
        $public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP);
        if (is_array($public)) {
            if ($public['publicKey'][0] != "\x00") {
                throw new \UnexpectedValueException('The first byte of the public key should be null - not ' . bin2hex($public['publicKey'][0]));
            }
            if (is_array(static::OID_NAME)) {
                if (!in_array($public['publicKeyAlgorithm']['algorithm'], static::OID_NAME)) {
                    throw new UnsupportedAlgorithmException($public['publicKeyAlgorithm']['algorithm'] . ' is not a supported key type');
                }
            } else {
                if ($public['publicKeyAlgorithm']['algorithm'] != static::OID_NAME) {
                    throw new UnsupportedAlgorithmException('Only ' . static::OID_NAME . ' keys are supported; this is a ' . $public['publicKeyAlgorithm']['algorithm'] . ' key');
                }
            }
            if (isset($public['publicKeyAlgorithm']['parameters']) && !$public['publicKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][0]['content'][1])) {
                $temp = $decoded[0]['content'][0]['content'][1];
                $public['publicKeyAlgorithm']['parameters'] = new ASN1\Element(\Phabel\Target\Php80\Polyfill::substr($key, $temp['start'], $temp['length']));
            }
            $public['publicKey'] = \Phabel\Target\Php80\Polyfill::substr($public['publicKey'], 1);
            return $public;
        }
        throw new \RuntimeException('Unable to parse using either OneAsymmetricKey or PublicKeyInfo ASN1 maps');
    }
    /**
     * Wrap a private key appropriately
     *
     * @access public
     * @param string $key
     * @param string $attr
     * @param mixed $params
     * @param string $password
     * @param string $oid optional
     * @param string $publicKey optional
     * @param array $options optional
     * @return string
     */
    protected static function wrapPrivateKey($key, $attr, $params, $password, $oid = null, $publicKey = '', array $options = [])
    {
        self::initialize_static_variables();
        $key = ['version' => 'v1', 'privateKeyAlgorithm' => ['algorithm' => is_string(static::OID_NAME) ? static::OID_NAME : $oid, 'parameters' => $params], 'privateKey' => $key];
        if (!empty($attr)) {
            $key['attributes'] = $attr;
        }
        if (!empty($publicKey)) {
            $key['version'] = 'v2';
            $key['publicKey'] = $publicKey;
        }
        $key = ASN1::encodeDER($key, Maps\OneAsymmetricKey::MAP);
        if (!empty($password) && is_string($password)) {
            $salt = Random::string(8);
            $iterationCount = isset($options['iterationCount']) ? $options['iterationCount'] : self::$defaultIterationCount;
            $encryptionAlgorithm = isset($options['encryptionAlgorithm']) ? $options['encryptionAlgorithm'] : self::$defaultEncryptionAlgorithm;
            $encryptionScheme = isset($options['encryptionScheme']) ? $options['encryptionScheme'] : self::$defaultEncryptionScheme;
            $prf = isset($options['PRF']) ? $options['PRF'] : self::$defaultPRF;
            if ($encryptionAlgorithm == 'id-PBES2') {
                $crypto = self::getPBES2EncryptionObject($encryptionScheme);
                $hash = str_replace('-', '/', \Phabel\Target\Php80\Polyfill::substr($prf, 11));
                $kdf = 'pbkdf2';
                $iv = Random::string($crypto->getBlockLength() >> 3);
                $PBKDF2params = ['salt' => $salt, 'iterationCount' => $iterationCount, 'prf' => ['algorithm' => $prf, 'parameters' => null]];
                $PBKDF2params = ASN1::encodeDER($PBKDF2params, Maps\PBKDF2params::MAP);
                if (!$crypto instanceof RC2) {
                    $params = ['octetString' => $iv];
                } else {
                    $params = ['rc2ParametersVersion' => 58, 'iv' => $iv];
                    $params = ASN1::encodeDER($params, Maps\RC2CBCParameter::MAP);
                    $params = new ASN1\Element($params);
                }
                $params = ['keyDerivationFunc' => ['algorithm' => 'id-PBKDF2', 'parameters' => new ASN1\Element($PBKDF2params)], 'encryptionScheme' => ['algorithm' => $encryptionScheme, 'parameters' => $params]];
                $params = ASN1::encodeDER($params, Maps\PBES2params::MAP);
                $crypto->setIV($iv);
            } else {
                $crypto = self::getPBES1EncryptionObject($encryptionAlgorithm);
                $hash = self::getPBES1Hash($encryptionAlgorithm);
                $kdf = self::getPBES1KDF($encryptionAlgorithm);
                $params = ['salt' => $salt, 'iterationCount' => $iterationCount];
                $params = ASN1::encodeDER($params, Maps\PBEParameter::MAP);
            }
            $crypto->setPassword($password, $kdf, $hash, $salt, $iterationCount);
            $key = $crypto->encrypt($key);
            $key = ['encryptionAlgorithm' => ['algorithm' => $encryptionAlgorithm, 'parameters' => new ASN1\Element($params)], 'encryptedData' => $key];
            $key = ASN1::encodeDER($key, Maps\EncryptedPrivateKeyInfo::MAP);
            return "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END ENCRYPTED PRIVATE KEY-----";
        }
        return "-----BEGIN PRIVATE KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END PRIVATE KEY-----";
    }
    /**
     * Wrap a public key appropriately
     *
     * @access public
     * @param string $key
     * @param mixed $params
     * @param string $oid
     * @return string
     */
    protected static function wrapPublicKey($key, $params, $oid = null)
    {
        self::initialize_static_variables();
        $key = ['publicKeyAlgorithm' => ['algorithm' => is_string(static::OID_NAME) ? static::OID_NAME : $oid, 'parameters' => $params], 'publicKey' => "\x00" . $key];
        $key = ASN1::encodeDER($key, Maps\PublicKeyInfo::MAP);
        return "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END PUBLIC KEY-----";
    }
    /**
     * Perform some preliminary parsing of the key
     *
     * @param string $key
     * @return array
     */
    private static function preParse(&$key)
    {
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (self::$format != self::MODE_DER) {
            $decoded = ASN1::extractBER($key);
            if ($decoded !== false) {
                $key = $decoded;
            } elseif (self::$format == self::MODE_PEM) {
                throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text');
            }
        }
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        return $decoded;
    }
    /**
     * Returns the encryption parameters used by the key
     *
     * @param string $key
     * @return array
     */
    public static function extractEncryptionAlgorithm($key)
    {
        $decoded = self::preParse($key);
        $r = ASN1::asn1map($decoded[0], ASN1\Maps\EncryptedPrivateKeyInfo::MAP);
        if (!is_array($r)) {
            throw new \RuntimeException('Unable to parse using EncryptedPrivateKeyInfo map');
        }
        if ($r['encryptionAlgorithm']['algorithm'] == 'id-PBES2') {
            $decoded = ASN1::decodeBER($r['encryptionAlgorithm']['parameters']->element);
            $r['encryptionAlgorithm']['parameters'] = ASN1::asn1map($decoded[0], ASN1\Maps\PBES2params::MAP);
            $kdf =& $r['encryptionAlgorithm']['parameters']['keyDerivationFunc'];
            switch ($kdf['algorithm']) {
                case 'id-PBKDF2':
                    $decoded = ASN1::decodeBER($kdf['parameters']->element);
                    $kdf['parameters'] = ASN1::asn1map($decoded[0], Maps\PBKDF2params::MAP);
            }
        }
        return $r['encryptionAlgorithm'];
    }
}<?php

/**
 * PuTTY Formatted Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib3\Crypt\AES;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedAlgorithmException;
/**
 * PuTTY Formatted Key Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PuTTY
{
    /**
     * Default comment
     *
     * @var string
     * @access private
     */
    private static $comment = 'phpseclib-generated-key';
    /**
     * Sets the default comment
     *
     * @access public
     * @param string $comment
     */
    public static function setComment($comment)
    {
        self::$comment = str_replace(["\r", "\n"], '', $comment);
    }
    /**
     * Generate a symmetric key for PuTTY keys
     *
     * @access public
     * @param string $password
     * @param int $length
     * @return string
     */
    private static function generateSymmetricKey($password, $length)
    {
        $symkey = '';
        $sequence = 0;
        while (strlen($symkey) < $length) {
            $temp = pack('Na*', $sequence++, $password);
            $symkey .= Hex::decode(sha1($temp));
        }
        return \Phabel\Target\Php80\Polyfill::substr($symkey, 0, $length);
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password
     * @return array
     */
    public static function load($key, $password)
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (strpos($key, 'BEGIN SSH2 PUBLIC KEY') !== false) {
            $lines = preg_split('#[\\r\\n]+#', $key);
            switch (true) {
                case $lines[0] != '---- BEGIN SSH2 PUBLIC KEY ----':
                    throw new \UnexpectedValueException('Key doesn\'t start with ---- BEGIN SSH2 PUBLIC KEY ----');
                case $lines[count($lines) - 1] != '---- END SSH2 PUBLIC KEY ----':
                    throw new \UnexpectedValueException('Key doesn\'t end with ---- END SSH2 PUBLIC KEY ----');
            }
            $lines = array_splice($lines, 1, -1);
            $lines = array_map(function ($line) {
                return rtrim($line, "\r\n");
            }, $lines);
            $data = $current = '';
            $values = [];
            $in_value = false;
            foreach ($lines as $line) {
                switch (true) {
                    case preg_match('#^(.*?): (.*)#', $line, $match):
                        $in_value = $line[strlen($line) - 1] == '\\';
                        $current = strtolower($match[1]);
                        $values[$current] = $in_value ? \Phabel\Target\Php80\Polyfill::substr($match[2], 0, -1) : $match[2];
                        break;
                    case $in_value:
                        $in_value = $line[strlen($line) - 1] == '\\';
                        $values[$current] .= $in_value ? \Phabel\Target\Php80\Polyfill::substr($line, 0, -1) : $line;
                        break;
                    default:
                        $data .= $line;
                }
            }
            $components = call_user_func([static::PUBLIC_HANDLER, 'load'], $data);
            if ($components === false) {
                throw new \UnexpectedValueException('Unable to decode public key');
            }
            $components += $values;
            $components['comment'] = str_replace(['\\\\', '\\"'], ['\\', '"'], $values['comment']);
            return $components;
        }
        $components = [];
        $key = preg_split('#\\r\\n|\\r|\\n#', trim($key));
        $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
        $components['type'] = $type;
        if (!in_array($type, static::$types)) {
            $error = count(static::$types) == 1 ? 'Only ' . static::$types[0] . ' keys are supported. ' : '';
            throw new UnsupportedAlgorithmException($error . 'This is an unsupported ' . $type . ' key');
        }
        $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
        $components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
        $publicLength = trim(preg_replace('#Public-Lines: (\\d+)#', '$1', $key[3]));
        $public = Base64::decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
        $source = Strings::packSSH2('ssss', $type, $encryption, $components['comment'], $public);
        extract(unpack('Nlength', Strings::shift($public, 4)));
        $newtype = Strings::shift($public, $length);
        if ($newtype != $type) {
            throw new \RuntimeException('The binary type does not match the human readable type field');
        }
        $components['public'] = $public;
        $privateLength = trim(preg_replace('#Private-Lines: (\\d+)#', '$1', $key[$publicLength + 4]));
        $private = Base64::decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength))));
        switch ($encryption) {
            case 'aes256-cbc':
                $symkey = self::generateSymmetricKey($password, 32);
                $crypto = new AES('cbc');
        }
        $hashkey = 'putty-private-key-file-mac-key';
        if ($encryption != 'none') {
            $hashkey .= $password;
            $crypto->setKey($symkey);
            $crypto->setIV(str_repeat("\x00", $crypto->getBlockLength() >> 3));
            $crypto->disablePadding();
            $private = $crypto->decrypt($private);
        }
        $source .= Strings::packSSH2('s', $private);
        $hash = new Hash('sha1');
        $hash->setKey(sha1($hashkey, true));
        $hmac = trim(preg_replace('#Private-MAC: (.+)#', '$1', $key[$publicLength + $privateLength + 5]));
        $hmac = Hex::decode($hmac);
        if (!hash_equals($hash->hash($source), $hmac)) {
            throw new \UnexpectedValueException('MAC validation error');
        }
        $components['private'] = $private;
        return $components;
    }
    /**
     * Wrap a private key appropriately
     *
     * @access private
     * @param string $public
     * @param string $private
     * @param string $type
     * @param string $password
     * @param array $options optional
     * @return string
     */
    protected static function wrapPrivateKey($public, $private, $type, $password, array $options = [])
    {
        $encryption = !empty($password) || is_string($password) ? 'aes256-cbc' : 'none';
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        $key = "PuTTY-User-Key-File-2: " . $type . "\r\nEncryption: ";
        $key .= $encryption;
        $key .= "\r\nComment: " . $comment . "\r\n";
        $public = Strings::packSSH2('s', $type) . $public;
        $source = Strings::packSSH2('ssss', $type, $encryption, $comment, $public);
        $public = Base64::encode($public);
        $key .= "Public-Lines: " . (strlen($public) + 63 >> 6) . "\r\n";
        $key .= chunk_split($public, 64);
        if (empty($password) && !is_string($password)) {
            $source .= Strings::packSSH2('s', $private);
            $hashkey = 'putty-private-key-file-mac-key';
        } else {
            $private .= Random::string(16 - (strlen($private) & 15));
            $source .= Strings::packSSH2('s', $private);
            $crypto = new AES('cbc');
            $crypto->setKey(self::generateSymmetricKey($password, 32));
            $crypto->setIV(str_repeat("\x00", $crypto->getBlockLength() >> 3));
            $crypto->disablePadding();
            $private = $crypto->encrypt($private);
            $hashkey = 'putty-private-key-file-mac-key' . $password;
        }
        $private = Base64::encode($private);
        $key .= 'Private-Lines: ' . (strlen($private) + 63 >> 6) . "\r\n";
        $key .= chunk_split($private, 64);
        $hash = new Hash('sha1');
        $hash->setKey(sha1($hashkey, true));
        $key .= 'Private-MAC: ' . Hex::encode($hash->hash($source)) . "\r\n";
        return $key;
    }
    /**
     * Wrap a public key appropriately
     *
     * This is basically the format described in RFC 4716 (https://tools.ietf.org/html/rfc4716)
     *
     * @access private
     * @param string $key
     * @param string $type
     * @return string
     */
    protected static function wrapPublicKey($key, $type)
    {
        $key = pack('Na*a*', strlen($type), $type, $key);
        $key = '---- BEGIN SSH2 PUBLIC KEY ----
Comment: "' . str_replace(['\\', '"'], ['\\\\', '\\"'], self::$comment) . "\"\r\n" . chunk_split(Base64::encode($key), 64) . '---- END SSH2 PUBLIC KEY ----';
        return $key;
    }
}<?php

/**
 * OpenSSH Key Handler
 *
 * PHP version 5
 *
 * Place in $HOME/.ssh/authorized_keys
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Random;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * OpenSSH Formatted RSA Key Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSH
{
    /**
     * Default comment
     *
     * @var string
     * @access private
     */
    protected static $comment = 'phpseclib-generated-key';
    /**
     * Binary key flag
     *
     * @var bool
     * @access private
     */
    protected static $binary = false;
    /**
     * Sets the default comment
     *
     * @access public
     * @param string $comment
     */
    public static function setComment($comment)
    {
        self::$comment = str_replace(["\r", "\n"], '', $comment);
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * $type can be either ssh-dss or ssh-rsa
     *
     * @access public
     * @param string $key
     * @param string $password
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        // key format is described here:
        // https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD
        if (strpos($key, 'BEGIN OPENSSH PRIVATE KEY') !== false) {
            $key = preg_replace('#(?:^-.*?-[\\r\\n]*$)|\\s#ms', '', $key);
            $key = Base64::decode($key);
            $magic = Strings::shift($key, 15);
            if ($magic != "openssh-key-v1\x00") {
                throw new \RuntimeException('Expected openssh-key-v1');
            }
            list($ciphername, $kdfname, $kdfoptions, $numKeys) = Strings::unpackSSH2('sssN', $key);
            if ($numKeys != 1) {
                // if we wanted to support multiple keys we could update PublicKeyLoader to preview what the # of keys
                // would be; it'd then call Common\Keys\OpenSSH.php::load() and get the paddedKey. it'd then pass
                // that to the appropriate key loading parser $numKey times or something
                throw new \RuntimeException('Although the OpenSSH private key format supports multiple keys phpseclib does not');
            }
            if (strlen($kdfoptions) || $kdfname != 'none' || $ciphername != 'none') {
                /*
                  OpenSSH private keys use a customized version of bcrypt. specifically, instead of encrypting
                  OrpheanBeholderScryDoubt 64 times OpenSSH's bcrypt variant encrypts
                  OxychromaticBlowfishSwatDynamite 64 times. so we can't use crypt().
                
                  bcrypt is basically Blowfish with an altered key expansion. whereas Blowfish just runs the
                  key through the key expansion bcrypt interleaves the key expansion with the salt and
                  password. this renders openssl / mcrypt unusuable. this forces us to use a pure-PHP implementation
                  of bcrypt. the problem with that is that pure-PHP is too slow to be practically useful.
                
                  in addition to encrypting a different string 64 times the OpenSSH implementation also performs bcrypt
                  from scratch $rounds times. calling crypt() 64x with bcrypt takes 0.7s. PHP is going to be naturally
                  slower. pure-PHP is 215x slower than OpenSSL for AES and pure-PHP is 43x slower for bcrypt.
                  43 * 0.7 = 30s. no one wants to wait 30s to load a private key.
                
                  another way to think about this..  according to wikipedia's article on Blowfish,
                  "Each new key requires pre-processing equivalent to encrypting about 4 kilobytes of text".
                  key expansion is done (9+64*2)*160 times. multiply that by 4 and it turns out that Blowfish,
                  OpenSSH style, is the equivalent of encrypting ~80mb of text.
                
                  more supporting evidence: sodium_compat does not implement Argon2 (another password hashing
                  algorithm) because "It's not feasible to polyfill scrypt or Argon2 into PHP and get reasonable
                  performance. Users would feel motivated to select parameters that downgrade security to avoid
                  denial of service (DoS) attacks. The only winning move is not to play"
                    -- https://github.com/paragonie/sodium_compat/blob/master/README.md
                */
                throw new \RuntimeException('Encrypted OpenSSH private keys are not supported');
                //list($salt, $rounds) = Strings::unpackSSH2('sN', $kdfoptions);
            }
            list($publicKey, $paddedKey) = Strings::unpackSSH2('ss', $key);
            list($type) = Strings::unpackSSH2('s', $publicKey);
            list($checkint1, $checkint2) = Strings::unpackSSH2('NN', $paddedKey);
            // any leftover bytes in $paddedKey are for padding? but they should be sequential bytes. eg. 1, 2, 3, etc.
            if ($checkint1 != $checkint2) {
                throw new \RuntimeException('The two checkints do not match');
            }
            self::checkType($type);
            return compact('type', 'publicKey', 'paddedKey');
        }
        $parts = explode(' ', $key, 3);
        if (!isset($parts[1])) {
            $key = base64_decode($parts[0]);
            $comment = isset($parts[1]) ? $parts[1] : false;
        } else {
            $asciiType = $parts[0];
            self::checkType($parts[0]);
            $key = base64_decode($parts[1]);
            $comment = isset($parts[2]) ? $parts[2] : false;
        }
        if ($key === false) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        list($type) = Strings::unpackSSH2('s', $key);
        self::checkType($type);
        if (isset($asciiType) && $asciiType != $type) {
            throw new \RuntimeException('Two different types of keys are claimed: ' . $asciiType . ' and ' . $type);
        }
        if (strlen($key) <= 4) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $publicKey = $key;
        return compact('type', 'publicKey', 'comment');
    }
    /**
    * Toggle between binary and printable keys
    *
    * Printable keys are what are generated by default. These are the ones that go in
    $HOME/.ssh/authorized_key.
    *
    * @access public
    * @param bool $enabled
    */
    public static function setBinaryOutput($enabled)
    {
        self::$binary = $enabled;
    }
    /**
     * Checks to see if the type is valid
     *
     * @access private
     * @param string $candidate
     */
    private static function checkType($candidate)
    {
        if (!in_array($candidate, static::$types)) {
            throw new \RuntimeException("The key type ({$candidate}) is not equal to: " . implode(',', static::$types));
        }
    }
    /**
     * Wrap a private key appropriately
     *
     * @access public
     * @param string $publicKey
     * @param string $privateKey
     * @param string $password
     * @param array $options
     * @return string
     */
    protected static function wrapPrivateKey($publicKey, $privateKey, $password, $options)
    {
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('Encrypted OpenSSH private keys are not supported');
        }
        list(, $checkint) = unpack('N', Random::string(4));
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        $paddedKey = Strings::packSSH2('NN', $checkint, $checkint) . $privateKey . Strings::packSSH2('s', $comment);
        /*
          from http://tools.ietf.org/html/rfc4253#section-6 :
        
          Note that the length of the concatenation of 'packet_length',
          'padding_length', 'payload', and 'random padding' MUST be a multiple
          of the cipher block size or 8, whichever is larger.
        */
        $paddingLength = 7 * strlen($paddedKey) % 8;
        for ($i = 1; $i <= $paddingLength; $i++) {
            $paddedKey .= chr($i);
        }
        $key = Strings::packSSH2('sssNss', 'none', 'none', '', 1, $publicKey, $paddedKey);
        $key = "openssh-key-v1\x00{$key}";
        return "-----BEGIN OPENSSH PRIVATE KEY-----\n" . chunk_split(Base64::encode($key), 70, "\n") . "-----END OPENSSH PRIVATE KEY-----\n";
    }
}<?php

/**
 * Raw Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures as arrays
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Signature;

use phpseclib3\Math\BigInteger;
/**
 * Raw Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw
{
    /**
     * Loads a signature
     *
     * @access public
     * @param array $sig
     * @return (array | bool)
     */
    public static function load($sig)
    {
        switch (true) {
            case !is_array($sig):
            case !isset($sig['r']) || !isset($sig['s']):
            case !$sig['r'] instanceof BigInteger:
            case !$sig['s'] instanceof BigInteger:
                return false;
        }
        return ['r' => $sig['r'], 's' => $sig['s']];
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s)
    {
        return compact('r', 's');
    }
}<?php

/**
 * Base Class for all block ciphers
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   BlockCipher
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

/**
 * Base Class for all block cipher classes
 *
 * @package BlockCipher
 * @author  Jim Wigginton <terrafrost@php.net>
 */
abstract class BlockCipher extends SymmetricKey
{
}<?php

/**
 * PrivateKey interface
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

/**
 * PrivateKey interface
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
interface PrivateKey
{
    /**
     *
     */
    public function sign($message);
    //public function decrypt($ciphertext);
    /**
     *
     */
    public function getPublicKey();
    /**
     *
     */
    public function toString($type, array $options = []);
    /**
     *
     */
    public function withPassword($string = false);
}<?php

/**
 * PublicKey interface
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

/**
 * PublicKey interface
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
interface PublicKey
{
    /**
     *
     */
    public function verify($message, $signature);
    //public function encrypt($plaintext);
    /**
     *
     */
    public function toString($type, array $options = []);
    /**
     *
     */
    public function getFingerprint($algorithm);
}<?php

/**
 * Base Class for all stream ciphers
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   StreamCipher
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

/**
 * Base Class for all stream cipher classes
 *
 * @package StreamCipher
 * @author  Jim Wigginton <terrafrost@php.net>
 */
abstract class StreamCipher extends SymmetricKey
{
    /**
     * Block Length of the cipher
     *
     * Stream ciphers do not have a block size
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
     * @var int
     * @access private
     */
    protected $block_size = 0;
    /**
     * Default Constructor.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @return \phpseclib3\Crypt\Common\StreamCipher
     */
    public function __construct()
    {
        parent::__construct('stream');
    }
    /**
     * Stream ciphers not use an IV
     *
     * @access public
     * @return bool
     */
    public function usesIV()
    {
        return false;
    }
}<?php

/**
 * Base Class for all \phpseclib3\Crypt\* cipher classes
 *
 * PHP version 5
 *
 * Internally for phpseclib developers:
 *  If you plan to add a new cipher class, please note following rules:
 *
 *  - The new \phpseclib3\Crypt\* cipher class should extend \phpseclib3\Crypt\Common\SymmetricKey
 *
 *  - Following methods are then required to be overridden/overloaded:
 *
 *    - encryptBlock()
 *
 *    - decryptBlock()
 *
 *    - setupKey()
 *
 *  - All other methods are optional to be overridden/overloaded
 *
 *  - Look at the source code of the current ciphers how they extend \phpseclib3\Crypt\Common\SymmetricKey
 *    and take one of them as a start up for the new cipher class.
 *
 *  - Please read all the other comments/notes/hints here also for each class var/method
 *
 * @category  Crypt
 * @package   Base
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

use phpseclib3\Crypt\Hash;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\BinaryField;
use phpseclib3\Math\PrimeField;
use phpseclib3\Exception\BadDecryptionException;
use phpseclib3\Exception\BadModeException;
use phpseclib3\Exception\InconsistentSetupException;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Exception\UnsupportedAlgorithmException;
/**
 * Base Class for all \phpseclib3\Crypt\* cipher classes
 *
 * @package Base
 * @author  Jim Wigginton <terrafrost@php.net>
 * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
 */
abstract class SymmetricKey
{
    /**
     * Encrypt / decrypt using the Counter mode.
     *
     * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_CTR = -1;
    /**
     * Encrypt / decrypt using the Electronic Code Book mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_ECB = 1;
    /**
     * Encrypt / decrypt using the Code Book Chaining mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_CBC = 2;
    /**
     * Encrypt / decrypt using the Cipher Feedback mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_CFB = 3;
    /**
     * Encrypt / decrypt using the Cipher Feedback mode (8bit)
     *
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_CFB8 = 38;
    /**
     * Encrypt / decrypt using the Output Feedback mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_OFB = 4;
    /**
     * Encrypt / decrypt using Galois/Counter mode.
     *
     * @link https://en.wikipedia.org/wiki/Galois/Counter_Mode
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_GCM = 5;
    /**
     * Encrypt / decrypt using streaming mode.
     *
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_STREAM = 6;
    /**
     * Mode Map
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const MODE_MAP = ['ctr' => self::MODE_CTR, 'ecb' => self::MODE_ECB, 'cbc' => self::MODE_CBC, 'cfb' => self::MODE_CFB, 'cfb8' => self::MODE_CFB8, 'ofb' => self::MODE_OFB, 'gcm' => self::MODE_GCM, 'stream' => self::MODE_STREAM];
    /**
     * Base value for the internal implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_INTERNAL = 1;
    /**
     * Base value for the eval() implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_EVAL = 2;
    /**
     * Base value for the mcrypt implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_MCRYPT = 3;
    /**
     * Base value for the openssl implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_OPENSSL = 4;
    /**
     * Base value for the libsodium implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_LIBSODIUM = 5;
    /**
     * Base value for the openssl / gcm implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_OPENSSL_GCM = 6;
    /**
     * Engine Reverse Map
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::getEngine()
     */
    const ENGINE_MAP = [self::ENGINE_INTERNAL => 'PHP', self::ENGINE_EVAL => 'Eval', self::ENGINE_MCRYPT => 'mcrypt', self::ENGINE_OPENSSL => 'OpenSSL', self::ENGINE_LIBSODIUM => 'libsodium', self::ENGINE_OPENSSL_GCM => 'OpenSSL (GCM)'];
    /**
     * The Encryption Mode
     *
     * @see self::__construct()
     * @var int
     * @access private
     */
    protected $mode;
    /**
     * The Block Length of the block cipher
     *
     * @var int
     * @access private
     */
    protected $block_size = 16;
    /**
     * The Key
     *
     * @see self::setKey()
     * @var string
     * @access private
     */
    protected $key = false;
    /**
     * The Initialization Vector
     *
     * @see self::setIV()
     * @var string
     * @access private
     */
    protected $iv = false;
    /**
     * A "sliding" Initialization Vector
     *
     * @see self::enableContinuousBuffer()
     * @see self::clearBuffers()
     * @var string
     * @access private
     */
    protected $encryptIV;
    /**
     * A "sliding" Initialization Vector
     *
     * @see self::enableContinuousBuffer()
     * @see self::clearBuffers()
     * @var string
     * @access private
     */
    protected $decryptIV;
    /**
     * Continuous Buffer status
     *
     * @see self::enableContinuousBuffer()
     * @var bool
     * @access private
     */
    protected $continuousBuffer = false;
    /**
     * Encryption buffer for CTR, OFB and CFB modes
     *
     * @see self::encrypt()
     * @see self::clearBuffers()
     * @var array
     * @access private
     */
    protected $enbuffer;
    /**
     * Decryption buffer for CTR, OFB and CFB modes
     *
     * @see self::decrypt()
     * @see self::clearBuffers()
     * @var array
     * @access private
     */
    protected $debuffer;
    /**
     * mcrypt resource for encryption
     *
     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
     *
     * @see self::encrypt()
     * @var resource
     * @access private
     */
    private $enmcrypt;
    /**
     * mcrypt resource for decryption
     *
     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
     *
     * @see self::decrypt()
     * @var resource
     * @access private
     */
    private $demcrypt;
    /**
     * Does the enmcrypt resource need to be (re)initialized?
     *
     * @see \phpseclib3\Crypt\Twofish::setKey()
     * @see \phpseclib3\Crypt\Twofish::setIV()
     * @var bool
     * @access private
     */
    private $enchanged = true;
    /**
     * Does the demcrypt resource need to be (re)initialized?
     *
     * @see \phpseclib3\Crypt\Twofish::setKey()
     * @see \phpseclib3\Crypt\Twofish::setIV()
     * @var bool
     * @access private
     */
    private $dechanged = true;
    /**
     * mcrypt resource for CFB mode
     *
     * mcrypt's CFB mode, in (and only in) buffered context,
     * is broken, so phpseclib implements the CFB mode by it self,
     * even when the mcrypt php extension is available.
     *
     * In order to do the CFB-mode work (fast) phpseclib
     * use a separate ECB-mode mcrypt resource.
     *
     * @link http://phpseclib.sourceforge.net/cfb-demo.phps
     * @see self::encrypt()
     * @see self::decrypt()
     * @see self::setupMcrypt()
     * @var resource
     * @access private
     */
    private $ecb;
    /**
     * Optimizing value while CFB-encrypting
     *
     * Only relevant if $continuousBuffer enabled
     * and $engine == self::ENGINE_MCRYPT
     *
     * It's faster to re-init $enmcrypt if
     * $buffer bytes > $cfb_init_len than
     * using the $ecb resource furthermore.
     *
     * This value depends of the chosen cipher
     * and the time it would be needed for it's
     * initialization [by mcrypt_generic_init()]
     * which, typically, depends on the complexity
     * on its internaly Key-expanding algorithm.
     *
     * @see self::encrypt()
     * @var int
     * @access private
     */
    protected $cfb_init_len = 600;
    /**
     * Does internal cipher state need to be (re)initialized?
     *
     * @see self::setKey()
     * @see self::setIV()
     * @see self::disableContinuousBuffer()
     * @var bool
     * @access private
     */
    protected $changed = true;
    /**
     * Does Eval engie need to be (re)initialized?
     *
     * @see self::setup()
     * @var bool
     * @access private
     */
    protected $nonIVChanged = true;
    /**
     * Padding status
     *
     * @see self::enablePadding()
     * @var bool
     * @access private
     */
    private $padding = true;
    /**
     * Is the mode one that is paddable?
     *
     * @see self::__construct()
     * @var bool
     * @access private
     */
    private $paddable = false;
    /**
     * Holds which crypt engine internaly should be use,
     * which will be determined automatically on __construct()
     *
     * Currently available $engines are:
     * - self::ENGINE_LIBSODIUM   (very fast, php-extension: libsodium, extension_loaded('libsodium') required)
     * - self::ENGINE_OPENSSL_GCM (very fast, php-extension: openssl, extension_loaded('openssl') required)
     * - self::ENGINE_OPENSSL     (very fast, php-extension: openssl, extension_loaded('openssl') required)
     * - self::ENGINE_MCRYPT      (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
     * - self::ENGINE_EVAL        (medium, pure php-engine, no php-extension required)
     * - self::ENGINE_INTERNAL    (slower, pure php-engine, no php-extension required)
     *
     * @see self::setEngine()
     * @see self::encrypt()
     * @see self::decrypt()
     * @var int
     * @access private
     */
    protected $engine;
    /**
     * Holds the preferred crypt engine
     *
     * @see self::setEngine()
     * @see self::setPreferredEngine()
     * @var int
     * @access private
     */
    private $preferredEngine;
    /**
     * The mcrypt specific name of the cipher
     *
     * Only used if $engine == self::ENGINE_MCRYPT
     *
     * @link http://www.php.net/mcrypt_module_open
     * @link http://www.php.net/mcrypt_list_algorithms
     * @see self::setupMcrypt()
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt;
    /**
     * The openssl specific name of the cipher
     *
     * Only used if $engine == self::ENGINE_OPENSSL
     *
     * @link http://www.php.net/openssl-get-cipher-methods
     * @var string
     * @access private
     */
    protected $cipher_name_openssl;
    /**
     * The openssl specific name of the cipher in ECB mode
     *
     * If OpenSSL does not support the mode we're trying to use (CTR)
     * it can still be emulated with ECB mode.
     *
     * @link http://www.php.net/openssl-get-cipher-methods
     * @var string
     * @access private
     */
    protected $cipher_name_openssl_ecb;
    /**
     * The default salt used by setPassword()
     *
     * @see self::setPassword()
     * @var string
     * @access private
     */
    private $password_default_salt = 'phpseclib/salt';
    /**
     * The name of the performance-optimized callback function
     *
     * Used by encrypt() / decrypt()
     * only if $engine == self::ENGINE_INTERNAL
     *
     * @see self::encrypt()
     * @see self::decrypt()
     * @see self::setupInlineCrypt()
     * @var Callback
     * @access private
     */
    protected $inline_crypt;
    /**
     * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
     *
     * @see self::openssl_ctr_process()
     * @var bool
     * @access private
     */
    private $openssl_emulate_ctr = false;
    /**
     * Don't truncate / null pad key
     *
     * @see self::clearBuffers()
     * @var bool
     * @access private
     */
    private $skip_key_adjustment = false;
    /**
     * Has the key length explicitly been set or should it be derived from the key, itself?
     *
     * @see self::setKeyLength()
     * @var bool
     * @access private
     */
    protected $explicit_key_length = false;
    /**
     * Hash subkey for GHASH
     *
     * @see self::setupGCM()
     * @see self::ghash()
     * @var BinaryField\Integer
     * @access private
     */
    private $h;
    /**
     * Additional authenticated data
     *
     * @var string
     * @access private
     */
    protected $aad = '';
    /**
     * Authentication Tag produced after a round of encryption
     *
     * @var string
     * @access private
     */
    protected $newtag = false;
    /**
     * Authentication Tag to be verified during decryption
     *
     * @var string
     * @access private
     */
    protected $oldtag = false;
    /**
     * GCM Binary Field
     *
     * @see self::__construct()
     * @see self::ghash()
     * @var BinaryField
     * @access private
     */
    private static $gcmField;
    /**
     * Poly1305 Prime Field
     *
     * @see self::enablePoly1305()
     * @see self::poly1305()
     * @var PrimeField
     * @access private
     */
    private static $poly1305Field;
    /**
     * Poly1305 Key
     *
     * @see self::setPoly1305Key()
     * @see self::poly1305()
     * @var string
     * @access private
     */
    protected $poly1305Key;
    /**
     * Poly1305 Flag
     *
     * @see self::setPoly1305Key()
     * @see self::enablePoly1305()
     * @var boolean
     * @access private
     */
    protected $usePoly1305 = false;
    /**
     * The Original Initialization Vector
     *
     * GCM uses the nonce to build the IV but we want to be able to distinguish between nonce-derived
     * IV's and user-set IV's
     *
     * @see self::setIV()
     * @var string
     * @access private
     */
    private $origIV = false;
    /**
     * Nonce
     *
     * Only used with GCM. We could re-use setIV() but nonce's can be of a different length and
     * toggling between GCM and other modes could be more complicated if we re-used setIV()
     *
     * @see self::setNonce()
     * @var string
     * @access private
     */
    protected $nonce = false;
    /**
     * Default Constructor.
     *
     * $mode could be:
     *
     * - ecb
     *
     * - cbc
     *
     * - ctr
     *
     * - cfb
     *
     * - cfb8
     *
     * - ofb
     *
     * - gcm
     *
     * @param string $mode
     * @access public
     * @throws BadModeException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        $mode = strtolower($mode);
        // necessary because of 5.6 compatibility; we can't do isset(self::MODE_MAP[$mode]) in 5.6
        $map = self::MODE_MAP;
        if (!isset($map[$mode])) {
            throw new BadModeException('No valid mode has been specified');
        }
        $mode = self::MODE_MAP[$mode];
        // $mode dependent settings
        switch ($mode) {
            case self::MODE_ECB:
            case self::MODE_CBC:
                $this->paddable = true;
                break;
            case self::MODE_CTR:
            case self::MODE_CFB:
            case self::MODE_CFB8:
            case self::MODE_OFB:
            case self::MODE_STREAM:
                $this->paddable = false;
                break;
            case self::MODE_GCM:
                if ($this->block_size != 16) {
                    throw new BadModeException('GCM is only valid for block ciphers with a block size of 128 bits');
                }
                if (!isset(self::$gcmField)) {
                    self::$gcmField = new BinaryField(128, 7, 2, 1, 0);
                }
                $this->paddable = false;
                break;
            default:
                throw new BadModeException('No valid mode has been specified');
        }
        $this->mode = $mode;
    }
    /**
     * Sets the initialization vector.
     *
     * setIV() is not required when ecb or gcm modes are being used.
     *
     * {@internal Can be overwritten by a sub class, but does not have to be}
     *
     * @access public
     * @param string $iv
     * @throws \LengthException if the IV length isn't equal to the block size
     * @throws \BadMethodCallException if an IV is provided when one shouldn't be
     */
    public function setIV($iv)
    {
        if ($this->mode == self::MODE_ECB) {
            throw new \BadMethodCallException('This mode does not require an IV.');
        }
        if ($this->mode == self::MODE_GCM) {
            throw new \BadMethodCallException('Use setNonce instead');
        }
        if (!$this->usesIV()) {
            throw new \BadMethodCallException('This algorithm does not use an IV.');
        }
        if (strlen($iv) != $this->block_size) {
            throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required');
        }
        $this->iv = $this->origIV = $iv;
        $this->changed = true;
    }
    /**
     * Enables Poly1305 mode.
     *
     * Once enabled Poly1305 cannot be disabled.
     *
     * @access public
     * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode
     */
    public function enablePoly1305()
    {
        if ($this->mode == self::MODE_GCM) {
            throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode');
        }
        $this->usePoly1305 = true;
    }
    /**
    * Enables Poly1305 mode.
    *
    * Once enabled Poly1305 cannot be disabled. If $key is not passed then an attempt to call createPoly1305Key
    will be made.
    *
    * @access public
    * @param string $key optional
    * @throws \LengthException if the key isn't long enough
    * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode
    */
    public function setPoly1305Key($key = null)
    {
        if ($this->mode == self::MODE_GCM) {
            throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode');
        }
        if (!is_string($key) || strlen($key) != 32) {
            throw new \LengthException('The Poly1305 key must be 32 bytes long (256 bits)');
        }
        if (!isset(self::$poly1305Field)) {
            // 2^130-5
            self::$poly1305Field = new PrimeField(new BigInteger('3fffffffffffffffffffffffffffffffb', 16));
        }
        $this->poly1305Key = $key;
        $this->usePoly1305 = true;
    }
    /**
     * Sets the nonce.
     *
     * setNonce() is only required when gcm is used
     *
     * @access public
     * @param string $nonce
     * @throws \BadMethodCallException if an nonce is provided when one shouldn't be
     */
    public function setNonce($nonce)
    {
        if ($this->mode != self::MODE_GCM) {
            throw new \BadMethodCallException('Nonces are only used in GCM mode.');
        }
        $this->nonce = $nonce;
        $this->setEngine();
    }
    /**
     * Sets additional authenticated data
     *
     * setAAD() is only used by gcm or in poly1305 mode
     *
     * @access public
     * @param string $aad
     * @throws \BadMethodCallException if mode isn't GCM or if poly1305 isn't being utilized
     */
    public function setAAD($aad)
    {
        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
            throw new \BadMethodCallException('Additional authenticated data is only utilized in GCM mode or with Poly1305');
        }
        $this->aad = $aad;
    }
    /**
     * Returns whether or not the algorithm uses an IV
     *
     * @access public
     * @return bool
     */
    public function usesIV()
    {
        return $this->mode != self::MODE_GCM && $this->mode != self::MODE_ECB;
    }
    /**
     * Returns whether or not the algorithm uses a nonce
     *
     * @access public
     * @return bool
     */
    public function usesNonce()
    {
        return $this->mode == self::MODE_GCM;
    }
    /**
     * Returns the current key length in bits
     *
     * @access public
     * @return int
     */
    public function getKeyLength()
    {
        return $this->key_length << 3;
    }
    /**
     * Returns the current block length in bits
     *
     * @access public
     * @return int
     */
    public function getBlockLength()
    {
        return $this->block_size << 3;
    }
    /**
     * Returns the current block length in bytes
     *
     * @access public
     * @return int
     */
    public function getBlockLengthInBytes()
    {
        return $this->block_size;
    }
    /**
     * Sets the key length.
     *
     * Keys with explicitly set lengths need to be treated accordingly
     *
     * @access public
     * @param int $length
     */
    public function setKeyLength($length)
    {
        $this->explicit_key_length = $length >> 3;
        if (is_string($this->key) && strlen($this->key) != $this->explicit_key_length) {
            $this->key = false;
            throw new InconsistentSetupException('Key has already been set and is not ' . $this->explicit_key_length . ' bytes long');
        }
    }
    /**
    * Sets the key.
    *
    * The min/max length(s) of the key depends on the cipher which is used.
    If the key not fits the length(s) of the cipher it will paded with null bytes
    up to the closest valid key length.  If the key is more than max length,
    we trim the excess bits.
    *
    * If the key is not explicitly set, it'll be assumed to be all null bytes.
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @access public
    * @param string $key
    */
    public function setKey($key)
    {
        if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
            throw new InconsistentSetupException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
        }
        $this->key = $key;
        $this->key_length = strlen($key);
        $this->setEngine();
    }
    /**
    * Sets the password.
    *
    * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
    {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
    $hash, $salt, $count, $dkLen
    *
    * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see Crypt/Hash.php
    * @param string $password
    * @param string $method
    * @param string[] ...$func_args
    * @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
    * @return bool
    * @access public
    */
    public function setPassword($password, $method = 'pbkdf2', ...$func_args)
    {
        $key = '';
        $method = strtolower($method);
        switch ($method) {
            case 'pkcs12':
            // from https://tools.ietf.org/html/rfc7292#appendix-B.2
            case 'pbkdf1':
            case 'pbkdf2':
                // Hash function
                $hash = isset($func_args[0]) ? strtolower($func_args[0]) : 'sha1';
                $hashObj = new Hash();
                $hashObj->setHash($hash);
                // WPA and WPA2 use the SSID as the salt
                $salt = isset($func_args[1]) ? $func_args[1] : $this->password_default_salt;
                // RFC2898#section-4.2 uses 1,000 iterations by default
                // WPA and WPA2 use 4,096.
                $count = isset($func_args[2]) ? $func_args[2] : 1000;
                // Keylength
                if (isset($func_args[3])) {
                    if ($func_args[3] <= 0) {
                        throw new \LengthException('Derived key length cannot be longer 0 or less');
                    }
                    $dkLen = $func_args[3];
                } else {
                    $key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length;
                    $dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length;
                }
                switch (true) {
                    case $method == 'pkcs12':
                        /*
                        In this specification, however, all passwords are created from
                        BMPStrings with a NULL terminator.  This means that each character in
                        the original BMPString is encoded in 2 bytes in big-endian format
                        (most-significant byte first).  There are no Unicode byte order
                        marks.  The 2 bytes produced from the last character in the BMPString
                        are followed by 2 additional bytes with the value 0x00.
                        
                        -- https://tools.ietf.org/html/rfc7292#appendix-B.1
                        */
                        $password = "\x00" . chunk_split($password, 1, "\x00") . "\x00";
                        /*
                        This standard specifies 3 different values for the ID byte mentioned
                        above:
                        
                        1.  If ID=1, then the pseudorandom bits being produced are to be used
                            as key material for performing encryption or decryption.
                        
                        2.  If ID=2, then the pseudorandom bits being produced are to be used
                            as an IV (Initial Value) for encryption or decryption.
                        
                        3.  If ID=3, then the pseudorandom bits being produced are to be used
                            as an integrity key for MACing.
                        */
                        // Construct a string, D (the "diversifier"), by concatenating v/8
                        // copies of ID.
                        $blockLength = $hashObj->getBlockLengthInBytes();
                        $d1 = str_repeat(chr(1), $blockLength);
                        $d2 = str_repeat(chr(2), $blockLength);
                        $s = '';
                        if (strlen($salt)) {
                            while (strlen($s) < $blockLength) {
                                $s .= $salt;
                            }
                        }
                        $s = \Phabel\Target\Php80\Polyfill::substr($s, 0, $blockLength);
                        $p = '';
                        if (strlen($password)) {
                            while (strlen($p) < $blockLength) {
                                $p .= $password;
                            }
                        }
                        $p = \Phabel\Target\Php80\Polyfill::substr($p, 0, $blockLength);
                        $i = $s . $p;
                        $this->setKey(self::pkcs12helper($dkLen, $hashObj, $i, $d1, $count));
                        if ($this->usesIV()) {
                            $this->setIV(self::pkcs12helper($this->block_size, $hashObj, $i, $d2, $count));
                        }
                        return true;
                    case $method == 'pbkdf1':
                        if ($dkLen > $hashObj->getLengthInBytes()) {
                            throw new \LengthException('Derived key length cannot be longer than the hash length');
                        }
                        $t = $password . $salt;
                        for ($i = 0; $i < $count; ++$i) {
                            $t = $hashObj->hash($t);
                        }
                        $key = \Phabel\Target\Php80\Polyfill::substr($t, 0, $dkLen);
                        $this->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $dkLen >> 1));
                        if ($this->usesIV()) {
                            $this->setIV(\Phabel\Target\Php80\Polyfill::substr($key, $dkLen >> 1));
                        }
                        return true;
                    case !in_array($hash, hash_algos()):
                        $i = 1;
                        $hashObj->setKey($password);
                        while (strlen($key) < $dkLen) {
                            $f = $u = $hashObj->hash($salt . pack('N', $i++));
                            for ($j = 2; $j <= $count; ++$j) {
                                $u = $hashObj->hash($u);
                                $f ^= $u;
                            }
                            $key .= $f;
                        }
                        $key = \Phabel\Target\Php80\Polyfill::substr($key, 0, $dkLen);
                        break;
                    default:
                        $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
                }
                break;
            default:
                throw new UnsupportedAlgorithmException($method . ' is not a supported password hashing method');
        }
        $this->setKey($key);
        return true;
    }
    /**
     * PKCS#12 KDF Helper Function
     *
     * As discussed here:
     *
     * {@link https://tools.ietf.org/html/rfc7292#appendix-B}
     *
     * @see self::setPassword()
     * @access private
     * @param int $n
     * @param \phpseclib3\Crypt\Hash $hashObj
     * @param string $i
     * @param string $d
     * @param int $count
     * @return string $a
     */
    private static function pkcs12helper($n, $hashObj, $i, $d, $count)
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        $blockLength = $hashObj->getBlockLength() >> 3;
        $c = ceil($n / $hashObj->getLengthInBytes());
        $a = '';
        for ($j = 1; $j <= $c; $j++) {
            $ai = $d . $i;
            for ($k = 0; $k < $count; $k++) {
                $ai = $hashObj->hash($ai);
            }
            $b = '';
            while (strlen($b) < $blockLength) {
                $b .= $ai;
            }
            $b = \Phabel\Target\Php80\Polyfill::substr($b, 0, $blockLength);
            $b = new BigInteger($b, 256);
            $newi = '';
            for ($k = 0; $k < strlen($i); $k += $blockLength) {
                $temp = \Phabel\Target\Php80\Polyfill::substr($i, $k, $blockLength);
                $temp = new BigInteger($temp, 256);
                $temp->setPrecision($blockLength << 3);
                $temp = $temp->add($b);
                $temp = $temp->add($one);
                $newi .= $temp->toBytes(false);
            }
            $i = $newi;
            $a .= $ai;
        }
        return \Phabel\Target\Php80\Polyfill::substr($a, 0, $n);
    }
    /**
    * Encrypts a message.
    *
    * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
    implementations may or may not pad in the same manner.  Other common approaches to padding and the reasons why it's
    necessary are discussed in the following
    URL:
    *
    * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
    *
    * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
    strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
    length.
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::decrypt()
    * @access public
    * @param string $plaintext
    * @return string $ciphertext
    */
    public function encrypt($plaintext)
    {
        if ($this->paddable) {
            $plaintext = $this->pad($plaintext);
        }
        $this->setup();
        if ($this->mode == self::MODE_GCM) {
            $oldIV = $this->iv;
            Strings::increment_str($this->iv);
            $cipher = new static('ctr');
            $cipher->setKey($this->key);
            $cipher->setIV($this->iv);
            $ciphertext = $cipher->encrypt($plaintext);
            $s = $this->ghash(self::nullPad128($this->aad) . self::nullPad128($ciphertext) . self::len64($this->aad) . self::len64($ciphertext));
            $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV;
            $this->newtag = $cipher->encrypt($s);
            return $ciphertext;
        }
        if (isset($this->poly1305Key)) {
            $cipher = clone $this;
            unset($cipher->poly1305Key);
            $this->usePoly1305 = false;
            $ciphertext = $cipher->encrypt($plaintext);
            $this->newtag = $this->poly1305($ciphertext);
            return $ciphertext;
        }
        if ($this->engine === self::ENGINE_OPENSSL) {
            switch ($this->mode) {
                case self::MODE_STREAM:
                    return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                case self::MODE_ECB:
                    return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                case self::MODE_CBC:
                    $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV);
                    if ($this->continuousBuffer) {
                        $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($result, -$this->block_size);
                    }
                    return $result;
                case self::MODE_CTR:
                    return $this->openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
                case self::MODE_CFB:
                    // cfb loosely routines inspired by openssl's:
                    // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
                    $ciphertext = '';
                    if ($this->continuousBuffer) {
                        $iv =& $this->encryptIV;
                        $pos =& $this->enbuffer['pos'];
                    } else {
                        $iv = $this->encryptIV;
                        $pos = 0;
                    }
                    $len = strlen($plaintext);
                    $i = 0;
                    if ($pos) {
                        $orig_pos = $pos;
                        $max = $this->block_size - $pos;
                        if ($len >= $max) {
                            $i = $max;
                            $len -= $max;
                            $pos = 0;
                        } else {
                            $i = $len;
                            $pos += $len;
                            $len = 0;
                        }
                        // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
                        $ciphertext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $plaintext;
                        $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $ciphertext, $orig_pos, $i);
                        $plaintext = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i);
                    }
                    $overflow = $len % $this->block_size;
                    if ($overflow) {
                        $ciphertext .= openssl_encrypt(\Phabel\Target\Php80\Polyfill::substr($plaintext, 0, -$overflow) . str_repeat("\x00", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        $iv = Strings::pop($ciphertext, $this->block_size);
                        $size = $len - $overflow;
                        $block = $iv ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, -$overflow);
                        $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $block, 0, $overflow);
                        $ciphertext .= $block;
                        $pos = $overflow;
                    } elseif ($len) {
                        $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        $iv = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$this->block_size);
                    }
                    return $ciphertext;
                case self::MODE_CFB8:
                    $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV);
                    if ($this->continuousBuffer) {
                        if (($len = strlen($ciphertext)) >= $this->block_size) {
                            $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$this->block_size);
                        } else {
                            $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($this->encryptIV, $len - $this->block_size) . \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                        }
                    }
                    return $ciphertext;
                case self::MODE_OFB:
                    return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
            }
        }
        if ($this->engine === self::ENGINE_MCRYPT) {
            set_error_handler(function () {
            });
            if ($this->enchanged) {
                mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV));
                $this->enchanged = false;
            }
            // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
            // using mcrypt's default handing of CFB the above would output two different things.  using phpseclib's
            // rewritten CFB implementation the above outputs the same thing twice.
            if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
                $block_size = $this->block_size;
                $iv =& $this->encryptIV;
                $pos =& $this->enbuffer['pos'];
                $len = strlen($plaintext);
                $ciphertext = '';
                $i = 0;
                if ($pos) {
                    $orig_pos = $pos;
                    $max = $block_size - $pos;
                    if ($len >= $max) {
                        $i = $max;
                        $len -= $max;
                        $pos = 0;
                    } else {
                        $i = $len;
                        $pos += $len;
                        $len = 0;
                    }
                    $ciphertext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $plaintext;
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $ciphertext, $orig_pos, $i);
                    $this->enbuffer['enmcrypt_init'] = true;
                }
                if ($len >= $block_size) {
                    if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
                        if ($this->enbuffer['enmcrypt_init'] === true) {
                            mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
                            $this->enbuffer['enmcrypt_init'] = false;
                        }
                        $ciphertext .= mcrypt_generic($this->enmcrypt, \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $len - $len % $block_size));
                        $iv = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$block_size);
                        $len %= $block_size;
                    } else {
                        while ($len >= $block_size) {
                            $iv = mcrypt_generic($this->ecb, $iv) ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                            $ciphertext .= $iv;
                            $len -= $block_size;
                            $i += $block_size;
                        }
                    }
                }
                if ($len) {
                    $iv = mcrypt_generic($this->ecb, $iv);
                    $block = $iv ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, -$len);
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $block, 0, $len);
                    $ciphertext .= $block;
                    $pos = $len;
                }
                restore_error_handler();
                return $ciphertext;
            }
            $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
            if (!$this->continuousBuffer) {
                mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV));
            }
            restore_error_handler();
            return $ciphertext;
        }
        if ($this->engine === self::ENGINE_EVAL) {
            $inline = $this->inline_crypt;
            return $inline('encrypt', $plaintext);
        }
        $buffer =& $this->enbuffer;
        $block_size = $this->block_size;
        $ciphertext = '';
        switch ($this->mode) {
            case self::MODE_ECB:
                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                    $ciphertext .= $this->encryptBlock(\Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size));
                }
                break;
            case self::MODE_CBC:
                $xor = $this->encryptIV;
                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                    $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                    $block = $this->encryptBlock($block ^ $xor);
                    $xor = $block;
                    $ciphertext .= $block;
                }
                if ($this->continuousBuffer) {
                    $this->encryptIV = $xor;
                }
                break;
            case self::MODE_CTR:
                $xor = $this->encryptIV;
                if (strlen($buffer['ciphertext'])) {
                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                        if (strlen($block) > strlen($buffer['ciphertext'])) {
                            $buffer['ciphertext'] .= $this->encryptBlock($xor);
                        }
                        Strings::increment_str($xor);
                        $key = Strings::shift($buffer['ciphertext'], $block_size);
                        $ciphertext .= $block ^ $key;
                    }
                } else {
                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                        $key = $this->encryptBlock($xor);
                        Strings::increment_str($xor);
                        $ciphertext .= $block ^ $key;
                    }
                }
                if ($this->continuousBuffer) {
                    $this->encryptIV = $xor;
                    if ($start = strlen($plaintext) % $block_size) {
                        $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['ciphertext'];
                    }
                }
                break;
            case self::MODE_CFB:
                // cfb loosely routines inspired by openssl's:
                // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
                if ($this->continuousBuffer) {
                    $iv =& $this->encryptIV;
                    $pos =& $buffer['pos'];
                } else {
                    $iv = $this->encryptIV;
                    $pos = 0;
                }
                $len = strlen($plaintext);
                $i = 0;
                if ($pos) {
                    $orig_pos = $pos;
                    $max = $block_size - $pos;
                    if ($len >= $max) {
                        $i = $max;
                        $len -= $max;
                        $pos = 0;
                    } else {
                        $i = $len;
                        $pos += $len;
                        $len = 0;
                    }
                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
                    $ciphertext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $plaintext;
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $ciphertext, $orig_pos, $i);
                }
                while ($len >= $block_size) {
                    $iv = $this->encryptBlock($iv) ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                    $ciphertext .= $iv;
                    $len -= $block_size;
                    $i += $block_size;
                }
                if ($len) {
                    $iv = $this->encryptBlock($iv);
                    $block = $iv ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, $i);
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $block, 0, $len);
                    $ciphertext .= $block;
                    $pos = $len;
                }
                break;
            case self::MODE_CFB8:
                $ciphertext = '';
                $len = strlen($plaintext);
                $iv = $this->encryptIV;
                for ($i = 0; $i < $len; ++$i) {
                    $ciphertext .= $c = $plaintext[$i] ^ $this->encryptBlock($iv);
                    $iv = \Phabel\Target\Php80\Polyfill::substr($iv, 1) . $c;
                }
                if ($this->continuousBuffer) {
                    if ($len >= $block_size) {
                        $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$block_size);
                    } else {
                        $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($this->encryptIV, $len - $block_size) . \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                    }
                }
                break;
            case self::MODE_OFB:
                $xor = $this->encryptIV;
                if (strlen($buffer['xor'])) {
                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                        if (strlen($block) > strlen($buffer['xor'])) {
                            $xor = $this->encryptBlock($xor);
                            $buffer['xor'] .= $xor;
                        }
                        $key = Strings::shift($buffer['xor'], $block_size);
                        $ciphertext .= $block ^ $key;
                    }
                } else {
                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                        $xor = $this->encryptBlock($xor);
                        $ciphertext .= \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size) ^ $xor;
                    }
                    $key = $xor;
                }
                if ($this->continuousBuffer) {
                    $this->encryptIV = $xor;
                    if ($start = strlen($plaintext) % $block_size) {
                        $buffer['xor'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['xor'];
                    }
                }
                break;
            case self::MODE_STREAM:
                $ciphertext = $this->encryptBlock($plaintext);
                break;
        }
        return $ciphertext;
    }
    /**
    * Decrypts a message.
    *
    * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
    it is.
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::encrypt()
    * @access public
    * @param string $ciphertext
    * @return string $plaintext
    * @throws \LengthException if we're inside a block cipher and the ciphertext length is not a multiple of the block size
    */
    public function decrypt($ciphertext)
    {
        if ($this->paddable && strlen($ciphertext) % $this->block_size) {
            throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')');
        }
        $this->setup();
        if ($this->mode == self::MODE_GCM || isset($this->poly1305Key)) {
            if ($this->oldtag === false) {
                throw new InsufficientSetupException('Authentication Tag has not been set');
            }
            if (isset($this->poly1305Key)) {
                $newtag = $this->poly1305($ciphertext);
            } else {
                $oldIV = $this->iv;
                Strings::increment_str($this->iv);
                $cipher = new static('ctr');
                $cipher->setKey($this->key);
                $cipher->setIV($this->iv);
                $plaintext = $cipher->decrypt($ciphertext);
                $s = $this->ghash(self::nullPad128($this->aad) . self::nullPad128($ciphertext) . self::len64($this->aad) . self::len64($ciphertext));
                $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV;
                $newtag = $cipher->encrypt($s);
            }
            if ($this->oldtag != \Phabel\Target\Php80\Polyfill::substr($newtag, 0, strlen($newtag))) {
                $cipher = clone $this;
                unset($cipher->poly1305Key);
                $this->usePoly1305 = false;
                $plaintext = $cipher->decrypt($ciphertext);
                $this->oldtag = false;
                throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
            }
            $this->oldtag = false;
            return $plaintext;
        }
        if ($this->engine === self::ENGINE_OPENSSL) {
            switch ($this->mode) {
                case self::MODE_STREAM:
                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                    break;
                case self::MODE_ECB:
                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                    break;
                case self::MODE_CBC:
                    $offset = $this->block_size;
                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV);
                    if ($this->continuousBuffer) {
                        $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$offset, $this->block_size);
                    }
                    break;
                case self::MODE_CTR:
                    $plaintext = $this->openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
                    break;
                case self::MODE_CFB:
                    // cfb loosely routines inspired by openssl's:
                    // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
                    $plaintext = '';
                    if ($this->continuousBuffer) {
                        $iv =& $this->decryptIV;
                        $pos =& $this->buffer['pos'];
                    } else {
                        $iv = $this->decryptIV;
                        $pos = 0;
                    }
                    $len = strlen($ciphertext);
                    $i = 0;
                    if ($pos) {
                        $orig_pos = $pos;
                        $max = $this->block_size - $pos;
                        if ($len >= $max) {
                            $i = $max;
                            $len -= $max;
                            $pos = 0;
                        } else {
                            $i = $len;
                            $pos += $len;
                            $len = 0;
                        }
                        // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
                        $plaintext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $ciphertext;
                        $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, $i), $orig_pos, $i);
                        $ciphertext = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i);
                    }
                    $overflow = $len % $this->block_size;
                    if ($overflow) {
                        $plaintext .= openssl_decrypt(\Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        if ($len - $overflow) {
                            $iv = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$overflow - $this->block_size, -$overflow);
                        }
                        $iv = openssl_encrypt(str_repeat("\x00", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        $plaintext .= $iv ^ \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$overflow);
                        $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$overflow), 0, $overflow);
                        $pos = $overflow;
                    } elseif ($len) {
                        $plaintext .= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        $iv = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$this->block_size);
                    }
                    break;
                case self::MODE_CFB8:
                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV);
                    if ($this->continuousBuffer) {
                        if (($len = strlen($ciphertext)) >= $this->block_size) {
                            $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$this->block_size);
                        } else {
                            $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($this->decryptIV, $len - $this->block_size) . \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                        }
                    }
                    break;
                case self::MODE_OFB:
                    $plaintext = $this->openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
            }
            return $this->paddable ? $this->unpad($plaintext) : $plaintext;
        }
        if ($this->engine === self::ENGINE_MCRYPT) {
            set_error_handler(function () {
            });
            $block_size = $this->block_size;
            if ($this->dechanged) {
                mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV));
                $this->dechanged = false;
            }
            if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
                $iv =& $this->decryptIV;
                $pos =& $this->debuffer['pos'];
                $len = strlen($ciphertext);
                $plaintext = '';
                $i = 0;
                if ($pos) {
                    $orig_pos = $pos;
                    $max = $block_size - $pos;
                    if ($len >= $max) {
                        $i = $max;
                        $len -= $max;
                        $pos = 0;
                    } else {
                        $i = $len;
                        $pos += $len;
                        $len = 0;
                    }
                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
                    $plaintext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $ciphertext;
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, $i), $orig_pos, $i);
                }
                if ($len >= $block_size) {
                    $cb = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $len - $len % $block_size);
                    $plaintext .= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
                    $iv = \Phabel\Target\Php80\Polyfill::substr($cb, -$block_size);
                    $len %= $block_size;
                }
                if ($len) {
                    $iv = mcrypt_generic($this->ecb, $iv);
                    $plaintext .= $iv ^ \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len), 0, $len);
                    $pos = $len;
                }
                restore_error_handler();
                return $plaintext;
            }
            $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
            if (!$this->continuousBuffer) {
                mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV));
            }
            restore_error_handler();
            return $this->paddable ? $this->unpad($plaintext) : $plaintext;
        }
        if ($this->engine === self::ENGINE_EVAL) {
            $inline = $this->inline_crypt;
            return $inline('decrypt', $ciphertext);
        }
        $block_size = $this->block_size;
        $buffer =& $this->debuffer;
        $plaintext = '';
        switch ($this->mode) {
            case self::MODE_ECB:
                for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                    $plaintext .= $this->decryptBlock(\Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size));
                }
                break;
            case self::MODE_CBC:
                $xor = $this->decryptIV;
                for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                    $block = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                    $plaintext .= $this->decryptBlock($block) ^ $xor;
                    $xor = $block;
                }
                if ($this->continuousBuffer) {
                    $this->decryptIV = $xor;
                }
                break;
            case self::MODE_CTR:
                $xor = $this->decryptIV;
                if (strlen($buffer['ciphertext'])) {
                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                        if (strlen($block) > strlen($buffer['ciphertext'])) {
                            $buffer['ciphertext'] .= $this->encryptBlock($xor);
                        }
                        Strings::increment_str($xor);
                        $key = Strings::shift($buffer['ciphertext'], $block_size);
                        $plaintext .= $block ^ $key;
                    }
                } else {
                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                        $key = $this->encryptBlock($xor);
                        Strings::increment_str($xor);
                        $plaintext .= $block ^ $key;
                    }
                }
                if ($this->continuousBuffer) {
                    $this->decryptIV = $xor;
                    if ($start = strlen($ciphertext) % $block_size) {
                        $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['ciphertext'];
                    }
                }
                break;
            case self::MODE_CFB:
                if ($this->continuousBuffer) {
                    $iv =& $this->decryptIV;
                    $pos =& $buffer['pos'];
                } else {
                    $iv = $this->decryptIV;
                    $pos = 0;
                }
                $len = strlen($ciphertext);
                $i = 0;
                if ($pos) {
                    $orig_pos = $pos;
                    $max = $block_size - $pos;
                    if ($len >= $max) {
                        $i = $max;
                        $len -= $max;
                        $pos = 0;
                    } else {
                        $i = $len;
                        $pos += $len;
                        $len = 0;
                    }
                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
                    $plaintext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $ciphertext;
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, $i), $orig_pos, $i);
                }
                while ($len >= $block_size) {
                    $iv = $this->encryptBlock($iv);
                    $cb = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                    $plaintext .= $iv ^ $cb;
                    $iv = $cb;
                    $len -= $block_size;
                    $i += $block_size;
                }
                if ($len) {
                    $iv = $this->encryptBlock($iv);
                    $plaintext .= $iv ^ \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i);
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i), 0, $len);
                    $pos = $len;
                }
                break;
            case self::MODE_CFB8:
                $plaintext = '';
                $len = strlen($ciphertext);
                $iv = $this->decryptIV;
                for ($i = 0; $i < $len; ++$i) {
                    $plaintext .= $ciphertext[$i] ^ $this->encryptBlock($iv);
                    $iv = \Phabel\Target\Php80\Polyfill::substr($iv, 1) . $ciphertext[$i];
                }
                if ($this->continuousBuffer) {
                    if ($len >= $block_size) {
                        $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$block_size);
                    } else {
                        $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($this->decryptIV, $len - $block_size) . \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                    }
                }
                break;
            case self::MODE_OFB:
                $xor = $this->decryptIV;
                if (strlen($buffer['xor'])) {
                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                        if (strlen($block) > strlen($buffer['xor'])) {
                            $xor = $this->encryptBlock($xor);
                            $buffer['xor'] .= $xor;
                        }
                        $key = Strings::shift($buffer['xor'], $block_size);
                        $plaintext .= $block ^ $key;
                    }
                } else {
                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                        $xor = $this->encryptBlock($xor);
                        $plaintext .= \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size) ^ $xor;
                    }
                    $key = $xor;
                }
                if ($this->continuousBuffer) {
                    $this->decryptIV = $xor;
                    if ($start = strlen($ciphertext) % $block_size) {
                        $buffer['xor'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['xor'];
                    }
                }
                break;
            case self::MODE_STREAM:
                $plaintext = $this->decryptBlock($ciphertext);
                break;
        }
        return $this->paddable ? $this->unpad($plaintext) : $plaintext;
    }
    /**
     * Get the authentication tag
     *
     * Only used in GCM or Poly1305 mode
     *
     * @see self::encrypt()
     * @param int $length optional
     * @return string
     * @access public
     * @throws \LengthException if $length isn't of a sufficient length
     * @throws \RuntimeException if GCM mode isn't being used
     */
    public function getTag($length = 16)
    {
        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
            throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305');
        }
        if ($this->newtag === false) {
            throw new \BadMethodCallException('A tag can only be returned after a round of encryption has been performed');
        }
        // the tag is 128-bits. it can't be greater than 16 bytes because that's bigger than the tag is. if it
        // were 0 you might as well be doing CTR and less than 4 provides minimal security that could be trivially
        // easily brute forced.
        // see https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=36
        // for more info
        if ($length < 4 || $length > 16) {
            throw new \LengthException('The authentication tag must be between 4 and 16 bytes long');
        }
        return $length == 16 ? $this->newtag : \Phabel\Target\Php80\Polyfill::substr($this->newtag, 0, $length);
    }
    /**
     * Sets the authentication tag
     *
     * Only used in GCM mode
     *
     * @see self::decrypt()
     * @param string $tag
     * @access public
     * @throws \LengthException if $length isn't of a sufficient length
     * @throws \RuntimeException if GCM mode isn't being used
     */
    public function setTag($tag)
    {
        if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) {
            $this->createPoly1305Key();
        }
        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
            throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305');
        }
        $length = strlen($tag);
        if ($length < 4 || $length > 16) {
            throw new \LengthException('The authentication tag must be between 4 and 16 bytes long');
        }
        $this->oldtag = $tag;
    }
    /**
     * Get the IV
     *
     * mcrypt requires an IV even if ECB is used
     *
     * @see self::encrypt()
     * @see self::decrypt()
     * @param string $iv
     * @return string
     * @access private
     */
    protected function getIV($iv)
    {
        return $this->mode == self::MODE_ECB ? str_repeat("\x00", $this->block_size) : $iv;
    }
    /**
    * OpenSSL CTR Processor
    *
    * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
    for CTR is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt()
    and SymmetricKey::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
    function will emulate CTR with ECB when necessary.
    *
    * @see self::encrypt()
    * @see self::decrypt()
    * @param string $plaintext
    * @param string $encryptIV
    * @param array $buffer
    * @return string
    * @access private
    */
    private function openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
    {
        $ciphertext = '';
        $block_size = $this->block_size;
        $key = $this->key;
        if ($this->openssl_emulate_ctr) {
            $xor = $encryptIV;
            if (strlen($buffer['ciphertext'])) {
                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                    $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                    if (strlen($block) > strlen($buffer['ciphertext'])) {
                        $buffer['ciphertext'] .= openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                    }
                    Strings::increment_str($xor);
                    $otp = Strings::shift($buffer['ciphertext'], $block_size);
                    $ciphertext .= $block ^ $otp;
                }
            } else {
                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                    $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                    $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                    Strings::increment_str($xor);
                    $ciphertext .= $block ^ $otp;
                }
            }
            if ($this->continuousBuffer) {
                $encryptIV = $xor;
                if ($start = strlen($plaintext) % $block_size) {
                    $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['ciphertext'];
                }
            }
            return $ciphertext;
        }
        if (strlen($buffer['ciphertext'])) {
            $ciphertext = $plaintext ^ Strings::shift($buffer['ciphertext'], strlen($plaintext));
            $plaintext = \Phabel\Target\Php80\Polyfill::substr($plaintext, strlen($ciphertext));
            if (!strlen($plaintext)) {
                return $ciphertext;
            }
        }
        $overflow = strlen($plaintext) % $block_size;
        if ($overflow) {
            $plaintext2 = Strings::pop($plaintext, $overflow);
            // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
            $encrypted = openssl_encrypt($plaintext . str_repeat("\x00", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
            $temp = Strings::pop($encrypted, $block_size);
            $ciphertext .= $encrypted . ($plaintext2 ^ $temp);
            if ($this->continuousBuffer) {
                $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($temp, $overflow);
                $encryptIV = $temp;
            }
        } elseif (!strlen($buffer['ciphertext'])) {
            $ciphertext .= openssl_encrypt($plaintext . str_repeat("\x00", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
            $temp = Strings::pop($ciphertext, $block_size);
            if ($this->continuousBuffer) {
                $encryptIV = $temp;
            }
        }
        if ($this->continuousBuffer) {
            $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
            if ($overflow) {
                Strings::increment_str($encryptIV);
            }
        }
        return $ciphertext;
    }
    /**
    * OpenSSL OFB Processor
    *
    * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
    for OFB is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt()
    and SymmetricKey::decrypt().
    *
    * @see self::encrypt()
    * @see self::decrypt()
    * @param string $plaintext
    * @param string $encryptIV
    * @param array $buffer
    * @return string
    * @access private
    */
    private function openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
    {
        if (strlen($buffer['xor'])) {
            $ciphertext = $plaintext ^ $buffer['xor'];
            $buffer['xor'] = \Phabel\Target\Php80\Polyfill::substr($buffer['xor'], strlen($ciphertext));
            $plaintext = \Phabel\Target\Php80\Polyfill::substr($plaintext, strlen($ciphertext));
        } else {
            $ciphertext = '';
        }
        $block_size = $this->block_size;
        $len = strlen($plaintext);
        $key = $this->key;
        $overflow = $len % $block_size;
        if (strlen($plaintext)) {
            if ($overflow) {
                $ciphertext .= openssl_encrypt(\Phabel\Target\Php80\Polyfill::substr($plaintext, 0, -$overflow) . str_repeat("\x00", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
                $xor = Strings::pop($ciphertext, $block_size);
                if ($this->continuousBuffer) {
                    $encryptIV = $xor;
                }
                $ciphertext .= Strings::shift($xor, $overflow) ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, -$overflow);
                if ($this->continuousBuffer) {
                    $buffer['xor'] = $xor;
                }
            } else {
                $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
                if ($this->continuousBuffer) {
                    $encryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$block_size) ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, -$block_size);
                }
            }
        }
        return $ciphertext;
    }
    /**
     * phpseclib <-> OpenSSL Mode Mapper
     *
     * May need to be overwritten by classes extending this one in some cases
     *
     * @return string
     * @access private
     */
    protected function openssl_translate_mode()
    {
        switch ($this->mode) {
            case self::MODE_ECB:
                return 'ecb';
            case self::MODE_CBC:
                return 'cbc';
            case self::MODE_CTR:
            case self::MODE_GCM:
                return 'ctr';
            case self::MODE_CFB:
                return 'cfb';
            case self::MODE_CFB8:
                return 'cfb8';
            case self::MODE_OFB:
                return 'ofb';
        }
    }
    /**
    * Pad "packets".
    *
    * Block ciphers working by encrypting between their specified [$this->]block_size at a time
    If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
    pad the input so that it is of the proper length.
    *
    * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH,
    where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping
    away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
    transmitted separately)
    *
    * @see self::disablePadding()
    * @access public
    */
    public function enablePadding()
    {
        $this->padding = true;
    }
    /**
     * Do not pad packets.
     *
     * @see self::enablePadding()
     * @access public
     */
    public function disablePadding()
    {
        $this->padding = false;
    }
    /**
    * Treat consecutive "packets" as if they are a continuous buffer.
    *
    * Say you have a 32-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
    will yield different outputs:
    *
    * <code>
    echo $rijndael->encrypt(substr($plaintext,  0, 16));
    echo $rijndael->encrypt(substr($plaintext, 16, 16));
    </code>
    <code>
    echo $rijndael->encrypt($plaintext);
    </code>
    *
    * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
    another, as demonstrated with the following:
    *
    * <code>
    $rijndael->encrypt(substr($plaintext, 0, 16));
    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
    </code>
    <code>
    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
    </code>
    *
    * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
    outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
    decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
    *
    * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\*() object changes after each
    encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
    continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
    however, they are also less intuitive and more likely to cause you problems.
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::disableContinuousBuffer()
    * @access public
    */
    public function enableContinuousBuffer()
    {
        if ($this->mode == self::MODE_ECB) {
            return;
        }
        if ($this->mode == self::MODE_GCM) {
            throw new \BadMethodCallException('This mode does not run in continuous mode');
        }
        $this->continuousBuffer = true;
        $this->setEngine();
    }
    /**
     * Treat consecutive packets as if they are a discontinuous buffer.
     *
     * The default behavior.
     *
     * {@internal Could, but not must, extend by the child Crypt_* class}
     *
     * @see self::enableContinuousBuffer()
     * @access public
     */
    public function disableContinuousBuffer()
    {
        if ($this->mode == self::MODE_ECB) {
            return;
        }
        if (!$this->continuousBuffer) {
            return;
        }
        $this->continuousBuffer = false;
        $this->setEngine();
    }
    /**
     * Test for engine validity
     *
     * @see self::__construct()
     * @param int $engine
     * @access private
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        switch ($engine) {
            case self::ENGINE_OPENSSL:
                $this->openssl_emulate_ctr = false;
                $result = $this->cipher_name_openssl && extension_loaded('openssl');
                if (!$result) {
                    return false;
                }
                $methods = openssl_get_cipher_methods();
                if (in_array($this->cipher_name_openssl, $methods)) {
                    return true;
                }
                // not all of openssl's symmetric cipher's support ctr. for those
                // that don't we'll emulate it
                switch ($this->mode) {
                    case self::MODE_CTR:
                        if (in_array($this->cipher_name_openssl_ecb, $methods)) {
                            $this->openssl_emulate_ctr = true;
                            return true;
                        }
                }
                return false;
            case self::ENGINE_MCRYPT:
                set_error_handler(function () {
                });
                $result = $this->cipher_name_mcrypt && extension_loaded('mcrypt') && in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms());
                restore_error_handler();
                return $result;
            case self::ENGINE_EVAL:
                return method_exists($this, 'setupInlineCrypt');
            case self::ENGINE_INTERNAL:
                return true;
        }
        return false;
    }
    /**
     * Test for engine validity
     *
     * @see self::__construct()
     * @param string $engine
     * @access public
     * @return bool
     */
    public function isValidEngine($engine)
    {
        static $reverseMap;
        if (!isset($reverseMap)) {
            $reverseMap = array_map('strtolower', self::ENGINE_MAP);
            $reverseMap = array_flip($reverseMap);
        }
        $engine = strtolower($engine);
        if (!isset($reverseMap[$engine])) {
            return false;
        }
        return $this->isValidEngineHelper($reverseMap[$engine]);
    }
    /**
     * Sets the preferred crypt engine
     *
     * Currently, $engine could be:
     *
     * - libsodium[very fast]
     *
     * - OpenSSL  [very fast]
     *
     * - mcrypt   [fast]
     *
     * - Eval     [slow]
     *
     * - PHP      [slowest]
     *
     * If the preferred crypt engine is not available the fastest available one will be used
     *
     * @see self::__construct()
     * @param string $engine
     * @access public
     */
    public function setPreferredEngine($engine)
    {
        static $reverseMap;
        if (!isset($reverseMap)) {
            $reverseMap = array_map('strtolower', self::ENGINE_MAP);
            $reverseMap = array_flip($reverseMap);
        }
        $engine = strtolower($engine);
        $this->preferredEngine = isset($reverseMap[$engine]) ? $reverseMap[$engine] : self::ENGINE_LIBSODIUM;
        $this->setEngine();
    }
    /**
     * Returns the engine currently being utilized
     *
     * @see self::setEngine()
     * @access public
     */
    public function getEngine()
    {
        return self::ENGINE_MAP[$this->engine];
    }
    /**
     * Sets the engine as appropriate
     *
     * @see self::__construct()
     * @access private
     */
    protected function setEngine()
    {
        $this->engine = null;
        $candidateEngines = [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM, self::ENGINE_OPENSSL, self::ENGINE_MCRYPT, self::ENGINE_EVAL];
        if (isset($this->preferredEngine)) {
            $temp = [$this->preferredEngine];
            $candidateEngines = array_merge($temp, array_diff($candidateEngines, $temp));
        }
        foreach ($candidateEngines as $engine) {
            if ($this->isValidEngineHelper($engine)) {
                $this->engine = $engine;
                break;
            }
        }
        if (!$this->engine) {
            $this->engine = self::ENGINE_INTERNAL;
        }
        if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
            set_error_handler(function () {
            });
            // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
            // (re)open them with the module named in $this->cipher_name_mcrypt
            mcrypt_module_close($this->enmcrypt);
            mcrypt_module_close($this->demcrypt);
            $this->enmcrypt = null;
            $this->demcrypt = null;
            if ($this->ecb) {
                mcrypt_module_close($this->ecb);
                $this->ecb = null;
            }
            restore_error_handler();
        }
        $this->changed = $this->nonIVChanged = true;
    }
    /**
     * Encrypts a block
     *
     * Note: Must be extended by the child \phpseclib3\Crypt\* class
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected abstract function encryptBlock($in);
    /**
     * Decrypts a block
     *
     * Note: Must be extended by the child \phpseclib3\Crypt\* class
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected abstract function decryptBlock($in);
    /**
     * Setup the key (expansion)
     *
     * Only used if $engine == self::ENGINE_INTERNAL
     *
     * Note: Must extend by the child \phpseclib3\Crypt\* class
     *
     * @see self::setup()
     * @access private
     */
    protected abstract function setupKey();
    /**
    * Setup the self::ENGINE_INTERNAL $engine
    *
    * (re)init, if necessary, the internal cipher $engine and flush all $buffers
    Used (only) if $engine == self::ENGINE_INTERNAL
    *
    * _setup() will be called each time if $changed === true
    typically this happens when using one or more of following public methods:
    *
    * - setKey()
    *
    * - setIV()
    *
    * - disableContinuousBuffer()
    *
    * - First run of encrypt() / decrypt() with no init-settings
    *
    * {@internal setup() is always called before en/decryption.}
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::setKey()
    * @see self::setIV()
    * @see self::disableContinuousBuffer()
    * @access private
    */
    protected function setup()
    {
        if (!$this->changed) {
            return;
        }
        $this->changed = false;
        if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) {
            $this->createPoly1305Key();
        }
        $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true];
        //$this->newtag = $this->oldtag = false;
        if ($this->usesNonce()) {
            if ($this->nonce === false) {
                throw new InsufficientSetupException('No nonce has been defined');
            }
            if ($this->mode == self::MODE_GCM && !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) {
                $this->setupGCM();
            }
        } else {
            $this->iv = $this->origIV;
        }
        if ($this->iv === false && !in_array($this->mode, [self::MODE_STREAM, self::MODE_ECB])) {
            if ($this->mode != self::MODE_GCM || !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) {
                throw new InsufficientSetupException('No IV has been defined');
            }
        }
        if ($this->key === false) {
            throw new InsufficientSetupException('No key has been defined');
        }
        $this->encryptIV = $this->decryptIV = $this->iv;
        switch ($this->engine) {
            case self::ENGINE_MCRYPT:
                $this->enchanged = $this->dechanged = true;
                set_error_handler(function () {
                });
                if (!isset($this->enmcrypt)) {
                    static $mcrypt_modes = [self::MODE_CTR => 'ctr', self::MODE_ECB => MCRYPT_MODE_ECB, self::MODE_CBC => MCRYPT_MODE_CBC, self::MODE_CFB => 'ncfb', self::MODE_CFB8 => MCRYPT_MODE_CFB, self::MODE_OFB => MCRYPT_MODE_NOFB, self::MODE_STREAM => MCRYPT_MODE_STREAM];
                    $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
                    $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
                    // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
                    // to workaround mcrypt's broken ncfb implementation in buffered mode
                    // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
                    if ($this->mode == self::MODE_CFB) {
                        $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
                    }
                }
                // else should mcrypt_generic_deinit be called?
                if ($this->mode == self::MODE_CFB) {
                    mcrypt_generic_init($this->ecb, $this->key, str_repeat("\x00", $this->block_size));
                }
                restore_error_handler();
                break;
            case self::ENGINE_INTERNAL:
                $this->setupKey();
                break;
            case self::ENGINE_EVAL:
                if ($this->nonIVChanged) {
                    $this->setupKey();
                    $this->setupInlineCrypt();
                }
        }
        $this->nonIVChanged = false;
    }
    /**
    * Pads a string
    *
    * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
    $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
    chr($this->block_size - (strlen($text) % $this->block_size)
    *
    * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
    and padding will, hence forth, be enabled.
    *
    * @see self::unpad()
    * @param string $text
    * @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size
    * @access private
    * @return string
    */
    protected function pad($text)
    {
        $length = strlen($text);
        if (!$this->padding) {
            if ($length % $this->block_size == 0) {
                return $text;
            } else {
                throw new \LengthException("The plaintext's length ({$length}) is not a multiple of the block size ({$this->block_size}). Try enabling padding.");
            }
        }
        $pad = $this->block_size - $length % $this->block_size;
        return str_pad($text, $length + $pad, chr($pad));
    }
    /**
    * Unpads a string.
    *
    * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
    and false will be returned.
    *
    * @see self::pad()
    * @param string $text
    * @throws \LengthException if the ciphertext's length is not a multiple of the block size
    * @access private
    * @return string
    */
    protected function unpad($text)
    {
        if (!$this->padding) {
            return $text;
        }
        $length = ord($text[strlen($text) - 1]);
        if (!$length || $length > $this->block_size) {
            throw new BadDecryptionException("The ciphertext has an invalid padding length ({$length}) compared to the block size ({$this->block_size})");
        }
        return \Phabel\Target\Php80\Polyfill::substr($text, 0, -$length);
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * Stores the created (or existing) callback function-name
     * in $this->inline_crypt
     *
     * Internally for phpseclib developers:
     *
     *     _setupInlineCrypt() would be called only if:
     *
     *     - $this->engine === self::ENGINE_EVAL
     *
     *     - each time on _setup(), after(!) _setupKey()
     *
     *
     *     This ensures that _setupInlineCrypt() has always a
     *     full ready2go initializated internal cipher $engine state
     *     where, for example, the keys already expanded,
     *     keys/block_size calculated and such.
     *
     *     It is, each time if called, the responsibility of _setupInlineCrypt():
     *
     *     - to set $this->inline_crypt to a valid and fully working callback function
     *       as a (faster) replacement for encrypt() / decrypt()
     *
     *     - NOT to create unlimited callback functions (for memory reasons!)
     *       no matter how often _setupInlineCrypt() would be called. At some
     *       point of amount they must be generic re-useable.
     *
     *     - the code of _setupInlineCrypt() it self,
     *       and the generated callback code,
     *       must be, in following order:
     *       - 100% safe
     *       - 100% compatible to encrypt()/decrypt()
     *       - using only php5+ features/lang-constructs/php-extensions if
     *         compatibility (down to php4) or fallback is provided
     *       - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
     *       - >= 10% faster than encrypt()/decrypt() [which is, by the way,
     *         the reason for the existence of _setupInlineCrypt() :-)]
     *       - memory-nice
     *       - short (as good as possible)
     *
     * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
     *       - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib3\Crypt\* class.
     *       - The following variable names are reserved:
     *         - $_*  (all variable names prefixed with an underscore)
     *         - $self (object reference to it self. Do not use $this, but $self instead)
     *         - $in (the content of $in has to en/decrypt by the generated code)
     *       - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
     *
     * {@internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()}
     *
     * @see self::setup()
     * @see self::createInlineCryptFunction()
     * @see self::encrypt()
     * @see self::decrypt()
     * @access private
     */
    //protected function setupInlineCrypt();
    /**
    * Creates the performance-optimized function for en/decrypt()
    *
    * Internally for phpseclib developers:
    *
    * _createInlineCryptFunction():
    *
    * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
    with the current [$this->]mode of operation code
    *
    * - create the $inline function, which called by encrypt() / decrypt()
    as its replacement to speed up the en/decryption operations.
    *
    * - return the name of the created $inline callback function
    *
    * - used to speed up en/decryption
    *
    *
    *
    * The main reason why can speed up things [up to 50%] this way are:
    *
    * - using variables more effective then regular.
    (ie no use of expensive arrays but integers $k_0, $k_1 ...
    or even, for example, the pure $key[] values hardcoded)
    *
    * - avoiding 1000's of function calls of ie _encryptBlock()
    but inlining the crypt operations.
    in the mode of operation for() loop.
    *
    * - full loop unroll the (sometimes key-dependent) rounds
    avoiding this way ++$i counters and runtime-if's etc...
    *
    * The basic code architectur of the generated $inline en/decrypt()
    lambda function, in pseudo php, is:
    *
    * <code>
    +----------------------------------------------------------------------------------------------+
    | callback $inline = create_function:                                                          |
    | lambda_function_0001_crypt_ECB($action, $text)                                               |
    | {                                                                                            |
    |     INSERT PHP CODE OF:                                                                      |
    |     $cipher_code['init_crypt'];                  // general init code.                       |
    |                                                  // ie: $sbox'es declarations used for       |
    |                                                  //     encrypt and decrypt'ing.             |
    |                                                                                              |
    |     switch ($action) {                                                                       |
    |         case 'encrypt':                                                                      |
    |             INSERT PHP CODE OF:                                                              |
    |             $cipher_code['init_encrypt'];       // encrypt sepcific init code.               |
    |                                                    ie: specified $key or $box                |
    |                                                        declarations for encrypt'ing.         |
    |                                                                                              |
    |             foreach ($ciphertext) {                                                          |
    |                 $in = $block_size of $ciphertext;                                            |
    |                                                                                              |
    |                 INSERT PHP CODE OF:                                                          |
    |                 $cipher_code['encrypt_block'];  // encrypt's (string) $in, which is always:  |
    |                                                 // strlen($in) == $this->block_size          |
    |                                                 // here comes the cipher algorithm in action |
    |                                                 // for encryption.                           |
    |                                                 // $cipher_code['encrypt_block'] has to      |
    |                                                 // encrypt the content of the $in variable   |
    |                                                                                              |
    |                 $plaintext .= $in;                                                           |
    |             }                                                                                |
    |             return $plaintext;                                                               |
    |                                                                                              |
    |         case 'decrypt':                                                                      |
    |             INSERT PHP CODE OF:                                                              |
    |             $cipher_code['init_decrypt'];       // decrypt sepcific init code                |
    |                                                    ie: specified $key or $box                |
    |                                                        declarations for decrypt'ing.         |
    |             foreach ($plaintext) {                                                           |
    |                 $in = $block_size of $plaintext;                                             |
    |                                                                                              |
    |                 INSERT PHP CODE OF:                                                          |
    |                 $cipher_code['decrypt_block'];  // decrypt's (string) $in, which is always   |
    |                                                 // strlen($in) == $this->block_size          |
    |                                                 // here comes the cipher algorithm in action |
    |                                                 // for decryption.                           |
    |                                                 // $cipher_code['decrypt_block'] has to      |
    |                                                 // decrypt the content of the $in variable   |
    |                 $ciphertext .= $in;                                                          |
    |             }                                                                                |
    |             return $ciphertext;                                                              |
    |     }                                                                                        |
    | }                                                                                            |
    +----------------------------------------------------------------------------------------------+
    </code>
    *
    * See also the \phpseclib3\Crypt\*::_setupInlineCrypt()'s for
    productive inline $cipher_code's how they works.
    *
    * Structure of:
    <code>
    $cipher_code = [
    'init_crypt'    => (string) '', // optional
    'init_encrypt'  => (string) '', // optional
    'init_decrypt'  => (string) '', // optional
    'encrypt_block' => (string) '', // required
    'decrypt_block' => (string) ''  // required
    ];
    </code>
    *
    * @see self::setupInlineCrypt()
    * @see self::encrypt()
    * @see self::decrypt()
    * @param array $cipher_code
    * @access private
    * @return string (the name of the created callback function)
    */
    protected function createInlineCryptFunction($cipher_code)
    {
        $block_size = $this->block_size;
        // optional
        $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
        $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
        $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
        // required
        $encrypt_block = $cipher_code['encrypt_block'];
        $decrypt_block = $cipher_code['decrypt_block'];
        // Generating mode of operation inline code,
        // merged with the $cipher_code algorithm
        // for encrypt- and decryption.
        switch ($this->mode) {
            case self::MODE_ECB:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);

                    for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                        $in = substr($_text, $_i, ' . $block_size . ');
                        ' . $encrypt_block . '
                        $_ciphertext.= $in;
                    }

                    return $_ciphertext;
                    ';
                $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0));
                    $_ciphertext_len = strlen($_text);

                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                        $in = substr($_text, $_i, ' . $block_size . ');
                        ' . $decrypt_block . '
                        $_plaintext.= $in;
                    }

                    return $this->unpad($_plaintext);
                    ';
                break;
            case self::MODE_CTR:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);
                    $_xor = $this->encryptIV;
                    $_buffer = &$this->enbuffer;
                    if (strlen($_buffer["ciphertext"])) {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
                                $in = $_xor;
                                ' . $encrypt_block . '
                                \\phpseclib3\\Common\\Functions\\Strings::increment_str($_xor);
                                $_buffer["ciphertext"].= $in;
                            }
                            $_key = \\phpseclib3\\Common\\Functions\\Strings::shift($_buffer["ciphertext"], ' . $block_size . ');
                            $_ciphertext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            $in = $_xor;
                            ' . $encrypt_block . '
                            \\phpseclib3\\Common\\Functions\\Strings::increment_str($_xor);
                            $_key = $in;
                            $_ciphertext.= $_block ^ $_key;
                        }
                    }
                    if ($this->continuousBuffer) {
                        $this->encryptIV = $_xor;
                        if ($_start = $_plaintext_len % ' . $block_size . ') {
                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
                        }
                    }

                    return $_ciphertext;
                ';
                $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_ciphertext_len = strlen($_text);
                    $_xor = $this->decryptIV;
                    $_buffer = &$this->debuffer;

                    if (strlen($_buffer["ciphertext"])) {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
                                $in = $_xor;
                                ' . $encrypt_block . '
                                \\phpseclib3\\Common\\Functions\\Strings::increment_str($_xor);
                                $_buffer["ciphertext"].= $in;
                            }
                            $_key = \\phpseclib3\\Common\\Functions\\Strings::shift($_buffer["ciphertext"], ' . $block_size . ');
                            $_plaintext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            $in = $_xor;
                            ' . $encrypt_block . '
                            \\phpseclib3\\Common\\Functions\\Strings::increment_str($_xor);
                            $_key = $in;
                            $_plaintext.= $_block ^ $_key;
                        }
                    }
                    if ($this->continuousBuffer) {
                        $this->decryptIV = $_xor;
                        if ($_start = $_ciphertext_len % ' . $block_size . ') {
                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
                        }
                    }

                    return $_plaintext;
                    ';
                break;
            case self::MODE_CFB:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_buffer = &$this->enbuffer;

                    if ($this->continuousBuffer) {
                        $_iv = &$this->encryptIV;
                        $_pos = &$_buffer["pos"];
                    } else {
                        $_iv = $this->encryptIV;
                        $_pos = 0;
                    }
                    $_len = strlen($_text);
                    $_i = 0;
                    if ($_pos) {
                        $_orig_pos = $_pos;
                        $_max = ' . $block_size . ' - $_pos;
                        if ($_len >= $_max) {
                            $_i = $_max;
                            $_len-= $_max;
                            $_pos = 0;
                        } else {
                            $_i = $_len;
                            $_pos+= $_len;
                            $_len = 0;
                        }
                        $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
                        $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
                    }
                    while ($_len >= ' . $block_size . ') {
                        $in = $_iv;
                        ' . $encrypt_block . ';
                        $_iv = $in ^ substr($_text, $_i, ' . $block_size . ');
                        $_ciphertext.= $_iv;
                        $_len-= ' . $block_size . ';
                        $_i+= ' . $block_size . ';
                    }
                    if ($_len) {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_iv = $in;
                        $_block = $_iv ^ substr($_text, $_i);
                        $_iv = substr_replace($_iv, $_block, 0, $_len);
                        $_ciphertext.= $_block;
                        $_pos = $_len;
                    }
                    return $_ciphertext;
                ';
                $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_buffer = &$this->debuffer;

                    if ($this->continuousBuffer) {
                        $_iv = &$this->decryptIV;
                        $_pos = &$_buffer["pos"];
                    } else {
                        $_iv = $this->decryptIV;
                        $_pos = 0;
                    }
                    $_len = strlen($_text);
                    $_i = 0;
                    if ($_pos) {
                        $_orig_pos = $_pos;
                        $_max = ' . $block_size . ' - $_pos;
                        if ($_len >= $_max) {
                            $_i = $_max;
                            $_len-= $_max;
                            $_pos = 0;
                        } else {
                            $_i = $_len;
                            $_pos+= $_len;
                            $_len = 0;
                        }
                        $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
                        $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
                    }
                    while ($_len >= ' . $block_size . ') {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_iv = $in;
                        $cb = substr($_text, $_i, ' . $block_size . ');
                        $_plaintext.= $_iv ^ $cb;
                        $_iv = $cb;
                        $_len-= ' . $block_size . ';
                        $_i+= ' . $block_size . ';
                    }
                    if ($_len) {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_iv = $in;
                        $_plaintext.= $_iv ^ substr($_text, $_i);
                        $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
                        $_pos = $_len;
                    }

                    return $_plaintext;
                    ';
                break;
            case self::MODE_CFB8:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_len = strlen($_text);
                    $_iv = $this->encryptIV;

                    for ($_i = 0; $_i < $_len; ++$_i) {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_ciphertext .= ($_c = $_text[$_i] ^ $in);
                        $_iv = substr($_iv, 1) . $_c;
                    }

                    if ($this->continuousBuffer) {
                        if ($_len >= ' . $block_size . ') {
                            $this->encryptIV = substr($_ciphertext, -' . $block_size . ');
                        } else {
                            $this->encryptIV = substr($this->encryptIV, $_len - ' . $block_size . ') . substr($_ciphertext, -$_len);
                        }
                    }

                    return $_ciphertext;
                    ';
                $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_len = strlen($_text);
                    $_iv = $this->decryptIV;

                    for ($_i = 0; $_i < $_len; ++$_i) {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_plaintext .= $_text[$_i] ^ $in;
                        $_iv = substr($_iv, 1) . $_text[$_i];
                    }

                    if ($this->continuousBuffer) {
                        if ($_len >= ' . $block_size . ') {
                            $this->decryptIV = substr($_text, -' . $block_size . ');
                        } else {
                            $this->decryptIV = substr($this->decryptIV, $_len - ' . $block_size . ') . substr($_text, -$_len);
                        }
                    }

                    return $_plaintext;
                    ';
                break;
            case self::MODE_OFB:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);
                    $_xor = $this->encryptIV;
                    $_buffer = &$this->enbuffer;

                    if (strlen($_buffer["xor"])) {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            if (strlen($_block) > strlen($_buffer["xor"])) {
                                $in = $_xor;
                                ' . $encrypt_block . '
                                $_xor = $in;
                                $_buffer["xor"].= $_xor;
                            }
                            $_key = \\phpseclib3\\Common\\Functions\\Strings::shift($_buffer["xor"], ' . $block_size . ');
                            $_ciphertext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                            $in = $_xor;
                            ' . $encrypt_block . '
                            $_xor = $in;
                            $_ciphertext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor;
                        }
                        $_key = $_xor;
                    }
                    if ($this->continuousBuffer) {
                        $this->encryptIV = $_xor;
                        if ($_start = $_plaintext_len % ' . $block_size . ') {
                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
                        }
                    }
                    return $_ciphertext;
                    ';
                $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_ciphertext_len = strlen($_text);
                    $_xor = $this->decryptIV;
                    $_buffer = &$this->debuffer;

                    if (strlen($_buffer["xor"])) {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            if (strlen($_block) > strlen($_buffer["xor"])) {
                                $in = $_xor;
                                ' . $encrypt_block . '
                                $_xor = $in;
                                $_buffer["xor"].= $_xor;
                            }
                            $_key = \\phpseclib3\\Common\\Functions\\Strings::shift($_buffer["xor"], ' . $block_size . ');
                            $_plaintext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                            $in = $_xor;
                            ' . $encrypt_block . '
                            $_xor = $in;
                            $_plaintext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor;
                        }
                        $_key = $_xor;
                    }
                    if ($this->continuousBuffer) {
                        $this->decryptIV = $_xor;
                        if ($_start = $_ciphertext_len % ' . $block_size . ') {
                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
                        }
                    }
                    return $_plaintext;
                    ';
                break;
            case self::MODE_STREAM:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    ' . $encrypt_block . '
                    return $_ciphertext;
                    ';
                $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    ' . $decrypt_block . '
                    return $_plaintext;
                    ';
                break;
            // case self::MODE_CBC:
            default:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);

                    $in = $this->encryptIV;

                    for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                        $in = substr($_text, $_i, ' . $block_size . ') ^ $in;
                        ' . $encrypt_block . '
                        $_ciphertext.= $in;
                    }

                    if ($this->continuousBuffer) {
                        $this->encryptIV = $in;
                    }

                    return $_ciphertext;
                    ';
                $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0));
                    $_ciphertext_len = strlen($_text);

                    $_iv = $this->decryptIV;

                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                        $in = $_block = substr($_text, $_i, ' . $block_size . ');
                        ' . $decrypt_block . '
                        $_plaintext.= $in ^ $_iv;
                        $_iv = $_block;
                    }

                    if ($this->continuousBuffer) {
                        $this->decryptIV = $_iv;
                    }

                    return $this->unpad($_plaintext);
                    ';
                break;
        }
        // Before discrediting this, please read the following:
        // @see https://github.com/phpseclib/phpseclib/issues/1293
        // @see https://github.com/phpseclib/phpseclib/pull/1143
        eval('$func = function ($_action, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }};');
        return \Closure::bind($func, $this, static::class);
    }
    /**
     * Convert float to int
     *
     * On ARM CPUs converting floats to ints doesn't always work
     *
     * @access private
     * @param string $x
     * @return int
     */
    protected static function safe_intval($x)
    {
        switch (true) {
            case is_int($x):
            // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
            case (php_uname('m') & "\xdf\xdf\xdf") != 'ARM':
                return $x;
        }
        return fmod($x, 0x80000000) & 0x7fffffff | (fmod(floor($x / 0x80000000), 2) & 1) << 31;
    }
    /**
     * eval()'able string for in-line float to int
     *
     * @access private
     * @return string
     */
    protected static function safe_intval_inline()
    {
        switch (true) {
            case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
            case (php_uname('m') & "\xdf\xdf\xdf") != 'ARM':
                return '%s';
                break;
            default:
                $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
                return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
        }
    }
    /**
    * Sets up GCM parameters
    *
    * See steps 1-2 of https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=23
    for more info
    *
    * @access private
    */
    private function setupGCM()
    {
        // don't keep on re-calculating $this->h
        if (!$this->h || $this->h->key != $this->key) {
            $cipher = new static('ecb');
            $cipher->setKey($this->key);
            $cipher->disablePadding();
            $this->h = self::$gcmField->newInteger(Strings::switchEndianness($cipher->encrypt("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")));
            $this->h->key = $this->key;
        }
        if (strlen($this->nonce) == 12) {
            $this->iv = $this->nonce . "\x00\x00\x00\x01";
        } else {
            $this->iv = $this->ghash(self::nullPad128($this->nonce) . str_repeat("\x00", 8) . self::len64($this->nonce));
        }
    }
    /**
    * Performs GHASH operation
    *
    * See https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=20
    for more info
    *
    * @see self::decrypt()
    * @see self::encrypt()
    * @access private
    * @param string $x
    * @return string
    */
    private function ghash($x)
    {
        $h = $this->h;
        $y = ["\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"];
        $x = str_split($x, 16);
        $n = 0;
        // the switchEndianness calls are necessary because the multiplication algorithm in BinaryField/Integer
        // interprets strings as polynomials in big endian order whereas in GCM they're interpreted in little
        // endian order per https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=19.
        // big endian order is what binary field elliptic curves use per http://www.secg.org/sec1-v2.pdf#page=18.
        // we could switchEndianness here instead of in the while loop but doing so in the while loop seems like it
        // might be slightly more performant
        //$x = Strings::switchEndianness($x);
        foreach ($x as $xn) {
            $xn = Strings::switchEndianness($xn);
            $t = $y[$n] ^ $xn;
            $temp = self::$gcmField->newInteger($t);
            $y[++$n] = $temp->multiply($h)->toBytes();
            $y[$n] = \Phabel\Target\Php80\Polyfill::substr($y[$n], 1);
        }
        $y[$n] = Strings::switchEndianness($y[$n]);
        return $y[$n];
    }
    /**
     * Returns the bit length of a string in a packed format
     *
     * @see self::decrypt()
     * @see self::encrypt()
     * @see self::setupGCM()
     * @access private
     * @param string $str
     * @return string
     */
    private static function len64($str)
    {
        return "\x00\x00\x00\x00" . pack('N', 8 * strlen($str));
    }
    /**
     * NULL pads a string to be a multiple of 128
     *
     * @see self::decrypt()
     * @see self::encrypt()
     * @see self::setupGCM()
     * @access private
     * @param string $str
     * @return string
     */
    protected static function nullPad128($str)
    {
        $len = strlen($str);
        return $str . str_repeat("\x00", 16 * ceil($len / 16) - $len);
    }
    /**
    * Calculates Poly1305 MAC
    *
    * On my system ChaCha20, with libsodium, takes 0.5s. With this custom Poly1305 implementation
    it takes 1.2s.
    *
    * @see self::decrypt()
    * @see self::encrypt()
    * @access private
    * @param string $text
    * @return string
    */
    protected function poly1305($text)
    {
        $s = $this->poly1305Key;
        // strlen($this->poly1305Key) == 32
        $r = Strings::shift($s, 16);
        $r = strrev($r);
        $r &= "\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xff";
        $s = strrev($s);
        $r = self::$poly1305Field->newInteger(new BigInteger($r, 256));
        $s = self::$poly1305Field->newInteger(new BigInteger($s, 256));
        $a = self::$poly1305Field->newInteger(new BigInteger());
        $blocks = str_split($text, 16);
        foreach ($blocks as $block) {
            $n = strrev($block . chr(1));
            $n = self::$poly1305Field->newInteger(new BigInteger($n, 256));
            $a = $a->add($n);
            $a = $a->multiply($r);
        }
        $r = $a->toBigInteger()->add($s->toBigInteger());
        $mask = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
        return strrev($r->toBytes()) & $mask;
    }
    /**
     * Return the mode
     *
     * You can do $obj instanceof AES or whatever to get the cipher but you can't do that to get the mode
     *
     * @access public
     * @return string
     */
    public function getMode()
    {
        return array_flip(self::MODE_MAP)[$this->mode];
    }
}<?php

/**
 * Base Class for all asymmetric key ciphers
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   AsymmetricKey
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

use phpseclib3\Exception\UnsupportedFormatException;
use phpseclib3\Exception\NoKeyLoadedException;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\ECDSA;
/**
 * Base Class for all asymmetric cipher classes
 *
 * @package AsymmetricKey
 * @author  Jim Wigginton <terrafrost@php.net>
 */
abstract class AsymmetricKey
{
    /**
     * Precomputed Zero
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected static $zero;
    /**
     * Precomputed One
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected static $one;
    /**
     * Format of the loaded key
     *
     * @var string
     * @access private
     */
    protected $format;
    /**
     * Hash function
     *
     * @var \phpseclib3\Crypt\Hash
     * @access private
     */
    protected $hash;
    /**
     * HMAC function
     *
     * @var \phpseclib3\Crypt\Hash
     * @access private
     */
    private $hmac;
    /**
     * Supported plugins (lower case)
     *
     * @see self::initialize_static_variables()
     * @var array
     * @access private
     */
    private static $plugins = [];
    /**
     * Invisible plugins
     *
     * @see self::initialize_static_variables()
     * @var array
     * @access private
     */
    private static $invisiblePlugins = [];
    /**
     * Supported signature formats (lower case)
     *
     * @see self::initialize_static_variables()
     * @var array
     * @access private
     */
    private static $signatureFormats = [];
    /**
     * Supported signature formats (original case)
     *
     * @see self::initialize_static_variables()
     * @var array
     * @access private
     */
    private static $signatureFileFormats = [];
    /**
     * Available Engines
     *
     * @var boolean[]
     * @access private
     */
    protected static $engines = [];
    /**
     * Key Comment
     *
     * @var null|string
     * @access private
     */
    private $comment;
    /**
     * The constructor
     */
    protected function __construct()
    {
        self::initialize_static_variables();
        $this->hash = new Hash('sha256');
        $this->hmac = new Hash('sha256');
    }
    /**
     * Initialize static variables
     */
    protected static function initialize_static_variables()
    {
        if (!isset(self::$zero)) {
            self::$zero = new BigInteger(0);
            self::$one = new BigInteger(1);
        }
        self::loadPlugins('Keys');
        if (static::ALGORITHM != 'RSA' && static::ALGORITHM != 'DH') {
            self::loadPlugins('Signature');
        }
    }
    /**
     * Load the key
     *
     * @param string $key
     * @param string $password optional
     * @return AsymmetricKey
     */
    public static function load($key, $password = false)
    {
        self::initialize_static_variables();
        $components = false;
        foreach (self::$plugins[static::ALGORITHM]['Keys'] as $format) {
            if (isset(self::$invisiblePlugins[static::ALGORITHM]) && in_array($format, self::$invisiblePlugins[static::ALGORITHM])) {
                continue;
            }
            try {
                $components = $format::load($key, $password);
            } catch (\Exception $e) {
                $components = false;
            }
            if ($components !== false) {
                break;
            }
        }
        if ($components === false) {
            throw new NoKeyLoadedException('Unable to read key');
        }
        $components['format'] = $format;
        $comment = isset($components['comment']) ? $components['comment'] : null;
        $new = static::onLoad($components);
        $new->format = $format;
        $new->comment = $comment;
        return $new instanceof PrivateKey ? $new->withPassword($password) : $new;
    }
    /**
     * Loads a private key
     *
     * @return PrivateKey
     * @access public
     * @param (string | array) $key
     * @param string $password optional
     */
    public static function loadPrivateKey($key, $password = '')
    {
        $key = self::load($key, $password);
        if (!$key instanceof PrivateKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a private key');
        }
        return $key;
    }
    /**
     * Loads a public key
     *
     * @return PublicKey
     * @access public
     * @param (string | array) $key
     */
    public static function loadPublicKey($key)
    {
        $key = self::load($key);
        if (!$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a public key');
        }
        return $key;
    }
    /**
     * Loads parameters
     *
     * @return AsymmetricKey
     * @access public
     * @param (string | array) $key
     */
    public static function loadParameters($key)
    {
        $key = self::load($key);
        if (!$key instanceof PrivateKey && !$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a parameter');
        }
        return $key;
    }
    /**
     * Load the key, assuming a specific format
     *
     * @param string $type
     * @param string $key
     * @param string $password optional
     * @return AsymmetricKey
     */
    public static function loadFormat($type, $key, $password = false)
    {
        self::initialize_static_variables();
        $components = false;
        $format = strtolower($type);
        if (isset(self::$plugins[static::ALGORITHM]['Keys'][$format])) {
            $format = self::$plugins[static::ALGORITHM]['Keys'][$format];
            $components = $format::load($key, $password);
        }
        if ($components === false) {
            throw new NoKeyLoadedException('Unable to read key');
        }
        $components['format'] = $format;
        $new = static::onLoad($components);
        $new->format = $format;
        return $new instanceof PrivateKey ? $new->withPassword($password) : $new;
    }
    /**
     * Loads a private key
     *
     * @return PrivateKey
     * @access public
     * @param string $type
     * @param string $key
     * @param string $password optional
     */
    public static function loadPrivateKeyFormat($type, $key, $password = false)
    {
        $key = self::loadFormat($type, $key, $password);
        if (!$key instanceof PrivateKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a private key');
        }
        return $key;
    }
    /**
     * Loads a public key
     *
     * @return PublicKey
     * @access public
     * @param string $type
     * @param string $key
     */
    public static function loadPublicKeyFormat($type, $key)
    {
        $key = self::loadFormat($type, $key);
        if (!$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a public key');
        }
        return $key;
    }
    /**
     * Loads parameters
     *
     * @return AsymmetricKey
     * @access public
     * @param string $type
     * @param (string | array) $key
     */
    public static function loadParametersFormat($type, $key)
    {
        $key = self::loadFormat($type, $key);
        if (!$key instanceof PrivateKey && !$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a parameter');
        }
        return $key;
    }
    /**
     * Validate Plugin
     *
     * @access private
     * @param string $format
     * @param string $type
     * @param string $method optional
     * @return mixed
     */
    protected static function validatePlugin($format, $type, $method = NULL)
    {
        $type = strtolower($type);
        if (!isset(self::$plugins[static::ALGORITHM][$format][$type])) {
            throw new UnsupportedFormatException("{$type} is not a supported format");
        }
        $type = self::$plugins[static::ALGORITHM][$format][$type];
        if (isset($method) && !method_exists($type, $method)) {
            throw new UnsupportedFormatException("{$type} does not implement {$method}");
        }
        return $type;
    }
    /**
     * Load Plugins
     *
     * @access private
     * @param string $format
     */
    private static function loadPlugins($format)
    {
        if (!isset(self::$plugins[static::ALGORITHM][$format])) {
            self::$plugins[static::ALGORITHM][$format] = [];
            foreach (new \DirectoryIterator(__DIR__ . '/../' . static::ALGORITHM . '/Formats/' . $format . '/') as $file) {
                if ($file->getExtension() != 'php') {
                    continue;
                }
                $name = $file->getBasename('.php');
                if ($name[0] == '.') {
                    continue;
                }
                $type = 'phpseclib3\\Crypt\\' . static::ALGORITHM . '\\Formats\\' . $format . '\\' . $name;
                $reflect = new \ReflectionClass($type);
                if ($reflect->isTrait()) {
                    continue;
                }
                self::$plugins[static::ALGORITHM][$format][strtolower($name)] = $type;
                if ($reflect->hasConstant('IS_INVISIBLE')) {
                    self::$invisiblePlugins[static::ALGORITHM][] = $type;
                }
            }
        }
    }
    /**
     * Returns a list of supported formats.
     *
     * @access public
     * @return array
     */
    public static function getSupportedKeyFormats()
    {
        self::initialize_static_variables();
        return self::$plugins[static::ALGORITHM]['Keys'];
    }
    /**
    * Add a fileformat plugin
    *
    * The plugin needs to either already be loaded or be auto-loadable.
    Loading a plugin whose shortname overwrite an existing shortname will overwrite the old plugin.
    *
    * @see self::load()
    * @param string $fullname
    * @access public
    * @return bool
    */
    public static function addFileFormat($fullname)
    {
        self::initialize_static_variables();
        if (class_exists($fullname)) {
            $meta = new \ReflectionClass($fullname);
            $shortname = $meta->getShortName();
            self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname;
            if ($meta->hasConstant('IS_INVISIBLE')) {
                self::$invisiblePlugins[static::ALGORITHM] = strtolower($name);
            }
        }
    }
    /**
    * Returns the format of the loaded key.
    *
    * If the key that was loaded wasn't in a valid or if the key was auto-generated
    with RSA::createKey() then this will throw an exception.
    *
    * @see self::load()
    * @access public
    * @return mixed
    */
    public function getLoadedFormat()
    {
        if (empty($this->format)) {
            throw new NoKeyLoadedException('This key was created with createKey - it was not loaded with load. Therefore there is no "loaded format"');
        }
        $meta = new \ReflectionClass($this->format);
        return $meta->getShortName();
    }
    /**
     * Returns the key's comment
     *
     * Not all key formats support comments. If you want to set a comment use toString()
     *
     * @access public
     * @return (null | string)
     */
    public function getComment()
    {
        return $this->comment;
    }
    /**
     * Tests engine validity
     *
     * @access public
     */
    public static function useBestEngine()
    {
        static::$engines = [
            'PHP' => true,
            'OpenSSL' => extension_loaded('openssl'),
            // this test can be satisfied by either of the following:
            // http://php.net/manual/en/book.sodium.php
            // https://github.com/paragonie/sodium_compat
            'libsodium' => function_exists('sodium_crypto_sign_keypair'),
        ];
        return static::$engines;
    }
    /**
     * Flag to use internal engine only (useful for unit testing)
     *
     * @access public
     */
    public static function useInternalEngine()
    {
        static::$engines = ['PHP' => true, 'OpenSSL' => false, 'libsodium' => false];
    }
    /**
     * __toString() magic method
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toString('PKCS8');
    }
    /**
     * Determines which hashing function should be used
     *
     * @access public
     * @param string $hash
     */
    public function withHash($hash)
    {
        $new = clone $this;
        $new->hash = new Hash($hash);
        $new->hmac = new Hash($hash);
        return $new;
    }
    /**
     * Returns the hash algorithm currently being used
     *
     * @access public
     */
    public function getHash()
    {
        return clone $this->hash;
    }
    /**
    * Compute the pseudorandom k for signature generation,
    using the process specified for deterministic DSA.
    *
    * @access public
    * @param string $h1
    * @return string
    */
    protected function computek($h1)
    {
        $v = str_repeat("\x01", strlen($h1));
        $k = str_repeat("\x00", strlen($h1));
        $x = $this->int2octets($this->x);
        $h1 = $this->bits2octets($h1);
        $this->hmac->setKey($k);
        $k = $this->hmac->hash($v . "\x00" . $x . $h1);
        $this->hmac->setKey($k);
        $v = $this->hmac->hash($v);
        $k = $this->hmac->hash($v . "\x01" . $x . $h1);
        $this->hmac->setKey($k);
        $v = $this->hmac->hash($v);
        $qlen = $this->q->getLengthInBytes();
        while (true) {
            $t = '';
            while (strlen($t) < $qlen) {
                $v = $this->hmac->hash($v);
                $t = $t . $v;
            }
            $k = $this->bits2int($t);
            if (!$k->equals(self::$zero) && $k->compare($this->q) < 0) {
                break;
            }
            $k = $this->hmac->hash($v . "\x00");
            $this->hmac->setKey($k);
            $v = $this->hmac->hash($v);
        }
        return $k;
    }
    /**
     * Integer to Octet String
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $v
     * @return string
     */
    private function int2octets($v)
    {
        $out = $v->toBytes();
        $rolen = $this->q->getLengthInBytes();
        if (strlen($out) < $rolen) {
            return str_pad($out, $rolen, "\x00", STR_PAD_LEFT);
        } else {
            if (strlen($out) > $rolen) {
                return \Phabel\Target\Php80\Polyfill::substr($out, -$rolen);
            } else {
                return $out;
            }
        }
    }
    /**
     * Bit String to Integer
     *
     * @access private
     * @param string $in
     * @return \phpseclib3\Math\BigInteger
     */
    protected function bits2int($in)
    {
        $v = new BigInteger($in, 256);
        $vlen = strlen($in) << 3;
        $qlen = $this->q->getLength();
        if ($vlen > $qlen) {
            return $v->bitwise_rightShift($vlen - $qlen);
        }
        return $v;
    }
    /**
     * Bit String to Octet String
     *
     * @access private
     * @param string $in
     * @return string
     */
    private function bits2octets($in)
    {
        $z1 = $this->bits2int($in);
        $z2 = $z1->subtract($this->q);
        return $z2->compare(self::$zero) < 0 ? $this->int2octets($z1) : $this->int2octets($z2);
    }
}<?php

/**
 * Password Protected Trait for Private Keys
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Traits;

/**
 * Password Protected Trait for Private Keys
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
trait PasswordProtected
{
    /**
     * Password
     *
     * @var string|bool
     */
    private $password = false;
    /**
    * Sets the password
    *
    * Private keys can be encrypted with a password.  To unset the password, pass in the empty string or false.
    Or rather, pass in $password such that empty($password) && !is_string($password) is true.
    *
    * @see self::createKey()
    * @see self::load()
    * @access public
    * @param (string | boolean) $password
    */
    public function withPassword($password = false)
    {
        $new = clone $this;
        $new->password = $password;
        return $new;
    }
}<?php

/**
 * Fingerprint Trait for Public Keys
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Traits;

use phpseclib3\Crypt\Hash;
/**
 * Fingerprint Trait for Private Keys
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
trait Fingerprint
{
    /**
    * Returns the public key's fingerprint
    *
    * The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is
    no public key currently loaded, false is returned.
    Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
    *
    * @access public
    * @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
    for invalid values.
    * @return mixed
    */
    public function getFingerprint($algorithm = 'md5')
    {
        $type = self::validatePlugin('Keys', 'OpenSSH', 'savePublicKey');
        if ($type === false) {
            return false;
        }
        $key = $this->toString('OpenSSH', ['binary' => true]);
        if ($key === false) {
            return false;
        }
        switch ($algorithm) {
            case 'sha256':
                $hash = new Hash('sha256');
                $base = base64_encode($hash->hash($key));
                return \Phabel\Target\Php80\Polyfill::substr($base, 0, strlen($base) - 1);
            case 'md5':
                return \Phabel\Target\Php80\Polyfill::substr(chunk_split(md5($key), 2, ':'), 0, -1);
            default:
                return false;
        }
    }
}<?php

/**
 * Pure-PHP (EC)DH implementation
 *
 * PHP version 5
 *
 * Here's an example of how to compute a shared secret with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $ourPrivate = \phpseclib3\Crypt\DH::createKey();
 * $secret = DH::computeSecret($ourPrivate, $theirPublic);
 *
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Exception\NoKeyLoadedException;
use phpseclib3\Exception\UnsupportedOperationException;
use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\DH\PrivateKey;
use phpseclib3\Crypt\DH\PublicKey;
use phpseclib3\Crypt\DH\Parameters;
use phpseclib3\Math\BigInteger;
/**
 * Pure-PHP (EC)DH implementation
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DH extends AsymmetricKey
{
    /**
     * Algorithm Name
     *
     * @var string
     * @access private
     */
    const ALGORITHM = 'DH';
    /**
     * DH prime
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $prime;
    /**
     * DH Base
     *
     * Prime divisor of p-1
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $base;
    /**
    * Create DH parameters
    *
    * This method is a bit polymorphic. It can take any of the following:
    - two BigInteger's (prime and base)
    - an integer representing the size of the prime in bits (the base is assumed to be 2)
    - a string (eg. diffie-hellman-group14-sha1)
    *
    * @access public
    * @return (\phpseclib3\Crypt\DH | bool)
    */
    public static function createParameters(...$args)
    {
        $params = new Parameters();
        if (count($args) == 2 && $args[0] instanceof BigInteger && $args[1] instanceof BigInteger) {
            //if (!$args[0]->isPrime()) {
            //    throw new \InvalidArgumentException('The first parameter should be a prime number');
            //}
            $params->prime = $args[0];
            $params->base = $args[1];
            return $params;
        } elseif (count($args) == 1 && is_numeric($args[0])) {
            $params->prime = BigInteger::randomPrime($args[0]);
            $params->base = new BigInteger(2);
            return $params;
        } elseif (count($args) != 1 || !is_string($args[0])) {
            throw new \InvalidArgumentException('Valid parameters are either: two BigInteger\'s (prime and base), a single integer (the length of the prime; base is assumed to be 2) or a string');
        }
        switch ($args[0]) {
            // see http://tools.ietf.org/html/rfc2409#section-6.2 and
            // http://tools.ietf.org/html/rfc2412, appendex E
            case 'diffie-hellman-group1-sha1':
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
                break;
            // see http://tools.ietf.org/html/rfc3526#section-3
            case 'diffie-hellman-group14-sha1':
            // 2048-bit MODP Group
            case 'diffie-hellman-group14-sha256':
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
                break;
            // see https://tools.ietf.org/html/rfc3526#section-4
            case 'diffie-hellman-group15-sha512':
                // 3072-bit MODP Group
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF';
                break;
            // see https://tools.ietf.org/html/rfc3526#section-5
            case 'diffie-hellman-group16-sha512':
                // 4096-bit MODP Group
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF';
                break;
            // see https://tools.ietf.org/html/rfc3526#section-6
            case 'diffie-hellman-group17-sha512':
                // 6144-bit MODP Group
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF';
                break;
            // see https://tools.ietf.org/html/rfc3526#section-7
            case 'diffie-hellman-group18-sha512':
                // 8192-bit MODP Group
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF';
                break;
            default:
                throw new \InvalidArgumentException('Invalid named prime provided');
        }
        $params->prime = new BigInteger($prime, 16);
        $params->base = new BigInteger(2);
        return $params;
    }
    /**
    * Create public / private key pair.
    *
    * The rationale for the second parameter is described in http://tools.ietf.org/html/rfc4419#section-6.2 :
    *
    * "To increase the speed of the key exchange, both client and server may
    reduce the size of their private exponents.  It should be at least
    twice as long as the key material that is generated from the shared
    secret.  For more details, see the paper by van Oorschot and Wiener
    [VAN-OORSCHOT]."
    *
    * $length is in bits
    *
    * @param Parameters $params
    * @param int $length optional
    * @access public
    * @return DH\PrivateKey
    */
    public static function createKey(Parameters $params, $length = 0)
    {
        $one = new BigInteger(1);
        if ($length) {
            $max = $one->bitwise_leftShift($length);
            $max = $max->subtract($one);
        } else {
            $max = $params->prime->subtract($one);
        }
        $key = new PrivateKey();
        $key->prime = $params->prime;
        $key->base = $params->base;
        $key->privateKey = BigInteger::randomRange($one, $max);
        $key->publicKey = $key->base->powMod($key->privateKey, $key->prime);
        return $key;
    }
    /**
     * Compute Shared Secret
     *
     * @param (PrivateKey | EC) $private
     * @param (PublicKey | BigInteger | string) $public
     * @access public
     * @return mixed
     */
    public static function computeSecret($private, $public)
    {
        if ($private instanceof PrivateKey) {
            // DH\PrivateKey
            switch (true) {
                case $public instanceof PublicKey:
                    if (!$private->prime->equals($public->prime) || !$private->base->equals($public->base)) {
                        throw new \InvalidArgumentException('The public and private key do not share the same prime and / or base numbers');
                    }
                    return $public->publicKey->powMod($private->privateKey, $private->prime)->toBytes(true);
                case is_string($public):
                    $public = new BigInteger($public, -256);
                case $public instanceof BigInteger:
                    return $public->powMod($private->privateKey, $private->prime)->toBytes(true);
                default:
                    throw new \InvalidArgumentException('$public needs to be an instance of DH\\PublicKey, a BigInteger or a string');
            }
        }
        if ($private instanceof EC\PrivateKey) {
            switch (true) {
                case $public instanceof EC\PublicKey:
                    $public = $public->getEncodedCoordinates();
                case is_string($public):
                    $point = $private->multiply($public);
                    switch ($private->getCurve()) {
                        case 'Curve25519':
                        case 'Curve448':
                            $secret = $point;
                            break;
                        default:
                            // according to https://www.secg.org/sec1-v2.pdf#page=33 only X is returned
                            $secret = \Phabel\Target\Php80\Polyfill::substr($point, 1, strlen($point) - 1 >> 1);
                    }
                    /*
                    if (($secret[0] & "\x80") === "\x80") {
                        $secret = "\0$secret";
                    }
                    */
                    return $secret;
                default:
                    throw new \InvalidArgumentException('$public needs to be an instance of EC\\PublicKey or a string (an encoded coordinate)');
            }
        }
    }
    /**
     * Load the key
     *
     * @param string $key
     * @param string $password optional
     * @return AsymmetricKey
     */
    public static function load($key, $password = false)
    {
        try {
            return EC::load($key, $password);
        } catch (NoKeyLoadedException $e) {
        }
        return parent::load($key, $password);
    }
    /**
     * OnLoad Handler
     *
     * @return bool
     * @access protected
     * @param array $components
     */
    protected static function onLoad($components)
    {
        if (!isset($components['privateKey']) && !isset($components['publicKey'])) {
            $new = new Parameters();
        } else {
            $new = isset($components['privateKey']) ? new PrivateKey() : new PublicKey();
        }
        $new->prime = $components['prime'];
        $new->base = $components['base'];
        if (isset($components['privateKey'])) {
            $new->privateKey = $components['privateKey'];
        }
        if (isset($components['publicKey'])) {
            $new->publicKey = $components['publicKey'];
        }
        return $new;
    }
    /**
     * Determines which hashing function should be used
     *
     * @access public
     * @param string $hash
     */
    public function withHash($hash)
    {
        throw new UnsupportedOperationException('DH does not use a hash algorithm');
    }
    /**
     * Returns the hash algorithm currently being used
     *
     * @access public
     */
    public function getHash()
    {
        throw new UnsupportedOperationException('DH does not use a hash algorithm');
    }
    /**
    * Returns the parameters
    *
    * A public / private key is only returned if the currently loaded "key" contains an x or y
    value.
    *
    * @see self::getPublicKey()
    * @access public
    * @return mixed
    */
    public function getParameters()
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        $key = $type::saveParameters($this->prime, $this->base);
        return self::load($key, 'PKCS1');
    }
}<?php

/**
 * Pure-PHP implementation of ChaCha20.
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   ChaCha20
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Exception\BadDecryptionException;
/**
 * Pure-PHP implementation of ChaCha20.
 *
 * @package ChaCha20
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class ChaCha20 extends Salsa20
{
    /**
     * The OpenSSL specific name of the cipher
     *
     * @var string
     */
    protected $cipher_name_openssl = 'chacha20';
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        switch ($engine) {
            case self::ENGINE_LIBSODIUM:
                // PHP 7.2.0 (30 Nov 2017) added support for libsodium
                // we could probably make it so that if $this->counter == 0 then the first block would be done with either OpenSSL
                // or PHP and then subsequent blocks would then be done with libsodium but idk - it's not a high priority atm
                // we could also make it so that if $this->counter == 0 and $this->continuousBuffer then do the first string
                // with libsodium and subsequent strings with openssl or pure-PHP but again not a high priority
                return function_exists('sodium_crypto_aead_chacha20poly1305_ietf_encrypt') && $this->key_length == 32 && ($this->usePoly1305 && !isset($this->poly1305Key) && $this->counter == 0 || $this->counter == 1) && !$this->continuousBuffer;
            case self::ENGINE_OPENSSL:
                // OpenSSL 1.1.0 (released 25 Aug 2016) added support for chacha20.
                // PHP didn't support OpenSSL 1.1.0 until 7.0.19 (11 May 2017)
                // if you attempt to provide openssl with a 128 bit key (as opposed to a 256 bit key) openssl will null
                // pad the key to 256 bits and still use the expansion constant for 256-bit keys. the fact that
                // openssl treats the IV as both the counter and nonce, however, let's us use openssl in continuous mode
                // whereas libsodium does not
                if ($this->key_length != 32) {
                    return false;
                }
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Encrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @see self::crypt()
     * @param string $plaintext
     * @return string $ciphertext
     */
    public function encrypt($plaintext)
    {
        $this->setup();
        if ($this->engine == self::ENGINE_LIBSODIUM) {
            return $this->encrypt_with_libsodium($plaintext);
        }
        return parent::encrypt($plaintext);
    }
    /**
    * Decrypts a message.
    *
    * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
    At least if the continuous buffer is disabled.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
    * @see self::crypt()
    * @param string $ciphertext
    * @return string $plaintext
    */
    public function decrypt($ciphertext)
    {
        $this->setup();
        if ($this->engine == self::ENGINE_LIBSODIUM) {
            return $this->decrypt_with_libsodium($ciphertext);
        }
        return parent::decrypt($ciphertext);
    }
    /**
     * Encrypts a message with libsodium
     *
     * @see self::encrypt()
     * @param string $plaintext
     * @return string $text
     */
    private function encrypt_with_libsodium($plaintext)
    {
        $params = [$plaintext, $this->aad, $this->nonce, $this->key];
        $ciphertext = strlen($this->nonce) == 8 ? sodium_crypto_aead_chacha20poly1305_encrypt(...$params) : sodium_crypto_aead_chacha20poly1305_ietf_encrypt(...$params);
        if (!$this->usePoly1305) {
            return \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, strlen($plaintext));
        }
        $newciphertext = \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, strlen($plaintext));
        $this->newtag = $this->usingGeneratedPoly1305Key && strlen($this->nonce) == 12 ? \Phabel\Target\Php80\Polyfill::substr($ciphertext, strlen($plaintext)) : $this->poly1305($newciphertext);
        return $newciphertext;
    }
    /**
     * Decrypts a message with libsodium
     *
     * @see self::decrypt()
     * @param string $ciphertext
     * @return string $text
     */
    private function decrypt_with_libsodium($ciphertext)
    {
        $params = [$ciphertext, $this->aad, $this->nonce, $this->key];
        if (isset($this->poly1305Key)) {
            if ($this->oldtag === false) {
                throw new InsufficientSetupException('Authentication Tag has not been set');
            }
            if ($this->usingGeneratedPoly1305Key && strlen($this->nonce) == 12) {
                $plaintext = sodium_crypto_aead_chacha20poly1305_ietf_decrypt(...$params);
                $this->oldtag = false;
                if ($plaintext === false) {
                    throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
                }
                return $plaintext;
            }
            $newtag = $this->poly1305($ciphertext);
            if ($this->oldtag != \Phabel\Target\Php80\Polyfill::substr($newtag, 0, strlen($this->oldtag))) {
                $this->oldtag = false;
                throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
            }
            $this->oldtag = false;
        }
        $plaintext = strlen($this->nonce) == 8 ? sodium_crypto_aead_chacha20poly1305_encrypt(...$params) : sodium_crypto_aead_chacha20poly1305_ietf_encrypt(...$params);
        return \Phabel\Target\Php80\Polyfill::substr($plaintext, 0, strlen($ciphertext));
    }
    /**
     * Sets the nonce.
     *
     * @param string $nonce
     */
    public function setNonce($nonce)
    {
        if (!is_string($nonce)) {
            throw new \UnexpectedValueException('The nonce should be a string');
        }
        /*
         from https://tools.ietf.org/html/rfc7539#page-7
        
         "Note also that the original ChaCha had a 64-bit nonce and 64-bit
          block count.  We have modified this here to be more consistent with
          recommendations in Section 3.2 of [RFC5116]."
        */
        switch (strlen($nonce)) {
            case 8:
            // 64 bits
            case 12:
                // 96 bits
                break;
            default:
                throw new \LengthException('Nonce of size ' . strlen($nonce) . ' not supported by this algorithm. Only 64-bit nonces or 96-bit nonces are supported');
        }
        $this->nonce = $nonce;
        $this->changed = true;
        $this->setEngine();
    }
    /**
    * Setup the self::ENGINE_INTERNAL $engine
    *
    * (re)init, if necessary, the internal cipher $engine
    *
    * _setup() will be called each time if $changed === true
    typically this happens when using one or more of following public methods:
    *
    * - setKey()
    *
    * - setNonce()
    *
    * - First run of encrypt() / decrypt() with no init-settings
    *
    * @see self::setKey()
    * @see self::setNonce()
    * @see self::disableContinuousBuffer()
    */
    protected function setup()
    {
        if (!$this->changed) {
            return;
        }
        $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'counter' => $this->counter];
        $this->changed = $this->nonIVChanged = false;
        if ($this->nonce === false) {
            throw new InsufficientSetupException('No nonce has been defined');
        }
        if ($this->key === false) {
            throw new InsufficientSetupException('No key has been defined');
        }
        if ($this->usePoly1305 && !isset($this->poly1305Key)) {
            $this->usingGeneratedPoly1305Key = true;
            if ($this->engine == self::ENGINE_LIBSODIUM) {
                return;
            }
            $this->createPoly1305Key();
        }
        $key = $this->key;
        if (strlen($key) == 16) {
            $constant = 'expand 16-byte k';
            $key .= $key;
        } else {
            $constant = 'expand 32-byte k';
        }
        $this->p1 = $constant . $key;
        $this->p2 = $this->nonce;
        if (strlen($this->nonce) == 8) {
            $this->p2 = "\x00\x00\x00\x00" . $this->p2;
        }
    }
    /**
     * The quarterround function
     *
     * @param int $a
     * @param int $b
     * @param int $c
     * @param int $d
     */
    protected static function quarterRound(&$a, &$b, &$c, &$d)
    {
        $a += $b;
        $d = self::leftRotate($d ^ $a, 16);
        $c += $d;
        $b = self::leftRotate($b ^ $c, 12);
        $a += $b;
        $d = self::leftRotate($d ^ $a, 8);
        $c += $d;
        $b = self::leftRotate($b ^ $c, 7);
    }
    /**
     * The doubleround function
     *
     * @param int $x0 (by reference)
     * @param int $x1 (by reference)
     * @param int $x2 (by reference)
     * @param int $x3 (by reference)
     * @param int $x4 (by reference)
     * @param int $x5 (by reference)
     * @param int $x6 (by reference)
     * @param int $x7 (by reference)
     * @param int $x8 (by reference)
     * @param int $x9 (by reference)
     * @param int $x10 (by reference)
     * @param int $x11 (by reference)
     * @param int $x12 (by reference)
     * @param int $x13 (by reference)
     * @param int $x14 (by reference)
     * @param int $x15 (by reference)
     */
    protected static function doubleRound(&$x0, &$x1, &$x2, &$x3, &$x4, &$x5, &$x6, &$x7, &$x8, &$x9, &$x10, &$x11, &$x12, &$x13, &$x14, &$x15)
    {
        // columnRound
        static::quarterRound($x0, $x4, $x8, $x12);
        static::quarterRound($x1, $x5, $x9, $x13);
        static::quarterRound($x2, $x6, $x10, $x14);
        static::quarterRound($x3, $x7, $x11, $x15);
        // rowRound
        static::quarterRound($x0, $x5, $x10, $x15);
        static::quarterRound($x1, $x6, $x11, $x12);
        static::quarterRound($x2, $x7, $x8, $x13);
        static::quarterRound($x3, $x4, $x9, $x14);
    }
    /**
    * The Salsa20 hash function function
    *
    * On my laptop this loop unrolled / function dereferenced version of parent::salsa20 encrypts 1mb of text in
    0.65s vs the 0.85s that it takes with the parent method.
    *
    * If we were free to assume that the host OS would always be 64-bits then the if condition in leftRotate could
    be eliminated and we could knock this done to 0.60s.
    *
    * For comparison purposes, RC4 takes 0.16s and AES in CTR mode with the Eval engine takes 0.48s.
    AES in CTR mode with the PHP engine takes 1.19s. Salsa20 / ChaCha20 do not benefit as much from the Eval
    approach due to the fact that there are a lot less variables to de-reference, fewer loops to unroll, etc
    *
    * @param string $x
    */
    protected static function salsa20($x)
    {
        list(, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15) = unpack('V*', $x);
        $z0 = $x0;
        $z1 = $x1;
        $z2 = $x2;
        $z3 = $x3;
        $z4 = $x4;
        $z5 = $x5;
        $z6 = $x6;
        $z7 = $x7;
        $z8 = $x8;
        $z9 = $x9;
        $z10 = $x10;
        $z11 = $x11;
        $z12 = $x12;
        $z13 = $x13;
        $z14 = $x14;
        $z15 = $x15;
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        $x0 += $z0;
        $x1 += $z1;
        $x2 += $z2;
        $x3 += $z3;
        $x4 += $z4;
        $x5 += $z5;
        $x6 += $z6;
        $x7 += $z7;
        $x8 += $z8;
        $x9 += $z9;
        $x10 += $z10;
        $x11 += $z11;
        $x12 += $z12;
        $x13 += $z13;
        $x14 += $z14;
        $x15 += $z15;
        return pack('V*', $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15);
    }
}<?php

/**
 * Pure-PHP implementation of Blowfish.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $blowfish = new \phpseclib3\Crypt\Blowfish('ctr');
 *
 *    $blowfish->setKey('12345678901234567890123456789012');
 *
 *    $plaintext = str_repeat('a', 1024);
 *
 *    echo $blowfish->decrypt($blowfish->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Blowfish
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
/**
 * Pure-PHP implementation of Blowfish.
 *
 * @package Blowfish
 * @author  Jim Wigginton <terrafrost@php.net>
 * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
 * @access  public
 */
class Blowfish extends BlockCipher
{
    /**
     * Block Length of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
     * @var int
     * @access private
     */
    protected $block_size = 8;
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'blowfish';
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 500;
    /**
     * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
     *
     * S-Box 0
     *
     * @access private
     * @var    array
     */
    private static $sbox0 = [0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0xd95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0xf6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x75372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x4c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x2e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x8ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x8ba4799, 0x6e85076a];
    /**
     * S-Box 1
     *
     * @access private
     * @var    array
     */
    private static $sbox1 = [0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x21ecc5e, 0x9686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0xfd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x43556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x18cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0xe358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x95bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0xc55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0xe1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7];
    /**
     * S-Box 2
     *
     * @access private
     * @var    array
     */
    private static $sbox2 = [0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x3bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0xa2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x4272f70, 0x80bb155c, 0x5282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x7f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0xe12b4c2, 0x2e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0xa476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x6a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0xa121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x9f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0xba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0xde6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x6058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x8fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0];
    /**
     * S-Box 3
     *
     * @access private
     * @var    array
     */
    private static $sbox3 = [0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x22b8b51, 0x96d5ac3a, 0x17da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x3a16125, 0x564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x3563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x9072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x115af84, 0xe1b00428, 0x95983a1d, 0x6b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x11a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0xf91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0xfe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x2fb8a8c, 0x1c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6];
    /**
     * P-Array consists of 18 32-bit subkeys
     *
     * @var array
     * @access private
     */
    private static $parray = [0x243f6a88, 0x85a308d3, 0x13198a2e, 0x3707344, 0xa4093822, 0x299f31d0, 0x82efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b];
    /**
     * The BCTX-working Array
     *
     * Holds the expanded key [p] and the key-depended s-boxes [sb]
     *
     * @var array
     * @access private
     */
    private $bctx;
    /**
     * Holds the last used key
     *
     * @var array
     * @access private
     */
    private $kl;
    /**
     * The Key Length (in bytes)
     * {@internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $Nk
     *    because the encryption / decryption / key schedule creation requires this number and not $key_length.  We could
     *    derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
     *    of that, we'll just precompute it once.}
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 16;
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws \InvalidArgumentException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
     * Sets the key length.
     *
     * Key lengths can be between 32 and 448 bits.
     *
     * @access public
     * @param int $length
     */
    public function setKeyLength($length)
    {
        if ($length < 32 || $length > 448) {
            throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes between 32 and 448 bits are supported');
        }
        $this->key_length = $length >> 3;
        parent::setKeyLength($length);
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        if ($engine == self::ENGINE_OPENSSL) {
            if (version_compare(PHP_VERSION, '5.3.7') < 0 && $this->key_length != 16) {
                return false;
            }
            if ($this->key_length < 16) {
                return false;
            }
            $this->cipher_name_openssl_ecb = 'bf-ecb';
            $this->cipher_name_openssl = 'bf-' . $this->openssl_translate_mode();
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Setup the key (expansion)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
     * @access private
     */
    protected function setupKey()
    {
        if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
            // already expanded
            return;
        }
        $this->kl = ['key' => $this->key];
        /* key-expanding p[] and S-Box building sb[] */
        $this->bctx = ['p' => [], 'sb' => [self::$sbox0, self::$sbox1, self::$sbox2, self::$sbox3]];
        // unpack binary string in unsigned chars
        $key = array_values(unpack('C*', $this->key));
        $keyl = count($key);
        for ($j = 0, $i = 0; $i < 18; ++$i) {
            // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
            for ($data = 0, $k = 0; $k < 4; ++$k) {
                $data = $data << 8 | $key[$j];
                if (++$j >= $keyl) {
                    $j = 0;
                }
            }
            $this->bctx['p'][] = self::$parray[$i] ^ $data;
        }
        // encrypt the zero-string, replace P1 and P2 with the encrypted data,
        // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
        $data = "\x00\x00\x00\x00\x00\x00\x00\x00";
        for ($i = 0; $i < 18; $i += 2) {
            list($l, $r) = array_values(unpack('N*', $data = $this->encryptBlock($data)));
            $this->bctx['p'][$i] = $l;
            $this->bctx['p'][$i + 1] = $r;
        }
        for ($i = 0; $i < 4; ++$i) {
            for ($j = 0; $j < 256; $j += 2) {
                list($l, $r) = array_values(unpack('N*', $data = $this->encryptBlock($data)));
                $this->bctx['sb'][$i][$j] = $l;
                $this->bctx['sb'][$i][$j + 1] = $r;
            }
        }
    }
    /**
     * Encrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        $p = $this->bctx['p'];
        // extract($this->bctx['sb'], EXTR_PREFIX_ALL, 'sb'); // slower
        $sb_0 = $this->bctx['sb'][0];
        $sb_1 = $this->bctx['sb'][1];
        $sb_2 = $this->bctx['sb'][2];
        $sb_3 = $this->bctx['sb'][3];
        $in = unpack('N*', $in);
        $l = $in[1];
        $r = $in[2];
        for ($i = 0; $i < 16; $i += 2) {
            $l ^= $p[$i];
            $r ^= self::safe_intval((self::safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^ $sb_2[$l >> 8 & 0xff]) + $sb_3[$l & 0xff]);
            $r ^= $p[$i + 1];
            $l ^= self::safe_intval((self::safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^ $sb_2[$r >> 8 & 0xff]) + $sb_3[$r & 0xff]);
        }
        return pack('N*', $r ^ $p[17], $l ^ $p[16]);
    }
    /**
     * Decrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        $p = $this->bctx['p'];
        $sb_0 = $this->bctx['sb'][0];
        $sb_1 = $this->bctx['sb'][1];
        $sb_2 = $this->bctx['sb'][2];
        $sb_3 = $this->bctx['sb'][3];
        $in = unpack('N*', $in);
        $l = $in[1];
        $r = $in[2];
        for ($i = 17; $i > 2; $i -= 2) {
            $l ^= $p[$i];
            $r ^= self::safe_intval((self::safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^ $sb_2[$l >> 8 & 0xff]) + $sb_3[$l & 0xff]);
            $r ^= $p[$i - 1];
            $l ^= self::safe_intval((self::safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^ $sb_2[$r >> 8 & 0xff]) + $sb_3[$r & 0xff]);
        }
        return pack('N*', $r ^ $p[0], $l ^ $p[1]);
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        $p = $this->bctx['p'];
        $init_crypt = '
            static $sb_0, $sb_1, $sb_2, $sb_3;
            if (!$sb_0) {
                $sb_0 = $this->bctx["sb"][0];
                $sb_1 = $this->bctx["sb"][1];
                $sb_2 = $this->bctx["sb"][2];
                $sb_3 = $this->bctx["sb"][3];
            }
        ';
        $safeint = self::safe_intval_inline();
        // Generating encrypt code:
        $encrypt_block = '
            $in = unpack("N*", $in);
            $l = $in[1];
            $r = $in[2];
        ';
        for ($i = 0; $i < 16; $i += 2) {
            $encrypt_block .= '
                $l^= ' . $p[$i] . ';
                $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
                      $sb_2[$l >>  8 & 0xff]) +
                      $sb_3[$l       & 0xff]') . ';

                $r^= ' . $p[$i + 1] . ';
                $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . '  ^
                      $sb_2[$r >>  8 & 0xff]) +
                      $sb_3[$r       & 0xff]') . ';
            ';
        }
        $encrypt_block .= '
            $in = pack("N*",
                $r ^ ' . $p[17] . ',
                $l ^ ' . $p[16] . '
            );
        ';
        // Generating decrypt code:
        $decrypt_block = '
            $in = unpack("N*", $in);
            $l = $in[1];
            $r = $in[2];
        ';
        for ($i = 17; $i > 2; $i -= 2) {
            $decrypt_block .= '
                $l^= ' . $p[$i] . ';
                $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
                      $sb_2[$l >>  8 & 0xff]) +
                      $sb_3[$l       & 0xff]') . ';

                $r^= ' . $p[$i - 1] . ';
                $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
                      $sb_2[$r >>  8 & 0xff]) +
                      $sb_3[$r       & 0xff]') . ';
            ';
        }
        $decrypt_block .= '
            $in = pack("N*",
                $r ^ ' . $p[0] . ',
                $l ^ ' . $p[1] . '
            );
        ';
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => $init_crypt, 'init_encrypt' => '', 'init_decrypt' => '', 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block]);
    }
}<?php

/**
 * Random Number Generator
 *
 * PHP version 5
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    echo bin2hex(\phpseclib3\Crypt\Random::string(8));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Random
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

/**
 * Pure-PHP Random Number Generator
 *
 * @package Random
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Random
{
    /**
    * Generate a random string.
    *
    * Although microoptimizations are generally discouraged as they impair readability this function is ripe with
    microoptimizations because this function has the potential of being called a huge number of times.
    eg. for RSA key generation.
    *
    * @param int $length
    * @throws \RuntimeException if a symmetric cipher is needed but not loaded
    * @return string
    */
    public static function string($length)
    {
        if (!$length) {
            return '';
        }
        try {
            return \random_bytes($length);
        } catch (\Exception $e) {
            // random_compat will throw an Exception, which in PHP 5 does not implement Throwable
        } catch (\Throwable $e) {
            // If a sufficient source of randomness is unavailable, random_bytes() will throw an
            // object that implements the Throwable interface (Exception, TypeError, Error).
            // We don't actually need to do anything here. The string() method should just continue
            // as normal. Note, however, that if we don't have a sufficient source of randomness for
            // random_bytes(), most of the other calls here will fail too, so we'll end up using
            // the PHP implementation.
        }
        // at this point we have no choice but to use a pure-PHP CSPRNG
        // cascade entropy across multiple PHP instances by fixing the session and collecting all
        // environmental variables, including the previous session data and the current session
        // data.
        //
        // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
        // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
        // PHP isn't low level to be able to use those as sources and on a web server there's not likely
        // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
        // however, a ton of people visiting the website. obviously you don't want to base your seeding
        // solely on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
        // by the user and (2) this isn't just looking at the data sent by the current user - it's based
        // on the data sent by all users. one user requests the page and a hash of their info is saved.
        // another user visits the page and the serialization of their data is utilized along with the
        // server environment stuff and a hash of the previous http request data (which itself utilizes
        // a hash of the session data before that). certainly an attacker should be assumed to have
        // full control over his own http requests. he, however, is not going to have control over
        // everyone's http requests.
        static $crypto = false, $v;
        if ($crypto === false) {
            // save old session data
            $old_session_id = \Phabel\Target\Php80\Polyfill::session_id();
            $old_use_cookies = ini_get('session.use_cookies');
            $old_session_cache_limiter = \Phabel\Target\Php80\Polyfill::session_cache_limiter();
            $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
            if ($old_session_id != '') {
                session_write_close();
            }
            \Phabel\Target\Php80\Polyfill::session_id(1);
            ini_set('session.use_cookies', 0);
            \Phabel\Target\Php80\Polyfill::session_cache_limiter('');
            session_start();
            $v = (isset($_SERVER) ? self::safe_serialize($_SERVER) : '') . (isset($_POST) ? self::safe_serialize($_POST) : '') . (isset($_GET) ? self::safe_serialize($_GET) : '') . (isset($_COOKIE) ? self::safe_serialize($_COOKIE) : '') . self::safe_serialize($GLOBALS) . self::safe_serialize($_SESSION) . self::safe_serialize($_OLD_SESSION);
            $v = $seed = $_SESSION['seed'] = sha1($v, true);
            if (!isset($_SESSION['count'])) {
                $_SESSION['count'] = 0;
            }
            $_SESSION['count']++;
            session_write_close();
            // restore old session data
            if ($old_session_id != '') {
                \Phabel\Target\Php80\Polyfill::session_id($old_session_id);
                session_start();
                ini_set('session.use_cookies', $old_use_cookies);
                \Phabel\Target\Php80\Polyfill::session_cache_limiter($old_session_cache_limiter);
            } else {
                if ($_OLD_SESSION !== false) {
                    $_SESSION = $_OLD_SESSION;
                    unset($_OLD_SESSION);
                } else {
                    unset($_SESSION);
                }
            }
            // in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
            // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
            // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
            // original hash and the current hash. we'll be emulating that. for more info see the following URL:
            //
            // http://tools.ietf.org/html/rfc4253#section-7.2
            //
            // see the is_string($crypto) part for an example of how to expand the keys
            $key = sha1($seed . 'A', true);
            $iv = sha1($seed . 'C', true);
            // ciphers are used as per the nist.gov link below. also, see this link:
            //
            // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
            switch (true) {
                case class_exists('\\phpseclib3\\Crypt\\AES'):
                    $crypto = new AES('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\Twofish'):
                    $crypto = new Twofish('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\Blowfish'):
                    $crypto = new Blowfish('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\TripleDES'):
                    $crypto = new TripleDES('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\DES'):
                    $crypto = new DES('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\RC4'):
                    $crypto = new RC4();
                    break;
                default:
                    throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded');
            }
            $crypto->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $crypto->getKeyLength() >> 3));
            $crypto->setIV(\Phabel\Target\Php80\Polyfill::substr($iv, 0, $crypto->getBlockLength() >> 3));
            $crypto->enableContinuousBuffer();
        }
        //return $crypto->encrypt(str_repeat("\0", $length));
        // the following is based off of ANSI X9.31:
        //
        // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
        //
        // OpenSSL uses that same standard for it's random numbers:
        //
        // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
        // (do a search for "ANS X9.31 A.2.4")
        $result = '';
        while (strlen($result) < $length) {
            $i = $crypto->encrypt(microtime());
            // strlen(microtime()) == 21
            $r = $crypto->encrypt($i ^ $v);
            // strlen($v) == 20
            $v = $crypto->encrypt($r ^ $i);
            // strlen($r) == 20
            $result .= $r;
        }
        return \Phabel\Target\Php80\Polyfill::substr($result, 0, $length);
    }
    /**
     * Safely serialize variables
     *
     * If a class has a private __sleep() it'll emit a warning
     * @return mixed
     * @param mixed $arr
     */
    private static function safe_serialize(&$arr)
    {
        if (is_object($arr)) {
            return '';
        }
        if (!is_array($arr)) {
            return serialize($arr);
        }
        // prevent circular array recursion
        if (isset($arr['__phpseclib_marker'])) {
            return '';
        }
        $safearr = [];
        $arr['__phpseclib_marker'] = true;
        foreach (array_keys($arr) as $key) {
            // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
            if ($key !== '__phpseclib_marker') {
                $safearr[$key] = self::safe_serialize($arr[$key]);
            }
        }
        unset($arr['__phpseclib_marker']);
        return serialize($safearr);
    }
}<?php

/**
 * Pure-PHP implementation of Salsa20.
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Salsa20
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\StreamCipher;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Exception\BadDecryptionException;
use phpseclib3\Common\Functions\Strings;
/**
 * Pure-PHP implementation of Salsa20.
 *
 * @package Salsa20
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Salsa20 extends StreamCipher
{
    /**
     * Part 1 of the state
     *
     * @var string|false
     */
    protected $p1 = false;
    /**
     * Part 2 of the state
     *
     * @var string|false
     */
    protected $p2 = false;
    /**
     * Key Length (in bytes)
     *
     * @var int
     */
    protected $key_length = 32;
    // = 256 bits
    /**
     * @access private
     * @see \phpseclib3\Crypt\Salsa20::crypt()
     */
    const ENCRYPT = 0;
    /**
     * @access private
     * @see \phpseclib3\Crypt\Salsa20::crypt()
     */
    const DECRYPT = 1;
    /**
     * Encryption buffer for continuous mode
     *
     * @var array
     */
    protected $enbuffer;
    /**
     * Decryption buffer for continuous mode
     *
     * @var array
     */
    protected $debuffer;
    /**
     * Counter
     *
     * @var int
     */
    protected $counter = 0;
    /**
     * Using Generated Poly1305 Key
     *
     * @var boolean
     */
    protected $usingGeneratedPoly1305Key = false;
    /**
     * Salsa20 uses a nonce
     *
     * @return bool
     */
    public function usesNonce()
    {
        return true;
    }
    /**
     * Sets the key.
     *
     * @param string $key
     * @throws \LengthException if the key length isn't supported
     */
    public function setKey($key)
    {
        switch (strlen($key)) {
            case 16:
            case 32:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 32 are supported');
        }
        parent::setKey($key);
    }
    /**
     * Sets the nonce.
     *
     * @param string $nonce
     */
    public function setNonce($nonce)
    {
        if (strlen($nonce) != 8) {
            throw new \LengthException('Nonce of size ' . strlen($key) . ' not supported by this algorithm. Only an 64-bit nonce is supported');
        }
        $this->nonce = $nonce;
        $this->changed = true;
        $this->setEngine();
    }
    /**
     * Sets the counter.
     *
     * @param int $counter
     */
    public function setCounter($counter)
    {
        $this->counter = $counter;
        $this->setEngine();
    }
    /**
     * Creates a Poly1305 key using the method discussed in RFC8439
     *
     * See https://tools.ietf.org/html/rfc8439#section-2.6.1
     */
    protected function createPoly1305Key()
    {
        if ($this->nonce === false) {
            throw new InsufficientSetupException('No nonce has been defined');
        }
        if ($this->key === false) {
            throw new InsufficientSetupException('No key has been defined');
        }
        $c = clone $this;
        $c->setCounter(0);
        $c->usePoly1305 = false;
        $block = $c->encrypt(str_repeat("\x00", 256));
        $this->setPoly1305Key(\Phabel\Target\Php80\Polyfill::substr($block, 0, 32));
        if ($this->counter == 0) {
            $this->counter++;
        }
    }
    /**
    * Setup the self::ENGINE_INTERNAL $engine
    *
    * (re)init, if necessary, the internal cipher $engine
    *
    * _setup() will be called each time if $changed === true
    typically this happens when using one or more of following public methods:
    *
    * - setKey()
    *
    * - setNonce()
    *
    * - First run of encrypt() / decrypt() with no init-settings
    *
    * @see self::setKey()
    * @see self::setNonce()
    * @see self::disableContinuousBuffer()
    */
    protected function setup()
    {
        if (!$this->changed) {
            return;
        }
        $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'counter' => $this->counter];
        $this->changed = $this->nonIVChanged = false;
        if ($this->nonce === false) {
            throw new InsufficientSetupException('No nonce has been defined');
        }
        if ($this->key === false) {
            throw new InsufficientSetupException('No key has been defined');
        }
        if ($this->usePoly1305 && !isset($this->poly1305Key)) {
            $this->usingGeneratedPoly1305Key = true;
            $this->createPoly1305Key();
        }
        $key = $this->key;
        if (strlen($key) == 16) {
            $constant = 'expand 16-byte k';
            $key .= $key;
        } else {
            $constant = 'expand 32-byte k';
        }
        $this->p1 = \Phabel\Target\Php80\Polyfill::substr($constant, 0, 4) . \Phabel\Target\Php80\Polyfill::substr($key, 0, 16) . \Phabel\Target\Php80\Polyfill::substr($constant, 4, 4) . $this->nonce . "\x00\x00\x00\x00";
        $this->p2 = \Phabel\Target\Php80\Polyfill::substr($constant, 8, 4) . \Phabel\Target\Php80\Polyfill::substr($key, 16, 16) . \Phabel\Target\Php80\Polyfill::substr($constant, 12, 4);
    }
    /**
     * Setup the key (expansion)
     */
    protected function setupKey()
    {
        // Salsa20 does not utilize this method
    }
    /**
     * Encrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @see self::crypt()
     * @param string $plaintext
     * @return string $ciphertext
     */
    public function encrypt($plaintext)
    {
        $ciphertext = $this->crypt($plaintext, self::ENCRYPT);
        if (isset($this->poly1305Key)) {
            $this->newtag = $this->poly1305($ciphertext);
        }
        return $ciphertext;
    }
    /**
    * Decrypts a message.
    *
    * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
    At least if the continuous buffer is disabled.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
    * @see self::crypt()
    * @param string $ciphertext
    * @return string $plaintext
    */
    public function decrypt($ciphertext)
    {
        if (isset($this->poly1305Key)) {
            if ($this->oldtag === false) {
                throw new InsufficientSetupException('Authentication Tag has not been set');
            }
            $newtag = $this->poly1305($ciphertext);
            if ($this->oldtag != \Phabel\Target\Php80\Polyfill::substr($newtag, 0, strlen($this->oldtag))) {
                $this->oldtag = false;
                throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
            }
            $this->oldtag = false;
        }
        return $this->crypt($ciphertext, self::DECRYPT);
    }
    /**
     * Encrypts a block
     *
     * @param string $in
     */
    protected function encryptBlock($in)
    {
        // Salsa20 does not utilize this method
    }
    /**
     * Decrypts a block
     *
     * @param string $in
     */
    protected function decryptBlock($in)
    {
        // Salsa20 does not utilize this method
    }
    /**
     * Encrypts or decrypts a message.
     *
     * @see self::encrypt()
     * @see self::decrypt()
     * @param string $text
     * @param int $mode
     * @return string $text
     */
    private function crypt($text, $mode)
    {
        $this->setup();
        if (!$this->continuousBuffer) {
            if ($this->engine == self::ENGINE_OPENSSL) {
                $iv = pack('V', $this->counter) . $this->p2;
                return openssl_encrypt($text, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA, $iv);
            }
            $i = $this->counter;
            $blocks = str_split($text, 64);
            foreach ($blocks as &$block) {
                $block ^= static::salsa20($this->p1 . pack('V', $i++) . $this->p2);
            }
            return implode('', $blocks);
        }
        if ($mode == self::ENCRYPT) {
            $buffer =& $this->enbuffer;
        } else {
            $buffer =& $this->debuffer;
        }
        if (strlen($buffer['ciphertext'])) {
            $ciphertext = $text ^ Strings::shift($buffer['ciphertext'], strlen($text));
            $text = \Phabel\Target\Php80\Polyfill::substr($text, strlen($ciphertext));
            if (!strlen($text)) {
                return $ciphertext;
            }
        }
        $overflow = strlen($text) % 64;
        // & 0x3F
        if ($overflow) {
            $text2 = Strings::pop($text, $overflow);
            if ($this->engine == self::ENGINE_OPENSSL) {
                $iv = pack('V', $buffer['counter']) . $this->p2;
                // at this point $text should be a multiple of 64
                $buffer['counter'] += (strlen($text) >> 6) + 1;
                // ie. divide by 64
                $encrypted = openssl_encrypt($text . str_repeat("\x00", 64), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA, $iv);
                $temp = Strings::pop($encrypted, 64);
            } else {
                $blocks = str_split($text, 64);
                if (strlen($text)) {
                    foreach ($blocks as &$block) {
                        $block ^= static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2);
                    }
                }
                $encrypted = implode('', $blocks);
                $temp = static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2);
            }
            $ciphertext .= $encrypted . ($text2 ^ $temp);
            $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($temp, $overflow);
        } elseif (!strlen($buffer['ciphertext'])) {
            if ($this->engine == self::ENGINE_OPENSSL) {
                $iv = pack('V', $buffer['counter']) . $this->p2;
                $buffer['counter'] += strlen($text) >> 6;
                $ciphertext .= openssl_encrypt($text, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA, $iv);
            } else {
                $blocks = str_split($text, 64);
                foreach ($blocks as &$block) {
                    $block ^= static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2);
                }
                $ciphertext .= implode('', $blocks);
            }
        }
        return $ciphertext;
    }
    /**
     * Left Rotate
     *
     * @param int $x
     * @param int $n
     * @return int
     */
    protected static function leftRotate($x, $n)
    {
        $r1 = $x << $n;
        if (PHP_INT_SIZE == 8) {
            $r1 &= 0xffffffff;
            $r2 = ($x & 0xffffffff) >> 32 - $n;
        } else {
            $r2 = $x >> 32 - $n;
            $r2 &= (1 << $n) - 1;
        }
        return $r1 | $r2;
    }
    /**
     * The quarterround function
     *
     * @param int $a
     * @param int $b
     * @param int $c
     * @param int $d
     */
    protected static function quarterRound(&$a, &$b, &$c, &$d)
    {
        $b ^= self::leftRotate($a + $d, 7);
        $c ^= self::leftRotate($b + $a, 9);
        $d ^= self::leftRotate($c + $b, 13);
        $a ^= self::leftRotate($d + $c, 18);
    }
    /**
     * The doubleround function
     *
     * @param int $x0 (by reference)
     * @param int $x1 (by reference)
     * @param int $x2 (by reference)
     * @param int $x3 (by reference)
     * @param int $x4 (by reference)
     * @param int $x5 (by reference)
     * @param int $x6 (by reference)
     * @param int $x7 (by reference)
     * @param int $x8 (by reference)
     * @param int $x9 (by reference)
     * @param int $x10 (by reference)
     * @param int $x11 (by reference)
     * @param int $x12 (by reference)
     * @param int $x13 (by reference)
     * @param int $x14 (by reference)
     * @param int $x15 (by reference)
     */
    protected static function doubleRound(&$x0, &$x1, &$x2, &$x3, &$x4, &$x5, &$x6, &$x7, &$x8, &$x9, &$x10, &$x11, &$x12, &$x13, &$x14, &$x15)
    {
        // columnRound
        static::quarterRound($x0, $x4, $x8, $x12);
        static::quarterRound($x5, $x9, $x13, $x1);
        static::quarterRound($x10, $x14, $x2, $x6);
        static::quarterRound($x15, $x3, $x7, $x11);
        // rowRound
        static::quarterRound($x0, $x1, $x2, $x3);
        static::quarterRound($x5, $x6, $x7, $x4);
        static::quarterRound($x10, $x11, $x8, $x9);
        static::quarterRound($x15, $x12, $x13, $x14);
    }
    /**
     * The Salsa20 hash function function
     *
     * @param string $x
     */
    protected static function salsa20($x)
    {
        $z = $x = unpack('V*', $x);
        for ($i = 0; $i < 10; $i++) {
            static::doubleRound(...$z);
        }
        for ($i = 1; $i <= 16; $i++) {
            $x[$i] += $z[$i];
        }
        return pack('V*', ...$x);
    }
    /**
     * Calculates Poly1305 MAC
     *
     * @see self::decrypt()
     * @see self::encrypt()
     * @access private
     * @param string $ciphertext
     * @return string
     */
    protected function poly1305($ciphertext)
    {
        if (!$this->usingGeneratedPoly1305Key) {
            return parent::poly1305($this->aad . $ciphertext);
        } else {
            /*
            sodium_crypto_aead_chacha20poly1305_encrypt does not calculate the poly1305 tag
            the same way sodium_crypto_aead_chacha20poly1305_ietf_encrypt does. you can see
            how the latter encrypts it in Salsa20::encrypt(). here's how the former encrypts
            it:
            
            $this->newtag = $this->poly1305(
                $this->aad .
                pack('V', strlen($this->aad)) . "\0\0\0\0" .
                $ciphertext .
                pack('V', strlen($ciphertext)) . "\0\0\0\0"
            );
            
            phpseclib opts to use the IETF construction, even when the nonce is 64-bits
            instead of 96-bits
            */
            return parent::poly1305(self::nullPad128($this->aad) . self::nullPad128($ciphertext) . pack('V', strlen($this->aad)) . "\x00\x00\x00\x00" . pack('V', strlen($ciphertext)) . "\x00\x00\x00\x00");
        }
    }
}<?php

/**
 * Pure-PHP implementation of SFTP.
 *
 * PHP version 5
 *
 * Supports SFTPv2/3/4/5/6. Defaults to v3.
 *
 * The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $sftp = new \phpseclib3\Net\SFTP('www.domain.tld');
 *    if (!$sftp->login('username', 'password')) {
 *        exit('Login Failed');
 *    }
 *
 *    echo $sftp->pwd() . "\r\n";
 *    $sftp->put('filename.ext', 'hello, world!');
 *    print_r($sftp->nlist());
 * ?>
 * </code>
 *
 * @category  Net
 * @package   SFTP
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Net;

use phpseclib3\Exception\FileNotFoundException;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\System\SSH\Agent;
/**
 * Pure-PHP implementations of SFTP.
 *
 * @package SFTP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class SFTP extends SSH2
{
    /**
     * SFTP channel constant
     *
     * \phpseclib3\Net\SSH2::exec() uses 0 and \phpseclib3\Net\SSH2::read() / \phpseclib3\Net\SSH2::write() use 1.
     *
     * @see \phpseclib3\Net\SSH2::send_channel_packet()
     * @see \phpseclib3\Net\SSH2::get_channel_packet()
     * @access private
     */
    const CHANNEL = 0x100;
    /**
     * Reads data from a local file.
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    const SOURCE_LOCAL_FILE = 1;
    /**
     * Reads data from a string.
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    // this value isn't really used anymore but i'm keeping it reserved for historical reasons
    const SOURCE_STRING = 2;
    /**
     * Reads data from callback:
     * function callback($length) returns string to proceed, null for EOF
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    const SOURCE_CALLBACK = 16;
    /**
     * Resumes an upload
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    const RESUME = 4;
    /**
     * Append a local file to an already existing remote file
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    const RESUME_START = 8;
    /**
     * Packet Types
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $packet_types = [];
    /**
     * Status Codes
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $status_codes = [];
    /**
     * The Request ID
     *
     * The request ID exists in the off chance that a packet is sent out-of-order.  Of course, this library doesn't support
     * concurrent actions, so it's somewhat academic, here.
     *
     * @var boolean
     * @see self::_send_sftp_packet()
     * @access private
     */
    private $use_request_id = false;
    /**
     * The Packet Type
     *
     * The request ID exists in the off chance that a packet is sent out-of-order.  Of course, this library doesn't support
     * concurrent actions, so it's somewhat academic, here.
     *
     * @var int
     * @see self::_get_sftp_packet()
     * @access private
     */
    private $packet_type = -1;
    /**
     * Packet Buffer
     *
     * @var string
     * @see self::_get_sftp_packet()
     * @access private
     */
    private $packet_buffer = '';
    /**
     * Extensions supported by the server
     *
     * @var array
     * @see self::_initChannel()
     * @access private
     */
    private $extensions = [];
    /**
     * Server SFTP version
     *
     * @var int
     * @see self::_initChannel()
     * @access private
     */
    private $version;
    /**
     * Default Server SFTP version
     *
     * @var int
     * @see self::_initChannel()
     * @access private
     */
    private $defaultVersion;
    /**
     * Preferred SFTP version
     *
     * @var int
     * @see self::_initChannel()
     * @access private
     */
    private $preferredVersion = 3;
    /**
     * Current working directory
     *
     * @var string
     * @see self::realpath()
     * @see self::chdir()
     * @access private
     */
    private $pwd = false;
    /**
     * Packet Type Log
     *
     * @see self::getLog()
     * @var array
     * @access private
     */
    private $packet_type_log = [];
    /**
     * Packet Log
     *
     * @see self::getLog()
     * @var array
     * @access private
     */
    private $packet_log = [];
    /**
     * Error information
     *
     * @see self::getSFTPErrors()
     * @see self::getLastSFTPError()
     * @var array
     * @access private
     */
    private $sftp_errors = [];
    /**
     * Stat Cache
     *
     * Rather than always having to open a directory and close it immediately there after to see if a file is a directory
     * we'll cache the results.
     *
     * @see self::_update_stat_cache()
     * @see self::_remove_from_stat_cache()
     * @see self::_query_stat_cache()
     * @var array
     * @access private
     */
    private $stat_cache = [];
    /**
     * Max SFTP Packet Size
     *
     * @see self::__construct()
     * @see self::get()
     * @var array
     * @access private
     */
    private $max_sftp_packet;
    /**
     * Stat Cache Flag
     *
     * @see self::disableStatCache()
     * @see self::enableStatCache()
     * @var bool
     * @access private
     */
    private $use_stat_cache = true;
    /**
     * Sort Options
     *
     * @see self::_comparator()
     * @see self::setListOrder()
     * @var array
     * @access private
     */
    protected $sortOptions = [];
    /**
     * Canonicalization Flag
     *
     * Determines whether or not paths should be canonicalized before being
     * passed on to the remote server.
     *
     * @see self::enablePathCanonicalization()
     * @see self::disablePathCanonicalization()
     * @see self::realpath()
     * @var bool
     * @access private
     */
    private $canonicalize_paths = true;
    /**
     * Request Buffers
     *
     * @see self::_get_sftp_packet()
     * @var array
     * @access private
     */
    private $requestBuffer = [];
    /**
     * Preserve timestamps on file downloads / uploads
     *
     * @see self::get()
     * @see self::put()
     * @var bool
     * @access private
     */
    private $preserveTime = false;
    /**
     * Arbitrary Length Packets Flag
     *
     * Determines whether or not packets of any length should be allowed,
     * in cases where the server chooses the packet length (such as
     * directory listings). By default, packets are only allowed to be
     * 256 * 1024 bytes (SFTP_MAX_MSG_LENGTH from OpenSSH's sftp-common.h)
     *
     * @see self::enableArbitraryLengthPackets()
     * @see self::_get_sftp_packet()
     * @var bool
     * @access private
     */
    private $allow_arbitrary_length_packets = false;
    /**
     * Was the last packet due to the channels being closed or not?
     *
     * @see self::get()
     * @see self::get_sftp_packet()
     * @var bool
     * @access private
     */
    private $channel_close = false;
    /**
     * Has the SFTP channel been partially negotiated?
     *
     * @var bool
     * @access private
     */
    private $partial_init = false;
    /**
     * Default Constructor.
     *
     * Connects to an SFTP server
     *
     * @param string $host
     * @param int $port
     * @param int $timeout
     * @return \phpseclib3\Net\SFTP
     * @access public
     */
    public function __construct($host, $port = 22, $timeout = 10)
    {
        parent::__construct($host, $port, $timeout);
        $this->max_sftp_packet = 1 << 15;
        $this->packet_types = [1 => 'NET_SFTP_INIT', 2 => 'NET_SFTP_VERSION', 3 => 'NET_SFTP_OPEN', 4 => 'NET_SFTP_CLOSE', 5 => 'NET_SFTP_READ', 6 => 'NET_SFTP_WRITE', 7 => 'NET_SFTP_LSTAT', 9 => 'NET_SFTP_SETSTAT', 10 => 'NET_SFTP_FSETSTAT', 11 => 'NET_SFTP_OPENDIR', 12 => 'NET_SFTP_READDIR', 13 => 'NET_SFTP_REMOVE', 14 => 'NET_SFTP_MKDIR', 15 => 'NET_SFTP_RMDIR', 16 => 'NET_SFTP_REALPATH', 17 => 'NET_SFTP_STAT', 18 => 'NET_SFTP_RENAME', 19 => 'NET_SFTP_READLINK', 20 => 'NET_SFTP_SYMLINK', 21 => 'NET_SFTP_LINK', 101 => 'NET_SFTP_STATUS', 102 => 'NET_SFTP_HANDLE', 103 => 'NET_SFTP_DATA', 104 => 'NET_SFTP_NAME', 105 => 'NET_SFTP_ATTRS', 200 => 'NET_SFTP_EXTENDED'];
        $this->status_codes = [0 => 'NET_SFTP_STATUS_OK', 1 => 'NET_SFTP_STATUS_EOF', 2 => 'NET_SFTP_STATUS_NO_SUCH_FILE', 3 => 'NET_SFTP_STATUS_PERMISSION_DENIED', 4 => 'NET_SFTP_STATUS_FAILURE', 5 => 'NET_SFTP_STATUS_BAD_MESSAGE', 6 => 'NET_SFTP_STATUS_NO_CONNECTION', 7 => 'NET_SFTP_STATUS_CONNECTION_LOST', 8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED', 9 => 'NET_SFTP_STATUS_INVALID_HANDLE', 10 => 'NET_SFTP_STATUS_NO_SUCH_PATH', 11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS', 12 => 'NET_SFTP_STATUS_WRITE_PROTECT', 13 => 'NET_SFTP_STATUS_NO_MEDIA', 14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM', 15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED', 16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL', 17 => 'NET_SFTP_STATUS_LOCK_CONFLICT', 18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY', 19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY', 20 => 'NET_SFTP_STATUS_INVALID_FILENAME', 21 => 'NET_SFTP_STATUS_LINK_LOOP', 22 => 'NET_SFTP_STATUS_CANNOT_DELETE', 23 => 'NET_SFTP_STATUS_INVALID_PARAMETER', 24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY', 25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT', 26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED', 27 => 'NET_SFTP_STATUS_DELETE_PENDING', 28 => 'NET_SFTP_STATUS_FILE_CORRUPT', 29 => 'NET_SFTP_STATUS_OWNER_INVALID', 30 => 'NET_SFTP_STATUS_GROUP_INVALID', 31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'];
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
        // the order, in this case, matters quite a lot - see \phpseclib3\Net\SFTP::_parseAttributes() to understand why
        $this->attributes = [
            0x1 => 'NET_SFTP_ATTR_SIZE',
            0x2 => 'NET_SFTP_ATTR_UIDGID',
            // defined in SFTPv3, removed in SFTPv4+
            0x80 => 'NET_SFTP_ATTR_OWNERGROUP',
            // defined in SFTPv4+
            0x4 => 'NET_SFTP_ATTR_PERMISSIONS',
            0x8 => 'NET_SFTP_ATTR_ACCESSTIME',
            0x10 => 'NET_SFTP_ATTR_CREATETIME',
            // SFTPv4+
            0x20 => 'NET_SFTP_ATTR_MODIFYTIME',
            0x40 => 'NET_SFTP_ATTR_ACL',
            0x100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
            0x200 => 'NET_SFTP_ATTR_BITS',
            // SFTPv5+
            0x400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE',
            // SFTPv6+
            0x800 => 'NET_SFTP_ATTR_TEXT_HINT',
            0x1000 => 'NET_SFTP_ATTR_MIME_TYPE',
            0x2000 => 'NET_SFTP_ATTR_LINK_COUNT',
            0x4000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
            0x8000 => 'NET_SFTP_ATTR_CTIME',
            // 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
            // yields inconsistent behavior depending on how php is compiled.  so we left shift -1 (which, in
            // two's compliment, consists of all 1 bits) by 31.  on 64-bit systems this'll yield 0xFFFFFFFF80000000.
            // that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
            -1 << 31 & 0xffffffff => 'NET_SFTP_ATTR_EXTENDED',
        ];
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
        // the flag definitions change somewhat in SFTPv5+.  if SFTPv5+ support is added to this library, maybe name
        // the array for that $this->open5_flags and similarly alter the constant names.
        $this->open_flags = [0x1 => 'NET_SFTP_OPEN_READ', 0x2 => 'NET_SFTP_OPEN_WRITE', 0x4 => 'NET_SFTP_OPEN_APPEND', 0x8 => 'NET_SFTP_OPEN_CREATE', 0x10 => 'NET_SFTP_OPEN_TRUNCATE', 0x20 => 'NET_SFTP_OPEN_EXCL', 0x40 => 'NET_SFTP_OPEN_TEXT'];
        // SFTPv5+ changed the flags up:
        // https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
        $this->open_flags5 = [
            // when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
            0x0 => 'NET_SFTP_OPEN_CREATE_NEW',
            0x1 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
            0x2 => 'NET_SFTP_OPEN_OPEN_EXISTING',
            0x3 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
            0x4 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
            // the rest of the flags are not supported
            0x8 => 'NET_SFTP_OPEN_APPEND_DATA',
            // "the offset field of SS_FXP_WRITE requests is ignored"
            0x10 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
            0x20 => 'NET_SFTP_OPEN_TEXT_MODE',
            0x40 => 'NET_SFTP_OPEN_BLOCK_READ',
            0x80 => 'NET_SFTP_OPEN_BLOCK_WRITE',
            0x100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
            0x200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
            0x400 => 'NET_SFTP_OPEN_NOFOLLOW',
            0x800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
            0x1000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
            0x2000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
            0x4000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
            0x8000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
        ];
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
        // see \phpseclib3\Net\SFTP::_parseLongname() for an explanation
        $this->file_types = [
            1 => 'NET_SFTP_TYPE_REGULAR',
            2 => 'NET_SFTP_TYPE_DIRECTORY',
            3 => 'NET_SFTP_TYPE_SYMLINK',
            4 => 'NET_SFTP_TYPE_SPECIAL',
            5 => 'NET_SFTP_TYPE_UNKNOWN',
            // the following types were first defined for use in SFTPv5+
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
            6 => 'NET_SFTP_TYPE_SOCKET',
            7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
            8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
            9 => 'NET_SFTP_TYPE_FIFO',
        ];
        $this->define_array($this->packet_types, $this->status_codes, $this->attributes, $this->open_flags, $this->open_flags5, $this->file_types);
        if (!defined('NET_SFTP_QUEUE_SIZE')) {
            define('NET_SFTP_QUEUE_SIZE', 32);
        }
        if (!defined('NET_SFTP_UPLOAD_QUEUE_SIZE')) {
            define('NET_SFTP_UPLOAD_QUEUE_SIZE', 1024);
        }
    }
    /**
     * Check a few things before SFTP functions are called
     *
     * @return bool
     * @access public
     */
    private function precheck()
    {
        if (!($this->bitmap & SSH2::MASK_LOGIN)) {
            return false;
        }
        if ($this->pwd === false) {
            return $this->init_sftp_connection();
        }
        return true;
    }
    /**
     * Partially initialize an SFTP connection
     *
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    private function partial_init_sftp_connection()
    {
        $this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL, $this->window_size, 0x4000);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
        $response = $this->get_channel_packet(self::CHANNEL, true);
        if ($response === true && $this->isTimeout()) {
            return false;
        }
        $packet = Strings::packSSH2('CNsbs', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], 'subsystem', true, 'sftp');
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
        $response = $this->get_channel_packet(self::CHANNEL, true);
        if ($response === false) {
            // from PuTTY's psftp.exe
            $command = 'test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server
test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server
exec sftp-server';
            // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
            // is redundant
            $packet = Strings::packSSH2('CNsCs', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], 'exec', 1, $command);
            $this->send_binary_packet($packet);
            $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
            $response = $this->get_channel_packet(self::CHANNEL, true);
            if ($response === false) {
                return false;
            }
        } else {
            if ($response === true && $this->isTimeout()) {
                return false;
            }
        }
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
        $this->send_sftp_packet(NET_SFTP_INIT, "\x00\x00\x00\x03");
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_VERSION) {
            throw new \UnexpectedValueException('Expected NET_SFTP_VERSION. Got packet type: ' . $this->packet_type);
        }
        $this->use_request_id = true;
        list($this->defaultVersion) = Strings::unpackSSH2('N', $response);
        while (!empty($response)) {
            list($key, $value) = Strings::unpackSSH2('ss', $response);
            $this->extensions[$key] = $value;
        }
        $this->partial_init = true;
        return true;
    }
    /**
     * (Re)initializes the SFTP channel
     *
     * @return bool
     * @access private
     */
    private function init_sftp_connection()
    {
        if (!$this->partial_init && !$this->partial_init_sftp_connection()) {
            return false;
        }
        /*
         A Note on SFTPv4/5/6 support:
         <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.1> states the following:
        
         "If the client wishes to interoperate with servers that support noncontiguous version
          numbers it SHOULD send '3'"
        
         Given that the server only sends its version number after the client has already done so, the above
         seems to be suggesting that v3 should be the default version.  This makes sense given that v3 is the
         most popular.
        
         <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.5> states the following;
        
         "If the server did not send the "versions" extension, or the version-from-list was not included, the
          server MAY send a status response describing the failure, but MUST then close the channel without
          processing any further requests."
        
         So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
         a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4?  If it only implements
         v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
         in draft-ietf-secsh-filexfer-13 would be quite impossible.  As such, what \phpseclib3\Net\SFTP would do is close the
         channel and reopen it with a new and updated SSH_FXP_INIT packet.
        */
        $this->version = $this->defaultVersion;
        if (isset($this->extensions['versions']) && (!$this->preferredVersion || $this->preferredVersion != $this->version)) {
            $versions = explode(',', $this->extensions['versions']);
            $supported = [6, 5, 4];
            if ($this->preferredVersion) {
                $supported = array_diff($supported, [$this->preferredVersion]);
                array_unshift($supported, $this->preferredVersion);
            }
            foreach ($supported as $ver) {
                if (in_array($ver, $versions)) {
                    if ($ver === $this->version) {
                        break;
                    }
                    $this->version = (int) $ver;
                    $packet = Strings::packSSH2('ss', 'version-select', "{$ver}");
                    $this->send_sftp_packet(NET_SFTP_EXTENDED, $packet);
                    $response = $this->get_sftp_packet();
                    if ($this->packet_type != NET_SFTP_STATUS) {
                        throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
                    }
                    list($status) = Strings::unpackSSH2('N', $response);
                    if ($status != NET_SFTP_STATUS_OK) {
                        $this->logError($response, $status);
                        throw new \UnexpectedValueException('Expected NET_SFTP_STATUS_OK.  Got ' . $status);
                    }
                    break;
                }
            }
        }
        /*
         SFTPv4+ defines a 'newline' extension.  SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com',
         however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's
         not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for
         one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
         'newline@vandyke.com' would.
        */
        /*
        if (isset($this->extensions['newline@vandyke.com'])) {
            $this->extensions['newline'] = $this->extensions['newline@vandyke.com'];
            unset($this->extensions['newline@vandyke.com']);
        }
        */
        if ($this->version < 2 || $this->version > 6) {
            return false;
        }
        $this->pwd = true;
        $this->pwd = $this->realpath('.');
        $this->update_stat_cache($this->pwd, []);
        return true;
    }
    /**
     * Disable the stat cache
     *
     * @access public
     */
    public function disableStatCache()
    {
        $this->use_stat_cache = false;
    }
    /**
     * Enable the stat cache
     *
     * @access public
     */
    public function enableStatCache()
    {
        $this->use_stat_cache = true;
    }
    /**
     * Clear the stat cache
     *
     * @access public
     */
    public function clearStatCache()
    {
        $this->stat_cache = [];
    }
    /**
     * Enable path canonicalization
     *
     * @access public
     */
    public function enablePathCanonicalization()
    {
        $this->canonicalize_paths = true;
    }
    /**
     * Enable path canonicalization
     *
     * @access public
     */
    public function disablePathCanonicalization()
    {
        $this->canonicalize_paths = false;
    }
    /**
     * Enable arbitrary length packets
     *
     * @access public
     */
    public function enableArbitraryLengthPackets()
    {
        $this->allow_arbitrary_length_packets = true;
    }
    /**
     * Disable arbitrary length packets
     *
     * @access public
     */
    public function disableArbitraryLengthPackets()
    {
        $this->allow_arbitrary_length_packets = false;
    }
    /**
     * Returns the current directory name
     *
     * @return mixed
     * @access public
     */
    public function pwd()
    {
        if (!$this->precheck()) {
            return false;
        }
        return $this->pwd;
    }
    /**
     * Logs errors
     *
     * @param string $response
     * @param int $status
     * @access private
     */
    private function logError($response, $status = -1)
    {
        if ($status == -1) {
            list($status) = Strings::unpackSSH2('N', $response);
        }
        $error = $this->status_codes[$status];
        if ($this->version > 2) {
            list($message) = Strings::unpackSSH2('s', $response);
            $this->sftp_errors[] = "{$error}: {$message}";
        } else {
            $this->sftp_errors[] = $error;
        }
    }
    /**
    * Canonicalize the Server-Side Path Name
    *
    * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it.  Returns
    the absolute (canonicalized) path.
    *
    * If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is.
    *
    * @see self::chdir()
    * @see self::disablePathCanonicalization()
    * @param string $path
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @return mixed
    * @access public
    */
    public function realpath($path)
    {
        if ($this->precheck() === false) {
            return false;
        }
        if (!$this->canonicalize_paths) {
            return $path;
        }
        if ($this->pwd === true) {
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
            $this->send_sftp_packet(NET_SFTP_REALPATH, Strings::packSSH2('s', $path));
            $response = $this->get_sftp_packet();
            switch ($this->packet_type) {
                case NET_SFTP_NAME:
                    // although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following
                    // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
                    // at is the first part and that part is defined the same in SFTP versions 3 through 6.
                    list(, $filename) = Strings::unpackSSH2('Ns', $response);
                    return $filename;
                case NET_SFTP_STATUS:
                    $this->logError($response);
                    return false;
                default:
                    throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
            }
        }
        if (!strlen($path) || $path[0] != '/') {
            $path = $this->pwd . '/' . $path;
        }
        $path = explode('/', $path);
        $new = [];
        foreach ($path as $dir) {
            if (!strlen($dir)) {
                continue;
            }
            switch ($dir) {
                case '..':
                    array_pop($new);
                case '.':
                    break;
                default:
                    $new[] = $dir;
            }
        }
        return '/' . implode('/', $new);
    }
    /**
     * Changes the current directory
     *
     * @param string $dir
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    public function chdir($dir)
    {
        if (!$this->precheck()) {
            return false;
        }
        // assume current dir if $dir is empty
        if ($dir === '') {
            $dir = './';
            // suffix a slash if needed
        } elseif ($dir[strlen($dir) - 1] != '/') {
            $dir .= '/';
        }
        $dir = $this->realpath($dir);
        // confirm that $dir is, in fact, a valid directory
        if ($this->use_stat_cache && is_array($this->query_stat_cache($dir))) {
            $this->pwd = $dir;
            return true;
        }
        // we could do a stat on the alleged $dir to see if it's a directory but that doesn't tell us
        // the currently logged in user has the appropriate permissions or not. maybe you could see if
        // the file's uid / gid match the currently logged in user's uid / gid but how there's no easy
        // way to get those with SFTP
        $this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir));
        // see \phpseclib3\Net\SFTP::nlist() for a more thorough explanation of the following
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                $handle = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUSGot packet type: ' . $this->packet_type);
        }
        if (!$this->close_handle($handle)) {
            return false;
        }
        $this->update_stat_cache($dir, []);
        $this->pwd = $dir;
        return true;
    }
    /**
     * Returns a list of files in the given directory
     *
     * @param string $dir
     * @param bool $recursive
     * @return mixed
     * @access public
     */
    public function nlist($dir = '.', $recursive = false)
    {
        return $this->nlist_helper($dir, $recursive, '');
    }
    /**
     * Helper method for nlist
     *
     * @param string $dir
     * @param bool $recursive
     * @param string $relativeDir
     * @return mixed
     * @access private
     */
    private function nlist_helper($dir, $recursive, $relativeDir)
    {
        $files = $this->readlist($dir, false);
        if (!$recursive || $files === false) {
            return $files;
        }
        $result = [];
        foreach ($files as $value) {
            if ($value == '.' || $value == '..') {
                $result[] = $relativeDir . $value;
                continue;
            }
            if (is_array($this->query_stat_cache($this->realpath($dir . '/' . $value)))) {
                $temp = $this->nlist_helper($dir . '/' . $value, true, $relativeDir . $value . '/');
                $temp = is_array($temp) ? $temp : [];
                $result = array_merge($result, $temp);
            } else {
                $result[] = $relativeDir . $value;
            }
        }
        return $result;
    }
    /**
     * Returns a detailed list of files in the given directory
     *
     * @param string $dir
     * @param bool $recursive
     * @return mixed
     * @access public
     */
    public function rawlist($dir = '.', $recursive = false)
    {
        $files = $this->readlist($dir, true);
        if (!$recursive || $files === false) {
            return $files;
        }
        static $depth = 0;
        foreach ($files as $key => $value) {
            if ($depth != 0 && $key == '..') {
                unset($files[$key]);
                continue;
            }
            $is_directory = false;
            if ($key != '.' && $key != '..') {
                if ($this->use_stat_cache) {
                    $is_directory = is_array($this->query_stat_cache($this->realpath($dir . '/' . $key)));
                } else {
                    $stat = $this->lstat($dir . '/' . $key);
                    $is_directory = $stat && $stat['type'] === NET_SFTP_TYPE_DIRECTORY;
                }
            }
            if ($is_directory) {
                $depth++;
                $files[$key] = $this->rawlist($dir . '/' . $key, true);
                $depth--;
            } else {
                $files[$key] = (object) $value;
            }
        }
        return $files;
    }
    /**
     * Reads a list, be it detailed or not, of files in the given directory
     *
     * @param string $dir
     * @param bool $raw
     * @return mixed
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @access private
     */
    private function readlist($dir, $raw = true)
    {
        if (!$this->precheck()) {
            return false;
        }
        $dir = $this->realpath($dir . '/');
        if ($dir === false) {
            return false;
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
        $this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir));
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2
                // since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that
                // represent the length of the string and leave it at that
                $handle = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        $this->update_stat_cache($dir, []);
        $contents = [];
        while (true) {
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
            // why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
            // SSH_MSG_CHANNEL_DATA messages is not known to me.
            $this->send_sftp_packet(NET_SFTP_READDIR, Strings::packSSH2('s', $handle));
            $response = $this->get_sftp_packet();
            switch ($this->packet_type) {
                case NET_SFTP_NAME:
                    list($count) = Strings::unpackSSH2('N', $response);
                    for ($i = 0; $i < $count; $i++) {
                        list($shortname) = Strings::unpackSSH2('s', $response);
                        // SFTPv4 "removed the long filename from the names structure-- it can now be
                        //         built from information available in the attrs structure."
                        if ($this->version < 4) {
                            list($longname) = Strings::unpackSSH2('s', $response);
                        }
                        $attributes = $this->parseAttributes($response);
                        if (!isset($attributes['type']) && $this->version < 4) {
                            $fileType = $this->parseLongname($longname);
                            if ($fileType) {
                                $attributes['type'] = $fileType;
                            }
                        }
                        $contents[$shortname] = $attributes + ['filename' => $shortname];
                        if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) {
                            $this->update_stat_cache($dir . '/' . $shortname, []);
                        } else {
                            if ($shortname == '..') {
                                $temp = $this->realpath($dir . '/..') . '/.';
                            } else {
                                $temp = $dir . '/' . $shortname;
                            }
                            $this->update_stat_cache($temp, (object) ['lstat' => $attributes]);
                        }
                        // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
                        // final SSH_FXP_STATUS packet should tell us that, already.
                    }
                    break;
                case NET_SFTP_STATUS:
                    list($status) = Strings::unpackSSH2('N', $response);
                    if ($status != NET_SFTP_STATUS_EOF) {
                        $this->logError($response, $status);
                        return false;
                    }
                    break 2;
                default:
                    throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
            }
        }
        if (!$this->close_handle($handle)) {
            return false;
        }
        if (count($this->sortOptions)) {
            uasort($contents, [&$this, 'comparator']);
        }
        return $raw ? $contents : array_map('strval', array_keys($contents));
    }
    /**
     * Compares two rawlist entries using parameters set by setListOrder()
     *
     * Intended for use with uasort()
     *
     * @param array $a
     * @param array $b
     * @return int
     * @access private
     */
    private function comparator($a, $b)
    {
        switch (true) {
            case $a['filename'] === '.' || $b['filename'] === '.':
                if ($a['filename'] === $b['filename']) {
                    return 0;
                }
                return $a['filename'] === '.' ? -1 : 1;
            case $a['filename'] === '..' || $b['filename'] === '..':
                if ($a['filename'] === $b['filename']) {
                    return 0;
                }
                return $a['filename'] === '..' ? -1 : 1;
            case isset($a['type']) && $a['type'] === NET_SFTP_TYPE_DIRECTORY:
                if (!isset($b['type'])) {
                    return 1;
                }
                if ($b['type'] !== $a['type']) {
                    return -1;
                }
                break;
            case isset($b['type']) && $b['type'] === NET_SFTP_TYPE_DIRECTORY:
                return 1;
        }
        foreach ($this->sortOptions as $sort => $order) {
            if (!isset($a[$sort]) || !isset($b[$sort])) {
                if (isset($a[$sort])) {
                    return -1;
                }
                if (isset($b[$sort])) {
                    return 1;
                }
                return 0;
            }
            switch ($sort) {
                case 'filename':
                    $result = strcasecmp($a['filename'], $b['filename']);
                    if ($result) {
                        return $order === SORT_DESC ? -$result : $result;
                    }
                    break;
                case 'mode':
                    $a[$sort] &= 07777;
                    $b[$sort] &= 07777;
                default:
                    if ($a[$sort] === $b[$sort]) {
                        break;
                    }
                    return $order === SORT_ASC ? $a[$sort] - $b[$sort] : $b[$sort] - $a[$sort];
            }
        }
    }
    /**
    * Defines how nlist() and rawlist() will be sorted - if at all.
    *
    * If sorting is enabled directories and files will be sorted independently with
    directories appearing before files in the resultant array that is returned.
    *
    * Any parameter returned by stat is a valid sort parameter for this function.
    Filename comparisons are case insensitive.
    *
    * Examples:
    *
    * $sftp->setListOrder('filename', SORT_ASC);
    $sftp->setListOrder('size', SORT_DESC, 'filename', SORT_ASC);
    $sftp->setListOrder(true);
    Separates directories from files but doesn't do any sorting beyond that
    $sftp->setListOrder();
    Don't do any sort of sorting
    *
    * @param string[] ...$args
    * @access public
    */
    public function setListOrder(...$args)
    {
        $this->sortOptions = [];
        if (empty($args)) {
            return;
        }
        $len = count($args) & 0x7ffffffe;
        for ($i = 0; $i < $len; $i += 2) {
            $this->sortOptions[$args[$i]] = $args[$i + 1];
        }
        if (!count($this->sortOptions)) {
            $this->sortOptions = ['bogus' => true];
        }
    }
    /**
     * Save files / directories to cache
     *
     * @param string $path
     * @param mixed $value
     * @access private
     */
    private function update_stat_cache($path, $value)
    {
        if ($this->use_stat_cache === false) {
            return;
        }
        // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/'))
        $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
        $temp =& $this->stat_cache;
        $max = count($dirs) - 1;
        foreach ($dirs as $i => $dir) {
            // if $temp is an object that means one of two things.
            //  1. a file was deleted and changed to a directory behind phpseclib's back
            //  2. it's a symlink. when lstat is done it's unclear what it's a symlink to
            if (is_object($temp)) {
                $temp = [];
            }
            if (!isset($temp[$dir])) {
                $temp[$dir] = [];
            }
            if ($i === $max) {
                if (is_object($temp[$dir]) && is_object($value)) {
                    if (!isset($value->stat) && isset($temp[$dir]->stat)) {
                        $value->stat = $temp[$dir]->stat;
                    }
                    if (!isset($value->lstat) && isset($temp[$dir]->lstat)) {
                        $value->lstat = $temp[$dir]->lstat;
                    }
                }
                $temp[$dir] = $value;
                break;
            }
            $temp =& $temp[$dir];
        }
    }
    /**
     * Remove files / directories from cache
     *
     * @param string $path
     * @return bool
     * @access private
     */
    private function remove_from_stat_cache($path)
    {
        $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
        $temp =& $this->stat_cache;
        $max = count($dirs) - 1;
        foreach ($dirs as $i => $dir) {
            if (!is_array($temp)) {
                return false;
            }
            if ($i === $max) {
                unset($temp[$dir]);
                return true;
            }
            if (!isset($temp[$dir])) {
                return false;
            }
            $temp =& $temp[$dir];
        }
    }
    /**
     * Checks cache for path
     *
     * Mainly used by file_exists
     *
     * @param string $path
     * @return mixed
     * @access private
     */
    private function query_stat_cache($path)
    {
        $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
        $temp =& $this->stat_cache;
        foreach ($dirs as $dir) {
            if (!is_array($temp)) {
                return null;
            }
            if (!isset($temp[$dir])) {
                return null;
            }
            $temp =& $temp[$dir];
        }
        return $temp;
    }
    /**
     * Returns general information about a file.
     *
     * Returns an array on success and false otherwise.
     *
     * @param string $filename
     * @return mixed
     * @access public
     */
    public function stat($filename)
    {
        if (!$this->precheck()) {
            return false;
        }
        $filename = $this->realpath($filename);
        if ($filename === false) {
            return false;
        }
        if ($this->use_stat_cache) {
            $result = $this->query_stat_cache($filename);
            if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) {
                return $result['.']->stat;
            }
            if (is_object($result) && isset($result->stat)) {
                return $result->stat;
            }
        }
        $stat = $this->stat_helper($filename, NET_SFTP_STAT);
        if ($stat === false) {
            $this->remove_from_stat_cache($filename);
            return false;
        }
        if (isset($stat['type'])) {
            if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
                $filename .= '/.';
            }
            $this->update_stat_cache($filename, (object) ['stat' => $stat]);
            return $stat;
        }
        $pwd = $this->pwd;
        $stat['type'] = $this->chdir($filename) ? NET_SFTP_TYPE_DIRECTORY : NET_SFTP_TYPE_REGULAR;
        $this->pwd = $pwd;
        if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
            $filename .= '/.';
        }
        $this->update_stat_cache($filename, (object) ['stat' => $stat]);
        return $stat;
    }
    /**
     * Returns general information about a file or symbolic link.
     *
     * Returns an array on success and false otherwise.
     *
     * @param string $filename
     * @return mixed
     * @access public
     */
    public function lstat($filename)
    {
        if (!$this->precheck()) {
            return false;
        }
        $filename = $this->realpath($filename);
        if ($filename === false) {
            return false;
        }
        if ($this->use_stat_cache) {
            $result = $this->query_stat_cache($filename);
            if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) {
                return $result['.']->lstat;
            }
            if (is_object($result) && isset($result->lstat)) {
                return $result->lstat;
            }
        }
        $lstat = $this->stat_helper($filename, NET_SFTP_LSTAT);
        if ($lstat === false) {
            $this->remove_from_stat_cache($filename);
            return false;
        }
        if (isset($lstat['type'])) {
            if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
                $filename .= '/.';
            }
            $this->update_stat_cache($filename, (object) ['lstat' => $lstat]);
            return $lstat;
        }
        $stat = $this->stat_helper($filename, NET_SFTP_STAT);
        if ($lstat != $stat) {
            $lstat = array_merge($lstat, ['type' => NET_SFTP_TYPE_SYMLINK]);
            $this->update_stat_cache($filename, (object) ['lstat' => $lstat]);
            return $stat;
        }
        $pwd = $this->pwd;
        $lstat['type'] = $this->chdir($filename) ? NET_SFTP_TYPE_DIRECTORY : NET_SFTP_TYPE_REGULAR;
        $this->pwd = $pwd;
        if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
            $filename .= '/.';
        }
        $this->update_stat_cache($filename, (object) ['lstat' => $lstat]);
        return $lstat;
    }
    /**
    * Returns general information about a file or symbolic link
    *
    * Determines information without calling \phpseclib3\Net\SFTP::realpath().
    The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT.
    *
    * @param string $filename
    * @param int $type
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @return mixed
    * @access private
    */
    private function stat_helper($filename, $type)
    {
        // SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
        $packet = Strings::packSSH2('s', $filename);
        $this->send_sftp_packet($type, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_ATTRS:
                return $this->parseAttributes($response);
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
        }
        throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
    }
    /**
     * Truncates a file to a given length
     *
     * @param string $filename
     * @param int $new_size
     * @return bool
     * @access public
     */
    public function truncate($filename, $new_size)
    {
        $attr = Strings::packSSH2('NQ', NET_SFTP_ATTR_SIZE, $new_size);
        return $this->setstat($filename, $attr, false);
    }
    /**
     * Sets access and modification time of file.
     *
     * If the file does not exist, it will be created.
     *
     * @param string $filename
     * @param int $time
     * @param int $atime
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    public function touch($filename, $time = null, $atime = null)
    {
        if (!$this->precheck()) {
            return false;
        }
        $filename = $this->realpath($filename);
        if ($filename === false) {
            return false;
        }
        if (!isset($time)) {
            $time = time();
        }
        if (!isset($atime)) {
            $atime = $time;
        }
        $attr = $this->version < 4 ? pack('N3', NET_SFTP_ATTR_ACCESSTIME, $atime, $time) : Strings::packSSH2('NQ2', NET_SFTP_ATTR_ACCESSTIME | NET_SFTP_ATTR_MODIFYTIME, $atime, $time);
        $packet = Strings::packSSH2('s', $filename);
        $packet .= $this->version >= 5 ? pack('N2', 0, NET_SFTP_OPEN_OPEN_EXISTING) : pack('N', NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL);
        $packet .= $attr;
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                return $this->close_handle(\Phabel\Target\Php80\Polyfill::substr($response, 4));
            case NET_SFTP_STATUS:
                $this->logError($response);
                break;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        return $this->setstat($filename, $attr, false);
    }
    /**
    * Changes file or directory owner
    *
    * $uid should be an int for SFTPv3 and a string for SFTPv4+. Ideally the string
    would be of the form "user@dns_domain" but it does not need to be.
    `$sftp->getSupportedVersions()['version']` will return the specific version
    that's being used.
    *
    * Returns true on success or false on error.
    *
    * @param string $filename
    * @param (int | string) $uid
    * @param bool $recursive
    * @return bool
    * @access public
    */
    public function chown($filename, $uid, $recursive = false)
    {
        /*
          quoting <https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.5>,
        
          "To avoid a representation that is tied to a particular underlying
           implementation at the client or server, the use of UTF-8 strings has
           been chosen.  The string should be of the form "user@dns_domain".
           This will allow for a client and server that do not use the same
           local representation the ability to translate to a common syntax that
           can be interpreted by both.  In the case where there is no
           translation available to the client or server, the attribute value
           must be constructed without the "@"."
        
          phpseclib _could_ auto append the dns_domain to $uid BUT what if it shouldn't
          have one? phpseclib would have no way of knowing so rather than guess phpseclib
          will just use whatever value the user provided
        */
        $attr = $this->version < 4 ? pack('N3', NET_SFTP_ATTR_UIDGID, $uid, -1) : Strings::packSSH2('Nss', NET_SFTP_ATTR_OWNERGROUP, $uid, '');
        return $this->setstat($filename, $attr, $recursive);
    }
    /**
    * Changes file or directory group
    *
    * $gid should be an int for SFTPv3 and a string for SFTPv4+. Ideally the string
    would be of the form "user@dns_domain" but it does not need to be.
    `$sftp->getSupportedVersions()['version']` will return the specific version
    that's being used.
    *
    * Returns true on success or false on error.
    *
    * @param string $filename
    * @param (int | string) $gid
    * @param bool $recursive
    * @return bool
    * @access public
    */
    public function chgrp($filename, $gid, $recursive = false)
    {
        $attr = $this->version < 4 ? pack('N3', NET_SFTP_ATTR_UIDGID, $gid, -1) : Strings::packSSH2('Nss', NET_SFTP_ATTR_OWNERGROUP, '', $gid);
        return $this->setstat($filename, $attr, $recursive);
    }
    /**
    * Set permissions on a file.
    *
    * Returns the new file permissions on success or false on error.
    If $recursive is true than this just returns true or false.
    *
    * @param int $mode
    * @param string $filename
    * @param bool $recursive
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @return mixed
    * @access public
    */
    public function chmod($mode, $filename, $recursive = false)
    {
        if (is_string($mode) && is_int($filename)) {
            $temp = $mode;
            $mode = $filename;
            $filename = $temp;
        }
        $attr = pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
        if (!$this->setstat($filename, $attr, $recursive)) {
            return false;
        }
        if ($recursive) {
            return true;
        }
        $filename = $this->realpath($filename);
        // rather than return what the permissions *should* be, we'll return what they actually are.  this will also
        // tell us if the file actually exists.
        // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
        $packet = pack('Na*', strlen($filename), $filename);
        $this->send_sftp_packet(NET_SFTP_STAT, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_ATTRS:
                $attrs = $this->parseAttributes($response);
                return $attrs['mode'];
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
        }
        throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
    }
    /**
     * Sets information about a file
     *
     * @param string $filename
     * @param string $attr
     * @param bool $recursive
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access private
     */
    private function setstat($filename, $attr, $recursive)
    {
        if (!$this->precheck()) {
            return false;
        }
        $filename = $this->realpath($filename);
        if ($filename === false) {
            return false;
        }
        $this->remove_from_stat_cache($filename);
        if ($recursive) {
            $i = 0;
            $result = $this->setstat_recursive($filename, $attr, $i);
            $this->read_put_responses($i);
            return $result;
        }
        $packet = Strings::packSSH2('s', $filename);
        $packet .= $this->version >= 4 ? pack('a*Ca*', \Phabel\Target\Php80\Polyfill::substr($attr, 0, 4), NET_SFTP_TYPE_UNKNOWN, \Phabel\Target\Php80\Polyfill::substr($attr, 4)) : $attr;
        $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet);
        /*
         "Because some systems must use separate system calls to set various attributes, it is possible that a failure
          response will be returned, but yet some of the attributes may be have been successfully modified.  If possible,
          servers SHOULD avoid this situation; however, clients MUST be aware that this is possible."
        
          -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6
        */
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        return true;
    }
    /**
     * Recursively sets information on directories on the SFTP server
     *
     * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
     *
     * @param string $path
     * @param string $attr
     * @param int $i
     * @return bool
     * @access private
     */
    private function setstat_recursive($path, $attr, &$i)
    {
        if (!$this->read_put_responses($i)) {
            return false;
        }
        $i = 0;
        $entries = $this->readlist($path, true);
        if ($entries === false) {
            return $this->setstat($path, $attr, false);
        }
        // normally $entries would have at least . and .. but it might not if the directories
        // permissions didn't allow reading
        if (empty($entries)) {
            return false;
        }
        unset($entries['.'], $entries['..']);
        foreach ($entries as $filename => $props) {
            if (!isset($props['type'])) {
                return false;
            }
            $temp = $path . '/' . $filename;
            if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) {
                if (!$this->setstat_recursive($temp, $attr, $i)) {
                    return false;
                }
            } else {
                $packet = Strings::packSSH2('s', $temp);
                $packet .= $this->version >= 4 ? pack('Ca*', NET_SFTP_TYPE_UNKNOWN, $attr) : $attr;
                $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet);
                $i++;
                if ($i >= NET_SFTP_QUEUE_SIZE) {
                    if (!$this->read_put_responses($i)) {
                        return false;
                    }
                    $i = 0;
                }
            }
        }
        $packet = Strings::packSSH2('s', $path);
        $packet .= $this->version >= 4 ? pack('Ca*', NET_SFTP_TYPE_UNKNOWN, $attr) : $atr;
        $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet);
        $i++;
        if ($i >= NET_SFTP_QUEUE_SIZE) {
            if (!$this->read_put_responses($i)) {
                return false;
            }
            $i = 0;
        }
        return true;
    }
    /**
     * Return the target of a symbolic link
     *
     * @param string $link
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return mixed
     * @access public
     */
    public function readlink($link)
    {
        if (!$this->precheck()) {
            return false;
        }
        $link = $this->realpath($link);
        $this->send_sftp_packet(NET_SFTP_READLINK, Strings::packSSH2('s', $link));
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_NAME:
                break;
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($count) = Strings::unpackSSH2('N', $response);
        // the file isn't a symlink
        if (!$count) {
            return false;
        }
        list($filename) = Strings::unpackSSH2('s', $response);
        return $filename;
    }
    /**
     * Create a symlink
     *
     * symlink() creates a symbolic link to the existing target with the specified name link.
     *
     * @param string $target
     * @param string $link
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    public function symlink($target, $link)
    {
        if (!$this->precheck()) {
            return false;
        }
        //$target = $this->realpath($target);
        $link = $this->realpath($link);
        /* quoting https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-12.1 :
        
                   Changed the SYMLINK packet to be LINK and give it the ability to
                   create hard links.  Also change it's packet number because many
                   implementation implemented SYMLINK with the arguments reversed.
                   Hopefully the new argument names make it clear which way is which.
                */
        if ($this->version == 6) {
            $type = NET_SFTP_LINK;
            $packet = Strings::packSSH2('ssC', $link, $target, 1);
        } else {
            $type = NET_SFTP_SYMLINK;
            /* quoting http://bxr.su/OpenBSD/usr.bin/ssh/PROTOCOL#347 :
            
                           3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
            
                           When OpenSSH's sftp-server was implemented, the order of the arguments
                           to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
                           the reversal was not noticed until the server was widely deployed. Since
                           fixing this to follow the specification would cause incompatibility, the
                           current order was retained. For correct operation, clients should send
                           SSH_FXP_SYMLINK as follows:
            
                               uint32      id
                               string      targetpath
                               string      linkpath */
            $packet = \Phabel\Target\Php80\Polyfill::substr($this->server_identifier, 0, 15) == 'SSH-2.0-OpenSSH' ? Strings::packSSH2('ss', $target, $link) : Strings::packSSH2('ss', $link, $target);
        }
        $this->send_sftp_packet($type, $packet);
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        return true;
    }
    /**
     * Creates a directory.
     *
     * @param string $dir
     * @param int $mode
     * @param bool $recursive
     * @return bool
     * @access public
     */
    public function mkdir($dir, $mode = -1, $recursive = false)
    {
        if (!$this->precheck()) {
            return false;
        }
        $dir = $this->realpath($dir);
        if ($recursive) {
            $dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir));
            if (empty($dirs[0])) {
                array_shift($dirs);
                $dirs[0] = '/' . $dirs[0];
            }
            for ($i = 0; $i < count($dirs); $i++) {
                $temp = array_slice($dirs, 0, $i + 1);
                $temp = implode('/', $temp);
                $result = $this->mkdir_helper($temp, $mode);
            }
            return $result;
        }
        return $this->mkdir_helper($dir, $mode);
    }
    /**
     * Helper function for directory creation
     *
     * @param string $dir
     * @param int $mode
     * @return bool
     * @access private
     */
    private function mkdir_helper($dir, $mode)
    {
        // send SSH_FXP_MKDIR without any attributes (that's what the \0\0\0\0 is doing)
        $this->send_sftp_packet(NET_SFTP_MKDIR, Strings::packSSH2('s', $dir) . "\x00\x00\x00\x00");
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        if ($mode !== -1) {
            $this->chmod($mode, $dir);
        }
        return true;
    }
    /**
     * Removes a directory.
     *
     * @param string $dir
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    public function rmdir($dir)
    {
        if (!$this->precheck()) {
            return false;
        }
        $dir = $this->realpath($dir);
        if ($dir === false) {
            return false;
        }
        $this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $dir));
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
            $this->logError($response, $status);
            return false;
        }
        $this->remove_from_stat_cache($dir);
        // the following will do a soft delete, which would be useful if you deleted a file
        // and then tried to do a stat on the deleted file. the above, in contrast, does
        // a hard delete
        //$this->update_stat_cache($dir, false);
        return true;
    }
    /**
    * Uploads a file to the SFTP server.
    *
    * By default, \phpseclib3\Net\SFTP::put() does not read from the local filesystem.  $data is dumped directly into $remote_file.
    So, for example, if you set $data to 'filename.ext' and then do \phpseclib3\Net\SFTP::get(), you will get a file, twelve bytes
    long, containing 'filename.ext' as its contents.
    *
    * Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior.  With self::SOURCE_LOCAL_FILE, $remote_file will
    contain as many bytes as filename.ext does on your local filesystem.  If your filename.ext is 1MB then that is how
    large $remote_file will be, as well.
    *
    * Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number
    of bytes to return, and returns a string if there is some data or null if there is no more data
    *
    * If $data is a resource then it'll be used as a resource instead.
    *
    * Currently, only binary mode is supported.  As such, if the line endings need to be adjusted, you will need to take
    care of that, yourself.
    *
    * $mode can take an additional two parameters - self::RESUME and self::RESUME_START. These are bitwise AND'd with
    $mode. So if you want to resume upload of a 300mb file on the local file system you'd set $mode to the following:
    *
    * self::SOURCE_LOCAL_FILE | self::RESUME
    *
    * If you wanted to simply append the full contents of a local file to the full contents of a remote file you'd replace
    self::RESUME with self::RESUME_START.
    *
    * If $mode & (self::RESUME | self::RESUME_START) then self::RESUME_START will be assumed.
    *
    * $start and $local_start give you more fine grained control over this process and take precident over self::RESUME
    when they're non-negative. ie. $start could let you write at the end of a file (like self::RESUME) or in the middle
    of one. $local_start could let you start your reading from the end of a file (like self::RESUME_START) or in the
    middle of one.
    *
    * Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE.
    *
    * {@internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib3\Net\SFTP::setMode().}
    *
    * @param string $remote_file
    * @param (string | resource) $data
    * @param int $mode
    * @param int $start
    * @param int $local_start
    * @param (callable | null) $progressCallback
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @throws \BadFunctionCallException if you're uploading via a callback and the callback function is invalid
    * @throws \phpseclib3\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
    * @return bool
    * @access public
    */
    public function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null)
    {
        if (!$this->precheck()) {
            return false;
        }
        $remote_file = $this->realpath($remote_file);
        if ($remote_file === false) {
            return false;
        }
        $this->remove_from_stat_cache($remote_file);
        if ($this->version >= 5) {
            $flags = NET_SFTP_OPEN_OPEN_OR_CREATE;
        } else {
            $flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE;
            // according to the SFTP specs, NET_SFTP_OPEN_APPEND should "force all writes to append data at the end of the file."
            // in practice, it doesn't seem to do that.
            //$flags|= ($mode & self::RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE;
        }
        if ($start >= 0) {
            $offset = $start;
        } elseif ($mode & self::RESUME) {
            // if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called
            $size = $this->stat($remote_file)['size'];
            $offset = $size !== false ? $size : 0;
        } else {
            $offset = 0;
            if ($this->version >= 5) {
                $flags = NET_SFTP_OPEN_CREATE_TRUNCATE;
            } else {
                $flags |= NET_SFTP_OPEN_TRUNCATE;
            }
        }
        $this->remove_from_stat_cache($remote_file);
        $packet = Strings::packSSH2('s', $remote_file);
        $packet .= $this->version >= 5 ? pack('N3', 0, $flags, 0) : pack('N2', $flags, 0);
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                $handle = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
        $dataCallback = false;
        switch (true) {
            case $mode & self::SOURCE_CALLBACK:
                if (!is_callable($data)) {
                    throw new \BadFunctionCallException("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
                }
                $dataCallback = $data;
                // do nothing
                break;
            case is_resource($data):
                $mode = $mode & ~self::SOURCE_LOCAL_FILE;
                $info = stream_get_meta_data($data);
                if ($info['wrapper_type'] == 'PHP' && $info['stream_type'] == 'Input') {
                    $fp = fopen('php://memory', 'w+');
                    stream_copy_to_stream($data, $fp);
                    rewind($fp);
                } else {
                    $fp = $data;
                }
                break;
            case $mode & self::SOURCE_LOCAL_FILE:
                if (!is_file($data)) {
                    throw new FileNotFoundException("{$data} is not a valid file");
                }
                $fp = @fopen($data, 'rb');
                if (!$fp) {
                    return false;
                }
        }
        if (isset($fp)) {
            $stat = fstat($fp);
            $size = !empty($stat) ? $stat['size'] : 0;
            if ($local_start >= 0) {
                fseek($fp, $local_start);
                $size -= $local_start;
            }
        } elseif ($dataCallback) {
            $size = 0;
        } else {
            $size = strlen($data);
        }
        $sent = 0;
        $size = $size < 0 ? ($size & 0x7fffffff) + 0x80000000 : $size;
        $sftp_packet_size = $this->max_sftp_packet;
        // make the SFTP packet be exactly the SFTP packet size by including the bytes in the NET_SFTP_WRITE packets "header"
        $sftp_packet_size -= strlen($handle) + 25;
        $i = $j = 0;
        while ($dataCallback || ($size === 0 || $sent < $size)) {
            if ($dataCallback) {
                $temp = $dataCallback($sftp_packet_size);
                if (is_null($temp)) {
                    break;
                }
            } else {
                $temp = isset($fp) ? fread($fp, $sftp_packet_size) : \Phabel\Target\Php80\Polyfill::substr($data, $sent, $sftp_packet_size);
                if ($temp === false || $temp === '') {
                    break;
                }
            }
            $subtemp = $offset + $sent;
            $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
            try {
                $this->send_sftp_packet(NET_SFTP_WRITE, $packet, $j);
            } catch (\Exception $e) {
                if ($mode & self::SOURCE_LOCAL_FILE) {
                    fclose($fp);
                }
                throw $e;
            }
            $sent += strlen($temp);
            if (is_callable($progressCallback)) {
                $progressCallback($sent);
            }
            $i++;
            $j++;
            if ($i == NET_SFTP_UPLOAD_QUEUE_SIZE) {
                if (!$this->read_put_responses($i)) {
                    $i = 0;
                    break;
                }
                $i = 0;
            }
        }
        $result = $this->close_handle($handle);
        if (!$this->read_put_responses($i)) {
            if ($mode & self::SOURCE_LOCAL_FILE) {
                fclose($fp);
            }
            $this->close_handle($handle);
            return false;
        }
        if ($mode & SFTP::SOURCE_LOCAL_FILE) {
            if (isset($fp) && is_resource($fp)) {
                fclose($fp);
            }
            if ($this->preserveTime) {
                $stat = stat($data);
                $attr = $this->version < 4 ? pack('N3', NET_SFTP_ATTR_ACCESSTIME, $stat['atime'], $stat['time']) : Strings::packSSH2('NQ2', NET_SFTP_ATTR_ACCESSTIME | NET_SFTP_ATTR_MODIFYTIME, $stat['atime'], $stat['time']);
                if (!$this->setstat($remote_file, $attr, false)) {
                    throw new \RuntimeException('Error setting file time');
                }
            }
        }
        return $result;
    }
    /**
    * Reads multiple successive SSH_FXP_WRITE responses
    *
    * Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i
    SSH_FXP_WRITEs, in succession, and then reading $i responses.
    *
    * @param int $i
    * @return bool
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @access private
    */
    private function read_put_responses($i)
    {
        while ($i--) {
            $response = $this->get_sftp_packet();
            if ($this->packet_type != NET_SFTP_STATUS) {
                throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
            }
            list($status) = Strings::unpackSSH2('N', $response);
            if ($status != NET_SFTP_STATUS_OK) {
                $this->logError($response, $status);
                break;
            }
        }
        return $i < 0;
    }
    /**
     * Close handle
     *
     * @param string $handle
     * @return bool
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @access private
     */
    private function close_handle($handle)
    {
        $this->send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle));
        // "The client MUST release all resources associated with the handle regardless of the status."
        //  -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        return true;
    }
    /**
    * Downloads a file from the SFTP server.
    *
    * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
    the operation was unsuccessful.  If $local_file is defined, returns true or false depending on the success of the
    operation.
    *
    * $offset and $length can be used to download files in chunks.
    *
    * @param string $remote_file
    * @param (string | bool | resource | callable) $local_file
    * @param int $offset
    * @param int $length
    * @param (callable | null) $progressCallback
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @return mixed
    * @access public
    */
    public function get($remote_file, $local_file = false, $offset = 0, $length = -1, $progressCallback = null)
    {
        if (!$this->precheck()) {
            return false;
        }
        $remote_file = $this->realpath($remote_file);
        if ($remote_file === false) {
            return false;
        }
        $packet = Strings::packSSH2('s', $remote_file);
        $packet .= $this->version >= 5 ? pack('N3', 0, NET_SFTP_OPEN_OPEN_EXISTING, 0) : pack('N2', NET_SFTP_OPEN_READ, 0);
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                $handle = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        if (is_resource($local_file)) {
            $fp = $local_file;
            $stat = fstat($fp);
            $res_offset = $stat['size'];
        } else {
            $res_offset = 0;
            if ($local_file !== false && !is_callable($local_file)) {
                $fp = fopen($local_file, 'wb');
                if (!$fp) {
                    return false;
                }
            } else {
                $content = '';
            }
        }
        $fclose_check = $local_file !== false && !is_callable($local_file) && !is_resource($local_file);
        $start = $offset;
        $read = 0;
        while (true) {
            $i = 0;
            while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) {
                $tempoffset = $start + $read;
                $packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
                $packet = Strings::packSSH2('sN3', $handle, $tempoffset / 4294967296, $tempoffset, $packet_size);
                try {
                    $this->send_sftp_packet(NET_SFTP_READ, $packet, $i);
                } catch (\Exception $e) {
                    if ($fclose_check) {
                        fclose($fp);
                    }
                    throw $e;
                }
                $packet = null;
                $read += $packet_size;
                $i++;
            }
            if (!$i) {
                break;
            }
            $packets_sent = $i - 1;
            $clear_responses = false;
            while ($i > 0) {
                $i--;
                if ($clear_responses) {
                    $this->get_sftp_packet($packets_sent - $i);
                    continue;
                } else {
                    $response = $this->get_sftp_packet($packets_sent - $i);
                }
                switch ($this->packet_type) {
                    case NET_SFTP_DATA:
                        $temp = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                        $offset += strlen($temp);
                        if ($local_file === false) {
                            $content .= $temp;
                        } elseif (is_callable($local_file)) {
                            $local_file($temp);
                        } else {
                            fputs($fp, $temp);
                        }
                        if (is_callable($progressCallback)) {
                            call_user_func($progressCallback, $offset);
                        }
                        $temp = null;
                        break;
                    case NET_SFTP_STATUS:
                        // could, in theory, return false if !strlen($content) but we'll hold off for the time being
                        $this->logError($response);
                        $clear_responses = true;
                        // don't break out of the loop yet, so we can read the remaining responses
                        break;
                    default:
                        if ($fclose_check) {
                            fclose($fp);
                        }
                        if ($this->channel_close) {
                            $this->partial_init = false;
                            $this->init_sftp_connection();
                            return false;
                        } else {
                            throw new \UnexpectedValueException('Expected NET_SFTP_DATA or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
                        }
                }
                $response = null;
            }
            if ($clear_responses) {
                break;
            }
        }
        if ($length > 0 && $length <= $offset - $start) {
            if ($local_file === false) {
                $content = \Phabel\Target\Php80\Polyfill::substr($content, 0, $length);
            } else {
                ftruncate($fp, $length + $res_offset);
            }
        }
        if ($fclose_check) {
            fclose($fp);
            if ($this->preserveTime) {
                $stat = $this->stat($remote_file);
                touch($local_file, $stat['mtime'], $stat['atime']);
            }
        }
        if (!$this->close_handle($handle)) {
            return false;
        }
        // if $content isn't set that means a file was written to
        return isset($content) ? $content : true;
    }
    /**
     * Deletes a file on the SFTP server.
     *
     * @param string $path
     * @param bool $recursive
     * @return bool
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @access public
     */
    public function delete($path, $recursive = true)
    {
        if (!$this->precheck()) {
            return false;
        }
        if (is_object($path)) {
            // It's an object. Cast it as string before we check anything else.
            $path = (string) $path;
        }
        if (!is_string($path) || $path == '') {
            return false;
        }
        $path = $this->realpath($path);
        if ($path === false) {
            return false;
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
        $this->send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path));
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            if (!$recursive) {
                return false;
            }
            $i = 0;
            $result = $this->delete_recursive($path, $i);
            $this->read_put_responses($i);
            return $result;
        }
        $this->remove_from_stat_cache($path);
        return true;
    }
    /**
     * Recursively deletes directories on the SFTP server
     *
     * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
     *
     * @param string $path
     * @param int $i
     * @return bool
     * @access private
     */
    private function delete_recursive($path, &$i)
    {
        if (!$this->read_put_responses($i)) {
            return false;
        }
        $i = 0;
        $entries = $this->readlist($path, true);
        // normally $entries would have at least . and .. but it might not if the directories
        // permissions didn't allow reading
        if (empty($entries)) {
            return false;
        }
        unset($entries['.'], $entries['..']);
        foreach ($entries as $filename => $props) {
            if (!isset($props['type'])) {
                return false;
            }
            $temp = $path . '/' . $filename;
            if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) {
                if (!$this->delete_recursive($temp, $i)) {
                    return false;
                }
            } else {
                $this->send_sftp_packet(NET_SFTP_REMOVE, Strings::packSSH2('s', $temp));
                $this->remove_from_stat_cache($temp);
                $i++;
                if ($i >= NET_SFTP_QUEUE_SIZE) {
                    if (!$this->read_put_responses($i)) {
                        return false;
                    }
                    $i = 0;
                }
            }
        }
        $this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $path));
        $this->remove_from_stat_cache($path);
        $i++;
        if ($i >= NET_SFTP_QUEUE_SIZE) {
            if (!$this->read_put_responses($i)) {
                return false;
            }
            $i = 0;
        }
        return true;
    }
    /**
     * Checks whether a file or directory exists
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function file_exists($path)
    {
        if ($this->use_stat_cache) {
            if (!$this->precheck()) {
                return false;
            }
            $path = $this->realpath($path);
            $result = $this->query_stat_cache($path);
            if (isset($result)) {
                // return true if $result is an array or if it's an stdClass object
                return $result !== false;
            }
        }
        return $this->stat($path) !== false;
    }
    /**
     * Tells whether the filename is a directory
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_dir($path)
    {
        $result = $this->get_stat_cache_prop($path, 'type');
        if ($result === false) {
            return false;
        }
        return $result === NET_SFTP_TYPE_DIRECTORY;
    }
    /**
     * Tells whether the filename is a regular file
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_file($path)
    {
        $result = $this->get_stat_cache_prop($path, 'type');
        if ($result === false) {
            return false;
        }
        return $result === NET_SFTP_TYPE_REGULAR;
    }
    /**
     * Tells whether the filename is a symbolic link
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_link($path)
    {
        $result = $this->get_lstat_cache_prop($path, 'type');
        if ($result === false) {
            return false;
        }
        return $result === NET_SFTP_TYPE_SYMLINK;
    }
    /**
     * Tells whether a file exists and is readable
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_readable($path)
    {
        if (!$this->precheck()) {
            return false;
        }
        $packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_READ, 0);
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                return true;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
    }
    /**
     * Tells whether the filename is writable
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_writable($path)
    {
        if (!$this->precheck()) {
            return false;
        }
        $packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_WRITE, 0);
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                return true;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                return false;
            default:
                throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS. Got packet type: ' . $this->packet_type);
        }
    }
    /**
     * Tells whether the filename is writeable
     *
     * Alias of is_writable
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_writeable($path)
    {
        return $this->is_writable($path);
    }
    /**
     * Gets last access time of file
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function fileatime($path)
    {
        return $this->get_stat_cache_prop($path, 'atime');
    }
    /**
     * Gets file modification time
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function filemtime($path)
    {
        return $this->get_stat_cache_prop($path, 'mtime');
    }
    /**
     * Gets file permissions
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function fileperms($path)
    {
        return $this->get_stat_cache_prop($path, 'mode');
    }
    /**
     * Gets file owner
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function fileowner($path)
    {
        return $this->get_stat_cache_prop($path, 'uid');
    }
    /**
     * Gets file group
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function filegroup($path)
    {
        return $this->get_stat_cache_prop($path, 'gid');
    }
    /**
     * Gets file size
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function filesize($path)
    {
        return $this->get_stat_cache_prop($path, 'size');
    }
    /**
     * Gets file type
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function filetype($path)
    {
        $type = $this->get_stat_cache_prop($path, 'type');
        if ($type === false) {
            return false;
        }
        switch ($type) {
            case NET_SFTP_TYPE_BLOCK_DEVICE:
                return 'block';
            case NET_SFTP_TYPE_CHAR_DEVICE:
                return 'char';
            case NET_SFTP_TYPE_DIRECTORY:
                return 'dir';
            case NET_SFTP_TYPE_FIFO:
                return 'fifo';
            case NET_SFTP_TYPE_REGULAR:
                return 'file';
            case NET_SFTP_TYPE_SYMLINK:
                return 'link';
            default:
                return false;
        }
    }
    /**
     * Return a stat properity
     *
     * Uses cache if appropriate.
     *
     * @param string $path
     * @param string $prop
     * @return mixed
     * @access private
     */
    private function get_stat_cache_prop($path, $prop)
    {
        return $this->get_xstat_cache_prop($path, $prop, 'stat');
    }
    /**
     * Return an lstat properity
     *
     * Uses cache if appropriate.
     *
     * @param string $path
     * @param string $prop
     * @return mixed
     * @access private
     */
    private function get_lstat_cache_prop($path, $prop)
    {
        return $this->get_xstat_cache_prop($path, $prop, 'lstat');
    }
    /**
     * Return a stat or lstat properity
     *
     * Uses cache if appropriate.
     *
     * @param string $path
     * @param string $prop
     * @param string $type
     * @return mixed
     * @access private
     */
    private function get_xstat_cache_prop($path, $prop, $type)
    {
        if (!$this->precheck()) {
            return false;
        }
        if ($this->use_stat_cache) {
            $path = $this->realpath($path);
            $result = $this->query_stat_cache($path);
            if (is_object($result) && isset($result->{$type})) {
                return $result->{$type}[$prop];
            }
        }
        $result = $this->{$type}($path);
        if ($result === false || !isset($result[$prop])) {
            return false;
        }
        return $result[$prop];
    }
    /**
     * Renames a file or a directory on the SFTP server.
     *
     * If the file already exists this will return false
     *
     * @param string $oldname
     * @param string $newname
     * @return bool
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @access public
     */
    public function rename($oldname, $newname)
    {
        if (!$this->precheck()) {
            return false;
        }
        $oldname = $this->realpath($oldname);
        $newname = $this->realpath($newname);
        if ($oldname === false || $newname === false) {
            return false;
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
        $packet = Strings::packSSH2('ss', $oldname, $newname);
        if ($this->version >= 5) {
            /* quoting https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-6.5 ,
            
                           'flags' is 0 or a combination of:
            
                               SSH_FXP_RENAME_OVERWRITE  0x00000001
                               SSH_FXP_RENAME_ATOMIC     0x00000002
                               SSH_FXP_RENAME_NATIVE     0x00000004
            
                           (none of these are currently supported) */
            $packet .= "\x00\x00\x00\x00";
        }
        $this->send_sftp_packet(NET_SFTP_RENAME, $packet);
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        // don't move the stat cache entry over since this operation could very well change the
        // atime and mtime attributes
        //$this->update_stat_cache($newname, $this->query_stat_cache($oldname));
        $this->remove_from_stat_cache($oldname);
        $this->remove_from_stat_cache($newname);
        return true;
    }
    /**
     * Parse Time
     *
     * See '7.7.  Times' of draft-ietf-secsh-filexfer-13 for more info.
     *
     * @param string $key
     * @param int $flags
     * @param string $response
     * @return array
     * @access private
     */
    private function parseTime($key, $flags, &$response)
    {
        $attr = [];
        list($attr[$key]) = Strings::unpackSSH2('Q', $response);
        if ($flags & NET_SFTP_ATTR_SUBSECOND_TIMES) {
            list($attr[key . '-nseconds']) = Strings::unpackSSH2('N', $response);
        }
        return $attr;
    }
    /**
     * Parse Attributes
     *
     * See '7.  File Attributes' of draft-ietf-secsh-filexfer-13 for more info.
     *
     * @param string $response
     * @return array
     * @access private
     */
    protected function parseAttributes(&$response)
    {
        if ($this->version >= 4) {
            list($flags, $attr['type']) = Strings::unpackSSH2('NC', $response);
        } else {
            list($flags) = Strings::unpackSSH2('N', $response);
        }
        foreach ($this->attributes as $key => $value) {
            switch ($flags & $key) {
                case NET_SFTP_ATTR_UIDGID:
                    if ($this->version > 3) {
                        continue 2;
                    }
                    break;
                case NET_SFTP_ATTR_CREATETIME:
                case NET_SFTP_ATTR_MODIFYTIME:
                case NET_SFTP_ATTR_ACL:
                case NET_SFTP_ATTR_OWNERGROUP:
                case NET_SFTP_ATTR_SUBSECOND_TIMES:
                    if ($this->version < 4) {
                        continue 2;
                    }
                    break;
                case NET_SFTP_ATTR_BITS:
                    if ($this->version < 5) {
                        continue 2;
                    }
                    break;
                case NET_SFTP_ATTR_ALLOCATION_SIZE:
                case NET_SFTP_ATTR_TEXT_HINT:
                case NET_SFTP_ATTR_MIME_TYPE:
                case NET_SFTP_ATTR_LINK_COUNT:
                case NET_SFTP_ATTR_UNTRANSLATED_NAME:
                case NET_SFTP_ATTR_CTIME:
                    if ($this->version < 6) {
                        continue 2;
                    }
            }
            switch ($flags & $key) {
                case NET_SFTP_ATTR_SIZE:
                    // 0x00000001
                    // The size attribute is defined as an unsigned 64-bit integer.
                    // The following will use floats on 32-bit platforms, if necessary.
                    // As can be seen in the BigInteger class, floats are generally
                    // IEEE 754 binary64 "double precision" on such platforms and
                    // as such can represent integers of at least 2^50 without loss
                    // of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
                    list($attr['size']) = Strings::unpackSSH2('Q', $response);
                    break;
                case NET_SFTP_ATTR_UIDGID:
                    // 0x00000002 (SFTPv3 only)
                    list($attr['uid'], $attr['gid']) = Strings::unpackSSH2('NN', $response);
                    break;
                case NET_SFTP_ATTR_PERMISSIONS:
                    // 0x00000004
                    list($attr['mode']) = Strings::unpackSSH2('N', $response);
                    $fileType = $this->parseMode($attr['mode']);
                    if ($this->version < 4 && $fileType !== false) {
                        $attr += ['type' => $fileType];
                    }
                    break;
                case NET_SFTP_ATTR_ACCESSTIME:
                    // 0x00000008
                    if ($this->version >= 4) {
                        $attr += $this->parseTime('atime', $flags, $response);
                        break;
                    }
                    list($attr['atime'], $attr['mtime']) = Strings::unpackSSH2('NN', $response);
                    break;
                case NET_SFTP_ATTR_CREATETIME:
                    // 0x00000010 (SFTPv4+)
                    $attr += $this->parseTime('createtime', $flags, $response);
                    break;
                case NET_SFTP_ATTR_MODIFYTIME:
                    // 0x00000020
                    $attr += $this->parseTime('mtime', $flags, $response);
                    break;
                case NET_SFTP_ATTR_ACL:
                    // 0x00000040
                    // access control list
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-04#section-5.7
                    // currently unsupported
                    list($count) = Strings::unpackSSH2('N', $response);
                    for ($i = 0; $i < $count; $i++) {
                        list($type, $flag, $mask, $who) = Strings::unpackSSH2('N3s', $result);
                    }
                    break;
                case NET_SFTP_ATTR_OWNERGROUP:
                    // 0x00000080
                    list($attr['owner'], $attr['$group']) = Strings::unpackSSH2('ss', $response);
                    break;
                case NET_SFTP_ATTR_SUBSECOND_TIMES:
                    // 0x00000100
                    break;
                case NET_SFTP_ATTR_BITS:
                    // 0x00000200 (SFTPv5+)
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-5.8
                    // currently unsupported
                    // tells if you file is:
                    // readonly, system, hidden, case inensitive, archive, encrypted, compressed, sparse
                    // append only, immutable, sync
                    list($attrib_bits, $attrib_bits_valid) = Strings::unpackSSH2('N2', $response);
                    // if we were actually gonna implement the above it ought to be
                    // $attr['attrib-bits'] and $attr['attrib-bits-valid']
                    // eg. - instead of _
                    break;
                case NET_SFTP_ATTR_ALLOCATION_SIZE:
                    // 0x00000400 (SFTPv6+)
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.4
                    // represents the number of bytes that the file consumes on the disk. will
                    // usually be larger than the 'size' field
                    list($attr['allocation-size']) = Strings::unpack('Q', $response);
                    break;
                case NET_SFTP_ATTR_TEXT_HINT:
                    // 0x00000800
                    // https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.10
                    // currently unsupported
                    // tells if file is "known text", "guessed text", "known binary", "guessed binary"
                    list($text_hint) = Strings::unpackSSH2('C', $response);
                    // the above should be $attr['text-hint']
                    break;
                case NET_SFTP_ATTR_MIME_TYPE:
                    // 0x00001000
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.11
                    list($attr['mime-type']) = Strings::unpackSSH2('s', $response);
                    break;
                case NET_SFTP_ATTR_LINK_COUNT:
                    // 0x00002000
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.12
                    list($attr['link-count']) = Strings::unpackSS2('N', $response);
                    break;
                case NET_SFTP_ATTR_UNTRANSLATED_NAME:
                    // 0x00004000
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.13
                    list($attr['untranslated-name']) = Strings::unpackSSH2('s', $response);
                    break;
                case NET_SFTP_ATTR_CTIME:
                    // 0x00008000
                    // 'ctime' contains the last time the file attributes were changed.  The
                    // exact meaning of this field depends on the server.
                    $attr += $this->parseTime('ctime', $flags, $response);
                    break;
                case NET_SFTP_ATTR_EXTENDED:
                    // 0x80000000
                    list($count) = Strings::unpackSSH2('N', $response);
                    for ($i = 0; $i < $count; $i++) {
                        list($key, $value) = Strings::unpackSSH2('ss', $response);
                        $attr[$key] = $value;
                    }
            }
        }
        return $attr;
    }
    /**
     * Attempt to identify the file type
     *
     * Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway
     *
     * @param int $mode
     * @return int
     * @access private
     */
    private function parseMode($mode)
    {
        // values come from http://lxr.free-electrons.com/source/include/uapi/linux/stat.h#L12
        // see, also, http://linux.die.net/man/2/stat
        switch ($mode & 0170000) {
            // ie. 1111 0000 0000 0000
            case 00:
                // no file type specified - figure out the file type using alternative means
                return false;
            case 040000:
                return NET_SFTP_TYPE_DIRECTORY;
            case 0100000:
                return NET_SFTP_TYPE_REGULAR;
            case 0120000:
                return NET_SFTP_TYPE_SYMLINK;
            // new types introduced in SFTPv5+
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
            case 010000:
                // named pipe (fifo)
                return NET_SFTP_TYPE_FIFO;
            case 020000:
                // character special
                return NET_SFTP_TYPE_CHAR_DEVICE;
            case 060000:
                // block special
                return NET_SFTP_TYPE_BLOCK_DEVICE;
            case 0140000:
                // socket
                return NET_SFTP_TYPE_SOCKET;
            case 0160000:
                // whiteout
                // "SPECIAL should be used for files that are of
                //  a known type which cannot be expressed in the protocol"
                return NET_SFTP_TYPE_SPECIAL;
            default:
                return NET_SFTP_TYPE_UNKNOWN;
        }
    }
    /**
    * Parse Longname
    *
    * SFTPv3 doesn't provide any easy way of identifying a file type.  You could try to open
    a file as a directory and see if an error is returned or you could try to parse the
    SFTPv3-specific longname field of the SSH_FXP_NAME packet.  That's what this function does.
    The result is returned using the
    {@link http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2 SFTPv4 type constants}.
    *
    * If the longname is in an unrecognized format bool(false) is returned.
    *
    * @param string $longname
    * @return mixed
    * @access private
    */
    private function parseLongname($longname)
    {
        // http://en.wikipedia.org/wiki/Unix_file_types
        // http://en.wikipedia.org/wiki/Filesystem_permissions#Notation_of_traditional_Unix_permissions
        if (preg_match('#^[^/]([r-][w-][xstST-]){3}#', $longname)) {
            switch ($longname[0]) {
                case '-':
                    return NET_SFTP_TYPE_REGULAR;
                case 'd':
                    return NET_SFTP_TYPE_DIRECTORY;
                case 'l':
                    return NET_SFTP_TYPE_SYMLINK;
                default:
                    return NET_SFTP_TYPE_SPECIAL;
            }
        }
        return false;
    }
    /**
     * Sends SFTP Packets
     *
     * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
     *
     * @param int $type
     * @param string $data
     * @param int $request_id
     * @see self::_get_sftp_packet()
     * @see self::send_channel_packet()
     * @return bool
     * @access private
     */
    private function send_sftp_packet($type, $data, $request_id = 1)
    {
        // in SSH2.php the timeout is cumulative per function call. eg. exec() will
        // timeout after 10s. but for SFTP.php it's cumulative per packet
        $this->curTimeout = $this->timeout;
        $packet = $this->use_request_id ? pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) : pack('NCa*', strlen($data) + 1, $type, $data);
        $start = microtime(true);
        $result = $this->send_channel_packet(self::CHANNEL, $packet);
        $stop = microtime(true);
        if (defined('NET_SFTP_LOGGING')) {
            $packet_type = '-> ' . $this->packet_types[$type] . ' (' . round($stop - $start, 4) . 's)';
            if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
                switch (PHP_SAPI) {
                    case 'cli':
                        $start = $stop = "\r\n";
                        break;
                    default:
                        $start = '<pre>';
                        $stop = '</pre>';
                }
                echo $start . $this->format_log([$data], [$packet_type]) . $stop;
                @flush();
                @ob_flush();
            } else {
                $this->packet_type_log[] = $packet_type;
                if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
                    $this->packet_log[] = $data;
                }
            }
        }
        return $result;
    }
    /**
     * Resets a connection for re-use
     *
     * @param int $reason
     * @access private
     */
    protected function reset_connection($reason)
    {
        parent::reset_connection($reason);
        $this->use_request_id = false;
        $this->pwd = false;
        $this->requestBuffer = [];
    }
    /**
    * Receives SFTP Packets
    *
    * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
    *
    * Incidentally, the number of SSH_MSG_CHANNEL_DATA messages has no bearing on the number of SFTP packets present.
    There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA
    messages containing one SFTP packet.
    *
    * @see self::_send_sftp_packet()
    * @return string
    * @access private
    */
    private function get_sftp_packet($request_id = null)
    {
        $this->channel_close = false;
        if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
            $this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
            $temp = $this->requestBuffer[$request_id]['packet'];
            unset($this->requestBuffer[$request_id]);
            return $temp;
        }
        // in SSH2.php the timeout is cumulative per function call. eg. exec() will
        // timeout after 10s. but for SFTP.php it's cumulative per packet
        $this->curTimeout = $this->timeout;
        $start = microtime(true);
        // SFTP packet length
        while (strlen($this->packet_buffer) < 4) {
            $temp = $this->get_channel_packet(self::CHANNEL, true);
            if ($temp === true) {
                if ($this->channel_status[self::CHANNEL] === NET_SSH2_MSG_CHANNEL_CLOSE) {
                    $this->channel_close = true;
                }
                $this->packet_type = false;
                $this->packet_buffer = '';
                return false;
            }
            $this->packet_buffer .= $temp;
        }
        if (strlen($this->packet_buffer) < 4) {
            throw new \RuntimeException('Packet is too small');
        }
        extract(unpack('Nlength', Strings::shift($this->packet_buffer, 4)));
        /** @var integer $length */
        $tempLength = $length;
        $tempLength -= strlen($this->packet_buffer);
        // 256 * 1024 is what SFTP_MAX_MSG_LENGTH is set to in OpenSSH's sftp-common.h
        if (!$this->allow_arbitrary_length_packets && !$this->use_request_id && $tempLength > 256 * 1024) {
            throw new \RuntimeException('Invalid Size');
        }
        // SFTP packet type and data payload
        while ($tempLength > 0) {
            $temp = $this->get_channel_packet(self::CHANNEL, true);
            if (is_bool($temp)) {
                $this->packet_type = false;
                $this->packet_buffer = '';
                return false;
            }
            $this->packet_buffer .= $temp;
            $tempLength -= strlen($temp);
        }
        $stop = microtime(true);
        $this->packet_type = ord(Strings::shift($this->packet_buffer));
        if ($this->use_request_id) {
            extract(unpack('Npacket_id', Strings::shift($this->packet_buffer, 4)));
            // remove the request id
            $length -= 5;
            // account for the request id and the packet type
        } else {
            $length -= 1;
            // account for the packet type
        }
        $packet = Strings::shift($this->packet_buffer, $length);
        if (defined('NET_SFTP_LOGGING')) {
            $packet_type = '<- ' . $this->packet_types[$this->packet_type] . ' (' . round($stop - $start, 4) . 's)';
            if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
                switch (PHP_SAPI) {
                    case 'cli':
                        $start = $stop = "\r\n";
                        break;
                    default:
                        $start = '<pre>';
                        $stop = '</pre>';
                }
                echo $start . $this->format_log([$packet], [$packet_type]) . $stop;
                @flush();
                @ob_flush();
            } else {
                $this->packet_type_log[] = $packet_type;
                if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
                    $this->packet_log[] = $packet;
                }
            }
        }
        if (isset($request_id) && $this->use_request_id && $packet_id != $request_id) {
            $this->requestBuffer[$packet_id] = ['packet_type' => $this->packet_type, 'packet' => $packet];
            return $this->get_sftp_packet($request_id);
        }
        return $packet;
    }
    /**
     * Returns a log of the packets that have been sent and received.
     *
     * Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
     *
     * @access public
     * @return (array | string)
     */
    public function getSFTPLog()
    {
        if (!defined('NET_SFTP_LOGGING')) {
            return false;
        }
        switch (NET_SFTP_LOGGING) {
            case self::LOG_COMPLEX:
                return $this->format_log($this->packet_log, $this->packet_type_log);
                break;
            //case self::LOG_SIMPLE:
            default:
                return $this->packet_type_log;
        }
    }
    /**
     * Returns all errors
     *
     * @return array
     * @access public
     */
    public function getSFTPErrors()
    {
        return $this->sftp_errors;
    }
    /**
     * Returns the last error
     *
     * @return string
     * @access public
     */
    public function getLastSFTPError()
    {
        return count($this->sftp_errors) ? $this->sftp_errors[count($this->sftp_errors) - 1] : '';
    }
    /**
     * Get supported SFTP versions
     *
     * @return array
     * @access public
     */
    public function getSupportedVersions()
    {
        if (!($this->bitmap & SSH2::MASK_LOGIN)) {
            return false;
        }
        if (!$this->partial_init) {
            $this->partial_init_sftp_connection();
        }
        $temp = ['version' => $this->defaultVersion];
        if (isset($this->extensions['versions'])) {
            $temp['extensions'] = $this->extensions['versions'];
        }
        return $temp;
    }
    /**
     * Get supported SFTP versions
     *
     * @return array
     * @access public
     */
    public function getNegotiatedVersion()
    {
        if (!$this->precheck()) {
            return false;
        }
        return $this->version;
    }
    /**
    * Set preferred version
    *
    * If you're preferred version isn't supported then the highest supported
    version of SFTP will be utilized. Set to null or false or int(0) to
    unset the preferred version
    *
    * @param int $version
    * @access public
    */
    public function setPreferredVersion($version)
    {
        $this->preferredVersion = $version;
    }
    /**
     * Disconnect
     *
     * @param int $reason
     * @return bool
     * @access protected
     */
    protected function disconnect_helper($reason)
    {
        $this->pwd = false;
        parent::disconnect_helper($reason);
    }
    /**
     * Enable Date Preservation
     *
     * @access public
     */
    public function enableDatePreservation()
    {
        $this->preserveTime = true;
    }
    /**
     * Disable Date Preservation
     *
     * @access public
     */
    public function disableDatePreservation()
    {
        $this->preserveTime = false;
    }
}<?php

/**
 * Pure-PHP implementation of SSHv2.
 *
 * PHP version 5
 *
 * Here are some examples of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $ssh = new \phpseclib3\Net\SSH2('www.domain.tld');
 *    if (!$ssh->login('username', 'password')) {
 *        exit('Login Failed');
 *    }
 *
 *    echo $ssh->exec('pwd');
 *    echo $ssh->exec('ls -la');
 * ?>
 * </code>
 *
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $key = \phpseclib3\Crypt\PublicKeyLoader::load('...', '(optional) password');
 *
 *    $ssh = new \phpseclib3\Net\SSH2('www.domain.tld');
 *    if (!$ssh->login('username', $key)) {
 *        exit('Login Failed');
 *    }
 *
 *    echo $ssh->read('username@username:~$');
 *    $ssh->write("ls -la\n");
 *    echo $ssh->read('username@username:~$');
 * ?>
 * </code>
 *
 * @category  Net
 * @package   SSH2
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Net;

use phpseclib3\Crypt\Blowfish;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\RC4;
use phpseclib3\Crypt\Rijndael;
use phpseclib3\Crypt\Common\PrivateKey;
use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\DH;
use phpseclib3\Crypt\TripleDES;
use phpseclib3\Crypt\Twofish;
use phpseclib3\Crypt\ChaCha20;
use phpseclib3\Math\BigInteger;
// Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
use phpseclib3\System\SSH\Agent;
use phpseclib3\System\SSH\Agent\Identity as AgentIdentity;
use phpseclib3\Exception\NoSupportedAlgorithmsException;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Exception\ConnectionClosedException;
use phpseclib3\Exception\UnableToConnectException;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\AsymmetricKey;
/**#@+
 * @access private
 */
/**
 * No compression
 */
define('NET_SSH2_COMPRESSION_NONE', 1);
/**
 * zlib compression
 */
define('NET_SSH2_COMPRESSION_ZLIB', 2);
/**
 * zlib@openssh.com
 */
define('NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH', 3);
/**#@-*/
/**
 * Pure-PHP implementation of SSHv2.
 *
 * @package SSH2
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class SSH2
{
    // Execution Bitmap Masks
    const MASK_CONSTRUCTOR = 0x1;
    const MASK_CONNECTED = 0x2;
    const MASK_LOGIN_REQ = 0x4;
    const MASK_LOGIN = 0x8;
    const MASK_SHELL = 0x10;
    const MASK_WINDOW_ADJUST = 0x20;
    /*
     * Channel constants
     *
     * RFC4254 refers not to client and server channels but rather to sender and recipient channels.  we don't refer
     * to them in that way because RFC4254 toggles the meaning. the client sends a SSH_MSG_CHANNEL_OPEN message with
     * a sender channel and the server sends a SSH_MSG_CHANNEL_OPEN_CONFIRMATION in response, with a sender and a
     * recipient channel.  at first glance, you might conclude that SSH_MSG_CHANNEL_OPEN_CONFIRMATION's sender channel
     * would be the same thing as SSH_MSG_CHANNEL_OPEN's sender channel, but it's not, per this snippet:
     *     The 'recipient channel' is the channel number given in the original
     *     open request, and 'sender channel' is the channel number allocated by
     *     the other side.
     *
     * @see \phpseclib3\Net\SSH2::send_channel_packet()
     * @see \phpseclib3\Net\SSH2::get_channel_packet()
     * @access private
     */
    const CHANNEL_EXEC = 1;
    // PuTTy uses 0x100
    const CHANNEL_SHELL = 2;
    const CHANNEL_SUBSYSTEM = 3;
    const CHANNEL_AGENT_FORWARD = 4;
    const CHANNEL_KEEP_ALIVE = 5;
    /**
     * Returns the message numbers
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_SIMPLE = 1;
    /**
     * Returns the message content
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_COMPLEX = 2;
    /**
     * Outputs the content real-time
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_REALTIME = 3;
    /**
     * Dumps the content real-time to a file
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_REALTIME_FILE = 4;
    /**
     * Make sure that the log never gets larger than this
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_MAX_SIZE = 1048576;
    // 1024 * 1024
    /**
     * Returns when a string matching $expect exactly is found
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::read()
     */
    const READ_SIMPLE = 1;
    /**
     * Returns when a string matching the regular expression $expect is found
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::read()
     */
    const READ_REGEX = 2;
    /**
     * Returns whenever a data packet is received.
     *
     * Some data packets may only contain a single character so it may be necessary
     * to call read() multiple times when using this option
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::read()
     */
    const READ_NEXT = 3;
    /**
     * The SSH identifier
     *
     * @var string
     * @access private
     */
    private $identifier;
    /**
     * The Socket Object
     *
     * @var object
     * @access private
     */
    public $fsock;
    /**
     * Execution Bitmap
     *
     * The bits that are set represent functions that have been called already.  This is used to determine
     * if a requisite function has been successfully executed.  If not, an error should be thrown.
     *
     * @var int
     * @access private
     */
    protected $bitmap = 0;
    /**
     * Error information
     *
     * @see self::getErrors()
     * @see self::getLastError()
     * @var array
     * @access private
     */
    private $errors = [];
    /**
     * Server Identifier
     *
     * @see self::getServerIdentification()
     * @var array|false
     * @access private
     */
    protected $server_identifier = false;
    /**
     * Key Exchange Algorithms
     *
     * @see self::getKexAlgorithims()
     * @var array|false
     * @access private
     */
    private $kex_algorithms = false;
    /**
     * Key Exchange Algorithm
     *
     * @see self::getMethodsNegotiated()
     * @var string|false
     * @access private
     */
    private $kex_algorithm = false;
    /**
     * Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
     *
     * @see self::_key_exchange()
     * @var int
     * @access private
     */
    private $kex_dh_group_size_min = 1536;
    /**
     * Preferred Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
     *
     * @see self::_key_exchange()
     * @var int
     * @access private
     */
    private $kex_dh_group_size_preferred = 2048;
    /**
     * Maximum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
     *
     * @see self::_key_exchange()
     * @var int
     * @access private
     */
    private $kex_dh_group_size_max = 4096;
    /**
     * Server Host Key Algorithms
     *
     * @see self::getServerHostKeyAlgorithms()
     * @var array|false
     * @access private
     */
    private $server_host_key_algorithms = false;
    /**
     * Encryption Algorithms: Client to Server
     *
     * @see self::getEncryptionAlgorithmsClient2Server()
     * @var array|false
     * @access private
     */
    private $encryption_algorithms_client_to_server = false;
    /**
     * Encryption Algorithms: Server to Client
     *
     * @see self::getEncryptionAlgorithmsServer2Client()
     * @var array|false
     * @access private
     */
    private $encryption_algorithms_server_to_client = false;
    /**
     * MAC Algorithms: Client to Server
     *
     * @see self::getMACAlgorithmsClient2Server()
     * @var array|false
     * @access private
     */
    private $mac_algorithms_client_to_server = false;
    /**
     * MAC Algorithms: Server to Client
     *
     * @see self::getMACAlgorithmsServer2Client()
     * @var array|false
     * @access private
     */
    private $mac_algorithms_server_to_client = false;
    /**
     * Compression Algorithms: Client to Server
     *
     * @see self::getCompressionAlgorithmsClient2Server()
     * @var array|false
     * @access private
     */
    private $compression_algorithms_client_to_server = false;
    /**
     * Compression Algorithms: Server to Client
     *
     * @see self::getCompressionAlgorithmsServer2Client()
     * @var array|false
     * @access private
     */
    private $compression_algorithms_server_to_client = false;
    /**
     * Languages: Server to Client
     *
     * @see self::getLanguagesServer2Client()
     * @var array|false
     * @access private
     */
    private $languages_server_to_client = false;
    /**
     * Languages: Client to Server
     *
     * @see self::getLanguagesClient2Server()
     * @var array|false
     * @access private
     */
    private $languages_client_to_server = false;
    /**
     * Preferred Algorithms
     *
     * @see self::setPreferredAlgorithms()
     * @var array
     * @access private
     */
    private $preferred = [];
    /**
     * Block Size for Server to Client Encryption
     *
     * "Note that the length of the concatenation of 'packet_length',
     *  'padding_length', 'payload', and 'random padding' MUST be a multiple
     *  of the cipher block size or 8, whichever is larger.  This constraint
     *  MUST be enforced, even when using stream ciphers."
     *
     *  -- http://tools.ietf.org/html/rfc4253#section-6
     *
     * @see self::__construct()
     * @see self::_send_binary_packet()
     * @var int
     * @access private
     */
    private $encrypt_block_size = 8;
    /**
     * Block Size for Client to Server Encryption
     *
     * @see self::__construct()
     * @see self::_get_binary_packet()
     * @var int
     * @access private
     */
    private $decrypt_block_size = 8;
    /**
     * Server to Client Encryption Object
     *
     * @see self::_get_binary_packet()
     * @var object
     * @access private
     */
    private $decrypt = false;
    /**
     * Server to Client Length Encryption Object
     *
     * @see self::_get_binary_packet()
     * @var object
     * @access private
     */
    private $lengthDecrypt = false;
    /**
     * Client to Server Encryption Object
     *
     * @see self::_send_binary_packet()
     * @var object
     * @access private
     */
    private $encrypt = false;
    /**
     * Client to Server Length Encryption Object
     *
     * @see self::_send_binary_packet()
     * @var object
     * @access private
     */
    private $lengthEncrypt = false;
    /**
     * Client to Server HMAC Object
     *
     * @see self::_send_binary_packet()
     * @var object
     * @access private
     */
    private $hmac_create = false;
    /**
     * Server to Client HMAC Object
     *
     * @see self::_get_binary_packet()
     * @var object
     * @access private
     */
    private $hmac_check = false;
    /**
     * Size of server to client HMAC
     *
     * We need to know how big the HMAC will be for the server to client direction so that we know how many bytes to read.
     * For the client to server side, the HMAC object will make the HMAC as long as it needs to be.  All we need to do is
     * append it.
     *
     * @see self::_get_binary_packet()
     * @var int
     * @access private
     */
    private $hmac_size = false;
    /**
     * Server Public Host Key
     *
     * @see self::getServerPublicHostKey()
     * @var string
     * @access private
     */
    private $server_public_host_key;
    /**
     * Session identifier
     *
     * "The exchange hash H from the first key exchange is additionally
     *  used as the session identifier, which is a unique identifier for
     *  this connection."
     *
     *  -- http://tools.ietf.org/html/rfc4253#section-7.2
     *
     * @see self::_key_exchange()
     * @var string
     * @access private
     */
    private $session_id = false;
    /**
     * Exchange hash
     *
     * The current exchange hash
     *
     * @see self::_key_exchange()
     * @var string
     * @access private
     */
    private $exchange_hash = false;
    /**
     * Message Numbers
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $message_numbers = [];
    /**
     * Disconnection Message 'reason codes' defined in RFC4253
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $disconnect_reasons = [];
    /**
     * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $channel_open_failure_reasons = [];
    /**
     * Terminal Modes
     *
     * @link http://tools.ietf.org/html/rfc4254#section-8
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $terminal_modes = [];
    /**
     * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
     *
     * @link http://tools.ietf.org/html/rfc4254#section-5.2
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $channel_extended_data_type_codes = [];
    /**
     * Send Sequence Number
     *
     * See 'Section 6.4.  Data Integrity' of rfc4253 for more info.
     *
     * @see self::_send_binary_packet()
     * @var int
     * @access private
     */
    private $send_seq_no = 0;
    /**
     * Get Sequence Number
     *
     * See 'Section 6.4.  Data Integrity' of rfc4253 for more info.
     *
     * @see self::_get_binary_packet()
     * @var int
     * @access private
     */
    private $get_seq_no = 0;
    /**
     * Server Channels
     *
     * Maps client channels to server channels
     *
     * @see self::get_channel_packet()
     * @see self::exec()
     * @var array
     * @access private
     */
    protected $server_channels = [];
    /**
     * Channel Buffers
     *
     * If a client requests a packet from one channel but receives two packets from another those packets should
     * be placed in a buffer
     *
     * @see self::get_channel_packet()
     * @see self::exec()
     * @var array
     * @access private
     */
    private $channel_buffers = [];
    /**
     * Channel Status
     *
     * Contains the type of the last sent message
     *
     * @see self::get_channel_packet()
     * @var array
     * @access private
     */
    protected $channel_status = [];
    /**
     * Packet Size
     *
     * Maximum packet size indexed by channel
     *
     * @see self::send_channel_packet()
     * @var array
     * @access private
     */
    private $packet_size_client_to_server = [];
    /**
     * Message Number Log
     *
     * @see self::getLog()
     * @var array
     * @access private
     */
    private $message_number_log = [];
    /**
     * Message Log
     *
     * @see self::getLog()
     * @var array
     * @access private
     */
    private $message_log = [];
    /**
     * The Window Size
     *
     * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB)
     *
     * @var int
     * @see self::send_channel_packet()
     * @see self::exec()
     * @access private
     */
    protected $window_size = 0x7fffffff;
    /**
     * What we resize the window to
     *
     * When PuTTY resizes the window it doesn't add an additional 0x7FFFFFFF bytes - it adds 0x40000000 bytes.
     * Some SFTP clients (GoAnywhere) don't support adding 0x7FFFFFFF to the window size after the fact so
     * we'll just do what PuTTY does
     *
     * @var int
     * @see self::_send_channel_packet()
     * @see self::exec()
     * @access private
     */
    private $window_resize = 0x40000000;
    /**
     * Window size, server to client
     *
     * Window size indexed by channel
     *
     * @see self::send_channel_packet()
     * @var array
     * @access private
     */
    protected $window_size_server_to_client = [];
    /**
     * Window size, client to server
     *
     * Window size indexed by channel
     *
     * @see self::get_channel_packet()
     * @var array
     * @access private
     */
    private $window_size_client_to_server = [];
    /**
     * Server signature
     *
     * Verified against $this->session_id
     *
     * @see self::getServerPublicHostKey()
     * @var string
     * @access private
     */
    private $signature = '';
    /**
     * Server signature format
     *
     * ssh-rsa or ssh-dss.
     *
     * @see self::getServerPublicHostKey()
     * @var string
     * @access private
     */
    private $signature_format = '';
    /**
     * Interactive Buffer
     *
     * @see self::read()
     * @var array
     * @access private
     */
    private $interactiveBuffer = '';
    /**
     * Current log size
     *
     * Should never exceed self::LOG_MAX_SIZE
     *
     * @see self::_send_binary_packet()
     * @see self::_get_binary_packet()
     * @var int
     * @access private
     */
    private $log_size;
    /**
     * Timeout
     *
     * @see self::setTimeout()
     * @access private
     */
    protected $timeout;
    /**
     * Current Timeout
     *
     * @see self::get_channel_packet()
     * @access private
     */
    protected $curTimeout;
    /**
     * Keep Alive Interval
     *
     * @see self::setKeepAlive()
     * @access private
     */
    private $keepAlive;
    /**
     * Real-time log file pointer
     *
     * @see self::_append_log()
     * @var resource
     * @access private
     */
    private $realtime_log_file;
    /**
     * Real-time log file size
     *
     * @see self::_append_log()
     * @var int
     * @access private
     */
    private $realtime_log_size;
    /**
     * Has the signature been validated?
     *
     * @see self::getServerPublicHostKey()
     * @var bool
     * @access private
     */
    private $signature_validated = false;
    /**
     * Real-time log file wrap boolean
     *
     * @see self::_append_log()
     * @access private
     */
    private $realtime_log_wrap;
    /**
     * Flag to suppress stderr from output
     *
     * @see self::enableQuietMode()
     * @access private
     */
    private $quiet_mode = false;
    /**
     * Time of first network activity
     *
     * @var int
     * @access private
     */
    private $last_packet;
    /**
     * Exit status returned from ssh if any
     *
     * @var int
     * @access private
     */
    private $exit_status;
    /**
     * Flag to request a PTY when using exec()
     *
     * @var bool
     * @see self::enablePTY()
     * @access private
     */
    private $request_pty = false;
    /**
     * Flag set while exec() is running when using enablePTY()
     *
     * @var bool
     * @access private
     */
    private $in_request_pty_exec = false;
    /**
     * Flag set after startSubsystem() is called
     *
     * @var bool
     * @access private
     */
    private $in_subsystem;
    /**
     * Contents of stdError
     *
     * @var string
     * @access private
     */
    private $stdErrorLog;
    /**
     * The Last Interactive Response
     *
     * @see self::_keyboard_interactive_process()
     * @var string
     * @access private
     */
    private $last_interactive_response = '';
    /**
     * Keyboard Interactive Request / Responses
     *
     * @see self::_keyboard_interactive_process()
     * @var array
     * @access private
     */
    private $keyboard_requests_responses = [];
    /**
     * Banner Message
     *
     * Quoting from the RFC, "in some jurisdictions, sending a warning message before
     * authentication may be relevant for getting legal protection."
     *
     * @see self::_filter()
     * @see self::getBannerMessage()
     * @var string
     * @access private
     */
    private $banner_message = '';
    /**
     * Did read() timeout or return normally?
     *
     * @see self::isTimeout()
     * @var bool
     * @access private
     */
    private $is_timeout = false;
    /**
     * Log Boundary
     *
     * @see self::_format_log()
     * @var string
     * @access private
     */
    private $log_boundary = ':';
    /**
     * Log Long Width
     *
     * @see self::_format_log()
     * @var int
     * @access private
     */
    private $log_long_width = 65;
    /**
     * Log Short Width
     *
     * @see self::_format_log()
     * @var int
     * @access private
     */
    private $log_short_width = 16;
    /**
     * Hostname
     *
     * @see self::__construct()
     * @see self::_connect()
     * @var string
     * @access private
     */
    private $host;
    /**
     * Port Number
     *
     * @see self::__construct()
     * @see self::_connect()
     * @var int
     * @access private
     */
    private $port;
    /**
     * Number of columns for terminal window size
     *
     * @see self::getWindowColumns()
     * @see self::setWindowColumns()
     * @see self::setWindowSize()
     * @var int
     * @access private
     */
    private $windowColumns = 80;
    /**
     * Number of columns for terminal window size
     *
     * @see self::getWindowRows()
     * @see self::setWindowRows()
     * @see self::setWindowSize()
     * @var int
     * @access private
     */
    private $windowRows = 24;
    /**
     * Crypto Engine
     *
     * @see self::setCryptoEngine()
     * @see self::_key_exchange()
     * @var int
     * @access private
     */
    private static $crypto_engine = false;
    /**
     * A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario
     *
     * @var \phpseclib3\System\Ssh\Agent
     * @access private
     */
    private $agent;
    /**
     * Connection storage to replicates ssh2 extension functionality:
     * {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples}
     *
     * @var SSH2[]
     */
    private static $connections;
    /**
     * Send the identification string first?
     *
     * @var bool
     * @access private
     */
    private $send_id_string_first = true;
    /**
     * Send the key exchange initiation packet first?
     *
     * @var bool
     * @access private
     */
    private $send_kex_first = true;
    /**
     * Some versions of OpenSSH incorrectly calculate the key size
     *
     * @var bool
     * @access private
     */
    private $bad_key_size_fix = false;
    /**
     * Should we try to re-connect to re-establish keys?
     *
     * @var bool
     * @access private
     */
    private $retry_connect = false;
    /**
     * Binary Packet Buffer
     *
     * @var string|false
     * @access private
     */
    private $binary_packet_buffer = false;
    /**
     * Preferred Signature Format
     *
     * @var string|false
     * @access private
     */
    protected $preferred_signature_format = false;
    /**
     * Authentication Credentials
     *
     * @var array
     * @access private
     */
    protected $auth = [];
    /**
     * Terminal
     *
     * @var string
     * @access private
     */
    private $term = 'vt100';
    /**
     * The authentication methods that may productively continue authentication.
     * 
     * @see https://tools.ietf.org/html/rfc4252#section-5.1
     * @var array|null
     * @access private
     */
    private $auth_methods_to_continue = null;
    /**
     * Compression method
     *
     * @var int
     * @access private
     */
    private $compress = NET_SSH2_COMPRESSION_NONE;
    /**
     * Decompression method
     *
     * @var resource|object
     * @access private
     */
    private $decompress = NET_SSH2_COMPRESSION_NONE;
    /**
     * Compression context
     *
     * @var int
     * @access private
     */
    private $compress_context;
    /**
     * Decompression context
     *
     * @var resource|object
     * @access private
     */
    private $decompress_context;
    /**
     * Regenerate Compression Context
     *
     * @var bool
     * @access private
     */
    private $regenerate_compression_context = false;
    /**
     * Regenerate Decompression Context
     *
     * @var bool
     * @access private
     */
    private $regenerate_decompression_context = false;
    /**
     * Smart multi-factor authentication flag
     *
     * @var bool
     * @access private
     */
    private $smartMFA = true;
    /**
     * Default Constructor.
     *
     * $host can either be a string, representing the host, or a stream resource.
     *
     * @param mixed $host
     * @param int $port
     * @param int $timeout
     * @see self::login()
     * @return (SSH2 | void)
     * @access public
     */
    public function __construct($host, $port = 22, $timeout = 10)
    {
        $this->message_numbers = [1 => 'NET_SSH2_MSG_DISCONNECT', 2 => 'NET_SSH2_MSG_IGNORE', 3 => 'NET_SSH2_MSG_UNIMPLEMENTED', 4 => 'NET_SSH2_MSG_DEBUG', 5 => 'NET_SSH2_MSG_SERVICE_REQUEST', 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT', 20 => 'NET_SSH2_MSG_KEXINIT', 21 => 'NET_SSH2_MSG_NEWKEYS', 30 => 'NET_SSH2_MSG_KEXDH_INIT', 31 => 'NET_SSH2_MSG_KEXDH_REPLY', 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST', 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE', 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS', 53 => 'NET_SSH2_MSG_USERAUTH_BANNER', 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST', 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS', 82 => 'NET_SSH2_MSG_REQUEST_FAILURE', 90 => 'NET_SSH2_MSG_CHANNEL_OPEN', 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION', 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE', 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST', 94 => 'NET_SSH2_MSG_CHANNEL_DATA', 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA', 96 => 'NET_SSH2_MSG_CHANNEL_EOF', 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE', 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST', 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS', 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'];
        $this->disconnect_reasons = [1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT', 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR', 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED', 4 => 'NET_SSH2_DISCONNECT_RESERVED', 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR', 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR', 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE', 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED', 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE', 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST', 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION', 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS', 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER', 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE', 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'];
        $this->channel_open_failure_reasons = [1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'];
        $this->terminal_modes = [0 => 'NET_SSH2_TTY_OP_END'];
        $this->channel_extended_data_type_codes = [1 => 'NET_SSH2_EXTENDED_DATA_STDERR'];
        $this->define_array(
            $this->message_numbers,
            $this->disconnect_reasons,
            $this->channel_open_failure_reasons,
            $this->terminal_modes,
            $this->channel_extended_data_type_codes,
            [60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'],
            [60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'],
            [60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST', 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'],
            // RFC 4419 - diffie-hellman-group-exchange-sha{1,256}
            [30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD', 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP', 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT', 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY', 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'],
            // RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org)
            [30 => 'NET_SSH2_MSG_KEX_ECDH_INIT', 31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY']
        );
        self::$connections[$this->getResourceId()] = class_exists('WeakReference') ? \WeakReference::create($this) : $this;
        if (is_resource($host)) {
            $this->fsock = $host;
            return;
        }
        if (is_string($host)) {
            $this->host = $host;
            $this->port = $port;
            $this->timeout = $timeout;
        }
    }
    /**
    * Set Crypto Engine Mode
    *
    * Possible $engine values:
    OpenSSL, mcrypt, Eval, PHP
    *
    * @param int $engine
    * @access public
    */
    public static function setCryptoEngine($engine)
    {
        self::$crypto_engine = $engine;
    }
    /**
    * Send Identification String First
    *
    * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
    both sides MUST send an identification string". It does not say which side sends it first. In
    theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
    *
    * @access public
    */
    public function sendIdentificationStringFirst()
    {
        $this->send_id_string_first = true;
    }
    /**
    * Send Identification String Last
    *
    * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
    both sides MUST send an identification string". It does not say which side sends it first. In
    theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
    *
    * @access public
    */
    public function sendIdentificationStringLast()
    {
        $this->send_id_string_first = false;
    }
    /**
    * Send SSH_MSG_KEXINIT First
    *
    * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
    sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
    it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
    *
    * @access public
    */
    public function sendKEXINITFirst()
    {
        $this->send_kex_first = true;
    }
    /**
    * Send SSH_MSG_KEXINIT Last
    *
    * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
    sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
    it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
    *
    * @access public
    */
    public function sendKEXINITLast()
    {
        $this->send_kex_first = false;
    }
    /**
     * Connect to an SSHv2 server
     *
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @throws \RuntimeException on other errors
     * @access private
     */
    private function connect()
    {
        if ($this->bitmap & self::MASK_CONSTRUCTOR) {
            return;
        }
        $this->bitmap |= self::MASK_CONSTRUCTOR;
        $this->curTimeout = $this->timeout;
        $this->last_packet = microtime(true);
        if (!is_resource($this->fsock)) {
            $start = microtime(true);
            // with stream_select a timeout of 0 means that no timeout takes place;
            // with fsockopen a timeout of 0 means that you instantly timeout
            // to resolve this incompatibility a timeout of 100,000 will be used for fsockopen if timeout is 0
            $this->fsock = @\Phabel\Target\Php80\Polyfill::fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout == 0 ? 100000 : $this->curTimeout);
            if (!$this->fsock) {
                $host = $this->host . ':' . $this->port;
                throw new UnableToConnectException(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"));
            }
            $elapsed = microtime(true) - $start;
            if ($this->curTimeout) {
                $this->curTimeout -= $elapsed;
                if ($this->curTimeout < 0) {
                    throw new \RuntimeException('Connection timed out whilst attempting to open socket connection');
                }
            }
        }
        $this->identifier = $this->generate_identifier();
        if ($this->send_id_string_first) {
            fputs($this->fsock, $this->identifier . "\r\n");
        }
        /* According to the SSH2 specs,
        
                  "The server MAY send other lines of data before sending the version
                   string.  Each line SHOULD be terminated by a Carriage Return and Line
                   Feed.  Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
                   in ISO-10646 UTF-8 [RFC3629] (language is not specified).  Clients
                   MUST be able to process such lines." */
        $data = '';
        while (!feof($this->fsock) && !preg_match('#(.*)^(SSH-(\\d\\.\\d+).*)#ms', $data, $matches)) {
            $line = '';
            while (true) {
                if ($this->curTimeout) {
                    if ($this->curTimeout < 0) {
                        throw new \RuntimeException('Connection timed out whilst receiving server identification string');
                    }
                    $read = [$this->fsock];
                    $write = $except = null;
                    $start = microtime(true);
                    $sec = floor($this->curTimeout);
                    $usec = 1000000 * ($this->curTimeout - $sec);
                    if (@stream_select($read, $write, $except, $sec, $usec) === false) {
                        throw new \RuntimeException('Connection timed out whilst receiving server identification string');
                    }
                    $elapsed = microtime(true) - $start;
                    $this->curTimeout -= $elapsed;
                }
                $temp = stream_get_line($this->fsock, 255, "\n");
                if ($temp === false) {
                    throw new \RuntimeException('Error reading from socket');
                }
                if (strlen($temp) == 255) {
                    continue;
                }
                $line .= "{$temp}\n";
                // quoting RFC4253, "Implementers who wish to maintain
                // compatibility with older, undocumented versions of this protocol may
                // want to process the identification string without expecting the
                // presence of the carriage return character for reasons described in
                // Section 5 of this document."
                //if (substr($line, -2) == "\r\n") {
                //    break;
                //}
                break;
            }
            $data .= $line;
        }
        if (feof($this->fsock)) {
            $this->bitmap = 0;
            throw new ConnectionClosedException('Connection closed by server');
        }
        $extra = $matches[1];
        if (defined('NET_SSH2_LOGGING')) {
            $this->append_log('<-', $matches[0]);
            $this->append_log('->', $this->identifier . "\r\n");
        }
        $this->server_identifier = trim($temp, "\r\n");
        if (strlen($extra)) {
            $this->errors[] = $data;
        }
        if (version_compare($matches[3], '1.99', '<')) {
            $this->bitmap = 0;
            throw new UnableToConnectException("Cannot connect to SSH {$matches[3]} servers");
        }
        if (!$this->send_id_string_first) {
            fputs($this->fsock, $this->identifier . "\r\n");
        }
        if (!$this->send_kex_first) {
            $response = $this->get_binary_packet();
            if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
                $this->bitmap = 0;
                throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
            }
            $this->key_exchange($response);
        }
        if ($this->send_kex_first) {
            $this->key_exchange();
        }
        $this->bitmap |= self::MASK_CONNECTED;
        return true;
    }
    /**
     * Generates the SSH identifier
     *
     * You should overwrite this method in your own class if you want to use another identifier
     *
     * @access protected
     * @return string
     */
    private function generate_identifier()
    {
        $identifier = 'SSH-2.0-phpseclib_3.0';
        $ext = [];
        if (extension_loaded('sodium')) {
            $ext[] = 'libsodium';
        }
        if (extension_loaded('openssl')) {
            $ext[] = 'openssl';
        } elseif (extension_loaded('mcrypt')) {
            $ext[] = 'mcrypt';
        }
        if (extension_loaded('gmp')) {
            $ext[] = 'gmp';
        } elseif (extension_loaded('bcmath')) {
            $ext[] = 'bcmath';
        }
        if (!empty($ext)) {
            $identifier .= ' (' . implode(', ', $ext) . ')';
        }
        return $identifier;
    }
    /**
     * Key Exchange
     *
     * @return bool
     * @param (string | bool) $kexinit_payload_server optional
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @throws \RuntimeException on other errors
     * @throws \phpseclib3\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible
     * @access private
     */
    private function key_exchange($kexinit_payload_server = false)
    {
        $preferred = $this->preferred;
        $send_kex = true;
        $kex_algorithms = isset($preferred['kex']) ? $preferred['kex'] : SSH2::getSupportedKEXAlgorithms();
        $server_host_key_algorithms = isset($preferred['hostkey']) ? $preferred['hostkey'] : SSH2::getSupportedHostKeyAlgorithms();
        $s2c_encryption_algorithms = isset($preferred['server_to_client']['crypt']) ? $preferred['server_to_client']['crypt'] : SSH2::getSupportedEncryptionAlgorithms();
        $c2s_encryption_algorithms = isset($preferred['client_to_server']['crypt']) ? $preferred['client_to_server']['crypt'] : SSH2::getSupportedEncryptionAlgorithms();
        $s2c_mac_algorithms = isset($preferred['server_to_client']['mac']) ? $preferred['server_to_client']['mac'] : SSH2::getSupportedMACAlgorithms();
        $c2s_mac_algorithms = isset($preferred['client_to_server']['mac']) ? $preferred['client_to_server']['mac'] : SSH2::getSupportedMACAlgorithms();
        $s2c_compression_algorithms = isset($preferred['server_to_client']['comp']) ? $preferred['server_to_client']['comp'] : SSH2::getSupportedCompressionAlgorithms();
        $c2s_compression_algorithms = isset($preferred['client_to_server']['comp']) ? $preferred['client_to_server']['comp'] : SSH2::getSupportedCompressionAlgorithms();
        // some SSH servers have buggy implementations of some of the above algorithms
        switch (true) {
            case $this->server_identifier == 'SSH-2.0-SSHD':
            case \Phabel\Target\Php80\Polyfill::substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK':
                if (!isset($preferred['server_to_client']['mac'])) {
                    $s2c_mac_algorithms = array_values(array_diff($s2c_mac_algorithms, ['hmac-sha1-96', 'hmac-md5-96']));
                }
                if (!isset($preferred['client_to_server']['mac'])) {
                    $c2s_mac_algorithms = array_values(array_diff($c2s_mac_algorithms, ['hmac-sha1-96', 'hmac-md5-96']));
                }
        }
        $client_cookie = Random::string(16);
        $kexinit_payload_client = pack('Ca*', NET_SSH2_MSG_KEXINIT, $client_cookie);
        $kexinit_payload_client .= Strings::packSSH2(
            'L10bN',
            $kex_algorithms,
            $server_host_key_algorithms,
            $c2s_encryption_algorithms,
            $s2c_encryption_algorithms,
            $c2s_mac_algorithms,
            $s2c_mac_algorithms,
            $c2s_compression_algorithms,
            $s2c_compression_algorithms,
            [],
            // language, client to server
            [],
            // language, server to client
            false,
            // first_kex_packet_follows
            0
        );
        if ($kexinit_payload_server === false) {
            $this->send_binary_packet($kexinit_payload_client);
            $kexinit_payload_server = $this->get_binary_packet();
            if (!strlen($kexinit_payload_server) || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT) {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
                throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
            }
            $send_kex = false;
        }
        $response = $kexinit_payload_server;
        Strings::shift($response, 1);
        // skip past the message number (it should be SSH_MSG_KEXINIT)
        $server_cookie = Strings::shift($response, 16);
        list($this->kex_algorithms, $this->server_host_key_algorithms, $this->encryption_algorithms_client_to_server, $this->encryption_algorithms_server_to_client, $this->mac_algorithms_client_to_server, $this->mac_algorithms_server_to_client, $this->compression_algorithms_client_to_server, $this->compression_algorithms_server_to_client, $this->languages_client_to_server, $this->languages_server_to_client, $first_kex_packet_follows) = Strings::unpackSSH2('L10C', $response);
        if ($send_kex) {
            $this->send_binary_packet($kexinit_payload_client);
        }
        // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
        // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
        // diffie-hellman key exchange as fast as possible
        $decrypt = self::array_intersect_first($s2c_encryption_algorithms, $this->encryption_algorithms_server_to_client);
        $decryptKeyLength = $this->encryption_algorithm_to_key_size($decrypt);
        if ($decryptKeyLength === null) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found');
        }
        $encrypt = self::array_intersect_first($c2s_encryption_algorithms, $this->encryption_algorithms_client_to_server);
        $encryptKeyLength = $this->encryption_algorithm_to_key_size($encrypt);
        if ($encryptKeyLength === null) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found');
        }
        // through diffie-hellman key exchange a symmetric key is obtained
        $this->kex_algorithm = self::array_intersect_first($kex_algorithms, $this->kex_algorithms);
        if ($this->kex_algorithm === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found');
        }
        $server_host_key_algorithm = self::array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
        if ($server_host_key_algorithm === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found');
        }
        $mac_algorithm_out = self::array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server);
        if ($mac_algorithm_out === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found');
        }
        $mac_algorithm_in = self::array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client);
        if ($mac_algorithm_in === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found');
        }
        $compression_map = ['none' => NET_SSH2_COMPRESSION_NONE, 'zlib' => NET_SSH2_COMPRESSION_ZLIB, 'zlib@openssh.com' => NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH];
        $compression_algorithm_in = self::array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_server_to_client);
        if ($compression_algorithm_in === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found');
        }
        $this->decompress = $compression_map[$compression_algorithm_in];
        $compression_algorithm_out = self::array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
        if ($compression_algorithm_out === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found');
        }
        $this->compress = $compression_map[$compression_algorithm_out];
        switch ($this->kex_algorithm) {
            case 'diffie-hellman-group15-sha512':
            case 'diffie-hellman-group16-sha512':
            case 'diffie-hellman-group17-sha512':
            case 'diffie-hellman-group18-sha512':
            case 'ecdh-sha2-nistp521':
                $kexHash = new Hash('sha512');
                break;
            case 'ecdh-sha2-nistp384':
                $kexHash = new Hash('sha384');
                break;
            case 'diffie-hellman-group-exchange-sha256':
            case 'diffie-hellman-group14-sha256':
            case 'ecdh-sha2-nistp256':
            case 'curve25519-sha256@libssh.org':
            case 'curve25519-sha256':
                $kexHash = new Hash('sha256');
                break;
            default:
                $kexHash = new Hash('sha1');
        }
        // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
        $exchange_hash_rfc4419 = '';
        if (strpos($this->kex_algorithm, 'curve25519-sha256') === 0 || strpos($this->kex_algorithm, 'ecdh-sha2-nistp') === 0) {
            $curve = strpos($this->kex_algorithm, 'curve25519-sha256') === 0 ? 'Curve25519' : \Phabel\Target\Php80\Polyfill::substr($this->kex_algorithm, 10);
            $ourPrivate = EC::createKey($curve);
            $ourPublicBytes = $ourPrivate->getPublicKey()->getEncodedCoordinates();
            $clientKexInitMessage = 'NET_SSH2_MSG_KEX_ECDH_INIT';
            $serverKexReplyMessage = 'NET_SSH2_MSG_KEX_ECDH_REPLY';
        } else {
            if (strpos($this->kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
                $dh_group_sizes_packed = pack('NNN', $this->kex_dh_group_size_min, $this->kex_dh_group_size_preferred, $this->kex_dh_group_size_max);
                $packet = pack('Ca*', NET_SSH2_MSG_KEXDH_GEX_REQUEST, $dh_group_sizes_packed);
                $this->send_binary_packet($packet);
                $this->updateLogHistory('UNKNOWN (34)', 'NET_SSH2_MSG_KEXDH_GEX_REQUEST');
                $response = $this->get_binary_packet();
                list($type, $primeBytes, $gBytes) = Strings::unpackSSH2('Css', $response);
                if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
                    throw new \UnexpectedValueException('Expected SSH_MSG_KEX_DH_GEX_GROUP');
                }
                $this->updateLogHistory('NET_SSH2_MSG_KEXDH_REPLY', 'NET_SSH2_MSG_KEXDH_GEX_GROUP');
                $prime = new BigInteger($primeBytes, -256);
                $g = new BigInteger($gBytes, -256);
                $exchange_hash_rfc4419 = $dh_group_sizes_packed . Strings::packSSH2('ss', $primeBytes, $gBytes);
                $params = DH::createParameters($prime, $g);
                $clientKexInitMessage = 'NET_SSH2_MSG_KEXDH_GEX_INIT';
                $serverKexReplyMessage = 'NET_SSH2_MSG_KEXDH_GEX_REPLY';
            } else {
                $params = DH::createParameters($this->kex_algorithm);
                $clientKexInitMessage = 'NET_SSH2_MSG_KEXDH_INIT';
                $serverKexReplyMessage = 'NET_SSH2_MSG_KEXDH_REPLY';
            }
            $keyLength = min($kexHash->getLengthInBytes(), max($encryptKeyLength, $decryptKeyLength));
            $ourPrivate = DH::createKey($params, 16 * $keyLength);
            // 2 * 8 * $keyLength
            $ourPublic = $ourPrivate->getPublicKey()->toBigInteger();
            $ourPublicBytes = $ourPublic->toBytes(true);
        }
        $data = pack('CNa*', constant($clientKexInitMessage), strlen($ourPublicBytes), $ourPublicBytes);
        $this->send_binary_packet($data);
        switch ($clientKexInitMessage) {
            case 'NET_SSH2_MSG_KEX_ECDH_INIT':
                $this->updateLogHistory('NET_SSH2_MSG_KEXDH_INIT', 'NET_SSH2_MSG_KEX_ECDH_INIT');
                break;
            case 'NET_SSH2_MSG_KEXDH_GEX_INIT':
                $this->updateLogHistory('UNKNOWN (32)', 'NET_SSH2_MSG_KEXDH_GEX_INIT');
        }
        $response = $this->get_binary_packet();
        list($type, $server_public_host_key, $theirPublicBytes, $this->signature) = Strings::unpackSSH2('Csss', $response);
        if ($type != constant($serverKexReplyMessage)) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
            throw new \UnexpectedValueException("Expected {$serverKexReplyMessage}");
        }
        switch ($serverKexReplyMessage) {
            case 'NET_SSH2_MSG_KEX_ECDH_REPLY':
                $this->updateLogHistory('NET_SSH2_MSG_KEXDH_REPLY', 'NET_SSH2_MSG_KEX_ECDH_REPLY');
                break;
            case 'NET_SSH2_MSG_KEXDH_GEX_REPLY':
                $this->updateLogHistory('UNKNOWN (33)', 'NET_SSH2_MSG_KEXDH_GEX_REPLY');
        }
        $this->server_public_host_key = $server_public_host_key;
        list($public_key_format) = Strings::unpackSSH2('s', $server_public_host_key);
        if (strlen($this->signature) < 4) {
            throw new \LengthException('The signature needs at least four bytes');
        }
        $temp = unpack('Nlength', \Phabel\Target\Php80\Polyfill::substr($this->signature, 0, 4));
        $this->signature_format = \Phabel\Target\Php80\Polyfill::substr($this->signature, 4, $temp['length']);
        $keyBytes = DH::computeSecret($ourPrivate, $theirPublicBytes);
        if (($keyBytes & "\xff\x80") === "\x00\x00") {
            $keyBytes = \Phabel\Target\Php80\Polyfill::substr($keyBytes, 1);
        } elseif (($keyBytes[0] & "\x80") === "\x80") {
            $keyBytes = "\x00{$keyBytes}";
        }
        $this->exchange_hash = Strings::packSSH2('s5', $this->identifier, $this->server_identifier, $kexinit_payload_client, $kexinit_payload_server, $this->server_public_host_key);
        $this->exchange_hash .= $exchange_hash_rfc4419;
        $this->exchange_hash .= Strings::packSSH2('s3', $ourPublicBytes, $theirPublicBytes, $keyBytes);
        $this->exchange_hash = $kexHash->hash($this->exchange_hash);
        if ($this->session_id === false) {
            $this->session_id = $this->exchange_hash;
        }
        switch ($server_host_key_algorithm) {
            case 'rsa-sha2-256':
            case 'rsa-sha2-512':
                //case 'ssh-rsa':
                $expected_key_format = 'ssh-rsa';
                break;
            default:
                $expected_key_format = $server_host_key_algorithm;
        }
        if ($public_key_format != $expected_key_format || $this->signature_format != $server_host_key_algorithm) {
            switch (true) {
                case $this->signature_format == $server_host_key_algorithm:
                case $server_host_key_algorithm != 'rsa-sha2-256' && $server_host_key_algorithm != 'rsa-sha2-512':
                case $this->signature_format != 'ssh-rsa':
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
                    throw new \RuntimeException('Server Host Key Algorithm Mismatch (' . $this->signature_format . ' vs ' . $server_host_key_algorithm . ')');
            }
        }
        $packet = pack('C', NET_SSH2_MSG_NEWKEYS);
        $this->send_binary_packet($packet);
        $response = $this->get_binary_packet();
        if ($response === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST);
            throw new ConnectionClosedException('Connection closed by server');
        }
        list($type) = Strings::unpackSSH2('C', $response);
        if ($type != NET_SSH2_MSG_NEWKEYS) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
            throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS');
        }
        $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
        $this->encrypt = self::encryption_algorithm_to_crypt_instance($encrypt);
        if ($this->encrypt) {
            if (self::$crypto_engine) {
                $this->encrypt->setPreferredEngine(self::$crypto_engine);
            }
            if ($this->encrypt->getBlockLengthInBytes()) {
                $this->encrypt_block_size = $this->encrypt->getBlockLengthInBytes();
            }
            $this->encrypt->disablePadding();
            if ($this->encrypt->usesIV()) {
                $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
                while ($this->encrypt_block_size > strlen($iv)) {
                    $iv .= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
                }
                $this->encrypt->setIV(\Phabel\Target\Php80\Polyfill::substr($iv, 0, $this->encrypt_block_size));
            }
            switch ($encrypt) {
                case 'aes128-gcm@openssh.com':
                case 'aes256-gcm@openssh.com':
                    $nonce = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
                    $this->encrypt->fixed = \Phabel\Target\Php80\Polyfill::substr($nonce, 0, 4);
                    $this->encrypt->invocation_counter = \Phabel\Target\Php80\Polyfill::substr($nonce, 4, 8);
                case 'chacha20-poly1305@openssh.com':
                    break;
                default:
                    $this->encrypt->enableContinuousBuffer();
            }
            $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id);
            while ($encryptKeyLength > strlen($key)) {
                $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
            }
            switch ($encrypt) {
                case 'chacha20-poly1305@openssh.com':
                    $encryptKeyLength = 32;
                    $this->lengthEncrypt = self::encryption_algorithm_to_crypt_instance($encrypt);
                    $this->lengthEncrypt->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 32, 32));
            }
            $this->encrypt->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $encryptKeyLength));
            $this->encrypt->name = $encrypt;
        }
        $this->decrypt = self::encryption_algorithm_to_crypt_instance($decrypt);
        if ($this->decrypt) {
            if (self::$crypto_engine) {
                $this->decrypt->setPreferredEngine(self::$crypto_engine);
            }
            if ($this->decrypt->getBlockLengthInBytes()) {
                $this->decrypt_block_size = $this->decrypt->getBlockLengthInBytes();
            }
            $this->decrypt->disablePadding();
            if ($this->decrypt->usesIV()) {
                $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
                while ($this->decrypt_block_size > strlen($iv)) {
                    $iv .= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
                }
                $this->decrypt->setIV(\Phabel\Target\Php80\Polyfill::substr($iv, 0, $this->decrypt_block_size));
            }
            switch ($decrypt) {
                case 'aes128-gcm@openssh.com':
                case 'aes256-gcm@openssh.com':
                    // see https://tools.ietf.org/html/rfc5647#section-7.1
                    $nonce = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
                    $this->decrypt->fixed = \Phabel\Target\Php80\Polyfill::substr($nonce, 0, 4);
                    $this->decrypt->invocation_counter = \Phabel\Target\Php80\Polyfill::substr($nonce, 4, 8);
                case 'chacha20-poly1305@openssh.com':
                    break;
                default:
                    $this->decrypt->enableContinuousBuffer();
            }
            $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id);
            while ($decryptKeyLength > strlen($key)) {
                $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
            }
            switch ($decrypt) {
                case 'chacha20-poly1305@openssh.com':
                    $decryptKeyLength = 32;
                    $this->lengthDecrypt = self::encryption_algorithm_to_crypt_instance($decrypt);
                    $this->lengthDecrypt->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 32, 32));
            }
            $this->decrypt->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $decryptKeyLength));
            $this->decrypt->name = $decrypt;
        }
        /* The "arcfour128" algorithm is the RC4 cipher, as described in
                   [SCHNEIER], using a 128-bit key.  The first 1536 bytes of keystream
                   generated by the cipher MUST be discarded, and the first byte of the
                   first encrypted packet MUST be encrypted using the 1537th byte of
                   keystream.
        
                   -- http://tools.ietf.org/html/rfc4345#section-4 */
        if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') {
            $this->encrypt->encrypt(str_repeat("\x00", 1536));
        }
        if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') {
            $this->decrypt->decrypt(str_repeat("\x00", 1536));
        }
        if (!$this->encrypt->usesNonce()) {
            list($this->hmac_create, $createKeyLength) = self::mac_algorithm_to_hash_instance($mac_algorithm_out);
        } else {
            $this->hmac_create = new \stdClass();
            $this->hmac_create->name = $mac_algorithm_out;
            //$mac_algorithm_out = 'none';
            $createKeyLength = 0;
        }
        if ($this->hmac_create instanceof Hash) {
            $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id);
            while ($createKeyLength > strlen($key)) {
                $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
            }
            $this->hmac_create->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $createKeyLength));
            $this->hmac_create->name = $mac_algorithm_out;
            $this->hmac_create->etm = preg_match('#-etm@openssh\\.com$#', $mac_algorithm_out);
        }
        if (!$this->decrypt->usesNonce()) {
            list($this->hmac_check, $checkKeyLength) = self::mac_algorithm_to_hash_instance($mac_algorithm_in);
            $this->hmac_size = $this->hmac_check->getLengthInBytes();
        } else {
            $this->hmac_check = new \stdClass();
            $this->hmac_check->name = $mac_algorithm_in;
            //$mac_algorithm_in = 'none';
            $checkKeyLength = 0;
            $this->hmac_size = 0;
        }
        if ($this->hmac_check instanceof Hash) {
            $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id);
            while ($checkKeyLength > strlen($key)) {
                $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
            }
            $this->hmac_check->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $checkKeyLength));
            $this->hmac_check->name = $mac_algorithm_in;
            $this->hmac_check->etm = preg_match('#-etm@openssh\\.com$#', $mac_algorithm_in);
        }
        $this->regenerate_compression_context = $this->regenerate_decompression_context = true;
        return true;
    }
    /**
     * Maps an encryption algorithm name to the number of key bytes.
     *
     * @param string $algorithm Name of the encryption algorithm
     * @return (int | null) Number of bytes as an integer or null for unknown
     * @access private
     */
    private function encryption_algorithm_to_key_size($algorithm)
    {
        if ($this->bad_key_size_fix && self::bad_algorithm_candidate($algorithm)) {
            return 16;
        }
        switch ($algorithm) {
            case 'none':
                return 0;
            case 'aes128-gcm@openssh.com':
            case 'aes128-cbc':
            case 'aes128-ctr':
            case 'arcfour':
            case 'arcfour128':
            case 'blowfish-cbc':
            case 'blowfish-ctr':
            case 'twofish128-cbc':
            case 'twofish128-ctr':
                return 16;
            case '3des-cbc':
            case '3des-ctr':
            case 'aes192-cbc':
            case 'aes192-ctr':
            case 'twofish192-cbc':
            case 'twofish192-ctr':
                return 24;
            case 'aes256-gcm@openssh.com':
            case 'aes256-cbc':
            case 'aes256-ctr':
            case 'arcfour256':
            case 'twofish-cbc':
            case 'twofish256-cbc':
            case 'twofish256-ctr':
                return 32;
            case 'chacha20-poly1305@openssh.com':
                return 64;
        }
        return null;
    }
    /**
    * Maps an encryption algorithm name to an instance of a subclass of
    \phpseclib3\Crypt\Common\SymmetricKey.
    *
    * @param string $algorithm Name of the encryption algorithm
    * @return mixed Instance of \phpseclib3\Crypt\Common\SymmetricKey or null for unknown
    * @access private
    */
    private static function encryption_algorithm_to_crypt_instance($algorithm)
    {
        switch ($algorithm) {
            case '3des-cbc':
                return new TripleDES('cbc');
            case '3des-ctr':
                return new TripleDES('ctr');
            case 'aes256-cbc':
            case 'aes192-cbc':
            case 'aes128-cbc':
                return new Rijndael('cbc');
            case 'aes256-ctr':
            case 'aes192-ctr':
            case 'aes128-ctr':
                return new Rijndael('ctr');
            case 'blowfish-cbc':
                return new Blowfish('cbc');
            case 'blowfish-ctr':
                return new Blowfish('ctr');
            case 'twofish128-cbc':
            case 'twofish192-cbc':
            case 'twofish256-cbc':
            case 'twofish-cbc':
                return new Twofish('cbc');
            case 'twofish128-ctr':
            case 'twofish192-ctr':
            case 'twofish256-ctr':
                return new Twofish('ctr');
            case 'arcfour':
            case 'arcfour128':
            case 'arcfour256':
                return new RC4();
            case 'aes128-gcm@openssh.com':
            case 'aes256-gcm@openssh.com':
                return new Rijndael('gcm');
            case 'chacha20-poly1305@openssh.com':
                return new ChaCha20();
        }
        return null;
    }
    /**
    * Maps an encryption algorithm name to an instance of a subclass of
    \phpseclib3\Crypt\Hash.
    *
    * @param string $algorithm Name of the encryption algorithm
    * @return mixed Instance of \phpseclib3\Crypt\Hash or null for unknown
    * @access private
    */
    private static function mac_algorithm_to_hash_instance($algorithm)
    {
        switch ($algorithm) {
            case 'umac-64@openssh.com':
            case 'umac-64-etm@openssh.com':
                return [new Hash('umac-64'), 16];
            case 'umac-128@openssh.com':
            case 'umac-128-etm@openssh.com':
                return [new Hash('umac-128'), 16];
            case 'hmac-sha2-512':
            case 'hmac-sha2-512-etm@openssh.com':
                return [new Hash('sha512'), 64];
            case 'hmac-sha2-256':
            case 'hmac-sha2-256-etm@openssh.com':
                return [new Hash('sha256'), 32];
            case 'hmac-sha1':
            case 'hmac-sha1-etm@openssh.com':
                return [new Hash('sha1'), 20];
            case 'hmac-sha1-96':
                return [new Hash('sha1-96'), 20];
            case 'hmac-md5':
                return [new Hash('md5'), 16];
            case 'hmac-md5-96':
                return [new Hash('md5-96'), 16];
        }
    }
    /*
     * Tests whether or not proposed algorithm has a potential for issues
     *
     * @link https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ssh2-aesctr-openssh.html
     * @link https://bugzilla.mindrot.org/show_bug.cgi?id=1291
     * @param string $algorithm Name of the encryption algorithm
     * @return bool
     * @access private
     */
    /**
     *
     */
    private static function bad_algorithm_candidate($algorithm)
    {
        switch ($algorithm) {
            case 'arcfour256':
            case 'aes192-ctr':
            case 'aes256-ctr':
                return true;
        }
        return false;
    }
    /**
     * Login
     *
     * The $password parameter can be a plaintext password, a \phpseclib3\Crypt\RSA|EC|DSA object, a \phpseclib3\System\SSH\Agent object or an array
     *
     * @param string $username
     * @param (string | AsymmetricKey | array[] | Agent | null) ...$args
     * @return bool
     * @see self::_login()
     * @access public
     */
    public function login($username, ...$args)
    {
        $this->auth[] = func_get_args();
        // try logging with 'none' as an authentication method first since that's what
        // PuTTY does
        if (\Phabel\Target\Php80\Polyfill::substr($this->server_identifier, 0, 15) != 'SSH-2.0-CoreFTP' && $this->auth_methods_to_continue === null) {
            if ($this->sublogin($username)) {
                return true;
            }
            if (!count($args)) {
                return false;
            }
        }
        return $this->sublogin($username, ...$args);
    }
    /**
     * Login Helper
     *
     * @param string $username
     * @param string[] ...$args
     * @return bool
     * @see self::_login_helper()
     * @access private
     */
    protected function sublogin($username, ...$args)
    {
        if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
            $this->connect();
        }
        if (empty($args)) {
            return $this->login_helper($username);
        }
        while (count($args)) {
            if (!$this->auth_methods_to_continue || !$this->smartMFA) {
                $newargs = $args;
                $args = [];
            } else {
                $newargs = [];
                foreach ($this->auth_methods_to_continue as $method) {
                    switch ($method) {
                        case 'publickey':
                            foreach ($args as $key => $arg) {
                                if ($arg instanceof PrivateKey || $arg instanceof Agent) {
                                    $newargs[] = $arg;
                                    unset($args[$key]);
                                    break;
                                }
                            }
                            break;
                        case 'keyboard-interactive':
                            $hasArray = $hasString = false;
                            foreach ($args as $arg) {
                                if ($hasArray || is_array($arg)) {
                                    $hasArray = true;
                                    break;
                                }
                                if ($hasString || is_string($arg)) {
                                    $hasString = true;
                                    break;
                                }
                            }
                            if ($hasArray && $hasString) {
                                foreach ($args as $key => $arg) {
                                    if (is_array($arg)) {
                                        $newargs[] = $arg;
                                        break 2;
                                    }
                                }
                            }
                        case 'password':
                            foreach ($args as $key => $arg) {
                                $newargs[] = $arg;
                                unset($args[$key]);
                                break;
                            }
                    }
                }
            }
            foreach ($newargs as $arg) {
                if ($this->login_helper($username, $arg)) {
                    return true;
                }
            }
        }
        return false;
    }
    /**
    * Login Helper
    *
    * {@internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
    by sending dummy SSH_MSG_IGNORE messages.}
    *
    * @param string $username
    * @param (string | AsymmetricKey | array[] | Agent | null) ...$args
    * @return bool
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @throws \RuntimeException on other errors
    * @access private
    */
    private function login_helper($username, $password = null)
    {
        if (!($this->bitmap & self::MASK_CONNECTED)) {
            return false;
        }
        if (!($this->bitmap & self::MASK_LOGIN_REQ)) {
            $packet = Strings::packSSH2('Cs', NET_SSH2_MSG_SERVICE_REQUEST, 'ssh-userauth');
            $this->send_binary_packet($packet);
            try {
                $response = $this->get_binary_packet();
            } catch (\Exception $e) {
                if ($this->retry_connect) {
                    $this->retry_connect = false;
                    $this->connect();
                    return $this->login_helper($username, $password);
                }
                $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST);
                throw new ConnectionClosedException('Connection closed by server');
            }
            list($type, $service) = Strings::unpackSSH2('Cs', $response);
            if ($type != NET_SSH2_MSG_SERVICE_ACCEPT || $service != 'ssh-userauth') {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
                throw new \UnexpectedValueException('Expected SSH_MSG_SERVICE_ACCEPT');
            }
            $this->bitmap |= self::MASK_LOGIN_REQ;
        }
        if (strlen($this->last_interactive_response)) {
            return !is_string($password) && !is_array($password) ? false : $this->keyboard_interactive_process($password);
        }
        if ($password instanceof PrivateKey) {
            return $this->privatekey_login($username, $password);
        }
        if ($password instanceof Agent) {
            return $this->ssh_agent_login($username, $password);
        }
        if (is_array($password)) {
            if ($this->keyboard_interactive_login($username, $password)) {
                $this->bitmap |= self::MASK_LOGIN;
                return true;
            }
            return false;
        }
        if (!isset($password)) {
            $packet = Strings::packSSH2('Cs3', NET_SSH2_MSG_USERAUTH_REQUEST, $username, 'ssh-connection', 'none');
            $this->send_binary_packet($packet);
            $response = $this->get_binary_packet();
            list($type) = Strings::unpackSSH2('C', $response);
            switch ($type) {
                case NET_SSH2_MSG_USERAUTH_SUCCESS:
                    $this->bitmap |= self::MASK_LOGIN;
                    return true;
                case NET_SSH2_MSG_USERAUTH_FAILURE:
                    list($auth_methods) = Strings::unpackSSH2('L', $response);
                    $this->auth_methods_to_continue = $auth_methods;
                default:
                    return false;
            }
        }
        if (!is_string($password)) {
            throw new \UnexpectedValueException('$password needs to either be an instance of \\phpseclib3\\Crypt\\Common\\PrivateKey, \\System\\SSH\\Agent, an array or a string');
        }
        $packet = Strings::packSSH2('Cs3bs', NET_SSH2_MSG_USERAUTH_REQUEST, $username, 'ssh-connection', 'password', false, $password);
        // remove the username and password from the logged packet
        if (!defined('NET_SSH2_LOGGING')) {
            $logged = null;
        } else {
            $logged = Strings::packSSH2('Cs3bs', NET_SSH2_MSG_USERAUTH_REQUEST, $username, 'ssh-connection', 'password', false, 'password');
        }
        $this->send_binary_packet($packet, $logged);
        $response = $this->get_binary_packet();
        list($type) = Strings::unpackSSH2('C', $response);
        switch ($type) {
            case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ:
                // in theory, the password can be changed
                $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ');
                list($message) = Strings::unpackSSH2('s', $response);
                $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . $message;
                return $this->disconnect_helper(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
            case NET_SSH2_MSG_USERAUTH_FAILURE:
                // can we use keyboard-interactive authentication?  if not then either the login is bad or the server employees
                // multi-factor authentication
                list($auth_methods, $partial_success) = Strings::unpackSSH2('Lb', $response);
                $this->auth_methods_to_continue = $auth_methods;
                if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) {
                    if ($this->keyboard_interactive_login($username, $password)) {
                        $this->bitmap |= self::MASK_LOGIN;
                        return true;
                    }
                    return false;
                }
                return false;
            case NET_SSH2_MSG_USERAUTH_SUCCESS:
                $this->bitmap |= self::MASK_LOGIN;
                return true;
        }
        return false;
    }
    /**
     * Login via keyboard-interactive authentication
     *
     * See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details.  This is not a full-featured keyboard-interactive authenticator.
     *
     * @param string $username
     * @param string $password
     * @return bool
     * @access private
     */
    private function keyboard_interactive_login($username, $password)
    {
        $packet = Strings::packSSH2(
            'Cs5',
            NET_SSH2_MSG_USERAUTH_REQUEST,
            $username,
            'ssh-connection',
            'keyboard-interactive',
            '',
            // language tag
            ''
        );
        $this->send_binary_packet($packet);
        return $this->keyboard_interactive_process($password);
    }
    /**
     * Handle the keyboard-interactive requests / responses.
     *
     * @param mixed[] ...$responses
     * @return bool
     * @throws \RuntimeException on connection error
     * @access private
     */
    private function keyboard_interactive_process(...$responses)
    {
        if (strlen($this->last_interactive_response)) {
            $response = $this->last_interactive_response;
        } else {
            $orig = $response = $this->get_binary_packet();
        }
        list($type) = Strings::unpackSSH2('C', $response);
        switch ($type) {
            case NET_SSH2_MSG_USERAUTH_INFO_REQUEST:
                list(, , , $num_prompts) = Strings::unpackSSH2('s3N', $response);
                for ($i = 0; $i < count($responses); $i++) {
                    if (is_array($responses[$i])) {
                        foreach ($responses[$i] as $key => $value) {
                            $this->keyboard_requests_responses[$key] = $value;
                        }
                        unset($responses[$i]);
                    }
                }
                $responses = array_values($responses);
                if (isset($this->keyboard_requests_responses)) {
                    for ($i = 0; $i < $num_prompts; $i++) {
                        list($prompt, ) = Strings::unpackSSH2('sC', $response);
                        foreach ($this->keyboard_requests_responses as $key => $value) {
                            if (\Phabel\Target\Php80\Polyfill::substr($prompt, 0, strlen($key)) == $key) {
                                $responses[] = $value;
                                break;
                            }
                        }
                    }
                }
                // see http://tools.ietf.org/html/rfc4256#section-3.2
                if (strlen($this->last_interactive_response)) {
                    $this->last_interactive_response = '';
                } else {
                    $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST');
                }
                if (!count($responses) && $num_prompts) {
                    $this->last_interactive_response = $orig;
                    return false;
                }
                /*
                   After obtaining the requested information from the user, the client
                   MUST respond with an SSH_MSG_USERAUTH_INFO_RESPONSE message.
                */
                // see http://tools.ietf.org/html/rfc4256#section-3.4
                $packet = $logged = pack('CN', NET_SSH2_MSG_USERAUTH_INFO_RESPONSE, count($responses));
                for ($i = 0; $i < count($responses); $i++) {
                    $packet .= Strings::packSSH2('s', $responses[$i]);
                    $logged .= Strings::packSSH2('s', 'dummy-answer');
                }
                $this->send_binary_packet($packet, $logged);
                $this->updateLogHistory('UNKNOWN (61)', 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE');
                /*
                   After receiving the response, the server MUST send either an
                   SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another
                   SSH_MSG_USERAUTH_INFO_REQUEST message.
                */
                // maybe phpseclib should force close the connection after x request / responses?  unless something like that is done
                // there could be an infinite loop of request / responses.
                return $this->keyboard_interactive_process();
            case NET_SSH2_MSG_USERAUTH_SUCCESS:
                return true;
            case NET_SSH2_MSG_USERAUTH_FAILURE:
                list($auth_methods) = Strings::unpackSSH2('L', $response);
                $this->auth_methods_to_continue = $auth_methods;
                return false;
        }
        return false;
    }
    /**
     * Login with an ssh-agent provided key
     *
     * @param string $username
     * @param \phpseclib3\System\SSH\Agent $agent
     * @return bool
     * @access private
     */
    private function ssh_agent_login($username, Agent $agent)
    {
        $this->agent = $agent;
        $keys = $agent->requestIdentities();
        foreach ($keys as $key) {
            if ($this->privatekey_login($username, $key)) {
                return true;
            }
        }
        return false;
    }
    /**
    * Login with an RSA private key
    *
    * {@internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
    by sending dummy SSH_MSG_IGNORE messages.}
    *
    * @param string $username
    * @param \phpseclib3\Crypt\Common\PrivateKey $privatekey
    * @return bool
    * @throws \RuntimeException on connection error
    * @access private
    */
    private function privatekey_login($username, PrivateKey $privatekey)
    {
        $publickey = $privatekey->getPublicKey();
        if ($publickey instanceof RSA) {
            $privatekey = $privatekey->withPadding(RSA::SIGNATURE_PKCS1);
            $algos = ['rsa-sha2-256', 'rsa-sha2-512', 'ssh-rsa'];
            if (isset($this->preferred['hostkey'])) {
                $algos = array_intersect($this->preferred['hostkey'], $algos);
            }
            $algo = self::array_intersect_first($algos, $this->server_host_key_algorithms);
            switch ($algo) {
                case 'rsa-sha2-512':
                    $hash = 'sha512';
                    $signatureType = 'rsa-sha2-512';
                    break;
                case 'rsa-sha2-256':
                    $hash = 'sha256';
                    $signatureType = 'rsa-sha2-256';
                    break;
                //case 'ssh-rsa':
                default:
                    $hash = 'sha1';
                    $signatureType = 'ssh-rsa';
            }
        } else {
            if ($publickey instanceof EC) {
                $privatekey = $privatekey->withSignatureFormat('SSH2');
                $curveName = $privatekey->getCurve();
                switch ($curveName) {
                    case 'Ed25519':
                        $hash = 'sha512';
                        $signatureType = 'ssh-ed25519';
                        break;
                    case 'secp256r1':
                        // nistp256
                        $hash = 'sha256';
                        $signatureType = 'ecdsa-sha2-nistp256';
                        break;
                    case 'secp384r1':
                        // nistp384
                        $hash = 'sha384';
                        $signatureType = 'ecdsa-sha2-nistp384';
                        break;
                    case 'secp521r1':
                        // nistp521
                        $hash = 'sha512';
                        $signatureType = 'ecdsa-sha2-nistp521';
                        break;
                    default:
                        if (is_array($curveName)) {
                            throw new UnsupportedCurveException('Specified Curves are not supported by SSH2');
                        }
                        throw new UnsupportedCurveException('Named Curve of ' . $curveName . ' is not supported by phpseclib3\'s SSH2 implementation');
                }
            } else {
                if ($publickey instanceof DSA) {
                    $privatekey = $privatekey->withSignatureFormat('SSH2');
                    $hash = 'sha1';
                    $signatureType = 'ssh-dss';
                } else {
                    throw new UnsupportedAlgorithmException('Please use either an RSA key, an EC one or a DSA key');
                }
            }
        }
        $publickeyStr = $publickey->toString('OpenSSH', ['binary' => true]);
        $part1 = Strings::packSSH2('Csss', NET_SSH2_MSG_USERAUTH_REQUEST, $username, 'ssh-connection', 'publickey');
        $part2 = Strings::packSSH2('ss', $signatureType, $publickeyStr);
        $packet = $part1 . chr(0) . $part2;
        $this->send_binary_packet($packet);
        $response = $this->get_binary_packet();
        list($type) = Strings::unpackSSH2('C', $response);
        switch ($type) {
            case NET_SSH2_MSG_USERAUTH_FAILURE:
                list($auth_methods) = Strings::unpackSSH2('L', $response);
                $this->auth_methods_to_continue = $auth_methods;
                $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE';
                return false;
            case NET_SSH2_MSG_USERAUTH_PK_OK:
                // we'll just take it on faith that the public key blob and the public key algorithm name are as
                // they should be
                $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PK_OK');
                break;
            case NET_SSH2_MSG_USERAUTH_SUCCESS:
                $this->bitmap |= self::MASK_LOGIN;
                return true;
            default:
                $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                throw new ConnectionClosedException('Unexpected response to publickey authentication pt 1');
        }
        $packet = $part1 . chr(1) . $part2;
        $privatekey = $privatekey->withHash($hash);
        $signature = $privatekey->sign(Strings::packSSH2('s', $this->session_id) . $packet);
        if ($publickey instanceof RSA) {
            $signature = Strings::packSSH2('ss', $signatureType, $signature);
        }
        $packet .= Strings::packSSH2('s', $signature);
        $this->send_binary_packet($packet);
        $response = $this->get_binary_packet();
        list($type) = Strings::unpackSSH2('C', $response);
        switch ($type) {
            case NET_SSH2_MSG_USERAUTH_FAILURE:
                // either the login is bad or the server employs multi-factor authentication
                list($auth_methods) = Strings::unpackSSH2('L', $response);
                $this->auth_methods_to_continue = $auth_methods;
                return false;
            case NET_SSH2_MSG_USERAUTH_SUCCESS:
                $this->bitmap |= self::MASK_LOGIN;
                return true;
        }
        $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
        throw new ConnectionClosedException('Unexpected response to publickey authentication pt 2');
    }
    /**
    * Set Timeout
    *
    * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely.  setTimeout() makes it so it'll timeout.
    Setting $timeout to false or 0 will mean there is no timeout.
    *
    * @param mixed $timeout
    * @access public
    */
    public function setTimeout($timeout)
    {
        $this->timeout = $this->curTimeout = $timeout;
    }
    /**
     * Set Keep Alive
     *
     * Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number.
     *
     * @param int $interval
     * @access public
     */
    function setKeepAlive($interval)
    {
        $this->keepAlive = $interval;
    }
    /**
     * Get the output from stdError
     *
     * @access public
     */
    public function getStdError()
    {
        return $this->stdErrorLog;
    }
    /**
    * Execute Command
    *
    * If $callback is set to false then \phpseclib3\Net\SSH2::get_channel_packet(self::CHANNEL_EXEC) will need to be called manually.
    In all likelihood, this is not a feature you want to be taking advantage of.
    *
    * @param string $command
    * @param callback $callback
    * @return string
    * @throws \RuntimeException on connection error
    * @access public
    */
    public function exec($command, $callback = null)
    {
        $this->curTimeout = $this->timeout;
        $this->is_timeout = false;
        $this->stdErrorLog = '';
        if (!$this->isAuthenticated()) {
            return false;
        }
        if ($this->in_request_pty_exec) {
            throw new \RuntimeException('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
        }
        // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
        // be adjusted".  0x7FFFFFFF is, at 2GB, the max size.  technically, it should probably be decremented, but,
        // honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway.
        // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
        $this->window_size_server_to_client[self::CHANNEL_EXEC] = $this->window_size;
        // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
        // uses 0x4000, that's what will be used here, as well.
        $packet_size = 0x4000;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL_EXEC, $this->window_size_server_to_client[self::CHANNEL_EXEC], $packet_size);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
        $this->get_channel_packet(self::CHANNEL_EXEC);
        if ($this->request_pty === true) {
            $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
            $packet = Strings::packSSH2('CNsCsN4s', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_EXEC], 'pty-req', 1, $this->term, $this->windowColumns, $this->windowRows, 0, 0, $terminal_modes);
            $this->send_binary_packet($packet);
            $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
            if (!$this->get_channel_packet(self::CHANNEL_EXEC)) {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                throw new \RuntimeException('Unable to request pseudo-terminal');
            }
            $this->in_request_pty_exec = true;
        }
        // sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things
        // down.  the one place where it might be desirable is if you're doing something like \phpseclib3\Net\SSH2::exec('ping localhost &').
        // with a pty-req SSH_MSG_CHANNEL_REQUEST, exec() will return immediately and the ping process will then
        // then immediately terminate.  without such a request exec() will loop indefinitely.  the ping process won't end but
        // neither will your script.
        // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by
        // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the
        // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA.  RFC4254#section-5.2 corroborates.
        $packet = Strings::packSSH2('CNsCs', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_EXEC], 'exec', 1, $command);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
        if (!$this->get_channel_packet(self::CHANNEL_EXEC)) {
            return false;
        }
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA;
        if ($callback === false || $this->in_request_pty_exec) {
            return true;
        }
        $output = '';
        while (true) {
            $temp = $this->get_channel_packet(self::CHANNEL_EXEC);
            switch (true) {
                case $temp === true:
                    return is_callable($callback) ? true : $output;
                case $temp === false:
                    return false;
                default:
                    if (is_callable($callback)) {
                        if ($callback($temp) === true) {
                            $this->close_channel(self::CHANNEL_EXEC);
                            return true;
                        }
                    } else {
                        $output .= $temp;
                    }
            }
        }
    }
    /**
     * Creates an interactive shell
     *
     * @see self::read()
     * @see self::write()
     * @return bool
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @throws \RuntimeException on other errors
     * @access private
     */
    private function initShell()
    {
        if ($this->in_request_pty_exec === true) {
            return true;
        }
        $this->window_size_server_to_client[self::CHANNEL_SHELL] = $this->window_size;
        $packet_size = 0x4000;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL_SHELL, $this->window_size_server_to_client[self::CHANNEL_SHELL], $packet_size);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
        $this->get_channel_packet(self::CHANNEL_SHELL);
        $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
        $packet = Strings::packSSH2(
            'CNsbsN4s',
            NET_SSH2_MSG_CHANNEL_REQUEST,
            $this->server_channels[self::CHANNEL_SHELL],
            'pty-req',
            true,
            // want reply
            $this->term,
            $this->windowColumns,
            $this->windowRows,
            0,
            0,
            $terminal_modes
        );
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
        if (!$this->get_channel_packet(self::CHANNEL_SHELL)) {
            throw new \RuntimeException('Unable to request pty');
        }
        $packet = Strings::packSSH2('CNsb', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_SHELL], 'shell', true);
        $this->send_binary_packet($packet);
        $response = $this->get_channel_packet(self::CHANNEL_SHELL);
        if ($response === false) {
            throw new \RuntimeException('Unable to request shell');
        }
        $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
        $this->bitmap |= self::MASK_SHELL;
        return true;
    }
    /**
     * Return the channel to be used with read() / write()
     *
     * @see self::read()
     * @see self::write()
     * @return int
     * @access public
     */
    private function get_interactive_channel()
    {
        switch (true) {
            case $this->in_subsystem:
                return self::CHANNEL_SUBSYSTEM;
            case $this->in_request_pty_exec:
                return self::CHANNEL_EXEC;
            default:
                return self::CHANNEL_SHELL;
        }
    }
    /**
     * Return an available open channel
     *
     * @return int
     * @access public
     */
    private function get_open_channel()
    {
        $channel = self::CHANNEL_EXEC;
        do {
            if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) {
                return $channel;
            }
        } while ($channel++ < self::CHANNEL_SUBSYSTEM);
        return false;
    }
    /**
     * Request agent forwarding of remote server
     *
     * @return bool
     * @access public
     */
    public function requestAgentForwarding()
    {
        $request_channel = $this->get_open_channel();
        if ($request_channel === false) {
            return false;
        }
        $packet = Strings::packSSH2('CNsC', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[$request_channel], 'auth-agent-req@openssh.com', 1);
        $this->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
        $this->send_binary_packet($packet);
        if (!$this->get_channel_packet($request_channel)) {
            return false;
        }
        $this->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
        return true;
    }
    /**
    * Returns the output of an interactive shell
    *
    * Returns when there's a match for $expect, which can take the form of a string literal or,
    if $mode == self::READ_REGEX, a regular expression.
    *
    * @see self::write()
    * @param string $expect
    * @param int $mode
    * @return (string | bool | null)
    * @throws \RuntimeException on connection error
    * @access public
    */
    public function read($expect = '', $mode = self::READ_SIMPLE)
    {
        $this->curTimeout = $this->timeout;
        $this->is_timeout = false;
        if (!$this->isAuthenticated()) {
            throw new InsufficientSetupException('Operation disallowed prior to login()');
        }
        if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) {
            throw new \RuntimeException('Unable to initiate an interactive shell session');
        }
        $channel = $this->get_interactive_channel();
        if ($mode == self::READ_NEXT) {
            return $this->get_channel_packet($channel);
        }
        $match = $expect;
        while (true) {
            if ($mode == self::READ_REGEX) {
                preg_match($expect, \Phabel\Target\Php80\Polyfill::substr($this->interactiveBuffer, -1024), $matches);
                $match = isset($matches[0]) ? $matches[0] : '';
            }
            $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
            if ($pos !== false) {
                return Strings::shift($this->interactiveBuffer, $pos + strlen($match));
            }
            $response = $this->get_channel_packet($channel);
            if ($response === true) {
                $this->in_request_pty_exec = false;
                return Strings::shift($this->interactiveBuffer, strlen($this->interactiveBuffer));
            }
            $this->interactiveBuffer .= $response;
        }
    }
    /**
     * Inputs a command into an interactive shell.
     *
     * @see self::read()
     * @param string $cmd
     * @return bool
     * @throws \RuntimeException on connection error
     * @access public
     */
    public function write($cmd)
    {
        if (!$this->isAuthenticated()) {
            throw new InsufficientSetupException('Operation disallowed prior to login()');
        }
        if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) {
            throw new \RuntimeException('Unable to initiate an interactive shell session');
        }
        return $this->send_channel_packet($this->get_interactive_channel(), $cmd);
    }
    /**
    * Start a subsystem.
    *
    * Right now only one subsystem at a time is supported. To support multiple subsystem's stopSubsystem() could accept
    a string that contained the name of the subsystem, but at that point, only one subsystem of each type could be opened.
    To support multiple subsystem's of the same name maybe it'd be best if startSubsystem() generated a new channel id and
    returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented
    if there's sufficient demand for such a feature.
    *
    * @see self::stopSubsystem()
    * @param string $subsystem
    * @return bool
    * @access public
    */
    public function startSubsystem($subsystem)
    {
        $this->window_size_server_to_client[self::CHANNEL_SUBSYSTEM] = $this->window_size;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL_SUBSYSTEM, $this->window_size, 0x4000);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
        $this->get_channel_packet(self::CHANNEL_SUBSYSTEM);
        $packet = Strings::packSSH2('CNsCs', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_SUBSYSTEM], 'subsystem', 1, $subsystem);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST;
        if (!$this->get_channel_packet(self::CHANNEL_SUBSYSTEM)) {
            return false;
        }
        $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
        $this->bitmap |= self::MASK_SHELL;
        $this->in_subsystem = true;
        return true;
    }
    /**
     * Stops a subsystem.
     *
     * @see self::startSubsystem()
     * @return bool
     * @access public
     */
    public function stopSubsystem()
    {
        $this->in_subsystem = false;
        $this->close_channel(self::CHANNEL_SUBSYSTEM);
        return true;
    }
    /**
     * Closes a channel
     *
     * If read() timed out you might want to just close the channel and have it auto-restart on the next read() call
     *
     * @access public
     */
    public function reset()
    {
        $this->close_channel($this->get_interactive_channel());
    }
    /**
     * Is timeout?
     *
     * Did exec() or read() return because they timed out or because they encountered the end?
     *
     * @access public
     */
    public function isTimeout()
    {
        return $this->is_timeout;
    }
    /**
     * Disconnect
     *
     * @access public
     */
    public function disconnect()
    {
        $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
        if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) {
            fclose($this->realtime_log_file);
        }
        unset(self::$connections[$this->getResourceId()]);
    }
    /**
    * Destructor.
    *
    * Will be called, automatically, if you're supporting just PHP5.  If you're supporting PHP4, you'll need to call
    disconnect().
    *
    * @access public
    */
    public function __destruct()
    {
        $this->disconnect();
    }
    /**
     * Is the connection still active?
     *
     * @return bool
     * @access public
     */
    public function isConnected()
    {
        return (bool) ($this->bitmap & self::MASK_CONNECTED);
    }
    /**
     * Have you successfully been logged in?
     *
     * @return bool
     * @access public
     */
    public function isAuthenticated()
    {
        return (bool) ($this->bitmap & self::MASK_LOGIN);
    }
    /**
     * Pings a server connection, or tries to reconnect if the connection has gone down
     *
     * Inspired by http://php.net/manual/en/mysqli.ping.php
     *
     * @return bool
     */
    public function ping()
    {
        if (!$this->isAuthenticated()) {
            if (!empty($this->auth)) {
                return $this->reconnect();
            }
            return false;
        }
        $this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE] = $this->window_size;
        $packet_size = 0x4000;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL_KEEP_ALIVE, $this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE], $packet_size);
        try {
            $this->send_binary_packet($packet);
            $this->channel_status[self::CHANNEL_KEEP_ALIVE] = NET_SSH2_MSG_CHANNEL_OPEN;
            $response = $this->get_channel_packet(self::CHANNEL_KEEP_ALIVE);
        } catch (\RuntimeException $e) {
            return $this->reconnect();
        }
        $this->close_channel(self::CHANNEL_KEEP_ALIVE);
        return true;
    }
    /**
     * In situ reconnect method
     *
     * @return boolean
     */
    private function reconnect()
    {
        $this->reset_connection(NET_SSH2_DISCONNECT_CONNECTION_LOST);
        $this->retry_connect = true;
        $this->connect();
        foreach ($this->auth as $auth) {
            $result = $this->login(...$auth);
        }
        return $result;
    }
    /**
     * Resets a connection for re-use
     *
     * @param int $reason
     * @access private
     */
    protected function reset_connection($reason)
    {
        $this->disconnect_helper($reason);
        $this->decrypt = $this->encrypt = false;
        $this->decrypt_block_size = $this->encrypt_block_size = 8;
        $this->hmac_check = $this->hmac_create = false;
        $this->hmac_size = false;
        $this->session_id = false;
        $this->retry_connect = true;
        $this->get_seq_no = $this->send_seq_no = 0;
    }
    /**
     * Gets Binary Packets
     *
     * See '6. Binary Packet Protocol' of rfc4253 for more info.
     *
     * @see self::_send_binary_packet()
     * @param bool $skip_channel_filter
     * @return string
     * @access private
     */
    private function get_binary_packet($skip_channel_filter = false)
    {
        if ($skip_channel_filter) {
            $read = [$this->fsock];
            $write = $except = null;
            if (!$this->curTimeout) {
                if ($this->keepAlive <= 0) {
                    @stream_select($read, $write, $except, null);
                } else {
                    if (!@stream_select($read, $write, $except, $this->keepAlive)) {
                        $this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
                        return $this->get_binary_packet(true);
                    }
                }
            } else {
                if ($this->curTimeout < 0) {
                    $this->is_timeout = true;
                    return true;
                }
                $read = [$this->fsock];
                $write = $except = null;
                $start = microtime(true);
                if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) {
                    if (!@stream_select($read, $write, $except, $this->keepAlive)) {
                        $this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
                        $elapsed = microtime(true) - $start;
                        $this->curTimeout -= $elapsed;
                        return $this->get_binary_packet(true);
                    }
                    $elapsed = microtime(true) - $start;
                    $this->curTimeout -= $elapsed;
                }
                $sec = floor($this->curTimeout);
                $usec = 1000000 * ($this->curTimeout - $sec);
                // this can return a "stream_select(): unable to select [4]: Interrupted system call" error
                if (!@stream_select($read, $write, $except, $sec, $usec)) {
                    $this->is_timeout = true;
                    return true;
                }
                $elapsed = microtime(true) - $start;
                $this->curTimeout -= $elapsed;
            }
        }
        if (!is_resource($this->fsock) || feof($this->fsock)) {
            $this->bitmap = 0;
            throw new ConnectionClosedException('Connection closed (by server) prematurely ' . $elapsed . 's');
        }
        $start = microtime(true);
        $raw = stream_get_contents($this->fsock, $this->decrypt_block_size);
        if (!strlen($raw)) {
            $this->bitmap = 0;
            throw new ConnectionClosedException('No data received from server');
        }
        if ($this->decrypt) {
            switch ($this->decrypt->name) {
                case 'aes128-gcm@openssh.com':
                case 'aes256-gcm@openssh.com':
                    $this->decrypt->setNonce($this->decrypt->fixed . $this->decrypt->invocation_counter);
                    Strings::increment_str($this->decrypt->invocation_counter);
                    $this->decrypt->setAAD($temp = Strings::shift($raw, 4));
                    extract(unpack('Npacket_length', $temp));
                    /**
                     * @var integer $packet_length
                     */
                    $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4);
                    $stop = microtime(true);
                    $tag = stream_get_contents($this->fsock, $this->decrypt_block_size);
                    $this->decrypt->setTag($tag);
                    $raw = $this->decrypt->decrypt($raw);
                    $raw = $temp . $raw;
                    $remaining_length = 0;
                    break;
                case 'chacha20-poly1305@openssh.com':
                    $nonce = pack('N2', 0, $this->get_seq_no);
                    $this->lengthDecrypt->setNonce($nonce);
                    $temp = $this->lengthDecrypt->decrypt($aad = Strings::shift($raw, 4));
                    extract(unpack('Npacket_length', $temp));
                    /**
                     * @var integer $packet_length
                     */
                    $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4);
                    $stop = microtime(true);
                    $tag = stream_get_contents($this->fsock, 16);
                    $this->decrypt->setNonce($nonce);
                    $this->decrypt->setCounter(0);
                    // this is the same approach that's implemented in Salsa20::createPoly1305Key()
                    // but we don't want to use the same AEAD construction that RFC8439 describes
                    // for ChaCha20-Poly1305 so we won't rely on it (see Salsa20::poly1305())
                    $this->decrypt->setPoly1305Key($this->decrypt->encrypt(str_repeat("\x00", 32)));
                    $this->decrypt->setAAD($aad);
                    $this->decrypt->setCounter(1);
                    $this->decrypt->setTag($tag);
                    $raw = $this->decrypt->decrypt($raw);
                    $raw = $temp . $raw;
                    $remaining_length = 0;
                    break;
                default:
                    if (!$this->hmac_check instanceof Hash || !$this->hmac_check->etm) {
                        $raw = $this->decrypt->decrypt($raw);
                        break;
                    }
                    extract(unpack('Npacket_length', $temp = Strings::shift($raw, 4)));
                    /**
                     * @var integer $packet_length
                     */
                    $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4);
                    $stop = microtime(true);
                    $encrypted = $temp . $raw;
                    $raw = $temp . $this->decrypt->decrypt($raw);
                    $remaining_length = 0;
            }
        }
        if (strlen($raw) < 5) {
            $this->bitmap = 0;
            throw new \RuntimeException('Plaintext is too short');
        }
        extract(unpack('Npacket_length/Cpadding_length', Strings::shift($raw, 5)));
        /**
         * @var integer $packet_length
         * @var integer $padding_length
         */
        if (!isset($remaining_length)) {
            $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
        }
        $buffer = $this->read_remaining_bytes($remaining_length);
        if (!isset($stop)) {
            $stop = microtime(true);
        }
        if (strlen($buffer)) {
            $raw .= $this->decrypt ? $this->decrypt->decrypt($buffer) : $buffer;
        }
        $payload = Strings::shift($raw, $packet_length - $padding_length - 1);
        $padding = Strings::shift($raw, $padding_length);
        // should leave $raw empty
        if ($this->hmac_check instanceof Hash) {
            $hmac = stream_get_contents($this->fsock, $this->hmac_size);
            if ($hmac === false || strlen($hmac) != $this->hmac_size) {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR);
                throw new \RuntimeException('Error reading socket');
            }
            $reconstructed = !$this->hmac_check->etm ? pack('NCa*', $packet_length, $padding_length, $payload . $padding) : $encrypted;
            if (($this->hmac_check->getHash() & "\xff\xff\xff\xff") == 'umac') {
                $this->hmac_check->setNonce("\x00\x00\x00\x00" . pack('N', $this->get_seq_no));
                if ($hmac != $this->hmac_check->hash($reconstructed)) {
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR);
                    throw new \RuntimeException('Invalid UMAC');
                }
            } else {
                if ($hmac != $this->hmac_check->hash(pack('Na*', $this->get_seq_no, $reconstructed))) {
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR);
                    throw new \RuntimeException('Invalid HMAC');
                }
            }
        }
        switch ($this->decompress) {
            case NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH:
                if (!$this->isAuthenticated()) {
                    break;
                }
            case NET_SSH2_COMPRESSION_ZLIB:
                if ($this->regenerate_decompression_context) {
                    $this->regenerate_decompression_context = false;
                    $cmf = ord($payload[0]);
                    $cm = $cmf & 0xf;
                    if ($cm != 8) {
                        // deflate
                        user_error("Only CM = 8 ('deflate') is supported ({$cm})");
                    }
                    $cinfo = ($cmf & 0xf0) >> 4;
                    if ($cinfo > 7) {
                        user_error("CINFO above 7 is not allowed ({$cinfo})");
                    }
                    $windowSize = 1 << $cinfo + 8;
                    $flg = ord($payload[1]);
                    //$fcheck = $flg && 0x0F;
                    if (($cmf << 8 | $flg) % 31) {
                        user_error('fcheck failed');
                    }
                    $fdict = boolval($flg & 0x20);
                    $flevel = ($flg & 0xc0) >> 6;
                    $this->decompress_context = inflate_init(ZLIB_ENCODING_RAW, ['window' => $cinfo + 8]);
                    $payload = \Phabel\Target\Php80\Polyfill::substr($payload, 2);
                }
                if ($this->decompress_context) {
                    $payload = inflate_add($this->decompress_context, $payload, ZLIB_PARTIAL_FLUSH);
                }
        }
        $this->get_seq_no++;
        if (defined('NET_SSH2_LOGGING')) {
            $current = microtime(true);
            $message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')';
            $message_number = '<- ' . $message_number . ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
            $this->append_log($message_number, $payload);
            $this->last_packet = $current;
        }
        return $this->filter($payload, $skip_channel_filter);
    }
    /**
     * Read Remaining Bytes
     *
     * @see self::get_binary_packet()
     * @param int $remaining_length
     * @return string
     * @access private
     */
    private function read_remaining_bytes($remaining_length)
    {
        if (!$remaining_length) {
            return '';
        }
        $adjustLength = false;
        if ($this->decrypt) {
            switch (true) {
                case $this->decrypt->name == 'aes128-gcm@openssh.com':
                case $this->decrypt->name == 'aes256-gcm@openssh.com':
                case $this->decrypt->name == 'chacha20-poly1305@openssh.com':
                case $this->hmac_check instanceof Hash && $this->hmac_check->etm:
                    $remaining_length += $this->decrypt_block_size - 4;
                    $adjustLength = true;
            }
        }
        // quoting <http://tools.ietf.org/html/rfc4253#section-6.1>,
        // "implementations SHOULD check that the packet length is reasonable"
        // PuTTY uses 0x9000 as the actual max packet size and so to shall we
        // don't do this when GCM mode is used since GCM mode doesn't encrypt the length
        if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
            if (!$this->bad_key_size_fix && self::bad_algorithm_candidate($this->decrypt ? $this->decrypt->name : '') && !($this->bitmap & SSH2::MASK_LOGIN)) {
                $this->bad_key_size_fix = true;
                $this->reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
                return false;
            }
            throw new \RuntimeException('Invalid size');
        }
        if ($adjustLength) {
            $remaining_length -= $this->decrypt_block_size - 4;
        }
        $buffer = '';
        while ($remaining_length > 0) {
            $temp = stream_get_contents($this->fsock, $remaining_length);
            if ($temp === false || feof($this->fsock)) {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST);
                throw new \RuntimeException('Error reading from socket');
            }
            $buffer .= $temp;
            $remaining_length -= strlen($temp);
        }
        return $buffer;
    }
    /**
     * Filter Binary Packets
     *
     * Because some binary packets need to be ignored...
     *
     * @see self::_get_binary_packet()
     * @param string $payload
     * @param bool $skip_channel_filter
     * @return string
     * @access private
     */
    private function filter($payload, $skip_channel_filter)
    {
        switch (ord($payload[0])) {
            case NET_SSH2_MSG_DISCONNECT:
                Strings::shift($payload, 1);
                list($reason_code, $message) = Strings::unpackSSH2('Ns', $payload);
                $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n{$message}";
                $this->bitmap = 0;
                return false;
            case NET_SSH2_MSG_IGNORE:
                $payload = $this->get_binary_packet($skip_channel_filter);
                break;
            case NET_SSH2_MSG_DEBUG:
                Strings::shift($payload, 2);
                // second byte is "always_display"
                list($message) = Strings::unpackSSH2('s', $payload);
                $this->errors[] = "SSH_MSG_DEBUG: {$message}";
                $payload = $this->get_binary_packet($skip_channel_filter);
                break;
            case NET_SSH2_MSG_UNIMPLEMENTED:
                return false;
            case NET_SSH2_MSG_KEXINIT:
                if ($this->session_id !== false) {
                    if (!$this->key_exchange($payload)) {
                        $this->bitmap = 0;
                        return false;
                    }
                    $payload = $this->get_binary_packet($skip_channel_filter);
                }
        }
        // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
        if ($this->bitmap & self::MASK_CONNECTED && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
            Strings::shift($payload, 1);
            list($this->banner_message) = Strings::unpackSSH2('s', $payload);
            $payload = $this->get_binary_packet();
        }
        // only called when we've already logged in
        if ($this->bitmap & self::MASK_CONNECTED && $this->isAuthenticated()) {
            if ($payload === true) {
                return true;
            }
            switch (ord($payload[0])) {
                case NET_SSH2_MSG_CHANNEL_REQUEST:
                    if (strlen($payload) == 31) {
                        extract(unpack('cpacket_type/Nchannel/Nlength', $payload));
                        if (\Phabel\Target\Php80\Polyfill::substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) {
                            if (ord(\Phabel\Target\Php80\Polyfill::substr($payload, 9 + $length))) {
                                // want reply
                                $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel]));
                            }
                            $payload = $this->get_binary_packet($skip_channel_filter);
                        }
                    }
                    break;
                case NET_SSH2_MSG_CHANNEL_DATA:
                case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
                case NET_SSH2_MSG_CHANNEL_CLOSE:
                case NET_SSH2_MSG_CHANNEL_EOF:
                    if (!$skip_channel_filter && !empty($this->server_channels)) {
                        $this->binary_packet_buffer = $payload;
                        $this->get_channel_packet(true);
                        $payload = $this->get_binary_packet();
                    }
                    break;
                case NET_SSH2_MSG_GLOBAL_REQUEST:
                    // see http://tools.ietf.org/html/rfc4254#section-4
                    Strings::shift($payload, 1);
                    list($request_name) = Strings::unpackSSH2('s', $payload);
                    $this->errors[] = "SSH_MSG_GLOBAL_REQUEST: {$request_name}";
                    try {
                        $this->send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE));
                    } catch (\RuntimeException $e) {
                        return $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                    }
                    $payload = $this->get_binary_packet($skip_channel_filter);
                    break;
                case NET_SSH2_MSG_CHANNEL_OPEN:
                    // see http://tools.ietf.org/html/rfc4254#section-5.1
                    Strings::shift($payload, 1);
                    list($data, $server_channel) = Strings::unpackSSH2('sN', $payload);
                    switch ($data) {
                        case 'auth-agent':
                        case 'auth-agent@openssh.com':
                            if (isset($this->agent)) {
                                $new_channel = self::CHANNEL_AGENT_FORWARD;
                                list($remote_window_size, $remote_maximum_packet_size) = Strings::unpackSSH2('NN', $payload);
                                $this->packet_size_client_to_server[$new_channel] = $remote_window_size;
                                $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size;
                                $this->window_size_client_to_server[$new_channel] = $this->window_size;
                                $packet_size = 0x4000;
                                $packet = pack('CN4', NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, $server_channel, $new_channel, $packet_size, $packet_size);
                                $this->server_channels[$new_channel] = $server_channel;
                                $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION;
                                $this->send_binary_packet($packet);
                            }
                            break;
                        default:
                            $packet = Strings::packSSH2(
                                'CN2ss',
                                NET_SSH2_MSG_CHANNEL_OPEN_FAILURE,
                                $server_channel,
                                NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
                                '',
                                // description
                                ''
                            );
                            try {
                                $this->send_binary_packet($packet);
                            } catch (\RuntimeException $e) {
                                return $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                            }
                    }
                    $payload = $this->get_binary_packet($skip_channel_filter);
                    break;
                case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
                    Strings::shift($payload, 1);
                    list($channel, $window_size) = Strings::unpackSSH2('NN', $payload);
                    $this->window_size_client_to_server[$channel] += $window_size;
                    $payload = $this->bitmap & self::MASK_WINDOW_ADJUST ? true : $this->get_binary_packet($skip_channel_filter);
            }
        }
        return $payload;
    }
    /**
     * Enable Quiet Mode
     *
     * Suppress stderr from output
     *
     * @access public
     */
    public function enableQuietMode()
    {
        $this->quiet_mode = true;
    }
    /**
     * Disable Quiet Mode
     *
     * Show stderr in output
     *
     * @access public
     */
    public function disableQuietMode()
    {
        $this->quiet_mode = false;
    }
    /**
     * Returns whether Quiet Mode is enabled or not
     *
     * @see self::enableQuietMode()
     * @see self::disableQuietMode()
     * @access public
     * @return bool
     */
    public function isQuietModeEnabled()
    {
        return $this->quiet_mode;
    }
    /**
     * Enable request-pty when using exec()
     *
     * @access public
     */
    public function enablePTY()
    {
        $this->request_pty = true;
    }
    /**
     * Disable request-pty when using exec()
     *
     * @access public
     */
    public function disablePTY()
    {
        if ($this->in_request_pty_exec) {
            $this->close_channel(self::CHANNEL_EXEC);
            $this->in_request_pty_exec = false;
        }
        $this->request_pty = false;
    }
    /**
     * Returns whether request-pty is enabled or not
     *
     * @see self::enablePTY()
     * @see self::disablePTY()
     * @access public
     * @return bool
     */
    public function isPTYEnabled()
    {
        return $this->request_pty;
    }
    /**
    * Gets channel data
    *
    * Returns the data as a string. bool(true) is returned if:
    *
    * - the server closes the channel
    - if the connection times out
    - if the channel status is CHANNEL_OPEN and the response was CHANNEL_OPEN_CONFIRMATION
    - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_SUCCESS
    *
    * bool(false) is returned if:
    *
    * - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_FAILURE
    *
    * @param int $client_channel
    * @param bool $skip_extended
    * @return mixed
    * @throws \RuntimeException on connection error
    * @access private
    */
    protected function get_channel_packet($client_channel, $skip_extended = false)
    {
        if (!empty($this->channel_buffers[$client_channel])) {
            switch ($this->channel_status[$client_channel]) {
                case NET_SSH2_MSG_CHANNEL_REQUEST:
                    foreach ($this->channel_buffers[$client_channel] as $i => $packet) {
                        switch (ord($packet[0])) {
                            case NET_SSH2_MSG_CHANNEL_SUCCESS:
                            case NET_SSH2_MSG_CHANNEL_FAILURE:
                                unset($this->channel_buffers[$client_channel][$i]);
                                return \Phabel\Target\Php80\Polyfill::substr($packet, 1);
                        }
                    }
                    break;
                default:
                    return \Phabel\Target\Php80\Polyfill::substr(array_shift($this->channel_buffers[$client_channel]), 1);
            }
        }
        while (true) {
            if ($this->binary_packet_buffer !== false) {
                $response = $this->binary_packet_buffer;
                $this->binary_packet_buffer = false;
            } else {
                $response = $this->get_binary_packet(true);
                if ($response === true && $this->is_timeout) {
                    if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) {
                        $this->close_channel($client_channel);
                    }
                    return true;
                }
                if ($response === false) {
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST);
                    throw new ConnectionClosedException('Connection closed by server');
                }
            }
            if ($client_channel == -1 && $response === true) {
                return true;
            }
            list($type, $channel) = Strings::unpackSSH2('CN', $response);
            // will not be setup yet on incoming channel open request
            if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) {
                $this->window_size_server_to_client[$channel] -= strlen($response);
                // resize the window, if appropriate
                if ($this->window_size_server_to_client[$channel] < 0) {
                    // PuTTY does something more analogous to the following:
                    //if ($this->window_size_server_to_client[$channel] < 0x3FFFFFFF) {
                    $packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_resize);
                    $this->send_binary_packet($packet);
                    $this->window_size_server_to_client[$channel] += $this->window_resize;
                }
                switch ($type) {
                    case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
                        /*
                        if ($client_channel == self::CHANNEL_EXEC) {
                            $this->send_channel_packet($client_channel, chr(0));
                        }
                        */
                        // currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR
                        list($data_type_code, $data) = Strings::unpackSSH2('Ns', $response);
                        $this->stdErrorLog .= $data;
                        if ($skip_extended || $this->quiet_mode) {
                            continue 2;
                        }
                        if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
                            return $data;
                        }
                        $this->channel_buffers[$channel][] = chr($type) . $data;
                        continue 2;
                    case NET_SSH2_MSG_CHANNEL_REQUEST:
                        if ($this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_CLOSE) {
                            continue 2;
                        }
                        list($value) = Strings::unpackSSH2('s', $response);
                        switch ($value) {
                            case 'exit-signal':
                                list(, $signal_name, , $error_message) = Strings::unpackSSH2('bsbs', $response);
                                $this->errors[] = "SSH_MSG_CHANNEL_REQUEST (exit-signal): {$signal_name}";
                                if (strlen($error_message)) {
                                    $this->errors[count($this->errors) - 1] .= "\r\n{$error_message}";
                                }
                                $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
                                $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
                                $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF;
                                continue 3;
                            case 'exit-status':
                                list(, $this->exit_status) = Strings::unpackSSH2('CN', $response);
                                // "The client MAY ignore these messages."
                                // -- http://tools.ietf.org/html/rfc4254#section-6.10
                                continue 3;
                            default:
                                // "Some systems may not implement signals, in which case they SHOULD ignore this message."
                                //  -- http://tools.ietf.org/html/rfc4254#section-6.9
                                continue 3;
                        }
                }
                switch ($this->channel_status[$channel]) {
                    case NET_SSH2_MSG_CHANNEL_OPEN:
                        switch ($type) {
                            case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
                                list($this->server_channels[$channel], $window_size, $this->packet_size_client_to_server[$channel]) = Strings::unpackSSH2('NNN', $response);
                                if ($window_size < 0) {
                                    $window_size &= 0x7fffffff;
                                    $window_size += 0x80000000;
                                }
                                $this->window_size_client_to_server[$channel] = $window_size;
                                $result = $client_channel == $channel ? true : $this->get_channel_packet($client_channel, $skip_extended);
                                $this->on_channel_open();
                                return $result;
                            case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
                                $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                                throw new \RuntimeException('Unable to open channel');
                            default:
                                if ($client_channel == $channel) {
                                    $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                                    throw new \RuntimeException('Unexpected response to open request');
                                }
                                return $this->get_channel_packet($client_channel, $skip_extended);
                        }
                        break;
                    case NET_SSH2_MSG_CHANNEL_REQUEST:
                        switch ($type) {
                            case NET_SSH2_MSG_CHANNEL_SUCCESS:
                                return true;
                            case NET_SSH2_MSG_CHANNEL_FAILURE:
                                return false;
                            case NET_SSH2_MSG_CHANNEL_DATA:
                                list($data) = Strings::unpackSSH2('s', $response);
                                $this->channel_buffers[$channel][] = chr($type) . $data;
                                return $this->get_channel_packet($client_channel, $skip_extended);
                            default:
                                $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                                throw new \RuntimeException('Unable to fulfill channel request');
                        }
                    case NET_SSH2_MSG_CHANNEL_CLOSE:
                        return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->get_channel_packet($client_channel, $skip_extended);
                }
            }
            // ie. $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA
            switch ($type) {
                case NET_SSH2_MSG_CHANNEL_DATA:
                    /*
                    if ($channel == self::CHANNEL_EXEC) {
                        // SCP requires null packets, such as this, be sent.  further, in the case of the ssh.com SSH server
                        // this actually seems to make things twice as fast.  more to the point, the message right after
                        // SSH_MSG_CHANNEL_DATA (usually SSH_MSG_IGNORE) won't block for as long as it would have otherwise.
                        // in OpenSSH it slows things down but only by a couple thousandths of a second.
                        $this->send_channel_packet($channel, chr(0));
                    }
                    */
                    list($data) = Strings::unpackSSH2('s', $response);
                    if ($channel == self::CHANNEL_AGENT_FORWARD) {
                        $agent_response = $this->agent->forwardData($data);
                        if (!is_bool($agent_response)) {
                            $this->send_channel_packet($channel, $agent_response);
                        }
                        break;
                    }
                    if ($client_channel == $channel) {
                        return $data;
                    }
                    $this->channel_buffers[$channel][] = chr($type) . $data;
                    break;
                case NET_SSH2_MSG_CHANNEL_CLOSE:
                    $this->curTimeout = 5;
                    if ($this->bitmap & self::MASK_SHELL) {
                        $this->bitmap &= ~self::MASK_SHELL;
                    }
                    if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) {
                        $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
                    }
                    $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
                    if ($client_channel == $channel) {
                        return true;
                    }
                case NET_SSH2_MSG_CHANNEL_EOF:
                    break;
                default:
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                    throw new \RuntimeException("Error reading channel data ({$type})");
            }
        }
    }
    /**
     * Sends Binary Packets
     *
     * See '6. Binary Packet Protocol' of rfc4253 for more info.
     *
     * @param string $data
     * @param string $logged
     * @see self::_get_binary_packet()
     * @return bool
     * @access private
     */
    protected function send_binary_packet($data, $logged = null)
    {
        if (!is_resource($this->fsock) || feof($this->fsock)) {
            $this->bitmap = 0;
            throw new ConnectionClosedException('Connection closed prematurely');
        }
        if (!isset($logged)) {
            $logged = $data;
        }
        switch ($this->compress) {
            case NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH:
                if (!$this->isAuthenticated()) {
                    break;
                }
            case NET_SSH2_COMPRESSION_ZLIB:
                if (!$this->regenerate_compression_context) {
                    $header = '';
                } else {
                    $this->regenerate_compression_context = false;
                    $this->compress_context = deflate_init(ZLIB_ENCODING_RAW, ['window' => 15]);
                    $header = "x\x9c";
                }
                if ($this->compress_context) {
                    $data = $header . deflate_add($this->compress_context, $data, ZLIB_PARTIAL_FLUSH);
                }
        }
        // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
        $packet_length = strlen($data) + 9;
        if ($this->encrypt && $this->encrypt->usesNonce()) {
            $packet_length -= 4;
        }
        // round up to the nearest $this->encrypt_block_size
        $packet_length += ($this->encrypt_block_size - 1) * $packet_length % $this->encrypt_block_size;
        // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length
        $padding_length = $packet_length - strlen($data) - 5;
        switch (true) {
            case $this->encrypt && $this->encrypt->usesNonce():
            case $this->hmac_create instanceof Hash && $this->hmac_create->etm:
                $padding_length += 4;
                $packet_length += 4;
        }
        $padding = Random::string($padding_length);
        // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself
        $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding);
        $hmac = '';
        if ($this->hmac_create instanceof Hash && !$this->hmac_create->etm) {
            if (($this->hmac_create->getHash() & "\xff\xff\xff\xff") == 'umac') {
                $this->hmac_create->setNonce("\x00\x00\x00\x00" . pack('N', $this->send_seq_no));
                $hmac = $this->hmac_create->hash($packet);
            } else {
                $hmac = $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet));
            }
        }
        if ($this->encrypt) {
            switch ($this->encrypt->name) {
                case 'aes128-gcm@openssh.com':
                case 'aes256-gcm@openssh.com':
                    $this->encrypt->setNonce($this->encrypt->fixed . $this->encrypt->invocation_counter);
                    Strings::increment_str($this->encrypt->invocation_counter);
                    $this->encrypt->setAAD($temp = $packet & "\xff\xff\xff\xff");
                    $packet = $temp . $this->encrypt->encrypt(\Phabel\Target\Php80\Polyfill::substr($packet, 4));
                    break;
                case 'chacha20-poly1305@openssh.com':
                    $nonce = pack('N2', 0, $this->send_seq_no);
                    $this->encrypt->setNonce($nonce);
                    $this->lengthEncrypt->setNonce($nonce);
                    $length = $this->lengthEncrypt->encrypt($packet & "\xff\xff\xff\xff");
                    $this->encrypt->setCounter(0);
                    // this is the same approach that's implemented in Salsa20::createPoly1305Key()
                    // but we don't want to use the same AEAD construction that RFC8439 describes
                    // for ChaCha20-Poly1305 so we won't rely on it (see Salsa20::poly1305())
                    $this->encrypt->setPoly1305Key($this->encrypt->encrypt(str_repeat("\x00", 32)));
                    $this->encrypt->setAAD($length);
                    $this->encrypt->setCounter(1);
                    $packet = $length . $this->encrypt->encrypt(\Phabel\Target\Php80\Polyfill::substr($packet, 4));
                    break;
                default:
                    $packet = $this->hmac_create instanceof Hash && $this->hmac_create->etm ? ($packet & "\xff\xff\xff\xff") . $this->encrypt->encrypt(\Phabel\Target\Php80\Polyfill::substr($packet, 4)) : $this->encrypt->encrypt($packet);
            }
        }
        if ($this->hmac_create instanceof Hash && $this->hmac_create->etm) {
            if (($this->hmac_create->getHash() & "\xff\xff\xff\xff") == 'umac') {
                $this->hmac_create->setNonce("\x00\x00\x00\x00" . pack('N', $this->send_seq_no));
                $hmac = $this->hmac_create->hash($packet);
            } else {
                $hmac = $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet));
            }
        }
        $this->send_seq_no++;
        $packet .= $this->encrypt && $this->encrypt->usesNonce() ? $this->encrypt->getTag() : $hmac;
        $start = microtime(true);
        $sent = @fputs($this->fsock, $packet);
        $stop = microtime(true);
        if (defined('NET_SSH2_LOGGING')) {
            $current = microtime(true);
            $message_number = isset($this->message_numbers[ord($logged[0])]) ? $this->message_numbers[ord($logged[0])] : 'UNKNOWN (' . ord($logged[0]) . ')';
            $message_number = '-> ' . $message_number . ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
            $this->append_log($message_number, $logged);
            $this->last_packet = $current;
        }
        if (strlen($packet) != $sent) {
            $this->bitmap = 0;
            throw new \RuntimeException("Only {$sent} of " . strlen($packet) . " bytes were sent");
        }
    }
    /**
     * Logs data packets
     *
     * Makes sure that only the last 1MB worth of packets will be logged
     *
     * @param string $message_number
     * @param string $message
     * @access private
     */
    private function append_log($message_number, $message)
    {
        // remove the byte identifying the message type from all but the first two messages (ie. the identification strings)
        if (strlen($message_number) > 2) {
            Strings::shift($message);
        }
        switch (NET_SSH2_LOGGING) {
            // useful for benchmarks
            case self::LOG_SIMPLE:
                $this->message_number_log[] = $message_number;
                break;
            // the most useful log for SSH2
            case self::LOG_COMPLEX:
                $this->message_number_log[] = $message_number;
                $this->log_size += strlen($message);
                $this->message_log[] = $message;
                while ($this->log_size > self::LOG_MAX_SIZE) {
                    $this->log_size -= strlen(array_shift($this->message_log));
                    array_shift($this->message_number_log);
                }
                break;
            // dump the output out realtime; packets may be interspersed with non packets,
            // passwords won't be filtered out and select other packets may not be correctly
            // identified
            case self::LOG_REALTIME:
                switch (PHP_SAPI) {
                    case 'cli':
                        $start = $stop = "\r\n";
                        break;
                    default:
                        $start = '<pre>';
                        $stop = '</pre>';
                }
                echo $start . $this->format_log([$message], [$message_number]) . $stop;
                @flush();
                @ob_flush();
                break;
            // basically the same thing as self::LOG_REALTIME with the caveat that NET_SSH2_LOG_REALTIME_FILENAME
            // needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
            // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
            // at the beginning of the file
            case self::LOG_REALTIME_FILE:
                if (!isset($this->realtime_log_file)) {
                    // PHP doesn't seem to like using constants in fopen()
                    $filename = NET_SSH2_LOG_REALTIME_FILENAME;
                    $fp = fopen($filename, 'w');
                    $this->realtime_log_file = $fp;
                }
                if (!is_resource($this->realtime_log_file)) {
                    break;
                }
                $entry = $this->format_log([$message], [$message_number]);
                if ($this->realtime_log_wrap) {
                    $temp = "<<< START >>>\r\n";
                    $entry .= $temp;
                    fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
                }
                $this->realtime_log_size += strlen($entry);
                if ($this->realtime_log_size > self::LOG_MAX_SIZE) {
                    fseek($this->realtime_log_file, 0);
                    $this->realtime_log_size = strlen($entry);
                    $this->realtime_log_wrap = true;
                }
                fputs($this->realtime_log_file, $entry);
        }
    }
    /**
     * Sends channel data
     *
     * Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate
     *
     * @param int $client_channel
     * @param string $data
     * @return bool
     * @access private
     */
    protected function send_channel_packet($client_channel, $data)
    {
        while (strlen($data)) {
            if (!$this->window_size_client_to_server[$client_channel]) {
                $this->bitmap ^= self::MASK_WINDOW_ADJUST;
                // using an invalid channel will let the buffers be built up for the valid channels
                $this->get_channel_packet(-1);
                $this->bitmap ^= self::MASK_WINDOW_ADJUST;
            }
            /* The maximum amount of data allowed is determined by the maximum
               packet size for the channel, and the current window size, whichever
               is smaller.
                 -- http://tools.ietf.org/html/rfc4254#section-5.2 */
            $max_size = min($this->packet_size_client_to_server[$client_channel], $this->window_size_client_to_server[$client_channel]);
            $temp = Strings::shift($data, $max_size);
            $packet = Strings::packSSH2('CNs', NET_SSH2_MSG_CHANNEL_DATA, $this->server_channels[$client_channel], $temp);
            $this->window_size_client_to_server[$client_channel] -= strlen($temp);
            $this->send_binary_packet($packet);
        }
        return true;
    }
    /**
    * Closes and flushes a channel
    *
    * \phpseclib3\Net\SSH2 doesn't properly close most channels.  For exec() channels are normally closed by the server
    and for SFTP channels are presumably closed when the client disconnects.  This functions is intended
    for SCP more than anything.
    *
    * @param int $client_channel
    * @param bool $want_reply
    * @return bool
    * @access private
    */
    private function close_channel($client_channel, $want_reply = false)
    {
        // see http://tools.ietf.org/html/rfc4254#section-5.3
        $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
        if (!$want_reply) {
            $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
        }
        $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
        $this->curTimeout = 5;
        while (!is_bool($this->get_channel_packet($client_channel))) {
        }
        if ($this->is_timeout) {
            $this->disconnect();
        }
        if ($want_reply) {
            $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
        }
        if ($this->bitmap & self::MASK_SHELL) {
            $this->bitmap &= ~self::MASK_SHELL;
        }
    }
    /**
     * Disconnect
     *
     * @param int $reason
     * @return bool
     * @access protected
     */
    protected function disconnect_helper($reason)
    {
        if ($this->bitmap & self::MASK_CONNECTED) {
            $data = Strings::packSSH2('CNss', NET_SSH2_MSG_DISCONNECT, $reason, '', '');
            try {
                $this->send_binary_packet($data);
            } catch (\Exception $e) {
            }
        }
        $this->bitmap = 0;
        if (is_resource($this->fsock) && get_resource_type($this->fsock) == 'stream') {
            fclose($this->fsock);
        }
        return false;
    }
    /**
    * Define Array
    *
    * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of
    named constants from it, using the value as the name of the constant and the index as the value of the constant.
    If any of the constants that would be defined already exists, none of the constants will be defined.
    *
    * @param mixed[] ...$args
    * @access protected
    */
    protected function define_array(...$args)
    {
        foreach ($args as $arg) {
            foreach ($arg as $key => $value) {
                if (!defined($value)) {
                    define($value, $key);
                } else {
                    break 2;
                }
            }
        }
    }
    /**
     * Returns a log of the packets that have been sent and received.
     *
     * Returns a string if NET_SSH2_LOGGING == self::LOG_COMPLEX, an array if NET_SSH2_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
     *
     * @access public
     * @return (array | false | string)
     */
    public function getLog()
    {
        if (!defined('NET_SSH2_LOGGING')) {
            return false;
        }
        switch (NET_SSH2_LOGGING) {
            case self::LOG_SIMPLE:
                return $this->message_number_log;
            case self::LOG_COMPLEX:
                $log = $this->format_log($this->message_log, $this->message_number_log);
                return PHP_SAPI == 'cli' ? $log : '<pre>' . $log . '</pre>';
            default:
                return false;
        }
    }
    /**
     * Formats a log for printing
     *
     * @param array $message_log
     * @param array $message_number_log
     * @access private
     * @return string
     */
    protected function format_log($message_log, $message_number_log)
    {
        $output = '';
        for ($i = 0; $i < count($message_log); $i++) {
            $output .= $message_number_log[$i] . "\r\n";
            $current_log = $message_log[$i];
            $j = 0;
            do {
                if (strlen($current_log)) {
                    $output .= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0  ';
                }
                $fragment = Strings::shift($current_log, $this->log_short_width);
                $hex = \Phabel\Target\Php80\Polyfill::substr(preg_replace_callback('#.#s', function ($matches) {
                    return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
                }, $fragment), strlen($this->log_boundary));
                // replace non ASCII printable characters with dots
                // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
                // also replace < with a . since < messes up the output on web browsers
                $raw = preg_replace('#[^\\x20-\\x7E]|<#', '.', $fragment);
                $output .= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n";
                $j++;
            } while (strlen($current_log));
            $output .= "\r\n";
        }
        return $output;
    }
    /**
    * Helper function for agent->on_channel_open()
    *
    * Used when channels are created to inform agent
    of said channel opening. Must be called after
    channel open confirmation received
    *
    * @access private
    */
    private function on_channel_open()
    {
        if (isset($this->agent)) {
            $this->agent->registerChannelOpen($this);
        }
    }
    /**
    * Returns the first value of the intersection of two arrays or false if
    the intersection is empty. The order is defined by the first parameter.
    *
    * @param array $array1
    * @param array $array2
    * @return mixed False if intersection is empty, else intersected value.
    * @access private
    */
    private static function array_intersect_first($array1, $array2)
    {
        foreach ($array1 as $value) {
            if (in_array($value, $array2)) {
                return $value;
            }
        }
        return false;
    }
    /**
     * Returns all errors
     *
     * @return string[]
     * @access public
     */
    public function getErrors()
    {
        return $this->errors;
    }
    /**
     * Returns the last error
     *
     * @return string
     * @access public
     */
    public function getLastError()
    {
        $count = count($this->errors);
        if ($count > 0) {
            return $this->errors[$count - 1];
        }
    }
    /**
     * Return the server identification.
     *
     * @return string
     * @access public
     */
    public function getServerIdentification()
    {
        $this->connect();
        return $this->server_identifier;
    }
    /**
     * Returns a list of algorithms the server supports
     *
     * @return array
     * @access public
     */
    public function getServerAlgorithms()
    {
        $this->connect();
        return ['kex' => $this->kex_algorithms, 'hostkey' => $this->server_host_key_algorithms, 'client_to_server' => ['crypt' => $this->encryption_algorithms_client_to_server, 'mac' => $this->mac_algorithms_client_to_server, 'comp' => $this->compression_algorithms_client_to_server, 'lang' => $this->languages_client_to_server], 'server_to_client' => ['crypt' => $this->encryption_algorithms_server_to_client, 'mac' => $this->mac_algorithms_server_to_client, 'comp' => $this->compression_algorithms_server_to_client, 'lang' => $this->languages_server_to_client]];
    }
    /**
     * Returns a list of KEX algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedKEXAlgorithms()
    {
        $kex_algorithms = [
            // Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using
            // Curve25519. See doc/curve25519-sha256@libssh.org.txt in the
            // libssh repository for more information.
            'curve25519-sha256',
            'curve25519-sha256@libssh.org',
            'ecdh-sha2-nistp256',
            // RFC 5656
            'ecdh-sha2-nistp384',
            // RFC 5656
            'ecdh-sha2-nistp521',
            // RFC 5656
            'diffie-hellman-group-exchange-sha256',
            // RFC 4419
            'diffie-hellman-group-exchange-sha1',
            // RFC 4419
            // Diffie-Hellman Key Agreement (DH) using integer modulo prime
            // groups.
            'diffie-hellman-group14-sha256',
            'diffie-hellman-group14-sha1',
            // REQUIRED
            'diffie-hellman-group15-sha512',
            'diffie-hellman-group16-sha512',
            'diffie-hellman-group17-sha512',
            'diffie-hellman-group18-sha512',
            'diffie-hellman-group1-sha1',
        ];
        return $kex_algorithms;
    }
    /**
     * Returns a list of host key algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedHostKeyAlgorithms()
    {
        return [
            'ssh-ed25519',
            // https://tools.ietf.org/html/draft-ietf-curdle-ssh-ed25519-02
            'ecdsa-sha2-nistp256',
            // RFC 5656
            'ecdsa-sha2-nistp384',
            // RFC 5656
            'ecdsa-sha2-nistp521',
            // RFC 5656
            'rsa-sha2-256',
            // RFC 8332
            'rsa-sha2-512',
            // RFC 8332
            'ssh-rsa',
            // RECOMMENDED  sign   Raw RSA Key
            'ssh-dss',
        ];
    }
    /**
     * Returns a list of symmetric key algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedEncryptionAlgorithms()
    {
        $algos = [
            // from <https://tools.ietf.org/html/rfc5647>:
            'aes128-gcm@openssh.com',
            'aes256-gcm@openssh.com',
            // from <http://tools.ietf.org/html/rfc4345#section-4>:
            'arcfour256',
            'arcfour128',
            //'arcfour',      // OPTIONAL          the ARCFOUR stream cipher with a 128-bit key
            // CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
            'aes128-ctr',
            // RECOMMENDED       AES (Rijndael) in SDCTR mode, with 128-bit key
            'aes192-ctr',
            // RECOMMENDED       AES with 192-bit key
            'aes256-ctr',
            // RECOMMENDED       AES with 256-bit key
            // from <https://git.io/fhxOl>:
            // one of the big benefits of chacha20-poly1305 is speed. the problem is...
            // libsodium doesn't generate the poly1305 keys in the way ssh does and openssl's PHP bindings don't even
            // seem to support poly1305 currently. so even if libsodium or openssl are being used for the chacha20
            // part, pure-PHP has to be used for the poly1305 part and that's gonna cause a big slow down.
            // speed-wise it winds up being faster to use AES (when openssl or mcrypt are available) and some HMAC
            // (which is always gonna be super fast to compute thanks to the hash extension, which
            // "is bundled and compiled into PHP by default")
            'chacha20-poly1305@openssh.com',
            'twofish128-ctr',
            // OPTIONAL          Twofish in SDCTR mode, with 128-bit key
            'twofish192-ctr',
            // OPTIONAL          Twofish with 192-bit key
            'twofish256-ctr',
            // OPTIONAL          Twofish with 256-bit key
            'aes128-cbc',
            // RECOMMENDED       AES with a 128-bit key
            'aes192-cbc',
            // OPTIONAL          AES with a 192-bit key
            'aes256-cbc',
            // OPTIONAL          AES in CBC mode, with a 256-bit key
            'twofish128-cbc',
            // OPTIONAL          Twofish with a 128-bit key
            'twofish192-cbc',
            // OPTIONAL          Twofish with a 192-bit key
            'twofish256-cbc',
            'twofish-cbc',
            // OPTIONAL          alias for "twofish256-cbc"
            //                   (this is being retained for historical reasons)
            'blowfish-ctr',
            // OPTIONAL          Blowfish in SDCTR mode
            'blowfish-cbc',
            // OPTIONAL          Blowfish in CBC mode
            '3des-ctr',
            // RECOMMENDED       Three-key 3DES in SDCTR mode
            '3des-cbc',
        ];
        if (self::$crypto_engine) {
            $engines = [self::$crypto_engine];
        } else {
            $engines = ['libsodium', 'OpenSSL (GCM)', 'OpenSSL', 'mcrypt', 'Eval', 'PHP'];
        }
        $ciphers = [];
        foreach ($engines as $engine) {
            foreach ($algos as $algo) {
                $obj = self::encryption_algorithm_to_crypt_instance($algo);
                if ($obj instanceof Rijndael) {
                    $obj->setKeyLength(preg_replace('#[^\\d]#', '', $algo));
                }
                switch ($algo) {
                    case 'chacha20-poly1305@openssh.com':
                    case 'arcfour128':
                    case 'arcfour256':
                        if ($engine != 'Eval') {
                            continue 2;
                        }
                        break;
                    case 'aes128-gcm@openssh.com':
                    case 'aes256-gcm@openssh.com':
                        if ($engine == 'OpenSSL') {
                            continue 2;
                        }
                        $obj->setNonce('dummydummydu');
                }
                if ($obj->isValidEngine($engine)) {
                    $algos = array_diff($algos, [$algo]);
                    $ciphers[] = $algo;
                }
            }
        }
        return $ciphers;
    }
    /**
     * Returns a list of MAC algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedMACAlgorithms()
    {
        return [
            'hmac-sha2-256-etm@openssh.com',
            'hmac-sha2-512-etm@openssh.com',
            'umac-64-etm@openssh.com',
            'umac-128-etm@openssh.com',
            'hmac-sha1-etm@openssh.com',
            // from <http://www.ietf.org/rfc/rfc6668.txt>:
            'hmac-sha2-256',
            // RECOMMENDED     HMAC-SHA256 (digest length = key length = 32)
            'hmac-sha2-512',
            // OPTIONAL        HMAC-SHA512 (digest length = key length = 64)
            // from <https://tools.ietf.org/html/draft-miller-secsh-umac-01>:
            'umac-64@openssh.com',
            'umac-128@openssh.com',
            'hmac-sha1-96',
            // RECOMMENDED     first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
            'hmac-sha1',
            // REQUIRED        HMAC-SHA1 (digest length = key length = 20)
            'hmac-md5-96',
            // OPTIONAL        first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
            'hmac-md5',
        ];
    }
    /**
     * Returns a list of compression algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedCompressionAlgorithms()
    {
        $algos = ['none'];
        // REQUIRED        no compression
        if (function_exists('deflate_init')) {
            $algos[] = 'zlib@openssh.com';
            // https://datatracker.ietf.org/doc/html/draft-miller-secsh-compression-delayed
            $algos[] = 'zlib';
        }
        return $algos;
    }
    /**
     * Return list of negotiated algorithms
     *
     * Uses the same format as https://www.php.net/ssh2-methods-negotiated
     *
     * @return array
     * @access public
     */
    public function getAlgorithmsNegotiated()
    {
        $this->connect();
        $compression_map = [NET_SSH2_COMPRESSION_NONE => 'none', NET_SSH2_COMPRESSION_ZLIB => 'zlib', NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH => 'zlib@openssh.com'];
        return ['kex' => $this->kex_algorithm, 'hostkey' => $this->signature_format, 'client_to_server' => ['crypt' => $this->encrypt->name, 'mac' => $this->hmac_create->name, 'comp' => $compression_map[$this->compress]], 'server_to_client' => ['crypt' => $this->decrypt->name, 'mac' => $this->hmac_check->name, 'comp' => $compression_map[$this->decompress]]];
    }
    /**
     * Allows you to set the terminal
     *
     * @param string $term
     * @access public
     */
    public function setTerminal($term)
    {
        $this->term = $term;
    }
    /**
    * Accepts an associative array with up to four parameters as described at
    <https://www.php.net/manual/en/function.ssh2-connect.php>
    *
    * @param array $methods
    * @access public
    */
    public function setPreferredAlgorithms(array $methods)
    {
        $preferred = $methods;
        if (isset($preferred['kex'])) {
            $preferred['kex'] = array_intersect($preferred['kex'], static::getSupportedKEXAlgorithms());
        }
        if (isset($preferred['hostkey'])) {
            $preferred['hostkey'] = array_intersect($preferred['hostkey'], static::getSupportedHostKeyAlgorithms());
        }
        $keys = ['client_to_server', 'server_to_client'];
        foreach ($keys as $key) {
            if (isset($preferred[$key])) {
                $a =& $preferred[$key];
                if (isset($a['crypt'])) {
                    $a['crypt'] = array_intersect($a['crypt'], static::getSupportedEncryptionAlgorithms());
                }
                if (isset($a['comp'])) {
                    $a['comp'] = array_intersect($a['comp'], static::getSupportedCompressionAlgorithms());
                }
                if (isset($a['mac'])) {
                    $a['mac'] = array_intersect($a['mac'], static::getSupportedMACAlgorithms());
                }
            }
        }
        $keys = ['kex', 'hostkey', 'client_to_server/crypt', 'client_to_server/comp', 'client_to_server/mac', 'server_to_client/crypt', 'server_to_client/comp', 'server_to_client/mac'];
        foreach ($keys as $key) {
            $p = $preferred;
            $m = $methods;
            $subkeys = explode('/', $key);
            foreach ($subkeys as $subkey) {
                if (!isset($p[$subkey])) {
                    continue 2;
                }
                $p = $p[$subkey];
                $m = $m[$subkey];
            }
            if (count($p) != count($m)) {
                $diff = array_diff($m, $p);
                $msg = count($diff) == 1 ? ' is not a supported algorithm' : ' are not supported algorithms';
                throw new UnsupportedAlgorithmException(implode(', ', $diff) . $msg);
            }
        }
        $this->preferred = $preferred;
    }
    /**
    * Returns the banner message.
    *
    * Quoting from the RFC, "in some jurisdictions, sending a warning message before
    authentication may be relevant for getting legal protection."
    *
    * @return string
    * @access public
    */
    public function getBannerMessage()
    {
        return $this->banner_message;
    }
    /**
    * Returns the server public host key.
    *
    * Caching this the first time you connect to a server and checking the result on subsequent connections
    is recommended.  Returns false if the server signature is not signed correctly with the public host key.
    *
    * @return mixed
    * @throws \RuntimeException on badly formatted keys
    * @throws \phpseclib3\Exception\NoSupportedAlgorithmsException when the key isn't in a supported format
    * @access public
    */
    public function getServerPublicHostKey()
    {
        if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
            $this->connect();
        }
        $signature = $this->signature;
        $server_public_host_key = base64_encode($this->server_public_host_key);
        if ($this->signature_validated) {
            return $this->bitmap ? $this->signature_format . ' ' . $server_public_host_key : false;
        }
        $this->signature_validated = true;
        switch ($this->signature_format) {
            case 'ssh-ed25519':
            case 'ecdsa-sha2-nistp256':
            case 'ecdsa-sha2-nistp384':
            case 'ecdsa-sha2-nistp521':
                $key = EC::loadFormat('OpenSSH', $server_public_host_key)->withSignatureFormat('SSH2');
                switch ($this->signature_format) {
                    case 'ssh-ed25519':
                        $hash = 'sha512';
                        break;
                    case 'ecdsa-sha2-nistp256':
                        $hash = 'sha256';
                        break;
                    case 'ecdsa-sha2-nistp384':
                        $hash = 'sha384';
                        break;
                    case 'ecdsa-sha2-nistp521':
                        $hash = 'sha512';
                }
                $key = $key->withHash($hash);
                break;
            case 'ssh-dss':
                $key = DSA::loadFormat('OpenSSH', $server_public_host_key)->withSignatureFormat('SSH2')->withHash('sha1');
                break;
            case 'ssh-rsa':
            case 'rsa-sha2-256':
            case 'rsa-sha2-512':
                if (strlen($signature) < 15) {
                    return false;
                }
                Strings::shift($signature, 11);
                $temp = unpack('Nlength', Strings::shift($signature, 4));
                $signature = Strings::shift($signature, $temp['length']);
                $key = RSA::loadFormat('OpenSSH', $server_public_host_key)->withPadding(RSA::SIGNATURE_PKCS1);
                switch ($this->signature_format) {
                    case 'rsa-sha2-512':
                        $hash = 'sha512';
                        break;
                    case 'rsa-sha2-256':
                        $hash = 'sha256';
                        break;
                    //case 'ssh-rsa':
                    default:
                        $hash = 'sha1';
                }
                $key = $key->withHash($hash);
                break;
            default:
                $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
                throw new NoSupportedAlgorithmsException('Unsupported signature format');
        }
        if (!$key->verify($this->exchange_hash, $signature)) {
            return $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
        }
        return $this->signature_format . ' ' . $server_public_host_key;
    }
    /**
     * Returns the exit status of an SSH command or false.
     *
     * @return (false | int)
     * @access public
     */
    public function getExitStatus()
    {
        if (is_null($this->exit_status)) {
            return false;
        }
        return $this->exit_status;
    }
    /**
     * Returns the number of columns for the terminal window size.
     *
     * @return int
     * @access public
     */
    public function getWindowColumns()
    {
        return $this->windowColumns;
    }
    /**
     * Returns the number of rows for the terminal window size.
     *
     * @return int
     * @access public
     */
    public function getWindowRows()
    {
        return $this->windowRows;
    }
    /**
     * Sets the number of columns for the terminal window size.
     *
     * @param int $value
     * @access public
     */
    public function setWindowColumns($value)
    {
        $this->windowColumns = $value;
    }
    /**
     * Sets the number of rows for the terminal window size.
     *
     * @param int $value
     * @access public
     */
    public function setWindowRows($value)
    {
        $this->windowRows = $value;
    }
    /**
     * Sets the number of columns and rows for the terminal window size.
     *
     * @param int $columns
     * @param int $rows
     * @access public
     */
    public function setWindowSize($columns = 80, $rows = 24)
    {
        $this->windowColumns = $columns;
        $this->windowRows = $rows;
    }
    /**
     * To String Magic Method
     *
     * @return string
     * @access public
     */
    public function __toString()
    {
        return $this->getResourceId();
    }
    /**
    * Get Resource ID
    *
    * We use {} because that symbols should not be in URL according to
    {@link http://tools.ietf.org/html/rfc3986#section-2 RFC}.
    It will safe us from any conflicts, because otherwise regexp will
    match all alphanumeric domains.
    *
    * @return string
    */
    public function getResourceId()
    {
        return '{' . spl_object_hash($this) . '}';
    }
    /**
     * Return existing connection
     *
     * @param string $id
     *
     * @return (bool | SSH2) will return false if no such connection
     */
    public static function getConnectionByResourceId($id)
    {
        if (isset(self::$connections[$id])) {
            return self::$connections[$id] instanceof \WeakReference ? self::$connections[$id]->get() : self::$connections[$id];
        }
        return false;
    }
    /**
     * Return all excising connections
     *
     * @return SSH2[]
     */
    public static function getConnections()
    {
        if (!class_exists('WeakReference')) {
            return self::$connections;
        }
        $temp = [];
        foreach (self::$connections as $key => $ref) {
            $temp[$key] = $ref->get();
        }
        return $temp;
    }
    /*
     * Update packet types in log history
     *
     * @param string $old
     * @param string $new
     * @access private
     */
    /**
     *
     */
    private function updateLogHistory($old, $new)
    {
        if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) {
            $this->message_number_log[count($this->message_number_log) - 1] = str_replace($old, $new, $this->message_number_log[count($this->message_number_log) - 1]);
        }
    }
    /**
     * Return the list of authentication methods that may productively continue authentication.
     *
     * @see https://tools.ietf.org/html/rfc4252#section-5.1
     * @return (array | null)
     */
    public function getAuthMethodsToContinue()
    {
        return $this->auth_methods_to_continue;
    }
    /**
     * Enables "smart" multi-factor authentication (MFA)
     */
    public function enableSmartMFA()
    {
        $this->smartMFA = true;
    }
    /**
     * Disables "smart" multi-factor authentication (MFA)
     */
    public function disableSmartMFA()
    {
        $this->smartMFA = false;
    }
}<?php

/**
 * SFTP Stream Wrapper
 *
 * Creates an sftp:// protocol handler that can be used with, for example, fopen(), dir(), etc.
 *
 * PHP version 5
 *
 * @category  Net
 * @package   SFTP
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2013 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Net\SFTP;

use phpseclib3\Crypt\Common\PrivateKey;
use phpseclib3\Net\SFTP;
use phpseclib3\Net\SSH2;
/**
 * SFTP Stream Wrapper
 *
 * @package SFTP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Stream
{
    /**
     * SFTP instances
     *
     * Rather than re-create the connection we re-use instances if possible
     *
     * @var array
     */
    static $instances;
    /**
     * SFTP instance
     *
     * @var object
     * @access private
     */
    private $sftp;
    /**
     * Path
     *
     * @var string
     * @access private
     */
    private $path;
    /**
     * Mode
     *
     * @var string
     * @access private
     */
    private $mode;
    /**
     * Position
     *
     * @var int
     * @access private
     */
    private $pos;
    /**
     * Size
     *
     * @var int
     * @access private
     */
    private $size;
    /**
     * Directory entries
     *
     * @var array
     * @access private
     */
    private $entries;
    /**
     * EOF flag
     *
     * @var bool
     * @access private
     */
    private $eof;
    /**
     * Context resource
     *
     * Technically this needs to be publicly accessible so PHP can set it directly
     *
     * @var resource
     * @access public
     */
    public $context;
    /**
     * Notification callback function
     *
     * @var callable
     * @access public
     */
    private $notification;
    /**
     * Registers this class as a URL wrapper.
     *
     * @param string $protocol The wrapper name to be registered.
     * @return bool True on success, false otherwise.
     * @access public
     */
    public static function register($protocol = 'sftp')
    {
        if (in_array($protocol, stream_get_wrappers(), true)) {
            return false;
        }
        return stream_wrapper_register($protocol, get_called_class());
    }
    /**
     * The Constructor
     *
     * @access public
     */
    public function __construct()
    {
        if (defined('NET_SFTP_STREAM_LOGGING')) {
            echo "__construct()\r\n";
        }
    }
    /**
    * Path Parser
    *
    * Extract a path from a URI and actually connect to an SSH server if appropriate
    *
    * If "notification" is set as a context parameter the message code for successful login is
    NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
    *
    * @param string $path
    * @return string
    * @access private
    */
    protected function parse_path($path)
    {
        $orig = $path;
        extract(parse_url($path) + ['port' => 22]);
        if (isset($query)) {
            $path .= '?' . $query;
        } elseif (preg_match('/(\\?|\\?#)$/', $orig)) {
            $path .= '?';
        }
        if (isset($fragment)) {
            $path .= '#' . $fragment;
        } elseif ($orig[strlen($orig) - 1] == '#') {
            $path .= '#';
        }
        if (!isset($host)) {
            return false;
        }
        if (isset($this->context)) {
            $context = stream_context_get_params($this->context);
            if (isset($context['notification'])) {
                $this->notification = $context['notification'];
            }
        }
        if (preg_match('/^{[a-z0-9]+}$/i', $host)) {
            $host = SSH2::getConnectionByResourceId($host);
            if ($host === false) {
                return false;
            }
            $this->sftp = $host;
        } else {
            if (isset($this->context)) {
                $context = stream_context_get_options($this->context);
            }
            if (isset($context[$scheme]['session'])) {
                $sftp = $context[$scheme]['session'];
            }
            if (isset($context[$scheme]['sftp'])) {
                $sftp = $context[$scheme]['sftp'];
            }
            if (isset($sftp) && $sftp instanceof SFTP) {
                $this->sftp = $sftp;
                return $path;
            }
            if (isset($context[$scheme]['username'])) {
                $user = $context[$scheme]['username'];
            }
            if (isset($context[$scheme]['password'])) {
                $pass = $context[$scheme]['password'];
            }
            if (isset($context[$scheme]['privkey']) && $context[$scheme]['privkey'] instanceof PrivateKey) {
                $pass = $context[$scheme]['privkey'];
            }
            if (!isset($user) || !isset($pass)) {
                return false;
            }
            // casting $pass to a string is necessary in the event that it's a \phpseclib3\Crypt\RSA object
            if (isset(self::$instances[$host][$port][$user][(string) $pass])) {
                $this->sftp = self::$instances[$host][$port][$user][(string) $pass];
            } else {
                $this->sftp = new SFTP($host, $port);
                $this->sftp->disableStatCache();
                if (isset($this->notification) && is_callable($this->notification)) {
                    /* if !is_callable($this->notification) we could do this:
                    
                                           user_error('fopen(): failed to call user notifier', E_USER_WARNING);
                    
                                           the ftp wrapper gives errors like that when the notifier isn't callable.
                                           i've opted not to do that, however, since the ftp wrapper gives the line
                                           on which the fopen occurred as the line number - not the line that the
                                           user_error is on.
                                        */
                    call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
                    call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
                    if (!$this->sftp->login($user, $pass)) {
                        call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0);
                        return false;
                    }
                    call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0);
                } else {
                    if (!$this->sftp->login($user, $pass)) {
                        return false;
                    }
                }
                self::$instances[$host][$port][$user][(string) $pass] = $this->sftp;
            }
        }
        return $path;
    }
    /**
     * Opens file or URL
     *
     * @param string $path
     * @param string $mode
     * @param int $options
     * @param string $opened_path
     * @return bool
     * @access public
     */
    private function _stream_open($path, $mode, $options, &$opened_path)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        $this->path = $path;
        $this->size = $this->sftp->filesize($path);
        $this->mode = preg_replace('#[bt]$#', '', $mode);
        $this->eof = false;
        if ($this->size === false) {
            if ($this->mode[0] == 'r') {
                return false;
            } else {
                $this->sftp->touch($path);
                $this->size = 0;
            }
        } else {
            switch ($this->mode[0]) {
                case 'x':
                    return false;
                case 'w':
                    $this->sftp->truncate($path, 0);
                    $this->size = 0;
            }
        }
        $this->pos = $this->mode[0] != 'a' ? 0 : $this->size;
        return true;
    }
    /**
     * Read from stream
     *
     * @param int $count
     * @return mixed
     * @access public
     */
    private function _stream_read($count)
    {
        switch ($this->mode) {
            case 'w':
            case 'a':
            case 'x':
            case 'c':
                return false;
        }
        // commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite
        //if ($this->pos >= $this->size) {
        //    $this->eof = true;
        //    return false;
        //}
        $result = $this->sftp->get($this->path, false, $this->pos, $count);
        if (isset($this->notification) && is_callable($this->notification)) {
            if ($result === false) {
                call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
                return 0;
            }
            // seems that PHP calls stream_read in 8k chunks
            call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size);
        }
        if (empty($result)) {
            // ie. false or empty string
            $this->eof = true;
            return false;
        }
        $this->pos += strlen($result);
        return $result;
    }
    /**
     * Write to stream
     *
     * @param string $data
     * @return mixed
     * @access public
     */
    private function _stream_write($data)
    {
        switch ($this->mode) {
            case 'r':
                return false;
        }
        $result = $this->sftp->put($this->path, $data, SFTP::SOURCE_STRING, $this->pos);
        if (isset($this->notification) && is_callable($this->notification)) {
            if (!$result) {
                call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
                return 0;
            }
            // seems that PHP splits up strings into 8k blocks before calling stream_write
            call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data));
        }
        if ($result === false) {
            return false;
        }
        $this->pos += strlen($data);
        if ($this->pos > $this->size) {
            $this->size = $this->pos;
        }
        $this->eof = false;
        return strlen($data);
    }
    /**
     * Retrieve the current position of a stream
     *
     * @return int
     * @access public
     */
    private function _stream_tell()
    {
        return $this->pos;
    }
    /**
    * Tests for end-of-file on a file pointer
    *
    * In my testing there are four classes functions that normally effect the pointer:
    fseek, fputs  / fwrite, fgets / fread and ftruncate.
    *
    * Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof()
    will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof()
    will return false. do fread($fp, 1) and feof() will then return true.
    *
    * @return bool
    * @access public
    */
    private function _stream_eof()
    {
        return $this->eof;
    }
    /**
     * Seeks to specific location in a stream
     *
     * @param int $offset
     * @param int $whence
     * @return bool
     * @access public
     */
    private function _stream_seek($offset, $whence)
    {
        switch ($whence) {
            case SEEK_SET:
                if ($offset < 0) {
                    return false;
                }
                break;
            case SEEK_CUR:
                $offset += $this->pos;
                break;
            case SEEK_END:
                $offset += $this->size;
        }
        $this->pos = $offset;
        $this->eof = false;
        return true;
    }
    /**
     * Change stream options
     *
     * @param string $path
     * @param int $option
     * @param mixed $var
     * @return bool
     * @access public
     */
    private function _stream_metadata($path, $option, $var)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        // stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined
        // see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246
        //     and https://github.com/php/php-src/blob/master/main/php_streams.h#L592
        switch ($option) {
            case 1:
                // PHP_STREAM_META_TOUCH
                $time = isset($var[0]) ? $var[0] : null;
                $atime = isset($var[1]) ? $var[1] : null;
                return $this->sftp->touch($path, $time, $atime);
            case 2:
            // PHP_STREAM_OWNER_NAME
            case 3:
                // PHP_STREAM_GROUP_NAME
                return false;
            case 4:
                // PHP_STREAM_META_OWNER
                return $this->sftp->chown($path, $var);
            case 5:
                // PHP_STREAM_META_GROUP
                return $this->sftp->chgrp($path, $var);
            case 6:
                // PHP_STREAM_META_ACCESS
                return $this->sftp->chmod($path, $var) !== false;
        }
    }
    /**
     * Retrieve the underlaying resource
     *
     * @param int $cast_as
     * @return resource
     * @access public
     */
    private function _stream_cast($cast_as)
    {
        return $this->sftp->fsock;
    }
    /**
     * Advisory file locking
     *
     * @param int $operation
     * @return bool
     * @access public
     */
    private function _stream_lock($operation)
    {
        return false;
    }
    /**
    * Renames a file or directory
    *
    * Attempts to rename oldname to newname, moving it between directories if necessary.
    If newname exists, it will be overwritten.  This is a departure from what \phpseclib3\Net\SFTP
    does.
    *
    * @param string $path_from
    * @param string $path_to
    * @return bool
    * @access public
    */
    private function _rename($path_from, $path_to)
    {
        $path1 = parse_url($path_from);
        $path2 = parse_url($path_to);
        unset($path1['path'], $path2['path']);
        if ($path1 != $path2) {
            return false;
        }
        $path_from = $this->parse_path($path_from);
        $path_to = parse_url($path_to);
        if ($path_from === false) {
            return false;
        }
        $path_to = $path_to['path'];
        // the $component part of parse_url() was added in PHP 5.1.2
        // "It is an error if there already exists a file with the name specified by newpath."
        //  -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5
        if (!$this->sftp->rename($path_from, $path_to)) {
            if ($this->sftp->stat($path_to)) {
                return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to);
            }
            return false;
        }
        return true;
    }
    /**
    * Open directory handle
    *
    * The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and
    removed in 5.4 I'm just going to ignore it.
    *
    * Also, nlist() is the best that this function is realistically going to be able to do. When an SFTP client
    sends a SSH_FXP_READDIR packet you don't generally get info on just one file but on multiple files. Quoting
    the SFTP specs:
    *
    * The SSH_FXP_NAME response has the following format:
    *
    * uint32     id
    uint32     count
    repeats count times:
    string     filename
    string     longname
    ATTRS      attrs
    *
    * @param string $path
    * @param int $options
    * @return bool
    * @access public
    */
    private function _dir_opendir($path, $options)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        $this->pos = 0;
        $this->entries = $this->sftp->nlist($path);
        return $this->entries !== false;
    }
    /**
     * Read entry from directory handle
     *
     * @return mixed
     * @access public
     */
    private function _dir_readdir()
    {
        if (isset($this->entries[$this->pos])) {
            return $this->entries[$this->pos++];
        }
        return false;
    }
    /**
     * Rewind directory handle
     *
     * @return bool
     * @access public
     */
    private function _dir_rewinddir()
    {
        $this->pos = 0;
        return true;
    }
    /**
     * Close directory handle
     *
     * @return bool
     * @access public
     */
    private function _dir_closedir()
    {
        return true;
    }
    /**
     * Create a directory
     *
     * Only valid $options is STREAM_MKDIR_RECURSIVE
     *
     * @param string $path
     * @param int $mode
     * @param int $options
     * @return bool
     * @access public
     */
    private function _mkdir($path, $mode, $options)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE);
    }
    /**
    * Removes a directory
    *
    * Only valid $options is STREAM_MKDIR_RECURSIVE per <http://php.net/streamwrapper.rmdir>, however,
    <http://php.net/rmdir>  does not have a $recursive parameter as mkdir() does so I don't know how
    STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as
    $options. What does 8 correspond to?
    *
    * @param string $path
    * @param int $options
    * @return bool
    * @access public
    */
    private function _rmdir($path, $options)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        return $this->sftp->rmdir($path);
    }
    /**
     * Flushes the output
     *
     * See <http://php.net/fflush>. Always returns true because \phpseclib3\Net\SFTP doesn't cache stuff before writing
     *
     * @return bool
     * @access public
     */
    private function _stream_flush()
    {
        return true;
    }
    /**
     * Retrieve information about a file resource
     *
     * @return mixed
     * @access public
     */
    private function _stream_stat()
    {
        $results = $this->sftp->stat($this->path);
        if ($results === false) {
            return false;
        }
        return $results;
    }
    /**
     * Delete a file
     *
     * @param string $path
     * @return bool
     * @access public
     */
    private function _unlink($path)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        return $this->sftp->delete($path, false);
    }
    /**
    * Retrieve information about a file
    *
    * Ignores the STREAM_URL_STAT_QUIET flag because the entirety of \phpseclib3\Net\SFTP\Stream is quiet by default
    might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll
    cross that bridge when and if it's reached
    *
    * @param string $path
    * @param int $flags
    * @return mixed
    * @access public
    */
    private function _url_stat($path, $flags)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        $results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path);
        if ($results === false) {
            return false;
        }
        return $results;
    }
    /**
     * Truncate stream
     *
     * @param int $new_size
     * @return bool
     * @access public
     */
    private function _stream_truncate($new_size)
    {
        if (!$this->sftp->truncate($this->path, $new_size)) {
            return false;
        }
        $this->eof = false;
        $this->size = $new_size;
        return true;
    }
    /**
    * Change stream options
    *
    * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't.
    The other two aren't supported because of limitations in \phpseclib3\Net\SFTP.
    *
    * @param int $option
    * @param int $arg1
    * @param int $arg2
    * @return bool
    * @access public
    */
    private function _stream_set_option($option, $arg1, $arg2)
    {
        return false;
    }
    /**
     * Close an resource
     *
     * @access public
     */
    private function _stream_close()
    {
    }
    /**
    * __call Magic Method
    *
    * When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you.
    Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function
    lets you figure that out.
    *
    * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
    NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
    *
    * @param string $name
    * @param array $arguments
    * @return mixed
    * @access public
    */
    public function __call($name, $arguments)
    {
        if (defined('NET_SFTP_STREAM_LOGGING')) {
            echo $name . '(';
            $last = count($arguments) - 1;
            foreach ($arguments as $i => $argument) {
                var_export($argument);
                if ($i != $last) {
                    echo ',';
                }
            }
            echo ")\r\n";
        }
        $name = '_' . $name;
        if (!method_exists($this, $name)) {
            return false;
        }
        return $this->{$name}(...$arguments);
    }
}<?php

/**
 * Pure-PHP ssh-agent client.
 *
 * {@internal See http://api.libssh.org/rfc/PROTOCOL.agent}
 *
 * PHP version 5
 *
 * @category  System
 * @package   SSH\Agent
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\System\SSH\Agent;

use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\EC;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\System\SSH\Agent;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\PrivateKey;
/**
 * Pure-PHP ssh-agent client identity object
 *
 * Instantiation should only be performed by \phpseclib3\System\SSH\Agent class.
 * This could be thought of as implementing an interface that phpseclib3\Crypt\RSA
 * implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
 * The methods in this interface would be getPublicKey and sign since those are the
 * methods phpseclib looks for to perform public key authentication.
 *
 * @package SSH\Agent
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  internal
 */
class Identity implements PrivateKey
{
    use \phpseclib3\System\SSH\Common\Traits\ReadBytes;
    // Signature Flags
    // See https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-5.3
    const SSH_AGENT_RSA2_256 = 2;
    const SSH_AGENT_RSA2_512 = 4;
    /**
     * Key Object
     *
     * @var \phpseclib3\Crypt\RSA
     * @access private
     * @see self::getPublicKey()
     */
    private $key;
    /**
     * Key Blob
     *
     * @var string
     * @access private
     * @see self::sign()
     */
    private $key_blob;
    /**
     * Socket Resource
     *
     * @var resource
     * @access private
     * @see self::sign()
     */
    private $fsock;
    /**
     * Signature flags
     *
     * @var int
     * @access private
     * @see self::sign()
     * @see self::setHash()
     */
    private $flags = 0;
    /**
     * Curve Aliases
     *
     * @var array
     * @access private
     */
    private static $curveAliases = ['secp256r1' => 'nistp256', 'secp384r1' => 'nistp384', 'secp521r1' => 'nistp521', 'Ed25519' => 'Ed25519'];
    /**
     * Default Constructor.
     *
     * @param resource $fsock
     * @return \phpseclib3\System\SSH\Agent\Identity
     * @access private
     */
    public function __construct($fsock)
    {
        $this->fsock = $fsock;
    }
    /**
     * Set Public Key
     *
     * Called by \phpseclib3\System\SSH\Agent::requestIdentities()
     *
     * @param \phpseclib3\Crypt\Common\PublicKey $key
     * @access private
     */
    public function withPublicKey($key)
    {
        if ($key instanceof EC) {
            if (is_array($key->getCurve()) || !isset(self::$curveAliases[$key->getCurve()])) {
                throw new UnsupportedAlgorithmException('The only supported curves are nistp256, nistp384, nistp512 and Ed25519');
            }
        }
        $new = clone $this;
        $new->key = $key;
        return $new;
    }
    /**
    * Set Public Key
    *
    * Called by \phpseclib3\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key
    but this saves a small amount of computation.
    *
    * @param string $key_blob
    * @access private
    */
    public function withPublicKeyBlob($key_blob)
    {
        $new = clone $this;
        $new->key_blob = $key_blob;
        return $new;
    }
    /**
     * Get Public Key
     *
     * Wrapper for $this->key->getPublicKey()
     *
     * @param string $type optional
     * @return mixed
     * @access public
     */
    public function getPublicKey($type = 'PKCS8')
    {
        return $this->key;
    }
    /**
     * Sets the hash
     *
     * @param string $hash
     * @access public
     */
    public function withHash($hash)
    {
        $new = clone $this;
        $hash = strtolower($hash);
        if ($this->key instanceof RSA) {
            $new->flags = 0;
            switch ($hash) {
                case 'sha1':
                    break;
                case 'sha256':
                    $new->flags = self::SSH_AGENT_RSA2_256;
                    break;
                case 'sha512':
                    $new->flags = self::SSH_AGENT_RSA2_512;
                    break;
                default:
                    throw new UnsupportedAlgorithmException('The only supported hashes for RSA are sha1, sha256 and sha512');
            }
        }
        if ($this->key instanceof EC) {
            switch ($this->key->getCurve()) {
                case 'secp256r1':
                    $expectedHash = 'sha256';
                    break;
                case 'secp384r1':
                    $expectedHash = 'sha384';
                    break;
                //case 'secp521r1':
                //case 'Ed25519':
                default:
                    $expectedHash = 'sha512';
            }
            if ($hash != $expectedHash) {
                throw new UnsupportedAlgorithmException('The only supported hash for ' . self::$curveAliases[$key->getCurve()] . ' is ' . $expectedHash);
            }
        }
        if ($this->key instanceof DSA) {
            if ($hash != 'sha1') {
                throw new UnsupportedAlgorithmException('The only supported hash for DSA is sha1');
            }
        }
        return $new;
    }
    /**
     * Sets the padding
     *
     * Only PKCS1 padding is supported
     *
     * @param string $padding
     * @access public
     */
    public function withPadding($padding)
    {
        if (!$this->key instanceof RSA) {
            throw new UnsupportedAlgorithmException('Only RSA keys support padding');
        }
        if ($padding != RSA::SIGNATURE_PKCS1 && $padding != RSA::SIGNATURE_RELAXED_PKCS1) {
            throw new UnsupportedAlgorithmException('ssh-agent can only create PKCS1 signatures');
        }
        return $this;
    }
    /**
     * Determines the signature padding mode
     *
     * Valid values are: ASN1, SSH2, Raw
     *
     * @access public
     * @param string $format
     */
    public function withSignatureFormat($format)
    {
        if ($this->key instanceof RSA) {
            throw new UnsupportedAlgorithmException('Only DSA and EC keys support signature format setting');
        }
        if ($format != 'SSH2') {
            throw new UnsupportedAlgorithmException('Only SSH2-formatted signatures are currently supported');
        }
        return $this;
    }
    /**
     * Returns the curve
     *
     * Returns a string if it's a named curve, an array if not
     *
     * @access public
     * @return (string | array)
     */
    public function getCurve()
    {
        if (!$this->key instanceof EC) {
            throw new UnsupportedAlgorithmException('Only EC keys have curves');
        }
        return $this->key->getCurve();
    }
    /**
     * Create a signature
     *
     * See "2.6.2 Protocol 2 private key signature request"
     *
     * @param string $message
     * @return string
     * @throws \RuntimeException on connection errors
     * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
     * @access public
     */
    public function sign($message)
    {
        // the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
        $packet = Strings::packSSH2('CssN', Agent::SSH_AGENTC_SIGN_REQUEST, $this->key_blob, $message, $this->flags);
        $packet = Strings::packSSH2('s', $packet);
        if (strlen($packet) != fputs($this->fsock, $packet)) {
            throw new \RuntimeException('Connection closed during signing');
        }
        $length = current(unpack('N', $this->readBytes(4)));
        $packet = $this->readBytes($length);
        list($type, $signature_blob) = Strings::unpackSSH2('Cs', $packet);
        if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
            throw new \RuntimeException('Unable to retrieve signature');
        }
        if (!$this->key instanceof RSA) {
            return $signature_blob;
        }
        list($type, $signature_blob) = Strings::unpackSSH2('ss', $signature_blob);
        return $signature_blob;
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        throw new \RuntimeException('ssh-agent does not provide a mechanism to get the private key');
    }
    /**
     * Sets the password
     *
     * @access public
     * @param (string | boolean) $password
     */
    public function withPassword($password = false)
    {
        throw new \RuntimeException('ssh-agent does not provide a mechanism to get the private key');
    }
}<?php

/**
 * ReadBytes trait
 *
 * PHP version 5
 *
 * @category  System
 * @package   SSH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\System\SSH\Common\Traits;

/**
 * ReadBytes trait
 *
 * @package SSH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
trait ReadBytes
{
    /**
     * Read data
     *
     * @param int $length
     * @throws \RuntimeException on connection errors
     * @access public
     */
    public function readBytes($length)
    {
        $temp = fread($this->fsock, $length);
        if (strlen($temp) != $length) {
            throw new \RuntimeException("Expected {$length} bytes; got " . strlen($temp));
        }
        return $temp;
    }
}<?php

/**
 * Pure-PHP ssh-agent client.
 *
 * {@internal See http://api.libssh.org/rfc/PROTOCOL.agent}
 *
 * PHP version 5
 *
 * Here are some examples of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $agent = new \phpseclib3\System\SSH\Agent();
 *
 *    $ssh = new \phpseclib3\Net\SSH2('www.domain.tld');
 *    if (!$ssh->login('username', $agent)) {
 *        exit('Login Failed');
 *    }
 *
 *    echo $ssh->exec('pwd');
 *    echo $ssh->exec('ls -la');
 * ?>
 * </code>
 *
 * @category  System
 * @package   SSH\Agent
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2014 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\System\SSH;

use phpseclib3\Crypt\RSA;
use phpseclib3\Exception\BadConfigurationException;
use phpseclib3\System\SSH\Agent\Identity;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\PublicKeyLoader;
/**
 * Pure-PHP ssh-agent client identity factory
 *
 * requestIdentities() method pumps out \phpseclib3\System\SSH\Agent\Identity objects
 *
 * @package SSH\Agent
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Agent
{
    use Common\Traits\ReadBytes;
    // Message numbers
    // to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
    const SSH_AGENTC_REQUEST_IDENTITIES = 11;
    // this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
    const SSH_AGENT_IDENTITIES_ANSWER = 12;
    // the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
    const SSH_AGENTC_SIGN_REQUEST = 13;
    // the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
    const SSH_AGENT_SIGN_RESPONSE = 14;
    // Agent forwarding status
    // no forwarding requested and not active
    const FORWARD_NONE = 0;
    // request agent forwarding when opportune
    const FORWARD_REQUEST = 1;
    // forwarding has been request and is active
    const FORWARD_ACTIVE = 2;
    /**
     * Unused
     */
    const SSH_AGENT_FAILURE = 5;
    /**
     * Socket Resource
     *
     * @var resource
     * @access private
     */
    private $fsock;
    /**
     * Agent forwarding status
     *
     * @var int
     * @access private
     */
    private $forward_status = self::FORWARD_NONE;
    /**
     * Buffer for accumulating forwarded authentication
     * agent data arriving on SSH data channel destined
     * for agent unix socket
     *
     * @var string
     * @access private
     */
    private $socket_buffer = '';
    /**
     * Tracking the number of bytes we are expecting
     * to arrive for the agent socket on the SSH data
     * channel
     *
     * @var int
     * @access private
     */
    private $expected_bytes = 0;
    /**
     * The current request channel
     *
     * @var int
     * @access private
     */
    private $request_channel;
    /**
     * Default Constructor
     *
     * @return \phpseclib3\System\SSH\Agent
     * @throws \phpseclib3\Exception\BadConfigurationException if SSH_AUTH_SOCK cannot be found
     * @throws \RuntimeException on connection errors
     * @access public
     */
    public function __construct($address = null)
    {
        if (!$address) {
            switch (true) {
                case isset($_SERVER['SSH_AUTH_SOCK']):
                    $address = $_SERVER['SSH_AUTH_SOCK'];
                    break;
                case isset($_ENV['SSH_AUTH_SOCK']):
                    $address = $_ENV['SSH_AUTH_SOCK'];
                    break;
                default:
                    throw new BadConfigurationException('SSH_AUTH_SOCK not found');
            }
        }
        $this->fsock = \Phabel\Target\Php80\Polyfill::fsockopen('unix://' . $address, 0, $errno, $errstr);
        if (!$this->fsock) {
            throw new \RuntimeException("Unable to connect to ssh-agent (Error {$errno}: {$errstr})");
        }
    }
    /**
    * Request Identities
    *
    * See "2.5.2 Requesting a list of protocol 2 keys"
    Returns an array containing zero or more \phpseclib3\System\SSH\Agent\Identity objects
    *
    * @return array
    * @throws \RuntimeException on receipt of unexpected packets
    * @access public
    */
    public function requestIdentities()
    {
        if (!$this->fsock) {
            return [];
        }
        $packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
        if (strlen($packet) != fputs($this->fsock, $packet)) {
            throw new \RuntimeException('Connection closed while requesting identities');
        }
        $length = current(unpack('N', $this->readBytes(4)));
        $packet = $this->readBytes($length);
        list($type, $keyCount) = Strings::unpackSSH2('CN', $packet);
        if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
            throw new \RuntimeException('Unable to request identities');
        }
        $identities = [];
        for ($i = 0; $i < $keyCount; $i++) {
            list($key_blob, $comment) = Strings::unpackSSH2('ss', $packet);
            $temp = $key_blob;
            list($key_type) = Strings::unpackSSH2('s', $temp);
            switch ($key_type) {
                case 'ssh-rsa':
                case 'ssh-dss':
                case 'ssh-ed25519':
                case 'ecdsa-sha2-nistp256':
                case 'ecdsa-sha2-nistp384':
                case 'ecdsa-sha2-nistp521':
                    $key = PublicKeyLoader::load($key_type . ' ' . base64_encode($key_blob));
            }
            // resources are passed by reference by default
            if (isset($key)) {
                $identity = (new Identity($this->fsock))->withPublicKey($key)->withPublicKeyBlob($key_blob);
                $identities[] = $identity;
                unset($key);
            }
        }
        return $identities;
    }
    /**
    * Signal that agent forwarding should
    be requested when a channel is opened
    *
    * @param \phpseclib3\Net\SSH2 $ssh
    * @return bool
    * @access public
    */
    public function startSSHForwarding($ssh)
    {
        if ($this->forward_status == self::FORWARD_NONE) {
            $this->forward_status = self::FORWARD_REQUEST;
        }
    }
    /**
     * Request agent forwarding of remote server
     *
     * @param \phpseclib3\Net\SSH2 $ssh
     * @return bool
     * @access private
     */
    private function request_forwarding($ssh)
    {
        if (!$ssh->requestAgentForwarding()) {
            return false;
        }
        $this->forward_status = self::FORWARD_ACTIVE;
        return true;
    }
    /**
    * On successful channel open
    *
    * This method is called upon successful channel
    open to give the SSH Agent an opportunity
    to take further action. i.e. request agent forwarding
    *
    * @param \phpseclib3\Net\SSH2 $ssh
    * @access private
    */
    public function registerChannelOpen($ssh)
    {
        if ($this->forward_status == self::FORWARD_REQUEST) {
            $this->request_forwarding($ssh);
        }
    }
    /**
     * Forward data to SSH Agent and return data reply
     *
     * @param string $data
     * @return string Data from SSH Agent
     * @throws \RuntimeException on connection errors
     * @access public
     */
    public function forwardData($data)
    {
        if ($this->expected_bytes > 0) {
            $this->socket_buffer .= $data;
            $this->expected_bytes -= strlen($data);
        } else {
            $agent_data_bytes = current(unpack('N', $data));
            $current_data_bytes = strlen($data);
            $this->socket_buffer = $data;
            if ($current_data_bytes != $agent_data_bytes + 4) {
                $this->expected_bytes = $agent_data_bytes + 4 - $current_data_bytes;
                return false;
            }
        }
        if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
            throw new \RuntimeException('Connection closed attempting to forward data to SSH agent');
        }
        $this->socket_buffer = '';
        $this->expected_bytes = 0;
        $agent_reply_bytes = current(unpack('N', $this->readBytes(4)));
        $agent_reply_data = $this->readBytes($agent_reply_bytes);
        $agent_reply_data = current(unpack('a*', $agent_reply_data));
        return pack('Na*', $agent_reply_bytes, $agent_reply_data);
    }
}<?php

/**
 * Pure-PHP ASN.1 Parser
 *
 * PHP version 5
 *
 * ASN.1 provides the semantics for data encoded using various schemes.  The most commonly
 * utilized scheme is DER or the "Distinguished Encoding Rules".  PEM's are base64 encoded
 * DER blobs.
 *
 * \phpseclib3\File\ASN1 decodes and encodes DER formatted messages and places them in a semantic context.
 *
 * Uses the 1988 ASN.1 syntax.
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2012 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\File\ASN1\Element;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use DateTime;
use DateTimeZone;
/**
 * Pure-PHP ASN.1 Parser
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ASN1
{
    // Tag Classes
    // http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12
    const CLASS_UNIVERSAL = 0;
    const CLASS_APPLICATION = 1;
    const CLASS_CONTEXT_SPECIFIC = 2;
    const CLASS_PRIVATE = 3;
    // Tag Classes
    // http://www.obj-sys.com/asn1tutorial/node124.html
    const TYPE_BOOLEAN = 1;
    const TYPE_INTEGER = 2;
    const TYPE_BIT_STRING = 3;
    const TYPE_OCTET_STRING = 4;
    const TYPE_NULL = 5;
    const TYPE_OBJECT_IDENTIFIER = 6;
    //const TYPE_OBJECT_DESCRIPTOR = 7;
    //const TYPE_INSTANCE_OF       = 8; // EXTERNAL
    const TYPE_REAL = 9;
    const TYPE_ENUMERATED = 10;
    //const TYPE_EMBEDDED          = 11;
    const TYPE_UTF8_STRING = 12;
    //const TYPE_RELATIVE_OID      = 13;
    const TYPE_SEQUENCE = 16;
    // SEQUENCE OF
    const TYPE_SET = 17;
    // SET OF
    // More Tag Classes
    // http://www.obj-sys.com/asn1tutorial/node10.html
    const TYPE_NUMERIC_STRING = 18;
    const TYPE_PRINTABLE_STRING = 19;
    const TYPE_TELETEX_STRING = 20;
    // T61String
    const TYPE_VIDEOTEX_STRING = 21;
    const TYPE_IA5_STRING = 22;
    const TYPE_UTC_TIME = 23;
    const TYPE_GENERALIZED_TIME = 24;
    const TYPE_GRAPHIC_STRING = 25;
    const TYPE_VISIBLE_STRING = 26;
    // ISO646String
    const TYPE_GENERAL_STRING = 27;
    const TYPE_UNIVERSAL_STRING = 28;
    //const TYPE_CHARACTER_STRING = 29;
    const TYPE_BMP_STRING = 30;
    // Tag Aliases
    // These tags are kinda place holders for other tags.
    const TYPE_CHOICE = -1;
    const TYPE_ANY = -2;
    /**
     * ASN.1 object identifiers
     *
     * @var array
     * @access private
     * @link http://en.wikipedia.org/wiki/Object_identifier
     */
    private static $oids = [];
    /**
     * ASN.1 object identifier reverse mapping
     *
     * @var array
     * @access private
     */
    private static $reverseOIDs = [];
    /**
     * Default date format
     *
     * @var string
     * @access private
     * @link http://php.net/class.datetime
     */
    private static $format = 'D, d M Y H:i:s O';
    /**
     * Filters
     *
     * If the mapping type is self::TYPE_ANY what do we actually encode it as?
     *
     * @var array
     * @access private
     * @see self::encode_der()
     */
    private static $filters;
    /**
     * Current Location of most recent ASN.1 encode process
     *
     * Useful for debug purposes
     *
     * @var array
     * @access private
     * @see self::encode_der()
     */
    private static $location;
    /**
     * DER Encoded String
     *
     * In case we need to create ASN1\Element object's..
     *
     * @var string
     * @access private
     * @see self::decodeDER()
     */
    private static $encoded;
    /**
     * Type mapping table for the ANY type.
     *
     * Structured or unknown types are mapped to a \phpseclib3\File\ASN1\Element.
     * Unambiguous types get the direct mapping (int/real/bool).
     * Others are mapped as a choice, with an extra indexing level.
     *
     * @var array
     * @access public
     */
    const ANY_MAP = [
        self::TYPE_BOOLEAN => true,
        self::TYPE_INTEGER => true,
        self::TYPE_BIT_STRING => 'bitString',
        self::TYPE_OCTET_STRING => 'octetString',
        self::TYPE_NULL => 'null',
        self::TYPE_OBJECT_IDENTIFIER => 'objectIdentifier',
        self::TYPE_REAL => true,
        self::TYPE_ENUMERATED => 'enumerated',
        self::TYPE_UTF8_STRING => 'utf8String',
        self::TYPE_NUMERIC_STRING => 'numericString',
        self::TYPE_PRINTABLE_STRING => 'printableString',
        self::TYPE_TELETEX_STRING => 'teletexString',
        self::TYPE_VIDEOTEX_STRING => 'videotexString',
        self::TYPE_IA5_STRING => 'ia5String',
        self::TYPE_UTC_TIME => 'utcTime',
        self::TYPE_GENERALIZED_TIME => 'generalTime',
        self::TYPE_GRAPHIC_STRING => 'graphicString',
        self::TYPE_VISIBLE_STRING => 'visibleString',
        self::TYPE_GENERAL_STRING => 'generalString',
        self::TYPE_UNIVERSAL_STRING => 'universalString',
        //self::TYPE_CHARACTER_STRING     => 'characterString',
        self::TYPE_BMP_STRING => 'bmpString',
    ];
    /**
     * String type to character size mapping table.
     *
     * Non-convertable types are absent from this table.
     * size == 0 indicates variable length encoding.
     *
     * @var array
     * @access public
     */
    const STRING_TYPE_SIZE = [self::TYPE_UTF8_STRING => 0, self::TYPE_BMP_STRING => 2, self::TYPE_UNIVERSAL_STRING => 4, self::TYPE_PRINTABLE_STRING => 1, self::TYPE_TELETEX_STRING => 1, self::TYPE_IA5_STRING => 1, self::TYPE_VISIBLE_STRING => 1];
    /**
     * Parse BER-encoding
     *
     * Serves a similar purpose to openssl's asn1parse
     *
     * @param string $encoded
     * @return array
     * @access public
     */
    public static function decodeBER($encoded)
    {
        if ($encoded instanceof Element) {
            $encoded = $encoded->element;
        }
        self::$encoded = $encoded;
        $decoded = [self::decode_ber($encoded)];
        // encapsulate in an array for BC with the old decodeBER
        return $decoded;
    }
    /**
    * Parse BER-encoding (Helper function)
    *
    * Sometimes we want to get the BER encoding of a particular tag.  $start lets us do that without having to reencode.
    $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and
    self::TYPE_OCTET_STRING. In those cases, the indefinite length is used.
    *
    * @param string $encoded
    * @param int $start
    * @param int $encoded_pos
    * @return (array | bool)
    * @access private
    */
    private static function decode_ber($encoded, $start = 0, $encoded_pos = 0)
    {
        $current = ['start' => $start];
        if (!isset($encoded[$encoded_pos])) {
            return false;
        }
        $type = ord($encoded[$encoded_pos++]);
        $startOffset = 1;
        $constructed = $type >> 5 & 1;
        $tag = $type & 0x1f;
        if ($tag == 0x1f) {
            $tag = 0;
            // process septets (since the eighth bit is ignored, it's not an octet)
            do {
                if (!isset($encoded[$encoded_pos])) {
                    return false;
                }
                $temp = ord($encoded[$encoded_pos++]);
                $startOffset++;
                $loop = $temp >> 7;
                $tag <<= 7;
                $temp &= 0x7f;
                // "bits 7 to 1 of the first subsequent octet shall not all be zero"
                if ($startOffset == 2 && $temp == 0) {
                    return false;
                }
                $tag |= $temp;
            } while ($loop);
        }
        $start += $startOffset;
        // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
        if (!isset($encoded[$encoded_pos])) {
            return false;
        }
        $length = ord($encoded[$encoded_pos++]);
        $start++;
        if ($length == 0x80) {
            // indefinite length
            // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
            //  immediately available." -- paragraph 8.1.3.2.c
            $length = strlen($encoded) - $encoded_pos;
        } elseif ($length & 0x80) {
            // definite length, long form
            // technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only
            // support it up to four.
            $length &= 0x7f;
            $temp = \Phabel\Target\Php80\Polyfill::substr($encoded, $encoded_pos, $length);
            $encoded_pos += $length;
            // tags of indefinte length don't really have a header length; this length includes the tag
            $current += ['headerlength' => $length + 2];
            $start += $length;
            extract(unpack('Nlength', \Phabel\Target\Php80\Polyfill::substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
            /** @var integer $length */
        } else {
            $current += ['headerlength' => 2];
        }
        if ($length > strlen($encoded) - $encoded_pos) {
            return false;
        }
        $content = \Phabel\Target\Php80\Polyfill::substr($encoded, $encoded_pos, $length);
        $content_pos = 0;
        // at this point $length can be overwritten. it's only accurate for definite length things as is
        /* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1
                   built-in types. It defines an application-independent data type that must be distinguishable from all other
                   data types. The other three classes are user defined. The APPLICATION class distinguishes data types that
                   have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within
                   a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the
                   alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this
                   data type; the term CONTEXT-SPECIFIC does not appear.
        
                     -- http://www.obj-sys.com/asn1tutorial/node12.html */
        $class = $type >> 6 & 3;
        switch ($class) {
            case self::CLASS_APPLICATION:
            case self::CLASS_PRIVATE:
            case self::CLASS_CONTEXT_SPECIFIC:
                if (!$constructed) {
                    return ['type' => $class, 'constant' => $tag, 'content' => $content, 'length' => $length + $start - $current['start']] + $current;
                }
                $newcontent = [];
                $remainingLength = $length;
                while ($remainingLength > 0) {
                    $temp = self::decode_ber($content, $start, $content_pos);
                    if ($temp === false) {
                        break;
                    }
                    $length = $temp['length'];
                    // end-of-content octets - see paragraph 8.1.5
                    if (\Phabel\Target\Php80\Polyfill::substr($content, $content_pos + $length, 2) == "\x00\x00") {
                        $length += 2;
                        $start += $length;
                        $newcontent[] = $temp;
                        break;
                    }
                    $start += $length;
                    $remainingLength -= $length;
                    $newcontent[] = $temp;
                    $content_pos += $length;
                }
                return [
                    'type' => $class,
                    'constant' => $tag,
                    // the array encapsulation is for BC with the old format
                    'content' => $newcontent,
                    // the only time when $content['headerlength'] isn't defined is when the length is indefinite.
                    // the absence of $content['headerlength'] is how we know if something is indefinite or not.
                    // technically, it could be defined to be 2 and then another indicator could be used but whatever.
                    'length' => $start - $current['start'],
                ] + $current;
        }
        $current += ['type' => $tag];
        // decode UNIVERSAL tags
        switch ($tag) {
            case self::TYPE_BOOLEAN:
                // "The contents octets shall consist of a single octet." -- paragraph 8.2.1
                if ($constructed || strlen($content) != 1) {
                    return false;
                }
                $current['content'] = (bool) ord($content[$content_pos]);
                break;
            case self::TYPE_INTEGER:
            case self::TYPE_ENUMERATED:
                if ($constructed) {
                    return false;
                }
                $current['content'] = new BigInteger(\Phabel\Target\Php80\Polyfill::substr($content, $content_pos), -256);
                break;
            case self::TYPE_REAL:
                // not currently supported
                return false;
            case self::TYPE_BIT_STRING:
                // The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
                // the number of unused bits in the final subsequent octet. The number shall be in the range zero to
                // seven.
                if (!$constructed) {
                    $current['content'] = \Phabel\Target\Php80\Polyfill::substr($content, $content_pos);
                } else {
                    $temp = self::decode_ber($content, $start, $content_pos);
                    if ($temp === false) {
                        return false;
                    }
                    $length -= strlen($content) - $content_pos;
                    $last = count($temp) - 1;
                    for ($i = 0; $i < $last; $i++) {
                        // all subtags should be bit strings
                        if ($temp[$i]['type'] != self::TYPE_BIT_STRING) {
                            return false;
                        }
                        $current['content'] .= \Phabel\Target\Php80\Polyfill::substr($temp[$i]['content'], 1);
                    }
                    // all subtags should be bit strings
                    if ($temp[$last]['type'] != self::TYPE_BIT_STRING) {
                        return false;
                    }
                    $current['content'] = $temp[$last]['content'][0] . $current['content'] . \Phabel\Target\Php80\Polyfill::substr($temp[$i]['content'], 1);
                }
                break;
            case self::TYPE_OCTET_STRING:
                if (!$constructed) {
                    $current['content'] = \Phabel\Target\Php80\Polyfill::substr($content, $content_pos);
                } else {
                    $current['content'] = '';
                    $length = 0;
                    while (\Phabel\Target\Php80\Polyfill::substr($content, $content_pos, 2) != "\x00\x00") {
                        $temp = self::decode_ber($content, $length + $start, $content_pos);
                        if ($temp === false) {
                            return false;
                        }
                        $content_pos += $temp['length'];
                        // all subtags should be octet strings
                        if ($temp['type'] != self::TYPE_OCTET_STRING) {
                            return false;
                        }
                        $current['content'] .= $temp['content'];
                        $length += $temp['length'];
                    }
                    if (\Phabel\Target\Php80\Polyfill::substr($content, $content_pos, 2) == "\x00\x00") {
                        $length += 2;
                        // +2 for the EOC
                    }
                }
                break;
            case self::TYPE_NULL:
                // "The contents octets shall not contain any octets." -- paragraph 8.8.2
                if ($constructed || strlen($content)) {
                    return false;
                }
                break;
            case self::TYPE_SEQUENCE:
            case self::TYPE_SET:
                if (!$constructed) {
                    return false;
                }
                $offset = 0;
                $current['content'] = [];
                $content_len = strlen($content);
                while ($content_pos < $content_len) {
                    // if indefinite length construction was used and we have an end-of-content string next
                    // see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
                    if (!isset($current['headerlength']) && \Phabel\Target\Php80\Polyfill::substr($content, $content_pos, 2) == "\x00\x00") {
                        $length = $offset + 2;
                        // +2 for the EOC
                        break 2;
                    }
                    $temp = self::decode_ber($content, $start + $offset, $content_pos);
                    if ($temp === false) {
                        return false;
                    }
                    $content_pos += $temp['length'];
                    $current['content'][] = $temp;
                    $offset += $temp['length'];
                }
                break;
            case self::TYPE_OBJECT_IDENTIFIER:
                if ($constructed) {
                    return false;
                }
                $current['content'] = self::decodeOID(\Phabel\Target\Php80\Polyfill::substr($content, $content_pos));
                if ($current['content'] === false) {
                    return false;
                }
                break;
            /* Each character string type shall be encoded as if it had been declared:
                           [UNIVERSAL x] IMPLICIT OCTET STRING
            
                             -- X.690-0207.pdf#page=23 (paragraph 8.21.3)
            
                           Per that, we're not going to do any validation.  If there are any illegal characters in the string,
                           we don't really care */
            case self::TYPE_NUMERIC_STRING:
            // 0,1,2,3,4,5,6,7,8,9, and space
            case self::TYPE_PRINTABLE_STRING:
            // Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma,
            // hyphen, full stop, solidus, colon, equal sign, question mark
            case self::TYPE_TELETEX_STRING:
            // The Teletex character set in CCITT's T61, space, and delete
            // see http://en.wikipedia.org/wiki/Teletex#Character_sets
            case self::TYPE_VIDEOTEX_STRING:
            // The Videotex character set in CCITT's T.100 and T.101, space, and delete
            case self::TYPE_VISIBLE_STRING:
            // Printing character sets of international ASCII, and space
            case self::TYPE_IA5_STRING:
            // International Alphabet 5 (International ASCII)
            case self::TYPE_GRAPHIC_STRING:
            // All registered G sets, and space
            case self::TYPE_GENERAL_STRING:
            // All registered C and G sets, space and delete
            case self::TYPE_UTF8_STRING:
            // ????
            case self::TYPE_BMP_STRING:
                if ($constructed) {
                    return false;
                }
                $current['content'] = \Phabel\Target\Php80\Polyfill::substr($content, $content_pos);
                break;
            case self::TYPE_UTC_TIME:
            case self::TYPE_GENERALIZED_TIME:
                if ($constructed) {
                    return false;
                }
                $current['content'] = self::decodeTime(\Phabel\Target\Php80\Polyfill::substr($content, $content_pos), $tag);
                break;
            default:
                return false;
        }
        $start += $length;
        // ie. length is the length of the full TLV encoding - it's not just the length of the value
        return $current + ['length' => $start - $current['start']];
    }
    /**
     * ASN.1 Map
     *
     * Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format.
     *
     * "Special" mappings may be applied on a per tag-name basis via $special.
     *
     * @param array $decoded
     * @param array $mapping
     * @param array $special
     * @return (array | bool | Element)
     * @access public
     */
    public static function asn1map($decoded, $mapping, $special = [])
    {
        if (!is_array($decoded)) {
            return false;
        }
        if (isset($mapping['explicit']) && is_array($decoded['content'])) {
            $decoded = $decoded['content'][0];
        }
        switch (true) {
            case $mapping['type'] == self::TYPE_ANY:
                $intype = $decoded['type'];
                // !isset(self::ANY_MAP[$intype]) produces a fatal error on PHP 5.6
                if (isset($decoded['constant']) || !array_key_exists($intype, self::ANY_MAP) || ord(self::$encoded[$decoded['start']]) & 0x20) {
                    return new Element(\Phabel\Target\Php80\Polyfill::substr(self::$encoded, $decoded['start'], $decoded['length']));
                }
                $inmap = self::ANY_MAP[$intype];
                if (is_string($inmap)) {
                    return [$inmap => self::asn1map($decoded, ['type' => $intype] + $mapping, $special)];
                }
                break;
            case $mapping['type'] == self::TYPE_CHOICE:
                foreach ($mapping['children'] as $key => $option) {
                    switch (true) {
                        case isset($option['constant']) && $option['constant'] == $decoded['constant']:
                        case !isset($option['constant']) && $option['type'] == $decoded['type']:
                            $value = self::asn1map($decoded, $option, $special);
                            break;
                        case !isset($option['constant']) && $option['type'] == self::TYPE_CHOICE:
                            $v = self::asn1map($decoded, $option, $special);
                            if (isset($v)) {
                                $value = $v;
                            }
                    }
                    if (isset($value)) {
                        if (isset($special[$key])) {
                            $value = $special[$key]($value);
                        }
                        return [$key => $value];
                    }
                }
                return null;
            case isset($mapping['implicit']):
            case isset($mapping['explicit']):
            case $decoded['type'] == $mapping['type']:
                break;
            default:
                // if $decoded['type'] and $mapping['type'] are both strings, but different types of strings,
                // let it through
                switch (true) {
                    case $decoded['type'] < 18:
                    // self::TYPE_NUMERIC_STRING == 18
                    case $decoded['type'] > 30:
                    // self::TYPE_BMP_STRING == 30
                    case $mapping['type'] < 18:
                    case $mapping['type'] > 30:
                        return null;
                }
        }
        if (isset($mapping['implicit'])) {
            $decoded['type'] = $mapping['type'];
        }
        switch ($decoded['type']) {
            case self::TYPE_SEQUENCE:
                $map = [];
                // ignore the min and max
                if (isset($mapping['min']) && isset($mapping['max'])) {
                    $child = $mapping['children'];
                    foreach ($decoded['content'] as $content) {
                        if (($map[] = self::asn1map($content, $child, $special)) === null) {
                            return null;
                        }
                    }
                    return $map;
                }
                $n = count($decoded['content']);
                $i = 0;
                foreach ($mapping['children'] as $key => $child) {
                    $maymatch = $i < $n;
                    // Match only existing input.
                    if ($maymatch) {
                        $temp = $decoded['content'][$i];
                        if ($child['type'] != self::TYPE_CHOICE) {
                            // Get the mapping and input class & constant.
                            $childClass = $tempClass = self::CLASS_UNIVERSAL;
                            $constant = null;
                            if (isset($temp['constant'])) {
                                $tempClass = $temp['type'];
                            }
                            if (isset($child['class'])) {
                                $childClass = $child['class'];
                                $constant = $child['cast'];
                            } elseif (isset($child['constant'])) {
                                $childClass = self::CLASS_CONTEXT_SPECIFIC;
                                $constant = $child['constant'];
                            }
                            if (isset($constant) && isset($temp['constant'])) {
                                // Can only match if constants and class match.
                                $maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
                            } else {
                                // Can only match if no constant expected and type matches or is generic.
                                $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false;
                            }
                        }
                    }
                    if ($maymatch) {
                        // Attempt submapping.
                        $candidate = self::asn1map($temp, $child, $special);
                        $maymatch = $candidate !== null;
                    }
                    if ($maymatch) {
                        // Got the match: use it.
                        if (isset($special[$key])) {
                            $candidate = $special[$key]($candidate);
                        }
                        $map[$key] = $candidate;
                        $i++;
                    } elseif (isset($child['default'])) {
                        $map[$key] = $child['default'];
                    } elseif (!isset($child['optional'])) {
                        return null;
                        // Syntax error.
                    }
                }
                // Fail mapping if all input items have not been consumed.
                return $i < $n ? null : $map;
            // the main diff between sets and sequences is the encapsulation of the foreach in another for loop
            case self::TYPE_SET:
                $map = [];
                // ignore the min and max
                if (isset($mapping['min']) && isset($mapping['max'])) {
                    $child = $mapping['children'];
                    foreach ($decoded['content'] as $content) {
                        if (($map[] = self::asn1map($content, $child, $special)) === null) {
                            return null;
                        }
                    }
                    return $map;
                }
                for ($i = 0; $i < count($decoded['content']); $i++) {
                    $temp = $decoded['content'][$i];
                    $tempClass = self::CLASS_UNIVERSAL;
                    if (isset($temp['constant'])) {
                        $tempClass = $temp['type'];
                    }
                    foreach ($mapping['children'] as $key => $child) {
                        if (isset($map[$key])) {
                            continue;
                        }
                        $maymatch = true;
                        if ($child['type'] != self::TYPE_CHOICE) {
                            $childClass = self::CLASS_UNIVERSAL;
                            $constant = null;
                            if (isset($child['class'])) {
                                $childClass = $child['class'];
                                $constant = $child['cast'];
                            } elseif (isset($child['constant'])) {
                                $childClass = self::CLASS_CONTEXT_SPECIFIC;
                                $constant = $child['constant'];
                            }
                            if (isset($constant) && isset($temp['constant'])) {
                                // Can only match if constants and class match.
                                $maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
                            } else {
                                // Can only match if no constant expected and type matches or is generic.
                                $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false;
                            }
                        }
                        if ($maymatch) {
                            // Attempt submapping.
                            $candidate = self::asn1map($temp, $child, $special);
                            $maymatch = $candidate !== null;
                        }
                        if (!$maymatch) {
                            break;
                        }
                        // Got the match: use it.
                        if (isset($special[$key])) {
                            $candidate = $special[$key]($candidate);
                        }
                        $map[$key] = $candidate;
                        break;
                    }
                }
                foreach ($mapping['children'] as $key => $child) {
                    if (!isset($map[$key])) {
                        if (isset($child['default'])) {
                            $map[$key] = $child['default'];
                        } elseif (!isset($child['optional'])) {
                            return null;
                        }
                    }
                }
                return $map;
            case self::TYPE_OBJECT_IDENTIFIER:
                return isset(self::$oids[$decoded['content']]) ? self::$oids[$decoded['content']] : $decoded['content'];
            case self::TYPE_UTC_TIME:
            case self::TYPE_GENERALIZED_TIME:
                // for explicitly tagged optional stuff
                if (is_array($decoded['content'])) {
                    $decoded['content'] = $decoded['content'][0]['content'];
                }
                // for implicitly tagged optional stuff
                // in theory, doing isset($mapping['implicit']) would work but malformed certs do exist
                // in the wild that OpenSSL decodes without issue so we'll support them as well
                if (!is_object($decoded['content'])) {
                    $decoded['content'] = self::decodeTime($decoded['content'], $decoded['type']);
                }
                return $decoded['content'] ? $decoded['content']->format(self::$format) : false;
            case self::TYPE_BIT_STRING:
                if (isset($mapping['mapping'])) {
                    $offset = ord($decoded['content'][0]);
                    $size = (strlen($decoded['content']) - 1) * 8 - $offset;
                    /*
                       From X.680-0207.pdf#page=46 (21.7):
                    
                       "When a "NamedBitList" is used in defining a bitstring type ASN.1 encoding rules are free to add (or remove)
                        arbitrarily any trailing 0 bits to (or from) values that are being encoded or decoded. Application designers should
                        therefore ensure that different semantics are not associated with such values which differ only in the number of trailing
                        0 bits."
                    */
                    $bits = count($mapping['mapping']) == $size ? [] : array_fill(0, count($mapping['mapping']) - $size, false);
                    for ($i = strlen($decoded['content']) - 1; $i > 0; $i--) {
                        $current = ord($decoded['content'][$i]);
                        for ($j = $offset; $j < 8; $j++) {
                            $bits[] = (bool) ($current & 1 << $j);
                        }
                        $offset = 0;
                    }
                    $values = [];
                    $map = array_reverse($mapping['mapping']);
                    foreach ($map as $i => $value) {
                        if ($bits[$i]) {
                            $values[] = $value;
                        }
                    }
                    return $values;
                }
            case self::TYPE_OCTET_STRING:
                return $decoded['content'];
            case self::TYPE_NULL:
                return '';
            case self::TYPE_BOOLEAN:
                return $decoded['content'];
            case self::TYPE_NUMERIC_STRING:
            case self::TYPE_PRINTABLE_STRING:
            case self::TYPE_TELETEX_STRING:
            case self::TYPE_VIDEOTEX_STRING:
            case self::TYPE_IA5_STRING:
            case self::TYPE_GRAPHIC_STRING:
            case self::TYPE_VISIBLE_STRING:
            case self::TYPE_GENERAL_STRING:
            case self::TYPE_UNIVERSAL_STRING:
            case self::TYPE_UTF8_STRING:
            case self::TYPE_BMP_STRING:
                return $decoded['content'];
            case self::TYPE_INTEGER:
            case self::TYPE_ENUMERATED:
                $temp = $decoded['content'];
                if (isset($mapping['implicit'])) {
                    $temp = new BigInteger($decoded['content'], -256);
                }
                if (isset($mapping['mapping'])) {
                    $temp = (int) $temp->toString();
                    return isset($mapping['mapping'][$temp]) ? $mapping['mapping'][$temp] : false;
                }
                return $temp;
        }
    }
    /**
    * DER-decode the length
    *
    * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4.  See
    {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
    *
    * @access public
    * @param string $string
    * @return int
    */
    public static function decodeLength(&$string)
    {
        $length = ord(Strings::shift($string));
        if ($length & 0x80) {
            // definite length, long form
            $length &= 0x7f;
            $temp = Strings::shift($string, $length);
            list(, $length) = unpack('N', \Phabel\Target\Php80\Polyfill::substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
        }
        return $length;
    }
    /**
    * ASN.1 Encode
    *
    * DER-encodes an ASN.1 semantic mapping ($mapping).  Some libraries would probably call this function
    an ASN.1 compiler.
    *
    * "Special" mappings can be applied via $special.
    *
    * @param (Element | string | array) $source
    * @param array $mapping
    * @param array $special
    * @return string
    * @access public
    */
    public static function encodeDER($source, $mapping, $special = [])
    {
        self::$location = [];
        return self::encode_der($source, $mapping, null, $special);
    }
    /**
     * ASN.1 Encode (Helper function)
     *
     * @param (Element | string | array) $source
     * @param array $mapping
     * @param int $idx
     * @param array $special
     * @return string
     * @access private
     */
    private static function encode_der($source, $mapping, $idx = null, $special = [])
    {
        if ($source instanceof Element) {
            return $source->element;
        }
        // do not encode (implicitly optional) fields with value set to default
        if (isset($mapping['default']) && $source === $mapping['default']) {
            return '';
        }
        if (isset($idx)) {
            if (isset($special[$idx])) {
                $source = $special[$idx]($source);
            }
            self::$location[] = $idx;
        }
        $tag = $mapping['type'];
        switch ($tag) {
            case self::TYPE_SET:
            // Children order is not important, thus process in sequence.
            case self::TYPE_SEQUENCE:
                $tag |= 0x20;
                // set the constructed bit
                // ignore the min and max
                if (isset($mapping['min']) && isset($mapping['max'])) {
                    $value = [];
                    $child = $mapping['children'];
                    foreach ($source as $content) {
                        $temp = self::encode_der($content, $child, null, $special);
                        if ($temp === false) {
                            return false;
                        }
                        $value[] = $temp;
                    }
                    /* "The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared
                                            as octet strings with the shorter components being padded at their trailing end with 0-octets.
                                            NOTE - The padding octets are for comparison purposes only and do not appear in the encodings."
                    
                                           -- sec 11.6 of http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf  */
                    if ($mapping['type'] == self::TYPE_SET) {
                        sort($value);
                    }
                    $value = implode('', $value);
                    break;
                }
                $value = '';
                foreach ($mapping['children'] as $key => $child) {
                    if (!array_key_exists($key, $source)) {
                        if (!isset($child['optional'])) {
                            return false;
                        }
                        continue;
                    }
                    $temp = self::encode_der($source[$key], $child, $key, $special);
                    if ($temp === false) {
                        return false;
                    }
                    // An empty child encoding means it has been optimized out.
                    // Else we should have at least one tag byte.
                    if ($temp === '') {
                        continue;
                    }
                    // if isset($child['constant']) is true then isset($child['optional']) should be true as well
                    if (isset($child['constant'])) {
                        /*
                          From X.680-0207.pdf#page=58 (30.6):
                        
                          "The tagging construction specifies explicit tagging if any of the following holds:
                           ...
                           c) the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or
                           AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or
                           an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)."
                        */
                        if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
                            $subtag = chr(self::CLASS_CONTEXT_SPECIFIC << 6 | 0x20 | $child['constant']);
                            $temp = $subtag . self::encodeLength(strlen($temp)) . $temp;
                        } else {
                            $subtag = chr(self::CLASS_CONTEXT_SPECIFIC << 6 | ord($temp[0]) & 0x20 | $child['constant']);
                            $temp = $subtag . \Phabel\Target\Php80\Polyfill::substr($temp, 1);
                        }
                    }
                    $value .= $temp;
                }
                break;
            case self::TYPE_CHOICE:
                $temp = false;
                foreach ($mapping['children'] as $key => $child) {
                    if (!isset($source[$key])) {
                        continue;
                    }
                    $temp = self::encode_der($source[$key], $child, $key, $special);
                    if ($temp === false) {
                        return false;
                    }
                    // An empty child encoding means it has been optimized out.
                    // Else we should have at least one tag byte.
                    if ($temp === '') {
                        continue;
                    }
                    $tag = ord($temp[0]);
                    // if isset($child['constant']) is true then isset($child['optional']) should be true as well
                    if (isset($child['constant'])) {
                        if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
                            $subtag = chr(self::CLASS_CONTEXT_SPECIFIC << 6 | 0x20 | $child['constant']);
                            $temp = $subtag . self::encodeLength(strlen($temp)) . $temp;
                        } else {
                            $subtag = chr(self::CLASS_CONTEXT_SPECIFIC << 6 | ord($temp[0]) & 0x20 | $child['constant']);
                            $temp = $subtag . \Phabel\Target\Php80\Polyfill::substr($temp, 1);
                        }
                    }
                }
                if (isset($idx)) {
                    array_pop(self::$location);
                }
                if ($temp && isset($mapping['cast'])) {
                    $temp[0] = chr($mapping['class'] << 6 | $tag & 0x20 | $mapping['cast']);
                }
                return $temp;
            case self::TYPE_INTEGER:
            case self::TYPE_ENUMERATED:
                if (!isset($mapping['mapping'])) {
                    if (is_numeric($source)) {
                        $source = new BigInteger($source);
                    }
                    $value = $source->toBytes(true);
                } else {
                    $value = array_search($source, $mapping['mapping']);
                    if ($value === false) {
                        return false;
                    }
                    $value = new BigInteger($value);
                    $value = $value->toBytes(true);
                }
                if (!strlen($value)) {
                    $value = chr(0);
                }
                break;
            case self::TYPE_UTC_TIME:
            case self::TYPE_GENERALIZED_TIME:
                $format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
                $format .= 'mdHis';
                // if $source does _not_ include timezone information within it then assume that the timezone is GMT
                $date = new DateTime($source, new DateTimeZone('GMT'));
                // if $source _does_ include timezone information within it then convert the time to GMT
                $date->setTimezone(new DateTimeZone('GMT'));
                $value = $date->format($format) . 'Z';
                break;
            case self::TYPE_BIT_STRING:
                if (isset($mapping['mapping'])) {
                    $bits = array_fill(0, count($mapping['mapping']), 0);
                    $size = 0;
                    for ($i = 0; $i < count($mapping['mapping']); $i++) {
                        if (in_array($mapping['mapping'][$i], $source)) {
                            $bits[$i] = 1;
                            $size = $i;
                        }
                    }
                    if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) {
                        $size = $mapping['min'] - 1;
                    }
                    $offset = 8 - ($size + 1 & 7);
                    $offset = $offset !== 8 ? $offset : 0;
                    $value = chr($offset);
                    for ($i = $size + 1; $i < count($mapping['mapping']); $i++) {
                        unset($bits[$i]);
                    }
                    $bits = implode('', array_pad($bits, $size + $offset + 1, 0));
                    $bytes = explode(' ', rtrim(chunk_split($bits, 8, ' ')));
                    foreach ($bytes as $byte) {
                        $value .= chr(bindec($byte));
                    }
                    break;
                }
            case self::TYPE_OCTET_STRING:
                /* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
                                   the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven.
                
                                   -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
                $value = $source;
                break;
            case self::TYPE_OBJECT_IDENTIFIER:
                $value = self::encodeOID($source);
                break;
            case self::TYPE_ANY:
                $loc = self::$location;
                if (isset($idx)) {
                    array_pop(self::$location);
                }
                switch (true) {
                    case !isset($source):
                        return self::encode_der(null, ['type' => self::TYPE_NULL] + $mapping, null, $special);
                    case is_int($source):
                    case $source instanceof BigInteger:
                        return self::encode_der($source, ['type' => self::TYPE_INTEGER] + $mapping, null, $special);
                    case is_float($source):
                        return self::encode_der($source, ['type' => self::TYPE_REAL] + $mapping, null, $special);
                    case is_bool($source):
                        return self::encode_der($source, ['type' => self::TYPE_BOOLEAN] + $mapping, null, $special);
                    case is_array($source) && count($source) == 1:
                        $typename = implode('', array_keys($source));
                        $outtype = array_search($typename, self::ANY_MAP, true);
                        if ($outtype !== false) {
                            return self::encode_der($source[$typename], ['type' => $outtype] + $mapping, null, $special);
                        }
                }
                $filters = self::$filters;
                foreach ($loc as $part) {
                    if (!isset($filters[$part])) {
                        $filters = false;
                        break;
                    }
                    $filters = $filters[$part];
                }
                if ($filters === false) {
                    throw new \RuntimeException('No filters defined for ' . implode('/', $loc));
                }
                return self::encode_der($source, $filters + $mapping, null, $special);
            case self::TYPE_NULL:
                $value = '';
                break;
            case self::TYPE_NUMERIC_STRING:
            case self::TYPE_TELETEX_STRING:
            case self::TYPE_PRINTABLE_STRING:
            case self::TYPE_UNIVERSAL_STRING:
            case self::TYPE_UTF8_STRING:
            case self::TYPE_BMP_STRING:
            case self::TYPE_IA5_STRING:
            case self::TYPE_VISIBLE_STRING:
            case self::TYPE_VIDEOTEX_STRING:
            case self::TYPE_GRAPHIC_STRING:
            case self::TYPE_GENERAL_STRING:
                $value = $source;
                break;
            case self::TYPE_BOOLEAN:
                $value = $source ? "\xff" : "\x00";
                break;
            default:
                throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', self::$location));
        }
        if (isset($idx)) {
            array_pop(self::$location);
        }
        if (isset($mapping['cast'])) {
            if (isset($mapping['explicit']) || $mapping['type'] == self::TYPE_CHOICE) {
                $value = chr($tag) . self::encodeLength(strlen($value)) . $value;
                $tag = $mapping['class'] << 6 | 0x20 | $mapping['cast'];
            } else {
                $tag = $mapping['class'] << 6 | ord($temp[0]) & 0x20 | $mapping['cast'];
            }
        }
        return chr($tag) . self::encodeLength(strlen($value)) . $value;
    }
    /**
     * BER-decode the OID
     *
     * Called by _decode_ber()
     *
     * @access public
     * @param string $content
     * @return string
     */
    public static function decodeOID($content)
    {
        static $eighty;
        if (!$eighty) {
            $eighty = new BigInteger(80);
        }
        $oid = [];
        $pos = 0;
        $len = strlen($content);
        if (ord($content[$len - 1]) & 0x80) {
            return false;
        }
        $n = new BigInteger();
        while ($pos < $len) {
            $temp = ord($content[$pos++]);
            $n = $n->bitwise_leftShift(7);
            $n = $n->bitwise_or(new BigInteger($temp & 0x7f));
            if (~$temp & 0x80) {
                $oid[] = $n;
                $n = new BigInteger();
            }
        }
        $part1 = array_shift($oid);
        $first = floor(ord($content[0]) / 40);
        /*
          "This packing of the first two object identifier components recognizes that only three values are allocated from the root
           node, and at most 39 subsequent values from nodes reached by X = 0 and X = 1."
        
          -- https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=22
        */
        if ($first <= 2) {
            // ie. 0 <= ord($content[0]) < 120 (0x78)
            array_unshift($oid, ord($content[0]) % 40);
            array_unshift($oid, $first);
        } else {
            array_unshift($oid, $part1->subtract($eighty));
            array_unshift($oid, 2);
        }
        return implode('.', $oid);
    }
    /**
     * DER-encode the OID
     *
     * Called by _encode_der()
     *
     * @access public
     * @param string $source
     * @return string
     */
    public static function encodeOID($source)
    {
        static $mask, $zero, $forty;
        if (!$mask) {
            $mask = new BigInteger(0x7f);
            $zero = new BigInteger();
            $forty = new BigInteger(40);
        }
        if (!preg_match('#(?:\\d+\\.)+#', $source)) {
            $oid = isset(self::$reverseOIDs[$source]) ? self::$reverseOIDs[$source] : false;
        } else {
            $oid = $source;
        }
        if ($oid === false) {
            throw new \RuntimeException('Invalid OID');
        }
        $parts = explode('.', $oid);
        $part1 = array_shift($parts);
        $part2 = array_shift($parts);
        $first = new BigInteger($part1);
        $first = $first->multiply($forty);
        $first = $first->add(new BigInteger($part2));
        array_unshift($parts, $first->toString());
        $value = '';
        foreach ($parts as $part) {
            if (!$part) {
                $temp = "\x00";
            } else {
                $temp = '';
                $part = new BigInteger($part);
                while (!$part->equals($zero)) {
                    $submask = $part->bitwise_and($mask);
                    $submask->setPrecision(8);
                    $temp = (chr(0x80) | $submask->toBytes()) . $temp;
                    $part = $part->bitwise_rightShift(7);
                }
                $temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7f);
            }
            $value .= $temp;
        }
        return $value;
    }
    /**
     * BER-decode the time
     *
     * Called by _decode_ber() and in the case of implicit tags asn1map().
     *
     * @access private
     * @param string $content
     * @param int $tag
     * @return string
     */
    private static function decodeTime($content, $tag)
    {
        /* UTCTime:
                   http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
                   http://www.obj-sys.com/asn1tutorial/node15.html
        
                   GeneralizedTime:
                   http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
                   http://www.obj-sys.com/asn1tutorial/node14.html */
        $format = 'YmdHis';
        if ($tag == self::TYPE_UTC_TIME) {
            // https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds
            // element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the
            // browsers parse it phpseclib ought to too
            if (preg_match('#^(\\d{10})(Z|[+-]\\d{4})$#', $content, $matches)) {
                $content = $matches[1] . '00' . $matches[2];
            }
            $prefix = \Phabel\Target\Php80\Polyfill::substr($content, 0, 2) >= 50 ? '19' : '20';
            $content = $prefix . $content;
        } elseif (strpos($content, '.') !== false) {
            $format .= '.u';
        }
        if ($content[strlen($content) - 1] == 'Z') {
            $content = \Phabel\Target\Php80\Polyfill::substr($content, 0, -1) . '+0000';
        }
        if (strpos($content, '-') !== false || strpos($content, '+') !== false) {
            $format .= 'O';
        }
        // error supression isn't necessary as of PHP 7.0:
        // http://php.net/manual/en/migration70.other-changes.php
        return @DateTime::createFromFormat($format, $content);
    }
    /**
     * Set the time format
     *
     * Sets the time / date format for asn1map().
     *
     * @access public
     * @param string $format
     */
    public static function setTimeFormat($format)
    {
        self::$format = $format;
    }
    /**
    * Load OIDs
    *
    * Load the relevant OIDs for a particular ASN.1 semantic mapping.
    Previously loaded OIDs are retained.
    *
    * @access public
    * @param array $oids
    */
    public static function loadOIDs($oids)
    {
        self::$reverseOIDs += $oids;
        self::$oids = array_flip(self::$reverseOIDs);
    }
    /**
    * Set filters
    *
    * See \phpseclib3\File\X509, etc, for an example.
    Previously loaded filters are not retained.
    *
    * @access public
    * @param array $filters
    */
    public static function setFilters($filters)
    {
        self::$filters = $filters;
    }
    /**
    * String type conversion
    *
    * This is a lazy conversion, dealing only with character size.
    No real conversion table is used.
    *
    * @param string $in
    * @param int $from
    * @param int $to
    * @return string
    * @access public
    */
    public static function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING)
    {
        // isset(self::STRING_TYPE_SIZE[$from] returns a fatal error on PHP 5.6
        if (!array_key_exists($from, self::STRING_TYPE_SIZE) || !array_key_exists($to, self::STRING_TYPE_SIZE)) {
            return false;
        }
        $insize = self::STRING_TYPE_SIZE[$from];
        $outsize = self::STRING_TYPE_SIZE[$to];
        $inlength = strlen($in);
        $out = '';
        for ($i = 0; $i < $inlength;) {
            if ($inlength - $i < $insize) {
                return false;
            }
            // Get an input character as a 32-bit value.
            $c = ord($in[$i++]);
            switch (true) {
                case $insize == 4:
                    $c = $c << 8 | ord($in[$i++]);
                    $c = $c << 8 | ord($in[$i++]);
                case $insize == 2:
                    $c = $c << 8 | ord($in[$i++]);
                case $insize == 1:
                    break;
                case ($c & 0x80) == 0x0:
                    break;
                case ($c & 0x40) == 0x0:
                    return false;
                default:
                    $bit = 6;
                    do {
                        if ($bit > 25 || $i >= $inlength || (ord($in[$i]) & 0xc0) != 0x80) {
                            return false;
                        }
                        $c = $c << 6 | ord($in[$i++]) & 0x3f;
                        $bit += 5;
                        $mask = 1 << $bit;
                    } while ($c & $bit);
                    $c &= $mask - 1;
                    break;
            }
            // Convert and append the character to output string.
            $v = '';
            switch (true) {
                case $outsize == 4:
                    $v .= chr($c & 0xff);
                    $c >>= 8;
                    $v .= chr($c & 0xff);
                    $c >>= 8;
                case $outsize == 2:
                    $v .= chr($c & 0xff);
                    $c >>= 8;
                case $outsize == 1:
                    $v .= chr($c & 0xff);
                    $c >>= 8;
                    if ($c) {
                        return false;
                    }
                    break;
                case ($c & 0x80000000) != 0:
                    return false;
                case $c >= 0x4000000:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0x4000000;
                case $c >= 0x200000:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0x200000;
                case $c >= 0x10000:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0x10000;
                case $c >= 0x800:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0x800;
                case $c >= 0x80:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0xc0;
                default:
                    $v .= chr($c);
                    break;
            }
            $out .= strrev($v);
        }
        return $out;
    }
    /**
     * Extract raw BER from Base64 encoding
     *
     * @access private
     * @param string $str
     * @return string
     */
    public static function extractBER($str)
    {
        /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them
         * above and beyond the ceritificate.
         * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line:
         *
         * Bag Attributes
         *     localKeyID: 01 00 00 00
         * subject=/O=organization/OU=org unit/CN=common name
         * issuer=/O=organization/CN=common name
         */
        if (strlen($str) > ini_get('pcre.backtrack_limit')) {
            $temp = $str;
        } else {
            $temp = preg_replace('#.*?^-+[^-]+-+[\\r\\n ]*$#ms', '', $str, 1);
            $temp = preg_replace('#-+END.*[\\r\\n ]*.*#ms', '', $temp, 1);
        }
        // remove new lines
        $temp = str_replace(["\r", "\n", ' '], '', $temp);
        // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
        $temp = preg_replace('#^-+[^-]+-+|-+[^-]+-+$#', '', $temp);
        $temp = preg_match('#^[a-zA-Z\\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false;
        return $temp != false ? $temp : $str;
    }
    /**
    * DER-encode the length
    *
    * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4.  See
    {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
    *
    * @access public
    * @param int $length
    * @return string
    */
    public static function encodeLength($length)
    {
        if ($length <= 0x7f) {
            return chr($length);
        }
        $temp = ltrim(pack('N', $length), chr(0));
        return pack('Ca*', 0x80 | strlen($temp), $temp);
    }
    /**
    * Returns the OID corresponding to a name
    *
    * What's returned in the associative array returned by loadX509() (or load*()) is either a name or an OID if
    no OID to name mapping is available. The problem with this is that what may be an unmapped OID in one version
    of phpseclib may not be unmapped in the next version, so apps that are looking at this OID may not be able
    to work from version to version.
    *
    * This method will return the OID if a name is passed to it and if no mapping is avialable it'll assume that
    what's being passed to it already is an OID and return that instead. A few examples.
    *
    * getOID('2.16.840.1.101.3.4.2.1') == '2.16.840.1.101.3.4.2.1'
    getOID('id-sha256') == '2.16.840.1.101.3.4.2.1'
    getOID('zzz') == 'zzz'
    *
    * @access public
    * @param string $name
    * @return string
    */
    public static function getOID($name)
    {
        return isset(self::$reverseOIDs[$name]) ? self::$reverseOIDs[$name] : $name;
    }
}<?php

/**
 * ASN.1 Raw Element
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2012 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1;

/**
 * ASN.1 Raw Element
 *
 * An ASN.1 ANY mapping will return an ASN1\Element object. Use of this object
 * will also bypass the normal encoding rules in ASN1::encodeDER()
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Element
{
    /**
     * Raw element value
     *
     * @var string
     * @access private
     */
    public $element;
    /**
     * Constructor
     *
     * @param string $encoded
     * @return \phpseclib3\File\ASN1\Element
     * @access public
     */
    public function __construct($encoded)
    {
        $this->element = $encoded;
    }
}<?php

/**
 * RSAPublicKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RSAPublicKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RSAPublicKey
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['modulus' => ['type' => ASN1::TYPE_INTEGER], 'publicExponent' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * DisplayText
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DisplayText
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DisplayText
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['ia5String' => ['type' => ASN1::TYPE_IA5_STRING], 'visibleString' => ['type' => ASN1::TYPE_VISIBLE_STRING], 'bmpString' => ['type' => ASN1::TYPE_BMP_STRING], 'utf8String' => ['type' => ASN1::TYPE_UTF8_STRING]]];
}<?php

/**
 * DirectoryString
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DirectoryString
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DirectoryString
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['teletexString' => ['type' => ASN1::TYPE_TELETEX_STRING], 'printableString' => ['type' => ASN1::TYPE_PRINTABLE_STRING], 'universalString' => ['type' => ASN1::TYPE_UNIVERSAL_STRING], 'utf8String' => ['type' => ASN1::TYPE_UTF8_STRING], 'bmpString' => ['type' => ASN1::TYPE_BMP_STRING]]];
}<?php

/**
 * PKCS9String 
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PKCS9String 
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS9String
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['ia5String' => ['type' => ASN1::TYPE_IA5_STRING], 'directoryString' => DirectoryString::MAP]];
}<?php

/**
 * PolicyInformation
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PolicyInformation
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PolicyInformation
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['policyIdentifier' => CertPolicyId::MAP, 'policyQualifiers' => ['type' => ASN1::TYPE_SEQUENCE, 'min' => 0, 'max' => -1, 'optional' => true, 'children' => PolicyQualifierInfo::MAP]]];
}<?php

/**
 * ExtKeyUsageSyntax
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ExtKeyUsageSyntax
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ExtKeyUsageSyntax
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => KeyPurposeId::MAP];
}<?php

/**
 * BasicConstraints
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BasicConstraints
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BasicConstraints
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['cA' => ['type' => ASN1::TYPE_BOOLEAN, 'optional' => true, 'default' => false], 'pathLenConstraint' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true]]];
}<?php

/**
 * CPSuri
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CPSuri
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CPSuri
{
    const MAP = ['type' => ASN1::TYPE_IA5_STRING];
}<?php

/**
 * EncryptedPrivateKeyInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * EncryptedPrivateKeyInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EncryptedPrivateKeyInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['encryptionAlgorithm' => AlgorithmIdentifier::MAP, 'encryptedData' => EncryptedData::MAP]];
}<?php

/**
 * CRLDistributionPoints
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CRLDistributionPoints
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CRLDistributionPoints
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => DistributionPoint::MAP];
}<?php

/**
 * OtherPrimeInfos
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OtherPrimeInfos
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OtherPrimeInfos
{
    // version must be multi if otherPrimeInfos present
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => OtherPrimeInfo::MAP];
}<?php

/**
 * PBKDF2params
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PBKDF2params
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PBKDF2params
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        // technically, this is a CHOICE in RFC2898 but the other "choice" is, currently, more of a placeholder
        // in the RFC
        'salt' => ['type' => ASN1::TYPE_OCTET_STRING],
        'iterationCount' => ['type' => ASN1::TYPE_INTEGER],
        'keyLength' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true],
        'prf' => AlgorithmIdentifier::MAP + ['optional' => true],
    ]];
}<?php

/**
 * IssuerAltName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * IssuerAltName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class IssuerAltName
{
    const MAP = GeneralNames::MAP;
}<?php

/**
 * Attributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Attributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Attributes
{
    const MAP = ['type' => ASN1::TYPE_SET, 'min' => 1, 'max' => -1, 'children' => Attribute::MAP];
}<?php

/**
 * SubjectDirectoryAttributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SubjectDirectoryAttributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SubjectDirectoryAttributes
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => Attribute::MAP];
}<?php

/**
 * PublicKeyAndChallenge
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PublicKeyAndChallenge
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PublicKeyAndChallenge
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['spki' => SubjectPublicKeyInfo::MAP, 'challenge' => ['type' => ASN1::TYPE_IA5_STRING]]];
}<?php

/**
 * AccessDescription
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AccessDescription
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AccessDescription
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['accessMethod' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'accessLocation' => GeneralName::MAP]];
}<?php

/**
 * ExtensionAttribute
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ExtensionAttribute
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ExtensionAttribute
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['extension-attribute-type' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 0, 'optional' => true, 'implicit' => true], 'extension-attribute-value' => ['type' => ASN1::TYPE_ANY, 'constant' => 1, 'optional' => true, 'explicit' => true]]];
}<?php

/**
 * netscape_cert_type
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * netscape_cert_type
 *
 * mapping is from <http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html>
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class netscape_cert_type
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING, 'mapping' => ['SSLClient', 'SSLServer', 'Email', 'ObjectSigning', 'Reserved', 'SSLCA', 'EmailCA', 'ObjectSigningCA']];
}<?php

/**
 * CountryName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CountryName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CountryName
{
    const MAP = [
        'type' => ASN1::TYPE_CHOICE,
        // if class isn't present it's assumed to be \phpseclib3\File\ASN1::CLASS_UNIVERSAL or
        // (if constant is present) \phpseclib3\File\ASN1::CLASS_CONTEXT_SPECIFIC
        'class' => ASN1::CLASS_APPLICATION,
        'cast' => 1,
        'children' => ['x121-dcc-code' => ['type' => ASN1::TYPE_NUMERIC_STRING], 'iso-3166-alpha2-code' => ['type' => ASN1::TYPE_PRINTABLE_STRING]],
    ];
}<?php

/**
 * DSAPrivateKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DSAPrivateKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DSAPrivateKey
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER], 'p' => ['type' => ASN1::TYPE_INTEGER], 'q' => ['type' => ASN1::TYPE_INTEGER], 'g' => ['type' => ASN1::TYPE_INTEGER], 'y' => ['type' => ASN1::TYPE_INTEGER], 'x' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * BaseDistance
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BaseDistance
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BaseDistance
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * PrivateKeyInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PrivateKeyInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PrivateKeyInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['v1']], 'privateKeyAlgorithm' => AlgorithmIdentifier::MAP, 'privateKey' => PrivateKey::MAP, 'attributes' => ['constant' => 0, 'optional' => true, 'implicit' => true] + Attributes::MAP]];
}<?php

/**
 * Validity
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Validity
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Validity
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['notBefore' => Time::MAP, 'notAfter' => Time::MAP]];
}<?php

/**
 * BuiltInDomainDefinedAttribute
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BuiltInDomainDefinedAttribute
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BuiltInDomainDefinedAttribute
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['type' => ['type' => ASN1::TYPE_PRINTABLE_STRING], 'value' => ['type' => ASN1::TYPE_PRINTABLE_STRING]]];
}<?php

/**
 * Extension
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Extension
 *
 * A certificate using system MUST reject the certificate if it encounters
 * a critical extension it does not recognize; however, a non-critical
 * extension may be ignored if it is not recognized.
 *
 * http://tools.ietf.org/html/rfc5280#section-4.2
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Extension
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['extnId' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'critical' => ['type' => ASN1::TYPE_BOOLEAN, 'optional' => true, 'default' => false], 'extnValue' => ['type' => ASN1::TYPE_OCTET_STRING]]];
}<?php

/**
 * Curve
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Curve
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Curve
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['a' => FieldElement::MAP, 'b' => FieldElement::MAP, 'seed' => ['type' => ASN1::TYPE_BIT_STRING, 'optional' => true]]];
}<?php

/**
 * AttributeType
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AttributeType
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AttributeType
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * GeneralSubtree
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * GeneralSubtree
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class GeneralSubtree
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['base' => GeneralName::MAP, 'minimum' => ['constant' => 0, 'optional' => true, 'implicit' => true, 'default' => '0'] + BaseDistance::MAP, 'maximum' => ['constant' => 1, 'optional' => true, 'implicit' => true] + BaseDistance::MAP]];
}<?php

/**
 * RC2CBCParameter
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RC2CBCParameter
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RC2CBCParameter
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['rc2ParametersVersion' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true], 'iv' => ['type' => ASN1::TYPE_OCTET_STRING]]];
}<?php

/**
 * DSAPublicKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DSAPublicKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DSAPublicKey
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * SubjectAltName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SubjectAltName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SubjectAltName
{
    const MAP = GeneralNames::MAP;
}<?php

/**
 * NetworkAddress
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * NetworkAddress
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class NetworkAddress
{
    const MAP = ['type' => ASN1::TYPE_NUMERIC_STRING];
}<?php

/**
 * RevokedCertificate
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RevokedCertificate
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RevokedCertificate
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['userCertificate' => CertificateSerialNumber::MAP, 'revocationDate' => Time::MAP, 'crlEntryExtensions' => ['optional' => true] + Extensions::MAP]];
}<?php

/**
 * NoticeReference
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * NoticeReference
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class NoticeReference
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['organization' => DisplayText::MAP, 'noticeNumbers' => ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => 200, 'children' => ['type' => ASN1::TYPE_INTEGER]]]];
}<?php

/**
 * DistributionPointName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DistributionPointName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DistributionPointName
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['fullName' => ['constant' => 0, 'optional' => true, 'implicit' => true] + GeneralNames::MAP, 'nameRelativeToCRLIssuer' => ['constant' => 1, 'optional' => true, 'implicit' => true] + RelativeDistinguishedName::MAP]];
}<?php

/**
 * OneAsymmetricKey
 *
 * See https://tools.ietf.org/html/rfc5958
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OneAsymmetricKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OneAsymmetricKey
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['v1', 'v2']], 'privateKeyAlgorithm' => AlgorithmIdentifier::MAP, 'privateKey' => PrivateKey::MAP, 'attributes' => ['constant' => 0, 'optional' => true, 'implicit' => true] + Attributes::MAP, 'publicKey' => ['constant' => 1, 'optional' => true, 'implicit' => true] + PublicKey::MAP]];
}<?php

/**
 * OrganizationalUnitNames
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OrganizationalUnitNames
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OrganizationalUnitNames
{
    const MAP = [
        'type' => ASN1::TYPE_SEQUENCE,
        'min' => 1,
        'max' => 4,
        // ub-organizational-units
        'children' => ['type' => ASN1::TYPE_PRINTABLE_STRING],
    ];
}<?php

/**
 * DssSigValue
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DssSigValue
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DssSigValue
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['r' => ['type' => ASN1::TYPE_INTEGER], 's' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * PrivateDomainName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PrivateDomainName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PrivateDomainName
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['numeric' => ['type' => ASN1::TYPE_NUMERIC_STRING], 'printable' => ['type' => ASN1::TYPE_PRINTABLE_STRING]]];
}<?php

/**
 * Characteristic_two
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Characteristic_two
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Characteristic_two
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'm' => ['type' => ASN1::TYPE_INTEGER],
        // field size 2**m
        'basis' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER],
        'parameters' => ['type' => ASN1::TYPE_ANY, 'optional' => true],
    ]];
}<?php

/**
 * Attribute
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Attribute
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Attribute
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['type' => AttributeType::MAP, 'value' => ['type' => ASN1::TYPE_SET, 'min' => 1, 'max' => -1, 'children' => AttributeValue::MAP]]];
}<?php

/**
 * Prime_p
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Prime_p
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Prime_p
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * TBSCertList
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * TBSCertList
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class TBSCertList
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['v1', 'v2', 'v3'], 'optional' => true, 'default' => 'v2'], 'signature' => AlgorithmIdentifier::MAP, 'issuer' => Name::MAP, 'thisUpdate' => Time::MAP, 'nextUpdate' => ['optional' => true] + Time::MAP, 'revokedCertificates' => ['type' => ASN1::TYPE_SEQUENCE, 'optional' => true, 'min' => 0, 'max' => -1, 'children' => RevokedCertificate::MAP], 'crlExtensions' => ['constant' => 0, 'optional' => true, 'explicit' => true] + Extensions::MAP]];
}<?php

/**
 * PrivateKeyUsagePeriod
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PrivateKeyUsagePeriod
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PrivateKeyUsagePeriod
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['notBefore' => ['constant' => 0, 'optional' => true, 'implicit' => true, 'type' => ASN1::TYPE_GENERALIZED_TIME], 'notAfter' => ['constant' => 1, 'optional' => true, 'implicit' => true, 'type' => ASN1::TYPE_GENERALIZED_TIME]]];
}<?php

/**
 * Extensions
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Extensions
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Extensions
{
    const MAP = [
        'type' => ASN1::TYPE_SEQUENCE,
        'min' => 1,
        // technically, it's MAX, but we'll assume anything < 0 is MAX
        'max' => -1,
        // if 'children' isn't an array then 'min' and 'max' must be defined
        'children' => Extension::MAP,
    ];
}<?php

/**
 * CRLReason
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CRLReason
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CRLReason
{
    const MAP = ['type' => ASN1::TYPE_ENUMERATED, 'mapping' => [
        'unspecified',
        'keyCompromise',
        'cACompromise',
        'affiliationChanged',
        'superseded',
        'cessationOfOperation',
        'certificateHold',
        // Value 7 is not used.
        8 => 'removeFromCRL',
        'privilegeWithdrawn',
        'aACompromise',
    ]];
}<?php

/**
 * PublicKeyInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PublicKeyInfo
 *
 * this format is not formally defined anywhere but is none-the-less the form you
 * get when you do "openssl rsa -in private.pem -outform PEM -pubout"
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PublicKeyInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['publicKeyAlgorithm' => AlgorithmIdentifier::MAP, 'publicKey' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * SubjectPublicKeyInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SubjectPublicKeyInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SubjectPublicKeyInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['algorithm' => AlgorithmIdentifier::MAP, 'subjectPublicKey' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * Name
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Name
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Name
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['rdnSequence' => RDNSequence::MAP]];
}<?php

/**
 * AuthorityInfoAccessSyntax
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AuthorityInfoAccessSyntax
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AuthorityInfoAccessSyntax
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => AccessDescription::MAP];
}<?php

/**
 * KeyIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * KeyIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class KeyIdentifier
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * Trinomial
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Trinomial
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Trinomial
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * PrivateKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PrivateKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PrivateKey
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * CertificatePolicies
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificatePolicies
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificatePolicies
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => PolicyInformation::MAP];
}<?php

/**
 * KeyUsage
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * KeyUsage
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class KeyUsage
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING, 'mapping' => ['digitalSignature', 'nonRepudiation', 'keyEncipherment', 'dataEncipherment', 'keyAgreement', 'keyCertSign', 'cRLSign', 'encipherOnly', 'decipherOnly']];
}<?php

/**
 * netscape_comment
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * netscape_comment
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class netscape_comment
{
    const MAP = ['type' => ASN1::TYPE_IA5_STRING];
}<?php

/**
 * UserNotice
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * UserNotice
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class UserNotice
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['noticeRef' => ['optional' => true, 'implicit' => true] + NoticeReference::MAP, 'explicitText' => ['optional' => true, 'implicit' => true] + DisplayText::MAP]];
}<?php

/**
 * SignedPublicKeyAndChallenge
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SignedPublicKeyAndChallenge
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SignedPublicKeyAndChallenge
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['publicKeyAndChallenge' => PublicKeyAndChallenge::MAP, 'signatureAlgorithm' => AlgorithmIdentifier::MAP, 'signature' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * PersonalName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PersonalName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PersonalName
{
    const MAP = ['type' => ASN1::TYPE_SET, 'children' => ['surname' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 0, 'optional' => true, 'implicit' => true], 'given-name' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 1, 'optional' => true, 'implicit' => true], 'initials' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 2, 'optional' => true, 'implicit' => true], 'generation-qualifier' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 3, 'optional' => true, 'implicit' => true]]];
}<?php

/**
 * ECParameters
 *
 * From: https://tools.ietf.org/html/rfc5915
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ECParameters
 *
 *  ECParameters ::= CHOICE {
 *    namedCurve         OBJECT IDENTIFIER
 *    -- implicitCurve   NULL
 *    -- specifiedCurve  SpecifiedECDomain
 *  }
 *    -- implicitCurve and specifiedCurve MUST NOT be used in PKIX.
 *    -- Details for SpecifiedECDomain can be found in [X9.62].
 *    -- Any future additions to this CHOICE should be coordinated
 *    -- with ANSI X9.
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ECParameters
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['namedCurve' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'implicitCurve' => ['type' => ASN1::TYPE_NULL], 'specifiedCurve' => SpecifiedECDomain::MAP]];
}<?php

/**
 * RSASSA_PSS_params
 *
 * As defined in https://tools.ietf.org/html/rfc4055#section-3.1
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RSASSA_PSS_params
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RSASSA_PSS_params
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['hashAlgorithm' => ['constant' => 0, 'optional' => true, 'explicit' => true] + HashAlgorithm::MAP, 'maskGenAlgorithm' => ['constant' => 1, 'optional' => true, 'explicit' => true] + MaskGenAlgorithm::MAP, 'saltLength' => ['type' => ASN1::TYPE_INTEGER, 'constant' => 2, 'optional' => true, 'explicit' => true, 'default' => 20], 'trailerField' => ['type' => ASN1::TYPE_INTEGER, 'constant' => 3, 'optional' => true, 'explicit' => true, 'default' => 1]]];
}<?php

/**
 * GeneralName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * GeneralName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class GeneralName
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['otherName' => ['constant' => 0, 'optional' => true, 'implicit' => true] + AnotherName::MAP, 'rfc822Name' => ['type' => ASN1::TYPE_IA5_STRING, 'constant' => 1, 'optional' => true, 'implicit' => true], 'dNSName' => ['type' => ASN1::TYPE_IA5_STRING, 'constant' => 2, 'optional' => true, 'implicit' => true], 'x400Address' => ['constant' => 3, 'optional' => true, 'implicit' => true] + ORAddress::MAP, 'directoryName' => ['constant' => 4, 'optional' => true, 'explicit' => true] + Name::MAP, 'ediPartyName' => ['constant' => 5, 'optional' => true, 'implicit' => true] + EDIPartyName::MAP, 'uniformResourceIdentifier' => ['type' => ASN1::TYPE_IA5_STRING, 'constant' => 6, 'optional' => true, 'implicit' => true], 'iPAddress' => ['type' => ASN1::TYPE_OCTET_STRING, 'constant' => 7, 'optional' => true, 'implicit' => true], 'registeredID' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER, 'constant' => 8, 'optional' => true, 'implicit' => true]]];
}<?php

/**
 * HoldInstructionCode
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * HoldInstructionCode
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class HoldInstructionCode
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * Pentanomial
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Pentanomial
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Pentanomial
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'k1' => ['type' => ASN1::TYPE_INTEGER],
        // k1 > 0
        'k2' => ['type' => ASN1::TYPE_INTEGER],
        // k2 > k1
        'k3' => ['type' => ASN1::TYPE_INTEGER],
    ]];
}<?php

/**
 * DistributionPoint
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DistributionPoint
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DistributionPoint
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['distributionPoint' => ['constant' => 0, 'optional' => true, 'explicit' => true] + DistributionPointName::MAP, 'reasons' => ['constant' => 1, 'optional' => true, 'implicit' => true] + ReasonFlags::MAP, 'cRLIssuer' => ['constant' => 2, 'optional' => true, 'implicit' => true] + GeneralNames::MAP]];
}<?php

/**
 * UniqueIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * UniqueIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class UniqueIdentifier
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING];
}<?php

/**
 * TerminalIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * TerminalIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class TerminalIdentifier
{
    const MAP = ['type' => ASN1::TYPE_PRINTABLE_STRING];
}<?php

/**
 * AnotherName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AnotherName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AnotherName
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['type-id' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'value' => ['type' => ASN1::TYPE_ANY, 'constant' => 0, 'optional' => true, 'explicit' => true]]];
}<?php

/**
 * CertificateSerialNumber
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificateSerialNumber
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificateSerialNumber
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * RelativeDistinguishedName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RelativeDistinguishedName
 *
 * In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare,
 * but they can be useful at times when either there is no unique attribute in the entry or you
 * want to ensure that the entry's DN contains some useful identifying information.
 *
 * - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RelativeDistinguishedName
{
    const MAP = ['type' => ASN1::TYPE_SET, 'min' => 1, 'max' => -1, 'children' => AttributeTypeAndValue::MAP];
}<?php

/**
 * OrganizationName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OrganizationName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OrganizationName
{
    const MAP = ['type' => ASN1::TYPE_PRINTABLE_STRING];
}<?php

/**
 * RSAPrivateKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RSAPrivateKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RSAPrivateKey
{
    // version must be multi if otherPrimeInfos present
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['two-prime', 'multi']],
        'modulus' => ['type' => ASN1::TYPE_INTEGER],
        // n
        'publicExponent' => ['type' => ASN1::TYPE_INTEGER],
        // e
        'privateExponent' => ['type' => ASN1::TYPE_INTEGER],
        // d
        'prime1' => ['type' => ASN1::TYPE_INTEGER],
        // p
        'prime2' => ['type' => ASN1::TYPE_INTEGER],
        // q
        'exponent1' => ['type' => ASN1::TYPE_INTEGER],
        // d mod (p-1)
        'exponent2' => ['type' => ASN1::TYPE_INTEGER],
        // d mod (q-1)
        'coefficient' => ['type' => ASN1::TYPE_INTEGER],
        // (inverse of q) mod p
        'otherPrimeInfos' => OtherPrimeInfos::MAP + ['optional' => true],
    ]];
}<?php

/**
 * AlgorithmIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AlgorithmIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AlgorithmIdentifier
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['algorithm' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'parameters' => ['type' => ASN1::TYPE_ANY, 'optional' => true]]];
}<?php

/**
 * BuiltInStandardAttributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BuiltInStandardAttributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BuiltInStandardAttributes
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['country-name' => ['optional' => true] + CountryName::MAP, 'administration-domain-name' => ['optional' => true] + AdministrationDomainName::MAP, 'network-address' => ['constant' => 0, 'optional' => true, 'implicit' => true] + NetworkAddress::MAP, 'terminal-identifier' => ['constant' => 1, 'optional' => true, 'implicit' => true] + TerminalIdentifier::MAP, 'private-domain-name' => ['constant' => 2, 'optional' => true, 'explicit' => true] + PrivateDomainName::MAP, 'organization-name' => ['constant' => 3, 'optional' => true, 'implicit' => true] + OrganizationName::MAP, 'numeric-user-identifier' => ['constant' => 4, 'optional' => true, 'implicit' => true] + NumericUserIdentifier::MAP, 'personal-name' => ['constant' => 5, 'optional' => true, 'implicit' => true] + PersonalName::MAP, 'organizational-unit-names' => ['constant' => 6, 'optional' => true, 'implicit' => true] + OrganizationalUnitNames::MAP]];
}<?php

/**
 * PublicKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PublicKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PublicKey
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING];
}<?php

/**
 * DSAParams
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DSAParams
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DSAParams
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['p' => ['type' => ASN1::TYPE_INTEGER], 'q' => ['type' => ASN1::TYPE_INTEGER], 'g' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * CRLNumber
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CRLNumber
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CRLNumber
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * ORAddress
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ORAddress
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ORAddress
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['built-in-standard-attributes' => BuiltInStandardAttributes::MAP, 'built-in-domain-defined-attributes' => ['optional' => true] + BuiltInDomainDefinedAttributes::MAP, 'extension-attributes' => ['optional' => true] + ExtensionAttributes::MAP]];
}<?php

/**
 * AdministrationDomainName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AdministrationDomainName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AdministrationDomainName
{
    const MAP = [
        'type' => ASN1::TYPE_CHOICE,
        // if class isn't present it's assumed to be \phpseclib3\File\ASN1::CLASS_UNIVERSAL or
        // (if constant is present) \phpseclib3\File\ASN1::CLASS_CONTEXT_SPECIFIC
        'class' => ASN1::CLASS_APPLICATION,
        'cast' => 2,
        'children' => ['numeric' => ['type' => ASN1::TYPE_NUMERIC_STRING], 'printable' => ['type' => ASN1::TYPE_PRINTABLE_STRING]],
    ];
}<?php

/**
 * ECPoint
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ECPoint
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ECPoint
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * ExtensionAttributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ExtensionAttributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ExtensionAttributes
{
    const MAP = [
        'type' => ASN1::TYPE_SET,
        'min' => 1,
        'max' => 256,
        // ub-extension-attributes
        'children' => ExtensionAttribute::MAP,
    ];
}<?php

/**
 * CertPolicyId
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertPolicyId
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertPolicyId
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * AuthorityKeyIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AuthorityKeyIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AuthorityKeyIdentifier
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['keyIdentifier' => ['constant' => 0, 'optional' => true, 'implicit' => true] + KeyIdentifier::MAP, 'authorityCertIssuer' => ['constant' => 1, 'optional' => true, 'implicit' => true] + GeneralNames::MAP, 'authorityCertSerialNumber' => ['constant' => 2, 'optional' => true, 'implicit' => true] + CertificateSerialNumber::MAP]];
}<?php

/**
 * SubjectInfoAccessSyntax
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SubjectInfoAccessSyntax
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SubjectInfoAccessSyntax
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => AccessDescription::MAP];
}<?php

/**
 * GeneralSubtrees
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * GeneralSubtrees
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class GeneralSubtrees
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => GeneralSubtree::MAP];
}<?php

/**
 * netscape_ca_policy_url
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * netscape_ca_policy_url
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class netscape_ca_policy_url
{
    const MAP = ['type' => ASN1::TYPE_IA5_STRING];
}<?php

/**
 * NumericUserIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * NumericUserIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class NumericUserIdentifier
{
    const MAP = ['type' => ASN1::TYPE_NUMERIC_STRING];
}<?php

/**
 * CertificationRequest
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificationRequest
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificationRequest
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['certificationRequestInfo' => CertificationRequestInfo::MAP, 'signatureAlgorithm' => AlgorithmIdentifier::MAP, 'signature' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * PolicyQualifierInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PolicyQualifierInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PolicyQualifierInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['policyQualifierId' => PolicyQualifierId::MAP, 'qualifier' => ['type' => ASN1::TYPE_ANY]]];
}<?php

/**
 * IssuingDistributionPoint
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * IssuingDistributionPoint
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class IssuingDistributionPoint
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['distributionPoint' => ['constant' => 0, 'optional' => true, 'explicit' => true] + DistributionPointName::MAP, 'onlyContainsUserCerts' => ['type' => ASN1::TYPE_BOOLEAN, 'constant' => 1, 'optional' => true, 'default' => false, 'implicit' => true], 'onlyContainsCACerts' => ['type' => ASN1::TYPE_BOOLEAN, 'constant' => 2, 'optional' => true, 'default' => false, 'implicit' => true], 'onlySomeReasons' => ['constant' => 3, 'optional' => true, 'implicit' => true] + ReasonFlags::MAP, 'indirectCRL' => ['type' => ASN1::TYPE_BOOLEAN, 'constant' => 4, 'optional' => true, 'default' => false, 'implicit' => true], 'onlyContainsAttributeCerts' => ['type' => ASN1::TYPE_BOOLEAN, 'constant' => 5, 'optional' => true, 'default' => false, 'implicit' => true]]];
}<?php

/**
 * CertificateIssuer
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificateIssuer
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificateIssuer
{
    const MAP = GeneralNames::MAP;
}<?php

/**
 * EncryptedData
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * EncryptedData
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EncryptedData
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * PBMAC1params
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PBMAC1params
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PBMAC1params
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['keyDerivationFunc' => AlgorithmIdentifier::MAP, 'messageAuthScheme' => AlgorithmIdentifier::MAP]];
}<?php

/**
 * DigestInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DigestInfo
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DigestInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['digestAlgorithm' => AlgorithmIdentifier::MAP, 'digest' => ['type' => ASN1::TYPE_OCTET_STRING]]];
}<?php

/**
 * KeyPurposeId
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * KeyPurposeId
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class KeyPurposeId
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * HashAglorithm
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * HashAglorithm
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class HashAlgorithm
{
    const MAP = AlgorithmIdentifier::MAP;
}<?php

/**
 * FieldID
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * FieldID
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class FieldID
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['fieldType' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'parameters' => ['type' => ASN1::TYPE_ANY, 'optional' => true]]];
}<?php

/**
 * PolicyMappings
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PolicyMappings
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PolicyMappings
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['issuerDomainPolicy' => CertPolicyId::MAP, 'subjectDomainPolicy' => CertPolicyId::MAP]]];
}<?php

/**
 * RDNSequence
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RDNSequence
 *
 * In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare,
 * but they can be useful at times when either there is no unique attribute in the entry or you
 * want to ensure that the entry's DN contains some useful identifying information.
 *
 * - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RDNSequence
{
    const MAP = [
        'type' => ASN1::TYPE_SEQUENCE,
        // RDNSequence does not define a min or a max, which means it doesn't have one
        'min' => 0,
        'max' => -1,
        'children' => RelativeDistinguishedName::MAP,
    ];
}<?php

/**
 * TBSCertificate
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * TBSCertificate
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class TBSCertificate
{
    // assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm'])
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        // technically, default implies optional, but we'll define it as being optional, none-the-less, just to
        // reenforce that fact
        'version' => ['type' => ASN1::TYPE_INTEGER, 'constant' => 0, 'optional' => true, 'explicit' => true, 'mapping' => ['v1', 'v2', 'v3'], 'default' => 'v1'],
        'serialNumber' => CertificateSerialNumber::MAP,
        'signature' => AlgorithmIdentifier::MAP,
        'issuer' => Name::MAP,
        'validity' => Validity::MAP,
        'subject' => Name::MAP,
        'subjectPublicKeyInfo' => SubjectPublicKeyInfo::MAP,
        // implicit means that the T in the TLV structure is to be rewritten, regardless of the type
        'issuerUniqueID' => ['constant' => 1, 'optional' => true, 'implicit' => true] + UniqueIdentifier::MAP,
        'subjectUniqueID' => ['constant' => 2, 'optional' => true, 'implicit' => true] + UniqueIdentifier::MAP,
        // <http://tools.ietf.org/html/rfc2459#page-74> doesn't use the EXPLICIT keyword but if
        // it's not IMPLICIT, it's EXPLICIT
        'extensions' => ['constant' => 3, 'optional' => true, 'explicit' => true] + Extensions::MAP,
    ]];
}<?php

/**
 * CertificateList
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificateList
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificateList
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['tbsCertList' => TBSCertList::MAP, 'signatureAlgorithm' => AlgorithmIdentifier::MAP, 'signature' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * BuiltInDomainDefinedAttributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BuiltInDomainDefinedAttributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BuiltInDomainDefinedAttributes
{
    const MAP = [
        'type' => ASN1::TYPE_SEQUENCE,
        'min' => 1,
        'max' => 4,
        // ub-domain-defined-attributes
        'children' => BuiltInDomainDefinedAttribute::MAP,
    ];
}<?php

/**
 * PolicyQualifierId
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PolicyQualifierId
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PolicyQualifierId
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * FieldElement
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * FieldElement
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class FieldElement
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * MaskGenAglorithm
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * MaskGenAglorithm
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MaskGenAlgorithm
{
    const MAP = AlgorithmIdentifier::MAP;
}<?php

/**
 * SpecifiedECDomain
 *
 * From: http://www.secg.org/sec1-v2.pdf#page=109
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SpecifiedECDomain
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SpecifiedECDomain
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => [1 => 'ecdpVer1', 'ecdpVer2', 'ecdpVer3']], 'fieldID' => FieldID::MAP, 'curve' => Curve::MAP, 'base' => ECPoint::MAP, 'order' => ['type' => ASN1::TYPE_INTEGER], 'cofactor' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true], 'hash' => ['optional' => true] + HashAlgorithm::MAP]];
}<?php

/**
 * GeneralNames
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * GeneralNames
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class GeneralNames
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => GeneralName::MAP];
}<?php

/**
 * EDIPartyName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * EDIPartyName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EDIPartyName
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'nameAssigner' => ['constant' => 0, 'optional' => true, 'implicit' => true] + DirectoryString::MAP,
        // partyName is technically required but \phpseclib3\File\ASN1 doesn't currently support non-optional constants and
        // setting it to optional gets the job done in any event.
        'partyName' => ['constant' => 1, 'optional' => true, 'implicit' => true] + DirectoryString::MAP,
    ]];
}<?php

/**
 * AttributeValue
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AttributeValue
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AttributeValue
{
    const MAP = ['type' => ASN1::TYPE_ANY];
}<?php

/**
 * DHParameter
 *
 * From: https://www.teletrust.de/fileadmin/files/oid/oid_pkcs-3v1-4.pdf#page=6
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DHParameter
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DHParameter
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['prime' => ['type' => ASN1::TYPE_INTEGER], 'base' => ['type' => ASN1::TYPE_INTEGER], 'privateValueLength' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true]]];
}<?php

/**
 * NameConstraints
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * NameConstraints
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class NameConstraints
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['permittedSubtrees' => ['constant' => 0, 'optional' => true, 'implicit' => true] + GeneralSubtrees::MAP, 'excludedSubtrees' => ['constant' => 1, 'optional' => true, 'implicit' => true] + GeneralSubtrees::MAP]];
}<?php

/**
 * OtherPrimeInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OtherPrimeInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OtherPrimeInfo
{
    // version must be multi if otherPrimeInfos present
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'prime' => ['type' => ASN1::TYPE_INTEGER],
        // ri
        'exponent' => ['type' => ASN1::TYPE_INTEGER],
        // di
        'coefficient' => ['type' => ASN1::TYPE_INTEGER],
    ]];
}<?php

/**
 * AttributeTypeAndValue
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AttributeTypeAndValue
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AttributeTypeAndValue
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['type' => AttributeType::MAP, 'value' => AttributeValue::MAP]];
}<?php

/**
 * ReasonFlags
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ReasonFlags
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ReasonFlags
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING, 'mapping' => ['unused', 'keyCompromise', 'cACompromise', 'affiliationChanged', 'superseded', 'cessationOfOperation', 'certificateHold', 'privilegeWithdrawn', 'aACompromise']];
}<?php

/**
 * Certificate
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Certificate
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Certificate
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['tbsCertificate' => TBSCertificate::MAP, 'signatureAlgorithm' => AlgorithmIdentifier::MAP, 'signature' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * PostalAddress
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PostalAddress
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PostalAddress
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'optional' => true, 'min' => 1, 'max' => -1, 'children' => DirectoryString::MAP];
}<?php

/**
 * ECPrivateKey
 *
 * From: https://tools.ietf.org/html/rfc5915
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ECPrivateKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ECPrivateKey
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => [1 => 'ecPrivkeyVer1']], 'privateKey' => ['type' => ASN1::TYPE_OCTET_STRING], 'parameters' => ['constant' => 0, 'optional' => true, 'explicit' => true] + ECParameters::MAP, 'publicKey' => ['type' => ASN1::TYPE_BIT_STRING, 'constant' => 1, 'optional' => true, 'explicit' => true]]];
}<?php

/**
 * EcdsaSigValue
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * EcdsaSigValue
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EcdsaSigValue
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['r' => ['type' => ASN1::TYPE_INTEGER], 's' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * InvalidityDate
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * InvalidityDate
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class InvalidityDate
{
    const MAP = ['type' => ASN1::TYPE_GENERALIZED_TIME];
}<?php

/**
 * PBES2params
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PBES2params
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PBES2params
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['keyDerivationFunc' => AlgorithmIdentifier::MAP, 'encryptionScheme' => AlgorithmIdentifier::MAP]];
}<?php

/**
 * CertificationRequestInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificationRequestInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificationRequestInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['v1']], 'subject' => Name::MAP, 'subjectPKInfo' => SubjectPublicKeyInfo::MAP, 'attributes' => ['constant' => 0, 'optional' => true, 'implicit' => true] + Attributes::MAP]];
}<?php

/**
 * PBEParameter
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PBEParameter
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PBEParameter
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['salt' => ['type' => ASN1::TYPE_OCTET_STRING], 'iterationCount' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * Time
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Time
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Time
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['utcTime' => ['type' => ASN1::TYPE_UTC_TIME], 'generalTime' => ['type' => ASN1::TYPE_GENERALIZED_TIME]]];
}<?php

/**
 * Pure-PHP X.509 Parser
 *
 * PHP version 5
 *
 * Encode and decode X.509 certificates.
 *
 * The extensions are from {@link http://tools.ietf.org/html/rfc5280 RFC5280} and
 * {@link http://web.archive.org/web/19961027104704/http://www3.netscape.com/eng/security/cert-exts.html Netscape Certificate Extensions}.
 *
 * Note that loading an X.509 certificate and resaving it may invalidate the signature.  The reason being that the signature is based on a
 * portion of the certificate that contains optional parameters with default values.  ie. if the parameter isn't there the default value is
 * used.  Problem is, if the parameter is there and it just so happens to have the default value there are two ways that that parameter can
 * be encoded.  It can be encoded explicitly or left out all together.  This would effect the signature value and thus may invalidate the
 * the certificate all together unless the certificate is re-signed.
 *
 * @category  File
 * @package   X509
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2012 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File;

use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib3\Crypt\Common\PrivateKey;
use phpseclib3\Crypt\Common\PublicKey;
use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\File\ASN1\Element;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\PublicKeyLoader;
/**
 * Pure-PHP X.509 Parser
 *
 * @package X509
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class X509
{
    /**
     * Flag to only accept signatures signed by certificate authorities
     *
     * Not really used anymore but retained all the same to suppress E_NOTICEs from old installs
     *
     * @access public
     */
    const VALIDATE_SIGNATURE_BY_CA = 1;
    /**
     * Return internal array representation
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_ARRAY = 0;
    /**
     * Return string
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_STRING = 1;
    /**
     * Return ASN.1 name string
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_ASN1 = 2;
    /**
     * Return OpenSSL compatible array
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_OPENSSL = 3;
    /**
     * Return canonical ASN.1 RDNs string
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_CANON = 4;
    /**
     * Return name hash for file indexing
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_HASH = 5;
    /**
     * Save as PEM
     *
     * ie. a base64-encoded PEM with a header and a footer
     *
     * @access public
     * @see \phpseclib3\File\X509::saveX509()
     * @see \phpseclib3\File\X509::saveCSR()
     * @see \phpseclib3\File\X509::saveCRL()
     */
    const FORMAT_PEM = 0;
    /**
     * Save as DER
     *
     * @access public
     * @see \phpseclib3\File\X509::saveX509()
     * @see \phpseclib3\File\X509::saveCSR()
     * @see \phpseclib3\File\X509::saveCRL()
     */
    const FORMAT_DER = 1;
    /**
     * Save as a SPKAC
     *
     * @access public
     * @see \phpseclib3\File\X509::saveX509()
     * @see \phpseclib3\File\X509::saveCSR()
     * @see \phpseclib3\File\X509::saveCRL()
     *
     * Only works on CSRs. Not currently supported.
     */
    const FORMAT_SPKAC = 2;
    /**
     * Auto-detect the format
     *
     * Used only by the load*() functions
     *
     * @access public
     * @see \phpseclib3\File\X509::saveX509()
     * @see \phpseclib3\File\X509::saveCSR()
     * @see \phpseclib3\File\X509::saveCRL()
     */
    const FORMAT_AUTO_DETECT = 3;
    /**
     * Attribute value disposition.
     * If disposition is >= 0, this is the index of the target value.
     */
    const ATTR_ALL = -1;
    // All attribute values (array).
    const ATTR_APPEND = -2;
    // Add a value.
    const ATTR_REPLACE = -3;
    // Clear first, then add a value.
    /**
     * Distinguished Name
     *
     * @var array
     * @access private
     */
    private $dn;
    /**
     * Public key
     *
     * @var string
     * @access private
     */
    private $publicKey;
    /**
     * Private key
     *
     * @var string
     * @access private
     */
    private $privateKey;
    /**
     * Object identifiers for X.509 certificates
     *
     * @var array
     * @access private
     * @link http://en.wikipedia.org/wiki/Object_identifier
     */
    private $oids;
    /**
     * The certificate authorities
     *
     * @var array
     * @access private
     */
    private $CAs;
    /**
     * The currently loaded certificate
     *
     * @var array
     * @access private
     */
    private $currentCert;
    /**
     * The signature subject
     *
     * There's no guarantee \phpseclib3\File\X509 is going to re-encode an X.509 cert in the same way it was originally
     * encoded so we take save the portion of the original cert that the signature would have made for.
     *
     * @var string
     * @access private
     */
    private $signatureSubject;
    /**
     * Certificate Start Date
     *
     * @var string
     * @access private
     */
    private $startDate;
    /**
     * Certificate End Date
     *
     * @var string
     * @access private
     */
    private $endDate;
    /**
     * Serial Number
     *
     * @var string
     * @access private
     */
    private $serialNumber;
    /**
     * Key Identifier
     *
     * See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and
     * {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}.
     *
     * @var string
     * @access private
     */
    private $currentKeyIdentifier;
    /**
     * CA Flag
     *
     * @var bool
     * @access private
     */
    private $caFlag = false;
    /**
     * SPKAC Challenge
     *
     * @var string
     * @access private
     */
    private $challenge;
    /**
     * @var array
     * @access private
     */
    private $extensionValues = [];
    /**
     * OIDs loaded
     *
     * @var bool
     * @access private
     */
    private static $oidsLoaded = false;
    /**
     * Recursion Limit
     *
     * @var int
     * @access private
     */
    private static $recur_limit = 5;
    /**
     * URL fetch flag
     *
     * @var bool
     * @access private
     */
    private static $disable_url_fetch = false;
    /**
     * @var array
     * @access private
     */
    private static $extensions = [];
    /**
     * @var ?array
     * @access private
     */
    private $ipAddresses = null;
    /**
     * @var ?array
     * @access private
     */
    private $domains = null;
    /**
     * Default Constructor.
     *
     * @return \phpseclib3\File\X509
     * @access public
     */
    public function __construct()
    {
        // Explicitly Tagged Module, 1988 Syntax
        // http://tools.ietf.org/html/rfc5280#appendix-A.1
        if (!self::$oidsLoaded) {
            // OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2
            ASN1::loadOIDs([
                //'id-pkix' => '1.3.6.1.5.5.7',
                //'id-pe' => '1.3.6.1.5.5.7.1',
                //'id-qt' => '1.3.6.1.5.5.7.2',
                //'id-kp' => '1.3.6.1.5.5.7.3',
                //'id-ad' => '1.3.6.1.5.5.7.48',
                'id-qt-cps' => '1.3.6.1.5.5.7.2.1',
                'id-qt-unotice' => '1.3.6.1.5.5.7.2.2',
                'id-ad-ocsp' => '1.3.6.1.5.5.7.48.1',
                'id-ad-caIssuers' => '1.3.6.1.5.5.7.48.2',
                'id-ad-timeStamping' => '1.3.6.1.5.5.7.48.3',
                'id-ad-caRepository' => '1.3.6.1.5.5.7.48.5',
                //'id-at' => '2.5.4',
                'id-at-name' => '2.5.4.41',
                'id-at-surname' => '2.5.4.4',
                'id-at-givenName' => '2.5.4.42',
                'id-at-initials' => '2.5.4.43',
                'id-at-generationQualifier' => '2.5.4.44',
                'id-at-commonName' => '2.5.4.3',
                'id-at-localityName' => '2.5.4.7',
                'id-at-stateOrProvinceName' => '2.5.4.8',
                'id-at-organizationName' => '2.5.4.10',
                'id-at-organizationalUnitName' => '2.5.4.11',
                'id-at-title' => '2.5.4.12',
                'id-at-description' => '2.5.4.13',
                'id-at-dnQualifier' => '2.5.4.46',
                'id-at-countryName' => '2.5.4.6',
                'id-at-serialNumber' => '2.5.4.5',
                'id-at-pseudonym' => '2.5.4.65',
                'id-at-postalCode' => '2.5.4.17',
                'id-at-streetAddress' => '2.5.4.9',
                'id-at-uniqueIdentifier' => '2.5.4.45',
                'id-at-role' => '2.5.4.72',
                'id-at-postalAddress' => '2.5.4.16',
                //'id-domainComponent' => '0.9.2342.19200300.100.1.25',
                //'pkcs-9' => '1.2.840.113549.1.9',
                'pkcs-9-at-emailAddress' => '1.2.840.113549.1.9.1',
                //'id-ce' => '2.5.29',
                'id-ce-authorityKeyIdentifier' => '2.5.29.35',
                'id-ce-subjectKeyIdentifier' => '2.5.29.14',
                'id-ce-keyUsage' => '2.5.29.15',
                'id-ce-privateKeyUsagePeriod' => '2.5.29.16',
                'id-ce-certificatePolicies' => '2.5.29.32',
                //'anyPolicy' => '2.5.29.32.0',
                'id-ce-policyMappings' => '2.5.29.33',
                'id-ce-subjectAltName' => '2.5.29.17',
                'id-ce-issuerAltName' => '2.5.29.18',
                'id-ce-subjectDirectoryAttributes' => '2.5.29.9',
                'id-ce-basicConstraints' => '2.5.29.19',
                'id-ce-nameConstraints' => '2.5.29.30',
                'id-ce-policyConstraints' => '2.5.29.36',
                'id-ce-cRLDistributionPoints' => '2.5.29.31',
                'id-ce-extKeyUsage' => '2.5.29.37',
                //'anyExtendedKeyUsage' => '2.5.29.37.0',
                'id-kp-serverAuth' => '1.3.6.1.5.5.7.3.1',
                'id-kp-clientAuth' => '1.3.6.1.5.5.7.3.2',
                'id-kp-codeSigning' => '1.3.6.1.5.5.7.3.3',
                'id-kp-emailProtection' => '1.3.6.1.5.5.7.3.4',
                'id-kp-timeStamping' => '1.3.6.1.5.5.7.3.8',
                'id-kp-OCSPSigning' => '1.3.6.1.5.5.7.3.9',
                'id-ce-inhibitAnyPolicy' => '2.5.29.54',
                'id-ce-freshestCRL' => '2.5.29.46',
                'id-pe-authorityInfoAccess' => '1.3.6.1.5.5.7.1.1',
                'id-pe-subjectInfoAccess' => '1.3.6.1.5.5.7.1.11',
                'id-ce-cRLNumber' => '2.5.29.20',
                'id-ce-issuingDistributionPoint' => '2.5.29.28',
                'id-ce-deltaCRLIndicator' => '2.5.29.27',
                'id-ce-cRLReasons' => '2.5.29.21',
                'id-ce-certificateIssuer' => '2.5.29.29',
                'id-ce-holdInstructionCode' => '2.5.29.23',
                //'holdInstruction' => '1.2.840.10040.2',
                'id-holdinstruction-none' => '1.2.840.10040.2.1',
                'id-holdinstruction-callissuer' => '1.2.840.10040.2.2',
                'id-holdinstruction-reject' => '1.2.840.10040.2.3',
                'id-ce-invalidityDate' => '2.5.29.24',
                'rsaEncryption' => '1.2.840.113549.1.1.1',
                'md2WithRSAEncryption' => '1.2.840.113549.1.1.2',
                'md5WithRSAEncryption' => '1.2.840.113549.1.1.4',
                'sha1WithRSAEncryption' => '1.2.840.113549.1.1.5',
                'sha224WithRSAEncryption' => '1.2.840.113549.1.1.14',
                'sha256WithRSAEncryption' => '1.2.840.113549.1.1.11',
                'sha384WithRSAEncryption' => '1.2.840.113549.1.1.12',
                'sha512WithRSAEncryption' => '1.2.840.113549.1.1.13',
                'id-ecPublicKey' => '1.2.840.10045.2.1',
                'ecdsa-with-SHA1' => '1.2.840.10045.4.1',
                // from https://tools.ietf.org/html/rfc5758#section-3.2
                'ecdsa-with-SHA224' => '1.2.840.10045.4.3.1',
                'ecdsa-with-SHA256' => '1.2.840.10045.4.3.2',
                'ecdsa-with-SHA384' => '1.2.840.10045.4.3.3',
                'ecdsa-with-SHA512' => '1.2.840.10045.4.3.4',
                'id-dsa' => '1.2.840.10040.4.1',
                'id-dsa-with-sha1' => '1.2.840.10040.4.3',
                // from https://tools.ietf.org/html/rfc5758#section-3.1
                'id-dsa-with-sha224' => '2.16.840.1.101.3.4.3.1',
                'id-dsa-with-sha256' => '2.16.840.1.101.3.4.3.2',
                // from https://tools.ietf.org/html/rfc8410:
                'id-Ed25519' => '1.3.101.112',
                'id-Ed448' => '1.3.101.113',
                'id-RSASSA-PSS' => '1.2.840.113549.1.1.10',
                //'id-sha224' => '2.16.840.1.101.3.4.2.4',
                //'id-sha256' => '2.16.840.1.101.3.4.2.1',
                //'id-sha384' => '2.16.840.1.101.3.4.2.2',
                //'id-sha512' => '2.16.840.1.101.3.4.2.3',
                //'id-GostR3411-94-with-GostR3410-94' => '1.2.643.2.2.4',
                //'id-GostR3411-94-with-GostR3410-2001' => '1.2.643.2.2.3',
                //'id-GostR3410-2001' => '1.2.643.2.2.20',
                //'id-GostR3410-94' => '1.2.643.2.2.19',
                // Netscape Object Identifiers from "Netscape Certificate Extensions"
                'netscape' => '2.16.840.1.113730',
                'netscape-cert-extension' => '2.16.840.1.113730.1',
                'netscape-cert-type' => '2.16.840.1.113730.1.1',
                'netscape-comment' => '2.16.840.1.113730.1.13',
                'netscape-ca-policy-url' => '2.16.840.1.113730.1.8',
                // the following are X.509 extensions not supported by phpseclib
                'id-pe-logotype' => '1.3.6.1.5.5.7.1.12',
                'entrustVersInfo' => '1.2.840.113533.7.65.0',
                'verisignPrivate' => '2.16.840.1.113733.1.6.9',
                // for Certificate Signing Requests
                // see http://tools.ietf.org/html/rfc2985
                'pkcs-9-at-unstructuredName' => '1.2.840.113549.1.9.2',
                // PKCS #9 unstructured name
                'pkcs-9-at-challengePassword' => '1.2.840.113549.1.9.7',
                // Challenge password for certificate revocations
                'pkcs-9-at-extensionRequest' => '1.2.840.113549.1.9.14',
            ]);
        }
    }
    /**
     * Load X.509 certificate
     *
     * Returns an associative array describing the X.509 cert or a false if the cert failed to load
     *
     * @param string $cert
     * @param int $mode
     * @access public
     * @return mixed
     */
    public function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT)
    {
        if (is_array($cert) && isset($cert['tbsCertificate'])) {
            unset($this->currentCert);
            unset($this->currentKeyIdentifier);
            $this->dn = $cert['tbsCertificate']['subject'];
            if (!isset($this->dn)) {
                return false;
            }
            $this->currentCert = $cert;
            $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
            $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
            unset($this->signatureSubject);
            return $cert;
        }
        if ($mode != self::FORMAT_DER) {
            $newcert = ASN1::extractBER($cert);
            if ($mode == self::FORMAT_PEM && $cert == $newcert) {
                return false;
            }
            $cert = $newcert;
        }
        if ($cert === false) {
            $this->currentCert = false;
            return false;
        }
        $decoded = ASN1::decodeBER($cert);
        if (!empty($decoded)) {
            $x509 = ASN1::asn1map($decoded[0], Maps\Certificate::MAP);
        }
        if (!isset($x509) || $x509 === false) {
            $this->currentCert = false;
            return false;
        }
        $this->signatureSubject = \Phabel\Target\Php80\Polyfill::substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
        if ($this->isSubArrayValid($x509, 'tbsCertificate/extensions')) {
            $this->mapInExtensions($x509, 'tbsCertificate/extensions');
        }
        $this->mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence');
        $this->mapInDNs($x509, 'tbsCertificate/subject/rdnSequence');
        $key = $x509['tbsCertificate']['subjectPublicKeyInfo'];
        $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP);
        $x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'] = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($key), 64) . "-----END PUBLIC KEY-----";
        $this->currentCert = $x509;
        $this->dn = $x509['tbsCertificate']['subject'];
        $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
        $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
        return $x509;
    }
    /**
     * Save X.509 certificate
     *
     * @param array $cert
     * @param int $format optional
     * @access public
     * @return string
     */
    public function saveX509($cert, $format = self::FORMAT_PEM)
    {
        if (!is_array($cert) || !isset($cert['tbsCertificate'])) {
            return false;
        }
        switch (true) {
            // "case !$a: case !$b: break; default: whatever();" is the same thing as "if ($a && $b) whatever()"
            case !($algorithm = $this->subArray($cert, 'tbsCertificate/subjectPublicKeyInfo/algorithm/algorithm')):
            case is_object($cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
                break;
            default:
                $cert['tbsCertificate']['subjectPublicKeyInfo'] = new Element(base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'])));
        }
        if ($algorithm == 'rsaEncryption') {
            $cert['signatureAlgorithm']['parameters'] = null;
            $cert['tbsCertificate']['signature']['parameters'] = null;
        }
        $filters = [];
        $type_utf8_string = ['type' => ASN1::TYPE_UTF8_STRING];
        $filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string;
        $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string;
        $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string;
        $filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string;
        $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string;
        $filters['signatureAlgorithm']['parameters'] = $type_utf8_string;
        $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
        //$filters['policyQualifiers']['qualifier'] = $type_utf8_string;
        $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
        $filters['directoryName']['rdnSequence']['value'] = $type_utf8_string;
        foreach (self::$extensions as $extension) {
            $filters['tbsCertificate']['extensions'][] = $extension;
        }
        /* in the case of policyQualifiers/qualifier, the type has to be \phpseclib3\File\ASN1::TYPE_IA5_STRING.
             \phpseclib3\File\ASN1::TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random
             characters.
           */
        $filters['policyQualifiers']['qualifier'] = ['type' => ASN1::TYPE_IA5_STRING];
        ASN1::setFilters($filters);
        $this->mapOutExtensions($cert, 'tbsCertificate/extensions');
        $this->mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence');
        $this->mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence');
        $cert = ASN1::encodeDER($cert, Maps\Certificate::MAP);
        switch ($format) {
            case self::FORMAT_DER:
                return $cert;
            // case self::FORMAT_PEM:
            default:
                return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(Base64::encode($cert), 64) . '-----END CERTIFICATE-----';
        }
    }
    /**
    * Map extension values from octet string to extension-specific internal
    format.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapInExtensions(&$root, $path)
    {
        $extensions =& $this->subArrayUnchecked($root, $path);
        if ($extensions) {
            for ($i = 0; $i < count($extensions); $i++) {
                $id = $extensions[$i]['extnId'];
                $value =& $extensions[$i]['extnValue'];
                /* [extnValue] contains the DER encoding of an ASN.1 value
                   corresponding to the extension type identified by extnID */
                $map = $this->getMapping($id);
                if (!is_bool($map)) {
                    $decoder = $id == 'id-ce-nameConstraints' ? [static::class, 'decodeNameConstraintIP'] : [static::class, 'decodeIP'];
                    $decoded = ASN1::decodeBER($value);
                    $mapped = ASN1::asn1map($decoded[0], $map, ['iPAddress' => $decoder]);
                    $value = $mapped === false ? $decoded[0] : $mapped;
                    if ($id == 'id-ce-certificatePolicies') {
                        for ($j = 0; $j < count($value); $j++) {
                            if (!isset($value[$j]['policyQualifiers'])) {
                                continue;
                            }
                            for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
                                $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
                                $map = $this->getMapping($subid);
                                $subvalue =& $value[$j]['policyQualifiers'][$k]['qualifier'];
                                if ($map !== false) {
                                    $decoded = ASN1::decodeBER($subvalue);
                                    $mapped = ASN1::asn1map($decoded[0], $map);
                                    $subvalue = $mapped === false ? $decoded[0] : $mapped;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    /**
    * Map extension values from extension-specific internal format to
    octet string.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapOutExtensions(&$root, $path)
    {
        $extensions =& $this->subArray($root, $path, !empty($this->extensionValues));
        foreach ($this->extensionValues as $id => $data) {
            extract($data);
            $newext = ['extnId' => $id, 'extnValue' => $value, 'critical' => $critical];
            if ($replace) {
                foreach ($extensions as $key => $value) {
                    if ($value['extnId'] == $id) {
                        $extensions[$key] = $newext;
                        continue 2;
                    }
                }
            }
            $extensions[] = $newext;
        }
        if (is_array($extensions)) {
            $size = count($extensions);
            for ($i = 0; $i < $size; $i++) {
                if ($extensions[$i] instanceof Element) {
                    continue;
                }
                $id = $extensions[$i]['extnId'];
                $value =& $extensions[$i]['extnValue'];
                switch ($id) {
                    case 'id-ce-certificatePolicies':
                        for ($j = 0; $j < count($value); $j++) {
                            if (!isset($value[$j]['policyQualifiers'])) {
                                continue;
                            }
                            for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
                                $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
                                $map = $this->getMapping($subid);
                                $subvalue =& $value[$j]['policyQualifiers'][$k]['qualifier'];
                                if ($map !== false) {
                                    // by default \phpseclib3\File\ASN1 will try to render qualifier as a \phpseclib3\File\ASN1::TYPE_IA5_STRING since it's
                                    // actual type is \phpseclib3\File\ASN1::TYPE_ANY
                                    $subvalue = new Element(ASN1::encodeDER($subvalue, $map));
                                }
                            }
                        }
                        break;
                    case 'id-ce-authorityKeyIdentifier':
                        // use 00 as the serial number instead of an empty string
                        if (isset($value['authorityCertSerialNumber'])) {
                            if ($value['authorityCertSerialNumber']->toBytes() == '') {
                                $temp = chr(ASN1::CLASS_CONTEXT_SPECIFIC << 6 | 2) . "\x01\x00";
                                $value['authorityCertSerialNumber'] = new Element($temp);
                            }
                        }
                }
                /* [extnValue] contains the DER encoding of an ASN.1 value
                   corresponding to the extension type identified by extnID */
                $map = $this->getMapping($id);
                if (is_bool($map)) {
                    if (!$map) {
                        //user_error($id . ' is not a currently supported extension');
                        unset($extensions[$i]);
                    }
                } else {
                    $value = ASN1::encodeDER($value, $map, ['iPAddress' => [static::class, 'encodeIP']]);
                }
            }
        }
    }
    /**
    * Map attribute values from ANY type to attribute-specific internal
    format.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapInAttributes(&$root, $path)
    {
        $attributes =& $this->subArray($root, $path);
        if (is_array($attributes)) {
            for ($i = 0; $i < count($attributes); $i++) {
                $id = $attributes[$i]['type'];
                /* $value contains the DER encoding of an ASN.1 value
                   corresponding to the attribute type identified by type */
                $map = $this->getMapping($id);
                if (is_array($attributes[$i]['value'])) {
                    $values =& $attributes[$i]['value'];
                    for ($j = 0; $j < count($values); $j++) {
                        $value = ASN1::encodeDER($values[$j], Maps\AttributeValue::MAP);
                        $decoded = ASN1::decodeBER($value);
                        if (!is_bool($map)) {
                            $mapped = ASN1::asn1map($decoded[0], $map);
                            if ($mapped !== false) {
                                $values[$j] = $mapped;
                            }
                            if ($id == 'pkcs-9-at-extensionRequest' && $this->isSubArrayValid($values, $j)) {
                                $this->mapInExtensions($values, $j);
                            }
                        } elseif ($map) {
                            $values[$j] = $value;
                        }
                    }
                }
            }
        }
    }
    /**
    * Map attribute values from attribute-specific internal format to
    ANY type.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapOutAttributes(&$root, $path)
    {
        $attributes =& $this->subArray($root, $path);
        if (is_array($attributes)) {
            $size = count($attributes);
            for ($i = 0; $i < $size; $i++) {
                /* [value] contains the DER encoding of an ASN.1 value
                   corresponding to the attribute type identified by type */
                $id = $attributes[$i]['type'];
                $map = $this->getMapping($id);
                if ($map === false) {
                    //user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
                    unset($attributes[$i]);
                } elseif (is_array($attributes[$i]['value'])) {
                    $values =& $attributes[$i]['value'];
                    for ($j = 0; $j < count($values); $j++) {
                        switch ($id) {
                            case 'pkcs-9-at-extensionRequest':
                                $this->mapOutExtensions($values, $j);
                                break;
                        }
                        if (!is_bool($map)) {
                            $temp = ASN1::encodeDER($values[$j], $map);
                            $decoded = ASN1::decodeBER($temp);
                            $values[$j] = ASN1::asn1map($decoded[0], Maps\AttributeValue::MAP);
                        }
                    }
                }
            }
        }
    }
    /**
    * Map DN values from ANY type to DN-specific internal
    format.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapInDNs(&$root, $path)
    {
        $dns =& $this->subArray($root, $path);
        if (is_array($dns)) {
            for ($i = 0; $i < count($dns); $i++) {
                for ($j = 0; $j < count($dns[$i]); $j++) {
                    $type = $dns[$i][$j]['type'];
                    $value =& $dns[$i][$j]['value'];
                    if (is_object($value) && $value instanceof Element) {
                        $map = $this->getMapping($type);
                        if (!is_bool($map)) {
                            $decoded = ASN1::decodeBER($value);
                            $value = ASN1::asn1map($decoded[0], $map);
                        }
                    }
                }
            }
        }
    }
    /**
    * Map DN values from DN-specific internal format to
    ANY type.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapOutDNs(&$root, $path)
    {
        $dns =& $this->subArray($root, $path);
        if (is_array($dns)) {
            $size = count($dns);
            for ($i = 0; $i < $size; $i++) {
                for ($j = 0; $j < count($dns[$i]); $j++) {
                    $type = $dns[$i][$j]['type'];
                    $value =& $dns[$i][$j]['value'];
                    if (is_object($value) && $value instanceof Element) {
                        continue;
                    }
                    $map = $this->getMapping($type);
                    if (!is_bool($map)) {
                        $value = new Element(ASN1::encodeDER($value, $map));
                    }
                }
            }
        }
    }
    /**
     * Associate an extension ID to an extension mapping
     *
     * @param string $extnId
     * @access private
     * @return mixed
     */
    private function getMapping($extnId)
    {
        if (!is_string($extnId)) {
            // eg. if it's a \phpseclib3\File\ASN1\Element object
            return true;
        }
        if (isset(self::$extensions[$extnId])) {
            return self::$extensions[$extnId];
        }
        switch ($extnId) {
            case 'id-ce-keyUsage':
                return Maps\KeyUsage::MAP;
            case 'id-ce-basicConstraints':
                return Maps\BasicConstraints::MAP;
            case 'id-ce-subjectKeyIdentifier':
                return Maps\KeyIdentifier::MAP;
            case 'id-ce-cRLDistributionPoints':
                return Maps\CRLDistributionPoints::MAP;
            case 'id-ce-authorityKeyIdentifier':
                return Maps\AuthorityKeyIdentifier::MAP;
            case 'id-ce-certificatePolicies':
                return Maps\CertificatePolicies::MAP;
            case 'id-ce-extKeyUsage':
                return Maps\ExtKeyUsageSyntax::MAP;
            case 'id-pe-authorityInfoAccess':
                return Maps\AuthorityInfoAccessSyntax::MAP;
            case 'id-ce-subjectAltName':
                return Maps\SubjectAltName::MAP;
            case 'id-ce-subjectDirectoryAttributes':
                return Maps\SubjectDirectoryAttributes::MAP;
            case 'id-ce-privateKeyUsagePeriod':
                return Maps\PrivateKeyUsagePeriod::MAP;
            case 'id-ce-issuerAltName':
                return Maps\IssuerAltName::MAP;
            case 'id-ce-policyMappings':
                return Maps\PolicyMappings::MAP;
            case 'id-ce-nameConstraints':
                return Maps\NameConstraints::MAP;
            case 'netscape-cert-type':
                return Maps\netscape_cert_type::MAP;
            case 'netscape-comment':
                return Maps\netscape_comment::MAP;
            case 'netscape-ca-policy-url':
                return Maps\netscape_ca_policy_url::MAP;
            // since id-qt-cps isn't a constructed type it will have already been decoded as a string by the time it gets
            // back around to asn1map() and we don't want it decoded again.
            //case 'id-qt-cps':
            //    return Maps\CPSuri::MAP;
            case 'id-qt-unotice':
                return Maps\UserNotice::MAP;
            // the following OIDs are unsupported but we don't want them to give notices when calling saveX509().
            case 'id-pe-logotype':
            // http://www.ietf.org/rfc/rfc3709.txt
            case 'entrustVersInfo':
            // http://support.microsoft.com/kb/287547
            case '1.3.6.1.4.1.311.20.2':
            // szOID_ENROLL_CERTTYPE_EXTENSION
            case '1.3.6.1.4.1.311.21.1':
            // szOID_CERTSRV_CA_VERSION
            // "SET Secure Electronic Transaction Specification"
            // http://www.maithean.com/docs/set_bk3.pdf
            case '2.23.42.7.0':
            // id-set-hashedRootKey
            // "Certificate Transparency"
            // https://tools.ietf.org/html/rfc6962
            case '1.3.6.1.4.1.11129.2.4.2':
            // "Qualified Certificate statements"
            // https://tools.ietf.org/html/rfc3739#section-3.2.6
            case '1.3.6.1.5.5.7.1.3':
                return true;
            // CSR attributes
            case 'pkcs-9-at-unstructuredName':
                return Maps\PKCS9String::MAP;
            case 'pkcs-9-at-challengePassword':
                return Maps\DirectoryString::MAP;
            case 'pkcs-9-at-extensionRequest':
                return Maps\Extensions::MAP;
            // CRL extensions.
            case 'id-ce-cRLNumber':
                return Maps\CRLNumber::MAP;
            case 'id-ce-deltaCRLIndicator':
                return Maps\CRLNumber::MAP;
            case 'id-ce-issuingDistributionPoint':
                return Maps\IssuingDistributionPoint::MAP;
            case 'id-ce-freshestCRL':
                return Maps\CRLDistributionPoints::MAP;
            case 'id-ce-cRLReasons':
                return Maps\CRLReason::MAP;
            case 'id-ce-invalidityDate':
                return Maps\InvalidityDate::MAP;
            case 'id-ce-certificateIssuer':
                return Maps\CertificateIssuer::MAP;
            case 'id-ce-holdInstructionCode':
                return Maps\HoldInstructionCode::MAP;
            case 'id-at-postalAddress':
                return Maps\PostalAddress::MAP;
        }
        return false;
    }
    /**
     * Load an X.509 certificate as a certificate authority
     *
     * @param string $cert
     * @access public
     * @return bool
     */
    public function loadCA($cert)
    {
        $olddn = $this->dn;
        $oldcert = $this->currentCert;
        $oldsigsubj = $this->signatureSubject;
        $oldkeyid = $this->currentKeyIdentifier;
        $cert = $this->loadX509($cert);
        if (!$cert) {
            $this->dn = $olddn;
            $this->currentCert = $oldcert;
            $this->signatureSubject = $oldsigsubj;
            $this->currentKeyIdentifier = $oldkeyid;
            return false;
        }
        /* From RFC5280 "PKIX Certificate and CRL Profile":
        
                   If the keyUsage extension is present, then the subject public key
                   MUST NOT be used to verify signatures on certificates or CRLs unless
                   the corresponding keyCertSign or cRLSign bit is set. */
        //$keyUsage = $this->getExtension('id-ce-keyUsage');
        //if ($keyUsage && !in_array('keyCertSign', $keyUsage)) {
        //    return false;
        //}
        /* From RFC5280 "PKIX Certificate and CRL Profile":
        
                   The cA boolean indicates whether the certified public key may be used
                   to verify certificate signatures.  If the cA boolean is not asserted,
                   then the keyCertSign bit in the key usage extension MUST NOT be
                   asserted.  If the basic constraints extension is not present in a
                   version 3 certificate, or the extension is present but the cA boolean
                   is not asserted, then the certified public key MUST NOT be used to
                   verify certificate signatures. */
        //$basicConstraints = $this->getExtension('id-ce-basicConstraints');
        //if (!$basicConstraints || !$basicConstraints['cA']) {
        //    return false;
        //}
        $this->CAs[] = $cert;
        $this->dn = $olddn;
        $this->currentCert = $oldcert;
        $this->signatureSubject = $oldsigsubj;
        return true;
    }
    /**
    * Validate an X.509 certificate against a URL
    *
    * From RFC2818 "HTTP over TLS":
    *
    * Matching is performed using the matching rules specified by
    [RFC2459].  If more than one identity of a given type is present in
    the certificate (e.g., more than one dNSName name, a match in any one
    of the set is considered acceptable.) Names may contain the wildcard
    character * which is considered to match any single domain name
    component or component fragment. E.g., *.a.com matches foo.a.com but
    not bar.foo.a.com. f*.com matches foo.com but not bar.com.
    *
    * @param string $url
    * @access public
    * @return bool
    */
    public function validateURL($url)
    {
        if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
            return false;
        }
        $components = parse_url($url);
        if (!isset($components['host'])) {
            return false;
        }
        if ($names = $this->getExtension('id-ce-subjectAltName')) {
            foreach ($names as $name) {
                foreach ($name as $key => $value) {
                    $value = str_replace(['.', '*'], ['\\.', '[^.]*'], $value);
                    switch ($key) {
                        case 'dNSName':
                            /* From RFC2818 "HTTP over TLS":
                            
                                                           If a subjectAltName extension of type dNSName is present, that MUST
                                                           be used as the identity. Otherwise, the (most specific) Common Name
                                                           field in the Subject field of the certificate MUST be used. Although
                                                           the use of the Common Name is existing practice, it is deprecated and
                                                           Certification Authorities are encouraged to use the dNSName instead. */
                            if (preg_match('#^' . $value . '$#', $components['host'])) {
                                return true;
                            }
                            break;
                        case 'iPAddress':
                            /* From RFC2818 "HTTP over TLS":
                            
                                                           In some cases, the URI is specified as an IP address rather than a
                                                           hostname. In this case, the iPAddress subjectAltName must be present
                                                           in the certificate and must exactly match the IP in the URI. */
                            if (preg_match('#(?:\\d{1-3}\\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
                                return true;
                            }
                    }
                }
            }
            return false;
        }
        if ($value = $this->getDNProp('id-at-commonName')) {
            $value = str_replace(['.', '*'], ['\\.', '[^.]*'], $value[0]);
            return preg_match('#^' . $value . '$#', $components['host']);
        }
        return false;
    }
    /**
     * Validate a date
     *
     * If $date isn't defined it is assumed to be the current date.
     *
     * @param (DateTimeInterface | string) $date optional
     * @access public
     * @return boolean
     */
    public function validateDate($date = null)
    {
        if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
            return false;
        }
        if (!isset($date)) {
            $date = new DateTimeImmutable(null, new DateTimeZone(@date_default_timezone_get()));
        }
        $notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore'];
        $notBefore = isset($notBefore['generalTime']) ? $notBefore['generalTime'] : $notBefore['utcTime'];
        $notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter'];
        $notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime'];
        if (is_string($date)) {
            $date = new DateTimeImmutable($date, new DateTimeZone(@date_default_timezone_get()));
        }
        $notBefore = new DateTimeImmutable($notBefore, new DateTimeZone(@date_default_timezone_get()));
        $notAfter = new DateTimeImmutable($notAfter, new DateTimeZone(@date_default_timezone_get()));
        return $date >= $notBefore && $date <= $notAfter;
    }
    /**
     * Fetches a URL
     *
     * @param string $url
     * @access private
     * @return (bool | string)
     */
    private static function fetchURL($url)
    {
        if (self::$disable_url_fetch) {
            return false;
        }
        $parts = parse_url($url);
        $data = '';
        switch ($parts['scheme']) {
            case 'http':
                $fsock = @\Phabel\Target\Php80\Polyfill::fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80);
                if (!$fsock) {
                    return false;
                }
                fputs($fsock, "GET {$parts['path']} HTTP/1.0\r\n");
                fputs($fsock, "Host: {$parts['host']}\r\n\r\n");
                $line = fgets($fsock, 1024);
                if (strlen($line) < 3) {
                    return false;
                }
                preg_match('#HTTP/1.\\d (\\d{3})#', $line, $temp);
                if ($temp[1] != '200') {
                    return false;
                }
                // skip the rest of the headers in the http response
                while (!feof($fsock) && fgets($fsock, 1024) != "\r\n") {
                }
                while (!feof($fsock)) {
                    $temp = fread($fsock, 1024);
                    if ($temp === false) {
                        return false;
                    }
                    $data .= $temp;
                }
                break;
        }
        return $data;
    }
    /**
     * Validates an intermediate cert as identified via authority info access extension
     *
     * See https://tools.ietf.org/html/rfc4325 for more info
     *
     * @param bool $caonly
     * @param int $count
     * @access private
     * @return bool
     */
    private function testForIntermediate($caonly, $count)
    {
        $opts = $this->getExtension('id-pe-authorityInfoAccess');
        if (!is_array($opts)) {
            return false;
        }
        foreach ($opts as $opt) {
            if ($opt['accessMethod'] == 'id-ad-caIssuers') {
                // accessLocation is a GeneralName. GeneralName fields support stuff like email addresses, IP addresses, LDAP,
                // etc, but we're only supporting URI's. URI's and LDAP are the only thing https://tools.ietf.org/html/rfc4325
                // discusses
                if (isset($opt['accessLocation']['uniformResourceIdentifier'])) {
                    $url = $opt['accessLocation']['uniformResourceIdentifier'];
                    break;
                }
            }
        }
        if (!isset($url)) {
            return false;
        }
        $cert = static::fetchURL($url);
        if (!is_string($cert)) {
            return false;
        }
        $parent = new static();
        $parent->CAs = $this->CAs;
        /*
         "Conforming applications that support HTTP or FTP for accessing
          certificates MUST be able to accept .cer files and SHOULD be able
          to accept .p7c files." -- https://tools.ietf.org/html/rfc4325
        
         A .p7c file is 'a "certs-only" CMS message as specified in RFC 2797"
        
         These are currently unsupported
        */
        if (!is_array($parent->loadX509($cert))) {
            return false;
        }
        if (!$parent->validateSignatureCountable($caonly, ++$count)) {
            return false;
        }
        $this->CAs[] = $parent->currentCert;
        //$this->loadCA($cert);
        return true;
    }
    /**
    * Validate a signature
    *
    * Works on X.509 certs, CSR's and CRL's.
    Returns true if the signature is verified, false if it is not correct or null on error
    *
    * By default returns false for self-signed certs. Call validateSignature(false) to make this support
    self-signed.
    *
    * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}.
    *
    * @param bool $caonly optional
    * @access public
    * @return mixed
    */
    public function validateSignature($caonly = true)
    {
        return $this->validateSignatureCountable($caonly, 0);
    }
    /**
     * Validate a signature
     *
     * Performs said validation whilst keeping track of how many times validation method is called
     *
     * @param bool $caonly
     * @param int $count
     * @access private
     * @return mixed
     */
    private function validateSignatureCountable($caonly, $count)
    {
        if (!is_array($this->currentCert) || !isset($this->signatureSubject)) {
            return null;
        }
        if ($count == self::$recur_limit) {
            return false;
        }
        /* TODO:
                   "emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")."
                    -- http://tools.ietf.org/html/rfc5280#section-4.1.2.6
        
                   implement pathLenConstraint in the id-ce-basicConstraints extension */
        switch (true) {
            case isset($this->currentCert['tbsCertificate']):
                // self-signed cert
                switch (true) {
                    case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']:
                    case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(self::DN_STRING) === $this->getDN(self::DN_STRING):
                        $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
                        $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
                        switch (true) {
                            case !is_array($authorityKey):
                            case !$subjectKeyID:
                            case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
                                $signingCert = $this->currentCert;
                        }
                }
                if (!empty($this->CAs)) {
                    for ($i = 0; $i < count($this->CAs); $i++) {
                        // even if the cert is a self-signed one we still want to see if it's a CA;
                        // if not, we'll conditionally return an error
                        $ca = $this->CAs[$i];
                        switch (true) {
                            case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']:
                            case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
                                $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
                                $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
                                switch (true) {
                                    case !is_array($authorityKey):
                                    case !$subjectKeyID:
                                    case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
                                        if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
                                            break 2;
                                            // serial mismatch - check other ca
                                        }
                                        $signingCert = $ca;
                                        // working cert
                                        break 3;
                                }
                        }
                    }
                    if (count($this->CAs) == $i && $caonly) {
                        return $this->testForIntermediate($caonly, $count) && $this->validateSignature($caonly);
                    }
                } elseif (!isset($signingCert) || $caonly) {
                    return $this->testForIntermediate($caonly, $count) && $this->validateSignature($caonly);
                }
                return $this->validateSignatureHelper($signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $this->currentCert['signatureAlgorithm']['algorithm'], \Phabel\Target\Php80\Polyfill::substr($this->currentCert['signature'], 1), $this->signatureSubject);
            case isset($this->currentCert['certificationRequestInfo']):
                return $this->validateSignatureHelper($this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'], $this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $this->currentCert['signatureAlgorithm']['algorithm'], \Phabel\Target\Php80\Polyfill::substr($this->currentCert['signature'], 1), $this->signatureSubject);
            case isset($this->currentCert['publicKeyAndChallenge']):
                return $this->validateSignatureHelper($this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'], $this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'], $this->currentCert['signatureAlgorithm']['algorithm'], \Phabel\Target\Php80\Polyfill::substr($this->currentCert['signature'], 1), $this->signatureSubject);
            case isset($this->currentCert['tbsCertList']):
                if (!empty($this->CAs)) {
                    for ($i = 0; $i < count($this->CAs); $i++) {
                        $ca = $this->CAs[$i];
                        switch (true) {
                            case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']:
                            case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
                                $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
                                $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
                                switch (true) {
                                    case !is_array($authorityKey):
                                    case !$subjectKeyID:
                                    case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
                                        if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
                                            break 2;
                                            // serial mismatch - check other ca
                                        }
                                        $signingCert = $ca;
                                        // working cert
                                        break 3;
                                }
                        }
                    }
                }
                if (!isset($signingCert)) {
                    return false;
                }
                return $this->validateSignatureHelper($signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $this->currentCert['signatureAlgorithm']['algorithm'], \Phabel\Target\Php80\Polyfill::substr($this->currentCert['signature'], 1), $this->signatureSubject);
            default:
                return false;
        }
    }
    /**
    * Validates a signature
    *
    * Returns true if the signature is verified and false if it is not correct.
    If the algorithms are unsupposed an exception is thrown.
    *
    * @param string $publicKeyAlgorithm
    * @param string $publicKey
    * @param string $signatureAlgorithm
    * @param string $signature
    * @param string $signatureSubject
    * @access private
    * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
    * @return bool
    */
    private function validateSignatureHelper($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
    {
        switch ($publicKeyAlgorithm) {
            case 'id-RSASSA-PSS':
                $key = RSA::loadFormat('PSS', $publicKey);
                break;
            case 'rsaEncryption':
                $key = RSA::loadFormat('PKCS8', $publicKey);
                switch ($signatureAlgorithm) {
                    case 'md2WithRSAEncryption':
                    case 'md5WithRSAEncryption':
                    case 'sha1WithRSAEncryption':
                    case 'sha224WithRSAEncryption':
                    case 'sha256WithRSAEncryption':
                    case 'sha384WithRSAEncryption':
                    case 'sha512WithRSAEncryption':
                        $key = $key->withHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm))->withPadding(RSA::SIGNATURE_PKCS1);
                        break;
                    default:
                        throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
                }
                break;
            case 'id-Ed25519':
            case 'id-Ed448':
                $key = EC::loadFormat('PKCS8', $publicKey);
                break;
            case 'id-ecPublicKey':
                $key = EC::loadFormat('PKCS8', $publicKey);
                switch ($signatureAlgorithm) {
                    case 'ecdsa-with-SHA1':
                    case 'ecdsa-with-SHA224':
                    case 'ecdsa-with-SHA256':
                    case 'ecdsa-with-SHA384':
                    case 'ecdsa-with-SHA512':
                        $key = $key->withHash(preg_replace('#^ecdsa-with-#', '', strtolower($signatureAlgorithm)));
                        break;
                    default:
                        throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
                }
                break;
            case 'id-dsa':
                $key = DSA::loadFormat('PKCS8', $publicKey);
                switch ($signatureAlgorithm) {
                    case 'id-dsa-with-sha1':
                    case 'id-dsa-with-sha224':
                    case 'id-dsa-with-sha256':
                        $key = $key->withHash(preg_replace('#^id-dsa-with-#', '', strtolower($signatureAlgorithm)));
                        break;
                    default:
                        throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
                }
                break;
            default:
                throw new UnsupportedAlgorithmException('Public key algorithm unsupported');
        }
        return $key->verify($signatureSubject, $signature);
    }
    /**
    * Sets the recursion limit
    *
    * When validating a signature it may be necessary to download intermediate certs from URI's.
    An intermediate cert that linked to itself would result in an infinite loop so to prevent
    that we set a recursion limit. A negative number means that there is no recursion limit.
    *
    * @param int $count
    * @access public
    */
    public static function setRecurLimit($count)
    {
        self::$recur_limit = $count;
    }
    /**
     * Prevents URIs from being automatically retrieved
     *
     * @access public
     */
    public static function disableURLFetch()
    {
        self::$disable_url_fetch = true;
    }
    /**
     * Allows URIs to be automatically retrieved
     *
     * @access public
     */
    public static function enableURLFetch()
    {
        self::$disable_url_fetch = false;
    }
    /**
     * Decodes an IP address
     *
     * Takes in a base64 encoded "blob" and returns a human readable IP address
     *
     * @param string $ip
     * @access private
     * @return string
     */
    public static function decodeIP($ip)
    {
        return inet_ntop($ip);
    }
    /**
     * Decodes an IP address in a name constraints extension
     *
     * Takes in a base64 encoded "blob" and returns a human readable IP address / mask
     *
     * @param string $ip
     * @access private
     * @return array
     */
    public static function decodeNameConstraintIP($ip)
    {
        $size = strlen($ip) >> 1;
        $mask = \Phabel\Target\Php80\Polyfill::substr($ip, $size);
        $ip = \Phabel\Target\Php80\Polyfill::substr($ip, 0, $size);
        return [inet_ntop($ip), inet_ntop($mask)];
    }
    /**
     * Encodes an IP address
     *
     * Takes a human readable IP address into a base64-encoded "blob"
     *
     * @param (string | array) $ip
     * @access private
     * @return string
     */
    public static function encodeIP($ip)
    {
        return is_string($ip) ? inet_pton($ip) : inet_pton($ip[0]) . inet_pton($ip[1]);
    }
    /**
     * "Normalizes" a Distinguished Name property
     *
     * @param string $propName
     * @access private
     * @return mixed
     */
    private function translateDNProp($propName)
    {
        switch (strtolower($propName)) {
            case 'id-at-countryname':
            case 'countryname':
            case 'c':
                return 'id-at-countryName';
            case 'id-at-organizationname':
            case 'organizationname':
            case 'o':
                return 'id-at-organizationName';
            case 'id-at-dnqualifier':
            case 'dnqualifier':
                return 'id-at-dnQualifier';
            case 'id-at-commonname':
            case 'commonname':
            case 'cn':
                return 'id-at-commonName';
            case 'id-at-stateorprovincename':
            case 'stateorprovincename':
            case 'state':
            case 'province':
            case 'provincename':
            case 'st':
                return 'id-at-stateOrProvinceName';
            case 'id-at-localityname':
            case 'localityname':
            case 'l':
                return 'id-at-localityName';
            case 'id-emailaddress':
            case 'emailaddress':
                return 'pkcs-9-at-emailAddress';
            case 'id-at-serialnumber':
            case 'serialnumber':
                return 'id-at-serialNumber';
            case 'id-at-postalcode':
            case 'postalcode':
                return 'id-at-postalCode';
            case 'id-at-streetaddress':
            case 'streetaddress':
                return 'id-at-streetAddress';
            case 'id-at-name':
            case 'name':
                return 'id-at-name';
            case 'id-at-givenname':
            case 'givenname':
                return 'id-at-givenName';
            case 'id-at-surname':
            case 'surname':
            case 'sn':
                return 'id-at-surname';
            case 'id-at-initials':
            case 'initials':
                return 'id-at-initials';
            case 'id-at-generationqualifier':
            case 'generationqualifier':
                return 'id-at-generationQualifier';
            case 'id-at-organizationalunitname':
            case 'organizationalunitname':
            case 'ou':
                return 'id-at-organizationalUnitName';
            case 'id-at-pseudonym':
            case 'pseudonym':
                return 'id-at-pseudonym';
            case 'id-at-title':
            case 'title':
                return 'id-at-title';
            case 'id-at-description':
            case 'description':
                return 'id-at-description';
            case 'id-at-role':
            case 'role':
                return 'id-at-role';
            case 'id-at-uniqueidentifier':
            case 'uniqueidentifier':
            case 'x500uniqueidentifier':
                return 'id-at-uniqueIdentifier';
            case 'postaladdress':
            case 'id-at-postaladdress':
                return 'id-at-postalAddress';
            default:
                return false;
        }
    }
    /**
     * Set a Distinguished Name property
     *
     * @param string $propName
     * @param mixed $propValue
     * @param string $type optional
     * @access public
     * @return bool
     */
    public function setDNProp($propName, $propValue, $type = 'utf8String')
    {
        if (empty($this->dn)) {
            $this->dn = ['rdnSequence' => []];
        }
        if (($propName = $this->translateDNProp($propName)) === false) {
            return false;
        }
        foreach ((array) $propValue as $v) {
            if (!is_array($v) && isset($type)) {
                $v = [$type => $v];
            }
            $this->dn['rdnSequence'][] = [['type' => $propName, 'value' => $v]];
        }
        return true;
    }
    /**
     * Remove Distinguished Name properties
     *
     * @param string $propName
     * @access public
     */
    public function removeDNProp($propName)
    {
        if (empty($this->dn)) {
            return;
        }
        if (($propName = $this->translateDNProp($propName)) === false) {
            return;
        }
        $dn =& $this->dn['rdnSequence'];
        $size = count($dn);
        for ($i = 0; $i < $size; $i++) {
            if ($dn[$i][0]['type'] == $propName) {
                unset($dn[$i]);
            }
        }
        $dn = array_values($dn);
        // fix for https://bugs.php.net/75433 affecting PHP 7.2
        if (!isset($dn[0])) {
            $dn = array_splice($dn, 0, 0);
        }
    }
    /**
     * Get Distinguished Name properties
     *
     * @param string $propName
     * @param array $dn optional
     * @param bool $withType optional
     * @return mixed
     * @access public
     */
    public function getDNProp($propName, $dn = null, $withType = false)
    {
        if (!isset($dn)) {
            $dn = $this->dn;
        }
        if (empty($dn)) {
            return false;
        }
        if (($propName = $this->translateDNProp($propName)) === false) {
            return false;
        }
        $filters = [];
        $filters['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
        ASN1::setFilters($filters);
        $this->mapOutDNs($dn, 'rdnSequence');
        $dn = $dn['rdnSequence'];
        $result = [];
        for ($i = 0; $i < count($dn); $i++) {
            if ($dn[$i][0]['type'] == $propName) {
                $v = $dn[$i][0]['value'];
                if (!$withType) {
                    if (is_array($v)) {
                        foreach ($v as $type => $s) {
                            $type = array_search($type, ASN1::ANY_MAP);
                            if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) {
                                $s = ASN1::convert($s, $type);
                                if ($s !== false) {
                                    $v = $s;
                                    break;
                                }
                            }
                        }
                        if (is_array($v)) {
                            $v = array_pop($v);
                            // Always strip data type.
                        }
                    } elseif (is_object($v) && $v instanceof Element) {
                        $map = $this->getMapping($propName);
                        if (!is_bool($map)) {
                            $decoded = ASN1::decodeBER($v);
                            $v = ASN1::asn1map($decoded[0], $map);
                        }
                    }
                }
                $result[] = $v;
            }
        }
        return $result;
    }
    /**
     * Set a Distinguished Name
     *
     * @param mixed $dn
     * @param bool $merge optional
     * @param string $type optional
     * @access public
     * @return bool
     */
    public function setDN($dn, $merge = false, $type = 'utf8String')
    {
        if (!$merge) {
            $this->dn = null;
        }
        if (is_array($dn)) {
            if (isset($dn['rdnSequence'])) {
                $this->dn = $dn;
                // No merge here.
                return true;
            }
            // handles stuff generated by openssl_x509_parse()
            foreach ($dn as $prop => $value) {
                if (!$this->setDNProp($prop, $value, $type)) {
                    return false;
                }
            }
            return true;
        }
        // handles everything else
        $results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
        for ($i = 1; $i < count($results); $i += 2) {
            $prop = trim($results[$i], ', =/');
            $value = $results[$i + 1];
            if (!$this->setDNProp($prop, $value, $type)) {
                return false;
            }
        }
        return true;
    }
    /**
     * Get the Distinguished Name for a certificates subject
     *
     * @param mixed $format optional
     * @param array $dn optional
     * @access public
     * @return (array | bool)
     */
    public function getDN($format = self::DN_ARRAY, $dn = null)
    {
        if (!isset($dn)) {
            $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn;
        }
        switch ((int) $format) {
            case self::DN_ARRAY:
                return $dn;
            case self::DN_ASN1:
                $filters = [];
                $filters['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
                ASN1::setFilters($filters);
                $this->mapOutDNs($dn, 'rdnSequence');
                return ASN1::encodeDER($dn, Maps\Name::MAP);
            case self::DN_CANON:
                //  No SEQUENCE around RDNs and all string values normalized as
                // trimmed lowercase UTF-8 with all spacing as one blank.
                // constructed RDNs will not be canonicalized
                $filters = [];
                $filters['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
                ASN1::setFilters($filters);
                $result = '';
                $this->mapOutDNs($dn, 'rdnSequence');
                foreach ($dn['rdnSequence'] as $rdn) {
                    foreach ($rdn as $i => $attr) {
                        $attr =& $rdn[$i];
                        if (is_array($attr['value'])) {
                            foreach ($attr['value'] as $type => $v) {
                                $type = array_search($type, ASN1::ANY_MAP, true);
                                if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) {
                                    $v = ASN1::convert($v, $type);
                                    if ($v !== false) {
                                        $v = preg_replace('/\\s+/', ' ', $v);
                                        $attr['value'] = strtolower(trim($v));
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    $result .= ASN1::encodeDER($rdn, Maps\RelativeDistinguishedName::MAP);
                }
                return $result;
            case self::DN_HASH:
                $dn = $this->getDN(self::DN_CANON, $dn);
                $hash = new Hash('sha1');
                $hash = $hash->hash($dn);
                extract(unpack('Vhash', $hash));
                return strtolower(Hex::encode(pack('N', $hash)));
        }
        // Default is to return a string.
        $start = true;
        $output = '';
        $result = [];
        $filters = [];
        $filters['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
        ASN1::setFilters($filters);
        $this->mapOutDNs($dn, 'rdnSequence');
        foreach ($dn['rdnSequence'] as $field) {
            $prop = $field[0]['type'];
            $value = $field[0]['value'];
            $delim = ', ';
            switch ($prop) {
                case 'id-at-countryName':
                    $desc = 'C';
                    break;
                case 'id-at-stateOrProvinceName':
                    $desc = 'ST';
                    break;
                case 'id-at-organizationName':
                    $desc = 'O';
                    break;
                case 'id-at-organizationalUnitName':
                    $desc = 'OU';
                    break;
                case 'id-at-commonName':
                    $desc = 'CN';
                    break;
                case 'id-at-localityName':
                    $desc = 'L';
                    break;
                case 'id-at-surname':
                    $desc = 'SN';
                    break;
                case 'id-at-uniqueIdentifier':
                    $delim = '/';
                    $desc = 'x500UniqueIdentifier';
                    break;
                case 'id-at-postalAddress':
                    $delim = '/';
                    $desc = 'postalAddress';
                    break;
                default:
                    $delim = '/';
                    $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop);
            }
            if (!$start) {
                $output .= $delim;
            }
            if (is_array($value)) {
                foreach ($value as $type => $v) {
                    $type = array_search($type, ASN1::ANY_MAP, true);
                    if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) {
                        $v = ASN1::convert($v, $type);
                        if ($v !== false) {
                            $value = $v;
                            break;
                        }
                    }
                }
                if (is_array($value)) {
                    $value = array_pop($value);
                    // Always strip data type.
                }
            } elseif (is_object($value) && $value instanceof Element) {
                $callback = function ($x) {
                    return '\\x' . bin2hex($x[0]);
                };
                $value = strtoupper(preg_replace_callback('#[^\\x20-\\x7E]#', $callback, $value->element));
            }
            $output .= $desc . '=' . $value;
            $result[$desc] = isset($result[$desc]) ? array_merge((array) $result[$desc], [$value]) : $value;
            $start = false;
        }
        return $format == self::DN_OPENSSL ? $result : $output;
    }
    /**
     * Get the Distinguished Name for a certificate/crl issuer
     *
     * @param int $format optional
     * @access public
     * @return mixed
     */
    public function getIssuerDN($format = self::DN_ARRAY)
    {
        switch (true) {
            case !isset($this->currentCert) || !is_array($this->currentCert):
                break;
            case isset($this->currentCert['tbsCertificate']):
                return $this->getDN($format, $this->currentCert['tbsCertificate']['issuer']);
            case isset($this->currentCert['tbsCertList']):
                return $this->getDN($format, $this->currentCert['tbsCertList']['issuer']);
        }
        return false;
    }
    /**
    * Get the Distinguished Name for a certificate/csr subject
    Alias of getDN()
    *
    * @param int $format optional
    * @access public
    * @return mixed
    */
    public function getSubjectDN($format = self::DN_ARRAY)
    {
        switch (true) {
            case !empty($this->dn):
                return $this->getDN($format);
            case !isset($this->currentCert) || !is_array($this->currentCert):
                break;
            case isset($this->currentCert['tbsCertificate']):
                return $this->getDN($format, $this->currentCert['tbsCertificate']['subject']);
            case isset($this->currentCert['certificationRequestInfo']):
                return $this->getDN($format, $this->currentCert['certificationRequestInfo']['subject']);
        }
        return false;
    }
    /**
     * Get an individual Distinguished Name property for a certificate/crl issuer
     *
     * @param string $propName
     * @param bool $withType optional
     * @access public
     * @return mixed
     */
    public function getIssuerDNProp($propName, $withType = false)
    {
        switch (true) {
            case !isset($this->currentCert) || !is_array($this->currentCert):
                break;
            case isset($this->currentCert['tbsCertificate']):
                return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType);
            case isset($this->currentCert['tbsCertList']):
                return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType);
        }
        return false;
    }
    /**
     * Get an individual Distinguished Name property for a certificate/csr subject
     *
     * @param string $propName
     * @param bool $withType optional
     * @access public
     * @return mixed
     */
    public function getSubjectDNProp($propName, $withType = false)
    {
        switch (true) {
            case !empty($this->dn):
                return $this->getDNProp($propName, null, $withType);
            case !isset($this->currentCert) || !is_array($this->currentCert):
                break;
            case isset($this->currentCert['tbsCertificate']):
                return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType);
            case isset($this->currentCert['certificationRequestInfo']):
                return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType);
        }
        return false;
    }
    /**
     * Get the certificate chain for the current cert
     *
     * @access public
     * @return mixed
     */
    public function getChain()
    {
        $chain = [$this->currentCert];
        if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
            return false;
        }
        if (empty($this->CAs)) {
            return $chain;
        }
        while (true) {
            $currentCert = $chain[count($chain) - 1];
            for ($i = 0; $i < count($this->CAs); $i++) {
                $ca = $this->CAs[$i];
                if ($currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) {
                    $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier', $currentCert);
                    $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
                    switch (true) {
                        case !is_array($authorityKey):
                        case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
                            if ($currentCert === $ca) {
                                break 3;
                            }
                            $chain[] = $ca;
                            break 2;
                    }
                }
            }
            if ($i == count($this->CAs)) {
                break;
            }
        }
        foreach ($chain as $key => $value) {
            $chain[$key] = new X509();
            $chain[$key]->loadX509($value);
        }
        return $chain;
    }
    /**
     * Returns the current cert
     *
     * @access public
     * @return (array | bool)
     */
    public function &getCurrentCert()
    {
        return $this->currentCert;
    }
    /**
     * Set public key
     *
     * Key needs to be a \phpseclib3\Crypt\RSA object
     *
     * @param PublicKey $key
     * @access public
     * @return bool
     */
    public function setPublicKey(PublicKey $key)
    {
        $this->publicKey = $key;
    }
    /**
     * Set private key
     *
     * Key needs to be a \phpseclib3\Crypt\RSA object
     *
     * @param PrivateKey $key
     * @access public
     */
    public function setPrivateKey(PrivateKey $key)
    {
        $this->privateKey = $key;
    }
    /**
     * Set challenge
     *
     * Used for SPKAC CSR's
     *
     * @param string $challenge
     * @access public
     */
    public function setChallenge($challenge)
    {
        $this->challenge = $challenge;
    }
    /**
     * Gets the public key
     *
     * Returns a \phpseclib3\Crypt\RSA object or a false.
     *
     * @access public
     * @return mixed
     */
    public function getPublicKey()
    {
        if (isset($this->publicKey)) {
            return $this->publicKey;
        }
        if (isset($this->currentCert) && is_array($this->currentCert)) {
            $paths = ['tbsCertificate/subjectPublicKeyInfo', 'certificationRequestInfo/subjectPKInfo', 'publicKeyAndChallenge/spki'];
            foreach ($paths as $path) {
                $keyinfo = $this->subArray($this->currentCert, $path);
                if (!empty($keyinfo)) {
                    break;
                }
            }
        }
        if (empty($keyinfo)) {
            return false;
        }
        $key = $keyinfo['subjectPublicKey'];
        switch ($keyinfo['algorithm']['algorithm']) {
            case 'id-RSASSA-PSS':
                return RSA::loadFormat('PSS', $key);
            case 'rsaEncryption':
                return RSA::loadFormat('PKCS8', $key)->withPadding(RSA::SIGNATURE_PKCS1);
            case 'id-ecPublicKey':
            case 'id-Ed25519':
            case 'id-Ed448':
                return EC::loadFormat('PKCS8', $key);
            case 'id-dsa':
                return DSA::loadFormat('PKCS8', $key);
        }
        return false;
    }
    /**
     * Load a Certificate Signing Request
     *
     * @param string $csr
     * @param int $mode
     * @return mixed
     * @access public
     */
    public function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT)
    {
        if (is_array($csr) && isset($csr['certificationRequestInfo'])) {
            unset($this->currentCert);
            unset($this->currentKeyIdentifier);
            unset($this->signatureSubject);
            $this->dn = $csr['certificationRequestInfo']['subject'];
            if (!isset($this->dn)) {
                return false;
            }
            $this->currentCert = $csr;
            return $csr;
        }
        // see http://tools.ietf.org/html/rfc2986
        if ($mode != self::FORMAT_DER) {
            $newcsr = ASN1::extractBER($csr);
            if ($mode == self::FORMAT_PEM && $csr == $newcsr) {
                return false;
            }
            $csr = $newcsr;
        }
        $orig = $csr;
        if ($csr === false) {
            $this->currentCert = false;
            return false;
        }
        $decoded = ASN1::decodeBER($csr);
        if (empty($decoded)) {
            $this->currentCert = false;
            return false;
        }
        $csr = ASN1::asn1map($decoded[0], Maps\CertificationRequest::MAP);
        if (!isset($csr) || $csr === false) {
            $this->currentCert = false;
            return false;
        }
        $this->mapInAttributes($csr, 'certificationRequestInfo/attributes');
        $this->mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence');
        $this->dn = $csr['certificationRequestInfo']['subject'];
        $this->signatureSubject = \Phabel\Target\Php80\Polyfill::substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
        $key = $csr['certificationRequestInfo']['subjectPKInfo'];
        $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP);
        $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'] = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($key), 64) . "-----END PUBLIC KEY-----";
        $this->currentKeyIdentifier = null;
        $this->currentCert = $csr;
        $this->publicKey = null;
        $this->publicKey = $this->getPublicKey();
        return $csr;
    }
    /**
     * Save CSR request
     *
     * @param array $csr
     * @param int $format optional
     * @access public
     * @return string
     */
    public function saveCSR($csr, $format = self::FORMAT_PEM)
    {
        if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) {
            return false;
        }
        switch (true) {
            case !($algorithm = $this->subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')):
            case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
                break;
            default:
                $csr['certificationRequestInfo']['subjectPKInfo'] = new Element(base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'])));
        }
        $filters = [];
        $filters['certificationRequestInfo']['subject']['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
        ASN1::setFilters($filters);
        $this->mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence');
        $this->mapOutAttributes($csr, 'certificationRequestInfo/attributes');
        $csr = ASN1::encodeDER($csr, Maps\CertificationRequest::MAP);
        switch ($format) {
            case self::FORMAT_DER:
                return $csr;
            // case self::FORMAT_PEM:
            default:
                return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(Base64::encode($csr), 64) . '-----END CERTIFICATE REQUEST-----';
        }
    }
    /**
     * Load a SPKAC CSR
     *
     * SPKAC's are produced by the HTML5 keygen element:
     *
     * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen
     *
     * @param string $spkac
     * @access public
     * @return mixed
     */
    public function loadSPKAC($spkac)
    {
        if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) {
            unset($this->currentCert);
            unset($this->currentKeyIdentifier);
            unset($this->signatureSubject);
            $this->currentCert = $spkac;
            return $spkac;
        }
        // see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge
        // OpenSSL produces SPKAC's that are preceded by the string SPKAC=
        $temp = preg_replace('#(?:SPKAC=)|[ \\r\\n\\\\]#', '', $spkac);
        $temp = preg_match('#^[a-zA-Z\\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false;
        if ($temp != false) {
            $spkac = $temp;
        }
        $orig = $spkac;
        if ($spkac === false) {
            $this->currentCert = false;
            return false;
        }
        $decoded = ASN1::decodeBER($spkac);
        if (empty($decoded)) {
            $this->currentCert = false;
            return false;
        }
        $spkac = ASN1::asn1map($decoded[0], Maps\SignedPublicKeyAndChallenge::MAP);
        if (!isset($spkac) || $spkac === false) {
            $this->currentCert = false;
            return false;
        }
        $this->signatureSubject = \Phabel\Target\Php80\Polyfill::substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
        $key = $spkac['publicKeyAndChallenge']['spki'];
        $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP);
        $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'] = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($key), 64) . "-----END PUBLIC KEY-----";
        $this->currentKeyIdentifier = null;
        $this->currentCert = $spkac;
        $this->publicKey = null;
        $this->publicKey = $this->getPublicKey();
        return $spkac;
    }
    /**
     * Save a SPKAC CSR request
     *
     * @param array $spkac
     * @param int $format optional
     * @access public
     * @return string
     */
    public function saveSPKAC($spkac, $format = self::FORMAT_PEM)
    {
        if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) {
            return false;
        }
        $algorithm = $this->subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm');
        switch (true) {
            case !$algorithm:
            case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']):
                break;
            default:
                $spkac['publicKeyAndChallenge']['spki'] = new Element(base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])));
        }
        $spkac = ASN1::encodeDER($spkac, Maps\SignedPublicKeyAndChallenge::MAP);
        switch ($format) {
            case self::FORMAT_DER:
                return $spkac;
            // case self::FORMAT_PEM:
            default:
                // OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much
                // no other SPKAC decoders phpseclib will use that same format
                return 'SPKAC=' . Base64::encode($spkac);
        }
    }
    /**
     * Load a Certificate Revocation List
     *
     * @param string $crl
     * @param int $mode
     * @return mixed
     * @access public
     */
    public function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT)
    {
        if (is_array($crl) && isset($crl['tbsCertList'])) {
            $this->currentCert = $crl;
            unset($this->signatureSubject);
            return $crl;
        }
        if ($mode != self::FORMAT_DER) {
            $newcrl = ASN1::extractBER($crl);
            if ($mode == self::FORMAT_PEM && $crl == $newcrl) {
                return false;
            }
            $crl = $newcrl;
        }
        $orig = $crl;
        if ($crl === false) {
            $this->currentCert = false;
            return false;
        }
        $decoded = ASN1::decodeBER($crl);
        if (empty($decoded)) {
            $this->currentCert = false;
            return false;
        }
        $crl = ASN1::asn1map($decoded[0], Maps\CertificateList::MAP);
        if (!isset($crl) || $crl === false) {
            $this->currentCert = false;
            return false;
        }
        $this->signatureSubject = \Phabel\Target\Php80\Polyfill::substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
        $this->mapInDNs($crl, 'tbsCertList/issuer/rdnSequence');
        if ($this->isSubArrayValid($crl, 'tbsCertList/crlExtensions')) {
            $this->mapInExtensions($crl, 'tbsCertList/crlExtensions');
        }
        if ($this->isSubArrayValid($crl, 'tbsCertList/revokedCertificates')) {
            $rclist_ref =& $this->subArrayUnchecked($crl, 'tbsCertList/revokedCertificates');
            if ($rclist_ref) {
                $rclist = $crl['tbsCertList']['revokedCertificates'];
                foreach ($rclist as $i => $extension) {
                    if ($this->isSubArrayValid($rclist, "{$i}/crlEntryExtensions")) {
                        $this->mapInExtensions($rclist_ref, "{$i}/crlEntryExtensions");
                    }
                }
            }
        }
        $this->currentKeyIdentifier = null;
        $this->currentCert = $crl;
        return $crl;
    }
    /**
     * Save Certificate Revocation List.
     *
     * @param array $crl
     * @param int $format optional
     * @access public
     * @return string
     */
    public function saveCRL($crl, $format = self::FORMAT_PEM)
    {
        if (!is_array($crl) || !isset($crl['tbsCertList'])) {
            return false;
        }
        $filters = [];
        $filters['tbsCertList']['issuer']['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
        $filters['tbsCertList']['signature']['parameters'] = ['type' => ASN1::TYPE_UTF8_STRING];
        $filters['signatureAlgorithm']['parameters'] = ['type' => ASN1::TYPE_UTF8_STRING];
        if (empty($crl['tbsCertList']['signature']['parameters'])) {
            $filters['tbsCertList']['signature']['parameters'] = ['type' => ASN1::TYPE_NULL];
        }
        if (empty($crl['signatureAlgorithm']['parameters'])) {
            $filters['signatureAlgorithm']['parameters'] = ['type' => ASN1::TYPE_NULL];
        }
        ASN1::setFilters($filters);
        $this->mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence');
        $this->mapOutExtensions($crl, 'tbsCertList/crlExtensions');
        $rclist =& $this->subArray($crl, 'tbsCertList/revokedCertificates');
        if (is_array($rclist)) {
            foreach ($rclist as $i => $extension) {
                $this->mapOutExtensions($rclist, "{$i}/crlEntryExtensions");
            }
        }
        $crl = ASN1::encodeDER($crl, Maps\CertificateList::MAP);
        switch ($format) {
            case self::FORMAT_DER:
                return $crl;
            // case self::FORMAT_PEM:
            default:
                return "-----BEGIN X509 CRL-----\r\n" . chunk_split(Base64::encode($crl), 64) . '-----END X509 CRL-----';
        }
    }
    /**
    * Helper function to build a time field according to RFC 3280 section
    - 4.1.2.5 Validity
    - 5.1.2.4 This Update
    - 5.1.2.5 Next Update
    - 5.1.2.6 Revoked Certificates
    by choosing utcTime iff year of date given is before 2050 and generalTime else.
    *
    * @param string $date in format date('D, d M Y H:i:s O')
    * @access private
    * @return (array | Element)
    */
    private function timeField($date)
    {
        if ($date instanceof Element) {
            return $date;
        }
        $dateObj = new DateTimeImmutable($date, new DateTimeZone('GMT'));
        $year = $dateObj->format('Y');
        // the same way ASN1.php parses this
        if ($year < 2050) {
            return ['utcTime' => $date];
        } else {
            return ['generalTime' => $date];
        }
    }
    /**
    * Sign an X.509 certificate
    *
    * $issuer's private key needs to be loaded.
    $subject can be either an existing X.509 cert (if you want to resign it),
    a CSR or something with the DN and public key explicitly set.
    *
    * @param \phpseclib3\File\X509 $issuer
    * @param \phpseclib3\File\X509 $subject
    * @access public
    * @return mixed
    */
    public function sign($issuer, $subject)
    {
        if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
            return false;
        }
        if (isset($subject->publicKey) && !($subjectPublicKey = $subject->formatSubjectPublicKey())) {
            return false;
        }
        $currentCert = isset($this->currentCert) ? $this->currentCert : null;
        $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
        $signatureAlgorithm = self::identifySignatureAlgorithm($issuer->privateKey);
        if ($signatureAlgorithm != 'id-RSASSA-PSS') {
            $signatureAlgorithm = ['algorithm' => $signatureAlgorithm];
        } else {
            $r = PSS::load($issuer->privateKey->withPassword()->toString('PSS'));
            $signatureAlgorithm = ['algorithm' => 'id-RSASSA-PSS', 'parameters' => PSS::savePSSParams($r)];
        }
        if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) {
            $this->currentCert = $subject->currentCert;
            $this->currentCert['tbsCertificate']['signature'] = $signatureAlgorithm;
            $this->currentCert['signatureAlgorithm'] = $signatureAlgorithm;
            if (!empty($this->startDate)) {
                $this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->timeField($this->startDate);
            }
            if (!empty($this->endDate)) {
                $this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->timeField($this->endDate);
            }
            if (!empty($this->serialNumber)) {
                $this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber;
            }
            if (!empty($subject->dn)) {
                $this->currentCert['tbsCertificate']['subject'] = $subject->dn;
            }
            if (!empty($subject->publicKey)) {
                $this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey;
            }
            $this->removeExtension('id-ce-authorityKeyIdentifier');
            if (isset($subject->domains)) {
                $this->removeExtension('id-ce-subjectAltName');
            }
        } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) {
            return false;
        } else {
            if (!isset($subject->publicKey)) {
                return false;
            }
            $startDate = new DateTimeImmutable('now', new DateTimeZone(@date_default_timezone_get()));
            $startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O');
            $endDate = new DateTimeImmutable('+1 year', new DateTimeZone(@date_default_timezone_get()));
            $endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O');
            /* "The serial number MUST be a positive integer"
                           "Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
                            -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
            
                           for the integer to be positive the leading bit needs to be 0 hence the
                           application of a bitmap
                        */
            $serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new BigInteger(Random::string(20) & "" . str_repeat("\xff", 19), 256);
            $this->currentCert = ['tbsCertificate' => [
                'version' => 'v3',
                'serialNumber' => $serialNumber,
                // $this->setSerialNumber()
                'signature' => $signatureAlgorithm,
                'issuer' => false,
                // this is going to be overwritten later
                'validity' => [
                    'notBefore' => $this->timeField($startDate),
                    // $this->setStartDate()
                    'notAfter' => $this->timeField($endDate),
                ],
                'subject' => $subject->dn,
                'subjectPublicKeyInfo' => $subjectPublicKey,
            ], 'signatureAlgorithm' => $signatureAlgorithm, 'signature' => false];
            // Copy extensions from CSR.
            $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0);
            if (!empty($csrexts)) {
                $this->currentCert['tbsCertificate']['extensions'] = $csrexts;
            }
        }
        $this->currentCert['tbsCertificate']['issuer'] = $issuer->dn;
        if (isset($issuer->currentKeyIdentifier)) {
            $this->setExtension('id-ce-authorityKeyIdentifier', [
                //'authorityCertIssuer' => array(
                //    array(
                //        'directoryName' => $issuer->dn
                //    )
                //),
                'keyIdentifier' => $issuer->currentKeyIdentifier,
            ]);
            //$extensions = &$this->currentCert['tbsCertificate']['extensions'];
            //if (isset($issuer->serialNumber)) {
            //    $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
            //}
            //unset($extensions);
        }
        if (isset($subject->currentKeyIdentifier)) {
            $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier);
        }
        $altName = [];
        if (isset($subject->domains) && count($subject->domains)) {
            $altName = array_map(['\\phpseclib3\\File\\X509', 'dnsName'], $subject->domains);
        }
        if (isset($subject->ipAddresses) && count($subject->ipAddresses)) {
            // should an IP address appear as the CN if no domain name is specified? idk
            //$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1);
            $ipAddresses = [];
            foreach ($subject->ipAddresses as $ipAddress) {
                $encoded = $subject->ipAddress($ipAddress);
                if ($encoded !== false) {
                    $ipAddresses[] = $encoded;
                }
            }
            if (count($ipAddresses)) {
                $altName = array_merge($altName, $ipAddresses);
            }
        }
        if (!empty($altName)) {
            $this->setExtension('id-ce-subjectAltName', $altName);
        }
        if ($this->caFlag) {
            $keyUsage = $this->getExtension('id-ce-keyUsage');
            if (!$keyUsage) {
                $keyUsage = [];
            }
            $this->setExtension('id-ce-keyUsage', array_values(array_unique(array_merge($keyUsage, ['cRLSign', 'keyCertSign']))));
            $basicConstraints = $this->getExtension('id-ce-basicConstraints');
            if (!$basicConstraints) {
                $basicConstraints = [];
            }
            $this->setExtension('id-ce-basicConstraints', array_merge(['cA' => true], $basicConstraints), true);
            if (!isset($subject->currentKeyIdentifier)) {
                $this->setExtension('id-ce-subjectKeyIdentifier', $this->computeKeyIdentifier($this->currentCert), false, false);
            }
        }
        // resync $this->signatureSubject
        // save $tbsCertificate in case there are any \phpseclib3\File\ASN1\Element objects in it
        $tbsCertificate = $this->currentCert['tbsCertificate'];
        $this->loadX509($this->saveX509($this->currentCert));
        $result = $this->currentCert;
        $this->currentCert['signature'] = $result['signature'] = "\x00" . $issuer->privateKey->sign($this->signatureSubject);
        $result['tbsCertificate'] = $tbsCertificate;
        $this->currentCert = $currentCert;
        $this->signatureSubject = $signatureSubject;
        return $result;
    }
    /**
     * Sign a CSR
     *
     * @access public
     * @return mixed
     */
    public function signCSR()
    {
        if (!is_object($this->privateKey) || empty($this->dn)) {
            return false;
        }
        $origPublicKey = $this->publicKey;
        $this->publicKey = $this->privateKey->getPublicKey();
        $publicKey = $this->formatSubjectPublicKey();
        $this->publicKey = $origPublicKey;
        $currentCert = isset($this->currentCert) ? $this->currentCert : null;
        $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
        $signatureAlgorithm = self::identifySignatureAlgorithm($this->privateKey);
        if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) {
            $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
            if (!empty($this->dn)) {
                $this->currentCert['certificationRequestInfo']['subject'] = $this->dn;
            }
            $this->currentCert['certificationRequestInfo']['subjectPKInfo'] = $publicKey;
        } else {
            $this->currentCert = ['certificationRequestInfo' => ['version' => 'v1', 'subject' => $this->dn, 'subjectPKInfo' => $publicKey], 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], 'signature' => false];
        }
        // resync $this->signatureSubject
        // save $certificationRequestInfo in case there are any \phpseclib3\File\ASN1\Element objects in it
        $certificationRequestInfo = $this->currentCert['certificationRequestInfo'];
        $this->loadCSR($this->saveCSR($this->currentCert));
        $result = $this->currentCert;
        $this->currentCert['signature'] = $result['signature'] = "\x00" . $this->privateKey->sign($this->signatureSubject);
        $result['certificationRequestInfo'] = $certificationRequestInfo;
        $this->currentCert = $currentCert;
        $this->signatureSubject = $signatureSubject;
        return $result;
    }
    /**
     * Sign a SPKAC
     *
     * @access public
     * @return mixed
     */
    public function signSPKAC()
    {
        if (!is_object($this->privateKey)) {
            return false;
        }
        $origPublicKey = $this->publicKey;
        $this->publicKey = $this->privateKey->getPublicKey();
        $publicKey = $this->formatSubjectPublicKey();
        $this->publicKey = $origPublicKey;
        $currentCert = isset($this->currentCert) ? $this->currentCert : null;
        $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
        $signatureAlgorithm = self::identifySignatureAlgorithm($this->privateKey);
        // re-signing a SPKAC seems silly but since everything else supports re-signing why not?
        if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) {
            $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
            $this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey;
            if (!empty($this->challenge)) {
                // the bitwise AND ensures that the output is a valid IA5String
                $this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("", strlen($this->challenge));
            }
        } else {
            $this->currentCert = ['publicKeyAndChallenge' => [
                'spki' => $publicKey,
                // quoting <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen>,
                // "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified."
                // both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way
                // we could alternatively do this instead if we ignored the specs:
                // Random::string(8) & str_repeat("\x7F", 8)
                'challenge' => !empty($this->challenge) ? $this->challenge : '',
            ], 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], 'signature' => false];
        }
        // resync $this->signatureSubject
        // save $publicKeyAndChallenge in case there are any \phpseclib3\File\ASN1\Element objects in it
        $publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge'];
        $this->loadSPKAC($this->saveSPKAC($this->currentCert));
        $result = $this->currentCert;
        $this->currentCert['signature'] = $result['signature'] = "\x00" . $this->privateKey->sign($this->signatureSubject);
        $result['publicKeyAndChallenge'] = $publicKeyAndChallenge;
        $this->currentCert = $currentCert;
        $this->signatureSubject = $signatureSubject;
        return $result;
    }
    /**
     * Sign a CRL
     *
     * $issuer's private key needs to be loaded.
     *
     * @param \phpseclib3\File\X509 $issuer
     * @param \phpseclib3\File\X509 $crl
     * @access public
     * @return mixed
     */
    public function signCRL($issuer, $crl)
    {
        if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
            return false;
        }
        $currentCert = isset($this->currentCert) ? $this->currentCert : null;
        $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
        $signatureAlgorithm = self::identifySignatureAlgorithm($issuer->privateKey);
        $thisUpdate = new DateTimeImmutable('now', new DateTimeZone(@date_default_timezone_get()));
        $thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O');
        if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
            $this->currentCert = $crl->currentCert;
            $this->currentCert['tbsCertList']['signature']['algorithm'] = $signatureAlgorithm;
            $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
        } else {
            $this->currentCert = ['tbsCertList' => [
                'version' => 'v2',
                'signature' => ['algorithm' => $signatureAlgorithm],
                'issuer' => false,
                // this is going to be overwritten later
                'thisUpdate' => $this->timeField($thisUpdate),
            ], 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], 'signature' => false];
        }
        $tbsCertList =& $this->currentCert['tbsCertList'];
        $tbsCertList['issuer'] = $issuer->dn;
        $tbsCertList['thisUpdate'] = $this->timeField($thisUpdate);
        if (!empty($this->endDate)) {
            $tbsCertList['nextUpdate'] = $this->timeField($this->endDate);
            // $this->setEndDate()
        } else {
            unset($tbsCertList['nextUpdate']);
        }
        if (!empty($this->serialNumber)) {
            $crlNumber = $this->serialNumber;
        } else {
            $crlNumber = $this->getExtension('id-ce-cRLNumber');
            // "The CRL number is a non-critical CRL extension that conveys a
            //  monotonically increasing sequence number for a given CRL scope and
            //  CRL issuer.  This extension allows users to easily determine when a
            //  particular CRL supersedes another CRL."
            // -- https://tools.ietf.org/html/rfc5280#section-5.2.3
            $crlNumber = $crlNumber !== false ? $crlNumber->add(new BigInteger(1)) : null;
        }
        $this->removeExtension('id-ce-authorityKeyIdentifier');
        $this->removeExtension('id-ce-issuerAltName');
        // Be sure version >= v2 if some extension found.
        $version = isset($tbsCertList['version']) ? $tbsCertList['version'] : 0;
        if (!$version) {
            if (!empty($tbsCertList['crlExtensions'])) {
                $version = 1;
                // v2.
            } elseif (!empty($tbsCertList['revokedCertificates'])) {
                foreach ($tbsCertList['revokedCertificates'] as $cert) {
                    if (!empty($cert['crlEntryExtensions'])) {
                        $version = 1;
                        // v2.
                    }
                }
            }
            if ($version) {
                $tbsCertList['version'] = $version;
            }
        }
        // Store additional extensions.
        if (!empty($tbsCertList['version'])) {
            // At least v2.
            if (!empty($crlNumber)) {
                $this->setExtension('id-ce-cRLNumber', $crlNumber);
            }
            if (isset($issuer->currentKeyIdentifier)) {
                $this->setExtension('id-ce-authorityKeyIdentifier', [
                    //'authorityCertIssuer' => array(
                    //    ]
                    //        'directoryName' => $issuer->dn
                    //    ]
                    //),
                    'keyIdentifier' => $issuer->currentKeyIdentifier,
                ]);
                //$extensions = &$tbsCertList['crlExtensions'];
                //if (isset($issuer->serialNumber)) {
                //    $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
                //}
                //unset($extensions);
            }
            $issuerAltName = $this->getExtension('id-ce-subjectAltName', $issuer->currentCert);
            if ($issuerAltName !== false) {
                $this->setExtension('id-ce-issuerAltName', $issuerAltName);
            }
        }
        if (empty($tbsCertList['revokedCertificates'])) {
            unset($tbsCertList['revokedCertificates']);
        }
        unset($tbsCertList);
        // resync $this->signatureSubject
        // save $tbsCertList in case there are any \phpseclib3\File\ASN1\Element objects in it
        $tbsCertList = $this->currentCert['tbsCertList'];
        $this->loadCRL($this->saveCRL($this->currentCert));
        $result = $this->currentCert;
        $this->currentCert['signature'] = $result['signature'] = "\x00" . $issuer->privateKey->sign($this->signatureSubject);
        $result['tbsCertList'] = $tbsCertList;
        $this->currentCert = $currentCert;
        $this->signatureSubject = $signatureSubject;
        return $result;
    }
    /**
     * Identify signature algorithm from key settings
     *
     * @param PrivateKey $key
     * @access private
     * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
     * @return string
     */
    private static function identifySignatureAlgorithm(PrivateKey $key)
    {
        if ($key instanceof RSA) {
            if ($key->getPadding() & RSA::SIGNATURE_PSS) {
                return 'id-RSASSA-PSS';
            }
            switch ($key->getHash()) {
                case 'md2':
                case 'md5':
                case 'sha1':
                case 'sha224':
                case 'sha256':
                case 'sha384':
                case 'sha512':
                    return $key->getHash() . 'WithRSAEncryption';
            }
            throw new UnsupportedAlgorithmException('The only supported hash algorithms for RSA are: md2, md5, sha1, sha224, sha256, sha384, sha512');
        }
        if ($key instanceof DSA) {
            switch ($key->getHash()) {
                case 'sha1':
                case 'sha224':
                case 'sha256':
                    return 'id-dsa-with-' . $key->getHash();
            }
            throw new UnsupportedAlgorithmException('The only supported hash algorithms for DSA are: sha1, sha224, sha256');
        }
        if ($key instanceof EC) {
            switch ($key->getCurve()) {
                case 'Ed25519':
                case 'Ed448':
                    return 'id-' . $key->getCurve();
            }
            switch ($key->getHash()) {
                case 'sha1':
                case 'sha224':
                case 'sha256':
                case 'sha384':
                case 'sha512':
                    return 'ecdsa-with-' . strtoupper($key->getHash());
            }
            throw new UnsupportedAlgorithmException('The only supported hash algorithms for EC are: sha1, sha224, sha256, sha384, sha512');
        }
        throw new UnsupportedAlgorithmException('The only supported public key classes are: RSA, DSA, EC');
    }
    /**
     * Set certificate start date
     *
     * @param (DateTimeInterface | string) $date
     * @access public
     */
    public function setStartDate($date)
    {
        if (!is_object($date) || !$date instanceof DateTimeInterface) {
            $date = new DateTimeImmutable($date, new DateTimeZone(@date_default_timezone_get()));
        }
        $this->startDate = $date->format('D, d M Y H:i:s O');
    }
    /**
     * Set certificate end date
     *
     * @param (DateTimeInterface | string) $date
     * @access public
     */
    public function setEndDate($date)
    {
        /*
          To indicate that a certificate has no well-defined expiration date,
          the notAfter SHOULD be assigned the GeneralizedTime value of
          99991231235959Z.
        
          -- http://tools.ietf.org/html/rfc5280#section-4.1.2.5
        */
        if (is_string($date) && strtolower($date) === 'lifetime') {
            $temp = '99991231235959Z';
            $temp = chr(ASN1::TYPE_GENERALIZED_TIME) . ASN1::encodeLength(strlen($temp)) . $temp;
            $this->endDate = new Element($temp);
        } else {
            if (!is_object($date) || !$date instanceof DateTimeInterface) {
                $date = new DateTimeImmutable($date, new DateTimeZone(@date_default_timezone_get()));
            }
            $this->endDate = $date->format('D, d M Y H:i:s O');
        }
    }
    /**
     * Set Serial Number
     *
     * @param string $serial
     * @param int $base optional
     * @access public
     */
    public function setSerialNumber($serial, $base = -256)
    {
        $this->serialNumber = new BigInteger($serial, $base);
    }
    /**
     * Turns the certificate into a certificate authority
     *
     * @access public
     */
    public function makeCA()
    {
        $this->caFlag = true;
    }
    /**
    * Check for validity of subarray
    *
    * This is intended for use in conjunction with _subArrayUnchecked(),
    implementing the checks included in _subArray() but without copying
    a potentially large array by passing its reference by-value to is_array().
    *
    * @param array $root
    * @param string $path
    * @return boolean
    * @access private
    */
    private function isSubArrayValid($root, $path)
    {
        if (!is_array($root)) {
            return false;
        }
        foreach (explode('/', $path) as $i) {
            if (!is_array($root)) {
                return false;
            }
            if (!isset($root[$i])) {
                return true;
            }
            $root = $root[$i];
        }
        return true;
    }
    /**
    * Get a reference to a subarray
    *
    * This variant of _subArray() does no is_array() checking,
    so $root should be checked with _isSubArrayValid() first.
    *
    * This is here for performance reasons:
    Passing a reference (i.e. $root) by-value (i.e. to is_array())
    creates a copy. If $root is an especially large array, this is expensive.
    *
    * @param array $root
    * @param string $path absolute path with / as component separator
    * @param bool $create optional
    * @access private
    * @return (array | false)
    */
    private function &subArrayUnchecked(&$root, $path, $create = false)
    {
        $false = false;
        foreach (explode('/', $path) as $i) {
            if (!isset($root[$i])) {
                if (!$create) {
                    return $false;
                }
                $root[$i] = [];
            }
            $root =& $root[$i];
        }
        return $root;
    }
    /**
     * Get a reference to a subarray
     *
     * @param array $root
     * @param string $path absolute path with / as component separator
     * @param bool $create optional
     * @access private
     * @return (array | false)
     */
    private function &subArray(&$root, $path, $create = false)
    {
        $false = false;
        if (!is_array($root)) {
            return $false;
        }
        foreach (explode('/', $path) as $i) {
            if (!is_array($root)) {
                return $false;
            }
            if (!isset($root[$i])) {
                if (!$create) {
                    return $false;
                }
                $root[$i] = [];
            }
            $root =& $root[$i];
        }
        return $root;
    }
    /**
     * Get a reference to an extension subarray
     *
     * @param array $root
     * @param string $path optional absolute path with / as component separator
     * @param bool $create optional
     * @access private
     * @return (array | false)
     */
    private function &extensions(&$root, $path = null, $create = false)
    {
        if (!isset($root)) {
            $root = $this->currentCert;
        }
        switch (true) {
            case !empty($path):
            case !is_array($root):
                break;
            case isset($root['tbsCertificate']):
                $path = 'tbsCertificate/extensions';
                break;
            case isset($root['tbsCertList']):
                $path = 'tbsCertList/crlExtensions';
                break;
            case isset($root['certificationRequestInfo']):
                $pth = 'certificationRequestInfo/attributes';
                $attributes =& $this->subArray($root, $pth, $create);
                if (is_array($attributes)) {
                    foreach ($attributes as $key => $value) {
                        if ($value['type'] == 'pkcs-9-at-extensionRequest') {
                            $path = "{$pth}/{$key}/value/0";
                            break 2;
                        }
                    }
                    if ($create) {
                        $key = count($attributes);
                        $attributes[] = ['type' => 'pkcs-9-at-extensionRequest', 'value' => []];
                        $path = "{$pth}/{$key}/value/0";
                    }
                }
                break;
        }
        $extensions =& $this->subArray($root, $path, $create);
        if (!is_array($extensions)) {
            $false = false;
            return $false;
        }
        return $extensions;
    }
    /**
     * Remove an Extension
     *
     * @param string $id
     * @param string $path optional
     * @access private
     * @return bool
     */
    private function removeExtensionHelper($id, $path = null)
    {
        $extensions =& $this->extensions($this->currentCert, $path);
        if (!is_array($extensions)) {
            return false;
        }
        $result = false;
        foreach ($extensions as $key => $value) {
            if ($value['extnId'] == $id) {
                unset($extensions[$key]);
                $result = true;
            }
        }
        $extensions = array_values($extensions);
        // fix for https://bugs.php.net/75433 affecting PHP 7.2
        if (!isset($extensions[0])) {
            $extensions = array_splice($extensions, 0, 0);
        }
        return $result;
    }
    /**
     * Get an Extension
     *
     * Returns the extension if it exists and false if not
     *
     * @param string $id
     * @param array $cert optional
     * @param string $path optional
     * @access private
     * @return mixed
     */
    private function getExtensionHelper($id, $cert = null, $path = null)
    {
        $extensions = $this->extensions($cert, $path);
        if (!is_array($extensions)) {
            return false;
        }
        foreach ($extensions as $key => $value) {
            if ($value['extnId'] == $id) {
                return $value['extnValue'];
            }
        }
        return false;
    }
    /**
     * Returns a list of all extensions in use
     *
     * @param array $cert optional
     * @param string $path optional
     * @access private
     * @return array
     */
    private function getExtensionsHelper($cert = null, $path = null)
    {
        $exts = $this->extensions($cert, $path);
        $extensions = [];
        if (is_array($exts)) {
            foreach ($exts as $extension) {
                $extensions[] = $extension['extnId'];
            }
        }
        return $extensions;
    }
    /**
     * Set an Extension
     *
     * @param string $id
     * @param mixed $value
     * @param bool $critical optional
     * @param bool $replace optional
     * @param string $path optional
     * @access private
     * @return bool
     */
    private function setExtensionHelper($id, $value, $critical = false, $replace = true, $path = null)
    {
        $extensions =& $this->extensions($this->currentCert, $path, true);
        if (!is_array($extensions)) {
            return false;
        }
        $newext = ['extnId' => $id, 'critical' => $critical, 'extnValue' => $value];
        foreach ($extensions as $key => $value) {
            if ($value['extnId'] == $id) {
                if (!$replace) {
                    return false;
                }
                $extensions[$key] = $newext;
                return true;
            }
        }
        $extensions[] = $newext;
        return true;
    }
    /**
     * Remove a certificate, CSR or CRL Extension
     *
     * @param string $id
     * @access public
     * @return bool
     */
    public function removeExtension($id)
    {
        return $this->removeExtensionHelper($id);
    }
    /**
     * Get a certificate, CSR or CRL Extension
     *
     * Returns the extension if it exists and false if not
     *
     * @param string $id
     * @param array $cert optional
     * @param string $path
     * @access public
     * @return mixed
     */
    public function getExtension($id, $cert = null, $path = null)
    {
        return $this->getExtensionHelper($id, $cert, $path);
    }
    /**
     * Returns a list of all extensions in use in certificate, CSR or CRL
     *
     * @param array $cert optional
     * @param string $path optional
     * @access public
     * @return array
     */
    public function getExtensions($cert = null, $path = null)
    {
        return $this->getExtensionsHelper($cert, $path);
    }
    /**
     * Set a certificate, CSR or CRL Extension
     *
     * @param string $id
     * @param mixed $value
     * @param bool $critical optional
     * @param bool $replace optional
     * @access public
     * @return bool
     */
    public function setExtension($id, $value, $critical = false, $replace = true)
    {
        return $this->setExtensionHelper($id, $value, $critical, $replace);
    }
    /**
     * Remove a CSR attribute.
     *
     * @param string $id
     * @param int $disposition optional
     * @access public
     * @return bool
     */
    public function removeAttribute($id, $disposition = self::ATTR_ALL)
    {
        $attributes =& $this->subArray($this->currentCert, 'certificationRequestInfo/attributes');
        if (!is_array($attributes)) {
            return false;
        }
        $result = false;
        foreach ($attributes as $key => $attribute) {
            if ($attribute['type'] == $id) {
                $n = count($attribute['value']);
                switch (true) {
                    case $disposition == self::ATTR_APPEND:
                    case $disposition == self::ATTR_REPLACE:
                        return false;
                    case $disposition >= $n:
                        $disposition -= $n;
                        break;
                    case $disposition == self::ATTR_ALL:
                    case $n == 1:
                        unset($attributes[$key]);
                        $result = true;
                        break;
                    default:
                        unset($attributes[$key]['value'][$disposition]);
                        $attributes[$key]['value'] = array_values($attributes[$key]['value']);
                        $result = true;
                        break;
                }
                if ($result && $disposition != self::ATTR_ALL) {
                    break;
                }
            }
        }
        $attributes = array_values($attributes);
        return $result;
    }
    /**
     * Get a CSR attribute
     *
     * Returns the attribute if it exists and false if not
     *
     * @param string $id
     * @param int $disposition optional
     * @param array $csr optional
     * @access public
     * @return mixed
     */
    public function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null)
    {
        if (empty($csr)) {
            $csr = $this->currentCert;
        }
        $attributes = $this->subArray($csr, 'certificationRequestInfo/attributes');
        if (!is_array($attributes)) {
            return false;
        }
        foreach ($attributes as $key => $attribute) {
            if ($attribute['type'] == $id) {
                $n = count($attribute['value']);
                switch (true) {
                    case $disposition == self::ATTR_APPEND:
                    case $disposition == self::ATTR_REPLACE:
                        return false;
                    case $disposition == self::ATTR_ALL:
                        return $attribute['value'];
                    case $disposition >= $n:
                        $disposition -= $n;
                        break;
                    default:
                        return $attribute['value'][$disposition];
                }
            }
        }
        return false;
    }
    /**
     * Returns a list of all CSR attributes in use
     *
     * @param array $csr optional
     * @access public
     * @return array
     */
    public function getAttributes($csr = null)
    {
        if (empty($csr)) {
            $csr = $this->currentCert;
        }
        $attributes = $this->subArray($csr, 'certificationRequestInfo/attributes');
        $attrs = [];
        if (is_array($attributes)) {
            foreach ($attributes as $attribute) {
                $attrs[] = $attribute['type'];
            }
        }
        return $attrs;
    }
    /**
     * Set a CSR attribute
     *
     * @param string $id
     * @param mixed $value
     * @param int $disposition optional
     * @access public
     * @return bool
     */
    public function setAttribute($id, $value, $disposition = self::ATTR_ALL)
    {
        $attributes =& $this->subArray($this->currentCert, 'certificationRequestInfo/attributes', true);
        if (!is_array($attributes)) {
            return false;
        }
        switch ($disposition) {
            case self::ATTR_REPLACE:
                $disposition = self::ATTR_APPEND;
            case self::ATTR_ALL:
                $this->removeAttribute($id);
                break;
        }
        foreach ($attributes as $key => $attribute) {
            if ($attribute['type'] == $id) {
                $n = count($attribute['value']);
                switch (true) {
                    case $disposition == self::ATTR_APPEND:
                        $last = $key;
                        break;
                    case $disposition >= $n:
                        $disposition -= $n;
                        break;
                    default:
                        $attributes[$key]['value'][$disposition] = $value;
                        return true;
                }
            }
        }
        switch (true) {
            case $disposition >= 0:
                return false;
            case isset($last):
                $attributes[$last]['value'][] = $value;
                break;
            default:
                $attributes[] = ['type' => $id, 'value' => $disposition == self::ATTR_ALL ? $value : [$value]];
                break;
        }
        return true;
    }
    /**
     * Sets the subject key identifier
     *
     * This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions.
     *
     * @param string $value
     * @access public
     */
    public function setKeyIdentifier($value)
    {
        if (empty($value)) {
            unset($this->currentKeyIdentifier);
        } else {
            $this->currentKeyIdentifier = $value;
        }
    }
    /**
    * Compute a public key identifier.
    *
    * Although key identifiers may be set to any unique value, this function
    computes key identifiers from public key according to the two
    recommended methods (4.2.1.2 RFC 3280).
    Highly polymorphic: try to accept all possible forms of key:
    - Key object
    - \phpseclib3\File\X509 object with public or private key defined
    - Certificate or CSR array
    - \phpseclib3\File\ASN1\Element object
    - PEM or DER string
    *
    * @param mixed $key optional
    * @param int $method optional
    * @access public
    * @return string binary key identifier
    */
    public function computeKeyIdentifier($key = null, $method = 1)
    {
        if (is_null($key)) {
            $key = $this;
        }
        switch (true) {
            case is_string($key):
                break;
            case is_array($key) && isset($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
                return $this->computeKeyIdentifier($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $method);
            case is_array($key) && isset($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
                return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method);
            case !is_object($key):
                return false;
            case $key instanceof Element:
                // Assume the element is a bitstring-packed key.
                $decoded = ASN1::decodeBER($key->element);
                if (empty($decoded)) {
                    return false;
                }
                $raw = ASN1::asn1map($decoded[0], ['type' => ASN1::TYPE_BIT_STRING]);
                if (empty($raw)) {
                    return false;
                }
                // If the key is private, compute identifier from its corresponding public key.
                $key = PublicKeyLoader::load($raw);
                if ($key instanceof PrivateKey) {
                    // If private.
                    return $this->computeKeyIdentifier($key, $method);
                }
                $key = $raw;
                // Is a public key.
                break;
            case $key instanceof X509:
                if (isset($key->publicKey)) {
                    return $this->computeKeyIdentifier($key->publicKey, $method);
                }
                if (isset($key->privateKey)) {
                    return $this->computeKeyIdentifier($key->privateKey, $method);
                }
                if (isset($key->currentCert['tbsCertificate']) || isset($key->currentCert['certificationRequestInfo'])) {
                    return $this->computeKeyIdentifier($key->currentCert, $method);
                }
                return false;
            default:
                // Should be a key object (i.e.: \phpseclib3\Crypt\RSA).
                $key = $key->getPublicKey();
                break;
        }
        // If in PEM format, convert to binary.
        $key = ASN1::extractBER($key);
        // Now we have the key string: compute its sha-1 sum.
        $hash = new Hash('sha1');
        $hash = $hash->hash($key);
        if ($method == 2) {
            $hash = \Phabel\Target\Php80\Polyfill::substr($hash, -8);
            $hash[0] = chr(ord($hash[0]) & 0xf | 0x40);
        }
        return $hash;
    }
    /**
     * Format a public key as appropriate
     *
     * @access private
     * @return (array | bool)
     */
    private function formatSubjectPublicKey()
    {
        $format = $this->publicKey instanceof RSA && $this->publicKey->getPadding() & RSA::SIGNATURE_PSS ? 'PSS' : 'PKCS8';
        $publicKey = base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $this->publicKey->toString($format)));
        $decoded = ASN1::decodeBER($publicKey);
        $mapped = ASN1::asn1map($decoded[0], Maps\SubjectPublicKeyInfo::MAP);
        $mapped['subjectPublicKey'] = $this->publicKey->toString($format);
        return $mapped;
    }
    /**
     * Set the domain name's which the cert is to be valid for
     *
     * @param mixed[] ...$domains
     * @access public
     * @return array
     */
    public function setDomain(...$domains)
    {
        $this->domains = $domains;
        $this->removeDNProp('id-at-commonName');
        $this->setDNProp('id-at-commonName', $this->domains[0]);
    }
    /**
     * Set the IP Addresses's which the cert is to be valid for
     *
     * @access public
     * @param mixed[] ...$ipAddresses
     */
    public function setIPAddress(...$ipAddresses)
    {
        $this->ipAddresses = $ipAddresses;
        /*
        if (!isset($this->domains)) {
            $this->removeDNProp('id-at-commonName');
            $this->setDNProp('id-at-commonName', $this->ipAddresses[0]);
        }
        */
    }
    /**
     * Helper function to build domain array
     *
     * @access private
     * @param string $domain
     * @return array
     */
    private function dnsName($domain)
    {
        return ['dNSName' => $domain];
    }
    /**
     * Helper function to build IP Address array
     *
     * (IPv6 is not currently supported)
     *
     * @access private
     * @param string $address
     * @return array
     */
    private function iPAddress($address)
    {
        return ['iPAddress' => $address];
    }
    /**
     * Get the index of a revoked certificate.
     *
     * @param array $rclist
     * @param string $serial
     * @param bool $create optional
     * @access private
     * @return (int | false)
     */
    private function revokedCertificate(&$rclist, $serial, $create = false)
    {
        $serial = new BigInteger($serial);
        foreach ($rclist as $i => $rc) {
            if (!$serial->compare($rc['userCertificate'])) {
                return $i;
            }
        }
        if (!$create) {
            return false;
        }
        $i = count($rclist);
        $revocationDate = new DateTimeImmutable('now', new DateTimeZone(@date_default_timezone_get()));
        $rclist[] = ['userCertificate' => $serial, 'revocationDate' => $this->timeField($revocationDate->format('D, d M Y H:i:s O'))];
        return $i;
    }
    /**
     * Revoke a certificate.
     *
     * @param string $serial
     * @param string $date optional
     * @access public
     * @return bool
     */
    public function revoke($serial, $date = null)
    {
        if (isset($this->currentCert['tbsCertList'])) {
            if (is_array($rclist =& $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
                if ($this->revokedCertificate($rclist, $serial) === false) {
                    // If not yet revoked
                    if (($i = $this->revokedCertificate($rclist, $serial, true)) !== false) {
                        if (!empty($date)) {
                            $rclist[$i]['revocationDate'] = $this->timeField($date);
                        }
                        return true;
                    }
                }
            }
        }
        return false;
    }
    /**
     * Unrevoke a certificate.
     *
     * @param string $serial
     * @access public
     * @return bool
     */
    public function unrevoke($serial)
    {
        if (is_array($rclist =& $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                unset($rclist[$i]);
                $rclist = array_values($rclist);
                return true;
            }
        }
        return false;
    }
    /**
     * Get a revoked certificate.
     *
     * @param string $serial
     * @access public
     * @return mixed
     */
    public function getRevoked($serial)
    {
        if (is_array($rclist = $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                return $rclist[$i];
            }
        }
        return false;
    }
    /**
     * List revoked certificates
     *
     * @param array $crl optional
     * @access public
     * @return (array | bool)
     */
    public function listRevoked($crl = null)
    {
        if (!isset($crl)) {
            $crl = $this->currentCert;
        }
        if (!isset($crl['tbsCertList'])) {
            return false;
        }
        $result = [];
        if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) {
            foreach ($rclist as $rc) {
                $result[] = $rc['userCertificate']->toString();
            }
        }
        return $result;
    }
    /**
     * Remove a Revoked Certificate Extension
     *
     * @param string $serial
     * @param string $id
     * @access public
     * @return bool
     */
    public function removeRevokedCertificateExtension($serial, $id)
    {
        if (is_array($rclist =& $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                return $this->removeExtensionHelper($id, "tbsCertList/revokedCertificates/{$i}/crlEntryExtensions");
            }
        }
        return false;
    }
    /**
     * Get a Revoked Certificate Extension
     *
     * Returns the extension if it exists and false if not
     *
     * @param string $serial
     * @param string $id
     * @param array $crl optional
     * @access public
     * @return mixed
     */
    public function getRevokedCertificateExtension($serial, $id, $crl = null)
    {
        if (!isset($crl)) {
            $crl = $this->currentCert;
        }
        if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                return $this->getExtension($id, $crl, "tbsCertList/revokedCertificates/{$i}/crlEntryExtensions");
            }
        }
        return false;
    }
    /**
     * Returns a list of all extensions in use for a given revoked certificate
     *
     * @param string $serial
     * @param array $crl optional
     * @access public
     * @return (array | bool)
     */
    public function getRevokedCertificateExtensions($serial, $crl = null)
    {
        if (!isset($crl)) {
            $crl = $this->currentCert;
        }
        if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                return $this->getExtensions($crl, "tbsCertList/revokedCertificates/{$i}/crlEntryExtensions");
            }
        }
        return false;
    }
    /**
     * Set a Revoked Certificate Extension
     *
     * @param string $serial
     * @param string $id
     * @param mixed $value
     * @param bool $critical optional
     * @param bool $replace optional
     * @access public
     * @return bool
     */
    public function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true)
    {
        if (isset($this->currentCert['tbsCertList'])) {
            if (is_array($rclist =& $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
                if (($i = $this->revokedCertificate($rclist, $serial, true)) !== false) {
                    return $this->setExtensionHelper($id, $value, $critical, $replace, "tbsCertList/revokedCertificates/{$i}/crlEntryExtensions");
                }
            }
        }
        return false;
    }
    /**
     * Register the mapping for a custom/unsupported extension.
     *
     * @param string $id
     * @param array $mapping
     */
    public static function registerExtension($id, array $mapping)
    {
        if (isset(self::$extensions[$id]) && self::$extensions[$id] !== $mapping) {
            throw new \RuntimeException('Extension ' . $id . ' has already been defined with a different mapping.');
        }
        self::$extensions[$id] = $mapping;
    }
    /**
     * Register the mapping for a custom/unsupported extension.
     *
     * @param string $id
     *
     * @return (array | null)
     */
    public static function getRegisteredExtension($id)
    {
        return isset(self::$extensions[$id]) ? self::$extensions[$id] : null;
    }
    /**
     * Register the mapping for a custom/unsupported extension.
     *
     * @param string $id
     * @param mixed $value
     * @param bool $critical
     * @param bool $replace
     */
    public function setExtensionValue($id, $value, $critical = false, $replace = false)
    {
        $this->extensionValues[$id] = compact('critical', 'replace', 'value');
    }
}<?php

/**
 * Pure-PHP ANSI Decoder
 *
 * PHP version 5
 *
 * If you call read() in \phpseclib3\Net\SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
 * They'd look like chr(0x1B) . '[00m' or whatever (0x1B = ESC).  They tell a
 * {@link http://en.wikipedia.org/wiki/Terminal_emulator terminal emulator} how to format the characters, what
 * color to display them in, etc. \phpseclib3\File\ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
 *
 * @category  File
 * @package   ANSI
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2012 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File;

/**
 * Pure-PHP ANSI Decoder
 *
 * @package ANSI
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class ANSI
{
    /**
     * Max Width
     *
     * @var int
     * @access private
     */
    private $max_x;
    /**
     * Max Height
     *
     * @var int
     * @access private
     */
    private $max_y;
    /**
     * Max History
     *
     * @var int
     * @access private
     */
    private $max_history;
    /**
     * History
     *
     * @var array
     * @access private
     */
    private $history;
    /**
     * History Attributes
     *
     * @var array
     * @access private
     */
    private $history_attrs;
    /**
     * Current Column
     *
     * @var int
     * @access private
     */
    private $x;
    /**
     * Current Row
     *
     * @var int
     * @access private
     */
    private $y;
    /**
     * Old Column
     *
     * @var int
     * @access private
     */
    private $old_x;
    /**
     * Old Row
     *
     * @var int
     * @access private
     */
    private $old_y;
    /**
     * An empty attribute cell
     *
     * @var object
     * @access private
     */
    private $base_attr_cell;
    /**
     * The current attribute cell
     *
     * @var object
     * @access private
     */
    private $attr_cell;
    /**
     * An empty attribute row
     *
     * @var array
     * @access private
     */
    private $attr_row;
    /**
     * The current screen text
     *
     * @var array
     * @access private
     */
    private $screen;
    /**
     * The current screen attributes
     *
     * @var array
     * @access private
     */
    private $attrs;
    /**
     * Current ANSI code
     *
     * @var string
     * @access private
     */
    private $ansi;
    /**
     * Tokenization
     *
     * @var array
     * @access private
     */
    private $tokenization;
    /**
     * Default Constructor.
     *
     * @return \phpseclib3\File\ANSI
     * @access public
     */
    public function __construct()
    {
        $attr_cell = new \stdClass();
        $attr_cell->bold = false;
        $attr_cell->underline = false;
        $attr_cell->blink = false;
        $attr_cell->background = 'black';
        $attr_cell->foreground = 'white';
        $attr_cell->reverse = false;
        $this->base_attr_cell = clone $attr_cell;
        $this->attr_cell = clone $attr_cell;
        $this->setHistory(200);
        $this->setDimensions(80, 24);
    }
    /**
     * Set terminal width and height
     *
     * Resets the screen as well
     *
     * @param int $x
     * @param int $y
     * @access public
     */
    public function setDimensions($x, $y)
    {
        $this->max_x = $x - 1;
        $this->max_y = $y - 1;
        $this->x = $this->y = 0;
        $this->history = $this->history_attrs = [];
        $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
        $this->screen = array_fill(0, $this->max_y + 1, '');
        $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
        $this->ansi = '';
    }
    /**
     * Set the number of lines that should be logged past the terminal height
     *
     * @param int $history
     * @access public
     */
    public function setHistory($history)
    {
        $this->max_history = $history;
    }
    /**
     * Load a string
     *
     * @param string $source
     * @access public
     */
    public function loadString($source)
    {
        $this->setDimensions($this->max_x + 1, $this->max_y + 1);
        $this->appendString($source);
    }
    /**
     * Appdend a string
     *
     * @param string $source
     * @access public
     */
    public function appendString($source)
    {
        $this->tokenization = [''];
        for ($i = 0; $i < strlen($source); $i++) {
            if (strlen($this->ansi)) {
                $this->ansi .= $source[$i];
                $chr = ord($source[$i]);
                // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
                // single character CSI's not currently supported
                switch (true) {
                    case $this->ansi == "\x1b=":
                        $this->ansi = '';
                        continue 2;
                    case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['):
                    case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126:
                        break;
                    default:
                        continue 2;
                }
                $this->tokenization[] = $this->ansi;
                $this->tokenization[] = '';
                // http://ascii-table.com/ansi-escape-sequences-vt-100.php
                switch ($this->ansi) {
                    case "\x1b[H":
                        // Move cursor to upper left corner
                        $this->old_x = $this->x;
                        $this->old_y = $this->y;
                        $this->x = $this->y = 0;
                        break;
                    case "\x1b[J":
                        // Clear screen from cursor down
                        $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
                        $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
                        $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y));
                        $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row));
                        if (count($this->history) == $this->max_history) {
                            array_shift($this->history);
                            array_shift($this->history_attrs);
                        }
                    case "\x1b[K":
                        // Clear screen from cursor right
                        $this->screen[$this->y] = \Phabel\Target\Php80\Polyfill::substr($this->screen[$this->y], 0, $this->x);
                        array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - ($this->x - 1), $this->base_attr_cell));
                        break;
                    case "\x1b[2K":
                        // Clear entire line
                        $this->screen[$this->y] = str_repeat(' ', $this->x);
                        $this->attrs[$this->y] = $this->attr_row;
                        break;
                    case "\x1b[?1h":
                    // set cursor key to application
                    case "\x1b[?25h":
                    // show the cursor
                    case "\x1b(B":
                        // set united states g0 character set
                        break;
                    case "\x1bE":
                        // Move to next line
                        $this->newLine();
                        $this->x = 0;
                        break;
                    default:
                        switch (true) {
                            case preg_match('#\\x1B\\[(\\d+)B#', $this->ansi, $match):
                                // Move cursor down n lines
                                $this->old_y = $this->y;
                                $this->y += $match[1];
                                break;
                            case preg_match('#\\x1B\\[(\\d+);(\\d+)H#', $this->ansi, $match):
                                // Move cursor to screen location v,h
                                $this->old_x = $this->x;
                                $this->old_y = $this->y;
                                $this->x = $match[2] - 1;
                                $this->y = $match[1] - 1;
                                break;
                            case preg_match('#\\x1B\\[(\\d+)C#', $this->ansi, $match):
                                // Move cursor right n lines
                                $this->old_x = $this->x;
                                $this->x += $match[1];
                                break;
                            case preg_match('#\\x1B\\[(\\d+)D#', $this->ansi, $match):
                                // Move cursor left n lines
                                $this->old_x = $this->x;
                                $this->x -= $match[1];
                                if ($this->x < 0) {
                                    $this->x = 0;
                                }
                                break;
                            case preg_match('#\\x1B\\[(\\d+);(\\d+)r#', $this->ansi, $match):
                                // Set top and bottom lines of a window
                                break;
                            case preg_match('#\\x1B\\[(\\d*(?:;\\d*)*)m#', $this->ansi, $match):
                                // character attributes
                                $attr_cell =& $this->attr_cell;
                                $mods = explode(';', $match[1]);
                                foreach ($mods as $mod) {
                                    switch ($mod) {
                                        case '':
                                        case '0':
                                            // Turn off character attributes
                                            $attr_cell = clone $this->base_attr_cell;
                                            break;
                                        case '1':
                                            // Turn bold mode on
                                            $attr_cell->bold = true;
                                            break;
                                        case '4':
                                            // Turn underline mode on
                                            $attr_cell->underline = true;
                                            break;
                                        case '5':
                                            // Turn blinking mode on
                                            $attr_cell->blink = true;
                                            break;
                                        case '7':
                                            // Turn reverse video on
                                            $attr_cell->reverse = !$attr_cell->reverse;
                                            $temp = $attr_cell->background;
                                            $attr_cell->background = $attr_cell->foreground;
                                            $attr_cell->foreground = $temp;
                                            break;
                                        default:
                                            // set colors
                                            //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
                                            $front =& $attr_cell->{$attr_cell->reverse ? 'background' : 'foreground'};
                                            //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
                                            $back =& $attr_cell->{$attr_cell->reverse ? 'foreground' : 'background'};
                                            switch ($mod) {
                                                // @codingStandardsIgnoreStart
                                                case '30':
                                                    $front = 'black';
                                                    break;
                                                case '31':
                                                    $front = 'red';
                                                    break;
                                                case '32':
                                                    $front = 'green';
                                                    break;
                                                case '33':
                                                    $front = 'yellow';
                                                    break;
                                                case '34':
                                                    $front = 'blue';
                                                    break;
                                                case '35':
                                                    $front = 'magenta';
                                                    break;
                                                case '36':
                                                    $front = 'cyan';
                                                    break;
                                                case '37':
                                                    $front = 'white';
                                                    break;
                                                case '40':
                                                    $back = 'black';
                                                    break;
                                                case '41':
                                                    $back = 'red';
                                                    break;
                                                case '42':
                                                    $back = 'green';
                                                    break;
                                                case '43':
                                                    $back = 'yellow';
                                                    break;
                                                case '44':
                                                    $back = 'blue';
                                                    break;
                                                case '45':
                                                    $back = 'magenta';
                                                    break;
                                                case '46':
                                                    $back = 'cyan';
                                                    break;
                                                case '47':
                                                    $back = 'white';
                                                    break;
                                                // @codingStandardsIgnoreEnd
                                                default:
                                                    //user_error('Unsupported attribute: ' . $mod);
                                                    $this->ansi = '';
                                                    break 2;
                                            }
                                    }
                                }
                                break;
                            default:
                        }
                }
                $this->ansi = '';
                continue;
            }
            $this->tokenization[count($this->tokenization) - 1] .= $source[$i];
            switch ($source[$i]) {
                case "\r":
                    $this->x = 0;
                    break;
                case "\n":
                    $this->newLine();
                    break;
                case "\x08":
                    // backspace
                    if ($this->x) {
                        $this->x--;
                        $this->attrs[$this->y][$this->x] = clone $this->base_attr_cell;
                        $this->screen[$this->y] = \Phabel\Target\Php80\Polyfill::substr_replace($this->screen[$this->y], $source[$i], $this->x, 1);
                    }
                    break;
                case "\x0f":
                    // shift
                    break;
                case "\x1b":
                    // start ANSI escape code
                    $this->tokenization[count($this->tokenization) - 1] = \Phabel\Target\Php80\Polyfill::substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
                    //if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
                    //    array_pop($this->tokenization);
                    //}
                    $this->ansi .= "\x1b";
                    break;
                default:
                    $this->attrs[$this->y][$this->x] = clone $this->attr_cell;
                    if ($this->x > strlen($this->screen[$this->y])) {
                        $this->screen[$this->y] = str_repeat(' ', $this->x);
                    }
                    $this->screen[$this->y] = \Phabel\Target\Php80\Polyfill::substr_replace($this->screen[$this->y], $source[$i], $this->x, 1);
                    if ($this->x > $this->max_x) {
                        $this->x = 0;
                        $this->newLine();
                    } else {
                        $this->x++;
                    }
            }
        }
    }
    /**
     * Add a new line
     *
     * Also update the $this->screen and $this->history buffers
     *
     * @access private
     */
    private function newLine()
    {
        //if ($this->y < $this->max_y) {
        //    $this->y++;
        //}
        while ($this->y >= $this->max_y) {
            $this->history = array_merge($this->history, [array_shift($this->screen)]);
            $this->screen[] = '';
            $this->history_attrs = array_merge($this->history_attrs, [array_shift($this->attrs)]);
            $this->attrs[] = $this->attr_row;
            if (count($this->history) >= $this->max_history) {
                array_shift($this->history);
                array_shift($this->history_attrs);
            }
            $this->y--;
        }
        $this->y++;
    }
    /**
     * Returns the current coordinate without preformating
     *
     * @access private
     * @param \stdClass $last_attr
     * @param \stdClass $cur_attr
     * @param string $char
     * @return string
     */
    private function processCoordinate($last_attr, $cur_attr, $char)
    {
        $output = '';
        if ($last_attr != $cur_attr) {
            $close = $open = '';
            if ($last_attr->foreground != $cur_attr->foreground) {
                if ($cur_attr->foreground != 'white') {
                    $open .= '<span style="color: ' . $cur_attr->foreground . '">';
                }
                if ($last_attr->foreground != 'white') {
                    $close = '</span>' . $close;
                }
            }
            if ($last_attr->background != $cur_attr->background) {
                if ($cur_attr->background != 'black') {
                    $open .= '<span style="background: ' . $cur_attr->background . '">';
                }
                if ($last_attr->background != 'black') {
                    $close = '</span>' . $close;
                }
            }
            if ($last_attr->bold != $cur_attr->bold) {
                if ($cur_attr->bold) {
                    $open .= '<b>';
                } else {
                    $close = '</b>' . $close;
                }
            }
            if ($last_attr->underline != $cur_attr->underline) {
                if ($cur_attr->underline) {
                    $open .= '<u>';
                } else {
                    $close = '</u>' . $close;
                }
            }
            if ($last_attr->blink != $cur_attr->blink) {
                if ($cur_attr->blink) {
                    $open .= '<blink>';
                } else {
                    $close = '</blink>' . $close;
                }
            }
            $output .= $close . $open;
        }
        $output .= htmlspecialchars($char);
        return $output;
    }
    /**
     * Returns the current screen without preformating
     *
     * @access private
     * @return string
     */
    private function getScreenHelper()
    {
        $output = '';
        $last_attr = $this->base_attr_cell;
        for ($i = 0; $i <= $this->max_y; $i++) {
            for ($j = 0; $j <= $this->max_x; $j++) {
                $cur_attr = $this->attrs[$i][$j];
                $output .= $this->processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
                $last_attr = $this->attrs[$i][$j];
            }
            $output .= "\r\n";
        }
        $output = \Phabel\Target\Php80\Polyfill::substr($output, 0, -2);
        // close any remaining open tags
        $output .= $this->processCoordinate($last_attr, $this->base_attr_cell, '');
        return rtrim($output);
    }
    /**
     * Returns the current screen
     *
     * @access public
     * @return string
     */
    public function getScreen()
    {
        return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->getScreenHelper() . '</pre>';
    }
    /**
     * Returns the current screen and the x previous lines
     *
     * @access public
     * @return string
     */
    public function getHistory()
    {
        $scrollback = '';
        $last_attr = $this->base_attr_cell;
        for ($i = 0; $i < count($this->history); $i++) {
            for ($j = 0; $j <= $this->max_x + 1; $j++) {
                $cur_attr = $this->history_attrs[$i][$j];
                $scrollback .= $this->processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
                $last_attr = $this->history_attrs[$i][$j];
            }
            $scrollback .= "\r\n";
        }
        $base_attr_cell = $this->base_attr_cell;
        $this->base_attr_cell = $last_attr;
        $scrollback .= $this->getScreen();
        $this->base_attr_cell = $base_attr_cell;
        return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
    }
}<?php

/**
 * Common String Functions
 *
 * PHP version 5
 *
 * @category  Common
 * @package   Functions\Strings
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Common\Functions;

use phpseclib3\Math\BigInteger;
use phpseclib3\Math\Common\FiniteField;
/**
 * Common String Functions
 *
 * @package Functions\Strings
 * @author  Jim Wigginton <terrafrost@php.net>
 */
abstract class Strings
{
    /**
     * String Shift
     *
     * Inspired by array_shift
     *
     * @param string $string
     * @param int $index
     * @access public
     * @return string
     */
    public static function shift(&$string, $index = 1)
    {
        $substr = \Phabel\Target\Php80\Polyfill::substr($string, 0, $index);
        $string = \Phabel\Target\Php80\Polyfill::substr($string, $index);
        return $substr;
    }
    /**
     * String Pop
     *
     * Inspired by array_pop
     *
     * @param string $string
     * @param int $index
     * @access public
     * @return string
     */
    public static function pop(&$string, $index = 1)
    {
        $substr = \Phabel\Target\Php80\Polyfill::substr($string, -$index);
        $string = \Phabel\Target\Php80\Polyfill::substr($string, 0, -$index);
        return $substr;
    }
    /**
    * Parse SSH2-style string
    *
    * Returns either an array or a boolean if $data is malformed.
    *
    * Valid characters for $format are as follows:
    *
    * C = byte
    b = boolean (true/false)
    N = uint32
    Q = uint64
    s = string
    i = mpint
    L = name-list
    *
    * uint64 is not supported.
    *
    * @param string $format
    * @param string $data
    * @return mixed
    */
    public static function unpackSSH2($format, &$data)
    {
        $format = self::formatPack($format);
        $result = [];
        for ($i = 0; $i < strlen($format); $i++) {
            switch ($format[$i]) {
                case 'C':
                case 'b':
                    if (!strlen($data)) {
                        throw new \LengthException('At least one byte needs to be present for successful C / b decodes');
                    }
                    break;
                case 'N':
                case 'i':
                case 's':
                case 'L':
                    if (strlen($data) < 4) {
                        throw new \LengthException('At least four byte needs to be present for successful N / i / s / L decodes');
                    }
                    break;
                case 'Q':
                    if (strlen($data) < 8) {
                        throw new \LengthException('At least eight byte needs to be present for successful N / i / s / L decodes');
                    }
                    break;
                default:
                    throw new \InvalidArgumentException('$format contains an invalid character');
            }
            switch ($format[$i]) {
                case 'C':
                    $result[] = ord(self::shift($data));
                    continue 2;
                case 'b':
                    $result[] = ord(self::shift($data)) != 0;
                    continue 2;
                case 'N':
                    list(, $temp) = unpack('N', self::shift($data, 4));
                    $result[] = $temp;
                    continue 2;
                case 'Q':
                    // pack() added support for Q in PHP 5.6.3 and PHP 5.6 is phpseclib 3's minimum version
                    // so in theory we could support this BUT, "64-bit format codes are not available for
                    // 32-bit versions" and phpseclib works on 32-bit installs. on 32-bit installs
                    // 64-bit floats can be used to get larger numbers then 32-bit signed ints would allow
                    // for. sure, you're not gonna get the full precision of 64-bit numbers but just because
                    // you need > 32-bit precision doesn't mean you need the full 64-bit precision
                    extract(unpack('Nupper/Nlower', self::shift($data, 8)));
                    $temp = $upper ? 4294967296 * $upper : 0;
                    $temp += $lower < 0 ? ($lower & 0x7ffffffff) + 0x80000000 : $lower;
                    // $temp = hexdec(bin2hex(self::shift($data, 8)));
                    $result[] = $temp;
                    continue 2;
            }
            list(, $length) = unpack('N', self::shift($data, 4));
            if (strlen($data) < $length) {
                throw new \LengthException("{$length} bytes needed; " . strlen($data) . ' bytes available');
            }
            $temp = self::shift($data, $length);
            switch ($format[$i]) {
                case 'i':
                    $result[] = new BigInteger($temp, -256);
                    break;
                case 's':
                    $result[] = $temp;
                    break;
                case 'L':
                    $result[] = explode(',', $temp);
            }
        }
        return $result;
    }
    /**
     * Create SSH2-style string
     *
     * @param string[] ...$elements
     * @access public
     * @return mixed
     */
    public static function packSSH2(...$elements)
    {
        $format = self::formatPack($elements[0]);
        array_shift($elements);
        if (strlen($format) != count($elements)) {
            throw new \InvalidArgumentException('There must be as many arguments as there are characters in the $format string');
        }
        $result = '';
        for ($i = 0; $i < strlen($format); $i++) {
            $element = $elements[$i];
            switch ($format[$i]) {
                case 'C':
                    if (!is_int($element)) {
                        throw new \InvalidArgumentException('Bytes must be represented as an integer between 0 and 255, inclusive.');
                    }
                    $result .= pack('C', $element);
                    break;
                case 'b':
                    if (!is_bool($element)) {
                        throw new \InvalidArgumentException('A boolean parameter was expected.');
                    }
                    $result .= $element ? "\x01" : "\x00";
                    break;
                case 'Q':
                    if (!is_int($element) && !is_float($element)) {
                        throw new \InvalidArgumentException('An integer was expected.');
                    }
                    // 4294967296 == 1 << 32
                    $result .= pack('NN', $element / 4294967296, $element);
                    break;
                case 'N':
                    if (is_float($element)) {
                        $element = (int) $element;
                    }
                    if (!is_int($element)) {
                        throw new \InvalidArgumentException('An integer was expected.');
                    }
                    $result .= pack('N', $element);
                    break;
                case 's':
                    if (!self::is_stringable($element)) {
                        throw new \InvalidArgumentException('A string was expected.');
                    }
                    $result .= pack('Na*', strlen($element), $element);
                    break;
                case 'i':
                    if (!$element instanceof BigInteger && !$element instanceof FiniteField\Integer) {
                        throw new \InvalidArgumentException('A phpseclib3\\Math\\BigInteger or phpseclib3\\Math\\Common\\FiniteField\\Integer object was expected.');
                    }
                    $element = $element->toBytes(true);
                    $result .= pack('Na*', strlen($element), $element);
                    break;
                case 'L':
                    if (!is_array($element)) {
                        throw new \InvalidArgumentException('An array was expected.');
                    }
                    $element = implode(',', $element);
                    $result .= pack('Na*', strlen($element), $element);
                    break;
                default:
                    throw new \InvalidArgumentException('$format contains an invalid character');
            }
        }
        return $result;
    }
    /**
     * Expand a pack string
     *
     * Converts C5 to CCCCC, for example.
     *
     * @access private
     * @param string $format
     * @return string
     */
    private static function formatPack($format)
    {
        $parts = preg_split('#(\\d+)#', $format, -1, PREG_SPLIT_DELIM_CAPTURE);
        $format = '';
        for ($i = 1; $i < count($parts); $i += 2) {
            $format .= \Phabel\Target\Php80\Polyfill::substr($parts[$i - 1], 0, -1) . str_repeat(\Phabel\Target\Php80\Polyfill::substr($parts[$i - 1], -1), $parts[$i]);
        }
        $format .= $parts[$i - 1];
        return $format;
    }
    /**
    * Convert binary data into bits
    *
    * bin2hex / hex2bin refer to base-256 encoded data as binary, whilst
    decbin / bindec refer to base-2 encoded data as binary. For the purposes
    of this function, bin refers to base-256 encoded data whilst bits refers
    to base-2 encoded data
    *
    * @access public
    * @param string $x
    * @return string
    */
    public static function bits2bin($x)
    {
        /*
        // the pure-PHP approach is faster than the GMP approach
        if (function_exists('gmp_export')) {
             return strlen($x) ? gmp_export(gmp_init($x, 2)) : gmp_init(0);
        }
        */
        if (preg_match('#[^01]#', $x)) {
            throw new \RuntimeException('The only valid characters are 0 and 1');
        }
        if (!defined('PHP_INT_MIN')) {
            define('PHP_INT_MIN', ~PHP_INT_MAX);
        }
        $length = strlen($x);
        if (!$length) {
            return '';
        }
        $block_size = PHP_INT_SIZE << 3;
        $pad = $block_size - $length % $block_size;
        if ($pad != $block_size) {
            $x = str_repeat('0', $pad) . $x;
        }
        $parts = str_split($x, $block_size);
        $str = '';
        foreach ($parts as $part) {
            $xor = $part[0] == '1' ? PHP_INT_MIN : 0;
            $part[0] = '0';
            $str .= pack(PHP_INT_SIZE == 4 ? 'N' : 'J', $xor ^ eval('return 0b' . $part . ';'));
        }
        return ltrim($str, "\x00");
    }
    /**
     * Convert bits to binary data
     *
     * @access public
     * @param string $x
     * @return string
     */
    public static function bin2bits($x)
    {
        /*
        // the pure-PHP approach is slower than the GMP approach BUT
        // i want to the pure-PHP version to be easily unit tested as well
        if (function_exists('gmp_import')) {
            return gmp_strval(gmp_import($x), 2);
        }
        */
        $len = strlen($x);
        $mod = $len % PHP_INT_SIZE;
        if ($mod) {
            $x = str_pad($x, $len + PHP_INT_SIZE - $mod, "\x00", STR_PAD_LEFT);
        }
        $bits = '';
        if (PHP_INT_SIZE == 4) {
            $digits = unpack('N*', $x);
            foreach ($digits as $digit) {
                $bits .= sprintf('%032b', $digit);
            }
        } else {
            $digits = unpack('J*', $x);
            foreach ($digits as $digit) {
                $bits .= sprintf('%064b', $digit);
            }
        }
        return ltrim($bits, '0');
    }
    /**
     * Switch Endianness Bit Order
     *
     * @access public
     * @param string $x
     * @return string
     */
    public static function switchEndianness($x)
    {
        $r = '';
        // from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
        for ($i = strlen($x) - 1; $i >= 0; $i--) {
            $b = ord($x[$i]);
            $p1 = $b * 0x802 & 0x22110;
            $p2 = $b * 0x8020 & 0x88440;
            $r .= chr(($p1 | $p2) * 0x10101 >> 16);
        }
        return $r;
    }
    /**
     * Increment the current string
     *
     * @param string $var
     * @return string
     * @access public
     */
    public static function increment_str(&$var)
    {
        for ($i = 4; $i <= strlen($var); $i += 4) {
            $temp = \Phabel\Target\Php80\Polyfill::substr($var, -$i, 4);
            switch ($temp) {
                case "\xff\xff\xff\xff":
                    $var = \Phabel\Target\Php80\Polyfill::substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
                    break;
                case "\xff\xff\xff":
                    $var = \Phabel\Target\Php80\Polyfill::substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
                    return $var;
                default:
                    $temp = unpack('Nnum', $temp);
                    $var = \Phabel\Target\Php80\Polyfill::substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
                    return $var;
            }
        }
        $remainder = strlen($var) % 4;
        if ($remainder == 0) {
            return $var;
        }
        $temp = unpack('Nnum', str_pad(\Phabel\Target\Php80\Polyfill::substr($var, 0, $remainder), 4, "\x00", STR_PAD_LEFT));
        $temp = \Phabel\Target\Php80\Polyfill::substr(pack('N', $temp['num'] + 1), -$remainder);
        $var = \Phabel\Target\Php80\Polyfill::substr_replace($var, $temp, 0, $remainder);
        return $var;
    }
    /**
     * Find whether the type of a variable is string (or could be converted to one)
     *
     * @param (string | object) $var
     * @return boolean
     * @access public
     */
    public static function is_stringable($var)
    {
        return is_string($var) || is_object($var) && method_exists($var, '__toString');
    }
}<?php

/**
 * InconsistentSetupException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   InconsistentSetupException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * InconsistentSetupException
 *
 * @package InconsistentSetupException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class InconsistentSetupException extends \RuntimeException
{
}<?php

/**
 * UnsupportedOperationException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnsupportedOperationException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnsupportedOperationException
 *
 * @package UnsupportedOperationException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnsupportedOperationException extends \RuntimeException
{
}<?php

/**
 * BadModeException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   BadModeException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * BadModeException
 *
 * @package BadModeException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class BadModeException extends \RuntimeException
{
}<?php

/**
 * BadDecryptionException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   BadDecryptionException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * BadDecryptionException
 *
 * @package BadDecryptionException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class BadDecryptionException extends \RuntimeException
{
}<?php

/**
 * UnsupportedAlgorithmException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnsupportedAlgorithmException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnsupportedAlgorithmException
 *
 * @package UnsupportedAlgorithmException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnsupportedAlgorithmException extends \RuntimeException
{
}<?php

/**
 * NoKeyLoadedException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   NoKeyLoadedException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * NoKeyLoadedException
 *
 * @package NoKeyLoadedException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class NoKeyLoadedException extends \RuntimeException
{
}<?php

/**
 * UnsupportedCurveException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnsupportedCurveException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnsupportedCurveException
 *
 * @package UnsupportedCurveException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnsupportedCurveException extends \RuntimeException
{
}<?php

/**
 * BadConfigurationException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   BadConfigurationException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * BadConfigurationException
 *
 * @package BadConfigurationException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class BadConfigurationException extends \RuntimeException
{
}<?php

/**
 * ConnectionClosedException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   ConnectionClosedException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * ConnectionClosedException
 *
 * @package ConnectionClosedException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class ConnectionClosedException extends \RuntimeException
{
}<?php

/**
 * InsufficientSetupException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   InsufficientSetupException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * InsufficientSetupException
 *
 * @package InsufficientSetupException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class InsufficientSetupException extends \RuntimeException
{
}<?php

/**
 * UnsupportedFormatException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnsupportedFormatException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnsupportedFormatException
 *
 * @package UnsupportedFormatException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnsupportedFormatException extends \RuntimeException
{
}<?php

/**
 * UnableToConnectException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnableToConnectException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnableToConnectException
 *
 * @package UnableToConnectException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnableToConnectException extends \RuntimeException
{
}<?php

/**
 * NoSupportedAlgorithmsException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   NoSupportedAlgorithmsException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * NoSupportedAlgorithmsException
 *
 * @package NoSupportedAlgorithmsException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class NoSupportedAlgorithmsException extends \RuntimeException
{
}<?php

/**
 * FileNotFoundException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   FileNotFoundException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * FileNotFoundException
 *
 * @package FileNotFoundException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class FileNotFoundException extends \RuntimeException
{
}<?php

/**
 * Prime Finite Fields
 *
 * Utilizes the factory design pattern
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math;

use phpseclib3\Math\Common\FiniteField;
use phpseclib3\Math\PrimeField\Integer;
/**
 * Prime Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrimeField extends FiniteField
{
    /**
     * Instance Counter
     *
     * @var int
     */
    private static $instanceCounter = 0;
    /**
     * Keeps track of current instance
     *
     * @var int
     */
    protected $instanceID;
    /**
     * Default constructor
     */
    public function __construct(BigInteger $modulo)
    {
        //if (!$modulo->isPrime()) {
        //    throw new \UnexpectedValueException('PrimeField requires a prime number be passed to the constructor');
        //}
        $this->modulo = $modulo;
        $this->instanceID = self::$instanceCounter++;
        Integer::setModulo($this->instanceID, $modulo);
        Integer::setRecurringModuloFunction($this->instanceID, $modulo->createRecurringModuloFunction());
    }
    /**
     * Use a custom defined modular reduction function
     */
    public function setReduction(callable $func)
    {
        $this->reduce = $func->bindTo($this, $this);
    }
    /**
     * Returns an instance of a dynamically generated PrimeFieldInteger class
     *
     * @return object
     */
    public function newInteger(BigInteger $num)
    {
        return new Integer($this->instanceID, $num);
    }
    /**
     * Returns an integer on the finite field between one and the prime modulo
     *
     * @return object
     */
    public function randomInteger()
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        return new Integer($this->instanceID, BigInteger::randomRange($one, Integer::getModulo($this->instanceID)));
    }
    /**
     * Returns the length of the modulo in bytes
     *
     * @return integer
     */
    public function getLengthInBytes()
    {
        return Integer::getModulo($this->instanceID)->getLengthInBytes();
    }
    /**
     * Returns the length of the modulo in bits
     *
     * @return integer
     */
    public function getLength()
    {
        return Integer::getModulo($this->instanceID)->getLength();
    }
    /**
     * Destructor
     */
    public function __destruct()
    {
        Integer::cleanupCache($this->instanceID);
    }
}<?php

/**
 * Binary Finite Fields
 *
 * In a binary finite field numbers are actually polynomial equations. If you
 * represent the number as a sequence of bits you get a sequence of 1's or 0's.
 * These 1's or 0's represent the coefficients of the x**n, where n is the
 * location of the given bit. When you add numbers over a binary finite field
 * the result should have a coefficient of 1 or 0 as well. Hence addition
 * and subtraction become the same operation as XOR.
 * eg. 1 + 1 + 1 == 3 % 2 == 1 or 0 - 1 == -1 % 2 == 1
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math\BinaryField;

use phpseclib3\Math\Common\FiniteField\Integer as Base;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\BinaryField;
use ParagonIE\ConstantTime\Hex;
/**
 * Binary Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Integer extends Base
{
    /**
     * Holds the BinaryField's value
     *
     * @var string
     */
    protected $value;
    /**
     * Keeps track of current instance
     *
     * @var int
     */
    protected $instanceID;
    /**
     * Holds the PrimeField's modulo
     *
     * @var string[]
     */
    protected static $modulo;
    /**
     * Holds a pre-generated function to perform modulo reductions
     *
     * @var callable[]
     */
    protected static $reduce;
    /**
     * Default constructor
     */
    public function __construct($instanceID, $num = '')
    {
        $this->instanceID = $instanceID;
        if (!strlen($num)) {
            $this->value = '';
        } else {
            $reduce = static::$reduce[$instanceID];
            $this->value = $reduce($num);
        }
    }
    /**
     * Set the modulo for a given instance
     */
    public static function setModulo($instanceID, $modulo)
    {
        static::$modulo[$instanceID] = $modulo;
    }
    /**
     * Set the modulo for a given instance
     */
    public static function setRecurringModuloFunction($instanceID, callable $function)
    {
        static::$reduce[$instanceID] = $function;
    }
    /**
     * Tests a parameter to see if it's of the right instance
     *
     * Throws an exception if the incorrect class is being utilized
     */
    private static function checkInstance(self $x, self $y)
    {
        if ($x->instanceID != $y->instanceID) {
            throw new \UnexpectedValueException('The instances of the two BinaryField\\Integer objects do not match');
        }
    }
    /**
     * Tests the equality of two numbers.
     *
     * @return bool
     */
    public function equals(self $x)
    {
        static::checkInstance($this, $x);
        return $this->value == $x->value;
    }
    /**
     * Compares two numbers.
     *
     * @return int
     */
    public function compare(self $x)
    {
        static::checkInstance($this, $x);
        $a = $this->value;
        $b = $x->value;
        $length = max(strlen($a), strlen($b));
        $a = str_pad($a, $length, "\x00", STR_PAD_LEFT);
        $b = str_pad($b, $length, "\x00", STR_PAD_LEFT);
        return strcmp($a, $b);
    }
    /**
     * Returns the degree of the polynomial
     *
     * @param string $x
     * @return int
     */
    private static function deg($x)
    {
        $x = ltrim($x, "\x00");
        $xbit = decbin(ord($x[0]));
        $xlen = $xbit == '0' ? 0 : strlen($xbit);
        $len = strlen($x);
        if (!$len) {
            return -1;
        }
        return 8 * strlen($x) - 9 + $xlen;
    }
    /**
     * Perform polynomial division
     *
     * @return string[]
     * @link https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#Euclidean_division
     */
    private static function polynomialDivide($x, $y)
    {
        // in wikipedia's description of the algorithm, lc() is the leading coefficient. over a binary field that's
        // always going to be 1.
        $q = chr(0);
        $d = static::deg($y);
        $r = $x;
        while (($degr = static::deg($r)) >= $d) {
            $s = '1' . str_repeat('0', $degr - $d);
            $s = BinaryField::base2ToBase256($s);
            $length = max(strlen($s), strlen($q));
            $q = !isset($q) ? $s : str_pad($q, $length, "\x00", STR_PAD_LEFT) ^ str_pad($s, $length, "\x00", STR_PAD_LEFT);
            $s = static::polynomialMultiply($s, $y);
            $length = max(strlen($r), strlen($s));
            $r = str_pad($r, $length, "\x00", STR_PAD_LEFT) ^ str_pad($s, $length, "\x00", STR_PAD_LEFT);
        }
        return [ltrim($q, "\x00"), ltrim($r, "\x00")];
    }
    /**
     * Perform polynomial multiplation in the traditional way
     *
     * @return string
     * @link https://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplication
     */
    private static function regularPolynomialMultiply($x, $y)
    {
        $precomputed = [ltrim($x, "\x00")];
        $x = strrev(BinaryField::base256ToBase2($x));
        $y = strrev(BinaryField::base256ToBase2($y));
        if (strlen($x) == strlen($y)) {
            $length = strlen($x);
        } else {
            $length = max(strlen($x), strlen($y));
            $x = str_pad($x, $length, '0');
            $y = str_pad($y, $length, '0');
        }
        $result = str_repeat('0', 2 * $length - 1);
        $result = BinaryField::base2ToBase256($result);
        $size = strlen($result);
        $x = strrev($x);
        // precompute left shift 1 through 7
        for ($i = 1; $i < 8; $i++) {
            $precomputed[$i] = BinaryField::base2ToBase256($x . str_repeat('0', $i));
        }
        for ($i = 0; $i < strlen($y); $i++) {
            if ($y[$i] == '1') {
                $temp = $precomputed[$i & 7] . str_repeat("\x00", $i >> 3);
                $result ^= str_pad($temp, $size, "\x00", STR_PAD_LEFT);
            }
        }
        return $result;
    }
    /**
     * Perform polynomial multiplation
     *
     * Uses karatsuba multiplication to reduce x-bit multiplications to a series of 32-bit multiplications
     *
     * @return string
     * @link https://en.wikipedia.org/wiki/Karatsuba_algorithm
     */
    private static function polynomialMultiply($x, $y)
    {
        if (strlen($x) == strlen($y)) {
            $length = strlen($x);
        } else {
            $length = max(strlen($x), strlen($y));
            $x = str_pad($x, $length, "\x00", STR_PAD_LEFT);
            $y = str_pad($y, $length, "\x00", STR_PAD_LEFT);
        }
        switch (true) {
            case PHP_INT_SIZE == 8 && $length <= 4:
                return $length != 4 ? self::subMultiply(str_pad($x, 4, "\x00", STR_PAD_LEFT), str_pad($y, 4, "\x00", STR_PAD_LEFT)) : self::subMultiply($x, $y);
            case PHP_INT_SIZE == 4 || $length > 32:
                return self::regularPolynomialMultiply($x, $y);
        }
        $m = $length >> 1;
        $x1 = \Phabel\Target\Php80\Polyfill::substr($x, 0, -$m);
        $x0 = \Phabel\Target\Php80\Polyfill::substr($x, -$m);
        $y1 = \Phabel\Target\Php80\Polyfill::substr($y, 0, -$m);
        $y0 = \Phabel\Target\Php80\Polyfill::substr($y, -$m);
        $z2 = self::polynomialMultiply($x1, $y1);
        $z0 = self::polynomialMultiply($x0, $y0);
        $z1 = self::polynomialMultiply(self::subAdd2($x1, $x0), self::subAdd2($y1, $y0));
        $z1 = self::subAdd3($z1, $z2, $z0);
        $xy = self::subAdd3($z2 . str_repeat("\x00", 2 * $m), $z1 . str_repeat("\x00", $m), $z0);
        return ltrim($xy, "\x00");
    }
    /**
    * Perform polynomial multiplication on 2x 32-bit numbers, returning
    a 64-bit number
    *
    * @param string $x
    * @param string $y
    * @return string
    * @link https://www.bearssl.org/constanttime.html#ghash-for-gcm
    */
    private static function subMultiply($x, $y)
    {
        $x = unpack('N', $x)[1];
        $y = unpack('N', $y)[1];
        $x0 = $x & 0x11111111;
        $x1 = $x & 0x22222222;
        $x2 = $x & 0x44444444;
        $x3 = $x & 0x88888888;
        $y0 = $y & 0x11111111;
        $y1 = $y & 0x22222222;
        $y2 = $y & 0x44444444;
        $y3 = $y & 0x88888888;
        $z0 = $x0 * $y0 ^ $x1 * $y3 ^ $x2 * $y2 ^ $x3 * $y1;
        $z1 = $x0 * $y1 ^ $x1 * $y0 ^ $x2 * $y3 ^ $x3 * $y2;
        $z2 = $x0 * $y2 ^ $x1 * $y1 ^ $x2 * $y0 ^ $x3 * $y3;
        $z3 = $x0 * $y3 ^ $x1 * $y2 ^ $x2 * $y1 ^ $x3 * $y0;
        $z0 &= 0x1111111111111111;
        $z1 &= 0x2222222222222222;
        $z2 &= 0x4444444444444444;
        $z3 &= -8608480567731124088;
        // 0x8888888888888888 gets interpreted as a float
        $z = $z0 | $z1 | $z2 | $z3;
        return pack('J', $z);
    }
    /**
     * Adds two numbers
     *
     * @param string $x
     * @param string $y
     * @return string
     */
    private static function subAdd2($x, $y)
    {
        $length = max(strlen($x), strlen($y));
        $x = str_pad($x, $length, "\x00", STR_PAD_LEFT);
        $y = str_pad($y, $length, "\x00", STR_PAD_LEFT);
        return $x ^ $y;
    }
    /**
     * Adds three numbers
     *
     * @param string $x
     * @param string $y
     * @return string
     */
    private static function subAdd3($x, $y, $z)
    {
        $length = max(strlen($x), strlen($y), strlen($z));
        $x = str_pad($x, $length, "\x00", STR_PAD_LEFT);
        $y = str_pad($y, $length, "\x00", STR_PAD_LEFT);
        $z = str_pad($z, $length, "\x00", STR_PAD_LEFT);
        return $x ^ $y ^ $z;
    }
    /**
     * Adds two BinaryFieldIntegers.
     *
     * @return static
     */
    public function add(self $y)
    {
        static::checkInstance($this, $y);
        $length = strlen(static::$modulo[$this->instanceID]);
        $x = str_pad($this->value, $length, "\x00", STR_PAD_LEFT);
        $y = str_pad($y->value, $length, "\x00", STR_PAD_LEFT);
        return new static($this->instanceID, $x ^ $y);
    }
    /**
     * Subtracts two BinaryFieldIntegers.
     *
     * @return static
     */
    public function subtract(self $x)
    {
        return $this->add($x);
    }
    /**
     * Multiplies two BinaryFieldIntegers.
     *
     * @return static
     */
    public function multiply(self $y)
    {
        static::checkInstance($this, $y);
        return new static($this->instanceID, static::polynomialMultiply($this->value, $y->value));
    }
    /**
     * Returns the modular inverse of a BinaryFieldInteger
     *
     * @return static
     */
    public function modInverse()
    {
        $remainder0 = static::$modulo[$this->instanceID];
        $remainder1 = $this->value;
        if ($remainder1 == '') {
            return new static($this->instanceID);
        }
        $aux0 = "\x00";
        $aux1 = "\x01";
        while ($remainder1 != "\x01") {
            list($q, $r) = static::polynomialDivide($remainder0, $remainder1);
            $remainder0 = $remainder1;
            $remainder1 = $r;
            // the auxiliary in row n is given by the sum of the auxiliary in
            // row n-2 and the product of the quotient and the auxiliary in row
            // n-1
            $temp = static::polynomialMultiply($aux1, $q);
            $aux = str_pad($aux0, strlen($temp), "\x00", STR_PAD_LEFT) ^ str_pad($temp, strlen($aux0), "\x00", STR_PAD_LEFT);
            $aux0 = $aux1;
            $aux1 = $aux;
        }
        $temp = new static($this->instanceID);
        $temp->value = ltrim($aux1, "\x00");
        return $temp;
    }
    /**
     * Divides two PrimeFieldIntegers.
     *
     * @return static
     */
    public function divide(self $x)
    {
        static::checkInstance($this, $x);
        $x = $x->modInverse();
        return $this->multiply($x);
    }
    /**
    * Negate
    *
    * A negative number can be written as 0-12. With modulos, 0 is the same thing as the modulo
    so 0-12 is the same thing as modulo-12
    *
    * @return object
    */
    public function negate()
    {
        $x = str_pad($this->value, strlen(static::$modulo[$this->instanceID]), "\x00", STR_PAD_LEFT);
        return new static($this->instanceID, $x ^ static::$modulo[$this->instanceID]);
    }
    /**
     * Returns the modulo
     *
     * @return integer
     */
    public static function getModulo($instanceID)
    {
        return static::$modulo[$instanceID];
    }
    /**
     * Converts an Integer to a byte string (eg. base-256).
     *
     * @return string
     */
    public function toBytes()
    {
        return str_pad($this->value, strlen(static::$modulo[$this->instanceID]), "\x00", STR_PAD_LEFT);
    }
    /**
     * Converts an Integer to a hex string (eg. base-16).
     *
     * @return string
     */
    public function toHex()
    {
        return Hex::encode($this->toBytes());
    }
    /**
     * Converts an Integer to a bit string (eg. base-2).
     *
     * @return string
     */
    public function toBits()
    {
        //return str_pad(BinaryField::base256ToBase2($this->value), strlen(static::$modulo[$this->instanceID]), '0', STR_PAD_LEFT);
        return BinaryField::base256ToBase2($this->value);
    }
    /**
     * Converts an Integer to a BigInteger
     *
     * @return string
     */
    public function toBigInteger()
    {
        return new BigInteger($this->value, 256);
    }
    /**
     * __toString() magic method
     *
     * @access public
     */
    public function __toString()
    {
        return (string) $this->toBigInteger();
    }
    /**
     * __debugInfo() magic method
     *
     * @access public
     */
    public function __debugInfo()
    {
        return ['value' => $this->toHex()];
    }
}<?php

/**
 * Prime Finite Fields
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math\PrimeField;

use phpseclib3\Math\Common\FiniteField\Integer as Base;
use phpseclib3\Math\BigInteger;
use ParagonIE\ConstantTime\Hex;
/**
 * Prime Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Integer extends Base
{
    /**
     * Holds the PrimeField's value
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected $value;
    /**
     * Keeps track of current instance
     *
     * @var int
     */
    protected $instanceID;
    /**
     * Holds the PrimeField's modulo
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected static $modulo;
    /**
     * Holds a pre-generated function to perform modulo reductions
     *
     * @var Callable
     */
    protected static $reduce;
    /**
     * Zero
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected static $zero;
    /**
     * Default constructor
     */
    public function __construct($instanceID, BigInteger $num = null)
    {
        $this->instanceID = $instanceID;
        if (!isset($num)) {
            $this->value = clone static::$zero;
        } else {
            $reduce = static::$reduce[$instanceID];
            $this->value = $reduce($num);
        }
    }
    /**
     * Set the modulo for a given instance
     */
    public static function setModulo($instanceID, BigInteger $modulo)
    {
        static::$modulo[$instanceID] = $modulo;
    }
    /**
     * Set the modulo for a given instance
     */
    public static function setRecurringModuloFunction($instanceID, callable $function)
    {
        static::$reduce[$instanceID] = $function;
        if (!isset(static::$zero)) {
            static::$zero = new BigInteger();
        }
    }
    /**
     * Delete the modulo for a given instance
     */
    public static function cleanupCache($instanceID)
    {
        unset(static::$modulo[$instanceID]);
        unset(static::$reduce[$instanceID]);
    }
    /**
     * Returns the modulo
     *
     * @return integer
     */
    public static function getModulo($instanceID)
    {
        return static::$modulo[$instanceID];
    }
    /**
     * Tests a parameter to see if it's of the right instance
     *
     * Throws an exception if the incorrect class is being utilized
     */
    public static function checkInstance(self $x, self $y)
    {
        if ($x->instanceID != $y->instanceID) {
            throw new \UnexpectedValueException('The instances of the two PrimeField\\Integer objects do not match');
        }
    }
    /**
     * Tests the equality of two numbers.
     *
     * @return bool
     */
    public function equals(self $x)
    {
        static::checkInstance($this, $x);
        return $this->value->equals($x->value);
    }
    /**
     * Compares two numbers.
     *
     * @return int
     */
    public function compare(self $x)
    {
        static::checkInstance($this, $x);
        return $this->value->compare($x->value);
    }
    /**
     * Adds two PrimeFieldIntegers.
     *
     * @return static
     */
    public function add(self $x)
    {
        static::checkInstance($this, $x);
        $temp = new static($this->instanceID);
        $temp->value = $this->value->add($x->value);
        if ($temp->value->compare(static::$modulo[$this->instanceID]) >= 0) {
            $temp->value = $temp->value->subtract(static::$modulo[$this->instanceID]);
        }
        return $temp;
    }
    /**
     * Subtracts two PrimeFieldIntegers.
     *
     * @return static
     */
    public function subtract(self $x)
    {
        static::checkInstance($this, $x);
        $temp = new static($this->instanceID);
        $temp->value = $this->value->subtract($x->value);
        if ($temp->value->isNegative()) {
            $temp->value = $temp->value->add(static::$modulo[$this->instanceID]);
        }
        return $temp;
    }
    /**
     * Multiplies two PrimeFieldIntegers.
     *
     * @return static
     */
    public function multiply(self $x)
    {
        static::checkInstance($this, $x);
        return new static($this->instanceID, $this->value->multiply($x->value));
    }
    /**
     * Divides two PrimeFieldIntegers.
     *
     * @return static
     */
    public function divide(self $x)
    {
        static::checkInstance($this, $x);
        $denominator = $x->value->modInverse(static::$modulo[$this->instanceID]);
        return new static($this->instanceID, $this->value->multiply($denominator));
    }
    /**
     * Performs power operation on a PrimeFieldInteger.
     *
     * @return static
     */
    public function pow(BigInteger $x)
    {
        $temp = new static($this->instanceID);
        $temp->value = $this->value->powMod($x, static::$modulo[$this->instanceID]);
        return $temp;
    }
    /**
     * Calculates the square root
     *
     * @link https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm
     * @return (static | false)
     */
    public function squareRoot()
    {
        static $one, $two;
        if (!isset($one)) {
            $one = new BigInteger(1);
            $two = new BigInteger(2);
        }
        $reduce = static::$reduce[$this->instanceID];
        $p_1 = static::$modulo[$this->instanceID]->subtract($one);
        $q = clone $p_1;
        $s = BigInteger::scan1divide($q);
        list($pow) = $p_1->divide($two);
        for ($z = $one; !$z->equals(static::$modulo[$this->instanceID]); $z = $z->add($one)) {
            $temp = $z->powMod($pow, static::$modulo[$this->instanceID]);
            if ($temp->equals($p_1)) {
                break;
            }
        }
        $m = new BigInteger($s);
        $c = $z->powMod($q, static::$modulo[$this->instanceID]);
        $t = $this->value->powMod($q, static::$modulo[$this->instanceID]);
        list($temp) = $q->add($one)->divide($two);
        $r = $this->value->powMod($temp, static::$modulo[$this->instanceID]);
        while (!$t->equals($one)) {
            $i = clone $one;
            while (!$t->powMod($two->pow($i), static::$modulo[$this->instanceID])->equals($one)) {
                $i = $i->add($one);
            }
            if ($i->compare($m) >= 0) {
                return false;
            }
            $b = $c->powMod($two->pow($m->subtract($i)->subtract($one)), static::$modulo[$this->instanceID]);
            $m = $i;
            $c = $reduce($b->multiply($b));
            $t = $reduce($t->multiply($c));
            $r = $reduce($r->multiply($b));
        }
        return new static($this->instanceID, $r);
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return $this->value->isOdd();
    }
    /**
    * Negate
    *
    * A negative number can be written as 0-12. With modulos, 0 is the same thing as the modulo
    so 0-12 is the same thing as modulo-12
    *
    * @return object
    */
    public function negate()
    {
        return new static($this->instanceID, static::$modulo[$this->instanceID]->subtract($this->value));
    }
    /**
     * Converts an Integer to a byte string (eg. base-256).
     *
     * @return string
     */
    public function toBytes()
    {
        $length = static::$modulo[$this->instanceID]->getLengthInBytes();
        return str_pad($this->value->toBytes(), $length, "\x00", STR_PAD_LEFT);
    }
    /**
     * Converts an Integer to a hex string (eg. base-16).
     *
     * @return string
     */
    public function toHex()
    {
        return Hex::encode($this->toBytes());
    }
    /**
     * Converts an Integer to a bit string (eg. base-2).
     *
     * @return string
     */
    public function toBits()
    {
        // return $this->value->toBits();
        static $length;
        if (!isset($length)) {
            $length = static::$modulo[$this->instanceID]->getLength();
        }
        return str_pad($this->value->toBits(), $length, '0', STR_PAD_LEFT);
    }
    /**
     * Returns the w-ary non-adjacent form (wNAF)
     *
     * @param int $w optional
     * @return int[]
     */
    public function getNAF($w = 1)
    {
        $w++;
        $mask = new BigInteger((1 << $w) - 1);
        $sub = new BigInteger(1 << $w);
        //$sub = new BigInteger(1 << ($w - 1));
        $d = $this->toBigInteger();
        $d_i = [];
        $i = 0;
        while ($d->compare(static::$zero) > 0) {
            if ($d->isOdd()) {
                // start mods
                $d_i[$i] = $d->testBit($w - 1) ? $d->bitwise_and($mask)->subtract($sub) : $d->bitwise_and($mask);
                // end mods
                $d = $d->subtract($d_i[$i]);
                $d_i[$i] = (int) $d_i[$i]->toString();
            } else {
                $d_i[$i] = 0;
            }
            $shift = !$d->equals(static::$zero) && $d->bitwise_and($mask)->equals(static::$zero) ? $w : 1;
            // $w or $w + 1?
            $d = $d->bitwise_rightShift($shift);
            while (--$shift > 0) {
                $d_i[++$i] = 0;
            }
            $i++;
        }
        return $d_i;
    }
    /**
     * Converts an Integer to a BigInteger
     *
     * @return string
     */
    public function toBigInteger()
    {
        return clone $this->value;
    }
    /**
     * __toString() magic method
     *
     * @access public
     */
    public function __toString()
    {
        return (string) $this->value;
    }
    /**
     * __debugInfo() magic method
     *
     * @access public
     */
    public function __debugInfo()
    {
        return ['value' => $this->toHex()];
    }
}<?php

/**
 * Binary Finite Fields
 *
 * Utilizes the factory design pattern
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Math\Common\FiniteField;
use phpseclib3\Math\BinaryField\Integer;
use phpseclib3\Common\Functions\Strings;
/**
 * Binary Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class BinaryField extends FiniteField
{
    /**
     * Instance Counter
     *
     * @var int
     */
    private static $instanceCounter = 0;
    /**
     * Keeps track of current instance
     *
     * @var int
     */
    protected $instanceID;
    /**
     * Default constructor
     */
    public function __construct(...$indices)
    {
        $m = array_shift($indices);
        $val = str_repeat('0', $m) . '1';
        foreach ($indices as $index) {
            $val[$index] = '1';
        }
        $modulo = static::base2ToBase256(strrev($val));
        $mStart = 2 * $m - 2;
        $t = ceil($m / 8);
        $finalMask = chr((1 << $m % 8) - 1);
        if ($finalMask == "\x00") {
            $finalMask = "\xff";
        }
        $bitLen = $mStart + 1;
        $pad = ceil($bitLen / 8);
        $h = $bitLen & 7;
        $h = $h ? 8 - $h : 0;
        $r = rtrim(\Phabel\Target\Php80\Polyfill::substr($val, 0, -1), '0');
        $u = [static::base2ToBase256(strrev($r))];
        for ($i = 1; $i < 8; $i++) {
            $u[] = static::base2ToBase256(strrev(str_repeat('0', $i) . $r));
        }
        // implements algorithm 2.40 (in section 2.3.5) in "Guide to Elliptic Curve Cryptography"
        // with W = 8
        $reduce = function ($c) use($u, $mStart, $m, $t, $finalMask, $pad, $h) {
            $c = str_pad($c, $pad, "\x00", STR_PAD_LEFT);
            for ($i = $mStart; $i >= $m;) {
                $g = $h >> 3;
                $mask = $h & 7;
                $mask = $mask ? 1 << 7 - $mask : 0x80;
                for (; $mask > 0; $mask >>= 1, $i--, $h++) {
                    if (ord($c[$g]) & $mask) {
                        $temp = $i - $m;
                        $j = $temp >> 3;
                        $k = $temp & 7;
                        $t1 = $j ? \Phabel\Target\Php80\Polyfill::substr($c, 0, -$j) : $c;
                        $length = strlen($t1);
                        if ($length) {
                            $t2 = str_pad($u[$k], $length, "\x00", STR_PAD_LEFT);
                            $temp = $t1 ^ $t2;
                            $c = $j ? \Phabel\Target\Php80\Polyfill::substr_replace($c, $temp, 0, $length) : $temp;
                        }
                    }
                }
            }
            $c = \Phabel\Target\Php80\Polyfill::substr($c, -$t);
            if (strlen($c) == $t) {
                $c[0] = $c[0] & $finalMask;
            }
            return ltrim($c, "\x00");
        };
        $this->instanceID = self::$instanceCounter++;
        Integer::setModulo($this->instanceID, $modulo);
        Integer::setRecurringModuloFunction($this->instanceID, $reduce);
        $this->randomMax = new BigInteger($modulo, 2);
    }
    /**
     * Returns an instance of a dynamically generated PrimeFieldInteger class
     *
     * @param string $num
     * @return object
     */
    public function newInteger($num)
    {
        return new Integer($this->instanceID, $num instanceof BigInteger ? $num->toBytes() : $num);
    }
    /**
     * Returns an integer on the finite field between one and the prime modulo
     *
     * @return object
     */
    public function randomInteger()
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        return new Integer($this->instanceID, BigInteger::randomRange($one, $this->randomMax)->toBytes());
    }
    /**
     * Returns the length of the modulo in bytes
     *
     * @return integer
     */
    public function getLengthInBytes()
    {
        return strlen(Integer::getModulo($this->instanceID));
    }
    /**
     * Returns the length of the modulo in bits
     *
     * @return integer
     */
    public function getLength()
    {
        return strlen(Integer::getModulo($this->instanceID)) << 3;
    }
    /**
     * Converts a base-2 string to a base-256 string
     *
     * @param string $x
     * @param integer $size
     * @return string
     */
    public static function base2ToBase256($x, $size = null)
    {
        $str = Strings::bits2bin($x);
        $pad = strlen($x) >> 3;
        if (strlen($x) & 3) {
            $pad++;
        }
        $str = str_pad($str, $pad, "\x00", STR_PAD_LEFT);
        if (isset($size)) {
            $str = str_pad($str, $size, "\x00", STR_PAD_LEFT);
        }
        return $str;
    }
    /**
     * Converts a base-256 string to a base-2 string
     *
     * @param string $x
     * @return string
     */
    public static function base256ToBase2($x)
    {
        if (function_exists('gmp_import')) {
            return gmp_strval(gmp_import($x), 2);
        }
        return Strings::bin2bits($x);
    }
}<?php

/**
 * Finite Field Integer Base Class
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math\Common\FiniteField;

/**
 * Finite Field Integer
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Integer
{
}<?php

/**
 * Finite Fields Base Class
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math\Common;

/**
 * Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class FiniteField
{
}<?php

/**
 * Pure-PHP arbitrary precision integer arithmetic library.
 *
 * Supports base-2, base-10, base-16, and base-256 numbers.  Uses the GMP or BCMath extensions, if available,
 * and an internal implementation, otherwise.
 *
 * PHP version 5 and 7
 *
 * Here's an example of how to use this library:
 * <code>
 * <?php
 *    $a = new \phpseclib3\Math\BigInteger(2);
 *    $b = new \phpseclib3\Math\BigInteger(3);
 *
 *    $c = $a->add($b);
 *
 *    echo $c->toString(); // outputs 5
 * ?>
 * </code>
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math;

use phpseclib3\Exception\BadConfigurationException;
/**
 * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
 * numbers.
 *
 * @package BigInteger
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class BigInteger
{
    /**
     * Main Engine
     *
     * @var string
     */
    private static $mainEngine;
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    private static $modexpEngine;
    /**
     * Selected Engines
     *
     * @var array
     */
    private static $engines;
    /**
     * The actual BigInteger object
     *
     * @var object
     */
    private $value;
    /**
     * Mode independent value used for serialization.
     *
     * @see self::__sleep()
     * @see self::__wakeup()
     * @var string
     */
    private $hex;
    /**
     * Precision (used only for serialization)
     *
     * @see self::__sleep()
     * @see self::__wakeup()
     * @var int
     */
    private $precision;
    /**
     * Sets engine type.
     *
     * Throws an exception if the type is invalid
     *
     * @param string $main
     * @param array $modexps optional
     */
    public static function setEngine($main, $modexps = ['DefaultEngine'])
    {
        self::$engines = [];
        $fqmain = 'phpseclib3\\Math\\BigInteger\\Engines\\' . $main;
        if (!class_exists($fqmain) || !method_exists($fqmain, 'isValidEngine')) {
            throw new \InvalidArgumentException("{$main} is not a valid engine");
        }
        if (!$fqmain::isValidEngine()) {
            throw new BadConfigurationException("{$main} is not setup correctly on this system");
        }
        self::$mainEngine = $fqmain;
        if (!in_array('Default', $modexps)) {
            $modexps[] = 'DefaultEngine';
        }
        $found = false;
        foreach ($modexps as $modexp) {
            try {
                $fqmain::setModExpEngine($modexp);
                $found = true;
                break;
            } catch (\Exception $e) {
            }
        }
        if (!$found) {
            throw new BadConfigurationException("No valid modular exponentiation engine found for {$main}");
        }
        self::$modexpEngine = $modexp;
        self::$engines = [$main, $modexp];
    }
    /**
     * Returns the engine type
     *
     * @return string[]
     */
    public static function getEngine()
    {
        self::initialize_static_variables();
        return self::$engines;
    }
    /**
     * Initialize static variables
     */
    private static function initialize_static_variables()
    {
        if (!isset(self::$mainEngine)) {
            $engines = [['GMP'], ['PHP64', ['OpenSSL']], ['BCMath', ['OpenSSL']], ['PHP32', ['OpenSSL']]];
            foreach ($engines as $engine) {
                try {
                    self::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []);
                    break;
                } catch (\Exception $e) {
                }
            }
        }
    }
    /**
    * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
    *
    * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
    two's compliment.  The sole exception to this is -10, which is treated the same as 10 is.
    *
    * @param (string | int | BigInteger\Engines\Engine) $x Base-10 number or base-$base number if $base set.
    * @param int $base
    * @return BigInteger
    */
    public function __construct($x = 0, $base = 10)
    {
        self::initialize_static_variables();
        if (\Phabel\Plugin\NewFixer::instanceOf($x, self::$mainEngine)) {
            $this->value = clone $x;
        } elseif ($x instanceof BigInteger\Engines\Engine) {
            $this->value = new static("{$x}");
            $this->value->setPrecision($x->getPrecision());
        } else {
            $this->value = ($phabel_3129085052483abc = self::$mainEngine) || true ? new $phabel_3129085052483abc($x, $base) : false;
        }
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function toString()
    {
        return $this->value->toString();
    }
    /**
     * __toString() magic method
     */
    public function __toString()
    {
        return (string) $this->value;
    }
    /**
     * __debugInfo() magic method
     *
     * Will be called, automatically, when print_r() or var_dump() are called
     */
    public function __debugInfo()
    {
        return $this->value->__debugInfo();
    }
    /**
     * Converts a BigInteger to a byte string (eg. base-256).
     *
     * @param bool $twos_compliment
     * @return string
     */
    public function toBytes($twos_compliment = false)
    {
        return $this->value->toBytes($twos_compliment);
    }
    /**
     * Converts a BigInteger to a hex string (eg. base-16).
     *
     * @param bool $twos_compliment
     * @return string
     */
    public function toHex($twos_compliment = false)
    {
        return $this->value->toHex($twos_compliment);
    }
    /**
    * Converts a BigInteger to a bit string (eg. base-2).
    *
    * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
    saved as two's compliment.
    *
    * @param bool $twos_compliment
    * @return string
    */
    function toBits($twos_compliment = false)
    {
        return $this->value->toBits($twos_compliment);
    }
    /**
     * Adds two BigIntegers.
     *
     * @param BigInteger $y
     * @return BigInteger
     */
    public function add(BigInteger $y)
    {
        return new static($this->value->add($y->value));
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param BigInteger $y
     * @return BigInteger
     */
    function subtract(BigInteger $y)
    {
        return new static($this->value->subtract($y->value));
    }
    /**
     * Multiplies two BigIntegers
     *
     * @param BigInteger $x
     * @return BigInteger
     */
    public function multiply(BigInteger $x)
    {
        return new static($this->value->multiply($x->value));
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * Here's an example:
    <code>
    <?php
    $a = new \phpseclib3\Math\BigInteger('10');
    $b = new \phpseclib3\Math\BigInteger('20');
    *
    * list($quotient, $remainder) = $a->divide($b);
    *
    * echo $quotient->toString(); // outputs 0
    echo "\r\n";
    echo $remainder->toString(); // outputs 10
    ?>
    </code>
    *
    * @param BigInteger $y
    * @return BigInteger[]
    */
    public function divide(BigInteger $y)
    {
        list($q, $r) = $this->value->divide($y->value);
        return [new static($q), new static($r)];
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @return BigInteger
     * @param BigInteger $n
     */
    public function modInverse(BigInteger $n)
    {
        return new static($this->value->modInverse($n->value));
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @return BigInteger[]
     * @param BigInteger $n
     */
    public function extendedGCD(BigInteger $n)
    {
        extract($this->value->extendedGCD($n->value));
        /**
         * @var BigInteger $gcd
         * @var BigInteger $x
         * @var BigInteger $y
         */
        return ['gcd' => new static($gcd), 'x' => new static($x), 'y' => new static($y)];
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param BigInteger $n
     * @return BigInteger
     */
    public function gcd(BigInteger $n)
    {
        return new static($this->value->gcd($n->value));
    }
    /**
     * Absolute value.
     *
     * @return BigInteger
     * @access public
     */
    public function abs()
    {
        return new static($this->value->abs());
    }
    /**
    * Set Precision
    *
    * Some bitwise operations give different results depending on the precision being used.  Examples include left
    shift, not, and rotates.
    *
    * @param int $bits
    */
    public function setPrecision($bits)
    {
        $this->value->setPrecision($bits);
    }
    /**
     * Get Precision
     *
     * Returns the precision if it exists, false if it doesn't
     *
     * @return (int | bool)
     */
    public function getPrecision()
    {
        return $this->value->getPrecision();
    }
    /**
    * Serialize
    *
    * Will be called, automatically, when serialize() is called on a BigInteger object.
    *
    * __sleep() / __wakeup() have been around since PHP 4.0
    *
    * \Serializable was introduced in PHP 5.1 and deprecated in PHP 8.1:
    https://wiki.php.net/rfc/phase_out_serializable
    *
    * __serialize() / __unserialize() were introduced in PHP 7.4:
    https://wiki.php.net/rfc/custom_object_serialization
    *
    * @return string
    */
    public function __sleep()
    {
        $this->hex = $this->toHex(true);
        $vars = ['hex'];
        if ($this->getPrecision() > 0) {
            $vars[] = 'precision';
        }
        return $vars;
    }
    /**
     * Serialize
     *
     * Will be called, automatically, when unserialize() is called on a BigInteger object.
     */
    public function __wakeup()
    {
        $temp = new static($this->hex, -16);
        $this->value = $temp->value;
        if ($this->precision > 0) {
            // recalculate $this->bitmask
            $this->setPrecision($this->precision);
        }
    }
    /**
     * Performs modular exponentiation.
     *
     * @param BigInteger $e
     * @param BigInteger $n
     * @return BigInteger
     */
    public function powMod(BigInteger $e, BigInteger $n)
    {
        return new static($this->value->powMod($e->value, $n->value));
    }
    /**
     * Performs modular exponentiation.
     *
     * @param BigInteger $e
     * @param BigInteger $n
     * @return BigInteger
     */
    public function modPow(BigInteger $e, BigInteger $n)
    {
        return new static($this->value->modPow($e->value, $n->value));
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param BigInteger $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @access public
    * @see self::equals()
    */
    public function compare(BigInteger $y)
    {
        return $this->value->compare($y->value);
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param BigInteger $x
     * @return bool
     */
    public function equals(BigInteger $x)
    {
        return $this->value->equals($x->value);
    }
    /**
     * Logical Not
     *
     * @return BigInteger
     */
    public function bitwise_not()
    {
        return new static($this->value->bitwise_not());
    }
    /**
     * Logical And
     *
     * @param BigInteger $x
     * @return BigInteger
     */
    public function bitwise_and(BigInteger $x)
    {
        return new static($this->value->bitwise_and($x->value));
    }
    /**
     * Logical Or
     *
     * @param BigInteger $x
     * @return BigInteger
     */
    public function bitwise_or(BigInteger $x)
    {
        return new static($this->value->bitwise_or($x->value));
    }
    /**
     * Logical Exclusive Or
     *
     * @param BigInteger $x
     * @return BigInteger
     */
    public function bitwise_xor(BigInteger $x)
    {
        return new static($this->value->bitwise_xor($x->value));
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
     *
     * @param int $shift
     * @return BigInteger
     */
    public function bitwise_rightShift($shift)
    {
        return new static($this->value->bitwise_rightShift($shift));
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
     *
     * @param int $shift
     * @return BigInteger
     */
    public function bitwise_leftShift($shift)
    {
        return new static($this->value->bitwise_leftShift($shift));
    }
    /**
     * Logical Left Rotate
     *
     * Instead of the top x bits being dropped they're appended to the shifted bit string.
     *
     * @param int $shift
     * @return BigInteger
     */
    public function bitwise_leftRotate($shift)
    {
        return new static($this->value->bitwise_leftRotate($shift));
    }
    /**
     * Logical Right Rotate
     *
     * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
     *
     * @param int $shift
     * @return BigInteger
     */
    public function bitwise_rightRotate($shift)
    {
        return new static($this->value->bitwise_rightRotate($shift));
    }
    /**
     * Returns the smallest and largest n-bit number
     *
     * @param int $bits
     * @return BigInteger[]
     */
    public static function minMaxBits($bits)
    {
        self::initialize_static_variables();
        $class = self::$mainEngine;
        extract($class::minMaxBits($bits));
        /** @var BigInteger $min
         *  @var BigInteger $max
         */
        return ['min' => new static($min), 'max' => new static($max)];
    }
    /**
     * Return the size of a BigInteger in bits
     *
     * @return int
     */
    public function getLength()
    {
        return $this->value->getLength();
    }
    /**
     * Return the size of a BigInteger in bytes
     *
     * @return int
     */
    public function getLengthInBytes()
    {
        return $this->value->getLengthInBytes();
    }
    /**
     * Generates a random number of a certain size
     *
     * Bit length is equal to $size
     *
     * @param int $size
     * @return BigInteger
     */
    public static function random($size)
    {
        self::initialize_static_variables();
        $class = self::$mainEngine;
        return new static($class::random($size));
    }
    /**
     * Generates a random prime number of a certain size
     *
     * Bit length is equal to $size
     *
     * @param int $size
     * @return BigInteger
     */
    public static function randomPrime($size)
    {
        self::initialize_static_variables();
        $class = self::$mainEngine;
        return new static($class::randomPrime($size));
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param BigInteger $min
     * @param BigInteger $max
     * @return (false | BigInteger)
     */
    public static function randomRangePrime(BigInteger $min, BigInteger $max)
    {
        $class = self::$mainEngine;
        return new static($class::randomRangePrime($min->value, $max->value));
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param BigInteger $min
    * @param BigInteger $max
    * @return BigInteger
    */
    public static function randomRange(BigInteger $min, BigInteger $max)
    {
        $class = self::$mainEngine;
        return new static($class::randomRange($min->value, $max->value));
    }
    /**
    * Checks a numer to see if it's prime
    *
    * Assuming the $t parameter is not set, this function has an error rate of 2**-80.  The main motivation for the
    $t parameter is distributability.  BigInteger::randomPrime() can be distributed across multiple pageloads
    on a website instead of just one.
    *
    * @param (int | bool) $t
    * @return bool
    */
    public function isPrime($t = false)
    {
        return $this->value->isPrime($t);
    }
    /**
     * Calculates the nth root of a biginteger.
     *
     * Returns the nth root of a positive biginteger, where n defaults to 2
     *
     * @param int $n optional
     * @return BigInteger
     */
    public function root($n = 2)
    {
        return new static($this->value->root($n));
    }
    /**
     * Performs exponentiation.
     *
     * @param BigInteger $n
     * @return BigInteger
     */
    public function pow(BigInteger $n)
    {
        return new static($this->value->pow($n->value));
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param BigInteger ...$nums
     * @return BigInteger
     */
    public static function min(BigInteger ...$nums)
    {
        $class = self::$mainEngine;
        $nums = array_map(function ($num) {
            return $num->value;
        }, $nums);
        return new static($class::min(...$nums));
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param BigInteger ...$nums
     * @return BigInteger
     */
    public static function max(BigInteger ...$nums)
    {
        $class = self::$mainEngine;
        $nums = array_map(function ($num) {
            return $num->value;
        }, $nums);
        return new static($class::max(...$nums));
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param BigInteger $min
     * @param BigInteger $max
     * @return bool
     */
    public function between(BigInteger $min, BigInteger $max)
    {
        return $this->value->between($min->value, $max->value);
    }
    /**
     * Clone
     */
    public function __clone()
    {
        $this->value = clone $this->value;
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return $this->value->isOdd();
    }
    /**
     * Tests if a bit is set
     *
     * @param int $x
     * @return boolean
     */
    public function testBit($x)
    {
        return $this->value->testBit($x);
    }
    /**
     * Is Negative?
     *
     * @return boolean
     */
    public function isNegative()
    {
        return $this->value->isNegative();
    }
    /**
     * Negate
     *
     * Given $k, returns -$k
     *
     * @return BigInteger
     */
    public function negate()
    {
        return new static($this->value->negate());
    }
    /**
     * Scan for 1 and right shift by that amount
     *
     * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
     *
     * @param BigInteger $r
     * @return int
     */
    public static function scan1divide(BigInteger $r)
    {
        $class = self::$mainEngine;
        return $class::scan1divide($r->value);
    }
    /**
    * Create Recurring Modulo Function
    *
    * Sometimes it may be desirable to do repeated modulos with the same number outside of
    modular exponentiation
    *
    * @return callable
    */
    public function createRecurringModuloFunction()
    {
        $func = $this->value->createRecurringModuloFunction();
        return function (BigInteger $x) use($func) {
            return new static($func($x->value));
        };
    }
    /**
     * Bitwise Split
     *
     * Splits BigInteger's into chunks of $split bits
     *
     * @param int $split
     * @return \phpseclib3\Math\BigInteger[]
     */
    public function bitwise_split($split)
    {
        return array_map(function ($val) {
            return new static($val);
        }, $this->value->bitwise_split($split));
    }
}<?php

/**
 * OpenSSL Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\RSA\Formats\Keys\PKCS8;
use phpseclib3\Math\BigInteger;
/**
 * OpenSSL Modular Exponentiation Engine
 *
 * @package Engines
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSL
{
    /**
     * Test for engine validity
     *
     * @return bool
     */
    public static function isValidEngine()
    {
        return extension_loaded('openssl') && static::class != __CLASS__;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param Engine $x
     * @param Engine $e
     * @param Engine $n
     * @return Engine
     */
    public static function powModHelper(Engine $x, Engine $e, Engine $n)
    {
        if ($n->getLengthInBytes() < 31 || $n->getLengthInBytes() > 16384) {
            throw new \OutOfRangeException('Only modulo between 31 and 16384 bits are accepted');
        }
        $key = PKCS8::savePublicKey(new BigInteger($n), new BigInteger($e));
        $plaintext = str_pad($x->toBytes(), $n->getLengthInBytes(), "\x00", STR_PAD_LEFT);
        // this is easily prone to failure. if the modulo is a multiple of 2 or 3 or whatever it
        // won't work and you'll get a "failure: error:0906D06C:PEM routines:PEM_read_bio:no start line"
        // error. i suppose, for even numbers, we could do what PHP\Montgomery.php does, but then what
        // about odd numbers divisible by 3, by 5, etc?
        if (!openssl_public_encrypt($plaintext, $result, $key, OPENSSL_NO_PADDING)) {
            throw new \UnexpectedValueException(openssl_error_string());
        }
        $class = get_class($x);
        return new $class($result, 256);
    }
}<?php

/**
 * GMP Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\GMP;

use phpseclib3\Math\BigInteger\Engines\GMP;
/**
 * GMP Modular Exponentiation Engine
 *
 * @package GMP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DefaultEngine extends GMP
{
    /**
     * Performs modular exponentiation.
     *
     * @param GMP $x
     * @param GMP $e
     * @param GMP $n
     * @return GMP
     */
    protected static function powModHelper(GMP $x, GMP $e, GMP $n)
    {
        $temp = new GMP();
        $temp->value = gmp_powm($x->value, $e->value, $n->value);
        return $x->normalize($temp);
    }
}<?php

/**
 * Pure-PHP 32-bit BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
/**
 * Pure-PHP 32-bit Engine.
 *
 * Uses 64-bit floats if int size is 4 bits
 *
 * @package PHP32
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PHP32 extends PHP
{
    // Constants used by PHP.php
    const BASE = 26;
    const BASE_FULL = 0x4000000;
    const MAX_DIGIT = 0x3ffffff;
    const MSB = 0x2000000;
    /**
     * MAX10 in greatest MAX10LEN satisfying
     * MAX10 = 10**MAX10LEN <= 2**BASE.
     */
    const MAX10 = 10000000;
    /**
     * MAX10LEN in greatest MAX10LEN satisfying
     * MAX10 = 10**MAX10LEN <= 2**BASE.
     */
    const MAX10LEN = 7;
    const MAX_DIGIT2 = 4503599627370496;
    /**#@-*/
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    protected static $modexpEngine;
    /**
     * Engine Validity Flag
     *
     * @var bool
     */
    protected static $isValidEngine;
    /**
     * Primes > 2 and < 1000
     *
     * @var array
     */
    protected static $primes;
    /**
     * BigInteger(0)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP32
     */
    protected static $zero;
    /**
     * BigInteger(1)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP32
     */
    protected static $one;
    /**
     * BigInteger(2)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP32
     */
    protected static $two;
    /**
     * Initialize a PHP32 BigInteger Engine instance
     *
     * @param int $base
     * @see parent::initialize()
     */
    protected function initialize($base)
    {
        if ($base != 256 && $base != -256) {
            return parent::initialize($base);
        }
        $val = $this->value;
        $this->value = [];
        $vals =& $this->value;
        $i = strlen($val);
        if (!$i) {
            return;
        }
        while (true) {
            $i -= 4;
            if ($i < 0) {
                if ($i == -4) {
                    break;
                }
                $val = \Phabel\Target\Php80\Polyfill::substr($val, 0, 4 + $i);
                $val = str_pad($val, 4, "\x00", STR_PAD_LEFT);
                if ($val == "\x00\x00\x00\x00") {
                    break;
                }
                $i = 0;
            }
            list(, $digit) = unpack('N', \Phabel\Target\Php80\Polyfill::substr($val, $i, 4));
            $step = count($vals) & 3;
            if ($step) {
                $digit >>= 2 * $step;
            }
            if ($step != 3) {
                $digit &= static::MAX_DIGIT;
                $i++;
            }
            $vals[] = $digit;
        }
        while (end($vals) === 0) {
            array_pop($vals);
        }
        reset($vals);
    }
    /**
     * Test for engine validity
     *
     * @see parent::__construct()
     * @return bool
     */
    public static function isValidEngine()
    {
        return PHP_INT_SIZE >= 4;
    }
    /**
     * Adds two BigIntegers.
     *
     * @param PHP32 $y
     * @return PHP32
     */
    public function add(PHP32 $y)
    {
        $temp = self::addHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param PHP32 $y
     * @return PHP32
     */
    public function subtract(PHP32 $y)
    {
        $temp = self::subtractHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
     * Multiplies two BigIntegers.
     *
     * @param PHP32 $y
     * @return PHP32
     */
    public function multiply(PHP32 $y)
    {
        $temp = self::multiplyHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param PHP32 $y
    * @return PHP32
    */
    public function divide(PHP32 $y)
    {
        return $this->divideHelper($y);
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @param PHP32 $n
     * @return (false | PHP32)
     */
    public function modInverse(PHP32 $n)
    {
        return $this->modInverseHelper($n);
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @param PHP32 $n
     * @return PHP32[]
     */
    public function extendedGCD(PHP32 $n)
    {
        return $this->extendedGCDHelper($n);
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param PHP32 $n
     * @return PHP32
     */
    public function gcd(PHP32 $n)
    {
        return $this->extendedGCD($n)['gcd'];
    }
    /**
     * Logical And
     *
     * @param PHP32 $x
     * @return PHP32
     */
    public function bitwise_and(PHP32 $x)
    {
        return $this->bitwiseAndHelper($x);
    }
    /**
     * Logical Or
     *
     * @param PHP32 $x
     * @return PHP32
     */
    public function bitwise_or(PHP32 $x)
    {
        return $this->bitwiseOrHelper($x);
    }
    /**
     * Logical Exclusive Or
     *
     * @param PHP32 $x
     * @return PHP32
     */
    public function bitwise_xor(PHP32 $x)
    {
        return $this->bitwiseXorHelper($x);
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param PHP32 $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @access public
    * @see self::equals()
    */
    public function compare(PHP32 $y)
    {
        return $this->compareHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param PHP32 $x
     * @return bool
     */
    public function equals(PHP32 $x)
    {
        return $this->value === $x->value && $this->is_negative == $x->is_negative;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param PHP32 $e
     * @param PHP32 $n
     * @return PHP32
     */
    public function modPow(PHP32 $e, PHP32 $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * Alias for modPow().
     *
     * @param PHP32 $e
     * @param PHP32 $n
     * @return PHP32
     */
    public function powMod(PHP32 $e, PHP32 $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param PHP32 $min
     * @param PHP32 $max
     * @return (false | PHP32)
     */
    public static function randomRangePrime(PHP32 $min, PHP32 $max)
    {
        return self::randomRangePrimeOuter($min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param PHP32 $min
    * @param PHP32 $max
    * @return PHP32
    */
    public static function randomRange(PHP32 $min, PHP32 $max)
    {
        return self::randomRangeHelper($min, $max);
    }
    /**
     * Performs exponentiation.
     *
     * @param PHP32 $n
     * @return PHP32
     */
    public function pow(PHP32 $n)
    {
        return $this->powHelper($n);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param PHP32 ...$nums
     * @return PHP32
     */
    public static function min(PHP32 ...$nums)
    {
        return self::minHelper($nums);
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param PHP32 ...$nums
     * @return PHP32
     */
    public static function max(PHP32 ...$nums)
    {
        return self::maxHelper($nums);
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param PHP32 $min
     * @param PHP32 $max
     * @return bool
     */
    public function between(PHP32 $min, PHP32 $max)
    {
        return $this->compare($min) >= 0 && $this->compare($max) <= 0;
    }
}<?php

/**
 * BCMath BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Exception\BadConfigurationException;
/**
 * BCMath Engine.
 *
 * @package BCMath
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class BCMath extends Engine
{
    /**
     * Can Bitwise operations be done fast?
     *
     * @see parent::bitwise_leftRotate()
     * @see parent::bitwise_rightRotate()
     * @access protected
     */
    const FAST_BITWISE = false;
    /**
     * Engine Directory
     *
     * @see parent::setModExpEngine
     * @access protected
     */
    const ENGINE_DIR = 'BCMath';
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    protected static $modexpEngine;
    /**
     * Engine Validity Flag
     *
     * @var bool
     */
    protected static $isValidEngine;
    /**
     * BigInteger(0)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    protected static $zero;
    /**
     * BigInteger(1)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    protected static $one;
    /**
     * BigInteger(2)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    protected static $two;
    /**
     * Primes > 2 and < 1000
     *
     * @var array
     */
    protected static $primes;
    /**
     * Test for engine validity
     *
     * @see parent::__construct()
     * @return bool
     */
    public static function isValidEngine()
    {
        return extension_loaded('bcmath');
    }
    /**
     * Default constructor
     *
     * @param mixed $x integer Base-10 number or base-$base number if $base set.
     * @param int $base
     * @see parent::__construct()
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    public function __construct($x = 0, $base = 10)
    {
        if (!isset(self::$isValidEngine)) {
            self::$isValidEngine = self::isValidEngine();
        }
        if (!self::$isValidEngine) {
            throw new BadConfigurationException('BCMath is not setup correctly on this system');
        }
        $this->value = '0';
        parent::__construct($x, $base);
    }
    /**
     * Initialize a BCMath BigInteger Engine instance
     *
     * @param int $base
     * @see parent::__construct()
     */
    protected function initialize($base)
    {
        switch (abs($base)) {
            case 256:
                // round $len to the nearest 4
                $len = strlen($this->value) + 3 & 0xfffffffc;
                $x = str_pad($this->value, $len, chr(0), STR_PAD_LEFT);
                $this->value = '0';
                for ($i = 0; $i < $len; $i += 4) {
                    $this->value = bcmul($this->value, '4294967296', 0);
                    // 4294967296 == 2**32
                    $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + (ord($x[$i + 1]) << 16 | ord($x[$i + 2]) << 8 | ord($x[$i + 3])), 0);
                }
                if ($this->is_negative) {
                    $this->value = '-' . $this->value;
                }
                break;
            case 16:
                $x = strlen($this->value) & 1 ? '0' . $this->value : $this->value;
                $temp = new self(Hex::decode($x), 256);
                $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
                $this->is_negative = false;
                break;
            case 10:
                // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
                // results then doing it on '-1' does (modInverse does $x[0])
                $this->value = $this->value === '-' ? '0' : (string) $this->value;
        }
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function toString()
    {
        if ($this->value === '0') {
            return '0';
        }
        return ltrim($this->value, '0');
    }
    /**
     * Converts a BigInteger to a byte string (eg. base-256).
     *
     * @param bool $twos_compliment
     * @return string
     */
    function toBytes($twos_compliment = false)
    {
        if ($twos_compliment) {
            return $this->toBytesHelper();
        }
        $value = '';
        $current = $this->value;
        if ($current[0] == '-') {
            $current = \Phabel\Target\Php80\Polyfill::substr($current, 1);
        }
        while (bccomp($current, '0', 0) > 0) {
            $temp = bcmod($current, '16777216');
            $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
            $current = bcdiv($current, '16777216', 0);
        }
        return $this->precision > 0 ? \Phabel\Target\Php80\Polyfill::substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : ltrim($value, chr(0));
    }
    /**
     * Adds two BigIntegers.
     *
     * @param BCMath $y
     * @return BCMath
     */
    public function add(BCMath $y)
    {
        $temp = new self();
        $temp->value = bcadd($this->value, $y->value);
        return $this->normalize($temp);
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param BCMath $y
     * @return BCMath
     */
    public function subtract(BCMath $y)
    {
        $temp = new self();
        $temp->value = bcsub($this->value, $y->value);
        return $this->normalize($temp);
    }
    /**
     * Multiplies two BigIntegers.
     *
     * @param BCMath $x
     * @return BCMath
     */
    public function multiply(BCMath $x)
    {
        $temp = new self();
        $temp->value = bcmul($this->value, $x->value);
        return $this->normalize($temp);
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param BCMath $y
    * @return BCMath
    */
    public function divide(BCMath $y)
    {
        $quotient = new self();
        $remainder = new self();
        $quotient->value = bcdiv($this->value, $y->value, 0);
        $remainder->value = bcmod($this->value, $y->value);
        if ($remainder->value[0] == '-') {
            $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? \Phabel\Target\Php80\Polyfill::substr($y->value, 1) : $y->value, 0);
        }
        return [$this->normalize($quotient), $this->normalize($remainder)];
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     *
     * @return (false | BCMath)
     * @param \phpseclib3\Math\BigInteger\Engines\BCMath $n
     */
    public function modInverse(BCMath $n)
    {
        return $this->modInverseHelper($n);
    }
    /**
    * Calculates the greatest common divisor and Bezout's identity.
    *
    * Say you have 693 and 609.  The GCD is 21.  Bezout's identity states that there exist integers x and y such that
    693*x + 609*y == 21.  In point of fact, there are actually an infinite number of x and y combinations and which
    combination is returned is dependent upon which mode is in use.  See
    {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
    *
    * @param BCMath $n
    * @return BCMath
    */
    public function extendedGCD(BCMath $n)
    {
        // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
        // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway.  as is,
        // the basic extended euclidean algorithim is what we're using.
        $u = $this->value;
        $v = $n->value;
        $a = '1';
        $b = '0';
        $c = '0';
        $d = '1';
        while (bccomp($v, '0', 0) != 0) {
            $q = bcdiv($u, $v, 0);
            $temp = $u;
            $u = $v;
            $v = bcsub($temp, bcmul($v, $q, 0), 0);
            $temp = $a;
            $a = $c;
            $c = bcsub($temp, bcmul($a, $q, 0), 0);
            $temp = $b;
            $b = $d;
            $d = bcsub($temp, bcmul($b, $q, 0), 0);
        }
        return ['gcd' => $this->normalize(new static($u)), 'x' => $this->normalize(new static($a)), 'y' => $this->normalize(new static($b))];
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param BCMath $n
     * @return BCMath
     */
    public function gcd(BCMath $n)
    {
        extract($this->extendedGCD($n));
        /** @var BCMath $gcd */
        return $gcd;
    }
    /**
     * Absolute value.
     *
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    public function abs()
    {
        $temp = new static();
        $temp->value = strlen($this->value) && $this->value[0] == '-' ? \Phabel\Target\Php80\Polyfill::substr($this->value, 1) : $this->value;
        return $temp;
    }
    /**
     * Logical And
     *
     * @param BCMath $x
     * @return BCMath
     */
    public function bitwise_and(BCMath $x)
    {
        return $this->bitwiseAndHelper($x);
    }
    /**
     * Logical Or
     *
     * @param BCMath $x
     * @return BCMath
     */
    public function bitwise_or(BCMath $x)
    {
        return $this->bitwiseXorHelper($x);
    }
    /**
     * Logical Exclusive Or
     *
     * @param BCMath $x
     * @return BCMath
     */
    public function bitwise_xor(BCMath $x)
    {
        return $this->bitwiseXorHelper($x);
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    public function bitwise_rightShift($shift)
    {
        $temp = new static();
        $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0);
        return $this->normalize($temp);
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    public function bitwise_leftShift($shift)
    {
        $temp = new static();
        $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0);
        return $this->normalize($temp);
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param BCMath $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @see self::equals()
    */
    public function compare(BCMath $y)
    {
        return bccomp($this->value, $y->value, 0);
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param BCMath $x
     * @return bool
     */
    public function equals(BCMath $x)
    {
        return $this->value == $x->value;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param BCMath $e
     * @param BCMath $n
     * @return BCMath
     */
    public function modPow(BCMath $e, BCMath $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * Alias for modPow().
     *
     * @param BCMath $e
     * @param BCMath $n
     * @return BCMath
     */
    public function powMod(BCMath $e, BCMath $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * @param BCMath $e
     * @param BCMath $n
     * @return BCMath
     */
    protected function powModInner(BCMath $e, BCMath $n)
    {
        try {
            $class = self::$modexpEngine;
            return $class::powModHelper($this, $e, $n, static::class);
        } catch (\Exception $err) {
            return BCMath\DefaultEngine::powModHelper($this, $e, $n, static::class);
        }
    }
    /**
     * Normalize
     *
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
     *
     * @param BCMath $result
     * @return BCMath
     */
    protected function normalize(BCMath $result)
    {
        $result->precision = $this->precision;
        $result->bitmask = $this->bitmask;
        if ($result->bitmask !== false) {
            $result->value = bcmod($result->value, $result->bitmask->value);
        }
        return $result;
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param BCMath $min
     * @param BCMath $max
     * @return (false | BCMath)
     */
    public static function randomRangePrime(BCMath $min, BCMath $max)
    {
        return self::randomRangePrimeOuter($min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param BCMath $min
    * @param BCMath $max
    * @return BCMath
    */
    public static function randomRange(BCMath $min, BCMath $max)
    {
        return self::randomRangeHelper($min, $max);
    }
    /**
     * Make the current number odd
     *
     * If the current number is odd it'll be unchanged.  If it's even, one will be added to it.
     *
     * @see self::randomPrime()
     */
    protected function make_odd()
    {
        if (!$this->isOdd()) {
            $this->value = bcadd($this->value, '1');
        }
    }
    /**
     * Test the number against small primes.
     *
     * @see self::isPrime()
     */
    protected function testSmallPrimes()
    {
        if ($this->value === '1') {
            return false;
        }
        if ($this->value === '2') {
            return true;
        }
        if ($this->value[strlen($this->value) - 1] % 2 == 0) {
            return false;
        }
        $value = $this->value;
        foreach (self::$primes as $prime) {
            $r = bcmod($this->value, $prime);
            if ($r == '0') {
                return $this->value == $prime;
            }
        }
        return true;
    }
    /**
     * Scan for 1 and right shift by that amount
     *
     * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
     *
     * @see self::isPrime()
     * @param BCMath $r
     * @return int
     */
    public static function scan1divide(BCMath $r)
    {
        $r_value =& $r->value;
        $s = 0;
        // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals(static::$one) check earlier
        while ($r_value[strlen($r_value) - 1] % 2 == 0) {
            $r_value = bcdiv($r_value, '2', 0);
            ++$s;
        }
        return $s;
    }
    /**
     * Performs exponentiation.
     *
     * @param BCMath $n
     * @return BCMath
     */
    public function pow(BCMath $n)
    {
        $temp = new self();
        $temp->value = bcpow($this->value, $n->value);
        return $this->normalize($temp);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param BCMath ...$nums
     * @return BCMath
     */
    public static function min(BCMath ...$nums)
    {
        return self::minHelper($nums);
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param BCMath ...$nums
     * @return BCMath
     */
    public static function max(BCMath ...$nums)
    {
        return self::maxHelper($nums);
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param BCMath $min
     * @param BCMath $max
     * @return bool
     */
    public function between(BCMath $min, BCMath $max)
    {
        return $this->compare($min) >= 0 && $this->compare($max) <= 0;
    }
    /**
     * Set Bitmask
     *
     * @return Engine
     * @param int $bits
     * @see self::setPrecision()
     */
    protected static function setBitmask($bits)
    {
        $temp = parent::setBitmask($bits);
        return $temp->add(static::$one);
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return $this->value[strlen($this->value) - 1] % 2 == 1;
    }
    /**
     * Tests if a bit is set
     *
     * @return boolean
     */
    public function testBit($x)
    {
        return bccomp(bcmod($this->value, bcpow('2', $x + 1, 0), 0), bcpow('2', $x, 0), 0) >= 0;
    }
    /**
     * Is Negative?
     *
     * @return boolean
     */
    public function isNegative()
    {
        return strlen($this->value) && $this->value[0] == '-';
    }
    /**
     * Negate
     *
     * Given $k, returns -$k
     *
     * @return BCMath
     */
    public function negate()
    {
        $temp = clone $this;
        if (!strlen($temp->value)) {
            return $temp;
        }
        $temp->value = $temp->value[0] == '-' ? \Phabel\Target\Php80\Polyfill::substr($this->value, 1) : '-' . $this->value;
        return $temp;
    }
}<?php

/**
 * Base BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Exception\BadConfigurationException;
use phpseclib3\Crypt\Random;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
/**
 * Base Engine.
 *
 * @package Engine
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Engine
{
    /**
     * Holds the BigInteger's value
     *
     * @var mixed
     */
    protected $value;
    /**
     * Holds the BigInteger's sign
     *
     * @var bool
     */
    protected $is_negative;
    /**
     * Precision
     *
     * @see static::setPrecision()
     */
    protected $precision = -1;
    /**
     * Precision Bitmask
     *
     * @see static::setPrecision()
     */
    protected $bitmask = false;
    /**
     * Recurring Modulo Function
     *
     * @var callable
     */
    protected $reduce;
    /**
     * Mode independent value used for serialization.
     *
     * @see self::__sleep()
     * @see self::__wakeup()
     * @var string
     */
    protected $hex;
    /**
     * Default constructor
     *
     * @param mixed $x integer Base-10 number or base-$base number if $base set.
     * @param int $base
     */
    public function __construct($x, $base)
    {
        if (!isset(static::$primes)) {
            static::$primes = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];
            static::$zero = new static(0);
            static::$one = new static(1);
            static::$two = new static(2);
        }
        // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
        // '0' is the only value like this per http://php.net/empty
        if (empty($x) && (abs($base) != 256 || $x !== '0')) {
            return;
        }
        switch ($base) {
            case -256:
            case 256:
                if ($base == -256 && ord($x[0]) & 0x80) {
                    $this->value = ~$x;
                    $this->is_negative = true;
                } else {
                    $this->value = $x;
                    $this->is_negative = false;
                }
                static::initialize($base);
                if ($this->is_negative) {
                    $temp = $this->add(new static('-1'));
                    $this->value = $temp->value;
                }
                break;
            case -16:
            case 16:
                if ($base > 0 && $x[0] == '-') {
                    $this->is_negative = true;
                    $x = \Phabel\Target\Php80\Polyfill::substr($x, 1);
                }
                $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
                $is_negative = false;
                if ($base < 0 && hexdec($x[0]) >= 8) {
                    $this->is_negative = $is_negative = true;
                    $x = Hex::encode(~Hex::decode($x));
                }
                $this->value = $x;
                static::initialize($base);
                if ($is_negative) {
                    $temp = $this->add(new static('-1'));
                    $this->value = $temp->value;
                }
                break;
            case -10:
            case 10:
                // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
                // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
                // [^-0-9].*: find any non-numeric characters and then any characters that follow that
                $this->value = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
                if (!strlen($this->value) || $this->value == '-') {
                    $this->value = '0';
                }
                static::initialize($base);
                break;
            case -2:
            case 2:
                if ($base > 0 && $x[0] == '-') {
                    $this->is_negative = true;
                    $x = \Phabel\Target\Php80\Polyfill::substr($x, 1);
                }
                $x = preg_replace('#^([01]*).*#', '$1', $x);
                $temp = new static(Strings::bits2bin($x), 128 * $base);
                // ie. either -16 or +16
                $this->value = $temp->value;
                if ($temp->is_negative) {
                    $this->is_negative = true;
                }
                break;
            default:
        }
    }
    /**
     * Sets engine type.
     *
     * Throws an exception if the type is invalid
     *
     * @param string $engine
     */
    public static function setModExpEngine($engine)
    {
        $fqengine = '\\phpseclib3\\Math\\BigInteger\\Engines\\' . static::ENGINE_DIR . '\\' . $engine;
        if (!class_exists($fqengine) || !method_exists($fqengine, 'isValidEngine')) {
            throw new \InvalidArgumentException("{$engine} is not a valid engine");
        }
        if (!$fqengine::isValidEngine()) {
            throw new BadConfigurationException("{$engine} is not setup correctly on this system");
        }
        static::$modexpEngine = $fqengine;
    }
    /**
    * Converts a BigInteger to a byte string (eg. base-256).
    *
    * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
    saved as two's compliment.
    * @return string
    */
    protected function toBytesHelper()
    {
        $comparison = $this->compare(new static());
        if ($comparison == 0) {
            return $this->precision > 0 ? str_repeat(chr(0), $this->precision + 1 >> 3) : '';
        }
        $temp = $comparison < 0 ? $this->add(new static(1)) : $this;
        $bytes = $temp->toBytes();
        if (!strlen($bytes)) {
            // eg. if the number we're trying to convert is -1
            $bytes = chr(0);
        }
        if (ord($bytes[0]) & 0x80) {
            $bytes = chr(0) . $bytes;
        }
        return $comparison < 0 ? ~$bytes : $bytes;
    }
    /**
     * Converts a BigInteger to a hex string (eg. base-16).
     *
     * @param bool $twos_compliment
     * @return string
     */
    public function toHex($twos_compliment = false)
    {
        return Hex::encode($this->toBytes($twos_compliment));
    }
    /**
    * Converts a BigInteger to a bit string (eg. base-2).
    *
    * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
    saved as two's compliment.
    *
    * @param bool $twos_compliment
    * @return string
    */
    public function toBits($twos_compliment = false)
    {
        $hex = $this->toBytes($twos_compliment);
        $bits = Strings::bin2bits($hex);
        $result = $this->precision > 0 ? \Phabel\Target\Php80\Polyfill::substr($bits, -$this->precision) : ltrim($bits, '0');
        if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
            return '0' . $result;
        }
        return $result;
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     *
     * {@internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.}
     *
     * @param \phpseclib3\Math\BigInteger\Engines\Engine $n
     * @return (\phpseclib3\Math\BigInteger\Engines\Engine | false)
     */
    protected function modInverseHelper(Engine $n)
    {
        // $x mod -$n == $x mod $n.
        $n = $n->abs();
        if ($this->compare(static::$zero) < 0) {
            $temp = $this->abs();
            $temp = $temp->modInverse($n);
            return $this->normalize($n->subtract($temp));
        }
        extract($this->extendedGCD($n));
        /**
         * @var BigInteger $gcd
         * @var BigInteger $x
         */
        if (!$gcd->equals(static::$one)) {
            return false;
        }
        $x = $x->compare(static::$zero) < 0 ? $x->add($n) : $x;
        return $this->compare(static::$zero) < 0 ? $this->normalize($n->subtract($x)) : $this->normalize($x);
    }
    /**
     * Serialize
     *
     * Will be called, automatically, when serialize() is called on a BigInteger object.
     *
     * @return string
     */
    public function __sleep()
    {
        $this->hex = $this->toHex(true);
        $vars = ['hex'];
        if ($this->precision > 0) {
            $vars[] = 'precision';
        }
        return $vars;
    }
    /**
     * Serialize
     *
     * Will be called, automatically, when unserialize() is called on a BigInteger object.
     */
    public function __wakeup()
    {
        $temp = new static($this->hex, -16);
        $this->value = $temp->value;
        $this->is_negative = $temp->is_negative;
        if ($this->precision > 0) {
            // recalculate $this->bitmask
            $this->setPrecision($this->precision);
        }
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toString();
    }
    /**
     * __debugInfo() magic method
     *
     * Will be called, automatically, when print_r() or var_dump() are called
     */
    public function __debugInfo()
    {
        return ['value' => '0x' . $this->toHex(true), 'engine' => basename(static::class)];
    }
    /**
    * Set Precision
    *
    * Some bitwise operations give different results depending on the precision being used.  Examples include left
    shift, not, and rotates.
    *
    * @param int $bits
    */
    public function setPrecision($bits)
    {
        if ($bits < 1) {
            $this->precision = -1;
            $this->bitmask = false;
            return;
        }
        $this->precision = $bits;
        $this->bitmask = static::setBitmask($bits);
        $temp = $this->normalize($this);
        $this->value = $temp->value;
    }
    /**
     * Get Precision
     *
     * Returns the precision if it exists, -1 if it doesn't
     *
     * @return int
     */
    public function getPrecision()
    {
        return $this->precision;
    }
    /**
     * Set Bitmask
     * @return Engine
     * @param int $bits
     * @see self::setPrecision()
     */
    protected static function setBitmask($bits)
    {
        return new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xff), $bits >> 3), 256);
    }
    /**
     * Logical Not
     *
     * @return (Engine | string)
     */
    public function bitwise_not()
    {
        // calculuate "not" without regard to $this->precision
        // (will always result in a smaller number.  ie. ~1 isn't 1111 1110 - it's 0)
        $temp = $this->toBytes();
        if ($temp == '') {
            return $this->normalize(static::$zero);
        }
        $pre_msb = decbin(ord($temp[0]));
        $temp = ~$temp;
        $msb = decbin(ord($temp[0]));
        if (strlen($msb) == 8) {
            $msb = \Phabel\Target\Php80\Polyfill::substr($msb, strpos($msb, '0'));
        }
        $temp[0] = chr(bindec($msb));
        // see if we need to add extra leading 1's
        $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8;
        $new_bits = $this->precision - $current_bits;
        if ($new_bits <= 0) {
            return $this->normalize(new static($temp, 256));
        }
        // generate as many leading 1's as we need to.
        $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xff), $new_bits >> 3);
        self::base256_lshift($leading_ones, $current_bits);
        $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT);
        return $this->normalize(new static($leading_ones | $temp, 256));
    }
    /**
     * Logical Left Shift
     *
     * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
     *
     * @param string $x
     * @param int $shift
     * @return string
     */
    protected static function base256_lshift(&$x, $shift)
    {
        if ($shift == 0) {
            return;
        }
        $num_bytes = $shift >> 3;
        // eg. floor($shift/8)
        $shift &= 7;
        // eg. $shift % 8
        $carry = 0;
        for ($i = strlen($x) - 1; $i >= 0; --$i) {
            $temp = ord($x[$i]) << $shift | $carry;
            $x[$i] = chr($temp);
            $carry = $temp >> 8;
        }
        $carry = $carry != 0 ? chr($carry) : '';
        $x = $carry . $x . str_repeat(chr(0), $num_bytes);
    }
    /**
     * Logical Left Rotate
     *
     * Instead of the top x bits being dropped they're appended to the shifted bit string.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    public function bitwise_leftRotate($shift)
    {
        $bits = $this->toBytes();
        if ($this->precision > 0) {
            $precision = $this->precision;
            if (static::FAST_BITWISE) {
                $mask = $this->bitmask->toBytes();
            } else {
                $mask = $this->bitmask->subtract(new static(1));
                $mask = $mask->toBytes();
            }
        } else {
            $temp = ord($bits[0]);
            for ($i = 0; $temp >> $i; ++$i) {
            }
            $precision = 8 * strlen($bits) - 8 + $i;
            $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xff), $precision >> 3);
        }
        if ($shift < 0) {
            $shift += $precision;
        }
        $shift %= $precision;
        if (!$shift) {
            return clone $this;
        }
        $left = $this->bitwise_leftShift($shift);
        $left = $left->bitwise_and(new static($mask, 256));
        $right = $this->bitwise_rightShift($precision - $shift);
        $result = static::FAST_BITWISE ? $left->bitwise_or($right) : $left->add($right);
        return $this->normalize($result);
    }
    /**
     * Logical Right Rotate
     *
     * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    public function bitwise_rightRotate($shift)
    {
        return $this->bitwise_leftRotate(-$shift);
    }
    /**
     * Returns the smallest and largest n-bit number
     *
     * @param int $bits
     * @return \phpseclib3\Math\BigInteger\Engines\Engine[]
     */
    public static function minMaxBits($bits)
    {
        $bytes = $bits >> 3;
        $min = str_repeat(chr(0), $bytes);
        $max = str_repeat(chr(0xff), $bytes);
        $msb = $bits & 7;
        if ($msb) {
            $min = chr(1 << $msb - 1) . $min;
            $max = chr((1 << $msb) - 1) . $max;
        } else {
            $min[0] = chr(0x80);
        }
        return ['min' => new static($min, 256), 'max' => new static($max, 256)];
    }
    /**
     * Return the size of a BigInteger in bits
     *
     * @return int
     */
    public function getLength()
    {
        return strlen($this->toBits());
    }
    /**
     * Return the size of a BigInteger in bytes
     *
     * @return int
     */
    public function getLengthInBytes()
    {
        return strlen($this->toBytes());
    }
    /**
     * Performs some pre-processing for powMod
     *
     * @param Engine $e
     * @param Engine $n
     * @return (bool | Engine)
     */
    protected function powModOuter(Engine $e, Engine $n)
    {
        $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
        if ($e->compare(new static()) < 0) {
            $e = $e->abs();
            $temp = $this->modInverse($n);
            if ($temp === false) {
                return false;
            }
            return $this->normalize($temp->powModInner($e, $n));
        }
        return $this->powModInner($e, $n);
    }
    /**
    * Sliding Window k-ary Modular Exponentiation
    *
    * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}.  In a departure from those algorithims,
    however, this function performs a modular reduction after every multiplication and squaring operation.
    As such, this function has the same preconditions that the reductions being used do.
    *
    * @param \phpseclib3\Math\BigInteger\Engines\Engine $x
    * @param \phpseclib3\Math\BigInteger\Engines\Engine $e
    * @param \phpseclib3\Math\BigInteger\Engines\Engine $n
    * @param string $class
    * @return \phpseclib3\Math\BigInteger\Engines\Engine
    */
    protected static function slidingWindow(Engine $x, Engine $e, Engine $n, $class)
    {
        static $window_ranges = [7, 25, 81, 241, 673, 1793];
        // from BigInteger.java's oddModPow function
        //static $window_ranges = [0, 7, 36, 140, 450, 1303, 3529]; // from MPM 7.3.1
        $e_bits = $e->toBits();
        $e_length = strlen($e_bits);
        // calculate the appropriate window size.
        // $window_size == 3 if $window_ranges is between 25 and 81, for example.
        for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) {
        }
        $n_value = $n->value;
        if (method_exists(static::class, 'generateCustomReduction')) {
            static::generateCustomReduction($n, $class);
        }
        // precompute $this^0 through $this^$window_size
        $powers = [];
        $powers[1] = static::prepareReduce($x->value, $n_value, $class);
        $powers[2] = static::squareReduce($powers[1], $n_value, $class);
        // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end
        // in a 1.  ie. it's supposed to be odd.
        $temp = 1 << $window_size - 1;
        for ($i = 1; $i < $temp; ++$i) {
            $i2 = $i << 1;
            $powers[$i2 + 1] = static::multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $class);
        }
        $result = new $class(1);
        $result = static::prepareReduce($result->value, $n_value, $class);
        for ($i = 0; $i < $e_length;) {
            if (!$e_bits[$i]) {
                $result = static::squareReduce($result, $n_value, $class);
                ++$i;
            } else {
                for ($j = $window_size - 1; $j > 0; --$j) {
                    if (!empty($e_bits[$i + $j])) {
                        break;
                    }
                }
                // eg. the length of substr($e_bits, $i, $j + 1)
                for ($k = 0; $k <= $j; ++$k) {
                    $result = static::squareReduce($result, $n_value, $class);
                }
                $result = static::multiplyReduce($result, $powers[bindec(\Phabel\Target\Php80\Polyfill::substr($e_bits, $i, $j + 1))], $n_value, $class);
                $i += $j + 1;
            }
        }
        $temp = new $class();
        $temp->value = static::reduce($result, $n_value, $class);
        return $temp;
    }
    /**
     * Generates a random number of a certain size
     *
     * Bit length is equal to $size
     *
     * @param int $size
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    public static function random($size)
    {
        extract(static::minMaxBits($size));
        /**
         * @var BigInteger $min
         * @var BigInteger $max
         */
        return static::randomRange($min, $max);
    }
    /**
     * Generates a random prime number of a certain size
     *
     * Bit length is equal to $size
     *
     * @param int $size
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    public static function randomPrime($size)
    {
        extract(static::minMaxBits($size));
        /**
         * @var BigInteger $min
         * @var BigInteger $max
         */
        return static::randomRangePrime($min, $max);
    }
    /**
     * Performs some pre-processing for randomRangePrime
     *
     * @param Engine $min
     * @param Engine $max
     * @return (bool | Engine)
     */
    protected static function randomRangePrimeOuter(Engine $min, Engine $max)
    {
        $compare = $max->compare($min);
        if (!$compare) {
            return $min->isPrime() ? $min : false;
        } elseif ($compare < 0) {
            // if $min is bigger then $max, swap $min and $max
            $temp = $max;
            $max = $min;
            $min = $temp;
        }
        $x = static::randomRange($min, $max);
        return static::randomRangePrimeInner($x, $min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param Engine $min
    * @param Engine $max
    * @return Engine
    */
    protected static function randomRangeHelper(Engine $min, Engine $max)
    {
        $compare = $max->compare($min);
        if (!$compare) {
            return $min;
        } elseif ($compare < 0) {
            // if $min is bigger then $max, swap $min and $max
            $temp = $max;
            $max = $min;
            $min = $temp;
        }
        if (!isset(static::$one)) {
            static::$one = new static(1);
        }
        $max = $max->subtract($min->subtract(static::$one));
        $size = strlen(ltrim($max->toBytes(), chr(0)));
        /*
            doing $random % $max doesn't work because some numbers will be more likely to occur than others.
            eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145
            would produce 5 whereas the only value of random that could produce 139 would be 139. ie.
            not all numbers would be equally likely. some would be more likely than others.
        
            creating a whole new random number until you find one that is within the range doesn't work
            because, for sufficiently small ranges, the likelihood that you'd get a number within that range
            would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability
            would be pretty high that $random would be greater than $max.
        
            phpseclib works around this using the technique described here:
        
            http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string
        */
        $random_max = new static(chr(1) . str_repeat("\x00", $size), 256);
        $random = new static(Random::string($size), 256);
        list($max_multiple) = $random_max->divide($max);
        $max_multiple = $max_multiple->multiply($max);
        while ($random->compare($max_multiple) >= 0) {
            $random = $random->subtract($max_multiple);
            $random_max = $random_max->subtract($max_multiple);
            $random = $random->bitwise_leftShift(8);
            $random = $random->add(new static(Random::string(1), 256));
            $random_max = $random_max->bitwise_leftShift(8);
            list($max_multiple) = $random_max->divide($max);
            $max_multiple = $max_multiple->multiply($max);
        }
        list(, $random) = $random->divide($max);
        return $random->add($min);
    }
    /**
     * Performs some post-processing for randomRangePrime
     *
     * @param Engine $x
     * @param Engine $min
     * @param Engine $max
     * @return (bool | Engine)
     */
    protected static function randomRangePrimeInner(Engine $x, Engine $min, Engine $max)
    {
        if (!isset(static::$two)) {
            static::$two = new static('2');
        }
        $x->make_odd();
        if ($x->compare($max) > 0) {
            // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range
            if ($min->equals($max)) {
                return false;
            }
            $x = clone $min;
            $x->make_odd();
        }
        $initial_x = clone $x;
        while (true) {
            if ($x->isPrime()) {
                return $x;
            }
            $x = $x->add(static::$two);
            if ($x->compare($max) > 0) {
                $x = clone $min;
                if ($x->equals(static::$two)) {
                    return $x;
                }
                $x->make_odd();
            }
            if ($x->equals($initial_x)) {
                return false;
            }
        }
    }
    /**
     * Sets the $t parameter for primality testing
     *
     * @return int
     */
    protected function setupIsPrime()
    {
        $length = $this->getLengthInBytes();
        // see HAC 4.49 "Note (controlling the error probability)"
        // @codingStandardsIgnoreStart
        if ($length >= 163) {
            $t = 2;
        } else {
            if ($length >= 106) {
                $t = 3;
            } else {
                if ($length >= 81) {
                    $t = 4;
                } else {
                    if ($length >= 68) {
                        $t = 5;
                    } else {
                        if ($length >= 56) {
                            $t = 6;
                        } else {
                            if ($length >= 50) {
                                $t = 7;
                            } else {
                                if ($length >= 43) {
                                    $t = 8;
                                } else {
                                    if ($length >= 37) {
                                        $t = 9;
                                    } else {
                                        if ($length >= 31) {
                                            $t = 12;
                                        } else {
                                            if ($length >= 25) {
                                                $t = 15;
                                            } else {
                                                if ($length >= 18) {
                                                    $t = 18;
                                                } else {
                                                    $t = 27;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // @codingStandardsIgnoreEnd
        return $t;
    }
    /**
    * Tests Primality
    *
    * Uses the {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}.
    See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24} for more info.
    *
    * @param int $t
    * @return bool
    */
    protected function testPrimality($t)
    {
        if (!$this->testSmallPrimes()) {
            return false;
        }
        $n = clone $this;
        $n_1 = $n->subtract(static::$one);
        $n_2 = $n->subtract(static::$two);
        $r = clone $n_1;
        $s = static::scan1divide($r);
        for ($i = 0; $i < $t; ++$i) {
            $a = static::randomRange(static::$two, $n_2);
            $y = $a->modPow($r, $n);
            if (!$y->equals(static::$one) && !$y->equals($n_1)) {
                for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) {
                    $y = $y->modPow(static::$two, $n);
                    if ($y->equals(static::$one)) {
                        return false;
                    }
                }
                if (!$y->equals($n_1)) {
                    return false;
                }
            }
        }
        return true;
    }
    /**
    * Checks a numer to see if it's prime
    *
    * Assuming the $t parameter is not set, this function has an error rate of 2**-80.  The main motivation for the
    $t parameter is distributability.  BigInteger::randomPrime() can be distributed across multiple pageloads
    on a website instead of just one.
    *
    * @param (int | bool) $t
    * @return bool
    */
    public function isPrime($t = false)
    {
        if (!$t) {
            $t = $this->setupIsPrime();
        }
        return $this->testPrimality($t);
    }
    /**
     * Performs a few preliminary checks on root
     *
     * @param int $n
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    protected function rootHelper($n)
    {
        if ($n < 1) {
            return clone static::$zero;
        }
        // we want positive exponents
        if ($this->compare(static::$one) < 0) {
            return clone static::$zero;
        }
        // we want positive numbers
        if ($this->compare(static::$two) < 0) {
            return clone static::$one;
        }
        // n-th root of 1 or 2 is 1
        return $this->rootInner($n);
    }
    /**
     * Calculates the nth root of a biginteger.
     *
     * Returns the nth root of a positive biginteger, where n defaults to 2
     *
     * {@internal This function is based off of {@link http://mathforum.org/library/drmath/view/52605.html this page} and {@link http://stackoverflow.com/questions/11242920/calculating-nth-root-with-bcmath-in-php this stackoverflow question}.}
     *
     * @param int $n
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    protected function rootInner($n)
    {
        $n = new static($n);
        // g is our guess number
        $g = static::$two;
        // while (g^n < num) g=g*2
        while ($g->pow($n)->compare($this) < 0) {
            $g = $g->multiply(static::$two);
        }
        // if (g^n==num) num is a power of 2, we're lucky, end of job
        // == 0 bccomp(bcpow($g, $n), $n->value)==0
        if ($g->pow($n)->equals($this) > 0) {
            $root = $g;
            return $this->normalize($root);
        }
        // if we're here num wasn't a power of 2 :(
        $og = $g;
        // og means original guess and here is our upper bound
        $g = $g->divide(static::$two)[0];
        // g is set to be our lower bound
        $step = $og->subtract($g)->divide(static::$two)[0];
        // step is the half of upper bound - lower bound
        $g = $g->add($step);
        // we start at lower bound + step , basically in the middle of our interval
        // while step>1
        while ($step->compare(static::$one) == 1) {
            $guess = $g->pow($n);
            $step = $step->divide(static::$two)[0];
            $comp = $guess->compare($this);
            // compare our guess with real number
            switch ($comp) {
                case -1:
                    // if guess is lower we add the new step
                    $g = $g->add($step);
                    break;
                case 1:
                    // if guess is higher we sub the new step
                    $g = $g->subtract($step);
                    break;
                case 0:
                    // if guess is exactly the num we're done, we return the value
                    $root = $g;
                    break 2;
            }
        }
        if ($comp == 1) {
            $g = $g->subtract($step);
        }
        // whatever happened, g is the closest guess we can make so return it
        $root = $g;
        return $this->normalize($root);
    }
    /**
     * Calculates the nth root of a biginteger.
     *
     * @param int $n
     * @return Engine
     */
    public function root($n = 2)
    {
        return $this->rootHelper($n);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param array $nums
     * @return Engine
     */
    protected static function minHelper(array $nums)
    {
        if (count($nums) == 1) {
            return $nums[0];
        }
        $min = $nums[0];
        for ($i = 1; $i < count($nums); $i++) {
            $min = $min->compare($nums[$i]) > 0 ? $nums[$i] : $min;
        }
        return $min;
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param array $nums
     * @return Engine
     */
    protected static function maxHelper(array $nums)
    {
        if (count($nums) == 1) {
            return $nums[0];
        }
        $max = $nums[0];
        for ($i = 1; $i < count($nums); $i++) {
            $max = $max->compare($nums[$i]) < 0 ? $nums[$i] : $max;
        }
        return $max;
    }
    /**
    * Create Recurring Modulo Function
    *
    * Sometimes it may be desirable to do repeated modulos with the same number outside of
    modular exponentiation
    *
    * @return callable
    */
    public function createRecurringModuloFunction()
    {
        $class = static::class;
        $fqengine = !method_exists(static::$modexpEngine, 'reduce') ? '\\phpseclib3\\Math\\BigInteger\\Engines\\' . static::ENGINE_DIR . '\\DefaultEngine' : static::$modexpEngine;
        if (method_exists($fqengine, 'generateCustomReduction')) {
            $func = $fqengine::generateCustomReduction($this, static::class);
            return eval('return function(' . static::class . ' $x) use ($func, $class) {
                $r = new $class();
                $r->value = $func($x->value);
                return $r;
            };');
        }
        $n = $this->value;
        return eval('return function(' . static::class . ' $x) use ($n, $fqengine, $class) {
            $r = new $class();
            $r->value = $fqengine::reduce($x->value, $n, $class);
            return $r;
        };');
    }
    /**
     * Calculates the greatest common divisor and Bezout's identity.
     *
     * @param Engine $n
     * @param Engine $stop (optional)
     * @return Engine
     */
    protected function extendedGCDHelper(Engine $n, Engine $stop = null)
    {
        $u = clone $this;
        $v = clone $n;
        $one = new static(1);
        $zero = new static();
        $a = clone $one;
        $b = clone $zero;
        $c = clone $zero;
        $d = clone $one;
        while (!$v->equals($zero)) {
            list($q) = $u->divide($v);
            $temp = $u;
            $u = $v;
            $v = $temp->subtract($v->multiply($q));
            $temp = $a;
            $a = $c;
            $c = $temp->subtract($a->multiply($q));
            $temp = $b;
            $b = $d;
            $d = $temp->subtract($b->multiply($q));
        }
        return ['gcd' => $u, 'x' => $a, 'y' => $b];
    }
    /**
     * Bitwise Split
     *
     * Splits BigInteger's into chunks of $split bits
     *
     * @param int $split
     * @return \phpseclib3\Math\BigInteger\Engines\Engine[]
     */
    public function bitwise_split($split)
    {
        if ($split < 1) {
            throw new \RuntimeException('Offset must be greater than 1');
        }
        $mask = static::$one->bitwise_leftShift($split)->subtract(static::$one);
        $num = clone $this;
        $vals = [];
        while (!$num->equals(static::$zero)) {
            $vals[] = $num->bitwise_and($mask);
            $num = $num->bitwise_rightShift($split);
        }
        return array_reverse($vals);
    }
    /**
     * Logical And
     *
     * @param Engine $x
     * @return Engine
     */
    protected function bitwiseAndHelper(Engine $x)
    {
        $left = $this->toBytes(true);
        $right = $x->toBytes(true);
        $length = max(strlen($left), strlen($right));
        $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
        $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
        return $this->normalize(new static($left & $right, -256));
    }
    /**
     * Logical Or
     *
     * @param Engine $x
     * @return Engine
     */
    protected function bitwiseOrHelper(Engine $x)
    {
        $left = $this->toBytes(true);
        $right = $x->toBytes(true);
        $length = max(strlen($left), strlen($right));
        $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
        $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
        return $this->normalize(new static($left | $right, -256));
    }
    /**
     * Logical Exclusive Or
     *
     * @param Engine $x
     * @return Engine
     */
    protected function bitwiseXorHelper(Engine $x)
    {
        $left = $this->toBytes(true);
        $right = $x->toBytes(true);
        $length = max(strlen($left), strlen($right));
        $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
        $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
        return $this->normalize(new static($left ^ $right, -256));
    }
}<?php

/**
 * Pure-PHP 64-bit BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
/**
 * Pure-PHP 64-bit Engine.
 *
 * Uses 64-bit integers if int size is 8 bits
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PHP64 extends PHP
{
    // Constants used by PHP.php
    const BASE = 31;
    const BASE_FULL = 0x80000000;
    const MAX_DIGIT = 0x7fffffff;
    const MSB = 0x40000000;
    /**
     * MAX10 in greatest MAX10LEN satisfying
     * MAX10 = 10**MAX10LEN <= 2**BASE.
     */
    const MAX10 = 1000000000;
    /**
     * MAX10LEN in greatest MAX10LEN satisfying
     * MAX10 = 10**MAX10LEN <= 2**BASE.
     */
    const MAX10LEN = 9;
    const MAX_DIGIT2 = 4611686018427387904;
    /**#@-*/
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    protected static $modexpEngine;
    /**
     * Engine Validity Flag
     *
     * @var bool
     */
    protected static $isValidEngine;
    /**
     * Primes > 2 and < 1000
     *
     * @var array
     */
    protected static $primes;
    /**
     * BigInteger(0)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP64
     */
    protected static $zero;
    /**
     * BigInteger(1)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP64
     */
    protected static $one;
    /**
     * BigInteger(2)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP64
     */
    protected static $two;
    /**
     * Initialize a PHP64 BigInteger Engine instance
     *
     * @param int $base
     * @see parent::initialize()
     */
    protected function initialize($base)
    {
        if ($base != 256 && $base != -256) {
            return parent::initialize($base);
        }
        $val = $this->value;
        $this->value = [];
        $vals =& $this->value;
        $i = strlen($val);
        if (!$i) {
            return;
        }
        while (true) {
            $i -= 4;
            if ($i < 0) {
                if ($i == -4) {
                    break;
                }
                $val = \Phabel\Target\Php80\Polyfill::substr($val, 0, 4 + $i);
                $val = str_pad($val, 4, "\x00", STR_PAD_LEFT);
                if ($val == "\x00\x00\x00\x00") {
                    break;
                }
                $i = 0;
            }
            list(, $digit) = unpack('N', \Phabel\Target\Php80\Polyfill::substr($val, $i, 4));
            $step = count($vals) & 7;
            if (!$step) {
                $digit &= static::MAX_DIGIT;
                $i++;
            } else {
                $shift = 8 - $step;
                $digit >>= $shift;
                $shift = 32 - $shift;
                $digit &= (1 << $shift) - 1;
                $temp = $i > 0 ? ord($val[$i - 1]) : 0;
                $digit |= $temp << $shift & 0x7f000000;
            }
            $vals[] = $digit;
        }
        while (end($vals) === 0) {
            array_pop($vals);
        }
        reset($vals);
    }
    /**
     * Test for engine validity
     *
     * @see parent::__construct()
     * @return bool
     */
    public static function isValidEngine()
    {
        return PHP_INT_SIZE >= 8;
    }
    /**
     * Adds two BigIntegers.
     *
     * @param PHP64 $y
     * @return PHP64
     */
    public function add(PHP64 $y)
    {
        $temp = self::addHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param PHP64 $y
     * @return PHP64
     */
    public function subtract(PHP64 $y)
    {
        $temp = self::subtractHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
     * Multiplies two BigIntegers.
     *
     * @param PHP64 $y
     * @return PHP64
     */
    public function multiply(PHP64 $y)
    {
        $temp = self::multiplyHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param PHP64 $y
    * @return PHP64
    */
    public function divide(PHP64 $y)
    {
        return $this->divideHelper($y);
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @param PHP64 $n
     * @return (false | PHP64)
     */
    public function modInverse(PHP64 $n)
    {
        return $this->modInverseHelper($n);
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @param PHP64 $n
     * @return PHP64[]
     */
    public function extendedGCD(PHP64 $n)
    {
        return $this->extendedGCDHelper($n);
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param PHP64 $n
     * @return PHP64
     */
    public function gcd(PHP64 $n)
    {
        return $this->extendedGCD($n)['gcd'];
    }
    /**
     * Logical And
     *
     * @param PHP64 $x
     * @return PHP64
     */
    public function bitwise_and(PHP64 $x)
    {
        return $this->bitwiseAndHelper($x);
    }
    /**
     * Logical Or
     *
     * @param PHP64 $x
     * @return PHP64
     */
    public function bitwise_or(PHP64 $x)
    {
        return $this->bitwiseOrHelper($x);
    }
    /**
     * Logical Exclusive Or
     *
     * @param PHP64 $x
     * @return PHP64
     */
    public function bitwise_xor(PHP64 $x)
    {
        return $this->bitwiseXorHelper($x);
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param PHP64 $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @access public
    * @see self::equals()
    */
    public function compare(PHP64 $y)
    {
        return parent::compareHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param PHP64 $x
     * @return bool
     */
    public function equals(PHP64 $x)
    {
        return $this->value === $x->value && $this->is_negative == $x->is_negative;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param PHP64 $e
     * @param PHP64 $n
     * @return PHP64
     */
    public function modPow(PHP64 $e, PHP64 $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * Alias for modPow().
     *
     * @param PHP64 $e
     * @param PHP64 $n
     * @return PHP64
     */
    public function powMod(PHP64 $e, PHP64 $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param PHP64 $min
     * @param PHP64 $max
     * @return (false | PHP64)
     */
    public static function randomRangePrime(PHP64 $min, PHP64 $max)
    {
        return self::randomRangePrimeOuter($min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param PHP64 $min
    * @param PHP64 $max
    * @return PHP64
    */
    public static function randomRange(PHP64 $min, PHP64 $max)
    {
        return self::randomRangeHelper($min, $max);
    }
    /**
     * Performs exponentiation.
     *
     * @param PHP64 $n
     * @return PHP64
     */
    public function pow(PHP64 $n)
    {
        return $this->powHelper($n);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param PHP64 ...$nums
     * @return PHP64
     */
    public static function min(PHP64 ...$nums)
    {
        return self::minHelper($nums);
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param PHP64 ...$nums
     * @return PHP64
     */
    public static function max(PHP64 ...$nums)
    {
        return self::maxHelper($nums);
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param PHP64 $min
     * @param PHP64 $max
     * @return bool
     */
    public function between(PHP64 $min, PHP64 $max)
    {
        return $this->compare($min) >= 0 && $this->compare($max) <= 0;
    }
}<?php

/**
 * Pure-PHP BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Exception\BadConfigurationException;
/**
 * Pure-PHP Engine.
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PHP extends Engine
{
    /**#@+
     * Array constants
     *
     * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and
     * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
     *
     * @access protected
     */
    /**
     * $result[self::VALUE] contains the value.
     */
    const VALUE = 0;
    /**
     * $result[self::SIGN] contains the sign.
     */
    const SIGN = 1;
    /**#@-*/
    /**
     * Karatsuba Cutoff
     *
     * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
     *
     * @access private
     */
    const KARATSUBA_CUTOFF = 25;
    /**
     * Can Bitwise operations be done fast?
     *
     * @see parent::bitwise_leftRotate()
     * @see parent::bitwise_rightRotate()
     * @access protected
     */
    const FAST_BITWISE = true;
    /**
     * Engine Directory
     *
     * @see parent::setModExpEngine
     * @access protected
     */
    const ENGINE_DIR = 'PHP';
    /**
     * Default constructor
     *
     * @param mixed $x integer Base-10 number or base-$base number if $base set.
     * @param int $base
     * @see parent::__construct()
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    public function __construct($x = 0, $base = 10)
    {
        if (!isset(static::$isValidEngine)) {
            static::$isValidEngine = static::isValidEngine();
        }
        if (!static::$isValidEngine) {
            throw new BadConfigurationException(static::class . ' is not setup correctly on this system');
        }
        $this->value = [];
        parent::__construct($x, $base);
    }
    /**
     * Initialize a PHP BigInteger Engine instance
     *
     * @param int $base
     * @see parent::__construct()
     */
    protected function initialize($base)
    {
        switch (abs($base)) {
            case 16:
                $x = strlen($this->value) & 1 ? '0' . $this->value : $this->value;
                $temp = new static(Hex::decode($x), 256);
                $this->value = $temp->value;
                break;
            case 10:
                $temp = new static();
                $multiplier = new static();
                $multiplier->value = [static::MAX10];
                $x = $this->value;
                if ($x[0] == '-') {
                    $this->is_negative = true;
                    $x = \Phabel\Target\Php80\Polyfill::substr($x, 1);
                }
                $x = str_pad($x, strlen($x) + (static::MAX10LEN - 1) * strlen($x) % static::MAX10LEN, 0, STR_PAD_LEFT);
                while (strlen($x)) {
                    $temp = $temp->multiply($multiplier);
                    $temp = $temp->add(new static($this->int2bytes(\Phabel\Target\Php80\Polyfill::substr($x, 0, static::MAX10LEN)), 256));
                    $x = \Phabel\Target\Php80\Polyfill::substr($x, static::MAX10LEN);
                }
                $this->value = $temp->value;
        }
    }
    /**
     * Pads strings so that unpack may be used on them
     *
     * @param string $str
     * @return string
     */
    protected function pad($str)
    {
        $length = strlen($str);
        $pad = 4 - strlen($str) % 4;
        return str_pad($str, $length + $pad, "\x00", STR_PAD_LEFT);
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function toString()
    {
        if (!count($this->value)) {
            return '0';
        }
        $temp = clone $this;
        $temp->bitmask = false;
        $temp->is_negative = false;
        $divisor = new static();
        $divisor->value = [static::MAX10];
        $result = '';
        while (count($temp->value)) {
            list($temp, $mod) = $temp->divide($divisor);
            $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', static::MAX10LEN, '0', STR_PAD_LEFT) . $result;
        }
        $result = ltrim($result, '0');
        if (empty($result)) {
            $result = '0';
        }
        if ($this->is_negative) {
            $result = '-' . $result;
        }
        return $result;
    }
    /**
     * Converts a BigInteger to a byte string (eg. base-256).
     *
     * @param bool $twos_compliment
     * @return string
     */
    public function toBytes($twos_compliment = false)
    {
        if ($twos_compliment) {
            return $this->toBytesHelper();
        }
        if (!count($this->value)) {
            return $this->precision > 0 ? str_repeat(chr(0), $this->precision + 1 >> 3) : '';
        }
        $result = $this->bitwise_small_split(8);
        $result = implode('', array_map('chr', $result));
        return $this->precision > 0 ? str_pad(\Phabel\Target\Php80\Polyfill::substr($result, -($this->precision + 7 >> 3)), $this->precision + 7 >> 3, chr(0), STR_PAD_LEFT) : $result;
    }
    /**
     * Performs addition.
     *
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @return array
     */
    protected static function addHelper(array $x_value, $x_negative, array $y_value, $y_negative)
    {
        $x_size = count($x_value);
        $y_size = count($y_value);
        if ($x_size == 0) {
            return [self::VALUE => $y_value, self::SIGN => $y_negative];
        } elseif ($y_size == 0) {
            return [self::VALUE => $x_value, self::SIGN => $x_negative];
        }
        // subtract, if appropriate
        if ($x_negative != $y_negative) {
            if ($x_value == $y_value) {
                return [self::VALUE => [], self::SIGN => false];
            }
            $temp = self::subtractHelper($x_value, false, $y_value, false);
            $temp[self::SIGN] = self::compareHelper($x_value, false, $y_value, false) > 0 ? $x_negative : $y_negative;
            return $temp;
        }
        if ($x_size < $y_size) {
            $size = $x_size;
            $value = $y_value;
        } else {
            $size = $y_size;
            $value = $x_value;
        }
        $value[count($value)] = 0;
        // just in case the carry adds an extra digit
        $carry = 0;
        for ($i = 0, $j = 1; $j < $size; $i += 2, $j += 2) {
            //$sum = $x_value[$j] * static::BASE_FULL + $x_value[$i] + $y_value[$j] * static::BASE_FULL + $y_value[$i] + $carry;
            $sum = ($x_value[$j] + $y_value[$j]) * static::BASE_FULL + $x_value[$i] + $y_value[$i] + $carry;
            $carry = $sum >= static::MAX_DIGIT2;
            // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
            $sum = $carry ? $sum - static::MAX_DIGIT2 : $sum;
            $temp = static::BASE === 26 ? intval($sum / 0x4000000) : $sum >> 31;
            $value[$i] = (int) ($sum - static::BASE_FULL * $temp);
            // eg. a faster alternative to fmod($sum, 0x4000000)
            $value[$j] = $temp;
        }
        if ($j == $size) {
            // ie. if $y_size is odd
            $sum = $x_value[$i] + $y_value[$i] + $carry;
            $carry = $sum >= static::BASE_FULL;
            $value[$i] = $carry ? $sum - static::BASE_FULL : $sum;
            ++$i;
            // ie. let $i = $j since we've just done $value[$i]
        }
        if ($carry) {
            for (; $value[$i] == static::MAX_DIGIT; ++$i) {
                $value[$i] = 0;
            }
            ++$value[$i];
        }
        return [self::VALUE => self::trim($value), self::SIGN => $x_negative];
    }
    /**
     * Performs subtraction.
     *
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @return array
     */
    static function subtractHelper(array $x_value, $x_negative, array $y_value, $y_negative)
    {
        $x_size = count($x_value);
        $y_size = count($y_value);
        if ($x_size == 0) {
            return [self::VALUE => $y_value, self::SIGN => !$y_negative];
        } elseif ($y_size == 0) {
            return [self::VALUE => $x_value, self::SIGN => $x_negative];
        }
        // add, if appropriate (ie. -$x - +$y or +$x - -$y)
        if ($x_negative != $y_negative) {
            $temp = self::addHelper($x_value, false, $y_value, false);
            $temp[self::SIGN] = $x_negative;
            return $temp;
        }
        $diff = self::compareHelper($x_value, $x_negative, $y_value, $y_negative);
        if (!$diff) {
            return [self::VALUE => [], self::SIGN => false];
        }
        // switch $x and $y around, if appropriate.
        if (!$x_negative && $diff < 0 || $x_negative && $diff > 0) {
            $temp = $x_value;
            $x_value = $y_value;
            $y_value = $temp;
            $x_negative = !$x_negative;
            $x_size = count($x_value);
            $y_size = count($y_value);
        }
        // at this point, $x_value should be at least as big as - if not bigger than - $y_value
        $carry = 0;
        for ($i = 0, $j = 1; $j < $y_size; $i += 2, $j += 2) {
            $sum = ($x_value[$j] - $y_value[$j]) * static::BASE_FULL + $x_value[$i] - $y_value[$i] - $carry;
            $carry = $sum < 0;
            // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
            $sum = $carry ? $sum + static::MAX_DIGIT2 : $sum;
            $temp = static::BASE === 26 ? intval($sum / 0x4000000) : $sum >> 31;
            $x_value[$i] = (int) ($sum - static::BASE_FULL * $temp);
            $x_value[$j] = $temp;
        }
        if ($j == $y_size) {
            // ie. if $y_size is odd
            $sum = $x_value[$i] - $y_value[$i] - $carry;
            $carry = $sum < 0;
            $x_value[$i] = $carry ? $sum + static::BASE_FULL : $sum;
            ++$i;
        }
        if ($carry) {
            for (; !$x_value[$i]; ++$i) {
                $x_value[$i] = static::MAX_DIGIT;
            }
            --$x_value[$i];
        }
        return [self::VALUE => self::trim($x_value), self::SIGN => $x_negative];
    }
    /**
     * Performs multiplication.
     *
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @return array
     */
    protected static function multiplyHelper(array $x_value, $x_negative, array $y_value, $y_negative)
    {
        //if ( $x_value == $y_value ) {
        //    return [
        //        self::VALUE => self::square($x_value),
        //        self::SIGN => $x_sign != $y_value
        //    ];
        //}
        $x_length = count($x_value);
        $y_length = count($y_value);
        if (!$x_length || !$y_length) {
            // a 0 is being multiplied
            return [self::VALUE => [], self::SIGN => false];
        }
        return [self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ? self::trim(self::regularMultiply($x_value, $y_value)) : self::trim(self::karatsuba($x_value, $y_value)), self::SIGN => $x_negative != $y_negative];
    }
    /**
    * Performs Karatsuba multiplication on two BigIntegers
    *
    * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
    *
    * @param array $x_value
    * @param array $y_value
    * @return array
    */
    private static function karatsuba(array $x_value, array $y_value)
    {
        $m = min(count($x_value) >> 1, count($y_value) >> 1);
        if ($m < self::KARATSUBA_CUTOFF) {
            return self::regularMultiply($x_value, $y_value);
        }
        $x1 = array_slice($x_value, $m);
        $x0 = array_slice($x_value, 0, $m);
        $y1 = array_slice($y_value, $m);
        $y0 = array_slice($y_value, 0, $m);
        $z2 = self::karatsuba($x1, $y1);
        $z0 = self::karatsuba($x0, $y0);
        $z1 = self::addHelper($x1, false, $x0, false);
        $temp = self::addHelper($y1, false, $y0, false);
        $z1 = self::karatsuba($z1[self::VALUE], $temp[self::VALUE]);
        $temp = self::addHelper($z2, false, $z0, false);
        $z1 = self::subtractHelper($z1, false, $temp[self::VALUE], false);
        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
        $xy = self::addHelper($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
        $xy = self::addHelper($xy[self::VALUE], $xy[self::SIGN], $z0, false);
        return $xy[self::VALUE];
    }
    /**
     * Performs long multiplication on two BigIntegers
     *
     * Modeled after 'multiply' in MutableBigInteger.java.
     *
     * @param array $x_value
     * @param array $y_value
     * @return array
     */
    protected static function regularMultiply(array $x_value, array $y_value)
    {
        $x_length = count($x_value);
        $y_length = count($y_value);
        if (!$x_length || !$y_length) {
            // a 0 is being multiplied
            return [];
        }
        $product_value = self::array_repeat(0, $x_length + $y_length);
        // the following for loop could be removed if the for loop following it
        // (the one with nested for loops) initially set $i to 0, but
        // doing so would also make the result in one set of unnecessary adds,
        // since on the outermost loops first pass, $product->value[$k] is going
        // to always be 0
        $carry = 0;
        for ($j = 0; $j < $x_length; ++$j) {
            // ie. $i = 0
            $temp = $x_value[$j] * $y_value[0] + $carry;
            // $product_value[$k] == 0
            $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
            $product_value[$j] = (int) ($temp - static::BASE_FULL * $carry);
        }
        $product_value[$j] = $carry;
        // the above for loop is what the previous comment was talking about.  the
        // following for loop is the "one with nested for loops"
        for ($i = 1; $i < $y_length; ++$i) {
            $carry = 0;
            for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
                $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
                $product_value[$k] = (int) ($temp - static::BASE_FULL * $carry);
            }
            $product_value[$k] = $carry;
        }
        return $product_value;
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param \phpseclib3\Math\BigInteger\engines\PHP $y
    * @return array
    * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
    */
    protected function divideHelper(PHP $y)
    {
        if (count($y->value) == 1) {
            list($q, $r) = $this->divide_digit($this->value, $y->value[0]);
            $quotient = new static();
            $remainder = new static();
            $quotient->value = $q;
            $remainder->value = [$r];
            $quotient->is_negative = $this->is_negative != $y->is_negative;
            return [$this->normalize($quotient), $this->normalize($remainder)];
        }
        $x = clone $this;
        $y = clone $y;
        $x_sign = $x->is_negative;
        $y_sign = $y->is_negative;
        $x->is_negative = $y->is_negative = false;
        $diff = $x->compare($y);
        if (!$diff) {
            $temp = new static();
            $temp->value = [1];
            $temp->is_negative = $x_sign != $y_sign;
            return [$this->normalize($temp), $this->normalize(static::$zero)];
        }
        if ($diff < 0) {
            // if $x is negative, "add" $y.
            if ($x_sign) {
                $x = $y->subtract($x);
            }
            return [$this->normalize(static::$zero), $this->normalize($x)];
        }
        // normalize $x and $y as described in HAC 14.23 / 14.24
        $msb = $y->value[count($y->value) - 1];
        for ($shift = 0; !($msb & static::MSB); ++$shift) {
            $msb <<= 1;
        }
        $x->lshift($shift);
        $y->lshift($shift);
        $y_value =& $y->value;
        $x_max = count($x->value) - 1;
        $y_max = count($y->value) - 1;
        $quotient = new static();
        $quotient_value =& $quotient->value;
        $quotient_value = self::array_repeat(0, $x_max - $y_max + 1);
        static $temp, $lhs, $rhs;
        if (!isset($temp)) {
            $temp = new static();
            $lhs = new static();
            $rhs = new static();
        }
        $temp_value =& $temp->value;
        $rhs_value =& $rhs->value;
        // $temp = $y << ($x_max - $y_max-1) in base 2**26
        $temp_value = array_merge(self::array_repeat(0, $x_max - $y_max), $y_value);
        while ($x->compare($temp) >= 0) {
            // calculate the "common residue"
            ++$quotient_value[$x_max - $y_max];
            $x = $x->subtract($temp);
            $x_max = count($x->value) - 1;
        }
        for ($i = $x_max; $i >= $y_max + 1; --$i) {
            $x_value =& $x->value;
            $x_window = [isset($x_value[$i]) ? $x_value[$i] : 0, isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0, isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0];
            $y_window = [$y_value[$y_max], $y_max > 0 ? $y_value[$y_max - 1] : 0];
            $q_index = $i - $y_max - 1;
            if ($x_window[0] == $y_window[0]) {
                $quotient_value[$q_index] = static::MAX_DIGIT;
            } else {
                $quotient_value[$q_index] = self::safe_divide($x_window[0] * static::BASE_FULL + $x_window[1], $y_window[0]);
            }
            $temp_value = [$y_window[1], $y_window[0]];
            $lhs->value = [$quotient_value[$q_index]];
            $lhs = $lhs->multiply($temp);
            $rhs_value = [$x_window[2], $x_window[1], $x_window[0]];
            while ($lhs->compare($rhs) > 0) {
                --$quotient_value[$q_index];
                $lhs->value = [$quotient_value[$q_index]];
                $lhs = $lhs->multiply($temp);
            }
            $adjust = self::array_repeat(0, $q_index);
            $temp_value = [$quotient_value[$q_index]];
            $temp = $temp->multiply($y);
            $temp_value =& $temp->value;
            if (count($temp_value)) {
                $temp_value = array_merge($adjust, $temp_value);
            }
            $x = $x->subtract($temp);
            if ($x->compare(static::$zero) < 0) {
                $temp_value = array_merge($adjust, $y_value);
                $x = $x->add($temp);
                --$quotient_value[$q_index];
            }
            $x_max = count($x_value) - 1;
        }
        // unnormalize the remainder
        $x->rshift($shift);
        $quotient->is_negative = $x_sign != $y_sign;
        // calculate the "common residue", if appropriate
        if ($x_sign) {
            $y->rshift($shift);
            $x = $y->subtract($x);
        }
        return [$this->normalize($quotient), $this->normalize($x)];
    }
    /**
     * Divides a BigInteger by a regular integer
     *
     * abc / x = a00 / x + b0 / x + c / x
     *
     * @param array $dividend
     * @param int $divisor
     * @return array
     */
    private static function divide_digit(array $dividend, $divisor)
    {
        $carry = 0;
        $result = [];
        for ($i = count($dividend) - 1; $i >= 0; --$i) {
            $temp = static::BASE_FULL * $carry + $dividend[$i];
            $result[$i] = self::safe_divide($temp, $divisor);
            $carry = (int) ($temp - $divisor * $result[$i]);
        }
        return [$result, $carry];
    }
    /**
    * Single digit division
    *
    * Even if int64 is being used the division operator will return a float64 value
    if the dividend is not evenly divisible by the divisor. Since a float64 doesn't
    have the precision of int64 this is a problem so, when int64 is being used,
    we'll guarantee that the dividend is divisible by first subtracting the remainder.
    *
    * @param int $x
    * @param int $y
    * @return int
    */
    private static function safe_divide($x, $y)
    {
        if (static::BASE === 26) {
            return (int) ($x / $y);
        }
        // static::BASE === 31
        return ($x - $x % $y) / $y;
    }
    /*
     * Convert an array / boolean to a PHP BigInteger object
     *
     * @param array $arr
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    /**
     *
     */
    protected function convertToObj(array $arr)
    {
        $result = new static();
        $result->value = $arr[self::VALUE];
        $result->is_negative = $arr[self::SIGN];
        return $this->normalize($result);
    }
    /**
     * Normalize
     *
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
     *
     * @param PHP $result
     * @return PHP
     */
    protected function normalize(PHP $result)
    {
        $result->precision = $this->precision;
        $result->bitmask = $this->bitmask;
        $value =& $result->value;
        if (!count($value)) {
            $result->is_negative = false;
            return $result;
        }
        $value = static::trim($value);
        if (!empty($result->bitmask->value)) {
            $length = min(count($value), count($result->bitmask->value));
            $value = array_slice($value, 0, $length);
            for ($i = 0; $i < $length; ++$i) {
                $value[$i] = $value[$i] & $result->bitmask->value[$i];
            }
        }
        return $result;
    }
    /*
     * Compares two numbers.
     *
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @return int
     * @see static::compare()
     */
    /**
     *
     */
    protected static function compareHelper(array $x_value, $x_negative, array $y_value, $y_negative)
    {
        if ($x_negative != $y_negative) {
            return !$x_negative && $y_negative ? 1 : -1;
        }
        $result = $x_negative ? -1 : 1;
        if (count($x_value) != count($y_value)) {
            return count($x_value) > count($y_value) ? $result : -$result;
        }
        $size = max(count($x_value), count($y_value));
        $x_value = array_pad($x_value, $size, 0);
        $y_value = array_pad($y_value, $size, 0);
        for ($i = count($x_value) - 1; $i >= 0; --$i) {
            if ($x_value[$i] != $y_value[$i]) {
                return $x_value[$i] > $y_value[$i] ? $result : -$result;
            }
        }
        return 0;
    }
    /**
     * Absolute value.
     *
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    public function abs()
    {
        $temp = new static();
        $temp->value = $this->value;
        return $temp;
    }
    /**
     * Trim
     *
     * Removes leading zeros
     *
     * @param array $value
     * @return PHP
     */
    protected static function trim(array $value)
    {
        for ($i = count($value) - 1; $i >= 0; --$i) {
            if ($value[$i]) {
                break;
            }
            unset($value[$i]);
        }
        return $value;
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    public function bitwise_rightShift($shift)
    {
        $temp = new static();
        // could just replace lshift with this, but then all lshift() calls would need to be rewritten
        // and I don't want to do that...
        $temp->value = $this->value;
        $temp->rshift($shift);
        return $this->normalize($temp);
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    public function bitwise_leftShift($shift)
    {
        $temp = new static();
        // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten
        // and I don't want to do that...
        $temp->value = $this->value;
        $temp->lshift($shift);
        return $this->normalize($temp);
    }
    /**
     * Converts 32-bit integers to bytes.
     *
     * @param int $x
     * @return string
     */
    private static function int2bytes($x)
    {
        return ltrim(pack('N', $x), chr(0));
    }
    /**
     * Array Repeat
     *
     * @param int $input
     * @param int $multiplier
     * @return array
     */
    protected static function array_repeat($input, $multiplier)
    {
        return $multiplier ? array_fill(0, $multiplier, $input) : [];
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits.
     *
     * @param int $shift
     */
    protected function lshift($shift)
    {
        if ($shift == 0) {
            return;
        }
        $num_digits = (int) ($shift / static::BASE);
        $shift %= static::BASE;
        $shift = 1 << $shift;
        $carry = 0;
        for ($i = 0; $i < count($this->value); ++$i) {
            $temp = $this->value[$i] * $shift + $carry;
            $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
            $this->value[$i] = (int) ($temp - $carry * static::BASE_FULL);
        }
        if ($carry) {
            $this->value[count($this->value)] = $carry;
        }
        while ($num_digits--) {
            array_unshift($this->value, 0);
        }
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits.
     *
     * @param int $shift
     */
    protected function rshift($shift)
    {
        if ($shift == 0) {
            return;
        }
        $num_digits = (int) ($shift / static::BASE);
        $shift %= static::BASE;
        $carry_shift = static::BASE - $shift;
        $carry_mask = (1 << $shift) - 1;
        if ($num_digits) {
            $this->value = array_slice($this->value, $num_digits);
        }
        $carry = 0;
        for ($i = count($this->value) - 1; $i >= 0; --$i) {
            $temp = $this->value[$i] >> $shift | $carry;
            $carry = ($this->value[$i] & $carry_mask) << $carry_shift;
            $this->value[$i] = $temp;
        }
        $this->value = static::trim($this->value);
    }
    /**
     * Performs modular exponentiation.
     *
     * @param PHP $e
     * @param PHP $n
     * @return PHP
     */
    protected function powModInner(PHP $e, PHP $n)
    {
        try {
            $class = static::$modexpEngine;
            return $class::powModHelper($this, $e, $n, static::class);
        } catch (\Exception $err) {
            return PHP\DefaultEngine::powModHelper($this, $e, $n, static::class);
        }
    }
    /**
     * Performs squaring
     *
     * @param array $x
     * @return array
     */
    protected static function square(array $x)
    {
        return count($x) < 2 * self::KARATSUBA_CUTOFF ? self::trim(self::baseSquare($x)) : self::trim(self::karatsubaSquare($x));
    }
    /**
    * Performs traditional squaring on two BigIntegers
    *
    * Squaring can be done faster than multiplying a number by itself can be.  See
    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
    *
    * @param array $value
    * @return array
    */
    protected static function baseSquare(array $value)
    {
        if (empty($value)) {
            return [];
        }
        $square_value = self::array_repeat(0, 2 * count($value));
        for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
            $i2 = $i << 1;
            $temp = $square_value[$i2] + $value[$i] * $value[$i];
            $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
            $square_value[$i2] = (int) ($temp - static::BASE_FULL * $carry);
            // note how we start from $i+1 instead of 0 as we do in multiplication.
            for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
                $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
                $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
                $square_value[$k] = (int) ($temp - static::BASE_FULL * $carry);
            }
            // the following line can yield values larger 2**15.  at this point, PHP should switch
            // over to floats.
            $square_value[$i + $max_index + 1] = $carry;
        }
        return $square_value;
    }
    /**
    * Performs Karatsuba "squaring" on two BigIntegers
    *
    * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
    *
    * @param array $value
    * @return array
    */
    protected static function karatsubaSquare(array $value)
    {
        $m = count($value) >> 1;
        if ($m < self::KARATSUBA_CUTOFF) {
            return self::baseSquare($value);
        }
        $x1 = array_slice($value, $m);
        $x0 = array_slice($value, 0, $m);
        $z2 = self::karatsubaSquare($x1);
        $z0 = self::karatsubaSquare($x0);
        $z1 = self::addHelper($x1, false, $x0, false);
        $z1 = self::karatsubaSquare($z1[self::VALUE]);
        $temp = self::addHelper($z2, false, $z0, false);
        $z1 = self::subtractHelper($z1, false, $temp[self::VALUE], false);
        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
        $xx = self::addHelper($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
        $xx = self::addHelper($xx[self::VALUE], $xx[self::SIGN], $z0, false);
        return $xx[self::VALUE];
    }
    /**
     * Make the current number odd
     *
     * If the current number is odd it'll be unchanged.  If it's even, one will be added to it.
     *
     * @see self::randomPrime()
     */
    protected function make_odd()
    {
        $this->value[0] |= 1;
    }
    /**
     * Test the number against small primes.
     *
     * @see self::isPrime()
     */
    protected function testSmallPrimes()
    {
        if ($this->value == [1]) {
            return false;
        }
        if ($this->value == [2]) {
            return true;
        }
        if (~$this->value[0] & 1) {
            return false;
        }
        $value = $this->value;
        foreach (static::$primes as $prime) {
            list(, $r) = self::divide_digit($value, $prime);
            if (!$r) {
                return count($value) == 1 && $value[0] == $prime;
            }
        }
        return true;
    }
    /**
     * Scan for 1 and right shift by that amount
     *
     * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
     *
     * @see self::isPrime()
     * @param PHP $r
     * @return int
     */
    public static function scan1divide(PHP $r)
    {
        $r_value =& $r->value;
        for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
            $temp = ~$r_value[$i] & static::MAX_DIGIT;
            for ($j = 1; $temp >> $j & 1; ++$j) {
            }
            if ($j <= static::BASE) {
                break;
            }
        }
        $s = static::BASE * $i + $j;
        $r->rshift($s);
        return $s;
    }
    /**
     * Performs exponentiation.
     *
     * @param PHP $n
     * @return PHP
     */
    protected function powHelper(PHP $n)
    {
        if ($n->compare(static::$zero) == 0) {
            return new static(1);
        }
        // n^0 = 1
        $temp = clone $this;
        while (!$n->equals(static::$one)) {
            $temp = $temp->multiply($this);
            $n = $n->subtract(static::$one);
        }
        return $temp;
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return (bool) ($this->value[0] & 1);
    }
    /**
     * Tests if a bit is set
     *
     * @return boolean
     */
    public function testBit($x)
    {
        $digit = floor($x / static::BASE);
        $bit = $x % static::BASE;
        if (!isset($this->value[$digit])) {
            return false;
        }
        return (bool) ($this->value[$digit] & 1 << $bit);
    }
    /**
     * Is Negative?
     *
     * @return boolean
     */
    public function isNegative()
    {
        return $this->is_negative;
    }
    /**
     * Negate
     *
     * Given $k, returns -$k
     *
     * @return BigInteger
     */
    public function negate()
    {
        $temp = clone $this;
        $temp->is_negative = !$temp->is_negative;
        return $temp;
    }
    /**
     * Bitwise Split
     *
     * Splits BigInteger's into chunks of $split bits
     *
     * @param int $split
     * @return \phpseclib3\Math\BigInteger\Engines\PHP[]
     */
    public function bitwise_split($split)
    {
        if ($split < 1) {
            throw new \RuntimeException('Offset must be greater than 1');
        }
        $width = (int) ($split / static::BASE);
        if (!$width) {
            $arr = $this->bitwise_small_split($split);
            return array_map(function ($digit) {
                $temp = new static();
                $temp->value = $digit != 0 ? [$digit] : [];
                return $temp;
            }, $arr);
        }
        $vals = [];
        $val = $this->value;
        $i = $overflow = 0;
        $len = count($val);
        while ($i < $len) {
            $digit = [];
            if (!$overflow) {
                $digit = array_slice($val, $i, $width);
                $i += $width;
                $overflow = $split % static::BASE;
                if ($overflow) {
                    $mask = (1 << $overflow) - 1;
                    $temp = isset($val[$i]) ? $val[$i] : 0;
                    $digit[] = $temp & $mask;
                }
            } else {
                $remaining = static::BASE - $overflow;
                $tempsplit = $split - $remaining;
                $tempwidth = (int) ($tempsplit / static::BASE + 1);
                $digit = array_slice($val, $i, $tempwidth);
                $i += $tempwidth;
                $tempoverflow = $tempsplit % static::BASE;
                if ($tempoverflow) {
                    $tempmask = (1 << $tempoverflow) - 1;
                    $temp = isset($val[$i]) ? $val[$i] : 0;
                    $digit[] = $temp & $tempmask;
                }
                $newbits = 0;
                for ($j = count($digit) - 1; $j >= 0; $j--) {
                    $temp = $digit[$j] & $mask;
                    $digit[$j] = $digit[$j] >> $overflow | $newbits << $remaining;
                    $newbits = $temp;
                }
                $overflow = $tempoverflow;
                $mask = $tempmask;
            }
            $temp = new static();
            $temp->value = static::trim($digit);
            $vals[] = $temp;
        }
        return array_reverse($vals);
    }
    /**
     * Bitwise Split where $split < static::BASE
     *
     * @param int $split
     * @return \phpseclib3\Math\BigInteger\Engines\PHP[]
     */
    private function bitwise_small_split($split)
    {
        $vals = [];
        $val = $this->value;
        $mask = (1 << $split) - 1;
        $i = $overflow = 0;
        $len = count($val);
        $val[] = 0;
        $remaining = static::BASE;
        while ($i != $len) {
            $digit = $val[$i] & $mask;
            $val[$i] >>= $split;
            if (!$overflow) {
                $remaining -= $split;
                $overflow = $split <= $remaining ? 0 : $split - $remaining;
                if (!$remaining) {
                    $i++;
                    $remaining = static::BASE;
                    $overflow = 0;
                }
            } else {
                if (++$i != $len) {
                    $tempmask = (1 << $overflow) - 1;
                    $digit |= ($val[$i] & $tempmask) << $remaining;
                    $val[$i] >>= $overflow;
                    $remaining = static::BASE - $overflow;
                    $overflow = $split <= $remaining ? 0 : $split - $remaining;
                }
            }
            $vals[] = $digit;
        }
        while ($vals[count($vals) - 1] == 0) {
            unset($vals[count($vals) - 1]);
        }
        return array_reverse($vals);
    }
}<?php

/**
 * OpenSSL Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP;

use phpseclib3\Math\BigInteger\Engines\OpenSSL as Progenitor;
/**
 * OpenSSL Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSL extends Progenitor
{
}<?php

/**
 * PHP Montgomery Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP;

use phpseclib3\Math\BigInteger\Engines\PHP\Reductions\PowerOfTwo;
use phpseclib3\Math\BigInteger\Engines\PHP;
use phpseclib3\Math\BigInteger\Engines\PHP\Base;
use phpseclib3\Math\BigInteger\Engines\Engine;
/**
 * PHP Montgomery Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Montgomery extends Base
{
    /**
     * Test for engine validity
     *
     * @return bool
     */
    public static function isValidEngine()
    {
        return static::class != __CLASS__;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param \phpseclib3\Math\BigInteger\Engines\Engine $x
     * @param \phpseclib3\Math\BigInteger\Engines\Engine $e
     * @param \phpseclib3\Math\BigInteger\Engines\Engine $n
     * @param string $class
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    protected static function slidingWindow(Engine $x, Engine $e, Engine $n, $class)
    {
        // is the modulo odd?
        if ($n->value[0] & 1) {
            return parent::slidingWindow($x, $e, $n, $class);
        }
        // if it's not, it's even
        // find the lowest set bit (eg. the max pow of 2 that divides $n)
        for ($i = 0; $i < count($n->value); ++$i) {
            if ($n->value[$i]) {
                $temp = decbin($n->value[$i]);
                $j = strlen($temp) - strrpos($temp, '1') - 1;
                $j += $class::BASE * $i;
                break;
            }
        }
        // at this point, 2^$j * $n/(2^$j) == $n
        $mod1 = clone $n;
        $mod1->rshift($j);
        $mod2 = new $class();
        $mod2->value = [1];
        $mod2->lshift($j);
        $part1 = $mod1->value != [1] ? parent::slidingWindow($x, $e, $mod1, $class) : new $class();
        $part2 = PowerOfTwo::slidingWindow($x, $e, $mod2, $class);
        $y1 = $mod2->modInverse($mod1);
        $y2 = $mod1->modInverse($mod2);
        $result = $part1->multiply($mod2);
        $result = $result->multiply($y1);
        $temp = $part2->multiply($mod1);
        $temp = $temp->multiply($y2);
        $result = $result->add($temp);
        list(, $result) = $result->divide($n);
        return $result;
    }
}<?php

/**
 * PHP Power of Two Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
/**
 * PHP Power Of Two Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PowerOfTwo extends Base
{
    /**
     * Prepare a number for use in Montgomery Modular Reductions
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @return array
     */
    protected static function prepareReduce(array $x, array $n, $class)
    {
        return self::reduce($x, $n, $class);
    }
    /**
     * Power Of Two Reduction
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @return array
     */
    protected static function reduce(array $x, array $n, $class)
    {
        $lhs = new $class();
        $lhs->value = $x;
        $rhs = new $class();
        $rhs->value = $n;
        $temp = new $class();
        $temp->value = [1];
        $result = $lhs->bitwise_and($rhs->subtract($temp));
        return $result->value;
    }
}<?php

/**
 * PHP Montgomery Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Montgomery as Progenitor;
/**
 * PHP Montgomery Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Montgomery extends Progenitor
{
    /**
     * Prepare a number for use in Montgomery Modular Reductions
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @return array
     */
    protected static function prepareReduce(array $x, array $n, $class)
    {
        $lhs = new $class();
        $lhs->value = array_merge(self::array_repeat(0, count($n)), $x);
        $rhs = new $class();
        $rhs->value = $n;
        list(, $temp) = $lhs->divide($rhs);
        return $temp->value;
    }
    /**
    * Montgomery Multiply
    *
    * Interleaves the montgomery reduction and long multiplication algorithms together as described in
    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
    *
    * @param array $x
    * @param array $n
    * @param string $class
    * @return array
    */
    protected static function reduce(array $x, array $n, $class)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $x;
            $cache[self::DATA][] = self::modInverse67108864($n, $class);
        }
        $k = count($n);
        $result = [self::VALUE => $x];
        for ($i = 0; $i < $k; ++$i) {
            $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key];
            $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31);
            $temp = $class::regularMultiply([$temp], $n);
            $temp = array_merge(self::array_repeat(0, $i), $temp);
            $result = $class::addHelper($result[self::VALUE], false, $temp, false);
        }
        $result[self::VALUE] = array_slice($result[self::VALUE], $k);
        if (self::compareHelper($result, false, $n, false) >= 0) {
            $result = $class::subtractHelper($result[self::VALUE], false, $n, false);
        }
        return $result[self::VALUE];
    }
    /**
    * Modular Inverse of a number mod 2**26 (eg. 67108864)
    *
    * Based off of the bnpInvDigit function implemented and justified in the following URL:
    *
    * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
    *
    * The following URL provides more info:
    *
    * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
    *
    * As for why we do all the bitmasking...  strange things can happen when converting from floats to ints. For
    instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
    int(-2147483648).  To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
    auto-converted to floats.  The outermost bitmask is present because without it, there's no guarantee that
    the "residue" returned would be the so-called "common residue".  We use fmod, in the last step, because the
    maximum possible $x is 26 bits and the maximum $result is 16 bits.  Thus, we have to be able to handle up to
    40 bits, which only 64-bit floating points will support.
    *
    * Thanks to Pedro Gimeno Fortea for input!
    *
    * @param array $x
    * @param string $class
    * @return int
    */
    protected static function modInverse67108864(array $x, $class)
    {
        $x = -$x[0];
        $result = $x & 0x3;
        // x**-1 mod 2**2
        $result = $result * (2 - $x * $result) & 0xf;
        // x**-1 mod 2**4
        $result = $result * (2 - ($x & 0xff) * $result) & 0xff;
        // x**-1 mod 2**8
        $result = $result * (2 - ($x & 0xffff) * $result & 0xffff) & 0xffff;
        // x**-1 mod 2**16
        $result = $class::BASE == 26 ? fmod($result * (2 - fmod($x * $result, $class::BASE_FULL)), $class::BASE_FULL) : $result * (2 - $x * $result % $class::BASE_FULL) % $class::BASE_FULL;
        return $result & $class::MAX_DIGIT;
    }
}<?php

/**
 * PHP Barrett Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
/**
 * PHP Barrett Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Barrett extends Base
{
    /**
    * Barrett Modular Reduction
    *
    * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information.  Modified slightly,
    so as not to require negative numbers (initially, this script didn't support negative numbers).
    *
    * Employs "folding", as described at
    {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}.  To quote from
    it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
    *
    * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
    usable on account of (1) its not using reasonable radix points as discussed in
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
    radix points, it only works when there are an even number of digits in the denominator.  The reason for (2) is that
    (x >> 1) + (x >> 1) != x / 2 + x / 2.  If x is even, they're the same, but if x is odd, they're not.  See the in-line
    comments for details.
    *
    * @param array $n
    * @param array $m
    * @param string $class
    * @return array
    */
    protected static function reduce(array $n, array $m, $class)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        $m_length = count($m);
        // if (self::compareHelper($n, $static::square($m)) >= 0) {
        if (count($n) > 2 * $m_length) {
            $lhs = new $class();
            $rhs = new $class();
            $lhs->value = $n;
            $rhs->value = $m;
            list(, $temp) = $lhs->divide($rhs);
            return $temp->value;
        }
        // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
        if ($m_length < 5) {
            return self::regularBarrett($n, $m, $class);
        }
        // n = 2 * m.length
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $m;
            $lhs = new $class();
            $lhs_value =& $lhs->value;
            $lhs_value = self::array_repeat(0, $m_length + ($m_length >> 1));
            $lhs_value[] = 1;
            $rhs = new $class();
            $rhs->value = $m;
            list($u, $m1) = $lhs->divide($rhs);
            $u = $u->value;
            $m1 = $m1->value;
            $cache[self::DATA][] = [
                'u' => $u,
                // m.length >> 1 (technically (m.length >> 1) + 1)
                'm1' => $m1,
            ];
        } else {
            extract($cache[self::DATA][$key]);
        }
        $cutoff = $m_length + ($m_length >> 1);
        $lsd = array_slice($n, 0, $cutoff);
        // m.length + (m.length >> 1)
        $msd = array_slice($n, $cutoff);
        // m.length >> 1
        $lsd = self::trim($lsd);
        $temp = $class::multiplyHelper($msd, false, $m1, false);
        // m.length + (m.length >> 1)
        $n = $class::addHelper($lsd, false, $temp[self::VALUE], false);
        // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers)
        //if ($m_length & 1) {
        //    return self::regularBarrett($n[self::VALUE], $m, $class);
        //}
        // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
        $temp = array_slice($n[self::VALUE], $m_length - 1);
        // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
        // if odd:  ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
        $temp = $class::multiplyHelper($temp, false, $u, false);
        // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
        // if odd:  (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
        $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1);
        // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
        // if odd:  (m.length - (m.length >> 1)) + m.length     = 2 * m.length - (m.length >> 1)
        $temp = $class::multiplyHelper($temp, false, $m, false);
        // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
        // number from a m.length + (m.length >> 1) + 1 digit number.  ie. there'd be an extra digit and the while loop
        // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
        $result = $class::subtractHelper($n[self::VALUE], false, $temp[self::VALUE], false);
        while (self::compareHelper($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) {
            $result = $class::subtractHelper($result[self::VALUE], $result[self::SIGN], $m, false);
        }
        return $result[self::VALUE];
    }
    /**
    * (Regular) Barrett Modular Reduction
    *
    * For numbers with more than four digits BigInteger::_barrett() is faster.  The difference between that and this
    is that this function does not fold the denominator into a smaller form.
    *
    * @param array $x
    * @param array $n
    * @param string $class
    * @return array
    */
    private static function regularBarrett(array $x, array $n, $class)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        $n_length = count($n);
        if (count($x) > 2 * $n_length) {
            $lhs = new $class();
            $rhs = new $class();
            $lhs->value = $x;
            $rhs->value = $n;
            list(, $temp) = $lhs->divide($rhs);
            return $temp->value;
        }
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $n;
            $lhs = new $class();
            $lhs_value =& $lhs->value;
            $lhs_value = self::array_repeat(0, 2 * $n_length);
            $lhs_value[] = 1;
            $rhs = new $class();
            $rhs->value = $n;
            list($temp, ) = $lhs->divide($rhs);
            // m.length
            $cache[self::DATA][] = $temp->value;
        }
        // 2 * m.length - (m.length - 1) = m.length + 1
        $temp = array_slice($x, $n_length - 1);
        // (m.length + 1) + m.length = 2 * m.length + 1
        $temp = $class::multiplyHelper($temp, false, $cache[self::DATA][$key], false);
        // (2 * m.length + 1) - (m.length - 1) = m.length + 2
        $temp = array_slice($temp[self::VALUE], $n_length + 1);
        // m.length + 1
        $result = array_slice($x, 0, $n_length + 1);
        // m.length + 1
        $temp = self::multiplyLower($temp, false, $n, false, $n_length + 1, $class);
        // $temp == array_slice($class::regularMultiply($temp, false, $n, false)->value, 0, $n_length + 1)
        if (self::compareHelper($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) {
            $corrector_value = self::array_repeat(0, $n_length + 1);
            $corrector_value[count($corrector_value)] = 1;
            $result = $class::addHelper($result, false, $corrector_value, false);
            $result = $result[self::VALUE];
        }
        // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits
        $result = $class::subtractHelper($result, false, $temp[self::VALUE], $temp[self::SIGN]);
        while (self::compareHelper($result[self::VALUE], $result[self::SIGN], $n, false) > 0) {
            $result = $class::subtractHelper($result[self::VALUE], $result[self::SIGN], $n, false);
        }
        return $result[self::VALUE];
    }
    /**
     * Performs long multiplication up to $stop digits
     *
     * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
     *
     * @see self::regularBarrett()
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @param int $stop
     * @param string $class
     * @return array
     */
    private static function multiplyLower(array $x_value, $x_negative, array $y_value, $y_negative, $stop, $class)
    {
        $x_length = count($x_value);
        $y_length = count($y_value);
        if (!$x_length || !$y_length) {
            // a 0 is being multiplied
            return [self::VALUE => [], self::SIGN => false];
        }
        if ($x_length < $y_length) {
            $temp = $x_value;
            $x_value = $y_value;
            $y_value = $temp;
            $x_length = count($x_value);
            $y_length = count($y_value);
        }
        $product_value = self::array_repeat(0, $x_length + $y_length);
        // the following for loop could be removed if the for loop following it
        // (the one with nested for loops) initially set $i to 0, but
        // doing so would also make the result in one set of unnecessary adds,
        // since on the outermost loops first pass, $product->value[$k] is going
        // to always be 0
        $carry = 0;
        for ($j = 0; $j < $x_length; ++$j) {
            // ie. $i = 0, $k = $i
            $temp = $x_value[$j] * $y_value[0] + $carry;
            // $product_value[$k] == 0
            $carry = $class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
            $product_value[$j] = (int) ($temp - $class::BASE_FULL * $carry);
        }
        if ($j < $stop) {
            $product_value[$j] = $carry;
        }
        // the above for loop is what the previous comment was talking about.  the
        // following for loop is the "one with nested for loops"
        for ($i = 1; $i < $y_length; ++$i) {
            $carry = 0;
            for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
                $carry = $class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
                $product_value[$k] = (int) ($temp - $class::BASE_FULL * $carry);
            }
            if ($k < $stop) {
                $product_value[$k] = $carry;
            }
        }
        return [self::VALUE => self::trim($product_value), self::SIGN => $x_negative != $y_negative];
    }
}<?php

/**
 * PHP Dynamic Barrett Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
use phpseclib3\Math\BigInteger\Engines\PHP;
/**
 * PHP Dynamic Barrett Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EvalBarrett extends Base
{
    /**
     * Custom Reduction Function
     *
     * @see self::generateCustomReduction
     */
    private static $custom_reduction;
    /**
    * Barrett Modular Reduction
    *
    * This calls a dynamically generated loop unrolled function that's specific to a given modulo.
    Array lookups are avoided as are if statements testing for how many bits the host OS supports, etc.
    *
    * @param array $n
    * @param array $m
    * @param string $class
    * @return array
    */
    protected static function reduce(array $n, array $m, $class)
    {
        $inline = self::$custom_reduction;
        return $inline($n);
    }
    /**
     * Generate Custom Reduction
     *
     * @param PHP $m
     * @param string $class
     * @return callable
     */
    protected static function generateCustomReduction(PHP $m, $class)
    {
        $m_length = count($m->value);
        if ($m_length < 5) {
            $code = '
                $lhs = new ' . $class . '();
                $lhs->value = $x;
                $rhs = new ' . $class . '();
                $rhs->value = [' . implode(',', array_map('self::float2string', $m->value)) . '];
                list(, $temp) = $lhs->divide($rhs);
                return $temp->value;
            ';
            eval('$func = function ($x) { ' . $code . '};');
            self::$custom_reduction = $func;
            //self::$custom_reduction = \Closure::bind($func, $m, $class);
            return $func;
        }
        $lhs = new $class();
        $lhs_value =& $lhs->value;
        $lhs_value = self::array_repeat(0, $m_length + ($m_length >> 1));
        $lhs_value[] = 1;
        $rhs = new $class();
        list($u, $m1) = $lhs->divide($m);
        if ($class::BASE != 26) {
            $u = $u->value;
        } else {
            $lhs_value = self::array_repeat(0, 2 * $m_length);
            $lhs_value[] = 1;
            $rhs = new $class();
            list($u) = $lhs->divide($m);
            $u = $u->value;
        }
        $m = $m->value;
        $m1 = $m1->value;
        $cutoff = count($m) + (count($m) >> 1);
        $code = '
            if (count($n) > ' . 2 * count($m) . ') {
                $lhs = new ' . $class . '();
                $rhs = new ' . $class . '();
                $lhs->value = $n;
                $rhs->value = [' . implode(',', array_map('self::float2string', $m)) . '];
                list(, $temp) = $lhs->divide($rhs);
                return $temp->value;
            }

            $lsd = array_slice($n, 0, ' . $cutoff . ');
            $msd = array_slice($n, ' . $cutoff . ');';
        $code .= self::generateInlineTrim('msd');
        $code .= self::generateInlineMultiply('msd', $m1, 'temp', $class);
        $code .= self::generateInlineAdd('lsd', 'temp', 'n', $class);
        $code .= '$temp = array_slice($n, ' . (count($m) - 1) . ');';
        $code .= self::generateInlineMultiply('temp', $u, 'temp2', $class);
        $code .= self::generateInlineTrim('temp2');
        $code .= $class::BASE == 26 ? '$temp = array_slice($temp2, ' . (count($m) + 1) . ');' : '$temp = array_slice($temp2, ' . ((count($m) >> 1) + 1) . ');';
        $code .= self::generateInlineMultiply('temp', $m, 'temp2', $class);
        $code .= self::generateInlineTrim('temp2');
        /*
        if ($class::BASE == 26) {
            $code.= '$n = array_slice($n, 0, ' . (count($m) + 1) . ');
                     $temp2 = array_slice($temp2, 0, ' . (count($m) + 1) . ');';
        }
        */
        $code .= self::generateInlineSubtract2('n', 'temp2', 'temp', $class);
        $subcode = self::generateInlineSubtract1('temp', $m, 'temp2', $class);
        $subcode .= '$temp = $temp2;';
        $code .= self::generateInlineCompare($m, 'temp', $subcode);
        $code .= 'return $temp;';
        eval('$func = function ($n) { ' . $code . '};');
        self::$custom_reduction = $func;
        return $func;
        //self::$custom_reduction = \Closure::bind($func, $m, $class);
    }
    /**
     * Inline Trim
     *
     * Removes leading zeros
     *
     * @param string $name
     * @return string
     */
    private static function generateInlineTrim($name)
    {
        return '
            for ($i = count($' . $name . ') - 1; $i >= 0; --$i) {
                if ($' . $name . '[$i]) {
                    break;
                }
                unset($' . $name . '[$i]);
            }';
    }
    /**
     * Inline Multiply (unknown, known)
     *
     * @param string $input
     * @param array $arr
     * @param string $output
     * @param string $class
     * @return string
     */
    private static function generateInlineMultiply($input, array $arr, $output, $class)
    {
        if (!count($arr)) {
            return 'return [];';
        }
        $regular = '
            $length = count($' . $input . ');
            if (!$length) {
                $' . $output . ' = [];
            }else{
            $' . $output . ' = array_fill(0, $length + ' . count($arr) . ', 0);
            $carry = 0;';
        for ($i = 0; $i < count($arr); $i++) {
            $regular .= '
                $subtemp = $' . $input . '[0] * ' . $arr[$i];
            $regular .= $i ? ' + $carry;' : ';';
            $regular .= '$carry = ';
            $regular .= $class::BASE === 26 ? 'intval($subtemp / 0x4000000);' : '$subtemp >> 31;';
            $regular .= '$' . $output . '[' . $i . '] = ';
            if ($class::BASE === 26) {
                $regular .= '(int) (';
            }
            $regular .= '$subtemp - ' . $class::BASE_FULL . ' * $carry';
            $regular .= $class::BASE === 26 ? ');' : ';';
        }
        $regular .= '$' . $output . '[' . count($arr) . '] = $carry;';
        $regular .= '
            for ($i = 1; $i < $length; ++$i) {';
        for ($j = 0; $j < count($arr); $j++) {
            $regular .= $j ? '$k++;' : '$k = $i;';
            $regular .= '
                $subtemp = $' . $output . '[$k] + $' . $input . '[$i] * ' . $arr[$j];
            $regular .= $j ? ' + $carry;' : ';';
            $regular .= '$carry = ';
            $regular .= $class::BASE === 26 ? 'intval($subtemp / 0x4000000);' : '$subtemp >> 31;';
            $regular .= '$' . $output . '[$k] = ';
            if ($class::BASE === 26) {
                $regular .= '(int) (';
            }
            $regular .= '$subtemp - ' . $class::BASE_FULL . ' * $carry';
            $regular .= $class::BASE === 26 ? ');' : ';';
        }
        $regular .= '$' . $output . '[++$k] = $carry; $carry = 0;';
        $regular .= '}}';
        //if (count($arr) < 2 * self::KARATSUBA_CUTOFF) {
        //}
        return $regular;
    }
    /**
     * Inline Addition
     *
     * @param string $x
     * @param string $y
     * @param string $result
     * @param string $class
     * @return string
     */
    private static function generateInlineAdd($x, $y, $result, $class)
    {
        $code = '
            $length = max(count($' . $x . '), count($' . $y . '));
            $' . $result . ' = array_pad($' . $x . ', $length + 1, 0);
            $_' . $y . ' = array_pad($' . $y . ', $length, 0);
            $carry = 0;
            for ($i = 0, $j = 1; $j < $length; $i+=2, $j+=2) {
                $sum = ($' . $result . '[$j] + $_' . $y . '[$j]) * ' . $class::BASE_FULL . '
                           + $' . $result . '[$i] + $_' . $y . '[$i] +
                           $carry;
                $carry = $sum >= ' . self::float2string($class::MAX_DIGIT2) . ';
                $sum = $carry ? $sum - ' . self::float2string($class::MAX_DIGIT2) . ' : $sum;';
        $code .= $class::BASE === 26 ? '$upper = intval($sum / 0x4000000); $' . $result . '[$i] = (int) ($sum - ' . $class::BASE_FULL . ' * $upper);' : '$upper = $sum >> 31; $' . $result . '[$i] = $sum - ' . $class::BASE_FULL . ' * $upper;';
        $code .= '
                $' . $result . '[$j] = $upper;
            }
            if ($j == $length) {
                $sum = $' . $result . '[$i] + $_' . $y . '[$i] + $carry;
                $carry = $sum >= ' . self::float2string($class::BASE_FULL) . ';
                $' . $result . '[$i] = $carry ? $sum - ' . self::float2string($class::BASE_FULL) . ' : $sum;
            }
            if ($carry) {
                for (; $' . $result . '[$i] == ' . $class::MAX_DIGIT . '; ++$i) {
                    $' . $result . '[$i] = 0;
                }
                ++$' . $result . '[$i];
            }';
        $code .= self::generateInlineTrim($result);
        return $code;
    }
    /**
     * Inline Subtraction 2
     *
     * For when $known is more digits than $unknown. This is the harder use case to optimize for.
     *
     * @param string $known
     * @param string $unknown
     * @param string $result
     * @param string $class
     * @return string
     */
    private static function generateInlineSubtract2($known, $unknown, $result, $class)
    {
        $code = '
            $' . $result . ' = $' . $known . ';
            $carry = 0;
            $size = count($' . $unknown . ');
            for ($i = 0, $j = 1; $j < $size; $i+= 2, $j+= 2) {
                $sum = ($' . $known . '[$j] - $' . $unknown . '[$j]) * ' . $class::BASE_FULL . ' + $' . $known . '[$i]
                    - $' . $unknown . '[$i]
                    - $carry;
                $carry = $sum < 0;
                if ($carry) {
                    $sum+= ' . self::float2string($class::MAX_DIGIT2) . ';
                }
                $subtemp = ';
        $code .= $class::BASE === 26 ? 'intval($sum / 0x4000000);' : '$sum >> 31;';
        $code .= '$' . $result . '[$i] = ';
        if ($class::BASE === 26) {
            $code .= '(int) (';
        }
        $code .= '$sum - ' . $class::BASE_FULL . ' * $subtemp';
        if ($class::BASE === 26) {
            $code .= ')';
        }
        $code .= ';
                $' . $result . '[$j] = $subtemp;
            }
            if ($j == $size) {
                $sum = $' . $known . '[$i] - $' . $unknown . '[$i] - $carry;
                $carry = $sum < 0;
                $' . $result . '[$i] = $carry ? $sum + ' . $class::BASE_FULL . ' : $sum;
                ++$i;
            }

            if ($carry) {
                for (; !$' . $result . '[$i]; ++$i) {
                    $' . $result . '[$i] = ' . $class::MAX_DIGIT . ';
                }
                --$' . $result . '[$i];
            }';
        $code .= self::generateInlineTrim($result);
        return $code;
    }
    /**
     * Inline Subtraction 1
     *
     * For when $unknown is more digits than $known. This is the easier use case to optimize for.
     *
     * @param string $unknown
     * @param array $known
     * @param string $result
     * @param string $class
     * @return string
     */
    private static function generateInlineSubtract1($unknown, array $known, $result, $class)
    {
        $code = '$' . $result . ' = $' . $unknown . ';';
        for ($i = 0, $j = 1; $j < count($known); $i += 2, $j += 2) {
            $code .= '$sum = $' . $unknown . '[' . $j . '] * ' . $class::BASE_FULL . ' + $' . $unknown . '[' . $i . '] - ';
            $code .= self::float2string($known[$j] * $class::BASE_FULL + $known[$i]);
            if ($i != 0) {
                $code .= ' - $carry';
            }
            $code .= ';
                if ($carry = $sum < 0) {
                    $sum+= ' . self::float2string($class::MAX_DIGIT2) . ';
                }
                $subtemp = ';
            $code .= $class::BASE === 26 ? 'intval($sum / 0x4000000);' : '$sum >> 31;';
            $code .= '
                $' . $result . '[' . $i . '] = ';
            if ($class::BASE === 26) {
                $code .= ' (int) (';
            }
            $code .= '$sum - ' . $class::BASE_FULL . ' * $subtemp';
            if ($class::BASE === 26) {
                $code .= ')';
            }
            $code .= ';
                $' . $result . '[' . $j . '] = $subtemp;';
        }
        $code .= '$i = ' . $i . ';';
        if ($j == count($known)) {
            $code .= '
                $sum = $' . $unknown . '[' . $i . '] - ' . $known[$i] . ' - $carry;
                $carry = $sum < 0;
                $' . $result . '[' . $i . '] = $carry ? $sum + ' . $class::BASE_FULL . ' : $sum;
                ++$i;';
        }
        $code .= '
            if ($carry) {
                for (; !$' . $result . '[$i]; ++$i) {
                    $' . $result . '[$i] = ' . $class::MAX_DIGIT . ';
                }
                --$' . $result . '[$i];
            }';
        $code .= self::generateInlineTrim($result);
        return $code;
    }
    /**
     * Inline Comparison
     *
     * If $unknown >= $known then loop
     *
     * @param array $known
     * @param string $unknown
     * @param string $subcode
     * @return string
     */
    private static function generateInlineCompare(array $known, $unknown, $subcode)
    {
        $uniqid = uniqid();
        $code = 'loop_' . $uniqid . ':
            $clength = count($' . $unknown . ');
            switch (true) {
                case $clength < ' . count($known) . ':
                    goto end_' . $uniqid . ';
                case $clength > ' . count($known) . ':';
        for ($i = count($known) - 1; $i >= 0; $i--) {
            $code .= '
                case $' . $unknown . '[' . $i . '] > ' . $known[$i] . ':
                    goto subcode_' . $uniqid . ';
                case $' . $unknown . '[' . $i . '] < ' . $known[$i] . ':
                    goto end_' . $uniqid . ';';
        }
        $code .= '
                default:
                    // do subcode
            }

            subcode_' . $uniqid . ':' . $subcode . '
            goto loop_' . $uniqid . ';

            end_' . $uniqid . ':';
        return $code;
    }
    /**
    * Convert a float to a string
    *
    * If you do echo floatval(pow(2, 52)) you'll get 4.6116860184274E+18. It /can/ be displayed without a loss of
    precision but displayed in this way there will be precision loss, hence the need for this method.
    *
    * @param (int | float) $num
    * @return string
    */
    private static function float2string($num)
    {
        if (!is_float($num)) {
            return $num;
        }
        if ($num < 0) {
            return '-' . self::float2string(abs($num));
        }
        $temp = '';
        while ($num) {
            $temp = fmod($num, 10) . $temp;
            $num = floor($num / 10);
        }
        return $temp;
    }
}<?php

/**
 * PHP Montgomery Modular Exponentiation Engine with interleaved multiplication
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
/**
 * PHP Montgomery Modular Exponentiation Engine with interleaved multiplication
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MontgomeryMult extends Montgomery
{
    /**
    * Montgomery Multiply
    *
    * Interleaves the montgomery reduction and long multiplication algorithms together as described in
    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
    *
    * @see self::_prepMontgomery()
    * @see self::_montgomery()
    * @access private
    * @param array $x
    * @param array $y
    * @param array $m
    * @param string $class
    * @return array
    */
    public static function multiplyReduce(array $x, array $y, array $m, $class)
    {
        // the following code, although not callable, can be run independently of the above code
        // although the above code performed better in my benchmarks the following could might
        // perform better under different circumstances. in lieu of deleting it it's just been
        // made uncallable
        static $cache = [self::VARIABLE => [], self::DATA => []];
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $m;
            $cache[self::DATA][] = self::modInverse67108864($m, $class);
        }
        $n = max(count($x), count($y), count($m));
        $x = array_pad($x, $n, 0);
        $y = array_pad($y, $n, 0);
        $m = array_pad($m, $n, 0);
        $a = [self::VALUE => self::array_repeat(0, $n + 1)];
        for ($i = 0; $i < $n; ++$i) {
            $temp = $a[self::VALUE][0] + $x[$i] * $y[0];
            $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31);
            $temp = $temp * $cache[self::DATA][$key];
            $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31);
            $temp = $class::addHelper($class::regularMultiply([$x[$i]], $y), false, $class::regularMultiply([$temp], $m), false);
            $a = $class::addHelper($a[self::VALUE], false, $temp[self::VALUE], false);
            $a[self::VALUE] = array_slice($a[self::VALUE], 1);
        }
        if (self::compareHelper($a[self::VALUE], false, $m, false) >= 0) {
            $a = $class::subtractHelper($a[self::VALUE], false, $m, false);
        }
        return $a[self::VALUE];
    }
}<?php

/**
 * PHP Classic Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
/**
 * PHP Classic Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Classic extends Base
{
    /**
     * Regular Division
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @return array
     */
    protected static function reduce(array $x, array $n, $class)
    {
        $lhs = new $class();
        $lhs->value = $x;
        $rhs = new $class();
        $rhs->value = $n;
        list(, $temp) = $lhs->divide($rhs);
        return $temp->value;
    }
}<?php

/**
 * PHP Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP;

use phpseclib3\Math\BigInteger\Engines\PHP;
/**
 * PHP Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Base extends PHP
{
    /**
     * Cache constants
     *
     * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
     *
     * @access private
     */
    const VARIABLE = 0;
    /**
     * $cache[self::DATA] contains the cached data.
     *
     * @access private
     */
    const DATA = 1;
    /**
     * Test for engine validity
     *
     * @return bool
     */
    public static function isValidEngine()
    {
        return static::class != __CLASS__;
    }
    /**
    * Performs modular exponentiation.
    *
    * The most naive approach to modular exponentiation has very unreasonable requirements, and
    and although the approach involving repeated squaring does vastly better, it, too, is impractical
    for our purposes.  The reason being that division - by far the most complicated and time-consuming
    of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
    *
    * Modular reductions resolve this issue.  Although an individual modular reduction takes more time
    then an individual division, when performed in succession (with the same modulo), they're a lot faster.
    *
    * The two most commonly used modular reductions are Barrett and Montgomery reduction.  Montgomery reduction,
    although faster, only works when the gcd of the modulo and of the base being used is 1.  In RSA, when the
    base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
    the product of two odd numbers is odd), but what about when RSA isn't used?
    *
    * In contrast, Barrett reduction has no such constraint.  As such, some bigint implementations perform a
    Barrett reduction after every operation in the modpow function.  Others perform Barrett reductions when the
    modulo is even and Montgomery reductions when the modulo is odd.  BigInteger.java's modPow method, however,
    uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
    the other, a power of two - and recombine them, later.  This is the method that this modPow function uses.
    {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
    *
    * @param \phpseclib3\Math\BigInteger\Engines\PHP $x
    * @param \phpseclib3\Math\BigInteger\Engines\PHP $e
    * @param \phpseclib3\Math\BigInteger\Engines\PHP $n
    * @param string $class
    * @return \phpseclib3\Math\BigInteger\Engines\PHP
    */
    protected static function powModHelper(PHP $x, PHP $e, PHP $n, $class)
    {
        if (empty($e->value)) {
            $temp = new $class();
            $temp->value = [1];
            return $x->normalize($temp);
        }
        if ($e->value == [1]) {
            list(, $temp) = $x->divide($n);
            return $x->normalize($temp);
        }
        if ($e->value == [2]) {
            $temp = new $class();
            $temp->value = $class::square($x->value);
            list(, $temp) = $temp->divide($n);
            return $x->normalize($temp);
        }
        return $x->normalize(static::slidingWindow($x, $e, $n, $class));
    }
    /**
     * Modular reduction preparation
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @see self::slidingWindow()
     * @return array
     */
    protected static function prepareReduce(array $x, array $n, $class)
    {
        return static::reduce($x, $n, $class);
    }
    /**
     * Modular multiply
     *
     * @param array $x
     * @param array $y
     * @param array $n
     * @param string $class
     * @see self::slidingWindow()
     * @return array
     */
    protected static function multiplyReduce(array $x, array $y, array $n, $class)
    {
        $temp = $class::multiplyHelper($x, false, $y, false);
        return static::reduce($temp[self::VALUE], $n, $class);
    }
    /**
     * Modular square
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @see self::slidingWindow()
     * @return array
     */
    protected static function squareReduce(array $x, array $n, $class)
    {
        return static::reduce($class::square($x), $n, $class);
    }
}<?php

/**
 * PHP Default Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP;

use phpseclib3\Math\BigInteger\Engines\PHP\Reductions\EvalBarrett;
/**
 * PHP Default Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DefaultEngine extends EvalBarrett
{
}<?php

/**
 * OpenSSL Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath;

use phpseclib3\Math\BigInteger\Engines\OpenSSL as Progenitor;
/**
 * OpenSSL Modular Exponentiation Engine
 *
 * @package BCMath
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSL extends Progenitor
{
}<?php

/**
 * Built-In BCMath Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath;

use phpseclib3\Math\BigInteger\Engines\BCMath;
/**
 * Built-In BCMath Modular Exponentiation Engine
 *
 * @package BCMath
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BuiltIn extends BCMath
{
    /**
     * Performs modular exponentiation.
     *
     * @param BCMath $x
     * @param BCMath $e
     * @param BCMath $n
     * @return BCMath
     */
    protected static function powModHelper(BCMath $x, BCMath $e, BCMath $n)
    {
        $temp = new BCMath();
        $temp->value = bcpowmod($x->value, $e->value, $n->value);
        return $x->normalize($temp);
    }
}<?php

/**
 * BCMath Barrett Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath\Reductions;

use phpseclib3\Math\BigInteger\Engines\BCMath\Base;
/**
 * PHP Barrett Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Barrett extends Base
{
    /**
     * Cache constants
     *
     * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
     *
     * @access private
     */
    const VARIABLE = 0;
    /**
     * $cache[self::DATA] contains the cached data.
     *
     * @access private
     */
    const DATA = 1;
    /**
    * Barrett Modular Reduction
    *
    * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information.  Modified slightly,
    so as not to require negative numbers (initially, this script didn't support negative numbers).
    *
    * Employs "folding", as described at
    {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}.  To quote from
    it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
    *
    * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
    usable on account of (1) its not using reasonable radix points as discussed in
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
    radix points, it only works when there are an even number of digits in the denominator.  The reason for (2) is that
    (x >> 1) + (x >> 1) != x / 2 + x / 2.  If x is even, they're the same, but if x is odd, they're not.  See the in-line
    comments for details.
    *
    * @param string $n
    * @param string $m
    * @return (array | string)
    */
    protected static function reduce($n, $m)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        $m_length = strlen($m);
        if (strlen($n) > 2 * $m_length) {
            return bcmod($n, $m);
        }
        // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
        if ($m_length < 5) {
            return self::regularBarrett($n, $m);
        }
        // n = 2 * m.length
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $m;
            $lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1));
            $u = bcdiv($lhs, $m, 0);
            $m1 = bcsub($lhs, bcmul($u, $m));
            $cache[self::DATA][] = [
                'u' => $u,
                // m.length >> 1 (technically (m.length >> 1) + 1)
                'm1' => $m1,
            ];
        } else {
            extract($cache[self::DATA][$key]);
        }
        $cutoff = $m_length + ($m_length >> 1);
        $lsd = \Phabel\Target\Php80\Polyfill::substr($n, -$cutoff);
        $msd = \Phabel\Target\Php80\Polyfill::substr($n, 0, -$cutoff);
        $temp = bcmul($msd, $m1);
        // m.length + (m.length >> 1)
        $n = bcadd($lsd, $temp);
        // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers)
        //if ($m_length & 1) {
        //    return self::regularBarrett($n, $m);
        //}
        // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
        $temp = \Phabel\Target\Php80\Polyfill::substr($n, 0, -$m_length + 1);
        // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
        // if odd:  ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
        $temp = bcmul($temp, $u);
        // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
        // if odd:  (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
        $temp = \Phabel\Target\Php80\Polyfill::substr($temp, 0, -($m_length >> 1) - 1);
        // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
        // if odd:  (m.length - (m.length >> 1)) + m.length     = 2 * m.length - (m.length >> 1)
        $temp = bcmul($temp, $m);
        // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
        // number from a m.length + (m.length >> 1) + 1 digit number.  ie. there'd be an extra digit and the while loop
        // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
        $result = bcsub($n, $temp);
        //if (bccomp($result, '0') < 0) {
        if ($result[0] == '-') {
            $temp = '1' . str_repeat('0', $m_length + 1);
            $result = bcadd($result, $temp);
        }
        while (bccomp($result, $m) >= 0) {
            $result = bcsub($result, $m);
        }
        return $result;
    }
    /**
    * (Regular) Barrett Modular Reduction
    *
    * For numbers with more than four digits BigInteger::_barrett() is faster.  The difference between that and this
    is that this function does not fold the denominator into a smaller form.
    *
    * @param string $x
    * @param string $n
    * @return string
    */
    private static function regularBarrett($x, $n)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        $n_length = strlen($n);
        if (strlen($x) > 2 * $n_length) {
            return bcmod($x, $n);
        }
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $n;
            $lhs = '1' . str_repeat('0', 2 * $n_length);
            $cache[self::DATA][] = bcdiv($lhs, $n, 0);
        }
        $temp = \Phabel\Target\Php80\Polyfill::substr($x, 0, -$n_length + 1);
        $temp = bcmul($temp, $cache[self::DATA][$key]);
        $temp = \Phabel\Target\Php80\Polyfill::substr($temp, 0, -$n_length - 1);
        $r1 = \Phabel\Target\Php80\Polyfill::substr($x, -$n_length - 1);
        $r2 = \Phabel\Target\Php80\Polyfill::substr(bcmul($temp, $n), -$n_length - 1);
        $result = bcsub($r1, $r2);
        //if (bccomp($result, '0') < 0) {
        if ($result[0] == '-') {
            $q = '1' . str_repeat('0', $n_length + 1);
            $result = bcadd($result, $q);
        }
        while (bccomp($result, $n) >= 0) {
            $result = bcsub($result, $n);
        }
        return $result;
    }
}<?php

/**
 * BCMath Dynamic Barrett Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath\Reductions;

use phpseclib3\Math\BigInteger\Engines\BCMath\Base;
use phpseclib3\Math\BigInteger\Engines\BCMath;
/**
 * PHP Barrett Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EvalBarrett extends Base
{
    /**
     * Custom Reduction Function
     *
     * @see self::generateCustomReduction
     */
    private static $custom_reduction;
    /**
    * Barrett Modular Reduction
    *
    * This calls a dynamically generated loop unrolled function that's specific to a given modulo.
    Array lookups are avoided as are if statements testing for how many bits the host OS supports, etc.
    *
    * @param string $n
    * @param string $m
    * @return string
    */
    protected static function reduce($n, $m)
    {
        $inline = self::$custom_reduction;
        return $inline($n);
    }
    /**
     * Generate Custom Reduction
     *
     * @param BCMath $m
     * @param string $class
     * @return (callable | void)
     */
    protected static function generateCustomReduction(BCMath $m, $class)
    {
        $m_length = strlen($m);
        if ($m_length < 5) {
            $code = 'return bcmod($x, $n);';
            eval('$func = function ($n) { ' . $code . '};');
            self::$custom_reduction = $func;
            return;
        }
        $lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1));
        $u = bcdiv($lhs, $m, 0);
        $m1 = bcsub($lhs, bcmul($u, $m));
        $cutoff = $m_length + ($m_length >> 1);
        $m = "'{$m}'";
        $u = "'{$u}'";
        $m1 = "'{$m1}'";
        $code .= '
            $lsd = substr($n, -' . $cutoff . ');
            $msd = substr($n, 0, -' . $cutoff . ');

            $temp = bcmul($msd, ' . $m1 . ');
            $n = bcadd($lsd, $temp);

            $temp = substr($n, 0, ' . (-$m_length + 1) . ');
            $temp = bcmul($temp, ' . $u . ');
            $temp = substr($temp, 0, ' . (-($m_length >> 1) - 1) . ');
            $temp = bcmul($temp, ' . $m . ');

            $result = bcsub($n, $temp);

            if ($result[0] == \'-\') {
                $temp = \'1' . str_repeat('0', $m_length + 1) . '\';
                $result = bcadd($result, $temp);
            }

            while (bccomp($result, ' . $m . ') >= 0) {
                $result = bcsub($result, ' . $m . ');
            }

            return $result;';
        eval('$func = function ($n) { ' . $code . '};');
        self::$custom_reduction = $func;
        return $func;
    }
}<?php

/**
 * Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath;

use phpseclib3\Math\BigInteger\Engines\BCMath;
/**
 * Sliding Window Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Base extends BCMath
{
    /**
     * Cache constants
     *
     * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
     *
     * @access private
     */
    const VARIABLE = 0;
    /**
     * $cache[self::DATA] contains the cached data.
     *
     * @access private
     */
    const DATA = 1;
    /**
     * Test for engine validity
     *
     * @return bool
     */
    public static function isValidEngine()
    {
        return static::class != __CLASS__;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param \phpseclib3\Math\BigInteger\Engines\BCMath $x
     * @param \phpseclib3\Math\BigInteger\Engines\BCMath $e
     * @param \phpseclib3\Math\BigInteger\Engines\BCMath $n
     * @param string $class
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    protected static function powModHelper(BCMath $x, BCMath $e, BCMath $n, $class)
    {
        if (empty($e->value)) {
            $temp = new $class();
            $temp->value = '1';
            return $x->normalize($temp);
        }
        return $x->normalize(static::slidingWindow($x, $e, $n, $class));
    }
    /**
     * Modular reduction preparation
     *
     * @param string $x
     * @param string $n
     * @param string $class
     * @see self::slidingWindow()
     * @return string
     */
    protected static function prepareReduce($x, $n, $class)
    {
        return static::reduce($x, $n);
    }
    /**
     * Modular multiply
     *
     * @param string $x
     * @param string $y
     * @param string $n
     * @param string $class
     * @see self::slidingWindow()
     * @return string
     */
    protected static function multiplyReduce($x, $y, $n, $class)
    {
        return static::reduce(bcmul($x, $y), $n);
    }
    /**
     * Modular square
     *
     * @param string $x
     * @param string $n
     * @param string $class
     * @see self::slidingWindow()
     * @return string
     */
    protected static function squareReduce($x, $n, $class)
    {
        return static::reduce(bcmul($x, $x), $n);
    }
}<?php

/**
 * BCMath Default Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath;

use phpseclib3\Math\BigInteger\Engines\BCMath\Reductions\Barrett;
/**
 * PHP Default Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DefaultEngine extends Barrett
{
}<?php

/**
 * GMP BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Exception\BadConfigurationException;
/**
 * GMP Engine.
 *
 * @package GMP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class GMP extends Engine
{
    /**
     * Can Bitwise operations be done fast?
     *
     * @see parent::bitwise_leftRotate()
     * @see parent::bitwise_rightRotate()
     * @access protected
     */
    const FAST_BITWISE = true;
    /**
     * Engine Directory
     *
     * @see parent::setModExpEngine
     * @access protected
     */
    const ENGINE_DIR = 'GMP';
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    protected static $modexpEngine;
    /**
     * Engine Validity Flag
     *
     * @var bool
     */
    protected static $isValidEngine;
    /**
     * BigInteger(0)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\GMP
     */
    protected static $zero;
    /**
     * BigInteger(1)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\GMP
     */
    protected static $one;
    /**
     * BigInteger(2)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\GMP
     */
    protected static $two;
    /**
     * Primes > 2 and < 1000
     *
     * Unused for GMP Engine
     *
     * @var mixed
     */
    protected static $primes;
    /**
     * Test for engine validity
     *
     * @see parent::__construct()
     * @return bool
     */
    public static function isValidEngine()
    {
        return extension_loaded('gmp');
    }
    /**
     * Default constructor
     *
     * @param mixed $x integer Base-10 number or base-$base number if $base set.
     * @param int $base
     * @see parent::__construct()
     * @return \phpseclib3\Math\BigInteger\Engines\GMP
     */
    public function __construct($x = 0, $base = 10)
    {
        if (!isset(self::$isValidEngine)) {
            self::$isValidEngine = self::isValidEngine();
        }
        if (!self::$isValidEngine) {
            throw new BadConfigurationException('GMP is not setup correctly on this system');
        }
        if ($x instanceof \GMP) {
            $this->value = $x;
            return;
        }
        $this->value = gmp_init(0);
        parent::__construct($x, $base);
    }
    /**
     * Initialize a GMP BigInteger Engine instance
     *
     * @param int $base
     * @see parent::__construct()
     */
    protected function initialize($base)
    {
        switch (abs($base)) {
            case 256:
                $this->value = gmp_import($this->value);
                if ($this->is_negative) {
                    $this->value = -$this->value;
                }
                break;
            case 16:
                $temp = $this->is_negative ? '-0x' . $this->value : '0x' . $this->value;
                $this->value = gmp_init($temp);
                break;
            case 10:
                $this->value = gmp_init(isset($this->value) ? $this->value : '0');
        }
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function toString()
    {
        return (string) $this->value;
    }
    /**
    * Converts a BigInteger to a bit string (eg. base-2).
    *
    * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
    saved as two's compliment.
    *
    * @param bool $twos_compliment
    * @return string
    */
    public function toBits($twos_compliment = false)
    {
        $hex = $this->toHex($twos_compliment);
        $bits = gmp_strval(gmp_init($hex, 16), 2);
        if ($this->precision > 0) {
            $bits = \Phabel\Target\Php80\Polyfill::substr($bits, -$this->precision);
        }
        if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
            return '0' . $bits;
        }
        return $bits;
    }
    /**
     * Converts a BigInteger to a byte string (eg. base-256).
     *
     * @param bool $twos_compliment
     * @return string
     */
    function toBytes($twos_compliment = false)
    {
        if ($twos_compliment) {
            return $this->toBytesHelper();
        }
        if (gmp_cmp($this->value, gmp_init(0)) == 0) {
            return $this->precision > 0 ? str_repeat(chr(0), $this->precision + 1 >> 3) : '';
        }
        $temp = gmp_export($this->value);
        return $this->precision > 0 ? \Phabel\Target\Php80\Polyfill::substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : ltrim($temp, chr(0));
    }
    /**
     * Adds two BigIntegers.
     *
     * @param GMP $y
     * @return GMP
     */
    public function add(GMP $y)
    {
        $temp = new self();
        $temp->value = $this->value + $y->value;
        return $this->normalize($temp);
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param GMP $y
     * @return GMP
     */
    public function subtract(GMP $y)
    {
        $temp = new self();
        $temp->value = $this->value - $y->value;
        return $this->normalize($temp);
    }
    /**
     * Multiplies two BigIntegers.
     *
     * @param GMP $x
     * @return GMP
     */
    public function multiply(GMP $x)
    {
        $temp = new self();
        $temp->value = $this->value * $x->value;
        return $this->normalize($temp);
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param GMP $y
    * @return GMP
    */
    public function divide(GMP $y)
    {
        $quotient = new self();
        $remainder = new self();
        list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
        if (gmp_sign($remainder->value) < 0) {
            $remainder->value = $remainder->value + gmp_abs($y->value);
        }
        return [$this->normalize($quotient), $this->normalize($remainder)];
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param GMP $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @access public
    * @see self::equals()
    */
    public function compare(GMP $y)
    {
        $r = gmp_cmp($this->value, $y->value);
        if ($r < -1) {
            $r = -1;
        }
        if ($r > 1) {
            $r = 1;
        }
        return $r;
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param GMP $x
     * @return bool
     */
    public function equals(GMP $x)
    {
        return $this->value == $x->value;
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     *
     * @param GMP $n
     * @return (false | GMP)
     */
    public function modInverse(GMP $n)
    {
        $temp = new self();
        $temp->value = gmp_invert($this->value, $n->value);
        return $temp->value === false ? false : $this->normalize($temp);
    }
    /**
    * Calculates the greatest common divisor and Bezout's identity.
    *
    * Say you have 693 and 609.  The GCD is 21.  Bezout's identity states that there exist integers x and y such that
    693*x + 609*y == 21.  In point of fact, there are actually an infinite number of x and y combinations and which
    combination is returned is dependent upon which mode is in use.  See
    {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
    *
    * @param \phpseclib3\Math\BigInteger\Engines\GMP $n
    * @return \phpseclib3\Math\BigInteger\Engines\GMP[]
    */
    public function extendedGCD(GMP $n)
    {
        extract(gmp_gcdext($this->value, $n->value));
        return ['gcd' => $this->normalize(new self($g)), 'x' => $this->normalize(new self($s)), 'y' => $this->normalize(new self($t))];
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param GMP $n
     * @return GMP
     */
    public function gcd(GMP $n)
    {
        $r = gmp_gcd($this->value, $n->value);
        return $this->normalize(new self($r));
    }
    /**
     * Absolute value.
     *
     * @return \phpseclib3\Math\BigInteger\Engines\GMP
     * @access public
     */
    public function abs()
    {
        $temp = new self();
        $temp->value = gmp_abs($this->value);
        return $temp;
    }
    /**
     * Logical And
     *
     * @param GMP $x
     * @return GMP
     */
    public function bitwise_and(GMP $x)
    {
        $temp = new self();
        $temp->value = $this->value & $x->value;
        return $this->normalize($temp);
    }
    /**
     * Logical Or
     *
     * @param GMP $x
     * @return GMP
     */
    public function bitwise_or(GMP $x)
    {
        $temp = new self();
        $temp->value = $this->value | $x->value;
        return $this->normalize($temp);
    }
    /**
     * Logical Exclusive Or
     *
     * @param GMP $x
     * @return GMP
     */
    public function bitwise_xor(GMP $x)
    {
        $temp = new self();
        $temp->value = $this->value ^ $x->value;
        return $this->normalize($temp);
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\GMP
     */
    public function bitwise_rightShift($shift)
    {
        // 0xFFFFFFFF >> 2 == -1 (on 32-bit systems)
        // gmp_init('0xFFFFFFFF') >> 2 == gmp_init('0x3FFFFFFF')
        $temp = new self();
        $temp->value = $this->value >> $shift;
        return $this->normalize($temp);
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\GMP
     */
    public function bitwise_leftShift($shift)
    {
        $temp = new self();
        $temp->value = $this->value << $shift;
        return $this->normalize($temp);
    }
    /**
     * Performs modular exponentiation.
     *
     * @param GMP $e
     * @param GMP $n
     * @return GMP
     */
    public function modPow(GMP $e, GMP $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * Alias for modPow().
     *
     * @param GMP $e
     * @param GMP $n
     * @return GMP
     */
    public function powMod(GMP $e, GMP $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * @param GMP $e
     * @param GMP $n
     * @return GMP
     */
    protected function powModInner(GMP $e, GMP $n)
    {
        $class = self::$modexpEngine;
        return $class::powModHelper($this, $e, $n);
    }
    /**
     * Normalize
     *
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
     *
     * @param GMP $result
     * @return GMP
     */
    protected function normalize(GMP $result)
    {
        $result->precision = $this->precision;
        $result->bitmask = $this->bitmask;
        if ($result->bitmask !== false) {
            $flip = $result->value < 0;
            if ($flip) {
                $result->value = -$result->value;
            }
            $result->value = $result->value & $result->bitmask->value;
            if ($flip) {
                $result->value = -$result->value;
            }
        }
        return $result;
    }
    /**
     * Performs some post-processing for randomRangePrime
     *
     * @param Engine $x
     * @param Engine $min
     * @param Engine $max
     * @return GMP
     */
    protected static function randomRangePrimeInner(Engine $x, Engine $min, Engine $max)
    {
        $p = gmp_nextprime($x->value);
        if ($p <= $max->value) {
            return new self($p);
        }
        if ($min->value != $x->value) {
            $x = new self($x->value - 1);
        }
        return self::randomRangePrime($min, $x);
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param GMP $min
     * @param GMP $max
     * @return (false | GMP)
     */
    public static function randomRangePrime(GMP $min, GMP $max)
    {
        return self::randomRangePrimeOuter($min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param GMP $min
    * @param GMP $max
    * @return GMP
    */
    public static function randomRange(GMP $min, GMP $max)
    {
        return self::randomRangeHelper($min, $max);
    }
    /**
     * Make the current number odd
     *
     * If the current number is odd it'll be unchanged.  If it's even, one will be added to it.
     *
     * @see self::randomPrime()
     */
    protected function make_odd()
    {
        gmp_setbit($this->value, 0);
    }
    /**
     * Tests Primality
     *
     * @param int $t
     * @return bool
     */
    protected function testPrimality($t)
    {
        return gmp_prob_prime($this->value, $t) != 0;
    }
    /**
     * Calculates the nth root of a biginteger.
     *
     * Returns the nth root of a positive biginteger, where n defaults to 2
     *
     * @param int $n
     * @return GMP
     */
    protected function rootInner($n)
    {
        $root = new self();
        $root->value = gmp_root($this->value, $n);
        return $this->normalize($root);
    }
    /**
     * Performs exponentiation.
     *
     * @param GMP $n
     * @return GMP
     */
    public function pow(GMP $n)
    {
        $temp = new self();
        $temp->value = $this->value ** $n->value;
        return $this->normalize($temp);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param GMP ...$nums
     * @return GMP
     */
    public static function min(GMP ...$nums)
    {
        return self::minHelper($nums);
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param GMP ...$nums
     * @return GMP
     */
    public static function max(GMP ...$nums)
    {
        return self::maxHelper($nums);
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param GMP $min
     * @param GMP $max
     * @return bool
     */
    public function between(GMP $min, GMP $max)
    {
        return $this->compare($min) >= 0 && $this->compare($max) <= 0;
    }
    /**
    * Create Recurring Modulo Function
    *
    * Sometimes it may be desirable to do repeated modulos with the same number outside of
    modular exponentiation
    *
    * @return callable
    */
    public function createRecurringModuloFunction()
    {
        $temp = $this->value;
        return function (GMP $x) use($temp) {
            return new GMP($x->value % $temp);
        };
    }
    /**
     * Scan for 1 and right shift by that amount
     *
     * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
     *
     * @param GMP $r
     * @return int
     */
    public static function scan1divide(GMP $r)
    {
        $s = gmp_scan1($r->value, 0);
        $r->value >>= $s;
        return $s;
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return gmp_testbit($this->value, 0);
    }
    /**
     * Tests if a bit is set
     *
     * @return boolean
     */
    public function testBit($x)
    {
        return gmp_testbit($this->value, $x);
    }
    /**
     * Is Negative?
     *
     * @return boolean
     */
    public function isNegative()
    {
        return gmp_sign($this->value) == -1;
    }
    /**
     * Negate
     *
     * Given $k, returns -$k
     *
     * @return GMP
     */
    public function negate()
    {
        $temp = clone $this;
        $temp->value = -$this->value;
        return $temp;
    }
}<?php

/**
 * Bootstrapping File for phpseclib
 *
 * composer isn't a requirement for phpseclib 2.0 but this file isn't really required
 * either. it's a bonus for those using composer but if you're not phpseclib will
 * still work
 *
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 */
if (extension_loaded('mbstring')) {
    // 2 - MB_OVERLOAD_STRING
    // mbstring.func_overload is deprecated in php 7.2 and removed in php 8.0.
    if (version_compare(PHP_VERSION, '8.0.0') < 0 && ini_get('mbstring.func_overload') & 2) {
        throw new UnexpectedValueException('Overloading of string functions using mbstring.func_overload is not supported by phpseclib.');
    }
}{
    "name": "kelunik/certificate",
    "description": "Access certificate details and transform between different formats.",
    "type": "library",
    "minimum-stability": "dev",
    "prefer-stable": true,
    "license": "MIT",
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "keywords": [
        "certificate",
        "certificates",
        "openssl",
        "x509",
        "pem",
        "der"
    ],
    "support": {
        "issues": "https://github.com/kelunik/certificate/issues"
    },
    "require": {
        "php": ">=5.4",
        "ext-openssl": "*"
    },
    "require-dev": {
        "phpunit/phpunit": "^4.8",
        "fabpot/php-cs-fixer": "^1.9"
    },
    "autoload": {
        "psr-4": {
            "Kelunik\\Certificate\\": "lib"
        }
    }
}
<?php

namespace Kelunik\Certificate;

class Profile
{
    private $commonName;
    private $organizationName;
    private $country;
    /**
     *
     */
    public function __construct($commonName, $organizationName, $country)
    {
        $this->commonName = $commonName;
        $this->organizationName = $organizationName;
        $this->country = $country;
    }
    /**
     *
     */
    public function getCommonName()
    {
        return $this->commonName;
    }
    /**
     *
     */
    public function getOrganizationName()
    {
        return $this->organizationName;
    }
    /**
     *
     */
    public function getCountry()
    {
        return $this->country;
    }
}<?php

namespace Kelunik\Certificate;

class InvalidCertificateException extends \Exception
{
}<?php

namespace Kelunik\Certificate;

class Certificate
{
    private $pem;
    private $info;
    private $issuer;
    private $subject;
    /**
     *
     */
    public function __construct($pem)
    {
        if (is_string($pem)) {
            if (!($cert = @openssl_x509_read($pem))) {
                throw new InvalidCertificateException("Invalid PEM encoded certificate!");
            }
        } else {
            if (\is_resource($pem)) {
                if (\get_resource_type($pem) !== "OpenSSL X.509") {
                    throw new InvalidCertificateException("Invalid resource of type other than 'OpenSSL X.509'!");
                }
                $cert = $pem;
            } else {
                throw new \InvalidArgumentException("Invalid variable type, expected string|resource, got " . gettype($pem));
            }
        }
        if (\openssl_x509_export($pem, $this->pem) === false) {
            throw new InvalidCertificateException("Could not convert 'OpenSSL X.509' resource to PEM!");
        }
        if (!($this->info = openssl_x509_parse($cert))) {
            throw new InvalidCertificateException("Invalid PEM encoded certificate!");
        }
    }
    /**
     *
     */
    public function getNames()
    {
        $san = isset($this->info["extensions"]["subjectAltName"]) ? $this->info["extensions"]["subjectAltName"] : "";
        $names = [];
        $parts = array_map("trim", explode(",", $san));
        foreach ($parts as $part) {
            if (stripos($part, "dns:") === 0) {
                $names[] = \Phabel\Target\Php80\Polyfill::substr($part, 4);
            }
        }
        $names = array_map("strtolower", $names);
        $names = array_unique($names);
        sort($names);
        return $names;
    }
    /**
     *
     */
    public function getSubject()
    {
        if ($this->subject === null) {
            $this->subject = new Profile(isset($this->info["subject"]["CN"]) ? $this->info["subject"]["CN"] : null, isset($this->info["subject"]["O"]) ? $this->info["subject"]["O"] : null, isset($this->info["subject"]["C"]) ? $this->info["subject"]["C"] : null);
        }
        return $this->subject;
    }
    /**
     *
     */
    public function getIssuer()
    {
        if ($this->issuer === null) {
            $this->issuer = new Profile(isset($this->info["issuer"]["CN"]) ? $this->info["issuer"]["CN"] : null, isset($this->info["issuer"]["O"]) ? $this->info["issuer"]["O"] : null, isset($this->info["issuer"]["C"]) ? $this->info["issuer"]["C"] : null);
        }
        return $this->issuer;
    }
    /**
     *
     */
    public function getSerialNumber()
    {
        return $this->info["serialNumber"];
    }
    /**
     *
     */
    public function getValidFrom()
    {
        return $this->info["validFrom_time_t"];
    }
    /**
     *
     */
    public function getValidTo()
    {
        return $this->info["validTo_time_t"];
    }
    /**
     *
     */
    public function getSignatureType()
    {
        // https://3v4l.org/Iu3T2
        if (!isset($this->info["signatureTypeSN"])) {
            throw new FieldNotSupportedException("Signature type is not supported in this version of PHP. Please update your version to a higher bugfix version. See: https://3v4l.org/Iu3T2");
        }
        return $this->info["signatureTypeSN"];
    }
    /**
     *
     */
    public function isSelfSigned()
    {
        return $this->info["subject"] === $this->info["issuer"];
    }
    /**
     *
     */
    public function toPem()
    {
        return $this->pem;
    }
    /**
     *
     */
    public function toDer()
    {
        return self::pemToDer($this->pem);
    }
    /**
     *
     */
    public function __toString()
    {
        return $this->pem;
    }
    /**
     *
     */
    public function __debugInfo()
    {
        return ["commonName" => $this->getSubject()->getCommonName(), "names" => $this->getNames(), "issuedBy" => $this->getIssuer()->getCommonName(), "validFrom" => \Phabel\Target\Php80\Polyfill::date("d.m.Y", $this->getValidFrom()), "validTo" => \Phabel\Target\Php80\Polyfill::date("d.m.Y", $this->getValidTo())];
    }
    /**
     *
     */
    public static function derToPem($der)
    {
        if (!is_string($der)) {
            throw new \InvalidArgumentException("\$der must be a string, " . gettype($der) . " given.");
        }
        return sprintf("-----BEGIN CERTIFICATE-----\n%s-----END CERTIFICATE-----\n", chunk_split(base64_encode($der), 64, "\n"));
    }
    /**
     *
     */
    public static function pemToDer($pem)
    {
        if (!is_string($pem)) {
            throw new \InvalidArgumentException("\$pem must be a string, " . gettype($pem) . " given.");
        }
        $pattern = "@-----BEGIN CERTIFICATE-----\n([a-zA-Z0-9+/=\n]+)-----END CERTIFICATE-----@";
        if (!preg_match($pattern, $pem, $match)) {
            throw new InvalidCertificateException("Invalid PEM could not be converted to DER format.");
        }
        return base64_decode(str_replace(["\n", "\r"], "", trim($match[1])));
    }
}<?php

namespace Kelunik\Certificate;

class FieldNotSupportedException extends \Exception
{
}<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer/autoload_real.php';

return ComposerAutoloaderInita56f38b10c587f7d23477ad1951b93ea::getLoader();
<?php

#
#
# Parsedown
# http://parsedown.org
#
# (c) Emanuil Rusev
# http://erusev.com
#
# For the full license information, view the LICENSE file that was distributed
# with this source code.
#
#
class Parsedown
{
    # ~
    const version = '1.7.4';
    # ~
    /**
     *
     */
    function text($text)
    {
        # make sure no definitions are set
        $this->DefinitionData = array();
        # standardize line breaks
        $text = str_replace(array("\r\n", "\r"), "\n", $text);
        # remove surrounding line breaks
        $text = trim($text, "\n");
        # split text into lines
        $lines = explode("\n", $text);
        # iterate through lines to identify blocks
        $markup = $this->lines($lines);
        # trim line breaks
        $markup = trim($markup, "\n");
        return $markup;
    }
    #
    # Setters
    #
    /**
     *
     */
    function setBreaksEnabled($breaksEnabled)
    {
        $this->breaksEnabled = $breaksEnabled;
        return $this;
    }
    protected $breaksEnabled;
    /**
     *
     */
    function setMarkupEscaped($markupEscaped)
    {
        $this->markupEscaped = $markupEscaped;
        return $this;
    }
    protected $markupEscaped;
    /**
     *
     */
    function setUrlsLinked($urlsLinked)
    {
        $this->urlsLinked = $urlsLinked;
        return $this;
    }
    protected $urlsLinked = true;
    /**
     *
     */
    function setSafeMode($safeMode)
    {
        $this->safeMode = (bool) $safeMode;
        return $this;
    }
    protected $safeMode;
    protected $safeLinksWhitelist = array('http://', 'https://', 'ftp://', 'ftps://', 'mailto:', 'data:image/png;base64,', 'data:image/gif;base64,', 'data:image/jpeg;base64,', 'irc:', 'ircs:', 'git:', 'ssh:', 'news:', 'steam:');
    #
    # Lines
    #
    protected $BlockTypes = array('#' => array('Header'), '*' => array('Rule', 'List'), '+' => array('List'), '-' => array('SetextHeader', 'Table', 'Rule', 'List'), '0' => array('List'), '1' => array('List'), '2' => array('List'), '3' => array('List'), '4' => array('List'), '5' => array('List'), '6' => array('List'), '7' => array('List'), '8' => array('List'), '9' => array('List'), ':' => array('Table'), '<' => array('Comment', 'Markup'), '=' => array('SetextHeader'), '>' => array('Quote'), '[' => array('Reference'), '_' => array('Rule'), '`' => array('FencedCode'), '|' => array('Table'), '~' => array('FencedCode'));
    # ~
    protected $unmarkedBlockTypes = array('Code');
    #
    # Blocks
    #
    /**
     *
     */
    protected function lines(array $lines)
    {
        $CurrentBlock = null;
        foreach ($lines as $line) {
            if (chop($line) === '') {
                if (isset($CurrentBlock)) {
                    $CurrentBlock['interrupted'] = true;
                }
                continue;
            }
            if (strpos($line, "\t") !== false) {
                $parts = explode("\t", $line);
                $line = $parts[0];
                unset($parts[0]);
                foreach ($parts as $part) {
                    $shortage = 4 - mb_strlen($line, 'utf-8') % 4;
                    $line .= str_repeat(' ', $shortage);
                    $line .= $part;
                }
            }
            $indent = 0;
            while (isset($line[$indent]) and $line[$indent] === ' ') {
                $indent++;
            }
            $text = $indent > 0 ? \Phabel\Target\Php80\Polyfill::substr($line, $indent) : $line;
            # ~
            $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
            # ~
            if (isset($CurrentBlock['continuable'])) {
                $Block = $this->{'block' . $CurrentBlock['type'] . 'Continue'}($Line, $CurrentBlock);
                if (isset($Block)) {
                    $CurrentBlock = $Block;
                    continue;
                } else {
                    if ($this->isBlockCompletable($CurrentBlock['type'])) {
                        $CurrentBlock = $this->{'block' . $CurrentBlock['type'] . 'Complete'}($CurrentBlock);
                    }
                }
            }
            # ~
            $marker = $text[0];
            # ~
            $blockTypes = $this->unmarkedBlockTypes;
            if (isset($this->BlockTypes[$marker])) {
                foreach ($this->BlockTypes[$marker] as $blockType) {
                    $blockTypes[] = $blockType;
                }
            }
            #
            # ~
            foreach ($blockTypes as $blockType) {
                $Block = $this->{'block' . $blockType}($Line, $CurrentBlock);
                if (isset($Block)) {
                    $Block['type'] = $blockType;
                    if (!isset($Block['identified'])) {
                        $Blocks[] = $CurrentBlock;
                        $Block['identified'] = true;
                    }
                    if ($this->isBlockContinuable($blockType)) {
                        $Block['continuable'] = true;
                    }
                    $CurrentBlock = $Block;
                    continue 2;
                }
            }
            # ~
            if (isset($CurrentBlock) and !isset($CurrentBlock['type']) and !isset($CurrentBlock['interrupted'])) {
                $CurrentBlock['element']['text'] .= "\n" . $text;
            } else {
                $Blocks[] = $CurrentBlock;
                $CurrentBlock = $this->paragraph($Line);
                $CurrentBlock['identified'] = true;
            }
        }
        # ~
        if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type'])) {
            $CurrentBlock = $this->{'block' . $CurrentBlock['type'] . 'Complete'}($CurrentBlock);
        }
        # ~
        $Blocks[] = $CurrentBlock;
        unset($Blocks[0]);
        # ~
        $markup = '';
        foreach ($Blocks as $Block) {
            if (isset($Block['hidden'])) {
                continue;
            }
            $markup .= "\n";
            $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
        }
        $markup .= "\n";
        # ~
        return $markup;
    }
    /**
     *
     */
    protected function isBlockContinuable($Type)
    {
        return method_exists($this, 'block' . $Type . 'Continue');
    }
    /**
     *
     */
    protected function isBlockCompletable($Type)
    {
        return method_exists($this, 'block' . $Type . 'Complete');
    }
    #
    # Code
    /**
     *
     */
    protected function blockCode($Line, $Block = null)
    {
        if (isset($Block) and !isset($Block['type']) and !isset($Block['interrupted'])) {
            return;
        }
        if ($Line['indent'] >= 4) {
            $text = \Phabel\Target\Php80\Polyfill::substr($Line['body'], 4);
            $Block = array('element' => array('name' => 'pre', 'handler' => 'element', 'text' => array('name' => 'code', 'text' => $text)));
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockCodeContinue($Line, $Block)
    {
        if ($Line['indent'] >= 4) {
            if (isset($Block['interrupted'])) {
                $Block['element']['text']['text'] .= "\n";
                unset($Block['interrupted']);
            }
            $Block['element']['text']['text'] .= "\n";
            $text = \Phabel\Target\Php80\Polyfill::substr($Line['body'], 4);
            $Block['element']['text']['text'] .= $text;
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockCodeComplete($Block)
    {
        $text = $Block['element']['text']['text'];
        $Block['element']['text']['text'] = $text;
        return $Block;
    }
    #
    # Comment
    /**
     *
     */
    protected function blockComment($Line)
    {
        if ($this->markupEscaped or $this->safeMode) {
            return;
        }
        if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!') {
            $Block = array('markup' => $Line['body']);
            if (preg_match('/-->$/', $Line['text'])) {
                $Block['closed'] = true;
            }
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockCommentContinue($Line, array $Block)
    {
        if (isset($Block['closed'])) {
            return;
        }
        $Block['markup'] .= "\n" . $Line['body'];
        if (preg_match('/-->$/', $Line['text'])) {
            $Block['closed'] = true;
        }
        return $Block;
    }
    #
    # Fenced Code
    /**
     *
     */
    protected function blockFencedCode($Line)
    {
        if (preg_match('/^[' . $Line['text'][0] . ']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches)) {
            $Element = array('name' => 'code', 'text' => '');
            if (isset($matches[1])) {
                /**
                 * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes
                 * Every HTML element may have a class attribute specified.
                 * The attribute, if specified, must have a value that is a set
                 * of space-separated tokens representing the various classes
                 * that the element belongs to.
                 * [...]
                 * The space characters, for the purposes of this specification,
                 * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab),
                 * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and
                 * U+000D CARRIAGE RETURN (CR).
                 */
                $language = \Phabel\Target\Php80\Polyfill::substr($matches[1], 0, \Phabel\Target\Php80\Polyfill::strcspn($matches[1], " \t\n\f\r"));
                $class = 'language-' . $language;
                $Element['attributes'] = array('class' => $class);
            }
            $Block = array('char' => $Line['text'][0], 'element' => array('name' => 'pre', 'handler' => 'element', 'text' => $Element));
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockFencedCodeContinue($Line, $Block)
    {
        if (isset($Block['complete'])) {
            return;
        }
        if (isset($Block['interrupted'])) {
            $Block['element']['text']['text'] .= "\n";
            unset($Block['interrupted']);
        }
        if (preg_match('/^' . $Block['char'] . '{3,}[ ]*$/', $Line['text'])) {
            $Block['element']['text']['text'] = \Phabel\Target\Php80\Polyfill::substr($Block['element']['text']['text'], 1);
            $Block['complete'] = true;
            return $Block;
        }
        $Block['element']['text']['text'] .= "\n" . $Line['body'];
        return $Block;
    }
    /**
     *
     */
    protected function blockFencedCodeComplete($Block)
    {
        $text = $Block['element']['text']['text'];
        $Block['element']['text']['text'] = $text;
        return $Block;
    }
    #
    # Header
    /**
     *
     */
    protected function blockHeader($Line)
    {
        if (isset($Line['text'][1])) {
            $level = 1;
            while (isset($Line['text'][$level]) and $Line['text'][$level] === '#') {
                $level++;
            }
            if ($level > 6) {
                return;
            }
            $text = trim($Line['text'], '# ');
            $Block = array('element' => array('name' => 'h' . min(6, $level), 'text' => $text, 'handler' => 'line'));
            return $Block;
        }
    }
    #
    # List
    /**
     *
     */
    protected function blockList($Line)
    {
        list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
        if (preg_match('/^(' . $pattern . '[ ]+)(.*)/', $Line['text'], $matches)) {
            $Block = array('indent' => $Line['indent'], 'pattern' => $pattern, 'element' => array('name' => $name, 'handler' => 'elements'));
            if ($name === 'ol') {
                $listStart = stristr($matches[0], '.', true);
                if ($listStart !== '1') {
                    $Block['element']['attributes'] = array('start' => $listStart);
                }
            }
            $Block['li'] = array('name' => 'li', 'handler' => 'li', 'text' => array($matches[2]));
            $Block['element']['text'][] =& $Block['li'];
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockListContinue($Line, array $Block)
    {
        if ($Block['indent'] === $Line['indent'] and preg_match('/^' . $Block['pattern'] . '(?:[ ]+(.*)|$)/', $Line['text'], $matches)) {
            if (isset($Block['interrupted'])) {
                $Block['li']['text'][] = '';
                $Block['loose'] = true;
                unset($Block['interrupted']);
            }
            unset($Block['li']);
            $text = isset($matches[1]) ? $matches[1] : '';
            $Block['li'] = array('name' => 'li', 'handler' => 'li', 'text' => array($text));
            $Block['element']['text'][] =& $Block['li'];
            return $Block;
        }
        if ($Line['text'][0] === '[' and $this->blockReference($Line)) {
            return $Block;
        }
        if (!isset($Block['interrupted'])) {
            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
            $Block['li']['text'][] = $text;
            return $Block;
        }
        if ($Line['indent'] > 0) {
            $Block['li']['text'][] = '';
            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
            $Block['li']['text'][] = $text;
            unset($Block['interrupted']);
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockListComplete(array $Block)
    {
        if (isset($Block['loose'])) {
            foreach ($Block['element']['text'] as &$li) {
                if (end($li['text']) !== '') {
                    $li['text'][] = '';
                }
            }
        }
        return $Block;
    }
    #
    # Quote
    /**
     *
     */
    protected function blockQuote($Line)
    {
        if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) {
            $Block = array('element' => array('name' => 'blockquote', 'handler' => 'lines', 'text' => (array) $matches[1]));
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockQuoteContinue($Line, array $Block)
    {
        if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) {
            if (isset($Block['interrupted'])) {
                $Block['element']['text'][] = '';
                unset($Block['interrupted']);
            }
            $Block['element']['text'][] = $matches[1];
            return $Block;
        }
        if (!isset($Block['interrupted'])) {
            $Block['element']['text'][] = $Line['text'];
            return $Block;
        }
    }
    #
    # Rule
    /**
     *
     */
    protected function blockRule($Line)
    {
        if (preg_match('/^([' . $Line['text'][0] . '])([ ]*\\1){2,}[ ]*$/', $Line['text'])) {
            $Block = array('element' => array('name' => 'hr'));
            return $Block;
        }
    }
    #
    # Setext
    /**
     *
     */
    protected function blockSetextHeader($Line, array $Block = null)
    {
        if (!isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) {
            return;
        }
        if (chop($Line['text'], $Line['text'][0]) === '') {
            $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
            return $Block;
        }
    }
    #
    # Markup
    /**
     *
     */
    protected function blockMarkup($Line)
    {
        if ($this->markupEscaped or $this->safeMode) {
            return;
        }
        if (preg_match('/^<(\\w[\\w-]*)(?:[ ]*' . $this->regexHtmlAttribute . ')*[ ]*(\\/)?>/', $Line['text'], $matches)) {
            $element = strtolower($matches[1]);
            if (in_array($element, $this->textLevelElements)) {
                return;
            }
            $Block = array('name' => $matches[1], 'depth' => 0, 'markup' => $Line['text']);
            $length = strlen($matches[0]);
            $remainder = \Phabel\Target\Php80\Polyfill::substr($Line['text'], $length);
            if (trim($remainder) === '') {
                if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) {
                    $Block['closed'] = true;
                    $Block['void'] = true;
                }
            } else {
                if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) {
                    return;
                }
                if (preg_match('/<\\/' . $matches[1] . '>[ ]*$/i', $remainder)) {
                    $Block['closed'] = true;
                }
            }
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockMarkupContinue($Line, array $Block)
    {
        if (isset($Block['closed'])) {
            return;
        }
        if (preg_match('/^<' . $Block['name'] . '(?:[ ]*' . $this->regexHtmlAttribute . ')*[ ]*>/i', $Line['text'])) {
            # open
            $Block['depth']++;
        }
        if (preg_match('/(.*?)<\\/' . $Block['name'] . '>[ ]*$/i', $Line['text'], $matches)) {
            # close
            if ($Block['depth'] > 0) {
                $Block['depth']--;
            } else {
                $Block['closed'] = true;
            }
        }
        if (isset($Block['interrupted'])) {
            $Block['markup'] .= "\n";
            unset($Block['interrupted']);
        }
        $Block['markup'] .= "\n" . $Line['body'];
        return $Block;
    }
    #
    # Reference
    /**
     *
     */
    protected function blockReference($Line)
    {
        if (preg_match('/^\\[(.+?)\\]:[ ]*<?(\\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) {
            $id = strtolower($matches[1]);
            $Data = array('url' => $matches[2], 'title' => null);
            if (isset($matches[3])) {
                $Data['title'] = $matches[3];
            }
            $this->DefinitionData['Reference'][$id] = $Data;
            $Block = array('hidden' => true);
            return $Block;
        }
    }
    #
    # Table
    /**
     *
     */
    protected function blockTable($Line, array $Block = null)
    {
        if (!isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) {
            return;
        }
        if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '') {
            $alignments = array();
            $divider = $Line['text'];
            $divider = trim($divider);
            $divider = trim($divider, '|');
            $dividerCells = explode('|', $divider);
            foreach ($dividerCells as $dividerCell) {
                $dividerCell = trim($dividerCell);
                if ($dividerCell === '') {
                    continue;
                }
                $alignment = null;
                if ($dividerCell[0] === ':') {
                    $alignment = 'left';
                }
                if (\Phabel\Target\Php80\Polyfill::substr($dividerCell, -1) === ':') {
                    $alignment = $alignment === 'left' ? 'center' : 'right';
                }
                $alignments[] = $alignment;
            }
            # ~
            $HeaderElements = array();
            $header = $Block['element']['text'];
            $header = trim($header);
            $header = trim($header, '|');
            $headerCells = explode('|', $header);
            foreach ($headerCells as $index => $headerCell) {
                $headerCell = trim($headerCell);
                $HeaderElement = array('name' => 'th', 'text' => $headerCell, 'handler' => 'line');
                if (isset($alignments[$index])) {
                    $alignment = $alignments[$index];
                    $HeaderElement['attributes'] = array('style' => 'text-align: ' . $alignment . ';');
                }
                $HeaderElements[] = $HeaderElement;
            }
            # ~
            $Block = array('alignments' => $alignments, 'identified' => true, 'element' => array('name' => 'table', 'handler' => 'elements'));
            $Block['element']['text'][] = array('name' => 'thead', 'handler' => 'elements');
            $Block['element']['text'][] = array('name' => 'tbody', 'handler' => 'elements', 'text' => array());
            $Block['element']['text'][0]['text'][] = array('name' => 'tr', 'handler' => 'elements', 'text' => $HeaderElements);
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockTableContinue($Line, array $Block)
    {
        if (isset($Block['interrupted'])) {
            return;
        }
        if ($Line['text'][0] === '|' or strpos($Line['text'], '|')) {
            $Elements = array();
            $row = $Line['text'];
            $row = trim($row);
            $row = trim($row, '|');
            preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
            foreach ($matches[0] as $index => $cell) {
                $cell = trim($cell);
                $Element = array('name' => 'td', 'handler' => 'line', 'text' => $cell);
                if (isset($Block['alignments'][$index])) {
                    $Element['attributes'] = array('style' => 'text-align: ' . $Block['alignments'][$index] . ';');
                }
                $Elements[] = $Element;
            }
            $Element = array('name' => 'tr', 'handler' => 'elements', 'text' => $Elements);
            $Block['element']['text'][1]['text'][] = $Element;
            return $Block;
        }
    }
    #
    # ~
    #
    /**
     *
     */
    protected function paragraph($Line)
    {
        $Block = array('element' => array('name' => 'p', 'text' => $Line['text'], 'handler' => 'line'));
        return $Block;
    }
    #
    # Inline Elements
    #
    protected $InlineTypes = array('"' => array('SpecialCharacter'), '!' => array('Image'), '&' => array('SpecialCharacter'), '*' => array('Emphasis'), ':' => array('Url'), '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'), '>' => array('SpecialCharacter'), '[' => array('Link'), '_' => array('Emphasis'), '`' => array('Code'), '~' => array('Strikethrough'), '\\' => array('EscapeSequence'));
    # ~
    protected $inlineMarkerList = '!"*_&[:<>`~\\';
    #
    # ~
    #
    /**
     *
     */
    public function line($text, $nonNestables = array())
    {
        $markup = '';
        # $excerpt is based on the first occurrence of a marker
        while ($excerpt = strpbrk($text, $this->inlineMarkerList)) {
            $marker = $excerpt[0];
            $markerPosition = strpos($text, $marker);
            $Excerpt = array('text' => $excerpt, 'context' => $text);
            foreach ($this->InlineTypes[$marker] as $inlineType) {
                # check to see if the current inline type is nestable in the current context
                if (!empty($nonNestables) and in_array($inlineType, $nonNestables)) {
                    continue;
                }
                $Inline = $this->{'inline' . $inlineType}($Excerpt);
                if (!isset($Inline)) {
                    continue;
                }
                # makes sure that the inline belongs to "our" marker
                if (isset($Inline['position']) and $Inline['position'] > $markerPosition) {
                    continue;
                }
                # sets a default inline position
                if (!isset($Inline['position'])) {
                    $Inline['position'] = $markerPosition;
                }
                # cause the new element to 'inherit' our non nestables
                foreach ($nonNestables as $non_nestable) {
                    $Inline['element']['nonNestables'][] = $non_nestable;
                }
                # the text that comes before the inline
                $unmarkedText = \Phabel\Target\Php80\Polyfill::substr($text, 0, $Inline['position']);
                # compile the unmarked text
                $markup .= $this->unmarkedText($unmarkedText);
                # compile the inline
                $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
                # remove the examined text
                $text = \Phabel\Target\Php80\Polyfill::substr($text, $Inline['position'] + $Inline['extent']);
                continue 2;
            }
            # the marker does not belong to an inline
            $unmarkedText = \Phabel\Target\Php80\Polyfill::substr($text, 0, $markerPosition + 1);
            $markup .= $this->unmarkedText($unmarkedText);
            $text = \Phabel\Target\Php80\Polyfill::substr($text, $markerPosition + 1);
        }
        $markup .= $this->unmarkedText($text);
        return $markup;
    }
    #
    # ~
    #
    /**
     *
     */
    protected function inlineCode($Excerpt)
    {
        $marker = $Excerpt['text'][0];
        if (preg_match('/^(' . $marker . '+)[ ]*(.+?)[ ]*(?<!' . $marker . ')\\1(?!' . $marker . ')/s', $Excerpt['text'], $matches)) {
            $text = $matches[2];
            $text = preg_replace("/[ ]*\n/", ' ', $text);
            return array('extent' => strlen($matches[0]), 'element' => array('name' => 'code', 'text' => $text));
        }
    }
    /**
     *
     */
    protected function inlineEmailTag($Excerpt)
    {
        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\\S+?@\\S+?)>/i', $Excerpt['text'], $matches)) {
            $url = $matches[1];
            if (!isset($matches[2])) {
                $url = 'mailto:' . $url;
            }
            return array('extent' => strlen($matches[0]), 'element' => array('name' => 'a', 'text' => $matches[1], 'attributes' => array('href' => $url)));
        }
    }
    /**
     *
     */
    protected function inlineEmphasis($Excerpt)
    {
        if (!isset($Excerpt['text'][1])) {
            return;
        }
        $marker = $Excerpt['text'][0];
        if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) {
            $emphasis = 'strong';
        } elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) {
            $emphasis = 'em';
        } else {
            return;
        }
        return array('extent' => strlen($matches[0]), 'element' => array('name' => $emphasis, 'handler' => 'line', 'text' => $matches[1]));
    }
    /**
     *
     */
    protected function inlineEscapeSequence($Excerpt)
    {
        if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) {
            return array('markup' => $Excerpt['text'][1], 'extent' => 2);
        }
    }
    /**
     *
     */
    protected function inlineImage($Excerpt)
    {
        if (!isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') {
            return;
        }
        $Excerpt['text'] = \Phabel\Target\Php80\Polyfill::substr($Excerpt['text'], 1);
        $Link = $this->inlineLink($Excerpt);
        if ($Link === null) {
            return;
        }
        $Inline = array('extent' => $Link['extent'] + 1, 'element' => array('name' => 'img', 'attributes' => array('src' => $Link['element']['attributes']['href'], 'alt' => $Link['element']['text'])));
        $Inline['element']['attributes'] += $Link['element']['attributes'];
        unset($Inline['element']['attributes']['href']);
        return $Inline;
    }
    /**
     *
     */
    protected function inlineLink($Excerpt)
    {
        $Element = array('name' => 'a', 'handler' => 'line', 'nonNestables' => array('Url', 'Link'), 'text' => null, 'attributes' => array('href' => null, 'title' => null));
        $extent = 0;
        $remainder = $Excerpt['text'];
        if (preg_match('/\\[((?:[^][]++|(?R))*+)\\]/', $remainder, $matches)) {
            $Element['text'] = $matches[1];
            $extent += strlen($matches[0]);
            $remainder = \Phabel\Target\Php80\Polyfill::substr($remainder, $extent);
        } else {
            return;
        }
        if (preg_match('/^[(]\\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\\s*[)]/', $remainder, $matches)) {
            $Element['attributes']['href'] = $matches[1];
            if (isset($matches[2])) {
                $Element['attributes']['title'] = \Phabel\Target\Php80\Polyfill::substr($matches[2], 1, -1);
            }
            $extent += strlen($matches[0]);
        } else {
            if (preg_match('/^\\s*\\[(.*?)\\]/', $remainder, $matches)) {
                $definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
                $definition = strtolower($definition);
                $extent += strlen($matches[0]);
            } else {
                $definition = strtolower($Element['text']);
            }
            if (!isset($this->DefinitionData['Reference'][$definition])) {
                return;
            }
            $Definition = $this->DefinitionData['Reference'][$definition];
            $Element['attributes']['href'] = $Definition['url'];
            $Element['attributes']['title'] = $Definition['title'];
        }
        return array('extent' => $extent, 'element' => $Element);
    }
    /**
     *
     */
    protected function inlineMarkup($Excerpt)
    {
        if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false) {
            return;
        }
        if ($Excerpt['text'][1] === '/' and preg_match('/^<\\/\\w[\\w-]*[ ]*>/s', $Excerpt['text'], $matches)) {
            return array('markup' => $matches[0], 'extent' => strlen($matches[0]));
        }
        if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches)) {
            return array('markup' => $matches[0], 'extent' => strlen($matches[0]));
        }
        if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\\w[\\w-]*(?:[ ]*' . $this->regexHtmlAttribute . ')*[ ]*\\/?>/s', $Excerpt['text'], $matches)) {
            return array('markup' => $matches[0], 'extent' => strlen($matches[0]));
        }
    }
    /**
     *
     */
    protected function inlineSpecialCharacter($Excerpt)
    {
        if ($Excerpt['text'][0] === '&' and !preg_match('/^&#?\\w+;/', $Excerpt['text'])) {
            return array('markup' => '&amp;', 'extent' => 1);
        }
        $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
        if (isset($SpecialCharacter[$Excerpt['text'][0]])) {
            return array('markup' => '&' . $SpecialCharacter[$Excerpt['text'][0]] . ';', 'extent' => 1);
        }
    }
    /**
     *
     */
    protected function inlineStrikethrough($Excerpt)
    {
        if (!isset($Excerpt['text'][1])) {
            return;
        }
        if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\\S)(.+?)(?<=\\S)~~/', $Excerpt['text'], $matches)) {
            return array('extent' => strlen($matches[0]), 'element' => array('name' => 'del', 'text' => $matches[1], 'handler' => 'line'));
        }
    }
    /**
     *
     */
    protected function inlineUrl($Excerpt)
    {
        if ($this->urlsLinked !== true or !isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') {
            return;
        }
        if (preg_match('/\\bhttps?:[\\/]{2}[^\\s<]+\\b\\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) {
            $url = $matches[0][0];
            $Inline = array('extent' => strlen($matches[0][0]), 'position' => $matches[0][1], 'element' => array('name' => 'a', 'text' => $url, 'attributes' => array('href' => $url)));
            return $Inline;
        }
    }
    /**
     *
     */
    protected function inlineUrlTag($Excerpt)
    {
        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\\w+:\\/{2}[^ >]+)>/i', $Excerpt['text'], $matches)) {
            $url = $matches[1];
            return array('extent' => strlen($matches[0]), 'element' => array('name' => 'a', 'text' => $url, 'attributes' => array('href' => $url)));
        }
    }
    # ~
    /**
     *
     */
    protected function unmarkedText($text)
    {
        if ($this->breaksEnabled) {
            $text = preg_replace('/[ ]*\\n/', "<br />\n", $text);
        } else {
            $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\\n/', "<br />\n", $text);
            $text = str_replace(" \n", "\n", $text);
        }
        return $text;
    }
    #
    # Handlers
    #
    /**
     *
     */
    protected function element(array $Element)
    {
        if ($this->safeMode) {
            $Element = $this->sanitiseElement($Element);
        }
        $markup = '<' . $Element['name'];
        if (isset($Element['attributes'])) {
            foreach ($Element['attributes'] as $name => $value) {
                if ($value === null) {
                    continue;
                }
                $markup .= ' ' . $name . '="' . self::escape($value) . '"';
            }
        }
        $permitRawHtml = false;
        if (isset($Element['text'])) {
            $text = $Element['text'];
        } elseif (isset($Element['rawHtml'])) {
            $text = $Element['rawHtml'];
            $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
            $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
        }
        if (isset($text)) {
            $markup .= '>';
            if (!isset($Element['nonNestables'])) {
                $Element['nonNestables'] = array();
            }
            if (isset($Element['handler'])) {
                $markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
            } elseif (!$permitRawHtml) {
                $markup .= self::escape($text, true);
            } else {
                $markup .= $text;
            }
            $markup .= '</' . $Element['name'] . '>';
        } else {
            $markup .= ' />';
        }
        return $markup;
    }
    /**
     *
     */
    protected function elements(array $Elements)
    {
        $markup = '';
        foreach ($Elements as $Element) {
            $markup .= "\n" . $this->element($Element);
        }
        $markup .= "\n";
        return $markup;
    }
    # ~
    /**
     *
     */
    protected function li($lines)
    {
        $markup = $this->lines($lines);
        $trimmedMarkup = trim($markup);
        if (!in_array('', $lines) and \Phabel\Target\Php80\Polyfill::substr($trimmedMarkup, 0, 3) === '<p>') {
            $markup = $trimmedMarkup;
            $markup = \Phabel\Target\Php80\Polyfill::substr($markup, 3);
            $position = strpos($markup, "</p>");
            $markup = \Phabel\Target\Php80\Polyfill::substr_replace($markup, '', $position, 4);
        }
        return $markup;
    }
    #
    # Deprecated Methods
    #
    /**
     *
     */
    function parse($text)
    {
        $markup = $this->text($text);
        return $markup;
    }
    /**
     *
     */
    protected function sanitiseElement(array $Element)
    {
        static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
        static $safeUrlNameToAtt = array('a' => 'href', 'img' => 'src');
        if (isset($safeUrlNameToAtt[$Element['name']])) {
            $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
        }
        if (!empty($Element['attributes'])) {
            foreach ($Element['attributes'] as $att => $val) {
                # filter out badly parsed attribute
                if (!preg_match($goodAttribute, $att)) {
                    unset($Element['attributes'][$att]);
                } elseif (self::striAtStart($att, 'on')) {
                    unset($Element['attributes'][$att]);
                }
            }
        }
        return $Element;
    }
    /**
     *
     */
    protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
    {
        foreach ($this->safeLinksWhitelist as $scheme) {
            if (self::striAtStart($Element['attributes'][$attribute], $scheme)) {
                return $Element;
            }
        }
        $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
        return $Element;
    }
    #
    # Static Methods
    #
    /**
     *
     */
    protected static function escape($text, $allowQuotes = false)
    {
        return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
    }
    /**
     *
     */
    protected static function striAtStart($string, $needle)
    {
        $len = strlen($needle);
        if ($len > strlen($string)) {
            return false;
        } else {
            return strtolower(\Phabel\Target\Php80\Polyfill::substr($string, 0, $len)) === strtolower($needle);
        }
    }
    /**
     *
     */
    static function instance($name = 'default')
    {
        if (isset(self::$instances[$name])) {
            return self::$instances[$name];
        }
        $instance = new static();
        self::$instances[$name] = $instance;
        return $instance;
    }
    private static $instances = array();
    #
    # Fields
    #
    protected $DefinitionData;
    #
    # Read-Only
    protected $specialCharacters = array('\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|');
    protected $StrongRegex = array('*' => '/^[*]{2}((?:\\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us');
    protected $EmRegex = array('*' => '/^[*]((?:\\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\\b/us');
    protected $regexHtmlAttribute = '[a-zA-Z_:][\\w:.-]*(?:\\s*=\\s*(?:[^"\'=<>`\\s]+|"[^"]*"|\'[^\']*\'))?';
    protected $voidElements = array('area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source');
    protected $textLevelElements = array('a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', 'i', 'rp', 'del', 'code', 'strike', 'marquee', 'q', 'rt', 'ins', 'font', 'strong', 's', 'tt', 'kbd', 'mark', 'u', 'xm', 'sub', 'nobr', 'sup', 'ruby', 'var', 'span', 'wbr', 'time');
}{
    "name": "erusev/parsedown",
    "description": "Parser for Markdown.",
    "keywords": ["markdown", "parser"],
    "homepage": "http://parsedown.org",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Emanuil Rusev",
            "email": "hello@erusev.com",
            "homepage": "http://erusev.com"
        }
    ],
    "require": {
        "php": ">=5.3.0",
        "ext-mbstring": "*"
    },
    "require-dev": {
        "phpunit/phpunit": "^4.8.35"
    },
    "autoload": {
        "psr-0": {"Parsedown": ""}
    },
    "autoload-dev": {
        "psr-0": {
            "TestParsedown": "test/",
            "ParsedownTest": "test/",
            "CommonMarkTest": "test/",
            "CommonMarkTestWeak": "test/"
        }
    }
}
<?php

declare (strict_types=1);
/**
 * Creates EncodingContext objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Encoder;

use LibDNS\Packets\Packet;
use LibDNS\Packets\LabelRegistry;
/**
 * Creates EncodingContext objects
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class EncodingContextFactory
{
    /**
     * Create a new EncodingContext object
     *
     * @param \LibDNS\Packets\Packet $packet The packet to be decoded
     * @param bool $compress Whether message compression is enabled
     * @return \LibDNS\Encoder\EncodingContext
     */
    public function create(Packet $packet, bool $compress) : EncodingContext
    {
        return new EncodingContext($packet, new LabelRegistry(), $compress);
    }
}<?php

declare (strict_types=1);
/**
 * Encodes Message objects to raw network data
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Encoder;

use LibDNS\Packets\PacketFactory;
use LibDNS\Messages\Message;
use LibDNS\Records\Question;
use LibDNS\Records\Resource;
use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
/**
 * Encodes Message objects to raw network data
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Encoder
{
    /**
     * @var \LibDNS\Packets\PacketFactory
     */
    private $packetFactory;
    /**
     * @var \LibDNS\Encoder\EncodingContextFactory
     */
    private $encodingContextFactory;
    /**
     * Constructor
     *
     * @param \LibDNS\Packets\PacketFactory $packetFactory
     * @param \LibDNS\Encoder\EncodingContextFactory $encodingContextFactory
     */
    public function __construct(PacketFactory $packetFactory, EncodingContextFactory $encodingContextFactory)
    {
        $this->packetFactory = $packetFactory;
        $this->encodingContextFactory = $encodingContextFactory;
    }
    /**
     * Encode the header section of the message
     *
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @param \LibDNS\Messages\Message $message
     * @return string
     * @throws \UnexpectedValueException When the header section is invalid
     */
    private function encodeHeader(EncodingContext $encodingContext, Message $message) : string
    {
        $header = ['id' => $message->getID(), 'meta' => 0, 'qd' => $message->getQuestionRecords()->count(), 'an' => $message->getAnswerRecords()->count(), 'ns' => $message->getAuthorityRecords()->count(), 'ar' => $message->getAdditionalRecords()->count()];
        $header['meta'] |= $message->getType() << 15;
        $header['meta'] |= $message->getOpCode() << 11;
        $header['meta'] |= (int) $message->isAuthoritative() << 10;
        $header['meta'] |= (int) $encodingContext->isTruncated() << 9;
        $header['meta'] |= (int) $message->isRecursionDesired() << 8;
        $header['meta'] |= (int) $message->isRecursionAvailable() << 7;
        $header['meta'] |= $message->getResponseCode();
        return \pack('n*', $header['id'], $header['meta'], $header['qd'], $header['an'], $header['ns'], $header['ar']);
    }
    /**
     * Encode an Anything field
     *
     * @param \LibDNS\Records\Types\Anything $anything
     * @return string
     */
    private function encodeAnything(Anything $anything) : string
    {
        return $anything->getValue();
    }
    /**
     * Encode a BitMap field
     *
     * @param \LibDNS\Records\Types\BitMap $bitMap
     * @return string
     */
    private function encodeBitMap(BitMap $bitMap) : string
    {
        return $bitMap->getValue();
    }
    /**
     * Encode a Char field
     *
     * @param \LibDNS\Records\Types\Char $char
     * @return string
     */
    private function encodeChar(Char $char) : string
    {
        return \chr($char->getValue());
    }
    /**
     * Encode a CharacterString field
     *
     * @param \LibDNS\Records\Types\CharacterString $characterString
     * @return string
     */
    private function encodeCharacterString(CharacterString $characterString) : string
    {
        $data = $characterString->getValue();
        return \chr(\strlen($data)) . $data;
    }
    /**
     * Encode a DomainName field
     *
     * @param \LibDNS\Records\Types\DomainName $domainName
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @return string
     */
    private function encodeDomainName(DomainName $domainName, EncodingContext $encodingContext) : string
    {
        $packetIndex = $encodingContext->getPacket()->getLength() + 12;
        $labelRegistry = $encodingContext->getLabelRegistry();
        $result = '';
        $labels = $domainName->getLabels();
        if ($encodingContext->useCompression()) {
            do {
                $part = \implode('.', $labels);
                $index = $labelRegistry->lookupIndex($part);
                if ($index === null) {
                    $labelRegistry->register($part, $packetIndex);
                    $label = \array_shift($labels);
                    $length = \strlen($label);
                    $result .= \chr($length) . $label;
                    $packetIndex += $length + 1;
                } else {
                    $result .= \pack('n', 0b1100000000000000 | $index);
                    break;
                }
            } while ($labels);
            if (!$labels) {
                $result .= "\x00";
            }
        } else {
            foreach ($labels as $label) {
                $result .= \chr(\strlen($label)) . $label;
            }
            $result .= "\x00";
        }
        return $result;
    }
    /**
     * Encode an IPv4Address field
     *
     * @param \LibDNS\Records\Types\IPv4Address $ipv4Address
     * @return string
     */
    private function encodeIPv4Address(IPv4Address $ipv4Address) : string
    {
        $octets = $ipv4Address->getOctets();
        return \pack('C*', $octets[0], $octets[1], $octets[2], $octets[3]);
    }
    /**
     * Encode an IPv6Address field
     *
     * @param \LibDNS\Records\Types\IPv6Address $ipv6Address
     * @return string
     */
    private function encodeIPv6Address(IPv6Address $ipv6Address) : string
    {
        $shorts = $ipv6Address->getShorts();
        return \pack('n*', $shorts[0], $shorts[1], $shorts[2], $shorts[3], $shorts[4], $shorts[5], $shorts[6], $shorts[7]);
    }
    /**
     * Encode a Long field
     *
     * @param \LibDNS\Records\Types\Long $long
     * @return string
     */
    private function encodeLong(Long $long) : string
    {
        return \pack('N', $long->getValue());
    }
    /**
     * Encode a Short field
     *
     * @param \LibDNS\Records\Types\Short $short
     * @return string
     */
    private function encodeShort(Short $short) : string
    {
        return \pack('n', $short->getValue());
    }
    /**
     * Encode a type object
     *
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @param \LibDNS\Records\Types\Type $type
     * @return string
     */
    private function encodeType(EncodingContext $encodingContext, Type $type) : string
    {
        if ($type instanceof Anything) {
            $result = $this->encodeAnything($type);
        } else {
            if ($type instanceof BitMap) {
                $result = $this->encodeBitMap($type);
            } else {
                if ($type instanceof Char) {
                    $result = $this->encodeChar($type);
                } else {
                    if ($type instanceof CharacterString) {
                        $result = $this->encodeCharacterString($type);
                    } else {
                        if ($type instanceof DomainName) {
                            $result = $this->encodeDomainName($type, $encodingContext);
                        } else {
                            if ($type instanceof IPv4Address) {
                                $result = $this->encodeIPv4Address($type);
                            } else {
                                if ($type instanceof IPv6Address) {
                                    $result = $this->encodeIPv6Address($type);
                                } else {
                                    if ($type instanceof Long) {
                                        $result = $this->encodeLong($type);
                                    } else {
                                        if ($type instanceof Short) {
                                            $result = $this->encodeShort($type);
                                        } else {
                                            throw new \InvalidArgumentException('Unknown Type ' . \get_class($type));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return $result;
    }
    /**
     * Encode a question record
     *
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @param \LibDNS\Records\Question $record
     */
    private function encodeQuestionRecord(EncodingContext $encodingContext, Question $record)
    {
        if (!$encodingContext->isTruncated()) {
            $packet = $encodingContext->getPacket();
            $name = $this->encodeDomainName($record->getName(), $encodingContext);
            $meta = \pack('n*', $record->getType(), $record->getClass());
            if (12 + $packet->getLength() + \strlen($name) + 4 > 512) {
                $encodingContext->isTruncated(true);
            } else {
                $packet->write($name);
                $packet->write($meta);
            }
        }
    }
    /**
     * Encode a resource record
     *
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @param \LibDNS\Records\Resource $record
     */
    private function encodeResourceRecord(EncodingContext $encodingContext, Resource $record)
    {
        if (!$encodingContext->isTruncated()) {
            $packet = $encodingContext->getPacket();
            $name = $this->encodeDomainName($record->getName(), $encodingContext);
            $data = '';
            foreach ($record->getData() as $field) {
                $data .= $this->encodeType($encodingContext, $field);
            }
            $meta = \pack('n2Nn', $record->getType(), $record->getClass(), $record->getTTL(), \strlen($data));
            if (12 + $packet->getLength() + \strlen($name) + 10 + \strlen($data) > 512) {
                $encodingContext->isTruncated(true);
            } else {
                $packet->write($name);
                $packet->write($meta);
                $packet->write($data);
            }
        }
    }
    /**
     * Encode a Message to raw network data
     *
     * @param \LibDNS\Messages\Message $message The Message to encode
     * @param bool $compress Enable message compression
     * @return string
     */
    public function encode(Message $message, $compress = true) : string
    {
        $packet = $this->packetFactory->create();
        $encodingContext = $this->encodingContextFactory->create($packet, $compress);
        foreach ($message->getQuestionRecords() as $record) {
            /** @var \LibDNS\Records\Question $record */
            $this->encodeQuestionRecord($encodingContext, $record);
        }
        foreach ($message->getAnswerRecords() as $record) {
            /** @var \LibDNS\Records\Resource $record */
            $this->encodeResourceRecord($encodingContext, $record);
        }
        foreach ($message->getAuthorityRecords() as $record) {
            /** @var \LibDNS\Records\Resource $record */
            $this->encodeResourceRecord($encodingContext, $record);
        }
        foreach ($message->getAdditionalRecords() as $record) {
            /** @var \LibDNS\Records\Resource $record */
            $this->encodeResourceRecord($encodingContext, $record);
        }
        return $this->encodeHeader($encodingContext, $message) . $packet->read($packet->getLength());
    }
}<?php

declare (strict_types=1);
/**
 * Holds data associated with an encode operation
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Encoder;

use LibDNS\Packets\Packet;
use LibDNS\Packets\LabelRegistry;
/**
 * Holds data associated with an encode operation
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class EncodingContext
{
    /**
     * @var \LibDNS\Packets\Packet
     */
    private $packet;
    /**
     * @var \LibDNS\Packets\LabelRegistry
     */
    private $labelRegistry;
    /**
     * @var bool
     */
    private $compress;
    /**
     * @var bool
     */
    private $truncate = false;
    /**
     * Constructor
     *
     * @param \LibDNS\Packets\Packet $packet
     * @param \LibDNS\Packets\LabelRegistry $labelRegistry
     * @param bool $compress
     */
    public function __construct(Packet $packet, LabelRegistry $labelRegistry, bool $compress)
    {
        $this->packet = $packet;
        $this->labelRegistry = $labelRegistry;
        $this->compress = $compress;
    }
    /**
     * Get the packet
     *
     * @return \LibDNS\Packets\Packet
     */
    public function getPacket() : Packet
    {
        return $this->packet;
    }
    /**
     * Get the label registry
     *
     * @return \LibDNS\Packets\LabelRegistry
     */
    public function getLabelRegistry() : LabelRegistry
    {
        return $this->labelRegistry;
    }
    /**
     * Determine whether compression is enabled
     *
     * @return bool
     */
    public function useCompression() : bool
    {
        return $this->compress;
    }
    /**
     * Determine or set whether the message is truncated
     *
     * @param bool $truncate
     * @return bool
     */
    public function isTruncated(bool $truncate = null) : bool
    {
        $result = $this->truncate;
        if ($truncate !== null) {
            $this->truncate = $truncate;
        }
        return $result;
    }
}<?php

declare (strict_types=1);
/**
 * Creates Encoder objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Encoder;

use LibDNS\Packets\PacketFactory;
/**
 * Creates Encoder objects
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class EncoderFactory
{
    /**
     * Create a new Encoder object
     *
     * @return \LibDNS\Encoder\Encoder
     */
    public function create() : Encoder
    {
        return new Encoder(new PacketFactory(), new EncodingContextFactory());
    }
}<?php

declare (strict_types=1);
/**
 * Holds data associated with a decode operation
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Decoder;

use LibDNS\Packets\Packet;
use LibDNS\Packets\LabelRegistry;
/**
 * Holds data associated with a decode operation
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class DecodingContext
{
    /**
     * @var \LibDNS\Packets\Packet
     */
    private $packet;
    /**
     * @var \LibDNS\Packets\LabelRegistry
     */
    private $labelRegistry;
    /**
     * @var int
     */
    private $expectedQuestionRecords = 0;
    /**
     * @var int
     */
    private $expectedAnswerRecords = 0;
    /**
     * @var int
     */
    private $expectedAuthorityRecords = 0;
    /**
     * @var int
     */
    private $expectedAdditionalRecords = 0;
    /**
     * Constructor
     *
     * @param \LibDNS\Packets\Packet $packet
     * @param \LibDNS\Packets\LabelRegistry $labelRegistry
     */
    public function __construct(Packet $packet, LabelRegistry $labelRegistry)
    {
        $this->packet = $packet;
        $this->labelRegistry = $labelRegistry;
    }
    /**
     * Get the packet
     *
     * @return \LibDNS\Packets\Packet
     */
    public function getPacket() : Packet
    {
        return $this->packet;
    }
    /**
     * Get the label registry
     *
     * @return \LibDNS\Packets\LabelRegistry
     */
    public function getLabelRegistry() : LabelRegistry
    {
        return $this->labelRegistry;
    }
    /**
     * Get the number of question records expected in the message
     *
     * @return int
     */
    public function getExpectedQuestionRecords() : int
    {
        return $this->expectedQuestionRecords;
    }
    /**
     * Get the number of question records expected in the message
     *
     * @param int $expectedQuestionRecords
     */
    public function setExpectedQuestionRecords(int $expectedQuestionRecords)
    {
        $this->expectedQuestionRecords = $expectedQuestionRecords;
    }
    /**
     * Get the number of answer records expected in the message
     *
     * @return int
     */
    public function getExpectedAnswerRecords() : int
    {
        return $this->expectedAnswerRecords;
    }
    /**
     * Set the number of answer records expected in the message
     *
     * @param int $expectedAnswerRecords
     */
    public function setExpectedAnswerRecords(int $expectedAnswerRecords)
    {
        $this->expectedAnswerRecords = $expectedAnswerRecords;
    }
    /**
     * Get the number of authority records expected in the message
     *
     * @return int
     */
    public function getExpectedAuthorityRecords() : int
    {
        return $this->expectedAuthorityRecords;
    }
    /**
     * Set the number of authority records expected in the message
     *
     * @param int $expectedAuthorityRecords
     */
    public function setExpectedAuthorityRecords(int $expectedAuthorityRecords)
    {
        $this->expectedAuthorityRecords = $expectedAuthorityRecords;
    }
    /**
     * Get the number of additional records expected in the message
     *
     * @return int
     */
    public function getExpectedAdditionalRecords() : int
    {
        return $this->expectedAdditionalRecords;
    }
    /**
     * Set the number of additional records expected in the message
     *
     * @param int $expectedAdditionalRecords
     */
    public function setExpectedAdditionalRecords(int $expectedAdditionalRecords)
    {
        $this->expectedAdditionalRecords = $expectedAdditionalRecords;
    }
}<?php

declare (strict_types=1);
/**
 * Creates Decoder objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Decoder;

use LibDNS\Packets\PacketFactory;
use LibDNS\Messages\MessageFactory;
use LibDNS\Records\RecordCollectionFactory;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\ResourceFactory;
use LibDNS\Records\RDataBuilder;
use LibDNS\Records\RDataFactory;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\TypeFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionManager;
use LibDNS\Records\TypeDefinitions\TypeDefinitionFactory;
use LibDNS\Records\TypeDefinitions\FieldDefinitionFactory;
/**
 * Creates Decoder objects
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class DecoderFactory
{
    /**
     * Create a new Decoder object
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager
     * @param bool $allowTrailingData
     * @return Decoder
     */
    public function create(TypeDefinitionManager $typeDefinitionManager = null, bool $allowTrailingData = true) : Decoder
    {
        $typeBuilder = new TypeBuilder(new TypeFactory());
        return new Decoder(new PacketFactory(), new MessageFactory(new RecordCollectionFactory()), new QuestionFactory(), new ResourceBuilder(new ResourceFactory(), new RDataBuilder(new RDataFactory(), $typeBuilder), $typeDefinitionManager ?: new TypeDefinitionManager(new TypeDefinitionFactory(), new FieldDefinitionFactory())), $typeBuilder, new DecodingContextFactory(), $allowTrailingData);
    }
}<?php

declare (strict_types=1);
/**
 * Creates DecodingContext objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Decoder;

use LibDNS\Packets\Packet;
use LibDNS\Packets\LabelRegistry;
/**
 * Creates DecodingContext objects
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class DecodingContextFactory
{
    /**
     * Create a new DecodingContext object
     *
     * @param \LibDNS\Packets\Packet $packet The packet to be decoded
     * @return \LibDNS\Decoder\DecodingContext
     */
    public function create(Packet $packet) : DecodingContext
    {
        return new DecodingContext($packet, new LabelRegistry());
    }
}<?php

declare (strict_types=1);
/**
 * Decodes raw network data to Message objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Decoder;

use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Packets\Packet;
use LibDNS\Packets\PacketFactory;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\Resource;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\Types;
/**
 * Decodes raw network data to Message objects
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Decoder
{
    /**
     * @var \LibDNS\Packets\PacketFactory
     */
    private $packetFactory;
    /**
     * @var \LibDNS\Messages\MessageFactory
     */
    private $messageFactory;
    /**
     * @var \LibDNS\Records\QuestionFactory
     */
    private $questionFactory;
    /**
     * @var \LibDNS\Records\ResourceBuilder
     */
    private $resourceBuilder;
    /**
     * @var \LibDNS\Records\Types\TypeBuilder
     */
    private $typeBuilder;
    /**
     * @var \LibDNS\Decoder\DecodingContextFactory
     */
    private $decodingContextFactory;
    /**
     * @var bool
     */
    private $allowTrailingData;
    /**
     * Constructor
     *
     * @param \LibDNS\Packets\PacketFactory $packetFactory
     * @param \LibDNS\Messages\MessageFactory $messageFactory
     * @param \LibDNS\Records\QuestionFactory $questionFactory
     * @param \LibDNS\Records\ResourceBuilder $resourceBuilder
     * @param \LibDNS\Records\Types\TypeBuilder $typeBuilder
     * @param \LibDNS\Decoder\DecodingContextFactory $decodingContextFactory
     * @param bool $allowTrailingData
     */
    public function __construct(PacketFactory $packetFactory, MessageFactory $messageFactory, QuestionFactory $questionFactory, ResourceBuilder $resourceBuilder, TypeBuilder $typeBuilder, DecodingContextFactory $decodingContextFactory, bool $allowTrailingData = true)
    {
        $this->packetFactory = $packetFactory;
        $this->messageFactory = $messageFactory;
        $this->questionFactory = $questionFactory;
        $this->resourceBuilder = $resourceBuilder;
        $this->typeBuilder = $typeBuilder;
        $this->decodingContextFactory = $decodingContextFactory;
        $this->allowTrailingData = $allowTrailingData;
    }
    /**
     * Read a specified number of bytes of data from a packet
     *
     * @param \LibDNS\Packets\Packet $packet
     * @param int $length
     * @return string
     * @throws \UnexpectedValueException When the read operation does not result in the requested number of bytes
     */
    private function readDataFromPacket(Packet $packet, int $length) : string
    {
        if ($packet->getBytesRemaining() < $length) {
            throw new \UnexpectedValueException('Decode error: Incomplete packet (tried to read ' . $length . ' bytes from index ' . $packet->getPointer());
        }
        return $packet->read($length);
    }
    /**
     * Decode the header section of the message
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Messages\Message $message
     * @throws \UnexpectedValueException When the header section is invalid
     */
    private function decodeHeader(DecodingContext $decodingContext, Message $message)
    {
        $header = \unpack('nid/nmeta/nqd/nan/nns/nar', $this->readDataFromPacket($decodingContext->getPacket(), 12));
        if (!$header) {
            throw new \UnexpectedValueException('Decode error: Header unpack failed');
        }
        $message->setID($header['id']);
        $message->setType(($header['meta'] & 0b1000000000000000) >> 15);
        $message->setOpCode(($header['meta'] & 0b111100000000000) >> 11);
        $message->isAuthoritative((bool) (($header['meta'] & 0b10000000000) >> 10));
        $message->isTruncated((bool) (($header['meta'] & 0b1000000000) >> 9));
        $message->isRecursionDesired((bool) (($header['meta'] & 0b100000000) >> 8));
        $message->isRecursionAvailable((bool) (($header['meta'] & 0b10000000) >> 7));
        $message->setResponseCode($header['meta'] & 0b1111);
        $decodingContext->setExpectedQuestionRecords($header['qd']);
        $decodingContext->setExpectedAnswerRecords($header['an']);
        $decodingContext->setExpectedAuthorityRecords($header['ns']);
        $decodingContext->setExpectedAdditionalRecords($header['ar']);
    }
    /**
     * Decode an Anything field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Anything $anything The object to populate with the result
     * @param int $length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeAnything(DecodingContext $decodingContext, Anything $anything, int $length) : int
    {
        $anything->setValue($this->readDataFromPacket($decodingContext->getPacket(), $length));
        return $length;
    }
    /**
     * Decode a BitMap field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\BitMap $bitMap The object to populate with the result
     * @param int $length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeBitMap(DecodingContext $decodingContext, BitMap $bitMap, int $length) : int
    {
        $bitMap->setValue($this->readDataFromPacket($decodingContext->getPacket(), $length));
        return $length;
    }
    /**
     * Decode a Char field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Char $char The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeChar(DecodingContext $decodingContext, Char $char) : int
    {
        $value = \unpack('C', $this->readDataFromPacket($decodingContext->getPacket(), 1))[1];
        $char->setValue($value);
        return 1;
    }
    /**
     * Decode a CharacterString field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\CharacterString $characterString The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeCharacterString(DecodingContext $decodingContext, CharacterString $characterString) : int
    {
        $packet = $decodingContext->getPacket();
        $length = \ord($this->readDataFromPacket($packet, 1));
        $characterString->setValue($this->readDataFromPacket($packet, $length));
        return $length + 1;
    }
    /**
     * Decode a DomainName field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\DomainName $domainName The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeDomainName(DecodingContext $decodingContext, DomainName $domainName) : int
    {
        $packet = $decodingContext->getPacket();
        $startIndex = '0x' . \dechex($packet->getPointer());
        $labelRegistry = $decodingContext->getLabelRegistry();
        $labels = [];
        $totalLength = 0;
        while (++$totalLength && ($length = \ord($this->readDataFromPacket($packet, 1)))) {
            $labelType = $length & 0b11000000;
            if ($labelType === 0b0) {
                $index = $packet->getPointer() - 1;
                $label = $this->readDataFromPacket($packet, $length);
                \array_unshift($labels, [$index, $label]);
                $totalLength += $length;
            } else {
                if ($labelType === 0b11000000) {
                    $index = ($length & 0b111111) << 8 | \ord($this->readDataFromPacket($packet, 1));
                    $ref = $labelRegistry->lookupLabel($index);
                    if ($ref === null) {
                        throw new \UnexpectedValueException('Decode error: Invalid compression pointer reference in domain name at position ' . $startIndex);
                    }
                    \array_unshift($labels, $ref);
                    $totalLength++;
                    break;
                } else {
                    throw new \UnexpectedValueException('Decode error: Invalid label type ' . $labelType . 'in domain name at position ' . $startIndex);
                }
            }
        }
        $result = [];
        foreach ($labels as $label) {
            if (\is_int($label[0])) {
                \array_unshift($result, $label[1]);
                $labelRegistry->register($result, $label[0]);
            } else {
                $result = $label;
            }
        }
        $domainName->setLabels($result);
        return $totalLength;
    }
    /**
     * Decode an IPv4Address field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\IPv4Address $ipv4Address The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeIPv4Address(DecodingContext $decodingContext, IPv4Address $ipv4Address) : int
    {
        $octets = \unpack('C4', $this->readDataFromPacket($decodingContext->getPacket(), 4));
        $ipv4Address->setOctets($octets);
        return 4;
    }
    /**
     * Decode an IPv6Address field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\IPv6Address $ipv6Address The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeIPv6Address(DecodingContext $decodingContext, IPv6Address $ipv6Address) : int
    {
        $shorts = \unpack('n8', $this->readDataFromPacket($decodingContext->getPacket(), 16));
        $ipv6Address->setShorts($shorts);
        return 16;
    }
    /**
     * Decode a Long field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Long $long The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeLong(DecodingContext $decodingContext, Long $long) : int
    {
        $value = \unpack('N', $this->readDataFromPacket($decodingContext->getPacket(), 4))[1];
        $long->setValue($value);
        return 4;
    }
    /**
     * Decode a Short field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Short $short The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeShort(DecodingContext $decodingContext, Short $short) : int
    {
        $value = \unpack('n', $this->readDataFromPacket($decodingContext->getPacket(), 2))[1];
        $short->setValue($value);
        return 2;
    }
    /**
     * Decode a Type field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Type $type The object to populate with the result
     * @param int $length Expected data length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     * @throws \InvalidArgumentException When the Type subtype is unknown
     */
    private function decodeType(DecodingContext $decodingContext, Type $type, int $length) : int
    {
        if ($type instanceof Anything) {
            $result = $this->decodeAnything($decodingContext, $type, $length);
        } else {
            if ($type instanceof BitMap) {
                $result = $this->decodeBitMap($decodingContext, $type, $length);
            } else {
                if ($type instanceof Char) {
                    $result = $this->decodeChar($decodingContext, $type);
                } else {
                    if ($type instanceof CharacterString) {
                        $result = $this->decodeCharacterString($decodingContext, $type);
                    } else {
                        if ($type instanceof DomainName) {
                            $result = $this->decodeDomainName($decodingContext, $type);
                        } else {
                            if ($type instanceof IPv4Address) {
                                $result = $this->decodeIPv4Address($decodingContext, $type);
                            } else {
                                if ($type instanceof IPv6Address) {
                                    $result = $this->decodeIPv6Address($decodingContext, $type);
                                } else {
                                    if ($type instanceof Long) {
                                        $result = $this->decodeLong($decodingContext, $type);
                                    } else {
                                        if ($type instanceof Short) {
                                            $result = $this->decodeShort($decodingContext, $type);
                                        } else {
                                            throw new \InvalidArgumentException('Unknown Type ' . \get_class($type));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return $result;
    }
    /**
     * Decode a question record
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @return \LibDNS\Records\Question
     * @throws \UnexpectedValueException When the record is invalid
     */
    private function decodeQuestionRecord(DecodingContext $decodingContext) : Question
    {
        /** @var \LibDNS\Records\Types\DomainName $domainName */
        $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
        $this->decodeDomainName($decodingContext, $domainName);
        $meta = \unpack('ntype/nclass', $this->readDataFromPacket($decodingContext->getPacket(), 4));
        $question = $this->questionFactory->create($meta['type']);
        $question->setName($domainName);
        $question->setClass($meta['class']);
        return $question;
    }
    /**
     * Decode a resource record
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @return \LibDNS\Records\Resource
     * @throws \UnexpectedValueException When the record is invalid
     * @throws \InvalidArgumentException When a type subtype is unknown
     */
    private function decodeResourceRecord(DecodingContext $decodingContext) : Resource
    {
        /** @var \LibDNS\Records\Types\DomainName $domainName */
        $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
        $this->decodeDomainName($decodingContext, $domainName);
        $meta = \unpack('ntype/nclass/Nttl/nlength', $this->readDataFromPacket($decodingContext->getPacket(), 10));
        $resource = $this->resourceBuilder->build($meta['type']);
        $resource->setName($domainName);
        $resource->setClass($meta['class']);
        $resource->setTTL($meta['ttl']);
        $data = $resource->getData();
        $remainingLength = $meta['length'];
        $fieldDef = $index = null;
        foreach ($resource->getData()->getTypeDefinition() as $index => $fieldDef) {
            $field = $this->typeBuilder->build($fieldDef->getType());
            $remainingLength -= $this->decodeType($decodingContext, $field, $remainingLength);
            $data->setField($index, $field);
        }
        if ($fieldDef->allowsMultiple()) {
            while ($remainingLength) {
                $field = $this->typeBuilder->build($fieldDef->getType());
                $remainingLength -= $this->decodeType($decodingContext, $field, $remainingLength);
                $data->setField(++$index, $field);
            }
        }
        if ($remainingLength !== 0) {
            throw new \UnexpectedValueException('Decode error: Invalid length for record data section');
        }
        return $resource;
    }
    /**
     * Decode a Message from raw network data
     *
     * @param string $data The data string to decode
     * @return \LibDNS\Messages\Message
     * @throws \UnexpectedValueException When the packet data is invalid
     * @throws \InvalidArgumentException When a type subtype is unknown
     */
    public function decode(string $data) : Message
    {
        $packet = $this->packetFactory->create($data);
        $decodingContext = $this->decodingContextFactory->create($packet);
        $message = $this->messageFactory->create();
        $this->decodeHeader($decodingContext, $message);
        $questionRecords = $message->getQuestionRecords();
        $expected = $decodingContext->getExpectedQuestionRecords();
        for ($i = 0; $i < $expected; $i++) {
            $questionRecords->add($this->decodeQuestionRecord($decodingContext));
        }
        $answerRecords = $message->getAnswerRecords();
        $expected = $decodingContext->getExpectedAnswerRecords();
        for ($i = 0; $i < $expected; $i++) {
            $answerRecords->add($this->decodeResourceRecord($decodingContext));
        }
        $authorityRecords = $message->getAuthorityRecords();
        $expected = $decodingContext->getExpectedAuthorityRecords();
        for ($i = 0; $i < $expected; $i++) {
            $authorityRecords->add($this->decodeResourceRecord($decodingContext));
        }
        $additionalRecords = $message->getAdditionalRecords();
        $expected = $decodingContext->getExpectedAdditionalRecords();
        for ($i = 0; $i < $expected; $i++) {
            $additionalRecords->add($this->decodeResourceRecord($decodingContext));
        }
        if (!$this->allowTrailingData && $packet->getBytesRemaining() !== 0) {
            throw new \UnexpectedValueException('Decode error: Unexpected data at end of packet');
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible message response codes
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Enumeration;
/**
 * Enumeration of possible message types
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class MessageResponseCodes extends Enumeration
{
    const NO_ERROR = 0;
    const FORMAT_ERROR = 1;
    const SERVER_FAILURE = 2;
    const NAME_ERROR = 3;
    const NOT_IMPLEMENTED = 4;
    const REFUSED = 5;
}<?php

declare (strict_types=1);
/**
 * Represents a DNS protocol message
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Records\RecordCollection;
use LibDNS\Records\RecordCollectionFactory;
use LibDNS\Records\RecordTypes;
/**
 * Represents a DNS protocol message
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Message
{
    /**
     * @var int Unsigned short that identifies the DNS transaction
     */
    private $id = 0;
    /**
     * @var int Indicates the type of the message, can be indicated using the MessageTypes enum
     */
    private $type = -1;
    /**
     * @var int Message opcode, can be indicated using the MessageOpCodes enum
     */
    private $opCode = MessageOpCodes::QUERY;
    /**
     * @var bool Whether a response message is authoritative
     */
    private $authoritative = false;
    /**
     * @var bool Whether the message is truncated
     */
    private $truncated = false;
    /**
     * @var bool Whether a query desires the server to recurse the lookup
     */
    private $recursionDesired = true;
    /**
     * @var bool Whether a server could provide recursion in a response
     */
    private $recursionAvailable = false;
    /**
     * @var int Message response code, can be indicated using the MessageResponseCodes enum
     */
    private $responseCode = MessageResponseCodes::NO_ERROR;
    /**
     * @var \LibDNS\Records\RecordCollection Collection of question records
     */
    private $questionRecords;
    /**
     * @var \LibDNS\Records\RecordCollection Collection of question records
     */
    private $answerRecords;
    /**
     * @var \LibDNS\Records\RecordCollection Collection of authority records
     */
    private $authorityRecords;
    /**
     * @var \LibDNS\Records\RecordCollection Collection of authority records
     */
    private $additionalRecords;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\RecordCollectionFactory $recordCollectionFactory Factory which makes RecordCollection objects
     * @param int $type Value of the message type field
     * @throws \RangeException When the supplied message type is outside the valid range 0 - 1
     */
    public function __construct(RecordCollectionFactory $recordCollectionFactory, int $type = null)
    {
        $this->questionRecords = $recordCollectionFactory->create(RecordTypes::QUESTION);
        $this->answerRecords = $recordCollectionFactory->create(RecordTypes::RESOURCE);
        $this->authorityRecords = $recordCollectionFactory->create(RecordTypes::RESOURCE);
        $this->additionalRecords = $recordCollectionFactory->create(RecordTypes::RESOURCE);
        if ($type !== null) {
            $this->setType($type);
        }
    }
    /**
     * Get the value of the message ID field
     *
     * @return int
     */
    public function getID() : int
    {
        return $this->id;
    }
    /**
     * Set the value of the message ID field
     *
     * @param int $id The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 65535
     */
    public function setID(int $id)
    {
        if ($id < 0 || $id > 65535) {
            throw new \RangeException('Message ID must be in the range 0 - 65535');
        }
        $this->id = $id;
    }
    /**
     * Get the value of the message type field
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     * Set the value of the message type field
     *
     * @param int $type The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 1
     */
    public function setType(int $type)
    {
        if ($type < 0 || $type > 1) {
            throw new \RangeException('Message type must be in the range 0 - 1');
        }
        $this->type = $type;
    }
    /**
     * Get the value of the message opcode field
     *
     * @return int
     */
    public function getOpCode() : int
    {
        return $this->opCode;
    }
    /**
     * Set the value of the message opcode field
     *
     * @param int $opCode The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 15
     */
    public function setOpCode(int $opCode)
    {
        if ($opCode < 0 || $opCode > 15) {
            throw new \RangeException('Message opcode must be in the range 0 - 15');
        }
        $this->opCode = $opCode;
    }
    /**
     * Inspect the value of the authoritative field and optionally set a new value
     *
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isAuthoritative(bool $newValue = null) : bool
    {
        $result = $this->authoritative;
        if ($newValue !== null) {
            $this->authoritative = $newValue;
        }
        return $result;
    }
    /**
     * Inspect the value of the truncated field and optionally set a new value
     *
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isTruncated(bool $newValue = null) : bool
    {
        $result = $this->truncated;
        if ($newValue !== null) {
            $this->truncated = $newValue;
        }
        return $result;
    }
    /**
     * Inspect the value of the recusion desired field and optionally set a new value
     *
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isRecursionDesired(bool $newValue = null) : bool
    {
        $result = $this->recursionDesired;
        if ($newValue !== null) {
            $this->recursionDesired = $newValue;
        }
        return $result;
    }
    /**
     * Inspect the value of the recursion available field and optionally set a new value
     *
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isRecursionAvailable(bool $newValue = null) : bool
    {
        $result = $this->recursionAvailable;
        if ($newValue !== null) {
            $this->recursionAvailable = $newValue;
        }
        return $result;
    }
    /**
     * Get the value of the message response code field
     *
     * @return int
     */
    public function getResponseCode() : int
    {
        return $this->responseCode;
    }
    /**
     * Set the value of the message response code field
     *
     * @param int $responseCode The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 15
     */
    public function setResponseCode(int $responseCode)
    {
        if ($responseCode < 0 || $responseCode > 15) {
            throw new \RangeException('Message response code must be in the range 0 - 15');
        }
        $this->responseCode = $responseCode;
    }
    /**
     * Get the question records collection
     *
     * @return \LibDNS\Records\RecordCollection
     */
    public function getQuestionRecords() : RecordCollection
    {
        return $this->questionRecords;
    }
    /**
     * Get the answer records collection
     *
     * @return \LibDNS\Records\RecordCollection
     */
    public function getAnswerRecords() : RecordCollection
    {
        return $this->answerRecords;
    }
    /**
     * Get the authority records collection
     *
     * @return \LibDNS\Records\RecordCollection
     */
    public function getAuthorityRecords() : RecordCollection
    {
        return $this->authorityRecords;
    }
    /**
     * Get the additional records collection
     *
     * @return \LibDNS\Records\RecordCollection
     */
    public function getAdditionalRecords() : RecordCollection
    {
        return $this->additionalRecords;
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible message types
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Enumeration;
/**
 * Enumeration of possible message types
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class MessageTypes extends Enumeration
{
    const QUERY = 0;
    const RESPONSE = 1;
}<?php

declare (strict_types=1);
/**
 * Factory which creates Message objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Records\RecordCollectionFactory;
/**
 * Factory which creates Message objects
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class MessageFactory
{
    /**
     * Create a new Message object
     *
     * @param int $type Value of the message type field
     * @return \LibDNS\Messages\Message
     */
    public function create(int $type = null) : Message
    {
        return new Message(new RecordCollectionFactory(), $type);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible message opcodes
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Enumeration;
/**
 * Enumeration of possible message types
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class MessageOpCodes extends Enumeration
{
    const QUERY = 0;
    const IQUERY = 1;
    const STATUS = 2;
}<?php

declare (strict_types=1);
/**
 * Base class for enumerations to prevent instantiation
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package LibDNS
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS;

/**
 * Base class for enumerations to prevent instantiation
 *
 * @category LibDNS
 * @package LibDNS
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class Enumeration
{
    /**
     *
     */
    protected final function __construct()
    {
        throw new \LogicException('Enumerations cannot be instantiated');
    }
}<?php

declare (strict_types=1);
namespace LibDNS;

if (\function_exists('idn_to_ascii')) {
    /**
     *
     */
    function normalize_name(string $label) : string
    {
        if (false === ($result = \idn_to_ascii($label, 0, INTL_IDNA_VARIANT_UTS46))) {
            throw new \InvalidArgumentException("Label '{$label}' could not be processed for IDN");
        }
        return $result;
    }
} else {
    /**
     *
     */
    function normalize_name(string $label) : string
    {
        if (\preg_match('/[\\x80-\\xff]/', $label)) {
            throw new \InvalidArgumentException("Label '{$label}' contains non-ASCII characters and IDN support is not available." . " Verify that ext/intl is installed for IDN support.");
        }
        return \strtolower($label);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible resource QCLASS values
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

/**
 * Enumeration of possible resource QCLASS values
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class ResourceQClasses extends ResourceClasses
{
    const ANY = 255;
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible record types
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Enumeration;
/**
 * Enumeration of possible record types
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class RecordTypes extends Enumeration
{
    const QUESTION = 0;
    const RESOURCE = 1;
}<?php

declare (strict_types=1);
/**
 * Creates ResourceBuilder objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\TypeFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionManager;
use LibDNS\Records\TypeDefinitions\TypeDefinitionFactory;
use LibDNS\Records\TypeDefinitions\FieldDefinitionFactory;
/**
 * Creates ResourceBuilder objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class ResourceBuilderFactory
{
    /**
     * Create a new ResourceBuilder object
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager
     * @return \LibDNS\Records\ResourceBuilder
     */
    public function create(TypeDefinitionManager $typeDefinitionManager = null) : ResourceBuilder
    {
        return new ResourceBuilder(new ResourceFactory(), new RDataBuilder(new RDataFactory(), new TypeBuilder(new TypeFactory())), $typeDefinitionManager ?: new TypeDefinitionManager(new TypeDefinitionFactory(), new FieldDefinitionFactory()));
    }
}<?php

declare (strict_types=1);
/**
 * Collection of Record objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

/**
 * Collection of Record objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RecordCollection implements \IteratorAggregate, \Countable
{
    /**
     * @var \LibDNS\Records\Record[] List of records held in the collection
     */
    private $records = [];
    /**
     * @var \LibDNS\Records\Record[][] Map of Records in the collection grouped by record name
     */
    private $nameMap = [];
    /**
     * @var int Number of Records in the collection
     */
    private $length = 0;
    /**
     * @var int Whether the collection holds question or resource records
     */
    private $type;
    /**
     * Constructor
     *
     * @param int $type Can be indicated using the RecordTypes enum
     * @throws \InvalidArgumentException When the specified record type is invalid
     */
    public function __construct($type)
    {
        if ($type !== RecordTypes::QUESTION && $type !== RecordTypes::RESOURCE) {
            throw new \InvalidArgumentException('Record type must be QUESTION or RESOURCE');
        }
        $this->type = $type;
    }
    /**
     * Add a record to the correct bucket in the name map
     *
     * @param \LibDNS\Records\Record $record The record to add
     */
    private function addToNameMap(Record $record)
    {
        if (!isset($this->nameMap[$name = (string) $record->getName()])) {
            $this->nameMap[$name] = [];
        }
        $this->nameMap[$name][] = $record;
    }
    /**
     * Remove a record from the name map
     *
     * @param \LibDNS\Records\Record $record The record to remove
     */
    private function removeFromNameMap(Record $record)
    {
        if (!empty($this->nameMap[$name = (string) $record->getName()])) {
            foreach ($this->nameMap[$name] as $key => $item) {
                if ($item === $record) {
                    \array_splice($this->nameMap[$name], $key, 1);
                    break;
                }
            }
        }
        if (empty($this->nameMap[$name])) {
            unset($this->nameMap[$name]);
        }
    }
    /**
     * Add a record to the collection
     *
     * @param \LibDNS\Records\Record $record The record to add
     * @throws \InvalidArgumentException When the wrong record type is supplied
     */
    public function add(Record $record)
    {
        if ($this->type === RecordTypes::QUESTION && !$record instanceof Question || $this->type === RecordTypes::RESOURCE && !$record instanceof Resource) {
            throw new \InvalidArgumentException('Incorrect record type for this collection');
        }
        $this->records[] = $record;
        $this->addToNameMap($record);
        $this->length++;
    }
    /**
     * Remove a record from the collection
     *
     * @param \LibDNS\Records\Record $record The record to remove
     */
    public function remove(Record $record)
    {
        foreach ($this->records as $key => $item) {
            if ($item === $record) {
                array_splice($this->records, $key, 1);
                $this->removeFromNameMap($record);
                $this->length--;
                return;
            }
        }
        throw new \InvalidArgumentException('The supplied record is not a member of this collection');
    }
    /**
     * Test whether the collection contains a specific record
     *
     * @param \LibDNS\Records\Record $record The record to search for
     * @param bool $sameInstance Whether to perform strict comparisons in search
     * @return bool
     */
    public function contains(Record $record, bool $sameInstance = false) : bool
    {
        return \in_array($record, $this->records, $sameInstance);
    }
    /**
     * Get all records in the collection that refer to the specified name
     *
     * @param string $name The name to match records against
     * @return \LibDNS\Records\Record[]
     */
    public function getRecordsByName(string $name) : array
    {
        return $this->nameMap[\strtolower($name)] ?? [];
    }
    /**
     * Get a record from the collection by index
     *
     * @param int $index Record index
     * @return \LibDNS\Records\Record
     * @throws \OutOfBoundsException When the supplied index does not refer to a valid record
     */
    public function getRecordByIndex(int $index) : Record
    {
        if (isset($this->records[$index])) {
            return $this->records[$index];
        }
        throw new \OutOfBoundsException('The specified index ' . $index . ' does not exist in the collection');
    }
    /**
     * Remove all records in the collection that refer to the specified name
     *
     * @param string $name The name to match records against
     * @return int The number of records removed
     */
    public function clearRecordsByName(string $name) : int
    {
        $count = 0;
        if (isset($this->nameMap[$name = \strtolower($name)])) {
            unset($this->nameMap[$name]);
            foreach ($this->records as $index => $record) {
                if ($record->getName() === $name) {
                    unset($this->records[$index]);
                    $count++;
                }
            }
            $this->records = \array_values($this->records);
        }
        return $count;
    }
    /**
     * Remove all records from the collection
     */
    public function clear()
    {
        $this->records = $this->nameMap = [];
        $this->length = 0;
    }
    /**
     * Get a list of all names referenced by records in the collection
     *
     * @return string[]
     */
    public function getNames() : array
    {
        return \array_keys($this->nameMap);
    }
    /**
     * Get whether the collection holds question or resource records
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     * Retrieve an iterator (IteratorAggregate interface)
     *
     * @return \Iterator
     */
    public function getIterator() : \Iterator
    {
        return new \ArrayIterator($this->records);
    }
    /**
     * Get the number of records in the collection (Countable interface)
     *
     * @return int
     */
    public function count() : int
    {
        return $this->length;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a DNS resource record
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeFactory;
/**
 * Represents a DNS resource record
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Resource extends Record
{
    /**
     * @var int Value of the resource's time-to-live property
     */
    private $ttl;
    /**
     * @var \LibDNS\Records\RData
     */
    private $data;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\Types\TypeFactory $typeFactory
     * @param int $type Can be indicated using the ResourceTypes enum
     * @param \LibDNS\Records\RData $data
     */
    public function __construct(TypeFactory $typeFactory, int $type, RData $data)
    {
        $this->typeFactory = $typeFactory;
        $this->type = $type;
        $this->data = $data;
    }
    /**
     * Get the value of the record TTL field
     *
     * @return int
     */
    public function getTTL() : int
    {
        return $this->ttl;
    }
    /**
     * Set the value of the record TTL field
     *
     * @param int $ttl The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 4294967296
     */
    public function setTTL(int $ttl)
    {
        if ($ttl < 0 || $ttl > 4294967296) {
            throw new \RangeException('Record class must be in the range 0 - 4294967296');
        }
        $this->ttl = $ttl;
    }
    /**
     * Get the value of the resource data field
     *
     * @return \LibDNS\Records\RData
     */
    public function getData() : RData
    {
        return $this->data;
    }
}<?php

declare (strict_types=1);
/**
 * Creates RecordCollection objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

/**
 * Creates RecordCollection objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RecordCollectionFactory
{
    /**
     * Create a new RecordCollection object
     *
     * @param int $type Can be indicated using the RecordTypes enum
     * @return \LibDNS\Records\RecordCollection
     * @throws \InvalidArgumentException When the specified record type is invalid
     */
    public function create(int $type) : RecordCollection
    {
        return new RecordCollection($type);
    }
}<?php

declare (strict_types=1);
/**
 * Represents the RDATA section of a resource record
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\Type;
use LibDNS\Records\TypeDefinitions\TypeDefinition;
/**
 * Represents a data type comprising multiple simple types
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RData implements \IteratorAggregate, \Countable
{
    /**
     * @var \LibDNS\Records\Types\Type[] The items that make up the complex type
     */
    private $fields = [];
    /**
     * @var \LibDNS\Records\TypeDefinitions\TypeDefinition Structural definition of the fields
     */
    private $typeDef;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinition $typeDef
     */
    public function __construct(TypeDefinition $typeDef)
    {
        $this->typeDef = $typeDef;
    }
    /**
     * Magic method for type coersion to string
     *
     * @return string
     */
    public function __toString()
    {
        if ($handler = $this->typeDef->getToStringFunction()) {
            $result = \call_user_func_array($handler, $this->fields);
        } else {
            $result = \implode(',', $this->fields);
        }
        return $result;
    }
    /**
     * Get the field indicated by the supplied index
     *
     * @param int $index
     * @return \LibDNS\Records\Types\Type
     * @throws \OutOfBoundsException When the supplied index does not refer to a valid field
     */
    public function getField(int $index)
    {
        if (!isset($this->fields[$index])) {
            throw new \OutOfBoundsException('Index ' . $index . ' does not refer to a valid field');
        }
        return $this->fields[$index];
    }
    /**
     * Set the field indicated by the supplied index
     *
     * @param int $index
     * @param \LibDNS\Records\Types\Type $value
     * @throws \InvalidArgumentException When the supplied index/value pair does not match the type definition
     */
    public function setField(int $index, Type $value)
    {
        if (!$this->typeDef->getFieldDefinition($index)->assertDataValid($value)) {
            throw new \InvalidArgumentException('The supplied value is not valid for the specified index');
        }
        $this->fields[$index] = $value;
    }
    /**
     * Get the field indicated by the supplied name
     *
     * @param string $name
     * @return \LibDNS\Records\Types\Type
     * @throws \OutOfBoundsException When the supplied name does not refer to a valid field
     */
    public function getFieldByName(string $name) : Type
    {
        return $this->getField($this->typeDef->getFieldIndexByName($name));
    }
    /**
     * Set the field indicated by the supplied name
     *
     * @param string $name
     * @param \LibDNS\Records\Types\Type $value
     * @throws \OutOfBoundsException When the supplied name does not refer to a valid field
     * @throws \InvalidArgumentException When the supplied value does not match the type definition
     */
    public function setFieldByName(string $name, Type $value)
    {
        $this->setField($this->typeDef->getFieldIndexByName($name), $value);
    }
    /**
     * Get the structural definition of the fields
     *
     * @return \LibDNS\Records\TypeDefinitions\TypeDefinition
     */
    public function getTypeDefinition() : TypeDefinition
    {
        return $this->typeDef;
    }
    /**
     * Retrieve an iterator (IteratorAggregate interface)
     *
     * @return \Iterator
     */
    public function getIterator() : \Iterator
    {
        return new \ArrayIterator($this->fields);
    }
    /**
     * Get the number of fields (Countable interface)
     *
     * @return int
     */
    public function count() : int
    {
        return \count($this->fields);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible resource CLASS values
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Enumeration;
/**
 * Enumeration of possible resource CLASS values
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class ResourceClasses extends Enumeration
{
    const IN = 1;
    const CS = 2;
    const CH = 3;
    const HS = 4;
}<?php

declare (strict_types=1);
/**
 * Creates Resource objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeFactory;
/**
 * Creates Resource objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class ResourceFactory
{
    /**
     * Create a new Resource object
     *
     * @param int $type Can be indicated using the ResourceTypes enum
     * @param \LibDNS\Records\RData $data
     * @return \LibDNS\Records\Resource
     */
    public function create(int $type, RData $data) : Resource
    {
        return new Resource(new TypeFactory(), $type, $data);
    }
}<?php

declare (strict_types=1);
/**
 * Creates RData objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\TypeDefinitions\TypeDefinition;
/**
 * Creates RData objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RDataFactory
{
    /**
     * Create a new RData object
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinition $typeDefinition
     * @return \LibDNS\Records\RData
     */
    public function create(TypeDefinition $typeDefinition) : RData
    {
        return new RData($typeDefinition);
    }
}<?php

declare (strict_types=1);
/**
 * Builds Resource objects of a specific type
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\TypeDefinitions\TypeDefinitionManager;
/**
 * Builds Resource objects of a specific type
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class ResourceBuilder
{
    /**
     * @var \LibDNS\Records\ResourceFactory
     */
    private $resourceFactory;
    /**
     * @var \LibDNS\Records\RDataBuilder
     */
    private $rDataBuilder;
    /**
     * @var \LibDNS\Records\TypeDefinitions\TypeDefinitionManager
     */
    private $typeDefinitionManager;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\ResourceFactory $resourceFactory
     * @param \LibDNS\Records\RDataBuilder $rDataBuilder
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager
     */
    public function __construct(ResourceFactory $resourceFactory, RDataBuilder $rDataBuilder, TypeDefinitionManager $typeDefinitionManager)
    {
        $this->resourceFactory = $resourceFactory;
        $this->rDataBuilder = $rDataBuilder;
        $this->typeDefinitionManager = $typeDefinitionManager;
    }
    /**
     * Create a new Resource object
     *
     * @param int $type Type of the resource, can be indicated using the ResourceTypes enum
     * @return \LibDNS\Records\Resource
     */
    public function build(int $type) : Resource
    {
        $typeDefinition = $this->typeDefinitionManager->getTypeDefinition($type);
        $rData = $this->rDataBuilder->build($typeDefinition);
        return $this->resourceFactory->create($type, $rData);
    }
}<?php

declare (strict_types=1);
/**
 * Defines a field in a type
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
use LibDNS\Records\Types\Types;
/**
 * Defines a field in a type
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class FieldDefinition
{
    /**
     * @var int
     */
    private $index;
    /**
     * @var string
     */
    private $name;
    /**
     * @var int
     */
    private $type;
    /**
     * @var bool
     */
    private $allowsMultiple;
    /**
     * @var int
     */
    private $minimumValues;
    /**
     * Constructor
     *
     * @param int $index
     * @param string $name
     * @param int $type
     * @param bool $allowsMultiple
     * @param int $minimumValues
     */
    public function __construct(int $index, string $name, int $type, bool $allowsMultiple, int $minimumValues)
    {
        $this->index = $index;
        $this->name = $name;
        $this->type = $type;
        $this->allowsMultiple = $allowsMultiple;
        $this->minimumValues = $minimumValues;
    }
    /**
     * Get the index of the field in the containing type
     *
     * @return int
     */
    public function getIndex() : int
    {
        return $this->index;
    }
    /**
     * Get the name of the field
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * Get the type of the field
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     * Determine whether the field allows multiple values
     *
     * @return bool
     */
    public function allowsMultiple() : bool
    {
        return $this->allowsMultiple;
    }
    /**
     * Get the minimum number of values for the field
     *
     * @return int
     */
    public function getMinimumValues() : int
    {
        return $this->minimumValues;
    }
    /**
     * Assert that a Type object is valid for this field
     *
     * @param \LibDNS\Records\Types\Type
     * @return bool
     */
    public function assertDataValid(Type $value) : bool
    {
        return $this->type & Types::ANYTHING && $value instanceof Anything || $this->type & Types::BITMAP && $value instanceof BitMap || $this->type & Types::CHAR && $value instanceof Char || $this->type & Types::CHARACTER_STRING && $value instanceof CharacterString || $this->type & Types::DOMAIN_NAME && $value instanceof DomainName || $this->type & Types::IPV4_ADDRESS && $value instanceof IPv4Address || $this->type & Types::IPV6_ADDRESS && $value instanceof IPv6Address || $this->type & Types::LONG && $value instanceof Long || $this->type & Types::SHORT && $value instanceof Short;
    }
}<?php

declare (strict_types=1);
/**
 * Defines a data type comprising multiple fields
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

/**
 * Defines a data type comprising multiple fields
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeDefinition implements \IteratorAggregate, \Countable
{
    /**
     * @var FieldDefinitionFactory Creates FieldDefinition objects
     */
    private $fieldDefFactory;
    /**
     * @var int Number of fields in the type
     */
    private $fieldCount;
    /**
     * @var \LibDNS\Records\TypeDefinitions\FieldDefinition The last field defined by the type
     */
    private $lastField;
    /**
     * @var int[] Map of field indexes to type identifiers
     */
    private $fieldDefs = [];
    /**
     * @var int[] Map of field names to indexes
     */
    private $fieldNameMap = [];
    /**
     * @var callable Custom implementation for __toString() handling
     */
    private $toStringFunction;
    /**
     * Constructor
     *
     * @param FieldDefinitionFactory $fieldDefFactory
     * @param array $definition Structural definition of the fields
     * @throws \InvalidArgumentException When the type definition is invalid
     */
    public function __construct(FieldDefinitionFactory $fieldDefFactory, array $definition)
    {
        $this->fieldDefFactory = $fieldDefFactory;
        if (isset($definition['__toString'])) {
            if (!\is_callable($definition['__toString'])) {
                throw new \InvalidArgumentException('Invalid type definition: __toString() implementation is not callable');
            }
            $this->toStringFunction = $definition['__toString'];
            unset($definition['__toString']);
        }
        $this->fieldCount = \count($definition);
        $index = 0;
        foreach ($definition as $name => $type) {
            $this->registerField($index++, $name, $type);
        }
    }
    /**
     * Register a field from the type definition
     *
     * @param int $index
     * @param string $name
     * @param int $type
     * @throws \InvalidArgumentException When the field definition is invalid
     */
    private function registerField(int $index, string $name, int $type)
    {
        if (!\preg_match('/^(?P<name>[\\w\\-]+)(?P<quantifier>\\+|\\*)?(?P<minimum>(?<=\\+)\\d+)?$/', \strtolower($name), $matches)) {
            throw new \InvalidArgumentException('Invalid field definition ' . $name . ': Syntax error');
        }
        if (isset($matches['quantifier'])) {
            if ($index !== $this->fieldCount - 1) {
                throw new \InvalidArgumentException('Invalid field definition ' . $name . ': Quantifiers only allowed in last field');
            }
            if (!isset($matches['minimum'])) {
                $matches['minimum'] = $matches['quantifier'] === '+' ? 1 : 0;
            }
            $allowsMultiple = true;
            $minimumValues = (int) $matches['minimum'];
        } else {
            $allowsMultiple = false;
            $minimumValues = 0;
        }
        $this->fieldDefs[$index] = $this->fieldDefFactory->create($index, $matches['name'], $type, $allowsMultiple, $minimumValues);
        if ($index === $this->fieldCount - 1) {
            $this->lastField = $this->fieldDefs[$index];
        }
        $this->fieldNameMap[$matches['name']] = $index;
    }
    /**
     * Get the field definition indicated by the supplied index
     *
     * @param int $index
     * @return \LibDNS\Records\TypeDefinitions\FieldDefinition
     * @throws \OutOfBoundsException When the supplied index does not refer to a valid field
     */
    public function getFieldDefinition(int $index) : FieldDefinition
    {
        if (isset($this->fieldDefs[$index])) {
            $fieldDef = $this->fieldDefs[$index];
        } else {
            if ($index >= 0 && $this->lastField->allowsMultiple()) {
                $fieldDef = $this->lastField;
            } else {
                throw new \OutOfBoundsException('Index ' . $index . ' does not refer to a valid field');
            }
        }
        return $fieldDef;
    }
    /**
     * Get the field index indicated by the supplied name
     *
     * @param string $name
     * @return int
     * @throws \OutOfBoundsException When the supplied name does not refer to a valid field
     */
    public function getFieldIndexByName($name) : int
    {
        $fieldName = \strtolower($name);
        if (!isset($this->fieldNameMap[$fieldName])) {
            throw new \OutOfBoundsException('Name ' . $name . ' does not refer to a valid field');
        }
        return $this->fieldNameMap[$fieldName];
    }
    /**
     * Get the __toString() implementation
     *
     * @return (callable | null)
     */
    public function getToStringFunction()
    {
        return $this->toStringFunction;
    }
    /**
     * Set the __toString() implementation
     *
     * @param callable $function
     */
    public function setToStringFunction(callable $function)
    {
        $this->toStringFunction = $function;
    }
    /**
     * Retrieve an iterator (IteratorAggregate interface)
     *
     * @return \Iterator
     */
    public function getIterator() : \Iterator
    {
        return new \ArrayIterator($this->fieldDefs);
    }
    /**
     * Get the number of fields (Countable interface)
     *
     * @return int
     */
    public function count() : int
    {
        return $this->fieldCount;
    }
}<?php

declare (strict_types=1);
/**
 * Holds data about how the RDATA sections of known resource record types are structured
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

use LibDNS\Records\ResourceTypes;
use LibDNS\Records\Types\Types;
use LibDNS\Records\Types\DomainName;
/**
 * Holds data about how the RDATA sections of known resource record types are structured
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeDefinitionManager
{
    /**
     * @var array[] How the RDATA sections of known resource record types are structured
     */
    private $definitions = [];
    /**
     * @var array Cache of created definitions
     */
    private $typeDefs = [];
    /**
     * @var \LibDNS\Records\TypeDefinitions\TypeDefinitionFactory
     */
    private $typeDefFactory;
    /**
     * @var \LibDNS\Records\TypeDefinitions\FieldDefinitionFactory
     */
    private $fieldDefFactory;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionFactory $typeDefFactory
     * @param \LibDNS\Records\TypeDefinitions\FieldDefinitionFactory $fieldDefFactory
     */
    public function __construct(TypeDefinitionFactory $typeDefFactory, FieldDefinitionFactory $fieldDefFactory)
    {
        $this->typeDefFactory = $typeDefFactory;
        $this->fieldDefFactory = $fieldDefFactory;
        $this->setDefinitions();
    }
    /**
     * Set the internal definitions structure
     */
    private function setDefinitions()
    {
        // This is defined in a method because PHP doesn't let you define properties with
        // expressions at the class level. If anyone has a better way to do this I am open
        // to any and all suggestions.
        $this->definitions = [ResourceTypes::A => [
            // RFC 1035
            'address' => Types::IPV4_ADDRESS,
        ], ResourceTypes::AAAA => [
            // RFC 3596
            'address' => Types::IPV6_ADDRESS,
        ], ResourceTypes::AFSDB => [
            // RFC 1183
            'subtype' => Types::SHORT,
            'hostname' => Types::DOMAIN_NAME,
        ], ResourceTypes::CAA => [
            // RFC 6844
            'flags' => Types::DOMAIN_NAME,
            'tag' => Types::CHARACTER_STRING,
            'value' => Types::ANYTHING,
        ], ResourceTypes::CERT => [
            // RFC 4398
            'type' => Types::SHORT,
            'key-tag' => Types::SHORT,
            'algorithm' => Types::CHAR,
            'certificate' => Types::ANYTHING,
        ], ResourceTypes::CNAME => [
            // RFC 1035
            'cname' => Types::DOMAIN_NAME,
        ], ResourceTypes::DHCID => [
            // RFC 4701
            'identifier-type' => Types::SHORT,
            'digest-type' => Types::CHAR,
            'digest' => Types::ANYTHING,
        ], ResourceTypes::DLV => [
            // RFC 4034
            'key-tag' => Types::SHORT,
            'algorithm' => Types::CHAR,
            'digest-type' => Types::CHAR,
            'digest' => Types::ANYTHING,
        ], ResourceTypes::DNAME => [
            // RFC 4034
            'target' => Types::DOMAIN_NAME,
        ], ResourceTypes::DNSKEY => [
            // RFC 6672
            'flags' => Types::SHORT,
            'protocol' => Types::CHAR,
            'algorithm' => Types::CHAR,
            'public-key' => Types::ANYTHING,
        ], ResourceTypes::DS => [
            // RFC 4034
            'key-tag' => Types::SHORT,
            'algorithm' => Types::CHAR,
            'digest-type' => Types::CHAR,
            'digest' => Types::ANYTHING,
        ], ResourceTypes::HINFO => [
            // RFC 1035
            'cpu' => Types::CHARACTER_STRING,
            'os' => Types::CHARACTER_STRING,
        ], ResourceTypes::ISDN => [
            // RFC 1183
            'isdn-address' => Types::CHARACTER_STRING,
            'sa' => Types::CHARACTER_STRING,
        ], ResourceTypes::KEY => [
            // RFC 2535
            'flags' => Types::SHORT,
            'protocol' => Types::CHAR,
            'algorithm' => Types::CHAR,
            'public-key' => Types::ANYTHING,
        ], ResourceTypes::KX => [
            // RFC 2230
            'preference' => Types::SHORT,
            'exchange' => Types::DOMAIN_NAME,
        ], ResourceTypes::LOC => [
            // RFC 1876
            'version' => Types::CHAR,
            'size' => Types::CHAR,
            'horizontal-precision' => Types::CHAR,
            'vertical-precision' => Types::CHAR,
            'latitude' => Types::LONG,
            'longitude' => Types::LONG,
            'altitude' => Types::LONG,
        ], ResourceTypes::MB => [
            // RFC 1035
            'madname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MD => [
            // RFC 1035
            'madname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MF => [
            // RFC 1035
            'madname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MG => [
            // RFC 1035
            'mgmname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MINFO => [
            // RFC 1035
            'rmailbx' => Types::DOMAIN_NAME,
            'emailbx' => Types::DOMAIN_NAME,
        ], ResourceTypes::MR => [
            // RFC 1035
            'newname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MX => [
            // RFC 1035
            'preference' => Types::SHORT,
            'exchange' => Types::DOMAIN_NAME,
        ], ResourceTypes::NAPTR => [
            // RFC 3403
            'order' => Types::SHORT,
            'preference' => Types::SHORT,
            'flags' => Types::CHARACTER_STRING,
            'services' => Types::CHARACTER_STRING,
            'regexp' => Types::CHARACTER_STRING,
            'replacement' => Types::DOMAIN_NAME,
        ], ResourceTypes::NS => [
            // RFC 1035
            'nsdname' => Types::DOMAIN_NAME,
        ], ResourceTypes::NULL => [
            // RFC 1035
            'data' => Types::ANYTHING,
        ], ResourceTypes::PTR => [
            // RFC 1035
            'ptrdname' => Types::DOMAIN_NAME,
        ], ResourceTypes::RP => [
            // RFC 1183
            'mbox-dname' => Types::DOMAIN_NAME,
            'txt-dname' => Types::DOMAIN_NAME,
        ], ResourceTypes::RT => [
            // RFC 1183
            'preference' => Types::SHORT,
            'intermediate-host' => Types::DOMAIN_NAME,
        ], ResourceTypes::SIG => [
            // RFC 4034
            'type-covered' => Types::SHORT,
            'algorithm' => Types::CHAR,
            'labels' => Types::CHAR,
            'original-ttl' => Types::LONG,
            'signature-expiration' => Types::LONG,
            'signature-inception' => Types::LONG,
            'key-tag' => Types::SHORT,
            'signers-name' => Types::DOMAIN_NAME,
            'signature' => Types::ANYTHING,
        ], ResourceTypes::SOA => [
            // RFC 1035
            'mname' => Types::DOMAIN_NAME,
            'rname' => Types::DOMAIN_NAME,
            'serial' => Types::LONG,
            'refresh' => Types::LONG,
            'retry' => Types::LONG,
            'expire' => Types::LONG,
            'minimum' => Types::LONG,
        ], ResourceTypes::SPF => [
            // RFC 4408
            'data+' => Types::CHARACTER_STRING,
        ], ResourceTypes::SRV => [
            // RFC 2782
            'priority' => Types::SHORT,
            'weight' => Types::SHORT,
            'port' => Types::SHORT,
            'name' => Types::DOMAIN_NAME | DomainName::FLAG_NO_COMPRESSION,
        ], ResourceTypes::TXT => [
            // RFC 1035
            'txtdata+' => Types::CHARACTER_STRING,
        ], ResourceTypes::WKS => [
            // RFC 1035
            'address' => Types::IPV4_ADDRESS,
            'protocol' => Types::SHORT,
            'bit-map' => Types::BITMAP,
        ], ResourceTypes::X25 => [
            // RFC 1183
            'psdn-address' => Types::CHARACTER_STRING,
        ]];
    }
    /**
     * Get a type definition for a record type if it is known
     *
     * @param int $recordType Resource type, can be indicated using the ResourceTypes enum
     * @return \LibDNS\Records\TypeDefinitions\TypeDefinition
     */
    public function getTypeDefinition(int $recordType)
    {
        if (!isset($this->typeDefs[$recordType])) {
            $definition = isset($this->definitions[$recordType]) ? $this->definitions[$recordType] : ['data' => Types::ANYTHING];
            $this->typeDefs[$recordType] = $this->typeDefFactory->create($this->fieldDefFactory, $definition);
        }
        return $this->typeDefs[$recordType];
    }
    /**
     * Register a custom type definition
     *
     * @param int $recordType Resource type, can be indicated using the ResourceTypes enum
     * @param (int[] | \LibDNS\Records\TypeDefinitions\TypeDefinition) $definition
     * @throws \InvalidArgumentException When the type definition is invalid
     */
    public function registerTypeDefinition(int $recordType, $definition)
    {
        if (!$definition instanceof TypeDefinition) {
            if (!\is_array($definition)) {
                throw new \InvalidArgumentException('Definition must be an array or an instance of ' . __NAMESPACE__ . '\\TypeDefinition');
            }
            $definition = $this->typeDefFactory->create($this->fieldDefFactory, $definition);
        }
        $this->typeDefs[$recordType] = $definition;
    }
}<?php

declare (strict_types=1);
/**
 * Creates TypeDefinition objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

/**
 * Creates TypeDefinition objects
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeDefinitionFactory
{
    /**
     * Create a new TypeDefinition object
     *
     * @param FieldDefinitionFactory $fieldDefinitionFactory
     * @param int[] $definition Structural definition of the fields
     * @return \LibDNS\Records\TypeDefinitions\TypeDefinition
     * @throws \InvalidArgumentException When the type definition is invalid
     */
    public function create(FieldDefinitionFactory $fieldDefinitionFactory, array $definition) : TypeDefinition
    {
        return new TypeDefinition($fieldDefinitionFactory, $definition);
    }
}<?php

declare (strict_types=1);
/**
 * Creates TypeDefinitionManager objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

/**
 * Creates TypeDefinitionManager objects
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeDefinitionManagerFactory
{
    /**
     * Create a new TypeDefinitionManager object
     *
     * @return \LibDNS\Records\TypeDefinitions\TypeDefinitionManager
     */
    public function create() : TypeDefinitionManager
    {
        return new TypeDefinitionManager(new TypeDefinitionFactory(), new FieldDefinitionFactory());
    }
}<?php

declare (strict_types=1);
/**
 * Creates FieldDefinition objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

/**
 * Creates FieldDefinition objects
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class FieldDefinitionFactory
{
    /**
     * Create a new FieldDefinition object
     *
     * @param int $index
     * @param string $name
     * @param int $type
     * @param bool $allowsMultiple
     * @param int $minimumValues
     * @return \LibDNS\Records\TypeDefinitions\FieldDefinition
     */
    public function create(int $index, string $name, int $type, bool $allowsMultiple, int $minimumValues) : FieldDefinition
    {
        return new FieldDefinition($index, $name, $type, $allowsMultiple, $minimumValues);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible resource TYPE values
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Enumeration;
/**
 * Enumeration of possible resource TYPE values
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class ResourceTypes extends Enumeration
{
    const A = 1;
    const AAAA = 28;
    const AFSDB = 18;
    //    const APL        = 42;
    const CAA = 257;
    const CERT = 37;
    const CNAME = 5;
    const DHCID = 49;
    const DLV = 32769;
    const DNAME = 39;
    const DNSKEY = 48;
    const DS = 43;
    const HINFO = 13;
    //    const HIP        = 55;
    //    const IPSECKEY   = 45;
    const KEY = 25;
    const KX = 36;
    const ISDN = 20;
    const LOC = 29;
    const MB = 7;
    const MD = 3;
    const MF = 4;
    const MG = 8;
    const MINFO = 14;
    const MR = 9;
    const MX = 15;
    const NAPTR = 35;
    const NS = 2;
    //    const NSEC       = 47;
    //    const NSEC3      = 50;
    //    const NSEC3PARAM = 50;
    const NULL = 10;
    const PTR = 12;
    const RP = 17;
    //    const RRSIG      = 46;
    const RT = 21;
    const SIG = 24;
    const SOA = 6;
    const SPF = 99;
    const SRV = 33;
    const TXT = 16;
    const WKS = 11;
    const X25 = 19;
}<?php

declare (strict_types=1);
/**
 * Creates Question objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeFactory;
/**
 * Creates Question objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class QuestionFactory
{
    /**
     * Create a new Question object
     *
     * @param int $type The resource type
     * @return \LibDNS\Records\Question
     */
    public function create(int $type) : Question
    {
        return new Question(new TypeFactory(), $type);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of simple data types
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

use LibDNS\Enumeration;
/**
 * Enumeration of simple data types
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class Types extends Enumeration
{
    const ANYTHING = 0b1;
    const BITMAP = 0b10;
    const CHAR = 0b100;
    const CHARACTER_STRING = 0b1000;
    const DOMAIN_NAME = 0b10000;
    const IPV4_ADDRESS = 0b100000;
    const IPV6_ADDRESS = 0b1000000;
    const LONG = 0b10000000;
    const SHORT = 0b100000000;
}<?php

declare (strict_types=1);
/**
 * Represents an IPv4 address
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents an IPv4 address
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class IPv4Address extends Type
{
    /**
     * @var string
     */
    protected $value = '0.0.0.0';
    /**
     * @var int[] The octets of the address
     */
    private $octets = [0, 0, 0, 0];
    /**
     * Constructor
     *
     * @param (string | int[]) $value String representation or octet list
     * @throws \UnexpectedValueException When the supplied value is not a valid IPv4 address
     */
    public function __construct($value = null)
    {
        if (\is_array($value)) {
            $this->setOctets($value);
        } else {
            parent::__construct($value);
        }
    }
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is outside the valid length range 0 - 65535
     */
    public function setValue($value)
    {
        $this->setOctets(\explode('.', (string) $value));
    }
    /**
     * Get the address octets
     *
     * @return int[]
     */
    public function getOctets() : array
    {
        return $this->octets;
    }
    /**
     * Set the address octets
     *
     * @param int[] $octets The new address octets
     * @throws \UnexpectedValueException When the supplied octet list is not a valid IPv4 address
     */
    public function setOctets(array $octets)
    {
        if (\count($octets) !== 4) {
            throw new \UnexpectedValueException('Octet list is not a valid IPv4 address: invalid octet count');
        }
        foreach ($octets as &$octet) {
            if (!\is_int($octet) && !\ctype_digit((string) $octet) || $octet < 0x0 || $octet > 0xff) {
                throw new \UnexpectedValueException('Octet list is not a valid IPv4 address: invalid octet value ' . $octet);
            }
            $octet = (int) $octet;
        }
        $this->octets = \array_values($octets);
        $this->value = \implode('.', $this->octets);
    }
}<?php

declare (strict_types=1);
/**
 * Represents an 8-bit unsigned integer
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents an 8-bit unsigned integer
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Char extends Type
{
    /**
     * @var int
     */
    protected $value = 0;
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnderflowException When the supplied value is less than 0
     * @throws \OverflowException When the supplied value is greater than 255
     */
    public function setValue($value)
    {
        $value = (int) $value;
        if ($value < 0) {
            throw new \UnderflowException('Char value must be in the range 0 - 255');
        } else {
            if ($value > 255) {
                throw new \OverflowException('Char value must be in the range 0 - 255');
            }
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a bit map
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a bit map
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class BitMap extends Type
{
    /**
     * @var string
     */
    protected $value = '';
    /**
     * Set the internal value
     *
     * @param string $value The new value
     */
    public function setValue($value)
    {
        $this->value = (string) $value;
    }
    /**
     * Inspect the value of the bit at the specific index and optionally set a new value
     *
     * @param int $index
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isBitSet(int $index, bool $newValue = null) : bool
    {
        $charIndex = (int) ($index / 8);
        $bitMask = 0b10000000 >> $index % 8;
        $result = false;
        if (isset($this->value[$charIndex])) {
            $result = (bool) (\ord($this->value[$charIndex]) & $bitMask);
        }
        if (isset($newValue) && $newValue != $result) {
            if (!isset($this->value[$charIndex])) {
                $this->value = \str_pad($this->value, $charIndex + 1, "\x00", STR_PAD_RIGHT);
            }
            $this->value[$charIndex] = \chr(\ord($this->value[$charIndex]) & ~$bitMask | ($newValue ? $bitMask : 0));
        }
        return $result;
    }
}<?php

declare (strict_types=1);
/**
 * Represents an IPv6 address
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents an IPv6 address
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class IPv6Address extends Type
{
    /**
     * @var string
     */
    protected $value = '::';
    /**
     * @var int[] The shorts of the address
     */
    private $shorts = [0, 0, 0, 0, 0, 0, 0, 0];
    /**
     * Create a compressed string representation of an IPv6 address
     *
     * @param int[] $shorts Address shorts
     * @return string
     */
    private function createCompressedString($shorts)
    {
        $compressLen = $compressPos = $currentLen = $currentPos = 0;
        $inBlock = false;
        for ($i = 0; $i < 8; $i++) {
            if ($shorts[$i] === 0) {
                if (!$inBlock) {
                    $inBlock = true;
                    $currentPos = $i;
                }
                $currentLen++;
            } else {
                if ($inBlock) {
                    if ($currentLen > $compressLen) {
                        $compressLen = $currentLen;
                        $compressPos = $currentPos;
                    }
                    $inBlock = false;
                    $currentPos = $currentLen = 0;
                }
            }
            $shorts[$i] = \dechex($shorts[$i]);
        }
        if ($inBlock) {
            $compressLen = $currentLen;
            $compressPos = $currentPos;
        }
        if ($compressLen > 1) {
            if ($compressLen === 8) {
                $replace = ['', '', ''];
            } else {
                if ($compressPos === 0 || $compressPos + $compressLen === 8) {
                    $replace = ['', ''];
                } else {
                    $replace = [''];
                }
            }
            \array_splice($shorts, $compressPos, $compressLen, $replace);
        }
        return \implode(':', $shorts);
    }
    /**
     * Constructor
     *
     * @param (string | int[]) $value String representation or shorts list
     * @throws \UnexpectedValueException When the supplied value is not a valid IPv6 address
     */
    public function __construct($value = null)
    {
        if (\is_array($value)) {
            $this->setShorts($value);
        } else {
            parent::__construct($value);
        }
    }
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is outside the valid length range 0 - 65535
     */
    public function setValue($value)
    {
        $shorts = \explode(':', (string) $value);
        $count = \count($shorts);
        if ($count < 3 || $count > 8) {
            throw new \UnexpectedValueException('Value is not a valid IPv6 address: invalid short count');
        } else {
            if ($shorts[0] === '' && $shorts[1] === '') {
                $shorts = \array_pad($shorts, -8, '0');
            } else {
                if ($shorts[$count - 2] === '' && $shorts[$count - 1] === '') {
                    $shorts = \array_pad($shorts, 8, '0');
                } else {
                    if (false !== ($pos = \array_search('', $shorts, true))) {
                        \array_splice($shorts, $pos, 1, \array_fill(0, 8 - ($count - 1), '0'));
                    }
                }
            }
        }
        $this->setShorts(\array_map('hexdec', $shorts));
    }
    /**
     * Get the address shorts
     *
     * @return int[]
     */
    public function getShorts() : array
    {
        return $this->shorts;
    }
    /**
     * Set the address shorts
     *
     * @param int[] $shorts The new address shorts
     * @throws \UnexpectedValueException When the supplied short list is not a valid IPv6 address
     */
    public function setShorts(array $shorts)
    {
        if (\count($shorts) !== 8) {
            throw new \UnexpectedValueException('Short list is not a valid IPv6 address: invalid short count');
        }
        foreach ($shorts as &$short) {
            if (!\is_int($short) && !\ctype_digit((string) $short) || $short < 0x0 || $short > 0xffff) {
                throw new \UnexpectedValueException('Short list is not a valid IPv6 address: invalid short value ' . $short);
            }
            $short = (int) $short;
        }
        $this->shorts = \array_values($shorts);
        $this->value = $this->createCompressedString($this->shorts);
    }
}<?php

declare (strict_types=1);
/**
 * Base class for simple data types
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Base class for simple data types
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class Type
{
    /**
     * @var mixed The internal value
     */
    protected $value;
    /**
     * Constructor
     *
     * @param string $value Internal value
     * @throws \RuntimeException When the supplied value is invalid
     */
    public function __construct(string $value = null)
    {
        if (isset($value)) {
            $this->setValue($value);
        }
    }
    /**
     * Magic method for type coercion to string
     *
     * @return string
     */
    public function __toString() : string
    {
        return (string) $this->value;
    }
    /**
     * Get the internal value
     *
     * @return mixed
     */
    public function getValue()
    {
        return $this->value;
    }
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \RuntimeException When the supplied value is invalid
     */
    public abstract function setValue($value);
}<?php

declare (strict_types=1);
/**
 * Creates Type objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Creates Type objects
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeFactory
{
    /**
     * Create a new Anything object
     *
     * @param string $value
     * @return \LibDNS\Records\Types\Anything
     */
    public function createAnything(string $value = null)
    {
        return new Anything($value);
    }
    /**
     * Create a new BitMap object
     *
     * @param string $value
     * @return \LibDNS\Records\Types\BitMap
     */
    public function createBitMap(string $value = null)
    {
        return new BitMap($value);
    }
    /**
     * Create a new Char object
     *
     * @param int $value
     * @return \LibDNS\Records\Types\Char
     */
    public function createChar(int $value = null)
    {
        return new Char((string) $value);
    }
    /**
     * Create a new CharacterString object
     *
     * @param string $value
     * @return \LibDNS\Records\Types\CharacterString
     */
    public function createCharacterString(string $value = null)
    {
        return new CharacterString($value);
    }
    /**
     * Create a new DomainName object
     *
     * @param (string | string[]) $value
     * @return \LibDNS\Records\Types\DomainName
     */
    public function createDomainName($value = null)
    {
        return new DomainName($value);
    }
    /**
     * Create a new IPv4Address object
     *
     * @param (string | int[]) $value
     * @return \LibDNS\Records\Types\IPv4Address
     */
    public function createIPv4Address($value = null)
    {
        return new IPv4Address($value);
    }
    /**
     * Create a new IPv6Address object
     *
     * @param (string | int[]) $value
     * @return \LibDNS\Records\Types\IPv6Address
     */
    public function createIPv6Address($value = null)
    {
        return new IPv6Address($value);
    }
    /**
     * Create a new Long object
     *
     * @param int $value
     * @return \LibDNS\Records\Types\Long
     */
    public function createLong(int $value = null)
    {
        return new Long((string) $value);
    }
    /**
     * Create a new Short object
     *
     * @param int $value
     * @return \LibDNS\Records\Types\Short
     */
    public function createShort(int $value = null)
    {
        return new Short((string) $value);
    }
}<?php

declare (strict_types=1);
/**
 * Represents a binary character string
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a binary character string
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class CharacterString extends Type
{
    /**
     * @var string
     */
    protected $value = '';
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is outside the valid length range 0 - 255
     */
    public function setValue($value)
    {
        $value = (string) $value;
        if (\strlen($value) > 255) {
            throw new \UnexpectedValueException('Character string length must be in the range 0 - 255');
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a 16-bit unsigned integer
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a 16-bit unsigned integer
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Short extends Type
{
    /**
     * @var int
     */
    protected $value = 0;
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnderflowException When the supplied value is less than 0
     * @throws \OverflowException When the supplied value is greater than 65535
     */
    public function setValue($value)
    {
        $value = (int) $value;
        if ($value < 0) {
            throw new \UnderflowException('Short integer value must be in the range 0 - 65535');
        } else {
            if ($value > 0xffff) {
                throw new \OverflowException('Short integer value must be in the range 0 - 65535');
            }
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a generic binary data string
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a generic binary data string
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Anything extends Type
{
    /**
     * @var string
     */
    protected $value = '';
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is outside the valid length range 0 - 65535
     */
    public function setValue($value)
    {
        $value = (string) $value;
        if (\strlen($value) > 65535) {
            throw new \UnexpectedValueException('Untyped string length must be in the range 0 - 65535');
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a 32-bit unsigned integer
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a 32-bit unsigned integer
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Long extends Type
{
    /**
     * @var int
     */
    protected $value = 0;
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnderflowException When the supplied value is less than 0
     * @throws \OverflowException When the supplied value is greater than 4294967296
     */
    public function setValue($value)
    {
        $value = (int) $value;
        if ($value < 0) {
            throw new \UnderflowException('Long integer value must be in the range 0 - 4294967296');
        } else {
            if ($value > 0xffffffff) {
                throw new \OverflowException('Long integer value must be in the range 0 - 4294967296');
            }
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a fully qualified domain name
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a fully qualified domain name
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class DomainName extends Type
{
    const FLAG_NO_COMPRESSION = 0x80000000;
    /**
     * @var string
     */
    protected $value = '';
    /**
     * @var string[] The value as a list of labels
     */
    private $labels = [];
    /**
     * Constructor
     *
     * @param (string | string[]) $value
     * @throws \UnexpectedValueException When the supplied value is not a valid domain name
     */
    public function __construct($value = null)
    {
        if (\is_array($value)) {
            $this->setLabels($value);
        } else {
            parent::__construct($value);
        }
    }
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is not a valid domain name
     */
    public function setValue($value)
    {
        $this->setLabels(\explode('.', (string) $value));
    }
    /**
     * Get the domain name labels
     *
     * @param bool $tldFirst Whether to return the label list ordered with the TLD label first
     * @return string[]
     */
    public function getLabels($tldFirst = false) : array
    {
        return $tldFirst ? \array_reverse($this->labels) : $this->labels;
    }
    /**
     * Set the domain name labels
     *
     * @param string[] $labels The new label list
     * @param bool $tldFirst Whether the supplied label list is ordered with the TLD label first
     * @throws \UnexpectedValueException When the supplied label list is not a valid domain name
     */
    public function setLabels(array $labels, $tldFirst = false)
    {
        if (!$labels) {
            $this->labels = [];
            $this->value = '';
            return;
        }
        $length = $count = 0;
        foreach ($labels as &$label) {
            $label = \LibDNS\normalize_name($label);
            $labelLength = \strlen($label);
            if ($labelLength > 63) {
                throw new \InvalidArgumentException('Label list is not a valid domain name: Label ' . $label . ' length exceeds 63 byte limit');
            }
            $length += $labelLength + 1;
            $count++;
        }
        $tld = $tldFirst ? $labels[0] : $labels[$count - 1];
        if ($tld === '') {
            $length--;
        }
        if ($length + 1 > 255) {
            throw new \InvalidArgumentException('Label list is not a valid domain name: Total length exceeds 255 byte limit');
        }
        $this->labels = $tldFirst ? \array_reverse($labels) : $labels;
        $this->value = \implode('.', $this->labels);
    }
}<?php

declare (strict_types=1);
/**
 * Builds Types from type definitions
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Builds Types from type definitions
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeBuilder
{
    /**
     * @var \LibDNS\Records\Types\TypeFactory
     */
    private $typeFactory;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\Types\TypeFactory $typeFactory
     */
    public function __construct(TypeFactory $typeFactory)
    {
        $this->typeFactory = $typeFactory;
    }
    /**
     * Build a new Type object corresponding to a resource record type
     *
     * @param int $type Data type, can be indicated using the Types enum
     * @return \LibDNS\Records\Types\Type
     */
    public function build(int $type) : Type
    {
        static $typeMap = [Types::ANYTHING => 'createAnything', Types::BITMAP => 'createBitMap', Types::CHAR => 'createChar', Types::CHARACTER_STRING => 'createCharacterString', Types::DOMAIN_NAME => 'createDomainName', Types::IPV4_ADDRESS => 'createIPv4Address', Types::IPV6_ADDRESS => 'createIPv6Address', Types::LONG => 'createLong', Types::SHORT => 'createShort'];
        if (!isset($typeMap[$type])) {
            throw new \InvalidArgumentException('Invalid Type identifier ' . $type);
        }
        return $this->typeFactory->{$typeMap[$type]}();
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible resource QTYPE values
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

/**
 * Enumeration of possible resource QTYPE values
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class ResourceQTypes extends ResourceTypes
{
    const AXFR = 252;
    const MAILB = 253;
    const MAILA = 254;
    const ALL = 255;
}<?php

declare (strict_types=1);
/**
 * Builds RData objects from a type definition
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\TypeDefinitions\TypeDefinition;
use LibDNS\Records\Types\TypeBuilder;
/**
 * Creates RData objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RDataBuilder
{
    /**
     * @var \LibDNS\Records\RDataFactory
     */
    private $rDataFactory;
    /**
     * @var \LibDNS\Records\Types\TypeBuilder
     */
    private $typeBuilder;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\RDataFactory $rDataFactory
     * @param \LibDNS\Records\Types\TypeBuilder $typeBuilder
     */
    public function __construct(RDataFactory $rDataFactory, TypeBuilder $typeBuilder)
    {
        $this->rDataFactory = $rDataFactory;
        $this->typeBuilder = $typeBuilder;
    }
    /**
     * Create a new RData object
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinition $typeDefinition
     * @return \LibDNS\Records\RData
     */
    public function build(TypeDefinition $typeDefinition) : RData
    {
        $rData = $this->rDataFactory->create($typeDefinition);
        foreach ($typeDefinition as $index => $type) {
            $rData->setField($index, $this->typeBuilder->build($type->getType()));
        }
        return $rData;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a DNS question record
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeFactory;
/**
 * Represents a DNS question record
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Question extends Record
{
    /**
     * Constructor
     *
     * @param \LibDNS\Records\Types\TypeFactory $typeFactory
     * @param int $type Resource type being requested, can be indicated using the ResourceQTypes enum
     */
    public function __construct(TypeFactory $typeFactory, int $type)
    {
        $this->typeFactory = $typeFactory;
        $this->type = $type;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a DNS record
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\DomainName;
/**
 * Represents a DNS record
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class Record
{
    /**
     * @var \LibDNS\Records\Types\TypeFactory
     */
    protected $typeFactory;
    /**
     * @var \LibDNS\Records\Types\DomainName
     */
    protected $name;
    /**
     * @var int
     */
    protected $type;
    /**
     * @var int
     */
    protected $class = ResourceClasses::IN;
    /**
     * Get the value of the record name field
     *
     * @return \LibDNS\Records\Types\DomainName
     */
    public function getName() : DomainName
    {
        return $this->name;
    }
    /**
     * Set the value of the record name field
     *
     * @param (string | \LibDNS\Records\Types\DomainName) $name
     * @throws \UnexpectedValueException When the supplied value is not a valid domain name
     */
    public function setName($name)
    {
        if (!$name instanceof DomainName) {
            $name = $this->typeFactory->createDomainName((string) $name);
        }
        $this->name = $name;
    }
    /**
     * Get the value of the record type field
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     * Get the value of the record class field
     *
     * @return int
     */
    public function getClass() : int
    {
        return $this->class;
    }
    /**
     * Set the value of the record class field
     *
     * @param int $class The new value, can be indicated using the ResourceClasses/ResourceQClasses enums
     * @throws \RangeException When the supplied value is outside the valid range 0 - 65535
     */
    public function setClass(int $class)
    {
        if ($class < 0 || $class > 65535) {
            throw new \RangeException('Record class must be in the range 0 - 65535');
        }
        $this->class = $class;
    }
}<?php

declare (strict_types=1);
/**
 * Creates Packet objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Packets;

/**
 * Creates Packet objects
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class PacketFactory
{
    /**
     * Create a new Packet object
     *
     * @param string $data
     * @return \LibDNS\Packets\Packet
     */
    public function create(string $data = '') : Packet
    {
        return new Packet($data);
    }
}<?php

declare (strict_types=1);
/**
 * Represents a raw network data packet
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Packets;

/**
 * Represents a raw network data packet
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Packet
{
    /**
     * @var string
     */
    private $data;
    /**
     * @var int Data length
     */
    private $length;
    /**
     * @var int Read pointer
     */
    private $pointer = 0;
    /**
     * Constructor
     *
     * @param string $data The initial packet raw data
     */
    public function __construct(string $data = '')
    {
        $this->data = $data;
        $this->length = \strlen($this->data);
    }
    /**
     * Read bytes from the packet data
     *
     * @param int $length The number of bytes to read
     * @return string
     * @throws \OutOfBoundsException When the pointer position is invalid or the supplied length is negative
     */
    public function read(int $length = null) : string
    {
        if ($this->pointer > $this->length) {
            throw new \OutOfBoundsException('Pointer position invalid');
        }
        if ($length === null) {
            $result = \Phabel\Target\Php80\Polyfill::substr($this->data, $this->pointer);
            $this->pointer = $this->length;
        } else {
            if ($length < 0) {
                throw new \OutOfBoundsException('Length must be a positive integer');
            }
            $result = \Phabel\Target\Php80\Polyfill::substr($this->data, $this->pointer, $length);
            $this->pointer += $length;
        }
        return $result;
    }
    /**
     * Append data to the packet
     *
     * @param string $data The data to append
     * @return int The number of bytes written
     */
    public function write(string $data) : int
    {
        $length = \strlen($data);
        $this->data .= $data;
        $this->length += $length;
        return $length;
    }
    /**
     * Reset the read pointer
     */
    public function reset()
    {
        $this->pointer = 0;
    }
    /**
     * Get the pointer index
     *
     * @return int
     */
    public function getPointer() : int
    {
        return $this->pointer;
    }
    /**
     * Get the data length
     *
     * @return int
     */
    public function getLength() : int
    {
        return $this->length;
    }
    /**
     * Get the number of remaining bytes from the pointer position
     *
     * @return int
     */
    public function getBytesRemaining() : int
    {
        return $this->length - $this->pointer;
    }
}<?php

declare (strict_types=1);
/**
 * Maintains a list of the relationships between domain name labels and the first point at
 * which they appear in a packet
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Packets;

/**
 * Creates Packet objects
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class LabelRegistry
{
    /**
     * @var int[] Map of labels to indexes
     */
    private $labels = [];
    /**
     * @var string[][] Map of indexes to labels
     */
    private $indexes = [];
    /**
     * Register a new relationship
     *
     * @param (string | string[]) $labels
     * @param int $index
     */
    public function register($labels, int $index)
    {
        if (\is_array($labels)) {
            $labelsArr = $labels;
            $labelsStr = \implode('.', $labels);
        } else {
            $labelsArr = \explode('.', $labels);
            $labelsStr = (string) $labels;
        }
        if (!isset($this->labels[$labelsStr]) || $index < $this->labels[$labelsStr]) {
            $this->labels[$labelsStr] = $index;
        }
        $this->indexes[$index] = $labelsArr;
    }
    /**
     * Lookup the index of a label
     *
     * @param string $label
     * @return (int | null)
     */
    public function lookupIndex(string $label)
    {
        return $this->labels[$label] ?? null;
    }
    /**
     * Lookup the label at an index
     *
     * @param int $index
     * @return (string[] | null)
     */
    public function lookupLabel(int $index)
    {
        return $this->indexes[$index] ?? null;
    }
}<?php

/**
 * This file was automatically generated by autoload_generator.php
 *
 * Do not edit this file directly
 */
\Phabel\Target\Php80\Polyfill::spl_autoload_register(function ($className) {
    static $classMap;
    if (!isset($classMap)) {
        $classMap = ['libdns\\decoder\\decoder' => __DIR__ . '/../src/Decoder/Decoder.php', 'libdns\\decoder\\decoderfactory' => __DIR__ . '/../src/Decoder/DecoderFactory.php', 'libdns\\decoder\\decodingcontext' => __DIR__ . '/../src/Decoder/DecodingContext.php', 'libdns\\decoder\\decodingcontextfactory' => __DIR__ . '/../src/Decoder/DecodingContextFactory.php', 'libdns\\encoder\\encoder' => __DIR__ . '/../src/Encoder/Encoder.php', 'libdns\\encoder\\encoderfactory' => __DIR__ . '/../src/Encoder/EncoderFactory.php', 'libdns\\encoder\\encodingcontext' => __DIR__ . '/../src/Encoder/EncodingContext.php', 'libdns\\encoder\\encodingcontextfactory' => __DIR__ . '/../src/Encoder/EncodingContextFactory.php', 'libdns\\enumeration' => __DIR__ . '/../src/Enumeration.php', 'libdns\\messages\\message' => __DIR__ . '/../src/Messages/Message.php', 'libdns\\messages\\messagefactory' => __DIR__ . '/../src/Messages/MessageFactory.php', 'libdns\\messages\\messageopcodes' => __DIR__ . '/../src/Messages/MessageOpCodes.php', 'libdns\\messages\\messageresponsecodes' => __DIR__ . '/../src/Messages/MessageResponseCodes.php', 'libdns\\messages\\messagetypes' => __DIR__ . '/../src/Messages/MessageTypes.php', 'libdns\\packets\\labelregistry' => __DIR__ . '/../src/Packets/LabelRegistry.php', 'libdns\\packets\\packet' => __DIR__ . '/../src/Packets/Packet.php', 'libdns\\packets\\packetfactory' => __DIR__ . '/../src/Packets/PacketFactory.php', 'libdns\\records\\question' => __DIR__ . '/../src/Records/Question.php', 'libdns\\records\\questionfactory' => __DIR__ . '/../src/Records/QuestionFactory.php', 'libdns\\records\\rdata' => __DIR__ . '/../src/Records/RData.php', 'libdns\\records\\rdatabuilder' => __DIR__ . '/../src/Records/RDataBuilder.php', 'libdns\\records\\rdatafactory' => __DIR__ . '/../src/Records/RDataFactory.php', 'libdns\\records\\record' => __DIR__ . '/../src/Records/Record.php', 'libdns\\records\\recordcollection' => __DIR__ . '/../src/Records/RecordCollection.php', 'libdns\\records\\recordcollectionfactory' => __DIR__ . '/../src/Records/RecordCollectionFactory.php', 'libdns\\records\\recordtypes' => __DIR__ . '/../src/Records/RecordTypes.php', 'libdns\\records\\resource' => __DIR__ . '/../src/Records/Resource.php', 'libdns\\records\\resourcebuilder' => __DIR__ . '/../src/Records/ResourceBuilder.php', 'libdns\\records\\resourcebuilderfactory' => __DIR__ . '/../src/Records/ResourceBuilderFactory.php', 'libdns\\records\\resourceclasses' => __DIR__ . '/../src/Records/ResourceClasses.php', 'libdns\\records\\resourcefactory' => __DIR__ . '/../src/Records/ResourceFactory.php', 'libdns\\records\\resourceqclasses' => __DIR__ . '/../src/Records/ResourceQClasses.php', 'libdns\\records\\resourceqtypes' => __DIR__ . '/../src/Records/ResourceQTypes.php', 'libdns\\records\\resourcetypes' => __DIR__ . '/../src/Records/ResourceTypes.php', 'libdns\\records\\typedefinitions\\fielddefinition' => __DIR__ . '/../src/Records/TypeDefinitions/FieldDefinition.php', 'libdns\\records\\typedefinitions\\fielddefinitionfactory' => __DIR__ . '/../src/Records/TypeDefinitions/FieldDefinitionFactory.php', 'libdns\\records\\typedefinitions\\typedefinition' => __DIR__ . '/../src/Records/TypeDefinitions/TypeDefinition.php', 'libdns\\records\\typedefinitions\\typedefinitionfactory' => __DIR__ . '/../src/Records/TypeDefinitions/TypeDefinitionFactory.php', 'libdns\\records\\typedefinitions\\typedefinitionmanager' => __DIR__ . '/../src/Records/TypeDefinitions/TypeDefinitionManager.php', 'libdns\\records\\typedefinitions\\typedefinitionmanagerfactory' => __DIR__ . '/../src/Records/TypeDefinitions/TypeDefinitionManagerFactory.php', 'libdns\\records\\types\\anything' => __DIR__ . '/../src/Records/Types/Anything.php', 'libdns\\records\\types\\bitmap' => __DIR__ . '/../src/Records/Types/BitMap.php', 'libdns\\records\\types\\char' => __DIR__ . '/../src/Records/Types/Char.php', 'libdns\\records\\types\\characterstring' => __DIR__ . '/../src/Records/Types/CharacterString.php', 'libdns\\records\\types\\domainname' => __DIR__ . '/../src/Records/Types/DomainName.php', 'libdns\\records\\types\\ipv4address' => __DIR__ . '/../src/Records/Types/IPv4Address.php', 'libdns\\records\\types\\ipv6address' => __DIR__ . '/../src/Records/Types/IPv6Address.php', 'libdns\\records\\types\\long' => __DIR__ . '/../src/Records/Types/Long.php', 'libdns\\records\\types\\short' => __DIR__ . '/../src/Records/Types/Short.php', 'libdns\\records\\types\\type' => __DIR__ . '/../src/Records/Types/Type.php', 'libdns\\records\\types\\typebuilder' => __DIR__ . '/../src/Records/Types/TypeBuilder.php', 'libdns\\records\\types\\typefactory' => __DIR__ . '/../src/Records/Types/TypeFactory.php', 'libdns\\records\\types\\types' => __DIR__ . '/../src/Records/Types/Types.php'];
    }
    $className = strtolower($className);
    if (isset($classMap[$className])) {
        /** @noinspection PhpIncludeInspection */
        require $classMap[$className];
    }
});<?php

/**
 * Makes a simple A record lookup query and outputs the results
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Examples
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 1.0.0
 */
namespace LibDNS\Examples;

use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\ResourceQTypes;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Decoder\DecoderFactory;
// Config
$queryName = 'faÃŸ.de';
$serverIP = '8.8.8.8';
$requestTimeout = 3;
require __DIR__ . '/autoload.php';
// Create question record
$question = (new QuestionFactory())->create(ResourceQTypes::A);
$question->setName($queryName);
// Create request message
$request = (new MessageFactory())->create(MessageTypes::QUERY);
$request->getQuestionRecords()->add($question);
$request->isRecursionDesired(true);
// Encode request message
$encoder = (new EncoderFactory())->create();
$requestPacket = $encoder->encode($request);
echo "\n" . $queryName . ":\n";
// Send request
$socket = stream_socket_client("udp://{$serverIP}:53");
stream_socket_sendto($socket, $requestPacket);
$r = [$socket];
$w = $e = [];
if (!stream_select($r, $w, $e, $requestTimeout)) {
    echo "    Request timeout.\n";
    exit;
}
// Decode response message
$decoder = (new DecoderFactory())->create();
$responsePacket = fread($socket, 512);
$response = $decoder->decode($responsePacket);
// Handle response
if ($response->getResponseCode() !== 0) {
    echo "    Server returned error code " . $response->getResponseCode() . ".\n";
    exit;
}
$answers = $response->getAnswerRecords();
if (count($answers)) {
    foreach ($response->getAnswerRecords() as $record) {
        /** @var \LibDNS\Records\Resource $record */
        echo "    " . $record->getData() . "\n";
    }
} else {
    echo "    Not found.\n";
}<?php

/**
 * Makes a simple A record lookup query and outputs the results
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Examples
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 1.0.0
 */
namespace LibDNS\Examples;

use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\ResourceTypes;
use LibDNS\Records\ResourceQTypes;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionManagerFactory;
// Config
$queryName = 'google.com';
$serverIP = '8.8.8.8';
$requestTimeout = 3;
require __DIR__ . '/autoload.php';
// Create question record
$question = (new QuestionFactory())->create(ResourceQTypes::SOA);
$question->setName($queryName);
// Create request message
$request = (new MessageFactory())->create(MessageTypes::QUERY);
$request->getQuestionRecords()->add($question);
$request->isRecursionDesired(true);
// Encode request message
$encoder = (new EncoderFactory())->create();
$requestPacket = $encoder->encode($request);
echo "\n" . $queryName . ":\n";
// Send request
$socket = stream_socket_client("udp://{$serverIP}:53");
stream_socket_sendto($socket, $requestPacket);
$r = [$socket];
$w = $e = [];
if (!stream_select($r, $w, $e, $requestTimeout)) {
    echo "    Request timeout.\n";
    exit;
}
// Create type definition manager for custom manipulation
$typeDefs = (new TypeDefinitionManagerFactory())->create();
$typeDefs->getTypeDefinition(ResourceTypes::SOA)->setToStringFunction(function ($mname, $rname, $serial, $refresh, $retry, $expire, $minimum) {
    return <<<DATA
{
    Primary Name Server : {$mname}
    Responsible Mail    : {$rname}
    Serial              : {$serial}
    Refresh             : {$refresh}
    Retry               : {$retry}
    Expire              : {$expire}
    Default TTL         : {$minimum}
}
DATA;
});
// Decode response message
$decoder = (new DecoderFactory())->create($typeDefs);
$responsePacket = fread($socket, 512);
$response = $decoder->decode($responsePacket);
// Handle response
if ($response->getResponseCode() !== 0) {
    echo "    Server returned error code " . $response->getResponseCode() . ".\n";
    exit;
}
$answers = $response->getAnswerRecords();
if (count($answers)) {
    foreach ($response->getAnswerRecords() as $record) {
        /** @var \LibDNS\Records\Resource $record */
        echo "    " . $record->getData() . "\n";
    }
} else {
    echo "    Not found.\n";
}<?php

/**
 * Generates a class-map based autoloader file for the examples directory
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Tools
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 1.0.0
 */
namespace LibDNS\Tools;

use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
use FilesystemIterator;
\Phabel\Target\Php80\Polyfill::error_reporting(0);
ini_set('display_errors', 0);
if (!isset($argv[1])) {
    $srcDir = getcwd();
} else {
    if (in_array(strtolower($argv[1]), ['--help', '?', '/?'])) {
        exit("Syntax: " . __FILE__ . " [source directory]\n");
    } else {
        if (!is_dir($srcDir = $argv[1])) {
            exit("Invalid source directory\n\nSyntax: " . __FILE__ . " [source directory]\n");
        }
    }
}
$srcDir = str_replace('\\', '/', $srcDir);
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($srcDir, FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS));
$items = [];
$stripLength = strlen($srcDir) + 1;
$maxLength = 0;
foreach ($iterator as $item) {
    if ($item->isFile() && $item->getFilename() !== 'autoload.php' && strtolower($item->getExtension()) === 'php') {
        $classPath = \Phabel\Target\Php80\Polyfill::substr($item->getPath() . '\\' . $item->getBasename('.' . $item->getExtension()), $stripLength);
        $lookupName = strtolower(str_replace('/', '\\', $classPath));
        $loadPath = "__DIR__ . '/{$srcDir}/" . str_replace('\\', '/', $classPath) . ".php'";
        $length = strlen($classPath);
        if ($length > $maxLength) {
            $maxLength = $length;
        }
        $items[$lookupName] = $loadPath;
    }
}
unset($iterator);
$output = <<<'PHP'
<?php
/**
 * This file was automatically generated by autoload_generator.php
 *
 * Do not edit this file directly
 */

spl_autoload_register(function($className) {
    static $classMap;
    if (!isset($classMap)) {
        $classMap = [
PHP;
$maxLength += 2;
foreach ($items as $lookupName => $loadPath) {
    $output .= "\n            " . str_pad("'" . $lookupName . "'", $maxLength, ' ', STR_PAD_RIGHT) . " => {$loadPath},";
}
$output .= <<<'PHP'

        ];
    }

    $className = strtolower($className);
    if (isset($classMap[$className])) {
        /** @noinspection PhpIncludeInspection */
        require $classMap[$className];
    }
});

PHP;
file_put_contents(getcwd() . '/autoload.php', $output);{
    "name": "daverandom/libdns",
    "description": "DNS protocol implementation written in pure PHP",
    "license": "MIT",
    "keywords": ["dns"],
    "require": {
        "php": ">=7.0",
        "ext-ctype": "*"
    },
    "autoload": {
        "psr-4": {
            "LibDNS\\": "src/"
        },
        "files": ["src/functions.php"]
    },
    "support": {
        "issues": "https://github.com/DaveRandom/LibDNS/issues"
    },
    "suggest": {
        "ext-intl": "Required for IDN support"
    }
}
<?php

#[Attribute(Attribute::TARGET_CLASS)]
final class Attribute
{
    public const TARGET_CLASS = 1;
    public const TARGET_FUNCTION = 2;
    public const TARGET_METHOD = 4;
    public const TARGET_PROPERTY = 8;
    public const TARGET_CLASS_CONSTANT = 16;
    public const TARGET_PARAMETER = 32;
    public const TARGET_ALL = 63;
    public const IS_REPEATABLE = 64;
    /** @var int */
    public $flags;
    /**
     *
     */
    public function __construct(int $flags = self::TARGET_ALL)
    {
        $this->flags = $flags;
    }
}<?php

class UnhandledMatchError extends Error
{
}<?php

if (\PHP_VERSION_ID < 80000) {
    interface Stringable
    {
        /**
         * @return string
         */
        public function __toString();
    }
}<?php

class ValueError extends Error
{
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php80;

/**
 * @author Ion Bazan <ion.bazan@gmail.com>
 * @author Nico Oelgart <nicoswd@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Php80
{
    /**
     *
     */
    public static function fdiv(float $dividend, float $divisor) : float
    {
        return @($dividend / $divisor);
    }
    /**
     *
     */
    public static function get_debug_type($value) : string
    {
        switch (true) {
            case null === $value:
                return 'null';
            case \is_bool($value):
                return 'bool';
            case \is_string($value):
                return 'string';
            case \is_array($value):
                return 'array';
            case \is_int($value):
                return 'int';
            case \is_float($value):
                return 'float';
            case \is_object($value):
                break;
            case $value instanceof \__PHP_Incomplete_Class:
                return '__PHP_Incomplete_Class';
            default:
                if (null === ($type = @get_resource_type($value))) {
                    return 'unknown';
                }
                if ('Unknown' === $type) {
                    $type = 'closed';
                }
                return "resource ({$type})";
        }
        $class = \get_class($value);
        if (false === strpos($class, '@')) {
            return $class;
        }
        return ((get_parent_class($class) ?: key(class_implements($class))) ?: 'class') . '@anonymous';
    }
    /**
     *
     */
    public static function get_resource_id($res) : int
    {
        if (!\is_resource($res) && null === @get_resource_type($res)) {
            throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res)));
        }
        return (int) $res;
    }
    /**
     *
     */
    public static function preg_last_error_msg() : string
    {
        switch (preg_last_error()) {
            case \PREG_INTERNAL_ERROR:
                return 'Internal error';
            case \PREG_BAD_UTF8_ERROR:
                return 'Malformed UTF-8 characters, possibly incorrectly encoded';
            case \PREG_BAD_UTF8_OFFSET_ERROR:
                return 'The offset did not correspond to the beginning of a valid UTF-8 code point';
            case \PREG_BACKTRACK_LIMIT_ERROR:
                return 'Backtrack limit exhausted';
            case \PREG_RECURSION_LIMIT_ERROR:
                return 'Recursion limit exhausted';
            case \PREG_JIT_STACKLIMIT_ERROR:
                return 'JIT stack limit exhausted';
            case \PREG_NO_ERROR:
                return 'No error';
            default:
                return 'Unknown error';
        }
    }
    /**
     *
     */
    public static function str_contains(string $haystack, string $needle) : bool
    {
        return '' === $needle || false !== strpos($haystack, $needle);
    }
    /**
     *
     */
    public static function str_starts_with(string $haystack, string $needle) : bool
    {
        return 0 === strncmp($haystack, $needle, \strlen($needle));
    }
    /**
     *
     */
    public static function str_ends_with(string $haystack, string $needle) : bool
    {
        return '' === $needle || '' !== $haystack && 0 === \Phabel\Target\Php80\Polyfill::substr_compare($haystack, $needle, -\strlen($needle));
    }
}{
    "name": "symfony/polyfill-php80",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
    "keywords": ["polyfill", "shim", "compatibility", "portable"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Ion Bazan",
            "email": "ion.bazan@gmail.com"
        },
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Php80\\": "" },
        "files": [ "bootstrap.php" ],
        "classmap": [ "Resources/stubs" ]
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Php80 as p;
if (\PHP_VERSION_ID >= 80000) {
    return;
}
if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) {
    define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN);
}
if (!function_exists('fdiv')) {
    /**
     *
     */
    function fdiv(float $num1, float $num2) : float
    {
        return p\Php80::fdiv($num1, $num2);
    }
}
if (!function_exists('preg_last_error_msg')) {
    /**
     *
     */
    function preg_last_error_msg() : string
    {
        return p\Php80::preg_last_error_msg();
    }
}
if (!function_exists('str_contains')) {
    /**
     *
     */
    function str_contains(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_contains($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('str_starts_with')) {
    /**
     *
     */
    function str_starts_with(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_starts_with($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('str_ends_with')) {
    /**
     *
     */
    function str_ends_with(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_ends_with($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('get_debug_type')) {
    /**
     *
     */
    function get_debug_type($value) : string
    {
        return p\Php80::get_debug_type($value);
    }
}
if (!function_exists('get_resource_id')) {
    /**
     *
     */
    function get_resource_id($resource) : int
    {
        return p\Php80::get_resource_id($resource);
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Mbstring as p;
if (!function_exists('mb_convert_encoding')) {
    /**
     * @param (array | string | null) $string
     * @param (array | string | null) $from_encoding
     * @return (array | string | false)
     */
    function mb_convert_encoding($string, ?string $to_encoding, $from_encoding = null)
    {
        if (!\is_null($string)) {
            if (!\is_string($string)) {
                if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                    if (!\is_array($string)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $string = (string) $string;
                }
            }
        }
        if (!(\is_null($from_encoding) || \is_null($from_encoding))) {
            if (!\is_string($from_encoding)) {
                if (!(\is_string($from_encoding) || \is_object($from_encoding) && \method_exists($from_encoding, '__toString') || (\is_bool($from_encoding) || \is_numeric($from_encoding)))) {
                    if (!\is_array($from_encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #3 ($from_encoding) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($from_encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $from_encoding = (string) $from_encoding;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    if (!\is_array($phabelReturn)) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_decode_mimeheader')) {
    /**
     *
     */
    function mb_decode_mimeheader(?string $string) : string
    {
        return p\Mbstring::mb_decode_mimeheader((string) $string);
    }
}
if (!function_exists('mb_encode_mimeheader')) {
    /**
     *
     */
    function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0) : string
    {
        return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent);
    }
}
if (!function_exists('mb_decode_numericentity')) {
    /**
     *
     */
    function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding);
    }
}
if (!function_exists('mb_encode_numericentity')) {
    /**
     *
     */
    function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false) : string
    {
        return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex);
    }
}
if (!function_exists('mb_convert_case')) {
    /**
     *
     */
    function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding);
    }
}
if (!function_exists('mb_internal_encoding')) {
    /**
     * @return (string | bool)
     */
    function mb_internal_encoding(?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_internal_encoding($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_language')) {
    /**
     * @return (string | bool)
     */
    function mb_language(?string $language = null)
    {
        $phabelReturn = p\Mbstring::mb_language($language);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_list_encodings')) {
    /**
     *
     */
    function mb_list_encodings() : array
    {
        return p\Mbstring::mb_list_encodings();
    }
}
if (!function_exists('mb_encoding_aliases')) {
    /**
     *
     */
    function mb_encoding_aliases(?string $encoding) : array
    {
        return p\Mbstring::mb_encoding_aliases((string) $encoding);
    }
}
if (!function_exists('mb_check_encoding')) {
    /**
     * @param (array | string | null) $value
     */
    function mb_check_encoding($value = null, ?string $encoding = null) : bool
    {
        if (!(\is_null($value) || \is_null($value))) {
            if (!\is_string($value)) {
                if (!(\is_string($value) || \is_object($value) && \method_exists($value, '__toString') || (\is_bool($value) || \is_numeric($value)))) {
                    if (!\is_array($value)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($value) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $value = (string) $value;
                }
            }
        }
        return p\Mbstring::mb_check_encoding($value, $encoding);
    }
}
if (!function_exists('mb_detect_encoding')) {
    /**
     * @param (array | string | null) $encodings
     * @return (string | false)
     */
    function mb_detect_encoding(?string $string, $encodings = null, ?bool $strict = false)
    {
        if (!(\is_null($encodings) || \is_null($encodings))) {
            if (!\is_string($encodings)) {
                if (!(\is_string($encodings) || \is_object($encodings) && \method_exists($encodings, '__toString') || (\is_bool($encodings) || \is_numeric($encodings)))) {
                    if (!\is_array($encodings)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #2 ($encodings) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($encodings) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $encodings = (string) $encodings;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_detect_order')) {
    /**
     * @param (array | string | null) $encoding
     * @return (array | bool)
     */
    function mb_detect_order($encoding = null)
    {
        if (!(\is_null($encoding) || \is_null($encoding))) {
            if (!\is_string($encoding)) {
                if (!(\is_string($encoding) || \is_object($encoding) && \method_exists($encoding, '__toString') || (\is_bool($encoding) || \is_numeric($encoding)))) {
                    if (!\is_array($encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($encoding) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $encoding = (string) $encoding;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_detect_order($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_array($phabelReturn)) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type array|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_parse_str')) {
    /**
     *
     */
    function mb_parse_str(?string $string, &$result = []) : bool
    {
        parse_str((string) $string, $result);
        return (bool) $result;
    }
}
if (!function_exists('mb_strlen')) {
    /**
     *
     */
    function mb_strlen(?string $string, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_strlen((string) $string, $encoding);
    }
}
if (!function_exists('mb_strpos')) {
    /**
     * @return (int | false)
     */
    function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strtolower')) {
    /**
     *
     */
    function mb_strtolower(?string $string, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_strtolower((string) $string, $encoding);
    }
}
if (!function_exists('mb_strtoupper')) {
    /**
     *
     */
    function mb_strtoupper(?string $string, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_strtoupper((string) $string, $encoding);
    }
}
if (!function_exists('mb_substitute_character')) {
    /**
     * @param (string | int | null) $substitute_character
     * @return (string | int | bool)
     */
    function mb_substitute_character($substitute_character = null)
    {
        if (!(\is_null($substitute_character) || \is_null($substitute_character))) {
            if (!\is_int($substitute_character)) {
                if (!(\is_bool($substitute_character) || \is_numeric($substitute_character))) {
                    if (!\is_string($substitute_character)) {
                        if (!(\is_string($substitute_character) || \is_object($substitute_character) && \method_exists($substitute_character, '__toString') || (\is_bool($substitute_character) || \is_numeric($substitute_character)))) {
                            throw new \TypeError(__METHOD__ . '(): Argument #1 ($substitute_character) must be of type ?string|int|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($substitute_character) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                        } else {
                            $substitute_character = (string) $substitute_character;
                        }
                    }
                } else {
                    $substitute_character = (int) $substitute_character;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_substitute_character($substitute_character);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        if (!\is_string($phabelReturn)) {
                            if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                                throw new \TypeError(__METHOD__ . '(): Return value must be of type string|int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                            } else {
                                $phabelReturn = (string) $phabelReturn;
                            }
                        }
                    } else {
                        $phabelReturn = (int) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_substr')) {
    /**
     *
     */
    function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding);
    }
}
if (!function_exists('mb_stripos')) {
    /**
     * @return (int | false)
     */
    function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_stristr')) {
    /**
     * @return (string | false)
     */
    function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrchr')) {
    /**
     * @return (string | false)
     */
    function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrichr')) {
    /**
     * @return (string | false)
     */
    function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strripos')) {
    /**
     * @return (int | false)
     */
    function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrpos')) {
    /**
     * @return (int | false)
     */
    function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strstr')) {
    /**
     * @return (string | false)
     */
    function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_get_info')) {
    /**
     * @return (array | string | int | false)
     */
    function mb_get_info(?string $type = 'all')
    {
        $phabelReturn = p\Mbstring::mb_get_info((string) $type);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    if (!\is_string($phabelReturn)) {
                        if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                            if (!\is_array($phabelReturn)) {
                                throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                            }
                        } else {
                            $phabelReturn = (string) $phabelReturn;
                        }
                    }
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_http_output')) {
    /**
     * @return (string | bool)
     */
    function mb_http_output(?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_http_output($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strwidth')) {
    /**
     *
     */
    function mb_strwidth(?string $string, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_strwidth((string) $string, $encoding);
    }
}
if (!function_exists('mb_substr_count')) {
    /**
     *
     */
    function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding);
    }
}
if (!function_exists('mb_output_handler')) {
    /**
     *
     */
    function mb_output_handler(?string $string, ?int $status) : string
    {
        return p\Mbstring::mb_output_handler((string) $string, (int) $status);
    }
}
if (!function_exists('mb_http_input')) {
    /**
     * @return (array | string | false)
     */
    function mb_http_input(?string $type = null)
    {
        $phabelReturn = p\Mbstring::mb_http_input($type);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    if (!\is_array($phabelReturn)) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_convert_variables')) {
    /**
     * @param (array | string | null) $from_encoding
     * @param mixed $var
     * @param mixed ...$vars
     * @return (string | false)
     */
    function mb_convert_variables(?string $to_encoding, $from_encoding, &$var, &...$vars)
    {
        if (!\is_null($from_encoding)) {
            if (!\is_string($from_encoding)) {
                if (!(\is_string($from_encoding) || \is_object($from_encoding) && \method_exists($from_encoding, '__toString') || (\is_bool($from_encoding) || \is_numeric($from_encoding)))) {
                    if (!\is_array($from_encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #2 ($from_encoding) must be of type array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($from_encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $from_encoding = (string) $from_encoding;
                }
            }
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #3 ($var) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($var) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        foreach ($vars as $phabelVariadicIndex => $phabelVariadic) {
            if (!true) {
                throw new \TypeError(__METHOD__ . '(): Argument #' . (4 + $phabelVariadicIndex) . ' must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($vars) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
        }
        $phabelReturn = p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_ord')) {
    /**
     * @return (int | false)
     */
    function mb_ord(?string $string, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_ord((string) $string, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_chr')) {
    /**
     * @return (string | false)
     */
    function mb_chr(?int $codepoint, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_chr((int) $codepoint, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_scrub')) {
    /**
     *
     */
    function mb_scrub(?string $string, ?string $encoding = null) : string
    {
        $encoding ??= mb_internal_encoding();
        return mb_convert_encoding((string) $string, $encoding, $encoding);
    }
}
if (!function_exists('mb_str_split')) {
    /**
     *
     */
    function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null) : array
    {
        return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding);
    }
}
if (extension_loaded('mbstring')) {
    return;
}
if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}<?php

// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt
return '/(?<![\\x{0027}\\x{002E}\\x{003A}\\x{005E}\\x{0060}\\x{00A8}\\x{00AD}\\x{00AF}\\x{00B4}\\x{00B7}\\x{00B8}\\x{02B0}-\\x{02C1}\\x{02C2}-\\x{02C5}\\x{02C6}-\\x{02D1}\\x{02D2}-\\x{02DF}\\x{02E0}-\\x{02E4}\\x{02E5}-\\x{02EB}\\x{02EC}\\x{02ED}\\x{02EE}\\x{02EF}-\\x{02FF}\\x{0300}-\\x{036F}\\x{0374}\\x{0375}\\x{037A}\\x{0384}-\\x{0385}\\x{0387}\\x{0483}-\\x{0487}\\x{0488}-\\x{0489}\\x{0559}\\x{0591}-\\x{05BD}\\x{05BF}\\x{05C1}-\\x{05C2}\\x{05C4}-\\x{05C5}\\x{05C7}\\x{05F4}\\x{0600}-\\x{0605}\\x{0610}-\\x{061A}\\x{061C}\\x{0640}\\x{064B}-\\x{065F}\\x{0670}\\x{06D6}-\\x{06DC}\\x{06DD}\\x{06DF}-\\x{06E4}\\x{06E5}-\\x{06E6}\\x{06E7}-\\x{06E8}\\x{06EA}-\\x{06ED}\\x{070F}\\x{0711}\\x{0730}-\\x{074A}\\x{07A6}-\\x{07B0}\\x{07EB}-\\x{07F3}\\x{07F4}-\\x{07F5}\\x{07FA}\\x{07FD}\\x{0816}-\\x{0819}\\x{081A}\\x{081B}-\\x{0823}\\x{0824}\\x{0825}-\\x{0827}\\x{0828}\\x{0829}-\\x{082D}\\x{0859}-\\x{085B}\\x{08D3}-\\x{08E1}\\x{08E2}\\x{08E3}-\\x{0902}\\x{093A}\\x{093C}\\x{0941}-\\x{0948}\\x{094D}\\x{0951}-\\x{0957}\\x{0962}-\\x{0963}\\x{0971}\\x{0981}\\x{09BC}\\x{09C1}-\\x{09C4}\\x{09CD}\\x{09E2}-\\x{09E3}\\x{09FE}\\x{0A01}-\\x{0A02}\\x{0A3C}\\x{0A41}-\\x{0A42}\\x{0A47}-\\x{0A48}\\x{0A4B}-\\x{0A4D}\\x{0A51}\\x{0A70}-\\x{0A71}\\x{0A75}\\x{0A81}-\\x{0A82}\\x{0ABC}\\x{0AC1}-\\x{0AC5}\\x{0AC7}-\\x{0AC8}\\x{0ACD}\\x{0AE2}-\\x{0AE3}\\x{0AFA}-\\x{0AFF}\\x{0B01}\\x{0B3C}\\x{0B3F}\\x{0B41}-\\x{0B44}\\x{0B4D}\\x{0B56}\\x{0B62}-\\x{0B63}\\x{0B82}\\x{0BC0}\\x{0BCD}\\x{0C00}\\x{0C04}\\x{0C3E}-\\x{0C40}\\x{0C46}-\\x{0C48}\\x{0C4A}-\\x{0C4D}\\x{0C55}-\\x{0C56}\\x{0C62}-\\x{0C63}\\x{0C81}\\x{0CBC}\\x{0CBF}\\x{0CC6}\\x{0CCC}-\\x{0CCD}\\x{0CE2}-\\x{0CE3}\\x{0D00}-\\x{0D01}\\x{0D3B}-\\x{0D3C}\\x{0D41}-\\x{0D44}\\x{0D4D}\\x{0D62}-\\x{0D63}\\x{0DCA}\\x{0DD2}-\\x{0DD4}\\x{0DD6}\\x{0E31}\\x{0E34}-\\x{0E3A}\\x{0E46}\\x{0E47}-\\x{0E4E}\\x{0EB1}\\x{0EB4}-\\x{0EB9}\\x{0EBB}-\\x{0EBC}\\x{0EC6}\\x{0EC8}-\\x{0ECD}\\x{0F18}-\\x{0F19}\\x{0F35}\\x{0F37}\\x{0F39}\\x{0F71}-\\x{0F7E}\\x{0F80}-\\x{0F84}\\x{0F86}-\\x{0F87}\\x{0F8D}-\\x{0F97}\\x{0F99}-\\x{0FBC}\\x{0FC6}\\x{102D}-\\x{1030}\\x{1032}-\\x{1037}\\x{1039}-\\x{103A}\\x{103D}-\\x{103E}\\x{1058}-\\x{1059}\\x{105E}-\\x{1060}\\x{1071}-\\x{1074}\\x{1082}\\x{1085}-\\x{1086}\\x{108D}\\x{109D}\\x{10FC}\\x{135D}-\\x{135F}\\x{1712}-\\x{1714}\\x{1732}-\\x{1734}\\x{1752}-\\x{1753}\\x{1772}-\\x{1773}\\x{17B4}-\\x{17B5}\\x{17B7}-\\x{17BD}\\x{17C6}\\x{17C9}-\\x{17D3}\\x{17D7}\\x{17DD}\\x{180B}-\\x{180D}\\x{180E}\\x{1843}\\x{1885}-\\x{1886}\\x{18A9}\\x{1920}-\\x{1922}\\x{1927}-\\x{1928}\\x{1932}\\x{1939}-\\x{193B}\\x{1A17}-\\x{1A18}\\x{1A1B}\\x{1A56}\\x{1A58}-\\x{1A5E}\\x{1A60}\\x{1A62}\\x{1A65}-\\x{1A6C}\\x{1A73}-\\x{1A7C}\\x{1A7F}\\x{1AA7}\\x{1AB0}-\\x{1ABD}\\x{1ABE}\\x{1B00}-\\x{1B03}\\x{1B34}\\x{1B36}-\\x{1B3A}\\x{1B3C}\\x{1B42}\\x{1B6B}-\\x{1B73}\\x{1B80}-\\x{1B81}\\x{1BA2}-\\x{1BA5}\\x{1BA8}-\\x{1BA9}\\x{1BAB}-\\x{1BAD}\\x{1BE6}\\x{1BE8}-\\x{1BE9}\\x{1BED}\\x{1BEF}-\\x{1BF1}\\x{1C2C}-\\x{1C33}\\x{1C36}-\\x{1C37}\\x{1C78}-\\x{1C7D}\\x{1CD0}-\\x{1CD2}\\x{1CD4}-\\x{1CE0}\\x{1CE2}-\\x{1CE8}\\x{1CED}\\x{1CF4}\\x{1CF8}-\\x{1CF9}\\x{1D2C}-\\x{1D6A}\\x{1D78}\\x{1D9B}-\\x{1DBF}\\x{1DC0}-\\x{1DF9}\\x{1DFB}-\\x{1DFF}\\x{1FBD}\\x{1FBF}-\\x{1FC1}\\x{1FCD}-\\x{1FCF}\\x{1FDD}-\\x{1FDF}\\x{1FED}-\\x{1FEF}\\x{1FFD}-\\x{1FFE}\\x{200B}-\\x{200F}\\x{2018}\\x{2019}\\x{2024}\\x{2027}\\x{202A}-\\x{202E}\\x{2060}-\\x{2064}\\x{2066}-\\x{206F}\\x{2071}\\x{207F}\\x{2090}-\\x{209C}\\x{20D0}-\\x{20DC}\\x{20DD}-\\x{20E0}\\x{20E1}\\x{20E2}-\\x{20E4}\\x{20E5}-\\x{20F0}\\x{2C7C}-\\x{2C7D}\\x{2CEF}-\\x{2CF1}\\x{2D6F}\\x{2D7F}\\x{2DE0}-\\x{2DFF}\\x{2E2F}\\x{3005}\\x{302A}-\\x{302D}\\x{3031}-\\x{3035}\\x{303B}\\x{3099}-\\x{309A}\\x{309B}-\\x{309C}\\x{309D}-\\x{309E}\\x{30FC}-\\x{30FE}\\x{A015}\\x{A4F8}-\\x{A4FD}\\x{A60C}\\x{A66F}\\x{A670}-\\x{A672}\\x{A674}-\\x{A67D}\\x{A67F}\\x{A69C}-\\x{A69D}\\x{A69E}-\\x{A69F}\\x{A6F0}-\\x{A6F1}\\x{A700}-\\x{A716}\\x{A717}-\\x{A71F}\\x{A720}-\\x{A721}\\x{A770}\\x{A788}\\x{A789}-\\x{A78A}\\x{A7F8}-\\x{A7F9}\\x{A802}\\x{A806}\\x{A80B}\\x{A825}-\\x{A826}\\x{A8C4}-\\x{A8C5}\\x{A8E0}-\\x{A8F1}\\x{A8FF}\\x{A926}-\\x{A92D}\\x{A947}-\\x{A951}\\x{A980}-\\x{A982}\\x{A9B3}\\x{A9B6}-\\x{A9B9}\\x{A9BC}\\x{A9CF}\\x{A9E5}\\x{A9E6}\\x{AA29}-\\x{AA2E}\\x{AA31}-\\x{AA32}\\x{AA35}-\\x{AA36}\\x{AA43}\\x{AA4C}\\x{AA70}\\x{AA7C}\\x{AAB0}\\x{AAB2}-\\x{AAB4}\\x{AAB7}-\\x{AAB8}\\x{AABE}-\\x{AABF}\\x{AAC1}\\x{AADD}\\x{AAEC}-\\x{AAED}\\x{AAF3}-\\x{AAF4}\\x{AAF6}\\x{AB5B}\\x{AB5C}-\\x{AB5F}\\x{ABE5}\\x{ABE8}\\x{ABED}\\x{FB1E}\\x{FBB2}-\\x{FBC1}\\x{FE00}-\\x{FE0F}\\x{FE13}\\x{FE20}-\\x{FE2F}\\x{FE52}\\x{FE55}\\x{FEFF}\\x{FF07}\\x{FF0E}\\x{FF1A}\\x{FF3E}\\x{FF40}\\x{FF70}\\x{FF9E}-\\x{FF9F}\\x{FFE3}\\x{FFF9}-\\x{FFFB}\\x{101FD}\\x{102E0}\\x{10376}-\\x{1037A}\\x{10A01}-\\x{10A03}\\x{10A05}-\\x{10A06}\\x{10A0C}-\\x{10A0F}\\x{10A38}-\\x{10A3A}\\x{10A3F}\\x{10AE5}-\\x{10AE6}\\x{10D24}-\\x{10D27}\\x{10F46}-\\x{10F50}\\x{11001}\\x{11038}-\\x{11046}\\x{1107F}-\\x{11081}\\x{110B3}-\\x{110B6}\\x{110B9}-\\x{110BA}\\x{110BD}\\x{110CD}\\x{11100}-\\x{11102}\\x{11127}-\\x{1112B}\\x{1112D}-\\x{11134}\\x{11173}\\x{11180}-\\x{11181}\\x{111B6}-\\x{111BE}\\x{111C9}-\\x{111CC}\\x{1122F}-\\x{11231}\\x{11234}\\x{11236}-\\x{11237}\\x{1123E}\\x{112DF}\\x{112E3}-\\x{112EA}\\x{11300}-\\x{11301}\\x{1133B}-\\x{1133C}\\x{11340}\\x{11366}-\\x{1136C}\\x{11370}-\\x{11374}\\x{11438}-\\x{1143F}\\x{11442}-\\x{11444}\\x{11446}\\x{1145E}\\x{114B3}-\\x{114B8}\\x{114BA}\\x{114BF}-\\x{114C0}\\x{114C2}-\\x{114C3}\\x{115B2}-\\x{115B5}\\x{115BC}-\\x{115BD}\\x{115BF}-\\x{115C0}\\x{115DC}-\\x{115DD}\\x{11633}-\\x{1163A}\\x{1163D}\\x{1163F}-\\x{11640}\\x{116AB}\\x{116AD}\\x{116B0}-\\x{116B5}\\x{116B7}\\x{1171D}-\\x{1171F}\\x{11722}-\\x{11725}\\x{11727}-\\x{1172B}\\x{1182F}-\\x{11837}\\x{11839}-\\x{1183A}\\x{11A01}-\\x{11A0A}\\x{11A33}-\\x{11A38}\\x{11A3B}-\\x{11A3E}\\x{11A47}\\x{11A51}-\\x{11A56}\\x{11A59}-\\x{11A5B}\\x{11A8A}-\\x{11A96}\\x{11A98}-\\x{11A99}\\x{11C30}-\\x{11C36}\\x{11C38}-\\x{11C3D}\\x{11C3F}\\x{11C92}-\\x{11CA7}\\x{11CAA}-\\x{11CB0}\\x{11CB2}-\\x{11CB3}\\x{11CB5}-\\x{11CB6}\\x{11D31}-\\x{11D36}\\x{11D3A}\\x{11D3C}-\\x{11D3D}\\x{11D3F}-\\x{11D45}\\x{11D47}\\x{11D90}-\\x{11D91}\\x{11D95}\\x{11D97}\\x{11EF3}-\\x{11EF4}\\x{16AF0}-\\x{16AF4}\\x{16B30}-\\x{16B36}\\x{16B40}-\\x{16B43}\\x{16F8F}-\\x{16F92}\\x{16F93}-\\x{16F9F}\\x{16FE0}-\\x{16FE1}\\x{1BC9D}-\\x{1BC9E}\\x{1BCA0}-\\x{1BCA3}\\x{1D167}-\\x{1D169}\\x{1D173}-\\x{1D17A}\\x{1D17B}-\\x{1D182}\\x{1D185}-\\x{1D18B}\\x{1D1AA}-\\x{1D1AD}\\x{1D242}-\\x{1D244}\\x{1DA00}-\\x{1DA36}\\x{1DA3B}-\\x{1DA6C}\\x{1DA75}\\x{1DA84}\\x{1DA9B}-\\x{1DA9F}\\x{1DAA1}-\\x{1DAAF}\\x{1E000}-\\x{1E006}\\x{1E008}-\\x{1E018}\\x{1E01B}-\\x{1E021}\\x{1E023}-\\x{1E024}\\x{1E026}-\\x{1E02A}\\x{1E8D0}-\\x{1E8D6}\\x{1E944}-\\x{1E94A}\\x{1F3FB}-\\x{1F3FF}\\x{E0001}\\x{E0020}-\\x{E007F}\\x{E0100}-\\x{E01EF}])(\\pL)(\\pL*+)/u';<?php

return array('A' => 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e', 'F' => 'f', 'G' => 'g', 'H' => 'h', 'I' => 'i', 'J' => 'j', 'K' => 'k', 'L' => 'l', 'M' => 'm', 'N' => 'n', 'O' => 'o', 'P' => 'p', 'Q' => 'q', 'R' => 'r', 'S' => 's', 'T' => 't', 'U' => 'u', 'V' => 'v', 'W' => 'w', 'X' => 'x', 'Y' => 'y', 'Z' => 'z', 'Ã€' => 'Ã ', 'Ã�' => 'Ã¡', 'Ã‚' => 'Ã¢', 'Ãƒ' => 'Ã£', 'Ã„' => 'Ã¤', 'Ã…' => 'Ã¥', 'Ã†' => 'Ã¦', 'Ã‡' => 'Ã§', 'Ãˆ' => 'Ã¨', 'Ã‰' => 'Ã©', 'ÃŠ' => 'Ãª', 'Ã‹' => 'Ã«', 'ÃŒ' => 'Ã¬', 'Ã�' => 'Ã­', 'ÃŽ' => 'Ã®', 'Ã�' => 'Ã¯', 'Ã�' => 'Ã°', 'Ã‘' => 'Ã±', 'Ã’' => 'Ã²', 'Ã“' => 'Ã³', 'Ã”' => 'Ã´', 'Ã•' => 'Ãµ', 'Ã–' => 'Ã¶', 'Ã˜' => 'Ã¸', 'Ã™' => 'Ã¹', 'Ãš' => 'Ãº', 'Ã›' => 'Ã»', 'Ãœ' => 'Ã¼', 'Ã�' => 'Ã½', 'Ãž' => 'Ã¾', 'Ä€' => 'Ä�', 'Ä‚' => 'Äƒ', 'Ä„' => 'Ä…', 'Ä†' => 'Ä‡', 'Äˆ' => 'Ä‰', 'ÄŠ' => 'Ä‹', 'ÄŒ' => 'Ä�', 'ÄŽ' => 'Ä�', 'Ä�' => 'Ä‘', 'Ä’' => 'Ä“', 'Ä”' => 'Ä•', 'Ä–' => 'Ä—', 'Ä˜' => 'Ä™', 'Äš' => 'Ä›', 'Äœ' => 'Ä�', 'Äž' => 'ÄŸ', 'Ä ' => 'Ä¡', 'Ä¢' => 'Ä£', 'Ä¤' => 'Ä¥', 'Ä¦' => 'Ä§', 'Ä¨' => 'Ä©', 'Äª' => 'Ä«', 'Ä¬' => 'Ä­', 'Ä®' => 'Ä¯', 'Ä°' => 'iÌ‡', 'Ä²' => 'Ä³', 'Ä´' => 'Äµ', 'Ä¶' => 'Ä·', 'Ä¹' => 'Äº', 'Ä»' => 'Ä¼', 'Ä½' => 'Ä¾', 'Ä¿' => 'Å€', 'Å�' => 'Å‚', 'Åƒ' => 'Å„', 'Å…' => 'Å†', 'Å‡' => 'Åˆ', 'ÅŠ' => 'Å‹', 'ÅŒ' => 'Å�', 'ÅŽ' => 'Å�', 'Å�' => 'Å‘', 'Å’' => 'Å“', 'Å”' => 'Å•', 'Å–' => 'Å—', 'Å˜' => 'Å™', 'Åš' => 'Å›', 'Åœ' => 'Å�', 'Åž' => 'ÅŸ', 'Å ' => 'Å¡', 'Å¢' => 'Å£', 'Å¤' => 'Å¥', 'Å¦' => 'Å§', 'Å¨' => 'Å©', 'Åª' => 'Å«', 'Å¬' => 'Å­', 'Å®' => 'Å¯', 'Å°' => 'Å±', 'Å²' => 'Å³', 'Å´' => 'Åµ', 'Å¶' => 'Å·', 'Å¸' => 'Ã¿', 'Å¹' => 'Åº', 'Å»' => 'Å¼', 'Å½' => 'Å¾', 'Æ�' => 'É“', 'Æ‚' => 'Æƒ', 'Æ„' => 'Æ…', 'Æ†' => 'É”', 'Æ‡' => 'Æˆ', 'Æ‰' => 'É–', 'ÆŠ' => 'É—', 'Æ‹' => 'ÆŒ', 'ÆŽ' => 'Ç�', 'Æ�' => 'É™', 'Æ�' => 'É›', 'Æ‘' => 'Æ’', 'Æ“' => 'É ', 'Æ”' => 'É£', 'Æ–' => 'É©', 'Æ—' => 'É¨', 'Æ˜' => 'Æ™', 'Æœ' => 'É¯', 'Æ�' => 'É²', 'ÆŸ' => 'Éµ', 'Æ ' => 'Æ¡', 'Æ¢' => 'Æ£', 'Æ¤' => 'Æ¥', 'Æ¦' => 'Ê€', 'Æ§' => 'Æ¨', 'Æ©' => 'Êƒ', 'Æ¬' => 'Æ­', 'Æ®' => 'Êˆ', 'Æ¯' => 'Æ°', 'Æ±' => 'ÊŠ', 'Æ²' => 'Ê‹', 'Æ³' => 'Æ´', 'Æµ' => 'Æ¶', 'Æ·' => 'Ê’', 'Æ¸' => 'Æ¹', 'Æ¼' => 'Æ½', 'Ç„' => 'Ç†', 'Ç…' => 'Ç†', 'Ç‡' => 'Ç‰', 'Çˆ' => 'Ç‰', 'ÇŠ' => 'ÇŒ', 'Ç‹' => 'ÇŒ', 'Ç�' => 'ÇŽ', 'Ç�' => 'Ç�', 'Ç‘' => 'Ç’', 'Ç“' => 'Ç”', 'Ç•' => 'Ç–', 'Ç—' => 'Ç˜', 'Ç™' => 'Çš', 'Ç›' => 'Çœ', 'Çž' => 'ÇŸ', 'Ç ' => 'Ç¡', 'Ç¢' => 'Ç£', 'Ç¤' => 'Ç¥', 'Ç¦' => 'Ç§', 'Ç¨' => 'Ç©', 'Çª' => 'Ç«', 'Ç¬' => 'Ç­', 'Ç®' => 'Ç¯', 'Ç±' => 'Ç³', 'Ç²' => 'Ç³', 'Ç´' => 'Çµ', 'Ç¶' => 'Æ•', 'Ç·' => 'Æ¿', 'Ç¸' => 'Ç¹', 'Çº' => 'Ç»', 'Ç¼' => 'Ç½', 'Ç¾' => 'Ç¿', 'È€' => 'È�', 'È‚' => 'Èƒ', 'È„' => 'È…', 'È†' => 'È‡', 'Èˆ' => 'È‰', 'ÈŠ' => 'È‹', 'ÈŒ' => 'È�', 'ÈŽ' => 'È�', 'È�' => 'È‘', 'È’' => 'È“', 'È”' => 'È•', 'È–' => 'È—', 'È˜' => 'È™', 'Èš' => 'È›', 'Èœ' => 'È�', 'Èž' => 'ÈŸ', 'È ' => 'Æž', 'È¢' => 'È£', 'È¤' => 'È¥', 'È¦' => 'È§', 'È¨' => 'È©', 'Èª' => 'È«', 'È¬' => 'È­', 'È®' => 'È¯', 'È°' => 'È±', 'È²' => 'È³', 'Èº' => 'â±¥', 'È»' => 'È¼', 'È½' => 'Æš', 'È¾' => 'â±¦', 'É�' => 'É‚', 'Éƒ' => 'Æ€', 'É„' => 'Ê‰', 'É…' => 'ÊŒ', 'É†' => 'É‡', 'Éˆ' => 'É‰', 'ÉŠ' => 'É‹', 'ÉŒ' => 'É�', 'ÉŽ' => 'É�', 'Í°' => 'Í±', 'Í²' => 'Í³', 'Í¶' => 'Í·', 'Í¿' => 'Ï³', 'Î†' => 'Î¬', 'Îˆ' => 'Î­', 'Î‰' => 'Î®', 'ÎŠ' => 'Î¯', 'ÎŒ' => 'ÏŒ', 'ÎŽ' => 'Ï�', 'Î�' => 'ÏŽ', 'Î‘' => 'Î±', 'Î’' => 'Î²', 'Î“' => 'Î³', 'Î”' => 'Î´', 'Î•' => 'Îµ', 'Î–' => 'Î¶', 'Î—' => 'Î·', 'Î˜' => 'Î¸', 'Î™' => 'Î¹', 'Îš' => 'Îº', 'Î›' => 'Î»', 'Îœ' => 'Î¼', 'Î�' => 'Î½', 'Îž' => 'Î¾', 'ÎŸ' => 'Î¿', 'Î ' => 'Ï€', 'Î¡' => 'Ï�', 'Î£' => 'Ïƒ', 'Î¤' => 'Ï„', 'Î¥' => 'Ï…', 'Î¦' => 'Ï†', 'Î§' => 'Ï‡', 'Î¨' => 'Ïˆ', 'Î©' => 'Ï‰', 'Îª' => 'ÏŠ', 'Î«' => 'Ï‹', 'Ï�' => 'Ï—', 'Ï˜' => 'Ï™', 'Ïš' => 'Ï›', 'Ïœ' => 'Ï�', 'Ïž' => 'ÏŸ', 'Ï ' => 'Ï¡', 'Ï¢' => 'Ï£', 'Ï¤' => 'Ï¥', 'Ï¦' => 'Ï§', 'Ï¨' => 'Ï©', 'Ïª' => 'Ï«', 'Ï¬' => 'Ï­', 'Ï®' => 'Ï¯', 'Ï´' => 'Î¸', 'Ï·' => 'Ï¸', 'Ï¹' => 'Ï²', 'Ïº' => 'Ï»', 'Ï½' => 'Í»', 'Ï¾' => 'Í¼', 'Ï¿' => 'Í½', 'Ð€' => 'Ñ�', 'Ð�' => 'Ñ‘', 'Ð‚' => 'Ñ’', 'Ðƒ' => 'Ñ“', 'Ð„' => 'Ñ”', 'Ð…' => 'Ñ•', 'Ð†' => 'Ñ–', 'Ð‡' => 'Ñ—', 'Ðˆ' => 'Ñ˜', 'Ð‰' => 'Ñ™', 'ÐŠ' => 'Ñš', 'Ð‹' => 'Ñ›', 'ÐŒ' => 'Ñœ', 'Ð�' => 'Ñ�', 'ÐŽ' => 'Ñž', 'Ð�' => 'ÑŸ', 'Ð�' => 'Ð°', 'Ð‘' => 'Ð±', 'Ð’' => 'Ð²', 'Ð“' => 'Ð³', 'Ð”' => 'Ð´', 'Ð•' => 'Ðµ', 'Ð–' => 'Ð¶', 'Ð—' => 'Ð·', 'Ð˜' => 'Ð¸', 'Ð™' => 'Ð¹', 'Ðš' => 'Ðº', 'Ð›' => 'Ð»', 'Ðœ' => 'Ð¼', 'Ð�' => 'Ð½', 'Ðž' => 'Ð¾', 'ÐŸ' => 'Ð¿', 'Ð ' => 'Ñ€', 'Ð¡' => 'Ñ�', 'Ð¢' => 'Ñ‚', 'Ð£' => 'Ñƒ', 'Ð¤' => 'Ñ„', 'Ð¥' => 'Ñ…', 'Ð¦' => 'Ñ†', 'Ð§' => 'Ñ‡', 'Ð¨' => 'Ñˆ', 'Ð©' => 'Ñ‰', 'Ðª' => 'ÑŠ', 'Ð«' => 'Ñ‹', 'Ð¬' => 'ÑŒ', 'Ð­' => 'Ñ�', 'Ð®' => 'ÑŽ', 'Ð¯' => 'Ñ�', 'Ñ ' => 'Ñ¡', 'Ñ¢' => 'Ñ£', 'Ñ¤' => 'Ñ¥', 'Ñ¦' => 'Ñ§', 'Ñ¨' => 'Ñ©', 'Ñª' => 'Ñ«', 'Ñ¬' => 'Ñ­', 'Ñ®' => 'Ñ¯', 'Ñ°' => 'Ñ±', 'Ñ²' => 'Ñ³', 'Ñ´' => 'Ñµ', 'Ñ¶' => 'Ñ·', 'Ñ¸' => 'Ñ¹', 'Ñº' => 'Ñ»', 'Ñ¼' => 'Ñ½', 'Ñ¾' => 'Ñ¿', 'Ò€' => 'Ò�', 'ÒŠ' => 'Ò‹', 'ÒŒ' => 'Ò�', 'ÒŽ' => 'Ò�', 'Ò�' => 'Ò‘', 'Ò’' => 'Ò“', 'Ò”' => 'Ò•', 'Ò–' => 'Ò—', 'Ò˜' => 'Ò™', 'Òš' => 'Ò›', 'Òœ' => 'Ò�', 'Òž' => 'ÒŸ', 'Ò ' => 'Ò¡', 'Ò¢' => 'Ò£', 'Ò¤' => 'Ò¥', 'Ò¦' => 'Ò§', 'Ò¨' => 'Ò©', 'Òª' => 'Ò«', 'Ò¬' => 'Ò­', 'Ò®' => 'Ò¯', 'Ò°' => 'Ò±', 'Ò²' => 'Ò³', 'Ò´' => 'Òµ', 'Ò¶' => 'Ò·', 'Ò¸' => 'Ò¹', 'Òº' => 'Ò»', 'Ò¼' => 'Ò½', 'Ò¾' => 'Ò¿', 'Ó€' => 'Ó�', 'Ó�' => 'Ó‚', 'Óƒ' => 'Ó„', 'Ó…' => 'Ó†', 'Ó‡' => 'Óˆ', 'Ó‰' => 'ÓŠ', 'Ó‹' => 'ÓŒ', 'Ó�' => 'ÓŽ', 'Ó�' => 'Ó‘', 'Ó’' => 'Ó“', 'Ó”' => 'Ó•', 'Ó–' => 'Ó—', 'Ó˜' => 'Ó™', 'Óš' => 'Ó›', 'Óœ' => 'Ó�', 'Óž' => 'ÓŸ', 'Ó ' => 'Ó¡', 'Ó¢' => 'Ó£', 'Ó¤' => 'Ó¥', 'Ó¦' => 'Ó§', 'Ó¨' => 'Ó©', 'Óª' => 'Ó«', 'Ó¬' => 'Ó­', 'Ó®' => 'Ó¯', 'Ó°' => 'Ó±', 'Ó²' => 'Ó³', 'Ó´' => 'Óµ', 'Ó¶' => 'Ó·', 'Ó¸' => 'Ó¹', 'Óº' => 'Ó»', 'Ó¼' => 'Ó½', 'Ó¾' => 'Ó¿', 'Ô€' => 'Ô�', 'Ô‚' => 'Ôƒ', 'Ô„' => 'Ô…', 'Ô†' => 'Ô‡', 'Ôˆ' => 'Ô‰', 'ÔŠ' => 'Ô‹', 'ÔŒ' => 'Ô�', 'ÔŽ' => 'Ô�', 'Ô�' => 'Ô‘', 'Ô’' => 'Ô“', 'Ô”' => 'Ô•', 'Ô–' => 'Ô—', 'Ô˜' => 'Ô™', 'Ôš' => 'Ô›', 'Ôœ' => 'Ô�', 'Ôž' => 'ÔŸ', 'Ô ' => 'Ô¡', 'Ô¢' => 'Ô£', 'Ô¤' => 'Ô¥', 'Ô¦' => 'Ô§', 'Ô¨' => 'Ô©', 'Ôª' => 'Ô«', 'Ô¬' => 'Ô­', 'Ô®' => 'Ô¯', 'Ô±' => 'Õ¡', 'Ô²' => 'Õ¢', 'Ô³' => 'Õ£', 'Ô´' => 'Õ¤', 'Ôµ' => 'Õ¥', 'Ô¶' => 'Õ¦', 'Ô·' => 'Õ§', 'Ô¸' => 'Õ¨', 'Ô¹' => 'Õ©', 'Ôº' => 'Õª', 'Ô»' => 'Õ«', 'Ô¼' => 'Õ¬', 'Ô½' => 'Õ­', 'Ô¾' => 'Õ®', 'Ô¿' => 'Õ¯', 'Õ€' => 'Õ°', 'Õ�' => 'Õ±', 'Õ‚' => 'Õ²', 'Õƒ' => 'Õ³', 'Õ„' => 'Õ´', 'Õ…' => 'Õµ', 'Õ†' => 'Õ¶', 'Õ‡' => 'Õ·', 'Õˆ' => 'Õ¸', 'Õ‰' => 'Õ¹', 'ÕŠ' => 'Õº', 'Õ‹' => 'Õ»', 'ÕŒ' => 'Õ¼', 'Õ�' => 'Õ½', 'ÕŽ' => 'Õ¾', 'Õ�' => 'Õ¿', 'Õ�' => 'Ö€', 'Õ‘' => 'Ö�', 'Õ’' => 'Ö‚', 'Õ“' => 'Öƒ', 'Õ”' => 'Ö„', 'Õ•' => 'Ö…', 'Õ–' => 'Ö†', 'á‚ ' => 'â´€', 'á‚¡' => 'â´�', 'á‚¢' => 'â´‚', 'á‚£' => 'â´ƒ', 'á‚¤' => 'â´„', 'á‚¥' => 'â´…', 'á‚¦' => 'â´†', 'á‚§' => 'â´‡', 'á‚¨' => 'â´ˆ', 'á‚©' => 'â´‰', 'á‚ª' => 'â´Š', 'á‚«' => 'â´‹', 'á‚¬' => 'â´Œ', 'á‚­' => 'â´�', 'á‚®' => 'â´Ž', 'á‚¯' => 'â´�', 'á‚°' => 'â´�', 'á‚±' => 'â´‘', 'á‚²' => 'â´’', 'á‚³' => 'â´“', 'á‚´' => 'â´”', 'á‚µ' => 'â´•', 'á‚¶' => 'â´–', 'á‚·' => 'â´—', 'á‚¸' => 'â´˜', 'á‚¹' => 'â´™', 'á‚º' => 'â´š', 'á‚»' => 'â´›', 'á‚¼' => 'â´œ', 'á‚½' => 'â´�', 'á‚¾' => 'â´ž', 'á‚¿' => 'â´Ÿ', 'áƒ€' => 'â´ ', 'áƒ�' => 'â´¡', 'áƒ‚' => 'â´¢', 'áƒƒ' => 'â´£', 'áƒ„' => 'â´¤', 'áƒ…' => 'â´¥', 'áƒ‡' => 'â´§', 'áƒ�' => 'â´­', 'áŽ ' => 'ê­°', 'áŽ¡' => 'ê­±', 'áŽ¢' => 'ê­²', 'áŽ£' => 'ê­³', 'áŽ¤' => 'ê­´', 'áŽ¥' => 'ê­µ', 'áŽ¦' => 'ê­¶', 'áŽ§' => 'ê­·', 'áŽ¨' => 'ê­¸', 'áŽ©' => 'ê­¹', 'áŽª' => 'ê­º', 'áŽ«' => 'ê­»', 'áŽ¬' => 'ê­¼', 'áŽ­' => 'ê­½', 'áŽ®' => 'ê­¾', 'áŽ¯' => 'ê­¿', 'áŽ°' => 'ê®€', 'áŽ±' => 'ê®�', 'áŽ²' => 'ê®‚', 'áŽ³' => 'ê®ƒ', 'áŽ´' => 'ê®„', 'áŽµ' => 'ê®…', 'áŽ¶' => 'ê®†', 'áŽ·' => 'ê®‡', 'áŽ¸' => 'ê®ˆ', 'áŽ¹' => 'ê®‰', 'áŽº' => 'ê®Š', 'áŽ»' => 'ê®‹', 'áŽ¼' => 'ê®Œ', 'áŽ½' => 'ê®�', 'áŽ¾' => 'ê®Ž', 'áŽ¿' => 'ê®�', 'á�€' => 'ê®�', 'á��' => 'ê®‘', 'á�‚' => 'ê®’', 'á�ƒ' => 'ê®“', 'á�„' => 'ê®”', 'á�…' => 'ê®•', 'á�†' => 'ê®–', 'á�‡' => 'ê®—', 'á�ˆ' => 'ê®˜', 'á�‰' => 'ê®™', 'á�Š' => 'ê®š', 'á�‹' => 'ê®›', 'á�Œ' => 'ê®œ', 'á��' => 'ê®�', 'á�Ž' => 'ê®ž', 'á��' => 'ê®Ÿ', 'á��' => 'ê® ', 'á�‘' => 'ê®¡', 'á�’' => 'ê®¢', 'á�“' => 'ê®£', 'á�”' => 'ê®¤', 'á�•' => 'ê®¥', 'á�–' => 'ê®¦', 'á�—' => 'ê®§', 'á�˜' => 'ê®¨', 'á�™' => 'ê®©', 'á�š' => 'ê®ª', 'á�›' => 'ê®«', 'á�œ' => 'ê®¬', 'á��' => 'ê®­', 'á�ž' => 'ê®®', 'á�Ÿ' => 'ê®¯', 'á� ' => 'ê®°', 'á�¡' => 'ê®±', 'á�¢' => 'ê®²', 'á�£' => 'ê®³', 'á�¤' => 'ê®´', 'á�¥' => 'ê®µ', 'á�¦' => 'ê®¶', 'á�§' => 'ê®·', 'á�¨' => 'ê®¸', 'á�©' => 'ê®¹', 'á�ª' => 'ê®º', 'á�«' => 'ê®»', 'á�¬' => 'ê®¼', 'á�­' => 'ê®½', 'á�®' => 'ê®¾', 'á�¯' => 'ê®¿', 'á�°' => 'á�¸', 'á�±' => 'á�¹', 'á�²' => 'á�º', 'á�³' => 'á�»', 'á�´' => 'á�¼', 'á�µ' => 'á�½', 'á²�' => 'áƒ�', 'á²‘' => 'áƒ‘', 'á²’' => 'áƒ’', 'á²“' => 'áƒ“', 'á²”' => 'áƒ”', 'á²•' => 'áƒ•', 'á²–' => 'áƒ–', 'á²—' => 'áƒ—', 'á²˜' => 'áƒ˜', 'á²™' => 'áƒ™', 'á²š' => 'áƒš', 'á²›' => 'áƒ›', 'á²œ' => 'áƒœ', 'á²�' => 'áƒ�', 'á²ž' => 'áƒž', 'á²Ÿ' => 'áƒŸ', 'á² ' => 'áƒ ', 'á²¡' => 'áƒ¡', 'á²¢' => 'áƒ¢', 'á²£' => 'áƒ£', 'á²¤' => 'áƒ¤', 'á²¥' => 'áƒ¥', 'á²¦' => 'áƒ¦', 'á²§' => 'áƒ§', 'á²¨' => 'áƒ¨', 'á²©' => 'áƒ©', 'á²ª' => 'áƒª', 'á²«' => 'áƒ«', 'á²¬' => 'áƒ¬', 'á²­' => 'áƒ­', 'á²®' => 'áƒ®', 'á²¯' => 'áƒ¯', 'á²°' => 'áƒ°', 'á²±' => 'áƒ±', 'á²²' => 'áƒ²', 'á²³' => 'áƒ³', 'á²´' => 'áƒ´', 'á²µ' => 'áƒµ', 'á²¶' => 'áƒ¶', 'á²·' => 'áƒ·', 'á²¸' => 'áƒ¸', 'á²¹' => 'áƒ¹', 'á²º' => 'áƒº', 'á²½' => 'áƒ½', 'á²¾' => 'áƒ¾', 'á²¿' => 'áƒ¿', 'á¸€' => 'á¸�', 'á¸‚' => 'á¸ƒ', 'á¸„' => 'á¸…', 'á¸†' => 'á¸‡', 'á¸ˆ' => 'á¸‰', 'á¸Š' => 'á¸‹', 'á¸Œ' => 'á¸�', 'á¸Ž' => 'á¸�', 'á¸�' => 'á¸‘', 'á¸’' => 'á¸“', 'á¸”' => 'á¸•', 'á¸–' => 'á¸—', 'á¸˜' => 'á¸™', 'á¸š' => 'á¸›', 'á¸œ' => 'á¸�', 'á¸ž' => 'á¸Ÿ', 'á¸ ' => 'á¸¡', 'á¸¢' => 'á¸£', 'á¸¤' => 'á¸¥', 'á¸¦' => 'á¸§', 'á¸¨' => 'á¸©', 'á¸ª' => 'á¸«', 'á¸¬' => 'á¸­', 'á¸®' => 'á¸¯', 'á¸°' => 'á¸±', 'á¸²' => 'á¸³', 'á¸´' => 'á¸µ', 'á¸¶' => 'á¸·', 'á¸¸' => 'á¸¹', 'á¸º' => 'á¸»', 'á¸¼' => 'á¸½', 'á¸¾' => 'á¸¿', 'á¹€' => 'á¹�', 'á¹‚' => 'á¹ƒ', 'á¹„' => 'á¹…', 'á¹†' => 'á¹‡', 'á¹ˆ' => 'á¹‰', 'á¹Š' => 'á¹‹', 'á¹Œ' => 'á¹�', 'á¹Ž' => 'á¹�', 'á¹�' => 'á¹‘', 'á¹’' => 'á¹“', 'á¹”' => 'á¹•', 'á¹–' => 'á¹—', 'á¹˜' => 'á¹™', 'á¹š' => 'á¹›', 'á¹œ' => 'á¹�', 'á¹ž' => 'á¹Ÿ', 'á¹ ' => 'á¹¡', 'á¹¢' => 'á¹£', 'á¹¤' => 'á¹¥', 'á¹¦' => 'á¹§', 'á¹¨' => 'á¹©', 'á¹ª' => 'á¹«', 'á¹¬' => 'á¹­', 'á¹®' => 'á¹¯', 'á¹°' => 'á¹±', 'á¹²' => 'á¹³', 'á¹´' => 'á¹µ', 'á¹¶' => 'á¹·', 'á¹¸' => 'á¹¹', 'á¹º' => 'á¹»', 'á¹¼' => 'á¹½', 'á¹¾' => 'á¹¿', 'áº€' => 'áº�', 'áº‚' => 'áºƒ', 'áº„' => 'áº…', 'áº†' => 'áº‡', 'áºˆ' => 'áº‰', 'áºŠ' => 'áº‹', 'áºŒ' => 'áº�', 'áºŽ' => 'áº�', 'áº�' => 'áº‘', 'áº’' => 'áº“', 'áº”' => 'áº•', 'áºž' => 'ÃŸ', 'áº ' => 'áº¡', 'áº¢' => 'áº£', 'áº¤' => 'áº¥', 'áº¦' => 'áº§', 'áº¨' => 'áº©', 'áºª' => 'áº«', 'áº¬' => 'áº­', 'áº®' => 'áº¯', 'áº°' => 'áº±', 'áº²' => 'áº³', 'áº´' => 'áºµ', 'áº¶' => 'áº·', 'áº¸' => 'áº¹', 'áºº' => 'áº»', 'áº¼' => 'áº½', 'áº¾' => 'áº¿', 'á»€' => 'á»�', 'á»‚' => 'á»ƒ', 'á»„' => 'á»…', 'á»†' => 'á»‡', 'á»ˆ' => 'á»‰', 'á»Š' => 'á»‹', 'á»Œ' => 'á»�', 'á»Ž' => 'á»�', 'á»�' => 'á»‘', 'á»’' => 'á»“', 'á»”' => 'á»•', 'á»–' => 'á»—', 'á»˜' => 'á»™', 'á»š' => 'á»›', 'á»œ' => 'á»�', 'á»ž' => 'á»Ÿ', 'á» ' => 'á»¡', 'á»¢' => 'á»£', 'á»¤' => 'á»¥', 'á»¦' => 'á»§', 'á»¨' => 'á»©', 'á»ª' => 'á»«', 'á»¬' => 'á»­', 'á»®' => 'á»¯', 'á»°' => 'á»±', 'á»²' => 'á»³', 'á»´' => 'á»µ', 'á»¶' => 'á»·', 'á»¸' => 'á»¹', 'á»º' => 'á»»', 'á»¼' => 'á»½', 'á»¾' => 'á»¿', 'á¼ˆ' => 'á¼€', 'á¼‰' => 'á¼�', 'á¼Š' => 'á¼‚', 'á¼‹' => 'á¼ƒ', 'á¼Œ' => 'á¼„', 'á¼�' => 'á¼…', 'á¼Ž' => 'á¼†', 'á¼�' => 'á¼‡', 'á¼˜' => 'á¼�', 'á¼™' => 'á¼‘', 'á¼š' => 'á¼’', 'á¼›' => 'á¼“', 'á¼œ' => 'á¼”', 'á¼�' => 'á¼•', 'á¼¨' => 'á¼ ', 'á¼©' => 'á¼¡', 'á¼ª' => 'á¼¢', 'á¼«' => 'á¼£', 'á¼¬' => 'á¼¤', 'á¼­' => 'á¼¥', 'á¼®' => 'á¼¦', 'á¼¯' => 'á¼§', 'á¼¸' => 'á¼°', 'á¼¹' => 'á¼±', 'á¼º' => 'á¼²', 'á¼»' => 'á¼³', 'á¼¼' => 'á¼´', 'á¼½' => 'á¼µ', 'á¼¾' => 'á¼¶', 'á¼¿' => 'á¼·', 'á½ˆ' => 'á½€', 'á½‰' => 'á½�', 'á½Š' => 'á½‚', 'á½‹' => 'á½ƒ', 'á½Œ' => 'á½„', 'á½�' => 'á½…', 'á½™' => 'á½‘', 'á½›' => 'á½“', 'á½�' => 'á½•', 'á½Ÿ' => 'á½—', 'á½¨' => 'á½ ', 'á½©' => 'á½¡', 'á½ª' => 'á½¢', 'á½«' => 'á½£', 'á½¬' => 'á½¤', 'á½­' => 'á½¥', 'á½®' => 'á½¦', 'á½¯' => 'á½§', 'á¾ˆ' => 'á¾€', 'á¾‰' => 'á¾�', 'á¾Š' => 'á¾‚', 'á¾‹' => 'á¾ƒ', 'á¾Œ' => 'á¾„', 'á¾�' => 'á¾…', 'á¾Ž' => 'á¾†', 'á¾�' => 'á¾‡', 'á¾˜' => 'á¾�', 'á¾™' => 'á¾‘', 'á¾š' => 'á¾’', 'á¾›' => 'á¾“', 'á¾œ' => 'á¾”', 'á¾�' => 'á¾•', 'á¾ž' => 'á¾–', 'á¾Ÿ' => 'á¾—', 'á¾¨' => 'á¾ ', 'á¾©' => 'á¾¡', 'á¾ª' => 'á¾¢', 'á¾«' => 'á¾£', 'á¾¬' => 'á¾¤', 'á¾­' => 'á¾¥', 'á¾®' => 'á¾¦', 'á¾¯' => 'á¾§', 'á¾¸' => 'á¾°', 'á¾¹' => 'á¾±', 'á¾º' => 'á½°', 'á¾»' => 'á½±', 'á¾¼' => 'á¾³', 'á¿ˆ' => 'á½²', 'á¿‰' => 'á½³', 'á¿Š' => 'á½´', 'á¿‹' => 'á½µ', 'á¿Œ' => 'á¿ƒ', 'á¿˜' => 'á¿�', 'á¿™' => 'á¿‘', 'á¿š' => 'á½¶', 'á¿›' => 'á½·', 'á¿¨' => 'á¿ ', 'á¿©' => 'á¿¡', 'á¿ª' => 'á½º', 'á¿«' => 'á½»', 'á¿¬' => 'á¿¥', 'á¿¸' => 'á½¸', 'á¿¹' => 'á½¹', 'á¿º' => 'á½¼', 'á¿»' => 'á½½', 'á¿¼' => 'á¿³', 'â„¦' => 'Ï‰', 'â„ª' => 'k', 'â„«' => 'Ã¥', 'â„²' => 'â…Ž', 'â… ' => 'â…°', 'â…¡' => 'â…±', 'â…¢' => 'â…²', 'â…£' => 'â…³', 'â…¤' => 'â…´', 'â…¥' => 'â…µ', 'â…¦' => 'â…¶', 'â…§' => 'â…·', 'â…¨' => 'â…¸', 'â…©' => 'â…¹', 'â…ª' => 'â…º', 'â…«' => 'â…»', 'â…¬' => 'â…¼', 'â…­' => 'â…½', 'â…®' => 'â…¾', 'â…¯' => 'â…¿', 'â†ƒ' => 'â†„', 'â’¶' => 'â“�', 'â’·' => 'â“‘', 'â’¸' => 'â“’', 'â’¹' => 'â““', 'â’º' => 'â“”', 'â’»' => 'â“•', 'â’¼' => 'â“–', 'â’½' => 'â“—', 'â’¾' => 'â“˜', 'â’¿' => 'â“™', 'â“€' => 'â“š', 'â“�' => 'â“›', 'â“‚' => 'â“œ', 'â“ƒ' => 'â“�', 'â“„' => 'â“ž', 'â“…' => 'â“Ÿ', 'â“†' => 'â“ ', 'â“‡' => 'â“¡', 'â“ˆ' => 'â“¢', 'â“‰' => 'â“£', 'â“Š' => 'â“¤', 'â“‹' => 'â“¥', 'â“Œ' => 'â“¦', 'â“�' => 'â“§', 'â“Ž' => 'â“¨', 'â“�' => 'â“©', 'â°€' => 'â°°', 'â°�' => 'â°±', 'â°‚' => 'â°²', 'â°ƒ' => 'â°³', 'â°„' => 'â°´', 'â°…' => 'â°µ', 'â°†' => 'â°¶', 'â°‡' => 'â°·', 'â°ˆ' => 'â°¸', 'â°‰' => 'â°¹', 'â°Š' => 'â°º', 'â°‹' => 'â°»', 'â°Œ' => 'â°¼', 'â°�' => 'â°½', 'â°Ž' => 'â°¾', 'â°�' => 'â°¿', 'â°�' => 'â±€', 'â°‘' => 'â±�', 'â°’' => 'â±‚', 'â°“' => 'â±ƒ', 'â°”' => 'â±„', 'â°•' => 'â±…', 'â°–' => 'â±†', 'â°—' => 'â±‡', 'â°˜' => 'â±ˆ', 'â°™' => 'â±‰', 'â°š' => 'â±Š', 'â°›' => 'â±‹', 'â°œ' => 'â±Œ', 'â°�' => 'â±�', 'â°ž' => 'â±Ž', 'â°Ÿ' => 'â±�', 'â° ' => 'â±�', 'â°¡' => 'â±‘', 'â°¢' => 'â±’', 'â°£' => 'â±“', 'â°¤' => 'â±”', 'â°¥' => 'â±•', 'â°¦' => 'â±–', 'â°§' => 'â±—', 'â°¨' => 'â±˜', 'â°©' => 'â±™', 'â°ª' => 'â±š', 'â°«' => 'â±›', 'â°¬' => 'â±œ', 'â°­' => 'â±�', 'â°®' => 'â±ž', 'â± ' => 'â±¡', 'â±¢' => 'É«', 'â±£' => 'áµ½', 'â±¤' => 'É½', 'â±§' => 'â±¨', 'â±©' => 'â±ª', 'â±«' => 'â±¬', 'â±­' => 'É‘', 'â±®' => 'É±', 'â±¯' => 'É�', 'â±°' => 'É’', 'â±²' => 'â±³', 'â±µ' => 'â±¶', 'â±¾' => 'È¿', 'â±¿' => 'É€', 'â²€' => 'â²�', 'â²‚' => 'â²ƒ', 'â²„' => 'â²…', 'â²†' => 'â²‡', 'â²ˆ' => 'â²‰', 'â²Š' => 'â²‹', 'â²Œ' => 'â²�', 'â²Ž' => 'â²�', 'â²�' => 'â²‘', 'â²’' => 'â²“', 'â²”' => 'â²•', 'â²–' => 'â²—', 'â²˜' => 'â²™', 'â²š' => 'â²›', 'â²œ' => 'â²�', 'â²ž' => 'â²Ÿ', 'â² ' => 'â²¡', 'â²¢' => 'â²£', 'â²¤' => 'â²¥', 'â²¦' => 'â²§', 'â²¨' => 'â²©', 'â²ª' => 'â²«', 'â²¬' => 'â²­', 'â²®' => 'â²¯', 'â²°' => 'â²±', 'â²²' => 'â²³', 'â²´' => 'â²µ', 'â²¶' => 'â²·', 'â²¸' => 'â²¹', 'â²º' => 'â²»', 'â²¼' => 'â²½', 'â²¾' => 'â²¿', 'â³€' => 'â³�', 'â³‚' => 'â³ƒ', 'â³„' => 'â³…', 'â³†' => 'â³‡', 'â³ˆ' => 'â³‰', 'â³Š' => 'â³‹', 'â³Œ' => 'â³�', 'â³Ž' => 'â³�', 'â³�' => 'â³‘', 'â³’' => 'â³“', 'â³”' => 'â³•', 'â³–' => 'â³—', 'â³˜' => 'â³™', 'â³š' => 'â³›', 'â³œ' => 'â³�', 'â³ž' => 'â³Ÿ', 'â³ ' => 'â³¡', 'â³¢' => 'â³£', 'â³«' => 'â³¬', 'â³­' => 'â³®', 'â³²' => 'â³³', 'ê™€' => 'ê™�', 'ê™‚' => 'ê™ƒ', 'ê™„' => 'ê™…', 'ê™†' => 'ê™‡', 'ê™ˆ' => 'ê™‰', 'ê™Š' => 'ê™‹', 'ê™Œ' => 'ê™�', 'ê™Ž' => 'ê™�', 'ê™�' => 'ê™‘', 'ê™’' => 'ê™“', 'ê™”' => 'ê™•', 'ê™–' => 'ê™—', 'ê™˜' => 'ê™™', 'ê™š' => 'ê™›', 'ê™œ' => 'ê™�', 'ê™ž' => 'ê™Ÿ', 'ê™ ' => 'ê™¡', 'ê™¢' => 'ê™£', 'ê™¤' => 'ê™¥', 'ê™¦' => 'ê™§', 'ê™¨' => 'ê™©', 'ê™ª' => 'ê™«', 'ê™¬' => 'ê™­', 'êš€' => 'êš�', 'êš‚' => 'êšƒ', 'êš„' => 'êš…', 'êš†' => 'êš‡', 'êšˆ' => 'êš‰', 'êšŠ' => 'êš‹', 'êšŒ' => 'êš�', 'êšŽ' => 'êš�', 'êš�' => 'êš‘', 'êš’' => 'êš“', 'êš”' => 'êš•', 'êš–' => 'êš—', 'êš˜' => 'êš™', 'êšš' => 'êš›', 'êœ¢' => 'êœ£', 'êœ¤' => 'êœ¥', 'êœ¦' => 'êœ§', 'êœ¨' => 'êœ©', 'êœª' => 'êœ«', 'êœ¬' => 'êœ­', 'êœ®' => 'êœ¯', 'êœ²' => 'êœ³', 'êœ´' => 'êœµ', 'êœ¶' => 'êœ·', 'êœ¸' => 'êœ¹', 'êœº' => 'êœ»', 'êœ¼' => 'êœ½', 'êœ¾' => 'êœ¿', 'ê�€' => 'ê��', 'ê�‚' => 'ê�ƒ', 'ê�„' => 'ê�…', 'ê�†' => 'ê�‡', 'ê�ˆ' => 'ê�‰', 'ê�Š' => 'ê�‹', 'ê�Œ' => 'ê��', 'ê�Ž' => 'ê��', 'ê��' => 'ê�‘', 'ê�’' => 'ê�“', 'ê�”' => 'ê�•', 'ê�–' => 'ê�—', 'ê�˜' => 'ê�™', 'ê�š' => 'ê�›', 'ê�œ' => 'ê��', 'ê�ž' => 'ê�Ÿ', 'ê� ' => 'ê�¡', 'ê�¢' => 'ê�£', 'ê�¤' => 'ê�¥', 'ê�¦' => 'ê�§', 'ê�¨' => 'ê�©', 'ê�ª' => 'ê�«', 'ê�¬' => 'ê�­', 'ê�®' => 'ê�¯', 'ê�¹' => 'ê�º', 'ê�»' => 'ê�¼', 'ê�½' => 'áµ¹', 'ê�¾' => 'ê�¿', 'êž€' => 'êž�', 'êž‚' => 'êžƒ', 'êž„' => 'êž…', 'êž†' => 'êž‡', 'êž‹' => 'êžŒ', 'êž�' => 'É¥', 'êž�' => 'êž‘', 'êž’' => 'êž“', 'êž–' => 'êž—', 'êž˜' => 'êž™', 'êžš' => 'êž›', 'êžœ' => 'êž�', 'êžž' => 'êžŸ', 'êž ' => 'êž¡', 'êž¢' => 'êž£', 'êž¤' => 'êž¥', 'êž¦' => 'êž§', 'êž¨' => 'êž©', 'êžª' => 'É¦', 'êž«' => 'Éœ', 'êž¬' => 'É¡', 'êž­' => 'É¬', 'êž®' => 'Éª', 'êž°' => 'Êž', 'êž±' => 'Ê‡', 'êž²' => 'Ê�', 'êž³' => 'ê­“', 'êž´' => 'êžµ', 'êž¶' => 'êž·', 'êž¸' => 'êž¹', 'êžº' => 'êž»', 'êž¼' => 'êž½', 'êž¾' => 'êž¿', 'êŸ‚' => 'êŸƒ', 'êŸ„' => 'êž”', 'êŸ…' => 'Ê‚', 'êŸ†' => 'á¶Ž', 'êŸ‡' => 'êŸˆ', 'êŸ‰' => 'êŸŠ', 'êŸµ' => 'êŸ¶', 'ï¼¡' => 'ï½�', 'ï¼¢' => 'ï½‚', 'ï¼£' => 'ï½ƒ', 'ï¼¤' => 'ï½„', 'ï¼¥' => 'ï½…', 'ï¼¦' => 'ï½†', 'ï¼§' => 'ï½‡', 'ï¼¨' => 'ï½ˆ', 'ï¼©' => 'ï½‰', 'ï¼ª' => 'ï½Š', 'ï¼«' => 'ï½‹', 'ï¼¬' => 'ï½Œ', 'ï¼­' => 'ï½�', 'ï¼®' => 'ï½Ž', 'ï¼¯' => 'ï½�', 'ï¼°' => 'ï½�', 'ï¼±' => 'ï½‘', 'ï¼²' => 'ï½’', 'ï¼³' => 'ï½“', 'ï¼´' => 'ï½”', 'ï¼µ' => 'ï½•', 'ï¼¶' => 'ï½–', 'ï¼·' => 'ï½—', 'ï¼¸' => 'ï½˜', 'ï¼¹' => 'ï½™', 'ï¼º' => 'ï½š', 'ð��€' => 'ð��¨', 'ð���' => 'ð��©', 'ð��‚' => 'ð��ª', 'ð��ƒ' => 'ð��«', 'ð��„' => 'ð��¬', 'ð��…' => 'ð��­', 'ð��†' => 'ð��®', 'ð��‡' => 'ð��¯', 'ð��ˆ' => 'ð��°', 'ð��‰' => 'ð��±', 'ð��Š' => 'ð��²', 'ð��‹' => 'ð��³', 'ð��Œ' => 'ð��´', 'ð���' => 'ð��µ', 'ð��Ž' => 'ð��¶', 'ð���' => 'ð��·', 'ð���' => 'ð��¸', 'ð��‘' => 'ð��¹', 'ð��’' => 'ð��º', 'ð��“' => 'ð��»', 'ð��”' => 'ð��¼', 'ð��•' => 'ð��½', 'ð��–' => 'ð��¾', 'ð��—' => 'ð��¿', 'ð��˜' => 'ð�‘€', 'ð��™' => 'ð�‘�', 'ð��š' => 'ð�‘‚', 'ð��›' => 'ð�‘ƒ', 'ð��œ' => 'ð�‘„', 'ð���' => 'ð�‘…', 'ð��ž' => 'ð�‘†', 'ð��Ÿ' => 'ð�‘‡', 'ð�� ' => 'ð�‘ˆ', 'ð��¡' => 'ð�‘‰', 'ð��¢' => 'ð�‘Š', 'ð��£' => 'ð�‘‹', 'ð��¤' => 'ð�‘Œ', 'ð��¥' => 'ð�‘�', 'ð��¦' => 'ð�‘Ž', 'ð��§' => 'ð�‘�', 'ð�’°' => 'ð�“˜', 'ð�’±' => 'ð�“™', 'ð�’²' => 'ð�“š', 'ð�’³' => 'ð�“›', 'ð�’´' => 'ð�“œ', 'ð�’µ' => 'ð�“�', 'ð�’¶' => 'ð�“ž', 'ð�’·' => 'ð�“Ÿ', 'ð�’¸' => 'ð�“ ', 'ð�’¹' => 'ð�“¡', 'ð�’º' => 'ð�“¢', 'ð�’»' => 'ð�“£', 'ð�’¼' => 'ð�“¤', 'ð�’½' => 'ð�“¥', 'ð�’¾' => 'ð�“¦', 'ð�’¿' => 'ð�“§', 'ð�“€' => 'ð�“¨', 'ð�“�' => 'ð�“©', 'ð�“‚' => 'ð�“ª', 'ð�“ƒ' => 'ð�“«', 'ð�“„' => 'ð�“¬', 'ð�“…' => 'ð�“­', 'ð�“†' => 'ð�“®', 'ð�“‡' => 'ð�“¯', 'ð�“ˆ' => 'ð�“°', 'ð�“‰' => 'ð�“±', 'ð�“Š' => 'ð�“²', 'ð�“‹' => 'ð�“³', 'ð�“Œ' => 'ð�“´', 'ð�“�' => 'ð�“µ', 'ð�“Ž' => 'ð�“¶', 'ð�“�' => 'ð�“·', 'ð�“�' => 'ð�“¸', 'ð�“‘' => 'ð�“¹', 'ð�“’' => 'ð�“º', 'ð�““' => 'ð�“»', 'ð�²€' => 'ð�³€', 'ð�²�' => 'ð�³�', 'ð�²‚' => 'ð�³‚', 'ð�²ƒ' => 'ð�³ƒ', 'ð�²„' => 'ð�³„', 'ð�²…' => 'ð�³…', 'ð�²†' => 'ð�³†', 'ð�²‡' => 'ð�³‡', 'ð�²ˆ' => 'ð�³ˆ', 'ð�²‰' => 'ð�³‰', 'ð�²Š' => 'ð�³Š', 'ð�²‹' => 'ð�³‹', 'ð�²Œ' => 'ð�³Œ', 'ð�²�' => 'ð�³�', 'ð�²Ž' => 'ð�³Ž', 'ð�²�' => 'ð�³�', 'ð�²�' => 'ð�³�', 'ð�²‘' => 'ð�³‘', 'ð�²’' => 'ð�³’', 'ð�²“' => 'ð�³“', 'ð�²”' => 'ð�³”', 'ð�²•' => 'ð�³•', 'ð�²–' => 'ð�³–', 'ð�²—' => 'ð�³—', 'ð�²˜' => 'ð�³˜', 'ð�²™' => 'ð�³™', 'ð�²š' => 'ð�³š', 'ð�²›' => 'ð�³›', 'ð�²œ' => 'ð�³œ', 'ð�²�' => 'ð�³�', 'ð�²ž' => 'ð�³ž', 'ð�²Ÿ' => 'ð�³Ÿ', 'ð�² ' => 'ð�³ ', 'ð�²¡' => 'ð�³¡', 'ð�²¢' => 'ð�³¢', 'ð�²£' => 'ð�³£', 'ð�²¤' => 'ð�³¤', 'ð�²¥' => 'ð�³¥', 'ð�²¦' => 'ð�³¦', 'ð�²§' => 'ð�³§', 'ð�²¨' => 'ð�³¨', 'ð�²©' => 'ð�³©', 'ð�²ª' => 'ð�³ª', 'ð�²«' => 'ð�³«', 'ð�²¬' => 'ð�³¬', 'ð�²­' => 'ð�³­', 'ð�²®' => 'ð�³®', 'ð�²¯' => 'ð�³¯', 'ð�²°' => 'ð�³°', 'ð�²±' => 'ð�³±', 'ð�²²' => 'ð�³²', 'ð‘¢ ' => 'ð‘£€', 'ð‘¢¡' => 'ð‘£�', 'ð‘¢¢' => 'ð‘£‚', 'ð‘¢£' => 'ð‘£ƒ', 'ð‘¢¤' => 'ð‘£„', 'ð‘¢¥' => 'ð‘£…', 'ð‘¢¦' => 'ð‘£†', 'ð‘¢§' => 'ð‘£‡', 'ð‘¢¨' => 'ð‘£ˆ', 'ð‘¢©' => 'ð‘£‰', 'ð‘¢ª' => 'ð‘£Š', 'ð‘¢«' => 'ð‘£‹', 'ð‘¢¬' => 'ð‘£Œ', 'ð‘¢­' => 'ð‘£�', 'ð‘¢®' => 'ð‘£Ž', 'ð‘¢¯' => 'ð‘£�', 'ð‘¢°' => 'ð‘£�', 'ð‘¢±' => 'ð‘£‘', 'ð‘¢²' => 'ð‘£’', 'ð‘¢³' => 'ð‘£“', 'ð‘¢´' => 'ð‘£”', 'ð‘¢µ' => 'ð‘£•', 'ð‘¢¶' => 'ð‘£–', 'ð‘¢·' => 'ð‘£—', 'ð‘¢¸' => 'ð‘£˜', 'ð‘¢¹' => 'ð‘£™', 'ð‘¢º' => 'ð‘£š', 'ð‘¢»' => 'ð‘£›', 'ð‘¢¼' => 'ð‘£œ', 'ð‘¢½' => 'ð‘£�', 'ð‘¢¾' => 'ð‘£ž', 'ð‘¢¿' => 'ð‘£Ÿ', 'ð–¹€' => 'ð–¹ ', 'ð–¹�' => 'ð–¹¡', 'ð–¹‚' => 'ð–¹¢', 'ð–¹ƒ' => 'ð–¹£', 'ð–¹„' => 'ð–¹¤', 'ð–¹…' => 'ð–¹¥', 'ð–¹†' => 'ð–¹¦', 'ð–¹‡' => 'ð–¹§', 'ð–¹ˆ' => 'ð–¹¨', 'ð–¹‰' => 'ð–¹©', 'ð–¹Š' => 'ð–¹ª', 'ð–¹‹' => 'ð–¹«', 'ð–¹Œ' => 'ð–¹¬', 'ð–¹�' => 'ð–¹­', 'ð–¹Ž' => 'ð–¹®', 'ð–¹�' => 'ð–¹¯', 'ð–¹�' => 'ð–¹°', 'ð–¹‘' => 'ð–¹±', 'ð–¹’' => 'ð–¹²', 'ð–¹“' => 'ð–¹³', 'ð–¹”' => 'ð–¹´', 'ð–¹•' => 'ð–¹µ', 'ð–¹–' => 'ð–¹¶', 'ð–¹—' => 'ð–¹·', 'ð–¹˜' => 'ð–¹¸', 'ð–¹™' => 'ð–¹¹', 'ð–¹š' => 'ð–¹º', 'ð–¹›' => 'ð–¹»', 'ð–¹œ' => 'ð–¹¼', 'ð–¹�' => 'ð–¹½', 'ð–¹ž' => 'ð–¹¾', 'ð–¹Ÿ' => 'ð–¹¿', 'ðž¤€' => 'ðž¤¢', 'ðž¤�' => 'ðž¤£', 'ðž¤‚' => 'ðž¤¤', 'ðž¤ƒ' => 'ðž¤¥', 'ðž¤„' => 'ðž¤¦', 'ðž¤…' => 'ðž¤§', 'ðž¤†' => 'ðž¤¨', 'ðž¤‡' => 'ðž¤©', 'ðž¤ˆ' => 'ðž¤ª', 'ðž¤‰' => 'ðž¤«', 'ðž¤Š' => 'ðž¤¬', 'ðž¤‹' => 'ðž¤­', 'ðž¤Œ' => 'ðž¤®', 'ðž¤�' => 'ðž¤¯', 'ðž¤Ž' => 'ðž¤°', 'ðž¤�' => 'ðž¤±', 'ðž¤�' => 'ðž¤²', 'ðž¤‘' => 'ðž¤³', 'ðž¤’' => 'ðž¤´', 'ðž¤“' => 'ðž¤µ', 'ðž¤”' => 'ðž¤¶', 'ðž¤•' => 'ðž¤·', 'ðž¤–' => 'ðž¤¸', 'ðž¤—' => 'ðž¤¹', 'ðž¤˜' => 'ðž¤º', 'ðž¤™' => 'ðž¤»', 'ðž¤š' => 'ðž¤¼', 'ðž¤›' => 'ðž¤½', 'ðž¤œ' => 'ðž¤¾', 'ðž¤�' => 'ðž¤¿', 'ðž¤ž' => 'ðž¥€', 'ðž¤Ÿ' => 'ðž¥�', 'ðž¤ ' => 'ðž¥‚', 'ðž¤¡' => 'ðž¥ƒ');<?php

return array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'e' => 'E', 'f' => 'F', 'g' => 'G', 'h' => 'H', 'i' => 'I', 'j' => 'J', 'k' => 'K', 'l' => 'L', 'm' => 'M', 'n' => 'N', 'o' => 'O', 'p' => 'P', 'q' => 'Q', 'r' => 'R', 's' => 'S', 't' => 'T', 'u' => 'U', 'v' => 'V', 'w' => 'W', 'x' => 'X', 'y' => 'Y', 'z' => 'Z', 'Âµ' => 'Îœ', 'Ã ' => 'Ã€', 'Ã¡' => 'Ã�', 'Ã¢' => 'Ã‚', 'Ã£' => 'Ãƒ', 'Ã¤' => 'Ã„', 'Ã¥' => 'Ã…', 'Ã¦' => 'Ã†', 'Ã§' => 'Ã‡', 'Ã¨' => 'Ãˆ', 'Ã©' => 'Ã‰', 'Ãª' => 'ÃŠ', 'Ã«' => 'Ã‹', 'Ã¬' => 'ÃŒ', 'Ã­' => 'Ã�', 'Ã®' => 'ÃŽ', 'Ã¯' => 'Ã�', 'Ã°' => 'Ã�', 'Ã±' => 'Ã‘', 'Ã²' => 'Ã’', 'Ã³' => 'Ã“', 'Ã´' => 'Ã”', 'Ãµ' => 'Ã•', 'Ã¶' => 'Ã–', 'Ã¸' => 'Ã˜', 'Ã¹' => 'Ã™', 'Ãº' => 'Ãš', 'Ã»' => 'Ã›', 'Ã¼' => 'Ãœ', 'Ã½' => 'Ã�', 'Ã¾' => 'Ãž', 'Ã¿' => 'Å¸', 'Ä�' => 'Ä€', 'Äƒ' => 'Ä‚', 'Ä…' => 'Ä„', 'Ä‡' => 'Ä†', 'Ä‰' => 'Äˆ', 'Ä‹' => 'ÄŠ', 'Ä�' => 'ÄŒ', 'Ä�' => 'ÄŽ', 'Ä‘' => 'Ä�', 'Ä“' => 'Ä’', 'Ä•' => 'Ä”', 'Ä—' => 'Ä–', 'Ä™' => 'Ä˜', 'Ä›' => 'Äš', 'Ä�' => 'Äœ', 'ÄŸ' => 'Äž', 'Ä¡' => 'Ä ', 'Ä£' => 'Ä¢', 'Ä¥' => 'Ä¤', 'Ä§' => 'Ä¦', 'Ä©' => 'Ä¨', 'Ä«' => 'Äª', 'Ä­' => 'Ä¬', 'Ä¯' => 'Ä®', 'Ä±' => 'I', 'Ä³' => 'Ä²', 'Äµ' => 'Ä´', 'Ä·' => 'Ä¶', 'Äº' => 'Ä¹', 'Ä¼' => 'Ä»', 'Ä¾' => 'Ä½', 'Å€' => 'Ä¿', 'Å‚' => 'Å�', 'Å„' => 'Åƒ', 'Å†' => 'Å…', 'Åˆ' => 'Å‡', 'Å‹' => 'ÅŠ', 'Å�' => 'ÅŒ', 'Å�' => 'ÅŽ', 'Å‘' => 'Å�', 'Å“' => 'Å’', 'Å•' => 'Å”', 'Å—' => 'Å–', 'Å™' => 'Å˜', 'Å›' => 'Åš', 'Å�' => 'Åœ', 'ÅŸ' => 'Åž', 'Å¡' => 'Å ', 'Å£' => 'Å¢', 'Å¥' => 'Å¤', 'Å§' => 'Å¦', 'Å©' => 'Å¨', 'Å«' => 'Åª', 'Å­' => 'Å¬', 'Å¯' => 'Å®', 'Å±' => 'Å°', 'Å³' => 'Å²', 'Åµ' => 'Å´', 'Å·' => 'Å¶', 'Åº' => 'Å¹', 'Å¼' => 'Å»', 'Å¾' => 'Å½', 'Å¿' => 'S', 'Æ€' => 'Éƒ', 'Æƒ' => 'Æ‚', 'Æ…' => 'Æ„', 'Æˆ' => 'Æ‡', 'ÆŒ' => 'Æ‹', 'Æ’' => 'Æ‘', 'Æ•' => 'Ç¶', 'Æ™' => 'Æ˜', 'Æš' => 'È½', 'Æž' => 'È ', 'Æ¡' => 'Æ ', 'Æ£' => 'Æ¢', 'Æ¥' => 'Æ¤', 'Æ¨' => 'Æ§', 'Æ­' => 'Æ¬', 'Æ°' => 'Æ¯', 'Æ´' => 'Æ³', 'Æ¶' => 'Æµ', 'Æ¹' => 'Æ¸', 'Æ½' => 'Æ¼', 'Æ¿' => 'Ç·', 'Ç…' => 'Ç„', 'Ç†' => 'Ç„', 'Çˆ' => 'Ç‡', 'Ç‰' => 'Ç‡', 'Ç‹' => 'ÇŠ', 'ÇŒ' => 'ÇŠ', 'ÇŽ' => 'Ç�', 'Ç�' => 'Ç�', 'Ç’' => 'Ç‘', 'Ç”' => 'Ç“', 'Ç–' => 'Ç•', 'Ç˜' => 'Ç—', 'Çš' => 'Ç™', 'Çœ' => 'Ç›', 'Ç�' => 'ÆŽ', 'ÇŸ' => 'Çž', 'Ç¡' => 'Ç ', 'Ç£' => 'Ç¢', 'Ç¥' => 'Ç¤', 'Ç§' => 'Ç¦', 'Ç©' => 'Ç¨', 'Ç«' => 'Çª', 'Ç­' => 'Ç¬', 'Ç¯' => 'Ç®', 'Ç²' => 'Ç±', 'Ç³' => 'Ç±', 'Çµ' => 'Ç´', 'Ç¹' => 'Ç¸', 'Ç»' => 'Çº', 'Ç½' => 'Ç¼', 'Ç¿' => 'Ç¾', 'È�' => 'È€', 'Èƒ' => 'È‚', 'È…' => 'È„', 'È‡' => 'È†', 'È‰' => 'Èˆ', 'È‹' => 'ÈŠ', 'È�' => 'ÈŒ', 'È�' => 'ÈŽ', 'È‘' => 'È�', 'È“' => 'È’', 'È•' => 'È”', 'È—' => 'È–', 'È™' => 'È˜', 'È›' => 'Èš', 'È�' => 'Èœ', 'ÈŸ' => 'Èž', 'È£' => 'È¢', 'È¥' => 'È¤', 'È§' => 'È¦', 'È©' => 'È¨', 'È«' => 'Èª', 'È­' => 'È¬', 'È¯' => 'È®', 'È±' => 'È°', 'È³' => 'È²', 'È¼' => 'È»', 'È¿' => 'â±¾', 'É€' => 'â±¿', 'É‚' => 'É�', 'É‡' => 'É†', 'É‰' => 'Éˆ', 'É‹' => 'ÉŠ', 'É�' => 'ÉŒ', 'É�' => 'ÉŽ', 'É�' => 'â±¯', 'É‘' => 'â±­', 'É’' => 'â±°', 'É“' => 'Æ�', 'É”' => 'Æ†', 'É–' => 'Æ‰', 'É—' => 'ÆŠ', 'É™' => 'Æ�', 'É›' => 'Æ�', 'Éœ' => 'êž«', 'É ' => 'Æ“', 'É¡' => 'êž¬', 'É£' => 'Æ”', 'É¥' => 'êž�', 'É¦' => 'êžª', 'É¨' => 'Æ—', 'É©' => 'Æ–', 'Éª' => 'êž®', 'É«' => 'â±¢', 'É¬' => 'êž­', 'É¯' => 'Æœ', 'É±' => 'â±®', 'É²' => 'Æ�', 'Éµ' => 'ÆŸ', 'É½' => 'â±¤', 'Ê€' => 'Æ¦', 'Ê‚' => 'êŸ…', 'Êƒ' => 'Æ©', 'Ê‡' => 'êž±', 'Êˆ' => 'Æ®', 'Ê‰' => 'É„', 'ÊŠ' => 'Æ±', 'Ê‹' => 'Æ²', 'ÊŒ' => 'É…', 'Ê’' => 'Æ·', 'Ê�' => 'êž²', 'Êž' => 'êž°', 'Í…' => 'Î™', 'Í±' => 'Í°', 'Í³' => 'Í²', 'Í·' => 'Í¶', 'Í»' => 'Ï½', 'Í¼' => 'Ï¾', 'Í½' => 'Ï¿', 'Î¬' => 'Î†', 'Î­' => 'Îˆ', 'Î®' => 'Î‰', 'Î¯' => 'ÎŠ', 'Î±' => 'Î‘', 'Î²' => 'Î’', 'Î³' => 'Î“', 'Î´' => 'Î”', 'Îµ' => 'Î•', 'Î¶' => 'Î–', 'Î·' => 'Î—', 'Î¸' => 'Î˜', 'Î¹' => 'Î™', 'Îº' => 'Îš', 'Î»' => 'Î›', 'Î¼' => 'Îœ', 'Î½' => 'Î�', 'Î¾' => 'Îž', 'Î¿' => 'ÎŸ', 'Ï€' => 'Î ', 'Ï�' => 'Î¡', 'Ï‚' => 'Î£', 'Ïƒ' => 'Î£', 'Ï„' => 'Î¤', 'Ï…' => 'Î¥', 'Ï†' => 'Î¦', 'Ï‡' => 'Î§', 'Ïˆ' => 'Î¨', 'Ï‰' => 'Î©', 'ÏŠ' => 'Îª', 'Ï‹' => 'Î«', 'ÏŒ' => 'ÎŒ', 'Ï�' => 'ÎŽ', 'ÏŽ' => 'Î�', 'Ï�' => 'Î’', 'Ï‘' => 'Î˜', 'Ï•' => 'Î¦', 'Ï–' => 'Î ', 'Ï—' => 'Ï�', 'Ï™' => 'Ï˜', 'Ï›' => 'Ïš', 'Ï�' => 'Ïœ', 'ÏŸ' => 'Ïž', 'Ï¡' => 'Ï ', 'Ï£' => 'Ï¢', 'Ï¥' => 'Ï¤', 'Ï§' => 'Ï¦', 'Ï©' => 'Ï¨', 'Ï«' => 'Ïª', 'Ï­' => 'Ï¬', 'Ï¯' => 'Ï®', 'Ï°' => 'Îš', 'Ï±' => 'Î¡', 'Ï²' => 'Ï¹', 'Ï³' => 'Í¿', 'Ïµ' => 'Î•', 'Ï¸' => 'Ï·', 'Ï»' => 'Ïº', 'Ð°' => 'Ð�', 'Ð±' => 'Ð‘', 'Ð²' => 'Ð’', 'Ð³' => 'Ð“', 'Ð´' => 'Ð”', 'Ðµ' => 'Ð•', 'Ð¶' => 'Ð–', 'Ð·' => 'Ð—', 'Ð¸' => 'Ð˜', 'Ð¹' => 'Ð™', 'Ðº' => 'Ðš', 'Ð»' => 'Ð›', 'Ð¼' => 'Ðœ', 'Ð½' => 'Ð�', 'Ð¾' => 'Ðž', 'Ð¿' => 'ÐŸ', 'Ñ€' => 'Ð ', 'Ñ�' => 'Ð¡', 'Ñ‚' => 'Ð¢', 'Ñƒ' => 'Ð£', 'Ñ„' => 'Ð¤', 'Ñ…' => 'Ð¥', 'Ñ†' => 'Ð¦', 'Ñ‡' => 'Ð§', 'Ñˆ' => 'Ð¨', 'Ñ‰' => 'Ð©', 'ÑŠ' => 'Ðª', 'Ñ‹' => 'Ð«', 'ÑŒ' => 'Ð¬', 'Ñ�' => 'Ð­', 'ÑŽ' => 'Ð®', 'Ñ�' => 'Ð¯', 'Ñ�' => 'Ð€', 'Ñ‘' => 'Ð�', 'Ñ’' => 'Ð‚', 'Ñ“' => 'Ðƒ', 'Ñ”' => 'Ð„', 'Ñ•' => 'Ð…', 'Ñ–' => 'Ð†', 'Ñ—' => 'Ð‡', 'Ñ˜' => 'Ðˆ', 'Ñ™' => 'Ð‰', 'Ñš' => 'ÐŠ', 'Ñ›' => 'Ð‹', 'Ñœ' => 'ÐŒ', 'Ñ�' => 'Ð�', 'Ñž' => 'ÐŽ', 'ÑŸ' => 'Ð�', 'Ñ¡' => 'Ñ ', 'Ñ£' => 'Ñ¢', 'Ñ¥' => 'Ñ¤', 'Ñ§' => 'Ñ¦', 'Ñ©' => 'Ñ¨', 'Ñ«' => 'Ñª', 'Ñ­' => 'Ñ¬', 'Ñ¯' => 'Ñ®', 'Ñ±' => 'Ñ°', 'Ñ³' => 'Ñ²', 'Ñµ' => 'Ñ´', 'Ñ·' => 'Ñ¶', 'Ñ¹' => 'Ñ¸', 'Ñ»' => 'Ñº', 'Ñ½' => 'Ñ¼', 'Ñ¿' => 'Ñ¾', 'Ò�' => 'Ò€', 'Ò‹' => 'ÒŠ', 'Ò�' => 'ÒŒ', 'Ò�' => 'ÒŽ', 'Ò‘' => 'Ò�', 'Ò“' => 'Ò’', 'Ò•' => 'Ò”', 'Ò—' => 'Ò–', 'Ò™' => 'Ò˜', 'Ò›' => 'Òš', 'Ò�' => 'Òœ', 'ÒŸ' => 'Òž', 'Ò¡' => 'Ò ', 'Ò£' => 'Ò¢', 'Ò¥' => 'Ò¤', 'Ò§' => 'Ò¦', 'Ò©' => 'Ò¨', 'Ò«' => 'Òª', 'Ò­' => 'Ò¬', 'Ò¯' => 'Ò®', 'Ò±' => 'Ò°', 'Ò³' => 'Ò²', 'Òµ' => 'Ò´', 'Ò·' => 'Ò¶', 'Ò¹' => 'Ò¸', 'Ò»' => 'Òº', 'Ò½' => 'Ò¼', 'Ò¿' => 'Ò¾', 'Ó‚' => 'Ó�', 'Ó„' => 'Óƒ', 'Ó†' => 'Ó…', 'Óˆ' => 'Ó‡', 'ÓŠ' => 'Ó‰', 'ÓŒ' => 'Ó‹', 'ÓŽ' => 'Ó�', 'Ó�' => 'Ó€', 'Ó‘' => 'Ó�', 'Ó“' => 'Ó’', 'Ó•' => 'Ó”', 'Ó—' => 'Ó–', 'Ó™' => 'Ó˜', 'Ó›' => 'Óš', 'Ó�' => 'Óœ', 'ÓŸ' => 'Óž', 'Ó¡' => 'Ó ', 'Ó£' => 'Ó¢', 'Ó¥' => 'Ó¤', 'Ó§' => 'Ó¦', 'Ó©' => 'Ó¨', 'Ó«' => 'Óª', 'Ó­' => 'Ó¬', 'Ó¯' => 'Ó®', 'Ó±' => 'Ó°', 'Ó³' => 'Ó²', 'Óµ' => 'Ó´', 'Ó·' => 'Ó¶', 'Ó¹' => 'Ó¸', 'Ó»' => 'Óº', 'Ó½' => 'Ó¼', 'Ó¿' => 'Ó¾', 'Ô�' => 'Ô€', 'Ôƒ' => 'Ô‚', 'Ô…' => 'Ô„', 'Ô‡' => 'Ô†', 'Ô‰' => 'Ôˆ', 'Ô‹' => 'ÔŠ', 'Ô�' => 'ÔŒ', 'Ô�' => 'ÔŽ', 'Ô‘' => 'Ô�', 'Ô“' => 'Ô’', 'Ô•' => 'Ô”', 'Ô—' => 'Ô–', 'Ô™' => 'Ô˜', 'Ô›' => 'Ôš', 'Ô�' => 'Ôœ', 'ÔŸ' => 'Ôž', 'Ô¡' => 'Ô ', 'Ô£' => 'Ô¢', 'Ô¥' => 'Ô¤', 'Ô§' => 'Ô¦', 'Ô©' => 'Ô¨', 'Ô«' => 'Ôª', 'Ô­' => 'Ô¬', 'Ô¯' => 'Ô®', 'Õ¡' => 'Ô±', 'Õ¢' => 'Ô²', 'Õ£' => 'Ô³', 'Õ¤' => 'Ô´', 'Õ¥' => 'Ôµ', 'Õ¦' => 'Ô¶', 'Õ§' => 'Ô·', 'Õ¨' => 'Ô¸', 'Õ©' => 'Ô¹', 'Õª' => 'Ôº', 'Õ«' => 'Ô»', 'Õ¬' => 'Ô¼', 'Õ­' => 'Ô½', 'Õ®' => 'Ô¾', 'Õ¯' => 'Ô¿', 'Õ°' => 'Õ€', 'Õ±' => 'Õ�', 'Õ²' => 'Õ‚', 'Õ³' => 'Õƒ', 'Õ´' => 'Õ„', 'Õµ' => 'Õ…', 'Õ¶' => 'Õ†', 'Õ·' => 'Õ‡', 'Õ¸' => 'Õˆ', 'Õ¹' => 'Õ‰', 'Õº' => 'ÕŠ', 'Õ»' => 'Õ‹', 'Õ¼' => 'ÕŒ', 'Õ½' => 'Õ�', 'Õ¾' => 'ÕŽ', 'Õ¿' => 'Õ�', 'Ö€' => 'Õ�', 'Ö�' => 'Õ‘', 'Ö‚' => 'Õ’', 'Öƒ' => 'Õ“', 'Ö„' => 'Õ”', 'Ö…' => 'Õ•', 'Ö†' => 'Õ–', 'áƒ�' => 'á²�', 'áƒ‘' => 'á²‘', 'áƒ’' => 'á²’', 'áƒ“' => 'á²“', 'áƒ”' => 'á²”', 'áƒ•' => 'á²•', 'áƒ–' => 'á²–', 'áƒ—' => 'á²—', 'áƒ˜' => 'á²˜', 'áƒ™' => 'á²™', 'áƒš' => 'á²š', 'áƒ›' => 'á²›', 'áƒœ' => 'á²œ', 'áƒ�' => 'á²�', 'áƒž' => 'á²ž', 'áƒŸ' => 'á²Ÿ', 'áƒ ' => 'á² ', 'áƒ¡' => 'á²¡', 'áƒ¢' => 'á²¢', 'áƒ£' => 'á²£', 'áƒ¤' => 'á²¤', 'áƒ¥' => 'á²¥', 'áƒ¦' => 'á²¦', 'áƒ§' => 'á²§', 'áƒ¨' => 'á²¨', 'áƒ©' => 'á²©', 'áƒª' => 'á²ª', 'áƒ«' => 'á²«', 'áƒ¬' => 'á²¬', 'áƒ­' => 'á²­', 'áƒ®' => 'á²®', 'áƒ¯' => 'á²¯', 'áƒ°' => 'á²°', 'áƒ±' => 'á²±', 'áƒ²' => 'á²²', 'áƒ³' => 'á²³', 'áƒ´' => 'á²´', 'áƒµ' => 'á²µ', 'áƒ¶' => 'á²¶', 'áƒ·' => 'á²·', 'áƒ¸' => 'á²¸', 'áƒ¹' => 'á²¹', 'áƒº' => 'á²º', 'áƒ½' => 'á²½', 'áƒ¾' => 'á²¾', 'áƒ¿' => 'á²¿', 'á�¸' => 'á�°', 'á�¹' => 'á�±', 'á�º' => 'á�²', 'á�»' => 'á�³', 'á�¼' => 'á�´', 'á�½' => 'á�µ', 'á²€' => 'Ð’', 'á²�' => 'Ð”', 'á²‚' => 'Ðž', 'á²ƒ' => 'Ð¡', 'á²„' => 'Ð¢', 'á²…' => 'Ð¢', 'á²†' => 'Ðª', 'á²‡' => 'Ñ¢', 'á²ˆ' => 'ê™Š', 'áµ¹' => 'ê�½', 'áµ½' => 'â±£', 'á¶Ž' => 'êŸ†', 'á¸�' => 'á¸€', 'á¸ƒ' => 'á¸‚', 'á¸…' => 'á¸„', 'á¸‡' => 'á¸†', 'á¸‰' => 'á¸ˆ', 'á¸‹' => 'á¸Š', 'á¸�' => 'á¸Œ', 'á¸�' => 'á¸Ž', 'á¸‘' => 'á¸�', 'á¸“' => 'á¸’', 'á¸•' => 'á¸”', 'á¸—' => 'á¸–', 'á¸™' => 'á¸˜', 'á¸›' => 'á¸š', 'á¸�' => 'á¸œ', 'á¸Ÿ' => 'á¸ž', 'á¸¡' => 'á¸ ', 'á¸£' => 'á¸¢', 'á¸¥' => 'á¸¤', 'á¸§' => 'á¸¦', 'á¸©' => 'á¸¨', 'á¸«' => 'á¸ª', 'á¸­' => 'á¸¬', 'á¸¯' => 'á¸®', 'á¸±' => 'á¸°', 'á¸³' => 'á¸²', 'á¸µ' => 'á¸´', 'á¸·' => 'á¸¶', 'á¸¹' => 'á¸¸', 'á¸»' => 'á¸º', 'á¸½' => 'á¸¼', 'á¸¿' => 'á¸¾', 'á¹�' => 'á¹€', 'á¹ƒ' => 'á¹‚', 'á¹…' => 'á¹„', 'á¹‡' => 'á¹†', 'á¹‰' => 'á¹ˆ', 'á¹‹' => 'á¹Š', 'á¹�' => 'á¹Œ', 'á¹�' => 'á¹Ž', 'á¹‘' => 'á¹�', 'á¹“' => 'á¹’', 'á¹•' => 'á¹”', 'á¹—' => 'á¹–', 'á¹™' => 'á¹˜', 'á¹›' => 'á¹š', 'á¹�' => 'á¹œ', 'á¹Ÿ' => 'á¹ž', 'á¹¡' => 'á¹ ', 'á¹£' => 'á¹¢', 'á¹¥' => 'á¹¤', 'á¹§' => 'á¹¦', 'á¹©' => 'á¹¨', 'á¹«' => 'á¹ª', 'á¹­' => 'á¹¬', 'á¹¯' => 'á¹®', 'á¹±' => 'á¹°', 'á¹³' => 'á¹²', 'á¹µ' => 'á¹´', 'á¹·' => 'á¹¶', 'á¹¹' => 'á¹¸', 'á¹»' => 'á¹º', 'á¹½' => 'á¹¼', 'á¹¿' => 'á¹¾', 'áº�' => 'áº€', 'áºƒ' => 'áº‚', 'áº…' => 'áº„', 'áº‡' => 'áº†', 'áº‰' => 'áºˆ', 'áº‹' => 'áºŠ', 'áº�' => 'áºŒ', 'áº�' => 'áºŽ', 'áº‘' => 'áº�', 'áº“' => 'áº’', 'áº•' => 'áº”', 'áº›' => 'á¹ ', 'áº¡' => 'áº ', 'áº£' => 'áº¢', 'áº¥' => 'áº¤', 'áº§' => 'áº¦', 'áº©' => 'áº¨', 'áº«' => 'áºª', 'áº­' => 'áº¬', 'áº¯' => 'áº®', 'áº±' => 'áº°', 'áº³' => 'áº²', 'áºµ' => 'áº´', 'áº·' => 'áº¶', 'áº¹' => 'áº¸', 'áº»' => 'áºº', 'áº½' => 'áº¼', 'áº¿' => 'áº¾', 'á»�' => 'á»€', 'á»ƒ' => 'á»‚', 'á»…' => 'á»„', 'á»‡' => 'á»†', 'á»‰' => 'á»ˆ', 'á»‹' => 'á»Š', 'á»�' => 'á»Œ', 'á»�' => 'á»Ž', 'á»‘' => 'á»�', 'á»“' => 'á»’', 'á»•' => 'á»”', 'á»—' => 'á»–', 'á»™' => 'á»˜', 'á»›' => 'á»š', 'á»�' => 'á»œ', 'á»Ÿ' => 'á»ž', 'á»¡' => 'á» ', 'á»£' => 'á»¢', 'á»¥' => 'á»¤', 'á»§' => 'á»¦', 'á»©' => 'á»¨', 'á»«' => 'á»ª', 'á»­' => 'á»¬', 'á»¯' => 'á»®', 'á»±' => 'á»°', 'á»³' => 'á»²', 'á»µ' => 'á»´', 'á»·' => 'á»¶', 'á»¹' => 'á»¸', 'á»»' => 'á»º', 'á»½' => 'á»¼', 'á»¿' => 'á»¾', 'á¼€' => 'á¼ˆ', 'á¼�' => 'á¼‰', 'á¼‚' => 'á¼Š', 'á¼ƒ' => 'á¼‹', 'á¼„' => 'á¼Œ', 'á¼…' => 'á¼�', 'á¼†' => 'á¼Ž', 'á¼‡' => 'á¼�', 'á¼�' => 'á¼˜', 'á¼‘' => 'á¼™', 'á¼’' => 'á¼š', 'á¼“' => 'á¼›', 'á¼”' => 'á¼œ', 'á¼•' => 'á¼�', 'á¼ ' => 'á¼¨', 'á¼¡' => 'á¼©', 'á¼¢' => 'á¼ª', 'á¼£' => 'á¼«', 'á¼¤' => 'á¼¬', 'á¼¥' => 'á¼­', 'á¼¦' => 'á¼®', 'á¼§' => 'á¼¯', 'á¼°' => 'á¼¸', 'á¼±' => 'á¼¹', 'á¼²' => 'á¼º', 'á¼³' => 'á¼»', 'á¼´' => 'á¼¼', 'á¼µ' => 'á¼½', 'á¼¶' => 'á¼¾', 'á¼·' => 'á¼¿', 'á½€' => 'á½ˆ', 'á½�' => 'á½‰', 'á½‚' => 'á½Š', 'á½ƒ' => 'á½‹', 'á½„' => 'á½Œ', 'á½…' => 'á½�', 'á½‘' => 'á½™', 'á½“' => 'á½›', 'á½•' => 'á½�', 'á½—' => 'á½Ÿ', 'á½ ' => 'á½¨', 'á½¡' => 'á½©', 'á½¢' => 'á½ª', 'á½£' => 'á½«', 'á½¤' => 'á½¬', 'á½¥' => 'á½­', 'á½¦' => 'á½®', 'á½§' => 'á½¯', 'á½°' => 'á¾º', 'á½±' => 'á¾»', 'á½²' => 'á¿ˆ', 'á½³' => 'á¿‰', 'á½´' => 'á¿Š', 'á½µ' => 'á¿‹', 'á½¶' => 'á¿š', 'á½·' => 'á¿›', 'á½¸' => 'á¿¸', 'á½¹' => 'á¿¹', 'á½º' => 'á¿ª', 'á½»' => 'á¿«', 'á½¼' => 'á¿º', 'á½½' => 'á¿»', 'á¾€' => 'á¼ˆÎ™', 'á¾�' => 'á¼‰Î™', 'á¾‚' => 'á¼ŠÎ™', 'á¾ƒ' => 'á¼‹Î™', 'á¾„' => 'á¼ŒÎ™', 'á¾…' => 'á¼�Î™', 'á¾†' => 'á¼ŽÎ™', 'á¾‡' => 'á¼�Î™', 'á¾�' => 'á¼¨Î™', 'á¾‘' => 'á¼©Î™', 'á¾’' => 'á¼ªÎ™', 'á¾“' => 'á¼«Î™', 'á¾”' => 'á¼¬Î™', 'á¾•' => 'á¼­Î™', 'á¾–' => 'á¼®Î™', 'á¾—' => 'á¼¯Î™', 'á¾ ' => 'á½¨Î™', 'á¾¡' => 'á½©Î™', 'á¾¢' => 'á½ªÎ™', 'á¾£' => 'á½«Î™', 'á¾¤' => 'á½¬Î™', 'á¾¥' => 'á½­Î™', 'á¾¦' => 'á½®Î™', 'á¾§' => 'á½¯Î™', 'á¾°' => 'á¾¸', 'á¾±' => 'á¾¹', 'á¾³' => 'Î‘Î™', 'á¾¾' => 'Î™', 'á¿ƒ' => 'Î—Î™', 'á¿�' => 'á¿˜', 'á¿‘' => 'á¿™', 'á¿ ' => 'á¿¨', 'á¿¡' => 'á¿©', 'á¿¥' => 'á¿¬', 'á¿³' => 'Î©Î™', 'â…Ž' => 'â„²', 'â…°' => 'â… ', 'â…±' => 'â…¡', 'â…²' => 'â…¢', 'â…³' => 'â…£', 'â…´' => 'â…¤', 'â…µ' => 'â…¥', 'â…¶' => 'â…¦', 'â…·' => 'â…§', 'â…¸' => 'â…¨', 'â…¹' => 'â…©', 'â…º' => 'â…ª', 'â…»' => 'â…«', 'â…¼' => 'â…¬', 'â…½' => 'â…­', 'â…¾' => 'â…®', 'â…¿' => 'â…¯', 'â†„' => 'â†ƒ', 'â“�' => 'â’¶', 'â“‘' => 'â’·', 'â“’' => 'â’¸', 'â““' => 'â’¹', 'â“”' => 'â’º', 'â“•' => 'â’»', 'â“–' => 'â’¼', 'â“—' => 'â’½', 'â“˜' => 'â’¾', 'â“™' => 'â’¿', 'â“š' => 'â“€', 'â“›' => 'â“�', 'â“œ' => 'â“‚', 'â“�' => 'â“ƒ', 'â“ž' => 'â“„', 'â“Ÿ' => 'â“…', 'â“ ' => 'â“†', 'â“¡' => 'â“‡', 'â“¢' => 'â“ˆ', 'â“£' => 'â“‰', 'â“¤' => 'â“Š', 'â“¥' => 'â“‹', 'â“¦' => 'â“Œ', 'â“§' => 'â“�', 'â“¨' => 'â“Ž', 'â“©' => 'â“�', 'â°°' => 'â°€', 'â°±' => 'â°�', 'â°²' => 'â°‚', 'â°³' => 'â°ƒ', 'â°´' => 'â°„', 'â°µ' => 'â°…', 'â°¶' => 'â°†', 'â°·' => 'â°‡', 'â°¸' => 'â°ˆ', 'â°¹' => 'â°‰', 'â°º' => 'â°Š', 'â°»' => 'â°‹', 'â°¼' => 'â°Œ', 'â°½' => 'â°�', 'â°¾' => 'â°Ž', 'â°¿' => 'â°�', 'â±€' => 'â°�', 'â±�' => 'â°‘', 'â±‚' => 'â°’', 'â±ƒ' => 'â°“', 'â±„' => 'â°”', 'â±…' => 'â°•', 'â±†' => 'â°–', 'â±‡' => 'â°—', 'â±ˆ' => 'â°˜', 'â±‰' => 'â°™', 'â±Š' => 'â°š', 'â±‹' => 'â°›', 'â±Œ' => 'â°œ', 'â±�' => 'â°�', 'â±Ž' => 'â°ž', 'â±�' => 'â°Ÿ', 'â±�' => 'â° ', 'â±‘' => 'â°¡', 'â±’' => 'â°¢', 'â±“' => 'â°£', 'â±”' => 'â°¤', 'â±•' => 'â°¥', 'â±–' => 'â°¦', 'â±—' => 'â°§', 'â±˜' => 'â°¨', 'â±™' => 'â°©', 'â±š' => 'â°ª', 'â±›' => 'â°«', 'â±œ' => 'â°¬', 'â±�' => 'â°­', 'â±ž' => 'â°®', 'â±¡' => 'â± ', 'â±¥' => 'Èº', 'â±¦' => 'È¾', 'â±¨' => 'â±§', 'â±ª' => 'â±©', 'â±¬' => 'â±«', 'â±³' => 'â±²', 'â±¶' => 'â±µ', 'â²�' => 'â²€', 'â²ƒ' => 'â²‚', 'â²…' => 'â²„', 'â²‡' => 'â²†', 'â²‰' => 'â²ˆ', 'â²‹' => 'â²Š', 'â²�' => 'â²Œ', 'â²�' => 'â²Ž', 'â²‘' => 'â²�', 'â²“' => 'â²’', 'â²•' => 'â²”', 'â²—' => 'â²–', 'â²™' => 'â²˜', 'â²›' => 'â²š', 'â²�' => 'â²œ', 'â²Ÿ' => 'â²ž', 'â²¡' => 'â² ', 'â²£' => 'â²¢', 'â²¥' => 'â²¤', 'â²§' => 'â²¦', 'â²©' => 'â²¨', 'â²«' => 'â²ª', 'â²­' => 'â²¬', 'â²¯' => 'â²®', 'â²±' => 'â²°', 'â²³' => 'â²²', 'â²µ' => 'â²´', 'â²·' => 'â²¶', 'â²¹' => 'â²¸', 'â²»' => 'â²º', 'â²½' => 'â²¼', 'â²¿' => 'â²¾', 'â³�' => 'â³€', 'â³ƒ' => 'â³‚', 'â³…' => 'â³„', 'â³‡' => 'â³†', 'â³‰' => 'â³ˆ', 'â³‹' => 'â³Š', 'â³�' => 'â³Œ', 'â³�' => 'â³Ž', 'â³‘' => 'â³�', 'â³“' => 'â³’', 'â³•' => 'â³”', 'â³—' => 'â³–', 'â³™' => 'â³˜', 'â³›' => 'â³š', 'â³�' => 'â³œ', 'â³Ÿ' => 'â³ž', 'â³¡' => 'â³ ', 'â³£' => 'â³¢', 'â³¬' => 'â³«', 'â³®' => 'â³­', 'â³³' => 'â³²', 'â´€' => 'á‚ ', 'â´�' => 'á‚¡', 'â´‚' => 'á‚¢', 'â´ƒ' => 'á‚£', 'â´„' => 'á‚¤', 'â´…' => 'á‚¥', 'â´†' => 'á‚¦', 'â´‡' => 'á‚§', 'â´ˆ' => 'á‚¨', 'â´‰' => 'á‚©', 'â´Š' => 'á‚ª', 'â´‹' => 'á‚«', 'â´Œ' => 'á‚¬', 'â´�' => 'á‚­', 'â´Ž' => 'á‚®', 'â´�' => 'á‚¯', 'â´�' => 'á‚°', 'â´‘' => 'á‚±', 'â´’' => 'á‚²', 'â´“' => 'á‚³', 'â´”' => 'á‚´', 'â´•' => 'á‚µ', 'â´–' => 'á‚¶', 'â´—' => 'á‚·', 'â´˜' => 'á‚¸', 'â´™' => 'á‚¹', 'â´š' => 'á‚º', 'â´›' => 'á‚»', 'â´œ' => 'á‚¼', 'â´�' => 'á‚½', 'â´ž' => 'á‚¾', 'â´Ÿ' => 'á‚¿', 'â´ ' => 'áƒ€', 'â´¡' => 'áƒ�', 'â´¢' => 'áƒ‚', 'â´£' => 'áƒƒ', 'â´¤' => 'áƒ„', 'â´¥' => 'áƒ…', 'â´§' => 'áƒ‡', 'â´­' => 'áƒ�', 'ê™�' => 'ê™€', 'ê™ƒ' => 'ê™‚', 'ê™…' => 'ê™„', 'ê™‡' => 'ê™†', 'ê™‰' => 'ê™ˆ', 'ê™‹' => 'ê™Š', 'ê™�' => 'ê™Œ', 'ê™�' => 'ê™Ž', 'ê™‘' => 'ê™�', 'ê™“' => 'ê™’', 'ê™•' => 'ê™”', 'ê™—' => 'ê™–', 'ê™™' => 'ê™˜', 'ê™›' => 'ê™š', 'ê™�' => 'ê™œ', 'ê™Ÿ' => 'ê™ž', 'ê™¡' => 'ê™ ', 'ê™£' => 'ê™¢', 'ê™¥' => 'ê™¤', 'ê™§' => 'ê™¦', 'ê™©' => 'ê™¨', 'ê™«' => 'ê™ª', 'ê™­' => 'ê™¬', 'êš�' => 'êš€', 'êšƒ' => 'êš‚', 'êš…' => 'êš„', 'êš‡' => 'êš†', 'êš‰' => 'êšˆ', 'êš‹' => 'êšŠ', 'êš�' => 'êšŒ', 'êš�' => 'êšŽ', 'êš‘' => 'êš�', 'êš“' => 'êš’', 'êš•' => 'êš”', 'êš—' => 'êš–', 'êš™' => 'êš˜', 'êš›' => 'êšš', 'êœ£' => 'êœ¢', 'êœ¥' => 'êœ¤', 'êœ§' => 'êœ¦', 'êœ©' => 'êœ¨', 'êœ«' => 'êœª', 'êœ­' => 'êœ¬', 'êœ¯' => 'êœ®', 'êœ³' => 'êœ²', 'êœµ' => 'êœ´', 'êœ·' => 'êœ¶', 'êœ¹' => 'êœ¸', 'êœ»' => 'êœº', 'êœ½' => 'êœ¼', 'êœ¿' => 'êœ¾', 'ê��' => 'ê�€', 'ê�ƒ' => 'ê�‚', 'ê�…' => 'ê�„', 'ê�‡' => 'ê�†', 'ê�‰' => 'ê�ˆ', 'ê�‹' => 'ê�Š', 'ê��' => 'ê�Œ', 'ê��' => 'ê�Ž', 'ê�‘' => 'ê��', 'ê�“' => 'ê�’', 'ê�•' => 'ê�”', 'ê�—' => 'ê�–', 'ê�™' => 'ê�˜', 'ê�›' => 'ê�š', 'ê��' => 'ê�œ', 'ê�Ÿ' => 'ê�ž', 'ê�¡' => 'ê� ', 'ê�£' => 'ê�¢', 'ê�¥' => 'ê�¤', 'ê�§' => 'ê�¦', 'ê�©' => 'ê�¨', 'ê�«' => 'ê�ª', 'ê�­' => 'ê�¬', 'ê�¯' => 'ê�®', 'ê�º' => 'ê�¹', 'ê�¼' => 'ê�»', 'ê�¿' => 'ê�¾', 'êž�' => 'êž€', 'êžƒ' => 'êž‚', 'êž…' => 'êž„', 'êž‡' => 'êž†', 'êžŒ' => 'êž‹', 'êž‘' => 'êž�', 'êž“' => 'êž’', 'êž”' => 'êŸ„', 'êž—' => 'êž–', 'êž™' => 'êž˜', 'êž›' => 'êžš', 'êž�' => 'êžœ', 'êžŸ' => 'êžž', 'êž¡' => 'êž ', 'êž£' => 'êž¢', 'êž¥' => 'êž¤', 'êž§' => 'êž¦', 'êž©' => 'êž¨', 'êžµ' => 'êž´', 'êž·' => 'êž¶', 'êž¹' => 'êž¸', 'êž»' => 'êžº', 'êž½' => 'êž¼', 'êž¿' => 'êž¾', 'êŸƒ' => 'êŸ‚', 'êŸˆ' => 'êŸ‡', 'êŸŠ' => 'êŸ‰', 'êŸ¶' => 'êŸµ', 'ê­“' => 'êž³', 'ê­°' => 'áŽ ', 'ê­±' => 'áŽ¡', 'ê­²' => 'áŽ¢', 'ê­³' => 'áŽ£', 'ê­´' => 'áŽ¤', 'ê­µ' => 'áŽ¥', 'ê­¶' => 'áŽ¦', 'ê­·' => 'áŽ§', 'ê­¸' => 'áŽ¨', 'ê­¹' => 'áŽ©', 'ê­º' => 'áŽª', 'ê­»' => 'áŽ«', 'ê­¼' => 'áŽ¬', 'ê­½' => 'áŽ­', 'ê­¾' => 'áŽ®', 'ê­¿' => 'áŽ¯', 'ê®€' => 'áŽ°', 'ê®�' => 'áŽ±', 'ê®‚' => 'áŽ²', 'ê®ƒ' => 'áŽ³', 'ê®„' => 'áŽ´', 'ê®…' => 'áŽµ', 'ê®†' => 'áŽ¶', 'ê®‡' => 'áŽ·', 'ê®ˆ' => 'áŽ¸', 'ê®‰' => 'áŽ¹', 'ê®Š' => 'áŽº', 'ê®‹' => 'áŽ»', 'ê®Œ' => 'áŽ¼', 'ê®�' => 'áŽ½', 'ê®Ž' => 'áŽ¾', 'ê®�' => 'áŽ¿', 'ê®�' => 'á�€', 'ê®‘' => 'á��', 'ê®’' => 'á�‚', 'ê®“' => 'á�ƒ', 'ê®”' => 'á�„', 'ê®•' => 'á�…', 'ê®–' => 'á�†', 'ê®—' => 'á�‡', 'ê®˜' => 'á�ˆ', 'ê®™' => 'á�‰', 'ê®š' => 'á�Š', 'ê®›' => 'á�‹', 'ê®œ' => 'á�Œ', 'ê®�' => 'á��', 'ê®ž' => 'á�Ž', 'ê®Ÿ' => 'á��', 'ê® ' => 'á��', 'ê®¡' => 'á�‘', 'ê®¢' => 'á�’', 'ê®£' => 'á�“', 'ê®¤' => 'á�”', 'ê®¥' => 'á�•', 'ê®¦' => 'á�–', 'ê®§' => 'á�—', 'ê®¨' => 'á�˜', 'ê®©' => 'á�™', 'ê®ª' => 'á�š', 'ê®«' => 'á�›', 'ê®¬' => 'á�œ', 'ê®­' => 'á��', 'ê®®' => 'á�ž', 'ê®¯' => 'á�Ÿ', 'ê®°' => 'á� ', 'ê®±' => 'á�¡', 'ê®²' => 'á�¢', 'ê®³' => 'á�£', 'ê®´' => 'á�¤', 'ê®µ' => 'á�¥', 'ê®¶' => 'á�¦', 'ê®·' => 'á�§', 'ê®¸' => 'á�¨', 'ê®¹' => 'á�©', 'ê®º' => 'á�ª', 'ê®»' => 'á�«', 'ê®¼' => 'á�¬', 'ê®½' => 'á�­', 'ê®¾' => 'á�®', 'ê®¿' => 'á�¯', 'ï½�' => 'ï¼¡', 'ï½‚' => 'ï¼¢', 'ï½ƒ' => 'ï¼£', 'ï½„' => 'ï¼¤', 'ï½…' => 'ï¼¥', 'ï½†' => 'ï¼¦', 'ï½‡' => 'ï¼§', 'ï½ˆ' => 'ï¼¨', 'ï½‰' => 'ï¼©', 'ï½Š' => 'ï¼ª', 'ï½‹' => 'ï¼«', 'ï½Œ' => 'ï¼¬', 'ï½�' => 'ï¼­', 'ï½Ž' => 'ï¼®', 'ï½�' => 'ï¼¯', 'ï½�' => 'ï¼°', 'ï½‘' => 'ï¼±', 'ï½’' => 'ï¼²', 'ï½“' => 'ï¼³', 'ï½”' => 'ï¼´', 'ï½•' => 'ï¼µ', 'ï½–' => 'ï¼¶', 'ï½—' => 'ï¼·', 'ï½˜' => 'ï¼¸', 'ï½™' => 'ï¼¹', 'ï½š' => 'ï¼º', 'ð��¨' => 'ð��€', 'ð��©' => 'ð���', 'ð��ª' => 'ð��‚', 'ð��«' => 'ð��ƒ', 'ð��¬' => 'ð��„', 'ð��­' => 'ð��…', 'ð��®' => 'ð��†', 'ð��¯' => 'ð��‡', 'ð��°' => 'ð��ˆ', 'ð��±' => 'ð��‰', 'ð��²' => 'ð��Š', 'ð��³' => 'ð��‹', 'ð��´' => 'ð��Œ', 'ð��µ' => 'ð���', 'ð��¶' => 'ð��Ž', 'ð��·' => 'ð���', 'ð��¸' => 'ð���', 'ð��¹' => 'ð��‘', 'ð��º' => 'ð��’', 'ð��»' => 'ð��“', 'ð��¼' => 'ð��”', 'ð��½' => 'ð��•', 'ð��¾' => 'ð��–', 'ð��¿' => 'ð��—', 'ð�‘€' => 'ð��˜', 'ð�‘�' => 'ð��™', 'ð�‘‚' => 'ð��š', 'ð�‘ƒ' => 'ð��›', 'ð�‘„' => 'ð��œ', 'ð�‘…' => 'ð���', 'ð�‘†' => 'ð��ž', 'ð�‘‡' => 'ð��Ÿ', 'ð�‘ˆ' => 'ð�� ', 'ð�‘‰' => 'ð��¡', 'ð�‘Š' => 'ð��¢', 'ð�‘‹' => 'ð��£', 'ð�‘Œ' => 'ð��¤', 'ð�‘�' => 'ð��¥', 'ð�‘Ž' => 'ð��¦', 'ð�‘�' => 'ð��§', 'ð�“˜' => 'ð�’°', 'ð�“™' => 'ð�’±', 'ð�“š' => 'ð�’²', 'ð�“›' => 'ð�’³', 'ð�“œ' => 'ð�’´', 'ð�“�' => 'ð�’µ', 'ð�“ž' => 'ð�’¶', 'ð�“Ÿ' => 'ð�’·', 'ð�“ ' => 'ð�’¸', 'ð�“¡' => 'ð�’¹', 'ð�“¢' => 'ð�’º', 'ð�“£' => 'ð�’»', 'ð�“¤' => 'ð�’¼', 'ð�“¥' => 'ð�’½', 'ð�“¦' => 'ð�’¾', 'ð�“§' => 'ð�’¿', 'ð�“¨' => 'ð�“€', 'ð�“©' => 'ð�“�', 'ð�“ª' => 'ð�“‚', 'ð�“«' => 'ð�“ƒ', 'ð�“¬' => 'ð�“„', 'ð�“­' => 'ð�“…', 'ð�“®' => 'ð�“†', 'ð�“¯' => 'ð�“‡', 'ð�“°' => 'ð�“ˆ', 'ð�“±' => 'ð�“‰', 'ð�“²' => 'ð�“Š', 'ð�“³' => 'ð�“‹', 'ð�“´' => 'ð�“Œ', 'ð�“µ' => 'ð�“�', 'ð�“¶' => 'ð�“Ž', 'ð�“·' => 'ð�“�', 'ð�“¸' => 'ð�“�', 'ð�“¹' => 'ð�“‘', 'ð�“º' => 'ð�“’', 'ð�“»' => 'ð�““', 'ð�³€' => 'ð�²€', 'ð�³�' => 'ð�²�', 'ð�³‚' => 'ð�²‚', 'ð�³ƒ' => 'ð�²ƒ', 'ð�³„' => 'ð�²„', 'ð�³…' => 'ð�²…', 'ð�³†' => 'ð�²†', 'ð�³‡' => 'ð�²‡', 'ð�³ˆ' => 'ð�²ˆ', 'ð�³‰' => 'ð�²‰', 'ð�³Š' => 'ð�²Š', 'ð�³‹' => 'ð�²‹', 'ð�³Œ' => 'ð�²Œ', 'ð�³�' => 'ð�²�', 'ð�³Ž' => 'ð�²Ž', 'ð�³�' => 'ð�²�', 'ð�³�' => 'ð�²�', 'ð�³‘' => 'ð�²‘', 'ð�³’' => 'ð�²’', 'ð�³“' => 'ð�²“', 'ð�³”' => 'ð�²”', 'ð�³•' => 'ð�²•', 'ð�³–' => 'ð�²–', 'ð�³—' => 'ð�²—', 'ð�³˜' => 'ð�²˜', 'ð�³™' => 'ð�²™', 'ð�³š' => 'ð�²š', 'ð�³›' => 'ð�²›', 'ð�³œ' => 'ð�²œ', 'ð�³�' => 'ð�²�', 'ð�³ž' => 'ð�²ž', 'ð�³Ÿ' => 'ð�²Ÿ', 'ð�³ ' => 'ð�² ', 'ð�³¡' => 'ð�²¡', 'ð�³¢' => 'ð�²¢', 'ð�³£' => 'ð�²£', 'ð�³¤' => 'ð�²¤', 'ð�³¥' => 'ð�²¥', 'ð�³¦' => 'ð�²¦', 'ð�³§' => 'ð�²§', 'ð�³¨' => 'ð�²¨', 'ð�³©' => 'ð�²©', 'ð�³ª' => 'ð�²ª', 'ð�³«' => 'ð�²«', 'ð�³¬' => 'ð�²¬', 'ð�³­' => 'ð�²­', 'ð�³®' => 'ð�²®', 'ð�³¯' => 'ð�²¯', 'ð�³°' => 'ð�²°', 'ð�³±' => 'ð�²±', 'ð�³²' => 'ð�²²', 'ð‘£€' => 'ð‘¢ ', 'ð‘£�' => 'ð‘¢¡', 'ð‘£‚' => 'ð‘¢¢', 'ð‘£ƒ' => 'ð‘¢£', 'ð‘£„' => 'ð‘¢¤', 'ð‘£…' => 'ð‘¢¥', 'ð‘£†' => 'ð‘¢¦', 'ð‘£‡' => 'ð‘¢§', 'ð‘£ˆ' => 'ð‘¢¨', 'ð‘£‰' => 'ð‘¢©', 'ð‘£Š' => 'ð‘¢ª', 'ð‘£‹' => 'ð‘¢«', 'ð‘£Œ' => 'ð‘¢¬', 'ð‘£�' => 'ð‘¢­', 'ð‘£Ž' => 'ð‘¢®', 'ð‘£�' => 'ð‘¢¯', 'ð‘£�' => 'ð‘¢°', 'ð‘£‘' => 'ð‘¢±', 'ð‘£’' => 'ð‘¢²', 'ð‘£“' => 'ð‘¢³', 'ð‘£”' => 'ð‘¢´', 'ð‘£•' => 'ð‘¢µ', 'ð‘£–' => 'ð‘¢¶', 'ð‘£—' => 'ð‘¢·', 'ð‘£˜' => 'ð‘¢¸', 'ð‘£™' => 'ð‘¢¹', 'ð‘£š' => 'ð‘¢º', 'ð‘£›' => 'ð‘¢»', 'ð‘£œ' => 'ð‘¢¼', 'ð‘£�' => 'ð‘¢½', 'ð‘£ž' => 'ð‘¢¾', 'ð‘£Ÿ' => 'ð‘¢¿', 'ð–¹ ' => 'ð–¹€', 'ð–¹¡' => 'ð–¹�', 'ð–¹¢' => 'ð–¹‚', 'ð–¹£' => 'ð–¹ƒ', 'ð–¹¤' => 'ð–¹„', 'ð–¹¥' => 'ð–¹…', 'ð–¹¦' => 'ð–¹†', 'ð–¹§' => 'ð–¹‡', 'ð–¹¨' => 'ð–¹ˆ', 'ð–¹©' => 'ð–¹‰', 'ð–¹ª' => 'ð–¹Š', 'ð–¹«' => 'ð–¹‹', 'ð–¹¬' => 'ð–¹Œ', 'ð–¹­' => 'ð–¹�', 'ð–¹®' => 'ð–¹Ž', 'ð–¹¯' => 'ð–¹�', 'ð–¹°' => 'ð–¹�', 'ð–¹±' => 'ð–¹‘', 'ð–¹²' => 'ð–¹’', 'ð–¹³' => 'ð–¹“', 'ð–¹´' => 'ð–¹”', 'ð–¹µ' => 'ð–¹•', 'ð–¹¶' => 'ð–¹–', 'ð–¹·' => 'ð–¹—', 'ð–¹¸' => 'ð–¹˜', 'ð–¹¹' => 'ð–¹™', 'ð–¹º' => 'ð–¹š', 'ð–¹»' => 'ð–¹›', 'ð–¹¼' => 'ð–¹œ', 'ð–¹½' => 'ð–¹�', 'ð–¹¾' => 'ð–¹ž', 'ð–¹¿' => 'ð–¹Ÿ', 'ðž¤¢' => 'ðž¤€', 'ðž¤£' => 'ðž¤�', 'ðž¤¤' => 'ðž¤‚', 'ðž¤¥' => 'ðž¤ƒ', 'ðž¤¦' => 'ðž¤„', 'ðž¤§' => 'ðž¤…', 'ðž¤¨' => 'ðž¤†', 'ðž¤©' => 'ðž¤‡', 'ðž¤ª' => 'ðž¤ˆ', 'ðž¤«' => 'ðž¤‰', 'ðž¤¬' => 'ðž¤Š', 'ðž¤­' => 'ðž¤‹', 'ðž¤®' => 'ðž¤Œ', 'ðž¤¯' => 'ðž¤�', 'ðž¤°' => 'ðž¤Ž', 'ðž¤±' => 'ðž¤�', 'ðž¤²' => 'ðž¤�', 'ðž¤³' => 'ðž¤‘', 'ðž¤´' => 'ðž¤’', 'ðž¤µ' => 'ðž¤“', 'ðž¤¶' => 'ðž¤”', 'ðž¤·' => 'ðž¤•', 'ðž¤¸' => 'ðž¤–', 'ðž¤¹' => 'ðž¤—', 'ðž¤º' => 'ðž¤˜', 'ðž¤»' => 'ðž¤™', 'ðž¤¼' => 'ðž¤š', 'ðž¤½' => 'ðž¤›', 'ðž¤¾' => 'ðž¤œ', 'ðž¤¿' => 'ðž¤�', 'ðž¥€' => 'ðž¤ž', 'ðž¥�' => 'ðž¤Ÿ', 'ðž¥‚' => 'ðž¤ ', 'ðž¥ƒ' => 'ðž¤¡', 'ÃŸ' => 'SS', 'ï¬€' => 'FF', 'ï¬�' => 'FI', 'ï¬‚' => 'FL', 'ï¬ƒ' => 'FFI', 'ï¬„' => 'FFL', 'ï¬…' => 'ST', 'ï¬†' => 'ST', 'Ö‡' => 'ÔµÕ’', 'ï¬“' => 'Õ„Õ†', 'ï¬”' => 'Õ„Ôµ', 'ï¬•' => 'Õ„Ô»', 'ï¬–' => 'ÕŽÕ†', 'ï¬—' => 'Õ„Ô½', 'Å‰' => 'Ê¼N', 'Î�' => 'Î™ÌˆÌ�', 'Î°' => 'Î¥ÌˆÌ�', 'Ç°' => 'JÌŒ', 'áº–' => 'HÌ±', 'áº—' => 'TÌˆ', 'áº˜' => 'WÌŠ', 'áº™' => 'YÌŠ', 'áºš' => 'AÊ¾', 'á½�' => 'Î¥Ì“', 'á½’' => 'Î¥Ì“Ì€', 'á½”' => 'Î¥Ì“Ì�', 'á½–' => 'Î¥Ì“Í‚', 'á¾¶' => 'Î‘Í‚', 'á¿†' => 'Î—Í‚', 'á¿’' => 'Î™ÌˆÌ€', 'á¿“' => 'Î™ÌˆÌ�', 'á¿–' => 'Î™Í‚', 'á¿—' => 'Î™ÌˆÍ‚', 'á¿¢' => 'Î¥ÌˆÌ€', 'á¿£' => 'Î¥ÌˆÌ�', 'á¿¤' => 'Î¡Ì“', 'á¿¦' => 'Î¥Í‚', 'á¿§' => 'Î¥ÌˆÍ‚', 'á¿¶' => 'Î©Í‚', 'á¾ˆ' => 'á¼ˆÎ™', 'á¾‰' => 'á¼‰Î™', 'á¾Š' => 'á¼ŠÎ™', 'á¾‹' => 'á¼‹Î™', 'á¾Œ' => 'á¼ŒÎ™', 'á¾�' => 'á¼�Î™', 'á¾Ž' => 'á¼ŽÎ™', 'á¾�' => 'á¼�Î™', 'á¾˜' => 'á¼¨Î™', 'á¾™' => 'á¼©Î™', 'á¾š' => 'á¼ªÎ™', 'á¾›' => 'á¼«Î™', 'á¾œ' => 'á¼¬Î™', 'á¾�' => 'á¼­Î™', 'á¾ž' => 'á¼®Î™', 'á¾Ÿ' => 'á¼¯Î™', 'á¾¨' => 'á½¨Î™', 'á¾©' => 'á½©Î™', 'á¾ª' => 'á½ªÎ™', 'á¾«' => 'á½«Î™', 'á¾¬' => 'á½¬Î™', 'á¾­' => 'á½­Î™', 'á¾®' => 'á½®Î™', 'á¾¯' => 'á½¯Î™', 'á¾¼' => 'Î‘Î™', 'á¿Œ' => 'Î—Î™', 'á¿¼' => 'Î©Î™', 'á¾²' => 'á¾ºÎ™', 'á¾´' => 'Î†Î™', 'á¿‚' => 'á¿ŠÎ™', 'á¿„' => 'Î‰Î™', 'á¿²' => 'á¿ºÎ™', 'á¿´' => 'Î�Î™', 'á¾·' => 'Î‘Í‚Î™', 'á¿‡' => 'Î—Í‚Î™', 'á¿·' => 'Î©Í‚Î™');<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Mbstring;

/**
 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
 *
 * Implemented:
 * - mb_chr                  - Returns a specific character from its Unicode code point
 * - mb_convert_encoding     - Convert character encoding
 * - mb_convert_variables    - Convert character code in variable(s)
 * - mb_decode_mimeheader    - Decode string in MIME header field
 * - mb_encode_mimeheader    - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
 * - mb_decode_numericentity - Decode HTML numeric string reference to character
 * - mb_encode_numericentity - Encode character to HTML numeric string reference
 * - mb_convert_case         - Perform case folding on a string
 * - mb_detect_encoding      - Detect character encoding
 * - mb_get_info             - Get internal settings of mbstring
 * - mb_http_input           - Detect HTTP input character encoding
 * - mb_http_output          - Set/Get HTTP output character encoding
 * - mb_internal_encoding    - Set/Get internal character encoding
 * - mb_list_encodings       - Returns an array of all supported encodings
 * - mb_ord                  - Returns the Unicode code point of a character
 * - mb_output_handler       - Callback function converts character encoding in output buffer
 * - mb_scrub                - Replaces ill-formed byte sequences with substitute characters
 * - mb_strlen               - Get string length
 * - mb_strpos               - Find position of first occurrence of string in a string
 * - mb_strrpos              - Find position of last occurrence of a string in a string
 * - mb_str_split            - Convert a string to an array
 * - mb_strtolower           - Make a string lowercase
 * - mb_strtoupper           - Make a string uppercase
 * - mb_substitute_character - Set/Get substitution character
 * - mb_substr               - Get part of string
 * - mb_stripos              - Finds position of first occurrence of a string within another, case insensitive
 * - mb_stristr              - Finds first occurrence of a string within another, case insensitive
 * - mb_strrchr              - Finds the last occurrence of a character in a string within another
 * - mb_strrichr             - Finds the last occurrence of a character in a string within another, case insensitive
 * - mb_strripos             - Finds position of last occurrence of a string within another, case insensitive
 * - mb_strstr               - Finds first occurrence of a string within another
 * - mb_strwidth             - Return width of string
 * - mb_substr_count         - Count the number of substring occurrences
 *
 * Not implemented:
 * - mb_convert_kana         - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
 * - mb_ereg_*               - Regular expression with multibyte support
 * - mb_parse_str            - Parse GET/POST/COOKIE data and set global variable
 * - mb_preferred_mime_name  - Get MIME charset string
 * - mb_regex_encoding       - Returns current encoding for multibyte regex as string
 * - mb_regex_set_options    - Set/Get the default options for mbregex functions
 * - mb_send_mail            - Send encoded mail
 * - mb_split                - Split multibyte string using regular expression
 * - mb_strcut               - Get part of string
 * - mb_strimwidth           - Get truncated string with specified width
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Mbstring
{
    public const MB_CASE_FOLD = \PHP_INT_MAX;
    private const CASE_FOLD = [['Âµ', 'Å¿', "Í…", 'Ï‚', "Ï�", "Ï‘", "Ï•", "Ï–", "Ï°", "Ï±", "Ïµ", "áº›", "á¾¾"], ['Î¼', 's', 'Î¹', 'Ïƒ', 'Î²', 'Î¸', 'Ï†', 'Ï€', 'Îº', 'Ï�', 'Îµ', "á¹¡", 'Î¹']];
    private static $encodingList = ['ASCII', 'UTF-8'];
    private static $language = 'neutral';
    private static $internalEncoding = 'UTF-8';
    /**
     *
     */
    public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
    {
        if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
            $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
        } else {
            $fromEncoding = self::getEncoding($fromEncoding);
        }
        $toEncoding = self::getEncoding($toEncoding);
        if ('BASE64' === $fromEncoding) {
            $s = base64_decode($s);
            $fromEncoding = $toEncoding;
        }
        if ('BASE64' === $toEncoding) {
            return base64_encode($s);
        }
        if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
            if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
                $fromEncoding = 'Windows-1252';
            }
            if ('UTF-8' !== $fromEncoding) {
                $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s);
            }
            return preg_replace_callback('/[\\x80-\\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
        }
        if ('HTML-ENTITIES' === $fromEncoding) {
            $s = \Phabel\Target\Php80\Polyfill::html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
            $fromEncoding = 'UTF-8';
        }
        return \iconv($fromEncoding, $toEncoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
    {
        $ok = true;
        array_walk_recursive($vars, function (&$v) use(&$ok, $toEncoding, $fromEncoding) {
            if (false === ($v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding))) {
                $ok = false;
            }
        });
        return $ok ? $fromEncoding : false;
    }
    /**
     *
     */
    public static function mb_decode_mimeheader($s)
    {
        return \Phabel\Target\Php80\Polyfill::iconv_mime_decode($s, 2, self::$internalEncoding);
    }
    /**
     *
     */
    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
    {
        trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
    }
    /**
     *
     */
    public static function mb_decode_numericentity($s, $convmap, $encoding = null)
    {
        if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_decode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
            return false;
        }
        if (null !== $encoding && !is_scalar($encoding)) {
            trigger_error('mb_decode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return '';
            // Instead of null (cf. mb_encode_numericentity).
        }
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        $cnt = floor(\count($convmap) / 4) * 4;
        for ($i = 0; $i < $cnt; $i += 4) {
            // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
            $convmap[$i] += $convmap[$i + 2];
            $convmap[$i + 1] += $convmap[$i + 2];
        }
        $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use($cnt, $convmap) {
            $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
            for ($i = 0; $i < $cnt; $i += 4) {
                if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
                    return self::mb_chr($c - $convmap[$i + 2]);
                }
            }
            return $m[0];
        }, $s);
        if (null === $encoding) {
            return $s;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
    {
        if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_encode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
            return false;
        }
        if (null !== $encoding && !is_scalar($encoding)) {
            trigger_error('mb_encode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
            // Instead of '' (cf. mb_decode_numericentity).
        }
        if (null !== $is_hex && !is_scalar($is_hex)) {
            trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
        $cnt = floor(\count($convmap) / 4) * 4;
        $i = 0;
        $len = \strlen($s);
        $result = '';
        while ($i < $len) {
            $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
            $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i, $ulen);
            $i += $ulen;
            $c = self::mb_ord($uchr);
            for ($j = 0; $j < $cnt; $j += 4) {
                if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
                    $cOffset = $c + $convmap[$j + 2] & $convmap[$j + 3];
                    $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#' . $cOffset . ';';
                    continue 2;
                }
            }
            $result .= $uchr;
        }
        if (null === $encoding) {
            return $result;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $result);
    }
    /**
     *
     */
    public static function mb_convert_case($s, $mode, $encoding = null)
    {
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        if (\MB_CASE_TITLE == $mode) {
            static $titleRegexp = null;
            if (null === $titleRegexp) {
                $titleRegexp = self::getData('titleCaseRegexp');
            }
            $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
        } else {
            if (\MB_CASE_UPPER == $mode) {
                static $upper = null;
                if (null === $upper) {
                    $upper = self::getData('upperCase');
                }
                $map = $upper;
            } else {
                if (self::MB_CASE_FOLD === $mode) {
                    $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
                }
                static $lower = null;
                if (null === $lower) {
                    $lower = self::getData('lowerCase');
                }
                $map = $lower;
            }
            static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
            $i = 0;
            $len = \strlen($s);
            while ($i < $len) {
                $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
                $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i, $ulen);
                $i += $ulen;
                if (isset($map[$uchr])) {
                    $uchr = $map[$uchr];
                    $nlen = \strlen($uchr);
                    if ($nlen == $ulen) {
                        $nlen = $i;
                        do {
                            $s[--$nlen] = $uchr[--$ulen];
                        } while ($ulen);
                    } else {
                        $s = \Phabel\Target\Php80\Polyfill::substr_replace($s, $uchr, $i - $ulen, $ulen);
                        $len += $nlen - $ulen;
                        $i += $nlen - $ulen;
                    }
                }
            }
        }
        if (null === $encoding) {
            return $s;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_internal_encoding($encoding = null)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }
        $normalizedEncoding = self::getEncoding($encoding);
        if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
            self::$internalEncoding = $normalizedEncoding;
            return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
    }
    /**
     *
     */
    public static function mb_language($lang = null)
    {
        if (null === $lang) {
            return self::$language;
        }
        switch ($normalizedLang = strtolower($lang)) {
            case 'uni':
            case 'neutral':
                self::$language = $normalizedLang;
                return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
    }
    /**
     *
     */
    public static function mb_list_encodings()
    {
        return ['UTF-8'];
    }
    /**
     *
     */
    public static function mb_encoding_aliases($encoding)
    {
        switch (strtoupper($encoding)) {
            case 'UTF8':
            case 'UTF-8':
                return ['utf8'];
        }
        return false;
    }
    /**
     *
     */
    public static function mb_check_encoding($var = null, $encoding = null)
    {
        if (null === $encoding) {
            if (null === $var) {
                return false;
            }
            $encoding = self::$internalEncoding;
        }
        return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var);
    }
    /**
     *
     */
    public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
    {
        if (null === $encodingList) {
            $encodingList = self::$encodingList;
        } else {
            if (!\is_array($encodingList)) {
                $encodingList = array_map('trim', explode(',', $encodingList));
            }
            $encodingList = array_map('strtoupper', $encodingList);
        }
        foreach ($encodingList as $enc) {
            switch ($enc) {
                case 'ASCII':
                    if (!preg_match('/[\\x80-\\xFF]/', $str)) {
                        return $enc;
                    }
                    break;
                case 'UTF8':
                case 'UTF-8':
                    if (preg_match('//u', $str)) {
                        return 'UTF-8';
                    }
                    break;
                default:
                    if (0 === strncmp($enc, 'ISO-8859-', 9)) {
                        return $enc;
                    }
            }
        }
        return false;
    }
    /**
     *
     */
    public static function mb_detect_order($encodingList = null)
    {
        if (null === $encodingList) {
            return self::$encodingList;
        }
        if (!\is_array($encodingList)) {
            $encodingList = array_map('trim', explode(',', $encodingList));
        }
        $encodingList = array_map('strtoupper', $encodingList);
        foreach ($encodingList as $enc) {
            switch ($enc) {
                default:
                    if (strncmp($enc, 'ISO-8859-', 9)) {
                        return false;
                    }
                // no break
                case 'ASCII':
                case 'UTF8':
                case 'UTF-8':
            }
        }
        self::$encodingList = $encodingList;
        return true;
    }
    /**
     *
     */
    public static function mb_strlen($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return \strlen($s);
        }
        return @\Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding);
    }
    /**
     *
     */
    public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strpos($haystack, $needle, $offset);
        }
        $needle = (string) $needle;
        if ('' === $needle) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(__METHOD__ . ': Empty delimiter', \E_USER_WARNING);
                return false;
            }
            return 0;
        }
        return \Phabel\Target\Php80\Polyfill::iconv_strpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strrpos($haystack, $needle, $offset);
        }
        if ($offset != (int) $offset) {
            $offset = 0;
        } elseif ($offset = (int) $offset) {
            if ($offset < 0) {
                if (0 > ($offset += self::mb_strlen($needle))) {
                    $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
                }
                $offset = 0;
            } else {
                $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
            }
        }
        $pos = '' !== $needle || 80000 > \PHP_VERSION_ID ? \Phabel\Target\Php80\Polyfill::iconv_strrpos($haystack, $needle, $encoding) : self::mb_strlen($haystack, $encoding);
        return false !== $pos ? $offset + $pos : false;
    }
    /**
     *
     */
    public static function mb_str_split($string, $split_length = 1, $encoding = null)
    {
        if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
            trigger_error('mb_str_split() expects parameter 1 to be string, ' . \gettype($string) . ' given', \E_USER_WARNING);
            return null;
        }
        if (1 > ($split_length = (int) $split_length)) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
                return false;
            }
            throw new \ValueError('Argument #2 ($length) must be greater than 0');
        }
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
        if ('UTF-8' === ($encoding = self::getEncoding($encoding))) {
            $rx = '/(';
            while (65535 < $split_length) {
                $rx .= '.{65535}';
                $split_length -= 65535;
            }
            $rx .= '.{' . $split_length . '})/us';
            return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
        }
        $result = [];
        $length = mb_strlen($string, $encoding);
        for ($i = 0; $i < $length; $i += $split_length) {
            $result[] = mb_substr($string, $i, $split_length, $encoding);
        }
        return $result;
    }
    /**
     *
     */
    public static function mb_strtolower($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
    }
    /**
     *
     */
    public static function mb_strtoupper($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
    }
    /**
     *
     */
    public static function mb_substitute_character($c = null)
    {
        if (null === $c) {
            return 'none';
        }
        if (0 === strcasecmp($c, 'none')) {
            return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
    }
    /**
     *
     */
    public static function mb_substr($s, $start, $length = null, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return (string) \Phabel\Target\Php80\Polyfill::substr($s, $start, null === $length ? 2147483647 : $length);
        }
        if ($start < 0) {
            $start = \Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding) + $start;
            if ($start < 0) {
                $start = 0;
            }
        }
        if (null === $length) {
            $length = 2147483647;
        } elseif ($length < 0) {
            $length = \Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding) + $length - $start;
            if ($length < 0) {
                return '';
            }
        }
        return (string) \Phabel\Target\Php80\Polyfill::iconv_substr($s, $start, $length, $encoding);
    }
    /**
     *
     */
    public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
        return self::mb_strpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            $pos = strrpos($haystack, $needle);
        } else {
            $needle = self::mb_substr($needle, 0, 1, $encoding);
            $pos = \Phabel\Target\Php80\Polyfill::iconv_strrpos($haystack, $needle, $encoding);
        }
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
    {
        $needle = self::mb_substr($needle, 0, 1, $encoding);
        $pos = self::mb_strripos($haystack, $needle, $encoding);
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
        return self::mb_strrpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = strpos($haystack, $needle);
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return \Phabel\Target\Php80\Polyfill::substr($haystack, 0, $pos);
        }
        return \Phabel\Target\Php80\Polyfill::substr($haystack, $pos);
    }
    /**
     *
     */
    public static function mb_get_info($type = 'all')
    {
        $info = ['internal_encoding' => self::$internalEncoding, 'http_output' => 'pass', 'http_output_conv_mimetypes' => '^(text/|application/xhtml\\+xml)', 'func_overload' => 0, 'func_overload_list' => 'no overload', 'mail_charset' => 'UTF-8', 'mail_header_encoding' => 'BASE64', 'mail_body_encoding' => 'BASE64', 'illegal_chars' => 0, 'encoding_translation' => 'Off', 'language' => self::$language, 'detect_order' => self::$encodingList, 'substitute_character' => 'none', 'strict_detection' => 'Off'];
        if ('all' === $type) {
            return $info;
        }
        if (isset($info[$type])) {
            return $info[$type];
        }
        return false;
    }
    /**
     *
     */
    public static function mb_http_input($type = '')
    {
        return false;
    }
    /**
     *
     */
    public static function mb_http_output($encoding = null)
    {
        return null !== $encoding ? 'pass' === $encoding : 'pass';
    }
    /**
     *
     */
    public static function mb_strwidth($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' !== $encoding) {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        $s = preg_replace('/[\\x{1100}-\\x{115F}\\x{2329}\\x{232A}\\x{2E80}-\\x{303E}\\x{3040}-\\x{A4CF}\\x{AC00}-\\x{D7A3}\\x{F900}-\\x{FAFF}\\x{FE10}-\\x{FE19}\\x{FE30}-\\x{FE6F}\\x{FF00}-\\x{FF60}\\x{FFE0}-\\x{FFE6}\\x{20000}-\\x{2FFFD}\\x{30000}-\\x{3FFFD}]/u', '', $s, -1, $wide);
        return ($wide << 1) + \Phabel\Target\Php80\Polyfill::iconv_strlen($s, 'UTF-8');
    }
    /**
     *
     */
    public static function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return \Phabel\Target\Php80\Polyfill::substr_count($haystack, $needle);
    }
    /**
     *
     */
    public static function mb_output_handler($contents, $status)
    {
        return $contents;
    }
    /**
     *
     */
    public static function mb_chr($code, $encoding = null)
    {
        if (0x80 > ($code %= 0x200000)) {
            $s = \chr($code);
        } elseif (0x800 > $code) {
            $s = \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
        } elseif (0x10000 > $code) {
            $s = \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
        } else {
            $s = \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
        }
        if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) {
            $s = mb_convert_encoding($s, $encoding, 'UTF-8');
        }
        return $s;
    }
    /**
     *
     */
    public static function mb_ord($s, $encoding = null)
    {
        if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) {
            $s = mb_convert_encoding($s, 'UTF-8', $encoding);
        }
        if (1 === \strlen($s)) {
            return \ord($s);
        }
        $code = ($s = unpack('C*', \Phabel\Target\Php80\Polyfill::substr($s, 0, 4))) ? $s[1] : 0;
        if (0xf0 <= $code) {
            return ($code - 0xf0 << 18) + ($s[2] - 0x80 << 12) + ($s[3] - 0x80 << 6) + $s[4] - 0x80;
        }
        if (0xe0 <= $code) {
            return ($code - 0xe0 << 12) + ($s[2] - 0x80 << 6) + $s[3] - 0x80;
        }
        if (0xc0 <= $code) {
            return ($code - 0xc0 << 6) + $s[2] - 0x80;
        }
        return $code;
    }
    /**
     *
     */
    private static function getSubpart($pos, $part, $haystack, $encoding)
    {
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return self::mb_substr($haystack, 0, $pos, $encoding);
        }
        return self::mb_substr($haystack, $pos, null, $encoding);
    }
    /**
     *
     */
    private static function html_encoding_callback(array $m)
    {
        $i = 1;
        $entities = '';
        $m = unpack('C*', \Phabel\Target\Php80\Polyfill::htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
        while (isset($m[$i])) {
            if (0x80 > $m[$i]) {
                $entities .= \chr($m[$i++]);
                continue;
            }
            if (0xf0 <= $m[$i]) {
                $c = ($m[$i++] - 0xf0 << 18) + ($m[$i++] - 0x80 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
            } elseif (0xe0 <= $m[$i]) {
                $c = ($m[$i++] - 0xe0 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
            } else {
                $c = ($m[$i++] - 0xc0 << 6) + $m[$i++] - 0x80;
            }
            $entities .= '&#' . $c . ';';
        }
        return $entities;
    }
    /**
     *
     */
    private static function title_case(array $s)
    {
        return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8') . self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
    }
    /**
     *
     */
    private static function getData($file)
    {
        if (file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) {
            return require $file;
        }
        return false;
    }
    /**
     *
     */
    private static function getEncoding($encoding)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }
        if ('UTF-8' === $encoding) {
            return 'UTF-8';
        }
        $encoding = strtoupper($encoding);
        if ('8BIT' === $encoding || 'BINARY' === $encoding) {
            return 'CP850';
        }
        if ('UTF8' === $encoding) {
            return 'UTF-8';
        }
        return $encoding;
    }
}{
    "name": "symfony/polyfill-mbstring",
    "type": "library",
    "description": "Symfony polyfill for the Mbstring extension",
    "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
        "files": [ "bootstrap.php" ]
    },
    "suggest": {
        "ext-mbstring": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Mbstring as p;
if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__ . '/bootstrap80.php';
}
if (!function_exists('mb_convert_encoding')) {
    /**
     *
     */
    function mb_convert_encoding($string, $to_encoding, $from_encoding = null)
    {
        return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding);
    }
}
if (!function_exists('mb_decode_mimeheader')) {
    /**
     *
     */
    function mb_decode_mimeheader($string)
    {
        return p\Mbstring::mb_decode_mimeheader($string);
    }
}
if (!function_exists('mb_encode_mimeheader')) {
    /**
     *
     */
    function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0)
    {
        return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent);
    }
}
if (!function_exists('mb_decode_numericentity')) {
    /**
     *
     */
    function mb_decode_numericentity($string, $map, $encoding = null)
    {
        return p\Mbstring::mb_decode_numericentity($string, $map, $encoding);
    }
}
if (!function_exists('mb_encode_numericentity')) {
    /**
     *
     */
    function mb_encode_numericentity($string, $map, $encoding = null, $hex = false)
    {
        return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex);
    }
}
if (!function_exists('mb_convert_case')) {
    /**
     *
     */
    function mb_convert_case($string, $mode, $encoding = null)
    {
        return p\Mbstring::mb_convert_case($string, $mode, $encoding);
    }
}
if (!function_exists('mb_internal_encoding')) {
    /**
     *
     */
    function mb_internal_encoding($encoding = null)
    {
        return p\Mbstring::mb_internal_encoding($encoding);
    }
}
if (!function_exists('mb_language')) {
    /**
     *
     */
    function mb_language($language = null)
    {
        return p\Mbstring::mb_language($language);
    }
}
if (!function_exists('mb_list_encodings')) {
    /**
     *
     */
    function mb_list_encodings()
    {
        return p\Mbstring::mb_list_encodings();
    }
}
if (!function_exists('mb_encoding_aliases')) {
    /**
     *
     */
    function mb_encoding_aliases($encoding)
    {
        return p\Mbstring::mb_encoding_aliases($encoding);
    }
}
if (!function_exists('mb_check_encoding')) {
    /**
     *
     */
    function mb_check_encoding($value = null, $encoding = null)
    {
        return p\Mbstring::mb_check_encoding($value, $encoding);
    }
}
if (!function_exists('mb_detect_encoding')) {
    /**
     *
     */
    function mb_detect_encoding($string, $encodings = null, $strict = false)
    {
        return p\Mbstring::mb_detect_encoding($string, $encodings, $strict);
    }
}
if (!function_exists('mb_detect_order')) {
    /**
     *
     */
    function mb_detect_order($encoding = null)
    {
        return p\Mbstring::mb_detect_order($encoding);
    }
}
if (!function_exists('mb_parse_str')) {
    /**
     *
     */
    function mb_parse_str($string, &$result = [])
    {
        parse_str($string, $result);
        return (bool) $result;
    }
}
if (!function_exists('mb_strlen')) {
    /**
     *
     */
    function mb_strlen($string, $encoding = null)
    {
        return p\Mbstring::mb_strlen($string, $encoding);
    }
}
if (!function_exists('mb_strpos')) {
    /**
     *
     */
    function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strtolower')) {
    /**
     *
     */
    function mb_strtolower($string, $encoding = null)
    {
        return p\Mbstring::mb_strtolower($string, $encoding);
    }
}
if (!function_exists('mb_strtoupper')) {
    /**
     *
     */
    function mb_strtoupper($string, $encoding = null)
    {
        return p\Mbstring::mb_strtoupper($string, $encoding);
    }
}
if (!function_exists('mb_substitute_character')) {
    /**
     *
     */
    function mb_substitute_character($substitute_character = null)
    {
        return p\Mbstring::mb_substitute_character($substitute_character);
    }
}
if (!function_exists('mb_substr')) {
    /**
     *
     */
    function mb_substr($string, $start, $length = 2147483647, $encoding = null)
    {
        return p\Mbstring::mb_substr($string, $start, $length, $encoding);
    }
}
if (!function_exists('mb_stripos')) {
    /**
     *
     */
    function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_stristr')) {
    /**
     *
     */
    function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strrchr')) {
    /**
     *
     */
    function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strrichr')) {
    /**
     *
     */
    function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strripos')) {
    /**
     *
     */
    function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strrpos')) {
    /**
     *
     */
    function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strstr')) {
    /**
     *
     */
    function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_get_info')) {
    /**
     *
     */
    function mb_get_info($type = 'all')
    {
        return p\Mbstring::mb_get_info($type);
    }
}
if (!function_exists('mb_http_output')) {
    /**
     *
     */
    function mb_http_output($encoding = null)
    {
        return p\Mbstring::mb_http_output($encoding);
    }
}
if (!function_exists('mb_strwidth')) {
    /**
     *
     */
    function mb_strwidth($string, $encoding = null)
    {
        return p\Mbstring::mb_strwidth($string, $encoding);
    }
}
if (!function_exists('mb_substr_count')) {
    /**
     *
     */
    function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return p\Mbstring::mb_substr_count($haystack, $needle, $encoding);
    }
}
if (!function_exists('mb_output_handler')) {
    /**
     *
     */
    function mb_output_handler($string, $status)
    {
        return p\Mbstring::mb_output_handler($string, $status);
    }
}
if (!function_exists('mb_http_input')) {
    /**
     *
     */
    function mb_http_input($type = null)
    {
        return p\Mbstring::mb_http_input($type);
    }
}
if (!function_exists('mb_convert_variables')) {
    /**
     *
     */
    function mb_convert_variables($to_encoding, $from_encoding, &...$vars)
    {
        return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars);
    }
}
if (!function_exists('mb_ord')) {
    /**
     *
     */
    function mb_ord($string, $encoding = null)
    {
        return p\Mbstring::mb_ord($string, $encoding);
    }
}
if (!function_exists('mb_chr')) {
    /**
     *
     */
    function mb_chr($codepoint, $encoding = null)
    {
        return p\Mbstring::mb_chr($codepoint, $encoding);
    }
}
if (!function_exists('mb_scrub')) {
    /**
     *
     */
    function mb_scrub($string, $encoding = null)
    {
        $encoding = null === $encoding ? mb_internal_encoding() : $encoding;
        return mb_convert_encoding($string, $encoding, $encoding);
    }
}
if (!function_exists('mb_str_split')) {
    /**
     *
     */
    function mb_str_split($string, $length = 1, $encoding = null)
    {
        return p\Mbstring::mb_str_split($string, $length, $encoding);
    }
}
if (extension_loaded('mbstring')) {
    return;
}
if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}<?php

#
#
# Parsedown
# http://parsedown.org
#
# (c) Emanuil Rusev
# http://erusev.com
#
# For the full license information, view the LICENSE file that was distributed
# with this source code.
#
#
class Parsedown
{
    # ~
    const version = '1.7.4';
    # ~
    /**
     *
     */
    function text($text)
    {
        # make sure no definitions are set
        $this->DefinitionData = array();
        # standardize line breaks
        $text = str_replace(array("\r\n", "\r"), "\n", $text);
        # remove surrounding line breaks
        $text = trim($text, "\n");
        # split text into lines
        $lines = explode("\n", $text);
        # iterate through lines to identify blocks
        $markup = $this->lines($lines);
        # trim line breaks
        $markup = trim($markup, "\n");
        return $markup;
    }
    #
    # Setters
    #
    /**
     *
     */
    function setBreaksEnabled($breaksEnabled)
    {
        $this->breaksEnabled = $breaksEnabled;
        return $this;
    }
    protected $breaksEnabled;
    /**
     *
     */
    function setMarkupEscaped($markupEscaped)
    {
        $this->markupEscaped = $markupEscaped;
        return $this;
    }
    protected $markupEscaped;
    /**
     *
     */
    function setUrlsLinked($urlsLinked)
    {
        $this->urlsLinked = $urlsLinked;
        return $this;
    }
    protected $urlsLinked = true;
    /**
     *
     */
    function setSafeMode($safeMode)
    {
        $this->safeMode = (bool) $safeMode;
        return $this;
    }
    protected $safeMode;
    protected $safeLinksWhitelist = array('http://', 'https://', 'ftp://', 'ftps://', 'mailto:', 'data:image/png;base64,', 'data:image/gif;base64,', 'data:image/jpeg;base64,', 'irc:', 'ircs:', 'git:', 'ssh:', 'news:', 'steam:');
    #
    # Lines
    #
    protected $BlockTypes = array('#' => array('Header'), '*' => array('Rule', 'List'), '+' => array('List'), '-' => array('SetextHeader', 'Table', 'Rule', 'List'), '0' => array('List'), '1' => array('List'), '2' => array('List'), '3' => array('List'), '4' => array('List'), '5' => array('List'), '6' => array('List'), '7' => array('List'), '8' => array('List'), '9' => array('List'), ':' => array('Table'), '<' => array('Comment', 'Markup'), '=' => array('SetextHeader'), '>' => array('Quote'), '[' => array('Reference'), '_' => array('Rule'), '`' => array('FencedCode'), '|' => array('Table'), '~' => array('FencedCode'));
    # ~
    protected $unmarkedBlockTypes = array('Code');
    #
    # Blocks
    #
    /**
     *
     */
    protected function lines(array $lines)
    {
        $CurrentBlock = null;
        foreach ($lines as $line) {
            if (chop($line) === '') {
                if (isset($CurrentBlock)) {
                    $CurrentBlock['interrupted'] = true;
                }
                continue;
            }
            if (strpos($line, "\t") !== false) {
                $parts = explode("\t", $line);
                $line = $parts[0];
                unset($parts[0]);
                foreach ($parts as $part) {
                    $shortage = 4 - mb_strlen($line, 'utf-8') % 4;
                    $line .= str_repeat(' ', $shortage);
                    $line .= $part;
                }
            }
            $indent = 0;
            while (isset($line[$indent]) and $line[$indent] === ' ') {
                $indent++;
            }
            $text = $indent > 0 ? \Phabel\Target\Php80\Polyfill::substr($line, $indent) : $line;
            # ~
            $Line = array('body' => $line, 'indent' => $indent, 'text' => $text);
            # ~
            if (isset($CurrentBlock['continuable'])) {
                $Block = $this->{'block' . $CurrentBlock['type'] . 'Continue'}($Line, $CurrentBlock);
                if (isset($Block)) {
                    $CurrentBlock = $Block;
                    continue;
                } else {
                    if ($this->isBlockCompletable($CurrentBlock['type'])) {
                        $CurrentBlock = $this->{'block' . $CurrentBlock['type'] . 'Complete'}($CurrentBlock);
                    }
                }
            }
            # ~
            $marker = $text[0];
            # ~
            $blockTypes = $this->unmarkedBlockTypes;
            if (isset($this->BlockTypes[$marker])) {
                foreach ($this->BlockTypes[$marker] as $blockType) {
                    $blockTypes[] = $blockType;
                }
            }
            #
            # ~
            foreach ($blockTypes as $blockType) {
                $Block = $this->{'block' . $blockType}($Line, $CurrentBlock);
                if (isset($Block)) {
                    $Block['type'] = $blockType;
                    if (!isset($Block['identified'])) {
                        $Blocks[] = $CurrentBlock;
                        $Block['identified'] = true;
                    }
                    if ($this->isBlockContinuable($blockType)) {
                        $Block['continuable'] = true;
                    }
                    $CurrentBlock = $Block;
                    continue 2;
                }
            }
            # ~
            if (isset($CurrentBlock) and !isset($CurrentBlock['type']) and !isset($CurrentBlock['interrupted'])) {
                $CurrentBlock['element']['text'] .= "\n" . $text;
            } else {
                $Blocks[] = $CurrentBlock;
                $CurrentBlock = $this->paragraph($Line);
                $CurrentBlock['identified'] = true;
            }
        }
        # ~
        if (isset($CurrentBlock['continuable']) and $this->isBlockCompletable($CurrentBlock['type'])) {
            $CurrentBlock = $this->{'block' . $CurrentBlock['type'] . 'Complete'}($CurrentBlock);
        }
        # ~
        $Blocks[] = $CurrentBlock;
        unset($Blocks[0]);
        # ~
        $markup = '';
        foreach ($Blocks as $Block) {
            if (isset($Block['hidden'])) {
                continue;
            }
            $markup .= "\n";
            $markup .= isset($Block['markup']) ? $Block['markup'] : $this->element($Block['element']);
        }
        $markup .= "\n";
        # ~
        return $markup;
    }
    /**
     *
     */
    protected function isBlockContinuable($Type)
    {
        return method_exists($this, 'block' . $Type . 'Continue');
    }
    /**
     *
     */
    protected function isBlockCompletable($Type)
    {
        return method_exists($this, 'block' . $Type . 'Complete');
    }
    #
    # Code
    /**
     *
     */
    protected function blockCode($Line, $Block = null)
    {
        if (isset($Block) and !isset($Block['type']) and !isset($Block['interrupted'])) {
            return;
        }
        if ($Line['indent'] >= 4) {
            $text = \Phabel\Target\Php80\Polyfill::substr($Line['body'], 4);
            $Block = array('element' => array('name' => 'pre', 'handler' => 'element', 'text' => array('name' => 'code', 'text' => $text)));
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockCodeContinue($Line, $Block)
    {
        if ($Line['indent'] >= 4) {
            if (isset($Block['interrupted'])) {
                $Block['element']['text']['text'] .= "\n";
                unset($Block['interrupted']);
            }
            $Block['element']['text']['text'] .= "\n";
            $text = \Phabel\Target\Php80\Polyfill::substr($Line['body'], 4);
            $Block['element']['text']['text'] .= $text;
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockCodeComplete($Block)
    {
        $text = $Block['element']['text']['text'];
        $Block['element']['text']['text'] = $text;
        return $Block;
    }
    #
    # Comment
    /**
     *
     */
    protected function blockComment($Line)
    {
        if ($this->markupEscaped or $this->safeMode) {
            return;
        }
        if (isset($Line['text'][3]) and $Line['text'][3] === '-' and $Line['text'][2] === '-' and $Line['text'][1] === '!') {
            $Block = array('markup' => $Line['body']);
            if (preg_match('/-->$/', $Line['text'])) {
                $Block['closed'] = true;
            }
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockCommentContinue($Line, array $Block)
    {
        if (isset($Block['closed'])) {
            return;
        }
        $Block['markup'] .= "\n" . $Line['body'];
        if (preg_match('/-->$/', $Line['text'])) {
            $Block['closed'] = true;
        }
        return $Block;
    }
    #
    # Fenced Code
    /**
     *
     */
    protected function blockFencedCode($Line)
    {
        if (preg_match('/^[' . $Line['text'][0] . ']{3,}[ ]*([^`]+)?[ ]*$/', $Line['text'], $matches)) {
            $Element = array('name' => 'code', 'text' => '');
            if (isset($matches[1])) {
                /**
                 * https://www.w3.org/TR/2011/WD-html5-20110525/elements.html#classes
                 * Every HTML element may have a class attribute specified.
                 * The attribute, if specified, must have a value that is a set
                 * of space-separated tokens representing the various classes
                 * that the element belongs to.
                 * [...]
                 * The space characters, for the purposes of this specification,
                 * are U+0020 SPACE, U+0009 CHARACTER TABULATION (tab),
                 * U+000A LINE FEED (LF), U+000C FORM FEED (FF), and
                 * U+000D CARRIAGE RETURN (CR).
                 */
                $language = \Phabel\Target\Php80\Polyfill::substr($matches[1], 0, \Phabel\Target\Php80\Polyfill::strcspn($matches[1], " \t\n\f\r"));
                $class = 'language-' . $language;
                $Element['attributes'] = array('class' => $class);
            }
            $Block = array('char' => $Line['text'][0], 'element' => array('name' => 'pre', 'handler' => 'element', 'text' => $Element));
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockFencedCodeContinue($Line, $Block)
    {
        if (isset($Block['complete'])) {
            return;
        }
        if (isset($Block['interrupted'])) {
            $Block['element']['text']['text'] .= "\n";
            unset($Block['interrupted']);
        }
        if (preg_match('/^' . $Block['char'] . '{3,}[ ]*$/', $Line['text'])) {
            $Block['element']['text']['text'] = \Phabel\Target\Php80\Polyfill::substr($Block['element']['text']['text'], 1);
            $Block['complete'] = true;
            return $Block;
        }
        $Block['element']['text']['text'] .= "\n" . $Line['body'];
        return $Block;
    }
    /**
     *
     */
    protected function blockFencedCodeComplete($Block)
    {
        $text = $Block['element']['text']['text'];
        $Block['element']['text']['text'] = $text;
        return $Block;
    }
    #
    # Header
    /**
     *
     */
    protected function blockHeader($Line)
    {
        if (isset($Line['text'][1])) {
            $level = 1;
            while (isset($Line['text'][$level]) and $Line['text'][$level] === '#') {
                $level++;
            }
            if ($level > 6) {
                return;
            }
            $text = trim($Line['text'], '# ');
            $Block = array('element' => array('name' => 'h' . min(6, $level), 'text' => $text, 'handler' => 'line'));
            return $Block;
        }
    }
    #
    # List
    /**
     *
     */
    protected function blockList($Line)
    {
        list($name, $pattern) = $Line['text'][0] <= '-' ? array('ul', '[*+-]') : array('ol', '[0-9]+[.]');
        if (preg_match('/^(' . $pattern . '[ ]+)(.*)/', $Line['text'], $matches)) {
            $Block = array('indent' => $Line['indent'], 'pattern' => $pattern, 'element' => array('name' => $name, 'handler' => 'elements'));
            if ($name === 'ol') {
                $listStart = stristr($matches[0], '.', true);
                if ($listStart !== '1') {
                    $Block['element']['attributes'] = array('start' => $listStart);
                }
            }
            $Block['li'] = array('name' => 'li', 'handler' => 'li', 'text' => array($matches[2]));
            $Block['element']['text'][] =& $Block['li'];
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockListContinue($Line, array $Block)
    {
        if ($Block['indent'] === $Line['indent'] and preg_match('/^' . $Block['pattern'] . '(?:[ ]+(.*)|$)/', $Line['text'], $matches)) {
            if (isset($Block['interrupted'])) {
                $Block['li']['text'][] = '';
                $Block['loose'] = true;
                unset($Block['interrupted']);
            }
            unset($Block['li']);
            $text = isset($matches[1]) ? $matches[1] : '';
            $Block['li'] = array('name' => 'li', 'handler' => 'li', 'text' => array($text));
            $Block['element']['text'][] =& $Block['li'];
            return $Block;
        }
        if ($Line['text'][0] === '[' and $this->blockReference($Line)) {
            return $Block;
        }
        if (!isset($Block['interrupted'])) {
            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
            $Block['li']['text'][] = $text;
            return $Block;
        }
        if ($Line['indent'] > 0) {
            $Block['li']['text'][] = '';
            $text = preg_replace('/^[ ]{0,4}/', '', $Line['body']);
            $Block['li']['text'][] = $text;
            unset($Block['interrupted']);
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockListComplete(array $Block)
    {
        if (isset($Block['loose'])) {
            foreach ($Block['element']['text'] as &$li) {
                if (end($li['text']) !== '') {
                    $li['text'][] = '';
                }
            }
        }
        return $Block;
    }
    #
    # Quote
    /**
     *
     */
    protected function blockQuote($Line)
    {
        if (preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) {
            $Block = array('element' => array('name' => 'blockquote', 'handler' => 'lines', 'text' => (array) $matches[1]));
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockQuoteContinue($Line, array $Block)
    {
        if ($Line['text'][0] === '>' and preg_match('/^>[ ]?(.*)/', $Line['text'], $matches)) {
            if (isset($Block['interrupted'])) {
                $Block['element']['text'][] = '';
                unset($Block['interrupted']);
            }
            $Block['element']['text'][] = $matches[1];
            return $Block;
        }
        if (!isset($Block['interrupted'])) {
            $Block['element']['text'][] = $Line['text'];
            return $Block;
        }
    }
    #
    # Rule
    /**
     *
     */
    protected function blockRule($Line)
    {
        if (preg_match('/^([' . $Line['text'][0] . '])([ ]*\\1){2,}[ ]*$/', $Line['text'])) {
            $Block = array('element' => array('name' => 'hr'));
            return $Block;
        }
    }
    #
    # Setext
    /**
     *
     */
    protected function blockSetextHeader($Line, array $Block = null)
    {
        if (!isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) {
            return;
        }
        if (chop($Line['text'], $Line['text'][0]) === '') {
            $Block['element']['name'] = $Line['text'][0] === '=' ? 'h1' : 'h2';
            return $Block;
        }
    }
    #
    # Markup
    /**
     *
     */
    protected function blockMarkup($Line)
    {
        if ($this->markupEscaped or $this->safeMode) {
            return;
        }
        if (preg_match('/^<(\\w[\\w-]*)(?:[ ]*' . $this->regexHtmlAttribute . ')*[ ]*(\\/)?>/', $Line['text'], $matches)) {
            $element = strtolower($matches[1]);
            if (in_array($element, $this->textLevelElements)) {
                return;
            }
            $Block = array('name' => $matches[1], 'depth' => 0, 'markup' => $Line['text']);
            $length = strlen($matches[0]);
            $remainder = \Phabel\Target\Php80\Polyfill::substr($Line['text'], $length);
            if (trim($remainder) === '') {
                if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) {
                    $Block['closed'] = true;
                    $Block['void'] = true;
                }
            } else {
                if (isset($matches[2]) or in_array($matches[1], $this->voidElements)) {
                    return;
                }
                if (preg_match('/<\\/' . $matches[1] . '>[ ]*$/i', $remainder)) {
                    $Block['closed'] = true;
                }
            }
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockMarkupContinue($Line, array $Block)
    {
        if (isset($Block['closed'])) {
            return;
        }
        if (preg_match('/^<' . $Block['name'] . '(?:[ ]*' . $this->regexHtmlAttribute . ')*[ ]*>/i', $Line['text'])) {
            # open
            $Block['depth']++;
        }
        if (preg_match('/(.*?)<\\/' . $Block['name'] . '>[ ]*$/i', $Line['text'], $matches)) {
            # close
            if ($Block['depth'] > 0) {
                $Block['depth']--;
            } else {
                $Block['closed'] = true;
            }
        }
        if (isset($Block['interrupted'])) {
            $Block['markup'] .= "\n";
            unset($Block['interrupted']);
        }
        $Block['markup'] .= "\n" . $Line['body'];
        return $Block;
    }
    #
    # Reference
    /**
     *
     */
    protected function blockReference($Line)
    {
        if (preg_match('/^\\[(.+?)\\]:[ ]*<?(\\S+?)>?(?:[ ]+["\'(](.+)["\')])?[ ]*$/', $Line['text'], $matches)) {
            $id = strtolower($matches[1]);
            $Data = array('url' => $matches[2], 'title' => null);
            if (isset($matches[3])) {
                $Data['title'] = $matches[3];
            }
            $this->DefinitionData['Reference'][$id] = $Data;
            $Block = array('hidden' => true);
            return $Block;
        }
    }
    #
    # Table
    /**
     *
     */
    protected function blockTable($Line, array $Block = null)
    {
        if (!isset($Block) or isset($Block['type']) or isset($Block['interrupted'])) {
            return;
        }
        if (strpos($Block['element']['text'], '|') !== false and chop($Line['text'], ' -:|') === '') {
            $alignments = array();
            $divider = $Line['text'];
            $divider = trim($divider);
            $divider = trim($divider, '|');
            $dividerCells = explode('|', $divider);
            foreach ($dividerCells as $dividerCell) {
                $dividerCell = trim($dividerCell);
                if ($dividerCell === '') {
                    continue;
                }
                $alignment = null;
                if ($dividerCell[0] === ':') {
                    $alignment = 'left';
                }
                if (\Phabel\Target\Php80\Polyfill::substr($dividerCell, -1) === ':') {
                    $alignment = $alignment === 'left' ? 'center' : 'right';
                }
                $alignments[] = $alignment;
            }
            # ~
            $HeaderElements = array();
            $header = $Block['element']['text'];
            $header = trim($header);
            $header = trim($header, '|');
            $headerCells = explode('|', $header);
            foreach ($headerCells as $index => $headerCell) {
                $headerCell = trim($headerCell);
                $HeaderElement = array('name' => 'th', 'text' => $headerCell, 'handler' => 'line');
                if (isset($alignments[$index])) {
                    $alignment = $alignments[$index];
                    $HeaderElement['attributes'] = array('style' => 'text-align: ' . $alignment . ';');
                }
                $HeaderElements[] = $HeaderElement;
            }
            # ~
            $Block = array('alignments' => $alignments, 'identified' => true, 'element' => array('name' => 'table', 'handler' => 'elements'));
            $Block['element']['text'][] = array('name' => 'thead', 'handler' => 'elements');
            $Block['element']['text'][] = array('name' => 'tbody', 'handler' => 'elements', 'text' => array());
            $Block['element']['text'][0]['text'][] = array('name' => 'tr', 'handler' => 'elements', 'text' => $HeaderElements);
            return $Block;
        }
    }
    /**
     *
     */
    protected function blockTableContinue($Line, array $Block)
    {
        if (isset($Block['interrupted'])) {
            return;
        }
        if ($Line['text'][0] === '|' or strpos($Line['text'], '|')) {
            $Elements = array();
            $row = $Line['text'];
            $row = trim($row);
            $row = trim($row, '|');
            preg_match_all('/(?:(\\\\[|])|[^|`]|`[^`]+`|`)+/', $row, $matches);
            foreach ($matches[0] as $index => $cell) {
                $cell = trim($cell);
                $Element = array('name' => 'td', 'handler' => 'line', 'text' => $cell);
                if (isset($Block['alignments'][$index])) {
                    $Element['attributes'] = array('style' => 'text-align: ' . $Block['alignments'][$index] . ';');
                }
                $Elements[] = $Element;
            }
            $Element = array('name' => 'tr', 'handler' => 'elements', 'text' => $Elements);
            $Block['element']['text'][1]['text'][] = $Element;
            return $Block;
        }
    }
    #
    # ~
    #
    /**
     *
     */
    protected function paragraph($Line)
    {
        $Block = array('element' => array('name' => 'p', 'text' => $Line['text'], 'handler' => 'line'));
        return $Block;
    }
    #
    # Inline Elements
    #
    protected $InlineTypes = array('"' => array('SpecialCharacter'), '!' => array('Image'), '&' => array('SpecialCharacter'), '*' => array('Emphasis'), ':' => array('Url'), '<' => array('UrlTag', 'EmailTag', 'Markup', 'SpecialCharacter'), '>' => array('SpecialCharacter'), '[' => array('Link'), '_' => array('Emphasis'), '`' => array('Code'), '~' => array('Strikethrough'), '\\' => array('EscapeSequence'));
    # ~
    protected $inlineMarkerList = '!"*_&[:<>`~\\';
    #
    # ~
    #
    /**
     *
     */
    public function line($text, $nonNestables = array())
    {
        $markup = '';
        # $excerpt is based on the first occurrence of a marker
        while ($excerpt = strpbrk($text, $this->inlineMarkerList)) {
            $marker = $excerpt[0];
            $markerPosition = strpos($text, $marker);
            $Excerpt = array('text' => $excerpt, 'context' => $text);
            foreach ($this->InlineTypes[$marker] as $inlineType) {
                # check to see if the current inline type is nestable in the current context
                if (!empty($nonNestables) and in_array($inlineType, $nonNestables)) {
                    continue;
                }
                $Inline = $this->{'inline' . $inlineType}($Excerpt);
                if (!isset($Inline)) {
                    continue;
                }
                # makes sure that the inline belongs to "our" marker
                if (isset($Inline['position']) and $Inline['position'] > $markerPosition) {
                    continue;
                }
                # sets a default inline position
                if (!isset($Inline['position'])) {
                    $Inline['position'] = $markerPosition;
                }
                # cause the new element to 'inherit' our non nestables
                foreach ($nonNestables as $non_nestable) {
                    $Inline['element']['nonNestables'][] = $non_nestable;
                }
                # the text that comes before the inline
                $unmarkedText = \Phabel\Target\Php80\Polyfill::substr($text, 0, $Inline['position']);
                # compile the unmarked text
                $markup .= $this->unmarkedText($unmarkedText);
                # compile the inline
                $markup .= isset($Inline['markup']) ? $Inline['markup'] : $this->element($Inline['element']);
                # remove the examined text
                $text = \Phabel\Target\Php80\Polyfill::substr($text, $Inline['position'] + $Inline['extent']);
                continue 2;
            }
            # the marker does not belong to an inline
            $unmarkedText = \Phabel\Target\Php80\Polyfill::substr($text, 0, $markerPosition + 1);
            $markup .= $this->unmarkedText($unmarkedText);
            $text = \Phabel\Target\Php80\Polyfill::substr($text, $markerPosition + 1);
        }
        $markup .= $this->unmarkedText($text);
        return $markup;
    }
    #
    # ~
    #
    /**
     *
     */
    protected function inlineCode($Excerpt)
    {
        $marker = $Excerpt['text'][0];
        if (preg_match('/^(' . $marker . '+)[ ]*(.+?)[ ]*(?<!' . $marker . ')\\1(?!' . $marker . ')/s', $Excerpt['text'], $matches)) {
            $text = $matches[2];
            $text = preg_replace("/[ ]*\n/", ' ', $text);
            return array('extent' => strlen($matches[0]), 'element' => array('name' => 'code', 'text' => $text));
        }
    }
    /**
     *
     */
    protected function inlineEmailTag($Excerpt)
    {
        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<((mailto:)?\\S+?@\\S+?)>/i', $Excerpt['text'], $matches)) {
            $url = $matches[1];
            if (!isset($matches[2])) {
                $url = 'mailto:' . $url;
            }
            return array('extent' => strlen($matches[0]), 'element' => array('name' => 'a', 'text' => $matches[1], 'attributes' => array('href' => $url)));
        }
    }
    /**
     *
     */
    protected function inlineEmphasis($Excerpt)
    {
        if (!isset($Excerpt['text'][1])) {
            return;
        }
        $marker = $Excerpt['text'][0];
        if ($Excerpt['text'][1] === $marker and preg_match($this->StrongRegex[$marker], $Excerpt['text'], $matches)) {
            $emphasis = 'strong';
        } elseif (preg_match($this->EmRegex[$marker], $Excerpt['text'], $matches)) {
            $emphasis = 'em';
        } else {
            return;
        }
        return array('extent' => strlen($matches[0]), 'element' => array('name' => $emphasis, 'handler' => 'line', 'text' => $matches[1]));
    }
    /**
     *
     */
    protected function inlineEscapeSequence($Excerpt)
    {
        if (isset($Excerpt['text'][1]) and in_array($Excerpt['text'][1], $this->specialCharacters)) {
            return array('markup' => $Excerpt['text'][1], 'extent' => 2);
        }
    }
    /**
     *
     */
    protected function inlineImage($Excerpt)
    {
        if (!isset($Excerpt['text'][1]) or $Excerpt['text'][1] !== '[') {
            return;
        }
        $Excerpt['text'] = \Phabel\Target\Php80\Polyfill::substr($Excerpt['text'], 1);
        $Link = $this->inlineLink($Excerpt);
        if ($Link === null) {
            return;
        }
        $Inline = array('extent' => $Link['extent'] + 1, 'element' => array('name' => 'img', 'attributes' => array('src' => $Link['element']['attributes']['href'], 'alt' => $Link['element']['text'])));
        $Inline['element']['attributes'] += $Link['element']['attributes'];
        unset($Inline['element']['attributes']['href']);
        return $Inline;
    }
    /**
     *
     */
    protected function inlineLink($Excerpt)
    {
        $Element = array('name' => 'a', 'handler' => 'line', 'nonNestables' => array('Url', 'Link'), 'text' => null, 'attributes' => array('href' => null, 'title' => null));
        $extent = 0;
        $remainder = $Excerpt['text'];
        if (preg_match('/\\[((?:[^][]++|(?R))*+)\\]/', $remainder, $matches)) {
            $Element['text'] = $matches[1];
            $extent += strlen($matches[0]);
            $remainder = \Phabel\Target\Php80\Polyfill::substr($remainder, $extent);
        } else {
            return;
        }
        if (preg_match('/^[(]\\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\\s*[)]/', $remainder, $matches)) {
            $Element['attributes']['href'] = $matches[1];
            if (isset($matches[2])) {
                $Element['attributes']['title'] = \Phabel\Target\Php80\Polyfill::substr($matches[2], 1, -1);
            }
            $extent += strlen($matches[0]);
        } else {
            if (preg_match('/^\\s*\\[(.*?)\\]/', $remainder, $matches)) {
                $definition = strlen($matches[1]) ? $matches[1] : $Element['text'];
                $definition = strtolower($definition);
                $extent += strlen($matches[0]);
            } else {
                $definition = strtolower($Element['text']);
            }
            if (!isset($this->DefinitionData['Reference'][$definition])) {
                return;
            }
            $Definition = $this->DefinitionData['Reference'][$definition];
            $Element['attributes']['href'] = $Definition['url'];
            $Element['attributes']['title'] = $Definition['title'];
        }
        return array('extent' => $extent, 'element' => $Element);
    }
    /**
     *
     */
    protected function inlineMarkup($Excerpt)
    {
        if ($this->markupEscaped or $this->safeMode or strpos($Excerpt['text'], '>') === false) {
            return;
        }
        if ($Excerpt['text'][1] === '/' and preg_match('/^<\\/\\w[\\w-]*[ ]*>/s', $Excerpt['text'], $matches)) {
            return array('markup' => $matches[0], 'extent' => strlen($matches[0]));
        }
        if ($Excerpt['text'][1] === '!' and preg_match('/^<!---?[^>-](?:-?[^-])*-->/s', $Excerpt['text'], $matches)) {
            return array('markup' => $matches[0], 'extent' => strlen($matches[0]));
        }
        if ($Excerpt['text'][1] !== ' ' and preg_match('/^<\\w[\\w-]*(?:[ ]*' . $this->regexHtmlAttribute . ')*[ ]*\\/?>/s', $Excerpt['text'], $matches)) {
            return array('markup' => $matches[0], 'extent' => strlen($matches[0]));
        }
    }
    /**
     *
     */
    protected function inlineSpecialCharacter($Excerpt)
    {
        if ($Excerpt['text'][0] === '&' and !preg_match('/^&#?\\w+;/', $Excerpt['text'])) {
            return array('markup' => '&amp;', 'extent' => 1);
        }
        $SpecialCharacter = array('>' => 'gt', '<' => 'lt', '"' => 'quot');
        if (isset($SpecialCharacter[$Excerpt['text'][0]])) {
            return array('markup' => '&' . $SpecialCharacter[$Excerpt['text'][0]] . ';', 'extent' => 1);
        }
    }
    /**
     *
     */
    protected function inlineStrikethrough($Excerpt)
    {
        if (!isset($Excerpt['text'][1])) {
            return;
        }
        if ($Excerpt['text'][1] === '~' and preg_match('/^~~(?=\\S)(.+?)(?<=\\S)~~/', $Excerpt['text'], $matches)) {
            return array('extent' => strlen($matches[0]), 'element' => array('name' => 'del', 'text' => $matches[1], 'handler' => 'line'));
        }
    }
    /**
     *
     */
    protected function inlineUrl($Excerpt)
    {
        if ($this->urlsLinked !== true or !isset($Excerpt['text'][2]) or $Excerpt['text'][2] !== '/') {
            return;
        }
        if (preg_match('/\\bhttps?:[\\/]{2}[^\\s<]+\\b\\/*/ui', $Excerpt['context'], $matches, PREG_OFFSET_CAPTURE)) {
            $url = $matches[0][0];
            $Inline = array('extent' => strlen($matches[0][0]), 'position' => $matches[0][1], 'element' => array('name' => 'a', 'text' => $url, 'attributes' => array('href' => $url)));
            return $Inline;
        }
    }
    /**
     *
     */
    protected function inlineUrlTag($Excerpt)
    {
        if (strpos($Excerpt['text'], '>') !== false and preg_match('/^<(\\w+:\\/{2}[^ >]+)>/i', $Excerpt['text'], $matches)) {
            $url = $matches[1];
            return array('extent' => strlen($matches[0]), 'element' => array('name' => 'a', 'text' => $url, 'attributes' => array('href' => $url)));
        }
    }
    # ~
    /**
     *
     */
    protected function unmarkedText($text)
    {
        if ($this->breaksEnabled) {
            $text = preg_replace('/[ ]*\\n/', "<br />\n", $text);
        } else {
            $text = preg_replace('/(?:[ ][ ]+|[ ]*\\\\)\\n/', "<br />\n", $text);
            $text = str_replace(" \n", "\n", $text);
        }
        return $text;
    }
    #
    # Handlers
    #
    /**
     *
     */
    protected function element(array $Element)
    {
        if ($this->safeMode) {
            $Element = $this->sanitiseElement($Element);
        }
        $markup = '<' . $Element['name'];
        if (isset($Element['attributes'])) {
            foreach ($Element['attributes'] as $name => $value) {
                if ($value === null) {
                    continue;
                }
                $markup .= ' ' . $name . '="' . self::escape($value) . '"';
            }
        }
        $permitRawHtml = false;
        if (isset($Element['text'])) {
            $text = $Element['text'];
        } elseif (isset($Element['rawHtml'])) {
            $text = $Element['rawHtml'];
            $allowRawHtmlInSafeMode = isset($Element['allowRawHtmlInSafeMode']) && $Element['allowRawHtmlInSafeMode'];
            $permitRawHtml = !$this->safeMode || $allowRawHtmlInSafeMode;
        }
        if (isset($text)) {
            $markup .= '>';
            if (!isset($Element['nonNestables'])) {
                $Element['nonNestables'] = array();
            }
            if (isset($Element['handler'])) {
                $markup .= $this->{$Element['handler']}($text, $Element['nonNestables']);
            } elseif (!$permitRawHtml) {
                $markup .= self::escape($text, true);
            } else {
                $markup .= $text;
            }
            $markup .= '</' . $Element['name'] . '>';
        } else {
            $markup .= ' />';
        }
        return $markup;
    }
    /**
     *
     */
    protected function elements(array $Elements)
    {
        $markup = '';
        foreach ($Elements as $Element) {
            $markup .= "\n" . $this->element($Element);
        }
        $markup .= "\n";
        return $markup;
    }
    # ~
    /**
     *
     */
    protected function li($lines)
    {
        $markup = $this->lines($lines);
        $trimmedMarkup = trim($markup);
        if (!in_array('', $lines) and \Phabel\Target\Php80\Polyfill::substr($trimmedMarkup, 0, 3) === '<p>') {
            $markup = $trimmedMarkup;
            $markup = \Phabel\Target\Php80\Polyfill::substr($markup, 3);
            $position = strpos($markup, "</p>");
            $markup = \Phabel\Target\Php80\Polyfill::substr_replace($markup, '', $position, 4);
        }
        return $markup;
    }
    #
    # Deprecated Methods
    #
    /**
     *
     */
    function parse($text)
    {
        $markup = $this->text($text);
        return $markup;
    }
    /**
     *
     */
    protected function sanitiseElement(array $Element)
    {
        static $goodAttribute = '/^[a-zA-Z0-9][a-zA-Z0-9-_]*+$/';
        static $safeUrlNameToAtt = array('a' => 'href', 'img' => 'src');
        if (isset($safeUrlNameToAtt[$Element['name']])) {
            $Element = $this->filterUnsafeUrlInAttribute($Element, $safeUrlNameToAtt[$Element['name']]);
        }
        if (!empty($Element['attributes'])) {
            foreach ($Element['attributes'] as $att => $val) {
                # filter out badly parsed attribute
                if (!preg_match($goodAttribute, $att)) {
                    unset($Element['attributes'][$att]);
                } elseif (self::striAtStart($att, 'on')) {
                    unset($Element['attributes'][$att]);
                }
            }
        }
        return $Element;
    }
    /**
     *
     */
    protected function filterUnsafeUrlInAttribute(array $Element, $attribute)
    {
        foreach ($this->safeLinksWhitelist as $scheme) {
            if (self::striAtStart($Element['attributes'][$attribute], $scheme)) {
                return $Element;
            }
        }
        $Element['attributes'][$attribute] = str_replace(':', '%3A', $Element['attributes'][$attribute]);
        return $Element;
    }
    #
    # Static Methods
    #
    /**
     *
     */
    protected static function escape($text, $allowQuotes = false)
    {
        return htmlspecialchars($text, $allowQuotes ? ENT_NOQUOTES : ENT_QUOTES, 'UTF-8');
    }
    /**
     *
     */
    protected static function striAtStart($string, $needle)
    {
        $len = strlen($needle);
        if ($len > strlen($string)) {
            return false;
        } else {
            return strtolower(\Phabel\Target\Php80\Polyfill::substr($string, 0, $len)) === strtolower($needle);
        }
    }
    /**
     *
     */
    static function instance($name = 'default')
    {
        if (isset(self::$instances[$name])) {
            return self::$instances[$name];
        }
        $instance = new static();
        self::$instances[$name] = $instance;
        return $instance;
    }
    private static $instances = array();
    #
    # Fields
    #
    protected $DefinitionData;
    #
    # Read-Only
    protected $specialCharacters = array('\\', '`', '*', '_', '{', '}', '[', ']', '(', ')', '>', '#', '+', '-', '.', '!', '|');
    protected $StrongRegex = array('*' => '/^[*]{2}((?:\\\\\\*|[^*]|[*][^*]*[*])+?)[*]{2}(?![*])/s', '_' => '/^__((?:\\\\_|[^_]|_[^_]*_)+?)__(?!_)/us');
    protected $EmRegex = array('*' => '/^[*]((?:\\\\\\*|[^*]|[*][*][^*]+?[*][*])+?)[*](?![*])/s', '_' => '/^_((?:\\\\_|[^_]|__[^_]*__)+?)_(?!_)\\b/us');
    protected $regexHtmlAttribute = '[a-zA-Z_:][\\w:.-]*(?:\\s*=\\s*(?:[^"\'=<>`\\s]+|"[^"]*"|\'[^\']*\'))?';
    protected $voidElements = array('area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source');
    protected $textLevelElements = array('a', 'br', 'bdo', 'abbr', 'blink', 'nextid', 'acronym', 'basefont', 'b', 'em', 'big', 'cite', 'small', 'spacer', 'listing', 'i', 'rp', 'del', 'code', 'strike', 'marquee', 'q', 'rt', 'ins', 'font', 'strong', 's', 'tt', 'kbd', 'mark', 'u', 'xm', 'sub', 'nobr', 'sup', 'ruby', 'var', 'span', 'wbr', 'time');
}{
    "name": "erusev/parsedown",
    "description": "Parser for Markdown.",
    "keywords": ["markdown", "parser"],
    "homepage": "http://parsedown.org",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Emanuil Rusev",
            "email": "hello@erusev.com",
            "homepage": "http://erusev.com"
        }
    ],
    "require": {
        "php": ">=5.3.0",
        "ext-mbstring": "*"
    },
    "require-dev": {
        "phpunit/phpunit": "^4.8.35"
    },
    "autoload": {
        "psr-0": {"Parsedown": ""}
    },
    "autoload-dev": {
        "psr-0": {
            "TestParsedown": "test/",
            "ParsedownTest": "test/",
            "CommonMarkTest": "test/",
            "CommonMarkTestWeak": "test/"
        }
    }
}
<?php

#[Attribute(Attribute::TARGET_CLASS)]
final class Attribute
{
    public const TARGET_CLASS = 1;
    public const TARGET_FUNCTION = 2;
    public const TARGET_METHOD = 4;
    public const TARGET_PROPERTY = 8;
    public const TARGET_CLASS_CONSTANT = 16;
    public const TARGET_PARAMETER = 32;
    public const TARGET_ALL = 63;
    public const IS_REPEATABLE = 64;
    /** @var int */
    public $flags;
    /**
     *
     */
    public function __construct(int $flags = self::TARGET_ALL)
    {
        $this->flags = $flags;
    }
}<?php

class UnhandledMatchError extends Error
{
}<?php

if (\PHP_VERSION_ID < 80000) {
    interface Stringable
    {
        /**
         * @return string
         */
        public function __toString();
    }
}<?php

class ValueError extends Error
{
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php80;

/**
 * @author Ion Bazan <ion.bazan@gmail.com>
 * @author Nico Oelgart <nicoswd@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Php80
{
    /**
     *
     */
    public static function fdiv(float $dividend, float $divisor) : float
    {
        return @($dividend / $divisor);
    }
    /**
     *
     */
    public static function get_debug_type($value) : string
    {
        switch (true) {
            case null === $value:
                return 'null';
            case \is_bool($value):
                return 'bool';
            case \is_string($value):
                return 'string';
            case \is_array($value):
                return 'array';
            case \is_int($value):
                return 'int';
            case \is_float($value):
                return 'float';
            case \is_object($value):
                break;
            case $value instanceof \__PHP_Incomplete_Class:
                return '__PHP_Incomplete_Class';
            default:
                if (null === ($type = @get_resource_type($value))) {
                    return 'unknown';
                }
                if ('Unknown' === $type) {
                    $type = 'closed';
                }
                return "resource ({$type})";
        }
        $class = \get_class($value);
        if (false === strpos($class, '@')) {
            return $class;
        }
        return ((get_parent_class($class) ?: key(class_implements($class))) ?: 'class') . '@anonymous';
    }
    /**
     *
     */
    public static function get_resource_id($res) : int
    {
        if (!\is_resource($res) && null === @get_resource_type($res)) {
            throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res)));
        }
        return (int) $res;
    }
    /**
     *
     */
    public static function preg_last_error_msg() : string
    {
        switch (preg_last_error()) {
            case \PREG_INTERNAL_ERROR:
                return 'Internal error';
            case \PREG_BAD_UTF8_ERROR:
                return 'Malformed UTF-8 characters, possibly incorrectly encoded';
            case \PREG_BAD_UTF8_OFFSET_ERROR:
                return 'The offset did not correspond to the beginning of a valid UTF-8 code point';
            case \PREG_BACKTRACK_LIMIT_ERROR:
                return 'Backtrack limit exhausted';
            case \PREG_RECURSION_LIMIT_ERROR:
                return 'Recursion limit exhausted';
            case \PREG_JIT_STACKLIMIT_ERROR:
                return 'JIT stack limit exhausted';
            case \PREG_NO_ERROR:
                return 'No error';
            default:
                return 'Unknown error';
        }
    }
    /**
     *
     */
    public static function str_contains(string $haystack, string $needle) : bool
    {
        return '' === $needle || false !== strpos($haystack, $needle);
    }
    /**
     *
     */
    public static function str_starts_with(string $haystack, string $needle) : bool
    {
        return 0 === strncmp($haystack, $needle, \strlen($needle));
    }
    /**
     *
     */
    public static function str_ends_with(string $haystack, string $needle) : bool
    {
        return '' === $needle || '' !== $haystack && 0 === \Phabel\Target\Php80\Polyfill::substr_compare($haystack, $needle, -\strlen($needle));
    }
}{
    "name": "symfony/polyfill-php80",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
    "keywords": ["polyfill", "shim", "compatibility", "portable"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Ion Bazan",
            "email": "ion.bazan@gmail.com"
        },
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Php80\\": "" },
        "files": [ "bootstrap.php" ],
        "classmap": [ "Resources/stubs" ]
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Php80 as p;
if (\PHP_VERSION_ID >= 80000) {
    return;
}
if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) {
    define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN);
}
if (!function_exists('fdiv')) {
    /**
     *
     */
    function fdiv(float $num1, float $num2) : float
    {
        return p\Php80::fdiv($num1, $num2);
    }
}
if (!function_exists('preg_last_error_msg')) {
    /**
     *
     */
    function preg_last_error_msg() : string
    {
        return p\Php80::preg_last_error_msg();
    }
}
if (!function_exists('str_contains')) {
    /**
     *
     */
    function str_contains(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_contains($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('str_starts_with')) {
    /**
     *
     */
    function str_starts_with(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_starts_with($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('str_ends_with')) {
    /**
     *
     */
    function str_ends_with(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_ends_with($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('get_debug_type')) {
    /**
     *
     */
    function get_debug_type($value) : string
    {
        return p\Php80::get_debug_type($value);
    }
}
if (!function_exists('get_resource_id')) {
    /**
     *
     */
    function get_resource_id($resource) : int
    {
        return p\Php80::get_resource_id($resource);
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Mbstring as p;
if (!function_exists('mb_convert_encoding')) {
    /**
     * @param (array | string | null) $string
     * @param (array | string | null) $from_encoding
     * @return (array | string | false)
     */
    function mb_convert_encoding($string, ?string $to_encoding, $from_encoding = null)
    {
        if (!\is_null($string)) {
            if (!\is_string($string)) {
                if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                    if (!\is_array($string)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $string = (string) $string;
                }
            }
        }
        if (!(\is_null($from_encoding) || \is_null($from_encoding))) {
            if (!\is_string($from_encoding)) {
                if (!(\is_string($from_encoding) || \is_object($from_encoding) && \method_exists($from_encoding, '__toString') || (\is_bool($from_encoding) || \is_numeric($from_encoding)))) {
                    if (!\is_array($from_encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #3 ($from_encoding) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($from_encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $from_encoding = (string) $from_encoding;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    if (!\is_array($phabelReturn)) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_decode_mimeheader')) {
    /**
     *
     */
    function mb_decode_mimeheader(?string $string) : string
    {
        return p\Mbstring::mb_decode_mimeheader((string) $string);
    }
}
if (!function_exists('mb_encode_mimeheader')) {
    /**
     *
     */
    function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0) : string
    {
        return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent);
    }
}
if (!function_exists('mb_decode_numericentity')) {
    /**
     *
     */
    function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding);
    }
}
if (!function_exists('mb_encode_numericentity')) {
    /**
     *
     */
    function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false) : string
    {
        return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex);
    }
}
if (!function_exists('mb_convert_case')) {
    /**
     *
     */
    function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding);
    }
}
if (!function_exists('mb_internal_encoding')) {
    /**
     * @return (string | bool)
     */
    function mb_internal_encoding(?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_internal_encoding($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_language')) {
    /**
     * @return (string | bool)
     */
    function mb_language(?string $language = null)
    {
        $phabelReturn = p\Mbstring::mb_language($language);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_list_encodings')) {
    /**
     *
     */
    function mb_list_encodings() : array
    {
        return p\Mbstring::mb_list_encodings();
    }
}
if (!function_exists('mb_encoding_aliases')) {
    /**
     *
     */
    function mb_encoding_aliases(?string $encoding) : array
    {
        return p\Mbstring::mb_encoding_aliases((string) $encoding);
    }
}
if (!function_exists('mb_check_encoding')) {
    /**
     * @param (array | string | null) $value
     */
    function mb_check_encoding($value = null, ?string $encoding = null) : bool
    {
        if (!(\is_null($value) || \is_null($value))) {
            if (!\is_string($value)) {
                if (!(\is_string($value) || \is_object($value) && \method_exists($value, '__toString') || (\is_bool($value) || \is_numeric($value)))) {
                    if (!\is_array($value)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($value) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $value = (string) $value;
                }
            }
        }
        return p\Mbstring::mb_check_encoding($value, $encoding);
    }
}
if (!function_exists('mb_detect_encoding')) {
    /**
     * @param (array | string | null) $encodings
     * @return (string | false)
     */
    function mb_detect_encoding(?string $string, $encodings = null, ?bool $strict = false)
    {
        if (!(\is_null($encodings) || \is_null($encodings))) {
            if (!\is_string($encodings)) {
                if (!(\is_string($encodings) || \is_object($encodings) && \method_exists($encodings, '__toString') || (\is_bool($encodings) || \is_numeric($encodings)))) {
                    if (!\is_array($encodings)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #2 ($encodings) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($encodings) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $encodings = (string) $encodings;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_detect_order')) {
    /**
     * @param (array | string | null) $encoding
     * @return (array | bool)
     */
    function mb_detect_order($encoding = null)
    {
        if (!(\is_null($encoding) || \is_null($encoding))) {
            if (!\is_string($encoding)) {
                if (!(\is_string($encoding) || \is_object($encoding) && \method_exists($encoding, '__toString') || (\is_bool($encoding) || \is_numeric($encoding)))) {
                    if (!\is_array($encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($encoding) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $encoding = (string) $encoding;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_detect_order($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_array($phabelReturn)) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type array|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_parse_str')) {
    /**
     *
     */
    function mb_parse_str(?string $string, &$result = []) : bool
    {
        parse_str((string) $string, $result);
        return (bool) $result;
    }
}
if (!function_exists('mb_strlen')) {
    /**
     *
     */
    function mb_strlen(?string $string, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_strlen((string) $string, $encoding);
    }
}
if (!function_exists('mb_strpos')) {
    /**
     * @return (int | false)
     */
    function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strtolower')) {
    /**
     *
     */
    function mb_strtolower(?string $string, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_strtolower((string) $string, $encoding);
    }
}
if (!function_exists('mb_strtoupper')) {
    /**
     *
     */
    function mb_strtoupper(?string $string, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_strtoupper((string) $string, $encoding);
    }
}
if (!function_exists('mb_substitute_character')) {
    /**
     * @param (string | int | null) $substitute_character
     * @return (string | int | bool)
     */
    function mb_substitute_character($substitute_character = null)
    {
        if (!(\is_null($substitute_character) || \is_null($substitute_character))) {
            if (!\is_int($substitute_character)) {
                if (!(\is_bool($substitute_character) || \is_numeric($substitute_character))) {
                    if (!\is_string($substitute_character)) {
                        if (!(\is_string($substitute_character) || \is_object($substitute_character) && \method_exists($substitute_character, '__toString') || (\is_bool($substitute_character) || \is_numeric($substitute_character)))) {
                            throw new \TypeError(__METHOD__ . '(): Argument #1 ($substitute_character) must be of type ?string|int|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($substitute_character) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                        } else {
                            $substitute_character = (string) $substitute_character;
                        }
                    }
                } else {
                    $substitute_character = (int) $substitute_character;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_substitute_character($substitute_character);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        if (!\is_string($phabelReturn)) {
                            if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                                throw new \TypeError(__METHOD__ . '(): Return value must be of type string|int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                            } else {
                                $phabelReturn = (string) $phabelReturn;
                            }
                        }
                    } else {
                        $phabelReturn = (int) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_substr')) {
    /**
     *
     */
    function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding);
    }
}
if (!function_exists('mb_stripos')) {
    /**
     * @return (int | false)
     */
    function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_stristr')) {
    /**
     * @return (string | false)
     */
    function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrchr')) {
    /**
     * @return (string | false)
     */
    function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrichr')) {
    /**
     * @return (string | false)
     */
    function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strripos')) {
    /**
     * @return (int | false)
     */
    function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrpos')) {
    /**
     * @return (int | false)
     */
    function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strstr')) {
    /**
     * @return (string | false)
     */
    function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_get_info')) {
    /**
     * @return (array | string | int | false)
     */
    function mb_get_info(?string $type = 'all')
    {
        $phabelReturn = p\Mbstring::mb_get_info((string) $type);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    if (!\is_string($phabelReturn)) {
                        if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                            if (!\is_array($phabelReturn)) {
                                throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                            }
                        } else {
                            $phabelReturn = (string) $phabelReturn;
                        }
                    }
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_http_output')) {
    /**
     * @return (string | bool)
     */
    function mb_http_output(?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_http_output($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strwidth')) {
    /**
     *
     */
    function mb_strwidth(?string $string, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_strwidth((string) $string, $encoding);
    }
}
if (!function_exists('mb_substr_count')) {
    /**
     *
     */
    function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding);
    }
}
if (!function_exists('mb_output_handler')) {
    /**
     *
     */
    function mb_output_handler(?string $string, ?int $status) : string
    {
        return p\Mbstring::mb_output_handler((string) $string, (int) $status);
    }
}
if (!function_exists('mb_http_input')) {
    /**
     * @return (array | string | false)
     */
    function mb_http_input(?string $type = null)
    {
        $phabelReturn = p\Mbstring::mb_http_input($type);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    if (!\is_array($phabelReturn)) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_convert_variables')) {
    /**
     * @param (array | string | null) $from_encoding
     * @param mixed $var
     * @param mixed ...$vars
     * @return (string | false)
     */
    function mb_convert_variables(?string $to_encoding, $from_encoding, &$var, &...$vars)
    {
        if (!\is_null($from_encoding)) {
            if (!\is_string($from_encoding)) {
                if (!(\is_string($from_encoding) || \is_object($from_encoding) && \method_exists($from_encoding, '__toString') || (\is_bool($from_encoding) || \is_numeric($from_encoding)))) {
                    if (!\is_array($from_encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #2 ($from_encoding) must be of type array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($from_encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $from_encoding = (string) $from_encoding;
                }
            }
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #3 ($var) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($var) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        foreach ($vars as $phabelVariadicIndex => $phabelVariadic) {
            if (!true) {
                throw new \TypeError(__METHOD__ . '(): Argument #' . (4 + $phabelVariadicIndex) . ' must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($vars) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
        }
        $phabelReturn = p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_ord')) {
    /**
     * @return (int | false)
     */
    function mb_ord(?string $string, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_ord((string) $string, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_chr')) {
    /**
     * @return (string | false)
     */
    function mb_chr(?int $codepoint, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_chr((int) $codepoint, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_scrub')) {
    /**
     *
     */
    function mb_scrub(?string $string, ?string $encoding = null) : string
    {
        $encoding ??= mb_internal_encoding();
        return mb_convert_encoding((string) $string, $encoding, $encoding);
    }
}
if (!function_exists('mb_str_split')) {
    /**
     *
     */
    function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null) : array
    {
        return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding);
    }
}
if (extension_loaded('mbstring')) {
    return;
}
if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}<?php

// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt
return '/(?<![\\x{0027}\\x{002E}\\x{003A}\\x{005E}\\x{0060}\\x{00A8}\\x{00AD}\\x{00AF}\\x{00B4}\\x{00B7}\\x{00B8}\\x{02B0}-\\x{02C1}\\x{02C2}-\\x{02C5}\\x{02C6}-\\x{02D1}\\x{02D2}-\\x{02DF}\\x{02E0}-\\x{02E4}\\x{02E5}-\\x{02EB}\\x{02EC}\\x{02ED}\\x{02EE}\\x{02EF}-\\x{02FF}\\x{0300}-\\x{036F}\\x{0374}\\x{0375}\\x{037A}\\x{0384}-\\x{0385}\\x{0387}\\x{0483}-\\x{0487}\\x{0488}-\\x{0489}\\x{0559}\\x{0591}-\\x{05BD}\\x{05BF}\\x{05C1}-\\x{05C2}\\x{05C4}-\\x{05C5}\\x{05C7}\\x{05F4}\\x{0600}-\\x{0605}\\x{0610}-\\x{061A}\\x{061C}\\x{0640}\\x{064B}-\\x{065F}\\x{0670}\\x{06D6}-\\x{06DC}\\x{06DD}\\x{06DF}-\\x{06E4}\\x{06E5}-\\x{06E6}\\x{06E7}-\\x{06E8}\\x{06EA}-\\x{06ED}\\x{070F}\\x{0711}\\x{0730}-\\x{074A}\\x{07A6}-\\x{07B0}\\x{07EB}-\\x{07F3}\\x{07F4}-\\x{07F5}\\x{07FA}\\x{07FD}\\x{0816}-\\x{0819}\\x{081A}\\x{081B}-\\x{0823}\\x{0824}\\x{0825}-\\x{0827}\\x{0828}\\x{0829}-\\x{082D}\\x{0859}-\\x{085B}\\x{08D3}-\\x{08E1}\\x{08E2}\\x{08E3}-\\x{0902}\\x{093A}\\x{093C}\\x{0941}-\\x{0948}\\x{094D}\\x{0951}-\\x{0957}\\x{0962}-\\x{0963}\\x{0971}\\x{0981}\\x{09BC}\\x{09C1}-\\x{09C4}\\x{09CD}\\x{09E2}-\\x{09E3}\\x{09FE}\\x{0A01}-\\x{0A02}\\x{0A3C}\\x{0A41}-\\x{0A42}\\x{0A47}-\\x{0A48}\\x{0A4B}-\\x{0A4D}\\x{0A51}\\x{0A70}-\\x{0A71}\\x{0A75}\\x{0A81}-\\x{0A82}\\x{0ABC}\\x{0AC1}-\\x{0AC5}\\x{0AC7}-\\x{0AC8}\\x{0ACD}\\x{0AE2}-\\x{0AE3}\\x{0AFA}-\\x{0AFF}\\x{0B01}\\x{0B3C}\\x{0B3F}\\x{0B41}-\\x{0B44}\\x{0B4D}\\x{0B56}\\x{0B62}-\\x{0B63}\\x{0B82}\\x{0BC0}\\x{0BCD}\\x{0C00}\\x{0C04}\\x{0C3E}-\\x{0C40}\\x{0C46}-\\x{0C48}\\x{0C4A}-\\x{0C4D}\\x{0C55}-\\x{0C56}\\x{0C62}-\\x{0C63}\\x{0C81}\\x{0CBC}\\x{0CBF}\\x{0CC6}\\x{0CCC}-\\x{0CCD}\\x{0CE2}-\\x{0CE3}\\x{0D00}-\\x{0D01}\\x{0D3B}-\\x{0D3C}\\x{0D41}-\\x{0D44}\\x{0D4D}\\x{0D62}-\\x{0D63}\\x{0DCA}\\x{0DD2}-\\x{0DD4}\\x{0DD6}\\x{0E31}\\x{0E34}-\\x{0E3A}\\x{0E46}\\x{0E47}-\\x{0E4E}\\x{0EB1}\\x{0EB4}-\\x{0EB9}\\x{0EBB}-\\x{0EBC}\\x{0EC6}\\x{0EC8}-\\x{0ECD}\\x{0F18}-\\x{0F19}\\x{0F35}\\x{0F37}\\x{0F39}\\x{0F71}-\\x{0F7E}\\x{0F80}-\\x{0F84}\\x{0F86}-\\x{0F87}\\x{0F8D}-\\x{0F97}\\x{0F99}-\\x{0FBC}\\x{0FC6}\\x{102D}-\\x{1030}\\x{1032}-\\x{1037}\\x{1039}-\\x{103A}\\x{103D}-\\x{103E}\\x{1058}-\\x{1059}\\x{105E}-\\x{1060}\\x{1071}-\\x{1074}\\x{1082}\\x{1085}-\\x{1086}\\x{108D}\\x{109D}\\x{10FC}\\x{135D}-\\x{135F}\\x{1712}-\\x{1714}\\x{1732}-\\x{1734}\\x{1752}-\\x{1753}\\x{1772}-\\x{1773}\\x{17B4}-\\x{17B5}\\x{17B7}-\\x{17BD}\\x{17C6}\\x{17C9}-\\x{17D3}\\x{17D7}\\x{17DD}\\x{180B}-\\x{180D}\\x{180E}\\x{1843}\\x{1885}-\\x{1886}\\x{18A9}\\x{1920}-\\x{1922}\\x{1927}-\\x{1928}\\x{1932}\\x{1939}-\\x{193B}\\x{1A17}-\\x{1A18}\\x{1A1B}\\x{1A56}\\x{1A58}-\\x{1A5E}\\x{1A60}\\x{1A62}\\x{1A65}-\\x{1A6C}\\x{1A73}-\\x{1A7C}\\x{1A7F}\\x{1AA7}\\x{1AB0}-\\x{1ABD}\\x{1ABE}\\x{1B00}-\\x{1B03}\\x{1B34}\\x{1B36}-\\x{1B3A}\\x{1B3C}\\x{1B42}\\x{1B6B}-\\x{1B73}\\x{1B80}-\\x{1B81}\\x{1BA2}-\\x{1BA5}\\x{1BA8}-\\x{1BA9}\\x{1BAB}-\\x{1BAD}\\x{1BE6}\\x{1BE8}-\\x{1BE9}\\x{1BED}\\x{1BEF}-\\x{1BF1}\\x{1C2C}-\\x{1C33}\\x{1C36}-\\x{1C37}\\x{1C78}-\\x{1C7D}\\x{1CD0}-\\x{1CD2}\\x{1CD4}-\\x{1CE0}\\x{1CE2}-\\x{1CE8}\\x{1CED}\\x{1CF4}\\x{1CF8}-\\x{1CF9}\\x{1D2C}-\\x{1D6A}\\x{1D78}\\x{1D9B}-\\x{1DBF}\\x{1DC0}-\\x{1DF9}\\x{1DFB}-\\x{1DFF}\\x{1FBD}\\x{1FBF}-\\x{1FC1}\\x{1FCD}-\\x{1FCF}\\x{1FDD}-\\x{1FDF}\\x{1FED}-\\x{1FEF}\\x{1FFD}-\\x{1FFE}\\x{200B}-\\x{200F}\\x{2018}\\x{2019}\\x{2024}\\x{2027}\\x{202A}-\\x{202E}\\x{2060}-\\x{2064}\\x{2066}-\\x{206F}\\x{2071}\\x{207F}\\x{2090}-\\x{209C}\\x{20D0}-\\x{20DC}\\x{20DD}-\\x{20E0}\\x{20E1}\\x{20E2}-\\x{20E4}\\x{20E5}-\\x{20F0}\\x{2C7C}-\\x{2C7D}\\x{2CEF}-\\x{2CF1}\\x{2D6F}\\x{2D7F}\\x{2DE0}-\\x{2DFF}\\x{2E2F}\\x{3005}\\x{302A}-\\x{302D}\\x{3031}-\\x{3035}\\x{303B}\\x{3099}-\\x{309A}\\x{309B}-\\x{309C}\\x{309D}-\\x{309E}\\x{30FC}-\\x{30FE}\\x{A015}\\x{A4F8}-\\x{A4FD}\\x{A60C}\\x{A66F}\\x{A670}-\\x{A672}\\x{A674}-\\x{A67D}\\x{A67F}\\x{A69C}-\\x{A69D}\\x{A69E}-\\x{A69F}\\x{A6F0}-\\x{A6F1}\\x{A700}-\\x{A716}\\x{A717}-\\x{A71F}\\x{A720}-\\x{A721}\\x{A770}\\x{A788}\\x{A789}-\\x{A78A}\\x{A7F8}-\\x{A7F9}\\x{A802}\\x{A806}\\x{A80B}\\x{A825}-\\x{A826}\\x{A8C4}-\\x{A8C5}\\x{A8E0}-\\x{A8F1}\\x{A8FF}\\x{A926}-\\x{A92D}\\x{A947}-\\x{A951}\\x{A980}-\\x{A982}\\x{A9B3}\\x{A9B6}-\\x{A9B9}\\x{A9BC}\\x{A9CF}\\x{A9E5}\\x{A9E6}\\x{AA29}-\\x{AA2E}\\x{AA31}-\\x{AA32}\\x{AA35}-\\x{AA36}\\x{AA43}\\x{AA4C}\\x{AA70}\\x{AA7C}\\x{AAB0}\\x{AAB2}-\\x{AAB4}\\x{AAB7}-\\x{AAB8}\\x{AABE}-\\x{AABF}\\x{AAC1}\\x{AADD}\\x{AAEC}-\\x{AAED}\\x{AAF3}-\\x{AAF4}\\x{AAF6}\\x{AB5B}\\x{AB5C}-\\x{AB5F}\\x{ABE5}\\x{ABE8}\\x{ABED}\\x{FB1E}\\x{FBB2}-\\x{FBC1}\\x{FE00}-\\x{FE0F}\\x{FE13}\\x{FE20}-\\x{FE2F}\\x{FE52}\\x{FE55}\\x{FEFF}\\x{FF07}\\x{FF0E}\\x{FF1A}\\x{FF3E}\\x{FF40}\\x{FF70}\\x{FF9E}-\\x{FF9F}\\x{FFE3}\\x{FFF9}-\\x{FFFB}\\x{101FD}\\x{102E0}\\x{10376}-\\x{1037A}\\x{10A01}-\\x{10A03}\\x{10A05}-\\x{10A06}\\x{10A0C}-\\x{10A0F}\\x{10A38}-\\x{10A3A}\\x{10A3F}\\x{10AE5}-\\x{10AE6}\\x{10D24}-\\x{10D27}\\x{10F46}-\\x{10F50}\\x{11001}\\x{11038}-\\x{11046}\\x{1107F}-\\x{11081}\\x{110B3}-\\x{110B6}\\x{110B9}-\\x{110BA}\\x{110BD}\\x{110CD}\\x{11100}-\\x{11102}\\x{11127}-\\x{1112B}\\x{1112D}-\\x{11134}\\x{11173}\\x{11180}-\\x{11181}\\x{111B6}-\\x{111BE}\\x{111C9}-\\x{111CC}\\x{1122F}-\\x{11231}\\x{11234}\\x{11236}-\\x{11237}\\x{1123E}\\x{112DF}\\x{112E3}-\\x{112EA}\\x{11300}-\\x{11301}\\x{1133B}-\\x{1133C}\\x{11340}\\x{11366}-\\x{1136C}\\x{11370}-\\x{11374}\\x{11438}-\\x{1143F}\\x{11442}-\\x{11444}\\x{11446}\\x{1145E}\\x{114B3}-\\x{114B8}\\x{114BA}\\x{114BF}-\\x{114C0}\\x{114C2}-\\x{114C3}\\x{115B2}-\\x{115B5}\\x{115BC}-\\x{115BD}\\x{115BF}-\\x{115C0}\\x{115DC}-\\x{115DD}\\x{11633}-\\x{1163A}\\x{1163D}\\x{1163F}-\\x{11640}\\x{116AB}\\x{116AD}\\x{116B0}-\\x{116B5}\\x{116B7}\\x{1171D}-\\x{1171F}\\x{11722}-\\x{11725}\\x{11727}-\\x{1172B}\\x{1182F}-\\x{11837}\\x{11839}-\\x{1183A}\\x{11A01}-\\x{11A0A}\\x{11A33}-\\x{11A38}\\x{11A3B}-\\x{11A3E}\\x{11A47}\\x{11A51}-\\x{11A56}\\x{11A59}-\\x{11A5B}\\x{11A8A}-\\x{11A96}\\x{11A98}-\\x{11A99}\\x{11C30}-\\x{11C36}\\x{11C38}-\\x{11C3D}\\x{11C3F}\\x{11C92}-\\x{11CA7}\\x{11CAA}-\\x{11CB0}\\x{11CB2}-\\x{11CB3}\\x{11CB5}-\\x{11CB6}\\x{11D31}-\\x{11D36}\\x{11D3A}\\x{11D3C}-\\x{11D3D}\\x{11D3F}-\\x{11D45}\\x{11D47}\\x{11D90}-\\x{11D91}\\x{11D95}\\x{11D97}\\x{11EF3}-\\x{11EF4}\\x{16AF0}-\\x{16AF4}\\x{16B30}-\\x{16B36}\\x{16B40}-\\x{16B43}\\x{16F8F}-\\x{16F92}\\x{16F93}-\\x{16F9F}\\x{16FE0}-\\x{16FE1}\\x{1BC9D}-\\x{1BC9E}\\x{1BCA0}-\\x{1BCA3}\\x{1D167}-\\x{1D169}\\x{1D173}-\\x{1D17A}\\x{1D17B}-\\x{1D182}\\x{1D185}-\\x{1D18B}\\x{1D1AA}-\\x{1D1AD}\\x{1D242}-\\x{1D244}\\x{1DA00}-\\x{1DA36}\\x{1DA3B}-\\x{1DA6C}\\x{1DA75}\\x{1DA84}\\x{1DA9B}-\\x{1DA9F}\\x{1DAA1}-\\x{1DAAF}\\x{1E000}-\\x{1E006}\\x{1E008}-\\x{1E018}\\x{1E01B}-\\x{1E021}\\x{1E023}-\\x{1E024}\\x{1E026}-\\x{1E02A}\\x{1E8D0}-\\x{1E8D6}\\x{1E944}-\\x{1E94A}\\x{1F3FB}-\\x{1F3FF}\\x{E0001}\\x{E0020}-\\x{E007F}\\x{E0100}-\\x{E01EF}])(\\pL)(\\pL*+)/u';<?php

return array('A' => 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e', 'F' => 'f', 'G' => 'g', 'H' => 'h', 'I' => 'i', 'J' => 'j', 'K' => 'k', 'L' => 'l', 'M' => 'm', 'N' => 'n', 'O' => 'o', 'P' => 'p', 'Q' => 'q', 'R' => 'r', 'S' => 's', 'T' => 't', 'U' => 'u', 'V' => 'v', 'W' => 'w', 'X' => 'x', 'Y' => 'y', 'Z' => 'z', 'Ã€' => 'Ã ', 'Ã�' => 'Ã¡', 'Ã‚' => 'Ã¢', 'Ãƒ' => 'Ã£', 'Ã„' => 'Ã¤', 'Ã…' => 'Ã¥', 'Ã†' => 'Ã¦', 'Ã‡' => 'Ã§', 'Ãˆ' => 'Ã¨', 'Ã‰' => 'Ã©', 'ÃŠ' => 'Ãª', 'Ã‹' => 'Ã«', 'ÃŒ' => 'Ã¬', 'Ã�' => 'Ã­', 'ÃŽ' => 'Ã®', 'Ã�' => 'Ã¯', 'Ã�' => 'Ã°', 'Ã‘' => 'Ã±', 'Ã’' => 'Ã²', 'Ã“' => 'Ã³', 'Ã”' => 'Ã´', 'Ã•' => 'Ãµ', 'Ã–' => 'Ã¶', 'Ã˜' => 'Ã¸', 'Ã™' => 'Ã¹', 'Ãš' => 'Ãº', 'Ã›' => 'Ã»', 'Ãœ' => 'Ã¼', 'Ã�' => 'Ã½', 'Ãž' => 'Ã¾', 'Ä€' => 'Ä�', 'Ä‚' => 'Äƒ', 'Ä„' => 'Ä…', 'Ä†' => 'Ä‡', 'Äˆ' => 'Ä‰', 'ÄŠ' => 'Ä‹', 'ÄŒ' => 'Ä�', 'ÄŽ' => 'Ä�', 'Ä�' => 'Ä‘', 'Ä’' => 'Ä“', 'Ä”' => 'Ä•', 'Ä–' => 'Ä—', 'Ä˜' => 'Ä™', 'Äš' => 'Ä›', 'Äœ' => 'Ä�', 'Äž' => 'ÄŸ', 'Ä ' => 'Ä¡', 'Ä¢' => 'Ä£', 'Ä¤' => 'Ä¥', 'Ä¦' => 'Ä§', 'Ä¨' => 'Ä©', 'Äª' => 'Ä«', 'Ä¬' => 'Ä­', 'Ä®' => 'Ä¯', 'Ä°' => 'iÌ‡', 'Ä²' => 'Ä³', 'Ä´' => 'Äµ', 'Ä¶' => 'Ä·', 'Ä¹' => 'Äº', 'Ä»' => 'Ä¼', 'Ä½' => 'Ä¾', 'Ä¿' => 'Å€', 'Å�' => 'Å‚', 'Åƒ' => 'Å„', 'Å…' => 'Å†', 'Å‡' => 'Åˆ', 'ÅŠ' => 'Å‹', 'ÅŒ' => 'Å�', 'ÅŽ' => 'Å�', 'Å�' => 'Å‘', 'Å’' => 'Å“', 'Å”' => 'Å•', 'Å–' => 'Å—', 'Å˜' => 'Å™', 'Åš' => 'Å›', 'Åœ' => 'Å�', 'Åž' => 'ÅŸ', 'Å ' => 'Å¡', 'Å¢' => 'Å£', 'Å¤' => 'Å¥', 'Å¦' => 'Å§', 'Å¨' => 'Å©', 'Åª' => 'Å«', 'Å¬' => 'Å­', 'Å®' => 'Å¯', 'Å°' => 'Å±', 'Å²' => 'Å³', 'Å´' => 'Åµ', 'Å¶' => 'Å·', 'Å¸' => 'Ã¿', 'Å¹' => 'Åº', 'Å»' => 'Å¼', 'Å½' => 'Å¾', 'Æ�' => 'É“', 'Æ‚' => 'Æƒ', 'Æ„' => 'Æ…', 'Æ†' => 'É”', 'Æ‡' => 'Æˆ', 'Æ‰' => 'É–', 'ÆŠ' => 'É—', 'Æ‹' => 'ÆŒ', 'ÆŽ' => 'Ç�', 'Æ�' => 'É™', 'Æ�' => 'É›', 'Æ‘' => 'Æ’', 'Æ“' => 'É ', 'Æ”' => 'É£', 'Æ–' => 'É©', 'Æ—' => 'É¨', 'Æ˜' => 'Æ™', 'Æœ' => 'É¯', 'Æ�' => 'É²', 'ÆŸ' => 'Éµ', 'Æ ' => 'Æ¡', 'Æ¢' => 'Æ£', 'Æ¤' => 'Æ¥', 'Æ¦' => 'Ê€', 'Æ§' => 'Æ¨', 'Æ©' => 'Êƒ', 'Æ¬' => 'Æ­', 'Æ®' => 'Êˆ', 'Æ¯' => 'Æ°', 'Æ±' => 'ÊŠ', 'Æ²' => 'Ê‹', 'Æ³' => 'Æ´', 'Æµ' => 'Æ¶', 'Æ·' => 'Ê’', 'Æ¸' => 'Æ¹', 'Æ¼' => 'Æ½', 'Ç„' => 'Ç†', 'Ç…' => 'Ç†', 'Ç‡' => 'Ç‰', 'Çˆ' => 'Ç‰', 'ÇŠ' => 'ÇŒ', 'Ç‹' => 'ÇŒ', 'Ç�' => 'ÇŽ', 'Ç�' => 'Ç�', 'Ç‘' => 'Ç’', 'Ç“' => 'Ç”', 'Ç•' => 'Ç–', 'Ç—' => 'Ç˜', 'Ç™' => 'Çš', 'Ç›' => 'Çœ', 'Çž' => 'ÇŸ', 'Ç ' => 'Ç¡', 'Ç¢' => 'Ç£', 'Ç¤' => 'Ç¥', 'Ç¦' => 'Ç§', 'Ç¨' => 'Ç©', 'Çª' => 'Ç«', 'Ç¬' => 'Ç­', 'Ç®' => 'Ç¯', 'Ç±' => 'Ç³', 'Ç²' => 'Ç³', 'Ç´' => 'Çµ', 'Ç¶' => 'Æ•', 'Ç·' => 'Æ¿', 'Ç¸' => 'Ç¹', 'Çº' => 'Ç»', 'Ç¼' => 'Ç½', 'Ç¾' => 'Ç¿', 'È€' => 'È�', 'È‚' => 'Èƒ', 'È„' => 'È…', 'È†' => 'È‡', 'Èˆ' => 'È‰', 'ÈŠ' => 'È‹', 'ÈŒ' => 'È�', 'ÈŽ' => 'È�', 'È�' => 'È‘', 'È’' => 'È“', 'È”' => 'È•', 'È–' => 'È—', 'È˜' => 'È™', 'Èš' => 'È›', 'Èœ' => 'È�', 'Èž' => 'ÈŸ', 'È ' => 'Æž', 'È¢' => 'È£', 'È¤' => 'È¥', 'È¦' => 'È§', 'È¨' => 'È©', 'Èª' => 'È«', 'È¬' => 'È­', 'È®' => 'È¯', 'È°' => 'È±', 'È²' => 'È³', 'Èº' => 'â±¥', 'È»' => 'È¼', 'È½' => 'Æš', 'È¾' => 'â±¦', 'É�' => 'É‚', 'Éƒ' => 'Æ€', 'É„' => 'Ê‰', 'É…' => 'ÊŒ', 'É†' => 'É‡', 'Éˆ' => 'É‰', 'ÉŠ' => 'É‹', 'ÉŒ' => 'É�', 'ÉŽ' => 'É�', 'Í°' => 'Í±', 'Í²' => 'Í³', 'Í¶' => 'Í·', 'Í¿' => 'Ï³', 'Î†' => 'Î¬', 'Îˆ' => 'Î­', 'Î‰' => 'Î®', 'ÎŠ' => 'Î¯', 'ÎŒ' => 'ÏŒ', 'ÎŽ' => 'Ï�', 'Î�' => 'ÏŽ', 'Î‘' => 'Î±', 'Î’' => 'Î²', 'Î“' => 'Î³', 'Î”' => 'Î´', 'Î•' => 'Îµ', 'Î–' => 'Î¶', 'Î—' => 'Î·', 'Î˜' => 'Î¸', 'Î™' => 'Î¹', 'Îš' => 'Îº', 'Î›' => 'Î»', 'Îœ' => 'Î¼', 'Î�' => 'Î½', 'Îž' => 'Î¾', 'ÎŸ' => 'Î¿', 'Î ' => 'Ï€', 'Î¡' => 'Ï�', 'Î£' => 'Ïƒ', 'Î¤' => 'Ï„', 'Î¥' => 'Ï…', 'Î¦' => 'Ï†', 'Î§' => 'Ï‡', 'Î¨' => 'Ïˆ', 'Î©' => 'Ï‰', 'Îª' => 'ÏŠ', 'Î«' => 'Ï‹', 'Ï�' => 'Ï—', 'Ï˜' => 'Ï™', 'Ïš' => 'Ï›', 'Ïœ' => 'Ï�', 'Ïž' => 'ÏŸ', 'Ï ' => 'Ï¡', 'Ï¢' => 'Ï£', 'Ï¤' => 'Ï¥', 'Ï¦' => 'Ï§', 'Ï¨' => 'Ï©', 'Ïª' => 'Ï«', 'Ï¬' => 'Ï­', 'Ï®' => 'Ï¯', 'Ï´' => 'Î¸', 'Ï·' => 'Ï¸', 'Ï¹' => 'Ï²', 'Ïº' => 'Ï»', 'Ï½' => 'Í»', 'Ï¾' => 'Í¼', 'Ï¿' => 'Í½', 'Ð€' => 'Ñ�', 'Ð�' => 'Ñ‘', 'Ð‚' => 'Ñ’', 'Ðƒ' => 'Ñ“', 'Ð„' => 'Ñ”', 'Ð…' => 'Ñ•', 'Ð†' => 'Ñ–', 'Ð‡' => 'Ñ—', 'Ðˆ' => 'Ñ˜', 'Ð‰' => 'Ñ™', 'ÐŠ' => 'Ñš', 'Ð‹' => 'Ñ›', 'ÐŒ' => 'Ñœ', 'Ð�' => 'Ñ�', 'ÐŽ' => 'Ñž', 'Ð�' => 'ÑŸ', 'Ð�' => 'Ð°', 'Ð‘' => 'Ð±', 'Ð’' => 'Ð²', 'Ð“' => 'Ð³', 'Ð”' => 'Ð´', 'Ð•' => 'Ðµ', 'Ð–' => 'Ð¶', 'Ð—' => 'Ð·', 'Ð˜' => 'Ð¸', 'Ð™' => 'Ð¹', 'Ðš' => 'Ðº', 'Ð›' => 'Ð»', 'Ðœ' => 'Ð¼', 'Ð�' => 'Ð½', 'Ðž' => 'Ð¾', 'ÐŸ' => 'Ð¿', 'Ð ' => 'Ñ€', 'Ð¡' => 'Ñ�', 'Ð¢' => 'Ñ‚', 'Ð£' => 'Ñƒ', 'Ð¤' => 'Ñ„', 'Ð¥' => 'Ñ…', 'Ð¦' => 'Ñ†', 'Ð§' => 'Ñ‡', 'Ð¨' => 'Ñˆ', 'Ð©' => 'Ñ‰', 'Ðª' => 'ÑŠ', 'Ð«' => 'Ñ‹', 'Ð¬' => 'ÑŒ', 'Ð­' => 'Ñ�', 'Ð®' => 'ÑŽ', 'Ð¯' => 'Ñ�', 'Ñ ' => 'Ñ¡', 'Ñ¢' => 'Ñ£', 'Ñ¤' => 'Ñ¥', 'Ñ¦' => 'Ñ§', 'Ñ¨' => 'Ñ©', 'Ñª' => 'Ñ«', 'Ñ¬' => 'Ñ­', 'Ñ®' => 'Ñ¯', 'Ñ°' => 'Ñ±', 'Ñ²' => 'Ñ³', 'Ñ´' => 'Ñµ', 'Ñ¶' => 'Ñ·', 'Ñ¸' => 'Ñ¹', 'Ñº' => 'Ñ»', 'Ñ¼' => 'Ñ½', 'Ñ¾' => 'Ñ¿', 'Ò€' => 'Ò�', 'ÒŠ' => 'Ò‹', 'ÒŒ' => 'Ò�', 'ÒŽ' => 'Ò�', 'Ò�' => 'Ò‘', 'Ò’' => 'Ò“', 'Ò”' => 'Ò•', 'Ò–' => 'Ò—', 'Ò˜' => 'Ò™', 'Òš' => 'Ò›', 'Òœ' => 'Ò�', 'Òž' => 'ÒŸ', 'Ò ' => 'Ò¡', 'Ò¢' => 'Ò£', 'Ò¤' => 'Ò¥', 'Ò¦' => 'Ò§', 'Ò¨' => 'Ò©', 'Òª' => 'Ò«', 'Ò¬' => 'Ò­', 'Ò®' => 'Ò¯', 'Ò°' => 'Ò±', 'Ò²' => 'Ò³', 'Ò´' => 'Òµ', 'Ò¶' => 'Ò·', 'Ò¸' => 'Ò¹', 'Òº' => 'Ò»', 'Ò¼' => 'Ò½', 'Ò¾' => 'Ò¿', 'Ó€' => 'Ó�', 'Ó�' => 'Ó‚', 'Óƒ' => 'Ó„', 'Ó…' => 'Ó†', 'Ó‡' => 'Óˆ', 'Ó‰' => 'ÓŠ', 'Ó‹' => 'ÓŒ', 'Ó�' => 'ÓŽ', 'Ó�' => 'Ó‘', 'Ó’' => 'Ó“', 'Ó”' => 'Ó•', 'Ó–' => 'Ó—', 'Ó˜' => 'Ó™', 'Óš' => 'Ó›', 'Óœ' => 'Ó�', 'Óž' => 'ÓŸ', 'Ó ' => 'Ó¡', 'Ó¢' => 'Ó£', 'Ó¤' => 'Ó¥', 'Ó¦' => 'Ó§', 'Ó¨' => 'Ó©', 'Óª' => 'Ó«', 'Ó¬' => 'Ó­', 'Ó®' => 'Ó¯', 'Ó°' => 'Ó±', 'Ó²' => 'Ó³', 'Ó´' => 'Óµ', 'Ó¶' => 'Ó·', 'Ó¸' => 'Ó¹', 'Óº' => 'Ó»', 'Ó¼' => 'Ó½', 'Ó¾' => 'Ó¿', 'Ô€' => 'Ô�', 'Ô‚' => 'Ôƒ', 'Ô„' => 'Ô…', 'Ô†' => 'Ô‡', 'Ôˆ' => 'Ô‰', 'ÔŠ' => 'Ô‹', 'ÔŒ' => 'Ô�', 'ÔŽ' => 'Ô�', 'Ô�' => 'Ô‘', 'Ô’' => 'Ô“', 'Ô”' => 'Ô•', 'Ô–' => 'Ô—', 'Ô˜' => 'Ô™', 'Ôš' => 'Ô›', 'Ôœ' => 'Ô�', 'Ôž' => 'ÔŸ', 'Ô ' => 'Ô¡', 'Ô¢' => 'Ô£', 'Ô¤' => 'Ô¥', 'Ô¦' => 'Ô§', 'Ô¨' => 'Ô©', 'Ôª' => 'Ô«', 'Ô¬' => 'Ô­', 'Ô®' => 'Ô¯', 'Ô±' => 'Õ¡', 'Ô²' => 'Õ¢', 'Ô³' => 'Õ£', 'Ô´' => 'Õ¤', 'Ôµ' => 'Õ¥', 'Ô¶' => 'Õ¦', 'Ô·' => 'Õ§', 'Ô¸' => 'Õ¨', 'Ô¹' => 'Õ©', 'Ôº' => 'Õª', 'Ô»' => 'Õ«', 'Ô¼' => 'Õ¬', 'Ô½' => 'Õ­', 'Ô¾' => 'Õ®', 'Ô¿' => 'Õ¯', 'Õ€' => 'Õ°', 'Õ�' => 'Õ±', 'Õ‚' => 'Õ²', 'Õƒ' => 'Õ³', 'Õ„' => 'Õ´', 'Õ…' => 'Õµ', 'Õ†' => 'Õ¶', 'Õ‡' => 'Õ·', 'Õˆ' => 'Õ¸', 'Õ‰' => 'Õ¹', 'ÕŠ' => 'Õº', 'Õ‹' => 'Õ»', 'ÕŒ' => 'Õ¼', 'Õ�' => 'Õ½', 'ÕŽ' => 'Õ¾', 'Õ�' => 'Õ¿', 'Õ�' => 'Ö€', 'Õ‘' => 'Ö�', 'Õ’' => 'Ö‚', 'Õ“' => 'Öƒ', 'Õ”' => 'Ö„', 'Õ•' => 'Ö…', 'Õ–' => 'Ö†', 'á‚ ' => 'â´€', 'á‚¡' => 'â´�', 'á‚¢' => 'â´‚', 'á‚£' => 'â´ƒ', 'á‚¤' => 'â´„', 'á‚¥' => 'â´…', 'á‚¦' => 'â´†', 'á‚§' => 'â´‡', 'á‚¨' => 'â´ˆ', 'á‚©' => 'â´‰', 'á‚ª' => 'â´Š', 'á‚«' => 'â´‹', 'á‚¬' => 'â´Œ', 'á‚­' => 'â´�', 'á‚®' => 'â´Ž', 'á‚¯' => 'â´�', 'á‚°' => 'â´�', 'á‚±' => 'â´‘', 'á‚²' => 'â´’', 'á‚³' => 'â´“', 'á‚´' => 'â´”', 'á‚µ' => 'â´•', 'á‚¶' => 'â´–', 'á‚·' => 'â´—', 'á‚¸' => 'â´˜', 'á‚¹' => 'â´™', 'á‚º' => 'â´š', 'á‚»' => 'â´›', 'á‚¼' => 'â´œ', 'á‚½' => 'â´�', 'á‚¾' => 'â´ž', 'á‚¿' => 'â´Ÿ', 'áƒ€' => 'â´ ', 'áƒ�' => 'â´¡', 'áƒ‚' => 'â´¢', 'áƒƒ' => 'â´£', 'áƒ„' => 'â´¤', 'áƒ…' => 'â´¥', 'áƒ‡' => 'â´§', 'áƒ�' => 'â´­', 'áŽ ' => 'ê­°', 'áŽ¡' => 'ê­±', 'áŽ¢' => 'ê­²', 'áŽ£' => 'ê­³', 'áŽ¤' => 'ê­´', 'áŽ¥' => 'ê­µ', 'áŽ¦' => 'ê­¶', 'áŽ§' => 'ê­·', 'áŽ¨' => 'ê­¸', 'áŽ©' => 'ê­¹', 'áŽª' => 'ê­º', 'áŽ«' => 'ê­»', 'áŽ¬' => 'ê­¼', 'áŽ­' => 'ê­½', 'áŽ®' => 'ê­¾', 'áŽ¯' => 'ê­¿', 'áŽ°' => 'ê®€', 'áŽ±' => 'ê®�', 'áŽ²' => 'ê®‚', 'áŽ³' => 'ê®ƒ', 'áŽ´' => 'ê®„', 'áŽµ' => 'ê®…', 'áŽ¶' => 'ê®†', 'áŽ·' => 'ê®‡', 'áŽ¸' => 'ê®ˆ', 'áŽ¹' => 'ê®‰', 'áŽº' => 'ê®Š', 'áŽ»' => 'ê®‹', 'áŽ¼' => 'ê®Œ', 'áŽ½' => 'ê®�', 'áŽ¾' => 'ê®Ž', 'áŽ¿' => 'ê®�', 'á�€' => 'ê®�', 'á��' => 'ê®‘', 'á�‚' => 'ê®’', 'á�ƒ' => 'ê®“', 'á�„' => 'ê®”', 'á�…' => 'ê®•', 'á�†' => 'ê®–', 'á�‡' => 'ê®—', 'á�ˆ' => 'ê®˜', 'á�‰' => 'ê®™', 'á�Š' => 'ê®š', 'á�‹' => 'ê®›', 'á�Œ' => 'ê®œ', 'á��' => 'ê®�', 'á�Ž' => 'ê®ž', 'á��' => 'ê®Ÿ', 'á��' => 'ê® ', 'á�‘' => 'ê®¡', 'á�’' => 'ê®¢', 'á�“' => 'ê®£', 'á�”' => 'ê®¤', 'á�•' => 'ê®¥', 'á�–' => 'ê®¦', 'á�—' => 'ê®§', 'á�˜' => 'ê®¨', 'á�™' => 'ê®©', 'á�š' => 'ê®ª', 'á�›' => 'ê®«', 'á�œ' => 'ê®¬', 'á��' => 'ê®­', 'á�ž' => 'ê®®', 'á�Ÿ' => 'ê®¯', 'á� ' => 'ê®°', 'á�¡' => 'ê®±', 'á�¢' => 'ê®²', 'á�£' => 'ê®³', 'á�¤' => 'ê®´', 'á�¥' => 'ê®µ', 'á�¦' => 'ê®¶', 'á�§' => 'ê®·', 'á�¨' => 'ê®¸', 'á�©' => 'ê®¹', 'á�ª' => 'ê®º', 'á�«' => 'ê®»', 'á�¬' => 'ê®¼', 'á�­' => 'ê®½', 'á�®' => 'ê®¾', 'á�¯' => 'ê®¿', 'á�°' => 'á�¸', 'á�±' => 'á�¹', 'á�²' => 'á�º', 'á�³' => 'á�»', 'á�´' => 'á�¼', 'á�µ' => 'á�½', 'á²�' => 'áƒ�', 'á²‘' => 'áƒ‘', 'á²’' => 'áƒ’', 'á²“' => 'áƒ“', 'á²”' => 'áƒ”', 'á²•' => 'áƒ•', 'á²–' => 'áƒ–', 'á²—' => 'áƒ—', 'á²˜' => 'áƒ˜', 'á²™' => 'áƒ™', 'á²š' => 'áƒš', 'á²›' => 'áƒ›', 'á²œ' => 'áƒœ', 'á²�' => 'áƒ�', 'á²ž' => 'áƒž', 'á²Ÿ' => 'áƒŸ', 'á² ' => 'áƒ ', 'á²¡' => 'áƒ¡', 'á²¢' => 'áƒ¢', 'á²£' => 'áƒ£', 'á²¤' => 'áƒ¤', 'á²¥' => 'áƒ¥', 'á²¦' => 'áƒ¦', 'á²§' => 'áƒ§', 'á²¨' => 'áƒ¨', 'á²©' => 'áƒ©', 'á²ª' => 'áƒª', 'á²«' => 'áƒ«', 'á²¬' => 'áƒ¬', 'á²­' => 'áƒ­', 'á²®' => 'áƒ®', 'á²¯' => 'áƒ¯', 'á²°' => 'áƒ°', 'á²±' => 'áƒ±', 'á²²' => 'áƒ²', 'á²³' => 'áƒ³', 'á²´' => 'áƒ´', 'á²µ' => 'áƒµ', 'á²¶' => 'áƒ¶', 'á²·' => 'áƒ·', 'á²¸' => 'áƒ¸', 'á²¹' => 'áƒ¹', 'á²º' => 'áƒº', 'á²½' => 'áƒ½', 'á²¾' => 'áƒ¾', 'á²¿' => 'áƒ¿', 'á¸€' => 'á¸�', 'á¸‚' => 'á¸ƒ', 'á¸„' => 'á¸…', 'á¸†' => 'á¸‡', 'á¸ˆ' => 'á¸‰', 'á¸Š' => 'á¸‹', 'á¸Œ' => 'á¸�', 'á¸Ž' => 'á¸�', 'á¸�' => 'á¸‘', 'á¸’' => 'á¸“', 'á¸”' => 'á¸•', 'á¸–' => 'á¸—', 'á¸˜' => 'á¸™', 'á¸š' => 'á¸›', 'á¸œ' => 'á¸�', 'á¸ž' => 'á¸Ÿ', 'á¸ ' => 'á¸¡', 'á¸¢' => 'á¸£', 'á¸¤' => 'á¸¥', 'á¸¦' => 'á¸§', 'á¸¨' => 'á¸©', 'á¸ª' => 'á¸«', 'á¸¬' => 'á¸­', 'á¸®' => 'á¸¯', 'á¸°' => 'á¸±', 'á¸²' => 'á¸³', 'á¸´' => 'á¸µ', 'á¸¶' => 'á¸·', 'á¸¸' => 'á¸¹', 'á¸º' => 'á¸»', 'á¸¼' => 'á¸½', 'á¸¾' => 'á¸¿', 'á¹€' => 'á¹�', 'á¹‚' => 'á¹ƒ', 'á¹„' => 'á¹…', 'á¹†' => 'á¹‡', 'á¹ˆ' => 'á¹‰', 'á¹Š' => 'á¹‹', 'á¹Œ' => 'á¹�', 'á¹Ž' => 'á¹�', 'á¹�' => 'á¹‘', 'á¹’' => 'á¹“', 'á¹”' => 'á¹•', 'á¹–' => 'á¹—', 'á¹˜' => 'á¹™', 'á¹š' => 'á¹›', 'á¹œ' => 'á¹�', 'á¹ž' => 'á¹Ÿ', 'á¹ ' => 'á¹¡', 'á¹¢' => 'á¹£', 'á¹¤' => 'á¹¥', 'á¹¦' => 'á¹§', 'á¹¨' => 'á¹©', 'á¹ª' => 'á¹«', 'á¹¬' => 'á¹­', 'á¹®' => 'á¹¯', 'á¹°' => 'á¹±', 'á¹²' => 'á¹³', 'á¹´' => 'á¹µ', 'á¹¶' => 'á¹·', 'á¹¸' => 'á¹¹', 'á¹º' => 'á¹»', 'á¹¼' => 'á¹½', 'á¹¾' => 'á¹¿', 'áº€' => 'áº�', 'áº‚' => 'áºƒ', 'áº„' => 'áº…', 'áº†' => 'áº‡', 'áºˆ' => 'áº‰', 'áºŠ' => 'áº‹', 'áºŒ' => 'áº�', 'áºŽ' => 'áº�', 'áº�' => 'áº‘', 'áº’' => 'áº“', 'áº”' => 'áº•', 'áºž' => 'ÃŸ', 'áº ' => 'áº¡', 'áº¢' => 'áº£', 'áº¤' => 'áº¥', 'áº¦' => 'áº§', 'áº¨' => 'áº©', 'áºª' => 'áº«', 'áº¬' => 'áº­', 'áº®' => 'áº¯', 'áº°' => 'áº±', 'áº²' => 'áº³', 'áº´' => 'áºµ', 'áº¶' => 'áº·', 'áº¸' => 'áº¹', 'áºº' => 'áº»', 'áº¼' => 'áº½', 'áº¾' => 'áº¿', 'á»€' => 'á»�', 'á»‚' => 'á»ƒ', 'á»„' => 'á»…', 'á»†' => 'á»‡', 'á»ˆ' => 'á»‰', 'á»Š' => 'á»‹', 'á»Œ' => 'á»�', 'á»Ž' => 'á»�', 'á»�' => 'á»‘', 'á»’' => 'á»“', 'á»”' => 'á»•', 'á»–' => 'á»—', 'á»˜' => 'á»™', 'á»š' => 'á»›', 'á»œ' => 'á»�', 'á»ž' => 'á»Ÿ', 'á» ' => 'á»¡', 'á»¢' => 'á»£', 'á»¤' => 'á»¥', 'á»¦' => 'á»§', 'á»¨' => 'á»©', 'á»ª' => 'á»«', 'á»¬' => 'á»­', 'á»®' => 'á»¯', 'á»°' => 'á»±', 'á»²' => 'á»³', 'á»´' => 'á»µ', 'á»¶' => 'á»·', 'á»¸' => 'á»¹', 'á»º' => 'á»»', 'á»¼' => 'á»½', 'á»¾' => 'á»¿', 'á¼ˆ' => 'á¼€', 'á¼‰' => 'á¼�', 'á¼Š' => 'á¼‚', 'á¼‹' => 'á¼ƒ', 'á¼Œ' => 'á¼„', 'á¼�' => 'á¼…', 'á¼Ž' => 'á¼†', 'á¼�' => 'á¼‡', 'á¼˜' => 'á¼�', 'á¼™' => 'á¼‘', 'á¼š' => 'á¼’', 'á¼›' => 'á¼“', 'á¼œ' => 'á¼”', 'á¼�' => 'á¼•', 'á¼¨' => 'á¼ ', 'á¼©' => 'á¼¡', 'á¼ª' => 'á¼¢', 'á¼«' => 'á¼£', 'á¼¬' => 'á¼¤', 'á¼­' => 'á¼¥', 'á¼®' => 'á¼¦', 'á¼¯' => 'á¼§', 'á¼¸' => 'á¼°', 'á¼¹' => 'á¼±', 'á¼º' => 'á¼²', 'á¼»' => 'á¼³', 'á¼¼' => 'á¼´', 'á¼½' => 'á¼µ', 'á¼¾' => 'á¼¶', 'á¼¿' => 'á¼·', 'á½ˆ' => 'á½€', 'á½‰' => 'á½�', 'á½Š' => 'á½‚', 'á½‹' => 'á½ƒ', 'á½Œ' => 'á½„', 'á½�' => 'á½…', 'á½™' => 'á½‘', 'á½›' => 'á½“', 'á½�' => 'á½•', 'á½Ÿ' => 'á½—', 'á½¨' => 'á½ ', 'á½©' => 'á½¡', 'á½ª' => 'á½¢', 'á½«' => 'á½£', 'á½¬' => 'á½¤', 'á½­' => 'á½¥', 'á½®' => 'á½¦', 'á½¯' => 'á½§', 'á¾ˆ' => 'á¾€', 'á¾‰' => 'á¾�', 'á¾Š' => 'á¾‚', 'á¾‹' => 'á¾ƒ', 'á¾Œ' => 'á¾„', 'á¾�' => 'á¾…', 'á¾Ž' => 'á¾†', 'á¾�' => 'á¾‡', 'á¾˜' => 'á¾�', 'á¾™' => 'á¾‘', 'á¾š' => 'á¾’', 'á¾›' => 'á¾“', 'á¾œ' => 'á¾”', 'á¾�' => 'á¾•', 'á¾ž' => 'á¾–', 'á¾Ÿ' => 'á¾—', 'á¾¨' => 'á¾ ', 'á¾©' => 'á¾¡', 'á¾ª' => 'á¾¢', 'á¾«' => 'á¾£', 'á¾¬' => 'á¾¤', 'á¾­' => 'á¾¥', 'á¾®' => 'á¾¦', 'á¾¯' => 'á¾§', 'á¾¸' => 'á¾°', 'á¾¹' => 'á¾±', 'á¾º' => 'á½°', 'á¾»' => 'á½±', 'á¾¼' => 'á¾³', 'á¿ˆ' => 'á½²', 'á¿‰' => 'á½³', 'á¿Š' => 'á½´', 'á¿‹' => 'á½µ', 'á¿Œ' => 'á¿ƒ', 'á¿˜' => 'á¿�', 'á¿™' => 'á¿‘', 'á¿š' => 'á½¶', 'á¿›' => 'á½·', 'á¿¨' => 'á¿ ', 'á¿©' => 'á¿¡', 'á¿ª' => 'á½º', 'á¿«' => 'á½»', 'á¿¬' => 'á¿¥', 'á¿¸' => 'á½¸', 'á¿¹' => 'á½¹', 'á¿º' => 'á½¼', 'á¿»' => 'á½½', 'á¿¼' => 'á¿³', 'â„¦' => 'Ï‰', 'â„ª' => 'k', 'â„«' => 'Ã¥', 'â„²' => 'â…Ž', 'â… ' => 'â…°', 'â…¡' => 'â…±', 'â…¢' => 'â…²', 'â…£' => 'â…³', 'â…¤' => 'â…´', 'â…¥' => 'â…µ', 'â…¦' => 'â…¶', 'â…§' => 'â…·', 'â…¨' => 'â…¸', 'â…©' => 'â…¹', 'â…ª' => 'â…º', 'â…«' => 'â…»', 'â…¬' => 'â…¼', 'â…­' => 'â…½', 'â…®' => 'â…¾', 'â…¯' => 'â…¿', 'â†ƒ' => 'â†„', 'â’¶' => 'â“�', 'â’·' => 'â“‘', 'â’¸' => 'â“’', 'â’¹' => 'â““', 'â’º' => 'â“”', 'â’»' => 'â“•', 'â’¼' => 'â“–', 'â’½' => 'â“—', 'â’¾' => 'â“˜', 'â’¿' => 'â“™', 'â“€' => 'â“š', 'â“�' => 'â“›', 'â“‚' => 'â“œ', 'â“ƒ' => 'â“�', 'â“„' => 'â“ž', 'â“…' => 'â“Ÿ', 'â“†' => 'â“ ', 'â“‡' => 'â“¡', 'â“ˆ' => 'â“¢', 'â“‰' => 'â“£', 'â“Š' => 'â“¤', 'â“‹' => 'â“¥', 'â“Œ' => 'â“¦', 'â“�' => 'â“§', 'â“Ž' => 'â“¨', 'â“�' => 'â“©', 'â°€' => 'â°°', 'â°�' => 'â°±', 'â°‚' => 'â°²', 'â°ƒ' => 'â°³', 'â°„' => 'â°´', 'â°…' => 'â°µ', 'â°†' => 'â°¶', 'â°‡' => 'â°·', 'â°ˆ' => 'â°¸', 'â°‰' => 'â°¹', 'â°Š' => 'â°º', 'â°‹' => 'â°»', 'â°Œ' => 'â°¼', 'â°�' => 'â°½', 'â°Ž' => 'â°¾', 'â°�' => 'â°¿', 'â°�' => 'â±€', 'â°‘' => 'â±�', 'â°’' => 'â±‚', 'â°“' => 'â±ƒ', 'â°”' => 'â±„', 'â°•' => 'â±…', 'â°–' => 'â±†', 'â°—' => 'â±‡', 'â°˜' => 'â±ˆ', 'â°™' => 'â±‰', 'â°š' => 'â±Š', 'â°›' => 'â±‹', 'â°œ' => 'â±Œ', 'â°�' => 'â±�', 'â°ž' => 'â±Ž', 'â°Ÿ' => 'â±�', 'â° ' => 'â±�', 'â°¡' => 'â±‘', 'â°¢' => 'â±’', 'â°£' => 'â±“', 'â°¤' => 'â±”', 'â°¥' => 'â±•', 'â°¦' => 'â±–', 'â°§' => 'â±—', 'â°¨' => 'â±˜', 'â°©' => 'â±™', 'â°ª' => 'â±š', 'â°«' => 'â±›', 'â°¬' => 'â±œ', 'â°­' => 'â±�', 'â°®' => 'â±ž', 'â± ' => 'â±¡', 'â±¢' => 'É«', 'â±£' => 'áµ½', 'â±¤' => 'É½', 'â±§' => 'â±¨', 'â±©' => 'â±ª', 'â±«' => 'â±¬', 'â±­' => 'É‘', 'â±®' => 'É±', 'â±¯' => 'É�', 'â±°' => 'É’', 'â±²' => 'â±³', 'â±µ' => 'â±¶', 'â±¾' => 'È¿', 'â±¿' => 'É€', 'â²€' => 'â²�', 'â²‚' => 'â²ƒ', 'â²„' => 'â²…', 'â²†' => 'â²‡', 'â²ˆ' => 'â²‰', 'â²Š' => 'â²‹', 'â²Œ' => 'â²�', 'â²Ž' => 'â²�', 'â²�' => 'â²‘', 'â²’' => 'â²“', 'â²”' => 'â²•', 'â²–' => 'â²—', 'â²˜' => 'â²™', 'â²š' => 'â²›', 'â²œ' => 'â²�', 'â²ž' => 'â²Ÿ', 'â² ' => 'â²¡', 'â²¢' => 'â²£', 'â²¤' => 'â²¥', 'â²¦' => 'â²§', 'â²¨' => 'â²©', 'â²ª' => 'â²«', 'â²¬' => 'â²­', 'â²®' => 'â²¯', 'â²°' => 'â²±', 'â²²' => 'â²³', 'â²´' => 'â²µ', 'â²¶' => 'â²·', 'â²¸' => 'â²¹', 'â²º' => 'â²»', 'â²¼' => 'â²½', 'â²¾' => 'â²¿', 'â³€' => 'â³�', 'â³‚' => 'â³ƒ', 'â³„' => 'â³…', 'â³†' => 'â³‡', 'â³ˆ' => 'â³‰', 'â³Š' => 'â³‹', 'â³Œ' => 'â³�', 'â³Ž' => 'â³�', 'â³�' => 'â³‘', 'â³’' => 'â³“', 'â³”' => 'â³•', 'â³–' => 'â³—', 'â³˜' => 'â³™', 'â³š' => 'â³›', 'â³œ' => 'â³�', 'â³ž' => 'â³Ÿ', 'â³ ' => 'â³¡', 'â³¢' => 'â³£', 'â³«' => 'â³¬', 'â³­' => 'â³®', 'â³²' => 'â³³', 'ê™€' => 'ê™�', 'ê™‚' => 'ê™ƒ', 'ê™„' => 'ê™…', 'ê™†' => 'ê™‡', 'ê™ˆ' => 'ê™‰', 'ê™Š' => 'ê™‹', 'ê™Œ' => 'ê™�', 'ê™Ž' => 'ê™�', 'ê™�' => 'ê™‘', 'ê™’' => 'ê™“', 'ê™”' => 'ê™•', 'ê™–' => 'ê™—', 'ê™˜' => 'ê™™', 'ê™š' => 'ê™›', 'ê™œ' => 'ê™�', 'ê™ž' => 'ê™Ÿ', 'ê™ ' => 'ê™¡', 'ê™¢' => 'ê™£', 'ê™¤' => 'ê™¥', 'ê™¦' => 'ê™§', 'ê™¨' => 'ê™©', 'ê™ª' => 'ê™«', 'ê™¬' => 'ê™­', 'êš€' => 'êš�', 'êš‚' => 'êšƒ', 'êš„' => 'êš…', 'êš†' => 'êš‡', 'êšˆ' => 'êš‰', 'êšŠ' => 'êš‹', 'êšŒ' => 'êš�', 'êšŽ' => 'êš�', 'êš�' => 'êš‘', 'êš’' => 'êš“', 'êš”' => 'êš•', 'êš–' => 'êš—', 'êš˜' => 'êš™', 'êšš' => 'êš›', 'êœ¢' => 'êœ£', 'êœ¤' => 'êœ¥', 'êœ¦' => 'êœ§', 'êœ¨' => 'êœ©', 'êœª' => 'êœ«', 'êœ¬' => 'êœ­', 'êœ®' => 'êœ¯', 'êœ²' => 'êœ³', 'êœ´' => 'êœµ', 'êœ¶' => 'êœ·', 'êœ¸' => 'êœ¹', 'êœº' => 'êœ»', 'êœ¼' => 'êœ½', 'êœ¾' => 'êœ¿', 'ê�€' => 'ê��', 'ê�‚' => 'ê�ƒ', 'ê�„' => 'ê�…', 'ê�†' => 'ê�‡', 'ê�ˆ' => 'ê�‰', 'ê�Š' => 'ê�‹', 'ê�Œ' => 'ê��', 'ê�Ž' => 'ê��', 'ê��' => 'ê�‘', 'ê�’' => 'ê�“', 'ê�”' => 'ê�•', 'ê�–' => 'ê�—', 'ê�˜' => 'ê�™', 'ê�š' => 'ê�›', 'ê�œ' => 'ê��', 'ê�ž' => 'ê�Ÿ', 'ê� ' => 'ê�¡', 'ê�¢' => 'ê�£', 'ê�¤' => 'ê�¥', 'ê�¦' => 'ê�§', 'ê�¨' => 'ê�©', 'ê�ª' => 'ê�«', 'ê�¬' => 'ê�­', 'ê�®' => 'ê�¯', 'ê�¹' => 'ê�º', 'ê�»' => 'ê�¼', 'ê�½' => 'áµ¹', 'ê�¾' => 'ê�¿', 'êž€' => 'êž�', 'êž‚' => 'êžƒ', 'êž„' => 'êž…', 'êž†' => 'êž‡', 'êž‹' => 'êžŒ', 'êž�' => 'É¥', 'êž�' => 'êž‘', 'êž’' => 'êž“', 'êž–' => 'êž—', 'êž˜' => 'êž™', 'êžš' => 'êž›', 'êžœ' => 'êž�', 'êžž' => 'êžŸ', 'êž ' => 'êž¡', 'êž¢' => 'êž£', 'êž¤' => 'êž¥', 'êž¦' => 'êž§', 'êž¨' => 'êž©', 'êžª' => 'É¦', 'êž«' => 'Éœ', 'êž¬' => 'É¡', 'êž­' => 'É¬', 'êž®' => 'Éª', 'êž°' => 'Êž', 'êž±' => 'Ê‡', 'êž²' => 'Ê�', 'êž³' => 'ê­“', 'êž´' => 'êžµ', 'êž¶' => 'êž·', 'êž¸' => 'êž¹', 'êžº' => 'êž»', 'êž¼' => 'êž½', 'êž¾' => 'êž¿', 'êŸ‚' => 'êŸƒ', 'êŸ„' => 'êž”', 'êŸ…' => 'Ê‚', 'êŸ†' => 'á¶Ž', 'êŸ‡' => 'êŸˆ', 'êŸ‰' => 'êŸŠ', 'êŸµ' => 'êŸ¶', 'ï¼¡' => 'ï½�', 'ï¼¢' => 'ï½‚', 'ï¼£' => 'ï½ƒ', 'ï¼¤' => 'ï½„', 'ï¼¥' => 'ï½…', 'ï¼¦' => 'ï½†', 'ï¼§' => 'ï½‡', 'ï¼¨' => 'ï½ˆ', 'ï¼©' => 'ï½‰', 'ï¼ª' => 'ï½Š', 'ï¼«' => 'ï½‹', 'ï¼¬' => 'ï½Œ', 'ï¼­' => 'ï½�', 'ï¼®' => 'ï½Ž', 'ï¼¯' => 'ï½�', 'ï¼°' => 'ï½�', 'ï¼±' => 'ï½‘', 'ï¼²' => 'ï½’', 'ï¼³' => 'ï½“', 'ï¼´' => 'ï½”', 'ï¼µ' => 'ï½•', 'ï¼¶' => 'ï½–', 'ï¼·' => 'ï½—', 'ï¼¸' => 'ï½˜', 'ï¼¹' => 'ï½™', 'ï¼º' => 'ï½š', 'ð��€' => 'ð��¨', 'ð���' => 'ð��©', 'ð��‚' => 'ð��ª', 'ð��ƒ' => 'ð��«', 'ð��„' => 'ð��¬', 'ð��…' => 'ð��­', 'ð��†' => 'ð��®', 'ð��‡' => 'ð��¯', 'ð��ˆ' => 'ð��°', 'ð��‰' => 'ð��±', 'ð��Š' => 'ð��²', 'ð��‹' => 'ð��³', 'ð��Œ' => 'ð��´', 'ð���' => 'ð��µ', 'ð��Ž' => 'ð��¶', 'ð���' => 'ð��·', 'ð���' => 'ð��¸', 'ð��‘' => 'ð��¹', 'ð��’' => 'ð��º', 'ð��“' => 'ð��»', 'ð��”' => 'ð��¼', 'ð��•' => 'ð��½', 'ð��–' => 'ð��¾', 'ð��—' => 'ð��¿', 'ð��˜' => 'ð�‘€', 'ð��™' => 'ð�‘�', 'ð��š' => 'ð�‘‚', 'ð��›' => 'ð�‘ƒ', 'ð��œ' => 'ð�‘„', 'ð���' => 'ð�‘…', 'ð��ž' => 'ð�‘†', 'ð��Ÿ' => 'ð�‘‡', 'ð�� ' => 'ð�‘ˆ', 'ð��¡' => 'ð�‘‰', 'ð��¢' => 'ð�‘Š', 'ð��£' => 'ð�‘‹', 'ð��¤' => 'ð�‘Œ', 'ð��¥' => 'ð�‘�', 'ð��¦' => 'ð�‘Ž', 'ð��§' => 'ð�‘�', 'ð�’°' => 'ð�“˜', 'ð�’±' => 'ð�“™', 'ð�’²' => 'ð�“š', 'ð�’³' => 'ð�“›', 'ð�’´' => 'ð�“œ', 'ð�’µ' => 'ð�“�', 'ð�’¶' => 'ð�“ž', 'ð�’·' => 'ð�“Ÿ', 'ð�’¸' => 'ð�“ ', 'ð�’¹' => 'ð�“¡', 'ð�’º' => 'ð�“¢', 'ð�’»' => 'ð�“£', 'ð�’¼' => 'ð�“¤', 'ð�’½' => 'ð�“¥', 'ð�’¾' => 'ð�“¦', 'ð�’¿' => 'ð�“§', 'ð�“€' => 'ð�“¨', 'ð�“�' => 'ð�“©', 'ð�“‚' => 'ð�“ª', 'ð�“ƒ' => 'ð�“«', 'ð�“„' => 'ð�“¬', 'ð�“…' => 'ð�“­', 'ð�“†' => 'ð�“®', 'ð�“‡' => 'ð�“¯', 'ð�“ˆ' => 'ð�“°', 'ð�“‰' => 'ð�“±', 'ð�“Š' => 'ð�“²', 'ð�“‹' => 'ð�“³', 'ð�“Œ' => 'ð�“´', 'ð�“�' => 'ð�“µ', 'ð�“Ž' => 'ð�“¶', 'ð�“�' => 'ð�“·', 'ð�“�' => 'ð�“¸', 'ð�“‘' => 'ð�“¹', 'ð�“’' => 'ð�“º', 'ð�““' => 'ð�“»', 'ð�²€' => 'ð�³€', 'ð�²�' => 'ð�³�', 'ð�²‚' => 'ð�³‚', 'ð�²ƒ' => 'ð�³ƒ', 'ð�²„' => 'ð�³„', 'ð�²…' => 'ð�³…', 'ð�²†' => 'ð�³†', 'ð�²‡' => 'ð�³‡', 'ð�²ˆ' => 'ð�³ˆ', 'ð�²‰' => 'ð�³‰', 'ð�²Š' => 'ð�³Š', 'ð�²‹' => 'ð�³‹', 'ð�²Œ' => 'ð�³Œ', 'ð�²�' => 'ð�³�', 'ð�²Ž' => 'ð�³Ž', 'ð�²�' => 'ð�³�', 'ð�²�' => 'ð�³�', 'ð�²‘' => 'ð�³‘', 'ð�²’' => 'ð�³’', 'ð�²“' => 'ð�³“', 'ð�²”' => 'ð�³”', 'ð�²•' => 'ð�³•', 'ð�²–' => 'ð�³–', 'ð�²—' => 'ð�³—', 'ð�²˜' => 'ð�³˜', 'ð�²™' => 'ð�³™', 'ð�²š' => 'ð�³š', 'ð�²›' => 'ð�³›', 'ð�²œ' => 'ð�³œ', 'ð�²�' => 'ð�³�', 'ð�²ž' => 'ð�³ž', 'ð�²Ÿ' => 'ð�³Ÿ', 'ð�² ' => 'ð�³ ', 'ð�²¡' => 'ð�³¡', 'ð�²¢' => 'ð�³¢', 'ð�²£' => 'ð�³£', 'ð�²¤' => 'ð�³¤', 'ð�²¥' => 'ð�³¥', 'ð�²¦' => 'ð�³¦', 'ð�²§' => 'ð�³§', 'ð�²¨' => 'ð�³¨', 'ð�²©' => 'ð�³©', 'ð�²ª' => 'ð�³ª', 'ð�²«' => 'ð�³«', 'ð�²¬' => 'ð�³¬', 'ð�²­' => 'ð�³­', 'ð�²®' => 'ð�³®', 'ð�²¯' => 'ð�³¯', 'ð�²°' => 'ð�³°', 'ð�²±' => 'ð�³±', 'ð�²²' => 'ð�³²', 'ð‘¢ ' => 'ð‘£€', 'ð‘¢¡' => 'ð‘£�', 'ð‘¢¢' => 'ð‘£‚', 'ð‘¢£' => 'ð‘£ƒ', 'ð‘¢¤' => 'ð‘£„', 'ð‘¢¥' => 'ð‘£…', 'ð‘¢¦' => 'ð‘£†', 'ð‘¢§' => 'ð‘£‡', 'ð‘¢¨' => 'ð‘£ˆ', 'ð‘¢©' => 'ð‘£‰', 'ð‘¢ª' => 'ð‘£Š', 'ð‘¢«' => 'ð‘£‹', 'ð‘¢¬' => 'ð‘£Œ', 'ð‘¢­' => 'ð‘£�', 'ð‘¢®' => 'ð‘£Ž', 'ð‘¢¯' => 'ð‘£�', 'ð‘¢°' => 'ð‘£�', 'ð‘¢±' => 'ð‘£‘', 'ð‘¢²' => 'ð‘£’', 'ð‘¢³' => 'ð‘£“', 'ð‘¢´' => 'ð‘£”', 'ð‘¢µ' => 'ð‘£•', 'ð‘¢¶' => 'ð‘£–', 'ð‘¢·' => 'ð‘£—', 'ð‘¢¸' => 'ð‘£˜', 'ð‘¢¹' => 'ð‘£™', 'ð‘¢º' => 'ð‘£š', 'ð‘¢»' => 'ð‘£›', 'ð‘¢¼' => 'ð‘£œ', 'ð‘¢½' => 'ð‘£�', 'ð‘¢¾' => 'ð‘£ž', 'ð‘¢¿' => 'ð‘£Ÿ', 'ð–¹€' => 'ð–¹ ', 'ð–¹�' => 'ð–¹¡', 'ð–¹‚' => 'ð–¹¢', 'ð–¹ƒ' => 'ð–¹£', 'ð–¹„' => 'ð–¹¤', 'ð–¹…' => 'ð–¹¥', 'ð–¹†' => 'ð–¹¦', 'ð–¹‡' => 'ð–¹§', 'ð–¹ˆ' => 'ð–¹¨', 'ð–¹‰' => 'ð–¹©', 'ð–¹Š' => 'ð–¹ª', 'ð–¹‹' => 'ð–¹«', 'ð–¹Œ' => 'ð–¹¬', 'ð–¹�' => 'ð–¹­', 'ð–¹Ž' => 'ð–¹®', 'ð–¹�' => 'ð–¹¯', 'ð–¹�' => 'ð–¹°', 'ð–¹‘' => 'ð–¹±', 'ð–¹’' => 'ð–¹²', 'ð–¹“' => 'ð–¹³', 'ð–¹”' => 'ð–¹´', 'ð–¹•' => 'ð–¹µ', 'ð–¹–' => 'ð–¹¶', 'ð–¹—' => 'ð–¹·', 'ð–¹˜' => 'ð–¹¸', 'ð–¹™' => 'ð–¹¹', 'ð–¹š' => 'ð–¹º', 'ð–¹›' => 'ð–¹»', 'ð–¹œ' => 'ð–¹¼', 'ð–¹�' => 'ð–¹½', 'ð–¹ž' => 'ð–¹¾', 'ð–¹Ÿ' => 'ð–¹¿', 'ðž¤€' => 'ðž¤¢', 'ðž¤�' => 'ðž¤£', 'ðž¤‚' => 'ðž¤¤', 'ðž¤ƒ' => 'ðž¤¥', 'ðž¤„' => 'ðž¤¦', 'ðž¤…' => 'ðž¤§', 'ðž¤†' => 'ðž¤¨', 'ðž¤‡' => 'ðž¤©', 'ðž¤ˆ' => 'ðž¤ª', 'ðž¤‰' => 'ðž¤«', 'ðž¤Š' => 'ðž¤¬', 'ðž¤‹' => 'ðž¤­', 'ðž¤Œ' => 'ðž¤®', 'ðž¤�' => 'ðž¤¯', 'ðž¤Ž' => 'ðž¤°', 'ðž¤�' => 'ðž¤±', 'ðž¤�' => 'ðž¤²', 'ðž¤‘' => 'ðž¤³', 'ðž¤’' => 'ðž¤´', 'ðž¤“' => 'ðž¤µ', 'ðž¤”' => 'ðž¤¶', 'ðž¤•' => 'ðž¤·', 'ðž¤–' => 'ðž¤¸', 'ðž¤—' => 'ðž¤¹', 'ðž¤˜' => 'ðž¤º', 'ðž¤™' => 'ðž¤»', 'ðž¤š' => 'ðž¤¼', 'ðž¤›' => 'ðž¤½', 'ðž¤œ' => 'ðž¤¾', 'ðž¤�' => 'ðž¤¿', 'ðž¤ž' => 'ðž¥€', 'ðž¤Ÿ' => 'ðž¥�', 'ðž¤ ' => 'ðž¥‚', 'ðž¤¡' => 'ðž¥ƒ');<?php

return array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'e' => 'E', 'f' => 'F', 'g' => 'G', 'h' => 'H', 'i' => 'I', 'j' => 'J', 'k' => 'K', 'l' => 'L', 'm' => 'M', 'n' => 'N', 'o' => 'O', 'p' => 'P', 'q' => 'Q', 'r' => 'R', 's' => 'S', 't' => 'T', 'u' => 'U', 'v' => 'V', 'w' => 'W', 'x' => 'X', 'y' => 'Y', 'z' => 'Z', 'Âµ' => 'Îœ', 'Ã ' => 'Ã€', 'Ã¡' => 'Ã�', 'Ã¢' => 'Ã‚', 'Ã£' => 'Ãƒ', 'Ã¤' => 'Ã„', 'Ã¥' => 'Ã…', 'Ã¦' => 'Ã†', 'Ã§' => 'Ã‡', 'Ã¨' => 'Ãˆ', 'Ã©' => 'Ã‰', 'Ãª' => 'ÃŠ', 'Ã«' => 'Ã‹', 'Ã¬' => 'ÃŒ', 'Ã­' => 'Ã�', 'Ã®' => 'ÃŽ', 'Ã¯' => 'Ã�', 'Ã°' => 'Ã�', 'Ã±' => 'Ã‘', 'Ã²' => 'Ã’', 'Ã³' => 'Ã“', 'Ã´' => 'Ã”', 'Ãµ' => 'Ã•', 'Ã¶' => 'Ã–', 'Ã¸' => 'Ã˜', 'Ã¹' => 'Ã™', 'Ãº' => 'Ãš', 'Ã»' => 'Ã›', 'Ã¼' => 'Ãœ', 'Ã½' => 'Ã�', 'Ã¾' => 'Ãž', 'Ã¿' => 'Å¸', 'Ä�' => 'Ä€', 'Äƒ' => 'Ä‚', 'Ä…' => 'Ä„', 'Ä‡' => 'Ä†', 'Ä‰' => 'Äˆ', 'Ä‹' => 'ÄŠ', 'Ä�' => 'ÄŒ', 'Ä�' => 'ÄŽ', 'Ä‘' => 'Ä�', 'Ä“' => 'Ä’', 'Ä•' => 'Ä”', 'Ä—' => 'Ä–', 'Ä™' => 'Ä˜', 'Ä›' => 'Äš', 'Ä�' => 'Äœ', 'ÄŸ' => 'Äž', 'Ä¡' => 'Ä ', 'Ä£' => 'Ä¢', 'Ä¥' => 'Ä¤', 'Ä§' => 'Ä¦', 'Ä©' => 'Ä¨', 'Ä«' => 'Äª', 'Ä­' => 'Ä¬', 'Ä¯' => 'Ä®', 'Ä±' => 'I', 'Ä³' => 'Ä²', 'Äµ' => 'Ä´', 'Ä·' => 'Ä¶', 'Äº' => 'Ä¹', 'Ä¼' => 'Ä»', 'Ä¾' => 'Ä½', 'Å€' => 'Ä¿', 'Å‚' => 'Å�', 'Å„' => 'Åƒ', 'Å†' => 'Å…', 'Åˆ' => 'Å‡', 'Å‹' => 'ÅŠ', 'Å�' => 'ÅŒ', 'Å�' => 'ÅŽ', 'Å‘' => 'Å�', 'Å“' => 'Å’', 'Å•' => 'Å”', 'Å—' => 'Å–', 'Å™' => 'Å˜', 'Å›' => 'Åš', 'Å�' => 'Åœ', 'ÅŸ' => 'Åž', 'Å¡' => 'Å ', 'Å£' => 'Å¢', 'Å¥' => 'Å¤', 'Å§' => 'Å¦', 'Å©' => 'Å¨', 'Å«' => 'Åª', 'Å­' => 'Å¬', 'Å¯' => 'Å®', 'Å±' => 'Å°', 'Å³' => 'Å²', 'Åµ' => 'Å´', 'Å·' => 'Å¶', 'Åº' => 'Å¹', 'Å¼' => 'Å»', 'Å¾' => 'Å½', 'Å¿' => 'S', 'Æ€' => 'Éƒ', 'Æƒ' => 'Æ‚', 'Æ…' => 'Æ„', 'Æˆ' => 'Æ‡', 'ÆŒ' => 'Æ‹', 'Æ’' => 'Æ‘', 'Æ•' => 'Ç¶', 'Æ™' => 'Æ˜', 'Æš' => 'È½', 'Æž' => 'È ', 'Æ¡' => 'Æ ', 'Æ£' => 'Æ¢', 'Æ¥' => 'Æ¤', 'Æ¨' => 'Æ§', 'Æ­' => 'Æ¬', 'Æ°' => 'Æ¯', 'Æ´' => 'Æ³', 'Æ¶' => 'Æµ', 'Æ¹' => 'Æ¸', 'Æ½' => 'Æ¼', 'Æ¿' => 'Ç·', 'Ç…' => 'Ç„', 'Ç†' => 'Ç„', 'Çˆ' => 'Ç‡', 'Ç‰' => 'Ç‡', 'Ç‹' => 'ÇŠ', 'ÇŒ' => 'ÇŠ', 'ÇŽ' => 'Ç�', 'Ç�' => 'Ç�', 'Ç’' => 'Ç‘', 'Ç”' => 'Ç“', 'Ç–' => 'Ç•', 'Ç˜' => 'Ç—', 'Çš' => 'Ç™', 'Çœ' => 'Ç›', 'Ç�' => 'ÆŽ', 'ÇŸ' => 'Çž', 'Ç¡' => 'Ç ', 'Ç£' => 'Ç¢', 'Ç¥' => 'Ç¤', 'Ç§' => 'Ç¦', 'Ç©' => 'Ç¨', 'Ç«' => 'Çª', 'Ç­' => 'Ç¬', 'Ç¯' => 'Ç®', 'Ç²' => 'Ç±', 'Ç³' => 'Ç±', 'Çµ' => 'Ç´', 'Ç¹' => 'Ç¸', 'Ç»' => 'Çº', 'Ç½' => 'Ç¼', 'Ç¿' => 'Ç¾', 'È�' => 'È€', 'Èƒ' => 'È‚', 'È…' => 'È„', 'È‡' => 'È†', 'È‰' => 'Èˆ', 'È‹' => 'ÈŠ', 'È�' => 'ÈŒ', 'È�' => 'ÈŽ', 'È‘' => 'È�', 'È“' => 'È’', 'È•' => 'È”', 'È—' => 'È–', 'È™' => 'È˜', 'È›' => 'Èš', 'È�' => 'Èœ', 'ÈŸ' => 'Èž', 'È£' => 'È¢', 'È¥' => 'È¤', 'È§' => 'È¦', 'È©' => 'È¨', 'È«' => 'Èª', 'È­' => 'È¬', 'È¯' => 'È®', 'È±' => 'È°', 'È³' => 'È²', 'È¼' => 'È»', 'È¿' => 'â±¾', 'É€' => 'â±¿', 'É‚' => 'É�', 'É‡' => 'É†', 'É‰' => 'Éˆ', 'É‹' => 'ÉŠ', 'É�' => 'ÉŒ', 'É�' => 'ÉŽ', 'É�' => 'â±¯', 'É‘' => 'â±­', 'É’' => 'â±°', 'É“' => 'Æ�', 'É”' => 'Æ†', 'É–' => 'Æ‰', 'É—' => 'ÆŠ', 'É™' => 'Æ�', 'É›' => 'Æ�', 'Éœ' => 'êž«', 'É ' => 'Æ“', 'É¡' => 'êž¬', 'É£' => 'Æ”', 'É¥' => 'êž�', 'É¦' => 'êžª', 'É¨' => 'Æ—', 'É©' => 'Æ–', 'Éª' => 'êž®', 'É«' => 'â±¢', 'É¬' => 'êž­', 'É¯' => 'Æœ', 'É±' => 'â±®', 'É²' => 'Æ�', 'Éµ' => 'ÆŸ', 'É½' => 'â±¤', 'Ê€' => 'Æ¦', 'Ê‚' => 'êŸ…', 'Êƒ' => 'Æ©', 'Ê‡' => 'êž±', 'Êˆ' => 'Æ®', 'Ê‰' => 'É„', 'ÊŠ' => 'Æ±', 'Ê‹' => 'Æ²', 'ÊŒ' => 'É…', 'Ê’' => 'Æ·', 'Ê�' => 'êž²', 'Êž' => 'êž°', 'Í…' => 'Î™', 'Í±' => 'Í°', 'Í³' => 'Í²', 'Í·' => 'Í¶', 'Í»' => 'Ï½', 'Í¼' => 'Ï¾', 'Í½' => 'Ï¿', 'Î¬' => 'Î†', 'Î­' => 'Îˆ', 'Î®' => 'Î‰', 'Î¯' => 'ÎŠ', 'Î±' => 'Î‘', 'Î²' => 'Î’', 'Î³' => 'Î“', 'Î´' => 'Î”', 'Îµ' => 'Î•', 'Î¶' => 'Î–', 'Î·' => 'Î—', 'Î¸' => 'Î˜', 'Î¹' => 'Î™', 'Îº' => 'Îš', 'Î»' => 'Î›', 'Î¼' => 'Îœ', 'Î½' => 'Î�', 'Î¾' => 'Îž', 'Î¿' => 'ÎŸ', 'Ï€' => 'Î ', 'Ï�' => 'Î¡', 'Ï‚' => 'Î£', 'Ïƒ' => 'Î£', 'Ï„' => 'Î¤', 'Ï…' => 'Î¥', 'Ï†' => 'Î¦', 'Ï‡' => 'Î§', 'Ïˆ' => 'Î¨', 'Ï‰' => 'Î©', 'ÏŠ' => 'Îª', 'Ï‹' => 'Î«', 'ÏŒ' => 'ÎŒ', 'Ï�' => 'ÎŽ', 'ÏŽ' => 'Î�', 'Ï�' => 'Î’', 'Ï‘' => 'Î˜', 'Ï•' => 'Î¦', 'Ï–' => 'Î ', 'Ï—' => 'Ï�', 'Ï™' => 'Ï˜', 'Ï›' => 'Ïš', 'Ï�' => 'Ïœ', 'ÏŸ' => 'Ïž', 'Ï¡' => 'Ï ', 'Ï£' => 'Ï¢', 'Ï¥' => 'Ï¤', 'Ï§' => 'Ï¦', 'Ï©' => 'Ï¨', 'Ï«' => 'Ïª', 'Ï­' => 'Ï¬', 'Ï¯' => 'Ï®', 'Ï°' => 'Îš', 'Ï±' => 'Î¡', 'Ï²' => 'Ï¹', 'Ï³' => 'Í¿', 'Ïµ' => 'Î•', 'Ï¸' => 'Ï·', 'Ï»' => 'Ïº', 'Ð°' => 'Ð�', 'Ð±' => 'Ð‘', 'Ð²' => 'Ð’', 'Ð³' => 'Ð“', 'Ð´' => 'Ð”', 'Ðµ' => 'Ð•', 'Ð¶' => 'Ð–', 'Ð·' => 'Ð—', 'Ð¸' => 'Ð˜', 'Ð¹' => 'Ð™', 'Ðº' => 'Ðš', 'Ð»' => 'Ð›', 'Ð¼' => 'Ðœ', 'Ð½' => 'Ð�', 'Ð¾' => 'Ðž', 'Ð¿' => 'ÐŸ', 'Ñ€' => 'Ð ', 'Ñ�' => 'Ð¡', 'Ñ‚' => 'Ð¢', 'Ñƒ' => 'Ð£', 'Ñ„' => 'Ð¤', 'Ñ…' => 'Ð¥', 'Ñ†' => 'Ð¦', 'Ñ‡' => 'Ð§', 'Ñˆ' => 'Ð¨', 'Ñ‰' => 'Ð©', 'ÑŠ' => 'Ðª', 'Ñ‹' => 'Ð«', 'ÑŒ' => 'Ð¬', 'Ñ�' => 'Ð­', 'ÑŽ' => 'Ð®', 'Ñ�' => 'Ð¯', 'Ñ�' => 'Ð€', 'Ñ‘' => 'Ð�', 'Ñ’' => 'Ð‚', 'Ñ“' => 'Ðƒ', 'Ñ”' => 'Ð„', 'Ñ•' => 'Ð…', 'Ñ–' => 'Ð†', 'Ñ—' => 'Ð‡', 'Ñ˜' => 'Ðˆ', 'Ñ™' => 'Ð‰', 'Ñš' => 'ÐŠ', 'Ñ›' => 'Ð‹', 'Ñœ' => 'ÐŒ', 'Ñ�' => 'Ð�', 'Ñž' => 'ÐŽ', 'ÑŸ' => 'Ð�', 'Ñ¡' => 'Ñ ', 'Ñ£' => 'Ñ¢', 'Ñ¥' => 'Ñ¤', 'Ñ§' => 'Ñ¦', 'Ñ©' => 'Ñ¨', 'Ñ«' => 'Ñª', 'Ñ­' => 'Ñ¬', 'Ñ¯' => 'Ñ®', 'Ñ±' => 'Ñ°', 'Ñ³' => 'Ñ²', 'Ñµ' => 'Ñ´', 'Ñ·' => 'Ñ¶', 'Ñ¹' => 'Ñ¸', 'Ñ»' => 'Ñº', 'Ñ½' => 'Ñ¼', 'Ñ¿' => 'Ñ¾', 'Ò�' => 'Ò€', 'Ò‹' => 'ÒŠ', 'Ò�' => 'ÒŒ', 'Ò�' => 'ÒŽ', 'Ò‘' => 'Ò�', 'Ò“' => 'Ò’', 'Ò•' => 'Ò”', 'Ò—' => 'Ò–', 'Ò™' => 'Ò˜', 'Ò›' => 'Òš', 'Ò�' => 'Òœ', 'ÒŸ' => 'Òž', 'Ò¡' => 'Ò ', 'Ò£' => 'Ò¢', 'Ò¥' => 'Ò¤', 'Ò§' => 'Ò¦', 'Ò©' => 'Ò¨', 'Ò«' => 'Òª', 'Ò­' => 'Ò¬', 'Ò¯' => 'Ò®', 'Ò±' => 'Ò°', 'Ò³' => 'Ò²', 'Òµ' => 'Ò´', 'Ò·' => 'Ò¶', 'Ò¹' => 'Ò¸', 'Ò»' => 'Òº', 'Ò½' => 'Ò¼', 'Ò¿' => 'Ò¾', 'Ó‚' => 'Ó�', 'Ó„' => 'Óƒ', 'Ó†' => 'Ó…', 'Óˆ' => 'Ó‡', 'ÓŠ' => 'Ó‰', 'ÓŒ' => 'Ó‹', 'ÓŽ' => 'Ó�', 'Ó�' => 'Ó€', 'Ó‘' => 'Ó�', 'Ó“' => 'Ó’', 'Ó•' => 'Ó”', 'Ó—' => 'Ó–', 'Ó™' => 'Ó˜', 'Ó›' => 'Óš', 'Ó�' => 'Óœ', 'ÓŸ' => 'Óž', 'Ó¡' => 'Ó ', 'Ó£' => 'Ó¢', 'Ó¥' => 'Ó¤', 'Ó§' => 'Ó¦', 'Ó©' => 'Ó¨', 'Ó«' => 'Óª', 'Ó­' => 'Ó¬', 'Ó¯' => 'Ó®', 'Ó±' => 'Ó°', 'Ó³' => 'Ó²', 'Óµ' => 'Ó´', 'Ó·' => 'Ó¶', 'Ó¹' => 'Ó¸', 'Ó»' => 'Óº', 'Ó½' => 'Ó¼', 'Ó¿' => 'Ó¾', 'Ô�' => 'Ô€', 'Ôƒ' => 'Ô‚', 'Ô…' => 'Ô„', 'Ô‡' => 'Ô†', 'Ô‰' => 'Ôˆ', 'Ô‹' => 'ÔŠ', 'Ô�' => 'ÔŒ', 'Ô�' => 'ÔŽ', 'Ô‘' => 'Ô�', 'Ô“' => 'Ô’', 'Ô•' => 'Ô”', 'Ô—' => 'Ô–', 'Ô™' => 'Ô˜', 'Ô›' => 'Ôš', 'Ô�' => 'Ôœ', 'ÔŸ' => 'Ôž', 'Ô¡' => 'Ô ', 'Ô£' => 'Ô¢', 'Ô¥' => 'Ô¤', 'Ô§' => 'Ô¦', 'Ô©' => 'Ô¨', 'Ô«' => 'Ôª', 'Ô­' => 'Ô¬', 'Ô¯' => 'Ô®', 'Õ¡' => 'Ô±', 'Õ¢' => 'Ô²', 'Õ£' => 'Ô³', 'Õ¤' => 'Ô´', 'Õ¥' => 'Ôµ', 'Õ¦' => 'Ô¶', 'Õ§' => 'Ô·', 'Õ¨' => 'Ô¸', 'Õ©' => 'Ô¹', 'Õª' => 'Ôº', 'Õ«' => 'Ô»', 'Õ¬' => 'Ô¼', 'Õ­' => 'Ô½', 'Õ®' => 'Ô¾', 'Õ¯' => 'Ô¿', 'Õ°' => 'Õ€', 'Õ±' => 'Õ�', 'Õ²' => 'Õ‚', 'Õ³' => 'Õƒ', 'Õ´' => 'Õ„', 'Õµ' => 'Õ…', 'Õ¶' => 'Õ†', 'Õ·' => 'Õ‡', 'Õ¸' => 'Õˆ', 'Õ¹' => 'Õ‰', 'Õº' => 'ÕŠ', 'Õ»' => 'Õ‹', 'Õ¼' => 'ÕŒ', 'Õ½' => 'Õ�', 'Õ¾' => 'ÕŽ', 'Õ¿' => 'Õ�', 'Ö€' => 'Õ�', 'Ö�' => 'Õ‘', 'Ö‚' => 'Õ’', 'Öƒ' => 'Õ“', 'Ö„' => 'Õ”', 'Ö…' => 'Õ•', 'Ö†' => 'Õ–', 'áƒ�' => 'á²�', 'áƒ‘' => 'á²‘', 'áƒ’' => 'á²’', 'áƒ“' => 'á²“', 'áƒ”' => 'á²”', 'áƒ•' => 'á²•', 'áƒ–' => 'á²–', 'áƒ—' => 'á²—', 'áƒ˜' => 'á²˜', 'áƒ™' => 'á²™', 'áƒš' => 'á²š', 'áƒ›' => 'á²›', 'áƒœ' => 'á²œ', 'áƒ�' => 'á²�', 'áƒž' => 'á²ž', 'áƒŸ' => 'á²Ÿ', 'áƒ ' => 'á² ', 'áƒ¡' => 'á²¡', 'áƒ¢' => 'á²¢', 'áƒ£' => 'á²£', 'áƒ¤' => 'á²¤', 'áƒ¥' => 'á²¥', 'áƒ¦' => 'á²¦', 'áƒ§' => 'á²§', 'áƒ¨' => 'á²¨', 'áƒ©' => 'á²©', 'áƒª' => 'á²ª', 'áƒ«' => 'á²«', 'áƒ¬' => 'á²¬', 'áƒ­' => 'á²­', 'áƒ®' => 'á²®', 'áƒ¯' => 'á²¯', 'áƒ°' => 'á²°', 'áƒ±' => 'á²±', 'áƒ²' => 'á²²', 'áƒ³' => 'á²³', 'áƒ´' => 'á²´', 'áƒµ' => 'á²µ', 'áƒ¶' => 'á²¶', 'áƒ·' => 'á²·', 'áƒ¸' => 'á²¸', 'áƒ¹' => 'á²¹', 'áƒº' => 'á²º', 'áƒ½' => 'á²½', 'áƒ¾' => 'á²¾', 'áƒ¿' => 'á²¿', 'á�¸' => 'á�°', 'á�¹' => 'á�±', 'á�º' => 'á�²', 'á�»' => 'á�³', 'á�¼' => 'á�´', 'á�½' => 'á�µ', 'á²€' => 'Ð’', 'á²�' => 'Ð”', 'á²‚' => 'Ðž', 'á²ƒ' => 'Ð¡', 'á²„' => 'Ð¢', 'á²…' => 'Ð¢', 'á²†' => 'Ðª', 'á²‡' => 'Ñ¢', 'á²ˆ' => 'ê™Š', 'áµ¹' => 'ê�½', 'áµ½' => 'â±£', 'á¶Ž' => 'êŸ†', 'á¸�' => 'á¸€', 'á¸ƒ' => 'á¸‚', 'á¸…' => 'á¸„', 'á¸‡' => 'á¸†', 'á¸‰' => 'á¸ˆ', 'á¸‹' => 'á¸Š', 'á¸�' => 'á¸Œ', 'á¸�' => 'á¸Ž', 'á¸‘' => 'á¸�', 'á¸“' => 'á¸’', 'á¸•' => 'á¸”', 'á¸—' => 'á¸–', 'á¸™' => 'á¸˜', 'á¸›' => 'á¸š', 'á¸�' => 'á¸œ', 'á¸Ÿ' => 'á¸ž', 'á¸¡' => 'á¸ ', 'á¸£' => 'á¸¢', 'á¸¥' => 'á¸¤', 'á¸§' => 'á¸¦', 'á¸©' => 'á¸¨', 'á¸«' => 'á¸ª', 'á¸­' => 'á¸¬', 'á¸¯' => 'á¸®', 'á¸±' => 'á¸°', 'á¸³' => 'á¸²', 'á¸µ' => 'á¸´', 'á¸·' => 'á¸¶', 'á¸¹' => 'á¸¸', 'á¸»' => 'á¸º', 'á¸½' => 'á¸¼', 'á¸¿' => 'á¸¾', 'á¹�' => 'á¹€', 'á¹ƒ' => 'á¹‚', 'á¹…' => 'á¹„', 'á¹‡' => 'á¹†', 'á¹‰' => 'á¹ˆ', 'á¹‹' => 'á¹Š', 'á¹�' => 'á¹Œ', 'á¹�' => 'á¹Ž', 'á¹‘' => 'á¹�', 'á¹“' => 'á¹’', 'á¹•' => 'á¹”', 'á¹—' => 'á¹–', 'á¹™' => 'á¹˜', 'á¹›' => 'á¹š', 'á¹�' => 'á¹œ', 'á¹Ÿ' => 'á¹ž', 'á¹¡' => 'á¹ ', 'á¹£' => 'á¹¢', 'á¹¥' => 'á¹¤', 'á¹§' => 'á¹¦', 'á¹©' => 'á¹¨', 'á¹«' => 'á¹ª', 'á¹­' => 'á¹¬', 'á¹¯' => 'á¹®', 'á¹±' => 'á¹°', 'á¹³' => 'á¹²', 'á¹µ' => 'á¹´', 'á¹·' => 'á¹¶', 'á¹¹' => 'á¹¸', 'á¹»' => 'á¹º', 'á¹½' => 'á¹¼', 'á¹¿' => 'á¹¾', 'áº�' => 'áº€', 'áºƒ' => 'áº‚', 'áº…' => 'áº„', 'áº‡' => 'áº†', 'áº‰' => 'áºˆ', 'áº‹' => 'áºŠ', 'áº�' => 'áºŒ', 'áº�' => 'áºŽ', 'áº‘' => 'áº�', 'áº“' => 'áº’', 'áº•' => 'áº”', 'áº›' => 'á¹ ', 'áº¡' => 'áº ', 'áº£' => 'áº¢', 'áº¥' => 'áº¤', 'áº§' => 'áº¦', 'áº©' => 'áº¨', 'áº«' => 'áºª', 'áº­' => 'áº¬', 'áº¯' => 'áº®', 'áº±' => 'áº°', 'áº³' => 'áº²', 'áºµ' => 'áº´', 'áº·' => 'áº¶', 'áº¹' => 'áº¸', 'áº»' => 'áºº', 'áº½' => 'áº¼', 'áº¿' => 'áº¾', 'á»�' => 'á»€', 'á»ƒ' => 'á»‚', 'á»…' => 'á»„', 'á»‡' => 'á»†', 'á»‰' => 'á»ˆ', 'á»‹' => 'á»Š', 'á»�' => 'á»Œ', 'á»�' => 'á»Ž', 'á»‘' => 'á»�', 'á»“' => 'á»’', 'á»•' => 'á»”', 'á»—' => 'á»–', 'á»™' => 'á»˜', 'á»›' => 'á»š', 'á»�' => 'á»œ', 'á»Ÿ' => 'á»ž', 'á»¡' => 'á» ', 'á»£' => 'á»¢', 'á»¥' => 'á»¤', 'á»§' => 'á»¦', 'á»©' => 'á»¨', 'á»«' => 'á»ª', 'á»­' => 'á»¬', 'á»¯' => 'á»®', 'á»±' => 'á»°', 'á»³' => 'á»²', 'á»µ' => 'á»´', 'á»·' => 'á»¶', 'á»¹' => 'á»¸', 'á»»' => 'á»º', 'á»½' => 'á»¼', 'á»¿' => 'á»¾', 'á¼€' => 'á¼ˆ', 'á¼�' => 'á¼‰', 'á¼‚' => 'á¼Š', 'á¼ƒ' => 'á¼‹', 'á¼„' => 'á¼Œ', 'á¼…' => 'á¼�', 'á¼†' => 'á¼Ž', 'á¼‡' => 'á¼�', 'á¼�' => 'á¼˜', 'á¼‘' => 'á¼™', 'á¼’' => 'á¼š', 'á¼“' => 'á¼›', 'á¼”' => 'á¼œ', 'á¼•' => 'á¼�', 'á¼ ' => 'á¼¨', 'á¼¡' => 'á¼©', 'á¼¢' => 'á¼ª', 'á¼£' => 'á¼«', 'á¼¤' => 'á¼¬', 'á¼¥' => 'á¼­', 'á¼¦' => 'á¼®', 'á¼§' => 'á¼¯', 'á¼°' => 'á¼¸', 'á¼±' => 'á¼¹', 'á¼²' => 'á¼º', 'á¼³' => 'á¼»', 'á¼´' => 'á¼¼', 'á¼µ' => 'á¼½', 'á¼¶' => 'á¼¾', 'á¼·' => 'á¼¿', 'á½€' => 'á½ˆ', 'á½�' => 'á½‰', 'á½‚' => 'á½Š', 'á½ƒ' => 'á½‹', 'á½„' => 'á½Œ', 'á½…' => 'á½�', 'á½‘' => 'á½™', 'á½“' => 'á½›', 'á½•' => 'á½�', 'á½—' => 'á½Ÿ', 'á½ ' => 'á½¨', 'á½¡' => 'á½©', 'á½¢' => 'á½ª', 'á½£' => 'á½«', 'á½¤' => 'á½¬', 'á½¥' => 'á½­', 'á½¦' => 'á½®', 'á½§' => 'á½¯', 'á½°' => 'á¾º', 'á½±' => 'á¾»', 'á½²' => 'á¿ˆ', 'á½³' => 'á¿‰', 'á½´' => 'á¿Š', 'á½µ' => 'á¿‹', 'á½¶' => 'á¿š', 'á½·' => 'á¿›', 'á½¸' => 'á¿¸', 'á½¹' => 'á¿¹', 'á½º' => 'á¿ª', 'á½»' => 'á¿«', 'á½¼' => 'á¿º', 'á½½' => 'á¿»', 'á¾€' => 'á¼ˆÎ™', 'á¾�' => 'á¼‰Î™', 'á¾‚' => 'á¼ŠÎ™', 'á¾ƒ' => 'á¼‹Î™', 'á¾„' => 'á¼ŒÎ™', 'á¾…' => 'á¼�Î™', 'á¾†' => 'á¼ŽÎ™', 'á¾‡' => 'á¼�Î™', 'á¾�' => 'á¼¨Î™', 'á¾‘' => 'á¼©Î™', 'á¾’' => 'á¼ªÎ™', 'á¾“' => 'á¼«Î™', 'á¾”' => 'á¼¬Î™', 'á¾•' => 'á¼­Î™', 'á¾–' => 'á¼®Î™', 'á¾—' => 'á¼¯Î™', 'á¾ ' => 'á½¨Î™', 'á¾¡' => 'á½©Î™', 'á¾¢' => 'á½ªÎ™', 'á¾£' => 'á½«Î™', 'á¾¤' => 'á½¬Î™', 'á¾¥' => 'á½­Î™', 'á¾¦' => 'á½®Î™', 'á¾§' => 'á½¯Î™', 'á¾°' => 'á¾¸', 'á¾±' => 'á¾¹', 'á¾³' => 'Î‘Î™', 'á¾¾' => 'Î™', 'á¿ƒ' => 'Î—Î™', 'á¿�' => 'á¿˜', 'á¿‘' => 'á¿™', 'á¿ ' => 'á¿¨', 'á¿¡' => 'á¿©', 'á¿¥' => 'á¿¬', 'á¿³' => 'Î©Î™', 'â…Ž' => 'â„²', 'â…°' => 'â… ', 'â…±' => 'â…¡', 'â…²' => 'â…¢', 'â…³' => 'â…£', 'â…´' => 'â…¤', 'â…µ' => 'â…¥', 'â…¶' => 'â…¦', 'â…·' => 'â…§', 'â…¸' => 'â…¨', 'â…¹' => 'â…©', 'â…º' => 'â…ª', 'â…»' => 'â…«', 'â…¼' => 'â…¬', 'â…½' => 'â…­', 'â…¾' => 'â…®', 'â…¿' => 'â…¯', 'â†„' => 'â†ƒ', 'â“�' => 'â’¶', 'â“‘' => 'â’·', 'â“’' => 'â’¸', 'â““' => 'â’¹', 'â“”' => 'â’º', 'â“•' => 'â’»', 'â“–' => 'â’¼', 'â“—' => 'â’½', 'â“˜' => 'â’¾', 'â“™' => 'â’¿', 'â“š' => 'â“€', 'â“›' => 'â“�', 'â“œ' => 'â“‚', 'â“�' => 'â“ƒ', 'â“ž' => 'â“„', 'â“Ÿ' => 'â“…', 'â“ ' => 'â“†', 'â“¡' => 'â“‡', 'â“¢' => 'â“ˆ', 'â“£' => 'â“‰', 'â“¤' => 'â“Š', 'â“¥' => 'â“‹', 'â“¦' => 'â“Œ', 'â“§' => 'â“�', 'â“¨' => 'â“Ž', 'â“©' => 'â“�', 'â°°' => 'â°€', 'â°±' => 'â°�', 'â°²' => 'â°‚', 'â°³' => 'â°ƒ', 'â°´' => 'â°„', 'â°µ' => 'â°…', 'â°¶' => 'â°†', 'â°·' => 'â°‡', 'â°¸' => 'â°ˆ', 'â°¹' => 'â°‰', 'â°º' => 'â°Š', 'â°»' => 'â°‹', 'â°¼' => 'â°Œ', 'â°½' => 'â°�', 'â°¾' => 'â°Ž', 'â°¿' => 'â°�', 'â±€' => 'â°�', 'â±�' => 'â°‘', 'â±‚' => 'â°’', 'â±ƒ' => 'â°“', 'â±„' => 'â°”', 'â±…' => 'â°•', 'â±†' => 'â°–', 'â±‡' => 'â°—', 'â±ˆ' => 'â°˜', 'â±‰' => 'â°™', 'â±Š' => 'â°š', 'â±‹' => 'â°›', 'â±Œ' => 'â°œ', 'â±�' => 'â°�', 'â±Ž' => 'â°ž', 'â±�' => 'â°Ÿ', 'â±�' => 'â° ', 'â±‘' => 'â°¡', 'â±’' => 'â°¢', 'â±“' => 'â°£', 'â±”' => 'â°¤', 'â±•' => 'â°¥', 'â±–' => 'â°¦', 'â±—' => 'â°§', 'â±˜' => 'â°¨', 'â±™' => 'â°©', 'â±š' => 'â°ª', 'â±›' => 'â°«', 'â±œ' => 'â°¬', 'â±�' => 'â°­', 'â±ž' => 'â°®', 'â±¡' => 'â± ', 'â±¥' => 'Èº', 'â±¦' => 'È¾', 'â±¨' => 'â±§', 'â±ª' => 'â±©', 'â±¬' => 'â±«', 'â±³' => 'â±²', 'â±¶' => 'â±µ', 'â²�' => 'â²€', 'â²ƒ' => 'â²‚', 'â²…' => 'â²„', 'â²‡' => 'â²†', 'â²‰' => 'â²ˆ', 'â²‹' => 'â²Š', 'â²�' => 'â²Œ', 'â²�' => 'â²Ž', 'â²‘' => 'â²�', 'â²“' => 'â²’', 'â²•' => 'â²”', 'â²—' => 'â²–', 'â²™' => 'â²˜', 'â²›' => 'â²š', 'â²�' => 'â²œ', 'â²Ÿ' => 'â²ž', 'â²¡' => 'â² ', 'â²£' => 'â²¢', 'â²¥' => 'â²¤', 'â²§' => 'â²¦', 'â²©' => 'â²¨', 'â²«' => 'â²ª', 'â²­' => 'â²¬', 'â²¯' => 'â²®', 'â²±' => 'â²°', 'â²³' => 'â²²', 'â²µ' => 'â²´', 'â²·' => 'â²¶', 'â²¹' => 'â²¸', 'â²»' => 'â²º', 'â²½' => 'â²¼', 'â²¿' => 'â²¾', 'â³�' => 'â³€', 'â³ƒ' => 'â³‚', 'â³…' => 'â³„', 'â³‡' => 'â³†', 'â³‰' => 'â³ˆ', 'â³‹' => 'â³Š', 'â³�' => 'â³Œ', 'â³�' => 'â³Ž', 'â³‘' => 'â³�', 'â³“' => 'â³’', 'â³•' => 'â³”', 'â³—' => 'â³–', 'â³™' => 'â³˜', 'â³›' => 'â³š', 'â³�' => 'â³œ', 'â³Ÿ' => 'â³ž', 'â³¡' => 'â³ ', 'â³£' => 'â³¢', 'â³¬' => 'â³«', 'â³®' => 'â³­', 'â³³' => 'â³²', 'â´€' => 'á‚ ', 'â´�' => 'á‚¡', 'â´‚' => 'á‚¢', 'â´ƒ' => 'á‚£', 'â´„' => 'á‚¤', 'â´…' => 'á‚¥', 'â´†' => 'á‚¦', 'â´‡' => 'á‚§', 'â´ˆ' => 'á‚¨', 'â´‰' => 'á‚©', 'â´Š' => 'á‚ª', 'â´‹' => 'á‚«', 'â´Œ' => 'á‚¬', 'â´�' => 'á‚­', 'â´Ž' => 'á‚®', 'â´�' => 'á‚¯', 'â´�' => 'á‚°', 'â´‘' => 'á‚±', 'â´’' => 'á‚²', 'â´“' => 'á‚³', 'â´”' => 'á‚´', 'â´•' => 'á‚µ', 'â´–' => 'á‚¶', 'â´—' => 'á‚·', 'â´˜' => 'á‚¸', 'â´™' => 'á‚¹', 'â´š' => 'á‚º', 'â´›' => 'á‚»', 'â´œ' => 'á‚¼', 'â´�' => 'á‚½', 'â´ž' => 'á‚¾', 'â´Ÿ' => 'á‚¿', 'â´ ' => 'áƒ€', 'â´¡' => 'áƒ�', 'â´¢' => 'áƒ‚', 'â´£' => 'áƒƒ', 'â´¤' => 'áƒ„', 'â´¥' => 'áƒ…', 'â´§' => 'áƒ‡', 'â´­' => 'áƒ�', 'ê™�' => 'ê™€', 'ê™ƒ' => 'ê™‚', 'ê™…' => 'ê™„', 'ê™‡' => 'ê™†', 'ê™‰' => 'ê™ˆ', 'ê™‹' => 'ê™Š', 'ê™�' => 'ê™Œ', 'ê™�' => 'ê™Ž', 'ê™‘' => 'ê™�', 'ê™“' => 'ê™’', 'ê™•' => 'ê™”', 'ê™—' => 'ê™–', 'ê™™' => 'ê™˜', 'ê™›' => 'ê™š', 'ê™�' => 'ê™œ', 'ê™Ÿ' => 'ê™ž', 'ê™¡' => 'ê™ ', 'ê™£' => 'ê™¢', 'ê™¥' => 'ê™¤', 'ê™§' => 'ê™¦', 'ê™©' => 'ê™¨', 'ê™«' => 'ê™ª', 'ê™­' => 'ê™¬', 'êš�' => 'êš€', 'êšƒ' => 'êš‚', 'êš…' => 'êš„', 'êš‡' => 'êš†', 'êš‰' => 'êšˆ', 'êš‹' => 'êšŠ', 'êš�' => 'êšŒ', 'êš�' => 'êšŽ', 'êš‘' => 'êš�', 'êš“' => 'êš’', 'êš•' => 'êš”', 'êš—' => 'êš–', 'êš™' => 'êš˜', 'êš›' => 'êšš', 'êœ£' => 'êœ¢', 'êœ¥' => 'êœ¤', 'êœ§' => 'êœ¦', 'êœ©' => 'êœ¨', 'êœ«' => 'êœª', 'êœ­' => 'êœ¬', 'êœ¯' => 'êœ®', 'êœ³' => 'êœ²', 'êœµ' => 'êœ´', 'êœ·' => 'êœ¶', 'êœ¹' => 'êœ¸', 'êœ»' => 'êœº', 'êœ½' => 'êœ¼', 'êœ¿' => 'êœ¾', 'ê��' => 'ê�€', 'ê�ƒ' => 'ê�‚', 'ê�…' => 'ê�„', 'ê�‡' => 'ê�†', 'ê�‰' => 'ê�ˆ', 'ê�‹' => 'ê�Š', 'ê��' => 'ê�Œ', 'ê��' => 'ê�Ž', 'ê�‘' => 'ê��', 'ê�“' => 'ê�’', 'ê�•' => 'ê�”', 'ê�—' => 'ê�–', 'ê�™' => 'ê�˜', 'ê�›' => 'ê�š', 'ê��' => 'ê�œ', 'ê�Ÿ' => 'ê�ž', 'ê�¡' => 'ê� ', 'ê�£' => 'ê�¢', 'ê�¥' => 'ê�¤', 'ê�§' => 'ê�¦', 'ê�©' => 'ê�¨', 'ê�«' => 'ê�ª', 'ê�­' => 'ê�¬', 'ê�¯' => 'ê�®', 'ê�º' => 'ê�¹', 'ê�¼' => 'ê�»', 'ê�¿' => 'ê�¾', 'êž�' => 'êž€', 'êžƒ' => 'êž‚', 'êž…' => 'êž„', 'êž‡' => 'êž†', 'êžŒ' => 'êž‹', 'êž‘' => 'êž�', 'êž“' => 'êž’', 'êž”' => 'êŸ„', 'êž—' => 'êž–', 'êž™' => 'êž˜', 'êž›' => 'êžš', 'êž�' => 'êžœ', 'êžŸ' => 'êžž', 'êž¡' => 'êž ', 'êž£' => 'êž¢', 'êž¥' => 'êž¤', 'êž§' => 'êž¦', 'êž©' => 'êž¨', 'êžµ' => 'êž´', 'êž·' => 'êž¶', 'êž¹' => 'êž¸', 'êž»' => 'êžº', 'êž½' => 'êž¼', 'êž¿' => 'êž¾', 'êŸƒ' => 'êŸ‚', 'êŸˆ' => 'êŸ‡', 'êŸŠ' => 'êŸ‰', 'êŸ¶' => 'êŸµ', 'ê­“' => 'êž³', 'ê­°' => 'áŽ ', 'ê­±' => 'áŽ¡', 'ê­²' => 'áŽ¢', 'ê­³' => 'áŽ£', 'ê­´' => 'áŽ¤', 'ê­µ' => 'áŽ¥', 'ê­¶' => 'áŽ¦', 'ê­·' => 'áŽ§', 'ê­¸' => 'áŽ¨', 'ê­¹' => 'áŽ©', 'ê­º' => 'áŽª', 'ê­»' => 'áŽ«', 'ê­¼' => 'áŽ¬', 'ê­½' => 'áŽ­', 'ê­¾' => 'áŽ®', 'ê­¿' => 'áŽ¯', 'ê®€' => 'áŽ°', 'ê®�' => 'áŽ±', 'ê®‚' => 'áŽ²', 'ê®ƒ' => 'áŽ³', 'ê®„' => 'áŽ´', 'ê®…' => 'áŽµ', 'ê®†' => 'áŽ¶', 'ê®‡' => 'áŽ·', 'ê®ˆ' => 'áŽ¸', 'ê®‰' => 'áŽ¹', 'ê®Š' => 'áŽº', 'ê®‹' => 'áŽ»', 'ê®Œ' => 'áŽ¼', 'ê®�' => 'áŽ½', 'ê®Ž' => 'áŽ¾', 'ê®�' => 'áŽ¿', 'ê®�' => 'á�€', 'ê®‘' => 'á��', 'ê®’' => 'á�‚', 'ê®“' => 'á�ƒ', 'ê®”' => 'á�„', 'ê®•' => 'á�…', 'ê®–' => 'á�†', 'ê®—' => 'á�‡', 'ê®˜' => 'á�ˆ', 'ê®™' => 'á�‰', 'ê®š' => 'á�Š', 'ê®›' => 'á�‹', 'ê®œ' => 'á�Œ', 'ê®�' => 'á��', 'ê®ž' => 'á�Ž', 'ê®Ÿ' => 'á��', 'ê® ' => 'á��', 'ê®¡' => 'á�‘', 'ê®¢' => 'á�’', 'ê®£' => 'á�“', 'ê®¤' => 'á�”', 'ê®¥' => 'á�•', 'ê®¦' => 'á�–', 'ê®§' => 'á�—', 'ê®¨' => 'á�˜', 'ê®©' => 'á�™', 'ê®ª' => 'á�š', 'ê®«' => 'á�›', 'ê®¬' => 'á�œ', 'ê®­' => 'á��', 'ê®®' => 'á�ž', 'ê®¯' => 'á�Ÿ', 'ê®°' => 'á� ', 'ê®±' => 'á�¡', 'ê®²' => 'á�¢', 'ê®³' => 'á�£', 'ê®´' => 'á�¤', 'ê®µ' => 'á�¥', 'ê®¶' => 'á�¦', 'ê®·' => 'á�§', 'ê®¸' => 'á�¨', 'ê®¹' => 'á�©', 'ê®º' => 'á�ª', 'ê®»' => 'á�«', 'ê®¼' => 'á�¬', 'ê®½' => 'á�­', 'ê®¾' => 'á�®', 'ê®¿' => 'á�¯', 'ï½�' => 'ï¼¡', 'ï½‚' => 'ï¼¢', 'ï½ƒ' => 'ï¼£', 'ï½„' => 'ï¼¤', 'ï½…' => 'ï¼¥', 'ï½†' => 'ï¼¦', 'ï½‡' => 'ï¼§', 'ï½ˆ' => 'ï¼¨', 'ï½‰' => 'ï¼©', 'ï½Š' => 'ï¼ª', 'ï½‹' => 'ï¼«', 'ï½Œ' => 'ï¼¬', 'ï½�' => 'ï¼­', 'ï½Ž' => 'ï¼®', 'ï½�' => 'ï¼¯', 'ï½�' => 'ï¼°', 'ï½‘' => 'ï¼±', 'ï½’' => 'ï¼²', 'ï½“' => 'ï¼³', 'ï½”' => 'ï¼´', 'ï½•' => 'ï¼µ', 'ï½–' => 'ï¼¶', 'ï½—' => 'ï¼·', 'ï½˜' => 'ï¼¸', 'ï½™' => 'ï¼¹', 'ï½š' => 'ï¼º', 'ð��¨' => 'ð��€', 'ð��©' => 'ð���', 'ð��ª' => 'ð��‚', 'ð��«' => 'ð��ƒ', 'ð��¬' => 'ð��„', 'ð��­' => 'ð��…', 'ð��®' => 'ð��†', 'ð��¯' => 'ð��‡', 'ð��°' => 'ð��ˆ', 'ð��±' => 'ð��‰', 'ð��²' => 'ð��Š', 'ð��³' => 'ð��‹', 'ð��´' => 'ð��Œ', 'ð��µ' => 'ð���', 'ð��¶' => 'ð��Ž', 'ð��·' => 'ð���', 'ð��¸' => 'ð���', 'ð��¹' => 'ð��‘', 'ð��º' => 'ð��’', 'ð��»' => 'ð��“', 'ð��¼' => 'ð��”', 'ð��½' => 'ð��•', 'ð��¾' => 'ð��–', 'ð��¿' => 'ð��—', 'ð�‘€' => 'ð��˜', 'ð�‘�' => 'ð��™', 'ð�‘‚' => 'ð��š', 'ð�‘ƒ' => 'ð��›', 'ð�‘„' => 'ð��œ', 'ð�‘…' => 'ð���', 'ð�‘†' => 'ð��ž', 'ð�‘‡' => 'ð��Ÿ', 'ð�‘ˆ' => 'ð�� ', 'ð�‘‰' => 'ð��¡', 'ð�‘Š' => 'ð��¢', 'ð�‘‹' => 'ð��£', 'ð�‘Œ' => 'ð��¤', 'ð�‘�' => 'ð��¥', 'ð�‘Ž' => 'ð��¦', 'ð�‘�' => 'ð��§', 'ð�“˜' => 'ð�’°', 'ð�“™' => 'ð�’±', 'ð�“š' => 'ð�’²', 'ð�“›' => 'ð�’³', 'ð�“œ' => 'ð�’´', 'ð�“�' => 'ð�’µ', 'ð�“ž' => 'ð�’¶', 'ð�“Ÿ' => 'ð�’·', 'ð�“ ' => 'ð�’¸', 'ð�“¡' => 'ð�’¹', 'ð�“¢' => 'ð�’º', 'ð�“£' => 'ð�’»', 'ð�“¤' => 'ð�’¼', 'ð�“¥' => 'ð�’½', 'ð�“¦' => 'ð�’¾', 'ð�“§' => 'ð�’¿', 'ð�“¨' => 'ð�“€', 'ð�“©' => 'ð�“�', 'ð�“ª' => 'ð�“‚', 'ð�“«' => 'ð�“ƒ', 'ð�“¬' => 'ð�“„', 'ð�“­' => 'ð�“…', 'ð�“®' => 'ð�“†', 'ð�“¯' => 'ð�“‡', 'ð�“°' => 'ð�“ˆ', 'ð�“±' => 'ð�“‰', 'ð�“²' => 'ð�“Š', 'ð�“³' => 'ð�“‹', 'ð�“´' => 'ð�“Œ', 'ð�“µ' => 'ð�“�', 'ð�“¶' => 'ð�“Ž', 'ð�“·' => 'ð�“�', 'ð�“¸' => 'ð�“�', 'ð�“¹' => 'ð�“‘', 'ð�“º' => 'ð�“’', 'ð�“»' => 'ð�““', 'ð�³€' => 'ð�²€', 'ð�³�' => 'ð�²�', 'ð�³‚' => 'ð�²‚', 'ð�³ƒ' => 'ð�²ƒ', 'ð�³„' => 'ð�²„', 'ð�³…' => 'ð�²…', 'ð�³†' => 'ð�²†', 'ð�³‡' => 'ð�²‡', 'ð�³ˆ' => 'ð�²ˆ', 'ð�³‰' => 'ð�²‰', 'ð�³Š' => 'ð�²Š', 'ð�³‹' => 'ð�²‹', 'ð�³Œ' => 'ð�²Œ', 'ð�³�' => 'ð�²�', 'ð�³Ž' => 'ð�²Ž', 'ð�³�' => 'ð�²�', 'ð�³�' => 'ð�²�', 'ð�³‘' => 'ð�²‘', 'ð�³’' => 'ð�²’', 'ð�³“' => 'ð�²“', 'ð�³”' => 'ð�²”', 'ð�³•' => 'ð�²•', 'ð�³–' => 'ð�²–', 'ð�³—' => 'ð�²—', 'ð�³˜' => 'ð�²˜', 'ð�³™' => 'ð�²™', 'ð�³š' => 'ð�²š', 'ð�³›' => 'ð�²›', 'ð�³œ' => 'ð�²œ', 'ð�³�' => 'ð�²�', 'ð�³ž' => 'ð�²ž', 'ð�³Ÿ' => 'ð�²Ÿ', 'ð�³ ' => 'ð�² ', 'ð�³¡' => 'ð�²¡', 'ð�³¢' => 'ð�²¢', 'ð�³£' => 'ð�²£', 'ð�³¤' => 'ð�²¤', 'ð�³¥' => 'ð�²¥', 'ð�³¦' => 'ð�²¦', 'ð�³§' => 'ð�²§', 'ð�³¨' => 'ð�²¨', 'ð�³©' => 'ð�²©', 'ð�³ª' => 'ð�²ª', 'ð�³«' => 'ð�²«', 'ð�³¬' => 'ð�²¬', 'ð�³­' => 'ð�²­', 'ð�³®' => 'ð�²®', 'ð�³¯' => 'ð�²¯', 'ð�³°' => 'ð�²°', 'ð�³±' => 'ð�²±', 'ð�³²' => 'ð�²²', 'ð‘£€' => 'ð‘¢ ', 'ð‘£�' => 'ð‘¢¡', 'ð‘£‚' => 'ð‘¢¢', 'ð‘£ƒ' => 'ð‘¢£', 'ð‘£„' => 'ð‘¢¤', 'ð‘£…' => 'ð‘¢¥', 'ð‘£†' => 'ð‘¢¦', 'ð‘£‡' => 'ð‘¢§', 'ð‘£ˆ' => 'ð‘¢¨', 'ð‘£‰' => 'ð‘¢©', 'ð‘£Š' => 'ð‘¢ª', 'ð‘£‹' => 'ð‘¢«', 'ð‘£Œ' => 'ð‘¢¬', 'ð‘£�' => 'ð‘¢­', 'ð‘£Ž' => 'ð‘¢®', 'ð‘£�' => 'ð‘¢¯', 'ð‘£�' => 'ð‘¢°', 'ð‘£‘' => 'ð‘¢±', 'ð‘£’' => 'ð‘¢²', 'ð‘£“' => 'ð‘¢³', 'ð‘£”' => 'ð‘¢´', 'ð‘£•' => 'ð‘¢µ', 'ð‘£–' => 'ð‘¢¶', 'ð‘£—' => 'ð‘¢·', 'ð‘£˜' => 'ð‘¢¸', 'ð‘£™' => 'ð‘¢¹', 'ð‘£š' => 'ð‘¢º', 'ð‘£›' => 'ð‘¢»', 'ð‘£œ' => 'ð‘¢¼', 'ð‘£�' => 'ð‘¢½', 'ð‘£ž' => 'ð‘¢¾', 'ð‘£Ÿ' => 'ð‘¢¿', 'ð–¹ ' => 'ð–¹€', 'ð–¹¡' => 'ð–¹�', 'ð–¹¢' => 'ð–¹‚', 'ð–¹£' => 'ð–¹ƒ', 'ð–¹¤' => 'ð–¹„', 'ð–¹¥' => 'ð–¹…', 'ð–¹¦' => 'ð–¹†', 'ð–¹§' => 'ð–¹‡', 'ð–¹¨' => 'ð–¹ˆ', 'ð–¹©' => 'ð–¹‰', 'ð–¹ª' => 'ð–¹Š', 'ð–¹«' => 'ð–¹‹', 'ð–¹¬' => 'ð–¹Œ', 'ð–¹­' => 'ð–¹�', 'ð–¹®' => 'ð–¹Ž', 'ð–¹¯' => 'ð–¹�', 'ð–¹°' => 'ð–¹�', 'ð–¹±' => 'ð–¹‘', 'ð–¹²' => 'ð–¹’', 'ð–¹³' => 'ð–¹“', 'ð–¹´' => 'ð–¹”', 'ð–¹µ' => 'ð–¹•', 'ð–¹¶' => 'ð–¹–', 'ð–¹·' => 'ð–¹—', 'ð–¹¸' => 'ð–¹˜', 'ð–¹¹' => 'ð–¹™', 'ð–¹º' => 'ð–¹š', 'ð–¹»' => 'ð–¹›', 'ð–¹¼' => 'ð–¹œ', 'ð–¹½' => 'ð–¹�', 'ð–¹¾' => 'ð–¹ž', 'ð–¹¿' => 'ð–¹Ÿ', 'ðž¤¢' => 'ðž¤€', 'ðž¤£' => 'ðž¤�', 'ðž¤¤' => 'ðž¤‚', 'ðž¤¥' => 'ðž¤ƒ', 'ðž¤¦' => 'ðž¤„', 'ðž¤§' => 'ðž¤…', 'ðž¤¨' => 'ðž¤†', 'ðž¤©' => 'ðž¤‡', 'ðž¤ª' => 'ðž¤ˆ', 'ðž¤«' => 'ðž¤‰', 'ðž¤¬' => 'ðž¤Š', 'ðž¤­' => 'ðž¤‹', 'ðž¤®' => 'ðž¤Œ', 'ðž¤¯' => 'ðž¤�', 'ðž¤°' => 'ðž¤Ž', 'ðž¤±' => 'ðž¤�', 'ðž¤²' => 'ðž¤�', 'ðž¤³' => 'ðž¤‘', 'ðž¤´' => 'ðž¤’', 'ðž¤µ' => 'ðž¤“', 'ðž¤¶' => 'ðž¤”', 'ðž¤·' => 'ðž¤•', 'ðž¤¸' => 'ðž¤–', 'ðž¤¹' => 'ðž¤—', 'ðž¤º' => 'ðž¤˜', 'ðž¤»' => 'ðž¤™', 'ðž¤¼' => 'ðž¤š', 'ðž¤½' => 'ðž¤›', 'ðž¤¾' => 'ðž¤œ', 'ðž¤¿' => 'ðž¤�', 'ðž¥€' => 'ðž¤ž', 'ðž¥�' => 'ðž¤Ÿ', 'ðž¥‚' => 'ðž¤ ', 'ðž¥ƒ' => 'ðž¤¡', 'ÃŸ' => 'SS', 'ï¬€' => 'FF', 'ï¬�' => 'FI', 'ï¬‚' => 'FL', 'ï¬ƒ' => 'FFI', 'ï¬„' => 'FFL', 'ï¬…' => 'ST', 'ï¬†' => 'ST', 'Ö‡' => 'ÔµÕ’', 'ï¬“' => 'Õ„Õ†', 'ï¬”' => 'Õ„Ôµ', 'ï¬•' => 'Õ„Ô»', 'ï¬–' => 'ÕŽÕ†', 'ï¬—' => 'Õ„Ô½', 'Å‰' => 'Ê¼N', 'Î�' => 'Î™ÌˆÌ�', 'Î°' => 'Î¥ÌˆÌ�', 'Ç°' => 'JÌŒ', 'áº–' => 'HÌ±', 'áº—' => 'TÌˆ', 'áº˜' => 'WÌŠ', 'áº™' => 'YÌŠ', 'áºš' => 'AÊ¾', 'á½�' => 'Î¥Ì“', 'á½’' => 'Î¥Ì“Ì€', 'á½”' => 'Î¥Ì“Ì�', 'á½–' => 'Î¥Ì“Í‚', 'á¾¶' => 'Î‘Í‚', 'á¿†' => 'Î—Í‚', 'á¿’' => 'Î™ÌˆÌ€', 'á¿“' => 'Î™ÌˆÌ�', 'á¿–' => 'Î™Í‚', 'á¿—' => 'Î™ÌˆÍ‚', 'á¿¢' => 'Î¥ÌˆÌ€', 'á¿£' => 'Î¥ÌˆÌ�', 'á¿¤' => 'Î¡Ì“', 'á¿¦' => 'Î¥Í‚', 'á¿§' => 'Î¥ÌˆÍ‚', 'á¿¶' => 'Î©Í‚', 'á¾ˆ' => 'á¼ˆÎ™', 'á¾‰' => 'á¼‰Î™', 'á¾Š' => 'á¼ŠÎ™', 'á¾‹' => 'á¼‹Î™', 'á¾Œ' => 'á¼ŒÎ™', 'á¾�' => 'á¼�Î™', 'á¾Ž' => 'á¼ŽÎ™', 'á¾�' => 'á¼�Î™', 'á¾˜' => 'á¼¨Î™', 'á¾™' => 'á¼©Î™', 'á¾š' => 'á¼ªÎ™', 'á¾›' => 'á¼«Î™', 'á¾œ' => 'á¼¬Î™', 'á¾�' => 'á¼­Î™', 'á¾ž' => 'á¼®Î™', 'á¾Ÿ' => 'á¼¯Î™', 'á¾¨' => 'á½¨Î™', 'á¾©' => 'á½©Î™', 'á¾ª' => 'á½ªÎ™', 'á¾«' => 'á½«Î™', 'á¾¬' => 'á½¬Î™', 'á¾­' => 'á½­Î™', 'á¾®' => 'á½®Î™', 'á¾¯' => 'á½¯Î™', 'á¾¼' => 'Î‘Î™', 'á¿Œ' => 'Î—Î™', 'á¿¼' => 'Î©Î™', 'á¾²' => 'á¾ºÎ™', 'á¾´' => 'Î†Î™', 'á¿‚' => 'á¿ŠÎ™', 'á¿„' => 'Î‰Î™', 'á¿²' => 'á¿ºÎ™', 'á¿´' => 'Î�Î™', 'á¾·' => 'Î‘Í‚Î™', 'á¿‡' => 'Î—Í‚Î™', 'á¿·' => 'Î©Í‚Î™');<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Mbstring;

/**
 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
 *
 * Implemented:
 * - mb_chr                  - Returns a specific character from its Unicode code point
 * - mb_convert_encoding     - Convert character encoding
 * - mb_convert_variables    - Convert character code in variable(s)
 * - mb_decode_mimeheader    - Decode string in MIME header field
 * - mb_encode_mimeheader    - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
 * - mb_decode_numericentity - Decode HTML numeric string reference to character
 * - mb_encode_numericentity - Encode character to HTML numeric string reference
 * - mb_convert_case         - Perform case folding on a string
 * - mb_detect_encoding      - Detect character encoding
 * - mb_get_info             - Get internal settings of mbstring
 * - mb_http_input           - Detect HTTP input character encoding
 * - mb_http_output          - Set/Get HTTP output character encoding
 * - mb_internal_encoding    - Set/Get internal character encoding
 * - mb_list_encodings       - Returns an array of all supported encodings
 * - mb_ord                  - Returns the Unicode code point of a character
 * - mb_output_handler       - Callback function converts character encoding in output buffer
 * - mb_scrub                - Replaces ill-formed byte sequences with substitute characters
 * - mb_strlen               - Get string length
 * - mb_strpos               - Find position of first occurrence of string in a string
 * - mb_strrpos              - Find position of last occurrence of a string in a string
 * - mb_str_split            - Convert a string to an array
 * - mb_strtolower           - Make a string lowercase
 * - mb_strtoupper           - Make a string uppercase
 * - mb_substitute_character - Set/Get substitution character
 * - mb_substr               - Get part of string
 * - mb_stripos              - Finds position of first occurrence of a string within another, case insensitive
 * - mb_stristr              - Finds first occurrence of a string within another, case insensitive
 * - mb_strrchr              - Finds the last occurrence of a character in a string within another
 * - mb_strrichr             - Finds the last occurrence of a character in a string within another, case insensitive
 * - mb_strripos             - Finds position of last occurrence of a string within another, case insensitive
 * - mb_strstr               - Finds first occurrence of a string within another
 * - mb_strwidth             - Return width of string
 * - mb_substr_count         - Count the number of substring occurrences
 *
 * Not implemented:
 * - mb_convert_kana         - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
 * - mb_ereg_*               - Regular expression with multibyte support
 * - mb_parse_str            - Parse GET/POST/COOKIE data and set global variable
 * - mb_preferred_mime_name  - Get MIME charset string
 * - mb_regex_encoding       - Returns current encoding for multibyte regex as string
 * - mb_regex_set_options    - Set/Get the default options for mbregex functions
 * - mb_send_mail            - Send encoded mail
 * - mb_split                - Split multibyte string using regular expression
 * - mb_strcut               - Get part of string
 * - mb_strimwidth           - Get truncated string with specified width
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Mbstring
{
    public const MB_CASE_FOLD = \PHP_INT_MAX;
    private const CASE_FOLD = [['Âµ', 'Å¿', "Í…", 'Ï‚', "Ï�", "Ï‘", "Ï•", "Ï–", "Ï°", "Ï±", "Ïµ", "áº›", "á¾¾"], ['Î¼', 's', 'Î¹', 'Ïƒ', 'Î²', 'Î¸', 'Ï†', 'Ï€', 'Îº', 'Ï�', 'Îµ', "á¹¡", 'Î¹']];
    private static $encodingList = ['ASCII', 'UTF-8'];
    private static $language = 'neutral';
    private static $internalEncoding = 'UTF-8';
    /**
     *
     */
    public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
    {
        if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
            $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
        } else {
            $fromEncoding = self::getEncoding($fromEncoding);
        }
        $toEncoding = self::getEncoding($toEncoding);
        if ('BASE64' === $fromEncoding) {
            $s = base64_decode($s);
            $fromEncoding = $toEncoding;
        }
        if ('BASE64' === $toEncoding) {
            return base64_encode($s);
        }
        if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
            if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
                $fromEncoding = 'Windows-1252';
            }
            if ('UTF-8' !== $fromEncoding) {
                $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s);
            }
            return preg_replace_callback('/[\\x80-\\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
        }
        if ('HTML-ENTITIES' === $fromEncoding) {
            $s = \Phabel\Target\Php80\Polyfill::html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
            $fromEncoding = 'UTF-8';
        }
        return \iconv($fromEncoding, $toEncoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
    {
        $ok = true;
        array_walk_recursive($vars, function (&$v) use(&$ok, $toEncoding, $fromEncoding) {
            if (false === ($v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding))) {
                $ok = false;
            }
        });
        return $ok ? $fromEncoding : false;
    }
    /**
     *
     */
    public static function mb_decode_mimeheader($s)
    {
        return \Phabel\Target\Php80\Polyfill::iconv_mime_decode($s, 2, self::$internalEncoding);
    }
    /**
     *
     */
    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
    {
        trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
    }
    /**
     *
     */
    public static function mb_decode_numericentity($s, $convmap, $encoding = null)
    {
        if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_decode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
            return false;
        }
        if (null !== $encoding && !is_scalar($encoding)) {
            trigger_error('mb_decode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return '';
            // Instead of null (cf. mb_encode_numericentity).
        }
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        $cnt = floor(\count($convmap) / 4) * 4;
        for ($i = 0; $i < $cnt; $i += 4) {
            // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
            $convmap[$i] += $convmap[$i + 2];
            $convmap[$i + 1] += $convmap[$i + 2];
        }
        $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use($cnt, $convmap) {
            $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
            for ($i = 0; $i < $cnt; $i += 4) {
                if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
                    return self::mb_chr($c - $convmap[$i + 2]);
                }
            }
            return $m[0];
        }, $s);
        if (null === $encoding) {
            return $s;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
    {
        if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_encode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
            return false;
        }
        if (null !== $encoding && !is_scalar($encoding)) {
            trigger_error('mb_encode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
            // Instead of '' (cf. mb_decode_numericentity).
        }
        if (null !== $is_hex && !is_scalar($is_hex)) {
            trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
        $cnt = floor(\count($convmap) / 4) * 4;
        $i = 0;
        $len = \strlen($s);
        $result = '';
        while ($i < $len) {
            $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
            $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i, $ulen);
            $i += $ulen;
            $c = self::mb_ord($uchr);
            for ($j = 0; $j < $cnt; $j += 4) {
                if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
                    $cOffset = $c + $convmap[$j + 2] & $convmap[$j + 3];
                    $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#' . $cOffset . ';';
                    continue 2;
                }
            }
            $result .= $uchr;
        }
        if (null === $encoding) {
            return $result;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $result);
    }
    /**
     *
     */
    public static function mb_convert_case($s, $mode, $encoding = null)
    {
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        if (\MB_CASE_TITLE == $mode) {
            static $titleRegexp = null;
            if (null === $titleRegexp) {
                $titleRegexp = self::getData('titleCaseRegexp');
            }
            $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
        } else {
            if (\MB_CASE_UPPER == $mode) {
                static $upper = null;
                if (null === $upper) {
                    $upper = self::getData('upperCase');
                }
                $map = $upper;
            } else {
                if (self::MB_CASE_FOLD === $mode) {
                    $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
                }
                static $lower = null;
                if (null === $lower) {
                    $lower = self::getData('lowerCase');
                }
                $map = $lower;
            }
            static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
            $i = 0;
            $len = \strlen($s);
            while ($i < $len) {
                $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
                $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i, $ulen);
                $i += $ulen;
                if (isset($map[$uchr])) {
                    $uchr = $map[$uchr];
                    $nlen = \strlen($uchr);
                    if ($nlen == $ulen) {
                        $nlen = $i;
                        do {
                            $s[--$nlen] = $uchr[--$ulen];
                        } while ($ulen);
                    } else {
                        $s = \Phabel\Target\Php80\Polyfill::substr_replace($s, $uchr, $i - $ulen, $ulen);
                        $len += $nlen - $ulen;
                        $i += $nlen - $ulen;
                    }
                }
            }
        }
        if (null === $encoding) {
            return $s;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_internal_encoding($encoding = null)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }
        $normalizedEncoding = self::getEncoding($encoding);
        if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
            self::$internalEncoding = $normalizedEncoding;
            return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
    }
    /**
     *
     */
    public static function mb_language($lang = null)
    {
        if (null === $lang) {
            return self::$language;
        }
        switch ($normalizedLang = strtolower($lang)) {
            case 'uni':
            case 'neutral':
                self::$language = $normalizedLang;
                return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
    }
    /**
     *
     */
    public static function mb_list_encodings()
    {
        return ['UTF-8'];
    }
    /**
     *
     */
    public static function mb_encoding_aliases($encoding)
    {
        switch (strtoupper($encoding)) {
            case 'UTF8':
            case 'UTF-8':
                return ['utf8'];
        }
        return false;
    }
    /**
     *
     */
    public static function mb_check_encoding($var = null, $encoding = null)
    {
        if (null === $encoding) {
            if (null === $var) {
                return false;
            }
            $encoding = self::$internalEncoding;
        }
        return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var);
    }
    /**
     *
     */
    public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
    {
        if (null === $encodingList) {
            $encodingList = self::$encodingList;
        } else {
            if (!\is_array($encodingList)) {
                $encodingList = array_map('trim', explode(',', $encodingList));
            }
            $encodingList = array_map('strtoupper', $encodingList);
        }
        foreach ($encodingList as $enc) {
            switch ($enc) {
                case 'ASCII':
                    if (!preg_match('/[\\x80-\\xFF]/', $str)) {
                        return $enc;
                    }
                    break;
                case 'UTF8':
                case 'UTF-8':
                    if (preg_match('//u', $str)) {
                        return 'UTF-8';
                    }
                    break;
                default:
                    if (0 === strncmp($enc, 'ISO-8859-', 9)) {
                        return $enc;
                    }
            }
        }
        return false;
    }
    /**
     *
     */
    public static function mb_detect_order($encodingList = null)
    {
        if (null === $encodingList) {
            return self::$encodingList;
        }
        if (!\is_array($encodingList)) {
            $encodingList = array_map('trim', explode(',', $encodingList));
        }
        $encodingList = array_map('strtoupper', $encodingList);
        foreach ($encodingList as $enc) {
            switch ($enc) {
                default:
                    if (strncmp($enc, 'ISO-8859-', 9)) {
                        return false;
                    }
                // no break
                case 'ASCII':
                case 'UTF8':
                case 'UTF-8':
            }
        }
        self::$encodingList = $encodingList;
        return true;
    }
    /**
     *
     */
    public static function mb_strlen($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return \strlen($s);
        }
        return @\Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding);
    }
    /**
     *
     */
    public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strpos($haystack, $needle, $offset);
        }
        $needle = (string) $needle;
        if ('' === $needle) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(__METHOD__ . ': Empty delimiter', \E_USER_WARNING);
                return false;
            }
            return 0;
        }
        return \Phabel\Target\Php80\Polyfill::iconv_strpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strrpos($haystack, $needle, $offset);
        }
        if ($offset != (int) $offset) {
            $offset = 0;
        } elseif ($offset = (int) $offset) {
            if ($offset < 0) {
                if (0 > ($offset += self::mb_strlen($needle))) {
                    $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
                }
                $offset = 0;
            } else {
                $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
            }
        }
        $pos = '' !== $needle || 80000 > \PHP_VERSION_ID ? \Phabel\Target\Php80\Polyfill::iconv_strrpos($haystack, $needle, $encoding) : self::mb_strlen($haystack, $encoding);
        return false !== $pos ? $offset + $pos : false;
    }
    /**
     *
     */
    public static function mb_str_split($string, $split_length = 1, $encoding = null)
    {
        if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
            trigger_error('mb_str_split() expects parameter 1 to be string, ' . \gettype($string) . ' given', \E_USER_WARNING);
            return null;
        }
        if (1 > ($split_length = (int) $split_length)) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
                return false;
            }
            throw new \ValueError('Argument #2 ($length) must be greater than 0');
        }
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
        if ('UTF-8' === ($encoding = self::getEncoding($encoding))) {
            $rx = '/(';
            while (65535 < $split_length) {
                $rx .= '.{65535}';
                $split_length -= 65535;
            }
            $rx .= '.{' . $split_length . '})/us';
            return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
        }
        $result = [];
        $length = mb_strlen($string, $encoding);
        for ($i = 0; $i < $length; $i += $split_length) {
            $result[] = mb_substr($string, $i, $split_length, $encoding);
        }
        return $result;
    }
    /**
     *
     */
    public static function mb_strtolower($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
    }
    /**
     *
     */
    public static function mb_strtoupper($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
    }
    /**
     *
     */
    public static function mb_substitute_character($c = null)
    {
        if (null === $c) {
            return 'none';
        }
        if (0 === strcasecmp($c, 'none')) {
            return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
    }
    /**
     *
     */
    public static function mb_substr($s, $start, $length = null, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return (string) \Phabel\Target\Php80\Polyfill::substr($s, $start, null === $length ? 2147483647 : $length);
        }
        if ($start < 0) {
            $start = \Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding) + $start;
            if ($start < 0) {
                $start = 0;
            }
        }
        if (null === $length) {
            $length = 2147483647;
        } elseif ($length < 0) {
            $length = \Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding) + $length - $start;
            if ($length < 0) {
                return '';
            }
        }
        return (string) \Phabel\Target\Php80\Polyfill::iconv_substr($s, $start, $length, $encoding);
    }
    /**
     *
     */
    public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
        return self::mb_strpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            $pos = strrpos($haystack, $needle);
        } else {
            $needle = self::mb_substr($needle, 0, 1, $encoding);
            $pos = \Phabel\Target\Php80\Polyfill::iconv_strrpos($haystack, $needle, $encoding);
        }
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
    {
        $needle = self::mb_substr($needle, 0, 1, $encoding);
        $pos = self::mb_strripos($haystack, $needle, $encoding);
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
        return self::mb_strrpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = strpos($haystack, $needle);
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return \Phabel\Target\Php80\Polyfill::substr($haystack, 0, $pos);
        }
        return \Phabel\Target\Php80\Polyfill::substr($haystack, $pos);
    }
    /**
     *
     */
    public static function mb_get_info($type = 'all')
    {
        $info = ['internal_encoding' => self::$internalEncoding, 'http_output' => 'pass', 'http_output_conv_mimetypes' => '^(text/|application/xhtml\\+xml)', 'func_overload' => 0, 'func_overload_list' => 'no overload', 'mail_charset' => 'UTF-8', 'mail_header_encoding' => 'BASE64', 'mail_body_encoding' => 'BASE64', 'illegal_chars' => 0, 'encoding_translation' => 'Off', 'language' => self::$language, 'detect_order' => self::$encodingList, 'substitute_character' => 'none', 'strict_detection' => 'Off'];
        if ('all' === $type) {
            return $info;
        }
        if (isset($info[$type])) {
            return $info[$type];
        }
        return false;
    }
    /**
     *
     */
    public static function mb_http_input($type = '')
    {
        return false;
    }
    /**
     *
     */
    public static function mb_http_output($encoding = null)
    {
        return null !== $encoding ? 'pass' === $encoding : 'pass';
    }
    /**
     *
     */
    public static function mb_strwidth($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' !== $encoding) {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        $s = preg_replace('/[\\x{1100}-\\x{115F}\\x{2329}\\x{232A}\\x{2E80}-\\x{303E}\\x{3040}-\\x{A4CF}\\x{AC00}-\\x{D7A3}\\x{F900}-\\x{FAFF}\\x{FE10}-\\x{FE19}\\x{FE30}-\\x{FE6F}\\x{FF00}-\\x{FF60}\\x{FFE0}-\\x{FFE6}\\x{20000}-\\x{2FFFD}\\x{30000}-\\x{3FFFD}]/u', '', $s, -1, $wide);
        return ($wide << 1) + \Phabel\Target\Php80\Polyfill::iconv_strlen($s, 'UTF-8');
    }
    /**
     *
     */
    public static function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return \Phabel\Target\Php80\Polyfill::substr_count($haystack, $needle);
    }
    /**
     *
     */
    public static function mb_output_handler($contents, $status)
    {
        return $contents;
    }
    /**
     *
     */
    public static function mb_chr($code, $encoding = null)
    {
        if (0x80 > ($code %= 0x200000)) {
            $s = \chr($code);
        } elseif (0x800 > $code) {
            $s = \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
        } elseif (0x10000 > $code) {
            $s = \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
        } else {
            $s = \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
        }
        if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) {
            $s = mb_convert_encoding($s, $encoding, 'UTF-8');
        }
        return $s;
    }
    /**
     *
     */
    public static function mb_ord($s, $encoding = null)
    {
        if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) {
            $s = mb_convert_encoding($s, 'UTF-8', $encoding);
        }
        if (1 === \strlen($s)) {
            return \ord($s);
        }
        $code = ($s = unpack('C*', \Phabel\Target\Php80\Polyfill::substr($s, 0, 4))) ? $s[1] : 0;
        if (0xf0 <= $code) {
            return ($code - 0xf0 << 18) + ($s[2] - 0x80 << 12) + ($s[3] - 0x80 << 6) + $s[4] - 0x80;
        }
        if (0xe0 <= $code) {
            return ($code - 0xe0 << 12) + ($s[2] - 0x80 << 6) + $s[3] - 0x80;
        }
        if (0xc0 <= $code) {
            return ($code - 0xc0 << 6) + $s[2] - 0x80;
        }
        return $code;
    }
    /**
     *
     */
    private static function getSubpart($pos, $part, $haystack, $encoding)
    {
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return self::mb_substr($haystack, 0, $pos, $encoding);
        }
        return self::mb_substr($haystack, $pos, null, $encoding);
    }
    /**
     *
     */
    private static function html_encoding_callback(array $m)
    {
        $i = 1;
        $entities = '';
        $m = unpack('C*', \Phabel\Target\Php80\Polyfill::htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
        while (isset($m[$i])) {
            if (0x80 > $m[$i]) {
                $entities .= \chr($m[$i++]);
                continue;
            }
            if (0xf0 <= $m[$i]) {
                $c = ($m[$i++] - 0xf0 << 18) + ($m[$i++] - 0x80 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
            } elseif (0xe0 <= $m[$i]) {
                $c = ($m[$i++] - 0xe0 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
            } else {
                $c = ($m[$i++] - 0xc0 << 6) + $m[$i++] - 0x80;
            }
            $entities .= '&#' . $c . ';';
        }
        return $entities;
    }
    /**
     *
     */
    private static function title_case(array $s)
    {
        return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8') . self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
    }
    /**
     *
     */
    private static function getData($file)
    {
        if (file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) {
            return require $file;
        }
        return false;
    }
    /**
     *
     */
    private static function getEncoding($encoding)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }
        if ('UTF-8' === $encoding) {
            return 'UTF-8';
        }
        $encoding = strtoupper($encoding);
        if ('8BIT' === $encoding || 'BINARY' === $encoding) {
            return 'CP850';
        }
        if ('UTF8' === $encoding) {
            return 'UTF-8';
        }
        return $encoding;
    }
}{
    "name": "symfony/polyfill-mbstring",
    "type": "library",
    "description": "Symfony polyfill for the Mbstring extension",
    "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
        "files": [ "bootstrap.php" ]
    },
    "suggest": {
        "ext-mbstring": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Mbstring as p;
if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__ . '/bootstrap80.php';
}
if (!function_exists('mb_convert_encoding')) {
    /**
     *
     */
    function mb_convert_encoding($string, $to_encoding, $from_encoding = null)
    {
        return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding);
    }
}
if (!function_exists('mb_decode_mimeheader')) {
    /**
     *
     */
    function mb_decode_mimeheader($string)
    {
        return p\Mbstring::mb_decode_mimeheader($string);
    }
}
if (!function_exists('mb_encode_mimeheader')) {
    /**
     *
     */
    function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0)
    {
        return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent);
    }
}
if (!function_exists('mb_decode_numericentity')) {
    /**
     *
     */
    function mb_decode_numericentity($string, $map, $encoding = null)
    {
        return p\Mbstring::mb_decode_numericentity($string, $map, $encoding);
    }
}
if (!function_exists('mb_encode_numericentity')) {
    /**
     *
     */
    function mb_encode_numericentity($string, $map, $encoding = null, $hex = false)
    {
        return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex);
    }
}
if (!function_exists('mb_convert_case')) {
    /**
     *
     */
    function mb_convert_case($string, $mode, $encoding = null)
    {
        return p\Mbstring::mb_convert_case($string, $mode, $encoding);
    }
}
if (!function_exists('mb_internal_encoding')) {
    /**
     *
     */
    function mb_internal_encoding($encoding = null)
    {
        return p\Mbstring::mb_internal_encoding($encoding);
    }
}
if (!function_exists('mb_language')) {
    /**
     *
     */
    function mb_language($language = null)
    {
        return p\Mbstring::mb_language($language);
    }
}
if (!function_exists('mb_list_encodings')) {
    /**
     *
     */
    function mb_list_encodings()
    {
        return p\Mbstring::mb_list_encodings();
    }
}
if (!function_exists('mb_encoding_aliases')) {
    /**
     *
     */
    function mb_encoding_aliases($encoding)
    {
        return p\Mbstring::mb_encoding_aliases($encoding);
    }
}
if (!function_exists('mb_check_encoding')) {
    /**
     *
     */
    function mb_check_encoding($value = null, $encoding = null)
    {
        return p\Mbstring::mb_check_encoding($value, $encoding);
    }
}
if (!function_exists('mb_detect_encoding')) {
    /**
     *
     */
    function mb_detect_encoding($string, $encodings = null, $strict = false)
    {
        return p\Mbstring::mb_detect_encoding($string, $encodings, $strict);
    }
}
if (!function_exists('mb_detect_order')) {
    /**
     *
     */
    function mb_detect_order($encoding = null)
    {
        return p\Mbstring::mb_detect_order($encoding);
    }
}
if (!function_exists('mb_parse_str')) {
    /**
     *
     */
    function mb_parse_str($string, &$result = [])
    {
        parse_str($string, $result);
        return (bool) $result;
    }
}
if (!function_exists('mb_strlen')) {
    /**
     *
     */
    function mb_strlen($string, $encoding = null)
    {
        return p\Mbstring::mb_strlen($string, $encoding);
    }
}
if (!function_exists('mb_strpos')) {
    /**
     *
     */
    function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strtolower')) {
    /**
     *
     */
    function mb_strtolower($string, $encoding = null)
    {
        return p\Mbstring::mb_strtolower($string, $encoding);
    }
}
if (!function_exists('mb_strtoupper')) {
    /**
     *
     */
    function mb_strtoupper($string, $encoding = null)
    {
        return p\Mbstring::mb_strtoupper($string, $encoding);
    }
}
if (!function_exists('mb_substitute_character')) {
    /**
     *
     */
    function mb_substitute_character($substitute_character = null)
    {
        return p\Mbstring::mb_substitute_character($substitute_character);
    }
}
if (!function_exists('mb_substr')) {
    /**
     *
     */
    function mb_substr($string, $start, $length = 2147483647, $encoding = null)
    {
        return p\Mbstring::mb_substr($string, $start, $length, $encoding);
    }
}
if (!function_exists('mb_stripos')) {
    /**
     *
     */
    function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_stristr')) {
    /**
     *
     */
    function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strrchr')) {
    /**
     *
     */
    function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strrichr')) {
    /**
     *
     */
    function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strripos')) {
    /**
     *
     */
    function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strrpos')) {
    /**
     *
     */
    function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strstr')) {
    /**
     *
     */
    function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_get_info')) {
    /**
     *
     */
    function mb_get_info($type = 'all')
    {
        return p\Mbstring::mb_get_info($type);
    }
}
if (!function_exists('mb_http_output')) {
    /**
     *
     */
    function mb_http_output($encoding = null)
    {
        return p\Mbstring::mb_http_output($encoding);
    }
}
if (!function_exists('mb_strwidth')) {
    /**
     *
     */
    function mb_strwidth($string, $encoding = null)
    {
        return p\Mbstring::mb_strwidth($string, $encoding);
    }
}
if (!function_exists('mb_substr_count')) {
    /**
     *
     */
    function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return p\Mbstring::mb_substr_count($haystack, $needle, $encoding);
    }
}
if (!function_exists('mb_output_handler')) {
    /**
     *
     */
    function mb_output_handler($string, $status)
    {
        return p\Mbstring::mb_output_handler($string, $status);
    }
}
if (!function_exists('mb_http_input')) {
    /**
     *
     */
    function mb_http_input($type = null)
    {
        return p\Mbstring::mb_http_input($type);
    }
}
if (!function_exists('mb_convert_variables')) {
    /**
     *
     */
    function mb_convert_variables($to_encoding, $from_encoding, &...$vars)
    {
        return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars);
    }
}
if (!function_exists('mb_ord')) {
    /**
     *
     */
    function mb_ord($string, $encoding = null)
    {
        return p\Mbstring::mb_ord($string, $encoding);
    }
}
if (!function_exists('mb_chr')) {
    /**
     *
     */
    function mb_chr($codepoint, $encoding = null)
    {
        return p\Mbstring::mb_chr($codepoint, $encoding);
    }
}
if (!function_exists('mb_scrub')) {
    /**
     *
     */
    function mb_scrub($string, $encoding = null)
    {
        $encoding = null === $encoding ? mb_internal_encoding() : $encoding;
        return mb_convert_encoding($string, $encoding, $encoding);
    }
}
if (!function_exists('mb_str_split')) {
    /**
     *
     */
    function mb_str_split($string, $length = 1, $encoding = null)
    {
        return p\Mbstring::mb_str_split($string, $length, $encoding);
    }
}
if (extension_loaded('mbstring')) {
    return;
}
if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}<?php

namespace cash;

/**
 * Least Recently Used Cache
 *
 * A fixed sized cache that removes the element used last when it reaches its
 * size limit.
 */
class LRUCache
{
    /** @var int */
    protected $maximumSize;
    /**
     * The front of the array contains the LRU element
     *
     * @var array
     */
    protected $data = array();
    /**
     * Create a LRU Cache
     *
     * @param int $size
     * @throws \InvalidArgumentException
     */
    public function __construct($size)
    {
        if (!is_int($size) || $size <= 0) {
            throw new \InvalidArgumentException();
        }
        $this->maximumSize = $size;
    }
    /**
     * Get the value cached with this key
     *
     * @param (int | string) $key The key. Strings that are ints are cast to ints.
     * @param mixed $default The value to be returned if key not found. (Optional)
     * @return mixed
     */
    public function get($key, $default = null)
    {
        if (isset($this->data[$key])) {
            $this->recordAccess($key);
            return $this->data[$key];
        } else {
            return $default;
        }
    }
    /**
     * Put something in the cache
     *
     * @param (int | string) $key The key. Strings that are ints are cast to ints.
     * @param mixed $value The value to cache
     */
    public function put($key, $value)
    {
        if (isset($this->data[$key])) {
            $this->data[$key] = $value;
            $this->recordAccess($key);
        } else {
            $this->data[$key] = $value;
            if ($this->size() > $this->maximumSize) {
                // remove least recently used element (front of array)
                reset($this->data);
                unset($this->data[key($this->data)]);
            }
        }
    }
    /**
     * Get the number of elements in the cache
     *
     * @return int
     */
    public function size()
    {
        return count($this->data);
    }
    /**
     * Does the cache contain an element with this key
     *
     * @param (int | string) $key The key
     * @return boolean
     */
    public function containsKey($key)
    {
        return isset($this->data[$key]);
    }
    /**
     * Remove the element with this key.
     *
     * @param (int | string) $key The key
     * @return mixed Value or null if not set
     */
    public function remove($key)
    {
        if (isset($this->data[$key])) {
            $value = $this->data[$key];
            unset($this->data[$key]);
            return $value;
        } else {
            return null;
        }
    }
    /**
     * Clear the cache
     */
    public function clear()
    {
        $this->data = array();
    }
    /**
     * Moves the element from current position to end of array
     *
     * @param (int | string) $key The key
     */
    protected function recordAccess($key)
    {
        $value = $this->data[$key];
        unset($this->data[$key]);
        $this->data[$key] = $value;
    }
}{
    "name": "cash/lrucache",
    "type": "library",
    "description": "An efficient memory-based Least Recently Used (LRU) cache",
    "keywords": ["cache", "lru"],
    "homepage": "https://github.com/cash/LRUCache",
    "license": "MIT",
    "authors": [
        {
            "name": "Cash Costello",
            "email": "cash.costello@gmail.com"
        }
    ],
    "minimum-stability": "stable",
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-0": {
            "cash": "src/"
        }
    }
}
<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\Response;
use Amp\Socket\Socket;
use Amp\Websocket\CompressionContext;
use Amp\Websocket\Options;
interface ConnectionFactory
{
    /**
     * @param Response $response
     * @param Socket $socket
     * @param Options $options
     * @param (CompressionContext | null) $compressionContext
     *
     * @return Connection
     */
    public function createConnection(Response $response, Socket $socket, Options $options, ?CompressionContext $compressionContext = null) : Connection;
}<?php

namespace Amp\Websocket\Client;

use Amp\ByteStream\InputStream;
use Amp\Http\Client\Response;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Websocket\ClientMetadata;
use Amp\Websocket\Code;
use Amp\Websocket\Options;
use Amp\Websocket\Rfc6455Client;
final class Rfc6455Connection implements Connection
{
    /** @var Rfc6455Client */
    private $client;
    /** @var Response */
    private $response;
    /**
     *
     */
    public function __construct(Rfc6455Client $client, Response $response)
    {
        $this->client = $client;
        $this->response = $response;
    }
    /**
     *
     */
    public function getResponse() : Response
    {
        return $this->response;
    }
    /**
     *
     */
    public function receive() : Promise
    {
        return $this->client->receive();
    }
    /**
     *
     */
    public function getId() : int
    {
        return $this->client->getId();
    }
    /**
     *
     */
    public function getOptions() : Options
    {
        return $this->client->getOptions();
    }
    /**
     *
     */
    public function isConnected() : bool
    {
        return $this->client->isConnected();
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->client->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->client->getRemoteAddress();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->client->getTlsInfo();
    }
    /**
     *
     */
    public function isClosedByPeer() : bool
    {
        return $this->client->isClosedByPeer();
    }
    /**
     *
     */
    public function getUnansweredPingCount() : int
    {
        return $this->client->getUnansweredPingCount();
    }
    /**
     *
     */
    public function getCloseCode() : int
    {
        return $this->client->getCloseCode();
    }
    /**
     *
     */
    public function getCloseReason() : string
    {
        return $this->client->getCloseReason();
    }
    /**
     *
     */
    public function send(string $data) : Promise
    {
        return $this->client->send($data);
    }
    /**
     *
     */
    public function sendBinary(string $data) : Promise
    {
        return $this->client->sendBinary($data);
    }
    /**
     *
     */
    public function stream(InputStream $stream) : Promise
    {
        return $this->client->stream($stream);
    }
    /**
     *
     */
    public function streamBinary(InputStream $stream) : Promise
    {
        return $this->client->streamBinary($stream);
    }
    /**
     *
     */
    public function ping() : Promise
    {
        return $this->client->ping();
    }
    /**
     *
     */
    public function getInfo() : ClientMetadata
    {
        return $this->client->getInfo();
    }
    /**
     *
     */
    public function close(int $code = Code::NORMAL_CLOSE, string $reason = '') : Promise
    {
        return $this->client->close($code, $reason);
    }
    /**
     *
     */
    public function onClose(callable $onClose) : void
    {
        $this->client->onClose($onClose);
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\Request;
use Amp\Http\Message;
use Amp\Websocket\Options;
use League\Uri;
use Psr\Http\Message\UriInterface as PsrUri;
final class Handshake extends Message
{
    /** @var PsrUri */
    private $uri;
    /** @var Options */
    private $options;
    /** @var int */
    private $tcpConnectTimeout = 10000;
    /** @var int */
    private $tlsHandshakeTimeout = 10000;
    /** @var int */
    private $headerSizeLimit = Request::DEFAULT_HEADER_SIZE_LIMIT;
    /**
    * @param (string | PsrUri) $uri target address of websocket (e.g. ws://foo.bar/bar or a
    wss://crypto.example/?secureConnection) or a PsrUri instance.
    * @param (Options | null) $options
    * @param (string[] | string[][]) $headers
    *
    * @throws \TypeError If $uri is not a string or an instance of PsrUri.
    */
    public function __construct($uri, ?Options $options = null, array $headers = [])
    {
        $this->uri = $this->makeUri($uri);
        $this->options = $this->checkOptions($options);
        $this->setHeaders($headers);
    }
    /**
     * @return PsrUri Websocket URI (scheme will be either ws or wss).
     */
    public function getUri() : PsrUri
    {
        return $this->uri;
    }
    /**
     * @param (string | PsrUri) $uri
     *
     * @return self Cloned object
     */
    public function withUri($uri) : self
    {
        $clone = clone $this;
        $clone->uri = $clone->makeUri($uri);
        return $clone;
    }
    /**
     * @return Options
     */
    public function getOptions() : Options
    {
        return $this->options;
    }
    /**
     * @param Options $options
     *
     * @return self Cloned object.
     */
    public function withOptions(Options $options) : self
    {
        $clone = clone $this;
        $clone->options = $clone->checkOptions($options);
        return $clone;
    }
    /**
     * @return int Timeout in milliseconds for the TCP connection.
     */
    public function getTcpConnectTimeout() : int
    {
        return $this->tcpConnectTimeout;
    }
    /**
     *
     */
    public function withTcpConnectTimeout(int $tcpConnectTimeout) : self
    {
        $clone = clone $this;
        $clone->tcpConnectTimeout = $tcpConnectTimeout;
        return $clone;
    }
    /**
     * @return int Timeout in milliseconds for the TLS handshake.
     */
    public function getTlsHandshakeTimeout() : int
    {
        return $this->tlsHandshakeTimeout;
    }
    /**
     *
     */
    public function withTlsHandshakeTimeout(int $tlsHandshakeTimeout) : self
    {
        $clone = clone $this;
        $clone->tlsHandshakeTimeout = $tlsHandshakeTimeout;
        return $clone;
    }
    /**
     *
     */
    public function getHeaderSizeLimit() : int
    {
        return $this->headerSizeLimit;
    }
    /**
     *
     */
    public function withHeaderSizeLimit(int $headerSizeLimit) : self
    {
        $clone = clone $this;
        $clone->headerSizeLimit = $headerSizeLimit;
        return $clone;
    }
    /**
     * Replaces all headers in the returned instance.
     *
     * @param (string[] | string[][]) $headers
     *
     * @return self Cloned object.
     */
    public function withHeaders(array $headers) : self
    {
        $clone = clone $this;
        foreach ($clone->getRawHeaders() as [$field]) {
            $clone->removeHeader($field);
        }
        $clone->setHeaders($headers);
        return $clone;
    }
    /**
     * Replaces the given header in the returned instance.
     *
     * @param string $name
     * @param (string | string[]) $value
     *
     * @return self Cloned object.
     */
    public function withHeader(string $name, $value) : self
    {
        $clone = clone $this;
        $clone->setHeader($name, $value);
        return $clone;
    }
    /**
     * Adds the given header in the returned instance.
     *
     * @param string $name
     * @param (string | string[]) $value
     *
     * @return self Cloned object.
     */
    public function withAddedHeader(string $name, $value) : self
    {
        $clone = clone $this;
        $clone->addHeader($name, $value);
        return $clone;
    }
    /**
     * Removes the given header in the returned instance.
     *
     * @param string $name
     *
     * @return self Cloned object.
     */
    public function withoutHeader(string $name) : self
    {
        $clone = clone $this;
        $clone->removeHeader($name);
        return $clone;
    }
    /**
     *
     */
    protected function setHeader(string $name, $value) : void
    {
        if (($name[0] ?? ':') === ':') {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::setHeader($name, $value);
    }
    /**
     *
     */
    protected function addHeader(string $name, $value) : void
    {
        if (($name[0] ?? ':') === ':') {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::addHeader($name, $value);
    }
    /**
     * @param (string | PsrUri) $uri
     *
     * @return PsrUri
     */
    private function makeUri($uri) : PsrUri
    {
        if (\is_string($uri)) {
            try {
                $uri = Uri\Http::createFromString($uri);
            } catch (\Exception $exception) {
                throw new \Error('Invalid Websocket URI provided', 0, $exception);
            }
        }
        /** @psalm-suppress DocblockTypeContradiction */
        if (!$uri instanceof PsrUri) {
            throw new \TypeError(\sprintf('Must provide an instance of %s or a websocket URI as a string', PsrUri::class));
        }
        switch ($uri->getScheme()) {
            case 'ws':
            case 'wss':
                break;
            default:
                throw new \Error('The URI scheme must be ws or wss: \'' . $uri->getScheme() . '\'');
        }
        return $uri;
    }
    /**
     *
     */
    private function checkOptions(?Options $options) : Options
    {
        if ($options === null) {
            return Options::createClientDefault();
        }
        return $options;
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\HttpException;
use Amp\Http\Client\Response;
final class ConnectionException extends HttpException
{
    /** @var Response */
    private $response;
    /**
     *
     */
    public function __construct(string $message, Response $response, ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->response = $response;
    }
    /**
     *
     */
    public function getResponse() : Response
    {
        return $this->response;
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Http;
use Amp\Http\Client\HttpClient;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Message;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Websocket;
use Amp\Websocket\CompressionContextFactory;
use Amp\Websocket\Rfc7692CompressionFactory;
use function Amp\call;
final class Rfc6455Connector implements Connector
{
    /** @var HttpClient */
    private $client;
    /** @var ConnectionFactory */
    private $connectionFactory;
    /** @var CompressionContextFactory */
    private $compressionFactory;
    /**
     * @param HttpClient $client
     * @param (ConnectionFactory | null) $connectionFactory Uses {@see Rfc6455ConnectionFactory} if null.
     * @param (CompressionContextFactory | null) $compressionFactory Uses {@see Rfc7692CompressionFactory} if null.
     */
    public function __construct(HttpClient $client, ?ConnectionFactory $connectionFactory = null, ?CompressionContextFactory $compressionFactory = null)
    {
        $this->client = $client;
        $this->connectionFactory = $connectionFactory ?? new Rfc6455ConnectionFactory();
        $this->compressionFactory = $compressionFactory ?? new Rfc7692CompressionFactory();
    }
    /**
     *
     */
    public function connect(Handshake $handshake, ?CancellationToken $cancellationToken = null) : Promise
    {
        return call(function () use($handshake, $cancellationToken) {
            $key = Websocket\generateKey();
            $request = $this->generateRequest($handshake, $key);
            $options = $handshake->getOptions();
            $deferred = new Deferred();
            $connectionFactory = $this->connectionFactory;
            $compressionFactory = $this->compressionFactory;
            $request->setUpgradeHandler(static function (EncryptableSocket $socket, Request $request, Response $response) use($connectionFactory, $compressionFactory, $deferred, $key, $options) : void {
                if (\strtolower((string) $response->getHeader('upgrade')) !== 'websocket') {
                    $deferred->fail(new ConnectionException('Upgrade header does not equal "websocket"', $response));
                    return;
                }
                if (!Websocket\validateAcceptForKey((string) $response->getHeader('sec-websocket-accept'), $key)) {
                    $deferred->fail(new ConnectionException('Invalid Sec-WebSocket-Accept header', $response));
                    return;
                }
                $extensions = self::splitField($response, 'sec-websocket-extensions');
                foreach ($extensions as $extension) {
                    if ($compressionContext = $compressionFactory->fromServerHeader($extension)) {
                        break;
                    }
                }
                $deferred->resolve($connectionFactory->createConnection($response, $socket, $options, $compressionContext ?? null));
            });
            /** @var Response $response */
            $response = (yield $this->client->request($request, $cancellationToken));
            if ($response->getStatus() !== Http\Status::SWITCHING_PROTOCOLS) {
                throw new ConnectionException(\sprintf('A %s (%d) response was not received; instead received response status: %s (%d)', Http\Status::getReason(Http\Status::SWITCHING_PROTOCOLS), Http\Status::SWITCHING_PROTOCOLS, $response->getReason(), $response->getStatus()), $response);
            }
            return (yield $deferred->promise());
        });
    }
    /**
     * @param Handshake $handshake
     * @param string $key
     *
     * @return Request
     */
    private function generateRequest(Handshake $handshake, string $key) : Request
    {
        $uri = $handshake->getUri();
        $uri = $uri->withScheme($uri->getScheme() === 'wss' ? 'https' : 'http');
        $request = new Request($uri, 'GET');
        $request->setHeaders($handshake->getHeaders());
        $request->setTcpConnectTimeout($handshake->getTcpConnectTimeout());
        $request->setTlsHandshakeTimeout($handshake->getTlsHandshakeTimeout());
        $request->setHeaderSizeLimit($handshake->getHeaderSizeLimit());
        if (!$request->hasHeader('origin')) {
            $origin = $uri->withUserInfo('')->withPath('')->withQuery('');
            $request->setHeader('origin', (string) $origin);
        }
        $extensions = self::splitField($request, 'sec-websocket-extensions');
        if ($handshake->getOptions()->isCompressionEnabled() && \extension_loaded('zlib')) {
            $extensions[] = $this->compressionFactory->createRequestHeader();
        }
        if (!empty($extensions)) {
            $request->setHeader('sec-websocket-extensions', \implode(', ', $extensions));
        }
        $request->setProtocolVersions(['1.1']);
        $request->setHeader('connection', 'Upgrade');
        $request->setHeader('upgrade', 'websocket');
        $request->setHeader('sec-websocket-version', '13');
        $request->setHeader('sec-websocket-key', $key);
        return $request;
    }
    /**
     *
     */
    private static function splitField(Message $message, string $headerName) : array
    {
        $header = \implode(', ', $message->getHeaderArray($headerName));
        if ($header === '') {
            return [];
        }
        \preg_match_all('(([^",]+(?:"((?:[^\\\\"]|\\\\.)*)"|([^,]*))?),?\\s*)', $header, $matches, \PREG_SET_ORDER);
        $values = [];
        foreach ($matches as $match) {
            // decode escaped characters
            $values[] = \preg_replace('(\\\\(.))', '\\1', \trim($match[1]));
        }
        return $values;
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\CancellationToken;
use Amp\Http\Client\HttpException;
use Amp\Promise;
interface Connector
{
    /**
     * @param Handshake $handshake
     * @param (CancellationToken | null) $cancellationToken
     *
     * @return Promise<Connection>
     *
     * @throws HttpException Thrown if the request fails.
     * @throws ConnectionException If the response received is invalid or is not a switching protocols (101) response.
     */
    public function connect(Handshake $handshake, ?CancellationToken $cancellationToken = null) : Promise;
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\Response;
use Amp\Websocket\Client;
interface Connection extends Client
{
    /**
     * @return Response Server response originating the client connection.
     */
    public function getResponse() : Response;
}<?php

namespace Amp\Websocket\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Connection\DefaultConnectionFactory;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\HttpException;
use Amp\Promise;
use Amp\Socket\ConnectContext;
use Psr\Http\Message\UriInterface as PsrUri;
/**
 * @param (string | PsrUri | Handshake) $handshake
 * @param (ConnectContext | null) $connectContext
 * @param (CancellationToken | null) $cancellationToken
 *
 * @return Promise<Connection>
 *
 * @throws ConnectionException If the response received is invalid or is not a switching protocols (101) response.
 * @throws HttpException Thrown if the request fails.
 */
function connect($handshake, ?ConnectContext $connectContext = null, ?CancellationToken $cancellationToken = null) : Promise
{
    if (!$handshake instanceof Handshake) {
        $handshake = new Handshake($handshake);
    }
    if ($connectContext === null) {
        $connectContext = (new ConnectContext())->withTcpNoDelay();
    }
    $httpClient = (new HttpClientBuilder())->usingPool(new UnlimitedConnectionPool(new DefaultConnectionFactory(null, $connectContext)))->build();
    return (new Rfc6455Connector($httpClient))->connect($handshake, $cancellationToken);
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\Response;
use Amp\Socket\Socket;
use Amp\Websocket\CompressionContext;
use Amp\Websocket\Options;
use Amp\Websocket\Rfc6455Client;
final class Rfc6455ConnectionFactory implements ConnectionFactory
{
    /**
     *
     */
    public function createConnection(Response $response, Socket $socket, Options $options, ?CompressionContext $compressionContext = null) : Connection
    {
        $client = new Rfc6455Client($socket, $options, true, $compressionContext);
        return new Rfc6455Connection($client, $response);
    }
}<?php

use Amp\ByteStream\StreamException;
use Amp\Loop;
use Amp\Websocket\Client;
use Amp\Websocket\Client\Connection;
use Amp\Websocket\Client\Handshake;
use Amp\Websocket\ClosedException;
use Amp\Websocket\Message;
use Amp\Websocket\Options;
require __DIR__ . '/../vendor/autoload.php';
const AGENT = 'amphp/websocket';
Loop::run(function () {
    $errors = 0;
    $options = Options::createClientDefault()->withBytesPerSecondLimit(\PHP_INT_MAX)->withFrameSizeLimit(\PHP_INT_MAX)->withFramesPerSecondLimit(\PHP_INT_MAX)->withMessageSizeLimit(\PHP_INT_MAX)->withValidateUtf8(true);
    /** @var Connection $connection */
    $connection = (yield Client\connect('ws://127.0.0.1:9001/getCaseCount'));
    /** @var Message $message */
    $message = (yield $connection->receive());
    $cases = (int) (yield $message->buffer());
    echo "Going to run {$cases} test cases." . PHP_EOL;
    for ($i = 1; $i < $cases; $i++) {
        $connection = (yield Client\connect('ws://127.0.0.1:9001/getCaseInfo?case=' . $i . '&agent=' . AGENT));
        $message = (yield $connection->receive());
        $info = \json_decode((yield $message->buffer()), true);
        print $info['id'] . ' ' . \str_repeat('-', 80 - \strlen($info['id']) - 1) . PHP_EOL;
        print \wordwrap($info['description'], 80, PHP_EOL) . ' ';
        $handshake = new Handshake('ws://127.0.0.1:9001/runCase?case=' . $i . '&agent=' . AGENT, $options);
        $connection = (yield Client\connect($handshake));
        try {
            while ($message = (yield $connection->receive())) {
                $content = (yield $message->buffer());
                if ($message->isBinary()) {
                    (yield $connection->sendBinary($content));
                } else {
                    (yield $connection->send($content));
                }
            }
        } catch (ClosedException $e) {
            // ignore
        } catch (AssertionError $e) {
            print 'Assertion error: ' . $e->getMessage() . PHP_EOL;
            $connection->close();
        } catch (Error $e) {
            print 'Error: ' . $e->getMessage() . PHP_EOL;
            $connection->close();
        } catch (StreamException $e) {
            print 'Stream exception: ' . $e->getMessage() . PHP_EOL;
            $connection->close();
        }
        $connection = (yield Client\connect('ws://127.0.0.1:9001/getCaseStatus?case=' . $i . '&agent=' . AGENT));
        $message = (yield $connection->receive());
        print $result = \json_decode((yield $message->buffer()), true)['behavior'];
        if ($result === 'FAILED') {
            $errors++;
        }
        print PHP_EOL . PHP_EOL;
    }
    $connection = (yield Client\connect('ws://127.0.0.1:9001/updateReports?agent=' . AGENT));
    $connection->close();
    Loop::stop();
    if ($errors) {
        exit(1);
    }
});{
    "url": "ws://127.0.0.1:9001",
    "outdir": "./reports/clients",
    "cases": [
        "*"
    ],
    "exclude-cases": [
        "12.2*",
        "12.3*",
        "12.4*",
        "12.5*"
    ]
}
{
    "name": "amphp/websocket-client",
    "description": "Async WebSocket client for PHP based on Amp.",
    "license": "MIT",
    "authors": [
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "support": {
        "issues": "https://github.com/amphp/websocket-client/issues"
    },
    "keywords": [
        "async",
        "non-blocking",
        "websocket",
        "client",
        "http",
        "amp",
        "amphp"
    ],
    "require": {
        "php": ">=7.2",
        "amphp/amp": "^2.2",
        "amphp/http": "^1.3",
        "amphp/http-client": "^4",
        "amphp/socket": "^1",
        "amphp/websocket": "^1",
        "league/uri": "^6",
        "psr/http-message": "^1"
    },
    "require-dev": {
        "amphp/http-server": "^2",
        "amphp/websocket-server": "dev-master as 2.0-rc4",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^8 || ^7",
        "psr/log": "^1",
        "vimeo/psalm": "^3.11@dev"
    },
    "minimum-stability": "RC",
    "autoload": {
        "psr-4": {
            "Amp\\Websocket\\Client\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Websocket\\Client\\Test\\": "test"
        }
    }
}
<?php

/** @noinspection PhpUnusedPrivateFieldInspection */
/** @noinspection PhpDocSignatureInspection */
/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Http2;

use Amp\Http\HPack;
final class Http2Parser
{
    public const PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
    private const DEFAULT_MAX_FRAME_SIZE = 1 << 14;
    private const HEADER_NAME_REGEX = '/^[\\x21-\\x40\\x5b-\\x7e]+$/';
    public const KNOWN_RESPONSE_PSEUDO_HEADERS = [":status" => true];
    public const KNOWN_REQUEST_PSEUDO_HEADERS = [":method" => true, ":authority" => true, ":path" => true, ":scheme" => true];
    // SETTINGS Flags - https://http2.github.io/http2-spec/#rfc.section.6.5
    public const ACK = 0x1;
    // HEADERS Flags - https://http2.github.io/http2-spec/#rfc.section.6.2
    public const NO_FLAG = 0x0;
    public const END_STREAM = 0x1;
    public const END_HEADERS = 0x4;
    public const PADDED = 0x8;
    public const PRIORITY_FLAG = 0x20;
    // Frame Types - https://http2.github.io/http2-spec/#rfc.section.11.2
    public const DATA = 0x0;
    public const HEADERS = 0x1;
    public const PRIORITY = 0x2;
    public const RST_STREAM = 0x3;
    public const SETTINGS = 0x4;
    public const PUSH_PROMISE = 0x5;
    public const PING = 0x6;
    public const GOAWAY = 0x7;
    public const WINDOW_UPDATE = 0x8;
    public const CONTINUATION = 0x9;
    // Settings
    public const HEADER_TABLE_SIZE = 0x1;
    // 1 << 12
    public const ENABLE_PUSH = 0x2;
    // 1
    public const MAX_CONCURRENT_STREAMS = 0x3;
    // INF
    public const INITIAL_WINDOW_SIZE = 0x4;
    // 1 << 16 - 1
    public const MAX_FRAME_SIZE = 0x5;
    // 1 << 14
    public const MAX_HEADER_LIST_SIZE = 0x6;
    // INF
    // Error codes
    public const GRACEFUL_SHUTDOWN = 0x0;
    public const PROTOCOL_ERROR = 0x1;
    public const INTERNAL_ERROR = 0x2;
    public const FLOW_CONTROL_ERROR = 0x3;
    public const SETTINGS_TIMEOUT = 0x4;
    public const STREAM_CLOSED = 0x5;
    public const FRAME_SIZE_ERROR = 0x6;
    public const REFUSED_STREAM = 0x7;
    public const CANCEL = 0x8;
    public const COMPRESSION_ERROR = 0x9;
    public const CONNECT_ERROR = 0xa;
    public const ENHANCE_YOUR_CALM = 0xb;
    public const INADEQUATE_SECURITY = 0xc;
    public const HTTP_1_1_REQUIRED = 0xd;
    /**
     *
     */
    public static function getFrameName(int $type) : string
    {
        $names = [self::DATA => 'DATA', self::HEADERS => 'HEADERS', self::PRIORITY => 'PRIORITY', self::RST_STREAM => 'RST_STREAM', self::SETTINGS => 'SETTINGS', self::PUSH_PROMISE => 'PUSH_PROMISE', self::PING => 'PING', self::GOAWAY => 'GOAWAY', self::WINDOW_UPDATE => 'WINDOW_UPDATE', self::CONTINUATION => 'CONTINUATION'];
        return $names[$type] ?? '0x' . \bin2hex(\chr($type));
    }
    /**
     *
     */
    public static function logDebugFrame(string $action, int $frameType, int $frameFlags, int $streamId, int $frameLength) : bool
    {
        $env = \getenv("AMP_DEBUG_HTTP2_FRAMES") ?: "0";
        if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG_HTTP2_FRAMES") && \AMP_DEBUG_HTTP2_FRAMES) {
            \fwrite(\STDERR, $action . ' ' . self::getFrameName($frameType) . ' <flags = ' . \bin2hex(\chr($frameFlags)) . ', stream = ' . $streamId . ', length = ' . $frameLength . '>
');
        }
        return true;
    }
    /** @var string */
    private $buffer = '';
    /** @var int */
    private $bufferOffset = 0;
    /** @var int */
    private $headerSizeLimit = self::DEFAULT_MAX_FRAME_SIZE;
    // Should be configurable?
    /** @var bool */
    private $continuationExpected = false;
    /** @var int */
    private $headerFrameType = 0;
    /** @var string */
    private $headerBuffer = '';
    /** @var int */
    private $headerStream = 0;
    /** @var HPack */
    private $hpack;
    /** @var Http2Processor */
    private $handler;
    /**
     *
     */
    public function __construct(Http2Processor $handler)
    {
        $this->hpack = new HPack();
        $this->handler = $handler;
    }
    /**
     *
     */
    public function parse(string $settings = null) : \Generator
    {
        if ($settings !== null) {
            $this->parseSettings($settings, \strlen($settings), self::NO_FLAG, 0);
        }
        $this->buffer = yield;
        while (true) {
            $frameHeader = (yield from $this->consume(9));
            ['length' => $frameLength, 'type' => $frameType, 'flags' => $frameFlags, 'id' => $streamId] = \unpack('Nlength/ctype/cflags/Nid', "\x00" . $frameHeader);
            $streamId &= 0x7fffffff;
            $frameBuffer = $frameLength === 0 ? '' : (yield from $this->consume($frameLength));
            \assert(self::logDebugFrame('recv', $frameType, $frameFlags, $streamId, $frameLength));
            try {
                // Do we want to allow increasing the maximum frame size?
                if ($frameLength > self::DEFAULT_MAX_FRAME_SIZE) {
                    throw new Http2ConnectionException("Frame size limit exceeded", self::FRAME_SIZE_ERROR);
                }
                if ($this->continuationExpected && $frameType !== self::CONTINUATION) {
                    throw new Http2ConnectionException("Expected continuation frame", self::PROTOCOL_ERROR);
                }
                switch ($frameType) {
                    case self::DATA:
                        $this->parseDataFrame($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::PUSH_PROMISE:
                        $this->parsePushPromise($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::HEADERS:
                        $this->parseHeaders($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::PRIORITY:
                        $this->parsePriorityFrame($frameBuffer, $frameLength, $streamId);
                        break;
                    case self::RST_STREAM:
                        $this->parseStreamReset($frameBuffer, $frameLength, $streamId);
                        break;
                    case self::SETTINGS:
                        $this->parseSettings($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::PING:
                        $this->parsePing($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::GOAWAY:
                        $this->parseGoAway($frameBuffer, $frameLength, $streamId);
                        break;
                    case self::WINDOW_UPDATE:
                        $this->parseWindowUpdate($frameBuffer, $frameLength, $streamId);
                        break;
                    case self::CONTINUATION:
                        $this->parseContinuation($frameBuffer, $frameFlags, $streamId);
                        break;
                    default:
                        // Ignore and discard unknown frame per spec
                        break;
                }
            } catch (Http2StreamException $exception) {
                $this->handler->handleStreamException($exception);
            } catch (Http2ConnectionException $exception) {
                $this->handler->handleConnectionException($exception);
                throw $exception;
            }
        }
    }
    /**
     *
     */
    private function consume(int $bytes) : \Generator
    {
        $bufferEnd = $this->bufferOffset + $bytes;
        while (\strlen($this->buffer) < $bufferEnd) {
            $this->buffer .= yield;
        }
        $consumed = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->bufferOffset, $bytes);
        if ($bufferEnd > 2048) {
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $bufferEnd);
            $this->bufferOffset = 0;
        } else {
            $this->bufferOffset += $bytes;
        }
        return $consumed;
    }
    /**
     *
     */
    private function parseDataFrame(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        $isPadded = $frameFlags & self::PADDED;
        $headerLength = $isPadded ? 1 : 0;
        if ($frameLength < $headerLength) {
            $this->throwInvalidFrameSizeError();
        }
        $header = $headerLength === 0 ? '' : \Phabel\Target\Php80\Polyfill::substr($frameBuffer, 0, $headerLength);
        $padding = $isPadded ? \ord($header[0]) : 0;
        if ($streamId === 0) {
            $this->throwInvalidZeroStreamIdError();
        }
        if ($frameLength - $headerLength - $padding < 0) {
            $this->throwInvalidPaddingError();
        }
        $data = \Phabel\Target\Php80\Polyfill::substr($frameBuffer, $headerLength, $frameLength - $headerLength - $padding);
        $this->handler->handleData($streamId, $data);
        if ($frameFlags & self::END_STREAM) {
            $this->handler->handleStreamEnd($streamId);
        }
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.6
     */
    private function parsePushPromise(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        $isPadded = $frameFlags & self::PADDED;
        $headerLength = $isPadded ? 5 : 4;
        if ($frameLength < $headerLength) {
            $this->throwInvalidFrameSizeError();
        }
        $header = \Phabel\Target\Php80\Polyfill::substr($frameBuffer, 0, $headerLength);
        $padding = $isPadded ? \ord($header[0]) : 0;
        $pushId = \unpack("N", $header)[1] & 0x7fffffff;
        if ($frameLength - $headerLength - $padding < 0) {
            $this->throwInvalidPaddingError();
        }
        $this->headerFrameType = self::PUSH_PROMISE;
        $this->pushHeaderBlockFragment($pushId, \Phabel\Target\Php80\Polyfill::substr($frameBuffer, $headerLength, $frameLength - $headerLength - $padding));
        if ($frameFlags & self::END_HEADERS) {
            $this->continuationExpected = false;
            [$pseudo, $headers] = $this->parseHeaderBuffer();
            $this->handler->handlePushPromise($streamId, $pushId, $pseudo, $headers);
        } else {
            $this->continuationExpected = true;
        }
        if ($frameFlags & self::END_STREAM) {
            $this->handler->handleStreamEnd($streamId);
        }
    }
    /**
     *
     */
    private function parseHeaderBuffer() : array
    {
        if ($this->headerStream === 0) {
            throw new Http2ConnectionException('Invalid stream ID 0 for header block', self::PROTOCOL_ERROR);
        }
        if ($this->headerBuffer === '') {
            throw new Http2StreamException('Invalid empty header section', $this->headerStream, self::PROTOCOL_ERROR);
        }
        $decoded = $this->hpack->decode($this->headerBuffer, $this->headerSizeLimit);
        if ($decoded === null) {
            throw new Http2ConnectionException("Compression error in headers", self::COMPRESSION_ERROR);
        }
        $headers = [];
        $pseudo = [];
        foreach ($decoded as [$name, $value]) {
            if (!\preg_match(self::HEADER_NAME_REGEX, $name)) {
                throw new Http2StreamException("Invalid header field name", $this->headerStream, self::PROTOCOL_ERROR);
            }
            if ($name[0] === ':') {
                if (!empty($headers)) {
                    throw new Http2ConnectionException("Pseudo header after other headers", self::PROTOCOL_ERROR);
                }
                if (isset($pseudo[$name])) {
                    throw new Http2ConnectionException("Repeat pseudo header", self::PROTOCOL_ERROR);
                }
                $pseudo[$name] = $value;
                continue;
            }
            $headers[$name][] = $value;
        }
        $this->headerBuffer = '';
        $this->headerStream = 0;
        return [$pseudo, $headers];
    }
    /**
     *
     */
    private function pushHeaderBlockFragment(int $streamId, string $buffer) : void
    {
        if ($this->headerStream !== 0 && $this->headerStream !== $streamId) {
            throw new Http2ConnectionException("Expected CONTINUATION frame for stream ID " . $this->headerStream, self::PROTOCOL_ERROR);
        }
        $this->headerStream = $streamId;
        $this->headerBuffer .= $buffer;
    }
    /**
     * @see https://http2.github.io/http2-spec/#HEADERS
     */
    private function parseHeaders(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        if ($streamId === 0) {
            $this->throwInvalidZeroStreamIdError();
        }
        $headerLength = 0;
        $isPadded = $frameFlags & self::PADDED;
        $isPriority = $frameFlags & self::PRIORITY_FLAG;
        if ($isPadded) {
            $headerLength++;
        }
        if ($isPriority) {
            $headerLength += 5;
        }
        if ($frameLength < $headerLength) {
            $this->throwInvalidFrameSizeError();
        }
        $header = \Phabel\Target\Php80\Polyfill::substr($frameBuffer, 0, $headerLength);
        $padding = $isPadded ? \ord($header[0]) : 0;
        if ($isPriority) {
            ['parent' => $parent, 'weight' => $weight] = \unpack("Nparent/cweight", $header, $isPadded ? 1 : 0);
            $parent &= 0x7fffffff;
            if ($parent === $streamId) {
                $this->throwInvalidRecursiveDependency($streamId);
            }
            $this->handler->handlePriority($streamId, $parent, $weight + 1);
        }
        if ($frameLength - $headerLength - $padding < 0) {
            $this->throwInvalidPaddingError();
        }
        $this->headerFrameType = self::HEADERS;
        $this->pushHeaderBlockFragment($streamId, \Phabel\Target\Php80\Polyfill::substr($frameBuffer, $headerLength, $frameLength - $headerLength - $padding));
        $ended = $frameFlags & self::END_STREAM;
        if ($frameFlags & self::END_HEADERS) {
            $this->continuationExpected = false;
            $headersTooLarge = \strlen($this->headerBuffer) > $this->headerSizeLimit;
            [$pseudo, $headers] = $this->parseHeaderBuffer();
            // This must happen after the parsing, otherwise we loose the connection state and must close the whole
            // connection, which is not what we want hereâ€¦
            if ($headersTooLarge) {
                throw new Http2StreamException("Headers exceed maximum configured size of {$this->headerSizeLimit} bytes", $streamId, self::ENHANCE_YOUR_CALM);
            }
            $this->handler->handleHeaders($streamId, $pseudo, $headers, $ended);
        } else {
            $this->continuationExpected = true;
        }
        if ($ended) {
            $this->handler->handleStreamEnd($streamId);
        }
    }
    /**
     *
     */
    private function parsePriorityFrame(string $frameBuffer, int $frameLength, int $streamId) : void
    {
        if ($frameLength !== 5) {
            $this->throwInvalidFrameSizeError();
        }
        ['parent' => $parent, 'weight' => $weight] = \unpack("Nparent/cweight", $frameBuffer);
        if ($exclusive = $parent & 0x80000000) {
            $parent &= 0x7fffffff;
        }
        if ($streamId === 0) {
            $this->throwInvalidZeroStreamIdError();
        }
        if ($parent === $streamId) {
            $this->throwInvalidRecursiveDependency($streamId);
        }
        $this->handler->handlePriority($streamId, $parent, $weight + 1);
    }
    /**
     *
     */
    private function parseStreamReset(string $frameBuffer, int $frameLength, int $streamId) : void
    {
        if ($frameLength !== 4) {
            $this->throwInvalidFrameSizeError();
        }
        if ($streamId === 0) {
            $this->throwInvalidZeroStreamIdError();
        }
        $errorCode = \unpack('N', $frameBuffer)[1];
        $this->handler->handleStreamReset($streamId, $errorCode);
    }
    /**
     *
     */
    private function parseSettings(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        if ($streamId !== 0) {
            $this->throwInvalidNonZeroStreamIdError();
        }
        if ($frameFlags & self::ACK) {
            if ($frameLength) {
                $this->throwInvalidFrameSizeError();
            }
            return;
            // Got ACK, nothing to do
        }
        if ($frameLength % 6 !== 0) {
            $this->throwInvalidFrameSizeError();
        }
        if ($frameLength > 60) {
            // Even with room for a few future options, sending that a big SETTINGS frame is just about
            // wasting our processing time. We declare this a protocol error.
            throw new Http2ConnectionException("Excessive SETTINGS frame", self::PROTOCOL_ERROR);
        }
        $settings = [];
        while ($frameLength > 0) {
            ['key' => $key, 'value' => $value] = \unpack("nkey/Nvalue", $frameBuffer);
            if ($value < 0) {
                throw new Http2ConnectionException("Invalid setting: {$value}", self::PROTOCOL_ERROR);
            }
            $settings[$key] = $value;
            $frameBuffer = \Phabel\Target\Php80\Polyfill::substr($frameBuffer, 6);
            $frameLength -= 6;
        }
        $this->handler->handleSettings($settings);
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.7
     */
    private function parsePing(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        if ($frameLength !== 8) {
            $this->throwInvalidFrameSizeError();
        }
        if ($streamId !== 0) {
            $this->throwInvalidNonZeroStreamIdError();
        }
        if ($frameFlags & self::ACK) {
            $this->handler->handlePong($frameBuffer);
        } else {
            $this->handler->handlePing($frameBuffer);
        }
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.8
     */
    private function parseGoAway(string $frameBuffer, int $frameLength, int $streamId) : void
    {
        if ($frameLength < 8) {
            $this->throwInvalidFrameSizeError();
        }
        if ($streamId !== 0) {
            $this->throwInvalidNonZeroStreamIdError();
        }
        ['last' => $lastId, 'error' => $error] = \unpack("Nlast/Nerror", $frameBuffer);
        $this->handler->handleShutdown($lastId & 0x7fffffff, $error);
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.9
     */
    private function parseWindowUpdate(string $frameBuffer, int $frameLength, int $streamId) : void
    {
        if ($frameLength !== 4) {
            $this->throwInvalidFrameSizeError();
        }
        $windowSize = \unpack('N', $frameBuffer)[1];
        if ($windowSize === 0) {
            if ($streamId) {
                throw new Http2StreamException("Invalid zero window update value", $streamId, self::PROTOCOL_ERROR);
            }
            throw new Http2ConnectionException("Invalid zero window update value", self::PROTOCOL_ERROR);
        }
        if ($streamId) {
            $this->handler->handleStreamWindowIncrement($streamId, $windowSize);
        } else {
            $this->handler->handleConnectionWindowIncrement($windowSize);
        }
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.10
     */
    private function parseContinuation(string $frameBuffer, int $frameFlags, int $streamId) : void
    {
        if ($streamId !== $this->headerStream) {
            throw new Http2ConnectionException("Invalid CONTINUATION frame stream ID", self::PROTOCOL_ERROR);
        }
        if ($this->headerBuffer === '') {
            throw new Http2ConnectionException("Unexpected CONTINUATION frame for stream ID " . $this->headerStream, self::PROTOCOL_ERROR);
        }
        $this->pushHeaderBlockFragment($streamId, $frameBuffer);
        $ended = $frameFlags & self::END_STREAM;
        if ($frameFlags & self::END_HEADERS) {
            $this->continuationExpected = false;
            $isPush = $this->headerFrameType === self::PUSH_PROMISE;
            $pushId = $this->headerStream;
            [$pseudo, $headers] = $this->parseHeaderBuffer();
            if ($isPush) {
                $this->handler->handlePushPromise($streamId, $pushId, $pseudo, $headers);
            } else {
                $this->handler->handleHeaders($streamId, $pseudo, $headers, $ended);
            }
        }
        if ($ended) {
            $this->handler->handleStreamEnd($streamId);
        }
    }
    /**
     *
     */
    private function throwInvalidFrameSizeError() : void
    {
        throw new Http2ConnectionException("Invalid frame length", self::PROTOCOL_ERROR);
    }
    /**
     *
     */
    private function throwInvalidRecursiveDependency(int $streamId) : void
    {
        throw new Http2ConnectionException("Invalid recursive dependency for stream {$streamId}", self::PROTOCOL_ERROR);
    }
    /**
     *
     */
    private function throwInvalidPaddingError() : void
    {
        throw new Http2ConnectionException("Padding greater than length", self::PROTOCOL_ERROR);
    }
    /**
     *
     */
    private function throwInvalidZeroStreamIdError() : void
    {
        throw new Http2ConnectionException("Invalid zero stream ID", self::PROTOCOL_ERROR);
    }
    /**
     *
     */
    private function throwInvalidNonZeroStreamIdError() : void
    {
        throw new Http2ConnectionException("Invalid non-zero stream ID", self::PROTOCOL_ERROR);
    }
}<?php

namespace Amp\Http\Http2;

final class Http2ConnectionException extends \Exception
{
    /**
     *
     */
    public function __construct(string $message, int $code, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Http\Http2;

interface Http2Processor
{
    /**
     *
     */
    public function handlePong(string $data) : void;
    /**
     *
     */
    public function handlePing(string $data) : void;
    /**
     *
     */
    public function handleShutdown(int $lastId, int $error) : void;
    /**
     *
     */
    public function handleStreamWindowIncrement(int $streamId, int $windowSize) : void;
    /**
     *
     */
    public function handleConnectionWindowIncrement(int $windowSize) : void;
    /**
     *
     */
    public function handleHeaders(int $streamId, array $pseudo, array $headers, bool $streamEnded) : void;
    /**
     *
     */
    public function handlePushPromise(int $streamId, int $pushId, array $pseudo, array $headers) : void;
    /**
     *
     */
    public function handlePriority(int $streamId, int $parentId, int $weight) : void;
    /**
     *
     */
    public function handleStreamReset(int $streamId, int $errorCode) : void;
    /**
     *
     */
    public function handleStreamException(Http2StreamException $exception) : void;
    /**
     *
     */
    public function handleConnectionException(Http2ConnectionException $exception) : void;
    /**
     *
     */
    public function handleData(int $streamId, string $data) : void;
    /**
     *
     */
    public function handleSettings(array $settings) : void;
    /**
     *
     */
    public function handleStreamEnd(int $streamId) : void;
}<?php

namespace Amp\Http\Http2;

final class Http2StreamException extends \Exception
{
    /** @var int */
    private $streamId;
    /**
     *
     */
    public function __construct(string $message, int $streamId, int $code, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->streamId = $streamId;
    }
    /**
     *
     */
    public function getStreamId() : int
    {
        return $this->streamId;
    }
}<?php

namespace Amp\Http;

/**
 * @link https://tools.ietf.org/html/rfc7230
 * @link https://tools.ietf.org/html/rfc2616
 * @link https://tools.ietf.org/html/rfc5234
 */
final class Rfc7230
{
    // We make use of possessive modifiers, which gives a slight performance boost
    public const HEADER_NAME_REGEX = "(^([^()<>@,;:\\\"/[\\]?={}\x01- ]++)\$)";
    public const HEADER_VALUE_REGEX = "(^[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\$)";
    public const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\\]?={}\x01- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r\n)m";
    public const HEADER_FOLD_REGEX = "(\r\n[ \t]++)";
    /**
     * Parses headers according to RFC 7230 and 2616.
     *
     * Allows empty header values, as HTTP/1.0 allows that.
     *
     * @param string $rawHeaders
     *
     * @return array Associative array mapping header names to arrays of values.
     *
     * @throws InvalidHeaderException If invalid headers have been passed.
     */
    public static function parseHeaders(string $rawHeaders) : array
    {
        $headers = [];
        foreach (self::parseRawHeaders($rawHeaders) as $header) {
            // Unfortunately, we can't avoid the \strtolower() calls due to \array_change_key_case() behavior
            // when equal headers are present with different casing, e.g. 'set-cookie' and 'Set-Cookie'.
            // Accessing headers directly instead of using foreach (... as list(...)) is slightly faster.
            $headers[\strtolower($header[0])][] = $header[1];
        }
        return $headers;
    }
    /**
     * Parses headers according to RFC 7230 and 2616.
     *
     * Allows empty header values, as HTTP/1.0 allows that.
     *
     * @param string $rawHeaders
     *
     * @return array List of [field, value] header pairs.
     *
     * @throws InvalidHeaderException If invalid headers have been passed.
     */
    public static function parseRawHeaders(string $rawHeaders) : array
    {
        // Ensure that the last line also ends with a newline, this is important.
        \assert(\Phabel\Target\Php80\Polyfill::substr($rawHeaders, -2) === "\r\n", "Argument 1 must end with CRLF: " . \bin2hex($rawHeaders));
        /** @var array[] $matches */
        $count = \preg_match_all(self::HEADER_REGEX, $rawHeaders, $matches, \PREG_SET_ORDER);
        // If these aren't the same, then one line didn't match and there's an invalid header.
        if ($count !== \Phabel\Target\Php80\Polyfill::substr_count($rawHeaders, "\n")) {
            // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4
            if (\preg_match(self::HEADER_FOLD_REGEX, $rawHeaders)) {
                throw new InvalidHeaderException("Invalid header syntax: Obsolete line folding");
            }
            throw new InvalidHeaderException("Invalid header syntax");
        }
        $headers = [];
        foreach ($matches as $match) {
            // We avoid a call to \trim() here due to the regex.
            // Accessing matches directly instead of using foreach (... as list(...)) is slightly faster.
            $headers[] = [$match[1], $match[2]];
        }
        return $headers;
    }
    /**
    * Format headers in to their on-the-wire format.
    *
    * Headers are always validated syntactically. This protects against response splitting and header injection
    attacks.
    *
    * @param array $headers Headers in a format as returned by {@see parseHeaders()}.
    *
    * @return string Formatted headers.
    *
    * @throws InvalidHeaderException If header names or values are invalid.
    */
    public static function formatHeaders(array $headers) : string
    {
        $headerList = [];
        foreach ($headers as $name => $values) {
            foreach ($values as $value) {
                // PHP casts integer-like keys to integers
                $headerList[] = [(string) $name, $value];
            }
        }
        return self::formatRawHeaders($headerList);
    }
    /**
    * Format headers in to their on-the-wire HTTP/1 format.
    *
    * Headers are always validated syntactically. This protects against response splitting and header injection
    attacks.
    *
    * @param array $headers List of headers in [field, value] format as returned by {@see Message::getRawHeaders()}.
    *
    * @return string Formatted headers.
    *
    * @throws InvalidHeaderException If header names or values are invalid.
    */
    public static function formatRawHeaders(array $headers) : string
    {
        $buffer = "";
        $lines = 0;
        foreach ($headers as [$name, $value]) {
            // Ignore any HTTP/2 pseudo headers
            if (($name[0] ?? '') === ':') {
                continue;
            }
            $buffer .= "{$name}: {$value}\r\n";
            $lines++;
        }
        $count = \preg_match_all(self::HEADER_REGEX, $buffer);
        if ($lines !== $count || $lines !== \Phabel\Target\Php80\Polyfill::substr_count($buffer, "\n")) {
            throw new InvalidHeaderException("Invalid headers");
        }
        return $buffer;
    }
}<?php

namespace Amp\Http;

/**
 * Base class for HTTP request and response messages.
 */
abstract class Message
{
    /** @var string[][] */
    private $headers = [];
    /** @var string[][] */
    private $headerCase = [];
    /**
    * Returns the headers as a string-indexed array of arrays of strings or an empty array if no headers
    have been set.
    *
    * @return string[][]
    */
    public function getHeaders() : array
    {
        return $this->headers;
    }
    /**
     * Returns the headers as list of [field, name] pairs in the original casing provided by the application or server.
     *
     * @return array
     */
    public final function getRawHeaders() : array
    {
        $headers = [];
        foreach ($this->headers as $lcName => $values) {
            $size = \count($values);
            for ($i = 0; $i < $size; $i++) {
                $headers[] = [$this->headerCase[$lcName][$i], $values[$i]];
            }
        }
        return $headers;
    }
    /**
     * Returns the array of values for the given header or an empty array if the header does not exist.
     *
     * @param string $name
     *
     * @return string[]
     */
    public function getHeaderArray(string $name) : array
    {
        return $this->headers[\strtolower($name)] ?? [];
    }
    /**
    * Returns the value of the given header. If multiple headers are present for the named header, only the first
    header value will be returned. Use getHeaderArray() to return an array of all values for the particular header.
    Returns null if the header does not exist.
    *
    * @param string $name
    *
    * @return (string | null)
    */
    public function getHeader(string $name)
    {
        return $this->headers[\strtolower($name)][0] ?? null;
    }
    /**
     * Sets the headers from the given array.
     *
     * @param (string[] | string[][]) $headers
     */
    protected function setHeaders(array $headers)
    {
        // Ensure this is an atomic operation, either all headers are set or none.
        $before = $this->headers;
        $beforeCase = $this->headerCase;
        try {
            foreach ($headers as $name => $value) {
                $this->setHeader($name, $value);
            }
        } catch (\Throwable $e) {
            $this->headers = $before;
            $this->headerCase = $beforeCase;
            throw $e;
        }
    }
    /**
     * Sets the named header to the given value.
     *
     * @param string $name
     * @param (string | string[]) $value
     *
     * @throws \Error If the header name or value is invalid.
     */
    protected function setHeader(string $name, $value)
    {
        \assert($this->isNameValid($name), "Invalid header name");
        if (\is_array($value)) {
            if (!$value) {
                $this->removeHeader($name);
                return;
            }
            $value = \array_values(\array_map("strval", $value));
        } else {
            $value = [(string) $value];
        }
        \assert($this->isValueValid($value), "Invalid header value");
        $lcName = \strtolower($name);
        $this->headers[$lcName] = $value;
        $this->headerCase[$lcName] = [];
        foreach ($value as $_) {
            $this->headerCase[$lcName][] = $name;
        }
    }
    /**
     * Adds the value to the named header, or creates the header with the given value if it did not exist.
     *
     * @param string $name
     * @param (string | string[]) $value
     *
     * @throws \Error If the header name or value is invalid.
     */
    protected function addHeader(string $name, $value)
    {
        \assert($this->isNameValid($name), "Invalid header name");
        if (\is_array($value)) {
            if (!$value) {
                return;
            }
            $value = \array_values(\array_map("strval", $value));
        } else {
            $value = [(string) $value];
        }
        \assert($this->isValueValid($value), "Invalid header value");
        $lcName = \strtolower($name);
        if (isset($this->headers[$lcName])) {
            $this->headers[$lcName] = \array_merge($this->headers[$lcName], $value);
            foreach ($value as $_) {
                $this->headerCase[$lcName][] = $name;
            }
        } else {
            $this->headers[$lcName] = $value;
            foreach ($value as $_) {
                $this->headerCase[$lcName][] = $name;
            }
        }
    }
    /**
     * Removes the given header if it exists.
     *
     * @param string $name
     */
    protected function removeHeader(string $name)
    {
        $lcName = \strtolower($name);
        unset($this->headers[$lcName], $this->headerCase[$lcName]);
    }
    /**
     * Checks if given header exists.
     *
     * @param string $name
     *
     * @return bool
     */
    public function hasHeader(string $name) : bool
    {
        return isset($this->headers[\strtolower($name)]);
    }
    /**
     * @param string $name
     *
     * @return bool
     */
    private function isNameValid(string $name) : bool
    {
        return (bool) \preg_match('/^[A-Za-z0-9`~!#$%^&_|\'\\-:]+$/', $name);
    }
    /**
    * Determines if the given value is a valid header value.
    *
    * @param string[] $values
    *
    * @return bool
    *
    * @throws \Error If the given value cannot be converted to a string and is not an array of values that can be
    converted to strings.
    */
    private function isValueValid(array $values) : bool
    {
        foreach ($values as $value) {
            if (\preg_match("/[^\t\r\n -~\x80-\xfe]|\r\n/", $value)) {
                return false;
            }
        }
        return true;
    }
}<?php

namespace Amp\Http;

/**
 * @link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
 */
final class Status
{
    const CONTINUE = 100;
    const SWITCHING_PROTOCOLS = 101;
    const PROCESSING = 102;
    const EARLY_HINTS = 103;
    const OK = 200;
    const CREATED = 201;
    const ACCEPTED = 202;
    const NON_AUTHORITATIVE_INFORMATION = 203;
    const NO_CONTENT = 204;
    const RESET_CONTENT = 205;
    const PARTIAL_CONTENT = 206;
    const MULTI_STATUS = 207;
    const ALREADY_REPORTED = 208;
    const IM_USED = 226;
    const MULTIPLE_CHOICES = 300;
    const MOVED_PERMANENTLY = 301;
    const FOUND = 302;
    const SEE_OTHER = 303;
    const NOT_MODIFIED = 304;
    const USE_PROXY = 305;
    const TEMPORARY_REDIRECT = 307;
    const PERMANENT_REDIRECT = 308;
    const BAD_REQUEST = 400;
    const UNAUTHORIZED = 401;
    const PAYMENT_REQUIRED = 402;
    const FORBIDDEN = 403;
    const NOT_FOUND = 404;
    const METHOD_NOT_ALLOWED = 405;
    const NOT_ACCEPTABLE = 406;
    const PROXY_AUTHENTICATION_REQUIRED = 407;
    const REQUEST_TIMEOUT = 408;
    const CONFLICT = 409;
    const GONE = 410;
    const LENGTH_REQUIRED = 411;
    const PRECONDITION_FAILED = 412;
    const PAYLOAD_TOO_LARGE = 413;
    const URI_TOO_LONG = 414;
    const UNSUPPORTED_MEDIA_TYPE = 415;
    const RANGE_NOT_SATISFIABLE = 416;
    const EXPECTATION_FAILED = 417;
    const MISDIRECTED_REQUEST = 421;
    const UNPROCESSABLE_ENTITY = 422;
    const LOCKED = 423;
    const FAILED_DEPENDENCY = 424;
    const UPGRADE_REQUIRED = 426;
    const PRECONDITION_REQUIRED = 428;
    const TOO_MANY_REQUESTS = 429;
    const REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
    const UNAVAILABLE_FOR_LEGAL_REASONS = 451;
    const INTERNAL_SERVER_ERROR = 500;
    const NOT_IMPLEMENTED = 501;
    const BAD_GATEWAY = 502;
    const SERVICE_UNAVAILABLE = 503;
    const GATEWAY_TIMEOUT = 504;
    const HTTP_VERSION_NOT_SUPPORTED = 505;
    const VARIANT_ALSO_NEGOTIATES = 506;
    const INSUFFICIENT_STORAGE = 507;
    const LOOP_DETECTED = 508;
    const NOT_EXTENDED = 510;
    const NETWORK_AUTHENTICATION_REQUIRED = 511;
    // @codeCoverageIgnoreStart
    /**
     *
     */
    private function __construct()
    {
        // forbid instances
    }
    // @codeCoverageIgnoreEnd
    /**
     *
     */
    public static function getReason(int $code) : string
    {
        return [100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 103 => 'Early Hints', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 208 => 'Already Reported', 226 => 'IM Used', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Payload Too Large', 414 => 'URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Range Not Satisfiable', 417 => 'Expectation Failed', 421 => 'Misdirected Request', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required'][$code] ?? '';
    }
}<?php

namespace Amp\Http\Cookie;

final class InvalidCookieException extends \Exception
{
    /**
     *
     */
    public function __construct(string $message)
    {
        parent::__construct($message);
    }
}<?php

namespace Amp\Http\Cookie;

/**
 * A cookie as sent in a response's 'set-cookie' header, so with attributes.
 *
 * This class does not deal with encoding of arbitrary names and values. If you want to use arbitrary values, please use
 * an encoding mechanism like Base64 or URL encoding.
 *
 * @link https://tools.ietf.org/html/rfc6265#section-5.2
 */
final class ResponseCookie
{
    private static $dateFormats = ['D, d M Y H:i:s T', 'D, d-M-y H:i:s T', 'D, d-M-Y H:i:s T', 'D, d-m-y H:i:s T', 'D, d-m-Y H:i:s T', 'D M j G:i:s Y', 'D M d H:i:s Y T'];
    /**
     * Parses a cookie from a 'set-cookie' header.
     *
     * @param string $string Valid 'set-cookie' header line.
     *
     * @return (self | null) Returns a `ResponseCookie` instance on success and `null` on failure.
     */
    public static function fromHeader(string $string) : ?self
    {
        $parts = \array_map("trim", \explode(";", $string));
        $nameValue = \explode("=", \array_shift($parts), 2);
        if (\count($nameValue) !== 2) {
            return null;
        }
        list($name, $value) = $nameValue;
        $name = \trim($name);
        $value = \trim($value, " \t\n\r\x00\v\"");
        if ($name === "") {
            return null;
        }
        // httpOnly must default to false for parsing
        $meta = CookieAttributes::empty();
        $unknownAttributes = [];
        foreach ($parts as $part) {
            $pieces = \array_map('trim', \explode('=', $part, 2));
            $key = \strtolower($pieces[0]);
            if (1 === \count($pieces)) {
                switch ($key) {
                    case 'secure':
                        $meta = $meta->withSecure();
                        break;
                    case 'httponly':
                        $meta = $meta->withHttpOnly();
                        break;
                    default:
                        $unknownAttributes[] = $part;
                        break;
                }
            } else {
                switch ($key) {
                    case 'expires':
                        $time = self::parseDate($pieces[1]);
                        if ($time === null) {
                            break;
                            // break is correct, see https://tools.ietf.org/html/rfc6265#section-5.2.1
                        }
                        $meta = $meta->withExpiry($time);
                        break;
                    case 'max-age':
                        $maxAge = \trim($pieces[1]);
                        // This also allows +1.42, but avoids a more complicated manual check
                        if (!\is_numeric($maxAge)) {
                            break;
                            // break is correct, see https://tools.ietf.org/html/rfc6265#section-5.2.2
                        }
                        $meta = $meta->withMaxAge($maxAge);
                        break;
                    case 'path':
                        $meta = $meta->withPath($pieces[1]);
                        break;
                    case 'domain':
                        $meta = $meta->withDomain($pieces[1]);
                        break;
                    case 'samesite':
                        $normalizedValue = \ucfirst(\strtolower($pieces[1]));
                        if (!\in_array($normalizedValue, [CookieAttributes::SAMESITE_NONE, CookieAttributes::SAMESITE_LAX, CookieAttributes::SAMESITE_STRICT], true)) {
                            $unknownAttributes[] = $part;
                        } else {
                            $meta = $meta->withSameSite($normalizedValue);
                        }
                        break;
                    default:
                        $unknownAttributes[] = $part;
                        break;
                }
            }
        }
        try {
            $cookie = new self($name, $value, $meta);
            $cookie->unknownAttributes = $unknownAttributes;
            return $cookie;
        } catch (InvalidCookieException $e) {
            return null;
        }
    }
    /**
     * @param string $date Formatted cookie date
     *
     * @return (\DateTimeImmutable | null) Parsed date.
     */
    private static function parseDate(string $date) : ?\DateTimeImmutable
    {
        foreach (self::$dateFormats as $dateFormat) {
            if ($parsedDate = \DateTimeImmutable::createFromFormat($dateFormat, $date, new \DateTimeZone('GMT'))) {
                return $parsedDate;
            }
        }
        return null;
    }
    /** @var string[] */
    private $unknownAttributes = [];
    /** @var string */
    private $name;
    /** @var string */
    private $value;
    /** @var CookieAttributes */
    private $attributes;
    /**
     * @param string $name Name of the cookie.
     * @param string $value Value of the cookie.
     * @param CookieAttributes $attributes Attributes of the cookie.
     *
     * @throws InvalidCookieException If name or value is invalid.
     */
    public function __construct(string $name, string $value = '', CookieAttributes $attributes = null)
    {
        if (!\preg_match('(^[^()<>@,;:\\\\"/[\\]?={}\\x01-\\x20\\x7F]++$)', $name)) {
            throw new InvalidCookieException("Invalid cookie name: '{$name}'");
        }
        if (!\preg_match('(^[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*+$)', $value)) {
            throw new InvalidCookieException("Invalid cookie value: '{$value}'");
        }
        $this->name = $name;
        $this->value = $value;
        $this->attributes = $attributes ?? CookieAttributes::default();
    }
    /**
     * @return string Name of the cookie.
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     *
     */
    public function withName(string $name) : self
    {
        if (!\preg_match('(^[^()<>@,;:\\\\"/[\\]?={}\\x01-\\x20\\x7F]++$)', $name)) {
            throw new InvalidCookieException("Invalid cookie name: '{$name}'");
        }
        $clone = clone $this;
        $clone->name = $name;
        return $clone;
    }
    /**
     * @return string Value of the cookie.
     */
    public function getValue() : string
    {
        return $this->value;
    }
    /**
     *
     */
    public function withValue(string $value) : self
    {
        if (!\preg_match('(^[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*+$)', $value)) {
            throw new InvalidCookieException("Invalid cookie value: '{$value}'");
        }
        $clone = clone $this;
        $clone->value = $value;
        return $clone;
    }
    /**
     * @return (\DateTimeImmutable | null) Expiry if set, otherwise `null`.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.1
     */
    public function getExpiry() : ?\DateTimeImmutable
    {
        return $this->attributes->getExpiry();
    }
    /**
     *
     */
    public function withExpiry(\DateTimeInterface $expiry) : self
    {
        return $this->withAttributes($this->attributes->withExpiry($expiry));
    }
    /**
     *
     */
    public function withoutExpiry() : self
    {
        return $this->withAttributes($this->attributes->withoutExpiry());
    }
    /**
     * @return (int | null) Max-Age if set, otherwise `null`.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function getMaxAge() : ?int
    {
        return $this->attributes->getMaxAge();
    }
    /**
     *
     */
    public function withMaxAge(int $maxAge) : self
    {
        return $this->withAttributes($this->attributes->withMaxAge($maxAge));
    }
    /**
     *
     */
    public function withoutMaxAge() : self
    {
        return $this->withAttributes($this->attributes->withoutMaxAge());
    }
    /**
     * @return string Cookie path.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.4
     */
    public function getPath() : string
    {
        return $this->attributes->getPath();
    }
    /**
     *
     */
    public function withPath(string $path) : self
    {
        return $this->withAttributes($this->attributes->withPath($path));
    }
    /**
     * @return string Cookie domain.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.3
     */
    public function getDomain() : string
    {
        return $this->attributes->getDomain();
    }
    /**
     *
     */
    public function withDomain(string $domain) : self
    {
        return $this->withAttributes($this->attributes->withDomain($domain));
    }
    /**
     * @return bool Whether the secure flag is enabled or not.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.5
     */
    public function isSecure() : bool
    {
        return $this->attributes->isSecure();
    }
    /**
     *
     */
    public function withSecure() : self
    {
        return $this->withAttributes($this->attributes->withSecure());
    }
    /**
     *
     */
    public function withoutSecure() : self
    {
        return $this->withAttributes($this->attributes->withoutSecure());
    }
    /**
     * @return bool Whether the httpOnly flag is enabled or not.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.6
     */
    public function isHttpOnly() : bool
    {
        return $this->attributes->isHttpOnly();
    }
    /**
     *
     */
    public function withHttpOnly() : self
    {
        return $this->withAttributes($this->attributes->withHttpOnly());
    }
    /**
     *
     */
    public function withoutHttpOnly() : self
    {
        return $this->withAttributes($this->attributes->withoutHttpOnly());
    }
    /**
     *
     */
    public function withSameSite(string $sameSite) : self
    {
        return $this->withAttributes($this->attributes->withSameSite($sameSite));
    }
    /**
     *
     */
    public function withoutSameSite() : self
    {
        return $this->withAttributes($this->attributes->withoutSameSite());
    }
    /**
     *
     */
    public function getSameSite() : ?string
    {
        return $this->attributes->getSameSite();
    }
    /**
     * @return CookieAttributes All cookie attributes.
     */
    public function getAttributes() : CookieAttributes
    {
        return $this->attributes;
    }
    /**
     *
     */
    public function withAttributes(CookieAttributes $attributes) : self
    {
        $clone = clone $this;
        $clone->attributes = $attributes;
        return $clone;
    }
    /**
     * @return string Representation of the cookie as in a 'set-cookie' header.
     */
    public function __toString() : string
    {
        $line = $this->name . '=' . $this->value;
        $line .= $this->attributes;
        $unknownAttributes = \implode('; ', $this->unknownAttributes);
        if ($unknownAttributes !== '') {
            $line .= '; ' . $unknownAttributes;
        }
        return $line;
    }
}<?php

namespace Amp\Http\Cookie;

/**
 * A cookie as sent in a request's 'cookie' header, so without any attributes.
 *
 * This class does not deal with encoding of arbitrary names and values. If you want to use arbitrary values, please use
 * an encoding mechanism like Base64 or URL encoding.
 *
 * @link https://tools.ietf.org/html/rfc6265#section-5.4
 */
final class RequestCookie
{
    /** @var string */
    private $name;
    /** @var string */
    private $value;
    /**
     * Parses the cookies from a 'cookie' header.
     *
     * Note: Parsing is aborted if there's an invalid value and no cookies are returned.
     *
     * @param string $string Valid 'cookie' header line.
     *
     * @return RequestCookie[]
     */
    public static function fromHeader(string $string) : array
    {
        $cookies = \explode(";", $string);
        $result = [];
        try {
            foreach ($cookies as $cookie) {
                $parts = \explode('=', $cookie, 2);
                if (2 !== \count($parts)) {
                    return [];
                }
                list($name, $value) = $parts;
                // We can safely trim quotes, as they're not allowed within cookie values
                $result[] = new self(\trim($name), \trim($value, " \t\""));
            }
        } catch (InvalidCookieException $e) {
            return [];
        }
        return $result;
    }
    /**
     * @param string $name Cookie name in its decoded form.
     * @param string $value Cookie value in its decoded form.
     *
     * @throws InvalidCookieException If name or value is invalid.
     */
    public function __construct(string $name, string $value = '')
    {
        if (!\preg_match('(^[^()<>@,;:\\\\"/[\\]?={}\\x01-\\x20\\x7F]*+$)', $name)) {
            throw new InvalidCookieException("Invalid cookie name: '{$name}'");
        }
        if (!\preg_match('(^[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*+$)', $value)) {
            throw new InvalidCookieException("Invalid cookie value: '{$value}'");
        }
        $this->name = $name;
        $this->value = $value;
    }
    /**
     * @return string Name of the cookie.
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     *
     */
    public function withName(string $name) : self
    {
        if (!\preg_match('(^[^()<>@,;:\\\\"/[\\]?={}\\x01-\\x20\\x7F]++$)', $name)) {
            throw new InvalidCookieException("Invalid cookie name: '{$name}'");
        }
        $clone = clone $this;
        $clone->name = $name;
        return $clone;
    }
    /**
     * @return string Value of the cookie.
     */
    public function getValue() : string
    {
        return $this->value;
    }
    /**
     *
     */
    public function withValue(string $value) : self
    {
        if (!\preg_match('(^[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*+$)', $value)) {
            throw new InvalidCookieException("Invalid cookie value: '{$value}'");
        }
        $clone = clone $this;
        $clone->value = $value;
        return $clone;
    }
    /**
     * @return string Representation of the cookie as in a 'cookie' header.
     */
    public function __toString() : string
    {
        return $this->name . '=' . $this->value;
    }
}<?php

namespace Amp\Http\Cookie;

/**
 * Cookie attributes as defined in https://tools.ietf.org/html/rfc6265.
 *
 * @link https://tools.ietf.org/html/rfc6265
 */
final class CookieAttributes
{
    public const SAMESITE_NONE = 'None';
    public const SAMESITE_LAX = 'Lax';
    public const SAMESITE_STRICT = 'Strict';
    /**
     * @return CookieAttributes No cookie attributes.
     *
     * @see self::default()
     */
    public static function empty() : self
    {
        $new = new self();
        $new->httpOnly = false;
        return $new;
    }
    /**
     * @return CookieAttributes Default cookie attributes, which means httpOnly is enabled by default.
     *
     * @see self::empty()
     */
    public static function default() : self
    {
        return new self();
    }
    /** @var string */
    private $path = '';
    /** @var string */
    private $domain = '';
    /** @var int|null */
    private $maxAge;
    /** @var \DateTimeImmutable */
    private $expiry;
    /** @var bool */
    private $secure = false;
    /** @var bool */
    private $httpOnly = true;
    /** @var string|null */
    private $sameSite;
    /**
     *
     */
    private function __construct()
    {
        // only allow creation via named constructors
    }
    /**
    * @param string $path Cookie path.
    *
    * @return self Cloned instance with the specified operation applied. Cloned instance with the specified operation
    applied.
    *
    * @link https://tools.ietf.org/html/rfc6265#section-5.2.4
    */
    public function withPath(string $path) : self
    {
        $new = clone $this;
        $new->path = $path;
        return $new;
    }
    /**
     * @param string $domain Cookie domain.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.3
     */
    public function withDomain(string $domain) : self
    {
        $new = clone $this;
        $new->domain = $domain;
        return $new;
    }
    /**
     * @param string $sameSite Cookie SameSite attribute value.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-5.3.7
     */
    public function withSameSite(string $sameSite) : self
    {
        $normalizedValue = \ucfirst(\strtolower($sameSite));
        if (!\in_array($normalizedValue, [self::SAMESITE_NONE, self::SAMESITE_LAX, self::SAMESITE_STRICT], true)) {
            throw new \Error("Invalid SameSite attribute: " . $sameSite);
        }
        $new = clone $this;
        $new->sameSite = $normalizedValue;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-5.3.7
     */
    public function withoutSameSite() : self
    {
        $new = clone $this;
        $new->sameSite = null;
        return $new;
    }
    /**
     * Applies the given maximum age to the cookie.
     *
     * @param int $maxAge Cookie maximum age.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withoutMaxAge()
     * @see self::withExpiry()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function withMaxAge(int $maxAge) : self
    {
        $new = clone $this;
        $new->maxAge = $maxAge;
        return $new;
    }
    /**
     * Removes any max-age information.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withMaxAge()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function withoutMaxAge() : self
    {
        $new = clone $this;
        $new->maxAge = null;
        return $new;
    }
    /**
     * Applies the given expiry to the cookie.
     *
     * @param \DateTimeInterface $date
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withMaxAge()
     * @see self::withoutExpiry()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.1
     */
    public function withExpiry(\DateTimeInterface $date) : self
    {
        $new = clone $this;
        if ($date instanceof \DateTimeImmutable) {
            $new->expiry = $date;
        } elseif ($date instanceof \DateTime) {
            $new->expiry = \DateTimeImmutable::createFromMutable($date);
        } else {
            $new->expiry = new \DateTimeImmutable("@" . $date->getTimestamp());
        }
        return $new;
    }
    /**
     * Removes any expiry information.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withExpiry()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.1
     */
    public function withoutExpiry() : self
    {
        $new = clone $this;
        $new->expiry = null;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withoutSecure()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.5
     */
    public function withSecure() : self
    {
        $new = clone $this;
        $new->secure = true;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withSecure()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.5
     */
    public function withoutSecure() : self
    {
        $new = clone $this;
        $new->secure = false;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withoutHttpOnly()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.6
     */
    public function withHttpOnly() : self
    {
        $new = clone $this;
        $new->httpOnly = true;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withHttpOnly()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.6
     */
    public function withoutHttpOnly() : self
    {
        $new = clone $this;
        $new->httpOnly = false;
        return $new;
    }
    /**
     * @return string Cookie path.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.4
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     * @return string Cookie domain.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.3
     */
    public function getDomain() : string
    {
        return $this->domain;
    }
    /**
     * @return string Cookie domain.
     *
     * @link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-5.3.7
     */
    public function getSameSite() : ?string
    {
        return $this->sameSite;
    }
    /**
     * @return (int | null) Cookie maximum age in seconds or `null` if no value is set.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function getMaxAge() : ?int
    {
        return $this->maxAge;
    }
    /**
     * @return (\DateTimeImmutable | null) Cookie expiry or `null` if no value is set.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function getExpiry() : ?\DateTimeImmutable
    {
        return $this->expiry;
    }
    /**
     * @return bool Whether the secure flag is enabled or not.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.5
     */
    public function isSecure() : bool
    {
        return $this->secure;
    }
    /**
     * @return bool Whether the httpOnly flag is enabled or not.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.6
     */
    public function isHttpOnly() : bool
    {
        return $this->httpOnly;
    }
    /**
     * @return string Representation of the cookie attributes appended to key=value in a 'set-cookie' header.
     */
    public function __toString() : string
    {
        $string = '';
        if ($this->expiry) {
            $string .= '; Expires=' . \Phabel\Target\Php80\Polyfill::gmdate('D, j M Y G:i:s T', $this->expiry->getTimestamp());
        }
        if ($this->maxAge) {
            $string .= '; Max-Age=' . $this->maxAge;
        }
        if ('' !== $this->path) {
            $string .= '; Path=' . $this->path;
        }
        if ('' !== $this->domain) {
            $string .= '; Domain=' . $this->domain;
        }
        if ($this->secure) {
            $string .= '; Secure';
        }
        if ($this->httpOnly) {
            $string .= '; HttpOnly';
        }
        if ($this->sameSite !== null) {
            $string .= '; SameSite=' . $this->sameSite;
        }
        return $string;
    }
}<?php

namespace Amp\Http;

/**
 * @param Message $message
 * @param string $headerName
 *
 * @return (array | null)
 *
 * @see https://tools.ietf.org/html/rfc7230#section-3.2.6
 */
function parseFieldValueComponents(Message $message, string $headerName) : ?array
{
    $header = \implode(', ', $message->getHeaderArray($headerName));
    if ($header === '') {
        return [];
    }
    \preg_match_all('(([^"=,]+)(?:=(?:"((?:[^\\\\"]|\\\\.)*)"|([^,"]*)))?,?\\s*)', $header, $matches, \PREG_SET_ORDER);
    $totalMatchedLength = 0;
    $pairs = [];
    foreach ($matches as $match) {
        $totalMatchedLength += \strlen($match[0]);
        $key = \trim($match[1]);
        $value = ($match[2] ?? '') . \trim($match[3] ?? '');
        if (($match[2] ?? '') !== '') {
            // decode escaped characters
            $value = \preg_replace('(\\\\(.))', '\\1', $value);
        }
        $pairs[] = [$key, $value];
    }
    if ($totalMatchedLength !== \strlen($header)) {
        return null;
        // parse error
    }
    return $pairs;
}
/**
 * @param array $pairs Output of {@code parseFieldValueComponents}. Keys are handled case-insensitively.
 *
 * @return (array | null) Map of keys to values or {@code null} if incompatible duplicates are found.
 */
function createFieldValueComponentMap(?array $pairs) : ?array
{
    if ($pairs === null) {
        return null;
    }
    $map = [];
    foreach ($pairs as $pair) {
        \assert(\count($pair) === 2);
        \assert(\is_string($pair[0]));
        \assert(\is_string($pair[1]));
    }
    foreach ($pairs as [$key, $value]) {
        $key = \strtolower($key);
        if (isset($map[$key]) && $map[$key] !== $value) {
            return null;
            // incompatible duplicates
        }
        $map[$key] = $value;
    }
    return $map;
}
/**
 * Format timestamp in seconds as an HTTP date header.
 *
 * @param (int | null) $timestamp Timestamp to format, current time if `null`.
 *
 * @return string Formatted date header value.
 */
function formatDateHeader(?int $timestamp = null) : string
{
    static $cachedTimestamp, $cachedFormattedDate;
    $timestamp = $timestamp ?? \time();
    if ($cachedTimestamp === $timestamp) {
        return $cachedFormattedDate;
    }
    return $cachedFormattedDate = \Phabel\Target\Php80\Polyfill::gmdate("D, d M Y H:i:s", $cachedTimestamp = $timestamp) . " GMT";
}<?php

namespace Amp\Http;

final class InvalidHeaderException extends \Exception
{
    /**
     * Thrown on header injection attempts.
     *
     * @param string $reason Reason that can be used as HTTP response reason.
     */
    public function __construct(string $reason)
    {
        parent::__construct($reason);
    }
}{
    "name": "amphp/http",
    "description": "Basic HTTP primitives which can be shared by servers and clients.",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "Amp\\Http\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "require": {
        "php": ">=7.1",
        "amphp/hpack": "^3"
    },
    "require-dev": {
        "phpunit/phpunit": "^7 || ^6.5",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "config": {
        "platform": {
            "php": "7.1.0"
        }
    },
    "scripts": {
        "test": "php vendor/bin/phpunit",
        "code-style": "php vendor/bin/php-cs-fixer fix"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    }
}
{
    "symbol-whitelist": [
        "null",
        "true",
        "false",
        "static",
        "self",
        "parent",
        "array",
        "string",
        "int",
        "float",
        "bool",
        "iterable",
        "callable",
        "void",
        "object",
        "Amp\\File\\Driver",
        "Amp\\File\\exists",
        "Amp\\File\\get",
        "Amp\\File\\isdir",
        "Amp\\File\\mkdir",
        "Amp\\File\\open",
        "Amp\\File\\put",
        "Amp\\File\\size"
    ],
    "php-core-extensions": [
        "Core",
        "date",
        "pcre",
        "Phar",
        "Reflection",
        "SPL",
        "standard"
    ]
}
<?php

namespace Amp\Http\Client\Cookie;

use Amp\Http\Client\HttpException;
use Amp\Http\Cookie\InvalidCookieException;
use Amp\Http\Cookie\RequestCookie;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use Amp\Success;
use Psr\Http\Message\UriInterface as PsrUri;
final class InMemoryCookieJar implements CookieJar
{
    /** @var ResponseCookie[][][] */
    private $cookies = [];
    /**
     *
     */
    public function store(ResponseCookie ...$cookies) : Promise
    {
        foreach ($cookies as $cookie) {
            if ($cookie->getDomain() === '') {
                throw new HttpException("Can't store cookie without domain information.");
            }
            $this->cookies[$cookie->getDomain()][$cookie->getPath() ?: '/'][$cookie->getName()] = $cookie;
        }
        return new Success();
    }
    /**
     *
     */
    public function get(PsrUri $uri) : Promise
    {
        $this->clearExpiredCookies();
        $path = $uri->getPath() ?: '/';
        $domain = $uri->getHost();
        $isRequestSecure = $uri->getScheme() === 'https';
        $matches = [];
        foreach ($this->cookies as $cookieDomain => $domainCookies) {
            if (!$this->matchesDomain($domain, $cookieDomain)) {
                continue;
            }
            foreach ($domainCookies as $cookiePath => $pathCookies) {
                if (!$this->matchesPath($path, $cookiePath)) {
                    continue;
                }
                foreach ($pathCookies as $cookieName => $cookie) {
                    if ($isRequestSecure || !$cookie->isSecure()) {
                        try {
                            $matches[] = new RequestCookie($cookie->getName(), $cookie->getValue());
                        } catch (InvalidCookieException $e) {
                            // ignore cookie
                        }
                    }
                }
            }
        }
        return new Success($matches);
    }
    /**
     *
     */
    public function getAll() : array
    {
        $cookies = [];
        foreach ($this->cookies as $cookiesPerDomain) {
            foreach ($cookiesPerDomain as $cookiesPerPath) {
                foreach ($cookiesPerPath as $cookie) {
                    $cookies[] = $cookie;
                }
            }
        }
        return $cookies;
    }
    /**
     *
     */
    public function clear() : void
    {
        $this->cookies = [];
    }
    /**
     *
     */
    private function clearExpiredCookies() : void
    {
        foreach ($this->cookies as $domain => $domainCookies) {
            foreach ($domainCookies as $path => $pathCookies) {
                foreach ($pathCookies as $name => $cookie) {
                    /** @var ResponseCookie $cookie */
                    if ($cookie->getExpiry() && $cookie->getExpiry()->getTimestamp() < \time()) {
                        unset($this->cookies[$domain][$path][$name]);
                    }
                }
            }
        }
    }
    /**
     * @param string $requestDomain
     * @param string $cookieDomain
     *
     * @return bool
     *
     * @link http://tools.ietf.org/html/rfc6265#section-5.1.3
     */
    private function matchesDomain(string $requestDomain, string $cookieDomain) : bool
    {
        if ($requestDomain === \ltrim($cookieDomain, '.')) {
            return true;
        }
        /** @noinspection SubStrUsedAsStrPosInspection */
        $isWildcardCookieDomain = $cookieDomain[0] === '.';
        if (!$isWildcardCookieDomain) {
            return false;
        }
        if (\filter_var($requestDomain, FILTER_VALIDATE_IP)) {
            return false;
        }
        if (\Phabel\Target\Php80\Polyfill::substr($requestDomain, 0, -\strlen($cookieDomain)) . $cookieDomain === $requestDomain) {
            return true;
        }
        return false;
    }
    /**
     * @link http://tools.ietf.org/html/rfc6265#section-5.1.4
     *
     * @param string $requestPath
     * @param string $cookiePath
     *
     * @return bool
     */
    private function matchesPath(string $requestPath, string $cookiePath) : bool
    {
        if ($requestPath === $cookiePath) {
            return true;
        }
        if (\strpos($requestPath, $cookiePath) !== 0) {
            return false;
        }
        if (\Phabel\Target\Php80\Polyfill::substr($cookiePath, -1) === '/' || $requestPath[\strlen($cookiePath)] === '/') {
            return true;
        }
        return false;
    }
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use Amp\Success;
use Psr\Http\Message\UriInterface as PsrUri;
final class NullCookieJar implements CookieJar
{
    /**
     *
     */
    public function get(PsrUri $uri) : Promise
    {
        return new Success([]);
    }
    /**
     *
     */
    public function store(ResponseCookie ...$cookie) : Promise
    {
        return new Success();
        // nothing to do
    }
}<?php

namespace Amp\Http\Client\Cookie\Internal;

use Amp\Dns\InvalidNameException;
use function Amp\Dns\normalizeName;
/** @internal */
final class PublicSuffixList
{
    private static $initialized = false;
    private static $suffixPatterns;
    private static $exceptionPatterns;
    /**
     * @param string $domain
     *
     * @return bool
     *
     * @throws InvalidNameException
     */
    public static function isPublicSuffix(string $domain) : bool
    {
        if (!self::$initialized) {
            self::readList();
            self::$initialized = true;
        }
        $domain = normalizeName($domain);
        $domain = \implode('.', \array_reverse(\explode('.', \trim($domain, '.'))));
        foreach (self::$exceptionPatterns as $pattern) {
            if (\preg_match($pattern, $domain)) {
                return false;
            }
        }
        foreach (self::$suffixPatterns as $pattern) {
            if (\preg_match($pattern, $domain)) {
                return true;
            }
        }
        return false;
    }
    /**
     *
     */
    private static function readList() : void
    {
        $lines = \file(__DIR__ . '/../../res/public_suffix_list.dat', \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES);
        $exceptions = [];
        $rules = [];
        foreach ($lines as $line) {
            if (\trim($line) === '') {
                continue;
            }
            if (\Phabel\Target\Php80\Polyfill::substr($line, 0, 2) === '//') {
                continue;
            }
            $rule = \strtok($line, " \t");
            try {
                if ($rule[0] === '!') {
                    $exceptions[] = self::toRegex(\Phabel\Target\Php80\Polyfill::substr($rule, 1), true);
                } else {
                    $rules[] = self::toRegex($rule, false);
                }
            } catch (InvalidNameException $e) {
                // ignore IDN rules if no IDN support is available
                // requests with IDNs will fail anyway then
            }
        }
        self::$exceptionPatterns = \array_map(static function ($list) {
            return '(^(?:' . \implode('|', $list) . ')$)i';
        }, \array_chunk($exceptions, 256));
        self::$suffixPatterns = \array_map(static function ($list) {
            return '(^(?:' . \implode('|', $list) . ')$)i';
        }, \array_chunk($rules, 256));
    }
    /**
     * @param string $rule
     * @param bool $exception
     *
     * @return string
     *
     * @throws InvalidNameException
     */
    private static function toRegex(string $rule, bool $exception) : string
    {
        $labels = \explode('.', $rule);
        foreach ($labels as $key => $label) {
            if ($label !== '*') {
                $labels[$key] = normalizeName($label);
            }
        }
        $rule = \implode('.', $labels);
        $regexParts = [];
        foreach (\explode('.', $rule) as $part) {
            if ($part === '*') {
                $regexParts[] = '[^.]+';
            } else {
                /** @noinspection PregQuoteUsageInspection */
                // We use (), so we don't have that problem
                $regexParts[] = \preg_quote($part);
            }
        }
        $regex = \array_reduce($regexParts, static function ($carry, $item) use($exception) {
            if ($carry === '') {
                return $item;
            }
            return $item . "(?:\\." . $carry . ')' . ($exception ? '' : '?');
        }, '');
        return $regex;
    }
    /**
     *
     */
    private function __construct()
    {
        // no instances should be built
    }
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\File;
use Amp\Http\Client\HttpException;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use Amp\Sync\LocalMutex;
use Amp\Sync\Lock;
use Amp\Sync\Mutex;
use Psr\Http\Message\UriInterface as PsrUri;
use function Amp\call;
final class FileCookieJar implements CookieJar
{
    /** @var Promise<InMemoryCookieJar> */
    private $cookieJar;
    /** @var string */
    private $storagePath;
    /** @var Mutex */
    private $mutex;
    /** @var bool */
    private $persistSessionCookies = false;
    /**
     *
     */
    public function __construct(string $storagePath, ?Mutex $mutex = null)
    {
        if (!\interface_exists(File\Driver::class)) {
            throw new \Error(self::class . ' requires amphp/file to be installed. Run composer require amphp/file to install it.');
        }
        $this->storagePath = $storagePath;
        $this->mutex = $mutex ?? new LocalMutex();
    }
    /**
     *
     */
    public function enableSessionCookiePersistence()
    {
        $this->persistSessionCookies = true;
    }
    /**
     *
     */
    public function disableSessionCookiePersistence()
    {
        $this->persistSessionCookies = false;
    }
    /**
     *
     */
    public function get(PsrUri $uri) : Promise
    {
        return call(function () use($uri) {
            /** @var CookieJar $cookieJar */
            $cookieJar = (yield $this->read());
            return $cookieJar->get($uri);
        });
    }
    /**
     *
     */
    public function store(ResponseCookie ...$cookies) : Promise
    {
        return call(function () use($cookies) {
            /** @var InMemoryCookieJar $cookieJar */
            $cookieJar = (yield $this->read());
            (yield $cookieJar->store(...$cookies));
            (yield $this->write($cookieJar));
        });
    }
    /**
     *
     */
    private function read() : Promise
    {
        if ($this->cookieJar) {
            return $this->cookieJar;
        }
        return $this->cookieJar = call(function () {
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire());
            $cookieJar = new InMemoryCookieJar();
            if (!(yield File\exists($this->storagePath))) {
                return $cookieJar;
            }
            $readPromise = \function_exists('Amp\\File\\read') ? File\read($this->storagePath) : File\get($this->storagePath);
            $lines = \explode("\n", (yield $readPromise));
            foreach ($lines as $line) {
                $line = \trim($line);
                if ($line) {
                    $cookie = ResponseCookie::fromHeader($line);
                    if ($cookie === null) {
                        continue;
                    }
                    try {
                        $cookieJar->store($cookie);
                    } catch (HttpException $e) {
                        // ignore invalid cookies in storage
                    }
                }
            }
            $lock->release();
            return $cookieJar;
        });
    }
    /**
     *
     */
    private function write(InMemoryCookieJar $cookieJar) : Promise
    {
        return call(function () use($cookieJar) {
            $cookieData = '';
            foreach ($cookieJar->getAll() as $cookie) {
                /** @var $cookie ResponseCookie */
                if ($cookie->getExpiry() ? $cookie->getExpiry()->getTimestamp() > \time() : $this->persistSessionCookies) {
                    $cookieData .= $cookie . "\r\n";
                }
            }
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire());
            if (\function_exists('Amp\\File\\createDirectoryRecursively')) {
                try {
                    (yield File\createDirectoryRecursively(\dirname($this->storagePath), 0755));
                } catch (File\FilesystemException $e) {
                    throw new HttpException('Failed to create cookie storage directory: ' . $this->storagePath);
                }
                (yield File\write($this->storagePath, $cookieData));
            } else {
                if (!(yield File\isdir(\dirname($this->storagePath)))) {
                    (yield File\mkdir(\dirname($this->storagePath), 0755, true));
                    if (!(yield File\isdir(\dirname($this->storagePath)))) {
                        throw new HttpException('Failed to create cookie storage directory: ' . $this->storagePath);
                    }
                }
                (yield File\put($this->storagePath, $cookieData));
            }
            $lock->release();
        });
    }
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\Http\Client\HttpException;
use Amp\Http\Cookie\RequestCookie;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use Psr\Http\Message\UriInterface as PsrUri;
interface CookieJar
{
    /**
     * Retrieve all cookies matching the specified constraints.
     *
     * @param PsrUri $uri
     *
     * @return Promise<RequestCookie[]> Returns an array (possibly empty) of all cookie matches.
     */
    public function get(PsrUri $uri) : Promise;
    /**
     * Store a cookie.
     *
     * @param ResponseCookie ...$cookie
     *
     * @return Promise
     *
     * @throws HttpException
     */
    public function store(ResponseCookie ...$cookie) : Promise;
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\CancellationToken;
use Amp\Dns\InvalidNameException;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Cookie\Internal\PublicSuffixList;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Cookie\RequestCookie;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use function Amp\call;
final class CookieInterceptor implements NetworkInterceptor
{
    /** @var CookieJar */
    private $cookieJar;
    /**
     *
     */
    public function __construct(CookieJar $cookieJar)
    {
        $this->cookieJar = $cookieJar;
    }
    /**
     *
     */
    public function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellation, $stream) {
            yield from $this->assignApplicableRequestCookies($request);
            $request->interceptPush(function (Response $response) {
                yield from $this->storeCookies($response);
            });
            /** @var Response $response */
            $response = (yield $stream->request($request, $cancellation));
            yield from $this->storeCookies($response);
            return $response;
        });
    }
    /**
     *
     */
    private function assignApplicableRequestCookies(Request $request) : \Generator
    {
        $applicableCookies = (yield $this->cookieJar->get($request->getUri()));
        if (!$applicableCookies) {
            return;
            // No cookies matched our request; we're finished.
        }
        $cookiePairs = [];
        /** @var RequestCookie $cookie */
        foreach ($applicableCookies as $cookie) {
            $cookiePairs[] = (string) $cookie;
        }
        if ($cookiePairs) {
            if ($request->hasHeader('cookie')) {
                \array_unshift($cookiePairs, $request->getHeader('cookie'));
            }
            $request->setHeader('cookie', \implode('; ', $cookiePairs));
        }
    }
    /**
     *
     */
    private function createResponseCookie(string $requestDomain, string $rawCookieStr) : ?ResponseCookie
    {
        try {
            $cookie = ResponseCookie::fromHeader($rawCookieStr);
            if ($cookie === null) {
                return null;
            }
            if (!$cookie->getDomain()) {
                $cookie = $cookie->withDomain($requestDomain);
            } else {
                // https://tools.ietf.org/html/rfc6265#section-4.1.2.3
                $cookieDomain = $cookie->getDomain();
                // If a domain is set, left dots are ignored and it's always a wildcard
                $cookieDomain = \ltrim($cookieDomain, '.');
                if ($cookieDomain !== $requestDomain) {
                    // ignore cookies on domains that are public suffixes
                    if (PublicSuffixList::isPublicSuffix($cookieDomain)) {
                        return null;
                    }
                    // cookie origin would not be included when sending the cookie
                    $cookieDomainLength = \strlen($cookieDomain);
                    if (\Phabel\Target\Php80\Polyfill::substr($requestDomain, 0, -$cookieDomainLength - 1) . '.' . $cookieDomain !== $requestDomain) {
                        return null;
                    }
                }
                // always add the dot, it's used internally for wildcard matching when an explicit domain is sent
                $cookie = $cookie->withDomain('.' . $cookieDomain);
            }
            return $cookie;
        } catch (InvalidNameException $e) {
            // Ignore malformed Set-Cookie headers
        }
        return null;
    }
    /**
     * @param Response $response
     *
     * @return \Generator
     * @throws \Amp\Http\Client\HttpException
     */
    private function storeCookies(Response $response) : \Generator
    {
        if ($response->hasHeader('set-cookie')) {
            $requestDomain = $response->getRequest()->getUri()->getHost();
            $rawCookies = $response->getHeaderArray('set-cookie');
            $cookies = [];
            foreach ($rawCookies as $rawCookie) {
                $cookie = $this->createResponseCookie($requestDomain, $rawCookie);
                if ($cookie !== null) {
                    $cookies[] = $cookie;
                }
            }
            if ($cookies) {
                (yield $this->cookieJar->store(...$cookies));
            }
        }
    }
}<?php

use Amp\Http\Client\Cookie\CookieInterceptor;
use Amp\Http\Client\Cookie\FileCookieJar;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Loop;
require __DIR__ . '/../vendor/autoload.php';
Loop::run(static function () {
    $cookieJar = new FileCookieJar(__DIR__ . '/basic-file.cookies');
    $httpClient = (new HttpClientBuilder())->interceptNetwork(new CookieInterceptor($cookieJar))->build();
    /** @var Response $firstResponse */
    $firstResponse = (yield $httpClient->request(new Request('https://google.com/')));
    (yield $firstResponse->getBody()->buffer());
    /** @var Response $secondResponse */
    $secondResponse = (yield $httpClient->request(new Request('https://google.com/')));
    (yield $secondResponse->getBody()->buffer());
    /** @var Response $otherDomainResponse */
    $otherDomainResponse = (yield $httpClient->request(new Request('https://amphp.org/')));
    (yield $otherDomainResponse->getBody()->buffer());
    print "== first request cookies ==\r\n";
    print \implode("\r\n", $firstResponse->getRequest()->getHeaderArray('cookie'));
    print "\r\n\r\n";
    print "== first response cookies ==\r\n";
    print \implode("\r\n", $firstResponse->getHeaderArray('set-cookie'));
    print "\r\n\r\n";
    print "== second request sends cookies back ==\r\n";
    print \implode("\r\n", $secondResponse->getRequest()->getHeaderArray('cookie'));
    print "\r\n\r\n";
    print "== other domain request (might send different cookies) ==\r\n";
    print \implode("\r\n", $otherDomainResponse->getRequest()->getHeaderArray('cookie'));
});<?php

use Amp\Http\Client\Cookie\CookieInterceptor;
use Amp\Http\Client\Cookie\InMemoryCookieJar;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Loop;
require __DIR__ . '/../vendor/autoload.php';
Loop::run(static function () {
    $cookieJar = new InMemoryCookieJar();
    $httpClient = (new HttpClientBuilder())->interceptNetwork(new CookieInterceptor($cookieJar))->build();
    /** @var Response $firstResponse */
    $firstResponse = (yield $httpClient->request(new Request('https://google.com/')));
    (yield $firstResponse->getBody()->buffer());
    /** @var Response $secondResponse */
    $secondResponse = (yield $httpClient->request(new Request('https://google.com/')));
    (yield $secondResponse->getBody()->buffer());
    /** @var Response $otherDomainResponse */
    $otherDomainResponse = (yield $httpClient->request(new Request('https://amphp.org/')));
    (yield $otherDomainResponse->getBody()->buffer());
    print "== first request cookies ==\r\n";
    print \implode("\r\n", $firstResponse->getRequest()->getHeaderArray('cookie'));
    print "\r\n\r\n";
    print "== first response cookies ==\r\n";
    print \implode("\r\n", $firstResponse->getHeaderArray('set-cookie'));
    print "\r\n\r\n";
    print "== second request sends cookies back ==\r\n";
    print \implode("\r\n", $secondResponse->getRequest()->getHeaderArray('cookie'));
    print "\r\n\r\n";
    print "== other domain request does not send cookies ==\r\n";
    print \implode("\r\n", $otherDomainResponse->getRequest()->getHeaderArray('cookie'));
});// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat,
// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported.

// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/.

// ===BEGIN ICANN DOMAINS===

// ac : https://en.wikipedia.org/wiki/.ac
ac
com.ac
edu.ac
gov.ac
net.ac
mil.ac
org.ac

// ad : https://en.wikipedia.org/wiki/.ad
ad
nom.ad

// ae : https://en.wikipedia.org/wiki/.ae
// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php
ae
co.ae
net.ae
org.ae
sch.ae
ac.ae
gov.ae
mil.ae

// aero : see https://www.information.aero/index.php?id=66
aero
accident-investigation.aero
accident-prevention.aero
aerobatic.aero
aeroclub.aero
aerodrome.aero
agents.aero
aircraft.aero
airline.aero
airport.aero
air-surveillance.aero
airtraffic.aero
air-traffic-control.aero
ambulance.aero
amusement.aero
association.aero
author.aero
ballooning.aero
broker.aero
caa.aero
cargo.aero
catering.aero
certification.aero
championship.aero
charter.aero
civilaviation.aero
club.aero
conference.aero
consultant.aero
consulting.aero
control.aero
council.aero
crew.aero
design.aero
dgca.aero
educator.aero
emergency.aero
engine.aero
engineer.aero
entertainment.aero
equipment.aero
exchange.aero
express.aero
federation.aero
flight.aero
fuel.aero
gliding.aero
government.aero
groundhandling.aero
group.aero
hanggliding.aero
homebuilt.aero
insurance.aero
journal.aero
journalist.aero
leasing.aero
logistics.aero
magazine.aero
maintenance.aero
media.aero
microlight.aero
modelling.aero
navigation.aero
parachuting.aero
paragliding.aero
passenger-association.aero
pilot.aero
press.aero
production.aero
recreation.aero
repbody.aero
res.aero
research.aero
rotorcraft.aero
safety.aero
scientist.aero
services.aero
show.aero
skydiving.aero
software.aero
student.aero
trader.aero
trading.aero
trainer.aero
union.aero
workinggroup.aero
works.aero

// af : http://www.nic.af/help.jsp
af
gov.af
com.af
org.af
net.af
edu.af

// ag : http://www.nic.ag/prices.htm
ag
com.ag
org.ag
net.ag
co.ag
nom.ag

// ai : http://nic.com.ai/
ai
off.ai
com.ai
net.ai
org.ai

// al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31
al
com.al
edu.al
gov.al
mil.al
net.al
org.al

// am : https://www.amnic.net/policy/en/Policy_EN.pdf
am
co.am
com.am
commune.am
net.am
org.am

// ao : https://en.wikipedia.org/wiki/.ao
// http://www.dns.ao/REGISTR.DOC
ao
ed.ao
gv.ao
og.ao
co.ao
pb.ao
it.ao

// aq : https://en.wikipedia.org/wiki/.aq
aq

// ar : https://nic.ar/es/nic-argentina/normativa
ar
bet.ar
com.ar
coop.ar
edu.ar
gob.ar
gov.ar
int.ar
mil.ar
musica.ar
mutual.ar
net.ar
org.ar
senasa.ar
tur.ar

// arpa : https://en.wikipedia.org/wiki/.arpa
// Confirmed by registry <iana-questions@icann.org> 2008-06-18
arpa
e164.arpa
in-addr.arpa
ip6.arpa
iris.arpa
uri.arpa
urn.arpa

// as : https://en.wikipedia.org/wiki/.as
as
gov.as

// asia : https://en.wikipedia.org/wiki/.asia
asia

// at : https://en.wikipedia.org/wiki/.at
// Confirmed by registry <it@nic.at> 2008-06-17
at
ac.at
co.at
gv.at
or.at
sth.ac.at

// au : https://en.wikipedia.org/wiki/.au
// http://www.auda.org.au/
au
// 2LDs
com.au
net.au
org.au
edu.au
gov.au
asn.au
id.au
// Historic 2LDs (closed to new registration, but sites still exist)
info.au
conf.au
oz.au
// CGDNs - http://www.cgdn.org.au/
act.au
nsw.au
nt.au
qld.au
sa.au
tas.au
vic.au
wa.au
// 3LDs
act.edu.au
catholic.edu.au
// eq.edu.au - Removed at the request of the Queensland Department of Education
nsw.edu.au
nt.edu.au
qld.edu.au
sa.edu.au
tas.edu.au
vic.edu.au
wa.edu.au
// act.gov.au  Bug 984824 - Removed at request of Greg Tankard
// nsw.gov.au  Bug 547985 - Removed at request of <Shae.Donelan@services.nsw.gov.au>
// nt.gov.au  Bug 940478 - Removed at request of Greg Connors <Greg.Connors@nt.gov.au>
qld.gov.au
sa.gov.au
tas.gov.au
vic.gov.au
wa.gov.au
// 4LDs
// education.tas.edu.au - Removed at the request of the Department of Education Tasmania
schools.nsw.edu.au

// aw : https://en.wikipedia.org/wiki/.aw
aw
com.aw

// ax : https://en.wikipedia.org/wiki/.ax
ax

// az : https://en.wikipedia.org/wiki/.az
az
com.az
net.az
int.az
gov.az
org.az
edu.az
info.az
pp.az
mil.az
name.az
pro.az
biz.az

// ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf
ba
com.ba
edu.ba
gov.ba
mil.ba
net.ba
org.ba

// bb : https://en.wikipedia.org/wiki/.bb
bb
biz.bb
co.bb
com.bb
edu.bb
gov.bb
info.bb
net.bb
org.bb
store.bb
tv.bb

// bd : https://en.wikipedia.org/wiki/.bd
*.bd

// be : https://en.wikipedia.org/wiki/.be
// Confirmed by registry <tech@dns.be> 2008-06-08
be
ac.be

// bf : https://en.wikipedia.org/wiki/.bf
bf
gov.bf

// bg : https://en.wikipedia.org/wiki/.bg
// https://www.register.bg/user/static/rules/en/index.html
bg
a.bg
b.bg
c.bg
d.bg
e.bg
f.bg
g.bg
h.bg
i.bg
j.bg
k.bg
l.bg
m.bg
n.bg
o.bg
p.bg
q.bg
r.bg
s.bg
t.bg
u.bg
v.bg
w.bg
x.bg
y.bg
z.bg
0.bg
1.bg
2.bg
3.bg
4.bg
5.bg
6.bg
7.bg
8.bg
9.bg

// bh : https://en.wikipedia.org/wiki/.bh
bh
com.bh
edu.bh
net.bh
org.bh
gov.bh

// bi : https://en.wikipedia.org/wiki/.bi
// http://whois.nic.bi/
bi
co.bi
com.bi
edu.bi
or.bi
org.bi

// biz : https://en.wikipedia.org/wiki/.biz
biz

// bj : https://en.wikipedia.org/wiki/.bj
bj
asso.bj
barreau.bj
gouv.bj

// bm : http://www.bermudanic.bm/dnr-text.txt
bm
com.bm
edu.bm
gov.bm
net.bm
org.bm

// bn : http://www.bnnic.bn/faqs
bn
com.bn
edu.bn
gov.bn
net.bn
org.bn

// bo : https://nic.bo/delegacion2015.php#h-1.10
bo
com.bo
edu.bo
gob.bo
int.bo
org.bo
net.bo
mil.bo
tv.bo
web.bo
// Social Domains
academia.bo
agro.bo
arte.bo
blog.bo
bolivia.bo
ciencia.bo
cooperativa.bo
democracia.bo
deporte.bo
ecologia.bo
economia.bo
empresa.bo
indigena.bo
industria.bo
info.bo
medicina.bo
movimiento.bo
musica.bo
natural.bo
nombre.bo
noticias.bo
patria.bo
politica.bo
profesional.bo
plurinacional.bo
pueblo.bo
revista.bo
salud.bo
tecnologia.bo
tksat.bo
transporte.bo
wiki.bo

// br : http://registro.br/dominio/categoria.html
// Submitted by registry <fneves@registro.br>
br
9guacu.br
abc.br
adm.br
adv.br
agr.br
aju.br
am.br
anani.br
aparecida.br
app.br
arq.br
art.br
ato.br
b.br
barueri.br
belem.br
bhz.br
bib.br
bio.br
blog.br
bmd.br
boavista.br
bsb.br
campinagrande.br
campinas.br
caxias.br
cim.br
cng.br
cnt.br
com.br
contagem.br
coop.br
coz.br
cri.br
cuiaba.br
curitiba.br
def.br
des.br
det.br
dev.br
ecn.br
eco.br
edu.br
emp.br
enf.br
eng.br
esp.br
etc.br
eti.br
far.br
feira.br
flog.br
floripa.br
fm.br
fnd.br
fortal.br
fot.br
foz.br
fst.br
g12.br
geo.br
ggf.br
goiania.br
gov.br
// gov.br 26 states + df https://en.wikipedia.org/wiki/States_of_Brazil
ac.gov.br
al.gov.br
am.gov.br
ap.gov.br
ba.gov.br
ce.gov.br
df.gov.br
es.gov.br
go.gov.br
ma.gov.br
mg.gov.br
ms.gov.br
mt.gov.br
pa.gov.br
pb.gov.br
pe.gov.br
pi.gov.br
pr.gov.br
rj.gov.br
rn.gov.br
ro.gov.br
rr.gov.br
rs.gov.br
sc.gov.br
se.gov.br
sp.gov.br
to.gov.br
gru.br
imb.br
ind.br
inf.br
jab.br
jampa.br
jdf.br
joinville.br
jor.br
jus.br
leg.br
lel.br
log.br
londrina.br
macapa.br
maceio.br
manaus.br
maringa.br
mat.br
med.br
mil.br
morena.br
mp.br
mus.br
natal.br
net.br
niteroi.br
*.nom.br
not.br
ntr.br
odo.br
ong.br
org.br
osasco.br
palmas.br
poa.br
ppg.br
pro.br
psc.br
psi.br
pvh.br
qsl.br
radio.br
rec.br
recife.br
rep.br
ribeirao.br
rio.br
riobranco.br
riopreto.br
salvador.br
sampa.br
santamaria.br
santoandre.br
saobernardo.br
saogonca.br
seg.br
sjc.br
slg.br
slz.br
sorocaba.br
srv.br
taxi.br
tc.br
tec.br
teo.br
the.br
tmp.br
trd.br
tur.br
tv.br
udi.br
vet.br
vix.br
vlog.br
wiki.br
zlg.br

// bs : http://www.nic.bs/rules.html
bs
com.bs
net.bs
org.bs
edu.bs
gov.bs

// bt : https://en.wikipedia.org/wiki/.bt
bt
com.bt
edu.bt
gov.bt
net.bt
org.bt

// bv : No registrations at this time.
// Submitted by registry <jarle@uninett.no>
bv

// bw : https://en.wikipedia.org/wiki/.bw
// http://www.gobin.info/domainname/bw.doc
// list of other 2nd level tlds ?
bw
co.bw
org.bw

// by : https://en.wikipedia.org/wiki/.by
// http://tld.by/rules_2006_en.html
// list of other 2nd level tlds ?
by
gov.by
mil.by
// Official information does not indicate that com.by is a reserved
// second-level domain, but it's being used as one (see www.google.com.by and
// www.yahoo.com.by, for example), so we list it here for safety's sake.
com.by

// http://hoster.by/
of.by

// bz : https://en.wikipedia.org/wiki/.bz
// http://www.belizenic.bz/
bz
com.bz
net.bz
org.bz
edu.bz
gov.bz

// ca : https://en.wikipedia.org/wiki/.ca
ca
// ca geographical names
ab.ca
bc.ca
mb.ca
nb.ca
nf.ca
nl.ca
ns.ca
nt.ca
nu.ca
on.ca
pe.ca
qc.ca
sk.ca
yk.ca
// gc.ca: https://en.wikipedia.org/wiki/.gc.ca
// see also: http://registry.gc.ca/en/SubdomainFAQ
gc.ca

// cat : https://en.wikipedia.org/wiki/.cat
cat

// cc : https://en.wikipedia.org/wiki/.cc
cc

// cd : https://en.wikipedia.org/wiki/.cd
// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1
cd
gov.cd

// cf : https://en.wikipedia.org/wiki/.cf
cf

// cg : https://en.wikipedia.org/wiki/.cg
cg

// ch : https://en.wikipedia.org/wiki/.ch
ch

// ci : https://en.wikipedia.org/wiki/.ci
// http://www.nic.ci/index.php?page=charte
ci
org.ci
or.ci
com.ci
co.ci
edu.ci
ed.ci
ac.ci
net.ci
go.ci
asso.ci
aÃ©roport.ci
int.ci
presse.ci
md.ci
gouv.ci

// ck : https://en.wikipedia.org/wiki/.ck
*.ck
!www.ck

// cl : https://www.nic.cl
// Confirmed by .CL registry <hsalgado@nic.cl>
cl
co.cl
gob.cl
gov.cl
mil.cl

// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927
cm
co.cm
com.cm
gov.cm
net.cm

// cn : https://en.wikipedia.org/wiki/.cn
// Submitted by registry <tanyaling@cnnic.cn>
cn
ac.cn
com.cn
edu.cn
gov.cn
net.cn
org.cn
mil.cn
å…¬å�¸.cn
ç½‘ç»œ.cn
ç¶²çµ¡.cn
// cn geographic names
ah.cn
bj.cn
cq.cn
fj.cn
gd.cn
gs.cn
gz.cn
gx.cn
ha.cn
hb.cn
he.cn
hi.cn
hl.cn
hn.cn
jl.cn
js.cn
jx.cn
ln.cn
nm.cn
nx.cn
qh.cn
sc.cn
sd.cn
sh.cn
sn.cn
sx.cn
tj.cn
xj.cn
xz.cn
yn.cn
zj.cn
hk.cn
mo.cn
tw.cn

// co : https://en.wikipedia.org/wiki/.co
// Submitted by registry <tecnico@uniandes.edu.co>
co
arts.co
com.co
edu.co
firm.co
gov.co
info.co
int.co
mil.co
net.co
nom.co
org.co
rec.co
web.co

// com : https://en.wikipedia.org/wiki/.com
com

// coop : https://en.wikipedia.org/wiki/.coop
coop

// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do
cr
ac.cr
co.cr
ed.cr
fi.cr
go.cr
or.cr
sa.cr

// cu : https://en.wikipedia.org/wiki/.cu
cu
com.cu
edu.cu
org.cu
net.cu
gov.cu
inf.cu

// cv : https://en.wikipedia.org/wiki/.cv
// cv : http://www.dns.cv/tldcv_portal/do?com=DS;5446457100;111;+PAGE(4000018)+K-CAT-CODIGO(RDOM)+RCNT(100); <- registration rules
cv
com.cv
edu.cv
int.cv
nome.cv
org.cv

// cw : http://www.una.cw/cw_registry/
// Confirmed by registry <registry@una.net> 2013-03-26
cw
com.cw
edu.cw
net.cw
org.cw

// cx : https://en.wikipedia.org/wiki/.cx
// list of other 2nd level tlds ?
cx
gov.cx

// cy : http://www.nic.cy/
// Submitted by registry Panayiotou Fotia <cydns@ucy.ac.cy>
cy
ac.cy
biz.cy
com.cy
ekloges.cy
gov.cy
ltd.cy
name.cy
net.cy
org.cy
parliament.cy
press.cy
pro.cy
tm.cy

// cz : https://en.wikipedia.org/wiki/.cz
cz

// de : https://en.wikipedia.org/wiki/.de
// Confirmed by registry <ops@denic.de> (with technical
// reservations) 2008-07-01
de

// dj : https://en.wikipedia.org/wiki/.dj
dj

// dk : https://en.wikipedia.org/wiki/.dk
// Confirmed by registry <robert@dk-hostmaster.dk> 2008-06-17
dk

// dm : https://en.wikipedia.org/wiki/.dm
dm
com.dm
net.dm
org.dm
edu.dm
gov.dm

// do : https://en.wikipedia.org/wiki/.do
do
art.do
com.do
edu.do
gob.do
gov.do
mil.do
net.do
org.do
sld.do
web.do

// dz : http://www.nic.dz/images/pdf_nic/charte.pdf
dz
art.dz
asso.dz
com.dz
edu.dz
gov.dz
org.dz
net.dz
pol.dz
soc.dz
tm.dz

// ec : http://www.nic.ec/reg/paso1.asp
// Submitted by registry <vabboud@nic.ec>
ec
com.ec
info.ec
net.ec
fin.ec
k12.ec
med.ec
pro.ec
org.ec
edu.ec
gov.ec
gob.ec
mil.ec

// edu : https://en.wikipedia.org/wiki/.edu
edu

// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B
ee
edu.ee
gov.ee
riik.ee
lib.ee
med.ee
com.ee
pri.ee
aip.ee
org.ee
fie.ee

// eg : https://en.wikipedia.org/wiki/.eg
eg
com.eg
edu.eg
eun.eg
gov.eg
mil.eg
name.eg
net.eg
org.eg
sci.eg

// er : https://en.wikipedia.org/wiki/.er
*.er

// es : https://www.nic.es/site_ingles/ingles/dominios/index.html
es
com.es
nom.es
org.es
gob.es
edu.es

// et : https://en.wikipedia.org/wiki/.et
et
com.et
gov.et
org.et
edu.et
biz.et
name.et
info.et
net.et

// eu : https://en.wikipedia.org/wiki/.eu
eu

// fi : https://en.wikipedia.org/wiki/.fi
fi
// aland.fi : https://en.wikipedia.org/wiki/.ax
// This domain is being phased out in favor of .ax. As there are still many
// domains under aland.fi, we still keep it on the list until aland.fi is
// completely removed.
// TODO: Check for updates (expected to be phased out around Q1/2009)
aland.fi

// fj : http://domains.fj/
// Submitted by registry <garth.miller@cocca.org.nz> 2020-02-11
fj
ac.fj
biz.fj
com.fj
gov.fj
info.fj
mil.fj
name.fj
net.fj
org.fj
pro.fj

// fk : https://en.wikipedia.org/wiki/.fk
*.fk

// fm : https://en.wikipedia.org/wiki/.fm
com.fm
edu.fm
net.fm
org.fm
fm

// fo : https://en.wikipedia.org/wiki/.fo
fo

// fr : http://www.afnic.fr/
// domaines descriptifs : https://www.afnic.fr/medias/documents/Cadre_legal/Afnic_Naming_Policy_12122016_VEN.pdf
fr
asso.fr
com.fr
gouv.fr
nom.fr
prd.fr
tm.fr
// domaines sectoriels : https://www.afnic.fr/en/products-and-services/the-fr-tld/sector-based-fr-domains-4.html
aeroport.fr
avocat.fr
avoues.fr
cci.fr
chambagri.fr
chirurgiens-dentistes.fr
experts-comptables.fr
geometre-expert.fr
greta.fr
huissier-justice.fr
medecin.fr
notaires.fr
pharmacien.fr
port.fr
veterinaire.fr

// ga : https://en.wikipedia.org/wiki/.ga
ga

// gb : This registry is effectively dormant
// Submitted by registry <Damien.Shaw@ja.net>
gb

// gd : https://en.wikipedia.org/wiki/.gd
edu.gd
gov.gd
gd

// ge : http://www.nic.net.ge/policy_en.pdf
ge
com.ge
edu.ge
gov.ge
org.ge
mil.ge
net.ge
pvt.ge

// gf : https://en.wikipedia.org/wiki/.gf
gf

// gg : http://www.channelisles.net/register-domains/
// Confirmed by registry <nigel@channelisles.net> 2013-11-28
gg
co.gg
net.gg
org.gg

// gh : https://en.wikipedia.org/wiki/.gh
// see also: http://www.nic.gh/reg_now.php
// Although domains directly at second level are not possible at the moment,
// they have been possible for some time and may come back.
gh
com.gh
edu.gh
gov.gh
org.gh
mil.gh

// gi : http://www.nic.gi/rules.html
gi
com.gi
ltd.gi
gov.gi
mod.gi
edu.gi
org.gi

// gl : https://en.wikipedia.org/wiki/.gl
// http://nic.gl
gl
co.gl
com.gl
edu.gl
net.gl
org.gl

// gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm
gm

// gn : http://psg.com/dns/gn/gn.txt
// Submitted by registry <randy@psg.com>
gn
ac.gn
com.gn
edu.gn
gov.gn
org.gn
net.gn

// gov : https://en.wikipedia.org/wiki/.gov
gov

// gp : http://www.nic.gp/index.php?lang=en
gp
com.gp
net.gp
mobi.gp
edu.gp
org.gp
asso.gp

// gq : https://en.wikipedia.org/wiki/.gq
gq

// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html
// Submitted by registry <segred@ics.forth.gr>
gr
com.gr
edu.gr
net.gr
org.gr
gov.gr

// gs : https://en.wikipedia.org/wiki/.gs
gs

// gt : https://www.gt/sitio/registration_policy.php?lang=en
gt
com.gt
edu.gt
gob.gt
ind.gt
mil.gt
net.gt
org.gt

// gu : http://gadao.gov.gu/register.html
// University of Guam : https://www.uog.edu
// Submitted by uognoc@triton.uog.edu
gu
com.gu
edu.gu
gov.gu
guam.gu
info.gu
net.gu
org.gu
web.gu

// gw : https://en.wikipedia.org/wiki/.gw
// gw : https://nic.gw/regras/
gw

// gy : https://en.wikipedia.org/wiki/.gy
// http://registry.gy/
gy
co.gy
com.gy
edu.gy
gov.gy
net.gy
org.gy

// hk : https://www.hkirc.hk
// Submitted by registry <hk.tech@hkirc.hk>
hk
com.hk
edu.hk
gov.hk
idv.hk
net.hk
org.hk
å…¬å�¸.hk
æ•™è‚².hk
æ•Žè‚².hk
æ”¿åºœ.hk
å€‹äºº.hk
ä¸ªäºº.hk
ç®‡äºº.hk
ç¶²ç»œ.hk
ç½‘ç»œ.hk
ç»„ç¹”.hk
ç¶²çµ¡.hk
ç½‘çµ¡.hk
ç»„ç»‡.hk
çµ„ç¹”.hk
çµ„ç»‡.hk

// hm : https://en.wikipedia.org/wiki/.hm
hm

// hn : http://www.nic.hn/politicas/ps02,,05.html
hn
com.hn
edu.hn
org.hn
net.hn
mil.hn
gob.hn

// hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf
hr
iz.hr
from.hr
name.hr
com.hr

// ht : http://www.nic.ht/info/charte.cfm
ht
com.ht
shop.ht
firm.ht
info.ht
adult.ht
net.ht
pro.ht
org.ht
med.ht
art.ht
coop.ht
pol.ht
asso.ht
edu.ht
rel.ht
gouv.ht
perso.ht

// hu : http://www.domain.hu/domain/English/sld.html
// Confirmed by registry <pasztor@iszt.hu> 2008-06-12
hu
co.hu
info.hu
org.hu
priv.hu
sport.hu
tm.hu
2000.hu
agrar.hu
bolt.hu
casino.hu
city.hu
erotica.hu
erotika.hu
film.hu
forum.hu
games.hu
hotel.hu
ingatlan.hu
jogasz.hu
konyvelo.hu
lakas.hu
media.hu
news.hu
reklam.hu
sex.hu
shop.hu
suli.hu
szex.hu
tozsde.hu
utazas.hu
video.hu

// id : https://pandi.id/en/domain/registration-requirements/
id
ac.id
biz.id
co.id
desa.id
go.id
mil.id
my.id
net.id
or.id
ponpes.id
sch.id
web.id

// ie : https://en.wikipedia.org/wiki/.ie
ie
gov.ie

// il : http://www.isoc.org.il/domains/
il
ac.il
co.il
gov.il
idf.il
k12.il
muni.il
net.il
org.il

// im : https://www.nic.im/
// Submitted by registry <info@nic.im>
im
ac.im
co.im
com.im
ltd.co.im
net.im
org.im
plc.co.im
tt.im
tv.im

// in : https://en.wikipedia.org/wiki/.in
// see also: https://registry.in/Policies
// Please note, that nic.in is not an official eTLD, but used by most
// government institutions.
in
co.in
firm.in
net.in
org.in
gen.in
ind.in
nic.in
ac.in
edu.in
res.in
gov.in
mil.in

// info : https://en.wikipedia.org/wiki/.info
info

// int : https://en.wikipedia.org/wiki/.int
// Confirmed by registry <iana-questions@icann.org> 2008-06-18
int
eu.int

// io : http://www.nic.io/rules.html
// list of other 2nd level tlds ?
io
com.io

// iq : http://www.cmc.iq/english/iq/iqregister1.htm
iq
gov.iq
edu.iq
mil.iq
com.iq
org.iq
net.iq

// ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules
// Also see http://www.nic.ir/Internationalized_Domain_Names
// Two <iran>.ir entries added at request of <tech-team@nic.ir>, 2010-04-16
ir
ac.ir
co.ir
gov.ir
id.ir
net.ir
org.ir
sch.ir
// xn--mgba3a4f16a.ir (<iran>.ir, Persian YEH)
Ø§ÛŒØ±Ø§Ù†.ir
// xn--mgba3a4fra.ir (<iran>.ir, Arabic YEH)
Ø§ÙŠØ±Ø§Ù†.ir

// is : http://www.isnic.is/domain/rules.php
// Confirmed by registry <marius@isgate.is> 2008-12-06
is
net.is
com.is
edu.is
gov.is
org.is
int.is

// it : https://en.wikipedia.org/wiki/.it
it
gov.it
edu.it
// Reserved geo-names (regions and provinces):
// https://www.nic.it/sites/default/files/archivio/docs/Regulation_assignation_v7.1.pdf
// Regions
abr.it
abruzzo.it
aosta-valley.it
aostavalley.it
bas.it
basilicata.it
cal.it
calabria.it
cam.it
campania.it
emilia-romagna.it
emiliaromagna.it
emr.it
friuli-v-giulia.it
friuli-ve-giulia.it
friuli-vegiulia.it
friuli-venezia-giulia.it
friuli-veneziagiulia.it
friuli-vgiulia.it
friuliv-giulia.it
friulive-giulia.it
friulivegiulia.it
friulivenezia-giulia.it
friuliveneziagiulia.it
friulivgiulia.it
fvg.it
laz.it
lazio.it
lig.it
liguria.it
lom.it
lombardia.it
lombardy.it
lucania.it
mar.it
marche.it
mol.it
molise.it
piedmont.it
piemonte.it
pmn.it
pug.it
puglia.it
sar.it
sardegna.it
sardinia.it
sic.it
sicilia.it
sicily.it
taa.it
tos.it
toscana.it
trentin-sud-tirol.it
trentin-sÃ¼d-tirol.it
trentin-sudtirol.it
trentin-sÃ¼dtirol.it
trentin-sued-tirol.it
trentin-suedtirol.it
trentino-a-adige.it
trentino-aadige.it
trentino-alto-adige.it
trentino-altoadige.it
trentino-s-tirol.it
trentino-stirol.it
trentino-sud-tirol.it
trentino-sÃ¼d-tirol.it
trentino-sudtirol.it
trentino-sÃ¼dtirol.it
trentino-sued-tirol.it
trentino-suedtirol.it
trentino.it
trentinoa-adige.it
trentinoaadige.it
trentinoalto-adige.it
trentinoaltoadige.it
trentinos-tirol.it
trentinostirol.it
trentinosud-tirol.it
trentinosÃ¼d-tirol.it
trentinosudtirol.it
trentinosÃ¼dtirol.it
trentinosued-tirol.it
trentinosuedtirol.it
trentinsud-tirol.it
trentinsÃ¼d-tirol.it
trentinsudtirol.it
trentinsÃ¼dtirol.it
trentinsued-tirol.it
trentinsuedtirol.it
tuscany.it
umb.it
umbria.it
val-d-aosta.it
val-daosta.it
vald-aosta.it
valdaosta.it
valle-aosta.it
valle-d-aosta.it
valle-daosta.it
valleaosta.it
valled-aosta.it
valledaosta.it
vallee-aoste.it
vallÃ©e-aoste.it
vallee-d-aoste.it
vallÃ©e-d-aoste.it
valleeaoste.it
vallÃ©eaoste.it
valleedaoste.it
vallÃ©edaoste.it
vao.it
vda.it
ven.it
veneto.it
// Provinces
ag.it
agrigento.it
al.it
alessandria.it
alto-adige.it
altoadige.it
an.it
ancona.it
andria-barletta-trani.it
andria-trani-barletta.it
andriabarlettatrani.it
andriatranibarletta.it
ao.it
aosta.it
aoste.it
ap.it
aq.it
aquila.it
ar.it
arezzo.it
ascoli-piceno.it
ascolipiceno.it
asti.it
at.it
av.it
avellino.it
ba.it
balsan-sudtirol.it
balsan-sÃ¼dtirol.it
balsan-suedtirol.it
balsan.it
bari.it
barletta-trani-andria.it
barlettatraniandria.it
belluno.it
benevento.it
bergamo.it
bg.it
bi.it
biella.it
bl.it
bn.it
bo.it
bologna.it
bolzano-altoadige.it
bolzano.it
bozen-sudtirol.it
bozen-sÃ¼dtirol.it
bozen-suedtirol.it
bozen.it
br.it
brescia.it
brindisi.it
bs.it
bt.it
bulsan-sudtirol.it
bulsan-sÃ¼dtirol.it
bulsan-suedtirol.it
bulsan.it
bz.it
ca.it
cagliari.it
caltanissetta.it
campidano-medio.it
campidanomedio.it
campobasso.it
carbonia-iglesias.it
carboniaiglesias.it
carrara-massa.it
carraramassa.it
caserta.it
catania.it
catanzaro.it
cb.it
ce.it
cesena-forli.it
cesena-forlÃ¬.it
cesenaforli.it
cesenaforlÃ¬.it
ch.it
chieti.it
ci.it
cl.it
cn.it
co.it
como.it
cosenza.it
cr.it
cremona.it
crotone.it
cs.it
ct.it
cuneo.it
cz.it
dell-ogliastra.it
dellogliastra.it
en.it
enna.it
fc.it
fe.it
fermo.it
ferrara.it
fg.it
fi.it
firenze.it
florence.it
fm.it
foggia.it
forli-cesena.it
forlÃ¬-cesena.it
forlicesena.it
forlÃ¬cesena.it
fr.it
frosinone.it
ge.it
genoa.it
genova.it
go.it
gorizia.it
gr.it
grosseto.it
iglesias-carbonia.it
iglesiascarbonia.it
im.it
imperia.it
is.it
isernia.it
kr.it
la-spezia.it
laquila.it
laspezia.it
latina.it
lc.it
le.it
lecce.it
lecco.it
li.it
livorno.it
lo.it
lodi.it
lt.it
lu.it
lucca.it
macerata.it
mantova.it
massa-carrara.it
massacarrara.it
matera.it
mb.it
mc.it
me.it
medio-campidano.it
mediocampidano.it
messina.it
mi.it
milan.it
milano.it
mn.it
mo.it
modena.it
monza-brianza.it
monza-e-della-brianza.it
monza.it
monzabrianza.it
monzaebrianza.it
monzaedellabrianza.it
ms.it
mt.it
na.it
naples.it
napoli.it
no.it
novara.it
nu.it
nuoro.it
og.it
ogliastra.it
olbia-tempio.it
olbiatempio.it
or.it
oristano.it
ot.it
pa.it
padova.it
padua.it
palermo.it
parma.it
pavia.it
pc.it
pd.it
pe.it
perugia.it
pesaro-urbino.it
pesarourbino.it
pescara.it
pg.it
pi.it
piacenza.it
pisa.it
pistoia.it
pn.it
po.it
pordenone.it
potenza.it
pr.it
prato.it
pt.it
pu.it
pv.it
pz.it
ra.it
ragusa.it
ravenna.it
rc.it
re.it
reggio-calabria.it
reggio-emilia.it
reggiocalabria.it
reggioemilia.it
rg.it
ri.it
rieti.it
rimini.it
rm.it
rn.it
ro.it
roma.it
rome.it
rovigo.it
sa.it
salerno.it
sassari.it
savona.it
si.it
siena.it
siracusa.it
so.it
sondrio.it
sp.it
sr.it
ss.it
suedtirol.it
sÃ¼dtirol.it
sv.it
ta.it
taranto.it
te.it
tempio-olbia.it
tempioolbia.it
teramo.it
terni.it
tn.it
to.it
torino.it
tp.it
tr.it
trani-andria-barletta.it
trani-barletta-andria.it
traniandriabarletta.it
tranibarlettaandria.it
trapani.it
trento.it
treviso.it
trieste.it
ts.it
turin.it
tv.it
ud.it
udine.it
urbino-pesaro.it
urbinopesaro.it
va.it
varese.it
vb.it
vc.it
ve.it
venezia.it
venice.it
verbania.it
vercelli.it
verona.it
vi.it
vibo-valentia.it
vibovalentia.it
vicenza.it
viterbo.it
vr.it
vs.it
vt.it
vv.it

// je : http://www.channelisles.net/register-domains/
// Confirmed by registry <nigel@channelisles.net> 2013-11-28
je
co.je
net.je
org.je

// jm : http://www.com.jm/register.html
*.jm

// jo : http://www.dns.jo/Registration_policy.aspx
jo
com.jo
org.jo
net.jo
edu.jo
sch.jo
gov.jo
mil.jo
name.jo

// jobs : https://en.wikipedia.org/wiki/.jobs
jobs

// jp : https://en.wikipedia.org/wiki/.jp
// http://jprs.co.jp/en/jpdomain.html
// Submitted by registry <info@jprs.jp>
jp
// jp organizational type names
ac.jp
ad.jp
co.jp
ed.jp
go.jp
gr.jp
lg.jp
ne.jp
or.jp
// jp prefecture type names
aichi.jp
akita.jp
aomori.jp
chiba.jp
ehime.jp
fukui.jp
fukuoka.jp
fukushima.jp
gifu.jp
gunma.jp
hiroshima.jp
hokkaido.jp
hyogo.jp
ibaraki.jp
ishikawa.jp
iwate.jp
kagawa.jp
kagoshima.jp
kanagawa.jp
kochi.jp
kumamoto.jp
kyoto.jp
mie.jp
miyagi.jp
miyazaki.jp
nagano.jp
nagasaki.jp
nara.jp
niigata.jp
oita.jp
okayama.jp
okinawa.jp
osaka.jp
saga.jp
saitama.jp
shiga.jp
shimane.jp
shizuoka.jp
tochigi.jp
tokushima.jp
tokyo.jp
tottori.jp
toyama.jp
wakayama.jp
yamagata.jp
yamaguchi.jp
yamanashi.jp
æ ƒæœ¨.jp
æ„›çŸ¥.jp
æ„›åª›.jp
å…µåº«.jp
ç†Šæœ¬.jp
èŒ¨åŸŽ.jp
åŒ—æµ·é�“.jp
å�ƒè‘‰.jp
å’Œæ­Œå±±.jp
é•·å´Ž.jp
é•·é‡Ž.jp
æ–°æ½Ÿ.jp
é�’æ£®.jp
é�™å²¡.jp
æ�±äº¬.jp
çŸ³å·�.jp
åŸ¼çŽ‰.jp
ä¸‰é‡�.jp
äº¬éƒ½.jp
ä½�è³€.jp
å¤§åˆ†.jp
å¤§é˜ª.jp
å¥ˆè‰¯.jp
å®®åŸŽ.jp
å®®å´Ž.jp
å¯Œå±±.jp
å±±å�£.jp
å±±å½¢.jp
å±±æ¢¨.jp
å²©æ‰‹.jp
å²�é˜œ.jp
å²¡å±±.jp
å³¶æ ¹.jp
åºƒå³¶.jp
å¾³å³¶.jp
æ²–ç¸„.jp
æ»‹è³€.jp
ç¥žå¥ˆå·�.jp
ç¦�äº•.jp
ç¦�å²¡.jp
ç¦�å³¶.jp
ç§‹ç”°.jp
ç¾¤é¦¬.jp
é¦™å·�.jp
é«˜çŸ¥.jp
é³¥å�–.jp
é¹¿å…�å³¶.jp
// jp geographic type names
// http://jprs.jp/doc/rule/saisoku-1.html
*.kawasaki.jp
*.kitakyushu.jp
*.kobe.jp
*.nagoya.jp
*.sapporo.jp
*.sendai.jp
*.yokohama.jp
!city.kawasaki.jp
!city.kitakyushu.jp
!city.kobe.jp
!city.nagoya.jp
!city.sapporo.jp
!city.sendai.jp
!city.yokohama.jp
// 4th level registration
aisai.aichi.jp
ama.aichi.jp
anjo.aichi.jp
asuke.aichi.jp
chiryu.aichi.jp
chita.aichi.jp
fuso.aichi.jp
gamagori.aichi.jp
handa.aichi.jp
hazu.aichi.jp
hekinan.aichi.jp
higashiura.aichi.jp
ichinomiya.aichi.jp
inazawa.aichi.jp
inuyama.aichi.jp
isshiki.aichi.jp
iwakura.aichi.jp
kanie.aichi.jp
kariya.aichi.jp
kasugai.aichi.jp
kira.aichi.jp
kiyosu.aichi.jp
komaki.aichi.jp
konan.aichi.jp
kota.aichi.jp
mihama.aichi.jp
miyoshi.aichi.jp
nishio.aichi.jp
nisshin.aichi.jp
obu.aichi.jp
oguchi.aichi.jp
oharu.aichi.jp
okazaki.aichi.jp
owariasahi.aichi.jp
seto.aichi.jp
shikatsu.aichi.jp
shinshiro.aichi.jp
shitara.aichi.jp
tahara.aichi.jp
takahama.aichi.jp
tobishima.aichi.jp
toei.aichi.jp
togo.aichi.jp
tokai.aichi.jp
tokoname.aichi.jp
toyoake.aichi.jp
toyohashi.aichi.jp
toyokawa.aichi.jp
toyone.aichi.jp
toyota.aichi.jp
tsushima.aichi.jp
yatomi.aichi.jp
akita.akita.jp
daisen.akita.jp
fujisato.akita.jp
gojome.akita.jp
hachirogata.akita.jp
happou.akita.jp
higashinaruse.akita.jp
honjo.akita.jp
honjyo.akita.jp
ikawa.akita.jp
kamikoani.akita.jp
kamioka.akita.jp
katagami.akita.jp
kazuno.akita.jp
kitaakita.akita.jp
kosaka.akita.jp
kyowa.akita.jp
misato.akita.jp
mitane.akita.jp
moriyoshi.akita.jp
nikaho.akita.jp
noshiro.akita.jp
odate.akita.jp
oga.akita.jp
ogata.akita.jp
semboku.akita.jp
yokote.akita.jp
yurihonjo.akita.jp
aomori.aomori.jp
gonohe.aomori.jp
hachinohe.aomori.jp
hashikami.aomori.jp
hiranai.aomori.jp
hirosaki.aomori.jp
itayanagi.aomori.jp
kuroishi.aomori.jp
misawa.aomori.jp
mutsu.aomori.jp
nakadomari.aomori.jp
noheji.aomori.jp
oirase.aomori.jp
owani.aomori.jp
rokunohe.aomori.jp
sannohe.aomori.jp
shichinohe.aomori.jp
shingo.aomori.jp
takko.aomori.jp
towada.aomori.jp
tsugaru.aomori.jp
tsuruta.aomori.jp
abiko.chiba.jp
asahi.chiba.jp
chonan.chiba.jp
chosei.chiba.jp
choshi.chiba.jp
chuo.chiba.jp
funabashi.chiba.jp
futtsu.chiba.jp
hanamigawa.chiba.jp
ichihara.chiba.jp
ichikawa.chiba.jp
ichinomiya.chiba.jp
inzai.chiba.jp
isumi.chiba.jp
kamagaya.chiba.jp
kamogawa.chiba.jp
kashiwa.chiba.jp
katori.chiba.jp
katsuura.chiba.jp
kimitsu.chiba.jp
kisarazu.chiba.jp
kozaki.chiba.jp
kujukuri.chiba.jp
kyonan.chiba.jp
matsudo.chiba.jp
midori.chiba.jp
mihama.chiba.jp
minamiboso.chiba.jp
mobara.chiba.jp
mutsuzawa.chiba.jp
nagara.chiba.jp
nagareyama.chiba.jp
narashino.chiba.jp
narita.chiba.jp
noda.chiba.jp
oamishirasato.chiba.jp
omigawa.chiba.jp
onjuku.chiba.jp
otaki.chiba.jp
sakae.chiba.jp
sakura.chiba.jp
shimofusa.chiba.jp
shirako.chiba.jp
shiroi.chiba.jp
shisui.chiba.jp
sodegaura.chiba.jp
sosa.chiba.jp
tako.chiba.jp
tateyama.chiba.jp
togane.chiba.jp
tohnosho.chiba.jp
tomisato.chiba.jp
urayasu.chiba.jp
yachimata.chiba.jp
yachiyo.chiba.jp
yokaichiba.chiba.jp
yokoshibahikari.chiba.jp
yotsukaido.chiba.jp
ainan.ehime.jp
honai.ehime.jp
ikata.ehime.jp
imabari.ehime.jp
iyo.ehime.jp
kamijima.ehime.jp
kihoku.ehime.jp
kumakogen.ehime.jp
masaki.ehime.jp
matsuno.ehime.jp
matsuyama.ehime.jp
namikata.ehime.jp
niihama.ehime.jp
ozu.ehime.jp
saijo.ehime.jp
seiyo.ehime.jp
shikokuchuo.ehime.jp
tobe.ehime.jp
toon.ehime.jp
uchiko.ehime.jp
uwajima.ehime.jp
yawatahama.ehime.jp
echizen.fukui.jp
eiheiji.fukui.jp
fukui.fukui.jp
ikeda.fukui.jp
katsuyama.fukui.jp
mihama.fukui.jp
minamiechizen.fukui.jp
obama.fukui.jp
ohi.fukui.jp
ono.fukui.jp
sabae.fukui.jp
sakai.fukui.jp
takahama.fukui.jp
tsuruga.fukui.jp
wakasa.fukui.jp
ashiya.fukuoka.jp
buzen.fukuoka.jp
chikugo.fukuoka.jp
chikuho.fukuoka.jp
chikujo.fukuoka.jp
chikushino.fukuoka.jp
chikuzen.fukuoka.jp
chuo.fukuoka.jp
dazaifu.fukuoka.jp
fukuchi.fukuoka.jp
hakata.fukuoka.jp
higashi.fukuoka.jp
hirokawa.fukuoka.jp
hisayama.fukuoka.jp
iizuka.fukuoka.jp
inatsuki.fukuoka.jp
kaho.fukuoka.jp
kasuga.fukuoka.jp
kasuya.fukuoka.jp
kawara.fukuoka.jp
keisen.fukuoka.jp
koga.fukuoka.jp
kurate.fukuoka.jp
kurogi.fukuoka.jp
kurume.fukuoka.jp
minami.fukuoka.jp
miyako.fukuoka.jp
miyama.fukuoka.jp
miyawaka.fukuoka.jp
mizumaki.fukuoka.jp
munakata.fukuoka.jp
nakagawa.fukuoka.jp
nakama.fukuoka.jp
nishi.fukuoka.jp
nogata.fukuoka.jp
ogori.fukuoka.jp
okagaki.fukuoka.jp
okawa.fukuoka.jp
oki.fukuoka.jp
omuta.fukuoka.jp
onga.fukuoka.jp
onojo.fukuoka.jp
oto.fukuoka.jp
saigawa.fukuoka.jp
sasaguri.fukuoka.jp
shingu.fukuoka.jp
shinyoshitomi.fukuoka.jp
shonai.fukuoka.jp
soeda.fukuoka.jp
sue.fukuoka.jp
tachiarai.fukuoka.jp
tagawa.fukuoka.jp
takata.fukuoka.jp
toho.fukuoka.jp
toyotsu.fukuoka.jp
tsuiki.fukuoka.jp
ukiha.fukuoka.jp
umi.fukuoka.jp
usui.fukuoka.jp
yamada.fukuoka.jp
yame.fukuoka.jp
yanagawa.fukuoka.jp
yukuhashi.fukuoka.jp
aizubange.fukushima.jp
aizumisato.fukushima.jp
aizuwakamatsu.fukushima.jp
asakawa.fukushima.jp
bandai.fukushima.jp
date.fukushima.jp
fukushima.fukushima.jp
furudono.fukushima.jp
futaba.fukushima.jp
hanawa.fukushima.jp
higashi.fukushima.jp
hirata.fukushima.jp
hirono.fukushima.jp
iitate.fukushima.jp
inawashiro.fukushima.jp
ishikawa.fukushima.jp
iwaki.fukushima.jp
izumizaki.fukushima.jp
kagamiishi.fukushima.jp
kaneyama.fukushima.jp
kawamata.fukushima.jp
kitakata.fukushima.jp
kitashiobara.fukushima.jp
koori.fukushima.jp
koriyama.fukushima.jp
kunimi.fukushima.jp
miharu.fukushima.jp
mishima.fukushima.jp
namie.fukushima.jp
nango.fukushima.jp
nishiaizu.fukushima.jp
nishigo.fukushima.jp
okuma.fukushima.jp
omotego.fukushima.jp
ono.fukushima.jp
otama.fukushima.jp
samegawa.fukushima.jp
shimogo.fukushima.jp
shirakawa.fukushima.jp
showa.fukushima.jp
soma.fukushima.jp
sukagawa.fukushima.jp
taishin.fukushima.jp
tamakawa.fukushima.jp
tanagura.fukushima.jp
tenei.fukushima.jp
yabuki.fukushima.jp
yamato.fukushima.jp
yamatsuri.fukushima.jp
yanaizu.fukushima.jp
yugawa.fukushima.jp
anpachi.gifu.jp
ena.gifu.jp
gifu.gifu.jp
ginan.gifu.jp
godo.gifu.jp
gujo.gifu.jp
hashima.gifu.jp
hichiso.gifu.jp
hida.gifu.jp
higashishirakawa.gifu.jp
ibigawa.gifu.jp
ikeda.gifu.jp
kakamigahara.gifu.jp
kani.gifu.jp
kasahara.gifu.jp
kasamatsu.gifu.jp
kawaue.gifu.jp
kitagata.gifu.jp
mino.gifu.jp
minokamo.gifu.jp
mitake.gifu.jp
mizunami.gifu.jp
motosu.gifu.jp
nakatsugawa.gifu.jp
ogaki.gifu.jp
sakahogi.gifu.jp
seki.gifu.jp
sekigahara.gifu.jp
shirakawa.gifu.jp
tajimi.gifu.jp
takayama.gifu.jp
tarui.gifu.jp
toki.gifu.jp
tomika.gifu.jp
wanouchi.gifu.jp
yamagata.gifu.jp
yaotsu.gifu.jp
yoro.gifu.jp
annaka.gunma.jp
chiyoda.gunma.jp
fujioka.gunma.jp
higashiagatsuma.gunma.jp
isesaki.gunma.jp
itakura.gunma.jp
kanna.gunma.jp
kanra.gunma.jp
katashina.gunma.jp
kawaba.gunma.jp
kiryu.gunma.jp
kusatsu.gunma.jp
maebashi.gunma.jp
meiwa.gunma.jp
midori.gunma.jp
minakami.gunma.jp
naganohara.gunma.jp
nakanojo.gunma.jp
nanmoku.gunma.jp
numata.gunma.jp
oizumi.gunma.jp
ora.gunma.jp
ota.gunma.jp
shibukawa.gunma.jp
shimonita.gunma.jp
shinto.gunma.jp
showa.gunma.jp
takasaki.gunma.jp
takayama.gunma.jp
tamamura.gunma.jp
tatebayashi.gunma.jp
tomioka.gunma.jp
tsukiyono.gunma.jp
tsumagoi.gunma.jp
ueno.gunma.jp
yoshioka.gunma.jp
asaminami.hiroshima.jp
daiwa.hiroshima.jp
etajima.hiroshima.jp
fuchu.hiroshima.jp
fukuyama.hiroshima.jp
hatsukaichi.hiroshima.jp
higashihiroshima.hiroshima.jp
hongo.hiroshima.jp
jinsekikogen.hiroshima.jp
kaita.hiroshima.jp
kui.hiroshima.jp
kumano.hiroshima.jp
kure.hiroshima.jp
mihara.hiroshima.jp
miyoshi.hiroshima.jp
naka.hiroshima.jp
onomichi.hiroshima.jp
osakikamijima.hiroshima.jp
otake.hiroshima.jp
saka.hiroshima.jp
sera.hiroshima.jp
seranishi.hiroshima.jp
shinichi.hiroshima.jp
shobara.hiroshima.jp
takehara.hiroshima.jp
abashiri.hokkaido.jp
abira.hokkaido.jp
aibetsu.hokkaido.jp
akabira.hokkaido.jp
akkeshi.hokkaido.jp
asahikawa.hokkaido.jp
ashibetsu.hokkaido.jp
ashoro.hokkaido.jp
assabu.hokkaido.jp
atsuma.hokkaido.jp
bibai.hokkaido.jp
biei.hokkaido.jp
bifuka.hokkaido.jp
bihoro.hokkaido.jp
biratori.hokkaido.jp
chippubetsu.hokkaido.jp
chitose.hokkaido.jp
date.hokkaido.jp
ebetsu.hokkaido.jp
embetsu.hokkaido.jp
eniwa.hokkaido.jp
erimo.hokkaido.jp
esan.hokkaido.jp
esashi.hokkaido.jp
fukagawa.hokkaido.jp
fukushima.hokkaido.jp
furano.hokkaido.jp
furubira.hokkaido.jp
haboro.hokkaido.jp
hakodate.hokkaido.jp
hamatonbetsu.hokkaido.jp
hidaka.hokkaido.jp
higashikagura.hokkaido.jp
higashikawa.hokkaido.jp
hiroo.hokkaido.jp
hokuryu.hokkaido.jp
hokuto.hokkaido.jp
honbetsu.hokkaido.jp
horokanai.hokkaido.jp
horonobe.hokkaido.jp
ikeda.hokkaido.jp
imakane.hokkaido.jp
ishikari.hokkaido.jp
iwamizawa.hokkaido.jp
iwanai.hokkaido.jp
kamifurano.hokkaido.jp
kamikawa.hokkaido.jp
kamishihoro.hokkaido.jp
kamisunagawa.hokkaido.jp
kamoenai.hokkaido.jp
kayabe.hokkaido.jp
kembuchi.hokkaido.jp
kikonai.hokkaido.jp
kimobetsu.hokkaido.jp
kitahiroshima.hokkaido.jp
kitami.hokkaido.jp
kiyosato.hokkaido.jp
koshimizu.hokkaido.jp
kunneppu.hokkaido.jp
kuriyama.hokkaido.jp
kuromatsunai.hokkaido.jp
kushiro.hokkaido.jp
kutchan.hokkaido.jp
kyowa.hokkaido.jp
mashike.hokkaido.jp
matsumae.hokkaido.jp
mikasa.hokkaido.jp
minamifurano.hokkaido.jp
mombetsu.hokkaido.jp
moseushi.hokkaido.jp
mukawa.hokkaido.jp
muroran.hokkaido.jp
naie.hokkaido.jp
nakagawa.hokkaido.jp
nakasatsunai.hokkaido.jp
nakatombetsu.hokkaido.jp
nanae.hokkaido.jp
nanporo.hokkaido.jp
nayoro.hokkaido.jp
nemuro.hokkaido.jp
niikappu.hokkaido.jp
niki.hokkaido.jp
nishiokoppe.hokkaido.jp
noboribetsu.hokkaido.jp
numata.hokkaido.jp
obihiro.hokkaido.jp
obira.hokkaido.jp
oketo.hokkaido.jp
okoppe.hokkaido.jp
otaru.hokkaido.jp
otobe.hokkaido.jp
otofuke.hokkaido.jp
otoineppu.hokkaido.jp
oumu.hokkaido.jp
ozora.hokkaido.jp
pippu.hokkaido.jp
rankoshi.hokkaido.jp
rebun.hokkaido.jp
rikubetsu.hokkaido.jp
rishiri.hokkaido.jp
rishirifuji.hokkaido.jp
saroma.hokkaido.jp
sarufutsu.hokkaido.jp
shakotan.hokkaido.jp
shari.hokkaido.jp
shibecha.hokkaido.jp
shibetsu.hokkaido.jp
shikabe.hokkaido.jp
shikaoi.hokkaido.jp
shimamaki.hokkaido.jp
shimizu.hokkaido.jp
shimokawa.hokkaido.jp
shinshinotsu.hokkaido.jp
shintoku.hokkaido.jp
shiranuka.hokkaido.jp
shiraoi.hokkaido.jp
shiriuchi.hokkaido.jp
sobetsu.hokkaido.jp
sunagawa.hokkaido.jp
taiki.hokkaido.jp
takasu.hokkaido.jp
takikawa.hokkaido.jp
takinoue.hokkaido.jp
teshikaga.hokkaido.jp
tobetsu.hokkaido.jp
tohma.hokkaido.jp
tomakomai.hokkaido.jp
tomari.hokkaido.jp
toya.hokkaido.jp
toyako.hokkaido.jp
toyotomi.hokkaido.jp
toyoura.hokkaido.jp
tsubetsu.hokkaido.jp
tsukigata.hokkaido.jp
urakawa.hokkaido.jp
urausu.hokkaido.jp
uryu.hokkaido.jp
utashinai.hokkaido.jp
wakkanai.hokkaido.jp
wassamu.hokkaido.jp
yakumo.hokkaido.jp
yoichi.hokkaido.jp
aioi.hyogo.jp
akashi.hyogo.jp
ako.hyogo.jp
amagasaki.hyogo.jp
aogaki.hyogo.jp
asago.hyogo.jp
ashiya.hyogo.jp
awaji.hyogo.jp
fukusaki.hyogo.jp
goshiki.hyogo.jp
harima.hyogo.jp
himeji.hyogo.jp
ichikawa.hyogo.jp
inagawa.hyogo.jp
itami.hyogo.jp
kakogawa.hyogo.jp
kamigori.hyogo.jp
kamikawa.hyogo.jp
kasai.hyogo.jp
kasuga.hyogo.jp
kawanishi.hyogo.jp
miki.hyogo.jp
minamiawaji.hyogo.jp
nishinomiya.hyogo.jp
nishiwaki.hyogo.jp
ono.hyogo.jp
sanda.hyogo.jp
sannan.hyogo.jp
sasayama.hyogo.jp
sayo.hyogo.jp
shingu.hyogo.jp
shinonsen.hyogo.jp
shiso.hyogo.jp
sumoto.hyogo.jp
taishi.hyogo.jp
taka.hyogo.jp
takarazuka.hyogo.jp
takasago.hyogo.jp
takino.hyogo.jp
tamba.hyogo.jp
tatsuno.hyogo.jp
toyooka.hyogo.jp
yabu.hyogo.jp
yashiro.hyogo.jp
yoka.hyogo.jp
yokawa.hyogo.jp
ami.ibaraki.jp
asahi.ibaraki.jp
bando.ibaraki.jp
chikusei.ibaraki.jp
daigo.ibaraki.jp
fujishiro.ibaraki.jp
hitachi.ibaraki.jp
hitachinaka.ibaraki.jp
hitachiomiya.ibaraki.jp
hitachiota.ibaraki.jp
ibaraki.ibaraki.jp
ina.ibaraki.jp
inashiki.ibaraki.jp
itako.ibaraki.jp
iwama.ibaraki.jp
joso.ibaraki.jp
kamisu.ibaraki.jp
kasama.ibaraki.jp
kashima.ibaraki.jp
kasumigaura.ibaraki.jp
koga.ibaraki.jp
miho.ibaraki.jp
mito.ibaraki.jp
moriya.ibaraki.jp
naka.ibaraki.jp
namegata.ibaraki.jp
oarai.ibaraki.jp
ogawa.ibaraki.jp
omitama.ibaraki.jp
ryugasaki.ibaraki.jp
sakai.ibaraki.jp
sakuragawa.ibaraki.jp
shimodate.ibaraki.jp
shimotsuma.ibaraki.jp
shirosato.ibaraki.jp
sowa.ibaraki.jp
suifu.ibaraki.jp
takahagi.ibaraki.jp
tamatsukuri.ibaraki.jp
tokai.ibaraki.jp
tomobe.ibaraki.jp
tone.ibaraki.jp
toride.ibaraki.jp
tsuchiura.ibaraki.jp
tsukuba.ibaraki.jp
uchihara.ibaraki.jp
ushiku.ibaraki.jp
yachiyo.ibaraki.jp
yamagata.ibaraki.jp
yawara.ibaraki.jp
yuki.ibaraki.jp
anamizu.ishikawa.jp
hakui.ishikawa.jp
hakusan.ishikawa.jp
kaga.ishikawa.jp
kahoku.ishikawa.jp
kanazawa.ishikawa.jp
kawakita.ishikawa.jp
komatsu.ishikawa.jp
nakanoto.ishikawa.jp
nanao.ishikawa.jp
nomi.ishikawa.jp
nonoichi.ishikawa.jp
noto.ishikawa.jp
shika.ishikawa.jp
suzu.ishikawa.jp
tsubata.ishikawa.jp
tsurugi.ishikawa.jp
uchinada.ishikawa.jp
wajima.ishikawa.jp
fudai.iwate.jp
fujisawa.iwate.jp
hanamaki.iwate.jp
hiraizumi.iwate.jp
hirono.iwate.jp
ichinohe.iwate.jp
ichinoseki.iwate.jp
iwaizumi.iwate.jp
iwate.iwate.jp
joboji.iwate.jp
kamaishi.iwate.jp
kanegasaki.iwate.jp
karumai.iwate.jp
kawai.iwate.jp
kitakami.iwate.jp
kuji.iwate.jp
kunohe.iwate.jp
kuzumaki.iwate.jp
miyako.iwate.jp
mizusawa.iwate.jp
morioka.iwate.jp
ninohe.iwate.jp
noda.iwate.jp
ofunato.iwate.jp
oshu.iwate.jp
otsuchi.iwate.jp
rikuzentakata.iwate.jp
shiwa.iwate.jp
shizukuishi.iwate.jp
sumita.iwate.jp
tanohata.iwate.jp
tono.iwate.jp
yahaba.iwate.jp
yamada.iwate.jp
ayagawa.kagawa.jp
higashikagawa.kagawa.jp
kanonji.kagawa.jp
kotohira.kagawa.jp
manno.kagawa.jp
marugame.kagawa.jp
mitoyo.kagawa.jp
naoshima.kagawa.jp
sanuki.kagawa.jp
tadotsu.kagawa.jp
takamatsu.kagawa.jp
tonosho.kagawa.jp
uchinomi.kagawa.jp
utazu.kagawa.jp
zentsuji.kagawa.jp
akune.kagoshima.jp
amami.kagoshima.jp
hioki.kagoshima.jp
isa.kagoshima.jp
isen.kagoshima.jp
izumi.kagoshima.jp
kagoshima.kagoshima.jp
kanoya.kagoshima.jp
kawanabe.kagoshima.jp
kinko.kagoshima.jp
kouyama.kagoshima.jp
makurazaki.kagoshima.jp
matsumoto.kagoshima.jp
minamitane.kagoshima.jp
nakatane.kagoshima.jp
nishinoomote.kagoshima.jp
satsumasendai.kagoshima.jp
soo.kagoshima.jp
tarumizu.kagoshima.jp
yusui.kagoshima.jp
aikawa.kanagawa.jp
atsugi.kanagawa.jp
ayase.kanagawa.jp
chigasaki.kanagawa.jp
ebina.kanagawa.jp
fujisawa.kanagawa.jp
hadano.kanagawa.jp
hakone.kanagawa.jp
hiratsuka.kanagawa.jp
isehara.kanagawa.jp
kaisei.kanagawa.jp
kamakura.kanagawa.jp
kiyokawa.kanagawa.jp
matsuda.kanagawa.jp
minamiashigara.kanagawa.jp
miura.kanagawa.jp
nakai.kanagawa.jp
ninomiya.kanagawa.jp
odawara.kanagawa.jp
oi.kanagawa.jp
oiso.kanagawa.jp
sagamihara.kanagawa.jp
samukawa.kanagawa.jp
tsukui.kanagawa.jp
yamakita.kanagawa.jp
yamato.kanagawa.jp
yokosuka.kanagawa.jp
yugawara.kanagawa.jp
zama.kanagawa.jp
zushi.kanagawa.jp
aki.kochi.jp
geisei.kochi.jp
hidaka.kochi.jp
higashitsuno.kochi.jp
ino.kochi.jp
kagami.kochi.jp
kami.kochi.jp
kitagawa.kochi.jp
kochi.kochi.jp
mihara.kochi.jp
motoyama.kochi.jp
muroto.kochi.jp
nahari.kochi.jp
nakamura.kochi.jp
nankoku.kochi.jp
nishitosa.kochi.jp
niyodogawa.kochi.jp
ochi.kochi.jp
okawa.kochi.jp
otoyo.kochi.jp
otsuki.kochi.jp
sakawa.kochi.jp
sukumo.kochi.jp
susaki.kochi.jp
tosa.kochi.jp
tosashimizu.kochi.jp
toyo.kochi.jp
tsuno.kochi.jp
umaji.kochi.jp
yasuda.kochi.jp
yusuhara.kochi.jp
amakusa.kumamoto.jp
arao.kumamoto.jp
aso.kumamoto.jp
choyo.kumamoto.jp
gyokuto.kumamoto.jp
kamiamakusa.kumamoto.jp
kikuchi.kumamoto.jp
kumamoto.kumamoto.jp
mashiki.kumamoto.jp
mifune.kumamoto.jp
minamata.kumamoto.jp
minamioguni.kumamoto.jp
nagasu.kumamoto.jp
nishihara.kumamoto.jp
oguni.kumamoto.jp
ozu.kumamoto.jp
sumoto.kumamoto.jp
takamori.kumamoto.jp
uki.kumamoto.jp
uto.kumamoto.jp
yamaga.kumamoto.jp
yamato.kumamoto.jp
yatsushiro.kumamoto.jp
ayabe.kyoto.jp
fukuchiyama.kyoto.jp
higashiyama.kyoto.jp
ide.kyoto.jp
ine.kyoto.jp
joyo.kyoto.jp
kameoka.kyoto.jp
kamo.kyoto.jp
kita.kyoto.jp
kizu.kyoto.jp
kumiyama.kyoto.jp
kyotamba.kyoto.jp
kyotanabe.kyoto.jp
kyotango.kyoto.jp
maizuru.kyoto.jp
minami.kyoto.jp
minamiyamashiro.kyoto.jp
miyazu.kyoto.jp
muko.kyoto.jp
nagaokakyo.kyoto.jp
nakagyo.kyoto.jp
nantan.kyoto.jp
oyamazaki.kyoto.jp
sakyo.kyoto.jp
seika.kyoto.jp
tanabe.kyoto.jp
uji.kyoto.jp
ujitawara.kyoto.jp
wazuka.kyoto.jp
yamashina.kyoto.jp
yawata.kyoto.jp
asahi.mie.jp
inabe.mie.jp
ise.mie.jp
kameyama.mie.jp
kawagoe.mie.jp
kiho.mie.jp
kisosaki.mie.jp
kiwa.mie.jp
komono.mie.jp
kumano.mie.jp
kuwana.mie.jp
matsusaka.mie.jp
meiwa.mie.jp
mihama.mie.jp
minamiise.mie.jp
misugi.mie.jp
miyama.mie.jp
nabari.mie.jp
shima.mie.jp
suzuka.mie.jp
tado.mie.jp
taiki.mie.jp
taki.mie.jp
tamaki.mie.jp
toba.mie.jp
tsu.mie.jp
udono.mie.jp
ureshino.mie.jp
watarai.mie.jp
yokkaichi.mie.jp
furukawa.miyagi.jp
higashimatsushima.miyagi.jp
ishinomaki.miyagi.jp
iwanuma.miyagi.jp
kakuda.miyagi.jp
kami.miyagi.jp
kawasaki.miyagi.jp
marumori.miyagi.jp
matsushima.miyagi.jp
minamisanriku.miyagi.jp
misato.miyagi.jp
murata.miyagi.jp
natori.miyagi.jp
ogawara.miyagi.jp
ohira.miyagi.jp
onagawa.miyagi.jp
osaki.miyagi.jp
rifu.miyagi.jp
semine.miyagi.jp
shibata.miyagi.jp
shichikashuku.miyagi.jp
shikama.miyagi.jp
shiogama.miyagi.jp
shiroishi.miyagi.jp
tagajo.miyagi.jp
taiwa.miyagi.jp
tome.miyagi.jp
tomiya.miyagi.jp
wakuya.miyagi.jp
watari.miyagi.jp
yamamoto.miyagi.jp
zao.miyagi.jp
aya.miyazaki.jp
ebino.miyazaki.jp
gokase.miyazaki.jp
hyuga.miyazaki.jp
kadogawa.miyazaki.jp
kawaminami.miyazaki.jp
kijo.miyazaki.jp
kitagawa.miyazaki.jp
kitakata.miyazaki.jp
kitaura.miyazaki.jp
kobayashi.miyazaki.jp
kunitomi.miyazaki.jp
kushima.miyazaki.jp
mimata.miyazaki.jp
miyakonojo.miyazaki.jp
miyazaki.miyazaki.jp
morotsuka.miyazaki.jp
nichinan.miyazaki.jp
nishimera.miyazaki.jp
nobeoka.miyazaki.jp
saito.miyazaki.jp
shiiba.miyazaki.jp
shintomi.miyazaki.jp
takaharu.miyazaki.jp
takanabe.miyazaki.jp
takazaki.miyazaki.jp
tsuno.miyazaki.jp
achi.nagano.jp
agematsu.nagano.jp
anan.nagano.jp
aoki.nagano.jp
asahi.nagano.jp
azumino.nagano.jp
chikuhoku.nagano.jp
chikuma.nagano.jp
chino.nagano.jp
fujimi.nagano.jp
hakuba.nagano.jp
hara.nagano.jp
hiraya.nagano.jp
iida.nagano.jp
iijima.nagano.jp
iiyama.nagano.jp
iizuna.nagano.jp
ikeda.nagano.jp
ikusaka.nagano.jp
ina.nagano.jp
karuizawa.nagano.jp
kawakami.nagano.jp
kiso.nagano.jp
kisofukushima.nagano.jp
kitaaiki.nagano.jp
komagane.nagano.jp
komoro.nagano.jp
matsukawa.nagano.jp
matsumoto.nagano.jp
miasa.nagano.jp
minamiaiki.nagano.jp
minamimaki.nagano.jp
minamiminowa.nagano.jp
minowa.nagano.jp
miyada.nagano.jp
miyota.nagano.jp
mochizuki.nagano.jp
nagano.nagano.jp
nagawa.nagano.jp
nagiso.nagano.jp
nakagawa.nagano.jp
nakano.nagano.jp
nozawaonsen.nagano.jp
obuse.nagano.jp
ogawa.nagano.jp
okaya.nagano.jp
omachi.nagano.jp
omi.nagano.jp
ookuwa.nagano.jp
ooshika.nagano.jp
otaki.nagano.jp
otari.nagano.jp
sakae.nagano.jp
sakaki.nagano.jp
saku.nagano.jp
sakuho.nagano.jp
shimosuwa.nagano.jp
shinanomachi.nagano.jp
shiojiri.nagano.jp
suwa.nagano.jp
suzaka.nagano.jp
takagi.nagano.jp
takamori.nagano.jp
takayama.nagano.jp
tateshina.nagano.jp
tatsuno.nagano.jp
togakushi.nagano.jp
togura.nagano.jp
tomi.nagano.jp
ueda.nagano.jp
wada.nagano.jp
yamagata.nagano.jp
yamanouchi.nagano.jp
yasaka.nagano.jp
yasuoka.nagano.jp
chijiwa.nagasaki.jp
futsu.nagasaki.jp
goto.nagasaki.jp
hasami.nagasaki.jp
hirado.nagasaki.jp
iki.nagasaki.jp
isahaya.nagasaki.jp
kawatana.nagasaki.jp
kuchinotsu.nagasaki.jp
matsuura.nagasaki.jp
nagasaki.nagasaki.jp
obama.nagasaki.jp
omura.nagasaki.jp
oseto.nagasaki.jp
saikai.nagasaki.jp
sasebo.nagasaki.jp
seihi.nagasaki.jp
shimabara.nagasaki.jp
shinkamigoto.nagasaki.jp
togitsu.nagasaki.jp
tsushima.nagasaki.jp
unzen.nagasaki.jp
ando.nara.jp
gose.nara.jp
heguri.nara.jp
higashiyoshino.nara.jp
ikaruga.nara.jp
ikoma.nara.jp
kamikitayama.nara.jp
kanmaki.nara.jp
kashiba.nara.jp
kashihara.nara.jp
katsuragi.nara.jp
kawai.nara.jp
kawakami.nara.jp
kawanishi.nara.jp
koryo.nara.jp
kurotaki.nara.jp
mitsue.nara.jp
miyake.nara.jp
nara.nara.jp
nosegawa.nara.jp
oji.nara.jp
ouda.nara.jp
oyodo.nara.jp
sakurai.nara.jp
sango.nara.jp
shimoichi.nara.jp
shimokitayama.nara.jp
shinjo.nara.jp
soni.nara.jp
takatori.nara.jp
tawaramoto.nara.jp
tenkawa.nara.jp
tenri.nara.jp
uda.nara.jp
yamatokoriyama.nara.jp
yamatotakada.nara.jp
yamazoe.nara.jp
yoshino.nara.jp
aga.niigata.jp
agano.niigata.jp
gosen.niigata.jp
itoigawa.niigata.jp
izumozaki.niigata.jp
joetsu.niigata.jp
kamo.niigata.jp
kariwa.niigata.jp
kashiwazaki.niigata.jp
minamiuonuma.niigata.jp
mitsuke.niigata.jp
muika.niigata.jp
murakami.niigata.jp
myoko.niigata.jp
nagaoka.niigata.jp
niigata.niigata.jp
ojiya.niigata.jp
omi.niigata.jp
sado.niigata.jp
sanjo.niigata.jp
seiro.niigata.jp
seirou.niigata.jp
sekikawa.niigata.jp
shibata.niigata.jp
tagami.niigata.jp
tainai.niigata.jp
tochio.niigata.jp
tokamachi.niigata.jp
tsubame.niigata.jp
tsunan.niigata.jp
uonuma.niigata.jp
yahiko.niigata.jp
yoita.niigata.jp
yuzawa.niigata.jp
beppu.oita.jp
bungoono.oita.jp
bungotakada.oita.jp
hasama.oita.jp
hiji.oita.jp
himeshima.oita.jp
hita.oita.jp
kamitsue.oita.jp
kokonoe.oita.jp
kuju.oita.jp
kunisaki.oita.jp
kusu.oita.jp
oita.oita.jp
saiki.oita.jp
taketa.oita.jp
tsukumi.oita.jp
usa.oita.jp
usuki.oita.jp
yufu.oita.jp
akaiwa.okayama.jp
asakuchi.okayama.jp
bizen.okayama.jp
hayashima.okayama.jp
ibara.okayama.jp
kagamino.okayama.jp
kasaoka.okayama.jp
kibichuo.okayama.jp
kumenan.okayama.jp
kurashiki.okayama.jp
maniwa.okayama.jp
misaki.okayama.jp
nagi.okayama.jp
niimi.okayama.jp
nishiawakura.okayama.jp
okayama.okayama.jp
satosho.okayama.jp
setouchi.okayama.jp
shinjo.okayama.jp
shoo.okayama.jp
soja.okayama.jp
takahashi.okayama.jp
tamano.okayama.jp
tsuyama.okayama.jp
wake.okayama.jp
yakage.okayama.jp
aguni.okinawa.jp
ginowan.okinawa.jp
ginoza.okinawa.jp
gushikami.okinawa.jp
haebaru.okinawa.jp
higashi.okinawa.jp
hirara.okinawa.jp
iheya.okinawa.jp
ishigaki.okinawa.jp
ishikawa.okinawa.jp
itoman.okinawa.jp
izena.okinawa.jp
kadena.okinawa.jp
kin.okinawa.jp
kitadaito.okinawa.jp
kitanakagusuku.okinawa.jp
kumejima.okinawa.jp
kunigami.okinawa.jp
minamidaito.okinawa.jp
motobu.okinawa.jp
nago.okinawa.jp
naha.okinawa.jp
nakagusuku.okinawa.jp
nakijin.okinawa.jp
nanjo.okinawa.jp
nishihara.okinawa.jp
ogimi.okinawa.jp
okinawa.okinawa.jp
onna.okinawa.jp
shimoji.okinawa.jp
taketomi.okinawa.jp
tarama.okinawa.jp
tokashiki.okinawa.jp
tomigusuku.okinawa.jp
tonaki.okinawa.jp
urasoe.okinawa.jp
uruma.okinawa.jp
yaese.okinawa.jp
yomitan.okinawa.jp
yonabaru.okinawa.jp
yonaguni.okinawa.jp
zamami.okinawa.jp
abeno.osaka.jp
chihayaakasaka.osaka.jp
chuo.osaka.jp
daito.osaka.jp
fujiidera.osaka.jp
habikino.osaka.jp
hannan.osaka.jp
higashiosaka.osaka.jp
higashisumiyoshi.osaka.jp
higashiyodogawa.osaka.jp
hirakata.osaka.jp
ibaraki.osaka.jp
ikeda.osaka.jp
izumi.osaka.jp
izumiotsu.osaka.jp
izumisano.osaka.jp
kadoma.osaka.jp
kaizuka.osaka.jp
kanan.osaka.jp
kashiwara.osaka.jp
katano.osaka.jp
kawachinagano.osaka.jp
kishiwada.osaka.jp
kita.osaka.jp
kumatori.osaka.jp
matsubara.osaka.jp
minato.osaka.jp
minoh.osaka.jp
misaki.osaka.jp
moriguchi.osaka.jp
neyagawa.osaka.jp
nishi.osaka.jp
nose.osaka.jp
osakasayama.osaka.jp
sakai.osaka.jp
sayama.osaka.jp
sennan.osaka.jp
settsu.osaka.jp
shijonawate.osaka.jp
shimamoto.osaka.jp
suita.osaka.jp
tadaoka.osaka.jp
taishi.osaka.jp
tajiri.osaka.jp
takaishi.osaka.jp
takatsuki.osaka.jp
tondabayashi.osaka.jp
toyonaka.osaka.jp
toyono.osaka.jp
yao.osaka.jp
ariake.saga.jp
arita.saga.jp
fukudomi.saga.jp
genkai.saga.jp
hamatama.saga.jp
hizen.saga.jp
imari.saga.jp
kamimine.saga.jp
kanzaki.saga.jp
karatsu.saga.jp
kashima.saga.jp
kitagata.saga.jp
kitahata.saga.jp
kiyama.saga.jp
kouhoku.saga.jp
kyuragi.saga.jp
nishiarita.saga.jp
ogi.saga.jp
omachi.saga.jp
ouchi.saga.jp
saga.saga.jp
shiroishi.saga.jp
taku.saga.jp
tara.saga.jp
tosu.saga.jp
yoshinogari.saga.jp
arakawa.saitama.jp
asaka.saitama.jp
chichibu.saitama.jp
fujimi.saitama.jp
fujimino.saitama.jp
fukaya.saitama.jp
hanno.saitama.jp
hanyu.saitama.jp
hasuda.saitama.jp
hatogaya.saitama.jp
hatoyama.saitama.jp
hidaka.saitama.jp
higashichichibu.saitama.jp
higashimatsuyama.saitama.jp
honjo.saitama.jp
ina.saitama.jp
iruma.saitama.jp
iwatsuki.saitama.jp
kamiizumi.saitama.jp
kamikawa.saitama.jp
kamisato.saitama.jp
kasukabe.saitama.jp
kawagoe.saitama.jp
kawaguchi.saitama.jp
kawajima.saitama.jp
kazo.saitama.jp
kitamoto.saitama.jp
koshigaya.saitama.jp
kounosu.saitama.jp
kuki.saitama.jp
kumagaya.saitama.jp
matsubushi.saitama.jp
minano.saitama.jp
misato.saitama.jp
miyashiro.saitama.jp
miyoshi.saitama.jp
moroyama.saitama.jp
nagatoro.saitama.jp
namegawa.saitama.jp
niiza.saitama.jp
ogano.saitama.jp
ogawa.saitama.jp
ogose.saitama.jp
okegawa.saitama.jp
omiya.saitama.jp
otaki.saitama.jp
ranzan.saitama.jp
ryokami.saitama.jp
saitama.saitama.jp
sakado.saitama.jp
satte.saitama.jp
sayama.saitama.jp
shiki.saitama.jp
shiraoka.saitama.jp
soka.saitama.jp
sugito.saitama.jp
toda.saitama.jp
tokigawa.saitama.jp
tokorozawa.saitama.jp
tsurugashima.saitama.jp
urawa.saitama.jp
warabi.saitama.jp
yashio.saitama.jp
yokoze.saitama.jp
yono.saitama.jp
yorii.saitama.jp
yoshida.saitama.jp
yoshikawa.saitama.jp
yoshimi.saitama.jp
aisho.shiga.jp
gamo.shiga.jp
higashiomi.shiga.jp
hikone.shiga.jp
koka.shiga.jp
konan.shiga.jp
kosei.shiga.jp
koto.shiga.jp
kusatsu.shiga.jp
maibara.shiga.jp
moriyama.shiga.jp
nagahama.shiga.jp
nishiazai.shiga.jp
notogawa.shiga.jp
omihachiman.shiga.jp
otsu.shiga.jp
ritto.shiga.jp
ryuoh.shiga.jp
takashima.shiga.jp
takatsuki.shiga.jp
torahime.shiga.jp
toyosato.shiga.jp
yasu.shiga.jp
akagi.shimane.jp
ama.shimane.jp
gotsu.shimane.jp
hamada.shimane.jp
higashiizumo.shimane.jp
hikawa.shimane.jp
hikimi.shimane.jp
izumo.shimane.jp
kakinoki.shimane.jp
masuda.shimane.jp
matsue.shimane.jp
misato.shimane.jp
nishinoshima.shimane.jp
ohda.shimane.jp
okinoshima.shimane.jp
okuizumo.shimane.jp
shimane.shimane.jp
tamayu.shimane.jp
tsuwano.shimane.jp
unnan.shimane.jp
yakumo.shimane.jp
yasugi.shimane.jp
yatsuka.shimane.jp
arai.shizuoka.jp
atami.shizuoka.jp
fuji.shizuoka.jp
fujieda.shizuoka.jp
fujikawa.shizuoka.jp
fujinomiya.shizuoka.jp
fukuroi.shizuoka.jp
gotemba.shizuoka.jp
haibara.shizuoka.jp
hamamatsu.shizuoka.jp
higashiizu.shizuoka.jp
ito.shizuoka.jp
iwata.shizuoka.jp
izu.shizuoka.jp
izunokuni.shizuoka.jp
kakegawa.shizuoka.jp
kannami.shizuoka.jp
kawanehon.shizuoka.jp
kawazu.shizuoka.jp
kikugawa.shizuoka.jp
kosai.shizuoka.jp
makinohara.shizuoka.jp
matsuzaki.shizuoka.jp
minamiizu.shizuoka.jp
mishima.shizuoka.jp
morimachi.shizuoka.jp
nishiizu.shizuoka.jp
numazu.shizuoka.jp
omaezaki.shizuoka.jp
shimada.shizuoka.jp
shimizu.shizuoka.jp
shimoda.shizuoka.jp
shizuoka.shizuoka.jp
susono.shizuoka.jp
yaizu.shizuoka.jp
yoshida.shizuoka.jp
ashikaga.tochigi.jp
bato.tochigi.jp
haga.tochigi.jp
ichikai.tochigi.jp
iwafune.tochigi.jp
kaminokawa.tochigi.jp
kanuma.tochigi.jp
karasuyama.tochigi.jp
kuroiso.tochigi.jp
mashiko.tochigi.jp
mibu.tochigi.jp
moka.tochigi.jp
motegi.tochigi.jp
nasu.tochigi.jp
nasushiobara.tochigi.jp
nikko.tochigi.jp
nishikata.tochigi.jp
nogi.tochigi.jp
ohira.tochigi.jp
ohtawara.tochigi.jp
oyama.tochigi.jp
sakura.tochigi.jp
sano.tochigi.jp
shimotsuke.tochigi.jp
shioya.tochigi.jp
takanezawa.tochigi.jp
tochigi.tochigi.jp
tsuga.tochigi.jp
ujiie.tochigi.jp
utsunomiya.tochigi.jp
yaita.tochigi.jp
aizumi.tokushima.jp
anan.tokushima.jp
ichiba.tokushima.jp
itano.tokushima.jp
kainan.tokushima.jp
komatsushima.tokushima.jp
matsushige.tokushima.jp
mima.tokushima.jp
minami.tokushima.jp
miyoshi.tokushima.jp
mugi.tokushima.jp
nakagawa.tokushima.jp
naruto.tokushima.jp
sanagochi.tokushima.jp
shishikui.tokushima.jp
tokushima.tokushima.jp
wajiki.tokushima.jp
adachi.tokyo.jp
akiruno.tokyo.jp
akishima.tokyo.jp
aogashima.tokyo.jp
arakawa.tokyo.jp
bunkyo.tokyo.jp
chiyoda.tokyo.jp
chofu.tokyo.jp
chuo.tokyo.jp
edogawa.tokyo.jp
fuchu.tokyo.jp
fussa.tokyo.jp
hachijo.tokyo.jp
hachioji.tokyo.jp
hamura.tokyo.jp
higashikurume.tokyo.jp
higashimurayama.tokyo.jp
higashiyamato.tokyo.jp
hino.tokyo.jp
hinode.tokyo.jp
hinohara.tokyo.jp
inagi.tokyo.jp
itabashi.tokyo.jp
katsushika.tokyo.jp
kita.tokyo.jp
kiyose.tokyo.jp
kodaira.tokyo.jp
koganei.tokyo.jp
kokubunji.tokyo.jp
komae.tokyo.jp
koto.tokyo.jp
kouzushima.tokyo.jp
kunitachi.tokyo.jp
machida.tokyo.jp
meguro.tokyo.jp
minato.tokyo.jp
mitaka.tokyo.jp
mizuho.tokyo.jp
musashimurayama.tokyo.jp
musashino.tokyo.jp
nakano.tokyo.jp
nerima.tokyo.jp
ogasawara.tokyo.jp
okutama.tokyo.jp
ome.tokyo.jp
oshima.tokyo.jp
ota.tokyo.jp
setagaya.tokyo.jp
shibuya.tokyo.jp
shinagawa.tokyo.jp
shinjuku.tokyo.jp
suginami.tokyo.jp
sumida.tokyo.jp
tachikawa.tokyo.jp
taito.tokyo.jp
tama.tokyo.jp
toshima.tokyo.jp
chizu.tottori.jp
hino.tottori.jp
kawahara.tottori.jp
koge.tottori.jp
kotoura.tottori.jp
misasa.tottori.jp
nanbu.tottori.jp
nichinan.tottori.jp
sakaiminato.tottori.jp
tottori.tottori.jp
wakasa.tottori.jp
yazu.tottori.jp
yonago.tottori.jp
asahi.toyama.jp
fuchu.toyama.jp
fukumitsu.toyama.jp
funahashi.toyama.jp
himi.toyama.jp
imizu.toyama.jp
inami.toyama.jp
johana.toyama.jp
kamiichi.toyama.jp
kurobe.toyama.jp
nakaniikawa.toyama.jp
namerikawa.toyama.jp
nanto.toyama.jp
nyuzen.toyama.jp
oyabe.toyama.jp
taira.toyama.jp
takaoka.toyama.jp
tateyama.toyama.jp
toga.toyama.jp
tonami.toyama.jp
toyama.toyama.jp
unazuki.toyama.jp
uozu.toyama.jp
yamada.toyama.jp
arida.wakayama.jp
aridagawa.wakayama.jp
gobo.wakayama.jp
hashimoto.wakayama.jp
hidaka.wakayama.jp
hirogawa.wakayama.jp
inami.wakayama.jp
iwade.wakayama.jp
kainan.wakayama.jp
kamitonda.wakayama.jp
katsuragi.wakayama.jp
kimino.wakayama.jp
kinokawa.wakayama.jp
kitayama.wakayama.jp
koya.wakayama.jp
koza.wakayama.jp
kozagawa.wakayama.jp
kudoyama.wakayama.jp
kushimoto.wakayama.jp
mihama.wakayama.jp
misato.wakayama.jp
nachikatsuura.wakayama.jp
shingu.wakayama.jp
shirahama.wakayama.jp
taiji.wakayama.jp
tanabe.wakayama.jp
wakayama.wakayama.jp
yuasa.wakayama.jp
yura.wakayama.jp
asahi.yamagata.jp
funagata.yamagata.jp
higashine.yamagata.jp
iide.yamagata.jp
kahoku.yamagata.jp
kaminoyama.yamagata.jp
kaneyama.yamagata.jp
kawanishi.yamagata.jp
mamurogawa.yamagata.jp
mikawa.yamagata.jp
murayama.yamagata.jp
nagai.yamagata.jp
nakayama.yamagata.jp
nanyo.yamagata.jp
nishikawa.yamagata.jp
obanazawa.yamagata.jp
oe.yamagata.jp
oguni.yamagata.jp
ohkura.yamagata.jp
oishida.yamagata.jp
sagae.yamagata.jp
sakata.yamagata.jp
sakegawa.yamagata.jp
shinjo.yamagata.jp
shirataka.yamagata.jp
shonai.yamagata.jp
takahata.yamagata.jp
tendo.yamagata.jp
tozawa.yamagata.jp
tsuruoka.yamagata.jp
yamagata.yamagata.jp
yamanobe.yamagata.jp
yonezawa.yamagata.jp
yuza.yamagata.jp
abu.yamaguchi.jp
hagi.yamaguchi.jp
hikari.yamaguchi.jp
hofu.yamaguchi.jp
iwakuni.yamaguchi.jp
kudamatsu.yamaguchi.jp
mitou.yamaguchi.jp
nagato.yamaguchi.jp
oshima.yamaguchi.jp
shimonoseki.yamaguchi.jp
shunan.yamaguchi.jp
tabuse.yamaguchi.jp
tokuyama.yamaguchi.jp
toyota.yamaguchi.jp
ube.yamaguchi.jp
yuu.yamaguchi.jp
chuo.yamanashi.jp
doshi.yamanashi.jp
fuefuki.yamanashi.jp
fujikawa.yamanashi.jp
fujikawaguchiko.yamanashi.jp
fujiyoshida.yamanashi.jp
hayakawa.yamanashi.jp
hokuto.yamanashi.jp
ichikawamisato.yamanashi.jp
kai.yamanashi.jp
kofu.yamanashi.jp
koshu.yamanashi.jp
kosuge.yamanashi.jp
minami-alps.yamanashi.jp
minobu.yamanashi.jp
nakamichi.yamanashi.jp
nanbu.yamanashi.jp
narusawa.yamanashi.jp
nirasaki.yamanashi.jp
nishikatsura.yamanashi.jp
oshino.yamanashi.jp
otsuki.yamanashi.jp
showa.yamanashi.jp
tabayama.yamanashi.jp
tsuru.yamanashi.jp
uenohara.yamanashi.jp
yamanakako.yamanashi.jp
yamanashi.yamanashi.jp

// ke : http://www.kenic.or.ke/index.php/en/ke-domains/ke-domains
ke
ac.ke
co.ke
go.ke
info.ke
me.ke
mobi.ke
ne.ke
or.ke
sc.ke

// kg : http://www.domain.kg/dmn_n.html
kg
org.kg
net.kg
com.kg
edu.kg
gov.kg
mil.kg

// kh : http://www.mptc.gov.kh/dns_registration.htm
*.kh

// ki : http://www.ki/dns/index.html
ki
edu.ki
biz.ki
net.ki
org.ki
gov.ki
info.ki
com.ki

// km : https://en.wikipedia.org/wiki/.km
// http://www.domaine.km/documents/charte.doc
km
org.km
nom.km
gov.km
prd.km
tm.km
edu.km
mil.km
ass.km
com.km
// These are only mentioned as proposed suggestions at domaine.km, but
// https://en.wikipedia.org/wiki/.km says they're available for registration:
coop.km
asso.km
presse.km
medecin.km
notaires.km
pharmaciens.km
veterinaire.km
gouv.km

// kn : https://en.wikipedia.org/wiki/.kn
// http://www.dot.kn/domainRules.html
kn
net.kn
org.kn
edu.kn
gov.kn

// kp : http://www.kcce.kp/en_index.php
kp
com.kp
edu.kp
gov.kp
org.kp
rep.kp
tra.kp

// kr : https://en.wikipedia.org/wiki/.kr
// see also: http://domain.nida.or.kr/eng/registration.jsp
kr
ac.kr
co.kr
es.kr
go.kr
hs.kr
kg.kr
mil.kr
ms.kr
ne.kr
or.kr
pe.kr
re.kr
sc.kr
// kr geographical names
busan.kr
chungbuk.kr
chungnam.kr
daegu.kr
daejeon.kr
gangwon.kr
gwangju.kr
gyeongbuk.kr
gyeonggi.kr
gyeongnam.kr
incheon.kr
jeju.kr
jeonbuk.kr
jeonnam.kr
seoul.kr
ulsan.kr

// kw : https://www.nic.kw/policies/
// Confirmed by registry <nic.tech@citra.gov.kw>
kw
com.kw
edu.kw
emb.kw
gov.kw
ind.kw
net.kw
org.kw

// ky : http://www.icta.ky/da_ky_reg_dom.php
// Confirmed by registry <kysupport@perimeterusa.com> 2008-06-17
ky
edu.ky
gov.ky
com.ky
org.ky
net.ky

// kz : https://en.wikipedia.org/wiki/.kz
// see also: http://www.nic.kz/rules/index.jsp
kz
org.kz
edu.kz
net.kz
gov.kz
mil.kz
com.kz

// la : https://en.wikipedia.org/wiki/.la
// Submitted by registry <gavin.brown@nic.la>
la
int.la
net.la
info.la
edu.la
gov.la
per.la
com.la
org.la

// lb : https://en.wikipedia.org/wiki/.lb
// Submitted by registry <randy@psg.com>
lb
com.lb
edu.lb
gov.lb
net.lb
org.lb

// lc : https://en.wikipedia.org/wiki/.lc
// see also: http://www.nic.lc/rules.htm
lc
com.lc
net.lc
co.lc
org.lc
edu.lc
gov.lc

// li : https://en.wikipedia.org/wiki/.li
li

// lk : https://www.nic.lk/index.php/domain-registration/lk-domain-naming-structure
lk
gov.lk
sch.lk
net.lk
int.lk
com.lk
org.lk
edu.lk
ngo.lk
soc.lk
web.lk
ltd.lk
assn.lk
grp.lk
hotel.lk
ac.lk

// lr : http://psg.com/dns/lr/lr.txt
// Submitted by registry <randy@psg.com>
lr
com.lr
edu.lr
gov.lr
org.lr
net.lr

// ls : http://www.nic.ls/
// Confirmed by registry <lsadmin@nic.ls>
ls
ac.ls
biz.ls
co.ls
edu.ls
gov.ls
info.ls
net.ls
org.ls
sc.ls

// lt : https://en.wikipedia.org/wiki/.lt
lt
// gov.lt : http://www.gov.lt/index_en.php
gov.lt

// lu : http://www.dns.lu/en/
lu

// lv : http://www.nic.lv/DNS/En/generic.php
lv
com.lv
edu.lv
gov.lv
org.lv
mil.lv
id.lv
net.lv
asn.lv
conf.lv

// ly : http://www.nic.ly/regulations.php
ly
com.ly
net.ly
gov.ly
plc.ly
edu.ly
sch.ly
med.ly
org.ly
id.ly

// ma : https://en.wikipedia.org/wiki/.ma
// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf
ma
co.ma
net.ma
gov.ma
org.ma
ac.ma
press.ma

// mc : http://www.nic.mc/
mc
tm.mc
asso.mc

// md : https://en.wikipedia.org/wiki/.md
md

// me : https://en.wikipedia.org/wiki/.me
me
co.me
net.me
org.me
edu.me
ac.me
gov.me
its.me
priv.me

// mg : http://nic.mg/nicmg/?page_id=39
mg
org.mg
nom.mg
gov.mg
prd.mg
tm.mg
edu.mg
mil.mg
com.mg
co.mg

// mh : https://en.wikipedia.org/wiki/.mh
mh

// mil : https://en.wikipedia.org/wiki/.mil
mil

// mk : https://en.wikipedia.org/wiki/.mk
// see also: http://dns.marnet.net.mk/postapka.php
mk
com.mk
org.mk
net.mk
edu.mk
gov.mk
inf.mk
name.mk

// ml : http://www.gobin.info/domainname/ml-template.doc
// see also: https://en.wikipedia.org/wiki/.ml
ml
com.ml
edu.ml
gouv.ml
gov.ml
net.ml
org.ml
presse.ml

// mm : https://en.wikipedia.org/wiki/.mm
*.mm

// mn : https://en.wikipedia.org/wiki/.mn
mn
gov.mn
edu.mn
org.mn

// mo : http://www.monic.net.mo/
mo
com.mo
net.mo
org.mo
edu.mo
gov.mo

// mobi : https://en.wikipedia.org/wiki/.mobi
mobi

// mp : http://www.dot.mp/
// Confirmed by registry <dcamacho@saipan.com> 2008-06-17
mp

// mq : https://en.wikipedia.org/wiki/.mq
mq

// mr : https://en.wikipedia.org/wiki/.mr
mr
gov.mr

// ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf
ms
com.ms
edu.ms
gov.ms
net.ms
org.ms

// mt : https://www.nic.org.mt/go/policy
// Submitted by registry <help@nic.org.mt>
mt
com.mt
edu.mt
net.mt
org.mt

// mu : https://en.wikipedia.org/wiki/.mu
mu
com.mu
net.mu
org.mu
gov.mu
ac.mu
co.mu
or.mu

// museum : http://about.museum/naming/
// http://index.museum/
museum
academy.museum
agriculture.museum
air.museum
airguard.museum
alabama.museum
alaska.museum
amber.museum
ambulance.museum
american.museum
americana.museum
americanantiques.museum
americanart.museum
amsterdam.museum
and.museum
annefrank.museum
anthro.museum
anthropology.museum
antiques.museum
aquarium.museum
arboretum.museum
archaeological.museum
archaeology.museum
architecture.museum
art.museum
artanddesign.museum
artcenter.museum
artdeco.museum
arteducation.museum
artgallery.museum
arts.museum
artsandcrafts.museum
asmatart.museum
assassination.museum
assisi.museum
association.museum
astronomy.museum
atlanta.museum
austin.museum
australia.museum
automotive.museum
aviation.museum
axis.museum
badajoz.museum
baghdad.museum
bahn.museum
bale.museum
baltimore.museum
barcelona.museum
baseball.museum
basel.museum
baths.museum
bauern.museum
beauxarts.museum
beeldengeluid.museum
bellevue.museum
bergbau.museum
berkeley.museum
berlin.museum
bern.museum
bible.museum
bilbao.museum
bill.museum
birdart.museum
birthplace.museum
bonn.museum
boston.museum
botanical.museum
botanicalgarden.museum
botanicgarden.museum
botany.museum
brandywinevalley.museum
brasil.museum
bristol.museum
british.museum
britishcolumbia.museum
broadcast.museum
brunel.museum
brussel.museum
brussels.museum
bruxelles.museum
building.museum
burghof.museum
bus.museum
bushey.museum
cadaques.museum
california.museum
cambridge.museum
can.museum
canada.museum
capebreton.museum
carrier.museum
cartoonart.museum
casadelamoneda.museum
castle.museum
castres.museum
celtic.museum
center.museum
chattanooga.museum
cheltenham.museum
chesapeakebay.museum
chicago.museum
children.museum
childrens.museum
childrensgarden.museum
chiropractic.museum
chocolate.museum
christiansburg.museum
cincinnati.museum
cinema.museum
circus.museum
civilisation.museum
civilization.museum
civilwar.museum
clinton.museum
clock.museum
coal.museum
coastaldefence.museum
cody.museum
coldwar.museum
collection.museum
colonialwilliamsburg.museum
coloradoplateau.museum
columbia.museum
columbus.museum
communication.museum
communications.museum
community.museum
computer.museum
computerhistory.museum
comunicaÃ§Ãµes.museum
contemporary.museum
contemporaryart.museum
convent.museum
copenhagen.museum
corporation.museum
correios-e-telecomunicaÃ§Ãµes.museum
corvette.museum
costume.museum
countryestate.museum
county.museum
crafts.museum
cranbrook.museum
creation.museum
cultural.museum
culturalcenter.museum
culture.museum
cyber.museum
cymru.museum
dali.museum
dallas.museum
database.museum
ddr.museum
decorativearts.museum
delaware.museum
delmenhorst.museum
denmark.museum
depot.museum
design.museum
detroit.museum
dinosaur.museum
discovery.museum
dolls.museum
donostia.museum
durham.museum
eastafrica.museum
eastcoast.museum
education.museum
educational.museum
egyptian.museum
eisenbahn.museum
elburg.museum
elvendrell.museum
embroidery.museum
encyclopedic.museum
england.museum
entomology.museum
environment.museum
environmentalconservation.museum
epilepsy.museum
essex.museum
estate.museum
ethnology.museum
exeter.museum
exhibition.museum
family.museum
farm.museum
farmequipment.museum
farmers.museum
farmstead.museum
field.museum
figueres.museum
filatelia.museum
film.museum
fineart.museum
finearts.museum
finland.museum
flanders.museum
florida.museum
force.museum
fortmissoula.museum
fortworth.museum
foundation.museum
francaise.museum
frankfurt.museum
franziskaner.museum
freemasonry.museum
freiburg.museum
fribourg.museum
frog.museum
fundacio.museum
furniture.museum
gallery.museum
garden.museum
gateway.museum
geelvinck.museum
gemological.museum
geology.museum
georgia.museum
giessen.museum
glas.museum
glass.museum
gorge.museum
grandrapids.museum
graz.museum
guernsey.museum
halloffame.museum
hamburg.museum
handson.museum
harvestcelebration.museum
hawaii.museum
health.museum
heimatunduhren.museum
hellas.museum
helsinki.museum
hembygdsforbund.museum
heritage.museum
histoire.museum
historical.museum
historicalsociety.museum
historichouses.museum
historisch.museum
historisches.museum
history.museum
historyofscience.museum
horology.museum
house.museum
humanities.museum
illustration.museum
imageandsound.museum
indian.museum
indiana.museum
indianapolis.museum
indianmarket.museum
intelligence.museum
interactive.museum
iraq.museum
iron.museum
isleofman.museum
jamison.museum
jefferson.museum
jerusalem.museum
jewelry.museum
jewish.museum
jewishart.museum
jfk.museum
journalism.museum
judaica.museum
judygarland.museum
juedisches.museum
juif.museum
karate.museum
karikatur.museum
kids.museum
koebenhavn.museum
koeln.museum
kunst.museum
kunstsammlung.museum
kunstunddesign.museum
labor.museum
labour.museum
lajolla.museum
lancashire.museum
landes.museum
lans.museum
lÃ¤ns.museum
larsson.museum
lewismiller.museum
lincoln.museum
linz.museum
living.museum
livinghistory.museum
localhistory.museum
london.museum
losangeles.museum
louvre.museum
loyalist.museum
lucerne.museum
luxembourg.museum
luzern.museum
mad.museum
madrid.museum
mallorca.museum
manchester.museum
mansion.museum
mansions.museum
manx.museum
marburg.museum
maritime.museum
maritimo.museum
maryland.museum
marylhurst.museum
media.museum
medical.museum
medizinhistorisches.museum
meeres.museum
memorial.museum
mesaverde.museum
michigan.museum
midatlantic.museum
military.museum
mill.museum
miners.museum
mining.museum
minnesota.museum
missile.museum
missoula.museum
modern.museum
moma.museum
money.museum
monmouth.museum
monticello.museum
montreal.museum
moscow.museum
motorcycle.museum
muenchen.museum
muenster.museum
mulhouse.museum
muncie.museum
museet.museum
museumcenter.museum
museumvereniging.museum
music.museum
national.museum
nationalfirearms.museum
nationalheritage.museum
nativeamerican.museum
naturalhistory.museum
naturalhistorymuseum.museum
naturalsciences.museum
nature.museum
naturhistorisches.museum
natuurwetenschappen.museum
naumburg.museum
naval.museum
nebraska.museum
neues.museum
newhampshire.museum
newjersey.museum
newmexico.museum
newport.museum
newspaper.museum
newyork.museum
niepce.museum
norfolk.museum
north.museum
nrw.museum
nyc.museum
nyny.museum
oceanographic.museum
oceanographique.museum
omaha.museum
online.museum
ontario.museum
openair.museum
oregon.museum
oregontrail.museum
otago.museum
oxford.museum
pacific.museum
paderborn.museum
palace.museum
paleo.museum
palmsprings.museum
panama.museum
paris.museum
pasadena.museum
pharmacy.museum
philadelphia.museum
philadelphiaarea.museum
philately.museum
phoenix.museum
photography.museum
pilots.museum
pittsburgh.museum
planetarium.museum
plantation.museum
plants.museum
plaza.museum
portal.museum
portland.museum
portlligat.museum
posts-and-telecommunications.museum
preservation.museum
presidio.museum
press.museum
project.museum
public.museum
pubol.museum
quebec.museum
railroad.museum
railway.museum
research.museum
resistance.museum
riodejaneiro.museum
rochester.museum
rockart.museum
roma.museum
russia.museum
saintlouis.museum
salem.museum
salvadordali.museum
salzburg.museum
sandiego.museum
sanfrancisco.museum
santabarbara.museum
santacruz.museum
santafe.museum
saskatchewan.museum
satx.museum
savannahga.museum
schlesisches.museum
schoenbrunn.museum
schokoladen.museum
school.museum
schweiz.museum
science.museum
scienceandhistory.museum
scienceandindustry.museum
sciencecenter.museum
sciencecenters.museum
science-fiction.museum
sciencehistory.museum
sciences.museum
sciencesnaturelles.museum
scotland.museum
seaport.museum
settlement.museum
settlers.museum
shell.museum
sherbrooke.museum
sibenik.museum
silk.museum
ski.museum
skole.museum
society.museum
sologne.museum
soundandvision.museum
southcarolina.museum
southwest.museum
space.museum
spy.museum
square.museum
stadt.museum
stalbans.museum
starnberg.museum
state.museum
stateofdelaware.museum
station.museum
steam.museum
steiermark.museum
stjohn.museum
stockholm.museum
stpetersburg.museum
stuttgart.museum
suisse.museum
surgeonshall.museum
surrey.museum
svizzera.museum
sweden.museum
sydney.museum
tank.museum
tcm.museum
technology.museum
telekommunikation.museum
television.museum
texas.museum
textile.museum
theater.museum
time.museum
timekeeping.museum
topology.museum
torino.museum
touch.museum
town.museum
transport.museum
tree.museum
trolley.museum
trust.museum
trustee.museum
uhren.museum
ulm.museum
undersea.museum
university.museum
usa.museum
usantiques.museum
usarts.museum
uscountryestate.museum
usculture.museum
usdecorativearts.museum
usgarden.museum
ushistory.museum
ushuaia.museum
uslivinghistory.museum
utah.museum
uvic.museum
valley.museum
vantaa.museum
versailles.museum
viking.museum
village.museum
virginia.museum
virtual.museum
virtuel.museum
vlaanderen.museum
volkenkunde.museum
wales.museum
wallonie.museum
war.museum
washingtondc.museum
watchandclock.museum
watch-and-clock.museum
western.museum
westfalen.museum
whaling.museum
wildlife.museum
williamsburg.museum
windmill.museum
workshop.museum
york.museum
yorkshire.museum
yosemite.museum
youth.museum
zoological.museum
zoology.museum
×™×¨×•×©×œ×™×�.museum
Ð¸ÐºÐ¾Ð¼.museum

// mv : https://en.wikipedia.org/wiki/.mv
// "mv" included because, contra Wikipedia, google.mv exists.
mv
aero.mv
biz.mv
com.mv
coop.mv
edu.mv
gov.mv
info.mv
int.mv
mil.mv
museum.mv
name.mv
net.mv
org.mv
pro.mv

// mw : http://www.registrar.mw/
mw
ac.mw
biz.mw
co.mw
com.mw
coop.mw
edu.mw
gov.mw
int.mw
museum.mw
net.mw
org.mw

// mx : http://www.nic.mx/
// Submitted by registry <farias@nic.mx>
mx
com.mx
org.mx
gob.mx
edu.mx
net.mx

// my : http://www.mynic.my/
// Available strings: https://mynic.my/resources/domains/buying-a-domain/
my
biz.my
com.my
edu.my
gov.my
mil.my
name.my
net.my
org.my

// mz : http://www.uem.mz/
// Submitted by registry <antonio@uem.mz>
mz
ac.mz
adv.mz
co.mz
edu.mz
gov.mz
mil.mz
net.mz
org.mz

// na : http://www.na-nic.com.na/
// http://www.info.na/domain/
na
info.na
pro.na
name.na
school.na
or.na
dr.na
us.na
mx.na
ca.na
in.na
cc.na
tv.na
ws.na
mobi.na
co.na
com.na
org.na

// name : has 2nd-level tlds, but there's no list of them
name

// nc : http://www.cctld.nc/
nc
asso.nc
nom.nc

// ne : https://en.wikipedia.org/wiki/.ne
ne

// net : https://en.wikipedia.org/wiki/.net
net

// nf : https://en.wikipedia.org/wiki/.nf
nf
com.nf
net.nf
per.nf
rec.nf
web.nf
arts.nf
firm.nf
info.nf
other.nf
store.nf

// ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds
ng
com.ng
edu.ng
gov.ng
i.ng
mil.ng
mobi.ng
name.ng
net.ng
org.ng
sch.ng

// ni : http://www.nic.ni/
ni
ac.ni
biz.ni
co.ni
com.ni
edu.ni
gob.ni
in.ni
info.ni
int.ni
mil.ni
net.ni
nom.ni
org.ni
web.ni

// nl : https://en.wikipedia.org/wiki/.nl
//      https://www.sidn.nl/
//      ccTLD for the Netherlands
nl

// no : https://www.norid.no/en/om-domenenavn/regelverk-for-no/
// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/
// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/
// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/
// RSS feed: https://teknisk.norid.no/en/feed/
no
// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/
fhs.no
vgs.no
fylkesbibl.no
folkebibl.no
museum.no
idrett.no
priv.no
// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/
mil.no
stat.no
dep.no
kommune.no
herad.no
// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/
// counties
aa.no
ah.no
bu.no
fm.no
hl.no
hm.no
jan-mayen.no
mr.no
nl.no
nt.no
of.no
ol.no
oslo.no
rl.no
sf.no
st.no
svalbard.no
tm.no
tr.no
va.no
vf.no
// primary and lower secondary schools per county
gs.aa.no
gs.ah.no
gs.bu.no
gs.fm.no
gs.hl.no
gs.hm.no
gs.jan-mayen.no
gs.mr.no
gs.nl.no
gs.nt.no
gs.of.no
gs.ol.no
gs.oslo.no
gs.rl.no
gs.sf.no
gs.st.no
gs.svalbard.no
gs.tm.no
gs.tr.no
gs.va.no
gs.vf.no
// cities
akrehamn.no
Ã¥krehamn.no
algard.no
Ã¥lgÃ¥rd.no
arna.no
brumunddal.no
bryne.no
bronnoysund.no
brÃ¸nnÃ¸ysund.no
drobak.no
drÃ¸bak.no
egersund.no
fetsund.no
floro.no
florÃ¸.no
fredrikstad.no
hokksund.no
honefoss.no
hÃ¸nefoss.no
jessheim.no
jorpeland.no
jÃ¸rpeland.no
kirkenes.no
kopervik.no
krokstadelva.no
langevag.no
langevÃ¥g.no
leirvik.no
mjondalen.no
mjÃ¸ndalen.no
mo-i-rana.no
mosjoen.no
mosjÃ¸en.no
nesoddtangen.no
orkanger.no
osoyro.no
osÃ¸yro.no
raholt.no
rÃ¥holt.no
sandnessjoen.no
sandnessjÃ¸en.no
skedsmokorset.no
slattum.no
spjelkavik.no
stathelle.no
stavern.no
stjordalshalsen.no
stjÃ¸rdalshalsen.no
tananger.no
tranby.no
vossevangen.no
// communities
afjord.no
Ã¥fjord.no
agdenes.no
al.no
Ã¥l.no
alesund.no
Ã¥lesund.no
alstahaug.no
alta.no
Ã¡ltÃ¡.no
alaheadju.no
Ã¡laheadju.no
alvdal.no
amli.no
Ã¥mli.no
amot.no
Ã¥mot.no
andebu.no
andoy.no
andÃ¸y.no
andasuolo.no
ardal.no
Ã¥rdal.no
aremark.no
arendal.no
Ã¥s.no
aseral.no
Ã¥seral.no
asker.no
askim.no
askvoll.no
askoy.no
askÃ¸y.no
asnes.no
Ã¥snes.no
audnedaln.no
aukra.no
aure.no
aurland.no
aurskog-holand.no
aurskog-hÃ¸land.no
austevoll.no
austrheim.no
averoy.no
averÃ¸y.no
balestrand.no
ballangen.no
balat.no
bÃ¡lÃ¡t.no
balsfjord.no
bahccavuotna.no
bÃ¡hccavuotna.no
bamble.no
bardu.no
beardu.no
beiarn.no
bajddar.no
bÃ¡jddar.no
baidar.no
bÃ¡idÃ¡r.no
berg.no
bergen.no
berlevag.no
berlevÃ¥g.no
bearalvahki.no
bearalvÃ¡hki.no
bindal.no
birkenes.no
bjarkoy.no
bjarkÃ¸y.no
bjerkreim.no
bjugn.no
bodo.no
bodÃ¸.no
badaddja.no
bÃ¥dÃ¥ddjÃ¥.no
budejju.no
bokn.no
bremanger.no
bronnoy.no
brÃ¸nnÃ¸y.no
bygland.no
bykle.no
barum.no
bÃ¦rum.no
bo.telemark.no
bÃ¸.telemark.no
bo.nordland.no
bÃ¸.nordland.no
bievat.no
bievÃ¡t.no
bomlo.no
bÃ¸mlo.no
batsfjord.no
bÃ¥tsfjord.no
bahcavuotna.no
bÃ¡hcavuotna.no
dovre.no
drammen.no
drangedal.no
dyroy.no
dyrÃ¸y.no
donna.no
dÃ¸nna.no
eid.no
eidfjord.no
eidsberg.no
eidskog.no
eidsvoll.no
eigersund.no
elverum.no
enebakk.no
engerdal.no
etne.no
etnedal.no
evenes.no
evenassi.no
evenÃ¡Å¡Å¡i.no
evje-og-hornnes.no
farsund.no
fauske.no
fuossko.no
fuoisku.no
fedje.no
fet.no
finnoy.no
finnÃ¸y.no
fitjar.no
fjaler.no
fjell.no
flakstad.no
flatanger.no
flekkefjord.no
flesberg.no
flora.no
fla.no
flÃ¥.no
folldal.no
forsand.no
fosnes.no
frei.no
frogn.no
froland.no
frosta.no
frana.no
frÃ¦na.no
froya.no
frÃ¸ya.no
fusa.no
fyresdal.no
forde.no
fÃ¸rde.no
gamvik.no
gangaviika.no
gÃ¡Å‹gaviika.no
gaular.no
gausdal.no
gildeskal.no
gildeskÃ¥l.no
giske.no
gjemnes.no
gjerdrum.no
gjerstad.no
gjesdal.no
gjovik.no
gjÃ¸vik.no
gloppen.no
gol.no
gran.no
grane.no
granvin.no
gratangen.no
grimstad.no
grong.no
kraanghke.no
krÃ¥anghke.no
grue.no
gulen.no
hadsel.no
halden.no
halsa.no
hamar.no
hamaroy.no
habmer.no
hÃ¡bmer.no
hapmir.no
hÃ¡pmir.no
hammerfest.no
hammarfeasta.no
hÃ¡mmÃ¡rfeasta.no
haram.no
hareid.no
harstad.no
hasvik.no
aknoluokta.no
Ã¡kÅ‹oluokta.no
hattfjelldal.no
aarborte.no
haugesund.no
hemne.no
hemnes.no
hemsedal.no
heroy.more-og-romsdal.no
herÃ¸y.mÃ¸re-og-romsdal.no
heroy.nordland.no
herÃ¸y.nordland.no
hitra.no
hjartdal.no
hjelmeland.no
hobol.no
hobÃ¸l.no
hof.no
hol.no
hole.no
holmestrand.no
holtalen.no
holtÃ¥len.no
hornindal.no
horten.no
hurdal.no
hurum.no
hvaler.no
hyllestad.no
hagebostad.no
hÃ¦gebostad.no
hoyanger.no
hÃ¸yanger.no
hoylandet.no
hÃ¸ylandet.no
ha.no
hÃ¥.no
ibestad.no
inderoy.no
inderÃ¸y.no
iveland.no
jevnaker.no
jondal.no
jolster.no
jÃ¸lster.no
karasjok.no
karasjohka.no
kÃ¡rÃ¡Å¡johka.no
karlsoy.no
galsa.no
gÃ¡lsÃ¡.no
karmoy.no
karmÃ¸y.no
kautokeino.no
guovdageaidnu.no
klepp.no
klabu.no
klÃ¦bu.no
kongsberg.no
kongsvinger.no
kragero.no
kragerÃ¸.no
kristiansand.no
kristiansund.no
krodsherad.no
krÃ¸dsherad.no
kvalsund.no
rahkkeravju.no
rÃ¡hkkerÃ¡vju.no
kvam.no
kvinesdal.no
kvinnherad.no
kviteseid.no
kvitsoy.no
kvitsÃ¸y.no
kvafjord.no
kvÃ¦fjord.no
giehtavuoatna.no
kvanangen.no
kvÃ¦nangen.no
navuotna.no
nÃ¡vuotna.no
kafjord.no
kÃ¥fjord.no
gaivuotna.no
gÃ¡ivuotna.no
larvik.no
lavangen.no
lavagis.no
loabat.no
loabÃ¡t.no
lebesby.no
davvesiida.no
leikanger.no
leirfjord.no
leka.no
leksvik.no
lenvik.no
leangaviika.no
leaÅ‹gaviika.no
lesja.no
levanger.no
lier.no
lierne.no
lillehammer.no
lillesand.no
lindesnes.no
lindas.no
lindÃ¥s.no
lom.no
loppa.no
lahppi.no
lÃ¡hppi.no
lund.no
lunner.no
luroy.no
lurÃ¸y.no
luster.no
lyngdal.no
lyngen.no
ivgu.no
lardal.no
lerdal.no
lÃ¦rdal.no
lodingen.no
lÃ¸dingen.no
lorenskog.no
lÃ¸renskog.no
loten.no
lÃ¸ten.no
malvik.no
masoy.no
mÃ¥sÃ¸y.no
muosat.no
muosÃ¡t.no
mandal.no
marker.no
marnardal.no
masfjorden.no
meland.no
meldal.no
melhus.no
meloy.no
melÃ¸y.no
meraker.no
merÃ¥ker.no
moareke.no
moÃ¥reke.no
midsund.no
midtre-gauldal.no
modalen.no
modum.no
molde.no
moskenes.no
moss.no
mosvik.no
malselv.no
mÃ¥lselv.no
malatvuopmi.no
mÃ¡latvuopmi.no
namdalseid.no
aejrie.no
namsos.no
namsskogan.no
naamesjevuemie.no
nÃ¥Ã¥mesjevuemie.no
laakesvuemie.no
nannestad.no
narvik.no
narviika.no
naustdal.no
nedre-eiker.no
nes.akershus.no
nes.buskerud.no
nesna.no
nesodden.no
nesseby.no
unjarga.no
unjÃ¡rga.no
nesset.no
nissedal.no
nittedal.no
nord-aurdal.no
nord-fron.no
nord-odal.no
norddal.no
nordkapp.no
davvenjarga.no
davvenjÃ¡rga.no
nordre-land.no
nordreisa.no
raisa.no
rÃ¡isa.no
nore-og-uvdal.no
notodden.no
naroy.no
nÃ¦rÃ¸y.no
notteroy.no
nÃ¸tterÃ¸y.no
odda.no
oksnes.no
Ã¸ksnes.no
oppdal.no
oppegard.no
oppegÃ¥rd.no
orkdal.no
orland.no
Ã¸rland.no
orskog.no
Ã¸rskog.no
orsta.no
Ã¸rsta.no
os.hedmark.no
os.hordaland.no
osen.no
osteroy.no
osterÃ¸y.no
ostre-toten.no
Ã¸stre-toten.no
overhalla.no
ovre-eiker.no
Ã¸vre-eiker.no
oyer.no
Ã¸yer.no
oygarden.no
Ã¸ygarden.no
oystre-slidre.no
Ã¸ystre-slidre.no
porsanger.no
porsangu.no
porsÃ¡Å‹gu.no
porsgrunn.no
radoy.no
radÃ¸y.no
rakkestad.no
rana.no
ruovat.no
randaberg.no
rauma.no
rendalen.no
rennebu.no
rennesoy.no
rennesÃ¸y.no
rindal.no
ringebu.no
ringerike.no
ringsaker.no
rissa.no
risor.no
risÃ¸r.no
roan.no
rollag.no
rygge.no
ralingen.no
rÃ¦lingen.no
rodoy.no
rÃ¸dÃ¸y.no
romskog.no
rÃ¸mskog.no
roros.no
rÃ¸ros.no
rost.no
rÃ¸st.no
royken.no
rÃ¸yken.no
royrvik.no
rÃ¸yrvik.no
rade.no
rÃ¥de.no
salangen.no
siellak.no
saltdal.no
salat.no
sÃ¡lÃ¡t.no
sÃ¡lat.no
samnanger.no
sande.more-og-romsdal.no
sande.mÃ¸re-og-romsdal.no
sande.vestfold.no
sandefjord.no
sandnes.no
sandoy.no
sandÃ¸y.no
sarpsborg.no
sauda.no
sauherad.no
sel.no
selbu.no
selje.no
seljord.no
sigdal.no
siljan.no
sirdal.no
skaun.no
skedsmo.no
ski.no
skien.no
skiptvet.no
skjervoy.no
skjervÃ¸y.no
skierva.no
skiervÃ¡.no
skjak.no
skjÃ¥k.no
skodje.no
skanland.no
skÃ¥nland.no
skanit.no
skÃ¡nit.no
smola.no
smÃ¸la.no
snillfjord.no
snasa.no
snÃ¥sa.no
snoasa.no
snaase.no
snÃ¥ase.no
sogndal.no
sokndal.no
sola.no
solund.no
songdalen.no
sortland.no
spydeberg.no
stange.no
stavanger.no
steigen.no
steinkjer.no
stjordal.no
stjÃ¸rdal.no
stokke.no
stor-elvdal.no
stord.no
stordal.no
storfjord.no
omasvuotna.no
strand.no
stranda.no
stryn.no
sula.no
suldal.no
sund.no
sunndal.no
surnadal.no
sveio.no
svelvik.no
sykkylven.no
sogne.no
sÃ¸gne.no
somna.no
sÃ¸mna.no
sondre-land.no
sÃ¸ndre-land.no
sor-aurdal.no
sÃ¸r-aurdal.no
sor-fron.no
sÃ¸r-fron.no
sor-odal.no
sÃ¸r-odal.no
sor-varanger.no
sÃ¸r-varanger.no
matta-varjjat.no
mÃ¡tta-vÃ¡rjjat.no
sorfold.no
sÃ¸rfold.no
sorreisa.no
sÃ¸rreisa.no
sorum.no
sÃ¸rum.no
tana.no
deatnu.no
time.no
tingvoll.no
tinn.no
tjeldsund.no
dielddanuorri.no
tjome.no
tjÃ¸me.no
tokke.no
tolga.no
torsken.no
tranoy.no
tranÃ¸y.no
tromso.no
tromsÃ¸.no
tromsa.no
romsa.no
trondheim.no
troandin.no
trysil.no
trana.no
trÃ¦na.no
trogstad.no
trÃ¸gstad.no
tvedestrand.no
tydal.no
tynset.no
tysfjord.no
divtasvuodna.no
divttasvuotna.no
tysnes.no
tysvar.no
tysvÃ¦r.no
tonsberg.no
tÃ¸nsberg.no
ullensaker.no
ullensvang.no
ulvik.no
utsira.no
vadso.no
vadsÃ¸.no
cahcesuolo.no
Ä�Ã¡hcesuolo.no
vaksdal.no
valle.no
vang.no
vanylven.no
vardo.no
vardÃ¸.no
varggat.no
vÃ¡rggÃ¡t.no
vefsn.no
vaapste.no
vega.no
vegarshei.no
vegÃ¥rshei.no
vennesla.no
verdal.no
verran.no
vestby.no
vestnes.no
vestre-slidre.no
vestre-toten.no
vestvagoy.no
vestvÃ¥gÃ¸y.no
vevelstad.no
vik.no
vikna.no
vindafjord.no
volda.no
voss.no
varoy.no
vÃ¦rÃ¸y.no
vagan.no
vÃ¥gan.no
voagat.no
vagsoy.no
vÃ¥gsÃ¸y.no
vaga.no
vÃ¥gÃ¥.no
valer.ostfold.no
vÃ¥ler.Ã¸stfold.no
valer.hedmark.no
vÃ¥ler.hedmark.no

// np : http://www.mos.com.np/register.html
*.np

// nr : http://cenpac.net.nr/dns/index.html
// Submitted by registry <technician@cenpac.net.nr>
nr
biz.nr
info.nr
gov.nr
edu.nr
org.nr
net.nr
com.nr

// nu : https://en.wikipedia.org/wiki/.nu
nu

// nz : https://en.wikipedia.org/wiki/.nz
// Submitted by registry <jay@nzrs.net.nz>
nz
ac.nz
co.nz
cri.nz
geek.nz
gen.nz
govt.nz
health.nz
iwi.nz
kiwi.nz
maori.nz
mil.nz
mÄ�ori.nz
net.nz
org.nz
parliament.nz
school.nz

// om : https://en.wikipedia.org/wiki/.om
om
co.om
com.om
edu.om
gov.om
med.om
museum.om
net.om
org.om
pro.om

// onion : https://tools.ietf.org/html/rfc7686
onion

// org : https://en.wikipedia.org/wiki/.org
org

// pa : http://www.nic.pa/
// Some additional second level "domains" resolve directly as hostnames, such as
// pannet.pa, so we add a rule for "pa".
pa
ac.pa
gob.pa
com.pa
org.pa
sld.pa
edu.pa
net.pa
ing.pa
abo.pa
med.pa
nom.pa

// pe : https://www.nic.pe/InformeFinalComision.pdf
pe
edu.pe
gob.pe
nom.pe
mil.pe
org.pe
com.pe
net.pe

// pf : http://www.gobin.info/domainname/formulaire-pf.pdf
pf
com.pf
org.pf
edu.pf

// pg : https://en.wikipedia.org/wiki/.pg
*.pg

// ph : http://www.domains.ph/FAQ2.asp
// Submitted by registry <jed@email.com.ph>
ph
com.ph
net.ph
org.ph
gov.ph
edu.ph
ngo.ph
mil.ph
i.ph

// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK
pk
com.pk
net.pk
edu.pk
org.pk
fam.pk
biz.pk
web.pk
gov.pk
gob.pk
gok.pk
gon.pk
gop.pk
gos.pk
info.pk

// pl http://www.dns.pl/english/index.html
// Submitted by registry
pl
com.pl
net.pl
org.pl
// pl functional domains (http://www.dns.pl/english/index.html)
aid.pl
agro.pl
atm.pl
auto.pl
biz.pl
edu.pl
gmina.pl
gsm.pl
info.pl
mail.pl
miasta.pl
media.pl
mil.pl
nieruchomosci.pl
nom.pl
pc.pl
powiat.pl
priv.pl
realestate.pl
rel.pl
sex.pl
shop.pl
sklep.pl
sos.pl
szkola.pl
targi.pl
tm.pl
tourism.pl
travel.pl
turystyka.pl
// Government domains
gov.pl
ap.gov.pl
ic.gov.pl
is.gov.pl
us.gov.pl
kmpsp.gov.pl
kppsp.gov.pl
kwpsp.gov.pl
psp.gov.pl
wskr.gov.pl
kwp.gov.pl
mw.gov.pl
ug.gov.pl
um.gov.pl
umig.gov.pl
ugim.gov.pl
upow.gov.pl
uw.gov.pl
starostwo.gov.pl
pa.gov.pl
po.gov.pl
psse.gov.pl
pup.gov.pl
rzgw.gov.pl
sa.gov.pl
so.gov.pl
sr.gov.pl
wsa.gov.pl
sko.gov.pl
uzs.gov.pl
wiih.gov.pl
winb.gov.pl
pinb.gov.pl
wios.gov.pl
witd.gov.pl
wzmiuw.gov.pl
piw.gov.pl
wiw.gov.pl
griw.gov.pl
wif.gov.pl
oum.gov.pl
sdn.gov.pl
zp.gov.pl
uppo.gov.pl
mup.gov.pl
wuoz.gov.pl
konsulat.gov.pl
oirm.gov.pl
// pl regional domains (http://www.dns.pl/english/index.html)
augustow.pl
babia-gora.pl
bedzin.pl
beskidy.pl
bialowieza.pl
bialystok.pl
bielawa.pl
bieszczady.pl
boleslawiec.pl
bydgoszcz.pl
bytom.pl
cieszyn.pl
czeladz.pl
czest.pl
dlugoleka.pl
elblag.pl
elk.pl
glogow.pl
gniezno.pl
gorlice.pl
grajewo.pl
ilawa.pl
jaworzno.pl
jelenia-gora.pl
jgora.pl
kalisz.pl
kazimierz-dolny.pl
karpacz.pl
kartuzy.pl
kaszuby.pl
katowice.pl
kepno.pl
ketrzyn.pl
klodzko.pl
kobierzyce.pl
kolobrzeg.pl
konin.pl
konskowola.pl
kutno.pl
lapy.pl
lebork.pl
legnica.pl
lezajsk.pl
limanowa.pl
lomza.pl
lowicz.pl
lubin.pl
lukow.pl
malbork.pl
malopolska.pl
mazowsze.pl
mazury.pl
mielec.pl
mielno.pl
mragowo.pl
naklo.pl
nowaruda.pl
nysa.pl
olawa.pl
olecko.pl
olkusz.pl
olsztyn.pl
opoczno.pl
opole.pl
ostroda.pl
ostroleka.pl
ostrowiec.pl
ostrowwlkp.pl
pila.pl
pisz.pl
podhale.pl
podlasie.pl
polkowice.pl
pomorze.pl
pomorskie.pl
prochowice.pl
pruszkow.pl
przeworsk.pl
pulawy.pl
radom.pl
rawa-maz.pl
rybnik.pl
rzeszow.pl
sanok.pl
sejny.pl
slask.pl
slupsk.pl
sosnowiec.pl
stalowa-wola.pl
skoczow.pl
starachowice.pl
stargard.pl
suwalki.pl
swidnica.pl
swiebodzin.pl
swinoujscie.pl
szczecin.pl
szczytno.pl
tarnobrzeg.pl
tgory.pl
turek.pl
tychy.pl
ustka.pl
walbrzych.pl
warmia.pl
warszawa.pl
waw.pl
wegrow.pl
wielun.pl
wlocl.pl
wloclawek.pl
wodzislaw.pl
wolomin.pl
wroclaw.pl
zachpomor.pl
zagan.pl
zarow.pl
zgora.pl
zgorzelec.pl

// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
pm

// pn : http://www.government.pn/PnRegistry/policies.htm
pn
gov.pn
co.pn
org.pn
edu.pn
net.pn

// post : https://en.wikipedia.org/wiki/.post
post

// pr : http://www.nic.pr/index.asp?f=1
pr
com.pr
net.pr
org.pr
gov.pr
edu.pr
isla.pr
pro.pr
biz.pr
info.pr
name.pr
// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr
est.pr
prof.pr
ac.pr

// pro : http://registry.pro/get-pro
pro
aaa.pro
aca.pro
acct.pro
avocat.pro
bar.pro
cpa.pro
eng.pro
jur.pro
law.pro
med.pro
recht.pro

// ps : https://en.wikipedia.org/wiki/.ps
// http://www.nic.ps/registration/policy.html#reg
ps
edu.ps
gov.ps
sec.ps
plo.ps
com.ps
org.ps
net.ps

// pt : https://www.dns.pt/en/domain/pt-terms-and-conditions-registration-rules/
pt
net.pt
gov.pt
org.pt
edu.pt
int.pt
publ.pt
com.pt
nome.pt

// pw : https://en.wikipedia.org/wiki/.pw
pw
co.pw
ne.pw
or.pw
ed.pw
go.pw
belau.pw

// py : http://www.nic.py/pautas.html#seccion_9
// Submitted by registry
py
com.py
coop.py
edu.py
gov.py
mil.py
net.py
org.py

// qa : http://domains.qa/en/
qa
com.qa
edu.qa
gov.qa
mil.qa
name.qa
net.qa
org.qa
sch.qa

// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs
re
asso.re
com.re
nom.re

// ro : http://www.rotld.ro/
ro
arts.ro
com.ro
firm.ro
info.ro
nom.ro
nt.ro
org.ro
rec.ro
store.ro
tm.ro
www.ro

// rs : https://www.rnids.rs/en/domains/national-domains
rs
ac.rs
co.rs
edu.rs
gov.rs
in.rs
org.rs

// ru : https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf
// Submitted by George Georgievsky <gug@cctld.ru>
ru

// rw : https://www.ricta.org.rw/sites/default/files/resources/registry_registrar_contract_0.pdf
rw
ac.rw
co.rw
coop.rw
gov.rw
mil.rw
net.rw
org.rw

// sa : http://www.nic.net.sa/
sa
com.sa
net.sa
org.sa
gov.sa
med.sa
pub.sa
edu.sa
sch.sa

// sb : http://www.sbnic.net.sb/
// Submitted by registry <lee.humphries@telekom.com.sb>
sb
com.sb
edu.sb
gov.sb
net.sb
org.sb

// sc : http://www.nic.sc/
sc
com.sc
gov.sc
net.sc
org.sc
edu.sc

// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm
// Submitted by registry <admin@isoc.sd>
sd
com.sd
net.sd
org.sd
edu.sd
med.sd
tv.sd
gov.sd
info.sd

// se : https://en.wikipedia.org/wiki/.se
// Submitted by registry <patrik.wallstrom@iis.se>
se
a.se
ac.se
b.se
bd.se
brand.se
c.se
d.se
e.se
f.se
fh.se
fhsk.se
fhv.se
g.se
h.se
i.se
k.se
komforb.se
kommunalforbund.se
komvux.se
l.se
lanbib.se
m.se
n.se
naturbruksgymn.se
o.se
org.se
p.se
parti.se
pp.se
press.se
r.se
s.se
t.se
tm.se
u.se
w.se
x.se
y.se
z.se

// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines
sg
com.sg
net.sg
org.sg
gov.sg
edu.sg
per.sg

// sh : http://www.nic.sh/registrar.html
sh
com.sh
net.sh
gov.sh
org.sh
mil.sh

// si : https://en.wikipedia.org/wiki/.si
si

// sj : No registrations at this time.
// Submitted by registry <jarle@uninett.no>
sj

// sk : https://en.wikipedia.org/wiki/.sk
// list of 2nd level domains ?
sk

// sl : http://www.nic.sl
// Submitted by registry <adam@neoip.com>
sl
com.sl
net.sl
edu.sl
gov.sl
org.sl

// sm : https://en.wikipedia.org/wiki/.sm
sm

// sn : https://en.wikipedia.org/wiki/.sn
sn
art.sn
com.sn
edu.sn
gouv.sn
org.sn
perso.sn
univ.sn

// so : http://sonic.so/policies/
so
com.so
edu.so
gov.so
me.so
net.so
org.so

// sr : https://en.wikipedia.org/wiki/.sr
sr

// ss : https://registry.nic.ss/
// Submitted by registry <technical@nic.ss>
ss
biz.ss
com.ss
edu.ss
gov.ss
me.ss
net.ss
org.ss
sch.ss

// st : http://www.nic.st/html/policyrules/
st
co.st
com.st
consulado.st
edu.st
embaixada.st
mil.st
net.st
org.st
principe.st
saotome.st
store.st

// su : https://en.wikipedia.org/wiki/.su
su

// sv : http://www.svnet.org.sv/niveldos.pdf
sv
com.sv
edu.sv
gob.sv
org.sv
red.sv

// sx : https://en.wikipedia.org/wiki/.sx
// Submitted by registry <jcvignes@openregistry.com>
sx
gov.sx

// sy : https://en.wikipedia.org/wiki/.sy
// see also: http://www.gobin.info/domainname/sy.doc
sy
edu.sy
gov.sy
net.sy
mil.sy
com.sy
org.sy

// sz : https://en.wikipedia.org/wiki/.sz
// http://www.sispa.org.sz/
sz
co.sz
ac.sz
org.sz

// tc : https://en.wikipedia.org/wiki/.tc
tc

// td : https://en.wikipedia.org/wiki/.td
td

// tel: https://en.wikipedia.org/wiki/.tel
// http://www.telnic.org/
tel

// tf : https://en.wikipedia.org/wiki/.tf
tf

// tg : https://en.wikipedia.org/wiki/.tg
// http://www.nic.tg/
tg

// th : https://en.wikipedia.org/wiki/.th
// Submitted by registry <krit@thains.co.th>
th
ac.th
co.th
go.th
in.th
mi.th
net.th
or.th

// tj : http://www.nic.tj/policy.html
tj
ac.tj
biz.tj
co.tj
com.tj
edu.tj
go.tj
gov.tj
int.tj
mil.tj
name.tj
net.tj
nic.tj
org.tj
test.tj
web.tj

// tk : https://en.wikipedia.org/wiki/.tk
tk

// tl : https://en.wikipedia.org/wiki/.tl
tl
gov.tl

// tm : http://www.nic.tm/local.html
tm
com.tm
co.tm
org.tm
net.tm
nom.tm
gov.tm
mil.tm
edu.tm

// tn : http://www.registre.tn/fr/
// https://whois.ati.tn/
tn
com.tn
ens.tn
fin.tn
gov.tn
ind.tn
info.tn
intl.tn
mincom.tn
nat.tn
net.tn
org.tn
perso.tn
tourism.tn

// to : https://en.wikipedia.org/wiki/.to
// Submitted by registry <egullich@colo.to>
to
com.to
gov.to
net.to
org.to
edu.to
mil.to

// tr : https://nic.tr/
// https://nic.tr/forms/eng/policies.pdf
// https://nic.tr/index.php?USRACTN=PRICELST
tr
av.tr
bbs.tr
bel.tr
biz.tr
com.tr
dr.tr
edu.tr
gen.tr
gov.tr
info.tr
mil.tr
k12.tr
kep.tr
name.tr
net.tr
org.tr
pol.tr
tel.tr
tsk.tr
tv.tr
web.tr
// Used by Northern Cyprus
nc.tr
// Used by government agencies of Northern Cyprus
gov.nc.tr

// tt : http://www.nic.tt/
tt
co.tt
com.tt
org.tt
net.tt
biz.tt
info.tt
pro.tt
int.tt
coop.tt
jobs.tt
mobi.tt
travel.tt
museum.tt
aero.tt
name.tt
gov.tt
edu.tt

// tv : https://en.wikipedia.org/wiki/.tv
// Not listing any 2LDs as reserved since none seem to exist in practice,
// Wikipedia notwithstanding.
tv

// tw : https://en.wikipedia.org/wiki/.tw
tw
edu.tw
gov.tw
mil.tw
com.tw
net.tw
org.tw
idv.tw
game.tw
ebiz.tw
club.tw
ç¶²è·¯.tw
çµ„ç¹”.tw
å•†æ¥­.tw

// tz : http://www.tznic.or.tz/index.php/domains
// Submitted by registry <manager@tznic.or.tz>
tz
ac.tz
co.tz
go.tz
hotel.tz
info.tz
me.tz
mil.tz
mobi.tz
ne.tz
or.tz
sc.tz
tv.tz

// ua : https://hostmaster.ua/policy/?ua
// Submitted by registry <dk@cctld.ua>
ua
// ua 2LD
com.ua
edu.ua
gov.ua
in.ua
net.ua
org.ua
// ua geographic names
// https://hostmaster.ua/2ld/
cherkassy.ua
cherkasy.ua
chernigov.ua
chernihiv.ua
chernivtsi.ua
chernovtsy.ua
ck.ua
cn.ua
cr.ua
crimea.ua
cv.ua
dn.ua
dnepropetrovsk.ua
dnipropetrovsk.ua
donetsk.ua
dp.ua
if.ua
ivano-frankivsk.ua
kh.ua
kharkiv.ua
kharkov.ua
kherson.ua
khmelnitskiy.ua
khmelnytskyi.ua
kiev.ua
kirovograd.ua
km.ua
kr.ua
krym.ua
ks.ua
kv.ua
kyiv.ua
lg.ua
lt.ua
lugansk.ua
lutsk.ua
lv.ua
lviv.ua
mk.ua
mykolaiv.ua
nikolaev.ua
od.ua
odesa.ua
odessa.ua
pl.ua
poltava.ua
rivne.ua
rovno.ua
rv.ua
sb.ua
sebastopol.ua
sevastopol.ua
sm.ua
sumy.ua
te.ua
ternopil.ua
uz.ua
uzhgorod.ua
vinnica.ua
vinnytsia.ua
vn.ua
volyn.ua
yalta.ua
zaporizhzhe.ua
zaporizhzhia.ua
zhitomir.ua
zhytomyr.ua
zp.ua
zt.ua

// ug : https://www.registry.co.ug/
ug
co.ug
or.ug
ac.ug
sc.ug
go.ug
ne.ug
com.ug
org.ug

// uk : https://en.wikipedia.org/wiki/.uk
// Submitted by registry <Michael.Daly@nominet.org.uk>
uk
ac.uk
co.uk
gov.uk
ltd.uk
me.uk
net.uk
nhs.uk
org.uk
plc.uk
police.uk
*.sch.uk

// us : https://en.wikipedia.org/wiki/.us
us
dni.us
fed.us
isa.us
kids.us
nsn.us
// us geographic names
ak.us
al.us
ar.us
as.us
az.us
ca.us
co.us
ct.us
dc.us
de.us
fl.us
ga.us
gu.us
hi.us
ia.us
id.us
il.us
in.us
ks.us
ky.us
la.us
ma.us
md.us
me.us
mi.us
mn.us
mo.us
ms.us
mt.us
nc.us
nd.us
ne.us
nh.us
nj.us
nm.us
nv.us
ny.us
oh.us
ok.us
or.us
pa.us
pr.us
ri.us
sc.us
sd.us
tn.us
tx.us
ut.us
vi.us
vt.us
va.us
wa.us
wi.us
wv.us
wy.us
// The registrar notes several more specific domains available in each state,
// such as state.*.us, dst.*.us, etc., but resolution of these is somewhat
// haphazard; in some states these domains resolve as addresses, while in others
// only subdomains are available, or even nothing at all. We include the
// most common ones where it's clear that different sites are different
// entities.
k12.ak.us
k12.al.us
k12.ar.us
k12.as.us
k12.az.us
k12.ca.us
k12.co.us
k12.ct.us
k12.dc.us
k12.de.us
k12.fl.us
k12.ga.us
k12.gu.us
// k12.hi.us  Bug 614565 - Hawaii has a state-wide DOE login
k12.ia.us
k12.id.us
k12.il.us
k12.in.us
k12.ks.us
k12.ky.us
k12.la.us
k12.ma.us
k12.md.us
k12.me.us
k12.mi.us
k12.mn.us
k12.mo.us
k12.ms.us
k12.mt.us
k12.nc.us
// k12.nd.us  Bug 1028347 - Removed at request of Travis Rosso <trossow@nd.gov>
k12.ne.us
k12.nh.us
k12.nj.us
k12.nm.us
k12.nv.us
k12.ny.us
k12.oh.us
k12.ok.us
k12.or.us
k12.pa.us
k12.pr.us
// k12.ri.us  Removed at request of Kim Cournoyer <netsupport@staff.ri.net>
k12.sc.us
// k12.sd.us  Bug 934131 - Removed at request of James Booze <James.Booze@k12.sd.us>
k12.tn.us
k12.tx.us
k12.ut.us
k12.vi.us
k12.vt.us
k12.va.us
k12.wa.us
k12.wi.us
// k12.wv.us  Bug 947705 - Removed at request of Verne Britton <verne@wvnet.edu>
k12.wy.us
cc.ak.us
cc.al.us
cc.ar.us
cc.as.us
cc.az.us
cc.ca.us
cc.co.us
cc.ct.us
cc.dc.us
cc.de.us
cc.fl.us
cc.ga.us
cc.gu.us
cc.hi.us
cc.ia.us
cc.id.us
cc.il.us
cc.in.us
cc.ks.us
cc.ky.us
cc.la.us
cc.ma.us
cc.md.us
cc.me.us
cc.mi.us
cc.mn.us
cc.mo.us
cc.ms.us
cc.mt.us
cc.nc.us
cc.nd.us
cc.ne.us
cc.nh.us
cc.nj.us
cc.nm.us
cc.nv.us
cc.ny.us
cc.oh.us
cc.ok.us
cc.or.us
cc.pa.us
cc.pr.us
cc.ri.us
cc.sc.us
cc.sd.us
cc.tn.us
cc.tx.us
cc.ut.us
cc.vi.us
cc.vt.us
cc.va.us
cc.wa.us
cc.wi.us
cc.wv.us
cc.wy.us
lib.ak.us
lib.al.us
lib.ar.us
lib.as.us
lib.az.us
lib.ca.us
lib.co.us
lib.ct.us
lib.dc.us
// lib.de.us  Issue #243 - Moved to Private section at request of Ed Moore <Ed.Moore@lib.de.us>
lib.fl.us
lib.ga.us
lib.gu.us
lib.hi.us
lib.ia.us
lib.id.us
lib.il.us
lib.in.us
lib.ks.us
lib.ky.us
lib.la.us
lib.ma.us
lib.md.us
lib.me.us
lib.mi.us
lib.mn.us
lib.mo.us
lib.ms.us
lib.mt.us
lib.nc.us
lib.nd.us
lib.ne.us
lib.nh.us
lib.nj.us
lib.nm.us
lib.nv.us
lib.ny.us
lib.oh.us
lib.ok.us
lib.or.us
lib.pa.us
lib.pr.us
lib.ri.us
lib.sc.us
lib.sd.us
lib.tn.us
lib.tx.us
lib.ut.us
lib.vi.us
lib.vt.us
lib.va.us
lib.wa.us
lib.wi.us
// lib.wv.us  Bug 941670 - Removed at request of Larry W Arnold <arnold@wvlc.lib.wv.us>
lib.wy.us
// k12.ma.us contains school districts in Massachusetts. The 4LDs are
//  managed independently except for private (PVT), charter (CHTR) and
//  parochial (PAROCH) schools.  Those are delegated directly to the
//  5LD operators.   <k12-ma-hostmaster _ at _ rsuc.gweep.net>
pvt.k12.ma.us
chtr.k12.ma.us
paroch.k12.ma.us
// Merit Network, Inc. maintains the registry for =~ /(k12|cc|lib).mi.us/ and the following
//    see also: http://domreg.merit.edu
//    see also: whois -h whois.domreg.merit.edu help
ann-arbor.mi.us
cog.mi.us
dst.mi.us
eaton.mi.us
gen.mi.us
mus.mi.us
tec.mi.us
washtenaw.mi.us

// uy : http://www.nic.org.uy/
uy
com.uy
edu.uy
gub.uy
mil.uy
net.uy
org.uy

// uz : http://www.reg.uz/
uz
co.uz
com.uz
net.uz
org.uz

// va : https://en.wikipedia.org/wiki/.va
va

// vc : https://en.wikipedia.org/wiki/.vc
// Submitted by registry <kshah@ca.afilias.info>
vc
com.vc
net.vc
org.vc
gov.vc
mil.vc
edu.vc

// ve : https://registro.nic.ve/
// Submitted by registry nic@nic.ve and nicve@conatel.gob.ve
ve
arts.ve
bib.ve
co.ve
com.ve
e12.ve
edu.ve
firm.ve
gob.ve
gov.ve
info.ve
int.ve
mil.ve
net.ve
nom.ve
org.ve
rar.ve
rec.ve
store.ve
tec.ve
web.ve

// vg : https://en.wikipedia.org/wiki/.vg
vg

// vi : http://www.nic.vi/newdomainform.htm
// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other
// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they
// are available for registration (which they do not seem to be).
vi
co.vi
com.vi
k12.vi
net.vi
org.vi

// vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp
vn
com.vn
net.vn
org.vn
edu.vn
gov.vn
int.vn
ac.vn
biz.vn
info.vn
name.vn
pro.vn
health.vn

// vu : https://en.wikipedia.org/wiki/.vu
// http://www.vunic.vu/
vu
com.vu
edu.vu
net.vu
org.vu

// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
wf

// ws : https://en.wikipedia.org/wiki/.ws
// http://samoanic.ws/index.dhtml
ws
com.ws
net.ws
org.ws
gov.ws
edu.ws

// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
yt

// IDN ccTLDs
// When submitting patches, please maintain a sort by ISO 3166 ccTLD, then
// U-label, and follow this format:
// // A-Label ("<Latin renderings>", <language name>[, variant info]) : <ISO 3166 ccTLD>
// // [sponsoring org]
// U-Label

// xn--mgbaam7a8h ("Emerat", Arabic) : AE
// http://nic.ae/english/arabicdomain/rules.jsp
Ø§Ù…Ø§Ø±Ø§Øª

// xn--y9a3aq ("hye", Armenian) : AM
// ISOC AM (operated by .am Registry)
Õ°Õ¡Õµ

// xn--54b7fta0cc ("Bangla", Bangla) : BD
à¦¬à¦¾à¦‚à¦²à¦¾

// xn--90ae ("bg", Bulgarian) : BG
Ð±Ð³

// xn--mgbcpq6gpa1a ("albahrain", Arabic) : BH
Ø§Ù„Ø¨Ø­Ø±ÙŠÙ†

// xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY
// Operated by .by registry
Ð±ÐµÐ»

// xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN
// CNNIC
// http://cnnic.cn/html/Dir/2005/10/11/3218.htm
ä¸­å›½

// xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN
// CNNIC
// http://cnnic.cn/html/Dir/2005/10/11/3218.htm
ä¸­åœ‹

// xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ
Ø§Ù„Ø¬Ø²Ø§Ø¦Ø±

// xn--wgbh1c ("Egypt/Masr", Arabic) : EG
// http://www.dotmasr.eg/
Ù…ØµØ±

// xn--e1a4c ("eu", Cyrillic) : EU
// https://eurid.eu
ÐµÑŽ

// xn--qxa6a ("eu", Greek) : EU
// https://eurid.eu
ÎµÏ…

// xn--mgbah1a3hjkrd ("Mauritania", Arabic) : MR
Ù…ÙˆØ±ÙŠØªØ§Ù†ÙŠØ§

// xn--node ("ge", Georgian Mkhedruli) : GE
áƒ’áƒ”

// xn--qxam ("el", Greek) : GR
// Hellenic Ministry of Infrastructure, Transport, and Networks
ÎµÎ»

// xn--j6w193g ("Hong Kong", Chinese) : HK
// https://www.hkirc.hk
// Submitted by registry <hk.tech@hkirc.hk>
// https://www.hkirc.hk/content.jsp?id=30#!/34
é¦™æ¸¯
å…¬å�¸.é¦™æ¸¯
æ•™è‚².é¦™æ¸¯
æ”¿åºœ.é¦™æ¸¯
å€‹äºº.é¦™æ¸¯
ç¶²çµ¡.é¦™æ¸¯
çµ„ç¹”.é¦™æ¸¯

// xn--2scrj9c ("Bharat", Kannada) : IN
// India
à²­à²¾à²°à²¤

// xn--3hcrj9c ("Bharat", Oriya) : IN
// India
à¬­à¬¾à¬°à¬¤

// xn--45br5cyl ("Bharatam", Assamese) : IN
// India
à¦­à¦¾à§°à¦¤

// xn--h2breg3eve ("Bharatam", Sanskrit) : IN
// India
à¤­à¤¾à¤°à¤¤à¤®à¥�

// xn--h2brj9c8c ("Bharot", Santali) : IN
// India
à¤­à¤¾à¤°à¥‹à¤¤

// xn--mgbgu82a ("Bharat", Sindhi) : IN
// India
Ú€Ø§Ø±Øª

// xn--rvc1e0am3e ("Bharatam", Malayalam) : IN
// India
à´­à´¾à´°à´¤à´‚

// xn--h2brj9c ("Bharat", Devanagari) : IN
// India
à¤­à¤¾à¤°à¤¤

// xn--mgbbh1a ("Bharat", Kashmiri) : IN
// India
Ø¨Ø§Ø±Øª

// xn--mgbbh1a71e ("Bharat", Arabic) : IN
// India
Ø¨Ú¾Ø§Ø±Øª

// xn--fpcrj9c3d ("Bharat", Telugu) : IN
// India
à°­à°¾à°°à°¤à±�

// xn--gecrj9c ("Bharat", Gujarati) : IN
// India
àª­àª¾àª°àª¤

// xn--s9brj9c ("Bharat", Gurmukhi) : IN
// India
à¨­à¨¾à¨°à¨¤

// xn--45brj9c ("Bharat", Bengali) : IN
// India
à¦­à¦¾à¦°à¦¤

// xn--xkc2dl3a5ee0h ("India", Tamil) : IN
// India
à®‡à®¨à¯�à®¤à®¿à®¯à®¾

// xn--mgba3a4f16a ("Iran", Persian) : IR
Ø§ÛŒØ±Ø§Ù†

// xn--mgba3a4fra ("Iran", Arabic) : IR
Ø§ÙŠØ±Ø§Ù†

// xn--mgbtx2b ("Iraq", Arabic) : IQ
// Communications and Media Commission
Ø¹Ø±Ø§Ù‚

// xn--mgbayh7gpa ("al-Ordon", Arabic) : JO
// National Information Technology Center (NITC)
// Royal Scientific Society, Al-Jubeiha
Ø§Ù„Ø§Ø±Ø¯Ù†

// xn--3e0b707e ("Republic of Korea", Hangul) : KR
í•œêµ­

// xn--80ao21a ("Kaz", Kazakh) : KZ
Ò›Ð°Ð·

// xn--q7ce6a ("Lao", Lao) : LA
àº¥àº²àº§

// xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK
// https://nic.lk
à¶½à¶‚à¶šà·�

// xn--xkc2al3hye2a ("Ilangai", Tamil) : LK
// https://nic.lk
à®‡à®²à®™à¯�à®•à¯ˆ

// xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA
Ø§Ù„Ù…ØºØ±Ø¨

// xn--d1alf ("mkd", Macedonian) : MK
// MARnet
Ð¼ÐºÐ´

// xn--l1acc ("mon", Mongolian) : MN
Ð¼Ð¾Ð½

// xn--mix891f ("Macao", Chinese, Traditional) : MO
// MONIC / HNET Asia (Registry Operator for .mo)
æ¾³é–€

// xn--mix082f ("Macao", Chinese, Simplified) : MO
æ¾³é—¨

// xn--mgbx4cd0ab ("Malaysia", Malay) : MY
Ù…Ù„ÙŠØ³ÙŠØ§

// xn--mgb9awbf ("Oman", Arabic) : OM
Ø¹Ù…Ø§Ù†

// xn--mgbai9azgqp6j ("Pakistan", Urdu/Arabic) : PK
Ù¾Ø§Ú©Ø³ØªØ§Ù†

// xn--mgbai9a5eva00b ("Pakistan", Urdu/Arabic, variant) : PK
Ù¾Ø§ÙƒØ³ØªØ§Ù†

// xn--ygbi2ammx ("Falasteen", Arabic) : PS
// The Palestinian National Internet Naming Authority (PNINA)
// http://www.pnina.ps
Ù�Ù„Ø³Ø·ÙŠÙ†

// xn--90a3ac ("srb", Cyrillic) : RS
// https://www.rnids.rs/en/domains/national-domains
Ñ�Ñ€Ð±
Ð¿Ñ€.Ñ�Ñ€Ð±
Ð¾Ñ€Ð³.Ñ�Ñ€Ð±
Ð¾Ð±Ñ€.Ñ�Ñ€Ð±
Ð¾Ð´.Ñ�Ñ€Ð±
ÑƒÐ¿Ñ€.Ñ�Ñ€Ð±
Ð°Ðº.Ñ�Ñ€Ð±

// xn--p1ai ("rf", Russian-Cyrillic) : RU
// https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf
// Submitted by George Georgievsky <gug@cctld.ru>
Ñ€Ñ„

// xn--wgbl6a ("Qatar", Arabic) : QA
// http://www.ict.gov.qa/
Ù‚Ø·Ø±

// xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA
// http://www.nic.net.sa/
Ø§Ù„Ø³Ø¹ÙˆØ¯ÙŠØ©

// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant)  : SA
Ø§Ù„Ø³Ø¹ÙˆØ¯ÛŒØ©

// xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA
Ø§Ù„Ø³Ø¹ÙˆØ¯ÛŒÛƒ

// xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA
Ø§Ù„Ø³Ø¹ÙˆØ¯ÙŠÙ‡

// xn--mgbpl2fh ("sudan", Arabic) : SD
// Operated by .sd registry
Ø³ÙˆØ¯Ø§Ù†

// xn--yfro4i67o Singapore ("Singapore", Chinese) : SG
æ–°åŠ å�¡

// xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG
à®šà®¿à®™à¯�à®•à®ªà¯�à®ªà¯‚à®°à¯�

// xn--ogbpf8fl ("Syria", Arabic) : SY
Ø³ÙˆØ±ÙŠØ©

// xn--mgbtf8fl ("Syria", Arabic, variant) : SY
Ø³ÙˆØ±ÙŠØ§

// xn--o3cw4h ("Thai", Thai) : TH
// http://www.thnic.co.th
à¹„à¸—à¸¢
à¸¨à¸¶à¸�à¸©à¸².à¹„à¸—à¸¢
à¸˜à¸¸à¸£à¸�à¸´à¸ˆ.à¹„à¸—à¸¢
à¸£à¸±à¸�à¸šà¸²à¸¥.à¹„à¸—à¸¢
à¸—à¸«à¸²à¸£.à¹„à¸—à¸¢
à¹€à¸™à¹‡à¸•.à¹„à¸—à¸¢
à¸­à¸‡à¸„à¹Œà¸�à¸£.à¹„à¸—à¸¢

// xn--pgbs0dh ("Tunisia", Arabic) : TN
// http://nic.tn
ØªÙˆÙ†Ø³

// xn--kpry57d ("Taiwan", Chinese, Traditional) : TW
// http://www.twnic.net/english/dn/dn_07a.htm
å�°ç�£

// xn--kprw13d ("Taiwan", Chinese, Simplified) : TW
// http://www.twnic.net/english/dn/dn_07a.htm
å�°æ¹¾

// xn--nnx388a ("Taiwan", Chinese, variant) : TW
è‡ºç�£

// xn--j1amh ("ukr", Cyrillic) : UA
ÑƒÐºÑ€

// xn--mgb2ddes ("AlYemen", Arabic) : YE
Ø§Ù„ÙŠÙ…Ù†

// xxx : http://icmregistry.com
xxx

// ye : http://www.y.net.ye/services/domain_name.htm
ye
com.ye
edu.ye
gov.ye
net.ye
mil.ye
org.ye

// za : https://www.zadna.org.za/content/page/domain-information/
ac.za
agric.za
alt.za
co.za
edu.za
gov.za
grondar.za
law.za
mil.za
net.za
ngo.za
nic.za
nis.za
nom.za
org.za
school.za
tm.za
web.za

// zm : https://zicta.zm/
// Submitted by registry <info@zicta.zm>
zm
ac.zm
biz.zm
co.zm
com.zm
edu.zm
gov.zm
info.zm
mil.zm
net.zm
org.zm
sch.zm

// zw : https://www.potraz.gov.zw/
// Confirmed by registry <bmtengwa@potraz.gov.zw> 2017-01-25
zw
ac.zw
co.zw
gov.zw
mil.zw
org.zw


// newGTLDs

// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2021-10-08T15:12:46Z
// This list is auto-generated, don't edit it manually.
// aaa : 2015-02-26 American Automobile Association, Inc.
aaa

// aarp : 2015-05-21 AARP
aarp

// abarth : 2015-07-30 Fiat Chrysler Automobiles N.V.
abarth

// abb : 2014-10-24 ABB Ltd
abb

// abbott : 2014-07-24 Abbott Laboratories, Inc.
abbott

// abbvie : 2015-07-30 AbbVie Inc.
abbvie

// abc : 2015-07-30 Disney Enterprises, Inc.
abc

// able : 2015-06-25 Able Inc.
able

// abogado : 2014-04-24 Registry Services, LLC
abogado

// abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre
abudhabi

// academy : 2013-11-07 Binky Moon, LLC
academy

// accenture : 2014-08-15 Accenture plc
accenture

// accountant : 2014-11-20 dot Accountant Limited
accountant

// accountants : 2014-03-20 Binky Moon, LLC
accountants

// aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG
aco

// actor : 2013-12-12 Dog Beach, LLC
actor

// adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC)
adac

// ads : 2014-12-04 Charleston Road Registry Inc.
ads

// adult : 2014-10-16 ICM Registry AD LLC
adult

// aeg : 2015-03-19 Aktiebolaget Electrolux
aeg

// aetna : 2015-05-21 Aetna Life Insurance Company
aetna

// afamilycompany : 2015-07-23 Johnson Shareholdings, Inc.
afamilycompany

// afl : 2014-10-02 Australian Football League
afl

// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa
africa

// agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
agakhan

// agency : 2013-11-14 Binky Moon, LLC
agency

// aig : 2014-12-18 American International Group, Inc.
aig

// airbus : 2015-07-30 Airbus S.A.S.
airbus

// airforce : 2014-03-06 Dog Beach, LLC
airforce

// airtel : 2014-10-24 Bharti Airtel Limited
airtel

// akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
akdn

// alfaromeo : 2015-07-31 Fiat Chrysler Automobiles N.V.
alfaromeo

// alibaba : 2015-01-15 Alibaba Group Holding Limited
alibaba

// alipay : 2015-01-15 Alibaba Group Holding Limited
alipay

// allfinanz : 2014-07-03 Allfinanz Deutsche VermÃ¶gensberatung Aktiengesellschaft
allfinanz

// allstate : 2015-07-31 Allstate Fire and Casualty Insurance Company
allstate

// ally : 2015-06-18 Ally Financial Inc.
ally

// alsace : 2014-07-02 Region Grand Est
alsace

// alstom : 2015-07-30 ALSTOM
alstom

// amazon : 2019-12-19 Amazon Registry Services, Inc.
amazon

// americanexpress : 2015-07-31 American Express Travel Related Services Company, Inc.
americanexpress

// americanfamily : 2015-07-23 AmFam, Inc.
americanfamily

// amex : 2015-07-31 American Express Travel Related Services Company, Inc.
amex

// amfam : 2015-07-23 AmFam, Inc.
amfam

// amica : 2015-05-28 Amica Mutual Insurance Company
amica

// amsterdam : 2014-07-24 Gemeente Amsterdam
amsterdam

// analytics : 2014-12-18 Campus IP LLC
analytics

// android : 2014-08-07 Charleston Road Registry Inc.
android

// anquan : 2015-01-08 Beijing Qihu Keji Co., Ltd.
anquan

// anz : 2015-07-31 Australia and New Zealand Banking Group Limited
anz

// aol : 2015-09-17 Oath Inc.
aol

// apartments : 2014-12-11 Binky Moon, LLC
apartments

// app : 2015-05-14 Charleston Road Registry Inc.
app

// apple : 2015-05-14 Apple Inc.
apple

// aquarelle : 2014-07-24 Aquarelle.com
aquarelle

// arab : 2015-11-12 League of Arab States
arab

// aramco : 2014-11-20 Aramco Services Company
aramco

// archi : 2014-02-06 Afilias Limited
archi

// army : 2014-03-06 Dog Beach, LLC
army

// art : 2016-03-24 UK Creative Ideas Limited
art

// arte : 2014-12-11 Association Relative Ã  la TÃ©lÃ©vision EuropÃ©enne G.E.I.E.
arte

// asda : 2015-07-31 Wal-Mart Stores, Inc.
asda

// associates : 2014-03-06 Binky Moon, LLC
associates

// athleta : 2015-07-30 The Gap, Inc.
athleta

// attorney : 2014-03-20 Dog Beach, LLC
attorney

// auction : 2014-03-20 Dog Beach, LLC
auction

// audi : 2015-05-21 AUDI Aktiengesellschaft
audi

// audible : 2015-06-25 Amazon Registry Services, Inc.
audible

// audio : 2014-03-20 UNR Corp.
audio

// auspost : 2015-08-13 Australian Postal Corporation
auspost

// author : 2014-12-18 Amazon Registry Services, Inc.
author

// auto : 2014-11-13 XYZ.COM LLC
auto

// autos : 2014-01-09 XYZ.COM LLC
autos

// avianca : 2015-01-08 Avianca Holdings S.A.
avianca

// aws : 2015-06-25 AWS Registry LLC
aws

// axa : 2013-12-19 AXA Group Operations SAS
axa

// azure : 2014-12-18 Microsoft Corporation
azure

// baby : 2015-04-09 XYZ.COM LLC
baby

// baidu : 2015-01-08 Baidu, Inc.
baidu

// banamex : 2015-07-30 Citigroup Inc.
banamex

// bananarepublic : 2015-07-31 The Gap, Inc.
bananarepublic

// band : 2014-06-12 Dog Beach, LLC
band

// bank : 2014-09-25 fTLD Registry Services LLC
bank

// bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
bar

// barcelona : 2014-07-24 Municipi de Barcelona
barcelona

// barclaycard : 2014-11-20 Barclays Bank PLC
barclaycard

// barclays : 2014-11-20 Barclays Bank PLC
barclays

// barefoot : 2015-06-11 Gallo Vineyards, Inc.
barefoot

// bargains : 2013-11-14 Binky Moon, LLC
bargains

// baseball : 2015-10-29 MLB Advanced Media DH, LLC
baseball

// basketball : 2015-08-20 FÃ©dÃ©ration Internationale de Basketball (FIBA)
basketball

// bauhaus : 2014-04-17 Werkhaus GmbH
bauhaus

// bayern : 2014-01-23 Bayern Connect GmbH
bayern

// bbc : 2014-12-18 British Broadcasting Corporation
bbc

// bbt : 2015-07-23 BB&T Corporation
bbt

// bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A.
bbva

// bcg : 2015-04-02 The Boston Consulting Group, Inc.
bcg

// bcn : 2014-07-24 Municipi de Barcelona
bcn

// beats : 2015-05-14 Beats Electronics, LLC
beats

// beauty : 2015-12-03 XYZ.COM LLC
beauty

// beer : 2014-01-09 Registry Services, LLC
beer

// bentley : 2014-12-18 Bentley Motors Limited
bentley

// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG
berlin

// best : 2013-12-19 BestTLD Pty Ltd
best

// bestbuy : 2015-07-31 BBY Solutions, Inc.
bestbuy

// bet : 2015-05-07 Afilias Limited
bet

// bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited
bharti

// bible : 2014-06-19 American Bible Society
bible

// bid : 2013-12-19 dot Bid Limited
bid

// bike : 2013-08-27 Binky Moon, LLC
bike

// bing : 2014-12-18 Microsoft Corporation
bing

// bingo : 2014-12-04 Binky Moon, LLC
bingo

// bio : 2014-03-06 Afilias Limited
bio

// black : 2014-01-16 Afilias Limited
black

// blackfriday : 2014-01-16 UNR Corp.
blackfriday

// blockbuster : 2015-07-30 Dish DBS Corporation
blockbuster

// blog : 2015-05-14 Knock Knock WHOIS There, LLC
blog

// bloomberg : 2014-07-17 Bloomberg IP Holdings LLC
bloomberg

// blue : 2013-11-07 Afilias Limited
blue

// bms : 2014-10-30 Bristol-Myers Squibb Company
bms

// bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
bmw

// bnpparibas : 2014-05-29 BNP Paribas
bnpparibas

// boats : 2014-12-04 XYZ.COM LLC
boats

// boehringer : 2015-07-09 Boehringer Ingelheim International GmbH
boehringer

// bofa : 2015-07-31 Bank of America Corporation
bofa

// bom : 2014-10-16 NÃºcleo de InformaÃ§Ã£o e CoordenaÃ§Ã£o do Ponto BR - NIC.br
bom

// bond : 2014-06-05 ShortDot SA
bond

// boo : 2014-01-30 Charleston Road Registry Inc.
boo

// book : 2015-08-27 Amazon Registry Services, Inc.
book

// booking : 2015-07-16 Booking.com B.V.
booking

// bosch : 2015-06-18 Robert Bosch GMBH
bosch

// bostik : 2015-05-28 Bostik SA
bostik

// boston : 2015-12-10 Boston TLD Management, LLC
boston

// bot : 2014-12-18 Amazon Registry Services, Inc.
bot

// boutique : 2013-11-14 Binky Moon, LLC
boutique

// box : 2015-11-12 Intercap Registry Inc.
box

// bradesco : 2014-12-18 Banco Bradesco S.A.
bradesco

// bridgestone : 2014-12-18 Bridgestone Corporation
bridgestone

// broadway : 2014-12-22 Celebrate Broadway, Inc.
broadway

// broker : 2014-12-11 Dog Beach, LLC
broker

// brother : 2015-01-29 Brother Industries, Ltd.
brother

// brussels : 2014-02-06 DNS.be vzw
brussels

// budapest : 2013-11-21 Minds + Machines Group Limited
budapest

// bugatti : 2015-07-23 Bugatti International SA
bugatti

// build : 2013-11-07 Plan Bee LLC
build

// builders : 2013-11-07 Binky Moon, LLC
builders

// business : 2013-11-07 Binky Moon, LLC
business

// buy : 2014-12-18 Amazon Registry Services, Inc.
buy

// buzz : 2013-10-02 DOTSTRATEGY CO.
buzz

// bzh : 2014-02-27 Association www.bzh
bzh

// cab : 2013-10-24 Binky Moon, LLC
cab

// cafe : 2015-02-11 Binky Moon, LLC
cafe

// cal : 2014-07-24 Charleston Road Registry Inc.
cal

// call : 2014-12-18 Amazon Registry Services, Inc.
call

// calvinklein : 2015-07-30 PVH gTLD Holdings LLC
calvinklein

// cam : 2016-04-21 AC Webconnecting Holding B.V.
cam

// camera : 2013-08-27 Binky Moon, LLC
camera

// camp : 2013-11-07 Binky Moon, LLC
camp

// cancerresearch : 2014-05-15 Australian Cancer Research Foundation
cancerresearch

// canon : 2014-09-12 Canon Inc.
canon

// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
capetown

// capital : 2014-03-06 Binky Moon, LLC
capital

// capitalone : 2015-08-06 Capital One Financial Corporation
capitalone

// car : 2015-01-22 XYZ.COM LLC
car

// caravan : 2013-12-12 Caravan International, Inc.
caravan

// cards : 2013-12-05 Binky Moon, LLC
cards

// care : 2014-03-06 Binky Moon, LLC
care

// career : 2013-10-09 dotCareer LLC
career

// careers : 2013-10-02 Binky Moon, LLC
careers

// cars : 2014-11-13 XYZ.COM LLC
cars

// casa : 2013-11-21 Registry Services, LLC
casa

// case : 2015-09-03 CNH Industrial N.V.
case

// cash : 2014-03-06 Binky Moon, LLC
cash

// casino : 2014-12-18 Binky Moon, LLC
casino

// catering : 2013-12-05 Binky Moon, LLC
catering

// catholic : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
catholic

// cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
cba

// cbn : 2014-08-22 The Christian Broadcasting Network, Inc.
cbn

// cbre : 2015-07-02 CBRE, Inc.
cbre

// cbs : 2015-08-06 CBS Domains Inc.
cbs

// center : 2013-11-07 Binky Moon, LLC
center

// ceo : 2013-11-07 CEOTLD Pty Ltd
ceo

// cern : 2014-06-05 European Organization for Nuclear Research ("CERN")
cern

// cfa : 2014-08-28 CFA Institute
cfa

// cfd : 2014-12-11 ShortDot SA
cfd

// chanel : 2015-04-09 Chanel International B.V.
chanel

// channel : 2014-05-08 Charleston Road Registry Inc.
channel

// charity : 2018-04-11 Binky Moon, LLC
charity

// chase : 2015-04-30 JPMorgan Chase Bank, National Association
chase

// chat : 2014-12-04 Binky Moon, LLC
chat

// cheap : 2013-11-14 Binky Moon, LLC
cheap

// chintai : 2015-06-11 CHINTAI Corporation
chintai

// christmas : 2013-11-21 UNR Corp.
christmas

// chrome : 2014-07-24 Charleston Road Registry Inc.
chrome

// church : 2014-02-06 Binky Moon, LLC
church

// cipriani : 2015-02-19 Hotel Cipriani Srl
cipriani

// circle : 2014-12-18 Amazon Registry Services, Inc.
circle

// cisco : 2014-12-22 Cisco Technology, Inc.
cisco

// citadel : 2015-07-23 Citadel Domain LLC
citadel

// citi : 2015-07-30 Citigroup Inc.
citi

// citic : 2014-01-09 CITIC Group Corporation
citic

// city : 2014-05-29 Binky Moon, LLC
city

// cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc.
cityeats

// claims : 2014-03-20 Binky Moon, LLC
claims

// cleaning : 2013-12-05 Binky Moon, LLC
cleaning

// click : 2014-06-05 UNR Corp.
click

// clinic : 2014-03-20 Binky Moon, LLC
clinic

// clinique : 2015-10-01 The EstÃ©e Lauder Companies Inc.
clinique

// clothing : 2013-08-27 Binky Moon, LLC
clothing

// cloud : 2015-04-16 Aruba PEC S.p.A.
cloud

// club : 2013-11-08 Registry Services, LLC
club

// clubmed : 2015-06-25 Club MÃ©diterranÃ©e S.A.
clubmed

// coach : 2014-10-09 Binky Moon, LLC
coach

// codes : 2013-10-31 Binky Moon, LLC
codes

// coffee : 2013-10-17 Binky Moon, LLC
coffee

// college : 2014-01-16 XYZ.COM LLC
college

// cologne : 2014-02-05 dotKoeln GmbH
cologne

// comcast : 2015-07-23 Comcast IP Holdings I, LLC
comcast

// commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
commbank

// community : 2013-12-05 Binky Moon, LLC
community

// company : 2013-11-07 Binky Moon, LLC
company

// compare : 2015-10-08 Registry Services, LLC
compare

// computer : 2013-10-24 Binky Moon, LLC
computer

// comsec : 2015-01-08 VeriSign, Inc.
comsec

// condos : 2013-12-05 Binky Moon, LLC
condos

// construction : 2013-09-16 Binky Moon, LLC
construction

// consulting : 2013-12-05 Dog Beach, LLC
consulting

// contact : 2015-01-08 Dog Beach, LLC
contact

// contractors : 2013-09-10 Binky Moon, LLC
contractors

// cooking : 2013-11-21 Registry Services, LLC
cooking

// cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
cookingchannel

// cool : 2013-11-14 Binky Moon, LLC
cool

// corsica : 2014-09-25 CollectivitÃ© de Corse
corsica

// country : 2013-12-19 DotCountry LLC
country

// coupon : 2015-02-26 Amazon Registry Services, Inc.
coupon

// coupons : 2015-03-26 Binky Moon, LLC
coupons

// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD
courses

// cpa : 2019-06-10 American Institute of Certified Public Accountants
cpa

// credit : 2014-03-20 Binky Moon, LLC
credit

// creditcard : 2014-03-20 Binky Moon, LLC
creditcard

// creditunion : 2015-01-22 DotCooperation LLC
creditunion

// cricket : 2014-10-09 dot Cricket Limited
cricket

// crown : 2014-10-24 Crown Equipment Corporation
crown

// crs : 2014-04-03 Federated Co-operatives Limited
crs

// cruise : 2015-12-10 Viking River Cruises (Bermuda) Ltd.
cruise

// cruises : 2013-12-05 Binky Moon, LLC
cruises

// csc : 2014-09-25 Alliance-One Services, Inc.
csc

// cuisinella : 2014-04-03 SCHMIDT GROUPE S.A.S.
cuisinella

// cymru : 2014-05-08 Nominet UK
cymru

// cyou : 2015-01-22 ShortDot SA
cyou

// dabur : 2014-02-06 Dabur India Limited
dabur

// dad : 2014-01-23 Charleston Road Registry Inc.
dad

// dance : 2013-10-24 Dog Beach, LLC
dance

// data : 2016-06-02 Dish DBS Corporation
data

// date : 2014-11-20 dot Date Limited
date

// dating : 2013-12-05 Binky Moon, LLC
dating

// datsun : 2014-03-27 NISSAN MOTOR CO., LTD.
datsun

// day : 2014-01-30 Charleston Road Registry Inc.
day

// dclk : 2014-11-20 Charleston Road Registry Inc.
dclk

// dds : 2015-05-07 Registry Services, LLC
dds

// deal : 2015-06-25 Amazon Registry Services, Inc.
deal

// dealer : 2014-12-22 Intercap Registry Inc.
dealer

// deals : 2014-05-22 Binky Moon, LLC
deals

// degree : 2014-03-06 Dog Beach, LLC
degree

// delivery : 2014-09-11 Binky Moon, LLC
delivery

// dell : 2014-10-24 Dell Inc.
dell

// deloitte : 2015-07-31 Deloitte Touche Tohmatsu
deloitte

// delta : 2015-02-19 Delta Air Lines, Inc.
delta

// democrat : 2013-10-24 Dog Beach, LLC
democrat

// dental : 2014-03-20 Binky Moon, LLC
dental

// dentist : 2014-03-20 Dog Beach, LLC
dentist

// desi : 2013-11-14 Desi Networks LLC
desi

// design : 2014-11-07 Registry Services, LLC
design

// dev : 2014-10-16 Charleston Road Registry Inc.
dev

// dhl : 2015-07-23 Deutsche Post AG
dhl

// diamonds : 2013-09-22 Binky Moon, LLC
diamonds

// diet : 2014-06-26 UNR Corp.
diet

// digital : 2014-03-06 Binky Moon, LLC
digital

// direct : 2014-04-10 Binky Moon, LLC
direct

// directory : 2013-09-20 Binky Moon, LLC
directory

// discount : 2014-03-06 Binky Moon, LLC
discount

// discover : 2015-07-23 Discover Financial Services
discover

// dish : 2015-07-30 Dish DBS Corporation
dish

// diy : 2015-11-05 Lifestyle Domain Holdings, Inc.
diy

// dnp : 2013-12-13 Dai Nippon Printing Co., Ltd.
dnp

// docs : 2014-10-16 Charleston Road Registry Inc.
docs

// doctor : 2016-06-02 Binky Moon, LLC
doctor

// dog : 2014-12-04 Binky Moon, LLC
dog

// domains : 2013-10-17 Binky Moon, LLC
domains

// dot : 2015-05-21 Dish DBS Corporation
dot

// download : 2014-11-20 dot Support Limited
download

// drive : 2015-03-05 Charleston Road Registry Inc.
drive

// dtv : 2015-06-04 Dish DBS Corporation
dtv

// dubai : 2015-01-01 Dubai Smart Government Department
dubai

// duck : 2015-07-23 Johnson Shareholdings, Inc.
duck

// dunlop : 2015-07-02 The Goodyear Tire & Rubber Company
dunlop

// dupont : 2015-06-25 DuPont Specialty Products USA, LLC
dupont

// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
durban

// dvag : 2014-06-23 Deutsche VermÃ¶gensberatung Aktiengesellschaft DVAG
dvag

// dvr : 2016-05-26 DISH Technologies L.L.C.
dvr

// earth : 2014-12-04 Interlink Co., Ltd.
earth

// eat : 2014-01-23 Charleston Road Registry Inc.
eat

// eco : 2016-07-08 Big Room Inc.
eco

// edeka : 2014-12-18 EDEKA Verband kaufmÃ¤nnischer Genossenschaften e.V.
edeka

// education : 2013-11-07 Binky Moon, LLC
education

// email : 2013-10-31 Binky Moon, LLC
email

// emerck : 2014-04-03 Merck KGaA
emerck

// energy : 2014-09-11 Binky Moon, LLC
energy

// engineer : 2014-03-06 Dog Beach, LLC
engineer

// engineering : 2014-03-06 Binky Moon, LLC
engineering

// enterprises : 2013-09-20 Binky Moon, LLC
enterprises

// epson : 2014-12-04 Seiko Epson Corporation
epson

// equipment : 2013-08-27 Binky Moon, LLC
equipment

// ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson
ericsson

// erni : 2014-04-03 ERNI Group Holding AG
erni

// esq : 2014-05-08 Charleston Road Registry Inc.
esq

// estate : 2013-08-27 Binky Moon, LLC
estate

// etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat)
etisalat

// eurovision : 2014-04-24 European Broadcasting Union (EBU)
eurovision

// eus : 2013-12-12 Puntueus Fundazioa
eus

// events : 2013-12-05 Binky Moon, LLC
events

// exchange : 2014-03-06 Binky Moon, LLC
exchange

// expert : 2013-11-21 Binky Moon, LLC
expert

// exposed : 2013-12-05 Binky Moon, LLC
exposed

// express : 2015-02-11 Binky Moon, LLC
express

// extraspace : 2015-05-14 Extra Space Storage LLC
extraspace

// fage : 2014-12-18 Fage International S.A.
fage

// fail : 2014-03-06 Binky Moon, LLC
fail

// fairwinds : 2014-11-13 FairWinds Partners, LLC
fairwinds

// faith : 2014-11-20 dot Faith Limited
faith

// family : 2015-04-02 Dog Beach, LLC
family

// fan : 2014-03-06 Dog Beach, LLC
fan

// fans : 2014-11-07 ZDNS International Limited
fans

// farm : 2013-11-07 Binky Moon, LLC
farm

// farmers : 2015-07-09 Farmers Insurance Exchange
farmers

// fashion : 2014-07-03 Registry Services, LLC
fashion

// fast : 2014-12-18 Amazon Registry Services, Inc.
fast

// fedex : 2015-08-06 Federal Express Corporation
fedex

// feedback : 2013-12-19 Top Level Spectrum, Inc.
feedback

// ferrari : 2015-07-31 Fiat Chrysler Automobiles N.V.
ferrari

// ferrero : 2014-12-18 Ferrero Trading Lux S.A.
ferrero

// fiat : 2015-07-31 Fiat Chrysler Automobiles N.V.
fiat

// fidelity : 2015-07-30 Fidelity Brokerage Services LLC
fidelity

// fido : 2015-08-06 Rogers Communications Canada Inc.
fido

// film : 2015-01-08 Motion Picture Domain Registry Pty Ltd
film

// final : 2014-10-16 NÃºcleo de InformaÃ§Ã£o e CoordenaÃ§Ã£o do Ponto BR - NIC.br
final

// finance : 2014-03-20 Binky Moon, LLC
finance

// financial : 2014-03-06 Binky Moon, LLC
financial

// fire : 2015-06-25 Amazon Registry Services, Inc.
fire

// firestone : 2014-12-18 Bridgestone Licensing Services, Inc
firestone

// firmdale : 2014-03-27 Firmdale Holdings Limited
firmdale

// fish : 2013-12-12 Binky Moon, LLC
fish

// fishing : 2013-11-21 Registry Services, LLC
fishing

// fit : 2014-11-07 Registry Services, LLC
fit

// fitness : 2014-03-06 Binky Moon, LLC
fitness

// flickr : 2015-04-02 Flickr, Inc.
flickr

// flights : 2013-12-05 Binky Moon, LLC
flights

// flir : 2015-07-23 FLIR Systems, Inc.
flir

// florist : 2013-11-07 Binky Moon, LLC
florist

// flowers : 2014-10-09 UNR Corp.
flowers

// fly : 2014-05-08 Charleston Road Registry Inc.
fly

// foo : 2014-01-23 Charleston Road Registry Inc.
foo

// food : 2016-04-21 Lifestyle Domain Holdings, Inc.
food

// foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc.
foodnetwork

// football : 2014-12-18 Binky Moon, LLC
football

// ford : 2014-11-13 Ford Motor Company
ford

// forex : 2014-12-11 Dog Beach, LLC
forex

// forsale : 2014-05-22 Dog Beach, LLC
forsale

// forum : 2015-04-02 Fegistry, LLC
forum

// foundation : 2013-12-05 Binky Moon, LLC
foundation

// fox : 2015-09-11 FOX Registry, LLC
fox

// free : 2015-12-10 Amazon Registry Services, Inc.
free

// fresenius : 2015-07-30 Fresenius Immobilien-Verwaltungs-GmbH
fresenius

// frl : 2014-05-15 FRLregistry B.V.
frl

// frogans : 2013-12-19 OP3FT
frogans

// frontdoor : 2015-07-02 Lifestyle Domain Holdings, Inc.
frontdoor

// frontier : 2015-02-05 Frontier Communications Corporation
frontier

// ftr : 2015-07-16 Frontier Communications Corporation
ftr

// fujitsu : 2015-07-30 Fujitsu Limited
fujitsu

// fun : 2016-01-14 Radix FZC
fun

// fund : 2014-03-20 Binky Moon, LLC
fund

// furniture : 2014-03-20 Binky Moon, LLC
furniture

// futbol : 2013-09-20 Dog Beach, LLC
futbol

// fyi : 2015-04-02 Binky Moon, LLC
fyi

// gal : 2013-11-07 AsociaciÃ³n puntoGAL
gal

// gallery : 2013-09-13 Binky Moon, LLC
gallery

// gallo : 2015-06-11 Gallo Vineyards, Inc.
gallo

// gallup : 2015-02-19 Gallup, Inc.
gallup

// game : 2015-05-28 UNR Corp.
game

// games : 2015-05-28 Dog Beach, LLC
games

// gap : 2015-07-31 The Gap, Inc.
gap

// garden : 2014-06-26 Registry Services, LLC
garden

// gay : 2019-05-23 Top Level Design, LLC
gay

// gbiz : 2014-07-17 Charleston Road Registry Inc.
gbiz

// gdn : 2014-07-31 Joint Stock Company "Navigation-information systems"
gdn

// gea : 2014-12-04 GEA Group Aktiengesellschaft
gea

// gent : 2014-01-23 COMBELL NV
gent

// genting : 2015-03-12 Resorts World Inc Pte. Ltd.
genting

// george : 2015-07-31 Wal-Mart Stores, Inc.
george

// ggee : 2014-01-09 GMO Internet, Inc.
ggee

// gift : 2013-10-17 DotGift, LLC
gift

// gifts : 2014-07-03 Binky Moon, LLC
gifts

// gives : 2014-03-06 Dog Beach, LLC
gives

// giving : 2014-11-13 Giving Limited
giving

// glade : 2015-07-23 Johnson Shareholdings, Inc.
glade

// glass : 2013-11-07 Binky Moon, LLC
glass

// gle : 2014-07-24 Charleston Road Registry Inc.
gle

// global : 2014-04-17 Dot Global Domain Registry Limited
global

// globo : 2013-12-19 Globo ComunicaÃ§Ã£o e ParticipaÃ§Ãµes S.A
globo

// gmail : 2014-05-01 Charleston Road Registry Inc.
gmail

// gmbh : 2016-01-29 Binky Moon, LLC
gmbh

// gmo : 2014-01-09 GMO Internet, Inc.
gmo

// gmx : 2014-04-24 1&1 Mail & Media GmbH
gmx

// godaddy : 2015-07-23 Go Daddy East, LLC
godaddy

// gold : 2015-01-22 Binky Moon, LLC
gold

// goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
goldpoint

// golf : 2014-12-18 Binky Moon, LLC
golf

// goo : 2014-12-18 NTT Resonant Inc.
goo

// goodyear : 2015-07-02 The Goodyear Tire & Rubber Company
goodyear

// goog : 2014-11-20 Charleston Road Registry Inc.
goog

// google : 2014-07-24 Charleston Road Registry Inc.
google

// gop : 2014-01-16 Republican State Leadership Committee, Inc.
gop

// got : 2014-12-18 Amazon Registry Services, Inc.
got

// grainger : 2015-05-07 Grainger Registry Services, LLC
grainger

// graphics : 2013-09-13 Binky Moon, LLC
graphics

// gratis : 2014-03-20 Binky Moon, LLC
gratis

// green : 2014-05-08 Afilias Limited
green

// gripe : 2014-03-06 Binky Moon, LLC
gripe

// grocery : 2016-06-16 Wal-Mart Stores, Inc.
grocery

// group : 2014-08-15 Binky Moon, LLC
group

// guardian : 2015-07-30 The Guardian Life Insurance Company of America
guardian

// gucci : 2014-11-13 Guccio Gucci S.p.a.
gucci

// guge : 2014-08-28 Charleston Road Registry Inc.
guge

// guide : 2013-09-13 Binky Moon, LLC
guide

// guitars : 2013-11-14 UNR Corp.
guitars

// guru : 2013-08-27 Binky Moon, LLC
guru

// hair : 2015-12-03 XYZ.COM LLC
hair

// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH
hamburg

// hangout : 2014-11-13 Charleston Road Registry Inc.
hangout

// haus : 2013-12-05 Dog Beach, LLC
haus

// hbo : 2015-07-30 HBO Registry Services, Inc.
hbo

// hdfc : 2015-07-30 HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED
hdfc

// hdfcbank : 2015-02-12 HDFC Bank Limited
hdfcbank

// health : 2015-02-11 DotHealth, LLC
health

// healthcare : 2014-06-12 Binky Moon, LLC
healthcare

// help : 2014-06-26 UNR Corp.
help

// helsinki : 2015-02-05 City of Helsinki
helsinki

// here : 2014-02-06 Charleston Road Registry Inc.
here

// hermes : 2014-07-10 HERMES INTERNATIONAL
hermes

// hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc.
hgtv

// hiphop : 2014-03-06 UNR Corp.
hiphop

// hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc.
hisamitsu

// hitachi : 2014-10-31 Hitachi, Ltd.
hitachi

// hiv : 2014-03-13 UNR Corp.
hiv

// hkt : 2015-05-14 PCCW-HKT DataCom Services Limited
hkt

// hockey : 2015-03-19 Binky Moon, LLC
hockey

// holdings : 2013-08-27 Binky Moon, LLC
holdings

// holiday : 2013-11-07 Binky Moon, LLC
holiday

// homedepot : 2015-04-02 Home Depot Product Authority, LLC
homedepot

// homegoods : 2015-07-16 The TJX Companies, Inc.
homegoods

// homes : 2014-01-09 XYZ.COM LLC
homes

// homesense : 2015-07-16 The TJX Companies, Inc.
homesense

// honda : 2014-12-18 Honda Motor Co., Ltd.
honda

// horse : 2013-11-21 Registry Services, LLC
horse

// hospital : 2016-10-20 Binky Moon, LLC
hospital

// host : 2014-04-17 Radix FZC
host

// hosting : 2014-05-29 UNR Corp.
hosting

// hot : 2015-08-27 Amazon Registry Services, Inc.
hot

// hoteles : 2015-03-05 Travel Reservations SRL
hoteles

// hotels : 2016-04-07 Booking.com B.V.
hotels

// hotmail : 2014-12-18 Microsoft Corporation
hotmail

// house : 2013-11-07 Binky Moon, LLC
house

// how : 2014-01-23 Charleston Road Registry Inc.
how

// hsbc : 2014-10-24 HSBC Global Services (UK) Limited
hsbc

// hughes : 2015-07-30 Hughes Satellite Systems Corporation
hughes

// hyatt : 2015-07-30 Hyatt GTLD, L.L.C.
hyatt

// hyundai : 2015-07-09 Hyundai Motor Company
hyundai

// ibm : 2014-07-31 International Business Machines Corporation
ibm

// icbc : 2015-02-19 Industrial and Commercial Bank of China Limited
icbc

// ice : 2014-10-30 IntercontinentalExchange, Inc.
ice

// icu : 2015-01-08 ShortDot SA
icu

// ieee : 2015-07-23 IEEE Global LLC
ieee

// ifm : 2014-01-30 ifm electronic gmbh
ifm

// ikano : 2015-07-09 Ikano S.A.
ikano

// imamat : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation)
imamat

// imdb : 2015-06-25 Amazon Registry Services, Inc.
imdb

// immo : 2014-07-10 Binky Moon, LLC
immo

// immobilien : 2013-11-07 Dog Beach, LLC
immobilien

// inc : 2018-03-10 Intercap Registry Inc.
inc

// industries : 2013-12-05 Binky Moon, LLC
industries

// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD.
infiniti

// ing : 2014-01-23 Charleston Road Registry Inc.
ing

// ink : 2013-12-05 Top Level Design, LLC
ink

// institute : 2013-11-07 Binky Moon, LLC
institute

// insurance : 2015-02-19 fTLD Registry Services LLC
insurance

// insure : 2014-03-20 Binky Moon, LLC
insure

// international : 2013-11-07 Binky Moon, LLC
international

// intuit : 2015-07-30 Intuit Administrative Services, Inc.
intuit

// investments : 2014-03-20 Binky Moon, LLC
investments

// ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A.
ipiranga

// irish : 2014-08-07 Binky Moon, LLC
irish

// ismaili : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation)
ismaili

// ist : 2014-08-28 Istanbul Metropolitan Municipality
ist

// istanbul : 2014-08-28 Istanbul Metropolitan Municipality
istanbul

// itau : 2014-10-02 Itau Unibanco Holding S.A.
itau

// itv : 2015-07-09 ITV Services Limited
itv

// jaguar : 2014-11-13 Jaguar Land Rover Ltd
jaguar

// java : 2014-06-19 Oracle Corporation
java

// jcb : 2014-11-20 JCB Co., Ltd.
jcb

// jeep : 2015-07-30 FCA US LLC.
jeep

// jetzt : 2014-01-09 Binky Moon, LLC
jetzt

// jewelry : 2015-03-05 Binky Moon, LLC
jewelry

// jio : 2015-04-02 Reliance Industries Limited
jio

// jll : 2015-04-02 Jones Lang LaSalle Incorporated
jll

// jmp : 2015-03-26 Matrix IP LLC
jmp

// jnj : 2015-06-18 Johnson & Johnson Services, Inc.
jnj

// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
joburg

// jot : 2014-12-18 Amazon Registry Services, Inc.
jot

// joy : 2014-12-18 Amazon Registry Services, Inc.
joy

// jpmorgan : 2015-04-30 JPMorgan Chase Bank, National Association
jpmorgan

// jprs : 2014-09-18 Japan Registry Services Co., Ltd.
jprs

// juegos : 2014-03-20 UNR Corp.
juegos

// juniper : 2015-07-30 JUNIPER NETWORKS, INC.
juniper

// kaufen : 2013-11-07 Dog Beach, LLC
kaufen

// kddi : 2014-09-12 KDDI CORPORATION
kddi

// kerryhotels : 2015-04-30 Kerry Trading Co. Limited
kerryhotels

// kerrylogistics : 2015-04-09 Kerry Trading Co. Limited
kerrylogistics

// kerryproperties : 2015-04-09 Kerry Trading Co. Limited
kerryproperties

// kfh : 2014-12-04 Kuwait Finance House
kfh

// kia : 2015-07-09 KIA MOTORS CORPORATION
kia

// kids : 2021-08-13 DotKids Foundation Limited
kids

// kim : 2013-09-23 Afilias Limited
kim

// kinder : 2014-11-07 Ferrero Trading Lux S.A.
kinder

// kindle : 2015-06-25 Amazon Registry Services, Inc.
kindle

// kitchen : 2013-09-20 Binky Moon, LLC
kitchen

// kiwi : 2013-09-20 DOT KIWI LIMITED
kiwi

// koeln : 2014-01-09 dotKoeln GmbH
koeln

// komatsu : 2015-01-08 Komatsu Ltd.
komatsu

// kosher : 2015-08-20 Kosher Marketing Assets LLC
kosher

// kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft)
kpmg

// kpn : 2015-01-08 Koninklijke KPN N.V.
kpn

// krd : 2013-12-05 KRG Department of Information Technology
krd

// kred : 2013-12-19 KredTLD Pty Ltd
kred

// kuokgroup : 2015-04-09 Kerry Trading Co. Limited
kuokgroup

// kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen
kyoto

// lacaixa : 2014-01-09 FundaciÃ³n Bancaria Caixa dâ€™Estalvis i Pensions de Barcelona, â€œla Caixaâ€�
lacaixa

// lamborghini : 2015-06-04 Automobili Lamborghini S.p.A.
lamborghini

// lamer : 2015-10-01 The EstÃ©e Lauder Companies Inc.
lamer

// lancaster : 2015-02-12 LANCASTER
lancaster

// lancia : 2015-07-31 Fiat Chrysler Automobiles N.V.
lancia

// land : 2013-09-10 Binky Moon, LLC
land

// landrover : 2014-11-13 Jaguar Land Rover Ltd
landrover

// lanxess : 2015-07-30 LANXESS Corporation
lanxess

// lasalle : 2015-04-02 Jones Lang LaSalle Incorporated
lasalle

// lat : 2014-10-16 ECOM-LAC FederaciÃ²n de LatinoamÃ¨rica y el Caribe para Internet y el Comercio ElectrÃ²nico
lat

// latino : 2015-07-30 Dish DBS Corporation
latino

// latrobe : 2014-06-16 La Trobe University
latrobe

// law : 2015-01-22 Registry Services, LLC
law

// lawyer : 2014-03-20 Dog Beach, LLC
lawyer

// lds : 2014-03-20 IRI Domain Management, LLC
lds

// lease : 2014-03-06 Binky Moon, LLC
lease

// leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc
leclerc

// lefrak : 2015-07-16 LeFrak Organization, Inc.
lefrak

// legal : 2014-10-16 Binky Moon, LLC
legal

// lego : 2015-07-16 LEGO Juris A/S
lego

// lexus : 2015-04-23 TOYOTA MOTOR CORPORATION
lexus

// lgbt : 2014-05-08 Afilias Limited
lgbt

// lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
lidl

// life : 2014-02-06 Binky Moon, LLC
life

// lifeinsurance : 2015-01-15 American Council of Life Insurers
lifeinsurance

// lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc.
lifestyle

// lighting : 2013-08-27 Binky Moon, LLC
lighting

// like : 2014-12-18 Amazon Registry Services, Inc.
like

// lilly : 2015-07-31 Eli Lilly and Company
lilly

// limited : 2014-03-06 Binky Moon, LLC
limited

// limo : 2013-10-17 Binky Moon, LLC
limo

// lincoln : 2014-11-13 Ford Motor Company
lincoln

// linde : 2014-12-04 Linde Aktiengesellschaft
linde

// link : 2013-11-14 UNR Corp.
link

// lipsy : 2015-06-25 Lipsy Ltd
lipsy

// live : 2014-12-04 Dog Beach, LLC
live

// living : 2015-07-30 Lifestyle Domain Holdings, Inc.
living

// lixil : 2015-03-19 LIXIL Group Corporation
lixil

// llc : 2017-12-14 Afilias Limited
llc

// llp : 2019-08-26 UNR Corp.
llp

// loan : 2014-11-20 dot Loan Limited
loan

// loans : 2014-03-20 Binky Moon, LLC
loans

// locker : 2015-06-04 Dish DBS Corporation
locker

// locus : 2015-06-25 Locus Analytics LLC
locus

// loft : 2015-07-30 Annco, Inc.
loft

// lol : 2015-01-30 UNR Corp.
lol

// london : 2013-11-14 Dot London Domains Limited
london

// lotte : 2014-11-07 Lotte Holdings Co., Ltd.
lotte

// lotto : 2014-04-10 Afilias Limited
lotto

// love : 2014-12-22 Merchant Law Group LLP
love

// lpl : 2015-07-30 LPL Holdings, Inc.
lpl

// lplfinancial : 2015-07-30 LPL Holdings, Inc.
lplfinancial

// ltd : 2014-09-25 Binky Moon, LLC
ltd

// ltda : 2014-04-17 InterNetX, Corp
ltda

// lundbeck : 2015-08-06 H. Lundbeck A/S
lundbeck

// luxe : 2014-01-09 Registry Services, LLC
luxe

// luxury : 2013-10-17 Luxury Partners, LLC
luxury

// macys : 2015-07-31 Macys, Inc.
macys

// madrid : 2014-05-01 Comunidad de Madrid
madrid

// maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF)
maif

// maison : 2013-12-05 Binky Moon, LLC
maison

// makeup : 2015-01-15 XYZ.COM LLC
makeup

// man : 2014-12-04 MAN SE
man

// management : 2013-11-07 Binky Moon, LLC
management

// mango : 2013-10-24 PUNTO FA S.L.
mango

// map : 2016-06-09 Charleston Road Registry Inc.
map

// market : 2014-03-06 Dog Beach, LLC
market

// marketing : 2013-11-07 Binky Moon, LLC
marketing

// markets : 2014-12-11 Dog Beach, LLC
markets

// marriott : 2014-10-09 Marriott Worldwide Corporation
marriott

// marshalls : 2015-07-16 The TJX Companies, Inc.
marshalls

// maserati : 2015-07-31 Fiat Chrysler Automobiles N.V.
maserati

// mattel : 2015-08-06 Mattel Sites, Inc.
mattel

// mba : 2015-04-02 Binky Moon, LLC
mba

// mckinsey : 2015-07-31 McKinsey Holdings, Inc.
mckinsey

// med : 2015-08-06 Medistry LLC
med

// media : 2014-03-06 Binky Moon, LLC
media

// meet : 2014-01-16 Charleston Road Registry Inc.
meet

// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation
melbourne

// meme : 2014-01-30 Charleston Road Registry Inc.
meme

// memorial : 2014-10-16 Dog Beach, LLC
memorial

// men : 2015-02-26 Exclusive Registry Limited
men

// menu : 2013-09-11 Dot Menu Registry, LLC
menu

// merckmsd : 2016-07-14 MSD Registry Holdings, Inc.
merckmsd

// miami : 2013-12-19 Minds + Machines Group Limited
miami

// microsoft : 2014-12-18 Microsoft Corporation
microsoft

// mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
mini

// mint : 2015-07-30 Intuit Administrative Services, Inc.
mint

// mit : 2015-07-02 Massachusetts Institute of Technology
mit

// mitsubishi : 2015-07-23 Mitsubishi Corporation
mitsubishi

// mlb : 2015-05-21 MLB Advanced Media DH, LLC
mlb

// mls : 2015-04-23 The Canadian Real Estate Association
mls

// mma : 2014-11-07 MMA IARD
mma

// mobile : 2016-06-02 Dish DBS Corporation
mobile

// moda : 2013-11-07 Dog Beach, LLC
moda

// moe : 2013-11-13 Interlink Co., Ltd.
moe

// moi : 2014-12-18 Amazon Registry Services, Inc.
moi

// mom : 2015-04-16 UNR Corp.
mom

// monash : 2013-09-30 Monash University
monash

// money : 2014-10-16 Binky Moon, LLC
money

// monster : 2015-09-11 XYZ.COM LLC
monster

// mormon : 2013-12-05 IRI Domain Management, LLC
mormon

// mortgage : 2014-03-20 Dog Beach, LLC
mortgage

// moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
moscow

// moto : 2015-06-04 Motorola Trademark Holdings, LLC
moto

// motorcycles : 2014-01-09 XYZ.COM LLC
motorcycles

// mov : 2014-01-30 Charleston Road Registry Inc.
mov

// movie : 2015-02-05 Binky Moon, LLC
movie

// msd : 2015-07-23 MSD Registry Holdings, Inc.
msd

// mtn : 2014-12-04 MTN Dubai Limited
mtn

// mtr : 2015-03-12 MTR Corporation Limited
mtr

// music : 2021-05-04 DotMusic Limited
music

// mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC
mutual

// nab : 2015-08-20 National Australia Bank Limited
nab

// nagoya : 2013-10-24 GMO Registry, Inc.
nagoya

// natura : 2015-03-12 NATURA COSMÃ‰TICOS S.A.
natura

// navy : 2014-03-06 Dog Beach, LLC
navy

// nba : 2015-07-31 NBA REGISTRY, LLC
nba

// nec : 2015-01-08 NEC Corporation
nec

// netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
netbank

// netflix : 2015-06-18 Netflix, Inc.
netflix

// network : 2013-11-14 Binky Moon, LLC
network

// neustar : 2013-12-05 NeuStar, Inc.
neustar

// new : 2014-01-30 Charleston Road Registry Inc.
new

// news : 2014-12-18 Dog Beach, LLC
news

// next : 2015-06-18 Next plc
next

// nextdirect : 2015-06-18 Next plc
nextdirect

// nexus : 2014-07-24 Charleston Road Registry Inc.
nexus

// nfl : 2015-07-23 NFL Reg Ops LLC
nfl

// ngo : 2014-03-06 Public Interest Registry
ngo

// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK)
nhk

// nico : 2014-12-04 DWANGO Co., Ltd.
nico

// nike : 2015-07-23 NIKE, Inc.
nike

// nikon : 2015-05-21 NIKON CORPORATION
nikon

// ninja : 2013-11-07 Dog Beach, LLC
ninja

// nissan : 2014-03-27 NISSAN MOTOR CO., LTD.
nissan

// nissay : 2015-10-29 Nippon Life Insurance Company
nissay

// nokia : 2015-01-08 Nokia Corporation
nokia

// northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC
northwesternmutual

// norton : 2014-12-04 NortonLifeLock Inc.
norton

// now : 2015-06-25 Amazon Registry Services, Inc.
now

// nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
nowruz

// nowtv : 2015-05-14 Starbucks (HK) Limited
nowtv

// nra : 2014-05-22 NRA Holdings Company, INC.
nra

// nrw : 2013-11-21 Minds + Machines GmbH
nrw

// ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
ntt

// nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications
nyc

// obi : 2014-09-25 OBI Group Holding SE & Co. KGaA
obi

// observer : 2015-04-30 Dog Beach, LLC
observer

// off : 2015-07-23 Johnson Shareholdings, Inc.
off

// office : 2015-03-12 Microsoft Corporation
office

// okinawa : 2013-12-05 BRregistry, Inc.
okinawa

// olayan : 2015-05-14 Crescent Holding GmbH
olayan

// olayangroup : 2015-05-14 Crescent Holding GmbH
olayangroup

// oldnavy : 2015-07-31 The Gap, Inc.
oldnavy

// ollo : 2015-06-04 Dish DBS Corporation
ollo

// omega : 2015-01-08 The Swatch Group Ltd
omega

// one : 2014-11-07 One.com A/S
one

// ong : 2014-03-06 Public Interest Registry
ong

// onl : 2013-09-16 iRegistry GmbH
onl

// online : 2015-01-15 Radix FZC
online

// ooo : 2014-01-09 INFIBEAM AVENUES LIMITED
ooo

// open : 2015-07-31 American Express Travel Related Services Company, Inc.
open

// oracle : 2014-06-19 Oracle Corporation
oracle

// orange : 2015-03-12 Orange Brand Services Limited
orange

// organic : 2014-03-27 Afilias Limited
organic

// origins : 2015-10-01 The EstÃ©e Lauder Companies Inc.
origins

// osaka : 2014-09-04 Osaka Registry Co., Ltd.
osaka

// otsuka : 2013-10-11 Otsuka Holdings Co., Ltd.
otsuka

// ott : 2015-06-04 Dish DBS Corporation
ott

// ovh : 2014-01-16 MÃ©diaBC
ovh

// page : 2014-12-04 Charleston Road Registry Inc.
page

// panasonic : 2015-07-30 Panasonic Corporation
panasonic

// paris : 2014-01-30 City of Paris
paris

// pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
pars

// partners : 2013-12-05 Binky Moon, LLC
partners

// parts : 2013-12-05 Binky Moon, LLC
parts

// party : 2014-09-11 Blue Sky Registry Limited
party

// passagens : 2015-03-05 Travel Reservations SRL
passagens

// pay : 2015-08-27 Amazon Registry Services, Inc.
pay

// pccw : 2015-05-14 PCCW Enterprises Limited
pccw

// pet : 2015-05-07 Afilias Limited
pet

// pfizer : 2015-09-11 Pfizer Inc.
pfizer

// pharmacy : 2014-06-19 National Association of Boards of Pharmacy
pharmacy

// phd : 2016-07-28 Charleston Road Registry Inc.
phd

// philips : 2014-11-07 Koninklijke Philips N.V.
philips

// phone : 2016-06-02 Dish DBS Corporation
phone

// photo : 2013-11-14 UNR Corp.
photo

// photography : 2013-09-20 Binky Moon, LLC
photography

// photos : 2013-10-17 Binky Moon, LLC
photos

// physio : 2014-05-01 PhysBiz Pty Ltd
physio

// pics : 2013-11-14 UNR Corp.
pics

// pictet : 2014-06-26 Pictet Europe S.A.
pictet

// pictures : 2014-03-06 Binky Moon, LLC
pictures

// pid : 2015-01-08 Top Level Spectrum, Inc.
pid

// pin : 2014-12-18 Amazon Registry Services, Inc.
pin

// ping : 2015-06-11 Ping Registry Provider, Inc.
ping

// pink : 2013-10-01 Afilias Limited
pink

// pioneer : 2015-07-16 Pioneer Corporation
pioneer

// pizza : 2014-06-26 Binky Moon, LLC
pizza

// place : 2014-04-24 Binky Moon, LLC
place

// play : 2015-03-05 Charleston Road Registry Inc.
play

// playstation : 2015-07-02 Sony Interactive Entertainment Inc.
playstation

// plumbing : 2013-09-10 Binky Moon, LLC
plumbing

// plus : 2015-02-05 Binky Moon, LLC
plus

// pnc : 2015-07-02 PNC Domain Co., LLC
pnc

// pohl : 2014-06-23 Deutsche VermÃ¶gensberatung Aktiengesellschaft DVAG
pohl

// poker : 2014-07-03 Afilias Limited
poker

// politie : 2015-08-20 Politie Nederland
politie

// porn : 2014-10-16 ICM Registry PN LLC
porn

// pramerica : 2015-07-30 Prudential Financial, Inc.
pramerica

// praxi : 2013-12-05 Praxi S.p.A.
praxi

// press : 2014-04-03 Radix FZC
press

// prime : 2015-06-25 Amazon Registry Services, Inc.
prime

// prod : 2014-01-23 Charleston Road Registry Inc.
prod

// productions : 2013-12-05 Binky Moon, LLC
productions

// prof : 2014-07-24 Charleston Road Registry Inc.
prof

// progressive : 2015-07-23 Progressive Casualty Insurance Company
progressive

// promo : 2014-12-18 Afilias Limited
promo

// properties : 2013-12-05 Binky Moon, LLC
properties

// property : 2014-05-22 UNR Corp.
property

// protection : 2015-04-23 XYZ.COM LLC
protection

// pru : 2015-07-30 Prudential Financial, Inc.
pru

// prudential : 2015-07-30 Prudential Financial, Inc.
prudential

// pub : 2013-12-12 Dog Beach, LLC
pub

// pwc : 2015-10-29 PricewaterhouseCoopers LLP
pwc

// qpon : 2013-11-14 dotCOOL, Inc.
qpon

// quebec : 2013-12-19 PointQuÃ©bec Inc
quebec

// quest : 2015-03-26 XYZ.COM LLC
quest

// racing : 2014-12-04 Premier Registry Limited
racing

// radio : 2016-07-21 European Broadcasting Union (EBU)
radio

// raid : 2015-07-23 Johnson Shareholdings, Inc.
raid

// read : 2014-12-18 Amazon Registry Services, Inc.
read

// realestate : 2015-09-11 dotRealEstate LLC
realestate

// realtor : 2014-05-29 Real Estate Domains LLC
realtor

// realty : 2015-03-19 Dog Beach, LLC
realty

// recipes : 2013-10-17 Binky Moon, LLC
recipes

// red : 2013-11-07 Afilias Limited
red

// redstone : 2014-10-31 Redstone Haute Couture Co., Ltd.
redstone

// redumbrella : 2015-03-26 Travelers TLD, LLC
redumbrella

// rehab : 2014-03-06 Dog Beach, LLC
rehab

// reise : 2014-03-13 Binky Moon, LLC
reise

// reisen : 2014-03-06 Binky Moon, LLC
reisen

// reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc.
reit

// reliance : 2015-04-02 Reliance Industries Limited
reliance

// ren : 2013-12-12 ZDNS International Limited
ren

// rent : 2014-12-04 XYZ.COM LLC
rent

// rentals : 2013-12-05 Binky Moon, LLC
rentals

// repair : 2013-11-07 Binky Moon, LLC
repair

// report : 2013-12-05 Binky Moon, LLC
report

// republican : 2014-03-20 Dog Beach, LLC
republican

// rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
rest

// restaurant : 2014-07-03 Binky Moon, LLC
restaurant

// review : 2014-11-20 dot Review Limited
review

// reviews : 2013-09-13 Dog Beach, LLC
reviews

// rexroth : 2015-06-18 Robert Bosch GMBH
rexroth

// rich : 2013-11-21 iRegistry GmbH
rich

// richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited
richardli

// ricoh : 2014-11-20 Ricoh Company, Ltd.
ricoh

// ril : 2015-04-02 Reliance Industries Limited
ril

// rio : 2014-02-27 Empresa Municipal de InformÃ¡tica SA - IPLANRIO
rio

// rip : 2014-07-10 Dog Beach, LLC
rip

// rocher : 2014-12-18 Ferrero Trading Lux S.A.
rocher

// rocks : 2013-11-14 Dog Beach, LLC
rocks

// rodeo : 2013-12-19 Registry Services, LLC
rodeo

// rogers : 2015-08-06 Rogers Communications Canada Inc.
rogers

// room : 2014-12-18 Amazon Registry Services, Inc.
room

// rsvp : 2014-05-08 Charleston Road Registry Inc.
rsvp

// rugby : 2016-12-15 World Rugby Strategic Developments Limited
rugby

// ruhr : 2013-10-02 regiodot GmbH & Co. KG
ruhr

// run : 2015-03-19 Binky Moon, LLC
run

// rwe : 2015-04-02 RWE AG
rwe

// ryukyu : 2014-01-09 BRregistry, Inc.
ryukyu

// saarland : 2013-12-12 dotSaarland GmbH
saarland

// safe : 2014-12-18 Amazon Registry Services, Inc.
safe

// safety : 2015-01-08 Safety Registry Services, LLC.
safety

// sakura : 2014-12-18 SAKURA Internet Inc.
sakura

// sale : 2014-10-16 Dog Beach, LLC
sale

// salon : 2014-12-11 Binky Moon, LLC
salon

// samsclub : 2015-07-31 Wal-Mart Stores, Inc.
samsclub

// samsung : 2014-04-03 SAMSUNG SDS CO., LTD
samsung

// sandvik : 2014-11-13 Sandvik AB
sandvik

// sandvikcoromant : 2014-11-07 Sandvik AB
sandvikcoromant

// sanofi : 2014-10-09 Sanofi
sanofi

// sap : 2014-03-27 SAP AG
sap

// sarl : 2014-07-03 Binky Moon, LLC
sarl

// sas : 2015-04-02 Research IP LLC
sas

// save : 2015-06-25 Amazon Registry Services, Inc.
save

// saxo : 2014-10-31 Saxo Bank A/S
saxo

// sbi : 2015-03-12 STATE BANK OF INDIA
sbi

// sbs : 2014-11-07 ShortDot SA
sbs

// sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ)
sca

// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB")
scb

// schaeffler : 2015-08-06 Schaeffler Technologies AG & Co. KG
schaeffler

// schmidt : 2014-04-03 SCHMIDT GROUPE S.A.S.
schmidt

// scholarships : 2014-04-24 Scholarships.com, LLC
scholarships

// school : 2014-12-18 Binky Moon, LLC
school

// schule : 2014-03-06 Binky Moon, LLC
schule

// schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
schwarz

// science : 2014-09-11 dot Science Limited
science

// scjohnson : 2015-07-23 Johnson Shareholdings, Inc.
scjohnson

// scot : 2014-01-23 Dot Scot Registry Limited
scot

// search : 2016-06-09 Charleston Road Registry Inc.
search

// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal)
seat

// secure : 2015-08-27 Amazon Registry Services, Inc.
secure

// security : 2015-05-14 XYZ.COM LLC
security

// seek : 2014-12-04 Seek Limited
seek

// select : 2015-10-08 Registry Services, LLC
select

// sener : 2014-10-24 Sener IngenierÃ­a y Sistemas, S.A.
sener

// services : 2014-02-27 Binky Moon, LLC
services

// ses : 2015-07-23 SES
ses

// seven : 2015-08-06 Seven West Media Ltd
seven

// sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG
sew

// sex : 2014-11-13 ICM Registry SX LLC
sex

// sexy : 2013-09-11 UNR Corp.
sexy

// sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR
sfr

// shangrila : 2015-09-03 Shangriâ€�La International Hotel Management Limited
shangrila

// sharp : 2014-05-01 Sharp Corporation
sharp

// shaw : 2015-04-23 Shaw Cablesystems G.P.
shaw

// shell : 2015-07-30 Shell Information Technology International Inc
shell

// shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
shia

// shiksha : 2013-11-14 Afilias Limited
shiksha

// shoes : 2013-10-02 Binky Moon, LLC
shoes

// shop : 2016-04-08 GMO Registry, Inc.
shop

// shopping : 2016-03-31 Binky Moon, LLC
shopping

// shouji : 2015-01-08 Beijing Qihu Keji Co., Ltd.
shouji

// show : 2015-03-05 Binky Moon, LLC
show

// showtime : 2015-08-06 CBS Domains Inc.
showtime

// silk : 2015-06-25 Amazon Registry Services, Inc.
silk

// sina : 2015-03-12 Sina Corporation
sina

// singles : 2013-08-27 Binky Moon, LLC
singles

// site : 2015-01-15 Radix FZC
site

// ski : 2015-04-09 Afilias Limited
ski

// skin : 2015-01-15 XYZ.COM LLC
skin

// sky : 2014-06-19 Sky International AG
sky

// skype : 2014-12-18 Microsoft Corporation
skype

// sling : 2015-07-30 DISH Technologies L.L.C.
sling

// smart : 2015-07-09 Smart Communications, Inc. (SMART)
smart

// smile : 2014-12-18 Amazon Registry Services, Inc.
smile

// sncf : 2015-02-19 SociÃ©tÃ© Nationale des Chemins de fer Francais S N C F
sncf

// soccer : 2015-03-26 Binky Moon, LLC
soccer

// social : 2013-11-07 Dog Beach, LLC
social

// softbank : 2015-07-02 SoftBank Group Corp.
softbank

// software : 2014-03-20 Dog Beach, LLC
software

// sohu : 2013-12-19 Sohu.com Limited
sohu

// solar : 2013-11-07 Binky Moon, LLC
solar

// solutions : 2013-11-07 Binky Moon, LLC
solutions

// song : 2015-02-26 Amazon Registry Services, Inc.
song

// sony : 2015-01-08 Sony Corporation
sony

// soy : 2014-01-23 Charleston Road Registry Inc.
soy

// spa : 2019-09-19 Asia Spa and Wellness Promotion Council Limited
spa

// space : 2014-04-03 Radix FZC
space

// sport : 2017-11-16 Global Association of International Sports Federations (GAISF)
sport

// spot : 2015-02-26 Amazon Registry Services, Inc.
spot

// srl : 2015-05-07 InterNetX, Corp
srl

// stada : 2014-11-13 STADA Arzneimittel AG
stada

// staples : 2015-07-30 Staples, Inc.
staples

// star : 2015-01-08 Star India Private Limited
star

// statebank : 2015-03-12 STATE BANK OF INDIA
statebank

// statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company
statefarm

// stc : 2014-10-09 Saudi Telecom Company
stc

// stcgroup : 2014-10-09 Saudi Telecom Company
stcgroup

// stockholm : 2014-12-18 Stockholms kommun
stockholm

// storage : 2014-12-22 XYZ.COM LLC
storage

// store : 2015-04-09 Radix FZC
store

// stream : 2016-01-08 dot Stream Limited
stream

// studio : 2015-02-11 Dog Beach, LLC
studio

// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD
study

// style : 2014-12-04 Binky Moon, LLC
style

// sucks : 2014-12-22 Vox Populi Registry Ltd.
sucks

// supplies : 2013-12-19 Binky Moon, LLC
supplies

// supply : 2013-12-19 Binky Moon, LLC
supply

// support : 2013-10-24 Binky Moon, LLC
support

// surf : 2014-01-09 Registry Services, LLC
surf

// surgery : 2014-03-20 Binky Moon, LLC
surgery

// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION
suzuki

// swatch : 2015-01-08 The Swatch Group Ltd
swatch

// swiss : 2014-10-16 Swiss Confederation
swiss

// sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet
sydney

// systems : 2013-11-07 Binky Moon, LLC
systems

// tab : 2014-12-04 Tabcorp Holdings Limited
tab

// taipei : 2014-07-10 Taipei City Government
taipei

// talk : 2015-04-09 Amazon Registry Services, Inc.
talk

// taobao : 2015-01-15 Alibaba Group Holding Limited
taobao

// target : 2015-07-31 Target Domain Holdings, LLC
target

// tatamotors : 2015-03-12 Tata Motors Ltd
tatamotors

// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
tatar

// tattoo : 2013-08-30 UNR Corp.
tattoo

// tax : 2014-03-20 Binky Moon, LLC
tax

// taxi : 2015-03-19 Binky Moon, LLC
taxi

// tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
tci

// tdk : 2015-06-11 TDK Corporation
tdk

// team : 2015-03-05 Binky Moon, LLC
team

// tech : 2015-01-30 Radix FZC
tech

// technology : 2013-09-13 Binky Moon, LLC
technology

// temasek : 2014-08-07 Temasek Holdings (Private) Limited
temasek

// tennis : 2014-12-04 Binky Moon, LLC
tennis

// teva : 2015-07-02 Teva Pharmaceutical Industries Limited
teva

// thd : 2015-04-02 Home Depot Product Authority, LLC
thd

// theater : 2015-03-19 Binky Moon, LLC
theater

// theatre : 2015-05-07 XYZ.COM LLC
theatre

// tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America
tiaa

// tickets : 2015-02-05 XYZ.COM LLC
tickets

// tienda : 2013-11-14 Binky Moon, LLC
tienda

// tiffany : 2015-01-30 Tiffany and Company
tiffany

// tips : 2013-09-20 Binky Moon, LLC
tips

// tires : 2014-11-07 Binky Moon, LLC
tires

// tirol : 2014-04-24 punkt Tirol GmbH
tirol

// tjmaxx : 2015-07-16 The TJX Companies, Inc.
tjmaxx

// tjx : 2015-07-16 The TJX Companies, Inc.
tjx

// tkmaxx : 2015-07-16 The TJX Companies, Inc.
tkmaxx

// tmall : 2015-01-15 Alibaba Group Holding Limited
tmall

// today : 2013-09-20 Binky Moon, LLC
today

// tokyo : 2013-11-13 GMO Registry, Inc.
tokyo

// tools : 2013-11-21 Binky Moon, LLC
tools

// top : 2014-03-20 .TOP Registry
top

// toray : 2014-12-18 Toray Industries, Inc.
toray

// toshiba : 2014-04-10 TOSHIBA Corporation
toshiba

// total : 2015-08-06 Total SA
total

// tours : 2015-01-22 Binky Moon, LLC
tours

// town : 2014-03-06 Binky Moon, LLC
town

// toyota : 2015-04-23 TOYOTA MOTOR CORPORATION
toyota

// toys : 2014-03-06 Binky Moon, LLC
toys

// trade : 2014-01-23 Elite Registry Limited
trade

// trading : 2014-12-11 Dog Beach, LLC
trading

// training : 2013-11-07 Binky Moon, LLC
training

// travel : 2015-10-09 Dog Beach, LLC
travel

// travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
travelchannel

// travelers : 2015-03-26 Travelers TLD, LLC
travelers

// travelersinsurance : 2015-03-26 Travelers TLD, LLC
travelersinsurance

// trust : 2014-10-16 UNR Corp.
trust

// trv : 2015-03-26 Travelers TLD, LLC
trv

// tube : 2015-06-11 Latin American Telecom LLC
tube

// tui : 2014-07-03 TUI AG
tui

// tunes : 2015-02-26 Amazon Registry Services, Inc.
tunes

// tushu : 2014-12-18 Amazon Registry Services, Inc.
tushu

// tvs : 2015-02-19 T V SUNDRAM IYENGAR  & SONS LIMITED
tvs

// ubank : 2015-08-20 National Australia Bank Limited
ubank

// ubs : 2014-12-11 UBS AG
ubs

// unicom : 2015-10-15 China United Network Communications Corporation Limited
unicom

// university : 2014-03-06 Binky Moon, LLC
university

// uno : 2013-09-11 Radix FZC
uno

// uol : 2014-05-01 UBN INTERNET LTDA.
uol

// ups : 2015-06-25 UPS Market Driver, Inc.
ups

// vacations : 2013-12-05 Binky Moon, LLC
vacations

// vana : 2014-12-11 Lifestyle Domain Holdings, Inc.
vana

// vanguard : 2015-09-03 The Vanguard Group, Inc.
vanguard

// vegas : 2014-01-16 Dot Vegas, Inc.
vegas

// ventures : 2013-08-27 Binky Moon, LLC
ventures

// verisign : 2015-08-13 VeriSign, Inc.
verisign

// versicherung : 2014-03-20 tldbox GmbH
versicherung

// vet : 2014-03-06 Dog Beach, LLC
vet

// viajes : 2013-10-17 Binky Moon, LLC
viajes

// video : 2014-10-16 Dog Beach, LLC
video

// vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe
vig

// viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd.
viking

// villas : 2013-12-05 Binky Moon, LLC
villas

// vin : 2015-06-18 Binky Moon, LLC
vin

// vip : 2015-01-22 Registry Services, LLC
vip

// virgin : 2014-09-25 Virgin Enterprises Limited
virgin

// visa : 2015-07-30 Visa Worldwide Pte. Limited
visa

// vision : 2013-12-05 Binky Moon, LLC
vision

// viva : 2014-11-07 Saudi Telecom Company
viva

// vivo : 2015-07-31 Telefonica Brasil S.A.
vivo

// vlaanderen : 2014-02-06 DNS.be vzw
vlaanderen

// vodka : 2013-12-19 Registry Services, LLC
vodka

// volkswagen : 2015-05-14 Volkswagen Group of America Inc.
volkswagen

// volvo : 2015-11-12 Volvo Holding Sverige Aktiebolag
volvo

// vote : 2013-11-21 Monolith Registry LLC
vote

// voting : 2013-11-13 Valuetainment Corp.
voting

// voto : 2013-11-21 Monolith Registry LLC
voto

// voyage : 2013-08-27 Binky Moon, LLC
voyage

// vuelos : 2015-03-05 Travel Reservations SRL
vuelos

// wales : 2014-05-08 Nominet UK
wales

// walmart : 2015-07-31 Wal-Mart Stores, Inc.
walmart

// walter : 2014-11-13 Sandvik AB
walter

// wang : 2013-10-24 Zodiac Wang Limited
wang

// wanggou : 2014-12-18 Amazon Registry Services, Inc.
wanggou

// watch : 2013-11-14 Binky Moon, LLC
watch

// watches : 2014-12-22 Afilias Limited
watches

// weather : 2015-01-08 International Business Machines Corporation
weather

// weatherchannel : 2015-03-12 International Business Machines Corporation
weatherchannel

// webcam : 2014-01-23 dot Webcam Limited
webcam

// weber : 2015-06-04 Saint-Gobain Weber SA
weber

// website : 2014-04-03 Radix FZC
website

// wedding : 2014-04-24 Registry Services, LLC
wedding

// weibo : 2015-03-05 Sina Corporation
weibo

// weir : 2015-01-29 Weir Group IP Limited
weir

// whoswho : 2014-02-20 Who's Who Registry
whoswho

// wien : 2013-10-28 punkt.wien GmbH
wien

// wiki : 2013-11-07 Top Level Design, LLC
wiki

// williamhill : 2014-03-13 William Hill Organization Limited
williamhill

// win : 2014-11-20 First Registry Limited
win

// windows : 2014-12-18 Microsoft Corporation
windows

// wine : 2015-06-18 Binky Moon, LLC
wine

// winners : 2015-07-16 The TJX Companies, Inc.
winners

// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC
wme

// wolterskluwer : 2015-08-06 Wolters Kluwer N.V.
wolterskluwer

// woodside : 2015-07-09 Woodside Petroleum Limited
woodside

// work : 2013-12-19 Registry Services, LLC
work

// works : 2013-11-14 Binky Moon, LLC
works

// world : 2014-06-12 Binky Moon, LLC
world

// wow : 2015-10-08 Amazon Registry Services, Inc.
wow

// wtc : 2013-12-19 World Trade Centers Association, Inc.
wtc

// wtf : 2014-03-06 Binky Moon, LLC
wtf

// xbox : 2014-12-18 Microsoft Corporation
xbox

// xerox : 2014-10-24 Xerox DNHC LLC
xerox

// xfinity : 2015-07-09 Comcast IP Holdings I, LLC
xfinity

// xihuan : 2015-01-08 Beijing Qihu Keji Co., Ltd.
xihuan

// xin : 2014-12-11 Elegant Leader Limited
xin

// xn--11b4c3d : 2015-01-15 VeriSign Sarl
à¤•à¥‰à¤®

// xn--1ck2e1b : 2015-02-26 Amazon Registry Services, Inc.
ã‚»ãƒ¼ãƒ«

// xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd.
ä½›å±±

// xn--30rr7y : 2014-06-12 Excellent First Limited
æ…ˆå–„

// xn--3bst00m : 2013-09-13 Eagle Horizon Limited
é›†å›¢

// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED OY
åœ¨çº¿

// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd.
å¤§ä¼—æ±½è½¦

// xn--3pxu8k : 2015-01-15 VeriSign Sarl
ç‚¹çœ‹

// xn--42c2d9a : 2015-01-15 VeriSign Sarl
à¸„à¸­à¸¡

// xn--45q11c : 2013-11-21 Zodiac Gemini Ltd
å…«å�¦

// xn--4gbrim : 2013-10-04 Helium TLDs Ltd
Ù…ÙˆÙ‚Ø¹

// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center
å…¬ç›Š

// xn--55qx5d : 2013-11-14 China Internet Network Information Center (CNNIC)
å…¬å�¸

// xn--5su34j936bgsg : 2015-09-03 Shangriâ€�La International Hotel Management Limited
é¦™æ ¼é‡Œæ‹‰

// xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited
ç½‘ç«™

// xn--6frz82g : 2013-09-23 Afilias Limited
ç§»åŠ¨

// xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited
æˆ‘çˆ±ä½ 

// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
Ð¼Ð¾Ñ�ÐºÐ²Ð°

// xn--80aqecdr1a : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
ÐºÐ°Ñ‚Ð¾Ð»Ð¸Ðº

// xn--80asehdb : 2013-07-14 CORE Association
Ð¾Ð½Ð»Ð°Ð¹Ð½

// xn--80aswg : 2013-07-14 CORE Association
Ñ�Ð°Ð¹Ñ‚

// xn--8y0a063a : 2015-03-26 China United Network Communications Corporation Limited
è�”é€š

// xn--9dbq2a : 2015-01-15 VeriSign Sarl
×§×•×�

// xn--9et52u : 2014-06-12 RISE VICTORY LIMITED
æ—¶å°š

// xn--9krt00a : 2015-03-12 Sina Corporation
å¾®å�š

// xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited
æ·¡é©¬é”¡

// xn--bck1b9a5dre4c : 2015-02-26 Amazon Registry Services, Inc.
ãƒ•ã‚¡ãƒƒã‚·ãƒ§ãƒ³

// xn--c1avg : 2013-11-14 Public Interest Registry
Ð¾Ñ€Ð³

// xn--c2br7g : 2015-01-15 VeriSign Sarl
à¤¨à¥‡à¤Ÿ

// xn--cck2b3b : 2015-02-26 Amazon Registry Services, Inc.
ã‚¹ãƒˆã‚¢

// xn--cckwcxetd : 2019-12-19 Amazon Registry Services, Inc.
ã‚¢ãƒžã‚¾ãƒ³

// xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD
ì‚¼ì„±

// xn--czr694b : 2014-01-16 Internet DotTrademark Organisation Limited
å•†æ ‡

// xn--czrs0t : 2013-12-19 Binky Moon, LLC
å•†åº—

// xn--czru2d : 2013-11-21 Zodiac Aquarius Limited
å•†åŸŽ

// xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives â€œThe Smart Internetâ€�
Ð´ÐµÑ‚Ð¸

// xn--eckvdtc9d : 2014-12-18 Amazon Registry Services, Inc.
ãƒ�ã‚¤ãƒ³ãƒˆ

// xn--efvy88h : 2014-08-22 Guangzhou YU Wei Information Technology Co., Ltd.
æ–°é—»

// xn--fct429k : 2015-04-09 Amazon Registry Services, Inc.
å®¶é›»

// xn--fhbei : 2015-01-15 VeriSign Sarl
ÙƒÙˆÙ…

// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED OY
ä¸­æ–‡ç½‘

// xn--fiq64b : 2013-10-14 CITIC Group Corporation
ä¸­ä¿¡

// xn--fjq720a : 2014-05-22 Binky Moon, LLC
å¨±ä¹�

// xn--flw351e : 2014-07-31 Charleston Road Registry Inc.
è°·æ­Œ

// xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited
é›»è¨Šç›ˆç§‘

// xn--g2xx48c : 2015-01-30 Nawang Heli(Xiamen) Network Service Co., LTD.
è´­ç‰©

// xn--gckr3f0f : 2015-02-26 Amazon Registry Services, Inc.
ã‚¯ãƒ©ã‚¦ãƒ‰

// xn--gk3at1e : 2015-10-08 Amazon Registry Services, Inc.
é€šè²©

// xn--hxt814e : 2014-05-15 Zodiac Taurus Limited
ç½‘åº—

// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry
à¤¸à¤‚à¤—à¤ à¤¨

// xn--imr513n : 2014-12-11 Internet DotTrademark Organisation Limited
é¤�åŽ…

// xn--io0a7i : 2013-11-14 China Internet Network Information Center (CNNIC)
ç½‘ç»œ

// xn--j1aef : 2015-01-15 VeriSign Sarl
ÐºÐ¾Ð¼

// xn--jlq480n2rg : 2019-12-19 Amazon Registry Services, Inc.
äºšé©¬é€Š

// xn--jlq61u9w7b : 2015-01-08 Nokia Corporation
è¯ºåŸºäºš

// xn--jvr189m : 2015-02-26 Amazon Registry Services, Inc.
é£Ÿå“�

// xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V.
é£žåˆ©æµ¦

// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd
æ‰‹æœº

// xn--mgba3a3ejt : 2014-11-20 Aramco Services Company
Ø§Ø±Ø§Ù…ÙƒÙˆ

// xn--mgba7c0bbn0a : 2015-05-14 Crescent Holding GmbH
Ø§Ù„Ø¹Ù„ÙŠØ§Ù†

// xn--mgbaakc7dvf : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat)
Ø§ØªØµØ§Ù„Ø§Øª

// xn--mgbab2bd : 2013-10-31 CORE Association
Ø¨Ø§Ø²Ø§Ø±

// xn--mgbca7dzdo : 2015-07-30 Abu Dhabi Systems and Information Centre
Ø§Ø¨ÙˆØ¸Ø¨ÙŠ

// xn--mgbi4ecexp : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
ÙƒØ§Ø«ÙˆÙ„ÙŠÙƒ

// xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
Ù‡Ù…Ø±Ø§Ù‡

// xn--mk1bu44c : 2015-01-15 VeriSign Sarl
ë‹·ì»´

// xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd.
æ”¿åºœ

// xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd.
Ø´Ø¨ÙƒØ©

// xn--ngbe9e0a : 2014-12-04 Kuwait Finance House
Ø¨ÙŠØªÙƒ

// xn--ngbrx : 2015-11-12 League of Arab States
Ø¹Ø±Ø¨

// xn--nqv7f : 2013-11-14 Public Interest Registry
æœºæž„

// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry
ç»„ç»‡æœºæž„

// xn--nyqy26a : 2014-11-07 Stable Tone Limited
å�¥åº·

// xn--otu796d : 2017-08-06 Jiang Yu Liang Cai Technology Company Limited
æ‹›è�˜

// xn--p1acf : 2013-12-12 Rusnames Limited
Ñ€ÑƒÑ�

// xn--pssy2u : 2015-01-15 VeriSign Sarl
å¤§æ‹¿

// xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc.
ã�¿ã‚“ã�ª

// xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc.
ã‚°ãƒ¼ã‚°ãƒ«

// xn--rhqv96g : 2013-09-11 Stable Tone Limited
ä¸–ç•Œ

// xn--rovu88b : 2015-02-26 Amazon Registry Services, Inc.
æ›¸ç±�

// xn--ses554g : 2014-01-16 KNET Co., Ltd.
ç½‘å�€

// xn--t60b56a : 2015-01-15 VeriSign Sarl
ë‹·ë„·

// xn--tckwe : 2015-01-15 VeriSign Sarl
ã‚³ãƒ 

// xn--tiq49xqyj : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
å¤©ä¸»æ•™

// xn--unup4y : 2013-07-14 Binky Moon, LLC
æ¸¸æˆ�

// xn--vermgensberater-ctb : 2014-06-23 Deutsche VermÃ¶gensberatung Aktiengesellschaft DVAG
vermÃ¶gensberater

// xn--vermgensberatung-pwb : 2014-06-23 Deutsche VermÃ¶gensberatung Aktiengesellschaft DVAG
vermÃ¶gensberatung

// xn--vhquv : 2013-08-27 Binky Moon, LLC
ä¼�ä¸š

// xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd.
ä¿¡æ�¯

// xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited
å˜‰é‡Œå¤§é…’åº—

// xn--w4rs40l : 2015-07-30 Kerry Trading Co. Limited
å˜‰é‡Œ

// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd.
å¹¿ä¸œ

// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center
æ”¿åŠ¡

// xyz : 2013-12-05 XYZ.COM LLC
xyz

// yachts : 2014-01-09 XYZ.COM LLC
yachts

// yahoo : 2015-04-02 Oath Inc.
yahoo

// yamaxun : 2014-12-18 Amazon Registry Services, Inc.
yamaxun

// yandex : 2014-04-10 Yandex Europe B.V.
yandex

// yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
yodobashi

// yoga : 2014-05-29 Registry Services, LLC
yoga

// yokohama : 2013-12-12 GMO Registry, Inc.
yokohama

// you : 2015-04-09 Amazon Registry Services, Inc.
you

// youtube : 2014-05-01 Charleston Road Registry Inc.
youtube

// yun : 2015-01-08 Beijing Qihu Keji Co., Ltd.
yun

// zappos : 2015-06-25 Amazon Registry Services, Inc.
zappos

// zara : 2014-11-07 Industria de DiseÃ±o Textil, S.A. (INDITEX, S.A.)
zara

// zero : 2014-12-18 Amazon Registry Services, Inc.
zero

// zip : 2014-05-08 Charleston Road Registry Inc.
zip

// zone : 2013-11-14 Binky Moon, LLC
zone

// zuerich : 2014-11-07 Kanton ZÃ¼rich (Canton of Zurich)
zuerich


// ===END ICANN DOMAINS===
// ===BEGIN PRIVATE DOMAINS===
// (Note: these are in alphabetical order by company name)

// 1GB LLC : https://www.1gb.ua/
// Submitted by 1GB LLC <noc@1gb.com.ua>
cc.ua
inf.ua
ltd.ua

// 611coin : https://611project.org/
611.to

// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za
// Submitted by Aaron Marais <its_me@aaronleem.co.za>
graphox.us

// accesso Technology Group, plc. : https://accesso.com/
// Submitted by accesso Team <accessoecommerce@accesso.com>
*.devcdnaccesso.com

// Adobe : https://www.adobe.com/
// Submitted by Ian Boston <boston@adobe.com> and Lars Trieloff <trieloff@adobe.com>
adobeaemcloud.com
*.dev.adobeaemcloud.com
hlx.live
adobeaemcloud.net
hlx.page
hlx3.page

// Agnat sp. z o.o. : https://domena.pl
// Submitted by Przemyslaw Plewa <it-admin@domena.pl>
beep.pl

// alboto.ca : http://alboto.ca
// Submitted by Anton Avramov <avramov@alboto.ca>
barsy.ca

// Alces Software Ltd : http://alces-software.com
// Submitted by Mark J. Titorenko <mark.titorenko@alces-software.com>
*.compute.estate
*.alces.network

// all-inkl.com : https://all-inkl.com
// Submitted by Werner Kaltofen <wk@all-inkl.com>
kasserver.com

// Altervista: https://www.altervista.org
// Submitted by Carlo Cannas <tech_staff@altervista.it>
altervista.org

// alwaysdata : https://www.alwaysdata.com
// Submitted by Cyril <admin@alwaysdata.com>
alwaysdata.net

// Amazon CloudFront : https://aws.amazon.com/cloudfront/
// Submitted by Donavan Miller <donavanm@amazon.com>
cloudfront.net

// Amazon Elastic Compute Cloud : https://aws.amazon.com/ec2/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
*.compute.amazonaws.com
*.compute-1.amazonaws.com
*.compute.amazonaws.com.cn
us-east-1.amazonaws.com

// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
cn-north-1.eb.amazonaws.com.cn
cn-northwest-1.eb.amazonaws.com.cn
elasticbeanstalk.com
ap-northeast-1.elasticbeanstalk.com
ap-northeast-2.elasticbeanstalk.com
ap-northeast-3.elasticbeanstalk.com
ap-south-1.elasticbeanstalk.com
ap-southeast-1.elasticbeanstalk.com
ap-southeast-2.elasticbeanstalk.com
ca-central-1.elasticbeanstalk.com
eu-central-1.elasticbeanstalk.com
eu-west-1.elasticbeanstalk.com
eu-west-2.elasticbeanstalk.com
eu-west-3.elasticbeanstalk.com
sa-east-1.elasticbeanstalk.com
us-east-1.elasticbeanstalk.com
us-east-2.elasticbeanstalk.com
us-gov-west-1.elasticbeanstalk.com
us-west-1.elasticbeanstalk.com
us-west-2.elasticbeanstalk.com

// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
*.elb.amazonaws.com
*.elb.amazonaws.com.cn

// Amazon Global Accelerator : https://aws.amazon.com/global-accelerator/
// Submitted by Daniel Massaguer <psl-maintainers@amazon.com>
awsglobalaccelerator.com

// Amazon S3 : https://aws.amazon.com/s3/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
s3.amazonaws.com
s3-ap-northeast-1.amazonaws.com
s3-ap-northeast-2.amazonaws.com
s3-ap-south-1.amazonaws.com
s3-ap-southeast-1.amazonaws.com
s3-ap-southeast-2.amazonaws.com
s3-ca-central-1.amazonaws.com
s3-eu-central-1.amazonaws.com
s3-eu-west-1.amazonaws.com
s3-eu-west-2.amazonaws.com
s3-eu-west-3.amazonaws.com
s3-external-1.amazonaws.com
s3-fips-us-gov-west-1.amazonaws.com
s3-sa-east-1.amazonaws.com
s3-us-gov-west-1.amazonaws.com
s3-us-east-2.amazonaws.com
s3-us-west-1.amazonaws.com
s3-us-west-2.amazonaws.com
s3.ap-northeast-2.amazonaws.com
s3.ap-south-1.amazonaws.com
s3.cn-north-1.amazonaws.com.cn
s3.ca-central-1.amazonaws.com
s3.eu-central-1.amazonaws.com
s3.eu-west-2.amazonaws.com
s3.eu-west-3.amazonaws.com
s3.us-east-2.amazonaws.com
s3.dualstack.ap-northeast-1.amazonaws.com
s3.dualstack.ap-northeast-2.amazonaws.com
s3.dualstack.ap-south-1.amazonaws.com
s3.dualstack.ap-southeast-1.amazonaws.com
s3.dualstack.ap-southeast-2.amazonaws.com
s3.dualstack.ca-central-1.amazonaws.com
s3.dualstack.eu-central-1.amazonaws.com
s3.dualstack.eu-west-1.amazonaws.com
s3.dualstack.eu-west-2.amazonaws.com
s3.dualstack.eu-west-3.amazonaws.com
s3.dualstack.sa-east-1.amazonaws.com
s3.dualstack.us-east-1.amazonaws.com
s3.dualstack.us-east-2.amazonaws.com
s3-website-us-east-1.amazonaws.com
s3-website-us-west-1.amazonaws.com
s3-website-us-west-2.amazonaws.com
s3-website-ap-northeast-1.amazonaws.com
s3-website-ap-southeast-1.amazonaws.com
s3-website-ap-southeast-2.amazonaws.com
s3-website-eu-west-1.amazonaws.com
s3-website-sa-east-1.amazonaws.com
s3-website.ap-northeast-2.amazonaws.com
s3-website.ap-south-1.amazonaws.com
s3-website.ca-central-1.amazonaws.com
s3-website.eu-central-1.amazonaws.com
s3-website.eu-west-2.amazonaws.com
s3-website.eu-west-3.amazonaws.com
s3-website.us-east-2.amazonaws.com

// Amsterdam Wireless: https://www.amsterdamwireless.nl/
// Submitted by Imre Jonk <hostmaster@amsterdamwireless.nl>
amsw.nl

// Amune : https://amune.org/
// Submitted by Team Amune <cert@amune.org>
t3l3p0rt.net
tele.amune.org

// Apigee : https://apigee.com/
// Submitted by Apigee Security Team <security@apigee.com>
apigee.io

// Apphud : https://apphud.com
// Submitted by Alexander Selivanov <alex@apphud.com>
siiites.com

// Appspace : https://www.appspace.com
// Submitted by Appspace Security Team <security@appspace.com>
appspacehosted.com
appspaceusercontent.com

// Appudo UG (haftungsbeschrÃ¤nkt) : https://www.appudo.com
// Submitted by Alexander Hochbaum <admin@appudo.com>
appudo.net

// Aptible : https://www.aptible.com/
// Submitted by Thomas Orozco <thomas@aptible.com>
on-aptible.com

// ASEINet : https://www.aseinet.com/
// Submitted by Asei SEKIGUCHI <mail@aseinet.com>
user.aseinet.ne.jp
gv.vc
d.gv.vc

// AsociaciÃ³n Amigos de la InformÃ¡tica "Euskalamiga" : http://encounter.eus/
// Submitted by Hector Martin <marcan@euskalencounter.org>
user.party.eus

// Association potager.org : https://potager.org/
// Submitted by Lunar <jardiniers@potager.org>
pimienta.org
poivron.org
potager.org
sweetpepper.org

// ASUSTOR Inc. : http://www.asustor.com
// Submitted by Vincent Tseng <vincenttseng@asustor.com>
myasustor.com

// Atlassian : https://atlassian.com
// Submitted by Sam Smyth <devloop@atlassian.com>
cdn.prod.atlassian-dev.net

// AVM : https://avm.de
// Submitted by Andreas Weise <a.weise@avm.de>
myfritz.net

// AVStack Pte. Ltd. : https://avstack.io
// Submitted by Jasper Hugo <jasper@avstack.io>
onavstack.net

// AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com
// Submitted by James Kennedy <domains@advisorwebsites.com>
*.awdev.ca
*.advisor.ws

// AZ.pl sp. z.o.o: https://az.pl
// Submited by Krzysztof Wolski <krzysztof.wolski@home.eu>
ecommerce-shop.pl

// b-data GmbH : https://www.b-data.io
// Submitted by Olivier Benz <olivier.benz@b-data.ch>
b-data.io

// backplane : https://www.backplane.io
// Submitted by Anthony Voutas <anthony@backplane.io>
backplaneapp.io

// Balena : https://www.balena.io
// Submitted by Petros Angelatos <petrosagg@balena.io>
balena-devices.com

// University of Banja Luka : https://unibl.org
// Domains for Republic of Srpska administrative entity.
// Submitted by Marko Ivanovic <kormang@hotmail.rs>
rs.ba

// Banzai Cloud
// Submitted by Janos Matyas <info@banzaicloud.com>
*.banzai.cloud
app.banzaicloud.io
*.backyards.banzaicloud.io


// BetaInABox
// Submitted by Adrian <adrian@betainabox.com>
betainabox.com

// BinaryLane : http://www.binarylane.com
// Submitted by Nathan O'Sullivan <nathan@mammoth.com.au>
bnr.la

// Bitbucket : http://bitbucket.org
// Submitted by Andy Ortlieb <aortlieb@atlassian.com>
bitbucket.io

// Blackbaud, Inc. : https://www.blackbaud.com
// Submitted by Paul Crowder <paul.crowder@blackbaud.com>
blackbaudcdn.net

// Blatech : http://www.blatech.net
// Submitted by Luke Bratch <luke@bratch.co.uk>
of.je

// Blue Bite, LLC : https://bluebite.com
// Submitted by Joshua Weiss <admin.engineering@bluebite.com>
bluebite.io

// Boomla : https://boomla.com
// Submitted by Tibor Halter <thalter@boomla.com>
boomla.net

// Boutir : https://www.boutir.com
// Submitted by Eric Ng Ka Ka <ngkaka@boutir.com>
boutir.com

// Boxfuse : https://boxfuse.com
// Submitted by Axel Fontaine <axel@boxfuse.com>
boxfuse.io

// bplaced : https://www.bplaced.net/
// Submitted by Miroslav Bozic <security@bplaced.net>
square7.ch
bplaced.com
bplaced.de
square7.de
bplaced.net
square7.net

// Brendly : https://brendly.rs
// Submitted by Dusan Radovanovic <dusan.radovanovic@brendly.rs>
shop.brendly.rs

// BrowserSafetyMark
// Submitted by Dave Tharp <browsersafetymark.io@quicinc.com>
browsersafetymark.io

// Bytemark Hosting : https://www.bytemark.co.uk
// Submitted by Paul Cammish <paul.cammish@bytemark.co.uk>
uk0.bigv.io
dh.bytemark.co.uk
vm.bytemark.co.uk

// Caf.js Labs LLC : https://www.cafjs.com
// Submitted by Antonio Lain <antlai@cafjs.com>
cafjs.com

// callidomus : https://www.callidomus.com/
// Submitted by Marcus Popp <admin@callidomus.com>
mycd.eu

// Carrd : https://carrd.co
// Submitted by AJ <aj@carrd.co>
drr.ac
uwu.ai
carrd.co
crd.co
ju.mp

// CentralNic : http://www.centralnic.com/names/domains
// Submitted by registry <gavin.brown@centralnic.com>
ae.org
br.com
cn.com
com.de
com.se
de.com
eu.com
gb.net
hu.net
jp.net
jpn.com
mex.com
ru.com
sa.com
se.net
uk.com
uk.net
us.com
za.bz
za.com

// No longer operated by CentralNic, these entries should be adopted and/or removed by current operators
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
ar.com
gb.com
hu.com
kr.com
no.com
qc.com
uy.com

// Africa.com Web Solutions Ltd : https://registry.africa.com
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
africa.com

// iDOT Services Limited : http://www.domain.gr.com
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
gr.com

// Radix FZC : http://domains.in.net
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
in.net
web.in

// US REGISTRY LLC : http://us.org
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
us.org

// co.com Registry, LLC : https://registry.co.com
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
co.com

// Roar Domains LLC : https://roar.basketball/
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
aus.basketball
nz.basketball

// BRS Media : https://brsmedia.com/
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
radio.am
radio.fm

// c.la : http://www.c.la/
c.la

// certmgr.org : https://certmgr.org
// Submitted by B. Blechschmidt <hostmaster@certmgr.org>
certmgr.org

// Cityhost LLC  : https://cityhost.ua
// Submitted by Maksym Rivtin <support@cityhost.net.ua>
cx.ua

// Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/
// Submitted by Rishabh Nambiar & Michael Brown <team@discourse.org>
discourse.group
discourse.team

// ClearVox : http://www.clearvox.nl/
// Submitted by Leon Rowland <leon@clearvox.nl>
virtueeldomein.nl

// Clever Cloud : https://www.clever-cloud.com/
// Submitted by Quentin Adam <noc@clever-cloud.com>
cleverapps.io

// Clerk : https://www.clerk.dev
// Submitted by Colin Sidoti <systems@clerk.dev>
clerk.app
clerkstage.app
*.lcl.dev
*.lclstage.dev
*.stg.dev
*.stgstage.dev

// ClickRising : https://clickrising.com/
// Submitted by Umut Gumeli <infrastructure-publicsuffixlist@clickrising.com>
clickrising.net

// Cloud66 : https://www.cloud66.com/
// Submitted by Khash Sajadi <khash@cloud66.com>
c66.me
cloud66.ws
cloud66.zone

// CloudAccess.net : https://www.cloudaccess.net/
// Submitted by Pawel Panek <noc@cloudaccess.net>
jdevcloud.com
wpdevcloud.com
cloudaccess.host
freesite.host
cloudaccess.net

// cloudControl : https://www.cloudcontrol.com/
// Submitted by Tobias Wilken <tw@cloudcontrol.com>
cloudcontrolled.com
cloudcontrolapp.com

// Cloudera, Inc. : https://www.cloudera.com/
// Submitted by Kedarnath Waikar <security@cloudera.com>
*.cloudera.site

// Cloudflare, Inc. : https://www.cloudflare.com/
// Submitted by Cloudflare Team <publicsuffixlist@cloudflare.com>
pages.dev
trycloudflare.com
workers.dev

// Clovyr : https://clovyr.io
// Submitted by Patrick Nielsen <patrick@clovyr.io>
wnext.app

// co.ca : http://registry.co.ca/
co.ca

// Co & Co : https://co-co.nl/
// Submitted by Govert Versluis <govert@co-co.nl>
*.otap.co

// i-registry s.r.o. : http://www.i-registry.cz/
// Submitted by Martin Semrad <semrad@i-registry.cz>
co.cz

// CDN77.com : http://www.cdn77.com
// Submitted by Jan Krpes <jan.krpes@cdn77.com>
c.cdn77.org
cdn77-ssl.net
r.cdn77.net
rsc.cdn77.org
ssl.origin.cdn77-secure.org

// Cloud DNS Ltd : http://www.cloudns.net
// Submitted by Aleksander Hristov <noc@cloudns.net>
cloudns.asia
cloudns.biz
cloudns.club
cloudns.cc
cloudns.eu
cloudns.in
cloudns.info
cloudns.org
cloudns.pro
cloudns.pw
cloudns.us

// CNPY : https://cnpy.gdn
// Submitted by Angelo Gladding <angelo@lahacker.net>
cnpy.gdn

// CoDNS B.V.
co.nl
co.no

// Combell.com : https://www.combell.com
// Submitted by Thomas Wouters <thomas.wouters@combellgroup.com>
webhosting.be
hosting-cluster.nl

// Coordination Center for TLD RU and XN--P1AI : https://cctld.ru/en/domains/domens_ru/reserved/
// Submitted by George Georgievsky <gug@cctld.ru>
ac.ru
edu.ru
gov.ru
int.ru
mil.ru
test.ru

// COSIMO GmbH : http://www.cosimo.de
// Submitted by Rene Marticke <rmarticke@cosimo.de>
dyn.cosidns.de
dynamisches-dns.de
dnsupdater.de
internet-dns.de
l-o-g-i-n.de
dynamic-dns.info
feste-ip.net
knx-server.net
static-access.net

// Craynic, s.r.o. : http://www.craynic.com/
// Submitted by Ales Krajnik <ales.krajnik@craynic.com>
realm.cz

// Cryptonomic : https://cryptonomic.net/
// Submitted by Andrew Cady <public-suffix-list@cryptonomic.net>
*.cryptonomic.net

// Cupcake : https://cupcake.io/
// Submitted by Jonathan Rudenberg <jonathan@cupcake.io>
cupcake.is

// Curv UG : https://curv-labs.de/
// Submitted by Marvin Wiesner <Marvin@curv-labs.de>
curv.dev

// Customer OCI - Oracle Dyn https://cloud.oracle.com/home https://dyn.com/dns/
// Submitted by Gregory Drake <support@dyn.com>
// Note: This is intended to also include customer-oci.com due to wildcards implicitly including the current label
*.customer-oci.com
*.oci.customer-oci.com
*.ocp.customer-oci.com
*.ocs.customer-oci.com

// cyon GmbH : https://www.cyon.ch/
// Submitted by Dominic Luechinger <dol@cyon.ch>
cyon.link
cyon.site

// Danger Science Group: https://dangerscience.com/
// Submitted by Skylar MacDonald <skylar@dangerscience.com>
fnwk.site
folionetwork.site
platform0.app

// Daplie, Inc : https://daplie.com
// Submitted by AJ ONeal <aj@daplie.com>
daplie.me
localhost.daplie.me

// Datto, Inc. : https://www.datto.com/
// Submitted by Philipp Heckel <ph@datto.com>
dattolocal.com
dattorelay.com
dattoweb.com
mydatto.com
dattolocal.net
mydatto.net

// Dansk.net : http://www.dansk.net/
// Submitted by Anani Voule <digital@digital.co.dk>
biz.dk
co.dk
firm.dk
reg.dk
store.dk

// dappnode.io : https://dappnode.io/
// Submitted by Abel Boldu / DAppNode Team <community@dappnode.io>
dyndns.dappnode.io

// dapps.earth : https://dapps.earth/
// Submitted by Daniil Burdakov <icqkill@gmail.com>
*.dapps.earth
*.bzz.dapps.earth

// Dark, Inc. : https://darklang.com
// Submitted by Paul Biggar <ops@darklang.com>
builtwithdark.com

// DataDetect, LLC. : https://datadetect.com
// Submitted by Andrew Banchich <abanchich@sceven.com>
demo.datadetect.com
instance.datadetect.com

// Datawire, Inc : https://www.datawire.io
// Submitted by Richard Li <secalert@datawire.io>
edgestack.me

// DDNS5 : https://ddns5.com
// Submitted by Cameron Elliott <cameron@cameronelliott.com>
ddns5.com

// Debian : https://www.debian.org/
// Submitted by Peter Palfrader / Debian Sysadmin Team <dsa-publicsuffixlist@debian.org>
debian.net

// Deno Land Inc : https://deno.com/
// Submitted by Luca Casonato <hostmaster@deno.com>
deno.dev
deno-staging.dev

// deSEC : https://desec.io/
// Submitted by Peter Thomassen <peter@desec.io>
dedyn.io

// Diher Solutions : https://diher.solutions
// Submitted by Didi Hermawan <mail@diher.solutions>
*.rss.my.id
*.diher.solutions

// DNS Africa Ltd https://dns.business
// Submitted by Calvin Browne <calvin@dns.business>
jozi.biz

// DNShome : https://www.dnshome.de/
// Submitted by Norbert Auler <mail@dnshome.de>
dnshome.de

// DotArai : https://www.dotarai.com/
// Submitted by Atsadawat Netcharadsang <atsadawat@dotarai.co.th>
online.th
shop.th

// DrayTek Corp. : https://www.draytek.com/
// Submitted by Paul Fang <mis@draytek.com>
drayddns.com

// DreamCommerce : https://shoper.pl/
// Submitted by Konrad Kotarba <konrad.kotarba@dreamcommerce.com>
shoparena.pl

// DreamHost : http://www.dreamhost.com/
// Submitted by Andrew Farmer <andrew.farmer@dreamhost.com>
dreamhosters.com

// Drobo : http://www.drobo.com/
// Submitted by Ricardo Padilha <rpadilha@drobo.com>
mydrobo.com

// Drud Holdings, LLC. : https://www.drud.com/
// Submitted by Kevin Bridges <kevin@drud.com>
drud.io
drud.us

// DuckDNS : http://www.duckdns.org/
// Submitted by Richard Harper <richard@duckdns.org>
duckdns.org

// Bip : https://bip.sh
// Submitted by Joel Kennedy <joel@bip.sh>
bip.sh

// bitbridge.net : Submitted by Craig Welch, abeliidev@gmail.com
bitbridge.net

// dy.fi : http://dy.fi/
// Submitted by Heikki Hannikainen <hessu@hes.iki.fi>
dy.fi
tunk.org

// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/
dyndns-at-home.com
dyndns-at-work.com
dyndns-blog.com
dyndns-free.com
dyndns-home.com
dyndns-ip.com
dyndns-mail.com
dyndns-office.com
dyndns-pics.com
dyndns-remote.com
dyndns-server.com
dyndns-web.com
dyndns-wiki.com
dyndns-work.com
dyndns.biz
dyndns.info
dyndns.org
dyndns.tv
at-band-camp.net
ath.cx
barrel-of-knowledge.info
barrell-of-knowledge.info
better-than.tv
blogdns.com
blogdns.net
blogdns.org
blogsite.org
boldlygoingnowhere.org
broke-it.net
buyshouses.net
cechire.com
dnsalias.com
dnsalias.net
dnsalias.org
dnsdojo.com
dnsdojo.net
dnsdojo.org
does-it.net
doesntexist.com
doesntexist.org
dontexist.com
dontexist.net
dontexist.org
doomdns.com
doomdns.org
dvrdns.org
dyn-o-saur.com
dynalias.com
dynalias.net
dynalias.org
dynathome.net
dyndns.ws
endofinternet.net
endofinternet.org
endoftheinternet.org
est-a-la-maison.com
est-a-la-masion.com
est-le-patron.com
est-mon-blogueur.com
for-better.biz
for-more.biz
for-our.info
for-some.biz
for-the.biz
forgot.her.name
forgot.his.name
from-ak.com
from-al.com
from-ar.com
from-az.net
from-ca.com
from-co.net
from-ct.com
from-dc.com
from-de.com
from-fl.com
from-ga.com
from-hi.com
from-ia.com
from-id.com
from-il.com
from-in.com
from-ks.com
from-ky.com
from-la.net
from-ma.com
from-md.com
from-me.org
from-mi.com
from-mn.com
from-mo.com
from-ms.com
from-mt.com
from-nc.com
from-nd.com
from-ne.com
from-nh.com
from-nj.com
from-nm.com
from-nv.com
from-ny.net
from-oh.com
from-ok.com
from-or.com
from-pa.com
from-pr.com
from-ri.com
from-sc.com
from-sd.com
from-tn.com
from-tx.com
from-ut.com
from-va.com
from-vt.com
from-wa.com
from-wi.com
from-wv.com
from-wy.com
ftpaccess.cc
fuettertdasnetz.de
game-host.org
game-server.cc
getmyip.com
gets-it.net
go.dyndns.org
gotdns.com
gotdns.org
groks-the.info
groks-this.info
ham-radio-op.net
here-for-more.info
hobby-site.com
hobby-site.org
home.dyndns.org
homedns.org
homeftp.net
homeftp.org
homeip.net
homelinux.com
homelinux.net
homelinux.org
homeunix.com
homeunix.net
homeunix.org
iamallama.com
in-the-band.net
is-a-anarchist.com
is-a-blogger.com
is-a-bookkeeper.com
is-a-bruinsfan.org
is-a-bulls-fan.com
is-a-candidate.org
is-a-caterer.com
is-a-celticsfan.org
is-a-chef.com
is-a-chef.net
is-a-chef.org
is-a-conservative.com
is-a-cpa.com
is-a-cubicle-slave.com
is-a-democrat.com
is-a-designer.com
is-a-doctor.com
is-a-financialadvisor.com
is-a-geek.com
is-a-geek.net
is-a-geek.org
is-a-green.com
is-a-guru.com
is-a-hard-worker.com
is-a-hunter.com
is-a-knight.org
is-a-landscaper.com
is-a-lawyer.com
is-a-liberal.com
is-a-libertarian.com
is-a-linux-user.org
is-a-llama.com
is-a-musician.com
is-a-nascarfan.com
is-a-nurse.com
is-a-painter.com
is-a-patsfan.org
is-a-personaltrainer.com
is-a-photographer.com
is-a-player.com
is-a-republican.com
is-a-rockstar.com
is-a-socialist.com
is-a-soxfan.org
is-a-student.com
is-a-teacher.com
is-a-techie.com
is-a-therapist.com
is-an-accountant.com
is-an-actor.com
is-an-actress.com
is-an-anarchist.com
is-an-artist.com
is-an-engineer.com
is-an-entertainer.com
is-by.us
is-certified.com
is-found.org
is-gone.com
is-into-anime.com
is-into-cars.com
is-into-cartoons.com
is-into-games.com
is-leet.com
is-lost.org
is-not-certified.com
is-saved.org
is-slick.com
is-uberleet.com
is-very-bad.org
is-very-evil.org
is-very-good.org
is-very-nice.org
is-very-sweet.org
is-with-theband.com
isa-geek.com
isa-geek.net
isa-geek.org
isa-hockeynut.com
issmarterthanyou.com
isteingeek.de
istmein.de
kicks-ass.net
kicks-ass.org
knowsitall.info
land-4-sale.us
lebtimnetz.de
leitungsen.de
likes-pie.com
likescandy.com
merseine.nu
mine.nu
misconfused.org
mypets.ws
myphotos.cc
neat-url.com
office-on-the.net
on-the-web.tv
podzone.net
podzone.org
readmyblog.org
saves-the-whales.com
scrapper-site.net
scrapping.cc
selfip.biz
selfip.com
selfip.info
selfip.net
selfip.org
sells-for-less.com
sells-for-u.com
sells-it.net
sellsyourhome.org
servebbs.com
servebbs.net
servebbs.org
serveftp.net
serveftp.org
servegame.org
shacknet.nu
simple-url.com
space-to-rent.com
stuff-4-sale.org
stuff-4-sale.us
teaches-yoga.com
thruhere.net
traeumtgerade.de
webhop.biz
webhop.info
webhop.net
webhop.org
worse-than.tv
writesthisblog.com

// ddnss.de : https://www.ddnss.de/
// Submitted by Robert Niedziela <webmaster@ddnss.de>
ddnss.de
dyn.ddnss.de
dyndns.ddnss.de
dyndns1.de
dyn-ip24.de
home-webserver.de
dyn.home-webserver.de
myhome-server.de
ddnss.org

// Definima : http://www.definima.com/
// Submitted by Maxence Bitterli <maxence@definima.com>
definima.net
definima.io

// DigitalOcean App Platform : https://www.digitalocean.com/products/app-platform/
// Submitted by Braxton Huggins <psl-maintainers@digitalocean.com>
ondigitalocean.app

// DigitalOcean Spaces : https://www.digitalocean.com/products/spaces/
// Submitted by Robin H. Johnson <psl-maintainers@digitalocean.com>
*.digitaloceanspaces.com

// dnstrace.pro : https://dnstrace.pro/
// Submitted by Chris Partridge <chris@partridge.tech>
bci.dnstrace.pro

// Dynu.com : https://www.dynu.com/
// Submitted by Sue Ye <sue@dynu.com>
ddnsfree.com
ddnsgeek.com
giize.com
gleeze.com
kozow.com
loseyourip.com
ooguy.com
theworkpc.com
casacam.net
dynu.net
accesscam.org
camdvr.org
freeddns.org
mywire.org
webredirect.org
myddns.rocks
blogsite.xyz

// dynv6 : https://dynv6.com
// Submitted by Dominik Menke <dom@digineo.de>
dynv6.net

// Ellucian : https://ellucian.com
// Submitted by Josue Colon <CloudOps-Network@ellucian.com>
elluciancrmadvance.com
elluciancrmadvise.com
elluciancrmrecruit.com

// E4YOU spol. s.r.o. : https://e4you.cz/
// Submitted by Vladimir Dudr <info@e4you.cz>
e4.cz

// eero : https://eero.com/
// Submitted by Yue Kang <eero-dynamic-dns@amazon.com>
eero.online
eero-stage.online

// Elementor : Elementor Ltd.
// Submitted by Anton Barkan <antonb@elementor.com>
elementor.cloud
elementor.cool

// En rootâ€½ : https://en-root.org
// Submitted by Emmanuel Raviart <emmanuel@raviart.com>
en-root.fr

// Enalean SAS: https://www.enalean.com
// Submitted by Thomas Cottier <thomas.cottier@enalean.com>
mytuleap.com
tuleap-partners.com

// ECG Robotics, Inc: https://ecgrobotics.org
// Submitted by <frc1533@ecgrobotics.org>
onred.one
staging.onred.one

// EU.org https://eu.org/
// Submitted by Pierre Beyssac <hostmaster@eu.org>
eu.org
al.eu.org
asso.eu.org
at.eu.org
au.eu.org
be.eu.org
bg.eu.org
ca.eu.org
cd.eu.org
ch.eu.org
cn.eu.org
cy.eu.org
cz.eu.org
de.eu.org
dk.eu.org
edu.eu.org
ee.eu.org
es.eu.org
fi.eu.org
fr.eu.org
gr.eu.org
hr.eu.org
hu.eu.org
ie.eu.org
il.eu.org
in.eu.org
int.eu.org
is.eu.org
it.eu.org
jp.eu.org
kr.eu.org
lt.eu.org
lu.eu.org
lv.eu.org
mc.eu.org
me.eu.org
mk.eu.org
mt.eu.org
my.eu.org
net.eu.org
ng.eu.org
nl.eu.org
no.eu.org
nz.eu.org
paris.eu.org
pl.eu.org
pt.eu.org
q-a.eu.org
ro.eu.org
ru.eu.org
se.eu.org
si.eu.org
sk.eu.org
tr.eu.org
uk.eu.org
us.eu.org

// Eurobyte : https://eurobyte.ru
// Submitted by Evgeniy Subbotin <e.subbotin@eurobyte.ru>
eurodir.ru

// Evennode : http://www.evennode.com/
// Submitted by Michal Kralik <support@evennode.com>
eu-1.evennode.com
eu-2.evennode.com
eu-3.evennode.com
eu-4.evennode.com
us-1.evennode.com
us-2.evennode.com
us-3.evennode.com
us-4.evennode.com

// eDirect Corp. : https://hosting.url.com.tw/
// Submitted by C.S. chang <cschang@corp.url.com.tw>
twmail.cc
twmail.net
twmail.org
mymailer.com.tw
url.tw

// Fabrica Technologies, Inc. : https://www.fabrica.dev/
// Submitted by Eric Jiang <eric@fabrica.dev>
onfabrica.com

// Facebook, Inc.
// Submitted by Peter Ruibal <public-suffix@fb.com>
apps.fbsbx.com

// FAITID : https://faitid.org/
// Submitted by Maxim Alzoba <tech.contact@faitid.org>
// https://www.flexireg.net/stat_info
ru.net
adygeya.ru
bashkiria.ru
bir.ru
cbg.ru
com.ru
dagestan.ru
grozny.ru
kalmykia.ru
kustanai.ru
marine.ru
mordovia.ru
msk.ru
mytis.ru
nalchik.ru
nov.ru
pyatigorsk.ru
spb.ru
vladikavkaz.ru
vladimir.ru
abkhazia.su
adygeya.su
aktyubinsk.su
arkhangelsk.su
armenia.su
ashgabad.su
azerbaijan.su
balashov.su
bashkiria.su
bryansk.su
bukhara.su
chimkent.su
dagestan.su
east-kazakhstan.su
exnet.su
georgia.su
grozny.su
ivanovo.su
jambyl.su
kalmykia.su
kaluga.su
karacol.su
karaganda.su
karelia.su
khakassia.su
krasnodar.su
kurgan.su
kustanai.su
lenug.su
mangyshlak.su
mordovia.su
msk.su
murmansk.su
nalchik.su
navoi.su
north-kazakhstan.su
nov.su
obninsk.su
penza.su
pokrovsk.su
sochi.su
spb.su
tashkent.su
termez.su
togliatti.su
troitsk.su
tselinograd.su
tula.su
tuva.su
vladikavkaz.su
vladimir.su
vologda.su

// Fancy Bits, LLC : http://getchannels.com
// Submitted by Aman Gupta <aman@getchannels.com>
channelsdvr.net
u.channelsdvr.net

// Fastly Inc. : http://www.fastly.com/
// Submitted by Fastly Security <security@fastly.com>
edgecompute.app
fastly-terrarium.com
fastlylb.net
map.fastlylb.net
freetls.fastly.net
map.fastly.net
a.prod.fastly.net
global.prod.fastly.net
a.ssl.fastly.net
b.ssl.fastly.net
global.ssl.fastly.net

// FASTVPS EESTI OU : https://fastvps.ru/
// Submitted by Likhachev Vasiliy <lihachev@fastvps.ru>
fastvps-server.com
fastvps.host
myfast.host
fastvps.site
myfast.space

// Fedora : https://fedoraproject.org/
// submitted by Patrick Uiterwijk <puiterwijk@fedoraproject.org>
fedorainfracloud.org
fedorapeople.org
cloud.fedoraproject.org
app.os.fedoraproject.org
app.os.stg.fedoraproject.org

// FearWorks Media Ltd. : https://fearworksmedia.co.uk
// submitted by Keith Fairley <domains@fearworksmedia.co.uk>
couk.me
ukco.me
conn.uk
copro.uk
hosp.uk

// Fermax : https://fermax.com/
// submitted by Koen Van Isterdael <k.vanisterdael@fermax.be>
mydobiss.com

// FH Muenster : https://www.fh-muenster.de
// Submitted by Robin Naundorf <r.naundorf@fh-muenster.de>
fh-muenster.io

// Filegear Inc. : https://www.filegear.com
// Submitted by Jason Zhu <jason@owtware.com>
filegear.me
filegear-au.me
filegear-de.me
filegear-gb.me
filegear-ie.me
filegear-jp.me
filegear-sg.me

// Firebase, Inc.
// Submitted by Chris Raynor <chris@firebase.com>
firebaseapp.com

// Firewebkit : https://www.firewebkit.com
// Submitted by Majid Qureshi <mqureshi@amrayn.com>
fireweb.app

// FLAP : https://www.flap.cloud
// Submitted by Louis Chemineau <louis@chmn.me>
flap.id

// fly.io: https://fly.io
// Submitted by Kurt Mackey <kurt@fly.io>
fly.dev
edgeapp.net
shw.io

// Flynn : https://flynn.io
// Submitted by Jonathan Rudenberg <jonathan@flynn.io>
flynnhosting.net

// Forgerock : https://www.forgerock.com
// Submitted by Roderick Parr <roderick.parr@forgerock.com>
forgeblocks.com
id.forgerock.io

// Framer : https://www.framer.com
// Submitted by Koen Rouwhorst <koenrh@framer.com>
framer.app
framercanvas.com

// Frusky MEDIA&PR : https://www.frusky.de
// Submitted by Victor Pupynin <hallo@frusky.de>
*.frusky.de

// RavPage : https://www.ravpage.co.il
// Submitted by Roni Horowitz <roni@responder.co.il>
ravpage.co.il

// Frederik Braun https://frederik-braun.com
// Submitted by Frederik Braun <fb@frederik-braun.com>
0e.vc

// Freebox : http://www.freebox.fr
// Submitted by Romain Fliedel <rfliedel@freebox.fr>
freebox-os.com
freeboxos.com
fbx-os.fr
fbxos.fr
freebox-os.fr
freeboxos.fr

// freedesktop.org : https://www.freedesktop.org
// Submitted by Daniel Stone <daniel@fooishbar.org>
freedesktop.org

// freemyip.com : https://freemyip.com
// Submitted by Cadence <contact@freemyip.com>
freemyip.com

// FunkFeuer - Verein zur FÃ¶rderung freier Netze : https://www.funkfeuer.at
// Submitted by Daniel A. Maierhofer <vorstand@funkfeuer.at>
wien.funkfeuer.at

// Futureweb OG : http://www.futureweb.at
// Submitted by Andreas Schnederle-Wagner <schnederle@futureweb.at>
*.futurecms.at
*.ex.futurecms.at
*.in.futurecms.at
futurehosting.at
futuremailing.at
*.ex.ortsinfo.at
*.kunden.ortsinfo.at
*.statics.cloud

// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains
// Submitted by David Illsley <david.illsley@digital.cabinet-office.gov.uk>
service.gov.uk

// Gehirn Inc. : https://www.gehirn.co.jp/
// Submitted by Kohei YOSHIDA <tech@gehirn.co.jp>
gehirn.ne.jp
usercontent.jp

// Gentlent, Inc. : https://www.gentlent.com
// Submitted by Tom Klein <tom@gentlent.com>
gentapps.com
gentlentapis.com
lab.ms
cdn-edges.net

// Ghost Foundation : https://ghost.org
// Submitted by Matt Hanley <security@ghost.org>
ghost.io

// GignoSystemJapan: http://gsj.bz
// Submitted by GignoSystemJapan <kakutou-ec@gsj.bz>
gsj.bz

// GitHub, Inc.
// Submitted by Patrick Toomey <security@github.com>
githubusercontent.com
githubpreview.dev
github.io

// GitLab, Inc.
// Submitted by Alex Hanselka <alex@gitlab.com>
gitlab.io

// Gitplac.si - https://gitplac.si
// Submitted by AljaÅ¾ Starc <me@aljaxus.eu>
gitapp.si
gitpage.si

// Glitch, Inc : https://glitch.com
// Submitted by Mads Hartmann <mads@glitch.com>
glitch.me

// Global NOG Alliance : https://nogalliance.org/
// Submitted by Sander Steffann <sander@nogalliance.org>
nog.community

// Globe Hosting SRL : https://www.globehosting.com/
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
co.ro
shop.ro

// GMO Pepabo, Inc. : https://pepabo.com/
// Submitted by dojineko <admin@pepabo.com>
lolipop.io

// GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/
// Submitted by Tom Whitwell <gov-uk-paas-support@digital.cabinet-office.gov.uk>
cloudapps.digital
london.cloudapps.digital

// GOV.UK Pay : https://www.payments.service.gov.uk/
// Submitted by Richard Baker <richard.baker@digital.cabinet-office.gov.uk>
pymnt.uk

// UKHomeOffice : https://www.gov.uk/government/organisations/home-office
// Submitted by Jon Shanks <jon.shanks@digital.homeoffice.gov.uk>
homeoffice.gov.uk

// GlobeHosting, Inc.
// Submitted by Zoltan Egresi <egresi@globehosting.com>
ro.im

// GoIP DNS Services : http://www.goip.de
// Submitted by Christian Poulter <milchstrasse@goip.de>
goip.de

// Google, Inc.
// Submitted by Eduardo Vela <evn@google.com>
run.app
a.run.app
web.app
*.0emm.com
appspot.com
*.r.appspot.com
codespot.com
googleapis.com
googlecode.com
pagespeedmobilizer.com
publishproxy.com
withgoogle.com
withyoutube.com
*.gateway.dev
cloud.goog
translate.goog
*.usercontent.goog
cloudfunctions.net
blogspot.ae
blogspot.al
blogspot.am
blogspot.ba
blogspot.be
blogspot.bg
blogspot.bj
blogspot.ca
blogspot.cf
blogspot.ch
blogspot.cl
blogspot.co.at
blogspot.co.id
blogspot.co.il
blogspot.co.ke
blogspot.co.nz
blogspot.co.uk
blogspot.co.za
blogspot.com
blogspot.com.ar
blogspot.com.au
blogspot.com.br
blogspot.com.by
blogspot.com.co
blogspot.com.cy
blogspot.com.ee
blogspot.com.eg
blogspot.com.es
blogspot.com.mt
blogspot.com.ng
blogspot.com.tr
blogspot.com.uy
blogspot.cv
blogspot.cz
blogspot.de
blogspot.dk
blogspot.fi
blogspot.fr
blogspot.gr
blogspot.hk
blogspot.hr
blogspot.hu
blogspot.ie
blogspot.in
blogspot.is
blogspot.it
blogspot.jp
blogspot.kr
blogspot.li
blogspot.lt
blogspot.lu
blogspot.md
blogspot.mk
blogspot.mr
blogspot.mx
blogspot.my
blogspot.nl
blogspot.no
blogspot.pe
blogspot.pt
blogspot.qa
blogspot.re
blogspot.ro
blogspot.rs
blogspot.ru
blogspot.se
blogspot.sg
blogspot.si
blogspot.sk
blogspot.sn
blogspot.td
blogspot.tw
blogspot.ug
blogspot.vn

// Goupile : https://goupile.fr
// Submitted by Niels Martignene <hello@goupile.fr>
goupile.fr

// Group 53, LLC : https://www.group53.com
// Submitted by Tyler Todd <noc@nova53.net>
awsmppl.com

// GÃ¼nstigBestellen : https://gÃ¼nstigbestellen.de
// Submitted by Furkan Akkoc <info@hendelzon.de>
gÃ¼nstigbestellen.de
gÃ¼nstigliefern.de

// Hakaran group: http://hakaran.cz
// Submited by Arseniy Sokolov <security@hakaran.cz>
fin.ci
free.hr
caa.li
ua.rs
conf.se

// Handshake : https://handshake.org
// Submitted by Mike Damm <md@md.vc>
hs.zone
hs.run

// Hashbang : https://hashbang.sh
hashbang.sh

// Hasura : https://hasura.io
// Submitted by Shahidh K Muhammed <shahidh@hasura.io>
hasura.app
hasura-app.io

// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab Pages): https://www.hs-heilbronn.de
// Submitted by Richard Zowalla <mi-admin@hs-heilbronn.de>
pages.it.hs-heilbronn.de

// Hepforge : https://www.hepforge.org
// Submitted by David Grellscheid <admin@hepforge.org>
hepforge.org

// Heroku : https://www.heroku.com/
// Submitted by Tom Maher <tmaher@heroku.com>
herokuapp.com
herokussl.com

// Hibernating Rhinos
// Submitted by Oren Eini <oren@ravendb.net>
myravendb.com
ravendb.community
ravendb.me
development.run
ravendb.run

// home.pl S.A.: https://home.pl
// Submited by Krzysztof Wolski <krzysztof.wolski@home.eu>
homesklep.pl

// Hong Kong Productivity Council: https://www.hkpc.org/
// Submitted by SECaaS Team <summchan@hkpc.org>
secaas.hk

// HOSTBIP REGISTRY : https://www.hostbip.com/
// Submitted by Atanunu Igbunuroghene <publicsuffixlist@hostbip.com>
orx.biz
biz.gl
col.ng
firm.ng
gen.ng
ltd.ng
ngo.ng
edu.scot
sch.so
org.yt

// HostyHosting (hostyhosting.com)
hostyhosting.io

// HÃ¤kkinen.fi
// Submitted by Eero HÃ¤kkinen <Eero+psl@HÃ¤kkinen.fi>
hÃ¤kkinen.fi

// Ici la Lune : http://www.icilalune.com/
// Submitted by Simon Morvan <simon@icilalune.com>
*.moonscale.io
moonscale.net

// iki.fi
// Submitted by Hannu Aronsson <haa@iki.fi>
iki.fi

// Impertrix Solutions : <https://impertrixcdn.com>
// Submitted by Zhixiang Zhao <csuite@impertrix.com>
impertrixcdn.com
impertrix.com

// Incsub, LLC: https://incsub.com/
// Submitted by Aaron Edwards <sysadmins@incsub.com>
smushcdn.com
wphostedmail.com
wpmucdn.com
tempurl.host
wpmudev.host

// Individual Network Berlin e.V. : https://www.in-berlin.de/
// Submitted by Christian Seitz <chris@in-berlin.de>
dyn-berlin.de
in-berlin.de
in-brb.de
in-butter.de
in-dsl.de
in-dsl.net
in-dsl.org
in-vpn.de
in-vpn.net
in-vpn.org

// info.at : http://www.info.at/
biz.at
info.at

// info.cx : http://info.cx
// Submitted by Jacob Slater <whois@igloo.to>
info.cx

// Interlegis : http://www.interlegis.leg.br
// Submitted by Gabriel Ferreira <registrobr@interlegis.leg.br>
ac.leg.br
al.leg.br
am.leg.br
ap.leg.br
ba.leg.br
ce.leg.br
df.leg.br
es.leg.br
go.leg.br
ma.leg.br
mg.leg.br
ms.leg.br
mt.leg.br
pa.leg.br
pb.leg.br
pe.leg.br
pi.leg.br
pr.leg.br
rj.leg.br
rn.leg.br
ro.leg.br
rr.leg.br
rs.leg.br
sc.leg.br
se.leg.br
sp.leg.br
to.leg.br

// intermetrics GmbH : https://pixolino.com/
// Submitted by Wolfgang Schwarz <admin@intermetrics.de>
pixolino.com

// Internet-Pro, LLP: https://netangels.ru/
// Submited by Vasiliy Sheredeko <piphon@gmail.com>
na4u.ru

// iopsys software solutions AB : https://iopsys.eu/
// Submitted by Roman Azarenko <roman.azarenko@iopsys.eu>
iopsys.se

// IPiFony Systems, Inc. : https://www.ipifony.com/
// Submitted by Matthew Hardeman <mhardeman@ipifony.com>
ipifony.net

// IServ GmbH : https://iserv.eu
// Submitted by Kim-Alexander Brodowski <info@iserv.eu>
mein-iserv.de
schulserver.de
test-iserv.de
iserv.dev

// I-O DATA DEVICE, INC. : http://www.iodata.com/
// Submitted by Yuji Minagawa <domains-admin@iodata.jp>
iobb.net

// Jelastic, Inc. : https://jelastic.com/
// Submited by Ihor Kolodyuk <ik@jelastic.com>
mel.cloudlets.com.au
cloud.interhostsolutions.be
users.scale.virtualcloud.com.br
mycloud.by
alp1.ae.flow.ch
appengine.flow.ch
es-1.axarnet.cloud
diadem.cloud
vip.jelastic.cloud
jele.cloud
it1.eur.aruba.jenv-aruba.cloud
it1.jenv-aruba.cloud
keliweb.cloud
cs.keliweb.cloud
oxa.cloud
tn.oxa.cloud
uk.oxa.cloud
primetel.cloud
uk.primetel.cloud
ca.reclaim.cloud
uk.reclaim.cloud
us.reclaim.cloud
ch.trendhosting.cloud
de.trendhosting.cloud
jele.club
amscompute.com
clicketcloud.com
dopaas.com
hidora.com
paas.hosted-by-previder.com
rag-cloud.hosteur.com
rag-cloud-ch.hosteur.com
jcloud.ik-server.com
jcloud-ver-jpc.ik-server.com
demo.jelastic.com
kilatiron.com
paas.massivegrid.com
jed.wafaicloud.com
lon.wafaicloud.com
ryd.wafaicloud.com
j.scaleforce.com.cy
jelastic.dogado.eu
fi.cloudplatform.fi
demo.datacenter.fi
paas.datacenter.fi
jele.host
mircloud.host
paas.beebyte.io
sekd1.beebyteapp.io
jele.io
cloud-fr1.unispace.io
jc.neen.it
cloud.jelastic.open.tim.it
jcloud.kz
upaas.kazteleport.kz
cloudjiffy.net
fra1-de.cloudjiffy.net
west1-us.cloudjiffy.net
jls-sto1.elastx.net
jls-sto2.elastx.net
jls-sto3.elastx.net
faststacks.net
fr-1.paas.massivegrid.net
lon-1.paas.massivegrid.net
lon-2.paas.massivegrid.net
ny-1.paas.massivegrid.net
ny-2.paas.massivegrid.net
sg-1.paas.massivegrid.net
jelastic.saveincloud.net
nordeste-idc.saveincloud.net
j.scaleforce.net
jelastic.tsukaeru.net
sdscloud.pl
unicloud.pl
mircloud.ru
jelastic.regruhosting.ru
enscaled.sg
jele.site
jelastic.team
orangecloud.tn
j.layershift.co.uk
phx.enscaled.us
mircloud.us

// Jino : https://www.jino.ru
// Submitted by Sergey Ulyashin <ulyashin@jino.ru>
myjino.ru
*.hosting.myjino.ru
*.landing.myjino.ru
*.spectrum.myjino.ru
*.vps.myjino.ru

// Jotelulu S.L. : https://jotelulu.com
// Submitted by Daniel FariÃ±a <ingenieria@jotelulu.com>
jotelulu.cloud

// Joyent : https://www.joyent.com/
// Submitted by Brian Bennett <brian.bennett@joyent.com>
*.triton.zone
*.cns.joyent.com

// JS.ORG : http://dns.js.org
// Submitted by Stefan Keim <admin@js.org>
js.org

// KaasHosting : http://www.kaashosting.nl/
// Submitted by Wouter Bakker <hostmaster@kaashosting.nl>
kaas.gg
khplay.nl

// Keyweb AG : https://www.keyweb.de
// Submitted by Martin Dannehl <postmaster@keymachine.de>
keymachine.de

// KingHost : https://king.host
// Submitted by Felipe Keller Braz <felipebraz@kinghost.com.br>
kinghost.net
uni5.net

// KnightPoint Systems, LLC : http://www.knightpoint.com/
// Submitted by Roy Keene <rkeene@knightpoint.com>
knightpoint.systems

// KUROKU LTD : https://kuroku.ltd/
// Submitted by DisposaBoy <security@oya.to>
oya.to

// Katholieke Universiteit Leuven: https://www.kuleuven.be
// Submitted by Abuse KU Leuven <abuse@kuleuven.be>
kuleuven.cloud
ezproxy.kuleuven.be

// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf
co.krd
edu.krd

// Krellian Ltd. : https://krellian.com
// Submitted by Ben Francis <ben@krellian.com>
krellian.net
webthings.io

// LCube - Professional hosting e.K. : https://www.lcube-webhosting.de
// Submitted by Lars Laehn <info@lcube.de>
git-repos.de
lcube-server.de
svn-repos.de

// Leadpages : https://www.leadpages.net
// Submitted by Greg Dallavalle <domains@leadpages.net>
leadpages.co
lpages.co
lpusercontent.com

// Lelux.fi : https://lelux.fi/
// Submitted by Lelux Admin <publisuffix@lelux.site>
lelux.site

// Lifetime Hosting : https://Lifetime.Hosting/
// Submitted by Mike Fillator <support@lifetime.hosting>
co.business
co.education
co.events
co.financial
co.network
co.place
co.technology

// Lightmaker Property Manager, Inc. : https://app.lmpm.com/
// Submitted by Greg Holland <greg.holland@lmpm.com>
app.lmpm.com

// linkyard ldt: https://www.linkyard.ch/
// Submitted by Mario Siegenthaler <mario.siegenthaler@linkyard.ch>
linkyard.cloud
linkyard-cloud.ch

// Linode : https://linode.com
// Submitted by <security@linode.com>
members.linode.com
*.nodebalancer.linode.com
*.linodeobjects.com
ip.linodeusercontent.com

// LiquidNet Ltd : http://www.liquidnetlimited.com/
// Submitted by Victor Velchev <admin@liquidnetlimited.com>
we.bs

// localzone.xyz
// Submitted by Kenny Niehage <hello@yahe.sh>
localzone.xyz

// Log'in Line : https://www.loginline.com/
// Submitted by RÃ©mi Mach <remi.mach@loginline.com>
loginline.app
loginline.dev
loginline.io
loginline.services
loginline.site

// Lokalized : https://lokalized.nl
// Submitted by Noah Taheij <noah@lokalized.nl>
servers.run

// LÃµhmus Family, The
// Submitted by Heiki LÃµhmus <hostmaster at lohmus dot me>
lohmus.me

// LubMAN UMCS Sp. z o.o : https://lubman.pl/
// Submitted by Ireneusz Maliszewski <ireneusz.maliszewski@lubman.pl>
krasnik.pl
leczna.pl
lubartow.pl
lublin.pl
poniatowa.pl
swidnik.pl

// Lug.org.uk : https://lug.org.uk
// Submitted by Jon Spriggs <admin@lug.org.uk>
glug.org.uk
lug.org.uk
lugs.org.uk

// Lukanet Ltd : https://lukanet.com
// Submitted by Anton Avramov <register@lukanet.com>
barsy.bg
barsy.co.uk
barsyonline.co.uk
barsycenter.com
barsyonline.com
barsy.club
barsy.de
barsy.eu
barsy.in
barsy.info
barsy.io
barsy.me
barsy.menu
barsy.mobi
barsy.net
barsy.online
barsy.org
barsy.pro
barsy.pub
barsy.ro
barsy.shop
barsy.site
barsy.support
barsy.uk

// Magento Commerce
// Submitted by Damien Tournoud <dtournoud@magento.cloud>
*.magentosite.cloud

// May First - People Link : https://mayfirst.org/
// Submitted by Jamie McClelland <info@mayfirst.org>
mayfirst.info
mayfirst.org

// Mail.Ru Group : https://hb.cldmail.ru
// Submitted by Ilya Zaretskiy <zaretskiy@corp.mail.ru>
hb.cldmail.ru

// Mail Transfer Platform : https://www.neupeer.com
// Submitted by Li Hui <lihui@neupeer.com>
cn.vu

// Maze Play: https://www.mazeplay.com
// Submitted by Adam Humpherys <adam@mws.dev>
mazeplay.com

// mcpe.me : https://mcpe.me
// Submitted by Noa Heyl <hi@noa.dev>
mcpe.me

// McHost : https://mchost.ru
// Submitted by Evgeniy Subbotin <e.subbotin@mchost.ru>
mcdir.me
mcdir.ru
mcpre.ru
vps.mcdir.ru

// Mediatech : https://mediatech.by
// Submitted by Evgeniy Kozhuhovskiy <ugenk@mediatech.by>
mediatech.by
mediatech.dev

// Medicom Health : https://medicomhealth.com
// Submitted by Michael Olson <molson@medicomhealth.com>
hra.health

// Memset hosting : https://www.memset.com
// Submitted by Tom Whitwell <domains@memset.com>
miniserver.com
memset.net

// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/
// Submitted by ZdenÄ›k Å ustr <zdenek.sustr@cesnet.cz>
*.cloud.metacentrum.cz
custom.metacentrum.cz

// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/
// Submitted by Radim JanÄ�a <janca@cesnet.cz>
flt.cloud.muni.cz
usr.cloud.muni.cz

// Meteor Development Group : https://www.meteor.com/hosting
// Submitted by Pierre Carrier <pierre@meteor.com>
meteorapp.com
eu.meteorapp.com

// Michau Enterprises Limited : http://www.co.pl/
co.pl

// Microsoft Corporation : http://microsoft.com
// Submitted by Mitch Webster <miwebst@microsoft.com>
*.azurecontainer.io
azurewebsites.net
azure-mobile.net
cloudapp.net
azurestaticapps.net
centralus.azurestaticapps.net
eastasia.azurestaticapps.net
eastus2.azurestaticapps.net
westeurope.azurestaticapps.net
westus2.azurestaticapps.net

// minion.systems : http://minion.systems
// Submitted by Robert BÃ¶ttinger <r@minion.systems>
csx.cc

// Mintere : https://mintere.com/
// Submitted by Ben Aubin <security@mintere.com>
mintere.site

// MobileEducation, LLC : https://joinforte.com
// Submitted by Grayson Martin <grayson.martin@mobileeducation.us>
forte.id

// Mozilla Corporation : https://mozilla.com
// Submitted by Ben Francis <bfrancis@mozilla.com>
mozilla-iot.org

// Mozilla Foundation : https://mozilla.org/
// Submitted by glob <glob@mozilla.com>
bmoattachments.org

// MSK-IX : https://www.msk-ix.ru/
// Submitted by Khannanov Roman <r.khannanov@msk-ix.ru>
net.ru
org.ru
pp.ru

// Mythic Beasts : https://www.mythic-beasts.com
// Submitted by Paul Cammish <kelduum@mythic-beasts.com>
hostedpi.com
customer.mythic-beasts.com
caracal.mythic-beasts.com
fentiger.mythic-beasts.com
lynx.mythic-beasts.com
ocelot.mythic-beasts.com
oncilla.mythic-beasts.com
onza.mythic-beasts.com
sphinx.mythic-beasts.com
vs.mythic-beasts.com
x.mythic-beasts.com
yali.mythic-beasts.com
cust.retrosnub.co.uk

// Nabu Casa : https://www.nabucasa.com
// Submitted by Paulus Schoutsen <infra@nabucasa.com>
ui.nabu.casa

// Names.of.London : https://names.of.london/
// Submitted by James Stevens <registry[at]names.of.london> or <publiclist[at]jrcs.net>
pony.club
of.fashion
in.london
of.london
from.marketing
with.marketing
for.men
repair.men
and.mom
for.mom
for.one
under.one
for.sale
that.win
from.work
to.work

// Netlify : https://www.netlify.com
// Submitted by Jessica Parsons <jessica@netlify.com>
netlify.app

// Neustar Inc.
// Submitted by Trung Tran <Trung.Tran@neustar.biz>
4u.com

// ngrok : https://ngrok.com/
// Submitted by Alan Shreve <alan@ngrok.com>
ngrok.io

// Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/
// Submitted by Nicholas Ford <nick@nimbushosting.co.uk>
nh-serv.co.uk

// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/
// Submitted by Jeff Wheelhouse <support@nearlyfreespeech.net>
nfshost.com

// Noop : https://noop.app
// Submitted by Nathaniel Schweinberg <noop@rearc.io>
*.developer.app
noop.app

// Northflank Ltd. : https://northflank.com/
// Submitted by Marco Suter <marco@northflank.com>
*.northflank.app
*.code.run

// Noticeable : https://noticeable.io
// Submitted by Laurent Pellegrino <security@noticeable.io>
noticeable.news

// Now-DNS : https://now-dns.com
// Submitted by Steve Russell <steve@now-dns.com>
dnsking.ch
mypi.co
n4t.co
001www.com
ddnslive.com
myiphost.com
forumz.info
16-b.it
32-b.it
64-b.it
soundcast.me
tcp4.me
dnsup.net
hicam.net
now-dns.net
ownip.net
vpndns.net
dynserv.org
now-dns.org
x443.pw
now-dns.top
ntdll.top
freeddns.us
crafting.xyz
zapto.xyz

// nsupdate.info : https://www.nsupdate.info/
// Submitted by Thomas Waldmann <info@nsupdate.info>
nsupdate.info
nerdpol.ovh

// No-IP.com : https://noip.com/
// Submitted by Deven Reza <publicsuffixlist@noip.com>
blogsyte.com
brasilia.me
cable-modem.org
ciscofreak.com
collegefan.org
couchpotatofries.org
damnserver.com
ddns.me
ditchyourip.com
dnsfor.me
dnsiskinky.com
dvrcam.info
dynns.com
eating-organic.net
fantasyleague.cc
geekgalaxy.com
golffan.us
health-carereform.com
homesecuritymac.com
homesecuritypc.com
hopto.me
ilovecollege.info
loginto.me
mlbfan.org
mmafan.biz
myactivedirectory.com
mydissent.net
myeffect.net
mymediapc.net
mypsx.net
mysecuritycamera.com
mysecuritycamera.net
mysecuritycamera.org
net-freaks.com
nflfan.org
nhlfan.net
no-ip.ca
no-ip.co.uk
no-ip.net
noip.us
onthewifi.com
pgafan.net
point2this.com
pointto.us
privatizehealthinsurance.net
quicksytes.com
read-books.org
securitytactics.com
serveexchange.com
servehumour.com
servep2p.com
servesarcasm.com
stufftoread.com
ufcfan.org
unusualperson.com
workisboring.com
3utilities.com
bounceme.net
ddns.net
ddnsking.com
gotdns.ch
hopto.org
myftp.biz
myftp.org
myvnc.com
no-ip.biz
no-ip.info
no-ip.org
noip.me
redirectme.net
servebeer.com
serveblog.net
servecounterstrike.com
serveftp.com
servegame.com
servehalflife.com
servehttp.com
serveirc.com
serveminecraft.net
servemp3.com
servepics.com
servequake.com
sytes.net
webhop.me
zapto.org

// NodeArt : https://nodeart.io
// Submitted by Konstantin Nosov <Nosov@nodeart.io>
stage.nodeart.io

// Nodum B.V. : https://nodum.io/
// Submitted by Wietse Wind <hello+publicsuffixlist@nodum.io>
nodum.co
nodum.io

// Nucleos Inc. : https://nucleos.com
// Submitted by Piotr Zduniak <piotr@nucleos.com>
pcloud.host

// NYC.mn : http://www.information.nyc.mn
// Submitted by Matthew Brown <mattbrown@nyc.mn>
nyc.mn

// Observable, Inc. : https://observablehq.com
// Submitted by Mike Bostock <dns@observablehq.com>
static.observableusercontent.com

// Octopodal Solutions, LLC. : https://ulterius.io/
// Submitted by Andrew Sampson <andrew@ulterius.io>
cya.gg

// OMG.LOL : <https://omg.lol>
// Submitted by Adam Newbold <adam@omg.lol>
omg.lol

// Omnibond Systems, LLC. : https://www.omnibond.com
// Submitted by Cole Estep <cole@omnibond.com>
cloudycluster.net

// OmniWe Limited: https://omniwe.com
// Submitted by Vicary Archangel <vicary@omniwe.com>
omniwe.site

// One.com: https://www.one.com/
// Submitted by Jacob Bunk Nielsen <jbn@one.com>
service.one

// One Fold Media : http://www.onefoldmedia.com/
// Submitted by Eddie Jones <eddie@onefoldmedia.com>
nid.io

// Open Social : https://www.getopensocial.com/
// Submitted by Alexander Varwijk <security@getopensocial.com>
opensocial.site

// OpenCraft GmbH : http://opencraft.com/
// Submitted by Sven Marnach <sven@opencraft.com>
opencraft.hosting

// OpenResearch GmbH: https://openresearch.com/
// Submitted by Philipp Schmid <ops@openresearch.com>
orsites.com

// Opera Software, A.S.A.
// Submitted by Yngve Pettersen <yngve@opera.com>
operaunite.com

// Oursky Limited : https://authgear.com/, https://skygear.io/
// Submited by Authgear Team <hello@authgear.com>, Skygear Developer <hello@skygear.io>
authgear-staging.com
authgearapps.com
skygearapp.com

// OutSystems
// Submitted by Duarte Santos <domain-admin@outsystemscloud.com>
outsystemscloud.com

// OVHcloud: https://ovhcloud.com
// Submitted by Vincent CassÃ© <vincent.casse@ovhcloud.com>
*.webpaas.ovh.net
*.hosting.ovh.net

// OwnProvider GmbH: http://www.ownprovider.com
// Submitted by Jan Moennich <jan.moennich@ownprovider.com>
ownprovider.com
own.pm

// OwO : https://whats-th.is/
// Submitted by Dean Sheather <dean@deansheather.com>
*.owo.codes

// OX : http://www.ox.rs
// Submitted by Adam Grand <webmaster@mail.ox.rs>
ox.rs

// oy.lc
// Submitted by Charly Coste <changaco@changaco.oy.lc>
oy.lc

// Pagefog : https://pagefog.com/
// Submitted by Derek Myers <derek@pagefog.com>
pgfog.com

// Pagefront : https://www.pagefronthq.com/
// Submitted by Jason Kriss <jason@pagefronthq.com>
pagefrontapp.com

// PageXL : https://pagexl.com
// Submitted by Yann Guichard <yann@pagexl.com>
pagexl.com

// Paywhirl, Inc : https://paywhirl.com/
// Submitted by Daniel Netzer <dan@paywhirl.com>
*.paywhirl.com

// pcarrier.ca Software Inc: https://pcarrier.ca/
// Submitted by Pierre Carrier <pc@rrier.ca>
bar0.net
bar1.net
bar2.net
rdv.to

// .pl domains (grandfathered)
art.pl
gliwice.pl
krakow.pl
poznan.pl
wroc.pl
zakopane.pl

// Pantheon Systems, Inc. : https://pantheon.io/
// Submitted by Gary Dylina <gary@pantheon.io>
pantheonsite.io
gotpantheon.com

// Peplink | Pepwave : http://peplink.com/
// Submitted by Steve Leung <steveleung@peplink.com>
mypep.link

// Perspecta : https://perspecta.com/
// Submitted by Kenneth Van Alstyne <kvanalstyne@perspecta.com>
perspecta.cloud

// PE Ulyanov Kirill Sergeevich : https://airy.host
// Submitted by Kirill Ulyanov <k.ulyanov@airy.host>
lk3.ru

// Planet-Work : https://www.planet-work.com/
// Submitted by FrÃ©dÃ©ric VANNIÃˆRE <f.vanniere@planet-work.com>
on-web.fr

// Platform.sh : https://platform.sh
// Submitted by Nikola Kotur <nikola@platform.sh>
bc.platform.sh
ent.platform.sh
eu.platform.sh
us.platform.sh
*.platformsh.site
*.tst.site

// Platter: https://platter.dev
// Submitted by Patrick Flor <patrick@platter.dev>
platter-app.com
platter-app.dev
platterp.us

// Plesk : https://www.plesk.com/
// Submitted by Anton Akhtyamov <program-managers@plesk.com>
pdns.page
plesk.page
pleskns.com

// Port53 : https://port53.io/
// Submitted by Maximilian Schieder <maxi@zeug.co>
dyn53.io

// Positive Codes Technology Company : http://co.bn/faq.html
// Submitted by Zulfais <pc@co.bn>
co.bn

// Postman, Inc : https://postman.com
// Submitted by Rahul Dhawan <security@postman.com>
postman-echo.com
pstmn.io
mock.pstmn.io
httpbin.org

//prequalifyme.today : https://prequalifyme.today
//Submitted by DeepakTiwari deepak@ivylead.io
prequalifyme.today

// prgmr.com : https://prgmr.com/
// Submitted by Sarah Newman <owner@prgmr.com>
xen.prgmr.com

// priv.at : http://www.nic.priv.at/
// Submitted by registry <lendl@nic.at>
priv.at

// privacytools.io : https://www.privacytools.io/
// Submitted by Jonah Aragon <jonah@privacytools.io>
prvcy.page

// Protocol Labs : https://protocol.ai/
// Submitted by Michael Burns <noc@protocol.ai>
*.dweb.link

// Protonet GmbH : http://protonet.io
// Submitted by Martin Meier <admin@protonet.io>
protonet.io

// Publication Presse Communication SARL : https://ppcom.fr
// Submitted by Yaacov Akiba Slama <admin@chirurgiens-dentistes-en-france.fr>
chirurgiens-dentistes-en-france.fr
byen.site

// pubtls.org: https://www.pubtls.org
// Submitted by Kor Nielsen <kor@pubtls.org>
pubtls.org

// PythonAnywhere LLP: https://www.pythonanywhere.com
// Submitted by Giles Thomas <giles@pythonanywhere.com>
pythonanywhere.com
eu.pythonanywhere.com

// QOTO, Org.
// Submitted by Jeffrey Phillips Freeman <jeffrey.freeman@qoto.org>
qoto.io

// Qualifio : https://qualifio.com/
// Submitted by Xavier De Cock <xdecock@gmail.com>
qualifioapp.com

// QuickBackend: https://www.quickbackend.com
// Submitted by Dani Biro <dani@pymet.com>
qbuser.com

// Rad Web Hosting: https://radwebhosting.com
// Submitted by Scott Claeys <s.claeys@radwebhosting.com>
cloudsite.builders

// Redgate Software: https://red-gate.com
// Submitted by Andrew Farries <andrew.farries@red-gate.com>
instances.spawn.cc

// Redstar Consultants : https://www.redstarconsultants.com/
// Submitted by Jons Slemmer <jons@redstarconsultants.com>
instantcloud.cn

// Russian Academy of Sciences
// Submitted by Tech Support <support@rasnet.ru>
ras.ru

// QA2
// Submitted by Daniel Dent (https://www.danieldent.com/)
qa2.com

// QCX
// Submitted by Cassandra Beelen <cassandra@beelen.one>
qcx.io
*.sys.qcx.io

// QNAP System Inc : https://www.qnap.com
// Submitted by Nick Chang <nickchang@qnap.com>
dev-myqnapcloud.com
alpha-myqnapcloud.com
myqnapcloud.com

// Quip : https://quip.com
// Submitted by Patrick Linehan <plinehan@quip.com>
*.quipelements.com

// Qutheory LLC : http://qutheory.io
// Submitted by Jonas Schwartz <jonas@qutheory.io>
vapor.cloud
vaporcloud.io

// Rackmaze LLC : https://www.rackmaze.com
// Submitted by Kirill Pertsev <kika@rackmaze.com>
rackmaze.com
rackmaze.net

// Rakuten Games, Inc : https://dev.viberplay.io
// Submitted by Joshua Zhang <public-suffix@rgames.jp>
g.vbrplsbx.io

// Rancher Labs, Inc : https://rancher.com
// Submitted by Vincent Fiduccia <domains@rancher.com>
*.on-k3s.io
*.on-rancher.cloud
*.on-rio.io

// Read The Docs, Inc : https://www.readthedocs.org
// Submitted by David Fischer <team@readthedocs.org>
readthedocs.io

// Red Hat, Inc. OpenShift : https://openshift.redhat.com/
// Submitted by Tim Kramer <tkramer@rhcloud.com>
rhcloud.com

// Render : https://render.com
// Submitted by Anurag Goel <dev@render.com>
app.render.com
onrender.com

// Repl.it : https://repl.it
// Submitted by Mason Clayton <mason@repl.it>
repl.co
id.repl.co
repl.run

// Resin.io : https://resin.io
// Submitted by Tim Perry <tim@resin.io>
resindevice.io
devices.resinstaging.io

// RethinkDB : https://www.rethinkdb.com/
// Submitted by Chris Kastorff <info@rethinkdb.com>
hzc.io

// Revitalised Limited : http://www.revitalised.co.uk
// Submitted by Jack Price <jack@revitalised.co.uk>
wellbeingzone.eu
wellbeingzone.co.uk

// Rico Developments Limited : https://adimo.co
// Submitted by Colin Brown <hello@adimo.co>
adimo.co.uk

// Riseup Networks : https://riseup.net
// Submitted by Micah Anderson <micah@riseup.net>
itcouldbewor.se

// Rochester Institute of Technology : http://www.rit.edu/
// Submitted by Jennifer Herting <jchits@rit.edu>
git-pages.rit.edu

// Rusnames Limited: http://rusnames.ru/
// Submitted by Sergey Zotov <admin@rusnames.ru>
Ð±Ð¸Ð·.Ñ€ÑƒÑ�
ÐºÐ¾Ð¼.Ñ€ÑƒÑ�
ÐºÑ€Ñ‹Ð¼.Ñ€ÑƒÑ�
Ð¼Ð¸Ñ€.Ñ€ÑƒÑ�
Ð¼Ñ�Ðº.Ñ€ÑƒÑ�
Ð¾Ñ€Ð³.Ñ€ÑƒÑ�
Ñ�Ð°Ð¼Ð°Ñ€Ð°.Ñ€ÑƒÑ�
Ñ�Ð¾Ñ‡Ð¸.Ñ€ÑƒÑ�
Ñ�Ð¿Ð±.Ñ€ÑƒÑ�
Ñ�.Ñ€ÑƒÑ�

// Sandstorm Development Group, Inc. : https://sandcats.io/
// Submitted by Asheesh Laroia <asheesh@sandstorm.io>
sandcats.io

// SBE network solutions GmbH : https://www.sbe.de/
// Submitted by Norman Meilick <nm@sbe.de>
logoip.de
logoip.com

// schokokeks.org GbR : https://schokokeks.org/
// Submitted by Hanno BÃ¶ck <hanno@schokokeks.org>
schokokeks.net

// Scottish Government: https://www.gov.scot
// Submitted by Martin Ellis <martin.ellis@gov.scot>
gov.scot
service.gov.scot

// Scry Security : http://www.scrysec.com
// Submitted by Shante Adam <shante@skyhat.io>
scrysec.com

// Securepoint GmbH : https://www.securepoint.de
// Submitted by Erik Anders <erik.anders@securepoint.de>
firewall-gateway.com
firewall-gateway.de
my-gateway.de
my-router.de
spdns.de
spdns.eu
firewall-gateway.net
my-firewall.org
myfirewall.org
spdns.org

// Seidat : https://www.seidat.com
// Submitted by Artem Kondratev <accounts@seidat.com>
seidat.net

// Sellfy : https://sellfy.com
// Submitted by Yuriy Romadin <contact@sellfy.com>
sellfy.store

// Senseering GmbH : https://www.senseering.de
// Submitted by Felix MÃ¶nckemeyer <f.moenckemeyer@senseering.de>
senseering.net

// Sendmsg: https://www.sendmsg.co.il
// Submitted by Assaf Stern <domains@comstar.co.il>
minisite.ms

// Service Magnet : https://myservicemagnet.com
// Submitted by Dave Sanders <dave@myservicemagnet.com>
magnet.page

// Service Online LLC : http://drs.ua/
// Submitted by Serhii Bulakh <support@drs.ua>
biz.ua
co.ua
pp.ua

// Shift Crypto AG : https://shiftcrypto.ch
// Submitted by alex <alex@shiftcrypto.ch>
shiftcrypto.dev
shiftcrypto.io

// ShiftEdit : https://shiftedit.net/
// Submitted by Adam Jimenez <adam@shiftcreate.com>
shiftedit.io

// Shopblocks : http://www.shopblocks.com/
// Submitted by Alex Bowers <alex@shopblocks.com>
myshopblocks.com

// Shopify : https://www.shopify.com
// Submitted by Alex Richter <alex.richter@shopify.com>
myshopify.com

// Shopit : https://www.shopitcommerce.com/
// Submitted by Craig McMahon <craig@shopitcommerce.com>
shopitsite.com

// shopware AG : https://shopware.com
// Submitted by Jens KÃ¼per <cloud@shopware.com>
shopware.store

// Siemens Mobility GmbH
// Submitted by Oliver Graebner <security@mo-siemens.io>
mo-siemens.io

// SinaAppEngine : http://sae.sina.com.cn/
// Submitted by SinaAppEngine <saesupport@sinacloud.com>
1kapp.com
appchizi.com
applinzi.com
sinaapp.com
vipsinaapp.com

// Siteleaf : https://www.siteleaf.com/
// Submitted by Skylar Challand <support@siteleaf.com>
siteleaf.net

// Skyhat : http://www.skyhat.io
// Submitted by Shante Adam <shante@skyhat.io>
bounty-full.com
alpha.bounty-full.com
beta.bounty-full.com

// Small Technology Foundation : https://small-tech.org
// Submitted by Aral Balkan <aral@small-tech.org>
small-web.org

// Smoove.io : https://www.smoove.io/
// Submitted by Dan Kozak <dan@smoove.io>
vp4.me

// Snowplow Analytics : https://snowplowanalytics.com/
// Submitted by Ian Streeter <ian@snowplowanalytics.com>
try-snowplow.com

// SourceHut : https://sourcehut.org
// Submitted by Drew DeVault <sir@cmpwn.com>
srht.site

// Stackhero : https://www.stackhero.io
// Submitted by Adrien Gillon <adrien+public-suffix-list@stackhero.io>
stackhero-network.com

// Staclar : https://staclar.com
// Submitted by Matthias Merkel <matthias.merkel@staclar.com>
novecore.site

// staticland : https://static.land
// Submitted by Seth Vincent <sethvincent@gmail.com>
static.land
dev.static.land
sites.static.land

// Storebase : https://www.storebase.io
// Submitted by Tony Schirmer <tony@storebase.io>
storebase.store

// Strategic System Consulting (eApps Hosting): https://www.eapps.com/
// Submitted by Alex Oancea <aoancea@cloudscale365.com>
vps-host.net
atl.jelastic.vps-host.net
njs.jelastic.vps-host.net
ric.jelastic.vps-host.net

// Sony Interactive Entertainment LLC : https://sie.com/
// Submitted by David Coles <david.coles@sony.com>
playstation-cloud.com

// SourceLair PC : https://www.sourcelair.com
// Submitted by Antonis Kalipetis <akalipetis@sourcelair.com>
apps.lair.io
*.stolos.io

// SpaceKit : https://www.spacekit.io/
// Submitted by Reza Akhavan <spacekit.io@gmail.com>
spacekit.io

// SpeedPartner GmbH: https://www.speedpartner.de/
// Submitted by Stefan Neufeind <info@speedpartner.de>
customer.speedpartner.de

// Spreadshop (sprd.net AG) : https://www.spreadshop.com/
// Submitted by Martin Breest <security@spreadshop.com>
myspreadshop.at
myspreadshop.com.au
myspreadshop.be
myspreadshop.ca
myspreadshop.ch
myspreadshop.com
myspreadshop.de
myspreadshop.dk
myspreadshop.es
myspreadshop.fi
myspreadshop.fr
myspreadshop.ie
myspreadshop.it
myspreadshop.net
myspreadshop.nl
myspreadshop.no
myspreadshop.pl
myspreadshop.se
myspreadshop.co.uk

// Standard Library : https://stdlib.com
// Submitted by Jacob Lee <jacob@stdlib.com>
api.stdlib.com

// Storj Labs Inc. : https://storj.io/
// Submitted by Philip Hutchins <hostmaster@storj.io>
storj.farm

// Studenten Net Twente : http://www.snt.utwente.nl/
// Submitted by Silke Hofstra <syscom@snt.utwente.nl>
utwente.io

// Student-Run Computing Facility : https://www.srcf.net/
// Submitted by Edwin Balani <sysadmins@srcf.net>
soc.srcf.net
user.srcf.net

// Sub 6 Limited: http://www.sub6.com
// Submitted by Dan Miller <dm@sub6.com>
temp-dns.com

// Supabase : https://supabase.io
// Submitted by Inian Parameshwaran <security@supabase.io>
supabase.co
supabase.in
supabase.net
su.paba.se

// Symfony, SAS : https://symfony.com/
// Submitted by Fabien Potencier <fabien@symfony.com>
*.s5y.io
*.sensiosite.cloud

// Syncloud : https://syncloud.org
// Submitted by Boris Rybalkin <syncloud@syncloud.it>
syncloud.it

// Synology, Inc. : https://www.synology.com/
// Submitted by Rony Weng <ronyweng@synology.com>
diskstation.me
dscloud.biz
dscloud.me
dscloud.mobi
dsmynas.com
dsmynas.net
dsmynas.org
familyds.com
familyds.net
familyds.org
i234.me
myds.me
synology.me
vpnplus.to
direct.quickconnect.to

// Tabit Technologies Ltd. : https://tabit.cloud/
// Submitted by Oren Agiv <oren@tabit.cloud>
tabitorder.co.il

// TAIFUN Software AG : http://taifun-software.de
// Submitted by Bjoern Henke <dev-server@taifun-software.de>
taifun-dns.de

// Tailscale Inc. : https://www.tailscale.com
// Submitted by David Anderson <danderson@tailscale.com>
beta.tailscale.net
ts.net

// TASK geographical domains (www.task.gda.pl/uslugi/dns)
gda.pl
gdansk.pl
gdynia.pl
med.pl
sopot.pl

// Teckids e.V. : https://www.teckids.org
// Submitted by Dominik George <dominik.george@teckids.org>
edugit.org

// Telebit : https://telebit.cloud
// Submitted by AJ ONeal <aj@telebit.cloud>
telebit.app
telebit.io
*.telebit.xyz

// The Gwiddle Foundation : https://gwiddlefoundation.org.uk
// Submitted by Joshua Bayfield <joshua.bayfield@gwiddlefoundation.org.uk>
gwiddle.co.uk

// Thingdust AG : https://thingdust.com/
// Submitted by Adrian Imboden <adi@thingdust.com>
*.firenet.ch
*.svc.firenet.ch
reservd.com
thingdustdata.com
cust.dev.thingdust.io
cust.disrec.thingdust.io
cust.prod.thingdust.io
cust.testing.thingdust.io
reservd.dev.thingdust.io
reservd.disrec.thingdust.io
reservd.testing.thingdust.io

// ticket i/O GmbH : https://ticket.io
// Submitted by Christian Franke <it@ticket.io>
tickets.io

// Tlon.io : https://tlon.io
// Submitted by Mark Staarink <mark@tlon.io>
arvo.network
azimuth.network
tlon.network

// Tor Project, Inc. : https://torproject.org
// Submitted by Antoine BeauprÃ© <anarcat@torproject.org
torproject.net
pages.torproject.net

// TownNews.com : http://www.townnews.com
// Submitted by Dustin Ward <dward@townnews.com>
bloxcms.com
townnews-staging.com

// TradableBits: https://tradablebits.com
// Submitted by Dmitry Khrisanov dmitry@tradablebits.com
tbits.me

// TrafficPlex GmbH : https://www.trafficplex.de/
// Submitted by Phillipp RÃ¶ll <phillipp.roell@trafficplex.de>
12hp.at
2ix.at
4lima.at
lima-city.at
12hp.ch
2ix.ch
4lima.ch
lima-city.ch
trafficplex.cloud
de.cool
12hp.de
2ix.de
4lima.de
lima-city.de
1337.pictures
clan.rip
lima-city.rocks
webspace.rocks
lima.zone

// TransIP : https://www.transip.nl
// Submitted by Rory Breuk <rbreuk@transip.nl>
*.transurl.be
*.transurl.eu
*.transurl.nl

// TuxFamily : http://tuxfamily.org
// Submitted by TuxFamily administrators <adm@staff.tuxfamily.org>
tuxfamily.org

// TwoDNS : https://www.twodns.de/
// Submitted by TwoDNS-Support <support@two-dns.de>
dd-dns.de
diskstation.eu
diskstation.org
dray-dns.de
draydns.de
dyn-vpn.de
dynvpn.de
mein-vigor.de
my-vigor.de
my-wan.de
syno-ds.de
synology-diskstation.de
synology-ds.de

// Uberspace : https://uberspace.de
// Submitted by Moritz Werner <mwerner@jonaspasche.com>
uber.space
*.uberspace.de

// UDR Limited : http://www.udr.hk.com
// Submitted by registry <hostmaster@udr.hk.com>
hk.com
hk.org
ltd.hk
inc.hk

// United Gameserver GmbH : https://united-gameserver.de
// Submitted by Stefan Schwarz <sysadm@united-gameserver.de>
virtualuser.de
virtual-user.de

// Upli : https://upli.io
// Submitted by Lenny Bakkalian <lenny.bakkalian@gmail.com>
upli.io

// urown.net : https://urown.net
// Submitted by Hostmaster <hostmaster@urown.net>
urown.cloud
dnsupdate.info

// .US
// Submitted by Ed Moore <Ed.Moore@lib.de.us>
lib.de.us

// VeryPositive SIA : http://very.lv
// Submitted by Danko Aleksejevs <danko@very.lv>
2038.io

// Vercel, Inc : https://vercel.com/
// Submitted by Connor Davis <security@vercel.com>
vercel.app
vercel.dev
now.sh

// Viprinet Europe GmbH : http://www.viprinet.com
// Submitted by Simon Kissel <hostmaster@viprinet.com>
router.management

// Virtual-Info : https://www.virtual-info.info/
// Submitted by Adnan RIHAN <hostmaster@v-info.info>
v-info.info

// Voorloper.com: https://voorloper.com
// Submitted by Nathan van Bakel <info@voorloper.com>
voorloper.cloud

// Voxel.sh DNS : https://voxel.sh/dns/
// Submitted by Mia Rehlinger <dns@voxel.sh>
neko.am
nyaa.am
be.ax
cat.ax
es.ax
eu.ax
gg.ax
mc.ax
us.ax
xy.ax
nl.ci
xx.gl
app.gp
blog.gt
de.gt
to.gt
be.gy
cc.hn
blog.kg
io.kg
jp.kg
tv.kg
uk.kg
us.kg
de.ls
at.md
de.md
jp.md
to.md
indie.porn
vxl.sh
ch.tc
me.tc
we.tc
nyan.to
at.vg
blog.vu
dev.vu
me.vu

// V.UA Domain Administrator : https://domain.v.ua/
// Submitted by Serhii Rostilo <sergey@rostilo.kiev.ua>
v.ua

// Waffle Computer Inc., Ltd. : https://docs.waffleinfo.com
// Submitted by Masayuki Note <masa@blade.wafflecell.com>
wafflecell.com

// WapBlog.ID : https://www.wapblog.id
// Submitted by Fajar Sodik <official@wapblog.id>
idnblogger.com
indowapblog.com
bloger.id
wblog.id
wbq.me
fastblog.net

// WebHare bv: https://www.webhare.com/
// Submitted by Arnold Hendriks <info@webhare.com>
*.webhare.dev

// WebHotelier Technologies Ltd: https://www.webhotelier.net/
// Submitted by Apostolos Tsakpinis <apostolos.tsakpinis@gmail.com>
reserve-online.net
reserve-online.com
bookonline.app
hotelwithflight.com

// WeDeploy by Liferay, Inc. : https://www.wedeploy.com
// Submitted by Henrique Vicente <security@wedeploy.com>
wedeploy.io
wedeploy.me
wedeploy.sh

// Western Digital Technologies, Inc : https://www.wdc.com
// Submitted by Jung Jin <jungseok.jin@wdc.com>
remotewd.com

// WIARD Enterprises : https://wiardweb.com
// Submitted by Kidd Hustle <kiddhustle@wiardweb.com>
pages.wiardweb.com

// Wikimedia Labs : https://wikitech.wikimedia.org
// Submitted by Arturo Borrero Gonzalez <aborrero@wikimedia.org>
wmflabs.org
toolforge.org
wmcloud.org

// WISP : https://wisp.gg
// Submitted by Stepan Fedotov <stepan@wisp.gg>
panel.gg
daemon.panel.gg

// WoltLab GmbH : https://www.woltlab.com
// Submitted by Tim DÃ¼sterhus <security@woltlab.cloud>
woltlab-demo.com
myforum.community
community-pro.de
diskussionsbereich.de
community-pro.net
meinforum.net

// Woods Valldata : https://www.woodsvalldata.co.uk/
// Submitted by Chris Whittle <chris.whittle@woodsvalldata.co.uk>
affinitylottery.org.uk
raffleentry.org.uk
weeklylottery.org.uk

// WP Engine : https://wpengine.com/
// Submitted by Michael Smith <michael.smith@wpengine.com>
// Submitted by Brandon DuRette <brandon.durette@wpengine.com>
wpenginepowered.com
js.wpenginepowered.com

// Wix.com, Inc. : https://www.wix.com
// Submitted by Shahar Talmi <shahar@wix.com>
wixsite.com
editorx.io

// XenonCloud GbR: https://xenoncloud.net
// Submitted by Julian Uphoff <publicsuffixlist@xenoncloud.net>
half.host

// XnBay Technology : http://www.xnbay.com/
// Submitted by XnBay Developer <developer.xncloud@gmail.com>
xnbay.com
u2.xnbay.com
u2-local.xnbay.com

// XS4ALL Internet bv : https://www.xs4all.nl/
// Submitted by Daniel Mostertman <unixbeheer+publicsuffix@xs4all.net>
cistron.nl
demon.nl
xs4all.space

// Yandex.Cloud LLC: https://cloud.yandex.com
// Submitted by Alexander Lodin <security+psl@yandex-team.ru>
yandexcloud.net
storage.yandexcloud.net
website.yandexcloud.net

// YesCourse Pty Ltd : https://yescourse.com
// Submitted by Atul Bhouraskar <atul@yescourse.com>
official.academy

// Yola : https://www.yola.com/
// Submitted by Stefano Rivera <stefano@yola.com>
yolasite.com

// Yombo : https://yombo.net
// Submitted by Mitch Schwenk <mitch@yombo.net>
ybo.faith
yombo.me
homelink.one
ybo.party
ybo.review
ybo.science
ybo.trade

// Yunohost : https://yunohost.org
// Submitted by Valentin Grimaud <security@yunohost.org>
ynh.fr
nohost.me
noho.st

// ZaNiC : http://www.za.net/
// Submitted by registry <hostmaster@nic.za.net>
za.net
za.org

// Zine EOOD : https://zine.bg/
// Submitted by Martin Angelov <martin@zine.bg>
bss.design

// Zitcom A/S : https://www.zitcom.dk
// Submitted by Emil Stahl <esp@zitcom.dk>
basicserver.io
virtualserver.io
enterprisecloud.nu

// ===END PRIVATE DOMAINS==={
    "name": "amphp/http-client-cookies",
    "homepage": "https://github.com/amphp/http-client-cookies",
    "description": "Automatic cookie handling for Amp's HTTP client.",
    "keywords": [
        "http",
        "cookie",
        "cookies",
        "client",
        "async"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@gmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.2",
        "ext-filter": "*",
        "amphp/amp": "^2.3",
        "amphp/dns": "^1.2",
        "amphp/http": "^1.5",
        "amphp/http-client": "^4",
        "amphp/sync": "^1.3",
        "psr/http-message": "^1.0"
    },
    "require-dev": {
        "amphp/socket": "^1",
        "amphp/file": "^2",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^7 || ^8",
        "friendsofphp/php-cs-fixer": "^2.3",
        "amphp/http-server": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Http\\Client\\Cookie\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Http\\Client\\Cookie\\": "test"
        }
    },
    "conflict": {
        "amphp/file": "<1 || >=3"
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Http\Client\Cookie\Internal;

use PHPUnit\Framework\TestCase;
class PublicSuffixListTest extends TestCase
{
    /**
     * @dataProvider provideTestData
     * @requires extension intl
     *
     * @param $domain
     * @param $expectation
     *
     * @throws \Amp\Dns\InvalidNameException
     */
    public function testWithData($domain, $expectation) : void
    {
        $this->assertSame($expectation, PublicSuffixList::isPublicSuffix($domain));
    }
    /**
     *
     */
    public function provideTestData() : array
    {
        $lines = \file(__DIR__ . '/../fixture/public_suffix_list_tests.txt', \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES);
        $lines = \array_filter($lines, static function ($line) {
            return \Phabel\Target\Php80\Polyfill::substr($line, 0, 2) !== '//';
        });
        return \array_map(static function ($line) {
            $parts = \explode(' ', $line);
            return [$parts[0], (bool) $parts[1]];
        }, $lines);
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Cookie;

class FileCookieJarTest extends CookieJarTest
{
    /**
     *
     */
    protected function createJar() : CookieJar
    {
        return new FileCookieJar(\tempnam(\sys_get_temp_dir(), 'amphp-http-client-cookies-test-'));
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Cookie;

use Amp\Http\Cookie\CookieAttributes;
use Amp\Http\Cookie\RequestCookie;
use Amp\Http\Cookie\ResponseCookie;
abstract class CookieJarTest extends CookieTest
{
    /** @var CookieJar */
    private $jar;
    /**
     *
     */
    public function setUp() : void
    {
        parent::setUp();
        $this->jar = $this->createJar();
    }
    /**
     * @dataProvider provideCookieDomainMatchData
     *
     * @param ResponseCookie $cookie
     * @param string $domain
     * @param bool $returned
     *
     * @return \Generator
     */
    public function testCookieDomainMatching(ResponseCookie $cookie, string $domain, bool $returned) : \Generator
    {
        $this->jar->store($cookie);
        $requestCookies = (yield $this->jar->get($this->getUri('https', $domain, '/')));
        if ($returned) {
            $requestCookie = new RequestCookie($cookie->getName(), $cookie->getValue());
            $this->assertSame((string) $requestCookie, \implode('; ', $requestCookies));
        } else {
            $this->assertSame([], $requestCookies);
        }
    }
    /**
     *
     */
    public function provideCookieDomainMatchData() : array
    {
        // See http://stackoverflow.com/a/1063760/2373138 for cases
        return [
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.foo.bar.example.com')), 'foo.bar', false],
            /* previous security issue */
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.example.com')), 'example.com', true],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.example.com')), 'www.example.com', true],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'example.com', true],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'www.example.com', false],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'anotherexample.com', false],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('anotherexample.com')), 'example.com', false],
        ];
    }
    /**
     *
     */
    protected abstract function createJar() : CookieJar;
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\PHPUnit\AsyncTestCase;
use Psr\Http\Message\UriInterface as PsrUri;
abstract class CookieTest extends AsyncTestCase
{
    /**
     *
     */
    protected function getUri(string $scheme, string $host, string $path) : PsrUri
    {
        $uri = $this->createMock(PsrUri::class);
        $uri->method('getScheme')->willReturn(\strtolower($scheme));
        $uri->method('getHost')->willReturn(\strtolower($host));
        $uri->method('getPath')->willReturn($path);
        return $uri;
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Cookie;

class InMemoryCookieJarTest extends CookieJarTest
{
    /**
     *
     */
    protected function createJar() : CookieJar
    {
        return new InMemoryCookieJar();
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Cookie;

use Amp\Http\Client\Connection\DefaultConnectionFactory;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\HttpClient;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Cookie\CookieAttributes;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Http\Server\Options;
use Amp\Http\Server\RequestHandler\CallableRequestHandler;
use Amp\Http\Server\Response as ServerResponse;
use Amp\Http\Server\Server;
use Amp\Http\Status;
use Amp\Socket;
use Amp\Socket\StaticConnector;
use Psr\Log\NullLogger;
use function Amp\Promise\wait;
use function Amp\Socket\connector;
class ClientCookieTest extends CookieTest
{
    /** @var HttpClient */
    private $client;
    /** @var InMemoryCookieJar */
    private $jar;
    /** @var Server */
    private $server;
    /** @var string */
    private $address;
    /** @var string */
    private $cookieHeader;
    /**
     *
     */
    public function provideCookieDomainMatchData() : array
    {
        return [[new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.foo.bar.example.com')), 'foo.bar', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.example.com')), 'example.com', true], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.example.com')), 'www.example.com', true], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'example.com', true], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'www.example.com', true], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'anotherexample.com', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('anotherexample.com')), 'example.com', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('com')), 'anotherexample.com', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.com')), 'anotherexample.com', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('')), 'example.com', true]];
    }
    /**
     *
     */
    public function setUp() : void
    {
        parent::setUp();
        $this->jar = new InMemoryCookieJar();
        $socket = Socket\Server::listen('127.0.0.1:0');
        $socket->unreference();
        $this->address = $socket->getAddress();
        $this->server = new Server([$socket], new CallableRequestHandler(function () {
            return new ServerResponse(Status::OK, ['set-cookie' => $this->cookieHeader], '');
        }), new NullLogger(), (new Options())->withHttp1Timeout(1)->withHttp2Timeout(1));
        wait($this->server->start());
        $this->client = (new HttpClientBuilder())->usingPool(new UnlimitedConnectionPool(new DefaultConnectionFactory(new StaticConnector($this->address, connector()))))->interceptNetwork(new CookieInterceptor($this->jar))->build();
    }
    /**
     * @dataProvider provideCookieDomainMatchData
     *
     * @param ResponseCookie $cookie
     * @param string $requestDomain
     * @param bool $accept
     *
     * @return \Generator
     */
    public function testCookieAccepting(ResponseCookie $cookie, string $requestDomain, bool $accept) : \Generator
    {
        $this->cookieHeader = (string) $cookie;
        /** @var Response $response */
        $response = (yield $this->client->request(new Request('http://' . $requestDomain . '/')));
        (yield $response->getBody()->buffer());
        $cookies = $this->jar->getAll();
        if ($accept) {
            $this->assertCount(1, $cookies);
        } else {
            $this->assertSame([], $cookies);
        }
        wait($this->server->stop());
    }
}{
    "name": "amphp/process",
    "homepage": "https://github.com/amphp/process",
    "description": "Asynchronous process manager.",
    "require": {
        "php": ">=7",
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.4"
    },
    "require-dev": {
        "phpunit/phpunit": "^6",
        "amphp/phpunit-util": "^1",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "license": "MIT",
    "authors": [
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "Amp\\Process\\": "lib"
        },
        "files": ["lib/functions.php"]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Process\\Test\\": "test"
        }
    },
    "config": {
        "platform": {
            "php": "7.0.33"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
MZ�       ÿÿ  ¸       @                                     º ´	Í!¸LÍ!This program cannot be run in DOS mode.
$       äíP¦ Œ>õ Œ>õ Œ>õ©ô­õ¬Œ>õ›Ò?ô¢Œ>õ›Ò=ô£Œ>õ›Ò;ô±Œ>õ›Ò:ô¬Œ>õ}sõõ¥Œ>õ Œ?õþŒ>õ
Ò6ô£Œ>õ
ÒÁõ¡Œ>õ Œ©õ¡Œ>õ
Ò<ô¡Œ>õRich Œ>õ                        PE  d† U%s\        ð "   0        „2        @                        �         `�                                           ð_  È       ¨Ü   €  H           € L   X  p                           €X  ”            @  ø                          .text   .      0                    `.rdata  H*   @   ,   4              @  @.data   €   p      `              @  À.pdata  H   €      b              @  @.gfids      �      f              @  @.rsrc   ¨Ü       Þ   h              @  @.reloc  L    €     F             @  B                                                                                                                                                                                                                        @SH�ì€   H‹ð_  H3ÄH‰D$xH‹ÙÇD$@   H‹IL�D$@º~f€ÿ11  …Àt‹H�¬4  D‹Àè”  3Àéó   H‰´$˜   3ö95-f  H‰¼$    t9·f  �~¸   f‰D$XH‹ f   ‰t$\D$`ÿî0  f‰D$ZH�T$Xë3¸   ¿   f‰D$HH‹Ìe  ‹‰L$L··e  ÿ¹0  f‰D$JH�T$HH‹KE3ÉH‰t$0D‹ÇH‰t$(H‰t$ ÿP0  H‹¼$    H‹´$˜   ƒøÿt‹H�Z4  èÅ  3Àë'ÿ;0  =3'  tD‹H�š4  ‹Èèc  3Àë¸   H‹L$xH3Ìè­  H�Ä€   [ÃÌÌÌÌ@SUVWAVAWHƒìXH‹Œ^  H3ÄH‰D$HL‹¼$°   3ÛA‹ñH‰\$0I‹èH‰\$(D‹ò‰\$ L�L$@D‹ÆH‹Õ‹ûÿÀ/  ƒøÿu!ÿ¥/  E‹ÎH�K4  ‹ÈM‹ÇèÑ  3Àév  D‹Óƒþ‚ã   ‹þWíƒçøfoåA»   @ „     E‹ÊE�CMÀA‹ÓHÒA�KÿHÉMÉAƒÂfBnLÅ E�CfnDÕ MÀfnTÍ A�SfBn\Í A�KfbØE�KfBnDÅ MÉfbÑHÒfbÚHÉfþÝAƒÃfBnLÍ foëfnTÕ fn\Í fbØfbÑfbÚfþÜfoãD;×‚]ÿÿÿfþåfoÄfsØfþàfoÄfsØfþàf~ç‹ÓD;ÖsW‹ÆA+Âƒør9A‹Â‹ÎA+ÊHÁàƒéHÅÑéÿÁD‹ÁE�J@ f„     PH�@ IƒèuñD;Ös
A‹ÂHÀ|Å �øD‹L$@D;ÏtE‹Æ‰|$ I‹×H�3  è�  3Àë¸   H‹L$HH3Ìè§  HƒÄXA_A^_^][ÃÌÌÌÌÌÌÌÌÌÌ@SH�ì�   H‹€\  H3ÄH‰„$ˆ   H‹ÙÇD$P    H‹IL�D$Pº~f€ÿ¾-  …Àt‹H�	3  D‹Àè!  3Àé«   ‹Èb  H�D$xH‰D$8‹¯Á‰L$@ÇD$0   ÆD$xHcÈH²b  H‰L$Hÿ_,  D$0‹L�D$X‹ÈˆD$|ÁéA¹   ˆL$y‹ÈÁéˆL$z‹È¶ÁéD$XˆD$}H�÷2  D$@ˆL${H‹KH‰D$ D$hèýÿÿ…À„ZÿÿÿÇC   ¸   H‹Œ$ˆ   H3Ìè  H�Ä�   [ÃÌÌÌÌÌÌH‰\$ AVH�ì€   H‹[[  H3ÄH‰D$p‹áa  H‹ÙƒÀE3ö‹ÈD‰t$d‰D$@ÿ-  H‹KL�L$hH‰D$HE�FH�D$dL‰t$0L‰t$(H�T$@H‰D$ ÿ¢,  ƒøÿu)ÿW,  D‹H�=2  ‹Èè†  H‹L$HÿÃ,  3Àé‚  D‹D$hAƒøs%D‹L$@H�m2  ‹è–  H‹L$Hÿ“,  3ÀéR  H‰¼$    H‹|$H¶<t$‹H�×2  D¾Àè^  H‹L$Hÿ[,  3Àé  ¶O„Ét@€ù}¶ÁL�õ?  M‹ÁëL�X3  ‹D¾ÁH�k3  è  H‹L$Hÿ,  3ÀéÊ   D‹L$@H�D$`H‰´$˜   A‹öH‰D$XfÇD$`ÇD$P   E;Át‹H��1  èÈ  H‹|$HëLHcn`  ‹L‹Á¯ÁH�OHcÐH|`  èq'  …Àt‹H�r3  è�  H‹|$Hë@ˆt$a¾   ÇC   H‹Ïÿt+  ‹H�³3  H‹KL�D$PA¹   H‰D$ èÊúÿÿ…ÀADö‹ÆH‹´$˜   H‹¼$    H‹L$pH3ÌèE  H‹œ$¨   H�Ä€   A^ÃÌÌÌ3ÀH‹Áƒz|HÿÀHƒø|í3ÀÃ¸   ÃÌÌH‰\$ UAVAWH�¬$€úÿÿH�ì€  H‹ðX  H3ÄH‰…p  E3ÿL‹ñA‹ßI‹ÞèÔøÿÿ…À„Ì  HÿÃHƒû|æH‰´$¨  I‹ÎH‰¼$°  è{ÿÿÿ…À„é   E‹ÇD‰|$@E‹ÏD‰½P  E‹×D‰½`  I‹Þ¿   @ „     L‹A‹C…À…‘   A‹ÏE…ÉtI‹SD  H9”ÍX  tÿÁA;ÉrïA;Éu#Aƒù@sI‹CH‰„ÍX  D‹�P  AÿÁD‰�P  A‹ÏE…ÒtI‹SH9”Íh  tÿÁA;ÊrïA;ÊuiAƒú@scI‹CH‰„Íh  D‹•`  AÿÂD‰•`  ëDƒøu?A‹ÇE…ÀtI‹S‹ÈH9TÌHtÿÀA;ÀrðA;ÀuAƒø@s‹ÈI‹CH‰DÌHD‹D$@AÿÀD‰D$@HƒÃHƒï…ÿÿÿL��`  L‰|$ L�…P  3ÉH�T$@ÿ¶(  ‹Øƒøÿ„=  …À„'  A‹÷I‹ÿ~y Hƒÿ}pI‹þH�T$@H‹Iÿ§(  I‹þ…Àtèªûÿÿ…À„¢   ÿËë;H‹IH�•P  ÿ}(  I‹þ…Àtè`úÿÿ…Àt|ÿËëH‹IH�•`  ÿW(  …ÀuÿÆHÿÇ…ÛŠI‹Îè’ýÿÿ…À…þÿÿ3ÀëIHcÆL�L$4ºÿÿ  ÇD$0   A¸  I‹ÆH�D$0H‰D$ H‹Kÿ+(  ƒøÿuE‹H�Å0  èP  ƒÈÿH‹´$¨  H‹¼$°  H‹�p  H3ÌèN  H‹œ$¸  H�Ä€  A_A^]ÃD‹H�×0  ‹L$4èÆ  ë´H�}1  èø  ë¦ÿp'  ‹ÈH�'1  è¢  ë�ƒÈÿëžÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$H‰|$AVHƒì 3ÛÇAH   H‰YPH‹ñÇAX   H‹ù�HcËL�FHHÁáE3ÉHÎH�QÿÍ%  …Àtj…ÛuH‹OëH‹E3ÀA�Pÿ�%  …ÀtCÿÃHƒÇƒû|¸ÇF`h   ¸   H‹H‰Ž°   H‹NH‰Ž¸   H‹N(�Žœ      H‰ŽÀ   ëH�i1  ëH�ð0  ‹Óè	  3ÀH‹\$0H‹t$8H‹|$@HƒÄ A^ÃÌH‰\$H‰l$H‰t$ WHƒìPH‹õT  H3ÄH‰D$HH‹ÙƒÏÿ¹   ÿ¼&  H‹KL�L$@3öH‰D$8H‹ÐÇD$0   A¸   H‰t$ ÿ°$  …ÀtZH�-í1  D  ‹D$@…Àtj‹L�D$0H‹KA¹   ‰D$0H‰l$ èÙõÿÿ…ÀtIH‹T$8L�L$@H‹KA¸   H‰t$ ÿV$  …Àu²ÿ”$  ƒømtÿ‰$  D‹H�'1  ‹ÈèÐ  ë‹þH‹Kÿr$  H‹Kÿ�%  ‹ÇH‹L$HH3Ìè	  H‹\$hH‹l$pH‹t$xHƒÄP_ÃÌÌÌÌH‰\$H‰t$WHƒìpH‹ÚS  H3ÄH‰D$`H‹Ù3ö¹   ‰t$TƒÏÿÿ›%  H‹KL�L$PH‰D$HD�FH�D$TH‰t$0H‰t$(H�T$@H‰D$ ÇD$@   ÿ"%  ;ÇtqD‹D$PE…À„Ä   H‹T$HL�L$XH‹KH‰t$ ÿo#  …À„”   D‹D$XD‹L$PE;ÁuuH‹KH�D$TH‰t$0L�L$PH‰t$(H�T$@A¸   H‰D$ ÿ²$  ƒøÿu�ÿO#  H�X0  D‹‹Èè–  H‹Kÿ<#  ‹ÇH‹L$`H3ÌèÝ  L�\$pI‹[I‹s I‹ã_Ã‹H�Â0  è�  ëÅÿý"  H�N0  ë¬‹þë²ÌÌÌÌÌÌÌÌH‰\$H‰l$H‰t$W¸P  èæ  H+àH‹|R  H3ÄH‰„$@  ‹ÿX  ¹öÿÿÿ�@Û�4@ÿh"  3íL�L$0H‹ÈH‰l$ D‹ÃH�T$@H‹øÿ8"  …Àuÿv"  ‹ÈH�µ0  èÀ  3Àéè  ‹T$0;ÓtD‹ÃH�ç0  èâ  3ÀéÊ  ‹Î‰5“X  ‹ÞÿË#  D‹ÆH�T$@H‹ÈH‰�X  èŒ  ‹Î‰5|X  ÿ¦#  H�T$@D‹ÆHÓH‰lX  H‹Èèd  L�L$0H‰l$ A¸   H�T$@H‹ÏÿŽ!  …ÀuÿÌ!  ‹ÈH�ë0  è  3Àé>  ‹T$0ƒútH�?1  è:  3Àé"  ¶D$@„Àt¾ÐH�Ð1  è  3Àé  L�L$0H‰l$ A¸   H�T$@H‹Ïÿ!  …ÀuÿT!  ‹ÈH�#2  èž  3ÀéÆ   ‹D$0=   uH�U2  èÀ  3Àé¨   ÿÈ@8l@tH�©2  è¤  3ÀéŒ   HƒÏÿ‰l$(D‹ÏH‰l$ L�D$@3Ò¹éý  ÿÓ   HcØ…ÀuH�í2  èh  3ÀëS¸   H÷ãH@ÇH‹ÈÿO"  D‹Ï‰\$(L�D$@H‰W  3ÒH‰D$ ¹éý  ÿ‚   …ÀuH�3  è  3Àë¸   H‹Œ$@  H3Ìè!  L�œ$P  I‹[I‹kI‹s I‹ã_ÃÌÌÌÌÌÌÌÌHƒìXH‹õO  H3ÄH‰D$H3ÀˆT$@‹H‹I‰D$AH�D$@H‰D$8A‹ÀÁèˆD$AA‹ÀÁèˆD$BA‹ÀÁèDˆD$DL�D$0L‰L$ A¹   ˆD$CÇD$0   èóðÿÿH‹L$HH3Ìè†  HƒÄXÃÌH‰\$H‰l$H‰t$ WAVAWHƒìPH‹aO  H3ÄH‰D$@3ÿH�t$(D‹÷‹ï‹ßL‹ù„     I‹ßH�T$ ÿq  …À„    ‹D$ =  uI‹ßAÿÆH‰HƒÆë…À…”   ÿÅHÿÃHƒû|»E…öt[AƒÉÿH�T$(A¸   A‹Îÿþ  ƒøÿuÿ  ‹ÈH�Š2  èe  H‹ßf�I‹ßH�T$ ÿñ  …Àtƒ|$  u4ÿÇHÿÃHƒû|Û¸   ë$ÿÖ  D‹Çë	ÿË  D‹ÅH�Ù1  ‹Èè  3ÀH‹L$@H3Ìèc  L�\$PI‹[(I‹k0I‹s8I‹ãA_A^_ÃÌÌÌÌÌÌÌÌÌ@USWH�¬$PÿÿÿH�ì°  H‹&N  H3ÄH‰…¨   Hƒ=ÜT   H‹ú‹Ùu"º   ‹ÊÿØ  H‰ÁT  H…Àt	H‹Èÿƒ  ¹  H�¿T  ÿ)  …Àt‹ÐH�Ü1  è§
  L‹Ç‹Óè­  …Àuè  ƒÈÿéa  èûÿÿ…Àtêƒ=,T   ¸   H‰´$Ð  H�uxL‰´$à  A¾   DEðL‰¼$è  E3ÿA‹ÿ¹   ÿ@  º   A‹ÎH‹Ø‰8D�BD‰xÿÝ  H‰CHƒøÿ„¾  H‰ÿÇHƒÆƒÿ|¾L‰|$(L�MxL�	ôÿÿD‰|$ 3Ò3Éÿb  3ÒH�M A¸È   H‹Øè,  H�M èýöÿÿ…À„z  ƒÊÿH‹Ëÿ	  ƒøÿuÿ  ‹ÈH�1  è`
  éP  H�UpH‹Ëÿî  …Àuÿì  ‹ÈH�+1  è6
  é&  D9}p…  H‹@S  H�EÐH‰D$HL�MèH�E 3ÉH‰D$@L�EèH‹õR  H‰D$8L‰|$0ÇD$(   ÇD$    ÿ¥  …Àuÿ{  ‹ÈH�Ò(  èÅ	  éµ  H‹MØÿf  H‹M ÿ\  H‹M¸ÿR  H‹MÈÿH  D‹EàL�Õ0  H‹Mxº   èßûÿÿ…À„l  H‹ExL�L$PD‰|$PL�Ò÷ÿÿL‰|$(3ÒD‰|$ H‹HH‹E¨H‰L$`3ÉH‰D$Xÿô  ÇD$h   L�L$hH‰…�   L�qöÿÿH‹…€   3ÒL‰|$(D‰|$ H‹HH‹E°H‰L$x3ÉH‰D$pÿ¬  ÇE€   L�M€H‰…˜   L�+öÿÿH‹…ˆ   3ÒL‰|$(D‰|$ H‹HH‹EÀH‰M�3ÉH‰Eˆÿh  H‹MÐƒÊÿH‰…    ÿ,  ƒøÿuÿ9  ‹ÈH�Ø/  èƒ  ëvH‹MÐH�UpÿC  …Àuÿ  ‹ÈH� 0  è[  ëND‹EpL�60  H‹Mxº   è úÿÿ…Àt1H���   èûÿÿ…Àt!H‹MxH‹Iÿö  ‹Epë‹H�X%  èK  èÆ  ƒÈÿL‹´$à  H‹´$Ð  L‹¼$è  H‹�¨   H3Ìè<
  H�Ä°  _[]ÃÌH‰\$H‰t$ WHƒì0H‹J  H3ÄH‰D$(3öH‹úH‰t$ H‹Ùÿ§  D�F
H‹ËH�T$ ‰0ÿ£  ‹ðH9\$ tÿ„  ƒ8 u	‰7¸   ë3ÀH‹L$(H3Ìè¿	  H‹\$PH‹t$XHƒÄ0_ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$WHƒì H‹ÙI‹ð¹   ÿ`  H‹Ö¹   L‹ÀH‹øÿü  …Àt.ƒøt	H�t/  ëtH‰{¸   ÇC    H‹\$0H‹t$8HƒÄ _ÃH‹Ïÿ  ¹   ÿ  H‹Ö¹   L‹ÀH‹øÿ¢  …Àt!ƒøu¦‰C¸   H‰{H‹\$0H‹t$8HƒÄ _ÃH�>/  èÁ  H‹ÏÿÀ  H‹\$03ÀH‹t$8HƒÄ _ÃÌÌÌÌÌÌ@SHƒì H‹ÙH‹ÑI‹Èè|þÿÿ…Àt‹ÿÈ=þÿ  w¸   HƒÄ [Ã‹H�/  èd  3ÀHƒÄ [ÃÌÌÌÌÌÌÌÌÌÌÌÌ@SHƒì H�YI‹ÈH‹Óè+þÿÿ…Àtƒ; ‹H�/  è$  ¸   HƒÄ [ÃÌÌÌÌÌÌÌÌÌL‰A¸   ÃÌÌÌÌÌÌH‰\$WHƒì ·I‹ØH‹úfƒø-uf9Bufƒz u¸   H‹\$@HƒÄ _ÃH‰t$0L‰t$8E…ÉtrI‹L�5H  E3ÒH�5gH  E‹ÚM‹Î�M‹H‹ÃL+Ã€    ·B· +ÑuHƒÀ…Éuì…ÒtAÿÃIƒÁL;Î|ÌëIcÃH�@M�ÎL‹ÇH�õM  H‹ÓAÿRéB  fƒø-…3  f9B…)  H�JH�2.  I‰ÿi  L‹L�5wG  E3ÒH�5ÍG  H‹øM‹ÎH…Àuof�M‹I‹ÃM+Ã€    ·B· +ÑuHƒÀ…Éuì…ÒtAÿÂIƒÁL;Î|Ìé}   IcÂH�@I�ÎH…ÀtmH‹@H…Àu
¸   é�   I‹ÓH�:M  ÿÐéŒ   fD‰M‹I‹ÃM+ÃfD  ·B· +ÑuHƒÀ…Éuì…ÒtAÿÂIƒÁL;Î|ÍëIcÂH�@I�ÎH…ÀuI‹ÓH�P-  è;  3Àë0H‹@I‹ÓH…ÀuH�\-  è  3ÀëL�GH�°L  ÿÐë¸   H‹t$0L‹t$8H‹\$@HƒÄ _ÃÌÌH‰\$H‰l$H‰L$VWAVHƒì 3ÿHcê3ÀH‰|$@»   ‰=bL  H‰cL  M‹ðÇ^L  ÿÿÿÿ‹÷‰=ZL  H‰=WL  H;Ý}Nff„     I‹ÞL�D$@D‹Îèýÿÿ…Àtd~ƒø~ƒøt	ƒøu	‹÷ë¾   HÿÃH;Ý|Éƒ=L  ÿ…±   ¹   ÿA  H�-  ¹   L‹ÀH‹ØÿÙ  …Àt$ƒøtH�Q+  ën3Àé¨   H‰±K  ‰=³K  ëfH‹Ëÿ   ¹   ÿí  H�Æ,  ¹   L‹ÀH‹Øÿ…  …Àt!ƒøt	H�ý*  ëH‰dK  ÇbK     ëH�!+  è¤  H‹Ëÿ£  9=IK  uH�ü+  è‡  ë9=K  uH�,  èq  ë¿   ‹ÇH‹\$HH‹l$PHƒÄ A^_^ÃÌÌÌÌÌH�áL  ÃÌÌÌÌÌÌÌÌH‰T$L‰D$L‰L$ SVWHƒì0H‹úH�t$`H‹ÙèÊÿÿÿE3ÉH‰t$ L‹ÇH‹ÓH‹ÿ  HƒÄ0_^[ÃÌÌÌÌÌÌÌÌÌÌÌH‰l$H‰t$H‰|$ ATAVAWHƒì0I‹èL‹òH‹ñèyÿÿÿH‰l$(M‹ÎE3ÀHÇD$     3ÒL‹øH‹HƒÉÿ“  IƒÌÿ‹ø…ÀAHüA;üuA‹ÄëlHcÏ¸   HÿÁH‰\$PH÷áI@ÄH‹Èÿm  H‹ØH…Àt7I‹�GLcÀM‹ÎH‰l$(H‹ÓHÇD$     ÿB  …ÀAHÄƒøÿuH‹Ëÿ6  A‹ÄëH‰H‹\$PH‹l$XH‹t$`H‹|$hHƒÄ0A_A^A\ÃÌÌÌÌÌÌÌH‰L$H‰T$L‰D$L‰L$ Hƒì8Hƒ=ÈI   u3ÀHƒÄ8Ãº   H‰\$0�Jÿ¼  H‹ØH…Àu
H‹\$0HƒÄ8ÃH‹T$@L�D$HH�L$ è®þÿÿH‹T$ ÿÈHcÈI¹ &     E3ÀH�J ·fƒù w·ÉI£És
fD‰ HƒèëäH‹EI  H‰SH‹Óÿ   H‹\$0¸   HƒÄ8ÃÌL‹ÜI‰SM‰CM‰K SHƒì`H‹EB  H3ÄH‰D$P3À‹ÙI‰CÈD‹Á‰D$(A¹   I‰Cà3ÒI�Cà¹   I‰C¸ÿ‡  H‹T$xH…Òu&L‹D$HH�Ñ)  ‹ÓèÒþÿÿH‹L$PH3Ìèå  HƒÄ`[ÃL�„$€   H�L$@è½ýÿÿL‹L$HH�©)  H‹T$@D‹Ãè”þÿÿH‹L$PH3Ìè§  HƒÄ`[ÃÌH‰l$H‰t$ AVHƒì@½€   ‹Íÿc  H‰\$PE3öH‹ðH‰|$X H‹1H  H…É„#  ÿú  H…À„î   H‹XH‹Èÿ4  H…Û„Ø   L‰t$8AƒÉÿL‰t$0L‹Ã‰l$(3Ò¹éý  H‰t$ ÿœ  …À…‡   ÿN  ƒøzu‘L‰t$8AƒÉÿL‰t$0L‹ÃD‰t$(3Ò¹éý  L‰t$ ÿa  Hcø…À„^ÿÿÿH‹×H‹Îÿ’  H…À„IÿÿÿL‰t$8AƒÉÿL‰t$0L‹Ã‰|$(3Ò¹éý  H‰D$ H‹ð‹ïÿ  …À„ÿÿÿ¹   ÿR  L‹ÆH�p(  H‹ÈèüÿÿéóþÿÿH‹$G  H…ÉtÿÑ  H‹G  ÿ4  L‰5G  H‹ÎH‹|$XH‹\$PH‹l$`H‹t$hHƒÄ@A^Hÿ%  ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌff„     H;ù?  òuHÁÁf÷ÁÿÿòuòÃHÁÉé«  ÌÌÌ@SHƒì ¹   è  è;  ‹Èè8  èc  H‹Øè  ¹   ‰èC  „ÀtlèR	  H�—	  è6  èù  ‹ÈèÔ  …ÀuVèù  è,  …ÀtH�Õ  è°  è‹  è†  èÁ  ‹Èèî  èÙ  „Àtè˜  è§  3ÀHƒÄ [Ã¹   èý  Ì¹   èò  ÌÌHƒì(è¯  3ÀHƒÄ(ÃHƒì(ès  èj  ‹ÈHƒÄ(é™  ÌÌÌH‰\$H‰t$WHƒì0¹   è+  „Àu¹   è�  Ì@2ö@ˆt$ èÓ  ŠØ‹ÇD  ƒùu
¹   èx  …ÉuJÇªD     H�Ë  H�¬  èí
  …Àt
¸ÿ   éì   H�Š  H�s  èÆ
  ÇlD     ë@¶@ˆt$ ŠËèO  è  H‹ØHƒ8 t"H‹Èè�  „ÀtH‹H‹Ëèr  E3ÀA�P3ÉÿÓèÞ  H‹ØHƒ8 tH‹Èèm  „ÀtH‹è�
  èx
  H‹øèj
  H‹Øè>
  L‹ÀH‹‹è—ïÿÿ‹Øèè  „Àu‹Ëè1
  @„öuèE
  3Ò±èÚ  ‹Ãë!‹Øè¿  „Àu‹Ëè
  Ì€|$  uè
  ‹ÃH‹\$@H‹t$HHƒÄ0_ÃÌHƒì(è/  HƒÄ(évþÿÿÌÌ@SHƒì H‹Ù3ÉÿG  H‹ËÿF  ÿ0  H‹Èº	 ÀHƒÄ [Hÿ%  H‰L$Hƒì8¹   èç	  …Àt¹   Í)H�O>  èª   H‹D$8H‰6?  H�D$8HƒÀH‰Æ>  H‹?  H‰�=  H‹D$@H‰”>  Çj=  	 ÀÇd=     Çn=     ¸   HkÀ H�f=  HÇ   ¸   HkÀ H‹Ž<  H‰L ¸   HkÀH‹�<  H‰L H�Í  è ÿÿÿHƒÄ8ÃÌÌÌ@SVWHƒì@H‹ÙÿW  H‹³ø   3ÿE3ÀH�T$`H‹ÎÿÝ  H…Àt9Hƒd$8 H�L$hH‹T$`L‹ÈH‰L$0L‹ÆH�L$pH‰L$(3ÉH‰\$ ÿþ  ÿÇƒÿ|±HƒÄ@_^[ÃÌÌÌHƒì(èÿ  …Àt!eH‹%0   H‹HëH;Èt3ÀðH±ØA  uî2ÀHƒÄ(Ã°ë÷ÌÌÌ@SHƒì ¶óA  …É»   DÃˆãA  èâ  è  „Àu2Àëè  „Àu	3Éèý  ëêŠÃHƒÄ [ÃÌÌÌH‰\$UH‹ìHƒì@‹Ùƒù‡¦   èc  …Àt+…Ûu'H�XA  èá  …Àt2ÀëzH�\A  èÍ  …À”ÀëgH‹;  IƒÈÿ‹Â¹@   ƒà?+È°IÓÈL3ÂL‰EàL‰EèEàL‰EðòMðý@  L‰EàL‰EèEàL‰Eðòõ@  òMðñ@  òù@  H‹\$PHƒÄ@]Ã¹   èl  ÌÌÌÌHƒìL‹Á¸MZ  f9…ÊÿÿuyHc¸ÊÿÿH�uÊÿÿH��9PE  u_¸  f9AuTL+Â·AH�QHÐ·AH�€L�ÊH‰$I;Ñt‹JL;Ár
‹BÁL;ÀrHƒÂ(ëß3ÒH…Òu2Àëƒz$ }2Àë
°ë2Àë2ÀHƒÄÃÌÌÌ@SHƒì ŠÙè  3Ò…Àt„ÛuH‡ö?  HƒÄ [Ã@SHƒì €=@   ŠÙt„ÒuŠËèH  ŠËèA  °HƒÄ [ÃÌ@SHƒì H‹Ÿ9  H‹Ù‹ÊH3³?  ƒá?HÓÊHƒúÿu
H‹Ëè9  ëH‹ÓH�“?  è"  3É…ÀHDËH‹ÁHƒÄ [ÃÌHƒì(è§ÿÿÿH÷ØÀ÷ØÿÈHƒÄ(ÃÌH‰\$ UH‹ìHƒì Hƒe H»2¢ß-™+  H‹!9  H;ÃuoH�MÿÒ	  H‹EH‰EÿÌ	  ‹ÀH1EÿX	  ‹ÀH�M H1Eÿ¸	  ‹E H�MHÁà H3E H3EH3ÁH¹ÿÿÿÿÿÿ  H#ÁH¹3¢ß-™+  H;ÃHDÁH‰­8  H‹\$HH÷ÐH‰¦8  HƒÄ ]Ã3ÀÃÌ¸   ÃÌÌ¸ @  ÃÌÌH�Ý>  Hÿ%	  ÌÌ°ÃÌH�Ù>  ÃHƒì(èïóÿÿHƒèæÿÿÿHƒHƒÄ(ÃÌ3À9X8  ”ÀÃH�?  ÃH�?  ÃH‰\$UH�¬$@ûÿÿH�ìÀ  ‹Ù¹   èÕ  …Àt‹ËÍ)ƒ%x>   H�Mð3ÒA¸Ð  è%  H�Mðÿí  H‹�è   H�•Ø  H‹ËE3Àÿs  H…Àt<Hƒd$8 H��à  H‹•Ø  L‹ÈH‰L$0L‹ÃH��è  H‰L$(H�MðH‰L$ 3ÉÿŠ  H‹…È  H�L$PH‰…è   3ÒH�…È  A¸˜   HƒÀH‰…ˆ   èŽ  H‹…È  H‰D$`ÇD$P  @ÇD$T   ÿî  ƒøH�D$PH‰D$@H�Eð”ÃH‰D$H3Éÿ  H�L$@ÿ  …Àu
öÛÀ!t=  H‹œ$Ð  H�ÄÀ  ]ÃÌÌÌHƒì(3ÉÿŒ  H‹ÈH…Àu2Àë7¸MZ  f9uòHcA<HÁ�8PE  uã¹  f9HuØƒ¸„   vÏƒ¸ø    •ÀHƒÄ(ÃH�	   Hÿ%v  ÌÌHƒì(H‹�8csmàuƒxu‹H ��àúlæƒøv�ù @™t3ÀHƒÄ(Ãè  ÌH‰\$H‰t$WHƒì H�N"  H�5G"  ëH‹;H…ÿt
H‹Ïèi   ÿ×HƒÃH;ÞråH‹\$0H‹t$8HƒÄ _ÃÌÌH‰\$H‰t$WHƒì H�"  H�5"  ëH‹;H…ÿt
H‹Ïè   ÿ×HƒÃH;ÞråH‹\$0H‹t$8HƒÄ _ÃÌÌHÿ%¥  ÌH‰\$H‰|$UH‹ìHƒì ƒeè 3É3ÀÇ¤5     ¢D‹ÁÇ‘5     �ñcAMDD‹ÊD‹ÒA�ñentiA�òineIA�ðntelEÐD‹ÛD‹Ç;  A�óAuthEÙ‹ÓDÙ�òGenu3É‹øDÒ¸   ¢‰EðD‹ÉD‰Mø‹È‰]ô‰UüE…ÒuRHƒ)5  ÿAƒÈ%ð?ÿD‰u;  =À t(=` t!=p t°ùüÿƒø wH»     H£ÃsAƒÈD‰;;  E…Ûu�á ð�ù ` rAƒÈD‰;  ¸   ‰UàD‰Mä;ø|$3É¢‰Eð‰]ô‰Mø‰Uü‰]èºã	sAƒÈD‰é:  AºásnÇt4     Çn4     AºásSAºásL3ÉÐHÁâ HÐH‰UH‹E$<u2‹@4  ƒÈÇ/4     öEè ‰)4  tƒÈ Ç4     ‰4  H‹\$83ÀH‹|$@HƒÄ ]ÃÌÌ3À94  •ÀÃÂ  ÌÌÌÌÌÿ%â  ÿ%ä  ÿ%F  ÿ%8  ÿ%Â  ÿ%  ÿ%Æ  ÿ%Ð  ÿ%*  ÿ%D  ÿ%.  ÿ%   ÿ%J  ÿ%ô  ÿ%Æ  ÿ%¨  ÿ%Ú  ÿ%Ä  ÿ%^  ÿ%   ÿ%  ÿ%t  ÿ%®  ÿ%€  ÿ%‚  ÿ%  Hƒì(M‹A8H‹ÊI‹Ñè   ¸   HƒÄ(ÃÌÌÌ@SE‹H‹ÚAƒãøL‹ÉAö L‹ÑtA‹@McP÷ØLÑHcÈL#ÑIcÃJ‹H‹C‹HHKöAt
¶AƒàðLÈL3ÊI‹É[é»òÿÿÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌff„     HƒìL‰$L‰\$M3ÛL�T$L+ÐMBÓeL‹%   M;ÓòsfA�â ðM�› ðÿÿAÆ M;ÓòuïL‹$L‹\$HƒÄòÃÌÿ%x  ÿ%z  ÌÌÌÌÌÌÌÌff„     ÿà@UHƒì H‹êH‹H‹Ñ‹èTþÿÿ�HƒÄ ]ÃÌ@UH‹êH‹3É�8  À”Á‹Á]ÃÌ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        °c      ¼c      Ôc      äc      ðc      
d      d      .d      Dd      Xd      hd      vd      †d      œd      ®d      Äd      Öd      îd      e       e      6e      i       j      j      òi      Üi      Âi      ¦i      ’i      ~i      `i      Di      0i      i              ¤e      ¼e      še      4j      >j              je      s      €      €o      €
      €xe            €—      €	      €‚e            €`e            €        êe              Êg      >f      Hf      àe      Øe      þe              ´g              ²f              Þf      êg      þf      rg      "h      0h      dg      Æf      †g      h      |g      Vg      ¢f      �f      g      @g      8g      ôe      *g              Úg      Hg      tf      ,f      f      Zf              (< @   Ð= @           ð0 @                   $0 @   à0 @                                            p @   @q @   S u c c e s s   S i g n a l   n o t   e x p e c t e d   a t   t h i s   t i m e         I n v a l i d   s t r e a m   i d e n t i f i e r       I n v a l i d   p r o c e s s   i d e n t i f i e r     D u p l i c a t e   s t r e a m   i d e n t i f i e r   I n v a l i d   c l i e n t   s e c u r i t y   t o k e n       I n v a l i d   s e r v e r   s e c u r i t y   t o k e n       F a i l e d   t o   s e t   s o c k e t   # % d   t o   n o n - b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       C o n n e c t i n g   s o c k e t   # % d   u n e x p e c t e d l y   s u c c e e d e d         C o n n e c t i n g   s o c k e t   # % d   f a i l e d         F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d   F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d :   s e n t   % d   o f   % d   b y t e s         F a i l e d   t o   s e t   s o c k e t   # % d   t o   b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       h a n d s h a k e       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   U n e x p e c t e d   s i g n a l   c o d e   % d   f r o m   s e r v e r ,   e x p e c t i n g   H A N D S H A K E _ A C K   U n k n o w n   e r r o r       H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   S e r v e r   r e j e c t e d   c o n n e c t i o n :   % d :   % s           H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   I n v a l i d   s e r v e r   t o k e n       h a n d s h a k e   a c k       F a i l e d   t o   c o n n e c t   s o c k e t   # % d :   U n k n o w n   e r r o r   F a i l e d   t o   c o n n e c t   s o c k e t   # % d         F a i l e d   t o   c r e a t e   s o c k e t   # % d   s e l e c t ( )   o p e r a t i o n   f a i l e d               s e l e c t ( )   u n e x p e c t e d l y   r e t u r n e d   z e r o   s o c k e t s           F a i l e d   t o   c r e a t e   p i p e   f o r   p r o c e s s   I / O   s t r e a m   # % d                 F a i l e d   t o   s e t   h a n d l e   i n f o r m a t i o n   f o r   p r o c e s s   I / O   s t r e a m   # % d   F a i l e d   t o   c r e a t e   c h i l d   p r o c e s s             F a i l e d   t o   r e a d   f r o m   c h i l d   p r o c e s s   p i p e   # % d     d a t a         F a i l e d   t o   r e a d   f r o m   s o c k e t   # % d             F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d       F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d :   s e n t   % d   o f   % d   b y t e s             F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n                 F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s             F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n               F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   1   b y t e               F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   e x p e c t e d   0 ,   g o t   % d       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n               F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   c o m m a n d   t o o   l o n g           F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   m i s s i n g   n u l l   t e r m i n a t o r             F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   i n v a l i d   U T F - 8   s t r i n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   f a i l e d   t o   d e c o d e   U T F - 8   s t r i n g                 R e t r i e v i n g   c o p y   t h r e a d   # % d   e x i t   c o d e   f a i l e d           W a i t   o p e r a t i o n   o n   c o p y   t h r e a d s   f a i l e d       W S A S t a r t u p   f a i l e d :   % d       W a i t   o p e r a t i o n   o n   c o n n e c t   t h r e a d   f a i l e d   R e t r i e v i n g   c o n n e c t   t h r e a d   e x i t   c o d e   f a i l e d     P I D   W a i t   o p e r a t i o n   o n   c h i l d   p r o c e s s   f a i l e d     R e t r i e v i n g   p r o c e s s   e x i t   c o d e   f a i l e d   e x i t   c o d e       pC @   €C @   ÈC @    D @   8D @   pD @   °D @   a d d r e s s   p o r t         t o k e n - s i z e     c w d   E r r o r   p a r s i n g   s e r v e r   a d d r e s s         I n v a l i d   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   p o r t :   % d   I n v a l i d   t o k e n   s i z e :   % d     =       U n k n o w n   o p t i o n :   % s     O p t i o n   % s   r e q u i r e s   a   v a l u e     P r o c e s s   l a b e l   n o t   s u p p l i e d     S e r v e r   p o r t   n o t   s u p p l i e d         1 2 7 . 0 . 0 . 1       % d :   % s     % s :   % d :   % s     %s
                 U%s\       h   Y  M      U%s\          |Y  |M      U%s\       €  �Y  �M      U%s\                   ”                                                                                        p @                   øB @    C @                      RSDS3Þ¬«öÛmN¢¼H^„‘gØ   C:\Users\Dave\source\repos\windows-process-wrapper\Release\ProcessWrapper64.pdb                   GCTL   À-  .text$mn    À=     .text$mn$00 Ò=  6   .text$x  @  ø  .idata$5    øB     .00cfg  C     .CRT$XCA    C     .CRT$XCAA   C     .CRT$XCZ     C     .CRT$XIA    (C     .CRT$XIAA   0C     .CRT$XIAC   8C     .CRT$XIZ    @C     .CRT$XPA    HC     .CRT$XPZ    PC     .CRT$XTA    XC     .CRT$XTZ    `C  ´  .rdata  Y  ü  .rdata$zzzdbg   \     .rtc$IAA    \     .rtc$IZZ     \     .rtc$TAA    (\     .rtc$TZZ    0\  À  .xdata  ð_  ´   .idata$2    ¤`     .idata$3    ¸`  ø  .idata$4    °c  ˜  .idata$6     p      .data    p  à  .bss     €  H  .pdata   �     .gfids$y        À  .rsrc$01    À¡  èÚ  .rsrc$02                                     	ò0Ì<  x   ! t d    S  0\  !      S  0\   ¢	ðàp`P0  Ì<  H    	 0  Ì<  ˆ    4 òàÌ<  p   ! t �  \  ˜\  ! d \  æ  ¬\  !   \  æ  ¬\  !   �  \  ˜\  * 4× Ð 
ðàP  Ì<  p  ! tÖ dÕ ð  =  ô\  !   ð  =  ô\  !   tÖ  dÕ ð  =  ô\   t d 4 2à# d T 4 ’pÌ<  H    d 4 ÒpÌ<  `   /	 d T 4 
 p  Ì<  @   ¢  Ì<  H   '
 d T 4 ’ðàpÌ<  @   $ 6 p0P  Ì<  ¨  !& &ô= ä< d: À!  i"  è]  !   À!  i"  è]   d 4
 RpÌ<  (    d 4 2p 20@ @ä ;d 
4 
2p T
 4	 2àp` Rp`0
 t d T RðàÀ! 4
 ð+  ^,  �^  !   ð+  ^,  �^   b  ! 4 à,  -  Ì^  !   4 à,  -  Ì^  # ²0Ì<  P   -
 -t "4
 d T rà       	 d	 4 Rp0<     <1  R2  Ò=  R2   2P	 	b   rp`0	 "  0<     o5  ú5  ð=  ú5   P   4
 rP 4	 2P 4º ¸ P   t 4 2P    0   B         ¸`          Re   @   b          Že  HA  Ða          Æe  A  €b          <h  ÈA  pb          \h  ¸A  Øb          ~h   B  xc           h  ÀB  Èb          Àh  B  ¸b          àh   B                      °c      ¼c      Ôc      äc      ðc      
d      d      .d      Dd      Xd      hd      vd      †d      œd      ®d      Äd      Öd      îd      e       e      6e      i       j      j      òi      Üi      Âi      ¦i      ’i      ~i      `i      Di      0i      i              ¤e      ¼e      še      4j      >j              je      s      €      €o      €
      €xe            €—      €	      €‚e            €`e            €        êe              Êg      >f      Hf      àe      Øe      þe              ´g              ²f              Þf      êg      þf      rg      "h      0h      dg      Æf      †g      h      |g      Vg      ¢f      �f      g      @g      8g      ôe      *g              Úg      Hg      tf      ,f      f      Zf              TReadFile  SetHandleInformation  ÇGetStdHandle  ñWriteFile ¹WaitForMultipleObjects  Ô CreatePipe  »WaitForSingleObject ÔMultiByteToWideChar 4GetExitCodeThread VGetLastError   CloseHandle ç CreateThread  GetCurrentProcessId Û CreateProcessW  3GetExitCodeProcess   FormatMessageW  XInterlockedFlushSList ÝWideCharToMultiByte ZInterlockedPushEntrySList TInitializeSListHead YInterlockedPopEntrySList  KERNEL32.dll  H WSARecv   WSAConnect  M WSASend  InetPtonW WS2_32.dll  F wcsstr   __C_specific_handler  > memset  VCRUNTIME140.dll   free   malloc  n wcstol  ! _errno    _aligned_free  __stdio_common_vswprintf_s    __acrt_iob_func  realloc  _aligned_malloc  __stdio_common_vfprintf  __stdio_common_vswprintf  @ _seh_filter_exe B _set_app_type 	 __setusermatherr   _configure_wide_argv  5 _initialize_wide_environment  ) _get_initial_wide_environment 6 _initterm 7 _initterm_e U exit  # _exit T _set_fmode   __p___argc   __p___wargv  _cexit   _c_exit = _register_thread_local_exe_atexit_callback   _configthreadlocale  _set_new_mode  __p__commode  4 _initialize_onexit_table  < _register_onexit_function  _crt_atexit g terminate api-ms-win-crt-heap-l1-1-0.dll  api-ms-win-crt-convert-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll  api-ms-win-crt-locale-l1-1-0.dll  ®RtlCaptureContext µRtlLookupFunctionEntry  ¼RtlVirtualUnwind  ’UnhandledExceptionFilter  RSetUnhandledExceptionFilter GetCurrentProcess pTerminateProcess  pIsProcessorFeaturePresent 0QueryPerformanceCounter GetCurrentThreadId  ÝGetSystemTimeAsFileTime jIsDebuggerPresent mGetModuleHandleW  ; memcmp  < memcpy                                                                                                                                                                                                                                                                                                                                                                                                                                                          2¢ß-™+  Í] ÒfÔÿÿÿÿÿÿ         /                              ØU @           `& @   èU @           @' @   øU @           �' @   V @           Ð' @                                                                                                                                                                                                                                                                                                                                                                      S  0\  S    @\    \  X\  `  f  h\  p  Š  „\  �  \  ˜\  \  æ  ¬\  æ  ¦  À\  ¦  ®  Ô\  ®  Í  ä\  ð  =  ô\  =  £  ]  £  Ç  (]  Ç     8]       (]    ï  P]  ð    d]    X  €]  `  ø  ˜]         ¸]  €   ·!  È]  À!  i"  è]  i"  µ%   ^  µ%  Ï%  ^  Ð%  Q&  ,^  `&  :'  D^  @'  „'  T^  �'  Ç'  T^  à'  î)  \^  ð)  ‹+  p^   +  å+  „^  ð+  ^,  �^  ^,  ¿,  ¨^  ¿,  Ù,  ¼^  à,  -  Ì^  -  .-  Ô^  .-  Ÿ-  è^   -  _.  ü^  `.  ç/  _   0  !0  (_  $0  ß0  T^  à0  ð0  Ü_  ð0  	1  Ü_  1  ƒ2  ,_  „2  –2  Ü_  ˜2  Ì2  T^  Ì2  �3  \_   3  4  d_  4  M4  Ü_  P4  ™4  T^  œ4  e5  ˜_  h5  6  p_  6  (6  T^  (6  S6  T^  T6  £6  T^  ¤6  »6  Ü_  ¼6  h7  ¤_  ˜7  ³7  Ü_  Ð7  9  °_  9  l9  Ü_  |9  ´9  Ü_  ´9  þ9  D^   :  J:  D^  T:  <  À_  Ì<  é<  Ü_  ì<  E=  Ô_  `=  ±=  è_  Ð=  Ò=  Ð_  Ò=  ð=  T_  ð=  >  �_                                                                                                                                                                                          
         E   r   7                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            0  €   `  €   x  €   �  €                  ¨  €   À  €   Ø  €   ð  €               e    €                    €                  8 €               	  P                 	  `                 	  p                 	  €                 	  �                 	                    	  °  À¡  h          (¦  ¨          Ð¶  ¨%          xÜ  ›          �w >           Ðw X          ({ }          (                                                ­�: ©|6	º�EcÈ™OÌÍ�Q÷Ò¥^ùÕ©cäË£c¡Ò¦_GÛ�5×žC         k7Ë *N H%ŒK/G»‹=xÃ�?õ³‚4ÿ«{/ÿ»‰9ÿÏšHÿ×©aÿÓ¬oî³‘[’²…>²�Q ˆ<  n:Î s<ÖV-§‰Y9Gb˜l3ì�\!ó_C—R:dgI�›o(æ¾�Dÿ¬˜xÿ¸�sÿÛµx±ÓžKÕ¤W e/Ên9Î’o?ÇøsI»ïoH¨ÿV4‰â;wCqV'_u_<–\F%l™‰oíÄ´›ÿÕªeÿà»‚ÿÔ®r�] yIÑLŠ`Øï�yßú¢€ÒÞ¢{¡ü†a¥ÿ_:¡Ù�`>ÅÂ£qÙxoa9ÄÅÇÜÊ¯ƒÿ×¨]ÿÝ´tÿÛ¼ŒèÕ¬lF‘jÞ`¢äÀ˜wÕÈaK¾�D¹©}>ÿ’jHÿ¹�VùØ·ƒ‚YPAMÁ¿»õ·›pÿÖ©bÿÝ³rÿäÃ�ÿá½„§‘xRlš~d\ˆmyL]Idšv;%Ã˜U}È ] ÂŸg x9UhK‘­†Iÿ»�KÿÓ¦_ÿÚ°nÿâ¿‰ÿÕºŽØÇ©{ûÜ¼ŠúÒ³�è’{W�´”b¯¤†V—´ŒM«³…<Ñ†`%°ZÆÅ‘?ÿØ¨[ÿ‰mAÿ€g@ÿÞ¾ŒÿçÍ¥ùÎ±ƒûæÅ’ÿäÂŽÿ¾žkþÕ«hÿÍžUÿº‡7ÿ�e$÷[AÛ›n'üÐ›Iÿ×§[ÿ‰mAÿ€g@ÿÞ¿ŒÿçÍ¥ùÆ§vãÝ³rÿÚ°lÿÙ¬cÿÎ›Jÿ½‰9ÿ•j&ÿ[AýhJþ®}/ÿÐ™DÿÓŸMÿÙ¬eÿÚ°mÿâÁŒÿÖ»�Ø½¡t§Ú°nÿ×ªbÿÍ�Oÿ¸…3ÿ¢r(ÿZ ÿS;ÿ�\!ÿ½‡1ÿÎ•<ÿÓ OÿÚ®iÿÜ³qÿåÆ•ÿá¾†¥ª“pIÓ¯víÆ’@ÿ¿ˆ0ÿµ€-ÿ�f%ÿnNÿV=ÿ“i%ÿÂ‹2ÿÎ˜AÿÖ§\ÿØªbÿÝ¶wÿäÅ’éÚ°lC?2Æ©{’Ï£]ÿ»…1ÿšn'ÿ‹c$ÿlMÿfIÿ¬|/ÿÎ˜CÿÓ¡PÿÕ¤WÿÛ±nÿá¾‡úÜ³r|µc ¸œn §ŒbÙ¹‡±Í¥gÿŸw6ÿŠc$ÿhJÿjKÿ±„=ÿÕ¢PÿÖ§[ÿÙ®iÿÝ·zëÛ³r|Ì’9
ÑœI , êÅˆ Ô­qâ¿ˆ“Ü¹�ïÇ¢gÿ³ŽTÿ½˜]ÿ×±uòÕªg½Öªg¶×¬g‹Ñ S9ÁÈŒ1             Ù¬e Ó£Vàº~IãÀˆ äÂŠËåÃŒÀá¼‚hÂ�@®o¡M ¢Q             ð  À  €                                          €  À  à  (       @                                                                 ‚Q �\ …]«:eÃ•K¿ÉœTë¾•TðÅ�_ñÓ¨cóÐ£]ÙËœR­Â�Bi—i ®f·t                                                                 �n# •e¯�8a»ŽHÌÂ—SóÕ¦[ÿÔ£TÿÒ Qÿ×©`ÿÙ­gÿÚ¯lÿÛ²qÿÐ©løÀ�eÍÓ£W–É‘77·o¿~                                            ‚[ [9¥{9zÉšO÷ÐœIÿÊ“=ÿÇ�7ÿÃ‹3ÿÄŒ3ÿÍ–?ÿÐšDÿÒ�HÿÔ Oÿ×ªbÿÝ·zÿà»ƒÿÛ²rêÔ¡QŠÙš6Æ�A ý¿%                             m9Ì     H&†29'  ÿ ©|5t»ŒBñË•@ÿ»…1ÿ«y+ÿ¤t)ÿšm'ÿšm'ÿ­{,ÿ¼‡2ÿÇ�9ÿÏ™CÿÔ¢QÿÖ¥XÿÛ¯iÿÖ²yÿ¸›lþ™u<Ã³�26\aj Ã‚                     l8Ì p<Ð p;ÑDN)“°%—l%0»Š<åÅŽ7ÿ°},ÿ—k&ÿoOüT<ÜG3·G2³Z@ÑxUö¡r(ÿÃŒ5ÿÐ›GÿÔ¢Qÿ²ŠIÿ”…nÿ�xjÿ°˜rÿÙ°oÙÏ—>Bá¹z Æˆ(             p=Í n:Î n:Î6k9ÉÜ@"w¯  $U<�‰b'ÿ€[ÿnOÿQ:ë(
w         "OV=Ç˜l&ÿÅŒ3ÿ©=ÿœ”ˆÿ¶±«ÿº™eÿã½„ÿåÆ–ÿÛ±nÙÌ“86ÑœG ÄŠ-         n:Í n:Ín:ÎÂm9Ìÿ\0®òX-§åX.�õY0‘ÿM+{ÿ6Oÿ(¢  " :+dK#JlQ&hnZ<>'S;¹�d#ÿ�‚nÿÛÝßÿ®˜vÿÕ§^ÿÛ¯lÿá½†ÿåÆ•ÿØªaÂÍ�/Í”8     n;Ì n<Én:Î‰m9Îÿn9ÎÿuCÒÿQÕÿ†YØÿ…YÙÿQ×ÿsBÏÿ`3´ôB#}£ (jQ)_yZ(÷P:ÿ‘}]ðspkI -RF4áÊÊÉÿ×ÔÑÿ·“\ÿÚ«bÿØªbÿÜ²qÿãÁ�ÿß¾Šÿ¹ŒDvÿÓ… W8 m9Í m8Í7n:Îè}OÓÿ™tÝÿ©Šãÿ¬�äÿª‹äÿ¦†àÿ¡�ÛÿœyÜÿ�dÝÿo?ÇÿD#‚ª?3!M¡IíÄŸeÿÀ¨ƒàlcV*   †††ÈëìíÿÇ¿³ÿÀ“LÿÙ«cÿØªbÿØ«dÿà¹}ÿØ¼’ÿºžqÏÎ›J0Ì›M P»sAÏ—ŽeÙÿ§‡âÿ§‡ãÿ¡ßø¡~âÆ˜u§Èª�sÿšqXÿxY[ÿz_˜ÿ…^ÐÿT,¡ø/'­ u/ñâ½ƒÿ×¼’¼©_ (()'¬¬¬çôõöÿÀ´¢ÿÂ�=ÿØ©`ÿÙ¬fÿÚ¯jÿÞ¶xÿæÇ–ÿéÍ¡ÿØ«b—·j }OÒ(’kÛÝ£�áÿ¢áÿ£âÿ…h¹ÝK:s%¤x+3¼�FÜÉ”?ÿ¦v&ÿvT$ÿ`CEÿ[==ÿ…^(ÿÊ™LÿÞ¿�ýÁ¥zr†‰� 655C···õøøùÿ¹®�ÿ¾Œ=ÿÚ¬cÿÜ²pÿÜ²pÿÜ³rÿâÀ‰ÿéÏ¦ÿßºÞÏ˜A*•mÞ¡~â^¢á‰¢á¯£€âÐ‘rÊåJ9gdñÄù «‚@bÉœVïÌšKÿ¿Œ9ÿ³‚0ÿ¼Š7ÿÑ¡TÿÛ·þË¯�²®…E   <0®©§¤ÿêëìÿ¤œ�ÿ”n2ÿØ©`ÿÜ²qÿÜ²pÿÜ²oÿàº~ÿçË�ÿåÇ–ûÕ£Sl	 	    —sÿ­‡þ¦‚ë)bLŠ+   �g£|@KÅ�\ÂÍ¤cïÔªhüÖ¯rùÐ®yÞÈ§s�›wA¤v-"!+fIæ’q>ÿ©Œ]ÿ±‹Oÿ—o1ÿÐ¢YÿÜ²pÿÜ²pÿÜ²oÿÞ¶wÿåÆ”ÿãÉŸÿÉŸ\�zb=»Ÿ‚UÆŠpF¡t\7yZF%R6(/       Ð³o �q,®‰M5»–[O°ŽXE�o;%`H"¤z9{™n+œ 4rQë°}+ÿÌ–@ÿÔŸLÿÄ“EÿÔ£WÿÝ±lÿÜ±mÿÝ´rÿÞ¶wÿæÇ•ÿÒ¿ þ¬‘f­§ŒbòæÅ’ÿà¿ŒÿØ·„ÿÌ«yû¼�lð�xR†E7!)e<�x_7€lU1`VC%,sY1`‡j=y¢I¢¸‹EÙ©z1þƒ]!€2#^€[ ûµ�/ÿÏšGÿÔ¢RÿÖ£SÿÓ¤[ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò®”jýçÇ”ÿåÅ“ÿæÆ”ÿçÇ”ÿéÉ–ÿ¤�iéPC-ÃÒ®uþ×²vÿÆ¤mù†mFÛË¢aýÎ¡ZÿË—Fÿ´�0ÿˆ`"ßI4`_DÒ q(ÿÆŽ7ÿÕ¤Vÿ×¨]ÿÛ®eÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý°—oýçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿçÇ•ÿÁ¦|ÿ„oMÿà»€ÿß¹|ÿÛ³sÿ¿”QÿÊ”AÿÃ‹4ÿ¯|,ÿŠc#ü\B­L6Ì€[ ÿ®|,ÿÌ•=ÿÖ¦Yÿ×§\ÿÛ®dÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý®–pòçÇ•ÿåÅ“ÿåÄ‘ÿäÂŽÿãÀŠÿÛ·ÿÊ¢bÿØ¨^ÿÕ¤VÿÔ¡PÿÎ˜Cÿ¼…/ÿ§w*ÿŒd#ÿjKìC0àaEÿŽe$ÿ·‚.ÿÍ—BÿÔ OÿÔ¡PÿÕ¢SÿÓ¥\ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò¤ŽjÙá¾†ÿÞ¶xÿÜ³rÿÛ°mÿÚ®iÿÙ®hÿÖ¦YÿÓžLÿÓŸMÿÐœKÿÀ�<ÿ¢s)ÿ�e$ÿuSÿK5ùQ9þrQÿšm'ÿ»†1ÿÏšEÿÓŸLÿÓŸMÿÓŸLÿ×¨]ÿÝ²mÿÜ±mÿÝ´rÿÞ¶wÿçÉ™ÿÓÀ¢þ­’g­”^¬Û¶|ÿÙ¬eÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿØªaÿÒŸNÿÇ“Bÿµ‚3ÿ¬z,ÿ r(ÿ~Z ÿaEÿ@.ÿ^Cÿƒ]!ÿ£t)ÿÃ�7ÿÏ—?ÿÐ™BÿÒœHÿÓ OÿÚ®hÿÜ²qÿÜ²pÿÜ²oÿÞ¶xÿæÉšÿäË¤ÿÉŸ]�zgJlÕ¶†ûÚ¯iÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÔ¥[ÿ¿Œ<ÿ­z,ÿ«y+ÿ¨w*ÿŽe$ÿZ ÿR:ÿJ5ÿjKÿ�f%ÿ®|,ÿÈ�5ÿÏ–>ÿÏ—?ÿÏ—?ÿÔ¡QÿÛ°lÿÜ²pÿÜ²pÿÜ²oÿà¼‚ÿéÎ¤ÿæÈ™ûÕ£SkI9*ÃªƒÞß·yÿÙ­fÿÙ­hÿÖ©aÿË™KÿÁ‹5ÿ»„/ÿ®|,ÿ©x+ÿ’h%ÿ�\!ÿxVÿF1ÿV>ÿvTÿ–k&ÿ»…/ÿÉŽ2ÿË’7ÿÏ–>ÿÑšEÿ×§\ÿØ«dÿÚ®iÿÛ±nÿÝ´sÿäÄ�ÿëÓ¬ÿß¹~ÛÏ—@'   £�i–áÂ‘ÿØ¬fÿÎžQÿÃŽ:ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿšm'ÿ‚\!ÿ‚]!ÿiKÿB/ÿ_Dÿ€\ ÿ�p(ÿÀ‰0ÿÈŽ2ÿÈŽ2ÿÍ–?ÿÖ¦ZÿØªbÿØªbÿØªbÿÙ«dÿÞ·zÿçËŸÿèÍ£ÿ×©_� = „kC nX67Ï¶ŽéØ¯nÿ¿‰2ÿ¾†/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¬{,ÿ�e$ÿ…_"ÿ�\!ÿZ@ÿC/ÿdHÿˆa"ÿ¦v*ÿ¾‡0ÿÈ�4ÿÌ•>ÿÒŸNÿ×§]ÿØªbÿØªbÿØªaÿÚ­hÿá½…ÿèÌ¡ÿÞ·yÝÐšE+ÒžL '	    £ŠbŠßÂ“ÿÎ Vÿ¾‡1ÿ¾‡0ÿ¿‡0ÿ²~-ÿ‘h%ÿŒd$ÿŒd$ÿ‚]!ÿY@ÿL6ÿmNÿ“i%ÿµ‚1ÿÆ�9ÿÐœHÿÔ¢QÿÔ¢RÿÔ£Tÿ×¨^ÿØªbÿÙ¬fÿß¹~ÿæÈ™ÿà¼ƒ÷Ñ›HhòÐ› Ì—C     pW. [CÁ¦{ÂäÅ•ÿÏ VÿÀ‰3ÿµ�-ÿ•j&ÿ‹d$ÿŒd$ÿ�d$ÿyVÿbEÿ]Bÿ€[ ÿ­|,ÿË”>ÿÑšCÿÓžKÿÔ¢RÿÔ¢RÿÔ¢RÿÕ£TÿÙ¬eÿßºÿåÇ—ÿâÀŠüÓ¡QŽÆ‡#	Ì’7           Ç¢f Šl>6Ò¶‰ÙæÈ˜ÿÓ§bÿ§{4ÿ‹c$ÿ‹c#ÿŒd$ÿŠb#ÿmMÿcFÿ_CÿkLÿ˜m(ÿÉ”?ÿÑšCÿÒœFÿÔ¡QÿÔ¢RÿÕ£Tÿ×©_ÿÞ¶yÿåÇ—ÿà½„÷Ô¡RŽÊ�-Í“9                 + ÿÿê ª‡NBÝ¾�ÙæÉšÿÔ­pÿµ‹Hÿšq/ÿŽf&ÿ€[ ÿcFÿaDÿaDÿ`Dÿ‰f.ÿÓ¤XÿÕ£SÿÓŸMÿÖ¦ZÿÙ¬fÿÜ´tÿà»�ÿÞ¹ÿØ­hÝÑœJgÇˆ&	Ë�3                         mI ÿÿÿ Î V6à¼ƒÃçÉ›þãÁ‹ÿÕ­mÿÂ˜Uÿ¦~>ÿ�i1ÿŠg0ÿ•p6ÿ°‡FÿÏ¡Xÿß¹}ÿÛ´vÿØ®lÿÛ´vÿÞ¸}ÿÛ´uùÖ©bÙÎšG‹ÆŠ,)­V À}                                 ±p Ý²m ÐœIÛ²q‹äÄ‘ëçËžÿåÆ”ÿàº}ÿÜ³rÿÛ±oÿÝ´sÿá»~ÿãÁŒÿãÃ�ðÍŸWŠÂ‘D‰Æ•H‘Í™F{É‘9OÂ…%¬e ¶r                                                 Ì’6 Å„"Ô¤V9Ü´t—âÀŠÛäÅ”÷æÈ™ÿæÊœÿçÊ�ÿæÉ›úá¿ˆ×Ù®ifÉ�.ÐšF                                                                                 Ê‹( À~Ð›F$Ö§[WÙ®h‚Û±n”Ú°m‰Øªb`Ñ�K"ºn Å…#                                                     ÿÀÿÿ€ ÿ  ?ù  ð  à  À €  €                 À                                      €  €  À  à  ð  ø  ü  þ ÿÿ€?ÿ(   0   `           $                                                                                  ?, Ê�+ ¦t$¯|,e¶…7¨¼�A×Â“Hó§�Dß¯‰LàÍžT÷ÊšNæÇ•FÌÃ�=£¿ˆ2nº‚(6¼ƒ"   õàX                                                                                                                 ”d uE ¡q%'šo,t™u<³ËŸYûÔ©dÿ×¬gÿÙ­fÿÏ¥bÿÓ­pÿÞ·zÿÝ·zÿÜ¶zÿÚ³uÿÕ¬küÏ¢Zê¨~<¢šo*LÆŠ*(¾}Â„                                                                                                      �n# ˜i¥v,d¶‰AÛÇšTþÂ˜Uþ×¨]ÿÕ£TÿÒŸMÿÐœHÿÑ�IÿÖ¥XÿÖ§\ÿ×©_ÿØ«dÿÚ¯kÿÜ³sÿÞ·zÿ¼žnúÏ«t÷Ô¤ZâË”<�ÅŠ+.¿Â…$                                                                                         Šb! }T¨z1†Á”L÷Ô¤XÿÓžKÿÎ˜AÿÍ–?ÿÊ’8ÿÈ�4ÿÇ�2ÿÈ�4ÿÐ˜AÿÑ›DÿÒ›EÿÒœGÿÓŸLÿÕ£TÿØªbÿÝµwÿá½…ÿãÂŽÿÞ¹~ÿÒ¢WãÉ�7|Ã‡(ÇŒ/ ¼                                                             H*t <$`$    šm& ¤s%
ˆb&n©‚DæÕ£TÿÏ˜BÿÅŽ7ÿ¼†1ÿ»…/ÿ¹„.ÿ¶�-ÿ´€-ÿ¶‚.ÿÂŒ5ÿÇ�9ÿË”=ÿÏ˜AÿÑšCÿÑšCÿÔ¡Pÿ×¨]ÿÚ¯kÿÝµwÿá½…ÿãÃ�ÿÜ´týÒœGÀÐ“3;íšÙ—/                                                     o<Î žUÿK(‹^-S8_ «‚> žq)h¸ŠA÷Æ“CÿË”<ÿÀ‰3ÿ²-ÿ¦v*ÿ r)ÿ�p(ÿ–j&ÿ’h%ÿ•j&ÿ¥u)ÿ°},ÿº„/ÿÂ‹4ÿÉ’:ÿÑœGÿÔ¢RÿÔ¢QÿÔ£Sÿ×¨^ÿÝ³pÿÕ¯uÿ¹Ÿvÿ”{Tÿ‰e,ã±0_ë§;Ê‘6                                             m9Í l8Ìo:ÐtF%ƒÓ)R9 ˜k$'°‚:ÚÎšGÿÅŒ2ÿ·‚.ÿ¬z,ÿœo(ÿˆ`"ÿoNÿ\BýM7òG2éK5î_CúvTÿ’h%ÿªx+ÿ¼…/ÿÊ’9ÿÑ�JÿÔ¢RÿÕ¢RÿÓ¡Qÿ¥€Dÿ{mWÿxtpÿ`VGÿ¶Ÿ{ÿÖ«eñÎ•;rÆŠ,É�4                                     n;Í o<Ìn:Ïrh7Ãø2\Ÿ   ÄŠ0 |X³ƒ5ÿ¾ˆ4ÿ±~,ÿ¡s)ÿ‘g%ÿvSÿI3õ&
´f9   *1Q&
“F2ßrQÿ¡r)ÿ¿ˆ0ÿÉ�5ÿÐ›GÿÐŸOÿŠl;ÿ€{sÿ¿ÀÁÿ�‚oÿËªwÿçÆ”ÿèÌŸÿÙ­gôÍ”:rÈŽ2Ë“:                             m9Ì {Eç n:Í^o;Ðñ]1®ÿ,   %5L6Î€[ÿwUÿjLÿcGÿX?ÿ5&ä`   
                     )*žeHø�p(ÿ¿‡0ÿÈ�4ÿ†f4ÿˆ…‚ÿäåæÿ ˜Œÿ¸�SÿÞ´rÿà¼„ÿäÄ’ÿçËŸÿ×ªañÌ’7_ÿÿ� È�7                     q?Î m:Í n:Í<n:Îâo:Ïÿe5½ÿM)‘ïN)’çM)�êN*†üP,~ÿH)lÿ:"Pÿ&,ÿøc#         	  4(I81?1&   
!cF÷¤t)ÿ’h&ÿ{ulÿáâãÿÔÓÓÿ—}SÿÙªaÿØªbÿÜ³sÿá¼…ÿåÆ•ÿæÉ›ÿÔ£TâÊ�3<Ì’7 Ê‘8                 n;Í n;Ìn:Î¿n:Îÿn:Îÿn:Ïÿo:Ðÿn9Ðÿn8Ðÿn8Ñÿm8Ñÿm8Ðÿk7Ìÿd4½ÿO*–û6e¹%G    fM$ƒvX'ÜmP#îx[.æ…u[­AAA)   )“iJÿdWBÿÉÉÊÿ÷÷øÿ¨¢˜ÿº’SÿÚ«cÿØªbÿØ«cÿÝ¶xÿá½‡ÿçÊœÿãÁŒÿÑ›E¾Ï“6Ð—< ®{*         n<É _�  n:Í{n:Îþn:Îÿm8Îÿm9ÎÿsAÐÿQÔÿ‰_×ÿ�fÙÿ�gÙÿŠ`×ÿ�TÕÿwEÒÿp;Ñÿi7ÆÿO)“î"@x   $=“o6ódHÿ-
ÿM9ÿº§‰ÿa`]„´±¬  &Ï”“�ÿèèéÿôôöÿ”…lÿÐ£\ÿØªbÿØªbÿØªbÿÙ¬fÿß¹ÿâ¿ŠÿéÎ£ÿÐ©kù¦v*T°2 _=         n;Í n;Í.n:Îàm8Îÿq>Ïÿ…ZÖÿ¢€ßÿ³—æÿ·œçÿ´˜æÿ°“æÿ®�æÿ­Žæÿ«‹æÿ¦…ãÿ—pÝÿ}OÔÿo;ÐÿV-¡÷!?s   hBºÀ™[ÿÁ—VÿÌ§kÿº¨‹çFDAAlha    III«ÈÈÈÿñññÿççèÿ“xMÿÖ¦YÿØªbÿØªbÿØªbÿØªaÿÛ°nÿá¼„ÿáÂ‘ÿ¦”xù™zI¤Ð›G$È–H     m9Ì m:Êm9Í�n;Îÿ„XÕÿ§‡áÿ´™æÿ­Žäÿ¥ƒâÿ¢áÿ¡~áÿ�{Úÿ›yÊÿ–t¹ÿ�m°ÿŠl¸ÿ™yÒÿ£�ãÿ‰^Øÿp<ÏÿG%‡ê>:*Š©€@ÿÞµuÿäÌ¦ÿÂ§}¼g. %
    zzy×ÜÜÜÿøøøÿÚÚÚÿ˜u=ÿÕ MÿØªbÿØªbÿØªbÿØªcÿÙ­gÿà¼‚ÿäÄ“ÿçÑ­ÿáÀ‹ÿÓŸN�Ë”;ÑžL m9Ì l7Ë(r@Ïá’kÚÿ¬�äÿ§†ãÿ¢~áÿ¡~áÿ¡~ßø¢áËž{ÜŠŠikÉ²ˆWÿ²‚>ÿ˜m/ÿvU+ÿW@?ÿnU“ÿ–sØÿwIÍÿO'œÿ/ÉaEß¼ˆ6ÿÜ²pÿêÒ¬ÿÈ¨uŸ    4˜——ïãããÿüüüÿÒÑÐÿžw9ÿÒšAÿ×¨_ÿÙ«dÿÚ­hÿÛ°mÿÜ±oÿÞ·zÿäÄ‘ÿèÌ ÿëÔ®ÿØªbáÐšE(ÒžM ‡[Ø xHÐs“lÛÿ¥„âÿ¢áÿ¢áÿ¢áÿ¡~ßÿpWœÉ^I�“j ¤v)[À“KõÎ›JÿÃŒ5ÿªy*ÿ„^ÿX?ÿL5JÿH-\ÿ@(:ÿ`C!ÿ¥u*ÿÎ›Jÿá¾‡ÿÕÀ�ô²�TXÀ¢r **) $##G¥¥¥øåååÿþþþÿÏÎÌÿ y:ÿÒš@ÿØ©`ÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿâ¿‰ÿæÆ•ÿìÖ²ÿà¼‚ÿÒ�JrÕ¡N l;Ç“lÛš¢áî¢áú¢áÿ¢áÿ¢áÿ£€ãÿw\¥ï!A:+0 ¡n�l2ƒÆœZýÔ NÿÃŒ5ÿ±~-ÿ�o'ÿŠb ÿ†_ÿ—l$ÿ´�/ÿË–CÿÜ³rÿåÊ ÿ½Ÿq¯c: E2    �¥¥¥ÿæææÿþþþÿÌÌÌÿsY1ÿË˜HÿØ©^ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿß¹~ÿåÅ’ÿêÐ§ÿèÍ¡ÿÕ£U»Ï™DˆbÌ¡~ß¡~à.¡}àN¡~àt¡~à›¢~á¿¢âÜ™xÕôL;k®   oP  Ÿp&¸ŒE¹Ê ]þÒ£XÿÎ™EÿÅ�9ÿÂŒ7ÿÃ�7ÿË•?ÿÔ¢Sÿß·yÿÜ¾�þ½£xÆ±…@4·‘X %	 VA1ö›š™ÿÜÝßÿôõöÿÁÀ¾ÿeM'ÿšs6ÿØ¦XÿÜ²oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÝµuÿäÃ�ÿçÊœÿìÖ²ÿÙ­gèÐšF6                žyß štßžzß
 }ß¤�å9kS–O §x.  p$•r;|ÆžaìÕ«jÿÕ«hÿÚ®gÿÙ®jÿß¸{ÿÙ·‚þÑ´…ôÅ¢k°�h.&i žq*    +�uTÿy`7ÿ‰uTÿ–‚cÿ™~Rÿ§|7ÿ‚a+ÿÔ¢SÿÛ°mÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²qÿâ¿‰ÿæÆ–ÿí×´ÿáº~üÐœHn#Q8*d? "                                  ¤q" šg­5@ª„H„¸•^»Î¨mÜ»›iÏÉ¦nËº–^™—t=D¬u"  œt4M—m)€   - —…_"ÿ¨w)ÿ¼†0ÿÌ˜EÿÔŸLÿÆ”Dÿ•o2ÿÒ PÿÛ¯kÿÜ²qÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà»�ÿåÆ”ÿãÌ§ÿ°˜tï•o3YbN.Ëº˜dÿ«ŒZô”wJâ|b:ÆdN+¤K:}1$W5                    e9 5  œh¯{)�n#¢g­J    SA%(›w=†©|3î‡`"—    0" †_"ÿ©x*ÿÁŠ4ÿÑœIÿÓŸMÿÒžLÿÍšJÿÓ OÿÚ®iÿÜ°mÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá¼ƒÿèËŸÿàË«ÿ´¥�õ¶�T›{eAçåÄ�ÿèÇ”ÿæÅ‘ÿâÀ‹ÿÙ·�ÿË©tÿ¸˜eü£…Tò�h@¡	7*C3g5(Z%D5		''5D3KhQ,r‘rA©´‹Jã¾‹;þ•j&þwUb   C/Ì�e$ÿ«y+ÿÂ‹5ÿÑ�KÿÓŸNÿÓ NÿÔ OÿÕ£TÿÖ§]ÿ»‹?ÿ¨|6ÿº’SÿÛ¶zÿà»ÿâÀ‰ÿéÏ¥ÿîÙ¸ÿòßÁÿÚ¯iæ†oKõåÅ’ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿæÆ•ÿçÇ•ÿêÈ•ÿ¹žtõ!WUE-z¸–`ý¹–]ý­‹V÷¥„Pò{c<¢aL+¢€Iê®ŠQð¼–YùÊ ^ÿÎ�QÿÅŽ9ÿ¢s(ÿ{XÙhJ"&
ojKû¡r(ÿ¹„/ÿË”=ÿÕ¤WÿÖ¦YÿÖ¦Zÿ×¨\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö�vRþæÆ”ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿÓ¶‡ÿ0)Þ]N5éà»€ÿâ½‚ÿã½�ÿå¿‚ÿ¢‡\ú~fAöàµqÿÛ¯iÿÓ¢VÿÉ“>ÿÀˆ1ÿ¦v*ÿ‚]!ýqQx!	TU=êŒc#ÿ¬z,ÿÅ�3ÿÑœGÿ×¨]ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�yVþçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿäÄ“ÿ]O;ÿˆrNÿä¾‚ÿà»�ÿà»�ÿá¼€ÿÌ¨oÿ·�PÿÎ›KÿÆ�9ÿÄŠ1ÿ¾†/ÿ¥v*ÿ‡`"ÿsRÆ1#mK5åvSÿ™m'ÿ´.ÿÊ‘6ÿÓ¡Pÿ×¨^ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�xWõæÇ—ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ”ÿèÇ•ÿ¤Œgÿºšhÿá¹{ÿÝ´sÿÚ®iÿ×¨^ÿÕ¢SÿÈ‘:ÿÃ‰0ÿÃŠ1ÿ¸‚.ÿ r)ÿŠb#ÿuTóH4¦>,äbEÿ�\ ÿžp(ÿ¹ƒ.ÿÈ�7ÿÓ OÿÕ£UÿÕ¥WÿÖ¦Yÿ×§\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö…qRçåÇ˜ÿåÅ“ÿåÅ”ÿåÅ“ÿåÄ’ÿäÃ�ÿãÁ‹ÿá¾†ÿàºÿÖ¯pÿÓ¤YÿÕ£SÿÓ OÿÓŸMÿÓŸLÿÓŸMÿÌ–@ÿ¿ˆ0ÿ®{,ÿ›n'ÿ�e$ÿxVÿ]Cß<+çP9ÿkLÿ‰a#ÿ¥u*ÿÀˆ0ÿË•?ÿÓŸMÿÓŸMÿÓŸMÿÓŸNÿÓ OÿÕ£Tÿ×¨^ÿ»‹?ÿ¨|6ÿ»’SÿÛ¶{ÿà»ÿâ¿‰ÿéÎ¥ÿîÙ¸ÿòßÁÿÚ¯iæxeIËáÄ–ÿâ¾‡ÿà»�ÿÞ·zÿÜ´tÿÛ±nÿÚ¯jÿÙ­hÿÙ­gÿÙ¬eÿÔ¢RÿÓŸLÿÓŸMÿÓŸMÿÓŸMÿÒžLÿÄ‘?ÿ¤u*ÿ–k&ÿ‘g%ÿ{WÿkLýB/õJ5ÿ_CÿtSÿ‘g%ÿ¬z+ÿ¼†1ÿÏšEÿÓŸMÿÓŸMÿÓŸMÿÓŸMÿÓŸLÿÕ£TÿÛ°mÿÜ°lÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá½…ÿéÍ¢ÿàÌ­ÿµ¦�õ¶�T›dS8£Ø»�ÿÛ°lÿÙ­gÿÙ­fÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÖ¥YÿÓŸMÿÓŸMÿÓŸMÿË—Fÿ¹‡7ÿ­{-ÿ¤t)ÿ•j&ÿ}Y ÿsRÿT<ÿ9(ÿS;ÿlLÿZ ÿ˜l'ÿ³-ÿÃ�7ÿÏ—@ÿÐšDÿÒ�JÿÓŸMÿÓŸMÿÓŸMÿ×¨]ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿá½…ÿçÊ›ÿäÎ¬ÿ°™vï”n3YI:#nÊ±‰üÞ¶vÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿØªaÿÔ OÿÎ›Iÿ¾‹;ÿ¯}.ÿªy+ÿ«y+ÿ©x+ÿ�d$ÿuTÿlMÿ@-ÿC0ÿX?ÿvTÿŠb#ÿ¡s)ÿ±.ÿÌ•=ÿÏ—?ÿÏ—?ÿÏ˜@ÿÑ›FÿÒžKÿÔ PÿÚ®hÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿãÂŽÿçÊ�ÿîÚ¹ÿá»üÐ›Hn!6²›wèäÁŠÿÙ¬fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ®hÿØ«cÿÈ•Fÿ²€1ÿ«y+ÿ«y+ÿ«y+ÿ«y+ÿ—k&ÿ‚]!ÿ€[!ÿ`Dÿ:)ÿO8ÿbFÿxUÿ˜l'ÿ¥v*ÿ»…/ÿÌ“9ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ˜AÿÕ£UÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÞ¶wÿåÇ–ÿèÎ£ÿíØ¶ÿÙ­gèÑ›F5   �yW»åÉ�ÿÚ¯lÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­hÿÙ¬fÿÑ¢XÿÆ‘?ÿ»…0ÿ­{+ÿ«y+ÿ«y+ÿ«y+ÿœo'ÿƒ^"ÿ�\!ÿ[!ÿN7ÿ@.ÿV>ÿmNÿ~Y ÿ�p(ÿ®|,ÿÆ�2ÿÈ�3ÿÌ”:ÿÏ—?ÿÏ—?ÿÏ—?ÿÐšDÿ×§\ÿÙ¬fÿÛ°lÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà¼ƒÿæÉšÿëÔ®ÿèÍ¢ÿÔ£T¹ÎšGâ¶q cO1r×¿™ÿà»�ÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÔ¦]ÿÉ–FÿÀ‰3ÿ¾†/ÿ¾‡0ÿ¸‚.ÿ¬z+ÿ«y+ÿ r(ÿ†_"ÿ�\!ÿ‚]!ÿuTÿ?-ÿH3ÿ^CÿsRÿ‰b#ÿšn'ÿº„/ÿÉŽ2ÿÈŽ2ÿÉ�3ÿÍ•<ÿÏ—?ÿÐ˜AÿÕ¤VÿØªbÿØªbÿØªcÿÙ­gÿÛ±mÿÜ²pÿÝ´sÿäÄ‘ÿçË�ÿîÙ¹ÿßºþÑ�IlÔ N 3' '(²šuàéÍ¢ÿÚ°lÿÙ­gÿÖ©aÿÌšLÿÁ‹6ÿ¾‡/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ·‚.ÿ¥u*ÿ‰a#ÿ€\!ÿ�\!ÿ‚]!ÿeHÿ:)ÿN8ÿeHÿxUÿ‘g%ÿ�p(ÿ¿ˆ0ÿÈŽ2ÿÈŽ2ÿÈŽ2ÿÉ�4ÿÎ—?ÿÔ¢TÿØªbÿØªbÿØªbÿØªbÿØªbÿØ«dÿÚ®iÿàºÿæÈ™ÿêÑ©ÿëÓ­ÿ×¨]ØÐ›F!ÒžM     }eA�áÊ¥ÿá¾‡ÿÑ¡VÿÃŽ;ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿ•j&ÿ‚]!ÿ�\!ÿ�\!ÿ[ ÿV=ÿ;*ÿQ:ÿiKÿ~Z ÿ•j&ÿ¥v*ÿ½‡0ÿÇŽ2ÿÈŽ2ÿÈŽ2ÿÊ‘6ÿÑ�KÿØ©`ÿØªbÿØªbÿØªbÿØªbÿØªbÿØªaÿÙ­hÿá¾†ÿåÈ˜ÿíÙ¸ÿà¼‚ÿÒžK|á«R ÏœM     K8 9(.·�uáêÏ¥ÿÑ£[ÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¼†/ÿŸr)ÿŒd$ÿŠc#ÿ…_"ÿ‚]!ÿvTÿL7ÿ=+ÿT<ÿlMÿ„^!ÿ—l&ÿ®|,ÿº…/ÿÄ‹1ÿÉ�4ÿÌ–>ÿÒŸMÿÔ¢RÿÕ¥XÿØªaÿØªbÿØªbÿØªbÿØªbÿØ«dÿÞ¸{ÿâÀŠÿçÌ ÿæÈ™ÿÔ£UËÐ›GÑžL              x_8}ÙÀ—þåÅ“ÿÍœPÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ½‡0ÿ¥v*ÿ�d$ÿŒd$ÿŒd$ÿŒd$ÿŠb#ÿoOÿO8ÿ?-ÿU<ÿmNÿˆa"ÿ›o'ÿ¶‚/ÿ¾‰3ÿÈ’<ÿÑžKÿÔ¢QÿÔ¢RÿÔ¢RÿÔ¢RÿÖ¦ZÿØªbÿØªbÿØªbÿØªbÿÝµuÿâ¿‰ÿåÇ—ÿèÎ¤ÿÖ§]ðÌ“:QÐ–: Í™H             :* ! £‡Z¾èÐ©ÿá¾‡ÿÌ›Oÿ¿ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ«z+ÿŽf%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿˆa#ÿjKÿ_CÿT;ÿgIÿ‚]!ÿ r(ÿµ‚0ÿË•>ÿÏ™BÿÑ›FÿÔ¡QÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢SÿÖ§\ÿØªbÿØªcÿÜ´tÿá¿ˆÿäÅ”ÿéÐ§ÿÚ°mûÎ–=‚Ë‘7Í•=                     Žl7 ]E;À£tâìÓ­ÿà¼ƒÿÏŸTÿÀŠ4ÿ¾‡/ÿ°}-ÿ‘g%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿ�d$ÿZ ÿdGÿcFÿZ@ÿhJÿ‰b#ÿªy+ÿÀ‹5ÿÐ™CÿÑšCÿÑšCÿÓŸMÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢Sÿ×©`ÿÝ¶wÿâ¿ˆÿåÆ”ÿéÏ¦ÿÜ³sýÏ˜AšÊ‘6Í”;                          ÿÿÿ €b3_Ñ³„ñìÔ®ÿá¾†ÿÔ§_ÿ½‹;ÿ”j&ÿ‹c#ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿrQÿbFÿcFÿ_Dÿ]BÿxVÿ�p(ÿ»†2ÿÏ˜AÿÑšCÿÑšCÿÒ�IÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢QÿÔ¢RÿÖ¦[ÿÛ±oÿá¾‡ÿæÉšÿèÎ£ÿÛ±nûÏ˜AšÎ•;Î–>                                 7(    šxArÚ»‹ôìÕ°ÿãÁŒÿÔ©fÿ±‡Dÿ”l+ÿ‹c#ÿ‹c#ÿŒd$ÿŒd$ÿ†`"ÿhJÿcFÿcFÿcFÿ_Cÿ_DÿjKÿ¬€9ÿÓŸMÿÑšDÿÑšBÿÑ›DÿÓ OÿÔ¢RÿÔ£TÿÖ§[ÿÙ­hÿÜ³tÿß¹~ÿäÅ“ÿäÅ”ÿ×©`ðÎ–?�Ê‘7Ì“9 _'                                      _F ( ²‰IqÞ½ˆñëÒ¬ÿäÃ�ÿÜ³sÿË [ÿ¯…Bÿ—o.ÿ�e%ÿ‹c#ÿzWÿbEÿbEÿbEÿbEÿaEÿ_CÿtV'ÿÈ™NÿÚ­fÿÖ¦ZÿÔ OÿÔ OÿÖ¦ZÿÙ¬fÿÛ°nÿÝµwÿßº�ÿâÁŒÿáÀ‹ÿ×¬hýÎ™EÊÌ”:PÊ�6Ë’8                                                 œs1 wQÏžP_Þ¸zãéÏ¦ÿçËŸÿá½„ÿÛ²pÿÐ¥`ÿ½“Oÿ«�>ÿˆd,ÿsS"ÿoP ÿpQ!ÿwW%ÿ‰f/ÿ«‚BÿÌœPÿØ©_ÿàºÿà»‚ÿÜ´tÿÜ³rÿÞ¶xÿá¾†ÿâÀ‹ÿâÀ‹ÿÞº€ÿ×ªeüÍ™FÕÇ�2xÄ‰*ÌŽ- ¿‡/                                                         Î˜B Á~Ñ�K<Ù®iÁåÆ–ýêÒ«ÿæÉ›ÿá¾†ÿÞ¶wÿÚ¯lÿÒ¥]ÿËžVÿÇšTÿÇ›TÿÎ XÿÖ¨^ÿÚ­dÿÚ­gÿß¹}ÿçÊœÿÔ«jóËžVöÏ¤`þÐ¦dÿÕªfýÔ¥\ôÏœKÜÊ“;«Å‹/bÃ‡)½�%¿„'                                                                     µz# Ö£R Î™CÕ¤W€Þ·yåçËžÿëÓ­ÿéÎ¤ÿäÃ�ÿà»€ÿß·yÿÞ¶vÿÞ¶uÿÞ·xÿßº~ÿâ¿ˆÿäÄ‘ÿéÎ£ÿá¾†ïÎœL`¶'C¸‚,`¹ƒ-eÁˆ-YÅ‰+=Ã‡'Á„#ÈŒ) ¦g                                                                                     Í•= È�2ÐœH0Ö¦Z’ÝµváäÅ“ýèÍ¢ÿéÏ§ÿéÏ¦ÿèÎ£ÿèÍ£ÿéÏ¦ÿêÑ«ÿëÓ­ÿæÉ›ÿÞ·yåÔ¤VhÊ‘6Ð›H                                                                                                                             Î–< Ê�5Ð›F&Ó¡Qj×©`¬Û²p×ß¹~íá¿‡öâÁŒùâÀŠöà»�ëÛ²qÎÖ§[�Ñ�K2Ê�5Î—A                                                                                                                                         œ= â¶S ÉŽ4Ï˜AÑœG;ÒžLQÒžLXÑžKPÐ›G7Î–=Ä„$Ç‹,                                                                                         ÿÿÀ ÿÿ  ÿþ  ÿ  ÿü  ÿ  ÿø  ÿ  ÿ0   ÿ  þ0     ü    ?  ø      ø €   ð <    à     à     À     €     €     €              0    ø     ü       ?€                                                                                            €      €      €      À      à      à      ð      ø      ø    ?  ü      þ   ÿ  ÿ   ÿ  ÿÀ  ÿ  ÿà ÿÿ  ÿø ÿÿ  ÿÿ ÿÿ  ‰PNG

   IHDR         \r¨f  € IDATxÚì}wœå™ÿ÷�ª.moöº¬;®‚ÁØ„ÐB	Ž$€Ó+I(ù]r	wÀÝåîRH%…�5	�\$@(¡0Ýlã¾öö¦®éïï�ÑhUFÒhW[Lüý|ÖÞ�F3£yž÷y¾OŽáŽáŽáŽáŽáŽádªOàÊcÃõ÷‡˜Æ–€ÝkFOTîO©çŸ¼Cžêó<†£ÇÀcÃõ÷‡hMÝ¬P °ŒaÈ
Ý �„�v AÏ¶k­srCSƒ°t
,Öºß0èÖp4ºÝxðW»Ž)ˆc°Ã10‰Øpýý!ÒÔ¶šg¹UA7·VÑéJŽeæNÆgkºñ¥t;�¥¤gŸúâÚÎ©¾Ç0õ8¦ &–À‡<âûŠÓ8–Y5ÕçdAÓ�7‚¿‡#w?{ÕÉ[§ú|ŽajpLTº¥�ã„KÝ{CõSŽgªy|.ïÓèø�©éÆþ”¢ß¢iÊ=Ç,ƒ,S U@–Ð_:ÖU>äâpq¹9E!77ÏÂ#0à¯À‚gí¿.U§H(:Tƒ"©ˆÊÂ)IÇ`BÁHRu¤(M5t0wG¢Ñï³
þ1pLŒ®¿?œ5ç ä“ËœZÉ{¼<Z"š¼ý"¼|Qá®T�b8©¢'*ãHTÅ�á$Í(ùô�ýÃá?¦ÞÝ8¦ *Ä)?|nE0¸Æ-pç8eè›}<f×ºÑr¡5 L¨°;E_LÁ;ƒ)ìêO",iE÷S5ýÎè¡_yæÆÂS}ÎÇP}Lý“x”à¼_o½ÌéjïâÌ«saN­í5.xÒ ªN¡Šf@5L›Ý0(ô"æ;K †!àók8Ó]¨DÁ$U=Q;ûSØ3�°u8†IŠvÕƒŸXq÷$ßöc˜`S %°~Óf±ö²k.!7–×¹8K=XÚìÅŒ ˜`;$UŠf@ÖH…fPõ*°yYpó&gàáST	%ÕQW@Ñ¼ÑÇŽ¾„­‹ jú�#wÿ3Çr
Þ=8¦ l°~ÓfÑýOW}Å-°Ÿ-%øæ7x±¬Ù‹yu.pì¨�¥T=ó{R5“4HÍÙ>Ùpó,‚.6‡PÌV ,Eðfw¬À"Ðtã�X2uÁ±hÁ»Ç@,Á¯ñ
ÿ\Ê¿¹8¬žáÃÊ6?Ü<[ðzJÕ3,üT
|)dGÎÞ:ˆIžÞAgXÊÙ®éÆþX2µñ˜8úqL¤‘öñKšúóëÜXÓ@G�»à5Kè“ê¨9_‰ð«…®›«±F	´ôï¥\	 ÿŸcp„‚e™Ì6'ˆ+|ƒ:/¯ÀÚîóv_ÏíÉ±Ž)�wþáÀ©?{åô€[üv±ø=G€%Í>œ<'ˆ:Ÿóš¦ˆÈ¦àÛùðÅ€¤ê�4“ðÓt
Å¨®ÿo�·E
º8o/ÜqeÔ9‚F/¿‹+Øo ®â¡]CH(£×¤éÆ‘ƒû7‹½ø‡U º¥½Îïù�r¡ÝëV¶ú±~N�<�ˆJÂ’†¤R:–®’ª9íû+šQ•Ì½±B`Ü<¯Èf¬„¸Í5øÍ~¡À5H(:Ú9„�„šÙÆ€þñW,ûÐÔ]Õ1Œÿp
Àòó½<þÛ.M·˜à—[í³‘RõÌ*‘§'ÀdLþlò25n-1g›¢¸ÿ­Á% iúåÇB„G'þ¡À)?|nE(¼­˜¹¿´Éƒ59¦¾¦H¨ˆH¥9¥êˆ+F�ÙïtÕ7zÚ÷×©ù+§Ù¸œåû3 K8–K(Æyé�aˆÊ¼‚°#4EŽ`fPÌ±ÍÀ}Û2	Dšnì¾ë¦%váÁõ›6‹ÌyŸZÔwh_jœ+xõº®µ €¡H�ùû3‚« X–ëQ’ÑA—7Ðçóˆ½„»�ñÕÇ?„Øpýý¡š9s¿É0ÌWí^o¹pÆ‚šœÕÎ‰à[+}¬„+ é’¦gÓ0L—@Ö)4ƒBÕ�LP5`%ñ,G rÅk,`¡”"h¹G-¢pJÃïßìË(·XJýÚãŸ]õ��?ÝÒK©TM{Ç«´TlÙX¯…< Ü¨2¦”FÐCšª¼¡ËÉíõ[i_×+Ç8ˆ±ã]¯ Ò$ß/ìØý�‹Ã¦y!,möe¶•|Í�é;ZM§N©�4Šdº`g²a��…‡gr”Q¶°Ô¸ù× ÁË£Á7*�ïô'ðøÞ°ußöïÛ€åD×¬j�7ë	:Ú�Pc»¦*oð÷„ßÍ?sÌRpŽw­X¿i³XÅµÿi·ês8af ›:B™‡ÜòñâªíñŠ™øvˆËd�"&kÐ)ªºÂW~��_ä rÄV ¦kQë.Œäó~{�a	á„„¡¡¡ª�cþê_	5¶SÃx8àÿ¦ýáæg�e.Ç»R”òõ["ÎYT›óG%	µh(/œÒJ
°eæGåâ
Â.ãnªaE6a?‘Aƒ/—Ì¶Â)¿y£=C$ñ²ŸéxE^vô~
<%}ß:§KHr�ªÜ3JiÔPåûkÞ»�)ƒB¼ëÀy¿ÞzãŽ|†Ÿ#ÀÆŽNœÊlK©:úb
$–.*kHÈ¥Mö¸¬•úlLG ˜¡=Ž >‘+ªD– Ù/ä¸3ƒBÆ:xl÷0ž~»’¬d^o¯ñ èá9]Ü‹¢8–�O0÷�+")1YÇ@BEXÒNH§4GÇÊ†¥”pÿ­;ÿç’ç§úÞO¼kÀ†ëïfÍùÏ±Wä¿ÖráÜ%uv¿”Ÿ_nÅW41YÏ˜÷N1ÝÜ Ù‰=ê½<Î&`£æÕ¹ pz¢2~ýü^´´5Ô¡ÎËW”�˜�R‰K$UG_BCOTF_$itÇuFÓœ+B�ír<|g�¡üê™D|W(€´ÉÿÇ|¢ÏnÕ/fî—üJVûb(fÈª=…šˆ"ž’AÔÉÌ¿W¥DÎ¾¼Ë \.x!PÁw b�)†l`ÁêN”�|%à´×¸ hvõ'Ç|_
>ßÍUüÕ è�)8‘qd ‚ž¤3‹Ë²
‚.ö²ÒQ¯ ÎûõÖË\÷Ãüâ�/�Ž«ÏøúÅV}Í00’*^´‘tŒ$•ŠVûbHÄ"ˆŽc¤¿R¸ƒ±”èŒ<!/B¬iBSC=¼¡:„ZÚá	Ô”?'Åþº]ƒZŸÉ7°àX4û…Ìß3ƒt
tŽH(‡låªeÝP.¦ä’cþ�qÅÀ¾¡ÆŒÎ°ìè€,!OÄûÝø�äÕ
à‚Û·}×Žå_ÚäÁyKê3+UJÕÑUrV}+œgÃ×tŠˆ¤UlæçÃøD4ŒÃýÃP#�ú'/BÅ¸¼hm›ÿÌ…¨ŸÙak%S €iA5úÅ%Pïát›î”È™=¬è‰ÕÐ$¥QÈšÍ Mw|ýâh¨R`8–”­g(‡¸b`÷@o÷Dq,!OxEæ;OaõãòÅL#•
`Ãõ÷‡::þ7?�Ÿ#ÀY‹ê°ªÍŸÙÖ•VýRßPB³à«ŠŒ�á’ƒ]8Ü?C.4‹“]{@õÊ	¬ñ‚°Úfw eÁr[FCõ¥€uOí”À¬�˜£`‡*ªUÙr•6ÿEŽÀ'rf£Ô¬š§è‰*ØÑ—ÀÞÁ$ÊqÿÁQ§ :>wóÜãÖžò‡ü_ÈÅáâå“ßŽá/eî�ÕÔWƒ½ÝéïEÏÀ`Ùý•È ÔÈÀ”ÞCÎÂ‚«Ñ4yÙæ €é4ú„œmÙ®Àî�ä¸ x–�·Â.ê"GàâXø]\E®ƒ¤êx«?åÈ*`	yÂM”¯¾9‚£J´žÿ•uKO9û/¾†¶n­ZÖ�Ia�Jº£JÎ{­VÙùˆË†SzE°ªS |dŸ#¡Ï†¡iHuï™ê[	 àƒ˜¿t%‚s––Ý×Ž´¬€½åãÿNàY°d|�¤_4;UB$îêObkOýÑ2<†®}ÛüŸwSÔà¨Q /žô¾ÿyð�|á_×ÀûÔfþÎ7ù5ÃÀ@\-0÷ÍÀ`R«ˆÕOÄ"èîîÁáCAuÕñûò‘ìÙªN�|”Ä¡˜µj=:Þ™QnˆI³/7DøDû†Rã>– ~±rö¿ü"‹:ç˜;80œÂË‡£%¥4ÊRýÊW¿ºþ®ªžìáèP „|xÓ·îÿmhFGfG€óŽ«Çª6?T�BÓ‰È9&±U(�PâÝ½ýcZí‹A�‡¡÷LáEâÐ €«yÖ^òEðþâ‘ƒ|W€cLËàp¤P™Y„«jPèEB«lVGc�ÀVlþ;Ç2ºL«À	gp`8…ç÷—tÞ-nÁ´W „å>µéßî¾5ÛLuq.]ÙˆÅ @DÒp(,gºbR5Ð“ùùªN1Øu»öî·%óÆƒéäX
  Ä`=V}øjøêš‹îŸop0œÔ i$Í¬lKÖcÐÅ‚#€È³9ÅKãu	
?‡C�›ud¼Õ—ÀK†m¯‡ã8øx€eØ¯¥~ÿÃ­)ÆÓ[ríi7üî{ÙÂrqøØ	ÍhIPICwLÉtç)fò÷ÇÄ4çP·™_©þÎªÄÿÇ}½¦‚cD9	¡¶k7¢Çc»>Ð–ÊöJ(ž¡ðöæ¿¥<<7ÏB¬ÒP§î�jP¼t(Š7�„GÏ‰ãrJ¦ãÉÔv/«_~4ZÓV–¿aý?ßz}Ãâ2Û¼<>vB3êÓ)½ƒI5Ó™Æ0(FRZN§Àùª?Y‚Ÿù¼iâd[ Z®Äq}ÉvŽ ­A ³QÉÎ*d zxÆñ0«n¡Z.ƒ[`Ñä-¯Â)Ïì4:Ã2ãw‹¯³ÐÁ2ì×ÿìªïŒû¤&ÓR–¿aí—x}ëª™m­ŸZÓ’ùÒ{b
†“*†d„?¿\×‰¯o™ú;wížÁÏF¢sç¤~^6¨aZLRÿÁLÙ-ÕÔŒ»³âÂÏ#[ùf£5`æôÇôÅÇÏ‚®±%ød1�×2pjôD<{`)Õ~EIJÊžpÏÅGK¤`Ú) Âò7œð™o]?óÄ³3ÛÚC.|ì„fxyŠAÑS2	,†AÑŸP!§É?M7�PtôÆÕ²¡½žÎâã;…<Ü-žÔÏ¤†CMMF¢º]N‚=Xÿéëm#Í>:ö•Oÿ-‡Ræ%pqB.vÜ‘„ ‹C½Ï¾˜)àâÀ³IÅÀcï�~hæ‰~éÑ�I86Õ;A ,ÃÒ‹¿|ýœM—d¶Í­uá“kZàæ
…_Õ)úb2²9š„¢£§ŒðaÏëÇ¡#Ý“¾êç\/a %"“òYÔ0`(IªÐÑ{CX¬èçöƒ=`xÁÈ	xƒuÄÛÐZx,tG%tüë‡‹cÁŽ£rÐ‚fPÄQIƒf .ž3QÖŒ$5p�+K÷¹y6ó7Ï,¨w£ÎËãHDB~.Cˆ„¹|ÁyŸKíÿË-/Œûâ&ÓGríâÓÿé¿~èË™MóëÜøØê�bPtŽH™Ìµ¤b /®ÂÈ2bâ2†S:B@)E¾‘¦*2ìÜŽÝ;ßBR™ütÜ|0œ`Z tb{šCN>¨ç�uyÀð‚ù#¸Àº¼`<A†„ÐœãFïŸnæ÷G$£*Â ž*þä\+ I30’Ò`ÐôÀ”1(˜¸b–|»9~_pž„Ô{y,lð /®ÚÌ:ÅéË?ô…¹�±Ô#�¶NËöÐÓÃ äÃ­+Nþíš/ÿ(crÎ­uáãyÂo1ûQIÃH*g@zc
d=?Ùg´¥§óÀ”øùå0‘©ÁÅÌ}Îë	€duæ<SðEOÎ6c[Î{}ÁZTÕ2ÿË!äâPëáÆR9‚9µnÔ¸90E‰aP¼x(Š—:£¶¯Ç“©íû�éØ«pê aÎt¬|ää¯þ"zj¹ðéµÎ„?¥êè�+(–Ò>8<Œ½[_Á`lüÙj�‰Ê	(&ü|°¬8:ÚŒ°<„`}Žà–‡PÛ&¯'_¨®±è�± ö¿¨TX	D€é´„’ç»o0…Gß²%5ƒ³jbÓtNLê•C–_&Ö¶ü~Ý¿“þfŸêË~Ã J¨9ÂKçüÛ	¿fPŒÛ�Œ`(9õæ~10Â‹ã?Pœ
? ˆµ-9ÂÀVø=^_U…Ÿgè¤
? „%�#’ã,Ðì0cJÕ±o(…¨¤Á(’ÙØQïÆeÇ7£Î[ØÌ”cH­Î{Ÿ<õg¯œ>©]SÆN˜Iuõ¹S¿~k] ÕläÓàåñ©5-ð‹l�ð[a>‘”Š�"‚•4lëÄ`$NÃ‚uû¡'"îk�ýfè©êÔ €¡$…ß_6ÝMÈ‚XÛFpåîh ë*Lry¼à¸ê™ëÕ"ÿ*¾70sC’ªŽe QBA—iT’�˜lŽxó	,ˆ�%!rŽkòb0¡b$/•˜!ÄÍzyÝÆ+öw?öëm“~ñ6˜€ñk©¦þyõç¿Ódeùy;¡AWVøâ2‹ÿÁÁ˜ñú¾n¤¤ÑÌLVô@l¬Z»úªƒuùÆ�4M)~Fp¬òœ'P°�°<8oÀö¸¢X]+e²Wÿ|Hš�î¨Œ�„š™ÄdÁ/²¶Âo!¦80,�É³ç-©Ãê™þ‚×t°ðz½wž~Ëÿ<¥7 �)Q F2rÇâ3>¼ÂŠõ»8&“ág…úŠ	oL±íe¯h:¶ìÅÁ¾Ûkâ<ˆÓS	0&ouÌP_!×Áês? à¼¡Â{d³0C5Á3Ó§9ªå$Ò±d·ÀEµƒjPt†%D‹¸CpÊÜ6Î³/®R|{:(�IW „åo,\û�…ÿôÿ2R|éÊF´ÍÆŠóÛ	ÿ‘°dÛÁ&šHâµ}ÝN(%?›Ô�ó×a:‚óÆ}Cµ~]¡ð{¶C7˜<~À‚ÈUwµæÙé} �ÝQ1Yƒ§Âôâî¨‚¡„Z”8¾Í‡Ž«·}m:(�ÉU „|XÔ\¿áËßƒî;wq]¦ª¯§ˆðkº�#a© Ì¤Mþƒƒ™LÀrp5Îr<rj2ÁûB ìØ}lj¦?a¹3@ ¤Ý„"“xN@51Õæ¿8HÅÁá]’²1�PÑ•K’ƒ-·� Lµ˜4@X~(½eõç¾“©9_×ÀúÙ¦0&Í¼};á/ã/eò—‚«±ÝV0¦¬{ì\€ÝêÏy‚«?ayÛkgÆ8†«RL'ó?¾t
±¤Qì–—+‹Å‡#JQ%0«FÄEKë¦�˜°~Óf‘êÚ]Ïû¬ß*0™[ëÂ9‹Ms<"�VñÅ½¬ð§To,kòay¸[:ªîÛŽcuìV ö«3ŸpÕ%ùŠaº™ÿ€I@çãHÄ4í+AJÕq`X²1 m!WI%pÂ÷ž¿|²¯}RÀóOÞyK`áš‹/øœ˜	—®h„À$TÝ1S�³“|Š	4‘Ä›ûsYþ±€°ü´‹°.ï˜Ü »ÕŸÜ«?P\ÐÇ:ˆ³RL7óß+ï,<�PÑ–sf”ƒjE°Æ ¼^ï�“�'0ñ
€�óÞÀæuŸûŽg8|ôø¦L¸¯'j
rR1r’|ì„¿R¿¦cd€ó•æ‘�b«?[ÄÅ)jŒƒpŠéfþ»8¦l‹°¤¢ãHDªˆp¢Šƒ*eï9å‡Ï­˜¬{0¡
€pÂLPzËÊ+¾™i3uÖ¢ºãoÅúU�æ4ò°#üöt�Éß/>P¡¦yüªŠ…âŠ�EÂPE )Jô· ml®V>¦“ùÏS8�¤QŽÈUU³jD[%`enüé–öÉ¸¦ Ò~ÿoÖœã·âýK›<Ò¯'+Öß5çóW~Í ØÓ=Œ®‘êeÊåC¨m�6‘�JSƒíŠ›ËÙšÿŒàvrÈ	ÁT¤þƒÕH¤¨ºIVÒï°œè¨wãôù…Ç�Ú¨¤ÿeÃõ÷‡&ú^L˜xá™ßþ‹+TòºÍ_`úý.k`’~ÃI5ÓÌCK—–Äåœ8¿fP¼ÝÙ7¡Âoa:Ex¿³Š»¢äo/èÅVùrdh5\®é´úW*üÙè©,B`)�bÑ�å­>¬k/$}÷²d¨å¾‰¾¢ Ë/cþmåÇ®Ï„ü.^Þ /ÏdH?†!Ii™‡+’Rs2ü,á+Ó?†sž6‘�ñ¦3|é¸=ÕÔÜ]…¡g¼«QB=]V;Æ¿R‰(+�R!Âg°¨±pññ¸„÷Mtx°êjyý¦Íbçþ7®?áÌæ¥ç
 °±£kfú¡]5Kàc’–SØ3ÙÂoÁ*Ò¢Õéÿ?öó``¨JÙá!TW, ªk ¬ ªÊÐ¥$ôTZ"->ªëÐ’1è©(´d$ó£§â Ðâ#™=‡.%@U	†œëò‚c	Sù#cšÿSZx
 4ã_)¢²G¥æ3]¬ˆˆ³çÀÁáyõ:ÅésÎùÔß>tëþ‰¸'UWË„åoà\žëÏüÎ_ÀûkÐìãñÅ“f@`zb
Â’U§™Ñ]ÖäÞì5ÂŸ5:yàÐ”}>P¾k05èRZ2šÓÌ0ËyíX}Þ_g›lDX®ÆÒœ“PÛš‰ –‡È0œ ·K,k5MvÝ¿\ã˜ô«3‚BE.EÈÍåŒWÏFTÒp÷ë½ý4ƒPWMDC‘ªÞËô_vÉUàý5àpéÊ&ADÒ2™~é§éúãÓKø�é°K¦†CS Ë	èRòÀaè‰HASÓJCzNL|šå"P]…$+H&âÂ`/â‘a$qh6½ß­Â˜î@%Ä`8¥- 
¸8œ¿Ä>2Wð¿qþU½+ÔÐêí8žÌÞx1 `cG-~Ša†ùòI¿ÞØh3�é"ü¦Cd€uû2B¯%#Ð¥%5öñâEÌw«Ex)P­´;b)„ðP?†††�LÄAuuÊcÿ•„ûÆŠÎ‘Êòº£JÑRâ¶�ëç„
¶OPµ;CXîS ÆÉ'lþ ³³Ï)&h•÷Æ=CúÄåœpßt~î–Ž)‹šÂò¡ÏG1%0–ó%“³ÂÛA—�·T£ºš±"±"’^46‘K¸o¬8©,c°'*½'«gøÐ^ã*Ø®øvµ“„ª¢ O°–êÚ.>ã#°x~hycÆô�¥ý~+Ó/–E f’Ït~“04†¦™ä›&ƒÝEÍyRåæ¦åÜ€±FdÊb$žB×Há„4©Š@t8¸PuŠ#çsTÃäÁì"CpÎ¢:¸ùB×)¡³w­ß´¹j…UQ F2úMÞlšûÁ« ˜U~íA1cúÀPÒü_ÓôgeýŒ“ç+ËÃÕÒ1þ•@¶Ðç›Úœ¯z]xË�C9Tb …ùá”†®‘ú#É	oË^MÆß)$�æÚå�Rõ‚¶a<ƒ3ö®ðyÜË’g}úÆj�ó¸ aùe,Ç]½ì’« z<ð
,Þ¿À|híLÿÞØèêŽH’Þ[m°¢®–yU?n¶àC±¤ MÃŠlŒ¯5½!U¦¨‹YNIÕ@Tš0Eà$Ç¢•´ŠªjQ> £Þ�e-…Q›�Ïõµj¹ã>ª«ÿåjšMÚO¾À €3ÔÀË3ˆHŠžcúgûýQIÃ;Gú«q“Î¨ZdÀ‰à[`8~RRx�œ‹Q�Ò!,_¶Âp"ÁD2þN1�P+Š”j&²±#”3�ÙÍx]"BÁàmÕ8×ñÝ)Âœ	àË.¹
Ç3í!N�[“¹	Ù!¿”ªgü~EÓñÖ¡©ŸŒ[)„ÚÖq·s*øÙ¨´B°JEœ·Y•ð&ÙŠ`<Ád0þNÑuN
ªéè˜x–àýjÁ±Lz6¡ÉkP�UÕˆ
ŒïnQú?�yÇÃšâ{áR3†™Pƒ¸¢C£$'Þ¯»ŽT­¤w²ájœ5&¦ÝZõÇ»F!åXûŠÏÏ¡p;åÆÒ_ ©²°â{4‰Œ¿¨:Íô¹p‚pJ+pƒ‚g–4ypB[¡+àåñßã­» äÃ ]±âbs–ßÒ&æÖš¦ª•è ê"G0’R3ñþ½#Ó–ñwŠJ"•˜ûÅÀp<8‡9	¥&—Š÷SÃp¤Tœð ã�š„SŽ„+‹L'á·�TôŠø€|WÀïâ2dæ©!¸óš³ê„c|n×ŒçÇ® (ý�ÀÂµhX|8œ—Î`êM›üé¹ñ²F!kôÇ•I©ì›h8�š6.ÁÏçåžÃVØb½€t.€ƒPŸ aSMÓ[Õ(ð™($TÇIB–+À3!—Cdz'Ïµq	sÅxº�Mòa +.ü< à„™4ûE¤TIÕ@BÑ‘Ru¨éÿ\ƒ¶šêÁ˜J”ŠTcÕÏç	Œ»kO9wâ¢”«tBþU‚pJ+ÉLE¸¯RtG�=å®cE‹6cÇnñÛc=·±)€¼Õßjî9˜Ì�ùÆÕLnxRÑÁ³3‚X2«µÞê¶šž
Øµ«æª_øyÎÜ€bdÕµ’n€S–_O„‹¾6IS7�)˜Êp_%�4ZÒà¿ÀÀ+š–Œ%?vØ4/T°�‚¬:ï×[/Ë¹U® òVÿg9sÅ×)†“*T�BRuDÒ\@B5�­Àý"‹ùmX0£±êC'&ÙÃF&Rø�Üh 7ÆU––È¨8‘ÍEû£RÆ%˜NŒ¿sÜ<¯È‚Í*—NªFÑ¦í!:êlÂÂ„Œ)9¨ò;Hñ5ß¬ã2«ÿûš‰*ƒIjº§?`¶ü �R¨ºýªSãáqÜ¬–£Þ-p5Îaù	~ %Sƒ³Q*M¸\��R$bæEÜ€ÉH™§4„Ò¤¦ùV½ñÑ{ææY„Ü\Ñ°”ÅpêÜBK�‚Ì‹P™ Ì™ ]±øìÍ Lß?(rˆÈf®8-üá¬N?I¥tö™åßÑzÔºjt| nRzë[©Á´„°i%»û”N¸qª´s&«pJ‹�¸Õ8ºBÉIÅäÈüSÖòUÓš¶C­‡Çr›Arc¥u•Z ßpÕ4¢mõé€LÊoTÒ 4ó¿Eüå›þ¥À³óÛ°dV3Ü®ÉR1^P]…`öÛw5Ì˜ðÏtÒ/°T8¯\‡_Ç<@ž0YS.Ñ\$Rª™w4)�À".k9æ~)ô'Ô¢×·¶½pò0™[{Ù5WrNŽ€9ÚË8yþ—ƒáxfy‹õÞvõJ›þ¥àY,o¯Çì¦c:óTW¡%¢¹÷ˆ!6Ll7g+5x¬ª«¥‰@%å(€êjŽ˜àásI?M7Ð9"Aªp–ßdÃÅ\8†@3€þ
„ìrqE­€JÎÍ± ºv-ËñtöÉ  6u„ ä®þ’:šøPÎô/‡¦ ‡™®ü€�ð[`]>µ­úùXÌä.™¤k%‰@Ày¶Ÿ•TíÐŸí5sØ"ŸÑ‘§¥àYSð.—¯LjÐ.ŽCÉÊ­€J¸ G
€ñkzaûúóï¯A{È…¹µîóo%ý¥{Ê:ulú—»�3‚X6§eÚð¥„ßçU<à£8™!XÊ×/Gê«þ´¤y&zõç8î2¤ßtR<KàØ’çÜ—p^üTÊ
XbÓM„\ãôØŽ€‘Š~€nºÕ—ÅBZÌJÕ!©:b²�šWžÉ„§’p"ü„ÚVÛ1ÜÕ€•\jÕÕKX†Z†¨ èGKD'|õ/'üº"SOZ‚Ï•ÉOÈ&ÊË¡”°Æf¦ Yå´\Ø™@éç½móœ³^�Å	3™ÕßÒNÖê/M`‘O�‡ŸR~À©ð[fMXd€ó…Jæ”$ÕTÙ>€N¯u¢CŸ~we÷oªˆÁl?ß)âÎï]1+ ÁËc–Mû°` àÈ
(« ^<	@ÇÜ“Ï ¼7íwDò|kõñW)¦‚°ÌÝJ1Q‘Î Jô	7PAó'¹c�ÅøWM7*¬ñ¢˜ŸïQÙplë$ ï±©da\æ¤R°¬0TåÓ `‘'Î0³•bé“²ü™ñ• “?0»~Âù«÷þX0‘‘¾Lo‚’õÿeâýN¢V£’±*ÇRÈgü+�"¬¼¤¸âs,ãç;A©´ßl¨-šØQçFÈ�Ò	Çpœpi¹ã–T ù×ºòðþÌ¯s£ÞÃgrþGRæêŸRÌÕ
¿‚Ä	M+Öåä¸kï'*2ÀùjJ&ß”äLü-°fR¼ªý	<<S”ñwŠ”Z\`Æ‹±˜ûÅNU(‘x|k¡àØÏ–;fI@åÄ… üm'~ €9Ã0ÍëæZ¾ÿd®þv¨ñðX9·³›jªæƒP]…Qa#Ìbà¼!ðÁ†ª^3+ºÁy‹•ä”TÙ¤­DÑO~›2-©Î}*î«C	µ¢~å`	þXÌý’ç™tvŽªAs†çfÃn¶ ™[®T¸´0Œ+XŽ§�+N…‹cp\“‘ôÍ÷ý§bõ·CSÐÃßÑ:n~ Æß)ø@CÕ#B¨©èkå|órn€© í�‘?i¸T… S8	÷UŠ¾¸:nRÐ
ëU[ð-Tb©D${àX,l(ä„ü.¡dN@Q@8a&Ë²ëk�?=,mòÂÍ³H)zA³Ï©^ýóQ�²ãJ[`;Eµ#e­Š!=]N”�¨ñpÁ¶bMJõqZÕ~ã!�†õÆÍ(Îòç#*kEÚqM…‹ã²RõE ÕÕKtM%³ßcöû[•f“ªaNz1("’6­Vÿ|XeÇ•†«á÷—‚«aFÕ” Ãñj[Š¾®Jã‹Ø‘�L]�ŒýžŒ�ñwŠ±ðÕôó� ’ÖaÅÜ€Ž:·mÛ°Rõ%\ r~¶ù¿¬Ù—“øci¬é¶úÛ¡’°a5ýþb œ¡¦iüJ£œP* 'ce�ŸÍ”kQ>+`<Œ¿S%TG™‚åç—ƒ¬Óª„í¸ �c>Xl[Àx‚µ,Ë®oZzbÆüÌÖÞ–ö‰HÓË÷/§eÇeúç£š‘�rn@©h€.ÅÊ'e…A™2]¥V@5§N�|L´ŸïNC‚IÕ(ê,i*\ä4M»`Ãõ÷‡ìö·U TN\¨k*i^µ€iþ[™QIC\1 éÆ„fýMJ•O´éŸ�jEÊ¹e:ˆãk‰°ã%N­€j2þNPÌ˜?ß	*‰XÄŠX­~1W‰é„c‚³æ|Àn{ kç@ýò“Á`^�‰´ÖQuŠHJ�´¬¿‰B~Ùñd˜þvàU)*eM”s´d¤¬P‰e¤FÊ*�‰`ü�`(«Æ~²ýür¨„)±ß¼ºÂÔ`
Ø†@š1Üàm›_]3æ7¤ÙU7§ü1Y?*W;Xü@]`b
wœ@¨m7)(Ö4•L
Ò¥WårV +º¡Å†ŸO¹¼€©~	EŸ?ß	œZªA‹º
Ÿ·À�c·o�xþ©»6ð·/] XÜ8ZöWt$d“0Œ£wõ·ƒ×ÄÌŽùà¼åKm'ã�šZ2)h<V€Uî«K‰Š:³&’ñ/Žeàæ	T½ú«ÕBT6gsZbA4 ¥uvIA…. ¥§@pÉI €¥Í¾ó$¥V­ÞºÀòy–E{[+šÚçÀãšÜ‡t¬-Åt9-…¡¤JFÌ}K'³XqÔ÷WFúŸ›jc1¸DaJZy»ybFÒ³õFnS�˜âLÄ‹Dàx† Ý¦B0äßŸ¿ÍŽ8 æ-GÈÅ¡ÞÃgÌI5Ç|+ÚôÔžcAR5
†Nx]"šÛç¢©¥eÂkÝ³QIá�%øÙÃ>ÑSº6 Œ %#9+<5Œâ�jrEƒ²­€É÷åÃÍ“œ¡šRÚôµœº¥¢µ…
À ¦lg#G0ž`-ËqË½móÁûk21EËü·4Ó»iõO”Ècðúƒ˜1k6|µõ“v>¬ËW22`hj�à[ S6¿ \åžÉüÎð¢mØÏj„êÊH/€É÷(˜¦k‡éjXS´� Øó;»¶0bCAVå‡s€‘Š­Ñ5•Xþÿ‚z·Ùô3mþÇeò»HúíVÿ|ð,‹ÆúzÌž5kÒø»È€%øåºõðÁÆ’¯ë‰Hé2a%•Yá³MÿlPMv¬¨&ƒ×S“*ü–¹_ÓÙ
°¸¶rHq¼[P" ¤©muöß¹w)íÿûæ®`j+÷ÿÝhþ'*ÈbdD·ÉL’[�ÝRÌÐTÇmºÊå å¹ ->\6æ¯%ÂŽ	AIžœiÐÅÌýR˜®V@Ä¡(¥ÀæÔ’Êù<@¾š< jŸñÿUƒ"©ˆ)ÆQ•ùWªN+?mÁëbÎÜ'¶ó/ 5Í04Õñ°ŽÌûj[�Ó�ÊY€³!NÂ‚ŒËCS!ÙUc|©iº¨¥.N¥Â�3Båy€ŒX¿i³ÈrÜrÞ„¯®í5®Lø/¥êˆË¦IÓÕª`¼uâõ¡ fvÌŸP~@—S‚ Leó[XÑ6Pú¼Jå0¼z2Zv…×¥DIN�qù2ó’‰ô*gY:ñó� ,M? ëÔq8°˜%;3Xh0T_‘]˜y²þþÜ='èšJæ›ÍDçÕ¹ ¤¨}×™ÿ©*$2YüÀD„µDTWA8b“Þî¦9%­ CNÚ–
3‚;£pœäõ«‘[E‘-ü™}+´dJ^ŸC?ß	b²mNr,ÅØ¥3ç}j‘õwæš² üí‹˜SHSŠY3�˜fM?Æ‹˜CÿÊ)ª6´„ß#zÀÊ¦ëfƒuûÀ”'.Gs\Âr`¸QEFuÍ¶@>òó'ÚN.ª†0s¿¦cUkRuö}—âZ…SR#Ë­ßGU(Å2 ´u  ZüTƒBÒL+àÝdþOÔ 	‹�[�/ü8o ¼/TÑ±<m2Ó{ŠÞ¨+Àð…ÄŸžŒ–�ûk‰pfÂ‰`Äâb<î¼Ûp6&Jð3çUÅÖaÕB5x€¶À¨0°íY¼ô“«ÿàzøÖ{­mÙjz% øg.Dƒ—‡›g¡êŠ™$ëïó¬ä_%h¬¯GMMzzû*j+¦Kq[á·À*Š°n¸`#Œd(2½Çt<`�E¹->R4$˜¹¯Ñ!°3J
?`F I„àr6I˜c™ª™ú¥`‘�Ó©>ÀâœU4¼Pxî!7‡Þ—ÁÛÞŠD×ÞïôÚlÇŽF	@ 4·M>>Sû/¥Í‹w‹ù?Yã£*M+¦šìH°…`CE£¸¼³—AO•núQªk`ºJ™¸?ÕdÇaÁdÂ™PM?ß	œúÜ“	§EwrÞs�EñûßÞ…½p-^¿õ›4Ñ½÷« ½6ÿ} ¼ðÌoP]%ÞÆ™`8ž™2	@Õ ™ðß»“=?ÎëámŸ‹D,‚þ�AÛªÉŽ{ë[¤ 4Ðéh†ãái[€TßA0®ÂfŒèáxèÑþ’V€žŒAãø¢s	Y—z2
Öå+kš
EJµÜ<™0S¿ŠŽ:Ïä%,9='¯Xþ^XŠ"‹â¡_ý ÿ{÷o �ô§_%? èMvïc €ÚR ¶ÎP>ð‰fE4ùx„\x‡óÍ§&Ãü/†RiÅ•v!ª42 ¶.€Gí¢i©i*t©¸¥@ZÜ>ù‡uy3V‰uÖ()ØV­°ÞX¡êtÚE‡¡À”ªãÅîÂ•ÿt6~ñó›é¨ð ½À^r­9ëc Ëß@uõúÅg|‹?úüÛûf ö¥°µ;Ÿhß¼!¥êP4)�BÖt$}Z»
1Y¯z`,Pu=ÃèR¼¢aœÙÐQÇghZOø¥?¶°5£	L¬Mù0ï¯+ï�@XbÝè1'ð| ¬ƒ&'¯._Ë€gè”	~6¼<.nüª8¦°¾ß*¨âY’ÞÇ\�—µŒ~oC	ÑîèéïÇ›o¿ƒ÷BMÅ¡�ô á®ÿåìS/þÙ³W�¼• ªk³ÀÝ: Pïáq8"!¥êÐ))ZÁåæÍVJÙ�‘¦H©ƒšaDÝ$W¦ƒbÐ¦I#‹HÄ¼è>°gÌÇá¼Gî5†iZ¼¤t®c}µ¶Â jl„åsÂ�9ÇJ‡y_ÈVø“´ËÈ‡$+¨©!ÓÊ¢ŒËÚ´Q °Ä”¿|a·CJÑáN�u^uó`ÎüpÏ^�è;9×gRŠVàCÖ•® !Ôoú ªN“4°„‚«àâX~kÿ,JÓ$ŠnDL¨Æ¤·«FòO5¡î–yPcCf-½ò¹“È€å×{Ú—ÎÙúÔs�µ'—:¦)ÉDÁº¼J¬òjd dM+z@Xñ”‚Ÿ³^ƒ“�©zF,açX,1Ï�ÉºÿœƒlPÕ °»“v¼†‹cZ�L � ž†hòñ™ƒI…P%íÌ±‚n>3B.,lð`i³unÌŠ¨÷šÍÙ	*Ÿ*ß¿øùèH¤Ì�¼¿î–Ž¢[9ˆu­Ž"Çµ´ŸåÎèî-}¥zöiš
-1R2ñH—%–!'m§1ÎÌœo"%CÕ§Þ-ËÆD†¼9Y¯ÀÂ+°ˆBnÎt³<KÀ0LŽðK+‹%ÙU*æ›çã	ÖÉˆ ¼ÁZÔºùQß^5 pkžM–1Ùì9ÄS¹r„å!6Ì¯$!uWÌˆµ-�‡{ÊZºAÎ%,w]bßë·z;Ž/š¹hUrÞšK€ð"¨¡C‰–$#µd4ã
0Âò¶ŠjºY’F!ØxŠ¦#,é�4³ŒÜ�SPSQˆ‚�gôûðšþºµ¢È¬êŒí*^~ÅÓ¨³UQ)òŒ\x†ä$‰S·áúûC•“m Àr<åý5¤ÆÍB1(dÍ€¤é¨á'?,RÊ�H©æyUêFLÿÈ]ýóÁ¸[æAéuLð&›/ë!÷”Ü�á¸–™ç~auçý?ù¾tø­kÜsVÝW—“`W)HøÑ4_]NBK„‹v5¦š
->Wã¬’J"%Ãç¦	˜‹…e‹iERÑÑ•0œ7ÄS•d¨±8 +¯¡nŽ % bÁüy<}çÆ|>fªoy9,51àâ
æÐšºY5ô6 pÕ6 ¨ñ™@:%ùÿŽeàwqcr#¦“û¯¨åÓN…šfxf,rÜ‹­(ÊðŸi=ÿË÷IáÁç”#;Kî«Æ†33³…?s-Ñ¡¢VG%uùÑTÂ²£’†þ˜Œ¸¬9VN‰x;wíÆƒ�<†×wìªŠë©9<F©Ï
ˆ…rÌ®F†0Ì `ÓNÐÅBÓ$U#Ã<Nw¸yA7�f¿€Y5n,nòaQƒ³B.´DøEŒœp¤$gÃ*	ËÃÝ2¯¢	Bœ7àˆK`ö;ŒÛA¢ÿð>¥ï@É}ÕØ0Ãeõó­Âñ`=�ŒòrÒ=h:qªNÑWrêx–@ å­H+"C5;wíÆÿ=ú4’69•@q˜›PJøÄÂï.àš€Ì  ŸÏÌó
,’ªÉÔO'¡©–µPçá1´ûUxâ]XÕêÅ’F:êÜh¹¹IWrª®CrXåe�÷×UdðÁ†²ûBNn9õÒK	Ë0Ñµ'VJ	po¶/ÒDÄÐTh‰0Ç›�Ió>ÛÌu(�nL�À³nÎüñ‹,¼<:êÜ.#GP–£šZ�é©'£¸ïþqpïî1Ÿ£aÐV‚S~¡ðÜSªÑÊQ]ó€2- Ï ©H©ú„€“…®¯ fÏ[· ¸‘ËŒªºYñ˜Ru$U#3þ|"0Ö‡Ü²œrb]ky2‘s]wÊu÷-yæß/¼Dê;ø0 "4Í)Ø�²< kP#ýE­]NA`ù¢V‚€Ø0«ä9'Rò„‘�™8:I“rEr[j=XBÐt¡;"å¼æu‰èÝ¿Ñ=¯Aê;�©¤jšà�¹ØöÞX•’O>ù>àõ¡±¥­âsgªNáD5Ý°uW\6‰|^‘mà Ô€K4ÓÝ‹ˆlF¼Âô eÆ‹½/>ÉU‹÷~ä‹¶¯ó,AÈÍe”‚aÐ)ABÑÍYˆ²Vµøðxëá…šfpÞ ¤þÎ²Œ¿l(`8®åÀÖ'¿j|V×éG¥¾ƒ¿Až`³ÚŒÓ´Èn<Êp|Ž©_¬+±ÙÔ4®L�‚„$Ãëß”$ž%eÝu>ÃÜ‹,A½—Ç`B…F�Ã/>œ®¨+ž¸Å{ƒ·ÁåAXºœÊIó~èáGðO}ž`Í¸®¯ŠåØeòr™Ë ´ Ñ E3 èÆ´" Ç
%6Œý»v oÇ‹Ôi}5Ã0¥Ð^ãÂ’fVµz±°Ám;|±TjþÛžŸàq”7à¤fÀ$¿²”þN×µÿ—èÚËàlH<C‘ ÅGÀp<Ø<s¿\Z³]^@>œò#@¡ùn)q¯ÀBäÙŠ„ß/0óÜA¿ÈAÐ“xéû_À+?ÿç’Â j"‚�—Â¡ßý’=ûrÆª¦}êo��iª–:Î�`/Ë Á3Z)&O³˜ùxðêßŸ èšJúw½2æã0ŸÈ™!žÏ˜B5I.+o AH8¾ld€aØï  (½‰°ü�– EBwTWÍ¨€�¹_ª�˜¡©¶Ó‚²!©FÁ}âY’v;A¯TØóÁ33‚…4cC½øÓ7?Šî7Ÿ­èxj"‚®©ÿ`Á}ëê<ˆÃ;^®ø�ö,æºÚYó.Žie@i  x·®´“!iÅ’Ž>~ëÕÌï{þþhÕŽ[L!4xù‚¹lœ„ÿ*…•EX*ÎÎy%• !ää¶³?û  ºzƒ¥R�oå^³àëöƒ°<Ôè íjohjÉnÁå:Ž‡¢j‚>–UÝ)fÔ¸Y4ûG•¹N)þú_Ÿ-»ê—ÂÐÿG-…¨ËI(á~hñaüý™§*¶œ&³ìëyˆ‡hfé·@JÕ�ê@6Þxî‰ÌïÝo�Ý(K!X.ÃòfÕ¸rÈFe‚,+'.AÙð çºÎšCuõ€|?Ñµ©}¯�°\Fð³¡F‡m#¥úZ\ `
;áxð.wæ‡ã8ÄULˆ C�Û¼.GPçáÐì°íÿnÁþ];Æu\]SÉÈ+†2Ò5ÒŸábF"tî»bì¢]ŠAÛ >À¬éæYÅ �T9ú5@Oç~$úgþÞ¿kÇ¸c²NÁ§I¤Ž:7VµzÑQç†G‹Â5An2©Ä%VúRáÁ!˜½–°ü�‰þÃH¾³Åö=ÔÐŠšü–Àp|æ‡uùÀº| º–vŽ³�„S“Ó£¯ÎÃÃ•·ÚÉ0žº÷—U9¾4Ò_à
 À[Û¶Vtœñf²«èe dh^KIHw”$•Â®—Ÿ)ØvxÛß'ý<†A@d�|þ7XÛÑ„U³0«ÞgL„2jšK-ÕR,CZ[î@ÿaÄw<mM04jlØ¼Î,a74¬ËgvNÿdŽ«©PÊôJtÚw¼°Ë�{áÑ –¤Z	¤Ãolë:¸oLd`9³2‹úËñÀŠ7˜’ÎÕÆÛ/=U°íÍ-/LÉ¹Þñ2Þxéy f^öìz?3QÊ€ó‹òå"B0�l%Ýö¤9«€1Û‡³¢''L˜/ìZ	Ö¿\ƒ˜¤BŸ„î<-~.žÍi¼i÷Ü8ÅG/»O?ý4^yå|ñKW0­ ªk™C‘ �«ž’DŽ©³µ¿Tƒõ
@ÓìÛöjÁöÎ7žƒa“Nrvíx‰®=PÂ}B£±ò€‹CÀågf×û1”T1Ž¡;ê<V/ õ* ë,%`W8d‚]ßò3kÕÕ@HLéÿ¶=‰Ð{ÎáscõjlØ¬øËZéÕèPéB!M+ê f'»RÖj¢Æ#ä¸ :îÚ>¦c}ô²Ëp÷]weþ>á„  ?ýÉ Îô_´Ð?Ð�Ù˜�;@7(]Ss^Ñtš^Y�éˆðî-¶f\¢ÿ0ûzÆpÄñaï‹�  zß(¾ºÔyxÌo­ÅIš1¿¥^÷øbËÃÕ8ËÖï/Y8Ä¹®ËïJo!_•Fú1ôâaØô1´[ÕKYz²ô
8n€�`äöÓsŽOêSÛ>ûé�§/V×Ð˜ñæØ�eHÁpP¨…ñ.èüâß·}­”N’‘‘£üÆo”ÝŸcÌTÔfÕbMG#ZcWV
±] Xd€á¸–ïßüß/¤•€šˆØ*]NAÏó%&—›™0]Gw¿›À°O³ÃËD�S…oW ãññÆ‚lâ±gës½×Í³9VÁX¹±a–­°‹ä‚£/”V!hA—S Zq—F•Šgjºy‚•€]âŒ«¦qGnýÕ¯
¶Ýrëmæ/,:Ž4ð‰pÉuƒæZ Ó¬kÖ˜“4ôíx1ûjbé À¾m¯Nª²ËNF’FúîÚWñ1,«`mG–¶×£Æ_yÑL1%P,2�Of�¥Â¯=ªæ
x~±R©¶çZ7`¢{ô�$Œ¤4ô'TôDeôÇdÌ^´lLÇúÍÝwã²Ë/Ç3Ï<ƒW_}W~ùüô'?  ˆ3ÁêÀy`E8ŽGcÃØÍXP,C�Ñ55˜Àtë›7VìyóEäp„ÜBnÌÜŒDdLé˜c…Åþ[è~ù‰1ÉD�‡Çò¶VÍn¨XØ)«›P>²3�N–Fú1òÊŸct¥Î_õKùúF™™Qibózb
$UÏIµ]²nã˜�÷›»ïÆ©§žŠÕ«Wg„ßUÓÂr™Fp�¯›—?8æÏ©4ƒ1 2NÚDS�¼”ß}ë7^qóú�WÜ�Lö…U"<ÑèïéÊN'Ý”vO*AÀÅeA%<��(J
r®ë²çÉg#�1x‡4Ò�È¶'s”@v6 ¡icv&ú™ŒÊ…–àIgœÞ[=átÍ<®`[ÛìŽ	‰D+á/–HÄ ÝÐLMÅ!«füÑž˜“òKÈ¿>ÿäòóOÞ!–»Üâ<ª%„å�E8þ…pÂF ±¾/Òjvž¸8Ìo­­È"°Sœ7PÀ0×rÀåúd±ã¬ßtÅgA˜ç]{ßÿff»!'s­€+}©f!šnLh>ÀPR-˜¿ÇxBØxÉgªr|WM#\�³¶·|EEÇoT®˜"e  %ŸV}óÆ
«ü @˜ç@éï¬×¨®n×5í **Ò¬ŒpÂ¨¦!7êšJvo/¨‹`f5®òJ\l(
ÁÊ¬€çŸ¼CfÜþ ì‹îÞuà�ùÃæZ%¢åF£Mô4§‘”IÎIÅPRCoLÁò}s-×qYŽ§5«Ï…PÓ>Ø˜áYj‚A´Ï�?¡×”;÷^`HB¢ ÀÈ&G–˜¡˜HXå¿,ÇSÂ°@Öoºâ öéšJ:·üÕÑ1Ã@JÑ—5„SÓ„QOTFçˆ„}C)¼3�Ä;I¼ÝÇÛ½qlë1Ž¼òË]C5Å,J ô&æ¹#¯=…Î°„îˆùÓWÐW0”T1”T•´t{v½âyu¯Ëg;‹äwìµË,gÉÈ0Ã‹›YŽ§Ã¯?F-¿ÞPåŒPJÈË±ãÝ+ðHDÁHJGoLÉ(–œù�[àm» Ö�ô!Â§*+z „ÁùjñÞ+6ÿ9âì(-°· h’5"  Éæ%kÆQ]`¥úêšv'ÕÕ‚”®çŸ¼Ca®FÙyKÀÃ)³lOTÎõÛ½qìèKbÏP
û‡%Sh£2**Â’fŽQ×Hš�Žv ŽØ5{ŽêZN|ˆ0ì{Þ6Ýkëý	ÅË–4$TôÆUtGåŒ²ÈVåCkÐ…÷ÌiÄ¬z_Ñ�‡™'�›6ÌˆžÂhçº®Ôgªü‚Añïº¦’ØÎç3|@vrÐØy€‰}UƒâH^û/ ð×5ãƒßúZWžRÑñxomç}¹Àô',�¶öÙ˜¹tMÅçÈ:tŠõ¸´[Ø%Íèæ 2PÈa3t?Ê-€Î7ž€ã	\ccŸ©ñW€ÜñÆKÏon½À™ëchª‘Œ1zt‰ð”pfØ¢$Ë�Ãˆ§dRTS '#�Fúc„å¿Hóª«Ûc¶ßøçÏŸt=+ˆ`yÄ ãòÁç!† êá­k6Çµ…êà©oü5Ðò¾Ž "ÏÂÃ3àY\Þ
À1³ëýL­Ï�ƒ½ƒ‘
/ÖÌlGªg4<ÉyC9ÂËp\ËÂ«o¿p÷>öÇb÷è¤ùïçŸ¼ó‚D×žž¶àëf@OÅ3ÊD��õlKˆ	ÇƒêöåÊq™ Ì�F)²òìB>ËOK)qL1 p4§+PLÖ °¬»ægcn	¦F2Ê•°6žvú˜È¿ñæ$•"EB †  73¸ŽæP`¦ü—��dd¸Ô¾Œ'pM¢kÏ™áÁÞ&_]3M5¢½�Lrà=û¡�ô ÒwÑ‘!hÑH#ýk„å¿og… –°Üq™š@GööR¹q¼×,ò©›1¾æÙÍY†À¬%Ð<žŒ†wqLú‡@àF»À\–ÏnÆÁÁ˜qh0^p-Œà�PÛ
e¸Û<÷t'¡ì˜~âà¶« U iëêë ô‘ð[Ï£víy Ò‚7t9FôØ¾×�â@‘~rž†Î~Fsœb5»(PºOàPRE“Ïì(ëƒ	5óÞ9ï=ÍkÎÂ¾·K7Íæ:XÑê	dÜŸsÎ>kBûÅ…]V¥fÐýa¹ÕUè)“p:‡lº &i�4QÙÀ³�=¤Ã~Ï?yGÉ÷ÉÈ0¹ú…ï}þ·P%$ú—p–ã©®©ý éèaÓzÂº	ÃF¨¡'Nè¤†€“6|ä�bçñü“wÈ æYäÚß_ºßK•””†ÃMõ†™A=ŠV€.PÑ™êÞ×›£{_Ïé¼ém›�ÆùËQ¿x-j_]3 €#*|"�Àf,Ëx§/Z0�ˆ÷×Á�â™•ŸórúüBNN�’+®\©ñWæ9599ÕõÜmLÁÜ%] Ã0–ÉA–²È=KIØ)‡á¤9¸ÛÆ%HH2|3Á7s‘yL)•ÓâŒj*”<²Ó*†ÚpÒº1uLÕiûúbÑ;¹NÈú !,÷)ªk·òÞ ÎýùX×nja».¢S	«ew\Ö�TtÄ£À¯yéû_@÷Öç>’Íü;ÀŸ| Èø~ ;òºt3œÐI)í<é”÷§wJÁx‚µP¥ÅÔÐS]_BVƒ+˜3ÛæcÆ{6aÆ{6"8Çd²]ƒ�‹ÍXšAq wÄ¶ò0Õ³7#ô†œÌ©4¤ø³+mA˜3A�GxoµkÏa8ˆõm`8¾dCwKGÑ×jC�qw®~‘Í‰�kè�$¡ÐQËW   wç�š¬'€óNZ9î•QƒÇÑ~ËZ¼¶ÛÚ9„í½‰œm‘¤r9Gã`fÇšj$UƒñLP×'°ÆˆÇd	Õ@2Í¾óÓ-Ó=vx7º·>ÿ\…ÂÂ	_ ºöSÂro�˜#àH¦‘Nu-gULÒ+ðé ]¼EX~@×&ºö®ßÝµçÌÝÞÒämœ‰ëÎFÛº³!Íè GTÔxøL�A0 `ç‘Ü‡ØÕ8É#»  3è#cˆÞK”V Ôø+€}j"ÒaÄ‡ÁøjÍ:ø2×EuÕÑ”ãÉ@­‡Ï<{€iId1pž ÔèÇcÑ¼¹X¶xá¸‡ÏýÿRŸ“=åÈBTRúaùeTW·ÀûðV-˜ƒf¿0)åÀ1IC"=ˆ#¥šB_jŠo|¨ÑÎÝHôìGïþ]Hv½©ï Õ5•°OŠÅ|îD˜
¢ºv@Wæ�…§_Š¶Õ§Ï3–"H©:¶uæ´,WcC>€j*¤�ÎÌks—�\óÌ�„Ë|úM ½Æ7ë8x;Ž¨ëò–e.Ô¶ä4ÉÆd[ uf~Déá …@öpP»q\c�‡gÐr•ßO`2ç��[·ô=Ô;¸’#¢§‹¦ÙòTÿÄfÍD³_¨êÍtb¾gCN&=ô6½0r`†Ž@ªg_±6MÄ4Ýµ ô˜ðg!­·¸�pÂÌØ�íŸ|åç¯_¶ýžÆŽùg\ŽŽ÷_fx\"Sëá±jV=vÈD	²ù Âñà<�7ÐoB	2 @Èã ôyð¼ÇÃPe°./Æ
E30öw�CÒM[|…ãÁ*ï³ V¢YéñàåáÔ/)°«© #C‡¸´9à—ÂýKc'Çc¾G»ö!Ö¹‘î9�<mÐà•´�þ*a¸'žò‘w¦ƒo>�‘NDºÀRxðÌí÷ÜôÅ=�Þõ�%|í'_`ÔúÜÌ’ö¦^@¨m5{t5',˜:ðú(£ Öo¼ü©Ÿý-Ub(©ÌÊNµâf~±ÙƒÓÇ¢Ñ—-Œn µ¶ûj ¥}H9“Èd€c�™>äT18M*V•´‚D Y3†ž¹ñ‚pÚF!ûºBé+i‚g£Jæ;)1*+Â¼	J÷–}ž0ìNð®�£´é£S]�6¾ùQÓGÿ«Yöúmÿ~íîÇ~»ùø+¾‰™ËÖ`Ns S	–l€2ÜmþLsá—ûˆ´BÞ C�•	”Î4Ÿ“‰™8™(§,¥  £\-€bÜ�]‡e�ÁÀÌ €7¬ˆ÷`fÝ£3&Á|ßàMlÈ[„åÞ¢šrÔT(V3E¨Çùj"í"|,Ù{ð¦çþûcÿÕ°æœ¬ÛüuÌhnAwTï¯ƒ�¡¤ÀûB�‡S º>ÏáGìÐaÈIPÃú.Ç7q20Ù£�QÅ g¥=sŒ–³Ggúþq%¬¾D~C>$ÍèÒ
€°ÜAª«™lÀýÃ ©bó}øÐ®rýÔöa4ÄVh¾SóªMþ˜èd¤Á¹Co<qÒŸ_~ø§ë®¾yÅ’OEwT†X×ŠTÏ>³©%ËƒZÖoÚ,–w»Ì,SCŠƒÓÛ¼ŸŽÐ …¬QÈ™ü¡`Y<cŽL³”‚;=þKÕ)º†aÄ†ÐÓß�7ß~oíDb¨ŒCÂ]ÿËÙ§^ü3 ­ ¨¡í€H·92œGØ™ï‰®=¥Ë|…°ìÎcæûÑC•_X¿ióÚ~|Õ¿ŒìûÄõk>r  ;ŠLV +º¡%Uô,XÝ†'ïØ_æ�C Ž:…>�¦b‰\¡ù¯QM£�­85tˆÁ_~ûküäûßÅ‘Ã�6G"[ApãÜf$#Ã�÷ÿØ¼V  ·ƒê*ý‡1°óU§æ;Ž™ïcÇ†ëïõËÊRCN6ò¡Æ¹Ztp €0™t±èžWnê~àG/u|îæ¹‚Ëó~ƒ0ýZ*þfË;¯tMé™>îï<ôëÿëïÜûËs®úïu)…`8Pg* —Z2ŠTÏžF˜>þQU×1ÔuÑ×Æ‚^9Õ§ãNÝÏ ãÜËðËMçã¡_ý ÿ{÷o²¬qò}€^
ä×Ç H›sHg’Á> ;	Ë¿Fm7a¸éT×c’í­çe]`þêkA��ÃÔ•Û?²û•ž9ñðœ·†�<ÝrúÇstš¶,·�hÊß)ùØ¾_\Yuad<ÁÚºE«oY÷Éë/TDû»¡F�êÙ]×Nì~àG/•>‚™àm›ßÂup5Îï�-BrÞø€ýmq»DÔ‡J�C/…„$£¿ûú½ÉƒÛ°éÛÝ×/²hôU7>V4zyø]åó	¼<|£Ñ9ÃC~ Üò]ôôôP]×þ(½)ÿ}�)â¸Ô¸ @˜wŠ™ï‰sÌ|/�õ›6‹+6žCXîÃïüè“?4Tùõð[×2V_bzOÇ¡Öï†Ï-¢ÖE ¹ÍtÑ “"éŽ´üîß¯Ü²úóß^ÑÒZ�ž¨ŒDÜ¬Ù`8n!€…à…‹D^À¢«oß†ù+á]Øù?—<?¦“Îƒ‘Œ¼þÄÅÙúÌç~ïÏ×K5ÍP£faO*6þ˜$¨ºŽápjd ±=¯€åK'Mæ`Òrp;ÌÊõ¹û‰^?.¼ô2œpÆEøÙ¯ï";¾ã{ñCo·ôÚìýFU‹jNÿnþwÌ|¯§üð¹ý‡||¸ŒM¯ò³þéøÍ_5XqãâùsÑQëF¨¦õ¾Òi¯ú¼YøÃMßXñÅ:®�ÙAV3ÄUôô¢ �#zGb£
AW¾Ò~Á—Ùyÿ�?[­k¢ºzÃk�ÿ©ÿ¸Ó/þ©h€–ˆB=Š@$–€.'AuÒH?¼�3Kî?]¦bqŒóV`ÅÎy ¡¢yÍYh^s¶={Í¾gþÔ¾0Ôv™e¹OìÜ¥ ,¼úö	ÁW»�’�ØÑ\ãGëqg¡-uð{Ýo½‚3VÌv|L–e°ñ’Ïd„0Ã@--�6`žI¤T;õb×á>tö‡;øÖòõ›6‹��à�=óÖÔNøÑx­« hÆÆKj¥-04†œ*:ÉxºÂŽ ´ß�Mê��°ËOAÃòS.êŠ<ˆ'ï¸8¦ Æ�Å_¿w=U’ßbX.Ó6Fà8tÌiÇq³š3ùà‹>=îþ×Ü®Z²FÍÎ>:…bÐÌ¬�šÚœ%ë.ý<jNè'?5ÔÍ³8~^ŽŸ×†”ªãÛOßºîù§îz|Án>™! tå¢E×Üþlc{Ç—Ÿ½êäÊæRg¡ëá[~X°Öàu?GïÑÃÿÉÕä²½-¸¦IÀíð<JïuG#0Žn³~?¦ ÆˆŽÏÝ<—÷…¾Mtå"Âš·Qà8,]8Kf6´U8›>ÿïè�)HiÔqïE‘%¶‰ž�›g!rž�ó,”‘>\ÿË{On>nÙ²{»Á°Ü)ƒ]‡Þ\tí�?jòn(_Ìc��?üÄ/]{ç¢©¾ÿN‘ÝOÐiÒdŽ-¯àÌ(V+`¥ågƒ¥ša<ø«]ÖßÇÀ¡ö¾ó5qþš‹€Ò‚¯hÂ’†˜¬CuÕ¡;*çtê+’ª‘3<ÓÃ3¹9xx+ÏºëN6‡[|þ¬Õ88œUó•¾xô²ÅWýúº�?üÄ/ÆòÙ»nºâª×ßê~àGU¿¯Z2
e¸òP7ÔØ09C5Wî°‹�!ú!x|àÝ>x›çÀÝ8b¨ÉÑ±©ÃiPÜ4à *ñÿ‹Y ½±ÂÕß ìÖìÈÝ»N8ËP:>wó\+øÏ?ïYøåUXÐÞ‚•K”~ÆeÃ)É¼•¾\Ç5-Ë  Ža�37‚Ž §_ü1Èš1íÎ®uãóg­ÆÛ»ñÐëûÑ;«#ü|ÑWï>­ÉëûôX¬'ï±ºMA5»ëP]ƒ¡iÈVTW?¸ñ½¯Aé?P2“´Ø+¼7ˆ†ù+P·h5ZÖžUT!X}À/­�Š4`;8íÉÁZÔÿ?.ìjÄü-çýS}¡cÅúM›ÅŸ5Î_å›×¶�²ˆ¬¥+/»ù†Âò7šSkª‡…Wß~!a˜_njçò'ªkCíá·±þüÓrö‹ËfÛp©HµªSð¬ùZ2ÝMXÓ�¢3ðx–dLAž!™^"K rÄV1HÅ�a	^‘E£—Ï(‚%³[Ñ1£�½þžÞ~ ÁE}Ñð²Å_¿÷SÕ
æ‚ =-xù&xlÏ«xöž‚D³3ÛÑÖÚŠÚ:³Ò®¶Öü?TÓ€ðˆIäc÷þNÚ»›ª‰é~óYt¿ù,ÞþÃ�é‚Ó.&s?xÑE5³ZM…1UH°¡¥Ø	ÃÅMóßåÐJ,•#p$Rh„“òcÙ
àÍ‹¯ŸX8û”´ Ï¥ Ç1„Ì[úéóâ…‘ƒ pá„ÿÍôâ']{ç†ù
 xg,Äi7þns×_oÅÝƒS/»K hzãjÁŠŸI3LW *�­¿�A¡*ÈêðÊ3�…—gàØœÕ !ë8 ëðŠ,šýx†@äœ»fæÏnÇoŸz‰xla|×ó—˜ @¶ æ@Ô€®ÂÐÔL_ÀDçÛè~ä ¦ÀoØp
ÞwÚiX»v-<žÂ¦ n·��…Ã4UI&{ìÇ–-[pï}÷á‘‡&;ý-$YÆÒÍ7@ÑP]Õ5ÈiâÒß^¼˜qºä 8�ÿóÿÍÀ@¢�ó }]¯dÿ=­À›_?‡aù&ß¼¶…CÎ¦ Ç�ÒV†arªÙ}Eotã»OþÁ|={Ç8°~ÓfqðøÓïf.²¶uÌž…å3€µk±óÑß`û3AûÚ3mo¶…°¤!"é™Î¬fGá~a¥$³Z
¼ùYí¿ÞcPD$É<îŒ  ŸÈåÄ…²Ž}r
>u3÷`Q£×ž"n}àIüí�Ÿ¼³~Ófq¿?´ª|vŸs¤3Eû 4)#}`E/O TW¡Œ˜}gÌlÇÝwÝ	 ðz½¶Â_
¼KÄâÅ‹±xñb|ìcÃu×Ý€o}ëF1ëZT)‘éi�8¸� 5Ë‹o( ‘%ãöÿF<èù®Û”(€bæ»­ ;˜S¨©*þß]?´þüKþ Ž±`Ãõ÷‡úbá‚Lxïøã`Vóèè¬ùïû0¢‰¢Â–4%Ô‚fªA3ÂO)Ð55§WÎ=àxpÜè×ÄeB��+`Š‡S:†S:‚.A›ó@ÄUÄ$m!x† èbÁ| 9glð_VœZ¸öÎíºéŠ«Æ{ÿ «®€ü ›¥ÃoA¬ŸªkÐ£ÍÏÛZ[Çñ	…˜7ovæ÷„$CÖ(´ø";Í‰Ñ®šF„Ž;©èû§CÐí�ý/ÿ?8RHƒåûÿÀ$( §æûxæ‘þâ¥G°#ÖŒÎà×9g„?+¶Ÿ/ü²¦£sD‚Fpš–CJš�¾¸jÛ‹�*)š‚Þ(SLM7 é@JE¦G�›gpqhŒæ¯›V�V $�bß`
í5.¸�ö¾øný¿GN> {pÿë‡ à+Ko|øÈŽëÏþÞ¸nb„ånb®�Fú‰;ÜVô€°Ü¤tÿIÄcÐ’QJ
‘7Ì‰Ñ³Nþ`I÷«šñÂ)(Ñsðp¤Päûÿ@ÀxÌ÷ñ ‹Ñï?û€yhBn¯é¿~Óf1[øŽÃñË— ¥f´N*¡èèÌbX5j’>‘Ã@Bµ�ÛS%…”$çaÕê€›RM÷BÕuD5|Ú„Œ¤G—Õ{r­…Î	F2‚›ÿ0jBAXc0ïýŒøðw_õëøXÃ„9×­«Ûu�;lŽïÞ!ÔFJäLšªIV F0òÊC�FúÁ{ƒXpÆeEßã4ñf"Á1Î{ æçÿ[ˆ«¶ñí7?[ðy•ž`µÍ÷ñâ¦?Üžn+F¶:RiŸtåÏþˆ¤Ù÷Ò×(ºÃQLî-µüÌkYm°M¢JÍd«Yí±ÇCÍVX„åÍŸ<· 0Õ JéJé¨s³E ÝQ~‘ËiøZ[W�UBç¾w9Â*ƒ§· á…Ÿ/þú½;ª ÿ¯TS.T|÷Kð/^_v h5 F?¸/? XvÉU€'TtqÌÂpÚI˜#´h¢Ðþ¡BÿŸã¸ûíÂã%?m2Ì÷ñàí�nÜÖùŠu_oüÑµwþ0›ð;þ¸Ž„?©hè�šÇ'•HÀPŠ�Å¶VACŠ—<¯Q]>úÅ*0GO–7‡yºr­‰¡”Ž¨¬¡Ö# äbÁ0ª�Ca­!·ùÕ¥ù‹¯ùþË7,E2ÇËû@UéþŽÏÝ¼f¼¥Æé±èŸ¥¿Mtíá0.ßxéä3?¸½ÿœ kÎAÛ)•|Ït  �šÿ¥Â{m€¢²Û×ö(ë7m±rMÊï÷çÜ‘©¿=¹øÉw§OŒy.]Í8ft|îæ¹T•¿‚ôj»xþÜŸ?¡èe… 4M«ëH&ì…ÚÐTr
Z"Àâ±Â´R@2Š¸ïòBGK]Uƒ /m¶„Œ5‘tø<c® Jàô5è¼÷YôŽÄêx�ï6 ÆýeQú;Ò
J¿?ôxoù&¡ã�îG×Ÿn¢º¦’À¼ã±æ×—}�Ç!ù6Q¨ÄüQ ±ôTé|Dø‹Ýþ¶êæù'ï�å—v½¬©Ó·�ãÛÝx¸k‡yÿ/ã=Þ¾_\¹øùßÿA—Sh®ñcQûh²ˆ¬åúüò…0GiÅ†í«Î´DÊpOFø�Ñ™xºœ2Ó`Gz!�4p©ž}HõìƒÜÊp7”án³A§Ï1¡	ËA’Ä"#‚,ç*ª¤jàÐH
IE‡7½Â‰ª9óâ†j¦{¬‡gð‰3×š÷–åNY|Õ¯?W•/�Ò›Ëß h—©jAMD k*	,\‹“¿ú0e­Ù[oj—¸j˜ÿ†ŸSút±ÌÍ¢ö†aÐ{£/ïÂtEfõþb¨òÕ8æà¶g¯9ø›¢‹fŒŽ¢Öt�#Î…ß2ë³+Ït9y¨;Gð¤ãá}Hõìƒ2Ü52 ]J€jrÎ Mª«0ä¤yüØ”‘^È‡ ÷‚)8¦¥²yÕ H¨Hd…ó•@oLÉÓì¨sãkMo�æªj}oTWo !�9‹bB1çÔáä«RVø�é‘ÇŸý·k ÐåL)ú#Åö/zÕüÌº?		±·Lõ})@,£™ÕŸÿg<ÇZzãÃ_�ñÁkž­YyÚ‹T×~#u¥îü×Ï`¤ß¬yïŽ)�‘Ë	¿=]ƒ®FrÂ^†œ„2Ü©¿³@)ä£ÔD]ª«Ð“QÈ��‡ºs&ìR]ÅÐÐPÆá
ž%èŽÊIŽ†I{bJNžBvùèŽŸƒ€Áîª*!ÁÑ“£¿!7Võ˜yðÍ:íÿttÎYk¯©V •$ÿ”2ÿíÊ5M¹§Ø±Šª’•÷Ýxàµ÷~i‹Ò5´6é÷À¿j>ôÁ‰Ý8Åo>•¶ÕÈÖñ¬þ§üð¹ƒ]‡¾˜w<óŽÇêÍÿ‚V—Ž·¶mÅsÿ«ÏßŒ„šû¥¨:u$üTS¡FMW ›é×Ñ¡743UÕPe³`ÅÐ3
ƒ°/‚0,Ã€°¼Iþq"˜¬H€¡¤ t‚óÀzC`8ó3“‰8MAcý¨UÓWÁ0‚.:%èŽ*˜2¹ƒ”ªc ¡¢ÁËcçlÿMZ¿æÌŽÏþø�jõ$™È\ †Í„+™‚g(Ü<)ÿŸjÿßïpõ9RÔügÐ6ûïé§¾¸¶³ØñJ:ºnÜÄ±ì½©]fh}:(MUqÛó�XW÷m8›šd‹þÎ}?f²jùç´ÏÏ2XÛ2IEÇ¡°žÑàFoÓH<÷&—þl?�j*”<K€ê*ôTºœÃ	04J¸z"’öóMmÎºý ËCÖƒ4‚õ˜‘	†ãÁÀq£ -…–ŒšÛ½fM…rGQ
dªÝº£2\�È±PušzÀä†û{ñûïü3®úô'°Ÿm¼uk*ƒâ .žÒ`°`ÀÍ³ikhTˆ¦ƒÿt;Ë	)•ü³«ß&âDéÿ–:^Ip�7þà�R�!Äm)�º3V#õv'¦
�Ü‰A% }ë7^ñÇ±Æý^}û…Ù™~sÚ3É3†1ZH¡I‡‡g��äœ|ª©Ž„_�t£Ñâ#Ð’³HeàpÙRØlðÞ ÄúpÏ\ÂòÐapÞPFà¤ÏA†Pk¦ÚJª�Áp-u£ì{çˆ„9µnp,“‰¸x<KP×Ü‚ïÝv àPï¶Þý,‚‹:>wóÜjXÔÐã=ÆX�Ru¤€«Àiã�‰B@tî~]öçÚ•Ø–jÆÈ¡C)u¼’
àù'ï�S'é!�nÆÆS»c@ÓeïCì™©Äûçg¬hùÍXãþë7m�ÿ²þöúühªmGSr›m f^ùp8šIÄ -YÈdç¿–C‰š#¤YÑC•¡FÍ•]ï qp;Õ55³üÔ^,ô6 èñ¡‰5É«>=…Îè zå•ÔDj"+œæ[¸¾ÙË Kqð¾˜ô N]NA�A¨1{½Jª�þH�Aóu�šM#[¦ù?”Ô0¯^ Ï$U)E‡[`1«¹óZë±·{¼7ðe W�ÿ›$# Å@$>þC�ÙVAƒ—‡fÐ)³j®þ>�)šû¿³¿Ðü×ÁÜ]®oCÙ¸C ­é&­³?“A‘ÚuÝ?­Ÿ?É·MºKpî†3�g€¿öïù£1ÆnÅCË7|<ÝE °pVK¦®Þ0Äeäg=Xí¸­Œ=«Ä4j¤¸ð[¯ër4Cø­ç­P©¼8·y	6úf¡Ã[Ø_bƒÓ¼‹è2:µ(^9Œ�©!ª&"däõÇß½5'œÚ8¬è†PÛ
ÂrÐ¥8”‘ÞŒH¤d„9!¯Ù#,i¨õp¹8ƒ”ªƒO»EYÏ¦\¸j¾Ó= —­ß´ùkãMºb8>f¨2”¬Â D"�††ÛýS)gýü*…•ü“Ttð,K&· ò¯Æm/®Šf`g¡A“”»Ë³¬X~Ïu/½vâ—Bæd>°k‡þë·˜õ��˜4‰ÖÀÙó—ãìùËaÆŸÜÙuà—+ï»±¢P%ÌU–x{}~£fqXÒ¡¹Â/ËfUYæýº
52 Â‰kÀ�â0äQL—S9Â¯'cÐ£ý�#ƒˆîÞÀœ¬tEëJòå§‚¯±ÏŒSGâ@bô8AVÄ2¶ËšÑeòŠÜ‡GûÌ¦ýÏÜƒÀÂµ-ß˜^ùÍÎ8ùJ`$–‚Àsð\ƒ¤¢ga„SZ†e§4Ôyxð,ÁÊ³!<ºŠ¦Õ¬Øxž¼£äxð²ß¥� Ð7<1ù N7?ú]«:…
@Ò4¸ÒÍV&Ú*:ú˜±ÿbá¿½CR&|k�€îú«/w\GªÇ ôæüm4)ãàu·!ùÖ!4|ìt°õcŸÚ20SÃ0Ì×k–tì?øo·?¹ÿºÛ6o¸þþP¹÷-¼úö³Wÿö–†œÕ8YFQ¥\íj•³RM6_ŠCÍvª«PÂ}™¿õdòp’·e„©¿�~ä›äºË>‡Ú“–Á¿düKæÀ=Üóg€õ›fzg‚œîZÔó¹µòAVÄû<í¸®ýR/x ÑÝ[0ô÷ÿK}Ö9Hñ—%žRàX¸8’F—MkF5(¢Y³!­ßy–à½‹Í~ú„aNÁ8qÒ)îg9žª‰"‘ÑóÒ´É"ZŒT“4Š¤bYiÆ8˜æà8šú 5žâáÌ7º
S*RŠ~‹“ã:R _=ã}¿¦”ÚÚ`ý¿{ûòGº|#ü–MÈ�*B˜�,ËÞ~'¢#ÿíößï¿î¶Íë7m¶ÿ’8¸í*iàt9�ãr|§«~l^�ešN €5ÌCJ yp+â»· Ño©o_�¾ô-ÌŸ3Ÿëÿq<Žçá™ÙÖïA½èÍ¼VL Àˆ¡PÀ´*]{0øÜïM¡�åº  À»Ü0rVÐpjô÷xVÇ¡ìîÅkÚ3–Rñ’:‡xþÉ;d]Sû³½—¨RùUÝjæ¤$œgHÙì;U7ATÒ hÎ:9;EÈ¡ð•“J÷¡_:9®#ðÌ�„S*öºòÒnrðÓ?_ëGÝÕçÃ½¤½ª7ªÂ\Â²ìíw�´±ÇR–e@8af|ß'Ç¼‰è®—�ŒãpO?Âá¨ºýêŸHå>tÙÍ, 3†o1ü†¦A‰@KFAUJï>Dß|,3`µ^ðâçù*nøø—
ßRg?Ü¼˜£ Sd+�Wä>¤‰Ä}º®Ÿ –èÚƒ‘7‡.%`(æù1CIf|Î¡,¡O*æ| éÒâtßÂ,2táÓ`¦®ãs7Ïÿ—Å¼ {÷ÌlR”*MV¥²»d›ÿN i¦uT«€cœ‡þjÜlQòïÍîBÕ	ù—9§'hkºI=Ôw)Rú§taÏ~ŒÆoBã§Î„oÍBÿeË”å¤Ë“/aY\r'¢ ÿvûSGžzmèŠ�§Ð·s/À»àn��={÷‚óÕ€j‡ Kq¸\nPo\¢ †rÒiíV=9ê¨ñ0�oAêÕèÉ¤‘~°Oÿß¦‹Èæ•i~�•Øú boìMšŸåæEÔ”G]‘ g’xû¤<Ú·› „åþ‡êÚ_­Ê»èî-p·-€—á˜äš–ˆBÔ�cMÂOÒŒL\B5LÇÇ³ÉÀ¨dò‡æ?zGbàÜ¾•ït`J÷8ùà¡} Ì6æ¥\ E–Á»JÏõM+EI”îj=c ªê£�¬&­•¢’Õßjã–�˜¤a÷@¡a‰F¿ïôØŽÏbù=×½ôÚ{¿´ÀÚRûõÿîI„ŸÝŠYßü(Ú®<ñ­ûynÇ”'Âlœ¹i5žÂjÄb1ú\ïr¤-…WºßÆ®#lFÐeO „‘Ý¦Y¯É™¬;=Ý_Hççk*”Þ}P%“üÓ"ýÐ¢Ðj"‚¥þfœµé"l^¹~¿pPPÉÖ ÷ÁÊ»°PL	d¯þ'møè]Ï?y‡™jr@7GÞxÞöã2¹€)\Àü=&ë£
@Ñ3¦¦¤ê20›`Z4£½#1‹‚í ÀÞ={3›ò™²‘�%xQšk²\ CNÒR÷Ûì°<þô_I£�4<KÀ³ÎIC§¹¥Vÿ×m|út%ÓŸ*jbe–ÛÏ²êN?uWŸ�¶ÓG €ßï'gûÍÆ�Ÿi7³ß	à`x;jÂØçp¨'ŠÁtcI«�•<�+”z|z2]1Ú¦Ú –{qÜªEØ´è,iÈô»sôT°õèƒQDž¶ÿþ\œ d)€ˆ&å¬þÙ¡9Æ¸ÆHF.”FúýÉ#»áïX	¤€–Œi•´L`v³ì¶æ	EG]zŸÕ´“0mãÿ&È[ ÅÖwF‰R¡@'L¡k*¡J
D°/
T°;A%VAÈÍ9ý[ýÍÀŽ¾ÂÌ¿hJþ¯rÇÌFEwaÍ–ŸÞ÷Ú{¿´…€¬u²ÿÐã¯bø…íhûô9h¸d|+:¦•"ÈÜžÇ’†V,ihÅÙ P Ð–®AJ’èa)F à`xvÁ{çs>¨>„ùõÅà^ÒŽÔÛ�züÕ¢ûBP/z3VÀ-=¯¦W²5¿ª9Î�Ü
Ðkâ{^†oöqk†j*4Ýl\¢ªAÁ3ªN¡éK
™Zhò¥CkÄ8Á¸ý/i7éÀ�˜3ÇŒ4kšVÐñp–PmL¥EÁ×ÛO¹«« ²QÊ*àçU¥ÞèŠÛ…þÞpúËFÅwÁ©`�&eùÑÑÿ‡gÐúùóP³q%|+:�:Ø‹øË»§4­¸ìÍáyøyž,1Í÷ì½ªðoX†‘'^/ºòÛáõx^9–ã)%ÌíâÞ/üÑPåkR]ïPCÓˆ.§Àq¦Mäà1ýeYÕÁ§ÙpƒZÎ²6JÖÖ¥‹Š(œÍã*SIa€ŽW_ß–Q Š¢Ø* 'ð`9žêšJñBõ…ûDfRºÿØY!—óÕ?»}[6ÍÀ›Ý6ÕÔ”:öý-Tì­ÙòÓû(¥×+]C8xÝmØõÉïaä©7ážÝŒ†K6 åë—À¿aÙ¤çL°õø7,CßÝO8~' ¢Iøé³}¿®iw«ˆ|ïÉ—¾j	ƒÈ!4³C›ŠjRý<K QóF}ÿì…¦IHƒaêQ�çàÕ—_Ìl)E:	¶´´ PFzm_+ù7HéIÐÇ@ÓËÏ(,µúoïML’" ûüÄŠ²™ù“šÕãk•XÙHí:Œƒ×Ý†¾E3ÑtÙûP³qeæçh°
ªÿ†eÐ"8ô_¿Í°ýNqKÏ«™‚¨´¯o»_šØ C‹‡˜µ
òP7æ-^Šµµ<êjB¨­«g²gâ©:ÅðÐ ¤p±á.ŠA\Ü�9óTý>–}žêÚæ×wìÌl+E:‰´µ¶âÈáN(‘Á‚×Ü<;eµÿ!gŽ‚×œév³J­þ¯¶qŸ)-ßóÌcR k¶üô¾üôàJa)‚î¶:4^´¡óÖÁ=»îÙÍP%òî#Hí>ò®SþËÀ×úqäÇ*`ú�àÁ¾·3¦¿®ëK›Ñ%@â EbÿÆâ´s.À	ûbÉ!˜<KÐÔØ Ža°pÎL,ð×ÇÇï~qR‹ ëM |i!tÂ<
˜-¼¶¼±kW-C"‘@MM�­à$0oþ<lÙòä¡®‚×êÜSSùçâH¦æŸ!Zšo�j€cIN/ÀRÌÿ]ñª­þÀ8æŒÇ
È†Ò5„#?ú#ºn}µ'-CíßßŠð+:à[Ñ‘£”þð´"+�Ã2¸æ4càöÇK}¥°#Ü�ÿì|– º¦ý  ¡RËñô}ç^HÎýÈ'?©æôœ,³”cˆ�‡7«[ýÎ=óýàÎ9o<z¾ækðÎ[]•IÌæ² +ž~ü¬]ef“&“É£Ÿ'DàìY  yðHÎv'™…z/¦H�¦SD4gr�"NBÑñj—­ï?¦Õg£ß×Þû¥—œF*�{ÑLÔ�±ž3VÁÌ}R{!è…6™öÖ�{I;Üg€zÇ%ø p8>ŒOîú“iúæ¹õ/?½”ð1ž`­‘ŠÝÏ{ü'ã‡ÿ‹ùïY Iéè�)I*Kz&P~‘Å{fø13(¢ÁË££Î…žƒ{ñþ3ÎÄ‘Ã‡·Ž?w¼ÃXËß@uõzÞÄã= ÀœX,ØÚÔ\Ò¸ýöÛññ�ÞÆ™Xqý™íÍ~¡¢œjÁ#°hõ;ãjÜ,¿ïv¼ü‡_¢­µüŒÅXÑšæ"én@SÆ_ŸihB@ßxðãË�ó½Ï…m»ô?×©‡ú^$8ÀR¾5ážÝ\ðz¶B˜‚%ôdv”×÷£û/§ÊK»ÇuƒRªŒËvÜ‹© ØÇx‚kJ™þ„fRMyŠåø¹_»ëI2Þ<
Ëè‘ i¹”µò[D  ¼Ù:ØRsjÝàY�!XÕæÃ™k±oß>,]ý^H#ý}„åO§º:æ’PÂòË¨®n€o~ózœ~º™8cÆ[7 >TS°0dã™gžÁ©§ž
 8ñ/€nðAGÝØ[°�í5.¢;zŽÛ^zßûæÕ™ú‘,Ä@˜7Vmêš;žêxÿe/T’ø“�qKîó'é>�N.ïqœ@h«Cè”ð7¾Û®ª$Cë�I µÛ4'J1°õ�¡ŒÀ¢ˆø‹;{f;†_Ø^1¹g‡”*ã³»°f–6Ó,¿s@W|øß~Š5ï;Û{Á×t‰Dƒ±$Y)èT”s}¢.QÀq³ZÐÁ³³B"Ö´Ðêçñìã�àüóÏ(%Ø cíÚuøö·Í>„µµµ¶n  Ìš5«è�úûûÑÔdF)WþË=ðÌX0e«ƒ—wTòkPŠ¶ ˜“ êÃÿüËW°ëÅ¿ [O`Ó8ïqÆ­ Þ¼øú9ú‘á·!“®^Ý‹fÂ¿j><ÇÍ‚kN³­…��D$
f$	=b&Ò¨Ã¦?¥¯IçÌX9_kæ°A/¸æð.1‡ŸèßòU·$ÕzyÂcxñ¬²MP	¹”~oî¢¥øÄÍÁÛé>q’f «o ‰heõ÷Þ@l:_ Ù/à’å�XÔhfÖ{x|ú#Ä#?€| ×Žãr÷è €Ûn»sæÌ—0³}ŽîÄœËnDûIçMÉêïâZbQß?nžA{�«`»ªSüúGßÅc·} ä#fšwõ0n•¸ò¾¼ºîÊ›!×UóÄœ µëp“N<"\í�f)m} žãf�¯õƒÌn€70ÍÆ`åù–â�ôf"ÉÃ}ù,~Uý Ãña\µç!Ëìw&ü @éç`åY—f„?�£³·ßv"¯�2«5Çƒp"ø@„Ú–Œð GÌ¹s�A{È¯@ð¹Ï~6­ è§×oÚü�1‘‚„|”vX>ñ·¿áÓŸú‰¼^/<žÂòçráÀeË–âÈáNÄnGÓªæWã¥ˆ¿|XmÙòÁ³â)W`¡þæ†_(‘�çÇË¹d£*6ÑUžØþ(øèxÂ‚Õ MÊJ!Ä#‚¯ñ�õ{ ‡<Ôír|;)I¢l8I @�%¡ta²±#Ü�kö>2ëçÅ9~Æ¬5’‘ ÐÚO `
ÿ¡®îÌ>Z|áíÏ"¾çe¤ºÞÉéG˜–ã©wö2â[¸'¼ï<,oY ØÖGÈÅ!äöbÝºuÖîþžùí qéHÂdo»÷OÆ%_Œ`0ˆD"a« Ã#%y€ãW­Æ#?ŒÔá�SÂü×z8¸V	Ö¸Ù¢aÙ—;£Jª¨[ø¸®þu óß¹wäÍ¿�X­ó¬ÚªõòÚ/^\�°à?2(¥x°ïmügç³–`î#,ÿA§[ZÀ‡~ùwˆ¾öuõeÌþðögÐó—›K
}1°OO»ü*rî§®B�›E�‡Ç™ÍÊ;Á‚šˆ€°üòŠÉÀ´ËÂr<õ/YOÂÛž |ô²ËðéO}
@q2°”�M^vûË<“—iÊ³3ƒÎLÿlâ/QIÃí¯öæÔe0††¡®ƒ'Wcj30†TàbX³å§÷QÐ-Õ:Þ?RªŒí|
7îÿ›YàC˜çOpM%•&ˆú @M×ÃKòhƒ�¾Ç�±?`V×=vÛwá˜ô(ró¡T%†œ¤,ÇS"zº*9&á„™VÛÛq<q7ÏÍ½÷OÎ´
±}ÿH	>ã„•«Àr<€C»ßÏWS1š|ÎLƒR´Š‡ŸÜ.(Ê’5úDµ„¨¢  ¶­öÃÅZ‡Cq<=°ço½wíH?´äûë7^~úØ_ò 8²ÍÌ­¯Œvª;ñÂq�çú}’jöÉ³âÚ�<ö(tM%º¦>TéùRMù ?ïÂ3s	XO ÁåfPMDpï}æ\‚D"a[P*)Èà„÷¼‡ Ààë��ëº+A%¦�‡+:xwûòÆ|3†7Q¾ZÍó­j^ä/Þ~&ü™k\„�q7�üGÀáø0¾Ûó"n>ø’f¡N¥¸ ?ë<°uLèOðUªÊÜó¦oÖÚ÷#P×ˆ¤ªC•exf.Bpñ‰`ˆ’ÈX	¥àªiDÍ	gáÄOþN¿ð2ÈC€%M^ˆj
gŸ{.¢ÑHŒ°üGAg“M “øþ êV½œ¯B¨| É[a¨2ví;„ó?p6\.t]‡×ë-8OEÜ€ƒ�à¹çžA*ÆÒ³¯˜ðïÓÅ4x8É‹áX‚™!—ík)UÇß*h;æáÙ¯=uåÚñ5aÉCÕ3xÖoÚ,þH
<3‚ï¤T¿ê{wv¿™å�“;Ò…=ãŽó2¼x’¡Ê�xgúOû—[áªŸ�Á‘0†Ã¹CJÓíÂ•È t9	ªk ,Vô€ó†àné@pF†œÇŒ€€—5b^�ýÃaÜø™Kðêk¯Q]×>ZIx*�¨ô
€&ß¬ãà_¸|°lzŠolß|ñ~ ÀYgŸ�¯ýó? m	Áb9¯¾ú*V¯^ 8ïE}Ûì	üV�'ü”bv­«èêÿÐÎ¡‚)¿²$mw?tËêñ¦^çcBRøÒ‚ONEnÀt†%øî}Ûbø�­/|±Z#Î-¤•ÀÿñÞ`Ó²K®Â¼MæH¿Á‘0²ê8À¢±¾^-«gø°ûñ{ðïÿý$úÇÒýÿúM›ÅçŸºëqPãdÞDÝ‰‚õø!F»3‹í8xû×2£ÒÊå”Ê´ò–]z-V_øéjÞâ´Dxygu½�/ÚégwÙ•ybŒ.¯OÆ_1LHiÔÏw<yä˜+0ŠÃñaÜÙÿ&®Úó}}ä0±Ì}ÂrW¯ßxù—í{­ê3Ø©¡&œð{]NÎïyó™_ø3tMEãìEhnl@]m‚¿á÷z‰èáõzr~êkBh¨¯5ê‚~²¬ÙA�ã�§þ·~ó³øã½÷@MÆŸ#,÷!úß*9¯ÎÛ¾ÐK ö„³ÀyƒkF{‹˜–€¬¿Ñ]fÏƒí»÷áüœU5§‹b®ÉŸ”$„B!ÛÏÛà0^yù%$F±ôÌ�LÈ÷[ëátjtóLÑ˜TÒðÀÛ“cú[˜°$þtW ¥ÊØ>Œÿ4Ëw³°„ü|ýÆ+n®¶9Wikàë,ÇŸ£k*ñÍ:3­€»u>¼ÍsPÓØ*x!ð,UQHDÃˆöv"¾ÿMÈ‡¶aÿ®V§�‡@˜Ÿ‚*ó`&üü ×Â;k)„Ú–Ì(sÖåÍL/€Î{ÿñCo ¾ø¥«qñ‡Î`,fd»§Ýxf-^YÕ{[I¶ Ì­s�ùÿþÍ>‰æ¶EWõ	ñÏ?ûÀD=+Úi*Ó„§–Ð?‘ìÄ£}»óãíû@È¿¦'OŠàçƒñk©œ¸�êúz€®G:õ¶ú ¼BXîæÑ±f¡Y¼ ¿·m>ü‹×ƒÔ‚ËŠÏ‹íe ˜3öüä3T×TÂr<ýÕ­¿$¥\�b\@ÇâeØ¿kæœú!lüÂ·ªv?+‰÷—óû_îŒâ¹ƒ¹n†¨«žúâÚ	+{�ðÆh/¯ýâÅ,ÃÜ;‘ƒSJ)ÞŠô`Ÿ4‚'Föá¥XW‰$²uý¦+ÖN•ðÛÁTÉ6jèm ­!ë5Çv“†ãcà];«AJ¦«ýÐäªiDè=çøýBmk† ÆåƒPÓŒÞÇoC÷#æ”«¹‹–â×¿0§ÔÙ
¹Ýn46ö*ýÎoÆ×®þXŽ§þÕ¤ZIA3‚‚ã�_)¿¿;ªàwoölWRÉ+^ýêú»ªr²E0)R9™ƒJ)Ž$F°/5Œíò Þ‰”øB–¿‘êêS}-“‰láç½AÔ®=¬ÛŸã÷sÞø,e@8BM3Çƒj*ÞùÑ'�èÚ 7CÐ.*`—˜ˆDQÓÖ5©X	éW¬Ð0C~w¿Þ‹¨œ7Ž>½së×OÝ<A_Ëè½žè Ò|@*°sªkŠ�R
IS0('Ñ$ªÉÌîwbè–"èTãE…�åxÊˆžÌké±ß™î´ÙûQÂœ\mÆº"_økN8œ'>ØPÔïLk€G[êÙ‹Ý?øxæ^~û?ÉtÊçŠYW~ùüô'?€«¦ùÙ ;öÆ NK|�Ò©¾€½ß?Q!?;Lš]>>à�Þ·ðoUí\éñ^1]Áˆ¡T´Š[Â.x ïáÐTzV[n]‘Á
bæw5ÉV}„VW³¢k:Â
C¢„ðN„«aFÎûø`CN¢…ÁïGç}fŸ WM#~û­ƒ¶|€!xèÐ!tÌ›OuM%Çüz¬<ëÃcº®Z‡Z‡3ý€Ò¤ßSûÂÓ}0Ìª‰Mò³Ã¤:æcåžØ‹kö<<)çÈr<åý5„åÅŒ€3.ÑÞå�*%‘ß…×PePMÉì]…2t,/‚¸aÅµ'ª¹Ã´�Éöß‚tšo1ájšrH?Ëï/†wÿFÒi½s-Å¾ý­¢JÀÎÈ¶.úÁ_*.
¸8Ô{8ÇŒ{�X”ôÛÙ—ÀÃ»¿þÉðû³1éÌÜ«ë®ü†a*êp8>Œó·¥›žòU Ý•¼ Ã-ôÔ5gš'zf/‡Øº /‚ÝP¢C ÂŒúuz*%œKÎ]…<Ü°|F)P–‡–ˆÀ�“ö®«ÐS1NÈ„µÞ­J€°üÁ¿éšJ\5�®:¬è)+ü„!6Ì,ylCNbÏÍŸÍð¥ºÙ¹ÙVÀÂó>‹“.»ÚñuyÍùäw÷ÉFLÆ=[

}¤dòÛ¯ÿ¿õ_Ÿð/)“Þ#ù—G^~êòÙk–ò”,qúž ïÂûß2óå	óPz?€•ü0nÿ6WýŒ¯1¢Œèë«E`ápÞ X—´`¦<a9ªd¦ÇºüàüµàCM¦EÀ`À˜·�eYP |°|°œ¯†ª€ê*Äš&ðõ3`(x_Jd  š©ªœI8á!úÑÙê8Œ'XKUù^Pã3Ô0ˆ·m>‚ËßÖå¨/+üBM3Súq$�Àâ÷bäµG`¨2ººŽ ¯¿ëO:	©T*'IHÓ4(Š’S?
… (:yî¹gÞ·�ÎXw6ñ¤g$–‚‹#hñŽ…¿Ñ/ ¦ˆ›•4Ü³qÝ2ª  ÍIDATmrÞpUQŸxíÚ÷N8é—�)i’þÎ¼Åž©‰§�Nö'„àåÈ–Â ,·ÔxºÒÏ¤ªœò´/9“*Ò Ðå$¼íÇ™«>Ë›Âlè`Ý°¢¼7Þ_Þ_Fp�uûÀð"Ë�áEh‰0 €\àýuêZÁyC™é;„å!Öµ�uû–a0‚†ª@¬i‚¤ÔÐ›aèaxñEjèG/'@˜3©*=àxÀLòñu¼¬Ç1Ô�ì’ÂÏ9ó«ëjC˜½ò$t>ÿ ¥†AöîÙUÓðžã�G*•‚ àÓ35M+(Zûžãqço~‹Hx„Äú:1ïäsK~^¥‰>µ>{‚1¥êøÃöADåÜÊFY’¶{#}gzæi2¿6`Š@ç�­úÖ�õ7#š:�Rãä=ª®á™‘és¦·�åsëŽ¿H(=‡õÕ‚uûánš±~&X—¬ÛÂ°`8Œ ‚p¼ù· BKäúüœÇÎ—VŒà6÷åE€R°ž „PXÑÖåƒ.% j€°œièø@=Ñ"ý”†�a˜�SJã ^ËuMÌU_ù9@¿ÀÇ{ƒ¨[õ>¸šç‚÷×€÷�~µvÂ bÝÇÂrsy]pÕ4"Ð¾˜ô¼ú8¥†A¶oÛ–Q‰D"G	$%	^—l:R ¸DÌëèÀ=÷ÜƒXï!_šç/³ý¼J…ßïâÐ\$ÍWÕ)îß1€¾¸š³� ÃŽnxúŸß×çä3ª�©“³tøÊõçmÑÃñ�BÊ>^p¸§oXŽk'.ÿO¨*WÜw ÑµwŸ»¥ãkÖß†ªÀÝ2šG@a7d“=`8oZ°Ý~ðþÚŒ`›û¸!àjœ:¨an'†M€åÁ
n°./¨¡�óÕCŠC““ÀûA˜ÓË½ZQYí`ý¦ÍbçÁmWQUºÀ 0³ûÞÆ€PÓÎí½./ÄºÖ_l˜U±ð[ð·ÌF }19ò’Ioß¶-ãä+�X"žS+°páBìÝ·Û·mCÿŽ¿Ûº•
¿›g0#T¼Gá_wcÿHîo1þÏ|ù½ïLÂ×f‹)S €Y4ô©¶ÕïB>PN	X<@B•Õ”­0}ûŠ@U9åmœ±œ° ôTžÖy œ`šö‚Ô$Ó®€¹Ò‡@½àae]^0o6Ïtû3¯3‚zj4¼CXœ' šV.„aÁºü`¨ËñPcÃ è,–e?GH×õO«æ*ë7mw¾õñÎýoüÀ¥ DÞD`ñ{án›Îí¨3]¥´°sÞ„P.G8qL+>ü-³œ},K`ïž=Ø¹sN?ý}H$9œ@>°~ýzÜóû{	��#;¶`Á) ›wæXÇ>?P:Ñ þ¶g;úr	bÆÐÀ3ôüg¾tâß'÷[ÌÅ”*  ¸µë•·ÓJàâRáABv«aì‰õÃœw‡ûÇòy5«No`=Ás8_x-8_Ü-æ*/z@X L:"0z{(¨®eÌzÖãç«ÃrÝvM÷f” Ãñ`]>pî,w€!ýy,!Ô„,kàDªÊ_ H=á„�SM2ž`-Õ”/txó6Pc3€Z–ã©îJâ_´œ¯| œ7dÞ3j¤c+8on¨­RŸ¿˜ð[°,K	tuÁ³/½ŠSO>	”ÒŒÈ'½^/Þsüñ¸ëîßP92@”¾ý˜yâ9±ý@yáî@¯uÅ¶Ë’tÅß¿râŸ&û»ÌÇ”+ ÀTŸž±&F€3J)FÕñèð hY¿ióOÆÒ5gÅÌ¥ÛÂ.ï'YÑã',=ƒ»iNFØÞ]2¿0Âr`Ñl�á«ëò˜ÖÇgÂ…Œà‚¡HWÀ‚É' º
Â‰émX—º"†BÞ•q	øP8—z"L©aˆ Ndæ*jÐ9/L6QÈðâIÔ0þƒªÒ- ÎEZð½3“Àqë	l ç	B5æøö¬è.ÈíÌ8¿X×V–í·PNø-ø[f£eùzÒ³õYhR#ƒý¸ÿÑ'1á"Ô…PU^¯·@	Ìž=®@yâÑG0xä ¼F+OÚT5áñP/uên/G¾öü—×þ|¢¿?'˜
  n=òò‹å”@“àÅýÛ(5ß‘#»þ:�è<°Ut¬L1‚ûÀôÑ9_êjCx„<"·*gZïÊ‚„°¶Ã‹¶9 „ãÁºý0²,yÂpà¼A€¦âÀ¨K`YbC;á\^PM±,‚•ÔÐ?àó ia˜õ›®8<Ö¶aÅ`úöÛO7?wRCÿ2€• ÄÑÿD"Ô¶€sû!„ÁºrÛt	Ázð�Ñ¤KØYW .øÝÎÓu]5�hYszw¼56MJà‰G�ªiX¶lTU…(Š0#G	œ´nM†èÜù&8–ÇìåkÊ~^9á¹3ŠÙÿãŸ]õ�j~oãÁ´Q €©>3cà;%À³:µÙë5ctŽÿÈ¿î‘óõŒÙ
Šy³Ûá9¸x^‘Ç`¼PÐ	Ã‚ ™Pßèv„1sr¶§-Ftƒjr†`òy.Ã»Ày‚E Ô¶@ð×‚Pš”  €zYç�­_aÎ°„Ô–'ë7^qªO°– Çƒ�3@éGA˜ëº¿õKjè—™Ÿ xgÂÛñø¬&\ |ÚÜ·¢&£×ã†X—›ÃŸë
�œ Sø=Bå½ü�3ß{ÂýÝH¦“…¶oÛ†g_z‹ÌË²`,Ëæ(�sÏ>¯¾ñ:öîÙƒ}oþl%àwq%	?»Ò^ÀLôyáËko¬øÂ&Ó²F÷ÕuWþ!ä:;%�•[¿isÃX&]{ç©*Åú{Öœ9hjiË¼NièIØ¾WOF`hjÁvCNeòË„¼Ôè�í,>5: -ÎÙFºƒ–Œ‚j*9irÑ¨±‘Rõ} é!QP#¯Àœ	‚­ øíÞÌr<uÕ6¶¦bÃL–3£n?XÑÂæ¡¢œ7”+øY¯åö”‚‡gPã+ž;_	>u¶Þõ_™ûÄr<½ôÒ"—\|1Z[[QSSŽã2)Ã‰H§�q¶l1»½ÿãÿ§|ô‹9î€A)ê<ýÅ…ÿÅCüÝfåŸŠ,?'˜–
 (®(¥8ãµ_§Çd�}VZÇçnžË	â¾Ì�`9¿z-Ø¬¦ŽbHªFÁ{©¦BKFl�kÈ)èR¼@ø-hÉ(4›n¼T“¡ÆÃÐ“…¯šb†³,92CŠƒ¦¢PÑLb¥à½¦Ïºý`õàýµéûÁ›.�è1óòPJð­|«Ùaù²¤ŸS¿Ä‡zñÒ/¾‰èîÑq®šF|ò²�ââ�ŸI¶Š‡úûûqÞyçg”Àâ3>‚‹¯ùO¸86“áW¬¦°/î¦¯ðÓX À+ë®¼†!ä¦|%ð“#/â¶ÎW Â<jŒ¹ï`¾ÐÖÜˆ¶¹2¯ËªŽ½qÛ÷–R  §-;š
-6Ã¦×}1E@Œè†ª@—bfß,¥ JI“‹ÐU[®0ùŠì:â6Âò`8$]‘¿Ò[(%ø ÒaÓ@ÁûKYc5ù�âàS÷aû½?ÌQ’3f¶ãü>„‹?t>QWW‡ÆÆÆK`î¢¥¸ôúŸcþ¼yEsûûN¾Àôóùó1­ `¯²‹ƒÆ4Ž*�×ßê‹G÷RUÎt£X¼òÃïqe*‚â2ú£öš†œ„žGþ±é]—“%• PÜÈ¼žCKFaÈ)3¡ÈUØŸê¨*ÃÐÌº+$i7Ô¼_\Æ¬'Î29¶øÊfÖBøl{ôºÝàƒE_·³ªiò—ƒÁÞŽwþv_ŽûÄ{ƒ¸äƒçâ}§�†µk×¢½Õt/þÈ‡ÓCOM«ákßù–¯ÛPx\�âÁ·qp¤ð™îÂL3Ð·yùÅOµ­~;;Y((¸±#Þ‡ÃR Ôƒ1’�‡ž¹GjX{n”Rúk["#MÍ£%©^�CBR*· “åÏ&Ù¬UÎL)v¯„¹3¢„-]Hgr¿~$È!�4É	`Ò†¬ÛÖí7ßgóÃºýf“à6žÒiÌ×Ærà<3¥7Ý©×n?Kðyméðµ2#Í}Bnu~wŽË5‘ðz½xÏ)ïÃŠ÷_LâI	#‡vQjÄPelß¶<ð xðÏØþö[ðx½¸òÊ+‘’u¼òòKÐ¤žùó½èîÄÒeË!zÌ,G3· G"¹ßch�%éŠéê+…ioXH÷¸Ãj(’M2žàìñ”Õ.ºúö]TWZç‚ºA±w0i;ž
0-ª«¶«ÕUh‰(¨Vš«44†’*jX1uª«™QÞ†’²%#+�¥´XÑÂ‰`8Œè)iXû³ÞPŽÒsŸÏ7i«¾…/�PžùêÅÞ§îÇÝƒDa4™÷qüÒÅèêîÆ‘Ã£=9]5�øäµÿŠ¥›>ˆÞ,håE€ažè—>ý…Õ�OÚŽG� 2G~K™C)ÅEoÞ�© äû ½v¬Ç]üõ{×ÉÈs™›ÂrX´leŽ+�Pt´ç\¢ ª¤�’Š¹–ŒÂ�âpÓìOæpùI5Ù º
CÓ@59£J¹ Ù¥¹¥Ìz»÷–sJÁçóÁç&ÔßÏ†‹cÐè –P6:¥Úý*^zìAt¾ñœ­2°½–YÇ¡õ_Dý’ÌxôIïæSU
 H·ëþYû@ï[¸qÿß€jXy„ ÛëÇ’eËsLT;>ÀÃ�æ›'ñ’JÀ©5`A—S%]ˆjÀIˆÎ$ýÜ¯ö™{éáñŽyxfÂ- »U¿DŽ@îÂ��Ûpø­W1ØÝ‰ÃûÞ�4Ü[4ìê›uZÎüVo¸ØLdï‰ÀQ§  3cíÔÀÝnUË
X¿i³8¸bãÖlW ?* ä*Žãàwå®„²,#/½ÒWb f
-ÕTèR†’§ÙŸsì"ñ{Â‰ãzÀ|ÁåÇævÏå:aV€“Uß~‘E£_ _„“§4<¿ë0ö’}ºªüµV—>üÌ�„'ä¢&G¥°ðêº+ÿãÏý;¯³¬ Â	Ç�§Ùf~n  ,X¸¡ºúœýºFˆ«(~N”€Sk€p¢m�j*¨&C—S²RÅ@8³JÑúk0èxQLð³Qm%À ÞËÃïpDW6šýBîâïH¨øëÎ~„S6n•®MÛ¿Õ
 0ÉÁ5[~ú€ü†ñ¾5Þ{‹¯úõçCÏao—.=žÀhs‹ƒ[· nþ
#¦1EŸpM7�ÅÒ†óQNS E�—¥ò�i%™¿›Çäª4$0}|–ãK
~6ªå
„\j=Ø
›Íº­�â«> ¼Õ—À“ïl§”FYª_9™<'G½ Òg«ØC=Ÿ°HA£2/Üþm�zœö±kÐW‘J§Þ—ã,P]5}þ<×€qùÊ¾w<¯p»D°_0°Ó	ÆkxM>¾bÁÊ¯ú’ªã©}aÛD0B�í^V¿üh"ûŠá]¡ ª�õ›6‹ƒ+7>F55“e¨w£ÿ±_Aî¥þÕ$ª�aŽ”€— ºœÌTV²ú�cQ „åáu‹­öÅ0+À+°¨óðûù@y_ º"2þº³ß6\W¤;ý�Ýö™é4âm<8¦ Š`Ãõ÷‡ú¢á—%¹pèå‡††^yø/ 0çÔ7ŸsÕÿdö3ƒ	C©ÒJ@Ó(RÒ‘5`�°|Ú2Hë�N€µÒWCèót9ËG�às,ƒf¿ ŸPüÜUƒâ¥ýƒx³§0òòn1ùîËTŸÀtÅ37^îøÜÍgK�ÛÏyëù{ :�ÛùãNCRÑáÒD�~"¯¡;oÄS68–÷ÿÛ;ûØªÎ:ŽŸç9çžû~o_i+XÖÂºN ¸¦BjL†fâÌÔÄlþ�C—8ÙœgÒD3’EˆD·l¨™Fb”2§t&3å5aH#8y]K¡o—{{_ÎÛóøÇí)íí¹¯½·´ô|’þçÐÒÛþ>Ïï÷{~Ï¹¾t�Oªy{ÀØ¤¡$�wê­�#nè�Þ£’«bŸIB3r–Ó	| ¨ñÉ¨óåÎ¤zo©xû¿ƒ¶�>"xOÈÍ6üëÉÕsj‹¯œ ªV®?ÚøÙo>èó°¼½m\	ÍD_4�çYó•…œ †~{`Lã×r‚°t°QI†wLJ f$Ø³‘Y
Hð+¥5÷,
I÷Sº‰“W†mW} s¾ËŸG Ò±î1¥·©%e=EØ%Ix`Åýðz&Oèé&G_T³­íÈ&‚BÏÐO—*ÑoÕX1Bn·Dv3x]¬äÀ÷¸ø$¸åÜ¥Åù›	t_²ýYÝM�¾\8(êUßûí�(¥ã']’„em-‡'¿µç‘”9åð¹ÈÁ|€µPÊôÞD‰ Î¯ä¬ó�ô¾þ‘‹CüjD�r£"J¸¹ÛûæË�wK£/Ž Š uó®Ù<1Q Ð¾´�õuSî/¦$°PU¦¡C3sPóN
 äfð¹¼òí8(Å¯ü…~¾tŸrØC´ïßí«þDIëæ]-²ÇˆJRÛÄ¿_ØÔ€%Í‹@3fƒJÉBnÝˆ§TŒêÈz
±Ì¤ ¬•>3è'Â
žæóŒ5ó¾ÎÎ\�ãôµû'<Ý¥þBpPk;÷…oÄ"oP&Mz‘ÏÀò{ï™Ò 
ïØÇ$4šnTD•€W¦ðH~E*x¿_f>9{P†oþHOò»4œýu7�í�ÑÁæâ9pP"ëS?¾~;¥ô©ÌkíK[° ¶fJ6 ¤Ë‚�¸žõ2ß`Œn
$tUUn4æ¢œ�©€ÌXÑoGf) 1Š�›!ì‘rvõ-ÎßLàäÕûù}ÌÏtßG Ó¤mËž�„ÒßdöªX|�}6À9GLãˆ$�)A\èPŒ…n
è¦	M7 ¼h)”" +ÐeFà–(%�))ë_«(é>A®±Ýñ×‚\HàÔµHÖÀ'‚÷<ò3så�•Æ@ÈÖ €ÖÅÍXÔXo›dŠ œ'ä,1èœŒÏ
hÆd9h‚¢Ú+AfS¥#3iì·Cb•	òlÈŒ¢ÚÃpí½XÝ±&ïŠŸÒMôôÇq¦÷VVÁ{ˆà?Ÿ�u~.”‰\%�Ï@[sã”íÂ‰$’Ihj
	:3Ûù&äf
™Q„ÜBn6ð'ïÇéãÝønç‹¶õ~$i §wïhY{#NàçÆ@™ißº·C¨‰Wì²�\eA×îN|aÓ³ ž bª�HÊDÊ˜~�Ÿ�;) �ÌThº_`³ÊóD?Øð€Xºjybû„=t.peDÅÙ¾ˆí>¾…ø…á äÊ€©":õìÝö=±õà…I?Õ0SÓ•’ÁL
Àêî—Djæýú‡�ãüÑ.´Ü·ŸÚú*.Ç�³ÏÁ9ìSè‹N�_Ž *Hëæ]-²?¼�<bw½¡* _¨ÿüñ— ÏüñxÖÏe˜1Õ@ÊUe¡R`pI
#EüDâš‰¿¼þN½ö“ÿ&ís…ë·,ùÖKA¥nÑ¤û„Q®«ûBn¶c¾wõ‹ÅÀÐ¾uo‡ÐÏgÎ À‡Ý�è§ú›?¶áÉ_í/ø0Žj˜Hh&R†@Êà%gå€Ì(Ü#ž±!ŸbƒÝ"®™¸8Åå�(†ãôèÎ¾ðè¿!øêUóDô¹ûŸýýÓîÆ% ‚÷¨£‘ßÕpí•ùº�?]Ì m[öl$À6«?9w}‡v�z‚où›Z‡Ú¾Ñ‰†Új,j¬G•·ð·Æ¶P�´t“§w¸€É“gÍr	ÀjøSJ!Q2~W‘\Œ–´ªÛÑÓ0��}&Wþôü±‘Ó]«­?Éµhí/»ïsÒüéãàÐ¶eÏFBðÔ…�Oüˆëj7 Ô¬zh°ñó›Æg	˜âÁ’ú ÔÖ”$;3�%˜"mƒÄðø½^„«Òo*MØâ+G`gc$©ãÃáQÜ¸•Â`,5O=“¸úÎù�¯-ðÓ;�#€YÂÂ/=ýNxÙšOÛ]óHµÕ¨«¡.è+Û™ý÷ßzJ 
ŸøÌ+ö}é\`(®c /8à-L]û»¼«®¶fï\{Þþ\Áy"Ð,Á·xÅKä£¢9óZÒ¸Ô?„KýCé{ƒ!,)üú¼ð¹J;9øþ¹s P6Ä5‘”�áX·b£IqÛ”>\ð˜0ŒnÅëÿƒ/6xÀ©ë+�“Ì2Ú·îízêæ=l';<AUÐÅ¥ äSàRÜðz<ðÉ4g¶ð‹¯}LVð³?Éû5t. 1Õ„j
Dã	hj
#) ©iˆ«zÁ+ûD˜ËÝ#8?”ê;Xsâo'çÃüÙ„#€YL)2ÈÄ#hÌ�¾ÛY‚âR�ìEWçWo Àºmo,hjjÄ(—93’4ÅÓ‰aRÓ�4	¸¡•ÜvXïûàDC0ü¶³ÊßYÌZ7ïjq¹½Ÿ’k=óV•*‹¡ãÐßõÛM ÐôÐw^®[ýpÙÿÏÌåî1tí]SMô˜ÉÑcÎ
?ûp0GiÝ¼«EòøWJ×È¡ú6®«íÅH¡÷ÀÎñ­µª•ë�6?úÜƒ…þÛ‰pÁc²â½lèÚ»ŒI×)ÁY¯$Îðý¯œw‚}öãà.bmç¾°¨ªi¾qå­r¸¾Åˆ.¡‘ƒµ~®«íÖ}¢ùì¶¯¬¦Þ „ÉË—ÿôÍnëº™Œ»ÃuQ ÐâÑ^êrßdLº®%¢ƒn_ð†ß«ôs-u“Œ]qRø¹ÍÿÒ‡+¦Å1È®    IEND®B`‚               h          ¨   00     ¨%          ›     X4   V S _ V E R S I O N _ I N F O     ½ïþ                  ?                        ¸   S t r i n g F i l e I n f o   ”   0 8 0 9 0 4 b 0   ,   C o m p a n y N a m e     a m p h p   Ô V  F i l e D e s c r i p t i o n     E x e c u t e s   a   c o m m a n d   a n d   p a s s e s   t h e   s t d i o   s t r e a m s   o f   t h e   c r e a t e d   p r o c e s s   t o   T C P   s o c k e t s   0   F i l e V e r s i o n     1 . 0 . 0 . 0   :   I n t e r n a l N a m e   P r o c e s s W . e x e     V   L e g a l C o p y r i g h t   C o p y r i g h t   ( C )   a m p h p   2 0 1 7     B   O r i g i n a l F i l e n a m e   P r o c e s s W . e x e     @   P r o d u c t N a m e     P r o c e s s   W r a p p e r   4   P r o d u c t V e r s i o n   0 . 0 . 0 . 0   D    V a r F i l e I n f o     $    T r a n s l a t i o n     	°<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
                                                                                                                                                                                                                                                                                                                                                            @     ø¢ ££(£0£`£h£   P      ¥¨¥°¥¸¥À¥È¥Ð¥Ø¨ð¨ø¨ p     @ P X h p € ˆ ˜                                                                                                                                                                                                                                                                                                                                                                                                                                                     MZ�       ÿÿ  ¸       @                                   ø   º ´	Í!¸LÍ!This program cannot be run in DOS mode.
$       ‹ìä Ï�ŠóÏ�ŠóÏ�ŠóÆõóÃ�ŠóôÓ‹òÍ�ŠóôÓ‰òÍ�ŠóôÓ�òÝ�ŠóôÓŽòÂ�ŠórAóÊ�ŠóÏ�‹ó”�ŠóeÓ‚òÌ�ŠóeÓuóÎ�ŠóÏ�óÎ�ŠóeÓˆòÎ�ŠóRichÏ�Šó        PE  L h%s\        à   (        1-      @    @                      €         @�                           TY  È    �  ¨Ü                   p @  PU  p                           ÀU  @            @  p                          .text   ô&      (                    `.rdata  ê!   @   "   ,              @  @.data   ˜   p      N              @  À.gfids       €      P              @  @.rsrc   ¨Ü   �   Þ   R              @  @.reloc  @   p     0             @  B                                                                                                                                                                                                                                                                                                U‹ìƒì8¡p@ 3Å‰EüVW�EøÇEø   ‹ñPh~f€ÿvÿ¬@@ …Àt"Pÿ6hC@ è‚  ƒÄ3À_^‹Mü3Íè¤  ‹å]Ãƒ=Äs@  t8¸   ¿   f‰EÌ¡Às@  ·¼s@ PEÔÇEÐ    ÿ°@@ f‰EÎ�EÌë-¸   ¿   f‰Eè¡Às@ ‹ ‰Eì·¼s@ Pÿ°@@ f‰Eê�Eèj j j j WPÿvÿ´@@ ƒøÿt!ÿ6h˜C@ èÛ  ƒÄ3À_^‹Mü3Íèý  ‹å]Ãÿ¤@@ =3'  t"ÿ6hôC@ Pè,  ƒÄ3À_^‹Mü3ÍèÎ  ‹å]Ã‹Mü¸   _3Í^è¹  ‹å]ÃÌÌU‹ìƒì¡p@ 3Å‰Eü‹ES‹]V‹uWj j j ‰Eð‹ú�Eø‰}ìPSVQÇEô    ÿœ@@ ƒøÿu+Wÿuðh0D@ ÿ¤@@ Pè¨  ƒÄ3À_^[‹Mü3ÍèI  ‹å]Ã3À…Û„�   ƒû‚†   ‹Ó�NWíƒâø(å�fnQ�I@fnAÀƒÀfnI¸fnY°fbØfnAàfbÊfnQèfbÙfnIØfþëfnYÐfbØfbÊfbÙfþã;Âr®fþå(ÄfsØfþà(ÄfsØfþàf~á‰Môë3É3Ò3ÿ;Ãs,‹Ë+Èƒùr�Kÿ Æ|ÆƒÀ;Árò‹Mô;ÃsÆ�È‹Eø;Át(QPÿuìÿuðhpD@ è*  ƒÄ3À_^[‹Mü3ÍèK  ‹å]Ã‹Mü¸   _^3Í[è5  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì$¡p@ 3Å‰EüSVW�EàÇEà    ‹ÙPh~f€ÿsÿ¬@@ …Àt#Pÿ3hàD@ è±  ƒÄ3À_^[‹Mü3ÍèÒ  ‹å]Ã‹;‹5Ès@ ¯þÆEô=Ôs@ ÿ0@@ ‹‹ÈÁéˆMõ‹ÈÁéˆMö‹ÈˆEøŠˆEù�EôÁéhTE@ ‰Eè�EäˆM÷‹KjPÇEä   ‰uì‰}ðè¸ýÿÿƒÄ…Àtƒ‹Mü¸   _^ÇC   3Í[èK  ‹å]ÃÌÌÌÌU‹ìƒì$¡p@ 3Å‰Eü¡Ès@ SVƒÀÇEô    WP‹ù‰EèÿÔ@@ ƒÄ‰Eì�Eôj j P�EðPj�EèPÿwÿÀ@@ ƒøÿu5ÿ7hhE@ ÿ¤@@ Pè)  ƒÄÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè¾  ‹å]Ã‹Eðƒøs/ÿuèPÿ7hÈE@ èo  ÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè‡  ‹å]Ã‹]ìŠ€ùt¾ÁPÿ7hhF@ è6  ë‹ŠK„ÉtF€ù}¶Á‹…S@ ë¸(G@ P¾ÁPÿ7hHG@ è  ÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè  ‹å]Ã�MøfÇEø‰Mä‹MèÇEà   ÇEÜ    ;ÁtQPÿ7hÈE@ è¸  ‹]ìƒÄé†   ‹�S‹5Ès@ ¯ÎÜs@ ƒîr@ ‹;uƒÂƒÁƒîsïƒþütAŠ:u'ƒþýt6ŠB:Auƒþþt)ŠB:AuƒþÿtŠB:Atÿ7hÐG@ èA  ‹]ìƒÄëÆEù ÇG   ÇEÜ   SÿØ@@ ‹�Eà‹OƒÄh<H@ jPèˆûÿÿ‹MüƒÄ÷ØÀ3Í#EÜ_^[è$  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌ3À‹�ƒz|	@ƒø|ñ3ÀÃ¸   ÃÌÌÌÌÌÌU‹ìQƒ=Äs@  ¸   S‹Ù¹   VEÁ3öW‰EüjÿÔ@@ ƒÄ‹øjjÿuü‰7ÇG    ÿÄ@@ ‰Gƒøÿt‰<³Fƒþ|Ì¸   _^[‹å]Ãÿ7hìH@ èR  ƒÄ3À_^[‹å]ÃÌÌÌÌÌÌU‹ìƒäø�ì,  ¡p@ 3Ä‰„$(  S‹]VW‰\$3ö‹³èRùÿÿ…À„  Fƒþ|ê‹Ëèÿÿÿ…À„¯  D  3Ò3ö3ÿ‰T$3À‰´$   ‰¼$(  ‰D$f�‹ƒ‹C…Àux3É…öt‹C9„Œ$  tA;Îrò;Îuƒþ@s‹C‰„Œ$  ‹´$   F‰´$   3É…ÿt‹C@ 9„Œ,  tA;Ïrò;ÏuRƒÿ@sM‹C‰„Œ,  ‹¼$(  G‰¼$(  ë2ƒøu-3À…Òt‹K9L„t@;Ârõ;Âuƒú@s‹K‰L„‹T$B‰T$‹D$‹\$@‰D$ƒøŒ6ÿÿÿj �„$,  P�„$(  P�D$$Pj ÿ @@ ‹ðƒþÿ„'  …ö„  3ÿ…ö~uƒÿ}p�D$P‹»ÿpÿ¸@@ …Àt‹»èœûÿÿ…À„³   NëC�„$   P‹»ÿpÿ¸@@ …Àt‹»è‘úÿÿ…À„ˆ   Në�„$(  P‹»ÿpÿ¸@@ …Àu1G…ö‹‹\$‹Ëènýÿÿ…À…Vþÿÿ3À_^[‹Œ$(  3Ìèf  ‹å]Â ‹4»�D$P�D$ÇD$   Ph  hÿÿ  ÿvÿ¼@@ ÿ6ƒøÿu'hXH@ èô  ƒÄ‹Œ$4  ƒÈÿ_^[3Ìè  ‹å]Â h°H@ ÿt$èI  ƒÄëÓhXI@ èº  ƒÄëÄh$I@ ÿ¤@@ Pè$  ë®ÌÌSVW‹ù3ö�G(Ç    ÇG0   ÇG,    f�j P�÷�CPSÿ@@ …Àt_…öu‹Gë‹j jPÿ@@ …Àt1F�G(ƒþ|ÈÇG4D   ‹‰Gl‹G‰Gp‹G�O`   ‰Gt¸   _^[ÃVhJ@ è  ƒÄ3À_^[ÃVh°I@ è  ƒÄ3À_^[ÃÌÌÌÌÌÌÌÌQVW‹ù�GP�G4Pÿ5Ìs@ �W(j h   jRRÿ5às@ j ÿ4@@ …Àuh�J@ ÿ$@@ Pè,  ƒÄ3À_^YÃÿw‹5(@@ ÿÖÿ7ÿÖÿwÿÖÿwÿÖ_¸   ^YÃÌU‹ìƒäøƒì¡p@ 3Ä‰D$SV‹uƒËÿWh   ÿÔ@@ ‹= @@ �L$ƒÄ‰D$ÇD$   j Qh   Pÿvÿ×…ÀtB‹D$…Àt[‹‹Nh(K@ ‰D$�D$jPè‹öÿÿƒÄ…Àt<j �D$Ph   ÿt$ ÿvÿ×…Àu¾‹=$@@ ÿ×ƒømtÿ6hÐJ@ ÿ×PèO  ƒÄë3Ûÿvÿ(@@ ÿvÿ˜@@ ‹L$‹Ã_^[3ÌèÙ  ‹å]Â U‹ìƒäøƒì¡p@ 3Ä‰D$SV‹uWh   ÇD$     ÇD$ÿÿÿÿÿÔ@@ ‹À@@ ƒÄ‰D$�D$ÇD$   j j P�D$$Pj�D$$PÿvÿÓƒøÿtS‹=@@ �‹D$…À„“   j �L$$QPÿt$ ÿvÿ×…Àtu‹D$ ‹L$;ÁuVj j �D$$P�D$$Pj�D$$PÿvÿÓƒøÿu´ÿ6h4K@ ÿ$@@ PèQ  ƒÄÿvÿ(@@ ‹L$$‹D$_^[3Ìèæ  ‹å]Â QPÿ6hØK@ èŸ  ƒÄëÌÿ6hxK@ ë´ÇD$    ë¹ÌÌÌÌÌÌÌU‹ì¸  ès  ¡p@ 3Å‰Eü¡Ès@ SVW�4@jöö�<@ÿ@@ ‹Ø�…ôÿþÿj PV�…øÿþÿPSÿ @@ …Àu'h`L@ ÿ$@@ Pè¢  ƒÄ3À_^[‹Mü3ÍèC  ‹å]Ã‹…ôÿþÿ;Æt"VPh¨L@ èö  ƒÄ3À_^[‹Mü3Íè  ‹å]Ã‹5Ô@@ W‰=Ðs@ ÿÖƒÄ£Ôs@ ��øÿþÿWQPèé  ƒÄ‰=Øs@ WÿÖƒÄ£Üs@ ��øÿþÿÏWQPèÅ  ‹5 @@ �…ôÿþÿƒÄj Pj�…øÿþÿPSÿÖ…Àu
h0M@ é=ÿÿÿ‹…ôÿþÿƒøtPh˜M@ èU  é.ÿÿÿŠ…øÿþÿ„Àt¾ÀPh@N@ è8  éÿÿÿj �…ôÿþÿPh   �…øÿþÿPSÿÖ…Àu
hÐN@ éßþÿÿ‹…ôÿþÿ=   u hO@ èö
  ƒÄ3À_^[‹Mü3Íè  ‹å]Ã€¼÷ÿþÿ t h€O@ èÌ
  ƒÄ3À_^[‹Mü3Íèí  ‹å]Ã‹=@@ �…øÿþÿj j jÿPj héý  ÿ×‹ð…öu høO@ èŠ
  ƒÄ3À_^[‹Mü3Íè«  ‹å]Ã3Éº   ÷â�Á÷ÙÈQÿÔ@@ ƒÄ£às@ VPjÿ�…øÿþÿPj héý  ÿ×…Àu hhP@ è3
  ƒÄ3À_^[‹Mü3ÍèT  ‹å]Ã‹Mü¸   _^3Í[è>  ‹å]ÃÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüˆUô�Eô‹U‰Eð‹ÂÁèÇEõ    ˆEõ‹ÂÁèˆEö‹ÂV‹uÁèVˆE÷�EìˆUø‹‹IjPÇEì   è&òÿÿ‹MüƒÄ3Í^èË  ‹å]ÃÌÌÌÌU‹ìƒì¡p@ 3Å‰EüSVW3ÿ‹Ù3ö€    �EìPÿ4³ÿ @@ …À„�   ‹Eì=  u
‹³‰D½ðGë…Àu~Fƒþ|Í…ÿtIjÿj�EðPWÿ@@ ƒøÿuhHQ@ ÿ$@@ Pè”	  ƒÄ‹= @@ 3ö�EìPÿ4³ÿ×…Àt"ƒ}ì u1Fƒþ|ç¸   _^[‹Mü3Íè  ‹å]ÃVhðP@ ÿ$@@ PèH	  ƒÄ‹Mü3À_^3Í[èé
  ‹å]ÃÌÌU‹ìƒäø�ìÀ   ¡p@ 3Ä‰„$¼   ƒ=äs@  V‹uWujjÿè@@ ƒÄ£äs@ …ÀtPÿL@@ h t@ h  ÿ¨@@ …ÀtPh”Q@ èL  ƒÄ‹UVè@  ƒÄ…Àtxè´ûÿÿ…Àto�Œ$¬   èdõÿÿ…Àt_‹=,@@ �„$¬   j j Ph€@ j j ÿ×jx‹ð�D$4j PèG  ƒÄ�L$0èGøÿÿ…Àt"jÿVÿ@@ ƒøÿu0hÀQ@ ÿ$@@ PèD  ƒÄèÌ  ƒÈÿ_^‹Œ$¼   3ÌèÜ	  ‹å]Ã�„$¨   PVÿ @@ …Àu0hR@ ÿ$@@ Pè  ƒÄè‰  ƒÈÿ_^‹Œ$¼   3Ìè™	  ‹å]Ãƒ¼$¨    u—�L$0è_øÿÿ…ÀtŠ‹Œ$¬   º   hhR@ ÿt$Tè1ýÿÿƒÄ…À„eÿÿÿ‹„$¬   j ÇD$    j ‹@‰D$‹D$<‰D$�D$Ph @ j j ÿ×‰„$¸   ‹„$°   j ÇD$   j ‹@‰D$(‹D$@‰D$$�D$ Ph@@ j j ÿ×‰„$¼   ‹„$´   j ÇD$(   j ‹@‰D$4‹D$H‰D$0�D$,Ph@@ j j ÿ×jÿÿt$L‰„$È   ÿ@@ ƒøÿu0hpR@ ÿ$@@ PèÙ  ƒÄèa  ƒÈÿ_^‹Œ$¼   3Ìèq  ‹å]Ã�„$¨   Pÿt$Lÿ8@@ …Àu0hÀR@ ÿ$@@ Pè“  ƒÄè  ƒÈÿ_^‹Œ$¼   3Ìè+  ‹å]Ã‹Œ$¬   º   hS@ ÿ´$¬   è×ûÿÿƒÄ…À„þÿÿ�Œ$¸   è0üÿÿ…À„÷ýÿÿ‹„$¬   ÿpÿ˜@@ ‹Œ$Ä   ‹„$¨   _^3ÌèÄ  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌSVW‹Ù3ÿ¾p@ @ ‹‹Óf‹
f;uf…Étf‹Jf;HuƒÂƒÀf…ÉuÞ3ÀëÀƒÈ…ÀtƒÆG�þHp@ |Á_^3À[Ã�_^�…p@ [ÃÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìQVWjÿÔ@@ ƒÄ‹ðVÿujÿ”@@ ƒè t:ƒèthtS@ èÝ  ƒÄVÿØ@@ ƒÄ3À_^Y]Ã‹E‰pÇ@    ¸   _^Y]Ã‹=Ø@@ Vÿ×ƒÄjÿÔ@@ ƒÄ‹ðVÿujÿ”@@ ƒè t#ƒèthtS@ ë‹E‰pÇ@   ¸   _^Y]Ãh°S@ è[  ƒÄVÿ×ƒÄ3À_^Y]ÃÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüS‹]V‹uWÇEø    ÿ<A@ j
Ç     �EøPVÿÌ@@ ƒÄ‹ø9uøt/ÿ<A@ ƒ8 u$‰;…ÿ~�ÿ   }_^¸   [‹Mü3Íè  ‹å]Ãÿ3hàS@ èÂ  ‹MüƒÄ3Í3À_^[èã  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüS‹]V‹uWÇEø    ÿ<A@ j
Ç     �EøPVÿÌ@@ ƒÄ‹ø9uøtÿ<A@ ƒ8 u‰{…ÿÿshT@ è>  ƒÄ‹Mü¸   _^3Í[è\  ‹å]ÃÌÌÌÌÌU‹ì‹E‹M‰H¸   ]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìVW‹ú·ƒø-uf9Gufƒ u	¸   _^]Ãƒ} t‹E‹0‹ÎèIýÿÿWVh¼s@ ‹@ÿÐƒÄ_^]Ãƒø-…£   f9G…™   ‹u�Gh@T@ P‰ÿˆ@@ ‹6‹øƒÄ‹Î…ÿu<èýüÿÿ…ÀuVhDT@ èn  ƒÄ3À_^]Ã‹@…Àu	¸   _^]ÃVh¼s@ ÿÐƒÄ_^]Ã3Àf‰è¼üÿÿ…Àt¿‹H…ÉuVhlT@ è&  ƒÄ3À_^]Ã�GPVh¼s@ ÿÑƒÄ_^]Ã_¸   ^]ÃÌU‹ìƒìS3ÛÇÄs@ ÿÿÿÿVW‹ú‰]ü�s‰¼s@ ‰Às@ ‰Ès@ ‰Ìs@ ;þ~=€    �EüSP‹E‹°è°þÿÿƒÄƒøwÿ$…˜'@ »   ë3ÛF;÷|Óƒ=Äs@ ÿuhU@ h8S@ h¼s@ èfüÿÿƒÄƒ=Ès@  uh¤T@ è`  ƒÄ3À_^[‹å]Ãƒ=¼s@  uhÜT@ èA  ƒÄ3À_^[‹å]Ã_^¸   [‹å]Ã�c'@ -'@ -'@ '@ &'@ ÌÌÌÌ¸�u@ ÃÌÌÌÌÌÌÌÌÌÌU‹ìƒäø‹E�MQj ÿuPèØÿÿÿÿpÿ0ÿXA@ ƒÄ‹å]ÃÌÌÌÌÌÌU‹ìƒäøƒìSV‹Ú‰L$W‰\$è¥ÿÿÿÿu‹øj Sj ‹j ÿwƒÉQÿTA@ ƒÉÿƒÄ…ÀHÁ;Áu	‹Á_^[‹å]Ã�X3É‹Ãº   ÷â�Á÷ÙÈQÿÔ@@ ‹ðƒÄ…öuƒÏÿ‹Ç_^[‹å]Ãÿuj ÿt$SVÿwÿ7ÿ`A@ ƒÄ¿ÿÿÿÿ…ÀHÇ;ÇuVÿØ@@ ƒÄ‹Ç_^[‹å]Ã‹L$_‰1^[‹å]ÃÌÌÌÌÌÌÌÌÌÌU‹ìƒìƒ=äs@  Vu3À^‹å]Ãjjÿè@@ ‹ðƒÄ…ötæ‹U�EP�Müè÷þÿÿ‹UüƒÄH�B·ƒø tƒø	t
ƒøtƒø
u
3Àf‰ƒéëßVÿ5äs@ ‰VÿH@@ ¸   ^‹å]ÃÌÌU‹ìƒì¡p@ 3Å‰EüV‹u�Eøj j Ph   Vj h   ÇEø    ÿ<@@ ‹U…Òu ÿuøVh$U@ è5ÿÿÿƒÄ^‹Mü3ÍèZ  ‹å]Ã�EP�MôèGþÿÿƒÄÿuøVÿuôh4U@ èÿÿÿ‹MüƒÄ3Í^è(  ‹å]ÃÌU‹ìQSVWh€   ÇEü€   ÿÔ@@ ƒÄ‹Ø‹=D@@ ¡äs@ …À„á   PÿP@@ …À„©   ‹pPÿÜ@@ ƒÄ…ö„”   j j ÿuüSjÿVj héý  ÿ×…Àu]ÿ$@@ ƒøzu¬j j j j jÿVj héý  ÿ×‹ø…ÿtŒWSÿà@@ ƒÄ…À„yÿÿÿj j WPjÿVj ‰}ü‹Ø‹=D@@ héý  ÿ×…À„ZÿÿÿShLU@ jÿ\A@ ƒÄPèýÿÿƒÄé;ÿÿÿ¡äs@ …Àt Pÿ@@@ ÿ5äs@ ÿÜ@@ ƒÄÇäs@     SÿØ@@ ƒÄ_^[‹å]Ã;p@ òuòÃòé_  Vjè  èX  PèE  èp  ‹ðè?  j‰èä  ƒÄ^„ÀtlÛâèL  h²3@ èl  è  Pèâ
  YY…ÀuJè  èc  …Àthb1@ è¾
  Yè+  è&  è   èß  Pè÷
  Yèì  „Àtè 
  èÅ  3ÀÃjè4  Ìèù  3ÀÃè…  è¨  PèÆ
  YÃjhY@ è"  jè  Y„Àujèú  2Ûˆ]çƒeü è³  ˆEÜ¡|s@ 3ÉA;ÁtÜ…ÀuI‰|s@ hŒA@ h€A@ è3
  YY…ÀtÇEüþÿÿÿ¸ÿ   éý   h|A@ htA@ è
  YYÇ|s@    ëŠÙˆ]çÿuÜèÙ  Yèq  ‹ð3ÿ9>tVè;  Y„ÀtWjW‹6‹Îè_  ÿÖèP  ‹ð9>tVè  Y„Àtÿ6èÝ	  YèÅ	  ‹øè¸	  ‹ðè�	  Pÿ7ÿ6èUóÿÿƒÄ‹ðè1  „ÀuVè�	  „Ûuè–	  j jèm  YYÇEüþÿÿÿ‹Æë=‹Mì‹‹ ‰EàQPè!	  YYÃ‹eèèì  „Àuÿuàè@	  €}ç uèS	  ÇEüþÿÿÿ‹Eàè  Ãè�  é‡þÿÿU‹ìj ÿt@@ ÿuÿx@@ h	 Àÿp@@ Pÿl@@ ]ÃU‹ì�ì$  jè=	  …ÀtjYÍ)£`q@ ‰\q@ ‰Xq@ ‰Tq@ ‰5Pq@ ‰=Lq@ fŒxq@ fŒlq@ fŒHq@ fŒDq@ fŒ%@q@ fŒ-<q@ œ�pq@ ‹E £dq@ ‹E£hq@ �E£tq@ ‹…ÜüÿÿÇ°p@   ¡hq@ £lp@ Ç`p@ 	 ÀÇdp@    Çpp@    jXkÀ Ç€tp@    jXkÀ ‹p@ ‰LøjXÁà ‹ p@ ‰Løh A@ èáþÿÿ‹å]ÃU‹ì‹EV‹H<È·A�QÐ·Akð(ò;Öt‹M;Jr
‹BB;ÈrƒÂ(;Öuê3À^]Ã‹Âëùèa  …Àu2ÀÃd¡   V¾€s@ ‹Pë;Ðt3À‹Êð±…Àuð2À^Ã°^ÃU‹ìƒ} uÆœs@ è‚  èŠ  „Àu2À]Ãè}  „Àu
j èr  Yëé°]ÃU‹ìƒìV‹u…ötƒþu|èà  …Àt*…öu&h„s@ èX  Y…Àt2ÀëWh�s@ èE  ÷ØYÀþÀëD¡p@ �uôWƒà¿„s@ j Y+ÈƒÈÿÓÈ3p@ ‰Eô‰Eø‰Eü¥¥¥¿�s@ ‰Eô‰Eø�uô‰Eü°¥¥¥_^‹å]Ãjè5  Ìjh8Y@ è=  ƒeü ¸MZ  f9  @ u]¡< @ �¸  @ PE  uL¹  f9ˆ @ u>‹E¹  @ +ÁPQèiþÿÿYY…Àt'ƒx$ |!ÇEüþÿÿÿ°ë‹Eì‹ 3É�8  À”Á‹ÁÃ‹eèÇEüþÿÿÿ2Àè  ÃU‹ìèÏ  …Àt€} u	3À¹€s@ ‡]ÃU‹ì€=œs@  t€} uÿuè  ÿuè  YY°]ÃU‹ì¡p@ ‹È3„s@ ƒáÿuÓÈƒøÿuè  ëh„s@ èô  Y÷ØYÀ÷Ð#E]ÃU‹ìÿuèºÿÿÿ÷ØYÀ÷ØH]ÃU‹ìƒìƒeô ƒeø ¡p@ VW¿Næ@»¾  ÿÿ;Çt…Æt	÷Ð£ p@ ëf�EôPÿ\@@ ‹Eø3Eô‰Eüÿ`@@ 1Eüÿ0@@ 1Eü�EìPÿd@@ ‹Mð�Eü3Mì3Mü3È;Ïu¹Oæ@»ë…Îu‹ÁG  ÁàÈ‰p@ ÷Ñ‰ p@ _^‹å]Ã3ÀÃ3À@Ã¸ @  Ãh s@ ÿL@@ Ã°Ãh   h   j è  ƒÄ…ÀuÃjè=   ÌÃ¸¨s@ Ãèöÿÿ‹Hƒ‰Hèçÿÿÿ‹Hƒ‰HÃ3À9p@ ”ÀÃ¸ìs@ Ã¸ès@ ÃU‹ì�ì$  SVjèÃ  …Àt‹MÍ)3ö�…ÜüÿÿhÌ  VP‰5°s@ è  ƒÄ‰…Œýÿÿ‰�ˆýÿÿ‰•„ýÿÿ‰�€ýÿÿ‰µ|ýÿÿ‰½xýÿÿfŒ•¤ýÿÿfŒ�˜ýÿÿfŒ�týÿÿfŒ…pýÿÿfŒ¥lýÿÿfŒ­hýÿÿœ�…œýÿÿ‹E‰…”ýÿÿ�E‰… ýÿÿÇ…Üüÿÿ  ‹@üjP‰…�ýÿÿ�E¨VPè{  ‹EƒÄÇE¨  @ÇE¬   ‰E´ÿX@@ V�Xÿ÷Û�E¨‰Eø�…ÜüÿÿÛ‰EüþÃÿt@@ �EøPÿx@@ …Àu¶Ã÷ØÀ!°s@ ^[‹å]Ãj ÿT@@ ‹È…Éu2ÀÃ¸MZ  f9uó‹A<Á�8PE  uæ¹  f9HuÛƒxtvÕƒ¸è    •ÀÃhF3@ ÿt@@ ÃU‹ì‹E‹ �8csmàu%ƒxu‹@= “t=!“t="“t= @™t3À]Â è$  ÌSV¾Y@ »Y@ ;ósW‹>…ÿt	‹Ïè8   ÿ×ƒÆ;órê_^[ÃSV¾Y@ »Y@ ;ósW‹>…ÿt	‹Ïè   ÿ×ƒÆ;órê_^[Ãÿ%pA@ ÌÌÌÌÌÌÌÌÌÌÌÌÌhK4@ dÿ5    ‹D$‰l$�l$+àSVW¡p@ 1Eü3ÅP‰eèÿuø‹EüÇEüþÿÿÿ‰Eø�Eðd£    òÃ‹Mðd‰    Y__^[‹å]QòÃU‹ìÿuÿuÿuÿuhó*@ hp@ è±  ƒÄ]ÃU‹ìƒ%´s@  ƒì(S3ÛC	p@ j
è$  …À„m  ƒeð 3Àƒp@ 3ÉVW‰´s@ �}ØS¢‹ó[‰‰w‰O‰W‹EØ‹Mä‰Eø�ñineI‹Eà5ntelÈ‹EÜj5GenuÈXj YS¢‹ó[‰‰w‰O‰WuC‹EØ%ð?ÿ=À t#=` t=p t=P t=` t=p u‹=¸s@ ƒÏ‰=¸s@ ë‹=¸s@ ƒ}ø‹Eä‰Eè‹Eà‰Eü‰Eì|2jX3ÉS¢‹ó[�]Ø‰‰s‰K‰S‹EÜ©   ‰Eð‹Eüt	ƒÏ‰=¸s@ _^©   tmƒp@ Ç´s@    ©   tU©   tN3ÉÐ‰Eô‰Uø‹Eô‹Møƒà3Éƒøu3…Éu/¡p@ ƒÈÇ´s@    öEð £p@ tƒÈ Ç´s@    £p@ 3À[‹å]Ã3À9p@ •ÀÃÿ%Œ@@ ÿ%„@@ ÿ%A@ ÿ%4A@ ÿ%ø@@ ÿ%HA@ ÿ%DA@ ÿ%@A@ ÿ%0A@ ÿ%,A@ ÿ%A@ ÿ%LA@ ÿ%dA@ ÿ%8A@ ÿ%A@ ÿ%A@ ÿ% A@ ÿ%A@ ÿ%ð@@ ÿ%ä@@ ÿ%hA@ ÿ%A@ ÿ%A@ ÿ% A@ ÿ%$A@ ÿ%(A@ ÿ%h@@ ÌÌÌÌÌÌÌÌÌÌQ�L$+ÈÀ÷Ð#È‹Ä% ðÿÿ;Èòr‹ÁY”‹ ‰$òÃ-   … ëçÌÿ%€@@                                                                                                                                                                                                                                                                             Œ[  ˜[  °[  À[  Ì[  æ[  ô[  
\   \  4\  D\  R\  b\  x\  Š\   \  ²\  Ê\  à\  ü\  ]  Ìa  ¸a  ža  ˆa  na  Ra  >a  *a  a  ð`      àa  Š]  v]  €]      ^]    €T]    €o  €s  €
  €	  €F]  —  €  €<]    €    È]      ¾]  ¶]  Ü]  ^  ¨_  &^      ’_      �^      Z_  d_  P_  _  n^  È_  ä_  B_   `  `  `  _  ü^  €^  4_  Ò]  Ü^  ¼^  ¤^  _      R^  8^  
^  ì]  &_  ¸_      Ÿ1@     °+@         +@ ¨+@                     `p@ °p@ S u c c e s s   S i g n a l   n o t   e x p e c t e d   a t   t h i s   t i m e     I n v a l i d   s t r e a m   i d e n t i f i e r   I n v a l i d   p r o c e s s   i d e n t i f i e r     D u p l i c a t e   s t r e a m   i d e n t i f i e r   I n v a l i d   c l i e n t   s e c u r i t y   t o k e n   I n v a l i d   s e r v e r   s e c u r i t y   t o k e n   F a i l e d   t o   s e t   s o c k e t   # % d   t o   n o n - b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       C o n n e c t i n g   s o c k e t   # % d   u n e x p e c t e d l y   s u c c e e d e d     C o n n e c t i n g   s o c k e t   # % d   f a i l e d     F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d   F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d :   s e n t   % d   o f   % d   b y t e s         F a i l e d   t o   s e t   s o c k e t   # % d   t o   b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d   h a n d s h a k e   F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   U n e x p e c t e d   s i g n a l   c o d e   % d   f r o m   s e r v e r ,   e x p e c t i n g   H A N D S H A K E _ A C K   U n k n o w n   e r r o r       H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   S e r v e r   r e j e c t e d   c o n n e c t i o n :   % d :   % s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   I n v a l i d   s e r v e r   t o k e n   h a n d s h a k e   a c k   F a i l e d   t o   c o n n e c t   s o c k e t   # % d :   U n k n o w n   e r r o r   F a i l e d   t o   c o n n e c t   s o c k e t   # % d     F a i l e d   t o   c r e a t e   s o c k e t   # % d   s e l e c t ( )   o p e r a t i o n   f a i l e d   s e l e c t ( )   u n e x p e c t e d l y   r e t u r n e d   z e r o   s o c k e t s   F a i l e d   t o   c r e a t e   p i p e   f o r   p r o c e s s   I / O   s t r e a m   # % d         F a i l e d   t o   s e t   h a n d l e   i n f o r m a t i o n   f o r   p r o c e s s   I / O   s t r e a m   # % d   F a i l e d   t o   c r e a t e   c h i l d   p r o c e s s     F a i l e d   t o   r e a d   f r o m   c h i l d   p r o c e s s   p i p e   # % d     d a t a     F a i l e d   t o   r e a d   f r o m   s o c k e t   # % d         F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d       F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d :   s e n t   % d   o f   % d   b y t e s     F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n         F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s     F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n       F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   1   b y t e       F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   e x p e c t e d   0 ,   g o t   % d       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   c o m m a n d   t o o   l o n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   m i s s i n g   n u l l   t e r m i n a t o r     F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   i n v a l i d   U T F - 8   s t r i n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   f a i l e d   t o   d e c o d e   U T F - 8   s t r i n g         R e t r i e v i n g   c o p y   t h r e a d   # % d   e x i t   c o d e   f a i l e d   W a i t   o p e r a t i o n   o n   c o p y   t h r e a d s   f a i l e d   W S A S t a r t u p   f a i l e d :   % d   W a i t   o p e r a t i o n   o n   c o n n e c t   t h r e a d   f a i l e d   R e t r i e v i n g   c o n n e c t   t h r e a d   e x i t   c o d e   f a i l e d     P I D   W a i t   o p e r a t i o n   o n   c h i l d   p r o c e s s   f a i l e d     R e t r i e v i n g   p r o c e s s   e x i t   c o d e   f a i l e d   e x i t   c o d e   ¨A@ ¸A@ üA@ 0B@ hB@  B@ ÜB@ a d d r e s s   p o r t     t o k e n - s i z e     c w d   E r r o r   p a r s i n g   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   p o r t :   % d   I n v a l i d   t o k e n   s i z e :   % d     =   U n k n o w n   o p t i o n :   % s     O p t i o n   % s   r e q u i r e s   a   v a l u e     P r o c e s s   l a b e l   n o t   s u p p l i e d     S e r v e r   p o r t   n o t   s u p p l i e d     1 2 7 . 0 . 0 . 1   % d :   % s     % s :   % d :   % s     %s
     h%s\       f   $V  $B      h%s\          ŒV  ŒB      h%s\       h   V   B      h%s\                   \                                                           p@  V@    pA@                    K4  RSDS0=|«@ÕèE�¾¿’ó œØ   C:\Users\Dave\source\repos\windows-process-wrapper\Release\ProcessWrapper.pdb       "   "         GCTL   ô&  .text$mn     @  p  .idata$5    pA     .00cfg  tA     .CRT$XCA    xA     .CRT$XCAA   |A     .CRT$XCZ    €A     .CRT$XIA    „A     .CRT$XIAA   ˆA     .CRT$XIAC   ŒA     .CRT$XIZ    �A     .CRT$XPA    ”A     .CRT$XPZ    ˜A     .CRT$XTA    œA     .CRT$XTZ     A  €  .rdata   V     .rdata$sxdata   $V  ä  .rdata$zzzdbg   Y     .rtc$IAA    Y     .rtc$IZZ    Y     .rtc$TAA    Y     .rtc$TZZ    Y  <   .xdata$x    TY  ´   .idata$2    Z     .idata$3    Z  p  .idata$4    Œ[  ^  .idata$6     p  `   .data   `p  8  .bss     €      .gfids$y     �  À  .rsrc$01    À‘  èÚ  .rsrc$02                    þÿÿÿ    Ìÿÿÿ    þÿÿÿî,@ -@     þÿÿÿ    Øÿÿÿ    þÿÿÿ0@ 0@ Z          .]   @  °Z          j]  ”@  œZ          ¤]  €@  ðZ          *`  Ô@  èZ          J`  Ì@  [          l`   A  p[          Ž`  TA  [          ®`  ø@  [          Î`  ð@                      Œ[  ˜[  °[  À[  Ì[  æ[  ô[  
\   \  4\  D\  R\  b\  x\  Š\   \  ²\  Ê\  à\  ü\  ]  Ìa  ¸a  ža  ˆa  na  Ra  >a  *a  a  ð`      àa  Š]  v]  €]      ^]    €T]    €o  €s  €
  €	  €F]  —  €  €<]    €    È]      ¾]  ¶]  Ü]  ^  ¨_  &^      ’_      �^      Z_  d_  P_  _  n^  È_  ä_  B_   `  `  `  _  ü^  €^  4_  Ò]  Ü^  ¼^  ¤^  _      R^  8^  
^  ì]  &_  ¸_      PReadFile  SetHandleInformation  ÀGetStdHandle  áWriteFile ©WaitForMultipleObjects  Ô CreatePipe  «WaitForSingleObject ÑMultiByteToWideChar -GetExitCodeThread PGetLastError   CloseHandle è CreateThread  
GetCurrentProcessId Û CreateProcessW  ,GetExitCodeProcess  šFormatMessageW  TInterlockedFlushSList ÍWideCharToMultiByte WInterlockedPushEntrySList KInitializeSListHead VInterlockedPopEntrySList  KERNEL32.dll  H WSARecv   WSAConnect  M WSASend  InetPtonW WS2_32.dll  P wcsstr  H memset  5 _except_handler4_common VCRUNTIME140.dll   free   malloc  n wcstol  # _errno    _aligned_free  __stdio_common_vswprintf_s    __acrt_iob_func  realloc  _aligned_malloc  __stdio_common_vfprintf  __stdio_common_vswprintf  B _seh_filter_exe D _set_app_type . __setusermatherr   _configure_wide_argv  7 _initialize_wide_environment  + _get_initial_wide_environment 8 _initterm 9 _initterm_e X exit  % _exit T _set_fmode   __p___argc   __p___wargv  _cexit   _c_exit ? _register_thread_local_exe_atexit_callback   _configthreadlocale  _set_new_mode  __p__commode  6 _initialize_onexit_table  > _register_onexit_function  _crt_atexit  _controlfp_s  j terminate api-ms-win-crt-heap-l1-1-0.dll  api-ms-win-crt-convert-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll  api-ms-win-crt-locale-l1-1-0.dll  ‚UnhandledExceptionFilter  CSetUnhandledExceptionFilter 	GetCurrentProcess aTerminateProcess  mIsProcessorFeaturePresent -QueryPerformanceCounter GetCurrentThreadId  ÖGetSystemTimeAsFileTime gIsDebuggerPresent gGetModuleHandleW  F memcpy                        ±¿DNæ@»ÿÿÿÿ         8S@     °#@ HS@     €$@ TS@      %@ lS@      %@                                                                                                                                                                                                                                                                                                                                                                                                                                                         
         E   s   4      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     0  €   `  €   x  €   �  €                  ¨  €   À  €   Ø  €   ð  €               e    €                    €                  8 €               	  P                 	  `                 	  p                 	  €                 	  �                 	                    	  °  À‘  h          (–  ¨          Ð¦  ¨%          xÌ  ›          �g >           Ðg X          (k }          (                                                ­�: ©|6	º�EcÈ™OÌÍ�Q÷Ò¥^ùÕ©cäË£c¡Ò¦_GÛ�5×žC         k7Ë *N H%ŒK/G»‹=xÃ�?õ³‚4ÿ«{/ÿ»‰9ÿÏšHÿ×©aÿÓ¬oî³‘[’²…>²�Q ˆ<  n:Î s<ÖV-§‰Y9Gb˜l3ì�\!ó_C—R:dgI�›o(æ¾�Dÿ¬˜xÿ¸�sÿÛµx±ÓžKÕ¤W e/Ên9Î’o?ÇøsI»ïoH¨ÿV4‰â;wCqV'_u_<–\F%l™‰oíÄ´›ÿÕªeÿà»‚ÿÔ®r�] yIÑLŠ`Øï�yßú¢€ÒÞ¢{¡ü†a¥ÿ_:¡Ù�`>ÅÂ£qÙxoa9ÄÅÇÜÊ¯ƒÿ×¨]ÿÝ´tÿÛ¼ŒèÕ¬lF‘jÞ`¢äÀ˜wÕÈaK¾�D¹©}>ÿ’jHÿ¹�VùØ·ƒ‚YPAMÁ¿»õ·›pÿÖ©bÿÝ³rÿäÃ�ÿá½„§‘xRlš~d\ˆmyL]Idšv;%Ã˜U}È ] ÂŸg x9UhK‘­†Iÿ»�KÿÓ¦_ÿÚ°nÿâ¿‰ÿÕºŽØÇ©{ûÜ¼ŠúÒ³�è’{W�´”b¯¤†V—´ŒM«³…<Ñ†`%°ZÆÅ‘?ÿØ¨[ÿ‰mAÿ€g@ÿÞ¾ŒÿçÍ¥ùÎ±ƒûæÅ’ÿäÂŽÿ¾žkþÕ«hÿÍžUÿº‡7ÿ�e$÷[AÛ›n'üÐ›Iÿ×§[ÿ‰mAÿ€g@ÿÞ¿ŒÿçÍ¥ùÆ§vãÝ³rÿÚ°lÿÙ¬cÿÎ›Jÿ½‰9ÿ•j&ÿ[AýhJþ®}/ÿÐ™DÿÓŸMÿÙ¬eÿÚ°mÿâÁŒÿÖ»�Ø½¡t§Ú°nÿ×ªbÿÍ�Oÿ¸…3ÿ¢r(ÿZ ÿS;ÿ�\!ÿ½‡1ÿÎ•<ÿÓ OÿÚ®iÿÜ³qÿåÆ•ÿá¾†¥ª“pIÓ¯víÆ’@ÿ¿ˆ0ÿµ€-ÿ�f%ÿnNÿV=ÿ“i%ÿÂ‹2ÿÎ˜AÿÖ§\ÿØªbÿÝ¶wÿäÅ’éÚ°lC?2Æ©{’Ï£]ÿ»…1ÿšn'ÿ‹c$ÿlMÿfIÿ¬|/ÿÎ˜CÿÓ¡PÿÕ¤WÿÛ±nÿá¾‡úÜ³r|µc ¸œn §ŒbÙ¹‡±Í¥gÿŸw6ÿŠc$ÿhJÿjKÿ±„=ÿÕ¢PÿÖ§[ÿÙ®iÿÝ·zëÛ³r|Ì’9
ÑœI , êÅˆ Ô­qâ¿ˆ“Ü¹�ïÇ¢gÿ³ŽTÿ½˜]ÿ×±uòÕªg½Öªg¶×¬g‹Ñ S9ÁÈŒ1             Ù¬e Ó£Vàº~IãÀˆ äÂŠËåÃŒÀá¼‚hÂ�@®o¡M ¢Q             ð  À  €                                          €  À  à  (       @                                                                 ‚Q �\ …]«:eÃ•K¿ÉœTë¾•TðÅ�_ñÓ¨cóÐ£]ÙËœR­Â�Bi—i ®f·t                                                                 �n# •e¯�8a»ŽHÌÂ—SóÕ¦[ÿÔ£TÿÒ Qÿ×©`ÿÙ­gÿÚ¯lÿÛ²qÿÐ©løÀ�eÍÓ£W–É‘77·o¿~                                            ‚[ [9¥{9zÉšO÷ÐœIÿÊ“=ÿÇ�7ÿÃ‹3ÿÄŒ3ÿÍ–?ÿÐšDÿÒ�HÿÔ Oÿ×ªbÿÝ·zÿà»ƒÿÛ²rêÔ¡QŠÙš6Æ�A ý¿%                             m9Ì     H&†29'  ÿ ©|5t»ŒBñË•@ÿ»…1ÿ«y+ÿ¤t)ÿšm'ÿšm'ÿ­{,ÿ¼‡2ÿÇ�9ÿÏ™CÿÔ¢QÿÖ¥XÿÛ¯iÿÖ²yÿ¸›lþ™u<Ã³�26\aj Ã‚                     l8Ì p<Ð p;ÑDN)“°%—l%0»Š<åÅŽ7ÿ°},ÿ—k&ÿoOüT<ÜG3·G2³Z@ÑxUö¡r(ÿÃŒ5ÿÐ›GÿÔ¢Qÿ²ŠIÿ”…nÿ�xjÿ°˜rÿÙ°oÙÏ—>Bá¹z Æˆ(             p=Í n:Î n:Î6k9ÉÜ@"w¯  $U<�‰b'ÿ€[ÿnOÿQ:ë(
w         "OV=Ç˜l&ÿÅŒ3ÿ©=ÿœ”ˆÿ¶±«ÿº™eÿã½„ÿåÆ–ÿÛ±nÙÌ“86ÑœG ÄŠ-         n:Í n:Ín:ÎÂm9Ìÿ\0®òX-§åX.�õY0‘ÿM+{ÿ6Oÿ(¢  " :+dK#JlQ&hnZ<>'S;¹�d#ÿ�‚nÿÛÝßÿ®˜vÿÕ§^ÿÛ¯lÿá½†ÿåÆ•ÿØªaÂÍ�/Í”8     n;Ì n<Én:Î‰m9Îÿn9ÎÿuCÒÿQÕÿ†YØÿ…YÙÿQ×ÿsBÏÿ`3´ôB#}£ (jQ)_yZ(÷P:ÿ‘}]ðspkI -RF4áÊÊÉÿ×ÔÑÿ·“\ÿÚ«bÿØªbÿÜ²qÿãÁ�ÿß¾Šÿ¹ŒDvÿÓ… W8 m9Í m8Í7n:Îè}OÓÿ™tÝÿ©Šãÿ¬�äÿª‹äÿ¦†àÿ¡�ÛÿœyÜÿ�dÝÿo?ÇÿD#‚ª?3!M¡IíÄŸeÿÀ¨ƒàlcV*   †††ÈëìíÿÇ¿³ÿÀ“LÿÙ«cÿØªbÿØ«dÿà¹}ÿØ¼’ÿºžqÏÎ›J0Ì›M P»sAÏ—ŽeÙÿ§‡âÿ§‡ãÿ¡ßø¡~âÆ˜u§Èª�sÿšqXÿxY[ÿz_˜ÿ…^ÐÿT,¡ø/'­ u/ñâ½ƒÿ×¼’¼©_ (()'¬¬¬çôõöÿÀ´¢ÿÂ�=ÿØ©`ÿÙ¬fÿÚ¯jÿÞ¶xÿæÇ–ÿéÍ¡ÿØ«b—·j }OÒ(’kÛÝ£�áÿ¢áÿ£âÿ…h¹ÝK:s%¤x+3¼�FÜÉ”?ÿ¦v&ÿvT$ÿ`CEÿ[==ÿ…^(ÿÊ™LÿÞ¿�ýÁ¥zr†‰� 655C···õøøùÿ¹®�ÿ¾Œ=ÿÚ¬cÿÜ²pÿÜ²pÿÜ³rÿâÀ‰ÿéÏ¦ÿßºÞÏ˜A*•mÞ¡~â^¢á‰¢á¯£€âÐ‘rÊåJ9gdñÄù «‚@bÉœVïÌšKÿ¿Œ9ÿ³‚0ÿ¼Š7ÿÑ¡TÿÛ·þË¯�²®…E   <0®©§¤ÿêëìÿ¤œ�ÿ”n2ÿØ©`ÿÜ²qÿÜ²pÿÜ²oÿàº~ÿçË�ÿåÇ–ûÕ£Sl	 	    —sÿ­‡þ¦‚ë)bLŠ+   �g£|@KÅ�\ÂÍ¤cïÔªhüÖ¯rùÐ®yÞÈ§s�›wA¤v-"!+fIæ’q>ÿ©Œ]ÿ±‹Oÿ—o1ÿÐ¢YÿÜ²pÿÜ²pÿÜ²oÿÞ¶wÿåÆ”ÿãÉŸÿÉŸ\�zb=»Ÿ‚UÆŠpF¡t\7yZF%R6(/       Ð³o �q,®‰M5»–[O°ŽXE�o;%`H"¤z9{™n+œ 4rQë°}+ÿÌ–@ÿÔŸLÿÄ“EÿÔ£WÿÝ±lÿÜ±mÿÝ´rÿÞ¶wÿæÇ•ÿÒ¿ þ¬‘f­§ŒbòæÅ’ÿà¿ŒÿØ·„ÿÌ«yû¼�lð�xR†E7!)e<�x_7€lU1`VC%,sY1`‡j=y¢I¢¸‹EÙ©z1þƒ]!€2#^€[ ûµ�/ÿÏšGÿÔ¢RÿÖ£SÿÓ¤[ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò®”jýçÇ”ÿåÅ“ÿæÆ”ÿçÇ”ÿéÉ–ÿ¤�iéPC-ÃÒ®uþ×²vÿÆ¤mù†mFÛË¢aýÎ¡ZÿË—Fÿ´�0ÿˆ`"ßI4`_DÒ q(ÿÆŽ7ÿÕ¤Vÿ×¨]ÿÛ®eÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý°—oýçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿçÇ•ÿÁ¦|ÿ„oMÿà»€ÿß¹|ÿÛ³sÿ¿”QÿÊ”AÿÃ‹4ÿ¯|,ÿŠc#ü\B­L6Ì€[ ÿ®|,ÿÌ•=ÿÖ¦Yÿ×§\ÿÛ®dÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý®–pòçÇ•ÿåÅ“ÿåÄ‘ÿäÂŽÿãÀŠÿÛ·ÿÊ¢bÿØ¨^ÿÕ¤VÿÔ¡PÿÎ˜Cÿ¼…/ÿ§w*ÿŒd#ÿjKìC0àaEÿŽe$ÿ·‚.ÿÍ—BÿÔ OÿÔ¡PÿÕ¢SÿÓ¥\ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò¤ŽjÙá¾†ÿÞ¶xÿÜ³rÿÛ°mÿÚ®iÿÙ®hÿÖ¦YÿÓžLÿÓŸMÿÐœKÿÀ�<ÿ¢s)ÿ�e$ÿuSÿK5ùQ9þrQÿšm'ÿ»†1ÿÏšEÿÓŸLÿÓŸMÿÓŸLÿ×¨]ÿÝ²mÿÜ±mÿÝ´rÿÞ¶wÿçÉ™ÿÓÀ¢þ­’g­”^¬Û¶|ÿÙ¬eÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿØªaÿÒŸNÿÇ“Bÿµ‚3ÿ¬z,ÿ r(ÿ~Z ÿaEÿ@.ÿ^Cÿƒ]!ÿ£t)ÿÃ�7ÿÏ—?ÿÐ™BÿÒœHÿÓ OÿÚ®hÿÜ²qÿÜ²pÿÜ²oÿÞ¶xÿæÉšÿäË¤ÿÉŸ]�zgJlÕ¶†ûÚ¯iÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÔ¥[ÿ¿Œ<ÿ­z,ÿ«y+ÿ¨w*ÿŽe$ÿZ ÿR:ÿJ5ÿjKÿ�f%ÿ®|,ÿÈ�5ÿÏ–>ÿÏ—?ÿÏ—?ÿÔ¡QÿÛ°lÿÜ²pÿÜ²pÿÜ²oÿà¼‚ÿéÎ¤ÿæÈ™ûÕ£SkI9*ÃªƒÞß·yÿÙ­fÿÙ­hÿÖ©aÿË™KÿÁ‹5ÿ»„/ÿ®|,ÿ©x+ÿ’h%ÿ�\!ÿxVÿF1ÿV>ÿvTÿ–k&ÿ»…/ÿÉŽ2ÿË’7ÿÏ–>ÿÑšEÿ×§\ÿØ«dÿÚ®iÿÛ±nÿÝ´sÿäÄ�ÿëÓ¬ÿß¹~ÛÏ—@'   £�i–áÂ‘ÿØ¬fÿÎžQÿÃŽ:ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿšm'ÿ‚\!ÿ‚]!ÿiKÿB/ÿ_Dÿ€\ ÿ�p(ÿÀ‰0ÿÈŽ2ÿÈŽ2ÿÍ–?ÿÖ¦ZÿØªbÿØªbÿØªbÿÙ«dÿÞ·zÿçËŸÿèÍ£ÿ×©_� = „kC nX67Ï¶ŽéØ¯nÿ¿‰2ÿ¾†/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¬{,ÿ�e$ÿ…_"ÿ�\!ÿZ@ÿC/ÿdHÿˆa"ÿ¦v*ÿ¾‡0ÿÈ�4ÿÌ•>ÿÒŸNÿ×§]ÿØªbÿØªbÿØªaÿÚ­hÿá½…ÿèÌ¡ÿÞ·yÝÐšE+ÒžL '	    £ŠbŠßÂ“ÿÎ Vÿ¾‡1ÿ¾‡0ÿ¿‡0ÿ²~-ÿ‘h%ÿŒd$ÿŒd$ÿ‚]!ÿY@ÿL6ÿmNÿ“i%ÿµ‚1ÿÆ�9ÿÐœHÿÔ¢QÿÔ¢RÿÔ£Tÿ×¨^ÿØªbÿÙ¬fÿß¹~ÿæÈ™ÿà¼ƒ÷Ñ›HhòÐ› Ì—C     pW. [CÁ¦{ÂäÅ•ÿÏ VÿÀ‰3ÿµ�-ÿ•j&ÿ‹d$ÿŒd$ÿ�d$ÿyVÿbEÿ]Bÿ€[ ÿ­|,ÿË”>ÿÑšCÿÓžKÿÔ¢RÿÔ¢RÿÔ¢RÿÕ£TÿÙ¬eÿßºÿåÇ—ÿâÀŠüÓ¡QŽÆ‡#	Ì’7           Ç¢f Šl>6Ò¶‰ÙæÈ˜ÿÓ§bÿ§{4ÿ‹c$ÿ‹c#ÿŒd$ÿŠb#ÿmMÿcFÿ_CÿkLÿ˜m(ÿÉ”?ÿÑšCÿÒœFÿÔ¡QÿÔ¢RÿÕ£Tÿ×©_ÿÞ¶yÿåÇ—ÿà½„÷Ô¡RŽÊ�-Í“9                 + ÿÿê ª‡NBÝ¾�ÙæÉšÿÔ­pÿµ‹Hÿšq/ÿŽf&ÿ€[ ÿcFÿaDÿaDÿ`Dÿ‰f.ÿÓ¤XÿÕ£SÿÓŸMÿÖ¦ZÿÙ¬fÿÜ´tÿà»�ÿÞ¹ÿØ­hÝÑœJgÇˆ&	Ë�3                         mI ÿÿÿ Î V6à¼ƒÃçÉ›þãÁ‹ÿÕ­mÿÂ˜Uÿ¦~>ÿ�i1ÿŠg0ÿ•p6ÿ°‡FÿÏ¡Xÿß¹}ÿÛ´vÿØ®lÿÛ´vÿÞ¸}ÿÛ´uùÖ©bÙÎšG‹ÆŠ,)­V À}                                 ±p Ý²m ÐœIÛ²q‹äÄ‘ëçËžÿåÆ”ÿàº}ÿÜ³rÿÛ±oÿÝ´sÿá»~ÿãÁŒÿãÃ�ðÍŸWŠÂ‘D‰Æ•H‘Í™F{É‘9OÂ…%¬e ¶r                                                 Ì’6 Å„"Ô¤V9Ü´t—âÀŠÛäÅ”÷æÈ™ÿæÊœÿçÊ�ÿæÉ›úá¿ˆ×Ù®ifÉ�.ÐšF                                                                                 Ê‹( À~Ð›F$Ö§[WÙ®h‚Û±n”Ú°m‰Øªb`Ñ�K"ºn Å…#                                                     ÿÀÿÿ€ ÿ  ?ù  ð  à  À €  €                 À                                      €  €  À  à  ð  ø  ü  þ ÿÿ€?ÿ(   0   `           $                                                                                  ?, Ê�+ ¦t$¯|,e¶…7¨¼�A×Â“Hó§�Dß¯‰LàÍžT÷ÊšNæÇ•FÌÃ�=£¿ˆ2nº‚(6¼ƒ"   õàX                                                                                                                 ”d uE ¡q%'šo,t™u<³ËŸYûÔ©dÿ×¬gÿÙ­fÿÏ¥bÿÓ­pÿÞ·zÿÝ·zÿÜ¶zÿÚ³uÿÕ¬küÏ¢Zê¨~<¢šo*LÆŠ*(¾}Â„                                                                                                      �n# ˜i¥v,d¶‰AÛÇšTþÂ˜Uþ×¨]ÿÕ£TÿÒŸMÿÐœHÿÑ�IÿÖ¥XÿÖ§\ÿ×©_ÿØ«dÿÚ¯kÿÜ³sÿÞ·zÿ¼žnúÏ«t÷Ô¤ZâË”<�ÅŠ+.¿Â…$                                                                                         Šb! }T¨z1†Á”L÷Ô¤XÿÓžKÿÎ˜AÿÍ–?ÿÊ’8ÿÈ�4ÿÇ�2ÿÈ�4ÿÐ˜AÿÑ›DÿÒ›EÿÒœGÿÓŸLÿÕ£TÿØªbÿÝµwÿá½…ÿãÂŽÿÞ¹~ÿÒ¢WãÉ�7|Ã‡(ÇŒ/ ¼                                                             H*t <$`$    šm& ¤s%
ˆb&n©‚DæÕ£TÿÏ˜BÿÅŽ7ÿ¼†1ÿ»…/ÿ¹„.ÿ¶�-ÿ´€-ÿ¶‚.ÿÂŒ5ÿÇ�9ÿË”=ÿÏ˜AÿÑšCÿÑšCÿÔ¡Pÿ×¨]ÿÚ¯kÿÝµwÿá½…ÿãÃ�ÿÜ´týÒœGÀÐ“3;íšÙ—/                                                     o<Î žUÿK(‹^-S8_ «‚> žq)h¸ŠA÷Æ“CÿË”<ÿÀ‰3ÿ²-ÿ¦v*ÿ r)ÿ�p(ÿ–j&ÿ’h%ÿ•j&ÿ¥u)ÿ°},ÿº„/ÿÂ‹4ÿÉ’:ÿÑœGÿÔ¢RÿÔ¢QÿÔ£Sÿ×¨^ÿÝ³pÿÕ¯uÿ¹Ÿvÿ”{Tÿ‰e,ã±0_ë§;Ê‘6                                             m9Í l8Ìo:ÐtF%ƒÓ)R9 ˜k$'°‚:ÚÎšGÿÅŒ2ÿ·‚.ÿ¬z,ÿœo(ÿˆ`"ÿoNÿ\BýM7òG2éK5î_CúvTÿ’h%ÿªx+ÿ¼…/ÿÊ’9ÿÑ�JÿÔ¢RÿÕ¢RÿÓ¡Qÿ¥€Dÿ{mWÿxtpÿ`VGÿ¶Ÿ{ÿÖ«eñÎ•;rÆŠ,É�4                                     n;Í o<Ìn:Ïrh7Ãø2\Ÿ   ÄŠ0 |X³ƒ5ÿ¾ˆ4ÿ±~,ÿ¡s)ÿ‘g%ÿvSÿI3õ&
´f9   *1Q&
“F2ßrQÿ¡r)ÿ¿ˆ0ÿÉ�5ÿÐ›GÿÐŸOÿŠl;ÿ€{sÿ¿ÀÁÿ�‚oÿËªwÿçÆ”ÿèÌŸÿÙ­gôÍ”:rÈŽ2Ë“:                             m9Ì {Eç n:Í^o;Ðñ]1®ÿ,   %5L6Î€[ÿwUÿjLÿcGÿX?ÿ5&ä`   
                     )*žeHø�p(ÿ¿‡0ÿÈ�4ÿ†f4ÿˆ…‚ÿäåæÿ ˜Œÿ¸�SÿÞ´rÿà¼„ÿäÄ’ÿçËŸÿ×ªañÌ’7_ÿÿ� È�7                     q?Î m:Í n:Í<n:Îâo:Ïÿe5½ÿM)‘ïN)’çM)�êN*†üP,~ÿH)lÿ:"Pÿ&,ÿøc#         	  4(I81?1&   
!cF÷¤t)ÿ’h&ÿ{ulÿáâãÿÔÓÓÿ—}SÿÙªaÿØªbÿÜ³sÿá¼…ÿåÆ•ÿæÉ›ÿÔ£TâÊ�3<Ì’7 Ê‘8                 n;Í n;Ìn:Î¿n:Îÿn:Îÿn:Ïÿo:Ðÿn9Ðÿn8Ðÿn8Ñÿm8Ñÿm8Ðÿk7Ìÿd4½ÿO*–û6e¹%G    fM$ƒvX'ÜmP#îx[.æ…u[­AAA)   )“iJÿdWBÿÉÉÊÿ÷÷øÿ¨¢˜ÿº’SÿÚ«cÿØªbÿØ«cÿÝ¶xÿá½‡ÿçÊœÿãÁŒÿÑ›E¾Ï“6Ð—< ®{*         n<É _�  n:Í{n:Îþn:Îÿm8Îÿm9ÎÿsAÐÿQÔÿ‰_×ÿ�fÙÿ�gÙÿŠ`×ÿ�TÕÿwEÒÿp;Ñÿi7ÆÿO)“î"@x   $=“o6ódHÿ-
ÿM9ÿº§‰ÿa`]„´±¬  &Ï”“�ÿèèéÿôôöÿ”…lÿÐ£\ÿØªbÿØªbÿØªbÿÙ¬fÿß¹ÿâ¿ŠÿéÎ£ÿÐ©kù¦v*T°2 _=         n;Í n;Í.n:Îàm8Îÿq>Ïÿ…ZÖÿ¢€ßÿ³—æÿ·œçÿ´˜æÿ°“æÿ®�æÿ­Žæÿ«‹æÿ¦…ãÿ—pÝÿ}OÔÿo;ÐÿV-¡÷!?s   hBºÀ™[ÿÁ—VÿÌ§kÿº¨‹çFDAAlha    III«ÈÈÈÿñññÿççèÿ“xMÿÖ¦YÿØªbÿØªbÿØªbÿØªaÿÛ°nÿá¼„ÿáÂ‘ÿ¦”xù™zI¤Ð›G$È–H     m9Ì m:Êm9Í�n;Îÿ„XÕÿ§‡áÿ´™æÿ­Žäÿ¥ƒâÿ¢áÿ¡~áÿ�{Úÿ›yÊÿ–t¹ÿ�m°ÿŠl¸ÿ™yÒÿ£�ãÿ‰^Øÿp<ÏÿG%‡ê>:*Š©€@ÿÞµuÿäÌ¦ÿÂ§}¼g. %
    zzy×ÜÜÜÿøøøÿÚÚÚÿ˜u=ÿÕ MÿØªbÿØªbÿØªbÿØªcÿÙ­gÿà¼‚ÿäÄ“ÿçÑ­ÿáÀ‹ÿÓŸN�Ë”;ÑžL m9Ì l7Ë(r@Ïá’kÚÿ¬�äÿ§†ãÿ¢~áÿ¡~áÿ¡~ßø¢áËž{ÜŠŠikÉ²ˆWÿ²‚>ÿ˜m/ÿvU+ÿW@?ÿnU“ÿ–sØÿwIÍÿO'œÿ/ÉaEß¼ˆ6ÿÜ²pÿêÒ¬ÿÈ¨uŸ    4˜——ïãããÿüüüÿÒÑÐÿžw9ÿÒšAÿ×¨_ÿÙ«dÿÚ­hÿÛ°mÿÜ±oÿÞ·zÿäÄ‘ÿèÌ ÿëÔ®ÿØªbáÐšE(ÒžM ‡[Ø xHÐs“lÛÿ¥„âÿ¢áÿ¢áÿ¢áÿ¡~ßÿpWœÉ^I�“j ¤v)[À“KõÎ›JÿÃŒ5ÿªy*ÿ„^ÿX?ÿL5JÿH-\ÿ@(:ÿ`C!ÿ¥u*ÿÎ›Jÿá¾‡ÿÕÀ�ô²�TXÀ¢r **) $##G¥¥¥øåååÿþþþÿÏÎÌÿ y:ÿÒš@ÿØ©`ÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿâ¿‰ÿæÆ•ÿìÖ²ÿà¼‚ÿÒ�JrÕ¡N l;Ç“lÛš¢áî¢áú¢áÿ¢áÿ¢áÿ£€ãÿw\¥ï!A:+0 ¡n�l2ƒÆœZýÔ NÿÃŒ5ÿ±~-ÿ�o'ÿŠb ÿ†_ÿ—l$ÿ´�/ÿË–CÿÜ³rÿåÊ ÿ½Ÿq¯c: E2    �¥¥¥ÿæææÿþþþÿÌÌÌÿsY1ÿË˜HÿØ©^ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿß¹~ÿåÅ’ÿêÐ§ÿèÍ¡ÿÕ£U»Ï™DˆbÌ¡~ß¡~à.¡}àN¡~àt¡~à›¢~á¿¢âÜ™xÕôL;k®   oP  Ÿp&¸ŒE¹Ê ]þÒ£XÿÎ™EÿÅ�9ÿÂŒ7ÿÃ�7ÿË•?ÿÔ¢Sÿß·yÿÜ¾�þ½£xÆ±…@4·‘X %	 VA1ö›š™ÿÜÝßÿôõöÿÁÀ¾ÿeM'ÿšs6ÿØ¦XÿÜ²oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÝµuÿäÃ�ÿçÊœÿìÖ²ÿÙ­gèÐšF6                žyß štßžzß
 }ß¤�å9kS–O §x.  p$•r;|ÆžaìÕ«jÿÕ«hÿÚ®gÿÙ®jÿß¸{ÿÙ·‚þÑ´…ôÅ¢k°�h.&i žq*    +�uTÿy`7ÿ‰uTÿ–‚cÿ™~Rÿ§|7ÿ‚a+ÿÔ¢SÿÛ°mÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²qÿâ¿‰ÿæÆ–ÿí×´ÿáº~üÐœHn#Q8*d? "                                  ¤q" šg­5@ª„H„¸•^»Î¨mÜ»›iÏÉ¦nËº–^™—t=D¬u"  œt4M—m)€   - —…_"ÿ¨w)ÿ¼†0ÿÌ˜EÿÔŸLÿÆ”Dÿ•o2ÿÒ PÿÛ¯kÿÜ²qÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà»�ÿåÆ”ÿãÌ§ÿ°˜tï•o3YbN.Ëº˜dÿ«ŒZô”wJâ|b:ÆdN+¤K:}1$W5                    e9 5  œh¯{)�n#¢g­J    SA%(›w=†©|3î‡`"—    0" †_"ÿ©x*ÿÁŠ4ÿÑœIÿÓŸMÿÒžLÿÍšJÿÓ OÿÚ®iÿÜ°mÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá¼ƒÿèËŸÿàË«ÿ´¥�õ¶�T›{eAçåÄ�ÿèÇ”ÿæÅ‘ÿâÀ‹ÿÙ·�ÿË©tÿ¸˜eü£…Tò�h@¡	7*C3g5(Z%D5		''5D3KhQ,r‘rA©´‹Jã¾‹;þ•j&þwUb   C/Ì�e$ÿ«y+ÿÂ‹5ÿÑ�KÿÓŸNÿÓ NÿÔ OÿÕ£TÿÖ§]ÿ»‹?ÿ¨|6ÿº’SÿÛ¶zÿà»ÿâÀ‰ÿéÏ¥ÿîÙ¸ÿòßÁÿÚ¯iæ†oKõåÅ’ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿæÆ•ÿçÇ•ÿêÈ•ÿ¹žtõ!WUE-z¸–`ý¹–]ý­‹V÷¥„Pò{c<¢aL+¢€Iê®ŠQð¼–YùÊ ^ÿÎ�QÿÅŽ9ÿ¢s(ÿ{XÙhJ"&
ojKû¡r(ÿ¹„/ÿË”=ÿÕ¤WÿÖ¦YÿÖ¦Zÿ×¨\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö�vRþæÆ”ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿÓ¶‡ÿ0)Þ]N5éà»€ÿâ½‚ÿã½�ÿå¿‚ÿ¢‡\ú~fAöàµqÿÛ¯iÿÓ¢VÿÉ“>ÿÀˆ1ÿ¦v*ÿ‚]!ýqQx!	TU=êŒc#ÿ¬z,ÿÅ�3ÿÑœGÿ×¨]ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�yVþçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿäÄ“ÿ]O;ÿˆrNÿä¾‚ÿà»�ÿà»�ÿá¼€ÿÌ¨oÿ·�PÿÎ›KÿÆ�9ÿÄŠ1ÿ¾†/ÿ¥v*ÿ‡`"ÿsRÆ1#mK5åvSÿ™m'ÿ´.ÿÊ‘6ÿÓ¡Pÿ×¨^ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�xWõæÇ—ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ”ÿèÇ•ÿ¤Œgÿºšhÿá¹{ÿÝ´sÿÚ®iÿ×¨^ÿÕ¢SÿÈ‘:ÿÃ‰0ÿÃŠ1ÿ¸‚.ÿ r)ÿŠb#ÿuTóH4¦>,äbEÿ�\ ÿžp(ÿ¹ƒ.ÿÈ�7ÿÓ OÿÕ£UÿÕ¥WÿÖ¦Yÿ×§\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö…qRçåÇ˜ÿåÅ“ÿåÅ”ÿåÅ“ÿåÄ’ÿäÃ�ÿãÁ‹ÿá¾†ÿàºÿÖ¯pÿÓ¤YÿÕ£SÿÓ OÿÓŸMÿÓŸLÿÓŸMÿÌ–@ÿ¿ˆ0ÿ®{,ÿ›n'ÿ�e$ÿxVÿ]Cß<+çP9ÿkLÿ‰a#ÿ¥u*ÿÀˆ0ÿË•?ÿÓŸMÿÓŸMÿÓŸMÿÓŸNÿÓ OÿÕ£Tÿ×¨^ÿ»‹?ÿ¨|6ÿ»’SÿÛ¶{ÿà»ÿâ¿‰ÿéÎ¥ÿîÙ¸ÿòßÁÿÚ¯iæxeIËáÄ–ÿâ¾‡ÿà»�ÿÞ·zÿÜ´tÿÛ±nÿÚ¯jÿÙ­hÿÙ­gÿÙ¬eÿÔ¢RÿÓŸLÿÓŸMÿÓŸMÿÓŸMÿÒžLÿÄ‘?ÿ¤u*ÿ–k&ÿ‘g%ÿ{WÿkLýB/õJ5ÿ_CÿtSÿ‘g%ÿ¬z+ÿ¼†1ÿÏšEÿÓŸMÿÓŸMÿÓŸMÿÓŸMÿÓŸLÿÕ£TÿÛ°mÿÜ°lÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá½…ÿéÍ¢ÿàÌ­ÿµ¦�õ¶�T›dS8£Ø»�ÿÛ°lÿÙ­gÿÙ­fÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÖ¥YÿÓŸMÿÓŸMÿÓŸMÿË—Fÿ¹‡7ÿ­{-ÿ¤t)ÿ•j&ÿ}Y ÿsRÿT<ÿ9(ÿS;ÿlLÿZ ÿ˜l'ÿ³-ÿÃ�7ÿÏ—@ÿÐšDÿÒ�JÿÓŸMÿÓŸMÿÓŸMÿ×¨]ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿá½…ÿçÊ›ÿäÎ¬ÿ°™vï”n3YI:#nÊ±‰üÞ¶vÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿØªaÿÔ OÿÎ›Iÿ¾‹;ÿ¯}.ÿªy+ÿ«y+ÿ©x+ÿ�d$ÿuTÿlMÿ@-ÿC0ÿX?ÿvTÿŠb#ÿ¡s)ÿ±.ÿÌ•=ÿÏ—?ÿÏ—?ÿÏ˜@ÿÑ›FÿÒžKÿÔ PÿÚ®hÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿãÂŽÿçÊ�ÿîÚ¹ÿá»üÐ›Hn!6²›wèäÁŠÿÙ¬fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ®hÿØ«cÿÈ•Fÿ²€1ÿ«y+ÿ«y+ÿ«y+ÿ«y+ÿ—k&ÿ‚]!ÿ€[!ÿ`Dÿ:)ÿO8ÿbFÿxUÿ˜l'ÿ¥v*ÿ»…/ÿÌ“9ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ˜AÿÕ£UÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÞ¶wÿåÇ–ÿèÎ£ÿíØ¶ÿÙ­gèÑ›F5   �yW»åÉ�ÿÚ¯lÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­hÿÙ¬fÿÑ¢XÿÆ‘?ÿ»…0ÿ­{+ÿ«y+ÿ«y+ÿ«y+ÿœo'ÿƒ^"ÿ�\!ÿ[!ÿN7ÿ@.ÿV>ÿmNÿ~Y ÿ�p(ÿ®|,ÿÆ�2ÿÈ�3ÿÌ”:ÿÏ—?ÿÏ—?ÿÏ—?ÿÐšDÿ×§\ÿÙ¬fÿÛ°lÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà¼ƒÿæÉšÿëÔ®ÿèÍ¢ÿÔ£T¹ÎšGâ¶q cO1r×¿™ÿà»�ÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÔ¦]ÿÉ–FÿÀ‰3ÿ¾†/ÿ¾‡0ÿ¸‚.ÿ¬z+ÿ«y+ÿ r(ÿ†_"ÿ�\!ÿ‚]!ÿuTÿ?-ÿH3ÿ^CÿsRÿ‰b#ÿšn'ÿº„/ÿÉŽ2ÿÈŽ2ÿÉ�3ÿÍ•<ÿÏ—?ÿÐ˜AÿÕ¤VÿØªbÿØªbÿØªcÿÙ­gÿÛ±mÿÜ²pÿÝ´sÿäÄ‘ÿçË�ÿîÙ¹ÿßºþÑ�IlÔ N 3' '(²šuàéÍ¢ÿÚ°lÿÙ­gÿÖ©aÿÌšLÿÁ‹6ÿ¾‡/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ·‚.ÿ¥u*ÿ‰a#ÿ€\!ÿ�\!ÿ‚]!ÿeHÿ:)ÿN8ÿeHÿxUÿ‘g%ÿ�p(ÿ¿ˆ0ÿÈŽ2ÿÈŽ2ÿÈŽ2ÿÉ�4ÿÎ—?ÿÔ¢TÿØªbÿØªbÿØªbÿØªbÿØªbÿØ«dÿÚ®iÿàºÿæÈ™ÿêÑ©ÿëÓ­ÿ×¨]ØÐ›F!ÒžM     }eA�áÊ¥ÿá¾‡ÿÑ¡VÿÃŽ;ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿ•j&ÿ‚]!ÿ�\!ÿ�\!ÿ[ ÿV=ÿ;*ÿQ:ÿiKÿ~Z ÿ•j&ÿ¥v*ÿ½‡0ÿÇŽ2ÿÈŽ2ÿÈŽ2ÿÊ‘6ÿÑ�KÿØ©`ÿØªbÿØªbÿØªbÿØªbÿØªbÿØªaÿÙ­hÿá¾†ÿåÈ˜ÿíÙ¸ÿà¼‚ÿÒžK|á«R ÏœM     K8 9(.·�uáêÏ¥ÿÑ£[ÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¼†/ÿŸr)ÿŒd$ÿŠc#ÿ…_"ÿ‚]!ÿvTÿL7ÿ=+ÿT<ÿlMÿ„^!ÿ—l&ÿ®|,ÿº…/ÿÄ‹1ÿÉ�4ÿÌ–>ÿÒŸMÿÔ¢RÿÕ¥XÿØªaÿØªbÿØªbÿØªbÿØªbÿØ«dÿÞ¸{ÿâÀŠÿçÌ ÿæÈ™ÿÔ£UËÐ›GÑžL              x_8}ÙÀ—þåÅ“ÿÍœPÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ½‡0ÿ¥v*ÿ�d$ÿŒd$ÿŒd$ÿŒd$ÿŠb#ÿoOÿO8ÿ?-ÿU<ÿmNÿˆa"ÿ›o'ÿ¶‚/ÿ¾‰3ÿÈ’<ÿÑžKÿÔ¢QÿÔ¢RÿÔ¢RÿÔ¢RÿÖ¦ZÿØªbÿØªbÿØªbÿØªbÿÝµuÿâ¿‰ÿåÇ—ÿèÎ¤ÿÖ§]ðÌ“:QÐ–: Í™H             :* ! £‡Z¾èÐ©ÿá¾‡ÿÌ›Oÿ¿ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ«z+ÿŽf%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿˆa#ÿjKÿ_CÿT;ÿgIÿ‚]!ÿ r(ÿµ‚0ÿË•>ÿÏ™BÿÑ›FÿÔ¡QÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢SÿÖ§\ÿØªbÿØªcÿÜ´tÿá¿ˆÿäÅ”ÿéÐ§ÿÚ°mûÎ–=‚Ë‘7Í•=                     Žl7 ]E;À£tâìÓ­ÿà¼ƒÿÏŸTÿÀŠ4ÿ¾‡/ÿ°}-ÿ‘g%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿ�d$ÿZ ÿdGÿcFÿZ@ÿhJÿ‰b#ÿªy+ÿÀ‹5ÿÐ™CÿÑšCÿÑšCÿÓŸMÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢Sÿ×©`ÿÝ¶wÿâ¿ˆÿåÆ”ÿéÏ¦ÿÜ³sýÏ˜AšÊ‘6Í”;                          ÿÿÿ €b3_Ñ³„ñìÔ®ÿá¾†ÿÔ§_ÿ½‹;ÿ”j&ÿ‹c#ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿrQÿbFÿcFÿ_Dÿ]BÿxVÿ�p(ÿ»†2ÿÏ˜AÿÑšCÿÑšCÿÒ�IÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢QÿÔ¢RÿÖ¦[ÿÛ±oÿá¾‡ÿæÉšÿèÎ£ÿÛ±nûÏ˜AšÎ•;Î–>                                 7(    šxArÚ»‹ôìÕ°ÿãÁŒÿÔ©fÿ±‡Dÿ”l+ÿ‹c#ÿ‹c#ÿŒd$ÿŒd$ÿ†`"ÿhJÿcFÿcFÿcFÿ_Cÿ_DÿjKÿ¬€9ÿÓŸMÿÑšDÿÑšBÿÑ›DÿÓ OÿÔ¢RÿÔ£TÿÖ§[ÿÙ­hÿÜ³tÿß¹~ÿäÅ“ÿäÅ”ÿ×©`ðÎ–?�Ê‘7Ì“9 _'                                      _F ( ²‰IqÞ½ˆñëÒ¬ÿäÃ�ÿÜ³sÿË [ÿ¯…Bÿ—o.ÿ�e%ÿ‹c#ÿzWÿbEÿbEÿbEÿbEÿaEÿ_CÿtV'ÿÈ™NÿÚ­fÿÖ¦ZÿÔ OÿÔ OÿÖ¦ZÿÙ¬fÿÛ°nÿÝµwÿßº�ÿâÁŒÿáÀ‹ÿ×¬hýÎ™EÊÌ”:PÊ�6Ë’8                                                 œs1 wQÏžP_Þ¸zãéÏ¦ÿçËŸÿá½„ÿÛ²pÿÐ¥`ÿ½“Oÿ«�>ÿˆd,ÿsS"ÿoP ÿpQ!ÿwW%ÿ‰f/ÿ«‚BÿÌœPÿØ©_ÿàºÿà»‚ÿÜ´tÿÜ³rÿÞ¶xÿá¾†ÿâÀ‹ÿâÀ‹ÿÞº€ÿ×ªeüÍ™FÕÇ�2xÄ‰*ÌŽ- ¿‡/                                                         Î˜B Á~Ñ�K<Ù®iÁåÆ–ýêÒ«ÿæÉ›ÿá¾†ÿÞ¶wÿÚ¯lÿÒ¥]ÿËžVÿÇšTÿÇ›TÿÎ XÿÖ¨^ÿÚ­dÿÚ­gÿß¹}ÿçÊœÿÔ«jóËžVöÏ¤`þÐ¦dÿÕªfýÔ¥\ôÏœKÜÊ“;«Å‹/bÃ‡)½�%¿„'                                                                     µz# Ö£R Î™CÕ¤W€Þ·yåçËžÿëÓ­ÿéÎ¤ÿäÃ�ÿà»€ÿß·yÿÞ¶vÿÞ¶uÿÞ·xÿßº~ÿâ¿ˆÿäÄ‘ÿéÎ£ÿá¾†ïÎœL`¶'C¸‚,`¹ƒ-eÁˆ-YÅ‰+=Ã‡'Á„#ÈŒ) ¦g                                                                                     Í•= È�2ÐœH0Ö¦Z’ÝµváäÅ“ýèÍ¢ÿéÏ§ÿéÏ¦ÿèÎ£ÿèÍ£ÿéÏ¦ÿêÑ«ÿëÓ­ÿæÉ›ÿÞ·yåÔ¤VhÊ‘6Ð›H                                                                                                                             Î–< Ê�5Ð›F&Ó¡Qj×©`¬Û²p×ß¹~íá¿‡öâÁŒùâÀŠöà»�ëÛ²qÎÖ§[�Ñ�K2Ê�5Î—A                                                                                                                                         œ= â¶S ÉŽ4Ï˜AÑœG;ÒžLQÒžLXÑžKPÐ›G7Î–=Ä„$Ç‹,                                                                                         ÿÿÀ ÿÿ  ÿþ  ÿ  ÿü  ÿ  ÿø  ÿ  ÿ0   ÿ  þ0     ü    ?  ø      ø €   ð <    à     à     À     €     €     €              0    ø     ü       ?€                                                                                            €      €      €      À      à      à      ð      ø      ø    ?  ü      þ   ÿ  ÿ   ÿ  ÿÀ  ÿ  ÿà ÿÿ  ÿø ÿÿ  ÿÿ ÿÿ  ‰PNG

   IHDR         \r¨f  € IDATxÚì}wœå™ÿ÷�ª.moöº¬;®‚ÁØ„ÐB	Ž$€Ó+I(ù]r	wÀÝåîRH%…�5	�\$@(¡0Ýlã¾öö¦®éïï�ÑhUFÒhW[Lüý|ÖÞ�F3£yž÷y¾OŽáŽáŽáŽáŽáŽádªOàÊcÃõ÷‡˜Æ–€ÝkFOTîO©çŸ¼Cžêó<†£ÇÀcÃõ÷‡hMÝ¬P °ŒaÈ
Ý �„�v AÏ¶k­srCSƒ°t
,Öºß0èÖp4ºÝxðW»Ž)ˆc°Ã10‰Øpýý!ÒÔ¶šg¹UA7·VÑéJŽeæNÆgkºñ¥t;�¥¤gŸúâÚÎ©¾Ç0õ8¦ &–À‡<âûŠÓ8–Y5ÕçdAÓ�7‚¿‡#w?{ÕÉ[§ú|ŽajpLTº¥�ã„KÝ{CõSŽgªy|.ïÓèø�©éÆþ”¢ß¢iÊ=Ç,ƒ,S U@–Ð_:ÖU>äâpq¹9E!77ÏÂ#0à¯À‚gí¿.U§H(:Tƒ"©ˆÊÂ)IÇ`BÁHRu¤(M5t0wG¢Ñï³
þ1pLŒ®¿?œ5ç ä“ËœZÉ{¼<Z"š¼ý"¼|Qá®T�b8©¢'*ãHTÅ�á$Í(ùô�ýÃá?¦ÞÝ8¦ *Ä)?|nE0¸Æ-pç8eè›}<f×ºÑr¡5 L¨°;E_LÁ;ƒ)ìêO",iE÷S5ýÎè¡_yæÆÂS}ÎÇP}Lý“x”à¼_o½ÌéjïâÌ«saN­í5.xÒ ªN¡Šf@5L›Ý0(ô"æ;K †!àók8Ó]¨DÁ$U=Q;ûSØ3�°u8†IŠvÕƒŸXq÷$ßöc˜`S %°~Óf±ö²k.!7–×¹8K=XÚìÅŒ ˜`;$UŠf@ÖH…fPõ*°yYpó&gàáST	%ÕQW@Ñ¼ÑÇŽ¾„­‹ jú�#wÿ3Çr
Þ=8¦ l°~ÓfÑýOW}Å-°Ÿ-%øæ7x±¬Ù‹yu.pì¨�¥T=ó{R5“4HÍÙ>Ùpó,‚.6‡PÌV ,Eðfw¬À"Ðtã�X2uÁ±hÁ»Ç@,Á¯ñ
ÿ\Ê¿¹8¬žáÃÊ6?Ü<[ðzJÕ3,üT
|)dGÎÞ:ˆIžÞAgXÊÙ®éÆþX2µñ˜8úqL¤‘öñKšúóëÜXÓ@G�»à5Kè“ê¨9_‰ð«…®›«±F	´ôï¥\	 ÿŸcp„‚e™Ì6'ˆ+|ƒ:/¯ÀÚîóv_ÏíÉ±Ž)�wþáÀ©?{åô€[üv±ø=G€%Í>œ<'ˆ:Ÿóš¦ˆÈ¦àÛùðÅ€¤ê�4“ðÓt
Å¨®ÿo�·E
º8o/ÜqeÔ9‚F/¿‹+Øo ®â¡]CH(£×¤éÆ‘ƒû7‹½ø‡U º¥½Îïù�r¡ÝëV¶ú±~N�<�ˆJÂ’†¤R:–®’ª9íû+šQ•Ì½±B`Ü<¯Èf¬„¸Í5øÍ~¡À5H(:Ú9„�„šÙÆ€þñW,ûÐÔ]Õ1Œÿp
Àòó½<þÛ.M·˜à—[í³‘RõÌ*‘§'ÀdLþlò25n-1g›¢¸ÿ­Á% iúåÇB„G'þ¡À)?|nE(¼­˜¹¿´Éƒ59¦¾¦H¨ˆH¥9¥êˆ+F�ÙïtÕ7zÚ÷×©ù+§Ù¸œåû3 K8–K(Æyé�aˆÊ¼‚°#4EŽ`fPÌ±ÍÀ}Û2	Dšnì¾ë¦%váÁõ›6‹ÌyŸZÔwh_jœ+xõº®µ €¡H�ùû3‚« X–ëQ’ÑA—7Ðçóˆ½„»�ñÕÇ?„Øpýý¡š9s¿É0ÌWí^o¹pÆ‚šœÕÎ‰à[+}¬„+ é’¦gÓ0L—@Ö)4ƒBÕ�LP5`%ñ,G rÅk,`¡”"h¹G-¢pJÃïßìË(·XJýÚãŸ]õ��?ÝÒK©TM{Ç«´TlÙX¯…< Ü¨2¦”FÐCšª¼¡ËÉíõ[i_×+Ç8ˆ±ã]¯ Ò$ß/ìØý�‹Ã¦y!,möe¶•|Í�é;ZM§N©�4Šdº`g²a��…‡gr”Q¶°Ô¸ù× ÁË£Á7*�ïô'ðøÞ°ußöïÛ€åD×¬j�7ë	:Ú�Pc»¦*oð÷„ßÍ?sÌRpŽw­X¿i³XÅµÿi·ês8af ›:B™‡ÜòñâªíñŠ™øvˆËd�"&kÐ)ªºÂW~��_ä rÄV ¦kQë.Œäó~{�a	á„„¡¡¡ª�cþê_	5¶SÃx8àÿ¦ýáæg�e.Ç»R”òõ["ÎYT›óG%	µh(/œÒJ
°eæGåâ
Â.ãnªaE6a?‘Aƒ/—Ì¶Â)¿y£=C$ñ²ŸéxE^vô~
<%}ß:§KHr�ªÜ3JiÔPåûkÞ»�)ƒB¼ëÀy¿ÞzãŽ|†Ÿ#ÀÆŽNœÊlK©:úb
$–.*kHÈ¥Mö¸¬•úlLG ˜¡=Ž >‘+ªD– Ù/ä¸3ƒBÆ:xl÷0ž~»’¬d^o¯ñ èá9]Ü‹¢8–�O0÷�+")1YÇ@BEXÒNH§4GÇÊ†¥”pÿ­;ÿç’ç§úÞO¼kÀ†ëïfÍùÏ±Wä¿ÖráÜ%uv¿”Ÿ_nÅW41YÏ˜÷N1ÝÜ Ù‰=ê½<Î&`£æÕ¹ pz¢2~ýü^´´5Ô¡ÎËW”�˜�R‰K$UG_BCOTF_$itÇuFÓœ+B�ír<|g�¡üê™D|W(€´ÉÿÇ|¢ÏnÕ/fî—üJVûb(fÈª=…šˆ"ž’AÔÉÌ¿W¥DÎ¾¼Ë \.x!PÁw b�)†l`ÁêN”�|%à´×¸ hvõ'Ç|_
>ßÍUüÕ è�)8‘qd ‚ž¤3‹Ë²
‚.ö²ÒQ¯ ÎûõÖË\÷Ãüâ�/�Ž«ÏøúÅV}Í00’*^´‘tŒ$•ŠVûbHÄ"ˆŽc¤¿R¸ƒ±”èŒ<!/B¬iBSC=¼¡:„ZÚá	Ô”?'Åþº]ƒZŸÉ7°àX4û…Ìß3ƒt
tŽH(‡låªeÝP.¦ä’cþ�qÅÀ¾¡ÆŒÎ°ìè€,!OÄûÝø�äÕ
à‚Û·}×Žå_ÚäÁyKê3+UJÕÑUrV}+œgÃ×tŠˆ¤UlæçÃøD4ŒÃýÃP#�ú'/BÅ¸¼hm›ÿÌ…¨ŸÙak%S €iA5úÅ%Pïát›î”È™=¬è‰ÕÐ$¥QÈšÍ Mw|ýâh¨R`8–”­g(‡¸b`÷@o÷Dq,!OxEæ;OaõãòÅL#•
`Ãõ÷‡::þ7?�Ÿ#ÀY‹ê°ªÍŸÙÖ•VýRßPB³à«ŠŒ�á’ƒ]8Ü?C.4‹“]{@õÊ	¬ñ‚°Úfw eÁr[FCõ¥€uOí”À¬�˜£`‡*ªUÙr•6ÿEŽÀ'rf£Ô¬š§è‰*ØÑ—ÀÞÁ$ÊqÿÁQ§ :>wóÜãÖžò‡ü_ÈÅáâå“ßŽá/eî�ÕÔWƒ½ÝéïEÏÀ`Ùý•È ÔÈÀ”ÞCÎÂ‚«Ñ4yÙæ €é4ú„œmÙ®Àî�ä¸ x–�·Â.ê"GàâXø]\E®ƒ¤êx«?åÈ*`	yÂM”¯¾9‚£J´žÿ•uKO9û/¾†¶n­ZÖ�Ia�Jº£JÎ{­VÙùˆË†SzE°ªS |dŸ#¡Ï†¡iHuï™ê[	 àƒ˜¿t%‚s––Ý×Ž´¬€½åãÿNàY°d|�¤_4;UB$îêObkOýÑ2<†®}ÛüŸwSÔà¨Q /žô¾ÿyð�|á_×ÀûÔfþÎ7ù5ÃÀ@\-0÷ÍÀ`R«ˆÕOÄ"èîîÁáCAuÕñûò‘ìÙªN�|”Ä¡˜µj=:Þ™QnˆI³/7DøDû†Rã>– ~±rö¿ü"‹:ç˜;80œÂË‡£%¥4ÊRýÊW¿ºþ®ªžìáèP „|xÓ·îÿmhFGfG€óŽ«Çª6?T�BÓ‰È9&±U(�PâÝ½ýcZí‹A�‡¡÷LáEâÐ €«yÖ^òEðþâ‘ƒ|W€cLËàp¤P™Y„«jPèEB«lVGc�ÀVlþ;Ç2ºL«À	gp`8…ç÷—tÞ-nÁ´W „å>µéßî¾5ÛLuq.]ÙˆÅ @DÒp(,gºbR5Ð“ùùªN1Øu»öî·%óÆƒéäX
  Ä`=V}øjøêš‹îŸop0œÔ i$Í¬lKÖcÐÅ‚#€È³9ÅKãu	
?‡C�›ud¼Õ—ÀK†m¯‡ã8øx€eØ¯¥~ÿÃ­)ÆÓ[ríi7üî{ÙÂrqøØ	ÍhIPICwLÉtç)fò÷ÇÄ4çP·™_©þÎªÄÿÇ}½¦‚cD9	¡¶k7¢Çc»>Ð–ÊöJ(ž¡ðöæ¿¥<<7ÏB¬ÒP§î�jP¼t(Š7�„GÏ‰ãrJ¦ãÉÔv/«_~4ZÓV–¿aý?ßz}Ãâ2Û¼<>vB3êÓ)½ƒI5Ó™Æ0(FRZN§Àùª?Y‚Ÿù¼iâd[ Z®Äq}ÉvŽ ­A ³QÉÎ*d zxÆñ0«n¡Z.ƒ[`Ñä-¯Â)Ïì4:Ã2ãw‹¯³ÐÁ2ì×ÿìªïŒû¤&ÓR–¿aí—x}ëª™m­ŸZÓ’ùÒ{b
†“*†d„?¿\×‰¯o™ú;wížÁÏF¢sç¤~^6¨aZLRÿÁLÙ-ÕÔŒ»³âÂÏ#[ùf£5`æôÇôÅÇÏ‚®±%ød1�×2pjôD<{`)Õ~EIJÊžpÏÅGK¤`Ú) Âò7œð™o]?óÄ³3ÛÚC.|ì„fxyŠAÑS2	,†AÑŸP!§É?M7�PtôÆÕ²¡½žÎâã;…<Ü-žÔÏ¤†CMMF¢º]N‚=Xÿéëm#Í>:ö•Oÿ-‡Ræ%pqB.vÜ‘„ ‹C½Ï¾˜)àâÀ³IÅÀcï�~hæ‰~éÑ�I86Õ;A ,ÃÒ‹¿|ýœM—d¶Í­uá“kZàæ
…_Õ)úb2²9š„¢£§ŒðaÏëÇ¡#Ý“¾êç\/a %"“òYÔ0`(IªÐÑ{CX¬èçöƒ=`xÁÈ	xƒuÄÛÐZx,tG%tüë‡‹cÁŽ£rÐ‚fPÄQIƒf .ž3QÖŒ$5p�+K÷¹y6ó7Ï,¨w£ÎËãHDB~.Cˆ„¹|ÁyŸKíÿË-/Œûâ&ÓGríâÓÿé¿~èË™MóëÜøØê�bPtŽH™Ìµ¤b /®ÂÈ2bâ2†S:B@)E¾‘¦*2ìÜŽÝ;ßBR™ütÜ|0œ`Z tb{šCN>¨ç�uyÀð‚ù#¸Àº¼`<A†„ÐœãFïŸnæ÷G$£*Â ž*þä\+ I30’Ò`ÐôÀ”1(˜¸b–|»9~_pž„Ô{y,lð /®ÚÌ:ÅéË?ô…¹�±Ô#�¶NËöÐÓÃ äÃ­+Nþíš/ÿ(crÎ­uáãyÂo1ûQIÃH*g@zc
d=?Ùg´¥§óÀ”øùå0‘©ÁÅÌ}Îë	€duæ<SðEOÎ6c[Î{}ÁZTÕ2ÿË!äâPëáÆR9‚9µnÔ¸90E‰aP¼x(Š—:£¶¯Ç“©íû�éØ«pê aÎt¬|ää¯þ"zj¹ðéµÎ„?¥êè�+(–Ò>8<Œ½[_Á`lüÙj�‰Ê	(&ü|°¬8:ÚŒ°<„`}Žà–‡PÛ&¯'_¨®±è�± ö¿¨TX	D€é´„’ç»o0…Gß²%5ƒ³jbÓtNLê•C–_&Ö¶ü~Ý¿“þfŸêË~Ã J¨9ÂKçüÛ	¿fPŒÛ�Œ`(9õæ~10Â‹ã?Pœ
? ˆµ-9ÂÀVø=^_U…Ÿgè¤
? „%�#’ã,Ðì0cJÕ±o(…¨¤Á(’ÙØQïÆeÇ7£Î[ØÌ”cH­Î{Ÿ<õg¯œ>©]SÆN˜Iuõ¹S¿~k] ÕläÓàåñ©5-ð‹l�ð[a>‘”Š�"‚•4lëÄ`$NÃ‚uû¡'"îk�ýfè©êÔ €¡$…ß_6ÝMÈ‚XÛFpåîh ë*Lry¼à¸ê™ëÕ"ÿ*¾70sC’ªŽe QBA—iT’�˜lŽxó	,ˆ�%!rŽkòb0¡b$/•˜!ÄÍzyÝÆ+öw?öëm“~ñ6˜€ñk©¦þyõç¿Ódeùy;¡AWVøâ2‹ÿÁÁ˜ñú¾n¤¤ÑÌLVô@l¬Z»úªƒuùÆ�4M)~Fp¬òœ'P°�°<8oÀö¸¢X]+e²Wÿ|Hš�î¨Œ�„š™ÄdÁ/²¶Âo!¦80,�É³ç-©Ãê™þ‚×t°ðz½wž~Ëÿ<¥7 �)Q F2rÇâ3>¼ÂŠõ»8&“ág…úŠ	oL±íe¯h:¶ìÅÁ¾Ûkâ<ˆÓS	0&ouÌP_!×Áês? à¼¡Â{d³0C5Á3Ó§9ªå$Ò±d·ÀEµƒjPt†%D‹¸CpÊÜ6Î³/®R|{:(�IW „åo,\û�…ÿôÿ2R|éÊF´ÍÆŠóÛ	ÿ‘°dÛÁ&šHâµ}ÝN(%?›Ô�ó×a:‚óÆ}Cµ~]¡ð{¶C7˜<~À‚ÈUwµæÙé} �ÝQ1Yƒ§Âôâî¨‚¡„Z”8¾Í‡Ž«·}m:(�ÉU „|XÔ\¿áËßƒî;wq]¦ª¯§ˆðkº�#a© Ì¤Mþƒƒ™LÀrp5Îr<rj2ÁûB ìØ}lj¦?a¹3@ ¤Ý„"“xN@51Õæ¿8HÅÁá]’²1�PÑ•K’ƒ-·� Lµ˜4@X~(½eõç¾“©9_×ÀúÙ¦0&Í¼};á/ã/eò—‚«±ÝV0¦¬{ì\€ÝêÏy‚«?ayÛkgÆ8†«RL'ó?¾t
±¤Qì–—+‹Å‡#JQ%0«FÄEKë¦�˜°~Óf‘êÚ]Ïû¬ß*0™[ëÂ9‹Ms<"�VñÅ½¬ð§To,kòay¸[:ªîÛŽcuìV ö«3ŸpÕ%ùŠaº™ÿ€I@çãHÄ4í+AJÕq`X²1 m!WI%pÂ÷ž¿|²¯}RÀóOÞyK`áš‹/øœ˜	—®h„À$TÝ1S�³“|Š	4‘Ä›ûsYþ±€°ü´‹°.ï˜Ü »ÕŸÜ«?P\ÐÇ:ˆ³RL7óß+ï,<�PÑ–sf”ƒjE°Æ ¼^ï�“�'0ñ
€�óÞÀæuŸûŽg8|ôø¦L¸¯'j
rR1r’|ì„¿R¿¦cd€ó•æ‘�b«?[ÄÅ)jŒƒpŠéfþ»8¦l‹°¤¢ãHDªˆp¢Šƒ*eï9å‡Ï­˜¬{0¡
€pÂLPzËÊ+¾™i3uÖ¢ºãoÅúU�æ4ò°#üöt�Éß/>P¡¦yüªŠ…âŠ�EÂPE )Jô· ml®V>¦“ùÏS8�¤QŽÈUU³jD[%`enüé–öÉ¸¦ Ò~ÿoÖœã·âýK›<Ò¯'+Öß5çóW~Í ØÓ=Œ®‘êeÊåC¨m�6‘�JSƒíŠ›ËÙšÿŒàvrÈ	ÁT¤þƒÕH¤¨ºIVÒï°œè¨wãôù…Ç�Ú¨¤ÿeÃõ÷‡&ú^L˜xá™ßþ‹+TòºÍ_`úý.k`’~ÃI5ÓÌCK—–Äåœ8¿fP¼ÝÙ7¡Âoa:Ex¿³Š»¢äo/èÅVùrdh5\®é´úW*üÙè©,B`)�bÑ�å­>¬k/$}÷²d¨å¾‰¾¢ Ë/cþmåÇ®Ï„ü.^Þ /ÏdH?†!Ii™‡+’Rs2ü,á+Ó?†sž6‘�ñ¦3|é¸=ÕÔÜ]…¡g¼«QB=]V;Æ¿R‰(+�R!Âg°¨±pññ¸„÷Mtx°êjyý¦Íbçþ7®?áÌæ¥ç
 °±£kfú¡]5Kàc’–SØ3ÙÂoÁ*Ò¢Õéÿ?öó``¨JÙá!TW, ªk ¬ ªÊÐ¥$ôTZ"->ªëÐ’1è©(´d$ó£§â Ðâ#™=‡.%@U	†œëò‚c	Sù#cšÿSZx
 4ã_)¢²G¥æ3]¬ˆˆ³çÀÁáyõ:ÅésÎùÔß>tëþ‰¸'UWË„åoà\žëÏüÎ_ÀûkÐìãñÅ“f@`zb
Â’U§™Ñ]ÖäÞì5ÂŸ5:yàÐ”}>P¾k05èRZ2šÓÌ0ËyíX}Þ_g›lDX®ÆÒœ“PÛš‰ –‡È0œ ·K,k5MvÝ¿\ã˜ô«3‚BE.EÈÍåŒWÏFTÒp÷ë½ý4ƒPWMDC‘ªÞËô_vÉUàý5àpéÊ&ADÒ2™~é§éúãÓKø�é°K¦†CS Ë	èRòÀaè‰HASÓJCzNL|šå"P]…$+H&âÂ`/â‘a$qh6½ß­Â˜î@%Ä`8¥- 
¸8œ¿Ä>2Wð¿qþU½+ÔÐêí8žÌÞx1 `cG-~Ša†ùòI¿ÞØh3�é"ü¦Cd€uû2B¯%#Ð¥%5öñâEÌw«Ex)P­´;b)„ðP?†††�LÄAuuÊcÿ•„ûÆŠÎ‘Êòº£JÑRâ¶�ëç„
¶OPµ;CXîS ÆÉ'lþ ³³Ï)&h•÷Æ=CúÄåœpßt~î–Ž)‹šÂò¡ÏG1%0–ó%“³ÂÛA—�·T£ºš±"±"’^46‘K¸o¬8©,c°'*½'«gøÐ^ã*Ø®øvµ“„ª¢ O°–êÚ.>ã#°x~hycÆô�¥ý~+Ó/–E f’Ït~“04†¦™ä›&ƒÝEÍyRåæ¦åÜ€±FdÊb$žB×Há„4©Š@t8¸PuŠ#çsTÃäÁì"CpÎ¢:¸ùB×)¡³w­ß´¹j…UQ F2úMÞlšûÁ« ˜U~íA1cúÀPÒü_ÓôgeýŒ“ç+ËÃÕÒ1þ•@¶Ðç›Úœ¯z]xË�C9Tb …ùá”†®‘ú#É	oË^MÆß)$�æÚå�Rõ‚¶a<ƒ3ö®ðyÜË’g}úÆj�ó¸ aùe,Ç]½ì’« z<ð
,Þ¿À|híLÿÞØèêŽH’Þ[m°¢®–yU?n¶àC±¤ MÃŠlŒ¯5½!U¦¨‹YNIÕ@Tš0Eà$Ç¢•´ŠªjQ> £Þ�e-…Q›�Ïõµj¹ã>ª«ÿåjšMÚO¾À €3ÔÀË3ˆHŠžcúgûýQIÃ;Gú«q“Î¨ZdÀ‰à[`8~RRx�œ‹Q�Ò!,_¶Âp"ÁD2þN1�P+Š”j&²±#”3�ÙÍx]"BÁàmÕ8×ñÝ)Âœ	àË.¹
Ç3í!N�[“¹	Ù!¿”ªgü~EÓñÖ¡©ŸŒ[)„ÚÖq·s*øÙ¨´B°JEœ·Y•ð&ÙŠ`<Ád0þNÑuN
ªéè˜x–àýjÁ±Lz6¡ÉkP�UÕˆ
ŒïnQú?�yÇÃšâ{áR3†™Pƒ¸¢C£$'Þ¯»ŽT­¤w²ájœ5&¦ÝZõÇ»F!åXûŠÏÏ¡p;åÆÒ_ ©²°â{4‰Œ¿¨:Íô¹p‚pJ+pƒ‚g–4ypB[¡+àåñßã­» äÃ ]±âbs–ßÒ&æÖš¦ª•è ê"G0’R3ñþ½#Ó–ñwŠJ"•˜ûÅÀp<8‡9	¥&—Š÷SÃp¤Tœð ã�š„SŽ„+‹L'á·�TôŠø€|WÀïâ2dæ©!¸óš³ê„c|n×ŒçÇ® (ý�ÀÂµhX|8œ—Î`êM›üé¹ñ²F!kôÇ•I©ì›h8�š6.ÁÏçåžÃVØb½€t.€ƒPŸ aSMÓ[Õ(ð™($TÇIB–+À3!—Cdz'Ïµq	sÅxº�Mòa +.ü< à„™4ûE¤TIÕ@BÑ‘Ru¨éÿ\ƒ¶šêÁ˜J”ŠTcÕÏç	Œ»kO9wâ¢”«tBþU‚pJ+ÉLE¸¯RtG�=å®cE‹6cÇnñÛc=·±)€¼Õßjî9˜Ì�ùÆÕLnxRÑÁ³3‚X2«µÞê¶šž
Øµ«æª_øyÎÜ€bdÕµ’n€S–_O„‹¾6IS7�)˜Êp_%�4ZÒà¿ÀÀ+š–Œ%?vØ4/T°�‚¬:ï×[/Ë¹U® òVÿg9sÅ×)†“*T�BRuDÒ\@B5�­Àý"‹ùmX0£±êC'&ÙÃF&Rø�Üh 7ÆU––È¨8‘ÍEû£RÆ%˜NŒ¿sÜ<¯È‚Í*—NªFÑ¦í!:êlÂÂ„Œ)9¨ò;Hñ5ß¬ã2«ÿûš‰*ƒIjº§?`¶ü �R¨ºýªSãáqÜ¬–£Þ-p5Îaù	~ %Sƒ³Q*M¸\��R$bæEÜ€ÉH™§4„Ò¤¦ùV½ñÑ{ææY„Ü\Ñ°”ÅpêÜBK�‚Ì‹P™ Ì™ ]±øìÍ Lß?(rˆÈf®8-üá¬N?I¥tö™åßÑzÔºjt| nRzë[©Á´„°i%»û”N¸qª´s&«pJ‹�¸Õ8ºBÉIÅäÈüSÖòUÓš¶C­‡Çr›Arc¥u•Z ßpÕ4¢mõé€LÊoTÒ 4ó¿Eüå›þ¥À³óÛ°dV3Ü®ÉR1^P]…`öÛw5Ì˜ðÏtÒ/°T8¯\‡_Ç<@ž0YS.Ñ\$Rª™w4)�À".k9æ~)ô'Ô¢×·¶½pò0™[{Ù5WrNŽ€9ÚË8yþ—ƒáxfy‹õÞvõJ›þ¥àY,o¯Çì¦c:óTW¡%¢¹÷ˆ!6Ll7g+5x¬ª«¥‰@%å(€êjŽ˜àásI?M7Ð9"Aªp–ßdÃÅ\8†@3€þ
„ìrqE­€JÎÍ± ºv-ËñtöÉ  6u„ ä®þ’:šøPÎô/‡¦ ‡™®ü€�ð[`]>µ­úùXÌä.™¤k%‰@Ày¶Ÿ•TíÐŸí5sØ"ŸÑ‘§¥àYSð.—¯LjÐ.ŽCÉÊ­€J¸ G
€ñkzaûúóï¯A{È…¹µîóo%ý¥{Ê:ulú—»�3‚X6§eÚð¥„ßçU<à£8™!XÊ×/Gê«þ´¤y&zõç8î2¤ßtR<KàØ’çÜ—p^üTÊ
XbÓM„\ãôØŽ€‘Š~€nºÕ—ÅBZÌJÕ!©:b²�šWžÉ„§’p"ü„ÚVÛ1ÜÕ€•\jÕÕKX†Z†¨ èGKD'|õ/'üº"SOZ‚Ï•ÉOÈ&ÊË¡”°Æf¦ Yå´\Ø™@éç½móœ³^�Å	3™ÕßÒNÖê/M`‘O�‡ŸR~À©ð[fMXd€ó…Jæ”$ÕTÙ>€N¯u¢CŸ~we÷oªˆÁl?ß)âÎï]1+ ÁËc–Mû°` àÈ
(« ^<	@ÇÜ“Ï ¼7íwDò|kõñW)¦‚°ÌÝJ1Q‘Î Jô	7PAó'¹c�ÅøWM7*¬ñ¢˜ŸïQÙplë$ ï±©da\æ¤R°¬0TåÓ `‘'Î0³•bé“²ü™ñ• “?0»~Âù«÷þX0‘‘¾Lo‚’õÿeâýN¢V£’±*ÇRÈgü+�"¬¼¤¸âs,ãç;A©´ßl¨-šØQçFÈ�Ò	Çpœpi¹ã–T ù×ºòðþÌ¯s£ÞÃgrþGRæêŸRÌÕ
¿‚Ä	M+Öåä¸kï'*2ÀùjJ&ß”äLü-°fR¼ªý	<<S”ñwŠ”Z\`Æ‹±˜ûÅNU(‘x|k¡àØÏ–;fI@åÄ… üm'~ €9Ã0ÍëæZ¾ÿd®þv¨ñðX9·³›jªæƒP]…Qa#Ìbà¼!ðÁ†ª^3+ºÁy‹•ä”TÙ¤­DÑO~›2-©Î}*î«C	µ¢~å`	þXÌý’ç™tvŽªAs†çfÃn¶ ™[®T¸´0Œ+XŽ§�+N…‹cp\“‘ôÍ÷ý§bõ·CSÐÃßÑ:n~ Æß)ø@CÕ#B¨©èkå|órn€© í�‘?i¸T… S8	÷UŠ¾¸:nRÐ
ëU[ð-Tb©D${àX,l(ä„ü.¡dN@Q@8a&Ë²ëk�?=,mòÂÍ³H)zA³Ï©^ýóQ�²ãJ[`;Eµ#e­Š!=]N”�¨ñpÁ¶bMJõqZÕ~ã!�†õÆÍ(Îòç#*kEÚqM…‹ã²RõE ÕÕKtM%³ßcöû[•f“ªaNz1("’6­Vÿ|XeÇ•†«á÷—‚«aFÕ” Ãñj[Š¾®Jã‹Ø‘�L]�ŒýžŒ�ñwŠ±ðÕôó� ’ÖaÅÜ€Ž:·mÛ°Rõ%\ r~¶ù¿¬Ù—“øci¬é¶úÛ¡’°a5ýþb œ¡¦iüJ£œP* 'ce�ŸÍ”kQ>+`<Œ¿S%TG™‚åç—ƒ¬Óª„í¸ �c>Xl[Àx‚µ,Ë®oZzbÆüÌÖÞ–ö‰HÓË÷/§eÇeúç£š‘�rn@©h€.ÅÊ'e…A™2]¥V@5§N�|L´ŸïNC‚IÕ(ê,i*\ä4M»`Ãõ÷‡ìö·U TN\¨k*i^µ€iþ[™QIC\1 éÆ„fýMJ•O´éŸ�jEÊ¹e:ˆãk‰°ã%N­€j2þNPÌ˜?ß	*‰XÄŠX­~1W‰é„c‚³æ|Àn{ kç@ýò“Á`^�‰´ÖQuŠHJ�´¬¿‰B~Ùñd˜þvàU)*eM”s´d¤¬P‰e¤FÊ*�‰`ü�`(«Æ~²ýür¨„)±ß¼ºÂÔ`
Ø†@š1Üàm›_]3æ7¤ÙU7§ü1Y?*W;Xü@]`b
wœ@¨m7)(Ö4•L
Ò¥WårV +º¡Å†ŸO¹¼€©~	EŸ?ß	œZªA‹º
Ÿ·À�c·o�xþ©»6ð·/] XÜ8ZöWt$d“0Œ£wõ·ƒ×ÄÌŽùà¼åKm'ã�šZ2)h<V€Uî«K‰Š:³&’ñ/Žeàæ	T½ú«ÕBT6gsZbA4 ¥uvIA…. ¥§@pÉI €¥Í¾ó$¥V­ÞºÀòy–E{[+šÚçÀãšÜ‡t¬-Åt9-…¡¤JFÌ}K'³XqÔ÷WFúŸ›jc1¸DaJZy»ybFÒ³õFnS�˜âLÄ‹Dàx† Ý¦B0äßŸ¿ÍŽ8 æ-GÈÅ¡ÞÃgÌI5Ç|+ÚôÔžcAR5
†Nx]"šÛç¢©¥eÂkÝ³QIá�%øÙÃ>ÑSº6 Œ %#9+<5Œâ�jrEƒ²­€É÷åÃÍ“œ¡šRÚôµœº¥¢µ…
À ¦lg#G0ž`-ËqË½móÁûk21EËü·4Ó»iõO”Ècðúƒ˜1k6|µõ“v>¬ËW22`hj�à[ S6¿ \åžÉüÎð¢mØÏj„êÊH/€É÷(˜¦k‡éjXS´� Øó;»¶0bCAVå‡s€‘Š­Ñ5•Xþÿ‚z·Ùô3mþÇeò»HúíVÿ|ð,‹ÆúzÌž5kÒø»È€%øåºõðÁÆ’¯ë‰Hé2a%•Yá³MÿlPMv¬¨&ƒ×S“*ü–¹_ÓÙ
°¸¶rHq¼[P" ¤©muöß¹w)íÿûæ®`j+÷ÿÝhþ'*ÈbdD·ÉL’[�ÝRÌÐTÇmºÊå å¹ ->\6æ¯%ÂŽ	AIžœiÐÅÌýR˜®V@Ä¡(¥ÀæÔ’Êù<@¾š< jŸñÿUƒ"©ˆ)ÆQ•ùWªN+?mÁëbÎÜ'¶ó/ 5Í04Õñ°ŽÌûj[�Ó�ÊY€³!NÂ‚ŒËCS!ÙUc|©iº¨¥.N¥Â�3Båy€ŒX¿i³ÈrÜrÞ„¯®í5®Lø/¥êˆË¦IÓÕª`¼uâõ¡ fvÌŸP~@—S‚ Leó[XÑ6Pú¼Jå0¼z2Zv…×¥DIN�qù2ó’‰ô*gY:ñó� ,M? ëÔq8°˜%;3Xh0T_‘]˜y²þþÜ='èšJæ›ÍDçÕ¹ ¤¨}×™ÿ©*$2YüÀD„µDTWA8b“Þî¦9%­ CNÚ–
3‚;£pœäõ«‘[E‘-ü™}+´dJ^ŸC?ß	b²mNr,ÅØ¥3ç}j‘õwæš² üí‹˜SHSŠY3�˜fM?Æ‹˜CÿÊ)ª6´„ß#zÀÊ¦ëfƒuûÀ”'.Gs\Âr`¸QEFuÍ¶@>òó'ÚN.ª†0s¿¦cUkRuö}—âZ…SR#Ë­ßGU(Å2 ´u  ZüTƒBÒL+àÝdþOÔ 	‹�[�/ü8o ¼/TÑ±<m2Ó{ŠÞ¨+Àð…ÄŸžŒ–�ûk‰pfÂ‰`Äâb<î¼Ûp6&Jð3çUÅÖaÕB5x€¶À¨0°íY¼ô“«ÿàzøÖ{­mÙjz% øg.Dƒ—‡›g¡êŠ™$ëïó¬ä_%h¬¯GMMzzû*j+¦Kq[á·À*Š°n¸`#Œd(2½Çt<`�E¹->R4$˜¹¯Ñ!°3J
?`F I„àr6I˜c™ª™ú¥`‘�Ó©>ÀâœU4¼Pxî!7‡Þ—ÁÛÞŠD×ÞïôÚlÇŽF	@ 4·M>>Sû/¥Í‹w‹ù?Yã£*M+¦šìH°…`CE£¸¼³—AO•núQªk`ºJ™¸?ÕdÇaÁdÂ™PM?ß	œúÜ“	§EwrÞs�EñûßÞ…½p-^¿õ›4Ñ½÷« ½6ÿ} ¼ðÌoP]%ÞÆ™`8ž™2	@Õ ™ðß»“=?ÎëámŸ‹D,‚þ�AÛªÉŽ{ë[¤ 4Ðéh†ãái[€TßA0®ÂfŒèáxèÑþ’V€žŒAãø¢s	Y—z2
Öå+kš
EJµÜ<™0S¿ŠŽ:Ïä%,9='¯Xþ^XŠ"‹â¡_ý ÿ{÷o �ô§_%? èMvïc €ÚR ¶ÎP>ð‰fE4ùx„\x‡óÍ§&Ãü/†RiÅ•v!ª42 ¶.€Gí¢i©i*t©¸¥@ZÜ>ù‡uy3V‰uÖ()ØV­°ÞX¡êtÚE‡¡À”ªãÅîÂ•ÿt6~ñó›é¨ð ½À^r­9ëc Ëß@uõúÅg|‹?úüÛûf ö¥°µ;Ÿhß¼!¥êP4)�BÖt$}Z»
1Y¯z`,Pu=ÃèR¼¢aœÙÐQÇghZOø¥?¶°5£	L¬Mù0ï¯+ï�@XbÝè1'ð| ¬ƒ&'¯._Ë€gè”	~6¼<.nüª8¦°¾ß*¨âY’ÞÇ\�—µŒ~oC	ÑîèéïÇ›o¿ƒ÷BMÅ¡�ô á®ÿåìS/þÙ³W�¼• ªk³ÀÝ: Pïáq8"!¥êÐ))ZÁåæÍVJÙ�‘¦H©ƒšaDÝ$W¦ƒbÐ¦I#‹HÄ¼è>°gÌÇá¼Gî5†iZ¼¤t®c}µ¶Â jl„åsÂ�9ÇJ‡y_ÈVø“´ËÈ‡$+¨©!ÓÊ¢ŒËÚ´Q °Ä”¿|a·CJÑáN�u^uó`ÎüpÏ^�è;9×gRŠVàCÖ•® !Ôoú ªN“4°„‚«àâX~kÿ,JÓ$ŠnDL¨Æ¤·«FòO5¡î–yPcCf-½ò¹“È€å×{Ú—ÎÙúÔs�µ'—:¦)ÉDÁº¼J¬òjd dM+z@Xñ”‚Ÿ³^ƒ“�©zF,açX,1Ï�ÉºÿœƒlPÕ °»“v¼†‹cZ�L � ž†hòñ™ƒI…P%íÌ±‚n>3B.,lð`i³unÌŠ¨÷šÍÙ	*Ÿ*ß¿øùèH¤Ì�¼¿î–Ž¢[9ˆu­Ž"Çµ´ŸåÎèî-}¥zöiš
-1R2ñH—%–!'m§1ÎÌœo"%CÕ§Þ-ËÆD†¼9Y¯ÀÂ+°ˆBnÎt³<KÀ0LŽðK+‹%ÙU*æ›çã	ÖÉˆ ¼ÁZÔºùQß^5 pkžM–1Ùì9ÄS¹r„å!6Ì¯$!uWÌˆµ-�‡{ÊZºAÎ%,w]bßë·z;Ž/š¹hUrÞšK€ð"¨¡C‰–$#µd4ã
0Âò¶ŠjºY’F!ØxŠ¦#,é�4³ŒÜ�SPSQˆ‚�gôûðšþºµ¢È¬êŒí*^~ÅÓ¨³UQ)òŒ\x†ä$‰S·áúûC•“m Àr<åý5¤ÆÍB1(dÍ€¤é¨á'?,RÊ�H©æyUêFLÿÈ]ýóÁ¸[æAéuLð&›/ë!÷”Ü�á¸–™ç~auçý?ù¾tø­kÜsVÝW—“`W)HøÑ4_]NBK„‹v5¦š
->Wã¬’J"%Ãç¦	˜‹…e‹iERÑÑ•0œ7ÄS•d¨±8 +¯¡nŽ % bÁüy<}çÆ|>fªoy9,51àâ
æÐšºY5ô6 pÕ6 ¨ñ™@:%ùÿŽeàwqcr#¦“û¯¨åÓN…šfxf,rÜ‹­(ÊðŸi=ÿË÷IáÁç”#;Kî«Æ†33³…?s-Ñ¡¢VG%uùÑTÂ²£’†þ˜Œ¸¬9VN‰x;wíÆƒ�<†×wìªŠë©9<F©Ï
ˆ…rÌ®F†0Ì `ÓNÐÅBÓ$U#Ã<Nw¸yA7�f¿€Y5n,nòaQƒ³B.´DøEŒœp¤$gÃ*	ËÃÝ2¯¢	Bœ7àˆK`ö;ŒÛA¢ÿð>¥ï@É}ÕØ0Ãeõó­Âñ`=�ŒòrÒ=h:qªNÑWrêx–@ å­H+"C5;wíÆÿ=ú4’69•@q˜›PJøÄÂï.àš€Ì  ŸÏÌó
,’ªÉÔO'¡©–µPçá1´ûUxâ]XÕêÅ’F:êÜh¹¹IWrª®CrXåe�÷×UdðÁ†²ûBNn9õÒK	Ë0Ñµ'VJ	po¶/ÒDÄÐTh‰0Ç›�Ió>ÛÌu(�nL�À³nÎüñ‹,¼<:êÜ.#GP–£šZ�é©'£¸ïþqpïî1Ÿ£aÐV‚S~¡ðÜSªÑÊQ]ó€2- Ï ©H©ú„€“…®¯ fÏ[· ¸‘ËŒªºYñ˜Ru$U#3þ|"0Ö‡Ü²œrb]ky2‘s]wÊu÷-yæß/¼Dê;ø0 "4Í)Ø�²< kP#ýE­]NA`ù¢V‚€Ø0«ä9'Rò„‘�™8:I“rEr[j=XBÐt¡;"å¼æu‰èÝ¿Ñ=¯Aê;�©¤jšà�¹ØöÞX•’O>ù>àõ¡±¥­âsgªNáD5Ý°uW\6‰|^‘mà Ô€K4ÓÝ‹ˆlF¼Âô eÆ‹½/>ÉU‹÷~ä‹¶¯ó,AÈÍe”‚aÐ)ABÑÍYˆ²Vµøðxëá…šfpÞ ¤þÎ²Œ¿l(`8®åÀÖ'¿j|V×éG¥¾ƒ¿Až`³ÚŒÓ´Èn<Êp|Ž©_¬+±ÙÔ4®L�‚„$Ãëß”$ž%eÝu>ÃÜ‹,A½—Ç`B…F�Ã/>œ®¨+ž¸Å{ƒ·ÁåAXºœÊIó~èáGðO}ž`Í¸®¯ŠåØeòr™Ë ´ Ñ E3 èÆ´" Ç
%6Œý»v oÇ‹Ôi}5Ã0¥Ð^ãÂ’fVµz±°Ám;|±TjþÛžŸàq”7à¤fÀ$¿²”þN×µÿ—èÚËàlH<C‘ ÅGÀp<Ø<s¿\Z³]^@>œò#@¡ùn)q¯ÀBäÙŠ„ß/0óÜA¿ÈAÐ“xéû_À+?ÿç’Â j"‚�—Â¡ßý’=ûrÆª¦}êo��iª–:Î�`/Ë Á3Z)&O³˜ùxðêßŸ èšJúw½2æã0ŸÈ™!žÏ˜B5I.+o AH8¾ld€aØï  (½‰°ü�– EBwTWÍ¨€�¹_ª�˜¡©¶Ó‚²!©FÁ}âY’v;A¯TØóÁ33‚…4cC½øÓ7?Šî7Ÿ­èxj"‚®©ÿ`Á}ëê<ˆÃ;^®ø�ö,æºÚYó.Žie@i  x·®´“!iÅ’Ž>~ëÕÌï{þþhÕŽ[L!4xù‚¹lœ„ÿ*…•EX*ÎÎy%• !ää¶³?û  ºzƒ¥R�oå^³àëöƒ°<Ôè íjohjÉnÁå:Ž‡¢j‚>–UÝ)fÔ¸Y4ûG•¹N)þú_Ÿ-»ê—ÂÐÿG-…¨ËI(á~hñaüý™§*¶œ&³ìëyˆ‡hfé·@JÕ�ê@6Þxî‰ÌïÝo�Ý(K!X.ÃòfÕ¸rÈFe‚,+'.AÙð çºÎšCuõ€|?Ñµ©}¯�°\Fð³¡F‡m#¥úZ\ `
;áxð.wæ‡ã8ÄULˆ C�Û¼.GPçáÐì°íÿnÁþ];Æu\]SÉÈ+†2Ò5ÒŸábF"tî»bì¢]ŠAÛ >À¬éæYÅ �T9ú5@Oç~$úgþÞ¿kÇ¸c²NÁ§I¤Ž:7VµzÑQç†G‹Â5An2©Ä%VúRáÁ!˜½–°ü�‰þÃH¾³Åö=ÔÐŠšü–Àp|æ‡uùÀº| º–vŽ³�„S“Ó£¯ÎÃÃ•·ÚÉ0žº÷—U9¾4Ò_à
 À[Û¶Vtœñf²«èe dh^KIHw”$•Â®—Ÿ)ØvxÛß'ý<†A@d�|þ7XÛÑ„U³0«ÞgL„2jšK-ÕR,CZ[î@ÿaÄw<mM04jlØ¼Î,a74¬ËgvNÿdŽ«©PÊôJtÚw¼°Ë�{áÑ –¤Z	¤Ãolë:¸oLd`9³2‹úËñÀŠ7˜’ÎÕÆÛ/=U°íÍ-/LÉ¹Þñ2Þxéy f^öìz?3QÊ€ó‹òå"B0�l%Ýö¤9«€1Û‡³¢''L˜/ìZ	Ö¿\ƒ˜¤BŸ„î<-~.žÍi¼i÷Ü8ÅG/»O?ý4^yå|ñKW0­ ªk™C‘ �«ž’DŽ©³µ¿Tƒõ
@ÓìÛöjÁöÎ7žƒa“Nrvíx‰®=PÂ}B£±ò€‹CÀågf×û1”T1Ž¡;ê<V/ õ* ë,%`W8d‚]ßò3kÕÕ@HLéÿ¶=‰Ð{ÎáscõjlØ¬øËZéÕèPéB!M+ê f'»RÖj¢Æ#ä¸ :îÚ>¦c}ô²Ëp÷]weþ>á„  ?ýÉ Îô_´Ð?Ð�Ù˜�;@7(]Ss^Ñtš^Y�éˆðî-¶f\¢ÿ0ûzÆpÄñaï‹�  zß(¾ºÔyxÌo­ÅIš1¿¥^÷øbËÃÕ8ËÖï/Y8Ä¹®ËïJo!_•Fú1ôâaØô1´[ÕKYz²ô
8n€�`äöÓsŽOêSÛ>ûé�§/V×Ð˜ñæØ�eHÁpP¨…ñ.èüâß·}­”N’‘‘£üÆo”ÝŸcÌTÔfÕbMG#ZcWV
±] Xd€á¸–ïßüß/¤•€šˆØ*]NAÏó%&—›™0]Gw¿›À°O³ÃËD�S…oW ãññÆ‚lâ±gës½×Í³9VÁX¹±a–­°‹ä‚£/”V!hA—S Zq—F•Šgjºy‚•€]âŒ«¦qGnýÕ¯
¶Ýrëmæ/,:Ž4ð‰pÉuƒæZ Ó¬kÖ˜“4ôíx1ûjbé À¾m¯Nª²ËNF’FúîÚWñ1,«`mG–¶×£Æ_yÑL1%P,2�Of�¥Â¯=ªæ
x~±R©¶çZ7`¢{ô�$Œ¤4ô'TôDeôÇdÌ^´lLÇúÍÝwã²Ë/Ç3Ï<ƒW_}W~ùüô'?  ˆ3ÁêÀy`E8ŽGcÃØÍXP,C�Ñ55˜Àtë›7VìyóEäp„ÜBnÌÜŒDdLé˜c…Åþ[è~ù‰1ÉD�‡Çò¶VÍn¨XØ)«›P>²3�N–Fú1òÊŸct¥Î_õKùúF™™Qibózb
$UÏIµ]²nã˜�÷›»ïÆ©§žŠÕ«Wg„ßUÓÂr™Fp�¯›—?8æÏ©4ƒ1 2NÚDS�¼”ß}ë7^qóú�WÜ�Lö…U"<ÑèïéÊN'Ý”vO*AÀÅeA%<��(J
r®ë²çÉg#�1x‡4Ò�È¶'s”@v6 ¡icv&ú™ŒÊ…–àIgœÞ[=átÍ<®`[ÛìŽ	‰D+á/–HÄ ÝÐLMÅ!«füÑž˜“òKÈ¿>ÿäòóOÞ!–»Üâ<ª%„å�E8þ…pÂF ±¾/Òjvž¸8Ìo­­È"°Sœ7PÀ0×rÀåúd±ã¬ßtÅgA˜ç]{ßÿff»!'s­€+}©f!šnLh>ÀPR-˜¿ÇxBØxÉgªr|WM#\�³¶·|EEÇoT®˜"e  %ŸV}óÆ
«ü @˜ç@éï¬×¨®n×5í **Ò¬ŒpÂ¨¦!7êšJvo/¨‹`f5®òJ\l(
ÁÊ¬€çŸ¼CfÜþ ì‹îÞuà�ùÃæZ%¢åF£Mô4§‘”IÎIÅPRCoLÁò}s-×qYŽ§5«Ï…PÓ>Ø˜áYj‚A´Ï�?¡×”;÷^`HB¢ ÀÈ&G–˜¡˜HXå¿,ÇSÂ°@Öoºâ öéšJ:·üÕÑ1Ã@JÑ—5„SÓ„QOTFçˆ„}C)¼3�Ä;I¼ÝÇÛ½qlë1Ž¼òË]C5Å,J ô&æ¹#¯=…Î°„îˆùÓWÐW0”T1”T•´t{v½âyu¯Ëg;‹äwìµË,gÉÈ0Ã‹›YŽ§Ã¯?F-¿ÞPåŒPJÈË±ãÝ+ðHDÁHJGoLÉ(–œù�[àm» Ö�ô!Â§*+z „ÁùjñÞ+6ÿ9âì(-°· h’5"  Éæ%kÆQ]`¥úêšv'ÕÕ‚”®çŸ¼Ca®FÙyKÀÃ)³lOTÎõÛ½qìèKbÏP
û‡%Sh£2**Â’fŽQ×Hš�Žv ŽØ5{ŽêZN|ˆ0ì{Þ6Ýkëý	ÅË–4$TôÆUtGåŒ²ÈVåCkÐ…÷ÌiÄ¬z_Ñ�‡™'�›6ÌˆžÂhçº®Ôgªü‚Añïº¦’ØÎç3|@vrÐØy€‰}UƒâH^û/ ð×5ãƒßúZWžRÑñxomç}¹Àô',�¶öÙ˜¹tMÅçÈ:tŠõ¸´[Ø%Íèæ 2PÈa3t?Ê-€Î7ž€ã	\ccŸ©ñW€ÜñÆKÏon½À™ëchª‘Œ1zt‰ð”pfØ¢$Ë�Ãˆ§dRTS '#�Fúc„å¿Hóª«Ûc¶ßøçÏŸt=+ˆ`yÄ ãòÁç!† êá­k6Çµ…êà©oü5Ðò¾Ž "ÏÂÃ3àY\Þ
À1³ëýL­Ï�ƒ½ƒ‘
/ÖÌlGªg4<ÉyC9ÂËp\ËÂ«o¿p÷>öÇb÷è¤ùïçŸ¼ó‚D×žž¶àëf@OÅ3ÊD��õlKˆ	ÇƒêöåÊq™ Ì�F)²òìB>ËOK)qL1 p4§+PLÖ °¬»ægcn	¦F2Ê•°6žvú˜È¿ñæ$•"EB †  73¸ŽæP`¦ü—��dd¸Ô¾Œ'pM¢kÏ™áÁÞ&_]3M5¢½�Lrà=û¡�ô ÒwÑ‘!hÑH#ýk„å¿og… –°Üq™š@GööR¹q¼×,ò©›1¾æÙÍY†À¬%Ð<žŒ†wqLú‡@àF»À\–ÏnÆÁÁ˜qh0^p-Œà�PÛ
e¸Û<÷t'¡ì˜~âà¶« U iëêë ô‘ð[Ï£víy Ò‚7t9FôØ¾×�â@‘~rž†Î~Fsœb5»(PºOàPRE“Ïì(ëƒ	5óÞ9ï=ÍkÎÂ¾·K7Íæ:XÑê	dÜŸsÎ>kBûÅ…]V¥fÐýa¹ÕUè)“p:‡lº &i�4QÙÀ³�=¤Ã~Ï?yGÉ÷ÉÈ0¹ú…ï}þ·P%$ú—p–ã©®©ý éèaÓzÂº	ÃF¨¡'Nè¤†€“6|ä�bçñü“wÈ æYäÚß_ºßK•””†ÃMõ†™A=ŠV€.PÑ™êÞ×›£{_Ïé¼ém›�ÆùËQ¿x-j_]3 €#*|"�Àf,Ëx§/Z0�ˆ÷×Á�â™•ŸórúüBNN�’+®\©ñWæ9599ÕõÜmLÁÜ%] Ã0–ÉA–²È=KIØ)‡á¤9¸ÛÆ%HH2|3Á7s‘yL)•ÓâŒj*”<²Ó*†ÚpÒº1uLÕiûúbÑ;¹NÈú !,÷)ªk·òÞ ÎýùX×nja».¢S	«ew\Ö�TtÄ£À¯yéû_@÷Öç>’Íü;ÀŸ| Èø~ ;òºt3œÐI)í<é”÷§wJÁx‚µP¥ÅÔÐS]_BVƒ+˜3ÛæcÆ{6aÆ{6"8Çd²]ƒ�‹ÍXšAq wÄ¶ò0Õ³7#ô†œÌ©4¤ø³+mA˜3A�GxoµkÏa8ˆõm`8¾dCwKGÑ×jC�qw®~‘Í‰�kè�$¡ÐQËW   wç�š¬'€óNZ9î•QƒÇÑ~ËZ¼¶ÛÚ9„í½‰œm‘¤r9Gã`fÇšj$UƒñLP×'°ÆˆÇd	Õ@2Í¾óÓ-Ó=vx7º·>ÿ\…ÂÂ	_ ºöSÂro�˜#àH¦‘Nu-gULÒ+ðé ]¼EX~@×&ºö®ßÝµçÌÝÞÒämœ‰ëÎFÛº³!Íè GTÔxøL�A0 `ç‘Ü‡ØÕ8É#»  3è#cˆÞK”V Ôø+€}j"ÒaÄ‡ÁøjÍ:ø2×EuÕÑ”ãÉ@­‡Ï<{€iId1pž ÔèÇcÑ¼¹X¶xá¸‡ÏýÿRŸ“=åÈBTRúaùeTW·ÀûðV-˜ƒf¿0)åÀ1IC"=ˆ#¥šB_jŠo|¨ÑÎÝHôìGïþ]Hv½©ï Õ5•°OŠÅ|îD˜
¢ºv@Wæ�…§_Š¶Õ§Ï3–"H©:¶uæ´,WcC>€j*¤�ÎÌks—�\óÌ�„Ë|úM ½Æ7ë8x;Ž¨ëò–e.Ô¶ä4ÉÆd[ uf~Déá …@öpP»q\c�‡gÐr•ßO`2ç��[·ô=Ô;¸’#¢§‹¦ÙòTÿÄfÍD³_¨êÍtb¾gCN&=ô6½0r`†Ž@ªg_±6MÄ4Ýµ ô˜ðg!­·¸�pÂÌØ�íŸ|åç¯_¶ýžÆŽùg\ŽŽ÷_fx\"Sëá±jV=vÈD	²ù Âñà<�7ÐoB	2 @Èã ôyð¼ÇÃPe°./Æ
E30öw�CÒM[|…ãÁ*ï³ V¢YéñàåáÔ/)°«© #C‡¸´9à—ÂýKc'Çc¾G»ö!Ö¹‘î9�<mÐà•´�þ*a¸'žò‘w¦ƒo>�‘NDºÀRxðÌí÷ÜôÅ=�Þõ�%|í'_`ÔúÜÌ’ö¦^@¨m5{t5',˜:ðú(£ Öo¼ü©Ÿý-Ub(©ÌÊNµâf~±ÙƒÓÇ¢Ñ—-Œn µ¶ûj ¥}H9“Èd€c�™>äT18M*V•´‚D Y3†ž¹ñ‚pÚF!ûºBé+i‚g£Jæ;)1*+Â¼	J÷–}ž0ìNð®�£´é£S]�6¾ùQÓGÿ«Yöúmÿ~íîÇ~»ùø+¾‰™ËÖ`Ns S	–l€2ÜmþLsá—ûˆ´BÞ C�•	”Î4Ÿ“‰™8™(§,¥  £\-€bÜ�]‡e�ÁÀÌ €7¬ˆ÷`fÝ£3&Á|ßàMlÈ[„åÞ¢šrÔT(V3E¨Çùj"í"|,Ù{ð¦çþûcÿÕ°æœ¬ÛüuÌhnAwTï¯ƒ�¡¤ÀûB�‡S º>ÏáGìÐaÈIPÃú.Ç7q20Ù£�QÅ g¥=sŒ–³Ggúþq%¬¾D~C>$ÍèÒ
€°ÜAª«™lÀýÃ ©bó}øÐ®rýÔöa4ÄVh¾SóªMþ˜èd¤Á¹Co<qÒŸ_~ø§ë®¾yÅ’OEwT†X×ŠTÏ>³©%ËƒZÖoÚ,–w»Ì,SCŠƒÓÛ¼ŸŽÐ …¬QÈ™ü¡`Y<cŽL³”‚;=þKÕ)º†aÄ†ÐÓß�7ß~oíDb¨ŒCÂ]ÿËÙ§^ü3 ­ ¨¡í€H·92œGØ™ï‰®=¥Ë|…°ìÎcæûÑC•_X¿ióÚ~|Õ¿ŒìûÄõk>r  ;ŠLV +º¡%Uô,XÝ†'ïØ_æ�C Ž:…>�¦b‰\¡ù¯QM£�­85tˆÁ_~ûküäûßÅ‘Ã�6G"[ApãÜf$#Ã�÷ÿØ¼V  ·ƒê*ý‡1°óU§æ;Ž™ïcÇ†ëïõËÊRCN6ò¡Æ¹Ztp €0™t±èžWnê~àG/u|îæ¹‚Ëó~ƒ0ýZ*þfË;¯tMé™>îï<ôëÿëïÜûËs®úïu)…`8Pg* —Z2ŠTÏžF˜>þQU×1ÔuÑ×Æ‚^9Õ§ãNÝÏ ãÜËðËMçã¡_ý ÿ{÷o²¬qò}€^
ä×Ç H›sHg’Á> ;	Ë¿Fm7a¸éT×c’í­çe]`þêkA��ÃÔ•Û?²û•ž9ñðœ·†�<ÝrúÇstš¶,·�hÊß)ùØ¾_\Yuad<ÁÚºE«oY÷Éë/TDû»¡F�êÙ]×Nì~àG/•>‚™àm›ßÂup5Îï�-BrÞø€ýmq»DÔ‡J�C/…„$£¿ûú½ÉƒÛ°éÛÝ×/²hôU7>V4zyø]åó	¼<|£Ñ9ÃC~ Üò]ôôôP]×þ(½)ÿ}�)â¸Ô¸ @˜wŠ™ï‰sÌ|/�õ›6‹+6žCXîÃïüè“?4Tùõð[×2V_bzOÇ¡Öï†Ï-¢ÖE ¹ÍtÑ “"éŽ´üîß¯Ü²úóß^ÑÒZ�ž¨ŒDÜ¬Ù`8n!€…à…‹D^À¢«oß†ù+á]Øù?—<?¦“Îƒ‘Œ¼þÄÅÙúÌç~ïÏ×K5ÍP£faO*6þ˜$¨ºŽápjd ±=¯€åK'Mæ`Òrp;ÌÊõ¹û‰^?.¼ô2œpÆEøÙ¯ï";¾ã{ñCo·ôÚìýFU‹jNÿnþwÌ|¯§üð¹ý‡||¸ŒM¯ò³þéøÍ_5XqãâùsÑQëF¨¦õ¾Òi¯ú¼YøÃMßXñÅ:®�ÙAV3ÄUôô¢ �#zGb£
AW¾Ò~Á—Ùyÿ�?[­k¢ºzÃk�ÿ©ÿ¸Ó/þ©h€–ˆB=Š@$–€.'AuÒH?¼�3Kî?]¦bqŒóV`ÅÎy ¡¢yÍYh^s¶={Í¾gþÔ¾0Ôv™e¹OìÜ¥ ,¼úö	ÁW»�’�ØÑ\ãGëqg¡-uð{Ýo½‚3VÌv|L–e°ñ’Ïd„0Ã@--�6`žI¤T;õb×á>tö‡;øÖòõ›6‹��à�=óÖÔNøÑx­« hÆÆKj¥-04†œ*:ÉxºÂŽ ´ß�Mê��°ËOAÃòS.êŠ<ˆ'ï¸8¦ Æ�Å_¿w=U’ßbX.Ó6Fà8tÌiÇq³š3ùà‹>=îþ×Ü®Z²FÍÎ>:…bÐÌ¬�šÚœ%ë.ý<jNè'?5ÔÍ³8~^ŽŸ×†”ªãÛOßºîù§îz|Án>™! tå¢E×Üþlc{Ç—Ÿ½êäÊæRg¡ëá[~X°Öàu?GïÑÃÿÉÕä²½-¸¦IÀíð<JïuG#0Žn³~?¦ ÆˆŽÏÝ<—÷…¾Mtå"Âš·Qà8,]8Kf6´U8›>ÿïè�)HiÔqïE‘%¶‰ž�›g!rž�ó,”‘>\ÿË{On>nÙ²{»Á°Ü)ƒ]‡Þ\tí�?jòn(_Ìc��?üÄ/]{ç¢©¾ÿN‘ÝOÐiÒdŽ-¯àÌ(V+`¥ågƒ¥ša<ø«]ÖßÇÀ¡ö¾ó5qþš‹€Ò‚¯hÂ’†˜¬CuÕ¡;*çtê+’ª‘3<ÓÃ3¹9xx+ÏºëN6‡[|þ¬Õ88œUó•¾xô²ÅWýúº�?üÄ/ÆòÙ»nºâª×ßê~àGU¿¯Z2
e¸òP7ÔØ09C5Wî°‹�!ú!x|àÝ>x›çÀÝ8b¨ÉÑ±©ÃiPÜ4à *ñÿ‹Y ½±ÂÕß ìÖìÈÝ»N8ËP:>wó\+øÏ?ïYøåUXÐÞ‚•K”~ÆeÃ)É¼•¾\Ç5-Ë  Ža�37‚Ž §_ü1Èš1íÎ®uãóg­ÆÛ»ñÐëûÑ;«#ü|ÑWï>­ÉëûôX¬'ï±ºMA5»ëP]ƒ¡iÈVTW?¸ñ½¯Aé?P2“´Ø+¼7ˆ†ù+P·h5ZÖžUT!X}À/­�Š4`;8íÉÁZÔÿ?.ìjÄü-çýS}¡cÅúM›ÅŸ5Î_å›×¶�²ˆ¬¥+/»ù†Âò7šSkª‡…Wß~!a˜_njçò'ªkCíá·±þüÓrö‹ËfÛp©HµªSð¬ùZ2ÝMXÓ�¢3ðx–dLAž!™^"K rÄV1HÅ�a	^‘E£—Ï(‚%³[Ñ1£�½þžÞ~ ÁE}Ñð²Å_¿÷SÕ
æ‚ =-xù&xlÏ«xöž‚D³3ÛÑÖÚŠÚ:³Ò®¶Öü?TÓ€ðˆIäc÷þNÚ»›ª‰é~óYt¿ù,ÞþÃ�é‚Ó.&s?xÑE5³ZM…1UH°¡¥Ø	ÃÅMóßåÐJ,•#p$Rh„“òcÙ
àÍ‹¯ŸX8û”´ Ï¥ Ç1„Ì[úéóâ…‘ƒ pá„ÿÍôâ']{ç†ù
 xg,Äi7þns×_oÅÝƒS/»K hzãjÁŠŸI3LW *�­¿�A¡*ÈêðÊ3�…—gàØœÕ !ë8 ëðŠ,šýx†@äœ»fæÏnÇoŸz‰xla|×ó—˜ @¶ æ@Ô€®ÂÐÔL_ÀDçÛè~ä ¦ÀoØp
ÞwÚiX»v-<žÂ¦ n·��…Ã4UI&{ìÇ–-[pï}÷á‘‡&;ý-$YÆÒÍ7@ÑP]Õ5ÈiâÒß^¼˜qºä 8�ÿóÿÍÀ@¢�ó }]¯dÿ=­À›_?‡aù&ß¼¶…CÎ¦ Ç�ÒV†arªÙ}Eotã»OþÁ|={Ç8°~ÓfqðøÓïf.²¶uÌž…å3€µk±óÑß`û3AûÚ3mo¶…°¤!"é™Î¬fGá~a¥$³Z
¼ùYí¿ÞcPD$É<îŒ  ŸÈåÄ…²Ž}r
>u3÷`Q£×ž"n}àIüí�Ÿ¼³~Ófq¿?´ª|vŸs¤3Eû 4)#}`E/O TW¡Œ˜}gÌlÇÝwÝ	 ðz½¶Â_
¼KÄâÅ‹±xñb|ìcÃu×Ý€o}ëF1ëZT)‘éi�8¸� 5Ë‹o( ‘%ãöÿF<èù®Û”(€bæ»­ ;˜S¨©*þß]?´þüKþ Ž±`Ãõ÷‡úbá‚Lxïøã`Vóèè¬ùïû0¢‰¢Â–4%Ô‚fªA3ÂO)Ð55§WÎ=àxpÜè×ÄeB��+`Š‡S:†S:‚.A›ó@ÄUÄ$m!x† èbÁ| 9glð_VœZ¸öÎíºéŠ«Æ{ÿ «®€ü ›¥ÃoA¬ŸªkÐ£ÍÏÛZ[Çñ	…˜7ovæ÷„$CÖ(´ø";Í‰Ñ®šF„Ž;©èû§CÐí�ý/ÿ?8RHƒåûÿÀ$( §æûxæ‘þâ¥G°#ÖŒÎà×9g„?+¶Ÿ/ü²¦£sD‚Fpš–CJš�¾¸jÛ‹�*)š‚Þ(SLM7 é@JE¦G�›gpqhŒæ¯›V�V $�bß`
í5.¸�ö¾øný¿GN> {pÿë‡ à+Ko|øÈŽëÏþÞ¸nb„ånb®�Fú‰;ÜVô€°Ü¤tÿIÄcÐ’QJ
‘7Ì‰Ñ³Nþ`I÷«šñÂ)(Ñsðp¤Päûÿ@ÀxÌ÷ñ ‹Ñï?û€yhBn¯é¿~Óf1[øŽÃñË— ¥f´N*¡èèÌbX5j’>‘Ã@Bµ�ÛS%…”$çaÕê€›RM÷BÕuD5|Ú„Œ¤G—Õ{r­…Î	F2‚›ÿ0jBAXc0ïýŒøðw_õëøXÃ„9×­«Ûu�;lŽïÞ!ÔFJäLšªIV F0òÊC�FúÁ{ƒXpÆeEßã4ñf"Á1Î{ æçÿ[ˆ«¶ñí7?[ðy•ž`µÍ÷ñâ¦?Üžn+F¶:RiŸtåÏþˆ¤Ù÷Ò×(ºÃQLî-µüÌkYm°M¢JÍd«Yí±ÇCÍVX„åÍŸ<· 0Õ JéJé¨s³E ÝQ~‘ËiøZ[W�UBç¾w9Â*ƒ§· á…Ÿ/þú½;ª ÿ¯TS.T|÷Kð/^_v h5 F?¸/? XvÉU€'TtqÌÂpÚI˜#´h¢Ðþ¡BÿŸã¸ûíÂã%?m2Ì÷ñàí�nÜÖùŠu_oüÑµwþ0›ð;þ¸Ž„?©hè�šÇ'•HÀPŠ�Å¶VACŠ—<¯Q]>úÅ*0GO–7‡yºr­‰¡”Ž¨¬¡Ö# äbÁ0ª�Ca­!·ùÕ¥ù‹¯ùþË7,E2ÇËû@UéþŽÏÝ¼f¼¥Æé±èŸ¥¿Mtíá0.ßxéä3?¸½ÿœ kÎAÛ)•|Ït  �šÿ¥Â{m€¢²Û×ö(ë7m±rMÊï÷çÜ‘©¿=¹øÉw§OŒy.]Í8ft|îæ¹T•¿‚ôj»xþÜŸ?¡èe… 4M«ëH&ì…ÚÐTr
Z"Àâ±Â´R@2Š¸ïòBGK]Uƒ /m¶„Œ5‘tø<c® Jàô5è¼÷YôŽÄêx�ï6 ÆýeQú;Ò
J¿?ôxoù&¡ã�îG×Ÿn¢º¦’À¼ã±æ×—}�Ç!ù6Q¨ÄüQ ±ôTé|Dø‹Ýþ¶êæù'ï�å—v½¬©Ó·�ãÛÝx¸k‡yÿ/ã=Þ¾_\¹øùßÿA—Sh®ñcQûh²ˆ¬åúüò…0GiÅ†í«Î´DÊpOFø�Ñ™xºœ2Ó`Gz!�4p©ž}HõìƒÜÊp7”án³A§Ï1¡	ËA’Ä"#‚,ç*ª¤jàÐH
IE‡7½Â‰ª9óâ†j¦{¬‡gð‰3×š÷–åNY|Õ¯?W•/�Ò›Ëß h—©jAMD k*	,\‹“¿ú0e­Ù[oj—¸j˜ÿ†ŸSút±ÌÍ¢ö†aÐ{£/ïÂtEfõþb¨òÕ8æà¶g¯9ø›¢‹fŒŽ¢Öt�#Î…ß2ë³+Ït9y¨;Gð¤ãá}Hõìƒ2Ü52 ]J€jrÎ Mª«0ä¤yüØ”‘^È‡ ÷‚)8¦¥²yÕ H¨Hd…ó•@oLÉÓì¨sãkMo�æªj}oTWo !�9‹bB1çÔáä«RVø�é‘ÇŸý·k ÐåL)ú#Åö/zÕüÌº?		±·Lõ})@,£™ÕŸÿg<ÇZzãÃ_�ñÁkž­YyÚ‹T×~#u¥îü×Ï`¤ß¬yïŽ)�‘Ë	¿=]ƒ®FrÂ^†œ„2Ü©¿³@)ä£ÔD]ª«Ð“QÈ��‡ºs&ìR]ÅÐÐPÆá
ž%èŽÊIŽ†I{bJNžBvùèŽŸƒ€Áîª*!ÁÑ“£¿!7Võ˜yðÍ:íÿttÎYk¯©V •$ÿ”2ÿíÊ5M¹§Ø±Šª’•÷Ýxàµ÷~i‹Ò5´6é÷À¿j>ôÁ‰Ý8Åo>•¶ÕÈÖñ¬þ§üð¹ƒ]‡¾˜w<óŽÇêÍÿ‚V—Ž·¶mÅsÿ«ÏßŒ„šû¥¨:u$üTS¡FMW ›é×Ñ¡743UÕPe³`ÅÐ3
ƒ°/‚0,Ã€°¼Iþq"˜¬H€¡¤ t‚óÀzC`8ó3“‰8MAcý¨UÓWÁ0‚.:%èŽ*˜2¹ƒ”ªc ¡¢ÁËcçlÿMZ¿æÌŽÏþø�jõ$™È\ †Í„+™‚g(Ü<)ÿŸjÿßïpõ9RÔügÐ6ûïé§¾¸¶³ØñJ:ºnÜÄ±ì½©]fh}:(MUqÛó�XW÷m8›šd‹þÎ}?f²jùç´ÏÏ2XÛ2IEÇ¡°žÑàFoÓH<÷&—þl?�j*”<K€ê*ôTºœÃ	04J¸z"’öóMmÎºý ËCÖƒ4‚õ˜‘	†ãÁÀq£ -…–ŒšÛ½fM…rGQ
dªÝº£2\�È±PušzÀä†û{ñûïü3®úô'°Ÿm¼uk*ƒâ .žÒ`°`ÀÍ³ikhTˆ¦ƒÿt;Ë	)•ü³«ß&âDéÿ–:^Ip�7þà�R�!Äm)�º3V#õv'¦
�Ü‰A% }ë7^ñÇ±Æý^}û…Ù™~sÚ3É3†1ZH¡I‡‡g��äœ|ª©Ž„_�t£Ñâ#Ð’³HeàpÙRØlðÞ ÄúpÏ\ÂòÐapÞPFà¤ÏA†Pk¦ÚJª�Áp-u£ì{çˆ„9µnp,“‰¸x<KP×Ü‚ïÝv àPï¶Þý,‚‹:>wóÜjXÔÐã=ÆX�Ru¤€«Àiã�‰B@tî~]öçÚ•Ø–jÆÈ¡C)u¼’
àù'ï�S'é!�nÆÆS»c@ÓeïCì™©Äûçg¬hùÍXãþë7m�ÿ²þöúühªmGSr›m f^ùp8šIÄ -YÈdç¿–C‰š#¤YÑC•¡FÍ•]ï qp;Õ55³üÔ^,ô6 èñ¡‰5É«>=…Îè zå•ÔDj"+œæ[¸¾ÙË Kqð¾˜ô N]NA�A¨1{½Jª�þH�Aóu�šM#[¦ù?”Ô0¯^ Ï$U)E‡[`1«¹óZë±·{¼7ðe W�ÿ›$# Å@$>þC�ÙVAƒ—‡fÐ)³j®þ>�)šû¿³¿Ðü×ÁÜ]®oCÙ¸C ­é&­³?“A‘ÚuÝ?­Ÿ?É·MºKpî†3�g€¿öïù£1ÆnÅCË7|<ÝE °pVK¦®Þ0Äeäg=Xí¸­Œ=«Ä4j¤¸ð[¯ër4Cø­ç­P©¼8·y	6úf¡Ã[Ø_bƒÓ¼‹è2:µ(^9Œ�©!ª&"däõÇß½5'œÚ8¬è†PÛ
ÂrÐ¥8”‘ÞŒH¤d„9!¯Ù#,i¨õp¹8ƒ”ªƒO»EYÏ¦\¸j¾Ó= —­ß´ùkãMºb8>f¨2”¬Â D"�††ÛýS)gýü*…•ü“Ttð,K&· ò¯Æm/®Šf`g¡A“”»Ë³¬X~Ïu/½vâ—Bæd>°k‡þë·˜õ��˜4‰ÖÀÙó—ãìùËaÆŸÜÙuà—+ï»±¢P%ÌU–x{}~£fqXÒ¡¹Â/ËfUYæýº
52 Â‰kÀ�â0äQL—S9Â¯'cÐ£ý�#ƒˆîÞÀœ¬tEëJòå§‚¯±ÏŒSGâ@bô8AVÄ2¶ËšÑeòŠÜ‡GûÌ¦ýÏÜƒÀÂµ-ß˜^ùÍÎ8ùJ`$–‚Àsð\ƒ¤¢ga„SZ†e§4Ôyxð,ÁÊ³!<ºŠ¦Õ¬Øxž¼£äxð²ß¥� Ð7<1ù N7?ú]«:…
@Ò4¸ÒÍV&Ú*:ú˜±ÿbá¿½CR&|k�€îú«/w\GªÇ ôæüm4)ãàu·!ùÖ!4|ìt°õcŸÚ20SÃ0Ì×k–tì?øo·?¹ÿºÛ6o¸þþP¹÷-¼úö³Wÿö–†œÕ8YFQ¥\íj•³RM6_ŠCÍvª«PÂ}™¿õdòp’·e„©¿�~ä›äºË>‡Ú“–Á¿düKæÀ=Üóg€õ›fzg‚œîZÔó¹µòAVÄû<í¸®ýR/x ÑÝ[0ô÷ÿK}Ö9Hñ—%žRàX¸8’F—MkF5(¢Y³!­ßy–à½‹Í~ú„aNÁ8qÒ)îg9žª‰"‘ÑóÒ´É"ZŒT“4Š¤bYiÆ8˜æà8šú 5žâáÌ7º
S*RŠ~‹“ã:R _=ã}¿¦”ÚÚ`ý¿{ûòGº|#ü–MÈ�*B˜�,ËÞ~'¢#ÿíößï¿î¶Íë7m¶ÿ’8¸í*iàt9�ãr|§«~l^�ešN €5ÌCJ yp+â»· Ño©o_�¾ô-ÌŸ3Ÿëÿq<Žçá™ÙÖïA½èÍ¼VL Àˆ¡PÀ´*]{0øÜïM¡�åº  À»Ü0rVÐpjô÷xVÇ¡ìîÅkÚ3–Rñ’:‡xþÉ;d]Sû³½—¨RùUÝjæ¤$œgHÙì;U7ATÒ hÎ:9;EÈ¡ð•“J÷¡_:9®#ðÌ�„S*öºòÒnrðÓ?_ëGÝÕçÃ½¤½ª7ªÂ\Â²ìíw�´±ÇR–e@8af|ß'Ç¼‰è®—�ŒãpO?Âá¨ºýêŸHå>tÙÍ, 3†o1ü†¦A‰@KFAUJï>Dß|,3`µ^ðâçù*nøø—
ßRg?Ü¼˜£ Sd+�Wä>¤‰Ä}º®Ÿ –èÚƒ‘7‡.%`(æù1CIf|Î¡,¡O*æ| éÒâtßÂ,2táÓ`¦®ãs7Ïÿ—Å¼ {÷ÌlR”*MV¥²»d›ÿN i¦uT«€cœ‡þjÜlQòïÍîBÕ	ù—9§'hkºI=Ôw)Rú§taÏ~ŒÆoBã§Î„oÍBÿeË”å¤Ë“/aY\r'¢ ÿvûSGžzmèŠ�§Ð·s/À»àn��={÷‚óÕ€j‡ Kq¸\nPo\¢ †rÒiíV=9ê¨ñ0�oAêÕèÉ¤‘~°Oÿß¦‹Èæ•i~�•Øú boìMšŸåæEÔ”G]‘ g’xû¤<Ú·› „åþ‡êÚ_­Ê»èî-p·-€—á˜äš–ˆBÔ�cMÂOÒŒL\B5LÇÇ³ÉÀ¨dò‡æ?zGbàÜ¾•ït`J÷8ùà¡} Ì6æ¥\ E–Á»JÏõM+EI”îj=c ªê£�¬&­•¢’Õßjã–�˜¤a÷@¡a‰F¿ïôØŽÏbù=×½ôÚ{¿´ÀÚRûõÿîI„ŸÝŠYßü(Ú®<ñ­ûynÇ”'Âlœ¹i5žÂjÄb1ú\ïr¤-…WºßÆ®#lFÐeO „‘Ý¦Y¯É™¬;=Ý_Hççk*”Þ}P%“üÓ"ýÐ¢Ðj"‚¥þfœµé"l^¹~¿pPPÉÖ ÷ÁÊ»°PL	d¯þ'møè]Ï?y‡™jr@7GÞxÞöã2¹€)\Àü=&ë£
@Ñ3¦¦¤ê20›`Z4£½#1‹‚í ÀÞ={3›ò™²‘�%xQšk²\ CNÒR÷Ûì°<þô_I£�4<KÀ³ÎIC§¹¥Vÿ×m|út%ÓŸ*jbe–ÛÏ²êN?uWŸ�¶ÓG €ßï'gûÍÆ�Ÿi7³ß	à`x;jÂØçp¨'ŠÁtcI«�•<�+”z|z2]1Ú¦Ú –{qÜªEØ´è,iÈô»sôT°õèƒQDž¶ÿþ\œ d)€ˆ&å¬þÙ¡9Æ¸ÆHF.”FúýÉ#»áïX	¤€–Œi•´L`v³ì¶æ	EG]zŸÕ´“0mãÿ&È[ ÅÖwF‰R¡@'L¡k*¡J
D°/
T°;A%VAÈÍ9ý[ýÍÀŽ¾ÂÌ¿hJþ¯rÇÌFEwaÍ–ŸÞ÷Ú{¿´…€¬u²ÿÐã¯bø…íhûô9h¸d|+:¦•"ÈÜžÇ’†V,ihÅÙ P Ð–®AJ’èa)F à`xvÁ{çs>¨>„ùõÅà^ÒŽÔÛ�züÕ¢ûBP/z3VÀ-=¯¦W²5¿ª9Î�Ü
Ðkâ{^†oöqk†j*4Ýl\¢ªAÁ3ªN¡éK
™Zhò¥CkÄ8Á¸ý/i7éÀ�˜3ÇŒ4kšVÐñp–PmL¥EÁ×ÛO¹«« ²QÊ*àçU¥ÞèŠÛ…þÞpúËFÅwÁ©`�&eùÑÑÿ‡gÐúùóP³q%|+:�:Ø‹øË»§4­¸ìÍáyøyž,1Í÷ì½ªðoX†‘'^/ºòÛáõx^9–ã)%ÌíâÞ/üÑPåkR]ïPCÓˆ.§Àq¦Mäà1ýeYÕÁ§ÙpƒZÎ²6JÖÖ¥‹Š(œÍã*SIa€ŽW_ß–Q Š¢Ø* 'ð`9žêšJñBõ…ûDfRºÿØY!—óÕ?»}[6ÍÀ›Ý6ÕÔ”:öý-Tì­ÙòÓû(¥×+]C8xÝmØõÉïaä©7ážÝŒ†K6 åë—À¿aÙ¤çL°õø7,CßÝO8~' ¢Iøé³}¿®iw«ˆ|ïÉ—¾j	ƒÈ!4³C›ŠjRý<K QóF}ÿì…¦IHƒaêQ�çàÕ—_Ìl)E:	¶´´ PFzm_+ù7HéIÐÇ@ÓËÏ(,µúoïML’" ûüÄŠ²™ù“šÕãk•XÙHí:Œƒ×Ý†¾E3ÑtÙûP³qeæçh°
ªÿ†eÐ"8ô_¿Í°ýNqKÏ«™‚¨´¯o»_šØ C‹‡˜µ
òP7æ-^Šµµ<êjB¨­«g²gâ©:ÅðÐ ¤p±á.ŠA\Ü�9óTý>–}žêÚæ×wìÌl+E:‰´µ¶âÈáN(‘Á‚×Ü<;eµÿ!gŽ‚×œév³J­þ¯¶qŸ)-ßóÌcR k¶üô¾üôàJa)‚î¶:4^´¡óÖÁ=»îÙÍP%òî#Hí>ò®SþËÀ×úqäÇ*`ú�àÁ¾·3¦¿®ëK›Ñ%@â EbÿÆâ´s.À	ûbÉ!˜<KÐÔØ Ža°pÎL,ð×ÇÇï~qR‹ ëM |i!tÂ<
˜-¼¶¼±kW-C"‘@MM�­à$0oþ<lÙòä¡®‚×êÜSSùçâH¦æŸ!Zšo�j€cIN/ÀRÌÿ]ñª­þÀ8æŒÇ
È†Ò5„#?ú#ºn}µ'-CíßßŠð+:à[Ñ‘£”þð´"+�Ã2¸æ4càöÇK}¥°#Ü�ÿì|– º¦ý  ¡RËñô}ç^HÎýÈ'?©æôœ,³”cˆ�‡7«[ýÎ=óýàÎ9o<z¾ækðÎ[]•IÌæ² +ž~ü¬]ef“&“É£Ÿ'DàìY  yðHÎv'™…z/¦H�¦SD4gr�"NBÑñj—­ï?¦Õg£ß×Þû¥—œF*�{ÑLÔ�±ž3VÁÌ}R{!è…6™öÖ�{I;Üg€zÇ%ø p8>ŒOîú“iúæ¹õ/?½”ð1ž`­‘ŠÝÏ{ü'ã‡ÿ‹ùïY Iéè�)I*Kz&P~‘Å{fø13(¢ÁË££Î…žƒ{ñþ3ÎÄ‘Ã‡·Ž?w¼ÃXËß@uõzÞÄã= ÀœX,ØÚÔ\Ò¸ýöÛññ�ÞÆ™Xqý™íÍ~¡¢œjÁ#°hõ;ãjÜ,¿ïv¼ü‡_¢­µüŒÅXÑšæ"én@SÆ_ŸihB@ßxðãË�ó½Ï…m»ô?×©‡ú^$8ÀR¾5ážÝ\ðz¶B˜‚%ôdv”×÷£û/§ÊK»ÇuƒRªŒËvÜ‹© ØÇx‚kJ™þ„fRMyŠåø¹_»ëI2Þ<
Ëè‘ i¹”µò[D  ¼Ù:ØRsjÝàY�!XÕæÃ™k±oß>,]ý^H#ý}„åO§º:æ’PÂòË¨®n€o~ózœ~º™8cÆ[7 >TS°0dã™gžÁ©§ž
 8ñ/€nðAGÝØ[°�í5.¢;zŽÛ^zßûæÕ™ú‘,Ä@˜7Vmêš;žêxÿe/T’ø“�qKîó'é>�N.ïqœ@h«Cè”ð7¾Û®ª$Cë�I µÛ4'J1°õ�¡ŒÀ¢ˆø‹;{f;†_Ø^1¹g‡”*ã³»°f–6Ó,¿s@W|øß~Š5ï;Û{Á×t‰Dƒ±$Y)èT”s}¢.QÀq³ZÐÁ³³B"Ö´Ðêçñìã�àüóÏ(%Ø cíÚuøö·Í>„µµµ¶n  Ìš5«è�úûûÑÔdF)WþË=ðÌX0e«ƒ—wTòkPŠ¶ ˜“ êÃÿüËW°ëÅ¿ [O`Ó8ïqÆ­ Þ¼øú9ú‘á·!“®^Ý‹fÂ¿j><ÇÍ‚kN³­…��D$
f$	=b&Ò¨Ã¦?¥¯IçÌX9_kæ°A/¸æð.1‡ŸèßòU·$ÕzyÂcxñ¬²MP	¹”~oî¢¥øÄÍÁÛé>q’f «o ‰heõ÷Þ@l:_ Ù/à’å�XÔhfÖ{x|ú#Ä#?€| ×Žãr÷è €Ûn»sæÌ—0³}ŽîÄœËnDûIçMÉêïâZbQß?nžA{�«`»ªSüúGßÅc·} ä#fšwõ0n•¸ò¾¼ºîÊ›!×UóÄœ µëp“N<"\í�f)m} žãf�¯õƒÌn€70ÍÆ`åù–â�ôf"ÉÃ}ù,~Uý Ãña\µç!Ëìw&ü @éç`åY—f„?�£³·ßv"¯�2«5Çƒp"ø@„Ú–Œð GÌ¹s�A{È¯@ð¹Ï~6­ è§×oÚü�1‘‚„|”vX>ñ·¿áÓŸú‰¼^/<žÂòçráÀeË–âÈáNÄnGÓªæWã¥ˆ¿|XmÙòÁ³â)W`¡þæ†_(‘�çÇË¹d£*6ÑUžØþ(øèxÂ‚Õ MÊJ!Ä#‚¯ñ�õ{ ‡<Ôír|;)I¢l8I @�%¡ta²±#Ü�kö>2ëçÅ9~Æ¬5’‘ ÐÚO `
ÿ¡®îÌ>Z|áíÏ"¾çe¤ºÞÉéG˜–ã©wö2â[¸'¼ï<,oY ØÖGÈÅ!äöbÝºuÖîþžùí qéHÂdo»÷OÆ%_Œ`0ˆD"a« Ã#%y€ãW­Æ#?ŒÔá�SÂü×z8¸V	Ö¸Ù¢aÙ—;£Jª¨[ø¸®þu óß¹wäÍ¿�X­ó¬ÚªõòÚ/^\�°à?2(¥x°ïmügç³–`î#,ÿA§[ZÀ‡~ùwˆ¾öuõeÌþðögÐó—›K
}1°OO»ü*rî§®B�›E�‡Ç™ÍÊ;Á‚šˆ€°üòŠÉÀ´ËÂr<õ/YOÂÛž |ô²ËðéO}
@q2°”�M^vûË<“—iÊ³3ƒÎLÿlâ/QIÃí¯öæÔe0††¡®ƒ'Wcj30†TàbX³å§÷QÐ-Õ:Þ?RªŒí|
7îÿ›YàC˜çOpM%•&ˆú @M×ÃKòhƒ�¾Ç�±?`V×=vÛwá˜ô(ró¡T%†œ¤,ÇS"zº*9&á„™VÛÛq<q7ÏÍ½÷OÎ´
±}ÿH	>ã„•«Àr<€C»ßÏWS1š|ÎLƒR´Š‡ŸÜ.(Ê’5úDµ„¨¢  ¶­öÃÅZ‡Cq<=°ço½wíH?´äûë7^~úØ_ò 8²ÍÌ­¯Œvª;ñÂq�çú}’jöÉ³âÚ�<ö(tM%º¦>TéùRMù ?ïÂ3s	XO ÁåfPMDpï}æ\‚D"a[P*)Èà„÷¼‡ Ààë��ëº+A%¦�‡+:xwûòÆ|3†7Q¾ZÍó­j^ä/Þ~&ü™k\„�q7�üGÀáø0¾Ûó"n>ø’f¡N¥¸ ?ë<°uLèOðUªÊÜó¦oÖÚ÷#P×ˆ¤ªC•exf.Bpñ‰`ˆ’ÈX	¥àªiDÍ	gáÄOþN¿ð2ÈC€%M^ˆj
gŸ{.¢ÑHŒ°üGAg“M “øþ êV½œ¯B¨| É[a¨2ví;„ó?p6\.t]‡×ë-8OEÜ€ƒ�à¹çžA*ÆÒ³¯˜ðïÓÅ4x8É‹áX‚™!—ík)UÇß*h;æáÙ¯=uåÚñ5aÉCÕ3xÖoÚ,þH
<3‚ï¤T¿ê{wv¿™å�“;Ò…=ãŽó2¼x’¡Ê�xgúOû—[áªŸ�Á‘0†Ã¹CJÓíÂ•È t9	ªk ,Vô€ó†àné@pF†œÇŒ€€—5b^�ýÃaÜø™Kðêk¯Q]×>ZIx*�¨ô
€&ß¬ãà_¸|°lzŠolß|ñ~ ÀYgŸ�¯ýó? m	Áb9¯¾ú*V¯^ 8ïE}Ûì	üV�'ü”bv­«èêÿÐÎ¡‚)¿²$mw?tËêñ¦^çcBRøÒ‚ONEnÀt†%øî}Ûbø�­/|±Z#Î-¤•ÀÿñÞ`Ó²K®Â¼MæH¿Á‘0²ê8À¢±¾^-«gø°ûñ{ðïÿý$úÇÒýÿúM›ÅçŸºëqPãdÞDÝ‰‚õø!F»3‹í8xû×2£ÒÊå”Ê´ò–]z-V_øéjÞâ´Dxygu½�/ÚégwÙ•ybŒ.¯OÆ_1LHiÔÏw<yä˜+0ŠÃñaÜÙÿ&®Úó}}ä0±Ì}ÂrW¯ßxù—í{­ê3Ø©¡&œð{]NÎïyó™_ø3tMEãìEhnl@]m‚¿á÷z‰èáõzr~êkBh¨¯5ê‚~²¬ÙA�ã�§þ·~ó³øã½÷@MÆŸ#,÷!úß*9¯ÎÛ¾ÐK ö„³ÀyƒkF{‹˜–€¬¿Ñ]fÏƒí»÷áüœU5§‹b®ÉŸ”$„B!ÛÏÛà0^yù%$F±ôÌ�LÈ÷[ëátjtóLÑ˜TÒðÀÛ“cú[˜°$þtW ¥ÊØ>Œÿ4Ëw³°„ü|ýÆ+n®¶9Wikàë,ÇŸ£k*ñÍ:3­€»u>¼ÍsPÓØ*x!ð,UQHDÃˆöv"¾ÿMÈ‡¶aÿ®V§�‡@˜Ÿ‚*ó`&üü ×Â;k)„Ú–Ì(sÖåÍL/€Î{ÿñCo ¾ø¥«qñ‡Î`,fd»§Ýxf-^YÕ{[I¶ Ì­s�ùÿþÍ>‰æ¶EWõ	ñÏ?ûÀD=+Úi*Ó„§–Ð?‘ìÄ£}»óãíû@È¿¦'OŠàçƒñk©œ¸�êúz€®G:õ¶ú ¼BXîæÑ±f¡Y¼ ¿·m>ü‹×ƒÔ‚ËŠÏ‹íe ˜3öüä3T×TÂr<ýÕ­¿$¥\�b\@ÇâeØ¿kæœú!lüÂ·ªv?+‰÷—óû_îŒâ¹ƒ¹n†¨«žúâÚ	+{�ðÆh/¯ýâÅ,ÃÜ;‘ƒSJ)ÞŠô`Ÿ4‚'Föá¥XW‰$²uý¦+ÖN•ðÛÁTÉ6jèm ­!ë5Çv“†ãcà];«AJ¦«ýÐäªiDè=çøýBmk† ÆåƒPÓŒÞÇoC÷#æ”«¹‹–â×¿0§ÔÙ
¹Ýn46ö*ýÎoÆ×®þXŽ§þÕ¤ZIA3‚‚ã�_)¿¿;ªàwoölWRÉ+^ýêú»ªr²E0)R9™ƒJ)Ž$F°/5Œíò Þ‰”øB–¿‘êêS}-“‰láç½AÔ®=¬ÛŸã÷sÞø,e@8BM3Çƒj*ÞùÑ'�èÚ 7CÐ.*`—˜ˆDQÓÖ5©X	éW¬Ð0C~w¿Þ‹¨œ7Ž>½së×OÝ<A_Ëè½žè Ò|@*°sªkŠ�R
IS0('Ñ$ªÉÌîwbè–"èTãE…�åxÊˆžÌké±ß™î´ÙûQÂœ\mÆº"_økN8œ'>ØPÔïLk€G[êÙ‹Ý?øxæ^~û?ÉtÊçŠYW~ùüô'?€«¦ùÙ ;öÆ NK|�Ò©¾€½ß?Q!?;Lš]>>à�Þ·ðoUí\éñ^1]Áˆ¡T´Š[Â.x ïáÐTzV[n]‘Á
bæw5ÉV}„VW³¢k:Â
C¢„ðN„«aFÎûø`CN¢…ÁïGç}fŸ WM#~û­ƒ¶|€!xèÐ!tÌ›OuM%Çüz¬<ëÃcº®Z‡Z‡3ý€Ò¤ßSûÂÓ}0Ìª‰Mò³Ã¤:æcåžØ‹kö<<)çÈr<åý5„åÅŒ€3.ÑÞå�*%‘ß…×PePMÉì]…2t,/‚¸aÅµ'ª¹Ã´�Éöß‚tšo1ájšrH?Ëï/†wÿFÒi½s-Å¾ý­¢JÀÎÈ¶.úÁ_*.
¸8Ô{8ÇŒ{�X”ôÛÙ—ÀÃ»¿þÉðû³1éÌÜ«ë®ü†a*êp8>Œó·¥›žòU Ý•¼ Ã-ôÔ5gš'zf/‡Øº /‚ÝP¢C ÂŒúuz*%œKÎ]…<Ü°|F)P–‡–ˆÀ�“ö®«ÐS1NÈ„µÞ­J€°üÁ¿éšJ\5�®:¬è)+ü„!6Ì,ylCNbÏÍŸÍð¥ºÙ¹ÙVÀÂó>‹“.»ÚñuyÍùäw÷ÉFLÆ=[

}¤dòÛ¯ÿ¿õ_Ÿð/)“Þ#ù—G^~êòÙk–ò”,qúž ïÂûß2óå	óPz?€•ü0nÿ6WýŒ¯1¢Œèë«E`ápÞ X—´`¦<a9ªd¦ÇºüàüµàCM¦EÀ`À˜·�eYP |°|°œ¯†ª€ê*Äš&ðõ3`(x_Jd  š©ªœI8á!úÑÙê8Œ'XKUù^Pã3Ô0ˆ·m>‚ËßÖå¨/+üBM3Súq$�Àâ÷bäµG`¨2ººŽ ¯¿ëO:	©T*'IHÓ4(Š’S?
… (:yî¹gÞ·�ÎXw6ñ¤g$–‚‹#hñŽ…¿Ñ/ ¦ˆ›•4Ü³qÝ2ª  ÍIDATmrÞpUQŸxíÚ÷N8é—�)i’þÎ¼Åž©‰§�Nö'„àåÈ–Â ,·ÔxºÒÏ¤ªœò´/9“*Ò Ðå$¼íÇ™«>Ë›Âlè`Ý°¢¼7Þ_Þ_Fp�uûÀð"Ë�áEh‰0 €\àýuêZÁyC™é;„å!Öµ�uû–a0‚†ª@¬i‚¤ÔÐ›aèaxñEjèG/'@˜3©*=àxÀLòñu¼¬Ç1Ô�ì’ÂÏ9ó«ëjC˜½ò$t>ÿ ¥†AöîÙUÓðžã�G*•‚ àÓ35M+(Zûžãqço~‹Hx„Äú:1ïäsK~^¥‰>µ>{‚1¥êøÃöADåÜÊFY’¶{#}gzæi2¿6`Š@ç�­úÖ�õ7#š:�Rãä=ª®á™‘és¦·�åsëŽ¿H(=‡õÕ‚uûánš±~&X—¬ÛÂ°`8Œ ‚p¼ù· BKäúüœÇÎ—VŒà6÷åE€R°ž „PXÑÖåƒ.% j€°œièø@=Ñ"ý”†�a˜�SJã ^ËuMÌU_ù9@¿ÀÇ{ƒ¨[õ>¸šç‚÷×€÷�~µvÂ bÝÇÂrsy]pÕ4"Ð¾˜ô¼ú8¥†A¶oÛ–Q‰D"G	$%	^—l:R ¸DÌëèÀ=÷ÜƒXï!_šç/³ý¼J…ßïâÐ\$ÍWÕ)îß1€¾¸š³� ÃŽnxúŸß×çä3ª�©“³tøÊõçmÑÃñ�BÊ>^p¸§oXŽk'.ÿO¨*WÜw ÑµwŸ»¥ãkÖß†ªÀÝ2šG@a7d“=`8oZ°Ý~ðþÚŒ`›û¸!àjœ:¨an'†M€åÁ
n°./¨¡�óÕCŠC““ÀûA˜ÓË½ZQYí`ý¦ÍbçÁmWQUºÀ 0³ûÞÆ€PÓÎí½./ÄºÖ_l˜U±ð[ð·ÌF }19ò’Ioß¶-ãä+�X"žS+°páBìÝ·Û·mCÿŽ¿Ûº•
¿›g0#T¼Gá_wcÿHîo1þÏ|ù½ïLÂ×f‹)S €Y4ô©¶ÕïB>PN	X<@B•Õ”­0}ûŠ@U9åmœ±œ° ôTžÖy œ`šö‚Ô$Ó®€¹Ò‡@½àae]^0o6Ïtû3¯3‚zj4¼CXœ' šV.„aÁºü`¨ËñPcÃ è,–e?GH×õO«æ*ë7mw¾õñÎýoüÀ¥ DÞD`ñ{án›Îí¨3]¥´°sÞ„P.G8qL+>ü-³œ},K`ïž=Ø¹sN?ý}H$9œ@>°~ýzÜóû{	��#;¶`Á) ›wæXÇ>?P:Ñ þ¶g;úr	bÆÐÀ3ôüg¾tâß'÷[ÌÅ”*  ¸µë•·ÓJàâRáABv«aì‰õÃœw‡ûÇòy5«No`=Ás8_x-8_Ü-æ*/z@X L:"0z{(¨®eÌzÖãç«ÃrÝvM÷f” Ãñ`]>pî,w€!ýy,!Ô„,kàDªÊ_ H=á„�SM2ž`-Õ”/txó6Pc3€Z–ã©îJâ_´œ¯| œ7dÞ3j¤c+8on¨­RŸ¿˜ð[°,K	tuÁ³/½ŠSO>	”ÒŒÈ'½^/Þsüñ¸ëîßP92@”¾ý˜yâ9±ý@yáî@¯uÅ¶Ë’tÅß¿râŸ&û»ÌÇ”+ ÀTŸž±&F€3J)FÕñèð hY¿ióOÆÒ5gÅÌ¥ÛÂ.ï'YÑã',=ƒ»iNFØÞ]2¿0Âr`Ñl�á«ëò˜ÖÇgÂ…Œà‚¡HWÀ‚É' º
Â‰émX—º"†BÞ•q	øP8—z"L©aˆ Ndæ*jÐ9/L6QÈðâIÔ0þƒªÒ- ÎEZð½3“Àqë	l ç	B5æøö¬è.ÈíÌ8¿X×V–í·PNø-ø[f£eùzÒ³õYhR#ƒý¸ÿÑ'1á"Ô…PU^¯·@	Ìž=®@yâÑG0xä ¼F+OÚT5áñP/uên/G¾öü—×þ|¢¿?'˜
  n=òò‹å”@“àÅýÛ(5ß‘#»þ:�è<°Ut¬L1‚ûÀôÑ9_êjCx„<"·*gZïÊ‚„°¶Ã‹¶9 „ãÁºý0²,yÂpà¼A€¦âÀ¨K`YbC;á\^PM±,‚•ÔÐ?àó ia˜õ›®8<Ö¶aÅ`úöÛO7?wRCÿ2€• ÄÑÿD"Ô¶€sû!„ÁºrÛt	Ázð�Ñ¤KØYW .øÝÎÓu]5�hYszw¼56MJà‰G�ªiX¶lTU…(Š0#G	œ´nM†èÜù&8–ÇìåkÊ~^9á¹3ŠÙÿãŸ]õ�j~oãÁ´Q €©>3cà;%À³:µÙë5ctŽÿÈ¿î‘óõŒÙ
Šy³Ûá9¸x^‘Ç`¼PÐ	Ã‚ ™Pßèv„1sr¶§-Ftƒjr†`òy.Ã»Ày‚E Ô¶@ð×‚Pš”  €zYç�­_aÎ°„Ô–'ë7^qªO°– Çƒ�3@éGA˜ëº¿õKjè—™Ÿ xgÂÛñø¬&\ |ÚÜ·¢&£×ã†X—›ÃŸë
�œ Sø=Bå½ü�3ß{ÂýÝH¦“…¶oÛ†g_z‹ÌË²`,Ëæ(�sÏ>¯¾ñ:öîÙƒ}oþl%àwq%	?»Ò^ÀLôyáËko¬øÂ&Ó²F÷ÕuWþ!ä:;%�•[¿isÃX&]{ç©*Åú{Öœ9hjiË¼NièIØ¾WOF`hjÁvCNeòË„¼Ôè�í,>5: -ÎÙFºƒ–Œ‚j*9irÑ¨±‘Rõ} é!QP#¯Àœ	‚­ øíÞÌr<uÕ6¶¦bÃL–3£n?XÑÂæ¡¢œ7”+øY¯åö”‚‡gPã+ž;_	>u¶Þõ_™ûÄr<½ôÒ"—\|1Z[[QSSŽã2)Ã‰H§�q¶l1»½ÿãÿ§|ô‹9î€A)ê<ýÅ…ÿÅCüÝfåŸŠ,?'˜–
 (®(¥8ãµ_§Çd�}VZÇçnžË	â¾Ì�`9¿z-Ø¬¦ŽbHªFÁ{©¦BKFl�kÈ)èR¼@ø-hÉ(4›n¼T“¡ÆÃÐ“…¯šb†³,92CŠƒ¦¢PÑLb¥à½¦Ïºý`õàýµéûÁ›.�è1óòPJð­|«Ùaù²¤ŸS¿Ä‡zñÒ/¾‰èîÑq®šF|ò²�ââ�ŸI¶Š‡úûûqÞyçg”Àâ3>‚‹¯ùO¸86“áW¬¦°/î¦¯ðÓX À+ë®¼†!ä¦|%ð“#/â¶ÎW Â<jŒ¹ï`¾ÐÖÜˆ¶¹2¯ËªŽ½qÛ÷–R  §-;š
-6Ã¦×}1E@Œè†ª@—bfß,¥ JI“‹ÐU[®0ùŠì:â6Âò`8$]‘¿Ò[(%ø ÒaÓ@ÁûKYc5ù�âàS÷aû½?ÌQ’3f¶ãü>„‹?t>QWW‡ÆÆÆK`î¢¥¸ôúŸcþ¼yEsûûN¾Àôóùó1­ `¯²‹ƒÆ4Ž*�×ßê‹G÷RUÎt£X¼òÃïqe*‚â2ú£öš†œ„žGþ±é]—“%• PÜÈ¼žCKFaÈ)3¡ÈUØŸê¨*ÃÐÌº+$i7Ô¼_\Æ¬'Î29¶øÊfÖBøl{ôºÝàƒE_·³ªiò—ƒÁÞŽwþv_ŽûÄ{ƒ¸äƒçâ}§�†µk×¢½Õt/þÈ‡ÓCOM«ákßù–¯ÛPx\�âÁ·qp¤ð™îÂL3Ð·yùÅOµ­~;;Y((¸±#Þ‡ÃR Ôƒ1’�‡ž¹GjX{n”Rúk["#MÍ£%©^�CBR*· “åÏ&Ù¬UÎL)v¯„¹3¢„-]Hgr¿~$È!�4É	`Ò†¬ÛÖí7ßgóÃºýf“à6žÒiÌ×Ærà<3¥7Ý©×n?Kðyméðµ2#Í}Bnu~wŽË5‘ðz½xÏ)ïÃŠ÷_LâI	#‡vQjÄPelß¶<ð xðÏØþö[ðx½¸òÊ+‘’u¼òòKÐ¤žùó½èîÄÒeË!zÌ,G3· G"¹ßch�%éŠéê+…ioXH÷¸Ãj(’M2žàìñ”Õ.ºúö]TWZç‚ºA±w0i;ž
0-ª«¶«ÕUh‰(¨Vš«44†’*jX1uª«™QÞ†’²%#+�¥´XÑÂ‰`8Œè)iXû³ÞPŽÒsŸÏ7i«¾…/�PžùêÅÞ§îÇÝƒDa4™÷qüÒÅèêîÆ‘Ã£=9]5�øäµÿŠ¥›>ˆÞ,håE€ažè—>ý…Õ�OÚŽG� 2G~K™C)ÅEoÞ�© äû ½v¬Ç]üõ{×ÉÈs™›ÂrX´leŽ+�Pt´ç\¢ ª¤�’Š¹–ŒÂ�âpÓìOæpùI5Ù º
CÓ@59£J¹ Ù¥¹¥Ìz»÷–sJÁçóÁç&ÔßÏ†‹cÐè –P6:¥Úý*^zìAt¾ñœ­2°½–YÇ¡õ_Dý’ÌxôIïæSU
 H·ëþYû@ï[¸qÿß€jXy„ ÛëÇ’eËsLT;>ÀÃ�æ›'ñ’JÀ©5`A—S%]ˆjÀIˆÎ$ýÜ¯ö™{éáñŽyxfÂ- »U¿DŽ@îÂ��Ûpø­W1ØÝ‰ÃûÞ�4Ü[4ìê›uZÎüVo¸ØLdï‰ÀQ§  3cíÔÀÝnUË
X¿i³8¸bãÖlW ?* ä*Žãàwå®„²,#/½ÒWb f
-ÕTèR†’§ÙŸsì"ñ{Â‰ãzÀ|ÁåÇævÏå:aV€“Uß~‘E£_ _„“§4<¿ë0ö’}ºªüµV—>üÌ�„'ä¢&G¥°ðêº+ÿãÏý;¯³¬ Â	Ç�§Ùf~n  ,X¸¡ºúœýºFˆ«(~N”€Sk€p¢m�j*¨&C—S²RÅ@8³JÑúk0èxQLð³Qm%À ÞËÃïpDW6šýBîâïH¨øëÎ~„S6n•®MÛ¿Õ
 0ÉÁ5[~ú€ü†ñ¾5Þ{‹¯úõçCÏao—.=žÀhs‹ƒ[· nþ
#¦1EŸpM7�ÅÒ†óQNS E�—¥ò�i%™¿›Çäª4$0}|–ãK
~6ªå
„\j=Ø
›Íº­�â«> ¼Õ—À“ïl§”FYª_9™<'G½ Òg«ØC=Ÿ°HA£2/Üþm�zœö±kÐW‘J§Þ—ã,P]5}þ<×€qùÊ¾w<¯p»D°_0°Ó	ÆkxM>¾bÁÊ¯ú’ªã©}aÛD0B�í^V¿üh"ûŠá]¡ ª�õ›6‹ƒ+7>F55“e¨w£ÿ±_Aî¥þÕ$ª�aŽ”€— ºœÌTV²ú�cQ „åáu‹­öÅ0+À+°¨óðûù@y_ º"2þº³ß6\W¤;ý�Ýö™é4âm<8¦ Š`Ãõ÷‡ú¢á—%¹pèå‡††^yø/ 0çÔ7ŸsÕÿdö3ƒ	C©ÒJ@Ó(RÒ‘5`�°|Ú2Hë�N€µÒWCèót9ËG�às,ƒf¿ ŸPüÜUƒâ¥ýƒx³§0òòn1ùîËTŸÀtÅ37^îøÜÍgK�ÛÏyëù{ :�ÛùãNCRÑáÒD�~"¯¡;oÄS68–÷ÿÛ;ûØªÎ:ŽŸç9çžû~o_i+XÖÂºN ¸¦BjL†fâÌÔÄlþ�C—8ÙœgÒD3’EˆD·l¨™Fb”2§t&3å5aH#8y]K¡o—{{_ÎÛóøÇí)íí¹¯½·´ô|’þçÐÒÛþ>Ïï÷{~Ï¹¾t�Oªy{ÀØ¤¡$�wê­�#nè�Þ£’«bŸIB3r–Ó	| ¨ñÉ¨óåÎ¤zo©xû¿ƒ¶�>"xOÈÍ6üëÉÕsj‹¯œ ªV®?ÚøÙo>èó°¼½m\	ÍD_4�çYó•…œ †~{`Lã×r‚°t°QI†wLJ f$Ø³‘Y
Hð+¥5÷,
I÷Sº‰“W†mW} s¾ËŸG Ò±î1¥·©%e=EØ%Ix`Åýðz&Oèé&G_T³­íÈ&‚BÏÐO—*ÑoÕX1Bn·Dv3x]¬äÀ÷¸ø$¸åÜ¥Åù›	t_²ýYÝM�¾\8(êUßûí�(¥ã']’„em-‡'¿µç‘”9åð¹ÈÁ|€µPÊôÞD‰ Î¯ä¬ó�ô¾þ‘‹CüjD�r£"J¸¹ÛûæË�wK£/Ž Š uó®Ù<1Q Ð¾´�õuSî/¦$°PU¦¡C3sPóN
 äfð¹¼òí8(Å¯ü…~¾tŸrØC´ïßí«þDIëæ]-²ÇˆJRÛÄ¿_ØÔ€%Í‹@3fƒJÉBnÝˆ§TŒêÈz
±Ì¤ ¬•>3è'Â
žæóŒ5ó¾ÎÎ\�ãôµû'<Ý¥þBpPk;÷…oÄ"oP&Mz‘ÏÀò{ï™Ò 
ïØÇ$4šnTD•€W¦ðH~E*x¿_f>9{P†oþHOò»4œýu7�í�ÑÁæâ9pP"ëS?¾~;¥ô©ÌkíK[° ¶fJ6 ¤Ë‚�¸žõ2ß`Œn
$tUUn4æ¢œ�©€ÌXÑoGf) 1Š�›!ì‘rvõ-ÎßLàäÕûù}ÌÏtßG Ó¤mËž�„ÒßdöªX|�}6À9GLãˆ$�)A\èPŒ…n
è¦	M7 ¼h)”" +ÐeFà–(%�))ë_«(é>A®±Ýñ×‚\HàÔµHÖÀ'‚÷<ò3så�•Æ@ÈÖ €ÖÅÍXÔXo›dŠ œ'ä,1èœŒÏ
hÆd9h‚¢Ú+AfS¥#3iì·Cb•	òlÈŒ¢ÚÃpí½XÝ±&ïŠŸÒMôôÇq¦÷VVÁ{ˆà?Ÿ�u~.”‰\%�Ï@[sã”íÂ‰$’Ihj
	:3Ûù&äf
™Q„ÜBn6ð'ïÇéãÝønç‹¶õ~$i §wïhY{#NàçÆ@™ißº·C¨‰Wì²�\eA×îN|aÓ³ ž bª�HÊDÊ˜~�Ÿ�;) �ÌThº_`³ÊóD?Øð€Xºjybû„=t.peDÅÙ¾ˆí>¾…ø…á äÊ€©":õìÝö=±õà…I?Õ0SÓ•’ÁL
Àêî—Djæýú‡�ãüÑ.´Ü·ŸÚú*.Ç�³ÏÁ9ìSè‹N�_Ž *Hëæ]-²?¼�<bw½¡* _¨ÿüñ— ÏüñxÖÏe˜1Õ@ÊUe¡R`pI
#EüDâš‰¿¼þN½ö“ÿ&ís…ë·,ùÖKA¥nÑ¤û„Q®«ûBn¶c¾wõ‹ÅÀÐ¾uo‡ÐÏgÎ À‡Ý�è§ú›?¶áÉ_í/ø0Žj˜Hh&R†@Êà%gå€Ì(Ü#ž±!ŸbƒÝ"®™¸8Åå�(†ãôèÎ¾ðè¿!øêUóDô¹ûŸýýÓîÆ% ‚÷¨£‘ßÕpí•ùº�?]Ì m[öl$À6«?9w}‡v�z‚où›Z‡Ú¾Ñ‰†Új,j¬G•·ð·Æ¶P�´t“§w¸€É“gÍr	ÀjøSJ!Q2~W‘\Œ–´ªÛÑÓ0��}&Wþôü±‘Ó]«­?Éµhí/»ïsÒüéãàÐ¶eÏFBðÔ…�Oüˆëj7 Ô¬zh°ñó›Æg	˜âÁ’ú ÔÖ”$;3�%˜"mƒÄðø½^„«Òo*MØâ+G`gc$©ãÃáQÜ¸•Â`,5O=“¸úÎù�¯-ðÓ;�#€YÂÂ/=ýNxÙšOÛ]óHµÕ¨«¡.è+Û™ý÷ßzJ 
ŸøÌ+ö}é\`(®c /8à-L]û»¼«®¶fï\{Þþ\Áy"Ð,Á·xÅKä£¢9óZÒ¸Ô?„KýCé{ƒ!,)üú¼ð¹J;9øþ¹s P6Ä5‘”�áX·b£IqÛ”>\ð˜0ŒnÅëÿƒ/6xÀ©ë+�“Ì2Ú·îízêæ=l';<AUÐÅ¥ äSàRÜðz<ðÉ4g¶ð‹¯}LVð³?Éû5t. 1Õ„j
Dã	hj
#) ©iˆ«zÁ+ûD˜ËÝ#8?”ê;Xsâo'çÃüÙ„#€YL)2ÈÄ#hÌ�¾ÛY‚âR�ìEWçWo Àºmo,hjjÄ(—93’4ÅÓ‰aRÓ�4	¸¡•ÜvXïûàDC0ü¶³ÊßYÌZ7ïjq¹½Ÿ’k=óV•*‹¡ãÐßõÛM ÐôÐw^®[ýpÙÿÏÌåî1tí]SMô˜ÉÑcÎ
?ûp0GiÝ¼«EòøWJ×È¡ú6®«íÅH¡÷ÀÎñ­µª•ë�6?úÜƒ…þÛ‰pÁc²â½lèÚ»ŒI×)ÁY¯$Îðý¯œw‚}öãà.bmç¾°¨ªi¾qå­r¸¾Åˆ.¡‘ƒµ~®«íÖ}¢ùì¶¯¬¦Þ „ÉË—ÿôÍnëº™Œ»ÃuQ ÐâÑ^êrßdLº®%¢ƒn_ð†ß«ôs-u“Œ]qRø¹ÍÿÒ‡+¦Å1È®    IEND®B`‚               h          ¨   00     ¨%          ›     X4   V S _ V E R S I O N _ I N F O     ½ïþ                  ?                        ¸   S t r i n g F i l e I n f o   ”   0 8 0 9 0 4 b 0   ,   C o m p a n y N a m e     a m p h p   Ô V  F i l e D e s c r i p t i o n     E x e c u t e s   a   c o m m a n d   a n d   p a s s e s   t h e   s t d i o   s t r e a m s   o f   t h e   c r e a t e d   p r o c e s s   t o   T C P   s o c k e t s   0   F i l e V e r s i o n     1 . 0 . 0 . 0   :   I n t e r n a l N a m e   P r o c e s s W . e x e     V   L e g a l C o p y r i g h t   C o p y r i g h t   ( C )   a m p h p   2 0 1 7     B   O r i g i n a l F i l e n a m e   P r o c e s s W . e x e     @   P r o d u c t N a m e     P r o c e s s   W r a p p e r   4   P r o d u c t V e r s i o n   0 . 0 . 0 . 0   D    V a r F i l e I n f o     $    T r a n s l a t i o n     	°<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
                                                                                                                                                                                                                                                                                                                                                              ü   0)050U0k0u0‡0£0¯0¶0Ð0Ü0ü0
1G1z1ˆ1Ž1�2×2ú23)363<3c3·3Á3Ú3û3444H4V4�4ž4¥4±4¿4ÿ45#5v5œ5¬56&6A6e6�6Õ78/8Z8·8Ã8ê8ý899M9g9¢9¶9ß9ó9û9:
:":J:d:j:¡:×:å:ý:;*;Q;W;‹;ß;å;÷;<)<N<X<k<…<Ž<”<Á<â<é<ó<
==+=L=b==ª=Á=ë=>->_>g>„>Ç>7?Y?’?œ?¢?±?è?î?      L  0,0>0F0Q0V0a0k0¢0³0â0ì0ò0&1/151‚1Â1û142M2W2]2”2�2£2Ù23H3‰3�3º3Ë3Ú3é344/4>4\4‡4¢4µ4Å4õ4'5B5U5e5y5ú5$6-6I6m6‘6©6Ë6ß6å6ë6ñ67/777<7A7O7W7n7v7˜7œ7 7¤7¨7±7ß7"8V8�8™8È8Ý8'909G9r9‚9´9å9ð9õ9::?:f:‡:œ:¤:º:Å:Ë:Ñ:Ú:å:õ:<;e;Å;ó;<	<</<4<A<B=K=V=]=}=ƒ=‰=�=•=›=¢=©=°=·=¾=Å=Ì=Ô=Ü=ä=ð=ù=þ=>>>(>8>H>Q>¶>â>1?D?W?c?s?„?ª?¿?Æ?Ì?Þ?è?   0  ¨   F0S0z0‚0›0Õ0ð0ü011!1P1X1p1v1¡1Ç1Ð1Ö12²2Ñ2Û2ì2ú2;3A3Š3�3µ3º3ß3ñ34[4`4s4�4œ4§4/585@5‡5–5�5Ó5Ü5é5ô5ý5666"6(6.646:6@6F6L6R6X6^6d6j6p6v6|6‚6ˆ6Ž6”6š6 6¦6¬6²6ð6 @     p1x1„1ˆ1 1¤1 P  $   3 3$3(3,30343ü5 66,909L9P9 p     0 0$0,00080<0D0                                                                                                                                                                                                <?php

namespace Amp\Process\Internal;

final class ProcessStatus
{
    const STARTING = 0;
    const RUNNING = 1;
    const ENDED = 2;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}<?php

namespace Amp\Process\Internal;

use Amp\Deferred;
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
use Amp\Struct;
abstract class ProcessHandle
{
    use Struct;
    /** @var ProcessOutputStream */
    public $stdin;
    /** @var ProcessInputStream */
    public $stdout;
    /** @var ProcessInputStream */
    public $stderr;
    /** @var Deferred */
    public $pidDeferred;
    /** @var int */
    public $status = ProcessStatus::STARTING;
}<?php

namespace Amp\Process\Internal\Posix;

use Amp\Deferred;
use Amp\Process\Internal\ProcessHandle;
/** @internal */
final class Handle extends ProcessHandle
{
    /**
     *
     */
    public function __construct()
    {
        $this->pidDeferred = new Deferred();
        $this->joinDeferred = new Deferred();
        $this->originalParentPid = \getmypid();
    }
    /** @var Deferred */
    public $joinDeferred;
    /** @var resource */
    public $proc;
    /** @var resource */
    public $extraDataPipe;
    /** @var string */
    public $extraDataPipeWatcher;
    /** @var string */
    public $extraDataPipeStartWatcher;
    /** @var int */
    public $originalParentPid;
}<?php

namespace Amp\Process\Internal\Posix;

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Deferred;
use Amp\Loop;
use Amp\Process\Internal\ProcessHandle;
use Amp\Process\Internal\ProcessRunner;
use Amp\Process\Internal\ProcessStatus;
use Amp\Process\ProcessException;
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
use Amp\Promise;
/** @internal */
final class Runner implements ProcessRunner
{
    const FD_SPEC = [
        ["pipe", "r"],
        // stdin
        ["pipe", "w"],
        // stdout
        ["pipe", "w"],
        // stderr
        ["pipe", "w"],
    ];
    /** @var string|null */
    private static $fdPath;
    /**
     *
     */
    public static function onProcessEndExtraDataPipeReadable($watcher, $stream, Handle $handle)
    {
        Loop::cancel($watcher);
        $handle->extraDataPipeWatcher = null;
        $handle->status = ProcessStatus::ENDED;
        if (!\is_resource($stream) || \feof($stream)) {
            $handle->joinDeferred->fail(new ProcessException("Process ended unexpectedly"));
        } else {
            $handle->joinDeferred->resolve((int) \rtrim(@\stream_get_contents($stream)));
        }
    }
    /**
     *
     */
    public static function onProcessStartExtraDataPipeReadable($watcher, $stream, $data)
    {
        Loop::cancel($watcher);
        $pid = \rtrim(@\fgets($stream));
        /** @var $deferreds Deferred[] */
        list($handle, $pipes, $deferreds) = $data;
        if (!$pid || !\is_numeric($pid)) {
            $error = new ProcessException("Could not determine PID");
            $handle->pidDeferred->fail($error);
            foreach ($deferreds as $deferred) {
                /** @var $deferred Deferred */
                $deferred->fail($error);
            }
            if ($handle->status < ProcessStatus::ENDED) {
                $handle->status = ProcessStatus::ENDED;
                $handle->joinDeferred->fail($error);
            }
            return;
        }
        $handle->status = ProcessStatus::RUNNING;
        $handle->pidDeferred->resolve((int) $pid);
        $deferreds[0]->resolve($pipes[0]);
        $deferreds[1]->resolve($pipes[1]);
        $deferreds[2]->resolve($pipes[2]);
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::enable($handle->extraDataPipeWatcher);
        }
    }
    /**
     * @inheritdoc
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle
    {
        $command = \sprintf('{ (%s) <&3 3<&- 3>/dev/null & } 3<&0; trap "" INT TERM QUIT HUP;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3; exit $RC', $command);
        $handle = new Handle();
        $handle->proc = @\proc_open($command, $this->generateFds(), $pipes, $cwd ?: null, $env ?: null, $options);
        if (!\is_resource($handle->proc)) {
            $message = "Could not start process";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            throw new ProcessException($message);
        }
        $status = \proc_get_status($handle->proc);
        if (!$status) {
            \proc_close($handle->proc);
            throw new ProcessException("Could not get process status");
        }
        $stdinDeferred = new Deferred();
        $handle->stdin = new ProcessOutputStream($stdinDeferred->promise());
        $stdoutDeferred = new Deferred();
        $handle->stdout = new ProcessInputStream($stdoutDeferred->promise());
        $stderrDeferred = new Deferred();
        $handle->stderr = new ProcessInputStream($stderrDeferred->promise());
        $handle->extraDataPipe = $pipes[3];
        \stream_set_blocking($pipes[3], false);
        $handle->extraDataPipeStartWatcher = Loop::onReadable($pipes[3], [self::class, 'onProcessStartExtraDataPipeReadable'], [$handle, [new ResourceOutputStream($pipes[0]), new ResourceInputStream($pipes[1]), new ResourceInputStream($pipes[2])], [$stdinDeferred, $stdoutDeferred, $stderrDeferred]]);
        $handle->extraDataPipeWatcher = Loop::onReadable($pipes[3], [self::class, 'onProcessEndExtraDataPipeReadable'], $handle);
        Loop::unreference($handle->extraDataPipeWatcher);
        Loop::disable($handle->extraDataPipeWatcher);
        return $handle;
    }
    /**
     *
     */
    private function generateFds() : array
    {
        if (self::$fdPath === null) {
            self::$fdPath = \file_exists("/dev/fd") ? "/dev/fd" : "/proc/self/fd";
        }
        $fdList = @\scandir(self::$fdPath, \SCANDIR_SORT_NONE);
        if ($fdList === false) {
            throw new ProcessException("Unable to list open file descriptors");
        }
        $fdList = \array_filter($fdList, function (string $path) : bool {
            return $path !== "." && $path !== "..";
        });
        $fds = [];
        foreach ($fdList as $id) {
            $fds[(int) $id] = ["file", "/dev/null", "r"];
        }
        return self::FD_SPEC + $fds;
    }
    /**
     * @inheritdoc
     */
    public function join(ProcessHandle $handle) : Promise
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::reference($handle->extraDataPipeWatcher);
        }
        return $handle->joinDeferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function kill(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::cancel($handle->extraDataPipeWatcher);
            $handle->extraDataPipeWatcher = null;
        }
        /** @var Handle $handle */
        if ($handle->extraDataPipeStartWatcher !== null) {
            Loop::cancel($handle->extraDataPipeStartWatcher);
            $handle->extraDataPipeStartWatcher = null;
        }
        if (!\proc_terminate($handle->proc, 9)) {
            // Forcefully kill the process using SIGKILL.
            throw new ProcessException("Terminating process failed");
        }
        $handle->pidDeferred->promise()->onResolve(function ($error, $pid) {
            // The function should not call posix_kill() if $pid is null (i.e., there was an error starting the process).
            if ($error) {
                return;
            }
            // ignore errors because process not always detached
            @\posix_kill($pid, 9);
        });
        if ($handle->status < ProcessStatus::ENDED) {
            $handle->status = ProcessStatus::ENDED;
            $handle->joinDeferred->fail(new ProcessException("The process was killed"));
        }
        $this->free($handle);
    }
    /**
     * @inheritdoc
     */
    public function signal(ProcessHandle $handle, int $signo)
    {
        $handle->pidDeferred->promise()->onResolve(function ($error, $pid) use($signo) {
            if ($error) {
                return;
            }
            @\posix_kill($pid, $signo);
        });
    }
    /**
     * @inheritdoc
     */
    public function destroy(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->status < ProcessStatus::ENDED && \getmypid() === $handle->originalParentPid) {
            try {
                $this->kill($handle);
                return;
            } catch (ProcessException $e) {
                // ignore
            }
        }
        $this->free($handle);
    }
    /**
     *
     */
    private function free(Handle $handle)
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::cancel($handle->extraDataPipeWatcher);
            $handle->extraDataPipeWatcher = null;
        }
        /** @var Handle $handle */
        if ($handle->extraDataPipeStartWatcher !== null) {
            Loop::cancel($handle->extraDataPipeStartWatcher);
            $handle->extraDataPipeStartWatcher = null;
        }
        if (\is_resource($handle->extraDataPipe)) {
            \fclose($handle->extraDataPipe);
        }
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        if (\is_resource($handle->proc)) {
            \proc_close($handle->proc);
        }
    }
}<?php

namespace Amp\Process\Internal\Windows;

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Loop;
use Amp\Process\Internal\ProcessStatus;
use Amp\Process\ProcessException;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class SocketConnector
{
    const SERVER_SOCKET_URI = 'tcp://127.0.0.1:0';
    const SECURITY_TOKEN_SIZE = 16;
    const CONNECT_TIMEOUT = 1000;
    /** @var resource */
    private $server;
    /** @var PendingSocketClient[] */
    private $pendingClients = [];
    /** @var Handle[] */
    private $pendingProcesses = [];
    /** @var string */
    public $address;
    /** @var int */
    public $port;
    /**
     *
     */
    public function __construct()
    {
        $flags = \STREAM_SERVER_LISTEN | \STREAM_SERVER_BIND;
        $this->server = \stream_socket_server(self::SERVER_SOCKET_URI, $errNo, $errStr, $flags);
        if (!$this->server) {
            throw new \Error("Failed to create TCP server socket for process wrapper: {$errNo}: {$errStr}");
        }
        if (!\stream_set_blocking($this->server, false)) {
            throw new \Error("Failed to set server socket to non-blocking mode");
        }
        list($this->address, $this->port) = \explode(':', \stream_socket_get_name($this->server, false));
        $this->port = (int) $this->port;
        Loop::unreference(Loop::onReadable($this->server, [$this, 'onServerSocketReadable']));
    }
    /**
     *
     */
    private function failClientHandshake($socket, int $code)
    {
        \fwrite($socket, \chr(SignalCode::HANDSHAKE_ACK) . \chr($code));
        \fclose($socket);
        unset($this->pendingClients[(int) $socket]);
    }
    /**
     *
     */
    public function failHandleStart(Handle $handle, string $message, ...$args)
    {
        Loop::cancel($handle->connectTimeoutWatcher);
        unset($this->pendingProcesses[$handle->wrapperPid]);
        foreach ($handle->sockets as $socket) {
            \fclose($socket);
        }
        $error = new ProcessException(\vsprintf($message, $args));
        $deferreds = $handle->stdioDeferreds;
        $deferreds[] = $handle->joinDeferred;
        $handle->stdioDeferreds = [];
        foreach ($deferreds as $deferred) {
            $deferred->fail($error);
        }
    }
    /**
     * Read data from a client socket.
     *
     * This method cleans up internal state as appropriate. Returns null if the read fails or needs to be repeated.
     *
     * @param resource $socket
     * @param int $length
     * @param PendingSocketClient $state
     *
     * @return (string | null)
     */
    private function readDataFromPendingClient($socket, int $length, PendingSocketClient $state)
    {
        $data = \fread($socket, $length);
        if ($data === false || $data === '') {
            return null;
        }
        $data = $state->receivedDataBuffer . $data;
        if (\strlen($data) < $length) {
            $state->receivedDataBuffer = $data;
            return null;
        }
        $state->receivedDataBuffer = '';
        Loop::cancel($state->readWatcher);
        return $data;
    }
    /**
     *
     */
    public function onReadableHandshake($watcher, $socket)
    {
        $socketId = (int) $socket;
        $pendingClient = $this->pendingClients[$socketId];
        if (null === ($data = $this->readDataFromPendingClient($socket, self::SECURITY_TOKEN_SIZE + 6, $pendingClient))) {
            return;
        }
        $packet = \unpack('Csignal/Npid/Cstream_id/a*client_token', $data);
        // validate the client's handshake
        if ($packet['signal'] !== SignalCode::HANDSHAKE) {
            $this->failClientHandshake($socket, HandshakeStatus::SIGNAL_UNEXPECTED);
            return;
        }
        if ($packet['stream_id'] > 2) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_STREAM_ID);
            return;
        }
        if (!isset($this->pendingProcesses[$packet['pid']])) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_PROCESS_ID);
            return;
        }
        $handle = $this->pendingProcesses[$packet['pid']];
        if (isset($handle->sockets[$packet['stream_id']])) {
            $this->failClientHandshake($socket, HandshakeStatus::DUPLICATE_STREAM_ID);
            \trigger_error(\sprintf("%s: Received duplicate socket for process #%s stream #%d", self::class, $handle->pid, $packet['stream_id']), E_USER_WARNING);
            return;
        }
        if (!\hash_equals($packet['client_token'], $handle->securityTokens[$packet['stream_id']])) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_CLIENT_TOKEN);
            $this->failHandleStart($handle, "Invalid client security token for stream #%d", $packet['stream_id']);
            return;
        }
        $ackData = \chr(SignalCode::HANDSHAKE_ACK) . \chr(HandshakeStatus::SUCCESS) . $handle->securityTokens[$packet['stream_id'] + 3];
        // Unless we set the security token size so high that it won't fit in the
        // buffer, this probably shouldn't ever happen unless something has gone wrong
        if (\fwrite($socket, $ackData) !== self::SECURITY_TOKEN_SIZE + 2) {
            unset($this->pendingClients[$socketId]);
            return;
        }
        $pendingClient->pid = $packet['pid'];
        $pendingClient->streamId = $packet['stream_id'];
        $pendingClient->readWatcher = Loop::onReadable($socket, [$this, 'onReadableHandshakeAck']);
    }
    /**
     *
     */
    public function onReadableHandshakeAck($watcher, $socket)
    {
        $socketId = (int) $socket;
        $pendingClient = $this->pendingClients[$socketId];
        // can happen if the start promise was failed
        if (!isset($this->pendingProcesses[$pendingClient->pid]) || $this->pendingProcesses[$pendingClient->pid]->status === ProcessStatus::ENDED) {
            \fclose($socket);
            Loop::cancel($watcher);
            Loop::cancel($pendingClient->timeoutWatcher);
            unset($this->pendingClients[$socketId]);
            return;
        }
        if (null === ($data = $this->readDataFromPendingClient($socket, 2, $pendingClient))) {
            return;
        }
        Loop::cancel($pendingClient->timeoutWatcher);
        unset($this->pendingClients[$socketId]);
        $handle = $this->pendingProcesses[$pendingClient->pid];
        $packet = \unpack('Csignal/Cstatus', $data);
        if ($packet['signal'] !== SignalCode::HANDSHAKE_ACK || $packet['status'] !== HandshakeStatus::SUCCESS) {
            $this->failHandleStart($handle, "Client rejected handshake with code %d for stream #%d", $packet['status'], $pendingClient->streamId);
            return;
        }
        $handle->sockets[$pendingClient->streamId] = $socket;
        if (\count($handle->sockets) === 3) {
            $handle->childPidWatcher = Loop::onReadable($handle->sockets[0], [$this, 'onReadableChildPid'], $handle);
            $deferreds = $handle->stdioDeferreds;
            $handle->stdioDeferreds = [];
            // clear, so there's no double resolution if process spawn fails
            $deferreds[0]->resolve(new ResourceOutputStream($handle->sockets[0]));
            $deferreds[1]->resolve(new ResourceInputStream($handle->sockets[1]));
            $deferreds[2]->resolve(new ResourceInputStream($handle->sockets[2]));
        }
    }
    /**
     *
     */
    public function onReadableChildPid($watcher, $socket, Handle $handle)
    {
        $data = \fread($socket, 5);
        if ($data === false || $data === '') {
            return;
        }
        Loop::cancel($handle->childPidWatcher);
        Loop::cancel($handle->connectTimeoutWatcher);
        $handle->childPidWatcher = null;
        if (\strlen($data) !== 5) {
            $this->failHandleStart($handle, 'Failed to read PID from wrapper: Received %d of 5 expected bytes', \strlen($data));
            return;
        }
        $packet = \unpack('Csignal/Npid', $data);
        if ($packet['signal'] !== SignalCode::CHILD_PID) {
            $this->failHandleStart($handle, "Failed to read PID from wrapper: Unexpected signal code %d", $packet['signal']);
            return;
        }
        // Required, because a process might be destroyed while starting
        if ($handle->status === ProcessStatus::STARTING) {
            $handle->status = ProcessStatus::RUNNING;
            $handle->exitCodeWatcher = Loop::onReadable($handle->sockets[0], [$this, 'onReadableExitCode'], $handle);
            if (!$handle->exitCodeRequested) {
                Loop::unreference($handle->exitCodeWatcher);
            }
        }
        $handle->pidDeferred->resolve($packet['pid']);
        unset($this->pendingProcesses[$handle->wrapperPid]);
    }
    /**
     *
     */
    public function onReadableExitCode($watcher, $socket, Handle $handle)
    {
        $data = \fread($socket, 5);
        if ($data === false || $data === '') {
            return;
        }
        Loop::cancel($handle->exitCodeWatcher);
        $handle->exitCodeWatcher = null;
        if (\strlen($data) !== 5) {
            $handle->status = ProcessStatus::ENDED;
            $handle->joinDeferred->fail(new ProcessException(\sprintf('Failed to read exit code from wrapper: Received %d of 5 expected bytes', \strlen($data))));
            return;
        }
        $packet = \unpack('Csignal/Ncode', $data);
        if ($packet['signal'] !== SignalCode::EXIT_CODE) {
            $this->failHandleStart($handle, "Failed to read exit code from wrapper: Unexpected signal code %d", $packet['signal']);
            return;
        }
        $handle->status = ProcessStatus::ENDED;
        $handle->joinDeferred->resolve($packet['code']);
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        // Explicitly \fclose() sockets, as resource streams shut only one side down.
        foreach ($handle->sockets as $sock) {
            // Ensure socket is still open before attempting to close.
            if (\is_resource($sock)) {
                @\fclose($sock);
            }
        }
    }
    /**
     *
     */
    public function onClientSocketConnectTimeout($watcher, $socket)
    {
        $id = (int) $socket;
        Loop::cancel($this->pendingClients[$id]->readWatcher);
        unset($this->pendingClients[$id]);
        \fclose($socket);
    }
    /**
     *
     */
    public function onServerSocketReadable()
    {
        $socket = \stream_socket_accept($this->server);
        if (!\stream_set_blocking($socket, false)) {
            throw new \Error("Failed to set client socket to non-blocking mode");
        }
        $pendingClient = new PendingSocketClient();
        $pendingClient->readWatcher = Loop::onReadable($socket, [$this, 'onReadableHandshake']);
        $pendingClient->timeoutWatcher = Loop::delay(self::CONNECT_TIMEOUT, [$this, 'onClientSocketConnectTimeout'], $socket);
        $this->pendingClients[(int) $socket] = $pendingClient;
    }
    /**
     *
     */
    public function onProcessConnectTimeout($watcher, Handle $handle)
    {
        $running = \is_resource($handle->proc) && \proc_get_status($handle->proc)['running'];
        $error = null;
        if (!$running) {
            $error = \stream_get_contents($handle->wrapperStderrPipe);
        }
        $error = $error ?: 'Process did not connect to server before timeout elapsed';
        foreach ($handle->sockets as $socket) {
            \fclose($socket);
        }
        $error = new ProcessException(\trim($error));
        foreach ($handle->stdioDeferreds as $deferred) {
            $deferred->fail($error);
        }
        \fclose($handle->wrapperStderrPipe);
        \proc_close($handle->proc);
        $handle->joinDeferred->fail($error);
    }
    /**
     *
     */
    public function registerPendingProcess(Handle $handle)
    {
        // Use Loop::defer() to start the timeout only after the loop has ticked once. This prevents issues with many
        // things started at once, see https://github.com/amphp/process/issues/21.
        $handle->connectTimeoutWatcher = Loop::defer(function () use($handle) {
            $handle->connectTimeoutWatcher = Loop::delay(self::CONNECT_TIMEOUT, [$this, 'onProcessConnectTimeout'], $handle);
        });
        $this->pendingProcesses[$handle->wrapperPid] = $handle;
    }
}<?php

namespace Amp\Process\Internal\Windows;

use Amp\Struct;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class PendingSocketClient
{
    use Struct;
    public $readWatcher;
    public $timeoutWatcher;
    public $receivedDataBuffer = '';
    public $pid;
    public $streamId;
}<?php

namespace Amp\Process\Internal\Windows;

/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class SignalCode
{
    const HANDSHAKE = 0x1;
    const HANDSHAKE_ACK = 0x2;
    const CHILD_PID = 0x3;
    const EXIT_CODE = 0x4;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}<?php

namespace Amp\Process\Internal\Windows;

use Amp\Deferred;
use Amp\Process\Internal\ProcessHandle;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class Handle extends ProcessHandle
{
    /**
     *
     */
    public function __construct()
    {
        $this->joinDeferred = new Deferred();
        $this->pidDeferred = new Deferred();
    }
    /** @var Deferred */
    public $joinDeferred;
    /** @var string */
    public $exitCodeWatcher;
    /** @var bool */
    public $exitCodeRequested = false;
    /** @var resource */
    public $proc;
    /** @var int */
    public $wrapperPid;
    /** @var resource */
    public $wrapperStderrPipe;
    /** @var resource[] */
    public $sockets = [];
    /** @var Deferred[] */
    public $stdioDeferreds;
    /** @var string */
    public $childPidWatcher;
    /** @var string */
    public $connectTimeoutWatcher;
    /** @var string[] */
    public $securityTokens;
}<?php

namespace Amp\Process\Internal\Windows;

/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class HandshakeStatus
{
    const SUCCESS = 0;
    const SIGNAL_UNEXPECTED = 0x1;
    const INVALID_STREAM_ID = 0x2;
    const INVALID_PROCESS_ID = 0x3;
    const DUPLICATE_STREAM_ID = 0x4;
    const INVALID_CLIENT_TOKEN = 0x5;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}<?php

namespace Amp\Process\Internal\Windows;

use Amp\Deferred;
use Amp\Loop;
use Amp\Process\Internal\ProcessHandle;
use Amp\Process\Internal\ProcessRunner;
use Amp\Process\Internal\ProcessStatus;
use Amp\Process\ProcessException;
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
use Amp\Promise;
use const Amp\Process\BIN_DIR;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class Runner implements ProcessRunner
{
    const FD_SPEC = [
        ["pipe", "r"],
        // stdin
        ["pipe", "w"],
        // stdout
        ["pipe", "w"],
        // stderr
        ["pipe", "w"],
    ];
    const WRAPPER_EXE_PATH = PHP_INT_SIZE === 8 ? BIN_DIR . '\\windows\\ProcessWrapper64.exe' : BIN_DIR . '\\windows\\ProcessWrapper.exe';
    private static $pharWrapperPath;
    private $socketConnector;
    /**
     *
     */
    private function makeCommand(string $workingDirectory) : string
    {
        $wrapperPath = self::WRAPPER_EXE_PATH;
        // We can't execute the exe from within the PHAR, so copy it out...
        if (\strncmp($wrapperPath, "phar://", 7) === 0) {
            if (self::$pharWrapperPath === null) {
                $fileHash = \hash_file('sha1', self::WRAPPER_EXE_PATH);
                self::$pharWrapperPath = \sys_get_temp_dir() . "/amphp-process-wrapper-" . $fileHash;
                if (!\file_exists(self::$pharWrapperPath) || \hash_file('sha1', self::$pharWrapperPath) !== $fileHash) {
                    \copy(self::WRAPPER_EXE_PATH, self::$pharWrapperPath);
                }
            }
            $wrapperPath = self::$pharWrapperPath;
        }
        $result = \sprintf('%s --address=%s --port=%d --token-size=%d', \escapeshellarg($wrapperPath), $this->socketConnector->address, $this->socketConnector->port, SocketConnector::SECURITY_TOKEN_SIZE);
        if ($workingDirectory !== '') {
            $result .= ' ' . \escapeshellarg('--cwd=' . \rtrim($workingDirectory, '\\'));
        }
        return $result;
    }
    /**
     *
     */
    public function __construct()
    {
        $this->socketConnector = new SocketConnector();
    }
    /**
     * @inheritdoc
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle
    {
        if (\strpos($command, "\x00") !== false) {
            throw new ProcessException("Can't execute commands that contain null bytes.");
        }
        $options['bypass_shell'] = true;
        $handle = new Handle();
        $handle->proc = @\proc_open($this->makeCommand($cwd ?? ''), self::FD_SPEC, $pipes, $cwd ?: null, $env ?: null, $options);
        if (!\is_resource($handle->proc)) {
            $message = "Could not start process";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            throw new ProcessException($message);
        }
        $status = \proc_get_status($handle->proc);
        if (!$status) {
            \proc_close($handle->proc);
            throw new ProcessException("Could not get process status");
        }
        $securityTokens = \random_bytes(SocketConnector::SECURITY_TOKEN_SIZE * 6);
        $written = \fwrite($pipes[0], $securityTokens . "\x00" . $command . "\x00");
        \fclose($pipes[0]);
        \fclose($pipes[1]);
        if ($written !== SocketConnector::SECURITY_TOKEN_SIZE * 6 + \strlen($command) + 2) {
            \fclose($pipes[2]);
            \proc_close($handle->proc);
            throw new ProcessException("Could not send security tokens / command to process wrapper");
        }
        $handle->securityTokens = \str_split($securityTokens, SocketConnector::SECURITY_TOKEN_SIZE);
        $handle->wrapperPid = $status['pid'];
        $handle->wrapperStderrPipe = $pipes[2];
        $stdinDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stdinDeferred;
        $handle->stdin = new ProcessOutputStream($stdinDeferred->promise());
        $stdoutDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stdoutDeferred;
        $handle->stdout = new ProcessInputStream($stdoutDeferred->promise());
        $stderrDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stderrDeferred;
        $handle->stderr = new ProcessInputStream($stderrDeferred->promise());
        $this->socketConnector->registerPendingProcess($handle);
        return $handle;
    }
    /**
     * @inheritdoc
     */
    public function join(ProcessHandle $handle) : Promise
    {
        /** @var Handle $handle */
        $handle->exitCodeRequested = true;
        if ($handle->exitCodeWatcher !== null) {
            Loop::reference($handle->exitCodeWatcher);
        }
        return $handle->joinDeferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function kill(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        \exec('taskkill /F /T /PID ' . $handle->wrapperPid . ' 2>&1', $output, $exitCode);
        $failStart = false;
        if ($handle->childPidWatcher !== null) {
            Loop::cancel($handle->childPidWatcher);
            $handle->childPidWatcher = null;
            $handle->pidDeferred->fail(new ProcessException("The process was killed"));
            $failStart = true;
        }
        if ($handle->exitCodeWatcher !== null) {
            Loop::cancel($handle->exitCodeWatcher);
            $handle->exitCodeWatcher = null;
            $handle->joinDeferred->fail(new ProcessException("The process was killed"));
        }
        $handle->status = ProcessStatus::ENDED;
        if ($failStart || $handle->stdioDeferreds) {
            $this->socketConnector->failHandleStart($handle, "The process was killed");
        }
        $this->free($handle);
    }
    /**
     * @inheritdoc
     */
    public function signal(ProcessHandle $handle, int $signo)
    {
        throw new ProcessException('Signals are not supported on Windows');
    }
    /**
     * @inheritdoc
     */
    public function destroy(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->status < ProcessStatus::ENDED && \is_resource($handle->proc)) {
            try {
                $this->kill($handle);
                return;
            } catch (ProcessException $e) {
                // ignore
            }
        }
        $this->free($handle);
    }
    /**
     *
     */
    private function free(Handle $handle)
    {
        if ($handle->childPidWatcher !== null) {
            Loop::cancel($handle->childPidWatcher);
            $handle->childPidWatcher = null;
        }
        if ($handle->exitCodeWatcher !== null) {
            Loop::cancel($handle->exitCodeWatcher);
            $handle->exitCodeWatcher = null;
        }
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        foreach ($handle->sockets as $socket) {
            if (\is_resource($socket)) {
                @\fclose($socket);
            }
        }
        if (\is_resource($handle->wrapperStderrPipe)) {
            @\fclose($handle->wrapperStderrPipe);
        }
        if (\is_resource($handle->proc)) {
            \proc_close($handle->proc);
        }
    }
}<?php

namespace Amp\Process\Internal;

use Amp\Process\ProcessException;
use Amp\Promise;
interface ProcessRunner
{
    /**
     * Start a process using the supplied parameters.
     *
     * @param string $command The command to execute.
     * @param (string | null) $cwd The working directory for the child process.
     * @param array $env Environment variables to pass to the child process.
     * @param array $options `proc_open()` options.
     *
     * @return ProcessHandle
     *
     * @throws ProcessException If starting the process fails.
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle;
    /**
     * Wait for the child process to end.
     *
     * @param ProcessHandle $handle The process descriptor.
     *
     * @return Promise<int> Succeeds with exit code of the process or fails if the process is killed.
     */
    public function join(ProcessHandle $handle) : Promise;
    /**
     * Forcibly end the child process.
     *
     * @param ProcessHandle $handle The process descriptor.
     *
     * @throws ProcessException If terminating the process fails.
     */
    public function kill(ProcessHandle $handle);
    /**
     * Send a signal signal to the child process.
     *
     * @param ProcessHandle $handle The process descriptor.
     * @param int $signo Signal number to send to process.
     *
     * @throws ProcessException If sending the signal fails.
     */
    public function signal(ProcessHandle $handle, int $signo);
    /**
     * Release all resources held by the process handle.
     *
     * @param ProcessHandle $handle The process descriptor.
     */
    public function destroy(ProcessHandle $handle);
}<?php

namespace Amp\Process;

class StatusError extends \Error
{
}<?php

namespace Amp\Process;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\OutputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Failure;
use Amp\Promise;
final class ProcessOutputStream implements OutputStream
{
    /** @var \SplQueue */
    private $queuedWrites;
    /** @var bool */
    private $shouldClose = false;
    /** @var ResourceOutputStream */
    private $resourceStream;
    /** @var StreamException|null */
    private $error;
    /**
     *
     */
    public function __construct(Promise $resourceStreamPromise)
    {
        $this->queuedWrites = new \SplQueue();
        $resourceStreamPromise->onResolve(function ($error, $resourceStream) {
            if ($error) {
                $this->error = new StreamException("Failed to launch process", 0, $error);
                while (!$this->queuedWrites->isEmpty()) {
                    list(, $deferred) = $this->queuedWrites->shift();
                    $deferred->fail($this->error);
                }
                return;
            }
            while (!$this->queuedWrites->isEmpty()) {
                /**
                 * @var string $data
                 * @var \Amp\Deferred $deferred
                 */
                list($data, $deferred) = $this->queuedWrites->shift();
                $deferred->resolve($resourceStream->write($data));
            }
            $this->resourceStream = $resourceStream;
            if ($this->shouldClose) {
                $this->resourceStream->close();
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function write(string $data) : Promise
    {
        if ($this->resourceStream) {
            return $this->resourceStream->write($data);
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->shouldClose) {
            throw new ClosedException("Stream has already been closed.");
        }
        $deferred = new Deferred();
        $this->queuedWrites->push([$data, $deferred]);
        return $deferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->resourceStream) {
            return $this->resourceStream->end($finalData);
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->shouldClose) {
            throw new ClosedException("Stream has already been closed.");
        }
        $deferred = new Deferred();
        $this->queuedWrites->push([$finalData, $deferred]);
        $this->shouldClose = true;
        return $deferred->promise();
    }
    /**
     *
     */
    public function close()
    {
        $this->shouldClose = true;
        if ($this->resourceStream) {
            $this->resourceStream->close();
        } elseif (!$this->queuedWrites->isEmpty()) {
            $error = new ClosedException("Stream closed.");
            do {
                list(, $deferred) = $this->queuedWrites->shift();
                $deferred->fail($error);
            } while (!$this->queuedWrites->isEmpty());
        }
    }
}<?php

namespace Amp\Process;

const BIN_DIR = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'bin';
const IS_WINDOWS = (PHP_OS & "\xdf\xdf\xdf") === 'WIN';
if (!\function_exists(__NAMESPACE__ . '\\escapeArguments')) {
    if (IS_WINDOWS) {
        /**
         * Escapes the command argument for safe inclusion into a Windows command string.
         *
         * @param string $arg
         *
         * @return string
         */
        function escapeArguments(string $arg) : string
        {
            return '"' . \preg_replace_callback('(\\\\*("|$))', function (array $m) : string {
                return \str_repeat('\\', \strlen($m[0])) . $m[0];
            }, $arg) . '"';
        }
    } else {
        /**
         * Escapes the command argument for safe inclusion into a Posix shell command string.
         *
         * @param string $arg
         *
         * @return string
         */
        function escapeArguments(string $arg) : string
        {
            return \escapeshellarg($arg);
        }
    }
}<?php

namespace Amp\Process;

use Amp\Loop;
use Amp\Process\Internal\Posix\Runner as PosixProcessRunner;
use Amp\Process\Internal\ProcessHandle;
use Amp\Process\Internal\ProcessRunner;
use Amp\Process\Internal\ProcessStatus;
use Amp\Process\Internal\Windows\Runner as WindowsProcessRunner;
use Amp\Promise;
use function Amp\call;
final class Process
{
    /** @var ProcessRunner */
    private $processRunner;
    /** @var string */
    private $command;
    /** @var string */
    private $cwd = "";
    /** @var array */
    private $env = [];
    /** @var array */
    private $options;
    /** @var ProcessHandle */
    private $handle;
    /** @var int|null */
    private $pid;
    /**
    * @param (string | string[]) $command Command to run.
    * @param (string | null) $cwd Working directory or use an empty string to use the working directory of the
    parent.
    * @param mixed[] $env Environment variables or use an empty array to inherit from the parent.
    * @param mixed[] $options Options for `proc_open()`.
    *
    * @throws \Error If the arguments are invalid.
    */
    public function __construct($command, string $cwd = null, array $env = [], array $options = [])
    {
        $command = \is_array($command) ? \implode(" ", \array_map(__NAMESPACE__ . "\\escapeArguments", $command)) : (string) $command;
        $cwd = $cwd ?? "";
        $envVars = [];
        foreach ($env as $key => $value) {
            if (\is_array($value)) {
                throw new \Error("\$env cannot accept array values");
            }
            $envVars[(string) $key] = (string) $value;
        }
        $this->command = $command;
        $this->cwd = $cwd;
        $this->env = $envVars;
        $this->options = $options;
        $this->processRunner = Loop::getState(self::class);
        if ($this->processRunner === null) {
            $this->processRunner = IS_WINDOWS ? new WindowsProcessRunner() : new PosixProcessRunner();
            Loop::setState(self::class, $this->processRunner);
        }
    }
    /**
     * Stops the process if it is still running.
     */
    public function __destruct()
    {
        if ($this->handle !== null) {
            $this->processRunner->destroy($this->handle);
        }
    }
    /**
     *
     */
    public function __clone()
    {
        throw new \Error("Cloning is not allowed!");
    }
    /**
     * Start the process.
     *
     * @return Promise<int> Resolves with the PID.
     *
     * @throws StatusError If the process has already been started.
     */
    public function start() : Promise
    {
        if ($this->handle) {
            throw new StatusError("Process has already been started.");
        }
        return call(function () {
            $this->handle = $this->processRunner->start($this->command, $this->cwd, $this->env, $this->options);
            return $this->pid = (yield $this->handle->pidDeferred->promise());
        });
    }
    /**
     * Wait for the process to end.
     *
     * @return Promise<int> Succeeds with process exit code or fails with a ProcessException if the process is killed.
     *
     * @throws StatusError If the process has already been started.
     */
    public function join() : Promise
    {
        if (!$this->handle) {
            throw new StatusError("Process has not been started.");
        }
        return $this->processRunner->join($this->handle);
    }
    /**
     * Forcibly end the process.
     *
     * @throws StatusError If the process is not running.
     * @throws ProcessException If terminating the process fails.
     */
    public function kill()
    {
        if (!$this->isRunning()) {
            throw new StatusError("Process is not running.");
        }
        $this->processRunner->kill($this->handle);
    }
    /**
     * Send a signal signal to the process.
     *
     * @param int $signo Signal number to send to process.
     *
     * @throws StatusError If the process is not running.
     * @throws ProcessException If sending the signal fails.
     */
    public function signal(int $signo)
    {
        if (!$this->isRunning()) {
            throw new StatusError("Process is not running.");
        }
        $this->processRunner->signal($this->handle, $signo);
    }
    /**
     * Returns the PID of the child process.
     *
     * @return int
     *
     * @throws StatusError If the process has not started or has not completed starting.
     */
    public function getPid() : int
    {
        if (!$this->pid) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->pid;
    }
    /**
     * Returns the command to execute.
     *
     * @return string The command to execute.
     */
    public function getCommand() : string
    {
        return $this->command;
    }
    /**
     * Gets the current working directory.
     *
     * @return string The current working directory an empty string if inherited from the current PHP process.
     */
    public function getWorkingDirectory() : string
    {
        if ($this->cwd === "") {
            return \getcwd() ?: "";
        }
        return $this->cwd;
    }
    /**
     * Gets the environment variables array.
     *
     * @return string[] Array of environment variables.
     */
    public function getEnv() : array
    {
        return $this->env;
    }
    /**
     * Gets the options to pass to proc_open().
     *
     * @return mixed[] Array of options.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * Determines if the process is still running.
     *
     * @return bool
     */
    public function isRunning() : bool
    {
        return $this->handle && $this->handle->status !== ProcessStatus::ENDED;
    }
    /**
     * Gets the process input stream (STDIN).
     *
     * @return ProcessOutputStream
     */
    public function getStdin() : ProcessOutputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stdin;
    }
    /**
     * Gets the process output stream (STDOUT).
     *
     * @return ProcessInputStream
     */
    public function getStdout() : ProcessInputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stdout;
    }
    /**
     * Gets the process error stream (STDERR).
     *
     * @return ProcessInputStream
     */
    public function getStderr() : ProcessInputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stderr;
    }
    /**
     *
     */
    public function __debugInfo() : array
    {
        return ['command' => $this->getCommand(), 'cwd' => $this->getWorkingDirectory(), 'env' => $this->getEnv(), 'options' => $this->getOptions(), 'pid' => $this->pid, 'status' => $this->handle ? $this->handle->status : -1];
    }
}<?php

namespace Amp\Process;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\PendingReadError;
use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Failure;
use Amp\Promise;
use Amp\Success;
final class ProcessInputStream implements InputStream
{
    /** @var Deferred */
    private $initialRead;
    /** @var bool */
    private $shouldClose = false;
    /** @var bool */
    private $referenced = true;
    /** @var ResourceInputStream */
    private $resourceStream;
    /** @var StreamException|null */
    private $error;
    /**
     *
     */
    public function __construct(Promise $resourceStreamPromise)
    {
        $resourceStreamPromise->onResolve(function ($error, $resourceStream) {
            if ($error) {
                $this->error = new StreamException("Failed to launch process", 0, $error);
                if ($this->initialRead) {
                    $initialRead = $this->initialRead;
                    $this->initialRead = null;
                    $initialRead->fail($this->error);
                }
                return;
            }
            $this->resourceStream = $resourceStream;
            if (!$this->referenced) {
                $this->resourceStream->unreference();
            }
            if ($this->shouldClose) {
                $this->resourceStream->close();
            }
            if ($this->initialRead) {
                $initialRead = $this->initialRead;
                $this->initialRead = null;
                $initialRead->resolve($this->shouldClose ? null : $this->resourceStream->read());
            }
        });
    }
    /**
     * Reads data from the stream.
     *
     * @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
     *
     * @throws PendingReadError Thrown if another read operation is still pending.
     */
    public function read() : Promise
    {
        if ($this->initialRead) {
            throw new PendingReadError();
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->resourceStream) {
            return $this->resourceStream->read();
        }
        if ($this->shouldClose) {
            return new Success();
            // Resolve reads on closed streams with null.
        }
        $this->initialRead = new Deferred();
        return $this->initialRead->promise();
    }
    /**
     *
     */
    public function reference()
    {
        $this->referenced = true;
        if ($this->resourceStream) {
            $this->resourceStream->reference();
        }
    }
    /**
     *
     */
    public function unreference()
    {
        $this->referenced = false;
        if ($this->resourceStream) {
            $this->resourceStream->unreference();
        }
    }
    /**
     *
     */
    public function close()
    {
        $this->shouldClose = true;
        if ($this->initialRead) {
            $initialRead = $this->initialRead;
            $this->initialRead = null;
            $initialRead->resolve();
        }
        if ($this->resourceStream) {
            $this->resourceStream->close();
        }
    }
}<?php

namespace Amp\Process;

class ProcessException extends \Exception
{
}{
    "name": "amphp/parallel",
    "description": "Parallel processing component for Amp.",
    "keywords": [
        "asynchronous",
        "async",
        "concurrent",
        "multi-threading",
        "multi-processing"
    ],
    "homepage": "https://github.com/amphp/parallel",
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Stephen Coakley",
            "email": "me@stephencoakley.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.6.1",
        "amphp/parser": "^1",
        "amphp/process": "^1",
        "amphp/serialization": "^1",
        "amphp/sync": "^1.0.1"
    },
    "require-dev": {
        "phpunit/phpunit": "^8 || ^7",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Parallel\\": "lib"
        },
        "files": [
            "lib/Context/functions.php",
            "lib/Sync/functions.php",
            "lib/Worker/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Parallel\\Example\\": "examples",
            "Amp\\Parallel\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\Parallel;
use Amp\Parallel\Context\Thread;
/**
 * Worker factory that includes a custom bootstrap file after initializing the worker.
 */
final class BootstrapWorkerFactory implements WorkerFactory
{
    /** @var string */
    private $bootstrapPath;
    /** @var string */
    private $className;
    /**
    * @param string $bootstrapFilePath Path to custom bootstrap file.
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate in each
    worker. Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    *
    * @throws \Error If the given class name does not exist or does not implement {@see Environment}.
    */
    public function __construct(string $bootstrapFilePath, string $envClassName = BasicEnvironment::class)
    {
        if (!\file_exists($bootstrapFilePath)) {
            throw new \Error(\sprintf("No file found at autoload path given '%s'", $bootstrapFilePath));
        }
        if (!\class_exists($envClassName)) {
            throw new \Error(\sprintf("Invalid environment class name '%s'", $envClassName));
        }
        if (!\is_subclass_of($envClassName, Environment::class)) {
            throw new \Error(\sprintf("The class '%s' does not implement '%s'", $envClassName, Environment::class));
        }
        $this->bootstrapPath = $bootstrapFilePath;
        $this->className = $envClassName;
    }
    /**
    * {@inheritdoc}
    *
    * The type of worker created depends on the extensions available. If multi-threading is enabled, a WorkerThread
    will be created. If threads are not available a WorkerProcess will be created.
    */
    public function create() : Worker
    {
        if (Parallel::isSupported()) {
            return new WorkerParallel($this->className, $this->bootstrapPath);
        }
        if (Thread::isSupported()) {
            return new WorkerThread($this->className, $this->bootstrapPath);
        }
        return new WorkerProcess($this->className, [], \getenv("AMP_PHP_BINARY") ?: (\defined("AMP_PHP_BINARY") ? \AMP_PHP_BINARY : null), $this->bootstrapPath);
    }
}<?php

namespace Amp\Parallel\Worker;

/**
 * Common interface for exceptions thrown when Task::run() throws an exception when being executed in a worker.
 */
interface TaskFailureThrowable extends \Throwable
{
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string;
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string;
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode();
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array;
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string;
}<?php

namespace Amp\Parallel\Worker;

/**
 * Interface for factories used to create new workers.
 */
interface WorkerFactory
{
    /**
     * Creates a new worker instance.
     *
     * @return Worker The newly created worker.
     */
    public function create() : Worker;
}<?php

namespace Amp\Parallel\Worker;

/**
 * Task implementation dispatching a simple callable.
 */
final class CallableTask implements Task
{
    /** @var callable */
    private $callable;
    /** @var mixed[] */
    private $args;
    /**
     * @param callable $callable Callable will be serialized.
     * @param mixed $args Arguments to pass to the function. Must be serializable.
     */
    public function __construct(callable $callable, array $args)
    {
        $this->callable = $callable;
        $this->args = $args;
    }
    /**
     *
     */
    public function run(Environment $environment)
    {
        if ($this->callable instanceof \__PHP_Incomplete_Class) {
            throw new \Error('When using a class instance as a callable, the class must be autoloadable');
        }
        if (\is_array($this->callable) && ($this->callable[0] ?? null) instanceof \__PHP_Incomplete_Class) {
            throw new \Error('When using a class instance method as a callable, the class must be autoloadable');
        }
        if (!\is_callable($this->callable)) {
            $message = 'User-defined functions must be autoloadable (that is, defined in a file autoloaded by composer)';
            if (\is_string($this->callable)) {
                $message .= \sprintf("; unable to load function '%s'", $this->callable);
            }
            throw new \Error($message);
        }
        return ($this->callable)(...$this->args);
    }
}<?php

namespace Amp\Parallel\Worker;

use function Amp\Parallel\Sync\formatFlattenedBacktrace;
final class TaskFailureException extends TaskException implements TaskFailureThrowable
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
    * @param string $className Original exception class name.
    * @param string $message Original exception message.
    * @param (int | string) $code Original exception code.
    * @param array $trace Backtrace generated by
    {@see \Amp\Parallel\Sync\flattenThrowableBacktrace()}.
    * @param (TaskFailureThrowable | null) $previous Instance representing any previous exception thrown in the Task.
    */
    public function __construct(string $className, string $message, $code, array $trace, ?TaskFailureThrowable $previous = null)
    {
        $format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the worker';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getWorkerTrace();
    }
}<?php

namespace Amp\Parallel\Worker;

use function Amp\Parallel\Sync\formatFlattenedBacktrace;
final class TaskFailureError extends TaskError implements TaskFailureThrowable
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
    * @param string $className Original exception class name.
    * @param string $message Original exception message.
    * @param (int | string) $code Original exception code.
    * @param array $trace Backtrace generated by
    {@see \Amp\Parallel\Sync\flattenThrowableBacktrace()}.
    * @param (TaskFailureThrowable | null) $previous Instance representing any previous exception thrown in the Task.
    */
    public function __construct(string $className, string $message, $code, array $trace, ?TaskFailureThrowable $previous = null)
    {
        $format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the worker';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getWorkerTrace();
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\StatusError;
use Amp\Promise;
use function Amp\asyncCall;
/**
 * Provides a pool of workers that can be used to execute multiple tasks asynchronously.
 *
 * A worker pool is a collection of worker threads that can perform multiple
 * tasks simultaneously. The load on each worker is balanced such that tasks
 * are completed as soon as possible and workers are used efficiently.
 */
final class DefaultPool implements Pool
{
    /** @var bool Indicates if the pool is currently running. */
    private $running = true;
    /** @var int The maximum number of workers the pool should spawn. */
    private $maxSize;
    /** @var WorkerFactory A worker factory to be used to create new workers. */
    private $factory;
    /** @var \SplObjectStorage A collection of all workers in the pool. */
    private $workers;
    /** @var \SplQueue A collection of idle workers. */
    private $idleWorkers;
    /** @var \SplQueue A queue of workers that have been assigned to tasks. */
    private $busyQueue;
    /** @var \Closure */
    private $push;
    /** @var Promise|null */
    private $exitStatus;
    /**
    * Creates a new worker pool.
    *
    * @param int $maxSize The maximum number of workers the pool should spawn.
    Defaults to `Pool::DEFAULT_MAX_SIZE`.
    * @param (WorkerFactory | null) $factory A worker factory to be used to create
    new workers.
    *
    * @throws \Error
    */
    public function __construct(int $maxSize = self::DEFAULT_MAX_SIZE, WorkerFactory $factory = null)
    {
        if ($maxSize < 0) {
            throw new \Error("Maximum size must be a non-negative integer");
        }
        $this->maxSize = $maxSize;
        // Use the global factory if none is given.
        $this->factory = $factory ?: factory();
        $this->workers = new \SplObjectStorage();
        $this->idleWorkers = new \SplQueue();
        $this->busyQueue = new \SplQueue();
        $workers = $this->workers;
        $idleWorkers = $this->idleWorkers;
        $busyQueue = $this->busyQueue;
        $this->push = static function (Worker $worker) use($workers, $idleWorkers, $busyQueue) : void {
            if (!$workers->contains($worker) || ($workers[$worker] -= 1) > 0) {
                return;
            }
            // Worker is completely idle, remove from busy queue and add to idle queue.
            foreach ($busyQueue as $key => $busy) {
                if ($busy === $worker) {
                    unset($busyQueue[$key]);
                    break;
                }
            }
            $idleWorkers->push($worker);
        };
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->isRunning()) {
            $this->kill();
        }
    }
    /**
     * Checks if the pool is running.
     *
     * @return bool True if the pool is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->running;
    }
    /**
     * Checks if the pool has any idle workers.
     *
     * @return bool True if the pool has at least one idle worker, otherwise false.
     */
    public function isIdle() : bool
    {
        return $this->idleWorkers->count() > 0 || $this->workers->count() === 0;
    }
    /**
     * {@inheritdoc}
     */
    public function getMaxSize() : int
    {
        return $this->maxSize;
    }
    /**
     * {@inheritdoc}
     */
    public function getWorkerCount() : int
    {
        return $this->workers->count();
    }
    /**
     * {@inheritdoc}
     */
    public function getIdleWorkerCount() : int
    {
        return $this->idleWorkers->count();
    }
    /**
     * Enqueues a {@see Task} to be executed by the worker pool.
     *
     * @param Task $task The task to enqueue.
     *
     * @return Promise<mixed> The return value of Task::run().
     *
     * @throws StatusError If the pool has been shutdown.
     * @throws TaskFailureThrowable If the task throws an exception.
     */
    public function enqueue(Task $task) : Promise
    {
        $worker = $this->pull();
        $promise = $worker->enqueue($task);
        $promise->onResolve(function () use($worker) : void {
            ($this->push)($worker);
        });
        return $promise;
    }
    /**
     * Shuts down the pool and all workers in it.
     *
     * @return Promise<int[]> Array of exit status from all workers.
     *
     * @throws StatusError If the pool has not been started.
     */
    public function shutdown() : Promise
    {
        if ($this->exitStatus) {
            return $this->exitStatus;
        }
        $this->running = false;
        $shutdowns = [];
        foreach ($this->workers as $worker) {
            if ($worker->isRunning()) {
                $shutdowns[] = $worker->shutdown();
            }
        }
        return $this->exitStatus = Promise\all($shutdowns);
    }
    /**
     * Kills all workers in the pool and halts the worker pool.
     */
    public function kill() : void
    {
        $this->running = false;
        foreach ($this->workers as $worker) {
            \assert($worker instanceof Worker);
            if ($worker->isRunning()) {
                $worker->kill();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getWorker() : Worker
    {
        return new Internal\PooledWorker($this->pull(), $this->push);
    }
    /**
     * Pulls a worker from the pool.
     *
     * @return Worker
     * @throws StatusError
     */
    private function pull() : Worker
    {
        if (!$this->isRunning()) {
            throw new StatusError("The pool was shutdown");
        }
        do {
            if ($this->idleWorkers->isEmpty()) {
                if ($this->getWorkerCount() >= $this->maxSize) {
                    // All possible workers busy, so shift from head (will be pushed back onto tail below).
                    $worker = $this->busyQueue->shift();
                } else {
                    // Max worker count has not been reached, so create another worker.
                    $worker = $this->factory->create();
                    if (!$worker->isRunning()) {
                        throw new WorkerException('Worker factory did not create a viable worker');
                    }
                    $this->workers->attach($worker, 0);
                    break;
                }
            } else {
                // Shift a worker off the idle queue.
                $worker = $this->idleWorkers->shift();
            }
            \assert($worker instanceof Worker);
            if ($worker->isRunning()) {
                break;
            }
            // Worker crashed; trigger error and remove it from the pool.
            asyncCall(function () use($worker) : \Generator {
                try {
                    $code = (yield $worker->shutdown());
                    \trigger_error('Worker in pool exited unexpectedly with code ' . $code, \E_USER_WARNING);
                } catch (\Throwable $exception) {
                    \trigger_error('Worker in pool crashed with exception on shutdown: ' . $exception->getMessage(), \E_USER_WARNING);
                }
            });
            $this->workers->detach($worker);
        } while (true);
        $this->busyQueue->push($worker);
        $this->workers[$worker] += 1;
        return $worker;
    }
}<?php

namespace Amp\Parallel\Worker;

class WorkerException extends \Exception
{
}<?php

namespace Amp\Parallel\Worker;

use Amp\Loop;
use Amp\Struct;
final class BasicEnvironment implements Environment
{
    /** @var array */
    private $data = [];
    /** @var \SplPriorityQueue */
    private $queue;
    /** @var string */
    private $timer;
    /**
     *
     */
    public function __construct()
    {
        $this->queue = $queue = new \SplPriorityQueue();
        $data =& $this->data;
        $this->timer = Loop::repeat(1000, static function (string $watcherId) use($queue, &$data) : void {
            $time = \time();
            while (!$queue->isEmpty()) {
                list($key, $expiration) = $queue->top();
                if (!isset($data[$key])) {
                    // Item removed.
                    $queue->extract();
                    continue;
                }
                $struct = $data[$key];
                if ($struct->expire === 0) {
                    // Item was set again without a TTL.
                    $queue->extract();
                    continue;
                }
                if ($struct->expire !== $expiration) {
                    // Expiration changed or TTL updated.
                    $queue->extract();
                    continue;
                }
                if ($time < $struct->expire) {
                    // Item at top has not expired, break out of loop.
                    break;
                }
                unset($data[$key]);
                $queue->extract();
            }
            if ($queue->isEmpty()) {
                Loop::disable($watcherId);
            }
        });
        Loop::disable($this->timer);
        Loop::unreference($this->timer);
    }
    /**
     * @param string $key
     *
     * @return bool
     */
    public function exists(string $key) : bool
    {
        return isset($this->data[$key]);
    }
    /**
     * @param string $key
     *
     * @return (mixed | null) Returns null if the key does not exist.
     */
    public function get(string $key)
    {
        if (!isset($this->data[$key])) {
            return null;
        }
        $struct = $this->data[$key];
        if ($struct->ttl !== null) {
            $expire = \time() + $struct->ttl;
            if ($struct->expire < $expire) {
                $struct->expire = $expire;
                $this->queue->insert([$key, $struct->expire], -$struct->expire);
            }
        }
        return $struct->data;
    }
    /**
     * @param string $key
     * @param mixed $value Using null for the value deletes the key.
     * @param int $ttl Number of seconds until data is automatically deleted. Use null for unlimited TTL.
     *
     * @throws \Error If the time-to-live is not a positive integer.
     */
    public function set(string $key, $value, int $ttl = null) : void
    {
        if ($value === null) {
            $this->delete($key);
            return;
        }
        if ($ttl !== null && $ttl <= 0) {
            throw new \Error("The time-to-live must be a positive integer or null");
        }
        $struct = new class
        {
            use Struct;
            public $data;
            public $expire = 0;
            public $ttl;
        };
        $struct->data = $value;
        if ($ttl !== null) {
            $struct->ttl = $ttl;
            $struct->expire = \time() + $ttl;
            $this->queue->insert([$key, $struct->expire], -$struct->expire);
            Loop::enable($this->timer);
        }
        $this->data[$key] = $struct;
    }
    /**
     * @param string $key
     */
    public function delete(string $key) : void
    {
        unset($this->data[$key]);
    }
    /**
     * Alias of exists().
     *
     * @param $key
     *
     * @return bool
     */
    public function offsetExists($key) : bool
    {
        return $this->exists($key);
    }
    /**
     * Alias of get().
     *
     * @param string $key
     *
     * @return mixed
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($key)
    {
        return $this->get($key);
    }
    /**
     * Alias of set() with $ttl = null.
     *
     * @param string $key
     * @param mixed $value
     */
    public function offsetSet($key, $value) : void
    {
        $this->set($key, $value);
    }
    /**
     * Alias of delete().
     *
     * @param string $key
     */
    public function offsetUnset($key) : void
    {
        $this->delete($key);
    }
    /**
     * Removes all values.
     */
    public function clear() : void
    {
        $this->data = [];
        Loop::disable($this->timer);
        $this->queue = new \SplPriorityQueue();
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Parallel\Worker\Task;
/** @internal */
final class Job
{
    /** @var string */
    private $id;
    /** @var Task */
    private $task;
    /**
     *
     */
    public function __construct(Task $task)
    {
        static $id = 'a';
        $this->task = $task;
        $this->id = $id++;
    }
    /**
     *
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     *
     */
    public function getTask() : Task
    {
        // Classes that cannot be autoloaded will be unserialized as an instance of __PHP_Incomplete_Class.
        if ($this->task instanceof \__PHP_Incomplete_Class) {
            throw new \Error(\sprintf("Classes implementing %s must be autoloadable by the Composer autoloader", Task::class));
        }
        return $this->task;
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Failure;
use Amp\Parallel\Sync;
use Amp\Parallel\Worker\TaskFailureError;
use Amp\Parallel\Worker\TaskFailureException;
use Amp\Parallel\Worker\TaskFailureThrowable;
use Amp\Promise;
/** @internal */
final class TaskFailure extends TaskResult
{
    const PARENT_EXCEPTION = 0;
    const PARENT_ERROR = 1;
    /** @var string */
    private $type;
    /** @var int */
    private $parent;
    /** @var string */
    private $message;
    /** @var int|string */
    private $code;
    /** @var string[] */
    private $trace;
    /** @var self|null */
    private $previous;
    /**
     *
     */
    public function __construct(string $id, \Throwable $exception)
    {
        parent::__construct($id);
        $this->type = \get_class($exception);
        $this->parent = $exception instanceof \Error ? self::PARENT_ERROR : self::PARENT_EXCEPTION;
        $this->message = $exception->getMessage();
        $this->code = $exception->getCode();
        $this->trace = Sync\flattenThrowableBacktrace($exception);
        if ($previous = $exception->getPrevious()) {
            $this->previous = new self($id, $previous);
        }
    }
    /**
     *
     */
    public function promise() : Promise
    {
        return new Failure($this->createException());
    }
    /**
     *
     */
    private function createException() : TaskFailureThrowable
    {
        $previous = $this->previous ? $this->previous->createException() : null;
        if ($this->parent === self::PARENT_ERROR) {
            return new TaskFailureError($this->type, $this->message, $this->code, $this->trace, $previous);
        }
        return new TaskFailureException($this->type, $this->message, $this->code, $this->trace, $previous);
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Parallel\Worker\Task;
use Amp\Parallel\Worker\Worker;
use Amp\Promise;
/** @internal */
final class PooledWorker implements Worker
{
    /** @var callable */
    private $push;
    /** @var Worker */
    private $worker;
    /**
     * @param Worker $worker
     * @param callable $push Callable to push the worker back into the queue.
     */
    public function __construct(Worker $worker, callable $push)
    {
        $this->worker = $worker;
        $this->push = $push;
    }
    /**
     * Automatically pushes the worker back into the queue.
     */
    public function __destruct()
    {
        ($this->push)($this->worker);
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        return $this->worker->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function isIdle() : bool
    {
        return $this->worker->isIdle();
    }
    /**
     * {@inheritdoc}
     */
    public function enqueue(Task $task) : Promise
    {
        return $this->worker->enqueue($task);
    }
    /**
     * {@inheritdoc}
     */
    public function shutdown() : Promise
    {
        return $this->worker->shutdown();
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        $this->worker->kill();
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\ByteStream;
use Amp\Parallel\Context\Context;
use Amp\Parallel\Context\Process;
use Amp\Promise;
use function Amp\call;
class WorkerProcess implements Context
{
    /** @var Process */
    private $process;
    /**
     *
     */
    public function __construct($script, array $env = [], string $binary = null)
    {
        $this->process = new Process($script, null, $env, $binary);
    }
    /**
     *
     */
    public function receive() : Promise
    {
        return $this->process->receive();
    }
    /**
     *
     */
    public function send($data) : Promise
    {
        return $this->process->send($data);
    }
    /**
     *
     */
    public function isRunning() : bool
    {
        return $this->process->isRunning();
    }
    /**
     *
     */
    public function start() : Promise
    {
        return call(function () {
            $result = (yield $this->process->start());
            $stdout = $this->process->getStdout();
            $stdout->unreference();
            $stderr = $this->process->getStderr();
            $stderr->unreference();
            ByteStream\pipe($stdout, ByteStream\getStdout());
            ByteStream\pipe($stderr, ByteStream\getStderr());
            return $result;
        });
    }
    /**
     *
     */
    public function kill() : void
    {
        if ($this->process->isRunning()) {
            $this->process->kill();
        }
    }
    /**
     *
     */
    public function join() : Promise
    {
        return $this->process->join();
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Parallel\Sync;
use Amp\Parallel\Worker;
use Amp\Promise;
return function (Sync\Channel $channel) use($argc, $argv) : Promise {
    if (!\defined("AMP_WORKER")) {
        \define("AMP_WORKER", \AMP_CONTEXT);
    }
    if (isset($argv[2])) {
        if (!\is_file($argv[2])) {
            throw new \Error(\sprintf("No file found at bootstrap file path given '%s'", $argv[2]));
        }
        // Include file within closure to protect scope.
        (function () use($argc, $argv) : void {
            require $argv[2];
        })();
    }
    if (!isset($argv[1])) {
        throw new \Error("No environment class name provided");
    }
    $className = $argv[1];
    if (!\class_exists($className)) {
        throw new \Error(\sprintf("Invalid environment class name '%s'", $className));
    }
    if (!\is_subclass_of($className, Worker\Environment::class)) {
        throw new \Error(\sprintf("The class '%s' does not implement '%s'", $className, Worker\Environment::class));
    }
    $environment = new $className();
    $runner = new Worker\TaskRunner($channel, $environment);
    return $runner->run();
};<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Promise;
/** @internal */
abstract class TaskResult
{
    /** @var string Task identifier. */
    private $id;
    /**
     * @param string $id Task identifier.
     */
    public function __construct(string $id)
    {
        $this->id = $id;
    }
    /**
     * @return string Task identifier.
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     * @return Promise<mixed> Resolved with the task result or failure reason.
     */
    public abstract function promise() : Promise;
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Failure;
use Amp\Parallel\Worker\Task;
use Amp\Promise;
use Amp\Success;
/** @internal */
final class TaskSuccess extends TaskResult
{
    /** @var mixed Result of task. */
    private $result;
    /**
     *
     */
    public function __construct(string $id, $result)
    {
        parent::__construct($id);
        $this->result = $result;
    }
    /**
     *
     */
    public function promise() : Promise
    {
        if ($this->result instanceof \__PHP_Incomplete_Class) {
            return new Failure(new \Error(\sprintf("Class instances returned from %s::run() must be autoloadable by the Composer autoloader", Task::class)));
        }
        return new Success($this->result);
    }
}<?php

namespace Amp\Parallel\Worker;

/**
 * An interface for worker pools.
 */
interface Pool extends Worker
{
    /** @var int The default maximum pool size. */
    const DEFAULT_MAX_SIZE = 32;
    /**
    * Gets a worker from the pool. The worker is marked as busy and will only be reused if the pool runs out of
    idle workers. The worker will be automatically marked as idle once no references to the returned worker remain.
    *
    * @return \Amp\Parallel\Worker\Worker
    *
    * @throws \Amp\Parallel\Context\StatusError If the queue is not running.
    */
    public function getWorker() : Worker;
    /**
     * Gets the number of workers currently running in the pool.
     *
     * @return int The number of workers.
     */
    public function getWorkerCount() : int;
    /**
     * Gets the number of workers that are currently idle.
     *
     * @return int The number of idle workers.
     */
    public function getIdleWorkerCount() : int;
    /**
     * Gets the maximum number of workers the pool may spawn to handle concurrent tasks.
     *
     * @return int The maximum number of workers.
     */
    public function getMaxSize() : int;
}<?php

namespace Amp\Parallel\Worker;

/**
 * @deprecated TaskFailureException will be thrown from failed Tasks instead of this class.
 */
class TaskException extends \Exception
{
    /** @var string Class name of exception thrown from task. */
    private $name;
    /** @var string Stack trace of the exception thrown from task. */
    private $trace;
    /**
     * @param string $name The exception class name.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalClassName() instead.
     *
     * Returns the class name of the exception thrown from the task.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the exception was thrown in the task.
     *
     * @return string
     */
    public function getWorkerTrace() : string
    {
        return $this->trace;
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\Thread;
use Amp\Parallel\Sync\Channel;
use Amp\Promise;
/**
 * A worker thread that executes task objects.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class WorkerThread extends TaskWorker
{
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param (string | null) $bootstrapPath Path to custom autoloader.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, string $bootstrapPath = null)
    {
        parent::__construct(new Thread(static function (Channel $channel, string $className, string $bootstrapPath = null) : Promise {
            if ($bootstrapPath !== null) {
                if (!\is_file($bootstrapPath)) {
                    throw new \Error(\sprintf("No file found at bootstrap file path given '%s'", $bootstrapPath));
                }
                // Include file within unbound closure to protect scope.
                (static function () use($bootstrapPath) : void {
                    require $bootstrapPath;
                })->bindTo(null, null)();
            }
            if (!\class_exists($className)) {
                throw new \Error(\sprintf("Invalid environment class name '%s'", $className));
            }
            if (!\is_subclass_of($className, Environment::class)) {
                throw new \Error(\sprintf("The class '%s' does not implement '%s'", $className, Environment::class));
            }
            $environment = new $className();
            if (!\defined("AMP_WORKER")) {
                \define("AMP_WORKER", \AMP_CONTEXT);
            }
            $runner = new TaskRunner($channel, $environment);
            return $runner->run();
        }, $envClassName, $bootstrapPath));
    }
}<?php

namespace Amp\Parallel\Worker;

interface Environment extends \ArrayAccess
{
    /**
     * @param string $key
     *
     * @return bool
     */
    public function exists(string $key) : bool;
    /**
     * @param string $key
     *
     * @return (mixed | null) Returns null if the key does not exist.
     */
    public function get(string $key);
    /**
     * @param string $key
     * @param mixed $value Using null for the value deletes the key.
     * @param int $ttl Number of seconds until data is automatically deleted. Use null for unlimited TTL.
     */
    public function set(string $key, $value, int $ttl = null);
    /**
     * @param string $key
     */
    public function delete(string $key);
    /**
     * Removes all values.
     */
    public function clear();
}<?php

namespace Amp\Parallel\Worker;

use Amp\Coroutine;
use Amp\Parallel\Sync\Channel;
use Amp\Parallel\Sync\SerializationException;
use Amp\Promise;
use function Amp\call;
final class TaskRunner
{
    /** @var Channel */
    private $channel;
    /** @var Environment */
    private $environment;
    /**
     *
     */
    public function __construct(Channel $channel, Environment $environment)
    {
        $this->channel = $channel;
        $this->environment = $environment;
    }
    /**
     * Runs the task runner, receiving tasks from the parent and sending the result of those tasks.
     *
     * @return \Amp\Promise
     */
    public function run() : Promise
    {
        return new Coroutine($this->execute());
    }
    /**
     * @coroutine
     *
     * @return \Generator
     */
    private function execute() : \Generator
    {
        $job = (yield $this->channel->receive());
        while ($job instanceof Internal\Job) {
            try {
                $result = (yield call([$job->getTask(), "run"], $this->environment));
                $result = new Internal\TaskSuccess($job->getId(), $result);
            } catch (\Throwable $exception) {
                $result = new Internal\TaskFailure($job->getId(), $exception);
            }
            $job = null;
            // Free memory from last job.
            try {
                (yield $this->channel->send($result));
            } catch (SerializationException $exception) {
                // Could not serialize task result.
                (yield $this->channel->send(new Internal\TaskFailure($result->getId(), $exception)));
            }
            $result = null;
            // Free memory from last result.
            $job = (yield $this->channel->receive());
        }
        return $job;
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Failure;
use Amp\Parallel\Context\Context;
use Amp\Parallel\Context\StatusError;
use Amp\Parallel\Sync\ChannelException;
use Amp\Promise;
use Amp\Success;
use Amp\TimeoutException;
use function Amp\call;
/**
 * Base class for most common types of task workers.
 */
abstract class TaskWorker implements Worker
{
    const SHUTDOWN_TIMEOUT = 1000;
    const ERROR_TIMEOUT = 250;
    /** @var Context */
    private $context;
    /** @var bool */
    private $started = false;
    /** @var Promise|null */
    private $pending;
    /** @var Promise|null */
    private $exitStatus;
    /**
     * @param Context $context A context running an instance of TaskRunner.
     */
    public function __construct(Context $context)
    {
        if ($context->isRunning()) {
            throw new \Error("The context was already running");
        }
        $this->context = $context;
        $context =& $this->context;
        $pending =& $this->pending;
        \register_shutdown_function(static function () use(&$context, &$pending) : void {
            if ($context === null || !$context->isRunning()) {
                return;
            }
            try {
                Promise\wait(Promise\timeout(call(function () use($context, $pending) : \Generator {
                    if ($pending) {
                        (yield $pending);
                    }
                    (yield $context->send(0));
                    return (yield $context->join());
                }), self::SHUTDOWN_TIMEOUT));
            } catch (\Throwable $exception) {
                if ($context !== null) {
                    $context->kill();
                }
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        // Report as running unless shutdown or crashed.
        return !$this->started || $this->exitStatus === null && $this->context !== null && $this->context->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function isIdle() : bool
    {
        return $this->pending === null;
    }
    /**
     * {@inheritdoc}
     */
    public function enqueue(Task $task) : Promise
    {
        if ($this->exitStatus) {
            throw new StatusError("The worker has been shut down");
        }
        $promise = $this->pending = call(function () use($task) : \Generator {
            if ($this->pending) {
                try {
                    (yield $this->pending);
                } catch (\Throwable $exception) {
                    // Ignore error from prior job.
                }
            }
            if ($this->exitStatus !== null || $this->context === null) {
                throw new WorkerException("The worker was shutdown");
            }
            if (!$this->context->isRunning()) {
                if ($this->started) {
                    throw new WorkerException("The worker crashed");
                }
                $this->started = true;
                (yield $this->context->start());
            }
            $job = new Internal\Job($task);
            try {
                (yield $this->context->send($job));
                $result = (yield $this->context->receive());
            } catch (ChannelException $exception) {
                try {
                    (yield Promise\timeout($this->context->join(), self::ERROR_TIMEOUT));
                } catch (TimeoutException $timeout) {
                    $this->kill();
                    throw new WorkerException("The worker failed unexpectedly", 0, $exception);
                }
                throw new WorkerException("The worker exited unexpectedly", 0, $exception);
            }
            if (!$result instanceof Internal\TaskResult) {
                $this->kill();
                throw new WorkerException("Context did not return a task result");
            }
            if ($result->getId() !== $job->getId()) {
                $this->kill();
                throw new WorkerException("Task results returned out of order");
            }
            return $result->promise();
        });
        $promise->onResolve(function () use($promise) : void {
            if ($this->pending === $promise) {
                $this->pending = null;
            }
        });
        return $promise;
    }
    /**
     * {@inheritdoc}
     */
    public function shutdown() : Promise
    {
        if ($this->exitStatus !== null) {
            return $this->exitStatus;
        }
        if ($this->context === null || !$this->context->isRunning()) {
            return $this->exitStatus = new Success(-1);
            // Context crashed?
        }
        return $this->exitStatus = call(function () : \Generator {
            if ($this->pending) {
                // If a task is currently running, wait for it to finish.
                (yield Promise\any([$this->pending]));
            }
            (yield $this->context->send(0));
            try {
                return (yield Promise\timeout($this->context->join(), self::SHUTDOWN_TIMEOUT));
            } catch (\Throwable $exception) {
                $this->context->kill();
                throw new WorkerException("Failed to gracefully shutdown worker", 0, $exception);
            } finally {
                // Null properties to free memory because the shutdown function has references to these.
                $this->context = null;
                $this->pending = null;
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        if ($this->exitStatus !== null || $this->context === null) {
            return;
        }
        if ($this->context->isRunning()) {
            $this->context->kill();
            $this->exitStatus = new Failure(new WorkerException("The worker was killed"));
            return;
        }
        $this->exitStatus = new Success(0);
        // Null properties to free memory because the shutdown function has references to these.
        $this->context = null;
        $this->pending = null;
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Loop;
use Amp\Promise;
const LOOP_POOL_IDENTIFIER = Pool::class;
const LOOP_FACTORY_IDENTIFIER = WorkerFactory::class;
/**
 * Gets or sets the global worker pool.
 *
 * @param (Pool | null) $pool A worker pool instance.
 *
 * @return Pool The global worker pool instance.
 */
function pool(Pool $pool = null) : Pool
{
    if ($pool === null) {
        $pool = Loop::getState(LOOP_POOL_IDENTIFIER);
        if ($pool) {
            return $pool;
        }
        $pool = new DefaultPool();
    }
    Loop::setState(LOOP_POOL_IDENTIFIER, $pool);
    return $pool;
}
/**
 * Enqueues a task to be executed by the global worker pool.
 *
 * @param Task $task The task to enqueue.
 *
 * @return Promise<mixed>
 */
function enqueue(Task $task) : Promise
{
    return pool()->enqueue($task);
}
/**
 * Enqueues a callable to be executed by the global worker pool.
 *
 * @param callable $callable Callable needs to be serializable.
 * @param mixed ...$args Arguments have to be serializable.
 *
 * @return Promise<mixed>
 */
function enqueueCallable(callable $callable, ...$args)
{
    return enqueue(new CallableTask($callable, $args));
}
/**
 * Gets a worker from the global worker pool.
 *
 * @return \Amp\Parallel\Worker\Worker
 */
function worker() : Worker
{
    return pool()->getWorker();
}
/**
 * Creates a worker using the global worker factory.
 *
 * @return \Amp\Parallel\Worker\Worker
 */
function create() : Worker
{
    return factory()->create();
}
/**
 * Gets or sets the global worker factory.
 *
 * @param (WorkerFactory | null) $factory
 *
 * @return WorkerFactory
 */
function factory(WorkerFactory $factory = null) : WorkerFactory
{
    if ($factory === null) {
        $factory = Loop::getState(LOOP_FACTORY_IDENTIFIER);
        if ($factory) {
            return $factory;
        }
        $factory = new DefaultWorkerFactory();
    }
    Loop::setState(LOOP_FACTORY_IDENTIFIER, $factory);
    return $factory;
}<?php

namespace Amp\Parallel\Worker;

use Amp\Promise;
/**
 * An interface for a parallel worker thread that runs a queue of tasks.
 */
interface Worker
{
    /**
     * Checks if the worker is running.
     *
     * @return bool True if the worker is running, otherwise false.
     */
    public function isRunning() : bool;
    /**
     * Checks if the worker is currently idle.
     *
     * @return bool
     */
    public function isIdle() : bool;
    /**
     * Enqueues a {@see Task} to be executed by the worker.
     *
     * @param Task $task The task to enqueue.
     *
     * @return Promise<mixed> Resolves with the return value of {@see Task::run()}.
     *
     * @throws TaskFailureThrowable Promise fails if {@see Task::run()} throws an exception.
     */
    public function enqueue(Task $task) : Promise;
    /**
     * @return Promise<int> Resolves with the worker exit code.
     */
    public function shutdown() : Promise;
    /**
     * Immediately kills the context.
     */
    public function kill();
}<?php

namespace Amp\Parallel\Worker;

/**
 * A worker process that executes task objects.
 */
final class WorkerProcess extends TaskWorker
{
    const SCRIPT_PATH = __DIR__ . "/Internal/worker-process.php";
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param mixed[] $env Array of environment variables to pass to the worker. Empty array inherits from the current
    PHP process. See the $env parameter of \Amp\Process\Process::__construct().
    * @param (string | null) $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    * @param (string | null) $bootstrapPath Path to custom bootstrap file.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, array $env = [], string $binary = null, string $bootstrapPath = null)
    {
        $script = [self::SCRIPT_PATH, $envClassName];
        if ($bootstrapPath !== null) {
            $script[] = $bootstrapPath;
        }
        parent::__construct(new Internal\WorkerProcess($script, $env, $binary));
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\Parallel;
/**
 * A worker parallel extension thread that executes task objects.
 */
final class WorkerParallel extends TaskWorker
{
    const SCRIPT_PATH = __DIR__ . "/Internal/worker-process.php";
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param string|null Path to custom bootstrap file.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, string $bootstrapPath = null)
    {
        $script = [self::SCRIPT_PATH, $envClassName];
        if ($bootstrapPath !== null) {
            $script[] = $bootstrapPath;
        }
        parent::__construct(new Parallel($script));
    }
}<?php

namespace Amp\Parallel\Worker;

/**
 * A runnable unit of execution.
 */
interface Task
{
    /**
     * Runs the task inside the caller's context.
     *
     * Does not have to be a coroutine, can also be a regular function returning a value.
     *
     * @param \Amp\Parallel\Worker\Environment
     *
     * @return (mixed | \Amp\Promise | \Generator)
     */
    public function run(Environment $environment);
}<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\Parallel;
use Amp\Parallel\Context\Thread;
/**
 * The built-in worker factory type.
 */
final class DefaultWorkerFactory implements WorkerFactory
{
    /** @var string */
    private $className;
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate in each
    worker. Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    *
    * @throws \Error If the given class name does not exist or does not implement {@see Environment}.
    */
    public function __construct(string $envClassName = BasicEnvironment::class)
    {
        if (!\class_exists($envClassName)) {
            throw new \Error(\sprintf("Invalid environment class name '%s'", $envClassName));
        }
        if (!\is_subclass_of($envClassName, Environment::class)) {
            throw new \Error(\sprintf("The class '%s' does not implement '%s'", $envClassName, Environment::class));
        }
        $this->className = $envClassName;
    }
    /**
    * {@inheritdoc}
    *
    * The type of worker created depends on the extensions available. If multi-threading is enabled, a WorkerThread
    will be created. If threads are not available a WorkerProcess will be created.
    */
    public function create() : Worker
    {
        if (Parallel::isSupported()) {
            return new WorkerParallel($this->className);
        }
        if (Thread::isSupported()) {
            return new WorkerThread($this->className);
        }
        return new WorkerProcess($this->className, [], \getenv("AMP_PHP_BINARY") ?: (\defined("AMP_PHP_BINARY") ? \AMP_PHP_BINARY : null));
    }
}<?php

namespace Amp\Parallel\Worker;

/**
 * @deprecated TaskFailureError will be thrown from failed Tasks instead of this class.
 */
class TaskError extends \Error
{
    /** @var string Class name of error thrown from task. */
    private $name;
    /** @var string Stack trace of the error thrown from task. */
    private $trace;
    /**
     * @param string $name The exception class name.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalClassName() instead.
     *
     * Returns the class name of the error thrown from the task.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the error was thrown in the task.
     *
     * @return string
     */
    public function getWorkerTrace() : string
    {
        return $this->trace;
    }
}<?php

namespace Amp\Parallel\Sync;

final class ContextPanicError extends PanicError
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
     * @param string $className Original exception class name.
     * @param string $message Original exception message.
     * @param (int | string) $code Original exception code.
     * @param array $trace Backtrace generated by {@see formatFlattenedBacktrace()}.
     * @param (self | null) $previous Instance representing any previous exception thrown in the child process or thread.
     */
    public function __construct(string $className, string $message, $code, array $trace, ?self $previous = null)
    {
        $format = 'Uncaught %s in child process or thread with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the child process or thread';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getPanicTrace();
    }
}<?php

namespace Amp\Parallel\Sync;

class SharedMemoryException extends ParcelException
{
}<?php

namespace Amp\Parallel\Sync;

final class ExitFailure implements ExitResult
{
    /** @var string */
    private $type;
    /** @var string */
    private $message;
    /** @var int|string */
    private $code;
    /** @var string[] */
    private $trace;
    /** @var self|null */
    private $previous;
    /**
     *
     */
    public function __construct(\Throwable $exception)
    {
        $this->type = \get_class($exception);
        $this->message = $exception->getMessage();
        $this->code = $exception->getCode();
        $this->trace = flattenThrowableBacktrace($exception);
        if ($previous = $exception->getPrevious()) {
            $this->previous = new self($previous);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getResult()
    {
        throw $this->createException();
    }
    /**
     *
     */
    private function createException() : ContextPanicError
    {
        $previous = $this->previous ? $this->previous->createException() : null;
        return new ContextPanicError($this->type, $this->message, $this->code, $this->trace, $previous);
    }
}<?php

namespace Amp\Parallel\Sync;

final class ExitSuccess implements ExitResult
{
    /** @var mixed */
    private $result;
    /**
     *
     */
    public function __construct($result)
    {
        $this->result = $result;
    }
    /**
     * {@inheritdoc}
     */
    public function getResult()
    {
        return $this->result;
    }
}<?php

namespace Amp\Parallel\Sync;

use Amp\Promise;
use Amp\Serialization\NativeSerializer;
use Amp\Serialization\Serializer;
use Amp\Sync\Lock;
use Amp\Sync\PosixSemaphore;
use Amp\Sync\SyncException;
use function Amp\call;
/**
 * A container object for sharing a value across contexts.
 *
 * A shared object is a container that stores an object inside shared memory.
 * The object can be accessed and mutated by any thread or process. The shared
 * object handle itself is serializable and can be sent to any thread or process
 * to give access to the value that is shared in the container.
 *
 * Because each shared object uses its own shared memory segment, it is much
 * more efficient to store a larger object containing many values inside a
 * single shared container than to use many small shared containers.
 *
 * Note that accessing a shared object is not atomic. Access to a shared object
 * should be protected with a mutex to preserve data integrity.
 *
 * When used with forking, the object must be created prior to forking for both
 * processes to access the synchronized object.
 *
 * @see http://php.net/manual/en/book.shmop.php The shared memory extension.
 * @see http://man7.org/linux/man-pages/man2/shmctl.2.html How shared memory works on Linux.
 * @see https://msdn.microsoft.com/en-us/library/ms810613.aspx How shared memory works on Windows.
 */
final class SharedMemoryParcel implements Parcel
{
    /** @var int The byte offset to the start of the object data in memory. */
    const MEM_DATA_OFFSET = 7;
    // A list of valid states the object can be in.
    const STATE_UNALLOCATED = 0;
    const STATE_ALLOCATED = 1;
    const STATE_MOVED = 2;
    const STATE_FREED = 3;
    /** @var string */
    private $id;
    /** @var int The shared memory segment key. */
    private $key;
    /** @var PosixSemaphore A semaphore for synchronizing on the parcel. */
    private $semaphore;
    /** @var resource|null An open handle to the shared memory segment. */
    private $handle;
    /** @var int */
    private $initializer = 0;
    /** @var Serializer */
    private $serializer;
    /**
    * @param string $id
    * @param mixed $value
    * @param int $size The initial size in bytes of the shared memory segment. It will automatically be expanded as
    necessary.
    * @param int $permissions Permissions to access the semaphore. Use file permission format specified as 0xxx.
    * @param (Serializer | null) $serializer
    *
    * @return self
    *
    * @throws SharedMemoryException
    * @throws SyncException
    * @throws \Error If the size or permissions are invalid.
    */
    public static function create(string $id, $value, int $size = 8192, int $permissions = 0600, ?Serializer $serializer = null) : self
    {
        $parcel = new self($id, $serializer);
        $parcel->init($value, $size, $permissions);
        return $parcel;
    }
    /**
     * @param string $id
     * @param (Serializer | null) $serializer
     *
     * @return self
     *
     * @throws SharedMemoryException
     */
    public static function use(string $id, ?Serializer $serializer = null) : self
    {
        $parcel = new self($id, $serializer);
        $parcel->open();
        return $parcel;
    }
    /**
     * @param string $id
     * @param (Serializer | null) $serializer
     */
    private function __construct(string $id, ?Serializer $serializer = null)
    {
        if (!\extension_loaded("shmop")) {
            throw new \Error(__CLASS__ . " requires the shmop extension");
        }
        $this->id = $id;
        $this->key = self::makeKey($this->id);
        $this->serializer = $serializer ?? new NativeSerializer();
    }
    /**
     * @param mixed $value
     * @param int $size
     * @param int $permissions
     *
     * @throws SharedMemoryException
     * @throws SyncException
     * @throws \Error If the size or permissions are invalid.
     */
    private function init($value, int $size = 8192, int $permissions = 0600) : void
    {
        if ($size <= 0) {
            throw new \Error('The memory size must be greater than 0');
        }
        if ($permissions <= 0 || $permissions > 0777) {
            throw new \Error('Invalid permissions');
        }
        $this->semaphore = PosixSemaphore::create($this->id, 1);
        $this->initializer = \getmypid();
        $this->memOpen($this->key, 'n', $permissions, $size + self::MEM_DATA_OFFSET);
        $this->setHeader(self::STATE_ALLOCATED, 0, $permissions);
        $this->wrap($value);
    }
    /**
     *
     */
    private function open() : void
    {
        $this->semaphore = PosixSemaphore::use($this->id);
        $this->memOpen($this->key, 'w', 0, 0);
    }
    /**
    * Checks if the object has been freed.
    *
    * Note that this does not check if the object has been destroyed; it only
    checks if this handle has freed its reference to the object.
    *
    * @return bool True if the object is freed, otherwise false.
    */
    private function isFreed() : bool
    {
        // If we are no longer connected to the memory segment, check if it has
        // been invalidated.
        if ($this->handle !== null) {
            $this->handleMovedMemory();
            $header = $this->getHeader();
            return $header['state'] === static::STATE_FREED;
        }
        return true;
    }
    /**
     * {@inheritdoc}
     */
    public function unwrap() : Promise
    {
        return call(function () {
            $lock = (yield $this->semaphore->acquire());
            \assert($lock instanceof Lock);
            try {
                return $this->getValue();
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * @return mixed
     *
     * @throws SharedMemoryException
     * @throws SerializationException
     */
    private function getValue()
    {
        if ($this->isFreed()) {
            throw new SharedMemoryException('The object has already been freed');
        }
        $header = $this->getHeader();
        // Make sure the header is in a valid state and format.
        if ($header['state'] !== self::STATE_ALLOCATED || $header['size'] <= 0) {
            throw new SharedMemoryException('Shared object memory is corrupt');
        }
        // Read the actual value data from memory and unserialize it.
        $data = $this->memGet(self::MEM_DATA_OFFSET, $header['size']);
        return $this->serializer->unserialize($data);
    }
    /**
    * If the value requires more memory to store than currently allocated, a
    new shared memory segment will be allocated with a larger size to store
    the value in. The previous memory segment will be cleaned up and marked
    for deletion. Other processes and threads will be notified of the new
    memory segment on the next read attempt. Once all running processes and
    threads disconnect from the old segment, it will be freed by the OS.
    */
    private function wrap($value) : void
    {
        if ($this->isFreed()) {
            throw new SharedMemoryException('The object has already been freed');
        }
        $serialized = $this->serializer->serialize($value);
        $size = \strlen($serialized);
        $header = $this->getHeader();
        /* If we run out of space, we need to allocate a new shared memory
              segment that is larger than the current one. To coordinate with other
              processes, we will leave a message in the old segment that the segment
              has moved and along with the new key. The old segment will be discarded
              automatically after all other processes notice the change and close
              the old handle.
           */
        if (\shmop_size($this->handle) < $size + self::MEM_DATA_OFFSET) {
            $this->key = $this->key < 0xffffffff ? $this->key + 1 : \random_int(0x10, 0xfffffffe);
            $this->setHeader(self::STATE_MOVED, $this->key, 0);
            $this->memDelete();
            \shmop_close($this->handle);
            $this->memOpen($this->key, 'n', $header['permissions'], $size * 2);
        }
        // Rewrite the header and the serialized value to memory.
        $this->setHeader(self::STATE_ALLOCATED, $size, $header['permissions']);
        $this->memSet(self::MEM_DATA_OFFSET, $serialized);
    }
    /**
     * {@inheritdoc}
     */
    public function synchronized(callable $callback) : Promise
    {
        return call(function () use($callback) : \Generator {
            $lock = (yield $this->semaphore->acquire());
            \assert($lock instanceof Lock);
            try {
                $result = (yield call($callback, $this->getValue()));
                if ($result !== null) {
                    $this->wrap($result);
                }
            } finally {
                $lock->release();
            }
            return $result;
        });
    }
    /**
    * Frees the shared object from memory.
    *
    * The memory containing the shared value will be invalidated. When all
    process disconnect from the object, the shared memory block will be
    destroyed by the OS.
    */
    public function __destruct()
    {
        if ($this->initializer === 0 || $this->initializer !== \getmypid()) {
            return;
        }
        if ($this->isFreed()) {
            return;
        }
        // Invalidate the memory block by setting its state to FREED.
        $this->setHeader(static::STATE_FREED, 0, 0);
        // Request the block to be deleted, then close our local handle.
        $this->memDelete();
        \shmop_close($this->handle);
        $this->handle = null;
        $this->semaphore = null;
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * Prevent serialization.
     */
    public function __sleep()
    {
        throw new \Error('A shared memory parcel cannot be serialized!');
    }
    /**
    * Updates the current memory segment handle, handling any moves made on the
    data.
    *
    * @throws SharedMemoryException
    */
    private function handleMovedMemory() : void
    {
        // Read from the memory block and handle moved blocks until we find the
        // correct block.
        while (true) {
            $header = $this->getHeader();
            // If the state is STATE_MOVED, the memory is stale and has been moved
            // to a new location. Move handle and try to read again.
            if ($header['state'] !== self::STATE_MOVED) {
                break;
            }
            \shmop_close($this->handle);
            $this->key = $header['size'];
            $this->memOpen($this->key, 'w', 0, 0);
        }
    }
    /**
     * Reads and returns the data header at the current memory segment.
     *
     * @return array An associative array of header data.
     *
     * @throws SharedMemoryException
     */
    private function getHeader() : array
    {
        $data = $this->memGet(0, self::MEM_DATA_OFFSET);
        return \unpack('Cstate/Lsize/Spermissions', $data);
    }
    /**
     * Sets the header data for the current memory segment.
     *
     * @param int $state An object state.
     * @param int $size The size of the stored data, or other value.
     * @param int $permissions The permissions mask on the memory segment.
     *
     * @throws SharedMemoryException
     */
    private function setHeader(int $state, int $size, int $permissions) : void
    {
        $header = \pack('CLS', $state, $size, $permissions);
        $this->memSet(0, $header);
    }
    /**
     * Opens a shared memory handle.
     *
     * @param int $key The shared memory key.
     * @param string $mode The mode to open the shared memory in.
     * @param int $permissions Process permissions on the shared memory.
     * @param int $size The size to crate the shared memory in bytes.
     *
     * @throws SharedMemoryException
     */
    private function memOpen(int $key, string $mode, int $permissions, int $size) : void
    {
        $handle = @\shmop_open($key, $mode, $permissions, $size);
        if ($handle === false) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to create shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
        $this->handle = $handle;
    }
    /**
     * Reads binary data from shared memory.
     *
     * @param int $offset The offset to read from.
     * @param int $size The number of bytes to read.
     *
     * @return string The binary data at the given offset.
     *
     * @throws SharedMemoryException
     */
    private function memGet(int $offset, int $size) : string
    {
        $data = \shmop_read($this->handle, $offset, $size);
        if ($data === false) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to read from shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
        return $data;
    }
    /**
     * Writes binary data to shared memory.
     *
     * @param int $offset The offset to write to.
     * @param string $data The binary data to write.
     *
     * @throws SharedMemoryException
     */
    private function memSet(int $offset, string $data) : void
    {
        if (!\shmop_write($this->handle, $data, $offset)) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to write to shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
    }
    /**
     * Requests the shared memory segment to be deleted.
     *
     * @throws SharedMemoryException
     */
    private function memDelete() : void
    {
        if (!\shmop_delete($this->handle)) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to discard shared memory block' . ($error['message'] ?? 'unknown error'));
        }
    }
    /**
     *
     */
    private static function makeKey(string $id) : int
    {
        return \abs(\unpack("l", \md5($id, true))[1]);
    }
}<?php

namespace Amp\Parallel\Sync;

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Promise;
use Amp\Serialization\Serializer;
final class ChannelledSocket implements Channel
{
    /** @var ChannelledStream */
    private $channel;
    /** @var ResourceInputStream */
    private $read;
    /** @var ResourceOutputStream */
    private $write;
    /**
     * @param resource $read Readable stream resource.
     * @param resource $write Writable stream resource.
     * @param (Serializer | null) $serializer
     *
     * @throws \Error If a stream resource is not given for $resource.
     */
    public function __construct($read, $write, ?Serializer $serializer = null)
    {
        $this->channel = new ChannelledStream($this->read = new ResourceInputStream($read), $this->write = new ResourceOutputStream($write), $serializer);
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        return $this->channel->receive();
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        return $this->channel->send($data);
    }
    /**
     *
     */
    public function unreference() : void
    {
        $this->read->unreference();
    }
    /**
     *
     */
    public function reference() : void
    {
        $this->read->reference();
    }
    /**
     * Closes the read and write resource streams.
     */
    public function close() : void
    {
        $this->read->close();
        $this->write->close();
    }
}<?php

namespace Amp\Parallel\Sync;

class ParcelException extends \Exception
{
}<?php

namespace Amp\Parallel\Sync;

class ChannelException extends \Exception
{
}<?php

namespace Amp\Parallel\Sync;

use Amp\Promise;
/**
 * A parcel object for sharing data across execution contexts.
 *
 * A parcel is an object that stores a value in a safe way that can be shared
 * between different threads or processes. Different handles to the same parcel
 * will access the same data, and a parcel handle itself is serializable and
 * can be transported to other execution contexts.
 *
 * Wrapping and unwrapping values in the parcel are not atomic. To prevent race
 * conditions and guarantee safety, you should use the provided synchronization
 * methods to acquire a lock for exclusive access to the parcel first before
 * accessing the contained value.
 */
interface Parcel
{
    /**
    * Asynchronously invokes a callback while maintaining an exclusive lock on the parcel. The current value of the
    parcel is provided as the first argument to the callback function.
    *
    * @param callable $callback The synchronized callback to invoke. The parcel value is given as the single argument
    to the callback function. The callback may be a regular function or a coroutine.
    *
    * @return \Amp\Promise<mixed> Resolves with the return value of $callback or fails if $callback
    throws an exception.
    */
    public function synchronized(callable $callback) : Promise;
    /**
     * @return \Amp\Promise<mixed> A promise for the value inside the parcel.
     */
    public function unwrap() : Promise;
}<?php

namespace Amp\Parallel\Sync\Internal;

final class ParcelStorage extends \Threaded
{
    /** @var mixed */
    private $value;
    /**
     * @param mixed $value
     */
    public function __construct($value)
    {
        $this->value = $value;
    }
    /**
     * @return mixed
     */
    public function get()
    {
        return $this->value;
    }
    /**
     * @param mixed $value
     */
    public function set($value) : void
    {
        $this->value = $value;
    }
}<?php

namespace Amp\Parallel\Sync;

class SynchronizationError extends \Error
{
}<?php

namespace Amp\Parallel\Sync;

use Amp\Promise;
use Amp\Success;
use Amp\Sync\ThreadedMutex;
use function Amp\call;
/**
 * A thread-safe container that shares a value between multiple threads.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class ThreadedParcel implements Parcel
{
    /** @var ThreadedMutex */
    private $mutex;
    /** @var \Threaded */
    private $storage;
    /**
     * Creates a new shared object container.
     *
     * @param mixed $value The value to store in the container.
     */
    public function __construct($value)
    {
        $this->mutex = new ThreadedMutex();
        $this->storage = new Internal\ParcelStorage($value);
    }
    /**
     * {@inheritdoc}
     */
    public function unwrap() : Promise
    {
        return new Success($this->storage->get());
    }
    /**
     * @return \Amp\Promise
     */
    public function synchronized(callable $callback) : Promise
    {
        return call(function () use($callback) : \Generator {
            /** @var \Amp\Sync\Lock $lock */
            $lock = (yield $this->mutex->acquire());
            try {
                $result = (yield call($callback, $this->storage->get()));
                if ($result !== null) {
                    $this->storage->set($result);
                }
            } finally {
                $lock->release();
            }
            return $result;
        });
    }
}<?php

namespace Amp\Parallel\Sync;

use Amp\Promise;
/**
 * Interface for sending messages between execution contexts.
 */
interface Channel
{
    /**
    * @return \Amp\Promise<mixed>
    *
    * @throws \Amp\Parallel\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Parallel\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Parallel\Sync\ChannelException If receiving from the channel fails.
    * @throws \Amp\Parallel\Sync\SerializationException If unserializing the data fails.
    */
    public function receive() : Promise;
    /**
    * @param mixed $data
    *
    * @return \Amp\Promise<int> Resolves with the number of bytes sent on the channel.
    *
    * @throws \Amp\Parallel\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Parallel\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Parallel\Sync\ChannelException If sending on the channel fails.
    * @throws \Error If an ExitResult object is given.
    * @throws \Amp\Parallel\Sync\SerializationException If serializing the data fails.
    */
    public function send($data) : Promise;
}<?php

namespace Amp\Parallel\Sync;

use Amp\Serialization\SerializationException as SerializerException;
// Alias must be defined in an always-loaded file as catch blocks do not trigger the autoloader.
\class_alias(SerializerException::class, SerializationException::class);
/**
 * @param \Throwable $exception
 *
 * @return array Serializable exception backtrace, with all function arguments flattened to strings.
 */
function flattenThrowableBacktrace(\Throwable $exception) : array
{
    $trace = $exception->getTrace();
    foreach ($trace as &$call) {
        unset($call['object']);
        $call['args'] = \array_map(__NAMESPACE__ . '\\flattenArgument', $call['args'] ?? []);
    }
    return $trace;
}
/**
 * @param array $trace Backtrace produced by {@see formatFlattenedBacktrace()}.
 *
 * @return string
 */
function formatFlattenedBacktrace(array $trace) : string
{
    $output = [];
    foreach ($trace as $index => $call) {
        if (isset($call['class'])) {
            $name = $call['class'] . $call['type'] . $call['function'];
        } else {
            $name = $call['function'];
        }
        $output[] = \sprintf('#%d %s(%d): %s(%s)', $index, $call['file'] ?? '[internal function]', $call['line'] ?? 0, $name, \implode(', ', $call['args'] ?? ['...']));
    }
    return \implode("\n", $output);
}
/**
 * @param mixed $value
 *
 * @return string Serializable string representation of $value for backtraces.
 */
function flattenArgument($value) : string
{
    if ($value instanceof \Closure) {
        $closureReflection = new \ReflectionFunction($value);
        return \sprintf('Closure(%s:%s)', $closureReflection->getFileName(), $closureReflection->getStartLine());
    }
    if (\is_object($value)) {
        return \sprintf('Object(%s)', \get_class($value));
    }
    if (\is_array($value)) {
        return 'Array([' . \implode(', ', \array_map(__FUNCTION__, $value)) . '])';
    }
    if (\is_resource($value)) {
        return \sprintf('Resource(%s)', \get_resource_type($value));
    }
    if (\is_string($value)) {
        return '"' . $value . '"';
    }
    if (\is_null($value)) {
        return 'null';
    }
    if (\is_bool($value)) {
        return $value ? 'true' : 'false';
    }
    return (string) $value;
}<?php

namespace Amp\Parallel\Sync;

/**
 * @deprecated ContextPanicError will be thrown from uncaught exceptions in child processes and threads instead of
 * this class.
 */
class PanicError extends \Error
{
    /** @var string Class name of uncaught exception. */
    private $name;
    /** @var string Stack trace of the panic. */
    private $trace;
    /**
     * Creates a new panic error.
     *
     * @param string $name The uncaught exception class.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use ContextPanicError::getOriginalClassName() instead.
     *
     * Returns the class name of the uncaught exception.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use ContextPanicError::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the panic occurred.
     *
     * @return string
     */
    public function getPanicTrace() : string
    {
        return $this->trace;
    }
}<?php

namespace Amp\Parallel\Sync;

use Amp\Parser\Parser;
use Amp\Serialization\NativeSerializer;
use Amp\Serialization\Serializer;
use function Amp\Serialization\encodeUnprintableChars;
final class ChannelParser extends Parser
{
    const HEADER_LENGTH = 5;
    /** @var Serializer */
    private $serializer;
    /**
     * @param callable(mixed $data) Callback invoked when data is parsed.
     * @param (Serializer | null) $serializer
     */
    public function __construct(callable $callback, ?Serializer $serializer = null)
    {
        $this->serializer = $serializer ?? new NativeSerializer();
        parent::__construct(self::parser($callback, $this->serializer));
    }
    /**
     * @param mixed $data Data to encode to send over a channel.
     *
     * @return string Encoded data that can be parsed by this class.
     *
     * @throws SerializationException
     */
    public function encode($data) : string
    {
        $data = $this->serializer->serialize($data);
        return \pack("CL", 0, \strlen($data)) . $data;
    }
    /**
     * @param callable $push
     * @param Serializer $serializer
     *
     * @return \Generator
     *
     * @throws ChannelException
     * @throws SerializationException
     */
    private static function parser(callable $push, Serializer $serializer) : \Generator
    {
        while (true) {
            $header = (yield self::HEADER_LENGTH);
            $data = \unpack("Cprefix/Llength", $header);
            if ($data["prefix"] !== 0) {
                $data = $header . yield;
                throw new ChannelException("Invalid packet received: " . encodeUnprintableChars($data));
            }
            $data = (yield $data["length"]);
            $push($serializer->unserialize($data));
        }
    }
}<?php

namespace Amp\Parallel\Sync;

interface ExitResult
{
    /**
     * @return mixed Return value of the callable given to the execution context.
     *
     * @throws \Amp\Parallel\Sync\PanicError If the context exited with an uncaught exception.
     */
    public function getResult();
}<?php

namespace Amp\Parallel\Sync;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
use Amp\ByteStream\StreamException;
use Amp\Promise;
use Amp\Serialization\Serializer;
use function Amp\call;
/**
 * An asynchronous channel for sending data between threads and processes.
 *
 * Supports full duplex read and write.
 */
final class ChannelledStream implements Channel
{
    /** @var InputStream */
    private $read;
    /** @var OutputStream */
    private $write;
    /** @var \SplQueue */
    private $received;
    /** @var ChannelParser */
    private $parser;
    /**
     * Creates a new channel from the given stream objects. Note that $read and $write can be the same object.
     *
     * @param InputStream $read
     * @param OutputStream $write
     * @param (Serializer | null) $serializer
     */
    public function __construct(InputStream $read, OutputStream $write, ?Serializer $serializer = null)
    {
        $this->read = $read;
        $this->write = $write;
        $this->received = new \SplQueue();
        $this->parser = new ChannelParser([$this->received, 'push'], $serializer);
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->write->write($this->parser->encode($data)));
            } catch (StreamException $exception) {
                throw new ChannelException("Sending on the channel failed. Did the context die?", 0, $exception);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        return call(function () : \Generator {
            while ($this->received->isEmpty()) {
                try {
                    $chunk = (yield $this->read->read());
                } catch (StreamException $exception) {
                    throw new ChannelException("Reading from the channel failed. Did the context die?", 0, $exception);
                }
                if ($chunk === null) {
                    throw new ChannelException("The channel closed unexpectedly. Did the context die?");
                }
                $this->parser->push($chunk);
            }
            return $this->received->shift();
        });
    }
}<?php

namespace Amp\Parallel\Context;

use Amp\Promise;
interface ContextFactory
{
    /**
    * Creates a new execution context.
    *
    * @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Context
    */
    public function create($script) : Context;
    /**
    * Creates and starts a new execution context.
    *
    * @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Promise<Context>
    */
    public function run($script) : Promise;
}<?php

namespace Amp\Parallel\Context;

use Amp\Failure;
use Amp\Loop;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitResult;
use Amp\Parallel\Sync\SynchronizationError;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
/**
 * Implements an execution context using native multi-threading.
 *
 * The thread context is not itself threaded. A local instance of the context is
 * maintained both in the context that creates the thread and in the thread
 * itself.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class Thread implements Context
{
    const EXIT_CHECK_FREQUENCY = 250;
    /** @var int */
    private static $nextId = 1;
    /** @var Internal\Thread An internal thread instance. */
    private $thread;
    /** @var ChannelledSocket A channel for communicating with the thread. */
    private $channel;
    /** @var resource */
    private $socket;
    /** @var callable */
    private $function;
    /** @var mixed[] */
    private $args;
    /** @var int|null */
    private $id;
    /** @var int */
    private $oid = 0;
    /** @var string */
    private $watcher;
    /**
     * Checks if threading is enabled.
     *
     * @return bool True if threading is enabled, otherwise false.
     */
    public static function isSupported() : bool
    {
        return \extension_loaded('pthreads');
    }
    /**
    * Creates and starts a new thread.
    *
    * @param callable $function The callable to invoke in the thread. First argument is an instance of
    \Amp\Parallel\Sync\Channel.
    * @param mixed ...$args Additional arguments to pass to the given callable.
    *
    * @return Promise<Thread> The thread object that was spawned.
    */
    public static function run(callable $function, ...$args) : Promise
    {
        $thread = new self($function, ...$args);
        return call(function () use($thread) : \Generator {
            (yield $thread->start());
            return $thread;
        });
    }
    /**
    * Creates a new thread.
    *
    * @param callable $function The callable to invoke in the thread. First argument is an instance of
    \Amp\Parallel\Sync\Channel.
    * @param mixed ...$args Additional arguments to pass to the given callable.
    *
    * @throws \Error Thrown if the pthreads extension is not available.
    */
    public function __construct(callable $function, ...$args)
    {
        if (!self::isSupported()) {
            throw new \Error("The pthreads extension is required to create threads.");
        }
        $this->function = $function;
        $this->args = $args;
    }
    /**
    * Returns the thread to the condition before starting. The new thread can be started and run independently of the
    first thread.
    */
    public function __clone()
    {
        $this->thread = null;
        $this->socket = null;
        $this->channel = null;
        $this->oid = 0;
    }
    /**
     * Kills the thread if it is still running.
     *
     * @throws \Amp\Parallel\Context\ContextException
     */
    public function __destruct()
    {
        if (\getmypid() === $this->oid) {
            $this->kill();
        }
    }
    /**
     * Checks if the context is running.
     *
     * @return bool True if the context is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->channel !== null;
    }
    /**
     * Spawns the thread and begins the thread's execution.
     *
     * @return Promise<int> Resolved once the thread has started.
     *
     * @throws \Amp\Parallel\Context\StatusError If the thread has already been started.
     * @throws \Amp\Parallel\Context\ContextException If starting the thread was unsuccessful.
     */
    public function start() : Promise
    {
        if ($this->oid !== 0) {
            throw new StatusError('The thread has already been started.');
        }
        $this->oid = \getmypid();
        $sockets = @\stream_socket_pair(\stripos(\PHP_OS, "win") === 0 ? STREAM_PF_INET : STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
        if ($sockets === false) {
            $message = "Failed to create socket pair";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            return new Failure(new ContextException($message));
        }
        list($channel, $this->socket) = $sockets;
        $this->id = self::$nextId++;
        $thread = $this->thread = new Internal\Thread($this->id, $this->socket, $this->function, $this->args);
        if (!$this->thread->start(\PTHREADS_INHERIT_INI)) {
            return new Failure(new ContextException('Failed to start the thread.'));
        }
        $channel = $this->channel = new ChannelledSocket($channel, $channel);
        $this->watcher = Loop::repeat(self::EXIT_CHECK_FREQUENCY, static function ($watcher) use($thread, $channel) : void {
            if (!$thread->isRunning()) {
                // Delay closing to avoid race condition between thread exiting and data becoming available.
                Loop::delay(self::EXIT_CHECK_FREQUENCY, [$channel, "close"]);
                Loop::cancel($watcher);
            }
        });
        Loop::disable($this->watcher);
        return new Success($this->id);
    }
    /**
     * Immediately kills the context.
     *
     * @throws ContextException If killing the thread was unsuccessful.
     */
    public function kill() : void
    {
        if ($this->thread !== null) {
            try {
                if ($this->thread->isRunning() && !$this->thread->kill()) {
                    throw new ContextException('Could not kill thread.');
                }
            } finally {
                $this->close();
            }
        }
    }
    /**
     * Closes channel and socket if still open.
     */
    private function close() : void
    {
        if ($this->channel !== null) {
            $this->channel->close();
        }
        $this->channel = null;
        Loop::cancel($this->watcher);
    }
    /**
    * Gets a promise that resolves when the context ends and joins with the
    parent context.
    *
    * @return \Amp\Promise<mixed>
    *
    * @throws StatusError Thrown if the context has not been started.
    * @throws SynchronizationError Thrown if an exit status object is not received.
    * @throws ContextException If the context stops responding.
    */
    public function join() : Promise
    {
        if ($this->channel == null || $this->thread === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        return call(function () : \Generator {
            Loop::enable($this->watcher);
            try {
                $response = (yield $this->channel->receive());
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Failed to receive result from thread", 0, $exception);
            } finally {
                Loop::disable($this->watcher);
                $this->close();
            }
            if (!$response instanceof ExitResult) {
                $this->kill();
                throw new SynchronizationError('Did not receive an exit result from thread.');
            }
            return $response->getResult();
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The process has not been started.');
        }
        return call(function () : \Generator {
            Loop::enable($this->watcher);
            try {
                $data = (yield $this->channel->receive());
            } finally {
                Loop::disable($this->watcher);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Thread process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        if ($data instanceof ExitResult) {
            throw new \Error('Cannot send exit result objects.');
        }
        return call(function () use($data) : \Generator {
            Loop::enable($this->watcher);
            try {
                $result = (yield $this->channel->send($data));
            } finally {
                Loop::disable($this->watcher);
            }
            return $result;
        });
    }
    /**
     * Returns the ID of the thread. This ID will be unique to this process.
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getId() : int
    {
        if ($this->id === null) {
            throw new StatusError('The thread has not been started');
        }
        return $this->id;
    }
}<?php

namespace Amp\Parallel\Context;

class ContextException extends \Exception
{
}<?php

namespace Amp\Parallel\Context\Internal;

use Amp\Deferred;
use Amp\Loop;
use Amp\Parallel\Context\ContextException;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Promise;
use Amp\TimeoutException;
use function Amp\asyncCall;
use function Amp\call;
class ProcessHub
{
    const PROCESS_START_TIMEOUT = 5000;
    const KEY_RECEIVE_TIMEOUT = 1000;
    /** @var resource|null */
    private $server;
    /** @var string|null */
    private $uri;
    /** @var int[] */
    private $keys;
    /** @var string|null */
    private $watcher;
    /** @var Deferred[] */
    private $acceptor = [];
    /** @var string|null */
    private $toUnlink;
    /**
     *
     */
    public function __construct()
    {
        $isWindows = \strncasecmp(\PHP_OS, "WIN", 3) === 0;
        if ($isWindows) {
            $this->uri = "tcp://127.0.0.1:0";
        } else {
            $suffix = \bin2hex(\random_bytes(10));
            $path = \sys_get_temp_dir() . "/amp-parallel-ipc-" . $suffix . ".sock";
            $this->uri = "unix://" . $path;
            $this->toUnlink = $path;
        }
        $context = \stream_context_create(['socket' => ['backlog' => 128]]);
        $this->server = \stream_socket_server($this->uri, $errno, $errstr, \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN, $context);
        if (!$this->server) {
            throw new \RuntimeException(\sprintf("Could not create IPC server: (Errno: %d) %s", $errno, $errstr));
        }
        if ($isWindows) {
            $name = \stream_socket_get_name($this->server, false);
            $port = \Phabel\Target\Php80\Polyfill::substr($name, \strrpos($name, ":") + 1);
            $this->uri = "tcp://127.0.0.1:" . $port;
        }
        $keys =& $this->keys;
        $acceptor =& $this->acceptor;
        $this->watcher = Loop::onReadable($this->server, static function (string $watcher, $server) use(&$keys, &$acceptor) : void {
            // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
            while ($client = @\stream_socket_accept($server, 0)) {
                // Timeout of 0 to be non-blocking.
                asyncCall(static function () use($client, &$keys, &$acceptor) {
                    $channel = new ChannelledSocket($client, $client);
                    try {
                        $received = (yield Promise\timeout($channel->receive(), self::KEY_RECEIVE_TIMEOUT));
                    } catch (\Throwable $exception) {
                        $channel->close();
                        return;
                        // Ignore possible foreign connection attempt.
                    }
                    if (!\is_string($received) || !isset($keys[$received])) {
                        $channel->close();
                        return;
                        // Ignore possible foreign connection attempt.
                    }
                    $pid = $keys[$received];
                    $deferred = $acceptor[$pid];
                    unset($acceptor[$pid], $keys[$received]);
                    $deferred->resolve($channel);
                });
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->watcher);
        \fclose($this->server);
        if ($this->toUnlink !== null) {
            @\unlink($this->toUnlink);
        }
    }
    /**
     *
     */
    public function getUri() : string
    {
        return $this->uri;
    }
    /**
     *
     */
    public function generateKey(int $pid, int $length) : string
    {
        $key = \random_bytes($length);
        $this->keys[$key] = $pid;
        return $key;
    }
    /**
     *
     */
    public function accept(int $pid) : Promise
    {
        return call(function () use($pid) : \Generator {
            $this->acceptor[$pid] = new Deferred();
            Loop::enable($this->watcher);
            try {
                $channel = (yield Promise\timeout($this->acceptor[$pid]->promise(), self::PROCESS_START_TIMEOUT));
            } catch (TimeoutException $exception) {
                $key = \array_search($pid, $this->keys, true);
                \assert(\is_string($key), "Key for {$pid} not found");
                unset($this->acceptor[$pid], $this->keys[$key]);
                throw new ContextException("Starting the process timed out", 0, $exception);
            } finally {
                if (empty($this->acceptor)) {
                    Loop::disable($this->watcher);
                }
            }
            return $channel;
        });
    }
}<?php

namespace Amp\Parallel\Context\Internal;

use Amp\Parallel\Context\Process;
use Amp\Parallel\Sync;
use Amp\Promise;
use function Amp\call;
use function Amp\getCurrentTime;
\define("AMP_CONTEXT", "process");
\define("AMP_CONTEXT_ID", \getmypid());
// Doesn't exist in phpdbg...
if (\function_exists("cli_set_process_title")) {
    @\cli_set_process_title("amp-process");
}
(function () : void {
    $paths = [\dirname(__DIR__, 5) . "/autoload.php", \dirname(__DIR__, 3) . "/vendor/autoload.php"];
    foreach ($paths as $path) {
        if (\file_exists($path)) {
            $autoloadPath = $path;
            break;
        }
    }
    if (!isset($autoloadPath)) {
        \trigger_error("Could not locate autoload.php in any of the following files: " . \implode(", ", $paths), E_USER_ERROR);
        exit(1);
    }
    require $autoloadPath;
})();
(function () use($argc, $argv) : void {
    // Remove this scripts path from process arguments.
    --$argc;
    \array_shift($argv);
    if (!isset($argv[0])) {
        \trigger_error("No socket path provided", E_USER_ERROR);
        exit(1);
    }
    // Remove socket path from process arguments.
    --$argc;
    $uri = \array_shift($argv);
    $key = "";
    // Read random key from STDIN and send back to parent over IPC socket to authenticate.
    do {
        if (($chunk = \fread(\STDIN, Process::KEY_LENGTH)) === false || \feof(\STDIN)) {
            \trigger_error("Could not read key from parent", E_USER_ERROR);
            exit(1);
        }
        $key .= $chunk;
    } while (\strlen($key) < Process::KEY_LENGTH);
    $connectStart = getCurrentTime();
    while (!($socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT))) {
        if (getCurrentTime() < $connectStart + 5000) {
            // try for 5 seconds, after that the parent times out anyway
            \trigger_error("Could not connect to IPC socket", \E_USER_ERROR);
            exit(1);
        }
        \usleep(50 * 1000);
    }
    $channel = new Sync\ChannelledSocket($socket, $socket);
    try {
        Promise\wait($channel->send($key));
    } catch (\Throwable $exception) {
        \trigger_error("Could not send key to parent", E_USER_ERROR);
        exit(1);
    }
    try {
        if (!isset($argv[0])) {
            throw new \Error("No script path given");
        }
        if (!\is_file($argv[0])) {
            throw new \Error(\sprintf("No script found at '%s' (be sure to provide the full path to the script)", $argv[0]));
        }
        try {
            // Protect current scope by requiring script within another function.
            $callable = (function () use($argc, $argv) : callable {
                // Using $argc so it is available to the required script.
                return require $argv[0];
            })();
        } catch (\TypeError $exception) {
            throw new \Error(\sprintf("Script '%s' did not return a callable function", $argv[0]), 0, $exception);
        } catch (\ParseError $exception) {
            throw new \Error(\sprintf("Script '%s' contains a parse error: " . $exception->getMessage(), $argv[0]), 0, $exception);
        }
        $result = new Sync\ExitSuccess(Promise\wait(call($callable, $channel)));
    } catch (\Throwable $exception) {
        $result = new Sync\ExitFailure($exception);
    }
    try {
        Promise\wait(call(function () use($channel, $result) : \Generator {
            try {
                (yield $channel->send($result));
            } catch (Sync\SerializationException $exception) {
                // Serializing the result failed. Send the reason why.
                (yield $channel->send(new Sync\ExitFailure($exception)));
            }
        }));
    } catch (\Throwable $exception) {
        \trigger_error("Could not send result to parent; be sure to shutdown the child before ending the parent", E_USER_ERROR);
        exit(1);
    }
})();<?php

namespace Amp\Parallel\Context\Internal;

use Amp\Loop;
use Amp\Parallel\Sync\Channel;
use Amp\Parallel\Sync\ChannelException;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitFailure;
use Amp\Parallel\Sync\ExitSuccess;
use Amp\Parallel\Sync\SerializationException;
use function Amp\call;
/**
 * An internal thread that executes a given function concurrently.
 *
 * @internal
 */
final class Thread extends \Thread
{
    const KILL_CHECK_FREQUENCY = 250;
    private $id;
    /** @var callable The function to execute in the thread. */
    private $function;
    /** @var mixed[] Arguments to pass to the function. */
    private $args;
    /** @var resource */
    private $socket;
    /** @var bool */
    private $killed = false;
    /**
     * Creates a new thread object.
     *
     * @param int $id Thread ID.
     * @param resource $socket IPC communication socket.
     * @param callable $function The function to execute in the thread.
     * @param mixed[] $args Arguments to pass to the function.
     */
    public function __construct(int $id, $socket, callable $function, array $args = [])
    {
        $this->id = $id;
        $this->function = $function;
        $this->args = $args;
        $this->socket = $socket;
    }
    /**
     * Runs the thread code and the initialized function.
     *
     * @codeCoverageIgnore Only executed in thread.
     */
    public function run()
    {
        \define("AMP_CONTEXT", "thread");
        \define("AMP_CONTEXT_ID", $this->id);
        /* First thing we need to do is re-initialize the class autoloader. If
         * we don't do this first, any object of a class that was loaded after
         * the thread started will just be garbage data and unserializable
         * values (like resources) will be lost. This happens even with
         * thread-safe objects.
         */
        // Protect scope by using an unbound closure (protects static access as well).
        (static function () : void {
            $paths = [\dirname(__DIR__, 3) . \DIRECTORY_SEPARATOR . "vendor" . \DIRECTORY_SEPARATOR . "autoload.php", \dirname(__DIR__, 5) . \DIRECTORY_SEPARATOR . "autoload.php"];
            foreach ($paths as $path) {
                if (\file_exists($path)) {
                    $autoloadPath = $path;
                    break;
                }
            }
            if (!isset($autoloadPath)) {
                throw new \Error("Could not locate autoload.php");
            }
            require $autoloadPath;
        })->bindTo(null, null)();
        // At this point, the thread environment has been prepared so begin using the thread.
        if ($this->killed) {
            return;
            // Thread killed while requiring autoloader, simply exit.
        }
        Loop::run(function () : \Generator {
            $watcher = Loop::repeat(self::KILL_CHECK_FREQUENCY, function () : void {
                if ($this->killed) {
                    Loop::stop();
                }
            });
            Loop::unreference($watcher);
            try {
                $channel = new ChannelledSocket($this->socket, $this->socket);
                yield from $this->execute($channel);
            } catch (\Throwable $exception) {
                return;
                // Parent context exited or destroyed thread, no need to continue.
            } finally {
                Loop::cancel($watcher);
            }
        });
    }
    /**
     * Sets a local variable to true so the running event loop can check for a kill signal.
     */
    public function kill()
    {
        return $this->killed = true;
    }
    /**
     * @param \Amp\Parallel\Sync\Channel $channel
     *
     * @return \Generator
     *
     * @codeCoverageIgnore Only executed in thread.
     */
    private function execute(Channel $channel) : \Generator
    {
        try {
            $result = new ExitSuccess((yield call($this->function, $channel, ...$this->args)));
        } catch (\Throwable $exception) {
            $result = new ExitFailure($exception);
        }
        if ($this->killed) {
            return;
            // Parent is not listening for a result.
        }
        // Attempt to return the result.
        try {
            try {
                (yield $channel->send($result));
            } catch (SerializationException $exception) {
                // Serializing the result failed. Send the reason why.
                (yield $channel->send(new ExitFailure($exception)));
            }
        } catch (ChannelException $exception) {
            // The result was not sendable! The parent context must have died or killed the context.
        }
    }
}<?php

namespace Amp\Parallel\Context\Internal;

use Amp\Loop;
use Amp\Parallel\Sync\ChannelledSocket;
use parallel\Events;
use parallel\Future;
class ParallelHub extends ProcessHub
{
    const EXIT_CHECK_FREQUENCY = 250;
    /** @var ChannelledSocket[] */
    private $channels;
    /** @var string */
    private $watcher;
    /** @var Events */
    private $events;
    /**
     *
     */
    public function __construct()
    {
        parent::__construct();
        $events = $this->events = new Events();
        $this->events->setBlocking(false);
        $channels =& $this->channels;
        $this->watcher = Loop::repeat(self::EXIT_CHECK_FREQUENCY, static function () use(&$channels, $events) : void {
            while ($event = $events->poll()) {
                $id = (int) $event->source;
                \assert(isset($channels[$id]), 'Channel for context ID not found');
                $channel = $channels[$id];
                unset($channels[$id]);
                $channel->close();
            }
        });
        Loop::disable($this->watcher);
        Loop::unreference($this->watcher);
    }
    /**
     *
     */
    public function add(int $id, ChannelledSocket $channel, Future $future) : void
    {
        $this->channels[$id] = $channel;
        $this->events->addFuture((string) $id, $future);
        Loop::enable($this->watcher);
    }
    /**
     *
     */
    public function remove(int $id) : void
    {
        if (!isset($this->channels[$id])) {
            return;
        }
        unset($this->channels[$id]);
        $this->events->remove((string) $id);
        if (empty($this->channels)) {
            Loop::disable($this->watcher);
        }
    }
}<?php

namespace Amp\Parallel\Context;

class StatusError extends \Error
{
}<?php

namespace Amp\Parallel\Context;

use Amp\Promise;
class DefaultContextFactory implements ContextFactory
{
    /**
     *
     */
    public function create($script) : Context
    {
        /**
         * Creates a thread if ext-parallel is installed, otherwise creates a child process.
         *
         * @inheritdoc
         */
        if (Parallel::isSupported()) {
            return new Parallel($script);
        }
        return new Process($script);
    }
    /**
     * Creates and starts a thread if ext-parallel is installed, otherwise creates a child process.
     *
     * @inheritdoc
     */
    public function run($script) : Promise
    {
        if (Parallel::isSupported()) {
            return Parallel::run($script);
        }
        return Process::run($script);
    }
}<?php

namespace Amp\Parallel\Context;

use Amp\Loop;
use Amp\Promise;
const LOOP_FACTORY_IDENTIFIER = ContextFactory::class;
/**
* @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
*
* @return Context
*/
function create($script) : Context
{
    return factory()->create($script);
}
/**
* Creates and starts a process based on installed extensions (a thread if ext-parallel is installed, otherwise a child
process).
*
* @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
*
* @return Promise<Context>
*/
function run($script) : Promise
{
    return factory()->run($script);
}
/**
 * Gets or sets the global context factory.
 *
 * @param (ContextFactory | null) $factory
 *
 * @return ContextFactory
 */
function factory(?ContextFactory $factory = null) : ContextFactory
{
    if ($factory === null) {
        $factory = Loop::getState(LOOP_FACTORY_IDENTIFIER);
        if ($factory) {
            return $factory;
        }
        $factory = new DefaultContextFactory();
    }
    Loop::setState(LOOP_FACTORY_IDENTIFIER, $factory);
    return $factory;
}<?php

namespace Amp\Parallel\Context;

use Amp\Loop;
use Amp\Parallel\Sync\ChannelException;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitResult;
use Amp\Parallel\Sync\SynchronizationError;
use Amp\Process\Process as BaseProcess;
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
use Amp\Promise;
use Amp\TimeoutException;
use function Amp\call;
final class Process implements Context
{
    const SCRIPT_PATH = __DIR__ . "/Internal/process-runner.php";
    const KEY_LENGTH = 32;
    /** @var string|null External version of SCRIPT_PATH if inside a PHAR. */
    private static $pharScriptPath;
    /** @var string|null PHAR path with a '.phar' extension. */
    private static $pharCopy;
    /** @var string|null Cached path to located PHP binary. */
    private static $binaryPath;
    /** @var Internal\ProcessHub */
    private $hub;
    /** @var BaseProcess */
    private $process;
    /** @var ChannelledSocket */
    private $channel;
    /**
    * Creates and starts the process at the given path using the optional PHP binary path.
    *
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    * @param (string | null) $cwd Working directory.
    * @param mixed[] $env Array of environment variables.
    * @param string $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    *
    * @return Promise<Process>
    */
    public static function run($script, string $cwd = null, array $env = [], string $binary = null) : Promise
    {
        $process = new self($script, $cwd, $env, $binary);
        return call(function () use($process) : \Generator {
            (yield $process->start());
            return $process;
        });
    }
    /**
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    * @param (string | null) $cwd Working directory.
    * @param mixed[] $env Array of environment variables.
    * @param string $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct($script, string $cwd = null, array $env = [], string $binary = null)
    {
        $this->hub = Loop::getState(self::class);
        if (!$this->hub instanceof Internal\ProcessHub) {
            $this->hub = new Internal\ProcessHub();
            Loop::setState(self::class, $this->hub);
        }
        $options = ["html_errors" => "0", "display_errors" => "0", "log_errors" => "1"];
        if ($binary === null) {
            if (\PHP_SAPI === "cli") {
                $binary = \PHP_BINARY;
            } else {
                $binary = self::$binaryPath ?? self::locateBinary();
            }
        } elseif (!\is_executable($binary)) {
            throw new \Error(\sprintf("The PHP binary path '%s' was not found or is not executable", $binary));
        }
        // Write process runner to external file if inside a PHAR,
        // because PHP can't open files inside a PHAR directly except for the stub.
        if (\strpos(self::SCRIPT_PATH, "phar://") === 0) {
            if (self::$pharScriptPath) {
                $scriptPath = self::$pharScriptPath;
            } else {
                $path = \dirname(self::SCRIPT_PATH);
                if (\Phabel\Target\Php80\Polyfill::substr(\Phar::running(false), -5) !== ".phar") {
                    self::$pharCopy = \sys_get_temp_dir() . "/phar-" . \bin2hex(\random_bytes(10)) . ".phar";
                    \copy(\Phar::running(false), self::$pharCopy);
                    \register_shutdown_function(static function () : void {
                        @\unlink(self::$pharCopy);
                    });
                    $path = "phar://" . self::$pharCopy . "/" . \Phabel\Target\Php80\Polyfill::substr($path, \strlen(\Phar::running(true)));
                }
                $contents = \file_get_contents(self::SCRIPT_PATH);
                $contents = \str_replace("__DIR__", \var_export($path, true), $contents);
                $suffix = \bin2hex(\random_bytes(10));
                self::$pharScriptPath = $scriptPath = \sys_get_temp_dir() . "/amp-process-runner-" . $suffix . ".php";
                \file_put_contents($scriptPath, $contents);
                \register_shutdown_function(static function () : void {
                    @\unlink(self::$pharScriptPath);
                });
            }
            // Monkey-patch the script path in the same way, only supported if the command is given as array.
            if (isset(self::$pharCopy) && \is_array($script) && isset($script[0])) {
                $script[0] = "phar://" . self::$pharCopy . \Phabel\Target\Php80\Polyfill::substr($script[0], \strlen(\Phar::running(true)));
            }
        } else {
            $scriptPath = self::SCRIPT_PATH;
        }
        if (\is_array($script)) {
            $script = \implode(" ", \array_map("escapeshellarg", $script));
        } else {
            $script = \escapeshellarg($script);
        }
        $command = \implode(" ", [\escapeshellarg($binary), $this->formatOptions($options), \escapeshellarg($scriptPath), $this->hub->getUri(), $script]);
        $this->process = new BaseProcess($command, $cwd, $env);
    }
    /**
     *
     */
    private static function locateBinary() : string
    {
        $executable = \strncasecmp(\PHP_OS, "WIN", 3) === 0 ? "php.exe" : "php";
        $paths = \array_filter(\explode(\PATH_SEPARATOR, \getenv("PATH")));
        $paths[] = \PHP_BINDIR;
        $paths = \array_unique($paths);
        foreach ($paths as $path) {
            $path .= \DIRECTORY_SEPARATOR . $executable;
            if (\is_executable($path)) {
                return self::$binaryPath = $path;
            }
        }
        throw new \Error("Could not locate PHP executable binary");
    }
    /**
     *
     */
    private function formatOptions(array $options) : string
    {
        $result = [];
        foreach ($options as $option => $value) {
            $result[] = \sprintf("-d%s=%s", $option, $value);
        }
        return \implode(" ", $result);
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * {@inheritdoc}
     */
    public function start() : Promise
    {
        return call(function () : \Generator {
            try {
                $pid = (yield $this->process->start());
                (yield $this->process->getStdin()->write($this->hub->generateKey($pid, self::KEY_LENGTH)));
                $this->channel = (yield $this->hub->accept($pid));
                return $pid;
            } catch (\Throwable $exception) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new ContextException("Starting the process failed", 0, $exception);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        return $this->process->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (ChannelException $e) {
                throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        if ($data instanceof ExitResult) {
            throw new \Error("Cannot send exit result objects");
        }
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->channel->send($data));
            } catch (ChannelException $e) {
                if ($this->channel === null) {
                    throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                try {
                    $data = (yield Promise\timeout($this->join(), 100));
                } catch (ContextException|ChannelException|TimeoutException $ex) {
                    if ($this->isRunning()) {
                        $this->kill();
                    }
                    throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                throw new SynchronizationError(\sprintf('Process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)), 0, $e);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function join() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (\Throwable $exception) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new ContextException("Failed to receive result from process", 0, $exception);
            }
            if (!$data instanceof ExitResult) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new SynchronizationError("Did not receive an exit result from process");
            }
            $this->channel->close();
            $code = (yield $this->process->join());
            if ($code !== 0) {
                throw new ContextException(\sprintf("Process exited with code %d", $code));
            }
            return $data->getResult();
        });
    }
    /**
     * Send a signal to the process.
     *
     * @see \Amp\Process\Process::signal()
     *
     * @param int $signo
     *
     * @throws \Amp\Process\ProcessException
     * @throws \Amp\Process\StatusError
     */
    public function signal(int $signo) : void
    {
        $this->process->signal($signo);
    }
    /**
     * Returns the PID of the process.
     *
     * @see \Amp\Process\Process::getPid()
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getPid() : int
    {
        return $this->process->getPid();
    }
    /**
     * Returns the STDIN stream of the process.
     *
     * @see \Amp\Process\Process::getStdin()
     *
     * @return ProcessOutputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStdin() : ProcessOutputStream
    {
        return $this->process->getStdin();
    }
    /**
     * Returns the STDOUT stream of the process.
     *
     * @see \Amp\Process\Process::getStdout()
     *
     * @return ProcessInputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStdout() : ProcessInputStream
    {
        return $this->process->getStdout();
    }
    /**
     * Returns the STDOUT stream of the process.
     *
     * @see \Amp\Process\Process::getStderr()
     *
     * @return ProcessInputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStderr() : ProcessInputStream
    {
        return $this->process->getStderr();
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        $this->process->kill();
        if ($this->channel !== null) {
            $this->channel->close();
        }
    }
}<?php

namespace Amp\Parallel\Context;

use Amp\Loop;
use Amp\Parallel\Sync\ChannelException;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitFailure;
use Amp\Parallel\Sync\ExitResult;
use Amp\Parallel\Sync\ExitSuccess;
use Amp\Parallel\Sync\SerializationException;
use Amp\Parallel\Sync\SynchronizationError;
use Amp\Promise;
use Amp\TimeoutException;
use parallel\Runtime;
use function Amp\call;
/**
 * Implements an execution context using native threads provided by the parallel extension.
 */
final class Parallel implements Context
{
    const EXIT_CHECK_FREQUENCY = 250;
    const KEY_LENGTH = 32;
    /** @var string|null */
    private static $autoloadPath;
    /** @var int Next thread ID. */
    private static $nextId = 1;
    /** @var Internal\ProcessHub */
    private $hub;
    /** @var int|null */
    private $id;
    /** @var Runtime|null */
    private $runtime;
    /** @var ChannelledSocket|null A channel for communicating with the parallel thread. */
    private $channel;
    /** @var string Script path. */
    private $script;
    /** @var string[] */
    private $args = [];
    /** @var int */
    private $oid = 0;
    /** @var bool */
    private $killed = false;
    /**
     * Checks if threading is enabled.
     *
     * @return bool True if threading is enabled, otherwise false.
     */
    public static function isSupported() : bool
    {
        return \extension_loaded('parallel');
    }
    /**
    * Creates and starts a new thread.
    *
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Promise<Thread> The thread object that was spawned.
    */
    public static function run($script) : Promise
    {
        $thread = new self($script);
        return call(function () use($thread) : \Generator {
            (yield $thread->start());
            return $thread;
        });
    }
    /**
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @throws \Error Thrown if the pthreads extension is not available.
    */
    public function __construct($script)
    {
        if (!self::isSupported()) {
            throw new \Error("The parallel extension is required to create parallel threads.");
        }
        $this->hub = Loop::getState(self::class);
        if (!$this->hub instanceof Internal\ParallelHub) {
            $this->hub = new Internal\ParallelHub();
            Loop::setState(self::class, $this->hub);
        }
        if (\is_array($script)) {
            $this->script = (string) \array_shift($script);
            $this->args = \array_values(\array_map("strval", $script));
        } else {
            $this->script = (string) $script;
        }
        if (self::$autoloadPath === null) {
            $paths = [\dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR . "vendor" . \DIRECTORY_SEPARATOR . "autoload.php", \dirname(__DIR__, 4) . \DIRECTORY_SEPARATOR . "autoload.php"];
            foreach ($paths as $path) {
                if (\file_exists($path)) {
                    self::$autoloadPath = $path;
                    break;
                }
            }
            if (self::$autoloadPath === null) {
                throw new \Error("Could not locate autoload.php");
            }
        }
    }
    /**
    * Returns the thread to the condition before starting. The new thread can be started and run independently of the
    first thread.
    */
    public function __clone()
    {
        $this->runtime = null;
        $this->channel = null;
        $this->id = null;
        $this->oid = 0;
        $this->killed = false;
    }
    /**
     * Kills the thread if it is still running.
     *
     * @throws \Amp\Parallel\Context\ContextException
     */
    public function __destruct()
    {
        if (\getmypid() === $this->oid) {
            $this->kill();
        }
    }
    /**
     * Checks if the context is running.
     *
     * @return bool True if the context is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->channel !== null;
    }
    /**
     * Spawns the thread and begins the thread's execution.
     *
     * @return Promise<int> Resolved once the thread has started.
     *
     * @throws \Amp\Parallel\Context\StatusError If the thread has already been started.
     * @throws \Amp\Parallel\Context\ContextException If starting the thread was unsuccessful.
     */
    public function start() : Promise
    {
        if ($this->oid !== 0) {
            throw new StatusError('The thread has already been started.');
        }
        $this->oid = \getmypid();
        $this->runtime = new Runtime(self::$autoloadPath);
        $this->id = self::$nextId++;
        $future = $this->runtime->run(static function (int $id, string $uri, string $key, string $path, array $argv) : int {
            // @codeCoverageIgnoreStart
            // Only executed in thread.
            \define("AMP_CONTEXT", "parallel");
            \define("AMP_CONTEXT_ID", $id);
            if (!($socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT))) {
                \trigger_error("Could not connect to IPC socket", E_USER_ERROR);
                return 1;
            }
            $channel = new ChannelledSocket($socket, $socket);
            try {
                Promise\wait($channel->send($key));
            } catch (\Throwable $exception) {
                \trigger_error("Could not send key to parent", E_USER_ERROR);
                return 1;
            }
            try {
                Loop::unreference(Loop::repeat(self::EXIT_CHECK_FREQUENCY, function () : void {
                    // Timer to give the chance for the PHP VM to be interrupted by Runtime::kill(), since system calls such as
                    // select() will not be interrupted.
                }));
                try {
                    if (!\is_file($path)) {
                        throw new \Error(\sprintf("No script found at '%s' (be sure to provide the full path to the script)", $path));
                    }
                    $argc = \array_unshift($argv, $path);
                    try {
                        // Protect current scope by requiring script within another function.
                        $callable = (function () use($argc, $argv) : callable {
                            // Using $argc so it is available to the required script.
                            return require $argv[0];
                        })->bindTo(null, null)();
                    } catch (\TypeError $exception) {
                        throw new \Error(\sprintf("Script '%s' did not return a callable function", $path), 0, $exception);
                    } catch (\ParseError $exception) {
                        throw new \Error(\sprintf("Script '%s' contains a parse error", $path), 0, $exception);
                    }
                    $result = new ExitSuccess(Promise\wait(call($callable, $channel)));
                } catch (\Throwable $exception) {
                    $result = new ExitFailure($exception);
                }
                Promise\wait(call(function () use($channel, $result) : \Generator {
                    try {
                        (yield $channel->send($result));
                    } catch (SerializationException $exception) {
                        // Serializing the result failed. Send the reason why.
                        (yield $channel->send(new ExitFailure($exception)));
                    }
                }));
            } catch (\Throwable $exception) {
                \trigger_error("Could not send result to parent; be sure to shutdown the child before ending the parent", E_USER_ERROR);
                return 1;
            } finally {
                $channel->close();
            }
            return 0;
            // @codeCoverageIgnoreEnd
        }, [$this->id, $this->hub->getUri(), $this->hub->generateKey($this->id, self::KEY_LENGTH), $this->script, $this->args]);
        return call(function () use($future) : \Generator {
            try {
                $this->channel = (yield $this->hub->accept($this->id));
                $this->hub->add($this->id, $this->channel, $future);
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Starting the parallel runtime failed", 0, $exception);
            }
            if ($this->killed) {
                $this->kill();
            }
            return $this->id;
        });
    }
    /**
     * Immediately kills the context.
     */
    public function kill() : void
    {
        $this->killed = true;
        if ($this->runtime !== null) {
            try {
                $this->runtime->kill();
            } finally {
                $this->close();
            }
        }
    }
    /**
     * Closes channel and socket if still open.
     */
    private function close() : void
    {
        $this->runtime = null;
        if ($this->channel !== null) {
            $this->channel->close();
        }
        $this->channel = null;
        $this->hub->remove($this->id);
    }
    /**
    * Gets a promise that resolves when the context ends and joins with the
    parent context.
    *
    * @return \Amp\Promise<mixed>
    *
    * @throws StatusError Thrown if the context has not been started.
    * @throws SynchronizationError Thrown if an exit status object is not received.
    * @throws ContextException If the context stops responding.
    */
    public function join() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        return call(function () : \Generator {
            try {
                $response = (yield $this->channel->receive());
                $this->close();
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Failed to receive result from thread", 0, $exception);
            }
            if (!$response instanceof ExitResult) {
                $this->kill();
                throw new SynchronizationError('Did not receive an exit result from thread.');
            }
            return $response->getResult();
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started.');
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (ChannelException $e) {
                throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Thread unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        if ($data instanceof ExitResult) {
            throw new \Error('Cannot send exit result objects.');
        }
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->channel->send($data));
            } catch (ChannelException $e) {
                if ($this->channel === null) {
                    throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                try {
                    $data = (yield Promise\timeout($this->join(), 100));
                } catch (ContextException|ChannelException|TimeoutException $ex) {
                    $this->kill();
                    throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                throw new SynchronizationError(\sprintf('Thread unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)), 0, $e);
            }
        });
    }
    /**
     * Returns the ID of the thread. This ID will be unique to this process.
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getId() : int
    {
        if ($this->id === null) {
            throw new StatusError('The thread has not been started');
        }
        return $this->id;
    }
}<?php

namespace Amp\Parallel\Context;

use Amp\Parallel\Sync\Channel;
use Amp\Promise;
interface Context extends Channel
{
    /**
     * @return bool
     */
    public function isRunning() : bool;
    /**
     * Starts the execution context.
     *
     * @return Promise<null> Resolved once the context has started.
     */
    public function start() : Promise;
    /**
     * Immediately kills the context.
     */
    public function kill();
    /**
     * @return \Amp\Promise<mixed> Resolves with the returned from the context.
     *
     * @throws \Amp\Parallel\Context\ContextException If the context dies unexpectedly.
     * @throws \Amp\Parallel\Sync\PanicError If the context throws an uncaught exception.
     */
    public function join() : Promise;
}<?php

namespace Amp\Redis;

use Exception;
class RedisException extends Exception
{
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Promise;
final class RedisHyperLogLog
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param string $element
     * @param string ...$elements
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/pfadd
     */
    public function add(string $element, string ...$elements) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['pfadd', $this->key, $element], $elements), toBool);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/pfcount
     */
    public function count() : Promise
    {
        return $this->queryExecutor->execute(['pfcount', $this->key]);
    }
    /**
     * @param string $sourceKey
     * @param string ...$sourceKeys
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/pfmerge
     */
    public function storeUnion(string $sourceKey, string ...$sourceKeys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['pfmerge', $this->key, $sourceKey], $sourceKeys), toNull);
    }
}<?php

namespace Amp\Redis;

final class RespParser
{
    public const CRLF = "\r\n";
    public const TYPE_SIMPLE_STRING = '+';
    public const TYPE_ERROR = '-';
    public const TYPE_ARRAY = '*';
    public const TYPE_BULK_STRING = '$';
    public const TYPE_INTEGER = ':';
    private $responseCallback;
    private $buffer = '';
    private $currentResponse;
    private $arrayStack;
    private $currentSize;
    private $arraySizes;
    /**
     *
     */
    public function __construct(callable $responseCallback)
    {
        $this->responseCallback = $responseCallback;
    }
    /**
     *
     */
    public function reset() : void
    {
        $this->buffer = '';
        $this->currentResponse = null;
        $this->arrayStack = null;
        $this->currentSize = null;
        $this->arraySizes = null;
    }
    /**
     *
     */
    public function append(string $str) : void
    {
        $this->buffer .= $str;
        do {
            $type = $this->buffer[0];
            $pos = \strpos($this->buffer, self::CRLF);
            if ($pos === false) {
                return;
            }
            switch ($type) {
                case self::TYPE_SIMPLE_STRING:
                case self::TYPE_INTEGER:
                case self::TYPE_ARRAY:
                case self::TYPE_ERROR:
                    $payload = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 1, $pos - 1);
                    $remove = $pos + 2;
                    break;
                case self::TYPE_BULK_STRING:
                    $length = (int) \Phabel\Target\Php80\Polyfill::substr($this->buffer, 1, $pos);
                    if ($length === -1) {
                        $payload = null;
                        $remove = $pos + 2;
                    } else {
                        if (\strlen($this->buffer) < $pos + $length + 4) {
                            return;
                        }
                        $payload = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $pos + 2, $length);
                        $remove = $pos + $length + 4;
                    }
                    break;
                default:
                    throw new ParserException(\sprintf('unknown resp data type: %s', $type));
            }
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $remove);
            switch ($type) {
                case self::TYPE_INTEGER:
                case self::TYPE_ARRAY:
                    $payload = (int) $payload;
                    break;
                case self::TYPE_ERROR:
                    $payload = new QueryException($payload);
                    break;
                default:
                    break;
            }
            if ($this->currentResponse !== null) {
                // extend array response
                if ($type === self::TYPE_ARRAY) {
                    if ($payload >= 0) {
                        $this->arraySizes[] = $this->currentSize;
                        $this->arrayStack[] =& $this->currentResponse;
                        $this->currentSize = $payload + 1;
                        $this->currentResponse[] = [];
                        $this->currentResponse =& $this->currentResponse[\sizeof($this->currentResponse) - 1];
                    } else {
                        $this->currentResponse[] = null;
                    }
                } else {
                    $this->currentResponse[] = $payload;
                }
                while (--$this->currentSize === 0) {
                    if (\count($this->arrayStack) === 0) {
                        $cb = $this->responseCallback;
                        $cb($this->currentResponse);
                        $this->currentResponse = null;
                        break;
                    }
                    // index doesn't start at 0 :(
                    \end($this->arrayStack);
                    $key = \key($this->arrayStack);
                    $this->currentResponse =& $this->arrayStack[$key];
                    $this->currentSize = \array_pop($this->arraySizes);
                    unset($this->arrayStack[$key]);
                }
            } elseif ($type === self::TYPE_ARRAY) {
                // start new array response
                if ($payload > 0) {
                    $this->currentSize = $payload;
                    $this->arrayStack = $this->arraySizes = $this->currentResponse = [];
                } elseif ($payload === 0) {
                    $cb = $this->responseCallback;
                    $cb([]);
                } else {
                    $cb = $this->responseCallback;
                    $cb(null);
                }
            } else {
                // single data type response
                $cb = $this->responseCallback;
                $cb($payload);
            }
        } while (isset($this->buffer[0]));
    }
}<?php

namespace Amp\Redis;

class SocketException extends RedisException
{
}<?php

namespace Amp\Redis;

class ParserException extends RedisException
{
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use function Amp\call;
final class Redis
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string[] */
    private $evalCache = [];
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor)
    {
        $this->queryExecutor = $queryExecutor;
    }
    /**
     *
     */
    public function getHyperLogLog(string $key) : RedisHyperLogLog
    {
        return new RedisHyperLogLog($this->queryExecutor, $key);
    }
    /**
     *
     */
    public function getList(string $key) : RedisList
    {
        return new RedisList($this->queryExecutor, $key);
    }
    /**
     *
     */
    public function getMap(string $key) : RedisMap
    {
        return new RedisMap($this->queryExecutor, $key);
    }
    /**
     *
     */
    public function getSet(string $key) : RedisSet
    {
        return new RedisSet($this->queryExecutor, $key);
    }
    /**
     *
     */
    public function getSortedSet(string $key) : RedisSortedSet
    {
        return new RedisSortedSet($this->queryExecutor, $key);
    }
    /**
     * @param string $arg
     * @param string ...$args
     *
     * @return Promise
     */
    public function query(string $arg, string ...$args) : Promise
    {
        return $this->queryExecutor->execute(\array_merge([$arg], $args));
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/del
     */
    public function delete(string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['del', $key], $keys));
    }
    /**
     * @param string $key
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/dump
     */
    public function dump(string $key) : Promise
    {
        return $this->queryExecutor->execute(['dump', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/exists
     */
    public function has(string $key) : Promise
    {
        return $this->queryExecutor->execute(['exists', $key], toBool);
    }
    /**
     * @param string $key
     * @param int $seconds
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/expire
     */
    public function expireIn(string $key, int $seconds) : Promise
    {
        return $this->queryExecutor->execute(['expire', $key, $seconds], toBool);
    }
    /**
     * @param string $key
     * @param int $millis
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/pexpire
     */
    public function expireInMillis(string $key, int $millis) : Promise
    {
        return $this->queryExecutor->execute(['pexpire', $key, $millis], toBool);
    }
    /**
     * @param string $key
     * @param int $timestamp
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/expireat
     */
    public function expireAt(string $key, int $timestamp) : Promise
    {
        return $this->queryExecutor->execute(['expireat', $key, $timestamp], toBool);
    }
    /**
     * @param string $key
     * @param int $timestamp
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/pexpireat
     */
    public function expireAtMillis(string $key, int $timestamp) : Promise
    {
        return $this->queryExecutor->execute(['pexpireat', $key, $timestamp], toBool);
    }
    /**
     * @param string $pattern
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/keys
     *
     * @see Redis::scan()
     */
    public function getKeys(string $pattern = '*') : Promise
    {
        return $this->queryExecutor->execute(['keys', $pattern]);
    }
    /**
     * @param string $key
     * @param int $db
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/move
     */
    public function move(string $key, int $db) : Promise
    {
        return $this->queryExecutor->execute(['move', $key, $db], toBool);
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/object
     */
    public function getObjectRefcount(string $key) : Promise
    {
        return $this->queryExecutor->execute(['object', 'refcount', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/object
     */
    public function getObjectEncoding(string $key) : Promise
    {
        return $this->queryExecutor->execute(['object', 'encoding', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/object
     */
    public function getObjectIdletime(string $key) : Promise
    {
        return $this->queryExecutor->execute(['object', 'idletime', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/persist
     */
    public function persist(string $key) : Promise
    {
        return $this->queryExecutor->execute(['persist', $key], toBool);
    }
    /**
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/randomkey
     */
    public function getRandomKey() : Promise
    {
        return $this->queryExecutor->execute(['randomkey']);
    }
    /**
     * @param string $key
     * @param string $newKey
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/rename
     */
    public function rename(string $key, string $newKey) : Promise
    {
        return $this->queryExecutor->execute(['rename', $key, $newKey], toNull);
    }
    /**
     * @param string $key
     * @param string $newKey
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/renamenx
     */
    public function renameWithoutOverwrite(string $key, string $newKey) : Promise
    {
        return $this->queryExecutor->execute(['renamenx', $key, $newKey], toNull);
    }
    /**
     * @param string $key
     * @param string $serializedValue
     * @param int $ttl
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/restore
     */
    public function restore(string $key, string $serializedValue, int $ttl = 0) : Promise
    {
        return $this->queryExecutor->execute(['restore', $key, $ttl, $serializedValue], toNull);
    }
    /**
     * @param string $pattern
     * @param int $count
     *
     * @return Iterator<string>
     *
     * @link https://redis.io/commands/scan
     */
    public function scan(?string $pattern = null, ?int $count = null) : Iterator
    {
        return new Producer(function (callable $emit) use($pattern, $count) {
            $cursor = 0;
            do {
                $query = ['SCAN', $cursor];
                if ($pattern !== null) {
                    $query[] = 'MATCH';
                    $query[] = $pattern;
                }
                if ($count !== null) {
                    $query[] = 'COUNT';
                    $query[] = $count;
                }
                [$cursor, $keys] = (yield $this->queryExecutor->execute($query));
                foreach ($keys as $key) {
                    (yield $emit($key));
                }
            } while ($cursor !== '0');
        });
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/ttl
     */
    public function getTtl(string $key) : Promise
    {
        return $this->queryExecutor->execute(['ttl', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/pttl
     */
    public function getTtlInMillis(string $key) : Promise
    {
        return $this->queryExecutor->execute(['pttl', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/type
     */
    public function getType(string $key) : Promise
    {
        return $this->queryExecutor->execute(['type', $key]);
    }
    /**
     * @param string $key
     * @param string $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/append
     */
    public function append(string $key, string $value) : Promise
    {
        return $this->queryExecutor->execute(['append', $key, $value]);
    }
    /**
     * @param string $key
     * @param (int | null) $start
     * @param (int | null) $end
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitcount
     */
    public function countBits(string $key, ?int $start = null, ?int $end = null) : Promise
    {
        $cmd = ['bitcount', $key];
        if (isset($start, $end)) {
            $cmd[] = $start;
            $cmd[] = $end;
        } elseif (isset($start) || isset($end)) {
            throw \Error('Start and end must both be set or unset in countBits(), got start = ' . $start . ' and end = ' . $end);
        }
        return $this->queryExecutor->execute($cmd);
    }
    /**
     * @param string $destination
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitop
     */
    public function storeBitwiseAnd(string $destination, string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['bitop', 'and', $destination, $key], $keys));
    }
    /**
     * @param string $destination
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitop
     */
    public function storeBitwiseOr(string $destination, string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['bitop', 'or', $destination, $key], $keys));
    }
    /**
     * @param string $destination
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitop
     */
    public function storeBitwiseXor(string $destination, string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['bitop', 'xor', $destination, $key], $keys));
    }
    /**
     * @param string $destination
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitop
     */
    public function storeBitwiseNot(string $destination, string $key) : Promise
    {
        return $this->queryExecutor->execute(['bitop', 'not', $destination, $key]);
    }
    /**
     * @param string $key
     * @param bool $bit
     * @param int $start
     * @param int $end
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitpos
     */
    public function getBitPosition(string $key, bool $bit, ?int $start = null, ?int $end = null) : Promise
    {
        $payload = ['bitpos', $key, $bit ? 1 : 0];
        if ($start !== null) {
            $payload[] = $start;
            if ($end !== null) {
                $payload[] = $end;
            }
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @param string $key
     * @param int $decrement
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/decrby
     */
    public function decrement(string $key, int $decrement = 1) : Promise
    {
        if ($decrement === 1) {
            return $this->queryExecutor->execute(['decr', $key]);
        }
        return $this->queryExecutor->execute(['decrby', $key, $decrement]);
    }
    /**
     * @param string $key
     *
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/get
     */
    public function get(string $key) : Promise
    {
        return $this->queryExecutor->execute(['get', $key]);
    }
    /**
     * @param string $key
     * @param int $offset
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/getbit
     */
    public function getBit(string $key, int $offset) : Promise
    {
        return $this->queryExecutor->execute(['getbit', $key, $offset], toBool);
    }
    /**
     * @param string $key
     * @param int $start
     * @param int $end
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/getrange
     */
    public function getRange(string $key, int $start = 0, int $end = -1) : Promise
    {
        return $this->queryExecutor->execute(['getrange', $key, $start, $end]);
    }
    /**
     * @param string $key
     * @param string $value
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/getset
     */
    public function getAndSet(string $key, string $value) : Promise
    {
        return $this->queryExecutor->execute(['getset', $key, $value]);
    }
    /**
     * @param string $key
     * @param int $increment
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/incrby
     */
    public function increment(string $key, int $increment = 1) : Promise
    {
        if ($increment === 1) {
            return $this->queryExecutor->execute(['incr', $key]);
        }
        return $this->queryExecutor->execute(['incrby', $key, $increment]);
    }
    /**
     * @param string $key
     * @param float $increment
     *
     * @return Promise<float>
     *
     * @link https://redis.io/commands/incrbyfloat
     */
    public function incrementByFloat(string $key, float $increment) : Promise
    {
        return $this->queryExecutor->execute(['incrbyfloat', $key, $increment], toFloat);
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<array<(string | null)>>
     *
     * @link https://redis.io/commands/mget
     */
    public function getMultiple(string $key, string ...$keys) : Promise
    {
        \array_unshift($keys, $key);
        $query = \array_merge(['mget'], $keys);
        return $this->queryExecutor->execute($query, static function ($response) use($keys) {
            return \array_combine($keys, $response);
        });
    }
    /**
     * @param array $data
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/mset
     */
    public function setMultiple(array $data) : Promise
    {
        $payload = ['mset'];
        foreach ($data as $key => $value) {
            $payload[] = $key;
            $payload[] = $value;
        }
        return $this->queryExecutor->execute($payload, toNull);
    }
    /**
     * @param array $data
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/msetnx
     */
    public function setMultipleWithoutOverwrite(array $data) : Promise
    {
        $payload = ['msetnx'];
        foreach ($data as $key => $value) {
            $payload[] = $key;
            $payload[] = $value;
        }
        return $this->queryExecutor->execute($payload, toNull);
    }
    /**
     * @param string $key
     * @param string $value
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/setnx
     */
    public function setWithoutOverwrite(string $key, string $value) : Promise
    {
        return $this->queryExecutor->execute(['setnx', $key, $value], toBool);
    }
    /**
     * @param string $key
     * @param string $value
     *
     * @return Promise<bool>
     */
    public function set(string $key, string $value, SetOptions $options = null) : Promise
    {
        $query = ['set', $key, $value];
        if ($options !== null) {
            $query = \array_merge($query, $options->toQuery());
        }
        return $this->queryExecutor->execute($query, toBool);
    }
    /**
     * @param string $key
     * @param int $offset
     * @param bool $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/setbit
     */
    public function setBit(string $key, int $offset, bool $value) : Promise
    {
        return $this->queryExecutor->execute(['setbit', $key, $offset, (int) $value]);
    }
    /**
     * @param string $key
     * @param int $offset
     * @param mixed $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/setrange
     */
    public function setRange(string $key, int $offset, string $value) : Promise
    {
        return $this->queryExecutor->execute(['setrange', $key, $offset, $value]);
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/strlen
     */
    public function getLength(string $key) : Promise
    {
        return $this->queryExecutor->execute(['strlen', $key]);
    }
    /**
     * @param string $channel
     * @param string $message
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/publish
     */
    public function publish(string $channel, string $message) : Promise
    {
        return $this->queryExecutor->execute(['publish', $channel, $message]);
    }
    /**
     * @param string $pattern
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/pubsub
     */
    public function getActiveChannels(?string $pattern = null) : Promise
    {
        $payload = ['pubsub', 'channels'];
        if ($pattern !== null) {
            $payload[] = $pattern;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @param string ...$channels
     *
     * @return Promise<int[]>
     *
     * @link https://redis.io/commands/pubsub
     */
    public function getNumberOfSubscriptions(string ...$channels) : Promise
    {
        $query = \array_merge(['pubsub', 'numsub'], $channels);
        return $this->queryExecutor->execute($query, static function ($response) {
            $result = [];
            for ($i = 0, $count = \count($response); $i < $count; $i += 2) {
                $result[$response[$i]] = $response[$i + 1];
            }
            return $result;
        });
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/pubsub
     */
    public function getNumberOfPatternSubscriptions() : Promise
    {
        return $this->queryExecutor->execute(['pubsub', 'numpat']);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/ping
     */
    public function ping() : Promise
    {
        return $this->queryExecutor->execute(['ping'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/quit
     */
    public function quit() : Promise
    {
        return $this->queryExecutor->execute(['quit'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/bgrewriteaof
     */
    public function rewriteAofAsync() : Promise
    {
        return $this->queryExecutor->execute(['bgrewriteaof'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/bgsave
     */
    public function saveAsync() : Promise
    {
        return $this->queryExecutor->execute(['bgsave'], toNull);
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/client-getname
     */
    public function getName() : Promise
    {
        return $this->queryExecutor->execute(['client', 'getname']);
    }
    /**
     * @param int $timeInMillis
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/client-pause
     */
    public function pauseMillis(int $timeInMillis) : Promise
    {
        return $this->queryExecutor->execute(['client', 'pause', $timeInMillis], toNull);
    }
    /**
     * @param string $name
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/client-setname
     */
    public function setName(string $name) : Promise
    {
        return $this->queryExecutor->execute(['client', 'setname', $name], toNull);
    }
    /**
     * @param string $parameter
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/config-get
     */
    public function getConfig(string $parameter) : Promise
    {
        return $this->queryExecutor->execute(['config', 'get', $parameter]);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/config-resetstat
     */
    public function resetStatistics() : Promise
    {
        return $this->queryExecutor->execute(['config', 'resetstat'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/config-rewrite
     */
    public function rewriteConfig() : Promise
    {
        return $this->queryExecutor->execute(['config', 'rewrite'], toNull);
    }
    /**
     * @param string $parameter
     * @param string $value
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/config-set
     */
    public function setConfig(string $parameter, string $value) : Promise
    {
        return $this->queryExecutor->execute(['config', 'set', $parameter, $value], toNull);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/dbsize
     */
    public function getDatabaseSize() : Promise
    {
        return $this->queryExecutor->execute(['dbsize']);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/flushall
     */
    public function flushAll() : Promise
    {
        return $this->queryExecutor->execute(['flushall'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/flushdb
     */
    public function flushDatabase() : Promise
    {
        return $this->queryExecutor->execute(['flushdb'], toNull);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/lastsave
     */
    public function getLastSave() : Promise
    {
        return $this->queryExecutor->execute(['lastsave']);
    }
    /**
     * @return Promise<array>
     *
     * @link https://redis.io/commands/role
     */
    public function getRole() : Promise
    {
        return $this->queryExecutor->execute(['role']);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/save
     */
    public function save() : Promise
    {
        return $this->queryExecutor->execute(['save'], toNull);
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/shutdown
     */
    public function shutdownWithSave() : Promise
    {
        return $this->queryExecutor->execute(['shutdown', 'save']);
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/shutdown
     */
    public function shutdownWithoutSave() : Promise
    {
        return $this->queryExecutor->execute(['shutdown', 'nosave']);
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/shutdown
     */
    public function shutdown() : Promise
    {
        return $this->queryExecutor->execute(['shutdown']);
    }
    /**
     * @param string $host
     * @param int $port
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/slaveof
     */
    public function enableReplication(string $host, int $port) : Promise
    {
        return $this->queryExecutor->execute(['slaveof', $host, $port], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/slaveof
     */
    public function disableReplication() : Promise
    {
        return $this->queryExecutor->execute(['slaveof', 'no', 'one'], toNull);
    }
    /**
     * @param int $count
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/slowlog
     */
    public function getSlowlog(?int $count = null) : Promise
    {
        $payload = ['slowlog', 'get'];
        if ($count !== null) {
            $payload[] = $count;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/slowlog
     */
    public function getSlowlogLength() : Promise
    {
        return $this->queryExecutor->execute(['slowlog', 'len']);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/slowlog
     */
    public function resetSlowlog() : Promise
    {
        return $this->queryExecutor->execute(['slowlog', 'reset'], toNull);
    }
    /**
     * @return Promise<array>
     *
     * @link https://redis.io/commands/time
     */
    public function getTime() : Promise
    {
        return $this->queryExecutor->execute(['time']);
    }
    /**
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/script-exists
     */
    public function hasScript(string $sha1) : Promise
    {
        return $this->queryExecutor->execute(['script', 'exists', $sha1], static function (array $array) {
            return (bool) $array[0];
        });
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/script-flush
     */
    public function flushScripts() : Promise
    {
        $this->evalCache = [];
        // same as internal redis behavior
        return $this->queryExecutor->execute(['script', 'flush'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/script-kill
     */
    public function killScript() : Promise
    {
        return $this->queryExecutor->execute(['script', 'kill'], toNull);
    }
    /**
     * @param string $script
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/script-load
     */
    public function loadScript(string $script) : Promise
    {
        return $this->queryExecutor->execute(['script', 'load', $script]);
    }
    /**
     * @param string $text
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/echo
     */
    public function echo(string $text) : Promise
    {
        return $this->queryExecutor->execute(['echo', $text]);
    }
    /**
     * @param string $script
     * @param string[] $keys
     * @param string[] $args
     *
     * @return Promise<mixed>
     *
     * @link https://redis.io/commands/eval
     */
    public function eval(string $script, array $keys = [], array $args = []) : Promise
    {
        return call(function () use($script, $keys, $args) {
            try {
                $sha1 = $this->evalCache[$script] ?? ($this->evalCache[$script] = \sha1($script));
                $query = \array_merge(['evalsha', $sha1, \count($keys)], $keys, $args);
                return (yield $this->queryExecutor->execute($query));
            } catch (QueryException $e) {
                if (\strtok($e->getMessage(), ' ') === 'NOSCRIPT') {
                    $query = \array_merge(['eval', $script, \count($keys)], $keys, $args);
                    return $this->queryExecutor->execute($query);
                }
                throw $e;
            }
        });
    }
    /**
     *
     */
    public function select(int $database) : Promise
    {
        return $this->queryExecutor->execute(['select', $database], toNull);
    }
}<?php

namespace Amp\Redis;

use Amp\Iterator;
use Amp\Promise;
final class Subscription implements Iterator
{
    private $iterator;
    private $unsubscribeCallback;
    /**
     *
     */
    public function __construct(Iterator $iterator, callable $unsubscribeCallback)
    {
        $this->iterator = $iterator;
        $this->unsubscribeCallback = $unsubscribeCallback;
    }
    /**
     * @inheritdoc
     */
    public function advance() : Promise
    {
        return $this->iterator->advance();
    }
    /**
     * @inheritdoc
     */
    public function getCurrent()
    {
        return $this->iterator->getCurrent();
    }
    /**
     *
     */
    public function cancel() : void
    {
        ($this->unsubscribeCallback)();
    }
}<?php

namespace Amp\Redis\Mutex;

class ConnectionLimitException extends MutexException
{
}<?php

namespace Amp\Redis\Mutex;

class LockException extends MutexException
{
}<?php

namespace Amp\Redis\Mutex;

final class MutexOptions
{
    private $keyPrefix = '';
    private $lockRenewInterval = 1000;
    private $lockExpiration = 3000;
    private $lockTimeout = 10000;
    /**
     *
     */
    public function getKeyPrefix() : string
    {
        return $this->keyPrefix;
    }
    /**
     *
     */
    public function getLockExpiration() : int
    {
        return $this->lockExpiration;
    }
    /**
     *
     */
    public function getLockRenewInterval() : int
    {
        return $this->lockRenewInterval;
    }
    /**
     *
     */
    public function getLockTimeout() : int
    {
        return $this->lockTimeout;
    }
    /**
     *
     */
    public function withKeyPrefix(string $keyPrefix) : self
    {
        $clone = clone $this;
        $clone->keyPrefix = $keyPrefix;
        return $clone;
    }
    /**
     *
     */
    public function withLockExpiration(int $lockExpiration) : self
    {
        $clone = clone $this;
        $clone->lockExpiration = $lockExpiration;
        return $clone;
    }
    /**
     *
     */
    public function withLockRenewInterval(int $lockRenewInterval) : self
    {
        $clone = clone $this;
        $clone->lockRenewInterval = $lockRenewInterval;
        return $clone;
    }
    /**
     *
     */
    public function withLockTimeout(int $lockTimeout) : self
    {
        $clone = clone $this;
        $clone->lockTimeout = $lockTimeout;
        return $clone;
    }
}<?php

namespace Amp\Redis\Mutex;

use Amp\Redis\RedisException;
class MutexException extends RedisException
{
}<?php

namespace Amp\Redis\Mutex;

use Amp\Loop;
use Amp\Promise;
use Amp\Redis\QueryExecutorFactory;
use Amp\Redis\Redis;
use Amp\Redis\RedisException;
use Amp\Sync\KeyedMutex;
use Amp\Sync\Lock;
use Psr\Log\LoggerInterface as PsrLogger;
use Psr\Log\NullLogger;
use function Amp\call;
use function Amp\delay;
/**
 * Mutex can be used to create locks for mutual exclusion in distributed clients.
 *
 * @author Niklas Keller <me@kelunik.com>
 */
final class Mutex implements KeyedMutex
{
    private const LOCK = <<<LOCK
local lock = KEYS[1]
local queue = KEYS[2]

local token = ARGV[1]
local ttl = ARGV[2]
local queueTtl = ARGV[3]

if redis.call("exists", lock) == 0 then
    if redis.call("llen", queue) == 0 then
        redis.call("set", lock, token, "px", ttl)
        return 1
    else
        local queued_tokens = redis.call("lrange", queue, 0, -1)
        local push = 1
        local position = 0
        
        for i=1,#queued_tokens do
            if queued_tokens[i] == token then
                push = 0
                position = i
                break
            end
        end

        if push == 1 then
            redis.call("rpush", queue, token)
        end

        local queued = redis.call("lpop", queue)
        redis.call("set", lock, queued, "px", ttl)
        if queued == token then
            return 2
        else
            redis.call("pexpire", queue, queueTtl)

            return -1 - position
        end
    end
else
    if redis.call("get", lock) == token then
        redis.call("set", lock, token, "px", ttl)
        return 1
    end

    local queued_tokens = redis.call("lrange", queue, 0, -1)
    for i=1,#queued_tokens do
        if queued_tokens[i] == token then
            redis.call("pexpire", queue, queueTtl)

            return -1 - i
        end
    end

    redis.call("rpush", queue, token)
    redis.call("pexpire", queue, queueTtl)

    return -1 - redis.call("llen", queue)
end
LOCK;
    private const UNLOCK = <<<UNLOCK
local lock = KEYS[1]
local token = ARGV[1]

if redis.call("get", lock) == token then
    redis.call("del", lock)
    return 1
else
    return 2
end
UNLOCK;
    private const RENEW = <<<RENEW
for i=1,#KEYS do
    if redis.call("get", KEYS[i]) == ARGV[i + 1] then
        redis.call("pexpire", KEYS[i], ARGV[1])
    end
end
RENEW;
    /** @var MutexOptions */
    private $options;
    /** @var Redis */
    private $sharedConnection;
    /** @var array[] */
    private $locks;
    /** @var string */
    private $watcher;
    /** @var PsrLogger */
    private $logger;
    private $numberOfLocks = 0;
    private $numberOfAttempts = 0;
    /**
     * Constructs a new Mutex instance. A single instance can be used to create as many locks as you need.
     *
     * @param QueryExecutorFactory $queryExecutorFactory
     * @param (MutexOptions | null) $options
     */
    public function __construct(QueryExecutorFactory $queryExecutorFactory, ?MutexOptions $options = null, ?PsrLogger $logger = null)
    {
        $this->options = $options ?? new MutexOptions();
        $this->sharedConnection = new Redis($queryExecutorFactory->createQueryExecutor());
        $this->logger = $logger ?? new NullLogger();
    }
    /**
     *
     */
    public function __destruct()
    {
        if (isset($this->watcher)) {
            Loop::cancel($this->watcher);
        }
    }
    /**
    * Acquires a lock.
    *
    * If directly acquiring a lock fails, the client is placed in a queue and reattempts to lock the key. If a client
    crashes or doesn't free the lock while not renewing it, the lock will expire and the next client in the queue
    will be able to acquire it.
    *
    * @param string $key Lock key.
    *
    * @return Promise<Lock> Resolves to an instance of `Lock`.
    */
    public function acquire(string $key) : Promise
    {
        return call(function () use($key) {
            $this->numberOfLocks++;
            $token = \base64_encode(\random_bytes(16));
            $prefix = $this->options->getKeyPrefix();
            $timeLimit = \microtime(true) * 1000 + $this->options->getLockTimeout();
            $attempts = 0;
            do {
                $attempts++;
                $this->numberOfAttempts++;
                $result = (yield $this->sharedConnection->eval(self::LOCK, ["{$prefix}lock:{$key}", "{$prefix}lock-queue:{$key}"], [$token, $this->options->getLockExpiration(), $this->options->getLockExpiration() + $this->options->getLockTimeout()]));
                if ($result < 1) {
                    if ($attempts > 2 && \microtime(true) * 1000 > $timeLimit) {
                        // In very rare cases we might not get the lock, but are at the head of the queue and another
                        // client moves us into the lock position. Deleting the token from the queue and afterwards
                        // unlocking solves this. No yield required, because we use the same connection.
                        $this->sharedConnection->getList("{$prefix}lock-queue:{$key}")->remove($token);
                        Promise\rethrow($this->unlock($key, $token));
                        throw new LockException('Failed to acquire lock for ' . $key . ' within ' . $this->options->getLockTimeout() . ' ms');
                    }
                    // A negative integer as reply means we're still in the queue and indicates the queue position.
                    // Making the timing dependent on the queue position greatly reduces CPU usage and locking attempts.
                    (yield delay(5 + \min((-$result - 1) * 10, 300)));
                }
            } while ($result < 1);
            if (empty($this->locks)) {
                $this->createRenewWatcher();
            }
            $this->locks[$key . ' @ ' . $token] = [$key, $token];
            return new Lock(0, function () use($key, $token) {
                Promise\rethrow($this->unlock($key, $token));
            });
        });
    }
    /**
     *
     */
    public function getNumberOfAttempts() : int
    {
        return $this->numberOfAttempts;
    }
    /**
     *
     */
    public function getNumberOfLocks() : int
    {
        return $this->numberOfLocks;
    }
    /**
     *
     */
    public function resetStatistics() : void
    {
        $this->numberOfAttempts = 0;
        $this->numberOfLocks = 0;
    }
    /**
     * Unlocks a previously acquired lock.
     *
     * @param string $key Lock key.
     * @param string $token Unique token generated during {@link lock()}.
     *
     * @return Promise Fails if lock couldn't be unlocked, otherwise resolves normally.
     */
    private function unlock(string $key, string $token) : Promise
    {
        return call(function () use($key, $token) {
            // Unset before unlocking, as we don't want to renew the lock anymore
            // If something goes wrong, the lock will simply expire
            unset($this->locks[$key . ' @ ' . $token]);
            if (empty($this->locks) && $this->watcher !== null) {
                Loop::cancel($this->watcher);
                $this->watcher = null;
            }
            $prefix = $this->options->getKeyPrefix();
            for ($attempt = 0; $attempt < 2; $attempt++) {
                try {
                    $result = (yield $this->sharedConnection->eval(self::UNLOCK, ["{$prefix}lock:{$key}"], [$token]));
                    if ($result === 2) {
                        $this->logger->warning('Lock was already expired when unlocked', ['key' => $key]);
                    }
                    break;
                } catch (RedisException $e) {
                    $this->logger->error('Unlock operation failed on attempt ' . ($attempt + 1), ['exception' => $e]);
                }
            }
        });
    }
    /**
     *
     */
    private function createRenewWatcher() : void
    {
        $this->watcher = Loop::repeat($this->options->getLockRenewInterval(), function () {
            \assert(!empty($this->locks));
            $keys = [];
            $arguments = [$this->options->getLockExpiration()];
            $prefix = $this->options->getKeyPrefix();
            foreach ($this->locks as [$key, $token]) {
                $keys[] = "{$prefix}lock:{$key}";
                $arguments[] = $token;
            }
            try {
                (yield $this->sharedConnection->eval(self::RENEW, $keys, $arguments));
            } catch (RedisException $e) {
                $this->logger->error('Renew operation failed, locks might expire', ['exception' => $e]);
            }
        });
    }
}<?php

namespace Amp\Redis;

class QueryException extends RedisException
{
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
final class RedisSet
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param string $member
     * @param string ...$members
     *
     * @return Promise<int>
     */
    public function add(string $member, string ...$members) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sadd', $this->key, $member], $members));
    }
    /**
     * @return Promise<int>
     */
    public function getSize() : Promise
    {
        return $this->queryExecutor->execute(['scard', $this->key]);
    }
    /**
     * @param string ...$keys
     *
     * @return Promise<array>
     */
    public function diff(string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sdiff', $this->key], $keys));
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     */
    public function storeDiff(string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sdiffstore', $this->key, $key], $keys));
    }
    /**
     * @param string ...$keys
     *
     * @return Promise<array>
     */
    public function intersect(string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sinter', $this->key], $keys));
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     */
    public function storeIntersection(string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sinterstore', $this->key, $key], $keys));
    }
    /**
     * @param string $member
     *
     * @return Promise<bool>
     */
    public function contains(string $member) : Promise
    {
        return $this->queryExecutor->execute(['sismember', $this->key, $member], toBool);
    }
    /**
     * @return Promise<array>
     */
    public function getAll() : Promise
    {
        return $this->queryExecutor->execute(['smembers', $this->key]);
    }
    /**
     * @param string $member
     * @param string $destination
     *
     * @return Promise<bool>
     */
    public function move(string $member, string $destination) : Promise
    {
        return $this->queryExecutor->execute(['smove', $this->key, $destination, $member], toBool);
    }
    /**
     * @return Promise<string>
     */
    public function popRandomMember() : Promise
    {
        return $this->queryExecutor->execute(['spop', $this->key]);
    }
    /**
     * @return Promise<(string | null)>
     */
    public function getRandomMember() : Promise
    {
        return $this->queryExecutor->execute(['srandmember', $this->key]);
    }
    /**
     * @param int $count
     *
     * @return Promise<string[]>
     */
    public function getRandomMembers(int $count) : Promise
    {
        return $this->queryExecutor->execute(['srandmember', $this->key, $count]);
    }
    /**
     * @param string $member
     * @param string ...$members
     *
     * @return Promise<int>
     */
    public function remove(string $member, string ...$members) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['srem', $this->key, $member], $members));
    }
    /**
     * @param string ...$keys
     *
     * @return Promise<array>
     */
    public function union(string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sunion', $this->key], $keys));
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     */
    public function storeUnion(string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sunionstore', $this->key, $key], $keys));
    }
    /**
     * @param string $pattern
     * @param int $count
     *
     * @return Iterator
     */
    public function scan(?string $pattern = null, ?int $count = null) : Iterator
    {
        return new Producer(function (callable $emit) use($pattern, $count) {
            $cursor = 0;
            do {
                $query = ['SSCAN', $this->key, $cursor];
                if ($pattern !== null) {
                    $query[] = 'MATCH';
                    $query[] = $pattern;
                }
                if ($count !== null) {
                    $query[] = 'COUNT';
                    $query[] = $count;
                }
                [$cursor, $keys] = (yield $this->queryExecutor->execute($query));
                foreach ($keys as $key) {
                    (yield $emit($key));
                }
            } while ($cursor !== '0');
        });
    }
    /**
     * @param SortOptions $sort
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/sort
     */
    public function sort(?SortOptions $sort = null) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['SORT', $this->key], ($sort ?? new SortOptions())->toQuery()));
    }
}<?php

namespace Amp\Redis;

use Amp\Emitter;
use Amp\Promise;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\delay;
final class Subscriber
{
    /** @var Config */
    private $config;
    /** @var Promise|null */
    private $connect;
    /** @var Emitter[][] */
    private $emitters = [];
    /** @var Emitter[][] */
    private $patternEmitters = [];
    /**
     *
     */
    public function __construct(Config $config)
    {
        $this->config = $config;
    }
    /**
     * @param string $channel
     *
     * @return Promise<Subscription>
     */
    public function subscribe(string $channel) : Promise
    {
        return call(function () use($channel) {
            $emitter = new Emitter();
            $this->emitters[$channel][\spl_object_hash($emitter)] = $emitter;
            try {
                /** @var RespSocket $resp */
                $resp = (yield $this->connect());
                $resp->reference();
                (yield $resp->write('subscribe', $channel));
            } catch (\Throwable $e) {
                $this->unloadEmitter($emitter, $channel);
                throw $e;
            }
            return new Subscription($emitter->iterate(), function () use($emitter, $channel) {
                $this->unloadEmitter($emitter, $channel);
            });
        });
    }
    /**
     * @param string $pattern
     *
     * @return Promise<Subscription>
     */
    public function subscribeToPattern(string $pattern) : Promise
    {
        return call(function () use($pattern) {
            $emitter = new Emitter();
            $this->patternEmitters[$pattern][\spl_object_hash($emitter)] = $emitter;
            try {
                /** @var RespSocket $resp */
                $resp = (yield $this->connect());
                $resp->reference();
                (yield $resp->write('psubscribe', $pattern));
            } catch (\Throwable $e) {
                $this->unloadPatternEmitter($emitter, $pattern);
                throw $e;
            }
            return new Subscription($emitter->iterate(), function () use($emitter, $pattern) {
                $this->unloadPatternEmitter($emitter, $pattern);
            });
        });
    }
    /**
     *
     */
    private function connect() : Promise
    {
        if ($this->connect) {
            return $this->connect;
        }
        return $this->connect = call(function () {
            try {
                /** @var RespSocket $resp */
                $resp = (yield connect($this->config));
            } catch (\Throwable $connectException) {
                (yield delay(0));
                // ensure $this->connect is already assigned above in case of immediate failure
                $this->connect = null;
                throw $connectException;
            }
            asyncCall(function () use($resp) {
                try {
                    while ([$response] = (yield $resp->read())) {
                        switch ($response[0]) {
                            case 'message':
                                $backpressure = [];
                                foreach ($this->emitters[$response[1]] as $emitter) {
                                    $backpressure[] = $emitter->emit($response[2]);
                                }
                                (yield Promise\any($backpressure));
                                break;
                            case 'pmessage':
                                $backpressure = [];
                                foreach ($this->patternEmitters[$response[1]] as $emitter) {
                                    $backpressure[] = $emitter->emit([$response[3], $response[2]]);
                                }
                                (yield Promise\any($backpressure));
                                break;
                        }
                    }
                    throw new SocketException('Socket to redis instance (' . $this->config->getConnectUri() . ') closed unexpectedly');
                } catch (\Throwable $error) {
                    $emitters = \array_merge($this->emitters, $this->patternEmitters);
                    $this->connect = null;
                    $this->emitters = [];
                    $this->patternEmitters = [];
                    foreach ($emitters as $emitterGroup) {
                        foreach ($emitterGroup as $emitter) {
                            $emitter->fail($error);
                        }
                    }
                    throw $error;
                }
            });
            return $resp;
        });
    }
    /**
     *
     */
    private function isIdle() : bool
    {
        return !$this->emitters && !$this->patternEmitters;
    }
    /**
     *
     */
    private function unloadEmitter(Emitter $emitter, string $channel) : void
    {
        $hash = \spl_object_hash($emitter);
        if (isset($this->emitters[$channel][$hash])) {
            unset($this->emitters[$channel][$hash]);
            $emitter->complete();
            if (empty($this->emitters[$channel])) {
                unset($this->emitters[$channel]);
                asyncCall(function () use($channel) {
                    try {
                        /** @var RespSocket $resp */
                        $resp = (yield $this->connect());
                        if (empty($this->emitters[$channel])) {
                            $resp->reference();
                            (yield $resp->write('unsubscribe', $channel));
                        }
                        if ($this->isIdle()) {
                            $resp->unreference();
                        }
                    } catch (RedisException $exception) {
                        // if there's an exception, the unsubscribe is implicitly successful, because the connection broke
                    }
                });
            }
        }
    }
    /**
     *
     */
    private function unloadPatternEmitter(Emitter $emitter, string $pattern) : void
    {
        $hash = \spl_object_hash($emitter);
        if (isset($this->patternEmitters[$pattern][$hash])) {
            unset($this->patternEmitters[$pattern][$hash]);
            $emitter->complete();
            if (empty($this->patternEmitters[$pattern])) {
                unset($this->patternEmitters[$pattern]);
                asyncCall(function () use($pattern) {
                    try {
                        /** @var RespSocket $resp */
                        $resp = (yield $this->connect());
                        if (empty($this->patternEmitters[$pattern])) {
                            $resp->reference();
                            (yield $resp->write('punsubscribe', $pattern));
                        }
                        if ($this->isIdle()) {
                            $resp->unreference();
                        }
                    } catch (RedisException $exception) {
                        // if there's an exception, the unsubscribe is implicitly successful, because the connection broke
                    }
                });
            }
        }
    }
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
final class RedisMap
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param string $field
     * @param string ...$fields
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/hdel
     */
    public function remove(string $field, string ...$fields) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['hdel', $this->key, $field], $fields));
    }
    /**
     * @param string $field
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/hexists
     */
    public function hasKey(string $field) : Promise
    {
        return $this->queryExecutor->execute(['hexists', $this->key, $field], toBool);
    }
    /**
     * @param string $field
     * @param int $increment
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/hincrby
     */
    public function increment(string $field, int $increment = 1) : Promise
    {
        return $this->queryExecutor->execute(['hincrby', $this->key, $field, $increment]);
    }
    /**
     * @param string $field
     * @param float $increment
     *
     * @return Promise<float>
     *
     * @link https://redis.io/commands/hincrbyfloat
     */
    public function incrementByFloat(string $field, float $increment) : Promise
    {
        return $this->queryExecutor->execute(['hincrbyfloat', $this->key, $field, $increment], toFloat);
    }
    /**
     * @return Promise<array>
     *
     * @link https://redis.io/commands/hkeys
     */
    public function getKeys() : Promise
    {
        return $this->queryExecutor->execute(['hkeys', $this->key]);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/hlen
     */
    public function getSize() : Promise
    {
        return $this->queryExecutor->execute(['hlen', $this->key]);
    }
    /**
     * @return Promise<array>
     *
     * @link https://redis.io/commands/hvals
     * @link https://redis.io/commands/hgetall
     */
    public function getAll() : Promise
    {
        return $this->queryExecutor->execute(['hgetall', $this->key], toMap);
    }
    /**
     * @param array $data
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/hmset
     */
    public function setValues(array $data) : Promise
    {
        $array = ['hmset', $this->key];
        foreach ($data as $dataKey => $value) {
            $array[] = $dataKey;
            $array[] = $value;
        }
        return $this->queryExecutor->execute($array, toNull);
    }
    /**
     * @param string $field
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/hget
     */
    public function getValue(string $field) : Promise
    {
        return $this->queryExecutor->execute(['hget', $this->key, $field]);
    }
    /**
     * @param string $field
     * @param string ...$fields
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/hmget
     */
    public function getValues(string $field, string ...$fields) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['hmget', $this->key, $field], $fields));
    }
    /**
     * @param string $field
     * @param string $value
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/hset
     */
    public function setValue(string $field, string $value) : Promise
    {
        return $this->queryExecutor->execute(['hset', $this->key, $field, $value], toBool);
    }
    /**
     * @param string $field
     * @param string $value
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/hsetnx
     */
    public function setValueWithoutOverwrite(string $field, string $value) : Promise
    {
        return $this->queryExecutor->execute(['hsetnx', $this->key, $field, $value], toBool);
    }
    /**
     * @param string $field
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/hstrlen
     */
    public function getLength(string $field) : Promise
    {
        return $this->queryExecutor->execute(['hstrlen', $this->key, $field]);
    }
    /**
     * @param (string | null) $pattern
     * @param (int | null) $count
     *
     * @return Iterator<string>
     *
     * @link https://redis.io/commands/hscan
     */
    public function scan(?string $pattern = null, ?int $count = null) : Iterator
    {
        return new Producer(function (callable $emit) use($pattern, $count) {
            $cursor = 0;
            do {
                $query = ['HSCAN', $this->key, $cursor];
                if ($pattern !== null) {
                    $query[] = 'MATCH';
                    $query[] = $pattern;
                }
                if ($count !== null) {
                    $query[] = 'COUNT';
                    $query[] = $count;
                }
                [$cursor, $keys] = (yield $this->queryExecutor->execute($query));
                $count = \count($keys);
                \assert($count % 2 === 0);
                for ($i = 0; $i < $count; $i += 2) {
                    (yield $emit([$keys[$i], $keys[$i + 1]]));
                }
            } while ($cursor !== '0');
        });
    }
}<?php

namespace Amp\Redis;

use function League\Uri\parse;
final class Config
{
    public const DEFAULT_HOST = 'localhost';
    public const DEFAULT_PORT = '6379';
    /**
     * @param string $uri
     *
     * @return self
     *
     * @throws RedisException
     */
    public static function fromUri(string $uri) : self
    {
        if (\stripos($uri, 'tcp://') !== 0 && \stripos($uri, 'unix://') !== 0 && \stripos($uri, 'redis://') !== 0) {
            throw new RedisException('Invalid redis configuration URI, must start with tcp://, unix:// or redis://');
        }
        return new self($uri);
    }
    /** @var string */
    private $uri;
    /** @var string */
    private $password = '';
    /** @var int */
    private $database = 0;
    /** @var int */
    private $timeout = 5000;
    /**
     * @param string $uri
     *
     * @throws RedisException
     */
    private function __construct(string $uri)
    {
        $this->applyUri($uri);
    }
    /**
     *
     */
    public function getConnectUri() : string
    {
        return $this->uri;
    }
    /**
     *
     */
    public function getTimeout() : int
    {
        return $this->timeout;
    }
    /**
     *
     */
    public function getPassword() : string
    {
        return $this->password;
    }
    /**
     *
     */
    public function hasPassword() : bool
    {
        return $this->password !== '';
    }
    /**
     *
     */
    public function getDatabase() : int
    {
        return $this->database;
    }
    /**
     *
     */
    public function withTimeout(int $timeout) : self
    {
        $clone = clone $this;
        $clone->timeout = $timeout;
        return $clone;
    }
    /**
     *
     */
    public function withPassword(string $password) : self
    {
        $clone = clone $this;
        $clone->password = $password;
        return $clone;
    }
    /**
     *
     */
    public function withDatabase(int $database) : self
    {
        $clone = clone $this;
        $clone->database = $database;
        return $clone;
    }
    /**
    * When using the "redis" schemes the URI is parsed according to the rules defined by the provisional registration
    documents approved by IANA. If the URI has a password in its "user-information" part or a database number in the
    "path" part these values override the values of "password" / "database" if they are present in the "query" part.
    *
    * @link http://www.iana.org/assignments/uri-schemes/prov/redis
    *
    * @param string $uri URI string.
    *
    * @throws RedisException
    */
    private function applyUri(string $uri) : void
    {
        if ($uri === 'redis://') {
            $uri = 'redis://' . self::DEFAULT_HOST . ':' . self::DEFAULT_PORT;
        }
        try {
            $parsedUri = parse($uri);
        } catch (\Exception $exception) {
            throw new RedisException('Invalid redis configuration URI: ' . $uri);
        }
        \parse_str($parsedUri['query'] ?? '', $query);
        switch (\strtolower($parsedUri['scheme'])) {
            case 'tcp':
                $this->uri = 'tcp://' . \strtolower($parsedUri['host']) . ':' . (int) $parsedUri['port'];
                $this->database = (int) ($query['database'] ?? $query['db'] ?? 0);
                $this->password = $query['password'] ?? $query['pass'] ?? '';
                break;
            case 'unix':
                $this->uri = 'unix://' . $parsedUri['path'];
                $this->database = (int) ($query['database'] ?? $query['db'] ?? 0);
                $this->password = $query['password'] ?? $query['pass'] ?? '';
                break;
            case 'redis':
                $host = \strtolower($parsedUri['host'] ?? self::DEFAULT_HOST);
                $port = (int) ($parsedUri['port'] ?? self::DEFAULT_PORT);
                if ($host === '') {
                    $host = self::DEFAULT_HOST;
                }
                if ($port === 0) {
                    $port = self::DEFAULT_PORT;
                }
                $this->uri = 'tcp://' . $host . ':' . $port;
                if (\ltrim($parsedUri['path'], '/') !== '') {
                    $this->database = (int) \ltrim($parsedUri['path'], '/');
                } else {
                    $this->database = (int) ($query['db'] ?? 0);
                }
                if (isset($parsedUri['pass']) && $parsedUri['pass'] !== '') {
                    $this->password = $parsedUri['pass'];
                } else {
                    $this->password = $query['password'] ?? '';
                }
                break;
        }
        $this->timeout = (int) ($query['timeout'] ?? $this->timeout);
    }
}<?php

namespace Amp\Redis;

use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Promise;
use Amp\Socket;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\delay;
final class RemoteExecutor implements QueryExecutor
{
    /** @var Deferred[] */
    private $queue = [];
    /** @var Config */
    private $config;
    /** @var int */
    private $database;
    /** @var Promise|null */
    private $connect;
    /** @var Socket\Connector */
    private $connector;
    /**
     *
     */
    public function __construct(Config $config, ?Socket\Connector $connector = null)
    {
        $this->config = $config;
        $this->database = $config->getDatabase();
        $this->connector = $connector ?? Socket\connector();
    }
    /**
     * @param string[] $args
     * @param callable $transform
     *
     * @return Promise
     */
    public function execute(array $args, callable $transform = null) : Promise
    {
        return call(function () use($args, $transform) {
            $command = \strtolower($args[0] ?? '');
            $connectPromise = $this->connect();
            if ($command === 'quit') {
                $this->connect = null;
            }
            /** @var RespSocket $resp */
            $resp = (yield $connectPromise);
            $response = (yield $this->enqueue($resp, ...$args));
            if ($command === 'select') {
                $this->database = (int) $args[1];
            }
            return $transform ? $transform($response) : $response;
        });
    }
    /**
     *
     */
    private function enqueue(RespSocket $resp, string ...$args) : Promise
    {
        return call(function () use($resp, $args) {
            $deferred = new Deferred();
            $this->queue[] = $deferred;
            $resp->reference();
            try {
                (yield $resp->write(...$args));
            } catch (Socket\SocketException|StreamException $exception) {
                throw new SocketException($exception);
            }
            return $deferred->promise();
        });
    }
    /**
     *
     */
    private function connect() : Promise
    {
        if ($this->connect) {
            return $this->connect;
        }
        return $this->connect = call(function () {
            try {
                /** @var RespSocket $resp */
                $resp = (yield connect($this->config->withDatabase($this->database), $this->connector));
            } catch (\Throwable $connectException) {
                (yield delay(0));
                // ensure $this->connect is already assigned above in case of immediate failure
                $this->connect = null;
                throw $connectException;
            }
            asyncCall(function () use($resp) {
                try {
                    while ([$response] = (yield $resp->read())) {
                        $deferred = \array_shift($this->queue);
                        if (!$this->queue) {
                            $resp->unreference();
                        }
                        if ($response instanceof \Throwable) {
                            $deferred->fail($response);
                        } else {
                            $deferred->resolve($response);
                        }
                    }
                    throw new SocketException('Socket to redis instance (' . $this->config->getConnectUri() . ') closed unexpectedly');
                } catch (\Throwable $error) {
                    $queue = $this->queue;
                    $this->queue = [];
                    $this->connect = null;
                    while ($queue) {
                        $deferred = \array_shift($queue);
                        $deferred->fail($error);
                    }
                }
            });
            return $resp;
        });
    }
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
final class RedisSortedSet
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param array $data
     *
     * @return Promise<int>
     */
    public function add(array $data) : Promise
    {
        $payload = ['zadd', $this->key];
        foreach ($data as $member => $score) {
            $payload[] = $score;
            $payload[] = $member;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @return Promise<int>
     */
    public function getSize() : Promise
    {
        return $this->queryExecutor->execute(['zcard', $this->key]);
    }
    /**
     * @param int $min
     * @param int $max
     *
     * @return Promise<int>
     */
    public function count(int $min, int $max) : Promise
    {
        return $this->queryExecutor->execute(['zcount', $this->key, $min, $max]);
    }
    /**
     * @param string $member
     * @param float $increment
     *
     * @return Promise<float>
     */
    public function increment(string $member, float $increment = 1) : Promise
    {
        return $this->queryExecutor->execute(['zincrby', $this->key, $increment, $member], toFloat);
    }
    /**
     * @param string[] $keys
     * @param string $aggregate
     *
     * @return Promise<int>
     */
    public function storeIntersection(array $keys, string $aggregate = 'sum') : Promise
    {
        $payload = ['zinterstore', $this->key, \count($keys)];
        $weights = [];
        if (\count(\array_filter(\array_keys($keys), 'is_string'))) {
            foreach ($keys as $key => $weight) {
                $payload[] = $key;
                $weights[] = $weight;
            }
        } else {
            foreach ($keys as $key) {
                $payload[] = $key;
            }
        }
        if (\count($weights) > 0) {
            $payload[] = 'WEIGHTS';
            foreach ($weights as $weight) {
                $payload[] = $weight;
            }
        }
        if (\strtolower($aggregate) !== 'sum') {
            $payload[] = 'AGGREGATE';
            $payload[] = $aggregate;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @param string $min
     * @param string $max
     *
     * @return Promise<int>
     */
    public function countLexicographically(string $min, string $max) : Promise
    {
        return $this->queryExecutor->execute(['zlexcount', $this->key, $min, $max]);
    }
    /**
     * @param string $member
     *
     * @return Promise<(int | null)>
     */
    public function getRank(string $member) : Promise
    {
        return $this->queryExecutor->execute(['zrank', $this->key, $member]);
    }
    /**
     * @param string $member
     * @param string ...$members
     *
     * @return Promise<int>
     */
    public function remove(string $member, string ...$members) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['zrem', $this->key, $member], $members));
    }
    /**
     * @param string $min
     * @param string $max
     *
     * @return Promise<int>
     */
    public function removeLexicographicRange(string $min, string $max) : Promise
    {
        return $this->queryExecutor->execute(['zremrangebylex', $this->key, $min, $max]);
    }
    /**
     * @param int $start
     * @param int $stop
     *
     * @return Promise<int>
     */
    public function removeRankRange(int $start, int $stop) : Promise
    {
        return $this->queryExecutor->execute(['zremrangebyrank', $this->key, $start, $stop]);
    }
    /**
     * @param float $min
     * @param float $max
     *
     * @return Promise<int>
     */
    public function removeScoreRange(float $min, float $max) : Promise
    {
        return $this->queryExecutor->execute(['zremrangebyscore', $this->key, $min, $max]);
    }
    /**
     * @param string $member
     *
     * @return Promise<(int | null)>
     */
    public function getReversedRank(string $member) : Promise
    {
        return $this->queryExecutor->execute(['zrevrank', $this->key, $member]);
    }
    /**
     * @param (string | null) $pattern
     * @param (int | null) $count
     *
     * @return Iterator<string>
     */
    public function scan(?string $pattern = null, ?int $count = null) : Iterator
    {
        return new Producer(function (callable $emit) use($pattern, $count) {
            $cursor = 0;
            do {
                $query = ['ZSCAN', $this->key, $cursor];
                if ($pattern !== null) {
                    $query[] = 'MATCH';
                    $query[] = $pattern;
                }
                if ($count !== null) {
                    $query[] = 'COUNT';
                    $query[] = $count;
                }
                [$cursor, $keys] = (yield $this->queryExecutor->execute($query));
                $count = \count($keys);
                \assert($count % 2 === 0);
                for ($i = 0; $i < $count; $i += 2) {
                    (yield $emit([$keys[$i], (float) $keys[$i + 1]]));
                }
            } while ($cursor !== '0');
        });
    }
    /**
     * @param string $member
     *
     * @return Promise<(float | null)>
     */
    public function getScore(string $member) : Promise
    {
        return $this->queryExecutor->execute(['zscore', $this->key, $member], toFloat);
    }
    /**
     * @param string[] $keys
     * @param string $aggregate
     *
     * @return Promise<int>
     */
    public function storeUnion(array $keys, string $aggregate = 'sum') : Promise
    {
        $payload = ['zunionstore', $this->key, \count($keys)];
        $weights = [];
        if (\count(\array_filter(\array_keys($keys), 'is_string'))) {
            foreach ($keys as $key => $weight) {
                $payload[] = $key;
                $weights[] = $weight;
            }
        } else {
            foreach ($keys as $key) {
                $payload[] = $key;
            }
        }
        if (\count($weights) > 0) {
            $payload[] = 'WEIGHTS';
            foreach ($weights as $weight) {
                $payload[] = $weight;
            }
        }
        if (\strtolower($aggregate) !== 'sum') {
            $payload[] = 'AGGREGATE';
            $payload[] = $aggregate;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @param SortOptions $sort
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/sort
     */
    public function sort(?SortOptions $sort = null) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['SORT', $this->key], ($sort ?? new SortOptions())->toQuery()));
    }
}<?php

namespace Amp\Redis;

interface QueryExecutorFactory
{
    /**
     * @return QueryExecutor New QueryExecutor instance.
     */
    public function createQueryExecutor() : QueryExecutor;
}<?php

namespace Amp\Redis;

final class SortOptions
{
    /** @var string|null */
    private $pattern;
    /** @var int|null */
    private $offset;
    /** @var int|null */
    private $count;
    /** @var bool */
    private $ascending = true;
    /** @var bool */
    private $lexicographically = false;
    /**
     *
     */
    public function hasPattern() : bool
    {
        return $this->pattern !== null;
    }
    /**
     *
     */
    public function getPattern() : ?string
    {
        return $this->pattern;
    }
    /**
     *
     */
    public function withPattern(string $pattern) : self
    {
        $clone = clone $this;
        $clone->pattern = $pattern;
        return $clone;
    }
    /**
     *
     */
    public function withoutPattern() : self
    {
        $clone = clone $this;
        $clone->pattern = null;
        return $clone;
    }
    /**
     *
     */
    public function getOffset() : ?int
    {
        return $this->offset;
    }
    /**
     *
     */
    public function getCount() : ?int
    {
        return $this->count;
    }
    /**
     *
     */
    public function hasLimit() : bool
    {
        return $this->offset !== null;
    }
    /**
     *
     */
    public function withLimit(int $offset, int $count) : self
    {
        $clone = clone $this;
        $clone->offset = $offset;
        $clone->count = $count;
        return $clone;
    }
    /**
     *
     */
    public function withoutLimit() : self
    {
        $clone = clone $this;
        $clone->offset = null;
        $clone->count = null;
        return $clone;
    }
    /**
     *
     */
    public function isAscending() : bool
    {
        return $this->ascending;
    }
    /**
     *
     */
    public function isDescending() : bool
    {
        return !$this->ascending;
    }
    /**
     *
     */
    public function withAscendingOrder() : self
    {
        $clone = clone $this;
        $clone->ascending = true;
        return $clone;
    }
    /**
     *
     */
    public function withDescendingOrder() : self
    {
        $clone = clone $this;
        $clone->ascending = false;
        return $clone;
    }
    /**
     *
     */
    public function isLexicographicSorting() : bool
    {
        return $this->lexicographically;
    }
    /**
     *
     */
    public function withLexicographicSorting() : self
    {
        $clone = clone $this;
        $clone->lexicographically = true;
        return $clone;
    }
    /**
     *
     */
    public function withNumericSorting() : self
    {
        $clone = clone $this;
        $clone->lexicographically = false;
        return $clone;
    }
    /**
     *
     */
    public function toQuery() : array
    {
        $payload = [];
        if ($this->hasPattern()) {
            $payload[] = 'BY';
            $payload[] = $this->getPattern();
        }
        if ($this->hasLimit()) {
            $payload[] = 'LIMIT';
            $payload[] = $this->getOffset();
            $payload[] = $this->getCount();
        }
        if ($this->isDescending()) {
            $payload[] = 'DESC';
        }
        if ($this->isLexicographicSorting()) {
            $payload[] = 'ALPHA';
        }
        return $payload;
    }
}<?php

namespace Amp\Redis;

use Amp\Promise;
interface QueryExecutor
{
    /**
     * @param string[] $query
     * @param (callable | null) $responseTransform
     *
     * @return Promise
     *
     * @see toBool()
     * @see toNull()
     * @see toFloat()
     * @see toMap()
     */
    public function execute(array $query, callable $responseTransform = null) : Promise;
}<?php

namespace Amp\Redis;

use Amp\Promise;
use Amp\Socket;
use Amp\Socket\ConnectContext;
use function Amp\call;
const toFloat = __NAMESPACE__ . '\\toFloat';
const toBool = __NAMESPACE__ . '\\toBool';
const toNull = __NAMESPACE__ . '\\toNull';
const toMap = __NAMESPACE__ . '\\toMap';
/**
 *
 */
function toFloat($response) : ?float
{
    if ($response === null) {
        return null;
    }
    return (float) $response;
}
/**
 *
 */
function toBool($response) : ?bool
{
    if ($response === null) {
        return null;
    }
    return (bool) $response;
}
/**
 *
 */
function toMap(?array $values) : ?array
{
    if ($values === null) {
        return null;
    }
    $size = \count($values);
    $result = [];
    for ($i = 0; $i < $size; $i += 2) {
        $result[$values[$i]] = $values[$i + 1];
    }
    return $result;
}
/**
 *
 */
function toNull($response) : void
{
    // nothing to do
}
/**
 * @param Config $config
 * @param (Socket\Connector | null) $connector
 *
 * @return Promise<RespSocket>
 *
 * @throws RedisException
 */
function connect(Config $config, ?Socket\Connector $connector = null) : Promise
{
    return call(static function () use($config, $connector) {
        try {
            $connectContext = (new ConnectContext())->withConnectTimeout($config->getTimeout());
            $resp = new RespSocket((yield ($connector ?? Socket\connector())->connect($config->getConnectUri(), $connectContext)));
        } catch (Socket\SocketException $e) {
            throw new SocketException('Failed to connect to redis instance (' . $config->getConnectUri() . ')', 0, $e);
        }
        $promises = [];
        if ($config->hasPassword()) {
            // pipeline, don't await
            $promises[] = $resp->write('AUTH', $config->getPassword());
        }
        if ($config->getDatabase() !== 0) {
            // pipeline, don't await
            $promises[] = $resp->write('SELECT', $config->getDatabase());
        }
        foreach ($promises as $promise) {
            (yield $promise);
            if ([$response] = (yield $resp->read())) {
                if ($response instanceof \Throwable) {
                    throw $response;
                }
            } else {
                throw new RedisException('Failed to connect to redis instance (' . $config->getConnectUri() . ')');
            }
        }
        return $resp;
    });
}<?php

namespace Amp\Redis;

use Amp\Socket;
final class RemoteExecutorFactory implements QueryExecutorFactory
{
    private $config;
    private $connector;
    /**
     *
     */
    public function __construct(Config $config, ?Socket\Connector $connector = null)
    {
        $this->config = $config;
        $this->connector = $connector ?? Socket\connector();
    }
    /**
     *
     */
    public function createQueryExecutor() : QueryExecutor
    {
        return new RemoteExecutor($this->config, $this->connector);
    }
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Promise;
final class RedisList
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param string $index
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/lindex
     */
    public function get(string $index) : Promise
    {
        return $this->queryExecutor->execute(['lindex', $this->key, $index]);
    }
    /**
     * @param string $pivot
     * @param string $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/linsert
     */
    public function insertBefore(string $pivot, string $value) : Promise
    {
        return $this->queryExecutor->execute(['linsert', $this->key, 'BEFORE', $pivot, $value]);
    }
    /**
     * @param string $pivot
     * @param string $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/linsert
     */
    public function insertAfter(string $pivot, string $value) : Promise
    {
        return $this->queryExecutor->execute(['linsert', $this->key, 'AFTER', $pivot, $value]);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/llen
     */
    public function getSize() : Promise
    {
        return $this->queryExecutor->execute(['llen', $this->key]);
    }
    /**
     * @param string $value
     * @param string ...$values
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/lpush
     */
    public function pushHead(string $value, string ...$values) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['lpush', $this->key, $value], $values));
    }
    /**
     * @param string $value
     * @param string ...$values
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/lpushx
     */
    public function pushHeadIfExists(string $value, string ...$values) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['lpushx', $this->key, $value], $values));
    }
    /**
     * @param string $value
     * @param string ...$values
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/rpush
     */
    public function pushTail(string $value, string ...$values) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['rpush', $this->key, $value], $values));
    }
    /**
     * @param string $value
     * @param string ...$values
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/rpushx
     */
    public function pushTailIfExists(string $value, string ...$values) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['rpushx', $this->key, $value], $values));
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/lpop
     */
    public function popHead() : Promise
    {
        return $this->queryExecutor->execute(['lpop', $this->key]);
    }
    /**
     * @param int $timeout
     *
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/blpop
     */
    public function popHeadBlocking(int $timeout = 0) : Promise
    {
        return $this->queryExecutor->execute(['blpop', $this->key, $timeout], static function ($response) {
            return $response[1] ?? null;
        });
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/rpop
     */
    public function popTail() : Promise
    {
        return $this->queryExecutor->execute(['rpop', $this->key]);
    }
    /**
     * @param int $timeout
     *
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/brpop
     */
    public function popTailBlocking(int $timeout = 0) : Promise
    {
        return $this->queryExecutor->execute(['brpop', $this->key, $timeout], static function ($response) {
            return $response[1] ?? null;
        });
    }
    /**
     * @param string $destination
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/rpoplpush
     */
    public function popTailPushHead(string $destination) : Promise
    {
        return $this->queryExecutor->execute(['rpoplpush', $this->key, $destination]);
    }
    /**
     * @param string $destination
     * @param int $timeout
     *
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/brpoplpush
     */
    public function popTailPushHeadBlocking(string $destination, int $timeout = 0) : Promise
    {
        return $this->queryExecutor->execute(['brpoplpush', $this->key, $destination, $timeout]);
    }
    /**
     * @param int $start
     * @param int $end
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/lrange
     */
    public function getRange(int $start = 0, int $end = -1) : Promise
    {
        return $this->queryExecutor->execute(['lrange', $this->key, $start, $end]);
    }
    /**
     * @param string $value
     * @param int $count
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/lrem
     */
    public function remove(string $value, int $count = 0) : Promise
    {
        return $this->queryExecutor->execute(['lrem', $this->key, $count, $value]);
    }
    /**
     * @param int $index
     * @param string $value
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/lset
     */
    public function set(int $index, string $value) : Promise
    {
        return $this->queryExecutor->execute(['lset', $this->key, $index, $value], toNull);
    }
    /**
     * @param int $start
     * @param int $stop
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/ltrim
     */
    public function trim(int $start = 0, int $stop = -1) : Promise
    {
        return $this->queryExecutor->execute(['ltrim', $this->key, $start, $stop], toNull);
    }
    /**
     * @param SortOptions $sort
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/sort
     */
    public function sort(?SortOptions $sort = null) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['SORT', $this->key], ($sort ?? new SortOptions())->toQuery()));
    }
}<?php

namespace Amp\Redis;

use Amp\ByteStream\ClosedException;
use Amp\Emitter;
use Amp\Iterator;
use Amp\Promise;
use Amp\Socket\Socket;
use Amp\Success;
use function Amp\asyncCall;
use function Amp\call;
final class RespSocket
{
    /** @var RespParser */
    private $parser;
    /** @var Socket */
    private $socket;
    /** @var Iterator */
    private $iterator;
    /** @var Promise */
    private $backpressure;
    /** @var \Throwable */
    private $error;
    /**
     *
     */
    public function __construct(Socket $socket)
    {
        $emitter = new Emitter();
        $backpressure =& $this->backpressure;
        $backpressure = new Success();
        $this->socket = $socket;
        $this->iterator = $emitter->iterate();
        $this->parser = new RespParser(static function ($message) use($emitter, &$backpressure) {
            $backpressure = $emitter->emit($message);
        });
        asyncCall(function () use($socket, $emitter) {
            try {
                while (null !== ($chunk = (yield $socket->read()))) {
                    $this->parser->append($chunk);
                    (yield $this->backpressure);
                }
                $emitter->fail(new ClosedException('Socket closed'));
            } catch (\Throwable $e) {
                if ($this->error === null) {
                    $this->error = $e;
                }
                $emitter->fail($e);
            }
            $this->close();
        });
    }
    /**
     *
     */
    public function read() : Promise
    {
        return call(function () {
            if ((yield $this->iterator->advance())) {
                return [$this->iterator->getCurrent()];
            }
            return null;
        });
    }
    /**
     *
     */
    public function write(string ...$args) : Promise
    {
        return call(function () use($args) {
            if ($this->error) {
                throw $this->error;
            }
            if ($this->socket === null) {
                throw new ClosedException('Redis connection already closed');
            }
            $payload = '';
            foreach ($args as $arg) {
                $payload .= '$' . \strlen($arg) . "\r\n{$arg}\r\n";
            }
            $payload = '*' . \count($args) . "\r\n{$payload}";
            (yield $this->socket->write($payload));
        });
    }
    /**
     *
     */
    public function reference() : void
    {
        if ($this->socket) {
            $this->socket->reference();
        }
    }
    /**
     *
     */
    public function unreference() : void
    {
        if ($this->socket) {
            $this->socket->unreference();
        }
    }
    /**
     *
     */
    public function close() : void
    {
        if ($this->parser) {
            $this->parser->reset();
        }
        if ($this->socket) {
            $this->socket->close();
            $this->socket = null;
        }
    }
    /**
     *
     */
    public function isClosed() : bool
    {
        return $this->socket === null;
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
}<?php

namespace Amp\Redis;

use Amp\Cache\Cache as CacheInterface;
use Amp\Cache\CacheException;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class Cache implements CacheInterface
{
    /** @var Redis */
    private $redis;
    /**
     * @param Redis $redis
     */
    public function __construct(Redis $redis)
    {
        $this->redis = $redis;
    }
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        return call(function () use($key) {
            try {
                return (yield $this->redis->get($key));
            } catch (RedisException $e) {
                throw new CacheException("Fetching '{$key}' from cache failed", 0, $e);
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        if ($ttl !== null && $ttl < 0) {
            throw new \Error('Invalid TTL: ' . $ttl);
        }
        if ($ttl === 0) {
            return new Success();
            // expires immediately
        }
        return call(function () use($key, $value, $ttl) {
            try {
                $options = new SetOptions();
                if ($ttl !== null) {
                    $options = $options->withTtl($ttl);
                }
                return (yield $this->redis->set($key, $value, $options));
            } catch (RedisException $e) {
                throw new CacheException("Storing '{$key}' to cache failed", 0, $e);
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        return call(function () use($key) {
            try {
                return (yield $this->redis->delete($key));
            } catch (RedisException $e) {
                throw new CacheException("Deleting '{$key}' from cache failed", 0, $e);
            }
        });
    }
}<?php

namespace Amp\Redis;

final class SetOptions
{
    /** @var int|null */
    private $ttl;
    /** @var string|null */
    private $ttlUnit;
    /** @var string|null */
    private $existenceFlag;
    /**
     *
     */
    public function withTtl(int $seconds) : self
    {
        $clone = clone $this;
        $clone->ttl = $seconds;
        $clone->ttlUnit = 'EX';
        return $clone;
    }
    /**
     *
     */
    public function withTtlInMillis(int $millis) : self
    {
        $clone = clone $this;
        $clone->ttl = $millis;
        $clone->ttlUnit = 'PX';
        return $clone;
    }
    /**
     *
     */
    public function withoutOverwrite() : self
    {
        $clone = clone $this;
        $clone->existenceFlag = 'NX';
        return $clone;
    }
    /**
     *
     */
    public function withoutCreation() : self
    {
        $clone = clone $this;
        $clone->existenceFlag = 'XX';
        return $clone;
    }
    /**
     *
     */
    public function toQuery() : array
    {
        $query = [];
        if ($this->ttl !== null) {
            $query[] = $this->ttlUnit;
            $query[] = $this->ttl;
        }
        if ($this->existenceFlag !== null) {
            $query[] = $this->existenceFlag;
        }
        return $query;
    }
}{
    "name": "amphp/redis",
    "description": "A non-blocking Redis client for Amp.",
    "keywords": [
        "amp",
        "amphp",
        "async",
        "client",
        "redis"
    ],
    "license": "MIT",
    "homepage": "https://github.com/amphp/redis",
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "support": {
        "issues": "https://github.com/amphp/redis/issues"
    },
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2.2.1",
        "amphp/cache": "^1.2.1",
        "amphp/socket": "^1",
        "league/uri-parser": "^1.4",
        "amphp/sync": "^1.1"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1.1.2",
        "phpunit/phpunit": "^7 | ^8",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Redis\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Redis\\": "test",
            "Amp\\Cache\\Test\\": "vendor/amphp/cache/test"
        }
    }
}
{
    "name": "amphp/windows-registry",
    "description": "Windows Registry Reader.",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "Amp\\WindowsRegistry\\": "lib"
        }
    },
    "require": {
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.4",
        "amphp/process": "^1"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "config": {
        "platform": {
            "php": "7.0.0"
        }
    }
}
<?php

namespace Amp\WindowsRegistry;

use Amp\ByteStream;
use Amp\Process\Process;
use Amp\Promise;
use function Amp\call;
class WindowsRegistry
{
    /**
     *
     */
    public function read(string $key) : Promise
    {
        return call(function () use($key) {
            $key = \strtr($key, '/', "\\");
            $parts = \explode("\\", $key);
            $value = \array_pop($parts);
            $key = \implode("\\", $parts);
            $lines = (yield $this->query($key));
            $lines = \array_filter($lines, function ($line) {
                return '' !== $line && $line[0] === ' ';
            });
            $values = \array_map(function ($line) {
                return \preg_split("(\\s+)", \ltrim($line), 3);
            }, $lines);
            $foundValue = null;
            foreach ($values as $v) {
                if ($v[0] === $value) {
                    if (\count($v) >= 3) {
                        return $v[2];
                    }
                    $foundValue = $v;
                }
            }
            if ($foundValue) {
                throw new KeyNotFoundException("Windows registry key '{$key}\\{$value}' was found, but could not be read correctly, got " . \var_export($foundValue, true));
            }
            throw new KeyNotFoundException("Windows registry key '{$key}\\{$value}' not found.");
        });
    }
    /**
     *
     */
    public function listKeys(string $key) : Promise
    {
        return call(function () use($key) {
            $lines = (yield $this->query($key));
            $lines = \array_filter($lines, function ($line) {
                return '' !== $line && $line[0] !== ' ';
            });
            return $lines;
        });
    }
    /**
     *
     */
    private function query(string $key) : Promise
    {
        return call(function () use($key) {
            if (0 !== \stripos(\PHP_OS, 'WIN')) {
                throw new \Error('Not running on Windows.');
            }
            $key = \strtr($key, '/', "\\");
            $cmd = \sprintf('reg query %s', \escapeshellarg($key));
            $process = new Process($cmd);
            (yield $process->start());
            $stdout = (yield ByteStream\buffer($process->getStdout()));
            $code = (yield $process->join());
            if ($code !== 0) {
                throw new KeyNotFoundException("Windows registry key '{$key}' not found.");
            }
            return \explode("\n", \str_replace("\r", '', $stdout));
        });
    }
}<?php

namespace Amp\WindowsRegistry;

class KeyNotFoundException extends \Exception
{
}{
    "name": "amphp/amp",
    "homepage": "http://amphp.org/amp",
    "description": "A non-blocking concurrency framework for PHP applications.",
    "keywords": [
        "async",
        "asynchronous",
        "concurrency",
        "promise",
        "awaitable",
        "future",
        "non-blocking",
        "event",
        "event-loop"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "require-dev": {
        "ext-json": "*",
        "amphp/phpunit-util": "^1",
        "amphp/php-cs-fixer-config": "dev-master",
        "react/promise": "^2",
        "phpunit/phpunit": "^7 | ^8 | ^9",
        "psalm/phar": "^3.11@dev",
        "jetbrains/phpstorm-stubs": "^2019.3"
    },
    "autoload": {
        "psr-4": {
            "Amp\\": "lib"
        },
        "files": [
            "lib/functions.php",
            "lib/Internal/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Test\\": "test"
        }
    },
    "support": {
        "issues": "https://github.com/amphp/amp/issues",
        "irc": "irc://irc.freenode.org/amphp"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.x-dev"
        }
    },
    "scripts": {
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit",
        "code-style": "@php ./vendor/bin/php-cs-fixer fix"
    }
}
<?php

namespace Amp;

/**
 * Emitter is a container for an iterator that can emit values using the emit() method and completed using the
 * complete() and fail() methods of this object. The contained iterator may be accessed using the iterate()
 * method. This object should not be part of a public API, but used internally to create and emit values to an
 * iterator.
 *
 * @template TValue
 */
final class Emitter
{
    /** @var Iterator<TValue> Has public emit, complete, and fail methods. */
    private $emitter;
    /** @var Iterator<TValue> Hides producer methods. */
    private $iterator;
    /**
     *
     */
    public function __construct()
    {
        $this->emitter = new class implements Iterator
        {
            use Internal\Producer {
                emit as public;
                complete as public;
                fail as public;
            }
        };
        $this->iterator = new Internal\PrivateIterator($this->emitter);
    }
    /**
     * @return Iterator
     * @psalm-return Iterator<TValue>
     */
    public function iterate() : Iterator
    {
        return $this->iterator;
    }
    /**
     * Emits a value to the iterator.
     *
     * @param mixed $value
     *
     * @psalm-param TValue $value
     *
     * @return Promise
     * @psalm-return Promise<null>
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public function emit($value) : Promise
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        return $this->emitter->emit($value);
    }
    /**
     * Completes the iterator.
     *
     * @return void
     */
    public function complete()
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->emitter->complete();
    }
    /**
     * Fails the iterator with the given reason.
     *
     * @param \Throwable $reason
     *
     * @return void
     */
    public function fail(\Throwable $reason)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->emitter->fail($reason);
    }
}<?php

namespace Amp;

/**
 * A NullCancellationToken can be used to avoid conditionals to check whether a token has been provided.
 *
 * Instead of writing
 *
 * ```php
 * if ($token) {
 *     $token->throwIfRequested();
 * }
 * ```
 *
 * potentially multiple times, it allows writing
 *
 * ```php
 * $token = $token ?? new NullCancellationToken;
 *
 * // ...
 *
 * $token->throwIfRequested();
 * ```
 *
 * instead.
 */
final class NullCancellationToken implements CancellationToken
{
    /**
     * @inheritdoc
     */
    public function subscribe(callable $callback) : string
    {
        return "null-token";
    }
    /**
     * @inheritdoc
     */
    public function unsubscribe(string $id)
    {
        // nothing to do
    }
    /**
     * @inheritdoc
     */
    public function isRequested() : bool
    {
        return false;
    }
    /**
     * @inheritdoc
     */
    public function throwIfRequested()
    {
        // nothing to do
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a successful promise using the given value (which can be any value except an object implementing
 * `Amp\Promise` or `React\Promise\PromiseInterface`).
 *
 * @template-covariant TValue
 * @template-implements Promise<TValue>
 */
final class Success implements Promise
{
    /** @var mixed */
    private $value;
    /**
     * @param mixed $value Anything other than a Promise object.
     *
     * @psalm-param TValue $value
     *
     * @throws \Error If a promise is given as the value.
     */
    public function __construct($value = null)
    {
        if ($value instanceof Promise || $value instanceof ReactPromise) {
            throw new \Error("Cannot use a promise as success value");
        }
        $this->value = $value;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        try {
            $result = $onResolved(null, $this->value);
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
}<?php

namespace Amp;

use function Amp\Internal\formatStacktrace;
/**
 * A TimeoutCancellationToken automatically requests cancellation after the timeout has elapsed.
 */
final class TimeoutCancellationToken implements CancellationToken
{
    /** @var string */
    private $watcher;
    /** @var CancellationToken */
    private $token;
    /**
     * @param int $timeout Milliseconds until cancellation is requested.
     * @param string $message Message for TimeoutException. Default is "Operation timed out".
     */
    public function __construct(int $timeout, string $message = "Operation timed out")
    {
        $source = new CancellationTokenSource();
        $this->token = $source->getToken();
        $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
        $this->watcher = Loop::delay($timeout, static function () use($source, $message, $trace) {
            $trace = formatStacktrace($trace);
            $source->cancel(new TimeoutException("{$message}\r\nTimeoutCancellationToken was created here:\r\n{$trace}"));
        });
        Loop::unreference($this->watcher);
    }
    /**
     * Cancels the delay watcher.
     */
    public function __destruct()
    {
        Loop::cancel($this->watcher);
    }
    /**
     * {@inheritdoc}
     */
    public function subscribe(callable $callback) : string
    {
        return $this->token->subscribe($callback);
    }
    /**
     * {@inheritdoc}
     */
    public function unsubscribe(string $id)
    {
        $this->token->unsubscribe($id);
    }
    /**
     * {@inheritdoc}
     */
    public function isRequested() : bool
    {
        return $this->token->isRequested();
    }
    /**
     * {@inheritdoc}
     */
    public function throwIfRequested()
    {
        $this->token->throwIfRequested();
    }
}<?php

namespace Amp;

/**
 * @template-covariant TValue
 * @template-implements Iterator<TValue>
 */
final class Producer implements Iterator
{
    /**
     * @use Internal\Producer<TValue>
     */
    use CallableMaker, Internal\Producer;
    /**
     * @param callable(callable(TValue ): Promise ): \Generator $producer
     *
     * @throws \Error Thrown if the callable does not return a Generator.
     */
    public function __construct(callable $producer)
    {
        $result = $producer($this->callableFromInstanceMethod("emit"));
        if (!$result instanceof \Generator) {
            throw new \Error("The callable did not return a Generator");
        }
        $coroutine = new Coroutine($result);
        $coroutine->onResolve(function ($exception) {
            if ($this->complete) {
                return;
            }
            if ($exception) {
                $this->fail($exception);
                return;
            }
            $this->complete();
        });
    }
}<?php

namespace Amp;

/**
 * Representation of the future value of an asynchronous operation.
 *
 * @template-covariant TValue
 * @psalm-yield TValue
 */
interface Promise
{
    /**
    * Registers a callback to be invoked when the promise is resolved.
    *
    * If this method is called multiple times, additional handlers will be registered instead of replacing any already
    existing handlers.
    *
    * If the promise is already resolved, the callback MUST be executed immediately.
    *
    * Exceptions MUST NOT be thrown from this method. Any exceptions thrown from invoked callbacks MUST be
    forwarded to the event-loop error handler.
    *
    * Note: You shouldn't implement this interface yourself. Instead, provide a method that returns a promise for the
    operation you're implementing. Objects other than pure placeholders implementing it are a very bad idea.
    *
    * @param callable $onResolved The first argument shall be `null` on success, while the second shall be `null` on
    failure.
    *
    * @psalm-param (callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $onResolved
    *
    * @return void
    */
    public function onResolve(callable $onResolved);
}<?php

namespace Amp\Internal;

use Amp\Coroutine;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
/**
 * Trait used by Promise implementations. Do not use this trait in your code, instead compose your class from one of
 * the available classes implementing \Amp\Promise.
 *
 * @internal
 */
trait Placeholder
{
    /** @var bool */
    private $resolved = false;
    /** @var mixed */
    private $result;
    /** @var ResolutionQueue|null|callable(\Throwable|null, mixed): (Promise|\React\Promise\PromiseInterface|\Generator<mixed,
     *     Promise|\React\Promise\PromiseInterface|array<array-key, Promise|\React\Promise\PromiseInterface>, mixed,
     *     mixed>|null)|callable(\Throwable|null, mixed): void */
    private $onResolved;
    /** @var null|array */
    private $resolutionTrace;
    /**
     * @inheritdoc
     */
    public function onResolve(callable $onResolved)
    {
        if ($this->resolved) {
            if ($this->result instanceof Promise) {
                $this->result->onResolve($onResolved);
                return;
            }
            try {
                /** @var mixed $result */
                $result = $onResolved(null, $this->result);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    Promise\rethrow($result);
                }
            } catch (\Throwable $exception) {
                Loop::defer(static function () use($exception) {
                    throw $exception;
                });
            }
            return;
        }
        if (null === $this->onResolved) {
            $this->onResolved = $onResolved;
            return;
        }
        if (!$this->onResolved instanceof ResolutionQueue) {
            /** @psalm-suppress InternalClass */
            $this->onResolved = new ResolutionQueue($this->onResolved);
        }
        /** @psalm-suppress InternalMethod */
        $this->onResolved->push($onResolved);
    }
    /**
     *
     */
    public function __destruct()
    {
        try {
            $this->result = null;
        } catch (\Throwable $e) {
            Loop::defer(static function () use($e) {
                throw $e;
            });
        }
    }
    /**
     * @param mixed $value
     *
     * @return void
     *
     * @throws \Error Thrown if the promise has already been resolved.
     */
    private function resolve($value = null)
    {
        if ($this->resolved) {
            $message = "Promise has already been resolved";
            if (isset($this->resolutionTrace)) {
                $trace = formatStacktrace($this->resolutionTrace);
                $message .= ". Previous resolution trace:\n\n{$trace}\n\n";
            } else {
                // @codeCoverageIgnoreStart
                $message .= ', define environment variable AMP_DEBUG or const AMP_DEBUG = true and enable assertions for a stacktrace of the previous resolution.';
                // @codeCoverageIgnoreEnd
            }
            throw new \Error($message);
        }
        \assert((function () {
            $env = \getenv("AMP_DEBUG") ?: "0";
            if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG") && \AMP_DEBUG) {
                $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
                \array_shift($trace);
                // remove current closure
                $this->resolutionTrace = $trace;
            }
            return true;
        })());
        if ($value instanceof ReactPromise) {
            $value = Promise\adapt($value);
        }
        $this->resolved = true;
        $this->result = $value;
        if ($this->onResolved === null) {
            return;
        }
        $onResolved = $this->onResolved;
        $this->onResolved = null;
        if ($this->result instanceof Promise) {
            $this->result->onResolve($onResolved);
            return;
        }
        try {
            /** @var mixed $result */
            $result = $onResolved(null, $this->result);
            $onResolved = null;
            // allow garbage collection of $onResolved, to catch any exceptions from destructors
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
    /**
     * @param \Throwable $reason Failure reason.
     *
     * @return void
     */
    private function fail(\Throwable $reason)
    {
        $this->resolve(new Failure($reason));
    }
    /**
     * @return bool True if the placeholder has been resolved.
     */
    private function isResolved() : bool
    {
        return $this->resolved;
    }
}<?php

namespace Amp\Internal;

use Amp\Deferred;
use Amp\Failure;
use Amp\Promise;
use Amp\Success;
use React\Promise\PromiseInterface as ReactPromise;
/**
 * Trait used by Iterator implementations. Do not use this trait in your code, instead compose your class from one of
 * the available classes implementing \Amp\Iterator.
 * Note that it is the responsibility of the user of this trait to ensure that listeners have a chance to listen first
 * before emitting values.
 *
 * @internal
 * @template-covariant TValue
 */
trait Producer
{
    /** @var Promise|null */
    private $complete;
    /** @var mixed[] */
    private $values = [];
    /** @var Deferred[] */
    private $backPressure = [];
    /** @var int */
    private $consumePosition = -1;
    /** @var int */
    private $emitPosition = -1;
    /** @var Deferred|null */
    private $waiting;
    /** @var null|array */
    private $resolutionTrace;
    /**
     * {@inheritdoc}
     *
     * @return Promise<bool>
     */
    public function advance() : Promise
    {
        if ($this->waiting !== null) {
            throw new \Error("The prior promise returned must resolve before invoking this method again");
        }
        unset($this->values[$this->consumePosition]);
        $position = ++$this->consumePosition;
        if (\array_key_exists($position, $this->values)) {
            \assert(isset($this->backPressure[$position]));
            $deferred = $this->backPressure[$position];
            unset($this->backPressure[$position]);
            $deferred->resolve();
            return new Success(true);
        }
        if ($this->complete) {
            return $this->complete;
        }
        $this->waiting = new Deferred();
        return $this->waiting->promise();
    }
    /**
     * {@inheritdoc}
     *
     * @return TValue
     */
    public function getCurrent()
    {
        if (empty($this->values) && $this->complete) {
            throw new \Error("The iterator has completed");
        }
        if (!\array_key_exists($this->consumePosition, $this->values)) {
            throw new \Error("Promise returned from advance() must resolve before calling this method");
        }
        return $this->values[$this->consumePosition];
    }
    /**
     * Emits a value from the iterator. The returned promise is resolved once the emitted value has been consumed.
     *
     * @param mixed $value
     *
     * @return Promise
     * @psalm-return Promise<null>
     *
     * @throws \Error If the iterator has completed.
     */
    private function emit($value) : Promise
    {
        if ($this->complete) {
            throw new \Error("Iterators cannot emit values after calling complete");
        }
        if ($value instanceof ReactPromise) {
            $value = Promise\adapt($value);
        }
        if ($value instanceof Promise) {
            $deferred = new Deferred();
            $value->onResolve(function ($e, $v) use($deferred) {
                if ($this->complete) {
                    $deferred->fail(new \Error("The iterator was completed before the promise result could be emitted"));
                    return;
                }
                if ($e) {
                    $this->fail($e);
                    $deferred->fail($e);
                    return;
                }
                $deferred->resolve($this->emit($v));
            });
            return $deferred->promise();
        }
        $position = ++$this->emitPosition;
        $this->values[$position] = $value;
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve(true);
            return new Success();
            // Consumer was already waiting for a new value, so back-pressure is unnecessary.
        }
        $this->backPressure[$position] = $pressure = new Deferred();
        return $pressure->promise();
    }
    /**
     * Completes the iterator.
     *
     * @return void
     *
     * @throws \Error If the iterator has already been completed.
     */
    private function complete()
    {
        if ($this->complete) {
            $message = "Iterator has already been completed";
            if (isset($this->resolutionTrace)) {
                $trace = formatStacktrace($this->resolutionTrace);
                $message .= ". Previous completion trace:\n\n{$trace}\n\n";
            } else {
                // @codeCoverageIgnoreStart
                $message .= ', define environment variable AMP_DEBUG or const AMP_DEBUG = true and enable assertions for a stacktrace of the previous resolution.';
                // @codeCoverageIgnoreEnd
            }
            throw new \Error($message);
        }
        \assert((function () {
            $env = \getenv("AMP_DEBUG") ?: "0";
            if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG") && \AMP_DEBUG) {
                $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
                \array_shift($trace);
                // remove current closure
                $this->resolutionTrace = $trace;
            }
            return true;
        })());
        $this->complete = new Success(false);
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve($this->complete);
        }
    }
    /**
     * @param \Throwable $exception
     *
     * @return void
     */
    private function fail(\Throwable $exception)
    {
        $this->complete = new Failure($exception);
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve($this->complete);
        }
    }
}<?php

namespace Amp\Internal;

use Amp\Promise;
/**
 * Wraps a Promise instance that has public methods to resolve and fail the promise into an object that only allows
 * access to the public API methods.
 */
final class PrivatePromise implements Promise
{
    /** @var Promise */
    private $promise;
    /**
     *
     */
    public function __construct(Promise $promise)
    {
        $this->promise = $promise;
    }
    /**
     *
     */
    public function onResolve(callable $onResolved)
    {
        $this->promise->onResolve($onResolved);
    }
}<?php

namespace Amp\Internal;

/**
* Formats a stacktrace obtained via `debug_backtrace()`.
*
* @param array<array{file?: string, line: int, type?: string, class: string, function: string}> $trace Output of
`debug_backtrace()`.
*
* @return string Formatted stacktrace.
*
* @codeCoverageIgnore
* @internal
*/
function formatStacktrace(array $trace) : string
{
    return \implode("\n", \array_map(static function ($e, $i) {
        $line = "#{$i} ";
        if (isset($e["file"])) {
            $line .= "{$e['file']}:{$e['line']} ";
        }
        if (isset($e["type"])) {
            $line .= $e["class"] . $e["type"];
        }
        return $line . $e["function"] . "()";
    }, $trace, \array_keys($trace)));
}
/**
 * Creates a `TypeError` with a standardized error message.
 *
 * @param string[] $expected Expected types.
 * @param mixed $given Given value.
 *
 * @return \TypeError
 *
 * @internal
 */
function createTypeError(array $expected, $given) : \TypeError
{
    $givenType = \is_object($given) ? \sprintf("instance of %s", \get_class($given)) : \gettype($given);
    if (\count($expected) === 1) {
        $expectedType = "Expected the following type: " . \array_pop($expected);
    } else {
        $expectedType = "Expected one of the following types: " . \implode(", ", $expected);
    }
    return new \TypeError("{$expectedType}; {$givenType} given");
}
/**
 * Returns the current time relative to an arbitrary point in time.
 *
 * @return int Time in milliseconds.
 */
function getCurrentTime() : int
{
    /** @var int|null $startTime */
    static $startTime;
    /** @var int|null $nextWarning */
    static $nextWarning;
    if (\PHP_INT_SIZE === 4) {
        // @codeCoverageIgnoreStart
        if ($startTime === null) {
            $startTime = \PHP_VERSION_ID >= 70300 ? \hrtime(false)[0] : \time();
            $nextWarning = \PHP_INT_MAX - 86400 * 7;
        }
        if (\PHP_VERSION_ID >= 70300) {
            list($seconds, $nanoseconds) = \hrtime(false);
            $seconds -= $startTime;
            if ($seconds >= $nextWarning) {
                $timeToOverflow = (\PHP_INT_MAX - $seconds * 1000) / 1000;
                \trigger_error("getCurrentTime() will overflow in {$timeToOverflow} seconds, please restart the process before that. " . "You're using a 32 bit version of PHP, so time will overflow about every 24 days. Regular restarts are required.", \E_USER_WARNING);
                /** @psalm-suppress PossiblyNullOperand */
                $nextWarning += 600;
                // every 10 minutes
            }
            return (int) ($seconds * 1000 + $nanoseconds / 1000000);
        }
        $seconds = \microtime(true) - $startTime;
        if ($seconds >= $nextWarning) {
            $timeToOverflow = (\PHP_INT_MAX - $seconds * 1000) / 1000;
            \trigger_error("getCurrentTime() will overflow in {$timeToOverflow} seconds, please restart the process before that. " . "You're using a 32 bit version of PHP, so time will overflow about every 24 days. Regular restarts are required.", \E_USER_WARNING);
            /** @psalm-suppress PossiblyNullOperand */
            $nextWarning += 600;
            // every 10 minutes
        }
        return (int) ($seconds * 1000);
        // @codeCoverageIgnoreEnd
    }
    if (\PHP_VERSION_ID >= 70300) {
        list($seconds, $nanoseconds) = \hrtime(false);
        return (int) ($seconds * 1000 + $nanoseconds / 1000000);
    }
    return (int) (\microtime(true) * 1000);
}<?php

namespace Amp\Internal;

use Amp\Iterator;
use Amp\Promise;
/**
 * Wraps an Iterator instance that has public methods to emit, complete, and fail into an object that only allows
 * access to the public API methods.
 *
 * @template-covariant TValue
 * @template-implements Iterator<TValue>
 */
final class PrivateIterator implements Iterator
{
    /** @var Iterator<TValue> */
    private $iterator;
    /**
     * @param Iterator $iterator
     *
     * @psalm-param Iterator<TValue> $iterator
     */
    public function __construct(Iterator $iterator)
    {
        $this->iterator = $iterator;
    }
    /**
     * @return Promise<bool>
     */
    public function advance() : Promise
    {
        return $this->iterator->advance();
    }
    /**
     * @psalm-return TValue
     */
    public function getCurrent()
    {
        return $this->iterator->getCurrent();
    }
}<?php

namespace Amp\Internal;

use Amp\Coroutine;
use Amp\Loop;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
/**
 * Stores a set of functions to be invoked when a promise is resolved.
 *
 * @internal
 * @psalm-internal Amp\Internal
 */
class ResolutionQueue
{
    /** @var array<array-key, callable(\Throwable|null, mixed): (Promise|\React\Promise\PromiseInterface|\Generator<mixed,
     *     Promise|\React\Promise\PromiseInterface|array<array-key, Promise|\React\Promise\PromiseInterface>, mixed,
     *     mixed>|null) | callable(\Throwable|null, mixed): void> */
    private $queue = [];
    /**
     * @param (callable | null) $callback Initial callback to add to queue.
     *
     * @psalm-param (null | callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $callback
     */
    public function __construct(callable $callback = null)
    {
        if ($callback !== null) {
            $this->push($callback);
        }
    }
    /**
     * Unrolls instances of self to avoid blowing up the call stack on resolution.
     *
     * @param callable $callback
     *
     * @psalm-param (callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $callback
     *
     * @return void
     */
    public function push(callable $callback)
    {
        if ($callback instanceof self) {
            $this->queue = \array_merge($this->queue, $callback->queue);
            return;
        }
        $this->queue[] = $callback;
    }
    /**
     * Calls each callback in the queue, passing the provided values to the function.
     *
     * @param (\Throwable | null) $exception
     * @param mixed $value
     *
     * @return void
     */
    public function __invoke($exception, $value)
    {
        foreach ($this->queue as $callback) {
            try {
                $result = $callback($exception, $value);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    Promise\rethrow($result);
                }
            } catch (\Throwable $exception) {
                Loop::defer(static function () use($exception) {
                    throw $exception;
                });
            }
        }
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Promise\rethrow;
/**
 * A cancellation token source provides a mechanism to cancel operations.
 *
 * Cancellation of operation works by creating a cancellation token source and passing the corresponding token when
 * starting the operation. To cancel the operation, invoke `CancellationTokenSource::cancel()`.
 *
 * Any operation can decide what to do on a cancellation request, it has "don't care" semantics. An operation SHOULD be
 * aborted, but MAY continue. Example: A DNS client might continue to receive and cache the response, as the query has
 * been sent anyway. An HTTP client would usually close a connection, but might not do so in case a response is close to
 * be fully received to reuse the connection.
 *
 * **Example**
 *
 * ```php
 * $tokenSource = new CancellationTokenSource;
 * $token = $tokenSource->getToken();
 *
 * $response = yield $httpClient->request("https://example.com/stream", $token);
 * $responseBody = $response->getBody();
 *
 * while (($chunk = yield $response->read()) !== null) {
 *     // consume $chunk
 *
 *     if ($noLongerInterested) {
 *         $cancellationTokenSource->cancel();
 *         break;
 *     }
 * }
 * ```
 *
 * @see CancellationToken
 * @see CancelledException
 */
final class CancellationTokenSource
{
    /** @var CancellationToken */
    private $token;
    /** @var callable|null */
    private $onCancel;
    /**
     *
     */
    public function __construct()
    {
        $onCancel = null;
        $this->token = new class($onCancel) implements CancellationToken
        {
            /** @var string */
            private $nextId = "a";
            /** @var callable[] */
            private $callbacks = [];
            /** @var \Throwable|null */
            private $exception;
            /**
             * @param mixed $onCancel
             * @param-out callable $onCancel
             */
            public function __construct(&$onCancel)
            {
                /** @psalm-suppress MissingClosureReturnType We still support PHP 7.0 */
                $onCancel = function (\Throwable $exception) {
                    $this->exception = $exception;
                    $callbacks = $this->callbacks;
                    $this->callbacks = [];
                    foreach ($callbacks as $callback) {
                        $this->invokeCallback($callback);
                    }
                };
            }
            /**
             * @param callable $callback
             *
             * @return void
             */
            private function invokeCallback(callable $callback)
            {
                // No type declaration to prevent exception outside the try!
                try {
                    /** @var mixed $result */
                    $result = $callback($this->exception);
                    if ($result instanceof \Generator) {
                        /** @psalm-var \Generator<mixed, Promise|ReactPromise|(Promise|ReactPromise)[], mixed, mixed> $result */
                        $result = new Coroutine($result);
                    }
                    if ($result instanceof Promise || $result instanceof ReactPromise) {
                        rethrow($result);
                    }
                } catch (\Throwable $exception) {
                    Loop::defer(static function () use($exception) {
                        throw $exception;
                    });
                }
            }
            /**
             *
             */
            public function subscribe(callable $callback) : string
            {
                $id = $this->nextId++;
                if ($this->exception) {
                    $this->invokeCallback($callback);
                } else {
                    $this->callbacks[$id] = $callback;
                }
                return $id;
            }
            /**
             *
             */
            public function unsubscribe(string $id)
            {
                unset($this->callbacks[$id]);
            }
            /**
             *
             */
            public function isRequested() : bool
            {
                return isset($this->exception);
            }
            /**
             *
             */
            public function throwIfRequested()
            {
                if (isset($this->exception)) {
                    throw $this->exception;
                }
            }
        };
        $this->onCancel = $onCancel;
    }
    /**
     *
     */
    public function getToken() : CancellationToken
    {
        return $this->token;
    }
    /**
     * @param (\Throwable | null) $previous Exception to be used as the previous exception to CancelledException.
     *
     * @return void
     */
    public function cancel(\Throwable $previous = null)
    {
        if ($this->onCancel === null) {
            return;
        }
        $onCancel = $this->onCancel;
        $this->onCancel = null;
        $onCancel(new CancelledException($previous));
    }
}<?php

namespace Amp\Loop;

use Amp\Struct;
/**
 * @template TValue as (int|resource|null)
 *
 * @psalm-suppress MissingConstructor
 */
class Watcher
{
    use Struct;
    const IO = 0b11;
    const READABLE = 0b1;
    const WRITABLE = 0b10;
    const DEFER = 0b100;
    const TIMER = 0b11000;
    const DELAY = 0b1000;
    const REPEAT = 0b10000;
    const SIGNAL = 0b100000;
    /** @var int */
    public $type;
    /** @var bool */
    public $enabled = true;
    /** @var bool */
    public $referenced = true;
    /** @var string */
    public $id;
    /** @var callable */
    public $callback;
    /**
     * Data provided to the watcher callback.
     *
     * @var mixed
     */
    public $data;
    /**
     * Watcher-dependent value storage. Stream for IO watchers, signal number for signal watchers, interval for timers.
     *
     * @var resource|int|null
     * @psalm-var TValue
     */
    public $value;
    /** @var int|null */
    public $expiration;
}<?php

namespace Amp\Loop;

use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
class EventDriver extends Driver
{
    /** @var \Event[]|null */
    private static $activeSignals;
    /** @var \EventBase */
    private $handle;
    /** @var \Event[] */
    private $events = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /** @var \Event[] */
    private $signals = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /**
     *
     */
    public function __construct()
    {
        $config = new \EventConfig();
        if (\DIRECTORY_SEPARATOR !== '\\') {
            $config->requireFeatures(\EventConfig::FEATURE_FDS);
        }
        $this->handle = new \EventBase($config);
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        if (self::$activeSignals === null) {
            self::$activeSignals =& $this->signals;
        }
        /**
         * @param         $resource
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->ioCallback = function ($resource, $what, Watcher $watcher) {
            \assert(\is_resource($watcher->value));
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param         $resource
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->timerCallback = function ($resource, $what, Watcher $watcher) {
            \assert(\is_int($watcher->value));
            if ($watcher->type & Watcher::DELAY) {
                $this->cancel($watcher->id);
            } else {
                $this->events[$watcher->id]->add($watcher->value / self::MILLISEC_PER_SEC);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param         $signum
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->signalCallback = function ($signum, $what, Watcher $watcher) {
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        if (isset($this->events[$watcherId])) {
            $this->events[$watcherId]->free();
            unset($this->events[$watcherId]);
        }
    }
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("event");
    }
    /**
     * @codeCoverageIgnore
     */
    public function __destruct()
    {
        // Unset here, otherwise $event->del() in the loop may fail with a warning, because __destruct order isn't defined.
        // Related https://github.com/amphp/amp/issues/159.
        $events = $this->events;
        $this->events = [];
        foreach ($events as $event) {
            if ($event !== null) {
                // Events may have been nulled in extension depending on destruct order.
                $event->free();
            }
        }
        // Manually free the loop handle to fully release loop resources.
        // See https://github.com/amphp/amp/issues/177.
        if ($this->handle !== null) {
            $this->handle->free();
            $this->handle = null;
        }
    }
    /**
     * {@inheritdoc}
     */
    public function run()
    {
        $active = self::$activeSignals;
        \assert($active !== null);
        foreach ($active as $event) {
            $event->del();
        }
        self::$activeSignals =& $this->signals;
        foreach ($this->signals as $event) {
            /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
            $event->add();
        }
        try {
            parent::run();
        } finally {
            foreach ($this->signals as $event) {
                $event->del();
            }
            self::$activeSignals =& $active;
            foreach ($active as $event) {
                /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
                $event->add();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function stop()
    {
        $this->handle->stop();
        parent::stop();
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle() : \EventBase
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        $this->handle->loop($blocking ? \EventBase::LOOP_ONCE : \EventBase::LOOP_ONCE | \EventBase::LOOP_NONBLOCK);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $now = $this->now();
        foreach ($watchers as $watcher) {
            if (!isset($this->events[$id = $watcher->id])) {
                switch ($watcher->type) {
                    case Watcher::READABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::READ | \Event::PERSIST, $this->ioCallback, $watcher);
                        break;
                    case Watcher::WRITABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::WRITE | \Event::PERSIST, $this->ioCallback, $watcher);
                        break;
                    case Watcher::DELAY:
                    case Watcher::REPEAT:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = new \Event($this->handle, -1, \Event::TIMEOUT, $this->timerCallback, $watcher);
                        break;
                    case Watcher::SIGNAL:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::SIGNAL | \Event::PERSIST, $this->signalCallback, $watcher);
                        break;
                    default:
                        // @codeCoverageIgnoreStart
                        throw new \Error("Unknown watcher type");
                }
            }
            switch ($watcher->type) {
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    $interval = \max(0, $watcher->expiration - $now);
                    $this->events[$id]->add($interval > 0 ? $interval / self::MILLISEC_PER_SEC : 0);
                    break;
                case Watcher::SIGNAL:
                    $this->signals[$id] = $this->events[$id];
                // no break
                default:
                    /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
                    $this->events[$id]->add();
                    break;
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        if (isset($this->events[$id = $watcher->id])) {
            $this->events[$id]->del();
            if ($watcher->type === Watcher::SIGNAL) {
                unset($this->signals[$id]);
            }
        }
    }
}<?php

namespace Amp\Loop;

use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Promise\rethrow;
/**
 * Event loop driver which implements all basic operations to allow interoperability.
 *
 * Watchers (enabled or new watchers) MUST immediately be marked as enabled, but only be activated (i.e. callbacks can
 * be called) right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
 *
 * All registered callbacks MUST NOT be called from a file with strict types enabled (`declare(strict_types=1)`).
 */
abstract class Driver
{
    // Don't use 1e3 / 1e6, they result in a float instead of int
    const MILLISEC_PER_SEC = 1000;
    const MICROSEC_PER_SEC = 1000000;
    /** @var string */
    private $nextId = "a";
    /** @var Watcher[] */
    private $watchers = [];
    /** @var Watcher[] */
    private $enableQueue = [];
    /** @var Watcher[] */
    private $deferQueue = [];
    /** @var Watcher[] */
    private $nextTickQueue = [];
    /** @var callable(\Throwable):void|null */
    private $errorHandler;
    /** @var bool */
    private $running = false;
    /** @var array */
    private $registry = [];
    /**
    * Run the event loop.
    *
    * One iteration of the loop is called one "tick". A tick covers the following steps:
    *
    * 1. Activate watchers created / enabled in the last tick / before `run()`.
    2. Execute all enabled defer watchers.
    3. Execute all due timer, pending signal and actionable stream callbacks, each only once per tick.
    *
    * The loop MUST continue to run until it is either stopped explicitly, no referenced watchers exist anymore, or an
    exception is thrown that cannot be handled. Exceptions that cannot be handled are exceptions thrown from an
    error handler or exceptions that would be passed to an error handler but none exists to handle them.
    *
    * @return void
    */
    public function run()
    {
        $this->running = true;
        try {
            while ($this->running) {
                if ($this->isEmpty()) {
                    return;
                }
                $this->tick();
            }
        } finally {
            $this->stop();
        }
    }
    /**
     * @return bool True if no enabled and referenced watchers remain in the loop.
     */
    private function isEmpty() : bool
    {
        foreach ($this->watchers as $watcher) {
            if ($watcher->enabled && $watcher->referenced) {
                return false;
            }
        }
        return true;
    }
    /**
     * Executes a single tick of the event loop.
     *
     * @return void
     */
    private function tick()
    {
        if (empty($this->deferQueue)) {
            $this->deferQueue = $this->nextTickQueue;
        } else {
            $this->deferQueue = \array_merge($this->deferQueue, $this->nextTickQueue);
        }
        $this->nextTickQueue = [];
        $this->activate($this->enableQueue);
        $this->enableQueue = [];
        foreach ($this->deferQueue as $watcher) {
            if (!isset($this->deferQueue[$watcher->id])) {
                continue;
                // Watcher disabled by another defer watcher.
            }
            unset($this->watchers[$watcher->id], $this->deferQueue[$watcher->id]);
            try {
                /** @var mixed $result */
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
        /** @psalm-suppress RedundantCondition */
        $this->dispatch(empty($this->nextTickQueue) && empty($this->enableQueue) && $this->running && !$this->isEmpty());
    }
    /**
     * Activates (enables) all the given watchers.
     *
     * @param Watcher[] $watchers
     *
     * @return void
     */
    protected abstract function activate(array $watchers);
    /**
     * Dispatches any pending read/write, timer, and signal events.
     *
     * @param bool $blocking
     *
     * @return void
     */
    protected abstract function dispatch(bool $blocking);
    /**
    * Stop the event loop.
    *
    * When an event loop is stopped, it continues with its current tick and exits the loop afterwards. Multiple calls
    to stop MUST be ignored and MUST NOT raise an exception.
    *
    * @return void
    */
    public function stop()
    {
        $this->running = false;
    }
    /**
    * Defer the execution of a callback.
    *
    * The deferred callable MUST be executed before any other type of watcher in a tick. Order of enabling MUST be
    preserved when executing the callbacks.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param callable (string $watcherId, mixed $data) $callback The callback to defer. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function defer(callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<null> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::DEFER;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->nextTickQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Delay the execution of a callback.
    *
    * The delay is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be determined by which
    timers expire first, but timers with the same expiration time MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $delay The amount of time, in milliseconds, to delay the execution for.
    * @param callable (string $watcherId, mixed $data) $callback The callback to delay. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function delay(int $delay, callable $callback, $data = null) : string
    {
        if ($delay < 0) {
            throw new \Error("Delay must be greater than or equal to zero");
        }
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::DELAY;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $delay;
        $watcher->expiration = $this->now() + $delay;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Repeatedly execute a callback.
    *
    * The interval between executions is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be
    determined by which timers expire first, but timers with the same expiration time MAY be executed in any order.
    The first execution is scheduled after the first interval period.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $interval The time interval, in milliseconds, to wait between executions.
    * @param callable (string $watcherId, mixed $data) $callback The callback to repeat.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function repeat(int $interval, callable $callback, $data = null) : string
    {
        if ($interval < 0) {
            throw new \Error("Interval must be greater than or equal to zero");
        }
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::REPEAT;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $interval;
        $watcher->expiration = $this->now() + $interval;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a stream resource becomes readable or is closed for reading.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable (string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function onReadable($stream, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<resource> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::READABLE;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $stream;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a stream resource becomes writable or is closed for writing.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable (string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function onWritable($stream, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<resource> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::WRITABLE;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $stream;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a signal is received.
    *
    * Warning: Installing the same signal on different instances of this interface is deemed undefined behavior.
    Implementations MAY try to detect this, if possible, but are not required to. This is due to technical
    limitations of the signals being registered globally per process.
    *
    * Multiple watchers on the same signal MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $signo The signal number to monitor.
    * @param callable (string $watcherId, int $signo, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the $data parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    *
    * @throws UnsupportedFeatureException If signal handling is not supported.
    */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::SIGNAL;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $signo;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Enable a watcher to be active starting in the next tick.
    *
    * Watchers MUST immediately be marked as enabled, but only be activated (i.e. callbacks can be called) right before
    the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public function enable(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            throw new InvalidWatcherError($watcherId, "Cannot enable an invalid watcher identifier: '{$watcherId}'");
        }
        $watcher = $this->watchers[$watcherId];
        if ($watcher->enabled) {
            return;
            // Watcher already enabled.
        }
        $watcher->enabled = true;
        switch ($watcher->type) {
            case Watcher::DEFER:
                $this->nextTickQueue[$watcher->id] = $watcher;
                break;
            case Watcher::REPEAT:
            case Watcher::DELAY:
                \assert(\is_int($watcher->value));
                $watcher->expiration = $this->now() + $watcher->value;
                $this->enableQueue[$watcher->id] = $watcher;
                break;
            default:
                $this->enableQueue[$watcher->id] = $watcher;
                break;
        }
    }
    /**
    * Cancel a watcher.
    *
    * This will detach the event loop from all resources that are associated to the watcher. After this operation the
    watcher is permanently invalid. Calling this function MUST NOT fail, even if passed an invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function cancel(string $watcherId)
    {
        $this->disable($watcherId);
        unset($this->watchers[$watcherId]);
    }
    /**
    * Disable a watcher immediately.
    *
    * A watcher MUST be disabled immediately, e.g. if a defer watcher disables a later defer watcher, the second defer
    watcher isn't executed in this tick.
    *
    * Disabling a watcher MUST NOT invalidate the watcher. Calling this function MUST NOT fail, even if passed an
    invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function disable(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            return;
        }
        $watcher = $this->watchers[$watcherId];
        if (!$watcher->enabled) {
            return;
            // Watcher already disabled.
        }
        $watcher->enabled = false;
        $id = $watcher->id;
        switch ($watcher->type) {
            case Watcher::DEFER:
                if (isset($this->nextTickQueue[$id])) {
                    // Watcher was only queued to be enabled.
                    unset($this->nextTickQueue[$id]);
                } else {
                    unset($this->deferQueue[$id]);
                }
                break;
            default:
                if (isset($this->enableQueue[$id])) {
                    // Watcher was only queued to be enabled.
                    unset($this->enableQueue[$id]);
                } else {
                    $this->deactivate($watcher);
                }
                break;
        }
    }
    /**
     * Deactivates (disables) the given watcher.
     *
     * @param Watcher $watcher
     *
     * @return void
     */
    protected abstract function deactivate(Watcher $watcher);
    /**
    * Reference a watcher.
    *
    * This will keep the event loop alive whilst the watcher is still being monitored. Watchers have this state by
    default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public function reference(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            throw new InvalidWatcherError($watcherId, "Cannot reference an invalid watcher identifier: '{$watcherId}'");
        }
        $this->watchers[$watcherId]->referenced = true;
    }
    /**
    * Unreference a watcher.
    *
    * The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers
    are all referenced by default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function unreference(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            return;
        }
        $this->watchers[$watcherId]->referenced = false;
    }
    /**
    * Stores information in the loop bound registry.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    * @param mixed $value The value to be stored.
    *
    * @return void
    */
    public final function setState(string $key, $value)
    {
        if ($value === null) {
            unset($this->registry[$key]);
        } else {
            $this->registry[$key] = $value;
        }
    }
    /**
    * Gets information stored bound to the loop.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    *
    * @return mixed The previously stored value or `null` if it doesn't exist.
    */
    public final function getState(string $key)
    {
        return isset($this->registry[$key]) ? $this->registry[$key] : null;
    }
    /**
    * Set a callback to be executed when an error occurs.
    *
    * The callback receives the error as the first and only parameter. The return value of the callback gets ignored.
    If it can't handle the error, it MUST throw the error. Errors thrown by the callback or during its invocation
    MUST be thrown into the `run` loop and stop the driver.
    *
    * Subsequent calls to this method will overwrite the previous handler.
    *
    * @param (callable(\Throwable $error): void | null) $callback The callback to execute. `null` will clear the
    current handler.
    *
    * @return (callable(\Throwable $error): void | null) The previous handler, `null` if there was none.
    */
    public function setErrorHandler(callable $callback = null)
    {
        $previous = $this->errorHandler;
        $this->errorHandler = $callback;
        return $previous;
    }
    /**
     * Invokes the error handler with the given exception.
     *
     * @param \Throwable $exception The exception thrown from a watcher callback.
     *
     * @return void
     * @throws \Throwable If no error handler has been set.
     */
    protected function error(\Throwable $exception)
    {
        if ($this->errorHandler === null) {
            throw $exception;
        }
        ($this->errorHandler)($exception);
    }
    /**
    * Returns the current loop time in millisecond increments. Note this value does not necessarily correlate to
    wall-clock time, rather the value returned is meant to be used in relative comparisons to prior values returned
    by this method (intervals, expiration calculations, etc.) and is only updated once per loop tick.
    *
    * Extending classes should override this function to return a value cached once per loop tick.
    *
    * @return int
    */
    public function now() : int
    {
        return (int) (\microtime(true) * self::MILLISEC_PER_SEC);
    }
    /**
    * Get the underlying loop handle.
    *
    * Example: the `uv_loop` resource for `libuv` or the `EvLoop` object for `libev` or `null` for a native driver.
    *
    * Note: This function is *not* exposed in the `Loop` class. Users shall access it directly on the respective loop
    instance.
    *
    * @return (null | object | resource) The loop handle the event loop operates on. `null` if there is none.
    */
    public abstract function getHandle();
    /**
     * Returns the same array of data as getInfo().
     *
     * @return array
     */
    public function __debugInfo()
    {
        // @codeCoverageIgnoreStart
        return $this->getInfo();
        // @codeCoverageIgnoreEnd
    }
    /**
    * Retrieve an associative array of information about the event loop driver.
    *
    * The returned array MUST contain the following data describing the driver's currently registered watchers:
    *
    * [
    "defer"            => ["enabled" => int, "disabled" => int],
    "delay"            => ["enabled" => int, "disabled" => int],
    "repeat"           => ["enabled" => int, "disabled" => int],
    "on_readable"      => ["enabled" => int, "disabled" => int],
    "on_writable"      => ["enabled" => int, "disabled" => int],
    "on_signal"        => ["enabled" => int, "disabled" => int],
    "enabled_watchers" => ["referenced" => int, "unreferenced" => int],
    "running"          => bool
    ];
    *
    * Implementations MAY optionally add more information in the array but at minimum the above `key => value` format
    MUST always be provided.
    *
    * @return array Statistics about the loop in the described format.
    */
    public function getInfo() : array
    {
        $watchers = ["referenced" => 0, "unreferenced" => 0];
        $defer = $delay = $repeat = $onReadable = $onWritable = $onSignal = ["enabled" => 0, "disabled" => 0];
        foreach ($this->watchers as $watcher) {
            switch ($watcher->type) {
                case Watcher::READABLE:
                    $array =& $onReadable;
                    break;
                case Watcher::WRITABLE:
                    $array =& $onWritable;
                    break;
                case Watcher::SIGNAL:
                    $array =& $onSignal;
                    break;
                case Watcher::DEFER:
                    $array =& $defer;
                    break;
                case Watcher::DELAY:
                    $array =& $delay;
                    break;
                case Watcher::REPEAT:
                    $array =& $repeat;
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
            if ($watcher->enabled) {
                ++$array["enabled"];
                if ($watcher->referenced) {
                    ++$watchers["referenced"];
                } else {
                    ++$watchers["unreferenced"];
                }
            } else {
                ++$array["disabled"];
            }
        }
        return ["enabled_watchers" => $watchers, "defer" => $defer, "delay" => $delay, "repeat" => $repeat, "on_readable" => $onReadable, "on_writable" => $onWritable, "on_signal" => $onSignal, "running" => (bool) $this->running];
    }
}<?php

namespace Amp\Loop;

// @codeCoverageIgnoreStart
class DriverFactory
{
    /**
     * Creates a new loop instance and chooses the best available driver.
     *
     * @return Driver
     *
     * @throws \Error If an invalid class has been specified via AMP_LOOP_DRIVER
     */
    public function create() : Driver
    {
        $driver = (function () {
            if ($driver = $this->createDriverFromEnv()) {
                return $driver;
            }
            if (UvDriver::isSupported()) {
                return new UvDriver();
            }
            if (EvDriver::isSupported()) {
                return new EvDriver();
            }
            if (EventDriver::isSupported()) {
                return new EventDriver();
            }
            return new NativeDriver();
        })();
        if (\getenv("AMP_DEBUG_TRACE_WATCHERS")) {
            return new TracingDriver($driver);
        }
        return $driver;
    }
    /**
     * @return (Driver | null)
     */
    private function createDriverFromEnv()
    {
        $driver = \getenv("AMP_LOOP_DRIVER");
        if (!$driver) {
            return null;
        }
        if (!\class_exists($driver)) {
            throw new \Error(\sprintf("Driver '%s' does not exist.", $driver));
        }
        if (!\is_subclass_of($driver, Driver::class)) {
            throw new \Error(\sprintf("Driver '%s' is not a subclass of '%s'.", $driver, Driver::class));
        }
        return new $driver();
    }
}
// @codeCoverageIgnoreEnd<?php

namespace Amp\Loop;

use Amp\CallableMaker;
use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
class NativeDriver extends Driver
{
    use CallableMaker;
    /** @var resource[] */
    private $readStreams = [];
    /** @var Watcher[][] */
    private $readWatchers = [];
    /** @var resource[] */
    private $writeStreams = [];
    /** @var Watcher[][] */
    private $writeWatchers = [];
    /** @var Internal\TimerQueue */
    private $timerQueue;
    /** @var Watcher[][] */
    private $signalWatchers = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /** @var bool */
    private $signalHandling;
    /** @var callable */
    private $streamSelectErrorHandler;
    /** @var bool */
    private $streamSelectIgnoreResult = false;
    /**
     *
     */
    public function __construct()
    {
        $this->timerQueue = new Internal\TimerQueue();
        $this->signalHandling = \extension_loaded("pcntl");
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        $this->streamSelectErrorHandler = function ($errno, $message) {
            // Casing changed in PHP 8 from 'unable' to 'Unable'
            if (\stripos($message, "stream_select(): unable to select [4]: ") === 0) {
                // EINTR
                $this->streamSelectIgnoreResult = true;
                return;
            }
            if (\strpos($message, 'FD_SETSIZE') !== false) {
                $message = \str_replace(["\r\n", "\n", "\r"], " ", $message);
                $pattern = '(stream_select\\(\\): You MUST recompile PHP with a larger value of FD_SETSIZE. It is set to (\\d+), but you have descriptors numbered at least as high as (\\d+)\\.)';
                if (\preg_match($pattern, $message, $match)) {
                    $helpLink = 'https://amphp.org/amp/event-loop/#implementations';
                    $message = 'You have reached the limits of stream_select(). It has a FD_SETSIZE of ' . $match[1] . ', but you have file descriptors numbered at least as high as ' . $match[2] . '. ' . "You can install one of the extensions listed on {$helpLink} to support a higher number of " . 'concurrent file descriptors. If a large number of open file descriptors is unexpected, you might be leaking file descriptors that aren\'t closed correctly.';
                }
            }
            throw new \Exception($message, $errno);
        };
    }
    /**
     * {@inheritdoc}
     *
     * @throws \Amp\Loop\UnsupportedFeatureException If the pcntl extension is not available.
     */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        if (!$this->signalHandling) {
            throw new UnsupportedFeatureException("Signal handling requires the pcntl extension");
        }
        return parent::onSignal($signo, $callback, $data);
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle()
    {
        return null;
    }
    /**
     * @param bool $blocking
     *
     * @return void
     *
     * @throws \Throwable
     */
    protected function dispatch(bool $blocking)
    {
        $this->selectStreams($this->readStreams, $this->writeStreams, $blocking ? $this->getTimeout() : 0);
        $now = $this->now();
        while ($watcher = $this->timerQueue->extract($now)) {
            if ($watcher->type & Watcher::REPEAT) {
                $watcher->enabled = false;
                // Trick base class into adding to enable queue when calling enable()
                $this->enable($watcher->id);
            } else {
                $this->cancel($watcher->id);
            }
            try {
                // Execute the timer.
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
        if ($this->signalHandling) {
            \pcntl_signal_dispatch();
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        foreach ($watchers as $watcher) {
            switch ($watcher->type) {
                case Watcher::READABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    $this->readWatchers[$streamId][$watcher->id] = $watcher;
                    $this->readStreams[$streamId] = $watcher->value;
                    break;
                case Watcher::WRITABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    $this->writeWatchers[$streamId][$watcher->id] = $watcher;
                    $this->writeStreams[$streamId] = $watcher->value;
                    break;
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    $this->timerQueue->insert($watcher);
                    break;
                case Watcher::SIGNAL:
                    \assert(\is_int($watcher->value));
                    if (!isset($this->signalWatchers[$watcher->value])) {
                        if (!@\pcntl_signal($watcher->value, $this->callableFromInstanceMethod('handleSignal'))) {
                            $message = "Failed to register signal handler";
                            if ($error = \error_get_last()) {
                                $message .= \sprintf("; Errno: %d; %s", $error["type"], $error["message"]);
                            }
                            throw new \Error($message);
                        }
                    }
                    $this->signalWatchers[$watcher->value][$watcher->id] = $watcher;
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        switch ($watcher->type) {
            case Watcher::READABLE:
                $streamId = (int) $watcher->value;
                unset($this->readWatchers[$streamId][$watcher->id]);
                if (empty($this->readWatchers[$streamId])) {
                    unset($this->readWatchers[$streamId], $this->readStreams[$streamId]);
                }
                break;
            case Watcher::WRITABLE:
                $streamId = (int) $watcher->value;
                unset($this->writeWatchers[$streamId][$watcher->id]);
                if (empty($this->writeWatchers[$streamId])) {
                    unset($this->writeWatchers[$streamId], $this->writeStreams[$streamId]);
                }
                break;
            case Watcher::DELAY:
            case Watcher::REPEAT:
                $this->timerQueue->remove($watcher);
                break;
            case Watcher::SIGNAL:
                \assert(\is_int($watcher->value));
                if (isset($this->signalWatchers[$watcher->value])) {
                    unset($this->signalWatchers[$watcher->value][$watcher->id]);
                    if (empty($this->signalWatchers[$watcher->value])) {
                        unset($this->signalWatchers[$watcher->value]);
                        @\pcntl_signal($watcher->value, \SIG_DFL);
                    }
                }
                break;
            default:
                // @codeCoverageIgnoreStart
                throw new \Error("Unknown watcher type");
        }
    }
    /**
     * @param resource[] $read
     * @param resource[] $write
     * @param int $timeout
     *
     * @return void
     */
    private function selectStreams(array $read, array $write, int $timeout)
    {
        $timeout /= self::MILLISEC_PER_SEC;
        if (!empty($read) || !empty($write)) {
            // Use stream_select() if there are any streams in the loop.
            if ($timeout >= 0) {
                $seconds = (int) $timeout;
                $microseconds = (int) (($timeout - $seconds) * self::MICROSEC_PER_SEC);
            } else {
                $seconds = null;
                $microseconds = null;
            }
            // Failed connection attempts are indicated via except on Windows
            // @link https://github.com/reactphp/event-loop/blob/8bd064ce23c26c4decf186c2a5a818c9a8209eb0/src/StreamSelectLoop.php#L279-L287
            // @link https://docs.microsoft.com/de-de/windows/win32/api/winsock2/nf-winsock2-select
            $except = null;
            if (\DIRECTORY_SEPARATOR === '\\') {
                $except = $write;
            }
            \set_error_handler($this->streamSelectErrorHandler);
            try {
                $result = \stream_select($read, $write, $except, $seconds, $microseconds);
            } finally {
                \restore_error_handler();
            }
            if ($this->streamSelectIgnoreResult || $result === 0) {
                $this->streamSelectIgnoreResult = false;
                return;
            }
            if (!$result) {
                $this->error(new \Exception('Unknown error during stream_select'));
                return;
            }
            foreach ($read as $stream) {
                $streamId = (int) $stream;
                if (!isset($this->readWatchers[$streamId])) {
                    continue;
                    // All read watchers disabled.
                }
                foreach ($this->readWatchers[$streamId] as $watcher) {
                    if (!isset($this->readWatchers[$streamId][$watcher->id])) {
                        continue;
                        // Watcher disabled by another IO watcher.
                    }
                    try {
                        $result = ($watcher->callback)($watcher->id, $stream, $watcher->data);
                        if ($result === null) {
                            continue;
                        }
                        if ($result instanceof \Generator) {
                            $result = new Coroutine($result);
                        }
                        if ($result instanceof Promise || $result instanceof ReactPromise) {
                            rethrow($result);
                        }
                    } catch (\Throwable $exception) {
                        $this->error($exception);
                    }
                }
            }
            \assert(\is_array($write));
            // See https://github.com/vimeo/psalm/issues/3036
            if ($except) {
                foreach ($except as $key => $socket) {
                    $write[$key] = $socket;
                }
            }
            foreach ($write as $stream) {
                $streamId = (int) $stream;
                if (!isset($this->writeWatchers[$streamId])) {
                    continue;
                    // All write watchers disabled.
                }
                foreach ($this->writeWatchers[$streamId] as $watcher) {
                    if (!isset($this->writeWatchers[$streamId][$watcher->id])) {
                        continue;
                        // Watcher disabled by another IO watcher.
                    }
                    try {
                        $result = ($watcher->callback)($watcher->id, $stream, $watcher->data);
                        if ($result === null) {
                            continue;
                        }
                        if ($result instanceof \Generator) {
                            $result = new Coroutine($result);
                        }
                        if ($result instanceof Promise || $result instanceof ReactPromise) {
                            rethrow($result);
                        }
                    } catch (\Throwable $exception) {
                        $this->error($exception);
                    }
                }
            }
            return;
        }
        if ($timeout < 0) {
            // Only signal watchers are enabled, so sleep indefinitely.
            \usleep(\PHP_INT_MAX);
            return;
        }
        if ($timeout > 0) {
            // Sleep until next timer expires.
            \usleep((int) ($timeout * self::MICROSEC_PER_SEC));
        }
    }
    /**
     * @return int Milliseconds until next timer expires or -1 if there are no pending times.
     */
    private function getTimeout() : int
    {
        $expiration = $this->timerQueue->peek();
        if ($expiration === null) {
            return -1;
        }
        $expiration -= getCurrentTime() - $this->nowOffset;
        return $expiration > 0 ? $expiration : 0;
    }
    /**
     * @param int $signo
     *
     * @return void
     */
    private function handleSignal(int $signo)
    {
        foreach ($this->signalWatchers[$signo] as $watcher) {
            if (!isset($this->signalWatchers[$signo][$watcher->id])) {
                continue;
            }
            try {
                $result = ($watcher->callback)($watcher->id, $signo, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
    }
}<?php

namespace Amp\Loop\Internal;

use Amp\Loop\Watcher;
/**
 * Uses a binary tree stored in an array to implement a heap.
 */
final class TimerQueue
{
    /** @var Watcher[] */
    private $data = [];
    /** @var int[] */
    private $pointers = [];
    /**
     * @param int $node Rebuild the data array from the given node upward.
     *
     * @return void
     */
    private function heapifyUp(int $node)
    {
        $entry = $this->data[$node];
        while ($node !== 0 && $entry->expiration < $this->data[$parent = $node - 1 >> 1]->expiration) {
            $this->swap($node, $parent);
            $node = $parent;
        }
    }
    /**
     * @param int $node Rebuild the data array from the given node downward.
     *
     * @return void
     */
    private function heapifyDown(int $node)
    {
        $length = \count($this->data);
        while (($child = ($node << 1) + 1) < $length) {
            if ($this->data[$child]->expiration < $this->data[$node]->expiration && ($child + 1 >= $length || $this->data[$child]->expiration < $this->data[$child + 1]->expiration)) {
                // Left child is less than parent and right child.
                $swap = $child;
            } elseif ($child + 1 < $length && $this->data[$child + 1]->expiration < $this->data[$node]->expiration) {
                // Right child is less than parent and left child.
                $swap = $child + 1;
            } else {
                // Left and right child are greater than parent.
                break;
            }
            $this->swap($node, $swap);
            $node = $swap;
        }
    }
    /**
     *
     */
    private function swap(int $left, int $right)
    {
        $temp = $this->data[$left];
        $this->data[$left] = $this->data[$right];
        $this->pointers[$this->data[$right]->id] = $left;
        $this->data[$right] = $temp;
        $this->pointers[$temp->id] = $right;
    }
    /**
     * Inserts the watcher into the queue. Time complexity: O(log(n)).
     *
     * @param Watcher $watcher
     *
     * @psalm-param Watcher<int> $watcher
     *
     * @return void
     */
    public function insert(Watcher $watcher)
    {
        \assert($watcher->expiration !== null);
        \assert(!isset($this->pointers[$watcher->id]));
        $node = \count($this->data);
        $this->data[$node] = $watcher;
        $this->pointers[$watcher->id] = $node;
        $this->heapifyUp($node);
    }
    /**
     * Removes the given watcher from the queue. Time complexity: O(log(n)).
     *
     * @param Watcher $watcher
     *
     * @psalm-param Watcher<int> $watcher
     *
     * @return void
     */
    public function remove(Watcher $watcher)
    {
        $id = $watcher->id;
        if (!isset($this->pointers[$id])) {
            return;
        }
        $this->removeAndRebuild($this->pointers[$id]);
    }
    /**
    * Deletes and returns the Watcher on top of the heap if it has expired, otherwise null is returned.
    Time complexity: O(log(n)).
    *
    * @param int $now Current loop time.
    *
    * @return (Watcher | null) Expired watcher at the top of the heap or null if the watcher has not expired.
    *
    * @psalm-return (Watcher<int> | null)
    */
    public function extract(int $now)
    {
        if (empty($this->data)) {
            return null;
        }
        $watcher = $this->data[0];
        if ($watcher->expiration > $now) {
            return null;
        }
        $this->removeAndRebuild(0);
        return $watcher;
    }
    /**
     * Returns the expiration time value at the top of the heap. Time complexity: O(1).
     *
     * @return (int | null) Expiration time of the watcher at the top of the heap or null if the heap is empty.
     */
    public function peek()
    {
        return isset($this->data[0]) ? $this->data[0]->expiration : null;
    }
    /**
     * @param int $node Remove the given node and then rebuild the data array.
     *
     * @return void
     */
    private function removeAndRebuild(int $node)
    {
        $length = \count($this->data) - 1;
        $id = $this->data[$node]->id;
        $left = $this->data[$node] = $this->data[$length];
        $this->pointers[$left->id] = $node;
        unset($this->data[$length], $this->pointers[$id]);
        if ($node < $length) {
            // don't need to do anything if we removed the last element
            $parent = $node - 1 >> 1;
            if ($parent >= 0 && $this->data[$node]->expiration < $this->data[$parent]->expiration) {
                $this->heapifyUp($node);
            } else {
                $this->heapifyDown($node);
            }
        }
    }
}<?php

namespace Amp\Loop;

/**
 * MUST be thrown if a feature is not supported by the system.
 *
 * This might happen if ext-pcntl is missing and the loop driver doesn't support another way to dispatch signals.
 */
class UnsupportedFeatureException extends \Exception
{
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\Loop;

use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
class EvDriver extends Driver
{
    /** @var \EvSignal[]|null */
    private static $activeSignals;
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("ev");
    }
    /** @var \EvLoop */
    private $handle;
    /** @var \EvWatcher[] */
    private $events = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /** @var \EvSignal[] */
    private $signals = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /**
     *
     */
    public function __construct()
    {
        $this->handle = new \EvLoop();
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        if (self::$activeSignals === null) {
            self::$activeSignals =& $this->signals;
        }
        /**
         * @param \EvIO $event
         *
         * @return void
         */
        $this->ioCallback = function (\EvIO $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param \EvTimer $event
         *
         * @return void
         */
        $this->timerCallback = function (\EvTimer $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            if ($watcher->type & Watcher::DELAY) {
                $this->cancel($watcher->id);
            } elseif ($watcher->value === 0) {
                // Disable and re-enable so it's not executed repeatedly in the same tick
                // See https://github.com/amphp/amp/issues/131
                $this->disable($watcher->id);
                $this->enable($watcher->id);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param \EvSignal $event
         *
         * @return void
         */
        $this->signalCallback = function (\EvSignal $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        unset($this->events[$watcherId]);
    }
    /**
     *
     */
    public function __destruct()
    {
        foreach ($this->events as $event) {
            /** @psalm-suppress all */
            if ($event !== null) {
                // Events may have been nulled in extension depending on destruct order.
                $event->stop();
            }
        }
        // We need to clear all references to events manually, see
        // https://bitbucket.org/osmanov/pecl-ev/issues/31/segfault-in-ev_timer_stop
        $this->events = [];
    }
    /**
     * {@inheritdoc}
     */
    public function run()
    {
        $active = self::$activeSignals;
        \assert($active !== null);
        foreach ($active as $event) {
            $event->stop();
        }
        self::$activeSignals =& $this->signals;
        foreach ($this->signals as $event) {
            $event->start();
        }
        try {
            parent::run();
        } finally {
            foreach ($this->signals as $event) {
                $event->stop();
            }
            self::$activeSignals =& $active;
            foreach ($active as $event) {
                $event->start();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function stop()
    {
        $this->handle->stop();
        parent::stop();
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle() : \EvLoop
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        $this->handle->run($blocking ? \Ev::RUN_ONCE : \Ev::RUN_ONCE | \Ev::RUN_NOWAIT);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $this->handle->nowUpdate();
        $now = $this->now();
        foreach ($watchers as $watcher) {
            if (!isset($this->events[$id = $watcher->id])) {
                switch ($watcher->type) {
                    case Watcher::READABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = $this->handle->io($watcher->value, \Ev::READ, $this->ioCallback, $watcher);
                        break;
                    case Watcher::WRITABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = $this->handle->io($watcher->value, \Ev::WRITE, $this->ioCallback, $watcher);
                        break;
                    case Watcher::DELAY:
                    case Watcher::REPEAT:
                        \assert(\is_int($watcher->value));
                        $interval = $watcher->value / self::MILLISEC_PER_SEC;
                        $this->events[$id] = $this->handle->timer(\max(0, ($watcher->expiration - $now) / self::MILLISEC_PER_SEC), $watcher->type & Watcher::REPEAT ? $interval : 0, $this->timerCallback, $watcher);
                        break;
                    case Watcher::SIGNAL:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = $this->handle->signal($watcher->value, $this->signalCallback, $watcher);
                        break;
                    default:
                        // @codeCoverageIgnoreStart
                        throw new \Error("Unknown watcher type");
                }
            } else {
                $this->events[$id]->start();
            }
            if ($watcher->type === Watcher::SIGNAL) {
                /** @psalm-suppress PropertyTypeCoercion */
                $this->signals[$id] = $this->events[$id];
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        if (isset($this->events[$id = $watcher->id])) {
            $this->events[$id]->stop();
            if ($watcher->type === Watcher::SIGNAL) {
                unset($this->signals[$id]);
            }
        }
    }
}<?php

namespace Amp\Loop;

use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Promise\rethrow;
class UvDriver extends Driver
{
    /** @var resource A uv_loop resource created with uv_loop_new() */
    private $handle;
    /** @var resource[] */
    private $events = [];
    /** @var Watcher[][] */
    private $watchers = [];
    /** @var resource[] */
    private $streams = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /**
     *
     */
    public function __construct()
    {
        $this->handle = \uv_loop_new();
        /**
         * @param $event
         * @param $status
         * @param $events
         * @param $resource
         *
         * @return void
         */
        $this->ioCallback = function ($event, $status, $events, $resource) {
            $watchers = $this->watchers[(int) $event];
            switch ($status) {
                case 0:
                    // OK
                    break;
                default:
                    // Invoke the callback on errors, as this matches behavior with other loop back-ends.
                    // Re-enable watcher as libuv disables the watcher on non-zero status.
                    $flags = 0;
                    foreach ($watchers as $watcher) {
                        $flags |= $watcher->enabled ? $watcher->type : 0;
                    }
                    \uv_poll_start($event, $flags, $this->ioCallback);
                    break;
            }
            foreach ($watchers as $watcher) {
                // $events is OR'ed with 4 to trigger watcher if no events are indicated (0) or on UV_DISCONNECT (4).
                // http://docs.libuv.org/en/v1.x/poll.html
                if (!($watcher->enabled && ($watcher->type & $events || ($events | 4) === 4))) {
                    continue;
                }
                try {
                    $result = ($watcher->callback)($watcher->id, $resource, $watcher->data);
                    if ($result === null) {
                        continue;
                    }
                    if ($result instanceof \Generator) {
                        $result = new Coroutine($result);
                    }
                    if ($result instanceof Promise || $result instanceof ReactPromise) {
                        rethrow($result);
                    }
                } catch (\Throwable $exception) {
                    $this->error($exception);
                }
            }
        };
        /**
         * @param $event
         *
         * @return void
         */
        $this->timerCallback = function ($event) {
            $watcher = $this->watchers[(int) $event][0];
            if ($watcher->type & Watcher::DELAY) {
                unset($this->events[$watcher->id], $this->watchers[(int) $event]);
                // Avoid call to uv_is_active().
                $this->cancel($watcher->id);
                // Remove reference to watcher in parent.
            } elseif ($watcher->value === 0) {
                // Disable and re-enable so it's not executed repeatedly in the same tick
                // See https://github.com/amphp/amp/issues/131
                $this->disable($watcher->id);
                $this->enable($watcher->id);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param $event
         * @param $signo
         *
         * @return void
         */
        $this->signalCallback = function ($event, $signo) {
            $watcher = $this->watchers[(int) $event][0];
            try {
                $result = ($watcher->callback)($watcher->id, $signo, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        if (!isset($this->events[$watcherId])) {
            return;
        }
        $event = $this->events[$watcherId];
        $eventId = (int) $event;
        if (isset($this->watchers[$eventId][0])) {
            // All except IO watchers.
            unset($this->watchers[$eventId]);
        } elseif (isset($this->watchers[$eventId][$watcherId])) {
            $watcher = $this->watchers[$eventId][$watcherId];
            unset($this->watchers[$eventId][$watcherId]);
            if (empty($this->watchers[$eventId])) {
                unset($this->watchers[$eventId], $this->streams[(int) $watcher->value]);
            }
        }
        unset($this->events[$watcherId]);
    }
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("uv");
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        \uv_update_time($this->handle);
        /** @psalm-suppress TooManyArguments */
        return \uv_now($this->handle);
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle()
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        /** @psalm-suppress TooManyArguments */
        \uv_run($this->handle, $blocking ? \UV::RUN_ONCE : \UV::RUN_NOWAIT);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $now = $this->now();
        foreach ($watchers as $watcher) {
            $id = $watcher->id;
            switch ($watcher->type) {
                case Watcher::READABLE:
                case Watcher::WRITABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    if (isset($this->streams[$streamId])) {
                        $event = $this->streams[$streamId];
                    } elseif (isset($this->events[$id])) {
                        $event = $this->streams[$streamId] = $this->events[$id];
                    } else {
                        /** @psalm-suppress UndefinedFunction */
                        $event = $this->streams[$streamId] = \uv_poll_init_socket($this->handle, $watcher->value);
                    }
                    $eventId = (int) $event;
                    $this->events[$id] = $event;
                    $this->watchers[$eventId][$id] = $watcher;
                    $flags = 0;
                    foreach ($this->watchers[$eventId] as $w) {
                        $flags |= $w->enabled ? $w->type : 0;
                    }
                    \uv_poll_start($event, $flags, $this->ioCallback);
                    break;
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    if (isset($this->events[$id])) {
                        $event = $this->events[$id];
                    } else {
                        $event = $this->events[$id] = \uv_timer_init($this->handle);
                    }
                    $this->watchers[(int) $event] = [$watcher];
                    \uv_timer_start($event, \max(0, $watcher->expiration - $now), $watcher->type & Watcher::REPEAT ? $watcher->value : 0, $this->timerCallback);
                    break;
                case Watcher::SIGNAL:
                    \assert(\is_int($watcher->value));
                    if (isset($this->events[$id])) {
                        $event = $this->events[$id];
                    } else {
                        /** @psalm-suppress UndefinedFunction */
                        $event = $this->events[$id] = \uv_signal_init($this->handle);
                    }
                    $this->watchers[(int) $event] = [$watcher];
                    /** @psalm-suppress UndefinedFunction */
                    \uv_signal_start($event, $this->signalCallback, $watcher->value);
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        $id = $watcher->id;
        if (!isset($this->events[$id])) {
            return;
        }
        $event = $this->events[$id];
        if (!\uv_is_active($event)) {
            return;
        }
        switch ($watcher->type) {
            case Watcher::READABLE:
            case Watcher::WRITABLE:
                $flags = 0;
                foreach ($this->watchers[(int) $event] as $w) {
                    $flags |= $w->enabled ? $w->type : 0;
                }
                if ($flags) {
                    \uv_poll_start($event, $flags, $this->ioCallback);
                } else {
                    \uv_poll_stop($event);
                }
                break;
            case Watcher::DELAY:
            case Watcher::REPEAT:
                \uv_timer_stop($event);
                break;
            case Watcher::SIGNAL:
                \uv_signal_stop($event);
                break;
            default:
                // @codeCoverageIgnoreStart
                throw new \Error("Unknown watcher type");
        }
    }
}<?php

namespace Amp\Loop;

/**
 * MUST be thrown if any operation (except disable() and cancel()) is attempted with an invalid watcher identifier.
 *
 * An invalid watcher identifier is any identifier that is not yet emitted by the driver or cancelled by the user.
 */
class InvalidWatcherError extends \Error
{
    /** @var string */
    private $watcherId;
    /**
     * @param string $watcherId The watcher identifier.
     * @param string $message The exception message.
     */
    public function __construct(string $watcherId, string $message)
    {
        $this->watcherId = $watcherId;
        parent::__construct($message);
    }
    /**
     * @return string The watcher identifier.
     */
    public function getWatcherId()
    {
        return $this->watcherId;
    }
}<?php

namespace Amp\Loop;

use function Amp\Internal\formatStacktrace;
final class TracingDriver extends Driver
{
    /** @var Driver */
    private $driver;
    /** @var true[] */
    private $enabledWatchers = [];
    /** @var true[] */
    private $unreferencedWatchers = [];
    /** @var string[] */
    private $creationTraces = [];
    /** @var string[] */
    private $cancelTraces = [];
    /**
     *
     */
    public function __construct(Driver $driver)
    {
        $this->driver = $driver;
    }
    /**
     *
     */
    public function run()
    {
        $this->driver->run();
    }
    /**
     *
     */
    public function stop()
    {
        $this->driver->stop();
    }
    /**
     *
     */
    public function defer(callable $callback, $data = null) : string
    {
        $id = $this->driver->defer(function (...$args) use($callback) {
            $this->cancel($args[0]);
            return $callback(...$args);
        }, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function delay(int $delay, callable $callback, $data = null) : string
    {
        $id = $this->driver->delay($delay, function (...$args) use($callback) {
            $this->cancel($args[0]);
            return $callback(...$args);
        }, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function repeat(int $interval, callable $callback, $data = null) : string
    {
        $id = $this->driver->repeat($interval, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function onReadable($stream, callable $callback, $data = null) : string
    {
        $id = $this->driver->onReadable($stream, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function onWritable($stream, callable $callback, $data = null) : string
    {
        $id = $this->driver->onWritable($stream, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        $id = $this->driver->onSignal($signo, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function enable(string $watcherId)
    {
        try {
            $this->driver->enable($watcherId);
            $this->enabledWatchers[$watcherId] = true;
        } catch (InvalidWatcherError $e) {
            throw new InvalidWatcherError($watcherId, $e->getMessage() . "\r\n\r\n" . $this->getTraces($watcherId));
        }
    }
    /**
     *
     */
    public function cancel(string $watcherId)
    {
        $this->driver->cancel($watcherId);
        if (!isset($this->cancelTraces[$watcherId])) {
            $this->cancelTraces[$watcherId] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        }
        unset($this->enabledWatchers[$watcherId], $this->unreferencedWatchers[$watcherId]);
    }
    /**
     *
     */
    public function disable(string $watcherId)
    {
        $this->driver->disable($watcherId);
        unset($this->enabledWatchers[$watcherId]);
    }
    /**
     *
     */
    public function reference(string $watcherId)
    {
        try {
            $this->driver->reference($watcherId);
            unset($this->unreferencedWatchers[$watcherId]);
        } catch (InvalidWatcherError $e) {
            throw new InvalidWatcherError($watcherId, $e->getMessage() . "\r\n\r\n" . $this->getTraces($watcherId));
        }
    }
    /**
     *
     */
    public function unreference(string $watcherId)
    {
        $this->driver->unreference($watcherId);
        $this->unreferencedWatchers[$watcherId] = true;
    }
    /**
     *
     */
    public function setErrorHandler(callable $callback = null)
    {
        return $this->driver->setErrorHandler($callback);
    }
    /**
     * @inheritdoc
     */
    public function getHandle()
    {
        $this->driver->getHandle();
    }
    /**
     *
     */
    public function dump() : string
    {
        $dump = "Enabled, referenced watchers keeping the loop running: ";
        foreach ($this->enabledWatchers as $watcher => $_) {
            if (isset($this->unreferencedWatchers[$watcher])) {
                continue;
            }
            $dump .= "Watcher ID: " . $watcher . "\r\n";
            $dump .= $this->getCreationTrace($watcher);
            $dump .= "\r\n\r\n";
        }
        return \rtrim($dump);
    }
    /**
     *
     */
    public function getInfo() : array
    {
        return $this->driver->getInfo();
    }
    /**
     *
     */
    public function __debugInfo()
    {
        return $this->driver->__debugInfo();
    }
    /**
     *
     */
    public function now() : int
    {
        return $this->driver->now();
    }
    /**
     *
     */
    protected function error(\Throwable $exception)
    {
        $this->driver->error($exception);
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        // nothing to do in a decorator
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        // nothing to do in a decorator
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        // nothing to do in a decorator
    }
    /**
     *
     */
    private function getTraces(string $watcherId) : string
    {
        return "Creation Trace:\r\n" . $this->getCreationTrace($watcherId) . '

Cancellation Trace:
' . $this->getCancelTrace($watcherId);
    }
    /**
     *
     */
    private function getCreationTrace(string $watcher) : string
    {
        if (!isset($this->creationTraces[$watcher])) {
            return 'No creation trace, yet.';
        }
        return $this->creationTraces[$watcher];
    }
    /**
     *
     */
    private function getCancelTrace(string $watcher) : string
    {
        if (!isset($this->cancelTraces[$watcher])) {
            return 'No cancellation trace, yet.';
        }
        return $this->cancelTraces[$watcher];
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a promise from a generator function yielding promises.
 *
 * When a promise is yielded, execution of the generator is interrupted until the promise is resolved. A success
 * value is sent into the generator, while a failure reason is thrown into the generator. Using a coroutine,
 * asynchronous code can be written without callbacks and be structured like synchronous code.
 *
 * @template-covariant TReturn
 * @template-implements Promise<TReturn>
 */
final class Coroutine implements Promise
{
    use Internal\Placeholder;
    /**
    * Attempts to transform the non-promise yielded from the generator into a promise, otherwise returns an instance
    `Amp\Failure` failed with an instance of `Amp\InvalidYieldError`.
    *
    * @param mixed $yielded Non-promise yielded from generator.
    * @param \Generator $generator No type for performance, we already know the type.
    *
    * @return Promise
    */
    private static function transform($yielded, $generator) : Promise
    {
        $exception = null;
        // initialize here, see https://github.com/vimeo/psalm/issues/2951
        try {
            if (\is_array($yielded)) {
                return Promise\all($yielded);
            }
            if ($yielded instanceof ReactPromise) {
                return Promise\adapt($yielded);
            }
            // No match, continue to returning Failure below.
        } catch (\Throwable $exception) {
            // Conversion to promise failed, fall-through to returning Failure below.
        }
        return new Failure(new InvalidYieldError($generator, \sprintf("Unexpected yield; Expected an instance of %s or %s or an array of such instances", Promise::class, ReactPromise::class), $exception));
    }
    /**
     * @param \Generator $generator
     * @psalm-param \Generator<mixed, (Promise | ReactPromise | array<array-key, (Promise | ReactPromise)>), mixed, (Promise<TReturn> | ReactPromise | TReturn)> $generator
     */
    public function __construct(\Generator $generator)
    {
        try {
            $yielded = $generator->current();
            if (!$yielded instanceof Promise) {
                if (!$generator->valid()) {
                    $this->resolve($generator->getReturn());
                    return;
                }
                $yielded = self::transform($yielded, $generator);
            }
        } catch (\Throwable $exception) {
            $this->fail($exception);
            return;
        }
        /**
         * @param \Throwable|null $e Exception to be thrown into the generator.
         * @param mixed           $v Value to be sent into the generator.
         *
         * @return void
         *
         * @psalm-suppress MissingClosureParamType
         * @psalm-suppress MissingClosureReturnType
         */
        $onResolve = function (\Throwable $e = null, $v) use($generator, &$onResolve) {
            /** @var bool $immediate Used to control iterative coroutine continuation. */
            static $immediate = true;
            /** @var \Throwable|null $exception Promise failure reason when executing next coroutine step, null at all other times. */
            static $exception;
            /** @var mixed $value Promise success value when executing next coroutine step, null at all other times. */
            static $value;
            $exception = $e;
            /** @psalm-suppress MixedAssignment */
            $value = $v;
            if (!$immediate) {
                $immediate = true;
                return;
            }
            try {
                try {
                    do {
                        if ($exception) {
                            // Throw exception at current execution point.
                            $yielded = $generator->throw($exception);
                        } else {
                            // Send the new value and execute to next yield statement.
                            $yielded = $generator->send($value);
                        }
                        if (!$yielded instanceof Promise) {
                            if (!$generator->valid()) {
                                $this->resolve($generator->getReturn());
                                $onResolve = null;
                                return;
                            }
                            $yielded = self::transform($yielded, $generator);
                        }
                        $immediate = false;
                        $yielded->onResolve($onResolve);
                    } while ($immediate);
                    $immediate = true;
                } catch (\Throwable $exception) {
                    $this->fail($exception);
                    $onResolve = null;
                } finally {
                    $exception = null;
                    $value = null;
                }
            } catch (\Throwable $e) {
                Loop::defer(static function () use($e) {
                    throw $e;
                });
            }
        };
        try {
            $yielded->onResolve($onResolve);
            unset($generator, $yielded, $onResolve);
        } catch (\Throwable $e) {
            Loop::defer(static function () use($e) {
                throw $e;
            });
        }
    }
}<?php

namespace Amp;

/**
 * Cancellation tokens are simple objects that allow registering handlers to subscribe to cancellation requests.
 */
interface CancellationToken
{
    /**
    * Subscribes a new handler to be invoked on a cancellation request.
    *
    * This handler might be invoked immediately in case the token has already been cancelled. Returned generators will
    automatically be run as coroutines. Any unhandled exceptions will be throw into the event loop.
    *
    * @param callable(CancelledException) $callback Callback to be invoked on a cancellation request. Will receive a
    `CancelledException` as first argument that may be used to fail the operation's promise.
    *
    * @return string Identifier that can be used to cancel the subscription.
    */
    public function subscribe(callable $callback) : string;
    /**
     * Unsubscribes a previously registered handler.
     *
     * The handler will no longer be called as long as this method isn't invoked from a subscribed callback.
     *
     * @param string $id
     *
     * @return void
     */
    public function unsubscribe(string $id);
    /**
     * Returns whether cancellation has been requested yet.
     *
     * @return bool
     */
    public function isRequested() : bool;
    /**
     * Throws the `CancelledException` if cancellation has been requested, otherwise does nothing.
     *
     * @return void
     *
     * @throws CancelledException
     */
    public function throwIfRequested();
}<?php

namespace Amp;

/**
 * Deferred is a container for a promise that is resolved using the resolve() and fail() methods of this object.
 * The contained promise may be accessed using the promise() method. This object should not be part of a public
 * API, but used internally to create and resolve a promise.
 *
 * @template TValue
 */
final class Deferred
{
    /** @var Promise<TValue> Has public resolve and fail methods. */
    private $resolver;
    /** @var Promise<TValue> Hides placeholder methods */
    private $promise;
    /**
     *
     */
    public function __construct()
    {
        $this->resolver = new class implements Promise
        {
            use Internal\Placeholder {
                resolve as public;
                fail as public;
                isResolved as public;
            }
        };
        $this->promise = new Internal\PrivatePromise($this->resolver);
    }
    /**
     * @return Promise<TValue>
     */
    public function promise() : Promise
    {
        return $this->promise;
    }
    /**
     * Fulfill the promise with the given value.
     *
     * @param mixed $value
     *
     * @psalm-param (TValue | Promise<TValue>) $value
     *
     * @return void
     */
    public function resolve($value = null)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->resolver->resolve($value);
    }
    /**
     * Fails the promise the the given reason.
     *
     * @param \Throwable $reason
     *
     * @return void
     */
    public function fail(\Throwable $reason)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->resolver->fail($reason);
    }
    /**
     * @return bool True if the promise has been resolved.
     */
    public function isResolved() : bool
    {
        return $this->resolver->isResolved();
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a failed promise using the given exception.
 *
 * @template-covariant TValue
 * @template-implements Promise<TValue>
 */
final class Failure implements Promise
{
    /** @var \Throwable $exception */
    private $exception;
    /**
     * @param \Throwable $exception Rejection reason.
     */
    public function __construct(\Throwable $exception)
    {
        $this->exception = $exception;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        try {
            /** @var mixed $result */
            $result = $onResolved($this->exception, null);
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
}<?php

namespace Amp;

class MultiReasonException extends \Exception
{
    /** @var \Throwable[] */
    private $reasons;
    /**
     * @param \Throwable[] $reasons Array of exceptions rejecting the promise.
     * @param (string | null) $message
     */
    public function __construct(array $reasons, string $message = null)
    {
        parent::__construct($message ?: "Multiple errors encountered; use " . self::class . "::getReasons() to retrieve the array of exceptions thrown");
        $this->reasons = $reasons;
    }
    /**
     * @return \Throwable[]
     */
    public function getReasons() : array
    {
        return $this->reasons;
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
/**
* Returns a new function that wraps $callback in a promise/coroutine-aware function that automatically runs
Generators as coroutines. The returned function always returns a promise when invoked. Errors have to be handled
by the callback caller or they will go unnoticed.
*
* Use this function to create a coroutine-aware callable for a promise-aware callback caller.
*
* @template TReturn
* @template TPromise
* @template TGeneratorReturn
* @template TGeneratorPromise
*
* @template TGenerator of (TGeneratorReturn | Promise<TGeneratorPromise>)
* @template T of (TReturn | Promise<TPromise> | \Generator<mixed, mixed, mixed, TGenerator>)
*
* @formatter :off
*
* @param callable(...mixed): T $callback
*
* @return callable
* @psalm-return (T is Promise ? (callable(mixed...): Promise<TPromise>) : (T is \Generator ? (TGenerator is Promise ? (callable(mixed...): Promise<TGeneratorPromise>) : (callable(mixed...): Promise<TGeneratorReturn>)) : (callable(mixed...): Promise<TReturn>)))
*
* @formatter :on
*
* @see asyncCoroutine()
*
* @psalm-suppress InvalidReturnType
*/
function coroutine(callable $callback) : callable
{
    /** @psalm-suppress InvalidReturnStatement */
    return static function (...$args) use($callback) : Promise {
        return call($callback, ...$args);
    };
}
/**
* Returns a new function that wraps $callback in a promise/coroutine-aware function that automatically runs
Generators as coroutines. The returned function always returns void when invoked. Errors are forwarded to the
loop's error handler using `Amp\Promise\rethrow()`.
*
* Use this function to create a coroutine-aware callable for a non-promise-aware callback caller.
*
* @param callable(...mixed): mixed $callback
*
* @return callable
* @psalm-return callable(mixed ...): void
*
* @see coroutine()
*/
function asyncCoroutine(callable $callback) : callable
{
    return static function (...$args) use($callback) {
        Promise\rethrow(call($callback, ...$args));
    };
}
/**
* Calls the given function, always returning a promise. If the function returns a Generator, it will be run as a
coroutine. If the function throws, a failed promise will be returned.
*
* @template TReturn
* @template TPromise
* @template TGeneratorReturn
* @template TGeneratorPromise
*
* @template TGenerator of (TGeneratorReturn | Promise<TGeneratorPromise>)
* @template T of (TReturn | Promise<TPromise> | \Generator<mixed, mixed, mixed, TGenerator>)
*
* @formatter :off
*
* @param callable(...mixed): T $callback
* @param mixed ...$args Arguments to pass to the function.
*
* @return Promise
* @psalm-return (T is Promise ? Promise<TPromise> : (T is \Generator ? (TGenerator is Promise ? Promise<TGeneratorPromise> : Promise<TGeneratorReturn>) : Promise<TReturn>))
*
* @formatter :on
*/
function call(callable $callback, ...$args) : Promise
{
    try {
        $result = $callback(...$args);
    } catch (\Throwable $exception) {
        return new Failure($exception);
    }
    if ($result instanceof \Generator) {
        return new Coroutine($result);
    }
    if ($result instanceof Promise) {
        return $result;
    }
    if ($result instanceof ReactPromise) {
        return Promise\adapt($result);
    }
    return new Success($result);
}
/**
* Calls the given function. If the function returns a Generator, it will be run as a coroutine. If the function
throws or returns a failing promise, the failure is forwarded to the loop error handler.
*
* @param callable(...mixed): mixed $callback
* @param mixed ...$args Arguments to pass to the function.
*
* @return void
*/
function asyncCall(callable $callback, ...$args)
{
    Promise\rethrow(call($callback, ...$args));
}
/**
 * Sleeps for the specified number of milliseconds.
 *
 * @param int $milliseconds
 *
 * @return Delayed
 */
function delay(int $milliseconds) : Delayed
{
    return new Delayed($milliseconds);
}
/**
 * Returns the current time relative to an arbitrary point in time.
 *
 * @return int Time in milliseconds.
 */
function getCurrentTime() : int
{
    return Internal\getCurrentTime();
}
namespace Amp\Promise;

use Amp\Deferred;
use Amp\Loop;
use Amp\MultiReasonException;
use Amp\Promise;
use Amp\Success;
use Amp\TimeoutException;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\call;
use function Amp\Internal\createTypeError;
/**
* Registers a callback that will forward the failure reason to the event loop's error handler if the promise fails.
*
* Use this function if you neither return the promise nor handle a possible error yourself to prevent errors from
going entirely unnoticed.
*
* @param (Promise | ReactPromise) $promise Promise to register the handler on.
*
* @return void
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
*
*/
function rethrow($promise)
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $promise->onResolve(static function ($exception) {
        if ($exception) {
            throw $exception;
        }
    });
}
/**
* Runs the event loop until the promise is resolved. Should not be called within a running event loop.
*
* Use this function only in synchronous contexts to wait for an asynchronous operation. Use coroutines and yield to
await promise resolution in a fully asynchronous application instead.
*
* @template TPromise
* @template T of (Promise<TPromise> | ReactPromise)
*
* @param (Promise | ReactPromise) $promise Promise to wait for.
*
* @return mixed Promise success value.
*
* @psalm-param T $promise
* @psalm-return (T is Promise ? TPromise : mixed)
*
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
* @throws \Error If the event loop stopped without the $promise being resolved.
* @throws \Throwable Promise failure reason.
*/
function wait($promise)
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $resolved = false;
    try {
        Loop::run(function () use(&$resolved, &$value, &$exception, $promise) {
            $promise->onResolve(function ($e, $v) use(&$resolved, &$value, &$exception) {
                Loop::stop();
                $resolved = true;
                $exception = $e;
                $value = $v;
            });
        });
    } catch (\Throwable $throwable) {
        throw new \Error("Loop exceptionally stopped without resolving the promise", 0, $throwable);
    }
    if (!$resolved) {
        throw new \Error("Loop stopped without resolving the promise");
    }
    if ($exception) {
        throw $exception;
    }
    return $value;
}
/**
* Creates an artificial timeout for any `Promise`.
*
* If the timeout expires before the promise is resolved, the returned promise fails with an instance of
`Amp\TimeoutException`.
*
* @template TReturn
*
* @param (Promise<TReturn> | ReactPromise) $promise Promise to which the timeout is applied.
* @param int $timeout Timeout in milliseconds.
*
* @return Promise<TReturn>
*
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
*/
function timeout($promise, int $timeout) : Promise
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $deferred = new Deferred();
    $watcher = Loop::delay($timeout, static function () use(&$deferred) {
        $temp = $deferred;
        // prevent double resolve
        $deferred = null;
        $temp->fail(new TimeoutException());
    });
    Loop::unreference($watcher);
    $promise->onResolve(function () use(&$deferred, $promise, $watcher) {
        if ($deferred !== null) {
            Loop::cancel($watcher);
            $deferred->resolve($promise);
        }
    });
    return $deferred->promise();
}
/**
 * Creates an artificial timeout for any `Promise`.
 *
 * If the promise is resolved before the timeout expires, the result is returned
 *
 * If the timeout expires before the promise is resolved, a default value is returned
 *
 * @template TReturn
 *
 * @param (Promise<TReturn> | ReactPromise) $promise Promise to which the timeout is applied.
 * @param int $timeout Timeout in milliseconds.
 * @param TReturn $default
 *
 * @return Promise<TReturn>
 *
 * @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
 */
function timeoutWithDefault($promise, int $timeout, $default = null) : Promise
{
    $promise = timeout($promise, $timeout);
    return call(static function () use($promise, $default) {
        try {
            return (yield $promise);
        } catch (TimeoutException $exception) {
            return $default;
        }
    });
}
/**
* Adapts any object with a done(callable $onFulfilled, callable $onRejected) or then(callable $onFulfilled,
callable $onRejected) method to a promise usable by components depending on placeholders implementing
\AsyncInterop\Promise.
*
* @param object $promise Object with a done() or then() method.
*
* @return Promise Promise resolved by the $thenable object.
*
* @throws \Error If the provided object does not have a then() method.
*/
function adapt($promise) : Promise
{
    if (!\is_object($promise)) {
        throw new \Error("Object must be provided");
    }
    $deferred = new Deferred();
    if (\method_exists($promise, 'done')) {
        $promise->done([$deferred, 'resolve'], [$deferred, 'fail']);
    } elseif (\method_exists($promise, 'then')) {
        $promise->then([$deferred, 'resolve'], [$deferred, 'fail']);
    } else {
        throw new \Error("Object must have a 'then' or 'done' method");
    }
    return $deferred->promise();
}
/**
* Returns a promise that is resolved when all promises are resolved. The returned promise will not fail.
Returned promise succeeds with a two-item array delineating successful and failed promise results,
with keys identical and corresponding to the original given array.
*
* This function is the same as some() with the notable exception that it will never fail even
if all promises in the array resolve unsuccessfully.
*
* @template TValue
*
* @param (Promise<TValue>[] | ReactPromise[]) $promises
*
* @return Promise<array{0: \Throwable[], 1: TValue[]}>
*
* @throws \Error If a non-Promise is in the array.
*/
function any(array $promises) : Promise
{
    return some($promises, 0);
}
/**
* Returns a promise that succeeds when all promises succeed, and fails if any promise fails. Returned
promise succeeds with an array of values used to succeed each contained promise, with keys corresponding to
the array of promises.
*
* @param (Promise[] | ReactPromise[]) $promises Array of only promises.
*
* @return Promise
*
* @throws \Error If a non-Promise is in the array.
*
* @template TValue
*
* @psalm-param array<array-key, (Promise<TValue> | ReactPromise)> $promises
* @psalm-assert array<array-key, Promise<TValue>|ReactPromise> $promises $promises
* @psalm-return Promise<array<array-key, TValue>>
*/
function all(array $promises) : Promise
{
    if (empty($promises)) {
        return new Success([]);
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $pending = \count($promises);
    $values = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $values[$key] = null;
        // add entry to array to preserve order
        $promise->onResolve(function ($exception, $value) use(&$deferred, &$values, &$pending, $key) {
            if ($pending === 0) {
                return;
            }
            if ($exception) {
                $pending = 0;
                $deferred->fail($exception);
                $deferred = null;
                return;
            }
            $values[$key] = $value;
            if (0 === --$pending) {
                $deferred->resolve($values);
            }
        });
    }
    return $result;
}
/**
 * Returns a promise that succeeds when the first promise succeeds, and fails only if all promises fail.
 *
 * @template TValue
 *
 * @param (Promise<TValue>[] | ReactPromise[]) $promises Array of only promises.
 *
 * @return Promise<TValue>
 *
 * @throws \Error If the array is empty or a non-Promise is in the array.
 */
function first(array $promises) : Promise
{
    if (empty($promises)) {
        throw new \Error("No promises provided");
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $pending = \count($promises);
    $exceptions = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $exceptions[$key] = null;
        // add entry to array to preserve order
        $promise->onResolve(function ($error, $value) use(&$deferred, &$exceptions, &$pending, $key) {
            if ($pending === 0) {
                return;
            }
            if (!$error) {
                $pending = 0;
                $deferred->resolve($value);
                $deferred = null;
                return;
            }
            $exceptions[$key] = $error;
            if (0 === --$pending) {
                $deferred->fail(new MultiReasonException($exceptions));
            }
        });
    }
    return $result;
}
/**
* Resolves with a two-item array delineating successful and failed Promise results.
*
* The returned promise will only fail if the given number of required promises fail.
*
* @template TValue
*
* @param (Promise<TValue>[] | ReactPromise[]) $promises Array of only promises.
* @param int $required Number of promises that must succeed for the
returned promise to succeed.
*
* @return Promise<array{0: \Throwable[], 1: TValue[]}>
*
* @throws \Error If a non-Promise is in the array.
*/
function some(array $promises, int $required = 1) : Promise
{
    if ($required < 0) {
        throw new \Error("Number of promises required must be non-negative");
    }
    $pending = \count($promises);
    if ($required > $pending) {
        throw new \Error("Too few promises provided");
    }
    if (empty($promises)) {
        return new Success([[], []]);
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $values = [];
    $exceptions = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $values[$key] = $exceptions[$key] = null;
        // add entry to arrays to preserve order
        $promise->onResolve(static function ($exception, $value) use(&$values, &$exceptions, &$pending, $key, $required, $deferred) {
            if ($exception) {
                $exceptions[$key] = $exception;
                unset($values[$key]);
            } else {
                $values[$key] = $value;
                unset($exceptions[$key]);
            }
            if (0 === --$pending) {
                if (\count($values) < $required) {
                    $deferred->fail(new MultiReasonException($exceptions));
                } else {
                    $deferred->resolve([$exceptions, $values]);
                }
            }
        });
    }
    return $result;
}
/**
 * Wraps a promise into another promise, altering the exception or result.
 *
 * @param (Promise | ReactPromise) $promise
 * @param callable $callback
 *
 * @return Promise
 */
function wrap($promise, callable $callback) : Promise
{
    if ($promise instanceof ReactPromise) {
        $promise = adapt($promise);
    } elseif (!$promise instanceof Promise) {
        throw createTypeError([Promise::class, ReactPromise::class], $promise);
    }
    $deferred = new Deferred();
    $promise->onResolve(static function (\Throwable $exception = null, $result) use($deferred, $callback) {
        try {
            $result = $callback($exception, $result);
        } catch (\Throwable $exception) {
            $deferred->fail($exception);
            return;
        }
        $deferred->resolve($result);
    });
    return $deferred->promise();
}
namespace Amp\Iterator;

use Amp\Delayed;
use Amp\Emitter;
use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use function Amp\call;
use function Amp\coroutine;
use function Amp\Internal\createTypeError;
/**
* Creates an iterator from the given iterable, emitting the each value. The iterable may contain promises. If any
promise fails, the iterator will fail with the same reason.
*
* @param (array | \Traversable) $iterable Elements to emit.
* @param int $delay Delay between element emissions in milliseconds.
*
* @return Iterator
*
* @throws \TypeError If the argument is not an array or instance of \Traversable.
*/
function fromIterable($iterable, int $delay = 0) : Iterator
{
    if (!$iterable instanceof \Traversable && !\is_array($iterable)) {
        throw createTypeError(["array", "Traversable"], $iterable);
    }
    if ($delay) {
        return new Producer(static function (callable $emit) use($iterable, $delay) {
            foreach ($iterable as $value) {
                (yield new Delayed($delay));
                (yield $emit($value));
            }
        });
    }
    return new Producer(static function (callable $emit) use($iterable) {
        foreach ($iterable as $value) {
            (yield $emit($value));
        }
    });
}
/**
 * @template TValue
 * @template TReturn
 *
 * @param Iterator<TValue> $iterator
 * @param callable(TValue $value): TReturn $onEmit
 *
 * @return Iterator<TReturn>
 */
function map(Iterator $iterator, callable $onEmit) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $onEmit) {
        while ((yield $iterator->advance())) {
            (yield $emit($onEmit($iterator->getCurrent())));
        }
    });
}
/**
 * @template TValue
 *
 * @param Iterator<TValue> $iterator
 * @param callable(TValue $value): bool $filter
 *
 * @return Iterator<TValue>
 */
function filter(Iterator $iterator, callable $filter) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $filter) {
        while ((yield $iterator->advance())) {
            if ($filter($iterator->getCurrent())) {
                (yield $emit($iterator->getCurrent()));
            }
        }
    });
}
/**
 * Creates an iterator that emits values emitted from any iterator in the array of iterators.
 *
 * @param Iterator[] $iterators
 *
 * @return Iterator
 */
function merge(array $iterators) : Iterator
{
    $emitter = new Emitter();
    $result = $emitter->iterate();
    $coroutine = coroutine(static function (Iterator $iterator) use(&$emitter) {
        while ((yield $iterator->advance()) && $emitter !== null) {
            (yield $emitter->emit($iterator->getCurrent()));
        }
    });
    $coroutines = [];
    foreach ($iterators as $iterator) {
        if (!$iterator instanceof Iterator) {
            throw createTypeError([Iterator::class], $iterator);
        }
        $coroutines[] = $coroutine($iterator);
    }
    Promise\all($coroutines)->onResolve(static function ($exception) use(&$emitter) {
        if ($exception) {
            $emitter->fail($exception);
            $emitter = null;
        } else {
            $emitter->complete();
        }
    });
    return $result;
}
/**
* Concatenates the given iterators into a single iterator, emitting values from a single iterator at a time. The
prior iterator must complete before values are emitted from any subsequent iterators. Iterators are concatenated
in the order given (iteration order of the array).
*
* @param Iterator[] $iterators
*
* @return Iterator
*/
function concat(array $iterators) : Iterator
{
    foreach ($iterators as $iterator) {
        if (!$iterator instanceof Iterator) {
            throw createTypeError([Iterator::class], $iterator);
        }
    }
    $emitter = new Emitter();
    $previous = [];
    $promise = Promise\all($previous);
    $coroutine = coroutine(static function (Iterator $iterator, callable $emit) {
        while ((yield $iterator->advance())) {
            (yield $emit($iterator->getCurrent()));
        }
    });
    foreach ($iterators as $iterator) {
        $emit = coroutine(static function ($value) use($emitter, $promise) {
            static $pending = true, $failed = false;
            if ($failed) {
                return;
            }
            if ($pending) {
                try {
                    (yield $promise);
                    $pending = false;
                } catch (\Throwable $exception) {
                    $failed = true;
                    return;
                    // Prior iterator failed.
                }
            }
            (yield $emitter->emit($value));
        });
        $previous[] = $coroutine($iterator, $emit);
        $promise = Promise\all($previous);
    }
    $promise->onResolve(static function ($exception) use($emitter) {
        if ($exception) {
            $emitter->fail($exception);
            return;
        }
        $emitter->complete();
    });
    return $emitter->iterate();
}
/**
 * Discards all remaining items and returns the number of discarded items.
 *
 * @template TValue
 *
 * @param Iterator $iterator
 *
 * @return Promise
 *
 * @psalm-param Iterator<TValue> $iterator
 * @psalm-return Promise<int>
 */
function discard(Iterator $iterator) : Promise
{
    return call(static function () use($iterator) : \Generator {
        $count = 0;
        while ((yield $iterator->advance())) {
            $count++;
        }
        return $count;
    });
}
/**
 * Collects all items from an iterator into an array.
 *
 * @template TValue
 *
 * @param Iterator $iterator
 *
 * @psalm-param Iterator<TValue> $iterator
 *
 * @return Promise
 * @psalm-return Promise<array<array-key, TValue>>
 */
function toArray(Iterator $iterator) : Promise
{
    return call(static function () use($iterator) {
        /** @psalm-var list $array */
        $array = [];
        while ((yield $iterator->advance())) {
            $array[] = $iterator->getCurrent();
        }
        return $array;
    });
}<?php

namespace Amp;

class InvalidYieldError extends \Error
{
    /**
     * @param \Generator $generator
     * @param string $prefix
     * @param (\Throwable | null) $previous
     */
    public function __construct(\Generator $generator, string $prefix, \Throwable $previous = null)
    {
        $yielded = $generator->current();
        $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), \var_export($generator->key(), true));
        if (!$generator->valid()) {
            parent::__construct($prefix, 0, $previous);
            return;
        }
        $reflGen = new \ReflectionGenerator($generator);
        $exeGen = $reflGen->getExecutingGenerator();
        if ($isSubgenerator = $exeGen !== $generator) {
            $reflGen = new \ReflectionGenerator($exeGen);
        }
        parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile()), 0, $previous);
    }
}<?php

namespace Amp;

final class CombinedCancellationToken implements CancellationToken
{
    /** @var array{0: CancellationToken, 1: string}[] */
    private $tokens = [];
    /** @var string */
    private $nextId = "a";
    /** @var callable[] */
    private $callbacks = [];
    /** @var CancelledException|null */
    private $exception;
    /**
     *
     */
    public function __construct(CancellationToken ...$tokens)
    {
        foreach ($tokens as $token) {
            $id = $token->subscribe(function (CancelledException $exception) {
                $this->exception = $exception;
                $callbacks = $this->callbacks;
                $this->callbacks = [];
                foreach ($callbacks as $callback) {
                    asyncCall($callback, $this->exception);
                }
            });
            $this->tokens[] = [$token, $id];
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        foreach ($this->tokens as list($token, $id)) {
            /** @var CancellationToken $token */
            $token->unsubscribe($id);
        }
    }
    /**
     * @inheritdoc
     */
    public function subscribe(callable $callback) : string
    {
        $id = $this->nextId++;
        if ($this->exception) {
            asyncCall($callback, $this->exception);
        } else {
            $this->callbacks[$id] = $callback;
        }
        return $id;
    }
    /**
     * @inheritdoc
     */
    public function unsubscribe(string $id)
    {
        unset($this->callbacks[$id]);
    }
    /**
     * @inheritdoc
     */
    public function isRequested() : bool
    {
        foreach ($this->tokens as list($token)) {
            if ($token->isRequested()) {
                return true;
            }
        }
        return false;
    }
    /**
     * @inheritdoc
     */
    public function throwIfRequested()
    {
        foreach ($this->tokens as list($token)) {
            $token->throwIfRequested();
        }
    }
}<?php

namespace Amp;

/**
 * Thrown if a promise doesn't resolve within a specified timeout.
 *
 * @see \Amp\Promise\timeout()
 */
class TimeoutException extends \Exception
{
    /**
     * @param string $message Exception message.
     */
    public function __construct(string $message = "Operation timed out")
    {
        parent::__construct($message);
    }
}<?php

namespace Amp;

use Amp\Loop\Driver;
use Amp\Loop\DriverFactory;
use Amp\Loop\InvalidWatcherError;
use Amp\Loop\UnsupportedFeatureException;
use Amp\Loop\Watcher;
/**
 * Accessor to allow global access to the event loop.
 *
 * @see \Amp\Loop\Driver
 */
final class Loop
{
    /**
     * @var Driver
     */
    private static $driver;
    /**
     * Disable construction as this is a static class.
     */
    private function __construct()
    {
        // intentionally left blank
    }
    /**
     * Sets the driver to be used for `Loop::run()`.
     *
     * @param Driver $driver
     *
     * @return void
     */
    public static function set(Driver $driver)
    {
        try {
            self::$driver = new class extends Driver
            {
                /**
                 * @return void
                 */
                protected function activate(array $watchers)
                {
                    throw new \Error("Can't activate watcher during garbage collection.");
                }
                /**
                 * @return void
                 */
                protected function dispatch(bool $blocking)
                {
                    throw new \Error("Can't dispatch during garbage collection.");
                }
                /**
                 * @return void
                 */
                protected function deactivate(Watcher $watcher)
                {
                    // do nothing
                }
                /**
                 *
                 */
                public function getHandle()
                {
                    return null;
                }
            };
            \gc_collect_cycles();
        } finally {
            self::$driver = $driver;
        }
    }
    /**
    * Run the event loop and optionally execute a callback within the scope of it.
    *
    * The loop MUST continue to run until it is either stopped explicitly, no referenced watchers exist anymore, or an
    exception is thrown that cannot be handled. Exceptions that cannot be handled are exceptions thrown from an
    error handler or exceptions that would be passed to an error handler but none exists to handle them.
    *
    * @param (callable | null) $callback The callback to execute.
    *
    * @return void
    */
    public static function run(callable $callback = null)
    {
        if ($callback) {
            self::$driver->defer($callback);
        }
        self::$driver->run();
    }
    /**
    * Stop the event loop.
    *
    * When an event loop is stopped, it continues with its current tick and exits the loop afterwards. Multiple calls
    to stop MUST be ignored and MUST NOT raise an exception.
    *
    * @return void
    */
    public static function stop()
    {
        self::$driver->stop();
    }
    /**
    * Defer the execution of a callback.
    *
    * The deferred callable MUST be executed before any other type of watcher in a tick. Order of enabling MUST be
    preserved when executing the callbacks.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param callable(string $watcherId, mixed $data) $callback The callback to defer. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function defer(callable $callback, $data = null) : string
    {
        return self::$driver->defer($callback, $data);
    }
    /**
    * Delay the execution of a callback.
    *
    * The delay is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be determined by which
    timers expire first, but timers with the same expiration time MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $delay The amount of time, in milliseconds, to delay the execution for.
    * @param callable(string $watcherId, mixed $data) $callback The callback to delay. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function delay(int $delay, callable $callback, $data = null) : string
    {
        return self::$driver->delay($delay, $callback, $data);
    }
    /**
    * Repeatedly execute a callback.
    *
    * The interval between executions is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be
    determined by which timers expire first, but timers with the same expiration time MAY be executed in any order.
    The first execution is scheduled after the first interval period.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $interval The time interval, in milliseconds, to wait between executions.
    * @param callable(string $watcherId, mixed $data) $callback The callback to repeat.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function repeat(int $interval, callable $callback, $data = null) : string
    {
        return self::$driver->repeat($interval, $callback, $data);
    }
    /**
    * Execute a callback when a stream resource becomes readable or is closed for reading.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable(string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function onReadable($stream, callable $callback, $data = null) : string
    {
        return self::$driver->onReadable($stream, $callback, $data);
    }
    /**
    * Execute a callback when a stream resource becomes writable or is closed for writing.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable(string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function onWritable($stream, callable $callback, $data = null) : string
    {
        return self::$driver->onWritable($stream, $callback, $data);
    }
    /**
    * Execute a callback when a signal is received.
    *
    * Warning: Installing the same signal on different instances of this interface is deemed undefined behavior.
    Implementations MAY try to detect this, if possible, but are not required to. This is due to technical
    limitations of the signals being registered globally per process.
    *
    * Multiple watchers on the same signal MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $signo The signal number to monitor.
    * @param callable(string $watcherId, int $signo, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the $data parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    *
    * @throws UnsupportedFeatureException If signal handling is not supported.
    */
    public static function onSignal(int $signo, callable $callback, $data = null) : string
    {
        return self::$driver->onSignal($signo, $callback, $data);
    }
    /**
    * Enable a watcher to be active starting in the next tick.
    *
    * Watchers MUST immediately be marked as enabled, but only be activated (i.e. callbacks can be called) right before
    the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public static function enable(string $watcherId)
    {
        self::$driver->enable($watcherId);
    }
    /**
    * Disable a watcher immediately.
    *
    * A watcher MUST be disabled immediately, e.g. if a defer watcher disables a later defer watcher, the second defer
    watcher isn't executed in this tick.
    *
    * Disabling a watcher MUST NOT invalidate the watcher. Calling this function MUST NOT fail, even if passed an
    invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function disable(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->disable($watcherId);
    }
    /**
    * Cancel a watcher.
    *
    * This will detatch the event loop from all resources that are associated to the watcher. After this operation the
    watcher is permanently invalid. Calling this function MUST NOT fail, even if passed an invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function cancel(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->cancel($watcherId);
    }
    /**
    * Reference a watcher.
    *
    * This will keep the event loop alive whilst the watcher is still being monitored. Watchers have this state by
    default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public static function reference(string $watcherId)
    {
        self::$driver->reference($watcherId);
    }
    /**
    * Unreference a watcher.
    *
    * The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers
    are all referenced by default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function unreference(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->unreference($watcherId);
    }
    /**
    * Returns the current loop time in millisecond increments. Note this value does not necessarily correlate to
    wall-clock time, rather the value returned is meant to be used in relative comparisons to prior values returned
    by this method (intervals, expiration calculations, etc.) and is only updated once per loop tick.
    *
    * @return int
    */
    public static function now() : int
    {
        return self::$driver->now();
    }
    /**
    * Stores information in the loop bound registry.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    * @param mixed $value The value to be stored.
    *
    * @return void
    */
    public static function setState(string $key, $value)
    {
        self::$driver->setState($key, $value);
    }
    /**
    * Gets information stored bound to the loop.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    *
    * @return mixed The previously stored value or `null` if it doesn't exist.
    */
    public static function getState(string $key)
    {
        return self::$driver->getState($key);
    }
    /**
    * Set a callback to be executed when an error occurs.
    *
    * The callback receives the error as the first and only parameter. The return value of the callback gets ignored.
    If it can't handle the error, it MUST throw the error. Errors thrown by the callback or during its invocation
    MUST be thrown into the `run` loop and stop the driver.
    *
    * Subsequent calls to this method will overwrite the previous handler.
    *
    * @param callable(\Throwable $error)|null $callback The callback to execute. `null` will clear the
    current handler.
    *
    * @return callable (\Throwable $error)|null The previous handler, `null` if there was none.
    */
    public static function setErrorHandler(callable $callback = null)
    {
        return self::$driver->setErrorHandler($callback);
    }
    /**
    * Retrieve an associative array of information about the event loop driver.
    *
    * The returned array MUST contain the following data describing the driver's currently registered watchers:
    *
    * [
    "defer"            => ["enabled" => int, "disabled" => int],
    "delay"            => ["enabled" => int, "disabled" => int],
    "repeat"           => ["enabled" => int, "disabled" => int],
    "on_readable"      => ["enabled" => int, "disabled" => int],
    "on_writable"      => ["enabled" => int, "disabled" => int],
    "on_signal"        => ["enabled" => int, "disabled" => int],
    "enabled_watchers" => ["referenced" => int, "unreferenced" => int],
    "running"          => bool
    ];
    *
    * Implementations MAY optionally add more information in the array but at minimum the above `key => value` format
    MUST always be provided.
    *
    * @return array Statistics about the loop in the described format.
    */
    public static function getInfo() : array
    {
        return self::$driver->getInfo();
    }
    /**
     * Retrieve the event loop driver that is in scope.
     *
     * @return Driver
     */
    public static function get() : Driver
    {
        return self::$driver;
    }
}
// Default factory, don't move this to a file loaded by the composer "files" autoload mechanism, otherwise custom
// implementations might have issues setting a default loop, because it's overridden by us then.
// @codeCoverageIgnoreStart
Loop::set((new DriverFactory())->create());
// @codeCoverageIgnoreEnd<?php

namespace Amp;

/**
 * Creates a promise that resolves itself with a given value after a number of milliseconds.
 *
 * @template-covariant TReturn
 * @template-implements Promise<TReturn>
 */
final class Delayed implements Promise
{
    use Internal\Placeholder;
    /** @var string|null Event loop watcher identifier. */
    private $watcher;
    /**
     * @param int $time Milliseconds before succeeding the promise.
     * @param TReturn $value Succeed the promise with this value.
     */
    public function __construct(int $time, $value = null)
    {
        $this->watcher = Loop::delay($time, function () use($value) {
            $this->watcher = null;
            $this->resolve($value);
        });
    }
    /**
     * References the internal watcher in the event loop, keeping the loop running while this promise is pending.
     *
     * @return self
     */
    public function reference() : self
    {
        if ($this->watcher !== null) {
            Loop::reference($this->watcher);
        }
        return $this;
    }
    /**
    * Unreferences the internal watcher in the event loop, allowing the loop to stop while this promise is pending if
    no other events are pending in the loop.
    *
    * @return self
    */
    public function unreference() : self
    {
        if ($this->watcher !== null) {
            Loop::unreference($this->watcher);
        }
        return $this;
    }
}<?php

namespace Amp;

/**
 * Defines an asynchronous iterator over a set of values that is designed to be used within a coroutine.
 *
 * @template-covariant TValue
 */
interface Iterator
{
    /**
    * Succeeds with true if an emitted value is available by calling getCurrent() or false if the iterator has
    resolved. If the iterator fails, the returned promise will fail with the same exception.
    *
    * @return Promise
    * @psalm-return Promise<bool>
    *
    * @throws \Error If the prior promise returned from this method has not resolved.
    * @throws \Throwable The exception used to fail the iterator.
    */
    public function advance() : Promise;
    /**
     * Gets the last emitted value or throws an exception if the iterator has completed.
     *
     * @return mixed Value emitted from the iterator.
     * @psalm-return TValue
     *
     * @throws \Error If the iterator has resolved or advance() was not called before calling this method.
     * @throws \Throwable The exception used to fail the iterator.
     */
    public function getCurrent();
}<?php

namespace Amp;

// @codeCoverageIgnoreStart
if (\PHP_VERSION_ID < 70100) {
    /** @psalm-suppress DuplicateClass */
    trait CallableMaker
    {
        /** @var \ReflectionClass */
        private static $__reflectionClass;
        /** @var \ReflectionMethod[] */
        private static $__reflectionMethods = [];
        /**
        * Creates a callable from a protected or private instance method that may be invoked by callers requiring a
        publicly invokable callback.
        *
        * @param string $method Instance method name.
        *
        * @return callable
        *
        * @psalm-suppress MixedInferredReturnType
        */
        private function callableFromInstanceMethod(string $method) : callable
        {
            if (!isset(self::$__reflectionMethods[$method])) {
                if (self::$__reflectionClass === null) {
                    self::$__reflectionClass = new \ReflectionClass(self::class);
                }
                self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method);
            }
            return self::$__reflectionMethods[$method]->getClosure($this);
        }
        /**
        * Creates a callable from a protected or private static method that may be invoked by methods requiring a
        publicly invokable callback.
        *
        * @param string $method Static method name.
        *
        * @return callable
        *
        * @psalm-suppress MixedInferredReturnType
        */
        private static function callableFromStaticMethod(string $method) : callable
        {
            if (!isset(self::$__reflectionMethods[$method])) {
                if (self::$__reflectionClass === null) {
                    self::$__reflectionClass = new \ReflectionClass(self::class);
                }
                self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method);
            }
            return self::$__reflectionMethods[$method]->getClosure();
        }
    }
} else {
    /** @psalm-suppress DuplicateClass */
    trait CallableMaker
    {
        /**
         * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1.
         */
        private function callableFromInstanceMethod(string $method) : callable
        {
            return \Closure::fromCallable([$this, $method]);
        }
        /**
         * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1.
         */
        private static function callableFromStaticMethod(string $method) : callable
        {
            return \Closure::fromCallable([self::class, $method]);
        }
    }
}
// @codeCoverageIgnoreEnd<?php

namespace Amp;

/**
 * Will be thrown in case an operation is cancelled.
 *
 * @see CancellationToken
 * @see CancellationTokenSource
 */
class CancelledException extends \Exception
{
    /**
     *
     */
    public function __construct(\Throwable $previous = null)
    {
        parent::__construct("The operation was cancelled", 0, $previous);
    }
}<?php

namespace Amp;

/**
 * Creates a promise that calls $promisor only when the result of the promise is requested (i.e. onResolve() is called
 * on the promise). $promisor can return a promise or any value. If $promisor throws an exception, the promise fails
 * with that exception. If $promisor returns a Generator, it will be run as a coroutine.
 */
final class LazyPromise implements Promise
{
    /** @var callable|null */
    private $promisor;
    /** @var Promise|null */
    private $promise;
    /**
    * @param callable $promisor Function which starts an async operation, returning a Promise (or any value).
    Generators will be run as a coroutine.
    */
    public function __construct(callable $promisor)
    {
        $this->promisor = $promisor;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        if ($this->promise === null) {
            \assert($this->promisor !== null);
            $provider = $this->promisor;
            $this->promisor = null;
            $this->promise = call($provider);
        }
        \assert($this->promise !== null);
        $this->promise->onResolve($onResolved);
    }
}<?php

namespace Amp;

/**
 * A "safe" struct trait for public property aggregators.
 *
 * This trait is intended to make using public properties a little safer by throwing when
 * nonexistent property names are read or written.
 */
trait Struct
{
    /**
     * The minimum percentage [0-100] at which to recommend a similar property
     * name when generating error messages.
     */
    private $__propertySuggestThreshold = 70;
    /**
     * @param string $property
     *
     * @psalm-return no-return
     */
    public function __get(string $property)
    {
        throw new \Error($this->generateStructPropertyError($property));
    }
    /**
     * @param string $property
     * @param mixed $value
     *
     * @psalm-return no-return
     */
    public function __set(string $property, $value)
    {
        throw new \Error($this->generateStructPropertyError($property));
    }
    /**
     *
     */
    private function generateStructPropertyError(string $property) : string
    {
        $suggestion = $this->suggestPropertyName($property);
        $suggestStr = $suggestion == "" ? "" : " ... did you mean \"{$suggestion}?\"";
        return \sprintf(
            "%s property \"%s\" does not exist%s",
            \str_replace("\x00", "@", \get_class($this)),
            // Handle anonymous class names.
            $property,
            $suggestStr
        );
    }
    /**
     *
     */
    private function suggestPropertyName(string $badProperty) : string
    {
        $badProperty = \strtolower($badProperty);
        $bestMatch = "";
        $bestMatchPercentage = 0;
        /** @psalm-suppress RawObjectIteration */
        foreach ($this as $property => $value) {
            // Never suggest properties that begin with an underscore
            if ($property[0] === "_") {
                continue;
            }
            \similar_text($badProperty, \strtolower($property), $byRefPercentage);
            if ($byRefPercentage > $bestMatchPercentage) {
                $bestMatchPercentage = $byRefPercentage;
                $bestMatch = $property;
            }
        }
        return $bestMatchPercentage >= $this->__propertySuggestThreshold ? $bestMatch : "";
    }
}<?php

namespace Amp\Http\Client;

final class MissingAttributeError extends \Error
{
    /**
     *
     */
    public function __construct(string $message)
    {
        parent::__construct($message);
    }
}<?php

namespace Amp\Http\Client;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\ByteStream\Payload;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Message;
use Amp\Http\Status;
use Amp\Promise;
use Amp\Success;
/**
 * An HTTP response.
 */
final class Response extends Message
{
    use ForbidSerialization;
    use ForbidCloning;
    /** @var string */
    private $protocolVersion;
    /** @var int */
    private $status;
    /** @var string */
    private $reason;
    /** @var Request */
    private $request;
    /** @var Payload */
    private $body;
    /** @var Promise<Trailers> */
    private $trailers;
    /** @var Response|null */
    private $previousResponse;
    /**
     *
     */
    public function __construct(string $protocolVersion, int $status, ?string $reason, array $headers, InputStream $body, Request $request, ?Promise $trailerPromise = null, ?Response $previousResponse = null)
    {
        $this->setProtocolVersion($protocolVersion);
        $this->setStatus($status, $reason);
        $this->setHeaders($headers);
        $this->setBody($body);
        $this->request = $request;
        /** @noinspection PhpUnhandledExceptionInspection */
        $this->trailers = $trailerPromise ?? new Success(new Trailers([]));
        $this->previousResponse = $previousResponse;
    }
    /**
     * Retrieve the requests's HTTP protocol version.
     *
     * @return string
     */
    public function getProtocolVersion() : string
    {
        return $this->protocolVersion;
    }
    /**
     *
     */
    public function setProtocolVersion(string $protocolVersion) : void
    {
        if (!\in_array($protocolVersion, ["1.0", "1.1", "2"], true)) {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \Error("Invalid HTTP protocol version: " . $protocolVersion);
        }
        $this->protocolVersion = $protocolVersion;
    }
    /**
     * Retrieve the response's three-digit HTTP status code.
     *
     * @return int
     */
    public function getStatus() : int
    {
        return $this->status;
    }
    /**
     *
     */
    public function setStatus(int $status, ?string $reason = null) : void
    {
        $this->status = $status;
        $this->reason = $reason ?? Status::getReason($status);
    }
    /**
     * Retrieve the response's (possibly empty) reason phrase.
     *
     * @return string
     */
    public function getReason() : string
    {
        return $this->reason;
    }
    /**
     * Retrieve the Request instance that resulted in this Response instance.
     *
     * @return Request
     */
    public function getRequest() : Request
    {
        return $this->request;
    }
    /**
     *
     */
    public function setRequest(Request $request) : void
    {
        $this->request = $request;
    }
    /**
    * Retrieve the original Request instance associated with this Response instance.
    *
    * A given Response may be the result of one or more redirects. This method is a shortcut to
    access information from the original Request that led to this response.
    *
    * @return Request
    */
    public function getOriginalRequest() : Request
    {
        if (empty($this->previousResponse)) {
            return $this->request;
        }
        return $this->previousResponse->getOriginalRequest();
    }
    /**
    * Retrieve the original Response instance associated with this Response instance.
    *
    * A given Response may be the result of one or more redirects. This method is a shortcut to
    access information from the original Response that led to this response.
    *
    * @return Response
    */
    public function getOriginalResponse() : Response
    {
        if (empty($this->previousResponse)) {
            return $this;
        }
        return $this->previousResponse->getOriginalResponse();
    }
    /**
     * If this Response is the result of a redirect traverse up the redirect history.
     *
     * @return (Response | null)
     */
    public function getPreviousResponse() : ?Response
    {
        return $this->previousResponse;
    }
    /**
     *
     */
    public function setPreviousResponse(?Response $previousResponse) : void
    {
        $this->previousResponse = $previousResponse;
    }
    /**
     * Assign a value for the specified header field by replacing any existing values for that field.
     *
     * @param string $name Header name.
     * @param (string | string[]) $value Header value.
     */
    public function setHeader(string $name, $value) : void
    {
        if (($name[0] ?? ":") === ":") {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::setHeader($name, $value);
    }
    /**
     * Assign a value for the specified header field by adding an additional header line.
     *
     * @param string $name Header name.
     * @param (string | string[]) $value Header value.
     */
    public function addHeader(string $name, $value) : void
    {
        if (($name[0] ?? ":") === ":") {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::addHeader($name, $value);
    }
    /**
     *
     */
    public function setHeaders(array $headers) : void
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        parent::setHeaders($headers);
    }
    /**
     * Remove the specified header field from the message.
     *
     * @param string $name Header name.
     */
    public function removeHeader(string $name) : void
    {
        parent::removeHeader($name);
    }
    /**
     * Retrieve the response body.
     *
     * Note: If you stream a Message, you can't consume the payload twice.
     *
     * @return Payload
     */
    public function getBody() : Payload
    {
        return $this->body;
    }
    /**
     * @param (Payload | InputStream | string | int | float | bool) $body
     */
    public function setBody($body) : void
    {
        if ($body instanceof Payload) {
            $this->body = $body;
        } elseif ($body === null) {
            $this->body = new Payload(new InMemoryStream());
        } elseif (\is_string($body)) {
            $this->body = new Payload(new InMemoryStream($body));
        } elseif (\is_scalar($body)) {
            $this->body = new Payload(new InMemoryStream(\var_export($body, true)));
        } elseif ($body instanceof InputStream) {
            $this->body = new Payload($body);
        } else {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \TypeError("Invalid body type: " . \gettype($body));
        }
    }
    /**
     * @return Promise<Trailers>
     */
    public function getTrailers() : Promise
    {
        return $this->trailers;
    }
    /**
     * @param Promise<Trailers> $promise
     */
    public function setTrailers(Promise $promise) : void
    {
        $this->trailers = $promise;
    }
}<?php

namespace Amp\Http\Client;

final class SocketException extends HttpException
{
}<?php

namespace Amp\Http\Client;

final class ParseException extends HttpException
{
    /**
     * @param string $message
     * @param int $code
     * @param (\Throwable | null) $previousException
     */
    public function __construct(string $message, int $code, \Throwable $previousException = null)
    {
        parent::__construct($message, $code, $previousException);
    }
}<?php

namespace Amp\Http\Client\EventListener;

use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\EventListener;
use Amp\Http\Client\Internal\HarAttributes;
use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Success;
use function Amp\getCurrentTime;
final class RecordHarAttributes implements EventListener
{
    /**
     *
     */
    public function startRequest(Request $request) : Promise
    {
        if (!$request->hasAttribute(HarAttributes::STARTED_DATE_TIME)) {
            $request->setAttribute(HarAttributes::STARTED_DATE_TIME, new \DateTimeImmutable());
        }
        return $this->addTiming(HarAttributes::TIME_START, $request);
    }
    /**
     *
     */
    public function startDnsResolution(Request $request) : Promise
    {
        return new Success();
        // not implemented
    }
    /**
     *
     */
    public function startConnectionCreation(Request $request) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_CONNECT, $request);
    }
    /**
     *
     */
    public function startTlsNegotiation(Request $request) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_SSL, $request);
    }
    /**
     *
     */
    public function startSendingRequest(Request $request, Stream $stream) : Promise
    {
        $host = $stream->getRemoteAddress()->getHost();
        if (\strrpos($host, ':')) {
            $host = '[' . $host . ']';
        }
        $request->setAttribute(HarAttributes::SERVER_IP_ADDRESS, $host);
        return $this->addTiming(HarAttributes::TIME_SEND, $request);
    }
    /**
     *
     */
    public function completeSendingRequest(Request $request, Stream $stream) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_WAIT, $request);
    }
    /**
     *
     */
    public function startReceivingResponse(Request $request, Stream $stream) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_RECEIVE, $request);
    }
    /**
     *
     */
    public function completeReceivingResponse(Request $request, Stream $stream) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_COMPLETE, $request);
    }
    /**
     *
     */
    public function completeDnsResolution(Request $request) : Promise
    {
        return new Success();
        // not implemented
    }
    /**
     *
     */
    public function completeConnectionCreation(Request $request) : Promise
    {
        return new Success();
        // not implemented
    }
    /**
     *
     */
    public function completeTlsNegotiation(Request $request) : Promise
    {
        return new Success();
        // not implemented
    }
    /**
     *
     */
    private function addTiming(string $key, Request $request) : Promise
    {
        if (!$request->hasAttribute($key)) {
            $request->setAttribute($key, getCurrentTime());
        }
        return new Success();
    }
    /**
     *
     */
    public function abort(Request $request, \Throwable $cause) : Promise
    {
        return new Success();
    }
}<?php

namespace Amp\Http\Client;

use Amp\Http\Client\Body\StringBody;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Message;
use Amp\Promise;
use League\Uri;
use Psr\Http\Message\UriInterface;
use function Amp\call;
/**
 * An HTTP request.
 */
final class Request extends Message
{
    use ForbidSerialization;
    public const DEFAULT_HEADER_SIZE_LIMIT = 2 * 8192;
    public const DEFAULT_BODY_SIZE_LIMIT = 10485760;
    /**
     * @template TValue
     *
     * @param mixed $value
     * @psalm-param TValue $value
     *
     * @return mixed
     * @psalm-return TValue
     */
    private static function clone($value)
    {
        if ($value === null || \is_scalar($value)) {
            return $value;
        }
        // force deep cloning
        return \unserialize(\serialize($value), ['allowed_classes' => true]);
    }
    /** @var string[] */
    private $protocolVersions = ['1.1', '2'];
    /** @var string */
    private $method;
    /** @var UriInterface */
    private $uri;
    /** @var RequestBody */
    private $body;
    /** @var int */
    private $tcpConnectTimeout = 10000;
    /** @var int */
    private $tlsHandshakeTimeout = 10000;
    /** @var int */
    private $transferTimeout = 10000;
    /** @var int */
    private $inactivityTimeout = 10000;
    /** @var int */
    private $bodySizeLimit = self::DEFAULT_BODY_SIZE_LIMIT;
    /** @var int */
    private $headerSizeLimit = self::DEFAULT_HEADER_SIZE_LIMIT;
    /** @var callable|null */
    private $onPush;
    /** @var callable|null */
    private $onUpgrade;
    /** @var callable|null */
    private $onInformationalResponse;
    /** @var mixed[] */
    private $attributes = [];
    /** @var EventListener[] */
    private $eventListeners = [];
    /**
     * Request constructor.
     *
     * @param (string | UriInterface) $uri
     * @param string $method
     * @param string $body
     */
    public function __construct($uri, string $method = "GET", ?string $body = null)
    {
        $this->setUri($uri);
        $this->setMethod($method);
        $this->setBody($body);
    }
    /**
     *
     */
    public function addEventListener(EventListener $eventListener) : void
    {
        $this->eventListeners[] = $eventListener;
    }
    /**
     * @return EventListener[]
     */
    public function getEventListeners() : array
    {
        return $this->eventListeners;
    }
    /**
     * Retrieve the requests's acceptable HTTP protocol versions.
     *
     * @return string[]
     */
    public function getProtocolVersions() : array
    {
        return $this->protocolVersions;
    }
    /**
     * Assign the requests's acceptable HTTP protocol versions.
     *
     * The HTTP client might choose any of these.
     *
     * @param string[] $versions
     */
    public function setProtocolVersions(array $versions) : void
    {
        $versions = \array_unique($versions);
        if (empty($versions)) {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \Error("Empty array of protocol versions provided, must not be empty.");
        }
        foreach ($versions as $version) {
            if (!\in_array($version, ["1.0", "1.1", "2"], true)) {
                /** @noinspection PhpUndefinedClassInspection */
                throw new \Error("Invalid HTTP protocol version: " . $version);
            }
        }
        $this->protocolVersions = $versions;
    }
    /**
     * Retrieve the request's HTTP method verb.
     *
     * @return string
     */
    public function getMethod() : string
    {
        return $this->method;
    }
    /**
     * Specify the request's HTTP method verb.
     *
     * @param string $method
     */
    public function setMethod(string $method) : void
    {
        $this->method = $method;
    }
    /**
     * Retrieve the request's URI.
     *
     * @return UriInterface
     */
    public function getUri() : UriInterface
    {
        return $this->uri;
    }
    /**
     * Specify the request's HTTP URI.
     *
     * @param (string | UriInterface) $uri
     */
    public function setUri($uri) : void
    {
        $this->uri = $uri instanceof UriInterface ? $uri : $this->createUriFromString($uri);
    }
    /**
     * Assign a value for the specified header field by replacing any existing values for that field.
     *
     * @param string $name Header name.
     * @param (string | string[]) $value Header value.
     */
    public function setHeader(string $name, $value) : void
    {
        if (($name[0] ?? ":") === ":") {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::setHeader($name, $value);
    }
    /**
     * Assign a value for the specified header field by adding an additional header line.
     *
     * @param string $name Header name.
     * @param (string | string[]) $value Header value.
     */
    public function addHeader(string $name, $value) : void
    {
        if (($name[0] ?? ":") === ":") {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::addHeader($name, $value);
    }
    /**
     *
     */
    public function setHeaders(array $headers) : void
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        parent::setHeaders($headers);
    }
    /**
     * Remove the specified header field from the message.
     *
     * @param string $name Header name.
     */
    public function removeHeader(string $name) : void
    {
        parent::removeHeader($name);
    }
    /**
     * Retrieve the message entity body.
     */
    public function getBody() : RequestBody
    {
        return $this->body;
    }
    /**
     * Assign the message entity body.
     *
     * @param mixed $body
     */
    public function setBody($body) : void
    {
        if ($body === null) {
            $this->body = new StringBody("");
        } elseif (\is_string($body)) {
            $this->body = new StringBody($body);
        } elseif (\is_scalar($body)) {
            $this->body = new StringBody(\var_export($body, true));
        } elseif ($body instanceof RequestBody) {
            $this->body = $body;
        } else {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \TypeError("Invalid body type: " . \gettype($body));
        }
    }
    /**
    * Registers a callback to the request that is invoked when the server pushes an additional resource.
    The callback is given two parameters: the Request generated from the pushed resource, and a promise for the
    Response containing the pushed resource. An HttpException, StreamException, or CancelledException can be thrown
    to refuse the push. If no callback is registered, pushes are automatically rejected.
    *
    * Interceptors can mostly use {@code interceptPush} instead.
    *
    * Example:
    function (Request $request, Promise $response): \Generator {
    $uri = $request->getUri(); // URI of pushed resource.
    $response = yield $promise; // Wait for resource to arrive.
    // Use Response object from resolved promise.
    }
    *
    * @param (callable | null) $onPush
    */
    public function setPushHandler(?callable $onPush) : void
    {
        $this->onPush = $onPush;
    }
    /**
    * Allows interceptors to modify also pushed responses.
    *
    * If no push callable has been set by the application, the interceptor won't be invoked. If you want to enable
    push in an interceptor without the application setting a push handler, you need to use {@code setPushHandler}.
    *
    * @param callable $interceptor Receives the response and might modify it or return a new instance.
    */
    public function interceptPush(callable $interceptor) : void
    {
        if ($this->onPush === null) {
            return;
        }
        $onPush = $this->onPush;
        /** @psalm-suppress MissingClosureReturnType */
        $this->onPush = static function (Request $request, Promise $response) use($onPush, $interceptor) {
            $response = call(static function () use($response, $interceptor) : \Generator {
                return (yield call($interceptor, (yield $response))) ?? $response;
            });
            return $onPush($request, $response);
        };
    }
    /**
     * @return (callable | null)
     */
    public function getPushHandler() : ?callable
    {
        return $this->onPush;
    }
    /**
     * Registers a callback invoked if a 101 response is returned to the request.
     *
     * @param (callable | null) $onUpgrade
     */
    public function setUpgradeHandler(?callable $onUpgrade) : void
    {
        $this->onUpgrade = $onUpgrade;
    }
    /**
     * @return (callable | null)
     */
    public function getUpgradeHandler() : ?callable
    {
        return $this->onUpgrade;
    }
    /**
     * Registers a callback invoked when a 1xx response is returned to the request (other than a 101).
     *
     * @param (callable | null) $onInformationalResponse
     */
    public function setInformationalResponseHandler(?callable $onInformationalResponse) : void
    {
        $this->onInformationalResponse = $onInformationalResponse;
    }
    /**
     * @return (callable | null)
     */
    public function getInformationalResponseHandler() : ?callable
    {
        return $this->onInformationalResponse;
    }
    /**
     * @return int Timeout in milliseconds for the TCP connection.
     */
    public function getTcpConnectTimeout() : int
    {
        return $this->tcpConnectTimeout;
    }
    /**
     *
     */
    public function setTcpConnectTimeout(int $tcpConnectTimeout) : void
    {
        $this->tcpConnectTimeout = $tcpConnectTimeout;
    }
    /**
     * @return int Timeout in milliseconds for the TLS handshake.
     */
    public function getTlsHandshakeTimeout() : int
    {
        return $this->tlsHandshakeTimeout;
    }
    /**
     *
     */
    public function setTlsHandshakeTimeout(int $tlsHandshakeTimeout) : void
    {
        $this->tlsHandshakeTimeout = $tlsHandshakeTimeout;
    }
    /**
     * @return int Timeout in milliseconds for the HTTP transfer (not counting TCP connect and TLS handshake)
     */
    public function getTransferTimeout() : int
    {
        return $this->transferTimeout;
    }
    /**
     *
     */
    public function setTransferTimeout(int $transferTimeout) : void
    {
        $this->transferTimeout = $transferTimeout;
    }
    /**
     * @return int Timeout in milliseconds since the last data was received before the request fails due to inactivity.
     */
    public function getInactivityTimeout() : int
    {
        return $this->inactivityTimeout;
    }
    /**
     *
     */
    public function setInactivityTimeout(int $inactivityTimeout) : void
    {
        $this->inactivityTimeout = $inactivityTimeout;
    }
    /**
     *
     */
    public function getHeaderSizeLimit() : int
    {
        return $this->headerSizeLimit;
    }
    /**
     *
     */
    public function setHeaderSizeLimit(int $headerSizeLimit) : void
    {
        $this->headerSizeLimit = $headerSizeLimit;
    }
    /**
     *
     */
    public function getBodySizeLimit() : int
    {
        return $this->bodySizeLimit;
    }
    /**
     *
     */
    public function setBodySizeLimit(int $bodySizeLimit) : void
    {
        $this->bodySizeLimit = $bodySizeLimit;
    }
    /**
    * Note: This method returns a deep clone of the request's attributes, so you can't modify the request attributes
    by modifying the returned value in any way.
    *
    * @return mixed[] An array of all request attributes in the request's local storage, indexed by name.
    */
    public function getAttributes() : array
    {
        return self::clone($this->attributes);
    }
    /**
    * Check whether a variable with the given name exists in the request's local storage.
    *
    * Each request has its own local storage to which applications and interceptors may read and write data.
    Other interceptors which are aware of this data can then access it without the server being tightly coupled to
    specific implementations.
    *
    * @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
    *
    * @return bool
    */
    public function hasAttribute(string $name) : bool
    {
        return \array_key_exists($name, $this->attributes);
    }
    /**
    * Retrieve a variable from the request's local storage.
    *
    * Each request has its own local storage to which applications and interceptors may read and write data.
    Other interceptors which are aware of this data can then access it without the server being tightly coupled to
    specific implementations.
    *
    * Note: This method returns a deep clone of the request's attribute, so you can't modify the request attribute
    by modifying the returned value in any way.
    *
    * @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
    *
    * @return mixed
    *
    * @throws MissingAttributeError If an attribute with the given name does not exist.
    */
    public function getAttribute(string $name)
    {
        if (!$this->hasAttribute($name)) {
            throw new MissingAttributeError("The requested attribute '{$name}' does not exist");
        }
        return self::clone($this->attributes[$name]);
    }
    /**
    * Assign a variable to the request's local storage.
    *
    * Each request has its own local storage to which applications and interceptors may read and write data.
    Other interceptors which are aware of this data can then access it without the server being tightly coupled to
    specific implementations.
    *
    * Note: This method performs a deep clone of the value via serialization, so you can't modify the given value
    after setting it.
    *
    * **Example**
    *
    * ```php
    $request->setAttribute(Timing::class, $stopWatch);
    ```
    *
    * @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
    * @param mixed $value Value of the attribute, might be any serializable value.
    */
    public function setAttribute(string $name, $value) : void
    {
        $this->attributes[$name] = self::clone($value);
    }
    /**
     * Remove an attribute from the request's local storage.
     *
     * @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
     *
     * @throws MissingAttributeError If an attribute with the given name does not exist.
     */
    public function removeAttribute(string $name) : void
    {
        if (!$this->hasAttribute($name)) {
            throw new MissingAttributeError("The requested attribute '{$name}' does not exist");
        }
        unset($this->attributes[$name]);
    }
    /**
     * Remove all attributes from the request's local storage.
     */
    public function removeAttributes() : void
    {
        $this->attributes = [];
    }
    /**
     *
     */
    public function isIdempotent() : bool
    {
        // https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
        return \in_array($this->method, ['GET', 'HEAD', 'PUT', 'DELETE'], true);
    }
    /**
     *
     */
    private function createUriFromString(string $uri) : UriInterface
    {
        return Uri\Http::createFromString($uri);
    }
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Connection\ConnectionPool;
use Amp\Http\Client\Connection\InterceptedStream;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Promise;
use function Amp\call;
final class PooledHttpClient implements DelegateHttpClient
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var ConnectionPool */
    private $connectionPool;
    /** @var NetworkInterceptor[] */
    private $networkInterceptors = [];
    /**
     *
     */
    public function __construct(?ConnectionPool $connectionPool = null)
    {
        $this->connectionPool = $connectionPool ?? new UnlimitedConnectionPool();
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise
    {
        return call(function () use($request, $cancellation) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startRequest($request));
            }
            $stream = (yield $this->connectionPool->getStream($request, $cancellation));
            \assert($stream instanceof Stream);
            foreach (\array_reverse($this->networkInterceptors) as $interceptor) {
                $stream = new InterceptedStream($stream, $interceptor);
            }
            return (yield $stream->request($request, $cancellation));
        });
    }
    /**
    * Adds a network interceptor.
    *
    * Network interceptors are only invoked if the request requires network access, i.e. there's no short-circuit by
    an application interceptor, e.g. a cache.
    *
    * Whether the given network interceptor will be respected for currently running requests is undefined.
    *
    * Any new requests have to take the new interceptor into account.
    *
    * @param NetworkInterceptor $networkInterceptor
    *
    * @return self
    */
    public function intercept(NetworkInterceptor $networkInterceptor) : self
    {
        $clone = clone $this;
        $clone->networkInterceptors[] = $networkInterceptor;
        return $clone;
    }
}<?php

namespace Amp\Http\Client;

use Amp\Http\Client\Connection\ConnectionPool;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\Interceptor\DecompressResponse;
use Amp\Http\Client\Interceptor\FollowRedirects;
use Amp\Http\Client\Interceptor\ForbidUriUserInfo;
use Amp\Http\Client\Interceptor\RetryRequests;
use Amp\Http\Client\Interceptor\SetRequestHeaderIfUnset;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
/**
 * Allows building an HttpClient instance.
 *
 * The builder is the recommended way to build an HttpClient instance.
 */
final class HttpClientBuilder
{
    use ForbidCloning;
    use ForbidSerialization;
    /**
     *
     */
    public static function buildDefault() : HttpClient
    {
        return (new self())->build();
    }
    /** @var ForbidUriUserInfo|null */
    private $forbidUriUserInfo;
    /** @var RetryRequests|null */
    private $retryInterceptor;
    /** @var FollowRedirects|null */
    private $followRedirectsInterceptor;
    /** @var SetRequestHeaderIfUnset|null */
    private $defaultUserAgentInterceptor;
    /** @var SetRequestHeaderIfUnset|null */
    private $defaultAcceptInterceptor;
    /** @var NetworkInterceptor|null */
    private $defaultCompressionHandler;
    /** @var ApplicationInterceptor[] */
    private $applicationInterceptors = [];
    /** @var NetworkInterceptor[] */
    private $networkInterceptors = [];
    /** @var ConnectionPool */
    private $pool;
    /**
     *
     */
    public function __construct()
    {
        $this->pool = new UnlimitedConnectionPool();
        $this->forbidUriUserInfo = new ForbidUriUserInfo();
        $this->followRedirectsInterceptor = new FollowRedirects(10);
        $this->retryInterceptor = new RetryRequests(2);
        $this->defaultAcceptInterceptor = new SetRequestHeaderIfUnset('accept', '*/*');
        $this->defaultUserAgentInterceptor = new SetRequestHeaderIfUnset('user-agent', 'amphp/http-client @ v4.x');
        $this->defaultCompressionHandler = new DecompressResponse();
    }
    /**
     *
     */
    public function build() : HttpClient
    {
        /** @var PooledHttpClient $client */
        $client = new PooledHttpClient($this->pool);
        foreach ($this->networkInterceptors as $interceptor) {
            $client = $client->intercept($interceptor);
        }
        if ($this->defaultAcceptInterceptor) {
            $client = $client->intercept($this->defaultAcceptInterceptor);
        }
        if ($this->defaultUserAgentInterceptor) {
            $client = $client->intercept($this->defaultUserAgentInterceptor);
        }
        if ($this->defaultCompressionHandler) {
            $client = $client->intercept($this->defaultCompressionHandler);
        }
        $applicationInterceptors = $this->applicationInterceptors;
        if ($this->followRedirectsInterceptor) {
            \array_unshift($applicationInterceptors, $this->followRedirectsInterceptor);
        }
        if ($this->forbidUriUserInfo) {
            \array_unshift($applicationInterceptors, $this->forbidUriUserInfo);
        }
        if ($this->retryInterceptor) {
            $applicationInterceptors[] = $this->retryInterceptor;
        }
        foreach (\array_reverse($applicationInterceptors) as $applicationInterceptor) {
            $client = new InterceptedHttpClient($client, $applicationInterceptor);
        }
        return new HttpClient($client);
    }
    /**
     * @param ConnectionPool $pool Connection pool to use.
     *
     * @return self
     */
    public function usingPool(ConnectionPool $pool) : self
    {
        $builder = clone $this;
        $builder->pool = $pool;
        return $builder;
    }
    /**
    * @param ApplicationInterceptor $interceptor This interceptor gets added to the interceptor queue, so interceptors
    are executed in the order given to this method.
    *
    * @return self
    */
    public function intercept(ApplicationInterceptor $interceptor) : self
    {
        if ($this->followRedirectsInterceptor !== null && $interceptor instanceof FollowRedirects) {
            throw new \Error('Disable automatic redirect following or use HttpClientBuilder::followRedirects() to customize redirects');
        }
        if ($this->retryInterceptor !== null && $interceptor instanceof RetryRequests) {
            throw new \Error('Disable automatic retries or use HttpClientBuilder::retry() to customize retries');
        }
        $builder = clone $this;
        $builder->applicationInterceptors[] = $interceptor;
        return $builder;
    }
    /**
    * @param NetworkInterceptor $interceptor This interceptor gets added to the interceptor queue, so interceptors
    are executed in the order given to this method.
    *
    * @return self
    */
    public function interceptNetwork(NetworkInterceptor $interceptor) : self
    {
        $builder = clone $this;
        $builder->networkInterceptors[] = $interceptor;
        return $builder;
    }
    /**
    * @param int $retryLimit Maximum number of times a request may be retried. Only certain requests will be retried
    automatically (GET, HEAD, PUT, and DELETE requests are automatically retried, or any
    request that was indicated as unprocessed by the connection).
    *
    * @return self
    */
    public function retry(int $retryLimit) : self
    {
        $builder = clone $this;
        if ($retryLimit <= 0) {
            $builder->retryInterceptor = null;
        } else {
            $builder->retryInterceptor = new RetryRequests($retryLimit);
        }
        return $builder;
    }
    /**
    * @param int $limit Maximum number of redirects to follow. The client will automatically request the URI supplied
    by a redirect response (3xx status codes) and returns that response instead.
    *
    * @return self
    */
    public function followRedirects(int $limit = 10) : self
    {
        $builder = clone $this;
        if ($limit <= 0) {
            $builder->followRedirectsInterceptor = null;
        } else {
            $builder->followRedirectsInterceptor = new FollowRedirects($limit);
        }
        return $builder;
    }
    /**
     * Removes the default restriction of user:password in request URIs.
     *
     * @return self
     */
    public function allowDeprecatedUriUserInfo() : self
    {
        $builder = clone $this;
        $builder->forbidUriUserInfo = null;
        return $builder;
    }
    /**
     * Doesn't automatically set an 'accept' header.
     *
     * @return self
     */
    public function skipDefaultAcceptHeader() : self
    {
        $builder = clone $this;
        $builder->defaultAcceptInterceptor = null;
        return $builder;
    }
    /**
     * Doesn't automatically set a 'user-agent' header.
     *
     * @return self
     */
    public function skipDefaultUserAgent() : self
    {
        $builder = clone $this;
        $builder->defaultUserAgentInterceptor = null;
        return $builder;
    }
    /**
     * Doesn't automatically set an 'accept-encoding' header and decompress the response.
     *
     * @return self
     */
    public function skipAutomaticCompression() : self
    {
        $builder = clone $this;
        $builder->defaultCompressionHandler = null;
        return $builder;
    }
}<?php

namespace Amp\Http\Client\Internal;

/** @internal */
trait ForbidSerialization
{
    /**
     *
     */
    public final function __sleep()
    {
        throw new \Error(__CLASS__ . ' does not support serialization');
    }
}<?php

namespace Amp\Http\Client\Internal;

/** @internal */
trait ForbidCloning
{
    /**
     *
     */
    protected final function __clone()
    {
        // clone is automatically denied to all external calls
        // final protected instead of private to also force denial for all children
    }
}<?php

namespace Amp\Http\Client\Internal;

/** @internal */
final class HarAttributes
{
    use ForbidCloning;
    use ForbidSerialization;
    public const STARTED_DATE_TIME = 'amp.http.client.har.startedDateTime';
    public const SERVER_IP_ADDRESS = 'amp.http.client.har.serverIPAddress';
    public const TIME_START = 'amp.http.client.har.timings.start';
    public const TIME_SSL = 'amp.http.client.har.timings.ssl';
    public const TIME_CONNECT = 'amp.http.client.har.timings.connect';
    public const TIME_SEND = 'amp.http.client.har.timings.send';
    public const TIME_WAIT = 'amp.http.client.har.timings.wait';
    public const TIME_RECEIVE = 'amp.http.client.har.timings.receive';
    public const TIME_COMPLETE = 'amp.http.client.har.timings.complete';
}<?php

namespace Amp\Http\Client\Internal;

use Amp\ByteStream\InputStream;
use Amp\CancellationTokenSource;
use Amp\Promise;
/** @internal */
final class ResponseBodyStream implements InputStream
{
    use ForbidSerialization;
    use ForbidCloning;
    /** @var InputStream */
    private $body;
    /** @var CancellationTokenSource */
    private $bodyCancellation;
    /** @var bool */
    private $successfulEnd = false;
    /**
     *
     */
    public function __construct(InputStream $body, CancellationTokenSource $bodyCancellation)
    {
        $this->body = $body;
        $this->bodyCancellation = $bodyCancellation;
    }
    /**
     *
     */
    public function read() : Promise
    {
        $promise = $this->body->read();
        $promise->onResolve(function ($error, $value) {
            if ($value === null && $error === null) {
                $this->successfulEnd = true;
            }
        });
        return $promise;
    }
    /**
     *
     */
    public function __destruct()
    {
        if (!$this->successfulEnd) {
            $this->bodyCancellation->cancel();
        }
    }
}<?php

namespace Amp\Http\Client\Internal;

use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\Request;
/**
 * @param Request $request
 *
 * @return string
 * @throws InvalidRequestException
 *
 * @internal
 */
function normalizeRequestPathWithQuery(Request $request) : string
{
    $path = $request->getUri()->getPath();
    $query = $request->getUri()->getQuery();
    if ($path === '') {
        return '/' . ($query !== '' ? '?' . $query : '');
    }
    if ($path[0] !== '/') {
        throw new InvalidRequestException($request, 'Relative path (' . $path . ') is not allowed in the request URI');
    }
    return $path . ($query !== '' ? '?' . $query : '');
}<?php

namespace Amp\Http\Client\Internal;

use Amp\ByteStream\InputStream;
use Amp\Failure;
use Amp\Http\Client\ParseException;
use Amp\Http\Status;
use Amp\Promise;
/** @internal */
final class SizeLimitingInputStream implements InputStream
{
    use ForbidSerialization;
    use ForbidCloning;
    /** @var InputStream|null */
    private $source;
    /** @var int */
    private $bytesRead = 0;
    /** @var int */
    private $sizeLimit;
    /** @var \Throwable|null */
    private $exception;
    /**
     *
     */
    public function __construct(InputStream $source, int $sizeLimit)
    {
        $this->source = $source;
        $this->sizeLimit = $sizeLimit;
    }
    /**
     *
     */
    public function read() : Promise
    {
        if ($this->exception) {
            return new Failure($this->exception);
        }
        \assert($this->source !== null);
        $promise = $this->source->read();
        $promise->onResolve(function ($error, $value) {
            if ($value !== null) {
                $this->bytesRead += \strlen($value);
                if ($this->bytesRead > $this->sizeLimit) {
                    $this->exception = new ParseException("Configured body size exceeded: {$this->bytesRead} bytes received, while the configured limit is {$this->sizeLimit} bytes", Status::PAYLOAD_TOO_LARGE);
                    $this->source = null;
                }
            }
        });
        return $promise;
    }
}<?php

namespace Amp\Http\Client;

use Amp\ByteStream\InputStream;
use Amp\Promise;
/**
 * An interface for generating HTTP message bodies + headers.
 */
interface RequestBody
{
    /**
     * Retrieve a key-value array of headers to add to the outbound request.
     *
     * The resolved promise value must be a key-value array mapping header fields to values.
     *
     * @return Promise
     */
    public function getHeaders() : Promise;
    /**
     * Create the HTTP message body to be sent.
     *
     * Further calls MUST return a new stream to make it possible to resend bodies on redirects.
     *
     * @return InputStream
     */
    public function createBodyStream() : InputStream;
    /**
     * Retrieve the HTTP message body length. If not available, return -1.
     *
     * @return Promise
     */
    public function getBodyLength() : Promise;
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Promise;
use function Amp\call;
final class InterceptedHttpClient implements DelegateHttpClient
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var DelegateHttpClient */
    private $httpClient;
    /** @var ApplicationInterceptor */
    private $interceptor;
    /**
     *
     */
    public function __construct(DelegateHttpClient $httpClient, ApplicationInterceptor $interceptor)
    {
        $this->httpClient = $httpClient;
        $this->interceptor = $interceptor;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise
    {
        return call(function () use($request, $cancellation) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startRequest($request));
            }
            return $this->interceptor->request($request, $cancellation, $this->httpClient);
        });
    }
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Promise;
/**
 * Base HTTP client interface for use in {@see ApplicationInterceptor}.
 *
 * Applications and implementations should depend on {@see HttpClient} instead. The intent of this interface is to
 * allow static analysis tools to find interceptors that forget to pass the cancellation token down. This situation is
 * created because of the cancellation token being optional.
 *
 * Before executing or delegating the request, any client implementation must call {@see EventListener::startRequest()}
 * on all event listeners registered on the given request in the order defined by {@see Request::getEventListeners()}.
 * Before calling the next listener, the promise returned from the previous one must resolve successfully.
 *
 * @see HttpClient
 */
interface DelegateHttpClient
{
    /**
     * Request a specific resource from an HTTP server.
     *
     * @param Request $request
     * @param CancellationToken $cancellation
     *
     * @return Promise<Response>
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise;
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\NullCancellationToken;
use Amp\Promise;
/**
 * Convenient HTTP client for use in applications and libraries, providing a default for the cancellation token and
 * automatically cloning the passed request, so future application requests can re-use the same object again.
 */
final class HttpClient implements DelegateHttpClient
{
    private $httpClient;
    /**
     *
     */
    public function __construct(DelegateHttpClient $httpClient)
    {
        $this->httpClient = $httpClient;
    }
    /**
     * Request a specific resource from an HTTP server.
     *
     * @param Request $request
     * @param CancellationToken $cancellation
     *
     * @return Promise<Response>
     */
    public function request(Request $request, ?CancellationToken $cancellation = null) : Promise
    {
        return $this->httpClient->request(clone $request, $cancellation ?? new NullCancellationToken());
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Promise;
use League\Uri\Http;
use Psr\Http\Message\UriInterface;
final class MatchOrigin implements ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var ApplicationInterceptor[] */
    private $originMap = [];
    /** @var ApplicationInterceptor|null */
    private $default;
    /**
     * @param ApplicationInterceptor[] $originMap
     * @param ApplicationInterceptor $default
     *
     * @throws HttpException
     */
    public function __construct(array $originMap, ?ApplicationInterceptor $default = null)
    {
        foreach ($originMap as $origin => $interceptor) {
            if (!$interceptor instanceof ApplicationInterceptor) {
                $type = \is_object($interceptor) ? \get_class($interceptor) : \gettype($interceptor);
                throw new HttpException('Origin map must be a map from origin to ApplicationInterceptor, got ' . $type);
            }
            $this->originMap[$this->checkOrigin($origin)] = $interceptor;
        }
        $this->default = $default;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        $interceptor = $this->originMap[$this->normalizeOrigin($request->getUri())] ?? $this->default;
        if (!$interceptor) {
            return $httpClient->request($request, $cancellation);
        }
        return $interceptor->request($request, $cancellation, $httpClient);
    }
    /**
     *
     */
    private function checkOrigin(string $origin) : string
    {
        try {
            $originUri = Http::createFromString($origin);
        } catch (\Exception $e) {
            throw new HttpException("Invalid origin provided: parsing failed: " . $origin);
        }
        if (!\in_array($originUri->getScheme(), ['http', 'https'], true)) {
            throw new HttpException('Invalid origin with unsupported scheme: ' . $origin);
        }
        if ($originUri->getHost() === '') {
            throw new HttpException('Invalid origin without host: ' . $origin);
        }
        if ($originUri->getUserInfo() !== '') {
            throw new HttpException('Invalid origin with user info, which must not be present: ' . $origin);
        }
        if (!\in_array($originUri->getPath(), ['', '/'], true)) {
            throw new HttpException('Invalid origin with path, which must not be present: ' . $origin);
        }
        if ($originUri->getQuery() !== '') {
            throw new HttpException('Invalid origin with query, which must not be present: ' . $origin);
        }
        if ($originUri->getFragment() !== '') {
            throw new HttpException('Invalid origin with fragment, which must not be present: ' . $origin);
        }
        return $this->normalizeOrigin($originUri);
    }
    /**
     *
     */
    private function normalizeOrigin(UriInterface $uri) : string
    {
        $defaultPort = $uri->getScheme() === 'https' ? 443 : 80;
        return $uri->getScheme() . '://' . $uri->getHost() . ':' . ($uri->getPort() ?? $defaultPort);
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use function Amp\call;
class ModifyResponse implements NetworkInterceptor, ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var callable(Response):(\Generator<mixed, mixed, mixed, Response|null>|Promise<Response>|Response|null) */
    private $mapper;
    /**
     * @psalm-param callable(Response ): (\Generator<mixed, mixed, mixed, (Response | null)> | Promise<Response> | Response | null) $mapper
     */
    public function __construct(callable $mapper)
    {
        $this->mapper = $mapper;
    }
    /**
     *
     */
    public final function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellation, $stream) {
            $response = (yield $stream->request($request, $cancellation));
            $mappedResponse = (yield call($this->mapper, $response));
            \assert($mappedResponse instanceof Response || $mappedResponse === null);
            return $mappedResponse ?? $response;
        });
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        return call(function () use($request, $cancellation, $httpClient) {
            $request->interceptPush($this->mapper);
            $response = (yield $httpClient->request($request, $cancellation));
            $mappedResponse = (yield call($this->mapper, $response));
            \assert($mappedResponse instanceof Response || $mappedResponse === null);
            return $mappedResponse ?? $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class SetRequestHeader extends ModifyRequest
{
    /**
     *
     */
    public function __construct(string $headerName, string $headerValue, string ...$headerValues)
    {
        \array_unshift($headerValues, $headerValue);
        parent::__construct(static function (Request $request) use($headerName, $headerValues) {
            $request->setHeader($headerName, $headerValues);
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class SetRequestHeaderIfUnset extends ModifyRequest
{
    /**
     *
     */
    public function __construct(string $headerName, string $headerValue, string ...$headerValues)
    {
        \array_unshift($headerValues, $headerValue);
        parent::__construct(static function (Request $request) use($headerName, $headerValues) {
            if (!$request->hasHeader($headerName)) {
                $request->setHeader($headerName, $headerValues);
            }
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class AddRequestHeader extends ModifyRequest
{
    /**
     *
     */
    public function __construct(string $headerName, string ...$headerValues)
    {
        parent::__construct(static function (Request $request) use($headerName, $headerValues) {
            $request->addHeader($headerName, $headerValues);
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\HttpException;
use Amp\Http\Client\Response;
class TooManyRedirectsException extends HttpException
{
    /** @var Response */
    private $response;
    /**
     *
     */
    public function __construct(Response $response)
    {
        parent::__construct("There were too many redirects");
        $this->response = $response;
    }
    /**
     *
     */
    public function getResponse() : Response
    {
        return $this->response;
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\ByteStream\ZlibInputStream;
use Amp\CancellationToken;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Internal\SizeLimitingInputStream;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use function Amp\call;
final class DecompressResponse implements NetworkInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var bool */
    private $hasZlib;
    /**
     *
     */
    public function __construct()
    {
        $this->hasZlib = \extension_loaded('zlib');
    }
    /**
     *
     */
    public function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        // If a header is manually set, we won't interfere
        if ($request->hasHeader('accept-encoding')) {
            return $stream->request($request, $cancellation);
        }
        return call(function () use($request, $cancellation, $stream) {
            $this->addAcceptEncodingHeader($request);
            $request->interceptPush(function (Response $response) {
                return $this->decompressResponse($response);
            });
            return $this->decompressResponse((yield $stream->request($request, $cancellation)));
        });
    }
    /**
     *
     */
    private function addAcceptEncodingHeader(Request $request) : void
    {
        if ($this->hasZlib) {
            $request->setHeader('Accept-Encoding', 'gzip, deflate, identity');
        }
    }
    /**
     *
     */
    private function decompressResponse(Response $response) : Response
    {
        if ($encoding = $this->determineCompressionEncoding($response)) {
            $sizeLimit = $response->getRequest()->getBodySizeLimit();
            /** @noinspection PhpUnhandledExceptionInspection */
            $decompressedBody = new ZlibInputStream($response->getBody(), $encoding);
            $response->setBody(new SizeLimitingInputStream($decompressedBody, $sizeLimit));
            $response->removeHeader('content-encoding');
        }
        return $response;
    }
    /**
     *
     */
    private function determineCompressionEncoding(Response $response) : int
    {
        if (!$this->hasZlib) {
            return 0;
        }
        if (!$response->hasHeader("content-encoding")) {
            return 0;
        }
        $contentEncoding = $response->getHeader("content-encoding");
        \assert($contentEncoding !== null);
        $contentEncodingHeader = \trim($contentEncoding);
        if (\strcasecmp($contentEncodingHeader, 'gzip') === 0) {
            return \ZLIB_ENCODING_GZIP;
        }
        if (\strcasecmp($contentEncodingHeader, 'deflate') === 0) {
            return \ZLIB_ENCODING_DEFLATE;
        }
        return 0;
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\File;
use Amp\File\Driver;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\EventListener;
use Amp\Http\Client\EventListener\RecordHarAttributes;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Internal\HarAttributes;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Message;
use Amp\Promise;
use Amp\Sync\LocalMutex;
use Amp\Sync\Lock;
use function Amp\call;
use function Amp\Promise\rethrow;
final class LogHttpArchive implements ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /**
     *
     */
    private static function getTime(Request $request, string $start, string ...$ends) : int
    {
        if (!$request->hasAttribute($start)) {
            return -1;
        }
        foreach ($ends as $end) {
            if ($request->hasAttribute($end)) {
                return $request->getAttribute($end) - $request->getAttribute($start);
            }
        }
        return -1;
    }
    /**
     *
     */
    private static function formatHeaders(Message $message) : array
    {
        $headers = [];
        foreach ($message->getHeaders() as $field => $values) {
            foreach ($values as $value) {
                $headers[] = ['name' => $field, 'value' => $value];
            }
        }
        return $headers;
    }
    /**
     *
     */
    private static function formatEntry(Response $response) : array
    {
        $request = $response->getRequest();
        $data = ['startedDateTime' => $request->getAttribute(HarAttributes::STARTED_DATE_TIME)->format(\DateTimeInterface::RFC3339_EXTENDED), 'time' => self::getTime($request, HarAttributes::TIME_START, HarAttributes::TIME_COMPLETE), 'request' => ['method' => $request->getMethod(), 'url' => (string) $request->getUri()->withUserInfo(''), 'httpVersion' => 'http/' . $request->getProtocolVersions()[0], 'headers' => self::formatHeaders($request), 'queryString' => [], 'cookies' => [], 'headersSize' => -1, 'bodySize' => -1], 'response' => ['status' => $response->getStatus(), 'statusText' => $response->getReason(), 'httpVersion' => 'http/' . $response->getProtocolVersion(), 'headers' => self::formatHeaders($response), 'cookies' => [], 'redirectURL' => $response->getHeader('location') ?? '', 'headersSize' => -1, 'bodySize' => -1, 'content' => ['size' => (int) ($response->getHeader('content-length') ?? '-1'), 'mimeType' => $response->getHeader('content-type') ?? '']], 'cache' => [], 'timings' => ['blocked' => self::getTime($request, HarAttributes::TIME_START, HarAttributes::TIME_CONNECT, HarAttributes::TIME_SEND), 'dns' => -1, 'connect' => self::getTime($request, HarAttributes::TIME_CONNECT, HarAttributes::TIME_SEND), 'ssl' => self::getTime($request, HarAttributes::TIME_SSL, HarAttributes::TIME_SEND), 'send' => self::getTime($request, HarAttributes::TIME_SEND, HarAttributes::TIME_WAIT), 'wait' => self::getTime($request, HarAttributes::TIME_WAIT, HarAttributes::TIME_RECEIVE), 'receive' => self::getTime($request, HarAttributes::TIME_RECEIVE, HarAttributes::TIME_COMPLETE)]];
        if ($request->hasAttribute(HarAttributes::SERVER_IP_ADDRESS)) {
            $data['serverIPAddress'] = $request->getAttribute(HarAttributes::SERVER_IP_ADDRESS);
        }
        return $data;
    }
    /** @var LocalMutex */
    private $fileMutex;
    /** @var File\File|null */
    private $fileHandle;
    /** @var string */
    private $filePath;
    /** @var \Throwable|null */
    private $error;
    /** @var EventListener */
    private $eventListener;
    /**
     *
     */
    public function __construct(string $filePath)
    {
        $this->filePath = $filePath;
        $this->fileMutex = new LocalMutex();
        $this->eventListener = new RecordHarAttributes();
        if (!\interface_exists(Driver::class)) {
            throw new \Error(__CLASS__ . ' requires amphp/file to be installed');
        }
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        return call(function () use($request, $cancellation, $httpClient) {
            if ($this->error) {
                throw $this->error;
            }
            $this->ensureEventListenerIsRegistered($request);
            /** @var Response $response */
            $response = (yield $httpClient->request($request, $cancellation));
            rethrow($this->writeLog($response));
            return $response;
        });
    }
    /**
     *
     */
    public function reset() : Promise
    {
        return $this->rotate($this->filePath);
    }
    /**
     *
     */
    public function rotate(string $filePath) : Promise
    {
        return call(function () use($filePath) {
            /** @var Lock $lock */
            $lock = (yield $this->fileMutex->acquire());
            // Will automatically reopen and reset the file
            $this->fileHandle = null;
            $this->filePath = $filePath;
            $this->error = null;
            $lock->release();
        });
    }
    /**
     *
     */
    private function writeLog(Response $response) : Promise
    {
        return call(function () use($response) {
            try {
                (yield $response->getTrailers());
            } catch (\Throwable $e) {
                // ignore, still log the remaining response times
            }
            try {
                /** @var Lock $lock */
                $lock = (yield $this->fileMutex->acquire());
                $firstEntry = $this->fileHandle === null;
                if ($firstEntry) {
                    $this->fileHandle = (yield \function_exists('Amp\\File\\openFile') ? File\openFile($this->filePath, 'w') : File\open($this->filePath, 'w'));
                    $header = '{"log":{"version":"1.2","creator":{"name":"amphp/http-client","version":"4.x"},"pages":[],"entries":[';
                    (yield $this->fileHandle->write($header));
                } else {
                    \assert($this->fileHandle !== null);
                    (yield $this->fileHandle->seek(-3, \SEEK_CUR));
                }
                /** @noinspection PhpComposerExtensionStubsInspection */
                $json = \json_encode(self::formatEntry($response));
                (yield $this->fileHandle->write(($firstEntry ? '' : ',') . $json . ']}}'));
                $lock->release();
            } catch (HttpException $e) {
                $this->error = $e;
            } catch (\Throwable $e) {
                $this->error = new HttpException('Writing HTTP archive log failed', 0, $e);
            }
        });
    }
    /**
     *
     */
    private function ensureEventListenerIsRegistered(Request $request) : void
    {
        foreach ($request->getEventListeners() as $eventListener) {
            if ($eventListener instanceof RecordHarAttributes) {
                return;
                // user added it manually
            }
        }
        $request->addEventListener($this->eventListener);
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Response;
final class AddResponseHeader extends ModifyResponse
{
    /**
     *
     */
    public function __construct(string $headerName, string ...$headerValues)
    {
        parent::__construct(static function (Response $response) use($headerName, $headerValues) {
            $response->addHeader($headerName, $headerValues);
            return $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use League\Uri;
use Psr\Http\Message\UriInterface as PsrUri;
use function Amp\call;
final class FollowRedirects implements ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /**
    * Resolves the given path in $locationUri using $baseUri as a base URI. For example, a base URI of
    http://example.com/example/path and a location path of 'to/resolve' will return a URI of
    http://example.com/example/to/resolve.
    *
    * @param PsrUri $baseUri
    * @param PsrUri $locationUri
    *
    * @return PsrUri
    */
    public static function resolve(PsrUri $baseUri, PsrUri $locationUri) : PsrUri
    {
        if ((string) $locationUri === '') {
            return $baseUri;
        }
        if ($locationUri->getScheme() !== '' || $locationUri->getHost() !== '') {
            $resultUri = $locationUri->withPath(self::removeDotSegments($locationUri->getPath()));
            if ($locationUri->getScheme() === '') {
                $resultUri = $resultUri->withScheme($baseUri->getScheme());
            }
            return $resultUri;
        }
        $baseUri = $baseUri->withQuery($locationUri->getQuery());
        $baseUri = $baseUri->withFragment($locationUri->getFragment());
        if ($locationUri->getPath() !== '' && \Phabel\Target\Php80\Polyfill::substr($locationUri->getPath(), 0, 1) === "/") {
            $baseUri = $baseUri->withPath(self::removeDotSegments($locationUri->getPath()));
        } else {
            $baseUri = $baseUri->withPath(self::mergePaths($baseUri->getPath(), $locationUri->getPath()));
        }
        return $baseUri;
    }
    /**
     * @param string $input
     *
     * @return string
     *
     * @link http://www.apps.ietf.org/rfc/rfc3986.html#sec-5.2.4
     */
    private static function removeDotSegments(string $input) : string
    {
        $output = '';
        $patternA = ',^(\\.\\.?/),';
        $patternB1 = ',^(/\\./),';
        $patternB2 = ',^(/\\.)$,';
        $patternC = ',^(/\\.\\./|/\\.\\.),';
        // $patternD  = ',^(\.\.?)$,';
        $patternE = ',(/*[^/]*),';
        while ($input !== '') {
            if (\preg_match($patternA, $input)) {
                $input = \preg_replace($patternA, '', $input);
            } elseif (\preg_match($patternB1, $input, $match) || \preg_match($patternB2, $input, $match)) {
                $input = \preg_replace(",^" . $match[1] . ",", '/', $input);
            } elseif (\preg_match($patternC, $input, $match)) {
                $input = \preg_replace(',^' . \preg_quote($match[1], ',') . ',', '/', $input);
                $output = \preg_replace(',/([^/]+)$,', '', $output);
            } elseif ($input === '.' || $input === '..') {
                // pattern D
                $input = '';
            } elseif (\preg_match($patternE, $input, $match)) {
                $initialSegment = $match[1];
                $input = \preg_replace(',^' . \preg_quote($initialSegment, ',') . ',', '', $input, 1);
                $output .= $initialSegment;
            }
        }
        return $output;
    }
    /**
     * @param string $basePath
     * @param string $pathToMerge
     *
     * @return string
     *
     * @link http://tools.ietf.org/html/rfc3986#section-5.2.3
     */
    private static function mergePaths(string $basePath, string $pathToMerge) : string
    {
        if ($pathToMerge === '') {
            return self::removeDotSegments($basePath);
        }
        if ($basePath === '') {
            return self::removeDotSegments('/' . $pathToMerge);
        }
        $parts = \explode('/', $basePath);
        \array_pop($parts);
        $parts[] = $pathToMerge;
        return self::removeDotSegments(\implode('/', $parts));
    }
    /** @var int */
    private $maxRedirects;
    /** @var bool */
    private $autoReferrer;
    /**
     *
     */
    public function __construct(int $limit, bool $autoReferrer = true)
    {
        if ($limit < 1) {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \Error("Invalid redirection limit: " . $limit);
        }
        $this->maxRedirects = $limit;
        $this->autoReferrer = $autoReferrer;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        // Don't follow redirects on pushes, just store the redirect in cache (if an interceptor is configured)
        return call(function () use($request, $cancellation, $httpClient) {
            /** @var Response $response */
            $response = (yield $httpClient->request(clone $request, $cancellation));
            $response = (yield from $this->followRedirects($request, $response, $httpClient, $cancellation));
            return $response;
        });
    }
    /**
     *
     */
    private function followRedirects(Request $request, Response $response, DelegateHttpClient $client, CancellationToken $cancellationToken) : \Generator
    {
        $previousResponse = null;
        $maxRedirects = $this->maxRedirects;
        $requestNr = 2;
        do {
            $request = (yield from $this->createRedirectRequest($request, $response));
            if ($request === null) {
                return $response;
            }
            /** @var Response $redirectResponse */
            $redirectResponse = (yield $client->request(clone $request, $cancellationToken));
            $redirectResponse->setPreviousResponse($response);
            $response = $redirectResponse;
        } while (++$requestNr <= $maxRedirects + 1);
        if ($this->getRedirectUri($response) !== null) {
            throw new TooManyRedirectsException($response);
        }
        return $response;
    }
    /**
     *
     */
    private function createRedirectRequest(Request $originalRequest, Response $response) : \Generator
    {
        $redirectUri = $this->getRedirectUri($response);
        if ($redirectUri === null) {
            return null;
        }
        $originalUri = $response->getRequest()->getUri();
        $isSameHost = $redirectUri->getAuthority() === $originalUri->getAuthority();
        $request = clone $originalRequest;
        $request->setMethod('GET');
        $request->setUri($redirectUri);
        $request->removeHeader('transfer-encoding');
        $request->removeHeader('content-length');
        $request->removeHeader('content-type');
        $request->removeAttributes();
        $request->setBody(null);
        if (!$isSameHost) {
            // Remove for security reasons, any interceptor headers will be added again,
            // but application headers will be discarded.
            foreach ($request->getRawHeaders() as [$field]) {
                $request->removeHeader($field);
            }
        }
        if ($this->autoReferrer) {
            $this->assignRedirectRefererHeader($request, $originalUri, $redirectUri);
        }
        yield from $this->discardResponseBody($response);
        return $request;
    }
    /**
    * Clients must not add a Referer header when leaving an unencrypted resource and redirecting to an encrypted
    resource.
    *
    * @param Request $request
    * @param PsrUri $referrerUri
    * @param PsrUri $followUri
    *
    * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3
    */
    private function assignRedirectRefererHeader(Request $request, PsrUri $referrerUri, PsrUri $followUri) : void
    {
        $referrerIsEncrypted = $referrerUri->getScheme() === 'https';
        $destinationIsEncrypted = $followUri->getScheme() === 'https';
        if (!$referrerIsEncrypted || $destinationIsEncrypted) {
            $request->setHeader('Referer', (string) $referrerUri->withUserInfo('')->withFragment(''));
        } else {
            $request->removeHeader('Referer');
        }
    }
    /**
     *
     */
    private function getRedirectUri(Response $response) : ?PsrUri
    {
        if (\count($response->getHeaderArray('location')) !== 1) {
            return null;
        }
        $status = $response->getStatus();
        $request = $response->getRequest();
        $method = $request->getMethod();
        if ($method !== 'GET' && \in_array($status, [307, 308], true)) {
            return null;
        }
        // We don't automatically follow:
        // - 300 (Multiple Choices)
        // - 304 (Not Modified)
        // - 305 (Use Proxy)
        if (!\in_array($status, [301, 302, 303, 307, 308], true)) {
            return null;
        }
        try {
            $locationUri = Uri\Http::createFromString($response->getHeader('location'));
        } catch (\Exception $e) {
            return null;
        }
        return self::resolve($request->getUri(), $locationUri);
    }
    /**
     *
     */
    private function discardResponseBody(Response $response) : \Generator
    {
        // Discard response body of redirect responses
        $body = $response->getBody();
        try {
            /** @noinspection PhpStatementHasEmptyBodyInspection */
            /** @noinspection LoopWhichDoesNotLoopInspection */
            /** @noinspection MissingOrEmptyGroupStatementInspection */
            while (null !== (yield $body->read())) {
                // discard
            }
        } catch (HttpException|StreamException $e) {
            // ignore streaming errors on previous responses
        } finally {
            unset($body);
        }
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Response;
final class SetResponseHeader extends ModifyResponse
{
    /**
     *
     */
    public function __construct(string $headerName, string $headerValue, string ...$headerValues)
    {
        \array_unshift($headerValues, $headerValue);
        parent::__construct(static function (Response $response) use($headerName, $headerValues) {
            $response->setHeader($headerName, $headerValues);
            return $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Response;
final class RemoveResponseHeader extends ModifyResponse
{
    /**
     *
     */
    public function __construct(string $headerName)
    {
        parent::__construct(static function (Response $response) use($headerName) {
            $response->removeHeader($headerName);
            return $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class RemoveRequestHeader extends ModifyRequest
{
    /**
     *
     */
    public function __construct(string $headerName)
    {
        parent::__construct(static function (Request $request) use($headerName) {
            $request->removeHeader($headerName);
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Response;
final class SetResponseHeaderIfUnset extends ModifyResponse
{
    /**
     *
     */
    public function __construct(string $headerName, string $headerValue, string ...$headerValues)
    {
        \array_unshift($headerValues, $headerValue);
        parent::__construct(static function (Response $response) use($headerName, $headerValues) {
            if (!$response->hasHeader($headerName)) {
                $response->setHeader($headerName, $headerValues);
            }
            return $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use function Amp\call;
class ModifyRequest implements NetworkInterceptor, ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var callable(Request):(\Generator<mixed, mixed, mixed, Promise<Request|null>|Request|null>|Promise<Request|null>|Request|null) */
    private $mapper;
    /**
     * @psalm-param callable(Request ): (\Generator<mixed, mixed, mixed, (Promise<(Request | null)> | Request | null)> | Promise<(Request | null)> | Request | null) $mapper
     */
    public function __construct(callable $mapper)
    {
        $this->mapper = $mapper;
    }
    /**
     * @param Request $request
     * @param CancellationToken $cancellation
     * @param Stream $stream
     *
     * @return Promise<Response>
     */
    public final function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellation, $stream) {
            $mappedRequest = (yield call($this->mapper, $request));
            \assert($mappedRequest instanceof Request || $mappedRequest === null);
            return (yield $stream->request($mappedRequest ?? $request, $cancellation));
        });
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        return call(function () use($request, $cancellation, $httpClient) {
            $mappedRequest = (yield call($this->mapper, $request));
            \assert($mappedRequest instanceof Request || $mappedRequest === null);
            return $httpClient->request($mappedRequest ?? $request, $cancellation);
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class SetRequestTimeout extends ModifyRequest
{
    /**
     *
     */
    public function __construct(int $tcpConnectTimeout = 10000, int $tlsHandshakeTimeout = 10000, int $transferTimeout = 10000)
    {
        parent::__construct(static function (Request $request) use($tcpConnectTimeout, $tlsHandshakeTimeout, $transferTimeout) {
            $request->setTcpConnectTimeout($tcpConnectTimeout);
            $request->setTlsHandshakeTimeout($tlsHandshakeTimeout);
            $request->setTransferTimeout($transferTimeout);
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\Request;
final class ForbidUriUserInfo extends ModifyRequest
{
    /**
     *
     */
    public function __construct()
    {
        parent::__construct(static function (Request $request) {
            if ($request->getUri()->getUserInfo() !== '') {
                throw new InvalidRequestException($request, 'The user information (username:password) component of URIs has been deprecated (see https://tools.ietf.org/html/rfc3986#section-3.2.1 and https://tools.ietf.org/html/rfc7230#section-2.7.1); Instead, set an "Authorization" header containing "Basic " . \\base64_encode("username:password"). If you used HttpClientBuilder, you can use HttpClientBuilder::allowDeprecatedUriUserInfo() to disable this protection. Doing so is strongly discouraged and you need to be aware of any interceptor using UriInterface::__toString(), which might expose the password in headers or logs.');
            }
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\Connection\Http2ConnectionException;
use Amp\Http\Client\Connection\UnprocessedRequestException;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\SocketException;
use Amp\Promise;
use function Amp\call;
final class RetryRequests implements ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var int */
    private $retryLimit;
    /**
     *
     */
    public function __construct(int $retryLimit)
    {
        $this->retryLimit = $retryLimit;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        return call(function () use($request, $cancellation, $httpClient) {
            $attempt = 1;
            do {
                try {
                    return (yield $httpClient->request(clone $request, $cancellation));
                } catch (UnprocessedRequestException $exception) {
                    // Request was deemed retryable by connection, so carry on.
                } catch (SocketException|Http2ConnectionException $exception) {
                    if (!$request->isIdempotent()) {
                        throw $exception;
                    }
                    // Request can safely be retried.
                }
            } while ($attempt++ <= $this->retryLimit);
            throw $exception;
        });
    }
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Interceptor\DecompressResponse;
use Amp\Promise;
/**
 * Allows intercepting an application request to an HTTP resource.
 */
interface ApplicationInterceptor
{
    /**
    * Intercepts an application request to an HTTP resource.
    *
    * The implementation might modify the request, delegate the request handling to the `$httpClient`, and/or modify
    the response after the promise returned from `$httpClient->request(...)` resolves.
    *
    * An interceptor might also short-circuit and not delegate to the `$httpClient` at all.
    *
    * Any retry or cloned follow-up request must be manually cloned from `$request` to ensure a properly working
    interceptor chain, e.g. the {@see DecompressResponse} interceptor only decodes a response if the
    `accept-encoding` header isn't set manually. If the request isn't cloned, the first attempt will set the header
    and the second attempt will see the header and won't decode the response, because it thinks another interceptor
    or the application itself will care about the decoding.
    *
    * @param Request $request
    * @param CancellationToken $cancellation
    * @param DelegateHttpClient $httpClient
    *
    * @return Promise<Response>
    */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise;
}<?php

namespace Amp\Http\Client\Body;

use Amp\ByteStream\InputStream;
use Amp\File\Driver;
use Amp\Http\Client\RequestBody;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
use function Amp\File\getSize;
use function Amp\File\open;
use function Amp\File\openFile;
use function Amp\File\size;
final class FileBody implements RequestBody
{
    /** @var string */
    private $path;
    /**
     * @param string $path The filesystem path for the file we wish to send
     */
    public function __construct(string $path)
    {
        if (!\interface_exists(Driver::class)) {
            throw new \Error("File request bodies require amphp/file to be installed");
        }
        $this->path = $path;
    }
    /**
     *
     */
    public function createBodyStream() : InputStream
    {
        $handlePromise = \function_exists('Amp\\File\\openFile') ? openFile($this->path, "r") : open($this->path, "r");
        return new class($handlePromise) implements InputStream
        {
            /** @var Promise<InputStream> */
            private $promise;
            /** @var InputStream|null */
            private $stream;
            /**
             *
             */
            public function __construct(Promise $promise)
            {
                $this->promise = $promise;
                $this->promise->onResolve(function ($error, $stream) {
                    if ($error) {
                        return;
                    }
                    $this->stream = $stream;
                });
            }
            /**
             *
             */
            public function read() : Promise
            {
                if (!$this->stream) {
                    return call(function () {
                        /** @var InputStream $stream */
                        $stream = (yield $this->promise);
                        return $stream->read();
                    });
                }
                return $this->stream->read();
            }
        };
    }
    /**
     *
     */
    public function getHeaders() : Promise
    {
        return new Success([]);
    }
    /**
     *
     */
    public function getBodyLength() : Promise
    {
        return \function_exists('Amp\\File\\getSize') ? getSize($this->path) : size($this->path);
    }
}<?php

namespace Amp\Http\Client\Body;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\Http\Client\RequestBody;
use Amp\Promise;
use Amp\Success;
final class StringBody implements RequestBody
{
    private $body;
    /**
     *
     */
    public function __construct(string $body)
    {
        $this->body = $body;
    }
    /**
     *
     */
    public function createBodyStream() : InputStream
    {
        return new InMemoryStream($this->body !== '' ? $this->body : null);
    }
    /**
     *
     */
    public function getHeaders() : Promise
    {
        return new Success([]);
    }
    /**
     *
     */
    public function getBodyLength() : Promise
    {
        return new Success(\strlen($this->body));
    }
}<?php

namespace Amp\Http\Client\Body;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\ByteStream\IteratorStream;
use Amp\Http\Client\RequestBody;
use Amp\Producer;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class FormBody implements RequestBody
{
    /** @var (array{0: string, 1: string, 2: string, 3: null}|array{0: string, 1: FileBody, 2: string, 3: string})[] */
    private $fields = [];
    /** @var string */
    private $boundary;
    /** @var bool */
    private $isMultipart = false;
    /** @var string|null */
    private $cachedBody;
    /** @var Promise<int>|null */
    private $cachedLength;
    /** @var list<string|FileBody>|null */
    private $cachedFields;
    /**
     * @param string $boundary An optional multipart boundary string
     */
    public function __construct(string $boundary = null)
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        $this->boundary = $boundary ?? \bin2hex(\random_bytes(16));
    }
    /**
     * Add a data field to the form entity body.
     *
     * @param string $name
     * @param string $value
     * @param string $contentType
     */
    public function addField(string $name, string $value, string $contentType = 'text/plain') : void
    {
        $this->fields[] = [$name, $value, $contentType, null];
        $this->resetCache();
    }
    /**
     * Add each element of a associative array as a data field to the form entity body.
     *
     * @param array $data
     * @param string $contentType
     */
    public function addFields(array $data, string $contentType = 'text/plain') : void
    {
        foreach ($data as $key => $value) {
            $this->addField($key, $value, $contentType);
        }
    }
    /**
     * Add a file field to the form entity body.
     *
     * @param string $name
     * @param string $filePath
     * @param string $contentType
     */
    public function addFile(string $name, string $filePath, string $contentType = 'application/octet-stream') : void
    {
        $fileName = \basename($filePath);
        $this->fields[] = [$name, new FileBody($filePath), $contentType, $fileName];
        $this->isMultipart = true;
        $this->resetCache();
    }
    /**
     * Add each element of a associative array as a file field to the form entity body.
     *
     * @param array $data
     * @param string $contentType
     */
    public function addFiles(array $data, string $contentType = 'application/octet-stream') : void
    {
        foreach ($data as $key => $value) {
            $this->addFile($key, $value, $contentType);
        }
    }
    /**
     * Add a file field to the form from a string.
     *
     * @param string $name
     * @param string $fileContent
     * @param string $fileName
     * @param string $contentType
     */
    public function addFileFromString(string $name, string $fileContent, string $fileName, string $contentType = 'application/octet-stream') : void
    {
        $this->fields[] = [$name, $fileContent, $contentType, $fileName];
        $this->isMultipart = true;
        $this->resetCache();
    }
    /**
    * Returns an array of fields, each being an array of [name, value, content-type, file-name|null].
    Both fields and files are returned in the array. Files use a FileBody object as the value. The file-name is
    always null for fields.
    *
    * @return array
    */
    public function getFields() : array
    {
        return $this->fields;
    }
    /**
     *
     */
    private function resetCache() : void
    {
        $this->cachedBody = null;
        $this->cachedLength = null;
        $this->cachedFields = null;
    }
    /**
     *
     */
    public function createBodyStream() : InputStream
    {
        if ($this->isMultipart) {
            return $this->generateMultipartStreamFromFields($this->getMultipartFieldArray());
        }
        return new InMemoryStream($this->getFormEncodedBodyString());
    }
    /**
     *
     */
    private function getMultipartFieldArray() : array
    {
        if (isset($this->cachedFields)) {
            return $this->cachedFields;
        }
        $fields = [];
        foreach ($this->fields as $fieldArr) {
            [$name, $field, $contentType, $fileName] = $fieldArr;
            $fields[] = "--{$this->boundary}\r\n";
            /** @psalm-suppress PossiblyNullArgument */
            $fields[] = $fileName !== null ? $this->generateMultipartFileHeader($name, $fileName, $contentType) : $this->generateMultipartFieldHeader($name, $contentType);
            $fields[] = $field;
            $fields[] = "\r\n";
        }
        $fields[] = "--{$this->boundary}--\r\n";
        return $this->cachedFields = $fields;
    }
    /**
     *
     */
    private function generateMultipartFileHeader(string $name, string $fileName, string $contentType) : string
    {
        $header = "Content-Disposition: form-data; name=\"{$name}\"; filename=\"{$fileName}\"\r\n";
        $header .= "Content-Type: {$contentType}\r\n";
        $header .= "Content-Transfer-Encoding: binary\r\n\r\n";
        return $header;
    }
    /**
     *
     */
    private function generateMultipartFieldHeader(string $name, string $contentType) : string
    {
        $header = "Content-Disposition: form-data; name=\"{$name}\"\r\n";
        if ($contentType !== "") {
            $header .= "Content-Type: {$contentType}\r\n\r\n";
        } else {
            $header .= "\r\n";
        }
        return $header;
    }
    /**
     *
     */
    private function generateMultipartStreamFromFields(array $fields) : InputStream
    {
        foreach ($fields as $key => $field) {
            $fields[$key] = $field instanceof FileBody ? $field->createBodyStream() : new InMemoryStream($field);
        }
        return new IteratorStream(new Producer(static function (callable $emit) use($fields) {
            foreach ($fields as $key => $stream) {
                while (($chunk = (yield $stream->read())) !== null) {
                    (yield $emit($chunk));
                }
            }
        }));
    }
    /**
     *
     */
    private function getFormEncodedBodyString() : string
    {
        if ($this->cachedBody) {
            return $this->cachedBody;
        }
        $fields = [];
        foreach ($this->fields as $fieldArr) {
            [$name, $value] = $fieldArr;
            $fields[$name][] = $value;
        }
        foreach ($fields as $key => $value) {
            $fields[$key] = isset($value[1]) ? $value : $value[0];
        }
        return $this->cachedBody = \http_build_query($fields);
    }
    /**
     *
     */
    public function getHeaders() : Promise
    {
        return new Success(['Content-Type' => $this->determineContentType()]);
    }
    /**
     *
     */
    private function determineContentType() : string
    {
        return $this->isMultipart ? "multipart/form-data; boundary={$this->boundary}" : 'application/x-www-form-urlencoded';
    }
    /**
     *
     */
    public function getBodyLength() : Promise
    {
        if ($this->cachedLength) {
            return $this->cachedLength;
        }
        if (!$this->isMultipart) {
            return $this->cachedLength = new Success(\strlen($this->getFormEncodedBodyString()));
        }
        /** @var Promise<int> $lengthPromise */
        $lengthPromise = call(function () : \Generator {
            $fields = $this->getMultipartFieldArray();
            $length = 0;
            foreach ($fields as $field) {
                if (\is_string($field)) {
                    $length += \strlen($field);
                } else {
                    $length += (yield $field->getBodyLength());
                }
            }
            return $length;
        });
        return $this->cachedLength = $lengthPromise;
    }
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\Http\Client\Body;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\RequestBody;
use Amp\Promise;
use Amp\Success;
final class JsonBody implements RequestBody
{
    /** @var string */
    private $json;
    /**
     * JsonBody constructor.
     *
     * @param mixed $data
     * @param int $options
     * @param int $depth
     *
     * @throws HttpException
     */
    public function __construct($data, int $options = 0, int $depth = 512)
    {
        $this->json = \json_encode($data, $options, $depth);
        if (\json_last_error() !== \JSON_ERROR_NONE) {
            throw new HttpException('Failed to encode data to JSON');
        }
    }
    /**
     *
     */
    public function getHeaders() : Promise
    {
        return new Success(['content-type' => 'application/json; charset=utf-8']);
    }
    /**
     *
     */
    public function createBodyStream() : InputStream
    {
        return new InMemoryStream($this->json);
    }
    /**
     *
     */
    public function getBodyLength() : Promise
    {
        return new Success(\strlen($this->json));
    }
}<?php

namespace Amp\Http\Client;

use Amp\Http\Client\Connection\ConnectionPool;
use Amp\Http\Client\Connection\Stream;
use Amp\Promise;
/**
 * Allows listening to more fine granular events than interceptors are able to achieve.
 *
 * All event listener methods might be called multiple times for a single request. The implementing listener is
 * responsible to detect another call, e.g. via attributes in the request.
 */
interface EventListener
{
    /**
     * Called at the very beginning of {@see DelegateHttpClient::request()}.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startRequest(Request $request) : Promise;
    /**
     * Optionally called by {@see ConnectionPool::getStream()} before DNS resolution is started.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startDnsResolution(Request $request) : Promise;
    /**
     * Optionally called by {@see ConnectionPool::getStream()} after DNS resolution is completed.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeDnsResolution(Request $request) : Promise;
    /**
     * Called by {@see ConnectionPool::getStream()} before a new connection is initiated.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startConnectionCreation(Request $request) : Promise;
    /**
     * Called by {@see ConnectionPool::getStream()} after a new connection is established and TLS negotiated.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeConnectionCreation(Request $request) : Promise;
    /**
     * Called by {@see ConnectionPool::getStream()} before TLS negotiation is started (only if HTTPS is used).
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startTlsNegotiation(Request $request) : Promise;
    /**
     * Called by {@see ConnectionPool::getStream()} after TLS negotiation is successful (only if HTTPS is used).
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeTlsNegotiation(Request $request) : Promise;
    /**
     * Called by {@see Stream::request()} before the request is sent.
     *
     * @param Request $request
     * @param Stream $stream
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startSendingRequest(Request $request, Stream $stream) : Promise;
    /**
     * Called by {@see Stream::request()} after the request is sent.
     *
     * @param Request $request
     * @param Stream $stream
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeSendingRequest(Request $request, Stream $stream) : Promise;
    /**
     * Called by {@see Stream::request()} after the first response byte is received.
     *
     * @param Request $request
     * @param Stream $stream
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startReceivingResponse(Request $request, Stream $stream) : Promise;
    /**
     * Called by {@see Stream::request()} after the request is complete.
     *
     * @param Request $request
     * @param Stream $stream
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeReceivingResponse(Request $request, Stream $stream) : Promise;
    /**
     * Called if the request is aborted.
     *
     * @param Request $request
     * @param \Throwable $cause
     *
     * @return Promise Should resolve successfully.
     */
    public function abort(Request $request, \Throwable $cause) : Promise;
}<?php

namespace Amp\Http\Client;

final class TimeoutException extends HttpException
{
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Request;
use Amp\Promise;
interface ConnectionFactory
{
    /**
    * During connection establishment, the factory must call the {@see EventListener::startConnectionCreation()},
    {@see EventListener::startTlsNegotiation()}, {@see EventListener::completeTlsNegotiation()}, and
    {@see EventListener::completeConnectionCreation()} on all event listeners registered on the given request in the
    order defined by {@see Request::getEventListeners()} as appropriate (TLS events are only invoked if TLS is
    used). Before calling the next listener, the promise returned from the previous one must resolve successfully.
    *
    * Additionally, the factory may invoke {@see EventListener::startDnsResolution()} and
    {@see EventListener::completeDnsResolution()}, but is not required to implement such granular events.
    *
    * @param Request $request
    * @param CancellationToken $cancellationToken
    *
    * @return Promise
    */
    public function create(Request $request, CancellationToken $cancellationToken) : Promise;
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\EventListener;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
interface Stream extends DelegateHttpClient
{
    /**
    * Executes the request.
    *
    * This method may only be invoked once per instance.
    *
    * The stream must call {@see EventListener::startSendingRequest()},
    {@see EventListener::completeSendingRequest()}, {@see EventListener::startReceivingResponse()}, and
    {@see EventListener::completeReceivingResponse()} event listener methods on all event listeners registered on
    the given request in the order defined by {@see Request::getEventListeners()}. Before calling the next listener,
    the promise returned from the previous one must resolve successfully.
    *
    * @param Request $request
    * @param CancellationToken $cancellation
    *
    * @return Promise<Response>
    *
    * @throws \Error Thrown if this method is called more than once.
    */
    public function request(Request $request, CancellationToken $cancellation) : Promise;
    /**
     *
     */
    public function getLocalAddress() : SocketAddress;
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress;
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo;
}<?php

namespace Amp\Http\Client\Connection;

// Alias for backward compatibility.
\class_alias(StreamLimitingPool::class, LimitedConnectionPool::class);<?php

namespace Amp\Http\Client\Connection;

use Amp\Http\Client\HttpException;
/**
 * @deprecated Exception moved to amphp/http. Catch the base exception class (HttpException) instead.
 */
final class Http2ConnectionException extends HttpException
{
    /**
     *
     */
    public function __construct(string $message, int $code, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Http\Client\Connection\Internal;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Loop;
use Amp\Promise;
use Amp\Struct;
/**
 * Used in Http2Connection.
 *
 * @internal
 */
final class Http2Stream
{
    use Struct;
    use ForbidSerialization;
    use ForbidCloning;
    /** @var int */
    public $id;
    /** @var Request */
    public $request;
    /** @var Response|null */
    public $response;
    /** @var Deferred|null */
    public $pendingResponse;
    /** @var Promise|null */
    public $preResponseResolution;
    /** @var bool */
    public $responsePending = true;
    /** @var Emitter|null */
    public $body;
    /** @var Deferred|null */
    public $trailers;
    /** @var CancellationToken */
    public $originalCancellation;
    /** @var CancellationToken */
    public $cancellationToken;
    /** @var int Bytes received on the stream. */
    public $received = 0;
    /** @var int */
    public $serverWindow;
    /** @var int */
    public $clientWindow;
    /** @var int */
    public $bufferSize;
    /** @var string */
    public $requestBodyBuffer = '';
    /** @var bool */
    public $requestBodyComplete = false;
    /** @var Deferred */
    public $requestBodyCompletion;
    /** @var int Integer between 1 and 256 */
    public $weight = 16;
    /** @var int */
    public $dependency = 0;
    /** @var int|null */
    public $expectedLength;
    /** @var Stream */
    public $stream;
    /** @var Deferred|null */
    public $windowSizeIncrease;
    /** @var string|null */
    private $watcher;
    /**
     *
     */
    public function __construct(int $id, Request $request, Stream $stream, CancellationToken $cancellationToken, CancellationToken $originalCancellation, ?string $watcher, int $serverSize, int $clientSize)
    {
        $this->id = $id;
        $this->request = $request;
        $this->stream = $stream;
        $this->cancellationToken = $cancellationToken;
        $this->originalCancellation = $originalCancellation;
        $this->watcher = $watcher;
        $this->serverWindow = $serverSize;
        $this->clientWindow = $clientSize;
        $this->pendingResponse = new Deferred();
        $this->requestBodyCompletion = new Deferred();
        $this->bufferSize = 0;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->watcher !== null) {
            Loop::cancel($this->watcher);
        }
    }
    /**
     *
     */
    public function disableInactivityWatcher() : void
    {
        if ($this->watcher === null) {
            return;
        }
        Loop::disable($this->watcher);
    }
    /**
     *
     */
    public function enableInactivityWatcher() : void
    {
        if ($this->watcher === null) {
            return;
        }
        Loop::disable($this->watcher);
        Loop::enable($this->watcher);
    }
}<?php

/** @noinspection PhpUnusedPrivateFieldInspection */
namespace Amp\Http\Client\Connection\Internal;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\IteratorStream;
use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\CancellationTokenSource;
use Amp\CancelledException;
use Amp\CombinedCancellationToken;
use Amp\Coroutine;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Failure;
use Amp\Http\Client\Connection\Http2ConnectionException as ClientHttp2ConnectionException;
use Amp\Http\Client\Connection\Http2StreamException as ClientHttp2StreamException;
use Amp\Http\Client\Connection\HttpStream;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Connection\UnprocessedRequestException;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ResponseBodyStream;
use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Client\SocketException;
use Amp\Http\Client\TimeoutException;
use Amp\Http\Client\Trailers;
use Amp\Http\HPack;
use Amp\Http\Http2\Http2ConnectionException;
use Amp\Http\Http2\Http2Parser;
use Amp\Http\Http2\Http2Processor;
use Amp\Http\Http2\Http2StreamException;
use Amp\Http\InvalidHeaderException;
use Amp\Http\Status;
use Amp\Iterator;
use Amp\Loop;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Success;
use Amp\TimeoutCancellationToken;
use League\Uri;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\Http\Client\Internal\normalizeRequestPathWithQuery;
/** @internal */
final class Http2ConnectionProcessor implements Http2Processor
{
    private const PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
    private const DEFAULT_MAX_FRAME_SIZE = 1 << 14;
    private const DEFAULT_WINDOW_SIZE = (1 << 16) - 1;
    private const MINIMUM_WINDOW = 512 * 1024;
    private const WINDOW_INCREMENT = 1024 * 1024;
    // Milliseconds to wait for pong (PING with ACK) frame before closing the connection.
    private const PONG_TIMEOUT = 5000;
    /** @var string 64-bit for ping. */
    private $counter = "aaaaaaaa";
    /** @var EncryptableSocket */
    private $socket;
    /** @var Http2Stream[] */
    private $streams = [];
    /** @var int */
    private $serverWindow = self::DEFAULT_WINDOW_SIZE;
    /** @var int */
    private $clientWindow = self::DEFAULT_WINDOW_SIZE;
    /** @var int */
    private $initialWindowSize = self::DEFAULT_WINDOW_SIZE;
    /** @var int */
    private $frameSizeLimit = self::DEFAULT_MAX_FRAME_SIZE;
    /** @var int Previous stream ID. */
    private $streamId = -1;
    /** @var int Maximum number of streams that may be opened. Initially unlimited. */
    private $concurrentStreamLimit = 2147483647;
    /** @var int Currently open or reserved streams. Initially unlimited. */
    private $remainingStreams = 2147483647;
    /** @var HPack */
    private $hpack;
    /** @var Deferred|null */
    private $settings;
    /** @var bool */
    private $initializeStarted = false;
    /** @var bool */
    private $initialized = false;
    /** @var string|null */
    private $pongWatcher;
    /** @var Deferred|null */
    private $pongDeferred;
    /** @var string|null */
    private $idleWatcher;
    /** @var int */
    private $idlePings = 0;
    /** @var callable[]|null */
    private $onClose = [];
    /** @var bool */
    private $hasTimeout = false;
    /** @var bool */
    private $hasWriteError = false;
    /** @var int|null */
    private $shutdown;
    /** @var Emitter */
    private $frameQueueEmitter;
    /** @var Iterator */
    private $frameQueue;
    /**
     *
     */
    public function __construct(EncryptableSocket $socket)
    {
        $this->socket = $socket;
        $this->hpack = new HPack();
        $this->frameQueueEmitter = new Emitter();
        $this->frameQueue = $this->frameQueueEmitter->iterate();
    }
    /**
     *
     */
    public function isInitialized() : bool
    {
        return $this->initialized;
    }
    /**
    * Returns a promise that is resolved once the connection has been initialized. A stream cannot be obtained from the
    connection until the promise returned by this method resolves.
    *
    * @return Promise
    */
    public function initialize() : Promise
    {
        if ($this->initializeStarted) {
            throw new \Error('Connection may only be initialized once');
        }
        $this->initializeStarted = true;
        if ($this->socket->isClosed()) {
            return new Failure(new UnprocessedRequestException(new SocketException('The socket closed before the connection could be initialized')));
        }
        $this->settings = new Deferred();
        $promise = $this->settings->promise();
        Promise\rethrow(new Coroutine($this->run()));
        return $promise;
    }
    /**
     *
     */
    public function onClose(callable $onClose) : void
    {
        if ($this->onClose === null) {
            asyncCall($onClose, $this);
            return;
        }
        $this->onClose[] = $onClose;
    }
    /**
     *
     */
    public function close() : Promise
    {
        $this->shutdown(new SocketException('Socket from \'' . $this->socket->getLocalAddress() . '\' to \'' . $this->socket->getRemoteAddress() . '\' closed'));
        $this->socket->close();
        if ($this->onClose !== null) {
            $onClose = $this->onClose;
            $this->onClose = null;
            foreach ($onClose as $callback) {
                asyncCall($callback, $this);
            }
        }
        return new Success();
    }
    /**
     *
     */
    public function handlePong(string $data) : void
    {
        if ($this->pongDeferred === null) {
            return;
        }
        if ($this->pongWatcher !== null) {
            Loop::cancel($this->pongWatcher);
            $this->pongWatcher = null;
        }
        $this->hasTimeout = false;
        $deferred = $this->pongDeferred;
        $this->pongDeferred = null;
        $deferred->resolve(true);
    }
    /**
     *
     */
    public function handlePing(string $data) : void
    {
        $this->writeFrame(Http2Parser::PING, Http2Parser::ACK, 0, $data);
    }
    /**
     *
     */
    public function handleShutdown(int $lastId, int $error) : void
    {
        $message = \sprintf("Received GOAWAY frame on '%s' from '%s' with error code %d", (string) $this->socket->getLocalAddress(), (string) $this->socket->getRemoteAddress(), $error);
        /**
         * @psalm-suppress DeprecatedClass
         * @noinspection PhpDeprecationInspection
         */
        $this->shutdown(new ClientHttp2ConnectionException($message, $error), $lastId);
    }
    /**
     *
     */
    public function handleStreamWindowIncrement(int $streamId, int $windowSize) : void
    {
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        if ($stream->clientWindow + $windowSize > 2147483647) {
            $this->handleStreamException(new Http2StreamException("Current window size plus new window exceeds maximum size", $streamId, Http2Parser::FLOW_CONTROL_ERROR));
            return;
        }
        $stream->clientWindow += $windowSize;
        $this->writeBufferedData($stream);
    }
    /**
     *
     */
    public function handleConnectionWindowIncrement(int $windowSize) : void
    {
        if ($this->clientWindow + $windowSize > 2147483647) {
            $this->handleConnectionException(new Http2ConnectionException("Current window size plus new window exceeds maximum size", Http2Parser::FLOW_CONTROL_ERROR));
            return;
        }
        $this->clientWindow += $windowSize;
        foreach ($this->streams as $stream) {
            if ($this->clientWindow <= 0) {
                return;
            }
            if ($stream->requestBodyBuffer === '' || $stream->clientWindow <= 0) {
                continue;
            }
            $this->writeBufferedData($stream);
        }
    }
    /**
     *
     */
    public function handleHeaders(int $streamId, array $pseudo, array $headers, bool $streamEnded) : void
    {
        foreach ($pseudo as $name => $value) {
            if (!isset(Http2Parser::KNOWN_RESPONSE_PSEUDO_HEADERS[$name])) {
                throw new Http2StreamException("Invalid pseudo header", $streamId, Http2Parser::PROTOCOL_ERROR);
            }
        }
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        $stream->enableInactivityWatcher();
        $this->hasTimeout = false;
        if ($stream->trailers) {
            if ($stream->expectedLength && $stream->received !== $stream->expectedLength) {
                $diff = $stream->expectedLength - $stream->received;
                $this->handleStreamException(new Http2StreamException("Content length mismatch: " . \abs($diff) . ' bytes ' . ($diff > 0 ? ' missing' : 'too much'), $streamId, Http2Parser::PROTOCOL_ERROR));
                return;
            }
            if (!empty($pseudo)) {
                $this->handleStreamException(new Http2StreamException("Trailers must not contain pseudo headers", $streamId, Http2Parser::PROTOCOL_ERROR));
                return;
            }
            try {
                // Constructor checks for any disallowed fields
                $parsedTrailers = new Trailers($headers);
            } catch (InvalidHeaderException $exception) {
                $this->handleStreamException(new Http2StreamException("Disallowed field names in trailer", $streamId, Http2Parser::PROTOCOL_ERROR, $exception));
                return;
            }
            $trailers = $stream->trailers;
            $stream->trailers = null;
            $trailers->resolve(call(function () use($stream, $streamId, $parsedTrailers) {
                try {
                    foreach ($stream->request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeReceivingResponse($stream->request, $stream->stream));
                    }
                    return $parsedTrailers;
                } catch (\Throwable $e) {
                    $this->handleStreamException(new Http2StreamException("Event listener error", $streamId, Http2Parser::CANCEL));
                    throw $e;
                }
            }));
            $this->setupPingIfIdle();
            return;
        }
        if (!isset($pseudo[":status"])) {
            $this->handleConnectionException(new Http2ConnectionException("No status pseudo header in response", Http2Parser::PROTOCOL_ERROR));
            return;
        }
        if (!\preg_match("/^[1-5]\\d\\d\$/", $pseudo[":status"])) {
            $this->handleStreamException(new Http2StreamException("Invalid response status code: " . $pseudo[':status'], $streamId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        if ($stream->response !== null) {
            $this->handleStreamException(new Http2StreamException("Stream headers already received", $streamId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $status = (int) $pseudo[":status"];
        if ($status === Status::SWITCHING_PROTOCOLS) {
            $this->handleConnectionException(new Http2ConnectionException("Switching Protocols (101) is not part of HTTP/2", Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $response = new Response('2', $status, Status::getReason($status), $headers, new InMemoryStream(), $stream->request);
        if ($status < 200) {
            $onInformationalResponse = $stream->request->getInformationalResponseHandler();
            if ($onInformationalResponse !== null) {
                $stream->preResponseResolution = call(function () use($onInformationalResponse, $response, $stream, $streamId) {
                    (yield $stream->preResponseResolution);
                    try {
                        (yield call($onInformationalResponse, $response));
                    } catch (\Throwable $e) {
                        $this->handleStreamException(new Http2StreamException('Informational response handler threw an exception', $streamId, Http2Parser::CANCEL));
                    }
                });
            }
            return;
        }
        \assert($stream->preResponseResolution === null);
        $stream->preResponseResolution = call(function () use($stream, $streamId) {
            try {
                foreach ($stream->request->getEventListeners() as $eventListener) {
                    (yield $eventListener->startReceivingResponse($stream->request, $stream->stream));
                }
            } catch (\Throwable $e) {
                $this->handleStreamException(new Http2StreamException("Event listener error", $streamId, Http2Parser::CANCEL));
            }
        });
        $stream->body = new Emitter();
        $stream->trailers = new Deferred();
        $bodyCancellation = new CancellationTokenSource();
        $cancellationToken = new CombinedCancellationToken($stream->cancellationToken, $bodyCancellation->getToken());
        $response->setBody(new ResponseBodyStream(new IteratorStream($stream->body->iterate()), $bodyCancellation));
        $response->setTrailers($stream->trailers->promise());
        \assert($stream->pendingResponse !== null);
        $stream->responsePending = false;
        $stream->pendingResponse->resolve(call(static function () use($response, $stream) {
            (yield $stream->requestBodyCompletion->promise());
            (yield $stream->preResponseResolution);
            $stream->preResponseResolution = null;
            $stream->pendingResponse = null;
            return $response;
        }));
        $this->increaseConnectionWindow();
        $this->increaseStreamWindow($stream);
        if (isset($headers["content-length"])) {
            if (\count($headers['content-length']) !== 1) {
                $this->handleStreamException(new Http2StreamException("Multiple content-length header values", $streamId, Http2Parser::PROTOCOL_ERROR));
                return;
            }
            $contentLength = $headers["content-length"][0];
            if (!\preg_match('/^(0|[1-9][0-9]*)$/', $contentLength)) {
                $this->handleStreamException(new Http2StreamException("Invalid content-length header value", $streamId, Http2Parser::PROTOCOL_ERROR));
                return;
            }
            $stream->expectedLength = (int) $contentLength;
        }
        $cancellationToken->subscribe(function (CancelledException $exception) use($streamId) : void {
            if (!isset($this->streams[$streamId])) {
                return;
            }
            $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $streamId, \pack("N", Http2Parser::CANCEL));
            if (!$this->streams[$streamId]->originalCancellation->isRequested()) {
                $this->hasTimeout = true;
                $this->ping();
                // async ping, if other requests occur, they wait for it
                $transferTimeout = $this->streams[$streamId]->request->getTransferTimeout();
                $exception = new TimeoutException('Allowed transfer timeout exceeded, took longer than ' . $transferTimeout . ' ms', 0, $exception);
            }
            $this->releaseStream($streamId, $exception);
        });
    }
    /**
     *
     */
    public function handlePushPromise(int $streamId, int $pushId, array $pseudo, array $headers) : void
    {
        if ($pushId % 2 === 1) {
            $this->handleConnectionException(new Http2ConnectionException("Invalid server initiated stream", Http2Parser::PROTOCOL_ERROR));
            return;
        }
        foreach ($pseudo as $name => $value) {
            if (!isset(Http2Parser::KNOWN_REQUEST_PSEUDO_HEADERS[$name])) {
                throw new Http2StreamException("Invalid pseudo header", $pushId, Http2Parser::PROTOCOL_ERROR);
            }
        }
        if (!isset($pseudo[":method"], $pseudo[":path"], $pseudo[":scheme"], $pseudo[":authority"]) || isset($headers["connection"]) || $pseudo[":path"] === '' || isset($headers["te"]) && \implode($headers["te"]) !== "trailers") {
            $this->handleStreamException(new Http2StreamException("Invalid header values", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $method = $pseudo[":method"];
        $target = $pseudo[":path"];
        $scheme = $pseudo[":scheme"];
        $host = $pseudo[":authority"];
        $query = null;
        if ($method !== 'GET' && $method !== 'HEAD') {
            $this->handleStreamException(new Http2StreamException("Pushed request method must be a safe method", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        if (!\preg_match("#^([A-Z\\d.\\-]+|\\[[\\d:]+])(?::([1-9]\\d*))?\$#i", $host, $matches)) {
            $this->handleStreamException(new Http2StreamException("Invalid pushed authority (host) name", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $host = $matches[1];
        $port = isset($matches[2]) ? (int) $matches[2] : $this->socket->getRemoteAddress()->getPort();
        if (!isset($this->streams[$streamId])) {
            $this->handleStreamException(new Http2StreamException("Parent stream {$streamId} is no longer open", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $parentStream = $this->streams[$streamId];
        $parentStream->enableInactivityWatcher();
        if (\strcasecmp($host, $parentStream->request->getUri()->getHost()) !== 0) {
            $this->handleStreamException(new Http2StreamException("Authority does not match original request authority", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        if ($position = \strpos($target, "#")) {
            $target = \Phabel\Target\Php80\Polyfill::substr($target, 0, $position);
        }
        if ($position = \strpos($target, "?")) {
            $query = \Phabel\Target\Php80\Polyfill::substr($target, $position + 1);
            $target = \Phabel\Target\Php80\Polyfill::substr($target, 0, $position);
        }
        try {
            $uri = Uri\Http::createFromComponents(["scheme" => $scheme, "host" => $host, "port" => $port, "path" => $target, "query" => $query]);
        } catch (\Exception $exception) {
            $this->handleConnectionException(new Http2ConnectionException("Invalid push URI", Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $request = new Request($uri, $method);
        $request->setHeaders($headers);
        $request->setProtocolVersions(['2']);
        $request->setPushHandler($parentStream->request->getPushHandler());
        $request->setHeaderSizeLimit($parentStream->request->getHeaderSizeLimit());
        $request->setBodySizeLimit($parentStream->request->getBodySizeLimit());
        $request->setInactivityTimeout($parentStream->request->getInactivityTimeout());
        $request->setTransferTimeout($parentStream->request->getTransferTimeout());
        $stream = new Http2Stream($pushId, $request, HttpStream::fromStream($parentStream->stream, static function () {
            throw new \Error('Calling Stream::request() on a pushed request is forbidden');
        }, static function () {
            // nothing to do
        }), $parentStream->cancellationToken, $parentStream->originalCancellation, $this->createStreamInactivityWatcher($pushId, $request->getInactivityTimeout()), self::DEFAULT_WINDOW_SIZE, 0);
        $stream->dependency = $streamId;
        $this->streams[$pushId] = $stream;
        $stream->requestBodyComplete = true;
        $stream->requestBodyCompletion->resolve();
        if ($parentStream->request->getPushHandler() === null) {
            $this->handleStreamException(new Http2StreamException("Push promise refused", $pushId, Http2Parser::CANCEL));
            return;
        }
        asyncCall(function () use($pushId, $stream) : \Generator {
            $tokenSource = new CancellationTokenSource();
            $cancellationToken = new CombinedCancellationToken($stream->cancellationToken, $tokenSource->getToken());
            $cancellationId = $cancellationToken->subscribe(function (CancelledException $exception) use($pushId) : void {
                if (!isset($this->streams[$pushId])) {
                    return;
                }
                $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $pushId, \pack("N", Http2Parser::CANCEL));
                $this->releaseStream($pushId, $exception);
            });
            $onPush = $stream->request->getPushHandler();
            try {
                \assert($onPush !== null);
                \assert($stream->pendingResponse !== null);
                (yield call($onPush, $stream->request, $stream->pendingResponse->promise()));
            } catch (HttpException|StreamException|CancelledException $exception) {
                $tokenSource->cancel($exception);
            } catch (\Throwable $exception) {
                $tokenSource->cancel($exception);
                throw $exception;
            } finally {
                $cancellationToken->unsubscribe($cancellationId);
            }
        });
    }
    /**
     *
     */
    public function handlePriority(int $streamId, int $parentId, int $weight) : void
    {
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        $stream->dependency = $parentId;
        $stream->weight = $weight;
    }
    /**
     *
     */
    public function handleStreamReset(int $streamId, int $errorCode) : void
    {
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $this->handleStreamException(new Http2StreamException("Stream closed by server", $streamId, $errorCode));
    }
    /**
     *
     */
    public function handleStreamException(Http2StreamException $exception) : void
    {
        $id = $exception->getStreamId();
        $code = $exception->getCode();
        /**
         * @psalm-suppress DeprecatedClass
         * @psalm-suppress InvalidScalarArgument
         * @noinspection PhpDeprecationInspection
         */
        $exception = new ClientHttp2StreamException($exception->getMessage(), $id, $code, $exception);
        if ($code === Http2Parser::REFUSED_STREAM) {
            $exception = new UnprocessedRequestException($exception);
        }
        $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $id, \pack("N", $code));
        if (isset($this->streams[$id])) {
            $this->releaseStream($id, $exception);
        }
    }
    /**
     *
     */
    public function handleConnectionException(Http2ConnectionException $exception) : void
    {
        /**
         * @psalm-suppress DeprecatedClass
         * @psalm-suppress InvalidScalarArgument
         * @noinspection PhpDeprecationInspection
         */
        $this->shutdown(new ClientHttp2ConnectionException($exception->getMessage(), $exception->getCode(), $exception));
        $this->close();
    }
    /**
     *
     */
    public function handleData(int $streamId, string $data) : void
    {
        $length = \strlen($data);
        $this->serverWindow -= $length;
        $this->increaseConnectionWindow();
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        $stream->disableInactivityWatcher();
        if (!$stream->body) {
            $this->handleStreamException(new Http2StreamException("Stream headers not complete or body already complete", $streamId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $stream->serverWindow -= $length;
        $stream->received += $length;
        $stream->bufferSize += $length;
        if ($stream->request->getBodySizeLimit() > 0 && $stream->received >= $stream->request->getBodySizeLimit()) {
            $this->handleStreamException(new Http2StreamException("Body size limit exceeded", $streamId, Http2Parser::CANCEL));
            return;
        }
        if ($stream->expectedLength !== null && $stream->received > $stream->expectedLength) {
            $this->handleStreamException(new Http2StreamException("Body size exceeded content-length in header", $streamId, Http2Parser::CANCEL));
            return;
        }
        $promise = $stream->body->emit($data);
        $promise->onResolve(function (?\Throwable $exception) use($streamId, $length) : void {
            if ($exception || !isset($this->streams[$streamId])) {
                return;
            }
            // Defer prevents sending increments for already closed streams
            Loop::defer(function () use($streamId, $length) {
                if (!isset($this->streams[$streamId])) {
                    return;
                }
                $this->streams[$streamId]->bufferSize -= $length;
                if ($this->streams[$streamId]->bufferSize === 0) {
                    $this->streams[$streamId]->enableInactivityWatcher();
                }
                $this->increaseStreamWindow($this->streams[$streamId]);
            });
        });
    }
    /**
     *
     */
    public function handleSettings(array $settings) : void
    {
        foreach ($settings as $setting => $value) {
            $this->applySetting($setting, $value);
        }
        $this->writeFrame(Http2Parser::SETTINGS, Http2Parser::ACK);
        if ($this->settings) {
            $deferred = $this->settings;
            $this->settings = null;
            $this->initialized = true;
            $deferred->resolve($this->remainingStreams);
        }
    }
    /**
     *
     */
    public function handleStreamEnd(int $streamId) : void
    {
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        if ($stream->expectedLength !== null && $stream->received !== $stream->expectedLength) {
            $this->handleStreamException(new Http2StreamException("Body length does not match content-length header", $streamId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $body = $stream->body;
        $stream->body = null;
        \assert($body !== null);
        $trailers = $stream->trailers;
        $stream->trailers = null;
        \assert($trailers !== null);
        $body->complete();
        $trailers->resolve(call(function () use($stream, $streamId) {
            try {
                foreach ($stream->request->getEventListeners() as $eventListener) {
                    (yield $eventListener->completeReceivingResponse($stream->request, $stream->stream));
                }
                return new Trailers([]);
            } catch (\Throwable $e) {
                $this->handleStreamException(new Http2StreamException("Event listener error", $streamId, Http2Parser::CANCEL));
                throw $e;
            }
        }));
        $this->setupPingIfIdle();
        // Stream might be cancelled right after body completion
        if (isset($this->streams[$streamId])) {
            $this->releaseStream($streamId);
        }
    }
    /**
     *
     */
    public function reserveStream() : void
    {
        if ($this->shutdown !== null || $this->hasWriteError || $this->hasTimeout) {
            throw new \Error("Can't reserve stream after shutdown started");
        }
        --$this->remainingStreams;
    }
    /**
     *
     */
    public function unreserveStream() : void
    {
        ++$this->remainingStreams;
        \assert($this->remainingStreams <= $this->concurrentStreamLimit);
    }
    /**
     *
     */
    public function getRemainingStreams() : int
    {
        if ($this->shutdown !== null || $this->hasWriteError || $this->hasTimeout) {
            return 0;
        }
        return $this->remainingStreams;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellationToken, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellationToken, $stream) : \Generator {
            if ($this->shutdown !== null) {
                $exception = new UnprocessedRequestException(new SocketException(\sprintf("Connection from '%s' to '%s' has already been shut down", (string) $this->socket->getLocalAddress(), (string) $this->socket->getRemoteAddress())));
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $exception));
                }
                throw $exception;
            }
            if ($this->hasTimeout && !(yield $this->ping())) {
                $exception = new UnprocessedRequestException(new SocketException(\sprintf("Socket to '%s' missed responding to PINGs", (string) $this->socket->getRemoteAddress())));
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $exception));
                }
                throw $exception;
            }
            $this->idlePings = 0;
            $this->cancelIdleWatcher();
            (yield RequestNormalizer::normalizeRequest($request));
            // Remove defunct HTTP/1.x headers.
            $request->removeHeader('host');
            $request->removeHeader('connection');
            $request->removeHeader('keep-alive');
            $request->removeHeader('transfer-encoding');
            $request->removeHeader('upgrade');
            $request->setProtocolVersions(['2']);
            if ($request->getMethod() === 'CONNECT') {
                $exception = new HttpException("CONNECT requests are currently not supported on HTTP/2");
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $exception));
                }
                throw $exception;
            }
            if ($this->socket->isClosed()) {
                $exception = new UnprocessedRequestException(new SocketException(\sprintf("Socket to '%s' closed before the request could be sent", (string) $this->socket->getRemoteAddress())));
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $exception));
                }
                throw $exception;
            }
            $originalCancellation = $cancellationToken;
            if ($request->getTransferTimeout() > 0) {
                $cancellationToken = new CombinedCancellationToken($cancellationToken, new TimeoutCancellationToken($request->getTransferTimeout()));
            }
            try {
                $headers = $this->generateHeaders($request);
                $body = $request->getBody()->createBodyStream();
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->startSendingRequest($request, $stream));
                }
                $chunk = (yield $body->read());
                $streamId = $this->streamId += 2;
                // Client streams should be odd-numbered, starting at 1.
                $this->streams[$streamId] = $http2stream = new Http2Stream($streamId, $request, $stream, $cancellationToken, $originalCancellation, $this->createStreamInactivityWatcher($streamId, $request->getInactivityTimeout()), self::DEFAULT_WINDOW_SIZE, $this->initialWindowSize);
                $this->socket->reference();
                $transferTimeout = $request->getTransferTimeout();
                $cancellationId = $cancellationToken->subscribe(function (CancelledException $exception) use($streamId, $originalCancellation, $transferTimeout) : void {
                    if (!isset($this->streams[$streamId])) {
                        return;
                    }
                    $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $streamId, \pack("N", Http2Parser::CANCEL));
                    if (!$originalCancellation->isRequested()) {
                        $this->hasTimeout = true;
                        $this->ping();
                        // async ping, if other requests occur, they wait for it
                        $exception = new TimeoutException('Allowed transfer timeout exceeded, took longer than ' . $transferTimeout . ' ms', 0, $exception);
                    }
                    $this->releaseStream($streamId, $exception);
                });
                if (!isset($this->streams[$streamId])) {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeSendingRequest($request, $stream));
                    }
                    \assert($http2stream->pendingResponse !== null);
                    return (yield $http2stream->pendingResponse->promise());
                }
                $flag = Http2Parser::END_HEADERS | ($chunk === null ? Http2Parser::END_STREAM : Http2Parser::NO_FLAG);
                $headers = $this->hpack->encode($headers);
                if (\strlen($headers) > $this->frameSizeLimit) {
                    /** @var string[] $split */
                    $split = \str_split($headers, $this->frameSizeLimit);
                    $firstChunk = \array_shift($split);
                    $lastChunk = \array_pop($split);
                    // no yield, because there must not be other frames in between
                    $this->writeFrame(Http2Parser::HEADERS, Http2Parser::NO_FLAG, $streamId, $firstChunk);
                    foreach ($split as $headerChunk) {
                        // no yield, because there must not be other frames in between
                        $this->writeFrame(Http2Parser::CONTINUATION, Http2Parser::NO_FLAG, $streamId, $headerChunk);
                    }
                    (yield $this->writeFrame(Http2Parser::CONTINUATION, $flag, $streamId, $lastChunk));
                } else {
                    (yield $this->writeFrame(Http2Parser::HEADERS, $flag, $streamId, $headers));
                }
                if ($chunk === null) {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeSendingRequest($request, $stream));
                    }
                    $http2stream->requestBodyComplete = true;
                    $http2stream->requestBodyCompletion->resolve();
                    \assert($http2stream->pendingResponse !== null);
                    return (yield $http2stream->pendingResponse->promise());
                }
                $buffer = $chunk;
                while (null !== ($chunk = (yield $body->read()))) {
                    if (!isset($this->streams[$streamId])) {
                        foreach ($request->getEventListeners() as $eventListener) {
                            (yield $eventListener->completeSendingRequest($request, $stream));
                        }
                        \assert($http2stream->pendingResponse !== null);
                        return (yield $http2stream->pendingResponse->promise());
                    }
                    (yield $this->writeData($http2stream, $buffer));
                    $buffer = $chunk;
                }
                if (!isset($this->streams[$streamId])) {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeSendingRequest($request, $stream));
                    }
                    \assert($http2stream->pendingResponse !== null);
                    return (yield $http2stream->pendingResponse->promise());
                }
                \assert($http2stream->pendingResponse !== null);
                $responsePromise = $http2stream->pendingResponse->promise();
                $http2stream->requestBodyComplete = true;
                $http2stream->requestBodyCompletion->resolve();
                (yield $this->writeData($http2stream, $buffer));
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->completeSendingRequest($request, $stream));
                }
                return (yield $responsePromise);
            } catch (\Throwable $exception) {
                if (isset($streamId) && isset($this->streams[$streamId])) {
                    \assert(isset($http2stream));
                    if (!$http2stream->requestBodyComplete) {
                        $http2stream->requestBodyCompletion->fail($exception);
                    }
                    $this->releaseStream($streamId, $exception);
                }
                if ($exception instanceof StreamException) {
                    $message = 'Failed to write request (stream ' . ($streamId ?? 'not assigned') . ') to socket: ' . $exception->getMessage();
                    $exception = new SocketException($message, 0, $exception);
                }
                throw $exception;
            } finally {
                if (isset($cancellationId)) {
                    $cancellationToken->unsubscribe($cancellationId);
                }
            }
        });
    }
    /**
     *
     */
    public function isClosed() : bool
    {
        return $this->onClose === null;
    }
    /**
     *
     */
    private function run() : \Generator
    {
        try {
            (yield $this->socket->write(Http2Parser::PREFACE));
            Promise\rethrow(new Coroutine($this->runWriteThread()));
            (yield $this->writeFrame(Http2Parser::SETTINGS, 0, 0, \pack("nNnNnNnN", Http2Parser::ENABLE_PUSH, 1, Http2Parser::MAX_CONCURRENT_STREAMS, 256, Http2Parser::INITIAL_WINDOW_SIZE, self::DEFAULT_WINDOW_SIZE, Http2Parser::MAX_FRAME_SIZE, self::DEFAULT_MAX_FRAME_SIZE)));
        } catch (\Throwable $e) {
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $this->shutdown(new ClientHttp2ConnectionException('The HTTP/2 connection closed' . ($this->shutdown !== null ? ' unexpectedly' : ''), $this->shutdown ?? Http2Parser::INTERNAL_ERROR));
            $this->close();
            return;
        }
        try {
            $parser = (new Http2Parser($this))->parse();
            while (null !== ($chunk = (yield $this->socket->read()))) {
                $return = $parser->send($chunk);
                \assert($return === null);
            }
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $this->shutdown(new ClientHttp2ConnectionException("The HTTP/2 connection from '" . $this->socket->getLocalAddress() . "' to '" . $this->socket->getRemoteAddress() . "' closed" . ($this->shutdown === null ? ' unexpectedly' : ''), $this->shutdown ?? Http2Parser::INTERNAL_ERROR));
            $this->close();
        } catch (\Throwable $exception) {
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $this->shutdown(new ClientHttp2ConnectionException("The HTTP/2 connection from '" . $this->socket->getLocalAddress() . "' to '" . $this->socket->getRemoteAddress() . "' closed unexpectedly: " . $exception->getMessage(), Http2Parser::INTERNAL_ERROR, $exception));
            $this->close();
        }
    }
    /**
     *
     */
    private function writeFrame(int $type, int $flags = Http2Parser::NO_FLAG, int $stream = 0, string $data = '') : Promise
    {
        \assert(Http2Parser::logDebugFrame('send', $type, $flags, $stream, \strlen($data)));
        return $this->frameQueueEmitter->emit(\Phabel\Target\Php80\Polyfill::substr(\pack("NccN", \strlen($data), $type, $flags, $stream), 1) . $data);
    }
    /**
     *
     */
    private function applySetting(int $setting, int $value) : void
    {
        switch ($setting) {
            case Http2Parser::INITIAL_WINDOW_SIZE:
                if ($value < 0 || $value > 2147483647) {
                    // (1 << 31) - 1
                    $this->handleConnectionException(new Http2ConnectionException("Invalid window size: {$value}", Http2Parser::FLOW_CONTROL_ERROR));
                    return;
                }
                $priorWindowSize = $this->initialWindowSize;
                $this->initialWindowSize = $value;
                $difference = $this->initialWindowSize - $priorWindowSize;
                foreach ($this->streams as $stream) {
                    $stream->clientWindow += $difference;
                }
                // Settings ACK should be sent before HEADER or DATA frames.
                if ($difference > 0) {
                    Loop::defer(function () {
                        foreach ($this->streams as $stream) {
                            if ($this->clientWindow <= 0) {
                                return;
                            }
                            if ($stream->requestBodyBuffer === '' || $stream->clientWindow <= 0) {
                                continue;
                            }
                            $this->writeBufferedData($stream);
                        }
                    });
                }
                return;
            case Http2Parser::MAX_FRAME_SIZE:
                if ($value < 1 << 14 || $value >= 1 << 24) {
                    $this->handleConnectionException(new Http2ConnectionException("Invalid maximum frame size: {$value}", Http2Parser::PROTOCOL_ERROR));
                    return;
                }
                $this->frameSizeLimit = $value;
                return;
            case Http2Parser::MAX_CONCURRENT_STREAMS:
                if ($value < 0 || $value > 2147483647) {
                    // (1 << 31) - 1
                    $this->handleConnectionException(new Http2ConnectionException("Invalid concurrent streams value: {$value}", Http2Parser::PROTOCOL_ERROR));
                    return;
                }
                $priorUsedStreams = $this->concurrentStreamLimit - $this->remainingStreams;
                $this->concurrentStreamLimit = $value;
                $this->remainingStreams = $this->concurrentStreamLimit - $priorUsedStreams;
                \assert($this->remainingStreams <= $this->concurrentStreamLimit);
                return;
            case Http2Parser::HEADER_TABLE_SIZE:
            // TODO Respect this setting from the server
            case Http2Parser::MAX_HEADER_LIST_SIZE:
            // TODO Respect this setting from the server
            case Http2Parser::ENABLE_PUSH:
            // No action needed.
            default:
                // Unknown setting, ignore (6.5.2).
                return;
        }
    }
    /**
     *
     */
    private function writeBufferedData(Http2Stream $stream) : Promise
    {
        if ($stream->requestBodyComplete && $stream->requestBodyBuffer === '') {
            return new Success();
        }
        $windowSize = \min($this->clientWindow, $stream->clientWindow);
        $length = \strlen($stream->requestBodyBuffer);
        if ($length <= $windowSize) {
            if ($stream->windowSizeIncrease) {
                $deferred = $stream->windowSizeIncrease;
                $stream->windowSizeIncrease = null;
                $deferred->resolve();
            }
            $this->clientWindow -= $length;
            $stream->clientWindow -= $length;
            if ($length > $this->frameSizeLimit) {
                /** @var string[] $chunks */
                $chunks = \str_split($stream->requestBodyBuffer, $this->frameSizeLimit);
                $stream->requestBodyBuffer = \array_pop($chunks);
                foreach ($chunks as $chunk) {
                    $this->writeFrame(Http2Parser::DATA, Http2Parser::NO_FLAG, $stream->id, $chunk);
                }
            }
            if ($stream->requestBodyComplete) {
                $promise = $this->writeFrame(Http2Parser::DATA, Http2Parser::END_STREAM, $stream->id, $stream->requestBodyBuffer);
            } else {
                $promise = $this->writeFrame(Http2Parser::DATA, Http2Parser::NO_FLAG, $stream->id, $stream->requestBodyBuffer);
            }
            $stream->requestBodyBuffer = "";
            $stream->enableInactivityWatcher();
            return $promise;
        }
        if ($windowSize > 0) {
            // Read next body chunk if less than 8192 bytes will remain in the buffer
            if ($length - 8192 < $windowSize && $stream->windowSizeIncrease) {
                $deferred = $stream->windowSizeIncrease;
                $stream->windowSizeIncrease = null;
                $deferred->resolve();
            }
            $data = $stream->requestBodyBuffer;
            $end = $windowSize - $this->frameSizeLimit;
            $stream->clientWindow -= $windowSize;
            $this->clientWindow -= $windowSize;
            for ($off = 0; $off < $end; $off += $this->frameSizeLimit) {
                $this->writeFrame(Http2Parser::DATA, Http2Parser::NO_FLAG, $stream->id, \Phabel\Target\Php80\Polyfill::substr($data, $off, $this->frameSizeLimit));
            }
            $promise = $this->writeFrame(Http2Parser::DATA, Http2Parser::NO_FLAG, $stream->id, \Phabel\Target\Php80\Polyfill::substr($data, $off, $windowSize - $off));
            $stream->requestBodyBuffer = \Phabel\Target\Php80\Polyfill::substr($data, $windowSize);
            $stream->enableInactivityWatcher();
            return $promise;
        }
        if ($stream->windowSizeIncrease === null) {
            $stream->windowSizeIncrease = new Deferred();
        }
        return $stream->windowSizeIncrease->promise();
    }
    /**
     *
     */
    private function releaseStream(int $streamId, ?\Throwable $exception = null) : void
    {
        \assert(isset($this->streams[$streamId]));
        $stream = $this->streams[$streamId];
        unset($this->streams[$streamId]);
        if ($streamId & 1) {
            // Client-initiated stream.
            $this->remainingStreams++;
            \assert($this->remainingStreams <= $this->concurrentStreamLimit);
        }
        if ($stream->responsePending || $stream->body || $stream->trailers) {
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $exception = $exception ?? new ClientHttp2StreamException(\sprintf("Stream %d closed unexpectedly", $streamId), $streamId, Http2Parser::INTERNAL_ERROR);
            if (!$exception instanceof HttpException && !$exception instanceof CancelledException) {
                $exception = new HttpException($exception->getMessage(), 0, $exception);
            }
            /** @var (Deferred|Emitter)[] $deferredAndEmitter */
            $deferredAndEmitter = [];
            if ($stream->responsePending) {
                $stream->responsePending = false;
                $deferredAndEmitter[] = $stream->pendingResponse;
                $stream->pendingResponse = null;
            }
            if ($stream->body) {
                $deferredAndEmitter[] = $stream->body;
                $stream->body = null;
            }
            if ($stream->trailers) {
                $deferredAndEmitter[] = $stream->trailers;
                $stream->trailers = null;
            }
            $request = $stream->request;
            asyncCall(static function () use($request, $deferredAndEmitter, $exception) {
                try {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->abort($request, $exception));
                    }
                } finally {
                    foreach ($deferredAndEmitter as $deferredOrEmitter) {
                        \assert($deferredOrEmitter !== null);
                        // TODO Find out why psalm reports this as nullable
                        $deferredOrEmitter->fail($exception);
                    }
                }
            });
        }
        if (!$this->streams && !$this->socket->isClosed()) {
            $this->socket->unreference();
        }
        if (!$this->streams && $this->shutdown !== null) {
            $this->close();
        }
    }
    /**
     *
     */
    private function setupPingIfIdle() : void
    {
        if ($this->idleWatcher !== null) {
            return;
        }
        $this->idleWatcher = Loop::defer(function ($watcher) {
            \assert($this->idleWatcher === null || $this->idleWatcher === $watcher);
            $this->idleWatcher = null;
            if (!empty($this->streams)) {
                return;
            }
            $this->idleWatcher = Loop::delay(300000, function ($watcher) {
                \assert($this->idleWatcher === null || $this->idleWatcher === $watcher);
                \assert(empty($this->streams));
                $this->idleWatcher = null;
                // Connection idle for 10 minutes
                if ($this->idlePings >= 1) {
                    $this->shutdown(new HttpException('Too many pending pings'));
                    $this->close();
                    return;
                }
                if ((yield $this->ping())) {
                    $this->setupPingIfIdle();
                }
            });
            Loop::unreference($this->idleWatcher);
        });
        Loop::unreference($this->idleWatcher);
    }
    /**
     *
     */
    private function cancelIdleWatcher() : void
    {
        if ($this->idleWatcher !== null) {
            Loop::cancel($this->idleWatcher);
            $this->idleWatcher = null;
        }
    }
    /**
     * @return Promise<bool> Fulfilled with true if a pong is received within the timeout, false if none is received.
     */
    private function ping() : Promise
    {
        if ($this->onClose === null) {
            return new Success(false);
        }
        if ($this->pongDeferred !== null) {
            return $this->pongDeferred->promise();
        }
        $this->pongDeferred = new Deferred();
        $this->idlePings++;
        $promise = $this->pongDeferred->promise();
        $this->pongWatcher = Loop::delay(self::PONG_TIMEOUT, function () {
            $this->hasTimeout = false;
            $deferred = $this->pongDeferred;
            $this->pongDeferred = null;
            \assert($deferred !== null);
            $deferred->resolve(false);
            // Shutdown connection to stop new requests, but keep it open, as other responses might still arrive
            $this->shutdown(new HttpException('PONG timeout of ' . self::PONG_TIMEOUT . 'ms reached'), \max(0, $this->streamId));
        });
        $this->writeFrame(Http2Parser::PING, 0, 0, $this->counter++);
        return $promise;
    }
    /**
    * @param HttpException $reason Shutdown reason.
    * @param (int | null) $lastId ID of last processed frame. Null to use the last opened frame ID or 0 if no
    streams have been opened.
    *
    * @return Promise
    */
    private function shutdown(HttpException $reason, ?int $lastId = null) : Promise
    {
        return call(function () use($lastId, $reason) {
            $code = (int) $reason->getCode();
            $this->shutdown = $code;
            if ($this->settings !== null) {
                $settings = $this->settings;
                $this->settings = null;
                $message = "Connection closed before HTTP/2 settings could be received";
                $settings->fail(new UnprocessedRequestException(new SocketException($message, 0, $reason)));
            }
            if ($this->streams) {
                $reason = $lastId !== null ? new UnprocessedRequestException($reason) : $reason;
                foreach ($this->streams as $id => $stream) {
                    if ($lastId !== null && $id <= $lastId) {
                        continue;
                    }
                    $this->releaseStream($id, $reason);
                }
            }
        });
    }
    /**
     * @param Request $request
     *
     * @return array
     * @throws InvalidRequestException
     */
    private function generateHeaders(Request $request) : array
    {
        $uri = $request->getUri();
        $path = normalizeRequestPathWithQuery($request);
        $authority = $uri->getHost();
        if ($port = $uri->getPort()) {
            $authority .= ':' . $port;
        }
        $headers = [[":authority", $authority], [":path", $path], [":scheme", $uri->getScheme()], [":method", $request->getMethod()]];
        foreach ($request->getHeaders() as $field => $values) {
            foreach ($values as $value) {
                if ($field === 'te' && $value !== 'trailers') {
                    continue;
                }
                $headers[] = [$field, $value];
            }
        }
        return $headers;
    }
    /**
     *
     */
    private function writeData(Http2Stream $stream, string $data) : Promise
    {
        $stream->requestBodyBuffer .= $data;
        return $this->writeBufferedData($stream);
    }
    /**
     *
     */
    private function increaseConnectionWindow() : void
    {
        $increase = 0;
        while ($this->serverWindow <= self::MINIMUM_WINDOW) {
            $this->serverWindow += self::WINDOW_INCREMENT;
            $increase += self::WINDOW_INCREMENT;
        }
        if ($increase > 0) {
            $this->writeFrame(Http2Parser::WINDOW_UPDATE, 0, 0, \pack("N", self::WINDOW_INCREMENT));
        }
    }
    /**
     *
     */
    private function increaseStreamWindow(Http2Stream $stream) : void
    {
        $minWindow = \min($stream->request->getBodySizeLimit(), self::MINIMUM_WINDOW);
        $increase = 0;
        while ($stream->serverWindow + $stream->bufferSize <= $minWindow) {
            $stream->serverWindow += self::WINDOW_INCREMENT;
            $increase += self::WINDOW_INCREMENT;
        }
        if ($increase > 0) {
            $this->writeFrame(Http2Parser::WINDOW_UPDATE, Http2Parser::NO_FLAG, $stream->id, \pack("N", self::WINDOW_INCREMENT));
        }
    }
    /**
     *
     */
    private function createStreamInactivityWatcher(int $streamId, int $timeout) : ?string
    {
        if ($timeout <= 0) {
            return null;
        }
        $watcher = Loop::delay($timeout, function () use($streamId, $timeout) : void {
            if (!isset($this->streams[$streamId])) {
                return;
            }
            $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $streamId, \pack("N", Http2Parser::CANCEL));
            $this->releaseStream($streamId, new TimeoutException("Inactivity timeout exceeded, more than {$timeout} ms elapsed from last data received"));
        });
        Loop::unreference($watcher);
        return $watcher;
    }
    /**
     *
     */
    private function runWriteThread() : \Generator
    {
        try {
            while ((yield $this->frameQueue->advance())) {
                (yield $this->socket->write($this->frameQueue->getCurrent()));
            }
        } catch (\Throwable $exception) {
            $this->hasWriteError = true;
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $this->shutdown(new ClientHttp2ConnectionException("The HTTP/2 connection closed unexpectedly: " . $exception->getMessage(), Http2Parser::INTERNAL_ERROR, $exception), \max(0, $this->streamId));
        }
    }
}<?php

namespace Amp\Http\Client\Connection\Internal;

use Amp\Http\Client\Request;
use Amp\Http\Client\RequestBody;
use Amp\Promise;
use function Amp\call;
/** @internal */
final class RequestNormalizer
{
    /**
     *
     */
    public static function normalizeRequest(Request $request) : Promise
    {
        return call(static function () use($request) {
            /** @var array $headers */
            $headers = (yield $request->getBody()->getHeaders());
            foreach ($headers as $name => $header) {
                if (!$request->hasHeader($name)) {
                    $request->setHeaders([$name => $header]);
                }
            }
            yield from self::normalizeRequestBodyHeaders($request);
            // Always normalize this as last item, because we need to strip sensitive headers
            self::normalizeTraceRequest($request);
            return $request;
        });
    }
    /**
     *
     */
    private static function normalizeRequestBodyHeaders(Request $request) : \Generator
    {
        if (!$request->hasHeader('host')) {
            // Though servers are supposed to be able to handle standard port names on the end of the
            // Host header some fail to do this correctly. Thankfully PSR-7 recommends to strip the port
            // if it is the standard port for the given scheme.
            $request->setHeader('host', $request->getUri()->withUserInfo('')->getAuthority());
        }
        if ($request->hasHeader("transfer-encoding")) {
            $request->removeHeader("content-length");
            return;
        }
        if ($request->hasHeader("content-length")) {
            return;
        }
        /** @var RequestBody $body */
        $body = $request->getBody();
        $bodyLength = (yield $body->getBodyLength());
        if ($bodyLength === 0) {
            if (\in_array($request->getMethod(), ['HEAD', 'GET', 'CONNECT'], true)) {
                $request->removeHeader('content-length');
            } else {
                $request->setHeader('content-length', '0');
            }
            $request->removeHeader('transfer-encoding');
        } elseif ($bodyLength > 0) {
            $request->setHeader("content-length", $bodyLength);
            $request->removeHeader("transfer-encoding");
        } else {
            $request->setHeader("transfer-encoding", "chunked");
        }
    }
    /**
     *
     */
    private static function normalizeTraceRequest(Request $request) : void
    {
        $method = $request->getMethod();
        if ($method !== 'TRACE') {
            return;
        }
        // https://tools.ietf.org/html/rfc7231#section-4.3.8
        $request->setBody(null);
        // Remove all body and sensitive headers
        $request->setHeaders(["transfer-encoding" => [], "content-length" => [], "authorization" => [], "proxy-authorization" => [], "cookie" => []]);
    }
}<?php

namespace Amp\Http\Client\Connection\Internal;

use Amp\ByteStream\InMemoryStream;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\ParseException;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\InvalidHeaderException;
use Amp\Http\Rfc7230;
use Amp\Http\Status;
/** @internal */
final class Http1Parser
{
    use ForbidSerialization;
    use ForbidCloning;
    private const STATUS_LINE_PATTERN = "#^\n        HTTP/(?P<protocol>\\d+\\.\\d+)[ \t]+\n        (?P<status>[1-9]\\d\\d)[ \t]*\n        (?P<reason>[^\x01-\x08\x10-\x19]*)\n    \$#ix";
    public const AWAITING_HEADERS = 0;
    public const BODY_IDENTITY = 1;
    public const BODY_IDENTITY_EOF = 2;
    public const BODY_CHUNKS = 3;
    public const TRAILERS_START = 4;
    public const TRAILERS = 5;
    /** @var int */
    private $state = self::AWAITING_HEADERS;
    /** @var string */
    private $buffer = '';
    /** @var string|null */
    private $protocol;
    /** @var int|null */
    private $statusCode;
    /** @var string|null */
    private $statusReason;
    /** @var string[][] */
    private $headers = [];
    /** @var int|null */
    private $remainingBodyBytes;
    /** @var int */
    private $bodyBytesConsumed = 0;
    /** @var bool */
    private $chunkedEncoding = false;
    /** @var int|null */
    private $chunkLengthRemaining;
    /** @var bool */
    private $complete = false;
    /** @var Request */
    private $request;
    /** @var int */
    private $maxHeaderBytes;
    /** @var int */
    private $maxBodyBytes;
    /** @var callable */
    private $bodyDataCallback;
    /** @var callable */
    private $trailersCallback;
    /**
     *
     */
    public function __construct(Request $request, callable $bodyDataCallback, callable $trailersCallback)
    {
        $this->request = $request;
        $this->bodyDataCallback = $bodyDataCallback;
        $this->trailersCallback = $trailersCallback;
        $this->maxHeaderBytes = $request->getHeaderSizeLimit();
        $this->maxBodyBytes = $request->getBodySizeLimit();
    }
    /**
     *
     */
    public function getBuffer() : string
    {
        return $this->buffer;
    }
    /**
     *
     */
    public function getState() : int
    {
        return $this->state;
    }
    /**
     *
     */
    public function buffer(string $data) : void
    {
        $this->buffer .= $data;
    }
    /**
     * @param (string | null) $data
     *
     * @return (Response | null)
     *
     * @throws ParseException
     */
    public function parse(string $data = null) : ?Response
    {
        if ($data !== null) {
            $this->buffer .= $data;
        }
        if ($this->buffer === '') {
            return null;
        }
        if ($this->complete) {
            throw new ParseException('Can\'t continue parsing, response is already complete', Status::BAD_REQUEST);
        }
        switch ($this->state) {
            case self::AWAITING_HEADERS:
                goto headers;
            case self::BODY_IDENTITY:
                goto body_identity;
            case self::BODY_IDENTITY_EOF:
                goto body_identity_eof;
            case self::BODY_CHUNKS:
                goto body_chunks;
            case self::TRAILERS_START:
                goto trailers_start;
            case self::TRAILERS:
                goto trailers;
        }
        headers:
        $startLineAndHeaders = $this->shiftHeadersFromBuffer();
        if ($startLineAndHeaders === null) {
            return null;
        }
        $startLineEndPos = \strpos($startLineAndHeaders, "\r\n");
        \assert($startLineEndPos !== false);
        $startLine = \Phabel\Target\Php80\Polyfill::substr($startLineAndHeaders, 0, $startLineEndPos);
        $rawHeaders = \Phabel\Target\Php80\Polyfill::substr($startLineAndHeaders, $startLineEndPos + 2);
        if (\preg_match(self::STATUS_LINE_PATTERN, $startLine, $match)) {
            $this->protocol = $match['protocol'];
            $this->statusCode = (int) $match['status'];
            $this->statusReason = \trim($match['reason']);
        } else {
            throw new ParseException('Invalid status line: ' . $startLine, Status::BAD_REQUEST);
        }
        if ($rawHeaders !== '') {
            $this->headers = $this->parseRawHeaders($rawHeaders);
        } else {
            $this->headers = [];
        }
        $requestMethod = $this->request->getMethod();
        $skipBody = $this->statusCode < Status::OK || $this->statusCode === Status::NOT_MODIFIED || $this->statusCode === Status::NO_CONTENT || $requestMethod === 'HEAD' || $requestMethod === 'CONNECT';
        if ($skipBody) {
            $this->complete = true;
        } elseif ($this->chunkedEncoding) {
            $this->state = self::BODY_CHUNKS;
        } elseif ($this->remainingBodyBytes === null) {
            $this->state = self::BODY_IDENTITY_EOF;
        } elseif ($this->remainingBodyBytes > 0) {
            $this->state = self::BODY_IDENTITY;
        } else {
            $this->complete = true;
        }
        $response = new Response($this->protocol, $this->statusCode, $this->statusReason, [], new InMemoryStream(), $this->request);
        foreach ($this->headers as [$key, $value]) {
            $response->addHeader($key, $value);
        }
        return $response;
        body_identity:
        $bufferDataSize = \strlen($this->buffer);
        if ($bufferDataSize <= $this->remainingBodyBytes) {
            $chunk = $this->buffer;
            $this->buffer = '';
            $this->remainingBodyBytes -= $bufferDataSize;
            $this->addToBody($chunk);
            if ($this->remainingBodyBytes === 0) {
                $this->complete = true;
            }
            return null;
        }
        $bodyData = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $this->remainingBodyBytes);
        $this->addToBody($bodyData);
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->remainingBodyBytes);
        $this->remainingBodyBytes = 0;
        goto complete;
        body_identity_eof:
        $this->addToBody($this->buffer);
        $this->buffer = '';
        return null;
        body_chunks:
        if ($this->parseChunkedBody()) {
            $this->state = self::TRAILERS_START;
            goto trailers_start;
        }
        return null;
        trailers_start:
        $firstTwoBytes = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, 2);
        if ($firstTwoBytes === "" || $firstTwoBytes === "\r") {
            return null;
        }
        if ($firstTwoBytes === "\r\n") {
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 2);
            goto complete;
        }
        $this->state = self::TRAILERS;
        goto trailers;
        trailers:
        $trailers = $this->shiftHeadersFromBuffer();
        if ($trailers === null) {
            return null;
        }
        $this->parseTrailers($trailers);
        goto complete;
        complete:
        $this->complete = true;
        return null;
    }
    /**
     *
     */
    public function isComplete() : bool
    {
        return $this->complete;
    }
    /**
     * @return (string | null)
     *
     * @throws ParseException
     */
    private function shiftHeadersFromBuffer() : ?string
    {
        $this->buffer = \ltrim($this->buffer, "\r\n");
        if ($headersSize = \strpos($this->buffer, "\r\n\r\n")) {
            $headers = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $headersSize + 2);
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $headersSize + 4);
        } else {
            $headersSize = \strlen($this->buffer);
            $headers = null;
        }
        if ($this->maxHeaderBytes > 0 && $headersSize > $this->maxHeaderBytes) {
            throw new ParseException("Configured header size exceeded: {$headersSize} bytes received, while the configured limit is {$this->maxHeaderBytes} bytes", Status::REQUEST_HEADER_FIELDS_TOO_LARGE);
        }
        return $headers;
    }
    /**
     * @param string $rawHeaders
     *
     * @return array
     *
     * @throws ParseException
     */
    private function parseRawHeaders(string $rawHeaders) : array
    {
        // Legacy support for folded headers
        if (\strpos($rawHeaders, "\r\n ") || \strpos($rawHeaders, "\r\n\t")) {
            $rawHeaders = \preg_replace("/\r\n[ \t]++/", ' ', $rawHeaders);
        }
        try {
            $headers = Rfc7230::parseRawHeaders($rawHeaders);
            $headerMap = [];
            foreach ($headers as [$key, $value]) {
                $headerMap[\strtolower($key)][] = $value;
            }
        } catch (InvalidHeaderException $e) {
            throw new ParseException('Invalid headers', Status::BAD_REQUEST, $e);
        }
        if (isset($headerMap['transfer-encoding'])) {
            $transferEncodings = \explode(',', \strtolower(\implode(',', $headerMap['transfer-encoding'])));
            $transferEncodings = \array_map('trim', $transferEncodings);
            $this->chunkedEncoding = \in_array('chunked', $transferEncodings, true);
        } elseif (isset($headerMap['content-length'])) {
            if (\count($headerMap['content-length']) > 1) {
                throw new ParseException('Can\'t determine body length, because multiple content-length headers present in the response', Status::BAD_REQUEST);
            }
            $contentLength = $headerMap['content-length'][0];
            if (!\preg_match('/^(0|[1-9][0-9]*)$/', $contentLength)) {
                throw new ParseException('Can\'t determine body length, because the content-length header value is invalid', Status::BAD_REQUEST);
            }
            $this->remainingBodyBytes = (int) $contentLength;
        }
        return $headers;
    }
    /**
     * Decodes a chunked response body.
     *
     * @return bool {@code true} if the body is complete, otherwise {@code false}.
     *
     * @throws ParseException
     */
    private function parseChunkedBody() : bool
    {
        if ($this->chunkLengthRemaining !== null) {
            goto decode_chunk;
        }
        determine_chunk_size:
        if (false === ($lineEndPos = \strpos($this->buffer, "\r\n"))) {
            return false;
        }
        if ($lineEndPos === 0) {
            throw new ParseException('Invalid line; hexadecimal chunk size expected', Status::BAD_REQUEST);
        }
        $line = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $lineEndPos);
        $hex = \strtolower(\trim(\ltrim($line, '0'))) ?: '0';
        $dec = \hexdec($hex);
        if ($hex !== \dechex($dec)) {
            throw new ParseException('Invalid hexadecimal chunk size', Status::BAD_REQUEST);
        }
        $this->chunkLengthRemaining = $dec;
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $lineEndPos + 2);
        if ($this->chunkLengthRemaining === 0) {
            return true;
        }
        decode_chunk:
        $bufferLength = \strlen($this->buffer);
        // These first two (extreme) edge cases prevent errors where the packet boundary ends after
        // the \r and before the \n at the end of a chunk.
        if ($bufferLength === $this->chunkLengthRemaining || $bufferLength === $this->chunkLengthRemaining + 1) {
            return false;
        }
        if ($bufferLength >= $this->chunkLengthRemaining + 2) {
            $chunk = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $this->chunkLengthRemaining);
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->chunkLengthRemaining + 2);
            $this->chunkLengthRemaining = null;
            $this->addToBody($chunk);
            goto determine_chunk_size;
        }
        /** @noinspection SuspiciousAssignmentsInspection */
        $chunk = $this->buffer;
        $this->buffer = '';
        $this->chunkLengthRemaining -= $bufferLength;
        $this->addToBody($chunk);
        return false;
    }
    /**
     * @param string $trailers
     *
     * @throws ParseException
     */
    private function parseTrailers(string $trailers) : void
    {
        try {
            $trailers = Rfc7230::parseHeaders($trailers);
        } catch (InvalidHeaderException $e) {
            throw new ParseException('Invalid trailers', Status::BAD_REQUEST, $e);
        }
        ($this->trailersCallback)($trailers);
    }
    /**
     * @param string $data
     *
     * @throws ParseException
     */
    private function addToBody(string $data) : void
    {
        $length = \strlen($data);
        if (!$length) {
            return;
        }
        $this->bodyBytesConsumed += $length;
        if ($this->maxBodyBytes > 0 && $this->bodyBytesConsumed > $this->maxBodyBytes) {
            throw new ParseException("Configured body size exceeded: {$this->bodyBytesConsumed} bytes received, while the configured limit is {$this->maxBodyBytes} bytes", Status::PAYLOAD_TOO_LARGE);
        }
        if ($this->bodyDataCallback) {
            ($this->bodyDataCallback)($data);
        }
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Request;
use Amp\Promise;
interface ConnectionPool
{
    /**
     * Reserve a stream for a particular request.
     *
     * @param Request $request
     * @param CancellationToken $cancellation
     *
     * @return Promise<Stream>
     */
    public function getStream(Request $request, CancellationToken $cancellation) : Promise;
}<?php

namespace Amp\Http\Client\Connection;

use Amp\Http\Client\HttpException;
final class UnprocessedRequestException extends HttpException
{
    /**
     *
     */
    public function __construct(HttpException $previous)
    {
        parent::__construct("The request was not processed and can be safely retried", 0, $previous);
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use function Amp\call;
final class HttpStream implements Stream
{
    use ForbidSerialization;
    use ForbidCloning;
    /**
     *
     */
    public static function fromConnection(Connection $connection, callable $requestCallback, callable $releaseCallback) : self
    {
        return new self($connection->getLocalAddress(), $connection->getRemoteAddress(), $connection->getTlsInfo(), $requestCallback, $releaseCallback);
    }
    /**
     *
     */
    public static function fromStream(Stream $stream, callable $requestCallback, callable $releaseCallback) : self
    {
        return new self($stream->getLocalAddress(), $stream->getRemoteAddress(), $stream->getTlsInfo(), $requestCallback, $releaseCallback);
    }
    /** @var SocketAddress */
    private $localAddress;
    /** @var SocketAddress */
    private $remoteAddress;
    /** @var TlsInfo|null */
    private $tlsInfo;
    /** @var callable */
    private $requestCallback;
    /** @var callable|null */
    private $releaseCallback;
    /**
     *
     */
    private function __construct(SocketAddress $localAddress, SocketAddress $remoteAddress, ?TlsInfo $tlsInfo, callable $requestCallback, callable $releaseCallback)
    {
        $this->localAddress = $localAddress;
        $this->remoteAddress = $remoteAddress;
        $this->tlsInfo = $tlsInfo;
        $this->requestCallback = $requestCallback;
        $this->releaseCallback = $releaseCallback;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->releaseCallback !== null) {
            ($this->releaseCallback)();
        }
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise
    {
        if ($this->releaseCallback === null) {
            throw new \Error('A stream may only be used for a single request');
        }
        $this->releaseCallback = null;
        return call(function () use($request, $cancellation) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startRequest($request));
            }
            return call($this->requestCallback, $request, $cancellation, $this);
        });
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->localAddress;
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->remoteAddress;
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->tlsInfo;
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
interface Connection
{
    /**
    * @param Request $request
    *
    * @return Promise<(Stream | null)> Returns a stream for the given request, or null if no stream is available or if
    the connection is not suited for the given request. The first request for a stream
    on a new connection MUST resolve the promise with a Stream instance.
    */
    public function getStream(Request $request) : Promise;
    /**
     * @return string[] Array of supported protocol versions.
     */
    public function getProtocolVersions() : array;
    /**
     *
     */
    public function close() : Promise;
    /**
     *
     */
    public function onClose(callable $onClose) : void;
    /**
     *
     */
    public function getLocalAddress() : SocketAddress;
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress;
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo;
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Coroutine;
use Amp\Deferred;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\MultiReasonException;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
use function Amp\coroutine;
final class ConnectionLimitingPool implements ConnectionPool
{
    use ForbidSerialization;
    /**
     * Create a connection pool that limits the number of connections per authority.
     *
     * @param int $connectionLimit Maximum number of connections allowed to a single authority.
     * @param (ConnectionFactory | null) $connectionFactory
     *
     * @return self
     */
    public static function byAuthority(int $connectionLimit, ?ConnectionFactory $connectionFactory = null) : self
    {
        return new self($connectionLimit, $connectionFactory);
    }
    /**
     *
     */
    private static function formatUri(Request $request) : string
    {
        $uri = $request->getUri();
        $scheme = $uri->getScheme();
        $isHttps = $scheme === 'https';
        $defaultPort = $isHttps ? 443 : 80;
        $host = $uri->getHost();
        $port = $uri->getPort() ?? $defaultPort;
        $authority = $host . ':' . $port;
        return $scheme . '://' . $authority;
    }
    /** @var int */
    private $connectionLimit;
    /** @var ConnectionFactory */
    private $connectionFactory;
    /** @var array<string, \ArrayObject<int, Promise<Connection>>> */
    private $connections = [];
    /** @var Connection[] */
    private $idleConnections = [];
    /** @var int[] */
    private $activeRequestCounts = [];
    /** @var Deferred[][] */
    private $waiting = [];
    /** @var bool[] */
    private $waitForPriorConnection = [];
    /** @var int */
    private $totalConnectionAttempts = 0;
    /** @var int */
    private $totalStreamRequests = 0;
    /** @var int */
    private $openConnectionCount = 0;
    /**
     *
     */
    private function __construct(int $connectionLimit, ?ConnectionFactory $connectionFactory = null)
    {
        if ($connectionLimit < 1) {
            throw new \Error('The connection limit must be greater than 0');
        }
        $this->connectionLimit = $connectionLimit;
        $this->connectionFactory = $connectionFactory ?? new DefaultConnectionFactory();
    }
    /**
     *
     */
    public function __clone()
    {
        $this->connections = [];
        $this->totalConnectionAttempts = 0;
        $this->totalStreamRequests = 0;
        $this->openConnectionCount = 0;
    }
    /**
     *
     */
    public function getTotalConnectionAttempts() : int
    {
        return $this->totalConnectionAttempts;
    }
    /**
     *
     */
    public function getTotalStreamRequests() : int
    {
        return $this->totalStreamRequests;
    }
    /**
     *
     */
    public function getOpenConnectionCount() : int
    {
        return $this->openConnectionCount;
    }
    /**
     *
     */
    public function getStream(Request $request, CancellationToken $cancellation) : Promise
    {
        return call(function () use($request, $cancellation) {
            $this->totalStreamRequests++;
            $uri = self::formatUri($request);
            // Using new Coroutine avoids a bug on PHP < 7.4, see #265
            /**
             * @var Stream $stream
             * @psalm-suppress all
             */
            [$connection, $stream] = (yield new Coroutine($this->getStreamFor($uri, $request, $cancellation)));
            $connectionId = \spl_object_id($connection);
            $this->activeRequestCounts[$connectionId] = ($this->activeRequestCounts[$connectionId] ?? 0) + 1;
            unset($this->idleConnections[$connectionId]);
            return HttpStream::fromStream($stream, coroutine(function (Request $request, CancellationToken $cancellationToken) use($connection, $stream, $uri) {
                try {
                    /** @var Response $response */
                    $response = (yield $stream->request($request, $cancellationToken));
                } catch (\Throwable $e) {
                    $this->onReadyConnection($connection, $uri);
                    throw $e;
                }
                // await response being completely received
                $response->getTrailers()->onResolve(function () use($connection, $uri) : void {
                    $this->onReadyConnection($connection, $uri);
                });
                return $response;
            }), function () use($connection, $uri) : void {
                $this->onReadyConnection($connection, $uri);
            });
        });
    }
    /**
     *
     */
    private function getStreamFor(string $uri, Request $request, CancellationToken $cancellation) : \Generator
    {
        $isHttps = $request->getUri()->getScheme() === 'https';
        $connections = $this->connections[$uri] ?? new \ArrayObject();
        do {
            foreach ($connections as $connectionPromise) {
                \assert($connectionPromise instanceof Promise);
                try {
                    if ($isHttps && ($this->waitForPriorConnection[$uri] ?? true)) {
                        // Wait for first successful connection if using a secure connection (maybe we can use HTTP/2).
                        $connection = (yield $connectionPromise);
                    } else {
                        $connection = (yield Promise\first([$connectionPromise, new Success()]));
                        if ($connection === null) {
                            continue;
                        }
                    }
                } catch (\Exception $exception) {
                    continue;
                    // Ignore cancellations and errors of other requests.
                }
                \assert($connection instanceof Connection);
                $stream = (yield $this->getStreamFromConnection($connection, $request));
                if ($stream === null) {
                    if (!$this->isAdditionalConnectionAllowed($uri) && $this->isConnectionIdle($connection)) {
                        $connection->close();
                        break;
                    }
                    continue;
                    // No stream available for the given request.
                }
                return [$connection, $stream];
            }
            $deferred = new Deferred();
            $deferredId = \spl_object_id($deferred);
            $this->waiting[$uri][$deferredId] = $deferred;
            $deferredPromise = $deferred->promise();
            $deferredPromise->onResolve(function () use($uri, $deferredId) : void {
                $this->removeWaiting($uri, $deferredId);
            });
            if ($this->isAdditionalConnectionAllowed($uri)) {
                break;
            }
            $connection = (yield $deferredPromise);
            \assert($connection instanceof Connection);
            $stream = (yield $this->getStreamFromConnection($connection, $request));
            if ($stream === null) {
                continue;
                // Wait for a different connection to become available.
            }
            return [$connection, $stream];
        } while (true);
        $this->totalConnectionAttempts++;
        $connectionPromise = $this->connectionFactory->create($request, $cancellation);
        $promiseId = \spl_object_id($connectionPromise);
        $this->connections[$uri] = $this->connections[$uri] ?? new \ArrayObject();
        $this->connections[$uri][$promiseId] = $connectionPromise;
        $connectionPromise->onResolve(function (?\Throwable $exception, ?Connection $connection) use(&$deferred, $uri, $promiseId, $isHttps) : void {
            if ($exception) {
                $this->dropConnection($uri, null, $promiseId);
                if ($deferred !== null) {
                    $deferred->fail($exception);
                    // Fail Deferred so Promise\first() below fails.
                }
                return;
            }
            \assert($connection !== null);
            $connectionId = \spl_object_id($connection);
            $this->openConnectionCount++;
            if ($isHttps) {
                $this->waitForPriorConnection[$uri] = \in_array('2', $connection->getProtocolVersions(), true);
            }
            $connection->onClose(function () use($uri, $connectionId, $promiseId) : void {
                $this->openConnectionCount--;
                $this->dropConnection($uri, $connectionId, $promiseId);
            });
        });
        try {
            $connection = (yield Promise\first([$connectionPromise, $deferredPromise]));
        } catch (MultiReasonException $exception) {
            [$exception] = $exception->getReasons();
            // The first reason is why the connection failed.
            throw $exception;
        }
        $deferred = null;
        // Null reference so connection promise handler does not double-resolve the Deferred.
        $this->removeWaiting($uri, $deferredId);
        // Deferred no longer needed for this request.
        \assert($connection instanceof Connection);
        $stream = (yield $this->getStreamFromConnection($connection, $request));
        if ($stream === null) {
            // Reused connection did not have an available stream for the given request.
            $connection = (yield $connectionPromise);
            // Wait for new connection request instead.
            $stream = (yield $this->getStreamFromConnection($connection, $request));
            if ($stream === null) {
                // Other requests used the new connection first, so we need to go around again.
                // Using new Coroutine avoids a bug on PHP < 7.4, see #265
                return (yield new Coroutine($this->getStreamFor($uri, $request, $cancellation)));
            }
        }
        return [$connection, $stream];
    }
    /**
     *
     */
    private function getStreamFromConnection(Connection $connection, Request $request) : Promise
    {
        if (!\array_intersect($request->getProtocolVersions(), $connection->getProtocolVersions())) {
            return new Success();
            // Connection does not support any of the requested protocol versions.
        }
        return $connection->getStream($request);
    }
    /**
     *
     */
    private function isAdditionalConnectionAllowed(string $uri) : bool
    {
        return \count($this->connections[$uri] ?? []) < $this->connectionLimit;
    }
    /**
     *
     */
    private function onReadyConnection(Connection $connection, string $uri) : void
    {
        $connectionId = \spl_object_id($connection);
        if (isset($this->activeRequestCounts[$connectionId])) {
            $this->activeRequestCounts[$connectionId]--;
            if ($this->activeRequestCounts[$connectionId] === 0) {
                while (\count($this->idleConnections) > 64) {
                    // not customizable for now
                    $idleConnection = \reset($this->idleConnections);
                    $key = \key($this->idleConnections);
                    unset($this->idleConnections[$key]);
                    $idleConnection->close();
                }
                $this->idleConnections[$connectionId] = $connection;
            }
        }
        if (empty($this->waiting[$uri])) {
            return;
        }
        $deferred = \reset($this->waiting[$uri]);
        // Deferred is removed from waiting list in onResolve callback attached above.
        $deferred->resolve($connection);
    }
    /**
     *
     */
    private function isConnectionIdle(Connection $connection) : bool
    {
        $connectionId = \spl_object_id($connection);
        \assert(!isset($this->activeRequestCounts[$connectionId]) || $this->activeRequestCounts[$connectionId] >= 0);
        return ($this->activeRequestCounts[$connectionId] ?? 0) === 0;
    }
    /**
     *
     */
    private function removeWaiting(string $uri, int $deferredId) : void
    {
        unset($this->waiting[$uri][$deferredId]);
        if (empty($this->waiting[$uri])) {
            unset($this->waiting[$uri]);
        }
    }
    /**
     *
     */
    private function dropConnection(string $uri, ?int $connectionId, int $promiseId) : void
    {
        unset($this->connections[$uri][$promiseId]);
        if ($connectionId !== null) {
            unset($this->activeRequestCounts[$connectionId], $this->idleConnections[$connectionId]);
        }
        if ($this->connections[$uri]->count() === 0) {
            unset($this->connections[$uri], $this->waitForPriorConnection[$uri]);
        }
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Promise;
final class UnlimitedConnectionPool implements ConnectionPool
{
    use ForbidSerialization;
    /** @var ConnectionLimitingPool */
    private $pool;
    /**
     *
     */
    public function __construct(?ConnectionFactory $connectionFactory = null)
    {
        $this->pool = ConnectionLimitingPool::byAuthority(\PHP_INT_MAX, $connectionFactory);
    }
    /**
     *
     */
    public function __clone()
    {
        $this->pool = clone $this->pool;
    }
    /**
     *
     */
    public function getTotalConnectionAttempts() : int
    {
        return $this->pool->getTotalConnectionAttempts();
    }
    /**
     *
     */
    public function getTotalStreamRequests() : int
    {
        return $this->pool->getTotalStreamRequests();
    }
    /**
     *
     */
    public function getOpenConnectionCount() : int
    {
        return $this->pool->getOpenConnectionCount();
    }
    /**
     *
     */
    public function getStream(Request $request, CancellationToken $cancellation) : Promise
    {
        return $this->pool->getStream($request, $cancellation);
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Success;
final class UpgradedSocket implements EncryptableSocket
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var EncryptableSocket */
    private $socket;
    /** @var string|null */
    private $buffer;
    /**
     * @param EncryptableSocket $socket
     * @param string $buffer Remaining buffer previously read from the socket.
     */
    public function __construct(EncryptableSocket $socket, string $buffer)
    {
        $this->socket = $socket;
        $this->buffer = $buffer !== '' ? $buffer : null;
    }
    /**
     *
     */
    public function read() : Promise
    {
        if ($this->buffer !== null) {
            $buffer = $this->buffer;
            $this->buffer = null;
            return new Success($buffer);
        }
        return $this->socket->read();
    }
    /**
     *
     */
    public function close() : void
    {
        $this->socket->close();
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        return $this->socket->write($data);
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        return $this->socket->end($finalData);
    }
    /**
     *
     */
    public function reference() : void
    {
        $this->socket->reference();
    }
    /**
     *
     */
    public function unreference() : void
    {
        $this->socket->unreference();
    }
    /**
     *
     */
    public function isClosed() : bool
    {
        return $this->socket->isClosed();
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->socket->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->socket->getRemoteAddress();
    }
    /**
     *
     */
    public function setupTls(?CancellationToken $cancellationToken = null) : Promise
    {
        return $this->socket->setupTls($cancellationToken);
    }
    /**
     *
     */
    public function shutdownTls(?CancellationToken $cancellationToken = null) : Promise
    {
        return $this->socket->shutdownTls();
    }
    /**
     *
     */
    public function getTlsState() : int
    {
        return $this->socket->getTlsState();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->socket->getTlsInfo();
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use Amp\Sync\KeyedSemaphore;
use Amp\Sync\Lock;
use function Amp\call;
use function Amp\coroutine;
final class StreamLimitingPool implements ConnectionPool
{
    use ForbidCloning;
    use ForbidSerialization;
    /**
     *
     */
    public static function byHost(ConnectionPool $delegate, KeyedSemaphore $semaphore) : self
    {
        return new self($delegate, $semaphore, static function (Request $request) {
            return $request->getUri()->getHost();
        });
    }
    /**
     *
     */
    public static function byStaticKey(ConnectionPool $delegate, KeyedSemaphore $semaphore, string $key = '') : self
    {
        return new self($delegate, $semaphore, static function () use($key) {
            return $key;
        });
    }
    /**
     *
     */
    public static function byCustomKey(ConnectionPool $delegate, KeyedSemaphore $semaphore, callable $requestToKeyMapper) : self
    {
        return new self($delegate, $semaphore, $requestToKeyMapper);
    }
    /** @var ConnectionPool */
    private $delegate;
    /** @var KeyedSemaphore */
    private $semaphore;
    /** @var callable */
    private $requestToKeyMapper;
    /**
     *
     */
    private function __construct(ConnectionPool $delegate, KeyedSemaphore $semaphore, callable $requestToKeyMapper)
    {
        $this->delegate = $delegate;
        $this->semaphore = $semaphore;
        $this->requestToKeyMapper = $requestToKeyMapper;
    }
    /**
     *
     */
    public function getStream(Request $request, CancellationToken $cancellation) : Promise
    {
        return call(function () use($request, $cancellation) {
            /** @var Lock $lock */
            $lock = (yield $this->semaphore->acquire(($this->requestToKeyMapper)($request)));
            /** @var Stream $stream */
            $stream = (yield $this->delegate->getStream($request, $cancellation));
            return HttpStream::fromStream($stream, coroutine(static function (Request $request, CancellationToken $cancellationToken) use($stream, $lock) {
                try {
                    /** @var Response $response */
                    $response = (yield $stream->request($request, $cancellationToken));
                    // await response being completely received
                    $response->getTrailers()->onResolve(static function () use($lock) {
                        $lock->release();
                    });
                } catch (\Throwable $e) {
                    $lock->release();
                    throw $e;
                }
                return $response;
            }), static function () use($lock) {
                $lock->release();
            });
        });
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\CombinedCancellationToken;
use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\Request;
use Amp\Http\Client\SocketException;
use Amp\Http\Client\TimeoutException;
use Amp\Promise;
use Amp\Socket;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectContext;
use Amp\Socket\Connector;
use Amp\Socket\EncryptableSocket;
use Amp\TimeoutCancellationToken;
use function Amp\call;
use function Amp\Socket\connector;
final class DefaultConnectionFactory implements ConnectionFactory
{
    /** @var Connector|null */
    private $connector;
    /** @var ConnectContext|null */
    private $connectContext;
    /**
     *
     */
    public function __construct(?Connector $connector = null, ?ConnectContext $connectContext = null)
    {
        $this->connector = $connector;
        $this->connectContext = $connectContext;
    }
    /**
     *
     */
    public function create(Request $request, CancellationToken $cancellationToken) : Promise
    {
        return call(function () use($request, $cancellationToken) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startConnectionCreation($request));
            }
            $connector = $this->connector ?? connector();
            $connectContext = $this->connectContext ?? new ConnectContext();
            $uri = $request->getUri();
            $scheme = $uri->getScheme();
            if (!\in_array($scheme, ['http', 'https'], true)) {
                throw new InvalidRequestException($request, 'Invalid scheme provided in the request URI: ' . $uri);
            }
            $isHttps = $scheme === 'https';
            $defaultPort = $isHttps ? 443 : 80;
            $host = $uri->getHost();
            $port = $uri->getPort() ?? $defaultPort;
            if ($host === '') {
                throw new InvalidRequestException($request, 'A host must be provided in the request URI: ' . $uri);
            }
            $authority = $host . ':' . $port;
            $protocolVersions = $request->getProtocolVersions();
            $isConnect = $request->getMethod() === 'CONNECT';
            if ($isHttps) {
                $protocols = [];
                if (!$isConnect && \in_array('2', $protocolVersions, true)) {
                    $protocols[] = 'h2';
                }
                if (\in_array('1.1', $protocolVersions, true) || \in_array('1.0', $protocolVersions, true)) {
                    $protocols[] = 'http/1.1';
                }
                if (!$protocols) {
                    throw new InvalidRequestException($request, \sprintf("None of the requested protocol versions (%s) are supported by %s (HTTP/2 is only supported on HTTPS)", \implode(', ', $protocolVersions), self::class));
                }
                $tlsContext = ($connectContext->getTlsContext() ?? new ClientTlsContext(''))->withPeerCapturing();
                // If we only have HTTP/1.1 available, don't set application layer protocols.
                // There are misbehaving sites like n11.com, see https://github.com/amphp/http-client/issues/255
                if ($protocols !== ['http/1.1'] && Socket\hasTlsAlpnSupport()) {
                    $tlsContext = $tlsContext->withApplicationLayerProtocols($protocols);
                }
                if ($tlsContext->getPeerName() === '') {
                    $tlsContext = $tlsContext->withPeerName($host);
                }
                $connectContext = $connectContext->withTlsContext($tlsContext);
            }
            try {
                /** @var EncryptableSocket $socket */
                $socket = (yield $connector->connect('tcp://' . $authority, $connectContext->withConnectTimeout($request->getTcpConnectTimeout()), $cancellationToken));
            } catch (Socket\ConnectException $e) {
                throw new UnprocessedRequestException(new SocketException(\sprintf("Connection to '%s' failed", $authority), 0, $e));
            } catch (CancelledException $e) {
                // In case of a user cancellation request, throw the expected exception
                $cancellationToken->throwIfRequested();
                // Otherwise we ran into a timeout of our TimeoutCancellationToken
                throw new UnprocessedRequestException(new TimeoutException(\sprintf("Connection to '%s' timed out, took longer than " . $request->getTcpConnectTimeout() . ' ms', $authority)));
                // don't pass $e
            }
            if ($isHttps) {
                try {
                    $tlsState = $socket->getTlsState();
                    // Error if anything enabled TLS on a new connection before we can do it
                    if ($tlsState !== EncryptableSocket::TLS_STATE_DISABLED) {
                        $socket->close();
                        throw new UnprocessedRequestException(new SocketException('Failed to setup TLS connection, connection was in an unexpected TLS state (' . $tlsState . ')'));
                    }
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->startTlsNegotiation($request));
                    }
                    $tlsCancellationToken = new CombinedCancellationToken($cancellationToken, new TimeoutCancellationToken($request->getTlsHandshakeTimeout()));
                    (yield $socket->setupTls($tlsCancellationToken));
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeTlsNegotiation($request));
                    }
                } catch (StreamException $exception) {
                    $socket->close();
                    throw new UnprocessedRequestException(new SocketException(\sprintf("Connection to '%s' @ '%s' closed during TLS handshake", $authority, $socket->getRemoteAddress()->toString()), 0, $exception));
                } catch (CancelledException $e) {
                    $socket->close();
                    // In case of a user cancellation request, throw the expected exception
                    $cancellationToken->throwIfRequested();
                    // Otherwise we ran into a timeout of our TimeoutCancellationToken
                    throw new UnprocessedRequestException(new TimeoutException(\sprintf("TLS handshake with '%s' @ '%s' timed out, took longer than " . $request->getTlsHandshakeTimeout() . ' ms', $authority, $socket->getRemoteAddress()->toString())));
                    // don't pass $e
                }
                $tlsInfo = $socket->getTlsInfo();
                if ($tlsInfo === null) {
                    throw new UnprocessedRequestException(new SocketException(\sprintf("Socket closed after TLS handshake with '%s' @ '%s'", $authority, $socket->getRemoteAddress()->toString())));
                }
                if ($tlsInfo->getApplicationLayerProtocol() === 'h2') {
                    $http2Connection = new Http2Connection($socket);
                    (yield $http2Connection->initialize());
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeConnectionCreation($request));
                    }
                    return $http2Connection;
                }
            }
            // Treat the presence of only HTTP/2 as prior knowledge, see https://http2.github.io/http2-spec/#known-http
            if ($request->getProtocolVersions() === ['2']) {
                $http2Connection = new Http2Connection($socket);
                (yield $http2Connection->initialize());
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->completeConnectionCreation($request));
                }
                return $http2Connection;
            }
            if (!\array_intersect($request->getProtocolVersions(), ['1.0', '1.1'])) {
                $socket->close();
                throw new InvalidRequestException($request, \sprintf("None of the requested protocol versions (%s) are supported by '%s' @ '%s'", \implode(', ', $protocolVersions), $authority, $socket->getRemoteAddress()->toString()));
            }
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->completeConnectionCreation($request));
            }
            return new Http1Connection($socket);
        });
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use function Amp\call;
final class InterceptedStream implements Stream
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var Stream */
    private $stream;
    /** @var NetworkInterceptor|null */
    private $interceptor;
    /**
     *
     */
    public function __construct(Stream $stream, NetworkInterceptor $interceptor)
    {
        $this->stream = $stream;
        $this->interceptor = $interceptor;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise
    {
        if (!$this->interceptor) {
            throw new \Error(__METHOD__ . ' may only be invoked once per instance. If you need to implement retries or otherwise issue multiple requests, register an ApplicationInterceptor to do so.');
        }
        $interceptor = $this->interceptor;
        $this->interceptor = null;
        return call(function () use($interceptor, $request, $cancellation) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startRequest($request));
            }
            return $interceptor->requestViaNetwork($request, $cancellation, $this->stream);
        });
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->stream->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->stream->getRemoteAddress();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->stream->getTlsInfo();
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\ByteStream\IteratorStream;
use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\CancellationTokenSource;
use Amp\CancelledException;
use Amp\CombinedCancellationToken;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Http;
use Amp\Http\Client\Connection\Internal\Http1Parser;
use Amp\Http\Client\Connection\Internal\RequestNormalizer;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Internal\ResponseBodyStream;
use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\ParseException;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Client\SocketException;
use Amp\Http\Client\TimeoutException;
use Amp\Http\InvalidHeaderException;
use Amp\Http\Rfc7230;
use Amp\Loop;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Success;
use Amp\TimeoutCancellationToken;
use Amp\TimeoutException as PromiseTimeoutException;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\getCurrentTime;
use function Amp\Http\Client\Internal\normalizeRequestPathWithQuery;
/**
 * Socket client implementation.
 *
 * @see Client
 */
final class Http1Connection implements Connection
{
    use ForbidSerialization;
    use ForbidCloning;
    private const MAX_KEEP_ALIVE_TIMEOUT = 60;
    private const PROTOCOL_VERSIONS = ['1.0', '1.1'];
    /** @var EncryptableSocket|null */
    private $socket;
    /** @var bool */
    private $busy = false;
    /** @var int Number of requests made on this connection. */
    private $requestCounter = 0;
    /** @var string|null Keep alive timeout watcher ID. */
    private $timeoutWatcher;
    /** @var int Keep-Alive timeout from last response. */
    private $priorTimeout = self::MAX_KEEP_ALIVE_TIMEOUT;
    /** @var callable[]|null */
    private $onClose = [];
    /** @var int */
    private $timeoutGracePeriod;
    /** @var int */
    private $lastUsedAt;
    /** @var bool */
    private $explicitTimeout = false;
    /** @var SocketAddress */
    private $localAddress;
    /** @var SocketAddress */
    private $remoteAddress;
    /** @var TlsInfo|null */
    private $tlsInfo;
    /** @var Promise|null */
    private $idleRead;
    /**
     *
     */
    public function __construct(EncryptableSocket $socket, int $timeoutGracePeriod = 2000)
    {
        $this->socket = $socket;
        $this->localAddress = $socket->getLocalAddress();
        $this->remoteAddress = $socket->getRemoteAddress();
        $this->tlsInfo = $socket->getTlsInfo();
        $this->timeoutGracePeriod = $timeoutGracePeriod;
        $this->lastUsedAt = getCurrentTime();
        $this->watchIdleConnection();
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     *
     */
    public function onClose(callable $onClose) : void
    {
        if (!$this->socket || $this->socket->isClosed()) {
            Promise\rethrow(call($onClose, $this));
            return;
        }
        $this->onClose[] = $onClose;
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->socket) {
            $this->socket->close();
        }
        return $this->free();
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->localAddress;
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->remoteAddress;
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->tlsInfo;
    }
    /**
     *
     */
    public function getProtocolVersions() : array
    {
        return self::PROTOCOL_VERSIONS;
    }
    /**
     *
     */
    public function getStream(Request $request) : Promise
    {
        if ($this->busy || $this->requestCounter && !$this->hasStreamFor($request)) {
            return new Success();
        }
        $this->busy = true;
        return new Success(HttpStream::fromConnection($this, \Closure::fromCallable([$this, 'request']), \Closure::fromCallable([$this, 'release'])));
    }
    /**
     *
     */
    private function free() : Promise
    {
        $this->socket = null;
        $this->idleRead = null;
        $this->lastUsedAt = 0;
        if ($this->timeoutWatcher !== null) {
            Loop::cancel($this->timeoutWatcher);
        }
        if ($this->onClose !== null) {
            $onClose = $this->onClose;
            $this->onClose = null;
            foreach ($onClose as $callback) {
                asyncCall($callback, $this);
            }
        }
        return new Success();
    }
    /**
     *
     */
    private function hasStreamFor(Request $request) : bool
    {
        return !$this->busy && $this->socket && !$this->socket->isClosed() && ($this->getRemainingTime() > 0 || $request->isIdempotent());
    }
    /**
     * @inheritdoc
     */
    private function request(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellation, $stream) {
            ++$this->requestCounter;
            if ($this->socket !== null && !$this->socket->isClosed()) {
                $this->socket->reference();
            }
            if ($this->timeoutWatcher !== null) {
                Loop::cancel($this->timeoutWatcher);
                $this->timeoutWatcher = null;
            }
            (yield RequestNormalizer::normalizeRequest($request));
            $protocolVersion = $this->determineProtocolVersion($request);
            $request->setProtocolVersions([$protocolVersion]);
            if ($request->getTransferTimeout() > 0) {
                $timeoutToken = new TimeoutCancellationToken($request->getTransferTimeout());
                $combinedCancellation = new CombinedCancellationToken($cancellation, $timeoutToken);
            } else {
                $combinedCancellation = $cancellation;
            }
            $id = $combinedCancellation->subscribe([$this, 'close']);
            try {
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->startSendingRequest($request, $stream));
                }
                yield from $this->writeRequest($request, $protocolVersion, $combinedCancellation);
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->completeSendingRequest($request, $stream));
                }
                return yield from $this->readResponse($request, $cancellation, $combinedCancellation, $stream);
            } catch (\Throwable $e) {
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $e));
                }
                if ($this->socket !== null) {
                    $this->socket->close();
                }
                throw $e;
            } finally {
                $combinedCancellation->unsubscribe($id);
                $cancellation->throwIfRequested();
            }
        });
    }
    /**
     *
     */
    private function release() : void
    {
        $this->busy = false;
    }
    /**
     * @param Request $request
     * @param CancellationToken $originalCancellation
     * @param CancellationToken $readingCancellation
     *
     * @param Stream $stream
     *
     * @return \Generator
     * @throws CancelledException
     * @throws HttpException
     * @throws ParseException
     * @throws SocketException
     */
    private function readResponse(Request $request, CancellationToken $originalCancellation, CancellationToken $readingCancellation, Stream $stream) : \Generator
    {
        $bodyEmitter = new Emitter();
        $backpressure = new Success();
        $bodyCallback = static function ($data) use($bodyEmitter, &$backpressure) : void {
            $backpressure = $bodyEmitter->emit($data);
        };
        $trailersDeferred = new Deferred();
        $trailers = [];
        $trailersCallback = static function (array $headers) use(&$trailers) : void {
            $trailers = $headers;
        };
        $parser = new Http1Parser($request, $bodyCallback, $trailersCallback);
        $start = getCurrentTime();
        $timeout = $request->getInactivityTimeout();
        try {
            if ($this->socket === null) {
                throw new SocketException('Socket closed prior to response completion');
            }
            while (null !== ($chunk = (yield $timeout > 0 ? Promise\timeout($this->idleRead ?: $this->socket->read(), $timeout) : ($this->idleRead ?: $this->socket->read())))) {
                $this->idleRead = null;
                parseChunk:
                $response = $parser->parse($chunk);
                if ($response === null) {
                    if ($this->socket === null) {
                        throw new SocketException('Socket closed prior to response completion');
                    }
                    continue;
                }
                $this->lastUsedAt = getCurrentTime();
                $status = $response->getStatus();
                if ($status === Http\Status::SWITCHING_PROTOCOLS) {
                    $connection = Http\createFieldValueComponentMap(Http\parseFieldValueComponents($response, 'connection'));
                    if (!isset($connection['upgrade'])) {
                        throw new HttpException('Switching protocols response missing "Connection: upgrade" header');
                    }
                    if (!$response->hasHeader('upgrade')) {
                        throw new HttpException('Switching protocols response missing "Upgrade" header');
                    }
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeReceivingResponse($request, $stream));
                    }
                    $trailersDeferred->resolve($trailers);
                    return $this->handleUpgradeResponse($request, $response, $parser->getBuffer());
                }
                if ($status < 200) {
                    // 1XX responses (excluding 101, handled above)
                    $onInformationalResponse = $request->getInformationalResponseHandler();
                    if ($onInformationalResponse !== null) {
                        (yield call($onInformationalResponse, $response));
                    }
                    $chunk = $parser->getBuffer();
                    $parser = new Http1Parser($request, $bodyCallback, $trailersCallback);
                    goto parseChunk;
                }
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->startReceivingResponse($request, $stream));
                }
                if ($status >= 200 && $status < 300 && $request->getMethod() === 'CONNECT') {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeReceivingResponse($request, $stream));
                    }
                    $trailersDeferred->resolve($trailers);
                    return $this->handleUpgradeResponse($request, $response, $parser->getBuffer());
                }
                $bodyCancellationSource = new CancellationTokenSource();
                $bodyCancellationToken = new CombinedCancellationToken($readingCancellation, $bodyCancellationSource->getToken());
                $response->setTrailers($trailersDeferred->promise());
                $response->setBody(new ResponseBodyStream(new IteratorStream($bodyEmitter->iterate()), $bodyCancellationSource));
                // Read body async
                asyncCall(function () use($parser, $request, $response, $bodyEmitter, $trailersDeferred, $originalCancellation, $readingCancellation, $bodyCancellationToken, $stream, $timeout, &$backpressure, &$trailers) {
                    $id = $bodyCancellationToken->subscribe([$this, 'close']);
                    try {
                        // Required, otherwise responses without body hang
                        if (!$parser->isComplete()) {
                            // Directly parse again in case we already have the full body but aborted parsing
                            // to resolve promise with headers.
                            $chunk = null;
                            try {
                                /** @psalm-suppress PossiblyNullReference */
                                do {
                                    /** @noinspection CallableParameterUseCaseInTypeContextInspection */
                                    $parser->parse($chunk);
                                    /**
                                     * @noinspection NotOptimalIfConditionsInspection
                                     * @psalm-suppress TypeDoesNotContainType
                                     */
                                    if ($parser->isComplete()) {
                                        break;
                                    }
                                    if (!$backpressure instanceof Success) {
                                        (yield $this->withCancellation($backpressure, $bodyCancellationToken));
                                    }
                                    /** @psalm-suppress TypeDoesNotContainNull */
                                    if ($this->socket === null) {
                                        throw new SocketException('Socket closed prior to response completion');
                                    }
                                } while (null !== ($chunk = (yield $timeout > 0 ? Promise\timeout($this->socket->read(), $timeout) : $this->socket->read())));
                            } catch (PromiseTimeoutException $e) {
                                $this->close();
                                throw new TimeoutException('Inactivity timeout exceeded, more than ' . $timeout . ' ms elapsed from last data received', 0, $e);
                            }
                            $originalCancellation->throwIfRequested();
                            if ($readingCancellation->isRequested()) {
                                throw new TimeoutException('Allowed transfer timeout exceeded, took longer than ' . $request->getTransferTimeout() . ' ms');
                            }
                            $bodyCancellationToken->throwIfRequested();
                            // Ignore check if neither content-length nor chunked encoding are given.
                            if (!$parser->isComplete() && $parser->getState() !== Http1Parser::BODY_IDENTITY_EOF) {
                                throw new SocketException('Socket disconnected prior to response completion');
                            }
                        }
                        $timeout = $this->determineKeepAliveTimeout($response);
                        if ($timeout > 0 && $parser->getState() !== Http1Parser::BODY_IDENTITY_EOF) {
                            $this->timeoutWatcher = Loop::delay($timeout * 1000, [$this, 'close']);
                            Loop::unreference($this->timeoutWatcher);
                            $this->watchIdleConnection();
                        } else {
                            $this->close();
                        }
                        $this->busy = false;
                        foreach ($request->getEventListeners() as $eventListener) {
                            (yield $eventListener->completeReceivingResponse($request, $stream));
                        }
                        $bodyEmitter->complete();
                        $trailersDeferred->resolve($trailers);
                    } catch (\Throwable $e) {
                        $this->close();
                        try {
                            foreach ($request->getEventListeners() as $eventListener) {
                                (yield $eventListener->abort($request, $e));
                            }
                        } finally {
                            $bodyEmitter->fail($e);
                            $trailersDeferred->fail($e);
                        }
                    } finally {
                        $bodyCancellationToken->unsubscribe($id);
                    }
                });
                return $response;
            }
            $originalCancellation->throwIfRequested();
            throw new SocketException(\sprintf("Receiving the response headers for '%s' failed, because the socket to '%s' @ '%s' closed early with %d bytes received within %d milliseconds", (string) $request->getUri()->withUserInfo(''), $request->getUri()->withUserInfo('')->getAuthority(), $this->socket === null ? '???' : (string) $this->socket->getRemoteAddress(), \strlen($parser->getBuffer()), getCurrentTime() - $start));
        } catch (HttpException $e) {
            $this->close();
            throw $e;
        } catch (PromiseTimeoutException $e) {
            $this->close();
            throw new TimeoutException('Inactivity timeout exceeded, more than ' . $timeout . ' ms elapsed from last data received', 0, $e);
        } catch (\Throwable $e) {
            $this->close();
            throw new SocketException('Receiving the response headers failed: ' . $e->getMessage(), 0, $e);
        }
    }
    /**
     *
     */
    private function handleUpgradeResponse(Request $request, Response $response, string $buffer) : Response
    {
        if ($this->socket === null) {
            throw new SocketException('Socket closed while upgrading');
        }
        $socket = new UpgradedSocket($this->socket, $buffer);
        $this->free();
        // Mark this connection as unusable without closing socket.
        if (($onUpgrade = $request->getUpgradeHandler()) === null) {
            $socket->close();
            throw new HttpException('CONNECT or upgrade request made without upgrade handler callback');
        }
        asyncCall(static function () use($onUpgrade, $socket, $request, $response) : \Generator {
            try {
                (yield call($onUpgrade, $socket, $request, $response));
            } catch (\Throwable $exception) {
                $socket->close();
                throw new HttpException('Upgrade handler threw an exception', 0, $exception);
            }
        });
        return $response;
    }
    /**
     * @return int Approximate number of milliseconds remaining until the connection is closed.
     */
    private function getRemainingTime() : int
    {
        $timestamp = $this->lastUsedAt + ($this->explicitTimeout ? $this->priorTimeout * 1000 : $this->timeoutGracePeriod);
        return \max(0, $timestamp - getCurrentTime());
    }
    /**
     *
     */
    private function withCancellation(Promise $promise, CancellationToken $cancellationToken) : Promise
    {
        $deferred = new Deferred();
        $newPromise = $deferred->promise();
        $promise->onResolve(static function ($error, $value) use(&$deferred) : void {
            if ($deferred) {
                $temp = $deferred;
                $deferred = null;
                if ($error) {
                    $temp->fail($error);
                } else {
                    $temp->resolve($value);
                }
            }
        });
        $cancellationSubscription = $cancellationToken->subscribe(static function ($e) use(&$deferred) : void {
            if ($deferred) {
                $temp = $deferred;
                $deferred = null;
                $temp->fail($e);
            }
        });
        $newPromise->onResolve(static function () use($cancellationToken, $cancellationSubscription) : void {
            $cancellationToken->unsubscribe($cancellationSubscription);
        });
        return $newPromise;
    }
    /**
     *
     */
    private function determineKeepAliveTimeout(Response $response) : int
    {
        $request = $response->getRequest();
        $requestConnHeader = $request->getHeader('connection') ?? '';
        $responseConnHeader = $response->getHeader('connection') ?? '';
        if (!\strcasecmp($requestConnHeader, 'close')) {
            return 0;
        }
        if ($response->getProtocolVersion() === '1.0') {
            return 0;
        }
        if (!\strcasecmp($responseConnHeader, 'close')) {
            return 0;
        }
        $params = Http\createFieldValueComponentMap(Http\parseFieldValueComponents($response, 'keep-alive'));
        $timeout = (int) ($params['timeout'] ?? $this->priorTimeout);
        if (isset($params['timeout'])) {
            $this->explicitTimeout = true;
        }
        return $this->priorTimeout = \min(\max(0, $timeout), self::MAX_KEEP_ALIVE_TIMEOUT);
    }
    /**
     *
     */
    private function determineProtocolVersion(Request $request) : string
    {
        $protocolVersions = $request->getProtocolVersions();
        if (\in_array("1.1", $protocolVersions, true)) {
            return "1.1";
        }
        if (\in_array("1.0", $protocolVersions, true)) {
            return "1.0";
        }
        throw new InvalidRequestException($request, "None of the requested protocol versions is supported: " . \implode(", ", $protocolVersions));
    }
    /**
     *
     */
    private function writeRequest(Request $request, string $protocolVersion, CancellationToken $cancellation) : \Generator
    {
        try {
            $rawHeaders = $this->generateRawHeader($request, $protocolVersion);
            if ($this->socket === null) {
                throw new UnprocessedRequestException(new SocketException('Socket closed before request started'));
            }
            (yield $this->socket->write($rawHeaders));
            if ($request->getMethod() === 'CONNECT') {
                return;
            }
            $body = $request->getBody()->createBodyStream();
            $chunking = $request->getHeader("transfer-encoding") === "chunked";
            $remainingBytes = $request->getHeader("content-length");
            if ($remainingBytes !== null) {
                $remainingBytes = (int) $remainingBytes;
            }
            if ($chunking && $protocolVersion === "1.0") {
                throw new InvalidRequestException($request, "Can't send chunked bodies over HTTP/1.0");
            }
            // We always buffer the last chunk to make sure we don't write $contentLength bytes if the body is too long.
            $buffer = "";
            while (null !== ($chunk = (yield $body->read()))) {
                $cancellation->throwIfRequested();
                if ($chunk === "") {
                    continue;
                }
                if ($chunking) {
                    $chunk = \dechex(\strlen($chunk)) . "\r\n" . $chunk . "\r\n";
                } elseif ($remainingBytes !== null) {
                    $remainingBytes -= \strlen($chunk);
                    if ($remainingBytes < 0) {
                        throw new InvalidRequestException($request, "Body contained more bytes than specified in Content-Length, aborting request");
                    }
                }
                (yield $this->socket->write($buffer));
                $buffer = $chunk;
            }
            $cancellation->throwIfRequested();
            // Flush last buffered chunk.
            (yield $this->socket->write($buffer));
            if ($chunking) {
                (yield $this->socket->write("0\r\n\r\n"));
            } elseif ($remainingBytes !== null && $remainingBytes > 0) {
                throw new InvalidRequestException($request, "Body contained fewer bytes than specified in Content-Length, aborting request");
            }
        } catch (StreamException $exception) {
            throw new SocketException('Socket disconnected prior to response completion');
        }
    }
    /**
     * @param Request $request
     * @param string $protocolVersion
     *
     * @return string
     *
     * @throws HttpException
     */
    private function generateRawHeader(Request $request, string $protocolVersion) : string
    {
        $uri = $request->getUri();
        $requestUri = normalizeRequestPathWithQuery($request);
        $method = $request->getMethod();
        if ($method === 'CONNECT') {
            $defaultPort = $uri->getScheme() === 'https' ? 443 : 80;
            $requestUri = $uri->getHost() . ':' . ($uri->getPort() ?? $defaultPort);
        }
        $header = $method . ' ' . $requestUri . ' HTTP/' . $protocolVersion . "\r\n";
        try {
            $header .= Rfc7230::formatRawHeaders($request->getRawHeaders());
        } catch (InvalidHeaderException $e) {
            throw new HttpException($e->getMessage());
        }
        return $header . "\r\n";
    }
    /**
     *
     */
    private function watchIdleConnection() : void
    {
        if ($this->socket === null || $this->socket->isClosed()) {
            return;
        }
        $this->socket->unreference();
        $this->idleRead = $this->socket->read();
        $this->idleRead->onResolve(function ($error, $chunk) {
            if ($error || $chunk === null) {
                $this->close();
            }
        });
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Connection\Internal\Http2ConnectionProcessor;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use function Amp\call;
final class Http2Connection implements Connection
{
    use ForbidSerialization;
    use ForbidCloning;
    private const PROTOCOL_VERSIONS = ['2'];
    /** @var EncryptableSocket */
    private $socket;
    /** @var Http2ConnectionProcessor */
    private $processor;
    /** @var int */
    private $requestCount = 0;
    /**
     *
     */
    public function __construct(EncryptableSocket $socket)
    {
        $this->socket = $socket;
        $this->processor = new Http2ConnectionProcessor($socket);
    }
    /**
     *
     */
    public function getProtocolVersions() : array
    {
        return self::PROTOCOL_VERSIONS;
    }
    /**
     *
     */
    public function initialize() : Promise
    {
        return $this->processor->initialize();
    }
    /**
     *
     */
    public function getStream(Request $request) : Promise
    {
        if (!$this->processor->isInitialized()) {
            throw new \Error('The promise returned from ' . __CLASS__ . '::initialize() must resolve before using the connection');
        }
        return call(function () {
            if ($this->processor->isClosed() || $this->processor->getRemainingStreams() <= 0) {
                return null;
            }
            $this->processor->reserveStream();
            return HttpStream::fromConnection($this, \Closure::fromCallable([$this, 'request']), \Closure::fromCallable([$this->processor, 'unreserveStream']));
        });
    }
    /**
     *
     */
    public function onClose(callable $onClose) : void
    {
        $this->processor->onClose($onClose);
    }
    /**
     *
     */
    public function close() : Promise
    {
        return $this->processor->close();
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->socket->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->socket->getRemoteAddress();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->socket->getTlsInfo();
    }
    /**
     *
     */
    private function request(Request $request, CancellationToken $token, Stream $applicationStream) : Promise
    {
        $this->requestCount++;
        return $this->processor->request($request, $token, $applicationStream);
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\Http\Client\HttpException;
/**
 * @deprecated Exception moved to amphp/http. Catch the base exception class (HttpException) instead.
 */
final class Http2StreamException extends HttpException
{
    /** @var int */
    private $streamId;
    /**
     *
     */
    public function __construct(string $message, int $streamId, int $code, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->streamId = $streamId;
    }
    /**
     *
     */
    public function getStreamId() : int
    {
        return $this->streamId;
    }
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Connection\Stream;
use Amp\Promise;
/**
 * Allows intercepting an HTTP request after the connection to the remote server has been established.
 */
interface NetworkInterceptor
{
    /**
    * Intercepts an HTTP request after the connection to the remote server has been established.
    *
    * The implementation might modify the request and/or modify the response after the promise returned from
    `$stream->request(...)` resolved.
    *
    * A NetworkInterceptor SHOULD NOT short-circuit and SHOULD delegate to the `$stream` passed as third argument
    exactly once. The only exception to this is throwing an exception, e.g. because the TLS settings used are
    unacceptable. If you need short circuits, use an {@see ApplicationInterceptor} instead.
    *
    * @param Request $request
    * @param CancellationToken $cancellation
    * @param Stream $stream
    *
    * @return Promise<Response>
    */
    public function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise;
}<?php

namespace Amp\Http\Client;

use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\InvalidHeaderException;
use Amp\Http\Message;
final class Trailers extends Message
{
    use ForbidSerialization;
    /** @see https://tools.ietf.org/html/rfc7230#section-4.1.2 */
    public const DISALLOWED_TRAILERS = ["authorization" => true, "content-encoding" => true, "content-length" => true, "content-range" => true, "content-type" => true, "cookie" => true, "expect" => true, "host" => true, "pragma" => true, "proxy-authenticate" => true, "proxy-authorization" => true, "range" => true, "te" => true, "trailer" => true, "transfer-encoding" => true, "www-authenticate" => true];
    /**
     * @param (string[] | string[][]) $headers
     *
     * @throws InvalidHeaderException Thrown if a disallowed field is in the header values.
     */
    public function __construct(array $headers)
    {
        if (!empty($headers)) {
            $this->setHeaders($headers);
        }
        if (\array_intersect_key($this->getHeaders(), self::DISALLOWED_TRAILERS)) {
            throw new InvalidHeaderException('Disallowed field in trailers');
        }
    }
}<?php

namespace Amp\Http\Client;

final class InvalidRequestException extends HttpException
{
    /** @var Request */
    private $request;
    /**
     *
     */
    public function __construct(Request $request, string $message, int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->request = $request;
    }
    /**
     *
     */
    public function getRequest() : Request
    {
        return $this->request;
    }
}<?php

namespace Amp\Http\Client;

class HttpException extends \Exception
{
}{
    "name": "amphp/http-client",
    "homepage": "https://github.com/amphp/http-client",
    "description": "Asynchronous concurrent HTTP/2 and HTTP/1.1 client built on the Amp concurrency framework",
    "keywords": [
        "http",
        "rest",
        "client",
        "concurrent",
        "async",
        "non-blocking"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@gmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.2",
        "amphp/amp": "^2.4",
        "amphp/byte-stream": "^1.6",
        "amphp/hpack": "^3",
        "amphp/http": "^1.6",
        "amphp/socket": "^1",
        "amphp/sync": "^1.3",
        "league/uri": "^6",
        "psr/http-message": "^1"
    },
    "require-dev": {
        "ext-json": "*",
        "amphp/file": "^0.2 || ^0.3 || ^1 || ^2",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^7 || ^8 || ^9",
        "amphp/http-server": "^2",
        "kelunik/link-header-rfc5988": "^1.0",
        "clue/socks-react": "^1.0",
        "amphp/react-adapter": "^2.1",
        "vimeo/psalm": "^4",
        "laminas/laminas-diactoros": "^2.3"
    },
    "suggest": {
        "ext-zlib": "Allows using compression for response bodies.",
        "ext-json": "Required for logging HTTP archives",
        "amphp/file": "Required for file request bodies and HTTP archive logging"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Http\\Client\\": "src"
        },
        "files": [
            "src/Internal/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Http\\Client\\": "test"
        }
    },
    "conflict": {
        "amphp/file": "<0.2 || >=3"
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "4.x-dev"
        }
    }
}
<?php

namespace Amp\Mysql;

use Amp\Socket\ConnectContext;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
final class ConnectionConfig extends SqlConnectionConfig
{
    public const DEFAULT_PORT = 3306;
    public const BIN_CHARSET = 45;
    // utf8mb4_general_ci
    public const KEY_MAP = ['hostname' => 'host', 'username' => 'user', 'pass' => 'password', 'database' => 'db', 'dbname' => 'db', 'compress' => 'compression', 'useCompression' => 'compression', 'cs' => 'charset', 'localInfile' => 'local-infile'];
    public const DEFAULT_CHARSET = "utf8mb4";
    public const DEFAULT_COLLATE = "utf8mb4_general_ci";
    /** @var bool */
    private $useCompression = false;
    /** @var bool */
    private $useLocalInfile = false;
    /** @var ConnectContext */
    private $context;
    /** @var string */
    private $charset = "utf8mb4";
    /** @var string  */
    private $collate = "utf8mb4_general_ci";
    /* @var string private key to use for sha256_password auth method */
    private $key;
    /**
     *
     */
    public static function fromString(string $connectionString, ConnectContext $context = null) : self
    {
        $parts = self::parseConnectionString($connectionString, self::KEY_MAP);
        if (!isset($parts['host'])) {
            throw new \Error('Host must be provided in connection string');
        }
        return new self($parts['host'], (int) ($parts['port'] ?? self::DEFAULT_PORT), $parts['user'] ?? null, $parts['password'] ?? null, $parts['db'] ?? null, $context, $parts['charset'] ?? self::DEFAULT_CHARSET, $parts['collate'] ?? self::DEFAULT_COLLATE, ($parts['compression'] ?? '') === 'on', ($parts['local-infile'] ?? '') === 'on');
    }
    /**
     *
     */
    public function __construct(string $host, int $port = self::DEFAULT_PORT, string $user = null, string $password = null, string $database = null, ConnectContext $context = null, string $charset = self::DEFAULT_CHARSET, string $collate = self::DEFAULT_COLLATE, bool $useCompression = false, string $key = '', bool $useLocalInfile = false)
    {
        parent::__construct($host, $port, $user, $password, $database);
        $this->context = $context ?? new ConnectContext();
        $this->charset = $charset;
        $this->collate = $collate;
        $this->useCompression = $useCompression;
        $this->key = $key;
        $this->useLocalInfile = $useLocalInfile;
    }
    /**
     *
     */
    public function getConnectionString() : string
    {
        return $this->getHost()[0] == "/" ? 'unix://' . $this->getHost() : 'tcp://' . $this->getHost() . ':' . $this->getPort();
    }
    /**
     *
     */
    public function isCompressionEnabled() : bool
    {
        return $this->useCompression;
    }
    /**
     *
     */
    public function withCompression() : self
    {
        $new = clone $this;
        $new->useCompression = true;
        return $new;
    }
    /**
     *
     */
    public function withoutCompression() : self
    {
        $new = clone $this;
        $new->useCompression = false;
        return $new;
    }
    /**
     *
     */
    public function isLocalInfileEnabled() : bool
    {
        return $this->useLocalInfile;
    }
    /**
     *
     */
    public function withLocalInfile() : self
    {
        $new = clone $this;
        $new->useLocalInfile = true;
        return $new;
    }
    /**
     *
     */
    public function withoutLocalInfile() : self
    {
        $new = clone $this;
        $new->useLocalInfile = false;
        return $new;
    }
    /**
     *
     */
    public function getConnectContext()
    {
        return $this->context;
    }
    /**
     *
     */
    public function withConnectContext(ConnectContext $context) : self
    {
        $new = clone $this;
        $new->context = $context;
        return $new;
    }
    /**
     *
     */
    public function getCharset() : string
    {
        return $this->charset;
    }
    /**
     *
     */
    public function getCollation() : string
    {
        return $this->collate;
    }
    /**
     *
     */
    public function withCharset(string $charset = self::DEFAULT_CHARSET, string $collate = self::DEFAULT_COLLATE) : self
    {
        $new = clone $this;
        $new->charset = $charset;
        $new->collate = $collate;
        return $new;
    }
    /**
     *
     */
    public function getKey() : string
    {
        return $this->key;
    }
    /**
     *
     */
    public function withKey(string $key) : self
    {
        $new = clone $this;
        $new->key = $key;
        return $new;
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Transaction as SqlTransaction;
use Amp\Sql\TransactionError;
use function Amp\call;
final class ConnectionTransaction implements SqlTransaction
{
    const SAVEPOINT_PREFIX = "amp_";
    /** @var Internal\Processor|null */
    private $processor;
    /** @var int */
    private $isolation;
    /** @var callable */
    private $release;
    /** @var int */
    private $refCount = 1;
    /**
     * @param Internal\Processor $processor
     * @param callable $release
     * @param int $isolation
     *
     * @throws \Error If the isolation level is invalid.
     */
    public function __construct(Internal\Processor $processor, callable $release, int $isolation = SqlTransaction::ISOLATION_COMMITTED)
    {
        switch ($isolation) {
            case SqlTransaction::ISOLATION_UNCOMMITTED:
            case SqlTransaction::ISOLATION_COMMITTED:
            case SqlTransaction::ISOLATION_REPEATABLE:
            case SqlTransaction::ISOLATION_SERIALIZABLE:
                $this->isolation = $isolation;
                break;
            default:
                throw new \Error("Isolation must be a valid transaction isolation level");
        }
        $this->processor = $processor;
        $refCount =& $this->refCount;
        $this->release = static function () use(&$refCount, $release) {
            if (--$refCount === 0) {
                $release();
            }
        };
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->processor && $this->processor->isAlive()) {
            $this->rollback();
            // Invokes $this->release callback.
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->processor->getLastUsedAt();
    }
    /**
     * {@inheritdoc}
     *
     * Closes and commits all changes in the transaction.
     */
    public function close() : void
    {
        if ($this->processor) {
            $this->commit();
            // Invokes $this->release callback.
        }
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->processor && $this->processor->isAlive();
    }
    /**
     * @return bool True if the transaction is active, false if it has been committed or rolled back.
     */
    public function isActive() : bool
    {
        return $this->processor !== null;
    }
    /**
     * @return int
     */
    public function getIsolationLevel() : int
    {
        return $this->isolation;
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function query(string $sql) : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            $result = (yield $this->processor->query($sql));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return new PooledResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function prepare(string $sql) : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            $statement = (yield $this->processor->prepare($sql));
            return new PooledStatement($statement, $this->release);
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql, $params) {
            $statement = (yield $this->processor->prepare($sql));
            \assert($statement instanceof Statement);
            $result = (yield $statement->execute($params));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return new PooledResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     * Commits the transaction and makes it inactive.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function commit() : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->processor->query("COMMIT");
        $this->processor = null;
        $promise->onResolve($this->release);
        return $promise;
    }
    /**
     * Rolls back the transaction and makes it inactive.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollback() : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->processor->query("ROLLBACK");
        $this->processor = null;
        $promise->onResolve($this->release);
        return $promise;
    }
    /**
     * Creates a savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function createSavepoint(string $identifier) : Promise
    {
        return $this->query(\sprintf("SAVEPOINT `%s%s`", self::SAVEPOINT_PREFIX, \sha1($identifier)));
    }
    /**
     * Rolls back to the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollbackTo(string $identifier) : Promise
    {
        return $this->query(\sprintf("ROLLBACK TO `%s%s`", self::SAVEPOINT_PREFIX, \sha1($identifier)));
    }
    /**
     * Releases the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function releaseSavepoint(string $identifier) : Promise
    {
        return $this->query(\sprintf("RELEASE SAVEPOINT `%s%s`", self::SAVEPOINT_PREFIX, \sha1($identifier)));
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Common\PooledStatement as SqlPooledStatement;
use Amp\Sql\ResultSet as SqlResultSet;
final class PooledStatement extends SqlPooledStatement implements Statement
{
    private $statement;
    /**
     *
     */
    public function __construct(Statement $statement, callable $release)
    {
        parent::__construct($statement, $release);
        $this->statement = $statement;
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    public function bind($paramId, $data) : void
    {
        $this->statement->bind($paramId, $data);
    }
    /**
     *
     */
    public function getFields() : Promise
    {
        return $this->statement->getFields();
    }
    /**
     *
     */
    public function reset() : Promise
    {
        return $this->statement->reset();
    }
}<?php

namespace Amp\Mysql;

use Amp\CancellationToken;
use Amp\Promise;
use Amp\Socket;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
use Amp\Sql\Connector;
final class CancellableConnector implements Connector
{
    /** @var Socket\Connector */
    private $connector;
    /**
     *
     */
    public function __construct(?Socket\Connector $connector = null)
    {
        $this->connector = $connector ?? Socket\connector();
    }
    /**
     *
     */
    public function connect(SqlConnectionConfig $config, ?CancellationToken $token = null) : Promise
    {
        if (!$config instanceof ConnectionConfig) {
            throw new \TypeError(\sprintf("Must provide an instance of %s to MySQL connectors", ConnectionConfig::class));
        }
        return Connection::connect($config, $token, $this->connector);
    }
}<?php

namespace Amp\Mysql;

use Amp\Deferred;
use Amp\Promise;
use Amp\Sql\ConnectionException;
use Amp\Sql\FailureException;
use Amp\Success;
use function Amp\call;
final class ConnectionStatement implements Statement
{
    private $paramCount;
    private $numParamCount;
    private $named = [];
    private $byNamed;
    private $query;
    private $stmtId;
    private $prebound = [];
    /** @var Internal\Processor|null */
    private $processor;
    /** @var Internal\ResultProxy */
    private $result;
    /** @var int */
    private $lastUsedAt;
    /**
     *
     */
    public function __construct(Internal\Processor $processor, string $query, int $stmtId, array $named, Internal\ResultProxy $result)
    {
        $this->processor = $processor;
        $this->query = $query;
        $this->stmtId = $stmtId;
        $this->result = $result;
        $this->numParamCount = $this->paramCount = $this->result->columnsToFetch;
        $this->byNamed = $named;
        foreach ($named as $name => $ids) {
            foreach ($ids as $id) {
                $this->named[$id] = $name;
                $this->numParamCount--;
            }
        }
        $this->lastUsedAt = \time();
    }
    /**
     *
     */
    private function getProcessor() : Internal\Processor
    {
        if ($this->processor === null) {
            throw new \Error("The statement has been closed");
        }
        if (!$this->processor->isAlive()) {
            throw new ConnectionException("Connection went away");
        }
        return $this->processor;
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        if ($this->processor === null) {
            return false;
        }
        return $this->processor->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public function bind($paramId, $data) : void
    {
        if (\is_int($paramId)) {
            if ($paramId >= $this->numParamCount) {
                throw new \Error("Parameter id {$paramId} is not defined for this prepared statement");
            }
            $i = $paramId;
        } elseif (\is_string($paramId)) {
            if (!isset($this->byNamed[$paramId])) {
                throw new \Error("Parameter :{$paramId} is not defined for this prepared statement");
            }
            $array = $this->byNamed[$paramId];
            $i = \reset($array);
        } else {
            throw new \TypeError("Invalid parameter ID type");
        }
        if (!\is_scalar($data) && !(\is_object($data) && \method_exists($data, '__toString'))) {
            throw new \TypeError("Data must be scalar or object that implements __toString method");
        }
        do {
            $realId = -1;
            while (isset($this->named[++$realId]) || $i-- > 0) {
                if (!\is_numeric($paramId) && isset($this->named[$realId]) && $this->named[$realId] == $paramId) {
                    break;
                }
            }
            $this->getProcessor()->bindParam($this->stmtId, $realId, $data);
        } while (isset($array) && ($i = \next($array)));
        if (isset($this->prebound[$paramId])) {
            $this->prebound[$paramId] .= (string) $data;
        } else {
            $this->prebound[$paramId] = (string) $data;
        }
    }
    /**
     * {@inheritdoc}
     */
    public function execute(array $params = []) : Promise
    {
        $this->lastUsedAt = \time();
        $prebound = $args = [];
        for ($unnamed = $i = 0; $i < $this->paramCount; $i++) {
            if (isset($this->named[$i])) {
                $name = $this->named[$i];
                if (\array_key_exists($name, $params)) {
                    $args[$i] = $params[$name];
                } elseif (!\array_key_exists($name, $this->prebound)) {
                    throw new \Error("Named parameter '{$name}' missing for executing prepared statement");
                } else {
                    $prebound[$i] = $this->prebound[$name];
                }
            } elseif (\array_key_exists($unnamed, $params)) {
                $args[$i] = $params[$unnamed];
                $unnamed++;
            } elseif (!\array_key_exists($unnamed, $this->prebound)) {
                throw new \Error("Parameter {$unnamed} for prepared statement missing");
            } else {
                $prebound[$i] = $this->prebound[$unnamed++];
            }
        }
        $promise = $this->getProcessor()->execute($this->stmtId, $this->query, $this->result->params, $prebound, $args);
        return call(function () use($promise) {
            $result = (yield $promise);
            if ($result instanceof Internal\ResultProxy) {
                $result = new ConnectionResultSet($result);
                return $result;
            }
            if ($result instanceof CommandResult) {
                return $result;
            }
            throw new FailureException("Unrecognized result type");
        });
    }
    /**
     *
     */
    public function getQuery() : string
    {
        return $this->query;
    }
    /**
     *
     */
    private function close() : void
    {
        if ($this->processor === null) {
            return;
        }
        $this->processor->closeStmt($this->stmtId);
        $this->processor->unreference();
        $this->processor = null;
    }
    /**
     *
     */
    public function reset() : Promise
    {
        return $this->getProcessor()->resetStmt($this->stmtId);
    }
    /**
     *
     */
    public function getFields() : Promise
    {
        if ($this->result->state >= Internal\ResultProxy::COLUMNS_FETCHED) {
            return new Success($this->result->columns);
        }
        if (isset($this->result->deferreds[Internal\ResultProxy::COLUMNS_FETCHED][0])) {
            return $this->result->deferreds[Internal\ResultProxy::COLUMNS_FETCHED][0][0]->promise();
        }
        $deferred = new Deferred();
        $this->result->deferreds[Internal\ResultProxy::COLUMNS_FETCHED][0] = [$deferred, &$this->result->columns, null];
        return $deferred->promise();
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
}<?php

namespace Amp\Mysql;

use Amp\Sql\FailureException;
/** @see 14.6.4.1.1.1 Column Type */
final class DataTypes
{
    public const MYSQL_TYPE_DECIMAL = 0x0;
    public const MYSQL_TYPE_TINY = 0x1;
    public const MYSQL_TYPE_SHORT = 0x2;
    public const MYSQL_TYPE_LONG = 0x3;
    public const MYSQL_TYPE_FLOAT = 0x4;
    public const MYSQL_TYPE_DOUBLE = 0x5;
    public const MYSQL_TYPE_NULL = 0x6;
    public const MYSQL_TYPE_TIMESTAMP = 0x7;
    public const MYSQL_TYPE_LONGLONG = 0x8;
    public const MYSQL_TYPE_INT24 = 0x9;
    public const MYSQL_TYPE_DATE = 0xa;
    public const MYSQL_TYPE_TIME = 0xb;
    public const MYSQL_TYPE_DATETIME = 0xc;
    public const MYSQL_TYPE_YEAR = 0xd;
    public const MYSQL_TYPE_NEWDATE = 0xe;
    public const MYSQL_TYPE_VARCHAR = 0xf;
    public const MYSQL_TYPE_BIT = 0x10;
    public const MYSQL_TYPE_TIMESTAMP2 = 0x11;
    public const MYSQL_TYPE_DATETIME2 = 0x12;
    public const MYSQL_TYPE_TIME2 = 0x13;
    public const MYSQL_TYPE_JSON = 0xf5;
    public const MYSQL_TYPE_NEWDECIMAL = 0xf6;
    public const MYSQL_TYPE_ENUM = 0xf7;
    public const MYSQL_TYPE_SET = 0xf8;
    public const MYSQL_TYPE_TINY_BLOB = 0xf9;
    public const MYSQL_TYPE_MEDIUM_BLOB = 0xfa;
    public const MYSQL_TYPE_LONG_BLOB = 0xfb;
    public const MYSQL_TYPE_BLOB = 0xfc;
    public const MYSQL_TYPE_VAR_STRING = 0xfd;
    public const MYSQL_TYPE_STRING = 0xfe;
    public const MYSQL_TYPE_GEOMETRY = 0xff;
    private const ENCODED_JSON_PREFIX = "base64:type251:";
    /**
     * @see 14.7.3 Binary Value
     */
    public static function encodeBinary($param) : array
    {
        $unsigned = 0;
        switch (\gettype($param)) {
            case "boolean":
                $type = self::MYSQL_TYPE_TINY;
                $value = $param ? "\x01" : "\x00";
                break;
            case "integer":
                if ($param >= 0) {
                    $unsigned = 1;
                }
                if ($param >= 0 && $param < 1 << 15) {
                    $value = self::encodeInt16($param);
                    $type = self::MYSQL_TYPE_SHORT;
                } else {
                    $value = self::encodeInt64($param);
                    $type = self::MYSQL_TYPE_LONGLONG;
                }
                break;
            case "double":
                $value = \pack("e", $param);
                $type = self::MYSQL_TYPE_DOUBLE;
                break;
            case "string":
                $type = self::MYSQL_TYPE_LONG_BLOB;
                $value = self::encodeInt(\strlen($param)) . $param;
                break;
            case "NULL":
                $type = self::MYSQL_TYPE_NULL;
                $value = "";
                break;
            default:
                throw new FailureException("Unexpected type for binding parameter: " . \gettype($param));
        }
        return [$unsigned, $type, $value];
    }
    /**
     * @see 14.7.3 Binary Protocol Value
     */
    public static function decodeBinary(int $type, string $str, ?int &$len = null)
    {
        $unsigned = $type & 0x80;
        switch ($type) {
            case self::MYSQL_TYPE_STRING:
            case self::MYSQL_TYPE_VARCHAR:
            case self::MYSQL_TYPE_VAR_STRING:
            case self::MYSQL_TYPE_ENUM:
            case self::MYSQL_TYPE_SET:
            case self::MYSQL_TYPE_LONG_BLOB:
            case self::MYSQL_TYPE_MEDIUM_BLOB:
            case self::MYSQL_TYPE_BLOB:
            case self::MYSQL_TYPE_TINY_BLOB:
            case self::MYSQL_TYPE_GEOMETRY:
            case self::MYSQL_TYPE_BIT:
            case self::MYSQL_TYPE_DECIMAL:
            case self::MYSQL_TYPE_NEWDECIMAL:
                $ret = self::decodeString($str, $intlen, $len);
                $len += $intlen;
                return $ret;
            case self::MYSQL_TYPE_JSON:
                $ret = self::decodeString($str, $intlen, $len);
                $len += $intlen;
                return self::decodeJson($ret);
            case self::MYSQL_TYPE_LONGLONG:
            case self::MYSQL_TYPE_LONGLONG | 0x80:
                $len = 8;
                return $unsigned ? self::decodeUnsigned64($str) : self::decodeInt64($str);
            case self::MYSQL_TYPE_LONG:
            case self::MYSQL_TYPE_LONG | 0x80:
            case self::MYSQL_TYPE_INT24:
            case self::MYSQL_TYPE_INT24 | 0x80:
                $len = 4;
                return $unsigned ? self::decodeUnsigned32($str) : self::decodeInt32($str);
            case self::MYSQL_TYPE_SHORT:
            case self::MYSQL_TYPE_SHORT | 0x80:
                $len = 2;
                return $unsigned ? self::decodeUnsigned16($str) : self::decodeInt16($str);
            case self::MYSQL_TYPE_TINY:
            case self::MYSQL_TYPE_TINY | 0x80:
                $len = 1;
                return $unsigned ? \ord($str) : self::decodeInt8($str);
            case self::MYSQL_TYPE_DOUBLE:
                $len = 8;
                return \unpack("e", $str)[1];
            case self::MYSQL_TYPE_FLOAT:
                $len = 4;
                return \unpack("g", $str)[1];
            case self::MYSQL_TYPE_DATE:
            case self::MYSQL_TYPE_DATETIME:
            case self::MYSQL_TYPE_TIMESTAMP:
                $year = $month = $day = $hour = $minute = $second = $microsecond = 0;
                switch ($len = \ord($str) + 1) {
                    case 12:
                        $microsecond = self::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($str, 8));
                    // no break
                    case 8:
                        $second = \ord($str[7]);
                        $minute = \ord($str[6]);
                        $hour = \ord($str[5]);
                    // no break
                    case 5:
                        $day = \ord($str[4]);
                        $month = \ord($str[3]);
                        $year = self::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($str, 1));
                    // no break
                    case 1:
                        break;
                    default:
                        throw new FailureException("Unexpected string length for date in binary protocol: " . ($len - 1));
                }
                return \str_pad($year, 2, "0", STR_PAD_LEFT) . "-" . \str_pad($month, 2, "0", STR_PAD_LEFT) . "-" . \str_pad($day, 2, "0", STR_PAD_LEFT) . " " . \str_pad($hour, 2, "0", STR_PAD_LEFT) . ":" . \str_pad($minute, 2, "0", STR_PAD_LEFT) . ":" . \str_pad($second, 2, "0", STR_PAD_LEFT) . "." . \str_pad($microsecond, 5, "0", STR_PAD_LEFT);
            case self::MYSQL_TYPE_TIME:
                $negative = $day = $hour = $minute = $second = $microsecond = 0;
                switch ($len = \ord($str) + 1) {
                    case 13:
                        $microsecond = self::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($str, 9));
                    // no break
                    case 9:
                        $second = \ord($str[8]);
                        $minute = \ord($str[7]);
                        $hour = \ord($str[6]);
                        $day = self::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($str, 2));
                        $negative = \ord($str[1]);
                    // no break
                    case 1:
                        break;
                    default:
                        throw new FailureException("Unexpected string length for time in binary protocol: " . ($len - 1));
                }
                return ($negative ? "" : "-") . \str_pad($day, 2, "0", STR_PAD_LEFT) . "d " . \str_pad($hour, 2, "0", STR_PAD_LEFT) . ":" . \str_pad($minute, 2, "0", STR_PAD_LEFT) . ":" . \str_pad($second, 2, "0", STR_PAD_LEFT) . "." . \str_pad($microsecond, 5, "0", STR_PAD_LEFT);
            case self::MYSQL_TYPE_NULL:
                $len = 0;
                return null;
            default:
                throw new FailureException("Invalid type for Binary Protocol: 0x" . \dechex($type));
        }
    }
    /**
     *
     */
    public static function decodeNullString(string $str, ?int &$len = null) : string
    {
        return \Phabel\Target\Php80\Polyfill::substr($str, 0, $len = \strpos($str, "\x00"));
    }
    /**
     *
     */
    public static function decodeStringOff(int $type, string $str, int &$off)
    {
        $len = self::decodeUnsignedOff($str, $off);
        $off += $len;
        $data = (string) \Phabel\Target\Php80\Polyfill::substr($str, $off - $len, $len);
        switch ($type) {
            case self::MYSQL_TYPE_LONGLONG | 0x80:
                return $type;
            // Return UNSIGNED BIGINT as a string.
            case self::MYSQL_TYPE_LONGLONG:
            case self::MYSQL_TYPE_LONG | 0x80:
                if (\PHP_INT_SIZE < 8) {
                    return $type;
                    // Return BIGINT and UNSIGNED INT as string on 32-bit.
                }
            // no break
            case self::MYSQL_TYPE_LONG:
            case self::MYSQL_TYPE_INT24:
            case self::MYSQL_TYPE_INT24 | 0x80:
            case self::MYSQL_TYPE_SHORT:
            case self::MYSQL_TYPE_SHORT | 0x80:
            case self::MYSQL_TYPE_TINY:
            case self::MYSQL_TYPE_TINY | 0x80:
                return (int) $data;
            case self::MYSQL_TYPE_DOUBLE:
            case self::MYSQL_TYPE_FLOAT:
                return (float) $data;
            case self::MYSQL_TYPE_JSON:
                return self::decodeJson($data);
            default:
                return $data;
        }
    }
    /**
     *
     */
    private static function decodeJson(string $data) : string
    {
        if (\strncmp(self::ENCODED_JSON_PREFIX, $data, \strlen(self::ENCODED_JSON_PREFIX)) !== 0) {
            return $data;
            // Data was not base-64 encoded.
        }
        $data = \Phabel\Target\Php80\Polyfill::substr($data, \strlen(self::ENCODED_JSON_PREFIX));
        return \base64_decode($data);
    }
    /**
     *
     */
    public static function decodeUnsignedOff(string $str, int &$off) : int
    {
        $int = \ord($str[$off]);
        if ($int < 0xfb) {
            $off += 1;
            return $int;
        }
        if ($int == 0xfc) {
            $off += 3;
            return self::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($str, $off - 2, 2));
        }
        if ($int == 0xfd) {
            $off += 4;
            return self::decodeUnsigned24(\Phabel\Target\Php80\Polyfill::substr($str, $off - 3, 3));
        }
        if ($int == 0xfe) {
            $off += 9;
            return self::decodeUnsigned64(\Phabel\Target\Php80\Polyfill::substr($str, $off - 8, 8));
        }
        // If that happens connection is borked...
        throw new FailureException("{$int} is not in ranges [0x00, 0xfa] or [0xfc, 0xfe]");
    }
    /**
     *
     */
    public static function decodeString(string $str, ?int &$intlen = null, ?int &$len = null) : string
    {
        $len = self::decodeUnsigned($str, $intlen);
        return \Phabel\Target\Php80\Polyfill::substr($str, $intlen, $len);
    }
    /**
     *
     */
    public static function decodeUnsigned(string $str, ?int &$len = null)
    {
        $int = \ord($str);
        if ($int < 0xfb) {
            $len = 1;
            return $int;
        }
        if ($int == 0xfc) {
            $len = 3;
            return self::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($str, 1, 2));
        }
        if ($int == 0xfd) {
            $len = 4;
            return self::decodeUnsigned24(\Phabel\Target\Php80\Polyfill::substr($str, 1, 4));
        }
        if ($int == 0xfe) {
            $len = 9;
            return self::decodeUnsigned64(\Phabel\Target\Php80\Polyfill::substr($str, 1, 8));
        }
        // If that happens connection is borked...
        throw new FailureException("{$int} is not in ranges [0x00, 0xfa] or [0xfc, 0xfe]");
    }
    /**
     *
     */
    public static function decodeIntByLen(string $str, int $len) : int
    {
        $int = 0;
        while ($len--) {
            $int = ($int << 8) + \ord($str[$len]);
        }
        return $int;
    }
    /**
     *
     */
    public static function decodeInt8(string $str) : int
    {
        $int = \ord($str);
        if ($int < 1 << 7) {
            return $int;
        }
        $shift = \PHP_INT_SIZE * 8 - 8;
        return $int << $shift >> $shift;
    }
    /**
     *
     */
    public static function decodeUnsigned8(string $str) : int
    {
        return \ord($str);
    }
    /**
     *
     */
    public static function decodeInt16(string $str) : int
    {
        $int = \unpack("v", $str)[1];
        if ($int < 1 << 15) {
            return $int;
        }
        $shift = \PHP_INT_SIZE * 8 - 16;
        return $int << $shift >> $shift;
    }
    /**
     *
     */
    public static function decodeUnsigned16(string $str)
    {
        return \unpack("v", $str)[1];
    }
    /**
     *
     */
    public static function decodeInt24(string $str) : int
    {
        $int = \unpack("V", \Phabel\Target\Php80\Polyfill::substr($str, 0, 3) . "\x00")[1];
        if ($int < 1 << 23) {
            return $int;
        }
        $shift = \PHP_INT_SIZE * 8 - 24;
        return $int << $shift >> $shift;
    }
    /**
     *
     */
    public static function decodeUnsigned24(string $str) : int
    {
        return \unpack("V", \Phabel\Target\Php80\Polyfill::substr($str, 0, 3) . "\x00")[1];
    }
    /**
     *
     */
    public static function decodeInt32($str) : int
    {
        if (\PHP_INT_SIZE > 4) {
            $int = \unpack("V", $str)[1];
            if ($int < 1 << 31) {
                return $int;
            }
            return $int << 32 >> 32;
        }
        return \unpack("V", $str)[1];
    }
    /**
     *
     */
    public static function decodeUnsigned32(string $str)
    {
        if (\PHP_INT_SIZE > 4) {
            return \unpack("V", $str)[1];
        }
        \assert(\extension_loaded("gmp"), "The GMP extension is required for UNSIGNED INT fields on 32-bit systems");
        return \gmp_strval(\gmp_import(\Phabel\Target\Php80\Polyfill::substr($str, 0, 4), 1, \GMP_LSW_FIRST));
    }
    /**
     *
     */
    public static function decodeInt64(string $str)
    {
        if (\PHP_INT_SIZE > 4) {
            return \unpack("P", $str)[1];
        }
        \assert(\extension_loaded("gmp"), "The GMP extension is required for BIGINT fields on 32-bit systems");
        return \gmp_strval(\gmp_import(\Phabel\Target\Php80\Polyfill::substr($str, 0, 8), 1, \GMP_LSW_FIRST));
    }
    /**
     *
     */
    public static function decodeUnsigned64(string $str)
    {
        \assert(\extension_loaded("gmp"), "The GMP extension is required for UNSIGNED BIGINT fields");
        return \gmp_strval(\gmp_import(\Phabel\Target\Php80\Polyfill::substr($str, 0, 8), 1, \GMP_LSW_FIRST));
    }
    /**
     *
     */
    public static function encodeInt(int $int) : string
    {
        if ($int < 0xfb) {
            return \chr($int);
        }
        if ($int < 1 << 16) {
            return "\xfc" . self::encodeInt16($int);
        }
        if ($int < 1 << 24) {
            return "\xfd" . self::encodeInt24($int);
        }
        if ($int < (1 << 62) * 4) {
            return "\xfe" . self::encodeInt64($int);
        }
        throw new FailureException("encodeInt doesn't allow integers bigger than 2^64 - 1 (current: {$int})");
    }
    /**
     *
     */
    public static function encodeInt16(int $int) : string
    {
        return \pack("v", $int);
    }
    /**
     *
     */
    public static function encodeInt24(int $int) : string
    {
        return \Phabel\Target\Php80\Polyfill::substr(\pack("V", $int), 0, 3);
    }
    /**
     *
     */
    public static function encodeInt32(int $int) : string
    {
        return \pack("V", $int);
    }
    /**
     *
     */
    public static function encodeInt64(int $int) : string
    {
        return \pack("VV", $int & 0xffffffff, $int >> 32);
    }
}<?php

namespace Amp\Mysql;

class TransactionError extends \Amp\Sql\TransactionError
{
}<?php

namespace Amp\Mysql;

use Amp\Sql\FailureException;
class InitializationException extends FailureException
{
}<?php

namespace Amp\Mysql\Internal;

use Amp\CancellationToken;
use Amp\Coroutine;
use Amp\Deferred;
use Amp\File;
use Amp\Loop;
use Amp\Mysql\CommandResult;
use Amp\Mysql\ConnectionConfig;
use Amp\Mysql\ConnectionStatement;
use Amp\Mysql\DataTypes;
use Amp\Mysql\InitializationException;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Sql\ConnectionException;
use Amp\Sql\FailureException;
use Amp\Sql\QueryError;
use Amp\Sql\TransientResource;
/* @TODO
 * 14.2.3 Auth switch request??
 * 14.2.4 COM_CHANGE_USER
 */
/** @see 14.1.3.4 Status Flags */
final class StatusFlags
{
    public const SERVER_STATUS_IN_TRANS = 0x1;
    // a transaction is active
    public const SERVER_STATUS_AUTOCOMMIT = 0x2;
    // auto-commit is enabled
    public const SERVER_MORE_RESULTS_EXISTS = 0x8;
    public const SERVER_STATUS_NO_GOOD_INDEX_USED = 0x10;
    public const SERVER_STATUS_NO_INDEX_USED = 0x20;
    public const SERVER_STATUS_CURSOR_EXISTS = 0x40;
    // Used by Binary Protocol Resultset to signal that COM_STMT_FETCH has to be used to fetch the row-data.
    public const SERVER_STATUS_LAST_ROW_SENT = 0x80;
    public const SERVER_STATUS_DB_DROPPED = 0x100;
    public const SERVER_STATUS_NO_BACKSLASH_ESCAPES = 0x200;
    public const SERVER_STATUS_METADATA_CHANGED = 0x400;
    public const SERVER_QUERY_WAS_SLOW = 0x800;
    public const SERVER_PS_OUT_PARAMS = 0x1000;
    public const SERVER_STATUS_IN_TRANS_READONLY = 0x2000;
    // in a read-only transaction
    public const SERVER_SESSION_STATE_CHANGED = 0x4000;
    // connection state information has changed
}
/** @see 13.1.3.1.1 Session State Information */
final class SessionStateTypes
{
    public const SESSION_TRACK_SYSTEM_VARIABLES = 0x0;
    public const SESSION_TRACK_SCHEMA = 0x1;
    public const SESSION_TRACK_STATE_CHANGE = 0x2;
    public const SESSION_TRACK_GTIDS = 0x3;
    public const SESSION_TRACK_TRANSACTION_CHARACTERISTICS = 0x4;
    public const SESSION_TRACK_TRANSACTION_STATE = 0x5;
}
/** @internal */
class Processor implements TransientResource
{
    const STATEMENT_PARAM_REGEX = <<<'REGEX'
~(["'`])(?:\\(?:\\|\1)|(?!\1).)*+\1(*SKIP)(*FAIL)|(\?)|:([a-zA-Z_][a-zA-Z0-9_]*)~ms
REGEX;
    /** @var \Generator[] */
    private $processors = [];
    /** @var int */
    private $protocol;
    private $seqId = -1;
    private $compressionId = -1;
    /** @var EncryptableSocket */
    private $socket;
    private $authPluginDataLen;
    private $query;
    public $named = [];
    /** @var callable|null */
    private $parseCallback = null;
    /** @var callable|null */
    private $packetCallback = null;
    /** @var \Amp\Promise|null */
    private $pendingWrite;
    /** @var \Amp\Sql\ConnectionConfig */
    public $config;
    /** @var \Amp\Deferred[] */
    private $deferreds = [];
    /** @var callable[] */
    private $onReady = [];
    /** @var ResultProxy|null */
    private $result;
    /** @var int */
    private $lastUsedAt;
    private $connectionId;
    private $authPluginData;
    private $capabilities = 0;
    private $serverCapabilities = 0;
    private $authPluginName;
    private $connInfo;
    private $refcount = 1;
    private $connectionState = self::UNCONNECTED;
    private const MAX_PACKET_SIZE = 0xffffff;
    private const MAX_UNCOMPRESSED_BUFLEN = 0xfffffb;
    private const CLIENT_LONG_FLAG = 0x4;
    private const CLIENT_CONNECT_WITH_DB = 0x8;
    private const CLIENT_COMPRESS = 0x20;
    private const CLIENT_LOCAL_INFILE = 0x80;
    private const CLIENT_PROTOCOL_41 = 0x200;
    private const CLIENT_SSL = 0x800;
    private const CLIENT_TRANSACTIONS = 0x2000;
    private const CLIENT_SECURE_CONNECTION = 0x8000;
    private const CLIENT_MULTI_STATEMENTS = 0x10000;
    private const CLIENT_MULTI_RESULTS = 0x20000;
    private const CLIENT_PS_MULTI_RESULTS = 0x40000;
    private const CLIENT_PLUGIN_AUTH = 0x80000;
    private const CLIENT_CONNECT_ATTRS = 0x100000;
    private const CLIENT_SESSION_TRACK = 0x800000;
    private const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x200000;
    private const CLIENT_DEPRECATE_EOF = 0x1000000;
    private const OK_PACKET = 0x0;
    private const EXTRA_AUTH_PACKET = 0x1;
    private const LOCAL_INFILE_REQUEST = 0xfb;
    private const AUTH_SWITCH_PACKET = 0xfe;
    private const EOF_PACKET = 0xfe;
    private const ERR_PACKET = 0xff;
    private const UNCONNECTED = 0;
    private const ESTABLISHED = 1;
    private const READY = 2;
    private const CLOSING = 3;
    private const CLOSED = 4;
    /**
     *
     */
    public function __construct(EncryptableSocket $socket, ConnectionConfig $config)
    {
        $this->socket = $socket;
        $this->connInfo = new ConnectionState();
        $this->config = $config;
        $this->lastUsedAt = \time();
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return $this->connectionState <= self::READY;
    }
    /**
     *
     */
    public function isReady() : bool
    {
        return $this->connectionState === self::READY;
    }
    /**
     *
     */
    public function unreference() : void
    {
        if (!--$this->refcount) {
            $this->appendTask(function () {
                $this->close();
            });
        }
    }
    /**
     *
     */
    private function ready() : void
    {
        if (!empty($this->deferreds)) {
            return;
        }
        if (!empty($this->onReady)) {
            \array_shift($this->onReady)();
            return;
        }
        $this->resetIds();
        if ($this->socket) {
            try {
                $this->socket->unreference();
            } catch (Loop\InvalidWatcherError $exception) {
                // Undefined destruct order can cause unref of an invalid watcher if the loop is swapped.
                // Generally this will only happen during tests.
            }
        }
    }
    /**
     *
     */
    private function addDeferred(Deferred $deferred) : void
    {
        \assert($this->socket, "The connection has been closed");
        $this->deferreds[] = $deferred;
        $this->socket->reference();
    }
    /**
     *
     */
    public function connect(CancellationToken $token) : Promise
    {
        \assert(!$this->processors, self::class . "::connect() must not be called twice");
        $this->deferreds[] = $deferred = new Deferred();
        // Will be resolved in sendHandshake().
        $this->processors = [$this->parseMysql()];
        $id = $token->subscribe(function () : void {
            $this->close();
        });
        Promise\rethrow(new Coroutine($this->read()));
        $promise = $deferred->promise();
        $promise->onResolve(static function () use($id, $token) : void {
            $token->unsubscribe($id);
        });
        if ($this->config->getCharset() !== ConnectionConfig::DEFAULT_CHARSET || $this->config->getCollation() !== ConnectionConfig::DEFAULT_COLLATE) {
            $promise->onResolve(function (?\Throwable $exception) : void {
                if ($exception) {
                    return;
                }
                $charset = $this->config->getCharset();
                $collate = $this->config->getCollation();
                $this->query("SET NAMES '{$charset}'" . ($collate === "" ? "" : " COLLATE '{$collate}'"));
            });
        }
        return $promise;
    }
    /**
     *
     */
    private function read() : \Generator
    {
        try {
            while (($bytes = (yield $this->socket->read())) !== null) {
                // @codeCoverageIgnoreStart
                \assert((function () use($bytes) {
                    if (\defined("MYSQL_DEBUG")) {
                        \fwrite(STDERR, "in: ");
                        for ($i = 0; $i < \min(\strlen($bytes), 200); $i++) {
                            \fwrite(STDERR, \dechex(\ord($bytes[$i])) . " ");
                        }
                        $r = \range("\x00", "\x1f");
                        unset($r[10], $r[9]);
                        \fwrite(STDERR, "len: " . \strlen($bytes) . "\n");
                        \fwrite(STDERR, \str_replace($r, ".", \Phabel\Target\Php80\Polyfill::substr($bytes, 0, 200)) . "\n");
                    }
                    return true;
                })());
                // @codeCoverageIgnoreEnd
                $this->lastUsedAt = \time();
                $this->processData($bytes);
                $bytes = null;
                // Free last data read.
                if (!$this->socket) {
                    // Connection closed.
                    break;
                }
            }
        } catch (\Throwable $exception) {
            // $exception used as previous exception below.
        } finally {
            $this->close();
        }
        if (!empty($this->deferreds)) {
            $exception = new ConnectionException("Connection closed unexpectedly", 0, $exception ?? null);
            foreach ($this->deferreds as $deferred) {
                $deferred->fail($exception);
            }
        }
    }
    /**
     *
     */
    private function processData(string $data) : void
    {
        foreach ($this->processors as $processor) {
            if (empty($data = $processor->send($data))) {
                return;
            }
        }
        \assert(\is_array($data), "Final processor should yield an array");
        foreach ($data as $packet) {
            $this->parsePayload($packet);
        }
    }
    /**
     *
     */
    private function getDeferred() : Deferred
    {
        return \array_shift($this->deferreds);
    }
    /**
     *
     */
    private function appendTask(callable $callback) : void
    {
        if ($this->packetCallback || $this->parseCallback || !empty($this->onReady) || !empty($this->deferreds) || $this->connectionState !== self::READY) {
            $this->onReady[] = $callback;
        } else {
            $callback();
        }
    }
    /**
     *
     */
    public function getConnInfo() : ConnectionState
    {
        return clone $this->connInfo;
    }
    /**
     *
     */
    public function getConnectionId() : int
    {
        return $this->connectionId;
    }
    /**
     *
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     *
     */
    protected function startCommand(callable $callback) : Promise
    {
        if ($this->connectionState > self::READY) {
            throw new \Error("The connection has been closed");
        }
        $deferred = new Deferred();
        $this->appendTask(function () use($callback, $deferred) {
            $this->seqId = $this->compressionId = -1;
            $this->addDeferred($deferred);
            $callback();
        });
        return $deferred->promise();
    }
    /**
     *
     */
    public function setCharset(string $charset, string $collate = "") : Promise
    {
        return \Amp\call(function () use($charset, $collate) {
            if ($collate === "" && false !== ($off = \strpos($charset, "_"))) {
                $collate = $charset;
                $charset = \Phabel\Target\Php80\Polyfill::substr($collate, 0, $off);
            }
            $query = "SET NAMES '{$charset}'" . ($collate === "" ? "" : " COLLATE '{$collate}'");
            $result = (yield $this->query($query));
            $this->config = $this->config->withCharset($charset, $collate);
            return $result;
        });
    }
    /**
     * @see 14.6.3 COM_INIT_DB
     */
    public function useDb(string $db) : Promise
    {
        return $this->startCommand(function () use($db) {
            $this->config = $this->config->withDatabase($db);
            $this->sendPacket("\x02{$db}");
        });
    }
    /**
     * @see 14.6.4 COM_QUERY
     */
    public function query(string $query) : Promise
    {
        return $this->startCommand(function () use($query) {
            $this->query = $query;
            $this->parseCallback = [$this, "handleQuery"];
            $this->sendPacket("\x03{$query}");
        });
    }
    /**
     * @see 14.7.4 COM_STMT_PREPARE
     */
    public function prepare(string $query) : Promise
    {
        return $this->startCommand(function () use($query) {
            $this->query = $query;
            $this->parseCallback = [$this, "handlePrepare"];
            $query = \preg_replace_callback(self::STATEMENT_PARAM_REGEX, function ($m) {
                static $index = 0;
                if ($m[2] !== "?") {
                    $this->named[$m[3]][] = $index;
                }
                $index++;
                return "?";
            }, $query);
            $this->sendPacket("\x16{$query}");
        });
    }
    /** @see 14.6.18 COM_CHANGE_USER */
    /* @TODO broken, my test server doesn't support that command, can't test now
        public function changeUser($user, $pass, $db = null) {
            return $this->startCommand(function() use ($user, $pass, $db) {
                $this->config->user = $user;
                $this->config->pass = $pass;
                $this->config->db = $db;
                $payload = "\x11";
    
                $payload .= "$user\0";
                $auth = $this->secureAuth($this->config->pass, $this->authPluginData);
                if ($this->capabilities & self::CLIENT_SECURE_CONNECTION) {
                    $payload .= ord($auth) . $auth;
                } else {
                    $payload .= "$auth\0";
                }
                $payload .= "$db\0";
    
                $this->sendPacket($payload);
                $this->parseCallback = [$this, "authSwitchRequest"];
            });
        }
        */
    /**
     * @see 14.6.15 COM_PING
     */
    public function ping() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\x0e");
        });
    }
    /**
     * @see 14.6.19 COM_RESET_CONNECTION
     */
    public function resetConnection() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\x1f");
        });
    }
    /**
     * @see 14.7.5 COM_STMT_SEND_LONG_DATA
     */
    public function bindParam(int $stmtId, int $paramId, string $data) : void
    {
        $payload = "\x18";
        $payload .= DataTypes::encodeInt32($stmtId);
        $payload .= DataTypes::encodeInt16($paramId);
        $payload .= $data;
        $this->appendTask(function () use($payload) {
            $this->resetIds();
            $this->sendPacket($payload);
            $this->ready();
        });
    }
    /**
     * @see 14.7.6 COM_STMT_EXECUTE
     */
    // prebound params: null-bit set, type MYSQL_TYPE_LONG_BLOB, no value
    // $params is by-ref, because the actual result object might not yet have been filled completely with data upon call of this method ...
    public function execute(int $stmtId, string $query, array &$params, array $prebound, array $data = []) : Promise
    {
        $deferred = new Deferred();
        $this->appendTask(function () use($stmtId, $query, &$params, $prebound, $data, $deferred) {
            $payload = "\x17";
            $payload .= DataTypes::encodeInt32($stmtId);
            $payload .= \chr(0);
            // cursor flag // @TODO cursor types?!
            $payload .= DataTypes::encodeInt32(1);
            $paramCount = \count($params);
            $bound = !empty($data) || !empty($prebound);
            $types = "";
            $values = "";
            if ($paramCount) {
                $args = $data + \array_fill(0, $paramCount, null);
                \ksort($args);
                $args = \array_slice($args, 0, $paramCount);
                $nullOff = \strlen($payload);
                $payload .= \str_repeat("\x00", $paramCount + 7 >> 3);
                foreach ($args as $paramId => $param) {
                    if ($param === null) {
                        $off = $nullOff + ($paramId >> 3);
                        $payload[$off] = $payload[$off] | \chr(1 << $paramId % 8);
                    } else {
                        $bound = 1;
                    }
                    list($unsigned, $type, $value) = DataTypes::encodeBinary($param);
                    if (isset($prebound[$paramId])) {
                        $types .= \chr(DataTypes::MYSQL_TYPE_LONG_BLOB);
                    } else {
                        $types .= \chr($type);
                    }
                    $types .= $unsigned ? "\x80" : "\x00";
                    $values .= $value;
                }
                $payload .= \chr($bound);
                if ($bound) {
                    $payload .= $types;
                    $payload .= $values;
                }
            }
            $this->query = $query;
            $this->resetIds();
            $this->addDeferred($deferred);
            $this->sendPacket($payload);
            // apparently LOAD DATA LOCAL INFILE requests are not supported via prepared statements
            $this->packetCallback = [$this, "handleExecute"];
        });
        return $deferred->promise();
        // do not use $this->startCommand(), that might unexpectedly reset the seqId!
    }
    /**
     * @see 14.7.7 COM_STMT_CLOSE
     */
    public function closeStmt(int $stmtId) : void
    {
        $payload = "\x19" . DataTypes::encodeInt32($stmtId);
        $this->appendTask(function () use($payload) {
            if ($this->connectionState === self::READY) {
                $this->resetIds();
                $this->sendPacket($payload);
                $this->resetIds();
                // does not expect a reply - must be reset immediately
            }
            $this->ready();
        });
    }
    /**
     * @see 14.6.5 COM_FIELD_LIST
     */
    public function listFields(string $table, string $like = "%") : Promise
    {
        return $this->startCommand(static function () use($table, $like) {
            $this->sendPacket("\x04{$table}\x00{$like}");
            $this->parseCallback = [$this, "handleFieldlist"];
        });
    }
    /**
     *
     */
    public function listAllFields(string $table, string $like = "%") : Promise
    {
        $deferred = new Deferred();
        $columns = [];
        $onResolve = function ($error, $array) use(&$columns, &$onResolve, $deferred) {
            if ($error) {
                $deferred->fail($error);
                return;
            }
            if ($array === null) {
                $deferred->resolve($columns);
                return;
            }
            list($columns[], $promise) = $array;
            $promise->onResolve($onResolve);
        };
        $this->listFields($table, $like)->onResolve($onResolve);
        return $deferred->promise();
    }
    /**
     * @see 14.6.6 COM_CREATE_DB
     */
    public function createDatabase(string $db) : Promise
    {
        return $this->startCommand(function () use($db) {
            $this->sendPacket("\x05{$db}");
        });
    }
    /**
     * @see 14.6.7 COM_DROP_DB
     */
    public function dropDatabase(string $db) : Promise
    {
        return $this->startCommand(function () use($db) {
            $this->sendPacket("\x06{$db}");
        });
    }
    /**
     * @param $subcommand int one of the self::REFRESH_* constants
     * @see 14.6.8 COM_REFRESH
     */
    public function refresh(int $subcommand) : Promise
    {
        return $this->startCommand(function () use($subcommand) {
            $this->sendPacket("\x07" . \chr($subcommand));
        });
    }
    /**
     * @see 14.6.9 COM_SHUTDOWN
     */
    public function shutdown() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\x08\x00");
            /* SHUTDOWN_DEFAULT / SHUTDOWN_WAIT_ALL_BUFFERS, only one in use */
        });
    }
    /**
     * @see 14.6.10 COM_STATISTICS
     */
    public function statistics() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\t");
            $this->parseCallback = [$this, "readStatistics"];
        });
    }
    /**
     * @see 14.6.11 COM_PROCESS_INFO
     */
    public function processInfo() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\n");
            $this->query("SHOW PROCESSLIST");
        });
    }
    /**
     * @see 14.6.13 COM_PROCESS_KILL
     */
    public function killProcess(int $process) : Promise
    {
        return $this->startCommand(function () use($process) {
            $this->sendPacket("\f" . DataTypes::encodeInt32($process));
        });
    }
    /**
     * @see 14.6.14 COM_DEBUG
     */
    public function debugStdout() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\r");
        });
    }
    /**
     * @see 14.7.8 COM_STMT_RESET
     */
    public function resetStmt(int $stmtId) : Promise
    {
        $payload = "\x1a" . DataTypes::encodeInt32($stmtId);
        $deferred = new Deferred();
        $this->appendTask(function () use($payload, $deferred) {
            $this->resetIds();
            $this->addDeferred($deferred);
            $this->sendPacket($payload);
        });
        return $deferred->promise();
    }
    /**
     * @see 14.8.4 COM_STMT_FETCH
     */
    public function fetchStmt(int $stmtId) : Promise
    {
        $payload = "\x1c" . DataTypes::encodeInt32($stmtId) . DataTypes::encodeInt32(1);
        $deferred = new Deferred();
        $this->appendTask(function () use($payload, $deferred) {
            $this->resetIds();
            $this->addDeferred($deferred);
            $this->sendPacket($payload);
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function established() : void
    {
        // @TODO flags to use?
        $this->capabilities |= self::CLIENT_SESSION_TRACK | self::CLIENT_TRANSACTIONS | self::CLIENT_PROTOCOL_41 | self::CLIENT_SECURE_CONNECTION | self::CLIENT_MULTI_RESULTS | self::CLIENT_PS_MULTI_RESULTS | self::CLIENT_MULTI_STATEMENTS | self::CLIENT_PLUGIN_AUTH | self::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA;
        if (\extension_loaded("zlib") && $this->config->isCompressionEnabled()) {
            $this->capabilities |= self::CLIENT_COMPRESS;
        }
        if ($this->config->isLocalInfileEnabled()) {
            $this->capabilities |= self::CLIENT_LOCAL_INFILE;
        }
    }
    /**
     * @see 14.1.3.2 ERR-Packet
     */
    private function handleError(string $packet) : void
    {
        $off = 1;
        $this->connInfo->errorCode = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off, 2));
        $off += 2;
        if ($this->capabilities & self::CLIENT_PROTOCOL_41) {
            $this->connInfo->errorState = \Phabel\Target\Php80\Polyfill::substr($packet, $off, 6);
            $off += 6;
        }
        $this->connInfo->errorMsg = \Phabel\Target\Php80\Polyfill::substr($packet, $off);
        $this->parseCallback = null;
        if ($this->connectionState < self::READY) {
            // connection failure
            $this->close();
            $this->getDeferred()->fail(new InitializationException("Could not connect to {$this->config->getConnectionString()}: {$this->connInfo->errorState} {$this->connInfo->errorMsg}"));
            return;
        }
        if ($this->result === null && empty($this->deferreds)) {
            // connection killed without pending query or active result
            $this->close();
            return;
        }
        $deferred = $this->result ?? $this->getDeferred();
        // normal error
        $exception = new QueryError("MySQL error ({$this->connInfo->errorCode}): {$this->connInfo->errorState} {$this->connInfo->errorMsg}", $this->query);
        $this->result = null;
        $this->query = null;
        $deferred->fail($exception);
        $this->ready();
    }
    /**
     * @see 14.1.3.1 OK-Packet
     */
    private function parseOk(string $packet) : void
    {
        $off = 1;
        $this->connInfo->affectedRows = DataTypes::decodeUnsigned(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $intlen);
        $off += $intlen;
        $this->connInfo->insertId = DataTypes::decodeUnsigned(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $intlen);
        $off += $intlen;
        if ($this->capabilities & (self::CLIENT_PROTOCOL_41 | self::CLIENT_TRANSACTIONS)) {
            $this->connInfo->statusFlags = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
            $off += 2;
            $this->connInfo->warnings = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
            $off += 2;
        }
        if ($this->capabilities & self::CLIENT_SESSION_TRACK) {
            // Even though it seems required according to 14.1.3.1, there is no length encoded string, i.e. no trailing NULL byte ....???
            if (\strlen($packet) > $off) {
                $this->connInfo->statusInfo = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
                if ($this->connInfo->statusFlags & StatusFlags::SERVER_SESSION_STATE_CHANGED) {
                    $sessionState = DataTypes::decodeString(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $intlen, $sessionStateLen);
                    $len = 0;
                    while ($len < $sessionStateLen) {
                        $data = DataTypes::decodeString(\Phabel\Target\Php80\Polyfill::substr($sessionState, $len + 1), $datalen, $intlen);
                        switch ($type = DataTypes::decodeUnsigned8(\Phabel\Target\Php80\Polyfill::substr($sessionState, $len))) {
                            case SessionStateTypes::SESSION_TRACK_SYSTEM_VARIABLES:
                                $var = DataTypes::decodeString($data, $varintlen, $strlen);
                                $this->connInfo->sessionState[$type][$var] = DataTypes::decodeString(\Phabel\Target\Php80\Polyfill::substr($data, $varintlen + $strlen));
                                break;
                            case SessionStateTypes::SESSION_TRACK_SCHEMA:
                            case SessionStateTypes::SESSION_TRACK_STATE_CHANGE:
                            case SessionStateTypes::SESSION_TRACK_GTIDS:
                            case SessionStateTypes::SESSION_TRACK_TRANSACTION_CHARACTERISTICS:
                            case SessionStateTypes::SESSION_TRACK_TRANSACTION_STATE:
                                $this->connInfo->sessionState[$type] = DataTypes::decodeString($data);
                                break;
                            default:
                                throw new \Error("{$type} is not a valid mysql session state type");
                        }
                        $len += 1 + $intlen + $datalen;
                    }
                }
            } else {
                $this->connInfo->statusInfo = "";
            }
        } else {
            $this->connInfo->statusInfo = \Phabel\Target\Php80\Polyfill::substr($packet, $off);
        }
    }
    /**
     *
     */
    private function handleOk(string $packet) : void
    {
        $this->parseOk($packet);
        $this->getDeferred()->resolve(new CommandResult($this->connInfo->affectedRows, $this->connInfo->insertId));
        $this->ready();
    }
    /**
     * @see 14.1.3.3 EOF-Packet
     */
    private function parseEof(string $packet) : void
    {
        if ($this->capabilities & self::CLIENT_PROTOCOL_41) {
            $this->connInfo->warnings = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, 1));
            $this->connInfo->statusFlags = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, 3));
        }
    }
    /**
     *
     */
    private function handleEof(string $packet) : void
    {
        $this->parseEof($packet);
        $exception = new FailureException($this->connInfo->errorMsg, $this->connInfo->errorCode);
        $this->getDeferred()->fail($exception);
        $this->ready();
    }
    /**
     * @see 14.2.5 Connection Phase Packets
     */
    private function handleHandshake(string $packet) : void
    {
        $off = 1;
        $this->protocol = \ord($packet);
        if ($this->protocol !== 0xa) {
            throw new ConnectionException("Unsupported protocol version " . \ord($packet) . " (Expected: 10)");
        }
        $this->connInfo->serverVersion = DataTypes::decodeNullString(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $len);
        $off += $len + 1;
        $this->connectionId = DataTypes::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 4;
        $this->authPluginData = \Phabel\Target\Php80\Polyfill::substr($packet, $off, 8);
        $off += 8;
        $off += 1;
        // filler byte
        $this->serverCapabilities = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 2;
        if (\strlen($packet) > $off) {
            $this->connInfo->charset = \ord(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
            $off += 1;
            $this->connInfo->statusFlags = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
            $off += 2;
            $this->serverCapabilities += DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off)) << 16;
            $off += 2;
            $this->authPluginDataLen = $this->serverCapabilities & self::CLIENT_PLUGIN_AUTH ? \ord(\Phabel\Target\Php80\Polyfill::substr($packet, $off)) : 0;
            $off += 1;
            if ($this->serverCapabilities & self::CLIENT_SECURE_CONNECTION) {
                $off += 10;
                $strlen = \max(13, $this->authPluginDataLen - 8);
                $this->authPluginData .= \Phabel\Target\Php80\Polyfill::substr($packet, $off, $strlen);
                $off += $strlen;
                if ($this->serverCapabilities & self::CLIENT_PLUGIN_AUTH) {
                    $this->authPluginName = DataTypes::decodeNullString(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
                }
            }
        }
        $this->sendHandshake();
    }
    /**
     * @see 14.2.5 Connection Phase Packets
     */
    private function handleAuthSwitch($packet)
    {
        $off = 1;
        $this->authPluginName = DataTypes::decodeNullString(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += \strlen($this->authPluginName) + 1;
        $this->authPluginData = \Phabel\Target\Php80\Polyfill::substr($packet, $off);
        $this->sendAuthSwitchResponse();
    }
    /**
     *
     */
    private function sendAuthSwitchResponse()
    {
        $this->write($this->getAuthData());
    }
    /**
     * @see 14.6.4.1.2 LOCAL INFILE Request
     */
    private function handleLocalInfileRequest(string $packet) : void
    {
        \Amp\asyncCall(function () use($packet) {
            try {
                $filePath = \Phabel\Target\Php80\Polyfill::substr($packet, 1);
                /** @var \Amp\File\File $fileHandle */
                if (\function_exists("Amp\\File\\openFile")) {
                    // amphp/file 2.x
                    $fileHandle = (yield File\openFile($filePath, 'r'));
                } elseif (\function_exists("Amp\\File\\open")) {
                    // amphp/file 1.x or 0.3.x
                    $fileHandle = (yield File\open($filePath, 'r'));
                } else {
                    throw new \Error("amphp/file must be installed for LOCAL INFILE queries");
                }
                while ("" != ($chunk = (yield $fileHandle->read()))) {
                    $this->sendPacket($chunk);
                }
                $this->sendPacket("");
            } catch (\Throwable $e) {
                $this->getDeferred()->fail(new ConnectionException("Failed to transfer a file to the server", 0, $e));
            }
        });
    }
    /**
     * @see 14.6.4.1.1 Text Resultset
     */
    private function handleQuery(string $packet) : void
    {
        switch (\ord($packet)) {
            case self::OK_PACKET:
                $this->parseOk($packet);
                if ($this->connInfo->statusFlags & StatusFlags::SERVER_MORE_RESULTS_EXISTS) {
                    $this->getDeferred()->resolve($result = new ResultProxy());
                    $this->result = $result;
                    $result->updateState(ResultProxy::COLUMNS_FETCHED);
                    $this->successfulResultsetFetch();
                } else {
                    $this->parseCallback = null;
                    $this->getDeferred()->resolve(new CommandResult($this->connInfo->affectedRows, $this->connInfo->insertId));
                    $this->ready();
                }
                return;
            case self::LOCAL_INFILE_REQUEST:
                if ($this->config->isLocalInfileEnabled()) {
                    $this->handleLocalInfileRequest($packet);
                } else {
                    $this->getDeferred()->fail(new ConnectionException("Unexpected LOCAL_INFILE_REQUEST packet"));
                }
                return;
            case self::ERR_PACKET:
                $this->handleError($packet);
                return;
        }
        $this->parseCallback = [$this, "handleTextColumnDefinition"];
        $this->getDeferred()->resolve($result = new ResultProxy());
        /* we need to resolve before assigning vars, so that a onResolve() handler won't have a partial result available */
        $this->result = $result;
        $result->setColumns(DataTypes::decodeUnsigned($packet));
    }
    /**
     * @see 14.7.1 Binary Protocol Resultset
     */
    private function handleExecute(string $packet) : void
    {
        $this->parseCallback = [$this, "handleBinaryColumnDefinition"];
        $this->getDeferred()->resolve($result = new ResultProxy());
        /* we need to resolve before assigning vars, so that a onResolve() handler won't have a partial result available */
        $this->result = $result;
        $result->setColumns(\ord($packet));
    }
    /**
     *
     */
    private function handleFieldList(string $packet) : void
    {
        if (\ord($packet) === self::ERR_PACKET) {
            $this->parseCallback = null;
            $this->handleError($packet);
        } elseif (\ord($packet) === self::EOF_PACKET) {
            $this->parseCallback = null;
            $this->parseEof($packet);
            $this->getDeferred()->resolve(null);
            $this->ready();
        } else {
            $this->addDeferred($deferred = new Deferred());
            $this->getDeferred()->resolve([$this->parseColumnDefinition($packet), $deferred]);
        }
    }
    /**
     *
     */
    private function handleTextColumnDefinition(string $packet) : void
    {
        $this->handleColumnDefinition($packet, "handleTextResultSetRow");
    }
    /**
     *
     */
    private function handleBinaryColumnDefinition(string $packet) : void
    {
        $this->handleColumnDefinition($packet, "handleBinaryResultSetRow");
    }
    /**
     *
     */
    private function handleColumnDefinition(string $packet, string $cbMethod) : void
    {
        if (!$this->result->columnsToFetch--) {
            $this->result->updateState(ResultProxy::COLUMNS_FETCHED);
            if (\ord($packet) === self::ERR_PACKET) {
                $this->parseCallback = null;
                $this->handleError($packet);
            } else {
                $cb = $this->parseCallback = [$this, $cbMethod];
                if ($this->capabilities & self::CLIENT_DEPRECATE_EOF) {
                    $cb($packet);
                } else {
                    $this->parseEof($packet);
                    // we don't need the EOF packet, skip!
                }
            }
            return;
        }
        $this->result->columns[] = $this->parseColumnDefinition($packet);
    }
    /**
     *
     */
    private function prepareParams(string $packet) : void
    {
        if (!$this->result->columnsToFetch--) {
            $this->result->columnsToFetch = $this->result->columnCount;
            if (!$this->result->columnsToFetch) {
                $this->prepareFields($packet);
            } else {
                $this->parseCallback = [$this, "prepareFields"];
            }
            return;
        }
        $this->result->params[] = $this->parseColumnDefinition($packet);
    }
    /**
     *
     */
    private function prepareFields(string $packet) : void
    {
        if (!$this->result->columnsToFetch--) {
            $this->parseCallback = null;
            $this->query = null;
            $result = $this->result;
            $this->result = null;
            $this->ready();
            $result->updateState(ResultProxy::COLUMNS_FETCHED);
            return;
        }
        $this->result->columns[] = $this->parseColumnDefinition($packet);
    }
    /**
     * @see 14.6.4.1.1.2 Column Defintion
     */
    private function parseColumnDefinition(string $packet) : array
    {
        $off = 0;
        $column = [];
        if ($this->capabilities & self::CLIENT_PROTOCOL_41) {
            $column["catalog"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["schema"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["table"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["original_table"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["name"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["original_name"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $fixlen = DataTypes::decodeUnsignedOff($packet, $off);
            $len = 0;
            $column["charset"] = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off + $len));
            $len += 2;
            $column["columnlen"] = DataTypes::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($packet, $off + $len));
            $len += 4;
            $column["type"] = \ord($packet[$off + $len]);
            $len += 1;
            $column["flags"] = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off + $len));
            $len += 2;
            $column["decimals"] = \ord($packet[$off + $len]);
            //$len += 1;
            $off += $fixlen;
        } else {
            $column["table"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["name"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $collen = DataTypes::decodeUnsignedOff($packet, $off);
            $column["columnlen"] = DataTypes::decodeIntByLen(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $collen);
            $off += $collen;
            $typelen = DataTypes::decodeUnsignedOff($packet, $off);
            $column["type"] = DataTypes::decodeIntByLen(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $typelen);
            $off += $typelen;
            $len = 1;
            $flaglen = $this->capabilities & self::CLIENT_LONG_FLAG ? DataTypes::decodeUnsigned(\Phabel\Target\Php80\Polyfill::substr($packet, $off, 9), $len) : \ord($packet[$off]);
            $off += $len;
            if ($flaglen > 2) {
                $len = 2;
                $column["flags"] = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off, 4));
            } else {
                $len = 1;
                $column["flags"] = \ord($packet[$off]);
            }
            $column["decimals"] = \ord($packet[$off + $len]);
            $off += $flaglen;
        }
        if ($off < \strlen($packet)) {
            $column["defaults"] = DataTypes::decodeString(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        }
        return $column;
    }
    /**
     *
     */
    private function successfulResultsetFetch() : void
    {
        $result = $this->result;
        $deferred =& $result->next;
        if (!$deferred) {
            $deferred = new Deferred();
        }
        if ($this->connInfo->statusFlags & StatusFlags::SERVER_MORE_RESULTS_EXISTS) {
            $this->parseCallback = [$this, "handleQuery"];
            $this->addDeferred($deferred);
        } else {
            $this->parseCallback = null;
            $this->query = null;
            $this->result = null;
            $deferred->resolve();
            $this->ready();
        }
        $result->updateState(ResultProxy::ROWS_FETCHED);
    }
    /**
     * @see 14.6.4.1.1.3 Resultset Row
     */
    private function handleTextResultSetRow(string $packet) : void
    {
        $packettype = \ord($packet);
        if ($packettype === self::EOF_PACKET) {
            if ($this->capabilities & self::CLIENT_DEPRECATE_EOF) {
                $this->parseOk($packet);
            } else {
                $this->parseEof($packet);
            }
            $this->successfulResultsetFetch();
            return;
        } elseif ($packettype === self::ERR_PACKET) {
            $this->handleError($packet);
            return;
        }
        $off = 0;
        $columns = $this->result->columns;
        $fields = [];
        for ($i = 0; $off < \strlen($packet); ++$i) {
            if (\ord($packet[$off]) === 0xfb) {
                $fields[] = null;
                $off += 1;
            } else {
                $fields[] = DataTypes::decodeStringOff($columns[$i]["type"], $packet, $off);
            }
        }
        $this->result->rowFetched($fields);
    }
    /**
     * @see 14.7.2 Binary Protocol Resultset Row
     */
    private function handleBinaryResultSetRow(string $packet) : void
    {
        $packettype = \ord($packet);
        if ($packettype === self::EOF_PACKET) {
            $this->parseEof($packet);
            $this->successfulResultsetFetch();
            return;
        } elseif ($packettype === self::ERR_PACKET) {
            $this->handleError($packet);
            return;
        }
        $off = 1;
        // skip first byte
        $columnCount = $this->result->columnCount;
        $columns = $this->result->columns;
        $fields = [];
        for ($i = 0; $i < $columnCount; $i++) {
            if (\ord($packet[$off + ($i + 2 >> 3)]) & 1 << ($i + 2) % 8) {
                $fields[$i] = null;
            }
        }
        $off += $columnCount + 9 >> 3;
        for ($i = 0; $off < \strlen($packet); $i++) {
            while (\array_key_exists($i, $fields)) {
                $i++;
            }
            $fields[$i] = DataTypes::decodeBinary($columns[$i]["type"], \Phabel\Target\Php80\Polyfill::substr($packet, $off), $len);
            $off += $len;
        }
        \ksort($fields);
        $this->result->rowFetched($fields);
    }
    /**
     * @see 14.7.4.1 COM_STMT_PREPARE Response
     */
    private function handlePrepare(string $packet) : void
    {
        switch (\ord($packet)) {
            case self::OK_PACKET:
                break;
            case self::ERR_PACKET:
                $this->handleError($packet);
                return;
            default:
                throw new ConnectionException("Unexpected value for first byte of COM_STMT_PREPARE Response");
        }
        $off = 1;
        $stmtId = DataTypes::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 4;
        $columns = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 2;
        $params = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 2;
        $off += 1;
        // filler
        $this->connInfo->warnings = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $this->result = new ResultProxy();
        $this->result->columnsToFetch = $params;
        $this->result->columnCount = $columns;
        $this->refcount++;
        $this->getDeferred()->resolve(new ConnectionStatement($this, $this->query, $stmtId, $this->named, $this->result));
        $this->named = [];
        if ($params) {
            $this->parseCallback = [$this, "prepareParams"];
        } else {
            $this->prepareParams($packet);
        }
    }
    /**
     *
     */
    private function readStatistics(string $packet) : void
    {
        $this->getDeferred()->resolve($packet);
        $this->parseCallback = null;
        $this->ready();
    }
    /**
     * @see 14.6.2 COM_QUIT
     */
    public function sendClose() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\x01");
            $this->connectionState = self::CLOSING;
        });
    }
    /**
     *
     */
    public function close() : void
    {
        if ($this->connectionState === self::CLOSING && $this->deferreds) {
            \array_pop($this->deferreds)->resolve();
        }
        $this->connectionState = self::CLOSED;
        if ($this->socket) {
            $this->socket->close();
            $this->socket = null;
        }
    }
    /**
     *
     */
    private function write(string $packet) : Promise
    {
        $packet = $this->compilePacket($packet);
        // @codeCoverageIgnoreStart
        \assert((function () use($packet) {
            if (\defined("MYSQL_DEBUG")) {
                \fwrite(STDERR, "out: ");
                for ($i = 0; $i < \min(\strlen($packet), 200); $i++) {
                    \fwrite(STDERR, \dechex(\ord($packet[$i])) . " ");
                }
                $r = \range("\x00", "\x1f");
                unset($r[10], $r[9]);
                \fwrite(STDERR, "len: " . \strlen($packet) . "\n");
                \fwrite(STDERR, \str_replace($r, ".", \Phabel\Target\Php80\Polyfill::substr($packet, 0, 200)) . "\n");
            }
            return true;
        })());
        // @codeCoverageIgnoreEnd
        if ($this->capabilities & self::CLIENT_COMPRESS && $this->connectionState >= self::READY) {
            $packet = $this->compressPacket($packet);
        }
        return $this->pendingWrite = $this->socket->write($packet);
    }
    /**
     *
     */
    private function resetIds() : void
    {
        if ($this->pendingWrite) {
            $this->pendingWrite->onResolve(function () {
                $this->seqId = $this->compressionId = -1;
            });
            return;
        }
        $this->seqId = $this->compressionId = -1;
    }
    /**
     *
     */
    private function compilePacket(string $pending) : string
    {
        $packet = "";
        do {
            $len = \strlen($pending);
            if ($len >= (1 << 24) - 1) {
                $out = \Phabel\Target\Php80\Polyfill::substr($pending, 0, (1 << 24) - 1);
                $pending = \Phabel\Target\Php80\Polyfill::substr($pending, (1 << 24) - 1);
                $len = (1 << 24) - 1;
            } else {
                $out = $pending;
                $pending = "";
            }
            $packet .= \Phabel\Target\Php80\Polyfill::substr_replace(\pack("V", $len), \chr(++$this->seqId), 3, 1) . $out;
            // expects $len < (1 << 24) - 1
        } while ($pending !== "");
        return $packet;
    }
    /**
     *
     */
    private function compressPacket(string $packet) : string
    {
        if ($packet === "") {
            return "";
        }
        $len = \strlen($packet);
        $deflated = \zlib_encode($packet, ZLIB_ENCODING_DEFLATE);
        if ($len < \strlen($deflated)) {
            return \Phabel\Target\Php80\Polyfill::substr_replace(\pack("V", \strlen($packet)), \chr(++$this->compressionId), 3, 1) . "\x00\x00\x00" . $packet;
        }
        return \Phabel\Target\Php80\Polyfill::substr_replace(\pack("V", \strlen($deflated)), \chr(++$this->compressionId), 3, 1) . \Phabel\Target\Php80\Polyfill::substr(\pack("V", $len), 0, 3) . $deflated;
    }
    /**
     * @see 14.4 Compression
     */
    private function parseCompression() : \Generator
    {
        $inflated = "";
        $buf = "";
        while (true) {
            while (\strlen($buf) < 7) {
                $buf .= (yield $inflated);
                $inflated = "";
            }
            $size = DataTypes::decodeUnsigned24($buf);
            $this->compressionId = \ord($buf[3]);
            $uncompressed = DataTypes::decodeUnsigned24(\Phabel\Target\Php80\Polyfill::substr($buf, 4, 3));
            $buf = \Phabel\Target\Php80\Polyfill::substr($buf, 7);
            if ($size > 0) {
                while (\strlen($buf) < $size) {
                    $buf .= (yield $inflated);
                    $inflated = "";
                }
                if ($uncompressed === 0) {
                    $inflated .= \Phabel\Target\Php80\Polyfill::substr($buf, 0, $size);
                } else {
                    $inflated .= \zlib_decode(\Phabel\Target\Php80\Polyfill::substr($buf, 0, $size), $uncompressed);
                }
                $buf = \Phabel\Target\Php80\Polyfill::substr($buf, $size);
            }
        }
    }
    /**
     * @see 14.1.2 MySQL Packet
     * @see 14.1.3 Generic Response Packets
     */
    private function parseMysql() : \Generator
    {
        $buf = "";
        $parsed = [];
        while (true) {
            $packet = "";
            do {
                while (\strlen($buf) < 4) {
                    $buf .= (yield $parsed);
                    $parsed = [];
                }
                $len = DataTypes::decodeUnsigned24($buf);
                $this->seqId = \ord($buf[3]);
                $buf = \Phabel\Target\Php80\Polyfill::substr($buf, 4);
                while (\strlen($buf) < ($len & 0xffffff)) {
                    $buf .= (yield $parsed);
                    $parsed = [];
                }
                $lastIn = $len !== 0xffffff;
                if ($lastIn) {
                    $size = $len % 0xffffff;
                } else {
                    $size = 0xffffff;
                }
                $packet .= \Phabel\Target\Php80\Polyfill::substr($buf, 0, $size);
                $buf = \Phabel\Target\Php80\Polyfill::substr($buf, $size);
            } while (!$lastIn);
            if (\strlen($packet) > 0) {
                $parsed[] = $packet;
            }
        }
    }
    /**
     *
     */
    private function parsePayload(string $packet) : void
    {
        if ($this->connectionState === self::UNCONNECTED) {
            $this->established();
            $this->connectionState = self::ESTABLISHED;
            $this->handleHandshake($packet);
            return;
        }
        if ($this->connectionState === self::ESTABLISHED) {
            switch (\ord($packet)) {
                case self::OK_PACKET:
                    if ($this->capabilities & self::CLIENT_COMPRESS) {
                        $this->processors = \array_merge([$this->parseCompression()], $this->processors);
                    }
                    $this->connectionState = self::READY;
                    $this->handleOk($packet);
                    break;
                case self::ERR_PACKET:
                    $this->handleError($packet);
                    break;
                case self::AUTH_SWITCH_PACKET:
                    $this->handleAuthSwitch($packet);
                    break;
                case self::EXTRA_AUTH_PACKET:
                    /** @see 14.2.5 Connection Phase Packets (AuthMoreData) */
                    switch ($this->authPluginName) {
                        case "sha256_password":
                            $key = \Phabel\Target\Php80\Polyfill::substr($packet, 1);
                            $this->config = $this->config->withKey($key);
                            $this->sendHandshake();
                            break;
                        case "caching_sha2_password":
                            switch (\ord(\Phabel\Target\Php80\Polyfill::substr($packet, 1, 1))) {
                                case 3:
                                    // success
                                    return;
                                // expecting OK afterwards
                                case 4:
                                    // fast auth failure
                                    if ($this->capabilities & self::CLIENT_SSL || $this->config->getHost()[0] === "/") {
                                        $this->write($this->config->getPassword() . "\x00");
                                    } else {
                                        $this->write("\x02");
                                    }
                                    break;
                                case 0x2d:
                                    // certificate
                                    $pubkey = \Phabel\Target\Php80\Polyfill::substr($packet, 1);
                                    $this->write($this->sha256Auth($this->config->getPassword(), $this->authPluginData, $pubkey));
                                    break;
                            }
                            break;
                        default:
                            throw new ConnectionException("Unexpected EXTRA_AUTH_PACKET in authentication phase for method {$this->authPluginName}");
                    }
                    break;
            }
            return;
        }
        if ($this->parseCallback) {
            ($this->parseCallback)($packet);
            return;
        }
        $cb = $this->packetCallback;
        $this->packetCallback = null;
        switch (\ord($packet)) {
            case self::OK_PACKET:
                $this->handleOk($packet);
                break;
            case self::ERR_PACKET:
                $this->handleError($packet);
                break;
            case self::EOF_PACKET:
                if (\strlen($packet) < 6) {
                    $this->handleEof($packet);
                    break;
                }
            // no break
            default:
                if (!$cb) {
                    throw new ConnectionException("Unexpected packet type: " . \ord($packet));
                }
                $cb($packet);
        }
    }
    /**
     *
     */
    private function secureAuth(string $pass, string $scramble) : string
    {
        $hash = \sha1($pass, 1);
        return $hash ^ \sha1(\Phabel\Target\Php80\Polyfill::substr($scramble, 0, 20) . \sha1($hash, 1), 1);
    }
    /**
     *
     */
    private function sha256Auth(string $pass, string $scramble, string $key) : string
    {
        \openssl_public_encrypt("{$pass}\x00" ^ \str_repeat($scramble, \ceil(\strlen($pass) / \strlen($scramble))), $auth, $key, OPENSSL_PKCS1_OAEP_PADDING);
        return $auth;
    }
    /**
     *
     */
    private function sha2Auth(string $pass, string $scramble) : string
    {
        $hash = \hash("sha256", $pass, true);
        return $hash ^ \hash("sha256", \Phabel\Target\Php80\Polyfill::substr($scramble, 0, 20) . \hash("sha256", $hash, true), true);
    }
    /**
     *
     */
    private function authSwitchRequest(string $packet) : void
    {
        $this->parseCallback = null;
        switch (\ord($packet)) {
            case self::EOF_PACKET:
                if (\strlen($packet) === 1) {
                    break;
                }
                $len = \strpos($packet, "\x00");
                $pluginName = \Phabel\Target\Php80\Polyfill::substr($packet, 0, $len);
                // @TODO mysql_native_pass only now...
                $authPluginData = \Phabel\Target\Php80\Polyfill::substr($packet, $len + 1);
                $this->sendPacket($this->secureAuth($this->config->getPassword(), $authPluginData));
                break;
            case self::ERR_PACKET:
                $this->handleError($packet);
                return;
            default:
                throw new ConnectionException("AuthSwitchRequest: Expecting 0xfe (or ERR_Packet), got 0x" . \dechex(\ord($packet)));
        }
    }
    /**
     * @see 14.2.5 Connection Phase Packets
     * @see 14.3 Authentication Method
     */
    private function sendHandshake(bool $inSSL = false) : void
    {
        if ($this->config->getDatabase() !== null) {
            $this->capabilities |= self::CLIENT_CONNECT_WITH_DB;
        }
        if ($this->config->getConnectContext()->getTlsContext() !== null) {
            $this->capabilities |= self::CLIENT_SSL;
        }
        $this->capabilities &= $this->serverCapabilities;
        $payload = "";
        $payload .= \pack("V", $this->capabilities);
        $payload .= \pack("V", 1 << 24 - 1);
        // max-packet size
        $payload .= \chr(ConnectionConfig::BIN_CHARSET);
        $payload .= \str_repeat("\x00", 23);
        // reserved
        if (!$inSSL && $this->capabilities & self::CLIENT_SSL) {
            \Amp\asyncCall(function () use($payload) {
                try {
                    (yield $this->write($payload));
                    (yield $this->socket->setupTls());
                    $this->sendHandshake(true);
                } catch (\Throwable $e) {
                    $this->close();
                    $this->getDeferred()->fail($e);
                }
            });
            return;
        }
        $payload .= $this->config->getUser() . "\x00";
        $auth = $this->getAuthData();
        if ($this->capabilities & self::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) {
            $payload .= DataTypes::encodeInt(\strlen($auth));
            $payload .= $auth;
        } elseif ($this->capabilities & self::CLIENT_SECURE_CONNECTION) {
            $payload .= \chr(\strlen($auth));
            $payload .= $auth;
        } else {
            $payload .= "{$auth}\x00";
        }
        if ($this->capabilities & self::CLIENT_CONNECT_WITH_DB) {
            $payload .= "{$this->config->getDatabase()}\x00";
        }
        if ($this->capabilities & self::CLIENT_PLUGIN_AUTH) {
            $payload .= "{$this->authPluginName}\x00";
        }
        if ($this->capabilities & self::CLIENT_CONNECT_ATTRS) {
            // connection attributes?! 5.6.6+ only!
        }
        $this->write($payload);
    }
    /**
     *
     */
    private function getAuthData() : string
    {
        $password = (string) $this->config->getPassword();
        if ($password === "") {
            return "";
        }
        if ($this->capabilities & self::CLIENT_PLUGIN_AUTH) {
            switch ($this->authPluginName) {
                case "mysql_native_password":
                    return $this->secureAuth($password, $this->authPluginData);
                case "mysql_clear_password":
                    return $password;
                case "sha256_password":
                    $key = $this->config->getKey();
                    if ($key !== "") {
                        return $this->sha256Auth($password, $this->authPluginData, $key);
                    }
                    return "\x01";
                case "caching_sha2_password":
                    return $this->sha2Auth($password, $this->authPluginData);
                case "mysql_old_password":
                    throw new ConnectionException("mysql_old_password is outdated and insecure. Intentionally not implemented!");
                default:
                    throw new ConnectionException("Invalid (or unimplemented?) auth method requested by server: {$this->authPluginName}");
            }
        }
        return $this->secureAuth($password, $this->authPluginData);
    }
    /**
     * @see 14.1.2 MySQL Packet
     */
    protected function sendPacket(string $payload) : Promise
    {
        if ($this->connectionState !== self::READY) {
            throw new \Error("Connection not ready, cannot send any packets");
        }
        return $this->write($payload);
    }
}<?php

namespace Amp\Mysql\Internal;

use Amp\Struct;
final class ConnectionState
{
    use Struct;
    /** @var int|null */
    public $affectedRows;
    public $insertId;
    public $statusFlags;
    public $warnings;
    public $statusInfo;
    public $sessionState = [];
    public $errorMsg;
    public $errorCode;
    public $errorState;
    // begins with "#"
    /** @var string */
    public $serverVersion;
    /** @var string */
    public $charset;
}<?php

namespace Amp\Mysql\Internal;

use Amp\Sql\FailureException;
use Amp\Struct;
final class ResultProxy
{
    use Struct;
    public $columnCount;
    public $columns = [];
    public $params = [];
    public $columnsToFetch;
    public $rows = [];
    public $fetchedRows = 0;
    public $userFetched = 0;
    public $deferreds = [self::UNFETCHED => [], self::COLUMNS_FETCHED => [], self::ROWS_FETCHED => []];
    /** @var int */
    public $state = self::UNFETCHED;
    /** @var \Amp\Deferred|null */
    public $next;
    public const UNFETCHED = 0;
    public const COLUMNS_FETCHED = 1;
    public const ROWS_FETCHED = 2;
    public const SINGLE_ROW_FETCH = 255;
    /**
     *
     */
    public function setColumns(int $columns) : void
    {
        $this->columnCount = $this->columnsToFetch = $columns;
    }
    /**
     *
     */
    public function updateState(int $state) : void
    {
        $this->state = $state;
        if ($state === self::ROWS_FETCHED) {
            $this->rowFetched(null);
        }
        if (empty($this->deferreds[$state])) {
            return;
        }
        foreach ($this->deferreds[$state] as [$deferred, $rows, $cb]) {
            $deferred->resolve($cb ? $cb($rows) : $rows);
        }
        $this->deferreds[$state] = [];
    }
    /**
     *
     */
    public function rowFetched(?array $row) : void
    {
        if ($row !== null) {
            $this->rows[$this->fetchedRows++] = $row;
        }
        [$entry, , $cb] = \current($this->deferreds[self::UNFETCHED]);
        if ($entry !== null) {
            unset($this->deferreds[self::UNFETCHED][\key($this->deferreds[self::UNFETCHED])]);
            $entry->resolve($cb && $row ? $cb($row) : $row);
        }
    }
    /**
     *
     */
    public function fail(FailureException $e) : void
    {
        foreach ($this->deferreds as $state) {
            foreach ($this->deferreds[$state] as [$deferred]) {
                $deferred->fail($e);
            }
            $this->deferreds[$state] = [];
        }
    }
    /**
     * @return array
     *
     * @codeCoverageIgnore
     */
    public function __debugInfo() : array
    {
        $tmp = clone $this;
        foreach ($tmp->deferreds as &$type) {
            foreach ($type as &$entry) {
                unset($entry[0], $entry[2]);
            }
        }
        return (array) $tmp;
    }
}<?php

namespace Amp\Mysql;

use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\Common\StatementPool as SqlStatementPool;
use Amp\Sql\Connector;
use Amp\Sql\Pool as SqlPool;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
use Amp\Sql\Transaction as SqlTransaction;
final class Pool extends ConnectionPool
{
    /**
     *
     */
    protected function createDefaultConnector() : Connector
    {
        return connector();
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    protected function createStatement(SqlStatement $statement, callable $release) : SqlStatement
    {
        \assert($statement instanceof Statement);
        return new PooledStatement($statement, $release);
    }
    /**
     *
     */
    protected function createStatementPool(SqlPool $pool, SqlStatement $statement, callable $prepare) : SqlStatementPool
    {
        \assert($statement instanceof Statement);
        return new StatementPool($pool, $statement, $prepare);
    }
    /**
     *
     */
    protected function createTransaction(SqlTransaction $transaction, callable $release) : SqlTransaction
    {
        return new PooledTransaction($transaction, $release);
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Common\StatementPool as SqlStatementPool;
use Amp\Sql\Pool;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
use Amp\Success;
use function Amp\call;
final class StatementPool extends SqlStatementPool implements Statement
{
    private $params = [];
    /**
     *
     */
    public function __construct(Pool $pool, Statement $statement, callable $prepare)
    {
        parent::__construct($pool, $statement, $prepare);
    }
    /**
     *
     */
    protected function prepare(SqlStatement $statement) : Promise
    {
        \assert($statement instanceof Statement);
        return call(function () use($statement) {
            (yield $statement->reset());
            foreach ($this->params as $paramId => $data) {
                $statement->bind($paramId, $data);
            }
            return $statement;
        });
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ConnectionResultSet || $resultSet instanceof PooledResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    public function bind($paramId, $data) : void
    {
        if (!\is_int($paramId) && !\is_string($paramId)) {
            throw new \TypeError("Invalid parameter ID type");
        }
        $this->params[$paramId] = $data;
    }
    /**
     *
     */
    public function reset() : Promise
    {
        $this->params = [];
        return new Success();
    }
    /**
     * @return Promise<array>
     */
    public function getFields() : Promise
    {
        return call(function () {
            $statement = (yield from $this->pop());
            \assert($statement instanceof Statement);
            $fields = (yield $statement->getFields());
            $this->push($statement);
            return $fields;
        });
    }
}<?php

namespace Amp\Mysql;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Socket;
use Amp\Sql\FailureException;
use Amp\Sql\Link;
use function Amp\call;
final class Connection implements Link
{
    public const REFRESH_GRANT = 0x1;
    public const REFRESH_LOG = 0x2;
    public const REFRESH_TABLES = 0x4;
    public const REFRESH_HOSTS = 0x8;
    public const REFRESH_STATUS = 0x10;
    public const REFRESH_THREADS = 0x20;
    public const REFRESH_SLAVE = 0x40;
    public const REFRESH_MASTER = 0x80;
    /** @var Internal\Processor */
    private $processor;
    /** @var Deferred|null */
    private $busy;
    /** @var callable Function used to release connection after a transaction has completed. */
    private $release;
    /**
     * @param ConnectionConfig $config
     * @param (CancellationToken | null) $token
     * @param (Socket\Connector | null) $connector
     *
     * @return Promise<self>
     */
    public static function connect(ConnectionConfig $config, ?CancellationToken $token = null, ?Socket\Connector $connector = null) : Promise
    {
        $token = $token ?? new NullCancellationToken();
        return call(function () use($config, $token, $connector) {
            $socket = (yield ($connector ?? Socket\connector())->connect($config->getConnectionString(), $config->getConnectContext(), $token));
            $processor = new Internal\Processor($socket, $config);
            (yield $processor->connect($token));
            return new self($processor);
        });
    }
    /**
     * @param Internal\Processor $processor
     */
    private function __construct(Internal\Processor $processor)
    {
        $this->processor = $processor;
        $this->release = function () {
            \assert($this->busy instanceof Deferred);
            $deferred = $this->busy;
            $this->busy = null;
            $deferred->resolve();
        };
    }
    /**
     * @return bool False if the connection has been closed.
     */
    public function isAlive() : bool
    {
        return $this->processor->isAlive();
    }
    /**
     * @return int Timestamp of the last time this connection was used.
     */
    public function getLastUsedAt() : int
    {
        return $this->processor->getLastUsedAt();
    }
    /**
     *
     */
    public function isReady() : bool
    {
        return $this->processor->isReady();
    }
    /**
     *
     */
    public function setCharset(string $charset, string $collate = "") : Promise
    {
        return $this->processor->setCharset($charset, $collate);
    }
    /**
     *
     */
    public function close()
    {
        $processor = $this->processor;
        // Send close command if connection is not already in a closed or closing state
        if ($processor->isAlive()) {
            $processor->sendClose()->onResolve(static function () use($processor) {
                $processor->close();
            });
        }
    }
    /**
     *
     */
    public function useDb(string $db) : Promise
    {
        return $this->processor->useDb($db);
    }
    /**
     * @param int $subcommand int one of the self::REFRESH_* constants
     *
     * @return Promise
     */
    public function refresh(int $subcommand) : Promise
    {
        return $this->processor->refresh($subcommand);
    }
    /**
     *
     */
    public function query(string $query) : Promise
    {
        return call(function () use($query) {
            while ($this->busy) {
                (yield $this->busy->promise());
            }
            $result = (yield $this->processor->query($query));
            if ($result instanceof Internal\ResultProxy) {
                return new ConnectionResultSet($result);
            }
            if ($result instanceof CommandResult) {
                return $result;
            }
            throw new FailureException("Unrecognized result type");
        });
    }
    /**
     *
     */
    public function beginTransaction(int $isolation = ConnectionTransaction::ISOLATION_COMMITTED) : Promise
    {
        return call(function () use($isolation) {
            switch ($isolation) {
                case ConnectionTransaction::ISOLATION_UNCOMMITTED:
                    (yield $this->query("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"));
                    break;
                case ConnectionTransaction::ISOLATION_COMMITTED:
                    (yield $this->query("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"));
                    break;
                case ConnectionTransaction::ISOLATION_REPEATABLE:
                    (yield $this->query("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"));
                    break;
                case ConnectionTransaction::ISOLATION_SERIALIZABLE:
                    (yield $this->query("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE"));
                    break;
                default:
                    throw new \Error("Invalid transaction type");
            }
            (yield $this->query("START TRANSACTION"));
            $this->busy = new Deferred();
            return new ConnectionTransaction($this->processor, $this->release, $isolation);
        });
    }
    /**
     *
     */
    public function ping() : Promise
    {
        return $this->processor->ping();
    }
    /**
     *
     */
    public function prepare(string $query) : Promise
    {
        return call(function () use($query) {
            while ($this->busy) {
                (yield $this->busy->promise());
            }
            return $this->processor->prepare($query);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        return call(function () use($sql, $params) {
            /** @var Statement $statment */
            $statment = (yield $this->prepare($sql));
            return (yield $statment->execute($params));
        });
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->processor->unreference();
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\ResultSet as SqlResultSet;
interface ResultSet extends SqlResultSet
{
    /**
    * @return Promise<bool> Resolves with true if another result set exists, false if all result sets have
    been consumed.
    */
    public function nextResultSet() : Promise;
    /**
     * @return Promise<mixed[][]>
     *
     * @throws \Error If nextResultSet() has been invoked and no further result sets were available.
     */
    public function getFields() : Promise;
}<?php

namespace Amp\Mysql;

use Amp\Loop;
use Amp\Promise;
use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
use Amp\Sql\Connector;
const LOOP_CONNECTOR_IDENTIFIER = Connector::class . "\\Mysql";
/**
 *
 */
function connector(?Connector $connector = null) : Connector
{
    if ($connector === null) {
        $connector = Loop::getState(LOOP_CONNECTOR_IDENTIFIER);
        if ($connector) {
            return $connector;
        }
        $connector = new CancellableConnector();
    }
    Loop::setState(LOOP_CONNECTOR_IDENTIFIER, $connector);
    return $connector;
}
/**
 * Create a connection using the global Connector instance.
 *
 * @param SqlConnectionConfig $config
 *
 * @return Promise<Connection>
 *
 * @throws \Amp\Sql\FailureException If connecting fails.
 * @throws \Error If the connection string does not contain a host, user, and password.
 */
function connect(SqlConnectionConfig $config) : Promise
{
    return connector()->connect($config);
}
/**
 * Create a pool using the global Connector instance.
 *
 * @param SqlConnectionConfig $config
 * @param int $maxConnections
 * @param int $idleTimeout
 *
 * @return Pool
 *
 * @throws \Error If the connection string does not contain a host, user, and password.
 */
function pool(SqlConnectionConfig $config, int $maxConnections = ConnectionPool::DEFAULT_MAX_CONNECTIONS, int $idleTimeout = ConnectionPool::DEFAULT_IDLE_TIMEOUT) : Pool
{
    return new Pool($config, $maxConnections, $idleTimeout, connector());
}<?php

namespace Amp\Mysql;

use Amp\Sql\Common\PooledTransaction as SqlPooledTransaction;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
final class PooledTransaction extends SqlPooledTransaction
{
    /**
     *
     */
    protected function createStatement(SqlStatement $statement, callable $release) : SqlStatement
    {
        \assert($statement instanceof Statement);
        return new PooledStatement($statement, $release);
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
}<?php

namespace Amp\Mysql;

use Amp\Deferred;
use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use Amp\Success;
use function Amp\asyncCall;
use function Amp\call;
final class ConnectionResultSet implements ResultSet
{
    /** @var Internal\ResultProxy|null */
    private $result;
    /** @var \Amp\Producer */
    private $producer;
    /** @var array|object Last emitted row. */
    private $currentRow;
    /** @var string[]|null */
    private $columnNames;
    /**
     *
     */
    public function __construct(Internal\ResultProxy $result)
    {
        $this->result = $result;
        $this->producer = self::makeIterator($result);
    }
    /**
     *
     */
    private static function makeIterator(Internal\ResultProxy $result) : Iterator
    {
        return new Producer(static function (callable $emit) use($result) {
            $row = (yield self::fetchRow($result));
            while ($row !== null) {
                $next = self::fetchRow($result);
                // Fetch next row while emitting last row.
                (yield $emit($row));
                $row = (yield $next);
            }
        });
    }
    /**
     *
     */
    public function __destruct()
    {
        if (!$this->result) {
            return;
        }
        $producer = $this->producer;
        asyncCall(static function () use($producer) {
            try {
                while ((yield $producer->advance())) {
                }
            } catch (\Throwable $exception) {
                // Ignore iterator failure when destroying.
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        $this->currentRow = null;
        return $this->producer->advance();
    }
    /**
     * {@inheritdoc}
     */
    public function getCurrent() : array
    {
        if ($this->currentRow !== null) {
            return $this->currentRow;
        }
        if (!$this->columnNames) {
            $this->columnNames = \array_column($this->result->columns, "name");
        }
        return $this->currentRow = \array_combine($this->columnNames, $this->producer->getCurrent());
    }
    /**
     *
     */
    private static function fetchRow(Internal\ResultProxy $result) : Promise
    {
        if ($result->userFetched < $result->fetchedRows) {
            $row = $result->rows[$result->userFetched];
            unset($result->rows[$result->userFetched]);
            $result->userFetched++;
            return new Success($row);
        }
        if ($result->state === Internal\ResultProxy::ROWS_FETCHED) {
            return new Success();
        }
        $deferred = new Deferred();
        /* We need to increment the internal counter, else the next time fetch is called,
         * it'll simply return the row we fetch here instead of fetching a new row
         * since callback order on promises isn't defined, we can't do this via onResolve() */
        $incRow = function ($row) use($result) {
            unset($result->rows[$result->userFetched++]);
            return $row;
        };
        $result->deferreds[Internal\ResultProxy::UNFETCHED][] = [$deferred, null, $incRow];
        return $deferred->promise();
    }
    /**
    * @return Promise<bool> Resolves with true if another result set exists, false if all result sets have
    been consumed.
    */
    public function nextResultSet() : Promise
    {
        if (!$this->result) {
            return new Success(false);
        }
        return call(function () {
            while ((yield $this->advance())) {
            }
            // Consume any values left in the current result.
            $this->columnNames = null;
            $deferred = $this->result->next ?: ($this->result->next = new Deferred());
            $this->result = (yield $deferred->promise());
            if ($this->result) {
                $this->producer = self::makeIterator($this->result);
                return true;
            }
            return false;
        });
    }
    /**
     * @return Promise<mixed[][]>
     *
     * @throws \Error If nextResultSet() has been invoked and no further result sets were available.
     */
    public function getFields() : Promise
    {
        if ($this->result === null) {
            throw new \Error("The current result set is empty; call this method before invoking ResultSet::nextResultSet()");
        }
        if ($this->result->state >= Internal\ResultProxy::COLUMNS_FETCHED) {
            return new Success($this->result->columns);
        }
        $deferred = new Deferred();
        $this->result->deferreds[Internal\ResultProxy::COLUMNS_FETCHED][] = [$deferred, &$this->result->columns, null];
        return $deferred->promise();
    }
}<?php

namespace Amp\Mysql;

use Amp\Sql\CommandResult as SqlCommandResult;
final class CommandResult implements SqlCommandResult
{
    /** @var int */
    private $affectedRows;
    /** @var int */
    private $lastInsertId;
    /**
     *
     */
    public function __construct(int $affectedRows, int $lastInsertId)
    {
        $this->affectedRows = $affectedRows;
        $this->lastInsertId = $lastInsertId;
    }
    /**
     * @return int Number of rows affected by the modification query.
     */
    public function getAffectedRowCount() : int
    {
        return $this->affectedRows;
    }
    /**
     * @return int Insert ID of the last auto increment row.
     */
    public function getLastInsertId() : int
    {
        return $this->lastInsertId;
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Statement as SqlStatement;
interface Statement extends SqlStatement
{
    /**
     * @param (int | string) $paramId Parameter ID or name.
     * @param mixed $data Data to bind to parameter.
     *
     * @throws \Error If $paramId is not an int or string, or the position does not exist.
     */
    public function bind($paramId, $data) : void;
    /**
     * @return Promise<array>
     */
    public function getFields() : Promise;
    /**
     * Reset statement to state just after preparing.
     *
     * @return Promise<null>
     */
    public function reset() : Promise;
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Common\PooledResultSet as SqlPooledResultSet;
final class PooledResultSet extends SqlPooledResultSet implements ResultSet
{
    /** @var ConnectionResultSet */
    private $result;
    /** @var callable */
    private $release;
    /** @var Promise|null a*/
    private $nextResultPromise;
    /**
     * @param ResultSet $result
     * @param callable $release
     */
    public function __construct(ResultSet $result, callable $release)
    {
        $this->result = $result;
        $this->release =& $release;
        parent::__construct($this->result, static function () use(&$release) {
            if ($release !== null) {
                $release();
            }
        });
    }
    /**
     *
     */
    public function advance() : Promise
    {
        $promise = $this->result->advance();
        $promise->onResolve(function (\Throwable $exception = null, bool $moreResults = null) {
            if ($moreResults || $this->release === null) {
                return;
            }
            $this->nextResultPromise = $this->result->nextResultSet();
            $this->nextResultPromise->onResolve(function (\Throwable $exception = null, bool $moreResults = null) {
                $this->nextResultPromise = null;
                if ($moreResults || $this->release === null) {
                    return;
                }
                $release = $this->release;
                $this->release = null;
                $release();
            });
        });
        return $promise;
    }
    /**
     *
     */
    public function nextResultSet() : Promise
    {
        if ($this->nextResultPromise !== null) {
            $nextResultPromise = $this->nextResultPromise;
            $this->nextResultPromise = null;
            return $nextResultPromise;
        }
        $promise = $this->result->nextResultSet();
        $promise->onResolve(function (\Throwable $exception = null, bool $moreResults = null) {
            if ($moreResults || $this->release === null) {
                return;
            }
            $release = $this->release;
            $this->release = null;
            $release();
        });
        return $promise;
    }
    /**
     *
     */
    public function getFields() : Promise
    {
        return $this->result->getFields();
    }
}<?php

namespace Amp\Mysql;

final class RefreshTypes
{
    const REFRESH_GRANT = 0x1;
    const REFRESH_LOG = 0x2;
    const REFRESH_TABLES = 0x4;
    const REFRESH_HOSTS = 0x8;
    const REFRESH_STATUS = 0x10;
    const REFRESH_THREADS = 0x20;
    const REFRESH_SLAVE = 0x40;
    const REFRESH_MASTER = 0x80;
}<?php

namespace Amp\Mysql\Bench;

class AbstractBench
{
    /** @var string */
    protected $host = '127.0.0.1';
    /** @var string */
    protected $user = 'root';
    /** @var string */
    protected $pass = '';
}<?php

namespace Amp\Mysql\Bench;

use Amp\Mysql\CancellableConnector;
use Amp\Mysql\Connection;
use Amp\Mysql\ConnectionConfig;
use Amp\Mysql\Pool as ConnectionPool;
use Amp\Mysql\ResultSet;
use function Amp\call;
use function Amp\Promise\wait;
/**
 * @BeforeMethods({"init"})
 * @AfterMethods({"onAfterMethods"})
 * @Iterations(1)
 * @Revs(100)
 * @Warmup(1)
 * @OutputTimeUnit("milliseconds", precision=5)
 */
class QueryBench extends AbstractBench
{
    /** @var  ConnectionPool */
    protected $connectionPool;
    /** @var  Connection */
    protected $connection;
    /** @var  \PDO */
    protected $pdoConnection;
    /** @var int */
    protected $maxQueries = 10;
    /** @var int */
    protected $poolLimit = 10;
    /**
     *
     */
    public function init()
    {
        $config = ConnectionConfig::fromString("host={$this->host};user={$this->user};pass={$this->pass}");
        $connector = new CancellableConnector();
        $this->connectionPool = new ConnectionPool($config, $this->poolLimit, 10, $connector);
        $connectionPromise = $connector->connect($config);
        $this->connection = wait($connectionPromise);
        $this->pdoConnection = new \PDO("mysql:host={$this->host};port=3306", $this->user, $this->pass);
    }
    /**
     *
     */
    public function onAfterMethods()
    {
        $this->connectionPool->close();
        $this->connection->close();
    }
    /**
     *
     */
    public function benchPdoQueries()
    {
        foreach (\range(1, $this->maxQueries) as $ii) {
            $resultSet = $this->pdoConnection->query("SELECT {$ii}");
            $resultSet->fetch(\PDO::FETCH_ASSOC);
        }
    }
    /**
     *
     */
    public function benchSyncQueries()
    {
        wait(call(function () {
            $connection = $this->connection;
            foreach (\range(1, $this->maxQueries) as $i) {
                /** @var ResultSet $resultSet */
                $resultSet = (yield $connection->query("SELECT {$i}"));
                (yield $resultSet->advance());
            }
        }));
    }
    /**
     *
     */
    public function benchAsyncQueries()
    {
        wait(call(function () {
            $connection = $this->connection;
            /** @var ResultSet[] $resultSets */
            $resultSets = (yield \array_map(function ($i) use($connection) {
                return $connection->query("SELECT {$i}");
            }, \range(1, $this->maxQueries)));
            (yield \array_map(function ($resultSet) {
                /** @var ResultSet $resultSet */
                return $resultSet->advance();
            }, $resultSets));
        }));
    }
    /**
     *
     */
    public function benchAsyncQueriesUsingPool()
    {
        wait(call(function () {
            $connection = $this->connectionPool;
            /** @var ResultSet[] $resultSets */
            $resultSets = (yield \array_map(function ($i) use($connection) {
                return $connection->query("SELECT {$i}");
            }, \range(1, $this->maxQueries)));
            (yield \array_map(function ($resultSet) {
                /** @var ResultSet $resultSet */
                return $resultSet->advance();
            }, $resultSets));
        }));
    }
}<?php

require 'support/bootstrap.php';
require 'support/generic-table.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /* create same table than in 3-generic-with-yield.php */
    yield from createGenericTable($db);
    $promises = [];
    $promises[] = $db->query("SELECT a * b FROM tmp");
    $promises[] = $db->execute("SELECT POW(a, ?) AS power FROM tmp", [2]);
    /**
     * @var Mysql\ResultSet $result1
     * @var Mysql\ResultSet $result2
     */
    list($result1, $result2) = (yield $promises);
    // Both queries execute simultaneously. Wait for both to finish here.
    print "Query 1 Results:" . PHP_EOL;
    while ((yield $result1->advance())) {
        \var_dump($result1->getCurrent());
    }
    print PHP_EOL . "Query 2 Results:" . PHP_EOL;
    while ((yield $result2->advance())) {
        \var_dump($result2->getCurrent());
    }
    (yield $db->query("DROP TABLE tmp"));
    $db->close();
});<?php

/* Create table and fill in a few rows for examples; for comments see 3-generic-with-yield.php */
/**
 *
 */
function createGenericTable(\Amp\Sql\Link $db) : Generator
{
    (yield $db->query("DROP TABLE IF EXISTS tmp"));
    (yield $db->query("CREATE TABLE tmp (a INT(10), b INT(10))"));
    $statement = (yield $db->prepare("INSERT INTO tmp (a, b) VALUES (?, ? * 2)"));
    $promises = [];
    foreach (\range(1, 5) as $num) {
        $promises[] = $statement->execute([$num, $num]);
    }
    return (yield $promises);
}<?php

require __DIR__ . '/../../vendor/autoload.php';
//define('MYSQL_DEBUG', true);
/*
 * This file is not in VCS - create it if you want to set
 * the DB credentials without having them commited to VCS.
 */
@(include_once __DIR__ . "/../../mysql-config.php");
if (!\defined('DB_HOST') || !\defined('DB_USER') || !\defined('DB_PASS') || !\defined('DB_NAME')) {
    print "We couldn't find a mysql-config.php." . PHP_EOL;
    ask_whether_config_should_be_created:
    print "Do you want to create a configuration to run the examples? (yes/no): ";
    $answer = \trim(\fgets(STDIN));
    if ($answer === "no") {
        print "Can't run any examples without valid database credentials." . PHP_EOL;
        exit(1);
    } elseif ($answer === "yes") {
        print "Database host: ";
        $host = \var_export(\trim(\fgets(STDIN)), true);
        print "Database user: ";
        $user = \var_export(\trim(\fgets(STDIN)), true);
        print "Database password: ";
        $pass = \var_export(\trim(\fgets(STDIN)), true);
        print "Database name: ";
        $name = \var_export(\trim(\fgets(STDIN)), true);
        $config = <<<CONFIG
<?php

const DB_HOST = {$host};
const DB_USER = {$user};
const DB_PASS = {$pass};
const DB_NAME = {$name};

CONFIG;
        \file_put_contents(__DIR__ . "/../../mysql-config.php", $config);
        require __DIR__ . "/../../mysql-config.php";
        print "Successfully created configuration, running example now." . PHP_EOL;
        print "You can find the config in " . \realpath(__DIR__ . "/../../mysql-config.php") . PHP_EOL;
        print \str_repeat("-", 80) . PHP_EOL;
    } else {
        goto ask_whether_config_should_be_created;
    }
}<?php

require 'support/bootstrap.php';
require 'support/generic-table.php';
use Amp\Mysql;
\Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /* create same table than in 3-generic-with-yield.php */
    yield from createGenericTable($db);
    /* multi statements are enabled by default, but generally stored procedures also might return multiple resultsets anyway */
    $result = (yield $db->query("SELECT a + b FROM tmp; SELECT a - b FROM tmp;"));
    $i = 0;
    /** @var Mysql\ResultSet $result */
    do {
        print PHP_EOL . "Query " . ++$i . " Results:" . PHP_EOL;
        while ((yield $result->advance())) {
            \var_dump($result->getCurrent());
        }
    } while ((yield $result->nextResultSet()));
    // Advances to the next result set.
    (yield $db->query("DROP TABLE tmp"));
    $db->close();
});<?php

require 'support/bootstrap.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /* Create table and insert a few rows */
    /* we need to wait until table is finished, so that we can insert. */
    (yield $db->query("CREATE TABLE IF NOT EXISTS tmp (a INT(10), b INT(10))"));
    print "Table successfully created." . PHP_EOL;
    /** @var Mysql\Statement $statement */
    $statement = (yield $db->prepare("INSERT INTO tmp (a, b) VALUES (?, ? * 2)"));
    $promises = [];
    foreach (\range(1, 5) as $num) {
        $promises[] = $statement->execute([$num, $num]);
    }
    /* wait until everything is inserted */
    (yield $promises);
    print "Insertion successful (if it wasn't, an exception would have been thrown by now)" . PHP_EOL;
    /** @var Mysql\ResultSet $result */
    $result = (yield $db->query("SELECT a, b FROM tmp"));
    while ((yield $result->advance())) {
        \var_dump($result->getCurrent());
    }
    (yield $db->query("DROP TABLE tmp"));
    $db->close();
});<?php

/*
 * Generic example for establishing a connection
 */
require 'support/bootstrap.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    /* If you want ssl, pass as second argument an array with ssl options (an empty options array is valid too); if null is passed, ssl is not enabled either */
    $config = Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME);
    /* use an alternative charset... Default is utf8mb4_general_ci */
    $config = $config->withCharset("latin1_general_ci");
    /** @var Mysql\Connection $db */
    $db = (yield Mysql\connect($config));
    echo "Character set changed\n";
    /* optional, as connection will automatically close when destructed. */
    $db->close();
});<?php

require 'support/bootstrap.php';
require 'support/generic-table.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /* create same table than in 3-generic-with-yield.php */
    yield from createGenericTable($db);
    /** @var \Amp\Sql\Transaction $transaction */
    $transaction = (yield $db->beginTransaction());
    (yield $transaction->execute("INSERT INTO tmp VALUES (?, ? * 2)", [6, 6]));
    /** @var Mysql\ResultSet $result */
    $result = (yield $transaction->execute("SELECT * FROM tmp WHERE a >= ?", [5]));
    // Two rows should be returned.
    while ((yield $result->advance())) {
        \var_dump($result->getCurrent());
    }
    (yield $transaction->rollback());
    // Run same query again, should only return a single row since the other was rolled back.
    $result = (yield $db->execute("SELECT * FROM tmp WHERE a >= ?", [5]));
    while ((yield $result->advance())) {
        \var_dump($result->getCurrent());
    }
    $db->close();
});<?php

require 'support/bootstrap.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /** @var Mysql\ResultSet $result */
    $result = (yield $db->query("SELECT 1 AS value"));
    while ((yield $result->advance())) {
        $row = $result->getCurrent();
        \var_dump($row['value']);
    }
    $db->close();
});{
    "bootstrap": "vendor/autoload.php",
    "path": "benchmarks",
    "php_binary": "php_no_xdebug"
}
{
    "name": "amphp/mysql",
    "description": "Asynchronous MySQL client for PHP based on Amp.",
    "license": "MIT",
    "authors": [
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/socket": "^1",
        "amphp/sql": "^1",
        "amphp/sql-common": "^1"
    },
    "require-dev": {
        "ext-openssl": "*",
        "amphp/process": "^1",
        "amphp/file": "^2 || ^1 || ^0.3.5",
        "phpunit/phpunit": "^9 || ^8 || ^7",
        "amphp/phpunit-util": "^1.1.2",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpbench/phpbench": "^0.13.0"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Mysql\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Mysql\\Test\\": "test",
            "Amp\\Mysql\\Bench\\": "benchmarks"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit"
    }
}
<?php

namespace Amp\File\Sync;

use Amp\Coroutine;
use Amp\Delayed;
use Amp\File\FilesystemException;
use Amp\Promise;
use Amp\Sync\Lock;
use Amp\Sync\Mutex;
use Amp\Sync\SyncException;
use function Amp\File\deleteFile;
use function Amp\File\openFile;
final class AsyncFileMutex implements Mutex
{
    private const LATENCY_TIMEOUT = 10;
    /** @var string The full path to the lock file. */
    private $fileName;
    /**
     * @param string $fileName Name of temporary file to use as a mutex.
     */
    public function __construct(string $fileName)
    {
        $this->fileName = $fileName;
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return new Coroutine($this->doAcquire());
    }
    /**
     * @coroutine
     *
     * @return \Generator
     */
    private function doAcquire() : \Generator
    {
        // Try to create the lock file. If the file already exists, someone else
        // has the lock, so set an asynchronous timer and try again.
        while (true) {
            try {
                $file = (yield openFile($this->fileName, 'x'));
                break;
            } catch (FilesystemException $exception) {
                (yield new Delayed(self::LATENCY_TIMEOUT));
            }
        }
        // Return a lock object that can be used to release the lock on the mutex.
        $lock = new Lock(0, function () : void {
            $this->release();
        });
        (yield $file->close());
        return $lock;
    }
    /**
     * Releases the lock on the mutex.
     */
    private function release() : void
    {
        deleteFile($this->fileName)->onResolve(function (?\Throwable $exception) : void {
            if ($exception !== null) {
                throw new SyncException('Failed to unlock the mutex file: ' . $this->fileName, 0, $exception);
            }
        });
    }
}<?php

namespace Amp\File;

use Amp\Promise;
interface Driver
{
    /**
     * Open a handle for the specified path.
     *
     * @param string $path
     * @param string $mode
     *
     * @return Promise<File>
     */
    public function openFile(string $path, string $mode) : Promise;
    /**
     * Get file status; also known as stat operation.
     *
     * If the requested path does not exist the resulting Promise will resolve to NULL.
     *
     * @param string $path The file system path to stat.
     *
     * @return Promise<(array | null)>
     */
    public function getStatus(string $path) : Promise;
    /**
     * Same as {@see Driver::getStatus()} except if the path is a link then the link's data is returned.
     *
     * If the requested path does not exist the resulting Promise will resolve to NULL.
     *
     * @param string $path The file system path to stat.
     *
     * @return Promise<(array | null)> A promise resolving to an associative array upon successful resolution.
     */
    public function getLinkStatus(string $path) : Promise;
    /**
     * Create a symlink $link pointing to the file/directory located at $target.
     *
     * @param string $target
     * @param string $link
     *
     * @return Promise<void>
     */
    public function createSymlink(string $target, string $link) : Promise;
    /**
     * Create a hard link $link pointing to the file/directory located at $target.
     *
     * @param string $target
     * @param string $link
     *
     * @return Promise<void>
     */
    public function createHardlink(string $target, string $link) : Promise;
    /**
     * Resolve the symlink at $path.
     *
     * @param string $target
     *
     * @return Promise<string>
     */
    public function resolveSymlink(string $target) : Promise;
    /**
     * Move / rename a file or directory.
     *
     * @param string $from
     * @param string $to
     *
     * @return Promise<void>
     */
    public function move(string $from, string $to) : Promise;
    /**
     * Delete a file.
     *
     * @param string $path
     *
     * @return Promise<void>
     */
    public function deleteFile(string $path) : Promise;
    /**
     * Create a directory.
     *
     * @param string $path
     * @param int $mode
     *
     * @return Promise<void>
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise;
    /**
     * Create a directory recursively.
     *
     * @param string $path
     * @param int $mode
     *
     * @return Promise<void>
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise;
    /**
     * Delete a directory.
     *
     * @param string $path
     *
     * @return Promise<void>
     */
    public function deleteDirectory(string $path) : Promise;
    /**
     * Retrieve an array of files and directories inside the specified path.
     *
     * Dot entries are not included in the resulting array (i.e. "." and "..").
     *
     * @param string $path
     *
     * @return Promise<list<string>>
     */
    public function listFiles(string $path) : Promise;
    /**
     * chmod a file or directory.
     *
     * @param string $path
     * @param int $mode
     *
     * @return Promise<void>
     */
    public function changePermissions(string $path, int $mode) : Promise;
    /**
     * chown a file or directory.
     *
     * @param string $path
     * @param (int | null) $uid
     * @param (int | null) $gid
     *
     * @return Promise<void>
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise;
    /**
    * Update the access and modification time of the specified path.
    *
    * If the file does not exist it will be created automatically.
    *
    * @param string $path
    * @param (int | null) $modificationTime The touch time. If $time is not supplied, the current system time is used.
    * @param (int | null) $accessTime The access time. If $atime is not supplied, value passed to the $time parameter is
    used.
    *
    * @return Promise<void>
    */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise;
    /**
     * Buffer the specified file's contents.
     *
     * @param string $path The file path from which to buffer contents.
     *
     * @return Promise<string> A promise resolving to a string upon successful resolution.
     */
    public function read(string $path) : Promise;
    /**
     * Write the contents string to the specified path.
     *
     * @param string $path The file path to which to $contents should be written.
     * @param string $contents The data to write to the specified $path.
     *
     * @return Promise<void>
     */
    public function write(string $path, string $contents) : Promise;
}<?php

namespace Amp\File\Internal;

use Amp\File\Driver\BlockingDriver;
use Amp\File\Driver\BlockingFile;
use Amp\File\FilesystemException;
use Amp\Parallel\Worker\Environment;
use Amp\Parallel\Worker\Task;
/**
 * @codeCoverageIgnore
 *
 * @internal
 */
final class FileTask implements Task
{
    private const ENV_PREFIX = "amphp/file#";
    /**
     *
     */
    private static function makeId(int $id) : string
    {
        return self::ENV_PREFIX . $id;
    }
    /** @var string */
    private $operation;
    /** @var mixed[] */
    private $args;
    /**  @var string|null */
    private $id;
    /**
     * @param string $operation
     * @param array $args
     * @param int $id File ID.
     *
     * @throws \Error
     */
    public function __construct(string $operation, array $args = [], int $id = null)
    {
        if ($operation === '') {
            throw new \Error('Operation must be a non-empty string');
        }
        $this->operation = $operation;
        $this->args = $args;
        $this->id = $id;
    }
    /**
     *
     */
    public function run(Environment $environment)
    {
        if ('f' === $this->operation[0]) {
            if ("fopen" === $this->operation) {
                $path = $this->args[0];
                $mode = \str_replace(['b', 't', 'e'], '', $this->args[1]);
                switch ($mode) {
                    case "r":
                    case "r+":
                    case "w":
                    case "w+":
                    case "a":
                    case "a+":
                    case "x":
                    case "x+":
                    case "c":
                    case "c+":
                        break;
                    default:
                        throw new \Error("Invalid file mode");
                }
                $handle = @\fopen($path, $mode . 'be');
                if (!$handle) {
                    $message = 'Could not open the file.';
                    if ($error = \error_get_last()) {
                        $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
                    }
                    throw new FilesystemException($message);
                }
                $file = new BlockingFile($handle, $path, $mode);
                $id = (int) $handle;
                $size = \fstat($handle)["size"];
                $environment->set(self::makeId($id), $file);
                return [$id, $size, $mode];
            }
            if ($this->id === null) {
                throw new FilesystemException("No file ID provided");
            }
            $id = self::makeId($this->id);
            if (!$environment->exists($id)) {
                throw new FilesystemException(\sprintf("No file handle with the ID %d has been opened on the worker", $this->id));
            }
            /** @var BlockingFile $file */
            if (!($file = $environment->get($id)) instanceof BlockingFile) {
                throw new FilesystemException("File storage found in inconsistent state");
            }
            switch ($this->operation) {
                case "fread":
                case "fwrite":
                case "fseek":
                case "ftruncate":
                    return [$file, \Phabel\Target\Php80\Polyfill::substr($this->operation, 1)](...$this->args);
                case "fclose":
                    $environment->delete($id);
                    $file->close();
                    return null;
                default:
                    throw new \Error('Invalid operation');
            }
        }
        switch ($this->operation) {
            case "getStatus":
            case "deleteFile":
            case "move":
            case "createHardlink":
            case "createSymlink":
            case "resolveSymlink":
            case "getLinkStatus":
            case "exists":
            case "createDirectory":
            case "createDirectoryRecursively":
            case "listFiles":
            case "deleteDirectory":
            case "changePermissions":
            case "changeOwner":
            case "touch":
            case "read":
            case "write":
                return [new BlockingDriver(), $this->operation](...$this->args);
            default:
                throw new \Error("Invalid operation");
        }
    }
}<?php

namespace Amp\File\Internal;

use Amp\Loop;
use Amp\Promise;
/** @internal */
final class EioPoll
{
    /** @var resource */
    private static $stream;
    /** @var string */
    private $watcher;
    /** @var int */
    private $requests = 0;
    /** @var Loop\Driver */
    private $driver;
    /**
     *
     */
    public function __construct(Loop\Driver $driver)
    {
        $this->driver = $driver;
        if (!self::$stream) {
            if (\function_exists('eio_init')) {
                \eio_init();
            }
            self::$stream = \eio_get_event_stream();
        }
        $this->watcher = $this->driver->onReadable(self::$stream, static function () : void {
            while (\eio_npending()) {
                \eio_poll();
            }
        });
        $this->driver->disable($this->watcher);
        $this->driver->setState(self::class, new class($this->watcher, $driver)
        {
            private $watcher;
            private $driver;
            /**
             *
             */
            public function __construct(string $watcher, Loop\Driver $driver)
            {
                $this->watcher = $watcher;
                $this->driver = $driver;
            }
            /**
             *
             */
            public function __destruct()
            {
                $this->driver->cancel($this->watcher);
                // Ensure there are no active operations anymore. This is a safe-guard as some operations might not be
                // finished on loop exit due to not being yielded. This also ensures a clean shutdown for these if PHP
                // exists.
                \eio_event_loop();
            }
        });
    }
    /**
     *
     */
    public function listen(Promise $promise) : void
    {
        if ($this->requests++ === 0) {
            $this->driver->enable($this->watcher);
        }
        $promise->onResolve(\Closure::fromCallable([$this, 'done']));
    }
    /**
     *
     */
    private function done() : void
    {
        if (--$this->requests === 0) {
            $this->driver->disable($this->watcher);
        }
        \assert($this->requests >= 0);
    }
}<?php

namespace Amp\File\Internal;

use Amp\Loop\UvDriver;
use Amp\Promise;
/** @internal */
final class UvPoll
{
    /** @var string */
    private $watcher;
    /** @var int */
    private $requests = 0;
    /** @var UvDriver */
    private $driver;
    /**
     *
     */
    public function __construct(UvDriver $driver)
    {
        $this->driver = $driver;
        $this->watcher = $this->driver->repeat(\PHP_INT_MAX / 2, static function () : void {
            // do nothing, it's a dummy watcher
        });
        $this->driver->disable($this->watcher);
        $this->driver->setState(self::class, new class($this->watcher, $driver)
        {
            private $watcher;
            private $driver;
            /**
             *
             */
            public function __construct(string $watcher, UvDriver $driver)
            {
                $this->watcher = $watcher;
                $this->driver = $driver;
            }
            /**
             *
             */
            public function __destruct()
            {
                $this->driver->cancel($this->watcher);
            }
        });
    }
    /**
     *
     */
    public function listen(Promise $promise) : void
    {
        if ($this->requests++ === 0) {
            $this->driver->enable($this->watcher);
        }
        $promise->onResolve(\Closure::fromCallable([$this, 'done']));
    }
    /**
     *
     */
    private function done() : void
    {
        if (--$this->requests === 0) {
            $this->driver->disable($this->watcher);
        }
        \assert($this->requests >= 0);
    }
}<?php

namespace Amp\File\Internal;

use Amp\Loop;
use Amp\Struct;
/** @internal */
final class Cache
{
    /** @var object */
    private $sharedState;
    /** @var string */
    private $ttlWatcherId;
    /** @var int|null */
    private $maxSize;
    /**
    * @param int $gcInterval The frequency in milliseconds at which expired cache entries should be garbage
    collected.
    * @param (int | null) $maxSize The maximum size of cache array (number of elements).
    */
    public function __construct(int $gcInterval = 1000, int $maxSize = null)
    {
        // By using a shared state object we're able to use `__destruct()` for "normal" garbage collection of both this
        // instance and the loop's watcher. Otherwise this object could only be GC'd when the TTL watcher was cancelled
        // at the loop layer.
        $this->sharedState = $sharedState = new class
        {
            use Struct;
            /** @var string[] */
            public $cache = [];
            /** @var int[] */
            public $cacheTimeouts = [];
            /** @var bool */
            public $isSortNeeded = false;
            /**
             *
             */
            public function collectGarbage() : void
            {
                $now = \time();
                if ($this->isSortNeeded) {
                    \asort($this->cacheTimeouts);
                    $this->isSortNeeded = false;
                }
                foreach ($this->cacheTimeouts as $key => $expiry) {
                    if ($now <= $expiry) {
                        break;
                    }
                    unset($this->cache[$key], $this->cacheTimeouts[$key]);
                }
            }
        };
        $this->ttlWatcherId = Loop::repeat($gcInterval, [$sharedState, "collectGarbage"]);
        $this->maxSize = $maxSize;
        Loop::unreference($this->ttlWatcherId);
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->sharedState->cache = [];
        $this->sharedState->cacheTimeouts = [];
        Loop::cancel($this->ttlWatcherId);
    }
    /**
     *
     */
    public function get(string $key)
    {
        if (!isset($this->sharedState->cache[$key])) {
            return null;
        }
        if (isset($this->sharedState->cacheTimeouts[$key]) && \time() > $this->sharedState->cacheTimeouts[$key]) {
            unset($this->sharedState->cache[$key], $this->sharedState->cacheTimeouts[$key]);
            return null;
        }
        return $this->sharedState->cache[$key];
    }
    /**
     *
     */
    public function set(string $key, $value, int $ttl = null) : void
    {
        if ($ttl === null) {
            unset($this->sharedState->cacheTimeouts[$key]);
        } elseif ($ttl >= 0) {
            $expiry = \time() + $ttl;
            $this->sharedState->cacheTimeouts[$key] = $expiry;
            $this->sharedState->isSortNeeded = true;
        } else {
            throw new \Error("Invalid cache TTL ({$ttl}; integer >= 0 or null required");
        }
        unset($this->sharedState->cache[$key]);
        if (\count($this->sharedState->cache) === $this->maxSize) {
            \array_shift($this->sharedState->cache);
        }
        $this->sharedState->cache[$key] = $value;
    }
    /**
     *
     */
    public function delete(string $key) : bool
    {
        $exists = isset($this->sharedState->cache[$key]);
        unset($this->sharedState->cache[$key], $this->sharedState->cacheTimeouts[$key]);
        return $exists;
    }
}<?php

namespace Amp\File\Driver;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\StreamException;
use Amp\Failure;
use Amp\File\File;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class BlockingFile implements File
{
    private $handle;
    private $path;
    private $mode;
    /**
     * @param resource $handle An open filesystem descriptor.
     * @param string $path File path.
     * @param string $mode File open mode.
     */
    public function __construct($handle, string $path, string $mode)
    {
        $this->handle = $handle;
        $this->path = $path;
        $this->mode = $mode;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->handle !== null) {
            @\fclose($this->handle);
        }
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        if ($this->handle === null) {
            return new Failure(new ClosedException("The file '{$this->path}' has been closed"));
        }
        try {
            \set_error_handler(function ($type, $message) {
                throw new StreamException("Failed reading from file '{$this->path}': {$message}");
            });
            $data = \fread($this->handle, $length);
            if ($data === false) {
                throw new StreamException("Failed reading from file '{$this->path}'");
            }
            return new Success($data !== '' ? $data : null);
        } catch (StreamException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->handle === null) {
            return new Failure(new ClosedException("The file '{$this->path}' has been closed"));
        }
        try {
            \set_error_handler(function ($type, $message) {
                throw new StreamException("Failed writing to file '{$this->path}': {$message}");
            });
            $length = \fwrite($this->handle, $data);
            if ($length === false) {
                throw new StreamException("Failed writing to file '{$this->path}'");
            }
            return new Success();
        } catch (StreamException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return call(function () use($data) {
            $promise = $this->write($data);
            // ignore any errors
            (yield Promise\any([$this->close()]));
            return $promise;
        });
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->handle === null) {
            return new Success();
        }
        $handle = $this->handle;
        $this->handle = null;
        try {
            \set_error_handler(function ($type, $message) {
                throw new StreamException("Failed closing file '{$this->path}': {$message}");
            });
            if (\fclose($handle)) {
                return new Success();
            }
            throw new StreamException("Failed closing file '{$this->path}'");
        } catch (StreamException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        if ($this->handle === null) {
            return new Failure(new ClosedException("The file '{$this->path}' has been closed"));
        }
        try {
            \set_error_handler(function ($type, $message) {
                throw new StreamException("Could not truncate file '{$this->path}': {$message}");
            });
            if (!\ftruncate($this->handle, $size)) {
                throw new StreamException("Could not truncate file '{$this->path}'");
            }
            return new Success();
        } catch (StreamException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function seek(int $position, int $whence = self::SEEK_SET) : Promise
    {
        if ($this->handle === null) {
            return new Failure(new ClosedException("The file '{$this->path}' has been closed"));
        }
        switch ($whence) {
            case self::SEEK_SET:
            case self::SEEK_CUR:
            case self::SEEK_END:
                try {
                    \set_error_handler(function ($type, $message) {
                        throw new StreamException("Could not seek in file '{$this->path}': {$message}");
                    });
                    if (\fseek($this->handle, $position, $whence) === -1) {
                        throw new StreamException("Could not seek in file '{$this->path}'");
                    }
                    return new Success($this->tell());
                } catch (StreamException $e) {
                    return new Failure($e);
                } finally {
                    \restore_error_handler();
                }
            default:
                throw new \Error("Invalid whence parameter; SEEK_SET, SEEK_CUR or SEEK_END expected");
        }
    }
    /**
     *
     */
    public function tell() : int
    {
        if ($this->handle === null) {
            throw new ClosedException("The file '{$this->path}' has been closed");
        }
        return \ftell($this->handle);
    }
    /**
     *
     */
    public function eof() : bool
    {
        if ($this->handle === null) {
            throw new ClosedException("The file '{$this->path}' has been closed");
        }
        return \feof($this->handle);
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->mode;
    }
}<?php

namespace Amp\File\Driver;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\StreamException;
use Amp\Failure;
use Amp\File\File;
use Amp\File\Internal;
use Amp\File\PendingOperationError;
use Amp\Parallel\Worker\TaskException;
use Amp\Parallel\Worker\Worker;
use Amp\Parallel\Worker\WorkerException;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class ParallelFile implements File
{
    /** @var Worker */
    private $worker;
    /** @var int|null */
    private $id;
    /** @var string */
    private $path;
    /** @var int */
    private $position;
    /** @var int */
    private $size;
    /** @var string */
    private $mode;
    /** @var bool True if an operation is pending. */
    private $busy = false;
    /** @var int Number of pending write operations. */
    private $pendingWrites = 0;
    /** @var bool */
    private $writable = true;
    /** @var Promise|null */
    private $closing;
    /**
     * @param Worker $worker
     * @param int $id
     * @param string $path
     * @param int $size
     * @param string $mode
     */
    public function __construct(Worker $worker, int $id, string $path, int $size, string $mode)
    {
        $this->worker = $worker;
        $this->id = $id;
        $this->path = $path;
        $this->size = $size;
        $this->mode = $mode;
        $this->position = $this->mode[0] === 'a' ? $this->size : 0;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->id !== null) {
            $this->close();
        }
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->closing) {
            return $this->closing;
        }
        $this->writable = false;
        if ($this->worker->isRunning()) {
            $this->closing = $this->worker->enqueue(new Internal\FileTask('fclose', [], $this->id));
            $this->id = null;
        } else {
            $this->closing = new Success();
        }
        return $this->closing;
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        if ($this->id === null) {
            return new Failure(new ClosedException("The file has been closed"));
        }
        if ($this->busy) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        return call(function () use($size) {
            ++$this->pendingWrites;
            $this->busy = true;
            try {
                (yield $this->worker->enqueue(new Internal\FileTask('ftruncate', [$size], $this->id)));
            } catch (TaskException $exception) {
                throw new StreamException("Reading from the file failed", 0, $exception);
            } catch (WorkerException $exception) {
                throw new StreamException("Sending the task to the worker failed", 0, $exception);
            } finally {
                if (--$this->pendingWrites === 0) {
                    $this->busy = false;
                }
            }
        });
    }
    /**
     *
     */
    public function eof() : bool
    {
        return $this->pendingWrites === 0 && $this->size <= $this->position;
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        if ($this->id === null) {
            return new Failure(new ClosedException("The file has been closed"));
        }
        if ($this->busy) {
            throw new PendingOperationError();
        }
        return call(function () use($length) {
            $this->busy = true;
            try {
                $data = (yield $this->worker->enqueue(new Internal\FileTask('fread', [$length], $this->id)));
                if ($data !== null) {
                    $this->position += \strlen($data);
                }
            } catch (TaskException $exception) {
                throw new StreamException("Reading from the file failed", 0, $exception);
            } catch (WorkerException $exception) {
                throw new StreamException("Sending the task to the worker failed", 0, $exception);
            } finally {
                $this->busy = false;
            }
            return $data;
        });
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->id === null) {
            return new Failure(new ClosedException("The file has been closed"));
        }
        if ($this->busy && $this->pendingWrites === 0) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        return call(function () use($data) {
            ++$this->pendingWrites;
            $this->busy = true;
            try {
                (yield $this->worker->enqueue(new Internal\FileTask('fwrite', [$data], $this->id)));
                $this->position += \strlen($data);
            } catch (TaskException $exception) {
                throw new StreamException("Writing to the file failed", 0, $exception);
            } catch (WorkerException $exception) {
                throw new StreamException("Sending the task to the worker failed", 0, $exception);
            } finally {
                if (--$this->pendingWrites === 0) {
                    $this->busy = false;
                }
            }
        });
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return call(function () use($data) {
            $promise = $this->write($data);
            $this->writable = false;
            // ignore any errors
            (yield Promise\any([$this->close()]));
            return $promise;
        });
    }
    /**
     *
     */
    public function seek(int $offset, int $whence = SEEK_SET) : Promise
    {
        if ($this->id === null) {
            return new Failure(new ClosedException("The file has been closed"));
        }
        if ($this->busy) {
            throw new PendingOperationError();
        }
        return call(function () use($offset, $whence) {
            switch ($whence) {
                case self::SEEK_SET:
                case self::SEEK_CUR:
                case self::SEEK_END:
                    try {
                        $this->position = (yield $this->worker->enqueue(new Internal\FileTask('fseek', [$offset, $whence], $this->id)));
                        if ($this->position > $this->size) {
                            $this->size = $this->position;
                        }
                        return $this->position;
                    } catch (TaskException $exception) {
                        throw new StreamException('Seeking in the file failed.', 0, $exception);
                    } catch (WorkerException $exception) {
                        throw new StreamException("Sending the task to the worker failed", 0, $exception);
                    }
                default:
                    throw new \Error('Invalid whence value. Use SEEK_SET, SEEK_CUR, or SEEK_END.');
            }
        });
    }
    /**
     *
     */
    public function tell() : int
    {
        return $this->position;
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->mode;
    }
}<?php

namespace Amp\File\Driver;

use Amp\Deferred;
use Amp\File\Driver;
use Amp\File\FilesystemException;
use Amp\File\Internal;
use Amp\Loop;
use Amp\Promise;
final class EioDriver implements Driver
{
    /**
     * @return bool Determines if this driver can be used based on the environment.
     */
    public static function isSupported() : bool
    {
        return \extension_loaded('eio');
    }
    /** @var Internal\EioPoll */
    private $poll;
    /**
     *
     */
    public function __construct(Loop\Driver $driver)
    {
        $this->poll = new Internal\EioPoll($driver);
    }
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        $flags = \EIO_O_NONBLOCK | $this->parseMode($mode);
        if (\defined('\\EIO_O_FSYNC')) {
            $flags |= \EIO_O_FSYNC;
        }
        $chmod = $flags & \EIO_O_CREAT ? 0644 : 0;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $openArr = [$mode, $path, $deferred];
        \eio_open($path, $flags, $chmod, \EIO_PRI_DEFAULT, [$this, "onOpenHandle"], $openArr);
        return $deferred->promise();
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        $data = [$deferred, $path];
        \eio_stat($path, $priority, [$this, "onStat"], $data);
        return $deferred->promise();
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_lstat($path, $priority, [$this, "onLstat"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_symlink($target, $link, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_link($target, $link, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function resolveSymlink(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_readlink($path, $priority, [$this, "onReadlink"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_rename($from, $to, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        $data = [$deferred, $path];
        $result = \eio_unlink($path, $priority, [$this, "onUnlink"], $data);
        // For a non-existent file eio_unlink immediately returns true and the callback is never called.
        if ($result === true) {
            $deferred->fail(new FilesystemException('File does not exist.'));
        }
        return $deferred->promise();
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \eio_mkdir($path, $mode, \EIO_PRI_DEFAULT, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        $path = \str_replace("/", DIRECTORY_SEPARATOR, $path);
        $arrayPath = \explode(DIRECTORY_SEPARATOR, $path);
        $tmpPath = "";
        $callback = function () use(&$callback, &$arrayPath, &$tmpPath, $mode, $priority, $deferred) : void {
            $tmpPath .= DIRECTORY_SEPARATOR . \array_shift($arrayPath);
            if (empty($arrayPath)) {
                \eio_mkdir($tmpPath, $mode, $priority, [$this, "onGenericResult"], $deferred);
            } else {
                $this->isdir($tmpPath)->onResolve(function ($error, $result) use($callback, $tmpPath, $mode, $priority) {
                    if ($result) {
                        $callback();
                    } else {
                        \eio_mkdir($tmpPath, $mode, $priority, $callback);
                    }
                });
            }
        };
        $callback();
        return $deferred->promise();
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        $data = [$deferred, $path];
        \eio_rmdir($path, $priority, [$this, "onRmdir"], $data);
        return $deferred->promise();
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $flags = \EIO_READDIR_STAT_ORDER | \EIO_READDIR_DIRS_FIRST;
        $priority = \EIO_PRI_DEFAULT;
        \eio_readdir($path, $flags, $priority, [$this, "onScandir"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_chmod($path, $mode, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_chown($path, $uid ?? -1, $gid ?? -1, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        $modificationTime = $modificationTime ?? \time();
        $accessTime = $accessTime ?? $modificationTime;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_utime($path, $accessTime, $modificationTime, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        $flags = $flags = \EIO_O_RDONLY;
        $mode = 0;
        $priority = \EIO_PRI_DEFAULT;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \eio_open($path, $flags, $mode, $priority, [$this, "onGetOpen"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        $flags = \EIO_O_RDWR | \EIO_O_CREAT;
        $mode = \EIO_S_IRUSR | \EIO_S_IWUSR | \EIO_S_IXUSR;
        $priority = \EIO_PRI_DEFAULT;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $data = [$contents, $deferred];
        \eio_open($path, $flags, $mode, $priority, [$this, "onPutOpen"], $data);
        return $deferred->promise();
    }
    /**
     *
     */
    private function parseMode(string $mode) : int
    {
        $mode = \str_replace(['b', 't', 'e'], '', $mode);
        switch ($mode) {
            case 'r':
                return \EIO_O_RDONLY;
            case 'r+':
                return \EIO_O_RDWR;
            case 'w':
                return \EIO_O_WRONLY | \EIO_O_TRUNC | \EIO_O_CREAT;
            case 'w+':
                return \EIO_O_RDWR | \EIO_O_TRUNC | \EIO_O_CREAT;
            case 'a':
                return \EIO_O_WRONLY | \EIO_O_APPEND | \EIO_O_CREAT;
            case 'a+':
                return \EIO_O_RDWR | \EIO_O_APPEND | \EIO_O_CREAT;
            case 'x':
                return \EIO_O_WRONLY | \EIO_O_CREAT | \EIO_O_EXCL;
            case 'x+':
                return \EIO_O_RDWR | \EIO_O_CREAT | \EIO_O_EXCL;
            case 'c':
                return \EIO_O_WRONLY | \EIO_O_CREAT;
            case 'c+':
                return \EIO_O_RDWR | \EIO_O_CREAT;
            default:
                throw new \Error('Invalid file mode: ' . $mode);
        }
    }
    /**
     *
     */
    private function onOpenHandle(array $openArr, $result, $req) : void
    {
        [$mode, $path, $deferred] = $openArr;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } elseif ($mode[0] === "a") {
            \array_unshift($openArr, $result);
            \eio_ftruncate($result, $offset = 0, \EIO_PRI_DEFAULT, [$this, "onOpenFtruncate"], $openArr);
        } else {
            \array_unshift($openArr, $result);
            \eio_fstat($result, \EIO_PRI_DEFAULT, [$this, "onOpenFstat"], $openArr);
        }
    }
    /**
     *
     */
    private function onOpenFtruncate(array $openArr, $result, $req) : void
    {
        [$fh, $mode, $path, $deferred] = $openArr;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $handle = new EioFile($this->poll, $fh, $path, $mode, $size = 0);
            $deferred->resolve($handle);
        }
    }
    /**
     *
     */
    private function onOpenFstat(array $openArr, $result, $req) : void
    {
        [$fh, $mode, $path, $deferred] = $openArr;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $handle = new EioFile($this->poll, $fh, $path, $mode, $result["size"]);
            $deferred->resolve($handle);
        }
    }
    /**
     *
     */
    private function onStat(array $data, $result, $req) : void
    {
        [$deferred, $path] = $data;
        if ($result === -1) {
            $deferred->resolve(null);
        } else {
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onLstat(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->resolve(null);
        } else {
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onReadlink(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onGenericResult(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve();
        }
    }
    /**
     *
     */
    private function onUnlink(array $data, $result, $req) : void
    {
        [$deferred, $path] = $data;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve();
        }
    }
    /**
     *
     */
    private function isDir(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->getStatus($path)->onResolve(static function ($error, $result) use($deferred) : void {
            if ($result) {
                $deferred->resolve(($result["mode"] & 040000) === 040000);
            } else {
                $deferred->resolve(false);
            }
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function onRmdir(array $data, $result, $req) : void
    {
        [$deferred, $path] = $data;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve();
        }
    }
    /**
     *
     */
    private function onScandir(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $result = $result["names"];
            \sort($result);
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onGetOpen(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $priority = \EIO_PRI_DEFAULT;
            \eio_fstat($result, $priority, [$this, "onGetFstat"], [$result, $deferred]);
        }
    }
    /**
     *
     */
    private function onGetFstat(array $fhAndPromisor, $result, $req) : void
    {
        [$fh, $deferred] = $fhAndPromisor;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
            return;
        }
        $offset = 0;
        $length = $result["size"];
        $priority = \EIO_PRI_DEFAULT;
        \eio_read($fh, $length, $offset, $priority, [$this, "onGetRead"], $fhAndPromisor);
    }
    /**
     *
     */
    private function onGetRead(array $fhAndPromisor, $result, $req) : void
    {
        [$fh, $deferred] = $fhAndPromisor;
        \eio_close($fh);
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onPutOpen(array $data, $result, $req) : void
    {
        [$contents, $deferred] = $data;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $length = \strlen($contents);
            $offset = 0;
            $priority = \EIO_PRI_DEFAULT;
            $callback = [$this, "onPutWrite"];
            $fhAndPromisor = [$result, $deferred];
            \eio_write($result, $contents, $length, $offset, $priority, $callback, $fhAndPromisor);
        }
    }
    /**
     *
     */
    private function onPutWrite(array $fhAndPromisor, $result, $req) : void
    {
        [$fh, $deferred] = $fhAndPromisor;
        \eio_close($fh);
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve();
        }
    }
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\File\Driver;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Failure;
use Amp\File\File;
use Amp\File\Internal;
use Amp\File\PendingOperationError;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class UvFile implements File
{
    /** @var Internal\UvPoll */
    private $poll;
    /** @var \UVLoop */
    private $loop;
    /** @var resource */
    private $fh;
    /** @var string */
    private $path;
    /** @var string */
    private $mode;
    /** @var int */
    private $size;
    /** @var int */
    private $position;
    /** @var \SplQueue */
    private $queue;
    /** @var bool */
    private $isActive = false;
    /** @var bool */
    private $writable = true;
    /** @var Promise|null */
    private $closing;
    /** @var bool True if ext-uv version is < 0.3.0. */
    private $priorVersion;
    /**
     * @param \Amp\Loop\UvDriver $driver
     * @param Internal\UvPoll $poll Poll for keeping the loop active.
     * @param resource $fh File handle.
     * @param string $path
     * @param string $mode
     * @param int $size
     */
    public function __construct(Loop\UvDriver $driver, Internal\UvPoll $poll, $fh, string $path, string $mode, int $size)
    {
        $this->poll = $poll;
        $this->fh = $fh;
        $this->path = $path;
        $this->mode = $mode;
        $this->size = $size;
        $this->loop = $driver->getHandle();
        $this->position = $mode[0] === "a" ? $size : 0;
        $this->queue = new \SplQueue();
        $this->priorVersion = \version_compare(\phpversion('uv'), '0.3.0', '<');
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        if ($this->isActive) {
            throw new PendingOperationError();
        }
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $this->isActive = true;
        $onRead = function ($result, $buffer) use($deferred) : void {
            $this->isActive = false;
            if (\is_int($buffer)) {
                $error = \uv_strerror($buffer);
                if ($error === "bad file descriptor") {
                    $deferred->fail(new ClosedException("Reading from the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Reading from the file failed: " . $error));
                }
                return;
            }
            $length = \strlen($buffer);
            $this->position += $length;
            $deferred->resolve($length ? $buffer : null);
        };
        if ($this->priorVersion) {
            $onRead = static function ($fh, $result, $buffer) use($onRead) : void {
                if ($result < 0) {
                    $buffer = $result;
                    // php-uv v0.3.0 changed the callback to put an int in $buffer on error.
                }
                $onRead($result, $buffer);
            };
        }
        \uv_fs_read($this->loop, $this->fh, $this->position, $length, $onRead);
        return $deferred->promise();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->isActive && $this->queue->isEmpty()) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        $this->isActive = true;
        if ($this->queue->isEmpty()) {
            $promise = $this->push($data);
        } else {
            $promise = $this->queue->top();
            $promise = call(function () use($promise, $data) {
                (yield $promise);
                return (yield $this->push($data));
            });
        }
        $this->queue->push($promise);
        return $promise;
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return call(function () use($data) {
            $promise = $this->write($data);
            $this->writable = false;
            // ignore any errors
            (yield Promise\any([$this->close()]));
            return $promise;
        });
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        if ($this->isActive && $this->queue->isEmpty()) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        $this->isActive = true;
        if ($this->queue->isEmpty()) {
            $promise = $this->trim($size);
        } else {
            $promise = $this->queue->top();
            $promise = call(function () use($promise, $size) {
                (yield $promise);
                return (yield $this->trim($size));
            });
        }
        $this->queue->push($promise);
        return $promise;
    }
    /**
     *
     */
    public function seek(int $offset, int $whence = \SEEK_SET) : Promise
    {
        if ($this->isActive) {
            throw new PendingOperationError();
        }
        $offset = (int) $offset;
        switch ($whence) {
            case self::SEEK_SET:
                $this->position = $offset;
                break;
            case self::SEEK_CUR:
                $this->position += $offset;
                break;
            case self::SEEK_END:
                $this->position = $this->size + $offset;
                break;
            default:
                throw new \Error("Invalid whence parameter; SEEK_SET, SEEK_CUR or SEEK_END expected");
        }
        return new Success($this->position);
    }
    /**
     *
     */
    public function tell() : int
    {
        return $this->position;
    }
    /**
     *
     */
    public function eof() : bool
    {
        return !$this->queue->isEmpty() ? false : $this->size <= $this->position;
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->mode;
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->closing) {
            return $this->closing;
        }
        $deferred = new Deferred();
        $this->poll->listen($this->closing = $deferred->promise());
        \uv_fs_close($this->loop, $this->fh, static function () use($deferred) : void {
            // Ignore errors when closing file, as the handle will become invalid anyway.
            $deferred->resolve();
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function push(string $data) : Promise
    {
        $length = \strlen($data);
        if ($length === 0) {
            return new Success(0);
        }
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onWrite = function ($fh, $result) use($deferred, $length) : void {
            if ($this->queue->isEmpty()) {
                $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
            }
            $this->queue->shift();
            if ($this->queue->isEmpty()) {
                $this->isActive = false;
            }
            if ($result < 0) {
                $error = \uv_strerror($result);
                if ($error === "bad file descriptor") {
                    $deferred->fail(new ClosedException("Writing to the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Writing to the file failed: " . $error));
                }
            } else {
                $this->position += $length;
                if ($this->position > $this->size) {
                    $this->size = $this->position;
                }
                $deferred->resolve($length);
            }
        };
        \uv_fs_write($this->loop, $this->fh, $data, $this->position, $onWrite);
        return $deferred->promise();
    }
    /**
     *
     */
    private function trim(int $size) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onTruncate = function ($fh) use($deferred, $size) : void {
            if ($this->queue->isEmpty()) {
                $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
            }
            $this->queue->shift();
            if ($this->queue->isEmpty()) {
                $this->isActive = false;
            }
            $this->size = $size;
            $deferred->resolve();
        };
        \uv_fs_ftruncate($this->loop, $this->fh, $size, $onTruncate);
        return $deferred->promise();
    }
}<?php

namespace Amp\File\Driver;

use Amp\File\Driver;
use Amp\File\Internal\Cache;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class StatusCachingDriver implements Driver
{
    /** @var Driver */
    private $driver;
    /** @var Cache */
    private $statusCache;
    /**
     *
     */
    public function __construct(Driver $driver)
    {
        $this->driver = $driver;
        $this->statusCache = new Cache(1000, 1024);
    }
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        return call(function () use($path, $mode) {
            $file = (yield $this->driver->openFile($path, $mode));
            return new StatusCachingFile($file, function () use($path) {
                $this->invalidate([$path], new Success());
            });
        });
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        if ($cachedStat = $this->statusCache->get($path)) {
            return new Success($cachedStat);
        }
        return call(function () use($path) {
            $stat = (yield $this->driver->getStatus($path));
            if ($stat) {
                $this->statusCache->set($path, $stat, 1000);
            }
            return $stat;
        });
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        return $this->driver->getLinkStatus($path);
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        return $this->invalidate([$target, $link], $this->driver->createSymlink($target, $link));
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        return $this->invalidate([$target, $link], $this->driver->createHardlink($target, $link));
    }
    /**
     *
     */
    public function resolveSymlink(string $target) : Promise
    {
        return $this->driver->resolveSymlink($target);
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        return $this->invalidate([$from, $to], $this->driver->move($from, $to));
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        return $this->invalidate([$path], $this->driver->deleteFile($path));
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        return $this->invalidate([$path], $this->driver->createDirectory($path, $mode));
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        return $this->invalidate([$path], $this->driver->createDirectoryRecursively($path, $mode));
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        return $this->invalidate([$path], $this->driver->deleteDirectory($path));
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        return $this->driver->listFiles($path);
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        return $this->invalidate([$path], $this->driver->changePermissions($path, $mode));
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        return $this->invalidate([$path], $this->driver->changeOwner($path, $uid, $gid));
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        return $this->invalidate([$path], $this->driver->touch($path, $modificationTime, $accessTime));
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        return $this->driver->read($path);
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        return $this->invalidate([$path], $this->driver->write($path, $contents));
    }
    /**
     *
     */
    private function invalidate(array $paths, Promise $promise) : Promise
    {
        foreach ($paths as $path) {
            $this->statusCache->delete($path);
        }
        if (!$promise instanceof Success) {
            $promise->onResolve(function () use($paths) {
                foreach ($paths as $path) {
                    $this->statusCache->delete($path);
                }
            });
        }
        return $promise;
    }
}<?php

namespace Amp\File\Driver;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Failure;
use Amp\File\File;
use Amp\File\Internal;
use Amp\File\PendingOperationError;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class EioFile implements File
{
    /** @var Internal\EioPoll */
    private $poll;
    /** @var resource eio file handle. */
    private $fh;
    /** @var string */
    private $path;
    /** @var string */
    private $mode;
    /** @var int */
    private $size;
    /** @var int */
    private $position;
    /** @var \SplQueue */
    private $queue;
    /** @var bool */
    private $isActive = false;
    /** @var bool */
    private $writable = true;
    /** @var Promise|null */
    private $closing;
    /**
     *
     */
    public function __construct(Internal\EioPoll $poll, $fh, string $path, string $mode, int $size)
    {
        $this->poll = $poll;
        $this->fh = $fh;
        $this->path = $path;
        $this->mode = $mode;
        $this->size = $size;
        $this->position = $mode[0] === "a" ? $size : 0;
        $this->queue = new \SplQueue();
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        if ($this->isActive) {
            throw new PendingOperationError();
        }
        $this->isActive = true;
        $remaining = $this->size - $this->position;
        $length = $length > $remaining ? $remaining : $length;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onRead = function (Deferred $deferred, $result, $req) : void {
            $this->isActive = false;
            if ($result === -1) {
                $error = \eio_get_last_error($req);
                if ($error === "Bad file descriptor") {
                    $deferred->fail(new ClosedException("Reading from the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Reading from the file failed:" . $error));
                }
            } else {
                $this->position += \strlen($result);
                $deferred->resolve(\strlen($result) ? $result : null);
            }
        };
        \eio_read($this->fh, $length, $this->position, \EIO_PRI_DEFAULT, $onRead, $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->isActive && $this->queue->isEmpty()) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            throw new ClosedException("The file is no longer writable");
        }
        $this->isActive = true;
        if ($this->queue->isEmpty()) {
            $promise = $this->push($data);
        } else {
            $promise = $this->queue->top();
            $promise = call(function () use($promise, $data) {
                (yield $promise);
                return (yield $this->push($data));
            });
        }
        $this->queue->push($promise);
        return $promise;
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return call(function () use($data) {
            $promise = $this->write($data);
            $this->writable = false;
            // ignore any errors
            (yield Promise\any([$this->close()]));
            return $promise;
        });
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->closing) {
            return $this->closing;
        }
        $deferred = new Deferred();
        $this->poll->listen($this->closing = $deferred->promise());
        \eio_close($this->fh, \EIO_PRI_DEFAULT, static function (Deferred $deferred) : void {
            // Ignore errors when closing file, as the handle will become invalid anyway.
            $deferred->resolve();
        }, $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        if ($this->isActive && $this->queue->isEmpty()) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        $this->isActive = true;
        if ($this->queue->isEmpty()) {
            $promise = $this->trim($size);
        } else {
            $promise = $this->queue->top();
            $promise = call(function () use($promise, $size) {
                (yield $promise);
                return (yield $this->trim($size));
            });
        }
        $this->queue->push($promise);
        return $promise;
    }
    /**
     *
     */
    public function seek(int $offset, int $whence = \SEEK_SET) : Promise
    {
        if ($this->isActive) {
            throw new PendingOperationError();
        }
        switch ($whence) {
            case self::SEEK_SET:
                $this->position = $offset;
                break;
            case self::SEEK_CUR:
                $this->position += $offset;
                break;
            case self::SEEK_END:
                $this->position = $this->size + $offset;
                break;
            default:
                throw new \Error("Invalid whence parameter; SEEK_SET, SEEK_CUR or SEEK_END expected");
        }
        return new Success($this->position);
    }
    /**
     *
     */
    public function tell() : int
    {
        return $this->position;
    }
    /**
     *
     */
    public function eof() : bool
    {
        return !$this->queue->isEmpty() ? false : $this->size <= $this->position;
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->mode;
    }
    /**
     *
     */
    private function push(string $data) : Promise
    {
        $length = \strlen($data);
        if ($length === 0) {
            return new Success(0);
        }
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onWrite = function (Deferred $deferred, $result, $req) : void {
            if ($this->queue->isEmpty()) {
                $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
            }
            $this->queue->shift();
            if ($this->queue->isEmpty()) {
                $this->isActive = false;
            }
            if ($result === -1) {
                $error = \eio_get_last_error($req);
                if ($error === "Bad file descriptor") {
                    $deferred->fail(new ClosedException("Writing to the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Writing to the file failed: " . $error));
                }
            } else {
                $this->position += $result;
                if ($this->position > $this->size) {
                    $this->size = $this->position;
                }
                $deferred->resolve($result);
            }
        };
        \eio_write($this->fh, $data, $length, $this->position, \EIO_PRI_DEFAULT, $onWrite, $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    private function trim(int $size) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onTruncate = function (Deferred $deferred, $result, $req) use($size) : void {
            if ($this->queue->isEmpty()) {
                $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
            }
            $this->queue->shift();
            if ($this->queue->isEmpty()) {
                $this->isActive = false;
            }
            if ($result === -1) {
                $error = \eio_get_last_error($req);
                if ($error === "Bad file descriptor") {
                    $deferred->fail(new ClosedException("Truncating the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Truncating the file failed: " . $error));
                }
            } else {
                $this->size = $size;
                $deferred->resolve();
            }
        };
        \eio_ftruncate($this->fh, $size, \EIO_PRI_DEFAULT, $onTruncate, $deferred);
        return $deferred->promise();
    }
}<?php

namespace Amp\File\Driver;

use Amp\Coroutine;
use Amp\File\Driver;
use Amp\File\FilesystemException;
use Amp\File\Internal;
use Amp\Parallel\Worker;
use Amp\Parallel\Worker\Pool;
use Amp\Parallel\Worker\TaskException;
use Amp\Parallel\Worker\WorkerException;
use Amp\Promise;
use function Amp\call;
final class ParallelDriver implements Driver
{
    /** @var Pool */
    private $pool;
    /**
     * @param (Pool | null) $pool
     */
    public function __construct(Pool $pool = null)
    {
        $this->pool = $pool ?: Worker\pool();
    }
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        return call(function () use($path, $mode) {
            $worker = $this->pool->getWorker();
            try {
                [$id, $size, $mode] = (yield $worker->enqueue(new Internal\FileTask("fopen", [$path, $mode])));
            } catch (TaskException $exception) {
                throw new FilesystemException("Could not open file", $exception);
            } catch (WorkerException $exception) {
                throw new FilesystemException("Could not send open request to worker", $exception);
            }
            return new ParallelFile($worker, $id, $path, $size, $mode);
        });
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("deleteFile", [$path])));
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("getStatus", [$path])));
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("move", [$from, $to])));
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("createHardlink", [$target, $link])));
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("createSymlink", [$target, $link])));
    }
    /**
     *
     */
    public function resolveSymlink(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("resolveSymlink", [$path])));
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("createDirectory", [$path, $mode])));
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("createDirectoryRecursively", [$path, $mode])));
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("listFiles", [$path])));
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("deleteDirectory", [$path])));
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("changePermissions", [$path, $mode])));
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("changeOwner", [$path, $uid, $gid])));
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("getLinkStatus", [$path])));
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("touch", [$path, $modificationTime, $accessTime])));
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("read", [$path])));
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("write", [$path, $contents])));
    }
    /**
     *
     */
    private function runFileTask(Internal\FileTask $task) : \Generator
    {
        try {
            return (yield $this->pool->enqueue($task));
        } catch (TaskException $exception) {
            throw new FilesystemException("The file operation failed", $exception);
        } catch (WorkerException $exception) {
            throw new FilesystemException("Could not send the file task to worker", $exception);
        }
    }
}<?php

namespace Amp\File\Driver;

use Amp\Failure;
use Amp\File\Driver;
use Amp\File\FilesystemException;
use Amp\Promise;
use Amp\Success;
final class BlockingDriver implements Driver
{
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        $mode = \str_replace(['b', 't', 'e'], '', $mode);
        switch ($mode) {
            case "r":
            case "r+":
            case "w":
            case "w+":
            case "a":
            case "a+":
            case "x":
            case "x+":
            case "c":
            case "c+":
                break;
            default:
                throw new \Error("Invalid file mode: {$mode}");
        }
        try {
            \set_error_handler(static function ($type, $message) use($path, $mode) {
                throw new FilesystemException("Failed to open '{$path}' in mode '{$mode}': {$message}");
            });
            if (!($handle = \fopen($path, $mode . 'be'))) {
                throw new FilesystemException("Failed to open '{$path}' in mode '{$mode}'");
            }
            return new Success(new BlockingFile($handle, $path, $mode));
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        \clearstatcache(true, $path);
        return new Success(@\stat($path) ?: null);
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        \clearstatcache(true, $path);
        return new Success(@\lstat($path) ?: null);
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($target, $link) {
                throw new FilesystemException("Could not create symbolic link '{$link}' to '{$target}': {$message}");
            });
            if (!\symlink($target, $link)) {
                throw new FilesystemException("Could not create symbolic link '{$link}' to '{$target}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($target, $link) {
                throw new FilesystemException("Could not create hard link '{$link}' to '{$target}': {$message}");
            });
            if (!\link($target, $link)) {
                throw new FilesystemException("Could not create hard link '{$link}' to '{$target}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function resolveSymlink(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Could not resolve symbolic link '{$path}': {$message}");
            });
            if (false === ($result = \readlink($path))) {
                throw new FilesystemException("Could not resolve symbolic link '{$path}'");
            }
            return new Success($result);
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($from, $to) {
                throw new FilesystemException("Could not move file from '{$from}' to '{$to}': {$message}");
            });
            if (!\rename($from, $to)) {
                throw new FilesystemException("Could not move file from '{$from}' to '{$to}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Could not delete file '{$path}': {$message}");
            });
            if (!\unlink($path)) {
                throw new FilesystemException("Could not delete file '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Could not create directory '{$path}': {$message}");
            });
            /** @noinspection MkdirRaceConditionInspection */
            if (!\mkdir($path, $mode)) {
                throw new FilesystemException("Could not create directory '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                if (!\is_dir($path)) {
                    throw new FilesystemException("Could not create directory '{$path}': {$message}");
                }
            });
            if (\is_dir($path)) {
                return new Success();
            }
            /** @noinspection MkdirRaceConditionInspection */
            if (!\mkdir($path, $mode, true)) {
                if (\is_dir($path)) {
                    return new Success();
                }
                throw new FilesystemException("Could not create directory '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Could not remove directory '{$path}': {$message}");
            });
            if (!\rmdir($path)) {
                throw new FilesystemException("Could not remove directory '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to list files in '{$path}': {$message}");
            });
            if (!\is_dir($path)) {
                throw new FilesystemException("Failed to list files; '{$path}' is not a directory");
            }
            if ($arr = \scandir($path)) {
                \clearstatcache(true, $path);
                return new Success(\array_values(\array_filter($arr, static function ($el) {
                    return $el !== "." && $el !== "..";
                })));
            }
            throw new FilesystemException("Failed to list files in '{$path}'");
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to change permissions for '{$path}': {$message}");
            });
            if (!\chmod($path, $mode)) {
                throw new FilesystemException("Failed to change permissions for '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to change owner for '{$path}': {$message}");
            });
            if (($uid ?? -1) !== -1 && !\chown($path, $uid)) {
                throw new FilesystemException("Failed to change owner for '{$path}'");
            }
            if (($gid ?? -1) !== -1 && !\chgrp($path, $gid)) {
                throw new FilesystemException("Failed to change owner for '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to touch '{$path}': {$message}");
            });
            $modificationTime = $modificationTime ?? \time();
            $accessTime = $accessTime ?? $modificationTime;
            if (!\touch($path, $modificationTime, $accessTime)) {
                throw new FilesystemException("Failed to touch '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to read '{$path}': {$message}");
            });
            if (false === ($result = \file_get_contents($path))) {
                throw new FilesystemException("Failed to read '{$path}'");
            }
            return new Success($result);
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to read '{$path}': {$message}");
            });
            if (false === ($result = \file_put_contents($path, $contents))) {
                throw new FilesystemException("Failed to read '{$path}'");
            }
            return new Success($result);
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
}<?php

namespace Amp\File\Driver;

use Amp\File\File;
use Amp\Promise;
final class StatusCachingFile implements File
{
    /** @var File */
    private $file;
    /** @var callable */
    private $invalidateCallback;
    /**
     * @param File $file Decorated instance.
     * @param callable $invalidateCallback Invalidation callback.
     *
     * @internal
     */
    public function __construct(File $file, callable $invalidateCallback)
    {
        $this->file = $file;
        $this->invalidateCallback = $invalidateCallback;
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        return $this->file->read($length);
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        return $this->invalidate($this->file->write($data));
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return $this->invalidate($this->file->end($data));
    }
    /**
     *
     */
    public function close() : Promise
    {
        return $this->file->close();
    }
    /**
     *
     */
    public function seek(int $position, int $whence = self::SEEK_SET) : Promise
    {
        return $this->file->seek($position, $whence);
    }
    /**
     *
     */
    public function tell() : int
    {
        return $this->file->tell();
    }
    /**
     *
     */
    public function eof() : bool
    {
        return $this->file->eof();
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->file->getPath();
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->file->getMode();
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        return $this->invalidate($this->file->truncate($size));
    }
    /**
     *
     */
    private function invalidate(Promise $promise) : Promise
    {
        $promise->onResolve(function () {
            ($this->invalidateCallback)();
        });
        return $promise;
    }
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\File\Driver;

use Amp\Coroutine;
use Amp\Deferred;
use Amp\File\Driver;
use Amp\File\FilesystemException;
use Amp\File\Internal;
use Amp\Loop;
use Amp\Promise;
use Closure;
final class UvDriver implements Driver
{
    /**
     * @param Loop\Driver $driver The currently active loop driver.
     *
     * @return bool Determines if this driver can be used based on the environment.
     */
    public static function isSupported(Loop\Driver $driver) : bool
    {
        return $driver instanceof Loop\UvDriver;
    }
    /** @var Loop\UvDriver */
    private $driver;
    /** @var \UVLoop|resource Loop resource of type uv_loop or instance of \UVLoop. */
    private $loop;
    /** @var Internal\UvPoll */
    private $poll;
    /** @var bool True if ext-uv version is < 0.3.0. */
    private $priorVersion;
    /**
     *
     */
    public function __construct(Loop\UvDriver $driver)
    {
        $this->driver = $driver;
        $this->loop = $driver->getHandle();
        $this->poll = new Internal\UvPoll($driver);
        $this->priorVersion = \version_compare(\phpversion('uv'), '0.3.0', '<');
    }
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        $flags = $this->parseMode($mode);
        $chmod = $flags & \UV::O_CREAT ? 0644 : 0;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $openArr = [$mode, $path, $deferred];
        \uv_fs_open($this->loop, $path, $flags, $chmod, function ($fh) use($openArr) : void {
            if (\is_resource($fh)) {
                $this->onOpenHandle($fh, $openArr);
            } else {
                [, $path, $deferred] = $openArr;
                $deferred->fail(new FilesystemException("Failed opening file '{$path}'"));
            }
        });
        return $deferred->promise();
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = static function ($stat) use($deferred, $path) : void {
            if (\is_int($stat)) {
                $deferred->resolve(null);
                return;
            }
            // link is not a valid stat type but returned by the uv extension
            // change link to nlink
            if (isset($stat['link'])) {
                $stat['nlink'] = $stat['link'];
                unset($stat['link']);
            }
            $deferred->resolve($stat);
        };
        if ($this->priorVersion) {
            $callback = static function ($fh, $stat) use($callback) : void {
                if (empty($fh)) {
                    $stat = 0;
                }
                $callback($stat);
            };
        }
        \uv_fs_stat($this->loop, $path, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        if ($this->priorVersion) {
            $callback = static function ($fh, $stat) use($deferred) : void {
                $deferred->resolve(empty($fh) ? null : $stat);
            };
        } else {
            $callback = static function ($stat) use($deferred) : void {
                $deferred->resolve(\is_int($stat) ? null : $stat);
            };
        }
        \uv_fs_lstat($this->loop, $path, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = $this->createGenericCallback($deferred, "Could not create symbolic link");
        \uv_fs_symlink($this->loop, $target, $link, \UV::S_IRWXU | \UV::S_IRUSR, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_link($this->loop, $target, $link, $this->createGenericCallback($deferred, "Could not create hard link"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function resolveSymlink(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        if ($this->priorVersion) {
            $callback = static function ($fh, $target) use($deferred) : void {
                if (!(bool) $fh) {
                    $deferred->fail(new FilesystemException("Could not read symbolic link"));
                    return;
                }
                $deferred->resolve($target);
            };
        } else {
            $callback = static function ($target) use($deferred) : void {
                if (\is_int($target)) {
                    $deferred->fail(new FilesystemException("Could not read symbolic link"));
                    return;
                }
                $deferred->resolve($target);
            };
        }
        \uv_fs_readlink($this->loop, $path, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_rename($this->loop, $from, $to, $this->createGenericCallback($deferred, "Could not rename file"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_unlink($this->loop, $path, $this->createGenericCallback($deferred, "Could not unlink file"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_mkdir($this->loop, $path, $mode, $this->createGenericCallback($deferred, "Could not create directory"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $path = \str_replace("/", DIRECTORY_SEPARATOR, $path);
        $arrayPath = \explode(DIRECTORY_SEPARATOR, $path);
        $tmpPath = "";
        $callback = function () use(&$callback, &$arrayPath, &$tmpPath, $mode, $deferred) {
            $tmpPath .= DIRECTORY_SEPARATOR . \array_shift($arrayPath);
            if (empty($arrayPath)) {
                \uv_fs_mkdir($this->loop, $tmpPath, $mode, $this->createGenericCallback($deferred, "Could not create directory"));
            } else {
                $this->isDir($tmpPath)->onResolve(function ($error, $result) use($callback, $tmpPath, $mode) : void {
                    if ($result) {
                        $callback();
                    } else {
                        \uv_fs_mkdir($this->loop, $tmpPath, $mode, $callback);
                    }
                });
            }
        };
        $callback();
        return $deferred->promise();
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_rmdir($this->loop, $path, $this->createGenericCallback($deferred, "Could not remove directory"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        if ($this->priorVersion) {
            \uv_fs_readdir($this->loop, $path, 0, static function ($fh, $data) use($deferred, $path) : void {
                if (empty($fh) && $data !== 0) {
                    $deferred->fail(new FilesystemException("Failed reading contents from {$path}"));
                } elseif ($data === 0) {
                    $deferred->resolve([]);
                } else {
                    $deferred->resolve($data);
                }
            });
        } else {
            /** @noinspection PhpUndefinedFunctionInspection */
            \uv_fs_scandir($this->loop, $path, static function ($data) use($deferred, $path) : void {
                if (\is_int($data) && $data !== 0) {
                    $deferred->fail(new FilesystemException("Failed reading contents from {$path}"));
                } elseif ($data === 0) {
                    $deferred->resolve([]);
                } else {
                    $deferred->resolve($data);
                }
            });
        }
        return $deferred->promise();
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = $this->createGenericCallback($deferred, "Could not change file permissions");
        \uv_fs_chmod($this->loop, $path, $mode, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        // @TODO Return a failure in windows environments
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = $this->createGenericCallback($deferred, "Could not change file owner");
        \uv_fs_chown($this->loop, $path, $uid ?? -1, $gid ?? -1, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        $modificationTime = $modificationTime ?? \time();
        $accessTime = $accessTime ?? $modificationTime;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = $this->createGenericCallback($deferred, "Could not touch file");
        \uv_fs_utime($this->loop, $path, $modificationTime, $accessTime, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        $promise = new Coroutine($this->doRead($path));
        $this->poll->listen($promise);
        return $promise;
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        $promise = new Coroutine($this->doWrite($path, $contents));
        $this->poll->listen($promise);
        return $promise;
    }
    /**
     *
     */
    private function parseMode(string $mode) : int
    {
        $mode = \str_replace(['b', 't', 'e'], '', $mode);
        switch ($mode) {
            case "r":
                return \UV::O_RDONLY;
            case "r+":
                return \UV::O_RDWR;
            case "c":
            case "w":
                return \UV::O_WRONLY | \UV::O_CREAT;
            case "c+":
            case "w+":
                return \UV::O_RDWR | \UV::O_CREAT;
            case "a":
                return \UV::O_WRONLY | \UV::O_CREAT | \UV::O_APPEND;
            case "a+":
                return \UV::O_RDWR | \UV::O_CREAT | \UV::O_APPEND;
            case "x":
                return \UV::O_WRONLY | \UV::O_CREAT | \UV::O_EXCL;
            case "x+":
                return \UV::O_RDWR | \UV::O_CREAT | \UV::O_EXCL;
            default:
                throw new \Error('Invalid file mode');
        }
    }
    /**
     *
     */
    private function onOpenHandle($fh, array $openArr) : void
    {
        [$mode] = $openArr;
        if ($mode[0] === "w") {
            \uv_fs_ftruncate($this->loop, $fh, $length = 0, function ($fh) use($openArr) : void {
                if (\is_resource($fh)) {
                    $this->finalizeHandle($fh, $size = 0, $openArr);
                } else {
                    [, $path, $deferred] = $openArr;
                    $deferred->fail(new FilesystemException("Failed truncating file {$path}"));
                }
            });
        } else {
            \uv_fs_fstat($this->loop, $fh, function ($fh, $stat) use($openArr) : void {
                if (\is_resource($fh)) {
                    $this->finalizeHandle($fh, $stat["size"], $openArr);
                } else {
                    [, $path, $deferred] = $openArr;
                    $deferred->fail(new FilesystemException("Failed reading file size from open handle pointing to {$path}"));
                }
            });
        }
    }
    /**
     *
     */
    private function finalizeHandle($fh, $size, array $openArr) : void
    {
        [$mode, $path, $deferred] = $openArr;
        $handle = new UvFile($this->driver, $this->poll, $fh, $path, $mode, $size);
        $deferred->resolve($handle);
    }
    /**
     *
     */
    private function isDir(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->getStatus($path)->onResolve(static function ($error, $result) use($deferred) : void {
            if ($result) {
                $deferred->resolve(($result["mode"] & \UV::S_IFDIR) === \UV::S_IFDIR);
            } else {
                $deferred->resolve(false);
            }
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function doRead($path) : \Generator
    {
        $promise = $this->doFsOpen($path, $flags = \UV::O_RDONLY, $mode = 0);
        if (!($fh = (yield $promise))) {
            throw new FilesystemException("Failed opening file handle: {$path}");
        }
        $deferred = new Deferred();
        $stat = (yield $this->doFsStat($fh));
        if (empty($stat)) {
            $deferred->fail(new FilesystemException("stat operation failed on open file handle"));
        } elseif (!$stat["isfile"]) {
            \uv_fs_close($this->loop, $fh, static function () use($deferred) : void {
                $deferred->fail(new FilesystemException("cannot buffer contents: path is not a file"));
            });
        } else {
            $buffer = (yield $this->doFsRead($fh, $offset = 0, $stat["size"]));
            if ($buffer === false) {
                \uv_fs_close($this->loop, $fh, static function () use($deferred) : void {
                    $deferred->fail(new FilesystemException("read operation failed on open file handle"));
                });
            } else {
                \uv_fs_close($this->loop, $fh, static function () use($deferred, $buffer) : void {
                    $deferred->resolve($buffer);
                });
            }
        }
        return (yield $deferred->promise());
    }
    /**
     *
     */
    private function doFsOpen(string $path, int $flags, int $mode) : Promise
    {
        $deferred = new Deferred();
        \uv_fs_open($this->loop, $path, $flags, $mode, static function ($fh) use($deferred) {
            $deferred->resolve($fh);
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function doFsStat($fh) : Promise
    {
        $deferred = new Deferred();
        \uv_fs_fstat($this->loop, $fh, static function ($fh, $stat) use($deferred) : void {
            if (\is_resource($fh)) {
                $stat["isdir"] = (bool) ($stat["mode"] & \UV::S_IFDIR);
                $stat["isfile"] = !$stat["isdir"];
                $deferred->resolve($stat);
            } else {
                $deferred->resolve();
            }
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function doFsRead($fh, int $offset, int $len) : Promise
    {
        $deferred = new Deferred();
        if ($this->priorVersion) {
            $callback = static function ($fh, $readBytes, $buffer) use($deferred) : void {
                $deferred->resolve($readBytes < 0 ? false : $buffer);
            };
        } else {
            $callback = static function ($readBytes, $buffer) use($deferred) : void {
                $deferred->resolve($readBytes < 0 ? false : $buffer);
            };
        }
        \uv_fs_read($this->loop, $fh, $offset, $len, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    private function doWrite(string $path, string $contents) : \Generator
    {
        $flags = \UV::O_WRONLY | \UV::O_CREAT;
        $mode = \UV::S_IRWXU | \UV::S_IRUSR;
        $promise = $this->doFsOpen($path, $flags, $mode);
        if (!($fh = (yield $promise))) {
            throw new FilesystemException("Failed opening write file handle");
        }
        $deferred = new Deferred();
        \uv_fs_write($this->loop, $fh, $contents, $offset = 0, function ($fh, $result) use($deferred) : void {
            \uv_fs_close($this->loop, $fh, static function () use($deferred, $result) : void {
                if ($result < 0) {
                    $deferred->fail(new FilesystemException(\uv_strerror($result)));
                } else {
                    $deferred->resolve();
                }
            });
        });
        return (yield $deferred->promise());
    }
    /**
     *
     */
    private function createGenericCallback(Deferred $deferred, string $error) : Closure
    {
        $callback = static function (int $result) use($deferred, $error) : void {
            if ($result !== 0) {
                $deferred->fail(new FilesystemException($error));
                return;
            }
            $deferred->resolve();
        };
        if ($this->priorVersion) {
            $callback = static function (bool $result) use($callback) : void {
                $callback($result ? 0 : -1);
            };
        }
        return $callback;
    }
}<?php

namespace Amp\File;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
use Amp\Promise;
interface File extends InputStream, OutputStream
{
    public const DEFAULT_READ_LENGTH = 8192;
    public const SEEK_SET = \SEEK_SET;
    public const SEEK_CUR = \SEEK_CUR;
    public const SEEK_END = \SEEK_END;
    /**
     * Read $length bytes from the open file handle.
     *
     * @param int $length
     *
     * @return Promise<(string | null)>
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise;
    /**
     * Write $data to the open file handle.
     *
     * @param string $data
     *
     * @return Promise<int>
     */
    public function write(string $data) : Promise;
    /**
     * Write $data to the open file handle and close the handle once the write completes.
     *
     * @param string $data
     *
     * @return Promise<int>
     */
    public function end(string $data = "") : Promise;
    /**
    * Close the file handle.
    *
    * Applications are not required to manually close handles -- they will
    be unloaded automatically when the object is garbage collected.
    *
    * @return Promise<void>
    */
    public function close() : Promise;
    /**
    * Set the handle's internal pointer position.
    *
    * $whence values:
    *
    * SEEK_SET - Set position equal to offset bytes.
    SEEK_CUR - Set position to current location plus offset.
    SEEK_END - Set position to end-of-file plus offset.
    *
    * @param int $position
    * @param int $whence
    *
    * @return Promise<int> New offset position.
    */
    public function seek(int $position, int $whence = self::SEEK_SET) : Promise;
    /**
     * Return the current internal offset position of the file handle.
     *
     * @return int
     */
    public function tell() : int;
    /**
     * Test for "end-of-file" on the file handle.
     *
     * @return bool
     */
    public function eof() : bool;
    /**
     * Retrieve the path used when opening the file handle.
     *
     * @return string
     */
    public function getPath() : string;
    /**
     * Retrieve the mode used when opening the file handle.
     *
     * @return string
     */
    public function getMode() : string;
    /**
    * Truncates the file to the given length. If $size is larger than the current file size, the file is extended
    with null bytes.
    *
    * @param int $size New file size.
    *
    * @return Promise<void>
    */
    public function truncate(int $size) : Promise;
}<?php

namespace Amp\File;

final class PendingOperationError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = "The previous file operation must complete before another can be started", int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\File;

class FilesystemException extends \Exception
{
    /**
     *
     */
    public function __construct(string $message, \Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
    }
}<?php

namespace Amp\File;

use Amp\File\Driver\BlockingDriver;
use Amp\File\Driver\EioDriver;
use Amp\File\Driver\ParallelDriver;
use Amp\File\Driver\StatusCachingDriver;
use Amp\File\Driver\UvDriver;
use Amp\Loop;
use Amp\Promise;
const LOOP_STATE_IDENTIFIER = Driver::class;
/**
 * Retrieve the application-wide filesystem instance.
 *
 * @param (Driver | null) $driver Use the specified object as the application-wide filesystem instance.
 *
 * @return Filesystem
 */
function filesystem(?Driver $driver = null) : Filesystem
{
    if ($driver === null) {
        if ($filesystem = Loop::getState(LOOP_STATE_IDENTIFIER)) {
            return $filesystem;
        }
        $defaultDriver = createDefaultDriver();
        if (!\defined("AMP_WORKER")) {
            // Prevent caching in workers, cache in parent instead.
            $defaultDriver = new StatusCachingDriver($defaultDriver);
        }
        $filesystem = new Filesystem($defaultDriver);
    } else {
        $filesystem = new Filesystem($driver);
    }
    if (\defined("AMP_WORKER") && $driver instanceof ParallelDriver) {
        throw new \Error("Cannot use the parallel driver within a worker");
    }
    Loop::setState(LOOP_STATE_IDENTIFIER, $filesystem);
    return $filesystem;
}
/**
 * Create a new filesystem driver best-suited for the current environment.
 *
 * @return Driver
 */
function createDefaultDriver() : Driver
{
    $driver = Loop::get();
    if (UvDriver::isSupported($driver)) {
        /** @var Loop\UvDriver $driver */
        return new UvDriver($driver);
    }
    if (EioDriver::isSupported()) {
        return new EioDriver($driver);
    }
    if (\defined("AMP_WORKER")) {
        // Prevent spawning infinite workers.
        return new BlockingDriver();
    }
    return new ParallelDriver();
}
/**
 * Open a handle for the specified path.
 *
 * @param string $path
 * @param string $mode
 *
 * @return Promise<File>
 */
function openFile(string $path, string $mode) : Promise
{
    return filesystem()->openFile($path, $mode);
}
/**
 * Execute a file stat operation.
 *
 * If the requested path does not exist the resulting Promise will resolve to NULL.
 *
 * @param string $path File system path.
 *
 * @return Promise<(array | null)>
 */
function getStatus(string $path) : Promise
{
    return filesystem()->getStatus($path);
}
/**
 * Same as {@see Filesystem::getStatus()} except if the path is a link then the link's data is returned.
 *
 * If the requested path does not exist the resulting Promise will resolve to NULL.
 *
 * @param string $path File system path.
 *
 * @return Promise<(array | null)>
 */
function getLinkStatus(string $path) : Promise
{
    return filesystem()->getLinkStatus($path);
}
/**
* Does the specified path exist?
*
* This function should never resolve as a failure -- only a successful bool value
indicating the existence of the specified path.
*
* @param string $path File system path.
*
* @return Promise<bool>
*/
function exists(string $path) : Promise
{
    return filesystem()->exists($path);
}
/**
* Retrieve the size in bytes of the file at the specified path.
*
* If the path does not exist or is not a regular file this
function's returned Promise WILL resolve as a failure.
*
* @param string $path File system path.
* @fails \Amp\Files\FilesystemException If the path does not exist or is not a file.
*
* @return Promise<int>
*/
function getSize(string $path) : Promise
{
    return filesystem()->getSize($path);
}
/**
 * Does the specified path exist and is it a directory?
 *
 * @param string $path File system path.
 *
 * @return Promise<bool>
 */
function isDirectory(string $path) : Promise
{
    return filesystem()->isDirectory($path);
}
/**
 * Does the specified path exist and is it a file?
 *
 * @param string $path File system path.
 *
 * @return Promise<bool>
 */
function isFile(string $path) : Promise
{
    return filesystem()->isFile($path);
}
/**
* Does the specified path exist and is it a symlink?
*
* If the path does not exist the returned Promise will resolve
to FALSE and will not reject with an error.
*
* @param string $path File system path.
*
* @return Promise<bool>
*/
function isSymlink(string $path) : Promise
{
    return filesystem()->isSymlink($path);
}
/**
 * Retrieve the path's last modification time as a unix timestamp.
 *
 * @param string $path File system path.
 * @fails \Amp\Files\FilesystemException If the path does not exist.
 *
 * @return Promise<int>
 */
function getModificationTime(string $path) : Promise
{
    return filesystem()->getModificationTime($path);
}
/**
 * Retrieve the path's last access time as a unix timestamp.
 *
 * @param string $path File system path.
 * @fails \Amp\Files\FilesystemException If the path does not exist.
 *
 * @return Promise<int>
 */
function getAccessTime(string $path) : Promise
{
    return filesystem()->getAccessTime($path);
}
/**
 * Retrieve the path's creation time as a unix timestamp.
 *
 * @param string $path File system path.
 * @fails \Amp\Files\FilesystemException If the path does not exist.
 *
 * @return Promise<int>
 */
function getCreationTime(string $path) : Promise
{
    return filesystem()->getCreationTime($path);
}
/**
 * Create a symlink $link pointing to the file/directory located at $original.
 *
 * @param string $original
 * @param string $link
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function createSymlink(string $original, string $link) : Promise
{
    return filesystem()->createSymlink($original, $link);
}
/**
 * Create a hard link $link pointing to the file/directory located at $target.
 *
 * @param string $target
 * @param string $link
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function createHardlink(string $target, string $link) : Promise
{
    return filesystem()->createHardlink($target, $link);
}
/**
 * Resolve the symlink at $path.
 *
 * @param string $path
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<string>
 */
function resolveSymlink(string $path) : Promise
{
    return filesystem()->resolveSymlink($path);
}
/**
 * Move / rename a file or directory.
 *
 * @param string $from
 * @param string $to
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function move(string $from, string $to) : Promise
{
    return filesystem()->move($from, $to);
}
/**
 * Delete a file.
 *
 * @param string $path
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function deleteFile(string $path) : Promise
{
    return filesystem()->deleteFile($path);
}
/**
 * Create a directory.
 *
 * @param string $path
 * @param int $mode
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function createDirectory(string $path, int $mode = 0777) : Promise
{
    return filesystem()->createDirectory($path, $mode);
}
/**
 * Create a directory recursively.
 *
 * @param string $path
 * @param int $mode
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
{
    return filesystem()->createDirectoryRecursively($path, $mode);
}
/**
 * Delete a directory.
 *
 * @param string $path
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function deleteDirectory(string $path) : Promise
{
    return filesystem()->deleteDirectory($path);
}
/**
 * Retrieve an array of files and directories inside the specified path.
 *
 * Dot entries are not included in the resulting array (i.e. "." and "..").
 *
 * @param string $path
 *
 * @return Promise<list<string>>
 */
function listFiles(string $path) : Promise
{
    return filesystem()->listFiles($path);
}
/**
 * Change permissions of a file or directory.
 *
 * @param string $path
 * @param int $mode
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function changePermissions(string $path, int $mode) : Promise
{
    return filesystem()->changePermissions($path, $mode);
}
/**
 * Change ownership of a file or directory.
 *
 * @param string $path
 * @param (int | null) $uid null to ignore
 * @param (int | null) $gid null to ignore
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function changeOwner(string $path, ?int $uid, ?int $gid = null) : Promise
{
    return filesystem()->changeOwner($path, $uid, $gid);
}
/**
 * Update the access and modification time of the specified path.
 *
 * If the file does not exist it will be created automatically.
 *
 * @param string $path
 * @param (int | null) $modificationTime The touch time. If $time is not supplied, the current system time is used.
 * @param (int | null) $accessTime The access time. If not supplied, the modification time is used.
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function touch(string $path, ?int $modificationTime = null, ?int $accessTime = null) : Promise
{
    return filesystem()->touch($path, $modificationTime, $accessTime);
}
/**
 * Buffer the specified file's contents.
 *
 * @param string $path The file path from which to buffer contents.
 *
 * @return Promise<string>
 */
function read(string $path) : Promise
{
    return filesystem()->read($path);
}
/**
 * Write the contents string to the specified path.
 *
 * @param string $path The file path to which to $contents should be written.
 * @param string $contents The data to write to the specified $path.
 *
 * @return Promise<void>
 */
function write(string $path, string $contents) : Promise
{
    return filesystem()->write($path, $contents);
}<?php

namespace Amp\File;

use Amp\Promise;
use function Amp\call;
final class Filesystem
{
    /** @var Driver */
    private $driver;
    /**
     *
     */
    public function __construct(Driver $driver)
    {
        $this->driver = $driver;
    }
    /**
     * Open a handle for the specified path.
     *
     * @param string $path
     * @param string $mode
     *
     * @return Promise<File>
     */
    public function openFile(string $path, string $mode) : Promise
    {
        return $this->driver->openFile($path, $mode);
    }
    /**
     * Execute a file stat operation.
     *
     * If the requested path does not exist the resulting Promise will resolve to NULL.
     *
     * @param string $path File system path.
     *
     * @return Promise<(array | null)>
     */
    public function getStatus(string $path) : Promise
    {
        return $this->driver->getStatus($path);
    }
    /**
     * Same as {@see Filesystem::getStatus()} except if the path is a link then the link's data is returned.
     *
     * If the requested path does not exist the resulting Promise will resolve to NULL.
     *
     * @param string $path File system path.
     *
     * @return Promise<(array | null)>
     */
    public function getLinkStatus(string $path) : Promise
    {
        return $this->driver->getLinkStatus($path);
    }
    /**
    * Does the specified path exist?
    *
    * This function should never resolve as a failure -- only a successful bool value
    indicating the existence of the specified path.
    *
    * @param string $path File system path.
    *
    * @return Promise<bool>
    */
    public function exists(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            return $result !== null;
        });
    }
    /**
    * Retrieve the size in bytes of the file at the specified path.
    *
    * If the path does not exist or is not a regular file this
    function's returned Promise WILL resolve as a failure.
    *
    * @param string $path File system path.
    * @fails \Amp\Files\FilesystemException If the path does not exist or is not a file.
    *
    * @return Promise<int>
    */
    public function getSize(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                throw new FilesystemException("Failed to read file size for '{$path}'");
            }
            if ($result['mode'] & 0100000) {
                return $result["size"];
            }
            throw new FilesystemException("Failed to read file size for '{$path}'; specified path is not a regular file");
        });
    }
    /**
     * Does the specified path exist and is it a directory?
     *
     * @param string $path File system path.
     *
     * @return Promise<bool>
     */
    public function isDirectory(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                return false;
            }
            return (bool) ($result['mode'] & 040000);
        });
    }
    /**
     * Does the specified path exist and is it a file?
     *
     * @param string $path File system path.
     *
     * @return Promise<bool>
     */
    public function isFile(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                return false;
            }
            return (bool) ($result['mode'] & 0100000);
        });
    }
    /**
    * Does the specified path exist and is it a symlink?
    *
    * If the path does not exist the returned Promise will resolve
    to FALSE and will not reject with an error.
    *
    * @param string $path File system path.
    *
    * @return Promise<bool>
    */
    public function isSymlink(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getLinkStatus($path));
            if ($result === null) {
                return false;
            }
            return ($result['mode'] & 0120000) === 0120000;
        });
    }
    /**
     * Retrieve the path's last modification time as a unix timestamp.
     *
     * @param string $path File system path.
     * @fails \Amp\Files\FilesystemException If the path does not exist.
     *
     * @return Promise<int>
     */
    public function getModificationTime(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                throw new FilesystemException("Failed to read file modification time for '{$path}'");
            }
            return $result["mtime"];
        });
    }
    /**
     * Retrieve the path's last access time as a unix timestamp.
     *
     * @param string $path File system path.
     * @fails \Amp\Files\FilesystemException If the path does not exist.
     *
     * @return Promise<int>
     */
    public function getAccessTime(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                throw new FilesystemException("Failed to read file access time for '{$path}'");
            }
            return $result["atime"];
        });
    }
    /**
     * Retrieve the path's creation time as a unix timestamp.
     *
     * @param string $path File system path.
     * @fails \Amp\Files\FilesystemException If the path does not exist.
     *
     * @return Promise<int>
     */
    public function getCreationTime(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                throw new FilesystemException("Failed to read file creation time for '{$path}'");
            }
            return $result["ctime"];
        });
    }
    /**
     * Create a symlink $link pointing to the file/directory located at $original.
     *
     * @param string $original
     * @param string $link
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function createSymlink(string $original, string $link) : Promise
    {
        return $this->driver->createSymlink($original, $link);
    }
    /**
     * Create a hard link $link pointing to the file/directory located at $target.
     *
     * @param string $target
     * @param string $link
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        return $this->driver->createHardlink($target, $link);
    }
    /**
     * Resolve the symlink at $path.
     *
     * @param string $path
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<string>
     */
    public function resolveSymlink(string $path) : Promise
    {
        return $this->driver->resolveSymlink($path);
    }
    /**
     * Move / rename a file or directory.
     *
     * @param string $from
     * @param string $to
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function move(string $from, string $to) : Promise
    {
        return $this->driver->move($from, $to);
    }
    /**
     * Delete a file.
     *
     * @param string $path
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function deleteFile(string $path) : Promise
    {
        return $this->driver->deleteFile($path);
    }
    /**
     * Create a directory.
     *
     * @param string $path
     * @param int $mode
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        return $this->driver->createDirectory($path, $mode);
    }
    /**
     * Create a directory recursively.
     *
     * @param string $path
     * @param int $mode
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        return $this->driver->createDirectoryRecursively($path, $mode);
    }
    /**
     * Delete a directory.
     *
     * @param string $path
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function deleteDirectory(string $path) : Promise
    {
        return $this->driver->deleteDirectory($path);
    }
    /**
     * Retrieve an array of files and directories inside the specified path.
     *
     * Dot entries are not included in the resulting array (i.e. "." and "..").
     *
     * @param string $path
     *
     * @return Promise<list<string>>
     */
    public function listFiles(string $path) : Promise
    {
        return $this->driver->listFiles($path);
    }
    /**
     * Change permissions of a file or directory.
     *
     * @param string $path
     * @param int $mode
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        return $this->driver->changePermissions($path, $mode);
    }
    /**
     * Change ownership of a file or directory.
     *
     * @param string $path
     * @param (int | null) $uid null to ignore
     * @param (int | null) $gid null to ignore
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid = null) : Promise
    {
        return $this->driver->changeOwner($path, $uid, $gid);
    }
    /**
     * Update the access and modification time of the specified path.
     *
     * If the file does not exist it will be created automatically.
     *
     * @param string $path
     * @param (int | null) $modificationTime The touch time. If $time is not supplied, the current system time is used.
     * @param (int | null) $accessTime The access time. If not supplied, the modification time is used.
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function touch(string $path, ?int $modificationTime = null, ?int $accessTime = null) : Promise
    {
        return $this->driver->touch($path, $modificationTime, $accessTime);
    }
    /**
     * Buffer the specified file's contents.
     *
     * @param string $path The file path from which to buffer contents.
     *
     * @return Promise<string>
     */
    public function read(string $path) : Promise
    {
        return $this->driver->read($path);
    }
    /**
     * Write the contents string to the specified path.
     *
     * @param string $path The file path to which to $contents should be written.
     * @param string $contents The data to write to the specified $path.
     *
     * @return Promise<void>
     */
    public function write(string $path, string $contents) : Promise
    {
        return $this->driver->write($path, $contents);
    }
}{
    "name": "amphp/file",
    "homepage": "https://github.com/amphp/file",
    "description": "Allows non-blocking access to the filesystem for Amp.",
    "support": {
        "issues": "https://github.com/amphp/file/issues"
    },
    "keywords": [
        "file",
        "disk",
        "static",
        "async",
        "non-blocking",
        "amp",
        "amphp",
        "io",
        "filesystem"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2.5.2",
        "amphp/byte-stream": "^1.8.1",
        "amphp/parallel": "^1.4",
        "amphp/sync": "^1.4"
    },
    "require-dev": {
        "ext-eio": "^2 || ^3",
        "ext-uv": "^0.3 || ^0.2",
        "amphp/phpunit-util": "^1.1",
        "phpunit/phpunit": "^9 || ^8 || ^7",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\File\\": "src"
        },
        "files": ["src/functions.php"]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\File\\Test\\": "test",
            "Amp\\Sync\\Test\\": "vendor/amphp/sync/test"
        }
    },
    "config": {
        "preferred-install": {
            "amphp/sync": "source"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.x-dev"
        }
    },
    "scripts": {
        "check": [
            "@code-style",
            "@test"
        ],
        "code-style": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

declare (strict_types=1);
namespace Amp\File\Test\Sync;

use Amp\File\Sync\AsyncFileMutex;
use Amp\Sync\Mutex;
use Amp\Sync\Test\AbstractMutexTest;
final class AsyncFileMutexTest extends AbstractMutexTest
{
    /**
     *
     */
    public function createMutex() : Mutex
    {
        return new AsyncFileMutex(\tempnam(\sys_get_temp_dir(), 'mutex-') . '.lock');
    }
}<?php

namespace Amp\File\Test;

use Amp\PHPUnit\AsyncTestCase;
abstract class FilesystemTest extends AsyncTestCase
{
    /**
     *
     */
    protected function setUp() : void
    {
        parent::setUp();
        Fixture::init();
    }
    /**
     *
     */
    protected function tearDown() : void
    {
        parent::tearDown();
        Fixture::clear();
    }
}<?php

namespace Amp\File\Test;

use Amp\File;
use Amp\File\PendingOperationError;
abstract class AsyncFileTest extends FileTest
{
    /**
     *
     */
    public function testSimultaneousReads() : \Generator
    {
        $this->expectException(PendingOperationError::class);
        /** @var File\File $handle */
        $handle = (yield File\openFile(__FILE__, "r"));
        $promise1 = $handle->read();
        $promise2 = $handle->read();
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield File\read(__FILE__)), 0, 20);
        $this->assertSame($expected, (yield $promise1));
        (yield $promise2);
    }
    /**
     *
     */
    public function testSeekWhileReading() : \Generator
    {
        $this->expectException(PendingOperationError::class);
        /** @var File\File $handle */
        $handle = (yield File\openFile(__FILE__, "r"));
        $promise1 = $handle->read(10);
        $promise2 = $handle->seek(0);
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield File\read(__FILE__)), 0, 10);
        $this->assertSame($expected, (yield $promise1));
        (yield $promise2);
    }
    /**
     *
     */
    public function testReadWhileWriting() : \Generator
    {
        $this->expectException(PendingOperationError::class);
        $path = Fixture::path() . "/temp";
        /** @var File\File $handle */
        $handle = (yield File\openFile($path, "c+"));
        $data = "test";
        $promise1 = $handle->write($data);
        $promise2 = $handle->read(10);
        $this->assertSame(\strlen($data), (yield $promise1));
        (yield $promise2);
        // Should throw.
    }
    /**
     *
     */
    public function testWriteWhileReading() : \Generator
    {
        $this->expectException(PendingOperationError::class);
        $path = Fixture::path() . "/temp";
        /** @var File\File $handle */
        $handle = (yield File\openFile($path, "c+"));
        $promise1 = $handle->read(10);
        $promise2 = $handle->write("test");
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield File\read(__FILE__)), 0, 10);
        $this->assertSame($expected, (yield $promise1));
        (yield $promise2);
        // Should throw.
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\BlockingDriver;
use Amp\File\Test\FileTest;
class StatusCachingFileTest extends FileTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        return new File\Driver\StatusCachingDriver(new BlockingDriver());
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\EioDriver;
use Amp\File\Test\AsyncFileTest;
use Amp\Loop;
class EioFileTest extends AsyncFileTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        if (!\extension_loaded("eio")) {
            $this->markTestSkipped("eio extension not loaded");
        }
        return new EioDriver(Loop::get());
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\BlockingDriver;
use Amp\File\Test\DriverTest;
class StatusCachingDriverTest extends DriverTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        return new File\Driver\StatusCachingDriver(new BlockingDriver());
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\EioDriver;
use Amp\File\Test\DriverTest;
use Amp\Loop;
class EioDriverTest extends DriverTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        if (!\extension_loaded("eio")) {
            $this->markTestSkipped("eio extension not loaded");
        }
        return new EioDriver(Loop::get());
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\ParallelDriver;
use Amp\File\Test\AsyncFileTest;
use Amp\Parallel\Worker\DefaultPool;
use Amp\Parallel\Worker\Pool;
class ParallelFileTest extends AsyncFileTest
{
    /** @var Pool */
    private $pool;
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        $this->pool = new DefaultPool();
        return new ParallelDriver($this->pool);
    }
    /**
     *
     */
    protected function tearDownAsync() : void
    {
        $this->pool->shutdown();
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\ParallelDriver;
use Amp\File\Test\DriverTest;
use Amp\Parallel\Worker\DefaultPool;
use Amp\Parallel\Worker\Pool;
class ParallelDriverTest extends DriverTest
{
    /** @var Pool */
    private $pool;
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        $this->pool = new DefaultPool();
        return new ParallelDriver($this->pool);
    }
    /**
     *
     */
    protected function tearDownAsync() : void
    {
        $this->pool->shutdown();
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\UvDriver;
use Amp\File\Test\DriverTest;
use Amp\Loop;
class UvDriverTest extends DriverTest
{
    /**
     * @dataProvider symlinkPathProvider
     *
     * @param \Closure $linkResolver
     */
    public function testResolveSymlinkError(\Closure $linkResolver) : \Generator
    {
        if (\version_compare(\phpversion('uv'), '0.3.0', '<')) {
            $this->markTestSkipped('UvDriver Test Skipped: Causes Crash');
        }
        yield from parent::testResolveSymlinkError($linkResolver);
    }
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        if (!\extension_loaded("uv")) {
            $this->markTestSkipped("php-uv extension not loaded");
        }
        $loop = new Loop\UvDriver();
        Loop::set($loop);
        return new UvDriver($loop);
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\BlockingDriver;
use Amp\File\Test\DriverTest;
class BlockingDriverTest extends DriverTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        return new BlockingDriver();
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\BlockingDriver;
use Amp\File\Test\FileTest;
class BlockingFileTest extends FileTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        return new BlockingDriver();
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\UvDriver;
use Amp\File\Test\AsyncFileTest;
use Amp\Loop;
class UvFileTest extends AsyncFileTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        if (!\extension_loaded("uv")) {
            $this->markTestSkipped("php-uv extension not loaded");
        }
        $loop = new Loop\UvDriver();
        Loop::set($loop);
        return new UvDriver($loop);
    }
}<?php

namespace Amp\File\Test;

use Amp\ByteStream\ClosedException;
use Amp\File;
abstract class FileTest extends FilesystemTest
{
    /** @var File\Driver */
    private $driver;
    /**
     *
     */
    public function testWrite() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        $this->assertSame(0, $handle->tell());
        $handle->write("foo");
        (yield $handle->write("bar"));
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertSame(6, $handle->tell());
        $this->assertTrue($handle->eof());
        $this->assertSame("foobar", $contents);
        (yield $handle->close());
    }
    /**
     *
     */
    public function testEmptyWrite() : \Generator
    {
        $path = Fixture::path() . "/write";
        $handle = (yield $this->driver->openFile($path, "c+"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->write(""));
        $this->assertSame(0, $handle->tell());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testWriteAfterClose() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        (yield $handle->close());
        $this->expectException(ClosedException::class);
        (yield $handle->write("bar"));
    }
    /**
     *
     */
    public function testDoubleClose() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        (yield $handle->close());
        $this->assertNull((yield $handle->close()));
    }
    /**
     *
     */
    public function testWriteAfterEnd() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->end("foo"));
        $this->expectException(ClosedException::class);
        (yield $handle->write("bar"));
    }
    /**
     *
     */
    public function testWriteInAppendMode() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "a+"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->write("bar"));
        (yield $handle->write("foo"));
        (yield $handle->write("baz"));
        $this->assertSame(9, $handle->tell());
        (yield $handle->seek(0));
        $this->assertSame(0, $handle->tell());
        $this->assertSame("barfoobaz", (yield $handle->read()));
    }
    /**
     *
     */
    public function testReadingToEof() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $contents = "";
        $position = 0;
        $stat = (yield $this->driver->getStatus(__FILE__));
        $chunkSize = (int) \floor($stat["size"] / 5);
        while (!$handle->eof()) {
            $chunk = (yield $handle->read($chunkSize));
            $contents .= $chunk;
            $position += \strlen($chunk);
            $this->assertSame($position, $handle->tell());
        }
        $this->assertNull((yield $handle->read()));
        $this->assertSame((yield $this->driver->read(__FILE__)), $contents);
        (yield $handle->close());
    }
    /**
     *
     */
    public function testSequentialReads() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $contents = "";
        $contents .= (yield $handle->read(10));
        $contents .= (yield $handle->read(10));
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield $this->driver->read(__FILE__)), 0, 20);
        $this->assertSame($expected, $contents);
        (yield $handle->close());
    }
    /**
     *
     */
    public function testReadingFromOffset() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->seek(10));
        $this->assertSame(10, $handle->tell());
        $chunk = (yield $handle->read(90));
        $this->assertSame(100, $handle->tell());
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield $this->driver->read(__FILE__)), 10, 90);
        $this->assertSame($expected, $chunk);
        (yield $handle->close());
    }
    /**
     *
     */
    public function testSeekThrowsOnInvalidWhence() : \Generator
    {
        $this->expectException(\Error::class);
        try {
            /** @var File\File $handle */
            $handle = (yield $this->driver->openFile(__FILE__, "r"));
            (yield $handle->seek(0, 99999));
        } finally {
            (yield $handle->close());
        }
    }
    /**
     *
     */
    public function testSeekSetCur() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->seek(10));
        $this->assertSame(10, $handle->tell());
        (yield $handle->seek(-10, \SEEK_CUR));
        $this->assertSame(0, $handle->tell());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testSeekSetEnd() : \Generator
    {
        $size = \filesize(__FILE__);
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->seek(-10, \SEEK_END));
        $this->assertSame($size - 10, $handle->tell());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testPath() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame(__FILE__, $handle->getPath());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testMode() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame("r", $handle->getMode());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testClose() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        (yield $handle->close());
        $this->expectException(ClosedException::class);
        (yield $handle->read());
    }
    /**
     * @depends testWrite
     */
    public function testTruncateToSmallerSize() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        $handle->write("foo");
        (yield $handle->write("bar"));
        (yield $handle->truncate(4));
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertTrue($handle->eof());
        $this->assertSame("foob", $contents);
        (yield $handle->write("bar"));
        $this->assertSame(7, $handle->tell());
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertSame("foobbar", $contents);
        (yield $handle->close());
    }
    /**
     * @depends testWrite
     */
    public function testTruncateToLargerSize() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        (yield $handle->write("foo"));
        (yield $handle->truncate(6));
        $this->assertSame(3, $handle->tell());
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertTrue($handle->eof());
        $this->assertSame("foo\x00\x00\x00", $contents);
        (yield $handle->write("bar"));
        $this->assertSame(9, $handle->tell());
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertSame("foo\x00\x00\x00bar", $contents);
        (yield $handle->close());
    }
    /**
     *
     */
    protected abstract function createDriver() : File\Driver;
    /**
     *
     */
    protected function setUp() : void
    {
        parent::setUp();
        $this->driver = $this->createDriver();
    }
}<?php

namespace Amp\File\Test;

use Amp\File;
use Amp\File\FilesystemException;
abstract class DriverTest extends FilesystemTest
{
    /** @var File\Filesystem */
    protected $driver;
    /**
     *
     */
    public function testListFiles() : \Generator
    {
        $fixtureDir = Fixture::path();
        $actual = (yield $this->driver->listFiles($fixtureDir));
        $expected = ["dir", "dirlink", "fifo", "fifolink", "file", "filelink", "linkloop"];
        $this->assertSame($expected, $actual);
    }
    /**
     *
     */
    public function testListFilesThrowsIfPathNotADirectory() : \Generator
    {
        $this->expectException(FilesystemException::class);
        (yield $this->driver->listFiles(__FILE__));
    }
    /**
     *
     */
    public function testListFilesThrowsIfPathDoesntExist() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $path = Fixture::path() . "/nonexistent";
        (yield $this->driver->listFiles($path));
    }
    /**
     *
     */
    public function testCreateSymlink() : \Generator
    {
        $fixtureDir = Fixture::path();
        $original = "{$fixtureDir}/file";
        $link = "{$fixtureDir}/symlink.txt";
        $this->assertNull((yield $this->driver->createSymlink($original, $link)));
        $this->assertTrue(\is_link($link));
        (yield $this->driver->deleteFile($link));
    }
    /**
     *
     */
    public function testCreateSymlinkFailWhenLinkExists() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        (yield $this->driver->createSymlink($path, $path));
    }
    /**
     *
     */
    public function testCreateHardlink() : \Generator
    {
        $fixtureDir = Fixture::path();
        $original = "{$fixtureDir}/file";
        $link = "{$fixtureDir}/hardlink.txt";
        $this->assertNull((yield $this->driver->createHardlink($original, $link)));
        $this->assertFileExists($link);
        $this->assertFalse(\is_link($link));
        (yield $this->driver->deleteFile($link));
    }
    /**
     *
     */
    public function testCreateHardlinkFailWhenLinkExists() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        (yield $this->driver->createHardlink($path, $path));
    }
    /**
     *
     */
    public function testResolveSymlink() : \Generator
    {
        $fixtureDir = Fixture::path();
        $original = "{$fixtureDir}/file";
        $link = "{$fixtureDir}/symlink.txt";
        \symlink($original, $link);
        $this->assertSame($original, (yield $this->driver->resolveSymlink($link)));
    }
    /**
     *
     */
    public function symlinkPathProvider() : array
    {
        return ['nonExistingPath' => [static function () {
            return Fixture::path() . '/' . \uniqid('amphp-test-', true);
        }], 'notLink' => [static function () {
            return Fixture::path();
        }]];
    }
    /**
     * @dataProvider symlinkPathProvider
     *
     * @param \Closure $linkResolver
     *
     * @return \Generator
     */
    public function testResolveSymlinkError(\Closure $linkResolver) : \Generator
    {
        $this->expectException(FilesystemException::class);
        $link = $linkResolver();
        (yield $this->driver->resolveSymlink($link));
    }
    /**
     *
     */
    public function testLinkStatus() : \Generator
    {
        $fixtureDir = Fixture::path();
        $target = "{$fixtureDir}/file";
        $link = "{$fixtureDir}/symlink.txt";
        (yield $this->driver->createSymlink($target, $link));
        $this->assertIsArray((yield $this->driver->getLinkStatus($link)));
        (yield $this->driver->deleteFile($link));
    }
    /**
     *
     */
    public function testStatus() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $this->assertIsArray($stat);
        $this->assertSameStatus(\stat($path), $stat);
    }
    /**
     *
     */
    public function testDirectoryStatus() : \Generator
    {
        $fixtureDir = Fixture::path();
        $stat = (yield $this->driver->getStatus("{$fixtureDir}/dir"));
        $this->assertIsArray($stat);
        $this->assertSameStatus(\stat("{$fixtureDir}/dir"), $stat);
    }
    /**
     *
     */
    public function testNonexistentPathStatusResolvesToNull() : \Generator
    {
        $fixtureDir = Fixture::path();
        $stat = (yield $this->driver->getStatus("{$fixtureDir}/nonexistent"));
        $this->assertNull($stat);
    }
    /**
     *
     */
    public function testExists() : \Generator
    {
        $fixtureDir = Fixture::path();
        $this->assertFalse((yield $this->driver->exists("{$fixtureDir}/nonexistent")));
        $this->assertTrue((yield $this->driver->exists("{$fixtureDir}/file")));
    }
    /**
     *
     */
    public function testRead() : \Generator
    {
        $fixtureDir = Fixture::path();
        $this->assertSame("small", (yield $this->driver->read("{$fixtureDir}/file")));
    }
    /**
     *
     */
    public function testSize() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $size = $stat["size"];
        $this->assertSame($size, (yield $this->driver->getSize($path)));
    }
    /**
     *
     */
    public function testSizeFailsOnNonexistentPath() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        (yield $this->driver->getSize($path));
    }
    /**
     *
     */
    public function testSizeFailsOnDirectoryPath() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/dir";
        $this->assertTrue((yield $this->driver->isDirectory($path)));
        (yield $this->driver->getSize($path));
    }
    /**
     * @dataProvider dataForDirectoryCheck
     */
    public function testIsDirectory(bool $expectedResult, string $name) : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/{$name}";
        $this->assertSame($expectedResult, (yield $this->driver->isDirectory($path)));
    }
    /**
     *
     */
    public function dataForDirectoryCheck() : \Generator
    {
        (yield 'file' => [false, 'file']);
        (yield 'filelink' => [false, 'filelink']);
        (yield 'dir' => [true, 'dir']);
        (yield 'dirlink' => [true, 'dirlink']);
        if (\extension_loaded('posix')) {
            (yield 'fifo' => [false, 'fifo']);
            (yield 'fifolink' => [false, 'fifolink']);
        }
        (yield 'linkloop' => [false, 'linkloop']);
        (yield 'nonexistent' => [false, 'nonexistent']);
    }
    /**
     * @dataProvider dataForFileCheck
     */
    public function testIsFile(bool $expectedResult, string $name) : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/{$name}";
        $this->assertSame($expectedResult, (yield $this->driver->isFile($path)));
    }
    /**
     *
     */
    public function dataForFileCheck() : \Generator
    {
        (yield 'file' => [true, 'file']);
        (yield 'filelink' => [true, 'filelink']);
        (yield 'dir' => [false, 'dir']);
        (yield 'dirlink' => [false, 'dirlink']);
        if (\extension_loaded('posix')) {
            (yield 'fifo' => [false, 'fifo']);
            (yield 'fifolink' => [false, 'fifolink']);
        }
        (yield 'linkloop' => [false, 'linkloop']);
        (yield 'nonexistent' => [false, 'nonexistent']);
    }
    /**
     * @dataProvider dataForSymlinkCheck
     */
    public function testIsSymlink(bool $expectedResult, string $name) : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/{$name}";
        $this->assertSame($expectedResult, (yield $this->driver->isSymlink($path)));
    }
    /**
     *
     */
    public function dataForSymlinkCheck() : \Generator
    {
        (yield 'file' => [false, 'file']);
        (yield 'filelink' => [true, 'filelink']);
        (yield 'dir' => [false, 'dir']);
        (yield 'dirlink' => [true, 'dirlink']);
        if (\extension_loaded('posix')) {
            (yield 'fifo' => [false, 'fifo']);
            (yield 'fifolink' => [true, 'fifolink']);
        }
        (yield 'linkloop' => [true, 'linkloop']);
        (yield 'nonexistent' => [false, 'nonexistent']);
    }
    /**
     *
     */
    public function testMove() : \Generator
    {
        $fixtureDir = Fixture::path();
        $contents1 = "rename test";
        $old = "{$fixtureDir}/rename1.txt";
        $new = "{$fixtureDir}/rename2.txt";
        (yield $this->driver->write($old, $contents1));
        $this->assertNull((yield $this->driver->move($old, $new)));
        $contents2 = (yield $this->driver->read($new));
        (yield $this->driver->deleteFile($new));
        $this->assertSame($contents1, $contents2);
    }
    /**
     *
     */
    public function testMoveFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->move($path, $path));
    }
    /**
     *
     */
    public function testDeleteFile() : \Generator
    {
        $fixtureDir = Fixture::path();
        $toUnlink = "{$fixtureDir}/unlink";
        (yield $this->driver->getStatus($toUnlink));
        (yield $this->driver->write($toUnlink, "unlink me"));
        $this->assertNull((yield $this->driver->deleteFile($toUnlink)));
        $this->assertNull((yield $this->driver->getStatus($toUnlink)));
    }
    /**
     *
     */
    public function testDeleteFileFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->deleteFile($path));
    }
    /**
     *
     */
    public function testDeleteFileFailsOnDirectory() : \Generator
    {
        $fixtureDir = Fixture::path();
        $dir = "{$fixtureDir}/newdir";
        (yield $this->driver->createDirectory($dir));
        $this->expectException(FilesystemException::class);
        (yield $this->driver->deleteFile($dir));
    }
    /**
     *
     */
    public function testCreateAndDeleteDirectory() : \Generator
    {
        $fixtureDir = Fixture::path();
        $dir = "{$fixtureDir}/newdir";
        \umask(022);
        $this->assertNull((yield $this->driver->createDirectory($dir)));
        $stat = (yield $this->driver->getStatus($dir));
        $this->assertSame('0755', $this->getPermissionsFromStatus($stat));
        $this->assertNull((yield $this->driver->deleteDirectory($dir)));
        $this->assertNull((yield $this->driver->getStatus($dir)));
        // test for 0, because previous array_filter made that not work
        $dir = "{$fixtureDir}/newdir/with/recursive/creation/0/1/2";
        $this->assertNull((yield $this->driver->createDirectoryRecursively($dir, 0764)));
        $stat = (yield $this->driver->getStatus($dir));
        $this->assertSame('0744', $this->getPermissionsFromStatus($stat));
    }
    /**
     *
     */
    public function testCreateDirectoryFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->createDirectory($path));
    }
    /**
     *
     */
    public function testDeleteDirectoryFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->deleteDirectory($path));
    }
    /**
     *
     */
    public function testDeleteDirectoryFailsOnFile() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->deleteDirectory($path));
    }
    /**
     *
     */
    public function testMtime() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $statMtime = $stat["mtime"];
        $this->assertSame($statMtime, (yield $this->driver->getModificationTime($path)));
    }
    /**
     *
     */
    public function testMtimeFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->getModificationTime($path));
    }
    /**
     *
     */
    public function testAtime() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $statAtime = $stat["atime"];
        $this->assertSame($statAtime, (yield $this->driver->getAccessTime($path)));
    }
    /**
     *
     */
    public function testAtimeFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->getAccessTime($path));
    }
    /**
     *
     */
    public function testCtime() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $statCtime = $stat["ctime"];
        $this->assertSame($statCtime, (yield $this->driver->getCreationTime($path)));
    }
    /**
     *
     */
    public function testCtimeFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->getCreationTime($path));
    }
    /**
     * @group slow
     */
    public function testTouch() : \Generator
    {
        $fixtureDir = Fixture::path();
        $touch = "{$fixtureDir}/touch";
        (yield $this->driver->write($touch, "touch me"));
        $oldStat = (yield $this->driver->getStatus($touch));
        $this->assertNull((yield $this->driver->touch($touch, \time() + 10, \time() + 20)));
        $newStat = (yield $this->driver->getStatus($touch));
        (yield $this->driver->deleteFile($touch));
        $this->assertTrue($newStat["atime"] > $oldStat["atime"]);
        $this->assertTrue($newStat["mtime"] > $oldStat["mtime"]);
    }
    /**
     *
     */
    public function testTouchFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->touch($path));
    }
    /**
     *
     */
    public function testChangePermissions() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $this->assertNotSame('0777', \Phabel\Target\Php80\Polyfill::substr(\decoct($stat['mode']), -4));
        $this->assertNull((yield $this->driver->changePermissions($path, 0777)));
        $stat = (yield $this->driver->getStatus($path));
        $this->assertSame('0777', \Phabel\Target\Php80\Polyfill::substr(\decoct($stat['mode']), -4));
    }
    /**
     *
     */
    public function testChangePermissionsFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->changePermissions($path, 0777));
    }
    /**
     *
     */
    public function testChangeOwner() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        (yield $this->driver->getStatus($path));
        $user = \fileowner($path);
        $this->assertNull((yield $this->driver->changeOwner($path, $user, null)));
    }
    /**
     *
     */
    public function testChangeOwnerFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->changeOwner($path, 0, null));
    }
    /**
     *
     */
    protected function setUp() : void
    {
        parent::setUp();
        $this->driver = new File\Filesystem($this->createDriver());
    }
    /**
     *
     */
    protected abstract function createDriver() : File\Driver;
    /**
     *
     */
    private function assertSameStatus(array $expected, array $actual) : void
    {
        $filter = function (array $stat) {
            $filtered = \array_filter($stat, function (string $key) : bool {
                return !\is_numeric($key);
            }, ARRAY_FILTER_USE_KEY);
            \ksort($filtered);
            return $filtered;
        };
        $this->assertSame($filter($expected), $filter($actual));
    }
    /**
     * @param array $stat
     *
     * @return string
     */
    private function getPermissionsFromStatus(array $stat) : string
    {
        return \Phabel\Target\Php80\Polyfill::substr(\decoct($stat["mode"]), 1);
    }
}<?php

namespace Amp\File\Test;

final class Fixture
{
    private static $fixtureId;
    /**
     *
     */
    public static function path() : string
    {
        if (empty(self::$fixtureId)) {
            self::$fixtureId = \uniqid('amphp-test-', true);
        }
        return \sys_get_temp_dir() . "/amphp_file_fixture/" . \str_replace("\\", ".", __CLASS__) . self::$fixtureId;
    }
    /**
     *
     */
    public static function init() : void
    {
        $fixtureDir = self::path();
        self::clear();
        if (!\mkdir($fixtureDir, $mode = 0777, $recursive = true)) {
            throw new \RuntimeException("Failed creating temporary test fixture directory: {$fixtureDir}");
        }
        if (!\mkdir($fixtureDir . "/dir", $mode = 0777, $recursive = true)) {
            throw new \RuntimeException("Failed creating temporary test fixture directory");
        }
        if (!\file_put_contents($fixtureDir . "/file", "small")) {
            throw new \RuntimeException("Failed creating temporary test fixture file");
        }
        if (!\symlink($fixtureDir . "/dir", $fixtureDir . "/dirlink")) {
            throw new \RuntimeException("Failed creating temporary test fixture symlink to directory");
        }
        if (!\symlink($fixtureDir . "/file", $fixtureDir . "/filelink")) {
            throw new \RuntimeException("Failed creating temporary test fixture symlink to file");
        }
        if (!\symlink($fixtureDir . "/linkloop", $fixtureDir . "/linkloop")) {
            throw new \RuntimeException("Failed creating temporary test fixture symlink loop");
        }
        if (\extension_loaded('posix')) {
            if (!\posix_mkfifo($fixtureDir . "/fifo", 0777)) {
                throw new \RuntimeException("Failed creating temporary test fixture fifo");
            }
            if (!\symlink($fixtureDir . "/fifo", $fixtureDir . "/fifolink")) {
                throw new \RuntimeException("Failed creating temporary test fixture symlink to file");
            }
        }
    }
    /**
     *
     */
    public static function clear() : void
    {
        \clearstatcache(true);
        $fixtureDir = self::path();
        if (!\file_exists($fixtureDir)) {
            return;
        }
        if (\stripos(\PHP_OS, "win") === 0) {
            \system('rd /Q /S "' . $fixtureDir . '"');
        } else {
            \system('/bin/rm -rf ' . \escapeshellarg($fixtureDir));
        }
        \clearstatcache(true);
    }
}<?php

namespace Amp\Sql;

abstract class ConnectionConfig
{
    const KEY_MAP = ['hostname' => 'host', 'username' => 'user', 'pass' => 'password', 'database' => 'db', 'dbname' => 'db'];
    /** @var string */
    private $host;
    /** @var int */
    private $port;
    /** @var string|null */
    private $user;
    /** @var string|null */
    private $password;
    /** @var string|null */
    private $database;
    /**
     * Parses a connection string into an array of keys and values given.
     *
     * @param string $connectionString
     * @param string[] $keymap Map of alternative key names to canonical key names.
     *
     * @return string[]
     */
    protected static function parseConnectionString(string $connectionString, array $keymap = self::KEY_MAP) : array
    {
        $values = [];
        $params = \explode(";", $connectionString);
        if (\count($params) === 1) {
            // Attempt to explode on a space if no ';' are found.
            $params = \explode(" ", $connectionString);
        }
        foreach ($params as $param) {
            list($key, $value) = \array_map("trim", \explode("=", $param, 2) + [1 => null]);
            if (isset($keymap[$key])) {
                $key = $keymap[$key];
            }
            $values[$key] = $value;
        }
        if (\preg_match('/^(.+):(\\d{1,5})$/', $values["host"] ?? "", $matches)) {
            $values["host"] = $matches[1];
            $values["port"] = $matches[2];
        }
        return $values;
    }
    /**
     *
     */
    public function __construct(string $host, int $port, string $user = null, string $password = null, string $database = null)
    {
        $this->host = $host;
        $this->port = $port;
        $this->user = $user;
        $this->password = $password;
        $this->database = $database;
    }
    /**
     *
     */
    public final function getHost() : string
    {
        return $this->host;
    }
    /**
     *
     */
    public final function withHost(string $host) : self
    {
        $new = clone $this;
        $new->host = $host;
        return $new;
    }
    /**
     *
     */
    public final function getPort() : int
    {
        return $this->port;
    }
    /**
     *
     */
    public final function withPort(int $port) : self
    {
        $new = clone $this;
        $new->port = $port;
        return $new;
    }
    /**
     * @return (string | null)
     */
    public final function getUser()
    {
        return $this->user;
    }
    /**
     *
     */
    public final function withUser(string $user = null) : self
    {
        $new = clone $this;
        $new->user = $user;
        return $new;
    }
    /**
     * @return (string | null)
     */
    public final function getPassword()
    {
        return $this->password;
    }
    /**
     *
     */
    public final function withPassword(string $password = null) : self
    {
        $new = clone $this;
        $new->password = $password;
        return $new;
    }
    /**
     * @return (string | null)
     */
    public final function getDatabase()
    {
        return $this->database;
    }
    /**
     *
     */
    public final function withDatabase(string $database = null) : self
    {
        $new = clone $this;
        $new->database = $database;
        return $new;
    }
}<?php

namespace Amp\Sql;

class PoolError extends \Error
{
}<?php

namespace Amp\Sql;

class FailureException extends \Exception
{
}<?php

namespace Amp\Sql;

interface TransientResource
{
    /**
     * Indicates if the resource is still valid.
     *
     * @return bool
     */
    public function isAlive() : bool;
    /**
     * Get the timestamp of the last usage of this resource.
     *
     * @return int Unix timestamp in seconds.
     */
    public function getLastUsedAt() : int;
}<?php

namespace Amp\Sql;

class TransactionError extends \Error
{
}<?php

namespace Amp\Sql;

class QueryError extends \Error
{
    protected $query = "";
    /**
     *
     */
    public function __construct(string $message, string $query = "", \Throwable $previous = null)
    {
        if ($query !== "") {
            $this->query = $query;
        }
        parent::__construct($message, 0, $previous);
    }
    /**
     *
     */
    public final function getQuery() : string
    {
        return $this->query;
    }
    /**
     *
     */
    public function __toString() : string
    {
        if ($this->query === "") {
            return parent::__toString();
        }
        $msg = $this->message;
        $this->message .= "\nCurrent query was {$this->query}";
        $str = parent::__toString();
        $this->message = $msg;
        return $str;
    }
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Pool extends Link
{
    /**
     * @return Promise<Link>
     */
    public function extractConnection() : Promise;
    /**
     * @return int Total number of active connections in the pool.
     */
    public function getConnectionCount() : int;
    /**
     * @return int Total number of idle connections in the pool.
     */
    public function getIdleConnectionCount() : int;
    /**
     * @return int Maximum number of connections this pool will create.
     */
    public function getConnectionLimit() : int;
    /**
     * @return int Number of seconds a connection may remain idle before it is automatically closed.
     */
    public function getIdleTimeout() : int;
}<?php

namespace Amp\Sql;

class ConnectionException extends FailureException
{
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Connector
{
    /**
     * @param ConnectionConfig $config
     *
     * @return Promise<Connection>
     */
    public function connect(ConnectionConfig $config) : Promise;
}<?php

namespace Amp\Sql;

use Amp\Iterator;
interface ResultSet extends Iterator
{
    /**
     * {@inheritdoc}
     *
     * @return array Map of row names to values.
     */
    public function getCurrent() : array;
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Executor extends TransientResource
{
    /**
     * @param string $sql SQL query to execute.
     *
     * @return Promise<(CommandResult | ResultSet)>
     *
     * @throws FailureException If the operation fails due to unexpected condition.
     * @throws ConnectionException If the connection to the database is lost.
     * @throws QueryError If the operation fails due to an error in the query (such as a syntax error).
     */
    public function query(string $sql) : Promise;
    /**
     * @param string $sql SQL query to prepare.
     *
     * @return Promise<Statement>
     *
     * @throws FailureException If the operation fails due to unexpected condition.
     * @throws ConnectionException If the connection to the database is lost.
     * @throws QueryError If the operation fails due to an error in the query (such as a syntax error).
     */
    public function prepare(string $sql) : Promise;
    /**
     * @param string $sql SQL query to prepare and execute.
     * @param mixed[] $params Query parameters.
     *
     * @return Promise<(CommandResult | ResultSet)>
     *
     * @throws FailureException If the operation fails due to unexpected condition.
     * @throws ConnectionException If the connection to the database is lost.
     * @throws QueryError If the operation fails due to an error in the query (such as a syntax error).
     */
    public function execute(string $sql, array $params = []) : Promise;
    /**
     * Closes the executor. No further queries may be performed.
     */
    public function close();
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Link extends Executor
{
    /**
     * Starts a transaction on a single connection.
     *
     * @param int $isolation Transaction isolation level.
     *
     * @return Promise<Transaction>
     */
    public function beginTransaction(int $isolation = Transaction::ISOLATION_COMMITTED) : Promise;
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Transaction extends Executor
{
    const ISOLATION_UNCOMMITTED = 0;
    const ISOLATION_COMMITTED = 1;
    const ISOLATION_REPEATABLE = 2;
    const ISOLATION_SERIALIZABLE = 4;
    /**
     * @return int
     */
    public function getIsolationLevel() : int;
    /**
     * @return bool True if the transaction is active, false if it has been committed or rolled back.
     */
    public function isActive() : bool;
    /**
     * Commits the transaction and makes it inactive.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function commit() : Promise;
    /**
     * Rolls back the transaction and makes it inactive.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollback() : Promise;
    /**
     * Creates a savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function createSavepoint(string $identifier) : Promise;
    /**
     * Rolls back to the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollbackTo(string $identifier) : Promise;
    /**
     * Releases the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function releaseSavepoint(string $identifier) : Promise;
}<?php

namespace Amp\Sql;

interface CommandResult
{
    /**
     * Returns the number of rows affected by the query.
     *
     * @return int
     */
    public function getAffectedRowCount() : int;
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Statement extends TransientResource
{
    /**
     * @param mixed[] $params
     *
     * @return Promise<(CommandResult | ResultSet)>
     */
    public function execute(array $params = []) : Promise;
    /**
     * @return string The SQL string used to prepare the statement.
     */
    public function getQuery() : string;
}{
    "name": "amphp/sql",
    "description": "Asynchronous SQL client for Amp.",
    "keywords": [
        "database",
        "db",
        "sql",
        "asynchronous",
        "async"
    ],
    "homepage": "http://amphp.org",
    "license": "MIT",
    "require": {
        "php": ">=7",
        "amphp/amp": "^2"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master",
        "amphp/phpunit-util": "^1",
        "phpunit/phpunit": "^6"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Sql\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Sql\\Test\\": "test"
        }
    },
    "config": {
        "platform": {
            "php": "7.0.0"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "phpunit --coverage-text"
    }
}
<?php

namespace Amp\Sql\Test;

use Amp\PHPUnit\TestCase;
use Amp\Sql\QueryError;
class QueryErrorTest extends TestCase
{
    /**
     * @test
     */
    public function testItPassesQueryAlong()
    {
        $error = new QueryError('error', 'SELECT * FROM foo');
        $this->assertSame('SELECT * FROM foo', $error->getQuery());
        $this->assertStringStartsWith("Amp\\Sql\\QueryError: error\nCurrent query was SELECT * FROM foo", (string) $error);
    }
}<?php

namespace Amp\Websocket;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\ByteStream\IteratorStream;
use Amp\ByteStream\StreamException;
use Amp\Coroutine;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Loop;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\Socket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Success;
use cash\LRUCache;
use function Amp\call;
use function Amp\getCurrentTime;
final class Rfc6455Client implements Client
{
    /** @var self[] */
    private static $clients = [];
    /** @var int[] */
    private static $bytesReadInLastSecond = [];
    /** @var int[] */
    private static $framesReadInLastSecond = [];
    /** @var Deferred[] */
    private static $rateDeferreds = [];
    /** @var string|null */
    private static $watcher;
    /** @var LRUCache&\IteratorAggregate Least-recently-used cache of next ping (heartbeat) times. */
    private static $heartbeatTimeouts;
    /** @var int Cached current time. */
    private static $now;
    /** @var Options */
    private $options;
    /** @var Socket */
    private $socket;
    /** @var Promise|null */
    private $lastWrite;
    /** @var Promise|null */
    private $lastEmit;
    /** @var bool */
    private $masked;
    /** @var CompressionContext|null */
    private $compressionContext;
    /** @var Emitter|null */
    private $currentMessageEmitter;
    /** @var Deferred|null */
    private $nextMessageDeferred;
    /** @var Message[] */
    private $messages = [];
    /** @var callable[]|null */
    private $onClose = [];
    /** @var ClientMetadata */
    private $metadata;
    /** @var Deferred|null */
    private $closeDeferred;
    /**
     * @param Socket $socket
     * @param Options $options
     * @param bool $masked True for client, false for server.
     * @param (CompressionContext | null) $compression
     */
    public function __construct(Socket $socket, Options $options, bool $masked, ?CompressionContext $compression = null)
    {
        $this->socket = $socket;
        $this->options = $options;
        $this->masked = $masked;
        $this->compressionContext = $compression;
        $this->closeDeferred = new Deferred();
        if (self::$watcher === null) {
            self::$now = getCurrentTime();
            self::$heartbeatTimeouts = new class(\PHP_INT_MAX) extends LRUCache implements \IteratorAggregate
            {
                /**
                 *
                 */
                public function getIterator() : \Iterator
                {
                    yield from $this->data;
                }
            };
            self::$watcher = Loop::repeat(1000, static function () : void {
                self::$now = getCurrentTime();
                self::$bytesReadInLastSecond = [];
                self::$framesReadInLastSecond = [];
                if (!empty(self::$rateDeferreds)) {
                    /** @psalm-suppress PossiblyNullArgument */
                    Loop::unreference(self::$watcher);
                    $rateDeferreds = self::$rateDeferreds;
                    self::$rateDeferreds = [];
                    foreach ($rateDeferreds as $deferred) {
                        $deferred->resolve();
                    }
                }
                foreach (self::$heartbeatTimeouts as $clientId => $expiryTime) {
                    if ($expiryTime >= self::$now) {
                        break;
                    }
                    $client = self::$clients[$clientId];
                    self::$heartbeatTimeouts->put($clientId, self::$now + $client->options->getHeartbeatPeriod() * 1000);
                    if ($client->getUnansweredPingCount() > $client->options->getQueuedPingLimit()) {
                        $client->close(Code::POLICY_VIOLATION, 'Exceeded unanswered PING limit');
                        continue;
                    }
                    $client->ping();
                }
            });
            Loop::unreference(self::$watcher);
        }
        $this->metadata = new ClientMetadata(self::$now, $compression !== null);
        self::$clients[$this->metadata->id] = $this;
        if ($this->options->isHeartbeatEnabled()) {
            self::$heartbeatTimeouts->put($this->metadata->id, self::$now + $this->options->getHeartbeatPeriod() * 1000);
        }
        Promise\rethrow(new Coroutine($this->read()));
    }
    /**
     *
     */
    public function receive() : Promise
    {
        if ($this->nextMessageDeferred) {
            throw new \Error('Await the previous promise returned from receive() before calling receive() again.');
        }
        // There might be messages already buffered and a close frame already received
        if ($this->messages) {
            $message = \reset($this->messages);
            unset($this->messages[\key($this->messages)]);
            return new Success($message);
        }
        if ($this->metadata->closedAt) {
            return new Success();
        }
        $this->nextMessageDeferred = new Deferred();
        return $this->nextMessageDeferred->promise();
    }
    /**
     *
     */
    public function getId() : int
    {
        return $this->metadata->id;
    }
    /**
     *
     */
    public function getUnansweredPingCount() : int
    {
        return $this->metadata->pingCount - $this->metadata->pongCount;
    }
    /**
     *
     */
    public function isConnected() : bool
    {
        return !$this->metadata->closedAt;
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->socket->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->socket->getRemoteAddress();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->socket instanceof EncryptableSocket ? $this->socket->getTlsInfo() : null;
    }
    /**
     *
     */
    public function getCloseCode() : int
    {
        if ($this->metadata->closeCode === null) {
            throw new \Error('The client has not closed');
        }
        return $this->metadata->closeCode;
    }
    /**
     *
     */
    public function getCloseReason() : string
    {
        if ($this->metadata->closeReason === null) {
            throw new \Error('The client has not closed');
        }
        return $this->metadata->closeReason;
    }
    /**
     *
     */
    public function isClosedByPeer() : bool
    {
        if (!$this->metadata->closedAt) {
            throw new \Error('The client has not closed');
        }
        return $this->metadata->closedByPeer;
    }
    /**
     *
     */
    public function getOptions() : Options
    {
        return $this->options;
    }
    /**
     *
     */
    public function getInfo() : ClientMetadata
    {
        return clone $this->metadata;
    }
    /**
     *
     */
    private function read() : \Generator
    {
        $maxFramesPerSecond = $this->options->getFramesPerSecondLimit();
        $maxBytesPerSecond = $this->options->getBytesPerSecondLimit();
        $heartbeatEnabled = $this->options->isHeartbeatEnabled();
        $heartbeatPeriod = $this->options->getHeartbeatPeriod() * 1000;
        $parser = $this->parser();
        try {
            while (($chunk = (yield $this->socket->read())) !== null) {
                if ($chunk === '') {
                    continue;
                }
                $this->metadata->lastReadAt = self::$now;
                $this->metadata->bytesRead += \strlen($chunk);
                self::$bytesReadInLastSecond[$this->metadata->id] = (self::$bytesReadInLastSecond[$this->metadata->id] ?? 0) + \strlen($chunk);
                if ($heartbeatEnabled) {
                    self::$heartbeatTimeouts->put($this->metadata->id, self::$now + $heartbeatPeriod);
                }
                $parser->send($chunk);
                $chunk = '';
                // Free memory from last chunk read.
                if ((self::$framesReadInLastSecond[$this->metadata->id] ?? 0) >= $maxFramesPerSecond || self::$bytesReadInLastSecond[$this->metadata->id] >= $maxBytesPerSecond) {
                    /** @psalm-suppress PossiblyNullArgument */
                    Loop::reference(self::$watcher);
                    // Reference watcher to keep loop running until rate limit released.
                    self::$rateDeferreds[$this->metadata->id] = $deferred = new Deferred();
                    (yield $deferred->promise());
                }
                if ($this->lastEmit && !$this->metadata->closedAt) {
                    (yield $this->lastEmit);
                }
            }
        } catch (\Throwable $exception) {
            $message = 'TCP connection closed with exception: ' . $exception->getMessage();
        }
        if ($this->closeDeferred !== null) {
            $deferred = $this->closeDeferred;
            $this->closeDeferred = null;
            $deferred->resolve();
        }
        if (!$this->metadata->closedAt) {
            $this->metadata->closedByPeer = true;
            $this->close(Code::ABNORMAL_CLOSE, $message ?? 'TCP connection closed unexpectedly');
        }
    }
    /**
     *
     */
    private function onData(int $opcode, string $data, bool $terminated) : void
    {
        // Ignore further data received after initiating close.
        if ($this->metadata->closedAt) {
            return;
        }
        $this->metadata->lastDataReadAt = self::$now;
        ++$this->metadata->framesRead;
        self::$framesReadInLastSecond[$this->metadata->id] = (self::$framesReadInLastSecond[$this->metadata->id] ?? 0) + 1;
        if (!$this->currentMessageEmitter) {
            if ($opcode === Opcode::CONT) {
                $this->onError(Code::PROTOCOL_ERROR, 'Illegal CONTINUATION opcode; initial message payload frame must be TEXT or BINARY');
                return;
            }
            if ($terminated) {
                $stream = new InMemoryStream($data);
                ++$this->metadata->messagesRead;
            } else {
                $this->currentMessageEmitter = new Emitter();
                $stream = new IteratorStream($this->currentMessageEmitter->iterate());
            }
            if ($opcode === Opcode::BIN) {
                $message = Message::fromBinary($stream);
            } else {
                $message = Message::fromText($stream);
            }
            if ($this->nextMessageDeferred) {
                $deferred = $this->nextMessageDeferred;
                $this->nextMessageDeferred = null;
                $deferred->resolve($message);
            } else {
                $this->messages[] = $message;
            }
            if ($terminated) {
                return;
            }
        } elseif ($opcode !== Opcode::CONT) {
            $this->onError(Code::PROTOCOL_ERROR, 'Illegal data type opcode after unfinished previous data type frame; opcode MUST be CONTINUATION');
            return;
        }
        $promise = $this->currentMessageEmitter->emit($data);
        $this->lastEmit = $this->nextMessageDeferred ? null : $promise;
        if ($terminated) {
            $emitter = $this->currentMessageEmitter;
            $this->currentMessageEmitter = null;
            $emitter->complete();
            ++$this->metadata->messagesRead;
        }
    }
    /**
     *
     */
    private function onControlFrame(int $opcode, string $data) : void
    {
        // Close already completed, so ignore any further data from the parser.
        if ($this->metadata->closedAt && $this->closeDeferred === null) {
            return;
        }
        ++$this->metadata->framesRead;
        self::$framesReadInLastSecond[$this->metadata->id] = (self::$framesReadInLastSecond[$this->metadata->id] ?? 0) + 1;
        switch ($opcode) {
            case Opcode::CLOSE:
                if ($this->closeDeferred) {
                    $deferred = $this->closeDeferred;
                    $this->closeDeferred = null;
                    $deferred->resolve();
                }
                if ($this->metadata->closedAt) {
                    break;
                }
                $this->metadata->closedByPeer = true;
                $length = \strlen($data);
                if ($length === 0) {
                    $code = Code::NONE;
                    $reason = '';
                } elseif ($length < 2) {
                    $code = Code::PROTOCOL_ERROR;
                    $reason = 'Close code must be two bytes';
                } else {
                    $code = \current(\unpack('n', \Phabel\Target\Php80\Polyfill::substr($data, 0, 2)));
                    $reason = \Phabel\Target\Php80\Polyfill::substr($data, 2);
                    if ($code < 1000 || $code >= 1004 && $code <= 1006 || $code >= 1014 && $code <= 1015 || $code >= 1016 && $code <= 1999 || $code >= 2000 && $code <= 2999 || $code >= 5000) {
                        $code = Code::PROTOCOL_ERROR;
                        $reason = 'Invalid close code';
                    } elseif ($this->options->isValidateUtf8() && !\preg_match('//u', $reason)) {
                        $code = Code::INCONSISTENT_FRAME_DATA_TYPE;
                        $reason = 'Close reason must be valid UTF-8';
                    }
                }
                $this->close($code, $reason);
                break;
            case Opcode::PING:
                $this->write($data, Opcode::PONG);
                break;
            case Opcode::PONG:
                if (!\preg_match('/^[1-9][0-9]*$/', $data)) {
                    // Ignore pong payload that is not an integer.
                    break;
                }
                // We need a min() here, else someone might just send a pong frame with a very high pong count and
                // leave TCP connection in open state... Then we'd accumulate connections which never are cleaned up...
                $this->metadata->pongCount = \min($this->metadata->pingCount, (int) $data);
                break;
        }
    }
    /**
     *
     */
    private function onError(int $code, string $reason) : void
    {
        $this->close($code, $reason);
    }
    /**
     *
     */
    public function send(string $data) : Promise
    {
        \assert((bool) \preg_match('//u', $data), 'Text data must be UTF-8');
        return $this->lastWrite = new Coroutine($this->sendData($data, Opcode::TEXT));
    }
    /**
     *
     */
    public function sendBinary(string $data) : Promise
    {
        return $this->lastWrite = new Coroutine($this->sendData($data, Opcode::BIN));
    }
    /**
     *
     */
    public function stream(InputStream $stream) : Promise
    {
        return $this->lastWrite = new Coroutine($this->sendStream($stream, Opcode::TEXT));
    }
    /**
     *
     */
    public function streamBinary(InputStream $stream) : Promise
    {
        return $this->lastWrite = new Coroutine($this->sendStream($stream, Opcode::BIN));
    }
    /**
     *
     */
    public function ping() : Promise
    {
        $this->metadata->lastHeartbeatAt = self::$now;
        ++$this->metadata->pingCount;
        return $this->write((string) $this->metadata->pingCount, Opcode::PING);
    }
    /**
     *
     */
    private function sendData(string $data, int $opcode) : \Generator
    {
        if ($this->lastWrite) {
            (yield $this->lastWrite);
        }
        ++$this->metadata->messagesSent;
        $this->metadata->lastDataSentAt = self::$now;
        $rsv = 0;
        $compress = false;
        if ($this->compressionContext && $opcode === Opcode::TEXT && \strlen($data) > $this->compressionContext->getCompressionThreshold()) {
            $rsv |= $this->compressionContext->getRsv();
            $compress = true;
        }
        try {
            if (\strlen($data) > $this->options->getFrameSplitThreshold()) {
                $length = \strlen($data);
                $slices = (int) \ceil($length / $this->options->getFrameSplitThreshold());
                $length = (int) \ceil($length / $slices);
                for ($i = 0; $i < $slices - 1; ++$i) {
                    $chunk = \Phabel\Target\Php80\Polyfill::substr($data, $length * $i, $length);
                    if ($compress) {
                        /** @psalm-suppress PossiblyNullReference */
                        $chunk = $this->compressionContext->compress($chunk, false);
                    }
                    (yield $this->write($chunk, $opcode, $rsv, false));
                    $opcode = Opcode::CONT;
                    $rsv = 0;
                    // RSV must be 0 in continuation frames.
                }
                $data = \Phabel\Target\Php80\Polyfill::substr($data, $length * $i, $length);
            }
            if ($compress) {
                /** @psalm-suppress PossiblyNullReference */
                $data = $this->compressionContext->compress($data, true);
            }
            (yield $this->write($data, $opcode, $rsv, true));
        } catch (StreamException $exception) {
            $code = Code::ABNORMAL_CLOSE;
            $reason = 'Writing to the client failed';
            (yield $this->close($code, $reason));
            throw new ClosedException('Client unexpectedly closed', $code, $reason);
        }
    }
    /**
     *
     */
    private function sendStream(InputStream $stream, int $opcode) : \Generator
    {
        if ($this->lastWrite) {
            (yield $this->lastWrite);
        }
        $rsv = 0;
        $compress = false;
        if ($this->compressionContext && $opcode === Opcode::TEXT) {
            $rsv |= $this->compressionContext->getRsv();
            $compress = true;
        }
        try {
            $buffer = (yield $stream->read());
            if ($buffer === null) {
                return (yield $this->write('', $opcode, 0, true));
            }
            $streamThreshold = $this->options->getStreamThreshold();
            while (($chunk = (yield $stream->read())) !== null) {
                if ($chunk === '') {
                    continue;
                }
                if (\strlen($buffer) < $streamThreshold) {
                    $buffer .= $chunk;
                    continue;
                }
                if ($compress) {
                    /** @psalm-suppress PossiblyNullReference */
                    $buffer = $this->compressionContext->compress($buffer, false);
                }
                (yield $this->write($buffer, $opcode, $rsv, false));
                $opcode = Opcode::CONT;
                $rsv = 0;
                // RSV must be 0 in continuation frames.
                $buffer = $chunk;
            }
            if ($compress) {
                /** @psalm-suppress PossiblyNullReference */
                $buffer = $this->compressionContext->compress($buffer, true);
            }
            (yield $this->write($buffer, $opcode, $rsv, true));
        } catch (StreamException $exception) {
            $code = Code::ABNORMAL_CLOSE;
            $reason = 'Writing to the client failed';
            (yield $this->close($code, $reason));
            throw new ClosedException('Client unexpectedly closed', $code, $reason);
        } catch (\Throwable $exception) {
            (yield $this->close(Code::UNEXPECTED_SERVER_ERROR, 'Error while reading message data'));
            throw $exception;
        }
    }
    /**
     *
     */
    private function write(string $data, int $opcode, int $rsv = 0, bool $isFinal = true) : Promise
    {
        if ($this->metadata->closedAt) {
            return new Success(0);
        }
        $frame = $this->compile($data, $opcode, $rsv, $isFinal);
        ++$this->metadata->framesSent;
        $this->metadata->bytesSent += \strlen($frame);
        $this->metadata->lastSentAt = self::$now;
        return $this->socket->write($frame);
    }
    /**
     *
     */
    private function compile(string $data, int $opcode, int $rsv, bool $isFinal) : string
    {
        $length = \strlen($data);
        $w = \chr((int) $isFinal << 7 | $rsv << 4 | $opcode);
        $maskFlag = $this->masked ? 0x80 : 0;
        if ($length > 0xffff) {
            $w .= \chr(0x7f | $maskFlag) . \pack('J', $length);
        } elseif ($length > 0x7d) {
            $w .= \chr(0x7e | $maskFlag) . \pack('n', $length);
        } else {
            $w .= \chr($length | $maskFlag);
        }
        if ($this->masked) {
            $mask = \random_bytes(4);
            return $w . $mask . ($data ^ \str_repeat($mask, $length + 3 >> 2));
        }
        return $w . $data;
    }
    /**
     *
     */
    public function close(int $code = Code::NORMAL_CLOSE, string $reason = '') : Promise
    {
        if ($this->metadata->closedAt) {
            return new Success([$this->metadata->closeCode, $this->metadata->closeReason]);
        }
        return call(function () use($code, $reason) {
            try {
                \assert($code !== Code::NONE || $reason === '');
                $promise = $this->write($code !== Code::NONE ? \pack('n', $code) . $reason : '', Opcode::CLOSE);
                $this->metadata->closedAt = self::$now;
                $this->metadata->closeCode = $code;
                $this->metadata->closeReason = $reason;
                if ($this->currentMessageEmitter) {
                    $emitter = $this->currentMessageEmitter;
                    $this->currentMessageEmitter = null;
                    $emitter->fail(new ClosedException('Connection closed while streaming message body', $code, $reason));
                }
                if ($this->nextMessageDeferred) {
                    $deferred = $this->nextMessageDeferred;
                    $this->nextMessageDeferred = null;
                    switch ($code) {
                        case Code::NORMAL_CLOSE:
                        case Code::NONE:
                            $deferred->resolve();
                            break;
                        default:
                            $deferred->fail(new ClosedException('Connection closed abnormally while awaiting message', $code, $reason));
                            break;
                    }
                }
                (yield $promise);
                // Wait for writing close frame to complete.
                if ($this->closeDeferred !== null) {
                    // Wait for peer close frame for configured number of seconds.
                    (yield Promise\timeout($this->closeDeferred->promise(), $this->options->getClosePeriod() * 1000));
                }
            } catch (\Throwable $exception) {
                // Failed to write close frame or to receive response frame, but we were disconnecting anyway.
            }
            $this->socket->close();
            $this->lastWrite = null;
            $this->lastEmit = null;
            $onClose = $this->onClose;
            $this->onClose = null;
            if ($onClose !== null) {
                foreach ($onClose as $callback) {
                    Promise\rethrow(call($callback, $this, $code, $reason));
                }
            }
            unset(self::$clients[$this->metadata->id]);
            self::$heartbeatTimeouts->remove($this->metadata->id);
            if (empty(self::$clients)) {
                /** @psalm-suppress PossiblyNullArgument */
                Loop::cancel(self::$watcher);
                self::$watcher = null;
                self::$heartbeatTimeouts = null;
            }
            return [$this->metadata->closeCode, $this->metadata->closeReason];
        });
    }
    /**
     *
     */
    public function onClose(callable $callback) : void
    {
        if ($this->onClose === null) {
            Promise\rethrow(call($callback, $this, $this->metadata->closeCode, $this->metadata->closeReason));
            return;
        }
        $this->onClose[] = $callback;
    }
    /**
     * A stateful generator websocket frame parser.
     *
     * @return \Generator
     */
    private function parser() : \Generator
    {
        $frameSizeLimit = $this->options->getFrameSizeLimit();
        $messageSizeLimit = $this->options->getMessageSizeLimit();
        $textOnly = $this->options->isTextOnly();
        $doUtf8Validation = $validateUtf8 = $this->options->isValidateUtf8();
        $compressionContext = $this->compressionContext;
        $compressedFlag = $compressionContext ? $compressionContext->getRsv() : 0;
        $dataMsgBytesRecd = 0;
        $savedBuffer = '';
        $compressed = false;
        $buffer = yield;
        $offset = 0;
        $bufferSize = \strlen($buffer);
        while (true) {
            $payload = '';
            // Free memory from last frame payload.
            while ($bufferSize < 2) {
                $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset);
                $offset = 0;
                $buffer .= yield;
                $bufferSize = \strlen($buffer);
            }
            $firstByte = \ord($buffer[$offset]);
            $secondByte = \ord($buffer[$offset + 1]);
            $offset += 2;
            $bufferSize -= 2;
            $final = (bool) ($firstByte & 0b10000000);
            $rsv = ($firstByte & 0b1110000) >> 4;
            $opcode = $firstByte & 0b1111;
            $isMasked = (bool) ($secondByte & 0b10000000);
            $maskingKey = '';
            $frameLength = $secondByte & 0b1111111;
            if ($opcode >= 3 && $opcode <= 7) {
                $this->onError(Code::PROTOCOL_ERROR, 'Use of reserved non-control frame opcode');
                return;
            }
            if ($opcode >= 11 && $opcode <= 15) {
                $this->onError(Code::PROTOCOL_ERROR, 'Use of reserved control frame opcode');
                return;
            }
            $isControlFrame = $opcode >= 0x8;
            if ($isControlFrame || $opcode === Opcode::CONT) {
                // Control and continuation frames
                if ($rsv !== 0) {
                    $this->onError(Code::PROTOCOL_ERROR, 'RSV must be 0 for control or continuation frames');
                    return;
                }
            } else {
                // Text and binary frames
                if ($rsv !== 0 && (!$compressionContext || $rsv & ~$compressedFlag)) {
                    $this->onError(Code::PROTOCOL_ERROR, 'Invalid RSV value for negotiated extensions');
                    return;
                }
                $doUtf8Validation = $validateUtf8 && $opcode === Opcode::TEXT;
                $compressed = (bool) ($rsv & $compressedFlag);
            }
            if ($frameLength === 0x7e) {
                while ($bufferSize < 2) {
                    $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset);
                    $offset = 0;
                    $buffer .= yield;
                    $bufferSize = \strlen($buffer);
                }
                $frameLength = \unpack('n', $buffer[$offset] . $buffer[$offset + 1])[1];
                $offset += 2;
                $bufferSize -= 2;
            } elseif ($frameLength === 0x7f) {
                while ($bufferSize < 8) {
                    $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset);
                    $offset = 0;
                    $buffer .= yield;
                    $bufferSize = \strlen($buffer);
                }
                $lengthLong32Pair = \unpack('N2', \Phabel\Target\Php80\Polyfill::substr($buffer, $offset, 8));
                $offset += 8;
                $bufferSize -= 8;
                if (\PHP_INT_MAX === 0x7fffffff) {
                    if ($lengthLong32Pair[1] !== 0 || $lengthLong32Pair[2] < 0) {
                        $this->onError(Code::MESSAGE_TOO_LARGE, 'Received payload exceeds maximum allowable size');
                        return;
                    }
                    $frameLength = $lengthLong32Pair[2];
                } else {
                    $frameLength = $lengthLong32Pair[1] << 32 | $lengthLong32Pair[2];
                    if ($frameLength < 0) {
                        $this->onError(Code::PROTOCOL_ERROR, 'Most significant bit of 64-bit length field set');
                        return;
                    }
                }
            }
            if ($frameLength > 0 && $isMasked === $this->masked) {
                $this->onError(Code::PROTOCOL_ERROR, 'Payload mask error');
                return;
            }
            if ($isControlFrame) {
                if (!$final) {
                    $this->onError(Code::PROTOCOL_ERROR, 'Illegal control frame fragmentation');
                    return;
                }
                if ($frameLength > 125) {
                    $this->onError(Code::PROTOCOL_ERROR, 'Control frame payload must be of maximum 125 bytes or less');
                    return;
                }
            }
            if ($frameSizeLimit && $frameLength > $frameSizeLimit) {
                $this->onError(Code::MESSAGE_TOO_LARGE, 'Received payload exceeds maximum allowable size');
                return;
            }
            if ($messageSizeLimit && $frameLength + $dataMsgBytesRecd > $messageSizeLimit) {
                $this->onError(Code::MESSAGE_TOO_LARGE, 'Received payload exceeds maximum allowable size');
                return;
            }
            if ($textOnly && $opcode === Opcode::BIN) {
                $this->onError(Code::UNACCEPTABLE_TYPE, 'BINARY opcodes (0x02) not accepted');
                return;
            }
            if ($isMasked) {
                while ($bufferSize < 4) {
                    $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset);
                    $offset = 0;
                    $buffer .= yield;
                    $bufferSize = \strlen($buffer);
                }
                $maskingKey = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset, 4);
                $offset += 4;
                $bufferSize -= 4;
            }
            while ($bufferSize < $frameLength) {
                $chunk = yield;
                $buffer .= $chunk;
                $bufferSize += \strlen($chunk);
            }
            $payload = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset, $frameLength);
            $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset + $frameLength);
            $offset = 0;
            $bufferSize = \strlen($buffer);
            if ($isMasked) {
                // This is memory hungry but it's ~70x faster than iterating byte-by-byte
                // over the masked string. Deal with it; manual iteration is untenable.
                /** @psalm-suppress InvalidOperand String operands expected. */
                $payload ^= \str_repeat($maskingKey, $frameLength + 3 >> 2);
            }
            if ($isControlFrame) {
                $this->onControlFrame($opcode, $payload);
                continue;
            }
            $dataMsgBytesRecd += $frameLength;
            if ($savedBuffer !== '') {
                $payload = $savedBuffer . $payload;
                $savedBuffer = '';
            }
            if ($compressed) {
                /** @psalm-suppress PossiblyNullReference */
                $payload = $compressionContext->decompress($payload, $final);
                if ($payload === null) {
                    // Decompression failed.
                    $this->onError(Code::PROTOCOL_ERROR, 'Invalid compressed data');
                    return;
                }
            }
            if ($doUtf8Validation) {
                if ($final) {
                    $valid = \preg_match('//u', $payload);
                } else {
                    for ($i = 0; !($valid = \preg_match('//u', $payload)); $i++) {
                        $savedBuffer = \Phabel\Target\Php80\Polyfill::substr($payload, -1) . $savedBuffer;
                        $payload = \Phabel\Target\Php80\Polyfill::substr($payload, 0, -1);
                        if ($i === 3) {
                            // Remove a maximum of three bytes
                            break;
                        }
                    }
                }
                /** @psalm-suppress PossiblyUndefinedVariable Defined in either condition above. */
                if (!$valid) {
                    $this->onError(Code::INCONSISTENT_FRAME_DATA_TYPE, 'Invalid TEXT data; UTF-8 required');
                    return;
                }
            }
            if ($final) {
                $dataMsgBytesRecd = 0;
            }
            $this->onData($opcode, $payload, $final);
        }
    }
}<?php

namespace Amp\Websocket;

final class Rfc7692CompressionFactory implements CompressionContextFactory
{
    /**
     *
     */
    public function fromClientHeader(string $headerIn, ?string &$headerOut) : ?CompressionContext
    {
        return Rfc7692Compression::fromClientHeader($headerIn, $headerOut);
    }
    /**
     *
     */
    public function fromServerHeader(string $header) : ?CompressionContext
    {
        return Rfc7692Compression::fromServerHeader($header);
    }
    /**
     *
     */
    public function createRequestHeader() : string
    {
        return Rfc7692Compression::createRequestHeader();
    }
}<?php

namespace Amp\Websocket;

interface CompressionContextFactory
{
    /**
     * Create a compression context from a header received from a websocket client request.
     *
     * @param string $headerIn Header from request.
     * @param string $headerOut Sec-Websocket-Extension response header.
     *
     * @return (CompressionContext | null)
     */
    public function fromClientHeader(string $headerIn, ?string &$headerOut) : ?CompressionContext;
    /**
     * Create a compression context from a header received from a websocket server response.
     *
     * @param string $header Header from response.
     *
     * @return (CompressionContext | null)
     */
    public function fromServerHeader(string $header) : ?CompressionContext;
    /**
     * @return string Header value for Sec-Websocket-Extension header.
     */
    public function createRequestHeader() : string;
}<?php

namespace Amp\Websocket;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\Payload;
use Amp\Promise;
/**
 * This class allows streamed and buffered access to the websocket message.
 */
final class Message implements InputStream
{
    /** @var Payload */
    private $stream;
    /** @var bool */
    private $binary;
    /**
     * Create a Message from a UTF-8 text stream.
     *
     * @param InputStream $stream UTF-8 text stream.
     *
     * @return self
     */
    public static function fromText(InputStream $stream) : self
    {
        return new self($stream, false);
    }
    /**
     * Create a Message from a binary stream.
     *
     * @param InputStream $stream Binary stream.
     *
     * @return self
     */
    public static function fromBinary(InputStream $stream) : self
    {
        return new self($stream, true);
    }
    /**
     *
     */
    private function __construct(InputStream $stream, bool $binary)
    {
        $this->stream = new Payload($stream);
        $this->binary = $binary;
    }
    /**
     * @return bool True if the message is UTF-8 text, false if it is binary.
     *
     * @see Message::isBinary()
     */
    public function isText() : bool
    {
        return !$this->binary;
    }
    /**
     * @return bool True if the message is binary, false if it is UTF-8 text.
     *
     * @see Message::isText()
     */
    public function isBinary() : bool
    {
        return $this->binary;
    }
    /**
     *
     */
    public function read() : Promise
    {
        return $this->stream->read();
    }
    /**
     *
     */
    public function buffer() : Promise
    {
        return $this->stream->buffer();
    }
}<?php

namespace Amp\Websocket;

final class Options
{
    /** @var int */
    private $streamThreshold = 32768;
    // 32KB
    /** @var int */
    private $frameSplitThreshold = 32768;
    // 32KB
    /** @var int */
    private $bytesPerSecondLimit = 1048576;
    // 1MB
    /** @var int */
    private $framesPerSecondLimit = 100;
    /** @var int */
    private $frameSizeLimit = 2097152;
    // 2MB
    /** @var int */
    private $messageSizeLimit = 10485760;
    // 10MB
    /** @var bool */
    private $textOnly = false;
    /** @var bool */
    private $validateUtf8 = true;
    /** @var int */
    private $closePeriod = 3;
    /** @var bool */
    private $compressionEnabled = false;
    /** @var bool */
    private $heartbeatEnabled = true;
    /** @var int */
    private $heartbeatPeriod = 10;
    /** @var int */
    private $queuedPingLimit = 3;
    /**
     * Creates an Options object with values as documented on the accessor methods.
     *
     * @return self
     */
    public static function createServerDefault() : self
    {
        return new self();
        // Initial parameter values already tuned for servers.
    }
    /**
    * Creates an Options object with values as documented on the accessor methods except for the changes below.
    *
    * Compression is enabled if the zlib extension is installed.
    Bytes per second limit is set to PHP_INT_MAX (effectively removing the limit).
    Frames per second limit is set to PHP_INI_MAX (effectively removing the limit).
    Message size limit is set to 1 GB.
    Frame size limit is set to 100 MB.
    *
    * @return self
    */
    public static function createClientDefault() : self
    {
        $options = new self();
        $options->bytesPerSecondLimit = \PHP_INT_MAX;
        $options->framesPerSecondLimit = \PHP_INT_MAX;
        $options->messageSizeLimit = 2 ** 30;
        // 1 GB
        $options->frameSizeLimit = 2 ** 20 * 100;
        // 100 MB
        if (\extension_loaded('zlib')) {
            $options->compressionEnabled = true;
        }
        return $options;
    }
    /**
     *
     */
    private function __construct()
    {
        // Private constructor to require use of named constructors.
    }
    /**
    * @return int Number of bytes that will be buffered when streaming a message
    body before sending a frame.
    */
    public function getStreamThreshold() : int
    {
        return $this->streamThreshold;
    }
    /**
    * @param int $streamThreshold Number of bytes that will be buffered when
    streaming a message body before sending a frame. Default is 32768 (32KB)
    *
    * @return self
    *
    * @throws \Error if the number is less than 1.
    */
    public function withStreamThreshold(int $streamThreshold) : self
    {
        if ($streamThreshold < 1) {
            throw new \Error('$streamThreshold must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->streamThreshold = $streamThreshold;
        return $clone;
    }
    /**
    * @return int If a message exceeds this number of bytes, it is split into
    multiple frames, each no bigger than this value.
    */
    public function getFrameSplitThreshold() : int
    {
        return $this->frameSplitThreshold;
    }
    /**
    * @param int $frameSplitThreshold If a message exceeds this number of bytes,
    it is split into multiple frames, each no bigger than this value.
    Default is 32768 (32KB)
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withFrameSplitThreshold(int $frameSplitThreshold) : self
    {
        if ($frameSplitThreshold < 1) {
            throw new \Error('$frameSplitThreshold must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->frameSplitThreshold = $frameSplitThreshold;
        return $clone;
    }
    /**
    * @return int Maximum frame size that can be received from the peer. If a
    larger frame is received, the connection is ended with a POLICY_VIOLATION.
    */
    public function getFrameSizeLimit() : int
    {
        return $this->frameSizeLimit;
    }
    /**
    * @param int $frameSizeLimit Maximum frame size that can be received from the peer.
    If a larger frame is received, the connection is ended with a POLICY_VIOLATION.
    Default is 2097152 (2MB)
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withFrameSizeLimit(int $frameSizeLimit) : self
    {
        if ($frameSizeLimit < 1) {
            throw new \Error('$frameSizeLimit must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->frameSizeLimit = $frameSizeLimit;
        return $clone;
    }
    /**
     * @return int Maximum number of bytes the peer can send per second before being throttled.
     */
    public function getBytesPerSecondLimit() : int
    {
        return $this->bytesPerSecondLimit;
    }
    /**
    * @param int $bytesPerSecond Maximum number of bytes the peer can send per
    second before being throttled. Default is 1048576 (1MB)
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withBytesPerSecondLimit(int $bytesPerSecond) : self
    {
        if ($bytesPerSecond < 1) {
            throw new \Error('$bytesPerSecond must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->bytesPerSecondLimit = $bytesPerSecond;
        return $clone;
    }
    /**
     * @return int Maximum number of frames the peer can send per second before being throttled.
     */
    public function getFramesPerSecondLimit() : int
    {
        return $this->framesPerSecondLimit;
    }
    /**
    * @param int $framesPerSecond Maximum number of frames the peer can send per
    second before being throttled.
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withFramesPerSecondLimit(int $framesPerSecond) : self
    {
        if ($framesPerSecond < 1) {
            throw new \Error('$bytesPerSecond must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->framesPerSecondLimit = $framesPerSecond;
        return $clone;
    }
    /**
    * @return int Maximum message size that can be received from the remote endpoint.
    If a larger message is received, the connection is ended with a POLICY_VIOLATION.
    */
    public function getMessageSizeLimit() : int
    {
        return $this->messageSizeLimit;
    }
    /**
    * @param int $messageSizeLimit Maximum message size that can be received
    from the remote endpoint. If a larger message is received, the connection
    is ended with a POLICY_VIOLATION. Default is 10485760 (10MB)
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withMessageSizeLimit(int $messageSizeLimit) : self
    {
        if ($messageSizeLimit < 1) {
            throw new \Error('$messageSizeLimit must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->messageSizeLimit = $messageSizeLimit;
        return $clone;
    }
    /**
     * @return bool If true ends the connection if a binary frame is received.
     */
    public function isTextOnly() : bool
    {
        return $this->textOnly;
    }
    /**
     * @param bool $textOnly If true ends the connection if a binary frame is received.
     *
     * @return self
     */
    public function withTextOnly(bool $textOnly) : self
    {
        $clone = clone $this;
        $clone->textOnly = $textOnly;
        return $clone;
    }
    /**
     * @return bool If true validates that all text received and sent is UTF-8.
     */
    public function isValidateUtf8() : bool
    {
        return $this->validateUtf8;
    }
    /**
     * @param bool $validateUtf8 If true validates that all text received and sent is UTF-8.
     *
     * @return self
     */
    public function withValidateUtf8(bool $validateUtf8) : self
    {
        $clone = clone $this;
        $clone->validateUtf8 = $validateUtf8;
        return $clone;
    }
    /**
     * @return int Number of seconds to wait to receive peer close frame.
     */
    public function getClosePeriod() : int
    {
        return $this->closePeriod;
    }
    /**
    * @param int $closePeriod Number of seconds to wait to receive peer close
    frame. Default is 3.
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withClosePeriod(int $closePeriod) : self
    {
        if ($closePeriod < 1) {
            throw new \Error('$closePeriod must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->closePeriod = $closePeriod;
        return $clone;
    }
    /**
     * @return bool Whether to request or accept per-message compression.
     */
    public function isCompressionEnabled() : bool
    {
        return $this->compressionEnabled;
    }
    /**
     * @return self Enables requesting or accepting per-message compression.
     */
    public function withCompression() : self
    {
        $clone = clone $this;
        $clone->compressionEnabled = true;
        return $clone;
    }
    /**
     * @return self Disables requesting or accepting per-message compression.
     */
    public function withoutCompression() : self
    {
        $clone = clone $this;
        $clone->compressionEnabled = false;
        return $clone;
    }
    /**
    * @return bool If enabled, sends a ping frame to the peer every X seconds (determined
    by the heartbeat period) if there is no other activity on the connection.
    */
    public function isHeartbeatEnabled() : bool
    {
        return $this->heartbeatEnabled;
    }
    /**
    * @return self Enables heartbeat; If enabled, sends a ping frame to the
    peer every X seconds (determined by the heartbeat period) if there
    is no other activity on the connection.
    */
    public function withHeartbeat() : self
    {
        $clone = clone $this;
        $clone->heartbeatEnabled = true;
        return $clone;
    }
    /**
    * @return self Disables heartbeat; If disabled, will not periodically send
    a ping frame to the peer during timetrames of inactivity on the connection.
    */
    public function withoutHeartbeat() : self
    {
        $clone = clone $this;
        $clone->heartbeatEnabled = false;
        return $clone;
    }
    /**
     * @return int Duration in seconds between pings or other connection activity if the heartbeat is enabled.
     */
    public function getHeartbeatPeriod() : int
    {
        return $this->heartbeatPeriod;
    }
    /**
    * @param int $heartbeatPeriod Duration in seconds between pings or other
    connection activity if the heartbeat is enabled. Default is 10.
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withHeartbeatPeriod(int $heartbeatPeriod) : self
    {
        if ($heartbeatPeriod < 1) {
            throw new \Error('$heartbeatPeriod must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->heartbeatPeriod = $heartbeatPeriod;
        return $clone;
    }
    /**
     * @return int The number of unanswered pings before the connection is closed.
     */
    public function getQueuedPingLimit() : int
    {
        return $this->queuedPingLimit;
    }
    /**
     * @param int $queuedPingLimit The number of unanswered pings before the connection is closed.
     *
     * @return self
     *
     * @throws \Error if number is less than 1.
     */
    public function withQueuedPingLimit(int $queuedPingLimit) : self
    {
        if ($queuedPingLimit < 1) {
            throw new \Error('$queuedPingLimit must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->queuedPingLimit = $queuedPingLimit;
        return $clone;
    }
}<?php

namespace Amp\Websocket;

use Amp\Struct;
final class ClientMetadata
{
    use Struct;
    /** @var int Next sequential client ID. */
    private static $nextId = 1;
    /** @var int */
    public $id;
    /** @var bool */
    public $closedByPeer = false;
    /** @var int|null */
    public $closeCode;
    /** @var string|null */
    public $closeReason;
    /** @var int */
    public $connectedAt = 0;
    /** @var int */
    public $closedAt = 0;
    /** @var int */
    public $lastReadAt = 0;
    /** @var int */
    public $lastSentAt = 0;
    /** @var int */
    public $lastDataReadAt = 0;
    /** @var int */
    public $lastDataSentAt = 0;
    /** @var int */
    public $lastHeartbeatAt = 0;
    /** @var int */
    public $bytesRead = 0;
    /** @var int */
    public $bytesSent = 0;
    /** @var int */
    public $framesRead = 0;
    /** @var int */
    public $framesSent = 0;
    /** @var int */
    public $messagesRead = 0;
    /** @var int */
    public $messagesSent = 0;
    /** @var int */
    public $pingCount = 0;
    /** @var int */
    public $pongCount = 0;
    /** @var bool */
    public $compressionEnabled;
    /**
     * @param int $time Current timestamp.
     * @param bool $compressionEnabled
     */
    public function __construct(int $time, bool $compressionEnabled)
    {
        $this->id = self::$nextId++;
        $this->connectedAt = $time;
        $this->compressionEnabled = $compressionEnabled;
    }
}<?php

namespace Amp\Websocket;

use Amp\ByteStream\InputStream;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
interface Client
{
    /**
     * Receive a message from the remote Websocket endpoint.
     *
     * @return Promise<(Message | null)> Resolves to message sent by the remote.
     *
     * @throws ClosedException Thrown if the connection is closed.
     */
    public function receive() : Promise;
    /**
     * @return int Unique identifier for the client.
     */
    public function getId() : int;
    /**
    * @return bool True if the client is still connected, false otherwise. Returns false as soon as the closing
    handshake is initiated by the server or client.
    */
    public function isConnected() : bool;
    /**
     * @return SocketAddress Local socket address.
     */
    public function getLocalAddress() : SocketAddress;
    /**
     * @return SocketAddress Remote socket address.
     */
    public function getRemoteAddress() : SocketAddress;
    /**
     * @return (TlsInfo | null) TlsInfo object if connection is secure.
     */
    public function getTlsInfo() : ?TlsInfo;
    /**
     * @return int Number of pings sent that have not been answered.
     */
    public function getUnansweredPingCount() : int;
    /**
     * @return int Client close code (generally one of those listed in Code, though not necessarily).
     *
     * @throws \Error Thrown if the client has not closed.
     */
    public function getCloseCode() : int;
    /**
     * @return string Client close reason.
     *
     * @throws \Error Thrown if the client has not closed.
     */
    public function getCloseReason() : string;
    /**
     * @return bool True if the peer initiated the websocket close.
     *
     * @throws \Error Thrown if the client has not closed.
     */
    public function isClosedByPeer() : bool;
    /**
    * Sends a text message to the endpoint. All data sent with this method must be valid UTF-8. Use `sendBinary()` if
    you want to send binary data.
    *
    * @param string $data Payload to send.
    *
    * @return Promise<void> Resolves once the message has been sent to the peer.
    *
    * @throws ClosedException Thrown if sending to the client fails.
    */
    public function send(string $data) : Promise;
    /**
     * Sends a binary message to the endpoint.
     *
     * @param string $data Payload to send.
     *
     * @return Promise<void> Resolves once the message has been sent to the peer.
     *
     * @throws ClosedException Thrown if sending to the client fails.
     */
    public function sendBinary(string $data) : Promise;
    /**
    * Streams the given UTF-8 text stream to the endpoint. This method should be used only for large payloads such as
    files. Use send() for smaller payloads.
    *
    * @param InputStream $stream
    *
    * @return Promise<void> Resolves once the message has been sent to the peer.
    *
    * @throws ClosedException Thrown if sending to the client fails.
    */
    public function stream(InputStream $stream) : Promise;
    /**
    * Streams the given binary to the endpoint. This method should be used only for large payloads such as
    files. Use sendBinary() for smaller payloads.
    *
    * @param InputStream $stream
    *
    * @return Promise<void> Resolves once the message has been sent to the peer.
    *
    * @throws ClosedException Thrown if sending to the client fails.
    */
    public function streamBinary(InputStream $stream) : Promise;
    /**
     * Sends a ping to the endpoint.
     *
     * @return Promise<int> Resolves with the number of bytes sent to the other endpoint.
     */
    public function ping() : Promise;
    /**
     * @return Options The options object associated with this client.
     */
    public function getOptions() : Options;
    /**
     * Returns connection metadata.
     *
     * @return ClientMetadata
     */
    public function getInfo() : ClientMetadata;
    /**
    * Closes the client connection.
    *
    * @param int $code
    * @param string $reason
    *
    * @return Promise<array> Resolves with an array containing the close code at key 0 and the close reason at key 1.
    These may differ from those provided if the connection was closed prior.
    */
    public function close(int $code = Code::NORMAL_CLOSE, string $reason = '') : Promise;
    /**
    * Attaches a callback invoked when the client closes. The callback is passed this object as the first parameter,
    the close code as the second parameter, and the close reason as the third parameter.
    *
    * @param callable(Client $client, int $code, string $reason) $callback
    */
    public function onClose(callable $callback) : void;
}<?php

namespace Amp\Websocket;

interface CompressionContext
{
    /**
     * @return int The RSV value for this compression extension.
     */
    public function getRsv() : int;
    /**
     * @return int Minimum number of bytes a message must be before compressing.
     */
    public function getCompressionThreshold() : int;
    /**
     * Compress the given payload data.
     *
     * @param string $data
     * @param bool $isFinal
     *
     * @return string
     */
    public function compress(string $data, bool $isFinal) : string;
    /**
     * Decompress the given payload data. Null should be returned if decompression fails.
     *
     * @param string $data
     * @param bool $isFinal
     *
     * @return (string | null)
     */
    public function decompress(string $data, bool $isFinal) : ?string;
}<?php

namespace Amp\Websocket;

// defined in https://tools.ietf.org/html/rfc6455#section-4
const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
/**
 * @param int $length Random bytes to use to generate the key.
 *
 * @return string
 *
 * @throws \Exception If generating a random key fails.
 */
function generateKey(int $length = 16) : string
{
    return \base64_encode(\random_bytes($length));
}
/**
 * Generates the value for the Sec-Websocket-Accept header based on the given Sec-Websocket-Key header value.
 *
 * @param string $key
 *
 * @return string
 */
function generateAcceptFromKey(string $key) : string
{
    return \base64_encode(\sha1($key . GUID, true));
}
/**
 * Determines if the Sec-Websocket-Accept value given matches the expected value for the Sec-Websocket-Key header.
 *
 * @param string $accept
 * @param string $key
 *
 * @return bool
 */
function validateAcceptForKey(string $accept, string $key) : bool
{
    return $accept === generateAcceptFromKey($key);
}<?php

namespace Amp\Websocket;

final class Code
{
    public const NORMAL_CLOSE = 1000;
    public const GOING_AWAY = 1001;
    public const PROTOCOL_ERROR = 1002;
    public const UNACCEPTABLE_TYPE = 1003;
    // 1004 reserved and unused.
    public const NONE = 1005;
    public const ABNORMAL_CLOSE = 1006;
    public const INCONSISTENT_FRAME_DATA_TYPE = 1007;
    public const POLICY_VIOLATION = 1008;
    public const MESSAGE_TOO_LARGE = 1009;
    public const EXPECTED_EXTENSION_MISSING = 1010;
    public const UNEXPECTED_SERVER_ERROR = 1011;
    public const SERVICE_RESTARTING = 1012;
    public const TRY_AGAIN_LATER = 1013;
    public const BAD_GATEWAY = 1014;
    public const TLS_HANDSHAKE_FAILURE = 1015;
    /**
     * @param int $code Close code.
     *
     * @return (string | null) Constant name corresponding to the given code or null if the code is undefined.
     */
    public static function getName(int $code) : ?string
    {
        return [self::NORMAL_CLOSE => 'NORMAL_CLOSE', self::GOING_AWAY => 'GOING_AWAY', self::PROTOCOL_ERROR => 'PROTOCOL_ERROR', self::UNACCEPTABLE_TYPE => 'UNACCEPTABLE_TYPE', self::NONE => 'NONE', self::ABNORMAL_CLOSE => 'ABNORMAL_CLOSE', self::INCONSISTENT_FRAME_DATA_TYPE => 'INCONSISTENT_FRAME_DATA_TYPE', self::POLICY_VIOLATION => 'POLICY_VIOLATION', self::MESSAGE_TOO_LARGE => 'MESSAGE_TOO_LARGE', self::EXPECTED_EXTENSION_MISSING => 'EXPECTED_EXTENSION_MISSING', self::UNEXPECTED_SERVER_ERROR => 'UNEXPECTED_SERVER_ERROR', self::SERVICE_RESTARTING => 'SERVICE_RESTARTING', self::TRY_AGAIN_LATER => 'TRY_AGAIN_LATER', self::BAD_GATEWAY => 'BAD_GATEWAY', self::TLS_HANDSHAKE_FAILURE => 'TLS_HANDSHAKE_FAILURE'][$code] ?? null;
    }
    /**
     * @codeCoverageIgnore Class cannot be instigated.
     */
    private function __construct()
    {
        // no instances allowed
    }
}<?php

namespace Amp\Websocket;

final class ClosedException extends \Exception
{
    /** @var string */
    private $reason;
    /**
     *
     */
    public function __construct(string $message, int $code, string $reason)
    {
        parent::__construct(\sprintf('%s; Code %s (%s); Reason: "%s"', $message, $code, Code::getName($code) ?? 'Unknown code', $reason), $code);
        $this->reason = $reason;
    }
    /**
     *
     */
    public function getReason() : string
    {
        return $this->reason;
    }
}<?php

namespace Amp\Websocket;

final class Opcode
{
    public const CONT = 0x0;
    public const TEXT = 0x1;
    public const BIN = 0x2;
    public const CLOSE = 0x8;
    public const PING = 0x9;
    public const PONG = 0xa;
    /**
     * @codeCoverageIgnore Class cannot be instigated.
     */
    private function __construct()
    {
        // forbid instances
    }
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\Websocket;

final class Rfc7692Compression implements CompressionContext
{
    public const DEFAULT_WINDOW_SIZE = 15;
    private const RSV = 0b100;
    private const MINIMUM_LENGTH = 860;
    private const EMPTY_BLOCK = "\x00\x00\xff\xff";
    /**
     * Create a compression context from a header received from a websocket client request.
     *
     * @param string $headerIn Header from request.
     * @param string $headerOut Sec-Websocket-Extension response header.
     *
     * @return (self | null)
     */
    public static function fromClientHeader(string $headerIn, ?string &$headerOut) : ?self
    {
        return self::fromHeader(true, $headerIn, $headerOut);
    }
    /**
     * Create a compression context from a header received from a websocket server response.
     *
     * @param string $header Header from response.
     *
     * @return (self | null)
     */
    public static function fromServerHeader(string $header) : ?self
    {
        return self::fromHeader(false, $header);
    }
    /**
     * @return string Header value for Sec-Websocket-Extension header.
     */
    public static function createRequestHeader() : string
    {
        return 'permessage-deflate; server_no_context_takeover; client_no_context_takeover';
    }
    /**
     * @param bool $isServer True if creating a server context, false if creating a client context.
     * @param string $headerIn Header from request.
     * @param string $headerOut Sec-Websocket-Extension response header.
     *
     * @return (self | null)
     */
    private static function fromHeader(bool $isServer, string $headerIn, ?string &$headerOut = null) : ?self
    {
        $headerIn = \explode(';', \strtolower($headerIn));
        $headerIn = \array_map('trim', $headerIn);
        if (!\in_array('permessage-deflate', $headerIn, true)) {
            return null;
        }
        $serverWindowSize = self::DEFAULT_WINDOW_SIZE;
        $clientWindowSize = self::DEFAULT_WINDOW_SIZE;
        $serverContextTakeover = true;
        $clientContextTakeover = true;
        $headers = [];
        $headerOut = 'permessage-deflate';
        foreach ($headerIn as $param) {
            $parts = \explode('=', $param, 2);
            if (\in_array($parts[0], $headers, true)) {
                return null;
                // Repeat params in header.
            }
            $headers[] = $parts[0];
            switch ($parts[0]) {
                case 'permessage-deflate':
                    break;
                case 'client_max_window_bits':
                    if (isset($parts[1])) {
                        $value = (int) $parts[1];
                        if ($value < 8 || $value > 15) {
                            return null;
                            // Invalid option value.
                        }
                        $clientWindowSize = $value;
                    }
                    $headerOut .= '; client_max_window_bits=' . $clientWindowSize;
                    break;
                case 'client_no_context_takeover':
                    $clientContextTakeover = false;
                    $headerOut .= '; client_no_context_takeover';
                    break;
                case 'server_max_window_bits':
                    if (isset($parts[1])) {
                        $value = (int) $parts[1];
                        if ($value < 8 || $value > 15) {
                            return null;
                            // Invalid option value.
                        }
                        $serverWindowSize = $value;
                    }
                    $headerOut .= '; server_max_window_bits=' . $serverWindowSize;
                    break;
                case 'server_no_context_takeover':
                    $serverContextTakeover = false;
                    $headerOut .= '; server_no_context_takeover';
                    break;
                default:
                    return null;
            }
        }
        if ($isServer) {
            return new self($clientWindowSize, $serverWindowSize, $clientContextTakeover, $serverContextTakeover);
        }
        return new self($serverWindowSize, $clientWindowSize, $serverContextTakeover, $clientContextTakeover);
    }
    /** @var resource */
    private $deflate;
    /** @var resource */
    private $inflate;
    /** @var int */
    private $sendingFlushMode;
    /** @var int */
    private $receivingFlushMode;
    /**
     *
     */
    private function __construct(int $receivingWindowSize, int $sendingWindowSize, bool $receivingContextTakeover, bool $sendingContextTakeover)
    {
        $this->receivingFlushMode = $receivingContextTakeover ? \ZLIB_SYNC_FLUSH : \ZLIB_FULL_FLUSH;
        $this->sendingFlushMode = $sendingContextTakeover ? \ZLIB_SYNC_FLUSH : \ZLIB_FULL_FLUSH;
        if (($this->inflate = \inflate_init(\ZLIB_ENCODING_RAW, ['window' => $receivingWindowSize])) === false) {
            throw new \RuntimeException('Failed initializing inflate context');
        }
        if (($this->deflate = \deflate_init(\ZLIB_ENCODING_RAW, ['window' => $sendingWindowSize])) === false) {
            throw new \RuntimeException('Failed initializing deflate context');
        }
    }
    /**
     *
     */
    public function getRsv() : int
    {
        return self::RSV;
    }
    /**
     *
     */
    public function getCompressionThreshold() : int
    {
        return self::MINIMUM_LENGTH;
    }
    /**
     *
     */
    public function decompress(string $data, bool $isFinal) : ?string
    {
        if ($isFinal) {
            $data .= self::EMPTY_BLOCK;
        }
        $data = \inflate_add($this->inflate, $data, $this->receivingFlushMode);
        if (false === $data) {
            return null;
        }
        return $data;
    }
    /**
     *
     */
    public function compress(string $data, bool $isFinal) : string
    {
        $data = \deflate_add($this->deflate, $data, $this->sendingFlushMode);
        if ($data === false) {
            throw new \RuntimeException('Failed to compress data');
        }
        if ($isFinal && \Phabel\Target\Php80\Polyfill::substr($data, -4) === self::EMPTY_BLOCK) {
            $data = \Phabel\Target\Php80\Polyfill::substr($data, 0, -4);
        }
        return $data;
    }
}{
    "name": "amphp/websocket",
    "homepage": "https://github.com/amphp/websocket",
    "description": "Shared code for websocket servers and clients.",
    "support": {
        "issues": "https://github.com/amphp/websocket/issues"
    },
    "keywords": [
        "async",
        "non-blocking",
        "websocket",
        "http",
        "amp",
        "amphp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2.2",
        "amphp/byte-stream": "^1.6.1",
        "amphp/socket": "^1",
        "cash/lrucache": "^1"
    },
    "require-dev": {
        "phpunit/phpunit": "^8 || ^7",
        "amphp/phpunit-util": "^1.1.2",
        "amphp/php-cs-fixer-config": "dev-master",
        "vimeo/psalm": "^3.11@dev"
    },
    "suggest": {
        "ext-zlib": "Required for compression"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Websocket\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Websocket\\Test\\": "test"
        },
        "files": [
            "test/functions.php"
        ]
    }
}
<?php

namespace Amp\Serialization;

final class NativeSerializer implements Serializer
{
    /** @var string[]|null */
    private $allowedClasses;
    /**
     * @param (string[] | null) $allowedClasses List of allowed class names to be unserialized. Null for any class.
     */
    public function __construct(?array $allowedClasses = null)
    {
        $this->allowedClasses = $allowedClasses;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        try {
            return \serialize($data);
        } catch (\Throwable $exception) {
            throw new SerializationException(\sprintf('The given data could not be serialized: %s', $exception->getMessage()), 0, $exception);
        }
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        try {
            $result = \unserialize($data, ['allowed_classes' => $this->allowedClasses ?? true]);
            if ($result === false && $data !== \serialize(false)) {
                throw new SerializationException('Invalid data provided to unserialize: ' . encodeUnprintableChars($data));
            }
        } catch (\Throwable $exception) {
            throw new SerializationException('Exception thrown when unserializing data', 0, $exception);
        }
        return $result;
    }
}<?php

namespace Amp\Serialization;

final class JsonSerializer implements Serializer
{
    // Equal to JSON_THROW_ON_ERROR, only available in PHP 7.3+.
    private const THROW_ON_ERROR = 4194304;
    /** @var bool */
    private $associative;
    /** @var int */
    private $encodeOptions;
    /** @var int */
    private $decodeOptions;
    /** @var int */
    private $depth;
    /**
     * Creates a JSON serializer that decodes objects to associative arrays.
     *
     * @param int $encodeOptions @see \json_encode() options parameter.
     * @param int $decodeOptions @see \json_decode() options parameter.
     * @param int $depth Maximum recursion depth.
     *
     * @return self
     */
    public static function withAssociativeArrays(int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512) : self
    {
        return new self(true, $encodeOptions, $decodeOptions, $depth);
    }
    /**
     * Creates a JSON serializer that decodes objects to instances of stdClass.
     *
     * @param int $encodeOptions @see \json_encode() options parameter.
     * @param int $decodeOptions @see \json_decode() options parameter.
     * @param int $depth Maximum recursion depth.
     *
     * @return self
     */
    public static function withObjects(int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512) : self
    {
        return new self(false, $encodeOptions, $decodeOptions, $depth);
    }
    /**
     *
     */
    private function __construct(bool $associative, int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512)
    {
        $this->associative = $associative;
        $this->depth = $depth;
        // We don't want to throw on errors, we manually check for errors using json_last_error().
        $this->encodeOptions = $encodeOptions & ~self::THROW_ON_ERROR;
        $this->decodeOptions = $decodeOptions & ~self::THROW_ON_ERROR;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        $result = \json_encode($data, $this->encodeOptions, $this->depth);
        switch ($code = \json_last_error()) {
            case \JSON_ERROR_NONE:
                return $result;
            default:
                throw new SerializationException(\json_last_error_msg(), $code);
        }
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        $result = \json_decode($data, $this->associative, $this->depth, $this->decodeOptions);
        switch ($code = \json_last_error()) {
            case \JSON_ERROR_NONE:
                return $result;
            default:
                throw new SerializationException(\json_last_error_msg(), $code);
        }
    }
}<?php

namespace Amp\Serialization;

interface Serializer
{
    /**
     * @param mixed $data
     *
     * @return string
     *
     * @throws SerializationException
     */
    public function serialize($data) : string;
    /**
     * @param string $data
     *
     * @return mixed The unserialized data.
     *
     * @throws SerializationException
     */
    public function unserialize(string $data);
}<?php

namespace Amp\Serialization;

final class CompressingSerializer implements Serializer
{
    private const FLAG_COMPRESSED = 1;
    private const COMPRESSION_THRESHOLD = 256;
    /** @var Serializer */
    private $serializer;
    /**
     *
     */
    public function __construct(Serializer $serializer)
    {
        $this->serializer = $serializer;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        $serializedData = $this->serializer->serialize($data);
        $flags = 0;
        if (\strlen($serializedData) > self::COMPRESSION_THRESHOLD) {
            $serializedData = @\gzdeflate($serializedData, 1);
            if ($serializedData === false) {
                $error = \error_get_last();
                throw new SerializationException('Could not compress data: ' . ($error['message'] ?? 'unknown error'));
            }
            $flags |= self::FLAG_COMPRESSED;
        }
        return \chr($flags & 0xff) . $serializedData;
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        $firstByte = \ord($data[0]);
        $data = \Phabel\Target\Php80\Polyfill::substr($data, 1);
        if ($firstByte & self::FLAG_COMPRESSED) {
            $data = @\gzinflate($data);
            if ($data === false) {
                $error = \error_get_last();
                throw new SerializationException('Could not decompress data: ' . ($error['message'] ?? 'unknown error'));
            }
        }
        return $this->serializer->unserialize($data);
    }
}<?php

namespace Amp\Serialization;

final class PassthroughSerializer implements Serializer
{
    /**
     *
     */
    public function serialize($data) : string
    {
        if (!\is_string($data)) {
            throw new SerializationException('Serializer implementation only allows strings');
        }
        return $data;
    }
    /**
     *
     */
    public function unserialize(string $data) : string
    {
        return $data;
    }
}<?php

namespace Amp\Serialization;

/**
 * @param string $data Binary data.
 *
 * @return string Unprintable characters encoded as \x##.
 */
function encodeUnprintableChars(string $data) : string
{
    return \preg_replace_callback("/[^ -~]/", function (array $matches) : string {
        return "\\x" . \dechex(\ord($matches[0]));
    }, $data);
}<?php

namespace Amp\Serialization;

class SerializationException extends \Exception
{
}{
    "name": "amphp/serialization",
    "description": "Serialization tools for IPC and data storage in PHP.",
    "keywords": [
        "asynchronous",
        "async",
        "serialization",
        "serialize"
    ],
    "homepage": "https://github.com/amphp/serialization",
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "require-dev": {
        "phpunit/phpunit": "^9 || ^8 || ^7",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Serialization\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Serialization\\Test\\": "test"
        }
    }
}
{
    "name": "amphp/byte-stream",
    "homepage": "http://amphp.org/byte-stream",
    "description": "A stream abstraction to make working with non-blocking I/O simple.",
    "support": {
        "issues": "https://github.com/amphp/byte-stream/issues",
        "irc": "irc://irc.freenode.org/amphp"
    },
    "keywords": [
        "stream",
        "async",
        "non-blocking",
        "amp",
        "amphp",
        "io"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1.4",
        "phpunit/phpunit": "^6 || ^7 || ^8",
        "friendsofphp/php-cs-fixer": "^2.3",
        "amphp/php-cs-fixer-config": "dev-master",
        "psalm/phar": "^3.11.4",
        "jetbrains/phpstorm-stubs": "^2019.3"
    },
    "autoload": {
        "psr-4": {
            "Amp\\ByteStream\\": "lib"
        },
        "files": [
            "lib/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\ByteStream\\Test\\": "test"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    }
}
<?php

namespace Amp\ByteStream\Base64;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\StreamException;
use Amp\Promise;
use function Amp\call;
final class Base64DecodingInputStream implements InputStream
{
    /** @var InputStream|null */
    private $source;
    /** @var string|null */
    private $buffer = '';
    /**
     *
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    public function read() : Promise
    {
        return call(function () {
            if ($this->source === null) {
                throw new StreamException('Failed to read stream chunk due to invalid base64 data');
            }
            $chunk = (yield $this->source->read());
            if ($chunk === null) {
                if ($this->buffer === null) {
                    return null;
                }
                $chunk = \base64_decode($this->buffer, true);
                if ($chunk === false) {
                    $this->source = null;
                    $this->buffer = null;
                    throw new StreamException('Failed to read stream chunk due to invalid base64 data');
                }
                $this->buffer = null;
                return $chunk;
            }
            $this->buffer .= $chunk;
            $length = \strlen($this->buffer);
            $chunk = \base64_decode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 4), true);
            if ($chunk === false) {
                $this->source = null;
                $this->buffer = null;
                throw new StreamException('Failed to read stream chunk due to invalid base64 data');
            }
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 4);
            return $chunk;
        });
    }
}<?php

namespace Amp\ByteStream\Base64;

use Amp\ByteStream\OutputStream;
use Amp\Promise;
final class Base64EncodingOutputStream implements OutputStream
{
    /** @var OutputStream */
    private $destination;
    /** @var string */
    private $buffer = '';
    /**
     *
     */
    public function __construct(OutputStream $destination)
    {
        $this->destination = $destination;
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        $this->buffer .= $data;
        $length = \strlen($this->buffer);
        $chunk = \base64_encode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 3));
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 3);
        return $this->destination->write($chunk);
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        $chunk = \base64_encode($this->buffer . $finalData);
        $this->buffer = '';
        return $this->destination->end($chunk);
    }
}<?php

namespace Amp\ByteStream\Base64;

use Amp\ByteStream\OutputStream;
use Amp\ByteStream\StreamException;
use Amp\Failure;
use Amp\Promise;
final class Base64DecodingOutputStream implements OutputStream
{
    /** @var OutputStream */
    private $destination;
    /** @var string */
    private $buffer = '';
    /** @var int */
    private $offset = 0;
    /**
     *
     */
    public function __construct(OutputStream $destination)
    {
        $this->destination = $destination;
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        $this->buffer .= $data;
        $length = \strlen($this->buffer);
        $chunk = \base64_decode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 4), true);
        if ($chunk === false) {
            return new Failure(new StreamException('Invalid base64 near offset ' . $this->offset));
        }
        $this->offset += $length - $length % 4;
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 4);
        return $this->destination->write($chunk);
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        $this->offset += \strlen($this->buffer);
        $chunk = \base64_decode($this->buffer . $finalData, true);
        if ($chunk === false) {
            return new Failure(new StreamException('Invalid base64 near offset ' . $this->offset));
        }
        $this->buffer = '';
        return $this->destination->end($chunk);
    }
}<?php

namespace Amp\ByteStream\Base64;

use Amp\ByteStream\InputStream;
use Amp\Promise;
use function Amp\call;
final class Base64EncodingInputStream implements InputStream
{
    /** @var InputStream */
    private $source;
    /** @var string|null */
    private $buffer = '';
    /**
     *
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    public function read() : Promise
    {
        return call(function () {
            $chunk = (yield $this->source->read());
            if ($chunk === null) {
                if ($this->buffer === null) {
                    return null;
                }
                $chunk = \base64_encode($this->buffer);
                $this->buffer = null;
                return $chunk;
            }
            $this->buffer .= $chunk;
            $length = \strlen($this->buffer);
            $chunk = \base64_encode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 3));
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 3);
            return $chunk;
        });
    }
}<?php

namespace Amp\ByteStream;

use Amp\Deferred;
use Amp\Failure;
use Amp\Iterator;
use Amp\Promise;
final class IteratorStream implements InputStream
{
    /** @var Iterator<string> */
    private $iterator;
    /** @var \Throwable|null */
    private $exception;
    /** @var bool */
    private $pending = false;
    /**
     * @psam-param Iterator<string> $iterator
     */
    public function __construct(Iterator $iterator)
    {
        $this->iterator = $iterator;
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        if ($this->exception) {
            return new Failure($this->exception);
        }
        if ($this->pending) {
            throw new PendingReadError();
        }
        $this->pending = true;
        /** @var Deferred<string|null> $deferred */
        $deferred = new Deferred();
        $this->iterator->advance()->onResolve(function ($error, $hasNextElement) use($deferred) {
            $this->pending = false;
            if ($error) {
                $this->exception = $error;
                $deferred->fail($error);
            } elseif ($hasNextElement) {
                $chunk = $this->iterator->getCurrent();
                if (!\is_string($chunk)) {
                    $this->exception = new StreamException(\sprintf("Unexpected iterator value of type '%s', expected string", \is_object($chunk) ? \get_class($chunk) : \gettype($chunk)));
                    $deferred->fail($this->exception);
                    return;
                }
                $deferred->resolve($chunk);
            } else {
                $deferred->resolve();
            }
        });
        return $deferred->promise();
    }
}<?php

namespace Amp\ByteStream;

use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
/**
 * Output stream abstraction for PHP's stream resources.
 */
final class ResourceOutputStream implements OutputStream
{
    const MAX_CONSECUTIVE_EMPTY_WRITES = 3;
    const LARGE_CHUNK_SIZE = 128 * 1024;
    /** @var resource|null */
    private $resource;
    /** @var string */
    private $watcher;
    /** @var \SplQueue<array> */
    private $writes;
    /** @var bool */
    private $writable = true;
    /** @var int|null */
    private $chunkSize;
    /**
     * @param resource $stream Stream resource.
     * @param (int | null) $chunkSize Chunk size per `fwrite()` operation.
     */
    public function __construct($stream, int $chunkSize = null)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== 'stream') {
            throw new \Error("Expected a valid stream");
        }
        $meta = \stream_get_meta_data($stream);
        if (\strpos($meta["mode"], "r") !== false && \strpos($meta["mode"], "+") === false) {
            throw new \Error("Expected a writable stream");
        }
        \stream_set_blocking($stream, false);
        \stream_set_write_buffer($stream, 0);
        $this->resource = $stream;
        $this->chunkSize =& $chunkSize;
        $writes = $this->writes = new \SplQueue();
        $writable =& $this->writable;
        $resource =& $this->resource;
        $this->watcher = Loop::onWritable($stream, static function ($watcher, $stream) use($writes, &$chunkSize, &$writable, &$resource) {
            static $emptyWrites = 0;
            try {
                while (!$writes->isEmpty()) {
                    /** @var Deferred $deferred */
                    list($data, $previous, $deferred) = $writes->shift();
                    $length = \strlen($data);
                    if ($length === 0) {
                        $deferred->resolve(0);
                        continue;
                    }
                    if (!\is_resource($stream) || ($metaData = @\stream_get_meta_data($stream)) && $metaData['eof']) {
                        throw new ClosedException("The stream was closed by the peer");
                    }
                    // Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full.
                    // Use conditional, because PHP doesn't like getting null passed
                    if ($chunkSize) {
                        $written = @\fwrite($stream, $data, $chunkSize);
                    } else {
                        $written = @\fwrite($stream, $data);
                    }
                    \assert(
                        $written !== false || \PHP_VERSION_ID >= 70400,
                        // PHP 7.4+ returns false on EPIPE.
                        "Trying to write on a previously fclose()'d resource. Do NOT manually fclose() resources the still referenced in the loop."
                    );
                    // PHP 7.4.0 and 7.4.1 may return false on EAGAIN.
                    if ($written === false && \PHP_VERSION_ID >= 70402) {
                        $message = "Failed to write to stream";
                        if ($error = \error_get_last()) {
                            $message .= \sprintf("; %s", $error["message"]);
                        }
                        throw new StreamException($message);
                    }
                    // Broken pipes between processes on macOS/FreeBSD do not detect EOF properly.
                    if ($written === 0 || $written === false) {
                        if ($emptyWrites++ > self::MAX_CONSECUTIVE_EMPTY_WRITES) {
                            $message = "Failed to write to stream after multiple attempts";
                            if ($error = \error_get_last()) {
                                $message .= \sprintf("; %s", $error["message"]);
                            }
                            throw new StreamException($message);
                        }
                        $writes->unshift([$data, $previous, $deferred]);
                        return;
                    }
                    $emptyWrites = 0;
                    if ($length > $written) {
                        $data = \Phabel\Target\Php80\Polyfill::substr($data, $written);
                        $writes->unshift([$data, $written + $previous, $deferred]);
                        return;
                    }
                    $deferred->resolve($written + $previous);
                }
            } catch (\Throwable $exception) {
                $resource = null;
                $writable = false;
                /** @psalm-suppress PossiblyUndefinedVariable */
                $deferred->fail($exception);
                while (!$writes->isEmpty()) {
                    list(, , $deferred) = $writes->shift();
                    $deferred->fail($exception);
                }
                Loop::cancel($watcher);
            } finally {
                if ($writes->isEmpty()) {
                    Loop::disable($watcher);
                }
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     */
    public function write(string $data) : Promise
    {
        return $this->send($data, false);
    }
    /**
     * Closes the stream after all pending writes have been completed. Optionally writes a final data chunk before.
     *
     * @param string $finalData Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     */
    public function end(string $finalData = "") : Promise
    {
        return $this->send($finalData, true);
    }
    /**
     *
     */
    private function send(string $data, bool $end = false) : Promise
    {
        if (!$this->writable) {
            return new Failure(new ClosedException("The stream is not writable"));
        }
        $length = \strlen($data);
        $written = 0;
        if ($end) {
            $this->writable = false;
        }
        if ($this->writes->isEmpty()) {
            if ($length === 0) {
                if ($end) {
                    $this->close();
                }
                return new Success(0);
            }
            if (!\is_resource($this->resource) || ($metaData = @\stream_get_meta_data($this->resource)) && $metaData['eof']) {
                return new Failure(new ClosedException("The stream was closed by the peer"));
            }
            // Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full.
            // Use conditional, because PHP doesn't like getting null passed.
            if ($this->chunkSize) {
                $written = @\fwrite($this->resource, $data, $this->chunkSize);
            } else {
                $written = @\fwrite($this->resource, $data);
            }
            \assert(
                $written !== false || \PHP_VERSION_ID >= 70400,
                // PHP 7.4+ returns false on EPIPE.
                "Trying to write on a previously fclose()'d resource. Do NOT manually fclose() resources the still referenced in the loop."
            );
            // PHP 7.4.0 and 7.4.1 may return false on EAGAIN.
            if ($written === false && \PHP_VERSION_ID >= 70402) {
                $message = "Failed to write to stream";
                if ($error = \error_get_last()) {
                    $message .= \sprintf("; %s", $error["message"]);
                }
                return new Failure(new StreamException($message));
            }
            $written = (int) $written;
            // Cast potential false to 0.
            if ($length === $written) {
                if ($end) {
                    $this->close();
                }
                return new Success($written);
            }
            $data = \Phabel\Target\Php80\Polyfill::substr($data, $written);
        }
        $deferred = new Deferred();
        if ($length - $written > self::LARGE_CHUNK_SIZE) {
            $chunks = \str_split($data, self::LARGE_CHUNK_SIZE);
            $data = \array_pop($chunks);
            foreach ($chunks as $chunk) {
                $this->writes->push([$chunk, $written, new Deferred()]);
                $written += self::LARGE_CHUNK_SIZE;
            }
        }
        $this->writes->push([$data, $written, $deferred]);
        Loop::enable($this->watcher);
        $promise = $deferred->promise();
        if ($end) {
            $promise->onResolve([$this, "close"]);
        }
        return $promise;
    }
    /**
     * Closes the stream forcefully. Multiple `close()` calls are ignored.
     *
     * @return void
     */
    public function close()
    {
        if (\is_resource($this->resource)) {
            // Error suppression, as resource might already be closed
            $meta = @\stream_get_meta_data($this->resource);
            if ($meta && \strpos($meta["mode"], "+") !== false) {
                @\stream_socket_shutdown($this->resource, \STREAM_SHUT_WR);
            } else {
                /** @psalm-suppress InvalidPropertyAssignmentValue psalm reports this as closed-resource */
                @\fclose($this->resource);
            }
        }
        $this->free();
    }
    /**
     * Nulls reference to resource, marks stream unwritable, and fails any pending write.
     *
     * @return void
     */
    private function free()
    {
        $this->resource = null;
        $this->writable = false;
        if (!$this->writes->isEmpty()) {
            $exception = new ClosedException("The socket was closed before writing completed");
            do {
                /** @var Deferred $deferred */
                list(, , $deferred) = $this->writes->shift();
                $deferred->fail($exception);
            } while (!$this->writes->isEmpty());
        }
        Loop::cancel($this->watcher);
    }
    /**
     * @return (resource | null) Stream resource or null if end() has been called or the stream closed.
     */
    public function getResource()
    {
        return $this->resource;
    }
    /**
     * @return void
     */
    public function setChunkSize(int $chunkSize)
    {
        $this->chunkSize = $chunkSize;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->resource !== null) {
            $this->free();
        }
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
/**
 * An `OutputStream` allows writing data in chunks. Writers can wait on the returned promises to feel the backpressure.
 */
interface OutputStream
{
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     * @throws StreamException If writing to the stream fails.
     */
    public function write(string $data) : Promise;
    /**
    * Marks the stream as no longer writable. Optionally writes a final data chunk before. Note that this is not the
    same as forcefully closing the stream. This method waits for all pending writes to complete before closing the
    stream. Socket streams implementing this interface should only close the writable side of the stream.
    *
    * @param string $finalData Bytes to write.
    *
    * @return Promise Succeeds once the data has been successfully written to the stream.
    *
    * @throws ClosedException If the stream has already been closed.
    * @throws StreamException If writing to the stream fails.
    */
    public function end(string $finalData = "") : Promise;
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class InputStreamChain implements InputStream
{
    /** @var InputStream[] */
    private $streams;
    /** @var bool */
    private $reading = false;
    /**
     *
     */
    public function __construct(InputStream ...$streams)
    {
        $this->streams = $streams;
    }
    /**
     * @inheritDoc
     */
    public function read() : Promise
    {
        if ($this->reading) {
            throw new PendingReadError();
        }
        if (!$this->streams) {
            return new Success(null);
        }
        return call(function () {
            $this->reading = true;
            try {
                while ($this->streams) {
                    $chunk = (yield $this->streams[0]->read());
                    if ($chunk === null) {
                        \array_shift($this->streams);
                        continue;
                    }
                    return $chunk;
                }
                return null;
            } finally {
                $this->reading = false;
            }
        });
    }
}<?php

namespace Amp\ByteStream;

use Amp\Coroutine;
use Amp\Deferred;
use Amp\Failure;
use Amp\Promise;
use Amp\Success;
/**
 * Creates a buffered message from an InputStream. The message can be consumed in chunks using the read() API or it may
 * be buffered and accessed in its entirety by waiting for the promise to resolve.
 *
 * Other implementations may extend this class to add custom properties such as a `isBinary()` flag for WebSocket
 * messages.
 *
 * Buffering Example:
 *
 * $stream = new Message($inputStream);
 * $content = yield $stream;
 *
 * Streaming Example:
 *
 * $stream = new Message($inputStream);
 *
 * while (($chunk = yield $stream->read()) !== null) {
 *     // Immediately use $chunk, reducing memory consumption since the entire message is never buffered.
 * }
 *
 * @deprecated Use Amp\ByteStream\Payload instead.
 */
class Message implements InputStream, Promise
{
    /** @var InputStream */
    private $source;
    /** @var string */
    private $buffer = "";
    /** @var Deferred|null */
    private $pendingRead;
    /** @var Coroutine|null */
    private $coroutine;
    /** @var bool True if onResolve() has been called. */
    private $buffering = false;
    /** @var Deferred|null */
    private $backpressure;
    /** @var bool True if the iterator has completed. */
    private $complete = false;
    /** @var \Throwable|null Used to fail future reads on failure. */
    private $error;
    /**
     * @param InputStream $source An iterator that only emits strings.
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    private function consume() : \Generator
    {
        while (($chunk = (yield $this->source->read())) !== null) {
            $buffer = $this->buffer .= $chunk;
            if ($buffer === "") {
                continue;
                // Do not succeed reads with empty string.
            } elseif ($this->pendingRead) {
                $deferred = $this->pendingRead;
                $this->pendingRead = null;
                $this->buffer = "";
                $deferred->resolve($buffer);
                $buffer = "";
                // Destroy last emitted chunk to free memory.
            } elseif (!$this->buffering) {
                $buffer = "";
                // Destroy last emitted chunk to free memory.
                $this->backpressure = new Deferred();
                (yield $this->backpressure->promise());
            }
        }
        $this->complete = true;
        if ($this->pendingRead) {
            $deferred = $this->pendingRead;
            $this->pendingRead = null;
            $deferred->resolve($this->buffer !== "" ? $this->buffer : null);
            $this->buffer = "";
        }
        return $this->buffer;
    }
    /**
     * @inheritdoc
     */
    public final function read() : Promise
    {
        if ($this->pendingRead) {
            throw new PendingReadError();
        }
        if ($this->coroutine === null) {
            $this->coroutine = new Coroutine($this->consume());
            $this->coroutine->onResolve(function ($error) {
                if ($error) {
                    $this->error = $error;
                }
                if ($this->pendingRead) {
                    $deferred = $this->pendingRead;
                    $this->pendingRead = null;
                    $deferred->fail($error);
                }
            });
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->buffer !== "") {
            $buffer = $this->buffer;
            $this->buffer = "";
            if ($this->backpressure) {
                $backpressure = $this->backpressure;
                $this->backpressure = null;
                $backpressure->resolve();
            }
            return new Success($buffer);
        }
        if ($this->complete) {
            return new Success();
        }
        $this->pendingRead = new Deferred();
        return $this->pendingRead->promise();
    }
    /**
     * @inheritdoc
     */
    public final function onResolve(callable $onResolved)
    {
        $this->buffering = true;
        if ($this->coroutine === null) {
            $this->coroutine = new Coroutine($this->consume());
        }
        if ($this->backpressure) {
            $backpressure = $this->backpressure;
            $this->backpressure = null;
            $backpressure->resolve();
        }
        $this->coroutine->onResolve($onResolved);
    }
    /**
    * Exposes the source input stream.
    *
    * This might be required to resolve a promise with an InputStream, because promises in Amp can't be resolved with
    other promises.
    *
    * @return InputStream
    */
    public final function getInputStream() : InputStream
    {
        return $this->source;
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
/**
 * An `InputStream` allows reading byte streams in chunks.
 *
 * **Example**
 *
 * ```php
 * function readAll(InputStream $in): Promise {
 *     return Amp\call(function () use ($in) {
 *         $buffer = "";
 *
 *         while (($chunk = yield $in->read()) !== null) {
 *             $buffer .= $chunk;
 *         }
 *
 *         return $buffer;
 *     });
 * }
 * ```
 */
interface InputStream
{
    /**
     * Reads data from the stream.
     *
     * @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
     *
     * @psalm-return Promise<(string | null)>
     *
     * @throws PendingReadError Thrown if another read operation is still pending.
     */
    public function read() : Promise;
}<?php

namespace Amp\ByteStream;

use Amp\Deferred;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
/**
 * Input stream abstraction for PHP's stream resources.
 */
final class ResourceInputStream implements InputStream
{
    const DEFAULT_CHUNK_SIZE = 8192;
    /** @var resource|null */
    private $resource;
    /** @var string */
    private $watcher;
    /** @var Deferred|null */
    private $deferred;
    /** @var bool */
    private $readable = true;
    /** @var int */
    private $chunkSize;
    /** @var bool */
    private $useSingleRead;
    /** @var callable */
    private $immediateCallable;
    /** @var string|null */
    private $immediateWatcher;
    /**
     * @param resource $stream Stream resource.
     * @param int $chunkSize Chunk size per read operation.
     *
     * @throws \Error If an invalid stream or parameter has been passed.
     */
    public function __construct($stream, int $chunkSize = self::DEFAULT_CHUNK_SIZE)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== 'stream') {
            throw new \Error("Expected a valid stream");
        }
        $meta = \stream_get_meta_data($stream);
        $useSingleRead = $meta["stream_type"] === "udp_socket" || $meta["stream_type"] === "STDIO";
        $this->useSingleRead = $useSingleRead;
        if (\strpos($meta["mode"], "r") === false && \strpos($meta["mode"], "+") === false) {
            throw new \Error("Expected a readable stream");
        }
        \stream_set_blocking($stream, false);
        \stream_set_read_buffer($stream, 0);
        $this->resource =& $stream;
        $this->chunkSize =& $chunkSize;
        $deferred =& $this->deferred;
        $readable =& $this->readable;
        $this->watcher = Loop::onReadable($this->resource, static function ($watcher) use(&$deferred, &$readable, &$stream, &$chunkSize, $useSingleRead) {
            if ($useSingleRead) {
                $data = @\fread($stream, $chunkSize);
            } else {
                $data = @\stream_get_contents($stream, $chunkSize);
            }
            \assert($data !== false, "Trying to read from a previously fclose()'d resource. Do NOT manually fclose() resources the loop still has a reference to.");
            // Error suppression, because pthreads does crazy things with resources,
            // which might be closed during two operations.
            // See https://github.com/amphp/byte-stream/issues/32
            if ($data === '' && @\feof($stream)) {
                $readable = false;
                $stream = null;
                $data = null;
                // Stream closed, resolve read with null.
                Loop::cancel($watcher);
            } else {
                Loop::disable($watcher);
            }
            $temp = $deferred;
            $deferred = null;
            \assert($temp instanceof Deferred);
            $temp->resolve($data);
        });
        $this->immediateCallable = static function ($watcherId, $data) use(&$deferred) {
            $temp = $deferred;
            $deferred = null;
            \assert($temp instanceof Deferred);
            $temp->resolve($data);
        };
        Loop::disable($this->watcher);
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        if ($this->deferred !== null) {
            throw new PendingReadError();
        }
        if (!$this->readable) {
            return new Success();
            // Resolve with null on closed stream.
        }
        \assert($this->resource !== null);
        // Attempt a direct read, because Windows suffers from slow I/O on STDIN otherwise.
        if ($this->useSingleRead) {
            $data = @\fread($this->resource, $this->chunkSize);
        } else {
            $data = @\stream_get_contents($this->resource, $this->chunkSize);
        }
        \assert($data !== false, "Trying to read from a previously fclose()'d resource. Do NOT manually fclose() resources the loop still has a reference to.");
        if ($data === '') {
            // Error suppression, because pthreads does crazy things with resources,
            // which might be closed during two operations.
            // See https://github.com/amphp/byte-stream/issues/32
            if (@\feof($this->resource)) {
                $this->readable = false;
                $this->resource = null;
                Loop::cancel($this->watcher);
                return new Success();
                // Stream closed, resolve read with null.
            }
            $this->deferred = new Deferred();
            Loop::enable($this->watcher);
            return $this->deferred->promise();
        }
        // Prevent an immediate read â†’ write loop from blocking everything
        // See e.g. examples/benchmark-throughput.php
        $this->deferred = new Deferred();
        $this->immediateWatcher = Loop::defer($this->immediateCallable, $data);
        return $this->deferred->promise();
    }
    /**
     * Closes the stream forcefully. Multiple `close()` calls are ignored.
     *
     * @return void
     */
    public function close()
    {
        if (\is_resource($this->resource)) {
            // Error suppression, as resource might already be closed
            $meta = @\stream_get_meta_data($this->resource);
            if ($meta && \strpos($meta["mode"], "+") !== false) {
                @\stream_socket_shutdown($this->resource, \STREAM_SHUT_RD);
            } else {
                /** @psalm-suppress InvalidPropertyAssignmentValue */
                @\fclose($this->resource);
            }
        }
        $this->free();
    }
    /**
     * Nulls reference to resource, marks stream unreadable, and succeeds any pending read with null.
     *
     * @return void
     */
    private function free()
    {
        $this->readable = false;
        $this->resource = null;
        if ($this->deferred !== null) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->resolve();
        }
        Loop::cancel($this->watcher);
        if ($this->immediateWatcher !== null) {
            Loop::cancel($this->immediateWatcher);
        }
    }
    /**
     * @return (resource | null) The stream resource or null if the stream has closed.
     */
    public function getResource()
    {
        return $this->resource;
    }
    /**
     * @return void
     */
    public function setChunkSize(int $chunkSize)
    {
        $this->chunkSize = $chunkSize;
    }
    /**
     * References the read watcher, so the loop keeps running in case there's an active read.
     *
     * @return void
     *
     * @see Loop::reference()
     */
    public function reference()
    {
        if (!$this->resource) {
            throw new \Error("Resource has already been freed");
        }
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the read watcher, so the loop doesn't keep running even if there are active reads.
     *
     * @return void
     *
     * @see Loop::unreference()
     */
    public function unreference()
    {
        if (!$this->resource) {
            throw new \Error("Resource has already been freed");
        }
        Loop::unreference($this->watcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->resource !== null) {
            $this->free();
        }
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
use function Amp\call;
/**
 * Allows decompression of input streams using Zlib.
 */
final class ZlibInputStream implements InputStream
{
    /** @var InputStream|null */
    private $source;
    /** @var int */
    private $encoding;
    /** @var array */
    private $options;
    /** @var resource|null */
    private $resource;
    /**
     * @param InputStream $source Input stream to read compressed data from.
     * @param int $encoding Compression algorithm used, see `inflate_init()`.
     * @param array $options Algorithm options, see `inflate_init()`.
     *
     * @throws StreamException
     * @throws \Error
     *
     * @see http://php.net/manual/en/function.inflate-init.php
     */
    public function __construct(InputStream $source, int $encoding, array $options = [])
    {
        $this->source = $source;
        $this->encoding = $encoding;
        $this->options = $options;
        $this->resource = @\inflate_init($encoding, $options);
        if ($this->resource === false) {
            throw new StreamException("Failed initializing deflate context");
        }
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        return call(function () {
            if ($this->resource === null) {
                return null;
            }
            \assert($this->source !== null);
            $data = (yield $this->source->read());
            // Needs a double guard, as stream might have been closed while reading
            /** @psalm-suppress ParadoxicalCondition */
            if ($this->resource === null) {
                return null;
            }
            if ($data === null) {
                $decompressed = @\inflate_add($this->resource, "", \ZLIB_FINISH);
                if ($decompressed === false) {
                    throw new StreamException("Failed adding data to deflate context");
                }
                $this->close();
                return $decompressed;
            }
            $decompressed = @\inflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH);
            if ($decompressed === false) {
                throw new StreamException("Failed adding data to deflate context");
            }
            return $decompressed;
        });
    }
    /**
     * @internal
     * @return void
     */
    private function close()
    {
        $this->resource = null;
        $this->source = null;
    }
    /**
     * Gets the used compression encoding.
     *
     * @return int Encoding specified on construction time.
     */
    public function getEncoding() : int
    {
        return $this->encoding;
    }
    /**
     * Gets the used compression options.
     *
     * @return array Options array passed on construction time.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
}<?php

namespace Amp\ByteStream;

class StreamException extends \Exception
{
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
use function Amp\call;
final class LineReader
{
    /** @var string */
    private $delimiter;
    /** @var bool */
    private $lineMode;
    /** @var string */
    private $buffer = "";
    /** @var InputStream */
    private $source;
    /**
     *
     */
    public function __construct(InputStream $inputStream, string $delimiter = null)
    {
        $this->source = $inputStream;
        $this->delimiter = $delimiter === null ? "\n" : $delimiter;
        $this->lineMode = $delimiter === null;
    }
    /**
     * @return Promise<(string | null)>
     */
    public function readLine() : Promise
    {
        return call(function () {
            if (false !== \strpos($this->buffer, $this->delimiter)) {
                list($line, $this->buffer) = \explode($this->delimiter, $this->buffer, 2);
                return $this->lineMode ? \rtrim($line, "\r") : $line;
            }
            while (null !== ($chunk = (yield $this->source->read()))) {
                $this->buffer .= $chunk;
                if (false !== \strpos($this->buffer, $this->delimiter)) {
                    list($line, $this->buffer) = \explode($this->delimiter, $this->buffer, 2);
                    return $this->lineMode ? \rtrim($line, "\r") : $line;
                }
            }
            if ($this->buffer === "") {
                return null;
            }
            $line = $this->buffer;
            $this->buffer = "";
            return $this->lineMode ? \rtrim($line, "\r") : $line;
        });
    }
    /**
     *
     */
    public function getBuffer() : string
    {
        return $this->buffer;
    }
    /**
     * @return void
     */
    public function clearBuffer()
    {
        $this->buffer = "";
    }
}<?php

namespace Amp\ByteStream;

use Amp\Iterator;
use Amp\Loop;
use Amp\Producer;
use Amp\Promise;
use function Amp\call;
// @codeCoverageIgnoreStart
if (\strlen('â€¦') !== 3) {
    throw new \Error('The mbstring.func_overload ini setting is enabled. It must be disabled to use the stream package.');
}
// @codeCoverageIgnoreEnd
if (!\defined('STDOUT')) {
    \define('STDOUT', \fopen('php://stdout', 'w'));
}
if (!\defined('STDERR')) {
    \define('STDERR', \fopen('php://stderr', 'w'));
}
/**
 * @param \Amp\ByteStream\InputStream $source
 * @param \Amp\ByteStream\OutputStream $destination
 *
 * @return \Amp\Promise
 */
function pipe(InputStream $source, OutputStream $destination) : Promise
{
    return call(function () use($source, $destination) : \Generator {
        $written = 0;
        while (($chunk = (yield $source->read())) !== null) {
            $written += \strlen($chunk);
            $writePromise = $destination->write($chunk);
            $chunk = null;
            // free memory
            (yield $writePromise);
        }
        return $written;
    });
}
/**
 * @param \Amp\ByteStream\InputStream $source
 *
 * @return \Amp\Promise
 */
function buffer(InputStream $source) : Promise
{
    return call(function () use($source) : \Generator {
        $buffer = "";
        while (($chunk = (yield $source->read())) !== null) {
            $buffer .= $chunk;
            $chunk = null;
            // free memory
        }
        return $buffer;
    });
}
/**
 * The php://input input buffer stream for the process associated with the currently active event loop.
 *
 * @return ResourceInputStream
 */
function getInputBufferStream() : ResourceInputStream
{
    static $key = InputStream::class . '\\input';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceInputStream(\fopen('php://input', 'rb'));
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The php://output output buffer stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getOutputBufferStream() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\output';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\fopen('php://output', 'wb'));
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDIN stream for the process associated with the currently active event loop.
 *
 * @return ResourceInputStream
 */
function getStdin() : ResourceInputStream
{
    static $key = InputStream::class . '\\stdin';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceInputStream(\STDIN);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDOUT stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getStdout() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\stdout';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\STDOUT);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDERR stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getStderr() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\stderr';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\STDERR);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 *
 */
function parseLineDelimitedJson(InputStream $stream, bool $assoc = false, int $depth = 512, int $options = 0) : Iterator
{
    return new Producer(static function (callable $emit) use($stream, $assoc, $depth, $options) {
        $reader = new LineReader($stream);
        while (null !== ($line = (yield $reader->readLine()))) {
            $line = \trim($line);
            if ($line === '') {
                continue;
            }
            /** @noinspection PhpComposerExtensionStubsInspection */
            $data = \json_decode($line, $assoc, $depth, $options);
            /** @noinspection PhpComposerExtensionStubsInspection */
            $error = \json_last_error();
            /** @noinspection PhpComposerExtensionStubsInspection */
            if ($error !== \JSON_ERROR_NONE) {
                /** @noinspection PhpComposerExtensionStubsInspection */
                throw new StreamException('Failed to parse JSON: ' . \json_last_error_msg(), $error);
            }
            (yield $emit($data));
        }
    });
}<?php

namespace Amp\ByteStream;

final class ClosedException extends StreamException
{
}<?php

namespace Amp\ByteStream;

use Amp\Coroutine;
use Amp\Promise;
use function Amp\call;
/**
 * Creates a buffered message from an InputStream. The message can be consumed in chunks using the read() API or it may
 * be buffered and accessed in its entirety by calling buffer(). Once buffering is requested through buffer(), the
 * stream cannot be read in chunks. On destruct any remaining data is read from the InputStream given to this class.
 */
class Payload implements InputStream
{
    /** @var InputStream */
    private $stream;
    /** @var \Amp\Promise|null */
    private $promise;
    /** @var \Amp\Promise|null */
    private $lastRead;
    /**
     * @param \Amp\ByteStream\InputStream $stream
     */
    public function __construct(InputStream $stream)
    {
        $this->stream = $stream;
    }
    /**
     *
     */
    public function __destruct()
    {
        if (!$this->promise) {
            Promise\rethrow(new Coroutine($this->consume()));
        }
    }
    /**
     *
     */
    private function consume() : \Generator
    {
        try {
            if ($this->lastRead && null === (yield $this->lastRead)) {
                return;
            }
            while (null !== (yield $this->stream->read())) {
                // Discard unread bytes from message.
            }
        } catch (\Throwable $exception) {
            // If exception is thrown here the connection closed anyway.
        }
    }
    /**
     * @inheritdoc
     *
     * @throws \Error If a buffered message was requested by calling buffer().
     */
    public final function read() : Promise
    {
        if ($this->promise) {
            throw new \Error("Cannot stream message data once a buffered message has been requested");
        }
        return $this->lastRead = $this->stream->read();
    }
    /**
     * Buffers the entire message and resolves the returned promise then.
     *
     * @return Promise<string> Resolves with the entire message contents.
     */
    public final function buffer() : Promise
    {
        if ($this->promise) {
            return $this->promise;
        }
        return $this->promise = call(function () {
            $buffer = '';
            if ($this->lastRead && null === (yield $this->lastRead)) {
                return $buffer;
            }
            while (null !== ($chunk = (yield $this->stream->read()))) {
                $buffer .= $chunk;
            }
            return $buffer;
        });
    }
}<?php

namespace Amp\ByteStream;

/**
 * Thrown in case a second read operation is attempted while another read operation is still pending.
 */
final class PendingReadError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = "The previous read operation must complete before read can be called again", int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
/**
 * Allows compression of output streams using Zlib.
 */
final class ZlibOutputStream implements OutputStream
{
    /** @var OutputStream|null */
    private $destination;
    /** @var int */
    private $encoding;
    /** @var array */
    private $options;
    /** @var resource|null */
    private $resource;
    /**
     * @param OutputStream $destination Output stream to write the compressed data to.
     * @param int $encoding Compression encoding to use, see `deflate_init()`.
     * @param array $options Compression options to use, see `deflate_init()`.
     *
     * @throws StreamException If an invalid encoding or invalid options have been passed.
     *
     * @see http://php.net/manual/en/function.deflate-init.php
     */
    public function __construct(OutputStream $destination, int $encoding, array $options = [])
    {
        $this->destination = $destination;
        $this->encoding = $encoding;
        $this->options = $options;
        $this->resource = @\deflate_init($encoding, $options);
        if ($this->resource === false) {
            throw new StreamException("Failed initializing deflate context");
        }
    }
    /**
     * @inheritdoc
     */
    public function write(string $data) : Promise
    {
        if ($this->resource === null) {
            throw new ClosedException("The stream has already been closed");
        }
        \assert($this->destination !== null);
        $compressed = \deflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH);
        if ($compressed === false) {
            throw new StreamException("Failed adding data to deflate context");
        }
        $promise = $this->destination->write($compressed);
        $promise->onResolve(function ($error) {
            if ($error) {
                $this->close();
            }
        });
        return $promise;
    }
    /**
     * @inheritdoc
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->resource === null) {
            throw new ClosedException("The stream has already been closed");
        }
        \assert($this->destination !== null);
        $compressed = \deflate_add($this->resource, $finalData, \ZLIB_FINISH);
        if ($compressed === false) {
            throw new StreamException("Failed adding data to deflate context");
        }
        $promise = $this->destination->end($compressed);
        $promise->onResolve(function () {
            $this->close();
        });
        return $promise;
    }
    /**
     * @internal
     * @return void
     */
    private function close()
    {
        $this->resource = null;
        $this->destination = null;
    }
    /**
     * Gets the used compression encoding.
     *
     * @return int Encoding specified on construction time.
     */
    public function getEncoding() : int
    {
        return $this->encoding;
    }
    /**
     * Gets the used compression options.
     *
     * @return array Options array passed on construction time.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
}<?php

namespace Amp\ByteStream;

use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
class OutputBuffer implements OutputStream, Promise
{
    /** @var Deferred */
    private $deferred;
    /** @var string */
    private $contents = '';
    /** @var bool */
    private $closed = false;
    /**
     *
     */
    public function __construct()
    {
        $this->deferred = new Deferred();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->closed) {
            throw new ClosedException("The stream has already been closed.");
        }
        $this->contents .= $data;
        return new Success(\strlen($data));
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->closed) {
            throw new ClosedException("The stream has already been closed.");
        }
        $this->contents .= $finalData;
        $this->closed = true;
        $this->deferred->resolve($this->contents);
        $this->contents = "";
        return new Success(\strlen($finalData));
    }
    /**
     *
     */
    public function onResolve(callable $onResolved)
    {
        $this->deferred->promise()->onResolve($onResolved);
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
use Amp\Success;
/**
 * Input stream with a single already known data chunk.
 */
final class InMemoryStream implements InputStream
{
    private $contents;
    /**
     * @param (string | null) $contents Data chunk or `null` for no data chunk.
     */
    public function __construct(string $contents = null)
    {
        $this->contents = $contents;
    }
    /**
     * Reads data from the stream.
     *
     * @return Promise<(string | null)> Resolves with the full contents or `null` if the stream has closed / already been consumed.
     */
    public function read() : Promise
    {
        if ($this->contents === null) {
            return new Success();
        }
        $promise = new Success($this->contents);
        $this->contents = null;
        return $promise;
    }
}{
    "name": "amphp/dns",
    "homepage": "https://github.com/amphp/dns",
    "description": "Async DNS resolution for Amp.",
    "keywords": [
        "dns",
        "resolve",
        "client",
        "async",
        "amp",
        "amphp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Chris Wright",
            "email": "addr@daverandom.com"
        },
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.0",
        "ext-json": "*",
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.1",
        "amphp/cache": "^1.2",
        "amphp/parser": "^1",
        "amphp/windows-registry": "^0.3",
        "daverandom/libdns": "^2.0.1",
        "ext-filter": "*"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1",
        "phpunit/phpunit": "^6 || ^7 || ^8 || ^9",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Dns\\": "lib"
        },
        "files": [
            "lib/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Dns\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Dns\Internal;

use Amp;
use Amp\Deferred;
use Amp\Dns\DnsException;
use Amp\Dns\TimeoutException;
use Amp\Loop;
use Amp\Parser\Parser;
use Amp\Promise;
use Amp\Success;
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Messages\Message;
use function Amp\call;
/** @internal */
final class TcpSocket extends Socket
{
    /** @var \LibDNS\Encoder\Encoder */
    private $encoder;
    /** @var \SplQueue */
    private $queue;
    /** @var Parser */
    private $parser;
    /** @var bool */
    private $isAlive = true;
    /**
     *
     */
    public static function connect(string $uri, int $timeout = 5000) : Promise
    {
        if (!($socket = @\stream_socket_client($uri, $errno, $errstr, 0, STREAM_CLIENT_ASYNC_CONNECT))) {
            throw new DnsException(\sprintf("Connection to %s failed: [Error #%d] %s", $uri, $errno, $errstr));
        }
        \stream_set_blocking($socket, false);
        return call(function () use($uri, $socket, $timeout) {
            $deferred = new Deferred();
            $watcher = Loop::onWritable($socket, static function () use($socket, $deferred) {
                $deferred->resolve(new self($socket));
            });
            try {
                return (yield Promise\timeout($deferred->promise(), $timeout));
            } catch (Amp\TimeoutException $e) {
                throw new TimeoutException("Name resolution timed out, could not connect to server at {$uri}");
            } finally {
                Loop::cancel($watcher);
            }
        });
    }
    /**
     *
     */
    public static function parser(callable $callback) : \Generator
    {
        $decoder = (new DecoderFactory())->create();
        while (true) {
            $length = (yield 2);
            $length = \unpack("n", $length)[1];
            $rawData = (yield $length);
            $callback($decoder->decode($rawData));
        }
    }
    /**
     *
     */
    protected function __construct($socket)
    {
        parent::__construct($socket);
        $this->encoder = (new EncoderFactory())->create();
        $this->queue = new \SplQueue();
        $this->parser = new Parser(self::parser([$this->queue, 'push']));
    }
    /**
     *
     */
    protected function send(Message $message) : Promise
    {
        $data = $this->encoder->encode($message);
        $promise = $this->write(\pack("n", \strlen($data)) . $data);
        $promise->onResolve(function ($error) {
            if ($error) {
                $this->isAlive = false;
            }
        });
        return $promise;
    }
    /**
     *
     */
    protected function receive() : Promise
    {
        if ($this->queue->isEmpty()) {
            return call(function () {
                do {
                    $chunk = (yield $this->read());
                    if ($chunk === null) {
                        $this->isAlive = false;
                        throw new DnsException("Reading from the server failed");
                    }
                    $this->parser->push($chunk);
                } while ($this->queue->isEmpty());
                return $this->queue->shift();
            });
        }
        return new Success($this->queue->shift());
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return $this->isAlive;
    }
}<?php

namespace Amp\Dns\Internal;

use Amp\Dns\DnsException;
use Amp\Promise;
use Amp\Success;
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Messages\Message;
use function Amp\call;
/** @internal */
final class UdpSocket extends Socket
{
    /** @var \LibDNS\Encoder\Encoder */
    private $encoder;
    /** @var \LibDNS\Decoder\Decoder */
    private $decoder;
    /**
     *
     */
    public static function connect(string $uri) : Promise
    {
        if (!($socket = @\stream_socket_client($uri, $errno, $errstr, 0, STREAM_CLIENT_ASYNC_CONNECT))) {
            throw new DnsException(\sprintf("Connection to %s failed: [Error #%d] %s", $uri, $errno, $errstr));
        }
        return new Success(new self($socket));
    }
    /**
     *
     */
    protected function __construct($socket)
    {
        parent::__construct($socket);
        $this->encoder = (new EncoderFactory())->create();
        $this->decoder = (new DecoderFactory())->create();
    }
    /**
     *
     */
    protected function send(Message $message) : Promise
    {
        $data = $this->encoder->encode($message);
        return $this->write($data);
    }
    /**
     *
     */
    protected function receive() : Promise
    {
        return call(function () {
            $data = (yield $this->read());
            if ($data === null) {
                throw new DnsException("Reading from the server failed");
            }
            return $this->decoder->decode($data);
        });
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return true;
    }
}<?php

namespace Amp\Dns\Internal;

use Amp;
use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Dns\DnsException;
use Amp\Dns\TimeoutException;
use Amp\Promise;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Records\Question;
use function Amp\call;
/** @internal */
abstract class Socket
{
    const MAX_CONCURRENT_REQUESTS = 500;
    /** @var ResourceInputStream */
    private $input;
    /** @var ResourceOutputStream */
    private $output;
    /** @var array Contains already sent queries with no response yet. For UDP this is exactly zero or one item. */
    private $pending = [];
    /** @var MessageFactory */
    private $messageFactory;
    /** @var callable */
    private $onResolve;
    /** @var int Used for determining whether the socket can be garbage collected, because it's inactive. */
    private $lastActivity;
    /** @var bool */
    private $receiving = false;
    /** @var array Queued requests if the number of concurrent requests is too large. */
    private $queue = [];
    /**
     * @param string $uri
     *
     * @return Promise<self>
     */
    public static abstract function connect(string $uri) : Promise;
    /**
     * @param Message $message
     *
     * @return Promise<int>
     */
    protected abstract function send(Message $message) : Promise;
    /**
     * @return Promise<Message>
     */
    protected abstract function receive() : Promise;
    /**
     * @return bool
     */
    public abstract function isAlive() : bool;
    /**
     *
     */
    public function getLastActivity() : int
    {
        return $this->lastActivity;
    }
    /**
     *
     */
    protected function __construct($socket)
    {
        $this->input = new ResourceInputStream($socket);
        $this->output = new ResourceOutputStream($socket);
        $this->messageFactory = new MessageFactory();
        $this->lastActivity = \time();
        $this->onResolve = function (\Throwable $exception = null, Message $message = null) {
            $this->lastActivity = \time();
            $this->receiving = false;
            if ($exception) {
                $this->error($exception);
                return;
            }
            \assert($message instanceof Message);
            $id = $message->getId();
            // Ignore duplicate and invalid responses.
            if (isset($this->pending[$id]) && $this->matchesQuestion($message, $this->pending[$id]->question)) {
                /** @var Deferred $deferred */
                $deferred = $this->pending[$id]->deferred;
                unset($this->pending[$id]);
                $deferred->resolve($message);
            }
            if (empty($this->pending)) {
                $this->input->unreference();
            } elseif (!$this->receiving) {
                $this->input->reference();
                $this->receiving = true;
                $this->receive()->onResolve($this->onResolve);
            }
        };
    }
    /**
     * @param \LibDNS\Records\Question $question
     * @param int $timeout
     *
     * @return \Amp\Promise<\LibDNS\Messages\Message>
     */
    public final function ask(Question $question, int $timeout) : Promise
    {
        return call(function () use($question, $timeout) {
            $this->lastActivity = \time();
            if (\count($this->pending) > self::MAX_CONCURRENT_REQUESTS) {
                $deferred = new Deferred();
                $this->queue[] = $deferred;
                (yield $deferred->promise());
            }
            do {
                $id = \random_int(0, 0xffff);
            } while (isset($this->pending[$id]));
            $deferred = new Deferred();
            $pending = new class
            {
                use Amp\Struct;
                public $deferred;
                public $question;
            };
            $pending->deferred = $deferred;
            $pending->question = $question;
            $this->pending[$id] = $pending;
            $message = $this->createMessage($question, $id);
            try {
                (yield $this->send($message));
            } catch (StreamException $exception) {
                $exception = new DnsException("Sending the request failed", 0, $exception);
                $this->error($exception);
                throw $exception;
            }
            $this->input->reference();
            if (!$this->receiving) {
                $this->receiving = true;
                $this->receive()->onResolve($this->onResolve);
            }
            try {
                // Work around an OPCache issue that returns an empty array with "return yield ...",
                // so assign to a variable first and return after the try block.
                //
                // See https://github.com/amphp/dns/issues/58.
                // See https://bugs.php.net/bug.php?id=74840.
                $result = (yield Promise\timeout($deferred->promise(), $timeout));
            } catch (Amp\TimeoutException $exception) {
                unset($this->pending[$id]);
                if (empty($this->pending)) {
                    $this->input->unreference();
                }
                throw new TimeoutException("Didn't receive a response within {$timeout} milliseconds.");
            } finally {
                if ($this->queue) {
                    $deferred = \array_shift($this->queue);
                    $deferred->resolve();
                }
            }
            return $result;
        });
    }
    /**
     *
     */
    public final function close()
    {
        $this->input->close();
        $this->output->close();
    }
    /**
     *
     */
    private function error(\Throwable $exception)
    {
        $this->close();
        if (empty($this->pending)) {
            return;
        }
        if (!$exception instanceof DnsException) {
            $message = "Unexpected error during resolution: " . $exception->getMessage();
            $exception = new DnsException($message, 0, $exception);
        }
        $pending = $this->pending;
        $this->pending = [];
        foreach ($pending as $pendingQuestion) {
            /** @var Deferred $deferred */
            $deferred = $pendingQuestion->deferred;
            $deferred->fail($exception);
        }
    }
    /**
     *
     */
    protected final function read() : Promise
    {
        return $this->input->read();
    }
    /**
     *
     */
    protected final function write(string $data) : Promise
    {
        return $this->output->write($data);
    }
    /**
     *
     */
    protected final function createMessage(Question $question, int $id) : Message
    {
        $request = $this->messageFactory->create(MessageTypes::QUERY);
        $request->getQuestionRecords()->add($question);
        $request->isRecursionDesired(true);
        $request->setID($id);
        return $request;
    }
    /**
     *
     */
    private function matchesQuestion(Message $message, Question $question) : bool
    {
        if ($message->getType() !== MessageTypes::RESPONSE) {
            return false;
        }
        $questionRecords = $message->getQuestionRecords();
        // We only ever ask one question at a time
        if (\count($questionRecords) !== 1) {
            return false;
        }
        $questionRecord = $questionRecords->getIterator()->current();
        if ($questionRecord->getClass() !== $question->getClass()) {
            return false;
        }
        if ($questionRecord->getType() !== $question->getType()) {
            return false;
        }
        if ($questionRecord->getName()->getValue() !== $question->getName()->getValue()) {
            return false;
        }
        return true;
    }
}<?php

namespace Amp\Dns;

use Amp\Failure;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
class UnixConfigLoader implements ConfigLoader
{
    const MAX_NAMESERVERS = 3;
    const MAX_DNS_SEARCH = 6;
    const MAX_TIMEOUT = 30 * 1000;
    const MAX_ATTEMPTS = 5;
    const MAX_NDOTS = 15;
    const DEFAULT_TIMEOUT = 5 * 1000;
    const DEFAULT_ATTEMPTS = 2;
    const DEFAULT_NDOTS = 1;
    const DEFAULT_OPTIONS = ["timeout" => self::DEFAULT_TIMEOUT, "attempts" => self::DEFAULT_ATTEMPTS, "ndots" => self::DEFAULT_NDOTS, "rotate" => false];
    private $path;
    private $hostLoader;
    /**
     *
     */
    public function __construct(string $path = "/etc/resolv.conf", HostLoader $hostLoader = null)
    {
        $this->path = $path;
        $this->hostLoader = $hostLoader ?? new HostLoader();
    }
    /**
     *
     */
    protected function readFile(string $path) : Promise
    {
        \set_error_handler(function (int $errno, string $message) use($path) {
            throw new ConfigException("Could not read configuration file '{$path}' ({$errno}) {$message}");
        });
        try {
            // Blocking file access, but this file should be local and usually loaded only once.
            $fileContent = \file_get_contents($path);
        } catch (ConfigException $exception) {
            return new Failure($exception);
        } finally {
            \restore_error_handler();
        }
        return new Success($fileContent);
    }
    /**
     *
     */
    public final function loadConfig() : Promise
    {
        return call(function () {
            $nameservers = [];
            $searchList = [];
            $options = self::DEFAULT_OPTIONS;
            $haveLocaldomainEnv = false;
            /* Allow user to override the local domain definition.  */
            if ($localdomain = \getenv("LOCALDOMAIN")) {
                /* Set search list to be blank-separated strings from rest of
                   env value.  Permits users of LOCALDOMAIN to still have a
                   search list, and anyone to set the one that they want to use
                   as an individual (even more important now that the rfc1535
                   stuff restricts searches).  */
                $searchList = $this->splitOnWhitespace($localdomain);
                $haveLocaldomainEnv = true;
            }
            $fileContent = (yield $this->readFile($this->path));
            $lines = \explode("\n", $fileContent);
            foreach ($lines as $line) {
                $line = \preg_split('#\\s+#', $line, 2);
                if (\count($line) !== 2) {
                    continue;
                }
                list($type, $value) = $line;
                if ($type === "nameserver") {
                    if (\count($nameservers) === self::MAX_NAMESERVERS) {
                        continue;
                    }
                    $value = \trim($value);
                    $ip = @\inet_pton($value);
                    if ($ip === false) {
                        continue;
                    }
                    if (isset($ip[15])) {
                        // IPv6
                        $nameservers[] = "[" . $value . "]:53";
                    } else {
                        // IPv4
                        $nameservers[] = $value . ":53";
                    }
                } elseif ($type === "domain" && !$haveLocaldomainEnv) {
                    // LOCALDOMAIN env overrides config
                    $searchList = $this->splitOnWhitespace($value);
                } elseif ($type === "search" && !$haveLocaldomainEnv) {
                    // LOCALDOMAIN env overrides config
                    $searchList = $this->splitOnWhitespace($value);
                } elseif ($type === "options") {
                    $option = $this->parseOption($value);
                    if (\count($option) === 2) {
                        $options[$option[0]] = $option[1];
                    }
                }
            }
            $hosts = (yield $this->hostLoader->loadHosts());
            if (\count($searchList) === 0) {
                $hostname = \gethostname();
                $dot = \strpos(".", $hostname);
                if ($dot !== false && $dot < \strlen($hostname)) {
                    $searchList = [\Phabel\Target\Php80\Polyfill::substr($hostname, $dot)];
                }
            }
            if (\count($searchList) > self::MAX_DNS_SEARCH) {
                $searchList = \array_slice($searchList, 0, self::MAX_DNS_SEARCH);
            }
            $resOptions = \getenv("RES_OPTIONS");
            if ($resOptions) {
                foreach ($this->splitOnWhitespace($resOptions) as $option) {
                    $option = $this->parseOption($option);
                    if (\count($option) === 2) {
                        $options[$option[0]] = $option[1];
                    }
                }
            }
            $config = new Config($nameservers, $hosts, $options["timeout"], $options["attempts"]);
            return $config->withSearchList($searchList)->withNdots($options["ndots"])->withRotationEnabled($options["rotate"]);
        });
    }
    /**
     *
     */
    private function splitOnWhitespace(string $names) : array
    {
        return \preg_split("#\\s+#", \trim($names));
    }
    /**
     *
     */
    private function parseOption(string $option) : array
    {
        $optline = \explode(':', $option, 2);
        list($name, $value) = $optline + [1 => null];
        switch ($name) {
            case "timeout":
                $value = (int) $value;
                if ($value < 0) {
                    return [];
                    // don't overwrite option value
                }
                // The value for this option is silently capped to 30s
                return ["timeout", (int) \min($value * 1000, self::MAX_TIMEOUT)];
            case "attempts":
                $value = (int) $value;
                if ($value < 0) {
                    return [];
                    // don't overwrite option value
                }
                // The value for this option is silently capped to 5
                return ["attempts", (int) \min($value, self::MAX_ATTEMPTS)];
            case "ndots":
                $value = (int) $value;
                if ($value < 0) {
                    return [];
                    // don't overwrite option value
                }
                // The value for this option is silently capped to 15
                return ["ndots", (int) \min($value, self::MAX_NDOTS)];
            case "rotate":
                return ["rotate", true];
        }
        return [];
    }
}<?php

namespace Amp\Dns;

final class Config
{
    /** @var array */
    private $nameservers;
    /** @var array */
    private $knownHosts;
    /** @var int */
    private $timeout;
    /** @var int */
    private $attempts;
    /** @var array */
    private $searchList = [];
    /** @var int */
    private $ndots = 1;
    /** @var bool */
    private $rotation = false;
    /**
     *
     */
    public function __construct(array $nameservers, array $knownHosts = [], int $timeout = 3000, int $attempts = 2)
    {
        if (\count($nameservers) < 1) {
            throw new ConfigException("At least one nameserver is required for a valid config");
        }
        foreach ($nameservers as $nameserver) {
            $this->validateNameserver($nameserver);
        }
        if ($timeout < 0) {
            throw new ConfigException("Invalid timeout ({$timeout}), must be 0 or greater");
        }
        if ($attempts < 1) {
            throw new ConfigException("Invalid attempt count ({$attempts}), must be 1 or greater");
        }
        // Windows does not include localhost in its host file. Fetch it from the system instead
        if (!isset($knownHosts[Record::A]["localhost"]) && !isset($knownHosts[Record::AAAA]["localhost"])) {
            // PHP currently provides no way to **resolve** IPv6 hostnames (not even with fallback)
            $local = \gethostbyname("localhost");
            if ($local !== "localhost") {
                $knownHosts[Record::A]["localhost"] = $local;
            } else {
                $knownHosts[Record::AAAA]["localhost"] = '::1';
            }
        }
        $this->nameservers = $nameservers;
        $this->knownHosts = $knownHosts;
        $this->timeout = $timeout;
        $this->attempts = $attempts;
    }
    /**
     *
     */
    public function withSearchList(array $searchList) : self
    {
        $self = clone $this;
        $self->searchList = $searchList;
        return $self;
    }
    /**
     * @throws ConfigException
     */
    public function withNdots(int $ndots) : self
    {
        if ($ndots < 0) {
            throw new ConfigException("Invalid ndots ({$ndots}), must be greater or equal to 0");
        }
        if ($ndots > 15) {
            $ndots = 15;
        }
        $self = clone $this;
        $self->ndots = $ndots;
        return $self;
    }
    /**
     *
     */
    public function withRotationEnabled(bool $enabled = true) : self
    {
        $self = clone $this;
        $self->rotation = $enabled;
        return $self;
    }
    /**
     *
     */
    private function validateNameserver($nameserver)
    {
        if (!$nameserver || !\is_string($nameserver)) {
            throw new ConfigException("Invalid nameserver: {$nameserver}");
        }
        if ($nameserver[0] === "[") {
            // IPv6
            $addr = \strstr(\Phabel\Target\Php80\Polyfill::substr($nameserver, 1), "]", true);
            $port = \Phabel\Target\Php80\Polyfill::substr($nameserver, \strrpos($nameserver, "]") + 1);
            if ($port !== "" && !\preg_match("(^:(\\d+)\$)", $port, $match)) {
                throw new ConfigException("Invalid nameserver: {$nameserver}");
            }
            $port = $port === "" ? 53 : \Phabel\Target\Php80\Polyfill::substr($port, 1);
        } else {
            // IPv4
            $arr = \explode(":", $nameserver, 2);
            if (\count($arr) === 2) {
                list($addr, $port) = $arr;
            } else {
                $addr = $arr[0];
                $port = 53;
            }
        }
        $addr = \trim($addr, "[]");
        $port = (int) $port;
        if (!($inAddr = @\inet_pton($addr))) {
            throw new ConfigException("Invalid server IP: {$addr}");
        }
        if ($port < 1 || $port > 65535) {
            throw new ConfigException("Invalid server port: {$port}");
        }
    }
    /**
     *
     */
    public function getNameservers() : array
    {
        return $this->nameservers;
    }
    /**
     *
     */
    public function getKnownHosts() : array
    {
        return $this->knownHosts;
    }
    /**
     *
     */
    public function getTimeout() : int
    {
        return $this->timeout;
    }
    /**
     *
     */
    public function getAttempts() : int
    {
        return $this->attempts;
    }
    /**
     *
     */
    public function getSearchList() : array
    {
        return $this->searchList;
    }
    /**
     *
     */
    public function getNdots() : int
    {
        return $this->ndots;
    }
    /**
     *
     */
    public function isRotationEnabled() : bool
    {
        return $this->rotation;
    }
}<?php

namespace Amp\Dns;

use Amp\Promise;
interface ConfigLoader
{
    /**
     *
     */
    public function loadConfig() : Promise;
}<?php

namespace Amp\Dns;

use Throwable;
/**
 * MUST be thrown in case the config can't be read and no fallback is available.
 */
class ConfigException extends DnsException
{
    /**
     *
     */
    public function __construct(string $message, Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
    }
}<?php

namespace Amp\Dns;

use Amp\Promise;
interface Resolver
{
    /**
     * Resolves a hostname name to an IP address [hostname as defined by RFC 3986].
     *
     * Upon success the returned promise resolves to an array of Record objects.
     *
     * A null $ttl value indicates the DNS name was resolved from the cache or the local hosts file.
     *
     * @param string $name The hostname to resolve.
     * @param int $typeRestriction Optional type restriction to `Record::A` or `Record::AAAA`, otherwise `null`.
     *
     * @return Promise
     */
    public function resolve(string $name, int $typeRestriction = null) : Promise;
    /**
     * Query specific DNS records.
     *
     * Upon success the returned promise resolves to an array of Record objects.
     *
     * @param string $name Record to question, A, AAAA and PTR queries are automatically normalized.
     * @param int $type Use constants of Amp\Dns\Record.
     *
     * @return Promise
     */
    public function query(string $name, int $type) : Promise;
}<?php

namespace Amp\Dns;

use Amp\Promise;
use Amp\WindowsRegistry\KeyNotFoundException;
use Amp\WindowsRegistry\WindowsRegistry;
use function Amp\call;
final class WindowsConfigLoader implements ConfigLoader
{
    private $hostLoader;
    /**
     *
     */
    public function __construct(HostLoader $hostLoader = null)
    {
        $this->hostLoader = $hostLoader ?? new HostLoader();
    }
    /**
     *
     */
    public function loadConfig() : Promise
    {
        return call(function () {
            $keys = ["HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\NameServer", "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\DhcpNameServer"];
            $reader = new WindowsRegistry();
            $nameserver = "";
            while ($nameserver === "" && ($key = \array_shift($keys))) {
                try {
                    $nameserver = (yield $reader->read($key));
                } catch (KeyNotFoundException $e) {
                    // retry other possible locations
                }
            }
            if ($nameserver === "") {
                $interfaces = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
                $subKeys = (yield $reader->listKeys($interfaces));
                foreach ($subKeys as $key) {
                    foreach (["NameServer", "DhcpNameServer"] as $property) {
                        try {
                            $nameserver = (yield $reader->read("{$key}\\{$property}"));
                            if ($nameserver !== "") {
                                break 2;
                            }
                        } catch (KeyNotFoundException $e) {
                            // retry other possible locations
                        }
                    }
                }
            }
            if ($nameserver === "") {
                throw new ConfigException("Could not find a nameserver in the Windows Registry");
            }
            $nameservers = [];
            // Microsoft documents space as delimiter, AppVeyor uses comma, we just accept both
            foreach (\explode(" ", \strtr($nameserver, ",", " ")) as $nameserver) {
                $nameserver = \trim($nameserver);
                $ip = @\inet_pton($nameserver);
                if ($ip === false) {
                    continue;
                }
                if (isset($ip[15])) {
                    // IPv6
                    $nameservers[] = "[" . $nameserver . "]:53";
                } else {
                    // IPv4
                    $nameservers[] = $nameserver . ":53";
                }
            }
            $hosts = (yield $this->hostLoader->loadHosts());
            return new Config($nameservers, $hosts);
        });
    }
}<?php

namespace Amp\Dns;

class NoRecordException extends DnsException
{
}<?php

namespace Amp\Dns;

use Amp\Failure;
use Amp\Promise;
use Amp\Success;
class BlockingFallbackResolver implements Resolver
{
    /**
     *
     */
    public function resolve(string $name, int $typeRestriction = null) : Promise
    {
        if (!\in_array($typeRestriction, [Record::A, null], true)) {
            return new Failure(new DnsException("Query for '{$name}' failed, because loading the system's DNS configuration failed and querying records other than A records isn't supported in blocking fallback mode."));
        }
        return $this->query($name, Record::A);
    }
    /**
     *
     */
    public function query(string $name, int $type) : Promise
    {
        if ($type !== Record::A) {
            return new Failure(new DnsException("Query for '{$name}' failed, because loading the system's DNS configuration failed and querying records other than A records isn't supported in blocking fallback mode."));
        }
        $result = \gethostbynamel($name);
        if ($result === false) {
            return new Failure(new DnsException("Query for '{$name}' failed, because loading the system's DNS configuration failed and blocking fallback via gethostbynamel() failed, too."));
        }
        if ($result === []) {
            return new Failure(new NoRecordException("No records returned for '{$name}' using blocking fallback mode."));
        }
        $records = [];
        foreach ($result as $record) {
            $records[] = new Record($record, Record::A, null);
        }
        return new Success($records);
    }
}<?php

namespace Amp\Dns;

use Amp\Loop;
use Amp\Promise;
const LOOP_STATE_IDENTIFIER = Resolver::class;
/**
 * Retrieve the application-wide dns resolver instance.
 *
 * @param \Amp\Dns\Resolver $resolver Optionally specify a new default dns resolver instance
 *
 * @return \Amp\Dns\Resolver Returns the application-wide dns resolver instance
 */
function resolver(Resolver $resolver = null) : Resolver
{
    if ($resolver === null) {
        $resolver = Loop::getState(LOOP_STATE_IDENTIFIER);
        if ($resolver) {
            return $resolver;
        }
        $resolver = createDefaultResolver();
    }
    Loop::setState(LOOP_STATE_IDENTIFIER, $resolver);
    return $resolver;
}
/**
 * Create a new dns resolver best-suited for the current environment.
 *
 * @return \Amp\Dns\Resolver
 */
function createDefaultResolver() : Resolver
{
    return new Rfc1035StubResolver();
}
/**
 * @see Resolver::resolve()
 */
function resolve(string $name, int $typeRestriction = null) : Promise
{
    return resolver()->resolve($name, $typeRestriction);
}
/**
 * @see Resolver::query()
 */
function query(string $name, int $type) : Promise
{
    return resolver()->query($name, $type);
}
/**
 * Checks whether a string is a valid DNS name.
 *
 * @param string $name String to check.
 *
 * @return bool
 */
function isValidName(string $name)
{
    try {
        normalizeName($name);
        return true;
    } catch (InvalidNameException $e) {
        return false;
    }
}
/**
 * Normalizes a DNS name and automatically checks it for validity.
 *
 * @param string $name DNS name.
 *
 * @return string Normalized DNS name.
 * @throws InvalidNameException If an invalid name or an IDN name without ext/intl being installed has been passed.
 */
function normalizeName(string $name) : string
{
    static $pattern = '/^(?<name>[a-z0-9]([a-z0-9-_]{0,61}[a-z0-9])?)(\\.(?&name))*\\.?$/i';
    if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) {
        if (false === ($result = \idn_to_ascii($name, 0, \INTL_IDNA_VARIANT_UTS46))) {
            throw new InvalidNameException("Name '{$name}' could not be processed for IDN.");
        }
        $name = $result;
    } elseif (\preg_match('/[\\x80-\\xff]/', $name)) {
        throw new InvalidNameException("Name '{$name}' contains non-ASCII characters and IDN support is not available. " . "Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.");
    }
    if (isset($name[253]) || !\preg_match($pattern, $name)) {
        throw new InvalidNameException("Name '{$name}' is not a valid hostname.");
    }
    if ($name[\strlen($name) - 1] === '.') {
        $name = \Phabel\Target\Php80\Polyfill::substr($name, 0, -1);
    }
    return $name;
}<?php

namespace Amp\Dns;

class DnsException extends \Exception
{
}<?php

namespace Amp\Dns;

class TimeoutException extends DnsException
{
}<?php

namespace Amp\Dns;

class InvalidNameException extends DnsException
{
}<?php

namespace Amp\Dns;

use LibDNS\Records\ResourceQTypes;
use LibDNS\Records\ResourceTypes;
final class Record
{
    const A = ResourceTypes::A;
    const AAAA = ResourceTypes::AAAA;
    const AFSDB = ResourceTypes::AFSDB;
    // const APL = ResourceTypes::APL;
    const CAA = ResourceTypes::CAA;
    const CERT = ResourceTypes::CERT;
    const CNAME = ResourceTypes::CNAME;
    const DHCID = ResourceTypes::DHCID;
    const DLV = ResourceTypes::DLV;
    const DNAME = ResourceTypes::DNAME;
    const DNSKEY = ResourceTypes::DNSKEY;
    const DS = ResourceTypes::DS;
    const HINFO = ResourceTypes::HINFO;
    // const HIP = ResourceTypes::HIP;
    // const IPSECKEY = ResourceTypes::IPSECKEY;
    const KEY = ResourceTypes::KEY;
    const KX = ResourceTypes::KX;
    const ISDN = ResourceTypes::ISDN;
    const LOC = ResourceTypes::LOC;
    const MB = ResourceTypes::MB;
    const MD = ResourceTypes::MD;
    const MF = ResourceTypes::MF;
    const MG = ResourceTypes::MG;
    const MINFO = ResourceTypes::MINFO;
    const MR = ResourceTypes::MR;
    const MX = ResourceTypes::MX;
    const NAPTR = ResourceTypes::NAPTR;
    const NS = ResourceTypes::NS;
    // const NSEC = ResourceTypes::NSEC;
    // const NSEC3 = ResourceTypes::NSEC3;
    // const NSEC3PARAM = ResourceTypes::NSEC3PARAM;
    const NULL = ResourceTypes::NULL;
    const PTR = ResourceTypes::PTR;
    const RP = ResourceTypes::RP;
    // const RRSIG = ResourceTypes::RRSIG;
    const RT = ResourceTypes::RT;
    const SIG = ResourceTypes::SIG;
    const SOA = ResourceTypes::SOA;
    const SPF = ResourceTypes::SPF;
    const SRV = ResourceTypes::SRV;
    const TXT = ResourceTypes::TXT;
    const WKS = ResourceTypes::WKS;
    const X25 = ResourceTypes::X25;
    const AXFR = ResourceQTypes::AXFR;
    const MAILB = ResourceQTypes::MAILB;
    const MAILA = ResourceQTypes::MAILA;
    const ALL = ResourceQTypes::ALL;
    private $value;
    private $type;
    private $ttl;
    /**
     *
     */
    public function __construct(string $value, int $type, int $ttl = null)
    {
        $this->value = $value;
        $this->type = $type;
        $this->ttl = $ttl;
    }
    /**
     *
     */
    public function getValue() : string
    {
        return $this->value;
    }
    /**
     *
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     *
     */
    public function getTtl()
    {
        return $this->ttl;
    }
    /**
     * Converts an record type integer back into its name as defined in this class.
     *
     * Returns "unknown (<type>)" in case a name for this record is not known.
     *
     * @param int $type Record type as integer.
     *
     * @return string Name of the constant for this record in this class.
     */
    public static function getName(int $type) : string
    {
        static $types;
        if (0 > $type || 0xffff < $type) {
            $message = \sprintf('%d does not correspond to a valid record type (must be between 0 and 65535).', $type);
            throw new \Error($message);
        }
        if ($types === null) {
            $types = \array_flip((new \ReflectionClass(self::class))->getConstants());
        }
        return $types[$type] ?? "unknown ({$type})";
    }
}<?php

namespace Amp\Dns;

use Amp\Failure;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
class HostLoader
{
    private $path;
    /**
     *
     */
    public function __construct(string $path = null)
    {
        $this->path = $path ?? $this->getDefaultPath();
    }
    /**
     *
     */
    private function getDefaultPath() : string
    {
        return \stripos(PHP_OS, "win") === 0 ? 'C:\\Windows\\system32\\drivers\\etc\\hosts' : '/etc/hosts';
    }
    /**
     *
     */
    protected function readFile(string $path) : Promise
    {
        \set_error_handler(function (int $errno, string $message) use($path) {
            throw new ConfigException("Could not read configuration file '{$path}' ({$errno}) {$message}");
        });
        try {
            // Blocking file access, but this file should be local and usually loaded only once.
            $fileContent = \file_get_contents($path);
        } catch (ConfigException $exception) {
            return new Failure($exception);
        } finally {
            \restore_error_handler();
        }
        return new Success($fileContent);
    }
    /**
     *
     */
    public function loadHosts() : Promise
    {
        return call(function () {
            try {
                $contents = (yield $this->readFile($this->path));
            } catch (ConfigException $exception) {
                return [];
            }
            $data = [];
            $lines = \array_filter(\array_map("trim", \explode("\n", $contents)));
            foreach ($lines as $line) {
                if ($line[0] === "#") {
                    // Skip comments
                    continue;
                }
                $parts = \preg_split('/\\s+/', $line);
                if (!($ip = @\inet_pton($parts[0]))) {
                    continue;
                } elseif (isset($ip[4])) {
                    $key = Record::AAAA;
                } else {
                    $key = Record::A;
                }
                for ($i = 1, $l = \count($parts); $i < $l; $i++) {
                    try {
                        $normalizedName = normalizeName($parts[$i]);
                        $data[$key][$normalizedName] = $parts[0];
                    } catch (InvalidNameException $e) {
                        // ignore invalid entries
                    }
                }
            }
            return $data;
        });
    }
}<?php

namespace Amp\Dns;

use Amp\Cache\ArrayCache;
use Amp\Cache\Cache;
use Amp\Dns\Internal\Socket;
use Amp\Dns\Internal\TcpSocket;
use Amp\Dns\Internal\UdpSocket;
use Amp\Loop;
use Amp\MultiReasonException;
use Amp\Promise;
use Amp\Success;
use LibDNS\Messages\Message;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use function Amp\call;
final class Rfc1035StubResolver implements Resolver
{
    const CACHE_PREFIX = "amphp.dns.";
    const CONFIG_NOT_LOADED = 0;
    const CONFIG_LOADED = 1;
    const CONFIG_FAILED = 2;
    /** @var ConfigLoader */
    private $configLoader;
    /** @var QuestionFactory */
    private $questionFactory;
    /** @var Config|null */
    private $config;
    /** @var int */
    private $configStatus = self::CONFIG_NOT_LOADED;
    /** @var Promise|null */
    private $pendingConfig;
    /** @var Cache */
    private $cache;
    /** @var Socket[] */
    private $sockets = [];
    /** @var Promise[] */
    private $pendingSockets = [];
    /** @var Promise[] */
    private $pendingQueries = [];
    /** @var string */
    private $gcWatcher;
    /** @var BlockingFallbackResolver */
    private $blockingFallbackResolver;
    /** @var int */
    private $nextNameserver = 0;
    /**
     *
     */
    public function __construct(Cache $cache = null, ConfigLoader $configLoader = null)
    {
        $this->cache = $cache ?? new ArrayCache(5000, 256);
        $this->configLoader = $configLoader ?? (\stripos(PHP_OS, "win") === 0 ? new WindowsConfigLoader() : new UnixConfigLoader());
        $this->questionFactory = new QuestionFactory();
        $this->blockingFallbackResolver = new BlockingFallbackResolver();
        $sockets =& $this->sockets;
        $this->gcWatcher = Loop::repeat(5000, static function () use(&$sockets) {
            if (!$sockets) {
                return;
            }
            $now = \time();
            foreach ($sockets as $key => $server) {
                if ($server->getLastActivity() < $now - 60) {
                    $server->close();
                    unset($sockets[$key]);
                }
            }
        });
        Loop::unreference($this->gcWatcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->gcWatcher);
    }
    /**
     * @inheritdoc
     */
    public function resolve(string $name, int $typeRestriction = null) : Promise
    {
        if ($typeRestriction !== null && $typeRestriction !== Record::A && $typeRestriction !== Record::AAAA) {
            throw new \Error("Invalid value for parameter 2: null|Record::A|Record::AAAA expected");
        }
        return call(function () use($name, $typeRestriction) {
            if ($this->configStatus === self::CONFIG_NOT_LOADED) {
                (yield $this->reloadConfig());
            }
            if ($this->configStatus === self::CONFIG_FAILED) {
                return $this->blockingFallbackResolver->resolve($name, $typeRestriction);
            }
            switch ($typeRestriction) {
                case Record::A:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        return [new Record($name, Record::A, null)];
                    }
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        throw new DnsException("Got an IPv6 address, but type is restricted to IPv4");
                    }
                    break;
                case Record::AAAA:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        return [new Record($name, Record::AAAA, null)];
                    }
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        throw new DnsException("Got an IPv4 address, but type is restricted to IPv6");
                    }
                    break;
                default:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        return [new Record($name, Record::A, null)];
                    }
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        return [new Record($name, Record::AAAA, null)];
                    }
                    break;
            }
            $dots = \Phabel\Target\Php80\Polyfill::substr_count($name, ".");
            // Should be replaced with $name[-1] from 7.1
            $trailingDot = \Phabel\Target\Php80\Polyfill::substr($name, -1, 1) === ".";
            $name = normalizeName($name);
            if ($records = $this->queryHosts($name, $typeRestriction)) {
                return $records;
            }
            // Follow RFC 6761 and never send queries for localhost to the caching DNS server
            // Usually, these queries are already resolved via queryHosts()
            if ($name === 'localhost') {
                return $typeRestriction === Record::AAAA ? [new Record('::1', Record::AAAA, null)] : [new Record('127.0.0.1', Record::A, null)];
            }
            $searchList = [null];
            if (!$trailingDot && $dots < $this->config->getNdots()) {
                $searchList = \array_merge($this->config->getSearchList(), $searchList);
            }
            foreach ($searchList as $searchIndex => $search) {
                for ($redirects = 0; $redirects < 5; $redirects++) {
                    $searchName = $name;
                    if ($search !== null) {
                        $searchName = $name . "." . $search;
                    }
                    try {
                        if ($typeRestriction) {
                            return (yield $this->query($searchName, $typeRestriction));
                        }
                        try {
                            list(, $records) = (yield Promise\some([$this->query($searchName, Record::A), $this->query($searchName, Record::AAAA)]));
                            return \array_merge(...$records);
                        } catch (MultiReasonException $e) {
                            $errors = [];
                            foreach ($e->getReasons() as $reason) {
                                if ($reason instanceof NoRecordException) {
                                    throw $reason;
                                }
                                if ($searchIndex < \count($searchList) - 1 && \in_array($reason->getCode(), [2, 3], true)) {
                                    continue 2;
                                }
                                $errors[] = $reason->getMessage();
                            }
                            throw new DnsException("All query attempts failed for {$searchName}: " . \implode(", ", $errors), 0, $e);
                        }
                    } catch (NoRecordException $e) {
                        try {
                            /** @var Record[] $cnameRecords */
                            $cnameRecords = (yield $this->query($searchName, Record::CNAME));
                            $name = $cnameRecords[0]->getValue();
                            continue;
                        } catch (NoRecordException $e) {
                            /** @var Record[] $dnameRecords */
                            $dnameRecords = (yield $this->query($searchName, Record::DNAME));
                            $name = $dnameRecords[0]->getValue();
                            continue;
                        }
                    } catch (DnsException $e) {
                        if ($searchIndex < \count($searchList) - 1 && \in_array($e->getCode(), [2, 3], true)) {
                            continue 2;
                        }
                        throw $e;
                    }
                }
            }
            throw new DnsException("Giving up resolution of '{$searchName}', too many redirects");
        });
    }
    /**
     * Reloads the configuration in the background.
     *
     * Once it's finished, the configuration will be used for new requests.
     *
     * @return Promise
     */
    public function reloadConfig() : Promise
    {
        if ($this->pendingConfig) {
            return $this->pendingConfig;
        }
        $promise = call(function () {
            try {
                $this->config = (yield $this->configLoader->loadConfig());
                $this->configStatus = self::CONFIG_LOADED;
            } catch (ConfigException $e) {
                $this->configStatus = self::CONFIG_FAILED;
                try {
                    \trigger_error("Could not load the system's DNS configuration, using synchronous, blocking fallback", \E_USER_WARNING);
                } catch (\Throwable $triggerException) {
                    \set_error_handler(null);
                    \trigger_error("Could not load the system's DNS configuration, using synchronous, blocking fallback", \E_USER_WARNING);
                    \restore_error_handler();
                }
            }
        });
        $this->pendingConfig = $promise;
        $promise->onResolve(function () {
            $this->pendingConfig = null;
        });
        return $promise;
    }
    /**
     * @inheritdoc
     */
    public function query(string $name, int $type) : Promise
    {
        $pendingQueryKey = $type . " " . $name;
        if (isset($this->pendingQueries[$pendingQueryKey])) {
            return $this->pendingQueries[$pendingQueryKey];
        }
        $promise = call(function () use($name, $type) {
            if ($this->configStatus === self::CONFIG_NOT_LOADED) {
                (yield $this->reloadConfig());
            }
            if ($this->configStatus === self::CONFIG_FAILED) {
                return $this->blockingFallbackResolver->query($name, $type);
            }
            $name = $this->normalizeName($name, $type);
            $question = $this->createQuestion($name, $type);
            if (null !== ($cachedValue = (yield $this->cache->get($this->getCacheKey($name, $type))))) {
                return $this->decodeCachedResult($name, $type, $cachedValue);
            }
            $nameservers = $this->selectNameservers();
            $nameserversCount = \count($nameservers);
            $attempts = $this->config->getAttempts();
            $protocol = "udp";
            $attempt = 0;
            /** @var Socket $socket */
            $uri = $protocol . "://" . $nameservers[0];
            $socket = (yield $this->getSocket($uri));
            $attemptDescription = [];
            while ($attempt < $attempts) {
                try {
                    if (!$socket->isAlive()) {
                        unset($this->sockets[$uri]);
                        $socket->close();
                        $uri = $protocol . "://" . $nameservers[$attempt % $nameserversCount];
                        $socket = (yield $this->getSocket($uri));
                    }
                    $attemptDescription[] = $uri;
                    /** @var Message $response */
                    $response = (yield $socket->ask($question, $this->config->getTimeout()));
                    $this->assertAcceptableResponse($response, $name);
                    // UDP sockets are never reused, they're not in the $this->sockets map
                    if ($protocol === "udp") {
                        // Defer call, because it interferes with the unreference() call in Internal\Socket otherwise
                        Loop::defer(static function () use($socket) {
                            $socket->close();
                        });
                    }
                    if ($response->isTruncated()) {
                        if ($protocol !== "tcp") {
                            // Retry with TCP, don't count attempt
                            $protocol = "tcp";
                            $uri = $protocol . "://" . $nameservers[$attempt % $nameserversCount];
                            $socket = (yield $this->getSocket($uri));
                            continue;
                        }
                        throw new DnsException("Server returned a truncated response for '{$name}' (" . Record::getName($type) . ")");
                    }
                    $answers = $response->getAnswerRecords();
                    $result = [];
                    $ttls = [];
                    /** @var \LibDNS\Records\Resource $record */
                    foreach ($answers as $record) {
                        $recordType = $record->getType();
                        $result[$recordType][] = (string) $record->getData();
                        // Cache for max one day
                        $ttls[$recordType] = \min($ttls[$recordType] ?? 86400, $record->getTTL());
                    }
                    foreach ($result as $recordType => $records) {
                        // We don't care here whether storing in the cache fails
                        $this->cache->set($this->getCacheKey($name, $recordType), \json_encode($records), $ttls[$recordType]);
                    }
                    if (!isset($result[$type])) {
                        // "it MUST NOT cache it for longer than five (5) minutes" per RFC 2308 section 7.1
                        $this->cache->set($this->getCacheKey($name, $type), \json_encode([]), 300);
                        throw new NoRecordException("No records returned for '{$name}' (" . Record::getName($type) . ")");
                    }
                    return \array_map(static function ($data) use($type, $ttls) {
                        return new Record($data, $type, $ttls[$type]);
                    }, $result[$type]);
                } catch (TimeoutException $e) {
                    // Defer call, because it might interfere with the unreference() call in Internal\Socket otherwise
                    Loop::defer(function () use($socket, $uri) {
                        unset($this->sockets[$uri]);
                        $socket->close();
                    });
                    $uri = $protocol . "://" . $nameservers[++$attempt % $nameserversCount];
                    $socket = (yield $this->getSocket($uri));
                    continue;
                }
            }
            throw new TimeoutException(\sprintf("No response for '%s' (%s) from any nameserver within %d ms after %d attempts, tried %s", $name, Record::getName($type), $this->config->getTimeout(), $attempts, \implode(", ", $attemptDescription)));
        });
        $this->pendingQueries[$type . " " . $name] = $promise;
        $promise->onResolve(function () use($name, $type) {
            unset($this->pendingQueries[$type . " " . $name]);
        });
        return $promise;
    }
    /**
     *
     */
    private function queryHosts(string $name, int $typeRestriction = null) : array
    {
        $hosts = $this->config->getKnownHosts();
        $records = [];
        $returnIPv4 = $typeRestriction === null || $typeRestriction === Record::A;
        $returnIPv6 = $typeRestriction === null || $typeRestriction === Record::AAAA;
        if ($returnIPv4 && isset($hosts[Record::A][$name])) {
            $records[] = new Record($hosts[Record::A][$name], Record::A, null);
        }
        if ($returnIPv6 && isset($hosts[Record::AAAA][$name])) {
            $records[] = new Record($hosts[Record::AAAA][$name], Record::AAAA, null);
        }
        return $records;
    }
    /**
     *
     */
    private function normalizeName(string $name, int $type)
    {
        if ($type === Record::PTR) {
            if (($packedIp = @\inet_pton($name)) !== false) {
                if (isset($packedIp[4])) {
                    // IPv6
                    $name = \wordwrap(\strrev(\bin2hex($packedIp)), 1, ".", true) . ".ip6.arpa";
                } else {
                    // IPv4
                    $name = \inet_ntop(\strrev($packedIp)) . ".in-addr.arpa";
                }
            }
        } elseif (\in_array($type, [Record::A, Record::AAAA], true)) {
            $name = normalizeName($name);
        }
        return $name;
    }
    /**
     * @param string $name
     * @param int $type
     *
     * @return Question
     */
    private function createQuestion(string $name, int $type) : Question
    {
        if (0 > $type || 0xffff < $type) {
            $message = \sprintf('%d does not correspond to a valid record type (must be between 0 and 65535).', $type);
            throw new \Error($message);
        }
        $question = $this->questionFactory->create($type);
        $question->setName($name);
        return $question;
    }
    /**
     *
     */
    private function getCacheKey(string $name, int $type) : string
    {
        return self::CACHE_PREFIX . $name . "#" . $type;
    }
    /**
     *
     */
    private function decodeCachedResult(string $name, int $type, string $encoded) : array
    {
        $decoded = \json_decode($encoded, true);
        if (!$decoded) {
            throw new NoRecordException("No records returned for {$name} (cached result)");
        }
        $result = [];
        foreach ($decoded as $data) {
            $result[] = new Record($data, $type);
        }
        return $result;
    }
    /**
     *
     */
    private function getSocket($uri) : Promise
    {
        // We use a new socket for each UDP request, as that increases the entropy and mitigates response forgery.
        if (\Phabel\Target\Php80\Polyfill::substr($uri, 0, 3) === "udp") {
            return UdpSocket::connect($uri);
        }
        // Over TCP we might reuse sockets if the server allows to keep them open. Sequence IDs in TCP are already
        // better than a random port. Additionally, a TCP connection is more expensive.
        if (isset($this->sockets[$uri])) {
            return new Success($this->sockets[$uri]);
        }
        if (isset($this->pendingSockets[$uri])) {
            return $this->pendingSockets[$uri];
        }
        $server = TcpSocket::connect($uri);
        $server->onResolve(function ($error, $server) use($uri) {
            unset($this->pendingSockets[$uri]);
            if (!$error) {
                $this->sockets[$uri] = $server;
            }
        });
        return $server;
    }
    /**
     * @throws DnsException
     */
    private function assertAcceptableResponse(Message $response, string $name)
    {
        if ($response->getResponseCode() !== 0) {
            // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
            $errors = [1 => 'FormErr', 2 => 'ServFail', 3 => 'NXDomain', 4 => 'NotImp', 5 => 'Refused', 6 => 'YXDomain', 7 => 'YXRRSet', 8 => 'NXRRSet', 9 => 'NotAuth', 10 => 'NotZone', 11 => 'DSOTYPENI', 16 => 'BADVERS', 17 => 'BADKEY', 18 => 'BADTIME', 19 => 'BADMODE', 20 => 'BADNAME', 21 => 'BADALG', 22 => 'BADTRUNC', 23 => 'BADCOOKIE'];
            throw new DnsException(\sprintf("Name resolution failed for '%s'; server returned error code: %d (%s)", $name, $response->getResponseCode(), $errors[$response->getResponseCode()] ?? 'UNKNOWN'), $response->getResponseCode());
        }
    }
    /**
     *
     */
    private function selectNameservers() : array
    {
        $nameservers = $this->config->getNameservers();
        if ($this->config->isRotationEnabled() && ($nameserversCount = \count($nameservers)) > 1) {
            $nameservers = \array_merge(\array_slice($nameservers, $this->nextNameserver), \array_slice($nameservers, 0, $this->nextNameserver));
            $this->nextNameserver = ++$this->nextNameserver % $nameserversCount;
        }
        return $nameservers;
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
final class ConnectionConfig extends SqlConnectionConfig
{
    public const DEFAULT_PORT = 5432;
    public const SSL_MODES = ['disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full'];
    /** @var string|null */
    private $sslMode = null;
    /** @var string|null */
    private $string;
    /**
     *
     */
    public static function fromString(string $connectionString) : self
    {
        $parts = self::parseConnectionString($connectionString);
        if (!isset($parts["host"])) {
            throw new \Error("Host must be provided in connection string");
        }
        $config = new self($parts["host"], (int) ($parts["port"] ?? self::DEFAULT_PORT), $parts["user"] ?? null, $parts["password"] ?? null, $parts["db"] ?? null);
        if (isset($parts["sslmode"])) {
            $config = $config->withSslMode($parts["sslmode"]);
        }
        return $config;
    }
    /**
     *
     */
    public function __construct(string $host, int $port = self::DEFAULT_PORT, string $user = null, string $password = null, string $database = null)
    {
        parent::__construct($host, $port, $user, $password, $database);
    }
    /**
     *
     */
    public function __clone()
    {
        $this->string = null;
    }
    /**
     *
     */
    public function getSslMode() : ?string
    {
        return $this->sslMode;
    }
    /**
     *
     */
    public function withSslMode(string $mode) : self
    {
        if (!\in_array($mode, self::SSL_MODES, true)) {
            throw new \Error('Invalid SSL mode, must be one of: ' . \implode(', ', self::SSL_MODES));
        }
        $new = clone $this;
        $new->sslMode = $mode;
        return $new;
    }
    /**
     *
     */
    public function withoutSslMode() : self
    {
        $new = clone $this;
        $new->sslMode = null;
        return $new;
    }
    /**
     * @return string Connection string used with ext-pgsql and pecl-pq.
     */
    public function getConnectionString() : string
    {
        if ($this->string !== null) {
            return $this->string;
        }
        $chunks = ["host=" . $this->getHost(), "port=" . $this->getPort()];
        $user = $this->getUser();
        if ($user !== null) {
            $chunks[] = "user=" . $user;
        }
        $password = $this->getPassword();
        if ($password !== null) {
            $chunks[] = "password=" . $password;
        }
        $database = $this->getDatabase();
        if ($database !== null) {
            $chunks[] = "dbname=" . $database;
        }
        if ($this->sslMode !== null) {
            $chunks[] = "sslmode=" . $this->sslMode;
        }
        return $this->string = \implode(" ", $chunks);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Transaction as SqlTransaction;
use Amp\Sql\TransactionError;
use function Amp\call;
final class ConnectionTransaction implements Transaction
{
    /** @var Handle|null */
    private $handle;
    /** @var int */
    private $isolation;
    /** @var callable */
    private $release;
    /** @var int */
    private $refCount = 1;
    /**
     * @param Handle $handle
     * @param callable $release
     * @param int $isolation
     *
     * @throws \Error If the isolation level is invalid.
     */
    public function __construct(Handle $handle, callable $release, int $isolation = SqlTransaction::ISOLATION_COMMITTED)
    {
        switch ($isolation) {
            case SqlTransaction::ISOLATION_UNCOMMITTED:
            case SqlTransaction::ISOLATION_COMMITTED:
            case SqlTransaction::ISOLATION_REPEATABLE:
            case SqlTransaction::ISOLATION_SERIALIZABLE:
                $this->isolation = $isolation;
                break;
            default:
                throw new \Error("Isolation must be a valid transaction isolation level");
        }
        $this->handle = $handle;
        $refCount =& $this->refCount;
        $this->release = static function () use(&$refCount, $release) {
            if (--$refCount === 0) {
                $release();
            }
        };
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->handle && $this->handle->isAlive()) {
            $this->rollback();
            // Invokes $this->release callback.
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->handle->getLastUsedAt();
    }
    /**
     * {@inheritdoc}
     *
     * Closes and commits all changes in the transaction.
     */
    public function close() : void
    {
        if ($this->handle) {
            $this->commit();
            // Invokes $this->release callback.
        }
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle && $this->handle->isAlive();
    }
    /**
     * @return bool True if the transaction is active, false if it has been committed or rolled back.
     */
    public function isActive() : bool
    {
        return $this->handle !== null;
    }
    /**
     * @return int
     */
    public function getIsolationLevel() : int
    {
        return $this->isolation;
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function query(string $sql) : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            ++$this->refCount;
            try {
                $result = (yield $this->handle->query($sql));
            } finally {
                ($this->release)();
            }
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return new PooledResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function prepare(string $sql) : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            ++$this->refCount;
            try {
                $statement = (yield $this->handle->prepare($sql));
            } catch (\Throwable $exception) {
                ($this->release)();
                throw $exception;
            }
            return new PooledStatement($statement, $this->release);
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql, $params) {
            ++$this->refCount;
            try {
                $result = (yield $this->handle->execute($sql, $params));
            } finally {
                ($this->release)();
            }
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return new PooledResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->handle->notify($channel, $payload);
    }
    /**
     * Commits the transaction and makes it inactive.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function commit() : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->handle->query("COMMIT");
        $this->handle = null;
        $promise->onResolve($this->release);
        return $promise;
    }
    /**
     * Rolls back the transaction and makes it inactive.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollback() : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->handle->query("ROLLBACK");
        $this->handle = null;
        $promise->onResolve($this->release);
        return $promise;
    }
    /**
     * Creates a savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function createSavepoint(string $identifier) : Promise
    {
        return $this->query("SAVEPOINT " . $this->quoteName($identifier));
    }
    /**
     * Rolls back to the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollbackTo(string $identifier) : Promise
    {
        return $this->query("ROLLBACK TO " . $this->quoteName($identifier));
    }
    /**
     * Releases the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function releaseSavepoint(string $identifier) : Promise
    {
        return $this->query("RELEASE SAVEPOINT " . $this->quoteName($identifier));
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function quoteString(string $data) : string
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->handle->quoteString($data);
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function quoteName(string $name) : string
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->handle->quoteName($name);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Statement;
final class PqStatement implements Statement
{
    /** @var PqHandle */
    private $handle;
    /** @var string */
    private $name;
    /** @var string */
    private $sql;
    /** @var array */
    private $params;
    /** @var int */
    private $lastUsedAt;
    /**
     * @param PqHandle $handle
     * @param string $name Statement name.
     * @param string $sql Original prepared SQL query.
     * @param string[] $params Parameter indices to parameter names.
     */
    public function __construct(PqHandle $handle, string $name, string $sql, array $params)
    {
        $this->handle = $handle;
        $this->name = $name;
        $this->params = $params;
        $this->sql = $sql;
        $this->lastUsedAt = \time();
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->handle->statementDeallocate($this->name);
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public function getQuery() : string
    {
        return $this->sql;
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     * {@inheritdoc}
     */
    public function execute(array $params = []) : Promise
    {
        $this->lastUsedAt = \time();
        return $this->handle->statementExecute($this->name, Internal\replaceNamedParams($params, $this->params));
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\Common\PooledStatement as SqlPooledStatement;
use Amp\Sql\ResultSet as SqlResultSet;
final class PooledStatement extends SqlPooledStatement
{
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\FailureException;
use Amp\Success;
final class PgSqlResultSet implements ResultSet
{
    /** @var resource PostgreSQL result resource. */
    private $handle;
    /** @var array<int, array{string, string}> */
    private $types;
    /** @var int */
    private $position = 0;
    /** @var mixed Last row emitted. */
    private $currentRow;
    /** @var int[] */
    private $fieldTypes = [];
    /** @var string[] */
    private $fieldNames = [];
    /** @var Internal\ArrayParser */
    private $parser;
    /**
     * @param resource $handle PostgreSQL result resource.
     * @param array<int, array{string, string}> $types
     */
    public function __construct($handle, array $types = [])
    {
        $this->handle = $handle;
        $this->types = $types;
        $numFields = \pg_num_fields($this->handle);
        for ($i = 0; $i < $numFields; ++$i) {
            $this->fieldNames[] = \pg_field_name($this->handle, $i);
            $this->fieldTypes[] = \pg_field_type_oid($this->handle, $i);
        }
        $this->parser = new Internal\ArrayParser();
    }
    /**
     * Frees the result resource.
     */
    public function __destruct()
    {
        \pg_free_result($this->handle);
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        $this->currentRow = null;
        if (++$this->position > \pg_num_rows($this->handle)) {
            return new Success(false);
        }
        return new Success(true);
    }
    /**
     * {@inheritdoc}
     */
    public function getCurrent() : array
    {
        if ($this->currentRow !== null) {
            return $this->currentRow;
        }
        if ($this->position > \pg_num_rows($this->handle)) {
            throw new \Error("No more rows remain in the result set");
        }
        $result = \pg_fetch_array($this->handle, null, \PGSQL_NUM);
        if ($result === false) {
            $message = \pg_result_error($this->handle);
            \pg_free_result($this->handle);
            throw new FailureException($message);
        }
        $columnCount = \count($result);
        for ($column = 0; $column < $columnCount; ++$column) {
            if ($result[$column] === null) {
                continue;
            }
            $result[$column] = $this->cast($this->fieldTypes[$column], $result[$column]);
        }
        return $this->currentRow = \array_combine($this->fieldNames, $result);
    }
    /**
     * @see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/include/catalog/pg_type.dat for OID types.
     * @see https://www.postgresql.org/docs/14/catalog-pg-type.html for pg_type catalog docs.
     *
     * @param int $oid
     * @param string $value
     *
     * @return (array | bool | float | int) Cast value.
     *
     * @throws ParseException
     */
    private function cast(int $oid, string $value)
    {
        [$type, $delimiter, $element] = $this->types[$oid] ?? ['S', ',', 0];
        switch ($type) {
            case 'A':
                // Arrays
                return $this->parser->parse($value, function (string $data) use($element) {
                    return $this->cast($element, $data);
                }, $delimiter);
            case 'B':
                // Binary
                return $value === 't';
            case 'N':
                // Numeric
                switch ($oid) {
                    case 700:
                    // float4
                    case 701:
                    // float8
                    case 790:
                    // money
                    case 1700:
                        // numeric
                        return (float) $value;
                    default:
                        // Cast all other numeric types to an integer.
                        return (int) $value;
                }
            default:
                // Return all other types as strings.
                return $value;
        }
    }
    /**
     * @return int Number of rows in the result set.
     */
    public function numRows() : int
    {
        return \pg_num_rows($this->handle);
    }
    /**
     * @return int Number of fields in each row.
     */
    public function getFieldCount() : int
    {
        return \pg_num_fields($this->handle);
    }
    /**
     * @param int $fieldNum
     *
     * @return string Column name at index $fieldNum
     *
     * @throws \Error If the field number does not exist in the result.
     */
    public function getFieldName(int $fieldNum) : string
    {
        if (0 > $fieldNum || $this->getFieldCount() <= $fieldNum) {
            throw new \Error(\sprintf('No field with index %d in result', $fieldNum));
        }
        return \pg_field_name($this->handle, $fieldNum);
    }
    /**
     * @param string $fieldName
     *
     * @return int Index of field with given name.
     *
     * @throws \Error If the field name does not exist in the result.
     */
    public function getFieldIndex(string $fieldName) : int
    {
        $result = \pg_field_num($this->handle, $fieldName);
        if (-1 === $result) {
            throw new \Error(\sprintf('No field with name "%s" in result', $fieldName));
        }
        return $result;
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Success;
use pq;
final class PqBufferedResultSet implements ResultSet
{
    /** @var \pq\Result */
    private $result;
    /** @var int */
    private $position = 0;
    /** @var mixed Last row emitted. */
    private $currentRow;
    /**
     * @param pq\Result $result PostgreSQL result object.
     */
    public function __construct(pq\Result $result)
    {
        $this->result = $result;
        $this->result->autoConvert = pq\Result::CONV_SCALAR | pq\Result::CONV_ARRAY;
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        $this->currentRow = null;
        if (++$this->position > $this->result->numRows) {
            return new Success(false);
        }
        return new Success(true);
    }
    /**
     * {@inheritdoc}
     */
    public function getCurrent() : array
    {
        if ($this->currentRow !== null) {
            return $this->currentRow;
        }
        if ($this->position > $this->result->numRows) {
            throw new \Error("No more rows remain in the result set");
        }
        return $this->currentRow = $this->result->fetchRow(pq\Result::FETCH_ASSOC);
    }
    /**
     *
     */
    public function getNumRows() : int
    {
        return $this->result->numRows;
    }
    /**
     *
     */
    public function getFieldCount() : int
    {
        return $this->result->numCols;
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\CommandResult;
final class PgSqlCommandResult implements CommandResult
{
    /** @var resource PostgreSQL result resource. */
    private $handle;
    /**
     * @param resource $handle PostgreSQL result resource.
     */
    public function __construct($handle)
    {
        $this->handle = $handle;
    }
    /**
     * Frees the result resource.
     */
    public function __destruct()
    {
        \pg_free_result($this->handle);
    }
    /**
     * @return int Number of rows affected by the INSERT, UPDATE, or DELETE query.
     */
    public function getAffectedRowCount() : int
    {
        return \pg_affected_rows($this->handle);
    }
    /**
    * @deprecated This is not meant to be used to get the last insertion ID. Use `INSERT ... RETURNING column_name`
    to get the last auto-increment ID.
    *
    * $sql = "INSERT INTO person (lastname, firstname) VALUES (?, ?) RETURNING id;"
    $statement = yield $pool->prepare($sql);
    $result = yield $statement->execute(['Doe', 'John']);
    if (!yield $result->advance()) {
    throw new \RuntimeException("Insertion failed");
    }
    $id = $result->getCurrent()['id'];
    *
    * @return string
    */
    public function getLastOid() : string
    {
        return (string) \pg_last_oid($this->handle);
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\FailureException;
class ParseException extends FailureException
{
    /**
     *
     */
    public function __construct(string $message = '')
    {
        $message = "Parse error while splitting array" . ($message === '' ? '' : ": " . $message);
        parent::__construct($message);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
interface Receiver extends Executor
{
    /**
     * @param string $channel Channel name.
     *
     * @return Promise<Listener>
     *
     * @throws \Amp\Sql\FailureException If the operation fails due to unexpected condition.
     * @throws \Amp\Sql\ConnectionException If the connection to the database is lost.
     * @throws \Amp\Sql\QueryError If the operation fails due to an error in the query (such as a syntax error).
     */
    public function listen(string $channel) : Promise;
}<?php

namespace Amp\Postgres;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Sql\ConnectionException;
use pq;
final class PqConnection extends Connection implements Link
{
    /** @var PqHandle */
    private $handle;
    /**
     * @param ConnectionConfig $connectionConfig
     * @param CancellationToken $token
     *
     * @return Promise<PqConnection>
     */
    public static function connect(ConnectionConfig $connectionConfig, ?CancellationToken $token = null) : Promise
    {
        try {
            $connection = new pq\Connection($connectionConfig->getConnectionString(), pq\Connection::ASYNC);
        } catch (pq\Exception $exception) {
            return new Failure(new ConnectionException("Could not connect to PostgreSQL server", 0, $exception));
        }
        $connection->nonblocking = true;
        $connection->unbuffered = true;
        $deferred = new Deferred();
        $callback = function () use($connection, $deferred) : void {
            switch ($connection->poll()) {
                case pq\Connection::POLLING_READING:
                // Connection not ready, poll again.
                case pq\Connection::POLLING_WRITING:
                    // Still writing...
                    return;
                case pq\Connection::POLLING_FAILED:
                    $deferred->fail(new ConnectionException($connection->errorMessage));
                    return;
                case pq\Connection::POLLING_OK:
                    $deferred->resolve(new self($connection));
                    return;
            }
        };
        $poll = Loop::onReadable($connection->socket, $callback);
        $await = Loop::onWritable($connection->socket, $callback);
        $promise = $deferred->promise();
        $token = $token ?? new NullCancellationToken();
        $id = $token->subscribe([$deferred, "fail"]);
        $promise->onResolve(function () use($poll, $await, $id, $token) : void {
            $token->unsubscribe($id);
            Loop::cancel($poll);
            Loop::cancel($await);
        });
        return $promise;
    }
    /**
     * @param \pq\Connection $handle
     */
    public function __construct(pq\Connection $handle)
    {
        $this->handle = new PqHandle($handle);
        parent::__construct($this->handle);
    }
    /**
     * @return bool True if result sets are buffered in memory, false if unbuffered.
     */
    public function isBufferingResults() : bool
    {
        return $this->handle->isBufferingResults();
    }
    /**
     * Sets result sets to be fully buffered in local memory.
     */
    public function shouldBufferResults() : void
    {
        $this->handle->shouldBufferResults();
    }
    /**
     * Sets result sets to be streamed from the database server.
     */
    public function shouldNotBufferResults() : void
    {
        $this->handle->shouldNotBufferResults();
    }
}<?php

namespace Amp\Postgres;

use Amp\Iterator;
use Amp\Promise;
final class ConnectionListener implements Listener
{
    /** @var \Amp\Iterator */
    private $iterator;
    /** @var string */
    private $channel;
    /** @var callable|null */
    private $unlisten;
    /**
     * @param \Amp\Iterator $iterator Iterator emitting notificatons on the channel.
     * @param string $channel Channel name.
     * @param callable(string $channel):  $unlisten Function invoked to unlisten from the channel.
     */
    public function __construct(Iterator $iterator, string $channel, callable $unlisten)
    {
        $this->iterator = $iterator;
        $this->channel = $channel;
        $this->unlisten = $unlisten;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->unlisten) {
            $this->unlisten();
            // Invokes $this->queue->complete().
        }
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        return $this->iterator->advance();
    }
    /**
     * {@inheritdoc}
     *
     * @return Notification
     */
    public function getCurrent() : Notification
    {
        return $this->iterator->getCurrent();
    }
    /**
     * @return string Channel name.
     */
    public function getChannel() : string
    {
        return $this->channel;
    }
    /**
     * @return bool
     */
    public function isListening() : bool
    {
        return $this->unlisten !== null;
    }
    /**
     * Unlistens from the channel. No more values will be emitted from this listener.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws \Error If this method was previously invoked.
     */
    public function unlisten() : Promise
    {
        if (!$this->unlisten) {
            throw new \Error("Already unlistened on this channel");
        }
        /** @var Promise $promise */
        $promise = ($this->unlisten)($this->channel);
        $this->unlisten = null;
        return $promise;
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
use Amp\Sql\Connector;
use Amp\Sql\FailureException;
use Amp\TimeoutCancellationToken;
final class TimeoutConnector implements Connector
{
    const DEFAULT_TIMEOUT = 5000;
    /** @var int */
    private $timeout;
    /**
     * @param int $timeout Milliseconds until connections attempts are cancelled.
     */
    public function __construct(int $timeout = self::DEFAULT_TIMEOUT)
    {
        $this->timeout = $timeout;
    }
    /**
     * {@inheritdoc}
     *
     * @throws FailureException If connecting fails.
     *
     * @throws \Error If neither ext-pgsql or pecl-pq is loaded.
     */
    public function connect(SqlConnectionConfig $connectionConfig) : Promise
    {
        if (!$connectionConfig instanceof ConnectionConfig) {
            throw new \TypeError(\sprintf("Must provide an instance of %s to Postgres connectors", ConnectionConfig::class));
        }
        $token = new TimeoutCancellationToken($this->timeout);
        if (\extension_loaded("pq")) {
            return PqConnection::connect($connectionConfig, $token);
        }
        if (\extension_loaded("pgsql")) {
            return PgSqlConnection::connect($connectionConfig, $token);
        }
        throw new \Error("amphp/postgres requires either pecl-pq or ext-pgsql");
    }
}<?php

namespace Amp\Postgres;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Sql\ConnectionException;
final class PgSqlConnection extends Connection implements Link
{
    /**
     * @param ConnectionConfig $connectionConfig
     * @param CancellationToken $token
     *
     * @return Promise<PgSqlConnection>
     *
     * @throws \Error If pecl-ev is used as a loop extension.
     */
    public static function connect(ConnectionConfig $connectionConfig, ?CancellationToken $token = null) : Promise
    {
        // @codeCoverageIgnoreStart
        if (Loop::get()->getHandle() instanceof \EvLoop) {
            throw new \Error('ext-pgsql is not compatible with pecl-ev; use pecl-pq or a different loop extension');
        }
        // @codeCoverageIgnoreEnd
        if (!($connection = @\pg_connect($connectionConfig->getConnectionString(), \PGSQL_CONNECT_ASYNC | \PGSQL_CONNECT_FORCE_NEW))) {
            return new Failure(new ConnectionException("Failed to create connection resource"));
        }
        if (\pg_connection_status($connection) === \PGSQL_CONNECTION_BAD) {
            return new Failure(new ConnectionException(\pg_last_error($connection)));
        }
        if (!($socket = \pg_socket($connection))) {
            return new Failure(new ConnectionException("Failed to access connection socket"));
        }
        $deferred = new Deferred();
        $id = \sha1($connectionConfig->getHost() . $connectionConfig->getPort() . $connectionConfig->getUser());
        $callback = function ($watcher, $resource) use($connection, $deferred, $id) : void {
            switch (\pg_connect_poll($connection)) {
                case \PGSQL_POLLING_READING:
                // Connection not ready, poll again.
                case \PGSQL_POLLING_WRITING:
                    // Still writing...
                    return;
                case \PGSQL_POLLING_FAILED:
                    $deferred->fail(new ConnectionException(\pg_last_error($connection)));
                    return;
                case \PGSQL_POLLING_OK:
                    $deferred->resolve(new self($connection, $resource, $id));
                    return;
            }
        };
        $poll = Loop::onReadable($socket, $callback);
        $await = Loop::onWritable($socket, $callback);
        $promise = $deferred->promise();
        $token = $token ?? new NullCancellationToken();
        $id = $token->subscribe([$deferred, "fail"]);
        $promise->onResolve(function ($exception) use($connection, $poll, $await, $id, $token) : void {
            if ($exception) {
                \pg_close($connection);
            }
            $token->unsubscribe($id);
            Loop::cancel($poll);
            Loop::cancel($await);
        });
        return $promise;
    }
    /**
     * @param resource $handle PostgreSQL connection handle.
     * @param resource $socket PostgreSQL connection stream socket.
     * @param string $id Connection identifier for determining which cached type table to use.
     */
    public function __construct($handle, $socket, string $id = '')
    {
        parent::__construct(new PgSqlHandle($handle, $socket, $id));
    }
}<?php

namespace Amp\Postgres;

use Amp\Coroutine;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Loop;
use Amp\Promise;
use Amp\Sql\ConnectionException;
use Amp\Sql\FailureException;
use Amp\Sql\QueryError;
use Amp\Struct;
use Amp\Success;
use pq;
use function Amp\call;
use function Amp\coroutine;
final class PqHandle implements Handle
{
    /** @var pq\Connection PostgreSQL connection object. */
    private $handle;
    /** @var Deferred|null */
    private $deferred;
    /** @var Deferred|null */
    private $busy;
    /** @var string */
    private $poll;
    /** @var string */
    private $await;
    /** @var Emitter[] */
    private $listeners = [];
    /** @var array<string, object{refCount: int, promise: Promise<string>, statement: pq\Statement, sql: string}> */
    private $statements = [];
    /** @var int */
    private $lastUsedAt;
    /**
     * Connection constructor.
     *
     * @param pq\Connection $handle
     */
    public function __construct(pq\Connection $handle)
    {
        $this->handle = $handle;
        $this->lastUsedAt = \time();
        $handle =& $this->handle;
        $lastUsedAt =& $this->lastUsedAt;
        $deferred =& $this->deferred;
        $listeners =& $this->listeners;
        $this->poll = Loop::onReadable($this->handle->socket, static function ($watcher) use(&$deferred, &$lastUsedAt, &$listeners, &$handle) : void {
            $lastUsedAt = \time();
            if ($handle->poll() === pq\Connection::POLLING_FAILED) {
                $exception = new ConnectionException($handle->errorMessage);
                $handle = null;
                // Marks connection as dead.
                Loop::disable($watcher);
                foreach ($listeners as $listener) {
                    $listener->fail($exception);
                }
                if ($deferred !== null) {
                    $deferred->fail($exception);
                }
                return;
            }
            if ($deferred === null) {
                return;
                // No active query, only notification listeners.
            }
            if ($handle->busy) {
                return;
                // Not finished receiving data, poll again.
            }
            $deferred->resolve($handle->getResult());
            if (!$deferred && empty($listeners)) {
                Loop::unreference($watcher);
            }
        });
        $this->await = Loop::onWritable($this->handle->socket, static function ($watcher) use(&$deferred, &$listeners, &$handle) : void {
            try {
                if (!$handle->flush()) {
                    return;
                    // Not finished sending data, continue polling for writability.
                }
            } catch (pq\Exception $exception) {
                $exception = new ConnectionException("Flushing the connection failed", 0, $exception);
                $handle = null;
                // Marks connection as dead.
                foreach ($listeners as $listener) {
                    $listener->fail($exception);
                }
                if ($deferred !== null) {
                    $deferred->fail($exception);
                }
            }
            Loop::disable($watcher);
        });
        Loop::unreference($this->poll);
        Loop::disable($this->await);
    }
    /**
     * Frees Io watchers from loop.
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle !== null;
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     * {@inheritdoc}
     */
    public function close() : void
    {
        if ($this->deferred) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->fail(new ConnectionException("The connection was closed"));
        }
        $this->handle = null;
        $this->free();
    }
    /**
     *
     */
    private function free() : void
    {
        Loop::cancel($this->poll);
        Loop::cancel($this->await);
    }
    /**
     * @param string|null Query SQL or null if not related.
     * @param callable $method Method to execute.
     * @param mixed ...$args Arguments to pass to function.
     *
     * @return \Generator
     *
     * @resolve \Amp\Sql\CommandResult|\pq\Statement
     *
     * @throws FailureException
     */
    private function send(?string $sql, callable $method, ...$args) : \Generator
    {
        while ($this->busy) {
            try {
                (yield $this->busy->promise());
            } catch (\Throwable $exception) {
                // Ignore failure from another operation.
            }
        }
        if (!$this->handle) {
            throw new ConnectionException("The connection to the database has been closed");
        }
        try {
            $this->deferred = $this->busy = new Deferred();
            $handle = $method(...$args);
            Loop::reference($this->poll);
            if (!$this->handle->flush()) {
                Loop::enable($this->await);
            }
            $result = (yield $this->deferred->promise());
        } catch (pq\Exception $exception) {
            throw new FailureException($this->handle->errorMessage, 0, $exception);
        } finally {
            $this->deferred = $this->busy = null;
        }
        if (!$result instanceof pq\Result) {
            throw new FailureException("Unknown query result");
        }
        switch ($result->status) {
            case pq\Result::EMPTY_QUERY:
                throw new QueryError("Empty query string");
            case pq\Result::COMMAND_OK:
                if ($handle instanceof pq\Statement) {
                    return $handle;
                    // Will be wrapped into a PqStatement object.
                }
                return new PqCommandResult($result);
            case pq\Result::TUPLES_OK:
                return new PqBufferedResultSet($result);
            case pq\Result::SINGLE_TUPLE:
                $this->busy = new Deferred();
                return new PqUnbufferedResultSet(coroutine(\Closure::fromCallable([$this, 'fetch'])), $result, \Closure::fromCallable([$this, 'release']));
            case pq\Result::NONFATAL_ERROR:
            case pq\Result::FATAL_ERROR:
                while ($this->handle->busy && $this->handle->getResult()) {
                }
                throw new QueryExecutionError($result->errorMessage, $result->diag, null, $sql ?? '');
            case pq\Result::BAD_RESPONSE:
                $this->close();
                throw new FailureException($result->errorMessage);
            default:
                $this->close();
                throw new FailureException("Unknown result status");
        }
    }
    /**
     *
     */
    private function fetch() : \Generator
    {
        if (!$this->handle->busy) {
            // Results buffered.
            $result = $this->handle->getResult();
        } else {
            $this->deferred = new Deferred();
            Loop::reference($this->poll);
            if (!$this->handle->flush()) {
                Loop::enable($this->await);
            }
            try {
                $result = (yield $this->deferred->promise());
            } finally {
                $this->deferred = null;
            }
        }
        if (!$result) {
            throw new ConnectionException("Connection closed");
        }
        switch ($result->status) {
            case pq\Result::TUPLES_OK:
                // End of result set.
                return null;
            case pq\Result::SINGLE_TUPLE:
                return $result;
            default:
                $this->close();
                throw new FailureException($result->errorMessage);
        }
    }
    /**
     *
     */
    private function release() : void
    {
        \assert($this->busy instanceof Deferred && $this->busy !== $this->deferred, "Connection in invalid state when releasing");
        while ($this->handle->busy && $this->handle->getResult()) {
        }
        $deferred = $this->busy;
        $this->busy = null;
        $deferred->resolve();
    }
    /**
     * Executes the named statement using the given parameters.
     *
     * @param string $name
     * @param array $params
     *
     * @return Promise
     * @throws FailureException
     */
    public function statementExecute(string $name, array $params) : Promise
    {
        \assert(isset($this->statements[$name]), "Named statement not found when executing");
        $storage = $this->statements[$name];
        \assert($storage->statement instanceof pq\Statement, "Statement storage in invalid state");
        return new Coroutine($this->send($storage->sql, [$storage->statement, "execAsync"], $params));
    }
    /**
     * @param string $name
     *
     * @return Promise
     *
     * @throws FailureException
     */
    public function statementDeallocate(string $name) : Promise
    {
        if (!$this->handle) {
            return new Success();
            // Connection dead.
        }
        \assert(isset($this->statements[$name]), "Named statement not found when deallocating");
        $storage = $this->statements[$name];
        if (--$storage->refCount) {
            return new Success();
        }
        \assert($storage->statement instanceof pq\Statement, "Statement storage in invalid state");
        return $storage->promise = call(function () use($storage, $name) {
            yield from $this->send(null, [$storage->statement, "deallocateAsync"]);
            unset($this->statements[$name]);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function query(string $sql) : Promise
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return new Coroutine($this->send($sql, [$this->handle, "execAsync"], $sql));
    }
    /**
     * {@inheritdoc}
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        $sql = Internal\parseNamedParams($sql, $names);
        $params = Internal\replaceNamedParams($params, $names);
        return new Coroutine($this->send($sql, [$this->handle, "execParamsAsync"], $sql, $params));
    }
    /**
     * {@inheritdoc}
     */
    public function prepare(string $sql) : Promise
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return call(function () use($sql) {
            $modifiedSql = Internal\parseNamedParams($sql, $names);
            $name = Handle::STATEMENT_NAME_PREFIX . \sha1($modifiedSql);
            while (isset($this->statements[$name])) {
                $storage = $this->statements[$name];
                ++$storage->refCount;
                // Statement may be being allocated or deallocated. Wait to finish, then check for existence again.
                if ($storage->promise instanceof Promise) {
                    // Do not return promised prepared statement object, as the $names array may differ.
                    (yield $storage->promise);
                    --$storage->refCount;
                    continue;
                }
                return new PqStatement($this, $name, $sql, $names);
            }
            $storage = new class
            {
                use Struct;
                public $refCount = 1;
                /** @var Promise<string> */
                public $promise;
                /** @var pq\Statement */
                public $statement;
                /** @var string */
                public $sql;
            };
            $storage->sql = $sql;
            $this->statements[$name] = $storage;
            try {
                $storage->statement = (yield $storage->promise = new Coroutine($this->send($sql, [$this->handle, "prepareAsync"], $name, $modifiedSql)));
            } catch (\Throwable $exception) {
                unset($this->statements[$name]);
                throw $exception;
            } finally {
                $storage->promise = null;
            }
            return new PqStatement($this, $name, $sql, $names);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        return new Coroutine($this->send(null, [$this->handle, "notifyAsync"], $channel, $payload));
    }
    /**
     * {@inheritdoc}
     */
    public function listen(string $channel) : Promise
    {
        return call(function () use($channel) {
            if (isset($this->listeners[$channel])) {
                throw new QueryError(\sprintf("Already listening on channel '%s'", $channel));
            }
            $this->listeners[$channel] = $emitter = new Emitter();
            try {
                yield from $this->send(null, [$this->handle, "listenAsync"], $channel, static function (string $channel, string $message, int $pid) use($emitter) {
                    $notification = new Notification();
                    $notification->channel = $channel;
                    $notification->pid = $pid;
                    $notification->payload = $message;
                    $emitter->emit($notification);
                });
            } catch (\Throwable $exception) {
                unset($this->listeners[$channel]);
                throw $exception;
            }
            Loop::reference($this->poll);
            return new ConnectionListener($emitter->iterate(), $channel, \Closure::fromCallable([$this, 'unlisten']));
        });
    }
    /**
     * @param string $channel
     *
     * @return Promise
     *
     * @throws \Error
     */
    private function unlisten(string $channel) : Promise
    {
        \assert(isset($this->listeners[$channel]), "Not listening on that channel");
        $emitter = $this->listeners[$channel];
        unset($this->listeners[$channel]);
        if (!$this->handle) {
            $promise = new Success();
            // Connection already closed.
        } else {
            $promise = new Coroutine($this->send(null, [$this->handle, "unlistenAsync"], $channel));
        }
        $promise->onResolve([$emitter, "complete"]);
        return $promise;
    }
    /**
     * {@inheritdoc}
     */
    public function quoteString(string $data) : string
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return $this->handle->quote($data);
    }
    /**
     * {@inheritdoc}
     */
    public function quoteName(string $name) : string
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return $this->handle->quoteName($name);
    }
    /**
     * @return bool True if result sets are buffered in memory, false if unbuffered.
     */
    public function isBufferingResults() : bool
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return !$this->handle->unbuffered;
    }
    /**
     * Sets result sets to be fully buffered in local memory.
     */
    public function shouldBufferResults()
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        $this->handle->unbuffered = false;
    }
    /**
     * Sets result sets to be streamed from the database server.
     */
    public function shouldNotBufferResults()
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        $this->handle->unbuffered = true;
    }
}<?php

namespace Amp\Postgres;

interface Quoter
{
    /**
    * Quotes (escapes) the given string for use as a string literal or identifier in a query. This method wraps the
    string in single quotes, so additional quotes should not be added in the query.
    *
    * @param string $data Unquoted data.
    *
    * @return string Quoted string wrapped in single quotes.
    *
    * @throws \Error If the connection to the database has been closed.
    */
    public function quoteString(string $data) : string;
    /**
     * Quotes (escapes) the given string for use as a name or identifier in a query.
     *
     * @param string $name Unquoted identifier.
     *
     * @return string Quoted identifier.
     *
     * @throws \Error If the connection to the database has been closed.
     */
    public function quoteName(string $name) : string;
}<?php

namespace Amp\Postgres;

use Amp\Sql\CommandResult;
use pq;
final class PqCommandResult implements CommandResult
{
    /** @var \pq\Result PostgreSQL result object. */
    private $result;
    /**
     * @param \pq\Result $result PostgreSQL result object.
     */
    public function __construct(pq\Result $result)
    {
        $this->result = $result;
    }
    /**
     * @return int Number of rows affected by the INSERT, UPDATE, or DELETE query.
     */
    public function getAffectedRowCount() : int
    {
        return $this->result->affectedRows;
    }
}<?php

namespace Amp\Postgres\Internal;

use function Amp\Postgres\cast;
const STATEMENT_PARAM_REGEX = <<<'REGEX'
[
    # Skip all quoted groups.
    (['"])(?:\\(?:\\|\1)|(?!\1).)*+\1(*SKIP)(*FAIL)
    |
    # Unnamed parameters.
    (?<unnamed>
        \$(?<numbered>\d+)
        |
        # Match all question marks except those surrounded by "operator"-class characters on either side.
        (?<!(?<operators>[-+\\*/<>~!@#%^&|`?]))
        \?
        (?!\g<operators>|=)
        |
        :\?
    )
    |
    # Named parameters.
    (?<!:):(?<named>[a-zA-Z_][a-zA-Z0-9_]*)
]msxS
REGEX;
/**
 * @param string $sql SQL statement with named and unnamed placeholders.
 * @param (array | null) $names [Output] Array of parameter positions mapped to names and/or indexed locations.
 *
 * @return string SQL statement with Postgres-style placeholders
 */
function parseNamedParams(string $sql, ?array &$names) : string
{
    $names = [];
    return \preg_replace_callback(STATEMENT_PARAM_REGEX, function (array $matches) use(&$names) : string {
        static $index = 0, $unnamed = 0, $numbered = 1;
        if (isset($matches['named'])) {
            $names[$index] = $matches['named'];
        } elseif (!isset($matches['numbered'])) {
            $names[$index] = $unnamed++;
        } else {
            if ($unnamed > 0) {
                throw new \Error("Cannot mix unnamed (? placeholders) with numbered parameters");
            }
            $position = (int) $matches['numbered'];
            if ($position <= 0 || $position > $numbered + 1) {
                throw new \Error("Numbered placeholders must be sequential starting at 1");
            }
            $numbered = \max($position, $numbered);
            $names[$index] = $position - 1;
        }
        return '$' . ++$index;
    }, $sql);
}
/**
 * @param mixed[] $params User-provided array of statement parameters.
 * @param mixed[] $names Array generated by parseNamedParams.
 *
 * @return mixed[]
 *
 * @throws \Error If the $param array does not contain a key corresponding to a named parameter.
 */
function replaceNamedParams(array $params, array $names) : array
{
    $values = [];
    foreach ($names as $index => $name) {
        if (!\array_key_exists($name, $params)) {
            if (\is_int($name)) {
                $message = \sprintf("Value for unnamed parameter at position %s missing", $name);
            } else {
                $message = \sprintf("Value for named parameter '%s' missing", $name);
            }
            throw new \Error($message);
        }
        $values[$index] = cast($params[$name]);
    }
    return $values;
}<?php

namespace Amp\Postgres\Internal;

use Amp\Postgres\ParseException;
/**
 * @internal
 */
final class ArrayParser
{
    /**
     * @param string $data String representation of PostgreSQL array.
     * @param callable $cast Callback to cast parsed values.
     * @param string $delimiter Delimiter used to separate values.
     *
     * @return array Parsed column data.
     *
     * @throws ParseException
     */
    public function parse(string $data, callable $cast, string $delimiter = ',') : array
    {
        $data = \trim($data);
        $parser = $this->parser($data, $cast, $delimiter);
        $data = \iterator_to_array($parser);
        if ($parser->getReturn() !== '') {
            throw new ParseException("Data left in buffer after parsing");
        }
        return $data;
    }
    /**
     * Recursive generator parser yielding array values.
     *
     * @param string $data Remaining buffer data.
     * @param callable $cast Callback to cast parsed values.
     * @param string $delimiter Delimiter used to separate values.
     *
     * @return \Generator
     *
     * @throws ParseException
     */
    private function parser(string $data, callable $cast, string $delimiter = ',') : \Generator
    {
        if ($data === '') {
            throw new ParseException("Unexpected end of data");
        }
        if ($data[0] !== '{') {
            throw new ParseException("Missing opening bracket");
        }
        $data = \ltrim(\Phabel\Target\Php80\Polyfill::substr($data, 1));
        do {
            if ($data === '') {
                throw new ParseException("Unexpected end of data");
            }
            if ($data[0] === '}') {
                // Empty array
                return \ltrim(\Phabel\Target\Php80\Polyfill::substr($data, 1));
            }
            if ($data[0] === '{') {
                // Array
                $parser = $this->parser($data, $cast, $delimiter);
                (yield \iterator_to_array($parser));
                $data = $parser->getReturn();
                $end = $this->trim($data, 0, $delimiter);
                continue;
            }
            if ($data[0] === '"') {
                // Quoted value
                for ($position = 1; isset($data[$position]); ++$position) {
                    if ($data[$position] === '\\') {
                        ++$position;
                        // Skip next character
                        continue;
                    }
                    if ($data[$position] === '"') {
                        break;
                    }
                }
                if (!isset($data[$position])) {
                    throw new ParseException("Could not find matching quote in quoted value");
                }
                $yield = \stripslashes(\Phabel\Target\Php80\Polyfill::substr($data, 1, $position - 1));
                $end = $this->trim($data, $position + 1, $delimiter);
            } else {
                // Unquoted value
                $position = 0;
                while (isset($data[$position]) && $data[$position] !== $delimiter && $data[$position] !== '}') {
                    ++$position;
                }
                $yield = \trim(\Phabel\Target\Php80\Polyfill::substr($data, 0, $position));
                $end = $this->trim($data, $position, $delimiter);
                if (\strcasecmp($yield, "NULL") === 0) {
                    // Literal NULL is always unquoted.
                    (yield null);
                    continue;
                }
            }
            (yield $cast($yield));
        } while ($end !== '}');
        return $data;
    }
    /**
     * @param string $data Data trimmed past next delimiter and any whitespace to the right of the delimiter.
     * @param int $position Position to start search for delimiter.
     * @param string $delimiter Delimiter used to separate values.
     *
     * @return string First non-whitespace character after given position.
     *
     * @throws ParseException
     */
    private function trim(string &$data, int $position, string $delimiter) : string
    {
        $data = \ltrim(\Phabel\Target\Php80\Polyfill::substr($data, $position));
        if ($data === '') {
            throw new ParseException("Unexpected end of data");
        }
        $end = $data[0];
        if ($end !== $delimiter && $end !== '}') {
            throw new ParseException("Invalid delimiter");
        }
        $data = \ltrim(\Phabel\Target\Php80\Polyfill::substr($data, 1));
        return $end;
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Statement;
final class PgSqlStatement implements Statement
{
    /** @var PgSqlHandle */
    private $handle;
    /** @var string */
    private $name;
    /** @var string */
    private $sql;
    /** @var string[] */
    private $params;
    /** @var int */
    private $lastUsedAt;
    /**
     * @param PgSqlHandle $handle
     * @param string $name
     * @param string $sql
     * @param string[] $params
     */
    public function __construct(PgSqlHandle $handle, string $name, string $sql, array $params)
    {
        $this->handle = $handle;
        $this->name = $name;
        $this->sql = $sql;
        $this->params = $params;
        $this->lastUsedAt = \time();
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->handle->statementDeallocate($this->name);
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public function getQuery() : string
    {
        return $this->sql;
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     * {@inheritdoc}
     */
    public function execute(array $params = []) : Promise
    {
        return $this->handle->statementExecute($this->name, Internal\replaceNamedParams($params, $this->params));
    }
}<?php

namespace Amp\Postgres;

use Amp\Coroutine;
use Amp\Promise;
use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\Common\StatementPool as SqlStatementPool;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\Connector;
use Amp\Sql\Pool as SqlPool;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
use Amp\Sql\Transaction as SqlTransaction;
use function Amp\call;
final class Pool extends ConnectionPool implements Link
{
    /** @var Connection|Promise|null Connection used for notification listening. */
    private $listeningConnection;
    /** @var int Number of listeners on listening connection. */
    private $listenerCount = 0;
    /** @var bool */
    private $resetConnections;
    /**
     * @param ConnectionConfig $config
     * @param int $maxConnections
     * @param int $idleTimeout
     * @param bool $resetConnections True to automatically execute DISCARD ALL on a connection before use.
     * @param (Connector | null) $connector
     */
    public function __construct(ConnectionConfig $config, int $maxConnections = self::DEFAULT_MAX_CONNECTIONS, int $idleTimeout = self::DEFAULT_IDLE_TIMEOUT, bool $resetConnections = true, ?Connector $connector = null)
    {
        parent::__construct($config, $maxConnections, $idleTimeout, $connector);
        $this->resetConnections = $resetConnections;
    }
    /**
     * @return Connector The Connector instance defined by the connector() function.
     */
    protected function createDefaultConnector() : Connector
    {
        return connector();
    }
    /**
     *
     */
    protected function createStatement(SqlStatement $statement, callable $release) : SqlStatement
    {
        return new PooledStatement($statement, $release);
    }
    /**
     *
     */
    protected function createStatementPool(SqlPool $pool, SqlStatement $statement, callable $prepare) : SqlStatementPool
    {
        return new StatementPool($pool, $statement, $prepare);
    }
    /**
     *
     */
    protected function createTransaction(SqlTransaction $transaction, callable $release) : SqlTransaction
    {
        \assert($transaction instanceof Transaction);
        return new PooledTransaction($transaction, $release);
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    protected function pop() : \Generator
    {
        $connection = (yield from parent::pop());
        \assert($connection instanceof Connection);
        if ($this->resetConnections) {
            (yield $connection->query("DISCARD ALL"));
        }
        return $connection;
    }
    /**
     * {@inheritdoc}
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        return call(function () use($channel, $payload) {
            $connection = (yield from $this->pop());
            \assert($connection instanceof Connection);
            try {
                $result = (yield $connection->notify($channel, $payload));
            } finally {
                $this->push($connection);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function listen(string $channel) : Promise
    {
        return call(function () use($channel) {
            ++$this->listenerCount;
            if ($this->listeningConnection === null) {
                $this->listeningConnection = new Coroutine($this->pop());
            }
            if ($this->listeningConnection instanceof Promise) {
                $this->listeningConnection = (yield $this->listeningConnection);
            }
            try {
                $listener = (yield $this->listeningConnection->listen($channel));
                \assert($listener instanceof Listener);
            } catch (\Throwable $exception) {
                if (--$this->listenerCount === 0) {
                    $connection = $this->listeningConnection;
                    $this->listeningConnection = null;
                    $this->push($connection);
                }
                throw $exception;
            }
            return new PooledListener($listener, function () {
                if (--$this->listenerCount === 0) {
                    $connection = $this->listeningConnection;
                    $this->listeningConnection = null;
                    $this->push($connection);
                }
            });
        });
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Common\StatementPool as SqlStatementPool;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement;
use Amp\Success;
final class StatementPool extends SqlStatementPool
{
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    protected function prepare(Statement $statement) : Promise
    {
        return new Success($statement);
        // Nothing to be done.
    }
}<?php

namespace Amp\Postgres;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Promise;
use Amp\Sql\Link;
use Amp\Sql\Transaction;
use function Amp\call;
abstract class Connection implements Link, Handle
{
    /** @var Handle */
    private $handle;
    /** @var Deferred|null Used to only allow one transaction at a time. */
    private $busy;
    /**
     * @param ConnectionConfig $connectionConfig
     * @param CancellationToken $token
     *
     * @return Promise<Connection>
     */
    public static abstract function connect(ConnectionConfig $connectionConfig, ?CancellationToken $token = null) : Promise;
    /**
     * @param Handle $handle
     */
    public function __construct(Handle $handle)
    {
        $this->handle = $handle;
    }
    /**
     * {@inheritdoc}
     */
    public final function isAlive() : bool
    {
        return $this->handle->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public final function getLastUsedAt() : int
    {
        return $this->handle->getLastUsedAt();
    }
    /**
     * {@inheritdoc}
     */
    public final function close() : void
    {
        $this->handle->close();
    }
    /**
     * @param string $methodName Method to execute.
     * @param mixed ...$args Arguments to pass to function.
     *
     * @return Promise
     */
    private function send(string $methodName, ...$args) : Promise
    {
        if ($this->busy) {
            return call(function () use($methodName, $args) {
                while ($this->busy) {
                    (yield $this->busy->promise());
                }
                return (yield $this->handle->{$methodName}(...$args));
            });
        }
        return $this->handle->{$methodName}(...$args);
    }
    /**
     * Reserves the connection for a transaction.
     */
    private function reserve() : void
    {
        \assert($this->busy === null);
        $this->busy = new Deferred();
    }
    /**
     * Releases the transaction lock.
     */
    private function release() : void
    {
        \assert($this->busy !== null);
        $deferred = $this->busy;
        $this->busy = null;
        $deferred->resolve();
    }
    /**
     * {@inheritdoc}
     */
    public final function query(string $sql) : Promise
    {
        return $this->send("query", $sql);
    }
    /**
     * {@inheritdoc}
     */
    public final function execute(string $sql, array $params = []) : Promise
    {
        return $this->send("execute", $sql, $params);
    }
    /**
     * {@inheritdoc}
     */
    public final function prepare(string $sql) : Promise
    {
        return $this->send("prepare", $sql);
    }
    /**
     * {@inheritdoc}
     */
    public final function notify(string $channel, string $payload = "") : Promise
    {
        return $this->send("notify", $channel, $payload);
    }
    /**
     * {@inheritdoc}
     */
    public final function listen(string $channel) : Promise
    {
        return $this->send("listen", $channel);
    }
    /**
     * {@inheritdoc}
     */
    public final function beginTransaction(int $isolation = Transaction::ISOLATION_COMMITTED) : Promise
    {
        return call(function () use($isolation) {
            $this->reserve();
            try {
                switch ($isolation) {
                    case Transaction::ISOLATION_UNCOMMITTED:
                        (yield $this->handle->query("BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"));
                        break;
                    case Transaction::ISOLATION_COMMITTED:
                        (yield $this->handle->query("BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED"));
                        break;
                    case Transaction::ISOLATION_REPEATABLE:
                        (yield $this->handle->query("BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ"));
                        break;
                    case Transaction::ISOLATION_SERIALIZABLE:
                        (yield $this->handle->query("BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE"));
                        break;
                    default:
                        throw new \Error("Invalid transaction type");
                }
            } catch (\Throwable $exception) {
                $this->release();
                throw $exception;
            }
            return new ConnectionTransaction($this->handle, \Closure::fromCallable([$this, 'release']), $isolation);
        });
    }
    /**
     * {@inheritdoc}
     */
    public final function quoteString(string $data) : string
    {
        return $this->handle->quoteString($data);
    }
    /**
     * {@inheritdoc}
     */
    public final function quoteName(string $name) : string
    {
        return $this->handle->quoteName($name);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
final class PooledListener implements Listener
{
    /** @var Listener */
    private $listener;
    /** @var callable|null */
    private $release;
    /**
     *
     */
    public function __construct(Listener $listener, callable $release)
    {
        $this->listener = $listener;
        $this->release = $release;
        if (!$this->listener->isListening()) {
            ($this->release)();
            $this->release = null;
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->listener->isListening()) {
            $this->unlisten();
            // Invokes $this->release callback.
        }
    }
    /**
     *
     */
    public function advance() : Promise
    {
        return $this->listener->advance();
    }
    /**
     *
     */
    public function getCurrent() : Notification
    {
        return $this->listener->getCurrent();
    }
    /**
     *
     */
    public function getChannel() : string
    {
        return $this->listener->getChannel();
    }
    /**
     *
     */
    public function isListening() : bool
    {
        return $this->listener->isListening();
    }
    /**
     *
     */
    public function unlisten() : Promise
    {
        if (!$this->release) {
            throw new \Error("Already unlistened on this channel");
        }
        $promise = $this->listener->unlisten();
        $promise->onResolve($this->release);
        $this->release = null;
        return $promise;
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\ResultSet as SqlResultSet;
interface ResultSet extends SqlResultSet
{
    /**
     * Returns the number of fields (columns) in each row.
     *
     * @return int
     */
    public function getFieldCount() : int;
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Executor as SqlExecutor;
interface Executor extends SqlExecutor
{
    /**
     * @param string $channel Channel name.
     * @param string $payload Notification payload.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws \Amp\Sql\FailureException If the operation fails due to unexpected condition.
     * @throws \Amp\Sql\ConnectionException If the connection to the database is lost.
     */
    public function notify(string $channel, string $payload = "") : Promise;
}<?php

namespace Amp\Postgres;

use Amp\Sql\Link as SqlLink;
interface Link extends Receiver, SqlLink
{
}<?php

namespace Amp\Postgres;

use Amp\Sql\Transaction as SqlTransaction;
/**
 * Note that notifications sent during a transaction are not delivered until the transaction has been committed.
 */
interface Transaction extends Executor, Quoter, SqlTransaction
{
}<?php

namespace Amp\Postgres;

use Amp\Loop;
use Amp\Promise;
use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
use Amp\Sql\Connector;
const LOOP_CONNECTOR_IDENTIFIER = Connector::class . "\\Postgres";
/**
 *
 */
function connector(?Connector $connector = null) : Connector
{
    if ($connector === null) {
        $connector = Loop::getState(LOOP_CONNECTOR_IDENTIFIER);
        if ($connector) {
            return $connector;
        }
        $connector = new TimeoutConnector();
    }
    Loop::setState(LOOP_CONNECTOR_IDENTIFIER, $connector);
    return $connector;
}
/**
 * Create a connection using the global Connector instance.
 *
 * @param SqlConnectionConfig $config
 *
 * @return Promise<Connection>
 *
 * @throws \Amp\Sql\FailureException If connecting fails.
 *
 * @throws \Error If neither ext-pgsql or pecl-pq is loaded.
 *
 * @codeCoverageIgnore
 */
function connect(SqlConnectionConfig $config) : Promise
{
    return connector()->connect($config);
}
/**
 * Create a pool using the global Connector instance.
 *
 * @param SqlConnectionConfig $config
 * @param int $maxConnections
 * @param int $idleTimeout
 * @param bool $resetConnections
 *
 * @return Pool
 */
function pool(SqlConnectionConfig $config, int $maxConnections = ConnectionPool::DEFAULT_MAX_CONNECTIONS, int $idleTimeout = ConnectionPool::DEFAULT_IDLE_TIMEOUT, bool $resetConnections = true) : Pool
{
    return new Pool($config, $maxConnections, $idleTimeout, $resetConnections, connector());
}
/**
 * Casts a PHP value to a representation that is understood by Postgres, including encoding arrays.
 *
 * @param mixed $value
 *
 * @return (string | int | float | null)
 *
 * @throws \Error If $value is an object without a __toString() method, a resource, or an unknown type.
 */
function cast($value)
{
    switch ($type = \gettype($value)) {
        case "NULL":
        case "integer":
        case "double":
        case "string":
            return $value;
        // No casting necessary for numerics, strings, and null.
        case "boolean":
            return $value ? 't' : 'f';
        case "array":
            return encode($value);
        case "object":
            if (!\method_exists($value, "__toString")) {
                throw new \Error("Object without a __toString() method included in parameter values");
            }
            return (string) $value;
        default:
            throw new \Error("Invalid value type '{$type}' in parameter values");
    }
}
/**
 * Encodes an array into a PostgreSQL representation of the array.
 *
 * @param array $array
 *
 * @return string The serialized representation of the array.
 *
 * @throws \Error If $array contains an object without a __toString() method, a resource, or an unknown type.
 */
function encode(array $array) : string
{
    $array = \array_map(function ($value) {
        switch (\gettype($value)) {
            case "NULL":
                return "NULL";
            case "object":
                if (!\method_exists($value, "__toString")) {
                    throw new \Error("Object without a __toString() method in array");
                }
                $value = (string) $value;
            // no break
            case "string":
                return '"' . \str_replace(['\\', '"'], ['\\\\', '\\"'], $value) . '"';
            default:
                return cast($value);
        }
    }, $array);
    return '{' . \implode(',', $array) . '}';
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Common\PooledTransaction as SqlPooledTransaction;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
final class PooledTransaction extends SqlPooledTransaction implements Transaction
{
    /** @var Transaction|null */
    private $transaction;
    /**
     *
     */
    protected function createStatement(SqlStatement $statement, callable $release) : SqlStatement
    {
        return new PooledStatement($statement, $release);
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     * @param Transaction $transaction
     * @param callable $release
     */
    public function __construct(Transaction $transaction, callable $release)
    {
        parent::__construct($transaction, $release);
        $this->transaction = $transaction;
    }
    /**
     *
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        return $this->transaction->notify($channel, $payload);
    }
    /**
     *
     */
    public function quoteString(string $data) : string
    {
        return $this->transaction->quoteString($data);
    }
    /**
     *
     */
    public function quoteName(string $name) : string
    {
        return $this->transaction->quoteName($name);
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\QueryError;
class QueryExecutionError extends QueryError
{
    /** @var mixed[] */
    private $diagnostics;
    /**
     *
     */
    public function __construct(string $message, array $diagnostics, \Throwable $previous = null, string $query = '')
    {
        parent::__construct($message, $query, $previous);
        $this->diagnostics = $diagnostics;
    }
    /**
     *
     */
    public function getDiagnostics() : array
    {
        return $this->diagnostics;
    }
}<?php

namespace Amp\Postgres;

interface Handle extends Receiver, Quoter
{
    const STATEMENT_NAME_PREFIX = "amp_";
}<?php

namespace Amp\Postgres;

use Amp\Iterator;
use Amp\Promise;
interface Listener extends Iterator
{
    /**
     * @return string Channel name.
     */
    public function getChannel() : string;
    /**
     * @return bool
     */
    public function isListening() : bool;
    /**
     * Unlistens from the channel. No more values will be emitted from this listener.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws \Error If this method was previously invoked.
     */
    public function unlisten() : Promise;
}<?php

namespace Amp\Postgres;

use Amp\Sql\Common\PooledResultSet as SqlPooledResultSet;
final class PooledResultSet extends SqlPooledResultSet implements ResultSet
{
    /** @var ResultSet */
    private $result;
    /**
     * @param ResultSet $result
     * @param callable $release
     */
    public function __construct(ResultSet $result, callable $release)
    {
        parent::__construct($result, $release);
        $this->result = $result;
    }
    /**
     *
     */
    public function getFieldCount() : int
    {
        return $this->result->getFieldCount();
    }
}<?php

namespace Amp\Postgres;

use Amp\Producer;
use Amp\Promise;
use pq;
use function Amp\asyncCall;
final class PqUnbufferedResultSet implements ResultSet
{
    /** @var int */
    private $numCols;
    /** @var \Amp\Producer */
    private $producer;
    /** @var array|object Last row emitted. */
    private $currentRow;
    /** @var bool */
    private $destroyed = false;
    /**
     * @param callable():  $fetch Function to fetch next result row.
     * @param \pq\Result $result PostgreSQL result object.
     */
    public function __construct(callable $fetch, pq\Result $result, callable $release)
    {
        $this->numCols = $result->numCols;
        $destroyed =& $this->destroyed;
        $this->producer = new Producer(static function (callable $emit) use(&$destroyed, $release, $result, $fetch) {
            try {
                do {
                    $result->autoConvert = pq\Result::CONV_SCALAR | pq\Result::CONV_ARRAY;
                    $next = $fetch();
                    (yield $emit($result));
                    $result = (yield $next);
                } while ($result instanceof pq\Result);
            } finally {
                $destroyed = true;
                $release();
            }
        });
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->destroyed) {
            return;
        }
        $producer = $this->producer;
        asyncCall(static function () use($producer) {
            try {
                while ((yield $producer->advance())) {
                }
            } catch (\Throwable $exception) {
                // Ignore iterator failure when destroying.
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        $this->currentRow = null;
        return $this->producer->advance();
    }
    /**
     * {@inheritdoc}
     */
    public function getCurrent() : array
    {
        if ($this->currentRow !== null) {
            return $this->currentRow;
        }
        $result = $this->producer->getCurrent();
        \assert($result instanceof pq\Result);
        return $this->currentRow = $result->fetchRow(pq\Result::FETCH_ASSOC);
    }
    /**
     * @return int Number of fields (columns) in each result set.
     */
    public function getFieldCount() : int
    {
        return $this->numCols;
    }
}<?php

namespace Amp\Postgres;

use Amp\Deferred;
use Amp\Emitter;
use Amp\Loop;
use Amp\Promise;
use Amp\Sql\ConnectionException;
use Amp\Sql\FailureException;
use Amp\Sql\QueryError;
use Amp\Struct;
use Amp\Success;
use function Amp\call;
final class PgSqlHandle implements Handle
{
    const DIAGNOSTIC_CODES = [\PGSQL_DIAG_SEVERITY => "severity", \PGSQL_DIAG_SQLSTATE => "sqlstate", \PGSQL_DIAG_MESSAGE_PRIMARY => "message_primary", \PGSQL_DIAG_MESSAGE_DETAIL => "message_detail", \PGSQL_DIAG_MESSAGE_HINT => "message_hint", \PGSQL_DIAG_STATEMENT_POSITION => "statement_position", \PGSQL_DIAG_INTERNAL_POSITION => "internal_position", \PGSQL_DIAG_INTERNAL_QUERY => "internal_query", \PGSQL_DIAG_CONTEXT => "context", \PGSQL_DIAG_SOURCE_FILE => "source_file", \PGSQL_DIAG_SOURCE_LINE => "source_line", \PGSQL_DIAG_SOURCE_FUNCTION => "source_function"];
    /** @var array<string, Promise<array<int, array{string, string}>>> */
    private static $typeCache;
    /** @var resource|\PgSql\Connection|null PostgreSQL connection handle. */
    private $handle;
    /** @var Promise<array<int, array{string, string}>> */
    private $types;
    /** @var Deferred|null */
    private $deferred;
    /** @var string */
    private $poll;
    /** @var string */
    private $await;
    /** @var Emitter[] */
    private $listeners = [];
    /** @var array<string, object{refCount: int, promise: Promise<string>, sql: string}> */
    private $statements = [];
    /** @var int */
    private $lastUsedAt;
    /**
     * @param resource $handle PostgreSQL connection handle.
     * @param resource $socket PostgreSQL connection stream socket.
     * @param string $id Connection identifier for determining which cached type table to use.
     */
    public function __construct($handle, $socket, string $id = '')
    {
        $this->handle = $handle;
        $this->lastUsedAt = \time();
        $handle =& $this->handle;
        $lastUsedAt =& $this->lastUsedAt;
        $deferred =& $this->deferred;
        $listeners =& $this->listeners;
        $this->poll = Loop::onReadable($socket, static function ($watcher) use(&$deferred, &$lastUsedAt, &$listeners, &$handle) : void {
            $lastUsedAt = \time();
            if (\pg_connection_status($handle) === \PGSQL_CONNECTION_BAD) {
                $handle = null;
                if ($deferred) {
                    $deferred->fail(new ConnectionException("The connection closed during the operation"));
                }
            }
            if (!\pg_consume_input($handle)) {
                $handle = null;
                // Marks connection as dead.
                Loop::disable($watcher);
                $exception = new ConnectionException(\pg_last_error($handle));
                foreach ($listeners as $listener) {
                    $listener->fail($exception);
                }
                if ($deferred !== null) {
                    $deferred->fail($exception);
                }
                return;
            }
            while ($result = \pg_get_notify($handle, \PGSQL_ASSOC)) {
                $channel = $result["message"];
                if (!isset($listeners[$channel])) {
                    continue;
                }
                $notification = new Notification();
                $notification->channel = $channel;
                $notification->pid = $result["pid"];
                $notification->payload = $result["payload"];
                $listeners[$channel]->emit($notification);
            }
            if ($deferred === null) {
                return;
                // No active query, only notification listeners.
            }
            if (\pg_connection_busy($handle)) {
                return;
            }
            $deferred->resolve(\pg_get_result($handle));
            if (!$deferred && empty($listeners)) {
                Loop::unreference($watcher);
            }
        });
        $this->await = Loop::onWritable($socket, static function ($watcher) use(&$deferred, &$listeners, &$handle) : void {
            $flush = \pg_flush($handle);
            if ($flush === 0) {
                return;
                // Not finished sending data, listen again.
            }
            Loop::disable($watcher);
            if ($flush === false) {
                $exception = new ConnectionException(\pg_last_error($handle));
                $handle = null;
                // Marks connection as dead.
                foreach ($listeners as $listener) {
                    $listener->fail($exception);
                }
                if ($deferred !== null) {
                    $deferred->fail($exception);
                }
            }
        });
        Loop::unreference($this->poll);
        Loop::disable($this->await);
        $this->types = $this->fetchTypes($id);
    }
    /**
     * Frees Io watchers from loop.
     */
    public function __destruct()
    {
        $this->free();
    }
    /**
     *
     */
    private function fetchTypes(string $id) : Promise
    {
        if (isset(self::$typeCache[$id])) {
            return self::$typeCache[$id];
        }
        return self::$typeCache[$id] = call(function () : \Generator {
            $result = (yield from $this->send("pg_send_query", "SELECT t.oid, t.typcategory, t.typdelim, t.typelem\n                 FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace=n.oid\n                 WHERE t.typisdefined AND n.nspname IN ('pg_catalog', 'public')"));
            $types = [];
            while ($row = \pg_fetch_array($result, null, \PGSQL_NUM)) {
                [$oid, $type, $delimiter, $element] = $row;
                $types[(int) $oid] = [$type, $delimiter, (int) $element];
            }
            return $types;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function close() : void
    {
        if ($this->handle instanceof \PgSql\Connection || \is_resource($this->handle)) {
            \pg_close($this->handle);
            $this->handle = null;
        }
        $this->free();
    }
    /**
     *
     */
    private function free() : void
    {
        if ($this->deferred) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->fail(new ConnectionException("The connection was closed"));
        }
        Loop::cancel($this->poll);
        Loop::cancel($this->await);
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle instanceof \PgSql\Connection || \is_resource($this->handle);
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     * @param callable $function Function name to execute.
     * @param mixed ...$args Arguments to pass to function.
     *
     * @return \Generator
     *
     * @resolve resource
     *
     * @throws FailureException
     */
    private function send(callable $function, ...$args) : \Generator
    {
        while ($this->deferred) {
            try {
                (yield $this->deferred->promise());
            } catch (\Throwable $exception) {
                // Ignore failure from another operation.
            }
        }
        if (!$this->isAlive()) {
            throw new ConnectionException("The connection to the database has been closed");
        }
        while ($result = \pg_get_result($this->handle)) {
            \pg_free_result($result);
        }
        $result = $function($this->handle, ...$args);
        if ($result === false) {
            throw new FailureException(\pg_last_error($this->handle));
        }
        $this->deferred = new Deferred();
        Loop::reference($this->poll);
        if (0 === $result) {
            Loop::enable($this->await);
        }
        try {
            $result = (yield $this->deferred->promise());
        } finally {
            $this->deferred = null;
        }
        return $result;
    }
    /**
     * @param resource $result PostgreSQL result resource.
     * @param string $sql Query SQL.
     *
     * @return (\Amp\Sql\CommandResult | ResultSet)
     *
     * @throws FailureException
     * @throws QueryError
     */
    private function createResult($result, string $sql, array $types)
    {
        switch (\pg_result_status($result, \PGSQL_STATUS_LONG)) {
            case \PGSQL_EMPTY_QUERY:
                throw new QueryError("Empty query string");
            case \PGSQL_COMMAND_OK:
                return new PgSqlCommandResult($result);
            case \PGSQL_TUPLES_OK:
                return new PgSqlResultSet($result, $types);
            case \PGSQL_NONFATAL_ERROR:
            case \PGSQL_FATAL_ERROR:
                $diagnostics = [];
                foreach (self::DIAGNOSTIC_CODES as $fieldCode => $desciption) {
                    $diagnostics[$desciption] = \pg_result_error_field($result, $fieldCode);
                }
                $message = \pg_result_error($result);
                while (\pg_connection_busy($this->handle) && \pg_get_result($this->handle)) {
                }
                throw new QueryExecutionError($message, $diagnostics, null, $sql);
            case \PGSQL_BAD_RESPONSE:
                $this->close();
                throw new FailureException(\pg_result_error($result));
            default:
                // @codeCoverageIgnoreStart
                $this->close();
                throw new FailureException("Unknown result status");
        }
    }
    /**
     * @param string $name
     * @param array $params
     *
     * @return Promise
     */
    public function statementExecute(string $name, array $params) : Promise
    {
        return call(function () use($name, $params) {
            \assert(isset($this->statements[$name]), "Named statement not found when executing");
            return $this->createResult(yield from $this->send("pg_send_execute", $name, $params), $this->statements[$name]->sql, (yield $this->types));
        });
    }
    /**
     * @param string $name
     *
     * @return Promise
     *
     * @throws \Error
     */
    public function statementDeallocate(string $name) : Promise
    {
        if (!$this->isAlive()) {
            return new Success();
            // Connection closed, no need to deallocate.
        }
        \assert(isset($this->statements[$name]), "Named statement not found when deallocating");
        $storage = $this->statements[$name];
        if (--$storage->refCount) {
            return new Success();
        }
        return $storage->promise = call(function () use($storage, $name) {
            (yield $this->query(\sprintf("DEALLOCATE %s", $name)));
            unset($this->statements[$name]);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function query(string $sql) : Promise
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        return call(function () use($sql) {
            return $this->createResult(yield from $this->send("pg_send_query", $sql), $sql, (yield $this->types));
        });
    }
    /**
     * {@inheritdoc}
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        $sql = Internal\parseNamedParams($sql, $names);
        $params = Internal\replaceNamedParams($params, $names);
        return call(function () use($sql, $params) {
            return $this->createResult(yield from $this->send("pg_send_query_params", $sql, $params), $sql, (yield $this->types));
        });
    }
    /**
     * {@inheritdoc}
     */
    public function prepare(string $sql) : Promise
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        return call(function () use($sql) {
            $modifiedSql = Internal\parseNamedParams($sql, $names);
            $name = Handle::STATEMENT_NAME_PREFIX . \sha1($modifiedSql);
            while (isset($this->statements[$name])) {
                $storage = $this->statements[$name];
                ++$storage->refCount;
                // Statement may be being allocated or deallocated. Wait to finish, then check for existence again.
                if ($storage->promise instanceof Promise) {
                    // Do not return promised prepared statement object, as the $names array may differ.
                    (yield $storage->promise);
                    --$storage->refCount;
                    continue;
                }
                return new PgSqlStatement($this, $name, $sql, $names);
            }
            $storage = new class
            {
                use Struct;
                public $refCount = 1;
                /** @var Promise<string> */
                public $promise;
                /** @var string */
                public $sql;
            };
            $storage->sql = $sql;
            $this->statements[$name] = $storage;
            try {
                (yield $storage->promise = call(function () use($name, $modifiedSql, $sql) {
                    $result = (yield from $this->send("pg_send_prepare", $name, $modifiedSql));
                    switch (\pg_result_status($result, \PGSQL_STATUS_LONG)) {
                        case \PGSQL_COMMAND_OK:
                            return $name;
                        // Statement created successfully.
                        case \PGSQL_NONFATAL_ERROR:
                        case \PGSQL_FATAL_ERROR:
                            $diagnostics = [];
                            foreach (self::DIAGNOSTIC_CODES as $fieldCode => $description) {
                                $diagnostics[$description] = \pg_result_error_field($result, $fieldCode);
                            }
                            throw new QueryExecutionError(\pg_result_error($result), $diagnostics, null, $sql);
                        case \PGSQL_BAD_RESPONSE:
                            throw new FailureException(\pg_result_error($result));
                        default:
                            // @codeCoverageIgnoreStart
                            throw new FailureException("Unknown result status");
                    }
                }));
            } catch (\Throwable $exception) {
                unset($this->statements[$name]);
                throw $exception;
            } finally {
                $storage->promise = null;
            }
            return new PgSqlStatement($this, $name, $sql, $names);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        if ($payload === "") {
            return $this->query(\sprintf("NOTIFY %s", $this->quoteName($channel)));
        }
        return $this->query(\sprintf("NOTIFY %s, %s", $this->quoteName($channel), $this->quoteString($payload)));
    }
    /**
     * {@inheritdoc}
     */
    public function listen(string $channel) : Promise
    {
        return call(function () use($channel) {
            if (isset($this->listeners[$channel])) {
                throw new QueryError(\sprintf("Already listening on channel '%s'", $channel));
            }
            $this->listeners[$channel] = $emitter = new Emitter();
            try {
                (yield $this->query(\sprintf("LISTEN %s", $this->quoteName($channel))));
            } catch (\Throwable $exception) {
                unset($this->listeners[$channel]);
                throw $exception;
            }
            return new ConnectionListener($emitter->iterate(), $channel, \Closure::fromCallable([$this, 'unlisten']));
        });
    }
    /**
     * @param string $channel
     *
     * @return Promise
     *
     * @throws \Error
     */
    private function unlisten(string $channel) : Promise
    {
        \assert(isset($this->listeners[$channel]), "Not listening on that channel");
        $emitter = $this->listeners[$channel];
        unset($this->listeners[$channel]);
        if (!$this->isAlive()) {
            $promise = new Success();
            // Connection already closed.
        } else {
            $promise = $this->query(\sprintf("UNLISTEN %s", $this->quoteName($channel)));
        }
        $promise->onResolve([$emitter, "complete"]);
        return $promise;
    }
    /**
     * {@inheritdoc}
     */
    public function quoteString(string $data) : string
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        return \pg_escape_literal($this->handle, $data);
    }
    /**
     * {@inheritdoc}
     */
    public function quoteName(string $name) : string
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        return \pg_escape_identifier($this->handle, $name);
    }
}<?php

namespace Amp\Postgres;

use Amp\Struct;
final class Notification
{
    use Struct;
    /** @var string Channel name. */
    public $channel;
    /** @var int PID of message source. */
    public $pid;
    /** @var string Message payload */
    public $payload;
}#!/usr/bin/env php
<?php 
require \dirname(__DIR__) . '/vendor/autoload.php';
use Amp\Postgres;
Amp\Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');
    $pool = Postgres\pool($config);
    (yield $pool->query('DROP TABLE IF EXISTS test'));
    /** @var \Amp\Postgres\Transaction $transaction */
    $transaction = (yield $pool->beginTransaction());
    (yield $transaction->query('CREATE TABLE test (domain VARCHAR(63), tld VARCHAR(63), PRIMARY KEY (domain, tld))'));
    /** @var \Amp\Sql\Statement $statement */
    $statement = (yield $transaction->prepare('INSERT INTO test VALUES (?, ?)'));
    (yield $statement->execute(['amphp', 'org']));
    (yield $statement->execute(['google', 'com']));
    (yield $statement->execute(['github', 'com']));
    /** @var \Amp\Postgres\ResultSet $result */
    $result = (yield $transaction->execute('SELECT * FROM test WHERE tld = :tld', ['tld' => 'com']));
    $format = "%-20s | %-10s\n";
    \printf($format, 'TLD', 'Domain');
    while ((yield $result->advance())) {
        $row = $result->getCurrent();
        \printf($format, $row['domain'], $row['tld']);
    }
    (yield $transaction->rollback());
});#!/usr/bin/env php
<?php 
require \dirname(__DIR__) . '/vendor/autoload.php';
use Amp\Iterator;
use Amp\Loop;
use Amp\Postgres;
Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');
    $pool = Postgres\pool($config);
    $channel1 = "test1";
    $channel2 = "test2";
    /** @var \Amp\Postgres\Listener $listener1 */
    $listener1 = (yield $pool->listen($channel1));
    \printf("Listening on channel '%s'\n", $listener1->getChannel());
    /** @var \Amp\Postgres\Listener $listener2 */
    $listener2 = (yield $pool->listen($channel2));
    \printf("Listening on channel '%s'\n", $listener2->getChannel());
    Loop::delay(6000, function () use($listener1) {
        // Unlisten in 6 seconds.
        \printf("Unlistening from channel '%s'\n", $listener1->getChannel());
        return $listener1->unlisten();
    });
    Loop::delay(4000, function () use($listener2) {
        // Unlisten in 4 seconds.
        \printf("Unlistening from channel '%s'\n", $listener2->getChannel());
        return $listener2->unlisten();
    });
    Loop::delay(1000, function () use($pool, $channel1) {
        return $pool->notify($channel1, "Data 1.1");
    });
    Loop::delay(2000, function () use($pool, $channel2) {
        return $pool->notify($channel2, "Data 2.1");
    });
    Loop::delay(3000, function () use($pool, $channel2) {
        return $pool->notify($channel2, "Data 2.2");
    });
    Loop::delay(5000, function () use($pool, $channel1) {
        return $pool->notify($channel1, "Data 1.2");
    });
    $iterator = Iterator\merge([$listener1, $listener2]);
    // Merge both listeners into single iterator.
    while ((yield $iterator->advance())) {
        $notification = $iterator->getCurrent();
        \printf("Received notification from PID %d on channel '%s' with payload: %s\n", $notification->pid, $notification->channel, $notification->payload);
    }
});#!/usr/bin/env php
<?php 
require \dirname(__DIR__) . '/vendor/autoload.php';
use Amp\Loop;
use Amp\Postgres;
Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');
    $pool = Postgres\pool($config);
    $channel = "test";
    /** @var \Amp\Postgres\Listener $listener */
    $listener = (yield $pool->listen($channel));
    \printf("Listening on channel '%s'\n", $listener->getChannel());
    Loop::delay(3000, function () use($listener) {
        // Unlisten in 3 seconds.
        \printf("Unlistening from channel '%s'\n", $listener->getChannel());
        return $listener->unlisten();
    });
    Loop::delay(1000, function () use($pool, $channel) {
        return $pool->notify($channel, "Data 1");
        // Send first notification.
    });
    Loop::delay(2000, function () use($pool, $channel) {
        return $pool->notify($channel, "Data 2");
        // Send second notification.
    });
    while ((yield $listener->advance())) {
        $notification = $listener->getCurrent();
        \printf("Received notification from PID %d on channel '%s' with payload: %s\n", $notification->pid, $notification->channel, $notification->payload);
    }
});#!/usr/bin/env php
<?php 
require \dirname(__DIR__) . '/vendor/autoload.php';
use Amp\Postgres;
Amp\Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');
    /** @var \Amp\Postgres\Connection $connection */
    $connection = (yield Postgres\connect($config));
    /** @var \Amp\Postgres\ResultSet $result */
    $result = (yield $connection->query('SHOW ALL'));
    while ((yield $result->advance())) {
        $row = $result->getCurrent();
        \printf("%-35s = %s (%s)\n", $row['name'], $row['setting'], $row['description']);
    }
});{
    "name": "amphp/postgres",
    "description": "Asynchronous PostgreSQL client for Amp.",
    "keywords": [
        "database",
        "db",
        "postgresql",
        "postgre",
        "pgsql",
        "asynchronous",
        "async"
    ],
    "homepage": "http://amphp.org",
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/sql": "^1",
        "amphp/sql-common": "^1"
    },
    "require-dev": {
        "ext-pgsql": "*",
        "ext-pq": "*",
        "amphp/phpunit-util": "^1.1.2",
        "phpunit/phpunit": "^8 | ^7",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Postgres\\": "src"
        },
        "files": [
            "src/functions.php",
            "src/Internal/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Postgres\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Sql\Common;

use Amp\Promise;
use Amp\Sql\ResultSet;
use Amp\Sql\Statement;
use function Amp\call;
abstract class PooledStatement implements Statement
{
    /** @var Statement */
    private $statement;
    /** @var callable|null */
    private $release;
    /** @var int */
    private $refCount = 1;
    /**
    * Creates a ResultSet of the appropriate type using the ResultSet object returned by the Statement object and
    the given release callable.
    *
    * @param ResultSet $resultSet
    * @param callable $release
    *
    * @return ResultSet
    */
    protected abstract function createResultSet(ResultSet $resultSet, callable $release) : ResultSet;
    /**
     * PooledStatement constructor.
     *
     * @param Statement $statement Statement object created by pooled connection.
     * @param callable $release Callable to be invoked when the statement and any associated results are destroyed.
     */
    public function __construct(Statement $statement, callable $release)
    {
        $this->statement = $statement;
        if (!$this->statement->isAlive()) {
            $release();
        } else {
            $refCount =& $this->refCount;
            $this->release = static function () use(&$refCount, $release) {
                if (--$refCount === 0) {
                    $release();
                }
            };
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->release) {
            ($this->release)();
        }
    }
    /**
     *
     */
    public function execute(array $params = []) : Promise
    {
        return call(function () use($params) {
            $result = (yield $this->statement->execute($params));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return $this->createResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return $this->statement->isAlive();
    }
    /**
     *
     */
    public function getQuery() : string
    {
        return $this->statement->getQuery();
    }
    /**
     *
     */
    public function getLastUsedAt() : int
    {
        return $this->statement->getLastUsedAt();
    }
}<?php

namespace Amp\Sql\Common;

use Amp\MultiReasonException;
use Amp\Promise;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\ConnectionException;
use Amp\Sql\Connector;
use function Amp\call;
final class RetryConnector implements Connector
{
    /** @var Connector */
    private $connector;
    /** @var int */
    private $maxTries;
    /**
     *
     */
    public function __construct(Connector $connector, int $maxTries = 3)
    {
        if ($maxTries <= 0) {
            throw new \Error('The number of tries must be 1 or greater');
        }
        $this->connector = $connector;
        $this->maxTries = $maxTries;
    }
    /**
     *
     */
    public function connect(ConnectionConfig $config) : Promise
    {
        return call(function () use($config) {
            $tries = 0;
            $exceptions = [];
            do {
                try {
                    return (yield $this->connector->connect($config));
                } catch (\Exception $exception) {
                    $exceptions[] = $exception;
                }
            } while (++$tries < $this->maxTries);
            $name = $config->getHost() . ':' . $config->getPort();
            throw new ConnectionException("Could not connect to database server at {$name} after {$tries} tries", 0, new MultiReasonException($exceptions));
        });
    }
}<?php

namespace Amp\Sql\Common;

use Amp\CallableMaker;
use Amp\Deferred;
use Amp\Loop;
use Amp\Promise;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\Connector;
use Amp\Sql\FailureException;
use Amp\Sql\Link;
use Amp\Sql\Pool;
use Amp\Sql\ResultSet;
use Amp\Sql\Statement;
use Amp\Sql\Transaction;
use function Amp\call;
use function Amp\coroutine;
abstract class ConnectionPool implements Pool
{
    use CallableMaker;
    const DEFAULT_MAX_CONNECTIONS = 100;
    const DEFAULT_IDLE_TIMEOUT = 60;
    /** @var Connector */
    private $connector;
    /** @var ConnectionConfig */
    private $connectionConfig;
    /** @var int */
    private $maxConnections;
    /** @var \SplQueue */
    private $idle;
    /** @var \SplObjectStorage */
    private $connections;
    /** @var Promise|null */
    private $promise;
    /** @var Deferred|null */
    private $deferred;
    /** @var int */
    private $idleTimeout;
    /** @var string */
    private $timeoutWatcher;
    /** @var bool */
    private $closed = false;
    /**
     * Create a default connector object based on the library of the extending class.
     *
     * @return Connector
     */
    protected abstract function createDefaultConnector() : Connector;
    /**
    * Creates a ResultSet of the appropriate type using the ResultSet object returned by the Link object and the
    given release callable.
    *
    * @param ResultSet $resultSet
    * @param callable $release
    *
    * @return ResultSet
    */
    protected abstract function createResultSet(ResultSet $resultSet, callable $release) : ResultSet;
    /**
    * Creates a Statement of the appropriate type using the Statement object returned by the Link object and the
    given release callable.
    *
    * @param Statement $statement
    * @param callable $release
    *
    * @return Statement
    */
    protected abstract function createStatement(Statement $statement, callable $release) : Statement;
    /**
     * @param Pool $pool
     * @param Statement $statement
     * @param callable $prepare
     *
     * @return StatementPool
     */
    protected abstract function createStatementPool(Pool $pool, Statement $statement, callable $prepare) : StatementPool;
    /**
    * Creates a Transaction of the appropriate type using the Transaction object returned by the Link object and the
    given release callable.
    *
    * @param Transaction $transaction
    * @param callable $release
    *
    * @return Transaction
    */
    protected abstract function createTransaction(Transaction $transaction, callable $release) : Transaction;
    /**
     * @param ConnectionConfig $config
     * @param int $maxConnections Maximum number of active connections in the pool.
     * @param int $idleTimeout Number of seconds until idle connections are removed from the pool.
     * @param (Connector | null) $connector
     */
    public function __construct(ConnectionConfig $config, int $maxConnections = self::DEFAULT_MAX_CONNECTIONS, int $idleTimeout = self::DEFAULT_IDLE_TIMEOUT, Connector $connector = null)
    {
        $this->connector = $connector ?? $this->createDefaultConnector();
        $this->connectionConfig = $config;
        $this->idleTimeout = $idleTimeout;
        if ($this->idleTimeout < 1) {
            throw new \Error("The idle timeout must be 1 or greater");
        }
        $this->maxConnections = $maxConnections;
        if ($this->maxConnections < 1) {
            throw new \Error("Pool must contain at least one connection");
        }
        $this->connections = $connections = new \SplObjectStorage();
        $this->idle = $idle = new \SplQueue();
        $idleTimeout =& $this->idleTimeout;
        $this->timeoutWatcher = Loop::repeat(1000, static function () use(&$idleTimeout, $connections, $idle) {
            $now = \time();
            while (!$idle->isEmpty()) {
                $connection = $idle->bottom();
                \assert($connection instanceof Link);
                if ($connection->getLastUsedAt() + $idleTimeout > $now) {
                    return;
                }
                // Close connection and remove it from the pool.
                $idle->shift();
                $connections->detach($connection);
                $connection->close();
            }
        });
        Loop::unreference($this->timeoutWatcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->timeoutWatcher);
    }
    /**
     *
     */
    public function getIdleTimeout() : int
    {
        return $this->idleTimeout;
    }
    /**
     *
     */
    public function getLastUsedAt() : int
    {
        // Simple implementation... can be improved if needed.
        $time = 0;
        foreach ($this->connections as $connection) {
            \assert($connection instanceof Link);
            if (($lastUsedAt = $connection->getLastUsedAt()) > $time) {
                $time = $lastUsedAt;
            }
        }
        return $time;
    }
    /**
     * @return bool
     */
    public function isAlive() : bool
    {
        return !$this->closed;
    }
    /**
     * Close all connections in the pool. No further queries may be made after a pool is closed.
     */
    public function close()
    {
        $this->closed = true;
        foreach ($this->connections as $connection) {
            $connection->close();
        }
        $this->idle = new \SplQueue();
        if ($this->deferred instanceof Deferred) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->fail(new FailureException("Connection pool closed"));
        }
    }
    /**
     * {@inheritdoc}
     */
    public function extractConnection() : Promise
    {
        return call(function () {
            $connection = (yield from $this->pop());
            $this->connections->detach($connection);
            return $connection;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function getConnectionCount() : int
    {
        return $this->connections->count();
    }
    /**
     * {@inheritdoc}
     */
    public function getIdleConnectionCount() : int
    {
        return $this->idle->count();
    }
    /**
     * {@inheritdoc}
     */
    public function getConnectionLimit() : int
    {
        return $this->maxConnections;
    }
    /**
     * @return \Generator
     *
     * @resolve Link
     *
     * @throws FailureException If creating a new connection fails.
     * @throws \Error If the pool has been closed.
     */
    protected function pop() : \Generator
    {
        if ($this->closed) {
            throw new \Error("The pool has been closed");
        }
        while ($this->promise !== null) {
            (yield $this->promise);
            // Prevent simultaneous connection creation or waiting.
        }
        do {
            // While loop to ensure an idle connection is available after promises below are resolved.
            while ($this->idle->isEmpty()) {
                if ($this->connections->count() < $this->getConnectionLimit()) {
                    // Max connection count has not been reached, so open another connection.
                    try {
                        $connection = (yield $this->promise = $this->connector->connect($this->connectionConfig));
                        if (!$connection instanceof Link) {
                            throw new \Error(\sprintf("%s::connect() must resolve to an instance of %s", \get_class($this->connector), Link::class));
                        }
                    } finally {
                        $this->promise = null;
                    }
                    $this->connections->attach($connection);
                    return $connection;
                }
                // All possible connections busy, so wait until one becomes available.
                try {
                    $this->deferred = new Deferred();
                    // Connection will be pulled from $this->idle when promise is resolved.
                    (yield $this->promise = $this->deferred->promise());
                } finally {
                    $this->deferred = null;
                    $this->promise = null;
                }
            }
            $connection = $this->idle->shift();
            \assert($connection instanceof Link);
            if ($connection->isAlive()) {
                return $connection;
            }
            $this->connections->detach($connection);
        } while (!$this->closed);
        throw new FailureException("Pool closed before an active connection could be obtained");
    }
    /**
     * @param Link $connection
     *
     * @throws \Error If the connection is not part of this pool.
     */
    protected function push(Link $connection)
    {
        \assert(isset($this->connections[$connection]), 'Connection is not part of this pool');
        if ($connection->isAlive()) {
            $this->idle->unshift($connection);
        } else {
            $this->connections->detach($connection);
        }
        if ($this->deferred instanceof Deferred) {
            $this->deferred->resolve($connection);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function query(string $sql) : Promise
    {
        return call(function () use($sql) {
            $connection = (yield from $this->pop());
            \assert($connection instanceof Link);
            try {
                $result = (yield $connection->query($sql));
            } catch (\Throwable $exception) {
                $this->push($connection);
                throw $exception;
            }
            if ($result instanceof ResultSet) {
                $result = $this->createResultSet($result, function () use($connection) {
                    $this->push($connection);
                });
            } else {
                $this->push($connection);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        return call(function () use($sql, $params) {
            $connection = (yield from $this->pop());
            \assert($connection instanceof Link);
            try {
                $result = (yield $connection->execute($sql, $params));
            } catch (\Throwable $exception) {
                $this->push($connection);
                throw $exception;
            }
            if ($result instanceof ResultSet) {
                $result = $this->createResultSet($result, function () use($connection) {
                    $this->push($connection);
                });
            } else {
                $this->push($connection);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     *
     * Prepared statements returned by this method will stay alive as long as the pool remains open.
     */
    public function prepare(string $sql) : Promise
    {
        return call(function () use($sql) {
            $statement = (yield from $this->prepareStatement($sql));
            return $this->createStatementPool($this, $statement, coroutine($this->callableFromInstanceMethod("prepareStatement")));
        });
    }
    /**
     * Prepares a new statement on an available connection.
     *
     * @param string $sql
     *
     * @return \Generator
     *
     * @throws FailureException
     */
    private function prepareStatement(string $sql) : \Generator
    {
        $connection = (yield from $this->pop());
        \assert($connection instanceof Link);
        try {
            $statement = (yield $connection->prepare($sql));
            \assert($statement instanceof Statement);
        } catch (\Throwable $exception) {
            $this->push($connection);
            throw $exception;
        }
        return $this->createStatement($statement, function () use($connection) {
            $this->push($connection);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function beginTransaction(int $isolation = Transaction::ISOLATION_COMMITTED) : Promise
    {
        return call(function () use($isolation) {
            $connection = (yield from $this->pop());
            \assert($connection instanceof Link);
            try {
                $transaction = (yield $connection->beginTransaction($isolation));
                \assert($transaction instanceof Transaction);
            } catch (\Throwable $exception) {
                $this->push($connection);
                throw $exception;
            }
            return $this->createTransaction($transaction, function () use($connection) {
                $this->push($connection);
            });
        });
    }
}<?php

namespace Amp\Sql\Common;

use Amp\Loop;
use Amp\Promise;
use Amp\Sql\Pool;
use Amp\Sql\ResultSet;
use Amp\Sql\Statement;
use function Amp\call;
abstract class StatementPool implements Statement
{
    /** @var \Amp\Sql\Pool */
    private $pool;
    /** @var \SplQueue */
    private $statements;
    /** @var string */
    private $sql;
    /** @var int */
    private $lastUsedAt;
    /** @var string */
    private $timeoutWatcher;
    /** @var callable */
    private $prepare;
    /**
    * Performs any necessary actions to the statement to prepare it for execution, returning a promise for the same or
    a new Statement object if necessary.
    *
    * @param Statement $statement
    *
    * @return Promise<Statement>
    */
    protected abstract function prepare(Statement $statement) : Promise;
    /**
     * @param ResultSet $resultSet
     * @param callable $release
     *
     * @return ResultSet
     */
    protected abstract function createResultSet(ResultSet $resultSet, callable $release) : ResultSet;
    /**
     * @param Pool $pool Pool used to re-create the statement if the original closes.
     * @param Statement $statement Original prepared statement returned from the Link.
     * @param callable $prepare Callable that returns a new prepared statement.
     */
    public function __construct(Pool $pool, Statement $statement, callable $prepare)
    {
        $this->lastUsedAt = \time();
        $this->statements = $statements = new \SplQueue();
        $this->pool = $pool;
        $this->prepare = $prepare;
        $this->sql = $statement->getQuery();
        $this->statements->push($statement);
        $this->timeoutWatcher = Loop::repeat(1000, static function () use($pool, $statements) {
            $now = \time();
            $idleTimeout = (int) ($pool->getIdleTimeout() / 10) ?: 1;
            while (!$statements->isEmpty()) {
                $statement = $statements->bottom();
                \assert($statement instanceof Statement);
                if ($statement->getLastUsedAt() + $idleTimeout > $now) {
                    return;
                }
                $statements->shift();
            }
        });
        Loop::unreference($this->timeoutWatcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->timeoutWatcher);
    }
    /**
     * {@inheritdoc}
     *
     * Unlike regular statements, as long as the pool is open this statement will not die.
     */
    public function execute(array $params = []) : Promise
    {
        $this->lastUsedAt = \time();
        return call(function () use($params) {
            $statement = (yield from $this->pop());
            \assert($statement instanceof Statement);
            try {
                $statement = (yield $this->prepare($statement));
                \assert($statement instanceof Statement);
                $result = (yield $statement->execute($params));
            } catch (\Throwable $exception) {
                $this->push($statement);
                throw $exception;
            }
            if ($result instanceof ResultSet) {
                $result = $this->createResultSet($result, function () use($statement) {
                    $this->push($statement);
                });
            } else {
                $this->push($statement);
            }
            return $result;
        });
    }
    /**
    * Only retains statements if less than 10% of the pool is consumed by this statement and the pool has
    available connections.
    *
    * @param Statement $statement
    */
    protected function push(Statement $statement)
    {
        $maxConnections = $this->pool->getConnectionLimit();
        if ($this->statements->count() > $maxConnections / 10) {
            return;
        }
        if ($maxConnections === $this->pool->getConnectionCount() && $this->pool->getIdleConnectionCount() === 0) {
            return;
        }
        $this->statements->unshift($statement);
    }
    /**
     * Coroutine returning a Statement object from the pool or creating a new Statement.
     *
     * @return \Generator
     */
    protected function pop() : \Generator
    {
        while (!$this->statements->isEmpty()) {
            $statement = $this->statements->shift();
            \assert($statement instanceof Statement);
            if ($statement->isAlive()) {
                return $statement;
            }
        }
        $statement = (yield ($this->prepare)($this->sql));
        \assert($statement instanceof Statement);
        return $statement;
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->pool->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public function getQuery() : string
    {
        return $this->sql;
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
}<?php

namespace Amp\Sql\Common;

use Amp\Promise;
use Amp\Sql\ResultSet;
use Amp\Sql\Statement;
use Amp\Sql\Transaction;
use Amp\Sql\TransactionError;
use function Amp\call;
abstract class PooledTransaction implements Transaction
{
    /** @var Transaction|null */
    private $transaction;
    /** @var callable|null */
    private $release;
    /** @var int */
    private $refCount = 1;
    /**
    * Creates a Statement of the appropriate type using the Statement object returned by the Transaction object and
    the given release callable.
    *
    * @param Statement $statement
    * @param callable $release
    *
    * @return Statement
    */
    protected abstract function createStatement(Statement $statement, callable $release) : Statement;
    /**
    * Creates a ResultSet of the appropriate type using the ResultSet object returned by the Transaction object and
    the given release callable.
    *
    * @param ResultSet $resultSet
    * @param callable $release
    *
    * @return ResultSet
    */
    protected abstract function createResultSet(ResultSet $resultSet, callable $release) : ResultSet;
    /**
     * @param Transaction $transaction Transaction object created by pooled connection.
     * @param callable $release Callable to be invoked when the transaction completes or is destroyed.
     */
    public function __construct(Transaction $transaction, callable $release)
    {
        $this->transaction = $transaction;
        $this->release = $release;
        if (!$this->transaction->isActive()) {
            $release();
            $this->transaction = null;
        } else {
            $refCount =& $this->refCount;
            $this->release = static function () use(&$refCount, $release) {
                if (--$refCount === 0) {
                    $release();
                }
            };
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->transaction && $this->transaction->isActive()) {
            $this->close();
            // Invokes $this->release callback.
        }
    }
    /**
     *
     */
    public function query(string $sql) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            $result = (yield $this->transaction->query($sql));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return $this->createResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     *
     */
    public function prepare(string $sql) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            $statement = (yield $this->transaction->prepare($sql));
            ++$this->refCount;
            return $this->createStatement($statement, $this->release);
        });
    }
    /**
     *
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql, $params) {
            $result = (yield $this->transaction->execute($sql, $params));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return $this->createResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return $this->transaction && $this->transaction->isAlive();
    }
    /**
     *
     */
    public function getLastUsedAt() : int
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->getLastUsedAt();
    }
    /**
     *
     */
    public function close()
    {
        if (!$this->transaction) {
            return;
        }
        $promise = $this->transaction->commit();
        $promise->onResolve($this->release);
        $this->transaction = null;
    }
    /**
     *
     */
    public function getIsolationLevel() : int
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->getIsolationLevel();
    }
    /**
     *
     */
    public function isActive() : bool
    {
        return $this->transaction && $this->transaction->isActive();
    }
    /**
     *
     */
    public function commit() : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->transaction->commit();
        $promise->onResolve($this->release);
        $this->transaction = null;
        return $promise;
    }
    /**
     *
     */
    public function rollback() : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->transaction->rollback();
        $promise->onResolve($this->release);
        $this->transaction = null;
        return $promise;
    }
    /**
     *
     */
    public function createSavepoint(string $identifier) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->createSavepoint($identifier);
    }
    /**
     *
     */
    public function rollbackTo(string $identifier) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->rollbackTo($identifier);
    }
    /**
     *
     */
    public function releaseSavepoint(string $identifier) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->releaseSavepoint($identifier);
    }
}<?php

namespace Amp\Sql\Common;

use Amp\Promise;
use Amp\Sql\ResultSet;
class PooledResultSet implements ResultSet
{
    /** @var ResultSet */
    private $result;
    /** @var callable */
    private $release;
    /**
     * @param ResultSet $result ResultSet object created by pooled connection or statement.
     * @param callable $release Callable to be invoked when the result set is destroyed.
     */
    public function __construct(ResultSet $result, callable $release)
    {
        $this->result = $result;
        $this->release = $release;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->release !== null) {
            ($this->release)();
        }
    }
    /**
     *
     */
    public function advance() : Promise
    {
        $promise = $this->result->advance();
        $promise->onResolve(function (\Throwable $exception = null, bool $moreResults = null) {
            if ($this->release === null) {
                return;
            }
            if ($exception || !$moreResults) {
                $release = $this->release;
                $this->release = null;
                $release();
            }
        });
        return $promise;
    }
    /**
     *
     */
    public function getCurrent() : array
    {
        return $this->result->getCurrent();
    }
}{
    "name": "amphp/sql-common",
    "description": "Common classes for non-blocking SQL implementations.",
    "keywords": [
        "database",
        "db",
        "sql",
        "asynchronous",
        "async"
    ],
    "homepage": "http://amphp.org",
    "license": "MIT",
    "require": {
        "php": ">=7",
        "amphp/amp": "^2",
        "amphp/sql": "^1"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master",
        "amphp/phpunit-util": "^1.3",
        "phpunit/phpunit": "^6 || ^7 || ^8 || ^9"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Sql\\Common\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Sql\\Common\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "phpunit --coverage-text"
    }
}
<?php

namespace Amp\Sql\Common\Test;

use Amp\Failure;
use Amp\PHPUnit\AsyncTestCase;
use Amp\Sql\Common\RetryConnector;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\ConnectionException;
use Amp\Sql\Connector;
use Amp\Sql\Link;
use Amp\Success;
class RetryConnectorTest extends AsyncTestCase
{
    /**
     *
     */
    public function testSuccessfulConnect() : \Generator
    {
        $connector = $this->createMock(Connector::class);
        $connector->expects($this->once())->method('connect')->willReturn(new Success($this->createMock(Link::class)));
        $retry = new RetryConnector($connector);
        $config = $this->getMockBuilder(ConnectionConfig::class)->setConstructorArgs(['localhost', 5432])->getMockForAbstractClass();
        $connection = (yield $retry->connect($config));
        $this->assertInstanceOf(Link::class, $connection);
    }
    /**
     *
     */
    public function testFirstTryFailConnect() : \Generator
    {
        $connector = $this->createMock(Connector::class);
        $connector->expects($this->exactly(2))->method('connect')->willReturnOnConsecutiveCalls(new Failure(new ConnectionException()), new Success($this->createMock(Link::class)));
        $retry = new RetryConnector($connector);
        $config = $this->getMockBuilder(ConnectionConfig::class)->setConstructorArgs(['localhost', 5432])->getMockForAbstractClass();
        $connection = (yield $retry->connect($config));
        $this->assertInstanceOf(Link::class, $connection);
    }
    /**
     *
     */
    public function testFailingConnect() : \Generator
    {
        $tries = 3;
        $connector = $this->createMock(Connector::class);
        $connector->expects($this->exactly($tries))->method('connect')->willReturn(new Failure(new ConnectionException()));
        $retry = new RetryConnector($connector, $tries);
        $config = $this->getMockBuilder(ConnectionConfig::class)->setConstructorArgs(['localhost', 5432])->getMockForAbstractClass();
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage('Could not connect to database server');
        $connection = (yield $retry->connect($config));
    }
}<?php

namespace Amp\Sql\Common\Test;

use Amp\PHPUnit\AsyncTestCase;
use Amp\Sql\Common\PooledResultSet;
use Amp\Sql\ResultSet;
use Amp\Success;
class PooledResultSetTest extends AsyncTestCase
{
    /**
     *
     */
    public function testIdleConnectionsRemovedAfterTimeout() : \Generator
    {
        $invoked = false;
        $release = function () use(&$invoked) {
            $invoked = true;
        };
        $result = $this->createMock(ResultSet::class);
        $result->method('advance')->willReturnOnConsecutiveCalls(new Success(true), new Success(false));
        $result = new PooledResultSet($result, $release);
        $this->assertTrue((yield $result->advance()));
        $this->assertFalse($invoked);
        $this->assertFalse((yield $result->advance()));
        $this->assertTrue($invoked);
    }
}<?php

namespace Amp\Sql\Common\Test;

use Amp\Delayed;
use Amp\PHPUnit\AsyncTestCase;
use Amp\Promise;
use Amp\Sql\CommandResult;
use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\Connector;
use Amp\Sql\Link;
use Amp\Success;
class ConnectionPoolTest extends AsyncTestCase
{
    /**
     *
     */
    public function testInvalidMaxConnections()
    {
        $this->expectException(\Error::class);
        $this->expectExceptionMessage('Pool must contain at least one connection');
        $this->getMockBuilder(ConnectionPool::class)->setConstructorArgs([$this->createMock(ConnectionConfig::class), 0])->getMock();
    }
    /**
     *
     */
    private function createConnector() : Connector
    {
        $now = \time();
        $connector = $this->createMock(Connector::class);
        $connector->method('connect')->willReturnCallback(function () use($now) : Promise {
            $link = $this->createMock(Link::class);
            $link->method('getLastUsedAt')->willReturn($now);
            $link->method('isAlive')->willReturn(true);
            $link->method('query')->willReturnCallback(function () {
                return new Delayed(100, $this->createMock(CommandResult::class));
            });
            return new Success($link);
        });
        return $connector;
    }
    /**
     *
     */
    private function createPool(Connector $connector, int $maxConnections = 100, int $idleTimeout = 10) : ConnectionPool
    {
        return $this->getMockBuilder(ConnectionPool::class)->setConstructorArgs([$this->createMock(ConnectionConfig::class), $maxConnections, $idleTimeout, $connector])->getMockForAbstractClass();
    }
    /**
     *
     */
    public function testIdleConnectionsRemovedAfterTimeout() : \Generator
    {
        $connector = $this->createConnector();
        $pool = $this->createPool($connector, 10, 2);
        $count = 3;
        $promises = [];
        for ($i = 0; $i < $count; ++$i) {
            $promises[] = $pool->query("SELECT {$i}");
        }
        $this->assertCount($count, (yield $promises));
        $this->assertSame($count, $pool->getConnectionCount());
        (yield new Delayed(1000));
        $this->assertSame($count, $pool->getConnectionCount());
        (yield new Delayed(1000));
        $this->assertSame(0, $pool->getConnectionCount());
    }
    /**
     *
     */
    public function testMaxConnectionCount() : \Generator
    {
        $connector = $this->createConnector();
        $pool = $this->createPool($connector, $maxConnections = 3);
        $count = 10;
        $promises = [];
        for ($i = 0; $i < $count; ++$i) {
            $promises[] = $pool->query("SELECT {$i}");
        }
        $this->assertSame($maxConnections, $pool->getConnectionCount());
        $expectedRuntime = 100 * \ceil($count / $maxConnections);
        $this->setMinimumRuntime($expectedRuntime);
        $this->setTimeout($expectedRuntime + 100);
        $this->assertCount($count, (yield $promises));
    }
}<?php

namespace Amp\Sql\Common\Test;

use Amp\Delayed;
use Amp\PHPUnit\AsyncTestCase;
use Amp\Sql\Common\StatementPool;
use Amp\Sql\Pool;
use Amp\Sql\Statement;
use Amp\Success;
class StatementPoolTest extends AsyncTestCase
{
    /**
     *
     */
    public function testActiveStatementsRemainAfterTimeout() : \Generator
    {
        $pool = $this->createMock(Pool::class);
        $pool->method('isAlive')->willReturn(true);
        $pool->method('getIdleTimeout')->willReturn(60);
        $statement = $this->createMock(Statement::class);
        $statement->method('isAlive')->willReturn(true);
        $statement->method('getQuery')->willReturn('SELECT 1');
        $statement->method('getLastUsedAt')->willReturn(\time());
        $statement->expects($this->once())->method('execute');
        /** @var StatementPool $statementPool */
        $statementPool = $this->getMockBuilder(StatementPool::class)->setConstructorArgs([$pool, $statement, $this->createCallback(0)])->getMockForAbstractClass();
        $statementPool->method('prepare')->willReturnCallback(function (Statement $statement) {
            return new Success($statement);
        });
        $this->assertTrue($statementPool->isAlive());
        $this->assertSame(\time(), $statementPool->getLastUsedAt());
        (yield new Delayed(1500));
        // Give timeout watcher enough time to execute.
        $statementPool->execute();
        $this->assertTrue($statementPool->isAlive());
        $this->assertSame(\time(), $statementPool->getLastUsedAt());
    }
    /**
     *
     */
    public function testIdleStatementsRemovedAfterTimeout() : \Generator
    {
        $pool = $this->createMock(Pool::class);
        $pool->method('isAlive')->willReturn(true);
        $pool->method('getIdleTimeout')->willReturn(1);
        $statement = $this->createMock(Statement::class);
        $statement->method('isAlive')->willReturn(true);
        $statement->method('getQuery')->willReturn('SELECT 1');
        $statement->method('getLastUsedAt')->willReturn(\time());
        $statement->expects($this->once())->method('execute');
        /** @var StatementPool $statementPool */
        $statementPool = $this->getMockBuilder(StatementPool::class)->setConstructorArgs([$pool, $statement, $this->createCallback(1)])->getMockForAbstractClass();
        $statementPool->method('prepare')->willReturnCallback(function (Statement $statement) {
            return new Success($statement);
        });
        $this->assertTrue($statementPool->isAlive());
        $this->assertSame(\time(), $statementPool->getLastUsedAt());
        $statementPool->execute();
        (yield new Delayed(1500));
        // Give timeout watcher enough time to execute.
        $statementPool->execute();
        $this->assertTrue($statementPool->isAlive());
        $this->assertSame(\time(), $statementPool->getLastUsedAt());
    }
}{
    "name": "amphp/parser",
    "homepage": "https://github.com/amphp/parser",
    "description": "A generator parser to make streaming parsers simple.",
    "support": {
        "issues": "https://github.com/amphp/parser/issues"
    },
    "keywords": [
        "stream",
        "async",
        "non-blocking",
        "parser"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7"
    },
    "require-dev": {
        "phpunit/phpunit": "^6",
        "friendsofphp/php-cs-fixer": "^2.3"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Parser\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Parser\\Test\\": "test"
        }
    }
}
<?php

namespace Amp\Parser;

class InvalidDelimiterError extends \Error
{
    /**
     * @param \Generator $generator
     * @param string $prefix
     * @param (\Throwable | null) $previous
     */
    public function __construct(\Generator $generator, string $prefix, \Throwable $previous = null)
    {
        $yielded = $generator->current();
        $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), \var_export($generator->key(), true));
        if (!$generator->valid()) {
            parent::__construct($prefix, 0, $previous);
            return;
        }
        $reflGen = new \ReflectionGenerator($generator);
        $exeGen = $reflGen->getExecutingGenerator();
        if ($isSubgenerator = $exeGen !== $generator) {
            $reflGen = new \ReflectionGenerator($exeGen);
        }
        parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile()), 0, $previous);
    }
}<?php

namespace Amp\Parser;

class Parser
{
    /** @var \Generator */
    private $generator;
    /** @var string */
    private $buffer = '';
    /** @var int|string|null */
    private $delimiter;
    /**
     * @param \Generator $generator
     *
     * @throws InvalidDelimiterError If the generator yields an invalid delimiter.
     * @throws \Throwable If the generator throws.
     */
    public function __construct(\Generator $generator)
    {
        $this->generator = $generator;
        $this->delimiter = $this->generator->current();
        if (!$this->generator->valid()) {
            $this->generator = null;
            return;
        }
        if ($this->delimiter !== null && (!\is_int($this->delimiter) || $this->delimiter <= 0) && (!\is_string($this->delimiter) || !\strlen($this->delimiter))) {
            throw new InvalidDelimiterError($generator, \sprintf("Invalid value yielded: Expected NULL, an int greater than 0, or a non-empty string; %s given", \is_object($this->delimiter) ? \sprintf("instance of %s", \get_class($this->delimiter)) : \gettype($this->delimiter)));
        }
    }
    /**
    * Cancels the generator parser and returns any remaining data in the internal buffer. Writing data after calling
    this method will result in an error.
    *
    * @return string
    */
    public final function cancel() : string
    {
        $this->generator = null;
        return $this->buffer;
    }
    /**
    * @return bool True if the parser can still receive more data to parse, false if it has ended and calling push
    will throw an exception.
    */
    public final function isValid() : bool
    {
        return $this->generator !== null;
    }
    /**
     * Adds data to the internal buffer and tries to continue parsing.
     *
     * @param string $data Data to append to the internal buffer.
     *
     * @throws InvalidDelimiterError If the generator yields an invalid delimiter.
     * @throws \Error If parsing has already been cancelled.
     * @throws \Throwable If the generator throws.
     */
    public final function push(string $data)
    {
        if ($this->generator === null) {
            throw new \Error("The parser is no longer writable");
        }
        $this->buffer .= $data;
        $end = false;
        try {
            while ($this->buffer !== "") {
                if (\is_int($this->delimiter)) {
                    if (\strlen($this->buffer) < $this->delimiter) {
                        break;
                        // Too few bytes in buffer.
                    }
                    $send = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $this->delimiter);
                    $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->delimiter);
                } elseif (\is_string($this->delimiter)) {
                    if (($position = \strpos($this->buffer, $this->delimiter)) === false) {
                        break;
                    }
                    $send = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $position);
                    $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $position + \strlen($this->delimiter));
                } else {
                    $send = $this->buffer;
                    $this->buffer = "";
                }
                $this->delimiter = $this->generator->send($send);
                if (!$this->generator->valid()) {
                    $end = true;
                    break;
                }
                if ($this->delimiter !== null && (!\is_int($this->delimiter) || $this->delimiter <= 0) && (!\is_string($this->delimiter) || !\strlen($this->delimiter))) {
                    throw new InvalidDelimiterError($this->generator, \sprintf("Invalid value yielded: Expected NULL, an int greater than 0, or a non-empty string; %s given", \is_object($this->delimiter) ? \sprintf("instance of %s", \get_class($this->delimiter)) : \gettype($this->delimiter)));
                }
            }
        } catch (\Throwable $exception) {
            $end = true;
            throw $exception;
        } finally {
            if ($end) {
                $this->generator = null;
            }
        }
    }
}<?php

namespace Amp\Http\Internal;

use Amp\Http\HPackException;
/** @internal */
final class HPackNative
{
    private const HUFFMAN_CODE = [
        /* 0x00 */
        0x1ff8,
        0x7fffd8,
        0xfffffe2,
        0xfffffe3,
        0xfffffe4,
        0xfffffe5,
        0xfffffe6,
        0xfffffe7,
        /* 0x08 */
        0xfffffe8,
        0xffffea,
        0x3ffffffc,
        0xfffffe9,
        0xfffffea,
        0x3ffffffd,
        0xfffffeb,
        0xfffffec,
        /* 0x10 */
        0xfffffed,
        0xfffffee,
        0xfffffef,
        0xffffff0,
        0xffffff1,
        0xffffff2,
        0x3ffffffe,
        0xffffff3,
        /* 0x18 */
        0xffffff4,
        0xffffff5,
        0xffffff6,
        0xffffff7,
        0xffffff8,
        0xffffff9,
        0xffffffa,
        0xffffffb,
        /* 0x20 */
        0x14,
        0x3f8,
        0x3f9,
        0xffa,
        0x1ff9,
        0x15,
        0xf8,
        0x7fa,
        /* 0x28 */
        0x3fa,
        0x3fb,
        0xf9,
        0x7fb,
        0xfa,
        0x16,
        0x17,
        0x18,
        /* 0x30 */
        0x0,
        0x1,
        0x2,
        0x19,
        0x1a,
        0x1b,
        0x1c,
        0x1d,
        /* 0x38 */
        0x1e,
        0x1f,
        0x5c,
        0xfb,
        0x7ffc,
        0x20,
        0xffb,
        0x3fc,
        /* 0x40 */
        0x1ffa,
        0x21,
        0x5d,
        0x5e,
        0x5f,
        0x60,
        0x61,
        0x62,
        /* 0x48 */
        0x63,
        0x64,
        0x65,
        0x66,
        0x67,
        0x68,
        0x69,
        0x6a,
        /* 0x50 */
        0x6b,
        0x6c,
        0x6d,
        0x6e,
        0x6f,
        0x70,
        0x71,
        0x72,
        /* 0x58 */
        0xfc,
        0x73,
        0xfd,
        0x1ffb,
        0x7fff0,
        0x1ffc,
        0x3ffc,
        0x22,
        /* 0x60 */
        0x7ffd,
        0x3,
        0x23,
        0x4,
        0x24,
        0x5,
        0x25,
        0x26,
        /* 0x68 */
        0x27,
        0x6,
        0x74,
        0x75,
        0x28,
        0x29,
        0x2a,
        0x7,
        /* 0x70 */
        0x2b,
        0x76,
        0x2c,
        0x8,
        0x9,
        0x2d,
        0x77,
        0x78,
        /* 0x78 */
        0x79,
        0x7a,
        0x7b,
        0x7ffe,
        0x7fc,
        0x3ffd,
        0x1ffd,
        0xffffffc,
        /* 0x80 */
        0xfffe6,
        0x3fffd2,
        0xfffe7,
        0xfffe8,
        0x3fffd3,
        0x3fffd4,
        0x3fffd5,
        0x7fffd9,
        /* 0x88 */
        0x3fffd6,
        0x7fffda,
        0x7fffdb,
        0x7fffdc,
        0x7fffdd,
        0x7fffde,
        0xffffeb,
        0x7fffdf,
        /* 0x90 */
        0xffffec,
        0xffffed,
        0x3fffd7,
        0x7fffe0,
        0xffffee,
        0x7fffe1,
        0x7fffe2,
        0x7fffe3,
        /* 0x98 */
        0x7fffe4,
        0x1fffdc,
        0x3fffd8,
        0x7fffe5,
        0x3fffd9,
        0x7fffe6,
        0x7fffe7,
        0xffffef,
        /* 0xA0 */
        0x3fffda,
        0x1fffdd,
        0xfffe9,
        0x3fffdb,
        0x3fffdc,
        0x7fffe8,
        0x7fffe9,
        0x1fffde,
        /* 0xA8 */
        0x7fffea,
        0x3fffdd,
        0x3fffde,
        0xfffff0,
        0x1fffdf,
        0x3fffdf,
        0x7fffeb,
        0x7fffec,
        /* 0xB0 */
        0x1fffe0,
        0x1fffe1,
        0x3fffe0,
        0x1fffe2,
        0x7fffed,
        0x3fffe1,
        0x7fffee,
        0x7fffef,
        /* 0xB8 */
        0xfffea,
        0x3fffe2,
        0x3fffe3,
        0x3fffe4,
        0x7ffff0,
        0x3fffe5,
        0x3fffe6,
        0x7ffff1,
        /* 0xC0 */
        0x3ffffe0,
        0x3ffffe1,
        0xfffeb,
        0x7fff1,
        0x3fffe7,
        0x7ffff2,
        0x3fffe8,
        0x1ffffec,
        /* 0xC8 */
        0x3ffffe2,
        0x3ffffe3,
        0x3ffffe4,
        0x7ffffde,
        0x7ffffdf,
        0x3ffffe5,
        0xfffff1,
        0x1ffffed,
        /* 0xD0 */
        0x7fff2,
        0x1fffe3,
        0x3ffffe6,
        0x7ffffe0,
        0x7ffffe1,
        0x3ffffe7,
        0x7ffffe2,
        0xfffff2,
        /* 0xD8 */
        0x1fffe4,
        0x1fffe5,
        0x3ffffe8,
        0x3ffffe9,
        0xffffffd,
        0x7ffffe3,
        0x7ffffe4,
        0x7ffffe5,
        /* 0xE0 */
        0xfffec,
        0xfffff3,
        0xfffed,
        0x1fffe6,
        0x3fffe9,
        0x1fffe7,
        0x1fffe8,
        0x7ffff3,
        /* 0xE8 */
        0x3fffea,
        0x3fffeb,
        0x1ffffee,
        0x1ffffef,
        0xfffff4,
        0xfffff5,
        0x3ffffea,
        0x7ffff4,
        /* 0xF0 */
        0x3ffffeb,
        0x7ffffe6,
        0x3ffffec,
        0x3ffffed,
        0x7ffffe7,
        0x7ffffe8,
        0x7ffffe9,
        0x7ffffea,
        /* 0xF8 */
        0x7ffffeb,
        0xffffffe,
        0x7ffffec,
        0x7ffffed,
        0x7ffffee,
        0x7ffffef,
        0x7fffff0,
        0x3ffffee,
        /* end! */
        0x3fffffff,
    ];
    private const HUFFMAN_CODE_LENGTHS = [
        /* 0x00 */
        13,
        23,
        28,
        28,
        28,
        28,
        28,
        28,
        /* 0x08 */
        28,
        24,
        30,
        28,
        28,
        30,
        28,
        28,
        /* 0x10 */
        28,
        28,
        28,
        28,
        28,
        28,
        30,
        28,
        /* 0x18 */
        28,
        28,
        28,
        28,
        28,
        28,
        28,
        28,
        /* 0x20 */
        6,
        10,
        10,
        12,
        13,
        6,
        8,
        11,
        /* 0x28 */
        10,
        10,
        8,
        11,
        8,
        6,
        6,
        6,
        /* 0x30 */
        5,
        5,
        5,
        6,
        6,
        6,
        6,
        6,
        /* 0x38 */
        6,
        6,
        7,
        8,
        15,
        6,
        12,
        10,
        /* 0x40 */
        13,
        6,
        7,
        7,
        7,
        7,
        7,
        7,
        /* 0x48 */
        7,
        7,
        7,
        7,
        7,
        7,
        7,
        7,
        /* 0x50 */
        7,
        7,
        7,
        7,
        7,
        7,
        7,
        7,
        /* 0x58 */
        8,
        7,
        8,
        13,
        19,
        13,
        14,
        6,
        /* 0x60 */
        15,
        5,
        6,
        5,
        6,
        5,
        6,
        6,
        /* 0x68 */
        6,
        5,
        7,
        7,
        6,
        6,
        6,
        5,
        /* 0x70 */
        6,
        7,
        6,
        5,
        5,
        6,
        7,
        7,
        /* 0x78 */
        7,
        7,
        7,
        15,
        11,
        14,
        13,
        28,
        /* 0x80 */
        20,
        22,
        20,
        20,
        22,
        22,
        22,
        23,
        /* 0x88 */
        22,
        23,
        23,
        23,
        23,
        23,
        24,
        23,
        /* 0x90 */
        24,
        24,
        22,
        23,
        24,
        23,
        23,
        23,
        /* 0x98 */
        23,
        21,
        22,
        23,
        22,
        23,
        23,
        24,
        /* 0xA0 */
        22,
        21,
        20,
        22,
        22,
        23,
        23,
        21,
        /* 0xA8 */
        23,
        22,
        22,
        24,
        21,
        22,
        23,
        23,
        /* 0xB0 */
        21,
        21,
        22,
        21,
        23,
        22,
        23,
        23,
        /* 0xB8 */
        20,
        22,
        22,
        22,
        23,
        22,
        22,
        23,
        /* 0xC0 */
        26,
        26,
        20,
        19,
        22,
        23,
        22,
        25,
        /* 0xC8 */
        26,
        26,
        26,
        27,
        27,
        26,
        24,
        25,
        /* 0xD0 */
        19,
        21,
        26,
        27,
        27,
        26,
        27,
        24,
        /* 0xD8 */
        21,
        21,
        26,
        26,
        28,
        27,
        27,
        27,
        /* 0xE0 */
        20,
        24,
        20,
        21,
        22,
        21,
        21,
        23,
        /* 0xE8 */
        22,
        22,
        25,
        25,
        24,
        24,
        26,
        23,
        /* 0xF0 */
        26,
        27,
        26,
        26,
        27,
        27,
        27,
        27,
        /* 0xF8 */
        27,
        28,
        27,
        27,
        27,
        27,
        27,
        26,
        /* end! */
        30,
    ];
    private const DEFAULT_COMPRESSION_THRESHOLD = 1024;
    private const DEFAULT_MAX_SIZE = 4096;
    private static $huffmanLookup;
    private static $huffmanCodes;
    private static $huffmanLengths;
    private static $indexMap = [];
    /** @var string[][] */
    private $headers = [];
    /** @var int */
    private $hardMaxSize = self::DEFAULT_MAX_SIZE;
    /** @var int Max table size. */
    private $currentMaxSize = self::DEFAULT_MAX_SIZE;
    /** @var int Current table size. */
    private $size = 0;
    /**
     * Called via bindTo(), see end of file
     */
    private static function init()
    {
        self::$huffmanLookup = self::huffmanLookupInit();
        self::$huffmanCodes = self::huffmanCodesInit();
        self::$huffmanLengths = self::huffmanLengthsInit();
        foreach (\array_column(self::TABLE, 0) as $index => $name) {
            if (isset(self::$indexMap[$name])) {
                continue;
            }
            self::$indexMap[$name] = $index + 1;
        }
    }
    // (micro-)optimized decode
    /**
     *
     */
    private static function huffmanLookupInit() : array
    {
        if ('cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI || \filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
            return require __DIR__ . '/huffman-lookup.php';
        }
        \gc_disable();
        $encodingAccess = [];
        $terminals = [];
        $index = 7;
        foreach (self::HUFFMAN_CODE as $chr => $bits) {
            $len = self::HUFFMAN_CODE_LENGTHS[$chr];
            for ($bit = 0; $bit < 8; $bit++) {
                $offlen = $len + $bit;
                $next = $bit;
                for ($byte = $offlen - 1 >> 3; $byte > 0; $byte--) {
                    $cur = \str_pad(\decbin($bits >> $byte * 8 - (0x30 - $offlen & 7) & 0xff), 8, "0", STR_PAD_LEFT);
                    if (($encodingAccess[$next][$cur][0] ?? 0) !== 0) {
                        $next = $encodingAccess[$next][$cur][0];
                    } else {
                        $encodingAccess[$next][$cur] = [++$index, null];
                        $next = $index;
                    }
                }
                $key = \str_pad(\decbin($bits & (1 << ($offlen - 1 & 7) + 1) - 1), ($offlen - 1 & 7) + 1, "0", STR_PAD_LEFT);
                $encodingAccess[$next][$key] = [null, $chr > 0xff ? "" : \chr($chr)];
                if ($offlen & 7) {
                    $terminals[$offlen & 7][] = [$key, $next];
                } else {
                    $encodingAccess[$next][$key][0] = 0;
                }
            }
        }
        $memoize = [];
        for ($off = 7; $off > 0; $off--) {
            foreach ($terminals[$off] as [$key, $next]) {
                if ($encodingAccess[$next][$key][0] === null) {
                    foreach ($encodingAccess[$off] as $chr => $cur) {
                        $encodingAccess[$next][($memoize[$key] ?? ($memoize[$key] = \str_pad($key, 8, "0", STR_PAD_RIGHT))) | $chr] = [$cur[0], $encodingAccess[$next][$key][1] != "" ? $encodingAccess[$next][$key][1] . $cur[1] : ""];
                    }
                    unset($encodingAccess[$next][$key]);
                }
            }
        }
        $memoize = [];
        for ($off = 7; $off > 0; $off--) {
            foreach ($terminals[$off] as [$key, $next]) {
                foreach ($encodingAccess[$next] as $k => $v) {
                    if (\strlen($k) !== 1) {
                        $encodingAccess[$next][$memoize[$k] ?? ($memoize[$k] = \chr(\bindec($k)))] = $v;
                        unset($encodingAccess[$next][$k]);
                    }
                }
            }
            unset($encodingAccess[$off]);
        }
        \gc_enable();
        return $encodingAccess;
    }
    /**
     * @param string $input
     *
     * @return (string | null) Returns null if decoding fails.
     */
    public static function huffmanDecode(string $input)
    {
        $huffmanLookup = self::$huffmanLookup;
        $lookup = 0;
        $lengths = self::$huffmanLengths;
        $length = \strlen($input);
        $out = \str_repeat("\x00", (int) \floor($length / 5 * 8 + 1));
        // max length
        // Fail if EOS symbol is found.
        if (\strpos($input, "?\xff\xff\xff") !== false) {
            return null;
        }
        for ($bitCount = $off = $i = 0; $i < $length; $i++) {
            [$lookup, $chr] = $huffmanLookup[$lookup][$input[$i]];
            if ($chr === null) {
                continue;
            }
            if ($chr === "") {
                return null;
            }
            $out[$off++] = $chr[0];
            $bitCount += $lengths[$chr[0]];
            if (isset($chr[1])) {
                $out[$off++] = $chr[1];
                $bitCount += $lengths[$chr[1]];
            }
        }
        // Padding longer than 7-bits
        if ($i && $chr === null) {
            return null;
        }
        // Check for 0's in padding
        if ($bitCount & 7) {
            $mask = 0xff >> ($bitCount & 7);
            if ((\ord($input[$i - 1]) & $mask) !== $mask) {
                return null;
            }
        }
        return \Phabel\Target\Php80\Polyfill::substr($out, 0, $off);
    }
    /**
     *
     */
    private static function huffmanCodesInit() : array
    {
        if ('cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI || \filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
            return require __DIR__ . '/huffman-codes.php';
        }
        $lookup = [];
        for ($chr = 0; $chr <= 0xff; $chr++) {
            $bits = self::HUFFMAN_CODE[$chr];
            $length = self::HUFFMAN_CODE_LENGTHS[$chr];
            for ($bit = 0; $bit < 8; $bit++) {
                $bytes = $length + $bit - 1 >> 3;
                $codes = [];
                for ($byte = $bytes; $byte >= 0; $byte--) {
                    $codes[] = \chr($byte ? $bits >> $length - ($bytes - $byte + 1) * 8 + $bit : $bits << (0x30 - $length - $bit & 7));
                }
                $lookup[$bit][\chr($chr)] = $codes;
            }
        }
        return $lookup;
    }
    /**
     *
     */
    private static function huffmanLengthsInit() : array
    {
        $lengths = [];
        for ($chr = 0; $chr <= 0xff; $chr++) {
            $lengths[\chr($chr)] = self::HUFFMAN_CODE_LENGTHS[$chr];
        }
        return $lengths;
    }
    /**
     *
     */
    public static function huffmanEncode(string $input) : string
    {
        $codes = self::$huffmanCodes;
        $lengths = self::$huffmanLengths;
        $length = \strlen($input);
        $out = \str_repeat("\x00", $length * 5 + 1);
        // max length
        for ($bitCount = $i = 0; $i < $length; $i++) {
            $chr = $input[$i];
            $byte = $bitCount >> 3;
            foreach ($codes[$bitCount & 7][$chr] as $bits) {
                // Note: |= can't be used with strings in PHP
                $out[$byte] = $out[$byte] | $bits;
                $byte++;
            }
            $bitCount += $lengths[$chr];
        }
        if ($bitCount & 7) {
            // Note: |= can't be used with strings in PHP
            $out[$byte - 1] = $out[$byte - 1] | \chr(0xff >> ($bitCount & 7));
        }
        return $i ? \Phabel\Target\Php80\Polyfill::substr($out, 0, $byte) : '';
    }
    /** @see RFC 7541 Appendix A */
    const LAST_INDEX = 61;
    const TABLE = [
        // starts at 1
        [":authority", ""],
        [":method", "GET"],
        [":method", "POST"],
        [":path", "/"],
        [":path", "/index.html"],
        [":scheme", "http"],
        [":scheme", "https"],
        [":status", "200"],
        [":status", "204"],
        [":status", "206"],
        [":status", "304"],
        [":status", "400"],
        [":status", "404"],
        [":status", "500"],
        ["accept-charset", ""],
        ["accept-encoding", "gzip, deflate"],
        ["accept-language", ""],
        ["accept-ranges", ""],
        ["accept", ""],
        ["access-control-allow-origin", ""],
        ["age", ""],
        ["allow", ""],
        ["authorization", ""],
        ["cache-control", ""],
        ["content-disposition", ""],
        ["content-encoding", ""],
        ["content-language", ""],
        ["content-length", ""],
        ["content-location", ""],
        ["content-range", ""],
        ["content-type", ""],
        ["cookie", ""],
        ["date", ""],
        ["etag", ""],
        ["expect", ""],
        ["expires", ""],
        ["from", ""],
        ["host", ""],
        ["if-match", ""],
        ["if-modified-since", ""],
        ["if-none-match", ""],
        ["if-range", ""],
        ["if-unmodified-since", ""],
        ["last-modified", ""],
        ["link", ""],
        ["location", ""],
        ["max-forwards", ""],
        ["proxy-authentication", ""],
        ["proxy-authorization", ""],
        ["range", ""],
        ["referer", ""],
        ["refresh", ""],
        ["retry-after", ""],
        ["server", ""],
        ["set-cookie", ""],
        ["strict-transport-security", ""],
        ["transfer-encoding", ""],
        ["user-agent", ""],
        ["vary", ""],
        ["via", ""],
        ["www-authenticate", ""],
    ];
    /**
     *
     */
    private static function decodeDynamicInteger(string $input, int &$off) : int
    {
        if (!isset($input[$off])) {
            throw new HPackException('Invalid input data, too short for dynamic integer');
        }
        $c = \ord($input[$off++]);
        $int = $c & 0x7f;
        $i = 0;
        while ($c & 0x80) {
            if (!isset($input[$off])) {
                return -0x80;
            }
            $c = \ord($input[$off++]);
            $int += ($c & 0x7f) << ++$i * 7;
        }
        return $int;
    }
    /**
     * @param int $maxSize Upper limit on table size.
     */
    public function __construct(int $maxSize = self::DEFAULT_MAX_SIZE)
    {
        $this->hardMaxSize = $maxSize;
    }
    /**
    * Sets the upper limit on table size. Dynamic table updates requesting a size above this size will result in a
    decoding error (i.e., returning null from decode()).
    *
    * @param int $maxSize
    */
    public function setTableSizeLimit(int $maxSize)
    {
        $this->hardMaxSize = $maxSize;
    }
    /**
     * Resizes the table to the given size, removing old entries as per section 4.4 if necessary.
     *
     * @param (int | null) $size
     */
    public function resizeTable(int $size = null)
    {
        if ($size !== null) {
            $this->currentMaxSize = \max(0, \min($size, $this->hardMaxSize));
        }
        while ($this->size > $this->currentMaxSize) {
            [$name, $value] = \array_pop($this->headers);
            $this->size -= 32 + \strlen($name) + \strlen($value);
        }
    }
    /**
     * @param string $input Encoded headers.
     * @param int $maxSize Maximum length of the decoded header string.
     *
     * @return (string[][] | null) Returns null if decoding fails or if $maxSize is exceeded.
     */
    public function decode(string $input, int $maxSize)
    {
        $headers = [];
        $off = 0;
        $inputLength = \strlen($input);
        $size = 0;
        try {
            // dynamic $table as per 2.3.2
            while ($off < $inputLength) {
                $index = \ord($input[$off++]);
                if ($index & 0x80) {
                    // range check
                    if ($index <= self::LAST_INDEX + 0x80) {
                        if ($index === 0x80) {
                            return null;
                        }
                        [$name, $value] = $headers[] = self::TABLE[$index - 0x81];
                    } else {
                        if ($index == 0xff) {
                            $index = self::decodeDynamicInteger($input, $off) + 0xff;
                        }
                        $index -= 0x81 + self::LAST_INDEX;
                        if (!isset($this->headers[$index])) {
                            return null;
                        }
                        [$name, $value] = $headers[] = $this->headers[$index];
                    }
                } elseif (($index & 0x60) !== 0x20) {
                    // (($index & 0x40) || !($index & 0x20)): bit 4: never index is ignored
                    $dynamic = (bool) ($index & 0x40);
                    if ($index & ($dynamic ? 0x3f : 0xf)) {
                        // separate length
                        if ($dynamic) {
                            if ($index === 0x7f) {
                                $index = self::decodeDynamicInteger($input, $off) + 0x3f;
                            } else {
                                $index &= 0x3f;
                            }
                        } else {
                            $index &= 0xf;
                            if ($index === 0xf) {
                                $index = self::decodeDynamicInteger($input, $off) + 0xf;
                            }
                        }
                        if ($index < 0) {
                            return null;
                        }
                        if ($index <= self::LAST_INDEX) {
                            $header = self::TABLE[$index - 1];
                        } elseif (!isset($this->headers[$index - 1 - self::LAST_INDEX])) {
                            return null;
                        } else {
                            $header = $this->headers[$index - 1 - self::LAST_INDEX];
                        }
                    } else {
                        if ($off >= $inputLength) {
                            return null;
                        }
                        $length = \ord($input[$off++]);
                        $huffman = $length & 0x80;
                        $length &= 0x7f;
                        if ($length === 0x7f) {
                            $length = self::decodeDynamicInteger($input, $off) + 0x7f;
                        }
                        if ($inputLength - $off < $length || $length <= 0) {
                            return null;
                        }
                        if ($huffman) {
                            $header = [self::huffmanDecode(\Phabel\Target\Php80\Polyfill::substr($input, $off, $length))];
                            if ($header[0] === null) {
                                return null;
                            }
                        } else {
                            $header = [\Phabel\Target\Php80\Polyfill::substr($input, $off, $length)];
                        }
                        $off += $length;
                    }
                    if ($off >= $inputLength) {
                        return null;
                    }
                    $length = \ord($input[$off++]);
                    $huffman = $length & 0x80;
                    $length &= 0x7f;
                    if ($length === 0x7f) {
                        $length = self::decodeDynamicInteger($input, $off) + 0x7f;
                    }
                    if ($inputLength - $off < $length || $length < 0) {
                        return null;
                    }
                    if ($huffman) {
                        $header[1] = self::huffmanDecode(\Phabel\Target\Php80\Polyfill::substr($input, $off, $length));
                        if ($header[1] === null) {
                            return null;
                        }
                    } else {
                        $header[1] = \Phabel\Target\Php80\Polyfill::substr($input, $off, $length);
                    }
                    $off += $length;
                    if ($dynamic) {
                        \array_unshift($this->headers, $header);
                        $this->size += 32 + \strlen($header[0]) + \strlen($header[1]);
                        if ($this->currentMaxSize < $this->size) {
                            $this->resizeTable();
                        }
                    }
                    [$name, $value] = $headers[] = $header;
                } else {
                    // if ($index & 0x20) {
                    if ($off >= $inputLength) {
                        return null;
                        // Dynamic table size update must not be the last entry in header block.
                    }
                    $index &= 0x1f;
                    if ($index === 0x1f) {
                        $index = self::decodeDynamicInteger($input, $off) + 0x1f;
                    }
                    if ($index > $this->hardMaxSize) {
                        return null;
                    }
                    $this->resizeTable($index);
                    continue;
                }
                $size += \strlen($name) + \strlen($value);
                if ($size > $maxSize) {
                    return null;
                }
            }
        } catch (HPackException $e) {
            return null;
        }
        return $headers;
    }
    /**
     *
     */
    private static function encodeDynamicInteger(int $int) : string
    {
        $out = "";
        for ($i = 0; $int >> $i > 0x80; $i += 7) {
            $out .= \chr(0x80 | $int >> $i & 0x7f);
        }
        return $out . \chr($int >> $i);
    }
    /**
     * @param string[][] $headers
     * @param int $compressionThreshold Compress strings whose length is at least the number of bytes given.
     *
     * @return string
     */
    public function encode(array $headers, int $compressionThreshold = self::DEFAULT_COMPRESSION_THRESHOLD) : string
    {
        // @TODO implementation is deliberately primitive... [doesn't use any dynamic table...]
        $output = "";
        foreach ($headers as [$name, $value]) {
            if (isset(self::$indexMap[$name])) {
                $index = self::$indexMap[$name];
                if ($index < 0x10) {
                    $output .= \chr($index);
                } else {
                    $output .= "\x0f" . \chr($index - 0xf);
                }
            } else {
                $output .= "\x00" . $this->encodeString($name, $compressionThreshold);
            }
            $output .= $this->encodeString($value, $compressionThreshold);
        }
        return $output;
    }
    /**
     *
     */
    private function encodeString(string $value, int $compressionThreshold) : string
    {
        $prefix = "\x00";
        if (\strlen($value) >= $compressionThreshold) {
            $value = self::huffmanEncode($value);
            $prefix = "\x80";
        }
        if (\strlen($value) < 0x7f) {
            return ($prefix | \chr(\strlen($value))) . $value;
        }
        return ($prefix | "") . self::encodeDynamicInteger(\strlen($value) - 0x7f) . $value;
    }
}
(function () {
    static::init();
})->bindTo(null, HPackNative::class)();<?php

/** @noinspection PhpUndefinedMethodInspection */
/** @noinspection PhpUndefinedClassInspection */
namespace Amp\Http\Internal;

use Amp\Http\HPackException;
use FFI;
/** @internal */
final class HPackNghttp2
{
    private const FLAG_NO_INDEX = 0x1;
    private const FLAG_NO_COPY_NAME = 0x2;
    private const FLAG_NO_COPY_VALUE = 0x4;
    private const FLAG_NO_COPY = self::FLAG_NO_COPY_NAME | self::FLAG_NO_COPY_VALUE;
    private const FLAG_NO_COPY_SENSITIVE = self::FLAG_NO_COPY | self::FLAG_NO_INDEX;
    private const SENSITIVE_HEADERS = ['authorization' => self::FLAG_NO_COPY_SENSITIVE, 'cookie' => self::FLAG_NO_COPY_SENSITIVE, 'proxy-authorization' => self::FLAG_NO_COPY_SENSITIVE, 'set-cookie' => self::FLAG_NO_COPY_SENSITIVE];
    private static $ffi;
    private static $deflatePtrType;
    private static $inflatePtrType;
    private static $nvType;
    private static $nvSize;
    private static $charType;
    private static $uint8Type;
    private static $uint8PtrType;
    private static $decodeNv;
    private static $decodeNvPtr;
    private static $decodeFlags;
    private static $decodeFlagsPtr;
    private static $supported;
    /**
     *
     */
    public static function isSupported() : bool
    {
        if (isset(self::$supported)) {
            return self::$supported;
        }
        if (!\extension_loaded('ffi')) {
            return self::$supported = false;
        }
        if (!\class_exists(FFI::class)) {
            return self::$supported = false;
        }
        try {
            self::init();
            return self::$supported = true;
        } catch (\Throwable $e) {
            return self::$supported = false;
        }
    }
    /**
     *
     */
    private static function init() : void
    {
        if (self::$ffi !== null) {
            return;
        }
        $header = \file_get_contents(__DIR__ . '/amp-hpack.h');
        try {
            self::$ffi = FFI::cdef($header, 'libnghttp2.so');
        } catch (\Throwable $exception) {
            self::$ffi = FFI::cdef($header, 'libnghttp2.dylib');
        }
        self::$deflatePtrType = self::$ffi->type('nghttp2_hd_deflater*');
        self::$inflatePtrType = self::$ffi->type('nghttp2_hd_inflater*');
        self::$nvType = self::$ffi->type('nghttp2_nv');
        self::$nvSize = FFI::sizeof(self::$nvType);
        self::$charType = self::$ffi->type('char');
        self::$uint8Type = self::$ffi->type('uint8_t');
        self::$uint8PtrType = self::$ffi->type('uint8_t*');
        self::$decodeNv = self::$ffi->new(self::$nvType);
        self::$decodeNvPtr = FFI::addr(self::$decodeNv);
        self::$decodeFlags = self::$ffi->new('int');
        self::$decodeFlagsPtr = FFI::addr(self::$decodeFlags);
    }
    /**
     *
     */
    private static function createBufferFromString(string $value)
    {
        $length = \strlen($value);
        $buffer = FFI::new(FFI::arrayType(self::$uint8Type, [$length]));
        FFI::memcpy($buffer, $value, $length);
        return $buffer;
    }
    private $deflatePtr;
    private $inflatePtr;
    /**
     * @param int $maxSize Upper limit on table size.
     */
    public function __construct(int $maxSize = 4096)
    {
        self::init();
        $this->deflatePtr = self::$ffi->new(self::$deflatePtrType);
        $this->inflatePtr = self::$ffi->new(self::$inflatePtrType);
        $return = self::$ffi->nghttp2_hd_deflate_new(FFI::addr($this->deflatePtr), $maxSize);
        if ($return !== 0) {
            throw new \RuntimeException('Failed to init deflate context');
        }
        $return = self::$ffi->nghttp2_hd_inflate_new(FFI::addr($this->inflatePtr));
        if ($return !== 0) {
            throw new \RuntimeException('Failed to init inflate context');
        }
    }
    /**
     * @param string $input Encoded headers.
     * @param int $maxSize Maximum length of the decoded header string.
     *
     * @return (string[][] | null) Returns null if decoding fails or if $maxSize is exceeded.
     */
    public function decode(string $input, int $maxSize) : ?array
    {
        $ffi = self::$ffi;
        $pair = self::$decodeNv;
        $pairPtr = self::$decodeNvPtr;
        $flags = self::$decodeFlags;
        $flagsPtr = self::$decodeFlagsPtr;
        $inflate = $this->inflatePtr;
        $size = 0;
        $bufferLength = \strlen($input);
        $buffer = self::createBufferFromString($input);
        $offset = 0;
        $bufferPtr = FFI::cast(self::$uint8PtrType, $buffer);
        $headers = [];
        while (true) {
            $read = $ffi->nghttp2_hd_inflate_hd2($inflate, $pairPtr, $flagsPtr, $bufferPtr, $bufferLength - $offset, 1);
            if ($read < 0) {
                return null;
            }
            $offset += $read;
            $bufferPtr += $read;
            $cFlags = $flags->cdata;
            if ($cFlags & 0x2) {
                // NGHTTP2_HD_INFLATE_EMIT
                $nameLength = $pair->namelen;
                $valueLength = $pair->valuelen;
                $headers[] = [FFI::string($pair->name, $nameLength), FFI::string($pair->value, $valueLength)];
                $size += $nameLength + $valueLength;
                if ($size > $maxSize) {
                    return null;
                }
            }
            if ($cFlags & 0x1) {
                // NGHTTP2_HD_INFLATE_FINAL
                $ffi->nghttp2_hd_inflate_end_headers($inflate);
                FFI::memset($pair, 0, self::$nvSize);
                return $headers;
            }
            if ($read === 0 || $offset > $bufferLength) {
                return null;
            }
        }
        return null;
    }
    /**
     * @param string[][] $headers
     *
     * @return string Encoded headers.
     */
    public function encode(array $headers) : string
    {
        $ffi = self::$ffi;
        // To keep memory buffers
        $buffers = [];
        $headerCount = \count($headers);
        $current = 0;
        $pairs = $ffi->new(FFI::arrayType(self::$nvType, [$headerCount]));
        foreach ($headers as $index => [$name, $value]) {
            \assert($index === $current);
            $pair = $pairs[$current];
            $nameBuffer = self::createBufferFromString($name);
            $valueBuffer = self::createBufferFromString($value);
            $pair->name = FFI::cast(self::$uint8PtrType, $nameBuffer);
            $pair->namelen = \strlen($name);
            $pair->value = FFI::cast(self::$uint8PtrType, $valueBuffer);
            $pair->valuelen = \strlen($value);
            $pair->flags = self::SENSITIVE_HEADERS[$name] ?? self::FLAG_NO_COPY;
            $buffers[] = $nameBuffer;
            $buffers[] = $valueBuffer;
            $current++;
        }
        $bufferLength = $ffi->nghttp2_hd_deflate_bound($this->deflatePtr, $pairs, $headerCount);
        $buffer = FFI::new(FFI::arrayType(self::$uint8Type, [$bufferLength]));
        $bufferLength = $ffi->nghttp2_hd_deflate_hd($this->deflatePtr, $buffer, $bufferLength, $pairs, $headerCount);
        if ($bufferLength < 0) {
            throw new HPackException('Failed to compress headers using nghttp2');
        }
        return FFI::string($buffer, $bufferLength);
    }
}<?php

return [["\x00" => [93, "0"], "\x01" => [138, "0"], "\x02" => [75, "0"], "\x03" => [91, "0"], "\x04" => [108, "0"], "\x05" => [103, "0"], "\x06" => [114, "0"], "\x07" => [14, "0"], "\x08" => [93, "1"], "\t" => [138, "1"], "\n" => [75, "1"], "\v" => [91, "1"], "\f" => [108, "1"], "\r" => [103, "1"], "\x0e" => [114, "1"], "\x0f" => [14, "1"], "\x10" => [93, "2"], "\x11" => [138, "2"], "\x12" => [75, "2"], "\x13" => [91, "2"], "\x14" => [108, "2"], "\x15" => [103, "2"], "\x16" => [114, "2"], "\x17" => [14, "2"], "\x18" => [93, "a"], "\x19" => [138, "a"], "\x1a" => [75, "a"], "\x1b" => [91, "a"], "\x1c" => [108, "a"], "\x1d" => [103, "a"], "\x1e" => [114, "a"], "\x1f" => [14, "a"], " " => [93, "c"], "!" => [138, "c"], "\"" => [75, "c"], "#" => [91, "c"], "\$" => [108, "c"], "%" => [103, "c"], "&" => [114, "c"], "'" => [14, "c"], "(" => [93, "e"], ")" => [138, "e"], "*" => [75, "e"], "+" => [91, "e"], "," => [108, "e"], "-" => [103, "e"], "." => [114, "e"], "/" => [14, "e"], [93, "i"], [138, "i"], [75, "i"], [91, "i"], [108, "i"], [103, "i"], [114, "i"], [14, "i"], [93, "o"], [138, "o"], ":" => [75, "o"], ";" => [91, "o"], "<" => [108, "o"], "=" => [103, "o"], ">" => [114, "o"], "?" => [14, "o"], "@" => [93, "s"], "A" => [138, "s"], "B" => [75, "s"], "C" => [91, "s"], "D" => [108, "s"], "E" => [103, "s"], "F" => [114, "s"], "G" => [14, "s"], "H" => [93, "t"], "I" => [138, "t"], "J" => [75, "t"], "K" => [91, "t"], "L" => [108, "t"], "M" => [103, "t"], "N" => [114, "t"], "O" => [14, "t"], "P" => [94, " "], "Q" => [76, " "], "R" => [104, " "], "S" => [16, " "], "T" => [94, "%"], "U" => [76, "%"], "V" => [104, "%"], "W" => [16, "%"], "X" => [94, "-"], "Y" => [76, "-"], "Z" => [104, "-"], "[" => [16, "-"], "\\" => [94, "."], "]" => [76, "."], "^" => [104, "."], "_" => [16, "."], "`" => [94, "/"], "a" => [76, "/"], "b" => [104, "/"], "c" => [16, "/"], "d" => [94, "3"], "e" => [76, "3"], "f" => [104, "3"], "g" => [16, "3"], "h" => [94, "4"], "i" => [76, "4"], "j" => [104, "4"], "k" => [16, "4"], "l" => [94, "5"], "m" => [76, "5"], "n" => [104, "5"], "o" => [16, "5"], "p" => [94, "6"], "q" => [76, "6"], "r" => [104, "6"], "s" => [16, "6"], "t" => [94, "7"], "u" => [76, "7"], "v" => [104, "7"], "w" => [16, "7"], "x" => [94, "8"], "y" => [76, "8"], "z" => [104, "8"], "{" => [16, "8"], "|" => [94, "9"], "}" => [76, "9"], "~" => [104, "9"], "" => [16, "9"], "\x80" => [94, "="], "\x81" => [76, "="], "\x82" => [104, "="], "\x83" => [16, "="], "\x84" => [94, "A"], "\x85" => [76, "A"], "\x86" => [104, "A"], "\x87" => [16, "A"], "\x88" => [94, "_"], "\x89" => [76, "_"], "\x8a" => [104, "_"], "\x8b" => [16, "_"], "\x8c" => [94, "b"], "\x8d" => [76, "b"], "\x8e" => [104, "b"], "\x8f" => [16, "b"], "\x90" => [94, "d"], "\x91" => [76, "d"], "\x92" => [104, "d"], "\x93" => [16, "d"], "\x94" => [94, "f"], "\x95" => [76, "f"], "\x96" => [104, "f"], "\x97" => [16, "f"], "\x98" => [94, "g"], "\x99" => [76, "g"], "\x9a" => [104, "g"], "\x9b" => [16, "g"], "\x9c" => [94, "h"], "\x9d" => [76, "h"], "\x9e" => [104, "h"], "\x9f" => [16, "h"], "\xa0" => [94, "l"], "\xa1" => [76, "l"], "\xa2" => [104, "l"], "\xa3" => [16, "l"], "\xa4" => [94, "m"], "\xa5" => [76, "m"], "\xa6" => [104, "m"], "\xa7" => [16, "m"], "\xa8" => [94, "n"], "\xa9" => [76, "n"], "\xaa" => [104, "n"], "\xab" => [16, "n"], "\xac" => [94, "p"], "\xad" => [76, "p"], "\xae" => [104, "p"], "\xaf" => [16, "p"], "\xb0" => [94, "r"], "\xb1" => [76, "r"], "\xb2" => [104, "r"], "\xb3" => [16, "r"], "\xb4" => [94, "u"], "\xb5" => [76, "u"], "\xb6" => [104, "u"], "\xb7" => [16, "u"], "\xb8" => [77, ":"], "\xb9" => [18, ":"], "\xba" => [77, "B"], "\xbb" => [18, "B"], "\xbc" => [77, "C"], "\xbd" => [18, "C"], "\xbe" => [77, "D"], "\xbf" => [18, "D"], "\xc0" => [77, "E"], "\xc1" => [18, "E"], "\xc2" => [77, "F"], "\xc3" => [18, "F"], "\xc4" => [77, "G"], "\xc5" => [18, "G"], "\xc6" => [77, "H"], "\xc7" => [18, "H"], "\xc8" => [77, "I"], "\xc9" => [18, "I"], "\xca" => [77, "J"], "\xcb" => [18, "J"], "\xcc" => [77, "K"], "\xcd" => [18, "K"], "\xce" => [77, "L"], "\xcf" => [18, "L"], "\xd0" => [77, "M"], "\xd1" => [18, "M"], "\xd2" => [77, "N"], "\xd3" => [18, "N"], "\xd4" => [77, "O"], "\xd5" => [18, "O"], "\xd6" => [77, "P"], "\xd7" => [18, "P"], "\xd8" => [77, "Q"], "\xd9" => [18, "Q"], "\xda" => [77, "R"], "\xdb" => [18, "R"], "\xdc" => [77, "S"], "\xdd" => [18, "S"], "\xde" => [77, "T"], "\xdf" => [18, "T"], "\xe0" => [77, "U"], "\xe1" => [18, "U"], "\xe2" => [77, "V"], "\xe3" => [18, "V"], "\xe4" => [77, "W"], "\xe5" => [18, "W"], "\xe6" => [77, "Y"], "\xe7" => [18, "Y"], "\xe8" => [77, "j"], "\xe9" => [18, "j"], "\xea" => [77, "k"], "\xeb" => [18, "k"], "\xec" => [77, "q"], "\xed" => [18, "q"], "\xee" => [77, "v"], "\xef" => [18, "v"], "\xf0" => [77, "w"], "\xf1" => [18, "w"], "\xf2" => [77, "x"], "\xf3" => [18, "x"], "\xf4" => [77, "y"], "\xf5" => [18, "y"], "\xf6" => [77, "z"], "\xf7" => [18, "z"], "\xf8" => [0, "&"], "\xf9" => [0, "*"], "\xfa" => [0, ","], "\xfb" => [0, ";"], "\xfc" => [0, "X"], "\xfd" => [0, "Z"], "\xfe" => [78, null], "\xff" => [8, null]], 8 => ["\x00" => [77, "?0"], "\x01" => [18, "?0"], "\x02" => [77, "?1"], "\x03" => [18, "?1"], "\x04" => [77, "?2"], "\x05" => [18, "?2"], "\x06" => [77, "?a"], "\x07" => [18, "?a"], "\x08" => [77, "?c"], "\t" => [18, "?c"], "\n" => [77, "?e"], "\v" => [18, "?e"], "\f" => [77, "?i"], "\r" => [18, "?i"], "\x0e" => [77, "?o"], "\x0f" => [18, "?o"], "\x10" => [77, "?s"], "\x11" => [18, "?s"], "\x12" => [77, "?t"], "\x13" => [18, "?t"], "\x14" => [0, "? "], "\x15" => [0, "?%"], "\x16" => [0, "?-"], "\x17" => [0, "?."], "\x18" => [0, "?/"], "\x19" => [0, "?3"], "\x1a" => [0, "?4"], "\x1b" => [0, "?5"], "\x1c" => [0, "?6"], "\x1d" => [0, "?7"], "\x1e" => [0, "?8"], "\x1f" => [0, "?9"], " " => [0, "?="], "!" => [0, "?A"], "\"" => [0, "?_"], "#" => [0, "?b"], "\$" => [0, "?d"], "%" => [0, "?f"], "&" => [0, "?g"], "'" => [0, "?h"], "(" => [0, "?l"], ")" => [0, "?m"], "*" => [0, "?n"], "+" => [0, "?p"], "," => [0, "?r"], "-" => [0, "?u"], "." => [100, "?"], "/" => [110, "?"], [111, "?"], [115, "?"], [116, "?"], [118, "?"], [119, "?"], [122, "?"], [123, "?"], [125, "?"], [126, "?"], [129, "?"], ":" => [143, "?"], ";" => [148, "?"], "<" => [151, "?"], "=" => [153, "?"], ">" => [83, "?"], "?" => [10, "?"], "@" => [0, "'0"], "A" => [0, "'1"], "B" => [0, "'2"], "C" => [0, "'a"], "D" => [0, "'c"], "E" => [0, "'e"], "F" => [0, "'i"], "G" => [0, "'o"], "H" => [0, "'s"], "I" => [0, "'t"], "J" => [73, "'"], "K" => [88, "'"], "L" => [89, "'"], "M" => [96, "'"], "N" => [97, "'"], "O" => [99, "'"], "P" => [106, "'"], "Q" => [136, "'"], "R" => [139, "'"], "S" => [141, "'"], "T" => [145, "'"], "U" => [147, "'"], "V" => [149, "'"], "W" => [101, "'"], "X" => [112, "'"], "Y" => [117, "'"], "Z" => [120, "'"], "[" => [124, "'"], "\\" => [127, "'"], "]" => [144, "'"], "^" => [152, "'"], "_" => [11, "'"], "`" => [0, "+0"], "a" => [0, "+1"], "b" => [0, "+2"], "c" => [0, "+a"], "d" => [0, "+c"], "e" => [0, "+e"], "f" => [0, "+i"], "g" => [0, "+o"], "h" => [0, "+s"], "i" => [0, "+t"], "j" => [73, "+"], "k" => [88, "+"], "l" => [89, "+"], "m" => [96, "+"], "n" => [97, "+"], "o" => [99, "+"], "p" => [106, "+"], "q" => [136, "+"], "r" => [139, "+"], "s" => [141, "+"], "t" => [145, "+"], "u" => [147, "+"], "v" => [149, "+"], "w" => [101, "+"], "x" => [112, "+"], "y" => [117, "+"], "z" => [120, "+"], "{" => [124, "+"], "|" => [127, "+"], "}" => [144, "+"], "~" => [152, "+"], "" => [11, "+"], "\x80" => [0, "|0"], "\x81" => [0, "|1"], "\x82" => [0, "|2"], "\x83" => [0, "|a"], "\x84" => [0, "|c"], "\x85" => [0, "|e"], "\x86" => [0, "|i"], "\x87" => [0, "|o"], "\x88" => [0, "|s"], "\x89" => [0, "|t"], "\x8a" => [73, "|"], "\x8b" => [88, "|"], "\x8c" => [89, "|"], "\x8d" => [96, "|"], "\x8e" => [97, "|"], "\x8f" => [99, "|"], "\x90" => [106, "|"], "\x91" => [136, "|"], "\x92" => [139, "|"], "\x93" => [141, "|"], "\x94" => [145, "|"], "\x95" => [147, "|"], "\x96" => [149, "|"], "\x97" => [101, "|"], "\x98" => [112, "|"], "\x99" => [117, "|"], "\x9a" => [120, "|"], "\x9b" => [124, "|"], "\x9c" => [127, "|"], "\x9d" => [144, "|"], "\x9e" => [152, "|"], "\x9f" => [11, "|"], "\xa0" => [92, "#"], "\xa1" => [95, "#"], "\xa2" => [137, "#"], "\xa3" => [142, "#"], "\xa4" => [150, "#"], "\xa5" => [74, "#"], "\xa6" => [90, "#"], "\xa7" => [98, "#"], "\xa8" => [107, "#"], "\xa9" => [140, "#"], "\xaa" => [146, "#"], "\xab" => [102, "#"], "\xac" => [113, "#"], "\xad" => [121, "#"], "\xae" => [128, "#"], "\xaf" => [12, "#"], "\xb0" => [92, ">"], "\xb1" => [95, ">"], "\xb2" => [137, ">"], "\xb3" => [142, ">"], "\xb4" => [150, ">"], "\xb5" => [74, ">"], "\xb6" => [90, ">"], "\xb7" => [98, ">"], "\xb8" => [107, ">"], "\xb9" => [140, ">"], "\xba" => [146, ">"], "\xbb" => [102, ">"], "\xbc" => [113, ">"], "\xbd" => [121, ">"], "\xbe" => [128, ">"], "\xbf" => [12, ">"], "\xc0" => [93, "\x00"], "\xc1" => [138, "\x00"], "\xc2" => [75, "\x00"], "\xc3" => [91, "\x00"], "\xc4" => [108, "\x00"], "\xc5" => [103, "\x00"], "\xc6" => [114, "\x00"], "\xc7" => [14, "\x00"], "\xc8" => [93, "\$"], "\xc9" => [138, "\$"], "\xca" => [75, "\$"], "\xcb" => [91, "\$"], "\xcc" => [108, "\$"], "\xcd" => [103, "\$"], "\xce" => [114, "\$"], "\xcf" => [14, "\$"], "\xd0" => [93, "@"], "\xd1" => [138, "@"], "\xd2" => [75, "@"], "\xd3" => [91, "@"], "\xd4" => [108, "@"], "\xd5" => [103, "@"], "\xd6" => [114, "@"], "\xd7" => [14, "@"], "\xd8" => [93, "["], "\xd9" => [138, "["], "\xda" => [75, "["], "\xdb" => [91, "["], "\xdc" => [108, "["], "\xdd" => [103, "["], "\xde" => [114, "["], "\xdf" => [14, "["], "\xe0" => [93, "]"], "\xe1" => [138, "]"], "\xe2" => [75, "]"], "\xe3" => [91, "]"], "\xe4" => [108, "]"], "\xe5" => [103, "]"], "\xe6" => [114, "]"], "\xe7" => [14, "]"], "\xe8" => [93, "~"], "\xe9" => [138, "~"], "\xea" => [75, "~"], "\xeb" => [91, "~"], "\xec" => [108, "~"], "\xed" => [103, "~"], "\xee" => [114, "~"], "\xef" => [14, "~"], "\xf0" => [94, "^"], "\xf1" => [76, "^"], "\xf2" => [104, "^"], "\xf3" => [16, "^"], "\xf4" => [94, "}"], "\xf5" => [76, "}"], "\xf6" => [104, "}"], "\xf7" => [16, "}"], "\xf8" => [77, "<"], "\xf9" => [18, "<"], "\xfa" => [77, "`"], "\xfb" => [18, "`"], "\xfc" => [77, "{"], "\xfd" => [18, "{"], "\xfe" => [131, null], "\xff" => [20, null]], ["\x00" => [0, "!0"], "\x01" => [0, "!1"], "\x02" => [0, "!2"], "\x03" => [0, "!a"], "\x04" => [0, "!c"], "\x05" => [0, "!e"], "\x06" => [0, "!i"], "\x07" => [0, "!o"], "\x08" => [0, "!s"], "\t" => [0, "!t"], "\n" => [73, "!"], "\v" => [88, "!"], "\f" => [89, "!"], "\r" => [96, "!"], "\x0e" => [97, "!"], "\x0f" => [99, "!"], "\x10" => [106, "!"], "\x11" => [136, "!"], "\x12" => [139, "!"], "\x13" => [141, "!"], "\x14" => [145, "!"], "\x15" => [147, "!"], "\x16" => [149, "!"], "\x17" => [101, "!"], "\x18" => [112, "!"], "\x19" => [117, "!"], "\x1a" => [120, "!"], "\x1b" => [124, "!"], "\x1c" => [127, "!"], "\x1d" => [144, "!"], "\x1e" => [152, "!"], "\x1f" => [11, "!"], " " => [0, "\"0"], "!" => [0, "\"1"], "\"" => [0, "\"2"], "#" => [0, "\"a"], "\$" => [0, "\"c"], "%" => [0, "\"e"], "&" => [0, "\"i"], "'" => [0, "\"o"], "(" => [0, "\"s"], ")" => [0, "\"t"], "*" => [73, "\""], "+" => [88, "\""], "," => [89, "\""], "-" => [96, "\""], "." => [97, "\""], "/" => [99, "\""], [106, "\""], [136, "\""], [139, "\""], [141, "\""], [145, "\""], [147, "\""], [149, "\""], [101, "\""], [112, "\""], [117, "\""], ":" => [120, "\""], ";" => [124, "\""], "<" => [127, "\""], "=" => [144, "\""], ">" => [152, "\""], "?" => [11, "\""], "@" => [0, "(0"], "A" => [0, "(1"], "B" => [0, "(2"], "C" => [0, "(a"], "D" => [0, "(c"], "E" => [0, "(e"], "F" => [0, "(i"], "G" => [0, "(o"], "H" => [0, "(s"], "I" => [0, "(t"], "J" => [73, "("], "K" => [88, "("], "L" => [89, "("], "M" => [96, "("], "N" => [97, "("], "O" => [99, "("], "P" => [106, "("], "Q" => [136, "("], "R" => [139, "("], "S" => [141, "("], "T" => [145, "("], "U" => [147, "("], "V" => [149, "("], "W" => [101, "("], "X" => [112, "("], "Y" => [117, "("], "Z" => [120, "("], "[" => [124, "("], "\\" => [127, "("], "]" => [144, "("], "^" => [152, "("], "_" => [11, "("], "`" => [0, ")0"], "a" => [0, ")1"], "b" => [0, ")2"], "c" => [0, ")a"], "d" => [0, ")c"], "e" => [0, ")e"], "f" => [0, ")i"], "g" => [0, ")o"], "h" => [0, ")s"], "i" => [0, ")t"], "j" => [73, ")"], "k" => [88, ")"], "l" => [89, ")"], "m" => [96, ")"], "n" => [97, ")"], "o" => [99, ")"], "p" => [106, ")"], "q" => [136, ")"], "r" => [139, ")"], "s" => [141, ")"], "t" => [145, ")"], "u" => [147, ")"], "v" => [149, ")"], "w" => [101, ")"], "x" => [112, ")"], "y" => [117, ")"], "z" => [120, ")"], "{" => [124, ")"], "|" => [127, ")"], "}" => [144, ")"], "~" => [152, ")"], "" => [11, ")"], "\x80" => [0, "?0"], "\x81" => [0, "?1"], "\x82" => [0, "?2"], "\x83" => [0, "?a"], "\x84" => [0, "?c"], "\x85" => [0, "?e"], "\x86" => [0, "?i"], "\x87" => [0, "?o"], "\x88" => [0, "?s"], "\x89" => [0, "?t"], "\x8a" => [73, "?"], "\x8b" => [88, "?"], "\x8c" => [89, "?"], "\x8d" => [96, "?"], "\x8e" => [97, "?"], "\x8f" => [99, "?"], "\x90" => [106, "?"], "\x91" => [136, "?"], "\x92" => [139, "?"], "\x93" => [141, "?"], "\x94" => [145, "?"], "\x95" => [147, "?"], "\x96" => [149, "?"], "\x97" => [101, "?"], "\x98" => [112, "?"], "\x99" => [117, "?"], "\x9a" => [120, "?"], "\x9b" => [124, "?"], "\x9c" => [127, "?"], "\x9d" => [144, "?"], "\x9e" => [152, "?"], "\x9f" => [11, "?"], "\xa0" => [92, "'"], "\xa1" => [95, "'"], "\xa2" => [137, "'"], "\xa3" => [142, "'"], "\xa4" => [150, "'"], "\xa5" => [74, "'"], "\xa6" => [90, "'"], "\xa7" => [98, "'"], "\xa8" => [107, "'"], "\xa9" => [140, "'"], "\xaa" => [146, "'"], "\xab" => [102, "'"], "\xac" => [113, "'"], "\xad" => [121, "'"], "\xae" => [128, "'"], "\xaf" => [12, "'"], "\xb0" => [92, "+"], "\xb1" => [95, "+"], "\xb2" => [137, "+"], "\xb3" => [142, "+"], "\xb4" => [150, "+"], "\xb5" => [74, "+"], "\xb6" => [90, "+"], "\xb7" => [98, "+"], "\xb8" => [107, "+"], "\xb9" => [140, "+"], "\xba" => [146, "+"], "\xbb" => [102, "+"], "\xbc" => [113, "+"], "\xbd" => [121, "+"], "\xbe" => [128, "+"], "\xbf" => [12, "+"], "\xc0" => [92, "|"], "\xc1" => [95, "|"], "\xc2" => [137, "|"], "\xc3" => [142, "|"], "\xc4" => [150, "|"], "\xc5" => [74, "|"], "\xc6" => [90, "|"], "\xc7" => [98, "|"], "\xc8" => [107, "|"], "\xc9" => [140, "|"], "\xca" => [146, "|"], "\xcb" => [102, "|"], "\xcc" => [113, "|"], "\xcd" => [121, "|"], "\xce" => [128, "|"], "\xcf" => [12, "|"], "\xd0" => [93, "#"], "\xd1" => [138, "#"], "\xd2" => [75, "#"], "\xd3" => [91, "#"], "\xd4" => [108, "#"], "\xd5" => [103, "#"], "\xd6" => [114, "#"], "\xd7" => [14, "#"], "\xd8" => [93, ">"], "\xd9" => [138, ">"], "\xda" => [75, ">"], "\xdb" => [91, ">"], "\xdc" => [108, ">"], "\xdd" => [103, ">"], "\xde" => [114, ">"], "\xdf" => [14, ">"], "\xe0" => [94, "\x00"], "\xe1" => [76, "\x00"], "\xe2" => [104, "\x00"], "\xe3" => [16, "\x00"], "\xe4" => [94, "\$"], "\xe5" => [76, "\$"], "\xe6" => [104, "\$"], "\xe7" => [16, "\$"], "\xe8" => [94, "@"], "\xe9" => [76, "@"], "\xea" => [104, "@"], "\xeb" => [16, "@"], "\xec" => [94, "["], "\xed" => [76, "["], "\xee" => [104, "["], "\xef" => [16, "["], "\xf0" => [94, "]"], "\xf1" => [76, "]"], "\xf2" => [104, "]"], "\xf3" => [16, "]"], "\xf4" => [94, "~"], "\xf5" => [76, "~"], "\xf6" => [104, "~"], "\xf7" => [16, "~"], "\xf8" => [77, "^"], "\xf9" => [18, "^"], "\xfa" => [77, "}"], "\xfb" => [18, "}"], "\xfc" => [0, "<"], "\xfd" => [0, "`"], "\xfe" => [0, "{"], "\xff" => [21, null]], ["\x00" => [77, "X0"], "\x01" => [18, "X0"], "\x02" => [77, "X1"], "\x03" => [18, "X1"], "\x04" => [77, "X2"], "\x05" => [18, "X2"], "\x06" => [77, "Xa"], "\x07" => [18, "Xa"], "\x08" => [77, "Xc"], "\t" => [18, "Xc"], "\n" => [77, "Xe"], "\v" => [18, "Xe"], "\f" => [77, "Xi"], "\r" => [18, "Xi"], "\x0e" => [77, "Xo"], "\x0f" => [18, "Xo"], "\x10" => [77, "Xs"], "\x11" => [18, "Xs"], "\x12" => [77, "Xt"], "\x13" => [18, "Xt"], "\x14" => [0, "X "], "\x15" => [0, "X%"], "\x16" => [0, "X-"], "\x17" => [0, "X."], "\x18" => [0, "X/"], "\x19" => [0, "X3"], "\x1a" => [0, "X4"], "\x1b" => [0, "X5"], "\x1c" => [0, "X6"], "\x1d" => [0, "X7"], "\x1e" => [0, "X8"], "\x1f" => [0, "X9"], " " => [0, "X="], "!" => [0, "XA"], "\"" => [0, "X_"], "#" => [0, "Xb"], "\$" => [0, "Xd"], "%" => [0, "Xf"], "&" => [0, "Xg"], "'" => [0, "Xh"], "(" => [0, "Xl"], ")" => [0, "Xm"], "*" => [0, "Xn"], "+" => [0, "Xp"], "," => [0, "Xr"], "-" => [0, "Xu"], "." => [100, "X"], "/" => [110, "X"], [111, "X"], [115, "X"], [116, "X"], [118, "X"], [119, "X"], [122, "X"], [123, "X"], [125, "X"], [126, "X"], [129, "X"], ":" => [143, "X"], ";" => [148, "X"], "<" => [151, "X"], "=" => [153, "X"], ">" => [83, "X"], "?" => [10, "X"], "@" => [77, "Z0"], "A" => [18, "Z0"], "B" => [77, "Z1"], "C" => [18, "Z1"], "D" => [77, "Z2"], "E" => [18, "Z2"], "F" => [77, "Za"], "G" => [18, "Za"], "H" => [77, "Zc"], "I" => [18, "Zc"], "J" => [77, "Ze"], "K" => [18, "Ze"], "L" => [77, "Zi"], "M" => [18, "Zi"], "N" => [77, "Zo"], "O" => [18, "Zo"], "P" => [77, "Zs"], "Q" => [18, "Zs"], "R" => [77, "Zt"], "S" => [18, "Zt"], "T" => [0, "Z "], "U" => [0, "Z%"], "V" => [0, "Z-"], "W" => [0, "Z."], "X" => [0, "Z/"], "Y" => [0, "Z3"], "Z" => [0, "Z4"], "[" => [0, "Z5"], "\\" => [0, "Z6"], "]" => [0, "Z7"], "^" => [0, "Z8"], "_" => [0, "Z9"], "`" => [0, "Z="], "a" => [0, "ZA"], "b" => [0, "Z_"], "c" => [0, "Zb"], "d" => [0, "Zd"], "e" => [0, "Zf"], "f" => [0, "Zg"], "g" => [0, "Zh"], "h" => [0, "Zl"], "i" => [0, "Zm"], "j" => [0, "Zn"], "k" => [0, "Zp"], "l" => [0, "Zr"], "m" => [0, "Zu"], "n" => [100, "Z"], "o" => [110, "Z"], "p" => [111, "Z"], "q" => [115, "Z"], "r" => [116, "Z"], "s" => [118, "Z"], "t" => [119, "Z"], "u" => [122, "Z"], "v" => [123, "Z"], "w" => [125, "Z"], "x" => [126, "Z"], "y" => [129, "Z"], "z" => [143, "Z"], "{" => [148, "Z"], "|" => [151, "Z"], "}" => [153, "Z"], "~" => [83, "Z"], "" => [10, "Z"], "\x80" => [92, "!"], "\x81" => [95, "!"], "\x82" => [137, "!"], "\x83" => [142, "!"], "\x84" => [150, "!"], "\x85" => [74, "!"], "\x86" => [90, "!"], "\x87" => [98, "!"], "\x88" => [107, "!"], "\x89" => [140, "!"], "\x8a" => [146, "!"], "\x8b" => [102, "!"], "\x8c" => [113, "!"], "\x8d" => [121, "!"], "\x8e" => [128, "!"], "\x8f" => [12, "!"], "\x90" => [92, "\""], "\x91" => [95, "\""], "\x92" => [137, "\""], "\x93" => [142, "\""], "\x94" => [150, "\""], "\x95" => [74, "\""], "\x96" => [90, "\""], "\x97" => [98, "\""], "\x98" => [107, "\""], "\x99" => [140, "\""], "\x9a" => [146, "\""], "\x9b" => [102, "\""], "\x9c" => [113, "\""], "\x9d" => [121, "\""], "\x9e" => [128, "\""], "\x9f" => [12, "\""], "\xa0" => [92, "("], "\xa1" => [95, "("], "\xa2" => [137, "("], "\xa3" => [142, "("], "\xa4" => [150, "("], "\xa5" => [74, "("], "\xa6" => [90, "("], "\xa7" => [98, "("], "\xa8" => [107, "("], "\xa9" => [140, "("], "\xaa" => [146, "("], "\xab" => [102, "("], "\xac" => [113, "("], "\xad" => [121, "("], "\xae" => [128, "("], "\xaf" => [12, "("], "\xb0" => [92, ")"], "\xb1" => [95, ")"], "\xb2" => [137, ")"], "\xb3" => [142, ")"], "\xb4" => [150, ")"], "\xb5" => [74, ")"], "\xb6" => [90, ")"], "\xb7" => [98, ")"], "\xb8" => [107, ")"], "\xb9" => [140, ")"], "\xba" => [146, ")"], "\xbb" => [102, ")"], "\xbc" => [113, ")"], "\xbd" => [121, ")"], "\xbe" => [128, ")"], "\xbf" => [12, ")"], "\xc0" => [92, "?"], "\xc1" => [95, "?"], "\xc2" => [137, "?"], "\xc3" => [142, "?"], "\xc4" => [150, "?"], "\xc5" => [74, "?"], "\xc6" => [90, "?"], "\xc7" => [98, "?"], "\xc8" => [107, "?"], "\xc9" => [140, "?"], "\xca" => [146, "?"], "\xcb" => [102, "?"], "\xcc" => [113, "?"], "\xcd" => [121, "?"], "\xce" => [128, "?"], "\xcf" => [12, "?"], "\xd0" => [93, "'"], "\xd1" => [138, "'"], "\xd2" => [75, "'"], "\xd3" => [91, "'"], "\xd4" => [108, "'"], "\xd5" => [103, "'"], "\xd6" => [114, "'"], "\xd7" => [14, "'"], "\xd8" => [93, "+"], "\xd9" => [138, "+"], "\xda" => [75, "+"], "\xdb" => [91, "+"], "\xdc" => [108, "+"], "\xdd" => [103, "+"], "\xde" => [114, "+"], "\xdf" => [14, "+"], "\xe0" => [93, "|"], "\xe1" => [138, "|"], "\xe2" => [75, "|"], "\xe3" => [91, "|"], "\xe4" => [108, "|"], "\xe5" => [103, "|"], "\xe6" => [114, "|"], "\xe7" => [14, "|"], "\xe8" => [94, "#"], "\xe9" => [76, "#"], "\xea" => [104, "#"], "\xeb" => [16, "#"], "\xec" => [94, ">"], "\xed" => [76, ">"], "\xee" => [104, ">"], "\xef" => [16, ">"], "\xf0" => [77, "\x00"], "\xf1" => [18, "\x00"], "\xf2" => [77, "\$"], "\xf3" => [18, "\$"], "\xf4" => [77, "@"], "\xf5" => [18, "@"], "\xf6" => [77, "["], "\xf7" => [18, "["], "\xf8" => [77, "]"], "\xf9" => [18, "]"], "\xfa" => [77, "~"], "\xfb" => [18, "~"], "\xfc" => [0, "^"], "\xfd" => [0, "}"], "\xfe" => [105, null], "\xff" => [22, null]], ["\x00" => [0, "&0"], "\x01" => [0, "&1"], "\x02" => [0, "&2"], "\x03" => [0, "&a"], "\x04" => [0, "&c"], "\x05" => [0, "&e"], "\x06" => [0, "&i"], "\x07" => [0, "&o"], "\x08" => [0, "&s"], "\t" => [0, "&t"], "\n" => [73, "&"], "\v" => [88, "&"], "\f" => [89, "&"], "\r" => [96, "&"], "\x0e" => [97, "&"], "\x0f" => [99, "&"], "\x10" => [106, "&"], "\x11" => [136, "&"], "\x12" => [139, "&"], "\x13" => [141, "&"], "\x14" => [145, "&"], "\x15" => [147, "&"], "\x16" => [149, "&"], "\x17" => [101, "&"], "\x18" => [112, "&"], "\x19" => [117, "&"], "\x1a" => [120, "&"], "\x1b" => [124, "&"], "\x1c" => [127, "&"], "\x1d" => [144, "&"], "\x1e" => [152, "&"], "\x1f" => [11, "&"], " " => [0, "*0"], "!" => [0, "*1"], "\"" => [0, "*2"], "#" => [0, "*a"], "\$" => [0, "*c"], "%" => [0, "*e"], "&" => [0, "*i"], "'" => [0, "*o"], "(" => [0, "*s"], ")" => [0, "*t"], "*" => [73, "*"], "+" => [88, "*"], "," => [89, "*"], "-" => [96, "*"], "." => [97, "*"], "/" => [99, "*"], [106, "*"], [136, "*"], [139, "*"], [141, "*"], [145, "*"], [147, "*"], [149, "*"], [101, "*"], [112, "*"], [117, "*"], ":" => [120, "*"], ";" => [124, "*"], "<" => [127, "*"], "=" => [144, "*"], ">" => [152, "*"], "?" => [11, "*"], "@" => [0, ",0"], "A" => [0, ",1"], "B" => [0, ",2"], "C" => [0, ",a"], "D" => [0, ",c"], "E" => [0, ",e"], "F" => [0, ",i"], "G" => [0, ",o"], "H" => [0, ",s"], "I" => [0, ",t"], "J" => [73, ","], "K" => [88, ","], "L" => [89, ","], "M" => [96, ","], "N" => [97, ","], "O" => [99, ","], "P" => [106, ","], "Q" => [136, ","], "R" => [139, ","], "S" => [141, ","], "T" => [145, ","], "U" => [147, ","], "V" => [149, ","], "W" => [101, ","], "X" => [112, ","], "Y" => [117, ","], "Z" => [120, ","], "[" => [124, ","], "\\" => [127, ","], "]" => [144, ","], "^" => [152, ","], "_" => [11, ","], "`" => [0, ";0"], "a" => [0, ";1"], "b" => [0, ";2"], "c" => [0, ";a"], "d" => [0, ";c"], "e" => [0, ";e"], "f" => [0, ";i"], "g" => [0, ";o"], "h" => [0, ";s"], "i" => [0, ";t"], "j" => [73, ";"], "k" => [88, ";"], "l" => [89, ";"], "m" => [96, ";"], "n" => [97, ";"], "o" => [99, ";"], "p" => [106, ";"], "q" => [136, ";"], "r" => [139, ";"], "s" => [141, ";"], "t" => [145, ";"], "u" => [147, ";"], "v" => [149, ";"], "w" => [101, ";"], "x" => [112, ";"], "y" => [117, ";"], "z" => [120, ";"], "{" => [124, ";"], "|" => [127, ";"], "}" => [144, ";"], "~" => [152, ";"], "" => [11, ";"], "\x80" => [0, "X0"], "\x81" => [0, "X1"], "\x82" => [0, "X2"], "\x83" => [0, "Xa"], "\x84" => [0, "Xc"], "\x85" => [0, "Xe"], "\x86" => [0, "Xi"], "\x87" => [0, "Xo"], "\x88" => [0, "Xs"], "\x89" => [0, "Xt"], "\x8a" => [73, "X"], "\x8b" => [88, "X"], "\x8c" => [89, "X"], "\x8d" => [96, "X"], "\x8e" => [97, "X"], "\x8f" => [99, "X"], "\x90" => [106, "X"], "\x91" => [136, "X"], "\x92" => [139, "X"], "\x93" => [141, "X"], "\x94" => [145, "X"], "\x95" => [147, "X"], "\x96" => [149, "X"], "\x97" => [101, "X"], "\x98" => [112, "X"], "\x99" => [117, "X"], "\x9a" => [120, "X"], "\x9b" => [124, "X"], "\x9c" => [127, "X"], "\x9d" => [144, "X"], "\x9e" => [152, "X"], "\x9f" => [11, "X"], "\xa0" => [0, "Z0"], "\xa1" => [0, "Z1"], "\xa2" => [0, "Z2"], "\xa3" => [0, "Za"], "\xa4" => [0, "Zc"], "\xa5" => [0, "Ze"], "\xa6" => [0, "Zi"], "\xa7" => [0, "Zo"], "\xa8" => [0, "Zs"], "\xa9" => [0, "Zt"], "\xaa" => [73, "Z"], "\xab" => [88, "Z"], "\xac" => [89, "Z"], "\xad" => [96, "Z"], "\xae" => [97, "Z"], "\xaf" => [99, "Z"], "\xb0" => [106, "Z"], "\xb1" => [136, "Z"], "\xb2" => [139, "Z"], "\xb3" => [141, "Z"], "\xb4" => [145, "Z"], "\xb5" => [147, "Z"], "\xb6" => [149, "Z"], "\xb7" => [101, "Z"], "\xb8" => [112, "Z"], "\xb9" => [117, "Z"], "\xba" => [120, "Z"], "\xbb" => [124, "Z"], "\xbc" => [127, "Z"], "\xbd" => [144, "Z"], "\xbe" => [152, "Z"], "\xbf" => [11, "Z"], "\xc0" => [93, "!"], "\xc1" => [138, "!"], "\xc2" => [75, "!"], "\xc3" => [91, "!"], "\xc4" => [108, "!"], "\xc5" => [103, "!"], "\xc6" => [114, "!"], "\xc7" => [14, "!"], "\xc8" => [93, "\""], "\xc9" => [138, "\""], "\xca" => [75, "\""], "\xcb" => [91, "\""], "\xcc" => [108, "\""], "\xcd" => [103, "\""], "\xce" => [114, "\""], "\xcf" => [14, "\""], "\xd0" => [93, "("], "\xd1" => [138, "("], "\xd2" => [75, "("], "\xd3" => [91, "("], "\xd4" => [108, "("], "\xd5" => [103, "("], "\xd6" => [114, "("], "\xd7" => [14, "("], "\xd8" => [93, ")"], "\xd9" => [138, ")"], "\xda" => [75, ")"], "\xdb" => [91, ")"], "\xdc" => [108, ")"], "\xdd" => [103, ")"], "\xde" => [114, ")"], "\xdf" => [14, ")"], "\xe0" => [93, "?"], "\xe1" => [138, "?"], "\xe2" => [75, "?"], "\xe3" => [91, "?"], "\xe4" => [108, "?"], "\xe5" => [103, "?"], "\xe6" => [114, "?"], "\xe7" => [14, "?"], "\xe8" => [94, "'"], "\xe9" => [76, "'"], "\xea" => [104, "'"], "\xeb" => [16, "'"], "\xec" => [94, "+"], "\xed" => [76, "+"], "\xee" => [104, "+"], "\xef" => [16, "+"], "\xf0" => [94, "|"], "\xf1" => [76, "|"], "\xf2" => [104, "|"], "\xf3" => [16, "|"], "\xf4" => [77, "#"], "\xf5" => [18, "#"], "\xf6" => [77, ">"], "\xf7" => [18, ">"], "\xf8" => [0, "\x00"], "\xf9" => [0, "\$"], "\xfa" => [0, "@"], "\xfb" => [0, "["], "\xfc" => [0, "]"], "\xfd" => [0, "~"], "\xfe" => [135, null], "\xff" => [24, null]], ["\x00" => [0, "w0"], "\x01" => [0, "w1"], "\x02" => [0, "w2"], "\x03" => [0, "wa"], "\x04" => [0, "wc"], "\x05" => [0, "we"], "\x06" => [0, "wi"], "\x07" => [0, "wo"], "\x08" => [0, "ws"], "\t" => [0, "wt"], "\n" => [73, "w"], "\v" => [88, "w"], "\f" => [89, "w"], "\r" => [96, "w"], "\x0e" => [97, "w"], "\x0f" => [99, "w"], "\x10" => [106, "w"], "\x11" => [136, "w"], "\x12" => [139, "w"], "\x13" => [141, "w"], "\x14" => [145, "w"], "\x15" => [147, "w"], "\x16" => [149, "w"], "\x17" => [101, "w"], "\x18" => [112, "w"], "\x19" => [117, "w"], "\x1a" => [120, "w"], "\x1b" => [124, "w"], "\x1c" => [127, "w"], "\x1d" => [144, "w"], "\x1e" => [152, "w"], "\x1f" => [11, "w"], " " => [0, "x0"], "!" => [0, "x1"], "\"" => [0, "x2"], "#" => [0, "xa"], "\$" => [0, "xc"], "%" => [0, "xe"], "&" => [0, "xi"], "'" => [0, "xo"], "(" => [0, "xs"], ")" => [0, "xt"], "*" => [73, "x"], "+" => [88, "x"], "," => [89, "x"], "-" => [96, "x"], "." => [97, "x"], "/" => [99, "x"], [106, "x"], [136, "x"], [139, "x"], [141, "x"], [145, "x"], [147, "x"], [149, "x"], [101, "x"], [112, "x"], [117, "x"], ":" => [120, "x"], ";" => [124, "x"], "<" => [127, "x"], "=" => [144, "x"], ">" => [152, "x"], "?" => [11, "x"], "@" => [0, "y0"], "A" => [0, "y1"], "B" => [0, "y2"], "C" => [0, "ya"], "D" => [0, "yc"], "E" => [0, "ye"], "F" => [0, "yi"], "G" => [0, "yo"], "H" => [0, "ys"], "I" => [0, "yt"], "J" => [73, "y"], "K" => [88, "y"], "L" => [89, "y"], "M" => [96, "y"], "N" => [97, "y"], "O" => [99, "y"], "P" => [106, "y"], "Q" => [136, "y"], "R" => [139, "y"], "S" => [141, "y"], "T" => [145, "y"], "U" => [147, "y"], "V" => [149, "y"], "W" => [101, "y"], "X" => [112, "y"], "Y" => [117, "y"], "Z" => [120, "y"], "[" => [124, "y"], "\\" => [127, "y"], "]" => [144, "y"], "^" => [152, "y"], "_" => [11, "y"], "`" => [0, "z0"], "a" => [0, "z1"], "b" => [0, "z2"], "c" => [0, "za"], "d" => [0, "zc"], "e" => [0, "ze"], "f" => [0, "zi"], "g" => [0, "zo"], "h" => [0, "zs"], "i" => [0, "zt"], "j" => [73, "z"], "k" => [88, "z"], "l" => [89, "z"], "m" => [96, "z"], "n" => [97, "z"], "o" => [99, "z"], "p" => [106, "z"], "q" => [136, "z"], "r" => [139, "z"], "s" => [141, "z"], "t" => [145, "z"], "u" => [147, "z"], "v" => [149, "z"], "w" => [101, "z"], "x" => [112, "z"], "y" => [117, "z"], "z" => [120, "z"], "{" => [124, "z"], "|" => [127, "z"], "}" => [144, "z"], "~" => [152, "z"], "" => [11, "z"], "\x80" => [92, "&"], "\x81" => [95, "&"], "\x82" => [137, "&"], "\x83" => [142, "&"], "\x84" => [150, "&"], "\x85" => [74, "&"], "\x86" => [90, "&"], "\x87" => [98, "&"], "\x88" => [107, "&"], "\x89" => [140, "&"], "\x8a" => [146, "&"], "\x8b" => [102, "&"], "\x8c" => [113, "&"], "\x8d" => [121, "&"], "\x8e" => [128, "&"], "\x8f" => [12, "&"], "\x90" => [92, "*"], "\x91" => [95, "*"], "\x92" => [137, "*"], "\x93" => [142, "*"], "\x94" => [150, "*"], "\x95" => [74, "*"], "\x96" => [90, "*"], "\x97" => [98, "*"], "\x98" => [107, "*"], "\x99" => [140, "*"], "\x9a" => [146, "*"], "\x9b" => [102, "*"], "\x9c" => [113, "*"], "\x9d" => [121, "*"], "\x9e" => [128, "*"], "\x9f" => [12, "*"], "\xa0" => [92, ","], "\xa1" => [95, ","], "\xa2" => [137, ","], "\xa3" => [142, ","], "\xa4" => [150, ","], "\xa5" => [74, ","], "\xa6" => [90, ","], "\xa7" => [98, ","], "\xa8" => [107, ","], "\xa9" => [140, ","], "\xaa" => [146, ","], "\xab" => [102, ","], "\xac" => [113, ","], "\xad" => [121, ","], "\xae" => [128, ","], "\xaf" => [12, ","], "\xb0" => [92, ";"], "\xb1" => [95, ";"], "\xb2" => [137, ";"], "\xb3" => [142, ";"], "\xb4" => [150, ";"], "\xb5" => [74, ";"], "\xb6" => [90, ";"], "\xb7" => [98, ";"], "\xb8" => [107, ";"], "\xb9" => [140, ";"], "\xba" => [146, ";"], "\xbb" => [102, ";"], "\xbc" => [113, ";"], "\xbd" => [121, ";"], "\xbe" => [128, ";"], "\xbf" => [12, ";"], "\xc0" => [92, "X"], "\xc1" => [95, "X"], "\xc2" => [137, "X"], "\xc3" => [142, "X"], "\xc4" => [150, "X"], "\xc5" => [74, "X"], "\xc6" => [90, "X"], "\xc7" => [98, "X"], "\xc8" => [107, "X"], "\xc9" => [140, "X"], "\xca" => [146, "X"], "\xcb" => [102, "X"], "\xcc" => [113, "X"], "\xcd" => [121, "X"], "\xce" => [128, "X"], "\xcf" => [12, "X"], "\xd0" => [92, "Z"], "\xd1" => [95, "Z"], "\xd2" => [137, "Z"], "\xd3" => [142, "Z"], "\xd4" => [150, "Z"], "\xd5" => [74, "Z"], "\xd6" => [90, "Z"], "\xd7" => [98, "Z"], "\xd8" => [107, "Z"], "\xd9" => [140, "Z"], "\xda" => [146, "Z"], "\xdb" => [102, "Z"], "\xdc" => [113, "Z"], "\xdd" => [121, "Z"], "\xde" => [128, "Z"], "\xdf" => [12, "Z"], "\xe0" => [94, "!"], "\xe1" => [76, "!"], "\xe2" => [104, "!"], "\xe3" => [16, "!"], "\xe4" => [94, "\""], "\xe5" => [76, "\""], "\xe6" => [104, "\""], "\xe7" => [16, "\""], "\xe8" => [94, "("], "\xe9" => [76, "("], "\xea" => [104, "("], "\xeb" => [16, "("], "\xec" => [94, ")"], "\xed" => [76, ")"], "\xee" => [104, ")"], "\xef" => [16, ")"], "\xf0" => [94, "?"], "\xf1" => [76, "?"], "\xf2" => [104, "?"], "\xf3" => [16, "?"], "\xf4" => [77, "'"], "\xf5" => [18, "'"], "\xf6" => [77, "+"], "\xf7" => [18, "+"], "\xf8" => [77, "|"], "\xf9" => [18, "|"], "\xfa" => [0, "#"], "\xfb" => [0, ">"], "\xfc" => [13, null], "\xfd" => [109, null], "\xfe" => [134, null], "\xff" => [26, null]], ["\x00" => [94, "\x000"], "\x01" => [76, "\x000"], "\x02" => [104, "\x000"], "\x03" => [16, "\x000"], "\x04" => [94, "\x001"], "\x05" => [76, "\x001"], "\x06" => [104, "\x001"], "\x07" => [16, "\x001"], "\x08" => [94, "\x002"], "\t" => [76, "\x002"], "\n" => [104, "\x002"], "\v" => [16, "\x002"], "\f" => [94, "\x00a"], "\r" => [76, "\x00a"], "\x0e" => [104, "\x00a"], "\x0f" => [16, "\x00a"], "\x10" => [94, "\x00c"], "\x11" => [76, "\x00c"], "\x12" => [104, "\x00c"], "\x13" => [16, "\x00c"], "\x14" => [94, "\x00e"], "\x15" => [76, "\x00e"], "\x16" => [104, "\x00e"], "\x17" => [16, "\x00e"], "\x18" => [94, "\x00i"], "\x19" => [76, "\x00i"], "\x1a" => [104, "\x00i"], "\x1b" => [16, "\x00i"], "\x1c" => [94, "\x00o"], "\x1d" => [76, "\x00o"], "\x1e" => [104, "\x00o"], "\x1f" => [16, "\x00o"], " " => [94, "\x00s"], "!" => [76, "\x00s"], "\"" => [104, "\x00s"], "#" => [16, "\x00s"], "\$" => [94, "\x00t"], "%" => [76, "\x00t"], "&" => [104, "\x00t"], "'" => [16, "\x00t"], "(" => [77, "\x00 "], ")" => [18, "\x00 "], "*" => [77, "\x00%"], "+" => [18, "\x00%"], "," => [77, "\x00-"], "-" => [18, "\x00-"], "." => [77, "\x00."], "/" => [18, "\x00."], [77, "\x00/"], [18, "\x00/"], [77, "\x003"], [18, "\x003"], [77, "\x004"], [18, "\x004"], [77, "\x005"], [18, "\x005"], [77, "\x006"], [18, "\x006"], ":" => [77, "\x007"], ";" => [18, "\x007"], "<" => [77, "\x008"], "=" => [18, "\x008"], ">" => [77, "\x009"], "?" => [18, "\x009"], "@" => [77, "\x00="], "A" => [18, "\x00="], "B" => [77, "\x00A"], "C" => [18, "\x00A"], "D" => [77, "\x00_"], "E" => [18, "\x00_"], "F" => [77, "\x00b"], "G" => [18, "\x00b"], "H" => [77, "\x00d"], "I" => [18, "\x00d"], "J" => [77, "\x00f"], "K" => [18, "\x00f"], "L" => [77, "\x00g"], "M" => [18, "\x00g"], "N" => [77, "\x00h"], "O" => [18, "\x00h"], "P" => [77, "\x00l"], "Q" => [18, "\x00l"], "R" => [77, "\x00m"], "S" => [18, "\x00m"], "T" => [77, "\x00n"], "U" => [18, "\x00n"], "V" => [77, "\x00p"], "W" => [18, "\x00p"], "X" => [77, "\x00r"], "Y" => [18, "\x00r"], "Z" => [77, "\x00u"], "[" => [18, "\x00u"], "\\" => [0, "\x00:"], "]" => [0, "\x00B"], "^" => [0, "\x00C"], "_" => [0, "\x00D"], "`" => [0, "\x00E"], "a" => [0, "\x00F"], "b" => [0, "\x00G"], "c" => [0, "\x00H"], "d" => [0, "\x00I"], "e" => [0, "\x00J"], "f" => [0, "\x00K"], "g" => [0, "\x00L"], "h" => [0, "\x00M"], "i" => [0, "\x00N"], "j" => [0, "\x00O"], "k" => [0, "\x00P"], "l" => [0, "\x00Q"], "m" => [0, "\x00R"], "n" => [0, "\x00S"], "o" => [0, "\x00T"], "p" => [0, "\x00U"], "q" => [0, "\x00V"], "r" => [0, "\x00W"], "s" => [0, "\x00Y"], "t" => [0, "\x00j"], "u" => [0, "\x00k"], "v" => [0, "\x00q"], "w" => [0, "\x00v"], "x" => [0, "\x00w"], "y" => [0, "\x00x"], "z" => [0, "\x00y"], "{" => [0, "\x00z"], "|" => [82, "\x00"], "}" => [87, "\x00"], "~" => [130, "\x00"], "" => [9, "\x00"], "\x80" => [94, "\$0"], "\x81" => [76, "\$0"], "\x82" => [104, "\$0"], "\x83" => [16, "\$0"], "\x84" => [94, "\$1"], "\x85" => [76, "\$1"], "\x86" => [104, "\$1"], "\x87" => [16, "\$1"], "\x88" => [94, "\$2"], "\x89" => [76, "\$2"], "\x8a" => [104, "\$2"], "\x8b" => [16, "\$2"], "\x8c" => [94, "\$a"], "\x8d" => [76, "\$a"], "\x8e" => [104, "\$a"], "\x8f" => [16, "\$a"], "\x90" => [94, "\$c"], "\x91" => [76, "\$c"], "\x92" => [104, "\$c"], "\x93" => [16, "\$c"], "\x94" => [94, "\$e"], "\x95" => [76, "\$e"], "\x96" => [104, "\$e"], "\x97" => [16, "\$e"], "\x98" => [94, "\$i"], "\x99" => [76, "\$i"], "\x9a" => [104, "\$i"], "\x9b" => [16, "\$i"], "\x9c" => [94, "\$o"], "\x9d" => [76, "\$o"], "\x9e" => [104, "\$o"], "\x9f" => [16, "\$o"], "\xa0" => [94, "\$s"], "\xa1" => [76, "\$s"], "\xa2" => [104, "\$s"], "\xa3" => [16, "\$s"], "\xa4" => [94, "\$t"], "\xa5" => [76, "\$t"], "\xa6" => [104, "\$t"], "\xa7" => [16, "\$t"], "\xa8" => [77, "\$ "], "\xa9" => [18, "\$ "], "\xaa" => [77, "\$%"], "\xab" => [18, "\$%"], "\xac" => [77, "\$-"], "\xad" => [18, "\$-"], "\xae" => [77, "\$."], "\xaf" => [18, "\$."], "\xb0" => [77, "\$/"], "\xb1" => [18, "\$/"], "\xb2" => [77, "\$3"], "\xb3" => [18, "\$3"], "\xb4" => [77, "\$4"], "\xb5" => [18, "\$4"], "\xb6" => [77, "\$5"], "\xb7" => [18, "\$5"], "\xb8" => [77, "\$6"], "\xb9" => [18, "\$6"], "\xba" => [77, "\$7"], "\xbb" => [18, "\$7"], "\xbc" => [77, "\$8"], "\xbd" => [18, "\$8"], "\xbe" => [77, "\$9"], "\xbf" => [18, "\$9"], "\xc0" => [77, "\$="], "\xc1" => [18, "\$="], "\xc2" => [77, "\$A"], "\xc3" => [18, "\$A"], "\xc4" => [77, "\$_"], "\xc5" => [18, "\$_"], "\xc6" => [77, "\$b"], "\xc7" => [18, "\$b"], "\xc8" => [77, "\$d"], "\xc9" => [18, "\$d"], "\xca" => [77, "\$f"], "\xcb" => [18, "\$f"], "\xcc" => [77, "\$g"], "\xcd" => [18, "\$g"], "\xce" => [77, "\$h"], "\xcf" => [18, "\$h"], "\xd0" => [77, "\$l"], "\xd1" => [18, "\$l"], "\xd2" => [77, "\$m"], "\xd3" => [18, "\$m"], "\xd4" => [77, "\$n"], "\xd5" => [18, "\$n"], "\xd6" => [77, "\$p"], "\xd7" => [18, "\$p"], "\xd8" => [77, "\$r"], "\xd9" => [18, "\$r"], "\xda" => [77, "\$u"], "\xdb" => [18, "\$u"], "\xdc" => [0, "\$:"], "\xdd" => [0, "\$B"], "\xde" => [0, "\$C"], "\xdf" => [0, "\$D"], "\xe0" => [0, "\$E"], "\xe1" => [0, "\$F"], "\xe2" => [0, "\$G"], "\xe3" => [0, "\$H"], "\xe4" => [0, "\$I"], "\xe5" => [0, "\$J"], "\xe6" => [0, "\$K"], "\xe7" => [0, "\$L"], "\xe8" => [0, "\$M"], "\xe9" => [0, "\$N"], "\xea" => [0, "\$O"], "\xeb" => [0, "\$P"], "\xec" => [0, "\$Q"], "\xed" => [0, "\$R"], "\xee" => [0, "\$S"], "\xef" => [0, "\$T"], "\xf0" => [0, "\$U"], "\xf1" => [0, "\$V"], "\xf2" => [0, "\$W"], "\xf3" => [0, "\$Y"], "\xf4" => [0, "\$j"], "\xf5" => [0, "\$k"], "\xf6" => [0, "\$q"], "\xf7" => [0, "\$v"], "\xf8" => [0, "\$w"], "\xf9" => [0, "\$x"], "\xfa" => [0, "\$y"], "\xfb" => [0, "\$z"], "\xfc" => [82, "\$"], "\xfd" => [87, "\$"], "\xfe" => [130, "\$"], "\xff" => [9, "\$"]], ["\x00" => [92, "U"], "\x01" => [95, "U"], "\x02" => [137, "U"], "\x03" => [142, "U"], "\x04" => [150, "U"], "\x05" => [74, "U"], "\x06" => [90, "U"], "\x07" => [98, "U"], "\x08" => [107, "U"], "\t" => [140, "U"], "\n" => [146, "U"], "\v" => [102, "U"], "\f" => [113, "U"], "\r" => [121, "U"], "\x0e" => [128, "U"], "\x0f" => [12, "U"], "\x10" => [92, "V"], "\x11" => [95, "V"], "\x12" => [137, "V"], "\x13" => [142, "V"], "\x14" => [150, "V"], "\x15" => [74, "V"], "\x16" => [90, "V"], "\x17" => [98, "V"], "\x18" => [107, "V"], "\x19" => [140, "V"], "\x1a" => [146, "V"], "\x1b" => [102, "V"], "\x1c" => [113, "V"], "\x1d" => [121, "V"], "\x1e" => [128, "V"], "\x1f" => [12, "V"], " " => [92, "W"], "!" => [95, "W"], "\"" => [137, "W"], "#" => [142, "W"], "\$" => [150, "W"], "%" => [74, "W"], "&" => [90, "W"], "'" => [98, "W"], "(" => [107, "W"], ")" => [140, "W"], "*" => [146, "W"], "+" => [102, "W"], "," => [113, "W"], "-" => [121, "W"], "." => [128, "W"], "/" => [12, "W"], [92, "Y"], [95, "Y"], [137, "Y"], [142, "Y"], [150, "Y"], [74, "Y"], [90, "Y"], [98, "Y"], [107, "Y"], [140, "Y"], ":" => [146, "Y"], ";" => [102, "Y"], "<" => [113, "Y"], "=" => [121, "Y"], ">" => [128, "Y"], "?" => [12, "Y"], "@" => [92, "j"], "A" => [95, "j"], "B" => [137, "j"], "C" => [142, "j"], "D" => [150, "j"], "E" => [74, "j"], "F" => [90, "j"], "G" => [98, "j"], "H" => [107, "j"], "I" => [140, "j"], "J" => [146, "j"], "K" => [102, "j"], "L" => [113, "j"], "M" => [121, "j"], "N" => [128, "j"], "O" => [12, "j"], "P" => [92, "k"], "Q" => [95, "k"], "R" => [137, "k"], "S" => [142, "k"], "T" => [150, "k"], "U" => [74, "k"], "V" => [90, "k"], "W" => [98, "k"], "X" => [107, "k"], "Y" => [140, "k"], "Z" => [146, "k"], "[" => [102, "k"], "\\" => [113, "k"], "]" => [121, "k"], "^" => [128, "k"], "_" => [12, "k"], "`" => [92, "q"], "a" => [95, "q"], "b" => [137, "q"], "c" => [142, "q"], "d" => [150, "q"], "e" => [74, "q"], "f" => [90, "q"], "g" => [98, "q"], "h" => [107, "q"], "i" => [140, "q"], "j" => [146, "q"], "k" => [102, "q"], "l" => [113, "q"], "m" => [121, "q"], "n" => [128, "q"], "o" => [12, "q"], "p" => [92, "v"], "q" => [95, "v"], "r" => [137, "v"], "s" => [142, "v"], "t" => [150, "v"], "u" => [74, "v"], "v" => [90, "v"], "w" => [98, "v"], "x" => [107, "v"], "y" => [140, "v"], "z" => [146, "v"], "{" => [102, "v"], "|" => [113, "v"], "}" => [121, "v"], "~" => [128, "v"], "" => [12, "v"], "\x80" => [92, "w"], "\x81" => [95, "w"], "\x82" => [137, "w"], "\x83" => [142, "w"], "\x84" => [150, "w"], "\x85" => [74, "w"], "\x86" => [90, "w"], "\x87" => [98, "w"], "\x88" => [107, "w"], "\x89" => [140, "w"], "\x8a" => [146, "w"], "\x8b" => [102, "w"], "\x8c" => [113, "w"], "\x8d" => [121, "w"], "\x8e" => [128, "w"], "\x8f" => [12, "w"], "\x90" => [92, "x"], "\x91" => [95, "x"], "\x92" => [137, "x"], "\x93" => [142, "x"], "\x94" => [150, "x"], "\x95" => [74, "x"], "\x96" => [90, "x"], "\x97" => [98, "x"], "\x98" => [107, "x"], "\x99" => [140, "x"], "\x9a" => [146, "x"], "\x9b" => [102, "x"], "\x9c" => [113, "x"], "\x9d" => [121, "x"], "\x9e" => [128, "x"], "\x9f" => [12, "x"], "\xa0" => [92, "y"], "\xa1" => [95, "y"], "\xa2" => [137, "y"], "\xa3" => [142, "y"], "\xa4" => [150, "y"], "\xa5" => [74, "y"], "\xa6" => [90, "y"], "\xa7" => [98, "y"], "\xa8" => [107, "y"], "\xa9" => [140, "y"], "\xaa" => [146, "y"], "\xab" => [102, "y"], "\xac" => [113, "y"], "\xad" => [121, "y"], "\xae" => [128, "y"], "\xaf" => [12, "y"], "\xb0" => [92, "z"], "\xb1" => [95, "z"], "\xb2" => [137, "z"], "\xb3" => [142, "z"], "\xb4" => [150, "z"], "\xb5" => [74, "z"], "\xb6" => [90, "z"], "\xb7" => [98, "z"], "\xb8" => [107, "z"], "\xb9" => [140, "z"], "\xba" => [146, "z"], "\xbb" => [102, "z"], "\xbc" => [113, "z"], "\xbd" => [121, "z"], "\xbe" => [128, "z"], "\xbf" => [12, "z"], "\xc0" => [93, "&"], "\xc1" => [138, "&"], "\xc2" => [75, "&"], "\xc3" => [91, "&"], "\xc4" => [108, "&"], "\xc5" => [103, "&"], "\xc6" => [114, "&"], "\xc7" => [14, "&"], "\xc8" => [93, "*"], "\xc9" => [138, "*"], "\xca" => [75, "*"], "\xcb" => [91, "*"], "\xcc" => [108, "*"], "\xcd" => [103, "*"], "\xce" => [114, "*"], "\xcf" => [14, "*"], "\xd0" => [93, ","], "\xd1" => [138, ","], "\xd2" => [75, ","], "\xd3" => [91, ","], "\xd4" => [108, ","], "\xd5" => [103, ","], "\xd6" => [114, ","], "\xd7" => [14, ","], "\xd8" => [93, ";"], "\xd9" => [138, ";"], "\xda" => [75, ";"], "\xdb" => [91, ";"], "\xdc" => [108, ";"], "\xdd" => [103, ";"], "\xde" => [114, ";"], "\xdf" => [14, ";"], "\xe0" => [93, "X"], "\xe1" => [138, "X"], "\xe2" => [75, "X"], "\xe3" => [91, "X"], "\xe4" => [108, "X"], "\xe5" => [103, "X"], "\xe6" => [114, "X"], "\xe7" => [14, "X"], "\xe8" => [93, "Z"], "\xe9" => [138, "Z"], "\xea" => [75, "Z"], "\xeb" => [91, "Z"], "\xec" => [108, "Z"], "\xed" => [103, "Z"], "\xee" => [114, "Z"], "\xef" => [14, "Z"], "\xf0" => [77, "!"], "\xf1" => [18, "!"], "\xf2" => [77, "\""], "\xf3" => [18, "\""], "\xf4" => [77, "("], "\xf5" => [18, "("], "\xf6" => [77, ")"], "\xf7" => [18, ")"], "\xf8" => [77, "?"], "\xf9" => [18, "?"], "\xfa" => [0, "'"], "\xfb" => [0, "+"], "\xfc" => [0, "|"], "\xfd" => [80, null], "\xfe" => [15, null], "\xff" => [28, null]], ["\x00" => [77, "\x000"], "\x01" => [18, "\x000"], "\x02" => [77, "\x001"], "\x03" => [18, "\x001"], "\x04" => [77, "\x002"], "\x05" => [18, "\x002"], "\x06" => [77, "\x00a"], "\x07" => [18, "\x00a"], "\x08" => [77, "\x00c"], "\t" => [18, "\x00c"], "\n" => [77, "\x00e"], "\v" => [18, "\x00e"], "\f" => [77, "\x00i"], "\r" => [18, "\x00i"], "\x0e" => [77, "\x00o"], "\x0f" => [18, "\x00o"], "\x10" => [77, "\x00s"], "\x11" => [18, "\x00s"], "\x12" => [77, "\x00t"], "\x13" => [18, "\x00t"], "\x14" => [0, "\x00 "], "\x15" => [0, "\x00%"], "\x16" => [0, "\x00-"], "\x17" => [0, "\x00."], "\x18" => [0, "\x00/"], "\x19" => [0, "\x003"], "\x1a" => [0, "\x004"], "\x1b" => [0, "\x005"], "\x1c" => [0, "\x006"], "\x1d" => [0, "\x007"], "\x1e" => [0, "\x008"], "\x1f" => [0, "\x009"], " " => [0, "\x00="], "!" => [0, "\x00A"], "\"" => [0, "\x00_"], "#" => [0, "\x00b"], "\$" => [0, "\x00d"], "%" => [0, "\x00f"], "&" => [0, "\x00g"], "'" => [0, "\x00h"], "(" => [0, "\x00l"], ")" => [0, "\x00m"], "*" => [0, "\x00n"], "+" => [0, "\x00p"], "," => [0, "\x00r"], "-" => [0, "\x00u"], "." => [100, "\x00"], "/" => [110, "\x00"], [111, "\x00"], [115, "\x00"], [116, "\x00"], [118, "\x00"], [119, "\x00"], [122, "\x00"], [123, "\x00"], [125, "\x00"], [126, "\x00"], [129, "\x00"], ":" => [143, "\x00"], ";" => [148, "\x00"], "<" => [151, "\x00"], "=" => [153, "\x00"], ">" => [83, "\x00"], "?" => [10, "\x00"], "@" => [77, "\$0"], "A" => [18, "\$0"], "B" => [77, "\$1"], "C" => [18, "\$1"], "D" => [77, "\$2"], "E" => [18, "\$2"], "F" => [77, "\$a"], "G" => [18, "\$a"], "H" => [77, "\$c"], "I" => [18, "\$c"], "J" => [77, "\$e"], "K" => [18, "\$e"], "L" => [77, "\$i"], "M" => [18, "\$i"], "N" => [77, "\$o"], "O" => [18, "\$o"], "P" => [77, "\$s"], "Q" => [18, "\$s"], "R" => [77, "\$t"], "S" => [18, "\$t"], "T" => [0, "\$ "], "U" => [0, "\$%"], "V" => [0, "\$-"], "W" => [0, "\$."], "X" => [0, "\$/"], "Y" => [0, "\$3"], "Z" => [0, "\$4"], "[" => [0, "\$5"], "\\" => [0, "\$6"], "]" => [0, "\$7"], "^" => [0, "\$8"], "_" => [0, "\$9"], "`" => [0, "\$="], "a" => [0, "\$A"], "b" => [0, "\$_"], "c" => [0, "\$b"], "d" => [0, "\$d"], "e" => [0, "\$f"], "f" => [0, "\$g"], "g" => [0, "\$h"], "h" => [0, "\$l"], "i" => [0, "\$m"], "j" => [0, "\$n"], "k" => [0, "\$p"], "l" => [0, "\$r"], "m" => [0, "\$u"], "n" => [100, "\$"], "o" => [110, "\$"], "p" => [111, "\$"], "q" => [115, "\$"], "r" => [116, "\$"], "s" => [118, "\$"], "t" => [119, "\$"], "u" => [122, "\$"], "v" => [123, "\$"], "w" => [125, "\$"], "x" => [126, "\$"], "y" => [129, "\$"], "z" => [143, "\$"], "{" => [148, "\$"], "|" => [151, "\$"], "}" => [153, "\$"], "~" => [83, "\$"], "" => [10, "\$"], "\x80" => [77, "@0"], "\x81" => [18, "@0"], "\x82" => [77, "@1"], "\x83" => [18, "@1"], "\x84" => [77, "@2"], "\x85" => [18, "@2"], "\x86" => [77, "@a"], "\x87" => [18, "@a"], "\x88" => [77, "@c"], "\x89" => [18, "@c"], "\x8a" => [77, "@e"], "\x8b" => [18, "@e"], "\x8c" => [77, "@i"], "\x8d" => [18, "@i"], "\x8e" => [77, "@o"], "\x8f" => [18, "@o"], "\x90" => [77, "@s"], "\x91" => [18, "@s"], "\x92" => [77, "@t"], "\x93" => [18, "@t"], "\x94" => [0, "@ "], "\x95" => [0, "@%"], "\x96" => [0, "@-"], "\x97" => [0, "@."], "\x98" => [0, "@/"], "\x99" => [0, "@3"], "\x9a" => [0, "@4"], "\x9b" => [0, "@5"], "\x9c" => [0, "@6"], "\x9d" => [0, "@7"], "\x9e" => [0, "@8"], "\x9f" => [0, "@9"], "\xa0" => [0, "@="], "\xa1" => [0, "@A"], "\xa2" => [0, "@_"], "\xa3" => [0, "@b"], "\xa4" => [0, "@d"], "\xa5" => [0, "@f"], "\xa6" => [0, "@g"], "\xa7" => [0, "@h"], "\xa8" => [0, "@l"], "\xa9" => [0, "@m"], "\xaa" => [0, "@n"], "\xab" => [0, "@p"], "\xac" => [0, "@r"], "\xad" => [0, "@u"], "\xae" => [100, "@"], "\xaf" => [110, "@"], "\xb0" => [111, "@"], "\xb1" => [115, "@"], "\xb2" => [116, "@"], "\xb3" => [118, "@"], "\xb4" => [119, "@"], "\xb5" => [122, "@"], "\xb6" => [123, "@"], "\xb7" => [125, "@"], "\xb8" => [126, "@"], "\xb9" => [129, "@"], "\xba" => [143, "@"], "\xbb" => [148, "@"], "\xbc" => [151, "@"], "\xbd" => [153, "@"], "\xbe" => [83, "@"], "\xbf" => [10, "@"], "\xc0" => [77, "[0"], "\xc1" => [18, "[0"], "\xc2" => [77, "[1"], "\xc3" => [18, "[1"], "\xc4" => [77, "[2"], "\xc5" => [18, "[2"], "\xc6" => [77, "[a"], "\xc7" => [18, "[a"], "\xc8" => [77, "[c"], "\xc9" => [18, "[c"], "\xca" => [77, "[e"], "\xcb" => [18, "[e"], "\xcc" => [77, "[i"], "\xcd" => [18, "[i"], "\xce" => [77, "[o"], "\xcf" => [18, "[o"], "\xd0" => [77, "[s"], "\xd1" => [18, "[s"], "\xd2" => [77, "[t"], "\xd3" => [18, "[t"], "\xd4" => [0, "[ "], "\xd5" => [0, "[%"], "\xd6" => [0, "[-"], "\xd7" => [0, "[."], "\xd8" => [0, "[/"], "\xd9" => [0, "[3"], "\xda" => [0, "[4"], "\xdb" => [0, "[5"], "\xdc" => [0, "[6"], "\xdd" => [0, "[7"], "\xde" => [0, "[8"], "\xdf" => [0, "[9"], "\xe0" => [0, "[="], "\xe1" => [0, "[A"], "\xe2" => [0, "[_"], "\xe3" => [0, "[b"], "\xe4" => [0, "[d"], "\xe5" => [0, "[f"], "\xe6" => [0, "[g"], "\xe7" => [0, "[h"], "\xe8" => [0, "[l"], "\xe9" => [0, "[m"], "\xea" => [0, "[n"], "\xeb" => [0, "[p"], "\xec" => [0, "[r"], "\xed" => [0, "[u"], "\xee" => [100, "["], "\xef" => [110, "["], "\xf0" => [111, "["], "\xf1" => [115, "["], "\xf2" => [116, "["], "\xf3" => [118, "["], "\xf4" => [119, "["], "\xf5" => [122, "["], "\xf6" => [123, "["], "\xf7" => [125, "["], "\xf8" => [126, "["], "\xf9" => [129, "["], "\xfa" => [143, "["], "\xfb" => [148, "["], "\xfc" => [151, "["], "\xfd" => [153, "["], "\xfe" => [83, "["], "\xff" => [10, "["]], ["\x00" => [93, "E"], "\x01" => [138, "E"], "\x02" => [75, "E"], "\x03" => [91, "E"], "\x04" => [108, "E"], "\x05" => [103, "E"], "\x06" => [114, "E"], "\x07" => [14, "E"], "\x08" => [93, "F"], "\t" => [138, "F"], "\n" => [75, "F"], "\v" => [91, "F"], "\f" => [108, "F"], "\r" => [103, "F"], "\x0e" => [114, "F"], "\x0f" => [14, "F"], "\x10" => [93, "G"], "\x11" => [138, "G"], "\x12" => [75, "G"], "\x13" => [91, "G"], "\x14" => [108, "G"], "\x15" => [103, "G"], "\x16" => [114, "G"], "\x17" => [14, "G"], "\x18" => [93, "H"], "\x19" => [138, "H"], "\x1a" => [75, "H"], "\x1b" => [91, "H"], "\x1c" => [108, "H"], "\x1d" => [103, "H"], "\x1e" => [114, "H"], "\x1f" => [14, "H"], " " => [93, "I"], "!" => [138, "I"], "\"" => [75, "I"], "#" => [91, "I"], "\$" => [108, "I"], "%" => [103, "I"], "&" => [114, "I"], "'" => [14, "I"], "(" => [93, "J"], ")" => [138, "J"], "*" => [75, "J"], "+" => [91, "J"], "," => [108, "J"], "-" => [103, "J"], "." => [114, "J"], "/" => [14, "J"], [93, "K"], [138, "K"], [75, "K"], [91, "K"], [108, "K"], [103, "K"], [114, "K"], [14, "K"], [93, "L"], [138, "L"], ":" => [75, "L"], ";" => [91, "L"], "<" => [108, "L"], "=" => [103, "L"], ">" => [114, "L"], "?" => [14, "L"], "@" => [93, "M"], "A" => [138, "M"], "B" => [75, "M"], "C" => [91, "M"], "D" => [108, "M"], "E" => [103, "M"], "F" => [114, "M"], "G" => [14, "M"], "H" => [93, "N"], "I" => [138, "N"], "J" => [75, "N"], "K" => [91, "N"], "L" => [108, "N"], "M" => [103, "N"], "N" => [114, "N"], "O" => [14, "N"], "P" => [93, "O"], "Q" => [138, "O"], "R" => [75, "O"], "S" => [91, "O"], "T" => [108, "O"], "U" => [103, "O"], "V" => [114, "O"], "W" => [14, "O"], "X" => [93, "P"], "Y" => [138, "P"], "Z" => [75, "P"], "[" => [91, "P"], "\\" => [108, "P"], "]" => [103, "P"], "^" => [114, "P"], "_" => [14, "P"], "`" => [93, "Q"], "a" => [138, "Q"], "b" => [75, "Q"], "c" => [91, "Q"], "d" => [108, "Q"], "e" => [103, "Q"], "f" => [114, "Q"], "g" => [14, "Q"], "h" => [93, "R"], "i" => [138, "R"], "j" => [75, "R"], "k" => [91, "R"], "l" => [108, "R"], "m" => [103, "R"], "n" => [114, "R"], "o" => [14, "R"], "p" => [93, "S"], "q" => [138, "S"], "r" => [75, "S"], "s" => [91, "S"], "t" => [108, "S"], "u" => [103, "S"], "v" => [114, "S"], "w" => [14, "S"], "x" => [93, "T"], "y" => [138, "T"], "z" => [75, "T"], "{" => [91, "T"], "|" => [108, "T"], "}" => [103, "T"], "~" => [114, "T"], "" => [14, "T"], "\x80" => [93, "U"], "\x81" => [138, "U"], "\x82" => [75, "U"], "\x83" => [91, "U"], "\x84" => [108, "U"], "\x85" => [103, "U"], "\x86" => [114, "U"], "\x87" => [14, "U"], "\x88" => [93, "V"], "\x89" => [138, "V"], "\x8a" => [75, "V"], "\x8b" => [91, "V"], "\x8c" => [108, "V"], "\x8d" => [103, "V"], "\x8e" => [114, "V"], "\x8f" => [14, "V"], "\x90" => [93, "W"], "\x91" => [138, "W"], "\x92" => [75, "W"], "\x93" => [91, "W"], "\x94" => [108, "W"], "\x95" => [103, "W"], "\x96" => [114, "W"], "\x97" => [14, "W"], "\x98" => [93, "Y"], "\x99" => [138, "Y"], "\x9a" => [75, "Y"], "\x9b" => [91, "Y"], "\x9c" => [108, "Y"], "\x9d" => [103, "Y"], "\x9e" => [114, "Y"], "\x9f" => [14, "Y"], "\xa0" => [93, "j"], "\xa1" => [138, "j"], "\xa2" => [75, "j"], "\xa3" => [91, "j"], "\xa4" => [108, "j"], "\xa5" => [103, "j"], "\xa6" => [114, "j"], "\xa7" => [14, "j"], "\xa8" => [93, "k"], "\xa9" => [138, "k"], "\xaa" => [75, "k"], "\xab" => [91, "k"], "\xac" => [108, "k"], "\xad" => [103, "k"], "\xae" => [114, "k"], "\xaf" => [14, "k"], "\xb0" => [93, "q"], "\xb1" => [138, "q"], "\xb2" => [75, "q"], "\xb3" => [91, "q"], "\xb4" => [108, "q"], "\xb5" => [103, "q"], "\xb6" => [114, "q"], "\xb7" => [14, "q"], "\xb8" => [93, "v"], "\xb9" => [138, "v"], "\xba" => [75, "v"], "\xbb" => [91, "v"], "\xbc" => [108, "v"], "\xbd" => [103, "v"], "\xbe" => [114, "v"], "\xbf" => [14, "v"], "\xc0" => [93, "w"], "\xc1" => [138, "w"], "\xc2" => [75, "w"], "\xc3" => [91, "w"], "\xc4" => [108, "w"], "\xc5" => [103, "w"], "\xc6" => [114, "w"], "\xc7" => [14, "w"], "\xc8" => [93, "x"], "\xc9" => [138, "x"], "\xca" => [75, "x"], "\xcb" => [91, "x"], "\xcc" => [108, "x"], "\xcd" => [103, "x"], "\xce" => [114, "x"], "\xcf" => [14, "x"], "\xd0" => [93, "y"], "\xd1" => [138, "y"], "\xd2" => [75, "y"], "\xd3" => [91, "y"], "\xd4" => [108, "y"], "\xd5" => [103, "y"], "\xd6" => [114, "y"], "\xd7" => [14, "y"], "\xd8" => [93, "z"], "\xd9" => [138, "z"], "\xda" => [75, "z"], "\xdb" => [91, "z"], "\xdc" => [108, "z"], "\xdd" => [103, "z"], "\xde" => [114, "z"], "\xdf" => [14, "z"], "\xe0" => [94, "&"], "\xe1" => [76, "&"], "\xe2" => [104, "&"], "\xe3" => [16, "&"], "\xe4" => [94, "*"], "\xe5" => [76, "*"], "\xe6" => [104, "*"], "\xe7" => [16, "*"], "\xe8" => [94, ","], "\xe9" => [76, ","], "\xea" => [104, ","], "\xeb" => [16, ","], "\xec" => [94, ";"], "\xed" => [76, ";"], "\xee" => [104, ";"], "\xef" => [16, ";"], "\xf0" => [94, "X"], "\xf1" => [76, "X"], "\xf2" => [104, "X"], "\xf3" => [16, "X"], "\xf4" => [94, "Z"], "\xf5" => [76, "Z"], "\xf6" => [104, "Z"], "\xf7" => [16, "Z"], "\xf8" => [0, "!"], "\xf9" => [0, "\""], "\xfa" => [0, "("], "\xfb" => [0, ")"], "\xfc" => [0, "?"], "\xfd" => [84, null], "\xfe" => [81, null], "\xff" => [17, null]], ["\x00" => [0, "\x000"], "\x01" => [0, "\x001"], "\x02" => [0, "\x002"], "\x03" => [0, "\x00a"], "\x04" => [0, "\x00c"], "\x05" => [0, "\x00e"], "\x06" => [0, "\x00i"], "\x07" => [0, "\x00o"], "\x08" => [0, "\x00s"], "\t" => [0, "\x00t"], "\n" => [73, "\x00"], "\v" => [88, "\x00"], "\f" => [89, "\x00"], "\r" => [96, "\x00"], "\x0e" => [97, "\x00"], "\x0f" => [99, "\x00"], "\x10" => [106, "\x00"], "\x11" => [136, "\x00"], "\x12" => [139, "\x00"], "\x13" => [141, "\x00"], "\x14" => [145, "\x00"], "\x15" => [147, "\x00"], "\x16" => [149, "\x00"], "\x17" => [101, "\x00"], "\x18" => [112, "\x00"], "\x19" => [117, "\x00"], "\x1a" => [120, "\x00"], "\x1b" => [124, "\x00"], "\x1c" => [127, "\x00"], "\x1d" => [144, "\x00"], "\x1e" => [152, "\x00"], "\x1f" => [11, "\x00"], " " => [0, "\$0"], "!" => [0, "\$1"], "\"" => [0, "\$2"], "#" => [0, "\$a"], "\$" => [0, "\$c"], "%" => [0, "\$e"], "&" => [0, "\$i"], "'" => [0, "\$o"], "(" => [0, "\$s"], ")" => [0, "\$t"], "*" => [73, "\$"], "+" => [88, "\$"], "," => [89, "\$"], "-" => [96, "\$"], "." => [97, "\$"], "/" => [99, "\$"], [106, "\$"], [136, "\$"], [139, "\$"], [141, "\$"], [145, "\$"], [147, "\$"], [149, "\$"], [101, "\$"], [112, "\$"], [117, "\$"], ":" => [120, "\$"], ";" => [124, "\$"], "<" => [127, "\$"], "=" => [144, "\$"], ">" => [152, "\$"], "?" => [11, "\$"], "@" => [0, "@0"], "A" => [0, "@1"], "B" => [0, "@2"], "C" => [0, "@a"], "D" => [0, "@c"], "E" => [0, "@e"], "F" => [0, "@i"], "G" => [0, "@o"], "H" => [0, "@s"], "I" => [0, "@t"], "J" => [73, "@"], "K" => [88, "@"], "L" => [89, "@"], "M" => [96, "@"], "N" => [97, "@"], "O" => [99, "@"], "P" => [106, "@"], "Q" => [136, "@"], "R" => [139, "@"], "S" => [141, "@"], "T" => [145, "@"], "U" => [147, "@"], "V" => [149, "@"], "W" => [101, "@"], "X" => [112, "@"], "Y" => [117, "@"], "Z" => [120, "@"], "[" => [124, "@"], "\\" => [127, "@"], "]" => [144, "@"], "^" => [152, "@"], "_" => [11, "@"], "`" => [0, "[0"], "a" => [0, "[1"], "b" => [0, "[2"], "c" => [0, "[a"], "d" => [0, "[c"], "e" => [0, "[e"], "f" => [0, "[i"], "g" => [0, "[o"], "h" => [0, "[s"], "i" => [0, "[t"], "j" => [73, "["], "k" => [88, "["], "l" => [89, "["], "m" => [96, "["], "n" => [97, "["], "o" => [99, "["], "p" => [106, "["], "q" => [136, "["], "r" => [139, "["], "s" => [141, "["], "t" => [145, "["], "u" => [147, "["], "v" => [149, "["], "w" => [101, "["], "x" => [112, "["], "y" => [117, "["], "z" => [120, "["], "{" => [124, "["], "|" => [127, "["], "}" => [144, "["], "~" => [152, "["], "" => [11, "["], "\x80" => [0, "]0"], "\x81" => [0, "]1"], "\x82" => [0, "]2"], "\x83" => [0, "]a"], "\x84" => [0, "]c"], "\x85" => [0, "]e"], "\x86" => [0, "]i"], "\x87" => [0, "]o"], "\x88" => [0, "]s"], "\x89" => [0, "]t"], "\x8a" => [73, "]"], "\x8b" => [88, "]"], "\x8c" => [89, "]"], "\x8d" => [96, "]"], "\x8e" => [97, "]"], "\x8f" => [99, "]"], "\x90" => [106, "]"], "\x91" => [136, "]"], "\x92" => [139, "]"], "\x93" => [141, "]"], "\x94" => [145, "]"], "\x95" => [147, "]"], "\x96" => [149, "]"], "\x97" => [101, "]"], "\x98" => [112, "]"], "\x99" => [117, "]"], "\x9a" => [120, "]"], "\x9b" => [124, "]"], "\x9c" => [127, "]"], "\x9d" => [144, "]"], "\x9e" => [152, "]"], "\x9f" => [11, "]"], "\xa0" => [0, "~0"], "\xa1" => [0, "~1"], "\xa2" => [0, "~2"], "\xa3" => [0, "~a"], "\xa4" => [0, "~c"], "\xa5" => [0, "~e"], "\xa6" => [0, "~i"], "\xa7" => [0, "~o"], "\xa8" => [0, "~s"], "\xa9" => [0, "~t"], "\xaa" => [73, "~"], "\xab" => [88, "~"], "\xac" => [89, "~"], "\xad" => [96, "~"], "\xae" => [97, "~"], "\xaf" => [99, "~"], "\xb0" => [106, "~"], "\xb1" => [136, "~"], "\xb2" => [139, "~"], "\xb3" => [141, "~"], "\xb4" => [145, "~"], "\xb5" => [147, "~"], "\xb6" => [149, "~"], "\xb7" => [101, "~"], "\xb8" => [112, "~"], "\xb9" => [117, "~"], "\xba" => [120, "~"], "\xbb" => [124, "~"], "\xbc" => [127, "~"], "\xbd" => [144, "~"], "\xbe" => [152, "~"], "\xbf" => [11, "~"], "\xc0" => [92, "^"], "\xc1" => [95, "^"], "\xc2" => [137, "^"], "\xc3" => [142, "^"], "\xc4" => [150, "^"], "\xc5" => [74, "^"], "\xc6" => [90, "^"], "\xc7" => [98, "^"], "\xc8" => [107, "^"], "\xc9" => [140, "^"], "\xca" => [146, "^"], "\xcb" => [102, "^"], "\xcc" => [113, "^"], "\xcd" => [121, "^"], "\xce" => [128, "^"], "\xcf" => [12, "^"], "\xd0" => [92, "}"], "\xd1" => [95, "}"], "\xd2" => [137, "}"], "\xd3" => [142, "}"], "\xd4" => [150, "}"], "\xd5" => [74, "}"], "\xd6" => [90, "}"], "\xd7" => [98, "}"], "\xd8" => [107, "}"], "\xd9" => [140, "}"], "\xda" => [146, "}"], "\xdb" => [102, "}"], "\xdc" => [113, "}"], "\xdd" => [121, "}"], "\xde" => [128, "}"], "\xdf" => [12, "}"], "\xe0" => [93, "<"], "\xe1" => [138, "<"], "\xe2" => [75, "<"], "\xe3" => [91, "<"], "\xe4" => [108, "<"], "\xe5" => [103, "<"], "\xe6" => [114, "<"], "\xe7" => [14, "<"], "\xe8" => [93, "`"], "\xe9" => [138, "`"], "\xea" => [75, "`"], "\xeb" => [91, "`"], "\xec" => [108, "`"], "\xed" => [103, "`"], "\xee" => [114, "`"], "\xef" => [14, "`"], "\xf0" => [93, "{"], "\xf1" => [138, "{"], "\xf2" => [75, "{"], "\xf3" => [91, "{"], "\xf4" => [108, "{"], "\xf5" => [103, "{"], "\xf6" => [114, "{"], "\xf7" => [14, "{"], "\xf8" => [132, null], "\xf9" => [156, null], "\xfa" => [163, null], "\xfb" => [184, null], "\xfc" => [205, null], "\xfd" => [160, null], "\xfe" => [30, null], "\xff" => [39, null]], ["\x00" => [93, "="], "\x01" => [138, "="], "\x02" => [75, "="], "\x03" => [91, "="], "\x04" => [108, "="], "\x05" => [103, "="], "\x06" => [114, "="], "\x07" => [14, "="], "\x08" => [93, "A"], "\t" => [138, "A"], "\n" => [75, "A"], "\v" => [91, "A"], "\f" => [108, "A"], "\r" => [103, "A"], "\x0e" => [114, "A"], "\x0f" => [14, "A"], "\x10" => [93, "_"], "\x11" => [138, "_"], "\x12" => [75, "_"], "\x13" => [91, "_"], "\x14" => [108, "_"], "\x15" => [103, "_"], "\x16" => [114, "_"], "\x17" => [14, "_"], "\x18" => [93, "b"], "\x19" => [138, "b"], "\x1a" => [75, "b"], "\x1b" => [91, "b"], "\x1c" => [108, "b"], "\x1d" => [103, "b"], "\x1e" => [114, "b"], "\x1f" => [14, "b"], " " => [93, "d"], "!" => [138, "d"], "\"" => [75, "d"], "#" => [91, "d"], "\$" => [108, "d"], "%" => [103, "d"], "&" => [114, "d"], "'" => [14, "d"], "(" => [93, "f"], ")" => [138, "f"], "*" => [75, "f"], "+" => [91, "f"], "," => [108, "f"], "-" => [103, "f"], "." => [114, "f"], "/" => [14, "f"], [93, "g"], [138, "g"], [75, "g"], [91, "g"], [108, "g"], [103, "g"], [114, "g"], [14, "g"], [93, "h"], [138, "h"], ":" => [75, "h"], ";" => [91, "h"], "<" => [108, "h"], "=" => [103, "h"], ">" => [114, "h"], "?" => [14, "h"], "@" => [93, "l"], "A" => [138, "l"], "B" => [75, "l"], "C" => [91, "l"], "D" => [108, "l"], "E" => [103, "l"], "F" => [114, "l"], "G" => [14, "l"], "H" => [93, "m"], "I" => [138, "m"], "J" => [75, "m"], "K" => [91, "m"], "L" => [108, "m"], "M" => [103, "m"], "N" => [114, "m"], "O" => [14, "m"], "P" => [93, "n"], "Q" => [138, "n"], "R" => [75, "n"], "S" => [91, "n"], "T" => [108, "n"], "U" => [103, "n"], "V" => [114, "n"], "W" => [14, "n"], "X" => [93, "p"], "Y" => [138, "p"], "Z" => [75, "p"], "[" => [91, "p"], "\\" => [108, "p"], "]" => [103, "p"], "^" => [114, "p"], "_" => [14, "p"], "`" => [93, "r"], "a" => [138, "r"], "b" => [75, "r"], "c" => [91, "r"], "d" => [108, "r"], "e" => [103, "r"], "f" => [114, "r"], "g" => [14, "r"], "h" => [93, "u"], "i" => [138, "u"], "j" => [75, "u"], "k" => [91, "u"], "l" => [108, "u"], "m" => [103, "u"], "n" => [114, "u"], "o" => [14, "u"], "p" => [94, ":"], "q" => [76, ":"], "r" => [104, ":"], "s" => [16, ":"], "t" => [94, "B"], "u" => [76, "B"], "v" => [104, "B"], "w" => [16, "B"], "x" => [94, "C"], "y" => [76, "C"], "z" => [104, "C"], "{" => [16, "C"], "|" => [94, "D"], "}" => [76, "D"], "~" => [104, "D"], "" => [16, "D"], "\x80" => [94, "E"], "\x81" => [76, "E"], "\x82" => [104, "E"], "\x83" => [16, "E"], "\x84" => [94, "F"], "\x85" => [76, "F"], "\x86" => [104, "F"], "\x87" => [16, "F"], "\x88" => [94, "G"], "\x89" => [76, "G"], "\x8a" => [104, "G"], "\x8b" => [16, "G"], "\x8c" => [94, "H"], "\x8d" => [76, "H"], "\x8e" => [104, "H"], "\x8f" => [16, "H"], "\x90" => [94, "I"], "\x91" => [76, "I"], "\x92" => [104, "I"], "\x93" => [16, "I"], "\x94" => [94, "J"], "\x95" => [76, "J"], "\x96" => [104, "J"], "\x97" => [16, "J"], "\x98" => [94, "K"], "\x99" => [76, "K"], "\x9a" => [104, "K"], "\x9b" => [16, "K"], "\x9c" => [94, "L"], "\x9d" => [76, "L"], "\x9e" => [104, "L"], "\x9f" => [16, "L"], "\xa0" => [94, "M"], "\xa1" => [76, "M"], "\xa2" => [104, "M"], "\xa3" => [16, "M"], "\xa4" => [94, "N"], "\xa5" => [76, "N"], "\xa6" => [104, "N"], "\xa7" => [16, "N"], "\xa8" => [94, "O"], "\xa9" => [76, "O"], "\xaa" => [104, "O"], "\xab" => [16, "O"], "\xac" => [94, "P"], "\xad" => [76, "P"], "\xae" => [104, "P"], "\xaf" => [16, "P"], "\xb0" => [94, "Q"], "\xb1" => [76, "Q"], "\xb2" => [104, "Q"], "\xb3" => [16, "Q"], "\xb4" => [94, "R"], "\xb5" => [76, "R"], "\xb6" => [104, "R"], "\xb7" => [16, "R"], "\xb8" => [94, "S"], "\xb9" => [76, "S"], "\xba" => [104, "S"], "\xbb" => [16, "S"], "\xbc" => [94, "T"], "\xbd" => [76, "T"], "\xbe" => [104, "T"], "\xbf" => [16, "T"], "\xc0" => [94, "U"], "\xc1" => [76, "U"], "\xc2" => [104, "U"], "\xc3" => [16, "U"], "\xc4" => [94, "V"], "\xc5" => [76, "V"], "\xc6" => [104, "V"], "\xc7" => [16, "V"], "\xc8" => [94, "W"], "\xc9" => [76, "W"], "\xca" => [104, "W"], "\xcb" => [16, "W"], "\xcc" => [94, "Y"], "\xcd" => [76, "Y"], "\xce" => [104, "Y"], "\xcf" => [16, "Y"], "\xd0" => [94, "j"], "\xd1" => [76, "j"], "\xd2" => [104, "j"], "\xd3" => [16, "j"], "\xd4" => [94, "k"], "\xd5" => [76, "k"], "\xd6" => [104, "k"], "\xd7" => [16, "k"], "\xd8" => [94, "q"], "\xd9" => [76, "q"], "\xda" => [104, "q"], "\xdb" => [16, "q"], "\xdc" => [94, "v"], "\xdd" => [76, "v"], "\xde" => [104, "v"], "\xdf" => [16, "v"], "\xe0" => [94, "w"], "\xe1" => [76, "w"], "\xe2" => [104, "w"], "\xe3" => [16, "w"], "\xe4" => [94, "x"], "\xe5" => [76, "x"], "\xe6" => [104, "x"], "\xe7" => [16, "x"], "\xe8" => [94, "y"], "\xe9" => [76, "y"], "\xea" => [104, "y"], "\xeb" => [16, "y"], "\xec" => [94, "z"], "\xed" => [76, "z"], "\xee" => [104, "z"], "\xef" => [16, "z"], "\xf0" => [77, "&"], "\xf1" => [18, "&"], "\xf2" => [77, "*"], "\xf3" => [18, "*"], "\xf4" => [77, ","], "\xf5" => [18, ","], "\xf6" => [77, ";"], "\xf7" => [18, ";"], "\xf8" => [77, "X"], "\xf9" => [18, "X"], "\xfa" => [77, "Z"], "\xfb" => [18, "Z"], "\xfc" => [79, null], "\xfd" => [86, null], "\xfe" => [85, null], "\xff" => [19, null]], ["\x00" => [77, "|0"], "\x01" => [18, "|0"], "\x02" => [77, "|1"], "\x03" => [18, "|1"], "\x04" => [77, "|2"], "\x05" => [18, "|2"], "\x06" => [77, "|a"], "\x07" => [18, "|a"], "\x08" => [77, "|c"], "\t" => [18, "|c"], "\n" => [77, "|e"], "\v" => [18, "|e"], "\f" => [77, "|i"], "\r" => [18, "|i"], "\x0e" => [77, "|o"], "\x0f" => [18, "|o"], "\x10" => [77, "|s"], "\x11" => [18, "|s"], "\x12" => [77, "|t"], "\x13" => [18, "|t"], "\x14" => [0, "| "], "\x15" => [0, "|%"], "\x16" => [0, "|-"], "\x17" => [0, "|."], "\x18" => [0, "|/"], "\x19" => [0, "|3"], "\x1a" => [0, "|4"], "\x1b" => [0, "|5"], "\x1c" => [0, "|6"], "\x1d" => [0, "|7"], "\x1e" => [0, "|8"], "\x1f" => [0, "|9"], " " => [0, "|="], "!" => [0, "|A"], "\"" => [0, "|_"], "#" => [0, "|b"], "\$" => [0, "|d"], "%" => [0, "|f"], "&" => [0, "|g"], "'" => [0, "|h"], "(" => [0, "|l"], ")" => [0, "|m"], "*" => [0, "|n"], "+" => [0, "|p"], "," => [0, "|r"], "-" => [0, "|u"], "." => [100, "|"], "/" => [110, "|"], [111, "|"], [115, "|"], [116, "|"], [118, "|"], [119, "|"], [122, "|"], [123, "|"], [125, "|"], [126, "|"], [129, "|"], ":" => [143, "|"], ";" => [148, "|"], "<" => [151, "|"], "=" => [153, "|"], ">" => [83, "|"], "?" => [10, "|"], "@" => [0, "#0"], "A" => [0, "#1"], "B" => [0, "#2"], "C" => [0, "#a"], "D" => [0, "#c"], "E" => [0, "#e"], "F" => [0, "#i"], "G" => [0, "#o"], "H" => [0, "#s"], "I" => [0, "#t"], "J" => [73, "#"], "K" => [88, "#"], "L" => [89, "#"], "M" => [96, "#"], "N" => [97, "#"], "O" => [99, "#"], "P" => [106, "#"], "Q" => [136, "#"], "R" => [139, "#"], "S" => [141, "#"], "T" => [145, "#"], "U" => [147, "#"], "V" => [149, "#"], "W" => [101, "#"], "X" => [112, "#"], "Y" => [117, "#"], "Z" => [120, "#"], "[" => [124, "#"], "\\" => [127, "#"], "]" => [144, "#"], "^" => [152, "#"], "_" => [11, "#"], "`" => [0, ">0"], "a" => [0, ">1"], "b" => [0, ">2"], "c" => [0, ">a"], "d" => [0, ">c"], "e" => [0, ">e"], "f" => [0, ">i"], "g" => [0, ">o"], "h" => [0, ">s"], "i" => [0, ">t"], "j" => [73, ">"], "k" => [88, ">"], "l" => [89, ">"], "m" => [96, ">"], "n" => [97, ">"], "o" => [99, ">"], "p" => [106, ">"], "q" => [136, ">"], "r" => [139, ">"], "s" => [141, ">"], "t" => [145, ">"], "u" => [147, ">"], "v" => [149, ">"], "w" => [101, ">"], "x" => [112, ">"], "y" => [117, ">"], "z" => [120, ">"], "{" => [124, ">"], "|" => [127, ">"], "}" => [144, ">"], "~" => [152, ">"], "" => [11, ">"], "\x80" => [92, "\x00"], "\x81" => [95, "\x00"], "\x82" => [137, "\x00"], "\x83" => [142, "\x00"], "\x84" => [150, "\x00"], "\x85" => [74, "\x00"], "\x86" => [90, "\x00"], "\x87" => [98, "\x00"], "\x88" => [107, "\x00"], "\x89" => [140, "\x00"], "\x8a" => [146, "\x00"], "\x8b" => [102, "\x00"], "\x8c" => [113, "\x00"], "\x8d" => [121, "\x00"], "\x8e" => [128, "\x00"], "\x8f" => [12, "\x00"], "\x90" => [92, "\$"], "\x91" => [95, "\$"], "\x92" => [137, "\$"], "\x93" => [142, "\$"], "\x94" => [150, "\$"], "\x95" => [74, "\$"], "\x96" => [90, "\$"], "\x97" => [98, "\$"], "\x98" => [107, "\$"], "\x99" => [140, "\$"], "\x9a" => [146, "\$"], "\x9b" => [102, "\$"], "\x9c" => [113, "\$"], "\x9d" => [121, "\$"], "\x9e" => [128, "\$"], "\x9f" => [12, "\$"], "\xa0" => [92, "@"], "\xa1" => [95, "@"], "\xa2" => [137, "@"], "\xa3" => [142, "@"], "\xa4" => [150, "@"], "\xa5" => [74, "@"], "\xa6" => [90, "@"], "\xa7" => [98, "@"], "\xa8" => [107, "@"], "\xa9" => [140, "@"], "\xaa" => [146, "@"], "\xab" => [102, "@"], "\xac" => [113, "@"], "\xad" => [121, "@"], "\xae" => [128, "@"], "\xaf" => [12, "@"], "\xb0" => [92, "["], "\xb1" => [95, "["], "\xb2" => [137, "["], "\xb3" => [142, "["], "\xb4" => [150, "["], "\xb5" => [74, "["], "\xb6" => [90, "["], "\xb7" => [98, "["], "\xb8" => [107, "["], "\xb9" => [140, "["], "\xba" => [146, "["], "\xbb" => [102, "["], "\xbc" => [113, "["], "\xbd" => [121, "["], "\xbe" => [128, "["], "\xbf" => [12, "["], "\xc0" => [92, "]"], "\xc1" => [95, "]"], "\xc2" => [137, "]"], "\xc3" => [142, "]"], "\xc4" => [150, "]"], "\xc5" => [74, "]"], "\xc6" => [90, "]"], "\xc7" => [98, "]"], "\xc8" => [107, "]"], "\xc9" => [140, "]"], "\xca" => [146, "]"], "\xcb" => [102, "]"], "\xcc" => [113, "]"], "\xcd" => [121, "]"], "\xce" => [128, "]"], "\xcf" => [12, "]"], "\xd0" => [92, "~"], "\xd1" => [95, "~"], "\xd2" => [137, "~"], "\xd3" => [142, "~"], "\xd4" => [150, "~"], "\xd5" => [74, "~"], "\xd6" => [90, "~"], "\xd7" => [98, "~"], "\xd8" => [107, "~"], "\xd9" => [140, "~"], "\xda" => [146, "~"], "\xdb" => [102, "~"], "\xdc" => [113, "~"], "\xdd" => [121, "~"], "\xde" => [128, "~"], "\xdf" => [12, "~"], "\xe0" => [93, "^"], "\xe1" => [138, "^"], "\xe2" => [75, "^"], "\xe3" => [91, "^"], "\xe4" => [108, "^"], "\xe5" => [103, "^"], "\xe6" => [114, "^"], "\xe7" => [14, "^"], "\xe8" => [93, "}"], "\xe9" => [138, "}"], "\xea" => [75, "}"], "\xeb" => [91, "}"], "\xec" => [108, "}"], "\xed" => [103, "}"], "\xee" => [114, "}"], "\xef" => [14, "}"], "\xf0" => [94, "<"], "\xf1" => [76, "<"], "\xf2" => [104, "<"], "\xf3" => [16, "<"], "\xf4" => [94, "`"], "\xf5" => [76, "`"], "\xf6" => [104, "`"], "\xf7" => [16, "`"], "\xf8" => [94, "{"], "\xf9" => [76, "{"], "\xfa" => [104, "{"], "\xfb" => [16, "{"], "\xfc" => [133, null], "\xfd" => [164, null], "\xfe" => [161, null], "\xff" => [31, null]], ["\x00" => [93, "\xb0"], "\x01" => [138, "\xb0"], "\x02" => [75, "\xb0"], "\x03" => [91, "\xb0"], "\x04" => [108, "\xb0"], "\x05" => [103, "\xb0"], "\x06" => [114, "\xb0"], "\x07" => [14, "\xb0"], "\x08" => [93, "\xb1"], "\t" => [138, "\xb1"], "\n" => [75, "\xb1"], "\v" => [91, "\xb1"], "\f" => [108, "\xb1"], "\r" => [103, "\xb1"], "\x0e" => [114, "\xb1"], "\x0f" => [14, "\xb1"], "\x10" => [93, "\xb3"], "\x11" => [138, "\xb3"], "\x12" => [75, "\xb3"], "\x13" => [91, "\xb3"], "\x14" => [108, "\xb3"], "\x15" => [103, "\xb3"], "\x16" => [114, "\xb3"], "\x17" => [14, "\xb3"], "\x18" => [93, "\xd1"], "\x19" => [138, "\xd1"], "\x1a" => [75, "\xd1"], "\x1b" => [91, "\xd1"], "\x1c" => [108, "\xd1"], "\x1d" => [103, "\xd1"], "\x1e" => [114, "\xd1"], "\x1f" => [14, "\xd1"], " " => [93, "\xd8"], "!" => [138, "\xd8"], "\"" => [75, "\xd8"], "#" => [91, "\xd8"], "\$" => [108, "\xd8"], "%" => [103, "\xd8"], "&" => [114, "\xd8"], "'" => [14, "\xd8"], "(" => [93, "\xd9"], ")" => [138, "\xd9"], "*" => [75, "\xd9"], "+" => [91, "\xd9"], "," => [108, "\xd9"], "-" => [103, "\xd9"], "." => [114, "\xd9"], "/" => [14, "\xd9"], [93, "\xe3"], [138, "\xe3"], [75, "\xe3"], [91, "\xe3"], [108, "\xe3"], [103, "\xe3"], [114, "\xe3"], [14, "\xe3"], [93, "\xe5"], [138, "\xe5"], ":" => [75, "\xe5"], ";" => [91, "\xe5"], "<" => [108, "\xe5"], "=" => [103, "\xe5"], ">" => [114, "\xe5"], "?" => [14, "\xe5"], "@" => [93, "\xe6"], "A" => [138, "\xe6"], "B" => [75, "\xe6"], "C" => [91, "\xe6"], "D" => [108, "\xe6"], "E" => [103, "\xe6"], "F" => [114, "\xe6"], "G" => [14, "\xe6"], "H" => [94, "\x81"], "I" => [76, "\x81"], "J" => [104, "\x81"], "K" => [16, "\x81"], "L" => [94, "\x84"], "M" => [76, "\x84"], "N" => [104, "\x84"], "O" => [16, "\x84"], "P" => [94, "\x85"], "Q" => [76, "\x85"], "R" => [104, "\x85"], "S" => [16, "\x85"], "T" => [94, "\x86"], "U" => [76, "\x86"], "V" => [104, "\x86"], "W" => [16, "\x86"], "X" => [94, "\x88"], "Y" => [76, "\x88"], "Z" => [104, "\x88"], "[" => [16, "\x88"], "\\" => [94, "\x92"], "]" => [76, "\x92"], "^" => [104, "\x92"], "_" => [16, "\x92"], "`" => [94, "\x9a"], "a" => [76, "\x9a"], "b" => [104, "\x9a"], "c" => [16, "\x9a"], "d" => [94, "\x9c"], "e" => [76, "\x9c"], "f" => [104, "\x9c"], "g" => [16, "\x9c"], "h" => [94, "\xa0"], "i" => [76, "\xa0"], "j" => [104, "\xa0"], "k" => [16, "\xa0"], "l" => [94, "\xa3"], "m" => [76, "\xa3"], "n" => [104, "\xa3"], "o" => [16, "\xa3"], "p" => [94, "\xa4"], "q" => [76, "\xa4"], "r" => [104, "\xa4"], "s" => [16, "\xa4"], "t" => [94, "\xa9"], "u" => [76, "\xa9"], "v" => [104, "\xa9"], "w" => [16, "\xa9"], "x" => [94, "\xaa"], "y" => [76, "\xaa"], "z" => [104, "\xaa"], "{" => [16, "\xaa"], "|" => [94, "\xad"], "}" => [76, "\xad"], "~" => [104, "\xad"], "" => [16, "\xad"], "\x80" => [94, "\xb2"], "\x81" => [76, "\xb2"], "\x82" => [104, "\xb2"], "\x83" => [16, "\xb2"], "\x84" => [94, "\xb5"], "\x85" => [76, "\xb5"], "\x86" => [104, "\xb5"], "\x87" => [16, "\xb5"], "\x88" => [94, "\xb9"], "\x89" => [76, "\xb9"], "\x8a" => [104, "\xb9"], "\x8b" => [16, "\xb9"], "\x8c" => [94, "\xba"], "\x8d" => [76, "\xba"], "\x8e" => [104, "\xba"], "\x8f" => [16, "\xba"], "\x90" => [94, "\xbb"], "\x91" => [76, "\xbb"], "\x92" => [104, "\xbb"], "\x93" => [16, "\xbb"], "\x94" => [94, "\xbd"], "\x95" => [76, "\xbd"], "\x96" => [104, "\xbd"], "\x97" => [16, "\xbd"], "\x98" => [94, "\xbe"], "\x99" => [76, "\xbe"], "\x9a" => [104, "\xbe"], "\x9b" => [16, "\xbe"], "\x9c" => [94, "\xc4"], "\x9d" => [76, "\xc4"], "\x9e" => [104, "\xc4"], "\x9f" => [16, "\xc4"], "\xa0" => [94, "\xc6"], "\xa1" => [76, "\xc6"], "\xa2" => [104, "\xc6"], "\xa3" => [16, "\xc6"], "\xa4" => [94, "\xe4"], "\xa5" => [76, "\xe4"], "\xa6" => [104, "\xe4"], "\xa7" => [16, "\xe4"], "\xa8" => [94, "\xe8"], "\xa9" => [76, "\xe8"], "\xaa" => [104, "\xe8"], "\xab" => [16, "\xe8"], "\xac" => [94, "\xe9"], "\xad" => [76, "\xe9"], "\xae" => [104, "\xe9"], "\xaf" => [16, "\xe9"], "\xb0" => [77, "\x01"], "\xb1" => [18, "\x01"], "\xb2" => [77, "\x87"], "\xb3" => [18, "\x87"], "\xb4" => [77, "\x89"], "\xb5" => [18, "\x89"], "\xb6" => [77, "\x8a"], "\xb7" => [18, "\x8a"], "\xb8" => [77, "\x8b"], "\xb9" => [18, "\x8b"], "\xba" => [77, "\x8c"], "\xbb" => [18, "\x8c"], "\xbc" => [77, "\x8d"], "\xbd" => [18, "\x8d"], "\xbe" => [77, "\x8f"], "\xbf" => [18, "\x8f"], "\xc0" => [77, "\x93"], "\xc1" => [18, "\x93"], "\xc2" => [77, "\x95"], "\xc3" => [18, "\x95"], "\xc4" => [77, "\x96"], "\xc5" => [18, "\x96"], "\xc6" => [77, "\x97"], "\xc7" => [18, "\x97"], "\xc8" => [77, "\x98"], "\xc9" => [18, "\x98"], "\xca" => [77, "\x9b"], "\xcb" => [18, "\x9b"], "\xcc" => [77, "\x9d"], "\xcd" => [18, "\x9d"], "\xce" => [77, "\x9e"], "\xcf" => [18, "\x9e"], "\xd0" => [77, "\xa5"], "\xd1" => [18, "\xa5"], "\xd2" => [77, "\xa6"], "\xd3" => [18, "\xa6"], "\xd4" => [77, "\xa8"], "\xd5" => [18, "\xa8"], "\xd6" => [77, "\xae"], "\xd7" => [18, "\xae"], "\xd8" => [77, "\xaf"], "\xd9" => [18, "\xaf"], "\xda" => [77, "\xb4"], "\xdb" => [18, "\xb4"], "\xdc" => [77, "\xb6"], "\xdd" => [18, "\xb6"], "\xde" => [77, "\xb7"], "\xdf" => [18, "\xb7"], "\xe0" => [77, "\xbc"], "\xe1" => [18, "\xbc"], "\xe2" => [77, "\xbf"], "\xe3" => [18, "\xbf"], "\xe4" => [77, "\xc5"], "\xe5" => [18, "\xc5"], "\xe6" => [77, "\xe7"], "\xe7" => [18, "\xe7"], "\xe8" => [77, "\xef"], "\xe9" => [18, "\xef"], "\xea" => [0, "\t"], "\xeb" => [0, "\x8e"], "\xec" => [0, "\x90"], "\xed" => [0, "\x91"], "\xee" => [0, "\x94"], "\xef" => [0, "\x9f"], "\xf0" => [0, "\xab"], "\xf1" => [0, "\xce"], "\xf2" => [0, "\xd7"], "\xf3" => [0, "\xe1"], "\xf4" => [0, "\xec"], "\xf5" => [0, "\xed"], "\xf6" => [225, null], "\xf7" => [251, null], "\xf8" => [218, null], "\xf9" => [229, null], "\xfa" => [244, null], "\xfb" => [231, null], "\xfc" => [236, null], "\xfd" => [256, null], "\xfe" => [32, null], "\xff" => [52, null]], ["\x00" => [92, "\\"], "\x01" => [95, "\\"], "\x02" => [137, "\\"], "\x03" => [142, "\\"], "\x04" => [150, "\\"], "\x05" => [74, "\\"], "\x06" => [90, "\\"], "\x07" => [98, "\\"], "\x08" => [107, "\\"], "\t" => [140, "\\"], "\n" => [146, "\\"], "\v" => [102, "\\"], "\f" => [113, "\\"], "\r" => [121, "\\"], "\x0e" => [128, "\\"], "\x0f" => [12, "\\"], "\x10" => [92, "\xc3"], "\x11" => [95, "\xc3"], "\x12" => [137, "\xc3"], "\x13" => [142, "\xc3"], "\x14" => [150, "\xc3"], "\x15" => [74, "\xc3"], "\x16" => [90, "\xc3"], "\x17" => [98, "\xc3"], "\x18" => [107, "\xc3"], "\x19" => [140, "\xc3"], "\x1a" => [146, "\xc3"], "\x1b" => [102, "\xc3"], "\x1c" => [113, "\xc3"], "\x1d" => [121, "\xc3"], "\x1e" => [128, "\xc3"], "\x1f" => [12, "\xc3"], " " => [92, "\xd0"], "!" => [95, "\xd0"], "\"" => [137, "\xd0"], "#" => [142, "\xd0"], "\$" => [150, "\xd0"], "%" => [74, "\xd0"], "&" => [90, "\xd0"], "'" => [98, "\xd0"], "(" => [107, "\xd0"], ")" => [140, "\xd0"], "*" => [146, "\xd0"], "+" => [102, "\xd0"], "," => [113, "\xd0"], "-" => [121, "\xd0"], "." => [128, "\xd0"], "/" => [12, "\xd0"], [93, "\x80"], [138, "\x80"], [75, "\x80"], [91, "\x80"], [108, "\x80"], [103, "\x80"], [114, "\x80"], [14, "\x80"], [93, "\x82"], [138, "\x82"], ":" => [75, "\x82"], ";" => [91, "\x82"], "<" => [108, "\x82"], "=" => [103, "\x82"], ">" => [114, "\x82"], "?" => [14, "\x82"], "@" => [93, "\x83"], "A" => [138, "\x83"], "B" => [75, "\x83"], "C" => [91, "\x83"], "D" => [108, "\x83"], "E" => [103, "\x83"], "F" => [114, "\x83"], "G" => [14, "\x83"], "H" => [93, "\xa2"], "I" => [138, "\xa2"], "J" => [75, "\xa2"], "K" => [91, "\xa2"], "L" => [108, "\xa2"], "M" => [103, "\xa2"], "N" => [114, "\xa2"], "O" => [14, "\xa2"], "P" => [93, "\xb8"], "Q" => [138, "\xb8"], "R" => [75, "\xb8"], "S" => [91, "\xb8"], "T" => [108, "\xb8"], "U" => [103, "\xb8"], "V" => [114, "\xb8"], "W" => [14, "\xb8"], "X" => [93, "\xc2"], "Y" => [138, "\xc2"], "Z" => [75, "\xc2"], "[" => [91, "\xc2"], "\\" => [108, "\xc2"], "]" => [103, "\xc2"], "^" => [114, "\xc2"], "_" => [14, "\xc2"], "`" => [93, "\xe0"], "a" => [138, "\xe0"], "b" => [75, "\xe0"], "c" => [91, "\xe0"], "d" => [108, "\xe0"], "e" => [103, "\xe0"], "f" => [114, "\xe0"], "g" => [14, "\xe0"], "h" => [93, "\xe2"], "i" => [138, "\xe2"], "j" => [75, "\xe2"], "k" => [91, "\xe2"], "l" => [108, "\xe2"], "m" => [103, "\xe2"], "n" => [114, "\xe2"], "o" => [14, "\xe2"], "p" => [94, "\x99"], "q" => [76, "\x99"], "r" => [104, "\x99"], "s" => [16, "\x99"], "t" => [94, "\xa1"], "u" => [76, "\xa1"], "v" => [104, "\xa1"], "w" => [16, "\xa1"], "x" => [94, "\xa7"], "y" => [76, "\xa7"], "z" => [104, "\xa7"], "{" => [16, "\xa7"], "|" => [94, "\xac"], "}" => [76, "\xac"], "~" => [104, "\xac"], "" => [16, "\xac"], "\x80" => [94, "\xb0"], "\x81" => [76, "\xb0"], "\x82" => [104, "\xb0"], "\x83" => [16, "\xb0"], "\x84" => [94, "\xb1"], "\x85" => [76, "\xb1"], "\x86" => [104, "\xb1"], "\x87" => [16, "\xb1"], "\x88" => [94, "\xb3"], "\x89" => [76, "\xb3"], "\x8a" => [104, "\xb3"], "\x8b" => [16, "\xb3"], "\x8c" => [94, "\xd1"], "\x8d" => [76, "\xd1"], "\x8e" => [104, "\xd1"], "\x8f" => [16, "\xd1"], "\x90" => [94, "\xd8"], "\x91" => [76, "\xd8"], "\x92" => [104, "\xd8"], "\x93" => [16, "\xd8"], "\x94" => [94, "\xd9"], "\x95" => [76, "\xd9"], "\x96" => [104, "\xd9"], "\x97" => [16, "\xd9"], "\x98" => [94, "\xe3"], "\x99" => [76, "\xe3"], "\x9a" => [104, "\xe3"], "\x9b" => [16, "\xe3"], "\x9c" => [94, "\xe5"], "\x9d" => [76, "\xe5"], "\x9e" => [104, "\xe5"], "\x9f" => [16, "\xe5"], "\xa0" => [94, "\xe6"], "\xa1" => [76, "\xe6"], "\xa2" => [104, "\xe6"], "\xa3" => [16, "\xe6"], "\xa4" => [77, "\x81"], "\xa5" => [18, "\x81"], "\xa6" => [77, "\x84"], "\xa7" => [18, "\x84"], "\xa8" => [77, "\x85"], "\xa9" => [18, "\x85"], "\xaa" => [77, "\x86"], "\xab" => [18, "\x86"], "\xac" => [77, "\x88"], "\xad" => [18, "\x88"], "\xae" => [77, "\x92"], "\xaf" => [18, "\x92"], "\xb0" => [77, "\x9a"], "\xb1" => [18, "\x9a"], "\xb2" => [77, "\x9c"], "\xb3" => [18, "\x9c"], "\xb4" => [77, "\xa0"], "\xb5" => [18, "\xa0"], "\xb6" => [77, "\xa3"], "\xb7" => [18, "\xa3"], "\xb8" => [77, "\xa4"], "\xb9" => [18, "\xa4"], "\xba" => [77, "\xa9"], "\xbb" => [18, "\xa9"], "\xbc" => [77, "\xaa"], "\xbd" => [18, "\xaa"], "\xbe" => [77, "\xad"], "\xbf" => [18, "\xad"], "\xc0" => [77, "\xb2"], "\xc1" => [18, "\xb2"], "\xc2" => [77, "\xb5"], "\xc3" => [18, "\xb5"], "\xc4" => [77, "\xb9"], "\xc5" => [18, "\xb9"], "\xc6" => [77, "\xba"], "\xc7" => [18, "\xba"], "\xc8" => [77, "\xbb"], "\xc9" => [18, "\xbb"], "\xca" => [77, "\xbd"], "\xcb" => [18, "\xbd"], "\xcc" => [77, "\xbe"], "\xcd" => [18, "\xbe"], "\xce" => [77, "\xc4"], "\xcf" => [18, "\xc4"], "\xd0" => [77, "\xc6"], "\xd1" => [18, "\xc6"], "\xd2" => [77, "\xe4"], "\xd3" => [18, "\xe4"], "\xd4" => [77, "\xe8"], "\xd5" => [18, "\xe8"], "\xd6" => [77, "\xe9"], "\xd7" => [18, "\xe9"], "\xd8" => [0, "\x01"], "\xd9" => [0, "\x87"], "\xda" => [0, "\x89"], "\xdb" => [0, "\x8a"], "\xdc" => [0, "\x8b"], "\xdd" => [0, "\x8c"], "\xde" => [0, "\x8d"], "\xdf" => [0, "\x8f"], "\xe0" => [0, "\x93"], "\xe1" => [0, "\x95"], "\xe2" => [0, "\x96"], "\xe3" => [0, "\x97"], "\xe4" => [0, "\x98"], "\xe5" => [0, "\x9b"], "\xe6" => [0, "\x9d"], "\xe7" => [0, "\x9e"], "\xe8" => [0, "\xa5"], "\xe9" => [0, "\xa6"], "\xea" => [0, "\xa8"], "\xeb" => [0, "\xae"], "\xec" => [0, "\xaf"], "\xed" => [0, "\xb4"], "\xee" => [0, "\xb6"], "\xef" => [0, "\xb7"], "\xf0" => [0, "\xbc"], "\xf1" => [0, "\xbf"], "\xf2" => [0, "\xc5"], "\xf3" => [0, "\xe7"], "\xf4" => [0, "\xef"], "\xf5" => [48, null], "\xf6" => [172, null], "\xf7" => [178, null], "\xf8" => [198, null], "\xf9" => [241, null], "\xfa" => [252, null], "\xfb" => [226, null], "\xfc" => [219, null], "\xfd" => [232, null], "\xfe" => [237, null], "\xff" => [33, null]], ["\x00" => [94, "{0"], "\x01" => [76, "{0"], "\x02" => [104, "{0"], "\x03" => [16, "{0"], "\x04" => [94, "{1"], "\x05" => [76, "{1"], "\x06" => [104, "{1"], "\x07" => [16, "{1"], "\x08" => [94, "{2"], "\t" => [76, "{2"], "\n" => [104, "{2"], "\v" => [16, "{2"], "\f" => [94, "{a"], "\r" => [76, "{a"], "\x0e" => [104, "{a"], "\x0f" => [16, "{a"], "\x10" => [94, "{c"], "\x11" => [76, "{c"], "\x12" => [104, "{c"], "\x13" => [16, "{c"], "\x14" => [94, "{e"], "\x15" => [76, "{e"], "\x16" => [104, "{e"], "\x17" => [16, "{e"], "\x18" => [94, "{i"], "\x19" => [76, "{i"], "\x1a" => [104, "{i"], "\x1b" => [16, "{i"], "\x1c" => [94, "{o"], "\x1d" => [76, "{o"], "\x1e" => [104, "{o"], "\x1f" => [16, "{o"], " " => [94, "{s"], "!" => [76, "{s"], "\"" => [104, "{s"], "#" => [16, "{s"], "\$" => [94, "{t"], "%" => [76, "{t"], "&" => [104, "{t"], "'" => [16, "{t"], "(" => [77, "{ "], ")" => [18, "{ "], "*" => [77, "{%"], "+" => [18, "{%"], "," => [77, "{-"], "-" => [18, "{-"], "." => [77, "{."], "/" => [18, "{."], [77, "{/"], [18, "{/"], [77, "{3"], [18, "{3"], [77, "{4"], [18, "{4"], [77, "{5"], [18, "{5"], [77, "{6"], [18, "{6"], ":" => [77, "{7"], ";" => [18, "{7"], "<" => [77, "{8"], "=" => [18, "{8"], ">" => [77, "{9"], "?" => [18, "{9"], "@" => [77, "{="], "A" => [18, "{="], "B" => [77, "{A"], "C" => [18, "{A"], "D" => [77, "{_"], "E" => [18, "{_"], "F" => [77, "{b"], "G" => [18, "{b"], "H" => [77, "{d"], "I" => [18, "{d"], "J" => [77, "{f"], "K" => [18, "{f"], "L" => [77, "{g"], "M" => [18, "{g"], "N" => [77, "{h"], "O" => [18, "{h"], "P" => [77, "{l"], "Q" => [18, "{l"], "R" => [77, "{m"], "S" => [18, "{m"], "T" => [77, "{n"], "U" => [18, "{n"], "V" => [77, "{p"], "W" => [18, "{p"], "X" => [77, "{r"], "Y" => [18, "{r"], "Z" => [77, "{u"], "[" => [18, "{u"], "\\" => [0, "{:"], "]" => [0, "{B"], "^" => [0, "{C"], "_" => [0, "{D"], "`" => [0, "{E"], "a" => [0, "{F"], "b" => [0, "{G"], "c" => [0, "{H"], "d" => [0, "{I"], "e" => [0, "{J"], "f" => [0, "{K"], "g" => [0, "{L"], "h" => [0, "{M"], "i" => [0, "{N"], "j" => [0, "{O"], "k" => [0, "{P"], "l" => [0, "{Q"], "m" => [0, "{R"], "n" => [0, "{S"], "o" => [0, "{T"], "p" => [0, "{U"], "q" => [0, "{V"], "r" => [0, "{W"], "s" => [0, "{Y"], "t" => [0, "{j"], "u" => [0, "{k"], "v" => [0, "{q"], "w" => [0, "{v"], "x" => [0, "{w"], "y" => [0, "{x"], "z" => [0, "{y"], "{" => [0, "{z"], "|" => [82, "{"], "}" => [87, "{"], "~" => [130, "{"], "" => [9, "{"], "\x80" => [93, "\\"], "\x81" => [138, "\\"], "\x82" => [75, "\\"], "\x83" => [91, "\\"], "\x84" => [108, "\\"], "\x85" => [103, "\\"], "\x86" => [114, "\\"], "\x87" => [14, "\\"], "\x88" => [93, "\xc3"], "\x89" => [138, "\xc3"], "\x8a" => [75, "\xc3"], "\x8b" => [91, "\xc3"], "\x8c" => [108, "\xc3"], "\x8d" => [103, "\xc3"], "\x8e" => [114, "\xc3"], "\x8f" => [14, "\xc3"], "\x90" => [93, "\xd0"], "\x91" => [138, "\xd0"], "\x92" => [75, "\xd0"], "\x93" => [91, "\xd0"], "\x94" => [108, "\xd0"], "\x95" => [103, "\xd0"], "\x96" => [114, "\xd0"], "\x97" => [14, "\xd0"], "\x98" => [94, "\x80"], "\x99" => [76, "\x80"], "\x9a" => [104, "\x80"], "\x9b" => [16, "\x80"], "\x9c" => [94, "\x82"], "\x9d" => [76, "\x82"], "\x9e" => [104, "\x82"], "\x9f" => [16, "\x82"], "\xa0" => [94, "\x83"], "\xa1" => [76, "\x83"], "\xa2" => [104, "\x83"], "\xa3" => [16, "\x83"], "\xa4" => [94, "\xa2"], "\xa5" => [76, "\xa2"], "\xa6" => [104, "\xa2"], "\xa7" => [16, "\xa2"], "\xa8" => [94, "\xb8"], "\xa9" => [76, "\xb8"], "\xaa" => [104, "\xb8"], "\xab" => [16, "\xb8"], "\xac" => [94, "\xc2"], "\xad" => [76, "\xc2"], "\xae" => [104, "\xc2"], "\xaf" => [16, "\xc2"], "\xb0" => [94, "\xe0"], "\xb1" => [76, "\xe0"], "\xb2" => [104, "\xe0"], "\xb3" => [16, "\xe0"], "\xb4" => [94, "\xe2"], "\xb5" => [76, "\xe2"], "\xb6" => [104, "\xe2"], "\xb7" => [16, "\xe2"], "\xb8" => [77, "\x99"], "\xb9" => [18, "\x99"], "\xba" => [77, "\xa1"], "\xbb" => [18, "\xa1"], "\xbc" => [77, "\xa7"], "\xbd" => [18, "\xa7"], "\xbe" => [77, "\xac"], "\xbf" => [18, "\xac"], "\xc0" => [77, "\xb0"], "\xc1" => [18, "\xb0"], "\xc2" => [77, "\xb1"], "\xc3" => [18, "\xb1"], "\xc4" => [77, "\xb3"], "\xc5" => [18, "\xb3"], "\xc6" => [77, "\xd1"], "\xc7" => [18, "\xd1"], "\xc8" => [77, "\xd8"], "\xc9" => [18, "\xd8"], "\xca" => [77, "\xd9"], "\xcb" => [18, "\xd9"], "\xcc" => [77, "\xe3"], "\xcd" => [18, "\xe3"], "\xce" => [77, "\xe5"], "\xcf" => [18, "\xe5"], "\xd0" => [77, "\xe6"], "\xd1" => [18, "\xe6"], "\xd2" => [0, "\x81"], "\xd3" => [0, "\x84"], "\xd4" => [0, "\x85"], "\xd5" => [0, "\x86"], "\xd6" => [0, "\x88"], "\xd7" => [0, "\x92"], "\xd8" => [0, "\x9a"], "\xd9" => [0, "\x9c"], "\xda" => [0, "\xa0"], "\xdb" => [0, "\xa3"], "\xdc" => [0, "\xa4"], "\xdd" => [0, "\xa9"], "\xde" => [0, "\xaa"], "\xdf" => [0, "\xad"], "\xe0" => [0, "\xb2"], "\xe1" => [0, "\xb5"], "\xe2" => [0, "\xb9"], "\xe3" => [0, "\xba"], "\xe4" => [0, "\xbb"], "\xe5" => [0, "\xbd"], "\xe6" => [0, "\xbe"], "\xe7" => [0, "\xc4"], "\xe8" => [0, "\xc6"], "\xe9" => [0, "\xe4"], "\xea" => [0, "\xe8"], "\xeb" => [0, "\xe9"], "\xec" => [23, null], "\xed" => [168, null], "\xee" => [169, null], "\xef" => [171, null], "\xf0" => [174, null], "\xf1" => [179, null], "\xf2" => [180, null], "\xf3" => [188, null], "\xf4" => [192, null], "\xf5" => [196, null], "\xf6" => [201, null], "\xf7" => [210, null], "\xf8" => [215, null], "\xf9" => [222, null], "\xfa" => [49, null], "\xfb" => [173, null], "\xfc" => [199, null], "\xfd" => [227, null], "\xfe" => [220, null], "\xff" => [34, null]], ["\x00" => [94, "\x010"], "\x01" => [76, "\x010"], "\x02" => [104, "\x010"], "\x03" => [16, "\x010"], "\x04" => [94, "\x011"], "\x05" => [76, "\x011"], "\x06" => [104, "\x011"], "\x07" => [16, "\x011"], "\x08" => [94, "\x012"], "\t" => [76, "\x012"], "\n" => [104, "\x012"], "\v" => [16, "\x012"], "\f" => [94, "\x01a"], "\r" => [76, "\x01a"], "\x0e" => [104, "\x01a"], "\x0f" => [16, "\x01a"], "\x10" => [94, "\x01c"], "\x11" => [76, "\x01c"], "\x12" => [104, "\x01c"], "\x13" => [16, "\x01c"], "\x14" => [94, "\x01e"], "\x15" => [76, "\x01e"], "\x16" => [104, "\x01e"], "\x17" => [16, "\x01e"], "\x18" => [94, "\x01i"], "\x19" => [76, "\x01i"], "\x1a" => [104, "\x01i"], "\x1b" => [16, "\x01i"], "\x1c" => [94, "\x01o"], "\x1d" => [76, "\x01o"], "\x1e" => [104, "\x01o"], "\x1f" => [16, "\x01o"], " " => [94, "\x01s"], "!" => [76, "\x01s"], "\"" => [104, "\x01s"], "#" => [16, "\x01s"], "\$" => [94, "\x01t"], "%" => [76, "\x01t"], "&" => [104, "\x01t"], "'" => [16, "\x01t"], "(" => [77, "\x01 "], ")" => [18, "\x01 "], "*" => [77, "\x01%"], "+" => [18, "\x01%"], "," => [77, "\x01-"], "-" => [18, "\x01-"], "." => [77, "\x01."], "/" => [18, "\x01."], [77, "\x01/"], [18, "\x01/"], [77, "\x013"], [18, "\x013"], [77, "\x014"], [18, "\x014"], [77, "\x015"], [18, "\x015"], [77, "\x016"], [18, "\x016"], ":" => [77, "\x017"], ";" => [18, "\x017"], "<" => [77, "\x018"], "=" => [18, "\x018"], ">" => [77, "\x019"], "?" => [18, "\x019"], "@" => [77, "\x01="], "A" => [18, "\x01="], "B" => [77, "\x01A"], "C" => [18, "\x01A"], "D" => [77, "\x01_"], "E" => [18, "\x01_"], "F" => [77, "\x01b"], "G" => [18, "\x01b"], "H" => [77, "\x01d"], "I" => [18, "\x01d"], "J" => [77, "\x01f"], "K" => [18, "\x01f"], "L" => [77, "\x01g"], "M" => [18, "\x01g"], "N" => [77, "\x01h"], "O" => [18, "\x01h"], "P" => [77, "\x01l"], "Q" => [18, "\x01l"], "R" => [77, "\x01m"], "S" => [18, "\x01m"], "T" => [77, "\x01n"], "U" => [18, "\x01n"], "V" => [77, "\x01p"], "W" => [18, "\x01p"], "X" => [77, "\x01r"], "Y" => [18, "\x01r"], "Z" => [77, "\x01u"], "[" => [18, "\x01u"], "\\" => [0, "\x01:"], "]" => [0, "\x01B"], "^" => [0, "\x01C"], "_" => [0, "\x01D"], "`" => [0, "\x01E"], "a" => [0, "\x01F"], "b" => [0, "\x01G"], "c" => [0, "\x01H"], "d" => [0, "\x01I"], "e" => [0, "\x01J"], "f" => [0, "\x01K"], "g" => [0, "\x01L"], "h" => [0, "\x01M"], "i" => [0, "\x01N"], "j" => [0, "\x01O"], "k" => [0, "\x01P"], "l" => [0, "\x01Q"], "m" => [0, "\x01R"], "n" => [0, "\x01S"], "o" => [0, "\x01T"], "p" => [0, "\x01U"], "q" => [0, "\x01V"], "r" => [0, "\x01W"], "s" => [0, "\x01Y"], "t" => [0, "\x01j"], "u" => [0, "\x01k"], "v" => [0, "\x01q"], "w" => [0, "\x01v"], "x" => [0, "\x01w"], "y" => [0, "\x01x"], "z" => [0, "\x01y"], "{" => [0, "\x01z"], "|" => [82, "\x01"], "}" => [87, "\x01"], "~" => [130, "\x01"], "" => [9, "\x01"], "\x80" => [94, "\x870"], "\x81" => [76, "\x870"], "\x82" => [104, "\x870"], "\x83" => [16, "\x870"], "\x84" => [94, "\x871"], "\x85" => [76, "\x871"], "\x86" => [104, "\x871"], "\x87" => [16, "\x871"], "\x88" => [94, "\x872"], "\x89" => [76, "\x872"], "\x8a" => [104, "\x872"], "\x8b" => [16, "\x872"], "\x8c" => [94, "\x87a"], "\x8d" => [76, "\x87a"], "\x8e" => [104, "\x87a"], "\x8f" => [16, "\x87a"], "\x90" => [94, "\x87c"], "\x91" => [76, "\x87c"], "\x92" => [104, "\x87c"], "\x93" => [16, "\x87c"], "\x94" => [94, "\x87e"], "\x95" => [76, "\x87e"], "\x96" => [104, "\x87e"], "\x97" => [16, "\x87e"], "\x98" => [94, "\x87i"], "\x99" => [76, "\x87i"], "\x9a" => [104, "\x87i"], "\x9b" => [16, "\x87i"], "\x9c" => [94, "\x87o"], "\x9d" => [76, "\x87o"], "\x9e" => [104, "\x87o"], "\x9f" => [16, "\x87o"], "\xa0" => [94, "\x87s"], "\xa1" => [76, "\x87s"], "\xa2" => [104, "\x87s"], "\xa3" => [16, "\x87s"], "\xa4" => [94, "\x87t"], "\xa5" => [76, "\x87t"], "\xa6" => [104, "\x87t"], "\xa7" => [16, "\x87t"], "\xa8" => [77, "\x87 "], "\xa9" => [18, "\x87 "], "\xaa" => [77, "\x87%"], "\xab" => [18, "\x87%"], "\xac" => [77, "\x87-"], "\xad" => [18, "\x87-"], "\xae" => [77, "\x87."], "\xaf" => [18, "\x87."], "\xb0" => [77, "\x87/"], "\xb1" => [18, "\x87/"], "\xb2" => [77, "\x873"], "\xb3" => [18, "\x873"], "\xb4" => [77, "\x874"], "\xb5" => [18, "\x874"], "\xb6" => [77, "\x875"], "\xb7" => [18, "\x875"], "\xb8" => [77, "\x876"], "\xb9" => [18, "\x876"], "\xba" => [77, "\x877"], "\xbb" => [18, "\x877"], "\xbc" => [77, "\x878"], "\xbd" => [18, "\x878"], "\xbe" => [77, "\x879"], "\xbf" => [18, "\x879"], "\xc0" => [77, "\x87="], "\xc1" => [18, "\x87="], "\xc2" => [77, "\x87A"], "\xc3" => [18, "\x87A"], "\xc4" => [77, "\x87_"], "\xc5" => [18, "\x87_"], "\xc6" => [77, "\x87b"], "\xc7" => [18, "\x87b"], "\xc8" => [77, "\x87d"], "\xc9" => [18, "\x87d"], "\xca" => [77, "\x87f"], "\xcb" => [18, "\x87f"], "\xcc" => [77, "\x87g"], "\xcd" => [18, "\x87g"], "\xce" => [77, "\x87h"], "\xcf" => [18, "\x87h"], "\xd0" => [77, "\x87l"], "\xd1" => [18, "\x87l"], "\xd2" => [77, "\x87m"], "\xd3" => [18, "\x87m"], "\xd4" => [77, "\x87n"], "\xd5" => [18, "\x87n"], "\xd6" => [77, "\x87p"], "\xd7" => [18, "\x87p"], "\xd8" => [77, "\x87r"], "\xd9" => [18, "\x87r"], "\xda" => [77, "\x87u"], "\xdb" => [18, "\x87u"], "\xdc" => [0, "\x87:"], "\xdd" => [0, "\x87B"], "\xde" => [0, "\x87C"], "\xdf" => [0, "\x87D"], "\xe0" => [0, "\x87E"], "\xe1" => [0, "\x87F"], "\xe2" => [0, "\x87G"], "\xe3" => [0, "\x87H"], "\xe4" => [0, "\x87I"], "\xe5" => [0, "\x87J"], "\xe6" => [0, "\x87K"], "\xe7" => [0, "\x87L"], "\xe8" => [0, "\x87M"], "\xe9" => [0, "\x87N"], "\xea" => [0, "\x87O"], "\xeb" => [0, "\x87P"], "\xec" => [0, "\x87Q"], "\xed" => [0, "\x87R"], "\xee" => [0, "\x87S"], "\xef" => [0, "\x87T"], "\xf0" => [0, "\x87U"], "\xf1" => [0, "\x87V"], "\xf2" => [0, "\x87W"], "\xf3" => [0, "\x87Y"], "\xf4" => [0, "\x87j"], "\xf5" => [0, "\x87k"], "\xf6" => [0, "\x87q"], "\xf7" => [0, "\x87v"], "\xf8" => [0, "\x87w"], "\xf9" => [0, "\x87x"], "\xfa" => [0, "\x87y"], "\xfb" => [0, "\x87z"], "\xfc" => [82, "\x87"], "\xfd" => [87, "\x87"], "\xfe" => [130, "\x87"], "\xff" => [9, "\x87"]], ["\x00" => [77, "<0"], "\x01" => [18, "<0"], "\x02" => [77, "<1"], "\x03" => [18, "<1"], "\x04" => [77, "<2"], "\x05" => [18, "<2"], "\x06" => [77, "<a"], "\x07" => [18, "<a"], "\x08" => [77, "<c"], "\t" => [18, "<c"], "\n" => [77, "<e"], "\v" => [18, "<e"], "\f" => [77, "<i"], "\r" => [18, "<i"], "\x0e" => [77, "<o"], "\x0f" => [18, "<o"], "\x10" => [77, "<s"], "\x11" => [18, "<s"], "\x12" => [77, "<t"], "\x13" => [18, "<t"], "\x14" => [0, "< "], "\x15" => [0, "<%"], "\x16" => [0, "<-"], "\x17" => [0, "<."], "\x18" => [0, "</"], "\x19" => [0, "<3"], "\x1a" => [0, "<4"], "\x1b" => [0, "<5"], "\x1c" => [0, "<6"], "\x1d" => [0, "<7"], "\x1e" => [0, "<8"], "\x1f" => [0, "<9"], " " => [0, "<="], "!" => [0, "<A"], "\"" => [0, "<_"], "#" => [0, "<b"], "\$" => [0, "<d"], "%" => [0, "<f"], "&" => [0, "<g"], "'" => [0, "<h"], "(" => [0, "<l"], ")" => [0, "<m"], "*" => [0, "<n"], "+" => [0, "<p"], "," => [0, "<r"], "-" => [0, "<u"], "." => [100, "<"], "/" => [110, "<"], [111, "<"], [115, "<"], [116, "<"], [118, "<"], [119, "<"], [122, "<"], [123, "<"], [125, "<"], [126, "<"], [129, "<"], ":" => [143, "<"], ";" => [148, "<"], "<" => [151, "<"], "=" => [153, "<"], ">" => [83, "<"], "?" => [10, "<"], "@" => [77, "`0"], "A" => [18, "`0"], "B" => [77, "`1"], "C" => [18, "`1"], "D" => [77, "`2"], "E" => [18, "`2"], "F" => [77, "`a"], "G" => [18, "`a"], "H" => [77, "`c"], "I" => [18, "`c"], "J" => [77, "`e"], "K" => [18, "`e"], "L" => [77, "`i"], "M" => [18, "`i"], "N" => [77, "`o"], "O" => [18, "`o"], "P" => [77, "`s"], "Q" => [18, "`s"], "R" => [77, "`t"], "S" => [18, "`t"], "T" => [0, "` "], "U" => [0, "`%"], "V" => [0, "`-"], "W" => [0, "`."], "X" => [0, "`/"], "Y" => [0, "`3"], "Z" => [0, "`4"], "[" => [0, "`5"], "\\" => [0, "`6"], "]" => [0, "`7"], "^" => [0, "`8"], "_" => [0, "`9"], "`" => [0, "`="], "a" => [0, "`A"], "b" => [0, "`_"], "c" => [0, "`b"], "d" => [0, "`d"], "e" => [0, "`f"], "f" => [0, "`g"], "g" => [0, "`h"], "h" => [0, "`l"], "i" => [0, "`m"], "j" => [0, "`n"], "k" => [0, "`p"], "l" => [0, "`r"], "m" => [0, "`u"], "n" => [100, "`"], "o" => [110, "`"], "p" => [111, "`"], "q" => [115, "`"], "r" => [116, "`"], "s" => [118, "`"], "t" => [119, "`"], "u" => [122, "`"], "v" => [123, "`"], "w" => [125, "`"], "x" => [126, "`"], "y" => [129, "`"], "z" => [143, "`"], "{" => [148, "`"], "|" => [151, "`"], "}" => [153, "`"], "~" => [83, "`"], "" => [10, "`"], "\x80" => [77, "{0"], "\x81" => [18, "{0"], "\x82" => [77, "{1"], "\x83" => [18, "{1"], "\x84" => [77, "{2"], "\x85" => [18, "{2"], "\x86" => [77, "{a"], "\x87" => [18, "{a"], "\x88" => [77, "{c"], "\x89" => [18, "{c"], "\x8a" => [77, "{e"], "\x8b" => [18, "{e"], "\x8c" => [77, "{i"], "\x8d" => [18, "{i"], "\x8e" => [77, "{o"], "\x8f" => [18, "{o"], "\x90" => [77, "{s"], "\x91" => [18, "{s"], "\x92" => [77, "{t"], "\x93" => [18, "{t"], "\x94" => [0, "{ "], "\x95" => [0, "{%"], "\x96" => [0, "{-"], "\x97" => [0, "{."], "\x98" => [0, "{/"], "\x99" => [0, "{3"], "\x9a" => [0, "{4"], "\x9b" => [0, "{5"], "\x9c" => [0, "{6"], "\x9d" => [0, "{7"], "\x9e" => [0, "{8"], "\x9f" => [0, "{9"], "\xa0" => [0, "{="], "\xa1" => [0, "{A"], "\xa2" => [0, "{_"], "\xa3" => [0, "{b"], "\xa4" => [0, "{d"], "\xa5" => [0, "{f"], "\xa6" => [0, "{g"], "\xa7" => [0, "{h"], "\xa8" => [0, "{l"], "\xa9" => [0, "{m"], "\xaa" => [0, "{n"], "\xab" => [0, "{p"], "\xac" => [0, "{r"], "\xad" => [0, "{u"], "\xae" => [100, "{"], "\xaf" => [110, "{"], "\xb0" => [111, "{"], "\xb1" => [115, "{"], "\xb2" => [116, "{"], "\xb3" => [118, "{"], "\xb4" => [119, "{"], "\xb5" => [122, "{"], "\xb6" => [123, "{"], "\xb7" => [125, "{"], "\xb8" => [126, "{"], "\xb9" => [129, "{"], "\xba" => [143, "{"], "\xbb" => [148, "{"], "\xbc" => [151, "{"], "\xbd" => [153, "{"], "\xbe" => [83, "{"], "\xbf" => [10, "{"], "\xc0" => [94, "\\"], "\xc1" => [76, "\\"], "\xc2" => [104, "\\"], "\xc3" => [16, "\\"], "\xc4" => [94, "\xc3"], "\xc5" => [76, "\xc3"], "\xc6" => [104, "\xc3"], "\xc7" => [16, "\xc3"], "\xc8" => [94, "\xd0"], "\xc9" => [76, "\xd0"], "\xca" => [104, "\xd0"], "\xcb" => [16, "\xd0"], "\xcc" => [77, "\x80"], "\xcd" => [18, "\x80"], "\xce" => [77, "\x82"], "\xcf" => [18, "\x82"], "\xd0" => [77, "\x83"], "\xd1" => [18, "\x83"], "\xd2" => [77, "\xa2"], "\xd3" => [18, "\xa2"], "\xd4" => [77, "\xb8"], "\xd5" => [18, "\xb8"], "\xd6" => [77, "\xc2"], "\xd7" => [18, "\xc2"], "\xd8" => [77, "\xe0"], "\xd9" => [18, "\xe0"], "\xda" => [77, "\xe2"], "\xdb" => [18, "\xe2"], "\xdc" => [0, "\x99"], "\xdd" => [0, "\xa1"], "\xde" => [0, "\xa7"], "\xdf" => [0, "\xac"], "\xe0" => [0, "\xb0"], "\xe1" => [0, "\xb1"], "\xe2" => [0, "\xb3"], "\xe3" => [0, "\xd1"], "\xe4" => [0, "\xd8"], "\xe5" => [0, "\xd9"], "\xe6" => [0, "\xe3"], "\xe7" => [0, "\xe5"], "\xe8" => [0, "\xe6"], "\xe9" => [157, null], "\xea" => [165, null], "\xeb" => [167, null], "\xec" => [185, null], "\xed" => [189, null], "\xee" => [190, null], "\xef" => [197, null], "\xf0" => [206, null], "\xf1" => [212, null], "\xf2" => [213, null], "\xf3" => [217, null], "\xf4" => [223, null], "\xf5" => [250, null], "\xf6" => [25, null], "\xf7" => [170, null], "\xf8" => [175, null], "\xf9" => [181, null], "\xfa" => [193, null], "\xfb" => [202, null], "\xfc" => [216, null], "\xfd" => [50, null], "\xfe" => [200, null], "\xff" => [35, null]], ["\x00" => [77, "\x010"], "\x01" => [18, "\x010"], "\x02" => [77, "\x011"], "\x03" => [18, "\x011"], "\x04" => [77, "\x012"], "\x05" => [18, "\x012"], "\x06" => [77, "\x01a"], "\x07" => [18, "\x01a"], "\x08" => [77, "\x01c"], "\t" => [18, "\x01c"], "\n" => [77, "\x01e"], "\v" => [18, "\x01e"], "\f" => [77, "\x01i"], "\r" => [18, "\x01i"], "\x0e" => [77, "\x01o"], "\x0f" => [18, "\x01o"], "\x10" => [77, "\x01s"], "\x11" => [18, "\x01s"], "\x12" => [77, "\x01t"], "\x13" => [18, "\x01t"], "\x14" => [0, "\x01 "], "\x15" => [0, "\x01%"], "\x16" => [0, "\x01-"], "\x17" => [0, "\x01."], "\x18" => [0, "\x01/"], "\x19" => [0, "\x013"], "\x1a" => [0, "\x014"], "\x1b" => [0, "\x015"], "\x1c" => [0, "\x016"], "\x1d" => [0, "\x017"], "\x1e" => [0, "\x018"], "\x1f" => [0, "\x019"], " " => [0, "\x01="], "!" => [0, "\x01A"], "\"" => [0, "\x01_"], "#" => [0, "\x01b"], "\$" => [0, "\x01d"], "%" => [0, "\x01f"], "&" => [0, "\x01g"], "'" => [0, "\x01h"], "(" => [0, "\x01l"], ")" => [0, "\x01m"], "*" => [0, "\x01n"], "+" => [0, "\x01p"], "," => [0, "\x01r"], "-" => [0, "\x01u"], "." => [100, "\x01"], "/" => [110, "\x01"], [111, "\x01"], [115, "\x01"], [116, "\x01"], [118, "\x01"], [119, "\x01"], [122, "\x01"], [123, "\x01"], [125, "\x01"], [126, "\x01"], [129, "\x01"], ":" => [143, "\x01"], ";" => [148, "\x01"], "<" => [151, "\x01"], "=" => [153, "\x01"], ">" => [83, "\x01"], "?" => [10, "\x01"], "@" => [77, "\x870"], "A" => [18, "\x870"], "B" => [77, "\x871"], "C" => [18, "\x871"], "D" => [77, "\x872"], "E" => [18, "\x872"], "F" => [77, "\x87a"], "G" => [18, "\x87a"], "H" => [77, "\x87c"], "I" => [18, "\x87c"], "J" => [77, "\x87e"], "K" => [18, "\x87e"], "L" => [77, "\x87i"], "M" => [18, "\x87i"], "N" => [77, "\x87o"], "O" => [18, "\x87o"], "P" => [77, "\x87s"], "Q" => [18, "\x87s"], "R" => [77, "\x87t"], "S" => [18, "\x87t"], "T" => [0, "\x87 "], "U" => [0, "\x87%"], "V" => [0, "\x87-"], "W" => [0, "\x87."], "X" => [0, "\x87/"], "Y" => [0, "\x873"], "Z" => [0, "\x874"], "[" => [0, "\x875"], "\\" => [0, "\x876"], "]" => [0, "\x877"], "^" => [0, "\x878"], "_" => [0, "\x879"], "`" => [0, "\x87="], "a" => [0, "\x87A"], "b" => [0, "\x87_"], "c" => [0, "\x87b"], "d" => [0, "\x87d"], "e" => [0, "\x87f"], "f" => [0, "\x87g"], "g" => [0, "\x87h"], "h" => [0, "\x87l"], "i" => [0, "\x87m"], "j" => [0, "\x87n"], "k" => [0, "\x87p"], "l" => [0, "\x87r"], "m" => [0, "\x87u"], "n" => [100, "\x87"], "o" => [110, "\x87"], "p" => [111, "\x87"], "q" => [115, "\x87"], "r" => [116, "\x87"], "s" => [118, "\x87"], "t" => [119, "\x87"], "u" => [122, "\x87"], "v" => [123, "\x87"], "w" => [125, "\x87"], "x" => [126, "\x87"], "y" => [129, "\x87"], "z" => [143, "\x87"], "{" => [148, "\x87"], "|" => [151, "\x87"], "}" => [153, "\x87"], "~" => [83, "\x87"], "" => [10, "\x87"], "\x80" => [77, "\x890"], "\x81" => [18, "\x890"], "\x82" => [77, "\x891"], "\x83" => [18, "\x891"], "\x84" => [77, "\x892"], "\x85" => [18, "\x892"], "\x86" => [77, "\x89a"], "\x87" => [18, "\x89a"], "\x88" => [77, "\x89c"], "\x89" => [18, "\x89c"], "\x8a" => [77, "\x89e"], "\x8b" => [18, "\x89e"], "\x8c" => [77, "\x89i"], "\x8d" => [18, "\x89i"], "\x8e" => [77, "\x89o"], "\x8f" => [18, "\x89o"], "\x90" => [77, "\x89s"], "\x91" => [18, "\x89s"], "\x92" => [77, "\x89t"], "\x93" => [18, "\x89t"], "\x94" => [0, "\x89 "], "\x95" => [0, "\x89%"], "\x96" => [0, "\x89-"], "\x97" => [0, "\x89."], "\x98" => [0, "\x89/"], "\x99" => [0, "\x893"], "\x9a" => [0, "\x894"], "\x9b" => [0, "\x895"], "\x9c" => [0, "\x896"], "\x9d" => [0, "\x897"], "\x9e" => [0, "\x898"], "\x9f" => [0, "\x899"], "\xa0" => [0, "\x89="], "\xa1" => [0, "\x89A"], "\xa2" => [0, "\x89_"], "\xa3" => [0, "\x89b"], "\xa4" => [0, "\x89d"], "\xa5" => [0, "\x89f"], "\xa6" => [0, "\x89g"], "\xa7" => [0, "\x89h"], "\xa8" => [0, "\x89l"], "\xa9" => [0, "\x89m"], "\xaa" => [0, "\x89n"], "\xab" => [0, "\x89p"], "\xac" => [0, "\x89r"], "\xad" => [0, "\x89u"], "\xae" => [100, "\x89"], "\xaf" => [110, "\x89"], "\xb0" => [111, "\x89"], "\xb1" => [115, "\x89"], "\xb2" => [116, "\x89"], "\xb3" => [118, "\x89"], "\xb4" => [119, "\x89"], "\xb5" => [122, "\x89"], "\xb6" => [123, "\x89"], "\xb7" => [125, "\x89"], "\xb8" => [126, "\x89"], "\xb9" => [129, "\x89"], "\xba" => [143, "\x89"], "\xbb" => [148, "\x89"], "\xbc" => [151, "\x89"], "\xbd" => [153, "\x89"], "\xbe" => [83, "\x89"], "\xbf" => [10, "\x89"], "\xc0" => [77, "\x8a0"], "\xc1" => [18, "\x8a0"], "\xc2" => [77, "\x8a1"], "\xc3" => [18, "\x8a1"], "\xc4" => [77, "\x8a2"], "\xc5" => [18, "\x8a2"], "\xc6" => [77, "\x8aa"], "\xc7" => [18, "\x8aa"], "\xc8" => [77, "\x8ac"], "\xc9" => [18, "\x8ac"], "\xca" => [77, "\x8ae"], "\xcb" => [18, "\x8ae"], "\xcc" => [77, "\x8ai"], "\xcd" => [18, "\x8ai"], "\xce" => [77, "\x8ao"], "\xcf" => [18, "\x8ao"], "\xd0" => [77, "\x8as"], "\xd1" => [18, "\x8as"], "\xd2" => [77, "\x8at"], "\xd3" => [18, "\x8at"], "\xd4" => [0, "\x8a "], "\xd5" => [0, "\x8a%"], "\xd6" => [0, "\x8a-"], "\xd7" => [0, "\x8a."], "\xd8" => [0, "\x8a/"], "\xd9" => [0, "\x8a3"], "\xda" => [0, "\x8a4"], "\xdb" => [0, "\x8a5"], "\xdc" => [0, "\x8a6"], "\xdd" => [0, "\x8a7"], "\xde" => [0, "\x8a8"], "\xdf" => [0, "\x8a9"], "\xe0" => [0, "\x8a="], "\xe1" => [0, "\x8aA"], "\xe2" => [0, "\x8a_"], "\xe3" => [0, "\x8ab"], "\xe4" => [0, "\x8ad"], "\xe5" => [0, "\x8af"], "\xe6" => [0, "\x8ag"], "\xe7" => [0, "\x8ah"], "\xe8" => [0, "\x8al"], "\xe9" => [0, "\x8am"], "\xea" => [0, "\x8an"], "\xeb" => [0, "\x8ap"], "\xec" => [0, "\x8ar"], "\xed" => [0, "\x8au"], "\xee" => [100, "\x8a"], "\xef" => [110, "\x8a"], "\xf0" => [111, "\x8a"], "\xf1" => [115, "\x8a"], "\xf2" => [116, "\x8a"], "\xf3" => [118, "\x8a"], "\xf4" => [119, "\x8a"], "\xf5" => [122, "\x8a"], "\xf6" => [123, "\x8a"], "\xf7" => [125, "\x8a"], "\xf8" => [126, "\x8a"], "\xf9" => [129, "\x8a"], "\xfa" => [143, "\x8a"], "\xfb" => [148, "\x8a"], "\xfc" => [151, "\x8a"], "\xfd" => [153, "\x8a"], "\xfe" => [83, "\x8a"], "\xff" => [10, "\x8a"]], ["\x00" => [77, "^0"], "\x01" => [18, "^0"], "\x02" => [77, "^1"], "\x03" => [18, "^1"], "\x04" => [77, "^2"], "\x05" => [18, "^2"], "\x06" => [77, "^a"], "\x07" => [18, "^a"], "\x08" => [77, "^c"], "\t" => [18, "^c"], "\n" => [77, "^e"], "\v" => [18, "^e"], "\f" => [77, "^i"], "\r" => [18, "^i"], "\x0e" => [77, "^o"], "\x0f" => [18, "^o"], "\x10" => [77, "^s"], "\x11" => [18, "^s"], "\x12" => [77, "^t"], "\x13" => [18, "^t"], "\x14" => [0, "^ "], "\x15" => [0, "^%"], "\x16" => [0, "^-"], "\x17" => [0, "^."], "\x18" => [0, "^/"], "\x19" => [0, "^3"], "\x1a" => [0, "^4"], "\x1b" => [0, "^5"], "\x1c" => [0, "^6"], "\x1d" => [0, "^7"], "\x1e" => [0, "^8"], "\x1f" => [0, "^9"], " " => [0, "^="], "!" => [0, "^A"], "\"" => [0, "^_"], "#" => [0, "^b"], "\$" => [0, "^d"], "%" => [0, "^f"], "&" => [0, "^g"], "'" => [0, "^h"], "(" => [0, "^l"], ")" => [0, "^m"], "*" => [0, "^n"], "+" => [0, "^p"], "," => [0, "^r"], "-" => [0, "^u"], "." => [100, "^"], "/" => [110, "^"], [111, "^"], [115, "^"], [116, "^"], [118, "^"], [119, "^"], [122, "^"], [123, "^"], [125, "^"], [126, "^"], [129, "^"], ":" => [143, "^"], ";" => [148, "^"], "<" => [151, "^"], "=" => [153, "^"], ">" => [83, "^"], "?" => [10, "^"], "@" => [77, "}0"], "A" => [18, "}0"], "B" => [77, "}1"], "C" => [18, "}1"], "D" => [77, "}2"], "E" => [18, "}2"], "F" => [77, "}a"], "G" => [18, "}a"], "H" => [77, "}c"], "I" => [18, "}c"], "J" => [77, "}e"], "K" => [18, "}e"], "L" => [77, "}i"], "M" => [18, "}i"], "N" => [77, "}o"], "O" => [18, "}o"], "P" => [77, "}s"], "Q" => [18, "}s"], "R" => [77, "}t"], "S" => [18, "}t"], "T" => [0, "} "], "U" => [0, "}%"], "V" => [0, "}-"], "W" => [0, "}."], "X" => [0, "}/"], "Y" => [0, "}3"], "Z" => [0, "}4"], "[" => [0, "}5"], "\\" => [0, "}6"], "]" => [0, "}7"], "^" => [0, "}8"], "_" => [0, "}9"], "`" => [0, "}="], "a" => [0, "}A"], "b" => [0, "}_"], "c" => [0, "}b"], "d" => [0, "}d"], "e" => [0, "}f"], "f" => [0, "}g"], "g" => [0, "}h"], "h" => [0, "}l"], "i" => [0, "}m"], "j" => [0, "}n"], "k" => [0, "}p"], "l" => [0, "}r"], "m" => [0, "}u"], "n" => [100, "}"], "o" => [110, "}"], "p" => [111, "}"], "q" => [115, "}"], "r" => [116, "}"], "s" => [118, "}"], "t" => [119, "}"], "u" => [122, "}"], "v" => [123, "}"], "w" => [125, "}"], "x" => [126, "}"], "y" => [129, "}"], "z" => [143, "}"], "{" => [148, "}"], "|" => [151, "}"], "}" => [153, "}"], "~" => [83, "}"], "" => [10, "}"], "\x80" => [0, "<0"], "\x81" => [0, "<1"], "\x82" => [0, "<2"], "\x83" => [0, "<a"], "\x84" => [0, "<c"], "\x85" => [0, "<e"], "\x86" => [0, "<i"], "\x87" => [0, "<o"], "\x88" => [0, "<s"], "\x89" => [0, "<t"], "\x8a" => [73, "<"], "\x8b" => [88, "<"], "\x8c" => [89, "<"], "\x8d" => [96, "<"], "\x8e" => [97, "<"], "\x8f" => [99, "<"], "\x90" => [106, "<"], "\x91" => [136, "<"], "\x92" => [139, "<"], "\x93" => [141, "<"], "\x94" => [145, "<"], "\x95" => [147, "<"], "\x96" => [149, "<"], "\x97" => [101, "<"], "\x98" => [112, "<"], "\x99" => [117, "<"], "\x9a" => [120, "<"], "\x9b" => [124, "<"], "\x9c" => [127, "<"], "\x9d" => [144, "<"], "\x9e" => [152, "<"], "\x9f" => [11, "<"], "\xa0" => [0, "`0"], "\xa1" => [0, "`1"], "\xa2" => [0, "`2"], "\xa3" => [0, "`a"], "\xa4" => [0, "`c"], "\xa5" => [0, "`e"], "\xa6" => [0, "`i"], "\xa7" => [0, "`o"], "\xa8" => [0, "`s"], "\xa9" => [0, "`t"], "\xaa" => [73, "`"], "\xab" => [88, "`"], "\xac" => [89, "`"], "\xad" => [96, "`"], "\xae" => [97, "`"], "\xaf" => [99, "`"], "\xb0" => [106, "`"], "\xb1" => [136, "`"], "\xb2" => [139, "`"], "\xb3" => [141, "`"], "\xb4" => [145, "`"], "\xb5" => [147, "`"], "\xb6" => [149, "`"], "\xb7" => [101, "`"], "\xb8" => [112, "`"], "\xb9" => [117, "`"], "\xba" => [120, "`"], "\xbb" => [124, "`"], "\xbc" => [127, "`"], "\xbd" => [144, "`"], "\xbe" => [152, "`"], "\xbf" => [11, "`"], "\xc0" => [0, "{0"], "\xc1" => [0, "{1"], "\xc2" => [0, "{2"], "\xc3" => [0, "{a"], "\xc4" => [0, "{c"], "\xc5" => [0, "{e"], "\xc6" => [0, "{i"], "\xc7" => [0, "{o"], "\xc8" => [0, "{s"], "\xc9" => [0, "{t"], "\xca" => [73, "{"], "\xcb" => [88, "{"], "\xcc" => [89, "{"], "\xcd" => [96, "{"], "\xce" => [97, "{"], "\xcf" => [99, "{"], "\xd0" => [106, "{"], "\xd1" => [136, "{"], "\xd2" => [139, "{"], "\xd3" => [141, "{"], "\xd4" => [145, "{"], "\xd5" => [147, "{"], "\xd6" => [149, "{"], "\xd7" => [101, "{"], "\xd8" => [112, "{"], "\xd9" => [117, "{"], "\xda" => [120, "{"], "\xdb" => [124, "{"], "\xdc" => [127, "{"], "\xdd" => [144, "{"], "\xde" => [152, "{"], "\xdf" => [11, "{"], "\xe0" => [77, "\\"], "\xe1" => [18, "\\"], "\xe2" => [77, "\xc3"], "\xe3" => [18, "\xc3"], "\xe4" => [77, "\xd0"], "\xe5" => [18, "\xd0"], "\xe6" => [0, "\x80"], "\xe7" => [0, "\x82"], "\xe8" => [0, "\x83"], "\xe9" => [0, "\xa2"], "\xea" => [0, "\xb8"], "\xeb" => [0, "\xc2"], "\xec" => [0, "\xe0"], "\xed" => [0, "\xe2"], "\xee" => [182, null], "\xef" => [195, null], "\xf0" => [203, null], "\xf1" => [209, null], "\xf2" => [242, null], "\xf3" => [249, null], "\xf4" => [158, null], "\xf5" => [166, null], "\xf6" => [186, null], "\xf7" => [191, null], "\xf8" => [207, null], "\xf9" => [214, null], "\xfa" => [224, null], "\xfb" => [27, null], "\xfc" => [176, null], "\xfd" => [194, null], "\xfe" => [51, null], "\xff" => [36, null]], ["\x00" => [0, "\x010"], "\x01" => [0, "\x011"], "\x02" => [0, "\x012"], "\x03" => [0, "\x01a"], "\x04" => [0, "\x01c"], "\x05" => [0, "\x01e"], "\x06" => [0, "\x01i"], "\x07" => [0, "\x01o"], "\x08" => [0, "\x01s"], "\t" => [0, "\x01t"], "\n" => [73, "\x01"], "\v" => [88, "\x01"], "\f" => [89, "\x01"], "\r" => [96, "\x01"], "\x0e" => [97, "\x01"], "\x0f" => [99, "\x01"], "\x10" => [106, "\x01"], "\x11" => [136, "\x01"], "\x12" => [139, "\x01"], "\x13" => [141, "\x01"], "\x14" => [145, "\x01"], "\x15" => [147, "\x01"], "\x16" => [149, "\x01"], "\x17" => [101, "\x01"], "\x18" => [112, "\x01"], "\x19" => [117, "\x01"], "\x1a" => [120, "\x01"], "\x1b" => [124, "\x01"], "\x1c" => [127, "\x01"], "\x1d" => [144, "\x01"], "\x1e" => [152, "\x01"], "\x1f" => [11, "\x01"], " " => [0, "\x870"], "!" => [0, "\x871"], "\"" => [0, "\x872"], "#" => [0, "\x87a"], "\$" => [0, "\x87c"], "%" => [0, "\x87e"], "&" => [0, "\x87i"], "'" => [0, "\x87o"], "(" => [0, "\x87s"], ")" => [0, "\x87t"], "*" => [73, "\x87"], "+" => [88, "\x87"], "," => [89, "\x87"], "-" => [96, "\x87"], "." => [97, "\x87"], "/" => [99, "\x87"], [106, "\x87"], [136, "\x87"], [139, "\x87"], [141, "\x87"], [145, "\x87"], [147, "\x87"], [149, "\x87"], [101, "\x87"], [112, "\x87"], [117, "\x87"], ":" => [120, "\x87"], ";" => [124, "\x87"], "<" => [127, "\x87"], "=" => [144, "\x87"], ">" => [152, "\x87"], "?" => [11, "\x87"], "@" => [0, "\x890"], "A" => [0, "\x891"], "B" => [0, "\x892"], "C" => [0, "\x89a"], "D" => [0, "\x89c"], "E" => [0, "\x89e"], "F" => [0, "\x89i"], "G" => [0, "\x89o"], "H" => [0, "\x89s"], "I" => [0, "\x89t"], "J" => [73, "\x89"], "K" => [88, "\x89"], "L" => [89, "\x89"], "M" => [96, "\x89"], "N" => [97, "\x89"], "O" => [99, "\x89"], "P" => [106, "\x89"], "Q" => [136, "\x89"], "R" => [139, "\x89"], "S" => [141, "\x89"], "T" => [145, "\x89"], "U" => [147, "\x89"], "V" => [149, "\x89"], "W" => [101, "\x89"], "X" => [112, "\x89"], "Y" => [117, "\x89"], "Z" => [120, "\x89"], "[" => [124, "\x89"], "\\" => [127, "\x89"], "]" => [144, "\x89"], "^" => [152, "\x89"], "_" => [11, "\x89"], "`" => [0, "\x8a0"], "a" => [0, "\x8a1"], "b" => [0, "\x8a2"], "c" => [0, "\x8aa"], "d" => [0, "\x8ac"], "e" => [0, "\x8ae"], "f" => [0, "\x8ai"], "g" => [0, "\x8ao"], "h" => [0, "\x8as"], "i" => [0, "\x8at"], "j" => [73, "\x8a"], "k" => [88, "\x8a"], "l" => [89, "\x8a"], "m" => [96, "\x8a"], "n" => [97, "\x8a"], "o" => [99, "\x8a"], "p" => [106, "\x8a"], "q" => [136, "\x8a"], "r" => [139, "\x8a"], "s" => [141, "\x8a"], "t" => [145, "\x8a"], "u" => [147, "\x8a"], "v" => [149, "\x8a"], "w" => [101, "\x8a"], "x" => [112, "\x8a"], "y" => [117, "\x8a"], "z" => [120, "\x8a"], "{" => [124, "\x8a"], "|" => [127, "\x8a"], "}" => [144, "\x8a"], "~" => [152, "\x8a"], "" => [11, "\x8a"], "\x80" => [0, "\x8b0"], "\x81" => [0, "\x8b1"], "\x82" => [0, "\x8b2"], "\x83" => [0, "\x8ba"], "\x84" => [0, "\x8bc"], "\x85" => [0, "\x8be"], "\x86" => [0, "\x8bi"], "\x87" => [0, "\x8bo"], "\x88" => [0, "\x8bs"], "\x89" => [0, "\x8bt"], "\x8a" => [73, "\x8b"], "\x8b" => [88, "\x8b"], "\x8c" => [89, "\x8b"], "\x8d" => [96, "\x8b"], "\x8e" => [97, "\x8b"], "\x8f" => [99, "\x8b"], "\x90" => [106, "\x8b"], "\x91" => [136, "\x8b"], "\x92" => [139, "\x8b"], "\x93" => [141, "\x8b"], "\x94" => [145, "\x8b"], "\x95" => [147, "\x8b"], "\x96" => [149, "\x8b"], "\x97" => [101, "\x8b"], "\x98" => [112, "\x8b"], "\x99" => [117, "\x8b"], "\x9a" => [120, "\x8b"], "\x9b" => [124, "\x8b"], "\x9c" => [127, "\x8b"], "\x9d" => [144, "\x8b"], "\x9e" => [152, "\x8b"], "\x9f" => [11, "\x8b"], "\xa0" => [0, "\x8c0"], "\xa1" => [0, "\x8c1"], "\xa2" => [0, "\x8c2"], "\xa3" => [0, "\x8ca"], "\xa4" => [0, "\x8cc"], "\xa5" => [0, "\x8ce"], "\xa6" => [0, "\x8ci"], "\xa7" => [0, "\x8co"], "\xa8" => [0, "\x8cs"], "\xa9" => [0, "\x8ct"], "\xaa" => [73, "\x8c"], "\xab" => [88, "\x8c"], "\xac" => [89, "\x8c"], "\xad" => [96, "\x8c"], "\xae" => [97, "\x8c"], "\xaf" => [99, "\x8c"], "\xb0" => [106, "\x8c"], "\xb1" => [136, "\x8c"], "\xb2" => [139, "\x8c"], "\xb3" => [141, "\x8c"], "\xb4" => [145, "\x8c"], "\xb5" => [147, "\x8c"], "\xb6" => [149, "\x8c"], "\xb7" => [101, "\x8c"], "\xb8" => [112, "\x8c"], "\xb9" => [117, "\x8c"], "\xba" => [120, "\x8c"], "\xbb" => [124, "\x8c"], "\xbc" => [127, "\x8c"], "\xbd" => [144, "\x8c"], "\xbe" => [152, "\x8c"], "\xbf" => [11, "\x8c"], "\xc0" => [0, "\x8d0"], "\xc1" => [0, "\x8d1"], "\xc2" => [0, "\x8d2"], "\xc3" => [0, "\x8da"], "\xc4" => [0, "\x8dc"], "\xc5" => [0, "\x8de"], "\xc6" => [0, "\x8di"], "\xc7" => [0, "\x8do"], "\xc8" => [0, "\x8ds"], "\xc9" => [0, "\x8dt"], "\xca" => [73, "\x8d"], "\xcb" => [88, "\x8d"], "\xcc" => [89, "\x8d"], "\xcd" => [96, "\x8d"], "\xce" => [97, "\x8d"], "\xcf" => [99, "\x8d"], "\xd0" => [106, "\x8d"], "\xd1" => [136, "\x8d"], "\xd2" => [139, "\x8d"], "\xd3" => [141, "\x8d"], "\xd4" => [145, "\x8d"], "\xd5" => [147, "\x8d"], "\xd6" => [149, "\x8d"], "\xd7" => [101, "\x8d"], "\xd8" => [112, "\x8d"], "\xd9" => [117, "\x8d"], "\xda" => [120, "\x8d"], "\xdb" => [124, "\x8d"], "\xdc" => [127, "\x8d"], "\xdd" => [144, "\x8d"], "\xde" => [152, "\x8d"], "\xdf" => [11, "\x8d"], "\xe0" => [0, "\x8f0"], "\xe1" => [0, "\x8f1"], "\xe2" => [0, "\x8f2"], "\xe3" => [0, "\x8fa"], "\xe4" => [0, "\x8fc"], "\xe5" => [0, "\x8fe"], "\xe6" => [0, "\x8fi"], "\xe7" => [0, "\x8fo"], "\xe8" => [0, "\x8fs"], "\xe9" => [0, "\x8ft"], "\xea" => [73, "\x8f"], "\xeb" => [88, "\x8f"], "\xec" => [89, "\x8f"], "\xed" => [96, "\x8f"], "\xee" => [97, "\x8f"], "\xef" => [99, "\x8f"], "\xf0" => [106, "\x8f"], "\xf1" => [136, "\x8f"], "\xf2" => [139, "\x8f"], "\xf3" => [141, "\x8f"], "\xf4" => [145, "\x8f"], "\xf5" => [147, "\x8f"], "\xf6" => [149, "\x8f"], "\xf7" => [101, "\x8f"], "\xf8" => [112, "\x8f"], "\xf9" => [117, "\x8f"], "\xfa" => [120, "\x8f"], "\xfb" => [124, "\x8f"], "\xfc" => [127, "\x8f"], "\xfd" => [144, "\x8f"], "\xfe" => [152, "\x8f"], "\xff" => [11, "\x8f"]], ["\x00" => [77, "]0"], "\x01" => [18, "]0"], "\x02" => [77, "]1"], "\x03" => [18, "]1"], "\x04" => [77, "]2"], "\x05" => [18, "]2"], "\x06" => [77, "]a"], "\x07" => [18, "]a"], "\x08" => [77, "]c"], "\t" => [18, "]c"], "\n" => [77, "]e"], "\v" => [18, "]e"], "\f" => [77, "]i"], "\r" => [18, "]i"], "\x0e" => [77, "]o"], "\x0f" => [18, "]o"], "\x10" => [77, "]s"], "\x11" => [18, "]s"], "\x12" => [77, "]t"], "\x13" => [18, "]t"], "\x14" => [0, "] "], "\x15" => [0, "]%"], "\x16" => [0, "]-"], "\x17" => [0, "]."], "\x18" => [0, "]/"], "\x19" => [0, "]3"], "\x1a" => [0, "]4"], "\x1b" => [0, "]5"], "\x1c" => [0, "]6"], "\x1d" => [0, "]7"], "\x1e" => [0, "]8"], "\x1f" => [0, "]9"], " " => [0, "]="], "!" => [0, "]A"], "\"" => [0, "]_"], "#" => [0, "]b"], "\$" => [0, "]d"], "%" => [0, "]f"], "&" => [0, "]g"], "'" => [0, "]h"], "(" => [0, "]l"], ")" => [0, "]m"], "*" => [0, "]n"], "+" => [0, "]p"], "," => [0, "]r"], "-" => [0, "]u"], "." => [100, "]"], "/" => [110, "]"], [111, "]"], [115, "]"], [116, "]"], [118, "]"], [119, "]"], [122, "]"], [123, "]"], [125, "]"], [126, "]"], [129, "]"], ":" => [143, "]"], ";" => [148, "]"], "<" => [151, "]"], "=" => [153, "]"], ">" => [83, "]"], "?" => [10, "]"], "@" => [77, "~0"], "A" => [18, "~0"], "B" => [77, "~1"], "C" => [18, "~1"], "D" => [77, "~2"], "E" => [18, "~2"], "F" => [77, "~a"], "G" => [18, "~a"], "H" => [77, "~c"], "I" => [18, "~c"], "J" => [77, "~e"], "K" => [18, "~e"], "L" => [77, "~i"], "M" => [18, "~i"], "N" => [77, "~o"], "O" => [18, "~o"], "P" => [77, "~s"], "Q" => [18, "~s"], "R" => [77, "~t"], "S" => [18, "~t"], "T" => [0, "~ "], "U" => [0, "~%"], "V" => [0, "~-"], "W" => [0, "~."], "X" => [0, "~/"], "Y" => [0, "~3"], "Z" => [0, "~4"], "[" => [0, "~5"], "\\" => [0, "~6"], "]" => [0, "~7"], "^" => [0, "~8"], "_" => [0, "~9"], "`" => [0, "~="], "a" => [0, "~A"], "b" => [0, "~_"], "c" => [0, "~b"], "d" => [0, "~d"], "e" => [0, "~f"], "f" => [0, "~g"], "g" => [0, "~h"], "h" => [0, "~l"], "i" => [0, "~m"], "j" => [0, "~n"], "k" => [0, "~p"], "l" => [0, "~r"], "m" => [0, "~u"], "n" => [100, "~"], "o" => [110, "~"], "p" => [111, "~"], "q" => [115, "~"], "r" => [116, "~"], "s" => [118, "~"], "t" => [119, "~"], "u" => [122, "~"], "v" => [123, "~"], "w" => [125, "~"], "x" => [126, "~"], "y" => [129, "~"], "z" => [143, "~"], "{" => [148, "~"], "|" => [151, "~"], "}" => [153, "~"], "~" => [83, "~"], "" => [10, "~"], "\x80" => [0, "^0"], "\x81" => [0, "^1"], "\x82" => [0, "^2"], "\x83" => [0, "^a"], "\x84" => [0, "^c"], "\x85" => [0, "^e"], "\x86" => [0, "^i"], "\x87" => [0, "^o"], "\x88" => [0, "^s"], "\x89" => [0, "^t"], "\x8a" => [73, "^"], "\x8b" => [88, "^"], "\x8c" => [89, "^"], "\x8d" => [96, "^"], "\x8e" => [97, "^"], "\x8f" => [99, "^"], "\x90" => [106, "^"], "\x91" => [136, "^"], "\x92" => [139, "^"], "\x93" => [141, "^"], "\x94" => [145, "^"], "\x95" => [147, "^"], "\x96" => [149, "^"], "\x97" => [101, "^"], "\x98" => [112, "^"], "\x99" => [117, "^"], "\x9a" => [120, "^"], "\x9b" => [124, "^"], "\x9c" => [127, "^"], "\x9d" => [144, "^"], "\x9e" => [152, "^"], "\x9f" => [11, "^"], "\xa0" => [0, "}0"], "\xa1" => [0, "}1"], "\xa2" => [0, "}2"], "\xa3" => [0, "}a"], "\xa4" => [0, "}c"], "\xa5" => [0, "}e"], "\xa6" => [0, "}i"], "\xa7" => [0, "}o"], "\xa8" => [0, "}s"], "\xa9" => [0, "}t"], "\xaa" => [73, "}"], "\xab" => [88, "}"], "\xac" => [89, "}"], "\xad" => [96, "}"], "\xae" => [97, "}"], "\xaf" => [99, "}"], "\xb0" => [106, "}"], "\xb1" => [136, "}"], "\xb2" => [139, "}"], "\xb3" => [141, "}"], "\xb4" => [145, "}"], "\xb5" => [147, "}"], "\xb6" => [149, "}"], "\xb7" => [101, "}"], "\xb8" => [112, "}"], "\xb9" => [117, "}"], "\xba" => [120, "}"], "\xbb" => [124, "}"], "\xbc" => [127, "}"], "\xbd" => [144, "}"], "\xbe" => [152, "}"], "\xbf" => [11, "}"], "\xc0" => [92, "<"], "\xc1" => [95, "<"], "\xc2" => [137, "<"], "\xc3" => [142, "<"], "\xc4" => [150, "<"], "\xc5" => [74, "<"], "\xc6" => [90, "<"], "\xc7" => [98, "<"], "\xc8" => [107, "<"], "\xc9" => [140, "<"], "\xca" => [146, "<"], "\xcb" => [102, "<"], "\xcc" => [113, "<"], "\xcd" => [121, "<"], "\xce" => [128, "<"], "\xcf" => [12, "<"], "\xd0" => [92, "`"], "\xd1" => [95, "`"], "\xd2" => [137, "`"], "\xd3" => [142, "`"], "\xd4" => [150, "`"], "\xd5" => [74, "`"], "\xd6" => [90, "`"], "\xd7" => [98, "`"], "\xd8" => [107, "`"], "\xd9" => [140, "`"], "\xda" => [146, "`"], "\xdb" => [102, "`"], "\xdc" => [113, "`"], "\xdd" => [121, "`"], "\xde" => [128, "`"], "\xdf" => [12, "`"], "\xe0" => [92, "{"], "\xe1" => [95, "{"], "\xe2" => [137, "{"], "\xe3" => [142, "{"], "\xe4" => [150, "{"], "\xe5" => [74, "{"], "\xe6" => [90, "{"], "\xe7" => [98, "{"], "\xe8" => [107, "{"], "\xe9" => [140, "{"], "\xea" => [146, "{"], "\xeb" => [102, "{"], "\xec" => [113, "{"], "\xed" => [121, "{"], "\xee" => [128, "{"], "\xef" => [12, "{"], "\xf0" => [0, "\\"], "\xf1" => [0, "\xc3"], "\xf2" => [0, "\xd0"], "\xf3" => [155, null], "\xf4" => [162, null], "\xf5" => [211, null], "\xf6" => [248, null], "\xf7" => [183, null], "\xf8" => [204, null], "\xf9" => [243, null], "\xfa" => [159, null], "\xfb" => [187, null], "\xfc" => [208, null], "\xfd" => [29, null], "\xfe" => [177, null], "\xff" => [37, null]], ["\x00" => [0, "\xc60"], "\x01" => [0, "\xc61"], "\x02" => [0, "\xc62"], "\x03" => [0, "\xc6a"], "\x04" => [0, "\xc6c"], "\x05" => [0, "\xc6e"], "\x06" => [0, "\xc6i"], "\x07" => [0, "\xc6o"], "\x08" => [0, "\xc6s"], "\t" => [0, "\xc6t"], "\n" => [73, "\xc6"], "\v" => [88, "\xc6"], "\f" => [89, "\xc6"], "\r" => [96, "\xc6"], "\x0e" => [97, "\xc6"], "\x0f" => [99, "\xc6"], "\x10" => [106, "\xc6"], "\x11" => [136, "\xc6"], "\x12" => [139, "\xc6"], "\x13" => [141, "\xc6"], "\x14" => [145, "\xc6"], "\x15" => [147, "\xc6"], "\x16" => [149, "\xc6"], "\x17" => [101, "\xc6"], "\x18" => [112, "\xc6"], "\x19" => [117, "\xc6"], "\x1a" => [120, "\xc6"], "\x1b" => [124, "\xc6"], "\x1c" => [127, "\xc6"], "\x1d" => [144, "\xc6"], "\x1e" => [152, "\xc6"], "\x1f" => [11, "\xc6"], " " => [0, "\xe40"], "!" => [0, "\xe41"], "\"" => [0, "\xe42"], "#" => [0, "\xe4a"], "\$" => [0, "\xe4c"], "%" => [0, "\xe4e"], "&" => [0, "\xe4i"], "'" => [0, "\xe4o"], "(" => [0, "\xe4s"], ")" => [0, "\xe4t"], "*" => [73, "\xe4"], "+" => [88, "\xe4"], "," => [89, "\xe4"], "-" => [96, "\xe4"], "." => [97, "\xe4"], "/" => [99, "\xe4"], [106, "\xe4"], [136, "\xe4"], [139, "\xe4"], [141, "\xe4"], [145, "\xe4"], [147, "\xe4"], [149, "\xe4"], [101, "\xe4"], [112, "\xe4"], [117, "\xe4"], ":" => [120, "\xe4"], ";" => [124, "\xe4"], "<" => [127, "\xe4"], "=" => [144, "\xe4"], ">" => [152, "\xe4"], "?" => [11, "\xe4"], "@" => [0, "\xe80"], "A" => [0, "\xe81"], "B" => [0, "\xe82"], "C" => [0, "\xe8a"], "D" => [0, "\xe8c"], "E" => [0, "\xe8e"], "F" => [0, "\xe8i"], "G" => [0, "\xe8o"], "H" => [0, "\xe8s"], "I" => [0, "\xe8t"], "J" => [73, "\xe8"], "K" => [88, "\xe8"], "L" => [89, "\xe8"], "M" => [96, "\xe8"], "N" => [97, "\xe8"], "O" => [99, "\xe8"], "P" => [106, "\xe8"], "Q" => [136, "\xe8"], "R" => [139, "\xe8"], "S" => [141, "\xe8"], "T" => [145, "\xe8"], "U" => [147, "\xe8"], "V" => [149, "\xe8"], "W" => [101, "\xe8"], "X" => [112, "\xe8"], "Y" => [117, "\xe8"], "Z" => [120, "\xe8"], "[" => [124, "\xe8"], "\\" => [127, "\xe8"], "]" => [144, "\xe8"], "^" => [152, "\xe8"], "_" => [11, "\xe8"], "`" => [0, "\xe90"], "a" => [0, "\xe91"], "b" => [0, "\xe92"], "c" => [0, "\xe9a"], "d" => [0, "\xe9c"], "e" => [0, "\xe9e"], "f" => [0, "\xe9i"], "g" => [0, "\xe9o"], "h" => [0, "\xe9s"], "i" => [0, "\xe9t"], "j" => [73, "\xe9"], "k" => [88, "\xe9"], "l" => [89, "\xe9"], "m" => [96, "\xe9"], "n" => [97, "\xe9"], "o" => [99, "\xe9"], "p" => [106, "\xe9"], "q" => [136, "\xe9"], "r" => [139, "\xe9"], "s" => [141, "\xe9"], "t" => [145, "\xe9"], "u" => [147, "\xe9"], "v" => [149, "\xe9"], "w" => [101, "\xe9"], "x" => [112, "\xe9"], "y" => [117, "\xe9"], "z" => [120, "\xe9"], "{" => [124, "\xe9"], "|" => [127, "\xe9"], "}" => [144, "\xe9"], "~" => [152, "\xe9"], "" => [11, "\xe9"], "\x80" => [92, "\x01"], "\x81" => [95, "\x01"], "\x82" => [137, "\x01"], "\x83" => [142, "\x01"], "\x84" => [150, "\x01"], "\x85" => [74, "\x01"], "\x86" => [90, "\x01"], "\x87" => [98, "\x01"], "\x88" => [107, "\x01"], "\x89" => [140, "\x01"], "\x8a" => [146, "\x01"], "\x8b" => [102, "\x01"], "\x8c" => [113, "\x01"], "\x8d" => [121, "\x01"], "\x8e" => [128, "\x01"], "\x8f" => [12, "\x01"], "\x90" => [92, "\x87"], "\x91" => [95, "\x87"], "\x92" => [137, "\x87"], "\x93" => [142, "\x87"], "\x94" => [150, "\x87"], "\x95" => [74, "\x87"], "\x96" => [90, "\x87"], "\x97" => [98, "\x87"], "\x98" => [107, "\x87"], "\x99" => [140, "\x87"], "\x9a" => [146, "\x87"], "\x9b" => [102, "\x87"], "\x9c" => [113, "\x87"], "\x9d" => [121, "\x87"], "\x9e" => [128, "\x87"], "\x9f" => [12, "\x87"], "\xa0" => [92, "\x89"], "\xa1" => [95, "\x89"], "\xa2" => [137, "\x89"], "\xa3" => [142, "\x89"], "\xa4" => [150, "\x89"], "\xa5" => [74, "\x89"], "\xa6" => [90, "\x89"], "\xa7" => [98, "\x89"], "\xa8" => [107, "\x89"], "\xa9" => [140, "\x89"], "\xaa" => [146, "\x89"], "\xab" => [102, "\x89"], "\xac" => [113, "\x89"], "\xad" => [121, "\x89"], "\xae" => [128, "\x89"], "\xaf" => [12, "\x89"], "\xb0" => [92, "\x8a"], "\xb1" => [95, "\x8a"], "\xb2" => [137, "\x8a"], "\xb3" => [142, "\x8a"], "\xb4" => [150, "\x8a"], "\xb5" => [74, "\x8a"], "\xb6" => [90, "\x8a"], "\xb7" => [98, "\x8a"], "\xb8" => [107, "\x8a"], "\xb9" => [140, "\x8a"], "\xba" => [146, "\x8a"], "\xbb" => [102, "\x8a"], "\xbc" => [113, "\x8a"], "\xbd" => [121, "\x8a"], "\xbe" => [128, "\x8a"], "\xbf" => [12, "\x8a"], "\xc0" => [92, "\x8b"], "\xc1" => [95, "\x8b"], "\xc2" => [137, "\x8b"], "\xc3" => [142, "\x8b"], "\xc4" => [150, "\x8b"], "\xc5" => [74, "\x8b"], "\xc6" => [90, "\x8b"], "\xc7" => [98, "\x8b"], "\xc8" => [107, "\x8b"], "\xc9" => [140, "\x8b"], "\xca" => [146, "\x8b"], "\xcb" => [102, "\x8b"], "\xcc" => [113, "\x8b"], "\xcd" => [121, "\x8b"], "\xce" => [128, "\x8b"], "\xcf" => [12, "\x8b"], "\xd0" => [92, "\x8c"], "\xd1" => [95, "\x8c"], "\xd2" => [137, "\x8c"], "\xd3" => [142, "\x8c"], "\xd4" => [150, "\x8c"], "\xd5" => [74, "\x8c"], "\xd6" => [90, "\x8c"], "\xd7" => [98, "\x8c"], "\xd8" => [107, "\x8c"], "\xd9" => [140, "\x8c"], "\xda" => [146, "\x8c"], "\xdb" => [102, "\x8c"], "\xdc" => [113, "\x8c"], "\xdd" => [121, "\x8c"], "\xde" => [128, "\x8c"], "\xdf" => [12, "\x8c"], "\xe0" => [92, "\x8d"], "\xe1" => [95, "\x8d"], "\xe2" => [137, "\x8d"], "\xe3" => [142, "\x8d"], "\xe4" => [150, "\x8d"], "\xe5" => [74, "\x8d"], "\xe6" => [90, "\x8d"], "\xe7" => [98, "\x8d"], "\xe8" => [107, "\x8d"], "\xe9" => [140, "\x8d"], "\xea" => [146, "\x8d"], "\xeb" => [102, "\x8d"], "\xec" => [113, "\x8d"], "\xed" => [121, "\x8d"], "\xee" => [128, "\x8d"], "\xef" => [12, "\x8d"], "\xf0" => [92, "\x8f"], "\xf1" => [95, "\x8f"], "\xf2" => [137, "\x8f"], "\xf3" => [142, "\x8f"], "\xf4" => [150, "\x8f"], "\xf5" => [74, "\x8f"], "\xf6" => [90, "\x8f"], "\xf7" => [98, "\x8f"], "\xf8" => [107, "\x8f"], "\xf9" => [140, "\x8f"], "\xfa" => [146, "\x8f"], "\xfb" => [102, "\x8f"], "\xfc" => [113, "\x8f"], "\xfd" => [121, "\x8f"], "\xfe" => [128, "\x8f"], "\xff" => [12, "\x8f"]], ["\x00" => [92, "\xb2"], "\x01" => [95, "\xb2"], "\x02" => [137, "\xb2"], "\x03" => [142, "\xb2"], "\x04" => [150, "\xb2"], "\x05" => [74, "\xb2"], "\x06" => [90, "\xb2"], "\x07" => [98, "\xb2"], "\x08" => [107, "\xb2"], "\t" => [140, "\xb2"], "\n" => [146, "\xb2"], "\v" => [102, "\xb2"], "\f" => [113, "\xb2"], "\r" => [121, "\xb2"], "\x0e" => [128, "\xb2"], "\x0f" => [12, "\xb2"], "\x10" => [92, "\xb5"], "\x11" => [95, "\xb5"], "\x12" => [137, "\xb5"], "\x13" => [142, "\xb5"], "\x14" => [150, "\xb5"], "\x15" => [74, "\xb5"], "\x16" => [90, "\xb5"], "\x17" => [98, "\xb5"], "\x18" => [107, "\xb5"], "\x19" => [140, "\xb5"], "\x1a" => [146, "\xb5"], "\x1b" => [102, "\xb5"], "\x1c" => [113, "\xb5"], "\x1d" => [121, "\xb5"], "\x1e" => [128, "\xb5"], "\x1f" => [12, "\xb5"], " " => [92, "\xb9"], "!" => [95, "\xb9"], "\"" => [137, "\xb9"], "#" => [142, "\xb9"], "\$" => [150, "\xb9"], "%" => [74, "\xb9"], "&" => [90, "\xb9"], "'" => [98, "\xb9"], "(" => [107, "\xb9"], ")" => [140, "\xb9"], "*" => [146, "\xb9"], "+" => [102, "\xb9"], "," => [113, "\xb9"], "-" => [121, "\xb9"], "." => [128, "\xb9"], "/" => [12, "\xb9"], [92, "\xba"], [95, "\xba"], [137, "\xba"], [142, "\xba"], [150, "\xba"], [74, "\xba"], [90, "\xba"], [98, "\xba"], [107, "\xba"], [140, "\xba"], ":" => [146, "\xba"], ";" => [102, "\xba"], "<" => [113, "\xba"], "=" => [121, "\xba"], ">" => [128, "\xba"], "?" => [12, "\xba"], "@" => [92, "\xbb"], "A" => [95, "\xbb"], "B" => [137, "\xbb"], "C" => [142, "\xbb"], "D" => [150, "\xbb"], "E" => [74, "\xbb"], "F" => [90, "\xbb"], "G" => [98, "\xbb"], "H" => [107, "\xbb"], "I" => [140, "\xbb"], "J" => [146, "\xbb"], "K" => [102, "\xbb"], "L" => [113, "\xbb"], "M" => [121, "\xbb"], "N" => [128, "\xbb"], "O" => [12, "\xbb"], "P" => [92, "\xbd"], "Q" => [95, "\xbd"], "R" => [137, "\xbd"], "S" => [142, "\xbd"], "T" => [150, "\xbd"], "U" => [74, "\xbd"], "V" => [90, "\xbd"], "W" => [98, "\xbd"], "X" => [107, "\xbd"], "Y" => [140, "\xbd"], "Z" => [146, "\xbd"], "[" => [102, "\xbd"], "\\" => [113, "\xbd"], "]" => [121, "\xbd"], "^" => [128, "\xbd"], "_" => [12, "\xbd"], "`" => [92, "\xbe"], "a" => [95, "\xbe"], "b" => [137, "\xbe"], "c" => [142, "\xbe"], "d" => [150, "\xbe"], "e" => [74, "\xbe"], "f" => [90, "\xbe"], "g" => [98, "\xbe"], "h" => [107, "\xbe"], "i" => [140, "\xbe"], "j" => [146, "\xbe"], "k" => [102, "\xbe"], "l" => [113, "\xbe"], "m" => [121, "\xbe"], "n" => [128, "\xbe"], "o" => [12, "\xbe"], "p" => [92, "\xc4"], "q" => [95, "\xc4"], "r" => [137, "\xc4"], "s" => [142, "\xc4"], "t" => [150, "\xc4"], "u" => [74, "\xc4"], "v" => [90, "\xc4"], "w" => [98, "\xc4"], "x" => [107, "\xc4"], "y" => [140, "\xc4"], "z" => [146, "\xc4"], "{" => [102, "\xc4"], "|" => [113, "\xc4"], "}" => [121, "\xc4"], "~" => [128, "\xc4"], "" => [12, "\xc4"], "\x80" => [92, "\xc6"], "\x81" => [95, "\xc6"], "\x82" => [137, "\xc6"], "\x83" => [142, "\xc6"], "\x84" => [150, "\xc6"], "\x85" => [74, "\xc6"], "\x86" => [90, "\xc6"], "\x87" => [98, "\xc6"], "\x88" => [107, "\xc6"], "\x89" => [140, "\xc6"], "\x8a" => [146, "\xc6"], "\x8b" => [102, "\xc6"], "\x8c" => [113, "\xc6"], "\x8d" => [121, "\xc6"], "\x8e" => [128, "\xc6"], "\x8f" => [12, "\xc6"], "\x90" => [92, "\xe4"], "\x91" => [95, "\xe4"], "\x92" => [137, "\xe4"], "\x93" => [142, "\xe4"], "\x94" => [150, "\xe4"], "\x95" => [74, "\xe4"], "\x96" => [90, "\xe4"], "\x97" => [98, "\xe4"], "\x98" => [107, "\xe4"], "\x99" => [140, "\xe4"], "\x9a" => [146, "\xe4"], "\x9b" => [102, "\xe4"], "\x9c" => [113, "\xe4"], "\x9d" => [121, "\xe4"], "\x9e" => [128, "\xe4"], "\x9f" => [12, "\xe4"], "\xa0" => [92, "\xe8"], "\xa1" => [95, "\xe8"], "\xa2" => [137, "\xe8"], "\xa3" => [142, "\xe8"], "\xa4" => [150, "\xe8"], "\xa5" => [74, "\xe8"], "\xa6" => [90, "\xe8"], "\xa7" => [98, "\xe8"], "\xa8" => [107, "\xe8"], "\xa9" => [140, "\xe8"], "\xaa" => [146, "\xe8"], "\xab" => [102, "\xe8"], "\xac" => [113, "\xe8"], "\xad" => [121, "\xe8"], "\xae" => [128, "\xe8"], "\xaf" => [12, "\xe8"], "\xb0" => [92, "\xe9"], "\xb1" => [95, "\xe9"], "\xb2" => [137, "\xe9"], "\xb3" => [142, "\xe9"], "\xb4" => [150, "\xe9"], "\xb5" => [74, "\xe9"], "\xb6" => [90, "\xe9"], "\xb7" => [98, "\xe9"], "\xb8" => [107, "\xe9"], "\xb9" => [140, "\xe9"], "\xba" => [146, "\xe9"], "\xbb" => [102, "\xe9"], "\xbc" => [113, "\xe9"], "\xbd" => [121, "\xe9"], "\xbe" => [128, "\xe9"], "\xbf" => [12, "\xe9"], "\xc0" => [93, "\x01"], "\xc1" => [138, "\x01"], "\xc2" => [75, "\x01"], "\xc3" => [91, "\x01"], "\xc4" => [108, "\x01"], "\xc5" => [103, "\x01"], "\xc6" => [114, "\x01"], "\xc7" => [14, "\x01"], "\xc8" => [93, "\x87"], "\xc9" => [138, "\x87"], "\xca" => [75, "\x87"], "\xcb" => [91, "\x87"], "\xcc" => [108, "\x87"], "\xcd" => [103, "\x87"], "\xce" => [114, "\x87"], "\xcf" => [14, "\x87"], "\xd0" => [93, "\x89"], "\xd1" => [138, "\x89"], "\xd2" => [75, "\x89"], "\xd3" => [91, "\x89"], "\xd4" => [108, "\x89"], "\xd5" => [103, "\x89"], "\xd6" => [114, "\x89"], "\xd7" => [14, "\x89"], "\xd8" => [93, "\x8a"], "\xd9" => [138, "\x8a"], "\xda" => [75, "\x8a"], "\xdb" => [91, "\x8a"], "\xdc" => [108, "\x8a"], "\xdd" => [103, "\x8a"], "\xde" => [114, "\x8a"], "\xdf" => [14, "\x8a"], "\xe0" => [93, "\x8b"], "\xe1" => [138, "\x8b"], "\xe2" => [75, "\x8b"], "\xe3" => [91, "\x8b"], "\xe4" => [108, "\x8b"], "\xe5" => [103, "\x8b"], "\xe6" => [114, "\x8b"], "\xe7" => [14, "\x8b"], "\xe8" => [93, "\x8c"], "\xe9" => [138, "\x8c"], "\xea" => [75, "\x8c"], "\xeb" => [91, "\x8c"], "\xec" => [108, "\x8c"], "\xed" => [103, "\x8c"], "\xee" => [114, "\x8c"], "\xef" => [14, "\x8c"], "\xf0" => [93, "\x8d"], "\xf1" => [138, "\x8d"], "\xf2" => [75, "\x8d"], "\xf3" => [91, "\x8d"], "\xf4" => [108, "\x8d"], "\xf5" => [103, "\x8d"], "\xf6" => [114, "\x8d"], "\xf7" => [14, "\x8d"], "\xf8" => [93, "\x8f"], "\xf9" => [138, "\x8f"], "\xfa" => [75, "\x8f"], "\xfb" => [91, "\x8f"], "\xfc" => [108, "\x8f"], "\xfd" => [103, "\x8f"], "\xfe" => [114, "\x8f"], "\xff" => [14, "\x8f"]], ["\x00" => [93, "\xb2"], "\x01" => [138, "\xb2"], "\x02" => [75, "\xb2"], "\x03" => [91, "\xb2"], "\x04" => [108, "\xb2"], "\x05" => [103, "\xb2"], "\x06" => [114, "\xb2"], "\x07" => [14, "\xb2"], "\x08" => [93, "\xb5"], "\t" => [138, "\xb5"], "\n" => [75, "\xb5"], "\v" => [91, "\xb5"], "\f" => [108, "\xb5"], "\r" => [103, "\xb5"], "\x0e" => [114, "\xb5"], "\x0f" => [14, "\xb5"], "\x10" => [93, "\xb9"], "\x11" => [138, "\xb9"], "\x12" => [75, "\xb9"], "\x13" => [91, "\xb9"], "\x14" => [108, "\xb9"], "\x15" => [103, "\xb9"], "\x16" => [114, "\xb9"], "\x17" => [14, "\xb9"], "\x18" => [93, "\xba"], "\x19" => [138, "\xba"], "\x1a" => [75, "\xba"], "\x1b" => [91, "\xba"], "\x1c" => [108, "\xba"], "\x1d" => [103, "\xba"], "\x1e" => [114, "\xba"], "\x1f" => [14, "\xba"], " " => [93, "\xbb"], "!" => [138, "\xbb"], "\"" => [75, "\xbb"], "#" => [91, "\xbb"], "\$" => [108, "\xbb"], "%" => [103, "\xbb"], "&" => [114, "\xbb"], "'" => [14, "\xbb"], "(" => [93, "\xbd"], ")" => [138, "\xbd"], "*" => [75, "\xbd"], "+" => [91, "\xbd"], "," => [108, "\xbd"], "-" => [103, "\xbd"], "." => [114, "\xbd"], "/" => [14, "\xbd"], [93, "\xbe"], [138, "\xbe"], [75, "\xbe"], [91, "\xbe"], [108, "\xbe"], [103, "\xbe"], [114, "\xbe"], [14, "\xbe"], [93, "\xc4"], [138, "\xc4"], ":" => [75, "\xc4"], ";" => [91, "\xc4"], "<" => [108, "\xc4"], "=" => [103, "\xc4"], ">" => [114, "\xc4"], "?" => [14, "\xc4"], "@" => [93, "\xc6"], "A" => [138, "\xc6"], "B" => [75, "\xc6"], "C" => [91, "\xc6"], "D" => [108, "\xc6"], "E" => [103, "\xc6"], "F" => [114, "\xc6"], "G" => [14, "\xc6"], "H" => [93, "\xe4"], "I" => [138, "\xe4"], "J" => [75, "\xe4"], "K" => [91, "\xe4"], "L" => [108, "\xe4"], "M" => [103, "\xe4"], "N" => [114, "\xe4"], "O" => [14, "\xe4"], "P" => [93, "\xe8"], "Q" => [138, "\xe8"], "R" => [75, "\xe8"], "S" => [91, "\xe8"], "T" => [108, "\xe8"], "U" => [103, "\xe8"], "V" => [114, "\xe8"], "W" => [14, "\xe8"], "X" => [93, "\xe9"], "Y" => [138, "\xe9"], "Z" => [75, "\xe9"], "[" => [91, "\xe9"], "\\" => [108, "\xe9"], "]" => [103, "\xe9"], "^" => [114, "\xe9"], "_" => [14, "\xe9"], "`" => [94, "\x01"], "a" => [76, "\x01"], "b" => [104, "\x01"], "c" => [16, "\x01"], "d" => [94, "\x87"], "e" => [76, "\x87"], "f" => [104, "\x87"], "g" => [16, "\x87"], "h" => [94, "\x89"], "i" => [76, "\x89"], "j" => [104, "\x89"], "k" => [16, "\x89"], "l" => [94, "\x8a"], "m" => [76, "\x8a"], "n" => [104, "\x8a"], "o" => [16, "\x8a"], "p" => [94, "\x8b"], "q" => [76, "\x8b"], "r" => [104, "\x8b"], "s" => [16, "\x8b"], "t" => [94, "\x8c"], "u" => [76, "\x8c"], "v" => [104, "\x8c"], "w" => [16, "\x8c"], "x" => [94, "\x8d"], "y" => [76, "\x8d"], "z" => [104, "\x8d"], "{" => [16, "\x8d"], "|" => [94, "\x8f"], "}" => [76, "\x8f"], "~" => [104, "\x8f"], "" => [16, "\x8f"], "\x80" => [94, "\x93"], "\x81" => [76, "\x93"], "\x82" => [104, "\x93"], "\x83" => [16, "\x93"], "\x84" => [94, "\x95"], "\x85" => [76, "\x95"], "\x86" => [104, "\x95"], "\x87" => [16, "\x95"], "\x88" => [94, "\x96"], "\x89" => [76, "\x96"], "\x8a" => [104, "\x96"], "\x8b" => [16, "\x96"], "\x8c" => [94, "\x97"], "\x8d" => [76, "\x97"], "\x8e" => [104, "\x97"], "\x8f" => [16, "\x97"], "\x90" => [94, "\x98"], "\x91" => [76, "\x98"], "\x92" => [104, "\x98"], "\x93" => [16, "\x98"], "\x94" => [94, "\x9b"], "\x95" => [76, "\x9b"], "\x96" => [104, "\x9b"], "\x97" => [16, "\x9b"], "\x98" => [94, "\x9d"], "\x99" => [76, "\x9d"], "\x9a" => [104, "\x9d"], "\x9b" => [16, "\x9d"], "\x9c" => [94, "\x9e"], "\x9d" => [76, "\x9e"], "\x9e" => [104, "\x9e"], "\x9f" => [16, "\x9e"], "\xa0" => [94, "\xa5"], "\xa1" => [76, "\xa5"], "\xa2" => [104, "\xa5"], "\xa3" => [16, "\xa5"], "\xa4" => [94, "\xa6"], "\xa5" => [76, "\xa6"], "\xa6" => [104, "\xa6"], "\xa7" => [16, "\xa6"], "\xa8" => [94, "\xa8"], "\xa9" => [76, "\xa8"], "\xaa" => [104, "\xa8"], "\xab" => [16, "\xa8"], "\xac" => [94, "\xae"], "\xad" => [76, "\xae"], "\xae" => [104, "\xae"], "\xaf" => [16, "\xae"], "\xb0" => [94, "\xaf"], "\xb1" => [76, "\xaf"], "\xb2" => [104, "\xaf"], "\xb3" => [16, "\xaf"], "\xb4" => [94, "\xb4"], "\xb5" => [76, "\xb4"], "\xb6" => [104, "\xb4"], "\xb7" => [16, "\xb4"], "\xb8" => [94, "\xb6"], "\xb9" => [76, "\xb6"], "\xba" => [104, "\xb6"], "\xbb" => [16, "\xb6"], "\xbc" => [94, "\xb7"], "\xbd" => [76, "\xb7"], "\xbe" => [104, "\xb7"], "\xbf" => [16, "\xb7"], "\xc0" => [94, "\xbc"], "\xc1" => [76, "\xbc"], "\xc2" => [104, "\xbc"], "\xc3" => [16, "\xbc"], "\xc4" => [94, "\xbf"], "\xc5" => [76, "\xbf"], "\xc6" => [104, "\xbf"], "\xc7" => [16, "\xbf"], "\xc8" => [94, "\xc5"], "\xc9" => [76, "\xc5"], "\xca" => [104, "\xc5"], "\xcb" => [16, "\xc5"], "\xcc" => [94, "\xe7"], "\xcd" => [76, "\xe7"], "\xce" => [104, "\xe7"], "\xcf" => [16, "\xe7"], "\xd0" => [94, "\xef"], "\xd1" => [76, "\xef"], "\xd2" => [104, "\xef"], "\xd3" => [16, "\xef"], "\xd4" => [77, "\t"], "\xd5" => [18, "\t"], "\xd6" => [77, "\x8e"], "\xd7" => [18, "\x8e"], "\xd8" => [77, "\x90"], "\xd9" => [18, "\x90"], "\xda" => [77, "\x91"], "\xdb" => [18, "\x91"], "\xdc" => [77, "\x94"], "\xdd" => [18, "\x94"], "\xde" => [77, "\x9f"], "\xdf" => [18, "\x9f"], "\xe0" => [77, "\xab"], "\xe1" => [18, "\xab"], "\xe2" => [77, "\xce"], "\xe3" => [18, "\xce"], "\xe4" => [77, "\xd7"], "\xe5" => [18, "\xd7"], "\xe6" => [77, "\xe1"], "\xe7" => [18, "\xe1"], "\xe8" => [77, "\xec"], "\xe9" => [18, "\xec"], "\xea" => [77, "\xed"], "\xeb" => [18, "\xed"], "\xec" => [0, "\xc7"], "\xed" => [0, "\xcf"], "\xee" => [0, "\xea"], "\xef" => [0, "\xeb"], "\xf0" => [221, null], "\xf1" => [228, null], "\xf2" => [230, null], "\xf3" => [235, null], "\xf4" => [245, null], "\xf5" => [253, null], "\xf6" => [255, null], "\xf7" => [234, null], "\xf8" => [239, null], "\xf9" => [247, null], "\xfa" => [258, null], "\xfb" => [261, null], "\xfc" => [41, null], "\xfd" => [47, null], "\xfe" => [64, null], "\xff" => [57, null]], ["\x00" => [0, "\xfe0"], "\x01" => [0, "\xfe1"], "\x02" => [0, "\xfe2"], "\x03" => [0, "\xfea"], "\x04" => [0, "\xfec"], "\x05" => [0, "\xfee"], "\x06" => [0, "\xfei"], "\x07" => [0, "\xfeo"], "\x08" => [0, "\xfes"], "\t" => [0, "\xfet"], "\n" => [73, "\xfe"], "\v" => [88, "\xfe"], "\f" => [89, "\xfe"], "\r" => [96, "\xfe"], "\x0e" => [97, "\xfe"], "\x0f" => [99, "\xfe"], "\x10" => [106, "\xfe"], "\x11" => [136, "\xfe"], "\x12" => [139, "\xfe"], "\x13" => [141, "\xfe"], "\x14" => [145, "\xfe"], "\x15" => [147, "\xfe"], "\x16" => [149, "\xfe"], "\x17" => [101, "\xfe"], "\x18" => [112, "\xfe"], "\x19" => [117, "\xfe"], "\x1a" => [120, "\xfe"], "\x1b" => [124, "\xfe"], "\x1c" => [127, "\xfe"], "\x1d" => [144, "\xfe"], "\x1e" => [152, "\xfe"], "\x1f" => [11, "\xfe"], " " => [92, "\x02"], "!" => [95, "\x02"], "\"" => [137, "\x02"], "#" => [142, "\x02"], "\$" => [150, "\x02"], "%" => [74, "\x02"], "&" => [90, "\x02"], "'" => [98, "\x02"], "(" => [107, "\x02"], ")" => [140, "\x02"], "*" => [146, "\x02"], "+" => [102, "\x02"], "," => [113, "\x02"], "-" => [121, "\x02"], "." => [128, "\x02"], "/" => [12, "\x02"], [92, "\x03"], [95, "\x03"], [137, "\x03"], [142, "\x03"], [150, "\x03"], [74, "\x03"], [90, "\x03"], [98, "\x03"], [107, "\x03"], [140, "\x03"], ":" => [146, "\x03"], ";" => [102, "\x03"], "<" => [113, "\x03"], "=" => [121, "\x03"], ">" => [128, "\x03"], "?" => [12, "\x03"], "@" => [92, "\x04"], "A" => [95, "\x04"], "B" => [137, "\x04"], "C" => [142, "\x04"], "D" => [150, "\x04"], "E" => [74, "\x04"], "F" => [90, "\x04"], "G" => [98, "\x04"], "H" => [107, "\x04"], "I" => [140, "\x04"], "J" => [146, "\x04"], "K" => [102, "\x04"], "L" => [113, "\x04"], "M" => [121, "\x04"], "N" => [128, "\x04"], "O" => [12, "\x04"], "P" => [92, "\x05"], "Q" => [95, "\x05"], "R" => [137, "\x05"], "S" => [142, "\x05"], "T" => [150, "\x05"], "U" => [74, "\x05"], "V" => [90, "\x05"], "W" => [98, "\x05"], "X" => [107, "\x05"], "Y" => [140, "\x05"], "Z" => [146, "\x05"], "[" => [102, "\x05"], "\\" => [113, "\x05"], "]" => [121, "\x05"], "^" => [128, "\x05"], "_" => [12, "\x05"], "`" => [92, "\x06"], "a" => [95, "\x06"], "b" => [137, "\x06"], "c" => [142, "\x06"], "d" => [150, "\x06"], "e" => [74, "\x06"], "f" => [90, "\x06"], "g" => [98, "\x06"], "h" => [107, "\x06"], "i" => [140, "\x06"], "j" => [146, "\x06"], "k" => [102, "\x06"], "l" => [113, "\x06"], "m" => [121, "\x06"], "n" => [128, "\x06"], "o" => [12, "\x06"], "p" => [92, "\x07"], "q" => [95, "\x07"], "r" => [137, "\x07"], "s" => [142, "\x07"], "t" => [150, "\x07"], "u" => [74, "\x07"], "v" => [90, "\x07"], "w" => [98, "\x07"], "x" => [107, "\x07"], "y" => [140, "\x07"], "z" => [146, "\x07"], "{" => [102, "\x07"], "|" => [113, "\x07"], "}" => [121, "\x07"], "~" => [128, "\x07"], "" => [12, "\x07"], "\x80" => [92, "\x08"], "\x81" => [95, "\x08"], "\x82" => [137, "\x08"], "\x83" => [142, "\x08"], "\x84" => [150, "\x08"], "\x85" => [74, "\x08"], "\x86" => [90, "\x08"], "\x87" => [98, "\x08"], "\x88" => [107, "\x08"], "\x89" => [140, "\x08"], "\x8a" => [146, "\x08"], "\x8b" => [102, "\x08"], "\x8c" => [113, "\x08"], "\x8d" => [121, "\x08"], "\x8e" => [128, "\x08"], "\x8f" => [12, "\x08"], "\x90" => [92, "\v"], "\x91" => [95, "\v"], "\x92" => [137, "\v"], "\x93" => [142, "\v"], "\x94" => [150, "\v"], "\x95" => [74, "\v"], "\x96" => [90, "\v"], "\x97" => [98, "\v"], "\x98" => [107, "\v"], "\x99" => [140, "\v"], "\x9a" => [146, "\v"], "\x9b" => [102, "\v"], "\x9c" => [113, "\v"], "\x9d" => [121, "\v"], "\x9e" => [128, "\v"], "\x9f" => [12, "\v"], "\xa0" => [92, "\f"], "\xa1" => [95, "\f"], "\xa2" => [137, "\f"], "\xa3" => [142, "\f"], "\xa4" => [150, "\f"], "\xa5" => [74, "\f"], "\xa6" => [90, "\f"], "\xa7" => [98, "\f"], "\xa8" => [107, "\f"], "\xa9" => [140, "\f"], "\xaa" => [146, "\f"], "\xab" => [102, "\f"], "\xac" => [113, "\f"], "\xad" => [121, "\f"], "\xae" => [128, "\f"], "\xaf" => [12, "\f"], "\xb0" => [92, "\x0e"], "\xb1" => [95, "\x0e"], "\xb2" => [137, "\x0e"], "\xb3" => [142, "\x0e"], "\xb4" => [150, "\x0e"], "\xb5" => [74, "\x0e"], "\xb6" => [90, "\x0e"], "\xb7" => [98, "\x0e"], "\xb8" => [107, "\x0e"], "\xb9" => [140, "\x0e"], "\xba" => [146, "\x0e"], "\xbb" => [102, "\x0e"], "\xbc" => [113, "\x0e"], "\xbd" => [121, "\x0e"], "\xbe" => [128, "\x0e"], "\xbf" => [12, "\x0e"], "\xc0" => [92, "\x0f"], "\xc1" => [95, "\x0f"], "\xc2" => [137, "\x0f"], "\xc3" => [142, "\x0f"], "\xc4" => [150, "\x0f"], "\xc5" => [74, "\x0f"], "\xc6" => [90, "\x0f"], "\xc7" => [98, "\x0f"], "\xc8" => [107, "\x0f"], "\xc9" => [140, "\x0f"], "\xca" => [146, "\x0f"], "\xcb" => [102, "\x0f"], "\xcc" => [113, "\x0f"], "\xcd" => [121, "\x0f"], "\xce" => [128, "\x0f"], "\xcf" => [12, "\x0f"], "\xd0" => [92, "\x10"], "\xd1" => [95, "\x10"], "\xd2" => [137, "\x10"], "\xd3" => [142, "\x10"], "\xd4" => [150, "\x10"], "\xd5" => [74, "\x10"], "\xd6" => [90, "\x10"], "\xd7" => [98, "\x10"], "\xd8" => [107, "\x10"], "\xd9" => [140, "\x10"], "\xda" => [146, "\x10"], "\xdb" => [102, "\x10"], "\xdc" => [113, "\x10"], "\xdd" => [121, "\x10"], "\xde" => [128, "\x10"], "\xdf" => [12, "\x10"], "\xe0" => [92, "\x11"], "\xe1" => [95, "\x11"], "\xe2" => [137, "\x11"], "\xe3" => [142, "\x11"], "\xe4" => [150, "\x11"], "\xe5" => [74, "\x11"], "\xe6" => [90, "\x11"], "\xe7" => [98, "\x11"], "\xe8" => [107, "\x11"], "\xe9" => [140, "\x11"], "\xea" => [146, "\x11"], "\xeb" => [102, "\x11"], "\xec" => [113, "\x11"], "\xed" => [121, "\x11"], "\xee" => [128, "\x11"], "\xef" => [12, "\x11"], "\xf0" => [92, "\x12"], "\xf1" => [95, "\x12"], "\xf2" => [137, "\x12"], "\xf3" => [142, "\x12"], "\xf4" => [150, "\x12"], "\xf5" => [74, "\x12"], "\xf6" => [90, "\x12"], "\xf7" => [98, "\x12"], "\xf8" => [107, "\x12"], "\xf9" => [140, "\x12"], "\xfa" => [146, "\x12"], "\xfb" => [102, "\x12"], "\xfc" => [113, "\x12"], "\xfd" => [121, "\x12"], "\xfe" => [128, "\x12"], "\xff" => [12, "\x12"]], ["\x00" => [92, "\xfe"], "\x01" => [95, "\xfe"], "\x02" => [137, "\xfe"], "\x03" => [142, "\xfe"], "\x04" => [150, "\xfe"], "\x05" => [74, "\xfe"], "\x06" => [90, "\xfe"], "\x07" => [98, "\xfe"], "\x08" => [107, "\xfe"], "\t" => [140, "\xfe"], "\n" => [146, "\xfe"], "\v" => [102, "\xfe"], "\f" => [113, "\xfe"], "\r" => [121, "\xfe"], "\x0e" => [128, "\xfe"], "\x0f" => [12, "\xfe"], "\x10" => [93, "\x02"], "\x11" => [138, "\x02"], "\x12" => [75, "\x02"], "\x13" => [91, "\x02"], "\x14" => [108, "\x02"], "\x15" => [103, "\x02"], "\x16" => [114, "\x02"], "\x17" => [14, "\x02"], "\x18" => [93, "\x03"], "\x19" => [138, "\x03"], "\x1a" => [75, "\x03"], "\x1b" => [91, "\x03"], "\x1c" => [108, "\x03"], "\x1d" => [103, "\x03"], "\x1e" => [114, "\x03"], "\x1f" => [14, "\x03"], " " => [93, "\x04"], "!" => [138, "\x04"], "\"" => [75, "\x04"], "#" => [91, "\x04"], "\$" => [108, "\x04"], "%" => [103, "\x04"], "&" => [114, "\x04"], "'" => [14, "\x04"], "(" => [93, "\x05"], ")" => [138, "\x05"], "*" => [75, "\x05"], "+" => [91, "\x05"], "," => [108, "\x05"], "-" => [103, "\x05"], "." => [114, "\x05"], "/" => [14, "\x05"], [93, "\x06"], [138, "\x06"], [75, "\x06"], [91, "\x06"], [108, "\x06"], [103, "\x06"], [114, "\x06"], [14, "\x06"], [93, "\x07"], [138, "\x07"], ":" => [75, "\x07"], ";" => [91, "\x07"], "<" => [108, "\x07"], "=" => [103, "\x07"], ">" => [114, "\x07"], "?" => [14, "\x07"], "@" => [93, "\x08"], "A" => [138, "\x08"], "B" => [75, "\x08"], "C" => [91, "\x08"], "D" => [108, "\x08"], "E" => [103, "\x08"], "F" => [114, "\x08"], "G" => [14, "\x08"], "H" => [93, "\v"], "I" => [138, "\v"], "J" => [75, "\v"], "K" => [91, "\v"], "L" => [108, "\v"], "M" => [103, "\v"], "N" => [114, "\v"], "O" => [14, "\v"], "P" => [93, "\f"], "Q" => [138, "\f"], "R" => [75, "\f"], "S" => [91, "\f"], "T" => [108, "\f"], "U" => [103, "\f"], "V" => [114, "\f"], "W" => [14, "\f"], "X" => [93, "\x0e"], "Y" => [138, "\x0e"], "Z" => [75, "\x0e"], "[" => [91, "\x0e"], "\\" => [108, "\x0e"], "]" => [103, "\x0e"], "^" => [114, "\x0e"], "_" => [14, "\x0e"], "`" => [93, "\x0f"], "a" => [138, "\x0f"], "b" => [75, "\x0f"], "c" => [91, "\x0f"], "d" => [108, "\x0f"], "e" => [103, "\x0f"], "f" => [114, "\x0f"], "g" => [14, "\x0f"], "h" => [93, "\x10"], "i" => [138, "\x10"], "j" => [75, "\x10"], "k" => [91, "\x10"], "l" => [108, "\x10"], "m" => [103, "\x10"], "n" => [114, "\x10"], "o" => [14, "\x10"], "p" => [93, "\x11"], "q" => [138, "\x11"], "r" => [75, "\x11"], "s" => [91, "\x11"], "t" => [108, "\x11"], "u" => [103, "\x11"], "v" => [114, "\x11"], "w" => [14, "\x11"], "x" => [93, "\x12"], "y" => [138, "\x12"], "z" => [75, "\x12"], "{" => [91, "\x12"], "|" => [108, "\x12"], "}" => [103, "\x12"], "~" => [114, "\x12"], "" => [14, "\x12"], "\x80" => [93, "\x13"], "\x81" => [138, "\x13"], "\x82" => [75, "\x13"], "\x83" => [91, "\x13"], "\x84" => [108, "\x13"], "\x85" => [103, "\x13"], "\x86" => [114, "\x13"], "\x87" => [14, "\x13"], "\x88" => [93, "\x14"], "\x89" => [138, "\x14"], "\x8a" => [75, "\x14"], "\x8b" => [91, "\x14"], "\x8c" => [108, "\x14"], "\x8d" => [103, "\x14"], "\x8e" => [114, "\x14"], "\x8f" => [14, "\x14"], "\x90" => [93, "\x15"], "\x91" => [138, "\x15"], "\x92" => [75, "\x15"], "\x93" => [91, "\x15"], "\x94" => [108, "\x15"], "\x95" => [103, "\x15"], "\x96" => [114, "\x15"], "\x97" => [14, "\x15"], "\x98" => [93, "\x17"], "\x99" => [138, "\x17"], "\x9a" => [75, "\x17"], "\x9b" => [91, "\x17"], "\x9c" => [108, "\x17"], "\x9d" => [103, "\x17"], "\x9e" => [114, "\x17"], "\x9f" => [14, "\x17"], "\xa0" => [93, "\x18"], "\xa1" => [138, "\x18"], "\xa2" => [75, "\x18"], "\xa3" => [91, "\x18"], "\xa4" => [108, "\x18"], "\xa5" => [103, "\x18"], "\xa6" => [114, "\x18"], "\xa7" => [14, "\x18"], "\xa8" => [93, "\x19"], "\xa9" => [138, "\x19"], "\xaa" => [75, "\x19"], "\xab" => [91, "\x19"], "\xac" => [108, "\x19"], "\xad" => [103, "\x19"], "\xae" => [114, "\x19"], "\xaf" => [14, "\x19"], "\xb0" => [93, "\x1a"], "\xb1" => [138, "\x1a"], "\xb2" => [75, "\x1a"], "\xb3" => [91, "\x1a"], "\xb4" => [108, "\x1a"], "\xb5" => [103, "\x1a"], "\xb6" => [114, "\x1a"], "\xb7" => [14, "\x1a"], "\xb8" => [93, "\x1b"], "\xb9" => [138, "\x1b"], "\xba" => [75, "\x1b"], "\xbb" => [91, "\x1b"], "\xbc" => [108, "\x1b"], "\xbd" => [103, "\x1b"], "\xbe" => [114, "\x1b"], "\xbf" => [14, "\x1b"], "\xc0" => [93, "\x1c"], "\xc1" => [138, "\x1c"], "\xc2" => [75, "\x1c"], "\xc3" => [91, "\x1c"], "\xc4" => [108, "\x1c"], "\xc5" => [103, "\x1c"], "\xc6" => [114, "\x1c"], "\xc7" => [14, "\x1c"], "\xc8" => [93, "\x1d"], "\xc9" => [138, "\x1d"], "\xca" => [75, "\x1d"], "\xcb" => [91, "\x1d"], "\xcc" => [108, "\x1d"], "\xcd" => [103, "\x1d"], "\xce" => [114, "\x1d"], "\xcf" => [14, "\x1d"], "\xd0" => [93, "\x1e"], "\xd1" => [138, "\x1e"], "\xd2" => [75, "\x1e"], "\xd3" => [91, "\x1e"], "\xd4" => [108, "\x1e"], "\xd5" => [103, "\x1e"], "\xd6" => [114, "\x1e"], "\xd7" => [14, "\x1e"], "\xd8" => [93, "\x1f"], "\xd9" => [138, "\x1f"], "\xda" => [75, "\x1f"], "\xdb" => [91, "\x1f"], "\xdc" => [108, "\x1f"], "\xdd" => [103, "\x1f"], "\xde" => [114, "\x1f"], "\xdf" => [14, "\x1f"], "\xe0" => [93, ""], "\xe1" => [138, ""], "\xe2" => [75, ""], "\xe3" => [91, ""], "\xe4" => [108, ""], "\xe5" => [103, ""], "\xe6" => [114, ""], "\xe7" => [14, ""], "\xe8" => [93, "\xdc"], "\xe9" => [138, "\xdc"], "\xea" => [75, "\xdc"], "\xeb" => [91, "\xdc"], "\xec" => [108, "\xdc"], "\xed" => [103, "\xdc"], "\xee" => [114, "\xdc"], "\xef" => [14, "\xdc"], "\xf0" => [93, "\xf9"], "\xf1" => [138, "\xf9"], "\xf2" => [75, "\xf9"], "\xf3" => [91, "\xf9"], "\xf4" => [108, "\xf9"], "\xf5" => [103, "\xf9"], "\xf6" => [114, "\xf9"], "\xf7" => [14, "\xf9"], "\xf8" => [77, "\n"], "\xf9" => [18, "\n"], "\xfa" => [77, "\r"], "\xfb" => [18, "\r"], "\xfc" => [77, "\x16"], "\xfd" => [18, "\x16"], "\xfe" => [77, ""], "\xff" => [18, ""]], ["\x00" => [93, "\xd3"], "\x01" => [138, "\xd3"], "\x02" => [75, "\xd3"], "\x03" => [91, "\xd3"], "\x04" => [108, "\xd3"], "\x05" => [103, "\xd3"], "\x06" => [114, "\xd3"], "\x07" => [14, "\xd3"], "\x08" => [93, "\xd4"], "\t" => [138, "\xd4"], "\n" => [75, "\xd4"], "\v" => [91, "\xd4"], "\f" => [108, "\xd4"], "\r" => [103, "\xd4"], "\x0e" => [114, "\xd4"], "\x0f" => [14, "\xd4"], "\x10" => [93, "\xd6"], "\x11" => [138, "\xd6"], "\x12" => [75, "\xd6"], "\x13" => [91, "\xd6"], "\x14" => [108, "\xd6"], "\x15" => [103, "\xd6"], "\x16" => [114, "\xd6"], "\x17" => [14, "\xd6"], "\x18" => [93, "\xdd"], "\x19" => [138, "\xdd"], "\x1a" => [75, "\xdd"], "\x1b" => [91, "\xdd"], "\x1c" => [108, "\xdd"], "\x1d" => [103, "\xdd"], "\x1e" => [114, "\xdd"], "\x1f" => [14, "\xdd"], " " => [93, "\xde"], "!" => [138, "\xde"], "\"" => [75, "\xde"], "#" => [91, "\xde"], "\$" => [108, "\xde"], "%" => [103, "\xde"], "&" => [114, "\xde"], "'" => [14, "\xde"], "(" => [93, "\xdf"], ")" => [138, "\xdf"], "*" => [75, "\xdf"], "+" => [91, "\xdf"], "," => [108, "\xdf"], "-" => [103, "\xdf"], "." => [114, "\xdf"], "/" => [14, "\xdf"], [93, "\xf1"], [138, "\xf1"], [75, "\xf1"], [91, "\xf1"], [108, "\xf1"], [103, "\xf1"], [114, "\xf1"], [14, "\xf1"], [93, "\xf4"], [138, "\xf4"], ":" => [75, "\xf4"], ";" => [91, "\xf4"], "<" => [108, "\xf4"], "=" => [103, "\xf4"], ">" => [114, "\xf4"], "?" => [14, "\xf4"], "@" => [93, "\xf5"], "A" => [138, "\xf5"], "B" => [75, "\xf5"], "C" => [91, "\xf5"], "D" => [108, "\xf5"], "E" => [103, "\xf5"], "F" => [114, "\xf5"], "G" => [14, "\xf5"], "H" => [93, "\xf6"], "I" => [138, "\xf6"], "J" => [75, "\xf6"], "K" => [91, "\xf6"], "L" => [108, "\xf6"], "M" => [103, "\xf6"], "N" => [114, "\xf6"], "O" => [14, "\xf6"], "P" => [93, "\xf7"], "Q" => [138, "\xf7"], "R" => [75, "\xf7"], "S" => [91, "\xf7"], "T" => [108, "\xf7"], "U" => [103, "\xf7"], "V" => [114, "\xf7"], "W" => [14, "\xf7"], "X" => [93, "\xf8"], "Y" => [138, "\xf8"], "Z" => [75, "\xf8"], "[" => [91, "\xf8"], "\\" => [108, "\xf8"], "]" => [103, "\xf8"], "^" => [114, "\xf8"], "_" => [14, "\xf8"], "`" => [93, "\xfa"], "a" => [138, "\xfa"], "b" => [75, "\xfa"], "c" => [91, "\xfa"], "d" => [108, "\xfa"], "e" => [103, "\xfa"], "f" => [114, "\xfa"], "g" => [14, "\xfa"], "h" => [93, "\xfb"], "i" => [138, "\xfb"], "j" => [75, "\xfb"], "k" => [91, "\xfb"], "l" => [108, "\xfb"], "m" => [103, "\xfb"], "n" => [114, "\xfb"], "o" => [14, "\xfb"], "p" => [93, "\xfc"], "q" => [138, "\xfc"], "r" => [75, "\xfc"], "s" => [91, "\xfc"], "t" => [108, "\xfc"], "u" => [103, "\xfc"], "v" => [114, "\xfc"], "w" => [14, "\xfc"], "x" => [93, "\xfd"], "y" => [138, "\xfd"], "z" => [75, "\xfd"], "{" => [91, "\xfd"], "|" => [108, "\xfd"], "}" => [103, "\xfd"], "~" => [114, "\xfd"], "" => [14, "\xfd"], "\x80" => [93, "\xfe"], "\x81" => [138, "\xfe"], "\x82" => [75, "\xfe"], "\x83" => [91, "\xfe"], "\x84" => [108, "\xfe"], "\x85" => [103, "\xfe"], "\x86" => [114, "\xfe"], "\x87" => [14, "\xfe"], "\x88" => [94, "\x02"], "\x89" => [76, "\x02"], "\x8a" => [104, "\x02"], "\x8b" => [16, "\x02"], "\x8c" => [94, "\x03"], "\x8d" => [76, "\x03"], "\x8e" => [104, "\x03"], "\x8f" => [16, "\x03"], "\x90" => [94, "\x04"], "\x91" => [76, "\x04"], "\x92" => [104, "\x04"], "\x93" => [16, "\x04"], "\x94" => [94, "\x05"], "\x95" => [76, "\x05"], "\x96" => [104, "\x05"], "\x97" => [16, "\x05"], "\x98" => [94, "\x06"], "\x99" => [76, "\x06"], "\x9a" => [104, "\x06"], "\x9b" => [16, "\x06"], "\x9c" => [94, "\x07"], "\x9d" => [76, "\x07"], "\x9e" => [104, "\x07"], "\x9f" => [16, "\x07"], "\xa0" => [94, "\x08"], "\xa1" => [76, "\x08"], "\xa2" => [104, "\x08"], "\xa3" => [16, "\x08"], "\xa4" => [94, "\v"], "\xa5" => [76, "\v"], "\xa6" => [104, "\v"], "\xa7" => [16, "\v"], "\xa8" => [94, "\f"], "\xa9" => [76, "\f"], "\xaa" => [104, "\f"], "\xab" => [16, "\f"], "\xac" => [94, "\x0e"], "\xad" => [76, "\x0e"], "\xae" => [104, "\x0e"], "\xaf" => [16, "\x0e"], "\xb0" => [94, "\x0f"], "\xb1" => [76, "\x0f"], "\xb2" => [104, "\x0f"], "\xb3" => [16, "\x0f"], "\xb4" => [94, "\x10"], "\xb5" => [76, "\x10"], "\xb6" => [104, "\x10"], "\xb7" => [16, "\x10"], "\xb8" => [94, "\x11"], "\xb9" => [76, "\x11"], "\xba" => [104, "\x11"], "\xbb" => [16, "\x11"], "\xbc" => [94, "\x12"], "\xbd" => [76, "\x12"], "\xbe" => [104, "\x12"], "\xbf" => [16, "\x12"], "\xc0" => [94, "\x13"], "\xc1" => [76, "\x13"], "\xc2" => [104, "\x13"], "\xc3" => [16, "\x13"], "\xc4" => [94, "\x14"], "\xc5" => [76, "\x14"], "\xc6" => [104, "\x14"], "\xc7" => [16, "\x14"], "\xc8" => [94, "\x15"], "\xc9" => [76, "\x15"], "\xca" => [104, "\x15"], "\xcb" => [16, "\x15"], "\xcc" => [94, "\x17"], "\xcd" => [76, "\x17"], "\xce" => [104, "\x17"], "\xcf" => [16, "\x17"], "\xd0" => [94, "\x18"], "\xd1" => [76, "\x18"], "\xd2" => [104, "\x18"], "\xd3" => [16, "\x18"], "\xd4" => [94, "\x19"], "\xd5" => [76, "\x19"], "\xd6" => [104, "\x19"], "\xd7" => [16, "\x19"], "\xd8" => [94, "\x1a"], "\xd9" => [76, "\x1a"], "\xda" => [104, "\x1a"], "\xdb" => [16, "\x1a"], "\xdc" => [94, "\x1b"], "\xdd" => [76, "\x1b"], "\xde" => [104, "\x1b"], "\xdf" => [16, "\x1b"], "\xe0" => [94, "\x1c"], "\xe1" => [76, "\x1c"], "\xe2" => [104, "\x1c"], "\xe3" => [16, "\x1c"], "\xe4" => [94, "\x1d"], "\xe5" => [76, "\x1d"], "\xe6" => [104, "\x1d"], "\xe7" => [16, "\x1d"], "\xe8" => [94, "\x1e"], "\xe9" => [76, "\x1e"], "\xea" => [104, "\x1e"], "\xeb" => [16, "\x1e"], "\xec" => [94, "\x1f"], "\xed" => [76, "\x1f"], "\xee" => [104, "\x1f"], "\xef" => [16, "\x1f"], "\xf0" => [94, ""], "\xf1" => [76, ""], "\xf2" => [104, ""], "\xf3" => [16, ""], "\xf4" => [94, "\xdc"], "\xf5" => [76, "\xdc"], "\xf6" => [104, "\xdc"], "\xf7" => [16, "\xdc"], "\xf8" => [94, "\xf9"], "\xf9" => [76, "\xf9"], "\xfa" => [104, "\xf9"], "\xfb" => [16, "\xf9"], "\xfc" => [0, "\n"], "\xfd" => [0, "\r"], "\xfe" => [0, "\x16"], "\xff" => [0, ""]], ["\x00" => [93, "\xc0"], "\x01" => [138, "\xc0"], "\x02" => [75, "\xc0"], "\x03" => [91, "\xc0"], "\x04" => [108, "\xc0"], "\x05" => [103, "\xc0"], "\x06" => [114, "\xc0"], "\x07" => [14, "\xc0"], "\x08" => [93, "\xc1"], "\t" => [138, "\xc1"], "\n" => [75, "\xc1"], "\v" => [91, "\xc1"], "\f" => [108, "\xc1"], "\r" => [103, "\xc1"], "\x0e" => [114, "\xc1"], "\x0f" => [14, "\xc1"], "\x10" => [93, "\xc8"], "\x11" => [138, "\xc8"], "\x12" => [75, "\xc8"], "\x13" => [91, "\xc8"], "\x14" => [108, "\xc8"], "\x15" => [103, "\xc8"], "\x16" => [114, "\xc8"], "\x17" => [14, "\xc8"], "\x18" => [93, "\xc9"], "\x19" => [138, "\xc9"], "\x1a" => [75, "\xc9"], "\x1b" => [91, "\xc9"], "\x1c" => [108, "\xc9"], "\x1d" => [103, "\xc9"], "\x1e" => [114, "\xc9"], "\x1f" => [14, "\xc9"], " " => [93, "\xca"], "!" => [138, "\xca"], "\"" => [75, "\xca"], "#" => [91, "\xca"], "\$" => [108, "\xca"], "%" => [103, "\xca"], "&" => [114, "\xca"], "'" => [14, "\xca"], "(" => [93, "\xcd"], ")" => [138, "\xcd"], "*" => [75, "\xcd"], "+" => [91, "\xcd"], "," => [108, "\xcd"], "-" => [103, "\xcd"], "." => [114, "\xcd"], "/" => [14, "\xcd"], [93, "\xd2"], [138, "\xd2"], [75, "\xd2"], [91, "\xd2"], [108, "\xd2"], [103, "\xd2"], [114, "\xd2"], [14, "\xd2"], [93, "\xd5"], [138, "\xd5"], ":" => [75, "\xd5"], ";" => [91, "\xd5"], "<" => [108, "\xd5"], "=" => [103, "\xd5"], ">" => [114, "\xd5"], "?" => [14, "\xd5"], "@" => [93, "\xda"], "A" => [138, "\xda"], "B" => [75, "\xda"], "C" => [91, "\xda"], "D" => [108, "\xda"], "E" => [103, "\xda"], "F" => [114, "\xda"], "G" => [14, "\xda"], "H" => [93, "\xdb"], "I" => [138, "\xdb"], "J" => [75, "\xdb"], "K" => [91, "\xdb"], "L" => [108, "\xdb"], "M" => [103, "\xdb"], "N" => [114, "\xdb"], "O" => [14, "\xdb"], "P" => [93, "\xee"], "Q" => [138, "\xee"], "R" => [75, "\xee"], "S" => [91, "\xee"], "T" => [108, "\xee"], "U" => [103, "\xee"], "V" => [114, "\xee"], "W" => [14, "\xee"], "X" => [93, "\xf0"], "Y" => [138, "\xf0"], "Z" => [75, "\xf0"], "[" => [91, "\xf0"], "\\" => [108, "\xf0"], "]" => [103, "\xf0"], "^" => [114, "\xf0"], "_" => [14, "\xf0"], "`" => [93, "\xf2"], "a" => [138, "\xf2"], "b" => [75, "\xf2"], "c" => [91, "\xf2"], "d" => [108, "\xf2"], "e" => [103, "\xf2"], "f" => [114, "\xf2"], "g" => [14, "\xf2"], "h" => [93, "\xf3"], "i" => [138, "\xf3"], "j" => [75, "\xf3"], "k" => [91, "\xf3"], "l" => [108, "\xf3"], "m" => [103, "\xf3"], "n" => [114, "\xf3"], "o" => [14, "\xf3"], "p" => [93, "\xff"], "q" => [138, "\xff"], "r" => [75, "\xff"], "s" => [91, "\xff"], "t" => [108, "\xff"], "u" => [103, "\xff"], "v" => [114, "\xff"], "w" => [14, "\xff"], "x" => [94, "\xcb"], "y" => [76, "\xcb"], "z" => [104, "\xcb"], "{" => [16, "\xcb"], "|" => [94, "\xcc"], "}" => [76, "\xcc"], "~" => [104, "\xcc"], "" => [16, "\xcc"], "\x80" => [94, "\xd3"], "\x81" => [76, "\xd3"], "\x82" => [104, "\xd3"], "\x83" => [16, "\xd3"], "\x84" => [94, "\xd4"], "\x85" => [76, "\xd4"], "\x86" => [104, "\xd4"], "\x87" => [16, "\xd4"], "\x88" => [94, "\xd6"], "\x89" => [76, "\xd6"], "\x8a" => [104, "\xd6"], "\x8b" => [16, "\xd6"], "\x8c" => [94, "\xdd"], "\x8d" => [76, "\xdd"], "\x8e" => [104, "\xdd"], "\x8f" => [16, "\xdd"], "\x90" => [94, "\xde"], "\x91" => [76, "\xde"], "\x92" => [104, "\xde"], "\x93" => [16, "\xde"], "\x94" => [94, "\xdf"], "\x95" => [76, "\xdf"], "\x96" => [104, "\xdf"], "\x97" => [16, "\xdf"], "\x98" => [94, "\xf1"], "\x99" => [76, "\xf1"], "\x9a" => [104, "\xf1"], "\x9b" => [16, "\xf1"], "\x9c" => [94, "\xf4"], "\x9d" => [76, "\xf4"], "\x9e" => [104, "\xf4"], "\x9f" => [16, "\xf4"], "\xa0" => [94, "\xf5"], "\xa1" => [76, "\xf5"], "\xa2" => [104, "\xf5"], "\xa3" => [16, "\xf5"], "\xa4" => [94, "\xf6"], "\xa5" => [76, "\xf6"], "\xa6" => [104, "\xf6"], "\xa7" => [16, "\xf6"], "\xa8" => [94, "\xf7"], "\xa9" => [76, "\xf7"], "\xaa" => [104, "\xf7"], "\xab" => [16, "\xf7"], "\xac" => [94, "\xf8"], "\xad" => [76, "\xf8"], "\xae" => [104, "\xf8"], "\xaf" => [16, "\xf8"], "\xb0" => [94, "\xfa"], "\xb1" => [76, "\xfa"], "\xb2" => [104, "\xfa"], "\xb3" => [16, "\xfa"], "\xb4" => [94, "\xfb"], "\xb5" => [76, "\xfb"], "\xb6" => [104, "\xfb"], "\xb7" => [16, "\xfb"], "\xb8" => [94, "\xfc"], "\xb9" => [76, "\xfc"], "\xba" => [104, "\xfc"], "\xbb" => [16, "\xfc"], "\xbc" => [94, "\xfd"], "\xbd" => [76, "\xfd"], "\xbe" => [104, "\xfd"], "\xbf" => [16, "\xfd"], "\xc0" => [94, "\xfe"], "\xc1" => [76, "\xfe"], "\xc2" => [104, "\xfe"], "\xc3" => [16, "\xfe"], "\xc4" => [77, "\x02"], "\xc5" => [18, "\x02"], "\xc6" => [77, "\x03"], "\xc7" => [18, "\x03"], "\xc8" => [77, "\x04"], "\xc9" => [18, "\x04"], "\xca" => [77, "\x05"], "\xcb" => [18, "\x05"], "\xcc" => [77, "\x06"], "\xcd" => [18, "\x06"], "\xce" => [77, "\x07"], "\xcf" => [18, "\x07"], "\xd0" => [77, "\x08"], "\xd1" => [18, "\x08"], "\xd2" => [77, "\v"], "\xd3" => [18, "\v"], "\xd4" => [77, "\f"], "\xd5" => [18, "\f"], "\xd6" => [77, "\x0e"], "\xd7" => [18, "\x0e"], "\xd8" => [77, "\x0f"], "\xd9" => [18, "\x0f"], "\xda" => [77, "\x10"], "\xdb" => [18, "\x10"], "\xdc" => [77, "\x11"], "\xdd" => [18, "\x11"], "\xde" => [77, "\x12"], "\xdf" => [18, "\x12"], "\xe0" => [77, "\x13"], "\xe1" => [18, "\x13"], "\xe2" => [77, "\x14"], "\xe3" => [18, "\x14"], "\xe4" => [77, "\x15"], "\xe5" => [18, "\x15"], "\xe6" => [77, "\x17"], "\xe7" => [18, "\x17"], "\xe8" => [77, "\x18"], "\xe9" => [18, "\x18"], "\xea" => [77, "\x19"], "\xeb" => [18, "\x19"], "\xec" => [77, "\x1a"], "\xed" => [18, "\x1a"], "\xee" => [77, "\x1b"], "\xef" => [18, "\x1b"], "\xf0" => [77, "\x1c"], "\xf1" => [18, "\x1c"], "\xf2" => [77, "\x1d"], "\xf3" => [18, "\x1d"], "\xf4" => [77, "\x1e"], "\xf5" => [18, "\x1e"], "\xf6" => [77, "\x1f"], "\xf7" => [18, "\x1f"], "\xf8" => [77, ""], "\xf9" => [18, ""], "\xfa" => [77, "\xdc"], "\xfb" => [18, "\xdc"], "\xfc" => [77, "\xf9"], "\xfd" => [18, "\xf9"], "\xfe" => [53, null], "\xff" => [66, null]], ["\x00" => [92, "\xab"], "\x01" => [95, "\xab"], "\x02" => [137, "\xab"], "\x03" => [142, "\xab"], "\x04" => [150, "\xab"], "\x05" => [74, "\xab"], "\x06" => [90, "\xab"], "\x07" => [98, "\xab"], "\x08" => [107, "\xab"], "\t" => [140, "\xab"], "\n" => [146, "\xab"], "\v" => [102, "\xab"], "\f" => [113, "\xab"], "\r" => [121, "\xab"], "\x0e" => [128, "\xab"], "\x0f" => [12, "\xab"], "\x10" => [92, "\xce"], "\x11" => [95, "\xce"], "\x12" => [137, "\xce"], "\x13" => [142, "\xce"], "\x14" => [150, "\xce"], "\x15" => [74, "\xce"], "\x16" => [90, "\xce"], "\x17" => [98, "\xce"], "\x18" => [107, "\xce"], "\x19" => [140, "\xce"], "\x1a" => [146, "\xce"], "\x1b" => [102, "\xce"], "\x1c" => [113, "\xce"], "\x1d" => [121, "\xce"], "\x1e" => [128, "\xce"], "\x1f" => [12, "\xce"], " " => [92, "\xd7"], "!" => [95, "\xd7"], "\"" => [137, "\xd7"], "#" => [142, "\xd7"], "\$" => [150, "\xd7"], "%" => [74, "\xd7"], "&" => [90, "\xd7"], "'" => [98, "\xd7"], "(" => [107, "\xd7"], ")" => [140, "\xd7"], "*" => [146, "\xd7"], "+" => [102, "\xd7"], "," => [113, "\xd7"], "-" => [121, "\xd7"], "." => [128, "\xd7"], "/" => [12, "\xd7"], [92, "\xe1"], [95, "\xe1"], [137, "\xe1"], [142, "\xe1"], [150, "\xe1"], [74, "\xe1"], [90, "\xe1"], [98, "\xe1"], [107, "\xe1"], [140, "\xe1"], ":" => [146, "\xe1"], ";" => [102, "\xe1"], "<" => [113, "\xe1"], "=" => [121, "\xe1"], ">" => [128, "\xe1"], "?" => [12, "\xe1"], "@" => [92, "\xec"], "A" => [95, "\xec"], "B" => [137, "\xec"], "C" => [142, "\xec"], "D" => [150, "\xec"], "E" => [74, "\xec"], "F" => [90, "\xec"], "G" => [98, "\xec"], "H" => [107, "\xec"], "I" => [140, "\xec"], "J" => [146, "\xec"], "K" => [102, "\xec"], "L" => [113, "\xec"], "M" => [121, "\xec"], "N" => [128, "\xec"], "O" => [12, "\xec"], "P" => [92, "\xed"], "Q" => [95, "\xed"], "R" => [137, "\xed"], "S" => [142, "\xed"], "T" => [150, "\xed"], "U" => [74, "\xed"], "V" => [90, "\xed"], "W" => [98, "\xed"], "X" => [107, "\xed"], "Y" => [140, "\xed"], "Z" => [146, "\xed"], "[" => [102, "\xed"], "\\" => [113, "\xed"], "]" => [121, "\xed"], "^" => [128, "\xed"], "_" => [12, "\xed"], "`" => [93, "\xc7"], "a" => [138, "\xc7"], "b" => [75, "\xc7"], "c" => [91, "\xc7"], "d" => [108, "\xc7"], "e" => [103, "\xc7"], "f" => [114, "\xc7"], "g" => [14, "\xc7"], "h" => [93, "\xcf"], "i" => [138, "\xcf"], "j" => [75, "\xcf"], "k" => [91, "\xcf"], "l" => [108, "\xcf"], "m" => [103, "\xcf"], "n" => [114, "\xcf"], "o" => [14, "\xcf"], "p" => [93, "\xea"], "q" => [138, "\xea"], "r" => [75, "\xea"], "s" => [91, "\xea"], "t" => [108, "\xea"], "u" => [103, "\xea"], "v" => [114, "\xea"], "w" => [14, "\xea"], "x" => [93, "\xeb"], "y" => [138, "\xeb"], "z" => [75, "\xeb"], "{" => [91, "\xeb"], "|" => [108, "\xeb"], "}" => [103, "\xeb"], "~" => [114, "\xeb"], "" => [14, "\xeb"], "\x80" => [94, "\xc0"], "\x81" => [76, "\xc0"], "\x82" => [104, "\xc0"], "\x83" => [16, "\xc0"], "\x84" => [94, "\xc1"], "\x85" => [76, "\xc1"], "\x86" => [104, "\xc1"], "\x87" => [16, "\xc1"], "\x88" => [94, "\xc8"], "\x89" => [76, "\xc8"], "\x8a" => [104, "\xc8"], "\x8b" => [16, "\xc8"], "\x8c" => [94, "\xc9"], "\x8d" => [76, "\xc9"], "\x8e" => [104, "\xc9"], "\x8f" => [16, "\xc9"], "\x90" => [94, "\xca"], "\x91" => [76, "\xca"], "\x92" => [104, "\xca"], "\x93" => [16, "\xca"], "\x94" => [94, "\xcd"], "\x95" => [76, "\xcd"], "\x96" => [104, "\xcd"], "\x97" => [16, "\xcd"], "\x98" => [94, "\xd2"], "\x99" => [76, "\xd2"], "\x9a" => [104, "\xd2"], "\x9b" => [16, "\xd2"], "\x9c" => [94, "\xd5"], "\x9d" => [76, "\xd5"], "\x9e" => [104, "\xd5"], "\x9f" => [16, "\xd5"], "\xa0" => [94, "\xda"], "\xa1" => [76, "\xda"], "\xa2" => [104, "\xda"], "\xa3" => [16, "\xda"], "\xa4" => [94, "\xdb"], "\xa5" => [76, "\xdb"], "\xa6" => [104, "\xdb"], "\xa7" => [16, "\xdb"], "\xa8" => [94, "\xee"], "\xa9" => [76, "\xee"], "\xaa" => [104, "\xee"], "\xab" => [16, "\xee"], "\xac" => [94, "\xf0"], "\xad" => [76, "\xf0"], "\xae" => [104, "\xf0"], "\xaf" => [16, "\xf0"], "\xb0" => [94, "\xf2"], "\xb1" => [76, "\xf2"], "\xb2" => [104, "\xf2"], "\xb3" => [16, "\xf2"], "\xb4" => [94, "\xf3"], "\xb5" => [76, "\xf3"], "\xb6" => [104, "\xf3"], "\xb7" => [16, "\xf3"], "\xb8" => [94, "\xff"], "\xb9" => [76, "\xff"], "\xba" => [104, "\xff"], "\xbb" => [16, "\xff"], "\xbc" => [77, "\xcb"], "\xbd" => [18, "\xcb"], "\xbe" => [77, "\xcc"], "\xbf" => [18, "\xcc"], "\xc0" => [77, "\xd3"], "\xc1" => [18, "\xd3"], "\xc2" => [77, "\xd4"], "\xc3" => [18, "\xd4"], "\xc4" => [77, "\xd6"], "\xc5" => [18, "\xd6"], "\xc6" => [77, "\xdd"], "\xc7" => [18, "\xdd"], "\xc8" => [77, "\xde"], "\xc9" => [18, "\xde"], "\xca" => [77, "\xdf"], "\xcb" => [18, "\xdf"], "\xcc" => [77, "\xf1"], "\xcd" => [18, "\xf1"], "\xce" => [77, "\xf4"], "\xcf" => [18, "\xf4"], "\xd0" => [77, "\xf5"], "\xd1" => [18, "\xf5"], "\xd2" => [77, "\xf6"], "\xd3" => [18, "\xf6"], "\xd4" => [77, "\xf7"], "\xd5" => [18, "\xf7"], "\xd6" => [77, "\xf8"], "\xd7" => [18, "\xf8"], "\xd8" => [77, "\xfa"], "\xd9" => [18, "\xfa"], "\xda" => [77, "\xfb"], "\xdb" => [18, "\xfb"], "\xdc" => [77, "\xfc"], "\xdd" => [18, "\xfc"], "\xde" => [77, "\xfd"], "\xdf" => [18, "\xfd"], "\xe0" => [77, "\xfe"], "\xe1" => [18, "\xfe"], "\xe2" => [0, "\x02"], "\xe3" => [0, "\x03"], "\xe4" => [0, "\x04"], "\xe5" => [0, "\x05"], "\xe6" => [0, "\x06"], "\xe7" => [0, "\x07"], "\xe8" => [0, "\x08"], "\xe9" => [0, "\v"], "\xea" => [0, "\f"], "\xeb" => [0, "\x0e"], "\xec" => [0, "\x0f"], "\xed" => [0, "\x10"], "\xee" => [0, "\x11"], "\xef" => [0, "\x12"], "\xf0" => [0, "\x13"], "\xf1" => [0, "\x14"], "\xf2" => [0, "\x15"], "\xf3" => [0, "\x17"], "\xf4" => [0, "\x18"], "\xf5" => [0, "\x19"], "\xf6" => [0, "\x1a"], "\xf7" => [0, "\x1b"], "\xf8" => [0, "\x1c"], "\xf9" => [0, "\x1d"], "\xfa" => [0, "\x1e"], "\xfb" => [0, "\x1f"], "\xfc" => [0, ""], "\xfd" => [0, "\xdc"], "\xfe" => [0, "\xf9"], "\xff" => [54, null]], ["\x00" => [92, "\xbc"], "\x01" => [95, "\xbc"], "\x02" => [137, "\xbc"], "\x03" => [142, "\xbc"], "\x04" => [150, "\xbc"], "\x05" => [74, "\xbc"], "\x06" => [90, "\xbc"], "\x07" => [98, "\xbc"], "\x08" => [107, "\xbc"], "\t" => [140, "\xbc"], "\n" => [146, "\xbc"], "\v" => [102, "\xbc"], "\f" => [113, "\xbc"], "\r" => [121, "\xbc"], "\x0e" => [128, "\xbc"], "\x0f" => [12, "\xbc"], "\x10" => [92, "\xbf"], "\x11" => [95, "\xbf"], "\x12" => [137, "\xbf"], "\x13" => [142, "\xbf"], "\x14" => [150, "\xbf"], "\x15" => [74, "\xbf"], "\x16" => [90, "\xbf"], "\x17" => [98, "\xbf"], "\x18" => [107, "\xbf"], "\x19" => [140, "\xbf"], "\x1a" => [146, "\xbf"], "\x1b" => [102, "\xbf"], "\x1c" => [113, "\xbf"], "\x1d" => [121, "\xbf"], "\x1e" => [128, "\xbf"], "\x1f" => [12, "\xbf"], " " => [92, "\xc5"], "!" => [95, "\xc5"], "\"" => [137, "\xc5"], "#" => [142, "\xc5"], "\$" => [150, "\xc5"], "%" => [74, "\xc5"], "&" => [90, "\xc5"], "'" => [98, "\xc5"], "(" => [107, "\xc5"], ")" => [140, "\xc5"], "*" => [146, "\xc5"], "+" => [102, "\xc5"], "," => [113, "\xc5"], "-" => [121, "\xc5"], "." => [128, "\xc5"], "/" => [12, "\xc5"], [92, "\xe7"], [95, "\xe7"], [137, "\xe7"], [142, "\xe7"], [150, "\xe7"], [74, "\xe7"], [90, "\xe7"], [98, "\xe7"], [107, "\xe7"], [140, "\xe7"], ":" => [146, "\xe7"], ";" => [102, "\xe7"], "<" => [113, "\xe7"], "=" => [121, "\xe7"], ">" => [128, "\xe7"], "?" => [12, "\xe7"], "@" => [92, "\xef"], "A" => [95, "\xef"], "B" => [137, "\xef"], "C" => [142, "\xef"], "D" => [150, "\xef"], "E" => [74, "\xef"], "F" => [90, "\xef"], "G" => [98, "\xef"], "H" => [107, "\xef"], "I" => [140, "\xef"], "J" => [146, "\xef"], "K" => [102, "\xef"], "L" => [113, "\xef"], "M" => [121, "\xef"], "N" => [128, "\xef"], "O" => [12, "\xef"], "P" => [93, "\t"], "Q" => [138, "\t"], "R" => [75, "\t"], "S" => [91, "\t"], "T" => [108, "\t"], "U" => [103, "\t"], "V" => [114, "\t"], "W" => [14, "\t"], "X" => [93, "\x8e"], "Y" => [138, "\x8e"], "Z" => [75, "\x8e"], "[" => [91, "\x8e"], "\\" => [108, "\x8e"], "]" => [103, "\x8e"], "^" => [114, "\x8e"], "_" => [14, "\x8e"], "`" => [93, "\x90"], "a" => [138, "\x90"], "b" => [75, "\x90"], "c" => [91, "\x90"], "d" => [108, "\x90"], "e" => [103, "\x90"], "f" => [114, "\x90"], "g" => [14, "\x90"], "h" => [93, "\x91"], "i" => [138, "\x91"], "j" => [75, "\x91"], "k" => [91, "\x91"], "l" => [108, "\x91"], "m" => [103, "\x91"], "n" => [114, "\x91"], "o" => [14, "\x91"], "p" => [93, "\x94"], "q" => [138, "\x94"], "r" => [75, "\x94"], "s" => [91, "\x94"], "t" => [108, "\x94"], "u" => [103, "\x94"], "v" => [114, "\x94"], "w" => [14, "\x94"], "x" => [93, "\x9f"], "y" => [138, "\x9f"], "z" => [75, "\x9f"], "{" => [91, "\x9f"], "|" => [108, "\x9f"], "}" => [103, "\x9f"], "~" => [114, "\x9f"], "" => [14, "\x9f"], "\x80" => [93, "\xab"], "\x81" => [138, "\xab"], "\x82" => [75, "\xab"], "\x83" => [91, "\xab"], "\x84" => [108, "\xab"], "\x85" => [103, "\xab"], "\x86" => [114, "\xab"], "\x87" => [14, "\xab"], "\x88" => [93, "\xce"], "\x89" => [138, "\xce"], "\x8a" => [75, "\xce"], "\x8b" => [91, "\xce"], "\x8c" => [108, "\xce"], "\x8d" => [103, "\xce"], "\x8e" => [114, "\xce"], "\x8f" => [14, "\xce"], "\x90" => [93, "\xd7"], "\x91" => [138, "\xd7"], "\x92" => [75, "\xd7"], "\x93" => [91, "\xd7"], "\x94" => [108, "\xd7"], "\x95" => [103, "\xd7"], "\x96" => [114, "\xd7"], "\x97" => [14, "\xd7"], "\x98" => [93, "\xe1"], "\x99" => [138, "\xe1"], "\x9a" => [75, "\xe1"], "\x9b" => [91, "\xe1"], "\x9c" => [108, "\xe1"], "\x9d" => [103, "\xe1"], "\x9e" => [114, "\xe1"], "\x9f" => [14, "\xe1"], "\xa0" => [93, "\xec"], "\xa1" => [138, "\xec"], "\xa2" => [75, "\xec"], "\xa3" => [91, "\xec"], "\xa4" => [108, "\xec"], "\xa5" => [103, "\xec"], "\xa6" => [114, "\xec"], "\xa7" => [14, "\xec"], "\xa8" => [93, "\xed"], "\xa9" => [138, "\xed"], "\xaa" => [75, "\xed"], "\xab" => [91, "\xed"], "\xac" => [108, "\xed"], "\xad" => [103, "\xed"], "\xae" => [114, "\xed"], "\xaf" => [14, "\xed"], "\xb0" => [94, "\xc7"], "\xb1" => [76, "\xc7"], "\xb2" => [104, "\xc7"], "\xb3" => [16, "\xc7"], "\xb4" => [94, "\xcf"], "\xb5" => [76, "\xcf"], "\xb6" => [104, "\xcf"], "\xb7" => [16, "\xcf"], "\xb8" => [94, "\xea"], "\xb9" => [76, "\xea"], "\xba" => [104, "\xea"], "\xbb" => [16, "\xea"], "\xbc" => [94, "\xeb"], "\xbd" => [76, "\xeb"], "\xbe" => [104, "\xeb"], "\xbf" => [16, "\xeb"], "\xc0" => [77, "\xc0"], "\xc1" => [18, "\xc0"], "\xc2" => [77, "\xc1"], "\xc3" => [18, "\xc1"], "\xc4" => [77, "\xc8"], "\xc5" => [18, "\xc8"], "\xc6" => [77, "\xc9"], "\xc7" => [18, "\xc9"], "\xc8" => [77, "\xca"], "\xc9" => [18, "\xca"], "\xca" => [77, "\xcd"], "\xcb" => [18, "\xcd"], "\xcc" => [77, "\xd2"], "\xcd" => [18, "\xd2"], "\xce" => [77, "\xd5"], "\xcf" => [18, "\xd5"], "\xd0" => [77, "\xda"], "\xd1" => [18, "\xda"], "\xd2" => [77, "\xdb"], "\xd3" => [18, "\xdb"], "\xd4" => [77, "\xee"], "\xd5" => [18, "\xee"], "\xd6" => [77, "\xf0"], "\xd7" => [18, "\xf0"], "\xd8" => [77, "\xf2"], "\xd9" => [18, "\xf2"], "\xda" => [77, "\xf3"], "\xdb" => [18, "\xf3"], "\xdc" => [77, "\xff"], "\xdd" => [18, "\xff"], "\xde" => [0, "\xcb"], "\xdf" => [0, "\xcc"], "\xe0" => [0, "\xd3"], "\xe1" => [0, "\xd4"], "\xe2" => [0, "\xd6"], "\xe3" => [0, "\xdd"], "\xe4" => [0, "\xde"], "\xe5" => [0, "\xdf"], "\xe6" => [0, "\xf1"], "\xe7" => [0, "\xf4"], "\xe8" => [0, "\xf5"], "\xe9" => [0, "\xf6"], "\xea" => [0, "\xf7"], "\xeb" => [0, "\xf8"], "\xec" => [0, "\xfa"], "\xed" => [0, "\xfb"], "\xee" => [0, "\xfc"], "\xef" => [0, "\xfd"], "\xf0" => [0, "\xfe"], "\xf1" => [38, null], "\xf2" => [42, null], "\xf3" => [44, null], "\xf4" => [45, null], "\xf5" => [58, null], "\xf6" => [59, null], "\xf7" => [61, null], "\xf8" => [62, null], "\xf9" => [65, null], "\xfa" => [67, null], "\xfb" => [69, null], "\xfc" => [70, null], "\xfd" => [72, null], "\xfe" => [154, null], "\xff" => [55, null]], ["\x00" => [94, "\x020"], "\x01" => [76, "\x020"], "\x02" => [104, "\x020"], "\x03" => [16, "\x020"], "\x04" => [94, "\x021"], "\x05" => [76, "\x021"], "\x06" => [104, "\x021"], "\x07" => [16, "\x021"], "\x08" => [94, "\x022"], "\t" => [76, "\x022"], "\n" => [104, "\x022"], "\v" => [16, "\x022"], "\f" => [94, "\x02a"], "\r" => [76, "\x02a"], "\x0e" => [104, "\x02a"], "\x0f" => [16, "\x02a"], "\x10" => [94, "\x02c"], "\x11" => [76, "\x02c"], "\x12" => [104, "\x02c"], "\x13" => [16, "\x02c"], "\x14" => [94, "\x02e"], "\x15" => [76, "\x02e"], "\x16" => [104, "\x02e"], "\x17" => [16, "\x02e"], "\x18" => [94, "\x02i"], "\x19" => [76, "\x02i"], "\x1a" => [104, "\x02i"], "\x1b" => [16, "\x02i"], "\x1c" => [94, "\x02o"], "\x1d" => [76, "\x02o"], "\x1e" => [104, "\x02o"], "\x1f" => [16, "\x02o"], " " => [94, "\x02s"], "!" => [76, "\x02s"], "\"" => [104, "\x02s"], "#" => [16, "\x02s"], "\$" => [94, "\x02t"], "%" => [76, "\x02t"], "&" => [104, "\x02t"], "'" => [16, "\x02t"], "(" => [77, "\x02 "], ")" => [18, "\x02 "], "*" => [77, "\x02%"], "+" => [18, "\x02%"], "," => [77, "\x02-"], "-" => [18, "\x02-"], "." => [77, "\x02."], "/" => [18, "\x02."], [77, "\x02/"], [18, "\x02/"], [77, "\x023"], [18, "\x023"], [77, "\x024"], [18, "\x024"], [77, "\x025"], [18, "\x025"], [77, "\x026"], [18, "\x026"], ":" => [77, "\x027"], ";" => [18, "\x027"], "<" => [77, "\x028"], "=" => [18, "\x028"], ">" => [77, "\x029"], "?" => [18, "\x029"], "@" => [77, "\x02="], "A" => [18, "\x02="], "B" => [77, "\x02A"], "C" => [18, "\x02A"], "D" => [77, "\x02_"], "E" => [18, "\x02_"], "F" => [77, "\x02b"], "G" => [18, "\x02b"], "H" => [77, "\x02d"], "I" => [18, "\x02d"], "J" => [77, "\x02f"], "K" => [18, "\x02f"], "L" => [77, "\x02g"], "M" => [18, "\x02g"], "N" => [77, "\x02h"], "O" => [18, "\x02h"], "P" => [77, "\x02l"], "Q" => [18, "\x02l"], "R" => [77, "\x02m"], "S" => [18, "\x02m"], "T" => [77, "\x02n"], "U" => [18, "\x02n"], "V" => [77, "\x02p"], "W" => [18, "\x02p"], "X" => [77, "\x02r"], "Y" => [18, "\x02r"], "Z" => [77, "\x02u"], "[" => [18, "\x02u"], "\\" => [0, "\x02:"], "]" => [0, "\x02B"], "^" => [0, "\x02C"], "_" => [0, "\x02D"], "`" => [0, "\x02E"], "a" => [0, "\x02F"], "b" => [0, "\x02G"], "c" => [0, "\x02H"], "d" => [0, "\x02I"], "e" => [0, "\x02J"], "f" => [0, "\x02K"], "g" => [0, "\x02L"], "h" => [0, "\x02M"], "i" => [0, "\x02N"], "j" => [0, "\x02O"], "k" => [0, "\x02P"], "l" => [0, "\x02Q"], "m" => [0, "\x02R"], "n" => [0, "\x02S"], "o" => [0, "\x02T"], "p" => [0, "\x02U"], "q" => [0, "\x02V"], "r" => [0, "\x02W"], "s" => [0, "\x02Y"], "t" => [0, "\x02j"], "u" => [0, "\x02k"], "v" => [0, "\x02q"], "w" => [0, "\x02v"], "x" => [0, "\x02w"], "y" => [0, "\x02x"], "z" => [0, "\x02y"], "{" => [0, "\x02z"], "|" => [82, "\x02"], "}" => [87, "\x02"], "~" => [130, "\x02"], "" => [9, "\x02"], "\x80" => [94, "\x030"], "\x81" => [76, "\x030"], "\x82" => [104, "\x030"], "\x83" => [16, "\x030"], "\x84" => [94, "\x031"], "\x85" => [76, "\x031"], "\x86" => [104, "\x031"], "\x87" => [16, "\x031"], "\x88" => [94, "\x032"], "\x89" => [76, "\x032"], "\x8a" => [104, "\x032"], "\x8b" => [16, "\x032"], "\x8c" => [94, "\x03a"], "\x8d" => [76, "\x03a"], "\x8e" => [104, "\x03a"], "\x8f" => [16, "\x03a"], "\x90" => [94, "\x03c"], "\x91" => [76, "\x03c"], "\x92" => [104, "\x03c"], "\x93" => [16, "\x03c"], "\x94" => [94, "\x03e"], "\x95" => [76, "\x03e"], "\x96" => [104, "\x03e"], "\x97" => [16, "\x03e"], "\x98" => [94, "\x03i"], "\x99" => [76, "\x03i"], "\x9a" => [104, "\x03i"], "\x9b" => [16, "\x03i"], "\x9c" => [94, "\x03o"], "\x9d" => [76, "\x03o"], "\x9e" => [104, "\x03o"], "\x9f" => [16, "\x03o"], "\xa0" => [94, "\x03s"], "\xa1" => [76, "\x03s"], "\xa2" => [104, "\x03s"], "\xa3" => [16, "\x03s"], "\xa4" => [94, "\x03t"], "\xa5" => [76, "\x03t"], "\xa6" => [104, "\x03t"], "\xa7" => [16, "\x03t"], "\xa8" => [77, "\x03 "], "\xa9" => [18, "\x03 "], "\xaa" => [77, "\x03%"], "\xab" => [18, "\x03%"], "\xac" => [77, "\x03-"], "\xad" => [18, "\x03-"], "\xae" => [77, "\x03."], "\xaf" => [18, "\x03."], "\xb0" => [77, "\x03/"], "\xb1" => [18, "\x03/"], "\xb2" => [77, "\x033"], "\xb3" => [18, "\x033"], "\xb4" => [77, "\x034"], "\xb5" => [18, "\x034"], "\xb6" => [77, "\x035"], "\xb7" => [18, "\x035"], "\xb8" => [77, "\x036"], "\xb9" => [18, "\x036"], "\xba" => [77, "\x037"], "\xbb" => [18, "\x037"], "\xbc" => [77, "\x038"], "\xbd" => [18, "\x038"], "\xbe" => [77, "\x039"], "\xbf" => [18, "\x039"], "\xc0" => [77, "\x03="], "\xc1" => [18, "\x03="], "\xc2" => [77, "\x03A"], "\xc3" => [18, "\x03A"], "\xc4" => [77, "\x03_"], "\xc5" => [18, "\x03_"], "\xc6" => [77, "\x03b"], "\xc7" => [18, "\x03b"], "\xc8" => [77, "\x03d"], "\xc9" => [18, "\x03d"], "\xca" => [77, "\x03f"], "\xcb" => [18, "\x03f"], "\xcc" => [77, "\x03g"], "\xcd" => [18, "\x03g"], "\xce" => [77, "\x03h"], "\xcf" => [18, "\x03h"], "\xd0" => [77, "\x03l"], "\xd1" => [18, "\x03l"], "\xd2" => [77, "\x03m"], "\xd3" => [18, "\x03m"], "\xd4" => [77, "\x03n"], "\xd5" => [18, "\x03n"], "\xd6" => [77, "\x03p"], "\xd7" => [18, "\x03p"], "\xd8" => [77, "\x03r"], "\xd9" => [18, "\x03r"], "\xda" => [77, "\x03u"], "\xdb" => [18, "\x03u"], "\xdc" => [0, "\x03:"], "\xdd" => [0, "\x03B"], "\xde" => [0, "\x03C"], "\xdf" => [0, "\x03D"], "\xe0" => [0, "\x03E"], "\xe1" => [0, "\x03F"], "\xe2" => [0, "\x03G"], "\xe3" => [0, "\x03H"], "\xe4" => [0, "\x03I"], "\xe5" => [0, "\x03J"], "\xe6" => [0, "\x03K"], "\xe7" => [0, "\x03L"], "\xe8" => [0, "\x03M"], "\xe9" => [0, "\x03N"], "\xea" => [0, "\x03O"], "\xeb" => [0, "\x03P"], "\xec" => [0, "\x03Q"], "\xed" => [0, "\x03R"], "\xee" => [0, "\x03S"], "\xef" => [0, "\x03T"], "\xf0" => [0, "\x03U"], "\xf1" => [0, "\x03V"], "\xf2" => [0, "\x03W"], "\xf3" => [0, "\x03Y"], "\xf4" => [0, "\x03j"], "\xf5" => [0, "\x03k"], "\xf6" => [0, "\x03q"], "\xf7" => [0, "\x03v"], "\xf8" => [0, "\x03w"], "\xf9" => [0, "\x03x"], "\xfa" => [0, "\x03y"], "\xfb" => [0, "\x03z"], "\xfc" => [82, "\x03"], "\xfd" => [87, "\x03"], "\xfe" => [130, "\x03"], "\xff" => [9, "\x03"]], ["\x00" => [93, "\x93"], "\x01" => [138, "\x93"], "\x02" => [75, "\x93"], "\x03" => [91, "\x93"], "\x04" => [108, "\x93"], "\x05" => [103, "\x93"], "\x06" => [114, "\x93"], "\x07" => [14, "\x93"], "\x08" => [93, "\x95"], "\t" => [138, "\x95"], "\n" => [75, "\x95"], "\v" => [91, "\x95"], "\f" => [108, "\x95"], "\r" => [103, "\x95"], "\x0e" => [114, "\x95"], "\x0f" => [14, "\x95"], "\x10" => [93, "\x96"], "\x11" => [138, "\x96"], "\x12" => [75, "\x96"], "\x13" => [91, "\x96"], "\x14" => [108, "\x96"], "\x15" => [103, "\x96"], "\x16" => [114, "\x96"], "\x17" => [14, "\x96"], "\x18" => [93, "\x97"], "\x19" => [138, "\x97"], "\x1a" => [75, "\x97"], "\x1b" => [91, "\x97"], "\x1c" => [108, "\x97"], "\x1d" => [103, "\x97"], "\x1e" => [114, "\x97"], "\x1f" => [14, "\x97"], " " => [93, "\x98"], "!" => [138, "\x98"], "\"" => [75, "\x98"], "#" => [91, "\x98"], "\$" => [108, "\x98"], "%" => [103, "\x98"], "&" => [114, "\x98"], "'" => [14, "\x98"], "(" => [93, "\x9b"], ")" => [138, "\x9b"], "*" => [75, "\x9b"], "+" => [91, "\x9b"], "," => [108, "\x9b"], "-" => [103, "\x9b"], "." => [114, "\x9b"], "/" => [14, "\x9b"], [93, "\x9d"], [138, "\x9d"], [75, "\x9d"], [91, "\x9d"], [108, "\x9d"], [103, "\x9d"], [114, "\x9d"], [14, "\x9d"], [93, "\x9e"], [138, "\x9e"], ":" => [75, "\x9e"], ";" => [91, "\x9e"], "<" => [108, "\x9e"], "=" => [103, "\x9e"], ">" => [114, "\x9e"], "?" => [14, "\x9e"], "@" => [93, "\xa5"], "A" => [138, "\xa5"], "B" => [75, "\xa5"], "C" => [91, "\xa5"], "D" => [108, "\xa5"], "E" => [103, "\xa5"], "F" => [114, "\xa5"], "G" => [14, "\xa5"], "H" => [93, "\xa6"], "I" => [138, "\xa6"], "J" => [75, "\xa6"], "K" => [91, "\xa6"], "L" => [108, "\xa6"], "M" => [103, "\xa6"], "N" => [114, "\xa6"], "O" => [14, "\xa6"], "P" => [93, "\xa8"], "Q" => [138, "\xa8"], "R" => [75, "\xa8"], "S" => [91, "\xa8"], "T" => [108, "\xa8"], "U" => [103, "\xa8"], "V" => [114, "\xa8"], "W" => [14, "\xa8"], "X" => [93, "\xae"], "Y" => [138, "\xae"], "Z" => [75, "\xae"], "[" => [91, "\xae"], "\\" => [108, "\xae"], "]" => [103, "\xae"], "^" => [114, "\xae"], "_" => [14, "\xae"], "`" => [93, "\xaf"], "a" => [138, "\xaf"], "b" => [75, "\xaf"], "c" => [91, "\xaf"], "d" => [108, "\xaf"], "e" => [103, "\xaf"], "f" => [114, "\xaf"], "g" => [14, "\xaf"], "h" => [93, "\xb4"], "i" => [138, "\xb4"], "j" => [75, "\xb4"], "k" => [91, "\xb4"], "l" => [108, "\xb4"], "m" => [103, "\xb4"], "n" => [114, "\xb4"], "o" => [14, "\xb4"], "p" => [93, "\xb6"], "q" => [138, "\xb6"], "r" => [75, "\xb6"], "s" => [91, "\xb6"], "t" => [108, "\xb6"], "u" => [103, "\xb6"], "v" => [114, "\xb6"], "w" => [14, "\xb6"], "x" => [93, "\xb7"], "y" => [138, "\xb7"], "z" => [75, "\xb7"], "{" => [91, "\xb7"], "|" => [108, "\xb7"], "}" => [103, "\xb7"], "~" => [114, "\xb7"], "" => [14, "\xb7"], "\x80" => [93, "\xbc"], "\x81" => [138, "\xbc"], "\x82" => [75, "\xbc"], "\x83" => [91, "\xbc"], "\x84" => [108, "\xbc"], "\x85" => [103, "\xbc"], "\x86" => [114, "\xbc"], "\x87" => [14, "\xbc"], "\x88" => [93, "\xbf"], "\x89" => [138, "\xbf"], "\x8a" => [75, "\xbf"], "\x8b" => [91, "\xbf"], "\x8c" => [108, "\xbf"], "\x8d" => [103, "\xbf"], "\x8e" => [114, "\xbf"], "\x8f" => [14, "\xbf"], "\x90" => [93, "\xc5"], "\x91" => [138, "\xc5"], "\x92" => [75, "\xc5"], "\x93" => [91, "\xc5"], "\x94" => [108, "\xc5"], "\x95" => [103, "\xc5"], "\x96" => [114, "\xc5"], "\x97" => [14, "\xc5"], "\x98" => [93, "\xe7"], "\x99" => [138, "\xe7"], "\x9a" => [75, "\xe7"], "\x9b" => [91, "\xe7"], "\x9c" => [108, "\xe7"], "\x9d" => [103, "\xe7"], "\x9e" => [114, "\xe7"], "\x9f" => [14, "\xe7"], "\xa0" => [93, "\xef"], "\xa1" => [138, "\xef"], "\xa2" => [75, "\xef"], "\xa3" => [91, "\xef"], "\xa4" => [108, "\xef"], "\xa5" => [103, "\xef"], "\xa6" => [114, "\xef"], "\xa7" => [14, "\xef"], "\xa8" => [94, "\t"], "\xa9" => [76, "\t"], "\xaa" => [104, "\t"], "\xab" => [16, "\t"], "\xac" => [94, "\x8e"], "\xad" => [76, "\x8e"], "\xae" => [104, "\x8e"], "\xaf" => [16, "\x8e"], "\xb0" => [94, "\x90"], "\xb1" => [76, "\x90"], "\xb2" => [104, "\x90"], "\xb3" => [16, "\x90"], "\xb4" => [94, "\x91"], "\xb5" => [76, "\x91"], "\xb6" => [104, "\x91"], "\xb7" => [16, "\x91"], "\xb8" => [94, "\x94"], "\xb9" => [76, "\x94"], "\xba" => [104, "\x94"], "\xbb" => [16, "\x94"], "\xbc" => [94, "\x9f"], "\xbd" => [76, "\x9f"], "\xbe" => [104, "\x9f"], "\xbf" => [16, "\x9f"], "\xc0" => [94, "\xab"], "\xc1" => [76, "\xab"], "\xc2" => [104, "\xab"], "\xc3" => [16, "\xab"], "\xc4" => [94, "\xce"], "\xc5" => [76, "\xce"], "\xc6" => [104, "\xce"], "\xc7" => [16, "\xce"], "\xc8" => [94, "\xd7"], "\xc9" => [76, "\xd7"], "\xca" => [104, "\xd7"], "\xcb" => [16, "\xd7"], "\xcc" => [94, "\xe1"], "\xcd" => [76, "\xe1"], "\xce" => [104, "\xe1"], "\xcf" => [16, "\xe1"], "\xd0" => [94, "\xec"], "\xd1" => [76, "\xec"], "\xd2" => [104, "\xec"], "\xd3" => [16, "\xec"], "\xd4" => [94, "\xed"], "\xd5" => [76, "\xed"], "\xd6" => [104, "\xed"], "\xd7" => [16, "\xed"], "\xd8" => [77, "\xc7"], "\xd9" => [18, "\xc7"], "\xda" => [77, "\xcf"], "\xdb" => [18, "\xcf"], "\xdc" => [77, "\xea"], "\xdd" => [18, "\xea"], "\xde" => [77, "\xeb"], "\xdf" => [18, "\xeb"], "\xe0" => [0, "\xc0"], "\xe1" => [0, "\xc1"], "\xe2" => [0, "\xc8"], "\xe3" => [0, "\xc9"], "\xe4" => [0, "\xca"], "\xe5" => [0, "\xcd"], "\xe6" => [0, "\xd2"], "\xe7" => [0, "\xd5"], "\xe8" => [0, "\xda"], "\xe9" => [0, "\xdb"], "\xea" => [0, "\xee"], "\xeb" => [0, "\xf0"], "\xec" => [0, "\xf2"], "\xed" => [0, "\xf3"], "\xee" => [0, "\xff"], "\xef" => [233, null], "\xf0" => [238, null], "\xf1" => [240, null], "\xf2" => [246, null], "\xf3" => [254, null], "\xf4" => [257, null], "\xf5" => [259, null], "\xf6" => [260, null], "\xf7" => [262, null], "\xf8" => [40, null], "\xf9" => [43, null], "\xfa" => [46, null], "\xfb" => [60, null], "\xfc" => [63, null], "\xfd" => [68, null], "\xfe" => [71, null], "\xff" => [56, null]], ["\x00" => [94, "\xfe0"], "\x01" => [76, "\xfe0"], "\x02" => [104, "\xfe0"], "\x03" => [16, "\xfe0"], "\x04" => [94, "\xfe1"], "\x05" => [76, "\xfe1"], "\x06" => [104, "\xfe1"], "\x07" => [16, "\xfe1"], "\x08" => [94, "\xfe2"], "\t" => [76, "\xfe2"], "\n" => [104, "\xfe2"], "\v" => [16, "\xfe2"], "\f" => [94, "\xfea"], "\r" => [76, "\xfea"], "\x0e" => [104, "\xfea"], "\x0f" => [16, "\xfea"], "\x10" => [94, "\xfec"], "\x11" => [76, "\xfec"], "\x12" => [104, "\xfec"], "\x13" => [16, "\xfec"], "\x14" => [94, "\xfee"], "\x15" => [76, "\xfee"], "\x16" => [104, "\xfee"], "\x17" => [16, "\xfee"], "\x18" => [94, "\xfei"], "\x19" => [76, "\xfei"], "\x1a" => [104, "\xfei"], "\x1b" => [16, "\xfei"], "\x1c" => [94, "\xfeo"], "\x1d" => [76, "\xfeo"], "\x1e" => [104, "\xfeo"], "\x1f" => [16, "\xfeo"], " " => [94, "\xfes"], "!" => [76, "\xfes"], "\"" => [104, "\xfes"], "#" => [16, "\xfes"], "\$" => [94, "\xfet"], "%" => [76, "\xfet"], "&" => [104, "\xfet"], "'" => [16, "\xfet"], "(" => [77, "\xfe "], ")" => [18, "\xfe "], "*" => [77, "\xfe%"], "+" => [18, "\xfe%"], "," => [77, "\xfe-"], "-" => [18, "\xfe-"], "." => [77, "\xfe."], "/" => [18, "\xfe."], [77, "\xfe/"], [18, "\xfe/"], [77, "\xfe3"], [18, "\xfe3"], [77, "\xfe4"], [18, "\xfe4"], [77, "\xfe5"], [18, "\xfe5"], [77, "\xfe6"], [18, "\xfe6"], ":" => [77, "\xfe7"], ";" => [18, "\xfe7"], "<" => [77, "\xfe8"], "=" => [18, "\xfe8"], ">" => [77, "\xfe9"], "?" => [18, "\xfe9"], "@" => [77, "\xfe="], "A" => [18, "\xfe="], "B" => [77, "\xfeA"], "C" => [18, "\xfeA"], "D" => [77, "\xfe_"], "E" => [18, "\xfe_"], "F" => [77, "\xfeb"], "G" => [18, "\xfeb"], "H" => [77, "\xfed"], "I" => [18, "\xfed"], "J" => [77, "\xfef"], "K" => [18, "\xfef"], "L" => [77, "\xfeg"], "M" => [18, "\xfeg"], "N" => [77, "\xfeh"], "O" => [18, "\xfeh"], "P" => [77, "\xfel"], "Q" => [18, "\xfel"], "R" => [77, "\xfem"], "S" => [18, "\xfem"], "T" => [77, "\xfen"], "U" => [18, "\xfen"], "V" => [77, "\xfep"], "W" => [18, "\xfep"], "X" => [77, "\xfer"], "Y" => [18, "\xfer"], "Z" => [77, "\xfeu"], "[" => [18, "\xfeu"], "\\" => [0, "\xfe:"], "]" => [0, "\xfeB"], "^" => [0, "\xfeC"], "_" => [0, "\xfeD"], "`" => [0, "\xfeE"], "a" => [0, "\xfeF"], "b" => [0, "\xfeG"], "c" => [0, "\xfeH"], "d" => [0, "\xfeI"], "e" => [0, "\xfeJ"], "f" => [0, "\xfeK"], "g" => [0, "\xfeL"], "h" => [0, "\xfeM"], "i" => [0, "\xfeN"], "j" => [0, "\xfeO"], "k" => [0, "\xfeP"], "l" => [0, "\xfeQ"], "m" => [0, "\xfeR"], "n" => [0, "\xfeS"], "o" => [0, "\xfeT"], "p" => [0, "\xfeU"], "q" => [0, "\xfeV"], "r" => [0, "\xfeW"], "s" => [0, "\xfeY"], "t" => [0, "\xfej"], "u" => [0, "\xfek"], "v" => [0, "\xfeq"], "w" => [0, "\xfev"], "x" => [0, "\xfew"], "y" => [0, "\xfex"], "z" => [0, "\xfey"], "{" => [0, "\xfez"], "|" => [82, "\xfe"], "}" => [87, "\xfe"], "~" => [130, "\xfe"], "" => [9, "\xfe"], "\x80" => [77, "\x020"], "\x81" => [18, "\x020"], "\x82" => [77, "\x021"], "\x83" => [18, "\x021"], "\x84" => [77, "\x022"], "\x85" => [18, "\x022"], "\x86" => [77, "\x02a"], "\x87" => [18, "\x02a"], "\x88" => [77, "\x02c"], "\x89" => [18, "\x02c"], "\x8a" => [77, "\x02e"], "\x8b" => [18, "\x02e"], "\x8c" => [77, "\x02i"], "\x8d" => [18, "\x02i"], "\x8e" => [77, "\x02o"], "\x8f" => [18, "\x02o"], "\x90" => [77, "\x02s"], "\x91" => [18, "\x02s"], "\x92" => [77, "\x02t"], "\x93" => [18, "\x02t"], "\x94" => [0, "\x02 "], "\x95" => [0, "\x02%"], "\x96" => [0, "\x02-"], "\x97" => [0, "\x02."], "\x98" => [0, "\x02/"], "\x99" => [0, "\x023"], "\x9a" => [0, "\x024"], "\x9b" => [0, "\x025"], "\x9c" => [0, "\x026"], "\x9d" => [0, "\x027"], "\x9e" => [0, "\x028"], "\x9f" => [0, "\x029"], "\xa0" => [0, "\x02="], "\xa1" => [0, "\x02A"], "\xa2" => [0, "\x02_"], "\xa3" => [0, "\x02b"], "\xa4" => [0, "\x02d"], "\xa5" => [0, "\x02f"], "\xa6" => [0, "\x02g"], "\xa7" => [0, "\x02h"], "\xa8" => [0, "\x02l"], "\xa9" => [0, "\x02m"], "\xaa" => [0, "\x02n"], "\xab" => [0, "\x02p"], "\xac" => [0, "\x02r"], "\xad" => [0, "\x02u"], "\xae" => [100, "\x02"], "\xaf" => [110, "\x02"], "\xb0" => [111, "\x02"], "\xb1" => [115, "\x02"], "\xb2" => [116, "\x02"], "\xb3" => [118, "\x02"], "\xb4" => [119, "\x02"], "\xb5" => [122, "\x02"], "\xb6" => [123, "\x02"], "\xb7" => [125, "\x02"], "\xb8" => [126, "\x02"], "\xb9" => [129, "\x02"], "\xba" => [143, "\x02"], "\xbb" => [148, "\x02"], "\xbc" => [151, "\x02"], "\xbd" => [153, "\x02"], "\xbe" => [83, "\x02"], "\xbf" => [10, "\x02"], "\xc0" => [77, "\x030"], "\xc1" => [18, "\x030"], "\xc2" => [77, "\x031"], "\xc3" => [18, "\x031"], "\xc4" => [77, "\x032"], "\xc5" => [18, "\x032"], "\xc6" => [77, "\x03a"], "\xc7" => [18, "\x03a"], "\xc8" => [77, "\x03c"], "\xc9" => [18, "\x03c"], "\xca" => [77, "\x03e"], "\xcb" => [18, "\x03e"], "\xcc" => [77, "\x03i"], "\xcd" => [18, "\x03i"], "\xce" => [77, "\x03o"], "\xcf" => [18, "\x03o"], "\xd0" => [77, "\x03s"], "\xd1" => [18, "\x03s"], "\xd2" => [77, "\x03t"], "\xd3" => [18, "\x03t"], "\xd4" => [0, "\x03 "], "\xd5" => [0, "\x03%"], "\xd6" => [0, "\x03-"], "\xd7" => [0, "\x03."], "\xd8" => [0, "\x03/"], "\xd9" => [0, "\x033"], "\xda" => [0, "\x034"], "\xdb" => [0, "\x035"], "\xdc" => [0, "\x036"], "\xdd" => [0, "\x037"], "\xde" => [0, "\x038"], "\xdf" => [0, "\x039"], "\xe0" => [0, "\x03="], "\xe1" => [0, "\x03A"], "\xe2" => [0, "\x03_"], "\xe3" => [0, "\x03b"], "\xe4" => [0, "\x03d"], "\xe5" => [0, "\x03f"], "\xe6" => [0, "\x03g"], "\xe7" => [0, "\x03h"], "\xe8" => [0, "\x03l"], "\xe9" => [0, "\x03m"], "\xea" => [0, "\x03n"], "\xeb" => [0, "\x03p"], "\xec" => [0, "\x03r"], "\xed" => [0, "\x03u"], "\xee" => [100, "\x03"], "\xef" => [110, "\x03"], "\xf0" => [111, "\x03"], "\xf1" => [115, "\x03"], "\xf2" => [116, "\x03"], "\xf3" => [118, "\x03"], "\xf4" => [119, "\x03"], "\xf5" => [122, "\x03"], "\xf6" => [123, "\x03"], "\xf7" => [125, "\x03"], "\xf8" => [126, "\x03"], "\xf9" => [129, "\x03"], "\xfa" => [143, "\x03"], "\xfb" => [148, "\x03"], "\xfc" => [151, "\x03"], "\xfd" => [153, "\x03"], "\xfe" => [83, "\x03"], "\xff" => [10, "\x03"]], ["\x00" => [77, "\xfe0"], "\x01" => [18, "\xfe0"], "\x02" => [77, "\xfe1"], "\x03" => [18, "\xfe1"], "\x04" => [77, "\xfe2"], "\x05" => [18, "\xfe2"], "\x06" => [77, "\xfea"], "\x07" => [18, "\xfea"], "\x08" => [77, "\xfec"], "\t" => [18, "\xfec"], "\n" => [77, "\xfee"], "\v" => [18, "\xfee"], "\f" => [77, "\xfei"], "\r" => [18, "\xfei"], "\x0e" => [77, "\xfeo"], "\x0f" => [18, "\xfeo"], "\x10" => [77, "\xfes"], "\x11" => [18, "\xfes"], "\x12" => [77, "\xfet"], "\x13" => [18, "\xfet"], "\x14" => [0, "\xfe "], "\x15" => [0, "\xfe%"], "\x16" => [0, "\xfe-"], "\x17" => [0, "\xfe."], "\x18" => [0, "\xfe/"], "\x19" => [0, "\xfe3"], "\x1a" => [0, "\xfe4"], "\x1b" => [0, "\xfe5"], "\x1c" => [0, "\xfe6"], "\x1d" => [0, "\xfe7"], "\x1e" => [0, "\xfe8"], "\x1f" => [0, "\xfe9"], " " => [0, "\xfe="], "!" => [0, "\xfeA"], "\"" => [0, "\xfe_"], "#" => [0, "\xfeb"], "\$" => [0, "\xfed"], "%" => [0, "\xfef"], "&" => [0, "\xfeg"], "'" => [0, "\xfeh"], "(" => [0, "\xfel"], ")" => [0, "\xfem"], "*" => [0, "\xfen"], "+" => [0, "\xfep"], "," => [0, "\xfer"], "-" => [0, "\xfeu"], "." => [100, "\xfe"], "/" => [110, "\xfe"], [111, "\xfe"], [115, "\xfe"], [116, "\xfe"], [118, "\xfe"], [119, "\xfe"], [122, "\xfe"], [123, "\xfe"], [125, "\xfe"], [126, "\xfe"], [129, "\xfe"], ":" => [143, "\xfe"], ";" => [148, "\xfe"], "<" => [151, "\xfe"], "=" => [153, "\xfe"], ">" => [83, "\xfe"], "?" => [10, "\xfe"], "@" => [0, "\x020"], "A" => [0, "\x021"], "B" => [0, "\x022"], "C" => [0, "\x02a"], "D" => [0, "\x02c"], "E" => [0, "\x02e"], "F" => [0, "\x02i"], "G" => [0, "\x02o"], "H" => [0, "\x02s"], "I" => [0, "\x02t"], "J" => [73, "\x02"], "K" => [88, "\x02"], "L" => [89, "\x02"], "M" => [96, "\x02"], "N" => [97, "\x02"], "O" => [99, "\x02"], "P" => [106, "\x02"], "Q" => [136, "\x02"], "R" => [139, "\x02"], "S" => [141, "\x02"], "T" => [145, "\x02"], "U" => [147, "\x02"], "V" => [149, "\x02"], "W" => [101, "\x02"], "X" => [112, "\x02"], "Y" => [117, "\x02"], "Z" => [120, "\x02"], "[" => [124, "\x02"], "\\" => [127, "\x02"], "]" => [144, "\x02"], "^" => [152, "\x02"], "_" => [11, "\x02"], "`" => [0, "\x030"], "a" => [0, "\x031"], "b" => [0, "\x032"], "c" => [0, "\x03a"], "d" => [0, "\x03c"], "e" => [0, "\x03e"], "f" => [0, "\x03i"], "g" => [0, "\x03o"], "h" => [0, "\x03s"], "i" => [0, "\x03t"], "j" => [73, "\x03"], "k" => [88, "\x03"], "l" => [89, "\x03"], "m" => [96, "\x03"], "n" => [97, "\x03"], "o" => [99, "\x03"], "p" => [106, "\x03"], "q" => [136, "\x03"], "r" => [139, "\x03"], "s" => [141, "\x03"], "t" => [145, "\x03"], "u" => [147, "\x03"], "v" => [149, "\x03"], "w" => [101, "\x03"], "x" => [112, "\x03"], "y" => [117, "\x03"], "z" => [120, "\x03"], "{" => [124, "\x03"], "|" => [127, "\x03"], "}" => [144, "\x03"], "~" => [152, "\x03"], "" => [11, "\x03"], "\x80" => [0, "\x040"], "\x81" => [0, "\x041"], "\x82" => [0, "\x042"], "\x83" => [0, "\x04a"], "\x84" => [0, "\x04c"], "\x85" => [0, "\x04e"], "\x86" => [0, "\x04i"], "\x87" => [0, "\x04o"], "\x88" => [0, "\x04s"], "\x89" => [0, "\x04t"], "\x8a" => [73, "\x04"], "\x8b" => [88, "\x04"], "\x8c" => [89, "\x04"], "\x8d" => [96, "\x04"], "\x8e" => [97, "\x04"], "\x8f" => [99, "\x04"], "\x90" => [106, "\x04"], "\x91" => [136, "\x04"], "\x92" => [139, "\x04"], "\x93" => [141, "\x04"], "\x94" => [145, "\x04"], "\x95" => [147, "\x04"], "\x96" => [149, "\x04"], "\x97" => [101, "\x04"], "\x98" => [112, "\x04"], "\x99" => [117, "\x04"], "\x9a" => [120, "\x04"], "\x9b" => [124, "\x04"], "\x9c" => [127, "\x04"], "\x9d" => [144, "\x04"], "\x9e" => [152, "\x04"], "\x9f" => [11, "\x04"], "\xa0" => [0, "\x050"], "\xa1" => [0, "\x051"], "\xa2" => [0, "\x052"], "\xa3" => [0, "\x05a"], "\xa4" => [0, "\x05c"], "\xa5" => [0, "\x05e"], "\xa6" => [0, "\x05i"], "\xa7" => [0, "\x05o"], "\xa8" => [0, "\x05s"], "\xa9" => [0, "\x05t"], "\xaa" => [73, "\x05"], "\xab" => [88, "\x05"], "\xac" => [89, "\x05"], "\xad" => [96, "\x05"], "\xae" => [97, "\x05"], "\xaf" => [99, "\x05"], "\xb0" => [106, "\x05"], "\xb1" => [136, "\x05"], "\xb2" => [139, "\x05"], "\xb3" => [141, "\x05"], "\xb4" => [145, "\x05"], "\xb5" => [147, "\x05"], "\xb6" => [149, "\x05"], "\xb7" => [101, "\x05"], "\xb8" => [112, "\x05"], "\xb9" => [117, "\x05"], "\xba" => [120, "\x05"], "\xbb" => [124, "\x05"], "\xbc" => [127, "\x05"], "\xbd" => [144, "\x05"], "\xbe" => [152, "\x05"], "\xbf" => [11, "\x05"], "\xc0" => [0, "\x060"], "\xc1" => [0, "\x061"], "\xc2" => [0, "\x062"], "\xc3" => [0, "\x06a"], "\xc4" => [0, "\x06c"], "\xc5" => [0, "\x06e"], "\xc6" => [0, "\x06i"], "\xc7" => [0, "\x06o"], "\xc8" => [0, "\x06s"], "\xc9" => [0, "\x06t"], "\xca" => [73, "\x06"], "\xcb" => [88, "\x06"], "\xcc" => [89, "\x06"], "\xcd" => [96, "\x06"], "\xce" => [97, "\x06"], "\xcf" => [99, "\x06"], "\xd0" => [106, "\x06"], "\xd1" => [136, "\x06"], "\xd2" => [139, "\x06"], "\xd3" => [141, "\x06"], "\xd4" => [145, "\x06"], "\xd5" => [147, "\x06"], "\xd6" => [149, "\x06"], "\xd7" => [101, "\x06"], "\xd8" => [112, "\x06"], "\xd9" => [117, "\x06"], "\xda" => [120, "\x06"], "\xdb" => [124, "\x06"], "\xdc" => [127, "\x06"], "\xdd" => [144, "\x06"], "\xde" => [152, "\x06"], "\xdf" => [11, "\x06"], "\xe0" => [0, "\x070"], "\xe1" => [0, "\x071"], "\xe2" => [0, "\x072"], "\xe3" => [0, "\x07a"], "\xe4" => [0, "\x07c"], "\xe5" => [0, "\x07e"], "\xe6" => [0, "\x07i"], "\xe7" => [0, "\x07o"], "\xe8" => [0, "\x07s"], "\xe9" => [0, "\x07t"], "\xea" => [73, "\x07"], "\xeb" => [88, "\x07"], "\xec" => [89, "\x07"], "\xed" => [96, "\x07"], "\xee" => [97, "\x07"], "\xef" => [99, "\x07"], "\xf0" => [106, "\x07"], "\xf1" => [136, "\x07"], "\xf2" => [139, "\x07"], "\xf3" => [141, "\x07"], "\xf4" => [145, "\x07"], "\xf5" => [147, "\x07"], "\xf6" => [149, "\x07"], "\xf7" => [101, "\x07"], "\xf8" => [112, "\x07"], "\xf9" => [117, "\x07"], "\xfa" => [120, "\x07"], "\xfb" => [124, "\x07"], "\xfc" => [127, "\x07"], "\xfd" => [144, "\x07"], "\xfe" => [152, "\x07"], "\xff" => [11, "\x07"]], ["\x00" => [94, "\x040"], "\x01" => [76, "\x040"], "\x02" => [104, "\x040"], "\x03" => [16, "\x040"], "\x04" => [94, "\x041"], "\x05" => [76, "\x041"], "\x06" => [104, "\x041"], "\x07" => [16, "\x041"], "\x08" => [94, "\x042"], "\t" => [76, "\x042"], "\n" => [104, "\x042"], "\v" => [16, "\x042"], "\f" => [94, "\x04a"], "\r" => [76, "\x04a"], "\x0e" => [104, "\x04a"], "\x0f" => [16, "\x04a"], "\x10" => [94, "\x04c"], "\x11" => [76, "\x04c"], "\x12" => [104, "\x04c"], "\x13" => [16, "\x04c"], "\x14" => [94, "\x04e"], "\x15" => [76, "\x04e"], "\x16" => [104, "\x04e"], "\x17" => [16, "\x04e"], "\x18" => [94, "\x04i"], "\x19" => [76, "\x04i"], "\x1a" => [104, "\x04i"], "\x1b" => [16, "\x04i"], "\x1c" => [94, "\x04o"], "\x1d" => [76, "\x04o"], "\x1e" => [104, "\x04o"], "\x1f" => [16, "\x04o"], " " => [94, "\x04s"], "!" => [76, "\x04s"], "\"" => [104, "\x04s"], "#" => [16, "\x04s"], "\$" => [94, "\x04t"], "%" => [76, "\x04t"], "&" => [104, "\x04t"], "'" => [16, "\x04t"], "(" => [77, "\x04 "], ")" => [18, "\x04 "], "*" => [77, "\x04%"], "+" => [18, "\x04%"], "," => [77, "\x04-"], "-" => [18, "\x04-"], "." => [77, "\x04."], "/" => [18, "\x04."], [77, "\x04/"], [18, "\x04/"], [77, "\x043"], [18, "\x043"], [77, "\x044"], [18, "\x044"], [77, "\x045"], [18, "\x045"], [77, "\x046"], [18, "\x046"], ":" => [77, "\x047"], ";" => [18, "\x047"], "<" => [77, "\x048"], "=" => [18, "\x048"], ">" => [77, "\x049"], "?" => [18, "\x049"], "@" => [77, "\x04="], "A" => [18, "\x04="], "B" => [77, "\x04A"], "C" => [18, "\x04A"], "D" => [77, "\x04_"], "E" => [18, "\x04_"], "F" => [77, "\x04b"], "G" => [18, "\x04b"], "H" => [77, "\x04d"], "I" => [18, "\x04d"], "J" => [77, "\x04f"], "K" => [18, "\x04f"], "L" => [77, "\x04g"], "M" => [18, "\x04g"], "N" => [77, "\x04h"], "O" => [18, "\x04h"], "P" => [77, "\x04l"], "Q" => [18, "\x04l"], "R" => [77, "\x04m"], "S" => [18, "\x04m"], "T" => [77, "\x04n"], "U" => [18, "\x04n"], "V" => [77, "\x04p"], "W" => [18, "\x04p"], "X" => [77, "\x04r"], "Y" => [18, "\x04r"], "Z" => [77, "\x04u"], "[" => [18, "\x04u"], "\\" => [0, "\x04:"], "]" => [0, "\x04B"], "^" => [0, "\x04C"], "_" => [0, "\x04D"], "`" => [0, "\x04E"], "a" => [0, "\x04F"], "b" => [0, "\x04G"], "c" => [0, "\x04H"], "d" => [0, "\x04I"], "e" => [0, "\x04J"], "f" => [0, "\x04K"], "g" => [0, "\x04L"], "h" => [0, "\x04M"], "i" => [0, "\x04N"], "j" => [0, "\x04O"], "k" => [0, "\x04P"], "l" => [0, "\x04Q"], "m" => [0, "\x04R"], "n" => [0, "\x04S"], "o" => [0, "\x04T"], "p" => [0, "\x04U"], "q" => [0, "\x04V"], "r" => [0, "\x04W"], "s" => [0, "\x04Y"], "t" => [0, "\x04j"], "u" => [0, "\x04k"], "v" => [0, "\x04q"], "w" => [0, "\x04v"], "x" => [0, "\x04w"], "y" => [0, "\x04x"], "z" => [0, "\x04y"], "{" => [0, "\x04z"], "|" => [82, "\x04"], "}" => [87, "\x04"], "~" => [130, "\x04"], "" => [9, "\x04"], "\x80" => [94, "\x050"], "\x81" => [76, "\x050"], "\x82" => [104, "\x050"], "\x83" => [16, "\x050"], "\x84" => [94, "\x051"], "\x85" => [76, "\x051"], "\x86" => [104, "\x051"], "\x87" => [16, "\x051"], "\x88" => [94, "\x052"], "\x89" => [76, "\x052"], "\x8a" => [104, "\x052"], "\x8b" => [16, "\x052"], "\x8c" => [94, "\x05a"], "\x8d" => [76, "\x05a"], "\x8e" => [104, "\x05a"], "\x8f" => [16, "\x05a"], "\x90" => [94, "\x05c"], "\x91" => [76, "\x05c"], "\x92" => [104, "\x05c"], "\x93" => [16, "\x05c"], "\x94" => [94, "\x05e"], "\x95" => [76, "\x05e"], "\x96" => [104, "\x05e"], "\x97" => [16, "\x05e"], "\x98" => [94, "\x05i"], "\x99" => [76, "\x05i"], "\x9a" => [104, "\x05i"], "\x9b" => [16, "\x05i"], "\x9c" => [94, "\x05o"], "\x9d" => [76, "\x05o"], "\x9e" => [104, "\x05o"], "\x9f" => [16, "\x05o"], "\xa0" => [94, "\x05s"], "\xa1" => [76, "\x05s"], "\xa2" => [104, "\x05s"], "\xa3" => [16, "\x05s"], "\xa4" => [94, "\x05t"], "\xa5" => [76, "\x05t"], "\xa6" => [104, "\x05t"], "\xa7" => [16, "\x05t"], "\xa8" => [77, "\x05 "], "\xa9" => [18, "\x05 "], "\xaa" => [77, "\x05%"], "\xab" => [18, "\x05%"], "\xac" => [77, "\x05-"], "\xad" => [18, "\x05-"], "\xae" => [77, "\x05."], "\xaf" => [18, "\x05."], "\xb0" => [77, "\x05/"], "\xb1" => [18, "\x05/"], "\xb2" => [77, "\x053"], "\xb3" => [18, "\x053"], "\xb4" => [77, "\x054"], "\xb5" => [18, "\x054"], "\xb6" => [77, "\x055"], "\xb7" => [18, "\x055"], "\xb8" => [77, "\x056"], "\xb9" => [18, "\x056"], "\xba" => [77, "\x057"], "\xbb" => [18, "\x057"], "\xbc" => [77, "\x058"], "\xbd" => [18, "\x058"], "\xbe" => [77, "\x059"], "\xbf" => [18, "\x059"], "\xc0" => [77, "\x05="], "\xc1" => [18, "\x05="], "\xc2" => [77, "\x05A"], "\xc3" => [18, "\x05A"], "\xc4" => [77, "\x05_"], "\xc5" => [18, "\x05_"], "\xc6" => [77, "\x05b"], "\xc7" => [18, "\x05b"], "\xc8" => [77, "\x05d"], "\xc9" => [18, "\x05d"], "\xca" => [77, "\x05f"], "\xcb" => [18, "\x05f"], "\xcc" => [77, "\x05g"], "\xcd" => [18, "\x05g"], "\xce" => [77, "\x05h"], "\xcf" => [18, "\x05h"], "\xd0" => [77, "\x05l"], "\xd1" => [18, "\x05l"], "\xd2" => [77, "\x05m"], "\xd3" => [18, "\x05m"], "\xd4" => [77, "\x05n"], "\xd5" => [18, "\x05n"], "\xd6" => [77, "\x05p"], "\xd7" => [18, "\x05p"], "\xd8" => [77, "\x05r"], "\xd9" => [18, "\x05r"], "\xda" => [77, "\x05u"], "\xdb" => [18, "\x05u"], "\xdc" => [0, "\x05:"], "\xdd" => [0, "\x05B"], "\xde" => [0, "\x05C"], "\xdf" => [0, "\x05D"], "\xe0" => [0, "\x05E"], "\xe1" => [0, "\x05F"], "\xe2" => [0, "\x05G"], "\xe3" => [0, "\x05H"], "\xe4" => [0, "\x05I"], "\xe5" => [0, "\x05J"], "\xe6" => [0, "\x05K"], "\xe7" => [0, "\x05L"], "\xe8" => [0, "\x05M"], "\xe9" => [0, "\x05N"], "\xea" => [0, "\x05O"], "\xeb" => [0, "\x05P"], "\xec" => [0, "\x05Q"], "\xed" => [0, "\x05R"], "\xee" => [0, "\x05S"], "\xef" => [0, "\x05T"], "\xf0" => [0, "\x05U"], "\xf1" => [0, "\x05V"], "\xf2" => [0, "\x05W"], "\xf3" => [0, "\x05Y"], "\xf4" => [0, "\x05j"], "\xf5" => [0, "\x05k"], "\xf6" => [0, "\x05q"], "\xf7" => [0, "\x05v"], "\xf8" => [0, "\x05w"], "\xf9" => [0, "\x05x"], "\xfa" => [0, "\x05y"], "\xfb" => [0, "\x05z"], "\xfc" => [82, "\x05"], "\xfd" => [87, "\x05"], "\xfe" => [130, "\x05"], "\xff" => [9, "\x05"]], ["\x00" => [77, "\x040"], "\x01" => [18, "\x040"], "\x02" => [77, "\x041"], "\x03" => [18, "\x041"], "\x04" => [77, "\x042"], "\x05" => [18, "\x042"], "\x06" => [77, "\x04a"], "\x07" => [18, "\x04a"], "\x08" => [77, "\x04c"], "\t" => [18, "\x04c"], "\n" => [77, "\x04e"], "\v" => [18, "\x04e"], "\f" => [77, "\x04i"], "\r" => [18, "\x04i"], "\x0e" => [77, "\x04o"], "\x0f" => [18, "\x04o"], "\x10" => [77, "\x04s"], "\x11" => [18, "\x04s"], "\x12" => [77, "\x04t"], "\x13" => [18, "\x04t"], "\x14" => [0, "\x04 "], "\x15" => [0, "\x04%"], "\x16" => [0, "\x04-"], "\x17" => [0, "\x04."], "\x18" => [0, "\x04/"], "\x19" => [0, "\x043"], "\x1a" => [0, "\x044"], "\x1b" => [0, "\x045"], "\x1c" => [0, "\x046"], "\x1d" => [0, "\x047"], "\x1e" => [0, "\x048"], "\x1f" => [0, "\x049"], " " => [0, "\x04="], "!" => [0, "\x04A"], "\"" => [0, "\x04_"], "#" => [0, "\x04b"], "\$" => [0, "\x04d"], "%" => [0, "\x04f"], "&" => [0, "\x04g"], "'" => [0, "\x04h"], "(" => [0, "\x04l"], ")" => [0, "\x04m"], "*" => [0, "\x04n"], "+" => [0, "\x04p"], "," => [0, "\x04r"], "-" => [0, "\x04u"], "." => [100, "\x04"], "/" => [110, "\x04"], [111, "\x04"], [115, "\x04"], [116, "\x04"], [118, "\x04"], [119, "\x04"], [122, "\x04"], [123, "\x04"], [125, "\x04"], [126, "\x04"], [129, "\x04"], ":" => [143, "\x04"], ";" => [148, "\x04"], "<" => [151, "\x04"], "=" => [153, "\x04"], ">" => [83, "\x04"], "?" => [10, "\x04"], "@" => [77, "\x050"], "A" => [18, "\x050"], "B" => [77, "\x051"], "C" => [18, "\x051"], "D" => [77, "\x052"], "E" => [18, "\x052"], "F" => [77, "\x05a"], "G" => [18, "\x05a"], "H" => [77, "\x05c"], "I" => [18, "\x05c"], "J" => [77, "\x05e"], "K" => [18, "\x05e"], "L" => [77, "\x05i"], "M" => [18, "\x05i"], "N" => [77, "\x05o"], "O" => [18, "\x05o"], "P" => [77, "\x05s"], "Q" => [18, "\x05s"], "R" => [77, "\x05t"], "S" => [18, "\x05t"], "T" => [0, "\x05 "], "U" => [0, "\x05%"], "V" => [0, "\x05-"], "W" => [0, "\x05."], "X" => [0, "\x05/"], "Y" => [0, "\x053"], "Z" => [0, "\x054"], "[" => [0, "\x055"], "\\" => [0, "\x056"], "]" => [0, "\x057"], "^" => [0, "\x058"], "_" => [0, "\x059"], "`" => [0, "\x05="], "a" => [0, "\x05A"], "b" => [0, "\x05_"], "c" => [0, "\x05b"], "d" => [0, "\x05d"], "e" => [0, "\x05f"], "f" => [0, "\x05g"], "g" => [0, "\x05h"], "h" => [0, "\x05l"], "i" => [0, "\x05m"], "j" => [0, "\x05n"], "k" => [0, "\x05p"], "l" => [0, "\x05r"], "m" => [0, "\x05u"], "n" => [100, "\x05"], "o" => [110, "\x05"], "p" => [111, "\x05"], "q" => [115, "\x05"], "r" => [116, "\x05"], "s" => [118, "\x05"], "t" => [119, "\x05"], "u" => [122, "\x05"], "v" => [123, "\x05"], "w" => [125, "\x05"], "x" => [126, "\x05"], "y" => [129, "\x05"], "z" => [143, "\x05"], "{" => [148, "\x05"], "|" => [151, "\x05"], "}" => [153, "\x05"], "~" => [83, "\x05"], "" => [10, "\x05"], "\x80" => [77, "\x060"], "\x81" => [18, "\x060"], "\x82" => [77, "\x061"], "\x83" => [18, "\x061"], "\x84" => [77, "\x062"], "\x85" => [18, "\x062"], "\x86" => [77, "\x06a"], "\x87" => [18, "\x06a"], "\x88" => [77, "\x06c"], "\x89" => [18, "\x06c"], "\x8a" => [77, "\x06e"], "\x8b" => [18, "\x06e"], "\x8c" => [77, "\x06i"], "\x8d" => [18, "\x06i"], "\x8e" => [77, "\x06o"], "\x8f" => [18, "\x06o"], "\x90" => [77, "\x06s"], "\x91" => [18, "\x06s"], "\x92" => [77, "\x06t"], "\x93" => [18, "\x06t"], "\x94" => [0, "\x06 "], "\x95" => [0, "\x06%"], "\x96" => [0, "\x06-"], "\x97" => [0, "\x06."], "\x98" => [0, "\x06/"], "\x99" => [0, "\x063"], "\x9a" => [0, "\x064"], "\x9b" => [0, "\x065"], "\x9c" => [0, "\x066"], "\x9d" => [0, "\x067"], "\x9e" => [0, "\x068"], "\x9f" => [0, "\x069"], "\xa0" => [0, "\x06="], "\xa1" => [0, "\x06A"], "\xa2" => [0, "\x06_"], "\xa3" => [0, "\x06b"], "\xa4" => [0, "\x06d"], "\xa5" => [0, "\x06f"], "\xa6" => [0, "\x06g"], "\xa7" => [0, "\x06h"], "\xa8" => [0, "\x06l"], "\xa9" => [0, "\x06m"], "\xaa" => [0, "\x06n"], "\xab" => [0, "\x06p"], "\xac" => [0, "\x06r"], "\xad" => [0, "\x06u"], "\xae" => [100, "\x06"], "\xaf" => [110, "\x06"], "\xb0" => [111, "\x06"], "\xb1" => [115, "\x06"], "\xb2" => [116, "\x06"], "\xb3" => [118, "\x06"], "\xb4" => [119, "\x06"], "\xb5" => [122, "\x06"], "\xb6" => [123, "\x06"], "\xb7" => [125, "\x06"], "\xb8" => [126, "\x06"], "\xb9" => [129, "\x06"], "\xba" => [143, "\x06"], "\xbb" => [148, "\x06"], "\xbc" => [151, "\x06"], "\xbd" => [153, "\x06"], "\xbe" => [83, "\x06"], "\xbf" => [10, "\x06"], "\xc0" => [77, "\x070"], "\xc1" => [18, "\x070"], "\xc2" => [77, "\x071"], "\xc3" => [18, "\x071"], "\xc4" => [77, "\x072"], "\xc5" => [18, "\x072"], "\xc6" => [77, "\x07a"], "\xc7" => [18, "\x07a"], "\xc8" => [77, "\x07c"], "\xc9" => [18, "\x07c"], "\xca" => [77, "\x07e"], "\xcb" => [18, "\x07e"], "\xcc" => [77, "\x07i"], "\xcd" => [18, "\x07i"], "\xce" => [77, "\x07o"], "\xcf" => [18, "\x07o"], "\xd0" => [77, "\x07s"], "\xd1" => [18, "\x07s"], "\xd2" => [77, "\x07t"], "\xd3" => [18, "\x07t"], "\xd4" => [0, "\x07 "], "\xd5" => [0, "\x07%"], "\xd6" => [0, "\x07-"], "\xd7" => [0, "\x07."], "\xd8" => [0, "\x07/"], "\xd9" => [0, "\x073"], "\xda" => [0, "\x074"], "\xdb" => [0, "\x075"], "\xdc" => [0, "\x076"], "\xdd" => [0, "\x077"], "\xde" => [0, "\x078"], "\xdf" => [0, "\x079"], "\xe0" => [0, "\x07="], "\xe1" => [0, "\x07A"], "\xe2" => [0, "\x07_"], "\xe3" => [0, "\x07b"], "\xe4" => [0, "\x07d"], "\xe5" => [0, "\x07f"], "\xe6" => [0, "\x07g"], "\xe7" => [0, "\x07h"], "\xe8" => [0, "\x07l"], "\xe9" => [0, "\x07m"], "\xea" => [0, "\x07n"], "\xeb" => [0, "\x07p"], "\xec" => [0, "\x07r"], "\xed" => [0, "\x07u"], "\xee" => [100, "\x07"], "\xef" => [110, "\x07"], "\xf0" => [111, "\x07"], "\xf1" => [115, "\x07"], "\xf2" => [116, "\x07"], "\xf3" => [118, "\x07"], "\xf4" => [119, "\x07"], "\xf5" => [122, "\x07"], "\xf6" => [123, "\x07"], "\xf7" => [125, "\x07"], "\xf8" => [126, "\x07"], "\xf9" => [129, "\x07"], "\xfa" => [143, "\x07"], "\xfb" => [148, "\x07"], "\xfc" => [151, "\x07"], "\xfd" => [153, "\x07"], "\xfe" => [83, "\x07"], "\xff" => [10, "\x07"]], ["\x00" => [94, "\x060"], "\x01" => [76, "\x060"], "\x02" => [104, "\x060"], "\x03" => [16, "\x060"], "\x04" => [94, "\x061"], "\x05" => [76, "\x061"], "\x06" => [104, "\x061"], "\x07" => [16, "\x061"], "\x08" => [94, "\x062"], "\t" => [76, "\x062"], "\n" => [104, "\x062"], "\v" => [16, "\x062"], "\f" => [94, "\x06a"], "\r" => [76, "\x06a"], "\x0e" => [104, "\x06a"], "\x0f" => [16, "\x06a"], "\x10" => [94, "\x06c"], "\x11" => [76, "\x06c"], "\x12" => [104, "\x06c"], "\x13" => [16, "\x06c"], "\x14" => [94, "\x06e"], "\x15" => [76, "\x06e"], "\x16" => [104, "\x06e"], "\x17" => [16, "\x06e"], "\x18" => [94, "\x06i"], "\x19" => [76, "\x06i"], "\x1a" => [104, "\x06i"], "\x1b" => [16, "\x06i"], "\x1c" => [94, "\x06o"], "\x1d" => [76, "\x06o"], "\x1e" => [104, "\x06o"], "\x1f" => [16, "\x06o"], " " => [94, "\x06s"], "!" => [76, "\x06s"], "\"" => [104, "\x06s"], "#" => [16, "\x06s"], "\$" => [94, "\x06t"], "%" => [76, "\x06t"], "&" => [104, "\x06t"], "'" => [16, "\x06t"], "(" => [77, "\x06 "], ")" => [18, "\x06 "], "*" => [77, "\x06%"], "+" => [18, "\x06%"], "," => [77, "\x06-"], "-" => [18, "\x06-"], "." => [77, "\x06."], "/" => [18, "\x06."], [77, "\x06/"], [18, "\x06/"], [77, "\x063"], [18, "\x063"], [77, "\x064"], [18, "\x064"], [77, "\x065"], [18, "\x065"], [77, "\x066"], [18, "\x066"], ":" => [77, "\x067"], ";" => [18, "\x067"], "<" => [77, "\x068"], "=" => [18, "\x068"], ">" => [77, "\x069"], "?" => [18, "\x069"], "@" => [77, "\x06="], "A" => [18, "\x06="], "B" => [77, "\x06A"], "C" => [18, "\x06A"], "D" => [77, "\x06_"], "E" => [18, "\x06_"], "F" => [77, "\x06b"], "G" => [18, "\x06b"], "H" => [77, "\x06d"], "I" => [18, "\x06d"], "J" => [77, "\x06f"], "K" => [18, "\x06f"], "L" => [77, "\x06g"], "M" => [18, "\x06g"], "N" => [77, "\x06h"], "O" => [18, "\x06h"], "P" => [77, "\x06l"], "Q" => [18, "\x06l"], "R" => [77, "\x06m"], "S" => [18, "\x06m"], "T" => [77, "\x06n"], "U" => [18, "\x06n"], "V" => [77, "\x06p"], "W" => [18, "\x06p"], "X" => [77, "\x06r"], "Y" => [18, "\x06r"], "Z" => [77, "\x06u"], "[" => [18, "\x06u"], "\\" => [0, "\x06:"], "]" => [0, "\x06B"], "^" => [0, "\x06C"], "_" => [0, "\x06D"], "`" => [0, "\x06E"], "a" => [0, "\x06F"], "b" => [0, "\x06G"], "c" => [0, "\x06H"], "d" => [0, "\x06I"], "e" => [0, "\x06J"], "f" => [0, "\x06K"], "g" => [0, "\x06L"], "h" => [0, "\x06M"], "i" => [0, "\x06N"], "j" => [0, "\x06O"], "k" => [0, "\x06P"], "l" => [0, "\x06Q"], "m" => [0, "\x06R"], "n" => [0, "\x06S"], "o" => [0, "\x06T"], "p" => [0, "\x06U"], "q" => [0, "\x06V"], "r" => [0, "\x06W"], "s" => [0, "\x06Y"], "t" => [0, "\x06j"], "u" => [0, "\x06k"], "v" => [0, "\x06q"], "w" => [0, "\x06v"], "x" => [0, "\x06w"], "y" => [0, "\x06x"], "z" => [0, "\x06y"], "{" => [0, "\x06z"], "|" => [82, "\x06"], "}" => [87, "\x06"], "~" => [130, "\x06"], "" => [9, "\x06"], "\x80" => [94, "\x070"], "\x81" => [76, "\x070"], "\x82" => [104, "\x070"], "\x83" => [16, "\x070"], "\x84" => [94, "\x071"], "\x85" => [76, "\x071"], "\x86" => [104, "\x071"], "\x87" => [16, "\x071"], "\x88" => [94, "\x072"], "\x89" => [76, "\x072"], "\x8a" => [104, "\x072"], "\x8b" => [16, "\x072"], "\x8c" => [94, "\x07a"], "\x8d" => [76, "\x07a"], "\x8e" => [104, "\x07a"], "\x8f" => [16, "\x07a"], "\x90" => [94, "\x07c"], "\x91" => [76, "\x07c"], "\x92" => [104, "\x07c"], "\x93" => [16, "\x07c"], "\x94" => [94, "\x07e"], "\x95" => [76, "\x07e"], "\x96" => [104, "\x07e"], "\x97" => [16, "\x07e"], "\x98" => [94, "\x07i"], "\x99" => [76, "\x07i"], "\x9a" => [104, "\x07i"], "\x9b" => [16, "\x07i"], "\x9c" => [94, "\x07o"], "\x9d" => [76, "\x07o"], "\x9e" => [104, "\x07o"], "\x9f" => [16, "\x07o"], "\xa0" => [94, "\x07s"], "\xa1" => [76, "\x07s"], "\xa2" => [104, "\x07s"], "\xa3" => [16, "\x07s"], "\xa4" => [94, "\x07t"], "\xa5" => [76, "\x07t"], "\xa6" => [104, "\x07t"], "\xa7" => [16, "\x07t"], "\xa8" => [77, "\x07 "], "\xa9" => [18, "\x07 "], "\xaa" => [77, "\x07%"], "\xab" => [18, "\x07%"], "\xac" => [77, "\x07-"], "\xad" => [18, "\x07-"], "\xae" => [77, "\x07."], "\xaf" => [18, "\x07."], "\xb0" => [77, "\x07/"], "\xb1" => [18, "\x07/"], "\xb2" => [77, "\x073"], "\xb3" => [18, "\x073"], "\xb4" => [77, "\x074"], "\xb5" => [18, "\x074"], "\xb6" => [77, "\x075"], "\xb7" => [18, "\x075"], "\xb8" => [77, "\x076"], "\xb9" => [18, "\x076"], "\xba" => [77, "\x077"], "\xbb" => [18, "\x077"], "\xbc" => [77, "\x078"], "\xbd" => [18, "\x078"], "\xbe" => [77, "\x079"], "\xbf" => [18, "\x079"], "\xc0" => [77, "\x07="], "\xc1" => [18, "\x07="], "\xc2" => [77, "\x07A"], "\xc3" => [18, "\x07A"], "\xc4" => [77, "\x07_"], "\xc5" => [18, "\x07_"], "\xc6" => [77, "\x07b"], "\xc7" => [18, "\x07b"], "\xc8" => [77, "\x07d"], "\xc9" => [18, "\x07d"], "\xca" => [77, "\x07f"], "\xcb" => [18, "\x07f"], "\xcc" => [77, "\x07g"], "\xcd" => [18, "\x07g"], "\xce" => [77, "\x07h"], "\xcf" => [18, "\x07h"], "\xd0" => [77, "\x07l"], "\xd1" => [18, "\x07l"], "\xd2" => [77, "\x07m"], "\xd3" => [18, "\x07m"], "\xd4" => [77, "\x07n"], "\xd5" => [18, "\x07n"], "\xd6" => [77, "\x07p"], "\xd7" => [18, "\x07p"], "\xd8" => [77, "\x07r"], "\xd9" => [18, "\x07r"], "\xda" => [77, "\x07u"], "\xdb" => [18, "\x07u"], "\xdc" => [0, "\x07:"], "\xdd" => [0, "\x07B"], "\xde" => [0, "\x07C"], "\xdf" => [0, "\x07D"], "\xe0" => [0, "\x07E"], "\xe1" => [0, "\x07F"], "\xe2" => [0, "\x07G"], "\xe3" => [0, "\x07H"], "\xe4" => [0, "\x07I"], "\xe5" => [0, "\x07J"], "\xe6" => [0, "\x07K"], "\xe7" => [0, "\x07L"], "\xe8" => [0, "\x07M"], "\xe9" => [0, "\x07N"], "\xea" => [0, "\x07O"], "\xeb" => [0, "\x07P"], "\xec" => [0, "\x07Q"], "\xed" => [0, "\x07R"], "\xee" => [0, "\x07S"], "\xef" => [0, "\x07T"], "\xf0" => [0, "\x07U"], "\xf1" => [0, "\x07V"], "\xf2" => [0, "\x07W"], "\xf3" => [0, "\x07Y"], "\xf4" => [0, "\x07j"], "\xf5" => [0, "\x07k"], "\xf6" => [0, "\x07q"], "\xf7" => [0, "\x07v"], "\xf8" => [0, "\x07w"], "\xf9" => [0, "\x07x"], "\xfa" => [0, "\x07y"], "\xfb" => [0, "\x07z"], "\xfc" => [82, "\x07"], "\xfd" => [87, "\x07"], "\xfe" => [130, "\x07"], "\xff" => [9, "\x07"]], ["\x00" => [94, "\x080"], "\x01" => [76, "\x080"], "\x02" => [104, "\x080"], "\x03" => [16, "\x080"], "\x04" => [94, "\x081"], "\x05" => [76, "\x081"], "\x06" => [104, "\x081"], "\x07" => [16, "\x081"], "\x08" => [94, "\x082"], "\t" => [76, "\x082"], "\n" => [104, "\x082"], "\v" => [16, "\x082"], "\f" => [94, "\x08a"], "\r" => [76, "\x08a"], "\x0e" => [104, "\x08a"], "\x0f" => [16, "\x08a"], "\x10" => [94, "\x08c"], "\x11" => [76, "\x08c"], "\x12" => [104, "\x08c"], "\x13" => [16, "\x08c"], "\x14" => [94, "\x08e"], "\x15" => [76, "\x08e"], "\x16" => [104, "\x08e"], "\x17" => [16, "\x08e"], "\x18" => [94, "\x08i"], "\x19" => [76, "\x08i"], "\x1a" => [104, "\x08i"], "\x1b" => [16, "\x08i"], "\x1c" => [94, "\x08o"], "\x1d" => [76, "\x08o"], "\x1e" => [104, "\x08o"], "\x1f" => [16, "\x08o"], " " => [94, "\x08s"], "!" => [76, "\x08s"], "\"" => [104, "\x08s"], "#" => [16, "\x08s"], "\$" => [94, "\x08t"], "%" => [76, "\x08t"], "&" => [104, "\x08t"], "'" => [16, "\x08t"], "(" => [77, "\x08 "], ")" => [18, "\x08 "], "*" => [77, "\x08%"], "+" => [18, "\x08%"], "," => [77, "\x08-"], "-" => [18, "\x08-"], "." => [77, "\x08."], "/" => [18, "\x08."], [77, "\x08/"], [18, "\x08/"], [77, "\x083"], [18, "\x083"], [77, "\x084"], [18, "\x084"], [77, "\x085"], [18, "\x085"], [77, "\x086"], [18, "\x086"], ":" => [77, "\x087"], ";" => [18, "\x087"], "<" => [77, "\x088"], "=" => [18, "\x088"], ">" => [77, "\x089"], "?" => [18, "\x089"], "@" => [77, "\x08="], "A" => [18, "\x08="], "B" => [77, "\x08A"], "C" => [18, "\x08A"], "D" => [77, "\x08_"], "E" => [18, "\x08_"], "F" => [77, "\x08b"], "G" => [18, "\x08b"], "H" => [77, "\x08d"], "I" => [18, "\x08d"], "J" => [77, "\x08f"], "K" => [18, "\x08f"], "L" => [77, "\x08g"], "M" => [18, "\x08g"], "N" => [77, "\x08h"], "O" => [18, "\x08h"], "P" => [77, "\x08l"], "Q" => [18, "\x08l"], "R" => [77, "\x08m"], "S" => [18, "\x08m"], "T" => [77, "\x08n"], "U" => [18, "\x08n"], "V" => [77, "\x08p"], "W" => [18, "\x08p"], "X" => [77, "\x08r"], "Y" => [18, "\x08r"], "Z" => [77, "\x08u"], "[" => [18, "\x08u"], "\\" => [0, "\x08:"], "]" => [0, "\x08B"], "^" => [0, "\x08C"], "_" => [0, "\x08D"], "`" => [0, "\x08E"], "a" => [0, "\x08F"], "b" => [0, "\x08G"], "c" => [0, "\x08H"], "d" => [0, "\x08I"], "e" => [0, "\x08J"], "f" => [0, "\x08K"], "g" => [0, "\x08L"], "h" => [0, "\x08M"], "i" => [0, "\x08N"], "j" => [0, "\x08O"], "k" => [0, "\x08P"], "l" => [0, "\x08Q"], "m" => [0, "\x08R"], "n" => [0, "\x08S"], "o" => [0, "\x08T"], "p" => [0, "\x08U"], "q" => [0, "\x08V"], "r" => [0, "\x08W"], "s" => [0, "\x08Y"], "t" => [0, "\x08j"], "u" => [0, "\x08k"], "v" => [0, "\x08q"], "w" => [0, "\x08v"], "x" => [0, "\x08w"], "y" => [0, "\x08x"], "z" => [0, "\x08y"], "{" => [0, "\x08z"], "|" => [82, "\x08"], "}" => [87, "\x08"], "~" => [130, "\x08"], "" => [9, "\x08"], "\x80" => [94, "\v0"], "\x81" => [76, "\v0"], "\x82" => [104, "\v0"], "\x83" => [16, "\v0"], "\x84" => [94, "\v1"], "\x85" => [76, "\v1"], "\x86" => [104, "\v1"], "\x87" => [16, "\v1"], "\x88" => [94, "\v2"], "\x89" => [76, "\v2"], "\x8a" => [104, "\v2"], "\x8b" => [16, "\v2"], "\x8c" => [94, "\va"], "\x8d" => [76, "\va"], "\x8e" => [104, "\va"], "\x8f" => [16, "\va"], "\x90" => [94, "\vc"], "\x91" => [76, "\vc"], "\x92" => [104, "\vc"], "\x93" => [16, "\vc"], "\x94" => [94, "\ve"], "\x95" => [76, "\ve"], "\x96" => [104, "\ve"], "\x97" => [16, "\ve"], "\x98" => [94, "\vi"], "\x99" => [76, "\vi"], "\x9a" => [104, "\vi"], "\x9b" => [16, "\vi"], "\x9c" => [94, "\vo"], "\x9d" => [76, "\vo"], "\x9e" => [104, "\vo"], "\x9f" => [16, "\vo"], "\xa0" => [94, "\vs"], "\xa1" => [76, "\vs"], "\xa2" => [104, "\vs"], "\xa3" => [16, "\vs"], "\xa4" => [94, "\vt"], "\xa5" => [76, "\vt"], "\xa6" => [104, "\vt"], "\xa7" => [16, "\vt"], "\xa8" => [77, "\v "], "\xa9" => [18, "\v "], "\xaa" => [77, "\v%"], "\xab" => [18, "\v%"], "\xac" => [77, "\v-"], "\xad" => [18, "\v-"], "\xae" => [77, "\v."], "\xaf" => [18, "\v."], "\xb0" => [77, "\v/"], "\xb1" => [18, "\v/"], "\xb2" => [77, "\v3"], "\xb3" => [18, "\v3"], "\xb4" => [77, "\v4"], "\xb5" => [18, "\v4"], "\xb6" => [77, "\v5"], "\xb7" => [18, "\v5"], "\xb8" => [77, "\v6"], "\xb9" => [18, "\v6"], "\xba" => [77, "\v7"], "\xbb" => [18, "\v7"], "\xbc" => [77, "\v8"], "\xbd" => [18, "\v8"], "\xbe" => [77, "\v9"], "\xbf" => [18, "\v9"], "\xc0" => [77, "\v="], "\xc1" => [18, "\v="], "\xc2" => [77, "\vA"], "\xc3" => [18, "\vA"], "\xc4" => [77, "\v_"], "\xc5" => [18, "\v_"], "\xc6" => [77, "\vb"], "\xc7" => [18, "\vb"], "\xc8" => [77, "\vd"], "\xc9" => [18, "\vd"], "\xca" => [77, "\vf"], "\xcb" => [18, "\vf"], "\xcc" => [77, "\vg"], "\xcd" => [18, "\vg"], "\xce" => [77, "\vh"], "\xcf" => [18, "\vh"], "\xd0" => [77, "\vl"], "\xd1" => [18, "\vl"], "\xd2" => [77, "\vm"], "\xd3" => [18, "\vm"], "\xd4" => [77, "\vn"], "\xd5" => [18, "\vn"], "\xd6" => [77, "\vp"], "\xd7" => [18, "\vp"], "\xd8" => [77, "\vr"], "\xd9" => [18, "\vr"], "\xda" => [77, "\vu"], "\xdb" => [18, "\vu"], "\xdc" => [0, "\v:"], "\xdd" => [0, "\vB"], "\xde" => [0, "\vC"], "\xdf" => [0, "\vD"], "\xe0" => [0, "\vE"], "\xe1" => [0, "\vF"], "\xe2" => [0, "\vG"], "\xe3" => [0, "\vH"], "\xe4" => [0, "\vI"], "\xe5" => [0, "\vJ"], "\xe6" => [0, "\vK"], "\xe7" => [0, "\vL"], "\xe8" => [0, "\vM"], "\xe9" => [0, "\vN"], "\xea" => [0, "\vO"], "\xeb" => [0, "\vP"], "\xec" => [0, "\vQ"], "\xed" => [0, "\vR"], "\xee" => [0, "\vS"], "\xef" => [0, "\vT"], "\xf0" => [0, "\vU"], "\xf1" => [0, "\vV"], "\xf2" => [0, "\vW"], "\xf3" => [0, "\vY"], "\xf4" => [0, "\vj"], "\xf5" => [0, "\vk"], "\xf6" => [0, "\vq"], "\xf7" => [0, "\vv"], "\xf8" => [0, "\vw"], "\xf9" => [0, "\vx"], "\xfa" => [0, "\vy"], "\xfb" => [0, "\vz"], "\xfc" => [82, "\v"], "\xfd" => [87, "\v"], "\xfe" => [130, "\v"], "\xff" => [9, "\v"]], ["\x00" => [77, "\x080"], "\x01" => [18, "\x080"], "\x02" => [77, "\x081"], "\x03" => [18, "\x081"], "\x04" => [77, "\x082"], "\x05" => [18, "\x082"], "\x06" => [77, "\x08a"], "\x07" => [18, "\x08a"], "\x08" => [77, "\x08c"], "\t" => [18, "\x08c"], "\n" => [77, "\x08e"], "\v" => [18, "\x08e"], "\f" => [77, "\x08i"], "\r" => [18, "\x08i"], "\x0e" => [77, "\x08o"], "\x0f" => [18, "\x08o"], "\x10" => [77, "\x08s"], "\x11" => [18, "\x08s"], "\x12" => [77, "\x08t"], "\x13" => [18, "\x08t"], "\x14" => [0, "\x08 "], "\x15" => [0, "\x08%"], "\x16" => [0, "\x08-"], "\x17" => [0, "\x08."], "\x18" => [0, "\x08/"], "\x19" => [0, "\x083"], "\x1a" => [0, "\x084"], "\x1b" => [0, "\x085"], "\x1c" => [0, "\x086"], "\x1d" => [0, "\x087"], "\x1e" => [0, "\x088"], "\x1f" => [0, "\x089"], " " => [0, "\x08="], "!" => [0, "\x08A"], "\"" => [0, "\x08_"], "#" => [0, "\x08b"], "\$" => [0, "\x08d"], "%" => [0, "\x08f"], "&" => [0, "\x08g"], "'" => [0, "\x08h"], "(" => [0, "\x08l"], ")" => [0, "\x08m"], "*" => [0, "\x08n"], "+" => [0, "\x08p"], "," => [0, "\x08r"], "-" => [0, "\x08u"], "." => [100, "\x08"], "/" => [110, "\x08"], [111, "\x08"], [115, "\x08"], [116, "\x08"], [118, "\x08"], [119, "\x08"], [122, "\x08"], [123, "\x08"], [125, "\x08"], [126, "\x08"], [129, "\x08"], ":" => [143, "\x08"], ";" => [148, "\x08"], "<" => [151, "\x08"], "=" => [153, "\x08"], ">" => [83, "\x08"], "?" => [10, "\x08"], "@" => [77, "\v0"], "A" => [18, "\v0"], "B" => [77, "\v1"], "C" => [18, "\v1"], "D" => [77, "\v2"], "E" => [18, "\v2"], "F" => [77, "\va"], "G" => [18, "\va"], "H" => [77, "\vc"], "I" => [18, "\vc"], "J" => [77, "\ve"], "K" => [18, "\ve"], "L" => [77, "\vi"], "M" => [18, "\vi"], "N" => [77, "\vo"], "O" => [18, "\vo"], "P" => [77, "\vs"], "Q" => [18, "\vs"], "R" => [77, "\vt"], "S" => [18, "\vt"], "T" => [0, "\v "], "U" => [0, "\v%"], "V" => [0, "\v-"], "W" => [0, "\v."], "X" => [0, "\v/"], "Y" => [0, "\v3"], "Z" => [0, "\v4"], "[" => [0, "\v5"], "\\" => [0, "\v6"], "]" => [0, "\v7"], "^" => [0, "\v8"], "_" => [0, "\v9"], "`" => [0, "\v="], "a" => [0, "\vA"], "b" => [0, "\v_"], "c" => [0, "\vb"], "d" => [0, "\vd"], "e" => [0, "\vf"], "f" => [0, "\vg"], "g" => [0, "\vh"], "h" => [0, "\vl"], "i" => [0, "\vm"], "j" => [0, "\vn"], "k" => [0, "\vp"], "l" => [0, "\vr"], "m" => [0, "\vu"], "n" => [100, "\v"], "o" => [110, "\v"], "p" => [111, "\v"], "q" => [115, "\v"], "r" => [116, "\v"], "s" => [118, "\v"], "t" => [119, "\v"], "u" => [122, "\v"], "v" => [123, "\v"], "w" => [125, "\v"], "x" => [126, "\v"], "y" => [129, "\v"], "z" => [143, "\v"], "{" => [148, "\v"], "|" => [151, "\v"], "}" => [153, "\v"], "~" => [83, "\v"], "" => [10, "\v"], "\x80" => [77, "\f0"], "\x81" => [18, "\f0"], "\x82" => [77, "\f1"], "\x83" => [18, "\f1"], "\x84" => [77, "\f2"], "\x85" => [18, "\f2"], "\x86" => [77, "\fa"], "\x87" => [18, "\fa"], "\x88" => [77, "\fc"], "\x89" => [18, "\fc"], "\x8a" => [77, "\fe"], "\x8b" => [18, "\fe"], "\x8c" => [77, "\fi"], "\x8d" => [18, "\fi"], "\x8e" => [77, "\fo"], "\x8f" => [18, "\fo"], "\x90" => [77, "\fs"], "\x91" => [18, "\fs"], "\x92" => [77, "\ft"], "\x93" => [18, "\ft"], "\x94" => [0, "\f "], "\x95" => [0, "\f%"], "\x96" => [0, "\f-"], "\x97" => [0, "\f."], "\x98" => [0, "\f/"], "\x99" => [0, "\f3"], "\x9a" => [0, "\f4"], "\x9b" => [0, "\f5"], "\x9c" => [0, "\f6"], "\x9d" => [0, "\f7"], "\x9e" => [0, "\f8"], "\x9f" => [0, "\f9"], "\xa0" => [0, "\f="], "\xa1" => [0, "\fA"], "\xa2" => [0, "\f_"], "\xa3" => [0, "\fb"], "\xa4" => [0, "\fd"], "\xa5" => [0, "\ff"], "\xa6" => [0, "\fg"], "\xa7" => [0, "\fh"], "\xa8" => [0, "\fl"], "\xa9" => [0, "\fm"], "\xaa" => [0, "\fn"], "\xab" => [0, "\fp"], "\xac" => [0, "\fr"], "\xad" => [0, "\fu"], "\xae" => [100, "\f"], "\xaf" => [110, "\f"], "\xb0" => [111, "\f"], "\xb1" => [115, "\f"], "\xb2" => [116, "\f"], "\xb3" => [118, "\f"], "\xb4" => [119, "\f"], "\xb5" => [122, "\f"], "\xb6" => [123, "\f"], "\xb7" => [125, "\f"], "\xb8" => [126, "\f"], "\xb9" => [129, "\f"], "\xba" => [143, "\f"], "\xbb" => [148, "\f"], "\xbc" => [151, "\f"], "\xbd" => [153, "\f"], "\xbe" => [83, "\f"], "\xbf" => [10, "\f"], "\xc0" => [77, "\x0e0"], "\xc1" => [18, "\x0e0"], "\xc2" => [77, "\x0e1"], "\xc3" => [18, "\x0e1"], "\xc4" => [77, "\x0e2"], "\xc5" => [18, "\x0e2"], "\xc6" => [77, "\x0ea"], "\xc7" => [18, "\x0ea"], "\xc8" => [77, "\x0ec"], "\xc9" => [18, "\x0ec"], "\xca" => [77, "\x0ee"], "\xcb" => [18, "\x0ee"], "\xcc" => [77, "\x0ei"], "\xcd" => [18, "\x0ei"], "\xce" => [77, "\x0eo"], "\xcf" => [18, "\x0eo"], "\xd0" => [77, "\x0es"], "\xd1" => [18, "\x0es"], "\xd2" => [77, "\x0et"], "\xd3" => [18, "\x0et"], "\xd4" => [0, "\x0e "], "\xd5" => [0, "\x0e%"], "\xd6" => [0, "\x0e-"], "\xd7" => [0, "\x0e."], "\xd8" => [0, "\x0e/"], "\xd9" => [0, "\x0e3"], "\xda" => [0, "\x0e4"], "\xdb" => [0, "\x0e5"], "\xdc" => [0, "\x0e6"], "\xdd" => [0, "\x0e7"], "\xde" => [0, "\x0e8"], "\xdf" => [0, "\x0e9"], "\xe0" => [0, "\x0e="], "\xe1" => [0, "\x0eA"], "\xe2" => [0, "\x0e_"], "\xe3" => [0, "\x0eb"], "\xe4" => [0, "\x0ed"], "\xe5" => [0, "\x0ef"], "\xe6" => [0, "\x0eg"], "\xe7" => [0, "\x0eh"], "\xe8" => [0, "\x0el"], "\xe9" => [0, "\x0em"], "\xea" => [0, "\x0en"], "\xeb" => [0, "\x0ep"], "\xec" => [0, "\x0er"], "\xed" => [0, "\x0eu"], "\xee" => [100, "\x0e"], "\xef" => [110, "\x0e"], "\xf0" => [111, "\x0e"], "\xf1" => [115, "\x0e"], "\xf2" => [116, "\x0e"], "\xf3" => [118, "\x0e"], "\xf4" => [119, "\x0e"], "\xf5" => [122, "\x0e"], "\xf6" => [123, "\x0e"], "\xf7" => [125, "\x0e"], "\xf8" => [126, "\x0e"], "\xf9" => [129, "\x0e"], "\xfa" => [143, "\x0e"], "\xfb" => [148, "\x0e"], "\xfc" => [151, "\x0e"], "\xfd" => [153, "\x0e"], "\xfe" => [83, "\x0e"], "\xff" => [10, "\x0e"]], ["\x00" => [0, "\x080"], "\x01" => [0, "\x081"], "\x02" => [0, "\x082"], "\x03" => [0, "\x08a"], "\x04" => [0, "\x08c"], "\x05" => [0, "\x08e"], "\x06" => [0, "\x08i"], "\x07" => [0, "\x08o"], "\x08" => [0, "\x08s"], "\t" => [0, "\x08t"], "\n" => [73, "\x08"], "\v" => [88, "\x08"], "\f" => [89, "\x08"], "\r" => [96, "\x08"], "\x0e" => [97, "\x08"], "\x0f" => [99, "\x08"], "\x10" => [106, "\x08"], "\x11" => [136, "\x08"], "\x12" => [139, "\x08"], "\x13" => [141, "\x08"], "\x14" => [145, "\x08"], "\x15" => [147, "\x08"], "\x16" => [149, "\x08"], "\x17" => [101, "\x08"], "\x18" => [112, "\x08"], "\x19" => [117, "\x08"], "\x1a" => [120, "\x08"], "\x1b" => [124, "\x08"], "\x1c" => [127, "\x08"], "\x1d" => [144, "\x08"], "\x1e" => [152, "\x08"], "\x1f" => [11, "\x08"], " " => [0, "\v0"], "!" => [0, "\v1"], "\"" => [0, "\v2"], "#" => [0, "\va"], "\$" => [0, "\vc"], "%" => [0, "\ve"], "&" => [0, "\vi"], "'" => [0, "\vo"], "(" => [0, "\vs"], ")" => [0, "\vt"], "*" => [73, "\v"], "+" => [88, "\v"], "," => [89, "\v"], "-" => [96, "\v"], "." => [97, "\v"], "/" => [99, "\v"], [106, "\v"], [136, "\v"], [139, "\v"], [141, "\v"], [145, "\v"], [147, "\v"], [149, "\v"], [101, "\v"], [112, "\v"], [117, "\v"], ":" => [120, "\v"], ";" => [124, "\v"], "<" => [127, "\v"], "=" => [144, "\v"], ">" => [152, "\v"], "?" => [11, "\v"], "@" => [0, "\f0"], "A" => [0, "\f1"], "B" => [0, "\f2"], "C" => [0, "\fa"], "D" => [0, "\fc"], "E" => [0, "\fe"], "F" => [0, "\fi"], "G" => [0, "\fo"], "H" => [0, "\fs"], "I" => [0, "\ft"], "J" => [73, "\f"], "K" => [88, "\f"], "L" => [89, "\f"], "M" => [96, "\f"], "N" => [97, "\f"], "O" => [99, "\f"], "P" => [106, "\f"], "Q" => [136, "\f"], "R" => [139, "\f"], "S" => [141, "\f"], "T" => [145, "\f"], "U" => [147, "\f"], "V" => [149, "\f"], "W" => [101, "\f"], "X" => [112, "\f"], "Y" => [117, "\f"], "Z" => [120, "\f"], "[" => [124, "\f"], "\\" => [127, "\f"], "]" => [144, "\f"], "^" => [152, "\f"], "_" => [11, "\f"], "`" => [0, "\x0e0"], "a" => [0, "\x0e1"], "b" => [0, "\x0e2"], "c" => [0, "\x0ea"], "d" => [0, "\x0ec"], "e" => [0, "\x0ee"], "f" => [0, "\x0ei"], "g" => [0, "\x0eo"], "h" => [0, "\x0es"], "i" => [0, "\x0et"], "j" => [73, "\x0e"], "k" => [88, "\x0e"], "l" => [89, "\x0e"], "m" => [96, "\x0e"], "n" => [97, "\x0e"], "o" => [99, "\x0e"], "p" => [106, "\x0e"], "q" => [136, "\x0e"], "r" => [139, "\x0e"], "s" => [141, "\x0e"], "t" => [145, "\x0e"], "u" => [147, "\x0e"], "v" => [149, "\x0e"], "w" => [101, "\x0e"], "x" => [112, "\x0e"], "y" => [117, "\x0e"], "z" => [120, "\x0e"], "{" => [124, "\x0e"], "|" => [127, "\x0e"], "}" => [144, "\x0e"], "~" => [152, "\x0e"], "" => [11, "\x0e"], "\x80" => [0, "\x0f0"], "\x81" => [0, "\x0f1"], "\x82" => [0, "\x0f2"], "\x83" => [0, "\x0fa"], "\x84" => [0, "\x0fc"], "\x85" => [0, "\x0fe"], "\x86" => [0, "\x0fi"], "\x87" => [0, "\x0fo"], "\x88" => [0, "\x0fs"], "\x89" => [0, "\x0ft"], "\x8a" => [73, "\x0f"], "\x8b" => [88, "\x0f"], "\x8c" => [89, "\x0f"], "\x8d" => [96, "\x0f"], "\x8e" => [97, "\x0f"], "\x8f" => [99, "\x0f"], "\x90" => [106, "\x0f"], "\x91" => [136, "\x0f"], "\x92" => [139, "\x0f"], "\x93" => [141, "\x0f"], "\x94" => [145, "\x0f"], "\x95" => [147, "\x0f"], "\x96" => [149, "\x0f"], "\x97" => [101, "\x0f"], "\x98" => [112, "\x0f"], "\x99" => [117, "\x0f"], "\x9a" => [120, "\x0f"], "\x9b" => [124, "\x0f"], "\x9c" => [127, "\x0f"], "\x9d" => [144, "\x0f"], "\x9e" => [152, "\x0f"], "\x9f" => [11, "\x0f"], "\xa0" => [0, "\x100"], "\xa1" => [0, "\x101"], "\xa2" => [0, "\x102"], "\xa3" => [0, "\x10a"], "\xa4" => [0, "\x10c"], "\xa5" => [0, "\x10e"], "\xa6" => [0, "\x10i"], "\xa7" => [0, "\x10o"], "\xa8" => [0, "\x10s"], "\xa9" => [0, "\x10t"], "\xaa" => [73, "\x10"], "\xab" => [88, "\x10"], "\xac" => [89, "\x10"], "\xad" => [96, "\x10"], "\xae" => [97, "\x10"], "\xaf" => [99, "\x10"], "\xb0" => [106, "\x10"], "\xb1" => [136, "\x10"], "\xb2" => [139, "\x10"], "\xb3" => [141, "\x10"], "\xb4" => [145, "\x10"], "\xb5" => [147, "\x10"], "\xb6" => [149, "\x10"], "\xb7" => [101, "\x10"], "\xb8" => [112, "\x10"], "\xb9" => [117, "\x10"], "\xba" => [120, "\x10"], "\xbb" => [124, "\x10"], "\xbc" => [127, "\x10"], "\xbd" => [144, "\x10"], "\xbe" => [152, "\x10"], "\xbf" => [11, "\x10"], "\xc0" => [0, "\x110"], "\xc1" => [0, "\x111"], "\xc2" => [0, "\x112"], "\xc3" => [0, "\x11a"], "\xc4" => [0, "\x11c"], "\xc5" => [0, "\x11e"], "\xc6" => [0, "\x11i"], "\xc7" => [0, "\x11o"], "\xc8" => [0, "\x11s"], "\xc9" => [0, "\x11t"], "\xca" => [73, "\x11"], "\xcb" => [88, "\x11"], "\xcc" => [89, "\x11"], "\xcd" => [96, "\x11"], "\xce" => [97, "\x11"], "\xcf" => [99, "\x11"], "\xd0" => [106, "\x11"], "\xd1" => [136, "\x11"], "\xd2" => [139, "\x11"], "\xd3" => [141, "\x11"], "\xd4" => [145, "\x11"], "\xd5" => [147, "\x11"], "\xd6" => [149, "\x11"], "\xd7" => [101, "\x11"], "\xd8" => [112, "\x11"], "\xd9" => [117, "\x11"], "\xda" => [120, "\x11"], "\xdb" => [124, "\x11"], "\xdc" => [127, "\x11"], "\xdd" => [144, "\x11"], "\xde" => [152, "\x11"], "\xdf" => [11, "\x11"], "\xe0" => [0, "\x120"], "\xe1" => [0, "\x121"], "\xe2" => [0, "\x122"], "\xe3" => [0, "\x12a"], "\xe4" => [0, "\x12c"], "\xe5" => [0, "\x12e"], "\xe6" => [0, "\x12i"], "\xe7" => [0, "\x12o"], "\xe8" => [0, "\x12s"], "\xe9" => [0, "\x12t"], "\xea" => [73, "\x12"], "\xeb" => [88, "\x12"], "\xec" => [89, "\x12"], "\xed" => [96, "\x12"], "\xee" => [97, "\x12"], "\xef" => [99, "\x12"], "\xf0" => [106, "\x12"], "\xf1" => [136, "\x12"], "\xf2" => [139, "\x12"], "\xf3" => [141, "\x12"], "\xf4" => [145, "\x12"], "\xf5" => [147, "\x12"], "\xf6" => [149, "\x12"], "\xf7" => [101, "\x12"], "\xf8" => [112, "\x12"], "\xf9" => [117, "\x12"], "\xfa" => [120, "\x12"], "\xfb" => [124, "\x12"], "\xfc" => [127, "\x12"], "\xfd" => [144, "\x12"], "\xfe" => [152, "\x12"], "\xff" => [11, "\x12"]], ["\x00" => [94, "\t0"], "\x01" => [76, "\t0"], "\x02" => [104, "\t0"], "\x03" => [16, "\t0"], "\x04" => [94, "\t1"], "\x05" => [76, "\t1"], "\x06" => [104, "\t1"], "\x07" => [16, "\t1"], "\x08" => [94, "\t2"], "\t" => [76, "\t2"], "\n" => [104, "\t2"], "\v" => [16, "\t2"], "\f" => [94, "\ta"], "\r" => [76, "\ta"], "\x0e" => [104, "\ta"], "\x0f" => [16, "\ta"], "\x10" => [94, "\tc"], "\x11" => [76, "\tc"], "\x12" => [104, "\tc"], "\x13" => [16, "\tc"], "\x14" => [94, "\te"], "\x15" => [76, "\te"], "\x16" => [104, "\te"], "\x17" => [16, "\te"], "\x18" => [94, "\ti"], "\x19" => [76, "\ti"], "\x1a" => [104, "\ti"], "\x1b" => [16, "\ti"], "\x1c" => [94, "\to"], "\x1d" => [76, "\to"], "\x1e" => [104, "\to"], "\x1f" => [16, "\to"], " " => [94, "\ts"], "!" => [76, "\ts"], "\"" => [104, "\ts"], "#" => [16, "\ts"], "\$" => [94, "\tt"], "%" => [76, "\tt"], "&" => [104, "\tt"], "'" => [16, "\tt"], "(" => [77, "\t "], ")" => [18, "\t "], "*" => [77, "\t%"], "+" => [18, "\t%"], "," => [77, "\t-"], "-" => [18, "\t-"], "." => [77, "\t."], "/" => [18, "\t."], [77, "\t/"], [18, "\t/"], [77, "\t3"], [18, "\t3"], [77, "\t4"], [18, "\t4"], [77, "\t5"], [18, "\t5"], [77, "\t6"], [18, "\t6"], ":" => [77, "\t7"], ";" => [18, "\t7"], "<" => [77, "\t8"], "=" => [18, "\t8"], ">" => [77, "\t9"], "?" => [18, "\t9"], "@" => [77, "\t="], "A" => [18, "\t="], "B" => [77, "\tA"], "C" => [18, "\tA"], "D" => [77, "\t_"], "E" => [18, "\t_"], "F" => [77, "\tb"], "G" => [18, "\tb"], "H" => [77, "\td"], "I" => [18, "\td"], "J" => [77, "\tf"], "K" => [18, "\tf"], "L" => [77, "\tg"], "M" => [18, "\tg"], "N" => [77, "\th"], "O" => [18, "\th"], "P" => [77, "\tl"], "Q" => [18, "\tl"], "R" => [77, "\tm"], "S" => [18, "\tm"], "T" => [77, "\tn"], "U" => [18, "\tn"], "V" => [77, "\tp"], "W" => [18, "\tp"], "X" => [77, "\tr"], "Y" => [18, "\tr"], "Z" => [77, "\tu"], "[" => [18, "\tu"], "\\" => [0, "\t:"], "]" => [0, "\tB"], "^" => [0, "\tC"], "_" => [0, "\tD"], "`" => [0, "\tE"], "a" => [0, "\tF"], "b" => [0, "\tG"], "c" => [0, "\tH"], "d" => [0, "\tI"], "e" => [0, "\tJ"], "f" => [0, "\tK"], "g" => [0, "\tL"], "h" => [0, "\tM"], "i" => [0, "\tN"], "j" => [0, "\tO"], "k" => [0, "\tP"], "l" => [0, "\tQ"], "m" => [0, "\tR"], "n" => [0, "\tS"], "o" => [0, "\tT"], "p" => [0, "\tU"], "q" => [0, "\tV"], "r" => [0, "\tW"], "s" => [0, "\tY"], "t" => [0, "\tj"], "u" => [0, "\tk"], "v" => [0, "\tq"], "w" => [0, "\tv"], "x" => [0, "\tw"], "y" => [0, "\tx"], "z" => [0, "\ty"], "{" => [0, "\tz"], "|" => [82, "\t"], "}" => [87, "\t"], "~" => [130, "\t"], "" => [9, "\t"], "\x80" => [94, "\x8e0"], "\x81" => [76, "\x8e0"], "\x82" => [104, "\x8e0"], "\x83" => [16, "\x8e0"], "\x84" => [94, "\x8e1"], "\x85" => [76, "\x8e1"], "\x86" => [104, "\x8e1"], "\x87" => [16, "\x8e1"], "\x88" => [94, "\x8e2"], "\x89" => [76, "\x8e2"], "\x8a" => [104, "\x8e2"], "\x8b" => [16, "\x8e2"], "\x8c" => [94, "\x8ea"], "\x8d" => [76, "\x8ea"], "\x8e" => [104, "\x8ea"], "\x8f" => [16, "\x8ea"], "\x90" => [94, "\x8ec"], "\x91" => [76, "\x8ec"], "\x92" => [104, "\x8ec"], "\x93" => [16, "\x8ec"], "\x94" => [94, "\x8ee"], "\x95" => [76, "\x8ee"], "\x96" => [104, "\x8ee"], "\x97" => [16, "\x8ee"], "\x98" => [94, "\x8ei"], "\x99" => [76, "\x8ei"], "\x9a" => [104, "\x8ei"], "\x9b" => [16, "\x8ei"], "\x9c" => [94, "\x8eo"], "\x9d" => [76, "\x8eo"], "\x9e" => [104, "\x8eo"], "\x9f" => [16, "\x8eo"], "\xa0" => [94, "\x8es"], "\xa1" => [76, "\x8es"], "\xa2" => [104, "\x8es"], "\xa3" => [16, "\x8es"], "\xa4" => [94, "\x8et"], "\xa5" => [76, "\x8et"], "\xa6" => [104, "\x8et"], "\xa7" => [16, "\x8et"], "\xa8" => [77, "\x8e "], "\xa9" => [18, "\x8e "], "\xaa" => [77, "\x8e%"], "\xab" => [18, "\x8e%"], "\xac" => [77, "\x8e-"], "\xad" => [18, "\x8e-"], "\xae" => [77, "\x8e."], "\xaf" => [18, "\x8e."], "\xb0" => [77, "\x8e/"], "\xb1" => [18, "\x8e/"], "\xb2" => [77, "\x8e3"], "\xb3" => [18, "\x8e3"], "\xb4" => [77, "\x8e4"], "\xb5" => [18, "\x8e4"], "\xb6" => [77, "\x8e5"], "\xb7" => [18, "\x8e5"], "\xb8" => [77, "\x8e6"], "\xb9" => [18, "\x8e6"], "\xba" => [77, "\x8e7"], "\xbb" => [18, "\x8e7"], "\xbc" => [77, "\x8e8"], "\xbd" => [18, "\x8e8"], "\xbe" => [77, "\x8e9"], "\xbf" => [18, "\x8e9"], "\xc0" => [77, "\x8e="], "\xc1" => [18, "\x8e="], "\xc2" => [77, "\x8eA"], "\xc3" => [18, "\x8eA"], "\xc4" => [77, "\x8e_"], "\xc5" => [18, "\x8e_"], "\xc6" => [77, "\x8eb"], "\xc7" => [18, "\x8eb"], "\xc8" => [77, "\x8ed"], "\xc9" => [18, "\x8ed"], "\xca" => [77, "\x8ef"], "\xcb" => [18, "\x8ef"], "\xcc" => [77, "\x8eg"], "\xcd" => [18, "\x8eg"], "\xce" => [77, "\x8eh"], "\xcf" => [18, "\x8eh"], "\xd0" => [77, "\x8el"], "\xd1" => [18, "\x8el"], "\xd2" => [77, "\x8em"], "\xd3" => [18, "\x8em"], "\xd4" => [77, "\x8en"], "\xd5" => [18, "\x8en"], "\xd6" => [77, "\x8ep"], "\xd7" => [18, "\x8ep"], "\xd8" => [77, "\x8er"], "\xd9" => [18, "\x8er"], "\xda" => [77, "\x8eu"], "\xdb" => [18, "\x8eu"], "\xdc" => [0, "\x8e:"], "\xdd" => [0, "\x8eB"], "\xde" => [0, "\x8eC"], "\xdf" => [0, "\x8eD"], "\xe0" => [0, "\x8eE"], "\xe1" => [0, "\x8eF"], "\xe2" => [0, "\x8eG"], "\xe3" => [0, "\x8eH"], "\xe4" => [0, "\x8eI"], "\xe5" => [0, "\x8eJ"], "\xe6" => [0, "\x8eK"], "\xe7" => [0, "\x8eL"], "\xe8" => [0, "\x8eM"], "\xe9" => [0, "\x8eN"], "\xea" => [0, "\x8eO"], "\xeb" => [0, "\x8eP"], "\xec" => [0, "\x8eQ"], "\xed" => [0, "\x8eR"], "\xee" => [0, "\x8eS"], "\xef" => [0, "\x8eT"], "\xf0" => [0, "\x8eU"], "\xf1" => [0, "\x8eV"], "\xf2" => [0, "\x8eW"], "\xf3" => [0, "\x8eY"], "\xf4" => [0, "\x8ej"], "\xf5" => [0, "\x8ek"], "\xf6" => [0, "\x8eq"], "\xf7" => [0, "\x8ev"], "\xf8" => [0, "\x8ew"], "\xf9" => [0, "\x8ex"], "\xfa" => [0, "\x8ey"], "\xfb" => [0, "\x8ez"], "\xfc" => [82, "\x8e"], "\xfd" => [87, "\x8e"], "\xfe" => [130, "\x8e"], "\xff" => [9, "\x8e"]], ["\x00" => [94, "\xef0"], "\x01" => [76, "\xef0"], "\x02" => [104, "\xef0"], "\x03" => [16, "\xef0"], "\x04" => [94, "\xef1"], "\x05" => [76, "\xef1"], "\x06" => [104, "\xef1"], "\x07" => [16, "\xef1"], "\x08" => [94, "\xef2"], "\t" => [76, "\xef2"], "\n" => [104, "\xef2"], "\v" => [16, "\xef2"], "\f" => [94, "\xefa"], "\r" => [76, "\xefa"], "\x0e" => [104, "\xefa"], "\x0f" => [16, "\xefa"], "\x10" => [94, "\xefc"], "\x11" => [76, "\xefc"], "\x12" => [104, "\xefc"], "\x13" => [16, "\xefc"], "\x14" => [94, "\xefe"], "\x15" => [76, "\xefe"], "\x16" => [104, "\xefe"], "\x17" => [16, "\xefe"], "\x18" => [94, "\xefi"], "\x19" => [76, "\xefi"], "\x1a" => [104, "\xefi"], "\x1b" => [16, "\xefi"], "\x1c" => [94, "\xefo"], "\x1d" => [76, "\xefo"], "\x1e" => [104, "\xefo"], "\x1f" => [16, "\xefo"], " " => [94, "\xefs"], "!" => [76, "\xefs"], "\"" => [104, "\xefs"], "#" => [16, "\xefs"], "\$" => [94, "\xeft"], "%" => [76, "\xeft"], "&" => [104, "\xeft"], "'" => [16, "\xeft"], "(" => [77, "\xef "], ")" => [18, "\xef "], "*" => [77, "\xef%"], "+" => [18, "\xef%"], "," => [77, "\xef-"], "-" => [18, "\xef-"], "." => [77, "\xef."], "/" => [18, "\xef."], [77, "\xef/"], [18, "\xef/"], [77, "\xef3"], [18, "\xef3"], [77, "\xef4"], [18, "\xef4"], [77, "\xef5"], [18, "\xef5"], [77, "\xef6"], [18, "\xef6"], ":" => [77, "\xef7"], ";" => [18, "\xef7"], "<" => [77, "\xef8"], "=" => [18, "\xef8"], ">" => [77, "\xef9"], "?" => [18, "\xef9"], "@" => [77, "\xef="], "A" => [18, "\xef="], "B" => [77, "\xefA"], "C" => [18, "\xefA"], "D" => [77, "\xef_"], "E" => [18, "\xef_"], "F" => [77, "\xefb"], "G" => [18, "\xefb"], "H" => [77, "\xefd"], "I" => [18, "\xefd"], "J" => [77, "\xeff"], "K" => [18, "\xeff"], "L" => [77, "\xefg"], "M" => [18, "\xefg"], "N" => [77, "\xefh"], "O" => [18, "\xefh"], "P" => [77, "\xefl"], "Q" => [18, "\xefl"], "R" => [77, "\xefm"], "S" => [18, "\xefm"], "T" => [77, "\xefn"], "U" => [18, "\xefn"], "V" => [77, "\xefp"], "W" => [18, "\xefp"], "X" => [77, "\xefr"], "Y" => [18, "\xefr"], "Z" => [77, "\xefu"], "[" => [18, "\xefu"], "\\" => [0, "\xef:"], "]" => [0, "\xefB"], "^" => [0, "\xefC"], "_" => [0, "\xefD"], "`" => [0, "\xefE"], "a" => [0, "\xefF"], "b" => [0, "\xefG"], "c" => [0, "\xefH"], "d" => [0, "\xefI"], "e" => [0, "\xefJ"], "f" => [0, "\xefK"], "g" => [0, "\xefL"], "h" => [0, "\xefM"], "i" => [0, "\xefN"], "j" => [0, "\xefO"], "k" => [0, "\xefP"], "l" => [0, "\xefQ"], "m" => [0, "\xefR"], "n" => [0, "\xefS"], "o" => [0, "\xefT"], "p" => [0, "\xefU"], "q" => [0, "\xefV"], "r" => [0, "\xefW"], "s" => [0, "\xefY"], "t" => [0, "\xefj"], "u" => [0, "\xefk"], "v" => [0, "\xefq"], "w" => [0, "\xefv"], "x" => [0, "\xefw"], "y" => [0, "\xefx"], "z" => [0, "\xefy"], "{" => [0, "\xefz"], "|" => [82, "\xef"], "}" => [87, "\xef"], "~" => [130, "\xef"], "" => [9, "\xef"], "\x80" => [77, "\t0"], "\x81" => [18, "\t0"], "\x82" => [77, "\t1"], "\x83" => [18, "\t1"], "\x84" => [77, "\t2"], "\x85" => [18, "\t2"], "\x86" => [77, "\ta"], "\x87" => [18, "\ta"], "\x88" => [77, "\tc"], "\x89" => [18, "\tc"], "\x8a" => [77, "\te"], "\x8b" => [18, "\te"], "\x8c" => [77, "\ti"], "\x8d" => [18, "\ti"], "\x8e" => [77, "\to"], "\x8f" => [18, "\to"], "\x90" => [77, "\ts"], "\x91" => [18, "\ts"], "\x92" => [77, "\tt"], "\x93" => [18, "\tt"], "\x94" => [0, "\t "], "\x95" => [0, "\t%"], "\x96" => [0, "\t-"], "\x97" => [0, "\t."], "\x98" => [0, "\t/"], "\x99" => [0, "\t3"], "\x9a" => [0, "\t4"], "\x9b" => [0, "\t5"], "\x9c" => [0, "\t6"], "\x9d" => [0, "\t7"], "\x9e" => [0, "\t8"], "\x9f" => [0, "\t9"], "\xa0" => [0, "\t="], "\xa1" => [0, "\tA"], "\xa2" => [0, "\t_"], "\xa3" => [0, "\tb"], "\xa4" => [0, "\td"], "\xa5" => [0, "\tf"], "\xa6" => [0, "\tg"], "\xa7" => [0, "\th"], "\xa8" => [0, "\tl"], "\xa9" => [0, "\tm"], "\xaa" => [0, "\tn"], "\xab" => [0, "\tp"], "\xac" => [0, "\tr"], "\xad" => [0, "\tu"], "\xae" => [100, "\t"], "\xaf" => [110, "\t"], "\xb0" => [111, "\t"], "\xb1" => [115, "\t"], "\xb2" => [116, "\t"], "\xb3" => [118, "\t"], "\xb4" => [119, "\t"], "\xb5" => [122, "\t"], "\xb6" => [123, "\t"], "\xb7" => [125, "\t"], "\xb8" => [126, "\t"], "\xb9" => [129, "\t"], "\xba" => [143, "\t"], "\xbb" => [148, "\t"], "\xbc" => [151, "\t"], "\xbd" => [153, "\t"], "\xbe" => [83, "\t"], "\xbf" => [10, "\t"], "\xc0" => [77, "\x8e0"], "\xc1" => [18, "\x8e0"], "\xc2" => [77, "\x8e1"], "\xc3" => [18, "\x8e1"], "\xc4" => [77, "\x8e2"], "\xc5" => [18, "\x8e2"], "\xc6" => [77, "\x8ea"], "\xc7" => [18, "\x8ea"], "\xc8" => [77, "\x8ec"], "\xc9" => [18, "\x8ec"], "\xca" => [77, "\x8ee"], "\xcb" => [18, "\x8ee"], "\xcc" => [77, "\x8ei"], "\xcd" => [18, "\x8ei"], "\xce" => [77, "\x8eo"], "\xcf" => [18, "\x8eo"], "\xd0" => [77, "\x8es"], "\xd1" => [18, "\x8es"], "\xd2" => [77, "\x8et"], "\xd3" => [18, "\x8et"], "\xd4" => [0, "\x8e "], "\xd5" => [0, "\x8e%"], "\xd6" => [0, "\x8e-"], "\xd7" => [0, "\x8e."], "\xd8" => [0, "\x8e/"], "\xd9" => [0, "\x8e3"], "\xda" => [0, "\x8e4"], "\xdb" => [0, "\x8e5"], "\xdc" => [0, "\x8e6"], "\xdd" => [0, "\x8e7"], "\xde" => [0, "\x8e8"], "\xdf" => [0, "\x8e9"], "\xe0" => [0, "\x8e="], "\xe1" => [0, "\x8eA"], "\xe2" => [0, "\x8e_"], "\xe3" => [0, "\x8eb"], "\xe4" => [0, "\x8ed"], "\xe5" => [0, "\x8ef"], "\xe6" => [0, "\x8eg"], "\xe7" => [0, "\x8eh"], "\xe8" => [0, "\x8el"], "\xe9" => [0, "\x8em"], "\xea" => [0, "\x8en"], "\xeb" => [0, "\x8ep"], "\xec" => [0, "\x8er"], "\xed" => [0, "\x8eu"], "\xee" => [100, "\x8e"], "\xef" => [110, "\x8e"], "\xf0" => [111, "\x8e"], "\xf1" => [115, "\x8e"], "\xf2" => [116, "\x8e"], "\xf3" => [118, "\x8e"], "\xf4" => [119, "\x8e"], "\xf5" => [122, "\x8e"], "\xf6" => [123, "\x8e"], "\xf7" => [125, "\x8e"], "\xf8" => [126, "\x8e"], "\xf9" => [129, "\x8e"], "\xfa" => [143, "\x8e"], "\xfb" => [148, "\x8e"], "\xfc" => [151, "\x8e"], "\xfd" => [153, "\x8e"], "\xfe" => [83, "\x8e"], "\xff" => [10, "\x8e"]], ["\x00" => [77, "\xef0"], "\x01" => [18, "\xef0"], "\x02" => [77, "\xef1"], "\x03" => [18, "\xef1"], "\x04" => [77, "\xef2"], "\x05" => [18, "\xef2"], "\x06" => [77, "\xefa"], "\x07" => [18, "\xefa"], "\x08" => [77, "\xefc"], "\t" => [18, "\xefc"], "\n" => [77, "\xefe"], "\v" => [18, "\xefe"], "\f" => [77, "\xefi"], "\r" => [18, "\xefi"], "\x0e" => [77, "\xefo"], "\x0f" => [18, "\xefo"], "\x10" => [77, "\xefs"], "\x11" => [18, "\xefs"], "\x12" => [77, "\xeft"], "\x13" => [18, "\xeft"], "\x14" => [0, "\xef "], "\x15" => [0, "\xef%"], "\x16" => [0, "\xef-"], "\x17" => [0, "\xef."], "\x18" => [0, "\xef/"], "\x19" => [0, "\xef3"], "\x1a" => [0, "\xef4"], "\x1b" => [0, "\xef5"], "\x1c" => [0, "\xef6"], "\x1d" => [0, "\xef7"], "\x1e" => [0, "\xef8"], "\x1f" => [0, "\xef9"], " " => [0, "\xef="], "!" => [0, "\xefA"], "\"" => [0, "\xef_"], "#" => [0, "\xefb"], "\$" => [0, "\xefd"], "%" => [0, "\xeff"], "&" => [0, "\xefg"], "'" => [0, "\xefh"], "(" => [0, "\xefl"], ")" => [0, "\xefm"], "*" => [0, "\xefn"], "+" => [0, "\xefp"], "," => [0, "\xefr"], "-" => [0, "\xefu"], "." => [100, "\xef"], "/" => [110, "\xef"], [111, "\xef"], [115, "\xef"], [116, "\xef"], [118, "\xef"], [119, "\xef"], [122, "\xef"], [123, "\xef"], [125, "\xef"], [126, "\xef"], [129, "\xef"], ":" => [143, "\xef"], ";" => [148, "\xef"], "<" => [151, "\xef"], "=" => [153, "\xef"], ">" => [83, "\xef"], "?" => [10, "\xef"], "@" => [0, "\t0"], "A" => [0, "\t1"], "B" => [0, "\t2"], "C" => [0, "\ta"], "D" => [0, "\tc"], "E" => [0, "\te"], "F" => [0, "\ti"], "G" => [0, "\to"], "H" => [0, "\ts"], "I" => [0, "\tt"], "J" => [73, "\t"], "K" => [88, "\t"], "L" => [89, "\t"], "M" => [96, "\t"], "N" => [97, "\t"], "O" => [99, "\t"], "P" => [106, "\t"], "Q" => [136, "\t"], "R" => [139, "\t"], "S" => [141, "\t"], "T" => [145, "\t"], "U" => [147, "\t"], "V" => [149, "\t"], "W" => [101, "\t"], "X" => [112, "\t"], "Y" => [117, "\t"], "Z" => [120, "\t"], "[" => [124, "\t"], "\\" => [127, "\t"], "]" => [144, "\t"], "^" => [152, "\t"], "_" => [11, "\t"], "`" => [0, "\x8e0"], "a" => [0, "\x8e1"], "b" => [0, "\x8e2"], "c" => [0, "\x8ea"], "d" => [0, "\x8ec"], "e" => [0, "\x8ee"], "f" => [0, "\x8ei"], "g" => [0, "\x8eo"], "h" => [0, "\x8es"], "i" => [0, "\x8et"], "j" => [73, "\x8e"], "k" => [88, "\x8e"], "l" => [89, "\x8e"], "m" => [96, "\x8e"], "n" => [97, "\x8e"], "o" => [99, "\x8e"], "p" => [106, "\x8e"], "q" => [136, "\x8e"], "r" => [139, "\x8e"], "s" => [141, "\x8e"], "t" => [145, "\x8e"], "u" => [147, "\x8e"], "v" => [149, "\x8e"], "w" => [101, "\x8e"], "x" => [112, "\x8e"], "y" => [117, "\x8e"], "z" => [120, "\x8e"], "{" => [124, "\x8e"], "|" => [127, "\x8e"], "}" => [144, "\x8e"], "~" => [152, "\x8e"], "" => [11, "\x8e"], "\x80" => [0, "\x900"], "\x81" => [0, "\x901"], "\x82" => [0, "\x902"], "\x83" => [0, "\x90a"], "\x84" => [0, "\x90c"], "\x85" => [0, "\x90e"], "\x86" => [0, "\x90i"], "\x87" => [0, "\x90o"], "\x88" => [0, "\x90s"], "\x89" => [0, "\x90t"], "\x8a" => [73, "\x90"], "\x8b" => [88, "\x90"], "\x8c" => [89, "\x90"], "\x8d" => [96, "\x90"], "\x8e" => [97, "\x90"], "\x8f" => [99, "\x90"], "\x90" => [106, "\x90"], "\x91" => [136, "\x90"], "\x92" => [139, "\x90"], "\x93" => [141, "\x90"], "\x94" => [145, "\x90"], "\x95" => [147, "\x90"], "\x96" => [149, "\x90"], "\x97" => [101, "\x90"], "\x98" => [112, "\x90"], "\x99" => [117, "\x90"], "\x9a" => [120, "\x90"], "\x9b" => [124, "\x90"], "\x9c" => [127, "\x90"], "\x9d" => [144, "\x90"], "\x9e" => [152, "\x90"], "\x9f" => [11, "\x90"], "\xa0" => [0, "\x910"], "\xa1" => [0, "\x911"], "\xa2" => [0, "\x912"], "\xa3" => [0, "\x91a"], "\xa4" => [0, "\x91c"], "\xa5" => [0, "\x91e"], "\xa6" => [0, "\x91i"], "\xa7" => [0, "\x91o"], "\xa8" => [0, "\x91s"], "\xa9" => [0, "\x91t"], "\xaa" => [73, "\x91"], "\xab" => [88, "\x91"], "\xac" => [89, "\x91"], "\xad" => [96, "\x91"], "\xae" => [97, "\x91"], "\xaf" => [99, "\x91"], "\xb0" => [106, "\x91"], "\xb1" => [136, "\x91"], "\xb2" => [139, "\x91"], "\xb3" => [141, "\x91"], "\xb4" => [145, "\x91"], "\xb5" => [147, "\x91"], "\xb6" => [149, "\x91"], "\xb7" => [101, "\x91"], "\xb8" => [112, "\x91"], "\xb9" => [117, "\x91"], "\xba" => [120, "\x91"], "\xbb" => [124, "\x91"], "\xbc" => [127, "\x91"], "\xbd" => [144, "\x91"], "\xbe" => [152, "\x91"], "\xbf" => [11, "\x91"], "\xc0" => [0, "\x940"], "\xc1" => [0, "\x941"], "\xc2" => [0, "\x942"], "\xc3" => [0, "\x94a"], "\xc4" => [0, "\x94c"], "\xc5" => [0, "\x94e"], "\xc6" => [0, "\x94i"], "\xc7" => [0, "\x94o"], "\xc8" => [0, "\x94s"], "\xc9" => [0, "\x94t"], "\xca" => [73, "\x94"], "\xcb" => [88, "\x94"], "\xcc" => [89, "\x94"], "\xcd" => [96, "\x94"], "\xce" => [97, "\x94"], "\xcf" => [99, "\x94"], "\xd0" => [106, "\x94"], "\xd1" => [136, "\x94"], "\xd2" => [139, "\x94"], "\xd3" => [141, "\x94"], "\xd4" => [145, "\x94"], "\xd5" => [147, "\x94"], "\xd6" => [149, "\x94"], "\xd7" => [101, "\x94"], "\xd8" => [112, "\x94"], "\xd9" => [117, "\x94"], "\xda" => [120, "\x94"], "\xdb" => [124, "\x94"], "\xdc" => [127, "\x94"], "\xdd" => [144, "\x94"], "\xde" => [152, "\x94"], "\xdf" => [11, "\x94"], "\xe0" => [0, "\x9f0"], "\xe1" => [0, "\x9f1"], "\xe2" => [0, "\x9f2"], "\xe3" => [0, "\x9fa"], "\xe4" => [0, "\x9fc"], "\xe5" => [0, "\x9fe"], "\xe6" => [0, "\x9fi"], "\xe7" => [0, "\x9fo"], "\xe8" => [0, "\x9fs"], "\xe9" => [0, "\x9ft"], "\xea" => [73, "\x9f"], "\xeb" => [88, "\x9f"], "\xec" => [89, "\x9f"], "\xed" => [96, "\x9f"], "\xee" => [97, "\x9f"], "\xef" => [99, "\x9f"], "\xf0" => [106, "\x9f"], "\xf1" => [136, "\x9f"], "\xf2" => [139, "\x9f"], "\xf3" => [141, "\x9f"], "\xf4" => [145, "\x9f"], "\xf5" => [147, "\x9f"], "\xf6" => [149, "\x9f"], "\xf7" => [101, "\x9f"], "\xf8" => [112, "\x9f"], "\xf9" => [117, "\x9f"], "\xfa" => [120, "\x9f"], "\xfb" => [124, "\x9f"], "\xfc" => [127, "\x9f"], "\xfd" => [144, "\x9f"], "\xfe" => [152, "\x9f"], "\xff" => [11, "\x9f"]], ["\x00" => [0, "\xbc0"], "\x01" => [0, "\xbc1"], "\x02" => [0, "\xbc2"], "\x03" => [0, "\xbca"], "\x04" => [0, "\xbcc"], "\x05" => [0, "\xbce"], "\x06" => [0, "\xbci"], "\x07" => [0, "\xbco"], "\x08" => [0, "\xbcs"], "\t" => [0, "\xbct"], "\n" => [73, "\xbc"], "\v" => [88, "\xbc"], "\f" => [89, "\xbc"], "\r" => [96, "\xbc"], "\x0e" => [97, "\xbc"], "\x0f" => [99, "\xbc"], "\x10" => [106, "\xbc"], "\x11" => [136, "\xbc"], "\x12" => [139, "\xbc"], "\x13" => [141, "\xbc"], "\x14" => [145, "\xbc"], "\x15" => [147, "\xbc"], "\x16" => [149, "\xbc"], "\x17" => [101, "\xbc"], "\x18" => [112, "\xbc"], "\x19" => [117, "\xbc"], "\x1a" => [120, "\xbc"], "\x1b" => [124, "\xbc"], "\x1c" => [127, "\xbc"], "\x1d" => [144, "\xbc"], "\x1e" => [152, "\xbc"], "\x1f" => [11, "\xbc"], " " => [0, "\xbf0"], "!" => [0, "\xbf1"], "\"" => [0, "\xbf2"], "#" => [0, "\xbfa"], "\$" => [0, "\xbfc"], "%" => [0, "\xbfe"], "&" => [0, "\xbfi"], "'" => [0, "\xbfo"], "(" => [0, "\xbfs"], ")" => [0, "\xbft"], "*" => [73, "\xbf"], "+" => [88, "\xbf"], "," => [89, "\xbf"], "-" => [96, "\xbf"], "." => [97, "\xbf"], "/" => [99, "\xbf"], [106, "\xbf"], [136, "\xbf"], [139, "\xbf"], [141, "\xbf"], [145, "\xbf"], [147, "\xbf"], [149, "\xbf"], [101, "\xbf"], [112, "\xbf"], [117, "\xbf"], ":" => [120, "\xbf"], ";" => [124, "\xbf"], "<" => [127, "\xbf"], "=" => [144, "\xbf"], ">" => [152, "\xbf"], "?" => [11, "\xbf"], "@" => [0, "\xc50"], "A" => [0, "\xc51"], "B" => [0, "\xc52"], "C" => [0, "\xc5a"], "D" => [0, "\xc5c"], "E" => [0, "\xc5e"], "F" => [0, "\xc5i"], "G" => [0, "\xc5o"], "H" => [0, "\xc5s"], "I" => [0, "\xc5t"], "J" => [73, "\xc5"], "K" => [88, "\xc5"], "L" => [89, "\xc5"], "M" => [96, "\xc5"], "N" => [97, "\xc5"], "O" => [99, "\xc5"], "P" => [106, "\xc5"], "Q" => [136, "\xc5"], "R" => [139, "\xc5"], "S" => [141, "\xc5"], "T" => [145, "\xc5"], "U" => [147, "\xc5"], "V" => [149, "\xc5"], "W" => [101, "\xc5"], "X" => [112, "\xc5"], "Y" => [117, "\xc5"], "Z" => [120, "\xc5"], "[" => [124, "\xc5"], "\\" => [127, "\xc5"], "]" => [144, "\xc5"], "^" => [152, "\xc5"], "_" => [11, "\xc5"], "`" => [0, "\xe70"], "a" => [0, "\xe71"], "b" => [0, "\xe72"], "c" => [0, "\xe7a"], "d" => [0, "\xe7c"], "e" => [0, "\xe7e"], "f" => [0, "\xe7i"], "g" => [0, "\xe7o"], "h" => [0, "\xe7s"], "i" => [0, "\xe7t"], "j" => [73, "\xe7"], "k" => [88, "\xe7"], "l" => [89, "\xe7"], "m" => [96, "\xe7"], "n" => [97, "\xe7"], "o" => [99, "\xe7"], "p" => [106, "\xe7"], "q" => [136, "\xe7"], "r" => [139, "\xe7"], "s" => [141, "\xe7"], "t" => [145, "\xe7"], "u" => [147, "\xe7"], "v" => [149, "\xe7"], "w" => [101, "\xe7"], "x" => [112, "\xe7"], "y" => [117, "\xe7"], "z" => [120, "\xe7"], "{" => [124, "\xe7"], "|" => [127, "\xe7"], "}" => [144, "\xe7"], "~" => [152, "\xe7"], "" => [11, "\xe7"], "\x80" => [0, "\xef0"], "\x81" => [0, "\xef1"], "\x82" => [0, "\xef2"], "\x83" => [0, "\xefa"], "\x84" => [0, "\xefc"], "\x85" => [0, "\xefe"], "\x86" => [0, "\xefi"], "\x87" => [0, "\xefo"], "\x88" => [0, "\xefs"], "\x89" => [0, "\xeft"], "\x8a" => [73, "\xef"], "\x8b" => [88, "\xef"], "\x8c" => [89, "\xef"], "\x8d" => [96, "\xef"], "\x8e" => [97, "\xef"], "\x8f" => [99, "\xef"], "\x90" => [106, "\xef"], "\x91" => [136, "\xef"], "\x92" => [139, "\xef"], "\x93" => [141, "\xef"], "\x94" => [145, "\xef"], "\x95" => [147, "\xef"], "\x96" => [149, "\xef"], "\x97" => [101, "\xef"], "\x98" => [112, "\xef"], "\x99" => [117, "\xef"], "\x9a" => [120, "\xef"], "\x9b" => [124, "\xef"], "\x9c" => [127, "\xef"], "\x9d" => [144, "\xef"], "\x9e" => [152, "\xef"], "\x9f" => [11, "\xef"], "\xa0" => [92, "\t"], "\xa1" => [95, "\t"], "\xa2" => [137, "\t"], "\xa3" => [142, "\t"], "\xa4" => [150, "\t"], "\xa5" => [74, "\t"], "\xa6" => [90, "\t"], "\xa7" => [98, "\t"], "\xa8" => [107, "\t"], "\xa9" => [140, "\t"], "\xaa" => [146, "\t"], "\xab" => [102, "\t"], "\xac" => [113, "\t"], "\xad" => [121, "\t"], "\xae" => [128, "\t"], "\xaf" => [12, "\t"], "\xb0" => [92, "\x8e"], "\xb1" => [95, "\x8e"], "\xb2" => [137, "\x8e"], "\xb3" => [142, "\x8e"], "\xb4" => [150, "\x8e"], "\xb5" => [74, "\x8e"], "\xb6" => [90, "\x8e"], "\xb7" => [98, "\x8e"], "\xb8" => [107, "\x8e"], "\xb9" => [140, "\x8e"], "\xba" => [146, "\x8e"], "\xbb" => [102, "\x8e"], "\xbc" => [113, "\x8e"], "\xbd" => [121, "\x8e"], "\xbe" => [128, "\x8e"], "\xbf" => [12, "\x8e"], "\xc0" => [92, "\x90"], "\xc1" => [95, "\x90"], "\xc2" => [137, "\x90"], "\xc3" => [142, "\x90"], "\xc4" => [150, "\x90"], "\xc5" => [74, "\x90"], "\xc6" => [90, "\x90"], "\xc7" => [98, "\x90"], "\xc8" => [107, "\x90"], "\xc9" => [140, "\x90"], "\xca" => [146, "\x90"], "\xcb" => [102, "\x90"], "\xcc" => [113, "\x90"], "\xcd" => [121, "\x90"], "\xce" => [128, "\x90"], "\xcf" => [12, "\x90"], "\xd0" => [92, "\x91"], "\xd1" => [95, "\x91"], "\xd2" => [137, "\x91"], "\xd3" => [142, "\x91"], "\xd4" => [150, "\x91"], "\xd5" => [74, "\x91"], "\xd6" => [90, "\x91"], "\xd7" => [98, "\x91"], "\xd8" => [107, "\x91"], "\xd9" => [140, "\x91"], "\xda" => [146, "\x91"], "\xdb" => [102, "\x91"], "\xdc" => [113, "\x91"], "\xdd" => [121, "\x91"], "\xde" => [128, "\x91"], "\xdf" => [12, "\x91"], "\xe0" => [92, "\x94"], "\xe1" => [95, "\x94"], "\xe2" => [137, "\x94"], "\xe3" => [142, "\x94"], "\xe4" => [150, "\x94"], "\xe5" => [74, "\x94"], "\xe6" => [90, "\x94"], "\xe7" => [98, "\x94"], "\xe8" => [107, "\x94"], "\xe9" => [140, "\x94"], "\xea" => [146, "\x94"], "\xeb" => [102, "\x94"], "\xec" => [113, "\x94"], "\xed" => [121, "\x94"], "\xee" => [128, "\x94"], "\xef" => [12, "\x94"], "\xf0" => [92, "\x9f"], "\xf1" => [95, "\x9f"], "\xf2" => [137, "\x9f"], "\xf3" => [142, "\x9f"], "\xf4" => [150, "\x9f"], "\xf5" => [74, "\x9f"], "\xf6" => [90, "\x9f"], "\xf7" => [98, "\x9f"], "\xf8" => [107, "\x9f"], "\xf9" => [140, "\x9f"], "\xfa" => [146, "\x9f"], "\xfb" => [102, "\x9f"], "\xfc" => [113, "\x9f"], "\xfd" => [121, "\x9f"], "\xfe" => [128, "\x9f"], "\xff" => [12, "\x9f"]], ["\x00" => [92, "\x13"], "\x01" => [95, "\x13"], "\x02" => [137, "\x13"], "\x03" => [142, "\x13"], "\x04" => [150, "\x13"], "\x05" => [74, "\x13"], "\x06" => [90, "\x13"], "\x07" => [98, "\x13"], "\x08" => [107, "\x13"], "\t" => [140, "\x13"], "\n" => [146, "\x13"], "\v" => [102, "\x13"], "\f" => [113, "\x13"], "\r" => [121, "\x13"], "\x0e" => [128, "\x13"], "\x0f" => [12, "\x13"], "\x10" => [92, "\x14"], "\x11" => [95, "\x14"], "\x12" => [137, "\x14"], "\x13" => [142, "\x14"], "\x14" => [150, "\x14"], "\x15" => [74, "\x14"], "\x16" => [90, "\x14"], "\x17" => [98, "\x14"], "\x18" => [107, "\x14"], "\x19" => [140, "\x14"], "\x1a" => [146, "\x14"], "\x1b" => [102, "\x14"], "\x1c" => [113, "\x14"], "\x1d" => [121, "\x14"], "\x1e" => [128, "\x14"], "\x1f" => [12, "\x14"], " " => [92, "\x15"], "!" => [95, "\x15"], "\"" => [137, "\x15"], "#" => [142, "\x15"], "\$" => [150, "\x15"], "%" => [74, "\x15"], "&" => [90, "\x15"], "'" => [98, "\x15"], "(" => [107, "\x15"], ")" => [140, "\x15"], "*" => [146, "\x15"], "+" => [102, "\x15"], "," => [113, "\x15"], "-" => [121, "\x15"], "." => [128, "\x15"], "/" => [12, "\x15"], [92, "\x17"], [95, "\x17"], [137, "\x17"], [142, "\x17"], [150, "\x17"], [74, "\x17"], [90, "\x17"], [98, "\x17"], [107, "\x17"], [140, "\x17"], ":" => [146, "\x17"], ";" => [102, "\x17"], "<" => [113, "\x17"], "=" => [121, "\x17"], ">" => [128, "\x17"], "?" => [12, "\x17"], "@" => [92, "\x18"], "A" => [95, "\x18"], "B" => [137, "\x18"], "C" => [142, "\x18"], "D" => [150, "\x18"], "E" => [74, "\x18"], "F" => [90, "\x18"], "G" => [98, "\x18"], "H" => [107, "\x18"], "I" => [140, "\x18"], "J" => [146, "\x18"], "K" => [102, "\x18"], "L" => [113, "\x18"], "M" => [121, "\x18"], "N" => [128, "\x18"], "O" => [12, "\x18"], "P" => [92, "\x19"], "Q" => [95, "\x19"], "R" => [137, "\x19"], "S" => [142, "\x19"], "T" => [150, "\x19"], "U" => [74, "\x19"], "V" => [90, "\x19"], "W" => [98, "\x19"], "X" => [107, "\x19"], "Y" => [140, "\x19"], "Z" => [146, "\x19"], "[" => [102, "\x19"], "\\" => [113, "\x19"], "]" => [121, "\x19"], "^" => [128, "\x19"], "_" => [12, "\x19"], "`" => [92, "\x1a"], "a" => [95, "\x1a"], "b" => [137, "\x1a"], "c" => [142, "\x1a"], "d" => [150, "\x1a"], "e" => [74, "\x1a"], "f" => [90, "\x1a"], "g" => [98, "\x1a"], "h" => [107, "\x1a"], "i" => [140, "\x1a"], "j" => [146, "\x1a"], "k" => [102, "\x1a"], "l" => [113, "\x1a"], "m" => [121, "\x1a"], "n" => [128, "\x1a"], "o" => [12, "\x1a"], "p" => [92, "\x1b"], "q" => [95, "\x1b"], "r" => [137, "\x1b"], "s" => [142, "\x1b"], "t" => [150, "\x1b"], "u" => [74, "\x1b"], "v" => [90, "\x1b"], "w" => [98, "\x1b"], "x" => [107, "\x1b"], "y" => [140, "\x1b"], "z" => [146, "\x1b"], "{" => [102, "\x1b"], "|" => [113, "\x1b"], "}" => [121, "\x1b"], "~" => [128, "\x1b"], "" => [12, "\x1b"], "\x80" => [92, "\x1c"], "\x81" => [95, "\x1c"], "\x82" => [137, "\x1c"], "\x83" => [142, "\x1c"], "\x84" => [150, "\x1c"], "\x85" => [74, "\x1c"], "\x86" => [90, "\x1c"], "\x87" => [98, "\x1c"], "\x88" => [107, "\x1c"], "\x89" => [140, "\x1c"], "\x8a" => [146, "\x1c"], "\x8b" => [102, "\x1c"], "\x8c" => [113, "\x1c"], "\x8d" => [121, "\x1c"], "\x8e" => [128, "\x1c"], "\x8f" => [12, "\x1c"], "\x90" => [92, "\x1d"], "\x91" => [95, "\x1d"], "\x92" => [137, "\x1d"], "\x93" => [142, "\x1d"], "\x94" => [150, "\x1d"], "\x95" => [74, "\x1d"], "\x96" => [90, "\x1d"], "\x97" => [98, "\x1d"], "\x98" => [107, "\x1d"], "\x99" => [140, "\x1d"], "\x9a" => [146, "\x1d"], "\x9b" => [102, "\x1d"], "\x9c" => [113, "\x1d"], "\x9d" => [121, "\x1d"], "\x9e" => [128, "\x1d"], "\x9f" => [12, "\x1d"], "\xa0" => [92, "\x1e"], "\xa1" => [95, "\x1e"], "\xa2" => [137, "\x1e"], "\xa3" => [142, "\x1e"], "\xa4" => [150, "\x1e"], "\xa5" => [74, "\x1e"], "\xa6" => [90, "\x1e"], "\xa7" => [98, "\x1e"], "\xa8" => [107, "\x1e"], "\xa9" => [140, "\x1e"], "\xaa" => [146, "\x1e"], "\xab" => [102, "\x1e"], "\xac" => [113, "\x1e"], "\xad" => [121, "\x1e"], "\xae" => [128, "\x1e"], "\xaf" => [12, "\x1e"], "\xb0" => [92, "\x1f"], "\xb1" => [95, "\x1f"], "\xb2" => [137, "\x1f"], "\xb3" => [142, "\x1f"], "\xb4" => [150, "\x1f"], "\xb5" => [74, "\x1f"], "\xb6" => [90, "\x1f"], "\xb7" => [98, "\x1f"], "\xb8" => [107, "\x1f"], "\xb9" => [140, "\x1f"], "\xba" => [146, "\x1f"], "\xbb" => [102, "\x1f"], "\xbc" => [113, "\x1f"], "\xbd" => [121, "\x1f"], "\xbe" => [128, "\x1f"], "\xbf" => [12, "\x1f"], "\xc0" => [92, ""], "\xc1" => [95, ""], "\xc2" => [137, ""], "\xc3" => [142, ""], "\xc4" => [150, ""], "\xc5" => [74, ""], "\xc6" => [90, ""], "\xc7" => [98, ""], "\xc8" => [107, ""], "\xc9" => [140, ""], "\xca" => [146, ""], "\xcb" => [102, ""], "\xcc" => [113, ""], "\xcd" => [121, ""], "\xce" => [128, ""], "\xcf" => [12, ""], "\xd0" => [92, "\xdc"], "\xd1" => [95, "\xdc"], "\xd2" => [137, "\xdc"], "\xd3" => [142, "\xdc"], "\xd4" => [150, "\xdc"], "\xd5" => [74, "\xdc"], "\xd6" => [90, "\xdc"], "\xd7" => [98, "\xdc"], "\xd8" => [107, "\xdc"], "\xd9" => [140, "\xdc"], "\xda" => [146, "\xdc"], "\xdb" => [102, "\xdc"], "\xdc" => [113, "\xdc"], "\xdd" => [121, "\xdc"], "\xde" => [128, "\xdc"], "\xdf" => [12, "\xdc"], "\xe0" => [92, "\xf9"], "\xe1" => [95, "\xf9"], "\xe2" => [137, "\xf9"], "\xe3" => [142, "\xf9"], "\xe4" => [150, "\xf9"], "\xe5" => [74, "\xf9"], "\xe6" => [90, "\xf9"], "\xe7" => [98, "\xf9"], "\xe8" => [107, "\xf9"], "\xe9" => [140, "\xf9"], "\xea" => [146, "\xf9"], "\xeb" => [102, "\xf9"], "\xec" => [113, "\xf9"], "\xed" => [121, "\xf9"], "\xee" => [128, "\xf9"], "\xef" => [12, "\xf9"], "\xf0" => [94, "\n"], "\xf1" => [76, "\n"], "\xf2" => [104, "\n"], "\xf3" => [16, "\n"], "\xf4" => [94, "\r"], "\xf5" => [76, "\r"], "\xf6" => [104, "\r"], "\xf7" => [16, "\r"], "\xf8" => [94, "\x16"], "\xf9" => [76, "\x16"], "\xfa" => [104, "\x16"], "\xfb" => [16, "\x16"], "\xfc" => [94, ""], "\xfd" => [76, ""], "\xfe" => [104, ""], "\xff" => [16, ""]], ["\x00" => [94, "\n0"], "\x01" => [76, "\n0"], "\x02" => [104, "\n0"], "\x03" => [16, "\n0"], "\x04" => [94, "\n1"], "\x05" => [76, "\n1"], "\x06" => [104, "\n1"], "\x07" => [16, "\n1"], "\x08" => [94, "\n2"], "\t" => [76, "\n2"], "\n" => [104, "\n2"], "\v" => [16, "\n2"], "\f" => [94, "\na"], "\r" => [76, "\na"], "\x0e" => [104, "\na"], "\x0f" => [16, "\na"], "\x10" => [94, "\nc"], "\x11" => [76, "\nc"], "\x12" => [104, "\nc"], "\x13" => [16, "\nc"], "\x14" => [94, "\ne"], "\x15" => [76, "\ne"], "\x16" => [104, "\ne"], "\x17" => [16, "\ne"], "\x18" => [94, "\ni"], "\x19" => [76, "\ni"], "\x1a" => [104, "\ni"], "\x1b" => [16, "\ni"], "\x1c" => [94, "\no"], "\x1d" => [76, "\no"], "\x1e" => [104, "\no"], "\x1f" => [16, "\no"], " " => [94, "\ns"], "!" => [76, "\ns"], "\"" => [104, "\ns"], "#" => [16, "\ns"], "\$" => [94, "\nt"], "%" => [76, "\nt"], "&" => [104, "\nt"], "'" => [16, "\nt"], "(" => [77, "\n "], ")" => [18, "\n "], "*" => [77, "\n%"], "+" => [18, "\n%"], "," => [77, "\n-"], "-" => [18, "\n-"], "." => [77, "\n."], "/" => [18, "\n."], [77, "\n/"], [18, "\n/"], [77, "\n3"], [18, "\n3"], [77, "\n4"], [18, "\n4"], [77, "\n5"], [18, "\n5"], [77, "\n6"], [18, "\n6"], ":" => [77, "\n7"], ";" => [18, "\n7"], "<" => [77, "\n8"], "=" => [18, "\n8"], ">" => [77, "\n9"], "?" => [18, "\n9"], "@" => [77, "\n="], "A" => [18, "\n="], "B" => [77, "\nA"], "C" => [18, "\nA"], "D" => [77, "\n_"], "E" => [18, "\n_"], "F" => [77, "\nb"], "G" => [18, "\nb"], "H" => [77, "\nd"], "I" => [18, "\nd"], "J" => [77, "\nf"], "K" => [18, "\nf"], "L" => [77, "\ng"], "M" => [18, "\ng"], "N" => [77, "\nh"], "O" => [18, "\nh"], "P" => [77, "\nl"], "Q" => [18, "\nl"], "R" => [77, "\nm"], "S" => [18, "\nm"], "T" => [77, "\nn"], "U" => [18, "\nn"], "V" => [77, "\np"], "W" => [18, "\np"], "X" => [77, "\nr"], "Y" => [18, "\nr"], "Z" => [77, "\nu"], "[" => [18, "\nu"], "\\" => [0, "\n:"], "]" => [0, "\nB"], "^" => [0, "\nC"], "_" => [0, "\nD"], "`" => [0, "\nE"], "a" => [0, "\nF"], "b" => [0, "\nG"], "c" => [0, "\nH"], "d" => [0, "\nI"], "e" => [0, "\nJ"], "f" => [0, "\nK"], "g" => [0, "\nL"], "h" => [0, "\nM"], "i" => [0, "\nN"], "j" => [0, "\nO"], "k" => [0, "\nP"], "l" => [0, "\nQ"], "m" => [0, "\nR"], "n" => [0, "\nS"], "o" => [0, "\nT"], "p" => [0, "\nU"], "q" => [0, "\nV"], "r" => [0, "\nW"], "s" => [0, "\nY"], "t" => [0, "\nj"], "u" => [0, "\nk"], "v" => [0, "\nq"], "w" => [0, "\nv"], "x" => [0, "\nw"], "y" => [0, "\nx"], "z" => [0, "\ny"], "{" => [0, "\nz"], "|" => [82, "\n"], "}" => [87, "\n"], "~" => [130, "\n"], "" => [9, "\n"], "\x80" => [94, "\r0"], "\x81" => [76, "\r0"], "\x82" => [104, "\r0"], "\x83" => [16, "\r0"], "\x84" => [94, "\r1"], "\x85" => [76, "\r1"], "\x86" => [104, "\r1"], "\x87" => [16, "\r1"], "\x88" => [94, "\r2"], "\x89" => [76, "\r2"], "\x8a" => [104, "\r2"], "\x8b" => [16, "\r2"], "\x8c" => [94, "\ra"], "\x8d" => [76, "\ra"], "\x8e" => [104, "\ra"], "\x8f" => [16, "\ra"], "\x90" => [94, "\rc"], "\x91" => [76, "\rc"], "\x92" => [104, "\rc"], "\x93" => [16, "\rc"], "\x94" => [94, "\re"], "\x95" => [76, "\re"], "\x96" => [104, "\re"], "\x97" => [16, "\re"], "\x98" => [94, "\ri"], "\x99" => [76, "\ri"], "\x9a" => [104, "\ri"], "\x9b" => [16, "\ri"], "\x9c" => [94, "\ro"], "\x9d" => [76, "\ro"], "\x9e" => [104, "\ro"], "\x9f" => [16, "\ro"], "\xa0" => [94, "\rs"], "\xa1" => [76, "\rs"], "\xa2" => [104, "\rs"], "\xa3" => [16, "\rs"], "\xa4" => [94, "\rt"], "\xa5" => [76, "\rt"], "\xa6" => [104, "\rt"], "\xa7" => [16, "\rt"], "\xa8" => [77, "\r "], "\xa9" => [18, "\r "], "\xaa" => [77, "\r%"], "\xab" => [18, "\r%"], "\xac" => [77, "\r-"], "\xad" => [18, "\r-"], "\xae" => [77, "\r."], "\xaf" => [18, "\r."], "\xb0" => [77, "\r/"], "\xb1" => [18, "\r/"], "\xb2" => [77, "\r3"], "\xb3" => [18, "\r3"], "\xb4" => [77, "\r4"], "\xb5" => [18, "\r4"], "\xb6" => [77, "\r5"], "\xb7" => [18, "\r5"], "\xb8" => [77, "\r6"], "\xb9" => [18, "\r6"], "\xba" => [77, "\r7"], "\xbb" => [18, "\r7"], "\xbc" => [77, "\r8"], "\xbd" => [18, "\r8"], "\xbe" => [77, "\r9"], "\xbf" => [18, "\r9"], "\xc0" => [77, "\r="], "\xc1" => [18, "\r="], "\xc2" => [77, "\rA"], "\xc3" => [18, "\rA"], "\xc4" => [77, "\r_"], "\xc5" => [18, "\r_"], "\xc6" => [77, "\rb"], "\xc7" => [18, "\rb"], "\xc8" => [77, "\rd"], "\xc9" => [18, "\rd"], "\xca" => [77, "\rf"], "\xcb" => [18, "\rf"], "\xcc" => [77, "\rg"], "\xcd" => [18, "\rg"], "\xce" => [77, "\rh"], "\xcf" => [18, "\rh"], "\xd0" => [77, "\rl"], "\xd1" => [18, "\rl"], "\xd2" => [77, "\rm"], "\xd3" => [18, "\rm"], "\xd4" => [77, "\rn"], "\xd5" => [18, "\rn"], "\xd6" => [77, "\rp"], "\xd7" => [18, "\rp"], "\xd8" => [77, "\rr"], "\xd9" => [18, "\rr"], "\xda" => [77, "\ru"], "\xdb" => [18, "\ru"], "\xdc" => [0, "\r:"], "\xdd" => [0, "\rB"], "\xde" => [0, "\rC"], "\xdf" => [0, "\rD"], "\xe0" => [0, "\rE"], "\xe1" => [0, "\rF"], "\xe2" => [0, "\rG"], "\xe3" => [0, "\rH"], "\xe4" => [0, "\rI"], "\xe5" => [0, "\rJ"], "\xe6" => [0, "\rK"], "\xe7" => [0, "\rL"], "\xe8" => [0, "\rM"], "\xe9" => [0, "\rN"], "\xea" => [0, "\rO"], "\xeb" => [0, "\rP"], "\xec" => [0, "\rQ"], "\xed" => [0, "\rR"], "\xee" => [0, "\rS"], "\xef" => [0, "\rT"], "\xf0" => [0, "\rU"], "\xf1" => [0, "\rV"], "\xf2" => [0, "\rW"], "\xf3" => [0, "\rY"], "\xf4" => [0, "\rj"], "\xf5" => [0, "\rk"], "\xf6" => [0, "\rq"], "\xf7" => [0, "\rv"], "\xf8" => [0, "\rw"], "\xf9" => [0, "\rx"], "\xfa" => [0, "\ry"], "\xfb" => [0, "\rz"], "\xfc" => [82, "\r"], "\xfd" => [87, "\r"], "\xfe" => [130, "\r"], "\xff" => [9, "\r"]], ["\x00" => [77, "\n0"], "\x01" => [18, "\n0"], "\x02" => [77, "\n1"], "\x03" => [18, "\n1"], "\x04" => [77, "\n2"], "\x05" => [18, "\n2"], "\x06" => [77, "\na"], "\x07" => [18, "\na"], "\x08" => [77, "\nc"], "\t" => [18, "\nc"], "\n" => [77, "\ne"], "\v" => [18, "\ne"], "\f" => [77, "\ni"], "\r" => [18, "\ni"], "\x0e" => [77, "\no"], "\x0f" => [18, "\no"], "\x10" => [77, "\ns"], "\x11" => [18, "\ns"], "\x12" => [77, "\nt"], "\x13" => [18, "\nt"], "\x14" => [0, "\n "], "\x15" => [0, "\n%"], "\x16" => [0, "\n-"], "\x17" => [0, "\n."], "\x18" => [0, "\n/"], "\x19" => [0, "\n3"], "\x1a" => [0, "\n4"], "\x1b" => [0, "\n5"], "\x1c" => [0, "\n6"], "\x1d" => [0, "\n7"], "\x1e" => [0, "\n8"], "\x1f" => [0, "\n9"], " " => [0, "\n="], "!" => [0, "\nA"], "\"" => [0, "\n_"], "#" => [0, "\nb"], "\$" => [0, "\nd"], "%" => [0, "\nf"], "&" => [0, "\ng"], "'" => [0, "\nh"], "(" => [0, "\nl"], ")" => [0, "\nm"], "*" => [0, "\nn"], "+" => [0, "\np"], "," => [0, "\nr"], "-" => [0, "\nu"], "." => [100, "\n"], "/" => [110, "\n"], [111, "\n"], [115, "\n"], [116, "\n"], [118, "\n"], [119, "\n"], [122, "\n"], [123, "\n"], [125, "\n"], [126, "\n"], [129, "\n"], ":" => [143, "\n"], ";" => [148, "\n"], "<" => [151, "\n"], "=" => [153, "\n"], ">" => [83, "\n"], "?" => [10, "\n"], "@" => [77, "\r0"], "A" => [18, "\r0"], "B" => [77, "\r1"], "C" => [18, "\r1"], "D" => [77, "\r2"], "E" => [18, "\r2"], "F" => [77, "\ra"], "G" => [18, "\ra"], "H" => [77, "\rc"], "I" => [18, "\rc"], "J" => [77, "\re"], "K" => [18, "\re"], "L" => [77, "\ri"], "M" => [18, "\ri"], "N" => [77, "\ro"], "O" => [18, "\ro"], "P" => [77, "\rs"], "Q" => [18, "\rs"], "R" => [77, "\rt"], "S" => [18, "\rt"], "T" => [0, "\r "], "U" => [0, "\r%"], "V" => [0, "\r-"], "W" => [0, "\r."], "X" => [0, "\r/"], "Y" => [0, "\r3"], "Z" => [0, "\r4"], "[" => [0, "\r5"], "\\" => [0, "\r6"], "]" => [0, "\r7"], "^" => [0, "\r8"], "_" => [0, "\r9"], "`" => [0, "\r="], "a" => [0, "\rA"], "b" => [0, "\r_"], "c" => [0, "\rb"], "d" => [0, "\rd"], "e" => [0, "\rf"], "f" => [0, "\rg"], "g" => [0, "\rh"], "h" => [0, "\rl"], "i" => [0, "\rm"], "j" => [0, "\rn"], "k" => [0, "\rp"], "l" => [0, "\rr"], "m" => [0, "\ru"], "n" => [100, "\r"], "o" => [110, "\r"], "p" => [111, "\r"], "q" => [115, "\r"], "r" => [116, "\r"], "s" => [118, "\r"], "t" => [119, "\r"], "u" => [122, "\r"], "v" => [123, "\r"], "w" => [125, "\r"], "x" => [126, "\r"], "y" => [129, "\r"], "z" => [143, "\r"], "{" => [148, "\r"], "|" => [151, "\r"], "}" => [153, "\r"], "~" => [83, "\r"], "" => [10, "\r"], "\x80" => [77, "\x160"], "\x81" => [18, "\x160"], "\x82" => [77, "\x161"], "\x83" => [18, "\x161"], "\x84" => [77, "\x162"], "\x85" => [18, "\x162"], "\x86" => [77, "\x16a"], "\x87" => [18, "\x16a"], "\x88" => [77, "\x16c"], "\x89" => [18, "\x16c"], "\x8a" => [77, "\x16e"], "\x8b" => [18, "\x16e"], "\x8c" => [77, "\x16i"], "\x8d" => [18, "\x16i"], "\x8e" => [77, "\x16o"], "\x8f" => [18, "\x16o"], "\x90" => [77, "\x16s"], "\x91" => [18, "\x16s"], "\x92" => [77, "\x16t"], "\x93" => [18, "\x16t"], "\x94" => [0, "\x16 "], "\x95" => [0, "\x16%"], "\x96" => [0, "\x16-"], "\x97" => [0, "\x16."], "\x98" => [0, "\x16/"], "\x99" => [0, "\x163"], "\x9a" => [0, "\x164"], "\x9b" => [0, "\x165"], "\x9c" => [0, "\x166"], "\x9d" => [0, "\x167"], "\x9e" => [0, "\x168"], "\x9f" => [0, "\x169"], "\xa0" => [0, "\x16="], "\xa1" => [0, "\x16A"], "\xa2" => [0, "\x16_"], "\xa3" => [0, "\x16b"], "\xa4" => [0, "\x16d"], "\xa5" => [0, "\x16f"], "\xa6" => [0, "\x16g"], "\xa7" => [0, "\x16h"], "\xa8" => [0, "\x16l"], "\xa9" => [0, "\x16m"], "\xaa" => [0, "\x16n"], "\xab" => [0, "\x16p"], "\xac" => [0, "\x16r"], "\xad" => [0, "\x16u"], "\xae" => [100, "\x16"], "\xaf" => [110, "\x16"], "\xb0" => [111, "\x16"], "\xb1" => [115, "\x16"], "\xb2" => [116, "\x16"], "\xb3" => [118, "\x16"], "\xb4" => [119, "\x16"], "\xb5" => [122, "\x16"], "\xb6" => [123, "\x16"], "\xb7" => [125, "\x16"], "\xb8" => [126, "\x16"], "\xb9" => [129, "\x16"], "\xba" => [143, "\x16"], "\xbb" => [148, "\x16"], "\xbc" => [151, "\x16"], "\xbd" => [153, "\x16"], "\xbe" => [83, "\x16"], "\xbf" => [10, "\x16"], "\xc0" => [77, ""], "\xc1" => [18, ""], "\xc2" => [77, ""], "\xc3" => [18, ""], "\xc4" => [77, ""], "\xc5" => [18, ""], "\xc6" => [77, ""], "\xc7" => [18, ""], "\xc8" => [77, ""], "\xc9" => [18, ""], "\xca" => [77, ""], "\xcb" => [18, ""], "\xcc" => [77, ""], "\xcd" => [18, ""], "\xce" => [77, ""], "\xcf" => [18, ""], "\xd0" => [77, ""], "\xd1" => [18, ""], "\xd2" => [77, ""], "\xd3" => [18, ""], "\xd4" => [0, ""], "\xd5" => [0, ""], "\xd6" => [0, ""], "\xd7" => [0, ""], "\xd8" => [0, ""], "\xd9" => [0, ""], "\xda" => [0, ""], "\xdb" => [0, ""], "\xdc" => [0, ""], "\xdd" => [0, ""], "\xde" => [0, ""], "\xdf" => [0, ""], "\xe0" => [0, ""], "\xe1" => [0, ""], "\xe2" => [0, ""], "\xe3" => [0, ""], "\xe4" => [0, ""], "\xe5" => [0, ""], "\xe6" => [0, ""], "\xe7" => [0, ""], "\xe8" => [0, ""], "\xe9" => [0, ""], "\xea" => [0, ""], "\xeb" => [0, ""], "\xec" => [0, ""], "\xed" => [0, ""], "\xee" => [100, ""], "\xef" => [110, ""], "\xf0" => [111, ""], "\xf1" => [115, ""], "\xf2" => [116, ""], "\xf3" => [118, ""], "\xf4" => [119, ""], "\xf5" => [122, ""], "\xf6" => [123, ""], "\xf7" => [125, ""], "\xf8" => [126, ""], "\xf9" => [129, ""], "\xfa" => [143, ""], "\xfb" => [148, ""], "\xfc" => [151, ""], "\xfd" => [153, ""], "\xfe" => [83, ""], "\xff" => [10, ""]], ["\x00" => [94, "\xf90"], "\x01" => [76, "\xf90"], "\x02" => [104, "\xf90"], "\x03" => [16, "\xf90"], "\x04" => [94, "\xf91"], "\x05" => [76, "\xf91"], "\x06" => [104, "\xf91"], "\x07" => [16, "\xf91"], "\x08" => [94, "\xf92"], "\t" => [76, "\xf92"], "\n" => [104, "\xf92"], "\v" => [16, "\xf92"], "\f" => [94, "\xf9a"], "\r" => [76, "\xf9a"], "\x0e" => [104, "\xf9a"], "\x0f" => [16, "\xf9a"], "\x10" => [94, "\xf9c"], "\x11" => [76, "\xf9c"], "\x12" => [104, "\xf9c"], "\x13" => [16, "\xf9c"], "\x14" => [94, "\xf9e"], "\x15" => [76, "\xf9e"], "\x16" => [104, "\xf9e"], "\x17" => [16, "\xf9e"], "\x18" => [94, "\xf9i"], "\x19" => [76, "\xf9i"], "\x1a" => [104, "\xf9i"], "\x1b" => [16, "\xf9i"], "\x1c" => [94, "\xf9o"], "\x1d" => [76, "\xf9o"], "\x1e" => [104, "\xf9o"], "\x1f" => [16, "\xf9o"], " " => [94, "\xf9s"], "!" => [76, "\xf9s"], "\"" => [104, "\xf9s"], "#" => [16, "\xf9s"], "\$" => [94, "\xf9t"], "%" => [76, "\xf9t"], "&" => [104, "\xf9t"], "'" => [16, "\xf9t"], "(" => [77, "\xf9 "], ")" => [18, "\xf9 "], "*" => [77, "\xf9%"], "+" => [18, "\xf9%"], "," => [77, "\xf9-"], "-" => [18, "\xf9-"], "." => [77, "\xf9."], "/" => [18, "\xf9."], [77, "\xf9/"], [18, "\xf9/"], [77, "\xf93"], [18, "\xf93"], [77, "\xf94"], [18, "\xf94"], [77, "\xf95"], [18, "\xf95"], [77, "\xf96"], [18, "\xf96"], ":" => [77, "\xf97"], ";" => [18, "\xf97"], "<" => [77, "\xf98"], "=" => [18, "\xf98"], ">" => [77, "\xf99"], "?" => [18, "\xf99"], "@" => [77, "\xf9="], "A" => [18, "\xf9="], "B" => [77, "\xf9A"], "C" => [18, "\xf9A"], "D" => [77, "\xf9_"], "E" => [18, "\xf9_"], "F" => [77, "\xf9b"], "G" => [18, "\xf9b"], "H" => [77, "\xf9d"], "I" => [18, "\xf9d"], "J" => [77, "\xf9f"], "K" => [18, "\xf9f"], "L" => [77, "\xf9g"], "M" => [18, "\xf9g"], "N" => [77, "\xf9h"], "O" => [18, "\xf9h"], "P" => [77, "\xf9l"], "Q" => [18, "\xf9l"], "R" => [77, "\xf9m"], "S" => [18, "\xf9m"], "T" => [77, "\xf9n"], "U" => [18, "\xf9n"], "V" => [77, "\xf9p"], "W" => [18, "\xf9p"], "X" => [77, "\xf9r"], "Y" => [18, "\xf9r"], "Z" => [77, "\xf9u"], "[" => [18, "\xf9u"], "\\" => [0, "\xf9:"], "]" => [0, "\xf9B"], "^" => [0, "\xf9C"], "_" => [0, "\xf9D"], "`" => [0, "\xf9E"], "a" => [0, "\xf9F"], "b" => [0, "\xf9G"], "c" => [0, "\xf9H"], "d" => [0, "\xf9I"], "e" => [0, "\xf9J"], "f" => [0, "\xf9K"], "g" => [0, "\xf9L"], "h" => [0, "\xf9M"], "i" => [0, "\xf9N"], "j" => [0, "\xf9O"], "k" => [0, "\xf9P"], "l" => [0, "\xf9Q"], "m" => [0, "\xf9R"], "n" => [0, "\xf9S"], "o" => [0, "\xf9T"], "p" => [0, "\xf9U"], "q" => [0, "\xf9V"], "r" => [0, "\xf9W"], "s" => [0, "\xf9Y"], "t" => [0, "\xf9j"], "u" => [0, "\xf9k"], "v" => [0, "\xf9q"], "w" => [0, "\xf9v"], "x" => [0, "\xf9w"], "y" => [0, "\xf9x"], "z" => [0, "\xf9y"], "{" => [0, "\xf9z"], "|" => [82, "\xf9"], "}" => [87, "\xf9"], "~" => [130, "\xf9"], "" => [9, "\xf9"], "\x80" => [0, "\n0"], "\x81" => [0, "\n1"], "\x82" => [0, "\n2"], "\x83" => [0, "\na"], "\x84" => [0, "\nc"], "\x85" => [0, "\ne"], "\x86" => [0, "\ni"], "\x87" => [0, "\no"], "\x88" => [0, "\ns"], "\x89" => [0, "\nt"], "\x8a" => [73, "\n"], "\x8b" => [88, "\n"], "\x8c" => [89, "\n"], "\x8d" => [96, "\n"], "\x8e" => [97, "\n"], "\x8f" => [99, "\n"], "\x90" => [106, "\n"], "\x91" => [136, "\n"], "\x92" => [139, "\n"], "\x93" => [141, "\n"], "\x94" => [145, "\n"], "\x95" => [147, "\n"], "\x96" => [149, "\n"], "\x97" => [101, "\n"], "\x98" => [112, "\n"], "\x99" => [117, "\n"], "\x9a" => [120, "\n"], "\x9b" => [124, "\n"], "\x9c" => [127, "\n"], "\x9d" => [144, "\n"], "\x9e" => [152, "\n"], "\x9f" => [11, "\n"], "\xa0" => [0, "\r0"], "\xa1" => [0, "\r1"], "\xa2" => [0, "\r2"], "\xa3" => [0, "\ra"], "\xa4" => [0, "\rc"], "\xa5" => [0, "\re"], "\xa6" => [0, "\ri"], "\xa7" => [0, "\ro"], "\xa8" => [0, "\rs"], "\xa9" => [0, "\rt"], "\xaa" => [73, "\r"], "\xab" => [88, "\r"], "\xac" => [89, "\r"], "\xad" => [96, "\r"], "\xae" => [97, "\r"], "\xaf" => [99, "\r"], "\xb0" => [106, "\r"], "\xb1" => [136, "\r"], "\xb2" => [139, "\r"], "\xb3" => [141, "\r"], "\xb4" => [145, "\r"], "\xb5" => [147, "\r"], "\xb6" => [149, "\r"], "\xb7" => [101, "\r"], "\xb8" => [112, "\r"], "\xb9" => [117, "\r"], "\xba" => [120, "\r"], "\xbb" => [124, "\r"], "\xbc" => [127, "\r"], "\xbd" => [144, "\r"], "\xbe" => [152, "\r"], "\xbf" => [11, "\r"], "\xc0" => [0, "\x160"], "\xc1" => [0, "\x161"], "\xc2" => [0, "\x162"], "\xc3" => [0, "\x16a"], "\xc4" => [0, "\x16c"], "\xc5" => [0, "\x16e"], "\xc6" => [0, "\x16i"], "\xc7" => [0, "\x16o"], "\xc8" => [0, "\x16s"], "\xc9" => [0, "\x16t"], "\xca" => [73, "\x16"], "\xcb" => [88, "\x16"], "\xcc" => [89, "\x16"], "\xcd" => [96, "\x16"], "\xce" => [97, "\x16"], "\xcf" => [99, "\x16"], "\xd0" => [106, "\x16"], "\xd1" => [136, "\x16"], "\xd2" => [139, "\x16"], "\xd3" => [141, "\x16"], "\xd4" => [145, "\x16"], "\xd5" => [147, "\x16"], "\xd6" => [149, "\x16"], "\xd7" => [101, "\x16"], "\xd8" => [112, "\x16"], "\xd9" => [117, "\x16"], "\xda" => [120, "\x16"], "\xdb" => [124, "\x16"], "\xdc" => [127, "\x16"], "\xdd" => [144, "\x16"], "\xde" => [152, "\x16"], "\xdf" => [11, "\x16"], "\xe0" => [0, ""], "\xe1" => [0, ""], "\xe2" => [0, ""], "\xe3" => [0, ""], "\xe4" => [0, ""], "\xe5" => [0, ""], "\xe6" => [0, ""], "\xe7" => [0, ""], "\xe8" => [0, ""], "\xe9" => [0, ""], "\xea" => [73, ""], "\xeb" => [88, ""], "\xec" => [89, ""], "\xed" => [96, ""], "\xee" => [97, ""], "\xef" => [99, ""], "\xf0" => [106, ""], "\xf1" => [136, ""], "\xf2" => [139, ""], "\xf3" => [141, ""], "\xf4" => [145, ""], "\xf5" => [147, ""], "\xf6" => [149, ""], "\xf7" => [101, ""], "\xf8" => [112, ""], "\xf9" => [117, ""], "\xfa" => [120, ""], "\xfb" => [124, ""], "\xfc" => [127, ""], "\xfd" => [144, ""], "\xfe" => [152, ""], "\xff" => [11, ""]], ["\x00" => [77, "0"], "\x01" => [18, "0"], "\x02" => [77, "1"], "\x03" => [18, "1"], "\x04" => [77, "2"], "\x05" => [18, "2"], "\x06" => [77, "a"], "\x07" => [18, "a"], "\x08" => [77, "c"], "\t" => [18, "c"], "\n" => [77, "e"], "\v" => [18, "e"], "\f" => [77, "i"], "\r" => [18, "i"], "\x0e" => [77, "o"], "\x0f" => [18, "o"], "\x10" => [77, "s"], "\x11" => [18, "s"], "\x12" => [77, "t"], "\x13" => [18, "t"], "\x14" => [0, " "], "\x15" => [0, "%"], "\x16" => [0, "-"], "\x17" => [0, "."], "\x18" => [0, "/"], "\x19" => [0, "3"], "\x1a" => [0, "4"], "\x1b" => [0, "5"], "\x1c" => [0, "6"], "\x1d" => [0, "7"], "\x1e" => [0, "8"], "\x1f" => [0, "9"], " " => [0, "="], "!" => [0, "A"], "\"" => [0, "_"], "#" => [0, "b"], "\$" => [0, "d"], "%" => [0, "f"], "&" => [0, "g"], "'" => [0, "h"], "(" => [0, "l"], ")" => [0, "m"], "*" => [0, "n"], "+" => [0, "p"], "," => [0, "r"], "-" => [0, "u"], "." => [100, ""], "/" => [110, ""], [111, ""], [115, ""], [116, ""], [118, ""], [119, ""], [122, ""], [123, ""], [125, ""], [126, ""], [129, ""], ":" => [143, ""], ";" => [148, ""], "<" => [151, ""], "=" => [153, ""], ">" => [83, ""], "?" => [10, ""], "@" => [77, "\xdc0"], "A" => [18, "\xdc0"], "B" => [77, "\xdc1"], "C" => [18, "\xdc1"], "D" => [77, "\xdc2"], "E" => [18, "\xdc2"], "F" => [77, "\xdca"], "G" => [18, "\xdca"], "H" => [77, "\xdcc"], "I" => [18, "\xdcc"], "J" => [77, "\xdce"], "K" => [18, "\xdce"], "L" => [77, "\xdci"], "M" => [18, "\xdci"], "N" => [77, "\xdco"], "O" => [18, "\xdco"], "P" => [77, "\xdcs"], "Q" => [18, "\xdcs"], "R" => [77, "\xdct"], "S" => [18, "\xdct"], "T" => [0, "\xdc "], "U" => [0, "\xdc%"], "V" => [0, "\xdc-"], "W" => [0, "\xdc."], "X" => [0, "\xdc/"], "Y" => [0, "\xdc3"], "Z" => [0, "\xdc4"], "[" => [0, "\xdc5"], "\\" => [0, "\xdc6"], "]" => [0, "\xdc7"], "^" => [0, "\xdc8"], "_" => [0, "\xdc9"], "`" => [0, "\xdc="], "a" => [0, "\xdcA"], "b" => [0, "\xdc_"], "c" => [0, "\xdcb"], "d" => [0, "\xdcd"], "e" => [0, "\xdcf"], "f" => [0, "\xdcg"], "g" => [0, "\xdch"], "h" => [0, "\xdcl"], "i" => [0, "\xdcm"], "j" => [0, "\xdcn"], "k" => [0, "\xdcp"], "l" => [0, "\xdcr"], "m" => [0, "\xdcu"], "n" => [100, "\xdc"], "o" => [110, "\xdc"], "p" => [111, "\xdc"], "q" => [115, "\xdc"], "r" => [116, "\xdc"], "s" => [118, "\xdc"], "t" => [119, "\xdc"], "u" => [122, "\xdc"], "v" => [123, "\xdc"], "w" => [125, "\xdc"], "x" => [126, "\xdc"], "y" => [129, "\xdc"], "z" => [143, "\xdc"], "{" => [148, "\xdc"], "|" => [151, "\xdc"], "}" => [153, "\xdc"], "~" => [83, "\xdc"], "" => [10, "\xdc"], "\x80" => [77, "\xf90"], "\x81" => [18, "\xf90"], "\x82" => [77, "\xf91"], "\x83" => [18, "\xf91"], "\x84" => [77, "\xf92"], "\x85" => [18, "\xf92"], "\x86" => [77, "\xf9a"], "\x87" => [18, "\xf9a"], "\x88" => [77, "\xf9c"], "\x89" => [18, "\xf9c"], "\x8a" => [77, "\xf9e"], "\x8b" => [18, "\xf9e"], "\x8c" => [77, "\xf9i"], "\x8d" => [18, "\xf9i"], "\x8e" => [77, "\xf9o"], "\x8f" => [18, "\xf9o"], "\x90" => [77, "\xf9s"], "\x91" => [18, "\xf9s"], "\x92" => [77, "\xf9t"], "\x93" => [18, "\xf9t"], "\x94" => [0, "\xf9 "], "\x95" => [0, "\xf9%"], "\x96" => [0, "\xf9-"], "\x97" => [0, "\xf9."], "\x98" => [0, "\xf9/"], "\x99" => [0, "\xf93"], "\x9a" => [0, "\xf94"], "\x9b" => [0, "\xf95"], "\x9c" => [0, "\xf96"], "\x9d" => [0, "\xf97"], "\x9e" => [0, "\xf98"], "\x9f" => [0, "\xf99"], "\xa0" => [0, "\xf9="], "\xa1" => [0, "\xf9A"], "\xa2" => [0, "\xf9_"], "\xa3" => [0, "\xf9b"], "\xa4" => [0, "\xf9d"], "\xa5" => [0, "\xf9f"], "\xa6" => [0, "\xf9g"], "\xa7" => [0, "\xf9h"], "\xa8" => [0, "\xf9l"], "\xa9" => [0, "\xf9m"], "\xaa" => [0, "\xf9n"], "\xab" => [0, "\xf9p"], "\xac" => [0, "\xf9r"], "\xad" => [0, "\xf9u"], "\xae" => [100, "\xf9"], "\xaf" => [110, "\xf9"], "\xb0" => [111, "\xf9"], "\xb1" => [115, "\xf9"], "\xb2" => [116, "\xf9"], "\xb3" => [118, "\xf9"], "\xb4" => [119, "\xf9"], "\xb5" => [122, "\xf9"], "\xb6" => [123, "\xf9"], "\xb7" => [125, "\xf9"], "\xb8" => [126, "\xf9"], "\xb9" => [129, "\xf9"], "\xba" => [143, "\xf9"], "\xbb" => [148, "\xf9"], "\xbc" => [151, "\xf9"], "\xbd" => [153, "\xf9"], "\xbe" => [83, "\xf9"], "\xbf" => [10, "\xf9"], "\xc0" => [92, "\n"], "\xc1" => [95, "\n"], "\xc2" => [137, "\n"], "\xc3" => [142, "\n"], "\xc4" => [150, "\n"], "\xc5" => [74, "\n"], "\xc6" => [90, "\n"], "\xc7" => [98, "\n"], "\xc8" => [107, "\n"], "\xc9" => [140, "\n"], "\xca" => [146, "\n"], "\xcb" => [102, "\n"], "\xcc" => [113, "\n"], "\xcd" => [121, "\n"], "\xce" => [128, "\n"], "\xcf" => [12, "\n"], "\xd0" => [92, "\r"], "\xd1" => [95, "\r"], "\xd2" => [137, "\r"], "\xd3" => [142, "\r"], "\xd4" => [150, "\r"], "\xd5" => [74, "\r"], "\xd6" => [90, "\r"], "\xd7" => [98, "\r"], "\xd8" => [107, "\r"], "\xd9" => [140, "\r"], "\xda" => [146, "\r"], "\xdb" => [102, "\r"], "\xdc" => [113, "\r"], "\xdd" => [121, "\r"], "\xde" => [128, "\r"], "\xdf" => [12, "\r"], "\xe0" => [92, "\x16"], "\xe1" => [95, "\x16"], "\xe2" => [137, "\x16"], "\xe3" => [142, "\x16"], "\xe4" => [150, "\x16"], "\xe5" => [74, "\x16"], "\xe6" => [90, "\x16"], "\xe7" => [98, "\x16"], "\xe8" => [107, "\x16"], "\xe9" => [140, "\x16"], "\xea" => [146, "\x16"], "\xeb" => [102, "\x16"], "\xec" => [113, "\x16"], "\xed" => [121, "\x16"], "\xee" => [128, "\x16"], "\xef" => [12, "\x16"], "\xf0" => [92, ""], "\xf1" => [95, ""], "\xf2" => [137, ""], "\xf3" => [142, ""], "\xf4" => [150, ""], "\xf5" => [74, ""], "\xf6" => [90, ""], "\xf7" => [98, ""], "\xf8" => [107, ""], "\xf9" => [140, ""], "\xfa" => [146, ""], "\xfb" => [102, ""], "\xfc" => [113, ""], "\xfd" => [121, ""], "\xfe" => [128, ""], "\xff" => [12, ""]], ["\x00" => [0, "\x1c0"], "\x01" => [0, "\x1c1"], "\x02" => [0, "\x1c2"], "\x03" => [0, "\x1ca"], "\x04" => [0, "\x1cc"], "\x05" => [0, "\x1ce"], "\x06" => [0, "\x1ci"], "\x07" => [0, "\x1co"], "\x08" => [0, "\x1cs"], "\t" => [0, "\x1ct"], "\n" => [73, "\x1c"], "\v" => [88, "\x1c"], "\f" => [89, "\x1c"], "\r" => [96, "\x1c"], "\x0e" => [97, "\x1c"], "\x0f" => [99, "\x1c"], "\x10" => [106, "\x1c"], "\x11" => [136, "\x1c"], "\x12" => [139, "\x1c"], "\x13" => [141, "\x1c"], "\x14" => [145, "\x1c"], "\x15" => [147, "\x1c"], "\x16" => [149, "\x1c"], "\x17" => [101, "\x1c"], "\x18" => [112, "\x1c"], "\x19" => [117, "\x1c"], "\x1a" => [120, "\x1c"], "\x1b" => [124, "\x1c"], "\x1c" => [127, "\x1c"], "\x1d" => [144, "\x1c"], "\x1e" => [152, "\x1c"], "\x1f" => [11, "\x1c"], " " => [0, "\x1d0"], "!" => [0, "\x1d1"], "\"" => [0, "\x1d2"], "#" => [0, "\x1da"], "\$" => [0, "\x1dc"], "%" => [0, "\x1de"], "&" => [0, "\x1di"], "'" => [0, "\x1do"], "(" => [0, "\x1ds"], ")" => [0, "\x1dt"], "*" => [73, "\x1d"], "+" => [88, "\x1d"], "," => [89, "\x1d"], "-" => [96, "\x1d"], "." => [97, "\x1d"], "/" => [99, "\x1d"], [106, "\x1d"], [136, "\x1d"], [139, "\x1d"], [141, "\x1d"], [145, "\x1d"], [147, "\x1d"], [149, "\x1d"], [101, "\x1d"], [112, "\x1d"], [117, "\x1d"], ":" => [120, "\x1d"], ";" => [124, "\x1d"], "<" => [127, "\x1d"], "=" => [144, "\x1d"], ">" => [152, "\x1d"], "?" => [11, "\x1d"], "@" => [0, "\x1e0"], "A" => [0, "\x1e1"], "B" => [0, "\x1e2"], "C" => [0, "\x1ea"], "D" => [0, "\x1ec"], "E" => [0, "\x1ee"], "F" => [0, "\x1ei"], "G" => [0, "\x1eo"], "H" => [0, "\x1es"], "I" => [0, "\x1et"], "J" => [73, "\x1e"], "K" => [88, "\x1e"], "L" => [89, "\x1e"], "M" => [96, "\x1e"], "N" => [97, "\x1e"], "O" => [99, "\x1e"], "P" => [106, "\x1e"], "Q" => [136, "\x1e"], "R" => [139, "\x1e"], "S" => [141, "\x1e"], "T" => [145, "\x1e"], "U" => [147, "\x1e"], "V" => [149, "\x1e"], "W" => [101, "\x1e"], "X" => [112, "\x1e"], "Y" => [117, "\x1e"], "Z" => [120, "\x1e"], "[" => [124, "\x1e"], "\\" => [127, "\x1e"], "]" => [144, "\x1e"], "^" => [152, "\x1e"], "_" => [11, "\x1e"], "`" => [0, "\x1f0"], "a" => [0, "\x1f1"], "b" => [0, "\x1f2"], "c" => [0, "\x1fa"], "d" => [0, "\x1fc"], "e" => [0, "\x1fe"], "f" => [0, "\x1fi"], "g" => [0, "\x1fo"], "h" => [0, "\x1fs"], "i" => [0, "\x1ft"], "j" => [73, "\x1f"], "k" => [88, "\x1f"], "l" => [89, "\x1f"], "m" => [96, "\x1f"], "n" => [97, "\x1f"], "o" => [99, "\x1f"], "p" => [106, "\x1f"], "q" => [136, "\x1f"], "r" => [139, "\x1f"], "s" => [141, "\x1f"], "t" => [145, "\x1f"], "u" => [147, "\x1f"], "v" => [149, "\x1f"], "w" => [101, "\x1f"], "x" => [112, "\x1f"], "y" => [117, "\x1f"], "z" => [120, "\x1f"], "{" => [124, "\x1f"], "|" => [127, "\x1f"], "}" => [144, "\x1f"], "~" => [152, "\x1f"], "" => [11, "\x1f"], "\x80" => [0, "0"], "\x81" => [0, "1"], "\x82" => [0, "2"], "\x83" => [0, "a"], "\x84" => [0, "c"], "\x85" => [0, "e"], "\x86" => [0, "i"], "\x87" => [0, "o"], "\x88" => [0, "s"], "\x89" => [0, "t"], "\x8a" => [73, ""], "\x8b" => [88, ""], "\x8c" => [89, ""], "\x8d" => [96, ""], "\x8e" => [97, ""], "\x8f" => [99, ""], "\x90" => [106, ""], "\x91" => [136, ""], "\x92" => [139, ""], "\x93" => [141, ""], "\x94" => [145, ""], "\x95" => [147, ""], "\x96" => [149, ""], "\x97" => [101, ""], "\x98" => [112, ""], "\x99" => [117, ""], "\x9a" => [120, ""], "\x9b" => [124, ""], "\x9c" => [127, ""], "\x9d" => [144, ""], "\x9e" => [152, ""], "\x9f" => [11, ""], "\xa0" => [0, "\xdc0"], "\xa1" => [0, "\xdc1"], "\xa2" => [0, "\xdc2"], "\xa3" => [0, "\xdca"], "\xa4" => [0, "\xdcc"], "\xa5" => [0, "\xdce"], "\xa6" => [0, "\xdci"], "\xa7" => [0, "\xdco"], "\xa8" => [0, "\xdcs"], "\xa9" => [0, "\xdct"], "\xaa" => [73, "\xdc"], "\xab" => [88, "\xdc"], "\xac" => [89, "\xdc"], "\xad" => [96, "\xdc"], "\xae" => [97, "\xdc"], "\xaf" => [99, "\xdc"], "\xb0" => [106, "\xdc"], "\xb1" => [136, "\xdc"], "\xb2" => [139, "\xdc"], "\xb3" => [141, "\xdc"], "\xb4" => [145, "\xdc"], "\xb5" => [147, "\xdc"], "\xb6" => [149, "\xdc"], "\xb7" => [101, "\xdc"], "\xb8" => [112, "\xdc"], "\xb9" => [117, "\xdc"], "\xba" => [120, "\xdc"], "\xbb" => [124, "\xdc"], "\xbc" => [127, "\xdc"], "\xbd" => [144, "\xdc"], "\xbe" => [152, "\xdc"], "\xbf" => [11, "\xdc"], "\xc0" => [0, "\xf90"], "\xc1" => [0, "\xf91"], "\xc2" => [0, "\xf92"], "\xc3" => [0, "\xf9a"], "\xc4" => [0, "\xf9c"], "\xc5" => [0, "\xf9e"], "\xc6" => [0, "\xf9i"], "\xc7" => [0, "\xf9o"], "\xc8" => [0, "\xf9s"], "\xc9" => [0, "\xf9t"], "\xca" => [73, "\xf9"], "\xcb" => [88, "\xf9"], "\xcc" => [89, "\xf9"], "\xcd" => [96, "\xf9"], "\xce" => [97, "\xf9"], "\xcf" => [99, "\xf9"], "\xd0" => [106, "\xf9"], "\xd1" => [136, "\xf9"], "\xd2" => [139, "\xf9"], "\xd3" => [141, "\xf9"], "\xd4" => [145, "\xf9"], "\xd5" => [147, "\xf9"], "\xd6" => [149, "\xf9"], "\xd7" => [101, "\xf9"], "\xd8" => [112, "\xf9"], "\xd9" => [117, "\xf9"], "\xda" => [120, "\xf9"], "\xdb" => [124, "\xf9"], "\xdc" => [127, "\xf9"], "\xdd" => [144, "\xf9"], "\xde" => [152, "\xf9"], "\xdf" => [11, "\xf9"], "\xe0" => [93, "\n"], "\xe1" => [138, "\n"], "\xe2" => [75, "\n"], "\xe3" => [91, "\n"], "\xe4" => [108, "\n"], "\xe5" => [103, "\n"], "\xe6" => [114, "\n"], "\xe7" => [14, "\n"], "\xe8" => [93, "\r"], "\xe9" => [138, "\r"], "\xea" => [75, "\r"], "\xeb" => [91, "\r"], "\xec" => [108, "\r"], "\xed" => [103, "\r"], "\xee" => [114, "\r"], "\xef" => [14, "\r"], "\xf0" => [93, "\x16"], "\xf1" => [138, "\x16"], "\xf2" => [75, "\x16"], "\xf3" => [91, "\x16"], "\xf4" => [108, "\x16"], "\xf5" => [103, "\x16"], "\xf6" => [114, "\x16"], "\xf7" => [14, "\x16"], "\xf8" => [93, ""], "\xf9" => [138, ""], "\xfa" => [75, ""], "\xfb" => [91, ""], "\xfc" => [108, ""], "\xfd" => [103, ""], "\xfe" => [114, ""], "\xff" => [14, ""]], ["\x00" => [94, "\f0"], "\x01" => [76, "\f0"], "\x02" => [104, "\f0"], "\x03" => [16, "\f0"], "\x04" => [94, "\f1"], "\x05" => [76, "\f1"], "\x06" => [104, "\f1"], "\x07" => [16, "\f1"], "\x08" => [94, "\f2"], "\t" => [76, "\f2"], "\n" => [104, "\f2"], "\v" => [16, "\f2"], "\f" => [94, "\fa"], "\r" => [76, "\fa"], "\x0e" => [104, "\fa"], "\x0f" => [16, "\fa"], "\x10" => [94, "\fc"], "\x11" => [76, "\fc"], "\x12" => [104, "\fc"], "\x13" => [16, "\fc"], "\x14" => [94, "\fe"], "\x15" => [76, "\fe"], "\x16" => [104, "\fe"], "\x17" => [16, "\fe"], "\x18" => [94, "\fi"], "\x19" => [76, "\fi"], "\x1a" => [104, "\fi"], "\x1b" => [16, "\fi"], "\x1c" => [94, "\fo"], "\x1d" => [76, "\fo"], "\x1e" => [104, "\fo"], "\x1f" => [16, "\fo"], " " => [94, "\fs"], "!" => [76, "\fs"], "\"" => [104, "\fs"], "#" => [16, "\fs"], "\$" => [94, "\ft"], "%" => [76, "\ft"], "&" => [104, "\ft"], "'" => [16, "\ft"], "(" => [77, "\f "], ")" => [18, "\f "], "*" => [77, "\f%"], "+" => [18, "\f%"], "," => [77, "\f-"], "-" => [18, "\f-"], "." => [77, "\f."], "/" => [18, "\f."], [77, "\f/"], [18, "\f/"], [77, "\f3"], [18, "\f3"], [77, "\f4"], [18, "\f4"], [77, "\f5"], [18, "\f5"], [77, "\f6"], [18, "\f6"], ":" => [77, "\f7"], ";" => [18, "\f7"], "<" => [77, "\f8"], "=" => [18, "\f8"], ">" => [77, "\f9"], "?" => [18, "\f9"], "@" => [77, "\f="], "A" => [18, "\f="], "B" => [77, "\fA"], "C" => [18, "\fA"], "D" => [77, "\f_"], "E" => [18, "\f_"], "F" => [77, "\fb"], "G" => [18, "\fb"], "H" => [77, "\fd"], "I" => [18, "\fd"], "J" => [77, "\ff"], "K" => [18, "\ff"], "L" => [77, "\fg"], "M" => [18, "\fg"], "N" => [77, "\fh"], "O" => [18, "\fh"], "P" => [77, "\fl"], "Q" => [18, "\fl"], "R" => [77, "\fm"], "S" => [18, "\fm"], "T" => [77, "\fn"], "U" => [18, "\fn"], "V" => [77, "\fp"], "W" => [18, "\fp"], "X" => [77, "\fr"], "Y" => [18, "\fr"], "Z" => [77, "\fu"], "[" => [18, "\fu"], "\\" => [0, "\f:"], "]" => [0, "\fB"], "^" => [0, "\fC"], "_" => [0, "\fD"], "`" => [0, "\fE"], "a" => [0, "\fF"], "b" => [0, "\fG"], "c" => [0, "\fH"], "d" => [0, "\fI"], "e" => [0, "\fJ"], "f" => [0, "\fK"], "g" => [0, "\fL"], "h" => [0, "\fM"], "i" => [0, "\fN"], "j" => [0, "\fO"], "k" => [0, "\fP"], "l" => [0, "\fQ"], "m" => [0, "\fR"], "n" => [0, "\fS"], "o" => [0, "\fT"], "p" => [0, "\fU"], "q" => [0, "\fV"], "r" => [0, "\fW"], "s" => [0, "\fY"], "t" => [0, "\fj"], "u" => [0, "\fk"], "v" => [0, "\fq"], "w" => [0, "\fv"], "x" => [0, "\fw"], "y" => [0, "\fx"], "z" => [0, "\fy"], "{" => [0, "\fz"], "|" => [82, "\f"], "}" => [87, "\f"], "~" => [130, "\f"], "" => [9, "\f"], "\x80" => [94, "\x0e0"], "\x81" => [76, "\x0e0"], "\x82" => [104, "\x0e0"], "\x83" => [16, "\x0e0"], "\x84" => [94, "\x0e1"], "\x85" => [76, "\x0e1"], "\x86" => [104, "\x0e1"], "\x87" => [16, "\x0e1"], "\x88" => [94, "\x0e2"], "\x89" => [76, "\x0e2"], "\x8a" => [104, "\x0e2"], "\x8b" => [16, "\x0e2"], "\x8c" => [94, "\x0ea"], "\x8d" => [76, "\x0ea"], "\x8e" => [104, "\x0ea"], "\x8f" => [16, "\x0ea"], "\x90" => [94, "\x0ec"], "\x91" => [76, "\x0ec"], "\x92" => [104, "\x0ec"], "\x93" => [16, "\x0ec"], "\x94" => [94, "\x0ee"], "\x95" => [76, "\x0ee"], "\x96" => [104, "\x0ee"], "\x97" => [16, "\x0ee"], "\x98" => [94, "\x0ei"], "\x99" => [76, "\x0ei"], "\x9a" => [104, "\x0ei"], "\x9b" => [16, "\x0ei"], "\x9c" => [94, "\x0eo"], "\x9d" => [76, "\x0eo"], "\x9e" => [104, "\x0eo"], "\x9f" => [16, "\x0eo"], "\xa0" => [94, "\x0es"], "\xa1" => [76, "\x0es"], "\xa2" => [104, "\x0es"], "\xa3" => [16, "\x0es"], "\xa4" => [94, "\x0et"], "\xa5" => [76, "\x0et"], "\xa6" => [104, "\x0et"], "\xa7" => [16, "\x0et"], "\xa8" => [77, "\x0e "], "\xa9" => [18, "\x0e "], "\xaa" => [77, "\x0e%"], "\xab" => [18, "\x0e%"], "\xac" => [77, "\x0e-"], "\xad" => [18, "\x0e-"], "\xae" => [77, "\x0e."], "\xaf" => [18, "\x0e."], "\xb0" => [77, "\x0e/"], "\xb1" => [18, "\x0e/"], "\xb2" => [77, "\x0e3"], "\xb3" => [18, "\x0e3"], "\xb4" => [77, "\x0e4"], "\xb5" => [18, "\x0e4"], "\xb6" => [77, "\x0e5"], "\xb7" => [18, "\x0e5"], "\xb8" => [77, "\x0e6"], "\xb9" => [18, "\x0e6"], "\xba" => [77, "\x0e7"], "\xbb" => [18, "\x0e7"], "\xbc" => [77, "\x0e8"], "\xbd" => [18, "\x0e8"], "\xbe" => [77, "\x0e9"], "\xbf" => [18, "\x0e9"], "\xc0" => [77, "\x0e="], "\xc1" => [18, "\x0e="], "\xc2" => [77, "\x0eA"], "\xc3" => [18, "\x0eA"], "\xc4" => [77, "\x0e_"], "\xc5" => [18, "\x0e_"], "\xc6" => [77, "\x0eb"], "\xc7" => [18, "\x0eb"], "\xc8" => [77, "\x0ed"], "\xc9" => [18, "\x0ed"], "\xca" => [77, "\x0ef"], "\xcb" => [18, "\x0ef"], "\xcc" => [77, "\x0eg"], "\xcd" => [18, "\x0eg"], "\xce" => [77, "\x0eh"], "\xcf" => [18, "\x0eh"], "\xd0" => [77, "\x0el"], "\xd1" => [18, "\x0el"], "\xd2" => [77, "\x0em"], "\xd3" => [18, "\x0em"], "\xd4" => [77, "\x0en"], "\xd5" => [18, "\x0en"], "\xd6" => [77, "\x0ep"], "\xd7" => [18, "\x0ep"], "\xd8" => [77, "\x0er"], "\xd9" => [18, "\x0er"], "\xda" => [77, "\x0eu"], "\xdb" => [18, "\x0eu"], "\xdc" => [0, "\x0e:"], "\xdd" => [0, "\x0eB"], "\xde" => [0, "\x0eC"], "\xdf" => [0, "\x0eD"], "\xe0" => [0, "\x0eE"], "\xe1" => [0, "\x0eF"], "\xe2" => [0, "\x0eG"], "\xe3" => [0, "\x0eH"], "\xe4" => [0, "\x0eI"], "\xe5" => [0, "\x0eJ"], "\xe6" => [0, "\x0eK"], "\xe7" => [0, "\x0eL"], "\xe8" => [0, "\x0eM"], "\xe9" => [0, "\x0eN"], "\xea" => [0, "\x0eO"], "\xeb" => [0, "\x0eP"], "\xec" => [0, "\x0eQ"], "\xed" => [0, "\x0eR"], "\xee" => [0, "\x0eS"], "\xef" => [0, "\x0eT"], "\xf0" => [0, "\x0eU"], "\xf1" => [0, "\x0eV"], "\xf2" => [0, "\x0eW"], "\xf3" => [0, "\x0eY"], "\xf4" => [0, "\x0ej"], "\xf5" => [0, "\x0ek"], "\xf6" => [0, "\x0eq"], "\xf7" => [0, "\x0ev"], "\xf8" => [0, "\x0ew"], "\xf9" => [0, "\x0ex"], "\xfa" => [0, "\x0ey"], "\xfb" => [0, "\x0ez"], "\xfc" => [82, "\x0e"], "\xfd" => [87, "\x0e"], "\xfe" => [130, "\x0e"], "\xff" => [9, "\x0e"]], ["\x00" => [94, "\x0f0"], "\x01" => [76, "\x0f0"], "\x02" => [104, "\x0f0"], "\x03" => [16, "\x0f0"], "\x04" => [94, "\x0f1"], "\x05" => [76, "\x0f1"], "\x06" => [104, "\x0f1"], "\x07" => [16, "\x0f1"], "\x08" => [94, "\x0f2"], "\t" => [76, "\x0f2"], "\n" => [104, "\x0f2"], "\v" => [16, "\x0f2"], "\f" => [94, "\x0fa"], "\r" => [76, "\x0fa"], "\x0e" => [104, "\x0fa"], "\x0f" => [16, "\x0fa"], "\x10" => [94, "\x0fc"], "\x11" => [76, "\x0fc"], "\x12" => [104, "\x0fc"], "\x13" => [16, "\x0fc"], "\x14" => [94, "\x0fe"], "\x15" => [76, "\x0fe"], "\x16" => [104, "\x0fe"], "\x17" => [16, "\x0fe"], "\x18" => [94, "\x0fi"], "\x19" => [76, "\x0fi"], "\x1a" => [104, "\x0fi"], "\x1b" => [16, "\x0fi"], "\x1c" => [94, "\x0fo"], "\x1d" => [76, "\x0fo"], "\x1e" => [104, "\x0fo"], "\x1f" => [16, "\x0fo"], " " => [94, "\x0fs"], "!" => [76, "\x0fs"], "\"" => [104, "\x0fs"], "#" => [16, "\x0fs"], "\$" => [94, "\x0ft"], "%" => [76, "\x0ft"], "&" => [104, "\x0ft"], "'" => [16, "\x0ft"], "(" => [77, "\x0f "], ")" => [18, "\x0f "], "*" => [77, "\x0f%"], "+" => [18, "\x0f%"], "," => [77, "\x0f-"], "-" => [18, "\x0f-"], "." => [77, "\x0f."], "/" => [18, "\x0f."], [77, "\x0f/"], [18, "\x0f/"], [77, "\x0f3"], [18, "\x0f3"], [77, "\x0f4"], [18, "\x0f4"], [77, "\x0f5"], [18, "\x0f5"], [77, "\x0f6"], [18, "\x0f6"], ":" => [77, "\x0f7"], ";" => [18, "\x0f7"], "<" => [77, "\x0f8"], "=" => [18, "\x0f8"], ">" => [77, "\x0f9"], "?" => [18, "\x0f9"], "@" => [77, "\x0f="], "A" => [18, "\x0f="], "B" => [77, "\x0fA"], "C" => [18, "\x0fA"], "D" => [77, "\x0f_"], "E" => [18, "\x0f_"], "F" => [77, "\x0fb"], "G" => [18, "\x0fb"], "H" => [77, "\x0fd"], "I" => [18, "\x0fd"], "J" => [77, "\x0ff"], "K" => [18, "\x0ff"], "L" => [77, "\x0fg"], "M" => [18, "\x0fg"], "N" => [77, "\x0fh"], "O" => [18, "\x0fh"], "P" => [77, "\x0fl"], "Q" => [18, "\x0fl"], "R" => [77, "\x0fm"], "S" => [18, "\x0fm"], "T" => [77, "\x0fn"], "U" => [18, "\x0fn"], "V" => [77, "\x0fp"], "W" => [18, "\x0fp"], "X" => [77, "\x0fr"], "Y" => [18, "\x0fr"], "Z" => [77, "\x0fu"], "[" => [18, "\x0fu"], "\\" => [0, "\x0f:"], "]" => [0, "\x0fB"], "^" => [0, "\x0fC"], "_" => [0, "\x0fD"], "`" => [0, "\x0fE"], "a" => [0, "\x0fF"], "b" => [0, "\x0fG"], "c" => [0, "\x0fH"], "d" => [0, "\x0fI"], "e" => [0, "\x0fJ"], "f" => [0, "\x0fK"], "g" => [0, "\x0fL"], "h" => [0, "\x0fM"], "i" => [0, "\x0fN"], "j" => [0, "\x0fO"], "k" => [0, "\x0fP"], "l" => [0, "\x0fQ"], "m" => [0, "\x0fR"], "n" => [0, "\x0fS"], "o" => [0, "\x0fT"], "p" => [0, "\x0fU"], "q" => [0, "\x0fV"], "r" => [0, "\x0fW"], "s" => [0, "\x0fY"], "t" => [0, "\x0fj"], "u" => [0, "\x0fk"], "v" => [0, "\x0fq"], "w" => [0, "\x0fv"], "x" => [0, "\x0fw"], "y" => [0, "\x0fx"], "z" => [0, "\x0fy"], "{" => [0, "\x0fz"], "|" => [82, "\x0f"], "}" => [87, "\x0f"], "~" => [130, "\x0f"], "" => [9, "\x0f"], "\x80" => [94, "\x100"], "\x81" => [76, "\x100"], "\x82" => [104, "\x100"], "\x83" => [16, "\x100"], "\x84" => [94, "\x101"], "\x85" => [76, "\x101"], "\x86" => [104, "\x101"], "\x87" => [16, "\x101"], "\x88" => [94, "\x102"], "\x89" => [76, "\x102"], "\x8a" => [104, "\x102"], "\x8b" => [16, "\x102"], "\x8c" => [94, "\x10a"], "\x8d" => [76, "\x10a"], "\x8e" => [104, "\x10a"], "\x8f" => [16, "\x10a"], "\x90" => [94, "\x10c"], "\x91" => [76, "\x10c"], "\x92" => [104, "\x10c"], "\x93" => [16, "\x10c"], "\x94" => [94, "\x10e"], "\x95" => [76, "\x10e"], "\x96" => [104, "\x10e"], "\x97" => [16, "\x10e"], "\x98" => [94, "\x10i"], "\x99" => [76, "\x10i"], "\x9a" => [104, "\x10i"], "\x9b" => [16, "\x10i"], "\x9c" => [94, "\x10o"], "\x9d" => [76, "\x10o"], "\x9e" => [104, "\x10o"], "\x9f" => [16, "\x10o"], "\xa0" => [94, "\x10s"], "\xa1" => [76, "\x10s"], "\xa2" => [104, "\x10s"], "\xa3" => [16, "\x10s"], "\xa4" => [94, "\x10t"], "\xa5" => [76, "\x10t"], "\xa6" => [104, "\x10t"], "\xa7" => [16, "\x10t"], "\xa8" => [77, "\x10 "], "\xa9" => [18, "\x10 "], "\xaa" => [77, "\x10%"], "\xab" => [18, "\x10%"], "\xac" => [77, "\x10-"], "\xad" => [18, "\x10-"], "\xae" => [77, "\x10."], "\xaf" => [18, "\x10."], "\xb0" => [77, "\x10/"], "\xb1" => [18, "\x10/"], "\xb2" => [77, "\x103"], "\xb3" => [18, "\x103"], "\xb4" => [77, "\x104"], "\xb5" => [18, "\x104"], "\xb6" => [77, "\x105"], "\xb7" => [18, "\x105"], "\xb8" => [77, "\x106"], "\xb9" => [18, "\x106"], "\xba" => [77, "\x107"], "\xbb" => [18, "\x107"], "\xbc" => [77, "\x108"], "\xbd" => [18, "\x108"], "\xbe" => [77, "\x109"], "\xbf" => [18, "\x109"], "\xc0" => [77, "\x10="], "\xc1" => [18, "\x10="], "\xc2" => [77, "\x10A"], "\xc3" => [18, "\x10A"], "\xc4" => [77, "\x10_"], "\xc5" => [18, "\x10_"], "\xc6" => [77, "\x10b"], "\xc7" => [18, "\x10b"], "\xc8" => [77, "\x10d"], "\xc9" => [18, "\x10d"], "\xca" => [77, "\x10f"], "\xcb" => [18, "\x10f"], "\xcc" => [77, "\x10g"], "\xcd" => [18, "\x10g"], "\xce" => [77, "\x10h"], "\xcf" => [18, "\x10h"], "\xd0" => [77, "\x10l"], "\xd1" => [18, "\x10l"], "\xd2" => [77, "\x10m"], "\xd3" => [18, "\x10m"], "\xd4" => [77, "\x10n"], "\xd5" => [18, "\x10n"], "\xd6" => [77, "\x10p"], "\xd7" => [18, "\x10p"], "\xd8" => [77, "\x10r"], "\xd9" => [18, "\x10r"], "\xda" => [77, "\x10u"], "\xdb" => [18, "\x10u"], "\xdc" => [0, "\x10:"], "\xdd" => [0, "\x10B"], "\xde" => [0, "\x10C"], "\xdf" => [0, "\x10D"], "\xe0" => [0, "\x10E"], "\xe1" => [0, "\x10F"], "\xe2" => [0, "\x10G"], "\xe3" => [0, "\x10H"], "\xe4" => [0, "\x10I"], "\xe5" => [0, "\x10J"], "\xe6" => [0, "\x10K"], "\xe7" => [0, "\x10L"], "\xe8" => [0, "\x10M"], "\xe9" => [0, "\x10N"], "\xea" => [0, "\x10O"], "\xeb" => [0, "\x10P"], "\xec" => [0, "\x10Q"], "\xed" => [0, "\x10R"], "\xee" => [0, "\x10S"], "\xef" => [0, "\x10T"], "\xf0" => [0, "\x10U"], "\xf1" => [0, "\x10V"], "\xf2" => [0, "\x10W"], "\xf3" => [0, "\x10Y"], "\xf4" => [0, "\x10j"], "\xf5" => [0, "\x10k"], "\xf6" => [0, "\x10q"], "\xf7" => [0, "\x10v"], "\xf8" => [0, "\x10w"], "\xf9" => [0, "\x10x"], "\xfa" => [0, "\x10y"], "\xfb" => [0, "\x10z"], "\xfc" => [82, "\x10"], "\xfd" => [87, "\x10"], "\xfe" => [130, "\x10"], "\xff" => [9, "\x10"]], ["\x00" => [77, "\x0f0"], "\x01" => [18, "\x0f0"], "\x02" => [77, "\x0f1"], "\x03" => [18, "\x0f1"], "\x04" => [77, "\x0f2"], "\x05" => [18, "\x0f2"], "\x06" => [77, "\x0fa"], "\x07" => [18, "\x0fa"], "\x08" => [77, "\x0fc"], "\t" => [18, "\x0fc"], "\n" => [77, "\x0fe"], "\v" => [18, "\x0fe"], "\f" => [77, "\x0fi"], "\r" => [18, "\x0fi"], "\x0e" => [77, "\x0fo"], "\x0f" => [18, "\x0fo"], "\x10" => [77, "\x0fs"], "\x11" => [18, "\x0fs"], "\x12" => [77, "\x0ft"], "\x13" => [18, "\x0ft"], "\x14" => [0, "\x0f "], "\x15" => [0, "\x0f%"], "\x16" => [0, "\x0f-"], "\x17" => [0, "\x0f."], "\x18" => [0, "\x0f/"], "\x19" => [0, "\x0f3"], "\x1a" => [0, "\x0f4"], "\x1b" => [0, "\x0f5"], "\x1c" => [0, "\x0f6"], "\x1d" => [0, "\x0f7"], "\x1e" => [0, "\x0f8"], "\x1f" => [0, "\x0f9"], " " => [0, "\x0f="], "!" => [0, "\x0fA"], "\"" => [0, "\x0f_"], "#" => [0, "\x0fb"], "\$" => [0, "\x0fd"], "%" => [0, "\x0ff"], "&" => [0, "\x0fg"], "'" => [0, "\x0fh"], "(" => [0, "\x0fl"], ")" => [0, "\x0fm"], "*" => [0, "\x0fn"], "+" => [0, "\x0fp"], "," => [0, "\x0fr"], "-" => [0, "\x0fu"], "." => [100, "\x0f"], "/" => [110, "\x0f"], [111, "\x0f"], [115, "\x0f"], [116, "\x0f"], [118, "\x0f"], [119, "\x0f"], [122, "\x0f"], [123, "\x0f"], [125, "\x0f"], [126, "\x0f"], [129, "\x0f"], ":" => [143, "\x0f"], ";" => [148, "\x0f"], "<" => [151, "\x0f"], "=" => [153, "\x0f"], ">" => [83, "\x0f"], "?" => [10, "\x0f"], "@" => [77, "\x100"], "A" => [18, "\x100"], "B" => [77, "\x101"], "C" => [18, "\x101"], "D" => [77, "\x102"], "E" => [18, "\x102"], "F" => [77, "\x10a"], "G" => [18, "\x10a"], "H" => [77, "\x10c"], "I" => [18, "\x10c"], "J" => [77, "\x10e"], "K" => [18, "\x10e"], "L" => [77, "\x10i"], "M" => [18, "\x10i"], "N" => [77, "\x10o"], "O" => [18, "\x10o"], "P" => [77, "\x10s"], "Q" => [18, "\x10s"], "R" => [77, "\x10t"], "S" => [18, "\x10t"], "T" => [0, "\x10 "], "U" => [0, "\x10%"], "V" => [0, "\x10-"], "W" => [0, "\x10."], "X" => [0, "\x10/"], "Y" => [0, "\x103"], "Z" => [0, "\x104"], "[" => [0, "\x105"], "\\" => [0, "\x106"], "]" => [0, "\x107"], "^" => [0, "\x108"], "_" => [0, "\x109"], "`" => [0, "\x10="], "a" => [0, "\x10A"], "b" => [0, "\x10_"], "c" => [0, "\x10b"], "d" => [0, "\x10d"], "e" => [0, "\x10f"], "f" => [0, "\x10g"], "g" => [0, "\x10h"], "h" => [0, "\x10l"], "i" => [0, "\x10m"], "j" => [0, "\x10n"], "k" => [0, "\x10p"], "l" => [0, "\x10r"], "m" => [0, "\x10u"], "n" => [100, "\x10"], "o" => [110, "\x10"], "p" => [111, "\x10"], "q" => [115, "\x10"], "r" => [116, "\x10"], "s" => [118, "\x10"], "t" => [119, "\x10"], "u" => [122, "\x10"], "v" => [123, "\x10"], "w" => [125, "\x10"], "x" => [126, "\x10"], "y" => [129, "\x10"], "z" => [143, "\x10"], "{" => [148, "\x10"], "|" => [151, "\x10"], "}" => [153, "\x10"], "~" => [83, "\x10"], "" => [10, "\x10"], "\x80" => [77, "\x110"], "\x81" => [18, "\x110"], "\x82" => [77, "\x111"], "\x83" => [18, "\x111"], "\x84" => [77, "\x112"], "\x85" => [18, "\x112"], "\x86" => [77, "\x11a"], "\x87" => [18, "\x11a"], "\x88" => [77, "\x11c"], "\x89" => [18, "\x11c"], "\x8a" => [77, "\x11e"], "\x8b" => [18, "\x11e"], "\x8c" => [77, "\x11i"], "\x8d" => [18, "\x11i"], "\x8e" => [77, "\x11o"], "\x8f" => [18, "\x11o"], "\x90" => [77, "\x11s"], "\x91" => [18, "\x11s"], "\x92" => [77, "\x11t"], "\x93" => [18, "\x11t"], "\x94" => [0, "\x11 "], "\x95" => [0, "\x11%"], "\x96" => [0, "\x11-"], "\x97" => [0, "\x11."], "\x98" => [0, "\x11/"], "\x99" => [0, "\x113"], "\x9a" => [0, "\x114"], "\x9b" => [0, "\x115"], "\x9c" => [0, "\x116"], "\x9d" => [0, "\x117"], "\x9e" => [0, "\x118"], "\x9f" => [0, "\x119"], "\xa0" => [0, "\x11="], "\xa1" => [0, "\x11A"], "\xa2" => [0, "\x11_"], "\xa3" => [0, "\x11b"], "\xa4" => [0, "\x11d"], "\xa5" => [0, "\x11f"], "\xa6" => [0, "\x11g"], "\xa7" => [0, "\x11h"], "\xa8" => [0, "\x11l"], "\xa9" => [0, "\x11m"], "\xaa" => [0, "\x11n"], "\xab" => [0, "\x11p"], "\xac" => [0, "\x11r"], "\xad" => [0, "\x11u"], "\xae" => [100, "\x11"], "\xaf" => [110, "\x11"], "\xb0" => [111, "\x11"], "\xb1" => [115, "\x11"], "\xb2" => [116, "\x11"], "\xb3" => [118, "\x11"], "\xb4" => [119, "\x11"], "\xb5" => [122, "\x11"], "\xb6" => [123, "\x11"], "\xb7" => [125, "\x11"], "\xb8" => [126, "\x11"], "\xb9" => [129, "\x11"], "\xba" => [143, "\x11"], "\xbb" => [148, "\x11"], "\xbc" => [151, "\x11"], "\xbd" => [153, "\x11"], "\xbe" => [83, "\x11"], "\xbf" => [10, "\x11"], "\xc0" => [77, "\x120"], "\xc1" => [18, "\x120"], "\xc2" => [77, "\x121"], "\xc3" => [18, "\x121"], "\xc4" => [77, "\x122"], "\xc5" => [18, "\x122"], "\xc6" => [77, "\x12a"], "\xc7" => [18, "\x12a"], "\xc8" => [77, "\x12c"], "\xc9" => [18, "\x12c"], "\xca" => [77, "\x12e"], "\xcb" => [18, "\x12e"], "\xcc" => [77, "\x12i"], "\xcd" => [18, "\x12i"], "\xce" => [77, "\x12o"], "\xcf" => [18, "\x12o"], "\xd0" => [77, "\x12s"], "\xd1" => [18, "\x12s"], "\xd2" => [77, "\x12t"], "\xd3" => [18, "\x12t"], "\xd4" => [0, "\x12 "], "\xd5" => [0, "\x12%"], "\xd6" => [0, "\x12-"], "\xd7" => [0, "\x12."], "\xd8" => [0, "\x12/"], "\xd9" => [0, "\x123"], "\xda" => [0, "\x124"], "\xdb" => [0, "\x125"], "\xdc" => [0, "\x126"], "\xdd" => [0, "\x127"], "\xde" => [0, "\x128"], "\xdf" => [0, "\x129"], "\xe0" => [0, "\x12="], "\xe1" => [0, "\x12A"], "\xe2" => [0, "\x12_"], "\xe3" => [0, "\x12b"], "\xe4" => [0, "\x12d"], "\xe5" => [0, "\x12f"], "\xe6" => [0, "\x12g"], "\xe7" => [0, "\x12h"], "\xe8" => [0, "\x12l"], "\xe9" => [0, "\x12m"], "\xea" => [0, "\x12n"], "\xeb" => [0, "\x12p"], "\xec" => [0, "\x12r"], "\xed" => [0, "\x12u"], "\xee" => [100, "\x12"], "\xef" => [110, "\x12"], "\xf0" => [111, "\x12"], "\xf1" => [115, "\x12"], "\xf2" => [116, "\x12"], "\xf3" => [118, "\x12"], "\xf4" => [119, "\x12"], "\xf5" => [122, "\x12"], "\xf6" => [123, "\x12"], "\xf7" => [125, "\x12"], "\xf8" => [126, "\x12"], "\xf9" => [129, "\x12"], "\xfa" => [143, "\x12"], "\xfb" => [148, "\x12"], "\xfc" => [151, "\x12"], "\xfd" => [153, "\x12"], "\xfe" => [83, "\x12"], "\xff" => [10, "\x12"]], ["\x00" => [94, "\x110"], "\x01" => [76, "\x110"], "\x02" => [104, "\x110"], "\x03" => [16, "\x110"], "\x04" => [94, "\x111"], "\x05" => [76, "\x111"], "\x06" => [104, "\x111"], "\x07" => [16, "\x111"], "\x08" => [94, "\x112"], "\t" => [76, "\x112"], "\n" => [104, "\x112"], "\v" => [16, "\x112"], "\f" => [94, "\x11a"], "\r" => [76, "\x11a"], "\x0e" => [104, "\x11a"], "\x0f" => [16, "\x11a"], "\x10" => [94, "\x11c"], "\x11" => [76, "\x11c"], "\x12" => [104, "\x11c"], "\x13" => [16, "\x11c"], "\x14" => [94, "\x11e"], "\x15" => [76, "\x11e"], "\x16" => [104, "\x11e"], "\x17" => [16, "\x11e"], "\x18" => [94, "\x11i"], "\x19" => [76, "\x11i"], "\x1a" => [104, "\x11i"], "\x1b" => [16, "\x11i"], "\x1c" => [94, "\x11o"], "\x1d" => [76, "\x11o"], "\x1e" => [104, "\x11o"], "\x1f" => [16, "\x11o"], " " => [94, "\x11s"], "!" => [76, "\x11s"], "\"" => [104, "\x11s"], "#" => [16, "\x11s"], "\$" => [94, "\x11t"], "%" => [76, "\x11t"], "&" => [104, "\x11t"], "'" => [16, "\x11t"], "(" => [77, "\x11 "], ")" => [18, "\x11 "], "*" => [77, "\x11%"], "+" => [18, "\x11%"], "," => [77, "\x11-"], "-" => [18, "\x11-"], "." => [77, "\x11."], "/" => [18, "\x11."], [77, "\x11/"], [18, "\x11/"], [77, "\x113"], [18, "\x113"], [77, "\x114"], [18, "\x114"], [77, "\x115"], [18, "\x115"], [77, "\x116"], [18, "\x116"], ":" => [77, "\x117"], ";" => [18, "\x117"], "<" => [77, "\x118"], "=" => [18, "\x118"], ">" => [77, "\x119"], "?" => [18, "\x119"], "@" => [77, "\x11="], "A" => [18, "\x11="], "B" => [77, "\x11A"], "C" => [18, "\x11A"], "D" => [77, "\x11_"], "E" => [18, "\x11_"], "F" => [77, "\x11b"], "G" => [18, "\x11b"], "H" => [77, "\x11d"], "I" => [18, "\x11d"], "J" => [77, "\x11f"], "K" => [18, "\x11f"], "L" => [77, "\x11g"], "M" => [18, "\x11g"], "N" => [77, "\x11h"], "O" => [18, "\x11h"], "P" => [77, "\x11l"], "Q" => [18, "\x11l"], "R" => [77, "\x11m"], "S" => [18, "\x11m"], "T" => [77, "\x11n"], "U" => [18, "\x11n"], "V" => [77, "\x11p"], "W" => [18, "\x11p"], "X" => [77, "\x11r"], "Y" => [18, "\x11r"], "Z" => [77, "\x11u"], "[" => [18, "\x11u"], "\\" => [0, "\x11:"], "]" => [0, "\x11B"], "^" => [0, "\x11C"], "_" => [0, "\x11D"], "`" => [0, "\x11E"], "a" => [0, "\x11F"], "b" => [0, "\x11G"], "c" => [0, "\x11H"], "d" => [0, "\x11I"], "e" => [0, "\x11J"], "f" => [0, "\x11K"], "g" => [0, "\x11L"], "h" => [0, "\x11M"], "i" => [0, "\x11N"], "j" => [0, "\x11O"], "k" => [0, "\x11P"], "l" => [0, "\x11Q"], "m" => [0, "\x11R"], "n" => [0, "\x11S"], "o" => [0, "\x11T"], "p" => [0, "\x11U"], "q" => [0, "\x11V"], "r" => [0, "\x11W"], "s" => [0, "\x11Y"], "t" => [0, "\x11j"], "u" => [0, "\x11k"], "v" => [0, "\x11q"], "w" => [0, "\x11v"], "x" => [0, "\x11w"], "y" => [0, "\x11x"], "z" => [0, "\x11y"], "{" => [0, "\x11z"], "|" => [82, "\x11"], "}" => [87, "\x11"], "~" => [130, "\x11"], "" => [9, "\x11"], "\x80" => [94, "\x120"], "\x81" => [76, "\x120"], "\x82" => [104, "\x120"], "\x83" => [16, "\x120"], "\x84" => [94, "\x121"], "\x85" => [76, "\x121"], "\x86" => [104, "\x121"], "\x87" => [16, "\x121"], "\x88" => [94, "\x122"], "\x89" => [76, "\x122"], "\x8a" => [104, "\x122"], "\x8b" => [16, "\x122"], "\x8c" => [94, "\x12a"], "\x8d" => [76, "\x12a"], "\x8e" => [104, "\x12a"], "\x8f" => [16, "\x12a"], "\x90" => [94, "\x12c"], "\x91" => [76, "\x12c"], "\x92" => [104, "\x12c"], "\x93" => [16, "\x12c"], "\x94" => [94, "\x12e"], "\x95" => [76, "\x12e"], "\x96" => [104, "\x12e"], "\x97" => [16, "\x12e"], "\x98" => [94, "\x12i"], "\x99" => [76, "\x12i"], "\x9a" => [104, "\x12i"], "\x9b" => [16, "\x12i"], "\x9c" => [94, "\x12o"], "\x9d" => [76, "\x12o"], "\x9e" => [104, "\x12o"], "\x9f" => [16, "\x12o"], "\xa0" => [94, "\x12s"], "\xa1" => [76, "\x12s"], "\xa2" => [104, "\x12s"], "\xa3" => [16, "\x12s"], "\xa4" => [94, "\x12t"], "\xa5" => [76, "\x12t"], "\xa6" => [104, "\x12t"], "\xa7" => [16, "\x12t"], "\xa8" => [77, "\x12 "], "\xa9" => [18, "\x12 "], "\xaa" => [77, "\x12%"], "\xab" => [18, "\x12%"], "\xac" => [77, "\x12-"], "\xad" => [18, "\x12-"], "\xae" => [77, "\x12."], "\xaf" => [18, "\x12."], "\xb0" => [77, "\x12/"], "\xb1" => [18, "\x12/"], "\xb2" => [77, "\x123"], "\xb3" => [18, "\x123"], "\xb4" => [77, "\x124"], "\xb5" => [18, "\x124"], "\xb6" => [77, "\x125"], "\xb7" => [18, "\x125"], "\xb8" => [77, "\x126"], "\xb9" => [18, "\x126"], "\xba" => [77, "\x127"], "\xbb" => [18, "\x127"], "\xbc" => [77, "\x128"], "\xbd" => [18, "\x128"], "\xbe" => [77, "\x129"], "\xbf" => [18, "\x129"], "\xc0" => [77, "\x12="], "\xc1" => [18, "\x12="], "\xc2" => [77, "\x12A"], "\xc3" => [18, "\x12A"], "\xc4" => [77, "\x12_"], "\xc5" => [18, "\x12_"], "\xc6" => [77, "\x12b"], "\xc7" => [18, "\x12b"], "\xc8" => [77, "\x12d"], "\xc9" => [18, "\x12d"], "\xca" => [77, "\x12f"], "\xcb" => [18, "\x12f"], "\xcc" => [77, "\x12g"], "\xcd" => [18, "\x12g"], "\xce" => [77, "\x12h"], "\xcf" => [18, "\x12h"], "\xd0" => [77, "\x12l"], "\xd1" => [18, "\x12l"], "\xd2" => [77, "\x12m"], "\xd3" => [18, "\x12m"], "\xd4" => [77, "\x12n"], "\xd5" => [18, "\x12n"], "\xd6" => [77, "\x12p"], "\xd7" => [18, "\x12p"], "\xd8" => [77, "\x12r"], "\xd9" => [18, "\x12r"], "\xda" => [77, "\x12u"], "\xdb" => [18, "\x12u"], "\xdc" => [0, "\x12:"], "\xdd" => [0, "\x12B"], "\xde" => [0, "\x12C"], "\xdf" => [0, "\x12D"], "\xe0" => [0, "\x12E"], "\xe1" => [0, "\x12F"], "\xe2" => [0, "\x12G"], "\xe3" => [0, "\x12H"], "\xe4" => [0, "\x12I"], "\xe5" => [0, "\x12J"], "\xe6" => [0, "\x12K"], "\xe7" => [0, "\x12L"], "\xe8" => [0, "\x12M"], "\xe9" => [0, "\x12N"], "\xea" => [0, "\x12O"], "\xeb" => [0, "\x12P"], "\xec" => [0, "\x12Q"], "\xed" => [0, "\x12R"], "\xee" => [0, "\x12S"], "\xef" => [0, "\x12T"], "\xf0" => [0, "\x12U"], "\xf1" => [0, "\x12V"], "\xf2" => [0, "\x12W"], "\xf3" => [0, "\x12Y"], "\xf4" => [0, "\x12j"], "\xf5" => [0, "\x12k"], "\xf6" => [0, "\x12q"], "\xf7" => [0, "\x12v"], "\xf8" => [0, "\x12w"], "\xf9" => [0, "\x12x"], "\xfa" => [0, "\x12y"], "\xfb" => [0, "\x12z"], "\xfc" => [82, "\x12"], "\xfd" => [87, "\x12"], "\xfe" => [130, "\x12"], "\xff" => [9, "\x12"]], ["\x00" => [94, "\x130"], "\x01" => [76, "\x130"], "\x02" => [104, "\x130"], "\x03" => [16, "\x130"], "\x04" => [94, "\x131"], "\x05" => [76, "\x131"], "\x06" => [104, "\x131"], "\x07" => [16, "\x131"], "\x08" => [94, "\x132"], "\t" => [76, "\x132"], "\n" => [104, "\x132"], "\v" => [16, "\x132"], "\f" => [94, "\x13a"], "\r" => [76, "\x13a"], "\x0e" => [104, "\x13a"], "\x0f" => [16, "\x13a"], "\x10" => [94, "\x13c"], "\x11" => [76, "\x13c"], "\x12" => [104, "\x13c"], "\x13" => [16, "\x13c"], "\x14" => [94, "\x13e"], "\x15" => [76, "\x13e"], "\x16" => [104, "\x13e"], "\x17" => [16, "\x13e"], "\x18" => [94, "\x13i"], "\x19" => [76, "\x13i"], "\x1a" => [104, "\x13i"], "\x1b" => [16, "\x13i"], "\x1c" => [94, "\x13o"], "\x1d" => [76, "\x13o"], "\x1e" => [104, "\x13o"], "\x1f" => [16, "\x13o"], " " => [94, "\x13s"], "!" => [76, "\x13s"], "\"" => [104, "\x13s"], "#" => [16, "\x13s"], "\$" => [94, "\x13t"], "%" => [76, "\x13t"], "&" => [104, "\x13t"], "'" => [16, "\x13t"], "(" => [77, "\x13 "], ")" => [18, "\x13 "], "*" => [77, "\x13%"], "+" => [18, "\x13%"], "," => [77, "\x13-"], "-" => [18, "\x13-"], "." => [77, "\x13."], "/" => [18, "\x13."], [77, "\x13/"], [18, "\x13/"], [77, "\x133"], [18, "\x133"], [77, "\x134"], [18, "\x134"], [77, "\x135"], [18, "\x135"], [77, "\x136"], [18, "\x136"], ":" => [77, "\x137"], ";" => [18, "\x137"], "<" => [77, "\x138"], "=" => [18, "\x138"], ">" => [77, "\x139"], "?" => [18, "\x139"], "@" => [77, "\x13="], "A" => [18, "\x13="], "B" => [77, "\x13A"], "C" => [18, "\x13A"], "D" => [77, "\x13_"], "E" => [18, "\x13_"], "F" => [77, "\x13b"], "G" => [18, "\x13b"], "H" => [77, "\x13d"], "I" => [18, "\x13d"], "J" => [77, "\x13f"], "K" => [18, "\x13f"], "L" => [77, "\x13g"], "M" => [18, "\x13g"], "N" => [77, "\x13h"], "O" => [18, "\x13h"], "P" => [77, "\x13l"], "Q" => [18, "\x13l"], "R" => [77, "\x13m"], "S" => [18, "\x13m"], "T" => [77, "\x13n"], "U" => [18, "\x13n"], "V" => [77, "\x13p"], "W" => [18, "\x13p"], "X" => [77, "\x13r"], "Y" => [18, "\x13r"], "Z" => [77, "\x13u"], "[" => [18, "\x13u"], "\\" => [0, "\x13:"], "]" => [0, "\x13B"], "^" => [0, "\x13C"], "_" => [0, "\x13D"], "`" => [0, "\x13E"], "a" => [0, "\x13F"], "b" => [0, "\x13G"], "c" => [0, "\x13H"], "d" => [0, "\x13I"], "e" => [0, "\x13J"], "f" => [0, "\x13K"], "g" => [0, "\x13L"], "h" => [0, "\x13M"], "i" => [0, "\x13N"], "j" => [0, "\x13O"], "k" => [0, "\x13P"], "l" => [0, "\x13Q"], "m" => [0, "\x13R"], "n" => [0, "\x13S"], "o" => [0, "\x13T"], "p" => [0, "\x13U"], "q" => [0, "\x13V"], "r" => [0, "\x13W"], "s" => [0, "\x13Y"], "t" => [0, "\x13j"], "u" => [0, "\x13k"], "v" => [0, "\x13q"], "w" => [0, "\x13v"], "x" => [0, "\x13w"], "y" => [0, "\x13x"], "z" => [0, "\x13y"], "{" => [0, "\x13z"], "|" => [82, "\x13"], "}" => [87, "\x13"], "~" => [130, "\x13"], "" => [9, "\x13"], "\x80" => [94, "\x140"], "\x81" => [76, "\x140"], "\x82" => [104, "\x140"], "\x83" => [16, "\x140"], "\x84" => [94, "\x141"], "\x85" => [76, "\x141"], "\x86" => [104, "\x141"], "\x87" => [16, "\x141"], "\x88" => [94, "\x142"], "\x89" => [76, "\x142"], "\x8a" => [104, "\x142"], "\x8b" => [16, "\x142"], "\x8c" => [94, "\x14a"], "\x8d" => [76, "\x14a"], "\x8e" => [104, "\x14a"], "\x8f" => [16, "\x14a"], "\x90" => [94, "\x14c"], "\x91" => [76, "\x14c"], "\x92" => [104, "\x14c"], "\x93" => [16, "\x14c"], "\x94" => [94, "\x14e"], "\x95" => [76, "\x14e"], "\x96" => [104, "\x14e"], "\x97" => [16, "\x14e"], "\x98" => [94, "\x14i"], "\x99" => [76, "\x14i"], "\x9a" => [104, "\x14i"], "\x9b" => [16, "\x14i"], "\x9c" => [94, "\x14o"], "\x9d" => [76, "\x14o"], "\x9e" => [104, "\x14o"], "\x9f" => [16, "\x14o"], "\xa0" => [94, "\x14s"], "\xa1" => [76, "\x14s"], "\xa2" => [104, "\x14s"], "\xa3" => [16, "\x14s"], "\xa4" => [94, "\x14t"], "\xa5" => [76, "\x14t"], "\xa6" => [104, "\x14t"], "\xa7" => [16, "\x14t"], "\xa8" => [77, "\x14 "], "\xa9" => [18, "\x14 "], "\xaa" => [77, "\x14%"], "\xab" => [18, "\x14%"], "\xac" => [77, "\x14-"], "\xad" => [18, "\x14-"], "\xae" => [77, "\x14."], "\xaf" => [18, "\x14."], "\xb0" => [77, "\x14/"], "\xb1" => [18, "\x14/"], "\xb2" => [77, "\x143"], "\xb3" => [18, "\x143"], "\xb4" => [77, "\x144"], "\xb5" => [18, "\x144"], "\xb6" => [77, "\x145"], "\xb7" => [18, "\x145"], "\xb8" => [77, "\x146"], "\xb9" => [18, "\x146"], "\xba" => [77, "\x147"], "\xbb" => [18, "\x147"], "\xbc" => [77, "\x148"], "\xbd" => [18, "\x148"], "\xbe" => [77, "\x149"], "\xbf" => [18, "\x149"], "\xc0" => [77, "\x14="], "\xc1" => [18, "\x14="], "\xc2" => [77, "\x14A"], "\xc3" => [18, "\x14A"], "\xc4" => [77, "\x14_"], "\xc5" => [18, "\x14_"], "\xc6" => [77, "\x14b"], "\xc7" => [18, "\x14b"], "\xc8" => [77, "\x14d"], "\xc9" => [18, "\x14d"], "\xca" => [77, "\x14f"], "\xcb" => [18, "\x14f"], "\xcc" => [77, "\x14g"], "\xcd" => [18, "\x14g"], "\xce" => [77, "\x14h"], "\xcf" => [18, "\x14h"], "\xd0" => [77, "\x14l"], "\xd1" => [18, "\x14l"], "\xd2" => [77, "\x14m"], "\xd3" => [18, "\x14m"], "\xd4" => [77, "\x14n"], "\xd5" => [18, "\x14n"], "\xd6" => [77, "\x14p"], "\xd7" => [18, "\x14p"], "\xd8" => [77, "\x14r"], "\xd9" => [18, "\x14r"], "\xda" => [77, "\x14u"], "\xdb" => [18, "\x14u"], "\xdc" => [0, "\x14:"], "\xdd" => [0, "\x14B"], "\xde" => [0, "\x14C"], "\xdf" => [0, "\x14D"], "\xe0" => [0, "\x14E"], "\xe1" => [0, "\x14F"], "\xe2" => [0, "\x14G"], "\xe3" => [0, "\x14H"], "\xe4" => [0, "\x14I"], "\xe5" => [0, "\x14J"], "\xe6" => [0, "\x14K"], "\xe7" => [0, "\x14L"], "\xe8" => [0, "\x14M"], "\xe9" => [0, "\x14N"], "\xea" => [0, "\x14O"], "\xeb" => [0, "\x14P"], "\xec" => [0, "\x14Q"], "\xed" => [0, "\x14R"], "\xee" => [0, "\x14S"], "\xef" => [0, "\x14T"], "\xf0" => [0, "\x14U"], "\xf1" => [0, "\x14V"], "\xf2" => [0, "\x14W"], "\xf3" => [0, "\x14Y"], "\xf4" => [0, "\x14j"], "\xf5" => [0, "\x14k"], "\xf6" => [0, "\x14q"], "\xf7" => [0, "\x14v"], "\xf8" => [0, "\x14w"], "\xf9" => [0, "\x14x"], "\xfa" => [0, "\x14y"], "\xfb" => [0, "\x14z"], "\xfc" => [82, "\x14"], "\xfd" => [87, "\x14"], "\xfe" => [130, "\x14"], "\xff" => [9, "\x14"]], ["\x00" => [77, "\x130"], "\x01" => [18, "\x130"], "\x02" => [77, "\x131"], "\x03" => [18, "\x131"], "\x04" => [77, "\x132"], "\x05" => [18, "\x132"], "\x06" => [77, "\x13a"], "\x07" => [18, "\x13a"], "\x08" => [77, "\x13c"], "\t" => [18, "\x13c"], "\n" => [77, "\x13e"], "\v" => [18, "\x13e"], "\f" => [77, "\x13i"], "\r" => [18, "\x13i"], "\x0e" => [77, "\x13o"], "\x0f" => [18, "\x13o"], "\x10" => [77, "\x13s"], "\x11" => [18, "\x13s"], "\x12" => [77, "\x13t"], "\x13" => [18, "\x13t"], "\x14" => [0, "\x13 "], "\x15" => [0, "\x13%"], "\x16" => [0, "\x13-"], "\x17" => [0, "\x13."], "\x18" => [0, "\x13/"], "\x19" => [0, "\x133"], "\x1a" => [0, "\x134"], "\x1b" => [0, "\x135"], "\x1c" => [0, "\x136"], "\x1d" => [0, "\x137"], "\x1e" => [0, "\x138"], "\x1f" => [0, "\x139"], " " => [0, "\x13="], "!" => [0, "\x13A"], "\"" => [0, "\x13_"], "#" => [0, "\x13b"], "\$" => [0, "\x13d"], "%" => [0, "\x13f"], "&" => [0, "\x13g"], "'" => [0, "\x13h"], "(" => [0, "\x13l"], ")" => [0, "\x13m"], "*" => [0, "\x13n"], "+" => [0, "\x13p"], "," => [0, "\x13r"], "-" => [0, "\x13u"], "." => [100, "\x13"], "/" => [110, "\x13"], [111, "\x13"], [115, "\x13"], [116, "\x13"], [118, "\x13"], [119, "\x13"], [122, "\x13"], [123, "\x13"], [125, "\x13"], [126, "\x13"], [129, "\x13"], ":" => [143, "\x13"], ";" => [148, "\x13"], "<" => [151, "\x13"], "=" => [153, "\x13"], ">" => [83, "\x13"], "?" => [10, "\x13"], "@" => [77, "\x140"], "A" => [18, "\x140"], "B" => [77, "\x141"], "C" => [18, "\x141"], "D" => [77, "\x142"], "E" => [18, "\x142"], "F" => [77, "\x14a"], "G" => [18, "\x14a"], "H" => [77, "\x14c"], "I" => [18, "\x14c"], "J" => [77, "\x14e"], "K" => [18, "\x14e"], "L" => [77, "\x14i"], "M" => [18, "\x14i"], "N" => [77, "\x14o"], "O" => [18, "\x14o"], "P" => [77, "\x14s"], "Q" => [18, "\x14s"], "R" => [77, "\x14t"], "S" => [18, "\x14t"], "T" => [0, "\x14 "], "U" => [0, "\x14%"], "V" => [0, "\x14-"], "W" => [0, "\x14."], "X" => [0, "\x14/"], "Y" => [0, "\x143"], "Z" => [0, "\x144"], "[" => [0, "\x145"], "\\" => [0, "\x146"], "]" => [0, "\x147"], "^" => [0, "\x148"], "_" => [0, "\x149"], "`" => [0, "\x14="], "a" => [0, "\x14A"], "b" => [0, "\x14_"], "c" => [0, "\x14b"], "d" => [0, "\x14d"], "e" => [0, "\x14f"], "f" => [0, "\x14g"], "g" => [0, "\x14h"], "h" => [0, "\x14l"], "i" => [0, "\x14m"], "j" => [0, "\x14n"], "k" => [0, "\x14p"], "l" => [0, "\x14r"], "m" => [0, "\x14u"], "n" => [100, "\x14"], "o" => [110, "\x14"], "p" => [111, "\x14"], "q" => [115, "\x14"], "r" => [116, "\x14"], "s" => [118, "\x14"], "t" => [119, "\x14"], "u" => [122, "\x14"], "v" => [123, "\x14"], "w" => [125, "\x14"], "x" => [126, "\x14"], "y" => [129, "\x14"], "z" => [143, "\x14"], "{" => [148, "\x14"], "|" => [151, "\x14"], "}" => [153, "\x14"], "~" => [83, "\x14"], "" => [10, "\x14"], "\x80" => [77, "\x150"], "\x81" => [18, "\x150"], "\x82" => [77, "\x151"], "\x83" => [18, "\x151"], "\x84" => [77, "\x152"], "\x85" => [18, "\x152"], "\x86" => [77, "\x15a"], "\x87" => [18, "\x15a"], "\x88" => [77, "\x15c"], "\x89" => [18, "\x15c"], "\x8a" => [77, "\x15e"], "\x8b" => [18, "\x15e"], "\x8c" => [77, "\x15i"], "\x8d" => [18, "\x15i"], "\x8e" => [77, "\x15o"], "\x8f" => [18, "\x15o"], "\x90" => [77, "\x15s"], "\x91" => [18, "\x15s"], "\x92" => [77, "\x15t"], "\x93" => [18, "\x15t"], "\x94" => [0, "\x15 "], "\x95" => [0, "\x15%"], "\x96" => [0, "\x15-"], "\x97" => [0, "\x15."], "\x98" => [0, "\x15/"], "\x99" => [0, "\x153"], "\x9a" => [0, "\x154"], "\x9b" => [0, "\x155"], "\x9c" => [0, "\x156"], "\x9d" => [0, "\x157"], "\x9e" => [0, "\x158"], "\x9f" => [0, "\x159"], "\xa0" => [0, "\x15="], "\xa1" => [0, "\x15A"], "\xa2" => [0, "\x15_"], "\xa3" => [0, "\x15b"], "\xa4" => [0, "\x15d"], "\xa5" => [0, "\x15f"], "\xa6" => [0, "\x15g"], "\xa7" => [0, "\x15h"], "\xa8" => [0, "\x15l"], "\xa9" => [0, "\x15m"], "\xaa" => [0, "\x15n"], "\xab" => [0, "\x15p"], "\xac" => [0, "\x15r"], "\xad" => [0, "\x15u"], "\xae" => [100, "\x15"], "\xaf" => [110, "\x15"], "\xb0" => [111, "\x15"], "\xb1" => [115, "\x15"], "\xb2" => [116, "\x15"], "\xb3" => [118, "\x15"], "\xb4" => [119, "\x15"], "\xb5" => [122, "\x15"], "\xb6" => [123, "\x15"], "\xb7" => [125, "\x15"], "\xb8" => [126, "\x15"], "\xb9" => [129, "\x15"], "\xba" => [143, "\x15"], "\xbb" => [148, "\x15"], "\xbc" => [151, "\x15"], "\xbd" => [153, "\x15"], "\xbe" => [83, "\x15"], "\xbf" => [10, "\x15"], "\xc0" => [77, "\x170"], "\xc1" => [18, "\x170"], "\xc2" => [77, "\x171"], "\xc3" => [18, "\x171"], "\xc4" => [77, "\x172"], "\xc5" => [18, "\x172"], "\xc6" => [77, "\x17a"], "\xc7" => [18, "\x17a"], "\xc8" => [77, "\x17c"], "\xc9" => [18, "\x17c"], "\xca" => [77, "\x17e"], "\xcb" => [18, "\x17e"], "\xcc" => [77, "\x17i"], "\xcd" => [18, "\x17i"], "\xce" => [77, "\x17o"], "\xcf" => [18, "\x17o"], "\xd0" => [77, "\x17s"], "\xd1" => [18, "\x17s"], "\xd2" => [77, "\x17t"], "\xd3" => [18, "\x17t"], "\xd4" => [0, "\x17 "], "\xd5" => [0, "\x17%"], "\xd6" => [0, "\x17-"], "\xd7" => [0, "\x17."], "\xd8" => [0, "\x17/"], "\xd9" => [0, "\x173"], "\xda" => [0, "\x174"], "\xdb" => [0, "\x175"], "\xdc" => [0, "\x176"], "\xdd" => [0, "\x177"], "\xde" => [0, "\x178"], "\xdf" => [0, "\x179"], "\xe0" => [0, "\x17="], "\xe1" => [0, "\x17A"], "\xe2" => [0, "\x17_"], "\xe3" => [0, "\x17b"], "\xe4" => [0, "\x17d"], "\xe5" => [0, "\x17f"], "\xe6" => [0, "\x17g"], "\xe7" => [0, "\x17h"], "\xe8" => [0, "\x17l"], "\xe9" => [0, "\x17m"], "\xea" => [0, "\x17n"], "\xeb" => [0, "\x17p"], "\xec" => [0, "\x17r"], "\xed" => [0, "\x17u"], "\xee" => [100, "\x17"], "\xef" => [110, "\x17"], "\xf0" => [111, "\x17"], "\xf1" => [115, "\x17"], "\xf2" => [116, "\x17"], "\xf3" => [118, "\x17"], "\xf4" => [119, "\x17"], "\xf5" => [122, "\x17"], "\xf6" => [123, "\x17"], "\xf7" => [125, "\x17"], "\xf8" => [126, "\x17"], "\xf9" => [129, "\x17"], "\xfa" => [143, "\x17"], "\xfb" => [148, "\x17"], "\xfc" => [151, "\x17"], "\xfd" => [153, "\x17"], "\xfe" => [83, "\x17"], "\xff" => [10, "\x17"]], ["\x00" => [0, "\x130"], "\x01" => [0, "\x131"], "\x02" => [0, "\x132"], "\x03" => [0, "\x13a"], "\x04" => [0, "\x13c"], "\x05" => [0, "\x13e"], "\x06" => [0, "\x13i"], "\x07" => [0, "\x13o"], "\x08" => [0, "\x13s"], "\t" => [0, "\x13t"], "\n" => [73, "\x13"], "\v" => [88, "\x13"], "\f" => [89, "\x13"], "\r" => [96, "\x13"], "\x0e" => [97, "\x13"], "\x0f" => [99, "\x13"], "\x10" => [106, "\x13"], "\x11" => [136, "\x13"], "\x12" => [139, "\x13"], "\x13" => [141, "\x13"], "\x14" => [145, "\x13"], "\x15" => [147, "\x13"], "\x16" => [149, "\x13"], "\x17" => [101, "\x13"], "\x18" => [112, "\x13"], "\x19" => [117, "\x13"], "\x1a" => [120, "\x13"], "\x1b" => [124, "\x13"], "\x1c" => [127, "\x13"], "\x1d" => [144, "\x13"], "\x1e" => [152, "\x13"], "\x1f" => [11, "\x13"], " " => [0, "\x140"], "!" => [0, "\x141"], "\"" => [0, "\x142"], "#" => [0, "\x14a"], "\$" => [0, "\x14c"], "%" => [0, "\x14e"], "&" => [0, "\x14i"], "'" => [0, "\x14o"], "(" => [0, "\x14s"], ")" => [0, "\x14t"], "*" => [73, "\x14"], "+" => [88, "\x14"], "," => [89, "\x14"], "-" => [96, "\x14"], "." => [97, "\x14"], "/" => [99, "\x14"], [106, "\x14"], [136, "\x14"], [139, "\x14"], [141, "\x14"], [145, "\x14"], [147, "\x14"], [149, "\x14"], [101, "\x14"], [112, "\x14"], [117, "\x14"], ":" => [120, "\x14"], ";" => [124, "\x14"], "<" => [127, "\x14"], "=" => [144, "\x14"], ">" => [152, "\x14"], "?" => [11, "\x14"], "@" => [0, "\x150"], "A" => [0, "\x151"], "B" => [0, "\x152"], "C" => [0, "\x15a"], "D" => [0, "\x15c"], "E" => [0, "\x15e"], "F" => [0, "\x15i"], "G" => [0, "\x15o"], "H" => [0, "\x15s"], "I" => [0, "\x15t"], "J" => [73, "\x15"], "K" => [88, "\x15"], "L" => [89, "\x15"], "M" => [96, "\x15"], "N" => [97, "\x15"], "O" => [99, "\x15"], "P" => [106, "\x15"], "Q" => [136, "\x15"], "R" => [139, "\x15"], "S" => [141, "\x15"], "T" => [145, "\x15"], "U" => [147, "\x15"], "V" => [149, "\x15"], "W" => [101, "\x15"], "X" => [112, "\x15"], "Y" => [117, "\x15"], "Z" => [120, "\x15"], "[" => [124, "\x15"], "\\" => [127, "\x15"], "]" => [144, "\x15"], "^" => [152, "\x15"], "_" => [11, "\x15"], "`" => [0, "\x170"], "a" => [0, "\x171"], "b" => [0, "\x172"], "c" => [0, "\x17a"], "d" => [0, "\x17c"], "e" => [0, "\x17e"], "f" => [0, "\x17i"], "g" => [0, "\x17o"], "h" => [0, "\x17s"], "i" => [0, "\x17t"], "j" => [73, "\x17"], "k" => [88, "\x17"], "l" => [89, "\x17"], "m" => [96, "\x17"], "n" => [97, "\x17"], "o" => [99, "\x17"], "p" => [106, "\x17"], "q" => [136, "\x17"], "r" => [139, "\x17"], "s" => [141, "\x17"], "t" => [145, "\x17"], "u" => [147, "\x17"], "v" => [149, "\x17"], "w" => [101, "\x17"], "x" => [112, "\x17"], "y" => [117, "\x17"], "z" => [120, "\x17"], "{" => [124, "\x17"], "|" => [127, "\x17"], "}" => [144, "\x17"], "~" => [152, "\x17"], "" => [11, "\x17"], "\x80" => [0, "\x180"], "\x81" => [0, "\x181"], "\x82" => [0, "\x182"], "\x83" => [0, "\x18a"], "\x84" => [0, "\x18c"], "\x85" => [0, "\x18e"], "\x86" => [0, "\x18i"], "\x87" => [0, "\x18o"], "\x88" => [0, "\x18s"], "\x89" => [0, "\x18t"], "\x8a" => [73, "\x18"], "\x8b" => [88, "\x18"], "\x8c" => [89, "\x18"], "\x8d" => [96, "\x18"], "\x8e" => [97, "\x18"], "\x8f" => [99, "\x18"], "\x90" => [106, "\x18"], "\x91" => [136, "\x18"], "\x92" => [139, "\x18"], "\x93" => [141, "\x18"], "\x94" => [145, "\x18"], "\x95" => [147, "\x18"], "\x96" => [149, "\x18"], "\x97" => [101, "\x18"], "\x98" => [112, "\x18"], "\x99" => [117, "\x18"], "\x9a" => [120, "\x18"], "\x9b" => [124, "\x18"], "\x9c" => [127, "\x18"], "\x9d" => [144, "\x18"], "\x9e" => [152, "\x18"], "\x9f" => [11, "\x18"], "\xa0" => [0, "\x190"], "\xa1" => [0, "\x191"], "\xa2" => [0, "\x192"], "\xa3" => [0, "\x19a"], "\xa4" => [0, "\x19c"], "\xa5" => [0, "\x19e"], "\xa6" => [0, "\x19i"], "\xa7" => [0, "\x19o"], "\xa8" => [0, "\x19s"], "\xa9" => [0, "\x19t"], "\xaa" => [73, "\x19"], "\xab" => [88, "\x19"], "\xac" => [89, "\x19"], "\xad" => [96, "\x19"], "\xae" => [97, "\x19"], "\xaf" => [99, "\x19"], "\xb0" => [106, "\x19"], "\xb1" => [136, "\x19"], "\xb2" => [139, "\x19"], "\xb3" => [141, "\x19"], "\xb4" => [145, "\x19"], "\xb5" => [147, "\x19"], "\xb6" => [149, "\x19"], "\xb7" => [101, "\x19"], "\xb8" => [112, "\x19"], "\xb9" => [117, "\x19"], "\xba" => [120, "\x19"], "\xbb" => [124, "\x19"], "\xbc" => [127, "\x19"], "\xbd" => [144, "\x19"], "\xbe" => [152, "\x19"], "\xbf" => [11, "\x19"], "\xc0" => [0, "\x1a0"], "\xc1" => [0, "\x1a1"], "\xc2" => [0, "\x1a2"], "\xc3" => [0, "\x1aa"], "\xc4" => [0, "\x1ac"], "\xc5" => [0, "\x1ae"], "\xc6" => [0, "\x1ai"], "\xc7" => [0, "\x1ao"], "\xc8" => [0, "\x1as"], "\xc9" => [0, "\x1at"], "\xca" => [73, "\x1a"], "\xcb" => [88, "\x1a"], "\xcc" => [89, "\x1a"], "\xcd" => [96, "\x1a"], "\xce" => [97, "\x1a"], "\xcf" => [99, "\x1a"], "\xd0" => [106, "\x1a"], "\xd1" => [136, "\x1a"], "\xd2" => [139, "\x1a"], "\xd3" => [141, "\x1a"], "\xd4" => [145, "\x1a"], "\xd5" => [147, "\x1a"], "\xd6" => [149, "\x1a"], "\xd7" => [101, "\x1a"], "\xd8" => [112, "\x1a"], "\xd9" => [117, "\x1a"], "\xda" => [120, "\x1a"], "\xdb" => [124, "\x1a"], "\xdc" => [127, "\x1a"], "\xdd" => [144, "\x1a"], "\xde" => [152, "\x1a"], "\xdf" => [11, "\x1a"], "\xe0" => [0, "\x1b0"], "\xe1" => [0, "\x1b1"], "\xe2" => [0, "\x1b2"], "\xe3" => [0, "\x1ba"], "\xe4" => [0, "\x1bc"], "\xe5" => [0, "\x1be"], "\xe6" => [0, "\x1bi"], "\xe7" => [0, "\x1bo"], "\xe8" => [0, "\x1bs"], "\xe9" => [0, "\x1bt"], "\xea" => [73, "\x1b"], "\xeb" => [88, "\x1b"], "\xec" => [89, "\x1b"], "\xed" => [96, "\x1b"], "\xee" => [97, "\x1b"], "\xef" => [99, "\x1b"], "\xf0" => [106, "\x1b"], "\xf1" => [136, "\x1b"], "\xf2" => [139, "\x1b"], "\xf3" => [141, "\x1b"], "\xf4" => [145, "\x1b"], "\xf5" => [147, "\x1b"], "\xf6" => [149, "\x1b"], "\xf7" => [101, "\x1b"], "\xf8" => [112, "\x1b"], "\xf9" => [117, "\x1b"], "\xfa" => [120, "\x1b"], "\xfb" => [124, "\x1b"], "\xfc" => [127, "\x1b"], "\xfd" => [144, "\x1b"], "\xfe" => [152, "\x1b"], "\xff" => [11, "\x1b"]], ["\x00" => [94, "\x150"], "\x01" => [76, "\x150"], "\x02" => [104, "\x150"], "\x03" => [16, "\x150"], "\x04" => [94, "\x151"], "\x05" => [76, "\x151"], "\x06" => [104, "\x151"], "\x07" => [16, "\x151"], "\x08" => [94, "\x152"], "\t" => [76, "\x152"], "\n" => [104, "\x152"], "\v" => [16, "\x152"], "\f" => [94, "\x15a"], "\r" => [76, "\x15a"], "\x0e" => [104, "\x15a"], "\x0f" => [16, "\x15a"], "\x10" => [94, "\x15c"], "\x11" => [76, "\x15c"], "\x12" => [104, "\x15c"], "\x13" => [16, "\x15c"], "\x14" => [94, "\x15e"], "\x15" => [76, "\x15e"], "\x16" => [104, "\x15e"], "\x17" => [16, "\x15e"], "\x18" => [94, "\x15i"], "\x19" => [76, "\x15i"], "\x1a" => [104, "\x15i"], "\x1b" => [16, "\x15i"], "\x1c" => [94, "\x15o"], "\x1d" => [76, "\x15o"], "\x1e" => [104, "\x15o"], "\x1f" => [16, "\x15o"], " " => [94, "\x15s"], "!" => [76, "\x15s"], "\"" => [104, "\x15s"], "#" => [16, "\x15s"], "\$" => [94, "\x15t"], "%" => [76, "\x15t"], "&" => [104, "\x15t"], "'" => [16, "\x15t"], "(" => [77, "\x15 "], ")" => [18, "\x15 "], "*" => [77, "\x15%"], "+" => [18, "\x15%"], "," => [77, "\x15-"], "-" => [18, "\x15-"], "." => [77, "\x15."], "/" => [18, "\x15."], [77, "\x15/"], [18, "\x15/"], [77, "\x153"], [18, "\x153"], [77, "\x154"], [18, "\x154"], [77, "\x155"], [18, "\x155"], [77, "\x156"], [18, "\x156"], ":" => [77, "\x157"], ";" => [18, "\x157"], "<" => [77, "\x158"], "=" => [18, "\x158"], ">" => [77, "\x159"], "?" => [18, "\x159"], "@" => [77, "\x15="], "A" => [18, "\x15="], "B" => [77, "\x15A"], "C" => [18, "\x15A"], "D" => [77, "\x15_"], "E" => [18, "\x15_"], "F" => [77, "\x15b"], "G" => [18, "\x15b"], "H" => [77, "\x15d"], "I" => [18, "\x15d"], "J" => [77, "\x15f"], "K" => [18, "\x15f"], "L" => [77, "\x15g"], "M" => [18, "\x15g"], "N" => [77, "\x15h"], "O" => [18, "\x15h"], "P" => [77, "\x15l"], "Q" => [18, "\x15l"], "R" => [77, "\x15m"], "S" => [18, "\x15m"], "T" => [77, "\x15n"], "U" => [18, "\x15n"], "V" => [77, "\x15p"], "W" => [18, "\x15p"], "X" => [77, "\x15r"], "Y" => [18, "\x15r"], "Z" => [77, "\x15u"], "[" => [18, "\x15u"], "\\" => [0, "\x15:"], "]" => [0, "\x15B"], "^" => [0, "\x15C"], "_" => [0, "\x15D"], "`" => [0, "\x15E"], "a" => [0, "\x15F"], "b" => [0, "\x15G"], "c" => [0, "\x15H"], "d" => [0, "\x15I"], "e" => [0, "\x15J"], "f" => [0, "\x15K"], "g" => [0, "\x15L"], "h" => [0, "\x15M"], "i" => [0, "\x15N"], "j" => [0, "\x15O"], "k" => [0, "\x15P"], "l" => [0, "\x15Q"], "m" => [0, "\x15R"], "n" => [0, "\x15S"], "o" => [0, "\x15T"], "p" => [0, "\x15U"], "q" => [0, "\x15V"], "r" => [0, "\x15W"], "s" => [0, "\x15Y"], "t" => [0, "\x15j"], "u" => [0, "\x15k"], "v" => [0, "\x15q"], "w" => [0, "\x15v"], "x" => [0, "\x15w"], "y" => [0, "\x15x"], "z" => [0, "\x15y"], "{" => [0, "\x15z"], "|" => [82, "\x15"], "}" => [87, "\x15"], "~" => [130, "\x15"], "" => [9, "\x15"], "\x80" => [94, "\x170"], "\x81" => [76, "\x170"], "\x82" => [104, "\x170"], "\x83" => [16, "\x170"], "\x84" => [94, "\x171"], "\x85" => [76, "\x171"], "\x86" => [104, "\x171"], "\x87" => [16, "\x171"], "\x88" => [94, "\x172"], "\x89" => [76, "\x172"], "\x8a" => [104, "\x172"], "\x8b" => [16, "\x172"], "\x8c" => [94, "\x17a"], "\x8d" => [76, "\x17a"], "\x8e" => [104, "\x17a"], "\x8f" => [16, "\x17a"], "\x90" => [94, "\x17c"], "\x91" => [76, "\x17c"], "\x92" => [104, "\x17c"], "\x93" => [16, "\x17c"], "\x94" => [94, "\x17e"], "\x95" => [76, "\x17e"], "\x96" => [104, "\x17e"], "\x97" => [16, "\x17e"], "\x98" => [94, "\x17i"], "\x99" => [76, "\x17i"], "\x9a" => [104, "\x17i"], "\x9b" => [16, "\x17i"], "\x9c" => [94, "\x17o"], "\x9d" => [76, "\x17o"], "\x9e" => [104, "\x17o"], "\x9f" => [16, "\x17o"], "\xa0" => [94, "\x17s"], "\xa1" => [76, "\x17s"], "\xa2" => [104, "\x17s"], "\xa3" => [16, "\x17s"], "\xa4" => [94, "\x17t"], "\xa5" => [76, "\x17t"], "\xa6" => [104, "\x17t"], "\xa7" => [16, "\x17t"], "\xa8" => [77, "\x17 "], "\xa9" => [18, "\x17 "], "\xaa" => [77, "\x17%"], "\xab" => [18, "\x17%"], "\xac" => [77, "\x17-"], "\xad" => [18, "\x17-"], "\xae" => [77, "\x17."], "\xaf" => [18, "\x17."], "\xb0" => [77, "\x17/"], "\xb1" => [18, "\x17/"], "\xb2" => [77, "\x173"], "\xb3" => [18, "\x173"], "\xb4" => [77, "\x174"], "\xb5" => [18, "\x174"], "\xb6" => [77, "\x175"], "\xb7" => [18, "\x175"], "\xb8" => [77, "\x176"], "\xb9" => [18, "\x176"], "\xba" => [77, "\x177"], "\xbb" => [18, "\x177"], "\xbc" => [77, "\x178"], "\xbd" => [18, "\x178"], "\xbe" => [77, "\x179"], "\xbf" => [18, "\x179"], "\xc0" => [77, "\x17="], "\xc1" => [18, "\x17="], "\xc2" => [77, "\x17A"], "\xc3" => [18, "\x17A"], "\xc4" => [77, "\x17_"], "\xc5" => [18, "\x17_"], "\xc6" => [77, "\x17b"], "\xc7" => [18, "\x17b"], "\xc8" => [77, "\x17d"], "\xc9" => [18, "\x17d"], "\xca" => [77, "\x17f"], "\xcb" => [18, "\x17f"], "\xcc" => [77, "\x17g"], "\xcd" => [18, "\x17g"], "\xce" => [77, "\x17h"], "\xcf" => [18, "\x17h"], "\xd0" => [77, "\x17l"], "\xd1" => [18, "\x17l"], "\xd2" => [77, "\x17m"], "\xd3" => [18, "\x17m"], "\xd4" => [77, "\x17n"], "\xd5" => [18, "\x17n"], "\xd6" => [77, "\x17p"], "\xd7" => [18, "\x17p"], "\xd8" => [77, "\x17r"], "\xd9" => [18, "\x17r"], "\xda" => [77, "\x17u"], "\xdb" => [18, "\x17u"], "\xdc" => [0, "\x17:"], "\xdd" => [0, "\x17B"], "\xde" => [0, "\x17C"], "\xdf" => [0, "\x17D"], "\xe0" => [0, "\x17E"], "\xe1" => [0, "\x17F"], "\xe2" => [0, "\x17G"], "\xe3" => [0, "\x17H"], "\xe4" => [0, "\x17I"], "\xe5" => [0, "\x17J"], "\xe6" => [0, "\x17K"], "\xe7" => [0, "\x17L"], "\xe8" => [0, "\x17M"], "\xe9" => [0, "\x17N"], "\xea" => [0, "\x17O"], "\xeb" => [0, "\x17P"], "\xec" => [0, "\x17Q"], "\xed" => [0, "\x17R"], "\xee" => [0, "\x17S"], "\xef" => [0, "\x17T"], "\xf0" => [0, "\x17U"], "\xf1" => [0, "\x17V"], "\xf2" => [0, "\x17W"], "\xf3" => [0, "\x17Y"], "\xf4" => [0, "\x17j"], "\xf5" => [0, "\x17k"], "\xf6" => [0, "\x17q"], "\xf7" => [0, "\x17v"], "\xf8" => [0, "\x17w"], "\xf9" => [0, "\x17x"], "\xfa" => [0, "\x17y"], "\xfb" => [0, "\x17z"], "\xfc" => [82, "\x17"], "\xfd" => [87, "\x17"], "\xfe" => [130, "\x17"], "\xff" => [9, "\x17"]], ["\x00" => [94, "\x160"], "\x01" => [76, "\x160"], "\x02" => [104, "\x160"], "\x03" => [16, "\x160"], "\x04" => [94, "\x161"], "\x05" => [76, "\x161"], "\x06" => [104, "\x161"], "\x07" => [16, "\x161"], "\x08" => [94, "\x162"], "\t" => [76, "\x162"], "\n" => [104, "\x162"], "\v" => [16, "\x162"], "\f" => [94, "\x16a"], "\r" => [76, "\x16a"], "\x0e" => [104, "\x16a"], "\x0f" => [16, "\x16a"], "\x10" => [94, "\x16c"], "\x11" => [76, "\x16c"], "\x12" => [104, "\x16c"], "\x13" => [16, "\x16c"], "\x14" => [94, "\x16e"], "\x15" => [76, "\x16e"], "\x16" => [104, "\x16e"], "\x17" => [16, "\x16e"], "\x18" => [94, "\x16i"], "\x19" => [76, "\x16i"], "\x1a" => [104, "\x16i"], "\x1b" => [16, "\x16i"], "\x1c" => [94, "\x16o"], "\x1d" => [76, "\x16o"], "\x1e" => [104, "\x16o"], "\x1f" => [16, "\x16o"], " " => [94, "\x16s"], "!" => [76, "\x16s"], "\"" => [104, "\x16s"], "#" => [16, "\x16s"], "\$" => [94, "\x16t"], "%" => [76, "\x16t"], "&" => [104, "\x16t"], "'" => [16, "\x16t"], "(" => [77, "\x16 "], ")" => [18, "\x16 "], "*" => [77, "\x16%"], "+" => [18, "\x16%"], "," => [77, "\x16-"], "-" => [18, "\x16-"], "." => [77, "\x16."], "/" => [18, "\x16."], [77, "\x16/"], [18, "\x16/"], [77, "\x163"], [18, "\x163"], [77, "\x164"], [18, "\x164"], [77, "\x165"], [18, "\x165"], [77, "\x166"], [18, "\x166"], ":" => [77, "\x167"], ";" => [18, "\x167"], "<" => [77, "\x168"], "=" => [18, "\x168"], ">" => [77, "\x169"], "?" => [18, "\x169"], "@" => [77, "\x16="], "A" => [18, "\x16="], "B" => [77, "\x16A"], "C" => [18, "\x16A"], "D" => [77, "\x16_"], "E" => [18, "\x16_"], "F" => [77, "\x16b"], "G" => [18, "\x16b"], "H" => [77, "\x16d"], "I" => [18, "\x16d"], "J" => [77, "\x16f"], "K" => [18, "\x16f"], "L" => [77, "\x16g"], "M" => [18, "\x16g"], "N" => [77, "\x16h"], "O" => [18, "\x16h"], "P" => [77, "\x16l"], "Q" => [18, "\x16l"], "R" => [77, "\x16m"], "S" => [18, "\x16m"], "T" => [77, "\x16n"], "U" => [18, "\x16n"], "V" => [77, "\x16p"], "W" => [18, "\x16p"], "X" => [77, "\x16r"], "Y" => [18, "\x16r"], "Z" => [77, "\x16u"], "[" => [18, "\x16u"], "\\" => [0, "\x16:"], "]" => [0, "\x16B"], "^" => [0, "\x16C"], "_" => [0, "\x16D"], "`" => [0, "\x16E"], "a" => [0, "\x16F"], "b" => [0, "\x16G"], "c" => [0, "\x16H"], "d" => [0, "\x16I"], "e" => [0, "\x16J"], "f" => [0, "\x16K"], "g" => [0, "\x16L"], "h" => [0, "\x16M"], "i" => [0, "\x16N"], "j" => [0, "\x16O"], "k" => [0, "\x16P"], "l" => [0, "\x16Q"], "m" => [0, "\x16R"], "n" => [0, "\x16S"], "o" => [0, "\x16T"], "p" => [0, "\x16U"], "q" => [0, "\x16V"], "r" => [0, "\x16W"], "s" => [0, "\x16Y"], "t" => [0, "\x16j"], "u" => [0, "\x16k"], "v" => [0, "\x16q"], "w" => [0, "\x16v"], "x" => [0, "\x16w"], "y" => [0, "\x16x"], "z" => [0, "\x16y"], "{" => [0, "\x16z"], "|" => [82, "\x16"], "}" => [87, "\x16"], "~" => [130, "\x16"], "" => [9, "\x16"], "\x80" => [94, ""], "\x81" => [76, ""], "\x82" => [104, ""], "\x83" => [16, ""], "\x84" => [94, ""], "\x85" => [76, ""], "\x86" => [104, ""], "\x87" => [16, ""], "\x88" => [94, ""], "\x89" => [76, ""], "\x8a" => [104, ""], "\x8b" => [16, ""], "\x8c" => [94, ""], "\x8d" => [76, ""], "\x8e" => [104, ""], "\x8f" => [16, ""], "\x90" => [94, ""], "\x91" => [76, ""], "\x92" => [104, ""], "\x93" => [16, ""], "\x94" => [94, ""], "\x95" => [76, ""], "\x96" => [104, ""], "\x97" => [16, ""], "\x98" => [94, ""], "\x99" => [76, ""], "\x9a" => [104, ""], "\x9b" => [16, ""], "\x9c" => [94, ""], "\x9d" => [76, ""], "\x9e" => [104, ""], "\x9f" => [16, ""], "\xa0" => [94, ""], "\xa1" => [76, ""], "\xa2" => [104, ""], "\xa3" => [16, ""], "\xa4" => [94, ""], "\xa5" => [76, ""], "\xa6" => [104, ""], "\xa7" => [16, ""], "\xa8" => [77, ""], "\xa9" => [18, ""], "\xaa" => [77, ""], "\xab" => [18, ""], "\xac" => [77, ""], "\xad" => [18, ""], "\xae" => [77, ""], "\xaf" => [18, ""], "\xb0" => [77, ""], "\xb1" => [18, ""], "\xb2" => [77, ""], "\xb3" => [18, ""], "\xb4" => [77, ""], "\xb5" => [18, ""], "\xb6" => [77, ""], "\xb7" => [18, ""], "\xb8" => [77, ""], "\xb9" => [18, ""], "\xba" => [77, ""], "\xbb" => [18, ""], "\xbc" => [77, ""], "\xbd" => [18, ""], "\xbe" => [77, ""], "\xbf" => [18, ""], "\xc0" => [77, ""], "\xc1" => [18, ""], "\xc2" => [77, ""], "\xc3" => [18, ""], "\xc4" => [77, ""], "\xc5" => [18, ""], "\xc6" => [77, ""], "\xc7" => [18, ""], "\xc8" => [77, ""], "\xc9" => [18, ""], "\xca" => [77, ""], "\xcb" => [18, ""], "\xcc" => [77, ""], "\xcd" => [18, ""], "\xce" => [77, ""], "\xcf" => [18, ""], "\xd0" => [77, ""], "\xd1" => [18, ""], "\xd2" => [77, ""], "\xd3" => [18, ""], "\xd4" => [77, ""], "\xd5" => [18, ""], "\xd6" => [77, ""], "\xd7" => [18, ""], "\xd8" => [77, ""], "\xd9" => [18, ""], "\xda" => [77, ""], "\xdb" => [18, ""], "\xdc" => [0, ""], "\xdd" => [0, ""], "\xde" => [0, ""], "\xdf" => [0, ""], "\xe0" => [0, ""], "\xe1" => [0, ""], "\xe2" => [0, ""], "\xe3" => [0, ""], "\xe4" => [0, ""], "\xe5" => [0, ""], "\xe6" => [0, ""], "\xe7" => [0, ""], "\xe8" => [0, ""], "\xe9" => [0, ""], "\xea" => [0, ""], "\xeb" => [0, ""], "\xec" => [0, ""], "\xed" => [0, ""], "\xee" => [0, ""], "\xef" => [0, ""], "\xf0" => [0, ""], "\xf1" => [0, ""], "\xf2" => [0, ""], "\xf3" => [0, ""], "\xf4" => [0, ""], "\xf5" => [0, ""], "\xf6" => [0, ""], "\xf7" => [0, ""], "\xf8" => [0, ""], "\xf9" => [0, ""], "\xfa" => [0, ""], "\xfb" => [0, ""], "\xfc" => [82, ""], "\xfd" => [87, ""], "\xfe" => [130, ""], "\xff" => [9, ""]], ["\x00" => [94, "\x180"], "\x01" => [76, "\x180"], "\x02" => [104, "\x180"], "\x03" => [16, "\x180"], "\x04" => [94, "\x181"], "\x05" => [76, "\x181"], "\x06" => [104, "\x181"], "\x07" => [16, "\x181"], "\x08" => [94, "\x182"], "\t" => [76, "\x182"], "\n" => [104, "\x182"], "\v" => [16, "\x182"], "\f" => [94, "\x18a"], "\r" => [76, "\x18a"], "\x0e" => [104, "\x18a"], "\x0f" => [16, "\x18a"], "\x10" => [94, "\x18c"], "\x11" => [76, "\x18c"], "\x12" => [104, "\x18c"], "\x13" => [16, "\x18c"], "\x14" => [94, "\x18e"], "\x15" => [76, "\x18e"], "\x16" => [104, "\x18e"], "\x17" => [16, "\x18e"], "\x18" => [94, "\x18i"], "\x19" => [76, "\x18i"], "\x1a" => [104, "\x18i"], "\x1b" => [16, "\x18i"], "\x1c" => [94, "\x18o"], "\x1d" => [76, "\x18o"], "\x1e" => [104, "\x18o"], "\x1f" => [16, "\x18o"], " " => [94, "\x18s"], "!" => [76, "\x18s"], "\"" => [104, "\x18s"], "#" => [16, "\x18s"], "\$" => [94, "\x18t"], "%" => [76, "\x18t"], "&" => [104, "\x18t"], "'" => [16, "\x18t"], "(" => [77, "\x18 "], ")" => [18, "\x18 "], "*" => [77, "\x18%"], "+" => [18, "\x18%"], "," => [77, "\x18-"], "-" => [18, "\x18-"], "." => [77, "\x18."], "/" => [18, "\x18."], [77, "\x18/"], [18, "\x18/"], [77, "\x183"], [18, "\x183"], [77, "\x184"], [18, "\x184"], [77, "\x185"], [18, "\x185"], [77, "\x186"], [18, "\x186"], ":" => [77, "\x187"], ";" => [18, "\x187"], "<" => [77, "\x188"], "=" => [18, "\x188"], ">" => [77, "\x189"], "?" => [18, "\x189"], "@" => [77, "\x18="], "A" => [18, "\x18="], "B" => [77, "\x18A"], "C" => [18, "\x18A"], "D" => [77, "\x18_"], "E" => [18, "\x18_"], "F" => [77, "\x18b"], "G" => [18, "\x18b"], "H" => [77, "\x18d"], "I" => [18, "\x18d"], "J" => [77, "\x18f"], "K" => [18, "\x18f"], "L" => [77, "\x18g"], "M" => [18, "\x18g"], "N" => [77, "\x18h"], "O" => [18, "\x18h"], "P" => [77, "\x18l"], "Q" => [18, "\x18l"], "R" => [77, "\x18m"], "S" => [18, "\x18m"], "T" => [77, "\x18n"], "U" => [18, "\x18n"], "V" => [77, "\x18p"], "W" => [18, "\x18p"], "X" => [77, "\x18r"], "Y" => [18, "\x18r"], "Z" => [77, "\x18u"], "[" => [18, "\x18u"], "\\" => [0, "\x18:"], "]" => [0, "\x18B"], "^" => [0, "\x18C"], "_" => [0, "\x18D"], "`" => [0, "\x18E"], "a" => [0, "\x18F"], "b" => [0, "\x18G"], "c" => [0, "\x18H"], "d" => [0, "\x18I"], "e" => [0, "\x18J"], "f" => [0, "\x18K"], "g" => [0, "\x18L"], "h" => [0, "\x18M"], "i" => [0, "\x18N"], "j" => [0, "\x18O"], "k" => [0, "\x18P"], "l" => [0, "\x18Q"], "m" => [0, "\x18R"], "n" => [0, "\x18S"], "o" => [0, "\x18T"], "p" => [0, "\x18U"], "q" => [0, "\x18V"], "r" => [0, "\x18W"], "s" => [0, "\x18Y"], "t" => [0, "\x18j"], "u" => [0, "\x18k"], "v" => [0, "\x18q"], "w" => [0, "\x18v"], "x" => [0, "\x18w"], "y" => [0, "\x18x"], "z" => [0, "\x18y"], "{" => [0, "\x18z"], "|" => [82, "\x18"], "}" => [87, "\x18"], "~" => [130, "\x18"], "" => [9, "\x18"], "\x80" => [94, "\x190"], "\x81" => [76, "\x190"], "\x82" => [104, "\x190"], "\x83" => [16, "\x190"], "\x84" => [94, "\x191"], "\x85" => [76, "\x191"], "\x86" => [104, "\x191"], "\x87" => [16, "\x191"], "\x88" => [94, "\x192"], "\x89" => [76, "\x192"], "\x8a" => [104, "\x192"], "\x8b" => [16, "\x192"], "\x8c" => [94, "\x19a"], "\x8d" => [76, "\x19a"], "\x8e" => [104, "\x19a"], "\x8f" => [16, "\x19a"], "\x90" => [94, "\x19c"], "\x91" => [76, "\x19c"], "\x92" => [104, "\x19c"], "\x93" => [16, "\x19c"], "\x94" => [94, "\x19e"], "\x95" => [76, "\x19e"], "\x96" => [104, "\x19e"], "\x97" => [16, "\x19e"], "\x98" => [94, "\x19i"], "\x99" => [76, "\x19i"], "\x9a" => [104, "\x19i"], "\x9b" => [16, "\x19i"], "\x9c" => [94, "\x19o"], "\x9d" => [76, "\x19o"], "\x9e" => [104, "\x19o"], "\x9f" => [16, "\x19o"], "\xa0" => [94, "\x19s"], "\xa1" => [76, "\x19s"], "\xa2" => [104, "\x19s"], "\xa3" => [16, "\x19s"], "\xa4" => [94, "\x19t"], "\xa5" => [76, "\x19t"], "\xa6" => [104, "\x19t"], "\xa7" => [16, "\x19t"], "\xa8" => [77, "\x19 "], "\xa9" => [18, "\x19 "], "\xaa" => [77, "\x19%"], "\xab" => [18, "\x19%"], "\xac" => [77, "\x19-"], "\xad" => [18, "\x19-"], "\xae" => [77, "\x19."], "\xaf" => [18, "\x19."], "\xb0" => [77, "\x19/"], "\xb1" => [18, "\x19/"], "\xb2" => [77, "\x193"], "\xb3" => [18, "\x193"], "\xb4" => [77, "\x194"], "\xb5" => [18, "\x194"], "\xb6" => [77, "\x195"], "\xb7" => [18, "\x195"], "\xb8" => [77, "\x196"], "\xb9" => [18, "\x196"], "\xba" => [77, "\x197"], "\xbb" => [18, "\x197"], "\xbc" => [77, "\x198"], "\xbd" => [18, "\x198"], "\xbe" => [77, "\x199"], "\xbf" => [18, "\x199"], "\xc0" => [77, "\x19="], "\xc1" => [18, "\x19="], "\xc2" => [77, "\x19A"], "\xc3" => [18, "\x19A"], "\xc4" => [77, "\x19_"], "\xc5" => [18, "\x19_"], "\xc6" => [77, "\x19b"], "\xc7" => [18, "\x19b"], "\xc8" => [77, "\x19d"], "\xc9" => [18, "\x19d"], "\xca" => [77, "\x19f"], "\xcb" => [18, "\x19f"], "\xcc" => [77, "\x19g"], "\xcd" => [18, "\x19g"], "\xce" => [77, "\x19h"], "\xcf" => [18, "\x19h"], "\xd0" => [77, "\x19l"], "\xd1" => [18, "\x19l"], "\xd2" => [77, "\x19m"], "\xd3" => [18, "\x19m"], "\xd4" => [77, "\x19n"], "\xd5" => [18, "\x19n"], "\xd6" => [77, "\x19p"], "\xd7" => [18, "\x19p"], "\xd8" => [77, "\x19r"], "\xd9" => [18, "\x19r"], "\xda" => [77, "\x19u"], "\xdb" => [18, "\x19u"], "\xdc" => [0, "\x19:"], "\xdd" => [0, "\x19B"], "\xde" => [0, "\x19C"], "\xdf" => [0, "\x19D"], "\xe0" => [0, "\x19E"], "\xe1" => [0, "\x19F"], "\xe2" => [0, "\x19G"], "\xe3" => [0, "\x19H"], "\xe4" => [0, "\x19I"], "\xe5" => [0, "\x19J"], "\xe6" => [0, "\x19K"], "\xe7" => [0, "\x19L"], "\xe8" => [0, "\x19M"], "\xe9" => [0, "\x19N"], "\xea" => [0, "\x19O"], "\xeb" => [0, "\x19P"], "\xec" => [0, "\x19Q"], "\xed" => [0, "\x19R"], "\xee" => [0, "\x19S"], "\xef" => [0, "\x19T"], "\xf0" => [0, "\x19U"], "\xf1" => [0, "\x19V"], "\xf2" => [0, "\x19W"], "\xf3" => [0, "\x19Y"], "\xf4" => [0, "\x19j"], "\xf5" => [0, "\x19k"], "\xf6" => [0, "\x19q"], "\xf7" => [0, "\x19v"], "\xf8" => [0, "\x19w"], "\xf9" => [0, "\x19x"], "\xfa" => [0, "\x19y"], "\xfb" => [0, "\x19z"], "\xfc" => [82, "\x19"], "\xfd" => [87, "\x19"], "\xfe" => [130, "\x19"], "\xff" => [9, "\x19"]], ["\x00" => [77, "\x180"], "\x01" => [18, "\x180"], "\x02" => [77, "\x181"], "\x03" => [18, "\x181"], "\x04" => [77, "\x182"], "\x05" => [18, "\x182"], "\x06" => [77, "\x18a"], "\x07" => [18, "\x18a"], "\x08" => [77, "\x18c"], "\t" => [18, "\x18c"], "\n" => [77, "\x18e"], "\v" => [18, "\x18e"], "\f" => [77, "\x18i"], "\r" => [18, "\x18i"], "\x0e" => [77, "\x18o"], "\x0f" => [18, "\x18o"], "\x10" => [77, "\x18s"], "\x11" => [18, "\x18s"], "\x12" => [77, "\x18t"], "\x13" => [18, "\x18t"], "\x14" => [0, "\x18 "], "\x15" => [0, "\x18%"], "\x16" => [0, "\x18-"], "\x17" => [0, "\x18."], "\x18" => [0, "\x18/"], "\x19" => [0, "\x183"], "\x1a" => [0, "\x184"], "\x1b" => [0, "\x185"], "\x1c" => [0, "\x186"], "\x1d" => [0, "\x187"], "\x1e" => [0, "\x188"], "\x1f" => [0, "\x189"], " " => [0, "\x18="], "!" => [0, "\x18A"], "\"" => [0, "\x18_"], "#" => [0, "\x18b"], "\$" => [0, "\x18d"], "%" => [0, "\x18f"], "&" => [0, "\x18g"], "'" => [0, "\x18h"], "(" => [0, "\x18l"], ")" => [0, "\x18m"], "*" => [0, "\x18n"], "+" => [0, "\x18p"], "," => [0, "\x18r"], "-" => [0, "\x18u"], "." => [100, "\x18"], "/" => [110, "\x18"], [111, "\x18"], [115, "\x18"], [116, "\x18"], [118, "\x18"], [119, "\x18"], [122, "\x18"], [123, "\x18"], [125, "\x18"], [126, "\x18"], [129, "\x18"], ":" => [143, "\x18"], ";" => [148, "\x18"], "<" => [151, "\x18"], "=" => [153, "\x18"], ">" => [83, "\x18"], "?" => [10, "\x18"], "@" => [77, "\x190"], "A" => [18, "\x190"], "B" => [77, "\x191"], "C" => [18, "\x191"], "D" => [77, "\x192"], "E" => [18, "\x192"], "F" => [77, "\x19a"], "G" => [18, "\x19a"], "H" => [77, "\x19c"], "I" => [18, "\x19c"], "J" => [77, "\x19e"], "K" => [18, "\x19e"], "L" => [77, "\x19i"], "M" => [18, "\x19i"], "N" => [77, "\x19o"], "O" => [18, "\x19o"], "P" => [77, "\x19s"], "Q" => [18, "\x19s"], "R" => [77, "\x19t"], "S" => [18, "\x19t"], "T" => [0, "\x19 "], "U" => [0, "\x19%"], "V" => [0, "\x19-"], "W" => [0, "\x19."], "X" => [0, "\x19/"], "Y" => [0, "\x193"], "Z" => [0, "\x194"], "[" => [0, "\x195"], "\\" => [0, "\x196"], "]" => [0, "\x197"], "^" => [0, "\x198"], "_" => [0, "\x199"], "`" => [0, "\x19="], "a" => [0, "\x19A"], "b" => [0, "\x19_"], "c" => [0, "\x19b"], "d" => [0, "\x19d"], "e" => [0, "\x19f"], "f" => [0, "\x19g"], "g" => [0, "\x19h"], "h" => [0, "\x19l"], "i" => [0, "\x19m"], "j" => [0, "\x19n"], "k" => [0, "\x19p"], "l" => [0, "\x19r"], "m" => [0, "\x19u"], "n" => [100, "\x19"], "o" => [110, "\x19"], "p" => [111, "\x19"], "q" => [115, "\x19"], "r" => [116, "\x19"], "s" => [118, "\x19"], "t" => [119, "\x19"], "u" => [122, "\x19"], "v" => [123, "\x19"], "w" => [125, "\x19"], "x" => [126, "\x19"], "y" => [129, "\x19"], "z" => [143, "\x19"], "{" => [148, "\x19"], "|" => [151, "\x19"], "}" => [153, "\x19"], "~" => [83, "\x19"], "" => [10, "\x19"], "\x80" => [77, "\x1a0"], "\x81" => [18, "\x1a0"], "\x82" => [77, "\x1a1"], "\x83" => [18, "\x1a1"], "\x84" => [77, "\x1a2"], "\x85" => [18, "\x1a2"], "\x86" => [77, "\x1aa"], "\x87" => [18, "\x1aa"], "\x88" => [77, "\x1ac"], "\x89" => [18, "\x1ac"], "\x8a" => [77, "\x1ae"], "\x8b" => [18, "\x1ae"], "\x8c" => [77, "\x1ai"], "\x8d" => [18, "\x1ai"], "\x8e" => [77, "\x1ao"], "\x8f" => [18, "\x1ao"], "\x90" => [77, "\x1as"], "\x91" => [18, "\x1as"], "\x92" => [77, "\x1at"], "\x93" => [18, "\x1at"], "\x94" => [0, "\x1a "], "\x95" => [0, "\x1a%"], "\x96" => [0, "\x1a-"], "\x97" => [0, "\x1a."], "\x98" => [0, "\x1a/"], "\x99" => [0, "\x1a3"], "\x9a" => [0, "\x1a4"], "\x9b" => [0, "\x1a5"], "\x9c" => [0, "\x1a6"], "\x9d" => [0, "\x1a7"], "\x9e" => [0, "\x1a8"], "\x9f" => [0, "\x1a9"], "\xa0" => [0, "\x1a="], "\xa1" => [0, "\x1aA"], "\xa2" => [0, "\x1a_"], "\xa3" => [0, "\x1ab"], "\xa4" => [0, "\x1ad"], "\xa5" => [0, "\x1af"], "\xa6" => [0, "\x1ag"], "\xa7" => [0, "\x1ah"], "\xa8" => [0, "\x1al"], "\xa9" => [0, "\x1am"], "\xaa" => [0, "\x1an"], "\xab" => [0, "\x1ap"], "\xac" => [0, "\x1ar"], "\xad" => [0, "\x1au"], "\xae" => [100, "\x1a"], "\xaf" => [110, "\x1a"], "\xb0" => [111, "\x1a"], "\xb1" => [115, "\x1a"], "\xb2" => [116, "\x1a"], "\xb3" => [118, "\x1a"], "\xb4" => [119, "\x1a"], "\xb5" => [122, "\x1a"], "\xb6" => [123, "\x1a"], "\xb7" => [125, "\x1a"], "\xb8" => [126, "\x1a"], "\xb9" => [129, "\x1a"], "\xba" => [143, "\x1a"], "\xbb" => [148, "\x1a"], "\xbc" => [151, "\x1a"], "\xbd" => [153, "\x1a"], "\xbe" => [83, "\x1a"], "\xbf" => [10, "\x1a"], "\xc0" => [77, "\x1b0"], "\xc1" => [18, "\x1b0"], "\xc2" => [77, "\x1b1"], "\xc3" => [18, "\x1b1"], "\xc4" => [77, "\x1b2"], "\xc5" => [18, "\x1b2"], "\xc6" => [77, "\x1ba"], "\xc7" => [18, "\x1ba"], "\xc8" => [77, "\x1bc"], "\xc9" => [18, "\x1bc"], "\xca" => [77, "\x1be"], "\xcb" => [18, "\x1be"], "\xcc" => [77, "\x1bi"], "\xcd" => [18, "\x1bi"], "\xce" => [77, "\x1bo"], "\xcf" => [18, "\x1bo"], "\xd0" => [77, "\x1bs"], "\xd1" => [18, "\x1bs"], "\xd2" => [77, "\x1bt"], "\xd3" => [18, "\x1bt"], "\xd4" => [0, "\x1b "], "\xd5" => [0, "\x1b%"], "\xd6" => [0, "\x1b-"], "\xd7" => [0, "\x1b."], "\xd8" => [0, "\x1b/"], "\xd9" => [0, "\x1b3"], "\xda" => [0, "\x1b4"], "\xdb" => [0, "\x1b5"], "\xdc" => [0, "\x1b6"], "\xdd" => [0, "\x1b7"], "\xde" => [0, "\x1b8"], "\xdf" => [0, "\x1b9"], "\xe0" => [0, "\x1b="], "\xe1" => [0, "\x1bA"], "\xe2" => [0, "\x1b_"], "\xe3" => [0, "\x1bb"], "\xe4" => [0, "\x1bd"], "\xe5" => [0, "\x1bf"], "\xe6" => [0, "\x1bg"], "\xe7" => [0, "\x1bh"], "\xe8" => [0, "\x1bl"], "\xe9" => [0, "\x1bm"], "\xea" => [0, "\x1bn"], "\xeb" => [0, "\x1bp"], "\xec" => [0, "\x1br"], "\xed" => [0, "\x1bu"], "\xee" => [100, "\x1b"], "\xef" => [110, "\x1b"], "\xf0" => [111, "\x1b"], "\xf1" => [115, "\x1b"], "\xf2" => [116, "\x1b"], "\xf3" => [118, "\x1b"], "\xf4" => [119, "\x1b"], "\xf5" => [122, "\x1b"], "\xf6" => [123, "\x1b"], "\xf7" => [125, "\x1b"], "\xf8" => [126, "\x1b"], "\xf9" => [129, "\x1b"], "\xfa" => [143, "\x1b"], "\xfb" => [148, "\x1b"], "\xfc" => [151, "\x1b"], "\xfd" => [153, "\x1b"], "\xfe" => [83, "\x1b"], "\xff" => [10, "\x1b"]], ["\x00" => [94, "\x1a0"], "\x01" => [76, "\x1a0"], "\x02" => [104, "\x1a0"], "\x03" => [16, "\x1a0"], "\x04" => [94, "\x1a1"], "\x05" => [76, "\x1a1"], "\x06" => [104, "\x1a1"], "\x07" => [16, "\x1a1"], "\x08" => [94, "\x1a2"], "\t" => [76, "\x1a2"], "\n" => [104, "\x1a2"], "\v" => [16, "\x1a2"], "\f" => [94, "\x1aa"], "\r" => [76, "\x1aa"], "\x0e" => [104, "\x1aa"], "\x0f" => [16, "\x1aa"], "\x10" => [94, "\x1ac"], "\x11" => [76, "\x1ac"], "\x12" => [104, "\x1ac"], "\x13" => [16, "\x1ac"], "\x14" => [94, "\x1ae"], "\x15" => [76, "\x1ae"], "\x16" => [104, "\x1ae"], "\x17" => [16, "\x1ae"], "\x18" => [94, "\x1ai"], "\x19" => [76, "\x1ai"], "\x1a" => [104, "\x1ai"], "\x1b" => [16, "\x1ai"], "\x1c" => [94, "\x1ao"], "\x1d" => [76, "\x1ao"], "\x1e" => [104, "\x1ao"], "\x1f" => [16, "\x1ao"], " " => [94, "\x1as"], "!" => [76, "\x1as"], "\"" => [104, "\x1as"], "#" => [16, "\x1as"], "\$" => [94, "\x1at"], "%" => [76, "\x1at"], "&" => [104, "\x1at"], "'" => [16, "\x1at"], "(" => [77, "\x1a "], ")" => [18, "\x1a "], "*" => [77, "\x1a%"], "+" => [18, "\x1a%"], "," => [77, "\x1a-"], "-" => [18, "\x1a-"], "." => [77, "\x1a."], "/" => [18, "\x1a."], [77, "\x1a/"], [18, "\x1a/"], [77, "\x1a3"], [18, "\x1a3"], [77, "\x1a4"], [18, "\x1a4"], [77, "\x1a5"], [18, "\x1a5"], [77, "\x1a6"], [18, "\x1a6"], ":" => [77, "\x1a7"], ";" => [18, "\x1a7"], "<" => [77, "\x1a8"], "=" => [18, "\x1a8"], ">" => [77, "\x1a9"], "?" => [18, "\x1a9"], "@" => [77, "\x1a="], "A" => [18, "\x1a="], "B" => [77, "\x1aA"], "C" => [18, "\x1aA"], "D" => [77, "\x1a_"], "E" => [18, "\x1a_"], "F" => [77, "\x1ab"], "G" => [18, "\x1ab"], "H" => [77, "\x1ad"], "I" => [18, "\x1ad"], "J" => [77, "\x1af"], "K" => [18, "\x1af"], "L" => [77, "\x1ag"], "M" => [18, "\x1ag"], "N" => [77, "\x1ah"], "O" => [18, "\x1ah"], "P" => [77, "\x1al"], "Q" => [18, "\x1al"], "R" => [77, "\x1am"], "S" => [18, "\x1am"], "T" => [77, "\x1an"], "U" => [18, "\x1an"], "V" => [77, "\x1ap"], "W" => [18, "\x1ap"], "X" => [77, "\x1ar"], "Y" => [18, "\x1ar"], "Z" => [77, "\x1au"], "[" => [18, "\x1au"], "\\" => [0, "\x1a:"], "]" => [0, "\x1aB"], "^" => [0, "\x1aC"], "_" => [0, "\x1aD"], "`" => [0, "\x1aE"], "a" => [0, "\x1aF"], "b" => [0, "\x1aG"], "c" => [0, "\x1aH"], "d" => [0, "\x1aI"], "e" => [0, "\x1aJ"], "f" => [0, "\x1aK"], "g" => [0, "\x1aL"], "h" => [0, "\x1aM"], "i" => [0, "\x1aN"], "j" => [0, "\x1aO"], "k" => [0, "\x1aP"], "l" => [0, "\x1aQ"], "m" => [0, "\x1aR"], "n" => [0, "\x1aS"], "o" => [0, "\x1aT"], "p" => [0, "\x1aU"], "q" => [0, "\x1aV"], "r" => [0, "\x1aW"], "s" => [0, "\x1aY"], "t" => [0, "\x1aj"], "u" => [0, "\x1ak"], "v" => [0, "\x1aq"], "w" => [0, "\x1av"], "x" => [0, "\x1aw"], "y" => [0, "\x1ax"], "z" => [0, "\x1ay"], "{" => [0, "\x1az"], "|" => [82, "\x1a"], "}" => [87, "\x1a"], "~" => [130, "\x1a"], "" => [9, "\x1a"], "\x80" => [94, "\x1b0"], "\x81" => [76, "\x1b0"], "\x82" => [104, "\x1b0"], "\x83" => [16, "\x1b0"], "\x84" => [94, "\x1b1"], "\x85" => [76, "\x1b1"], "\x86" => [104, "\x1b1"], "\x87" => [16, "\x1b1"], "\x88" => [94, "\x1b2"], "\x89" => [76, "\x1b2"], "\x8a" => [104, "\x1b2"], "\x8b" => [16, "\x1b2"], "\x8c" => [94, "\x1ba"], "\x8d" => [76, "\x1ba"], "\x8e" => [104, "\x1ba"], "\x8f" => [16, "\x1ba"], "\x90" => [94, "\x1bc"], "\x91" => [76, "\x1bc"], "\x92" => [104, "\x1bc"], "\x93" => [16, "\x1bc"], "\x94" => [94, "\x1be"], "\x95" => [76, "\x1be"], "\x96" => [104, "\x1be"], "\x97" => [16, "\x1be"], "\x98" => [94, "\x1bi"], "\x99" => [76, "\x1bi"], "\x9a" => [104, "\x1bi"], "\x9b" => [16, "\x1bi"], "\x9c" => [94, "\x1bo"], "\x9d" => [76, "\x1bo"], "\x9e" => [104, "\x1bo"], "\x9f" => [16, "\x1bo"], "\xa0" => [94, "\x1bs"], "\xa1" => [76, "\x1bs"], "\xa2" => [104, "\x1bs"], "\xa3" => [16, "\x1bs"], "\xa4" => [94, "\x1bt"], "\xa5" => [76, "\x1bt"], "\xa6" => [104, "\x1bt"], "\xa7" => [16, "\x1bt"], "\xa8" => [77, "\x1b "], "\xa9" => [18, "\x1b "], "\xaa" => [77, "\x1b%"], "\xab" => [18, "\x1b%"], "\xac" => [77, "\x1b-"], "\xad" => [18, "\x1b-"], "\xae" => [77, "\x1b."], "\xaf" => [18, "\x1b."], "\xb0" => [77, "\x1b/"], "\xb1" => [18, "\x1b/"], "\xb2" => [77, "\x1b3"], "\xb3" => [18, "\x1b3"], "\xb4" => [77, "\x1b4"], "\xb5" => [18, "\x1b4"], "\xb6" => [77, "\x1b5"], "\xb7" => [18, "\x1b5"], "\xb8" => [77, "\x1b6"], "\xb9" => [18, "\x1b6"], "\xba" => [77, "\x1b7"], "\xbb" => [18, "\x1b7"], "\xbc" => [77, "\x1b8"], "\xbd" => [18, "\x1b8"], "\xbe" => [77, "\x1b9"], "\xbf" => [18, "\x1b9"], "\xc0" => [77, "\x1b="], "\xc1" => [18, "\x1b="], "\xc2" => [77, "\x1bA"], "\xc3" => [18, "\x1bA"], "\xc4" => [77, "\x1b_"], "\xc5" => [18, "\x1b_"], "\xc6" => [77, "\x1bb"], "\xc7" => [18, "\x1bb"], "\xc8" => [77, "\x1bd"], "\xc9" => [18, "\x1bd"], "\xca" => [77, "\x1bf"], "\xcb" => [18, "\x1bf"], "\xcc" => [77, "\x1bg"], "\xcd" => [18, "\x1bg"], "\xce" => [77, "\x1bh"], "\xcf" => [18, "\x1bh"], "\xd0" => [77, "\x1bl"], "\xd1" => [18, "\x1bl"], "\xd2" => [77, "\x1bm"], "\xd3" => [18, "\x1bm"], "\xd4" => [77, "\x1bn"], "\xd5" => [18, "\x1bn"], "\xd6" => [77, "\x1bp"], "\xd7" => [18, "\x1bp"], "\xd8" => [77, "\x1br"], "\xd9" => [18, "\x1br"], "\xda" => [77, "\x1bu"], "\xdb" => [18, "\x1bu"], "\xdc" => [0, "\x1b:"], "\xdd" => [0, "\x1bB"], "\xde" => [0, "\x1bC"], "\xdf" => [0, "\x1bD"], "\xe0" => [0, "\x1bE"], "\xe1" => [0, "\x1bF"], "\xe2" => [0, "\x1bG"], "\xe3" => [0, "\x1bH"], "\xe4" => [0, "\x1bI"], "\xe5" => [0, "\x1bJ"], "\xe6" => [0, "\x1bK"], "\xe7" => [0, "\x1bL"], "\xe8" => [0, "\x1bM"], "\xe9" => [0, "\x1bN"], "\xea" => [0, "\x1bO"], "\xeb" => [0, "\x1bP"], "\xec" => [0, "\x1bQ"], "\xed" => [0, "\x1bR"], "\xee" => [0, "\x1bS"], "\xef" => [0, "\x1bT"], "\xf0" => [0, "\x1bU"], "\xf1" => [0, "\x1bV"], "\xf2" => [0, "\x1bW"], "\xf3" => [0, "\x1bY"], "\xf4" => [0, "\x1bj"], "\xf5" => [0, "\x1bk"], "\xf6" => [0, "\x1bq"], "\xf7" => [0, "\x1bv"], "\xf8" => [0, "\x1bw"], "\xf9" => [0, "\x1bx"], "\xfa" => [0, "\x1by"], "\xfb" => [0, "\x1bz"], "\xfc" => [82, "\x1b"], "\xfd" => [87, "\x1b"], "\xfe" => [130, "\x1b"], "\xff" => [9, "\x1b"]], ["\x00" => [94, "\x1c0"], "\x01" => [76, "\x1c0"], "\x02" => [104, "\x1c0"], "\x03" => [16, "\x1c0"], "\x04" => [94, "\x1c1"], "\x05" => [76, "\x1c1"], "\x06" => [104, "\x1c1"], "\x07" => [16, "\x1c1"], "\x08" => [94, "\x1c2"], "\t" => [76, "\x1c2"], "\n" => [104, "\x1c2"], "\v" => [16, "\x1c2"], "\f" => [94, "\x1ca"], "\r" => [76, "\x1ca"], "\x0e" => [104, "\x1ca"], "\x0f" => [16, "\x1ca"], "\x10" => [94, "\x1cc"], "\x11" => [76, "\x1cc"], "\x12" => [104, "\x1cc"], "\x13" => [16, "\x1cc"], "\x14" => [94, "\x1ce"], "\x15" => [76, "\x1ce"], "\x16" => [104, "\x1ce"], "\x17" => [16, "\x1ce"], "\x18" => [94, "\x1ci"], "\x19" => [76, "\x1ci"], "\x1a" => [104, "\x1ci"], "\x1b" => [16, "\x1ci"], "\x1c" => [94, "\x1co"], "\x1d" => [76, "\x1co"], "\x1e" => [104, "\x1co"], "\x1f" => [16, "\x1co"], " " => [94, "\x1cs"], "!" => [76, "\x1cs"], "\"" => [104, "\x1cs"], "#" => [16, "\x1cs"], "\$" => [94, "\x1ct"], "%" => [76, "\x1ct"], "&" => [104, "\x1ct"], "'" => [16, "\x1ct"], "(" => [77, "\x1c "], ")" => [18, "\x1c "], "*" => [77, "\x1c%"], "+" => [18, "\x1c%"], "," => [77, "\x1c-"], "-" => [18, "\x1c-"], "." => [77, "\x1c."], "/" => [18, "\x1c."], [77, "\x1c/"], [18, "\x1c/"], [77, "\x1c3"], [18, "\x1c3"], [77, "\x1c4"], [18, "\x1c4"], [77, "\x1c5"], [18, "\x1c5"], [77, "\x1c6"], [18, "\x1c6"], ":" => [77, "\x1c7"], ";" => [18, "\x1c7"], "<" => [77, "\x1c8"], "=" => [18, "\x1c8"], ">" => [77, "\x1c9"], "?" => [18, "\x1c9"], "@" => [77, "\x1c="], "A" => [18, "\x1c="], "B" => [77, "\x1cA"], "C" => [18, "\x1cA"], "D" => [77, "\x1c_"], "E" => [18, "\x1c_"], "F" => [77, "\x1cb"], "G" => [18, "\x1cb"], "H" => [77, "\x1cd"], "I" => [18, "\x1cd"], "J" => [77, "\x1cf"], "K" => [18, "\x1cf"], "L" => [77, "\x1cg"], "M" => [18, "\x1cg"], "N" => [77, "\x1ch"], "O" => [18, "\x1ch"], "P" => [77, "\x1cl"], "Q" => [18, "\x1cl"], "R" => [77, "\x1cm"], "S" => [18, "\x1cm"], "T" => [77, "\x1cn"], "U" => [18, "\x1cn"], "V" => [77, "\x1cp"], "W" => [18, "\x1cp"], "X" => [77, "\x1cr"], "Y" => [18, "\x1cr"], "Z" => [77, "\x1cu"], "[" => [18, "\x1cu"], "\\" => [0, "\x1c:"], "]" => [0, "\x1cB"], "^" => [0, "\x1cC"], "_" => [0, "\x1cD"], "`" => [0, "\x1cE"], "a" => [0, "\x1cF"], "b" => [0, "\x1cG"], "c" => [0, "\x1cH"], "d" => [0, "\x1cI"], "e" => [0, "\x1cJ"], "f" => [0, "\x1cK"], "g" => [0, "\x1cL"], "h" => [0, "\x1cM"], "i" => [0, "\x1cN"], "j" => [0, "\x1cO"], "k" => [0, "\x1cP"], "l" => [0, "\x1cQ"], "m" => [0, "\x1cR"], "n" => [0, "\x1cS"], "o" => [0, "\x1cT"], "p" => [0, "\x1cU"], "q" => [0, "\x1cV"], "r" => [0, "\x1cW"], "s" => [0, "\x1cY"], "t" => [0, "\x1cj"], "u" => [0, "\x1ck"], "v" => [0, "\x1cq"], "w" => [0, "\x1cv"], "x" => [0, "\x1cw"], "y" => [0, "\x1cx"], "z" => [0, "\x1cy"], "{" => [0, "\x1cz"], "|" => [82, "\x1c"], "}" => [87, "\x1c"], "~" => [130, "\x1c"], "" => [9, "\x1c"], "\x80" => [94, "\x1d0"], "\x81" => [76, "\x1d0"], "\x82" => [104, "\x1d0"], "\x83" => [16, "\x1d0"], "\x84" => [94, "\x1d1"], "\x85" => [76, "\x1d1"], "\x86" => [104, "\x1d1"], "\x87" => [16, "\x1d1"], "\x88" => [94, "\x1d2"], "\x89" => [76, "\x1d2"], "\x8a" => [104, "\x1d2"], "\x8b" => [16, "\x1d2"], "\x8c" => [94, "\x1da"], "\x8d" => [76, "\x1da"], "\x8e" => [104, "\x1da"], "\x8f" => [16, "\x1da"], "\x90" => [94, "\x1dc"], "\x91" => [76, "\x1dc"], "\x92" => [104, "\x1dc"], "\x93" => [16, "\x1dc"], "\x94" => [94, "\x1de"], "\x95" => [76, "\x1de"], "\x96" => [104, "\x1de"], "\x97" => [16, "\x1de"], "\x98" => [94, "\x1di"], "\x99" => [76, "\x1di"], "\x9a" => [104, "\x1di"], "\x9b" => [16, "\x1di"], "\x9c" => [94, "\x1do"], "\x9d" => [76, "\x1do"], "\x9e" => [104, "\x1do"], "\x9f" => [16, "\x1do"], "\xa0" => [94, "\x1ds"], "\xa1" => [76, "\x1ds"], "\xa2" => [104, "\x1ds"], "\xa3" => [16, "\x1ds"], "\xa4" => [94, "\x1dt"], "\xa5" => [76, "\x1dt"], "\xa6" => [104, "\x1dt"], "\xa7" => [16, "\x1dt"], "\xa8" => [77, "\x1d "], "\xa9" => [18, "\x1d "], "\xaa" => [77, "\x1d%"], "\xab" => [18, "\x1d%"], "\xac" => [77, "\x1d-"], "\xad" => [18, "\x1d-"], "\xae" => [77, "\x1d."], "\xaf" => [18, "\x1d."], "\xb0" => [77, "\x1d/"], "\xb1" => [18, "\x1d/"], "\xb2" => [77, "\x1d3"], "\xb3" => [18, "\x1d3"], "\xb4" => [77, "\x1d4"], "\xb5" => [18, "\x1d4"], "\xb6" => [77, "\x1d5"], "\xb7" => [18, "\x1d5"], "\xb8" => [77, "\x1d6"], "\xb9" => [18, "\x1d6"], "\xba" => [77, "\x1d7"], "\xbb" => [18, "\x1d7"], "\xbc" => [77, "\x1d8"], "\xbd" => [18, "\x1d8"], "\xbe" => [77, "\x1d9"], "\xbf" => [18, "\x1d9"], "\xc0" => [77, "\x1d="], "\xc1" => [18, "\x1d="], "\xc2" => [77, "\x1dA"], "\xc3" => [18, "\x1dA"], "\xc4" => [77, "\x1d_"], "\xc5" => [18, "\x1d_"], "\xc6" => [77, "\x1db"], "\xc7" => [18, "\x1db"], "\xc8" => [77, "\x1dd"], "\xc9" => [18, "\x1dd"], "\xca" => [77, "\x1df"], "\xcb" => [18, "\x1df"], "\xcc" => [77, "\x1dg"], "\xcd" => [18, "\x1dg"], "\xce" => [77, "\x1dh"], "\xcf" => [18, "\x1dh"], "\xd0" => [77, "\x1dl"], "\xd1" => [18, "\x1dl"], "\xd2" => [77, "\x1dm"], "\xd3" => [18, "\x1dm"], "\xd4" => [77, "\x1dn"], "\xd5" => [18, "\x1dn"], "\xd6" => [77, "\x1dp"], "\xd7" => [18, "\x1dp"], "\xd8" => [77, "\x1dr"], "\xd9" => [18, "\x1dr"], "\xda" => [77, "\x1du"], "\xdb" => [18, "\x1du"], "\xdc" => [0, "\x1d:"], "\xdd" => [0, "\x1dB"], "\xde" => [0, "\x1dC"], "\xdf" => [0, "\x1dD"], "\xe0" => [0, "\x1dE"], "\xe1" => [0, "\x1dF"], "\xe2" => [0, "\x1dG"], "\xe3" => [0, "\x1dH"], "\xe4" => [0, "\x1dI"], "\xe5" => [0, "\x1dJ"], "\xe6" => [0, "\x1dK"], "\xe7" => [0, "\x1dL"], "\xe8" => [0, "\x1dM"], "\xe9" => [0, "\x1dN"], "\xea" => [0, "\x1dO"], "\xeb" => [0, "\x1dP"], "\xec" => [0, "\x1dQ"], "\xed" => [0, "\x1dR"], "\xee" => [0, "\x1dS"], "\xef" => [0, "\x1dT"], "\xf0" => [0, "\x1dU"], "\xf1" => [0, "\x1dV"], "\xf2" => [0, "\x1dW"], "\xf3" => [0, "\x1dY"], "\xf4" => [0, "\x1dj"], "\xf5" => [0, "\x1dk"], "\xf6" => [0, "\x1dq"], "\xf7" => [0, "\x1dv"], "\xf8" => [0, "\x1dw"], "\xf9" => [0, "\x1dx"], "\xfa" => [0, "\x1dy"], "\xfb" => [0, "\x1dz"], "\xfc" => [82, "\x1d"], "\xfd" => [87, "\x1d"], "\xfe" => [130, "\x1d"], "\xff" => [9, "\x1d"]], ["\x00" => [77, "\x1c0"], "\x01" => [18, "\x1c0"], "\x02" => [77, "\x1c1"], "\x03" => [18, "\x1c1"], "\x04" => [77, "\x1c2"], "\x05" => [18, "\x1c2"], "\x06" => [77, "\x1ca"], "\x07" => [18, "\x1ca"], "\x08" => [77, "\x1cc"], "\t" => [18, "\x1cc"], "\n" => [77, "\x1ce"], "\v" => [18, "\x1ce"], "\f" => [77, "\x1ci"], "\r" => [18, "\x1ci"], "\x0e" => [77, "\x1co"], "\x0f" => [18, "\x1co"], "\x10" => [77, "\x1cs"], "\x11" => [18, "\x1cs"], "\x12" => [77, "\x1ct"], "\x13" => [18, "\x1ct"], "\x14" => [0, "\x1c "], "\x15" => [0, "\x1c%"], "\x16" => [0, "\x1c-"], "\x17" => [0, "\x1c."], "\x18" => [0, "\x1c/"], "\x19" => [0, "\x1c3"], "\x1a" => [0, "\x1c4"], "\x1b" => [0, "\x1c5"], "\x1c" => [0, "\x1c6"], "\x1d" => [0, "\x1c7"], "\x1e" => [0, "\x1c8"], "\x1f" => [0, "\x1c9"], " " => [0, "\x1c="], "!" => [0, "\x1cA"], "\"" => [0, "\x1c_"], "#" => [0, "\x1cb"], "\$" => [0, "\x1cd"], "%" => [0, "\x1cf"], "&" => [0, "\x1cg"], "'" => [0, "\x1ch"], "(" => [0, "\x1cl"], ")" => [0, "\x1cm"], "*" => [0, "\x1cn"], "+" => [0, "\x1cp"], "," => [0, "\x1cr"], "-" => [0, "\x1cu"], "." => [100, "\x1c"], "/" => [110, "\x1c"], [111, "\x1c"], [115, "\x1c"], [116, "\x1c"], [118, "\x1c"], [119, "\x1c"], [122, "\x1c"], [123, "\x1c"], [125, "\x1c"], [126, "\x1c"], [129, "\x1c"], ":" => [143, "\x1c"], ";" => [148, "\x1c"], "<" => [151, "\x1c"], "=" => [153, "\x1c"], ">" => [83, "\x1c"], "?" => [10, "\x1c"], "@" => [77, "\x1d0"], "A" => [18, "\x1d0"], "B" => [77, "\x1d1"], "C" => [18, "\x1d1"], "D" => [77, "\x1d2"], "E" => [18, "\x1d2"], "F" => [77, "\x1da"], "G" => [18, "\x1da"], "H" => [77, "\x1dc"], "I" => [18, "\x1dc"], "J" => [77, "\x1de"], "K" => [18, "\x1de"], "L" => [77, "\x1di"], "M" => [18, "\x1di"], "N" => [77, "\x1do"], "O" => [18, "\x1do"], "P" => [77, "\x1ds"], "Q" => [18, "\x1ds"], "R" => [77, "\x1dt"], "S" => [18, "\x1dt"], "T" => [0, "\x1d "], "U" => [0, "\x1d%"], "V" => [0, "\x1d-"], "W" => [0, "\x1d."], "X" => [0, "\x1d/"], "Y" => [0, "\x1d3"], "Z" => [0, "\x1d4"], "[" => [0, "\x1d5"], "\\" => [0, "\x1d6"], "]" => [0, "\x1d7"], "^" => [0, "\x1d8"], "_" => [0, "\x1d9"], "`" => [0, "\x1d="], "a" => [0, "\x1dA"], "b" => [0, "\x1d_"], "c" => [0, "\x1db"], "d" => [0, "\x1dd"], "e" => [0, "\x1df"], "f" => [0, "\x1dg"], "g" => [0, "\x1dh"], "h" => [0, "\x1dl"], "i" => [0, "\x1dm"], "j" => [0, "\x1dn"], "k" => [0, "\x1dp"], "l" => [0, "\x1dr"], "m" => [0, "\x1du"], "n" => [100, "\x1d"], "o" => [110, "\x1d"], "p" => [111, "\x1d"], "q" => [115, "\x1d"], "r" => [116, "\x1d"], "s" => [118, "\x1d"], "t" => [119, "\x1d"], "u" => [122, "\x1d"], "v" => [123, "\x1d"], "w" => [125, "\x1d"], "x" => [126, "\x1d"], "y" => [129, "\x1d"], "z" => [143, "\x1d"], "{" => [148, "\x1d"], "|" => [151, "\x1d"], "}" => [153, "\x1d"], "~" => [83, "\x1d"], "" => [10, "\x1d"], "\x80" => [77, "\x1e0"], "\x81" => [18, "\x1e0"], "\x82" => [77, "\x1e1"], "\x83" => [18, "\x1e1"], "\x84" => [77, "\x1e2"], "\x85" => [18, "\x1e2"], "\x86" => [77, "\x1ea"], "\x87" => [18, "\x1ea"], "\x88" => [77, "\x1ec"], "\x89" => [18, "\x1ec"], "\x8a" => [77, "\x1ee"], "\x8b" => [18, "\x1ee"], "\x8c" => [77, "\x1ei"], "\x8d" => [18, "\x1ei"], "\x8e" => [77, "\x1eo"], "\x8f" => [18, "\x1eo"], "\x90" => [77, "\x1es"], "\x91" => [18, "\x1es"], "\x92" => [77, "\x1et"], "\x93" => [18, "\x1et"], "\x94" => [0, "\x1e "], "\x95" => [0, "\x1e%"], "\x96" => [0, "\x1e-"], "\x97" => [0, "\x1e."], "\x98" => [0, "\x1e/"], "\x99" => [0, "\x1e3"], "\x9a" => [0, "\x1e4"], "\x9b" => [0, "\x1e5"], "\x9c" => [0, "\x1e6"], "\x9d" => [0, "\x1e7"], "\x9e" => [0, "\x1e8"], "\x9f" => [0, "\x1e9"], "\xa0" => [0, "\x1e="], "\xa1" => [0, "\x1eA"], "\xa2" => [0, "\x1e_"], "\xa3" => [0, "\x1eb"], "\xa4" => [0, "\x1ed"], "\xa5" => [0, "\x1ef"], "\xa6" => [0, "\x1eg"], "\xa7" => [0, "\x1eh"], "\xa8" => [0, "\x1el"], "\xa9" => [0, "\x1em"], "\xaa" => [0, "\x1en"], "\xab" => [0, "\x1ep"], "\xac" => [0, "\x1er"], "\xad" => [0, "\x1eu"], "\xae" => [100, "\x1e"], "\xaf" => [110, "\x1e"], "\xb0" => [111, "\x1e"], "\xb1" => [115, "\x1e"], "\xb2" => [116, "\x1e"], "\xb3" => [118, "\x1e"], "\xb4" => [119, "\x1e"], "\xb5" => [122, "\x1e"], "\xb6" => [123, "\x1e"], "\xb7" => [125, "\x1e"], "\xb8" => [126, "\x1e"], "\xb9" => [129, "\x1e"], "\xba" => [143, "\x1e"], "\xbb" => [148, "\x1e"], "\xbc" => [151, "\x1e"], "\xbd" => [153, "\x1e"], "\xbe" => [83, "\x1e"], "\xbf" => [10, "\x1e"], "\xc0" => [77, "\x1f0"], "\xc1" => [18, "\x1f0"], "\xc2" => [77, "\x1f1"], "\xc3" => [18, "\x1f1"], "\xc4" => [77, "\x1f2"], "\xc5" => [18, "\x1f2"], "\xc6" => [77, "\x1fa"], "\xc7" => [18, "\x1fa"], "\xc8" => [77, "\x1fc"], "\xc9" => [18, "\x1fc"], "\xca" => [77, "\x1fe"], "\xcb" => [18, "\x1fe"], "\xcc" => [77, "\x1fi"], "\xcd" => [18, "\x1fi"], "\xce" => [77, "\x1fo"], "\xcf" => [18, "\x1fo"], "\xd0" => [77, "\x1fs"], "\xd1" => [18, "\x1fs"], "\xd2" => [77, "\x1ft"], "\xd3" => [18, "\x1ft"], "\xd4" => [0, "\x1f "], "\xd5" => [0, "\x1f%"], "\xd6" => [0, "\x1f-"], "\xd7" => [0, "\x1f."], "\xd8" => [0, "\x1f/"], "\xd9" => [0, "\x1f3"], "\xda" => [0, "\x1f4"], "\xdb" => [0, "\x1f5"], "\xdc" => [0, "\x1f6"], "\xdd" => [0, "\x1f7"], "\xde" => [0, "\x1f8"], "\xdf" => [0, "\x1f9"], "\xe0" => [0, "\x1f="], "\xe1" => [0, "\x1fA"], "\xe2" => [0, "\x1f_"], "\xe3" => [0, "\x1fb"], "\xe4" => [0, "\x1fd"], "\xe5" => [0, "\x1ff"], "\xe6" => [0, "\x1fg"], "\xe7" => [0, "\x1fh"], "\xe8" => [0, "\x1fl"], "\xe9" => [0, "\x1fm"], "\xea" => [0, "\x1fn"], "\xeb" => [0, "\x1fp"], "\xec" => [0, "\x1fr"], "\xed" => [0, "\x1fu"], "\xee" => [100, "\x1f"], "\xef" => [110, "\x1f"], "\xf0" => [111, "\x1f"], "\xf1" => [115, "\x1f"], "\xf2" => [116, "\x1f"], "\xf3" => [118, "\x1f"], "\xf4" => [119, "\x1f"], "\xf5" => [122, "\x1f"], "\xf6" => [123, "\x1f"], "\xf7" => [125, "\x1f"], "\xf8" => [126, "\x1f"], "\xf9" => [129, "\x1f"], "\xfa" => [143, "\x1f"], "\xfb" => [148, "\x1f"], "\xfc" => [151, "\x1f"], "\xfd" => [153, "\x1f"], "\xfe" => [83, "\x1f"], "\xff" => [10, "\x1f"]], ["\x00" => [94, "\x1e0"], "\x01" => [76, "\x1e0"], "\x02" => [104, "\x1e0"], "\x03" => [16, "\x1e0"], "\x04" => [94, "\x1e1"], "\x05" => [76, "\x1e1"], "\x06" => [104, "\x1e1"], "\x07" => [16, "\x1e1"], "\x08" => [94, "\x1e2"], "\t" => [76, "\x1e2"], "\n" => [104, "\x1e2"], "\v" => [16, "\x1e2"], "\f" => [94, "\x1ea"], "\r" => [76, "\x1ea"], "\x0e" => [104, "\x1ea"], "\x0f" => [16, "\x1ea"], "\x10" => [94, "\x1ec"], "\x11" => [76, "\x1ec"], "\x12" => [104, "\x1ec"], "\x13" => [16, "\x1ec"], "\x14" => [94, "\x1ee"], "\x15" => [76, "\x1ee"], "\x16" => [104, "\x1ee"], "\x17" => [16, "\x1ee"], "\x18" => [94, "\x1ei"], "\x19" => [76, "\x1ei"], "\x1a" => [104, "\x1ei"], "\x1b" => [16, "\x1ei"], "\x1c" => [94, "\x1eo"], "\x1d" => [76, "\x1eo"], "\x1e" => [104, "\x1eo"], "\x1f" => [16, "\x1eo"], " " => [94, "\x1es"], "!" => [76, "\x1es"], "\"" => [104, "\x1es"], "#" => [16, "\x1es"], "\$" => [94, "\x1et"], "%" => [76, "\x1et"], "&" => [104, "\x1et"], "'" => [16, "\x1et"], "(" => [77, "\x1e "], ")" => [18, "\x1e "], "*" => [77, "\x1e%"], "+" => [18, "\x1e%"], "," => [77, "\x1e-"], "-" => [18, "\x1e-"], "." => [77, "\x1e."], "/" => [18, "\x1e."], [77, "\x1e/"], [18, "\x1e/"], [77, "\x1e3"], [18, "\x1e3"], [77, "\x1e4"], [18, "\x1e4"], [77, "\x1e5"], [18, "\x1e5"], [77, "\x1e6"], [18, "\x1e6"], ":" => [77, "\x1e7"], ";" => [18, "\x1e7"], "<" => [77, "\x1e8"], "=" => [18, "\x1e8"], ">" => [77, "\x1e9"], "?" => [18, "\x1e9"], "@" => [77, "\x1e="], "A" => [18, "\x1e="], "B" => [77, "\x1eA"], "C" => [18, "\x1eA"], "D" => [77, "\x1e_"], "E" => [18, "\x1e_"], "F" => [77, "\x1eb"], "G" => [18, "\x1eb"], "H" => [77, "\x1ed"], "I" => [18, "\x1ed"], "J" => [77, "\x1ef"], "K" => [18, "\x1ef"], "L" => [77, "\x1eg"], "M" => [18, "\x1eg"], "N" => [77, "\x1eh"], "O" => [18, "\x1eh"], "P" => [77, "\x1el"], "Q" => [18, "\x1el"], "R" => [77, "\x1em"], "S" => [18, "\x1em"], "T" => [77, "\x1en"], "U" => [18, "\x1en"], "V" => [77, "\x1ep"], "W" => [18, "\x1ep"], "X" => [77, "\x1er"], "Y" => [18, "\x1er"], "Z" => [77, "\x1eu"], "[" => [18, "\x1eu"], "\\" => [0, "\x1e:"], "]" => [0, "\x1eB"], "^" => [0, "\x1eC"], "_" => [0, "\x1eD"], "`" => [0, "\x1eE"], "a" => [0, "\x1eF"], "b" => [0, "\x1eG"], "c" => [0, "\x1eH"], "d" => [0, "\x1eI"], "e" => [0, "\x1eJ"], "f" => [0, "\x1eK"], "g" => [0, "\x1eL"], "h" => [0, "\x1eM"], "i" => [0, "\x1eN"], "j" => [0, "\x1eO"], "k" => [0, "\x1eP"], "l" => [0, "\x1eQ"], "m" => [0, "\x1eR"], "n" => [0, "\x1eS"], "o" => [0, "\x1eT"], "p" => [0, "\x1eU"], "q" => [0, "\x1eV"], "r" => [0, "\x1eW"], "s" => [0, "\x1eY"], "t" => [0, "\x1ej"], "u" => [0, "\x1ek"], "v" => [0, "\x1eq"], "w" => [0, "\x1ev"], "x" => [0, "\x1ew"], "y" => [0, "\x1ex"], "z" => [0, "\x1ey"], "{" => [0, "\x1ez"], "|" => [82, "\x1e"], "}" => [87, "\x1e"], "~" => [130, "\x1e"], "" => [9, "\x1e"], "\x80" => [94, "\x1f0"], "\x81" => [76, "\x1f0"], "\x82" => [104, "\x1f0"], "\x83" => [16, "\x1f0"], "\x84" => [94, "\x1f1"], "\x85" => [76, "\x1f1"], "\x86" => [104, "\x1f1"], "\x87" => [16, "\x1f1"], "\x88" => [94, "\x1f2"], "\x89" => [76, "\x1f2"], "\x8a" => [104, "\x1f2"], "\x8b" => [16, "\x1f2"], "\x8c" => [94, "\x1fa"], "\x8d" => [76, "\x1fa"], "\x8e" => [104, "\x1fa"], "\x8f" => [16, "\x1fa"], "\x90" => [94, "\x1fc"], "\x91" => [76, "\x1fc"], "\x92" => [104, "\x1fc"], "\x93" => [16, "\x1fc"], "\x94" => [94, "\x1fe"], "\x95" => [76, "\x1fe"], "\x96" => [104, "\x1fe"], "\x97" => [16, "\x1fe"], "\x98" => [94, "\x1fi"], "\x99" => [76, "\x1fi"], "\x9a" => [104, "\x1fi"], "\x9b" => [16, "\x1fi"], "\x9c" => [94, "\x1fo"], "\x9d" => [76, "\x1fo"], "\x9e" => [104, "\x1fo"], "\x9f" => [16, "\x1fo"], "\xa0" => [94, "\x1fs"], "\xa1" => [76, "\x1fs"], "\xa2" => [104, "\x1fs"], "\xa3" => [16, "\x1fs"], "\xa4" => [94, "\x1ft"], "\xa5" => [76, "\x1ft"], "\xa6" => [104, "\x1ft"], "\xa7" => [16, "\x1ft"], "\xa8" => [77, "\x1f "], "\xa9" => [18, "\x1f "], "\xaa" => [77, "\x1f%"], "\xab" => [18, "\x1f%"], "\xac" => [77, "\x1f-"], "\xad" => [18, "\x1f-"], "\xae" => [77, "\x1f."], "\xaf" => [18, "\x1f."], "\xb0" => [77, "\x1f/"], "\xb1" => [18, "\x1f/"], "\xb2" => [77, "\x1f3"], "\xb3" => [18, "\x1f3"], "\xb4" => [77, "\x1f4"], "\xb5" => [18, "\x1f4"], "\xb6" => [77, "\x1f5"], "\xb7" => [18, "\x1f5"], "\xb8" => [77, "\x1f6"], "\xb9" => [18, "\x1f6"], "\xba" => [77, "\x1f7"], "\xbb" => [18, "\x1f7"], "\xbc" => [77, "\x1f8"], "\xbd" => [18, "\x1f8"], "\xbe" => [77, "\x1f9"], "\xbf" => [18, "\x1f9"], "\xc0" => [77, "\x1f="], "\xc1" => [18, "\x1f="], "\xc2" => [77, "\x1fA"], "\xc3" => [18, "\x1fA"], "\xc4" => [77, "\x1f_"], "\xc5" => [18, "\x1f_"], "\xc6" => [77, "\x1fb"], "\xc7" => [18, "\x1fb"], "\xc8" => [77, "\x1fd"], "\xc9" => [18, "\x1fd"], "\xca" => [77, "\x1ff"], "\xcb" => [18, "\x1ff"], "\xcc" => [77, "\x1fg"], "\xcd" => [18, "\x1fg"], "\xce" => [77, "\x1fh"], "\xcf" => [18, "\x1fh"], "\xd0" => [77, "\x1fl"], "\xd1" => [18, "\x1fl"], "\xd2" => [77, "\x1fm"], "\xd3" => [18, "\x1fm"], "\xd4" => [77, "\x1fn"], "\xd5" => [18, "\x1fn"], "\xd6" => [77, "\x1fp"], "\xd7" => [18, "\x1fp"], "\xd8" => [77, "\x1fr"], "\xd9" => [18, "\x1fr"], "\xda" => [77, "\x1fu"], "\xdb" => [18, "\x1fu"], "\xdc" => [0, "\x1f:"], "\xdd" => [0, "\x1fB"], "\xde" => [0, "\x1fC"], "\xdf" => [0, "\x1fD"], "\xe0" => [0, "\x1fE"], "\xe1" => [0, "\x1fF"], "\xe2" => [0, "\x1fG"], "\xe3" => [0, "\x1fH"], "\xe4" => [0, "\x1fI"], "\xe5" => [0, "\x1fJ"], "\xe6" => [0, "\x1fK"], "\xe7" => [0, "\x1fL"], "\xe8" => [0, "\x1fM"], "\xe9" => [0, "\x1fN"], "\xea" => [0, "\x1fO"], "\xeb" => [0, "\x1fP"], "\xec" => [0, "\x1fQ"], "\xed" => [0, "\x1fR"], "\xee" => [0, "\x1fS"], "\xef" => [0, "\x1fT"], "\xf0" => [0, "\x1fU"], "\xf1" => [0, "\x1fV"], "\xf2" => [0, "\x1fW"], "\xf3" => [0, "\x1fY"], "\xf4" => [0, "\x1fj"], "\xf5" => [0, "\x1fk"], "\xf6" => [0, "\x1fq"], "\xf7" => [0, "\x1fv"], "\xf8" => [0, "\x1fw"], "\xf9" => [0, "\x1fx"], "\xfa" => [0, "\x1fy"], "\xfb" => [0, "\x1fz"], "\xfc" => [82, "\x1f"], "\xfd" => [87, "\x1f"], "\xfe" => [130, "\x1f"], "\xff" => [9, "\x1f"]], ["\x00" => [94, " 0"], "\x01" => [76, " 0"], "\x02" => [104, " 0"], "\x03" => [16, " 0"], "\x04" => [94, " 1"], "\x05" => [76, " 1"], "\x06" => [104, " 1"], "\x07" => [16, " 1"], "\x08" => [94, " 2"], "\t" => [76, " 2"], "\n" => [104, " 2"], "\v" => [16, " 2"], "\f" => [94, " a"], "\r" => [76, " a"], "\x0e" => [104, " a"], "\x0f" => [16, " a"], "\x10" => [94, " c"], "\x11" => [76, " c"], "\x12" => [104, " c"], "\x13" => [16, " c"], "\x14" => [94, " e"], "\x15" => [76, " e"], "\x16" => [104, " e"], "\x17" => [16, " e"], "\x18" => [94, " i"], "\x19" => [76, " i"], "\x1a" => [104, " i"], "\x1b" => [16, " i"], "\x1c" => [94, " o"], "\x1d" => [76, " o"], "\x1e" => [104, " o"], "\x1f" => [16, " o"], " " => [94, " s"], "!" => [76, " s"], "\"" => [104, " s"], "#" => [16, " s"], "\$" => [94, " t"], "%" => [76, " t"], "&" => [104, " t"], "'" => [16, " t"], "(" => [77, "  "], ")" => [18, "  "], "*" => [77, " %"], "+" => [18, " %"], "," => [77, " -"], "-" => [18, " -"], "." => [77, " ."], "/" => [18, " ."], [77, " /"], [18, " /"], [77, " 3"], [18, " 3"], [77, " 4"], [18, " 4"], [77, " 5"], [18, " 5"], [77, " 6"], [18, " 6"], ":" => [77, " 7"], ";" => [18, " 7"], "<" => [77, " 8"], "=" => [18, " 8"], ">" => [77, " 9"], "?" => [18, " 9"], "@" => [77, " ="], "A" => [18, " ="], "B" => [77, " A"], "C" => [18, " A"], "D" => [77, " _"], "E" => [18, " _"], "F" => [77, " b"], "G" => [18, " b"], "H" => [77, " d"], "I" => [18, " d"], "J" => [77, " f"], "K" => [18, " f"], "L" => [77, " g"], "M" => [18, " g"], "N" => [77, " h"], "O" => [18, " h"], "P" => [77, " l"], "Q" => [18, " l"], "R" => [77, " m"], "S" => [18, " m"], "T" => [77, " n"], "U" => [18, " n"], "V" => [77, " p"], "W" => [18, " p"], "X" => [77, " r"], "Y" => [18, " r"], "Z" => [77, " u"], "[" => [18, " u"], "\\" => [0, " :"], "]" => [0, " B"], "^" => [0, " C"], "_" => [0, " D"], "`" => [0, " E"], "a" => [0, " F"], "b" => [0, " G"], "c" => [0, " H"], "d" => [0, " I"], "e" => [0, " J"], "f" => [0, " K"], "g" => [0, " L"], "h" => [0, " M"], "i" => [0, " N"], "j" => [0, " O"], "k" => [0, " P"], "l" => [0, " Q"], "m" => [0, " R"], "n" => [0, " S"], "o" => [0, " T"], "p" => [0, " U"], "q" => [0, " V"], "r" => [0, " W"], "s" => [0, " Y"], "t" => [0, " j"], "u" => [0, " k"], "v" => [0, " q"], "w" => [0, " v"], "x" => [0, " w"], "y" => [0, " x"], "z" => [0, " y"], "{" => [0, " z"], "|" => [82, " "], "}" => [87, " "], "~" => [130, " "], "" => [9, " "], "\x80" => [94, "%0"], "\x81" => [76, "%0"], "\x82" => [104, "%0"], "\x83" => [16, "%0"], "\x84" => [94, "%1"], "\x85" => [76, "%1"], "\x86" => [104, "%1"], "\x87" => [16, "%1"], "\x88" => [94, "%2"], "\x89" => [76, "%2"], "\x8a" => [104, "%2"], "\x8b" => [16, "%2"], "\x8c" => [94, "%a"], "\x8d" => [76, "%a"], "\x8e" => [104, "%a"], "\x8f" => [16, "%a"], "\x90" => [94, "%c"], "\x91" => [76, "%c"], "\x92" => [104, "%c"], "\x93" => [16, "%c"], "\x94" => [94, "%e"], "\x95" => [76, "%e"], "\x96" => [104, "%e"], "\x97" => [16, "%e"], "\x98" => [94, "%i"], "\x99" => [76, "%i"], "\x9a" => [104, "%i"], "\x9b" => [16, "%i"], "\x9c" => [94, "%o"], "\x9d" => [76, "%o"], "\x9e" => [104, "%o"], "\x9f" => [16, "%o"], "\xa0" => [94, "%s"], "\xa1" => [76, "%s"], "\xa2" => [104, "%s"], "\xa3" => [16, "%s"], "\xa4" => [94, "%t"], "\xa5" => [76, "%t"], "\xa6" => [104, "%t"], "\xa7" => [16, "%t"], "\xa8" => [77, "% "], "\xa9" => [18, "% "], "\xaa" => [77, "%%"], "\xab" => [18, "%%"], "\xac" => [77, "%-"], "\xad" => [18, "%-"], "\xae" => [77, "%."], "\xaf" => [18, "%."], "\xb0" => [77, "%/"], "\xb1" => [18, "%/"], "\xb2" => [77, "%3"], "\xb3" => [18, "%3"], "\xb4" => [77, "%4"], "\xb5" => [18, "%4"], "\xb6" => [77, "%5"], "\xb7" => [18, "%5"], "\xb8" => [77, "%6"], "\xb9" => [18, "%6"], "\xba" => [77, "%7"], "\xbb" => [18, "%7"], "\xbc" => [77, "%8"], "\xbd" => [18, "%8"], "\xbe" => [77, "%9"], "\xbf" => [18, "%9"], "\xc0" => [77, "%="], "\xc1" => [18, "%="], "\xc2" => [77, "%A"], "\xc3" => [18, "%A"], "\xc4" => [77, "%_"], "\xc5" => [18, "%_"], "\xc6" => [77, "%b"], "\xc7" => [18, "%b"], "\xc8" => [77, "%d"], "\xc9" => [18, "%d"], "\xca" => [77, "%f"], "\xcb" => [18, "%f"], "\xcc" => [77, "%g"], "\xcd" => [18, "%g"], "\xce" => [77, "%h"], "\xcf" => [18, "%h"], "\xd0" => [77, "%l"], "\xd1" => [18, "%l"], "\xd2" => [77, "%m"], "\xd3" => [18, "%m"], "\xd4" => [77, "%n"], "\xd5" => [18, "%n"], "\xd6" => [77, "%p"], "\xd7" => [18, "%p"], "\xd8" => [77, "%r"], "\xd9" => [18, "%r"], "\xda" => [77, "%u"], "\xdb" => [18, "%u"], "\xdc" => [0, "%:"], "\xdd" => [0, "%B"], "\xde" => [0, "%C"], "\xdf" => [0, "%D"], "\xe0" => [0, "%E"], "\xe1" => [0, "%F"], "\xe2" => [0, "%G"], "\xe3" => [0, "%H"], "\xe4" => [0, "%I"], "\xe5" => [0, "%J"], "\xe6" => [0, "%K"], "\xe7" => [0, "%L"], "\xe8" => [0, "%M"], "\xe9" => [0, "%N"], "\xea" => [0, "%O"], "\xeb" => [0, "%P"], "\xec" => [0, "%Q"], "\xed" => [0, "%R"], "\xee" => [0, "%S"], "\xef" => [0, "%T"], "\xf0" => [0, "%U"], "\xf1" => [0, "%V"], "\xf2" => [0, "%W"], "\xf3" => [0, "%Y"], "\xf4" => [0, "%j"], "\xf5" => [0, "%k"], "\xf6" => [0, "%q"], "\xf7" => [0, "%v"], "\xf8" => [0, "%w"], "\xf9" => [0, "%x"], "\xfa" => [0, "%y"], "\xfb" => [0, "%z"], "\xfc" => [82, "%"], "\xfd" => [87, "%"], "\xfe" => [130, "%"], "\xff" => [9, "%"]], ["\x00" => [77, " 0"], "\x01" => [18, " 0"], "\x02" => [77, " 1"], "\x03" => [18, " 1"], "\x04" => [77, " 2"], "\x05" => [18, " 2"], "\x06" => [77, " a"], "\x07" => [18, " a"], "\x08" => [77, " c"], "\t" => [18, " c"], "\n" => [77, " e"], "\v" => [18, " e"], "\f" => [77, " i"], "\r" => [18, " i"], "\x0e" => [77, " o"], "\x0f" => [18, " o"], "\x10" => [77, " s"], "\x11" => [18, " s"], "\x12" => [77, " t"], "\x13" => [18, " t"], "\x14" => [0, "  "], "\x15" => [0, " %"], "\x16" => [0, " -"], "\x17" => [0, " ."], "\x18" => [0, " /"], "\x19" => [0, " 3"], "\x1a" => [0, " 4"], "\x1b" => [0, " 5"], "\x1c" => [0, " 6"], "\x1d" => [0, " 7"], "\x1e" => [0, " 8"], "\x1f" => [0, " 9"], " " => [0, " ="], "!" => [0, " A"], "\"" => [0, " _"], "#" => [0, " b"], "\$" => [0, " d"], "%" => [0, " f"], "&" => [0, " g"], "'" => [0, " h"], "(" => [0, " l"], ")" => [0, " m"], "*" => [0, " n"], "+" => [0, " p"], "," => [0, " r"], "-" => [0, " u"], "." => [100, " "], "/" => [110, " "], [111, " "], [115, " "], [116, " "], [118, " "], [119, " "], [122, " "], [123, " "], [125, " "], [126, " "], [129, " "], ":" => [143, " "], ";" => [148, " "], "<" => [151, " "], "=" => [153, " "], ">" => [83, " "], "?" => [10, " "], "@" => [77, "%0"], "A" => [18, "%0"], "B" => [77, "%1"], "C" => [18, "%1"], "D" => [77, "%2"], "E" => [18, "%2"], "F" => [77, "%a"], "G" => [18, "%a"], "H" => [77, "%c"], "I" => [18, "%c"], "J" => [77, "%e"], "K" => [18, "%e"], "L" => [77, "%i"], "M" => [18, "%i"], "N" => [77, "%o"], "O" => [18, "%o"], "P" => [77, "%s"], "Q" => [18, "%s"], "R" => [77, "%t"], "S" => [18, "%t"], "T" => [0, "% "], "U" => [0, "%%"], "V" => [0, "%-"], "W" => [0, "%."], "X" => [0, "%/"], "Y" => [0, "%3"], "Z" => [0, "%4"], "[" => [0, "%5"], "\\" => [0, "%6"], "]" => [0, "%7"], "^" => [0, "%8"], "_" => [0, "%9"], "`" => [0, "%="], "a" => [0, "%A"], "b" => [0, "%_"], "c" => [0, "%b"], "d" => [0, "%d"], "e" => [0, "%f"], "f" => [0, "%g"], "g" => [0, "%h"], "h" => [0, "%l"], "i" => [0, "%m"], "j" => [0, "%n"], "k" => [0, "%p"], "l" => [0, "%r"], "m" => [0, "%u"], "n" => [100, "%"], "o" => [110, "%"], "p" => [111, "%"], "q" => [115, "%"], "r" => [116, "%"], "s" => [118, "%"], "t" => [119, "%"], "u" => [122, "%"], "v" => [123, "%"], "w" => [125, "%"], "x" => [126, "%"], "y" => [129, "%"], "z" => [143, "%"], "{" => [148, "%"], "|" => [151, "%"], "}" => [153, "%"], "~" => [83, "%"], "" => [10, "%"], "\x80" => [77, "-0"], "\x81" => [18, "-0"], "\x82" => [77, "-1"], "\x83" => [18, "-1"], "\x84" => [77, "-2"], "\x85" => [18, "-2"], "\x86" => [77, "-a"], "\x87" => [18, "-a"], "\x88" => [77, "-c"], "\x89" => [18, "-c"], "\x8a" => [77, "-e"], "\x8b" => [18, "-e"], "\x8c" => [77, "-i"], "\x8d" => [18, "-i"], "\x8e" => [77, "-o"], "\x8f" => [18, "-o"], "\x90" => [77, "-s"], "\x91" => [18, "-s"], "\x92" => [77, "-t"], "\x93" => [18, "-t"], "\x94" => [0, "- "], "\x95" => [0, "-%"], "\x96" => [0, "--"], "\x97" => [0, "-."], "\x98" => [0, "-/"], "\x99" => [0, "-3"], "\x9a" => [0, "-4"], "\x9b" => [0, "-5"], "\x9c" => [0, "-6"], "\x9d" => [0, "-7"], "\x9e" => [0, "-8"], "\x9f" => [0, "-9"], "\xa0" => [0, "-="], "\xa1" => [0, "-A"], "\xa2" => [0, "-_"], "\xa3" => [0, "-b"], "\xa4" => [0, "-d"], "\xa5" => [0, "-f"], "\xa6" => [0, "-g"], "\xa7" => [0, "-h"], "\xa8" => [0, "-l"], "\xa9" => [0, "-m"], "\xaa" => [0, "-n"], "\xab" => [0, "-p"], "\xac" => [0, "-r"], "\xad" => [0, "-u"], "\xae" => [100, "-"], "\xaf" => [110, "-"], "\xb0" => [111, "-"], "\xb1" => [115, "-"], "\xb2" => [116, "-"], "\xb3" => [118, "-"], "\xb4" => [119, "-"], "\xb5" => [122, "-"], "\xb6" => [123, "-"], "\xb7" => [125, "-"], "\xb8" => [126, "-"], "\xb9" => [129, "-"], "\xba" => [143, "-"], "\xbb" => [148, "-"], "\xbc" => [151, "-"], "\xbd" => [153, "-"], "\xbe" => [83, "-"], "\xbf" => [10, "-"], "\xc0" => [77, ".0"], "\xc1" => [18, ".0"], "\xc2" => [77, ".1"], "\xc3" => [18, ".1"], "\xc4" => [77, ".2"], "\xc5" => [18, ".2"], "\xc6" => [77, ".a"], "\xc7" => [18, ".a"], "\xc8" => [77, ".c"], "\xc9" => [18, ".c"], "\xca" => [77, ".e"], "\xcb" => [18, ".e"], "\xcc" => [77, ".i"], "\xcd" => [18, ".i"], "\xce" => [77, ".o"], "\xcf" => [18, ".o"], "\xd0" => [77, ".s"], "\xd1" => [18, ".s"], "\xd2" => [77, ".t"], "\xd3" => [18, ".t"], "\xd4" => [0, ". "], "\xd5" => [0, ".%"], "\xd6" => [0, ".-"], "\xd7" => [0, ".."], "\xd8" => [0, "./"], "\xd9" => [0, ".3"], "\xda" => [0, ".4"], "\xdb" => [0, ".5"], "\xdc" => [0, ".6"], "\xdd" => [0, ".7"], "\xde" => [0, ".8"], "\xdf" => [0, ".9"], "\xe0" => [0, ".="], "\xe1" => [0, ".A"], "\xe2" => [0, "._"], "\xe3" => [0, ".b"], "\xe4" => [0, ".d"], "\xe5" => [0, ".f"], "\xe6" => [0, ".g"], "\xe7" => [0, ".h"], "\xe8" => [0, ".l"], "\xe9" => [0, ".m"], "\xea" => [0, ".n"], "\xeb" => [0, ".p"], "\xec" => [0, ".r"], "\xed" => [0, ".u"], "\xee" => [100, "."], "\xef" => [110, "."], "\xf0" => [111, "."], "\xf1" => [115, "."], "\xf2" => [116, "."], "\xf3" => [118, "."], "\xf4" => [119, "."], "\xf5" => [122, "."], "\xf6" => [123, "."], "\xf7" => [125, "."], "\xf8" => [126, "."], "\xf9" => [129, "."], "\xfa" => [143, "."], "\xfb" => [148, "."], "\xfc" => [151, "."], "\xfd" => [153, "."], "\xfe" => [83, "."], "\xff" => [10, "."]], ["\x00" => [77, "s0"], "\x01" => [18, "s0"], "\x02" => [77, "s1"], "\x03" => [18, "s1"], "\x04" => [77, "s2"], "\x05" => [18, "s2"], "\x06" => [77, "sa"], "\x07" => [18, "sa"], "\x08" => [77, "sc"], "\t" => [18, "sc"], "\n" => [77, "se"], "\v" => [18, "se"], "\f" => [77, "si"], "\r" => [18, "si"], "\x0e" => [77, "so"], "\x0f" => [18, "so"], "\x10" => [77, "ss"], "\x11" => [18, "ss"], "\x12" => [77, "st"], "\x13" => [18, "st"], "\x14" => [0, "s "], "\x15" => [0, "s%"], "\x16" => [0, "s-"], "\x17" => [0, "s."], "\x18" => [0, "s/"], "\x19" => [0, "s3"], "\x1a" => [0, "s4"], "\x1b" => [0, "s5"], "\x1c" => [0, "s6"], "\x1d" => [0, "s7"], "\x1e" => [0, "s8"], "\x1f" => [0, "s9"], " " => [0, "s="], "!" => [0, "sA"], "\"" => [0, "s_"], "#" => [0, "sb"], "\$" => [0, "sd"], "%" => [0, "sf"], "&" => [0, "sg"], "'" => [0, "sh"], "(" => [0, "sl"], ")" => [0, "sm"], "*" => [0, "sn"], "+" => [0, "sp"], "," => [0, "sr"], "-" => [0, "su"], "." => [100, "s"], "/" => [110, "s"], [111, "s"], [115, "s"], [116, "s"], [118, "s"], [119, "s"], [122, "s"], [123, "s"], [125, "s"], [126, "s"], [129, "s"], ":" => [143, "s"], ";" => [148, "s"], "<" => [151, "s"], "=" => [153, "s"], ">" => [83, "s"], "?" => [10, "s"], "@" => [77, "t0"], "A" => [18, "t0"], "B" => [77, "t1"], "C" => [18, "t1"], "D" => [77, "t2"], "E" => [18, "t2"], "F" => [77, "ta"], "G" => [18, "ta"], "H" => [77, "tc"], "I" => [18, "tc"], "J" => [77, "te"], "K" => [18, "te"], "L" => [77, "ti"], "M" => [18, "ti"], "N" => [77, "to"], "O" => [18, "to"], "P" => [77, "ts"], "Q" => [18, "ts"], "R" => [77, "tt"], "S" => [18, "tt"], "T" => [0, "t "], "U" => [0, "t%"], "V" => [0, "t-"], "W" => [0, "t."], "X" => [0, "t/"], "Y" => [0, "t3"], "Z" => [0, "t4"], "[" => [0, "t5"], "\\" => [0, "t6"], "]" => [0, "t7"], "^" => [0, "t8"], "_" => [0, "t9"], "`" => [0, "t="], "a" => [0, "tA"], "b" => [0, "t_"], "c" => [0, "tb"], "d" => [0, "td"], "e" => [0, "tf"], "f" => [0, "tg"], "g" => [0, "th"], "h" => [0, "tl"], "i" => [0, "tm"], "j" => [0, "tn"], "k" => [0, "tp"], "l" => [0, "tr"], "m" => [0, "tu"], "n" => [100, "t"], "o" => [110, "t"], "p" => [111, "t"], "q" => [115, "t"], "r" => [116, "t"], "s" => [118, "t"], "t" => [119, "t"], "u" => [122, "t"], "v" => [123, "t"], "w" => [125, "t"], "x" => [126, "t"], "y" => [129, "t"], "z" => [143, "t"], "{" => [148, "t"], "|" => [151, "t"], "}" => [153, "t"], "~" => [83, "t"], "" => [10, "t"], "\x80" => [0, " 0"], "\x81" => [0, " 1"], "\x82" => [0, " 2"], "\x83" => [0, " a"], "\x84" => [0, " c"], "\x85" => [0, " e"], "\x86" => [0, " i"], "\x87" => [0, " o"], "\x88" => [0, " s"], "\x89" => [0, " t"], "\x8a" => [73, " "], "\x8b" => [88, " "], "\x8c" => [89, " "], "\x8d" => [96, " "], "\x8e" => [97, " "], "\x8f" => [99, " "], "\x90" => [106, " "], "\x91" => [136, " "], "\x92" => [139, " "], "\x93" => [141, " "], "\x94" => [145, " "], "\x95" => [147, " "], "\x96" => [149, " "], "\x97" => [101, " "], "\x98" => [112, " "], "\x99" => [117, " "], "\x9a" => [120, " "], "\x9b" => [124, " "], "\x9c" => [127, " "], "\x9d" => [144, " "], "\x9e" => [152, " "], "\x9f" => [11, " "], "\xa0" => [0, "%0"], "\xa1" => [0, "%1"], "\xa2" => [0, "%2"], "\xa3" => [0, "%a"], "\xa4" => [0, "%c"], "\xa5" => [0, "%e"], "\xa6" => [0, "%i"], "\xa7" => [0, "%o"], "\xa8" => [0, "%s"], "\xa9" => [0, "%t"], "\xaa" => [73, "%"], "\xab" => [88, "%"], "\xac" => [89, "%"], "\xad" => [96, "%"], "\xae" => [97, "%"], "\xaf" => [99, "%"], "\xb0" => [106, "%"], "\xb1" => [136, "%"], "\xb2" => [139, "%"], "\xb3" => [141, "%"], "\xb4" => [145, "%"], "\xb5" => [147, "%"], "\xb6" => [149, "%"], "\xb7" => [101, "%"], "\xb8" => [112, "%"], "\xb9" => [117, "%"], "\xba" => [120, "%"], "\xbb" => [124, "%"], "\xbc" => [127, "%"], "\xbd" => [144, "%"], "\xbe" => [152, "%"], "\xbf" => [11, "%"], "\xc0" => [0, "-0"], "\xc1" => [0, "-1"], "\xc2" => [0, "-2"], "\xc3" => [0, "-a"], "\xc4" => [0, "-c"], "\xc5" => [0, "-e"], "\xc6" => [0, "-i"], "\xc7" => [0, "-o"], "\xc8" => [0, "-s"], "\xc9" => [0, "-t"], "\xca" => [73, "-"], "\xcb" => [88, "-"], "\xcc" => [89, "-"], "\xcd" => [96, "-"], "\xce" => [97, "-"], "\xcf" => [99, "-"], "\xd0" => [106, "-"], "\xd1" => [136, "-"], "\xd2" => [139, "-"], "\xd3" => [141, "-"], "\xd4" => [145, "-"], "\xd5" => [147, "-"], "\xd6" => [149, "-"], "\xd7" => [101, "-"], "\xd8" => [112, "-"], "\xd9" => [117, "-"], "\xda" => [120, "-"], "\xdb" => [124, "-"], "\xdc" => [127, "-"], "\xdd" => [144, "-"], "\xde" => [152, "-"], "\xdf" => [11, "-"], "\xe0" => [0, ".0"], "\xe1" => [0, ".1"], "\xe2" => [0, ".2"], "\xe3" => [0, ".a"], "\xe4" => [0, ".c"], "\xe5" => [0, ".e"], "\xe6" => [0, ".i"], "\xe7" => [0, ".o"], "\xe8" => [0, ".s"], "\xe9" => [0, ".t"], "\xea" => [73, "."], "\xeb" => [88, "."], "\xec" => [89, "."], "\xed" => [96, "."], "\xee" => [97, "."], "\xef" => [99, "."], "\xf0" => [106, "."], "\xf1" => [136, "."], "\xf2" => [139, "."], "\xf3" => [141, "."], "\xf4" => [145, "."], "\xf5" => [147, "."], "\xf6" => [149, "."], "\xf7" => [101, "."], "\xf8" => [112, "."], "\xf9" => [117, "."], "\xfa" => [120, "."], "\xfb" => [124, "."], "\xfc" => [127, "."], "\xfd" => [144, "."], "\xfe" => [152, "."], "\xff" => [11, "."]], ["\x00" => [0, "s0"], "\x01" => [0, "s1"], "\x02" => [0, "s2"], "\x03" => [0, "sa"], "\x04" => [0, "sc"], "\x05" => [0, "se"], "\x06" => [0, "si"], "\x07" => [0, "so"], "\x08" => [0, "ss"], "\t" => [0, "st"], "\n" => [73, "s"], "\v" => [88, "s"], "\f" => [89, "s"], "\r" => [96, "s"], "\x0e" => [97, "s"], "\x0f" => [99, "s"], "\x10" => [106, "s"], "\x11" => [136, "s"], "\x12" => [139, "s"], "\x13" => [141, "s"], "\x14" => [145, "s"], "\x15" => [147, "s"], "\x16" => [149, "s"], "\x17" => [101, "s"], "\x18" => [112, "s"], "\x19" => [117, "s"], "\x1a" => [120, "s"], "\x1b" => [124, "s"], "\x1c" => [127, "s"], "\x1d" => [144, "s"], "\x1e" => [152, "s"], "\x1f" => [11, "s"], " " => [0, "t0"], "!" => [0, "t1"], "\"" => [0, "t2"], "#" => [0, "ta"], "\$" => [0, "tc"], "%" => [0, "te"], "&" => [0, "ti"], "'" => [0, "to"], "(" => [0, "ts"], ")" => [0, "tt"], "*" => [73, "t"], "+" => [88, "t"], "," => [89, "t"], "-" => [96, "t"], "." => [97, "t"], "/" => [99, "t"], [106, "t"], [136, "t"], [139, "t"], [141, "t"], [145, "t"], [147, "t"], [149, "t"], [101, "t"], [112, "t"], [117, "t"], ":" => [120, "t"], ";" => [124, "t"], "<" => [127, "t"], "=" => [144, "t"], ">" => [152, "t"], "?" => [11, "t"], "@" => [92, " "], "A" => [95, " "], "B" => [137, " "], "C" => [142, " "], "D" => [150, " "], "E" => [74, " "], "F" => [90, " "], "G" => [98, " "], "H" => [107, " "], "I" => [140, " "], "J" => [146, " "], "K" => [102, " "], "L" => [113, " "], "M" => [121, " "], "N" => [128, " "], "O" => [12, " "], "P" => [92, "%"], "Q" => [95, "%"], "R" => [137, "%"], "S" => [142, "%"], "T" => [150, "%"], "U" => [74, "%"], "V" => [90, "%"], "W" => [98, "%"], "X" => [107, "%"], "Y" => [140, "%"], "Z" => [146, "%"], "[" => [102, "%"], "\\" => [113, "%"], "]" => [121, "%"], "^" => [128, "%"], "_" => [12, "%"], "`" => [92, "-"], "a" => [95, "-"], "b" => [137, "-"], "c" => [142, "-"], "d" => [150, "-"], "e" => [74, "-"], "f" => [90, "-"], "g" => [98, "-"], "h" => [107, "-"], "i" => [140, "-"], "j" => [146, "-"], "k" => [102, "-"], "l" => [113, "-"], "m" => [121, "-"], "n" => [128, "-"], "o" => [12, "-"], "p" => [92, "."], "q" => [95, "."], "r" => [137, "."], "s" => [142, "."], "t" => [150, "."], "u" => [74, "."], "v" => [90, "."], "w" => [98, "."], "x" => [107, "."], "y" => [140, "."], "z" => [146, "."], "{" => [102, "."], "|" => [113, "."], "}" => [121, "."], "~" => [128, "."], "" => [12, "."], "\x80" => [92, "/"], "\x81" => [95, "/"], "\x82" => [137, "/"], "\x83" => [142, "/"], "\x84" => [150, "/"], "\x85" => [74, "/"], "\x86" => [90, "/"], "\x87" => [98, "/"], "\x88" => [107, "/"], "\x89" => [140, "/"], "\x8a" => [146, "/"], "\x8b" => [102, "/"], "\x8c" => [113, "/"], "\x8d" => [121, "/"], "\x8e" => [128, "/"], "\x8f" => [12, "/"], "\x90" => [92, "3"], "\x91" => [95, "3"], "\x92" => [137, "3"], "\x93" => [142, "3"], "\x94" => [150, "3"], "\x95" => [74, "3"], "\x96" => [90, "3"], "\x97" => [98, "3"], "\x98" => [107, "3"], "\x99" => [140, "3"], "\x9a" => [146, "3"], "\x9b" => [102, "3"], "\x9c" => [113, "3"], "\x9d" => [121, "3"], "\x9e" => [128, "3"], "\x9f" => [12, "3"], "\xa0" => [92, "4"], "\xa1" => [95, "4"], "\xa2" => [137, "4"], "\xa3" => [142, "4"], "\xa4" => [150, "4"], "\xa5" => [74, "4"], "\xa6" => [90, "4"], "\xa7" => [98, "4"], "\xa8" => [107, "4"], "\xa9" => [140, "4"], "\xaa" => [146, "4"], "\xab" => [102, "4"], "\xac" => [113, "4"], "\xad" => [121, "4"], "\xae" => [128, "4"], "\xaf" => [12, "4"], "\xb0" => [92, "5"], "\xb1" => [95, "5"], "\xb2" => [137, "5"], "\xb3" => [142, "5"], "\xb4" => [150, "5"], "\xb5" => [74, "5"], "\xb6" => [90, "5"], "\xb7" => [98, "5"], "\xb8" => [107, "5"], "\xb9" => [140, "5"], "\xba" => [146, "5"], "\xbb" => [102, "5"], "\xbc" => [113, "5"], "\xbd" => [121, "5"], "\xbe" => [128, "5"], "\xbf" => [12, "5"], "\xc0" => [92, "6"], "\xc1" => [95, "6"], "\xc2" => [137, "6"], "\xc3" => [142, "6"], "\xc4" => [150, "6"], "\xc5" => [74, "6"], "\xc6" => [90, "6"], "\xc7" => [98, "6"], "\xc8" => [107, "6"], "\xc9" => [140, "6"], "\xca" => [146, "6"], "\xcb" => [102, "6"], "\xcc" => [113, "6"], "\xcd" => [121, "6"], "\xce" => [128, "6"], "\xcf" => [12, "6"], "\xd0" => [92, "7"], "\xd1" => [95, "7"], "\xd2" => [137, "7"], "\xd3" => [142, "7"], "\xd4" => [150, "7"], "\xd5" => [74, "7"], "\xd6" => [90, "7"], "\xd7" => [98, "7"], "\xd8" => [107, "7"], "\xd9" => [140, "7"], "\xda" => [146, "7"], "\xdb" => [102, "7"], "\xdc" => [113, "7"], "\xdd" => [121, "7"], "\xde" => [128, "7"], "\xdf" => [12, "7"], "\xe0" => [92, "8"], "\xe1" => [95, "8"], "\xe2" => [137, "8"], "\xe3" => [142, "8"], "\xe4" => [150, "8"], "\xe5" => [74, "8"], "\xe6" => [90, "8"], "\xe7" => [98, "8"], "\xe8" => [107, "8"], "\xe9" => [140, "8"], "\xea" => [146, "8"], "\xeb" => [102, "8"], "\xec" => [113, "8"], "\xed" => [121, "8"], "\xee" => [128, "8"], "\xef" => [12, "8"], "\xf0" => [92, "9"], "\xf1" => [95, "9"], "\xf2" => [137, "9"], "\xf3" => [142, "9"], "\xf4" => [150, "9"], "\xf5" => [74, "9"], "\xf6" => [90, "9"], "\xf7" => [98, "9"], "\xf8" => [107, "9"], "\xf9" => [140, "9"], "\xfa" => [146, "9"], "\xfb" => [102, "9"], "\xfc" => [113, "9"], "\xfd" => [121, "9"], "\xfe" => [128, "9"], "\xff" => [12, "9"]], ["\x00" => [92, "0"], "\x01" => [95, "0"], "\x02" => [137, "0"], "\x03" => [142, "0"], "\x04" => [150, "0"], "\x05" => [74, "0"], "\x06" => [90, "0"], "\x07" => [98, "0"], "\x08" => [107, "0"], "\t" => [140, "0"], "\n" => [146, "0"], "\v" => [102, "0"], "\f" => [113, "0"], "\r" => [121, "0"], "\x0e" => [128, "0"], "\x0f" => [12, "0"], "\x10" => [92, "1"], "\x11" => [95, "1"], "\x12" => [137, "1"], "\x13" => [142, "1"], "\x14" => [150, "1"], "\x15" => [74, "1"], "\x16" => [90, "1"], "\x17" => [98, "1"], "\x18" => [107, "1"], "\x19" => [140, "1"], "\x1a" => [146, "1"], "\x1b" => [102, "1"], "\x1c" => [113, "1"], "\x1d" => [121, "1"], "\x1e" => [128, "1"], "\x1f" => [12, "1"], " " => [92, "2"], "!" => [95, "2"], "\"" => [137, "2"], "#" => [142, "2"], "\$" => [150, "2"], "%" => [74, "2"], "&" => [90, "2"], "'" => [98, "2"], "(" => [107, "2"], ")" => [140, "2"], "*" => [146, "2"], "+" => [102, "2"], "," => [113, "2"], "-" => [121, "2"], "." => [128, "2"], "/" => [12, "2"], [92, "a"], [95, "a"], [137, "a"], [142, "a"], [150, "a"], [74, "a"], [90, "a"], [98, "a"], [107, "a"], [140, "a"], ":" => [146, "a"], ";" => [102, "a"], "<" => [113, "a"], "=" => [121, "a"], ">" => [128, "a"], "?" => [12, "a"], "@" => [92, "c"], "A" => [95, "c"], "B" => [137, "c"], "C" => [142, "c"], "D" => [150, "c"], "E" => [74, "c"], "F" => [90, "c"], "G" => [98, "c"], "H" => [107, "c"], "I" => [140, "c"], "J" => [146, "c"], "K" => [102, "c"], "L" => [113, "c"], "M" => [121, "c"], "N" => [128, "c"], "O" => [12, "c"], "P" => [92, "e"], "Q" => [95, "e"], "R" => [137, "e"], "S" => [142, "e"], "T" => [150, "e"], "U" => [74, "e"], "V" => [90, "e"], "W" => [98, "e"], "X" => [107, "e"], "Y" => [140, "e"], "Z" => [146, "e"], "[" => [102, "e"], "\\" => [113, "e"], "]" => [121, "e"], "^" => [128, "e"], "_" => [12, "e"], "`" => [92, "i"], "a" => [95, "i"], "b" => [137, "i"], "c" => [142, "i"], "d" => [150, "i"], "e" => [74, "i"], "f" => [90, "i"], "g" => [98, "i"], "h" => [107, "i"], "i" => [140, "i"], "j" => [146, "i"], "k" => [102, "i"], "l" => [113, "i"], "m" => [121, "i"], "n" => [128, "i"], "o" => [12, "i"], "p" => [92, "o"], "q" => [95, "o"], "r" => [137, "o"], "s" => [142, "o"], "t" => [150, "o"], "u" => [74, "o"], "v" => [90, "o"], "w" => [98, "o"], "x" => [107, "o"], "y" => [140, "o"], "z" => [146, "o"], "{" => [102, "o"], "|" => [113, "o"], "}" => [121, "o"], "~" => [128, "o"], "" => [12, "o"], "\x80" => [92, "s"], "\x81" => [95, "s"], "\x82" => [137, "s"], "\x83" => [142, "s"], "\x84" => [150, "s"], "\x85" => [74, "s"], "\x86" => [90, "s"], "\x87" => [98, "s"], "\x88" => [107, "s"], "\x89" => [140, "s"], "\x8a" => [146, "s"], "\x8b" => [102, "s"], "\x8c" => [113, "s"], "\x8d" => [121, "s"], "\x8e" => [128, "s"], "\x8f" => [12, "s"], "\x90" => [92, "t"], "\x91" => [95, "t"], "\x92" => [137, "t"], "\x93" => [142, "t"], "\x94" => [150, "t"], "\x95" => [74, "t"], "\x96" => [90, "t"], "\x97" => [98, "t"], "\x98" => [107, "t"], "\x99" => [140, "t"], "\x9a" => [146, "t"], "\x9b" => [102, "t"], "\x9c" => [113, "t"], "\x9d" => [121, "t"], "\x9e" => [128, "t"], "\x9f" => [12, "t"], "\xa0" => [93, " "], "\xa1" => [138, " "], "\xa2" => [75, " "], "\xa3" => [91, " "], "\xa4" => [108, " "], "\xa5" => [103, " "], "\xa6" => [114, " "], "\xa7" => [14, " "], "\xa8" => [93, "%"], "\xa9" => [138, "%"], "\xaa" => [75, "%"], "\xab" => [91, "%"], "\xac" => [108, "%"], "\xad" => [103, "%"], "\xae" => [114, "%"], "\xaf" => [14, "%"], "\xb0" => [93, "-"], "\xb1" => [138, "-"], "\xb2" => [75, "-"], "\xb3" => [91, "-"], "\xb4" => [108, "-"], "\xb5" => [103, "-"], "\xb6" => [114, "-"], "\xb7" => [14, "-"], "\xb8" => [93, "."], "\xb9" => [138, "."], "\xba" => [75, "."], "\xbb" => [91, "."], "\xbc" => [108, "."], "\xbd" => [103, "."], "\xbe" => [114, "."], "\xbf" => [14, "."], "\xc0" => [93, "/"], "\xc1" => [138, "/"], "\xc2" => [75, "/"], "\xc3" => [91, "/"], "\xc4" => [108, "/"], "\xc5" => [103, "/"], "\xc6" => [114, "/"], "\xc7" => [14, "/"], "\xc8" => [93, "3"], "\xc9" => [138, "3"], "\xca" => [75, "3"], "\xcb" => [91, "3"], "\xcc" => [108, "3"], "\xcd" => [103, "3"], "\xce" => [114, "3"], "\xcf" => [14, "3"], "\xd0" => [93, "4"], "\xd1" => [138, "4"], "\xd2" => [75, "4"], "\xd3" => [91, "4"], "\xd4" => [108, "4"], "\xd5" => [103, "4"], "\xd6" => [114, "4"], "\xd7" => [14, "4"], "\xd8" => [93, "5"], "\xd9" => [138, "5"], "\xda" => [75, "5"], "\xdb" => [91, "5"], "\xdc" => [108, "5"], "\xdd" => [103, "5"], "\xde" => [114, "5"], "\xdf" => [14, "5"], "\xe0" => [93, "6"], "\xe1" => [138, "6"], "\xe2" => [75, "6"], "\xe3" => [91, "6"], "\xe4" => [108, "6"], "\xe5" => [103, "6"], "\xe6" => [114, "6"], "\xe7" => [14, "6"], "\xe8" => [93, "7"], "\xe9" => [138, "7"], "\xea" => [75, "7"], "\xeb" => [91, "7"], "\xec" => [108, "7"], "\xed" => [103, "7"], "\xee" => [114, "7"], "\xef" => [14, "7"], "\xf0" => [93, "8"], "\xf1" => [138, "8"], "\xf2" => [75, "8"], "\xf3" => [91, "8"], "\xf4" => [108, "8"], "\xf5" => [103, "8"], "\xf6" => [114, "8"], "\xf7" => [14, "8"], "\xf8" => [93, "9"], "\xf9" => [138, "9"], "\xfa" => [75, "9"], "\xfb" => [91, "9"], "\xfc" => [108, "9"], "\xfd" => [103, "9"], "\xfe" => [114, "9"], "\xff" => [14, "9"]], ["\x00" => [77, "!0"], "\x01" => [18, "!0"], "\x02" => [77, "!1"], "\x03" => [18, "!1"], "\x04" => [77, "!2"], "\x05" => [18, "!2"], "\x06" => [77, "!a"], "\x07" => [18, "!a"], "\x08" => [77, "!c"], "\t" => [18, "!c"], "\n" => [77, "!e"], "\v" => [18, "!e"], "\f" => [77, "!i"], "\r" => [18, "!i"], "\x0e" => [77, "!o"], "\x0f" => [18, "!o"], "\x10" => [77, "!s"], "\x11" => [18, "!s"], "\x12" => [77, "!t"], "\x13" => [18, "!t"], "\x14" => [0, "! "], "\x15" => [0, "!%"], "\x16" => [0, "!-"], "\x17" => [0, "!."], "\x18" => [0, "!/"], "\x19" => [0, "!3"], "\x1a" => [0, "!4"], "\x1b" => [0, "!5"], "\x1c" => [0, "!6"], "\x1d" => [0, "!7"], "\x1e" => [0, "!8"], "\x1f" => [0, "!9"], " " => [0, "!="], "!" => [0, "!A"], "\"" => [0, "!_"], "#" => [0, "!b"], "\$" => [0, "!d"], "%" => [0, "!f"], "&" => [0, "!g"], "'" => [0, "!h"], "(" => [0, "!l"], ")" => [0, "!m"], "*" => [0, "!n"], "+" => [0, "!p"], "," => [0, "!r"], "-" => [0, "!u"], "." => [100, "!"], "/" => [110, "!"], [111, "!"], [115, "!"], [116, "!"], [118, "!"], [119, "!"], [122, "!"], [123, "!"], [125, "!"], [126, "!"], [129, "!"], ":" => [143, "!"], ";" => [148, "!"], "<" => [151, "!"], "=" => [153, "!"], ">" => [83, "!"], "?" => [10, "!"], "@" => [77, "\"0"], "A" => [18, "\"0"], "B" => [77, "\"1"], "C" => [18, "\"1"], "D" => [77, "\"2"], "E" => [18, "\"2"], "F" => [77, "\"a"], "G" => [18, "\"a"], "H" => [77, "\"c"], "I" => [18, "\"c"], "J" => [77, "\"e"], "K" => [18, "\"e"], "L" => [77, "\"i"], "M" => [18, "\"i"], "N" => [77, "\"o"], "O" => [18, "\"o"], "P" => [77, "\"s"], "Q" => [18, "\"s"], "R" => [77, "\"t"], "S" => [18, "\"t"], "T" => [0, "\" "], "U" => [0, "\"%"], "V" => [0, "\"-"], "W" => [0, "\"."], "X" => [0, "\"/"], "Y" => [0, "\"3"], "Z" => [0, "\"4"], "[" => [0, "\"5"], "\\" => [0, "\"6"], "]" => [0, "\"7"], "^" => [0, "\"8"], "_" => [0, "\"9"], "`" => [0, "\"="], "a" => [0, "\"A"], "b" => [0, "\"_"], "c" => [0, "\"b"], "d" => [0, "\"d"], "e" => [0, "\"f"], "f" => [0, "\"g"], "g" => [0, "\"h"], "h" => [0, "\"l"], "i" => [0, "\"m"], "j" => [0, "\"n"], "k" => [0, "\"p"], "l" => [0, "\"r"], "m" => [0, "\"u"], "n" => [100, "\""], "o" => [110, "\""], "p" => [111, "\""], "q" => [115, "\""], "r" => [116, "\""], "s" => [118, "\""], "t" => [119, "\""], "u" => [122, "\""], "v" => [123, "\""], "w" => [125, "\""], "x" => [126, "\""], "y" => [129, "\""], "z" => [143, "\""], "{" => [148, "\""], "|" => [151, "\""], "}" => [153, "\""], "~" => [83, "\""], "" => [10, "\""], "\x80" => [77, "(0"], "\x81" => [18, "(0"], "\x82" => [77, "(1"], "\x83" => [18, "(1"], "\x84" => [77, "(2"], "\x85" => [18, "(2"], "\x86" => [77, "(a"], "\x87" => [18, "(a"], "\x88" => [77, "(c"], "\x89" => [18, "(c"], "\x8a" => [77, "(e"], "\x8b" => [18, "(e"], "\x8c" => [77, "(i"], "\x8d" => [18, "(i"], "\x8e" => [77, "(o"], "\x8f" => [18, "(o"], "\x90" => [77, "(s"], "\x91" => [18, "(s"], "\x92" => [77, "(t"], "\x93" => [18, "(t"], "\x94" => [0, "( "], "\x95" => [0, "(%"], "\x96" => [0, "(-"], "\x97" => [0, "(."], "\x98" => [0, "(/"], "\x99" => [0, "(3"], "\x9a" => [0, "(4"], "\x9b" => [0, "(5"], "\x9c" => [0, "(6"], "\x9d" => [0, "(7"], "\x9e" => [0, "(8"], "\x9f" => [0, "(9"], "\xa0" => [0, "(="], "\xa1" => [0, "(A"], "\xa2" => [0, "(_"], "\xa3" => [0, "(b"], "\xa4" => [0, "(d"], "\xa5" => [0, "(f"], "\xa6" => [0, "(g"], "\xa7" => [0, "(h"], "\xa8" => [0, "(l"], "\xa9" => [0, "(m"], "\xaa" => [0, "(n"], "\xab" => [0, "(p"], "\xac" => [0, "(r"], "\xad" => [0, "(u"], "\xae" => [100, "("], "\xaf" => [110, "("], "\xb0" => [111, "("], "\xb1" => [115, "("], "\xb2" => [116, "("], "\xb3" => [118, "("], "\xb4" => [119, "("], "\xb5" => [122, "("], "\xb6" => [123, "("], "\xb7" => [125, "("], "\xb8" => [126, "("], "\xb9" => [129, "("], "\xba" => [143, "("], "\xbb" => [148, "("], "\xbc" => [151, "("], "\xbd" => [153, "("], "\xbe" => [83, "("], "\xbf" => [10, "("], "\xc0" => [77, ")0"], "\xc1" => [18, ")0"], "\xc2" => [77, ")1"], "\xc3" => [18, ")1"], "\xc4" => [77, ")2"], "\xc5" => [18, ")2"], "\xc6" => [77, ")a"], "\xc7" => [18, ")a"], "\xc8" => [77, ")c"], "\xc9" => [18, ")c"], "\xca" => [77, ")e"], "\xcb" => [18, ")e"], "\xcc" => [77, ")i"], "\xcd" => [18, ")i"], "\xce" => [77, ")o"], "\xcf" => [18, ")o"], "\xd0" => [77, ")s"], "\xd1" => [18, ")s"], "\xd2" => [77, ")t"], "\xd3" => [18, ")t"], "\xd4" => [0, ") "], "\xd5" => [0, ")%"], "\xd6" => [0, ")-"], "\xd7" => [0, ")."], "\xd8" => [0, ")/"], "\xd9" => [0, ")3"], "\xda" => [0, ")4"], "\xdb" => [0, ")5"], "\xdc" => [0, ")6"], "\xdd" => [0, ")7"], "\xde" => [0, ")8"], "\xdf" => [0, ")9"], "\xe0" => [0, ")="], "\xe1" => [0, ")A"], "\xe2" => [0, ")_"], "\xe3" => [0, ")b"], "\xe4" => [0, ")d"], "\xe5" => [0, ")f"], "\xe6" => [0, ")g"], "\xe7" => [0, ")h"], "\xe8" => [0, ")l"], "\xe9" => [0, ")m"], "\xea" => [0, ")n"], "\xeb" => [0, ")p"], "\xec" => [0, ")r"], "\xed" => [0, ")u"], "\xee" => [100, ")"], "\xef" => [110, ")"], "\xf0" => [111, ")"], "\xf1" => [115, ")"], "\xf2" => [116, ")"], "\xf3" => [118, ")"], "\xf4" => [119, ")"], "\xf5" => [122, ")"], "\xf6" => [123, ")"], "\xf7" => [125, ")"], "\xf8" => [126, ")"], "\xf9" => [129, ")"], "\xfa" => [143, ")"], "\xfb" => [148, ")"], "\xfc" => [151, ")"], "\xfd" => [153, ")"], "\xfe" => [83, ")"], "\xff" => [10, ")"]], ["\x00" => [94, "!0"], "\x01" => [76, "!0"], "\x02" => [104, "!0"], "\x03" => [16, "!0"], "\x04" => [94, "!1"], "\x05" => [76, "!1"], "\x06" => [104, "!1"], "\x07" => [16, "!1"], "\x08" => [94, "!2"], "\t" => [76, "!2"], "\n" => [104, "!2"], "\v" => [16, "!2"], "\f" => [94, "!a"], "\r" => [76, "!a"], "\x0e" => [104, "!a"], "\x0f" => [16, "!a"], "\x10" => [94, "!c"], "\x11" => [76, "!c"], "\x12" => [104, "!c"], "\x13" => [16, "!c"], "\x14" => [94, "!e"], "\x15" => [76, "!e"], "\x16" => [104, "!e"], "\x17" => [16, "!e"], "\x18" => [94, "!i"], "\x19" => [76, "!i"], "\x1a" => [104, "!i"], "\x1b" => [16, "!i"], "\x1c" => [94, "!o"], "\x1d" => [76, "!o"], "\x1e" => [104, "!o"], "\x1f" => [16, "!o"], " " => [94, "!s"], "!" => [76, "!s"], "\"" => [104, "!s"], "#" => [16, "!s"], "\$" => [94, "!t"], "%" => [76, "!t"], "&" => [104, "!t"], "'" => [16, "!t"], "(" => [77, "! "], ")" => [18, "! "], "*" => [77, "!%"], "+" => [18, "!%"], "," => [77, "!-"], "-" => [18, "!-"], "." => [77, "!."], "/" => [18, "!."], [77, "!/"], [18, "!/"], [77, "!3"], [18, "!3"], [77, "!4"], [18, "!4"], [77, "!5"], [18, "!5"], [77, "!6"], [18, "!6"], ":" => [77, "!7"], ";" => [18, "!7"], "<" => [77, "!8"], "=" => [18, "!8"], ">" => [77, "!9"], "?" => [18, "!9"], "@" => [77, "!="], "A" => [18, "!="], "B" => [77, "!A"], "C" => [18, "!A"], "D" => [77, "!_"], "E" => [18, "!_"], "F" => [77, "!b"], "G" => [18, "!b"], "H" => [77, "!d"], "I" => [18, "!d"], "J" => [77, "!f"], "K" => [18, "!f"], "L" => [77, "!g"], "M" => [18, "!g"], "N" => [77, "!h"], "O" => [18, "!h"], "P" => [77, "!l"], "Q" => [18, "!l"], "R" => [77, "!m"], "S" => [18, "!m"], "T" => [77, "!n"], "U" => [18, "!n"], "V" => [77, "!p"], "W" => [18, "!p"], "X" => [77, "!r"], "Y" => [18, "!r"], "Z" => [77, "!u"], "[" => [18, "!u"], "\\" => [0, "!:"], "]" => [0, "!B"], "^" => [0, "!C"], "_" => [0, "!D"], "`" => [0, "!E"], "a" => [0, "!F"], "b" => [0, "!G"], "c" => [0, "!H"], "d" => [0, "!I"], "e" => [0, "!J"], "f" => [0, "!K"], "g" => [0, "!L"], "h" => [0, "!M"], "i" => [0, "!N"], "j" => [0, "!O"], "k" => [0, "!P"], "l" => [0, "!Q"], "m" => [0, "!R"], "n" => [0, "!S"], "o" => [0, "!T"], "p" => [0, "!U"], "q" => [0, "!V"], "r" => [0, "!W"], "s" => [0, "!Y"], "t" => [0, "!j"], "u" => [0, "!k"], "v" => [0, "!q"], "w" => [0, "!v"], "x" => [0, "!w"], "y" => [0, "!x"], "z" => [0, "!y"], "{" => [0, "!z"], "|" => [82, "!"], "}" => [87, "!"], "~" => [130, "!"], "" => [9, "!"], "\x80" => [94, "\"0"], "\x81" => [76, "\"0"], "\x82" => [104, "\"0"], "\x83" => [16, "\"0"], "\x84" => [94, "\"1"], "\x85" => [76, "\"1"], "\x86" => [104, "\"1"], "\x87" => [16, "\"1"], "\x88" => [94, "\"2"], "\x89" => [76, "\"2"], "\x8a" => [104, "\"2"], "\x8b" => [16, "\"2"], "\x8c" => [94, "\"a"], "\x8d" => [76, "\"a"], "\x8e" => [104, "\"a"], "\x8f" => [16, "\"a"], "\x90" => [94, "\"c"], "\x91" => [76, "\"c"], "\x92" => [104, "\"c"], "\x93" => [16, "\"c"], "\x94" => [94, "\"e"], "\x95" => [76, "\"e"], "\x96" => [104, "\"e"], "\x97" => [16, "\"e"], "\x98" => [94, "\"i"], "\x99" => [76, "\"i"], "\x9a" => [104, "\"i"], "\x9b" => [16, "\"i"], "\x9c" => [94, "\"o"], "\x9d" => [76, "\"o"], "\x9e" => [104, "\"o"], "\x9f" => [16, "\"o"], "\xa0" => [94, "\"s"], "\xa1" => [76, "\"s"], "\xa2" => [104, "\"s"], "\xa3" => [16, "\"s"], "\xa4" => [94, "\"t"], "\xa5" => [76, "\"t"], "\xa6" => [104, "\"t"], "\xa7" => [16, "\"t"], "\xa8" => [77, "\" "], "\xa9" => [18, "\" "], "\xaa" => [77, "\"%"], "\xab" => [18, "\"%"], "\xac" => [77, "\"-"], "\xad" => [18, "\"-"], "\xae" => [77, "\"."], "\xaf" => [18, "\"."], "\xb0" => [77, "\"/"], "\xb1" => [18, "\"/"], "\xb2" => [77, "\"3"], "\xb3" => [18, "\"3"], "\xb4" => [77, "\"4"], "\xb5" => [18, "\"4"], "\xb6" => [77, "\"5"], "\xb7" => [18, "\"5"], "\xb8" => [77, "\"6"], "\xb9" => [18, "\"6"], "\xba" => [77, "\"7"], "\xbb" => [18, "\"7"], "\xbc" => [77, "\"8"], "\xbd" => [18, "\"8"], "\xbe" => [77, "\"9"], "\xbf" => [18, "\"9"], "\xc0" => [77, "\"="], "\xc1" => [18, "\"="], "\xc2" => [77, "\"A"], "\xc3" => [18, "\"A"], "\xc4" => [77, "\"_"], "\xc5" => [18, "\"_"], "\xc6" => [77, "\"b"], "\xc7" => [18, "\"b"], "\xc8" => [77, "\"d"], "\xc9" => [18, "\"d"], "\xca" => [77, "\"f"], "\xcb" => [18, "\"f"], "\xcc" => [77, "\"g"], "\xcd" => [18, "\"g"], "\xce" => [77, "\"h"], "\xcf" => [18, "\"h"], "\xd0" => [77, "\"l"], "\xd1" => [18, "\"l"], "\xd2" => [77, "\"m"], "\xd3" => [18, "\"m"], "\xd4" => [77, "\"n"], "\xd5" => [18, "\"n"], "\xd6" => [77, "\"p"], "\xd7" => [18, "\"p"], "\xd8" => [77, "\"r"], "\xd9" => [18, "\"r"], "\xda" => [77, "\"u"], "\xdb" => [18, "\"u"], "\xdc" => [0, "\":"], "\xdd" => [0, "\"B"], "\xde" => [0, "\"C"], "\xdf" => [0, "\"D"], "\xe0" => [0, "\"E"], "\xe1" => [0, "\"F"], "\xe2" => [0, "\"G"], "\xe3" => [0, "\"H"], "\xe4" => [0, "\"I"], "\xe5" => [0, "\"J"], "\xe6" => [0, "\"K"], "\xe7" => [0, "\"L"], "\xe8" => [0, "\"M"], "\xe9" => [0, "\"N"], "\xea" => [0, "\"O"], "\xeb" => [0, "\"P"], "\xec" => [0, "\"Q"], "\xed" => [0, "\"R"], "\xee" => [0, "\"S"], "\xef" => [0, "\"T"], "\xf0" => [0, "\"U"], "\xf1" => [0, "\"V"], "\xf2" => [0, "\"W"], "\xf3" => [0, "\"Y"], "\xf4" => [0, "\"j"], "\xf5" => [0, "\"k"], "\xf6" => [0, "\"q"], "\xf7" => [0, "\"v"], "\xf8" => [0, "\"w"], "\xf9" => [0, "\"x"], "\xfa" => [0, "\"y"], "\xfb" => [0, "\"z"], "\xfc" => [82, "\""], "\xfd" => [87, "\""], "\xfe" => [130, "\""], "\xff" => [9, "\""]], ["\x00" => [94, "#0"], "\x01" => [76, "#0"], "\x02" => [104, "#0"], "\x03" => [16, "#0"], "\x04" => [94, "#1"], "\x05" => [76, "#1"], "\x06" => [104, "#1"], "\x07" => [16, "#1"], "\x08" => [94, "#2"], "\t" => [76, "#2"], "\n" => [104, "#2"], "\v" => [16, "#2"], "\f" => [94, "#a"], "\r" => [76, "#a"], "\x0e" => [104, "#a"], "\x0f" => [16, "#a"], "\x10" => [94, "#c"], "\x11" => [76, "#c"], "\x12" => [104, "#c"], "\x13" => [16, "#c"], "\x14" => [94, "#e"], "\x15" => [76, "#e"], "\x16" => [104, "#e"], "\x17" => [16, "#e"], "\x18" => [94, "#i"], "\x19" => [76, "#i"], "\x1a" => [104, "#i"], "\x1b" => [16, "#i"], "\x1c" => [94, "#o"], "\x1d" => [76, "#o"], "\x1e" => [104, "#o"], "\x1f" => [16, "#o"], " " => [94, "#s"], "!" => [76, "#s"], "\"" => [104, "#s"], "#" => [16, "#s"], "\$" => [94, "#t"], "%" => [76, "#t"], "&" => [104, "#t"], "'" => [16, "#t"], "(" => [77, "# "], ")" => [18, "# "], "*" => [77, "#%"], "+" => [18, "#%"], "," => [77, "#-"], "-" => [18, "#-"], "." => [77, "#."], "/" => [18, "#."], [77, "#/"], [18, "#/"], [77, "#3"], [18, "#3"], [77, "#4"], [18, "#4"], [77, "#5"], [18, "#5"], [77, "#6"], [18, "#6"], ":" => [77, "#7"], ";" => [18, "#7"], "<" => [77, "#8"], "=" => [18, "#8"], ">" => [77, "#9"], "?" => [18, "#9"], "@" => [77, "#="], "A" => [18, "#="], "B" => [77, "#A"], "C" => [18, "#A"], "D" => [77, "#_"], "E" => [18, "#_"], "F" => [77, "#b"], "G" => [18, "#b"], "H" => [77, "#d"], "I" => [18, "#d"], "J" => [77, "#f"], "K" => [18, "#f"], "L" => [77, "#g"], "M" => [18, "#g"], "N" => [77, "#h"], "O" => [18, "#h"], "P" => [77, "#l"], "Q" => [18, "#l"], "R" => [77, "#m"], "S" => [18, "#m"], "T" => [77, "#n"], "U" => [18, "#n"], "V" => [77, "#p"], "W" => [18, "#p"], "X" => [77, "#r"], "Y" => [18, "#r"], "Z" => [77, "#u"], "[" => [18, "#u"], "\\" => [0, "#:"], "]" => [0, "#B"], "^" => [0, "#C"], "_" => [0, "#D"], "`" => [0, "#E"], "a" => [0, "#F"], "b" => [0, "#G"], "c" => [0, "#H"], "d" => [0, "#I"], "e" => [0, "#J"], "f" => [0, "#K"], "g" => [0, "#L"], "h" => [0, "#M"], "i" => [0, "#N"], "j" => [0, "#O"], "k" => [0, "#P"], "l" => [0, "#Q"], "m" => [0, "#R"], "n" => [0, "#S"], "o" => [0, "#T"], "p" => [0, "#U"], "q" => [0, "#V"], "r" => [0, "#W"], "s" => [0, "#Y"], "t" => [0, "#j"], "u" => [0, "#k"], "v" => [0, "#q"], "w" => [0, "#v"], "x" => [0, "#w"], "y" => [0, "#x"], "z" => [0, "#y"], "{" => [0, "#z"], "|" => [82, "#"], "}" => [87, "#"], "~" => [130, "#"], "" => [9, "#"], "\x80" => [94, ">0"], "\x81" => [76, ">0"], "\x82" => [104, ">0"], "\x83" => [16, ">0"], "\x84" => [94, ">1"], "\x85" => [76, ">1"], "\x86" => [104, ">1"], "\x87" => [16, ">1"], "\x88" => [94, ">2"], "\x89" => [76, ">2"], "\x8a" => [104, ">2"], "\x8b" => [16, ">2"], "\x8c" => [94, ">a"], "\x8d" => [76, ">a"], "\x8e" => [104, ">a"], "\x8f" => [16, ">a"], "\x90" => [94, ">c"], "\x91" => [76, ">c"], "\x92" => [104, ">c"], "\x93" => [16, ">c"], "\x94" => [94, ">e"], "\x95" => [76, ">e"], "\x96" => [104, ">e"], "\x97" => [16, ">e"], "\x98" => [94, ">i"], "\x99" => [76, ">i"], "\x9a" => [104, ">i"], "\x9b" => [16, ">i"], "\x9c" => [94, ">o"], "\x9d" => [76, ">o"], "\x9e" => [104, ">o"], "\x9f" => [16, ">o"], "\xa0" => [94, ">s"], "\xa1" => [76, ">s"], "\xa2" => [104, ">s"], "\xa3" => [16, ">s"], "\xa4" => [94, ">t"], "\xa5" => [76, ">t"], "\xa6" => [104, ">t"], "\xa7" => [16, ">t"], "\xa8" => [77, "> "], "\xa9" => [18, "> "], "\xaa" => [77, ">%"], "\xab" => [18, ">%"], "\xac" => [77, ">-"], "\xad" => [18, ">-"], "\xae" => [77, ">."], "\xaf" => [18, ">."], "\xb0" => [77, ">/"], "\xb1" => [18, ">/"], "\xb2" => [77, ">3"], "\xb3" => [18, ">3"], "\xb4" => [77, ">4"], "\xb5" => [18, ">4"], "\xb6" => [77, ">5"], "\xb7" => [18, ">5"], "\xb8" => [77, ">6"], "\xb9" => [18, ">6"], "\xba" => [77, ">7"], "\xbb" => [18, ">7"], "\xbc" => [77, ">8"], "\xbd" => [18, ">8"], "\xbe" => [77, ">9"], "\xbf" => [18, ">9"], "\xc0" => [77, ">="], "\xc1" => [18, ">="], "\xc2" => [77, ">A"], "\xc3" => [18, ">A"], "\xc4" => [77, ">_"], "\xc5" => [18, ">_"], "\xc6" => [77, ">b"], "\xc7" => [18, ">b"], "\xc8" => [77, ">d"], "\xc9" => [18, ">d"], "\xca" => [77, ">f"], "\xcb" => [18, ">f"], "\xcc" => [77, ">g"], "\xcd" => [18, ">g"], "\xce" => [77, ">h"], "\xcf" => [18, ">h"], "\xd0" => [77, ">l"], "\xd1" => [18, ">l"], "\xd2" => [77, ">m"], "\xd3" => [18, ">m"], "\xd4" => [77, ">n"], "\xd5" => [18, ">n"], "\xd6" => [77, ">p"], "\xd7" => [18, ">p"], "\xd8" => [77, ">r"], "\xd9" => [18, ">r"], "\xda" => [77, ">u"], "\xdb" => [18, ">u"], "\xdc" => [0, ">:"], "\xdd" => [0, ">B"], "\xde" => [0, ">C"], "\xdf" => [0, ">D"], "\xe0" => [0, ">E"], "\xe1" => [0, ">F"], "\xe2" => [0, ">G"], "\xe3" => [0, ">H"], "\xe4" => [0, ">I"], "\xe5" => [0, ">J"], "\xe6" => [0, ">K"], "\xe7" => [0, ">L"], "\xe8" => [0, ">M"], "\xe9" => [0, ">N"], "\xea" => [0, ">O"], "\xeb" => [0, ">P"], "\xec" => [0, ">Q"], "\xed" => [0, ">R"], "\xee" => [0, ">S"], "\xef" => [0, ">T"], "\xf0" => [0, ">U"], "\xf1" => [0, ">V"], "\xf2" => [0, ">W"], "\xf3" => [0, ">Y"], "\xf4" => [0, ">j"], "\xf5" => [0, ">k"], "\xf6" => [0, ">q"], "\xf7" => [0, ">v"], "\xf8" => [0, ">w"], "\xf9" => [0, ">x"], "\xfa" => [0, ">y"], "\xfb" => [0, ">z"], "\xfc" => [82, ">"], "\xfd" => [87, ">"], "\xfe" => [130, ">"], "\xff" => [9, ">"]], ["\x00" => [94, "|0"], "\x01" => [76, "|0"], "\x02" => [104, "|0"], "\x03" => [16, "|0"], "\x04" => [94, "|1"], "\x05" => [76, "|1"], "\x06" => [104, "|1"], "\x07" => [16, "|1"], "\x08" => [94, "|2"], "\t" => [76, "|2"], "\n" => [104, "|2"], "\v" => [16, "|2"], "\f" => [94, "|a"], "\r" => [76, "|a"], "\x0e" => [104, "|a"], "\x0f" => [16, "|a"], "\x10" => [94, "|c"], "\x11" => [76, "|c"], "\x12" => [104, "|c"], "\x13" => [16, "|c"], "\x14" => [94, "|e"], "\x15" => [76, "|e"], "\x16" => [104, "|e"], "\x17" => [16, "|e"], "\x18" => [94, "|i"], "\x19" => [76, "|i"], "\x1a" => [104, "|i"], "\x1b" => [16, "|i"], "\x1c" => [94, "|o"], "\x1d" => [76, "|o"], "\x1e" => [104, "|o"], "\x1f" => [16, "|o"], " " => [94, "|s"], "!" => [76, "|s"], "\"" => [104, "|s"], "#" => [16, "|s"], "\$" => [94, "|t"], "%" => [76, "|t"], "&" => [104, "|t"], "'" => [16, "|t"], "(" => [77, "| "], ")" => [18, "| "], "*" => [77, "|%"], "+" => [18, "|%"], "," => [77, "|-"], "-" => [18, "|-"], "." => [77, "|."], "/" => [18, "|."], [77, "|/"], [18, "|/"], [77, "|3"], [18, "|3"], [77, "|4"], [18, "|4"], [77, "|5"], [18, "|5"], [77, "|6"], [18, "|6"], ":" => [77, "|7"], ";" => [18, "|7"], "<" => [77, "|8"], "=" => [18, "|8"], ">" => [77, "|9"], "?" => [18, "|9"], "@" => [77, "|="], "A" => [18, "|="], "B" => [77, "|A"], "C" => [18, "|A"], "D" => [77, "|_"], "E" => [18, "|_"], "F" => [77, "|b"], "G" => [18, "|b"], "H" => [77, "|d"], "I" => [18, "|d"], "J" => [77, "|f"], "K" => [18, "|f"], "L" => [77, "|g"], "M" => [18, "|g"], "N" => [77, "|h"], "O" => [18, "|h"], "P" => [77, "|l"], "Q" => [18, "|l"], "R" => [77, "|m"], "S" => [18, "|m"], "T" => [77, "|n"], "U" => [18, "|n"], "V" => [77, "|p"], "W" => [18, "|p"], "X" => [77, "|r"], "Y" => [18, "|r"], "Z" => [77, "|u"], "[" => [18, "|u"], "\\" => [0, "|:"], "]" => [0, "|B"], "^" => [0, "|C"], "_" => [0, "|D"], "`" => [0, "|E"], "a" => [0, "|F"], "b" => [0, "|G"], "c" => [0, "|H"], "d" => [0, "|I"], "e" => [0, "|J"], "f" => [0, "|K"], "g" => [0, "|L"], "h" => [0, "|M"], "i" => [0, "|N"], "j" => [0, "|O"], "k" => [0, "|P"], "l" => [0, "|Q"], "m" => [0, "|R"], "n" => [0, "|S"], "o" => [0, "|T"], "p" => [0, "|U"], "q" => [0, "|V"], "r" => [0, "|W"], "s" => [0, "|Y"], "t" => [0, "|j"], "u" => [0, "|k"], "v" => [0, "|q"], "w" => [0, "|v"], "x" => [0, "|w"], "y" => [0, "|x"], "z" => [0, "|y"], "{" => [0, "|z"], "|" => [82, "|"], "}" => [87, "|"], "~" => [130, "|"], "" => [9, "|"], "\x80" => [77, "#0"], "\x81" => [18, "#0"], "\x82" => [77, "#1"], "\x83" => [18, "#1"], "\x84" => [77, "#2"], "\x85" => [18, "#2"], "\x86" => [77, "#a"], "\x87" => [18, "#a"], "\x88" => [77, "#c"], "\x89" => [18, "#c"], "\x8a" => [77, "#e"], "\x8b" => [18, "#e"], "\x8c" => [77, "#i"], "\x8d" => [18, "#i"], "\x8e" => [77, "#o"], "\x8f" => [18, "#o"], "\x90" => [77, "#s"], "\x91" => [18, "#s"], "\x92" => [77, "#t"], "\x93" => [18, "#t"], "\x94" => [0, "# "], "\x95" => [0, "#%"], "\x96" => [0, "#-"], "\x97" => [0, "#."], "\x98" => [0, "#/"], "\x99" => [0, "#3"], "\x9a" => [0, "#4"], "\x9b" => [0, "#5"], "\x9c" => [0, "#6"], "\x9d" => [0, "#7"], "\x9e" => [0, "#8"], "\x9f" => [0, "#9"], "\xa0" => [0, "#="], "\xa1" => [0, "#A"], "\xa2" => [0, "#_"], "\xa3" => [0, "#b"], "\xa4" => [0, "#d"], "\xa5" => [0, "#f"], "\xa6" => [0, "#g"], "\xa7" => [0, "#h"], "\xa8" => [0, "#l"], "\xa9" => [0, "#m"], "\xaa" => [0, "#n"], "\xab" => [0, "#p"], "\xac" => [0, "#r"], "\xad" => [0, "#u"], "\xae" => [100, "#"], "\xaf" => [110, "#"], "\xb0" => [111, "#"], "\xb1" => [115, "#"], "\xb2" => [116, "#"], "\xb3" => [118, "#"], "\xb4" => [119, "#"], "\xb5" => [122, "#"], "\xb6" => [123, "#"], "\xb7" => [125, "#"], "\xb8" => [126, "#"], "\xb9" => [129, "#"], "\xba" => [143, "#"], "\xbb" => [148, "#"], "\xbc" => [151, "#"], "\xbd" => [153, "#"], "\xbe" => [83, "#"], "\xbf" => [10, "#"], "\xc0" => [77, ">0"], "\xc1" => [18, ">0"], "\xc2" => [77, ">1"], "\xc3" => [18, ">1"], "\xc4" => [77, ">2"], "\xc5" => [18, ">2"], "\xc6" => [77, ">a"], "\xc7" => [18, ">a"], "\xc8" => [77, ">c"], "\xc9" => [18, ">c"], "\xca" => [77, ">e"], "\xcb" => [18, ">e"], "\xcc" => [77, ">i"], "\xcd" => [18, ">i"], "\xce" => [77, ">o"], "\xcf" => [18, ">o"], "\xd0" => [77, ">s"], "\xd1" => [18, ">s"], "\xd2" => [77, ">t"], "\xd3" => [18, ">t"], "\xd4" => [0, "> "], "\xd5" => [0, ">%"], "\xd6" => [0, ">-"], "\xd7" => [0, ">."], "\xd8" => [0, ">/"], "\xd9" => [0, ">3"], "\xda" => [0, ">4"], "\xdb" => [0, ">5"], "\xdc" => [0, ">6"], "\xdd" => [0, ">7"], "\xde" => [0, ">8"], "\xdf" => [0, ">9"], "\xe0" => [0, ">="], "\xe1" => [0, ">A"], "\xe2" => [0, ">_"], "\xe3" => [0, ">b"], "\xe4" => [0, ">d"], "\xe5" => [0, ">f"], "\xe6" => [0, ">g"], "\xe7" => [0, ">h"], "\xe8" => [0, ">l"], "\xe9" => [0, ">m"], "\xea" => [0, ">n"], "\xeb" => [0, ">p"], "\xec" => [0, ">r"], "\xed" => [0, ">u"], "\xee" => [100, ">"], "\xef" => [110, ">"], "\xf0" => [111, ">"], "\xf1" => [115, ">"], "\xf2" => [116, ">"], "\xf3" => [118, ">"], "\xf4" => [119, ">"], "\xf5" => [122, ">"], "\xf6" => [123, ">"], "\xf7" => [125, ">"], "\xf8" => [126, ">"], "\xf9" => [129, ">"], "\xfa" => [143, ">"], "\xfb" => [148, ">"], "\xfc" => [151, ">"], "\xfd" => [153, ">"], "\xfe" => [83, ">"], "\xff" => [10, ">"]], ["\x00" => [94, "&0"], "\x01" => [76, "&0"], "\x02" => [104, "&0"], "\x03" => [16, "&0"], "\x04" => [94, "&1"], "\x05" => [76, "&1"], "\x06" => [104, "&1"], "\x07" => [16, "&1"], "\x08" => [94, "&2"], "\t" => [76, "&2"], "\n" => [104, "&2"], "\v" => [16, "&2"], "\f" => [94, "&a"], "\r" => [76, "&a"], "\x0e" => [104, "&a"], "\x0f" => [16, "&a"], "\x10" => [94, "&c"], "\x11" => [76, "&c"], "\x12" => [104, "&c"], "\x13" => [16, "&c"], "\x14" => [94, "&e"], "\x15" => [76, "&e"], "\x16" => [104, "&e"], "\x17" => [16, "&e"], "\x18" => [94, "&i"], "\x19" => [76, "&i"], "\x1a" => [104, "&i"], "\x1b" => [16, "&i"], "\x1c" => [94, "&o"], "\x1d" => [76, "&o"], "\x1e" => [104, "&o"], "\x1f" => [16, "&o"], " " => [94, "&s"], "!" => [76, "&s"], "\"" => [104, "&s"], "#" => [16, "&s"], "\$" => [94, "&t"], "%" => [76, "&t"], "&" => [104, "&t"], "'" => [16, "&t"], "(" => [77, "& "], ")" => [18, "& "], "*" => [77, "&%"], "+" => [18, "&%"], "," => [77, "&-"], "-" => [18, "&-"], "." => [77, "&."], "/" => [18, "&."], [77, "&/"], [18, "&/"], [77, "&3"], [18, "&3"], [77, "&4"], [18, "&4"], [77, "&5"], [18, "&5"], [77, "&6"], [18, "&6"], ":" => [77, "&7"], ";" => [18, "&7"], "<" => [77, "&8"], "=" => [18, "&8"], ">" => [77, "&9"], "?" => [18, "&9"], "@" => [77, "&="], "A" => [18, "&="], "B" => [77, "&A"], "C" => [18, "&A"], "D" => [77, "&_"], "E" => [18, "&_"], "F" => [77, "&b"], "G" => [18, "&b"], "H" => [77, "&d"], "I" => [18, "&d"], "J" => [77, "&f"], "K" => [18, "&f"], "L" => [77, "&g"], "M" => [18, "&g"], "N" => [77, "&h"], "O" => [18, "&h"], "P" => [77, "&l"], "Q" => [18, "&l"], "R" => [77, "&m"], "S" => [18, "&m"], "T" => [77, "&n"], "U" => [18, "&n"], "V" => [77, "&p"], "W" => [18, "&p"], "X" => [77, "&r"], "Y" => [18, "&r"], "Z" => [77, "&u"], "[" => [18, "&u"], "\\" => [0, "&:"], "]" => [0, "&B"], "^" => [0, "&C"], "_" => [0, "&D"], "`" => [0, "&E"], "a" => [0, "&F"], "b" => [0, "&G"], "c" => [0, "&H"], "d" => [0, "&I"], "e" => [0, "&J"], "f" => [0, "&K"], "g" => [0, "&L"], "h" => [0, "&M"], "i" => [0, "&N"], "j" => [0, "&O"], "k" => [0, "&P"], "l" => [0, "&Q"], "m" => [0, "&R"], "n" => [0, "&S"], "o" => [0, "&T"], "p" => [0, "&U"], "q" => [0, "&V"], "r" => [0, "&W"], "s" => [0, "&Y"], "t" => [0, "&j"], "u" => [0, "&k"], "v" => [0, "&q"], "w" => [0, "&v"], "x" => [0, "&w"], "y" => [0, "&x"], "z" => [0, "&y"], "{" => [0, "&z"], "|" => [82, "&"], "}" => [87, "&"], "~" => [130, "&"], "" => [9, "&"], "\x80" => [94, "*0"], "\x81" => [76, "*0"], "\x82" => [104, "*0"], "\x83" => [16, "*0"], "\x84" => [94, "*1"], "\x85" => [76, "*1"], "\x86" => [104, "*1"], "\x87" => [16, "*1"], "\x88" => [94, "*2"], "\x89" => [76, "*2"], "\x8a" => [104, "*2"], "\x8b" => [16, "*2"], "\x8c" => [94, "*a"], "\x8d" => [76, "*a"], "\x8e" => [104, "*a"], "\x8f" => [16, "*a"], "\x90" => [94, "*c"], "\x91" => [76, "*c"], "\x92" => [104, "*c"], "\x93" => [16, "*c"], "\x94" => [94, "*e"], "\x95" => [76, "*e"], "\x96" => [104, "*e"], "\x97" => [16, "*e"], "\x98" => [94, "*i"], "\x99" => [76, "*i"], "\x9a" => [104, "*i"], "\x9b" => [16, "*i"], "\x9c" => [94, "*o"], "\x9d" => [76, "*o"], "\x9e" => [104, "*o"], "\x9f" => [16, "*o"], "\xa0" => [94, "*s"], "\xa1" => [76, "*s"], "\xa2" => [104, "*s"], "\xa3" => [16, "*s"], "\xa4" => [94, "*t"], "\xa5" => [76, "*t"], "\xa6" => [104, "*t"], "\xa7" => [16, "*t"], "\xa8" => [77, "* "], "\xa9" => [18, "* "], "\xaa" => [77, "*%"], "\xab" => [18, "*%"], "\xac" => [77, "*-"], "\xad" => [18, "*-"], "\xae" => [77, "*."], "\xaf" => [18, "*."], "\xb0" => [77, "*/"], "\xb1" => [18, "*/"], "\xb2" => [77, "*3"], "\xb3" => [18, "*3"], "\xb4" => [77, "*4"], "\xb5" => [18, "*4"], "\xb6" => [77, "*5"], "\xb7" => [18, "*5"], "\xb8" => [77, "*6"], "\xb9" => [18, "*6"], "\xba" => [77, "*7"], "\xbb" => [18, "*7"], "\xbc" => [77, "*8"], "\xbd" => [18, "*8"], "\xbe" => [77, "*9"], "\xbf" => [18, "*9"], "\xc0" => [77, "*="], "\xc1" => [18, "*="], "\xc2" => [77, "*A"], "\xc3" => [18, "*A"], "\xc4" => [77, "*_"], "\xc5" => [18, "*_"], "\xc6" => [77, "*b"], "\xc7" => [18, "*b"], "\xc8" => [77, "*d"], "\xc9" => [18, "*d"], "\xca" => [77, "*f"], "\xcb" => [18, "*f"], "\xcc" => [77, "*g"], "\xcd" => [18, "*g"], "\xce" => [77, "*h"], "\xcf" => [18, "*h"], "\xd0" => [77, "*l"], "\xd1" => [18, "*l"], "\xd2" => [77, "*m"], "\xd3" => [18, "*m"], "\xd4" => [77, "*n"], "\xd5" => [18, "*n"], "\xd6" => [77, "*p"], "\xd7" => [18, "*p"], "\xd8" => [77, "*r"], "\xd9" => [18, "*r"], "\xda" => [77, "*u"], "\xdb" => [18, "*u"], "\xdc" => [0, "*:"], "\xdd" => [0, "*B"], "\xde" => [0, "*C"], "\xdf" => [0, "*D"], "\xe0" => [0, "*E"], "\xe1" => [0, "*F"], "\xe2" => [0, "*G"], "\xe3" => [0, "*H"], "\xe4" => [0, "*I"], "\xe5" => [0, "*J"], "\xe6" => [0, "*K"], "\xe7" => [0, "*L"], "\xe8" => [0, "*M"], "\xe9" => [0, "*N"], "\xea" => [0, "*O"], "\xeb" => [0, "*P"], "\xec" => [0, "*Q"], "\xed" => [0, "*R"], "\xee" => [0, "*S"], "\xef" => [0, "*T"], "\xf0" => [0, "*U"], "\xf1" => [0, "*V"], "\xf2" => [0, "*W"], "\xf3" => [0, "*Y"], "\xf4" => [0, "*j"], "\xf5" => [0, "*k"], "\xf6" => [0, "*q"], "\xf7" => [0, "*v"], "\xf8" => [0, "*w"], "\xf9" => [0, "*x"], "\xfa" => [0, "*y"], "\xfb" => [0, "*z"], "\xfc" => [82, "*"], "\xfd" => [87, "*"], "\xfe" => [130, "*"], "\xff" => [9, "*"]], ["\x00" => [77, "&0"], "\x01" => [18, "&0"], "\x02" => [77, "&1"], "\x03" => [18, "&1"], "\x04" => [77, "&2"], "\x05" => [18, "&2"], "\x06" => [77, "&a"], "\x07" => [18, "&a"], "\x08" => [77, "&c"], "\t" => [18, "&c"], "\n" => [77, "&e"], "\v" => [18, "&e"], "\f" => [77, "&i"], "\r" => [18, "&i"], "\x0e" => [77, "&o"], "\x0f" => [18, "&o"], "\x10" => [77, "&s"], "\x11" => [18, "&s"], "\x12" => [77, "&t"], "\x13" => [18, "&t"], "\x14" => [0, "& "], "\x15" => [0, "&%"], "\x16" => [0, "&-"], "\x17" => [0, "&."], "\x18" => [0, "&/"], "\x19" => [0, "&3"], "\x1a" => [0, "&4"], "\x1b" => [0, "&5"], "\x1c" => [0, "&6"], "\x1d" => [0, "&7"], "\x1e" => [0, "&8"], "\x1f" => [0, "&9"], " " => [0, "&="], "!" => [0, "&A"], "\"" => [0, "&_"], "#" => [0, "&b"], "\$" => [0, "&d"], "%" => [0, "&f"], "&" => [0, "&g"], "'" => [0, "&h"], "(" => [0, "&l"], ")" => [0, "&m"], "*" => [0, "&n"], "+" => [0, "&p"], "," => [0, "&r"], "-" => [0, "&u"], "." => [100, "&"], "/" => [110, "&"], [111, "&"], [115, "&"], [116, "&"], [118, "&"], [119, "&"], [122, "&"], [123, "&"], [125, "&"], [126, "&"], [129, "&"], ":" => [143, "&"], ";" => [148, "&"], "<" => [151, "&"], "=" => [153, "&"], ">" => [83, "&"], "?" => [10, "&"], "@" => [77, "*0"], "A" => [18, "*0"], "B" => [77, "*1"], "C" => [18, "*1"], "D" => [77, "*2"], "E" => [18, "*2"], "F" => [77, "*a"], "G" => [18, "*a"], "H" => [77, "*c"], "I" => [18, "*c"], "J" => [77, "*e"], "K" => [18, "*e"], "L" => [77, "*i"], "M" => [18, "*i"], "N" => [77, "*o"], "O" => [18, "*o"], "P" => [77, "*s"], "Q" => [18, "*s"], "R" => [77, "*t"], "S" => [18, "*t"], "T" => [0, "* "], "U" => [0, "*%"], "V" => [0, "*-"], "W" => [0, "*."], "X" => [0, "*/"], "Y" => [0, "*3"], "Z" => [0, "*4"], "[" => [0, "*5"], "\\" => [0, "*6"], "]" => [0, "*7"], "^" => [0, "*8"], "_" => [0, "*9"], "`" => [0, "*="], "a" => [0, "*A"], "b" => [0, "*_"], "c" => [0, "*b"], "d" => [0, "*d"], "e" => [0, "*f"], "f" => [0, "*g"], "g" => [0, "*h"], "h" => [0, "*l"], "i" => [0, "*m"], "j" => [0, "*n"], "k" => [0, "*p"], "l" => [0, "*r"], "m" => [0, "*u"], "n" => [100, "*"], "o" => [110, "*"], "p" => [111, "*"], "q" => [115, "*"], "r" => [116, "*"], "s" => [118, "*"], "t" => [119, "*"], "u" => [122, "*"], "v" => [123, "*"], "w" => [125, "*"], "x" => [126, "*"], "y" => [129, "*"], "z" => [143, "*"], "{" => [148, "*"], "|" => [151, "*"], "}" => [153, "*"], "~" => [83, "*"], "" => [10, "*"], "\x80" => [77, ",0"], "\x81" => [18, ",0"], "\x82" => [77, ",1"], "\x83" => [18, ",1"], "\x84" => [77, ",2"], "\x85" => [18, ",2"], "\x86" => [77, ",a"], "\x87" => [18, ",a"], "\x88" => [77, ",c"], "\x89" => [18, ",c"], "\x8a" => [77, ",e"], "\x8b" => [18, ",e"], "\x8c" => [77, ",i"], "\x8d" => [18, ",i"], "\x8e" => [77, ",o"], "\x8f" => [18, ",o"], "\x90" => [77, ",s"], "\x91" => [18, ",s"], "\x92" => [77, ",t"], "\x93" => [18, ",t"], "\x94" => [0, ", "], "\x95" => [0, ",%"], "\x96" => [0, ",-"], "\x97" => [0, ",."], "\x98" => [0, ",/"], "\x99" => [0, ",3"], "\x9a" => [0, ",4"], "\x9b" => [0, ",5"], "\x9c" => [0, ",6"], "\x9d" => [0, ",7"], "\x9e" => [0, ",8"], "\x9f" => [0, ",9"], "\xa0" => [0, ",="], "\xa1" => [0, ",A"], "\xa2" => [0, ",_"], "\xa3" => [0, ",b"], "\xa4" => [0, ",d"], "\xa5" => [0, ",f"], "\xa6" => [0, ",g"], "\xa7" => [0, ",h"], "\xa8" => [0, ",l"], "\xa9" => [0, ",m"], "\xaa" => [0, ",n"], "\xab" => [0, ",p"], "\xac" => [0, ",r"], "\xad" => [0, ",u"], "\xae" => [100, ","], "\xaf" => [110, ","], "\xb0" => [111, ","], "\xb1" => [115, ","], "\xb2" => [116, ","], "\xb3" => [118, ","], "\xb4" => [119, ","], "\xb5" => [122, ","], "\xb6" => [123, ","], "\xb7" => [125, ","], "\xb8" => [126, ","], "\xb9" => [129, ","], "\xba" => [143, ","], "\xbb" => [148, ","], "\xbc" => [151, ","], "\xbd" => [153, ","], "\xbe" => [83, ","], "\xbf" => [10, ","], "\xc0" => [77, ";0"], "\xc1" => [18, ";0"], "\xc2" => [77, ";1"], "\xc3" => [18, ";1"], "\xc4" => [77, ";2"], "\xc5" => [18, ";2"], "\xc6" => [77, ";a"], "\xc7" => [18, ";a"], "\xc8" => [77, ";c"], "\xc9" => [18, ";c"], "\xca" => [77, ";e"], "\xcb" => [18, ";e"], "\xcc" => [77, ";i"], "\xcd" => [18, ";i"], "\xce" => [77, ";o"], "\xcf" => [18, ";o"], "\xd0" => [77, ";s"], "\xd1" => [18, ";s"], "\xd2" => [77, ";t"], "\xd3" => [18, ";t"], "\xd4" => [0, "; "], "\xd5" => [0, ";%"], "\xd6" => [0, ";-"], "\xd7" => [0, ";."], "\xd8" => [0, ";/"], "\xd9" => [0, ";3"], "\xda" => [0, ";4"], "\xdb" => [0, ";5"], "\xdc" => [0, ";6"], "\xdd" => [0, ";7"], "\xde" => [0, ";8"], "\xdf" => [0, ";9"], "\xe0" => [0, ";="], "\xe1" => [0, ";A"], "\xe2" => [0, ";_"], "\xe3" => [0, ";b"], "\xe4" => [0, ";d"], "\xe5" => [0, ";f"], "\xe6" => [0, ";g"], "\xe7" => [0, ";h"], "\xe8" => [0, ";l"], "\xe9" => [0, ";m"], "\xea" => [0, ";n"], "\xeb" => [0, ";p"], "\xec" => [0, ";r"], "\xed" => [0, ";u"], "\xee" => [100, ";"], "\xef" => [110, ";"], "\xf0" => [111, ";"], "\xf1" => [115, ";"], "\xf2" => [116, ";"], "\xf3" => [118, ";"], "\xf4" => [119, ";"], "\xf5" => [122, ";"], "\xf6" => [123, ";"], "\xf7" => [125, ";"], "\xf8" => [126, ";"], "\xf9" => [129, ";"], "\xfa" => [143, ";"], "\xfb" => [148, ";"], "\xfc" => [151, ";"], "\xfd" => [153, ";"], "\xfe" => [83, ";"], "\xff" => [10, ";"]], ["\x00" => [94, "'0"], "\x01" => [76, "'0"], "\x02" => [104, "'0"], "\x03" => [16, "'0"], "\x04" => [94, "'1"], "\x05" => [76, "'1"], "\x06" => [104, "'1"], "\x07" => [16, "'1"], "\x08" => [94, "'2"], "\t" => [76, "'2"], "\n" => [104, "'2"], "\v" => [16, "'2"], "\f" => [94, "'a"], "\r" => [76, "'a"], "\x0e" => [104, "'a"], "\x0f" => [16, "'a"], "\x10" => [94, "'c"], "\x11" => [76, "'c"], "\x12" => [104, "'c"], "\x13" => [16, "'c"], "\x14" => [94, "'e"], "\x15" => [76, "'e"], "\x16" => [104, "'e"], "\x17" => [16, "'e"], "\x18" => [94, "'i"], "\x19" => [76, "'i"], "\x1a" => [104, "'i"], "\x1b" => [16, "'i"], "\x1c" => [94, "'o"], "\x1d" => [76, "'o"], "\x1e" => [104, "'o"], "\x1f" => [16, "'o"], " " => [94, "'s"], "!" => [76, "'s"], "\"" => [104, "'s"], "#" => [16, "'s"], "\$" => [94, "'t"], "%" => [76, "'t"], "&" => [104, "'t"], "'" => [16, "'t"], "(" => [77, "' "], ")" => [18, "' "], "*" => [77, "'%"], "+" => [18, "'%"], "," => [77, "'-"], "-" => [18, "'-"], "." => [77, "'."], "/" => [18, "'."], [77, "'/"], [18, "'/"], [77, "'3"], [18, "'3"], [77, "'4"], [18, "'4"], [77, "'5"], [18, "'5"], [77, "'6"], [18, "'6"], ":" => [77, "'7"], ";" => [18, "'7"], "<" => [77, "'8"], "=" => [18, "'8"], ">" => [77, "'9"], "?" => [18, "'9"], "@" => [77, "'="], "A" => [18, "'="], "B" => [77, "'A"], "C" => [18, "'A"], "D" => [77, "'_"], "E" => [18, "'_"], "F" => [77, "'b"], "G" => [18, "'b"], "H" => [77, "'d"], "I" => [18, "'d"], "J" => [77, "'f"], "K" => [18, "'f"], "L" => [77, "'g"], "M" => [18, "'g"], "N" => [77, "'h"], "O" => [18, "'h"], "P" => [77, "'l"], "Q" => [18, "'l"], "R" => [77, "'m"], "S" => [18, "'m"], "T" => [77, "'n"], "U" => [18, "'n"], "V" => [77, "'p"], "W" => [18, "'p"], "X" => [77, "'r"], "Y" => [18, "'r"], "Z" => [77, "'u"], "[" => [18, "'u"], "\\" => [0, "':"], "]" => [0, "'B"], "^" => [0, "'C"], "_" => [0, "'D"], "`" => [0, "'E"], "a" => [0, "'F"], "b" => [0, "'G"], "c" => [0, "'H"], "d" => [0, "'I"], "e" => [0, "'J"], "f" => [0, "'K"], "g" => [0, "'L"], "h" => [0, "'M"], "i" => [0, "'N"], "j" => [0, "'O"], "k" => [0, "'P"], "l" => [0, "'Q"], "m" => [0, "'R"], "n" => [0, "'S"], "o" => [0, "'T"], "p" => [0, "'U"], "q" => [0, "'V"], "r" => [0, "'W"], "s" => [0, "'Y"], "t" => [0, "'j"], "u" => [0, "'k"], "v" => [0, "'q"], "w" => [0, "'v"], "x" => [0, "'w"], "y" => [0, "'x"], "z" => [0, "'y"], "{" => [0, "'z"], "|" => [82, "'"], "}" => [87, "'"], "~" => [130, "'"], "" => [9, "'"], "\x80" => [94, "+0"], "\x81" => [76, "+0"], "\x82" => [104, "+0"], "\x83" => [16, "+0"], "\x84" => [94, "+1"], "\x85" => [76, "+1"], "\x86" => [104, "+1"], "\x87" => [16, "+1"], "\x88" => [94, "+2"], "\x89" => [76, "+2"], "\x8a" => [104, "+2"], "\x8b" => [16, "+2"], "\x8c" => [94, "+a"], "\x8d" => [76, "+a"], "\x8e" => [104, "+a"], "\x8f" => [16, "+a"], "\x90" => [94, "+c"], "\x91" => [76, "+c"], "\x92" => [104, "+c"], "\x93" => [16, "+c"], "\x94" => [94, "+e"], "\x95" => [76, "+e"], "\x96" => [104, "+e"], "\x97" => [16, "+e"], "\x98" => [94, "+i"], "\x99" => [76, "+i"], "\x9a" => [104, "+i"], "\x9b" => [16, "+i"], "\x9c" => [94, "+o"], "\x9d" => [76, "+o"], "\x9e" => [104, "+o"], "\x9f" => [16, "+o"], "\xa0" => [94, "+s"], "\xa1" => [76, "+s"], "\xa2" => [104, "+s"], "\xa3" => [16, "+s"], "\xa4" => [94, "+t"], "\xa5" => [76, "+t"], "\xa6" => [104, "+t"], "\xa7" => [16, "+t"], "\xa8" => [77, "+ "], "\xa9" => [18, "+ "], "\xaa" => [77, "+%"], "\xab" => [18, "+%"], "\xac" => [77, "+-"], "\xad" => [18, "+-"], "\xae" => [77, "+."], "\xaf" => [18, "+."], "\xb0" => [77, "+/"], "\xb1" => [18, "+/"], "\xb2" => [77, "+3"], "\xb3" => [18, "+3"], "\xb4" => [77, "+4"], "\xb5" => [18, "+4"], "\xb6" => [77, "+5"], "\xb7" => [18, "+5"], "\xb8" => [77, "+6"], "\xb9" => [18, "+6"], "\xba" => [77, "+7"], "\xbb" => [18, "+7"], "\xbc" => [77, "+8"], "\xbd" => [18, "+8"], "\xbe" => [77, "+9"], "\xbf" => [18, "+9"], "\xc0" => [77, "+="], "\xc1" => [18, "+="], "\xc2" => [77, "+A"], "\xc3" => [18, "+A"], "\xc4" => [77, "+_"], "\xc5" => [18, "+_"], "\xc6" => [77, "+b"], "\xc7" => [18, "+b"], "\xc8" => [77, "+d"], "\xc9" => [18, "+d"], "\xca" => [77, "+f"], "\xcb" => [18, "+f"], "\xcc" => [77, "+g"], "\xcd" => [18, "+g"], "\xce" => [77, "+h"], "\xcf" => [18, "+h"], "\xd0" => [77, "+l"], "\xd1" => [18, "+l"], "\xd2" => [77, "+m"], "\xd3" => [18, "+m"], "\xd4" => [77, "+n"], "\xd5" => [18, "+n"], "\xd6" => [77, "+p"], "\xd7" => [18, "+p"], "\xd8" => [77, "+r"], "\xd9" => [18, "+r"], "\xda" => [77, "+u"], "\xdb" => [18, "+u"], "\xdc" => [0, "+:"], "\xdd" => [0, "+B"], "\xde" => [0, "+C"], "\xdf" => [0, "+D"], "\xe0" => [0, "+E"], "\xe1" => [0, "+F"], "\xe2" => [0, "+G"], "\xe3" => [0, "+H"], "\xe4" => [0, "+I"], "\xe5" => [0, "+J"], "\xe6" => [0, "+K"], "\xe7" => [0, "+L"], "\xe8" => [0, "+M"], "\xe9" => [0, "+N"], "\xea" => [0, "+O"], "\xeb" => [0, "+P"], "\xec" => [0, "+Q"], "\xed" => [0, "+R"], "\xee" => [0, "+S"], "\xef" => [0, "+T"], "\xf0" => [0, "+U"], "\xf1" => [0, "+V"], "\xf2" => [0, "+W"], "\xf3" => [0, "+Y"], "\xf4" => [0, "+j"], "\xf5" => [0, "+k"], "\xf6" => [0, "+q"], "\xf7" => [0, "+v"], "\xf8" => [0, "+w"], "\xf9" => [0, "+x"], "\xfa" => [0, "+y"], "\xfb" => [0, "+z"], "\xfc" => [82, "+"], "\xfd" => [87, "+"], "\xfe" => [130, "+"], "\xff" => [9, "+"]], ["\x00" => [94, "?0"], "\x01" => [76, "?0"], "\x02" => [104, "?0"], "\x03" => [16, "?0"], "\x04" => [94, "?1"], "\x05" => [76, "?1"], "\x06" => [104, "?1"], "\x07" => [16, "?1"], "\x08" => [94, "?2"], "\t" => [76, "?2"], "\n" => [104, "?2"], "\v" => [16, "?2"], "\f" => [94, "?a"], "\r" => [76, "?a"], "\x0e" => [104, "?a"], "\x0f" => [16, "?a"], "\x10" => [94, "?c"], "\x11" => [76, "?c"], "\x12" => [104, "?c"], "\x13" => [16, "?c"], "\x14" => [94, "?e"], "\x15" => [76, "?e"], "\x16" => [104, "?e"], "\x17" => [16, "?e"], "\x18" => [94, "?i"], "\x19" => [76, "?i"], "\x1a" => [104, "?i"], "\x1b" => [16, "?i"], "\x1c" => [94, "?o"], "\x1d" => [76, "?o"], "\x1e" => [104, "?o"], "\x1f" => [16, "?o"], " " => [94, "?s"], "!" => [76, "?s"], "\"" => [104, "?s"], "#" => [16, "?s"], "\$" => [94, "?t"], "%" => [76, "?t"], "&" => [104, "?t"], "'" => [16, "?t"], "(" => [77, "? "], ")" => [18, "? "], "*" => [77, "?%"], "+" => [18, "?%"], "," => [77, "?-"], "-" => [18, "?-"], "." => [77, "?."], "/" => [18, "?."], [77, "?/"], [18, "?/"], [77, "?3"], [18, "?3"], [77, "?4"], [18, "?4"], [77, "?5"], [18, "?5"], [77, "?6"], [18, "?6"], ":" => [77, "?7"], ";" => [18, "?7"], "<" => [77, "?8"], "=" => [18, "?8"], ">" => [77, "?9"], "?" => [18, "?9"], "@" => [77, "?="], "A" => [18, "?="], "B" => [77, "?A"], "C" => [18, "?A"], "D" => [77, "?_"], "E" => [18, "?_"], "F" => [77, "?b"], "G" => [18, "?b"], "H" => [77, "?d"], "I" => [18, "?d"], "J" => [77, "?f"], "K" => [18, "?f"], "L" => [77, "?g"], "M" => [18, "?g"], "N" => [77, "?h"], "O" => [18, "?h"], "P" => [77, "?l"], "Q" => [18, "?l"], "R" => [77, "?m"], "S" => [18, "?m"], "T" => [77, "?n"], "U" => [18, "?n"], "V" => [77, "?p"], "W" => [18, "?p"], "X" => [77, "?r"], "Y" => [18, "?r"], "Z" => [77, "?u"], "[" => [18, "?u"], "\\" => [0, "?:"], "]" => [0, "?B"], "^" => [0, "?C"], "_" => [0, "?D"], "`" => [0, "?E"], "a" => [0, "?F"], "b" => [0, "?G"], "c" => [0, "?H"], "d" => [0, "?I"], "e" => [0, "?J"], "f" => [0, "?K"], "g" => [0, "?L"], "h" => [0, "?M"], "i" => [0, "?N"], "j" => [0, "?O"], "k" => [0, "?P"], "l" => [0, "?Q"], "m" => [0, "?R"], "n" => [0, "?S"], "o" => [0, "?T"], "p" => [0, "?U"], "q" => [0, "?V"], "r" => [0, "?W"], "s" => [0, "?Y"], "t" => [0, "?j"], "u" => [0, "?k"], "v" => [0, "?q"], "w" => [0, "?v"], "x" => [0, "?w"], "y" => [0, "?x"], "z" => [0, "?y"], "{" => [0, "?z"], "|" => [82, "?"], "}" => [87, "?"], "~" => [130, "?"], "" => [9, "?"], "\x80" => [77, "'0"], "\x81" => [18, "'0"], "\x82" => [77, "'1"], "\x83" => [18, "'1"], "\x84" => [77, "'2"], "\x85" => [18, "'2"], "\x86" => [77, "'a"], "\x87" => [18, "'a"], "\x88" => [77, "'c"], "\x89" => [18, "'c"], "\x8a" => [77, "'e"], "\x8b" => [18, "'e"], "\x8c" => [77, "'i"], "\x8d" => [18, "'i"], "\x8e" => [77, "'o"], "\x8f" => [18, "'o"], "\x90" => [77, "'s"], "\x91" => [18, "'s"], "\x92" => [77, "'t"], "\x93" => [18, "'t"], "\x94" => [0, "' "], "\x95" => [0, "'%"], "\x96" => [0, "'-"], "\x97" => [0, "'."], "\x98" => [0, "'/"], "\x99" => [0, "'3"], "\x9a" => [0, "'4"], "\x9b" => [0, "'5"], "\x9c" => [0, "'6"], "\x9d" => [0, "'7"], "\x9e" => [0, "'8"], "\x9f" => [0, "'9"], "\xa0" => [0, "'="], "\xa1" => [0, "'A"], "\xa2" => [0, "'_"], "\xa3" => [0, "'b"], "\xa4" => [0, "'d"], "\xa5" => [0, "'f"], "\xa6" => [0, "'g"], "\xa7" => [0, "'h"], "\xa8" => [0, "'l"], "\xa9" => [0, "'m"], "\xaa" => [0, "'n"], "\xab" => [0, "'p"], "\xac" => [0, "'r"], "\xad" => [0, "'u"], "\xae" => [100, "'"], "\xaf" => [110, "'"], "\xb0" => [111, "'"], "\xb1" => [115, "'"], "\xb2" => [116, "'"], "\xb3" => [118, "'"], "\xb4" => [119, "'"], "\xb5" => [122, "'"], "\xb6" => [123, "'"], "\xb7" => [125, "'"], "\xb8" => [126, "'"], "\xb9" => [129, "'"], "\xba" => [143, "'"], "\xbb" => [148, "'"], "\xbc" => [151, "'"], "\xbd" => [153, "'"], "\xbe" => [83, "'"], "\xbf" => [10, "'"], "\xc0" => [77, "+0"], "\xc1" => [18, "+0"], "\xc2" => [77, "+1"], "\xc3" => [18, "+1"], "\xc4" => [77, "+2"], "\xc5" => [18, "+2"], "\xc6" => [77, "+a"], "\xc7" => [18, "+a"], "\xc8" => [77, "+c"], "\xc9" => [18, "+c"], "\xca" => [77, "+e"], "\xcb" => [18, "+e"], "\xcc" => [77, "+i"], "\xcd" => [18, "+i"], "\xce" => [77, "+o"], "\xcf" => [18, "+o"], "\xd0" => [77, "+s"], "\xd1" => [18, "+s"], "\xd2" => [77, "+t"], "\xd3" => [18, "+t"], "\xd4" => [0, "+ "], "\xd5" => [0, "+%"], "\xd6" => [0, "+-"], "\xd7" => [0, "+."], "\xd8" => [0, "+/"], "\xd9" => [0, "+3"], "\xda" => [0, "+4"], "\xdb" => [0, "+5"], "\xdc" => [0, "+6"], "\xdd" => [0, "+7"], "\xde" => [0, "+8"], "\xdf" => [0, "+9"], "\xe0" => [0, "+="], "\xe1" => [0, "+A"], "\xe2" => [0, "+_"], "\xe3" => [0, "+b"], "\xe4" => [0, "+d"], "\xe5" => [0, "+f"], "\xe6" => [0, "+g"], "\xe7" => [0, "+h"], "\xe8" => [0, "+l"], "\xe9" => [0, "+m"], "\xea" => [0, "+n"], "\xeb" => [0, "+p"], "\xec" => [0, "+r"], "\xed" => [0, "+u"], "\xee" => [100, "+"], "\xef" => [110, "+"], "\xf0" => [111, "+"], "\xf1" => [115, "+"], "\xf2" => [116, "+"], "\xf3" => [118, "+"], "\xf4" => [119, "+"], "\xf5" => [122, "+"], "\xf6" => [123, "+"], "\xf7" => [125, "+"], "\xf8" => [126, "+"], "\xf9" => [129, "+"], "\xfa" => [143, "+"], "\xfb" => [148, "+"], "\xfc" => [151, "+"], "\xfd" => [153, "+"], "\xfe" => [83, "+"], "\xff" => [10, "+"]], ["\x00" => [94, "(0"], "\x01" => [76, "(0"], "\x02" => [104, "(0"], "\x03" => [16, "(0"], "\x04" => [94, "(1"], "\x05" => [76, "(1"], "\x06" => [104, "(1"], "\x07" => [16, "(1"], "\x08" => [94, "(2"], "\t" => [76, "(2"], "\n" => [104, "(2"], "\v" => [16, "(2"], "\f" => [94, "(a"], "\r" => [76, "(a"], "\x0e" => [104, "(a"], "\x0f" => [16, "(a"], "\x10" => [94, "(c"], "\x11" => [76, "(c"], "\x12" => [104, "(c"], "\x13" => [16, "(c"], "\x14" => [94, "(e"], "\x15" => [76, "(e"], "\x16" => [104, "(e"], "\x17" => [16, "(e"], "\x18" => [94, "(i"], "\x19" => [76, "(i"], "\x1a" => [104, "(i"], "\x1b" => [16, "(i"], "\x1c" => [94, "(o"], "\x1d" => [76, "(o"], "\x1e" => [104, "(o"], "\x1f" => [16, "(o"], " " => [94, "(s"], "!" => [76, "(s"], "\"" => [104, "(s"], "#" => [16, "(s"], "\$" => [94, "(t"], "%" => [76, "(t"], "&" => [104, "(t"], "'" => [16, "(t"], "(" => [77, "( "], ")" => [18, "( "], "*" => [77, "(%"], "+" => [18, "(%"], "," => [77, "(-"], "-" => [18, "(-"], "." => [77, "(."], "/" => [18, "(."], [77, "(/"], [18, "(/"], [77, "(3"], [18, "(3"], [77, "(4"], [18, "(4"], [77, "(5"], [18, "(5"], [77, "(6"], [18, "(6"], ":" => [77, "(7"], ";" => [18, "(7"], "<" => [77, "(8"], "=" => [18, "(8"], ">" => [77, "(9"], "?" => [18, "(9"], "@" => [77, "(="], "A" => [18, "(="], "B" => [77, "(A"], "C" => [18, "(A"], "D" => [77, "(_"], "E" => [18, "(_"], "F" => [77, "(b"], "G" => [18, "(b"], "H" => [77, "(d"], "I" => [18, "(d"], "J" => [77, "(f"], "K" => [18, "(f"], "L" => [77, "(g"], "M" => [18, "(g"], "N" => [77, "(h"], "O" => [18, "(h"], "P" => [77, "(l"], "Q" => [18, "(l"], "R" => [77, "(m"], "S" => [18, "(m"], "T" => [77, "(n"], "U" => [18, "(n"], "V" => [77, "(p"], "W" => [18, "(p"], "X" => [77, "(r"], "Y" => [18, "(r"], "Z" => [77, "(u"], "[" => [18, "(u"], "\\" => [0, "(:"], "]" => [0, "(B"], "^" => [0, "(C"], "_" => [0, "(D"], "`" => [0, "(E"], "a" => [0, "(F"], "b" => [0, "(G"], "c" => [0, "(H"], "d" => [0, "(I"], "e" => [0, "(J"], "f" => [0, "(K"], "g" => [0, "(L"], "h" => [0, "(M"], "i" => [0, "(N"], "j" => [0, "(O"], "k" => [0, "(P"], "l" => [0, "(Q"], "m" => [0, "(R"], "n" => [0, "(S"], "o" => [0, "(T"], "p" => [0, "(U"], "q" => [0, "(V"], "r" => [0, "(W"], "s" => [0, "(Y"], "t" => [0, "(j"], "u" => [0, "(k"], "v" => [0, "(q"], "w" => [0, "(v"], "x" => [0, "(w"], "y" => [0, "(x"], "z" => [0, "(y"], "{" => [0, "(z"], "|" => [82, "("], "}" => [87, "("], "~" => [130, "("], "" => [9, "("], "\x80" => [94, ")0"], "\x81" => [76, ")0"], "\x82" => [104, ")0"], "\x83" => [16, ")0"], "\x84" => [94, ")1"], "\x85" => [76, ")1"], "\x86" => [104, ")1"], "\x87" => [16, ")1"], "\x88" => [94, ")2"], "\x89" => [76, ")2"], "\x8a" => [104, ")2"], "\x8b" => [16, ")2"], "\x8c" => [94, ")a"], "\x8d" => [76, ")a"], "\x8e" => [104, ")a"], "\x8f" => [16, ")a"], "\x90" => [94, ")c"], "\x91" => [76, ")c"], "\x92" => [104, ")c"], "\x93" => [16, ")c"], "\x94" => [94, ")e"], "\x95" => [76, ")e"], "\x96" => [104, ")e"], "\x97" => [16, ")e"], "\x98" => [94, ")i"], "\x99" => [76, ")i"], "\x9a" => [104, ")i"], "\x9b" => [16, ")i"], "\x9c" => [94, ")o"], "\x9d" => [76, ")o"], "\x9e" => [104, ")o"], "\x9f" => [16, ")o"], "\xa0" => [94, ")s"], "\xa1" => [76, ")s"], "\xa2" => [104, ")s"], "\xa3" => [16, ")s"], "\xa4" => [94, ")t"], "\xa5" => [76, ")t"], "\xa6" => [104, ")t"], "\xa7" => [16, ")t"], "\xa8" => [77, ") "], "\xa9" => [18, ") "], "\xaa" => [77, ")%"], "\xab" => [18, ")%"], "\xac" => [77, ")-"], "\xad" => [18, ")-"], "\xae" => [77, ")."], "\xaf" => [18, ")."], "\xb0" => [77, ")/"], "\xb1" => [18, ")/"], "\xb2" => [77, ")3"], "\xb3" => [18, ")3"], "\xb4" => [77, ")4"], "\xb5" => [18, ")4"], "\xb6" => [77, ")5"], "\xb7" => [18, ")5"], "\xb8" => [77, ")6"], "\xb9" => [18, ")6"], "\xba" => [77, ")7"], "\xbb" => [18, ")7"], "\xbc" => [77, ")8"], "\xbd" => [18, ")8"], "\xbe" => [77, ")9"], "\xbf" => [18, ")9"], "\xc0" => [77, ")="], "\xc1" => [18, ")="], "\xc2" => [77, ")A"], "\xc3" => [18, ")A"], "\xc4" => [77, ")_"], "\xc5" => [18, ")_"], "\xc6" => [77, ")b"], "\xc7" => [18, ")b"], "\xc8" => [77, ")d"], "\xc9" => [18, ")d"], "\xca" => [77, ")f"], "\xcb" => [18, ")f"], "\xcc" => [77, ")g"], "\xcd" => [18, ")g"], "\xce" => [77, ")h"], "\xcf" => [18, ")h"], "\xd0" => [77, ")l"], "\xd1" => [18, ")l"], "\xd2" => [77, ")m"], "\xd3" => [18, ")m"], "\xd4" => [77, ")n"], "\xd5" => [18, ")n"], "\xd6" => [77, ")p"], "\xd7" => [18, ")p"], "\xd8" => [77, ")r"], "\xd9" => [18, ")r"], "\xda" => [77, ")u"], "\xdb" => [18, ")u"], "\xdc" => [0, "):"], "\xdd" => [0, ")B"], "\xde" => [0, ")C"], "\xdf" => [0, ")D"], "\xe0" => [0, ")E"], "\xe1" => [0, ")F"], "\xe2" => [0, ")G"], "\xe3" => [0, ")H"], "\xe4" => [0, ")I"], "\xe5" => [0, ")J"], "\xe6" => [0, ")K"], "\xe7" => [0, ")L"], "\xe8" => [0, ")M"], "\xe9" => [0, ")N"], "\xea" => [0, ")O"], "\xeb" => [0, ")P"], "\xec" => [0, ")Q"], "\xed" => [0, ")R"], "\xee" => [0, ")S"], "\xef" => [0, ")T"], "\xf0" => [0, ")U"], "\xf1" => [0, ")V"], "\xf2" => [0, ")W"], "\xf3" => [0, ")Y"], "\xf4" => [0, ")j"], "\xf5" => [0, ")k"], "\xf6" => [0, ")q"], "\xf7" => [0, ")v"], "\xf8" => [0, ")w"], "\xf9" => [0, ")x"], "\xfa" => [0, ")y"], "\xfb" => [0, ")z"], "\xfc" => [82, ")"], "\xfd" => [87, ")"], "\xfe" => [130, ")"], "\xff" => [9, ")"]], ["\x00" => [94, ",0"], "\x01" => [76, ",0"], "\x02" => [104, ",0"], "\x03" => [16, ",0"], "\x04" => [94, ",1"], "\x05" => [76, ",1"], "\x06" => [104, ",1"], "\x07" => [16, ",1"], "\x08" => [94, ",2"], "\t" => [76, ",2"], "\n" => [104, ",2"], "\v" => [16, ",2"], "\f" => [94, ",a"], "\r" => [76, ",a"], "\x0e" => [104, ",a"], "\x0f" => [16, ",a"], "\x10" => [94, ",c"], "\x11" => [76, ",c"], "\x12" => [104, ",c"], "\x13" => [16, ",c"], "\x14" => [94, ",e"], "\x15" => [76, ",e"], "\x16" => [104, ",e"], "\x17" => [16, ",e"], "\x18" => [94, ",i"], "\x19" => [76, ",i"], "\x1a" => [104, ",i"], "\x1b" => [16, ",i"], "\x1c" => [94, ",o"], "\x1d" => [76, ",o"], "\x1e" => [104, ",o"], "\x1f" => [16, ",o"], " " => [94, ",s"], "!" => [76, ",s"], "\"" => [104, ",s"], "#" => [16, ",s"], "\$" => [94, ",t"], "%" => [76, ",t"], "&" => [104, ",t"], "'" => [16, ",t"], "(" => [77, ", "], ")" => [18, ", "], "*" => [77, ",%"], "+" => [18, ",%"], "," => [77, ",-"], "-" => [18, ",-"], "." => [77, ",."], "/" => [18, ",."], [77, ",/"], [18, ",/"], [77, ",3"], [18, ",3"], [77, ",4"], [18, ",4"], [77, ",5"], [18, ",5"], [77, ",6"], [18, ",6"], ":" => [77, ",7"], ";" => [18, ",7"], "<" => [77, ",8"], "=" => [18, ",8"], ">" => [77, ",9"], "?" => [18, ",9"], "@" => [77, ",="], "A" => [18, ",="], "B" => [77, ",A"], "C" => [18, ",A"], "D" => [77, ",_"], "E" => [18, ",_"], "F" => [77, ",b"], "G" => [18, ",b"], "H" => [77, ",d"], "I" => [18, ",d"], "J" => [77, ",f"], "K" => [18, ",f"], "L" => [77, ",g"], "M" => [18, ",g"], "N" => [77, ",h"], "O" => [18, ",h"], "P" => [77, ",l"], "Q" => [18, ",l"], "R" => [77, ",m"], "S" => [18, ",m"], "T" => [77, ",n"], "U" => [18, ",n"], "V" => [77, ",p"], "W" => [18, ",p"], "X" => [77, ",r"], "Y" => [18, ",r"], "Z" => [77, ",u"], "[" => [18, ",u"], "\\" => [0, ",:"], "]" => [0, ",B"], "^" => [0, ",C"], "_" => [0, ",D"], "`" => [0, ",E"], "a" => [0, ",F"], "b" => [0, ",G"], "c" => [0, ",H"], "d" => [0, ",I"], "e" => [0, ",J"], "f" => [0, ",K"], "g" => [0, ",L"], "h" => [0, ",M"], "i" => [0, ",N"], "j" => [0, ",O"], "k" => [0, ",P"], "l" => [0, ",Q"], "m" => [0, ",R"], "n" => [0, ",S"], "o" => [0, ",T"], "p" => [0, ",U"], "q" => [0, ",V"], "r" => [0, ",W"], "s" => [0, ",Y"], "t" => [0, ",j"], "u" => [0, ",k"], "v" => [0, ",q"], "w" => [0, ",v"], "x" => [0, ",w"], "y" => [0, ",x"], "z" => [0, ",y"], "{" => [0, ",z"], "|" => [82, ","], "}" => [87, ","], "~" => [130, ","], "" => [9, ","], "\x80" => [94, ";0"], "\x81" => [76, ";0"], "\x82" => [104, ";0"], "\x83" => [16, ";0"], "\x84" => [94, ";1"], "\x85" => [76, ";1"], "\x86" => [104, ";1"], "\x87" => [16, ";1"], "\x88" => [94, ";2"], "\x89" => [76, ";2"], "\x8a" => [104, ";2"], "\x8b" => [16, ";2"], "\x8c" => [94, ";a"], "\x8d" => [76, ";a"], "\x8e" => [104, ";a"], "\x8f" => [16, ";a"], "\x90" => [94, ";c"], "\x91" => [76, ";c"], "\x92" => [104, ";c"], "\x93" => [16, ";c"], "\x94" => [94, ";e"], "\x95" => [76, ";e"], "\x96" => [104, ";e"], "\x97" => [16, ";e"], "\x98" => [94, ";i"], "\x99" => [76, ";i"], "\x9a" => [104, ";i"], "\x9b" => [16, ";i"], "\x9c" => [94, ";o"], "\x9d" => [76, ";o"], "\x9e" => [104, ";o"], "\x9f" => [16, ";o"], "\xa0" => [94, ";s"], "\xa1" => [76, ";s"], "\xa2" => [104, ";s"], "\xa3" => [16, ";s"], "\xa4" => [94, ";t"], "\xa5" => [76, ";t"], "\xa6" => [104, ";t"], "\xa7" => [16, ";t"], "\xa8" => [77, "; "], "\xa9" => [18, "; "], "\xaa" => [77, ";%"], "\xab" => [18, ";%"], "\xac" => [77, ";-"], "\xad" => [18, ";-"], "\xae" => [77, ";."], "\xaf" => [18, ";."], "\xb0" => [77, ";/"], "\xb1" => [18, ";/"], "\xb2" => [77, ";3"], "\xb3" => [18, ";3"], "\xb4" => [77, ";4"], "\xb5" => [18, ";4"], "\xb6" => [77, ";5"], "\xb7" => [18, ";5"], "\xb8" => [77, ";6"], "\xb9" => [18, ";6"], "\xba" => [77, ";7"], "\xbb" => [18, ";7"], "\xbc" => [77, ";8"], "\xbd" => [18, ";8"], "\xbe" => [77, ";9"], "\xbf" => [18, ";9"], "\xc0" => [77, ";="], "\xc1" => [18, ";="], "\xc2" => [77, ";A"], "\xc3" => [18, ";A"], "\xc4" => [77, ";_"], "\xc5" => [18, ";_"], "\xc6" => [77, ";b"], "\xc7" => [18, ";b"], "\xc8" => [77, ";d"], "\xc9" => [18, ";d"], "\xca" => [77, ";f"], "\xcb" => [18, ";f"], "\xcc" => [77, ";g"], "\xcd" => [18, ";g"], "\xce" => [77, ";h"], "\xcf" => [18, ";h"], "\xd0" => [77, ";l"], "\xd1" => [18, ";l"], "\xd2" => [77, ";m"], "\xd3" => [18, ";m"], "\xd4" => [77, ";n"], "\xd5" => [18, ";n"], "\xd6" => [77, ";p"], "\xd7" => [18, ";p"], "\xd8" => [77, ";r"], "\xd9" => [18, ";r"], "\xda" => [77, ";u"], "\xdb" => [18, ";u"], "\xdc" => [0, ";:"], "\xdd" => [0, ";B"], "\xde" => [0, ";C"], "\xdf" => [0, ";D"], "\xe0" => [0, ";E"], "\xe1" => [0, ";F"], "\xe2" => [0, ";G"], "\xe3" => [0, ";H"], "\xe4" => [0, ";I"], "\xe5" => [0, ";J"], "\xe6" => [0, ";K"], "\xe7" => [0, ";L"], "\xe8" => [0, ";M"], "\xe9" => [0, ";N"], "\xea" => [0, ";O"], "\xeb" => [0, ";P"], "\xec" => [0, ";Q"], "\xed" => [0, ";R"], "\xee" => [0, ";S"], "\xef" => [0, ";T"], "\xf0" => [0, ";U"], "\xf1" => [0, ";V"], "\xf2" => [0, ";W"], "\xf3" => [0, ";Y"], "\xf4" => [0, ";j"], "\xf5" => [0, ";k"], "\xf6" => [0, ";q"], "\xf7" => [0, ";v"], "\xf8" => [0, ";w"], "\xf9" => [0, ";x"], "\xfa" => [0, ";y"], "\xfb" => [0, ";z"], "\xfc" => [82, ";"], "\xfd" => [87, ";"], "\xfe" => [130, ";"], "\xff" => [9, ";"]], ["\x00" => [94, "-0"], "\x01" => [76, "-0"], "\x02" => [104, "-0"], "\x03" => [16, "-0"], "\x04" => [94, "-1"], "\x05" => [76, "-1"], "\x06" => [104, "-1"], "\x07" => [16, "-1"], "\x08" => [94, "-2"], "\t" => [76, "-2"], "\n" => [104, "-2"], "\v" => [16, "-2"], "\f" => [94, "-a"], "\r" => [76, "-a"], "\x0e" => [104, "-a"], "\x0f" => [16, "-a"], "\x10" => [94, "-c"], "\x11" => [76, "-c"], "\x12" => [104, "-c"], "\x13" => [16, "-c"], "\x14" => [94, "-e"], "\x15" => [76, "-e"], "\x16" => [104, "-e"], "\x17" => [16, "-e"], "\x18" => [94, "-i"], "\x19" => [76, "-i"], "\x1a" => [104, "-i"], "\x1b" => [16, "-i"], "\x1c" => [94, "-o"], "\x1d" => [76, "-o"], "\x1e" => [104, "-o"], "\x1f" => [16, "-o"], " " => [94, "-s"], "!" => [76, "-s"], "\"" => [104, "-s"], "#" => [16, "-s"], "\$" => [94, "-t"], "%" => [76, "-t"], "&" => [104, "-t"], "'" => [16, "-t"], "(" => [77, "- "], ")" => [18, "- "], "*" => [77, "-%"], "+" => [18, "-%"], "," => [77, "--"], "-" => [18, "--"], "." => [77, "-."], "/" => [18, "-."], [77, "-/"], [18, "-/"], [77, "-3"], [18, "-3"], [77, "-4"], [18, "-4"], [77, "-5"], [18, "-5"], [77, "-6"], [18, "-6"], ":" => [77, "-7"], ";" => [18, "-7"], "<" => [77, "-8"], "=" => [18, "-8"], ">" => [77, "-9"], "?" => [18, "-9"], "@" => [77, "-="], "A" => [18, "-="], "B" => [77, "-A"], "C" => [18, "-A"], "D" => [77, "-_"], "E" => [18, "-_"], "F" => [77, "-b"], "G" => [18, "-b"], "H" => [77, "-d"], "I" => [18, "-d"], "J" => [77, "-f"], "K" => [18, "-f"], "L" => [77, "-g"], "M" => [18, "-g"], "N" => [77, "-h"], "O" => [18, "-h"], "P" => [77, "-l"], "Q" => [18, "-l"], "R" => [77, "-m"], "S" => [18, "-m"], "T" => [77, "-n"], "U" => [18, "-n"], "V" => [77, "-p"], "W" => [18, "-p"], "X" => [77, "-r"], "Y" => [18, "-r"], "Z" => [77, "-u"], "[" => [18, "-u"], "\\" => [0, "-:"], "]" => [0, "-B"], "^" => [0, "-C"], "_" => [0, "-D"], "`" => [0, "-E"], "a" => [0, "-F"], "b" => [0, "-G"], "c" => [0, "-H"], "d" => [0, "-I"], "e" => [0, "-J"], "f" => [0, "-K"], "g" => [0, "-L"], "h" => [0, "-M"], "i" => [0, "-N"], "j" => [0, "-O"], "k" => [0, "-P"], "l" => [0, "-Q"], "m" => [0, "-R"], "n" => [0, "-S"], "o" => [0, "-T"], "p" => [0, "-U"], "q" => [0, "-V"], "r" => [0, "-W"], "s" => [0, "-Y"], "t" => [0, "-j"], "u" => [0, "-k"], "v" => [0, "-q"], "w" => [0, "-v"], "x" => [0, "-w"], "y" => [0, "-x"], "z" => [0, "-y"], "{" => [0, "-z"], "|" => [82, "-"], "}" => [87, "-"], "~" => [130, "-"], "" => [9, "-"], "\x80" => [94, ".0"], "\x81" => [76, ".0"], "\x82" => [104, ".0"], "\x83" => [16, ".0"], "\x84" => [94, ".1"], "\x85" => [76, ".1"], "\x86" => [104, ".1"], "\x87" => [16, ".1"], "\x88" => [94, ".2"], "\x89" => [76, ".2"], "\x8a" => [104, ".2"], "\x8b" => [16, ".2"], "\x8c" => [94, ".a"], "\x8d" => [76, ".a"], "\x8e" => [104, ".a"], "\x8f" => [16, ".a"], "\x90" => [94, ".c"], "\x91" => [76, ".c"], "\x92" => [104, ".c"], "\x93" => [16, ".c"], "\x94" => [94, ".e"], "\x95" => [76, ".e"], "\x96" => [104, ".e"], "\x97" => [16, ".e"], "\x98" => [94, ".i"], "\x99" => [76, ".i"], "\x9a" => [104, ".i"], "\x9b" => [16, ".i"], "\x9c" => [94, ".o"], "\x9d" => [76, ".o"], "\x9e" => [104, ".o"], "\x9f" => [16, ".o"], "\xa0" => [94, ".s"], "\xa1" => [76, ".s"], "\xa2" => [104, ".s"], "\xa3" => [16, ".s"], "\xa4" => [94, ".t"], "\xa5" => [76, ".t"], "\xa6" => [104, ".t"], "\xa7" => [16, ".t"], "\xa8" => [77, ". "], "\xa9" => [18, ". "], "\xaa" => [77, ".%"], "\xab" => [18, ".%"], "\xac" => [77, ".-"], "\xad" => [18, ".-"], "\xae" => [77, ".."], "\xaf" => [18, ".."], "\xb0" => [77, "./"], "\xb1" => [18, "./"], "\xb2" => [77, ".3"], "\xb3" => [18, ".3"], "\xb4" => [77, ".4"], "\xb5" => [18, ".4"], "\xb6" => [77, ".5"], "\xb7" => [18, ".5"], "\xb8" => [77, ".6"], "\xb9" => [18, ".6"], "\xba" => [77, ".7"], "\xbb" => [18, ".7"], "\xbc" => [77, ".8"], "\xbd" => [18, ".8"], "\xbe" => [77, ".9"], "\xbf" => [18, ".9"], "\xc0" => [77, ".="], "\xc1" => [18, ".="], "\xc2" => [77, ".A"], "\xc3" => [18, ".A"], "\xc4" => [77, "._"], "\xc5" => [18, "._"], "\xc6" => [77, ".b"], "\xc7" => [18, ".b"], "\xc8" => [77, ".d"], "\xc9" => [18, ".d"], "\xca" => [77, ".f"], "\xcb" => [18, ".f"], "\xcc" => [77, ".g"], "\xcd" => [18, ".g"], "\xce" => [77, ".h"], "\xcf" => [18, ".h"], "\xd0" => [77, ".l"], "\xd1" => [18, ".l"], "\xd2" => [77, ".m"], "\xd3" => [18, ".m"], "\xd4" => [77, ".n"], "\xd5" => [18, ".n"], "\xd6" => [77, ".p"], "\xd7" => [18, ".p"], "\xd8" => [77, ".r"], "\xd9" => [18, ".r"], "\xda" => [77, ".u"], "\xdb" => [18, ".u"], "\xdc" => [0, ".:"], "\xdd" => [0, ".B"], "\xde" => [0, ".C"], "\xdf" => [0, ".D"], "\xe0" => [0, ".E"], "\xe1" => [0, ".F"], "\xe2" => [0, ".G"], "\xe3" => [0, ".H"], "\xe4" => [0, ".I"], "\xe5" => [0, ".J"], "\xe6" => [0, ".K"], "\xe7" => [0, ".L"], "\xe8" => [0, ".M"], "\xe9" => [0, ".N"], "\xea" => [0, ".O"], "\xeb" => [0, ".P"], "\xec" => [0, ".Q"], "\xed" => [0, ".R"], "\xee" => [0, ".S"], "\xef" => [0, ".T"], "\xf0" => [0, ".U"], "\xf1" => [0, ".V"], "\xf2" => [0, ".W"], "\xf3" => [0, ".Y"], "\xf4" => [0, ".j"], "\xf5" => [0, ".k"], "\xf6" => [0, ".q"], "\xf7" => [0, ".v"], "\xf8" => [0, ".w"], "\xf9" => [0, ".x"], "\xfa" => [0, ".y"], "\xfb" => [0, ".z"], "\xfc" => [82, "."], "\xfd" => [87, "."], "\xfe" => [130, "."], "\xff" => [9, "."]], ["\x00" => [94, "/0"], "\x01" => [76, "/0"], "\x02" => [104, "/0"], "\x03" => [16, "/0"], "\x04" => [94, "/1"], "\x05" => [76, "/1"], "\x06" => [104, "/1"], "\x07" => [16, "/1"], "\x08" => [94, "/2"], "\t" => [76, "/2"], "\n" => [104, "/2"], "\v" => [16, "/2"], "\f" => [94, "/a"], "\r" => [76, "/a"], "\x0e" => [104, "/a"], "\x0f" => [16, "/a"], "\x10" => [94, "/c"], "\x11" => [76, "/c"], "\x12" => [104, "/c"], "\x13" => [16, "/c"], "\x14" => [94, "/e"], "\x15" => [76, "/e"], "\x16" => [104, "/e"], "\x17" => [16, "/e"], "\x18" => [94, "/i"], "\x19" => [76, "/i"], "\x1a" => [104, "/i"], "\x1b" => [16, "/i"], "\x1c" => [94, "/o"], "\x1d" => [76, "/o"], "\x1e" => [104, "/o"], "\x1f" => [16, "/o"], " " => [94, "/s"], "!" => [76, "/s"], "\"" => [104, "/s"], "#" => [16, "/s"], "\$" => [94, "/t"], "%" => [76, "/t"], "&" => [104, "/t"], "'" => [16, "/t"], "(" => [77, "/ "], ")" => [18, "/ "], "*" => [77, "/%"], "+" => [18, "/%"], "," => [77, "/-"], "-" => [18, "/-"], "." => [77, "/."], "/" => [18, "/."], [77, "//"], [18, "//"], [77, "/3"], [18, "/3"], [77, "/4"], [18, "/4"], [77, "/5"], [18, "/5"], [77, "/6"], [18, "/6"], ":" => [77, "/7"], ";" => [18, "/7"], "<" => [77, "/8"], "=" => [18, "/8"], ">" => [77, "/9"], "?" => [18, "/9"], "@" => [77, "/="], "A" => [18, "/="], "B" => [77, "/A"], "C" => [18, "/A"], "D" => [77, "/_"], "E" => [18, "/_"], "F" => [77, "/b"], "G" => [18, "/b"], "H" => [77, "/d"], "I" => [18, "/d"], "J" => [77, "/f"], "K" => [18, "/f"], "L" => [77, "/g"], "M" => [18, "/g"], "N" => [77, "/h"], "O" => [18, "/h"], "P" => [77, "/l"], "Q" => [18, "/l"], "R" => [77, "/m"], "S" => [18, "/m"], "T" => [77, "/n"], "U" => [18, "/n"], "V" => [77, "/p"], "W" => [18, "/p"], "X" => [77, "/r"], "Y" => [18, "/r"], "Z" => [77, "/u"], "[" => [18, "/u"], "\\" => [0, "/:"], "]" => [0, "/B"], "^" => [0, "/C"], "_" => [0, "/D"], "`" => [0, "/E"], "a" => [0, "/F"], "b" => [0, "/G"], "c" => [0, "/H"], "d" => [0, "/I"], "e" => [0, "/J"], "f" => [0, "/K"], "g" => [0, "/L"], "h" => [0, "/M"], "i" => [0, "/N"], "j" => [0, "/O"], "k" => [0, "/P"], "l" => [0, "/Q"], "m" => [0, "/R"], "n" => [0, "/S"], "o" => [0, "/T"], "p" => [0, "/U"], "q" => [0, "/V"], "r" => [0, "/W"], "s" => [0, "/Y"], "t" => [0, "/j"], "u" => [0, "/k"], "v" => [0, "/q"], "w" => [0, "/v"], "x" => [0, "/w"], "y" => [0, "/x"], "z" => [0, "/y"], "{" => [0, "/z"], "|" => [82, "/"], "}" => [87, "/"], "~" => [130, "/"], "" => [9, "/"], "\x80" => [94, "30"], "\x81" => [76, "30"], "\x82" => [104, "30"], "\x83" => [16, "30"], "\x84" => [94, "31"], "\x85" => [76, "31"], "\x86" => [104, "31"], "\x87" => [16, "31"], "\x88" => [94, "32"], "\x89" => [76, "32"], "\x8a" => [104, "32"], "\x8b" => [16, "32"], "\x8c" => [94, "3a"], "\x8d" => [76, "3a"], "\x8e" => [104, "3a"], "\x8f" => [16, "3a"], "\x90" => [94, "3c"], "\x91" => [76, "3c"], "\x92" => [104, "3c"], "\x93" => [16, "3c"], "\x94" => [94, "3e"], "\x95" => [76, "3e"], "\x96" => [104, "3e"], "\x97" => [16, "3e"], "\x98" => [94, "3i"], "\x99" => [76, "3i"], "\x9a" => [104, "3i"], "\x9b" => [16, "3i"], "\x9c" => [94, "3o"], "\x9d" => [76, "3o"], "\x9e" => [104, "3o"], "\x9f" => [16, "3o"], "\xa0" => [94, "3s"], "\xa1" => [76, "3s"], "\xa2" => [104, "3s"], "\xa3" => [16, "3s"], "\xa4" => [94, "3t"], "\xa5" => [76, "3t"], "\xa6" => [104, "3t"], "\xa7" => [16, "3t"], "\xa8" => [77, "3 "], "\xa9" => [18, "3 "], "\xaa" => [77, "3%"], "\xab" => [18, "3%"], "\xac" => [77, "3-"], "\xad" => [18, "3-"], "\xae" => [77, "3."], "\xaf" => [18, "3."], "\xb0" => [77, "3/"], "\xb1" => [18, "3/"], "\xb2" => [77, "33"], "\xb3" => [18, "33"], "\xb4" => [77, "34"], "\xb5" => [18, "34"], "\xb6" => [77, "35"], "\xb7" => [18, "35"], "\xb8" => [77, "36"], "\xb9" => [18, "36"], "\xba" => [77, "37"], "\xbb" => [18, "37"], "\xbc" => [77, "38"], "\xbd" => [18, "38"], "\xbe" => [77, "39"], "\xbf" => [18, "39"], "\xc0" => [77, "3="], "\xc1" => [18, "3="], "\xc2" => [77, "3A"], "\xc3" => [18, "3A"], "\xc4" => [77, "3_"], "\xc5" => [18, "3_"], "\xc6" => [77, "3b"], "\xc7" => [18, "3b"], "\xc8" => [77, "3d"], "\xc9" => [18, "3d"], "\xca" => [77, "3f"], "\xcb" => [18, "3f"], "\xcc" => [77, "3g"], "\xcd" => [18, "3g"], "\xce" => [77, "3h"], "\xcf" => [18, "3h"], "\xd0" => [77, "3l"], "\xd1" => [18, "3l"], "\xd2" => [77, "3m"], "\xd3" => [18, "3m"], "\xd4" => [77, "3n"], "\xd5" => [18, "3n"], "\xd6" => [77, "3p"], "\xd7" => [18, "3p"], "\xd8" => [77, "3r"], "\xd9" => [18, "3r"], "\xda" => [77, "3u"], "\xdb" => [18, "3u"], "\xdc" => [0, "3:"], "\xdd" => [0, "3B"], "\xde" => [0, "3C"], "\xdf" => [0, "3D"], "\xe0" => [0, "3E"], "\xe1" => [0, "3F"], "\xe2" => [0, "3G"], "\xe3" => [0, "3H"], "\xe4" => [0, "3I"], "\xe5" => [0, "3J"], "\xe6" => [0, "3K"], "\xe7" => [0, "3L"], "\xe8" => [0, "3M"], "\xe9" => [0, "3N"], "\xea" => [0, "3O"], "\xeb" => [0, "3P"], "\xec" => [0, "3Q"], "\xed" => [0, "3R"], "\xee" => [0, "3S"], "\xef" => [0, "3T"], "\xf0" => [0, "3U"], "\xf1" => [0, "3V"], "\xf2" => [0, "3W"], "\xf3" => [0, "3Y"], "\xf4" => [0, "3j"], "\xf5" => [0, "3k"], "\xf6" => [0, "3q"], "\xf7" => [0, "3v"], "\xf8" => [0, "3w"], "\xf9" => [0, "3x"], "\xfa" => [0, "3y"], "\xfb" => [0, "3z"], "\xfc" => [82, "3"], "\xfd" => [87, "3"], "\xfe" => [130, "3"], "\xff" => [9, "3"]], ["\x00" => [77, "/0"], "\x01" => [18, "/0"], "\x02" => [77, "/1"], "\x03" => [18, "/1"], "\x04" => [77, "/2"], "\x05" => [18, "/2"], "\x06" => [77, "/a"], "\x07" => [18, "/a"], "\x08" => [77, "/c"], "\t" => [18, "/c"], "\n" => [77, "/e"], "\v" => [18, "/e"], "\f" => [77, "/i"], "\r" => [18, "/i"], "\x0e" => [77, "/o"], "\x0f" => [18, "/o"], "\x10" => [77, "/s"], "\x11" => [18, "/s"], "\x12" => [77, "/t"], "\x13" => [18, "/t"], "\x14" => [0, "/ "], "\x15" => [0, "/%"], "\x16" => [0, "/-"], "\x17" => [0, "/."], "\x18" => [0, "//"], "\x19" => [0, "/3"], "\x1a" => [0, "/4"], "\x1b" => [0, "/5"], "\x1c" => [0, "/6"], "\x1d" => [0, "/7"], "\x1e" => [0, "/8"], "\x1f" => [0, "/9"], " " => [0, "/="], "!" => [0, "/A"], "\"" => [0, "/_"], "#" => [0, "/b"], "\$" => [0, "/d"], "%" => [0, "/f"], "&" => [0, "/g"], "'" => [0, "/h"], "(" => [0, "/l"], ")" => [0, "/m"], "*" => [0, "/n"], "+" => [0, "/p"], "," => [0, "/r"], "-" => [0, "/u"], "." => [100, "/"], "/" => [110, "/"], [111, "/"], [115, "/"], [116, "/"], [118, "/"], [119, "/"], [122, "/"], [123, "/"], [125, "/"], [126, "/"], [129, "/"], ":" => [143, "/"], ";" => [148, "/"], "<" => [151, "/"], "=" => [153, "/"], ">" => [83, "/"], "?" => [10, "/"], "@" => [77, "30"], "A" => [18, "30"], "B" => [77, "31"], "C" => [18, "31"], "D" => [77, "32"], "E" => [18, "32"], "F" => [77, "3a"], "G" => [18, "3a"], "H" => [77, "3c"], "I" => [18, "3c"], "J" => [77, "3e"], "K" => [18, "3e"], "L" => [77, "3i"], "M" => [18, "3i"], "N" => [77, "3o"], "O" => [18, "3o"], "P" => [77, "3s"], "Q" => [18, "3s"], "R" => [77, "3t"], "S" => [18, "3t"], "T" => [0, "3 "], "U" => [0, "3%"], "V" => [0, "3-"], "W" => [0, "3."], "X" => [0, "3/"], "Y" => [0, "33"], "Z" => [0, "34"], "[" => [0, "35"], "\\" => [0, "36"], "]" => [0, "37"], "^" => [0, "38"], "_" => [0, "39"], "`" => [0, "3="], "a" => [0, "3A"], "b" => [0, "3_"], "c" => [0, "3b"], "d" => [0, "3d"], "e" => [0, "3f"], "f" => [0, "3g"], "g" => [0, "3h"], "h" => [0, "3l"], "i" => [0, "3m"], "j" => [0, "3n"], "k" => [0, "3p"], "l" => [0, "3r"], "m" => [0, "3u"], "n" => [100, "3"], "o" => [110, "3"], "p" => [111, "3"], "q" => [115, "3"], "r" => [116, "3"], "s" => [118, "3"], "t" => [119, "3"], "u" => [122, "3"], "v" => [123, "3"], "w" => [125, "3"], "x" => [126, "3"], "y" => [129, "3"], "z" => [143, "3"], "{" => [148, "3"], "|" => [151, "3"], "}" => [153, "3"], "~" => [83, "3"], "" => [10, "3"], "\x80" => [77, "40"], "\x81" => [18, "40"], "\x82" => [77, "41"], "\x83" => [18, "41"], "\x84" => [77, "42"], "\x85" => [18, "42"], "\x86" => [77, "4a"], "\x87" => [18, "4a"], "\x88" => [77, "4c"], "\x89" => [18, "4c"], "\x8a" => [77, "4e"], "\x8b" => [18, "4e"], "\x8c" => [77, "4i"], "\x8d" => [18, "4i"], "\x8e" => [77, "4o"], "\x8f" => [18, "4o"], "\x90" => [77, "4s"], "\x91" => [18, "4s"], "\x92" => [77, "4t"], "\x93" => [18, "4t"], "\x94" => [0, "4 "], "\x95" => [0, "4%"], "\x96" => [0, "4-"], "\x97" => [0, "4."], "\x98" => [0, "4/"], "\x99" => [0, "43"], "\x9a" => [0, "44"], "\x9b" => [0, "45"], "\x9c" => [0, "46"], "\x9d" => [0, "47"], "\x9e" => [0, "48"], "\x9f" => [0, "49"], "\xa0" => [0, "4="], "\xa1" => [0, "4A"], "\xa2" => [0, "4_"], "\xa3" => [0, "4b"], "\xa4" => [0, "4d"], "\xa5" => [0, "4f"], "\xa6" => [0, "4g"], "\xa7" => [0, "4h"], "\xa8" => [0, "4l"], "\xa9" => [0, "4m"], "\xaa" => [0, "4n"], "\xab" => [0, "4p"], "\xac" => [0, "4r"], "\xad" => [0, "4u"], "\xae" => [100, "4"], "\xaf" => [110, "4"], "\xb0" => [111, "4"], "\xb1" => [115, "4"], "\xb2" => [116, "4"], "\xb3" => [118, "4"], "\xb4" => [119, "4"], "\xb5" => [122, "4"], "\xb6" => [123, "4"], "\xb7" => [125, "4"], "\xb8" => [126, "4"], "\xb9" => [129, "4"], "\xba" => [143, "4"], "\xbb" => [148, "4"], "\xbc" => [151, "4"], "\xbd" => [153, "4"], "\xbe" => [83, "4"], "\xbf" => [10, "4"], "\xc0" => [77, "50"], "\xc1" => [18, "50"], "\xc2" => [77, "51"], "\xc3" => [18, "51"], "\xc4" => [77, "52"], "\xc5" => [18, "52"], "\xc6" => [77, "5a"], "\xc7" => [18, "5a"], "\xc8" => [77, "5c"], "\xc9" => [18, "5c"], "\xca" => [77, "5e"], "\xcb" => [18, "5e"], "\xcc" => [77, "5i"], "\xcd" => [18, "5i"], "\xce" => [77, "5o"], "\xcf" => [18, "5o"], "\xd0" => [77, "5s"], "\xd1" => [18, "5s"], "\xd2" => [77, "5t"], "\xd3" => [18, "5t"], "\xd4" => [0, "5 "], "\xd5" => [0, "5%"], "\xd6" => [0, "5-"], "\xd7" => [0, "5."], "\xd8" => [0, "5/"], "\xd9" => [0, "53"], "\xda" => [0, "54"], "\xdb" => [0, "55"], "\xdc" => [0, "56"], "\xdd" => [0, "57"], "\xde" => [0, "58"], "\xdf" => [0, "59"], "\xe0" => [0, "5="], "\xe1" => [0, "5A"], "\xe2" => [0, "5_"], "\xe3" => [0, "5b"], "\xe4" => [0, "5d"], "\xe5" => [0, "5f"], "\xe6" => [0, "5g"], "\xe7" => [0, "5h"], "\xe8" => [0, "5l"], "\xe9" => [0, "5m"], "\xea" => [0, "5n"], "\xeb" => [0, "5p"], "\xec" => [0, "5r"], "\xed" => [0, "5u"], "\xee" => [100, "5"], "\xef" => [110, "5"], "\xf0" => [111, "5"], "\xf1" => [115, "5"], "\xf2" => [116, "5"], "\xf3" => [118, "5"], "\xf4" => [119, "5"], "\xf5" => [122, "5"], "\xf6" => [123, "5"], "\xf7" => [125, "5"], "\xf8" => [126, "5"], "\xf9" => [129, "5"], "\xfa" => [143, "5"], "\xfb" => [148, "5"], "\xfc" => [151, "5"], "\xfd" => [153, "5"], "\xfe" => [83, "5"], "\xff" => [10, "5"]], ["\x00" => [0, "/0"], "\x01" => [0, "/1"], "\x02" => [0, "/2"], "\x03" => [0, "/a"], "\x04" => [0, "/c"], "\x05" => [0, "/e"], "\x06" => [0, "/i"], "\x07" => [0, "/o"], "\x08" => [0, "/s"], "\t" => [0, "/t"], "\n" => [73, "/"], "\v" => [88, "/"], "\f" => [89, "/"], "\r" => [96, "/"], "\x0e" => [97, "/"], "\x0f" => [99, "/"], "\x10" => [106, "/"], "\x11" => [136, "/"], "\x12" => [139, "/"], "\x13" => [141, "/"], "\x14" => [145, "/"], "\x15" => [147, "/"], "\x16" => [149, "/"], "\x17" => [101, "/"], "\x18" => [112, "/"], "\x19" => [117, "/"], "\x1a" => [120, "/"], "\x1b" => [124, "/"], "\x1c" => [127, "/"], "\x1d" => [144, "/"], "\x1e" => [152, "/"], "\x1f" => [11, "/"], " " => [0, "30"], "!" => [0, "31"], "\"" => [0, "32"], "#" => [0, "3a"], "\$" => [0, "3c"], "%" => [0, "3e"], "&" => [0, "3i"], "'" => [0, "3o"], "(" => [0, "3s"], ")" => [0, "3t"], "*" => [73, "3"], "+" => [88, "3"], "," => [89, "3"], "-" => [96, "3"], "." => [97, "3"], "/" => [99, "3"], [106, "3"], [136, "3"], [139, "3"], [141, "3"], [145, "3"], [147, "3"], [149, "3"], [101, "3"], [112, "3"], [117, "3"], ":" => [120, "3"], ";" => [124, "3"], "<" => [127, "3"], "=" => [144, "3"], ">" => [152, "3"], "?" => [11, "3"], "@" => [0, "40"], "A" => [0, "41"], "B" => [0, "42"], "C" => [0, "4a"], "D" => [0, "4c"], "E" => [0, "4e"], "F" => [0, "4i"], "G" => [0, "4o"], "H" => [0, "4s"], "I" => [0, "4t"], "J" => [73, "4"], "K" => [88, "4"], "L" => [89, "4"], "M" => [96, "4"], "N" => [97, "4"], "O" => [99, "4"], "P" => [106, "4"], "Q" => [136, "4"], "R" => [139, "4"], "S" => [141, "4"], "T" => [145, "4"], "U" => [147, "4"], "V" => [149, "4"], "W" => [101, "4"], "X" => [112, "4"], "Y" => [117, "4"], "Z" => [120, "4"], "[" => [124, "4"], "\\" => [127, "4"], "]" => [144, "4"], "^" => [152, "4"], "_" => [11, "4"], "`" => [0, "50"], "a" => [0, "51"], "b" => [0, "52"], "c" => [0, "5a"], "d" => [0, "5c"], "e" => [0, "5e"], "f" => [0, "5i"], "g" => [0, "5o"], "h" => [0, "5s"], "i" => [0, "5t"], "j" => [73, "5"], "k" => [88, "5"], "l" => [89, "5"], "m" => [96, "5"], "n" => [97, "5"], "o" => [99, "5"], "p" => [106, "5"], "q" => [136, "5"], "r" => [139, "5"], "s" => [141, "5"], "t" => [145, "5"], "u" => [147, "5"], "v" => [149, "5"], "w" => [101, "5"], "x" => [112, "5"], "y" => [117, "5"], "z" => [120, "5"], "{" => [124, "5"], "|" => [127, "5"], "}" => [144, "5"], "~" => [152, "5"], "" => [11, "5"], "\x80" => [0, "60"], "\x81" => [0, "61"], "\x82" => [0, "62"], "\x83" => [0, "6a"], "\x84" => [0, "6c"], "\x85" => [0, "6e"], "\x86" => [0, "6i"], "\x87" => [0, "6o"], "\x88" => [0, "6s"], "\x89" => [0, "6t"], "\x8a" => [73, "6"], "\x8b" => [88, "6"], "\x8c" => [89, "6"], "\x8d" => [96, "6"], "\x8e" => [97, "6"], "\x8f" => [99, "6"], "\x90" => [106, "6"], "\x91" => [136, "6"], "\x92" => [139, "6"], "\x93" => [141, "6"], "\x94" => [145, "6"], "\x95" => [147, "6"], "\x96" => [149, "6"], "\x97" => [101, "6"], "\x98" => [112, "6"], "\x99" => [117, "6"], "\x9a" => [120, "6"], "\x9b" => [124, "6"], "\x9c" => [127, "6"], "\x9d" => [144, "6"], "\x9e" => [152, "6"], "\x9f" => [11, "6"], "\xa0" => [0, "70"], "\xa1" => [0, "71"], "\xa2" => [0, "72"], "\xa3" => [0, "7a"], "\xa4" => [0, "7c"], "\xa5" => [0, "7e"], "\xa6" => [0, "7i"], "\xa7" => [0, "7o"], "\xa8" => [0, "7s"], "\xa9" => [0, "7t"], "\xaa" => [73, "7"], "\xab" => [88, "7"], "\xac" => [89, "7"], "\xad" => [96, "7"], "\xae" => [97, "7"], "\xaf" => [99, "7"], "\xb0" => [106, "7"], "\xb1" => [136, "7"], "\xb2" => [139, "7"], "\xb3" => [141, "7"], "\xb4" => [145, "7"], "\xb5" => [147, "7"], "\xb6" => [149, "7"], "\xb7" => [101, "7"], "\xb8" => [112, "7"], "\xb9" => [117, "7"], "\xba" => [120, "7"], "\xbb" => [124, "7"], "\xbc" => [127, "7"], "\xbd" => [144, "7"], "\xbe" => [152, "7"], "\xbf" => [11, "7"], "\xc0" => [0, "80"], "\xc1" => [0, "81"], "\xc2" => [0, "82"], "\xc3" => [0, "8a"], "\xc4" => [0, "8c"], "\xc5" => [0, "8e"], "\xc6" => [0, "8i"], "\xc7" => [0, "8o"], "\xc8" => [0, "8s"], "\xc9" => [0, "8t"], "\xca" => [73, "8"], "\xcb" => [88, "8"], "\xcc" => [89, "8"], "\xcd" => [96, "8"], "\xce" => [97, "8"], "\xcf" => [99, "8"], "\xd0" => [106, "8"], "\xd1" => [136, "8"], "\xd2" => [139, "8"], "\xd3" => [141, "8"], "\xd4" => [145, "8"], "\xd5" => [147, "8"], "\xd6" => [149, "8"], "\xd7" => [101, "8"], "\xd8" => [112, "8"], "\xd9" => [117, "8"], "\xda" => [120, "8"], "\xdb" => [124, "8"], "\xdc" => [127, "8"], "\xdd" => [144, "8"], "\xde" => [152, "8"], "\xdf" => [11, "8"], "\xe0" => [0, "90"], "\xe1" => [0, "91"], "\xe2" => [0, "92"], "\xe3" => [0, "9a"], "\xe4" => [0, "9c"], "\xe5" => [0, "9e"], "\xe6" => [0, "9i"], "\xe7" => [0, "9o"], "\xe8" => [0, "9s"], "\xe9" => [0, "9t"], "\xea" => [73, "9"], "\xeb" => [88, "9"], "\xec" => [89, "9"], "\xed" => [96, "9"], "\xee" => [97, "9"], "\xef" => [99, "9"], "\xf0" => [106, "9"], "\xf1" => [136, "9"], "\xf2" => [139, "9"], "\xf3" => [141, "9"], "\xf4" => [145, "9"], "\xf5" => [147, "9"], "\xf6" => [149, "9"], "\xf7" => [101, "9"], "\xf8" => [112, "9"], "\xf9" => [117, "9"], "\xfa" => [120, "9"], "\xfb" => [124, "9"], "\xfc" => [127, "9"], "\xfd" => [144, "9"], "\xfe" => [152, "9"], "\xff" => [11, "9"]], ["\x00" => [94, "00"], "\x01" => [76, "00"], "\x02" => [104, "00"], "\x03" => [16, "00"], "\x04" => [94, "01"], "\x05" => [76, "01"], "\x06" => [104, "01"], "\x07" => [16, "01"], "\x08" => [94, "02"], "\t" => [76, "02"], "\n" => [104, "02"], "\v" => [16, "02"], "\f" => [94, "0a"], "\r" => [76, "0a"], "\x0e" => [104, "0a"], "\x0f" => [16, "0a"], "\x10" => [94, "0c"], "\x11" => [76, "0c"], "\x12" => [104, "0c"], "\x13" => [16, "0c"], "\x14" => [94, "0e"], "\x15" => [76, "0e"], "\x16" => [104, "0e"], "\x17" => [16, "0e"], "\x18" => [94, "0i"], "\x19" => [76, "0i"], "\x1a" => [104, "0i"], "\x1b" => [16, "0i"], "\x1c" => [94, "0o"], "\x1d" => [76, "0o"], "\x1e" => [104, "0o"], "\x1f" => [16, "0o"], " " => [94, "0s"], "!" => [76, "0s"], "\"" => [104, "0s"], "#" => [16, "0s"], "\$" => [94, "0t"], "%" => [76, "0t"], "&" => [104, "0t"], "'" => [16, "0t"], "(" => [77, "0 "], ")" => [18, "0 "], "*" => [77, "0%"], "+" => [18, "0%"], "," => [77, "0-"], "-" => [18, "0-"], "." => [77, "0."], "/" => [18, "0."], [77, "0/"], [18, "0/"], [77, "03"], [18, "03"], [77, "04"], [18, "04"], [77, "05"], [18, "05"], [77, "06"], [18, "06"], ":" => [77, "07"], ";" => [18, "07"], "<" => [77, "08"], "=" => [18, "08"], ">" => [77, "09"], "?" => [18, "09"], "@" => [77, "0="], "A" => [18, "0="], "B" => [77, "0A"], "C" => [18, "0A"], "D" => [77, "0_"], "E" => [18, "0_"], "F" => [77, "0b"], "G" => [18, "0b"], "H" => [77, "0d"], "I" => [18, "0d"], "J" => [77, "0f"], "K" => [18, "0f"], "L" => [77, "0g"], "M" => [18, "0g"], "N" => [77, "0h"], "O" => [18, "0h"], "P" => [77, "0l"], "Q" => [18, "0l"], "R" => [77, "0m"], "S" => [18, "0m"], "T" => [77, "0n"], "U" => [18, "0n"], "V" => [77, "0p"], "W" => [18, "0p"], "X" => [77, "0r"], "Y" => [18, "0r"], "Z" => [77, "0u"], "[" => [18, "0u"], "\\" => [0, "0:"], "]" => [0, "0B"], "^" => [0, "0C"], "_" => [0, "0D"], "`" => [0, "0E"], "a" => [0, "0F"], "b" => [0, "0G"], "c" => [0, "0H"], "d" => [0, "0I"], "e" => [0, "0J"], "f" => [0, "0K"], "g" => [0, "0L"], "h" => [0, "0M"], "i" => [0, "0N"], "j" => [0, "0O"], "k" => [0, "0P"], "l" => [0, "0Q"], "m" => [0, "0R"], "n" => [0, "0S"], "o" => [0, "0T"], "p" => [0, "0U"], "q" => [0, "0V"], "r" => [0, "0W"], "s" => [0, "0Y"], "t" => [0, "0j"], "u" => [0, "0k"], "v" => [0, "0q"], "w" => [0, "0v"], "x" => [0, "0w"], "y" => [0, "0x"], "z" => [0, "0y"], "{" => [0, "0z"], "|" => [82, "0"], "}" => [87, "0"], "~" => [130, "0"], "" => [9, "0"], "\x80" => [94, "10"], "\x81" => [76, "10"], "\x82" => [104, "10"], "\x83" => [16, "10"], "\x84" => [94, "11"], "\x85" => [76, "11"], "\x86" => [104, "11"], "\x87" => [16, "11"], "\x88" => [94, "12"], "\x89" => [76, "12"], "\x8a" => [104, "12"], "\x8b" => [16, "12"], "\x8c" => [94, "1a"], "\x8d" => [76, "1a"], "\x8e" => [104, "1a"], "\x8f" => [16, "1a"], "\x90" => [94, "1c"], "\x91" => [76, "1c"], "\x92" => [104, "1c"], "\x93" => [16, "1c"], "\x94" => [94, "1e"], "\x95" => [76, "1e"], "\x96" => [104, "1e"], "\x97" => [16, "1e"], "\x98" => [94, "1i"], "\x99" => [76, "1i"], "\x9a" => [104, "1i"], "\x9b" => [16, "1i"], "\x9c" => [94, "1o"], "\x9d" => [76, "1o"], "\x9e" => [104, "1o"], "\x9f" => [16, "1o"], "\xa0" => [94, "1s"], "\xa1" => [76, "1s"], "\xa2" => [104, "1s"], "\xa3" => [16, "1s"], "\xa4" => [94, "1t"], "\xa5" => [76, "1t"], "\xa6" => [104, "1t"], "\xa7" => [16, "1t"], "\xa8" => [77, "1 "], "\xa9" => [18, "1 "], "\xaa" => [77, "1%"], "\xab" => [18, "1%"], "\xac" => [77, "1-"], "\xad" => [18, "1-"], "\xae" => [77, "1."], "\xaf" => [18, "1."], "\xb0" => [77, "1/"], "\xb1" => [18, "1/"], "\xb2" => [77, "13"], "\xb3" => [18, "13"], "\xb4" => [77, "14"], "\xb5" => [18, "14"], "\xb6" => [77, "15"], "\xb7" => [18, "15"], "\xb8" => [77, "16"], "\xb9" => [18, "16"], "\xba" => [77, "17"], "\xbb" => [18, "17"], "\xbc" => [77, "18"], "\xbd" => [18, "18"], "\xbe" => [77, "19"], "\xbf" => [18, "19"], "\xc0" => [77, "1="], "\xc1" => [18, "1="], "\xc2" => [77, "1A"], "\xc3" => [18, "1A"], "\xc4" => [77, "1_"], "\xc5" => [18, "1_"], "\xc6" => [77, "1b"], "\xc7" => [18, "1b"], "\xc8" => [77, "1d"], "\xc9" => [18, "1d"], "\xca" => [77, "1f"], "\xcb" => [18, "1f"], "\xcc" => [77, "1g"], "\xcd" => [18, "1g"], "\xce" => [77, "1h"], "\xcf" => [18, "1h"], "\xd0" => [77, "1l"], "\xd1" => [18, "1l"], "\xd2" => [77, "1m"], "\xd3" => [18, "1m"], "\xd4" => [77, "1n"], "\xd5" => [18, "1n"], "\xd6" => [77, "1p"], "\xd7" => [18, "1p"], "\xd8" => [77, "1r"], "\xd9" => [18, "1r"], "\xda" => [77, "1u"], "\xdb" => [18, "1u"], "\xdc" => [0, "1:"], "\xdd" => [0, "1B"], "\xde" => [0, "1C"], "\xdf" => [0, "1D"], "\xe0" => [0, "1E"], "\xe1" => [0, "1F"], "\xe2" => [0, "1G"], "\xe3" => [0, "1H"], "\xe4" => [0, "1I"], "\xe5" => [0, "1J"], "\xe6" => [0, "1K"], "\xe7" => [0, "1L"], "\xe8" => [0, "1M"], "\xe9" => [0, "1N"], "\xea" => [0, "1O"], "\xeb" => [0, "1P"], "\xec" => [0, "1Q"], "\xed" => [0, "1R"], "\xee" => [0, "1S"], "\xef" => [0, "1T"], "\xf0" => [0, "1U"], "\xf1" => [0, "1V"], "\xf2" => [0, "1W"], "\xf3" => [0, "1Y"], "\xf4" => [0, "1j"], "\xf5" => [0, "1k"], "\xf6" => [0, "1q"], "\xf7" => [0, "1v"], "\xf8" => [0, "1w"], "\xf9" => [0, "1x"], "\xfa" => [0, "1y"], "\xfb" => [0, "1z"], "\xfc" => [82, "1"], "\xfd" => [87, "1"], "\xfe" => [130, "1"], "\xff" => [9, "1"]], ["\x00" => [77, "00"], "\x01" => [18, "00"], "\x02" => [77, "01"], "\x03" => [18, "01"], "\x04" => [77, "02"], "\x05" => [18, "02"], "\x06" => [77, "0a"], "\x07" => [18, "0a"], "\x08" => [77, "0c"], "\t" => [18, "0c"], "\n" => [77, "0e"], "\v" => [18, "0e"], "\f" => [77, "0i"], "\r" => [18, "0i"], "\x0e" => [77, "0o"], "\x0f" => [18, "0o"], "\x10" => [77, "0s"], "\x11" => [18, "0s"], "\x12" => [77, "0t"], "\x13" => [18, "0t"], "\x14" => [0, "0 "], "\x15" => [0, "0%"], "\x16" => [0, "0-"], "\x17" => [0, "0."], "\x18" => [0, "0/"], "\x19" => [0, "03"], "\x1a" => [0, "04"], "\x1b" => [0, "05"], "\x1c" => [0, "06"], "\x1d" => [0, "07"], "\x1e" => [0, "08"], "\x1f" => [0, "09"], " " => [0, "0="], "!" => [0, "0A"], "\"" => [0, "0_"], "#" => [0, "0b"], "\$" => [0, "0d"], "%" => [0, "0f"], "&" => [0, "0g"], "'" => [0, "0h"], "(" => [0, "0l"], ")" => [0, "0m"], "*" => [0, "0n"], "+" => [0, "0p"], "," => [0, "0r"], "-" => [0, "0u"], "." => [100, "0"], "/" => [110, "0"], [111, "0"], [115, "0"], [116, "0"], [118, "0"], [119, "0"], [122, "0"], [123, "0"], [125, "0"], [126, "0"], [129, "0"], ":" => [143, "0"], ";" => [148, "0"], "<" => [151, "0"], "=" => [153, "0"], ">" => [83, "0"], "?" => [10, "0"], "@" => [77, "10"], "A" => [18, "10"], "B" => [77, "11"], "C" => [18, "11"], "D" => [77, "12"], "E" => [18, "12"], "F" => [77, "1a"], "G" => [18, "1a"], "H" => [77, "1c"], "I" => [18, "1c"], "J" => [77, "1e"], "K" => [18, "1e"], "L" => [77, "1i"], "M" => [18, "1i"], "N" => [77, "1o"], "O" => [18, "1o"], "P" => [77, "1s"], "Q" => [18, "1s"], "R" => [77, "1t"], "S" => [18, "1t"], "T" => [0, "1 "], "U" => [0, "1%"], "V" => [0, "1-"], "W" => [0, "1."], "X" => [0, "1/"], "Y" => [0, "13"], "Z" => [0, "14"], "[" => [0, "15"], "\\" => [0, "16"], "]" => [0, "17"], "^" => [0, "18"], "_" => [0, "19"], "`" => [0, "1="], "a" => [0, "1A"], "b" => [0, "1_"], "c" => [0, "1b"], "d" => [0, "1d"], "e" => [0, "1f"], "f" => [0, "1g"], "g" => [0, "1h"], "h" => [0, "1l"], "i" => [0, "1m"], "j" => [0, "1n"], "k" => [0, "1p"], "l" => [0, "1r"], "m" => [0, "1u"], "n" => [100, "1"], "o" => [110, "1"], "p" => [111, "1"], "q" => [115, "1"], "r" => [116, "1"], "s" => [118, "1"], "t" => [119, "1"], "u" => [122, "1"], "v" => [123, "1"], "w" => [125, "1"], "x" => [126, "1"], "y" => [129, "1"], "z" => [143, "1"], "{" => [148, "1"], "|" => [151, "1"], "}" => [153, "1"], "~" => [83, "1"], "" => [10, "1"], "\x80" => [77, "20"], "\x81" => [18, "20"], "\x82" => [77, "21"], "\x83" => [18, "21"], "\x84" => [77, "22"], "\x85" => [18, "22"], "\x86" => [77, "2a"], "\x87" => [18, "2a"], "\x88" => [77, "2c"], "\x89" => [18, "2c"], "\x8a" => [77, "2e"], "\x8b" => [18, "2e"], "\x8c" => [77, "2i"], "\x8d" => [18, "2i"], "\x8e" => [77, "2o"], "\x8f" => [18, "2o"], "\x90" => [77, "2s"], "\x91" => [18, "2s"], "\x92" => [77, "2t"], "\x93" => [18, "2t"], "\x94" => [0, "2 "], "\x95" => [0, "2%"], "\x96" => [0, "2-"], "\x97" => [0, "2."], "\x98" => [0, "2/"], "\x99" => [0, "23"], "\x9a" => [0, "24"], "\x9b" => [0, "25"], "\x9c" => [0, "26"], "\x9d" => [0, "27"], "\x9e" => [0, "28"], "\x9f" => [0, "29"], "\xa0" => [0, "2="], "\xa1" => [0, "2A"], "\xa2" => [0, "2_"], "\xa3" => [0, "2b"], "\xa4" => [0, "2d"], "\xa5" => [0, "2f"], "\xa6" => [0, "2g"], "\xa7" => [0, "2h"], "\xa8" => [0, "2l"], "\xa9" => [0, "2m"], "\xaa" => [0, "2n"], "\xab" => [0, "2p"], "\xac" => [0, "2r"], "\xad" => [0, "2u"], "\xae" => [100, "2"], "\xaf" => [110, "2"], "\xb0" => [111, "2"], "\xb1" => [115, "2"], "\xb2" => [116, "2"], "\xb3" => [118, "2"], "\xb4" => [119, "2"], "\xb5" => [122, "2"], "\xb6" => [123, "2"], "\xb7" => [125, "2"], "\xb8" => [126, "2"], "\xb9" => [129, "2"], "\xba" => [143, "2"], "\xbb" => [148, "2"], "\xbc" => [151, "2"], "\xbd" => [153, "2"], "\xbe" => [83, "2"], "\xbf" => [10, "2"], "\xc0" => [77, "a0"], "\xc1" => [18, "a0"], "\xc2" => [77, "a1"], "\xc3" => [18, "a1"], "\xc4" => [77, "a2"], "\xc5" => [18, "a2"], "\xc6" => [77, "aa"], "\xc7" => [18, "aa"], "\xc8" => [77, "ac"], "\xc9" => [18, "ac"], "\xca" => [77, "ae"], "\xcb" => [18, "ae"], "\xcc" => [77, "ai"], "\xcd" => [18, "ai"], "\xce" => [77, "ao"], "\xcf" => [18, "ao"], "\xd0" => [77, "as"], "\xd1" => [18, "as"], "\xd2" => [77, "at"], "\xd3" => [18, "at"], "\xd4" => [0, "a "], "\xd5" => [0, "a%"], "\xd6" => [0, "a-"], "\xd7" => [0, "a."], "\xd8" => [0, "a/"], "\xd9" => [0, "a3"], "\xda" => [0, "a4"], "\xdb" => [0, "a5"], "\xdc" => [0, "a6"], "\xdd" => [0, "a7"], "\xde" => [0, "a8"], "\xdf" => [0, "a9"], "\xe0" => [0, "a="], "\xe1" => [0, "aA"], "\xe2" => [0, "a_"], "\xe3" => [0, "ab"], "\xe4" => [0, "ad"], "\xe5" => [0, "af"], "\xe6" => [0, "ag"], "\xe7" => [0, "ah"], "\xe8" => [0, "al"], "\xe9" => [0, "am"], "\xea" => [0, "an"], "\xeb" => [0, "ap"], "\xec" => [0, "ar"], "\xed" => [0, "au"], "\xee" => [100, "a"], "\xef" => [110, "a"], "\xf0" => [111, "a"], "\xf1" => [115, "a"], "\xf2" => [116, "a"], "\xf3" => [118, "a"], "\xf4" => [119, "a"], "\xf5" => [122, "a"], "\xf6" => [123, "a"], "\xf7" => [125, "a"], "\xf8" => [126, "a"], "\xf9" => [129, "a"], "\xfa" => [143, "a"], "\xfb" => [148, "a"], "\xfc" => [151, "a"], "\xfd" => [153, "a"], "\xfe" => [83, "a"], "\xff" => [10, "a"]], ["\x00" => [0, "00"], "\x01" => [0, "01"], "\x02" => [0, "02"], "\x03" => [0, "0a"], "\x04" => [0, "0c"], "\x05" => [0, "0e"], "\x06" => [0, "0i"], "\x07" => [0, "0o"], "\x08" => [0, "0s"], "\t" => [0, "0t"], "\n" => [73, "0"], "\v" => [88, "0"], "\f" => [89, "0"], "\r" => [96, "0"], "\x0e" => [97, "0"], "\x0f" => [99, "0"], "\x10" => [106, "0"], "\x11" => [136, "0"], "\x12" => [139, "0"], "\x13" => [141, "0"], "\x14" => [145, "0"], "\x15" => [147, "0"], "\x16" => [149, "0"], "\x17" => [101, "0"], "\x18" => [112, "0"], "\x19" => [117, "0"], "\x1a" => [120, "0"], "\x1b" => [124, "0"], "\x1c" => [127, "0"], "\x1d" => [144, "0"], "\x1e" => [152, "0"], "\x1f" => [11, "0"], " " => [0, "10"], "!" => [0, "11"], "\"" => [0, "12"], "#" => [0, "1a"], "\$" => [0, "1c"], "%" => [0, "1e"], "&" => [0, "1i"], "'" => [0, "1o"], "(" => [0, "1s"], ")" => [0, "1t"], "*" => [73, "1"], "+" => [88, "1"], "," => [89, "1"], "-" => [96, "1"], "." => [97, "1"], "/" => [99, "1"], [106, "1"], [136, "1"], [139, "1"], [141, "1"], [145, "1"], [147, "1"], [149, "1"], [101, "1"], [112, "1"], [117, "1"], ":" => [120, "1"], ";" => [124, "1"], "<" => [127, "1"], "=" => [144, "1"], ">" => [152, "1"], "?" => [11, "1"], "@" => [0, "20"], "A" => [0, "21"], "B" => [0, "22"], "C" => [0, "2a"], "D" => [0, "2c"], "E" => [0, "2e"], "F" => [0, "2i"], "G" => [0, "2o"], "H" => [0, "2s"], "I" => [0, "2t"], "J" => [73, "2"], "K" => [88, "2"], "L" => [89, "2"], "M" => [96, "2"], "N" => [97, "2"], "O" => [99, "2"], "P" => [106, "2"], "Q" => [136, "2"], "R" => [139, "2"], "S" => [141, "2"], "T" => [145, "2"], "U" => [147, "2"], "V" => [149, "2"], "W" => [101, "2"], "X" => [112, "2"], "Y" => [117, "2"], "Z" => [120, "2"], "[" => [124, "2"], "\\" => [127, "2"], "]" => [144, "2"], "^" => [152, "2"], "_" => [11, "2"], "`" => [0, "a0"], "a" => [0, "a1"], "b" => [0, "a2"], "c" => [0, "aa"], "d" => [0, "ac"], "e" => [0, "ae"], "f" => [0, "ai"], "g" => [0, "ao"], "h" => [0, "as"], "i" => [0, "at"], "j" => [73, "a"], "k" => [88, "a"], "l" => [89, "a"], "m" => [96, "a"], "n" => [97, "a"], "o" => [99, "a"], "p" => [106, "a"], "q" => [136, "a"], "r" => [139, "a"], "s" => [141, "a"], "t" => [145, "a"], "u" => [147, "a"], "v" => [149, "a"], "w" => [101, "a"], "x" => [112, "a"], "y" => [117, "a"], "z" => [120, "a"], "{" => [124, "a"], "|" => [127, "a"], "}" => [144, "a"], "~" => [152, "a"], "" => [11, "a"], "\x80" => [0, "c0"], "\x81" => [0, "c1"], "\x82" => [0, "c2"], "\x83" => [0, "ca"], "\x84" => [0, "cc"], "\x85" => [0, "ce"], "\x86" => [0, "ci"], "\x87" => [0, "co"], "\x88" => [0, "cs"], "\x89" => [0, "ct"], "\x8a" => [73, "c"], "\x8b" => [88, "c"], "\x8c" => [89, "c"], "\x8d" => [96, "c"], "\x8e" => [97, "c"], "\x8f" => [99, "c"], "\x90" => [106, "c"], "\x91" => [136, "c"], "\x92" => [139, "c"], "\x93" => [141, "c"], "\x94" => [145, "c"], "\x95" => [147, "c"], "\x96" => [149, "c"], "\x97" => [101, "c"], "\x98" => [112, "c"], "\x99" => [117, "c"], "\x9a" => [120, "c"], "\x9b" => [124, "c"], "\x9c" => [127, "c"], "\x9d" => [144, "c"], "\x9e" => [152, "c"], "\x9f" => [11, "c"], "\xa0" => [0, "e0"], "\xa1" => [0, "e1"], "\xa2" => [0, "e2"], "\xa3" => [0, "ea"], "\xa4" => [0, "ec"], "\xa5" => [0, "ee"], "\xa6" => [0, "ei"], "\xa7" => [0, "eo"], "\xa8" => [0, "es"], "\xa9" => [0, "et"], "\xaa" => [73, "e"], "\xab" => [88, "e"], "\xac" => [89, "e"], "\xad" => [96, "e"], "\xae" => [97, "e"], "\xaf" => [99, "e"], "\xb0" => [106, "e"], "\xb1" => [136, "e"], "\xb2" => [139, "e"], "\xb3" => [141, "e"], "\xb4" => [145, "e"], "\xb5" => [147, "e"], "\xb6" => [149, "e"], "\xb7" => [101, "e"], "\xb8" => [112, "e"], "\xb9" => [117, "e"], "\xba" => [120, "e"], "\xbb" => [124, "e"], "\xbc" => [127, "e"], "\xbd" => [144, "e"], "\xbe" => [152, "e"], "\xbf" => [11, "e"], "\xc0" => [0, "i0"], "\xc1" => [0, "i1"], "\xc2" => [0, "i2"], "\xc3" => [0, "ia"], "\xc4" => [0, "ic"], "\xc5" => [0, "ie"], "\xc6" => [0, "ii"], "\xc7" => [0, "io"], "\xc8" => [0, "is"], "\xc9" => [0, "it"], "\xca" => [73, "i"], "\xcb" => [88, "i"], "\xcc" => [89, "i"], "\xcd" => [96, "i"], "\xce" => [97, "i"], "\xcf" => [99, "i"], "\xd0" => [106, "i"], "\xd1" => [136, "i"], "\xd2" => [139, "i"], "\xd3" => [141, "i"], "\xd4" => [145, "i"], "\xd5" => [147, "i"], "\xd6" => [149, "i"], "\xd7" => [101, "i"], "\xd8" => [112, "i"], "\xd9" => [117, "i"], "\xda" => [120, "i"], "\xdb" => [124, "i"], "\xdc" => [127, "i"], "\xdd" => [144, "i"], "\xde" => [152, "i"], "\xdf" => [11, "i"], "\xe0" => [0, "o0"], "\xe1" => [0, "o1"], "\xe2" => [0, "o2"], "\xe3" => [0, "oa"], "\xe4" => [0, "oc"], "\xe5" => [0, "oe"], "\xe6" => [0, "oi"], "\xe7" => [0, "oo"], "\xe8" => [0, "os"], "\xe9" => [0, "ot"], "\xea" => [73, "o"], "\xeb" => [88, "o"], "\xec" => [89, "o"], "\xed" => [96, "o"], "\xee" => [97, "o"], "\xef" => [99, "o"], "\xf0" => [106, "o"], "\xf1" => [136, "o"], "\xf2" => [139, "o"], "\xf3" => [141, "o"], "\xf4" => [145, "o"], "\xf5" => [147, "o"], "\xf6" => [149, "o"], "\xf7" => [101, "o"], "\xf8" => [112, "o"], "\xf9" => [117, "o"], "\xfa" => [120, "o"], "\xfb" => [124, "o"], "\xfc" => [127, "o"], "\xfd" => [144, "o"], "\xfe" => [152, "o"], "\xff" => [11, "o"]], ["\x00" => [94, "20"], "\x01" => [76, "20"], "\x02" => [104, "20"], "\x03" => [16, "20"], "\x04" => [94, "21"], "\x05" => [76, "21"], "\x06" => [104, "21"], "\x07" => [16, "21"], "\x08" => [94, "22"], "\t" => [76, "22"], "\n" => [104, "22"], "\v" => [16, "22"], "\f" => [94, "2a"], "\r" => [76, "2a"], "\x0e" => [104, "2a"], "\x0f" => [16, "2a"], "\x10" => [94, "2c"], "\x11" => [76, "2c"], "\x12" => [104, "2c"], "\x13" => [16, "2c"], "\x14" => [94, "2e"], "\x15" => [76, "2e"], "\x16" => [104, "2e"], "\x17" => [16, "2e"], "\x18" => [94, "2i"], "\x19" => [76, "2i"], "\x1a" => [104, "2i"], "\x1b" => [16, "2i"], "\x1c" => [94, "2o"], "\x1d" => [76, "2o"], "\x1e" => [104, "2o"], "\x1f" => [16, "2o"], " " => [94, "2s"], "!" => [76, "2s"], "\"" => [104, "2s"], "#" => [16, "2s"], "\$" => [94, "2t"], "%" => [76, "2t"], "&" => [104, "2t"], "'" => [16, "2t"], "(" => [77, "2 "], ")" => [18, "2 "], "*" => [77, "2%"], "+" => [18, "2%"], "," => [77, "2-"], "-" => [18, "2-"], "." => [77, "2."], "/" => [18, "2."], [77, "2/"], [18, "2/"], [77, "23"], [18, "23"], [77, "24"], [18, "24"], [77, "25"], [18, "25"], [77, "26"], [18, "26"], ":" => [77, "27"], ";" => [18, "27"], "<" => [77, "28"], "=" => [18, "28"], ">" => [77, "29"], "?" => [18, "29"], "@" => [77, "2="], "A" => [18, "2="], "B" => [77, "2A"], "C" => [18, "2A"], "D" => [77, "2_"], "E" => [18, "2_"], "F" => [77, "2b"], "G" => [18, "2b"], "H" => [77, "2d"], "I" => [18, "2d"], "J" => [77, "2f"], "K" => [18, "2f"], "L" => [77, "2g"], "M" => [18, "2g"], "N" => [77, "2h"], "O" => [18, "2h"], "P" => [77, "2l"], "Q" => [18, "2l"], "R" => [77, "2m"], "S" => [18, "2m"], "T" => [77, "2n"], "U" => [18, "2n"], "V" => [77, "2p"], "W" => [18, "2p"], "X" => [77, "2r"], "Y" => [18, "2r"], "Z" => [77, "2u"], "[" => [18, "2u"], "\\" => [0, "2:"], "]" => [0, "2B"], "^" => [0, "2C"], "_" => [0, "2D"], "`" => [0, "2E"], "a" => [0, "2F"], "b" => [0, "2G"], "c" => [0, "2H"], "d" => [0, "2I"], "e" => [0, "2J"], "f" => [0, "2K"], "g" => [0, "2L"], "h" => [0, "2M"], "i" => [0, "2N"], "j" => [0, "2O"], "k" => [0, "2P"], "l" => [0, "2Q"], "m" => [0, "2R"], "n" => [0, "2S"], "o" => [0, "2T"], "p" => [0, "2U"], "q" => [0, "2V"], "r" => [0, "2W"], "s" => [0, "2Y"], "t" => [0, "2j"], "u" => [0, "2k"], "v" => [0, "2q"], "w" => [0, "2v"], "x" => [0, "2w"], "y" => [0, "2x"], "z" => [0, "2y"], "{" => [0, "2z"], "|" => [82, "2"], "}" => [87, "2"], "~" => [130, "2"], "" => [9, "2"], "\x80" => [94, "a0"], "\x81" => [76, "a0"], "\x82" => [104, "a0"], "\x83" => [16, "a0"], "\x84" => [94, "a1"], "\x85" => [76, "a1"], "\x86" => [104, "a1"], "\x87" => [16, "a1"], "\x88" => [94, "a2"], "\x89" => [76, "a2"], "\x8a" => [104, "a2"], "\x8b" => [16, "a2"], "\x8c" => [94, "aa"], "\x8d" => [76, "aa"], "\x8e" => [104, "aa"], "\x8f" => [16, "aa"], "\x90" => [94, "ac"], "\x91" => [76, "ac"], "\x92" => [104, "ac"], "\x93" => [16, "ac"], "\x94" => [94, "ae"], "\x95" => [76, "ae"], "\x96" => [104, "ae"], "\x97" => [16, "ae"], "\x98" => [94, "ai"], "\x99" => [76, "ai"], "\x9a" => [104, "ai"], "\x9b" => [16, "ai"], "\x9c" => [94, "ao"], "\x9d" => [76, "ao"], "\x9e" => [104, "ao"], "\x9f" => [16, "ao"], "\xa0" => [94, "as"], "\xa1" => [76, "as"], "\xa2" => [104, "as"], "\xa3" => [16, "as"], "\xa4" => [94, "at"], "\xa5" => [76, "at"], "\xa6" => [104, "at"], "\xa7" => [16, "at"], "\xa8" => [77, "a "], "\xa9" => [18, "a "], "\xaa" => [77, "a%"], "\xab" => [18, "a%"], "\xac" => [77, "a-"], "\xad" => [18, "a-"], "\xae" => [77, "a."], "\xaf" => [18, "a."], "\xb0" => [77, "a/"], "\xb1" => [18, "a/"], "\xb2" => [77, "a3"], "\xb3" => [18, "a3"], "\xb4" => [77, "a4"], "\xb5" => [18, "a4"], "\xb6" => [77, "a5"], "\xb7" => [18, "a5"], "\xb8" => [77, "a6"], "\xb9" => [18, "a6"], "\xba" => [77, "a7"], "\xbb" => [18, "a7"], "\xbc" => [77, "a8"], "\xbd" => [18, "a8"], "\xbe" => [77, "a9"], "\xbf" => [18, "a9"], "\xc0" => [77, "a="], "\xc1" => [18, "a="], "\xc2" => [77, "aA"], "\xc3" => [18, "aA"], "\xc4" => [77, "a_"], "\xc5" => [18, "a_"], "\xc6" => [77, "ab"], "\xc7" => [18, "ab"], "\xc8" => [77, "ad"], "\xc9" => [18, "ad"], "\xca" => [77, "af"], "\xcb" => [18, "af"], "\xcc" => [77, "ag"], "\xcd" => [18, "ag"], "\xce" => [77, "ah"], "\xcf" => [18, "ah"], "\xd0" => [77, "al"], "\xd1" => [18, "al"], "\xd2" => [77, "am"], "\xd3" => [18, "am"], "\xd4" => [77, "an"], "\xd5" => [18, "an"], "\xd6" => [77, "ap"], "\xd7" => [18, "ap"], "\xd8" => [77, "ar"], "\xd9" => [18, "ar"], "\xda" => [77, "au"], "\xdb" => [18, "au"], "\xdc" => [0, "a:"], "\xdd" => [0, "aB"], "\xde" => [0, "aC"], "\xdf" => [0, "aD"], "\xe0" => [0, "aE"], "\xe1" => [0, "aF"], "\xe2" => [0, "aG"], "\xe3" => [0, "aH"], "\xe4" => [0, "aI"], "\xe5" => [0, "aJ"], "\xe6" => [0, "aK"], "\xe7" => [0, "aL"], "\xe8" => [0, "aM"], "\xe9" => [0, "aN"], "\xea" => [0, "aO"], "\xeb" => [0, "aP"], "\xec" => [0, "aQ"], "\xed" => [0, "aR"], "\xee" => [0, "aS"], "\xef" => [0, "aT"], "\xf0" => [0, "aU"], "\xf1" => [0, "aV"], "\xf2" => [0, "aW"], "\xf3" => [0, "aY"], "\xf4" => [0, "aj"], "\xf5" => [0, "ak"], "\xf6" => [0, "aq"], "\xf7" => [0, "av"], "\xf8" => [0, "aw"], "\xf9" => [0, "ax"], "\xfa" => [0, "ay"], "\xfb" => [0, "az"], "\xfc" => [82, "a"], "\xfd" => [87, "a"], "\xfe" => [130, "a"], "\xff" => [9, "a"]], ["\x00" => [94, "40"], "\x01" => [76, "40"], "\x02" => [104, "40"], "\x03" => [16, "40"], "\x04" => [94, "41"], "\x05" => [76, "41"], "\x06" => [104, "41"], "\x07" => [16, "41"], "\x08" => [94, "42"], "\t" => [76, "42"], "\n" => [104, "42"], "\v" => [16, "42"], "\f" => [94, "4a"], "\r" => [76, "4a"], "\x0e" => [104, "4a"], "\x0f" => [16, "4a"], "\x10" => [94, "4c"], "\x11" => [76, "4c"], "\x12" => [104, "4c"], "\x13" => [16, "4c"], "\x14" => [94, "4e"], "\x15" => [76, "4e"], "\x16" => [104, "4e"], "\x17" => [16, "4e"], "\x18" => [94, "4i"], "\x19" => [76, "4i"], "\x1a" => [104, "4i"], "\x1b" => [16, "4i"], "\x1c" => [94, "4o"], "\x1d" => [76, "4o"], "\x1e" => [104, "4o"], "\x1f" => [16, "4o"], " " => [94, "4s"], "!" => [76, "4s"], "\"" => [104, "4s"], "#" => [16, "4s"], "\$" => [94, "4t"], "%" => [76, "4t"], "&" => [104, "4t"], "'" => [16, "4t"], "(" => [77, "4 "], ")" => [18, "4 "], "*" => [77, "4%"], "+" => [18, "4%"], "," => [77, "4-"], "-" => [18, "4-"], "." => [77, "4."], "/" => [18, "4."], [77, "4/"], [18, "4/"], [77, "43"], [18, "43"], [77, "44"], [18, "44"], [77, "45"], [18, "45"], [77, "46"], [18, "46"], ":" => [77, "47"], ";" => [18, "47"], "<" => [77, "48"], "=" => [18, "48"], ">" => [77, "49"], "?" => [18, "49"], "@" => [77, "4="], "A" => [18, "4="], "B" => [77, "4A"], "C" => [18, "4A"], "D" => [77, "4_"], "E" => [18, "4_"], "F" => [77, "4b"], "G" => [18, "4b"], "H" => [77, "4d"], "I" => [18, "4d"], "J" => [77, "4f"], "K" => [18, "4f"], "L" => [77, "4g"], "M" => [18, "4g"], "N" => [77, "4h"], "O" => [18, "4h"], "P" => [77, "4l"], "Q" => [18, "4l"], "R" => [77, "4m"], "S" => [18, "4m"], "T" => [77, "4n"], "U" => [18, "4n"], "V" => [77, "4p"], "W" => [18, "4p"], "X" => [77, "4r"], "Y" => [18, "4r"], "Z" => [77, "4u"], "[" => [18, "4u"], "\\" => [0, "4:"], "]" => [0, "4B"], "^" => [0, "4C"], "_" => [0, "4D"], "`" => [0, "4E"], "a" => [0, "4F"], "b" => [0, "4G"], "c" => [0, "4H"], "d" => [0, "4I"], "e" => [0, "4J"], "f" => [0, "4K"], "g" => [0, "4L"], "h" => [0, "4M"], "i" => [0, "4N"], "j" => [0, "4O"], "k" => [0, "4P"], "l" => [0, "4Q"], "m" => [0, "4R"], "n" => [0, "4S"], "o" => [0, "4T"], "p" => [0, "4U"], "q" => [0, "4V"], "r" => [0, "4W"], "s" => [0, "4Y"], "t" => [0, "4j"], "u" => [0, "4k"], "v" => [0, "4q"], "w" => [0, "4v"], "x" => [0, "4w"], "y" => [0, "4x"], "z" => [0, "4y"], "{" => [0, "4z"], "|" => [82, "4"], "}" => [87, "4"], "~" => [130, "4"], "" => [9, "4"], "\x80" => [94, "50"], "\x81" => [76, "50"], "\x82" => [104, "50"], "\x83" => [16, "50"], "\x84" => [94, "51"], "\x85" => [76, "51"], "\x86" => [104, "51"], "\x87" => [16, "51"], "\x88" => [94, "52"], "\x89" => [76, "52"], "\x8a" => [104, "52"], "\x8b" => [16, "52"], "\x8c" => [94, "5a"], "\x8d" => [76, "5a"], "\x8e" => [104, "5a"], "\x8f" => [16, "5a"], "\x90" => [94, "5c"], "\x91" => [76, "5c"], "\x92" => [104, "5c"], "\x93" => [16, "5c"], "\x94" => [94, "5e"], "\x95" => [76, "5e"], "\x96" => [104, "5e"], "\x97" => [16, "5e"], "\x98" => [94, "5i"], "\x99" => [76, "5i"], "\x9a" => [104, "5i"], "\x9b" => [16, "5i"], "\x9c" => [94, "5o"], "\x9d" => [76, "5o"], "\x9e" => [104, "5o"], "\x9f" => [16, "5o"], "\xa0" => [94, "5s"], "\xa1" => [76, "5s"], "\xa2" => [104, "5s"], "\xa3" => [16, "5s"], "\xa4" => [94, "5t"], "\xa5" => [76, "5t"], "\xa6" => [104, "5t"], "\xa7" => [16, "5t"], "\xa8" => [77, "5 "], "\xa9" => [18, "5 "], "\xaa" => [77, "5%"], "\xab" => [18, "5%"], "\xac" => [77, "5-"], "\xad" => [18, "5-"], "\xae" => [77, "5."], "\xaf" => [18, "5."], "\xb0" => [77, "5/"], "\xb1" => [18, "5/"], "\xb2" => [77, "53"], "\xb3" => [18, "53"], "\xb4" => [77, "54"], "\xb5" => [18, "54"], "\xb6" => [77, "55"], "\xb7" => [18, "55"], "\xb8" => [77, "56"], "\xb9" => [18, "56"], "\xba" => [77, "57"], "\xbb" => [18, "57"], "\xbc" => [77, "58"], "\xbd" => [18, "58"], "\xbe" => [77, "59"], "\xbf" => [18, "59"], "\xc0" => [77, "5="], "\xc1" => [18, "5="], "\xc2" => [77, "5A"], "\xc3" => [18, "5A"], "\xc4" => [77, "5_"], "\xc5" => [18, "5_"], "\xc6" => [77, "5b"], "\xc7" => [18, "5b"], "\xc8" => [77, "5d"], "\xc9" => [18, "5d"], "\xca" => [77, "5f"], "\xcb" => [18, "5f"], "\xcc" => [77, "5g"], "\xcd" => [18, "5g"], "\xce" => [77, "5h"], "\xcf" => [18, "5h"], "\xd0" => [77, "5l"], "\xd1" => [18, "5l"], "\xd2" => [77, "5m"], "\xd3" => [18, "5m"], "\xd4" => [77, "5n"], "\xd5" => [18, "5n"], "\xd6" => [77, "5p"], "\xd7" => [18, "5p"], "\xd8" => [77, "5r"], "\xd9" => [18, "5r"], "\xda" => [77, "5u"], "\xdb" => [18, "5u"], "\xdc" => [0, "5:"], "\xdd" => [0, "5B"], "\xde" => [0, "5C"], "\xdf" => [0, "5D"], "\xe0" => [0, "5E"], "\xe1" => [0, "5F"], "\xe2" => [0, "5G"], "\xe3" => [0, "5H"], "\xe4" => [0, "5I"], "\xe5" => [0, "5J"], "\xe6" => [0, "5K"], "\xe7" => [0, "5L"], "\xe8" => [0, "5M"], "\xe9" => [0, "5N"], "\xea" => [0, "5O"], "\xeb" => [0, "5P"], "\xec" => [0, "5Q"], "\xed" => [0, "5R"], "\xee" => [0, "5S"], "\xef" => [0, "5T"], "\xf0" => [0, "5U"], "\xf1" => [0, "5V"], "\xf2" => [0, "5W"], "\xf3" => [0, "5Y"], "\xf4" => [0, "5j"], "\xf5" => [0, "5k"], "\xf6" => [0, "5q"], "\xf7" => [0, "5v"], "\xf8" => [0, "5w"], "\xf9" => [0, "5x"], "\xfa" => [0, "5y"], "\xfb" => [0, "5z"], "\xfc" => [82, "5"], "\xfd" => [87, "5"], "\xfe" => [130, "5"], "\xff" => [9, "5"]], ["\x00" => [94, "60"], "\x01" => [76, "60"], "\x02" => [104, "60"], "\x03" => [16, "60"], "\x04" => [94, "61"], "\x05" => [76, "61"], "\x06" => [104, "61"], "\x07" => [16, "61"], "\x08" => [94, "62"], "\t" => [76, "62"], "\n" => [104, "62"], "\v" => [16, "62"], "\f" => [94, "6a"], "\r" => [76, "6a"], "\x0e" => [104, "6a"], "\x0f" => [16, "6a"], "\x10" => [94, "6c"], "\x11" => [76, "6c"], "\x12" => [104, "6c"], "\x13" => [16, "6c"], "\x14" => [94, "6e"], "\x15" => [76, "6e"], "\x16" => [104, "6e"], "\x17" => [16, "6e"], "\x18" => [94, "6i"], "\x19" => [76, "6i"], "\x1a" => [104, "6i"], "\x1b" => [16, "6i"], "\x1c" => [94, "6o"], "\x1d" => [76, "6o"], "\x1e" => [104, "6o"], "\x1f" => [16, "6o"], " " => [94, "6s"], "!" => [76, "6s"], "\"" => [104, "6s"], "#" => [16, "6s"], "\$" => [94, "6t"], "%" => [76, "6t"], "&" => [104, "6t"], "'" => [16, "6t"], "(" => [77, "6 "], ")" => [18, "6 "], "*" => [77, "6%"], "+" => [18, "6%"], "," => [77, "6-"], "-" => [18, "6-"], "." => [77, "6."], "/" => [18, "6."], [77, "6/"], [18, "6/"], [77, "63"], [18, "63"], [77, "64"], [18, "64"], [77, "65"], [18, "65"], [77, "66"], [18, "66"], ":" => [77, "67"], ";" => [18, "67"], "<" => [77, "68"], "=" => [18, "68"], ">" => [77, "69"], "?" => [18, "69"], "@" => [77, "6="], "A" => [18, "6="], "B" => [77, "6A"], "C" => [18, "6A"], "D" => [77, "6_"], "E" => [18, "6_"], "F" => [77, "6b"], "G" => [18, "6b"], "H" => [77, "6d"], "I" => [18, "6d"], "J" => [77, "6f"], "K" => [18, "6f"], "L" => [77, "6g"], "M" => [18, "6g"], "N" => [77, "6h"], "O" => [18, "6h"], "P" => [77, "6l"], "Q" => [18, "6l"], "R" => [77, "6m"], "S" => [18, "6m"], "T" => [77, "6n"], "U" => [18, "6n"], "V" => [77, "6p"], "W" => [18, "6p"], "X" => [77, "6r"], "Y" => [18, "6r"], "Z" => [77, "6u"], "[" => [18, "6u"], "\\" => [0, "6:"], "]" => [0, "6B"], "^" => [0, "6C"], "_" => [0, "6D"], "`" => [0, "6E"], "a" => [0, "6F"], "b" => [0, "6G"], "c" => [0, "6H"], "d" => [0, "6I"], "e" => [0, "6J"], "f" => [0, "6K"], "g" => [0, "6L"], "h" => [0, "6M"], "i" => [0, "6N"], "j" => [0, "6O"], "k" => [0, "6P"], "l" => [0, "6Q"], "m" => [0, "6R"], "n" => [0, "6S"], "o" => [0, "6T"], "p" => [0, "6U"], "q" => [0, "6V"], "r" => [0, "6W"], "s" => [0, "6Y"], "t" => [0, "6j"], "u" => [0, "6k"], "v" => [0, "6q"], "w" => [0, "6v"], "x" => [0, "6w"], "y" => [0, "6x"], "z" => [0, "6y"], "{" => [0, "6z"], "|" => [82, "6"], "}" => [87, "6"], "~" => [130, "6"], "" => [9, "6"], "\x80" => [94, "70"], "\x81" => [76, "70"], "\x82" => [104, "70"], "\x83" => [16, "70"], "\x84" => [94, "71"], "\x85" => [76, "71"], "\x86" => [104, "71"], "\x87" => [16, "71"], "\x88" => [94, "72"], "\x89" => [76, "72"], "\x8a" => [104, "72"], "\x8b" => [16, "72"], "\x8c" => [94, "7a"], "\x8d" => [76, "7a"], "\x8e" => [104, "7a"], "\x8f" => [16, "7a"], "\x90" => [94, "7c"], "\x91" => [76, "7c"], "\x92" => [104, "7c"], "\x93" => [16, "7c"], "\x94" => [94, "7e"], "\x95" => [76, "7e"], "\x96" => [104, "7e"], "\x97" => [16, "7e"], "\x98" => [94, "7i"], "\x99" => [76, "7i"], "\x9a" => [104, "7i"], "\x9b" => [16, "7i"], "\x9c" => [94, "7o"], "\x9d" => [76, "7o"], "\x9e" => [104, "7o"], "\x9f" => [16, "7o"], "\xa0" => [94, "7s"], "\xa1" => [76, "7s"], "\xa2" => [104, "7s"], "\xa3" => [16, "7s"], "\xa4" => [94, "7t"], "\xa5" => [76, "7t"], "\xa6" => [104, "7t"], "\xa7" => [16, "7t"], "\xa8" => [77, "7 "], "\xa9" => [18, "7 "], "\xaa" => [77, "7%"], "\xab" => [18, "7%"], "\xac" => [77, "7-"], "\xad" => [18, "7-"], "\xae" => [77, "7."], "\xaf" => [18, "7."], "\xb0" => [77, "7/"], "\xb1" => [18, "7/"], "\xb2" => [77, "73"], "\xb3" => [18, "73"], "\xb4" => [77, "74"], "\xb5" => [18, "74"], "\xb6" => [77, "75"], "\xb7" => [18, "75"], "\xb8" => [77, "76"], "\xb9" => [18, "76"], "\xba" => [77, "77"], "\xbb" => [18, "77"], "\xbc" => [77, "78"], "\xbd" => [18, "78"], "\xbe" => [77, "79"], "\xbf" => [18, "79"], "\xc0" => [77, "7="], "\xc1" => [18, "7="], "\xc2" => [77, "7A"], "\xc3" => [18, "7A"], "\xc4" => [77, "7_"], "\xc5" => [18, "7_"], "\xc6" => [77, "7b"], "\xc7" => [18, "7b"], "\xc8" => [77, "7d"], "\xc9" => [18, "7d"], "\xca" => [77, "7f"], "\xcb" => [18, "7f"], "\xcc" => [77, "7g"], "\xcd" => [18, "7g"], "\xce" => [77, "7h"], "\xcf" => [18, "7h"], "\xd0" => [77, "7l"], "\xd1" => [18, "7l"], "\xd2" => [77, "7m"], "\xd3" => [18, "7m"], "\xd4" => [77, "7n"], "\xd5" => [18, "7n"], "\xd6" => [77, "7p"], "\xd7" => [18, "7p"], "\xd8" => [77, "7r"], "\xd9" => [18, "7r"], "\xda" => [77, "7u"], "\xdb" => [18, "7u"], "\xdc" => [0, "7:"], "\xdd" => [0, "7B"], "\xde" => [0, "7C"], "\xdf" => [0, "7D"], "\xe0" => [0, "7E"], "\xe1" => [0, "7F"], "\xe2" => [0, "7G"], "\xe3" => [0, "7H"], "\xe4" => [0, "7I"], "\xe5" => [0, "7J"], "\xe6" => [0, "7K"], "\xe7" => [0, "7L"], "\xe8" => [0, "7M"], "\xe9" => [0, "7N"], "\xea" => [0, "7O"], "\xeb" => [0, "7P"], "\xec" => [0, "7Q"], "\xed" => [0, "7R"], "\xee" => [0, "7S"], "\xef" => [0, "7T"], "\xf0" => [0, "7U"], "\xf1" => [0, "7V"], "\xf2" => [0, "7W"], "\xf3" => [0, "7Y"], "\xf4" => [0, "7j"], "\xf5" => [0, "7k"], "\xf6" => [0, "7q"], "\xf7" => [0, "7v"], "\xf8" => [0, "7w"], "\xf9" => [0, "7x"], "\xfa" => [0, "7y"], "\xfb" => [0, "7z"], "\xfc" => [82, "7"], "\xfd" => [87, "7"], "\xfe" => [130, "7"], "\xff" => [9, "7"]], ["\x00" => [77, "60"], "\x01" => [18, "60"], "\x02" => [77, "61"], "\x03" => [18, "61"], "\x04" => [77, "62"], "\x05" => [18, "62"], "\x06" => [77, "6a"], "\x07" => [18, "6a"], "\x08" => [77, "6c"], "\t" => [18, "6c"], "\n" => [77, "6e"], "\v" => [18, "6e"], "\f" => [77, "6i"], "\r" => [18, "6i"], "\x0e" => [77, "6o"], "\x0f" => [18, "6o"], "\x10" => [77, "6s"], "\x11" => [18, "6s"], "\x12" => [77, "6t"], "\x13" => [18, "6t"], "\x14" => [0, "6 "], "\x15" => [0, "6%"], "\x16" => [0, "6-"], "\x17" => [0, "6."], "\x18" => [0, "6/"], "\x19" => [0, "63"], "\x1a" => [0, "64"], "\x1b" => [0, "65"], "\x1c" => [0, "66"], "\x1d" => [0, "67"], "\x1e" => [0, "68"], "\x1f" => [0, "69"], " " => [0, "6="], "!" => [0, "6A"], "\"" => [0, "6_"], "#" => [0, "6b"], "\$" => [0, "6d"], "%" => [0, "6f"], "&" => [0, "6g"], "'" => [0, "6h"], "(" => [0, "6l"], ")" => [0, "6m"], "*" => [0, "6n"], "+" => [0, "6p"], "," => [0, "6r"], "-" => [0, "6u"], "." => [100, "6"], "/" => [110, "6"], [111, "6"], [115, "6"], [116, "6"], [118, "6"], [119, "6"], [122, "6"], [123, "6"], [125, "6"], [126, "6"], [129, "6"], ":" => [143, "6"], ";" => [148, "6"], "<" => [151, "6"], "=" => [153, "6"], ">" => [83, "6"], "?" => [10, "6"], "@" => [77, "70"], "A" => [18, "70"], "B" => [77, "71"], "C" => [18, "71"], "D" => [77, "72"], "E" => [18, "72"], "F" => [77, "7a"], "G" => [18, "7a"], "H" => [77, "7c"], "I" => [18, "7c"], "J" => [77, "7e"], "K" => [18, "7e"], "L" => [77, "7i"], "M" => [18, "7i"], "N" => [77, "7o"], "O" => [18, "7o"], "P" => [77, "7s"], "Q" => [18, "7s"], "R" => [77, "7t"], "S" => [18, "7t"], "T" => [0, "7 "], "U" => [0, "7%"], "V" => [0, "7-"], "W" => [0, "7."], "X" => [0, "7/"], "Y" => [0, "73"], "Z" => [0, "74"], "[" => [0, "75"], "\\" => [0, "76"], "]" => [0, "77"], "^" => [0, "78"], "_" => [0, "79"], "`" => [0, "7="], "a" => [0, "7A"], "b" => [0, "7_"], "c" => [0, "7b"], "d" => [0, "7d"], "e" => [0, "7f"], "f" => [0, "7g"], "g" => [0, "7h"], "h" => [0, "7l"], "i" => [0, "7m"], "j" => [0, "7n"], "k" => [0, "7p"], "l" => [0, "7r"], "m" => [0, "7u"], "n" => [100, "7"], "o" => [110, "7"], "p" => [111, "7"], "q" => [115, "7"], "r" => [116, "7"], "s" => [118, "7"], "t" => [119, "7"], "u" => [122, "7"], "v" => [123, "7"], "w" => [125, "7"], "x" => [126, "7"], "y" => [129, "7"], "z" => [143, "7"], "{" => [148, "7"], "|" => [151, "7"], "}" => [153, "7"], "~" => [83, "7"], "" => [10, "7"], "\x80" => [77, "80"], "\x81" => [18, "80"], "\x82" => [77, "81"], "\x83" => [18, "81"], "\x84" => [77, "82"], "\x85" => [18, "82"], "\x86" => [77, "8a"], "\x87" => [18, "8a"], "\x88" => [77, "8c"], "\x89" => [18, "8c"], "\x8a" => [77, "8e"], "\x8b" => [18, "8e"], "\x8c" => [77, "8i"], "\x8d" => [18, "8i"], "\x8e" => [77, "8o"], "\x8f" => [18, "8o"], "\x90" => [77, "8s"], "\x91" => [18, "8s"], "\x92" => [77, "8t"], "\x93" => [18, "8t"], "\x94" => [0, "8 "], "\x95" => [0, "8%"], "\x96" => [0, "8-"], "\x97" => [0, "8."], "\x98" => [0, "8/"], "\x99" => [0, "83"], "\x9a" => [0, "84"], "\x9b" => [0, "85"], "\x9c" => [0, "86"], "\x9d" => [0, "87"], "\x9e" => [0, "88"], "\x9f" => [0, "89"], "\xa0" => [0, "8="], "\xa1" => [0, "8A"], "\xa2" => [0, "8_"], "\xa3" => [0, "8b"], "\xa4" => [0, "8d"], "\xa5" => [0, "8f"], "\xa6" => [0, "8g"], "\xa7" => [0, "8h"], "\xa8" => [0, "8l"], "\xa9" => [0, "8m"], "\xaa" => [0, "8n"], "\xab" => [0, "8p"], "\xac" => [0, "8r"], "\xad" => [0, "8u"], "\xae" => [100, "8"], "\xaf" => [110, "8"], "\xb0" => [111, "8"], "\xb1" => [115, "8"], "\xb2" => [116, "8"], "\xb3" => [118, "8"], "\xb4" => [119, "8"], "\xb5" => [122, "8"], "\xb6" => [123, "8"], "\xb7" => [125, "8"], "\xb8" => [126, "8"], "\xb9" => [129, "8"], "\xba" => [143, "8"], "\xbb" => [148, "8"], "\xbc" => [151, "8"], "\xbd" => [153, "8"], "\xbe" => [83, "8"], "\xbf" => [10, "8"], "\xc0" => [77, "90"], "\xc1" => [18, "90"], "\xc2" => [77, "91"], "\xc3" => [18, "91"], "\xc4" => [77, "92"], "\xc5" => [18, "92"], "\xc6" => [77, "9a"], "\xc7" => [18, "9a"], "\xc8" => [77, "9c"], "\xc9" => [18, "9c"], "\xca" => [77, "9e"], "\xcb" => [18, "9e"], "\xcc" => [77, "9i"], "\xcd" => [18, "9i"], "\xce" => [77, "9o"], "\xcf" => [18, "9o"], "\xd0" => [77, "9s"], "\xd1" => [18, "9s"], "\xd2" => [77, "9t"], "\xd3" => [18, "9t"], "\xd4" => [0, "9 "], "\xd5" => [0, "9%"], "\xd6" => [0, "9-"], "\xd7" => [0, "9."], "\xd8" => [0, "9/"], "\xd9" => [0, "93"], "\xda" => [0, "94"], "\xdb" => [0, "95"], "\xdc" => [0, "96"], "\xdd" => [0, "97"], "\xde" => [0, "98"], "\xdf" => [0, "99"], "\xe0" => [0, "9="], "\xe1" => [0, "9A"], "\xe2" => [0, "9_"], "\xe3" => [0, "9b"], "\xe4" => [0, "9d"], "\xe5" => [0, "9f"], "\xe6" => [0, "9g"], "\xe7" => [0, "9h"], "\xe8" => [0, "9l"], "\xe9" => [0, "9m"], "\xea" => [0, "9n"], "\xeb" => [0, "9p"], "\xec" => [0, "9r"], "\xed" => [0, "9u"], "\xee" => [100, "9"], "\xef" => [110, "9"], "\xf0" => [111, "9"], "\xf1" => [115, "9"], "\xf2" => [116, "9"], "\xf3" => [118, "9"], "\xf4" => [119, "9"], "\xf5" => [122, "9"], "\xf6" => [123, "9"], "\xf7" => [125, "9"], "\xf8" => [126, "9"], "\xf9" => [129, "9"], "\xfa" => [143, "9"], "\xfb" => [148, "9"], "\xfc" => [151, "9"], "\xfd" => [153, "9"], "\xfe" => [83, "9"], "\xff" => [10, "9"]], ["\x00" => [94, "80"], "\x01" => [76, "80"], "\x02" => [104, "80"], "\x03" => [16, "80"], "\x04" => [94, "81"], "\x05" => [76, "81"], "\x06" => [104, "81"], "\x07" => [16, "81"], "\x08" => [94, "82"], "\t" => [76, "82"], "\n" => [104, "82"], "\v" => [16, "82"], "\f" => [94, "8a"], "\r" => [76, "8a"], "\x0e" => [104, "8a"], "\x0f" => [16, "8a"], "\x10" => [94, "8c"], "\x11" => [76, "8c"], "\x12" => [104, "8c"], "\x13" => [16, "8c"], "\x14" => [94, "8e"], "\x15" => [76, "8e"], "\x16" => [104, "8e"], "\x17" => [16, "8e"], "\x18" => [94, "8i"], "\x19" => [76, "8i"], "\x1a" => [104, "8i"], "\x1b" => [16, "8i"], "\x1c" => [94, "8o"], "\x1d" => [76, "8o"], "\x1e" => [104, "8o"], "\x1f" => [16, "8o"], " " => [94, "8s"], "!" => [76, "8s"], "\"" => [104, "8s"], "#" => [16, "8s"], "\$" => [94, "8t"], "%" => [76, "8t"], "&" => [104, "8t"], "'" => [16, "8t"], "(" => [77, "8 "], ")" => [18, "8 "], "*" => [77, "8%"], "+" => [18, "8%"], "," => [77, "8-"], "-" => [18, "8-"], "." => [77, "8."], "/" => [18, "8."], [77, "8/"], [18, "8/"], [77, "83"], [18, "83"], [77, "84"], [18, "84"], [77, "85"], [18, "85"], [77, "86"], [18, "86"], ":" => [77, "87"], ";" => [18, "87"], "<" => [77, "88"], "=" => [18, "88"], ">" => [77, "89"], "?" => [18, "89"], "@" => [77, "8="], "A" => [18, "8="], "B" => [77, "8A"], "C" => [18, "8A"], "D" => [77, "8_"], "E" => [18, "8_"], "F" => [77, "8b"], "G" => [18, "8b"], "H" => [77, "8d"], "I" => [18, "8d"], "J" => [77, "8f"], "K" => [18, "8f"], "L" => [77, "8g"], "M" => [18, "8g"], "N" => [77, "8h"], "O" => [18, "8h"], "P" => [77, "8l"], "Q" => [18, "8l"], "R" => [77, "8m"], "S" => [18, "8m"], "T" => [77, "8n"], "U" => [18, "8n"], "V" => [77, "8p"], "W" => [18, "8p"], "X" => [77, "8r"], "Y" => [18, "8r"], "Z" => [77, "8u"], "[" => [18, "8u"], "\\" => [0, "8:"], "]" => [0, "8B"], "^" => [0, "8C"], "_" => [0, "8D"], "`" => [0, "8E"], "a" => [0, "8F"], "b" => [0, "8G"], "c" => [0, "8H"], "d" => [0, "8I"], "e" => [0, "8J"], "f" => [0, "8K"], "g" => [0, "8L"], "h" => [0, "8M"], "i" => [0, "8N"], "j" => [0, "8O"], "k" => [0, "8P"], "l" => [0, "8Q"], "m" => [0, "8R"], "n" => [0, "8S"], "o" => [0, "8T"], "p" => [0, "8U"], "q" => [0, "8V"], "r" => [0, "8W"], "s" => [0, "8Y"], "t" => [0, "8j"], "u" => [0, "8k"], "v" => [0, "8q"], "w" => [0, "8v"], "x" => [0, "8w"], "y" => [0, "8x"], "z" => [0, "8y"], "{" => [0, "8z"], "|" => [82, "8"], "}" => [87, "8"], "~" => [130, "8"], "" => [9, "8"], "\x80" => [94, "90"], "\x81" => [76, "90"], "\x82" => [104, "90"], "\x83" => [16, "90"], "\x84" => [94, "91"], "\x85" => [76, "91"], "\x86" => [104, "91"], "\x87" => [16, "91"], "\x88" => [94, "92"], "\x89" => [76, "92"], "\x8a" => [104, "92"], "\x8b" => [16, "92"], "\x8c" => [94, "9a"], "\x8d" => [76, "9a"], "\x8e" => [104, "9a"], "\x8f" => [16, "9a"], "\x90" => [94, "9c"], "\x91" => [76, "9c"], "\x92" => [104, "9c"], "\x93" => [16, "9c"], "\x94" => [94, "9e"], "\x95" => [76, "9e"], "\x96" => [104, "9e"], "\x97" => [16, "9e"], "\x98" => [94, "9i"], "\x99" => [76, "9i"], "\x9a" => [104, "9i"], "\x9b" => [16, "9i"], "\x9c" => [94, "9o"], "\x9d" => [76, "9o"], "\x9e" => [104, "9o"], "\x9f" => [16, "9o"], "\xa0" => [94, "9s"], "\xa1" => [76, "9s"], "\xa2" => [104, "9s"], "\xa3" => [16, "9s"], "\xa4" => [94, "9t"], "\xa5" => [76, "9t"], "\xa6" => [104, "9t"], "\xa7" => [16, "9t"], "\xa8" => [77, "9 "], "\xa9" => [18, "9 "], "\xaa" => [77, "9%"], "\xab" => [18, "9%"], "\xac" => [77, "9-"], "\xad" => [18, "9-"], "\xae" => [77, "9."], "\xaf" => [18, "9."], "\xb0" => [77, "9/"], "\xb1" => [18, "9/"], "\xb2" => [77, "93"], "\xb3" => [18, "93"], "\xb4" => [77, "94"], "\xb5" => [18, "94"], "\xb6" => [77, "95"], "\xb7" => [18, "95"], "\xb8" => [77, "96"], "\xb9" => [18, "96"], "\xba" => [77, "97"], "\xbb" => [18, "97"], "\xbc" => [77, "98"], "\xbd" => [18, "98"], "\xbe" => [77, "99"], "\xbf" => [18, "99"], "\xc0" => [77, "9="], "\xc1" => [18, "9="], "\xc2" => [77, "9A"], "\xc3" => [18, "9A"], "\xc4" => [77, "9_"], "\xc5" => [18, "9_"], "\xc6" => [77, "9b"], "\xc7" => [18, "9b"], "\xc8" => [77, "9d"], "\xc9" => [18, "9d"], "\xca" => [77, "9f"], "\xcb" => [18, "9f"], "\xcc" => [77, "9g"], "\xcd" => [18, "9g"], "\xce" => [77, "9h"], "\xcf" => [18, "9h"], "\xd0" => [77, "9l"], "\xd1" => [18, "9l"], "\xd2" => [77, "9m"], "\xd3" => [18, "9m"], "\xd4" => [77, "9n"], "\xd5" => [18, "9n"], "\xd6" => [77, "9p"], "\xd7" => [18, "9p"], "\xd8" => [77, "9r"], "\xd9" => [18, "9r"], "\xda" => [77, "9u"], "\xdb" => [18, "9u"], "\xdc" => [0, "9:"], "\xdd" => [0, "9B"], "\xde" => [0, "9C"], "\xdf" => [0, "9D"], "\xe0" => [0, "9E"], "\xe1" => [0, "9F"], "\xe2" => [0, "9G"], "\xe3" => [0, "9H"], "\xe4" => [0, "9I"], "\xe5" => [0, "9J"], "\xe6" => [0, "9K"], "\xe7" => [0, "9L"], "\xe8" => [0, "9M"], "\xe9" => [0, "9N"], "\xea" => [0, "9O"], "\xeb" => [0, "9P"], "\xec" => [0, "9Q"], "\xed" => [0, "9R"], "\xee" => [0, "9S"], "\xef" => [0, "9T"], "\xf0" => [0, "9U"], "\xf1" => [0, "9V"], "\xf2" => [0, "9W"], "\xf3" => [0, "9Y"], "\xf4" => [0, "9j"], "\xf5" => [0, "9k"], "\xf6" => [0, "9q"], "\xf7" => [0, "9v"], "\xf8" => [0, "9w"], "\xf9" => [0, "9x"], "\xfa" => [0, "9y"], "\xfb" => [0, "9z"], "\xfc" => [82, "9"], "\xfd" => [87, "9"], "\xfe" => [130, "9"], "\xff" => [9, "9"]], ["\x00" => [94, ":0"], "\x01" => [76, ":0"], "\x02" => [104, ":0"], "\x03" => [16, ":0"], "\x04" => [94, ":1"], "\x05" => [76, ":1"], "\x06" => [104, ":1"], "\x07" => [16, ":1"], "\x08" => [94, ":2"], "\t" => [76, ":2"], "\n" => [104, ":2"], "\v" => [16, ":2"], "\f" => [94, ":a"], "\r" => [76, ":a"], "\x0e" => [104, ":a"], "\x0f" => [16, ":a"], "\x10" => [94, ":c"], "\x11" => [76, ":c"], "\x12" => [104, ":c"], "\x13" => [16, ":c"], "\x14" => [94, ":e"], "\x15" => [76, ":e"], "\x16" => [104, ":e"], "\x17" => [16, ":e"], "\x18" => [94, ":i"], "\x19" => [76, ":i"], "\x1a" => [104, ":i"], "\x1b" => [16, ":i"], "\x1c" => [94, ":o"], "\x1d" => [76, ":o"], "\x1e" => [104, ":o"], "\x1f" => [16, ":o"], " " => [94, ":s"], "!" => [76, ":s"], "\"" => [104, ":s"], "#" => [16, ":s"], "\$" => [94, ":t"], "%" => [76, ":t"], "&" => [104, ":t"], "'" => [16, ":t"], "(" => [77, ": "], ")" => [18, ": "], "*" => [77, ":%"], "+" => [18, ":%"], "," => [77, ":-"], "-" => [18, ":-"], "." => [77, ":."], "/" => [18, ":."], [77, ":/"], [18, ":/"], [77, ":3"], [18, ":3"], [77, ":4"], [18, ":4"], [77, ":5"], [18, ":5"], [77, ":6"], [18, ":6"], ":" => [77, ":7"], ";" => [18, ":7"], "<" => [77, ":8"], "=" => [18, ":8"], ">" => [77, ":9"], "?" => [18, ":9"], "@" => [77, ":="], "A" => [18, ":="], "B" => [77, ":A"], "C" => [18, ":A"], "D" => [77, ":_"], "E" => [18, ":_"], "F" => [77, ":b"], "G" => [18, ":b"], "H" => [77, ":d"], "I" => [18, ":d"], "J" => [77, ":f"], "K" => [18, ":f"], "L" => [77, ":g"], "M" => [18, ":g"], "N" => [77, ":h"], "O" => [18, ":h"], "P" => [77, ":l"], "Q" => [18, ":l"], "R" => [77, ":m"], "S" => [18, ":m"], "T" => [77, ":n"], "U" => [18, ":n"], "V" => [77, ":p"], "W" => [18, ":p"], "X" => [77, ":r"], "Y" => [18, ":r"], "Z" => [77, ":u"], "[" => [18, ":u"], "\\" => [0, "::"], "]" => [0, ":B"], "^" => [0, ":C"], "_" => [0, ":D"], "`" => [0, ":E"], "a" => [0, ":F"], "b" => [0, ":G"], "c" => [0, ":H"], "d" => [0, ":I"], "e" => [0, ":J"], "f" => [0, ":K"], "g" => [0, ":L"], "h" => [0, ":M"], "i" => [0, ":N"], "j" => [0, ":O"], "k" => [0, ":P"], "l" => [0, ":Q"], "m" => [0, ":R"], "n" => [0, ":S"], "o" => [0, ":T"], "p" => [0, ":U"], "q" => [0, ":V"], "r" => [0, ":W"], "s" => [0, ":Y"], "t" => [0, ":j"], "u" => [0, ":k"], "v" => [0, ":q"], "w" => [0, ":v"], "x" => [0, ":w"], "y" => [0, ":x"], "z" => [0, ":y"], "{" => [0, ":z"], "|" => [82, ":"], "}" => [87, ":"], "~" => [130, ":"], "" => [9, ":"], "\x80" => [94, "B0"], "\x81" => [76, "B0"], "\x82" => [104, "B0"], "\x83" => [16, "B0"], "\x84" => [94, "B1"], "\x85" => [76, "B1"], "\x86" => [104, "B1"], "\x87" => [16, "B1"], "\x88" => [94, "B2"], "\x89" => [76, "B2"], "\x8a" => [104, "B2"], "\x8b" => [16, "B2"], "\x8c" => [94, "Ba"], "\x8d" => [76, "Ba"], "\x8e" => [104, "Ba"], "\x8f" => [16, "Ba"], "\x90" => [94, "Bc"], "\x91" => [76, "Bc"], "\x92" => [104, "Bc"], "\x93" => [16, "Bc"], "\x94" => [94, "Be"], "\x95" => [76, "Be"], "\x96" => [104, "Be"], "\x97" => [16, "Be"], "\x98" => [94, "Bi"], "\x99" => [76, "Bi"], "\x9a" => [104, "Bi"], "\x9b" => [16, "Bi"], "\x9c" => [94, "Bo"], "\x9d" => [76, "Bo"], "\x9e" => [104, "Bo"], "\x9f" => [16, "Bo"], "\xa0" => [94, "Bs"], "\xa1" => [76, "Bs"], "\xa2" => [104, "Bs"], "\xa3" => [16, "Bs"], "\xa4" => [94, "Bt"], "\xa5" => [76, "Bt"], "\xa6" => [104, "Bt"], "\xa7" => [16, "Bt"], "\xa8" => [77, "B "], "\xa9" => [18, "B "], "\xaa" => [77, "B%"], "\xab" => [18, "B%"], "\xac" => [77, "B-"], "\xad" => [18, "B-"], "\xae" => [77, "B."], "\xaf" => [18, "B."], "\xb0" => [77, "B/"], "\xb1" => [18, "B/"], "\xb2" => [77, "B3"], "\xb3" => [18, "B3"], "\xb4" => [77, "B4"], "\xb5" => [18, "B4"], "\xb6" => [77, "B5"], "\xb7" => [18, "B5"], "\xb8" => [77, "B6"], "\xb9" => [18, "B6"], "\xba" => [77, "B7"], "\xbb" => [18, "B7"], "\xbc" => [77, "B8"], "\xbd" => [18, "B8"], "\xbe" => [77, "B9"], "\xbf" => [18, "B9"], "\xc0" => [77, "B="], "\xc1" => [18, "B="], "\xc2" => [77, "BA"], "\xc3" => [18, "BA"], "\xc4" => [77, "B_"], "\xc5" => [18, "B_"], "\xc6" => [77, "Bb"], "\xc7" => [18, "Bb"], "\xc8" => [77, "Bd"], "\xc9" => [18, "Bd"], "\xca" => [77, "Bf"], "\xcb" => [18, "Bf"], "\xcc" => [77, "Bg"], "\xcd" => [18, "Bg"], "\xce" => [77, "Bh"], "\xcf" => [18, "Bh"], "\xd0" => [77, "Bl"], "\xd1" => [18, "Bl"], "\xd2" => [77, "Bm"], "\xd3" => [18, "Bm"], "\xd4" => [77, "Bn"], "\xd5" => [18, "Bn"], "\xd6" => [77, "Bp"], "\xd7" => [18, "Bp"], "\xd8" => [77, "Br"], "\xd9" => [18, "Br"], "\xda" => [77, "Bu"], "\xdb" => [18, "Bu"], "\xdc" => [0, "B:"], "\xdd" => [0, "BB"], "\xde" => [0, "BC"], "\xdf" => [0, "BD"], "\xe0" => [0, "BE"], "\xe1" => [0, "BF"], "\xe2" => [0, "BG"], "\xe3" => [0, "BH"], "\xe4" => [0, "BI"], "\xe5" => [0, "BJ"], "\xe6" => [0, "BK"], "\xe7" => [0, "BL"], "\xe8" => [0, "BM"], "\xe9" => [0, "BN"], "\xea" => [0, "BO"], "\xeb" => [0, "BP"], "\xec" => [0, "BQ"], "\xed" => [0, "BR"], "\xee" => [0, "BS"], "\xef" => [0, "BT"], "\xf0" => [0, "BU"], "\xf1" => [0, "BV"], "\xf2" => [0, "BW"], "\xf3" => [0, "BY"], "\xf4" => [0, "Bj"], "\xf5" => [0, "Bk"], "\xf6" => [0, "Bq"], "\xf7" => [0, "Bv"], "\xf8" => [0, "Bw"], "\xf9" => [0, "Bx"], "\xfa" => [0, "By"], "\xfb" => [0, "Bz"], "\xfc" => [82, "B"], "\xfd" => [87, "B"], "\xfe" => [130, "B"], "\xff" => [9, "B"]], ["\x00" => [77, ":0"], "\x01" => [18, ":0"], "\x02" => [77, ":1"], "\x03" => [18, ":1"], "\x04" => [77, ":2"], "\x05" => [18, ":2"], "\x06" => [77, ":a"], "\x07" => [18, ":a"], "\x08" => [77, ":c"], "\t" => [18, ":c"], "\n" => [77, ":e"], "\v" => [18, ":e"], "\f" => [77, ":i"], "\r" => [18, ":i"], "\x0e" => [77, ":o"], "\x0f" => [18, ":o"], "\x10" => [77, ":s"], "\x11" => [18, ":s"], "\x12" => [77, ":t"], "\x13" => [18, ":t"], "\x14" => [0, ": "], "\x15" => [0, ":%"], "\x16" => [0, ":-"], "\x17" => [0, ":."], "\x18" => [0, ":/"], "\x19" => [0, ":3"], "\x1a" => [0, ":4"], "\x1b" => [0, ":5"], "\x1c" => [0, ":6"], "\x1d" => [0, ":7"], "\x1e" => [0, ":8"], "\x1f" => [0, ":9"], " " => [0, ":="], "!" => [0, ":A"], "\"" => [0, ":_"], "#" => [0, ":b"], "\$" => [0, ":d"], "%" => [0, ":f"], "&" => [0, ":g"], "'" => [0, ":h"], "(" => [0, ":l"], ")" => [0, ":m"], "*" => [0, ":n"], "+" => [0, ":p"], "," => [0, ":r"], "-" => [0, ":u"], "." => [100, ":"], "/" => [110, ":"], [111, ":"], [115, ":"], [116, ":"], [118, ":"], [119, ":"], [122, ":"], [123, ":"], [125, ":"], [126, ":"], [129, ":"], ":" => [143, ":"], ";" => [148, ":"], "<" => [151, ":"], "=" => [153, ":"], ">" => [83, ":"], "?" => [10, ":"], "@" => [77, "B0"], "A" => [18, "B0"], "B" => [77, "B1"], "C" => [18, "B1"], "D" => [77, "B2"], "E" => [18, "B2"], "F" => [77, "Ba"], "G" => [18, "Ba"], "H" => [77, "Bc"], "I" => [18, "Bc"], "J" => [77, "Be"], "K" => [18, "Be"], "L" => [77, "Bi"], "M" => [18, "Bi"], "N" => [77, "Bo"], "O" => [18, "Bo"], "P" => [77, "Bs"], "Q" => [18, "Bs"], "R" => [77, "Bt"], "S" => [18, "Bt"], "T" => [0, "B "], "U" => [0, "B%"], "V" => [0, "B-"], "W" => [0, "B."], "X" => [0, "B/"], "Y" => [0, "B3"], "Z" => [0, "B4"], "[" => [0, "B5"], "\\" => [0, "B6"], "]" => [0, "B7"], "^" => [0, "B8"], "_" => [0, "B9"], "`" => [0, "B="], "a" => [0, "BA"], "b" => [0, "B_"], "c" => [0, "Bb"], "d" => [0, "Bd"], "e" => [0, "Bf"], "f" => [0, "Bg"], "g" => [0, "Bh"], "h" => [0, "Bl"], "i" => [0, "Bm"], "j" => [0, "Bn"], "k" => [0, "Bp"], "l" => [0, "Br"], "m" => [0, "Bu"], "n" => [100, "B"], "o" => [110, "B"], "p" => [111, "B"], "q" => [115, "B"], "r" => [116, "B"], "s" => [118, "B"], "t" => [119, "B"], "u" => [122, "B"], "v" => [123, "B"], "w" => [125, "B"], "x" => [126, "B"], "y" => [129, "B"], "z" => [143, "B"], "{" => [148, "B"], "|" => [151, "B"], "}" => [153, "B"], "~" => [83, "B"], "" => [10, "B"], "\x80" => [77, "C0"], "\x81" => [18, "C0"], "\x82" => [77, "C1"], "\x83" => [18, "C1"], "\x84" => [77, "C2"], "\x85" => [18, "C2"], "\x86" => [77, "Ca"], "\x87" => [18, "Ca"], "\x88" => [77, "Cc"], "\x89" => [18, "Cc"], "\x8a" => [77, "Ce"], "\x8b" => [18, "Ce"], "\x8c" => [77, "Ci"], "\x8d" => [18, "Ci"], "\x8e" => [77, "Co"], "\x8f" => [18, "Co"], "\x90" => [77, "Cs"], "\x91" => [18, "Cs"], "\x92" => [77, "Ct"], "\x93" => [18, "Ct"], "\x94" => [0, "C "], "\x95" => [0, "C%"], "\x96" => [0, "C-"], "\x97" => [0, "C."], "\x98" => [0, "C/"], "\x99" => [0, "C3"], "\x9a" => [0, "C4"], "\x9b" => [0, "C5"], "\x9c" => [0, "C6"], "\x9d" => [0, "C7"], "\x9e" => [0, "C8"], "\x9f" => [0, "C9"], "\xa0" => [0, "C="], "\xa1" => [0, "CA"], "\xa2" => [0, "C_"], "\xa3" => [0, "Cb"], "\xa4" => [0, "Cd"], "\xa5" => [0, "Cf"], "\xa6" => [0, "Cg"], "\xa7" => [0, "Ch"], "\xa8" => [0, "Cl"], "\xa9" => [0, "Cm"], "\xaa" => [0, "Cn"], "\xab" => [0, "Cp"], "\xac" => [0, "Cr"], "\xad" => [0, "Cu"], "\xae" => [100, "C"], "\xaf" => [110, "C"], "\xb0" => [111, "C"], "\xb1" => [115, "C"], "\xb2" => [116, "C"], "\xb3" => [118, "C"], "\xb4" => [119, "C"], "\xb5" => [122, "C"], "\xb6" => [123, "C"], "\xb7" => [125, "C"], "\xb8" => [126, "C"], "\xb9" => [129, "C"], "\xba" => [143, "C"], "\xbb" => [148, "C"], "\xbc" => [151, "C"], "\xbd" => [153, "C"], "\xbe" => [83, "C"], "\xbf" => [10, "C"], "\xc0" => [77, "D0"], "\xc1" => [18, "D0"], "\xc2" => [77, "D1"], "\xc3" => [18, "D1"], "\xc4" => [77, "D2"], "\xc5" => [18, "D2"], "\xc6" => [77, "Da"], "\xc7" => [18, "Da"], "\xc8" => [77, "Dc"], "\xc9" => [18, "Dc"], "\xca" => [77, "De"], "\xcb" => [18, "De"], "\xcc" => [77, "Di"], "\xcd" => [18, "Di"], "\xce" => [77, "Do"], "\xcf" => [18, "Do"], "\xd0" => [77, "Ds"], "\xd1" => [18, "Ds"], "\xd2" => [77, "Dt"], "\xd3" => [18, "Dt"], "\xd4" => [0, "D "], "\xd5" => [0, "D%"], "\xd6" => [0, "D-"], "\xd7" => [0, "D."], "\xd8" => [0, "D/"], "\xd9" => [0, "D3"], "\xda" => [0, "D4"], "\xdb" => [0, "D5"], "\xdc" => [0, "D6"], "\xdd" => [0, "D7"], "\xde" => [0, "D8"], "\xdf" => [0, "D9"], "\xe0" => [0, "D="], "\xe1" => [0, "DA"], "\xe2" => [0, "D_"], "\xe3" => [0, "Db"], "\xe4" => [0, "Dd"], "\xe5" => [0, "Df"], "\xe6" => [0, "Dg"], "\xe7" => [0, "Dh"], "\xe8" => [0, "Dl"], "\xe9" => [0, "Dm"], "\xea" => [0, "Dn"], "\xeb" => [0, "Dp"], "\xec" => [0, "Dr"], "\xed" => [0, "Du"], "\xee" => [100, "D"], "\xef" => [110, "D"], "\xf0" => [111, "D"], "\xf1" => [115, "D"], "\xf2" => [116, "D"], "\xf3" => [118, "D"], "\xf4" => [119, "D"], "\xf5" => [122, "D"], "\xf6" => [123, "D"], "\xf7" => [125, "D"], "\xf8" => [126, "D"], "\xf9" => [129, "D"], "\xfa" => [143, "D"], "\xfb" => [148, "D"], "\xfc" => [151, "D"], "\xfd" => [153, "D"], "\xfe" => [83, "D"], "\xff" => [10, "D"]], ["\x00" => [77, "r0"], "\x01" => [18, "r0"], "\x02" => [77, "r1"], "\x03" => [18, "r1"], "\x04" => [77, "r2"], "\x05" => [18, "r2"], "\x06" => [77, "ra"], "\x07" => [18, "ra"], "\x08" => [77, "rc"], "\t" => [18, "rc"], "\n" => [77, "re"], "\v" => [18, "re"], "\f" => [77, "ri"], "\r" => [18, "ri"], "\x0e" => [77, "ro"], "\x0f" => [18, "ro"], "\x10" => [77, "rs"], "\x11" => [18, "rs"], "\x12" => [77, "rt"], "\x13" => [18, "rt"], "\x14" => [0, "r "], "\x15" => [0, "r%"], "\x16" => [0, "r-"], "\x17" => [0, "r."], "\x18" => [0, "r/"], "\x19" => [0, "r3"], "\x1a" => [0, "r4"], "\x1b" => [0, "r5"], "\x1c" => [0, "r6"], "\x1d" => [0, "r7"], "\x1e" => [0, "r8"], "\x1f" => [0, "r9"], " " => [0, "r="], "!" => [0, "rA"], "\"" => [0, "r_"], "#" => [0, "rb"], "\$" => [0, "rd"], "%" => [0, "rf"], "&" => [0, "rg"], "'" => [0, "rh"], "(" => [0, "rl"], ")" => [0, "rm"], "*" => [0, "rn"], "+" => [0, "rp"], "," => [0, "rr"], "-" => [0, "ru"], "." => [100, "r"], "/" => [110, "r"], [111, "r"], [115, "r"], [116, "r"], [118, "r"], [119, "r"], [122, "r"], [123, "r"], [125, "r"], [126, "r"], [129, "r"], ":" => [143, "r"], ";" => [148, "r"], "<" => [151, "r"], "=" => [153, "r"], ">" => [83, "r"], "?" => [10, "r"], "@" => [77, "u0"], "A" => [18, "u0"], "B" => [77, "u1"], "C" => [18, "u1"], "D" => [77, "u2"], "E" => [18, "u2"], "F" => [77, "ua"], "G" => [18, "ua"], "H" => [77, "uc"], "I" => [18, "uc"], "J" => [77, "ue"], "K" => [18, "ue"], "L" => [77, "ui"], "M" => [18, "ui"], "N" => [77, "uo"], "O" => [18, "uo"], "P" => [77, "us"], "Q" => [18, "us"], "R" => [77, "ut"], "S" => [18, "ut"], "T" => [0, "u "], "U" => [0, "u%"], "V" => [0, "u-"], "W" => [0, "u."], "X" => [0, "u/"], "Y" => [0, "u3"], "Z" => [0, "u4"], "[" => [0, "u5"], "\\" => [0, "u6"], "]" => [0, "u7"], "^" => [0, "u8"], "_" => [0, "u9"], "`" => [0, "u="], "a" => [0, "uA"], "b" => [0, "u_"], "c" => [0, "ub"], "d" => [0, "ud"], "e" => [0, "uf"], "f" => [0, "ug"], "g" => [0, "uh"], "h" => [0, "ul"], "i" => [0, "um"], "j" => [0, "un"], "k" => [0, "up"], "l" => [0, "ur"], "m" => [0, "uu"], "n" => [100, "u"], "o" => [110, "u"], "p" => [111, "u"], "q" => [115, "u"], "r" => [116, "u"], "s" => [118, "u"], "t" => [119, "u"], "u" => [122, "u"], "v" => [123, "u"], "w" => [125, "u"], "x" => [126, "u"], "y" => [129, "u"], "z" => [143, "u"], "{" => [148, "u"], "|" => [151, "u"], "}" => [153, "u"], "~" => [83, "u"], "" => [10, "u"], "\x80" => [0, ":0"], "\x81" => [0, ":1"], "\x82" => [0, ":2"], "\x83" => [0, ":a"], "\x84" => [0, ":c"], "\x85" => [0, ":e"], "\x86" => [0, ":i"], "\x87" => [0, ":o"], "\x88" => [0, ":s"], "\x89" => [0, ":t"], "\x8a" => [73, ":"], "\x8b" => [88, ":"], "\x8c" => [89, ":"], "\x8d" => [96, ":"], "\x8e" => [97, ":"], "\x8f" => [99, ":"], "\x90" => [106, ":"], "\x91" => [136, ":"], "\x92" => [139, ":"], "\x93" => [141, ":"], "\x94" => [145, ":"], "\x95" => [147, ":"], "\x96" => [149, ":"], "\x97" => [101, ":"], "\x98" => [112, ":"], "\x99" => [117, ":"], "\x9a" => [120, ":"], "\x9b" => [124, ":"], "\x9c" => [127, ":"], "\x9d" => [144, ":"], "\x9e" => [152, ":"], "\x9f" => [11, ":"], "\xa0" => [0, "B0"], "\xa1" => [0, "B1"], "\xa2" => [0, "B2"], "\xa3" => [0, "Ba"], "\xa4" => [0, "Bc"], "\xa5" => [0, "Be"], "\xa6" => [0, "Bi"], "\xa7" => [0, "Bo"], "\xa8" => [0, "Bs"], "\xa9" => [0, "Bt"], "\xaa" => [73, "B"], "\xab" => [88, "B"], "\xac" => [89, "B"], "\xad" => [96, "B"], "\xae" => [97, "B"], "\xaf" => [99, "B"], "\xb0" => [106, "B"], "\xb1" => [136, "B"], "\xb2" => [139, "B"], "\xb3" => [141, "B"], "\xb4" => [145, "B"], "\xb5" => [147, "B"], "\xb6" => [149, "B"], "\xb7" => [101, "B"], "\xb8" => [112, "B"], "\xb9" => [117, "B"], "\xba" => [120, "B"], "\xbb" => [124, "B"], "\xbc" => [127, "B"], "\xbd" => [144, "B"], "\xbe" => [152, "B"], "\xbf" => [11, "B"], "\xc0" => [0, "C0"], "\xc1" => [0, "C1"], "\xc2" => [0, "C2"], "\xc3" => [0, "Ca"], "\xc4" => [0, "Cc"], "\xc5" => [0, "Ce"], "\xc6" => [0, "Ci"], "\xc7" => [0, "Co"], "\xc8" => [0, "Cs"], "\xc9" => [0, "Ct"], "\xca" => [73, "C"], "\xcb" => [88, "C"], "\xcc" => [89, "C"], "\xcd" => [96, "C"], "\xce" => [97, "C"], "\xcf" => [99, "C"], "\xd0" => [106, "C"], "\xd1" => [136, "C"], "\xd2" => [139, "C"], "\xd3" => [141, "C"], "\xd4" => [145, "C"], "\xd5" => [147, "C"], "\xd6" => [149, "C"], "\xd7" => [101, "C"], "\xd8" => [112, "C"], "\xd9" => [117, "C"], "\xda" => [120, "C"], "\xdb" => [124, "C"], "\xdc" => [127, "C"], "\xdd" => [144, "C"], "\xde" => [152, "C"], "\xdf" => [11, "C"], "\xe0" => [0, "D0"], "\xe1" => [0, "D1"], "\xe2" => [0, "D2"], "\xe3" => [0, "Da"], "\xe4" => [0, "Dc"], "\xe5" => [0, "De"], "\xe6" => [0, "Di"], "\xe7" => [0, "Do"], "\xe8" => [0, "Ds"], "\xe9" => [0, "Dt"], "\xea" => [73, "D"], "\xeb" => [88, "D"], "\xec" => [89, "D"], "\xed" => [96, "D"], "\xee" => [97, "D"], "\xef" => [99, "D"], "\xf0" => [106, "D"], "\xf1" => [136, "D"], "\xf2" => [139, "D"], "\xf3" => [141, "D"], "\xf4" => [145, "D"], "\xf5" => [147, "D"], "\xf6" => [149, "D"], "\xf7" => [101, "D"], "\xf8" => [112, "D"], "\xf9" => [117, "D"], "\xfa" => [120, "D"], "\xfb" => [124, "D"], "\xfc" => [127, "D"], "\xfd" => [144, "D"], "\xfe" => [152, "D"], "\xff" => [11, "D"]], ["\x00" => [0, "l0"], "\x01" => [0, "l1"], "\x02" => [0, "l2"], "\x03" => [0, "la"], "\x04" => [0, "lc"], "\x05" => [0, "le"], "\x06" => [0, "li"], "\x07" => [0, "lo"], "\x08" => [0, "ls"], "\t" => [0, "lt"], "\n" => [73, "l"], "\v" => [88, "l"], "\f" => [89, "l"], "\r" => [96, "l"], "\x0e" => [97, "l"], "\x0f" => [99, "l"], "\x10" => [106, "l"], "\x11" => [136, "l"], "\x12" => [139, "l"], "\x13" => [141, "l"], "\x14" => [145, "l"], "\x15" => [147, "l"], "\x16" => [149, "l"], "\x17" => [101, "l"], "\x18" => [112, "l"], "\x19" => [117, "l"], "\x1a" => [120, "l"], "\x1b" => [124, "l"], "\x1c" => [127, "l"], "\x1d" => [144, "l"], "\x1e" => [152, "l"], "\x1f" => [11, "l"], " " => [0, "m0"], "!" => [0, "m1"], "\"" => [0, "m2"], "#" => [0, "ma"], "\$" => [0, "mc"], "%" => [0, "me"], "&" => [0, "mi"], "'" => [0, "mo"], "(" => [0, "ms"], ")" => [0, "mt"], "*" => [73, "m"], "+" => [88, "m"], "," => [89, "m"], "-" => [96, "m"], "." => [97, "m"], "/" => [99, "m"], [106, "m"], [136, "m"], [139, "m"], [141, "m"], [145, "m"], [147, "m"], [149, "m"], [101, "m"], [112, "m"], [117, "m"], ":" => [120, "m"], ";" => [124, "m"], "<" => [127, "m"], "=" => [144, "m"], ">" => [152, "m"], "?" => [11, "m"], "@" => [0, "n0"], "A" => [0, "n1"], "B" => [0, "n2"], "C" => [0, "na"], "D" => [0, "nc"], "E" => [0, "ne"], "F" => [0, "ni"], "G" => [0, "no"], "H" => [0, "ns"], "I" => [0, "nt"], "J" => [73, "n"], "K" => [88, "n"], "L" => [89, "n"], "M" => [96, "n"], "N" => [97, "n"], "O" => [99, "n"], "P" => [106, "n"], "Q" => [136, "n"], "R" => [139, "n"], "S" => [141, "n"], "T" => [145, "n"], "U" => [147, "n"], "V" => [149, "n"], "W" => [101, "n"], "X" => [112, "n"], "Y" => [117, "n"], "Z" => [120, "n"], "[" => [124, "n"], "\\" => [127, "n"], "]" => [144, "n"], "^" => [152, "n"], "_" => [11, "n"], "`" => [0, "p0"], "a" => [0, "p1"], "b" => [0, "p2"], "c" => [0, "pa"], "d" => [0, "pc"], "e" => [0, "pe"], "f" => [0, "pi"], "g" => [0, "po"], "h" => [0, "ps"], "i" => [0, "pt"], "j" => [73, "p"], "k" => [88, "p"], "l" => [89, "p"], "m" => [96, "p"], "n" => [97, "p"], "o" => [99, "p"], "p" => [106, "p"], "q" => [136, "p"], "r" => [139, "p"], "s" => [141, "p"], "t" => [145, "p"], "u" => [147, "p"], "v" => [149, "p"], "w" => [101, "p"], "x" => [112, "p"], "y" => [117, "p"], "z" => [120, "p"], "{" => [124, "p"], "|" => [127, "p"], "}" => [144, "p"], "~" => [152, "p"], "" => [11, "p"], "\x80" => [0, "r0"], "\x81" => [0, "r1"], "\x82" => [0, "r2"], "\x83" => [0, "ra"], "\x84" => [0, "rc"], "\x85" => [0, "re"], "\x86" => [0, "ri"], "\x87" => [0, "ro"], "\x88" => [0, "rs"], "\x89" => [0, "rt"], "\x8a" => [73, "r"], "\x8b" => [88, "r"], "\x8c" => [89, "r"], "\x8d" => [96, "r"], "\x8e" => [97, "r"], "\x8f" => [99, "r"], "\x90" => [106, "r"], "\x91" => [136, "r"], "\x92" => [139, "r"], "\x93" => [141, "r"], "\x94" => [145, "r"], "\x95" => [147, "r"], "\x96" => [149, "r"], "\x97" => [101, "r"], "\x98" => [112, "r"], "\x99" => [117, "r"], "\x9a" => [120, "r"], "\x9b" => [124, "r"], "\x9c" => [127, "r"], "\x9d" => [144, "r"], "\x9e" => [152, "r"], "\x9f" => [11, "r"], "\xa0" => [0, "u0"], "\xa1" => [0, "u1"], "\xa2" => [0, "u2"], "\xa3" => [0, "ua"], "\xa4" => [0, "uc"], "\xa5" => [0, "ue"], "\xa6" => [0, "ui"], "\xa7" => [0, "uo"], "\xa8" => [0, "us"], "\xa9" => [0, "ut"], "\xaa" => [73, "u"], "\xab" => [88, "u"], "\xac" => [89, "u"], "\xad" => [96, "u"], "\xae" => [97, "u"], "\xaf" => [99, "u"], "\xb0" => [106, "u"], "\xb1" => [136, "u"], "\xb2" => [139, "u"], "\xb3" => [141, "u"], "\xb4" => [145, "u"], "\xb5" => [147, "u"], "\xb6" => [149, "u"], "\xb7" => [101, "u"], "\xb8" => [112, "u"], "\xb9" => [117, "u"], "\xba" => [120, "u"], "\xbb" => [124, "u"], "\xbc" => [127, "u"], "\xbd" => [144, "u"], "\xbe" => [152, "u"], "\xbf" => [11, "u"], "\xc0" => [92, ":"], "\xc1" => [95, ":"], "\xc2" => [137, ":"], "\xc3" => [142, ":"], "\xc4" => [150, ":"], "\xc5" => [74, ":"], "\xc6" => [90, ":"], "\xc7" => [98, ":"], "\xc8" => [107, ":"], "\xc9" => [140, ":"], "\xca" => [146, ":"], "\xcb" => [102, ":"], "\xcc" => [113, ":"], "\xcd" => [121, ":"], "\xce" => [128, ":"], "\xcf" => [12, ":"], "\xd0" => [92, "B"], "\xd1" => [95, "B"], "\xd2" => [137, "B"], "\xd3" => [142, "B"], "\xd4" => [150, "B"], "\xd5" => [74, "B"], "\xd6" => [90, "B"], "\xd7" => [98, "B"], "\xd8" => [107, "B"], "\xd9" => [140, "B"], "\xda" => [146, "B"], "\xdb" => [102, "B"], "\xdc" => [113, "B"], "\xdd" => [121, "B"], "\xde" => [128, "B"], "\xdf" => [12, "B"], "\xe0" => [92, "C"], "\xe1" => [95, "C"], "\xe2" => [137, "C"], "\xe3" => [142, "C"], "\xe4" => [150, "C"], "\xe5" => [74, "C"], "\xe6" => [90, "C"], "\xe7" => [98, "C"], "\xe8" => [107, "C"], "\xe9" => [140, "C"], "\xea" => [146, "C"], "\xeb" => [102, "C"], "\xec" => [113, "C"], "\xed" => [121, "C"], "\xee" => [128, "C"], "\xef" => [12, "C"], "\xf0" => [92, "D"], "\xf1" => [95, "D"], "\xf2" => [137, "D"], "\xf3" => [142, "D"], "\xf4" => [150, "D"], "\xf5" => [74, "D"], "\xf6" => [90, "D"], "\xf7" => [98, "D"], "\xf8" => [107, "D"], "\xf9" => [140, "D"], "\xfa" => [146, "D"], "\xfb" => [102, "D"], "\xfc" => [113, "D"], "\xfd" => [121, "D"], "\xfe" => [128, "D"], "\xff" => [12, "D"]], ["\x00" => [92, "="], "\x01" => [95, "="], "\x02" => [137, "="], "\x03" => [142, "="], "\x04" => [150, "="], "\x05" => [74, "="], "\x06" => [90, "="], "\x07" => [98, "="], "\x08" => [107, "="], "\t" => [140, "="], "\n" => [146, "="], "\v" => [102, "="], "\f" => [113, "="], "\r" => [121, "="], "\x0e" => [128, "="], "\x0f" => [12, "="], "\x10" => [92, "A"], "\x11" => [95, "A"], "\x12" => [137, "A"], "\x13" => [142, "A"], "\x14" => [150, "A"], "\x15" => [74, "A"], "\x16" => [90, "A"], "\x17" => [98, "A"], "\x18" => [107, "A"], "\x19" => [140, "A"], "\x1a" => [146, "A"], "\x1b" => [102, "A"], "\x1c" => [113, "A"], "\x1d" => [121, "A"], "\x1e" => [128, "A"], "\x1f" => [12, "A"], " " => [92, "_"], "!" => [95, "_"], "\"" => [137, "_"], "#" => [142, "_"], "\$" => [150, "_"], "%" => [74, "_"], "&" => [90, "_"], "'" => [98, "_"], "(" => [107, "_"], ")" => [140, "_"], "*" => [146, "_"], "+" => [102, "_"], "," => [113, "_"], "-" => [121, "_"], "." => [128, "_"], "/" => [12, "_"], [92, "b"], [95, "b"], [137, "b"], [142, "b"], [150, "b"], [74, "b"], [90, "b"], [98, "b"], [107, "b"], [140, "b"], ":" => [146, "b"], ";" => [102, "b"], "<" => [113, "b"], "=" => [121, "b"], ">" => [128, "b"], "?" => [12, "b"], "@" => [92, "d"], "A" => [95, "d"], "B" => [137, "d"], "C" => [142, "d"], "D" => [150, "d"], "E" => [74, "d"], "F" => [90, "d"], "G" => [98, "d"], "H" => [107, "d"], "I" => [140, "d"], "J" => [146, "d"], "K" => [102, "d"], "L" => [113, "d"], "M" => [121, "d"], "N" => [128, "d"], "O" => [12, "d"], "P" => [92, "f"], "Q" => [95, "f"], "R" => [137, "f"], "S" => [142, "f"], "T" => [150, "f"], "U" => [74, "f"], "V" => [90, "f"], "W" => [98, "f"], "X" => [107, "f"], "Y" => [140, "f"], "Z" => [146, "f"], "[" => [102, "f"], "\\" => [113, "f"], "]" => [121, "f"], "^" => [128, "f"], "_" => [12, "f"], "`" => [92, "g"], "a" => [95, "g"], "b" => [137, "g"], "c" => [142, "g"], "d" => [150, "g"], "e" => [74, "g"], "f" => [90, "g"], "g" => [98, "g"], "h" => [107, "g"], "i" => [140, "g"], "j" => [146, "g"], "k" => [102, "g"], "l" => [113, "g"], "m" => [121, "g"], "n" => [128, "g"], "o" => [12, "g"], "p" => [92, "h"], "q" => [95, "h"], "r" => [137, "h"], "s" => [142, "h"], "t" => [150, "h"], "u" => [74, "h"], "v" => [90, "h"], "w" => [98, "h"], "x" => [107, "h"], "y" => [140, "h"], "z" => [146, "h"], "{" => [102, "h"], "|" => [113, "h"], "}" => [121, "h"], "~" => [128, "h"], "" => [12, "h"], "\x80" => [92, "l"], "\x81" => [95, "l"], "\x82" => [137, "l"], "\x83" => [142, "l"], "\x84" => [150, "l"], "\x85" => [74, "l"], "\x86" => [90, "l"], "\x87" => [98, "l"], "\x88" => [107, "l"], "\x89" => [140, "l"], "\x8a" => [146, "l"], "\x8b" => [102, "l"], "\x8c" => [113, "l"], "\x8d" => [121, "l"], "\x8e" => [128, "l"], "\x8f" => [12, "l"], "\x90" => [92, "m"], "\x91" => [95, "m"], "\x92" => [137, "m"], "\x93" => [142, "m"], "\x94" => [150, "m"], "\x95" => [74, "m"], "\x96" => [90, "m"], "\x97" => [98, "m"], "\x98" => [107, "m"], "\x99" => [140, "m"], "\x9a" => [146, "m"], "\x9b" => [102, "m"], "\x9c" => [113, "m"], "\x9d" => [121, "m"], "\x9e" => [128, "m"], "\x9f" => [12, "m"], "\xa0" => [92, "n"], "\xa1" => [95, "n"], "\xa2" => [137, "n"], "\xa3" => [142, "n"], "\xa4" => [150, "n"], "\xa5" => [74, "n"], "\xa6" => [90, "n"], "\xa7" => [98, "n"], "\xa8" => [107, "n"], "\xa9" => [140, "n"], "\xaa" => [146, "n"], "\xab" => [102, "n"], "\xac" => [113, "n"], "\xad" => [121, "n"], "\xae" => [128, "n"], "\xaf" => [12, "n"], "\xb0" => [92, "p"], "\xb1" => [95, "p"], "\xb2" => [137, "p"], "\xb3" => [142, "p"], "\xb4" => [150, "p"], "\xb5" => [74, "p"], "\xb6" => [90, "p"], "\xb7" => [98, "p"], "\xb8" => [107, "p"], "\xb9" => [140, "p"], "\xba" => [146, "p"], "\xbb" => [102, "p"], "\xbc" => [113, "p"], "\xbd" => [121, "p"], "\xbe" => [128, "p"], "\xbf" => [12, "p"], "\xc0" => [92, "r"], "\xc1" => [95, "r"], "\xc2" => [137, "r"], "\xc3" => [142, "r"], "\xc4" => [150, "r"], "\xc5" => [74, "r"], "\xc6" => [90, "r"], "\xc7" => [98, "r"], "\xc8" => [107, "r"], "\xc9" => [140, "r"], "\xca" => [146, "r"], "\xcb" => [102, "r"], "\xcc" => [113, "r"], "\xcd" => [121, "r"], "\xce" => [128, "r"], "\xcf" => [12, "r"], "\xd0" => [92, "u"], "\xd1" => [95, "u"], "\xd2" => [137, "u"], "\xd3" => [142, "u"], "\xd4" => [150, "u"], "\xd5" => [74, "u"], "\xd6" => [90, "u"], "\xd7" => [98, "u"], "\xd8" => [107, "u"], "\xd9" => [140, "u"], "\xda" => [146, "u"], "\xdb" => [102, "u"], "\xdc" => [113, "u"], "\xdd" => [121, "u"], "\xde" => [128, "u"], "\xdf" => [12, "u"], "\xe0" => [93, ":"], "\xe1" => [138, ":"], "\xe2" => [75, ":"], "\xe3" => [91, ":"], "\xe4" => [108, ":"], "\xe5" => [103, ":"], "\xe6" => [114, ":"], "\xe7" => [14, ":"], "\xe8" => [93, "B"], "\xe9" => [138, "B"], "\xea" => [75, "B"], "\xeb" => [91, "B"], "\xec" => [108, "B"], "\xed" => [103, "B"], "\xee" => [114, "B"], "\xef" => [14, "B"], "\xf0" => [93, "C"], "\xf1" => [138, "C"], "\xf2" => [75, "C"], "\xf3" => [91, "C"], "\xf4" => [108, "C"], "\xf5" => [103, "C"], "\xf6" => [114, "C"], "\xf7" => [14, "C"], "\xf8" => [93, "D"], "\xf9" => [138, "D"], "\xfa" => [75, "D"], "\xfb" => [91, "D"], "\xfc" => [108, "D"], "\xfd" => [103, "D"], "\xfe" => [114, "D"], "\xff" => [14, "D"]], ["\x00" => [94, "<0"], "\x01" => [76, "<0"], "\x02" => [104, "<0"], "\x03" => [16, "<0"], "\x04" => [94, "<1"], "\x05" => [76, "<1"], "\x06" => [104, "<1"], "\x07" => [16, "<1"], "\x08" => [94, "<2"], "\t" => [76, "<2"], "\n" => [104, "<2"], "\v" => [16, "<2"], "\f" => [94, "<a"], "\r" => [76, "<a"], "\x0e" => [104, "<a"], "\x0f" => [16, "<a"], "\x10" => [94, "<c"], "\x11" => [76, "<c"], "\x12" => [104, "<c"], "\x13" => [16, "<c"], "\x14" => [94, "<e"], "\x15" => [76, "<e"], "\x16" => [104, "<e"], "\x17" => [16, "<e"], "\x18" => [94, "<i"], "\x19" => [76, "<i"], "\x1a" => [104, "<i"], "\x1b" => [16, "<i"], "\x1c" => [94, "<o"], "\x1d" => [76, "<o"], "\x1e" => [104, "<o"], "\x1f" => [16, "<o"], " " => [94, "<s"], "!" => [76, "<s"], "\"" => [104, "<s"], "#" => [16, "<s"], "\$" => [94, "<t"], "%" => [76, "<t"], "&" => [104, "<t"], "'" => [16, "<t"], "(" => [77, "< "], ")" => [18, "< "], "*" => [77, "<%"], "+" => [18, "<%"], "," => [77, "<-"], "-" => [18, "<-"], "." => [77, "<."], "/" => [18, "<."], [77, "</"], [18, "</"], [77, "<3"], [18, "<3"], [77, "<4"], [18, "<4"], [77, "<5"], [18, "<5"], [77, "<6"], [18, "<6"], ":" => [77, "<7"], ";" => [18, "<7"], "<" => [77, "<8"], "=" => [18, "<8"], ">" => [77, "<9"], "?" => [18, "<9"], "@" => [77, "<="], "A" => [18, "<="], "B" => [77, "<A"], "C" => [18, "<A"], "D" => [77, "<_"], "E" => [18, "<_"], "F" => [77, "<b"], "G" => [18, "<b"], "H" => [77, "<d"], "I" => [18, "<d"], "J" => [77, "<f"], "K" => [18, "<f"], "L" => [77, "<g"], "M" => [18, "<g"], "N" => [77, "<h"], "O" => [18, "<h"], "P" => [77, "<l"], "Q" => [18, "<l"], "R" => [77, "<m"], "S" => [18, "<m"], "T" => [77, "<n"], "U" => [18, "<n"], "V" => [77, "<p"], "W" => [18, "<p"], "X" => [77, "<r"], "Y" => [18, "<r"], "Z" => [77, "<u"], "[" => [18, "<u"], "\\" => [0, "<:"], "]" => [0, "<B"], "^" => [0, "<C"], "_" => [0, "<D"], "`" => [0, "<E"], "a" => [0, "<F"], "b" => [0, "<G"], "c" => [0, "<H"], "d" => [0, "<I"], "e" => [0, "<J"], "f" => [0, "<K"], "g" => [0, "<L"], "h" => [0, "<M"], "i" => [0, "<N"], "j" => [0, "<O"], "k" => [0, "<P"], "l" => [0, "<Q"], "m" => [0, "<R"], "n" => [0, "<S"], "o" => [0, "<T"], "p" => [0, "<U"], "q" => [0, "<V"], "r" => [0, "<W"], "s" => [0, "<Y"], "t" => [0, "<j"], "u" => [0, "<k"], "v" => [0, "<q"], "w" => [0, "<v"], "x" => [0, "<w"], "y" => [0, "<x"], "z" => [0, "<y"], "{" => [0, "<z"], "|" => [82, "<"], "}" => [87, "<"], "~" => [130, "<"], "" => [9, "<"], "\x80" => [94, "`0"], "\x81" => [76, "`0"], "\x82" => [104, "`0"], "\x83" => [16, "`0"], "\x84" => [94, "`1"], "\x85" => [76, "`1"], "\x86" => [104, "`1"], "\x87" => [16, "`1"], "\x88" => [94, "`2"], "\x89" => [76, "`2"], "\x8a" => [104, "`2"], "\x8b" => [16, "`2"], "\x8c" => [94, "`a"], "\x8d" => [76, "`a"], "\x8e" => [104, "`a"], "\x8f" => [16, "`a"], "\x90" => [94, "`c"], "\x91" => [76, "`c"], "\x92" => [104, "`c"], "\x93" => [16, "`c"], "\x94" => [94, "`e"], "\x95" => [76, "`e"], "\x96" => [104, "`e"], "\x97" => [16, "`e"], "\x98" => [94, "`i"], "\x99" => [76, "`i"], "\x9a" => [104, "`i"], "\x9b" => [16, "`i"], "\x9c" => [94, "`o"], "\x9d" => [76, "`o"], "\x9e" => [104, "`o"], "\x9f" => [16, "`o"], "\xa0" => [94, "`s"], "\xa1" => [76, "`s"], "\xa2" => [104, "`s"], "\xa3" => [16, "`s"], "\xa4" => [94, "`t"], "\xa5" => [76, "`t"], "\xa6" => [104, "`t"], "\xa7" => [16, "`t"], "\xa8" => [77, "` "], "\xa9" => [18, "` "], "\xaa" => [77, "`%"], "\xab" => [18, "`%"], "\xac" => [77, "`-"], "\xad" => [18, "`-"], "\xae" => [77, "`."], "\xaf" => [18, "`."], "\xb0" => [77, "`/"], "\xb1" => [18, "`/"], "\xb2" => [77, "`3"], "\xb3" => [18, "`3"], "\xb4" => [77, "`4"], "\xb5" => [18, "`4"], "\xb6" => [77, "`5"], "\xb7" => [18, "`5"], "\xb8" => [77, "`6"], "\xb9" => [18, "`6"], "\xba" => [77, "`7"], "\xbb" => [18, "`7"], "\xbc" => [77, "`8"], "\xbd" => [18, "`8"], "\xbe" => [77, "`9"], "\xbf" => [18, "`9"], "\xc0" => [77, "`="], "\xc1" => [18, "`="], "\xc2" => [77, "`A"], "\xc3" => [18, "`A"], "\xc4" => [77, "`_"], "\xc5" => [18, "`_"], "\xc6" => [77, "`b"], "\xc7" => [18, "`b"], "\xc8" => [77, "`d"], "\xc9" => [18, "`d"], "\xca" => [77, "`f"], "\xcb" => [18, "`f"], "\xcc" => [77, "`g"], "\xcd" => [18, "`g"], "\xce" => [77, "`h"], "\xcf" => [18, "`h"], "\xd0" => [77, "`l"], "\xd1" => [18, "`l"], "\xd2" => [77, "`m"], "\xd3" => [18, "`m"], "\xd4" => [77, "`n"], "\xd5" => [18, "`n"], "\xd6" => [77, "`p"], "\xd7" => [18, "`p"], "\xd8" => [77, "`r"], "\xd9" => [18, "`r"], "\xda" => [77, "`u"], "\xdb" => [18, "`u"], "\xdc" => [0, "`:"], "\xdd" => [0, "`B"], "\xde" => [0, "`C"], "\xdf" => [0, "`D"], "\xe0" => [0, "`E"], "\xe1" => [0, "`F"], "\xe2" => [0, "`G"], "\xe3" => [0, "`H"], "\xe4" => [0, "`I"], "\xe5" => [0, "`J"], "\xe6" => [0, "`K"], "\xe7" => [0, "`L"], "\xe8" => [0, "`M"], "\xe9" => [0, "`N"], "\xea" => [0, "`O"], "\xeb" => [0, "`P"], "\xec" => [0, "`Q"], "\xed" => [0, "`R"], "\xee" => [0, "`S"], "\xef" => [0, "`T"], "\xf0" => [0, "`U"], "\xf1" => [0, "`V"], "\xf2" => [0, "`W"], "\xf3" => [0, "`Y"], "\xf4" => [0, "`j"], "\xf5" => [0, "`k"], "\xf6" => [0, "`q"], "\xf7" => [0, "`v"], "\xf8" => [0, "`w"], "\xf9" => [0, "`x"], "\xfa" => [0, "`y"], "\xfb" => [0, "`z"], "\xfc" => [82, "`"], "\xfd" => [87, "`"], "\xfe" => [130, "`"], "\xff" => [9, "`"]], ["\x00" => [94, "=0"], "\x01" => [76, "=0"], "\x02" => [104, "=0"], "\x03" => [16, "=0"], "\x04" => [94, "=1"], "\x05" => [76, "=1"], "\x06" => [104, "=1"], "\x07" => [16, "=1"], "\x08" => [94, "=2"], "\t" => [76, "=2"], "\n" => [104, "=2"], "\v" => [16, "=2"], "\f" => [94, "=a"], "\r" => [76, "=a"], "\x0e" => [104, "=a"], "\x0f" => [16, "=a"], "\x10" => [94, "=c"], "\x11" => [76, "=c"], "\x12" => [104, "=c"], "\x13" => [16, "=c"], "\x14" => [94, "=e"], "\x15" => [76, "=e"], "\x16" => [104, "=e"], "\x17" => [16, "=e"], "\x18" => [94, "=i"], "\x19" => [76, "=i"], "\x1a" => [104, "=i"], "\x1b" => [16, "=i"], "\x1c" => [94, "=o"], "\x1d" => [76, "=o"], "\x1e" => [104, "=o"], "\x1f" => [16, "=o"], " " => [94, "=s"], "!" => [76, "=s"], "\"" => [104, "=s"], "#" => [16, "=s"], "\$" => [94, "=t"], "%" => [76, "=t"], "&" => [104, "=t"], "'" => [16, "=t"], "(" => [77, "= "], ")" => [18, "= "], "*" => [77, "=%"], "+" => [18, "=%"], "," => [77, "=-"], "-" => [18, "=-"], "." => [77, "=."], "/" => [18, "=."], [77, "=/"], [18, "=/"], [77, "=3"], [18, "=3"], [77, "=4"], [18, "=4"], [77, "=5"], [18, "=5"], [77, "=6"], [18, "=6"], ":" => [77, "=7"], ";" => [18, "=7"], "<" => [77, "=8"], "=" => [18, "=8"], ">" => [77, "=9"], "?" => [18, "=9"], "@" => [77, "=="], "A" => [18, "=="], "B" => [77, "=A"], "C" => [18, "=A"], "D" => [77, "=_"], "E" => [18, "=_"], "F" => [77, "=b"], "G" => [18, "=b"], "H" => [77, "=d"], "I" => [18, "=d"], "J" => [77, "=f"], "K" => [18, "=f"], "L" => [77, "=g"], "M" => [18, "=g"], "N" => [77, "=h"], "O" => [18, "=h"], "P" => [77, "=l"], "Q" => [18, "=l"], "R" => [77, "=m"], "S" => [18, "=m"], "T" => [77, "=n"], "U" => [18, "=n"], "V" => [77, "=p"], "W" => [18, "=p"], "X" => [77, "=r"], "Y" => [18, "=r"], "Z" => [77, "=u"], "[" => [18, "=u"], "\\" => [0, "=:"], "]" => [0, "=B"], "^" => [0, "=C"], "_" => [0, "=D"], "`" => [0, "=E"], "a" => [0, "=F"], "b" => [0, "=G"], "c" => [0, "=H"], "d" => [0, "=I"], "e" => [0, "=J"], "f" => [0, "=K"], "g" => [0, "=L"], "h" => [0, "=M"], "i" => [0, "=N"], "j" => [0, "=O"], "k" => [0, "=P"], "l" => [0, "=Q"], "m" => [0, "=R"], "n" => [0, "=S"], "o" => [0, "=T"], "p" => [0, "=U"], "q" => [0, "=V"], "r" => [0, "=W"], "s" => [0, "=Y"], "t" => [0, "=j"], "u" => [0, "=k"], "v" => [0, "=q"], "w" => [0, "=v"], "x" => [0, "=w"], "y" => [0, "=x"], "z" => [0, "=y"], "{" => [0, "=z"], "|" => [82, "="], "}" => [87, "="], "~" => [130, "="], "" => [9, "="], "\x80" => [94, "A0"], "\x81" => [76, "A0"], "\x82" => [104, "A0"], "\x83" => [16, "A0"], "\x84" => [94, "A1"], "\x85" => [76, "A1"], "\x86" => [104, "A1"], "\x87" => [16, "A1"], "\x88" => [94, "A2"], "\x89" => [76, "A2"], "\x8a" => [104, "A2"], "\x8b" => [16, "A2"], "\x8c" => [94, "Aa"], "\x8d" => [76, "Aa"], "\x8e" => [104, "Aa"], "\x8f" => [16, "Aa"], "\x90" => [94, "Ac"], "\x91" => [76, "Ac"], "\x92" => [104, "Ac"], "\x93" => [16, "Ac"], "\x94" => [94, "Ae"], "\x95" => [76, "Ae"], "\x96" => [104, "Ae"], "\x97" => [16, "Ae"], "\x98" => [94, "Ai"], "\x99" => [76, "Ai"], "\x9a" => [104, "Ai"], "\x9b" => [16, "Ai"], "\x9c" => [94, "Ao"], "\x9d" => [76, "Ao"], "\x9e" => [104, "Ao"], "\x9f" => [16, "Ao"], "\xa0" => [94, "As"], "\xa1" => [76, "As"], "\xa2" => [104, "As"], "\xa3" => [16, "As"], "\xa4" => [94, "At"], "\xa5" => [76, "At"], "\xa6" => [104, "At"], "\xa7" => [16, "At"], "\xa8" => [77, "A "], "\xa9" => [18, "A "], "\xaa" => [77, "A%"], "\xab" => [18, "A%"], "\xac" => [77, "A-"], "\xad" => [18, "A-"], "\xae" => [77, "A."], "\xaf" => [18, "A."], "\xb0" => [77, "A/"], "\xb1" => [18, "A/"], "\xb2" => [77, "A3"], "\xb3" => [18, "A3"], "\xb4" => [77, "A4"], "\xb5" => [18, "A4"], "\xb6" => [77, "A5"], "\xb7" => [18, "A5"], "\xb8" => [77, "A6"], "\xb9" => [18, "A6"], "\xba" => [77, "A7"], "\xbb" => [18, "A7"], "\xbc" => [77, "A8"], "\xbd" => [18, "A8"], "\xbe" => [77, "A9"], "\xbf" => [18, "A9"], "\xc0" => [77, "A="], "\xc1" => [18, "A="], "\xc2" => [77, "AA"], "\xc3" => [18, "AA"], "\xc4" => [77, "A_"], "\xc5" => [18, "A_"], "\xc6" => [77, "Ab"], "\xc7" => [18, "Ab"], "\xc8" => [77, "Ad"], "\xc9" => [18, "Ad"], "\xca" => [77, "Af"], "\xcb" => [18, "Af"], "\xcc" => [77, "Ag"], "\xcd" => [18, "Ag"], "\xce" => [77, "Ah"], "\xcf" => [18, "Ah"], "\xd0" => [77, "Al"], "\xd1" => [18, "Al"], "\xd2" => [77, "Am"], "\xd3" => [18, "Am"], "\xd4" => [77, "An"], "\xd5" => [18, "An"], "\xd6" => [77, "Ap"], "\xd7" => [18, "Ap"], "\xd8" => [77, "Ar"], "\xd9" => [18, "Ar"], "\xda" => [77, "Au"], "\xdb" => [18, "Au"], "\xdc" => [0, "A:"], "\xdd" => [0, "AB"], "\xde" => [0, "AC"], "\xdf" => [0, "AD"], "\xe0" => [0, "AE"], "\xe1" => [0, "AF"], "\xe2" => [0, "AG"], "\xe3" => [0, "AH"], "\xe4" => [0, "AI"], "\xe5" => [0, "AJ"], "\xe6" => [0, "AK"], "\xe7" => [0, "AL"], "\xe8" => [0, "AM"], "\xe9" => [0, "AN"], "\xea" => [0, "AO"], "\xeb" => [0, "AP"], "\xec" => [0, "AQ"], "\xed" => [0, "AR"], "\xee" => [0, "AS"], "\xef" => [0, "AT"], "\xf0" => [0, "AU"], "\xf1" => [0, "AV"], "\xf2" => [0, "AW"], "\xf3" => [0, "AY"], "\xf4" => [0, "Aj"], "\xf5" => [0, "Ak"], "\xf6" => [0, "Aq"], "\xf7" => [0, "Av"], "\xf8" => [0, "Aw"], "\xf9" => [0, "Ax"], "\xfa" => [0, "Ay"], "\xfb" => [0, "Az"], "\xfc" => [82, "A"], "\xfd" => [87, "A"], "\xfe" => [130, "A"], "\xff" => [9, "A"]], ["\x00" => [77, "=0"], "\x01" => [18, "=0"], "\x02" => [77, "=1"], "\x03" => [18, "=1"], "\x04" => [77, "=2"], "\x05" => [18, "=2"], "\x06" => [77, "=a"], "\x07" => [18, "=a"], "\x08" => [77, "=c"], "\t" => [18, "=c"], "\n" => [77, "=e"], "\v" => [18, "=e"], "\f" => [77, "=i"], "\r" => [18, "=i"], "\x0e" => [77, "=o"], "\x0f" => [18, "=o"], "\x10" => [77, "=s"], "\x11" => [18, "=s"], "\x12" => [77, "=t"], "\x13" => [18, "=t"], "\x14" => [0, "= "], "\x15" => [0, "=%"], "\x16" => [0, "=-"], "\x17" => [0, "=."], "\x18" => [0, "=/"], "\x19" => [0, "=3"], "\x1a" => [0, "=4"], "\x1b" => [0, "=5"], "\x1c" => [0, "=6"], "\x1d" => [0, "=7"], "\x1e" => [0, "=8"], "\x1f" => [0, "=9"], " " => [0, "=="], "!" => [0, "=A"], "\"" => [0, "=_"], "#" => [0, "=b"], "\$" => [0, "=d"], "%" => [0, "=f"], "&" => [0, "=g"], "'" => [0, "=h"], "(" => [0, "=l"], ")" => [0, "=m"], "*" => [0, "=n"], "+" => [0, "=p"], "," => [0, "=r"], "-" => [0, "=u"], "." => [100, "="], "/" => [110, "="], [111, "="], [115, "="], [116, "="], [118, "="], [119, "="], [122, "="], [123, "="], [125, "="], [126, "="], [129, "="], ":" => [143, "="], ";" => [148, "="], "<" => [151, "="], "=" => [153, "="], ">" => [83, "="], "?" => [10, "="], "@" => [77, "A0"], "A" => [18, "A0"], "B" => [77, "A1"], "C" => [18, "A1"], "D" => [77, "A2"], "E" => [18, "A2"], "F" => [77, "Aa"], "G" => [18, "Aa"], "H" => [77, "Ac"], "I" => [18, "Ac"], "J" => [77, "Ae"], "K" => [18, "Ae"], "L" => [77, "Ai"], "M" => [18, "Ai"], "N" => [77, "Ao"], "O" => [18, "Ao"], "P" => [77, "As"], "Q" => [18, "As"], "R" => [77, "At"], "S" => [18, "At"], "T" => [0, "A "], "U" => [0, "A%"], "V" => [0, "A-"], "W" => [0, "A."], "X" => [0, "A/"], "Y" => [0, "A3"], "Z" => [0, "A4"], "[" => [0, "A5"], "\\" => [0, "A6"], "]" => [0, "A7"], "^" => [0, "A8"], "_" => [0, "A9"], "`" => [0, "A="], "a" => [0, "AA"], "b" => [0, "A_"], "c" => [0, "Ab"], "d" => [0, "Ad"], "e" => [0, "Af"], "f" => [0, "Ag"], "g" => [0, "Ah"], "h" => [0, "Al"], "i" => [0, "Am"], "j" => [0, "An"], "k" => [0, "Ap"], "l" => [0, "Ar"], "m" => [0, "Au"], "n" => [100, "A"], "o" => [110, "A"], "p" => [111, "A"], "q" => [115, "A"], "r" => [116, "A"], "s" => [118, "A"], "t" => [119, "A"], "u" => [122, "A"], "v" => [123, "A"], "w" => [125, "A"], "x" => [126, "A"], "y" => [129, "A"], "z" => [143, "A"], "{" => [148, "A"], "|" => [151, "A"], "}" => [153, "A"], "~" => [83, "A"], "" => [10, "A"], "\x80" => [77, "_0"], "\x81" => [18, "_0"], "\x82" => [77, "_1"], "\x83" => [18, "_1"], "\x84" => [77, "_2"], "\x85" => [18, "_2"], "\x86" => [77, "_a"], "\x87" => [18, "_a"], "\x88" => [77, "_c"], "\x89" => [18, "_c"], "\x8a" => [77, "_e"], "\x8b" => [18, "_e"], "\x8c" => [77, "_i"], "\x8d" => [18, "_i"], "\x8e" => [77, "_o"], "\x8f" => [18, "_o"], "\x90" => [77, "_s"], "\x91" => [18, "_s"], "\x92" => [77, "_t"], "\x93" => [18, "_t"], "\x94" => [0, "_ "], "\x95" => [0, "_%"], "\x96" => [0, "_-"], "\x97" => [0, "_."], "\x98" => [0, "_/"], "\x99" => [0, "_3"], "\x9a" => [0, "_4"], "\x9b" => [0, "_5"], "\x9c" => [0, "_6"], "\x9d" => [0, "_7"], "\x9e" => [0, "_8"], "\x9f" => [0, "_9"], "\xa0" => [0, "_="], "\xa1" => [0, "_A"], "\xa2" => [0, "__"], "\xa3" => [0, "_b"], "\xa4" => [0, "_d"], "\xa5" => [0, "_f"], "\xa6" => [0, "_g"], "\xa7" => [0, "_h"], "\xa8" => [0, "_l"], "\xa9" => [0, "_m"], "\xaa" => [0, "_n"], "\xab" => [0, "_p"], "\xac" => [0, "_r"], "\xad" => [0, "_u"], "\xae" => [100, "_"], "\xaf" => [110, "_"], "\xb0" => [111, "_"], "\xb1" => [115, "_"], "\xb2" => [116, "_"], "\xb3" => [118, "_"], "\xb4" => [119, "_"], "\xb5" => [122, "_"], "\xb6" => [123, "_"], "\xb7" => [125, "_"], "\xb8" => [126, "_"], "\xb9" => [129, "_"], "\xba" => [143, "_"], "\xbb" => [148, "_"], "\xbc" => [151, "_"], "\xbd" => [153, "_"], "\xbe" => [83, "_"], "\xbf" => [10, "_"], "\xc0" => [77, "b0"], "\xc1" => [18, "b0"], "\xc2" => [77, "b1"], "\xc3" => [18, "b1"], "\xc4" => [77, "b2"], "\xc5" => [18, "b2"], "\xc6" => [77, "ba"], "\xc7" => [18, "ba"], "\xc8" => [77, "bc"], "\xc9" => [18, "bc"], "\xca" => [77, "be"], "\xcb" => [18, "be"], "\xcc" => [77, "bi"], "\xcd" => [18, "bi"], "\xce" => [77, "bo"], "\xcf" => [18, "bo"], "\xd0" => [77, "bs"], "\xd1" => [18, "bs"], "\xd2" => [77, "bt"], "\xd3" => [18, "bt"], "\xd4" => [0, "b "], "\xd5" => [0, "b%"], "\xd6" => [0, "b-"], "\xd7" => [0, "b."], "\xd8" => [0, "b/"], "\xd9" => [0, "b3"], "\xda" => [0, "b4"], "\xdb" => [0, "b5"], "\xdc" => [0, "b6"], "\xdd" => [0, "b7"], "\xde" => [0, "b8"], "\xdf" => [0, "b9"], "\xe0" => [0, "b="], "\xe1" => [0, "bA"], "\xe2" => [0, "b_"], "\xe3" => [0, "bb"], "\xe4" => [0, "bd"], "\xe5" => [0, "bf"], "\xe6" => [0, "bg"], "\xe7" => [0, "bh"], "\xe8" => [0, "bl"], "\xe9" => [0, "bm"], "\xea" => [0, "bn"], "\xeb" => [0, "bp"], "\xec" => [0, "br"], "\xed" => [0, "bu"], "\xee" => [100, "b"], "\xef" => [110, "b"], "\xf0" => [111, "b"], "\xf1" => [115, "b"], "\xf2" => [116, "b"], "\xf3" => [118, "b"], "\xf4" => [119, "b"], "\xf5" => [122, "b"], "\xf6" => [123, "b"], "\xf7" => [125, "b"], "\xf8" => [126, "b"], "\xf9" => [129, "b"], "\xfa" => [143, "b"], "\xfb" => [148, "b"], "\xfc" => [151, "b"], "\xfd" => [153, "b"], "\xfe" => [83, "b"], "\xff" => [10, "b"]], ["\x00" => [0, "=0"], "\x01" => [0, "=1"], "\x02" => [0, "=2"], "\x03" => [0, "=a"], "\x04" => [0, "=c"], "\x05" => [0, "=e"], "\x06" => [0, "=i"], "\x07" => [0, "=o"], "\x08" => [0, "=s"], "\t" => [0, "=t"], "\n" => [73, "="], "\v" => [88, "="], "\f" => [89, "="], "\r" => [96, "="], "\x0e" => [97, "="], "\x0f" => [99, "="], "\x10" => [106, "="], "\x11" => [136, "="], "\x12" => [139, "="], "\x13" => [141, "="], "\x14" => [145, "="], "\x15" => [147, "="], "\x16" => [149, "="], "\x17" => [101, "="], "\x18" => [112, "="], "\x19" => [117, "="], "\x1a" => [120, "="], "\x1b" => [124, "="], "\x1c" => [127, "="], "\x1d" => [144, "="], "\x1e" => [152, "="], "\x1f" => [11, "="], " " => [0, "A0"], "!" => [0, "A1"], "\"" => [0, "A2"], "#" => [0, "Aa"], "\$" => [0, "Ac"], "%" => [0, "Ae"], "&" => [0, "Ai"], "'" => [0, "Ao"], "(" => [0, "As"], ")" => [0, "At"], "*" => [73, "A"], "+" => [88, "A"], "," => [89, "A"], "-" => [96, "A"], "." => [97, "A"], "/" => [99, "A"], [106, "A"], [136, "A"], [139, "A"], [141, "A"], [145, "A"], [147, "A"], [149, "A"], [101, "A"], [112, "A"], [117, "A"], ":" => [120, "A"], ";" => [124, "A"], "<" => [127, "A"], "=" => [144, "A"], ">" => [152, "A"], "?" => [11, "A"], "@" => [0, "_0"], "A" => [0, "_1"], "B" => [0, "_2"], "C" => [0, "_a"], "D" => [0, "_c"], "E" => [0, "_e"], "F" => [0, "_i"], "G" => [0, "_o"], "H" => [0, "_s"], "I" => [0, "_t"], "J" => [73, "_"], "K" => [88, "_"], "L" => [89, "_"], "M" => [96, "_"], "N" => [97, "_"], "O" => [99, "_"], "P" => [106, "_"], "Q" => [136, "_"], "R" => [139, "_"], "S" => [141, "_"], "T" => [145, "_"], "U" => [147, "_"], "V" => [149, "_"], "W" => [101, "_"], "X" => [112, "_"], "Y" => [117, "_"], "Z" => [120, "_"], "[" => [124, "_"], "\\" => [127, "_"], "]" => [144, "_"], "^" => [152, "_"], "_" => [11, "_"], "`" => [0, "b0"], "a" => [0, "b1"], "b" => [0, "b2"], "c" => [0, "ba"], "d" => [0, "bc"], "e" => [0, "be"], "f" => [0, "bi"], "g" => [0, "bo"], "h" => [0, "bs"], "i" => [0, "bt"], "j" => [73, "b"], "k" => [88, "b"], "l" => [89, "b"], "m" => [96, "b"], "n" => [97, "b"], "o" => [99, "b"], "p" => [106, "b"], "q" => [136, "b"], "r" => [139, "b"], "s" => [141, "b"], "t" => [145, "b"], "u" => [147, "b"], "v" => [149, "b"], "w" => [101, "b"], "x" => [112, "b"], "y" => [117, "b"], "z" => [120, "b"], "{" => [124, "b"], "|" => [127, "b"], "}" => [144, "b"], "~" => [152, "b"], "" => [11, "b"], "\x80" => [0, "d0"], "\x81" => [0, "d1"], "\x82" => [0, "d2"], "\x83" => [0, "da"], "\x84" => [0, "dc"], "\x85" => [0, "de"], "\x86" => [0, "di"], "\x87" => [0, "do"], "\x88" => [0, "ds"], "\x89" => [0, "dt"], "\x8a" => [73, "d"], "\x8b" => [88, "d"], "\x8c" => [89, "d"], "\x8d" => [96, "d"], "\x8e" => [97, "d"], "\x8f" => [99, "d"], "\x90" => [106, "d"], "\x91" => [136, "d"], "\x92" => [139, "d"], "\x93" => [141, "d"], "\x94" => [145, "d"], "\x95" => [147, "d"], "\x96" => [149, "d"], "\x97" => [101, "d"], "\x98" => [112, "d"], "\x99" => [117, "d"], "\x9a" => [120, "d"], "\x9b" => [124, "d"], "\x9c" => [127, "d"], "\x9d" => [144, "d"], "\x9e" => [152, "d"], "\x9f" => [11, "d"], "\xa0" => [0, "f0"], "\xa1" => [0, "f1"], "\xa2" => [0, "f2"], "\xa3" => [0, "fa"], "\xa4" => [0, "fc"], "\xa5" => [0, "fe"], "\xa6" => [0, "fi"], "\xa7" => [0, "fo"], "\xa8" => [0, "fs"], "\xa9" => [0, "ft"], "\xaa" => [73, "f"], "\xab" => [88, "f"], "\xac" => [89, "f"], "\xad" => [96, "f"], "\xae" => [97, "f"], "\xaf" => [99, "f"], "\xb0" => [106, "f"], "\xb1" => [136, "f"], "\xb2" => [139, "f"], "\xb3" => [141, "f"], "\xb4" => [145, "f"], "\xb5" => [147, "f"], "\xb6" => [149, "f"], "\xb7" => [101, "f"], "\xb8" => [112, "f"], "\xb9" => [117, "f"], "\xba" => [120, "f"], "\xbb" => [124, "f"], "\xbc" => [127, "f"], "\xbd" => [144, "f"], "\xbe" => [152, "f"], "\xbf" => [11, "f"], "\xc0" => [0, "g0"], "\xc1" => [0, "g1"], "\xc2" => [0, "g2"], "\xc3" => [0, "ga"], "\xc4" => [0, "gc"], "\xc5" => [0, "ge"], "\xc6" => [0, "gi"], "\xc7" => [0, "go"], "\xc8" => [0, "gs"], "\xc9" => [0, "gt"], "\xca" => [73, "g"], "\xcb" => [88, "g"], "\xcc" => [89, "g"], "\xcd" => [96, "g"], "\xce" => [97, "g"], "\xcf" => [99, "g"], "\xd0" => [106, "g"], "\xd1" => [136, "g"], "\xd2" => [139, "g"], "\xd3" => [141, "g"], "\xd4" => [145, "g"], "\xd5" => [147, "g"], "\xd6" => [149, "g"], "\xd7" => [101, "g"], "\xd8" => [112, "g"], "\xd9" => [117, "g"], "\xda" => [120, "g"], "\xdb" => [124, "g"], "\xdc" => [127, "g"], "\xdd" => [144, "g"], "\xde" => [152, "g"], "\xdf" => [11, "g"], "\xe0" => [0, "h0"], "\xe1" => [0, "h1"], "\xe2" => [0, "h2"], "\xe3" => [0, "ha"], "\xe4" => [0, "hc"], "\xe5" => [0, "he"], "\xe6" => [0, "hi"], "\xe7" => [0, "ho"], "\xe8" => [0, "hs"], "\xe9" => [0, "ht"], "\xea" => [73, "h"], "\xeb" => [88, "h"], "\xec" => [89, "h"], "\xed" => [96, "h"], "\xee" => [97, "h"], "\xef" => [99, "h"], "\xf0" => [106, "h"], "\xf1" => [136, "h"], "\xf2" => [139, "h"], "\xf3" => [141, "h"], "\xf4" => [145, "h"], "\xf5" => [147, "h"], "\xf6" => [149, "h"], "\xf7" => [101, "h"], "\xf8" => [112, "h"], "\xf9" => [117, "h"], "\xfa" => [120, "h"], "\xfb" => [124, "h"], "\xfc" => [127, "h"], "\xfd" => [144, "h"], "\xfe" => [152, "h"], "\xff" => [11, "h"]], ["\x00" => [94, "@0"], "\x01" => [76, "@0"], "\x02" => [104, "@0"], "\x03" => [16, "@0"], "\x04" => [94, "@1"], "\x05" => [76, "@1"], "\x06" => [104, "@1"], "\x07" => [16, "@1"], "\x08" => [94, "@2"], "\t" => [76, "@2"], "\n" => [104, "@2"], "\v" => [16, "@2"], "\f" => [94, "@a"], "\r" => [76, "@a"], "\x0e" => [104, "@a"], "\x0f" => [16, "@a"], "\x10" => [94, "@c"], "\x11" => [76, "@c"], "\x12" => [104, "@c"], "\x13" => [16, "@c"], "\x14" => [94, "@e"], "\x15" => [76, "@e"], "\x16" => [104, "@e"], "\x17" => [16, "@e"], "\x18" => [94, "@i"], "\x19" => [76, "@i"], "\x1a" => [104, "@i"], "\x1b" => [16, "@i"], "\x1c" => [94, "@o"], "\x1d" => [76, "@o"], "\x1e" => [104, "@o"], "\x1f" => [16, "@o"], " " => [94, "@s"], "!" => [76, "@s"], "\"" => [104, "@s"], "#" => [16, "@s"], "\$" => [94, "@t"], "%" => [76, "@t"], "&" => [104, "@t"], "'" => [16, "@t"], "(" => [77, "@ "], ")" => [18, "@ "], "*" => [77, "@%"], "+" => [18, "@%"], "," => [77, "@-"], "-" => [18, "@-"], "." => [77, "@."], "/" => [18, "@."], [77, "@/"], [18, "@/"], [77, "@3"], [18, "@3"], [77, "@4"], [18, "@4"], [77, "@5"], [18, "@5"], [77, "@6"], [18, "@6"], ":" => [77, "@7"], ";" => [18, "@7"], "<" => [77, "@8"], "=" => [18, "@8"], ">" => [77, "@9"], "?" => [18, "@9"], "@" => [77, "@="], "A" => [18, "@="], "B" => [77, "@A"], "C" => [18, "@A"], "D" => [77, "@_"], "E" => [18, "@_"], "F" => [77, "@b"], "G" => [18, "@b"], "H" => [77, "@d"], "I" => [18, "@d"], "J" => [77, "@f"], "K" => [18, "@f"], "L" => [77, "@g"], "M" => [18, "@g"], "N" => [77, "@h"], "O" => [18, "@h"], "P" => [77, "@l"], "Q" => [18, "@l"], "R" => [77, "@m"], "S" => [18, "@m"], "T" => [77, "@n"], "U" => [18, "@n"], "V" => [77, "@p"], "W" => [18, "@p"], "X" => [77, "@r"], "Y" => [18, "@r"], "Z" => [77, "@u"], "[" => [18, "@u"], "\\" => [0, "@:"], "]" => [0, "@B"], "^" => [0, "@C"], "_" => [0, "@D"], "`" => [0, "@E"], "a" => [0, "@F"], "b" => [0, "@G"], "c" => [0, "@H"], "d" => [0, "@I"], "e" => [0, "@J"], "f" => [0, "@K"], "g" => [0, "@L"], "h" => [0, "@M"], "i" => [0, "@N"], "j" => [0, "@O"], "k" => [0, "@P"], "l" => [0, "@Q"], "m" => [0, "@R"], "n" => [0, "@S"], "o" => [0, "@T"], "p" => [0, "@U"], "q" => [0, "@V"], "r" => [0, "@W"], "s" => [0, "@Y"], "t" => [0, "@j"], "u" => [0, "@k"], "v" => [0, "@q"], "w" => [0, "@v"], "x" => [0, "@w"], "y" => [0, "@x"], "z" => [0, "@y"], "{" => [0, "@z"], "|" => [82, "@"], "}" => [87, "@"], "~" => [130, "@"], "" => [9, "@"], "\x80" => [94, "[0"], "\x81" => [76, "[0"], "\x82" => [104, "[0"], "\x83" => [16, "[0"], "\x84" => [94, "[1"], "\x85" => [76, "[1"], "\x86" => [104, "[1"], "\x87" => [16, "[1"], "\x88" => [94, "[2"], "\x89" => [76, "[2"], "\x8a" => [104, "[2"], "\x8b" => [16, "[2"], "\x8c" => [94, "[a"], "\x8d" => [76, "[a"], "\x8e" => [104, "[a"], "\x8f" => [16, "[a"], "\x90" => [94, "[c"], "\x91" => [76, "[c"], "\x92" => [104, "[c"], "\x93" => [16, "[c"], "\x94" => [94, "[e"], "\x95" => [76, "[e"], "\x96" => [104, "[e"], "\x97" => [16, "[e"], "\x98" => [94, "[i"], "\x99" => [76, "[i"], "\x9a" => [104, "[i"], "\x9b" => [16, "[i"], "\x9c" => [94, "[o"], "\x9d" => [76, "[o"], "\x9e" => [104, "[o"], "\x9f" => [16, "[o"], "\xa0" => [94, "[s"], "\xa1" => [76, "[s"], "\xa2" => [104, "[s"], "\xa3" => [16, "[s"], "\xa4" => [94, "[t"], "\xa5" => [76, "[t"], "\xa6" => [104, "[t"], "\xa7" => [16, "[t"], "\xa8" => [77, "[ "], "\xa9" => [18, "[ "], "\xaa" => [77, "[%"], "\xab" => [18, "[%"], "\xac" => [77, "[-"], "\xad" => [18, "[-"], "\xae" => [77, "[."], "\xaf" => [18, "[."], "\xb0" => [77, "[/"], "\xb1" => [18, "[/"], "\xb2" => [77, "[3"], "\xb3" => [18, "[3"], "\xb4" => [77, "[4"], "\xb5" => [18, "[4"], "\xb6" => [77, "[5"], "\xb7" => [18, "[5"], "\xb8" => [77, "[6"], "\xb9" => [18, "[6"], "\xba" => [77, "[7"], "\xbb" => [18, "[7"], "\xbc" => [77, "[8"], "\xbd" => [18, "[8"], "\xbe" => [77, "[9"], "\xbf" => [18, "[9"], "\xc0" => [77, "[="], "\xc1" => [18, "[="], "\xc2" => [77, "[A"], "\xc3" => [18, "[A"], "\xc4" => [77, "[_"], "\xc5" => [18, "[_"], "\xc6" => [77, "[b"], "\xc7" => [18, "[b"], "\xc8" => [77, "[d"], "\xc9" => [18, "[d"], "\xca" => [77, "[f"], "\xcb" => [18, "[f"], "\xcc" => [77, "[g"], "\xcd" => [18, "[g"], "\xce" => [77, "[h"], "\xcf" => [18, "[h"], "\xd0" => [77, "[l"], "\xd1" => [18, "[l"], "\xd2" => [77, "[m"], "\xd3" => [18, "[m"], "\xd4" => [77, "[n"], "\xd5" => [18, "[n"], "\xd6" => [77, "[p"], "\xd7" => [18, "[p"], "\xd8" => [77, "[r"], "\xd9" => [18, "[r"], "\xda" => [77, "[u"], "\xdb" => [18, "[u"], "\xdc" => [0, "[:"], "\xdd" => [0, "[B"], "\xde" => [0, "[C"], "\xdf" => [0, "[D"], "\xe0" => [0, "[E"], "\xe1" => [0, "[F"], "\xe2" => [0, "[G"], "\xe3" => [0, "[H"], "\xe4" => [0, "[I"], "\xe5" => [0, "[J"], "\xe6" => [0, "[K"], "\xe7" => [0, "[L"], "\xe8" => [0, "[M"], "\xe9" => [0, "[N"], "\xea" => [0, "[O"], "\xeb" => [0, "[P"], "\xec" => [0, "[Q"], "\xed" => [0, "[R"], "\xee" => [0, "[S"], "\xef" => [0, "[T"], "\xf0" => [0, "[U"], "\xf1" => [0, "[V"], "\xf2" => [0, "[W"], "\xf3" => [0, "[Y"], "\xf4" => [0, "[j"], "\xf5" => [0, "[k"], "\xf6" => [0, "[q"], "\xf7" => [0, "[v"], "\xf8" => [0, "[w"], "\xf9" => [0, "[x"], "\xfa" => [0, "[y"], "\xfb" => [0, "[z"], "\xfc" => [82, "["], "\xfd" => [87, "["], "\xfe" => [130, "["], "\xff" => [9, "["]], ["\x00" => [94, "C0"], "\x01" => [76, "C0"], "\x02" => [104, "C0"], "\x03" => [16, "C0"], "\x04" => [94, "C1"], "\x05" => [76, "C1"], "\x06" => [104, "C1"], "\x07" => [16, "C1"], "\x08" => [94, "C2"], "\t" => [76, "C2"], "\n" => [104, "C2"], "\v" => [16, "C2"], "\f" => [94, "Ca"], "\r" => [76, "Ca"], "\x0e" => [104, "Ca"], "\x0f" => [16, "Ca"], "\x10" => [94, "Cc"], "\x11" => [76, "Cc"], "\x12" => [104, "Cc"], "\x13" => [16, "Cc"], "\x14" => [94, "Ce"], "\x15" => [76, "Ce"], "\x16" => [104, "Ce"], "\x17" => [16, "Ce"], "\x18" => [94, "Ci"], "\x19" => [76, "Ci"], "\x1a" => [104, "Ci"], "\x1b" => [16, "Ci"], "\x1c" => [94, "Co"], "\x1d" => [76, "Co"], "\x1e" => [104, "Co"], "\x1f" => [16, "Co"], " " => [94, "Cs"], "!" => [76, "Cs"], "\"" => [104, "Cs"], "#" => [16, "Cs"], "\$" => [94, "Ct"], "%" => [76, "Ct"], "&" => [104, "Ct"], "'" => [16, "Ct"], "(" => [77, "C "], ")" => [18, "C "], "*" => [77, "C%"], "+" => [18, "C%"], "," => [77, "C-"], "-" => [18, "C-"], "." => [77, "C."], "/" => [18, "C."], [77, "C/"], [18, "C/"], [77, "C3"], [18, "C3"], [77, "C4"], [18, "C4"], [77, "C5"], [18, "C5"], [77, "C6"], [18, "C6"], ":" => [77, "C7"], ";" => [18, "C7"], "<" => [77, "C8"], "=" => [18, "C8"], ">" => [77, "C9"], "?" => [18, "C9"], "@" => [77, "C="], "A" => [18, "C="], "B" => [77, "CA"], "C" => [18, "CA"], "D" => [77, "C_"], "E" => [18, "C_"], "F" => [77, "Cb"], "G" => [18, "Cb"], "H" => [77, "Cd"], "I" => [18, "Cd"], "J" => [77, "Cf"], "K" => [18, "Cf"], "L" => [77, "Cg"], "M" => [18, "Cg"], "N" => [77, "Ch"], "O" => [18, "Ch"], "P" => [77, "Cl"], "Q" => [18, "Cl"], "R" => [77, "Cm"], "S" => [18, "Cm"], "T" => [77, "Cn"], "U" => [18, "Cn"], "V" => [77, "Cp"], "W" => [18, "Cp"], "X" => [77, "Cr"], "Y" => [18, "Cr"], "Z" => [77, "Cu"], "[" => [18, "Cu"], "\\" => [0, "C:"], "]" => [0, "CB"], "^" => [0, "CC"], "_" => [0, "CD"], "`" => [0, "CE"], "a" => [0, "CF"], "b" => [0, "CG"], "c" => [0, "CH"], "d" => [0, "CI"], "e" => [0, "CJ"], "f" => [0, "CK"], "g" => [0, "CL"], "h" => [0, "CM"], "i" => [0, "CN"], "j" => [0, "CO"], "k" => [0, "CP"], "l" => [0, "CQ"], "m" => [0, "CR"], "n" => [0, "CS"], "o" => [0, "CT"], "p" => [0, "CU"], "q" => [0, "CV"], "r" => [0, "CW"], "s" => [0, "CY"], "t" => [0, "Cj"], "u" => [0, "Ck"], "v" => [0, "Cq"], "w" => [0, "Cv"], "x" => [0, "Cw"], "y" => [0, "Cx"], "z" => [0, "Cy"], "{" => [0, "Cz"], "|" => [82, "C"], "}" => [87, "C"], "~" => [130, "C"], "" => [9, "C"], "\x80" => [94, "D0"], "\x81" => [76, "D0"], "\x82" => [104, "D0"], "\x83" => [16, "D0"], "\x84" => [94, "D1"], "\x85" => [76, "D1"], "\x86" => [104, "D1"], "\x87" => [16, "D1"], "\x88" => [94, "D2"], "\x89" => [76, "D2"], "\x8a" => [104, "D2"], "\x8b" => [16, "D2"], "\x8c" => [94, "Da"], "\x8d" => [76, "Da"], "\x8e" => [104, "Da"], "\x8f" => [16, "Da"], "\x90" => [94, "Dc"], "\x91" => [76, "Dc"], "\x92" => [104, "Dc"], "\x93" => [16, "Dc"], "\x94" => [94, "De"], "\x95" => [76, "De"], "\x96" => [104, "De"], "\x97" => [16, "De"], "\x98" => [94, "Di"], "\x99" => [76, "Di"], "\x9a" => [104, "Di"], "\x9b" => [16, "Di"], "\x9c" => [94, "Do"], "\x9d" => [76, "Do"], "\x9e" => [104, "Do"], "\x9f" => [16, "Do"], "\xa0" => [94, "Ds"], "\xa1" => [76, "Ds"], "\xa2" => [104, "Ds"], "\xa3" => [16, "Ds"], "\xa4" => [94, "Dt"], "\xa5" => [76, "Dt"], "\xa6" => [104, "Dt"], "\xa7" => [16, "Dt"], "\xa8" => [77, "D "], "\xa9" => [18, "D "], "\xaa" => [77, "D%"], "\xab" => [18, "D%"], "\xac" => [77, "D-"], "\xad" => [18, "D-"], "\xae" => [77, "D."], "\xaf" => [18, "D."], "\xb0" => [77, "D/"], "\xb1" => [18, "D/"], "\xb2" => [77, "D3"], "\xb3" => [18, "D3"], "\xb4" => [77, "D4"], "\xb5" => [18, "D4"], "\xb6" => [77, "D5"], "\xb7" => [18, "D5"], "\xb8" => [77, "D6"], "\xb9" => [18, "D6"], "\xba" => [77, "D7"], "\xbb" => [18, "D7"], "\xbc" => [77, "D8"], "\xbd" => [18, "D8"], "\xbe" => [77, "D9"], "\xbf" => [18, "D9"], "\xc0" => [77, "D="], "\xc1" => [18, "D="], "\xc2" => [77, "DA"], "\xc3" => [18, "DA"], "\xc4" => [77, "D_"], "\xc5" => [18, "D_"], "\xc6" => [77, "Db"], "\xc7" => [18, "Db"], "\xc8" => [77, "Dd"], "\xc9" => [18, "Dd"], "\xca" => [77, "Df"], "\xcb" => [18, "Df"], "\xcc" => [77, "Dg"], "\xcd" => [18, "Dg"], "\xce" => [77, "Dh"], "\xcf" => [18, "Dh"], "\xd0" => [77, "Dl"], "\xd1" => [18, "Dl"], "\xd2" => [77, "Dm"], "\xd3" => [18, "Dm"], "\xd4" => [77, "Dn"], "\xd5" => [18, "Dn"], "\xd6" => [77, "Dp"], "\xd7" => [18, "Dp"], "\xd8" => [77, "Dr"], "\xd9" => [18, "Dr"], "\xda" => [77, "Du"], "\xdb" => [18, "Du"], "\xdc" => [0, "D:"], "\xdd" => [0, "DB"], "\xde" => [0, "DC"], "\xdf" => [0, "DD"], "\xe0" => [0, "DE"], "\xe1" => [0, "DF"], "\xe2" => [0, "DG"], "\xe3" => [0, "DH"], "\xe4" => [0, "DI"], "\xe5" => [0, "DJ"], "\xe6" => [0, "DK"], "\xe7" => [0, "DL"], "\xe8" => [0, "DM"], "\xe9" => [0, "DN"], "\xea" => [0, "DO"], "\xeb" => [0, "DP"], "\xec" => [0, "DQ"], "\xed" => [0, "DR"], "\xee" => [0, "DS"], "\xef" => [0, "DT"], "\xf0" => [0, "DU"], "\xf1" => [0, "DV"], "\xf2" => [0, "DW"], "\xf3" => [0, "DY"], "\xf4" => [0, "Dj"], "\xf5" => [0, "Dk"], "\xf6" => [0, "Dq"], "\xf7" => [0, "Dv"], "\xf8" => [0, "Dw"], "\xf9" => [0, "Dx"], "\xfa" => [0, "Dy"], "\xfb" => [0, "Dz"], "\xfc" => [82, "D"], "\xfd" => [87, "D"], "\xfe" => [130, "D"], "\xff" => [9, "D"]], ["\x00" => [94, "E0"], "\x01" => [76, "E0"], "\x02" => [104, "E0"], "\x03" => [16, "E0"], "\x04" => [94, "E1"], "\x05" => [76, "E1"], "\x06" => [104, "E1"], "\x07" => [16, "E1"], "\x08" => [94, "E2"], "\t" => [76, "E2"], "\n" => [104, "E2"], "\v" => [16, "E2"], "\f" => [94, "Ea"], "\r" => [76, "Ea"], "\x0e" => [104, "Ea"], "\x0f" => [16, "Ea"], "\x10" => [94, "Ec"], "\x11" => [76, "Ec"], "\x12" => [104, "Ec"], "\x13" => [16, "Ec"], "\x14" => [94, "Ee"], "\x15" => [76, "Ee"], "\x16" => [104, "Ee"], "\x17" => [16, "Ee"], "\x18" => [94, "Ei"], "\x19" => [76, "Ei"], "\x1a" => [104, "Ei"], "\x1b" => [16, "Ei"], "\x1c" => [94, "Eo"], "\x1d" => [76, "Eo"], "\x1e" => [104, "Eo"], "\x1f" => [16, "Eo"], " " => [94, "Es"], "!" => [76, "Es"], "\"" => [104, "Es"], "#" => [16, "Es"], "\$" => [94, "Et"], "%" => [76, "Et"], "&" => [104, "Et"], "'" => [16, "Et"], "(" => [77, "E "], ")" => [18, "E "], "*" => [77, "E%"], "+" => [18, "E%"], "," => [77, "E-"], "-" => [18, "E-"], "." => [77, "E."], "/" => [18, "E."], [77, "E/"], [18, "E/"], [77, "E3"], [18, "E3"], [77, "E4"], [18, "E4"], [77, "E5"], [18, "E5"], [77, "E6"], [18, "E6"], ":" => [77, "E7"], ";" => [18, "E7"], "<" => [77, "E8"], "=" => [18, "E8"], ">" => [77, "E9"], "?" => [18, "E9"], "@" => [77, "E="], "A" => [18, "E="], "B" => [77, "EA"], "C" => [18, "EA"], "D" => [77, "E_"], "E" => [18, "E_"], "F" => [77, "Eb"], "G" => [18, "Eb"], "H" => [77, "Ed"], "I" => [18, "Ed"], "J" => [77, "Ef"], "K" => [18, "Ef"], "L" => [77, "Eg"], "M" => [18, "Eg"], "N" => [77, "Eh"], "O" => [18, "Eh"], "P" => [77, "El"], "Q" => [18, "El"], "R" => [77, "Em"], "S" => [18, "Em"], "T" => [77, "En"], "U" => [18, "En"], "V" => [77, "Ep"], "W" => [18, "Ep"], "X" => [77, "Er"], "Y" => [18, "Er"], "Z" => [77, "Eu"], "[" => [18, "Eu"], "\\" => [0, "E:"], "]" => [0, "EB"], "^" => [0, "EC"], "_" => [0, "ED"], "`" => [0, "EE"], "a" => [0, "EF"], "b" => [0, "EG"], "c" => [0, "EH"], "d" => [0, "EI"], "e" => [0, "EJ"], "f" => [0, "EK"], "g" => [0, "EL"], "h" => [0, "EM"], "i" => [0, "EN"], "j" => [0, "EO"], "k" => [0, "EP"], "l" => [0, "EQ"], "m" => [0, "ER"], "n" => [0, "ES"], "o" => [0, "ET"], "p" => [0, "EU"], "q" => [0, "EV"], "r" => [0, "EW"], "s" => [0, "EY"], "t" => [0, "Ej"], "u" => [0, "Ek"], "v" => [0, "Eq"], "w" => [0, "Ev"], "x" => [0, "Ew"], "y" => [0, "Ex"], "z" => [0, "Ey"], "{" => [0, "Ez"], "|" => [82, "E"], "}" => [87, "E"], "~" => [130, "E"], "" => [9, "E"], "\x80" => [94, "F0"], "\x81" => [76, "F0"], "\x82" => [104, "F0"], "\x83" => [16, "F0"], "\x84" => [94, "F1"], "\x85" => [76, "F1"], "\x86" => [104, "F1"], "\x87" => [16, "F1"], "\x88" => [94, "F2"], "\x89" => [76, "F2"], "\x8a" => [104, "F2"], "\x8b" => [16, "F2"], "\x8c" => [94, "Fa"], "\x8d" => [76, "Fa"], "\x8e" => [104, "Fa"], "\x8f" => [16, "Fa"], "\x90" => [94, "Fc"], "\x91" => [76, "Fc"], "\x92" => [104, "Fc"], "\x93" => [16, "Fc"], "\x94" => [94, "Fe"], "\x95" => [76, "Fe"], "\x96" => [104, "Fe"], "\x97" => [16, "Fe"], "\x98" => [94, "Fi"], "\x99" => [76, "Fi"], "\x9a" => [104, "Fi"], "\x9b" => [16, "Fi"], "\x9c" => [94, "Fo"], "\x9d" => [76, "Fo"], "\x9e" => [104, "Fo"], "\x9f" => [16, "Fo"], "\xa0" => [94, "Fs"], "\xa1" => [76, "Fs"], "\xa2" => [104, "Fs"], "\xa3" => [16, "Fs"], "\xa4" => [94, "Ft"], "\xa5" => [76, "Ft"], "\xa6" => [104, "Ft"], "\xa7" => [16, "Ft"], "\xa8" => [77, "F "], "\xa9" => [18, "F "], "\xaa" => [77, "F%"], "\xab" => [18, "F%"], "\xac" => [77, "F-"], "\xad" => [18, "F-"], "\xae" => [77, "F."], "\xaf" => [18, "F."], "\xb0" => [77, "F/"], "\xb1" => [18, "F/"], "\xb2" => [77, "F3"], "\xb3" => [18, "F3"], "\xb4" => [77, "F4"], "\xb5" => [18, "F4"], "\xb6" => [77, "F5"], "\xb7" => [18, "F5"], "\xb8" => [77, "F6"], "\xb9" => [18, "F6"], "\xba" => [77, "F7"], "\xbb" => [18, "F7"], "\xbc" => [77, "F8"], "\xbd" => [18, "F8"], "\xbe" => [77, "F9"], "\xbf" => [18, "F9"], "\xc0" => [77, "F="], "\xc1" => [18, "F="], "\xc2" => [77, "FA"], "\xc3" => [18, "FA"], "\xc4" => [77, "F_"], "\xc5" => [18, "F_"], "\xc6" => [77, "Fb"], "\xc7" => [18, "Fb"], "\xc8" => [77, "Fd"], "\xc9" => [18, "Fd"], "\xca" => [77, "Ff"], "\xcb" => [18, "Ff"], "\xcc" => [77, "Fg"], "\xcd" => [18, "Fg"], "\xce" => [77, "Fh"], "\xcf" => [18, "Fh"], "\xd0" => [77, "Fl"], "\xd1" => [18, "Fl"], "\xd2" => [77, "Fm"], "\xd3" => [18, "Fm"], "\xd4" => [77, "Fn"], "\xd5" => [18, "Fn"], "\xd6" => [77, "Fp"], "\xd7" => [18, "Fp"], "\xd8" => [77, "Fr"], "\xd9" => [18, "Fr"], "\xda" => [77, "Fu"], "\xdb" => [18, "Fu"], "\xdc" => [0, "F:"], "\xdd" => [0, "FB"], "\xde" => [0, "FC"], "\xdf" => [0, "FD"], "\xe0" => [0, "FE"], "\xe1" => [0, "FF"], "\xe2" => [0, "FG"], "\xe3" => [0, "FH"], "\xe4" => [0, "FI"], "\xe5" => [0, "FJ"], "\xe6" => [0, "FK"], "\xe7" => [0, "FL"], "\xe8" => [0, "FM"], "\xe9" => [0, "FN"], "\xea" => [0, "FO"], "\xeb" => [0, "FP"], "\xec" => [0, "FQ"], "\xed" => [0, "FR"], "\xee" => [0, "FS"], "\xef" => [0, "FT"], "\xf0" => [0, "FU"], "\xf1" => [0, "FV"], "\xf2" => [0, "FW"], "\xf3" => [0, "FY"], "\xf4" => [0, "Fj"], "\xf5" => [0, "Fk"], "\xf6" => [0, "Fq"], "\xf7" => [0, "Fv"], "\xf8" => [0, "Fw"], "\xf9" => [0, "Fx"], "\xfa" => [0, "Fy"], "\xfb" => [0, "Fz"], "\xfc" => [82, "F"], "\xfd" => [87, "F"], "\xfe" => [130, "F"], "\xff" => [9, "F"]], ["\x00" => [77, "E0"], "\x01" => [18, "E0"], "\x02" => [77, "E1"], "\x03" => [18, "E1"], "\x04" => [77, "E2"], "\x05" => [18, "E2"], "\x06" => [77, "Ea"], "\x07" => [18, "Ea"], "\x08" => [77, "Ec"], "\t" => [18, "Ec"], "\n" => [77, "Ee"], "\v" => [18, "Ee"], "\f" => [77, "Ei"], "\r" => [18, "Ei"], "\x0e" => [77, "Eo"], "\x0f" => [18, "Eo"], "\x10" => [77, "Es"], "\x11" => [18, "Es"], "\x12" => [77, "Et"], "\x13" => [18, "Et"], "\x14" => [0, "E "], "\x15" => [0, "E%"], "\x16" => [0, "E-"], "\x17" => [0, "E."], "\x18" => [0, "E/"], "\x19" => [0, "E3"], "\x1a" => [0, "E4"], "\x1b" => [0, "E5"], "\x1c" => [0, "E6"], "\x1d" => [0, "E7"], "\x1e" => [0, "E8"], "\x1f" => [0, "E9"], " " => [0, "E="], "!" => [0, "EA"], "\"" => [0, "E_"], "#" => [0, "Eb"], "\$" => [0, "Ed"], "%" => [0, "Ef"], "&" => [0, "Eg"], "'" => [0, "Eh"], "(" => [0, "El"], ")" => [0, "Em"], "*" => [0, "En"], "+" => [0, "Ep"], "," => [0, "Er"], "-" => [0, "Eu"], "." => [100, "E"], "/" => [110, "E"], [111, "E"], [115, "E"], [116, "E"], [118, "E"], [119, "E"], [122, "E"], [123, "E"], [125, "E"], [126, "E"], [129, "E"], ":" => [143, "E"], ";" => [148, "E"], "<" => [151, "E"], "=" => [153, "E"], ">" => [83, "E"], "?" => [10, "E"], "@" => [77, "F0"], "A" => [18, "F0"], "B" => [77, "F1"], "C" => [18, "F1"], "D" => [77, "F2"], "E" => [18, "F2"], "F" => [77, "Fa"], "G" => [18, "Fa"], "H" => [77, "Fc"], "I" => [18, "Fc"], "J" => [77, "Fe"], "K" => [18, "Fe"], "L" => [77, "Fi"], "M" => [18, "Fi"], "N" => [77, "Fo"], "O" => [18, "Fo"], "P" => [77, "Fs"], "Q" => [18, "Fs"], "R" => [77, "Ft"], "S" => [18, "Ft"], "T" => [0, "F "], "U" => [0, "F%"], "V" => [0, "F-"], "W" => [0, "F."], "X" => [0, "F/"], "Y" => [0, "F3"], "Z" => [0, "F4"], "[" => [0, "F5"], "\\" => [0, "F6"], "]" => [0, "F7"], "^" => [0, "F8"], "_" => [0, "F9"], "`" => [0, "F="], "a" => [0, "FA"], "b" => [0, "F_"], "c" => [0, "Fb"], "d" => [0, "Fd"], "e" => [0, "Ff"], "f" => [0, "Fg"], "g" => [0, "Fh"], "h" => [0, "Fl"], "i" => [0, "Fm"], "j" => [0, "Fn"], "k" => [0, "Fp"], "l" => [0, "Fr"], "m" => [0, "Fu"], "n" => [100, "F"], "o" => [110, "F"], "p" => [111, "F"], "q" => [115, "F"], "r" => [116, "F"], "s" => [118, "F"], "t" => [119, "F"], "u" => [122, "F"], "v" => [123, "F"], "w" => [125, "F"], "x" => [126, "F"], "y" => [129, "F"], "z" => [143, "F"], "{" => [148, "F"], "|" => [151, "F"], "}" => [153, "F"], "~" => [83, "F"], "" => [10, "F"], "\x80" => [77, "G0"], "\x81" => [18, "G0"], "\x82" => [77, "G1"], "\x83" => [18, "G1"], "\x84" => [77, "G2"], "\x85" => [18, "G2"], "\x86" => [77, "Ga"], "\x87" => [18, "Ga"], "\x88" => [77, "Gc"], "\x89" => [18, "Gc"], "\x8a" => [77, "Ge"], "\x8b" => [18, "Ge"], "\x8c" => [77, "Gi"], "\x8d" => [18, "Gi"], "\x8e" => [77, "Go"], "\x8f" => [18, "Go"], "\x90" => [77, "Gs"], "\x91" => [18, "Gs"], "\x92" => [77, "Gt"], "\x93" => [18, "Gt"], "\x94" => [0, "G "], "\x95" => [0, "G%"], "\x96" => [0, "G-"], "\x97" => [0, "G."], "\x98" => [0, "G/"], "\x99" => [0, "G3"], "\x9a" => [0, "G4"], "\x9b" => [0, "G5"], "\x9c" => [0, "G6"], "\x9d" => [0, "G7"], "\x9e" => [0, "G8"], "\x9f" => [0, "G9"], "\xa0" => [0, "G="], "\xa1" => [0, "GA"], "\xa2" => [0, "G_"], "\xa3" => [0, "Gb"], "\xa4" => [0, "Gd"], "\xa5" => [0, "Gf"], "\xa6" => [0, "Gg"], "\xa7" => [0, "Gh"], "\xa8" => [0, "Gl"], "\xa9" => [0, "Gm"], "\xaa" => [0, "Gn"], "\xab" => [0, "Gp"], "\xac" => [0, "Gr"], "\xad" => [0, "Gu"], "\xae" => [100, "G"], "\xaf" => [110, "G"], "\xb0" => [111, "G"], "\xb1" => [115, "G"], "\xb2" => [116, "G"], "\xb3" => [118, "G"], "\xb4" => [119, "G"], "\xb5" => [122, "G"], "\xb6" => [123, "G"], "\xb7" => [125, "G"], "\xb8" => [126, "G"], "\xb9" => [129, "G"], "\xba" => [143, "G"], "\xbb" => [148, "G"], "\xbc" => [151, "G"], "\xbd" => [153, "G"], "\xbe" => [83, "G"], "\xbf" => [10, "G"], "\xc0" => [77, "H0"], "\xc1" => [18, "H0"], "\xc2" => [77, "H1"], "\xc3" => [18, "H1"], "\xc4" => [77, "H2"], "\xc5" => [18, "H2"], "\xc6" => [77, "Ha"], "\xc7" => [18, "Ha"], "\xc8" => [77, "Hc"], "\xc9" => [18, "Hc"], "\xca" => [77, "He"], "\xcb" => [18, "He"], "\xcc" => [77, "Hi"], "\xcd" => [18, "Hi"], "\xce" => [77, "Ho"], "\xcf" => [18, "Ho"], "\xd0" => [77, "Hs"], "\xd1" => [18, "Hs"], "\xd2" => [77, "Ht"], "\xd3" => [18, "Ht"], "\xd4" => [0, "H "], "\xd5" => [0, "H%"], "\xd6" => [0, "H-"], "\xd7" => [0, "H."], "\xd8" => [0, "H/"], "\xd9" => [0, "H3"], "\xda" => [0, "H4"], "\xdb" => [0, "H5"], "\xdc" => [0, "H6"], "\xdd" => [0, "H7"], "\xde" => [0, "H8"], "\xdf" => [0, "H9"], "\xe0" => [0, "H="], "\xe1" => [0, "HA"], "\xe2" => [0, "H_"], "\xe3" => [0, "Hb"], "\xe4" => [0, "Hd"], "\xe5" => [0, "Hf"], "\xe6" => [0, "Hg"], "\xe7" => [0, "Hh"], "\xe8" => [0, "Hl"], "\xe9" => [0, "Hm"], "\xea" => [0, "Hn"], "\xeb" => [0, "Hp"], "\xec" => [0, "Hr"], "\xed" => [0, "Hu"], "\xee" => [100, "H"], "\xef" => [110, "H"], "\xf0" => [111, "H"], "\xf1" => [115, "H"], "\xf2" => [116, "H"], "\xf3" => [118, "H"], "\xf4" => [119, "H"], "\xf5" => [122, "H"], "\xf6" => [123, "H"], "\xf7" => [125, "H"], "\xf8" => [126, "H"], "\xf9" => [129, "H"], "\xfa" => [143, "H"], "\xfb" => [148, "H"], "\xfc" => [151, "H"], "\xfd" => [153, "H"], "\xfe" => [83, "H"], "\xff" => [10, "H"]], ["\x00" => [0, "E0"], "\x01" => [0, "E1"], "\x02" => [0, "E2"], "\x03" => [0, "Ea"], "\x04" => [0, "Ec"], "\x05" => [0, "Ee"], "\x06" => [0, "Ei"], "\x07" => [0, "Eo"], "\x08" => [0, "Es"], "\t" => [0, "Et"], "\n" => [73, "E"], "\v" => [88, "E"], "\f" => [89, "E"], "\r" => [96, "E"], "\x0e" => [97, "E"], "\x0f" => [99, "E"], "\x10" => [106, "E"], "\x11" => [136, "E"], "\x12" => [139, "E"], "\x13" => [141, "E"], "\x14" => [145, "E"], "\x15" => [147, "E"], "\x16" => [149, "E"], "\x17" => [101, "E"], "\x18" => [112, "E"], "\x19" => [117, "E"], "\x1a" => [120, "E"], "\x1b" => [124, "E"], "\x1c" => [127, "E"], "\x1d" => [144, "E"], "\x1e" => [152, "E"], "\x1f" => [11, "E"], " " => [0, "F0"], "!" => [0, "F1"], "\"" => [0, "F2"], "#" => [0, "Fa"], "\$" => [0, "Fc"], "%" => [0, "Fe"], "&" => [0, "Fi"], "'" => [0, "Fo"], "(" => [0, "Fs"], ")" => [0, "Ft"], "*" => [73, "F"], "+" => [88, "F"], "," => [89, "F"], "-" => [96, "F"], "." => [97, "F"], "/" => [99, "F"], [106, "F"], [136, "F"], [139, "F"], [141, "F"], [145, "F"], [147, "F"], [149, "F"], [101, "F"], [112, "F"], [117, "F"], ":" => [120, "F"], ";" => [124, "F"], "<" => [127, "F"], "=" => [144, "F"], ">" => [152, "F"], "?" => [11, "F"], "@" => [0, "G0"], "A" => [0, "G1"], "B" => [0, "G2"], "C" => [0, "Ga"], "D" => [0, "Gc"], "E" => [0, "Ge"], "F" => [0, "Gi"], "G" => [0, "Go"], "H" => [0, "Gs"], "I" => [0, "Gt"], "J" => [73, "G"], "K" => [88, "G"], "L" => [89, "G"], "M" => [96, "G"], "N" => [97, "G"], "O" => [99, "G"], "P" => [106, "G"], "Q" => [136, "G"], "R" => [139, "G"], "S" => [141, "G"], "T" => [145, "G"], "U" => [147, "G"], "V" => [149, "G"], "W" => [101, "G"], "X" => [112, "G"], "Y" => [117, "G"], "Z" => [120, "G"], "[" => [124, "G"], "\\" => [127, "G"], "]" => [144, "G"], "^" => [152, "G"], "_" => [11, "G"], "`" => [0, "H0"], "a" => [0, "H1"], "b" => [0, "H2"], "c" => [0, "Ha"], "d" => [0, "Hc"], "e" => [0, "He"], "f" => [0, "Hi"], "g" => [0, "Ho"], "h" => [0, "Hs"], "i" => [0, "Ht"], "j" => [73, "H"], "k" => [88, "H"], "l" => [89, "H"], "m" => [96, "H"], "n" => [97, "H"], "o" => [99, "H"], "p" => [106, "H"], "q" => [136, "H"], "r" => [139, "H"], "s" => [141, "H"], "t" => [145, "H"], "u" => [147, "H"], "v" => [149, "H"], "w" => [101, "H"], "x" => [112, "H"], "y" => [117, "H"], "z" => [120, "H"], "{" => [124, "H"], "|" => [127, "H"], "}" => [144, "H"], "~" => [152, "H"], "" => [11, "H"], "\x80" => [0, "I0"], "\x81" => [0, "I1"], "\x82" => [0, "I2"], "\x83" => [0, "Ia"], "\x84" => [0, "Ic"], "\x85" => [0, "Ie"], "\x86" => [0, "Ii"], "\x87" => [0, "Io"], "\x88" => [0, "Is"], "\x89" => [0, "It"], "\x8a" => [73, "I"], "\x8b" => [88, "I"], "\x8c" => [89, "I"], "\x8d" => [96, "I"], "\x8e" => [97, "I"], "\x8f" => [99, "I"], "\x90" => [106, "I"], "\x91" => [136, "I"], "\x92" => [139, "I"], "\x93" => [141, "I"], "\x94" => [145, "I"], "\x95" => [147, "I"], "\x96" => [149, "I"], "\x97" => [101, "I"], "\x98" => [112, "I"], "\x99" => [117, "I"], "\x9a" => [120, "I"], "\x9b" => [124, "I"], "\x9c" => [127, "I"], "\x9d" => [144, "I"], "\x9e" => [152, "I"], "\x9f" => [11, "I"], "\xa0" => [0, "J0"], "\xa1" => [0, "J1"], "\xa2" => [0, "J2"], "\xa3" => [0, "Ja"], "\xa4" => [0, "Jc"], "\xa5" => [0, "Je"], "\xa6" => [0, "Ji"], "\xa7" => [0, "Jo"], "\xa8" => [0, "Js"], "\xa9" => [0, "Jt"], "\xaa" => [73, "J"], "\xab" => [88, "J"], "\xac" => [89, "J"], "\xad" => [96, "J"], "\xae" => [97, "J"], "\xaf" => [99, "J"], "\xb0" => [106, "J"], "\xb1" => [136, "J"], "\xb2" => [139, "J"], "\xb3" => [141, "J"], "\xb4" => [145, "J"], "\xb5" => [147, "J"], "\xb6" => [149, "J"], "\xb7" => [101, "J"], "\xb8" => [112, "J"], "\xb9" => [117, "J"], "\xba" => [120, "J"], "\xbb" => [124, "J"], "\xbc" => [127, "J"], "\xbd" => [144, "J"], "\xbe" => [152, "J"], "\xbf" => [11, "J"], "\xc0" => [0, "K0"], "\xc1" => [0, "K1"], "\xc2" => [0, "K2"], "\xc3" => [0, "Ka"], "\xc4" => [0, "Kc"], "\xc5" => [0, "Ke"], "\xc6" => [0, "Ki"], "\xc7" => [0, "Ko"], "\xc8" => [0, "Ks"], "\xc9" => [0, "Kt"], "\xca" => [73, "K"], "\xcb" => [88, "K"], "\xcc" => [89, "K"], "\xcd" => [96, "K"], "\xce" => [97, "K"], "\xcf" => [99, "K"], "\xd0" => [106, "K"], "\xd1" => [136, "K"], "\xd2" => [139, "K"], "\xd3" => [141, "K"], "\xd4" => [145, "K"], "\xd5" => [147, "K"], "\xd6" => [149, "K"], "\xd7" => [101, "K"], "\xd8" => [112, "K"], "\xd9" => [117, "K"], "\xda" => [120, "K"], "\xdb" => [124, "K"], "\xdc" => [127, "K"], "\xdd" => [144, "K"], "\xde" => [152, "K"], "\xdf" => [11, "K"], "\xe0" => [0, "L0"], "\xe1" => [0, "L1"], "\xe2" => [0, "L2"], "\xe3" => [0, "La"], "\xe4" => [0, "Lc"], "\xe5" => [0, "Le"], "\xe6" => [0, "Li"], "\xe7" => [0, "Lo"], "\xe8" => [0, "Ls"], "\xe9" => [0, "Lt"], "\xea" => [73, "L"], "\xeb" => [88, "L"], "\xec" => [89, "L"], "\xed" => [96, "L"], "\xee" => [97, "L"], "\xef" => [99, "L"], "\xf0" => [106, "L"], "\xf1" => [136, "L"], "\xf2" => [139, "L"], "\xf3" => [141, "L"], "\xf4" => [145, "L"], "\xf5" => [147, "L"], "\xf6" => [149, "L"], "\xf7" => [101, "L"], "\xf8" => [112, "L"], "\xf9" => [117, "L"], "\xfa" => [120, "L"], "\xfb" => [124, "L"], "\xfc" => [127, "L"], "\xfd" => [144, "L"], "\xfe" => [152, "L"], "\xff" => [11, "L"]], ["\x00" => [92, "E"], "\x01" => [95, "E"], "\x02" => [137, "E"], "\x03" => [142, "E"], "\x04" => [150, "E"], "\x05" => [74, "E"], "\x06" => [90, "E"], "\x07" => [98, "E"], "\x08" => [107, "E"], "\t" => [140, "E"], "\n" => [146, "E"], "\v" => [102, "E"], "\f" => [113, "E"], "\r" => [121, "E"], "\x0e" => [128, "E"], "\x0f" => [12, "E"], "\x10" => [92, "F"], "\x11" => [95, "F"], "\x12" => [137, "F"], "\x13" => [142, "F"], "\x14" => [150, "F"], "\x15" => [74, "F"], "\x16" => [90, "F"], "\x17" => [98, "F"], "\x18" => [107, "F"], "\x19" => [140, "F"], "\x1a" => [146, "F"], "\x1b" => [102, "F"], "\x1c" => [113, "F"], "\x1d" => [121, "F"], "\x1e" => [128, "F"], "\x1f" => [12, "F"], " " => [92, "G"], "!" => [95, "G"], "\"" => [137, "G"], "#" => [142, "G"], "\$" => [150, "G"], "%" => [74, "G"], "&" => [90, "G"], "'" => [98, "G"], "(" => [107, "G"], ")" => [140, "G"], "*" => [146, "G"], "+" => [102, "G"], "," => [113, "G"], "-" => [121, "G"], "." => [128, "G"], "/" => [12, "G"], [92, "H"], [95, "H"], [137, "H"], [142, "H"], [150, "H"], [74, "H"], [90, "H"], [98, "H"], [107, "H"], [140, "H"], ":" => [146, "H"], ";" => [102, "H"], "<" => [113, "H"], "=" => [121, "H"], ">" => [128, "H"], "?" => [12, "H"], "@" => [92, "I"], "A" => [95, "I"], "B" => [137, "I"], "C" => [142, "I"], "D" => [150, "I"], "E" => [74, "I"], "F" => [90, "I"], "G" => [98, "I"], "H" => [107, "I"], "I" => [140, "I"], "J" => [146, "I"], "K" => [102, "I"], "L" => [113, "I"], "M" => [121, "I"], "N" => [128, "I"], "O" => [12, "I"], "P" => [92, "J"], "Q" => [95, "J"], "R" => [137, "J"], "S" => [142, "J"], "T" => [150, "J"], "U" => [74, "J"], "V" => [90, "J"], "W" => [98, "J"], "X" => [107, "J"], "Y" => [140, "J"], "Z" => [146, "J"], "[" => [102, "J"], "\\" => [113, "J"], "]" => [121, "J"], "^" => [128, "J"], "_" => [12, "J"], "`" => [92, "K"], "a" => [95, "K"], "b" => [137, "K"], "c" => [142, "K"], "d" => [150, "K"], "e" => [74, "K"], "f" => [90, "K"], "g" => [98, "K"], "h" => [107, "K"], "i" => [140, "K"], "j" => [146, "K"], "k" => [102, "K"], "l" => [113, "K"], "m" => [121, "K"], "n" => [128, "K"], "o" => [12, "K"], "p" => [92, "L"], "q" => [95, "L"], "r" => [137, "L"], "s" => [142, "L"], "t" => [150, "L"], "u" => [74, "L"], "v" => [90, "L"], "w" => [98, "L"], "x" => [107, "L"], "y" => [140, "L"], "z" => [146, "L"], "{" => [102, "L"], "|" => [113, "L"], "}" => [121, "L"], "~" => [128, "L"], "" => [12, "L"], "\x80" => [92, "M"], "\x81" => [95, "M"], "\x82" => [137, "M"], "\x83" => [142, "M"], "\x84" => [150, "M"], "\x85" => [74, "M"], "\x86" => [90, "M"], "\x87" => [98, "M"], "\x88" => [107, "M"], "\x89" => [140, "M"], "\x8a" => [146, "M"], "\x8b" => [102, "M"], "\x8c" => [113, "M"], "\x8d" => [121, "M"], "\x8e" => [128, "M"], "\x8f" => [12, "M"], "\x90" => [92, "N"], "\x91" => [95, "N"], "\x92" => [137, "N"], "\x93" => [142, "N"], "\x94" => [150, "N"], "\x95" => [74, "N"], "\x96" => [90, "N"], "\x97" => [98, "N"], "\x98" => [107, "N"], "\x99" => [140, "N"], "\x9a" => [146, "N"], "\x9b" => [102, "N"], "\x9c" => [113, "N"], "\x9d" => [121, "N"], "\x9e" => [128, "N"], "\x9f" => [12, "N"], "\xa0" => [92, "O"], "\xa1" => [95, "O"], "\xa2" => [137, "O"], "\xa3" => [142, "O"], "\xa4" => [150, "O"], "\xa5" => [74, "O"], "\xa6" => [90, "O"], "\xa7" => [98, "O"], "\xa8" => [107, "O"], "\xa9" => [140, "O"], "\xaa" => [146, "O"], "\xab" => [102, "O"], "\xac" => [113, "O"], "\xad" => [121, "O"], "\xae" => [128, "O"], "\xaf" => [12, "O"], "\xb0" => [92, "P"], "\xb1" => [95, "P"], "\xb2" => [137, "P"], "\xb3" => [142, "P"], "\xb4" => [150, "P"], "\xb5" => [74, "P"], "\xb6" => [90, "P"], "\xb7" => [98, "P"], "\xb8" => [107, "P"], "\xb9" => [140, "P"], "\xba" => [146, "P"], "\xbb" => [102, "P"], "\xbc" => [113, "P"], "\xbd" => [121, "P"], "\xbe" => [128, "P"], "\xbf" => [12, "P"], "\xc0" => [92, "Q"], "\xc1" => [95, "Q"], "\xc2" => [137, "Q"], "\xc3" => [142, "Q"], "\xc4" => [150, "Q"], "\xc5" => [74, "Q"], "\xc6" => [90, "Q"], "\xc7" => [98, "Q"], "\xc8" => [107, "Q"], "\xc9" => [140, "Q"], "\xca" => [146, "Q"], "\xcb" => [102, "Q"], "\xcc" => [113, "Q"], "\xcd" => [121, "Q"], "\xce" => [128, "Q"], "\xcf" => [12, "Q"], "\xd0" => [92, "R"], "\xd1" => [95, "R"], "\xd2" => [137, "R"], "\xd3" => [142, "R"], "\xd4" => [150, "R"], "\xd5" => [74, "R"], "\xd6" => [90, "R"], "\xd7" => [98, "R"], "\xd8" => [107, "R"], "\xd9" => [140, "R"], "\xda" => [146, "R"], "\xdb" => [102, "R"], "\xdc" => [113, "R"], "\xdd" => [121, "R"], "\xde" => [128, "R"], "\xdf" => [12, "R"], "\xe0" => [92, "S"], "\xe1" => [95, "S"], "\xe2" => [137, "S"], "\xe3" => [142, "S"], "\xe4" => [150, "S"], "\xe5" => [74, "S"], "\xe6" => [90, "S"], "\xe7" => [98, "S"], "\xe8" => [107, "S"], "\xe9" => [140, "S"], "\xea" => [146, "S"], "\xeb" => [102, "S"], "\xec" => [113, "S"], "\xed" => [121, "S"], "\xee" => [128, "S"], "\xef" => [12, "S"], "\xf0" => [92, "T"], "\xf1" => [95, "T"], "\xf2" => [137, "T"], "\xf3" => [142, "T"], "\xf4" => [150, "T"], "\xf5" => [74, "T"], "\xf6" => [90, "T"], "\xf7" => [98, "T"], "\xf8" => [107, "T"], "\xf9" => [140, "T"], "\xfa" => [146, "T"], "\xfb" => [102, "T"], "\xfc" => [113, "T"], "\xfd" => [121, "T"], "\xfe" => [128, "T"], "\xff" => [12, "T"]], ["\x00" => [94, "G0"], "\x01" => [76, "G0"], "\x02" => [104, "G0"], "\x03" => [16, "G0"], "\x04" => [94, "G1"], "\x05" => [76, "G1"], "\x06" => [104, "G1"], "\x07" => [16, "G1"], "\x08" => [94, "G2"], "\t" => [76, "G2"], "\n" => [104, "G2"], "\v" => [16, "G2"], "\f" => [94, "Ga"], "\r" => [76, "Ga"], "\x0e" => [104, "Ga"], "\x0f" => [16, "Ga"], "\x10" => [94, "Gc"], "\x11" => [76, "Gc"], "\x12" => [104, "Gc"], "\x13" => [16, "Gc"], "\x14" => [94, "Ge"], "\x15" => [76, "Ge"], "\x16" => [104, "Ge"], "\x17" => [16, "Ge"], "\x18" => [94, "Gi"], "\x19" => [76, "Gi"], "\x1a" => [104, "Gi"], "\x1b" => [16, "Gi"], "\x1c" => [94, "Go"], "\x1d" => [76, "Go"], "\x1e" => [104, "Go"], "\x1f" => [16, "Go"], " " => [94, "Gs"], "!" => [76, "Gs"], "\"" => [104, "Gs"], "#" => [16, "Gs"], "\$" => [94, "Gt"], "%" => [76, "Gt"], "&" => [104, "Gt"], "'" => [16, "Gt"], "(" => [77, "G "], ")" => [18, "G "], "*" => [77, "G%"], "+" => [18, "G%"], "," => [77, "G-"], "-" => [18, "G-"], "." => [77, "G."], "/" => [18, "G."], [77, "G/"], [18, "G/"], [77, "G3"], [18, "G3"], [77, "G4"], [18, "G4"], [77, "G5"], [18, "G5"], [77, "G6"], [18, "G6"], ":" => [77, "G7"], ";" => [18, "G7"], "<" => [77, "G8"], "=" => [18, "G8"], ">" => [77, "G9"], "?" => [18, "G9"], "@" => [77, "G="], "A" => [18, "G="], "B" => [77, "GA"], "C" => [18, "GA"], "D" => [77, "G_"], "E" => [18, "G_"], "F" => [77, "Gb"], "G" => [18, "Gb"], "H" => [77, "Gd"], "I" => [18, "Gd"], "J" => [77, "Gf"], "K" => [18, "Gf"], "L" => [77, "Gg"], "M" => [18, "Gg"], "N" => [77, "Gh"], "O" => [18, "Gh"], "P" => [77, "Gl"], "Q" => [18, "Gl"], "R" => [77, "Gm"], "S" => [18, "Gm"], "T" => [77, "Gn"], "U" => [18, "Gn"], "V" => [77, "Gp"], "W" => [18, "Gp"], "X" => [77, "Gr"], "Y" => [18, "Gr"], "Z" => [77, "Gu"], "[" => [18, "Gu"], "\\" => [0, "G:"], "]" => [0, "GB"], "^" => [0, "GC"], "_" => [0, "GD"], "`" => [0, "GE"], "a" => [0, "GF"], "b" => [0, "GG"], "c" => [0, "GH"], "d" => [0, "GI"], "e" => [0, "GJ"], "f" => [0, "GK"], "g" => [0, "GL"], "h" => [0, "GM"], "i" => [0, "GN"], "j" => [0, "GO"], "k" => [0, "GP"], "l" => [0, "GQ"], "m" => [0, "GR"], "n" => [0, "GS"], "o" => [0, "GT"], "p" => [0, "GU"], "q" => [0, "GV"], "r" => [0, "GW"], "s" => [0, "GY"], "t" => [0, "Gj"], "u" => [0, "Gk"], "v" => [0, "Gq"], "w" => [0, "Gv"], "x" => [0, "Gw"], "y" => [0, "Gx"], "z" => [0, "Gy"], "{" => [0, "Gz"], "|" => [82, "G"], "}" => [87, "G"], "~" => [130, "G"], "" => [9, "G"], "\x80" => [94, "H0"], "\x81" => [76, "H0"], "\x82" => [104, "H0"], "\x83" => [16, "H0"], "\x84" => [94, "H1"], "\x85" => [76, "H1"], "\x86" => [104, "H1"], "\x87" => [16, "H1"], "\x88" => [94, "H2"], "\x89" => [76, "H2"], "\x8a" => [104, "H2"], "\x8b" => [16, "H2"], "\x8c" => [94, "Ha"], "\x8d" => [76, "Ha"], "\x8e" => [104, "Ha"], "\x8f" => [16, "Ha"], "\x90" => [94, "Hc"], "\x91" => [76, "Hc"], "\x92" => [104, "Hc"], "\x93" => [16, "Hc"], "\x94" => [94, "He"], "\x95" => [76, "He"], "\x96" => [104, "He"], "\x97" => [16, "He"], "\x98" => [94, "Hi"], "\x99" => [76, "Hi"], "\x9a" => [104, "Hi"], "\x9b" => [16, "Hi"], "\x9c" => [94, "Ho"], "\x9d" => [76, "Ho"], "\x9e" => [104, "Ho"], "\x9f" => [16, "Ho"], "\xa0" => [94, "Hs"], "\xa1" => [76, "Hs"], "\xa2" => [104, "Hs"], "\xa3" => [16, "Hs"], "\xa4" => [94, "Ht"], "\xa5" => [76, "Ht"], "\xa6" => [104, "Ht"], "\xa7" => [16, "Ht"], "\xa8" => [77, "H "], "\xa9" => [18, "H "], "\xaa" => [77, "H%"], "\xab" => [18, "H%"], "\xac" => [77, "H-"], "\xad" => [18, "H-"], "\xae" => [77, "H."], "\xaf" => [18, "H."], "\xb0" => [77, "H/"], "\xb1" => [18, "H/"], "\xb2" => [77, "H3"], "\xb3" => [18, "H3"], "\xb4" => [77, "H4"], "\xb5" => [18, "H4"], "\xb6" => [77, "H5"], "\xb7" => [18, "H5"], "\xb8" => [77, "H6"], "\xb9" => [18, "H6"], "\xba" => [77, "H7"], "\xbb" => [18, "H7"], "\xbc" => [77, "H8"], "\xbd" => [18, "H8"], "\xbe" => [77, "H9"], "\xbf" => [18, "H9"], "\xc0" => [77, "H="], "\xc1" => [18, "H="], "\xc2" => [77, "HA"], "\xc3" => [18, "HA"], "\xc4" => [77, "H_"], "\xc5" => [18, "H_"], "\xc6" => [77, "Hb"], "\xc7" => [18, "Hb"], "\xc8" => [77, "Hd"], "\xc9" => [18, "Hd"], "\xca" => [77, "Hf"], "\xcb" => [18, "Hf"], "\xcc" => [77, "Hg"], "\xcd" => [18, "Hg"], "\xce" => [77, "Hh"], "\xcf" => [18, "Hh"], "\xd0" => [77, "Hl"], "\xd1" => [18, "Hl"], "\xd2" => [77, "Hm"], "\xd3" => [18, "Hm"], "\xd4" => [77, "Hn"], "\xd5" => [18, "Hn"], "\xd6" => [77, "Hp"], "\xd7" => [18, "Hp"], "\xd8" => [77, "Hr"], "\xd9" => [18, "Hr"], "\xda" => [77, "Hu"], "\xdb" => [18, "Hu"], "\xdc" => [0, "H:"], "\xdd" => [0, "HB"], "\xde" => [0, "HC"], "\xdf" => [0, "HD"], "\xe0" => [0, "HE"], "\xe1" => [0, "HF"], "\xe2" => [0, "HG"], "\xe3" => [0, "HH"], "\xe4" => [0, "HI"], "\xe5" => [0, "HJ"], "\xe6" => [0, "HK"], "\xe7" => [0, "HL"], "\xe8" => [0, "HM"], "\xe9" => [0, "HN"], "\xea" => [0, "HO"], "\xeb" => [0, "HP"], "\xec" => [0, "HQ"], "\xed" => [0, "HR"], "\xee" => [0, "HS"], "\xef" => [0, "HT"], "\xf0" => [0, "HU"], "\xf1" => [0, "HV"], "\xf2" => [0, "HW"], "\xf3" => [0, "HY"], "\xf4" => [0, "Hj"], "\xf5" => [0, "Hk"], "\xf6" => [0, "Hq"], "\xf7" => [0, "Hv"], "\xf8" => [0, "Hw"], "\xf9" => [0, "Hx"], "\xfa" => [0, "Hy"], "\xfb" => [0, "Hz"], "\xfc" => [82, "H"], "\xfd" => [87, "H"], "\xfe" => [130, "H"], "\xff" => [9, "H"]], ["\x00" => [94, "I0"], "\x01" => [76, "I0"], "\x02" => [104, "I0"], "\x03" => [16, "I0"], "\x04" => [94, "I1"], "\x05" => [76, "I1"], "\x06" => [104, "I1"], "\x07" => [16, "I1"], "\x08" => [94, "I2"], "\t" => [76, "I2"], "\n" => [104, "I2"], "\v" => [16, "I2"], "\f" => [94, "Ia"], "\r" => [76, "Ia"], "\x0e" => [104, "Ia"], "\x0f" => [16, "Ia"], "\x10" => [94, "Ic"], "\x11" => [76, "Ic"], "\x12" => [104, "Ic"], "\x13" => [16, "Ic"], "\x14" => [94, "Ie"], "\x15" => [76, "Ie"], "\x16" => [104, "Ie"], "\x17" => [16, "Ie"], "\x18" => [94, "Ii"], "\x19" => [76, "Ii"], "\x1a" => [104, "Ii"], "\x1b" => [16, "Ii"], "\x1c" => [94, "Io"], "\x1d" => [76, "Io"], "\x1e" => [104, "Io"], "\x1f" => [16, "Io"], " " => [94, "Is"], "!" => [76, "Is"], "\"" => [104, "Is"], "#" => [16, "Is"], "\$" => [94, "It"], "%" => [76, "It"], "&" => [104, "It"], "'" => [16, "It"], "(" => [77, "I "], ")" => [18, "I "], "*" => [77, "I%"], "+" => [18, "I%"], "," => [77, "I-"], "-" => [18, "I-"], "." => [77, "I."], "/" => [18, "I."], [77, "I/"], [18, "I/"], [77, "I3"], [18, "I3"], [77, "I4"], [18, "I4"], [77, "I5"], [18, "I5"], [77, "I6"], [18, "I6"], ":" => [77, "I7"], ";" => [18, "I7"], "<" => [77, "I8"], "=" => [18, "I8"], ">" => [77, "I9"], "?" => [18, "I9"], "@" => [77, "I="], "A" => [18, "I="], "B" => [77, "IA"], "C" => [18, "IA"], "D" => [77, "I_"], "E" => [18, "I_"], "F" => [77, "Ib"], "G" => [18, "Ib"], "H" => [77, "Id"], "I" => [18, "Id"], "J" => [77, "If"], "K" => [18, "If"], "L" => [77, "Ig"], "M" => [18, "Ig"], "N" => [77, "Ih"], "O" => [18, "Ih"], "P" => [77, "Il"], "Q" => [18, "Il"], "R" => [77, "Im"], "S" => [18, "Im"], "T" => [77, "In"], "U" => [18, "In"], "V" => [77, "Ip"], "W" => [18, "Ip"], "X" => [77, "Ir"], "Y" => [18, "Ir"], "Z" => [77, "Iu"], "[" => [18, "Iu"], "\\" => [0, "I:"], "]" => [0, "IB"], "^" => [0, "IC"], "_" => [0, "ID"], "`" => [0, "IE"], "a" => [0, "IF"], "b" => [0, "IG"], "c" => [0, "IH"], "d" => [0, "II"], "e" => [0, "IJ"], "f" => [0, "IK"], "g" => [0, "IL"], "h" => [0, "IM"], "i" => [0, "IN"], "j" => [0, "IO"], "k" => [0, "IP"], "l" => [0, "IQ"], "m" => [0, "IR"], "n" => [0, "IS"], "o" => [0, "IT"], "p" => [0, "IU"], "q" => [0, "IV"], "r" => [0, "IW"], "s" => [0, "IY"], "t" => [0, "Ij"], "u" => [0, "Ik"], "v" => [0, "Iq"], "w" => [0, "Iv"], "x" => [0, "Iw"], "y" => [0, "Ix"], "z" => [0, "Iy"], "{" => [0, "Iz"], "|" => [82, "I"], "}" => [87, "I"], "~" => [130, "I"], "" => [9, "I"], "\x80" => [94, "J0"], "\x81" => [76, "J0"], "\x82" => [104, "J0"], "\x83" => [16, "J0"], "\x84" => [94, "J1"], "\x85" => [76, "J1"], "\x86" => [104, "J1"], "\x87" => [16, "J1"], "\x88" => [94, "J2"], "\x89" => [76, "J2"], "\x8a" => [104, "J2"], "\x8b" => [16, "J2"], "\x8c" => [94, "Ja"], "\x8d" => [76, "Ja"], "\x8e" => [104, "Ja"], "\x8f" => [16, "Ja"], "\x90" => [94, "Jc"], "\x91" => [76, "Jc"], "\x92" => [104, "Jc"], "\x93" => [16, "Jc"], "\x94" => [94, "Je"], "\x95" => [76, "Je"], "\x96" => [104, "Je"], "\x97" => [16, "Je"], "\x98" => [94, "Ji"], "\x99" => [76, "Ji"], "\x9a" => [104, "Ji"], "\x9b" => [16, "Ji"], "\x9c" => [94, "Jo"], "\x9d" => [76, "Jo"], "\x9e" => [104, "Jo"], "\x9f" => [16, "Jo"], "\xa0" => [94, "Js"], "\xa1" => [76, "Js"], "\xa2" => [104, "Js"], "\xa3" => [16, "Js"], "\xa4" => [94, "Jt"], "\xa5" => [76, "Jt"], "\xa6" => [104, "Jt"], "\xa7" => [16, "Jt"], "\xa8" => [77, "J "], "\xa9" => [18, "J "], "\xaa" => [77, "J%"], "\xab" => [18, "J%"], "\xac" => [77, "J-"], "\xad" => [18, "J-"], "\xae" => [77, "J."], "\xaf" => [18, "J."], "\xb0" => [77, "J/"], "\xb1" => [18, "J/"], "\xb2" => [77, "J3"], "\xb3" => [18, "J3"], "\xb4" => [77, "J4"], "\xb5" => [18, "J4"], "\xb6" => [77, "J5"], "\xb7" => [18, "J5"], "\xb8" => [77, "J6"], "\xb9" => [18, "J6"], "\xba" => [77, "J7"], "\xbb" => [18, "J7"], "\xbc" => [77, "J8"], "\xbd" => [18, "J8"], "\xbe" => [77, "J9"], "\xbf" => [18, "J9"], "\xc0" => [77, "J="], "\xc1" => [18, "J="], "\xc2" => [77, "JA"], "\xc3" => [18, "JA"], "\xc4" => [77, "J_"], "\xc5" => [18, "J_"], "\xc6" => [77, "Jb"], "\xc7" => [18, "Jb"], "\xc8" => [77, "Jd"], "\xc9" => [18, "Jd"], "\xca" => [77, "Jf"], "\xcb" => [18, "Jf"], "\xcc" => [77, "Jg"], "\xcd" => [18, "Jg"], "\xce" => [77, "Jh"], "\xcf" => [18, "Jh"], "\xd0" => [77, "Jl"], "\xd1" => [18, "Jl"], "\xd2" => [77, "Jm"], "\xd3" => [18, "Jm"], "\xd4" => [77, "Jn"], "\xd5" => [18, "Jn"], "\xd6" => [77, "Jp"], "\xd7" => [18, "Jp"], "\xd8" => [77, "Jr"], "\xd9" => [18, "Jr"], "\xda" => [77, "Ju"], "\xdb" => [18, "Ju"], "\xdc" => [0, "J:"], "\xdd" => [0, "JB"], "\xde" => [0, "JC"], "\xdf" => [0, "JD"], "\xe0" => [0, "JE"], "\xe1" => [0, "JF"], "\xe2" => [0, "JG"], "\xe3" => [0, "JH"], "\xe4" => [0, "JI"], "\xe5" => [0, "JJ"], "\xe6" => [0, "JK"], "\xe7" => [0, "JL"], "\xe8" => [0, "JM"], "\xe9" => [0, "JN"], "\xea" => [0, "JO"], "\xeb" => [0, "JP"], "\xec" => [0, "JQ"], "\xed" => [0, "JR"], "\xee" => [0, "JS"], "\xef" => [0, "JT"], "\xf0" => [0, "JU"], "\xf1" => [0, "JV"], "\xf2" => [0, "JW"], "\xf3" => [0, "JY"], "\xf4" => [0, "Jj"], "\xf5" => [0, "Jk"], "\xf6" => [0, "Jq"], "\xf7" => [0, "Jv"], "\xf8" => [0, "Jw"], "\xf9" => [0, "Jx"], "\xfa" => [0, "Jy"], "\xfb" => [0, "Jz"], "\xfc" => [82, "J"], "\xfd" => [87, "J"], "\xfe" => [130, "J"], "\xff" => [9, "J"]], ["\x00" => [77, "I0"], "\x01" => [18, "I0"], "\x02" => [77, "I1"], "\x03" => [18, "I1"], "\x04" => [77, "I2"], "\x05" => [18, "I2"], "\x06" => [77, "Ia"], "\x07" => [18, "Ia"], "\x08" => [77, "Ic"], "\t" => [18, "Ic"], "\n" => [77, "Ie"], "\v" => [18, "Ie"], "\f" => [77, "Ii"], "\r" => [18, "Ii"], "\x0e" => [77, "Io"], "\x0f" => [18, "Io"], "\x10" => [77, "Is"], "\x11" => [18, "Is"], "\x12" => [77, "It"], "\x13" => [18, "It"], "\x14" => [0, "I "], "\x15" => [0, "I%"], "\x16" => [0, "I-"], "\x17" => [0, "I."], "\x18" => [0, "I/"], "\x19" => [0, "I3"], "\x1a" => [0, "I4"], "\x1b" => [0, "I5"], "\x1c" => [0, "I6"], "\x1d" => [0, "I7"], "\x1e" => [0, "I8"], "\x1f" => [0, "I9"], " " => [0, "I="], "!" => [0, "IA"], "\"" => [0, "I_"], "#" => [0, "Ib"], "\$" => [0, "Id"], "%" => [0, "If"], "&" => [0, "Ig"], "'" => [0, "Ih"], "(" => [0, "Il"], ")" => [0, "Im"], "*" => [0, "In"], "+" => [0, "Ip"], "," => [0, "Ir"], "-" => [0, "Iu"], "." => [100, "I"], "/" => [110, "I"], [111, "I"], [115, "I"], [116, "I"], [118, "I"], [119, "I"], [122, "I"], [123, "I"], [125, "I"], [126, "I"], [129, "I"], ":" => [143, "I"], ";" => [148, "I"], "<" => [151, "I"], "=" => [153, "I"], ">" => [83, "I"], "?" => [10, "I"], "@" => [77, "J0"], "A" => [18, "J0"], "B" => [77, "J1"], "C" => [18, "J1"], "D" => [77, "J2"], "E" => [18, "J2"], "F" => [77, "Ja"], "G" => [18, "Ja"], "H" => [77, "Jc"], "I" => [18, "Jc"], "J" => [77, "Je"], "K" => [18, "Je"], "L" => [77, "Ji"], "M" => [18, "Ji"], "N" => [77, "Jo"], "O" => [18, "Jo"], "P" => [77, "Js"], "Q" => [18, "Js"], "R" => [77, "Jt"], "S" => [18, "Jt"], "T" => [0, "J "], "U" => [0, "J%"], "V" => [0, "J-"], "W" => [0, "J."], "X" => [0, "J/"], "Y" => [0, "J3"], "Z" => [0, "J4"], "[" => [0, "J5"], "\\" => [0, "J6"], "]" => [0, "J7"], "^" => [0, "J8"], "_" => [0, "J9"], "`" => [0, "J="], "a" => [0, "JA"], "b" => [0, "J_"], "c" => [0, "Jb"], "d" => [0, "Jd"], "e" => [0, "Jf"], "f" => [0, "Jg"], "g" => [0, "Jh"], "h" => [0, "Jl"], "i" => [0, "Jm"], "j" => [0, "Jn"], "k" => [0, "Jp"], "l" => [0, "Jr"], "m" => [0, "Ju"], "n" => [100, "J"], "o" => [110, "J"], "p" => [111, "J"], "q" => [115, "J"], "r" => [116, "J"], "s" => [118, "J"], "t" => [119, "J"], "u" => [122, "J"], "v" => [123, "J"], "w" => [125, "J"], "x" => [126, "J"], "y" => [129, "J"], "z" => [143, "J"], "{" => [148, "J"], "|" => [151, "J"], "}" => [153, "J"], "~" => [83, "J"], "" => [10, "J"], "\x80" => [77, "K0"], "\x81" => [18, "K0"], "\x82" => [77, "K1"], "\x83" => [18, "K1"], "\x84" => [77, "K2"], "\x85" => [18, "K2"], "\x86" => [77, "Ka"], "\x87" => [18, "Ka"], "\x88" => [77, "Kc"], "\x89" => [18, "Kc"], "\x8a" => [77, "Ke"], "\x8b" => [18, "Ke"], "\x8c" => [77, "Ki"], "\x8d" => [18, "Ki"], "\x8e" => [77, "Ko"], "\x8f" => [18, "Ko"], "\x90" => [77, "Ks"], "\x91" => [18, "Ks"], "\x92" => [77, "Kt"], "\x93" => [18, "Kt"], "\x94" => [0, "K "], "\x95" => [0, "K%"], "\x96" => [0, "K-"], "\x97" => [0, "K."], "\x98" => [0, "K/"], "\x99" => [0, "K3"], "\x9a" => [0, "K4"], "\x9b" => [0, "K5"], "\x9c" => [0, "K6"], "\x9d" => [0, "K7"], "\x9e" => [0, "K8"], "\x9f" => [0, "K9"], "\xa0" => [0, "K="], "\xa1" => [0, "KA"], "\xa2" => [0, "K_"], "\xa3" => [0, "Kb"], "\xa4" => [0, "Kd"], "\xa5" => [0, "Kf"], "\xa6" => [0, "Kg"], "\xa7" => [0, "Kh"], "\xa8" => [0, "Kl"], "\xa9" => [0, "Km"], "\xaa" => [0, "Kn"], "\xab" => [0, "Kp"], "\xac" => [0, "Kr"], "\xad" => [0, "Ku"], "\xae" => [100, "K"], "\xaf" => [110, "K"], "\xb0" => [111, "K"], "\xb1" => [115, "K"], "\xb2" => [116, "K"], "\xb3" => [118, "K"], "\xb4" => [119, "K"], "\xb5" => [122, "K"], "\xb6" => [123, "K"], "\xb7" => [125, "K"], "\xb8" => [126, "K"], "\xb9" => [129, "K"], "\xba" => [143, "K"], "\xbb" => [148, "K"], "\xbc" => [151, "K"], "\xbd" => [153, "K"], "\xbe" => [83, "K"], "\xbf" => [10, "K"], "\xc0" => [77, "L0"], "\xc1" => [18, "L0"], "\xc2" => [77, "L1"], "\xc3" => [18, "L1"], "\xc4" => [77, "L2"], "\xc5" => [18, "L2"], "\xc6" => [77, "La"], "\xc7" => [18, "La"], "\xc8" => [77, "Lc"], "\xc9" => [18, "Lc"], "\xca" => [77, "Le"], "\xcb" => [18, "Le"], "\xcc" => [77, "Li"], "\xcd" => [18, "Li"], "\xce" => [77, "Lo"], "\xcf" => [18, "Lo"], "\xd0" => [77, "Ls"], "\xd1" => [18, "Ls"], "\xd2" => [77, "Lt"], "\xd3" => [18, "Lt"], "\xd4" => [0, "L "], "\xd5" => [0, "L%"], "\xd6" => [0, "L-"], "\xd7" => [0, "L."], "\xd8" => [0, "L/"], "\xd9" => [0, "L3"], "\xda" => [0, "L4"], "\xdb" => [0, "L5"], "\xdc" => [0, "L6"], "\xdd" => [0, "L7"], "\xde" => [0, "L8"], "\xdf" => [0, "L9"], "\xe0" => [0, "L="], "\xe1" => [0, "LA"], "\xe2" => [0, "L_"], "\xe3" => [0, "Lb"], "\xe4" => [0, "Ld"], "\xe5" => [0, "Lf"], "\xe6" => [0, "Lg"], "\xe7" => [0, "Lh"], "\xe8" => [0, "Ll"], "\xe9" => [0, "Lm"], "\xea" => [0, "Ln"], "\xeb" => [0, "Lp"], "\xec" => [0, "Lr"], "\xed" => [0, "Lu"], "\xee" => [100, "L"], "\xef" => [110, "L"], "\xf0" => [111, "L"], "\xf1" => [115, "L"], "\xf2" => [116, "L"], "\xf3" => [118, "L"], "\xf4" => [119, "L"], "\xf5" => [122, "L"], "\xf6" => [123, "L"], "\xf7" => [125, "L"], "\xf8" => [126, "L"], "\xf9" => [129, "L"], "\xfa" => [143, "L"], "\xfb" => [148, "L"], "\xfc" => [151, "L"], "\xfd" => [153, "L"], "\xfe" => [83, "L"], "\xff" => [10, "L"]], ["\x00" => [94, "K0"], "\x01" => [76, "K0"], "\x02" => [104, "K0"], "\x03" => [16, "K0"], "\x04" => [94, "K1"], "\x05" => [76, "K1"], "\x06" => [104, "K1"], "\x07" => [16, "K1"], "\x08" => [94, "K2"], "\t" => [76, "K2"], "\n" => [104, "K2"], "\v" => [16, "K2"], "\f" => [94, "Ka"], "\r" => [76, "Ka"], "\x0e" => [104, "Ka"], "\x0f" => [16, "Ka"], "\x10" => [94, "Kc"], "\x11" => [76, "Kc"], "\x12" => [104, "Kc"], "\x13" => [16, "Kc"], "\x14" => [94, "Ke"], "\x15" => [76, "Ke"], "\x16" => [104, "Ke"], "\x17" => [16, "Ke"], "\x18" => [94, "Ki"], "\x19" => [76, "Ki"], "\x1a" => [104, "Ki"], "\x1b" => [16, "Ki"], "\x1c" => [94, "Ko"], "\x1d" => [76, "Ko"], "\x1e" => [104, "Ko"], "\x1f" => [16, "Ko"], " " => [94, "Ks"], "!" => [76, "Ks"], "\"" => [104, "Ks"], "#" => [16, "Ks"], "\$" => [94, "Kt"], "%" => [76, "Kt"], "&" => [104, "Kt"], "'" => [16, "Kt"], "(" => [77, "K "], ")" => [18, "K "], "*" => [77, "K%"], "+" => [18, "K%"], "," => [77, "K-"], "-" => [18, "K-"], "." => [77, "K."], "/" => [18, "K."], [77, "K/"], [18, "K/"], [77, "K3"], [18, "K3"], [77, "K4"], [18, "K4"], [77, "K5"], [18, "K5"], [77, "K6"], [18, "K6"], ":" => [77, "K7"], ";" => [18, "K7"], "<" => [77, "K8"], "=" => [18, "K8"], ">" => [77, "K9"], "?" => [18, "K9"], "@" => [77, "K="], "A" => [18, "K="], "B" => [77, "KA"], "C" => [18, "KA"], "D" => [77, "K_"], "E" => [18, "K_"], "F" => [77, "Kb"], "G" => [18, "Kb"], "H" => [77, "Kd"], "I" => [18, "Kd"], "J" => [77, "Kf"], "K" => [18, "Kf"], "L" => [77, "Kg"], "M" => [18, "Kg"], "N" => [77, "Kh"], "O" => [18, "Kh"], "P" => [77, "Kl"], "Q" => [18, "Kl"], "R" => [77, "Km"], "S" => [18, "Km"], "T" => [77, "Kn"], "U" => [18, "Kn"], "V" => [77, "Kp"], "W" => [18, "Kp"], "X" => [77, "Kr"], "Y" => [18, "Kr"], "Z" => [77, "Ku"], "[" => [18, "Ku"], "\\" => [0, "K:"], "]" => [0, "KB"], "^" => [0, "KC"], "_" => [0, "KD"], "`" => [0, "KE"], "a" => [0, "KF"], "b" => [0, "KG"], "c" => [0, "KH"], "d" => [0, "KI"], "e" => [0, "KJ"], "f" => [0, "KK"], "g" => [0, "KL"], "h" => [0, "KM"], "i" => [0, "KN"], "j" => [0, "KO"], "k" => [0, "KP"], "l" => [0, "KQ"], "m" => [0, "KR"], "n" => [0, "KS"], "o" => [0, "KT"], "p" => [0, "KU"], "q" => [0, "KV"], "r" => [0, "KW"], "s" => [0, "KY"], "t" => [0, "Kj"], "u" => [0, "Kk"], "v" => [0, "Kq"], "w" => [0, "Kv"], "x" => [0, "Kw"], "y" => [0, "Kx"], "z" => [0, "Ky"], "{" => [0, "Kz"], "|" => [82, "K"], "}" => [87, "K"], "~" => [130, "K"], "" => [9, "K"], "\x80" => [94, "L0"], "\x81" => [76, "L0"], "\x82" => [104, "L0"], "\x83" => [16, "L0"], "\x84" => [94, "L1"], "\x85" => [76, "L1"], "\x86" => [104, "L1"], "\x87" => [16, "L1"], "\x88" => [94, "L2"], "\x89" => [76, "L2"], "\x8a" => [104, "L2"], "\x8b" => [16, "L2"], "\x8c" => [94, "La"], "\x8d" => [76, "La"], "\x8e" => [104, "La"], "\x8f" => [16, "La"], "\x90" => [94, "Lc"], "\x91" => [76, "Lc"], "\x92" => [104, "Lc"], "\x93" => [16, "Lc"], "\x94" => [94, "Le"], "\x95" => [76, "Le"], "\x96" => [104, "Le"], "\x97" => [16, "Le"], "\x98" => [94, "Li"], "\x99" => [76, "Li"], "\x9a" => [104, "Li"], "\x9b" => [16, "Li"], "\x9c" => [94, "Lo"], "\x9d" => [76, "Lo"], "\x9e" => [104, "Lo"], "\x9f" => [16, "Lo"], "\xa0" => [94, "Ls"], "\xa1" => [76, "Ls"], "\xa2" => [104, "Ls"], "\xa3" => [16, "Ls"], "\xa4" => [94, "Lt"], "\xa5" => [76, "Lt"], "\xa6" => [104, "Lt"], "\xa7" => [16, "Lt"], "\xa8" => [77, "L "], "\xa9" => [18, "L "], "\xaa" => [77, "L%"], "\xab" => [18, "L%"], "\xac" => [77, "L-"], "\xad" => [18, "L-"], "\xae" => [77, "L."], "\xaf" => [18, "L."], "\xb0" => [77, "L/"], "\xb1" => [18, "L/"], "\xb2" => [77, "L3"], "\xb3" => [18, "L3"], "\xb4" => [77, "L4"], "\xb5" => [18, "L4"], "\xb6" => [77, "L5"], "\xb7" => [18, "L5"], "\xb8" => [77, "L6"], "\xb9" => [18, "L6"], "\xba" => [77, "L7"], "\xbb" => [18, "L7"], "\xbc" => [77, "L8"], "\xbd" => [18, "L8"], "\xbe" => [77, "L9"], "\xbf" => [18, "L9"], "\xc0" => [77, "L="], "\xc1" => [18, "L="], "\xc2" => [77, "LA"], "\xc3" => [18, "LA"], "\xc4" => [77, "L_"], "\xc5" => [18, "L_"], "\xc6" => [77, "Lb"], "\xc7" => [18, "Lb"], "\xc8" => [77, "Ld"], "\xc9" => [18, "Ld"], "\xca" => [77, "Lf"], "\xcb" => [18, "Lf"], "\xcc" => [77, "Lg"], "\xcd" => [18, "Lg"], "\xce" => [77, "Lh"], "\xcf" => [18, "Lh"], "\xd0" => [77, "Ll"], "\xd1" => [18, "Ll"], "\xd2" => [77, "Lm"], "\xd3" => [18, "Lm"], "\xd4" => [77, "Ln"], "\xd5" => [18, "Ln"], "\xd6" => [77, "Lp"], "\xd7" => [18, "Lp"], "\xd8" => [77, "Lr"], "\xd9" => [18, "Lr"], "\xda" => [77, "Lu"], "\xdb" => [18, "Lu"], "\xdc" => [0, "L:"], "\xdd" => [0, "LB"], "\xde" => [0, "LC"], "\xdf" => [0, "LD"], "\xe0" => [0, "LE"], "\xe1" => [0, "LF"], "\xe2" => [0, "LG"], "\xe3" => [0, "LH"], "\xe4" => [0, "LI"], "\xe5" => [0, "LJ"], "\xe6" => [0, "LK"], "\xe7" => [0, "LL"], "\xe8" => [0, "LM"], "\xe9" => [0, "LN"], "\xea" => [0, "LO"], "\xeb" => [0, "LP"], "\xec" => [0, "LQ"], "\xed" => [0, "LR"], "\xee" => [0, "LS"], "\xef" => [0, "LT"], "\xf0" => [0, "LU"], "\xf1" => [0, "LV"], "\xf2" => [0, "LW"], "\xf3" => [0, "LY"], "\xf4" => [0, "Lj"], "\xf5" => [0, "Lk"], "\xf6" => [0, "Lq"], "\xf7" => [0, "Lv"], "\xf8" => [0, "Lw"], "\xf9" => [0, "Lx"], "\xfa" => [0, "Ly"], "\xfb" => [0, "Lz"], "\xfc" => [82, "L"], "\xfd" => [87, "L"], "\xfe" => [130, "L"], "\xff" => [9, "L"]], ["\x00" => [94, "M0"], "\x01" => [76, "M0"], "\x02" => [104, "M0"], "\x03" => [16, "M0"], "\x04" => [94, "M1"], "\x05" => [76, "M1"], "\x06" => [104, "M1"], "\x07" => [16, "M1"], "\x08" => [94, "M2"], "\t" => [76, "M2"], "\n" => [104, "M2"], "\v" => [16, "M2"], "\f" => [94, "Ma"], "\r" => [76, "Ma"], "\x0e" => [104, "Ma"], "\x0f" => [16, "Ma"], "\x10" => [94, "Mc"], "\x11" => [76, "Mc"], "\x12" => [104, "Mc"], "\x13" => [16, "Mc"], "\x14" => [94, "Me"], "\x15" => [76, "Me"], "\x16" => [104, "Me"], "\x17" => [16, "Me"], "\x18" => [94, "Mi"], "\x19" => [76, "Mi"], "\x1a" => [104, "Mi"], "\x1b" => [16, "Mi"], "\x1c" => [94, "Mo"], "\x1d" => [76, "Mo"], "\x1e" => [104, "Mo"], "\x1f" => [16, "Mo"], " " => [94, "Ms"], "!" => [76, "Ms"], "\"" => [104, "Ms"], "#" => [16, "Ms"], "\$" => [94, "Mt"], "%" => [76, "Mt"], "&" => [104, "Mt"], "'" => [16, "Mt"], "(" => [77, "M "], ")" => [18, "M "], "*" => [77, "M%"], "+" => [18, "M%"], "," => [77, "M-"], "-" => [18, "M-"], "." => [77, "M."], "/" => [18, "M."], [77, "M/"], [18, "M/"], [77, "M3"], [18, "M3"], [77, "M4"], [18, "M4"], [77, "M5"], [18, "M5"], [77, "M6"], [18, "M6"], ":" => [77, "M7"], ";" => [18, "M7"], "<" => [77, "M8"], "=" => [18, "M8"], ">" => [77, "M9"], "?" => [18, "M9"], "@" => [77, "M="], "A" => [18, "M="], "B" => [77, "MA"], "C" => [18, "MA"], "D" => [77, "M_"], "E" => [18, "M_"], "F" => [77, "Mb"], "G" => [18, "Mb"], "H" => [77, "Md"], "I" => [18, "Md"], "J" => [77, "Mf"], "K" => [18, "Mf"], "L" => [77, "Mg"], "M" => [18, "Mg"], "N" => [77, "Mh"], "O" => [18, "Mh"], "P" => [77, "Ml"], "Q" => [18, "Ml"], "R" => [77, "Mm"], "S" => [18, "Mm"], "T" => [77, "Mn"], "U" => [18, "Mn"], "V" => [77, "Mp"], "W" => [18, "Mp"], "X" => [77, "Mr"], "Y" => [18, "Mr"], "Z" => [77, "Mu"], "[" => [18, "Mu"], "\\" => [0, "M:"], "]" => [0, "MB"], "^" => [0, "MC"], "_" => [0, "MD"], "`" => [0, "ME"], "a" => [0, "MF"], "b" => [0, "MG"], "c" => [0, "MH"], "d" => [0, "MI"], "e" => [0, "MJ"], "f" => [0, "MK"], "g" => [0, "ML"], "h" => [0, "MM"], "i" => [0, "MN"], "j" => [0, "MO"], "k" => [0, "MP"], "l" => [0, "MQ"], "m" => [0, "MR"], "n" => [0, "MS"], "o" => [0, "MT"], "p" => [0, "MU"], "q" => [0, "MV"], "r" => [0, "MW"], "s" => [0, "MY"], "t" => [0, "Mj"], "u" => [0, "Mk"], "v" => [0, "Mq"], "w" => [0, "Mv"], "x" => [0, "Mw"], "y" => [0, "Mx"], "z" => [0, "My"], "{" => [0, "Mz"], "|" => [82, "M"], "}" => [87, "M"], "~" => [130, "M"], "" => [9, "M"], "\x80" => [94, "N0"], "\x81" => [76, "N0"], "\x82" => [104, "N0"], "\x83" => [16, "N0"], "\x84" => [94, "N1"], "\x85" => [76, "N1"], "\x86" => [104, "N1"], "\x87" => [16, "N1"], "\x88" => [94, "N2"], "\x89" => [76, "N2"], "\x8a" => [104, "N2"], "\x8b" => [16, "N2"], "\x8c" => [94, "Na"], "\x8d" => [76, "Na"], "\x8e" => [104, "Na"], "\x8f" => [16, "Na"], "\x90" => [94, "Nc"], "\x91" => [76, "Nc"], "\x92" => [104, "Nc"], "\x93" => [16, "Nc"], "\x94" => [94, "Ne"], "\x95" => [76, "Ne"], "\x96" => [104, "Ne"], "\x97" => [16, "Ne"], "\x98" => [94, "Ni"], "\x99" => [76, "Ni"], "\x9a" => [104, "Ni"], "\x9b" => [16, "Ni"], "\x9c" => [94, "No"], "\x9d" => [76, "No"], "\x9e" => [104, "No"], "\x9f" => [16, "No"], "\xa0" => [94, "Ns"], "\xa1" => [76, "Ns"], "\xa2" => [104, "Ns"], "\xa3" => [16, "Ns"], "\xa4" => [94, "Nt"], "\xa5" => [76, "Nt"], "\xa6" => [104, "Nt"], "\xa7" => [16, "Nt"], "\xa8" => [77, "N "], "\xa9" => [18, "N "], "\xaa" => [77, "N%"], "\xab" => [18, "N%"], "\xac" => [77, "N-"], "\xad" => [18, "N-"], "\xae" => [77, "N."], "\xaf" => [18, "N."], "\xb0" => [77, "N/"], "\xb1" => [18, "N/"], "\xb2" => [77, "N3"], "\xb3" => [18, "N3"], "\xb4" => [77, "N4"], "\xb5" => [18, "N4"], "\xb6" => [77, "N5"], "\xb7" => [18, "N5"], "\xb8" => [77, "N6"], "\xb9" => [18, "N6"], "\xba" => [77, "N7"], "\xbb" => [18, "N7"], "\xbc" => [77, "N8"], "\xbd" => [18, "N8"], "\xbe" => [77, "N9"], "\xbf" => [18, "N9"], "\xc0" => [77, "N="], "\xc1" => [18, "N="], "\xc2" => [77, "NA"], "\xc3" => [18, "NA"], "\xc4" => [77, "N_"], "\xc5" => [18, "N_"], "\xc6" => [77, "Nb"], "\xc7" => [18, "Nb"], "\xc8" => [77, "Nd"], "\xc9" => [18, "Nd"], "\xca" => [77, "Nf"], "\xcb" => [18, "Nf"], "\xcc" => [77, "Ng"], "\xcd" => [18, "Ng"], "\xce" => [77, "Nh"], "\xcf" => [18, "Nh"], "\xd0" => [77, "Nl"], "\xd1" => [18, "Nl"], "\xd2" => [77, "Nm"], "\xd3" => [18, "Nm"], "\xd4" => [77, "Nn"], "\xd5" => [18, "Nn"], "\xd6" => [77, "Np"], "\xd7" => [18, "Np"], "\xd8" => [77, "Nr"], "\xd9" => [18, "Nr"], "\xda" => [77, "Nu"], "\xdb" => [18, "Nu"], "\xdc" => [0, "N:"], "\xdd" => [0, "NB"], "\xde" => [0, "NC"], "\xdf" => [0, "ND"], "\xe0" => [0, "NE"], "\xe1" => [0, "NF"], "\xe2" => [0, "NG"], "\xe3" => [0, "NH"], "\xe4" => [0, "NI"], "\xe5" => [0, "NJ"], "\xe6" => [0, "NK"], "\xe7" => [0, "NL"], "\xe8" => [0, "NM"], "\xe9" => [0, "NN"], "\xea" => [0, "NO"], "\xeb" => [0, "NP"], "\xec" => [0, "NQ"], "\xed" => [0, "NR"], "\xee" => [0, "NS"], "\xef" => [0, "NT"], "\xf0" => [0, "NU"], "\xf1" => [0, "NV"], "\xf2" => [0, "NW"], "\xf3" => [0, "NY"], "\xf4" => [0, "Nj"], "\xf5" => [0, "Nk"], "\xf6" => [0, "Nq"], "\xf7" => [0, "Nv"], "\xf8" => [0, "Nw"], "\xf9" => [0, "Nx"], "\xfa" => [0, "Ny"], "\xfb" => [0, "Nz"], "\xfc" => [82, "N"], "\xfd" => [87, "N"], "\xfe" => [130, "N"], "\xff" => [9, "N"]], ["\x00" => [77, "M0"], "\x01" => [18, "M0"], "\x02" => [77, "M1"], "\x03" => [18, "M1"], "\x04" => [77, "M2"], "\x05" => [18, "M2"], "\x06" => [77, "Ma"], "\x07" => [18, "Ma"], "\x08" => [77, "Mc"], "\t" => [18, "Mc"], "\n" => [77, "Me"], "\v" => [18, "Me"], "\f" => [77, "Mi"], "\r" => [18, "Mi"], "\x0e" => [77, "Mo"], "\x0f" => [18, "Mo"], "\x10" => [77, "Ms"], "\x11" => [18, "Ms"], "\x12" => [77, "Mt"], "\x13" => [18, "Mt"], "\x14" => [0, "M "], "\x15" => [0, "M%"], "\x16" => [0, "M-"], "\x17" => [0, "M."], "\x18" => [0, "M/"], "\x19" => [0, "M3"], "\x1a" => [0, "M4"], "\x1b" => [0, "M5"], "\x1c" => [0, "M6"], "\x1d" => [0, "M7"], "\x1e" => [0, "M8"], "\x1f" => [0, "M9"], " " => [0, "M="], "!" => [0, "MA"], "\"" => [0, "M_"], "#" => [0, "Mb"], "\$" => [0, "Md"], "%" => [0, "Mf"], "&" => [0, "Mg"], "'" => [0, "Mh"], "(" => [0, "Ml"], ")" => [0, "Mm"], "*" => [0, "Mn"], "+" => [0, "Mp"], "," => [0, "Mr"], "-" => [0, "Mu"], "." => [100, "M"], "/" => [110, "M"], [111, "M"], [115, "M"], [116, "M"], [118, "M"], [119, "M"], [122, "M"], [123, "M"], [125, "M"], [126, "M"], [129, "M"], ":" => [143, "M"], ";" => [148, "M"], "<" => [151, "M"], "=" => [153, "M"], ">" => [83, "M"], "?" => [10, "M"], "@" => [77, "N0"], "A" => [18, "N0"], "B" => [77, "N1"], "C" => [18, "N1"], "D" => [77, "N2"], "E" => [18, "N2"], "F" => [77, "Na"], "G" => [18, "Na"], "H" => [77, "Nc"], "I" => [18, "Nc"], "J" => [77, "Ne"], "K" => [18, "Ne"], "L" => [77, "Ni"], "M" => [18, "Ni"], "N" => [77, "No"], "O" => [18, "No"], "P" => [77, "Ns"], "Q" => [18, "Ns"], "R" => [77, "Nt"], "S" => [18, "Nt"], "T" => [0, "N "], "U" => [0, "N%"], "V" => [0, "N-"], "W" => [0, "N."], "X" => [0, "N/"], "Y" => [0, "N3"], "Z" => [0, "N4"], "[" => [0, "N5"], "\\" => [0, "N6"], "]" => [0, "N7"], "^" => [0, "N8"], "_" => [0, "N9"], "`" => [0, "N="], "a" => [0, "NA"], "b" => [0, "N_"], "c" => [0, "Nb"], "d" => [0, "Nd"], "e" => [0, "Nf"], "f" => [0, "Ng"], "g" => [0, "Nh"], "h" => [0, "Nl"], "i" => [0, "Nm"], "j" => [0, "Nn"], "k" => [0, "Np"], "l" => [0, "Nr"], "m" => [0, "Nu"], "n" => [100, "N"], "o" => [110, "N"], "p" => [111, "N"], "q" => [115, "N"], "r" => [116, "N"], "s" => [118, "N"], "t" => [119, "N"], "u" => [122, "N"], "v" => [123, "N"], "w" => [125, "N"], "x" => [126, "N"], "y" => [129, "N"], "z" => [143, "N"], "{" => [148, "N"], "|" => [151, "N"], "}" => [153, "N"], "~" => [83, "N"], "" => [10, "N"], "\x80" => [77, "O0"], "\x81" => [18, "O0"], "\x82" => [77, "O1"], "\x83" => [18, "O1"], "\x84" => [77, "O2"], "\x85" => [18, "O2"], "\x86" => [77, "Oa"], "\x87" => [18, "Oa"], "\x88" => [77, "Oc"], "\x89" => [18, "Oc"], "\x8a" => [77, "Oe"], "\x8b" => [18, "Oe"], "\x8c" => [77, "Oi"], "\x8d" => [18, "Oi"], "\x8e" => [77, "Oo"], "\x8f" => [18, "Oo"], "\x90" => [77, "Os"], "\x91" => [18, "Os"], "\x92" => [77, "Ot"], "\x93" => [18, "Ot"], "\x94" => [0, "O "], "\x95" => [0, "O%"], "\x96" => [0, "O-"], "\x97" => [0, "O."], "\x98" => [0, "O/"], "\x99" => [0, "O3"], "\x9a" => [0, "O4"], "\x9b" => [0, "O5"], "\x9c" => [0, "O6"], "\x9d" => [0, "O7"], "\x9e" => [0, "O8"], "\x9f" => [0, "O9"], "\xa0" => [0, "O="], "\xa1" => [0, "OA"], "\xa2" => [0, "O_"], "\xa3" => [0, "Ob"], "\xa4" => [0, "Od"], "\xa5" => [0, "Of"], "\xa6" => [0, "Og"], "\xa7" => [0, "Oh"], "\xa8" => [0, "Ol"], "\xa9" => [0, "Om"], "\xaa" => [0, "On"], "\xab" => [0, "Op"], "\xac" => [0, "Or"], "\xad" => [0, "Ou"], "\xae" => [100, "O"], "\xaf" => [110, "O"], "\xb0" => [111, "O"], "\xb1" => [115, "O"], "\xb2" => [116, "O"], "\xb3" => [118, "O"], "\xb4" => [119, "O"], "\xb5" => [122, "O"], "\xb6" => [123, "O"], "\xb7" => [125, "O"], "\xb8" => [126, "O"], "\xb9" => [129, "O"], "\xba" => [143, "O"], "\xbb" => [148, "O"], "\xbc" => [151, "O"], "\xbd" => [153, "O"], "\xbe" => [83, "O"], "\xbf" => [10, "O"], "\xc0" => [77, "P0"], "\xc1" => [18, "P0"], "\xc2" => [77, "P1"], "\xc3" => [18, "P1"], "\xc4" => [77, "P2"], "\xc5" => [18, "P2"], "\xc6" => [77, "Pa"], "\xc7" => [18, "Pa"], "\xc8" => [77, "Pc"], "\xc9" => [18, "Pc"], "\xca" => [77, "Pe"], "\xcb" => [18, "Pe"], "\xcc" => [77, "Pi"], "\xcd" => [18, "Pi"], "\xce" => [77, "Po"], "\xcf" => [18, "Po"], "\xd0" => [77, "Ps"], "\xd1" => [18, "Ps"], "\xd2" => [77, "Pt"], "\xd3" => [18, "Pt"], "\xd4" => [0, "P "], "\xd5" => [0, "P%"], "\xd6" => [0, "P-"], "\xd7" => [0, "P."], "\xd8" => [0, "P/"], "\xd9" => [0, "P3"], "\xda" => [0, "P4"], "\xdb" => [0, "P5"], "\xdc" => [0, "P6"], "\xdd" => [0, "P7"], "\xde" => [0, "P8"], "\xdf" => [0, "P9"], "\xe0" => [0, "P="], "\xe1" => [0, "PA"], "\xe2" => [0, "P_"], "\xe3" => [0, "Pb"], "\xe4" => [0, "Pd"], "\xe5" => [0, "Pf"], "\xe6" => [0, "Pg"], "\xe7" => [0, "Ph"], "\xe8" => [0, "Pl"], "\xe9" => [0, "Pm"], "\xea" => [0, "Pn"], "\xeb" => [0, "Pp"], "\xec" => [0, "Pr"], "\xed" => [0, "Pu"], "\xee" => [100, "P"], "\xef" => [110, "P"], "\xf0" => [111, "P"], "\xf1" => [115, "P"], "\xf2" => [116, "P"], "\xf3" => [118, "P"], "\xf4" => [119, "P"], "\xf5" => [122, "P"], "\xf6" => [123, "P"], "\xf7" => [125, "P"], "\xf8" => [126, "P"], "\xf9" => [129, "P"], "\xfa" => [143, "P"], "\xfb" => [148, "P"], "\xfc" => [151, "P"], "\xfd" => [153, "P"], "\xfe" => [83, "P"], "\xff" => [10, "P"]], ["\x00" => [0, "M0"], "\x01" => [0, "M1"], "\x02" => [0, "M2"], "\x03" => [0, "Ma"], "\x04" => [0, "Mc"], "\x05" => [0, "Me"], "\x06" => [0, "Mi"], "\x07" => [0, "Mo"], "\x08" => [0, "Ms"], "\t" => [0, "Mt"], "\n" => [73, "M"], "\v" => [88, "M"], "\f" => [89, "M"], "\r" => [96, "M"], "\x0e" => [97, "M"], "\x0f" => [99, "M"], "\x10" => [106, "M"], "\x11" => [136, "M"], "\x12" => [139, "M"], "\x13" => [141, "M"], "\x14" => [145, "M"], "\x15" => [147, "M"], "\x16" => [149, "M"], "\x17" => [101, "M"], "\x18" => [112, "M"], "\x19" => [117, "M"], "\x1a" => [120, "M"], "\x1b" => [124, "M"], "\x1c" => [127, "M"], "\x1d" => [144, "M"], "\x1e" => [152, "M"], "\x1f" => [11, "M"], " " => [0, "N0"], "!" => [0, "N1"], "\"" => [0, "N2"], "#" => [0, "Na"], "\$" => [0, "Nc"], "%" => [0, "Ne"], "&" => [0, "Ni"], "'" => [0, "No"], "(" => [0, "Ns"], ")" => [0, "Nt"], "*" => [73, "N"], "+" => [88, "N"], "," => [89, "N"], "-" => [96, "N"], "." => [97, "N"], "/" => [99, "N"], [106, "N"], [136, "N"], [139, "N"], [141, "N"], [145, "N"], [147, "N"], [149, "N"], [101, "N"], [112, "N"], [117, "N"], ":" => [120, "N"], ";" => [124, "N"], "<" => [127, "N"], "=" => [144, "N"], ">" => [152, "N"], "?" => [11, "N"], "@" => [0, "O0"], "A" => [0, "O1"], "B" => [0, "O2"], "C" => [0, "Oa"], "D" => [0, "Oc"], "E" => [0, "Oe"], "F" => [0, "Oi"], "G" => [0, "Oo"], "H" => [0, "Os"], "I" => [0, "Ot"], "J" => [73, "O"], "K" => [88, "O"], "L" => [89, "O"], "M" => [96, "O"], "N" => [97, "O"], "O" => [99, "O"], "P" => [106, "O"], "Q" => [136, "O"], "R" => [139, "O"], "S" => [141, "O"], "T" => [145, "O"], "U" => [147, "O"], "V" => [149, "O"], "W" => [101, "O"], "X" => [112, "O"], "Y" => [117, "O"], "Z" => [120, "O"], "[" => [124, "O"], "\\" => [127, "O"], "]" => [144, "O"], "^" => [152, "O"], "_" => [11, "O"], "`" => [0, "P0"], "a" => [0, "P1"], "b" => [0, "P2"], "c" => [0, "Pa"], "d" => [0, "Pc"], "e" => [0, "Pe"], "f" => [0, "Pi"], "g" => [0, "Po"], "h" => [0, "Ps"], "i" => [0, "Pt"], "j" => [73, "P"], "k" => [88, "P"], "l" => [89, "P"], "m" => [96, "P"], "n" => [97, "P"], "o" => [99, "P"], "p" => [106, "P"], "q" => [136, "P"], "r" => [139, "P"], "s" => [141, "P"], "t" => [145, "P"], "u" => [147, "P"], "v" => [149, "P"], "w" => [101, "P"], "x" => [112, "P"], "y" => [117, "P"], "z" => [120, "P"], "{" => [124, "P"], "|" => [127, "P"], "}" => [144, "P"], "~" => [152, "P"], "" => [11, "P"], "\x80" => [0, "Q0"], "\x81" => [0, "Q1"], "\x82" => [0, "Q2"], "\x83" => [0, "Qa"], "\x84" => [0, "Qc"], "\x85" => [0, "Qe"], "\x86" => [0, "Qi"], "\x87" => [0, "Qo"], "\x88" => [0, "Qs"], "\x89" => [0, "Qt"], "\x8a" => [73, "Q"], "\x8b" => [88, "Q"], "\x8c" => [89, "Q"], "\x8d" => [96, "Q"], "\x8e" => [97, "Q"], "\x8f" => [99, "Q"], "\x90" => [106, "Q"], "\x91" => [136, "Q"], "\x92" => [139, "Q"], "\x93" => [141, "Q"], "\x94" => [145, "Q"], "\x95" => [147, "Q"], "\x96" => [149, "Q"], "\x97" => [101, "Q"], "\x98" => [112, "Q"], "\x99" => [117, "Q"], "\x9a" => [120, "Q"], "\x9b" => [124, "Q"], "\x9c" => [127, "Q"], "\x9d" => [144, "Q"], "\x9e" => [152, "Q"], "\x9f" => [11, "Q"], "\xa0" => [0, "R0"], "\xa1" => [0, "R1"], "\xa2" => [0, "R2"], "\xa3" => [0, "Ra"], "\xa4" => [0, "Rc"], "\xa5" => [0, "Re"], "\xa6" => [0, "Ri"], "\xa7" => [0, "Ro"], "\xa8" => [0, "Rs"], "\xa9" => [0, "Rt"], "\xaa" => [73, "R"], "\xab" => [88, "R"], "\xac" => [89, "R"], "\xad" => [96, "R"], "\xae" => [97, "R"], "\xaf" => [99, "R"], "\xb0" => [106, "R"], "\xb1" => [136, "R"], "\xb2" => [139, "R"], "\xb3" => [141, "R"], "\xb4" => [145, "R"], "\xb5" => [147, "R"], "\xb6" => [149, "R"], "\xb7" => [101, "R"], "\xb8" => [112, "R"], "\xb9" => [117, "R"], "\xba" => [120, "R"], "\xbb" => [124, "R"], "\xbc" => [127, "R"], "\xbd" => [144, "R"], "\xbe" => [152, "R"], "\xbf" => [11, "R"], "\xc0" => [0, "S0"], "\xc1" => [0, "S1"], "\xc2" => [0, "S2"], "\xc3" => [0, "Sa"], "\xc4" => [0, "Sc"], "\xc5" => [0, "Se"], "\xc6" => [0, "Si"], "\xc7" => [0, "So"], "\xc8" => [0, "Ss"], "\xc9" => [0, "St"], "\xca" => [73, "S"], "\xcb" => [88, "S"], "\xcc" => [89, "S"], "\xcd" => [96, "S"], "\xce" => [97, "S"], "\xcf" => [99, "S"], "\xd0" => [106, "S"], "\xd1" => [136, "S"], "\xd2" => [139, "S"], "\xd3" => [141, "S"], "\xd4" => [145, "S"], "\xd5" => [147, "S"], "\xd6" => [149, "S"], "\xd7" => [101, "S"], "\xd8" => [112, "S"], "\xd9" => [117, "S"], "\xda" => [120, "S"], "\xdb" => [124, "S"], "\xdc" => [127, "S"], "\xdd" => [144, "S"], "\xde" => [152, "S"], "\xdf" => [11, "S"], "\xe0" => [0, "T0"], "\xe1" => [0, "T1"], "\xe2" => [0, "T2"], "\xe3" => [0, "Ta"], "\xe4" => [0, "Tc"], "\xe5" => [0, "Te"], "\xe6" => [0, "Ti"], "\xe7" => [0, "To"], "\xe8" => [0, "Ts"], "\xe9" => [0, "Tt"], "\xea" => [73, "T"], "\xeb" => [88, "T"], "\xec" => [89, "T"], "\xed" => [96, "T"], "\xee" => [97, "T"], "\xef" => [99, "T"], "\xf0" => [106, "T"], "\xf1" => [136, "T"], "\xf2" => [139, "T"], "\xf3" => [141, "T"], "\xf4" => [145, "T"], "\xf5" => [147, "T"], "\xf6" => [149, "T"], "\xf7" => [101, "T"], "\xf8" => [112, "T"], "\xf9" => [117, "T"], "\xfa" => [120, "T"], "\xfb" => [124, "T"], "\xfc" => [127, "T"], "\xfd" => [144, "T"], "\xfe" => [152, "T"], "\xff" => [11, "T"]], ["\x00" => [94, "O0"], "\x01" => [76, "O0"], "\x02" => [104, "O0"], "\x03" => [16, "O0"], "\x04" => [94, "O1"], "\x05" => [76, "O1"], "\x06" => [104, "O1"], "\x07" => [16, "O1"], "\x08" => [94, "O2"], "\t" => [76, "O2"], "\n" => [104, "O2"], "\v" => [16, "O2"], "\f" => [94, "Oa"], "\r" => [76, "Oa"], "\x0e" => [104, "Oa"], "\x0f" => [16, "Oa"], "\x10" => [94, "Oc"], "\x11" => [76, "Oc"], "\x12" => [104, "Oc"], "\x13" => [16, "Oc"], "\x14" => [94, "Oe"], "\x15" => [76, "Oe"], "\x16" => [104, "Oe"], "\x17" => [16, "Oe"], "\x18" => [94, "Oi"], "\x19" => [76, "Oi"], "\x1a" => [104, "Oi"], "\x1b" => [16, "Oi"], "\x1c" => [94, "Oo"], "\x1d" => [76, "Oo"], "\x1e" => [104, "Oo"], "\x1f" => [16, "Oo"], " " => [94, "Os"], "!" => [76, "Os"], "\"" => [104, "Os"], "#" => [16, "Os"], "\$" => [94, "Ot"], "%" => [76, "Ot"], "&" => [104, "Ot"], "'" => [16, "Ot"], "(" => [77, "O "], ")" => [18, "O "], "*" => [77, "O%"], "+" => [18, "O%"], "," => [77, "O-"], "-" => [18, "O-"], "." => [77, "O."], "/" => [18, "O."], [77, "O/"], [18, "O/"], [77, "O3"], [18, "O3"], [77, "O4"], [18, "O4"], [77, "O5"], [18, "O5"], [77, "O6"], [18, "O6"], ":" => [77, "O7"], ";" => [18, "O7"], "<" => [77, "O8"], "=" => [18, "O8"], ">" => [77, "O9"], "?" => [18, "O9"], "@" => [77, "O="], "A" => [18, "O="], "B" => [77, "OA"], "C" => [18, "OA"], "D" => [77, "O_"], "E" => [18, "O_"], "F" => [77, "Ob"], "G" => [18, "Ob"], "H" => [77, "Od"], "I" => [18, "Od"], "J" => [77, "Of"], "K" => [18, "Of"], "L" => [77, "Og"], "M" => [18, "Og"], "N" => [77, "Oh"], "O" => [18, "Oh"], "P" => [77, "Ol"], "Q" => [18, "Ol"], "R" => [77, "Om"], "S" => [18, "Om"], "T" => [77, "On"], "U" => [18, "On"], "V" => [77, "Op"], "W" => [18, "Op"], "X" => [77, "Or"], "Y" => [18, "Or"], "Z" => [77, "Ou"], "[" => [18, "Ou"], "\\" => [0, "O:"], "]" => [0, "OB"], "^" => [0, "OC"], "_" => [0, "OD"], "`" => [0, "OE"], "a" => [0, "OF"], "b" => [0, "OG"], "c" => [0, "OH"], "d" => [0, "OI"], "e" => [0, "OJ"], "f" => [0, "OK"], "g" => [0, "OL"], "h" => [0, "OM"], "i" => [0, "ON"], "j" => [0, "OO"], "k" => [0, "OP"], "l" => [0, "OQ"], "m" => [0, "OR"], "n" => [0, "OS"], "o" => [0, "OT"], "p" => [0, "OU"], "q" => [0, "OV"], "r" => [0, "OW"], "s" => [0, "OY"], "t" => [0, "Oj"], "u" => [0, "Ok"], "v" => [0, "Oq"], "w" => [0, "Ov"], "x" => [0, "Ow"], "y" => [0, "Ox"], "z" => [0, "Oy"], "{" => [0, "Oz"], "|" => [82, "O"], "}" => [87, "O"], "~" => [130, "O"], "" => [9, "O"], "\x80" => [94, "P0"], "\x81" => [76, "P0"], "\x82" => [104, "P0"], "\x83" => [16, "P0"], "\x84" => [94, "P1"], "\x85" => [76, "P1"], "\x86" => [104, "P1"], "\x87" => [16, "P1"], "\x88" => [94, "P2"], "\x89" => [76, "P2"], "\x8a" => [104, "P2"], "\x8b" => [16, "P2"], "\x8c" => [94, "Pa"], "\x8d" => [76, "Pa"], "\x8e" => [104, "Pa"], "\x8f" => [16, "Pa"], "\x90" => [94, "Pc"], "\x91" => [76, "Pc"], "\x92" => [104, "Pc"], "\x93" => [16, "Pc"], "\x94" => [94, "Pe"], "\x95" => [76, "Pe"], "\x96" => [104, "Pe"], "\x97" => [16, "Pe"], "\x98" => [94, "Pi"], "\x99" => [76, "Pi"], "\x9a" => [104, "Pi"], "\x9b" => [16, "Pi"], "\x9c" => [94, "Po"], "\x9d" => [76, "Po"], "\x9e" => [104, "Po"], "\x9f" => [16, "Po"], "\xa0" => [94, "Ps"], "\xa1" => [76, "Ps"], "\xa2" => [104, "Ps"], "\xa3" => [16, "Ps"], "\xa4" => [94, "Pt"], "\xa5" => [76, "Pt"], "\xa6" => [104, "Pt"], "\xa7" => [16, "Pt"], "\xa8" => [77, "P "], "\xa9" => [18, "P "], "\xaa" => [77, "P%"], "\xab" => [18, "P%"], "\xac" => [77, "P-"], "\xad" => [18, "P-"], "\xae" => [77, "P."], "\xaf" => [18, "P."], "\xb0" => [77, "P/"], "\xb1" => [18, "P/"], "\xb2" => [77, "P3"], "\xb3" => [18, "P3"], "\xb4" => [77, "P4"], "\xb5" => [18, "P4"], "\xb6" => [77, "P5"], "\xb7" => [18, "P5"], "\xb8" => [77, "P6"], "\xb9" => [18, "P6"], "\xba" => [77, "P7"], "\xbb" => [18, "P7"], "\xbc" => [77, "P8"], "\xbd" => [18, "P8"], "\xbe" => [77, "P9"], "\xbf" => [18, "P9"], "\xc0" => [77, "P="], "\xc1" => [18, "P="], "\xc2" => [77, "PA"], "\xc3" => [18, "PA"], "\xc4" => [77, "P_"], "\xc5" => [18, "P_"], "\xc6" => [77, "Pb"], "\xc7" => [18, "Pb"], "\xc8" => [77, "Pd"], "\xc9" => [18, "Pd"], "\xca" => [77, "Pf"], "\xcb" => [18, "Pf"], "\xcc" => [77, "Pg"], "\xcd" => [18, "Pg"], "\xce" => [77, "Ph"], "\xcf" => [18, "Ph"], "\xd0" => [77, "Pl"], "\xd1" => [18, "Pl"], "\xd2" => [77, "Pm"], "\xd3" => [18, "Pm"], "\xd4" => [77, "Pn"], "\xd5" => [18, "Pn"], "\xd6" => [77, "Pp"], "\xd7" => [18, "Pp"], "\xd8" => [77, "Pr"], "\xd9" => [18, "Pr"], "\xda" => [77, "Pu"], "\xdb" => [18, "Pu"], "\xdc" => [0, "P:"], "\xdd" => [0, "PB"], "\xde" => [0, "PC"], "\xdf" => [0, "PD"], "\xe0" => [0, "PE"], "\xe1" => [0, "PF"], "\xe2" => [0, "PG"], "\xe3" => [0, "PH"], "\xe4" => [0, "PI"], "\xe5" => [0, "PJ"], "\xe6" => [0, "PK"], "\xe7" => [0, "PL"], "\xe8" => [0, "PM"], "\xe9" => [0, "PN"], "\xea" => [0, "PO"], "\xeb" => [0, "PP"], "\xec" => [0, "PQ"], "\xed" => [0, "PR"], "\xee" => [0, "PS"], "\xef" => [0, "PT"], "\xf0" => [0, "PU"], "\xf1" => [0, "PV"], "\xf2" => [0, "PW"], "\xf3" => [0, "PY"], "\xf4" => [0, "Pj"], "\xf5" => [0, "Pk"], "\xf6" => [0, "Pq"], "\xf7" => [0, "Pv"], "\xf8" => [0, "Pw"], "\xf9" => [0, "Px"], "\xfa" => [0, "Py"], "\xfb" => [0, "Pz"], "\xfc" => [82, "P"], "\xfd" => [87, "P"], "\xfe" => [130, "P"], "\xff" => [9, "P"]], ["\x00" => [94, "Q0"], "\x01" => [76, "Q0"], "\x02" => [104, "Q0"], "\x03" => [16, "Q0"], "\x04" => [94, "Q1"], "\x05" => [76, "Q1"], "\x06" => [104, "Q1"], "\x07" => [16, "Q1"], "\x08" => [94, "Q2"], "\t" => [76, "Q2"], "\n" => [104, "Q2"], "\v" => [16, "Q2"], "\f" => [94, "Qa"], "\r" => [76, "Qa"], "\x0e" => [104, "Qa"], "\x0f" => [16, "Qa"], "\x10" => [94, "Qc"], "\x11" => [76, "Qc"], "\x12" => [104, "Qc"], "\x13" => [16, "Qc"], "\x14" => [94, "Qe"], "\x15" => [76, "Qe"], "\x16" => [104, "Qe"], "\x17" => [16, "Qe"], "\x18" => [94, "Qi"], "\x19" => [76, "Qi"], "\x1a" => [104, "Qi"], "\x1b" => [16, "Qi"], "\x1c" => [94, "Qo"], "\x1d" => [76, "Qo"], "\x1e" => [104, "Qo"], "\x1f" => [16, "Qo"], " " => [94, "Qs"], "!" => [76, "Qs"], "\"" => [104, "Qs"], "#" => [16, "Qs"], "\$" => [94, "Qt"], "%" => [76, "Qt"], "&" => [104, "Qt"], "'" => [16, "Qt"], "(" => [77, "Q "], ")" => [18, "Q "], "*" => [77, "Q%"], "+" => [18, "Q%"], "," => [77, "Q-"], "-" => [18, "Q-"], "." => [77, "Q."], "/" => [18, "Q."], [77, "Q/"], [18, "Q/"], [77, "Q3"], [18, "Q3"], [77, "Q4"], [18, "Q4"], [77, "Q5"], [18, "Q5"], [77, "Q6"], [18, "Q6"], ":" => [77, "Q7"], ";" => [18, "Q7"], "<" => [77, "Q8"], "=" => [18, "Q8"], ">" => [77, "Q9"], "?" => [18, "Q9"], "@" => [77, "Q="], "A" => [18, "Q="], "B" => [77, "QA"], "C" => [18, "QA"], "D" => [77, "Q_"], "E" => [18, "Q_"], "F" => [77, "Qb"], "G" => [18, "Qb"], "H" => [77, "Qd"], "I" => [18, "Qd"], "J" => [77, "Qf"], "K" => [18, "Qf"], "L" => [77, "Qg"], "M" => [18, "Qg"], "N" => [77, "Qh"], "O" => [18, "Qh"], "P" => [77, "Ql"], "Q" => [18, "Ql"], "R" => [77, "Qm"], "S" => [18, "Qm"], "T" => [77, "Qn"], "U" => [18, "Qn"], "V" => [77, "Qp"], "W" => [18, "Qp"], "X" => [77, "Qr"], "Y" => [18, "Qr"], "Z" => [77, "Qu"], "[" => [18, "Qu"], "\\" => [0, "Q:"], "]" => [0, "QB"], "^" => [0, "QC"], "_" => [0, "QD"], "`" => [0, "QE"], "a" => [0, "QF"], "b" => [0, "QG"], "c" => [0, "QH"], "d" => [0, "QI"], "e" => [0, "QJ"], "f" => [0, "QK"], "g" => [0, "QL"], "h" => [0, "QM"], "i" => [0, "QN"], "j" => [0, "QO"], "k" => [0, "QP"], "l" => [0, "QQ"], "m" => [0, "QR"], "n" => [0, "QS"], "o" => [0, "QT"], "p" => [0, "QU"], "q" => [0, "QV"], "r" => [0, "QW"], "s" => [0, "QY"], "t" => [0, "Qj"], "u" => [0, "Qk"], "v" => [0, "Qq"], "w" => [0, "Qv"], "x" => [0, "Qw"], "y" => [0, "Qx"], "z" => [0, "Qy"], "{" => [0, "Qz"], "|" => [82, "Q"], "}" => [87, "Q"], "~" => [130, "Q"], "" => [9, "Q"], "\x80" => [94, "R0"], "\x81" => [76, "R0"], "\x82" => [104, "R0"], "\x83" => [16, "R0"], "\x84" => [94, "R1"], "\x85" => [76, "R1"], "\x86" => [104, "R1"], "\x87" => [16, "R1"], "\x88" => [94, "R2"], "\x89" => [76, "R2"], "\x8a" => [104, "R2"], "\x8b" => [16, "R2"], "\x8c" => [94, "Ra"], "\x8d" => [76, "Ra"], "\x8e" => [104, "Ra"], "\x8f" => [16, "Ra"], "\x90" => [94, "Rc"], "\x91" => [76, "Rc"], "\x92" => [104, "Rc"], "\x93" => [16, "Rc"], "\x94" => [94, "Re"], "\x95" => [76, "Re"], "\x96" => [104, "Re"], "\x97" => [16, "Re"], "\x98" => [94, "Ri"], "\x99" => [76, "Ri"], "\x9a" => [104, "Ri"], "\x9b" => [16, "Ri"], "\x9c" => [94, "Ro"], "\x9d" => [76, "Ro"], "\x9e" => [104, "Ro"], "\x9f" => [16, "Ro"], "\xa0" => [94, "Rs"], "\xa1" => [76, "Rs"], "\xa2" => [104, "Rs"], "\xa3" => [16, "Rs"], "\xa4" => [94, "Rt"], "\xa5" => [76, "Rt"], "\xa6" => [104, "Rt"], "\xa7" => [16, "Rt"], "\xa8" => [77, "R "], "\xa9" => [18, "R "], "\xaa" => [77, "R%"], "\xab" => [18, "R%"], "\xac" => [77, "R-"], "\xad" => [18, "R-"], "\xae" => [77, "R."], "\xaf" => [18, "R."], "\xb0" => [77, "R/"], "\xb1" => [18, "R/"], "\xb2" => [77, "R3"], "\xb3" => [18, "R3"], "\xb4" => [77, "R4"], "\xb5" => [18, "R4"], "\xb6" => [77, "R5"], "\xb7" => [18, "R5"], "\xb8" => [77, "R6"], "\xb9" => [18, "R6"], "\xba" => [77, "R7"], "\xbb" => [18, "R7"], "\xbc" => [77, "R8"], "\xbd" => [18, "R8"], "\xbe" => [77, "R9"], "\xbf" => [18, "R9"], "\xc0" => [77, "R="], "\xc1" => [18, "R="], "\xc2" => [77, "RA"], "\xc3" => [18, "RA"], "\xc4" => [77, "R_"], "\xc5" => [18, "R_"], "\xc6" => [77, "Rb"], "\xc7" => [18, "Rb"], "\xc8" => [77, "Rd"], "\xc9" => [18, "Rd"], "\xca" => [77, "Rf"], "\xcb" => [18, "Rf"], "\xcc" => [77, "Rg"], "\xcd" => [18, "Rg"], "\xce" => [77, "Rh"], "\xcf" => [18, "Rh"], "\xd0" => [77, "Rl"], "\xd1" => [18, "Rl"], "\xd2" => [77, "Rm"], "\xd3" => [18, "Rm"], "\xd4" => [77, "Rn"], "\xd5" => [18, "Rn"], "\xd6" => [77, "Rp"], "\xd7" => [18, "Rp"], "\xd8" => [77, "Rr"], "\xd9" => [18, "Rr"], "\xda" => [77, "Ru"], "\xdb" => [18, "Ru"], "\xdc" => [0, "R:"], "\xdd" => [0, "RB"], "\xde" => [0, "RC"], "\xdf" => [0, "RD"], "\xe0" => [0, "RE"], "\xe1" => [0, "RF"], "\xe2" => [0, "RG"], "\xe3" => [0, "RH"], "\xe4" => [0, "RI"], "\xe5" => [0, "RJ"], "\xe6" => [0, "RK"], "\xe7" => [0, "RL"], "\xe8" => [0, "RM"], "\xe9" => [0, "RN"], "\xea" => [0, "RO"], "\xeb" => [0, "RP"], "\xec" => [0, "RQ"], "\xed" => [0, "RR"], "\xee" => [0, "RS"], "\xef" => [0, "RT"], "\xf0" => [0, "RU"], "\xf1" => [0, "RV"], "\xf2" => [0, "RW"], "\xf3" => [0, "RY"], "\xf4" => [0, "Rj"], "\xf5" => [0, "Rk"], "\xf6" => [0, "Rq"], "\xf7" => [0, "Rv"], "\xf8" => [0, "Rw"], "\xf9" => [0, "Rx"], "\xfa" => [0, "Ry"], "\xfb" => [0, "Rz"], "\xfc" => [82, "R"], "\xfd" => [87, "R"], "\xfe" => [130, "R"], "\xff" => [9, "R"]], ["\x00" => [77, "Q0"], "\x01" => [18, "Q0"], "\x02" => [77, "Q1"], "\x03" => [18, "Q1"], "\x04" => [77, "Q2"], "\x05" => [18, "Q2"], "\x06" => [77, "Qa"], "\x07" => [18, "Qa"], "\x08" => [77, "Qc"], "\t" => [18, "Qc"], "\n" => [77, "Qe"], "\v" => [18, "Qe"], "\f" => [77, "Qi"], "\r" => [18, "Qi"], "\x0e" => [77, "Qo"], "\x0f" => [18, "Qo"], "\x10" => [77, "Qs"], "\x11" => [18, "Qs"], "\x12" => [77, "Qt"], "\x13" => [18, "Qt"], "\x14" => [0, "Q "], "\x15" => [0, "Q%"], "\x16" => [0, "Q-"], "\x17" => [0, "Q."], "\x18" => [0, "Q/"], "\x19" => [0, "Q3"], "\x1a" => [0, "Q4"], "\x1b" => [0, "Q5"], "\x1c" => [0, "Q6"], "\x1d" => [0, "Q7"], "\x1e" => [0, "Q8"], "\x1f" => [0, "Q9"], " " => [0, "Q="], "!" => [0, "QA"], "\"" => [0, "Q_"], "#" => [0, "Qb"], "\$" => [0, "Qd"], "%" => [0, "Qf"], "&" => [0, "Qg"], "'" => [0, "Qh"], "(" => [0, "Ql"], ")" => [0, "Qm"], "*" => [0, "Qn"], "+" => [0, "Qp"], "," => [0, "Qr"], "-" => [0, "Qu"], "." => [100, "Q"], "/" => [110, "Q"], [111, "Q"], [115, "Q"], [116, "Q"], [118, "Q"], [119, "Q"], [122, "Q"], [123, "Q"], [125, "Q"], [126, "Q"], [129, "Q"], ":" => [143, "Q"], ";" => [148, "Q"], "<" => [151, "Q"], "=" => [153, "Q"], ">" => [83, "Q"], "?" => [10, "Q"], "@" => [77, "R0"], "A" => [18, "R0"], "B" => [77, "R1"], "C" => [18, "R1"], "D" => [77, "R2"], "E" => [18, "R2"], "F" => [77, "Ra"], "G" => [18, "Ra"], "H" => [77, "Rc"], "I" => [18, "Rc"], "J" => [77, "Re"], "K" => [18, "Re"], "L" => [77, "Ri"], "M" => [18, "Ri"], "N" => [77, "Ro"], "O" => [18, "Ro"], "P" => [77, "Rs"], "Q" => [18, "Rs"], "R" => [77, "Rt"], "S" => [18, "Rt"], "T" => [0, "R "], "U" => [0, "R%"], "V" => [0, "R-"], "W" => [0, "R."], "X" => [0, "R/"], "Y" => [0, "R3"], "Z" => [0, "R4"], "[" => [0, "R5"], "\\" => [0, "R6"], "]" => [0, "R7"], "^" => [0, "R8"], "_" => [0, "R9"], "`" => [0, "R="], "a" => [0, "RA"], "b" => [0, "R_"], "c" => [0, "Rb"], "d" => [0, "Rd"], "e" => [0, "Rf"], "f" => [0, "Rg"], "g" => [0, "Rh"], "h" => [0, "Rl"], "i" => [0, "Rm"], "j" => [0, "Rn"], "k" => [0, "Rp"], "l" => [0, "Rr"], "m" => [0, "Ru"], "n" => [100, "R"], "o" => [110, "R"], "p" => [111, "R"], "q" => [115, "R"], "r" => [116, "R"], "s" => [118, "R"], "t" => [119, "R"], "u" => [122, "R"], "v" => [123, "R"], "w" => [125, "R"], "x" => [126, "R"], "y" => [129, "R"], "z" => [143, "R"], "{" => [148, "R"], "|" => [151, "R"], "}" => [153, "R"], "~" => [83, "R"], "" => [10, "R"], "\x80" => [77, "S0"], "\x81" => [18, "S0"], "\x82" => [77, "S1"], "\x83" => [18, "S1"], "\x84" => [77, "S2"], "\x85" => [18, "S2"], "\x86" => [77, "Sa"], "\x87" => [18, "Sa"], "\x88" => [77, "Sc"], "\x89" => [18, "Sc"], "\x8a" => [77, "Se"], "\x8b" => [18, "Se"], "\x8c" => [77, "Si"], "\x8d" => [18, "Si"], "\x8e" => [77, "So"], "\x8f" => [18, "So"], "\x90" => [77, "Ss"], "\x91" => [18, "Ss"], "\x92" => [77, "St"], "\x93" => [18, "St"], "\x94" => [0, "S "], "\x95" => [0, "S%"], "\x96" => [0, "S-"], "\x97" => [0, "S."], "\x98" => [0, "S/"], "\x99" => [0, "S3"], "\x9a" => [0, "S4"], "\x9b" => [0, "S5"], "\x9c" => [0, "S6"], "\x9d" => [0, "S7"], "\x9e" => [0, "S8"], "\x9f" => [0, "S9"], "\xa0" => [0, "S="], "\xa1" => [0, "SA"], "\xa2" => [0, "S_"], "\xa3" => [0, "Sb"], "\xa4" => [0, "Sd"], "\xa5" => [0, "Sf"], "\xa6" => [0, "Sg"], "\xa7" => [0, "Sh"], "\xa8" => [0, "Sl"], "\xa9" => [0, "Sm"], "\xaa" => [0, "Sn"], "\xab" => [0, "Sp"], "\xac" => [0, "Sr"], "\xad" => [0, "Su"], "\xae" => [100, "S"], "\xaf" => [110, "S"], "\xb0" => [111, "S"], "\xb1" => [115, "S"], "\xb2" => [116, "S"], "\xb3" => [118, "S"], "\xb4" => [119, "S"], "\xb5" => [122, "S"], "\xb6" => [123, "S"], "\xb7" => [125, "S"], "\xb8" => [126, "S"], "\xb9" => [129, "S"], "\xba" => [143, "S"], "\xbb" => [148, "S"], "\xbc" => [151, "S"], "\xbd" => [153, "S"], "\xbe" => [83, "S"], "\xbf" => [10, "S"], "\xc0" => [77, "T0"], "\xc1" => [18, "T0"], "\xc2" => [77, "T1"], "\xc3" => [18, "T1"], "\xc4" => [77, "T2"], "\xc5" => [18, "T2"], "\xc6" => [77, "Ta"], "\xc7" => [18, "Ta"], "\xc8" => [77, "Tc"], "\xc9" => [18, "Tc"], "\xca" => [77, "Te"], "\xcb" => [18, "Te"], "\xcc" => [77, "Ti"], "\xcd" => [18, "Ti"], "\xce" => [77, "To"], "\xcf" => [18, "To"], "\xd0" => [77, "Ts"], "\xd1" => [18, "Ts"], "\xd2" => [77, "Tt"], "\xd3" => [18, "Tt"], "\xd4" => [0, "T "], "\xd5" => [0, "T%"], "\xd6" => [0, "T-"], "\xd7" => [0, "T."], "\xd8" => [0, "T/"], "\xd9" => [0, "T3"], "\xda" => [0, "T4"], "\xdb" => [0, "T5"], "\xdc" => [0, "T6"], "\xdd" => [0, "T7"], "\xde" => [0, "T8"], "\xdf" => [0, "T9"], "\xe0" => [0, "T="], "\xe1" => [0, "TA"], "\xe2" => [0, "T_"], "\xe3" => [0, "Tb"], "\xe4" => [0, "Td"], "\xe5" => [0, "Tf"], "\xe6" => [0, "Tg"], "\xe7" => [0, "Th"], "\xe8" => [0, "Tl"], "\xe9" => [0, "Tm"], "\xea" => [0, "Tn"], "\xeb" => [0, "Tp"], "\xec" => [0, "Tr"], "\xed" => [0, "Tu"], "\xee" => [100, "T"], "\xef" => [110, "T"], "\xf0" => [111, "T"], "\xf1" => [115, "T"], "\xf2" => [116, "T"], "\xf3" => [118, "T"], "\xf4" => [119, "T"], "\xf5" => [122, "T"], "\xf6" => [123, "T"], "\xf7" => [125, "T"], "\xf8" => [126, "T"], "\xf9" => [129, "T"], "\xfa" => [143, "T"], "\xfb" => [148, "T"], "\xfc" => [151, "T"], "\xfd" => [153, "T"], "\xfe" => [83, "T"], "\xff" => [10, "T"]], ["\x00" => [94, "S0"], "\x01" => [76, "S0"], "\x02" => [104, "S0"], "\x03" => [16, "S0"], "\x04" => [94, "S1"], "\x05" => [76, "S1"], "\x06" => [104, "S1"], "\x07" => [16, "S1"], "\x08" => [94, "S2"], "\t" => [76, "S2"], "\n" => [104, "S2"], "\v" => [16, "S2"], "\f" => [94, "Sa"], "\r" => [76, "Sa"], "\x0e" => [104, "Sa"], "\x0f" => [16, "Sa"], "\x10" => [94, "Sc"], "\x11" => [76, "Sc"], "\x12" => [104, "Sc"], "\x13" => [16, "Sc"], "\x14" => [94, "Se"], "\x15" => [76, "Se"], "\x16" => [104, "Se"], "\x17" => [16, "Se"], "\x18" => [94, "Si"], "\x19" => [76, "Si"], "\x1a" => [104, "Si"], "\x1b" => [16, "Si"], "\x1c" => [94, "So"], "\x1d" => [76, "So"], "\x1e" => [104, "So"], "\x1f" => [16, "So"], " " => [94, "Ss"], "!" => [76, "Ss"], "\"" => [104, "Ss"], "#" => [16, "Ss"], "\$" => [94, "St"], "%" => [76, "St"], "&" => [104, "St"], "'" => [16, "St"], "(" => [77, "S "], ")" => [18, "S "], "*" => [77, "S%"], "+" => [18, "S%"], "," => [77, "S-"], "-" => [18, "S-"], "." => [77, "S."], "/" => [18, "S."], [77, "S/"], [18, "S/"], [77, "S3"], [18, "S3"], [77, "S4"], [18, "S4"], [77, "S5"], [18, "S5"], [77, "S6"], [18, "S6"], ":" => [77, "S7"], ";" => [18, "S7"], "<" => [77, "S8"], "=" => [18, "S8"], ">" => [77, "S9"], "?" => [18, "S9"], "@" => [77, "S="], "A" => [18, "S="], "B" => [77, "SA"], "C" => [18, "SA"], "D" => [77, "S_"], "E" => [18, "S_"], "F" => [77, "Sb"], "G" => [18, "Sb"], "H" => [77, "Sd"], "I" => [18, "Sd"], "J" => [77, "Sf"], "K" => [18, "Sf"], "L" => [77, "Sg"], "M" => [18, "Sg"], "N" => [77, "Sh"], "O" => [18, "Sh"], "P" => [77, "Sl"], "Q" => [18, "Sl"], "R" => [77, "Sm"], "S" => [18, "Sm"], "T" => [77, "Sn"], "U" => [18, "Sn"], "V" => [77, "Sp"], "W" => [18, "Sp"], "X" => [77, "Sr"], "Y" => [18, "Sr"], "Z" => [77, "Su"], "[" => [18, "Su"], "\\" => [0, "S:"], "]" => [0, "SB"], "^" => [0, "SC"], "_" => [0, "SD"], "`" => [0, "SE"], "a" => [0, "SF"], "b" => [0, "SG"], "c" => [0, "SH"], "d" => [0, "SI"], "e" => [0, "SJ"], "f" => [0, "SK"], "g" => [0, "SL"], "h" => [0, "SM"], "i" => [0, "SN"], "j" => [0, "SO"], "k" => [0, "SP"], "l" => [0, "SQ"], "m" => [0, "SR"], "n" => [0, "SS"], "o" => [0, "ST"], "p" => [0, "SU"], "q" => [0, "SV"], "r" => [0, "SW"], "s" => [0, "SY"], "t" => [0, "Sj"], "u" => [0, "Sk"], "v" => [0, "Sq"], "w" => [0, "Sv"], "x" => [0, "Sw"], "y" => [0, "Sx"], "z" => [0, "Sy"], "{" => [0, "Sz"], "|" => [82, "S"], "}" => [87, "S"], "~" => [130, "S"], "" => [9, "S"], "\x80" => [94, "T0"], "\x81" => [76, "T0"], "\x82" => [104, "T0"], "\x83" => [16, "T0"], "\x84" => [94, "T1"], "\x85" => [76, "T1"], "\x86" => [104, "T1"], "\x87" => [16, "T1"], "\x88" => [94, "T2"], "\x89" => [76, "T2"], "\x8a" => [104, "T2"], "\x8b" => [16, "T2"], "\x8c" => [94, "Ta"], "\x8d" => [76, "Ta"], "\x8e" => [104, "Ta"], "\x8f" => [16, "Ta"], "\x90" => [94, "Tc"], "\x91" => [76, "Tc"], "\x92" => [104, "Tc"], "\x93" => [16, "Tc"], "\x94" => [94, "Te"], "\x95" => [76, "Te"], "\x96" => [104, "Te"], "\x97" => [16, "Te"], "\x98" => [94, "Ti"], "\x99" => [76, "Ti"], "\x9a" => [104, "Ti"], "\x9b" => [16, "Ti"], "\x9c" => [94, "To"], "\x9d" => [76, "To"], "\x9e" => [104, "To"], "\x9f" => [16, "To"], "\xa0" => [94, "Ts"], "\xa1" => [76, "Ts"], "\xa2" => [104, "Ts"], "\xa3" => [16, "Ts"], "\xa4" => [94, "Tt"], "\xa5" => [76, "Tt"], "\xa6" => [104, "Tt"], "\xa7" => [16, "Tt"], "\xa8" => [77, "T "], "\xa9" => [18, "T "], "\xaa" => [77, "T%"], "\xab" => [18, "T%"], "\xac" => [77, "T-"], "\xad" => [18, "T-"], "\xae" => [77, "T."], "\xaf" => [18, "T."], "\xb0" => [77, "T/"], "\xb1" => [18, "T/"], "\xb2" => [77, "T3"], "\xb3" => [18, "T3"], "\xb4" => [77, "T4"], "\xb5" => [18, "T4"], "\xb6" => [77, "T5"], "\xb7" => [18, "T5"], "\xb8" => [77, "T6"], "\xb9" => [18, "T6"], "\xba" => [77, "T7"], "\xbb" => [18, "T7"], "\xbc" => [77, "T8"], "\xbd" => [18, "T8"], "\xbe" => [77, "T9"], "\xbf" => [18, "T9"], "\xc0" => [77, "T="], "\xc1" => [18, "T="], "\xc2" => [77, "TA"], "\xc3" => [18, "TA"], "\xc4" => [77, "T_"], "\xc5" => [18, "T_"], "\xc6" => [77, "Tb"], "\xc7" => [18, "Tb"], "\xc8" => [77, "Td"], "\xc9" => [18, "Td"], "\xca" => [77, "Tf"], "\xcb" => [18, "Tf"], "\xcc" => [77, "Tg"], "\xcd" => [18, "Tg"], "\xce" => [77, "Th"], "\xcf" => [18, "Th"], "\xd0" => [77, "Tl"], "\xd1" => [18, "Tl"], "\xd2" => [77, "Tm"], "\xd3" => [18, "Tm"], "\xd4" => [77, "Tn"], "\xd5" => [18, "Tn"], "\xd6" => [77, "Tp"], "\xd7" => [18, "Tp"], "\xd8" => [77, "Tr"], "\xd9" => [18, "Tr"], "\xda" => [77, "Tu"], "\xdb" => [18, "Tu"], "\xdc" => [0, "T:"], "\xdd" => [0, "TB"], "\xde" => [0, "TC"], "\xdf" => [0, "TD"], "\xe0" => [0, "TE"], "\xe1" => [0, "TF"], "\xe2" => [0, "TG"], "\xe3" => [0, "TH"], "\xe4" => [0, "TI"], "\xe5" => [0, "TJ"], "\xe6" => [0, "TK"], "\xe7" => [0, "TL"], "\xe8" => [0, "TM"], "\xe9" => [0, "TN"], "\xea" => [0, "TO"], "\xeb" => [0, "TP"], "\xec" => [0, "TQ"], "\xed" => [0, "TR"], "\xee" => [0, "TS"], "\xef" => [0, "TT"], "\xf0" => [0, "TU"], "\xf1" => [0, "TV"], "\xf2" => [0, "TW"], "\xf3" => [0, "TY"], "\xf4" => [0, "Tj"], "\xf5" => [0, "Tk"], "\xf6" => [0, "Tq"], "\xf7" => [0, "Tv"], "\xf8" => [0, "Tw"], "\xf9" => [0, "Tx"], "\xfa" => [0, "Ty"], "\xfb" => [0, "Tz"], "\xfc" => [82, "T"], "\xfd" => [87, "T"], "\xfe" => [130, "T"], "\xff" => [9, "T"]], ["\x00" => [94, "U0"], "\x01" => [76, "U0"], "\x02" => [104, "U0"], "\x03" => [16, "U0"], "\x04" => [94, "U1"], "\x05" => [76, "U1"], "\x06" => [104, "U1"], "\x07" => [16, "U1"], "\x08" => [94, "U2"], "\t" => [76, "U2"], "\n" => [104, "U2"], "\v" => [16, "U2"], "\f" => [94, "Ua"], "\r" => [76, "Ua"], "\x0e" => [104, "Ua"], "\x0f" => [16, "Ua"], "\x10" => [94, "Uc"], "\x11" => [76, "Uc"], "\x12" => [104, "Uc"], "\x13" => [16, "Uc"], "\x14" => [94, "Ue"], "\x15" => [76, "Ue"], "\x16" => [104, "Ue"], "\x17" => [16, "Ue"], "\x18" => [94, "Ui"], "\x19" => [76, "Ui"], "\x1a" => [104, "Ui"], "\x1b" => [16, "Ui"], "\x1c" => [94, "Uo"], "\x1d" => [76, "Uo"], "\x1e" => [104, "Uo"], "\x1f" => [16, "Uo"], " " => [94, "Us"], "!" => [76, "Us"], "\"" => [104, "Us"], "#" => [16, "Us"], "\$" => [94, "Ut"], "%" => [76, "Ut"], "&" => [104, "Ut"], "'" => [16, "Ut"], "(" => [77, "U "], ")" => [18, "U "], "*" => [77, "U%"], "+" => [18, "U%"], "," => [77, "U-"], "-" => [18, "U-"], "." => [77, "U."], "/" => [18, "U."], [77, "U/"], [18, "U/"], [77, "U3"], [18, "U3"], [77, "U4"], [18, "U4"], [77, "U5"], [18, "U5"], [77, "U6"], [18, "U6"], ":" => [77, "U7"], ";" => [18, "U7"], "<" => [77, "U8"], "=" => [18, "U8"], ">" => [77, "U9"], "?" => [18, "U9"], "@" => [77, "U="], "A" => [18, "U="], "B" => [77, "UA"], "C" => [18, "UA"], "D" => [77, "U_"], "E" => [18, "U_"], "F" => [77, "Ub"], "G" => [18, "Ub"], "H" => [77, "Ud"], "I" => [18, "Ud"], "J" => [77, "Uf"], "K" => [18, "Uf"], "L" => [77, "Ug"], "M" => [18, "Ug"], "N" => [77, "Uh"], "O" => [18, "Uh"], "P" => [77, "Ul"], "Q" => [18, "Ul"], "R" => [77, "Um"], "S" => [18, "Um"], "T" => [77, "Un"], "U" => [18, "Un"], "V" => [77, "Up"], "W" => [18, "Up"], "X" => [77, "Ur"], "Y" => [18, "Ur"], "Z" => [77, "Uu"], "[" => [18, "Uu"], "\\" => [0, "U:"], "]" => [0, "UB"], "^" => [0, "UC"], "_" => [0, "UD"], "`" => [0, "UE"], "a" => [0, "UF"], "b" => [0, "UG"], "c" => [0, "UH"], "d" => [0, "UI"], "e" => [0, "UJ"], "f" => [0, "UK"], "g" => [0, "UL"], "h" => [0, "UM"], "i" => [0, "UN"], "j" => [0, "UO"], "k" => [0, "UP"], "l" => [0, "UQ"], "m" => [0, "UR"], "n" => [0, "US"], "o" => [0, "UT"], "p" => [0, "UU"], "q" => [0, "UV"], "r" => [0, "UW"], "s" => [0, "UY"], "t" => [0, "Uj"], "u" => [0, "Uk"], "v" => [0, "Uq"], "w" => [0, "Uv"], "x" => [0, "Uw"], "y" => [0, "Ux"], "z" => [0, "Uy"], "{" => [0, "Uz"], "|" => [82, "U"], "}" => [87, "U"], "~" => [130, "U"], "" => [9, "U"], "\x80" => [94, "V0"], "\x81" => [76, "V0"], "\x82" => [104, "V0"], "\x83" => [16, "V0"], "\x84" => [94, "V1"], "\x85" => [76, "V1"], "\x86" => [104, "V1"], "\x87" => [16, "V1"], "\x88" => [94, "V2"], "\x89" => [76, "V2"], "\x8a" => [104, "V2"], "\x8b" => [16, "V2"], "\x8c" => [94, "Va"], "\x8d" => [76, "Va"], "\x8e" => [104, "Va"], "\x8f" => [16, "Va"], "\x90" => [94, "Vc"], "\x91" => [76, "Vc"], "\x92" => [104, "Vc"], "\x93" => [16, "Vc"], "\x94" => [94, "Ve"], "\x95" => [76, "Ve"], "\x96" => [104, "Ve"], "\x97" => [16, "Ve"], "\x98" => [94, "Vi"], "\x99" => [76, "Vi"], "\x9a" => [104, "Vi"], "\x9b" => [16, "Vi"], "\x9c" => [94, "Vo"], "\x9d" => [76, "Vo"], "\x9e" => [104, "Vo"], "\x9f" => [16, "Vo"], "\xa0" => [94, "Vs"], "\xa1" => [76, "Vs"], "\xa2" => [104, "Vs"], "\xa3" => [16, "Vs"], "\xa4" => [94, "Vt"], "\xa5" => [76, "Vt"], "\xa6" => [104, "Vt"], "\xa7" => [16, "Vt"], "\xa8" => [77, "V "], "\xa9" => [18, "V "], "\xaa" => [77, "V%"], "\xab" => [18, "V%"], "\xac" => [77, "V-"], "\xad" => [18, "V-"], "\xae" => [77, "V."], "\xaf" => [18, "V."], "\xb0" => [77, "V/"], "\xb1" => [18, "V/"], "\xb2" => [77, "V3"], "\xb3" => [18, "V3"], "\xb4" => [77, "V4"], "\xb5" => [18, "V4"], "\xb6" => [77, "V5"], "\xb7" => [18, "V5"], "\xb8" => [77, "V6"], "\xb9" => [18, "V6"], "\xba" => [77, "V7"], "\xbb" => [18, "V7"], "\xbc" => [77, "V8"], "\xbd" => [18, "V8"], "\xbe" => [77, "V9"], "\xbf" => [18, "V9"], "\xc0" => [77, "V="], "\xc1" => [18, "V="], "\xc2" => [77, "VA"], "\xc3" => [18, "VA"], "\xc4" => [77, "V_"], "\xc5" => [18, "V_"], "\xc6" => [77, "Vb"], "\xc7" => [18, "Vb"], "\xc8" => [77, "Vd"], "\xc9" => [18, "Vd"], "\xca" => [77, "Vf"], "\xcb" => [18, "Vf"], "\xcc" => [77, "Vg"], "\xcd" => [18, "Vg"], "\xce" => [77, "Vh"], "\xcf" => [18, "Vh"], "\xd0" => [77, "Vl"], "\xd1" => [18, "Vl"], "\xd2" => [77, "Vm"], "\xd3" => [18, "Vm"], "\xd4" => [77, "Vn"], "\xd5" => [18, "Vn"], "\xd6" => [77, "Vp"], "\xd7" => [18, "Vp"], "\xd8" => [77, "Vr"], "\xd9" => [18, "Vr"], "\xda" => [77, "Vu"], "\xdb" => [18, "Vu"], "\xdc" => [0, "V:"], "\xdd" => [0, "VB"], "\xde" => [0, "VC"], "\xdf" => [0, "VD"], "\xe0" => [0, "VE"], "\xe1" => [0, "VF"], "\xe2" => [0, "VG"], "\xe3" => [0, "VH"], "\xe4" => [0, "VI"], "\xe5" => [0, "VJ"], "\xe6" => [0, "VK"], "\xe7" => [0, "VL"], "\xe8" => [0, "VM"], "\xe9" => [0, "VN"], "\xea" => [0, "VO"], "\xeb" => [0, "VP"], "\xec" => [0, "VQ"], "\xed" => [0, "VR"], "\xee" => [0, "VS"], "\xef" => [0, "VT"], "\xf0" => [0, "VU"], "\xf1" => [0, "VV"], "\xf2" => [0, "VW"], "\xf3" => [0, "VY"], "\xf4" => [0, "Vj"], "\xf5" => [0, "Vk"], "\xf6" => [0, "Vq"], "\xf7" => [0, "Vv"], "\xf8" => [0, "Vw"], "\xf9" => [0, "Vx"], "\xfa" => [0, "Vy"], "\xfb" => [0, "Vz"], "\xfc" => [82, "V"], "\xfd" => [87, "V"], "\xfe" => [130, "V"], "\xff" => [9, "V"]], ["\x00" => [77, "U0"], "\x01" => [18, "U0"], "\x02" => [77, "U1"], "\x03" => [18, "U1"], "\x04" => [77, "U2"], "\x05" => [18, "U2"], "\x06" => [77, "Ua"], "\x07" => [18, "Ua"], "\x08" => [77, "Uc"], "\t" => [18, "Uc"], "\n" => [77, "Ue"], "\v" => [18, "Ue"], "\f" => [77, "Ui"], "\r" => [18, "Ui"], "\x0e" => [77, "Uo"], "\x0f" => [18, "Uo"], "\x10" => [77, "Us"], "\x11" => [18, "Us"], "\x12" => [77, "Ut"], "\x13" => [18, "Ut"], "\x14" => [0, "U "], "\x15" => [0, "U%"], "\x16" => [0, "U-"], "\x17" => [0, "U."], "\x18" => [0, "U/"], "\x19" => [0, "U3"], "\x1a" => [0, "U4"], "\x1b" => [0, "U5"], "\x1c" => [0, "U6"], "\x1d" => [0, "U7"], "\x1e" => [0, "U8"], "\x1f" => [0, "U9"], " " => [0, "U="], "!" => [0, "UA"], "\"" => [0, "U_"], "#" => [0, "Ub"], "\$" => [0, "Ud"], "%" => [0, "Uf"], "&" => [0, "Ug"], "'" => [0, "Uh"], "(" => [0, "Ul"], ")" => [0, "Um"], "*" => [0, "Un"], "+" => [0, "Up"], "," => [0, "Ur"], "-" => [0, "Uu"], "." => [100, "U"], "/" => [110, "U"], [111, "U"], [115, "U"], [116, "U"], [118, "U"], [119, "U"], [122, "U"], [123, "U"], [125, "U"], [126, "U"], [129, "U"], ":" => [143, "U"], ";" => [148, "U"], "<" => [151, "U"], "=" => [153, "U"], ">" => [83, "U"], "?" => [10, "U"], "@" => [77, "V0"], "A" => [18, "V0"], "B" => [77, "V1"], "C" => [18, "V1"], "D" => [77, "V2"], "E" => [18, "V2"], "F" => [77, "Va"], "G" => [18, "Va"], "H" => [77, "Vc"], "I" => [18, "Vc"], "J" => [77, "Ve"], "K" => [18, "Ve"], "L" => [77, "Vi"], "M" => [18, "Vi"], "N" => [77, "Vo"], "O" => [18, "Vo"], "P" => [77, "Vs"], "Q" => [18, "Vs"], "R" => [77, "Vt"], "S" => [18, "Vt"], "T" => [0, "V "], "U" => [0, "V%"], "V" => [0, "V-"], "W" => [0, "V."], "X" => [0, "V/"], "Y" => [0, "V3"], "Z" => [0, "V4"], "[" => [0, "V5"], "\\" => [0, "V6"], "]" => [0, "V7"], "^" => [0, "V8"], "_" => [0, "V9"], "`" => [0, "V="], "a" => [0, "VA"], "b" => [0, "V_"], "c" => [0, "Vb"], "d" => [0, "Vd"], "e" => [0, "Vf"], "f" => [0, "Vg"], "g" => [0, "Vh"], "h" => [0, "Vl"], "i" => [0, "Vm"], "j" => [0, "Vn"], "k" => [0, "Vp"], "l" => [0, "Vr"], "m" => [0, "Vu"], "n" => [100, "V"], "o" => [110, "V"], "p" => [111, "V"], "q" => [115, "V"], "r" => [116, "V"], "s" => [118, "V"], "t" => [119, "V"], "u" => [122, "V"], "v" => [123, "V"], "w" => [125, "V"], "x" => [126, "V"], "y" => [129, "V"], "z" => [143, "V"], "{" => [148, "V"], "|" => [151, "V"], "}" => [153, "V"], "~" => [83, "V"], "" => [10, "V"], "\x80" => [77, "W0"], "\x81" => [18, "W0"], "\x82" => [77, "W1"], "\x83" => [18, "W1"], "\x84" => [77, "W2"], "\x85" => [18, "W2"], "\x86" => [77, "Wa"], "\x87" => [18, "Wa"], "\x88" => [77, "Wc"], "\x89" => [18, "Wc"], "\x8a" => [77, "We"], "\x8b" => [18, "We"], "\x8c" => [77, "Wi"], "\x8d" => [18, "Wi"], "\x8e" => [77, "Wo"], "\x8f" => [18, "Wo"], "\x90" => [77, "Ws"], "\x91" => [18, "Ws"], "\x92" => [77, "Wt"], "\x93" => [18, "Wt"], "\x94" => [0, "W "], "\x95" => [0, "W%"], "\x96" => [0, "W-"], "\x97" => [0, "W."], "\x98" => [0, "W/"], "\x99" => [0, "W3"], "\x9a" => [0, "W4"], "\x9b" => [0, "W5"], "\x9c" => [0, "W6"], "\x9d" => [0, "W7"], "\x9e" => [0, "W8"], "\x9f" => [0, "W9"], "\xa0" => [0, "W="], "\xa1" => [0, "WA"], "\xa2" => [0, "W_"], "\xa3" => [0, "Wb"], "\xa4" => [0, "Wd"], "\xa5" => [0, "Wf"], "\xa6" => [0, "Wg"], "\xa7" => [0, "Wh"], "\xa8" => [0, "Wl"], "\xa9" => [0, "Wm"], "\xaa" => [0, "Wn"], "\xab" => [0, "Wp"], "\xac" => [0, "Wr"], "\xad" => [0, "Wu"], "\xae" => [100, "W"], "\xaf" => [110, "W"], "\xb0" => [111, "W"], "\xb1" => [115, "W"], "\xb2" => [116, "W"], "\xb3" => [118, "W"], "\xb4" => [119, "W"], "\xb5" => [122, "W"], "\xb6" => [123, "W"], "\xb7" => [125, "W"], "\xb8" => [126, "W"], "\xb9" => [129, "W"], "\xba" => [143, "W"], "\xbb" => [148, "W"], "\xbc" => [151, "W"], "\xbd" => [153, "W"], "\xbe" => [83, "W"], "\xbf" => [10, "W"], "\xc0" => [77, "Y0"], "\xc1" => [18, "Y0"], "\xc2" => [77, "Y1"], "\xc3" => [18, "Y1"], "\xc4" => [77, "Y2"], "\xc5" => [18, "Y2"], "\xc6" => [77, "Ya"], "\xc7" => [18, "Ya"], "\xc8" => [77, "Yc"], "\xc9" => [18, "Yc"], "\xca" => [77, "Ye"], "\xcb" => [18, "Ye"], "\xcc" => [77, "Yi"], "\xcd" => [18, "Yi"], "\xce" => [77, "Yo"], "\xcf" => [18, "Yo"], "\xd0" => [77, "Ys"], "\xd1" => [18, "Ys"], "\xd2" => [77, "Yt"], "\xd3" => [18, "Yt"], "\xd4" => [0, "Y "], "\xd5" => [0, "Y%"], "\xd6" => [0, "Y-"], "\xd7" => [0, "Y."], "\xd8" => [0, "Y/"], "\xd9" => [0, "Y3"], "\xda" => [0, "Y4"], "\xdb" => [0, "Y5"], "\xdc" => [0, "Y6"], "\xdd" => [0, "Y7"], "\xde" => [0, "Y8"], "\xdf" => [0, "Y9"], "\xe0" => [0, "Y="], "\xe1" => [0, "YA"], "\xe2" => [0, "Y_"], "\xe3" => [0, "Yb"], "\xe4" => [0, "Yd"], "\xe5" => [0, "Yf"], "\xe6" => [0, "Yg"], "\xe7" => [0, "Yh"], "\xe8" => [0, "Yl"], "\xe9" => [0, "Ym"], "\xea" => [0, "Yn"], "\xeb" => [0, "Yp"], "\xec" => [0, "Yr"], "\xed" => [0, "Yu"], "\xee" => [100, "Y"], "\xef" => [110, "Y"], "\xf0" => [111, "Y"], "\xf1" => [115, "Y"], "\xf2" => [116, "Y"], "\xf3" => [118, "Y"], "\xf4" => [119, "Y"], "\xf5" => [122, "Y"], "\xf6" => [123, "Y"], "\xf7" => [125, "Y"], "\xf8" => [126, "Y"], "\xf9" => [129, "Y"], "\xfa" => [143, "Y"], "\xfb" => [148, "Y"], "\xfc" => [151, "Y"], "\xfd" => [153, "Y"], "\xfe" => [83, "Y"], "\xff" => [10, "Y"]], ["\x00" => [0, "U0"], "\x01" => [0, "U1"], "\x02" => [0, "U2"], "\x03" => [0, "Ua"], "\x04" => [0, "Uc"], "\x05" => [0, "Ue"], "\x06" => [0, "Ui"], "\x07" => [0, "Uo"], "\x08" => [0, "Us"], "\t" => [0, "Ut"], "\n" => [73, "U"], "\v" => [88, "U"], "\f" => [89, "U"], "\r" => [96, "U"], "\x0e" => [97, "U"], "\x0f" => [99, "U"], "\x10" => [106, "U"], "\x11" => [136, "U"], "\x12" => [139, "U"], "\x13" => [141, "U"], "\x14" => [145, "U"], "\x15" => [147, "U"], "\x16" => [149, "U"], "\x17" => [101, "U"], "\x18" => [112, "U"], "\x19" => [117, "U"], "\x1a" => [120, "U"], "\x1b" => [124, "U"], "\x1c" => [127, "U"], "\x1d" => [144, "U"], "\x1e" => [152, "U"], "\x1f" => [11, "U"], " " => [0, "V0"], "!" => [0, "V1"], "\"" => [0, "V2"], "#" => [0, "Va"], "\$" => [0, "Vc"], "%" => [0, "Ve"], "&" => [0, "Vi"], "'" => [0, "Vo"], "(" => [0, "Vs"], ")" => [0, "Vt"], "*" => [73, "V"], "+" => [88, "V"], "," => [89, "V"], "-" => [96, "V"], "." => [97, "V"], "/" => [99, "V"], [106, "V"], [136, "V"], [139, "V"], [141, "V"], [145, "V"], [147, "V"], [149, "V"], [101, "V"], [112, "V"], [117, "V"], ":" => [120, "V"], ";" => [124, "V"], "<" => [127, "V"], "=" => [144, "V"], ">" => [152, "V"], "?" => [11, "V"], "@" => [0, "W0"], "A" => [0, "W1"], "B" => [0, "W2"], "C" => [0, "Wa"], "D" => [0, "Wc"], "E" => [0, "We"], "F" => [0, "Wi"], "G" => [0, "Wo"], "H" => [0, "Ws"], "I" => [0, "Wt"], "J" => [73, "W"], "K" => [88, "W"], "L" => [89, "W"], "M" => [96, "W"], "N" => [97, "W"], "O" => [99, "W"], "P" => [106, "W"], "Q" => [136, "W"], "R" => [139, "W"], "S" => [141, "W"], "T" => [145, "W"], "U" => [147, "W"], "V" => [149, "W"], "W" => [101, "W"], "X" => [112, "W"], "Y" => [117, "W"], "Z" => [120, "W"], "[" => [124, "W"], "\\" => [127, "W"], "]" => [144, "W"], "^" => [152, "W"], "_" => [11, "W"], "`" => [0, "Y0"], "a" => [0, "Y1"], "b" => [0, "Y2"], "c" => [0, "Ya"], "d" => [0, "Yc"], "e" => [0, "Ye"], "f" => [0, "Yi"], "g" => [0, "Yo"], "h" => [0, "Ys"], "i" => [0, "Yt"], "j" => [73, "Y"], "k" => [88, "Y"], "l" => [89, "Y"], "m" => [96, "Y"], "n" => [97, "Y"], "o" => [99, "Y"], "p" => [106, "Y"], "q" => [136, "Y"], "r" => [139, "Y"], "s" => [141, "Y"], "t" => [145, "Y"], "u" => [147, "Y"], "v" => [149, "Y"], "w" => [101, "Y"], "x" => [112, "Y"], "y" => [117, "Y"], "z" => [120, "Y"], "{" => [124, "Y"], "|" => [127, "Y"], "}" => [144, "Y"], "~" => [152, "Y"], "" => [11, "Y"], "\x80" => [0, "j0"], "\x81" => [0, "j1"], "\x82" => [0, "j2"], "\x83" => [0, "ja"], "\x84" => [0, "jc"], "\x85" => [0, "je"], "\x86" => [0, "ji"], "\x87" => [0, "jo"], "\x88" => [0, "js"], "\x89" => [0, "jt"], "\x8a" => [73, "j"], "\x8b" => [88, "j"], "\x8c" => [89, "j"], "\x8d" => [96, "j"], "\x8e" => [97, "j"], "\x8f" => [99, "j"], "\x90" => [106, "j"], "\x91" => [136, "j"], "\x92" => [139, "j"], "\x93" => [141, "j"], "\x94" => [145, "j"], "\x95" => [147, "j"], "\x96" => [149, "j"], "\x97" => [101, "j"], "\x98" => [112, "j"], "\x99" => [117, "j"], "\x9a" => [120, "j"], "\x9b" => [124, "j"], "\x9c" => [127, "j"], "\x9d" => [144, "j"], "\x9e" => [152, "j"], "\x9f" => [11, "j"], "\xa0" => [0, "k0"], "\xa1" => [0, "k1"], "\xa2" => [0, "k2"], "\xa3" => [0, "ka"], "\xa4" => [0, "kc"], "\xa5" => [0, "ke"], "\xa6" => [0, "ki"], "\xa7" => [0, "ko"], "\xa8" => [0, "ks"], "\xa9" => [0, "kt"], "\xaa" => [73, "k"], "\xab" => [88, "k"], "\xac" => [89, "k"], "\xad" => [96, "k"], "\xae" => [97, "k"], "\xaf" => [99, "k"], "\xb0" => [106, "k"], "\xb1" => [136, "k"], "\xb2" => [139, "k"], "\xb3" => [141, "k"], "\xb4" => [145, "k"], "\xb5" => [147, "k"], "\xb6" => [149, "k"], "\xb7" => [101, "k"], "\xb8" => [112, "k"], "\xb9" => [117, "k"], "\xba" => [120, "k"], "\xbb" => [124, "k"], "\xbc" => [127, "k"], "\xbd" => [144, "k"], "\xbe" => [152, "k"], "\xbf" => [11, "k"], "\xc0" => [0, "q0"], "\xc1" => [0, "q1"], "\xc2" => [0, "q2"], "\xc3" => [0, "qa"], "\xc4" => [0, "qc"], "\xc5" => [0, "qe"], "\xc6" => [0, "qi"], "\xc7" => [0, "qo"], "\xc8" => [0, "qs"], "\xc9" => [0, "qt"], "\xca" => [73, "q"], "\xcb" => [88, "q"], "\xcc" => [89, "q"], "\xcd" => [96, "q"], "\xce" => [97, "q"], "\xcf" => [99, "q"], "\xd0" => [106, "q"], "\xd1" => [136, "q"], "\xd2" => [139, "q"], "\xd3" => [141, "q"], "\xd4" => [145, "q"], "\xd5" => [147, "q"], "\xd6" => [149, "q"], "\xd7" => [101, "q"], "\xd8" => [112, "q"], "\xd9" => [117, "q"], "\xda" => [120, "q"], "\xdb" => [124, "q"], "\xdc" => [127, "q"], "\xdd" => [144, "q"], "\xde" => [152, "q"], "\xdf" => [11, "q"], "\xe0" => [0, "v0"], "\xe1" => [0, "v1"], "\xe2" => [0, "v2"], "\xe3" => [0, "va"], "\xe4" => [0, "vc"], "\xe5" => [0, "ve"], "\xe6" => [0, "vi"], "\xe7" => [0, "vo"], "\xe8" => [0, "vs"], "\xe9" => [0, "vt"], "\xea" => [73, "v"], "\xeb" => [88, "v"], "\xec" => [89, "v"], "\xed" => [96, "v"], "\xee" => [97, "v"], "\xef" => [99, "v"], "\xf0" => [106, "v"], "\xf1" => [136, "v"], "\xf2" => [139, "v"], "\xf3" => [141, "v"], "\xf4" => [145, "v"], "\xf5" => [147, "v"], "\xf6" => [149, "v"], "\xf7" => [101, "v"], "\xf8" => [112, "v"], "\xf9" => [117, "v"], "\xfa" => [120, "v"], "\xfb" => [124, "v"], "\xfc" => [127, "v"], "\xfd" => [144, "v"], "\xfe" => [152, "v"], "\xff" => [11, "v"]], ["\x00" => [94, "W0"], "\x01" => [76, "W0"], "\x02" => [104, "W0"], "\x03" => [16, "W0"], "\x04" => [94, "W1"], "\x05" => [76, "W1"], "\x06" => [104, "W1"], "\x07" => [16, "W1"], "\x08" => [94, "W2"], "\t" => [76, "W2"], "\n" => [104, "W2"], "\v" => [16, "W2"], "\f" => [94, "Wa"], "\r" => [76, "Wa"], "\x0e" => [104, "Wa"], "\x0f" => [16, "Wa"], "\x10" => [94, "Wc"], "\x11" => [76, "Wc"], "\x12" => [104, "Wc"], "\x13" => [16, "Wc"], "\x14" => [94, "We"], "\x15" => [76, "We"], "\x16" => [104, "We"], "\x17" => [16, "We"], "\x18" => [94, "Wi"], "\x19" => [76, "Wi"], "\x1a" => [104, "Wi"], "\x1b" => [16, "Wi"], "\x1c" => [94, "Wo"], "\x1d" => [76, "Wo"], "\x1e" => [104, "Wo"], "\x1f" => [16, "Wo"], " " => [94, "Ws"], "!" => [76, "Ws"], "\"" => [104, "Ws"], "#" => [16, "Ws"], "\$" => [94, "Wt"], "%" => [76, "Wt"], "&" => [104, "Wt"], "'" => [16, "Wt"], "(" => [77, "W "], ")" => [18, "W "], "*" => [77, "W%"], "+" => [18, "W%"], "," => [77, "W-"], "-" => [18, "W-"], "." => [77, "W."], "/" => [18, "W."], [77, "W/"], [18, "W/"], [77, "W3"], [18, "W3"], [77, "W4"], [18, "W4"], [77, "W5"], [18, "W5"], [77, "W6"], [18, "W6"], ":" => [77, "W7"], ";" => [18, "W7"], "<" => [77, "W8"], "=" => [18, "W8"], ">" => [77, "W9"], "?" => [18, "W9"], "@" => [77, "W="], "A" => [18, "W="], "B" => [77, "WA"], "C" => [18, "WA"], "D" => [77, "W_"], "E" => [18, "W_"], "F" => [77, "Wb"], "G" => [18, "Wb"], "H" => [77, "Wd"], "I" => [18, "Wd"], "J" => [77, "Wf"], "K" => [18, "Wf"], "L" => [77, "Wg"], "M" => [18, "Wg"], "N" => [77, "Wh"], "O" => [18, "Wh"], "P" => [77, "Wl"], "Q" => [18, "Wl"], "R" => [77, "Wm"], "S" => [18, "Wm"], "T" => [77, "Wn"], "U" => [18, "Wn"], "V" => [77, "Wp"], "W" => [18, "Wp"], "X" => [77, "Wr"], "Y" => [18, "Wr"], "Z" => [77, "Wu"], "[" => [18, "Wu"], "\\" => [0, "W:"], "]" => [0, "WB"], "^" => [0, "WC"], "_" => [0, "WD"], "`" => [0, "WE"], "a" => [0, "WF"], "b" => [0, "WG"], "c" => [0, "WH"], "d" => [0, "WI"], "e" => [0, "WJ"], "f" => [0, "WK"], "g" => [0, "WL"], "h" => [0, "WM"], "i" => [0, "WN"], "j" => [0, "WO"], "k" => [0, "WP"], "l" => [0, "WQ"], "m" => [0, "WR"], "n" => [0, "WS"], "o" => [0, "WT"], "p" => [0, "WU"], "q" => [0, "WV"], "r" => [0, "WW"], "s" => [0, "WY"], "t" => [0, "Wj"], "u" => [0, "Wk"], "v" => [0, "Wq"], "w" => [0, "Wv"], "x" => [0, "Ww"], "y" => [0, "Wx"], "z" => [0, "Wy"], "{" => [0, "Wz"], "|" => [82, "W"], "}" => [87, "W"], "~" => [130, "W"], "" => [9, "W"], "\x80" => [94, "Y0"], "\x81" => [76, "Y0"], "\x82" => [104, "Y0"], "\x83" => [16, "Y0"], "\x84" => [94, "Y1"], "\x85" => [76, "Y1"], "\x86" => [104, "Y1"], "\x87" => [16, "Y1"], "\x88" => [94, "Y2"], "\x89" => [76, "Y2"], "\x8a" => [104, "Y2"], "\x8b" => [16, "Y2"], "\x8c" => [94, "Ya"], "\x8d" => [76, "Ya"], "\x8e" => [104, "Ya"], "\x8f" => [16, "Ya"], "\x90" => [94, "Yc"], "\x91" => [76, "Yc"], "\x92" => [104, "Yc"], "\x93" => [16, "Yc"], "\x94" => [94, "Ye"], "\x95" => [76, "Ye"], "\x96" => [104, "Ye"], "\x97" => [16, "Ye"], "\x98" => [94, "Yi"], "\x99" => [76, "Yi"], "\x9a" => [104, "Yi"], "\x9b" => [16, "Yi"], "\x9c" => [94, "Yo"], "\x9d" => [76, "Yo"], "\x9e" => [104, "Yo"], "\x9f" => [16, "Yo"], "\xa0" => [94, "Ys"], "\xa1" => [76, "Ys"], "\xa2" => [104, "Ys"], "\xa3" => [16, "Ys"], "\xa4" => [94, "Yt"], "\xa5" => [76, "Yt"], "\xa6" => [104, "Yt"], "\xa7" => [16, "Yt"], "\xa8" => [77, "Y "], "\xa9" => [18, "Y "], "\xaa" => [77, "Y%"], "\xab" => [18, "Y%"], "\xac" => [77, "Y-"], "\xad" => [18, "Y-"], "\xae" => [77, "Y."], "\xaf" => [18, "Y."], "\xb0" => [77, "Y/"], "\xb1" => [18, "Y/"], "\xb2" => [77, "Y3"], "\xb3" => [18, "Y3"], "\xb4" => [77, "Y4"], "\xb5" => [18, "Y4"], "\xb6" => [77, "Y5"], "\xb7" => [18, "Y5"], "\xb8" => [77, "Y6"], "\xb9" => [18, "Y6"], "\xba" => [77, "Y7"], "\xbb" => [18, "Y7"], "\xbc" => [77, "Y8"], "\xbd" => [18, "Y8"], "\xbe" => [77, "Y9"], "\xbf" => [18, "Y9"], "\xc0" => [77, "Y="], "\xc1" => [18, "Y="], "\xc2" => [77, "YA"], "\xc3" => [18, "YA"], "\xc4" => [77, "Y_"], "\xc5" => [18, "Y_"], "\xc6" => [77, "Yb"], "\xc7" => [18, "Yb"], "\xc8" => [77, "Yd"], "\xc9" => [18, "Yd"], "\xca" => [77, "Yf"], "\xcb" => [18, "Yf"], "\xcc" => [77, "Yg"], "\xcd" => [18, "Yg"], "\xce" => [77, "Yh"], "\xcf" => [18, "Yh"], "\xd0" => [77, "Yl"], "\xd1" => [18, "Yl"], "\xd2" => [77, "Ym"], "\xd3" => [18, "Ym"], "\xd4" => [77, "Yn"], "\xd5" => [18, "Yn"], "\xd6" => [77, "Yp"], "\xd7" => [18, "Yp"], "\xd8" => [77, "Yr"], "\xd9" => [18, "Yr"], "\xda" => [77, "Yu"], "\xdb" => [18, "Yu"], "\xdc" => [0, "Y:"], "\xdd" => [0, "YB"], "\xde" => [0, "YC"], "\xdf" => [0, "YD"], "\xe0" => [0, "YE"], "\xe1" => [0, "YF"], "\xe2" => [0, "YG"], "\xe3" => [0, "YH"], "\xe4" => [0, "YI"], "\xe5" => [0, "YJ"], "\xe6" => [0, "YK"], "\xe7" => [0, "YL"], "\xe8" => [0, "YM"], "\xe9" => [0, "YN"], "\xea" => [0, "YO"], "\xeb" => [0, "YP"], "\xec" => [0, "YQ"], "\xed" => [0, "YR"], "\xee" => [0, "YS"], "\xef" => [0, "YT"], "\xf0" => [0, "YU"], "\xf1" => [0, "YV"], "\xf2" => [0, "YW"], "\xf3" => [0, "YY"], "\xf4" => [0, "Yj"], "\xf5" => [0, "Yk"], "\xf6" => [0, "Yq"], "\xf7" => [0, "Yv"], "\xf8" => [0, "Yw"], "\xf9" => [0, "Yx"], "\xfa" => [0, "Yy"], "\xfb" => [0, "Yz"], "\xfc" => [82, "Y"], "\xfd" => [87, "Y"], "\xfe" => [130, "Y"], "\xff" => [9, "Y"]], ["\x00" => [94, "X0"], "\x01" => [76, "X0"], "\x02" => [104, "X0"], "\x03" => [16, "X0"], "\x04" => [94, "X1"], "\x05" => [76, "X1"], "\x06" => [104, "X1"], "\x07" => [16, "X1"], "\x08" => [94, "X2"], "\t" => [76, "X2"], "\n" => [104, "X2"], "\v" => [16, "X2"], "\f" => [94, "Xa"], "\r" => [76, "Xa"], "\x0e" => [104, "Xa"], "\x0f" => [16, "Xa"], "\x10" => [94, "Xc"], "\x11" => [76, "Xc"], "\x12" => [104, "Xc"], "\x13" => [16, "Xc"], "\x14" => [94, "Xe"], "\x15" => [76, "Xe"], "\x16" => [104, "Xe"], "\x17" => [16, "Xe"], "\x18" => [94, "Xi"], "\x19" => [76, "Xi"], "\x1a" => [104, "Xi"], "\x1b" => [16, "Xi"], "\x1c" => [94, "Xo"], "\x1d" => [76, "Xo"], "\x1e" => [104, "Xo"], "\x1f" => [16, "Xo"], " " => [94, "Xs"], "!" => [76, "Xs"], "\"" => [104, "Xs"], "#" => [16, "Xs"], "\$" => [94, "Xt"], "%" => [76, "Xt"], "&" => [104, "Xt"], "'" => [16, "Xt"], "(" => [77, "X "], ")" => [18, "X "], "*" => [77, "X%"], "+" => [18, "X%"], "," => [77, "X-"], "-" => [18, "X-"], "." => [77, "X."], "/" => [18, "X."], [77, "X/"], [18, "X/"], [77, "X3"], [18, "X3"], [77, "X4"], [18, "X4"], [77, "X5"], [18, "X5"], [77, "X6"], [18, "X6"], ":" => [77, "X7"], ";" => [18, "X7"], "<" => [77, "X8"], "=" => [18, "X8"], ">" => [77, "X9"], "?" => [18, "X9"], "@" => [77, "X="], "A" => [18, "X="], "B" => [77, "XA"], "C" => [18, "XA"], "D" => [77, "X_"], "E" => [18, "X_"], "F" => [77, "Xb"], "G" => [18, "Xb"], "H" => [77, "Xd"], "I" => [18, "Xd"], "J" => [77, "Xf"], "K" => [18, "Xf"], "L" => [77, "Xg"], "M" => [18, "Xg"], "N" => [77, "Xh"], "O" => [18, "Xh"], "P" => [77, "Xl"], "Q" => [18, "Xl"], "R" => [77, "Xm"], "S" => [18, "Xm"], "T" => [77, "Xn"], "U" => [18, "Xn"], "V" => [77, "Xp"], "W" => [18, "Xp"], "X" => [77, "Xr"], "Y" => [18, "Xr"], "Z" => [77, "Xu"], "[" => [18, "Xu"], "\\" => [0, "X:"], "]" => [0, "XB"], "^" => [0, "XC"], "_" => [0, "XD"], "`" => [0, "XE"], "a" => [0, "XF"], "b" => [0, "XG"], "c" => [0, "XH"], "d" => [0, "XI"], "e" => [0, "XJ"], "f" => [0, "XK"], "g" => [0, "XL"], "h" => [0, "XM"], "i" => [0, "XN"], "j" => [0, "XO"], "k" => [0, "XP"], "l" => [0, "XQ"], "m" => [0, "XR"], "n" => [0, "XS"], "o" => [0, "XT"], "p" => [0, "XU"], "q" => [0, "XV"], "r" => [0, "XW"], "s" => [0, "XY"], "t" => [0, "Xj"], "u" => [0, "Xk"], "v" => [0, "Xq"], "w" => [0, "Xv"], "x" => [0, "Xw"], "y" => [0, "Xx"], "z" => [0, "Xy"], "{" => [0, "Xz"], "|" => [82, "X"], "}" => [87, "X"], "~" => [130, "X"], "" => [9, "X"], "\x80" => [94, "Z0"], "\x81" => [76, "Z0"], "\x82" => [104, "Z0"], "\x83" => [16, "Z0"], "\x84" => [94, "Z1"], "\x85" => [76, "Z1"], "\x86" => [104, "Z1"], "\x87" => [16, "Z1"], "\x88" => [94, "Z2"], "\x89" => [76, "Z2"], "\x8a" => [104, "Z2"], "\x8b" => [16, "Z2"], "\x8c" => [94, "Za"], "\x8d" => [76, "Za"], "\x8e" => [104, "Za"], "\x8f" => [16, "Za"], "\x90" => [94, "Zc"], "\x91" => [76, "Zc"], "\x92" => [104, "Zc"], "\x93" => [16, "Zc"], "\x94" => [94, "Ze"], "\x95" => [76, "Ze"], "\x96" => [104, "Ze"], "\x97" => [16, "Ze"], "\x98" => [94, "Zi"], "\x99" => [76, "Zi"], "\x9a" => [104, "Zi"], "\x9b" => [16, "Zi"], "\x9c" => [94, "Zo"], "\x9d" => [76, "Zo"], "\x9e" => [104, "Zo"], "\x9f" => [16, "Zo"], "\xa0" => [94, "Zs"], "\xa1" => [76, "Zs"], "\xa2" => [104, "Zs"], "\xa3" => [16, "Zs"], "\xa4" => [94, "Zt"], "\xa5" => [76, "Zt"], "\xa6" => [104, "Zt"], "\xa7" => [16, "Zt"], "\xa8" => [77, "Z "], "\xa9" => [18, "Z "], "\xaa" => [77, "Z%"], "\xab" => [18, "Z%"], "\xac" => [77, "Z-"], "\xad" => [18, "Z-"], "\xae" => [77, "Z."], "\xaf" => [18, "Z."], "\xb0" => [77, "Z/"], "\xb1" => [18, "Z/"], "\xb2" => [77, "Z3"], "\xb3" => [18, "Z3"], "\xb4" => [77, "Z4"], "\xb5" => [18, "Z4"], "\xb6" => [77, "Z5"], "\xb7" => [18, "Z5"], "\xb8" => [77, "Z6"], "\xb9" => [18, "Z6"], "\xba" => [77, "Z7"], "\xbb" => [18, "Z7"], "\xbc" => [77, "Z8"], "\xbd" => [18, "Z8"], "\xbe" => [77, "Z9"], "\xbf" => [18, "Z9"], "\xc0" => [77, "Z="], "\xc1" => [18, "Z="], "\xc2" => [77, "ZA"], "\xc3" => [18, "ZA"], "\xc4" => [77, "Z_"], "\xc5" => [18, "Z_"], "\xc6" => [77, "Zb"], "\xc7" => [18, "Zb"], "\xc8" => [77, "Zd"], "\xc9" => [18, "Zd"], "\xca" => [77, "Zf"], "\xcb" => [18, "Zf"], "\xcc" => [77, "Zg"], "\xcd" => [18, "Zg"], "\xce" => [77, "Zh"], "\xcf" => [18, "Zh"], "\xd0" => [77, "Zl"], "\xd1" => [18, "Zl"], "\xd2" => [77, "Zm"], "\xd3" => [18, "Zm"], "\xd4" => [77, "Zn"], "\xd5" => [18, "Zn"], "\xd6" => [77, "Zp"], "\xd7" => [18, "Zp"], "\xd8" => [77, "Zr"], "\xd9" => [18, "Zr"], "\xda" => [77, "Zu"], "\xdb" => [18, "Zu"], "\xdc" => [0, "Z:"], "\xdd" => [0, "ZB"], "\xde" => [0, "ZC"], "\xdf" => [0, "ZD"], "\xe0" => [0, "ZE"], "\xe1" => [0, "ZF"], "\xe2" => [0, "ZG"], "\xe3" => [0, "ZH"], "\xe4" => [0, "ZI"], "\xe5" => [0, "ZJ"], "\xe6" => [0, "ZK"], "\xe7" => [0, "ZL"], "\xe8" => [0, "ZM"], "\xe9" => [0, "ZN"], "\xea" => [0, "ZO"], "\xeb" => [0, "ZP"], "\xec" => [0, "ZQ"], "\xed" => [0, "ZR"], "\xee" => [0, "ZS"], "\xef" => [0, "ZT"], "\xf0" => [0, "ZU"], "\xf1" => [0, "ZV"], "\xf2" => [0, "ZW"], "\xf3" => [0, "ZY"], "\xf4" => [0, "Zj"], "\xf5" => [0, "Zk"], "\xf6" => [0, "Zq"], "\xf7" => [0, "Zv"], "\xf8" => [0, "Zw"], "\xf9" => [0, "Zx"], "\xfa" => [0, "Zy"], "\xfb" => [0, "Zz"], "\xfc" => [82, "Z"], "\xfd" => [87, "Z"], "\xfe" => [130, "Z"], "\xff" => [9, "Z"]], ["\x00" => [0, "\\0"], "\x01" => [0, "\\1"], "\x02" => [0, "\\2"], "\x03" => [0, "\\a"], "\x04" => [0, "\\c"], "\x05" => [0, "\\e"], "\x06" => [0, "\\i"], "\x07" => [0, "\\o"], "\x08" => [0, "\\s"], "\t" => [0, "\\t"], "\n" => [73, "\\"], "\v" => [88, "\\"], "\f" => [89, "\\"], "\r" => [96, "\\"], "\x0e" => [97, "\\"], "\x0f" => [99, "\\"], "\x10" => [106, "\\"], "\x11" => [136, "\\"], "\x12" => [139, "\\"], "\x13" => [141, "\\"], "\x14" => [145, "\\"], "\x15" => [147, "\\"], "\x16" => [149, "\\"], "\x17" => [101, "\\"], "\x18" => [112, "\\"], "\x19" => [117, "\\"], "\x1a" => [120, "\\"], "\x1b" => [124, "\\"], "\x1c" => [127, "\\"], "\x1d" => [144, "\\"], "\x1e" => [152, "\\"], "\x1f" => [11, "\\"], " " => [0, "\xc30"], "!" => [0, "\xc31"], "\"" => [0, "\xc32"], "#" => [0, "\xc3a"], "\$" => [0, "\xc3c"], "%" => [0, "\xc3e"], "&" => [0, "\xc3i"], "'" => [0, "\xc3o"], "(" => [0, "\xc3s"], ")" => [0, "\xc3t"], "*" => [73, "\xc3"], "+" => [88, "\xc3"], "," => [89, "\xc3"], "-" => [96, "\xc3"], "." => [97, "\xc3"], "/" => [99, "\xc3"], [106, "\xc3"], [136, "\xc3"], [139, "\xc3"], [141, "\xc3"], [145, "\xc3"], [147, "\xc3"], [149, "\xc3"], [101, "\xc3"], [112, "\xc3"], [117, "\xc3"], ":" => [120, "\xc3"], ";" => [124, "\xc3"], "<" => [127, "\xc3"], "=" => [144, "\xc3"], ">" => [152, "\xc3"], "?" => [11, "\xc3"], "@" => [0, "\xd00"], "A" => [0, "\xd01"], "B" => [0, "\xd02"], "C" => [0, "\xd0a"], "D" => [0, "\xd0c"], "E" => [0, "\xd0e"], "F" => [0, "\xd0i"], "G" => [0, "\xd0o"], "H" => [0, "\xd0s"], "I" => [0, "\xd0t"], "J" => [73, "\xd0"], "K" => [88, "\xd0"], "L" => [89, "\xd0"], "M" => [96, "\xd0"], "N" => [97, "\xd0"], "O" => [99, "\xd0"], "P" => [106, "\xd0"], "Q" => [136, "\xd0"], "R" => [139, "\xd0"], "S" => [141, "\xd0"], "T" => [145, "\xd0"], "U" => [147, "\xd0"], "V" => [149, "\xd0"], "W" => [101, "\xd0"], "X" => [112, "\xd0"], "Y" => [117, "\xd0"], "Z" => [120, "\xd0"], "[" => [124, "\xd0"], "\\" => [127, "\xd0"], "]" => [144, "\xd0"], "^" => [152, "\xd0"], "_" => [11, "\xd0"], "`" => [92, "\x80"], "a" => [95, "\x80"], "b" => [137, "\x80"], "c" => [142, "\x80"], "d" => [150, "\x80"], "e" => [74, "\x80"], "f" => [90, "\x80"], "g" => [98, "\x80"], "h" => [107, "\x80"], "i" => [140, "\x80"], "j" => [146, "\x80"], "k" => [102, "\x80"], "l" => [113, "\x80"], "m" => [121, "\x80"], "n" => [128, "\x80"], "o" => [12, "\x80"], "p" => [92, "\x82"], "q" => [95, "\x82"], "r" => [137, "\x82"], "s" => [142, "\x82"], "t" => [150, "\x82"], "u" => [74, "\x82"], "v" => [90, "\x82"], "w" => [98, "\x82"], "x" => [107, "\x82"], "y" => [140, "\x82"], "z" => [146, "\x82"], "{" => [102, "\x82"], "|" => [113, "\x82"], "}" => [121, "\x82"], "~" => [128, "\x82"], "" => [12, "\x82"], "\x80" => [92, "\x83"], "\x81" => [95, "\x83"], "\x82" => [137, "\x83"], "\x83" => [142, "\x83"], "\x84" => [150, "\x83"], "\x85" => [74, "\x83"], "\x86" => [90, "\x83"], "\x87" => [98, "\x83"], "\x88" => [107, "\x83"], "\x89" => [140, "\x83"], "\x8a" => [146, "\x83"], "\x8b" => [102, "\x83"], "\x8c" => [113, "\x83"], "\x8d" => [121, "\x83"], "\x8e" => [128, "\x83"], "\x8f" => [12, "\x83"], "\x90" => [92, "\xa2"], "\x91" => [95, "\xa2"], "\x92" => [137, "\xa2"], "\x93" => [142, "\xa2"], "\x94" => [150, "\xa2"], "\x95" => [74, "\xa2"], "\x96" => [90, "\xa2"], "\x97" => [98, "\xa2"], "\x98" => [107, "\xa2"], "\x99" => [140, "\xa2"], "\x9a" => [146, "\xa2"], "\x9b" => [102, "\xa2"], "\x9c" => [113, "\xa2"], "\x9d" => [121, "\xa2"], "\x9e" => [128, "\xa2"], "\x9f" => [12, "\xa2"], "\xa0" => [92, "\xb8"], "\xa1" => [95, "\xb8"], "\xa2" => [137, "\xb8"], "\xa3" => [142, "\xb8"], "\xa4" => [150, "\xb8"], "\xa5" => [74, "\xb8"], "\xa6" => [90, "\xb8"], "\xa7" => [98, "\xb8"], "\xa8" => [107, "\xb8"], "\xa9" => [140, "\xb8"], "\xaa" => [146, "\xb8"], "\xab" => [102, "\xb8"], "\xac" => [113, "\xb8"], "\xad" => [121, "\xb8"], "\xae" => [128, "\xb8"], "\xaf" => [12, "\xb8"], "\xb0" => [92, "\xc2"], "\xb1" => [95, "\xc2"], "\xb2" => [137, "\xc2"], "\xb3" => [142, "\xc2"], "\xb4" => [150, "\xc2"], "\xb5" => [74, "\xc2"], "\xb6" => [90, "\xc2"], "\xb7" => [98, "\xc2"], "\xb8" => [107, "\xc2"], "\xb9" => [140, "\xc2"], "\xba" => [146, "\xc2"], "\xbb" => [102, "\xc2"], "\xbc" => [113, "\xc2"], "\xbd" => [121, "\xc2"], "\xbe" => [128, "\xc2"], "\xbf" => [12, "\xc2"], "\xc0" => [92, "\xe0"], "\xc1" => [95, "\xe0"], "\xc2" => [137, "\xe0"], "\xc3" => [142, "\xe0"], "\xc4" => [150, "\xe0"], "\xc5" => [74, "\xe0"], "\xc6" => [90, "\xe0"], "\xc7" => [98, "\xe0"], "\xc8" => [107, "\xe0"], "\xc9" => [140, "\xe0"], "\xca" => [146, "\xe0"], "\xcb" => [102, "\xe0"], "\xcc" => [113, "\xe0"], "\xcd" => [121, "\xe0"], "\xce" => [128, "\xe0"], "\xcf" => [12, "\xe0"], "\xd0" => [92, "\xe2"], "\xd1" => [95, "\xe2"], "\xd2" => [137, "\xe2"], "\xd3" => [142, "\xe2"], "\xd4" => [150, "\xe2"], "\xd5" => [74, "\xe2"], "\xd6" => [90, "\xe2"], "\xd7" => [98, "\xe2"], "\xd8" => [107, "\xe2"], "\xd9" => [140, "\xe2"], "\xda" => [146, "\xe2"], "\xdb" => [102, "\xe2"], "\xdc" => [113, "\xe2"], "\xdd" => [121, "\xe2"], "\xde" => [128, "\xe2"], "\xdf" => [12, "\xe2"], "\xe0" => [93, "\x99"], "\xe1" => [138, "\x99"], "\xe2" => [75, "\x99"], "\xe3" => [91, "\x99"], "\xe4" => [108, "\x99"], "\xe5" => [103, "\x99"], "\xe6" => [114, "\x99"], "\xe7" => [14, "\x99"], "\xe8" => [93, "\xa1"], "\xe9" => [138, "\xa1"], "\xea" => [75, "\xa1"], "\xeb" => [91, "\xa1"], "\xec" => [108, "\xa1"], "\xed" => [103, "\xa1"], "\xee" => [114, "\xa1"], "\xef" => [14, "\xa1"], "\xf0" => [93, "\xa7"], "\xf1" => [138, "\xa7"], "\xf2" => [75, "\xa7"], "\xf3" => [91, "\xa7"], "\xf4" => [108, "\xa7"], "\xf5" => [103, "\xa7"], "\xf6" => [114, "\xa7"], "\xf7" => [14, "\xa7"], "\xf8" => [93, "\xac"], "\xf9" => [138, "\xac"], "\xfa" => [75, "\xac"], "\xfb" => [91, "\xac"], "\xfc" => [108, "\xac"], "\xfd" => [103, "\xac"], "\xfe" => [114, "\xac"], "\xff" => [14, "\xac"]], ["\x00" => [94, "\\0"], "\x01" => [76, "\\0"], "\x02" => [104, "\\0"], "\x03" => [16, "\\0"], "\x04" => [94, "\\1"], "\x05" => [76, "\\1"], "\x06" => [104, "\\1"], "\x07" => [16, "\\1"], "\x08" => [94, "\\2"], "\t" => [76, "\\2"], "\n" => [104, "\\2"], "\v" => [16, "\\2"], "\f" => [94, "\\a"], "\r" => [76, "\\a"], "\x0e" => [104, "\\a"], "\x0f" => [16, "\\a"], "\x10" => [94, "\\c"], "\x11" => [76, "\\c"], "\x12" => [104, "\\c"], "\x13" => [16, "\\c"], "\x14" => [94, "\\e"], "\x15" => [76, "\\e"], "\x16" => [104, "\\e"], "\x17" => [16, "\\e"], "\x18" => [94, "\\i"], "\x19" => [76, "\\i"], "\x1a" => [104, "\\i"], "\x1b" => [16, "\\i"], "\x1c" => [94, "\\o"], "\x1d" => [76, "\\o"], "\x1e" => [104, "\\o"], "\x1f" => [16, "\\o"], " " => [94, "\\s"], "!" => [76, "\\s"], "\"" => [104, "\\s"], "#" => [16, "\\s"], "\$" => [94, "\\t"], "%" => [76, "\\t"], "&" => [104, "\\t"], "'" => [16, "\\t"], "(" => [77, "\\ "], ")" => [18, "\\ "], "*" => [77, "\\%"], "+" => [18, "\\%"], "," => [77, "\\-"], "-" => [18, "\\-"], "." => [77, "\\."], "/" => [18, "\\."], [77, "\\/"], [18, "\\/"], [77, "\\3"], [18, "\\3"], [77, "\\4"], [18, "\\4"], [77, "\\5"], [18, "\\5"], [77, "\\6"], [18, "\\6"], ":" => [77, "\\7"], ";" => [18, "\\7"], "<" => [77, "\\8"], "=" => [18, "\\8"], ">" => [77, "\\9"], "?" => [18, "\\9"], "@" => [77, "\\="], "A" => [18, "\\="], "B" => [77, "\\A"], "C" => [18, "\\A"], "D" => [77, "\\_"], "E" => [18, "\\_"], "F" => [77, "\\b"], "G" => [18, "\\b"], "H" => [77, "\\d"], "I" => [18, "\\d"], "J" => [77, "\\f"], "K" => [18, "\\f"], "L" => [77, "\\g"], "M" => [18, "\\g"], "N" => [77, "\\h"], "O" => [18, "\\h"], "P" => [77, "\\l"], "Q" => [18, "\\l"], "R" => [77, "\\m"], "S" => [18, "\\m"], "T" => [77, "\\n"], "U" => [18, "\\n"], "V" => [77, "\\p"], "W" => [18, "\\p"], "X" => [77, "\\r"], "Y" => [18, "\\r"], "Z" => [77, "\\u"], "[" => [18, "\\u"], "\\" => [0, "\\:"], "]" => [0, "\\B"], "^" => [0, "\\C"], "_" => [0, "\\D"], "`" => [0, "\\E"], "a" => [0, "\\F"], "b" => [0, "\\G"], "c" => [0, "\\H"], "d" => [0, "\\I"], "e" => [0, "\\J"], "f" => [0, "\\K"], "g" => [0, "\\L"], "h" => [0, "\\M"], "i" => [0, "\\N"], "j" => [0, "\\O"], "k" => [0, "\\P"], "l" => [0, "\\Q"], "m" => [0, "\\R"], "n" => [0, "\\S"], "o" => [0, "\\T"], "p" => [0, "\\U"], "q" => [0, "\\V"], "r" => [0, "\\W"], "s" => [0, "\\Y"], "t" => [0, "\\j"], "u" => [0, "\\k"], "v" => [0, "\\q"], "w" => [0, "\\v"], "x" => [0, "\\w"], "y" => [0, "\\x"], "z" => [0, "\\y"], "{" => [0, "\\z"], "|" => [82, "\\"], "}" => [87, "\\"], "~" => [130, "\\"], "" => [9, "\\"], "\x80" => [94, "\xc30"], "\x81" => [76, "\xc30"], "\x82" => [104, "\xc30"], "\x83" => [16, "\xc30"], "\x84" => [94, "\xc31"], "\x85" => [76, "\xc31"], "\x86" => [104, "\xc31"], "\x87" => [16, "\xc31"], "\x88" => [94, "\xc32"], "\x89" => [76, "\xc32"], "\x8a" => [104, "\xc32"], "\x8b" => [16, "\xc32"], "\x8c" => [94, "\xc3a"], "\x8d" => [76, "\xc3a"], "\x8e" => [104, "\xc3a"], "\x8f" => [16, "\xc3a"], "\x90" => [94, "\xc3c"], "\x91" => [76, "\xc3c"], "\x92" => [104, "\xc3c"], "\x93" => [16, "\xc3c"], "\x94" => [94, "\xc3e"], "\x95" => [76, "\xc3e"], "\x96" => [104, "\xc3e"], "\x97" => [16, "\xc3e"], "\x98" => [94, "\xc3i"], "\x99" => [76, "\xc3i"], "\x9a" => [104, "\xc3i"], "\x9b" => [16, "\xc3i"], "\x9c" => [94, "\xc3o"], "\x9d" => [76, "\xc3o"], "\x9e" => [104, "\xc3o"], "\x9f" => [16, "\xc3o"], "\xa0" => [94, "\xc3s"], "\xa1" => [76, "\xc3s"], "\xa2" => [104, "\xc3s"], "\xa3" => [16, "\xc3s"], "\xa4" => [94, "\xc3t"], "\xa5" => [76, "\xc3t"], "\xa6" => [104, "\xc3t"], "\xa7" => [16, "\xc3t"], "\xa8" => [77, "\xc3 "], "\xa9" => [18, "\xc3 "], "\xaa" => [77, "\xc3%"], "\xab" => [18, "\xc3%"], "\xac" => [77, "\xc3-"], "\xad" => [18, "\xc3-"], "\xae" => [77, "\xc3."], "\xaf" => [18, "\xc3."], "\xb0" => [77, "\xc3/"], "\xb1" => [18, "\xc3/"], "\xb2" => [77, "\xc33"], "\xb3" => [18, "\xc33"], "\xb4" => [77, "\xc34"], "\xb5" => [18, "\xc34"], "\xb6" => [77, "\xc35"], "\xb7" => [18, "\xc35"], "\xb8" => [77, "\xc36"], "\xb9" => [18, "\xc36"], "\xba" => [77, "\xc37"], "\xbb" => [18, "\xc37"], "\xbc" => [77, "\xc38"], "\xbd" => [18, "\xc38"], "\xbe" => [77, "\xc39"], "\xbf" => [18, "\xc39"], "\xc0" => [77, "\xc3="], "\xc1" => [18, "\xc3="], "\xc2" => [77, "\xc3A"], "\xc3" => [18, "\xc3A"], "\xc4" => [77, "\xc3_"], "\xc5" => [18, "\xc3_"], "\xc6" => [77, "\xc3b"], "\xc7" => [18, "\xc3b"], "\xc8" => [77, "\xc3d"], "\xc9" => [18, "\xc3d"], "\xca" => [77, "\xc3f"], "\xcb" => [18, "\xc3f"], "\xcc" => [77, "\xc3g"], "\xcd" => [18, "\xc3g"], "\xce" => [77, "\xc3h"], "\xcf" => [18, "\xc3h"], "\xd0" => [77, "\xc3l"], "\xd1" => [18, "\xc3l"], "\xd2" => [77, "\xc3m"], "\xd3" => [18, "\xc3m"], "\xd4" => [77, "\xc3n"], "\xd5" => [18, "\xc3n"], "\xd6" => [77, "\xc3p"], "\xd7" => [18, "\xc3p"], "\xd8" => [77, "\xc3r"], "\xd9" => [18, "\xc3r"], "\xda" => [77, "\xc3u"], "\xdb" => [18, "\xc3u"], "\xdc" => [0, "\xc3:"], "\xdd" => [0, "\xc3B"], "\xde" => [0, "\xc3C"], "\xdf" => [0, "\xc3D"], "\xe0" => [0, "\xc3E"], "\xe1" => [0, "\xc3F"], "\xe2" => [0, "\xc3G"], "\xe3" => [0, "\xc3H"], "\xe4" => [0, "\xc3I"], "\xe5" => [0, "\xc3J"], "\xe6" => [0, "\xc3K"], "\xe7" => [0, "\xc3L"], "\xe8" => [0, "\xc3M"], "\xe9" => [0, "\xc3N"], "\xea" => [0, "\xc3O"], "\xeb" => [0, "\xc3P"], "\xec" => [0, "\xc3Q"], "\xed" => [0, "\xc3R"], "\xee" => [0, "\xc3S"], "\xef" => [0, "\xc3T"], "\xf0" => [0, "\xc3U"], "\xf1" => [0, "\xc3V"], "\xf2" => [0, "\xc3W"], "\xf3" => [0, "\xc3Y"], "\xf4" => [0, "\xc3j"], "\xf5" => [0, "\xc3k"], "\xf6" => [0, "\xc3q"], "\xf7" => [0, "\xc3v"], "\xf8" => [0, "\xc3w"], "\xf9" => [0, "\xc3x"], "\xfa" => [0, "\xc3y"], "\xfb" => [0, "\xc3z"], "\xfc" => [82, "\xc3"], "\xfd" => [87, "\xc3"], "\xfe" => [130, "\xc3"], "\xff" => [9, "\xc3"]], ["\x00" => [77, "\\0"], "\x01" => [18, "\\0"], "\x02" => [77, "\\1"], "\x03" => [18, "\\1"], "\x04" => [77, "\\2"], "\x05" => [18, "\\2"], "\x06" => [77, "\\a"], "\x07" => [18, "\\a"], "\x08" => [77, "\\c"], "\t" => [18, "\\c"], "\n" => [77, "\\e"], "\v" => [18, "\\e"], "\f" => [77, "\\i"], "\r" => [18, "\\i"], "\x0e" => [77, "\\o"], "\x0f" => [18, "\\o"], "\x10" => [77, "\\s"], "\x11" => [18, "\\s"], "\x12" => [77, "\\t"], "\x13" => [18, "\\t"], "\x14" => [0, "\\ "], "\x15" => [0, "\\%"], "\x16" => [0, "\\-"], "\x17" => [0, "\\."], "\x18" => [0, "\\/"], "\x19" => [0, "\\3"], "\x1a" => [0, "\\4"], "\x1b" => [0, "\\5"], "\x1c" => [0, "\\6"], "\x1d" => [0, "\\7"], "\x1e" => [0, "\\8"], "\x1f" => [0, "\\9"], " " => [0, "\\="], "!" => [0, "\\A"], "\"" => [0, "\\_"], "#" => [0, "\\b"], "\$" => [0, "\\d"], "%" => [0, "\\f"], "&" => [0, "\\g"], "'" => [0, "\\h"], "(" => [0, "\\l"], ")" => [0, "\\m"], "*" => [0, "\\n"], "+" => [0, "\\p"], "," => [0, "\\r"], "-" => [0, "\\u"], "." => [100, "\\"], "/" => [110, "\\"], [111, "\\"], [115, "\\"], [116, "\\"], [118, "\\"], [119, "\\"], [122, "\\"], [123, "\\"], [125, "\\"], [126, "\\"], [129, "\\"], ":" => [143, "\\"], ";" => [148, "\\"], "<" => [151, "\\"], "=" => [153, "\\"], ">" => [83, "\\"], "?" => [10, "\\"], "@" => [77, "\xc30"], "A" => [18, "\xc30"], "B" => [77, "\xc31"], "C" => [18, "\xc31"], "D" => [77, "\xc32"], "E" => [18, "\xc32"], "F" => [77, "\xc3a"], "G" => [18, "\xc3a"], "H" => [77, "\xc3c"], "I" => [18, "\xc3c"], "J" => [77, "\xc3e"], "K" => [18, "\xc3e"], "L" => [77, "\xc3i"], "M" => [18, "\xc3i"], "N" => [77, "\xc3o"], "O" => [18, "\xc3o"], "P" => [77, "\xc3s"], "Q" => [18, "\xc3s"], "R" => [77, "\xc3t"], "S" => [18, "\xc3t"], "T" => [0, "\xc3 "], "U" => [0, "\xc3%"], "V" => [0, "\xc3-"], "W" => [0, "\xc3."], "X" => [0, "\xc3/"], "Y" => [0, "\xc33"], "Z" => [0, "\xc34"], "[" => [0, "\xc35"], "\\" => [0, "\xc36"], "]" => [0, "\xc37"], "^" => [0, "\xc38"], "_" => [0, "\xc39"], "`" => [0, "\xc3="], "a" => [0, "\xc3A"], "b" => [0, "\xc3_"], "c" => [0, "\xc3b"], "d" => [0, "\xc3d"], "e" => [0, "\xc3f"], "f" => [0, "\xc3g"], "g" => [0, "\xc3h"], "h" => [0, "\xc3l"], "i" => [0, "\xc3m"], "j" => [0, "\xc3n"], "k" => [0, "\xc3p"], "l" => [0, "\xc3r"], "m" => [0, "\xc3u"], "n" => [100, "\xc3"], "o" => [110, "\xc3"], "p" => [111, "\xc3"], "q" => [115, "\xc3"], "r" => [116, "\xc3"], "s" => [118, "\xc3"], "t" => [119, "\xc3"], "u" => [122, "\xc3"], "v" => [123, "\xc3"], "w" => [125, "\xc3"], "x" => [126, "\xc3"], "y" => [129, "\xc3"], "z" => [143, "\xc3"], "{" => [148, "\xc3"], "|" => [151, "\xc3"], "}" => [153, "\xc3"], "~" => [83, "\xc3"], "" => [10, "\xc3"], "\x80" => [77, "\xd00"], "\x81" => [18, "\xd00"], "\x82" => [77, "\xd01"], "\x83" => [18, "\xd01"], "\x84" => [77, "\xd02"], "\x85" => [18, "\xd02"], "\x86" => [77, "\xd0a"], "\x87" => [18, "\xd0a"], "\x88" => [77, "\xd0c"], "\x89" => [18, "\xd0c"], "\x8a" => [77, "\xd0e"], "\x8b" => [18, "\xd0e"], "\x8c" => [77, "\xd0i"], "\x8d" => [18, "\xd0i"], "\x8e" => [77, "\xd0o"], "\x8f" => [18, "\xd0o"], "\x90" => [77, "\xd0s"], "\x91" => [18, "\xd0s"], "\x92" => [77, "\xd0t"], "\x93" => [18, "\xd0t"], "\x94" => [0, "\xd0 "], "\x95" => [0, "\xd0%"], "\x96" => [0, "\xd0-"], "\x97" => [0, "\xd0."], "\x98" => [0, "\xd0/"], "\x99" => [0, "\xd03"], "\x9a" => [0, "\xd04"], "\x9b" => [0, "\xd05"], "\x9c" => [0, "\xd06"], "\x9d" => [0, "\xd07"], "\x9e" => [0, "\xd08"], "\x9f" => [0, "\xd09"], "\xa0" => [0, "\xd0="], "\xa1" => [0, "\xd0A"], "\xa2" => [0, "\xd0_"], "\xa3" => [0, "\xd0b"], "\xa4" => [0, "\xd0d"], "\xa5" => [0, "\xd0f"], "\xa6" => [0, "\xd0g"], "\xa7" => [0, "\xd0h"], "\xa8" => [0, "\xd0l"], "\xa9" => [0, "\xd0m"], "\xaa" => [0, "\xd0n"], "\xab" => [0, "\xd0p"], "\xac" => [0, "\xd0r"], "\xad" => [0, "\xd0u"], "\xae" => [100, "\xd0"], "\xaf" => [110, "\xd0"], "\xb0" => [111, "\xd0"], "\xb1" => [115, "\xd0"], "\xb2" => [116, "\xd0"], "\xb3" => [118, "\xd0"], "\xb4" => [119, "\xd0"], "\xb5" => [122, "\xd0"], "\xb6" => [123, "\xd0"], "\xb7" => [125, "\xd0"], "\xb8" => [126, "\xd0"], "\xb9" => [129, "\xd0"], "\xba" => [143, "\xd0"], "\xbb" => [148, "\xd0"], "\xbc" => [151, "\xd0"], "\xbd" => [153, "\xd0"], "\xbe" => [83, "\xd0"], "\xbf" => [10, "\xd0"], "\xc0" => [0, "\x800"], "\xc1" => [0, "\x801"], "\xc2" => [0, "\x802"], "\xc3" => [0, "\x80a"], "\xc4" => [0, "\x80c"], "\xc5" => [0, "\x80e"], "\xc6" => [0, "\x80i"], "\xc7" => [0, "\x80o"], "\xc8" => [0, "\x80s"], "\xc9" => [0, "\x80t"], "\xca" => [73, "\x80"], "\xcb" => [88, "\x80"], "\xcc" => [89, "\x80"], "\xcd" => [96, "\x80"], "\xce" => [97, "\x80"], "\xcf" => [99, "\x80"], "\xd0" => [106, "\x80"], "\xd1" => [136, "\x80"], "\xd2" => [139, "\x80"], "\xd3" => [141, "\x80"], "\xd4" => [145, "\x80"], "\xd5" => [147, "\x80"], "\xd6" => [149, "\x80"], "\xd7" => [101, "\x80"], "\xd8" => [112, "\x80"], "\xd9" => [117, "\x80"], "\xda" => [120, "\x80"], "\xdb" => [124, "\x80"], "\xdc" => [127, "\x80"], "\xdd" => [144, "\x80"], "\xde" => [152, "\x80"], "\xdf" => [11, "\x80"], "\xe0" => [0, "\x820"], "\xe1" => [0, "\x821"], "\xe2" => [0, "\x822"], "\xe3" => [0, "\x82a"], "\xe4" => [0, "\x82c"], "\xe5" => [0, "\x82e"], "\xe6" => [0, "\x82i"], "\xe7" => [0, "\x82o"], "\xe8" => [0, "\x82s"], "\xe9" => [0, "\x82t"], "\xea" => [73, "\x82"], "\xeb" => [88, "\x82"], "\xec" => [89, "\x82"], "\xed" => [96, "\x82"], "\xee" => [97, "\x82"], "\xef" => [99, "\x82"], "\xf0" => [106, "\x82"], "\xf1" => [136, "\x82"], "\xf2" => [139, "\x82"], "\xf3" => [141, "\x82"], "\xf4" => [145, "\x82"], "\xf5" => [147, "\x82"], "\xf6" => [149, "\x82"], "\xf7" => [101, "\x82"], "\xf8" => [112, "\x82"], "\xf9" => [117, "\x82"], "\xfa" => [120, "\x82"], "\xfb" => [124, "\x82"], "\xfc" => [127, "\x82"], "\xfd" => [144, "\x82"], "\xfe" => [152, "\x82"], "\xff" => [11, "\x82"]], ["\x00" => [94, "]0"], "\x01" => [76, "]0"], "\x02" => [104, "]0"], "\x03" => [16, "]0"], "\x04" => [94, "]1"], "\x05" => [76, "]1"], "\x06" => [104, "]1"], "\x07" => [16, "]1"], "\x08" => [94, "]2"], "\t" => [76, "]2"], "\n" => [104, "]2"], "\v" => [16, "]2"], "\f" => [94, "]a"], "\r" => [76, "]a"], "\x0e" => [104, "]a"], "\x0f" => [16, "]a"], "\x10" => [94, "]c"], "\x11" => [76, "]c"], "\x12" => [104, "]c"], "\x13" => [16, "]c"], "\x14" => [94, "]e"], "\x15" => [76, "]e"], "\x16" => [104, "]e"], "\x17" => [16, "]e"], "\x18" => [94, "]i"], "\x19" => [76, "]i"], "\x1a" => [104, "]i"], "\x1b" => [16, "]i"], "\x1c" => [94, "]o"], "\x1d" => [76, "]o"], "\x1e" => [104, "]o"], "\x1f" => [16, "]o"], " " => [94, "]s"], "!" => [76, "]s"], "\"" => [104, "]s"], "#" => [16, "]s"], "\$" => [94, "]t"], "%" => [76, "]t"], "&" => [104, "]t"], "'" => [16, "]t"], "(" => [77, "] "], ")" => [18, "] "], "*" => [77, "]%"], "+" => [18, "]%"], "," => [77, "]-"], "-" => [18, "]-"], "." => [77, "]."], "/" => [18, "]."], [77, "]/"], [18, "]/"], [77, "]3"], [18, "]3"], [77, "]4"], [18, "]4"], [77, "]5"], [18, "]5"], [77, "]6"], [18, "]6"], ":" => [77, "]7"], ";" => [18, "]7"], "<" => [77, "]8"], "=" => [18, "]8"], ">" => [77, "]9"], "?" => [18, "]9"], "@" => [77, "]="], "A" => [18, "]="], "B" => [77, "]A"], "C" => [18, "]A"], "D" => [77, "]_"], "E" => [18, "]_"], "F" => [77, "]b"], "G" => [18, "]b"], "H" => [77, "]d"], "I" => [18, "]d"], "J" => [77, "]f"], "K" => [18, "]f"], "L" => [77, "]g"], "M" => [18, "]g"], "N" => [77, "]h"], "O" => [18, "]h"], "P" => [77, "]l"], "Q" => [18, "]l"], "R" => [77, "]m"], "S" => [18, "]m"], "T" => [77, "]n"], "U" => [18, "]n"], "V" => [77, "]p"], "W" => [18, "]p"], "X" => [77, "]r"], "Y" => [18, "]r"], "Z" => [77, "]u"], "[" => [18, "]u"], "\\" => [0, "]:"], "]" => [0, "]B"], "^" => [0, "]C"], "_" => [0, "]D"], "`" => [0, "]E"], "a" => [0, "]F"], "b" => [0, "]G"], "c" => [0, "]H"], "d" => [0, "]I"], "e" => [0, "]J"], "f" => [0, "]K"], "g" => [0, "]L"], "h" => [0, "]M"], "i" => [0, "]N"], "j" => [0, "]O"], "k" => [0, "]P"], "l" => [0, "]Q"], "m" => [0, "]R"], "n" => [0, "]S"], "o" => [0, "]T"], "p" => [0, "]U"], "q" => [0, "]V"], "r" => [0, "]W"], "s" => [0, "]Y"], "t" => [0, "]j"], "u" => [0, "]k"], "v" => [0, "]q"], "w" => [0, "]v"], "x" => [0, "]w"], "y" => [0, "]x"], "z" => [0, "]y"], "{" => [0, "]z"], "|" => [82, "]"], "}" => [87, "]"], "~" => [130, "]"], "" => [9, "]"], "\x80" => [94, "~0"], "\x81" => [76, "~0"], "\x82" => [104, "~0"], "\x83" => [16, "~0"], "\x84" => [94, "~1"], "\x85" => [76, "~1"], "\x86" => [104, "~1"], "\x87" => [16, "~1"], "\x88" => [94, "~2"], "\x89" => [76, "~2"], "\x8a" => [104, "~2"], "\x8b" => [16, "~2"], "\x8c" => [94, "~a"], "\x8d" => [76, "~a"], "\x8e" => [104, "~a"], "\x8f" => [16, "~a"], "\x90" => [94, "~c"], "\x91" => [76, "~c"], "\x92" => [104, "~c"], "\x93" => [16, "~c"], "\x94" => [94, "~e"], "\x95" => [76, "~e"], "\x96" => [104, "~e"], "\x97" => [16, "~e"], "\x98" => [94, "~i"], "\x99" => [76, "~i"], "\x9a" => [104, "~i"], "\x9b" => [16, "~i"], "\x9c" => [94, "~o"], "\x9d" => [76, "~o"], "\x9e" => [104, "~o"], "\x9f" => [16, "~o"], "\xa0" => [94, "~s"], "\xa1" => [76, "~s"], "\xa2" => [104, "~s"], "\xa3" => [16, "~s"], "\xa4" => [94, "~t"], "\xa5" => [76, "~t"], "\xa6" => [104, "~t"], "\xa7" => [16, "~t"], "\xa8" => [77, "~ "], "\xa9" => [18, "~ "], "\xaa" => [77, "~%"], "\xab" => [18, "~%"], "\xac" => [77, "~-"], "\xad" => [18, "~-"], "\xae" => [77, "~."], "\xaf" => [18, "~."], "\xb0" => [77, "~/"], "\xb1" => [18, "~/"], "\xb2" => [77, "~3"], "\xb3" => [18, "~3"], "\xb4" => [77, "~4"], "\xb5" => [18, "~4"], "\xb6" => [77, "~5"], "\xb7" => [18, "~5"], "\xb8" => [77, "~6"], "\xb9" => [18, "~6"], "\xba" => [77, "~7"], "\xbb" => [18, "~7"], "\xbc" => [77, "~8"], "\xbd" => [18, "~8"], "\xbe" => [77, "~9"], "\xbf" => [18, "~9"], "\xc0" => [77, "~="], "\xc1" => [18, "~="], "\xc2" => [77, "~A"], "\xc3" => [18, "~A"], "\xc4" => [77, "~_"], "\xc5" => [18, "~_"], "\xc6" => [77, "~b"], "\xc7" => [18, "~b"], "\xc8" => [77, "~d"], "\xc9" => [18, "~d"], "\xca" => [77, "~f"], "\xcb" => [18, "~f"], "\xcc" => [77, "~g"], "\xcd" => [18, "~g"], "\xce" => [77, "~h"], "\xcf" => [18, "~h"], "\xd0" => [77, "~l"], "\xd1" => [18, "~l"], "\xd2" => [77, "~m"], "\xd3" => [18, "~m"], "\xd4" => [77, "~n"], "\xd5" => [18, "~n"], "\xd6" => [77, "~p"], "\xd7" => [18, "~p"], "\xd8" => [77, "~r"], "\xd9" => [18, "~r"], "\xda" => [77, "~u"], "\xdb" => [18, "~u"], "\xdc" => [0, "~:"], "\xdd" => [0, "~B"], "\xde" => [0, "~C"], "\xdf" => [0, "~D"], "\xe0" => [0, "~E"], "\xe1" => [0, "~F"], "\xe2" => [0, "~G"], "\xe3" => [0, "~H"], "\xe4" => [0, "~I"], "\xe5" => [0, "~J"], "\xe6" => [0, "~K"], "\xe7" => [0, "~L"], "\xe8" => [0, "~M"], "\xe9" => [0, "~N"], "\xea" => [0, "~O"], "\xeb" => [0, "~P"], "\xec" => [0, "~Q"], "\xed" => [0, "~R"], "\xee" => [0, "~S"], "\xef" => [0, "~T"], "\xf0" => [0, "~U"], "\xf1" => [0, "~V"], "\xf2" => [0, "~W"], "\xf3" => [0, "~Y"], "\xf4" => [0, "~j"], "\xf5" => [0, "~k"], "\xf6" => [0, "~q"], "\xf7" => [0, "~v"], "\xf8" => [0, "~w"], "\xf9" => [0, "~x"], "\xfa" => [0, "~y"], "\xfb" => [0, "~z"], "\xfc" => [82, "~"], "\xfd" => [87, "~"], "\xfe" => [130, "~"], "\xff" => [9, "~"]], ["\x00" => [94, "^0"], "\x01" => [76, "^0"], "\x02" => [104, "^0"], "\x03" => [16, "^0"], "\x04" => [94, "^1"], "\x05" => [76, "^1"], "\x06" => [104, "^1"], "\x07" => [16, "^1"], "\x08" => [94, "^2"], "\t" => [76, "^2"], "\n" => [104, "^2"], "\v" => [16, "^2"], "\f" => [94, "^a"], "\r" => [76, "^a"], "\x0e" => [104, "^a"], "\x0f" => [16, "^a"], "\x10" => [94, "^c"], "\x11" => [76, "^c"], "\x12" => [104, "^c"], "\x13" => [16, "^c"], "\x14" => [94, "^e"], "\x15" => [76, "^e"], "\x16" => [104, "^e"], "\x17" => [16, "^e"], "\x18" => [94, "^i"], "\x19" => [76, "^i"], "\x1a" => [104, "^i"], "\x1b" => [16, "^i"], "\x1c" => [94, "^o"], "\x1d" => [76, "^o"], "\x1e" => [104, "^o"], "\x1f" => [16, "^o"], " " => [94, "^s"], "!" => [76, "^s"], "\"" => [104, "^s"], "#" => [16, "^s"], "\$" => [94, "^t"], "%" => [76, "^t"], "&" => [104, "^t"], "'" => [16, "^t"], "(" => [77, "^ "], ")" => [18, "^ "], "*" => [77, "^%"], "+" => [18, "^%"], "," => [77, "^-"], "-" => [18, "^-"], "." => [77, "^."], "/" => [18, "^."], [77, "^/"], [18, "^/"], [77, "^3"], [18, "^3"], [77, "^4"], [18, "^4"], [77, "^5"], [18, "^5"], [77, "^6"], [18, "^6"], ":" => [77, "^7"], ";" => [18, "^7"], "<" => [77, "^8"], "=" => [18, "^8"], ">" => [77, "^9"], "?" => [18, "^9"], "@" => [77, "^="], "A" => [18, "^="], "B" => [77, "^A"], "C" => [18, "^A"], "D" => [77, "^_"], "E" => [18, "^_"], "F" => [77, "^b"], "G" => [18, "^b"], "H" => [77, "^d"], "I" => [18, "^d"], "J" => [77, "^f"], "K" => [18, "^f"], "L" => [77, "^g"], "M" => [18, "^g"], "N" => [77, "^h"], "O" => [18, "^h"], "P" => [77, "^l"], "Q" => [18, "^l"], "R" => [77, "^m"], "S" => [18, "^m"], "T" => [77, "^n"], "U" => [18, "^n"], "V" => [77, "^p"], "W" => [18, "^p"], "X" => [77, "^r"], "Y" => [18, "^r"], "Z" => [77, "^u"], "[" => [18, "^u"], "\\" => [0, "^:"], "]" => [0, "^B"], "^" => [0, "^C"], "_" => [0, "^D"], "`" => [0, "^E"], "a" => [0, "^F"], "b" => [0, "^G"], "c" => [0, "^H"], "d" => [0, "^I"], "e" => [0, "^J"], "f" => [0, "^K"], "g" => [0, "^L"], "h" => [0, "^M"], "i" => [0, "^N"], "j" => [0, "^O"], "k" => [0, "^P"], "l" => [0, "^Q"], "m" => [0, "^R"], "n" => [0, "^S"], "o" => [0, "^T"], "p" => [0, "^U"], "q" => [0, "^V"], "r" => [0, "^W"], "s" => [0, "^Y"], "t" => [0, "^j"], "u" => [0, "^k"], "v" => [0, "^q"], "w" => [0, "^v"], "x" => [0, "^w"], "y" => [0, "^x"], "z" => [0, "^y"], "{" => [0, "^z"], "|" => [82, "^"], "}" => [87, "^"], "~" => [130, "^"], "" => [9, "^"], "\x80" => [94, "}0"], "\x81" => [76, "}0"], "\x82" => [104, "}0"], "\x83" => [16, "}0"], "\x84" => [94, "}1"], "\x85" => [76, "}1"], "\x86" => [104, "}1"], "\x87" => [16, "}1"], "\x88" => [94, "}2"], "\x89" => [76, "}2"], "\x8a" => [104, "}2"], "\x8b" => [16, "}2"], "\x8c" => [94, "}a"], "\x8d" => [76, "}a"], "\x8e" => [104, "}a"], "\x8f" => [16, "}a"], "\x90" => [94, "}c"], "\x91" => [76, "}c"], "\x92" => [104, "}c"], "\x93" => [16, "}c"], "\x94" => [94, "}e"], "\x95" => [76, "}e"], "\x96" => [104, "}e"], "\x97" => [16, "}e"], "\x98" => [94, "}i"], "\x99" => [76, "}i"], "\x9a" => [104, "}i"], "\x9b" => [16, "}i"], "\x9c" => [94, "}o"], "\x9d" => [76, "}o"], "\x9e" => [104, "}o"], "\x9f" => [16, "}o"], "\xa0" => [94, "}s"], "\xa1" => [76, "}s"], "\xa2" => [104, "}s"], "\xa3" => [16, "}s"], "\xa4" => [94, "}t"], "\xa5" => [76, "}t"], "\xa6" => [104, "}t"], "\xa7" => [16, "}t"], "\xa8" => [77, "} "], "\xa9" => [18, "} "], "\xaa" => [77, "}%"], "\xab" => [18, "}%"], "\xac" => [77, "}-"], "\xad" => [18, "}-"], "\xae" => [77, "}."], "\xaf" => [18, "}."], "\xb0" => [77, "}/"], "\xb1" => [18, "}/"], "\xb2" => [77, "}3"], "\xb3" => [18, "}3"], "\xb4" => [77, "}4"], "\xb5" => [18, "}4"], "\xb6" => [77, "}5"], "\xb7" => [18, "}5"], "\xb8" => [77, "}6"], "\xb9" => [18, "}6"], "\xba" => [77, "}7"], "\xbb" => [18, "}7"], "\xbc" => [77, "}8"], "\xbd" => [18, "}8"], "\xbe" => [77, "}9"], "\xbf" => [18, "}9"], "\xc0" => [77, "}="], "\xc1" => [18, "}="], "\xc2" => [77, "}A"], "\xc3" => [18, "}A"], "\xc4" => [77, "}_"], "\xc5" => [18, "}_"], "\xc6" => [77, "}b"], "\xc7" => [18, "}b"], "\xc8" => [77, "}d"], "\xc9" => [18, "}d"], "\xca" => [77, "}f"], "\xcb" => [18, "}f"], "\xcc" => [77, "}g"], "\xcd" => [18, "}g"], "\xce" => [77, "}h"], "\xcf" => [18, "}h"], "\xd0" => [77, "}l"], "\xd1" => [18, "}l"], "\xd2" => [77, "}m"], "\xd3" => [18, "}m"], "\xd4" => [77, "}n"], "\xd5" => [18, "}n"], "\xd6" => [77, "}p"], "\xd7" => [18, "}p"], "\xd8" => [77, "}r"], "\xd9" => [18, "}r"], "\xda" => [77, "}u"], "\xdb" => [18, "}u"], "\xdc" => [0, "}:"], "\xdd" => [0, "}B"], "\xde" => [0, "}C"], "\xdf" => [0, "}D"], "\xe0" => [0, "}E"], "\xe1" => [0, "}F"], "\xe2" => [0, "}G"], "\xe3" => [0, "}H"], "\xe4" => [0, "}I"], "\xe5" => [0, "}J"], "\xe6" => [0, "}K"], "\xe7" => [0, "}L"], "\xe8" => [0, "}M"], "\xe9" => [0, "}N"], "\xea" => [0, "}O"], "\xeb" => [0, "}P"], "\xec" => [0, "}Q"], "\xed" => [0, "}R"], "\xee" => [0, "}S"], "\xef" => [0, "}T"], "\xf0" => [0, "}U"], "\xf1" => [0, "}V"], "\xf2" => [0, "}W"], "\xf3" => [0, "}Y"], "\xf4" => [0, "}j"], "\xf5" => [0, "}k"], "\xf6" => [0, "}q"], "\xf7" => [0, "}v"], "\xf8" => [0, "}w"], "\xf9" => [0, "}x"], "\xfa" => [0, "}y"], "\xfb" => [0, "}z"], "\xfc" => [82, "}"], "\xfd" => [87, "}"], "\xfe" => [130, "}"], "\xff" => [9, "}"]], ["\x00" => [94, "_0"], "\x01" => [76, "_0"], "\x02" => [104, "_0"], "\x03" => [16, "_0"], "\x04" => [94, "_1"], "\x05" => [76, "_1"], "\x06" => [104, "_1"], "\x07" => [16, "_1"], "\x08" => [94, "_2"], "\t" => [76, "_2"], "\n" => [104, "_2"], "\v" => [16, "_2"], "\f" => [94, "_a"], "\r" => [76, "_a"], "\x0e" => [104, "_a"], "\x0f" => [16, "_a"], "\x10" => [94, "_c"], "\x11" => [76, "_c"], "\x12" => [104, "_c"], "\x13" => [16, "_c"], "\x14" => [94, "_e"], "\x15" => [76, "_e"], "\x16" => [104, "_e"], "\x17" => [16, "_e"], "\x18" => [94, "_i"], "\x19" => [76, "_i"], "\x1a" => [104, "_i"], "\x1b" => [16, "_i"], "\x1c" => [94, "_o"], "\x1d" => [76, "_o"], "\x1e" => [104, "_o"], "\x1f" => [16, "_o"], " " => [94, "_s"], "!" => [76, "_s"], "\"" => [104, "_s"], "#" => [16, "_s"], "\$" => [94, "_t"], "%" => [76, "_t"], "&" => [104, "_t"], "'" => [16, "_t"], "(" => [77, "_ "], ")" => [18, "_ "], "*" => [77, "_%"], "+" => [18, "_%"], "," => [77, "_-"], "-" => [18, "_-"], "." => [77, "_."], "/" => [18, "_."], [77, "_/"], [18, "_/"], [77, "_3"], [18, "_3"], [77, "_4"], [18, "_4"], [77, "_5"], [18, "_5"], [77, "_6"], [18, "_6"], ":" => [77, "_7"], ";" => [18, "_7"], "<" => [77, "_8"], "=" => [18, "_8"], ">" => [77, "_9"], "?" => [18, "_9"], "@" => [77, "_="], "A" => [18, "_="], "B" => [77, "_A"], "C" => [18, "_A"], "D" => [77, "__"], "E" => [18, "__"], "F" => [77, "_b"], "G" => [18, "_b"], "H" => [77, "_d"], "I" => [18, "_d"], "J" => [77, "_f"], "K" => [18, "_f"], "L" => [77, "_g"], "M" => [18, "_g"], "N" => [77, "_h"], "O" => [18, "_h"], "P" => [77, "_l"], "Q" => [18, "_l"], "R" => [77, "_m"], "S" => [18, "_m"], "T" => [77, "_n"], "U" => [18, "_n"], "V" => [77, "_p"], "W" => [18, "_p"], "X" => [77, "_r"], "Y" => [18, "_r"], "Z" => [77, "_u"], "[" => [18, "_u"], "\\" => [0, "_:"], "]" => [0, "_B"], "^" => [0, "_C"], "_" => [0, "_D"], "`" => [0, "_E"], "a" => [0, "_F"], "b" => [0, "_G"], "c" => [0, "_H"], "d" => [0, "_I"], "e" => [0, "_J"], "f" => [0, "_K"], "g" => [0, "_L"], "h" => [0, "_M"], "i" => [0, "_N"], "j" => [0, "_O"], "k" => [0, "_P"], "l" => [0, "_Q"], "m" => [0, "_R"], "n" => [0, "_S"], "o" => [0, "_T"], "p" => [0, "_U"], "q" => [0, "_V"], "r" => [0, "_W"], "s" => [0, "_Y"], "t" => [0, "_j"], "u" => [0, "_k"], "v" => [0, "_q"], "w" => [0, "_v"], "x" => [0, "_w"], "y" => [0, "_x"], "z" => [0, "_y"], "{" => [0, "_z"], "|" => [82, "_"], "}" => [87, "_"], "~" => [130, "_"], "" => [9, "_"], "\x80" => [94, "b0"], "\x81" => [76, "b0"], "\x82" => [104, "b0"], "\x83" => [16, "b0"], "\x84" => [94, "b1"], "\x85" => [76, "b1"], "\x86" => [104, "b1"], "\x87" => [16, "b1"], "\x88" => [94, "b2"], "\x89" => [76, "b2"], "\x8a" => [104, "b2"], "\x8b" => [16, "b2"], "\x8c" => [94, "ba"], "\x8d" => [76, "ba"], "\x8e" => [104, "ba"], "\x8f" => [16, "ba"], "\x90" => [94, "bc"], "\x91" => [76, "bc"], "\x92" => [104, "bc"], "\x93" => [16, "bc"], "\x94" => [94, "be"], "\x95" => [76, "be"], "\x96" => [104, "be"], "\x97" => [16, "be"], "\x98" => [94, "bi"], "\x99" => [76, "bi"], "\x9a" => [104, "bi"], "\x9b" => [16, "bi"], "\x9c" => [94, "bo"], "\x9d" => [76, "bo"], "\x9e" => [104, "bo"], "\x9f" => [16, "bo"], "\xa0" => [94, "bs"], "\xa1" => [76, "bs"], "\xa2" => [104, "bs"], "\xa3" => [16, "bs"], "\xa4" => [94, "bt"], "\xa5" => [76, "bt"], "\xa6" => [104, "bt"], "\xa7" => [16, "bt"], "\xa8" => [77, "b "], "\xa9" => [18, "b "], "\xaa" => [77, "b%"], "\xab" => [18, "b%"], "\xac" => [77, "b-"], "\xad" => [18, "b-"], "\xae" => [77, "b."], "\xaf" => [18, "b."], "\xb0" => [77, "b/"], "\xb1" => [18, "b/"], "\xb2" => [77, "b3"], "\xb3" => [18, "b3"], "\xb4" => [77, "b4"], "\xb5" => [18, "b4"], "\xb6" => [77, "b5"], "\xb7" => [18, "b5"], "\xb8" => [77, "b6"], "\xb9" => [18, "b6"], "\xba" => [77, "b7"], "\xbb" => [18, "b7"], "\xbc" => [77, "b8"], "\xbd" => [18, "b8"], "\xbe" => [77, "b9"], "\xbf" => [18, "b9"], "\xc0" => [77, "b="], "\xc1" => [18, "b="], "\xc2" => [77, "bA"], "\xc3" => [18, "bA"], "\xc4" => [77, "b_"], "\xc5" => [18, "b_"], "\xc6" => [77, "bb"], "\xc7" => [18, "bb"], "\xc8" => [77, "bd"], "\xc9" => [18, "bd"], "\xca" => [77, "bf"], "\xcb" => [18, "bf"], "\xcc" => [77, "bg"], "\xcd" => [18, "bg"], "\xce" => [77, "bh"], "\xcf" => [18, "bh"], "\xd0" => [77, "bl"], "\xd1" => [18, "bl"], "\xd2" => [77, "bm"], "\xd3" => [18, "bm"], "\xd4" => [77, "bn"], "\xd5" => [18, "bn"], "\xd6" => [77, "bp"], "\xd7" => [18, "bp"], "\xd8" => [77, "br"], "\xd9" => [18, "br"], "\xda" => [77, "bu"], "\xdb" => [18, "bu"], "\xdc" => [0, "b:"], "\xdd" => [0, "bB"], "\xde" => [0, "bC"], "\xdf" => [0, "bD"], "\xe0" => [0, "bE"], "\xe1" => [0, "bF"], "\xe2" => [0, "bG"], "\xe3" => [0, "bH"], "\xe4" => [0, "bI"], "\xe5" => [0, "bJ"], "\xe6" => [0, "bK"], "\xe7" => [0, "bL"], "\xe8" => [0, "bM"], "\xe9" => [0, "bN"], "\xea" => [0, "bO"], "\xeb" => [0, "bP"], "\xec" => [0, "bQ"], "\xed" => [0, "bR"], "\xee" => [0, "bS"], "\xef" => [0, "bT"], "\xf0" => [0, "bU"], "\xf1" => [0, "bV"], "\xf2" => [0, "bW"], "\xf3" => [0, "bY"], "\xf4" => [0, "bj"], "\xf5" => [0, "bk"], "\xf6" => [0, "bq"], "\xf7" => [0, "bv"], "\xf8" => [0, "bw"], "\xf9" => [0, "bx"], "\xfa" => [0, "by"], "\xfb" => [0, "bz"], "\xfc" => [82, "b"], "\xfd" => [87, "b"], "\xfe" => [130, "b"], "\xff" => [9, "b"]], ["\x00" => [94, "c0"], "\x01" => [76, "c0"], "\x02" => [104, "c0"], "\x03" => [16, "c0"], "\x04" => [94, "c1"], "\x05" => [76, "c1"], "\x06" => [104, "c1"], "\x07" => [16, "c1"], "\x08" => [94, "c2"], "\t" => [76, "c2"], "\n" => [104, "c2"], "\v" => [16, "c2"], "\f" => [94, "ca"], "\r" => [76, "ca"], "\x0e" => [104, "ca"], "\x0f" => [16, "ca"], "\x10" => [94, "cc"], "\x11" => [76, "cc"], "\x12" => [104, "cc"], "\x13" => [16, "cc"], "\x14" => [94, "ce"], "\x15" => [76, "ce"], "\x16" => [104, "ce"], "\x17" => [16, "ce"], "\x18" => [94, "ci"], "\x19" => [76, "ci"], "\x1a" => [104, "ci"], "\x1b" => [16, "ci"], "\x1c" => [94, "co"], "\x1d" => [76, "co"], "\x1e" => [104, "co"], "\x1f" => [16, "co"], " " => [94, "cs"], "!" => [76, "cs"], "\"" => [104, "cs"], "#" => [16, "cs"], "\$" => [94, "ct"], "%" => [76, "ct"], "&" => [104, "ct"], "'" => [16, "ct"], "(" => [77, "c "], ")" => [18, "c "], "*" => [77, "c%"], "+" => [18, "c%"], "," => [77, "c-"], "-" => [18, "c-"], "." => [77, "c."], "/" => [18, "c."], [77, "c/"], [18, "c/"], [77, "c3"], [18, "c3"], [77, "c4"], [18, "c4"], [77, "c5"], [18, "c5"], [77, "c6"], [18, "c6"], ":" => [77, "c7"], ";" => [18, "c7"], "<" => [77, "c8"], "=" => [18, "c8"], ">" => [77, "c9"], "?" => [18, "c9"], "@" => [77, "c="], "A" => [18, "c="], "B" => [77, "cA"], "C" => [18, "cA"], "D" => [77, "c_"], "E" => [18, "c_"], "F" => [77, "cb"], "G" => [18, "cb"], "H" => [77, "cd"], "I" => [18, "cd"], "J" => [77, "cf"], "K" => [18, "cf"], "L" => [77, "cg"], "M" => [18, "cg"], "N" => [77, "ch"], "O" => [18, "ch"], "P" => [77, "cl"], "Q" => [18, "cl"], "R" => [77, "cm"], "S" => [18, "cm"], "T" => [77, "cn"], "U" => [18, "cn"], "V" => [77, "cp"], "W" => [18, "cp"], "X" => [77, "cr"], "Y" => [18, "cr"], "Z" => [77, "cu"], "[" => [18, "cu"], "\\" => [0, "c:"], "]" => [0, "cB"], "^" => [0, "cC"], "_" => [0, "cD"], "`" => [0, "cE"], "a" => [0, "cF"], "b" => [0, "cG"], "c" => [0, "cH"], "d" => [0, "cI"], "e" => [0, "cJ"], "f" => [0, "cK"], "g" => [0, "cL"], "h" => [0, "cM"], "i" => [0, "cN"], "j" => [0, "cO"], "k" => [0, "cP"], "l" => [0, "cQ"], "m" => [0, "cR"], "n" => [0, "cS"], "o" => [0, "cT"], "p" => [0, "cU"], "q" => [0, "cV"], "r" => [0, "cW"], "s" => [0, "cY"], "t" => [0, "cj"], "u" => [0, "ck"], "v" => [0, "cq"], "w" => [0, "cv"], "x" => [0, "cw"], "y" => [0, "cx"], "z" => [0, "cy"], "{" => [0, "cz"], "|" => [82, "c"], "}" => [87, "c"], "~" => [130, "c"], "" => [9, "c"], "\x80" => [94, "e0"], "\x81" => [76, "e0"], "\x82" => [104, "e0"], "\x83" => [16, "e0"], "\x84" => [94, "e1"], "\x85" => [76, "e1"], "\x86" => [104, "e1"], "\x87" => [16, "e1"], "\x88" => [94, "e2"], "\x89" => [76, "e2"], "\x8a" => [104, "e2"], "\x8b" => [16, "e2"], "\x8c" => [94, "ea"], "\x8d" => [76, "ea"], "\x8e" => [104, "ea"], "\x8f" => [16, "ea"], "\x90" => [94, "ec"], "\x91" => [76, "ec"], "\x92" => [104, "ec"], "\x93" => [16, "ec"], "\x94" => [94, "ee"], "\x95" => [76, "ee"], "\x96" => [104, "ee"], "\x97" => [16, "ee"], "\x98" => [94, "ei"], "\x99" => [76, "ei"], "\x9a" => [104, "ei"], "\x9b" => [16, "ei"], "\x9c" => [94, "eo"], "\x9d" => [76, "eo"], "\x9e" => [104, "eo"], "\x9f" => [16, "eo"], "\xa0" => [94, "es"], "\xa1" => [76, "es"], "\xa2" => [104, "es"], "\xa3" => [16, "es"], "\xa4" => [94, "et"], "\xa5" => [76, "et"], "\xa6" => [104, "et"], "\xa7" => [16, "et"], "\xa8" => [77, "e "], "\xa9" => [18, "e "], "\xaa" => [77, "e%"], "\xab" => [18, "e%"], "\xac" => [77, "e-"], "\xad" => [18, "e-"], "\xae" => [77, "e."], "\xaf" => [18, "e."], "\xb0" => [77, "e/"], "\xb1" => [18, "e/"], "\xb2" => [77, "e3"], "\xb3" => [18, "e3"], "\xb4" => [77, "e4"], "\xb5" => [18, "e4"], "\xb6" => [77, "e5"], "\xb7" => [18, "e5"], "\xb8" => [77, "e6"], "\xb9" => [18, "e6"], "\xba" => [77, "e7"], "\xbb" => [18, "e7"], "\xbc" => [77, "e8"], "\xbd" => [18, "e8"], "\xbe" => [77, "e9"], "\xbf" => [18, "e9"], "\xc0" => [77, "e="], "\xc1" => [18, "e="], "\xc2" => [77, "eA"], "\xc3" => [18, "eA"], "\xc4" => [77, "e_"], "\xc5" => [18, "e_"], "\xc6" => [77, "eb"], "\xc7" => [18, "eb"], "\xc8" => [77, "ed"], "\xc9" => [18, "ed"], "\xca" => [77, "ef"], "\xcb" => [18, "ef"], "\xcc" => [77, "eg"], "\xcd" => [18, "eg"], "\xce" => [77, "eh"], "\xcf" => [18, "eh"], "\xd0" => [77, "el"], "\xd1" => [18, "el"], "\xd2" => [77, "em"], "\xd3" => [18, "em"], "\xd4" => [77, "en"], "\xd5" => [18, "en"], "\xd6" => [77, "ep"], "\xd7" => [18, "ep"], "\xd8" => [77, "er"], "\xd9" => [18, "er"], "\xda" => [77, "eu"], "\xdb" => [18, "eu"], "\xdc" => [0, "e:"], "\xdd" => [0, "eB"], "\xde" => [0, "eC"], "\xdf" => [0, "eD"], "\xe0" => [0, "eE"], "\xe1" => [0, "eF"], "\xe2" => [0, "eG"], "\xe3" => [0, "eH"], "\xe4" => [0, "eI"], "\xe5" => [0, "eJ"], "\xe6" => [0, "eK"], "\xe7" => [0, "eL"], "\xe8" => [0, "eM"], "\xe9" => [0, "eN"], "\xea" => [0, "eO"], "\xeb" => [0, "eP"], "\xec" => [0, "eQ"], "\xed" => [0, "eR"], "\xee" => [0, "eS"], "\xef" => [0, "eT"], "\xf0" => [0, "eU"], "\xf1" => [0, "eV"], "\xf2" => [0, "eW"], "\xf3" => [0, "eY"], "\xf4" => [0, "ej"], "\xf5" => [0, "ek"], "\xf6" => [0, "eq"], "\xf7" => [0, "ev"], "\xf8" => [0, "ew"], "\xf9" => [0, "ex"], "\xfa" => [0, "ey"], "\xfb" => [0, "ez"], "\xfc" => [82, "e"], "\xfd" => [87, "e"], "\xfe" => [130, "e"], "\xff" => [9, "e"]], ["\x00" => [77, "c0"], "\x01" => [18, "c0"], "\x02" => [77, "c1"], "\x03" => [18, "c1"], "\x04" => [77, "c2"], "\x05" => [18, "c2"], "\x06" => [77, "ca"], "\x07" => [18, "ca"], "\x08" => [77, "cc"], "\t" => [18, "cc"], "\n" => [77, "ce"], "\v" => [18, "ce"], "\f" => [77, "ci"], "\r" => [18, "ci"], "\x0e" => [77, "co"], "\x0f" => [18, "co"], "\x10" => [77, "cs"], "\x11" => [18, "cs"], "\x12" => [77, "ct"], "\x13" => [18, "ct"], "\x14" => [0, "c "], "\x15" => [0, "c%"], "\x16" => [0, "c-"], "\x17" => [0, "c."], "\x18" => [0, "c/"], "\x19" => [0, "c3"], "\x1a" => [0, "c4"], "\x1b" => [0, "c5"], "\x1c" => [0, "c6"], "\x1d" => [0, "c7"], "\x1e" => [0, "c8"], "\x1f" => [0, "c9"], " " => [0, "c="], "!" => [0, "cA"], "\"" => [0, "c_"], "#" => [0, "cb"], "\$" => [0, "cd"], "%" => [0, "cf"], "&" => [0, "cg"], "'" => [0, "ch"], "(" => [0, "cl"], ")" => [0, "cm"], "*" => [0, "cn"], "+" => [0, "cp"], "," => [0, "cr"], "-" => [0, "cu"], "." => [100, "c"], "/" => [110, "c"], [111, "c"], [115, "c"], [116, "c"], [118, "c"], [119, "c"], [122, "c"], [123, "c"], [125, "c"], [126, "c"], [129, "c"], ":" => [143, "c"], ";" => [148, "c"], "<" => [151, "c"], "=" => [153, "c"], ">" => [83, "c"], "?" => [10, "c"], "@" => [77, "e0"], "A" => [18, "e0"], "B" => [77, "e1"], "C" => [18, "e1"], "D" => [77, "e2"], "E" => [18, "e2"], "F" => [77, "ea"], "G" => [18, "ea"], "H" => [77, "ec"], "I" => [18, "ec"], "J" => [77, "ee"], "K" => [18, "ee"], "L" => [77, "ei"], "M" => [18, "ei"], "N" => [77, "eo"], "O" => [18, "eo"], "P" => [77, "es"], "Q" => [18, "es"], "R" => [77, "et"], "S" => [18, "et"], "T" => [0, "e "], "U" => [0, "e%"], "V" => [0, "e-"], "W" => [0, "e."], "X" => [0, "e/"], "Y" => [0, "e3"], "Z" => [0, "e4"], "[" => [0, "e5"], "\\" => [0, "e6"], "]" => [0, "e7"], "^" => [0, "e8"], "_" => [0, "e9"], "`" => [0, "e="], "a" => [0, "eA"], "b" => [0, "e_"], "c" => [0, "eb"], "d" => [0, "ed"], "e" => [0, "ef"], "f" => [0, "eg"], "g" => [0, "eh"], "h" => [0, "el"], "i" => [0, "em"], "j" => [0, "en"], "k" => [0, "ep"], "l" => [0, "er"], "m" => [0, "eu"], "n" => [100, "e"], "o" => [110, "e"], "p" => [111, "e"], "q" => [115, "e"], "r" => [116, "e"], "s" => [118, "e"], "t" => [119, "e"], "u" => [122, "e"], "v" => [123, "e"], "w" => [125, "e"], "x" => [126, "e"], "y" => [129, "e"], "z" => [143, "e"], "{" => [148, "e"], "|" => [151, "e"], "}" => [153, "e"], "~" => [83, "e"], "" => [10, "e"], "\x80" => [77, "i0"], "\x81" => [18, "i0"], "\x82" => [77, "i1"], "\x83" => [18, "i1"], "\x84" => [77, "i2"], "\x85" => [18, "i2"], "\x86" => [77, "ia"], "\x87" => [18, "ia"], "\x88" => [77, "ic"], "\x89" => [18, "ic"], "\x8a" => [77, "ie"], "\x8b" => [18, "ie"], "\x8c" => [77, "ii"], "\x8d" => [18, "ii"], "\x8e" => [77, "io"], "\x8f" => [18, "io"], "\x90" => [77, "is"], "\x91" => [18, "is"], "\x92" => [77, "it"], "\x93" => [18, "it"], "\x94" => [0, "i "], "\x95" => [0, "i%"], "\x96" => [0, "i-"], "\x97" => [0, "i."], "\x98" => [0, "i/"], "\x99" => [0, "i3"], "\x9a" => [0, "i4"], "\x9b" => [0, "i5"], "\x9c" => [0, "i6"], "\x9d" => [0, "i7"], "\x9e" => [0, "i8"], "\x9f" => [0, "i9"], "\xa0" => [0, "i="], "\xa1" => [0, "iA"], "\xa2" => [0, "i_"], "\xa3" => [0, "ib"], "\xa4" => [0, "id"], "\xa5" => [0, "if"], "\xa6" => [0, "ig"], "\xa7" => [0, "ih"], "\xa8" => [0, "il"], "\xa9" => [0, "im"], "\xaa" => [0, "in"], "\xab" => [0, "ip"], "\xac" => [0, "ir"], "\xad" => [0, "iu"], "\xae" => [100, "i"], "\xaf" => [110, "i"], "\xb0" => [111, "i"], "\xb1" => [115, "i"], "\xb2" => [116, "i"], "\xb3" => [118, "i"], "\xb4" => [119, "i"], "\xb5" => [122, "i"], "\xb6" => [123, "i"], "\xb7" => [125, "i"], "\xb8" => [126, "i"], "\xb9" => [129, "i"], "\xba" => [143, "i"], "\xbb" => [148, "i"], "\xbc" => [151, "i"], "\xbd" => [153, "i"], "\xbe" => [83, "i"], "\xbf" => [10, "i"], "\xc0" => [77, "o0"], "\xc1" => [18, "o0"], "\xc2" => [77, "o1"], "\xc3" => [18, "o1"], "\xc4" => [77, "o2"], "\xc5" => [18, "o2"], "\xc6" => [77, "oa"], "\xc7" => [18, "oa"], "\xc8" => [77, "oc"], "\xc9" => [18, "oc"], "\xca" => [77, "oe"], "\xcb" => [18, "oe"], "\xcc" => [77, "oi"], "\xcd" => [18, "oi"], "\xce" => [77, "oo"], "\xcf" => [18, "oo"], "\xd0" => [77, "os"], "\xd1" => [18, "os"], "\xd2" => [77, "ot"], "\xd3" => [18, "ot"], "\xd4" => [0, "o "], "\xd5" => [0, "o%"], "\xd6" => [0, "o-"], "\xd7" => [0, "o."], "\xd8" => [0, "o/"], "\xd9" => [0, "o3"], "\xda" => [0, "o4"], "\xdb" => [0, "o5"], "\xdc" => [0, "o6"], "\xdd" => [0, "o7"], "\xde" => [0, "o8"], "\xdf" => [0, "o9"], "\xe0" => [0, "o="], "\xe1" => [0, "oA"], "\xe2" => [0, "o_"], "\xe3" => [0, "ob"], "\xe4" => [0, "od"], "\xe5" => [0, "of"], "\xe6" => [0, "og"], "\xe7" => [0, "oh"], "\xe8" => [0, "ol"], "\xe9" => [0, "om"], "\xea" => [0, "on"], "\xeb" => [0, "op"], "\xec" => [0, "or"], "\xed" => [0, "ou"], "\xee" => [100, "o"], "\xef" => [110, "o"], "\xf0" => [111, "o"], "\xf1" => [115, "o"], "\xf2" => [116, "o"], "\xf3" => [118, "o"], "\xf4" => [119, "o"], "\xf5" => [122, "o"], "\xf6" => [123, "o"], "\xf7" => [125, "o"], "\xf8" => [126, "o"], "\xf9" => [129, "o"], "\xfa" => [143, "o"], "\xfb" => [148, "o"], "\xfc" => [151, "o"], "\xfd" => [153, "o"], "\xfe" => [83, "o"], "\xff" => [10, "o"]], ["\x00" => [94, "d0"], "\x01" => [76, "d0"], "\x02" => [104, "d0"], "\x03" => [16, "d0"], "\x04" => [94, "d1"], "\x05" => [76, "d1"], "\x06" => [104, "d1"], "\x07" => [16, "d1"], "\x08" => [94, "d2"], "\t" => [76, "d2"], "\n" => [104, "d2"], "\v" => [16, "d2"], "\f" => [94, "da"], "\r" => [76, "da"], "\x0e" => [104, "da"], "\x0f" => [16, "da"], "\x10" => [94, "dc"], "\x11" => [76, "dc"], "\x12" => [104, "dc"], "\x13" => [16, "dc"], "\x14" => [94, "de"], "\x15" => [76, "de"], "\x16" => [104, "de"], "\x17" => [16, "de"], "\x18" => [94, "di"], "\x19" => [76, "di"], "\x1a" => [104, "di"], "\x1b" => [16, "di"], "\x1c" => [94, "do"], "\x1d" => [76, "do"], "\x1e" => [104, "do"], "\x1f" => [16, "do"], " " => [94, "ds"], "!" => [76, "ds"], "\"" => [104, "ds"], "#" => [16, "ds"], "\$" => [94, "dt"], "%" => [76, "dt"], "&" => [104, "dt"], "'" => [16, "dt"], "(" => [77, "d "], ")" => [18, "d "], "*" => [77, "d%"], "+" => [18, "d%"], "," => [77, "d-"], "-" => [18, "d-"], "." => [77, "d."], "/" => [18, "d."], [77, "d/"], [18, "d/"], [77, "d3"], [18, "d3"], [77, "d4"], [18, "d4"], [77, "d5"], [18, "d5"], [77, "d6"], [18, "d6"], ":" => [77, "d7"], ";" => [18, "d7"], "<" => [77, "d8"], "=" => [18, "d8"], ">" => [77, "d9"], "?" => [18, "d9"], "@" => [77, "d="], "A" => [18, "d="], "B" => [77, "dA"], "C" => [18, "dA"], "D" => [77, "d_"], "E" => [18, "d_"], "F" => [77, "db"], "G" => [18, "db"], "H" => [77, "dd"], "I" => [18, "dd"], "J" => [77, "df"], "K" => [18, "df"], "L" => [77, "dg"], "M" => [18, "dg"], "N" => [77, "dh"], "O" => [18, "dh"], "P" => [77, "dl"], "Q" => [18, "dl"], "R" => [77, "dm"], "S" => [18, "dm"], "T" => [77, "dn"], "U" => [18, "dn"], "V" => [77, "dp"], "W" => [18, "dp"], "X" => [77, "dr"], "Y" => [18, "dr"], "Z" => [77, "du"], "[" => [18, "du"], "\\" => [0, "d:"], "]" => [0, "dB"], "^" => [0, "dC"], "_" => [0, "dD"], "`" => [0, "dE"], "a" => [0, "dF"], "b" => [0, "dG"], "c" => [0, "dH"], "d" => [0, "dI"], "e" => [0, "dJ"], "f" => [0, "dK"], "g" => [0, "dL"], "h" => [0, "dM"], "i" => [0, "dN"], "j" => [0, "dO"], "k" => [0, "dP"], "l" => [0, "dQ"], "m" => [0, "dR"], "n" => [0, "dS"], "o" => [0, "dT"], "p" => [0, "dU"], "q" => [0, "dV"], "r" => [0, "dW"], "s" => [0, "dY"], "t" => [0, "dj"], "u" => [0, "dk"], "v" => [0, "dq"], "w" => [0, "dv"], "x" => [0, "dw"], "y" => [0, "dx"], "z" => [0, "dy"], "{" => [0, "dz"], "|" => [82, "d"], "}" => [87, "d"], "~" => [130, "d"], "" => [9, "d"], "\x80" => [94, "f0"], "\x81" => [76, "f0"], "\x82" => [104, "f0"], "\x83" => [16, "f0"], "\x84" => [94, "f1"], "\x85" => [76, "f1"], "\x86" => [104, "f1"], "\x87" => [16, "f1"], "\x88" => [94, "f2"], "\x89" => [76, "f2"], "\x8a" => [104, "f2"], "\x8b" => [16, "f2"], "\x8c" => [94, "fa"], "\x8d" => [76, "fa"], "\x8e" => [104, "fa"], "\x8f" => [16, "fa"], "\x90" => [94, "fc"], "\x91" => [76, "fc"], "\x92" => [104, "fc"], "\x93" => [16, "fc"], "\x94" => [94, "fe"], "\x95" => [76, "fe"], "\x96" => [104, "fe"], "\x97" => [16, "fe"], "\x98" => [94, "fi"], "\x99" => [76, "fi"], "\x9a" => [104, "fi"], "\x9b" => [16, "fi"], "\x9c" => [94, "fo"], "\x9d" => [76, "fo"], "\x9e" => [104, "fo"], "\x9f" => [16, "fo"], "\xa0" => [94, "fs"], "\xa1" => [76, "fs"], "\xa2" => [104, "fs"], "\xa3" => [16, "fs"], "\xa4" => [94, "ft"], "\xa5" => [76, "ft"], "\xa6" => [104, "ft"], "\xa7" => [16, "ft"], "\xa8" => [77, "f "], "\xa9" => [18, "f "], "\xaa" => [77, "f%"], "\xab" => [18, "f%"], "\xac" => [77, "f-"], "\xad" => [18, "f-"], "\xae" => [77, "f."], "\xaf" => [18, "f."], "\xb0" => [77, "f/"], "\xb1" => [18, "f/"], "\xb2" => [77, "f3"], "\xb3" => [18, "f3"], "\xb4" => [77, "f4"], "\xb5" => [18, "f4"], "\xb6" => [77, "f5"], "\xb7" => [18, "f5"], "\xb8" => [77, "f6"], "\xb9" => [18, "f6"], "\xba" => [77, "f7"], "\xbb" => [18, "f7"], "\xbc" => [77, "f8"], "\xbd" => [18, "f8"], "\xbe" => [77, "f9"], "\xbf" => [18, "f9"], "\xc0" => [77, "f="], "\xc1" => [18, "f="], "\xc2" => [77, "fA"], "\xc3" => [18, "fA"], "\xc4" => [77, "f_"], "\xc5" => [18, "f_"], "\xc6" => [77, "fb"], "\xc7" => [18, "fb"], "\xc8" => [77, "fd"], "\xc9" => [18, "fd"], "\xca" => [77, "ff"], "\xcb" => [18, "ff"], "\xcc" => [77, "fg"], "\xcd" => [18, "fg"], "\xce" => [77, "fh"], "\xcf" => [18, "fh"], "\xd0" => [77, "fl"], "\xd1" => [18, "fl"], "\xd2" => [77, "fm"], "\xd3" => [18, "fm"], "\xd4" => [77, "fn"], "\xd5" => [18, "fn"], "\xd6" => [77, "fp"], "\xd7" => [18, "fp"], "\xd8" => [77, "fr"], "\xd9" => [18, "fr"], "\xda" => [77, "fu"], "\xdb" => [18, "fu"], "\xdc" => [0, "f:"], "\xdd" => [0, "fB"], "\xde" => [0, "fC"], "\xdf" => [0, "fD"], "\xe0" => [0, "fE"], "\xe1" => [0, "fF"], "\xe2" => [0, "fG"], "\xe3" => [0, "fH"], "\xe4" => [0, "fI"], "\xe5" => [0, "fJ"], "\xe6" => [0, "fK"], "\xe7" => [0, "fL"], "\xe8" => [0, "fM"], "\xe9" => [0, "fN"], "\xea" => [0, "fO"], "\xeb" => [0, "fP"], "\xec" => [0, "fQ"], "\xed" => [0, "fR"], "\xee" => [0, "fS"], "\xef" => [0, "fT"], "\xf0" => [0, "fU"], "\xf1" => [0, "fV"], "\xf2" => [0, "fW"], "\xf3" => [0, "fY"], "\xf4" => [0, "fj"], "\xf5" => [0, "fk"], "\xf6" => [0, "fq"], "\xf7" => [0, "fv"], "\xf8" => [0, "fw"], "\xf9" => [0, "fx"], "\xfa" => [0, "fy"], "\xfb" => [0, "fz"], "\xfc" => [82, "f"], "\xfd" => [87, "f"], "\xfe" => [130, "f"], "\xff" => [9, "f"]], ["\x00" => [77, "d0"], "\x01" => [18, "d0"], "\x02" => [77, "d1"], "\x03" => [18, "d1"], "\x04" => [77, "d2"], "\x05" => [18, "d2"], "\x06" => [77, "da"], "\x07" => [18, "da"], "\x08" => [77, "dc"], "\t" => [18, "dc"], "\n" => [77, "de"], "\v" => [18, "de"], "\f" => [77, "di"], "\r" => [18, "di"], "\x0e" => [77, "do"], "\x0f" => [18, "do"], "\x10" => [77, "ds"], "\x11" => [18, "ds"], "\x12" => [77, "dt"], "\x13" => [18, "dt"], "\x14" => [0, "d "], "\x15" => [0, "d%"], "\x16" => [0, "d-"], "\x17" => [0, "d."], "\x18" => [0, "d/"], "\x19" => [0, "d3"], "\x1a" => [0, "d4"], "\x1b" => [0, "d5"], "\x1c" => [0, "d6"], "\x1d" => [0, "d7"], "\x1e" => [0, "d8"], "\x1f" => [0, "d9"], " " => [0, "d="], "!" => [0, "dA"], "\"" => [0, "d_"], "#" => [0, "db"], "\$" => [0, "dd"], "%" => [0, "df"], "&" => [0, "dg"], "'" => [0, "dh"], "(" => [0, "dl"], ")" => [0, "dm"], "*" => [0, "dn"], "+" => [0, "dp"], "," => [0, "dr"], "-" => [0, "du"], "." => [100, "d"], "/" => [110, "d"], [111, "d"], [115, "d"], [116, "d"], [118, "d"], [119, "d"], [122, "d"], [123, "d"], [125, "d"], [126, "d"], [129, "d"], ":" => [143, "d"], ";" => [148, "d"], "<" => [151, "d"], "=" => [153, "d"], ">" => [83, "d"], "?" => [10, "d"], "@" => [77, "f0"], "A" => [18, "f0"], "B" => [77, "f1"], "C" => [18, "f1"], "D" => [77, "f2"], "E" => [18, "f2"], "F" => [77, "fa"], "G" => [18, "fa"], "H" => [77, "fc"], "I" => [18, "fc"], "J" => [77, "fe"], "K" => [18, "fe"], "L" => [77, "fi"], "M" => [18, "fi"], "N" => [77, "fo"], "O" => [18, "fo"], "P" => [77, "fs"], "Q" => [18, "fs"], "R" => [77, "ft"], "S" => [18, "ft"], "T" => [0, "f "], "U" => [0, "f%"], "V" => [0, "f-"], "W" => [0, "f."], "X" => [0, "f/"], "Y" => [0, "f3"], "Z" => [0, "f4"], "[" => [0, "f5"], "\\" => [0, "f6"], "]" => [0, "f7"], "^" => [0, "f8"], "_" => [0, "f9"], "`" => [0, "f="], "a" => [0, "fA"], "b" => [0, "f_"], "c" => [0, "fb"], "d" => [0, "fd"], "e" => [0, "ff"], "f" => [0, "fg"], "g" => [0, "fh"], "h" => [0, "fl"], "i" => [0, "fm"], "j" => [0, "fn"], "k" => [0, "fp"], "l" => [0, "fr"], "m" => [0, "fu"], "n" => [100, "f"], "o" => [110, "f"], "p" => [111, "f"], "q" => [115, "f"], "r" => [116, "f"], "s" => [118, "f"], "t" => [119, "f"], "u" => [122, "f"], "v" => [123, "f"], "w" => [125, "f"], "x" => [126, "f"], "y" => [129, "f"], "z" => [143, "f"], "{" => [148, "f"], "|" => [151, "f"], "}" => [153, "f"], "~" => [83, "f"], "" => [10, "f"], "\x80" => [77, "g0"], "\x81" => [18, "g0"], "\x82" => [77, "g1"], "\x83" => [18, "g1"], "\x84" => [77, "g2"], "\x85" => [18, "g2"], "\x86" => [77, "ga"], "\x87" => [18, "ga"], "\x88" => [77, "gc"], "\x89" => [18, "gc"], "\x8a" => [77, "ge"], "\x8b" => [18, "ge"], "\x8c" => [77, "gi"], "\x8d" => [18, "gi"], "\x8e" => [77, "go"], "\x8f" => [18, "go"], "\x90" => [77, "gs"], "\x91" => [18, "gs"], "\x92" => [77, "gt"], "\x93" => [18, "gt"], "\x94" => [0, "g "], "\x95" => [0, "g%"], "\x96" => [0, "g-"], "\x97" => [0, "g."], "\x98" => [0, "g/"], "\x99" => [0, "g3"], "\x9a" => [0, "g4"], "\x9b" => [0, "g5"], "\x9c" => [0, "g6"], "\x9d" => [0, "g7"], "\x9e" => [0, "g8"], "\x9f" => [0, "g9"], "\xa0" => [0, "g="], "\xa1" => [0, "gA"], "\xa2" => [0, "g_"], "\xa3" => [0, "gb"], "\xa4" => [0, "gd"], "\xa5" => [0, "gf"], "\xa6" => [0, "gg"], "\xa7" => [0, "gh"], "\xa8" => [0, "gl"], "\xa9" => [0, "gm"], "\xaa" => [0, "gn"], "\xab" => [0, "gp"], "\xac" => [0, "gr"], "\xad" => [0, "gu"], "\xae" => [100, "g"], "\xaf" => [110, "g"], "\xb0" => [111, "g"], "\xb1" => [115, "g"], "\xb2" => [116, "g"], "\xb3" => [118, "g"], "\xb4" => [119, "g"], "\xb5" => [122, "g"], "\xb6" => [123, "g"], "\xb7" => [125, "g"], "\xb8" => [126, "g"], "\xb9" => [129, "g"], "\xba" => [143, "g"], "\xbb" => [148, "g"], "\xbc" => [151, "g"], "\xbd" => [153, "g"], "\xbe" => [83, "g"], "\xbf" => [10, "g"], "\xc0" => [77, "h0"], "\xc1" => [18, "h0"], "\xc2" => [77, "h1"], "\xc3" => [18, "h1"], "\xc4" => [77, "h2"], "\xc5" => [18, "h2"], "\xc6" => [77, "ha"], "\xc7" => [18, "ha"], "\xc8" => [77, "hc"], "\xc9" => [18, "hc"], "\xca" => [77, "he"], "\xcb" => [18, "he"], "\xcc" => [77, "hi"], "\xcd" => [18, "hi"], "\xce" => [77, "ho"], "\xcf" => [18, "ho"], "\xd0" => [77, "hs"], "\xd1" => [18, "hs"], "\xd2" => [77, "ht"], "\xd3" => [18, "ht"], "\xd4" => [0, "h "], "\xd5" => [0, "h%"], "\xd6" => [0, "h-"], "\xd7" => [0, "h."], "\xd8" => [0, "h/"], "\xd9" => [0, "h3"], "\xda" => [0, "h4"], "\xdb" => [0, "h5"], "\xdc" => [0, "h6"], "\xdd" => [0, "h7"], "\xde" => [0, "h8"], "\xdf" => [0, "h9"], "\xe0" => [0, "h="], "\xe1" => [0, "hA"], "\xe2" => [0, "h_"], "\xe3" => [0, "hb"], "\xe4" => [0, "hd"], "\xe5" => [0, "hf"], "\xe6" => [0, "hg"], "\xe7" => [0, "hh"], "\xe8" => [0, "hl"], "\xe9" => [0, "hm"], "\xea" => [0, "hn"], "\xeb" => [0, "hp"], "\xec" => [0, "hr"], "\xed" => [0, "hu"], "\xee" => [100, "h"], "\xef" => [110, "h"], "\xf0" => [111, "h"], "\xf1" => [115, "h"], "\xf2" => [116, "h"], "\xf3" => [118, "h"], "\xf4" => [119, "h"], "\xf5" => [122, "h"], "\xf6" => [123, "h"], "\xf7" => [125, "h"], "\xf8" => [126, "h"], "\xf9" => [129, "h"], "\xfa" => [143, "h"], "\xfb" => [148, "h"], "\xfc" => [151, "h"], "\xfd" => [153, "h"], "\xfe" => [83, "h"], "\xff" => [10, "h"]], ["\x00" => [94, "g0"], "\x01" => [76, "g0"], "\x02" => [104, "g0"], "\x03" => [16, "g0"], "\x04" => [94, "g1"], "\x05" => [76, "g1"], "\x06" => [104, "g1"], "\x07" => [16, "g1"], "\x08" => [94, "g2"], "\t" => [76, "g2"], "\n" => [104, "g2"], "\v" => [16, "g2"], "\f" => [94, "ga"], "\r" => [76, "ga"], "\x0e" => [104, "ga"], "\x0f" => [16, "ga"], "\x10" => [94, "gc"], "\x11" => [76, "gc"], "\x12" => [104, "gc"], "\x13" => [16, "gc"], "\x14" => [94, "ge"], "\x15" => [76, "ge"], "\x16" => [104, "ge"], "\x17" => [16, "ge"], "\x18" => [94, "gi"], "\x19" => [76, "gi"], "\x1a" => [104, "gi"], "\x1b" => [16, "gi"], "\x1c" => [94, "go"], "\x1d" => [76, "go"], "\x1e" => [104, "go"], "\x1f" => [16, "go"], " " => [94, "gs"], "!" => [76, "gs"], "\"" => [104, "gs"], "#" => [16, "gs"], "\$" => [94, "gt"], "%" => [76, "gt"], "&" => [104, "gt"], "'" => [16, "gt"], "(" => [77, "g "], ")" => [18, "g "], "*" => [77, "g%"], "+" => [18, "g%"], "," => [77, "g-"], "-" => [18, "g-"], "." => [77, "g."], "/" => [18, "g."], [77, "g/"], [18, "g/"], [77, "g3"], [18, "g3"], [77, "g4"], [18, "g4"], [77, "g5"], [18, "g5"], [77, "g6"], [18, "g6"], ":" => [77, "g7"], ";" => [18, "g7"], "<" => [77, "g8"], "=" => [18, "g8"], ">" => [77, "g9"], "?" => [18, "g9"], "@" => [77, "g="], "A" => [18, "g="], "B" => [77, "gA"], "C" => [18, "gA"], "D" => [77, "g_"], "E" => [18, "g_"], "F" => [77, "gb"], "G" => [18, "gb"], "H" => [77, "gd"], "I" => [18, "gd"], "J" => [77, "gf"], "K" => [18, "gf"], "L" => [77, "gg"], "M" => [18, "gg"], "N" => [77, "gh"], "O" => [18, "gh"], "P" => [77, "gl"], "Q" => [18, "gl"], "R" => [77, "gm"], "S" => [18, "gm"], "T" => [77, "gn"], "U" => [18, "gn"], "V" => [77, "gp"], "W" => [18, "gp"], "X" => [77, "gr"], "Y" => [18, "gr"], "Z" => [77, "gu"], "[" => [18, "gu"], "\\" => [0, "g:"], "]" => [0, "gB"], "^" => [0, "gC"], "_" => [0, "gD"], "`" => [0, "gE"], "a" => [0, "gF"], "b" => [0, "gG"], "c" => [0, "gH"], "d" => [0, "gI"], "e" => [0, "gJ"], "f" => [0, "gK"], "g" => [0, "gL"], "h" => [0, "gM"], "i" => [0, "gN"], "j" => [0, "gO"], "k" => [0, "gP"], "l" => [0, "gQ"], "m" => [0, "gR"], "n" => [0, "gS"], "o" => [0, "gT"], "p" => [0, "gU"], "q" => [0, "gV"], "r" => [0, "gW"], "s" => [0, "gY"], "t" => [0, "gj"], "u" => [0, "gk"], "v" => [0, "gq"], "w" => [0, "gv"], "x" => [0, "gw"], "y" => [0, "gx"], "z" => [0, "gy"], "{" => [0, "gz"], "|" => [82, "g"], "}" => [87, "g"], "~" => [130, "g"], "" => [9, "g"], "\x80" => [94, "h0"], "\x81" => [76, "h0"], "\x82" => [104, "h0"], "\x83" => [16, "h0"], "\x84" => [94, "h1"], "\x85" => [76, "h1"], "\x86" => [104, "h1"], "\x87" => [16, "h1"], "\x88" => [94, "h2"], "\x89" => [76, "h2"], "\x8a" => [104, "h2"], "\x8b" => [16, "h2"], "\x8c" => [94, "ha"], "\x8d" => [76, "ha"], "\x8e" => [104, "ha"], "\x8f" => [16, "ha"], "\x90" => [94, "hc"], "\x91" => [76, "hc"], "\x92" => [104, "hc"], "\x93" => [16, "hc"], "\x94" => [94, "he"], "\x95" => [76, "he"], "\x96" => [104, "he"], "\x97" => [16, "he"], "\x98" => [94, "hi"], "\x99" => [76, "hi"], "\x9a" => [104, "hi"], "\x9b" => [16, "hi"], "\x9c" => [94, "ho"], "\x9d" => [76, "ho"], "\x9e" => [104, "ho"], "\x9f" => [16, "ho"], "\xa0" => [94, "hs"], "\xa1" => [76, "hs"], "\xa2" => [104, "hs"], "\xa3" => [16, "hs"], "\xa4" => [94, "ht"], "\xa5" => [76, "ht"], "\xa6" => [104, "ht"], "\xa7" => [16, "ht"], "\xa8" => [77, "h "], "\xa9" => [18, "h "], "\xaa" => [77, "h%"], "\xab" => [18, "h%"], "\xac" => [77, "h-"], "\xad" => [18, "h-"], "\xae" => [77, "h."], "\xaf" => [18, "h."], "\xb0" => [77, "h/"], "\xb1" => [18, "h/"], "\xb2" => [77, "h3"], "\xb3" => [18, "h3"], "\xb4" => [77, "h4"], "\xb5" => [18, "h4"], "\xb6" => [77, "h5"], "\xb7" => [18, "h5"], "\xb8" => [77, "h6"], "\xb9" => [18, "h6"], "\xba" => [77, "h7"], "\xbb" => [18, "h7"], "\xbc" => [77, "h8"], "\xbd" => [18, "h8"], "\xbe" => [77, "h9"], "\xbf" => [18, "h9"], "\xc0" => [77, "h="], "\xc1" => [18, "h="], "\xc2" => [77, "hA"], "\xc3" => [18, "hA"], "\xc4" => [77, "h_"], "\xc5" => [18, "h_"], "\xc6" => [77, "hb"], "\xc7" => [18, "hb"], "\xc8" => [77, "hd"], "\xc9" => [18, "hd"], "\xca" => [77, "hf"], "\xcb" => [18, "hf"], "\xcc" => [77, "hg"], "\xcd" => [18, "hg"], "\xce" => [77, "hh"], "\xcf" => [18, "hh"], "\xd0" => [77, "hl"], "\xd1" => [18, "hl"], "\xd2" => [77, "hm"], "\xd3" => [18, "hm"], "\xd4" => [77, "hn"], "\xd5" => [18, "hn"], "\xd6" => [77, "hp"], "\xd7" => [18, "hp"], "\xd8" => [77, "hr"], "\xd9" => [18, "hr"], "\xda" => [77, "hu"], "\xdb" => [18, "hu"], "\xdc" => [0, "h:"], "\xdd" => [0, "hB"], "\xde" => [0, "hC"], "\xdf" => [0, "hD"], "\xe0" => [0, "hE"], "\xe1" => [0, "hF"], "\xe2" => [0, "hG"], "\xe3" => [0, "hH"], "\xe4" => [0, "hI"], "\xe5" => [0, "hJ"], "\xe6" => [0, "hK"], "\xe7" => [0, "hL"], "\xe8" => [0, "hM"], "\xe9" => [0, "hN"], "\xea" => [0, "hO"], "\xeb" => [0, "hP"], "\xec" => [0, "hQ"], "\xed" => [0, "hR"], "\xee" => [0, "hS"], "\xef" => [0, "hT"], "\xf0" => [0, "hU"], "\xf1" => [0, "hV"], "\xf2" => [0, "hW"], "\xf3" => [0, "hY"], "\xf4" => [0, "hj"], "\xf5" => [0, "hk"], "\xf6" => [0, "hq"], "\xf7" => [0, "hv"], "\xf8" => [0, "hw"], "\xf9" => [0, "hx"], "\xfa" => [0, "hy"], "\xfb" => [0, "hz"], "\xfc" => [82, "h"], "\xfd" => [87, "h"], "\xfe" => [130, "h"], "\xff" => [9, "h"]], ["\x00" => [94, "i0"], "\x01" => [76, "i0"], "\x02" => [104, "i0"], "\x03" => [16, "i0"], "\x04" => [94, "i1"], "\x05" => [76, "i1"], "\x06" => [104, "i1"], "\x07" => [16, "i1"], "\x08" => [94, "i2"], "\t" => [76, "i2"], "\n" => [104, "i2"], "\v" => [16, "i2"], "\f" => [94, "ia"], "\r" => [76, "ia"], "\x0e" => [104, "ia"], "\x0f" => [16, "ia"], "\x10" => [94, "ic"], "\x11" => [76, "ic"], "\x12" => [104, "ic"], "\x13" => [16, "ic"], "\x14" => [94, "ie"], "\x15" => [76, "ie"], "\x16" => [104, "ie"], "\x17" => [16, "ie"], "\x18" => [94, "ii"], "\x19" => [76, "ii"], "\x1a" => [104, "ii"], "\x1b" => [16, "ii"], "\x1c" => [94, "io"], "\x1d" => [76, "io"], "\x1e" => [104, "io"], "\x1f" => [16, "io"], " " => [94, "is"], "!" => [76, "is"], "\"" => [104, "is"], "#" => [16, "is"], "\$" => [94, "it"], "%" => [76, "it"], "&" => [104, "it"], "'" => [16, "it"], "(" => [77, "i "], ")" => [18, "i "], "*" => [77, "i%"], "+" => [18, "i%"], "," => [77, "i-"], "-" => [18, "i-"], "." => [77, "i."], "/" => [18, "i."], [77, "i/"], [18, "i/"], [77, "i3"], [18, "i3"], [77, "i4"], [18, "i4"], [77, "i5"], [18, "i5"], [77, "i6"], [18, "i6"], ":" => [77, "i7"], ";" => [18, "i7"], "<" => [77, "i8"], "=" => [18, "i8"], ">" => [77, "i9"], "?" => [18, "i9"], "@" => [77, "i="], "A" => [18, "i="], "B" => [77, "iA"], "C" => [18, "iA"], "D" => [77, "i_"], "E" => [18, "i_"], "F" => [77, "ib"], "G" => [18, "ib"], "H" => [77, "id"], "I" => [18, "id"], "J" => [77, "if"], "K" => [18, "if"], "L" => [77, "ig"], "M" => [18, "ig"], "N" => [77, "ih"], "O" => [18, "ih"], "P" => [77, "il"], "Q" => [18, "il"], "R" => [77, "im"], "S" => [18, "im"], "T" => [77, "in"], "U" => [18, "in"], "V" => [77, "ip"], "W" => [18, "ip"], "X" => [77, "ir"], "Y" => [18, "ir"], "Z" => [77, "iu"], "[" => [18, "iu"], "\\" => [0, "i:"], "]" => [0, "iB"], "^" => [0, "iC"], "_" => [0, "iD"], "`" => [0, "iE"], "a" => [0, "iF"], "b" => [0, "iG"], "c" => [0, "iH"], "d" => [0, "iI"], "e" => [0, "iJ"], "f" => [0, "iK"], "g" => [0, "iL"], "h" => [0, "iM"], "i" => [0, "iN"], "j" => [0, "iO"], "k" => [0, "iP"], "l" => [0, "iQ"], "m" => [0, "iR"], "n" => [0, "iS"], "o" => [0, "iT"], "p" => [0, "iU"], "q" => [0, "iV"], "r" => [0, "iW"], "s" => [0, "iY"], "t" => [0, "ij"], "u" => [0, "ik"], "v" => [0, "iq"], "w" => [0, "iv"], "x" => [0, "iw"], "y" => [0, "ix"], "z" => [0, "iy"], "{" => [0, "iz"], "|" => [82, "i"], "}" => [87, "i"], "~" => [130, "i"], "" => [9, "i"], "\x80" => [94, "o0"], "\x81" => [76, "o0"], "\x82" => [104, "o0"], "\x83" => [16, "o0"], "\x84" => [94, "o1"], "\x85" => [76, "o1"], "\x86" => [104, "o1"], "\x87" => [16, "o1"], "\x88" => [94, "o2"], "\x89" => [76, "o2"], "\x8a" => [104, "o2"], "\x8b" => [16, "o2"], "\x8c" => [94, "oa"], "\x8d" => [76, "oa"], "\x8e" => [104, "oa"], "\x8f" => [16, "oa"], "\x90" => [94, "oc"], "\x91" => [76, "oc"], "\x92" => [104, "oc"], "\x93" => [16, "oc"], "\x94" => [94, "oe"], "\x95" => [76, "oe"], "\x96" => [104, "oe"], "\x97" => [16, "oe"], "\x98" => [94, "oi"], "\x99" => [76, "oi"], "\x9a" => [104, "oi"], "\x9b" => [16, "oi"], "\x9c" => [94, "oo"], "\x9d" => [76, "oo"], "\x9e" => [104, "oo"], "\x9f" => [16, "oo"], "\xa0" => [94, "os"], "\xa1" => [76, "os"], "\xa2" => [104, "os"], "\xa3" => [16, "os"], "\xa4" => [94, "ot"], "\xa5" => [76, "ot"], "\xa6" => [104, "ot"], "\xa7" => [16, "ot"], "\xa8" => [77, "o "], "\xa9" => [18, "o "], "\xaa" => [77, "o%"], "\xab" => [18, "o%"], "\xac" => [77, "o-"], "\xad" => [18, "o-"], "\xae" => [77, "o."], "\xaf" => [18, "o."], "\xb0" => [77, "o/"], "\xb1" => [18, "o/"], "\xb2" => [77, "o3"], "\xb3" => [18, "o3"], "\xb4" => [77, "o4"], "\xb5" => [18, "o4"], "\xb6" => [77, "o5"], "\xb7" => [18, "o5"], "\xb8" => [77, "o6"], "\xb9" => [18, "o6"], "\xba" => [77, "o7"], "\xbb" => [18, "o7"], "\xbc" => [77, "o8"], "\xbd" => [18, "o8"], "\xbe" => [77, "o9"], "\xbf" => [18, "o9"], "\xc0" => [77, "o="], "\xc1" => [18, "o="], "\xc2" => [77, "oA"], "\xc3" => [18, "oA"], "\xc4" => [77, "o_"], "\xc5" => [18, "o_"], "\xc6" => [77, "ob"], "\xc7" => [18, "ob"], "\xc8" => [77, "od"], "\xc9" => [18, "od"], "\xca" => [77, "of"], "\xcb" => [18, "of"], "\xcc" => [77, "og"], "\xcd" => [18, "og"], "\xce" => [77, "oh"], "\xcf" => [18, "oh"], "\xd0" => [77, "ol"], "\xd1" => [18, "ol"], "\xd2" => [77, "om"], "\xd3" => [18, "om"], "\xd4" => [77, "on"], "\xd5" => [18, "on"], "\xd6" => [77, "op"], "\xd7" => [18, "op"], "\xd8" => [77, "or"], "\xd9" => [18, "or"], "\xda" => [77, "ou"], "\xdb" => [18, "ou"], "\xdc" => [0, "o:"], "\xdd" => [0, "oB"], "\xde" => [0, "oC"], "\xdf" => [0, "oD"], "\xe0" => [0, "oE"], "\xe1" => [0, "oF"], "\xe2" => [0, "oG"], "\xe3" => [0, "oH"], "\xe4" => [0, "oI"], "\xe5" => [0, "oJ"], "\xe6" => [0, "oK"], "\xe7" => [0, "oL"], "\xe8" => [0, "oM"], "\xe9" => [0, "oN"], "\xea" => [0, "oO"], "\xeb" => [0, "oP"], "\xec" => [0, "oQ"], "\xed" => [0, "oR"], "\xee" => [0, "oS"], "\xef" => [0, "oT"], "\xf0" => [0, "oU"], "\xf1" => [0, "oV"], "\xf2" => [0, "oW"], "\xf3" => [0, "oY"], "\xf4" => [0, "oj"], "\xf5" => [0, "ok"], "\xf6" => [0, "oq"], "\xf7" => [0, "ov"], "\xf8" => [0, "ow"], "\xf9" => [0, "ox"], "\xfa" => [0, "oy"], "\xfb" => [0, "oz"], "\xfc" => [82, "o"], "\xfd" => [87, "o"], "\xfe" => [130, "o"], "\xff" => [9, "o"]], ["\x00" => [94, "j0"], "\x01" => [76, "j0"], "\x02" => [104, "j0"], "\x03" => [16, "j0"], "\x04" => [94, "j1"], "\x05" => [76, "j1"], "\x06" => [104, "j1"], "\x07" => [16, "j1"], "\x08" => [94, "j2"], "\t" => [76, "j2"], "\n" => [104, "j2"], "\v" => [16, "j2"], "\f" => [94, "ja"], "\r" => [76, "ja"], "\x0e" => [104, "ja"], "\x0f" => [16, "ja"], "\x10" => [94, "jc"], "\x11" => [76, "jc"], "\x12" => [104, "jc"], "\x13" => [16, "jc"], "\x14" => [94, "je"], "\x15" => [76, "je"], "\x16" => [104, "je"], "\x17" => [16, "je"], "\x18" => [94, "ji"], "\x19" => [76, "ji"], "\x1a" => [104, "ji"], "\x1b" => [16, "ji"], "\x1c" => [94, "jo"], "\x1d" => [76, "jo"], "\x1e" => [104, "jo"], "\x1f" => [16, "jo"], " " => [94, "js"], "!" => [76, "js"], "\"" => [104, "js"], "#" => [16, "js"], "\$" => [94, "jt"], "%" => [76, "jt"], "&" => [104, "jt"], "'" => [16, "jt"], "(" => [77, "j "], ")" => [18, "j "], "*" => [77, "j%"], "+" => [18, "j%"], "," => [77, "j-"], "-" => [18, "j-"], "." => [77, "j."], "/" => [18, "j."], [77, "j/"], [18, "j/"], [77, "j3"], [18, "j3"], [77, "j4"], [18, "j4"], [77, "j5"], [18, "j5"], [77, "j6"], [18, "j6"], ":" => [77, "j7"], ";" => [18, "j7"], "<" => [77, "j8"], "=" => [18, "j8"], ">" => [77, "j9"], "?" => [18, "j9"], "@" => [77, "j="], "A" => [18, "j="], "B" => [77, "jA"], "C" => [18, "jA"], "D" => [77, "j_"], "E" => [18, "j_"], "F" => [77, "jb"], "G" => [18, "jb"], "H" => [77, "jd"], "I" => [18, "jd"], "J" => [77, "jf"], "K" => [18, "jf"], "L" => [77, "jg"], "M" => [18, "jg"], "N" => [77, "jh"], "O" => [18, "jh"], "P" => [77, "jl"], "Q" => [18, "jl"], "R" => [77, "jm"], "S" => [18, "jm"], "T" => [77, "jn"], "U" => [18, "jn"], "V" => [77, "jp"], "W" => [18, "jp"], "X" => [77, "jr"], "Y" => [18, "jr"], "Z" => [77, "ju"], "[" => [18, "ju"], "\\" => [0, "j:"], "]" => [0, "jB"], "^" => [0, "jC"], "_" => [0, "jD"], "`" => [0, "jE"], "a" => [0, "jF"], "b" => [0, "jG"], "c" => [0, "jH"], "d" => [0, "jI"], "e" => [0, "jJ"], "f" => [0, "jK"], "g" => [0, "jL"], "h" => [0, "jM"], "i" => [0, "jN"], "j" => [0, "jO"], "k" => [0, "jP"], "l" => [0, "jQ"], "m" => [0, "jR"], "n" => [0, "jS"], "o" => [0, "jT"], "p" => [0, "jU"], "q" => [0, "jV"], "r" => [0, "jW"], "s" => [0, "jY"], "t" => [0, "jj"], "u" => [0, "jk"], "v" => [0, "jq"], "w" => [0, "jv"], "x" => [0, "jw"], "y" => [0, "jx"], "z" => [0, "jy"], "{" => [0, "jz"], "|" => [82, "j"], "}" => [87, "j"], "~" => [130, "j"], "" => [9, "j"], "\x80" => [94, "k0"], "\x81" => [76, "k0"], "\x82" => [104, "k0"], "\x83" => [16, "k0"], "\x84" => [94, "k1"], "\x85" => [76, "k1"], "\x86" => [104, "k1"], "\x87" => [16, "k1"], "\x88" => [94, "k2"], "\x89" => [76, "k2"], "\x8a" => [104, "k2"], "\x8b" => [16, "k2"], "\x8c" => [94, "ka"], "\x8d" => [76, "ka"], "\x8e" => [104, "ka"], "\x8f" => [16, "ka"], "\x90" => [94, "kc"], "\x91" => [76, "kc"], "\x92" => [104, "kc"], "\x93" => [16, "kc"], "\x94" => [94, "ke"], "\x95" => [76, "ke"], "\x96" => [104, "ke"], "\x97" => [16, "ke"], "\x98" => [94, "ki"], "\x99" => [76, "ki"], "\x9a" => [104, "ki"], "\x9b" => [16, "ki"], "\x9c" => [94, "ko"], "\x9d" => [76, "ko"], "\x9e" => [104, "ko"], "\x9f" => [16, "ko"], "\xa0" => [94, "ks"], "\xa1" => [76, "ks"], "\xa2" => [104, "ks"], "\xa3" => [16, "ks"], "\xa4" => [94, "kt"], "\xa5" => [76, "kt"], "\xa6" => [104, "kt"], "\xa7" => [16, "kt"], "\xa8" => [77, "k "], "\xa9" => [18, "k "], "\xaa" => [77, "k%"], "\xab" => [18, "k%"], "\xac" => [77, "k-"], "\xad" => [18, "k-"], "\xae" => [77, "k."], "\xaf" => [18, "k."], "\xb0" => [77, "k/"], "\xb1" => [18, "k/"], "\xb2" => [77, "k3"], "\xb3" => [18, "k3"], "\xb4" => [77, "k4"], "\xb5" => [18, "k4"], "\xb6" => [77, "k5"], "\xb7" => [18, "k5"], "\xb8" => [77, "k6"], "\xb9" => [18, "k6"], "\xba" => [77, "k7"], "\xbb" => [18, "k7"], "\xbc" => [77, "k8"], "\xbd" => [18, "k8"], "\xbe" => [77, "k9"], "\xbf" => [18, "k9"], "\xc0" => [77, "k="], "\xc1" => [18, "k="], "\xc2" => [77, "kA"], "\xc3" => [18, "kA"], "\xc4" => [77, "k_"], "\xc5" => [18, "k_"], "\xc6" => [77, "kb"], "\xc7" => [18, "kb"], "\xc8" => [77, "kd"], "\xc9" => [18, "kd"], "\xca" => [77, "kf"], "\xcb" => [18, "kf"], "\xcc" => [77, "kg"], "\xcd" => [18, "kg"], "\xce" => [77, "kh"], "\xcf" => [18, "kh"], "\xd0" => [77, "kl"], "\xd1" => [18, "kl"], "\xd2" => [77, "km"], "\xd3" => [18, "km"], "\xd4" => [77, "kn"], "\xd5" => [18, "kn"], "\xd6" => [77, "kp"], "\xd7" => [18, "kp"], "\xd8" => [77, "kr"], "\xd9" => [18, "kr"], "\xda" => [77, "ku"], "\xdb" => [18, "ku"], "\xdc" => [0, "k:"], "\xdd" => [0, "kB"], "\xde" => [0, "kC"], "\xdf" => [0, "kD"], "\xe0" => [0, "kE"], "\xe1" => [0, "kF"], "\xe2" => [0, "kG"], "\xe3" => [0, "kH"], "\xe4" => [0, "kI"], "\xe5" => [0, "kJ"], "\xe6" => [0, "kK"], "\xe7" => [0, "kL"], "\xe8" => [0, "kM"], "\xe9" => [0, "kN"], "\xea" => [0, "kO"], "\xeb" => [0, "kP"], "\xec" => [0, "kQ"], "\xed" => [0, "kR"], "\xee" => [0, "kS"], "\xef" => [0, "kT"], "\xf0" => [0, "kU"], "\xf1" => [0, "kV"], "\xf2" => [0, "kW"], "\xf3" => [0, "kY"], "\xf4" => [0, "kj"], "\xf5" => [0, "kk"], "\xf6" => [0, "kq"], "\xf7" => [0, "kv"], "\xf8" => [0, "kw"], "\xf9" => [0, "kx"], "\xfa" => [0, "ky"], "\xfb" => [0, "kz"], "\xfc" => [82, "k"], "\xfd" => [87, "k"], "\xfe" => [130, "k"], "\xff" => [9, "k"]], ["\x00" => [77, "j0"], "\x01" => [18, "j0"], "\x02" => [77, "j1"], "\x03" => [18, "j1"], "\x04" => [77, "j2"], "\x05" => [18, "j2"], "\x06" => [77, "ja"], "\x07" => [18, "ja"], "\x08" => [77, "jc"], "\t" => [18, "jc"], "\n" => [77, "je"], "\v" => [18, "je"], "\f" => [77, "ji"], "\r" => [18, "ji"], "\x0e" => [77, "jo"], "\x0f" => [18, "jo"], "\x10" => [77, "js"], "\x11" => [18, "js"], "\x12" => [77, "jt"], "\x13" => [18, "jt"], "\x14" => [0, "j "], "\x15" => [0, "j%"], "\x16" => [0, "j-"], "\x17" => [0, "j."], "\x18" => [0, "j/"], "\x19" => [0, "j3"], "\x1a" => [0, "j4"], "\x1b" => [0, "j5"], "\x1c" => [0, "j6"], "\x1d" => [0, "j7"], "\x1e" => [0, "j8"], "\x1f" => [0, "j9"], " " => [0, "j="], "!" => [0, "jA"], "\"" => [0, "j_"], "#" => [0, "jb"], "\$" => [0, "jd"], "%" => [0, "jf"], "&" => [0, "jg"], "'" => [0, "jh"], "(" => [0, "jl"], ")" => [0, "jm"], "*" => [0, "jn"], "+" => [0, "jp"], "," => [0, "jr"], "-" => [0, "ju"], "." => [100, "j"], "/" => [110, "j"], [111, "j"], [115, "j"], [116, "j"], [118, "j"], [119, "j"], [122, "j"], [123, "j"], [125, "j"], [126, "j"], [129, "j"], ":" => [143, "j"], ";" => [148, "j"], "<" => [151, "j"], "=" => [153, "j"], ">" => [83, "j"], "?" => [10, "j"], "@" => [77, "k0"], "A" => [18, "k0"], "B" => [77, "k1"], "C" => [18, "k1"], "D" => [77, "k2"], "E" => [18, "k2"], "F" => [77, "ka"], "G" => [18, "ka"], "H" => [77, "kc"], "I" => [18, "kc"], "J" => [77, "ke"], "K" => [18, "ke"], "L" => [77, "ki"], "M" => [18, "ki"], "N" => [77, "ko"], "O" => [18, "ko"], "P" => [77, "ks"], "Q" => [18, "ks"], "R" => [77, "kt"], "S" => [18, "kt"], "T" => [0, "k "], "U" => [0, "k%"], "V" => [0, "k-"], "W" => [0, "k."], "X" => [0, "k/"], "Y" => [0, "k3"], "Z" => [0, "k4"], "[" => [0, "k5"], "\\" => [0, "k6"], "]" => [0, "k7"], "^" => [0, "k8"], "_" => [0, "k9"], "`" => [0, "k="], "a" => [0, "kA"], "b" => [0, "k_"], "c" => [0, "kb"], "d" => [0, "kd"], "e" => [0, "kf"], "f" => [0, "kg"], "g" => [0, "kh"], "h" => [0, "kl"], "i" => [0, "km"], "j" => [0, "kn"], "k" => [0, "kp"], "l" => [0, "kr"], "m" => [0, "ku"], "n" => [100, "k"], "o" => [110, "k"], "p" => [111, "k"], "q" => [115, "k"], "r" => [116, "k"], "s" => [118, "k"], "t" => [119, "k"], "u" => [122, "k"], "v" => [123, "k"], "w" => [125, "k"], "x" => [126, "k"], "y" => [129, "k"], "z" => [143, "k"], "{" => [148, "k"], "|" => [151, "k"], "}" => [153, "k"], "~" => [83, "k"], "" => [10, "k"], "\x80" => [77, "q0"], "\x81" => [18, "q0"], "\x82" => [77, "q1"], "\x83" => [18, "q1"], "\x84" => [77, "q2"], "\x85" => [18, "q2"], "\x86" => [77, "qa"], "\x87" => [18, "qa"], "\x88" => [77, "qc"], "\x89" => [18, "qc"], "\x8a" => [77, "qe"], "\x8b" => [18, "qe"], "\x8c" => [77, "qi"], "\x8d" => [18, "qi"], "\x8e" => [77, "qo"], "\x8f" => [18, "qo"], "\x90" => [77, "qs"], "\x91" => [18, "qs"], "\x92" => [77, "qt"], "\x93" => [18, "qt"], "\x94" => [0, "q "], "\x95" => [0, "q%"], "\x96" => [0, "q-"], "\x97" => [0, "q."], "\x98" => [0, "q/"], "\x99" => [0, "q3"], "\x9a" => [0, "q4"], "\x9b" => [0, "q5"], "\x9c" => [0, "q6"], "\x9d" => [0, "q7"], "\x9e" => [0, "q8"], "\x9f" => [0, "q9"], "\xa0" => [0, "q="], "\xa1" => [0, "qA"], "\xa2" => [0, "q_"], "\xa3" => [0, "qb"], "\xa4" => [0, "qd"], "\xa5" => [0, "qf"], "\xa6" => [0, "qg"], "\xa7" => [0, "qh"], "\xa8" => [0, "ql"], "\xa9" => [0, "qm"], "\xaa" => [0, "qn"], "\xab" => [0, "qp"], "\xac" => [0, "qr"], "\xad" => [0, "qu"], "\xae" => [100, "q"], "\xaf" => [110, "q"], "\xb0" => [111, "q"], "\xb1" => [115, "q"], "\xb2" => [116, "q"], "\xb3" => [118, "q"], "\xb4" => [119, "q"], "\xb5" => [122, "q"], "\xb6" => [123, "q"], "\xb7" => [125, "q"], "\xb8" => [126, "q"], "\xb9" => [129, "q"], "\xba" => [143, "q"], "\xbb" => [148, "q"], "\xbc" => [151, "q"], "\xbd" => [153, "q"], "\xbe" => [83, "q"], "\xbf" => [10, "q"], "\xc0" => [77, "v0"], "\xc1" => [18, "v0"], "\xc2" => [77, "v1"], "\xc3" => [18, "v1"], "\xc4" => [77, "v2"], "\xc5" => [18, "v2"], "\xc6" => [77, "va"], "\xc7" => [18, "va"], "\xc8" => [77, "vc"], "\xc9" => [18, "vc"], "\xca" => [77, "ve"], "\xcb" => [18, "ve"], "\xcc" => [77, "vi"], "\xcd" => [18, "vi"], "\xce" => [77, "vo"], "\xcf" => [18, "vo"], "\xd0" => [77, "vs"], "\xd1" => [18, "vs"], "\xd2" => [77, "vt"], "\xd3" => [18, "vt"], "\xd4" => [0, "v "], "\xd5" => [0, "v%"], "\xd6" => [0, "v-"], "\xd7" => [0, "v."], "\xd8" => [0, "v/"], "\xd9" => [0, "v3"], "\xda" => [0, "v4"], "\xdb" => [0, "v5"], "\xdc" => [0, "v6"], "\xdd" => [0, "v7"], "\xde" => [0, "v8"], "\xdf" => [0, "v9"], "\xe0" => [0, "v="], "\xe1" => [0, "vA"], "\xe2" => [0, "v_"], "\xe3" => [0, "vb"], "\xe4" => [0, "vd"], "\xe5" => [0, "vf"], "\xe6" => [0, "vg"], "\xe7" => [0, "vh"], "\xe8" => [0, "vl"], "\xe9" => [0, "vm"], "\xea" => [0, "vn"], "\xeb" => [0, "vp"], "\xec" => [0, "vr"], "\xed" => [0, "vu"], "\xee" => [100, "v"], "\xef" => [110, "v"], "\xf0" => [111, "v"], "\xf1" => [115, "v"], "\xf2" => [116, "v"], "\xf3" => [118, "v"], "\xf4" => [119, "v"], "\xf5" => [122, "v"], "\xf6" => [123, "v"], "\xf7" => [125, "v"], "\xf8" => [126, "v"], "\xf9" => [129, "v"], "\xfa" => [143, "v"], "\xfb" => [148, "v"], "\xfc" => [151, "v"], "\xfd" => [153, "v"], "\xfe" => [83, "v"], "\xff" => [10, "v"]], ["\x00" => [94, "l0"], "\x01" => [76, "l0"], "\x02" => [104, "l0"], "\x03" => [16, "l0"], "\x04" => [94, "l1"], "\x05" => [76, "l1"], "\x06" => [104, "l1"], "\x07" => [16, "l1"], "\x08" => [94, "l2"], "\t" => [76, "l2"], "\n" => [104, "l2"], "\v" => [16, "l2"], "\f" => [94, "la"], "\r" => [76, "la"], "\x0e" => [104, "la"], "\x0f" => [16, "la"], "\x10" => [94, "lc"], "\x11" => [76, "lc"], "\x12" => [104, "lc"], "\x13" => [16, "lc"], "\x14" => [94, "le"], "\x15" => [76, "le"], "\x16" => [104, "le"], "\x17" => [16, "le"], "\x18" => [94, "li"], "\x19" => [76, "li"], "\x1a" => [104, "li"], "\x1b" => [16, "li"], "\x1c" => [94, "lo"], "\x1d" => [76, "lo"], "\x1e" => [104, "lo"], "\x1f" => [16, "lo"], " " => [94, "ls"], "!" => [76, "ls"], "\"" => [104, "ls"], "#" => [16, "ls"], "\$" => [94, "lt"], "%" => [76, "lt"], "&" => [104, "lt"], "'" => [16, "lt"], "(" => [77, "l "], ")" => [18, "l "], "*" => [77, "l%"], "+" => [18, "l%"], "," => [77, "l-"], "-" => [18, "l-"], "." => [77, "l."], "/" => [18, "l."], [77, "l/"], [18, "l/"], [77, "l3"], [18, "l3"], [77, "l4"], [18, "l4"], [77, "l5"], [18, "l5"], [77, "l6"], [18, "l6"], ":" => [77, "l7"], ";" => [18, "l7"], "<" => [77, "l8"], "=" => [18, "l8"], ">" => [77, "l9"], "?" => [18, "l9"], "@" => [77, "l="], "A" => [18, "l="], "B" => [77, "lA"], "C" => [18, "lA"], "D" => [77, "l_"], "E" => [18, "l_"], "F" => [77, "lb"], "G" => [18, "lb"], "H" => [77, "ld"], "I" => [18, "ld"], "J" => [77, "lf"], "K" => [18, "lf"], "L" => [77, "lg"], "M" => [18, "lg"], "N" => [77, "lh"], "O" => [18, "lh"], "P" => [77, "ll"], "Q" => [18, "ll"], "R" => [77, "lm"], "S" => [18, "lm"], "T" => [77, "ln"], "U" => [18, "ln"], "V" => [77, "lp"], "W" => [18, "lp"], "X" => [77, "lr"], "Y" => [18, "lr"], "Z" => [77, "lu"], "[" => [18, "lu"], "\\" => [0, "l:"], "]" => [0, "lB"], "^" => [0, "lC"], "_" => [0, "lD"], "`" => [0, "lE"], "a" => [0, "lF"], "b" => [0, "lG"], "c" => [0, "lH"], "d" => [0, "lI"], "e" => [0, "lJ"], "f" => [0, "lK"], "g" => [0, "lL"], "h" => [0, "lM"], "i" => [0, "lN"], "j" => [0, "lO"], "k" => [0, "lP"], "l" => [0, "lQ"], "m" => [0, "lR"], "n" => [0, "lS"], "o" => [0, "lT"], "p" => [0, "lU"], "q" => [0, "lV"], "r" => [0, "lW"], "s" => [0, "lY"], "t" => [0, "lj"], "u" => [0, "lk"], "v" => [0, "lq"], "w" => [0, "lv"], "x" => [0, "lw"], "y" => [0, "lx"], "z" => [0, "ly"], "{" => [0, "lz"], "|" => [82, "l"], "}" => [87, "l"], "~" => [130, "l"], "" => [9, "l"], "\x80" => [94, "m0"], "\x81" => [76, "m0"], "\x82" => [104, "m0"], "\x83" => [16, "m0"], "\x84" => [94, "m1"], "\x85" => [76, "m1"], "\x86" => [104, "m1"], "\x87" => [16, "m1"], "\x88" => [94, "m2"], "\x89" => [76, "m2"], "\x8a" => [104, "m2"], "\x8b" => [16, "m2"], "\x8c" => [94, "ma"], "\x8d" => [76, "ma"], "\x8e" => [104, "ma"], "\x8f" => [16, "ma"], "\x90" => [94, "mc"], "\x91" => [76, "mc"], "\x92" => [104, "mc"], "\x93" => [16, "mc"], "\x94" => [94, "me"], "\x95" => [76, "me"], "\x96" => [104, "me"], "\x97" => [16, "me"], "\x98" => [94, "mi"], "\x99" => [76, "mi"], "\x9a" => [104, "mi"], "\x9b" => [16, "mi"], "\x9c" => [94, "mo"], "\x9d" => [76, "mo"], "\x9e" => [104, "mo"], "\x9f" => [16, "mo"], "\xa0" => [94, "ms"], "\xa1" => [76, "ms"], "\xa2" => [104, "ms"], "\xa3" => [16, "ms"], "\xa4" => [94, "mt"], "\xa5" => [76, "mt"], "\xa6" => [104, "mt"], "\xa7" => [16, "mt"], "\xa8" => [77, "m "], "\xa9" => [18, "m "], "\xaa" => [77, "m%"], "\xab" => [18, "m%"], "\xac" => [77, "m-"], "\xad" => [18, "m-"], "\xae" => [77, "m."], "\xaf" => [18, "m."], "\xb0" => [77, "m/"], "\xb1" => [18, "m/"], "\xb2" => [77, "m3"], "\xb3" => [18, "m3"], "\xb4" => [77, "m4"], "\xb5" => [18, "m4"], "\xb6" => [77, "m5"], "\xb7" => [18, "m5"], "\xb8" => [77, "m6"], "\xb9" => [18, "m6"], "\xba" => [77, "m7"], "\xbb" => [18, "m7"], "\xbc" => [77, "m8"], "\xbd" => [18, "m8"], "\xbe" => [77, "m9"], "\xbf" => [18, "m9"], "\xc0" => [77, "m="], "\xc1" => [18, "m="], "\xc2" => [77, "mA"], "\xc3" => [18, "mA"], "\xc4" => [77, "m_"], "\xc5" => [18, "m_"], "\xc6" => [77, "mb"], "\xc7" => [18, "mb"], "\xc8" => [77, "md"], "\xc9" => [18, "md"], "\xca" => [77, "mf"], "\xcb" => [18, "mf"], "\xcc" => [77, "mg"], "\xcd" => [18, "mg"], "\xce" => [77, "mh"], "\xcf" => [18, "mh"], "\xd0" => [77, "ml"], "\xd1" => [18, "ml"], "\xd2" => [77, "mm"], "\xd3" => [18, "mm"], "\xd4" => [77, "mn"], "\xd5" => [18, "mn"], "\xd6" => [77, "mp"], "\xd7" => [18, "mp"], "\xd8" => [77, "mr"], "\xd9" => [18, "mr"], "\xda" => [77, "mu"], "\xdb" => [18, "mu"], "\xdc" => [0, "m:"], "\xdd" => [0, "mB"], "\xde" => [0, "mC"], "\xdf" => [0, "mD"], "\xe0" => [0, "mE"], "\xe1" => [0, "mF"], "\xe2" => [0, "mG"], "\xe3" => [0, "mH"], "\xe4" => [0, "mI"], "\xe5" => [0, "mJ"], "\xe6" => [0, "mK"], "\xe7" => [0, "mL"], "\xe8" => [0, "mM"], "\xe9" => [0, "mN"], "\xea" => [0, "mO"], "\xeb" => [0, "mP"], "\xec" => [0, "mQ"], "\xed" => [0, "mR"], "\xee" => [0, "mS"], "\xef" => [0, "mT"], "\xf0" => [0, "mU"], "\xf1" => [0, "mV"], "\xf2" => [0, "mW"], "\xf3" => [0, "mY"], "\xf4" => [0, "mj"], "\xf5" => [0, "mk"], "\xf6" => [0, "mq"], "\xf7" => [0, "mv"], "\xf8" => [0, "mw"], "\xf9" => [0, "mx"], "\xfa" => [0, "my"], "\xfb" => [0, "mz"], "\xfc" => [82, "m"], "\xfd" => [87, "m"], "\xfe" => [130, "m"], "\xff" => [9, "m"]], ["\x00" => [77, "l0"], "\x01" => [18, "l0"], "\x02" => [77, "l1"], "\x03" => [18, "l1"], "\x04" => [77, "l2"], "\x05" => [18, "l2"], "\x06" => [77, "la"], "\x07" => [18, "la"], "\x08" => [77, "lc"], "\t" => [18, "lc"], "\n" => [77, "le"], "\v" => [18, "le"], "\f" => [77, "li"], "\r" => [18, "li"], "\x0e" => [77, "lo"], "\x0f" => [18, "lo"], "\x10" => [77, "ls"], "\x11" => [18, "ls"], "\x12" => [77, "lt"], "\x13" => [18, "lt"], "\x14" => [0, "l "], "\x15" => [0, "l%"], "\x16" => [0, "l-"], "\x17" => [0, "l."], "\x18" => [0, "l/"], "\x19" => [0, "l3"], "\x1a" => [0, "l4"], "\x1b" => [0, "l5"], "\x1c" => [0, "l6"], "\x1d" => [0, "l7"], "\x1e" => [0, "l8"], "\x1f" => [0, "l9"], " " => [0, "l="], "!" => [0, "lA"], "\"" => [0, "l_"], "#" => [0, "lb"], "\$" => [0, "ld"], "%" => [0, "lf"], "&" => [0, "lg"], "'" => [0, "lh"], "(" => [0, "ll"], ")" => [0, "lm"], "*" => [0, "ln"], "+" => [0, "lp"], "," => [0, "lr"], "-" => [0, "lu"], "." => [100, "l"], "/" => [110, "l"], [111, "l"], [115, "l"], [116, "l"], [118, "l"], [119, "l"], [122, "l"], [123, "l"], [125, "l"], [126, "l"], [129, "l"], ":" => [143, "l"], ";" => [148, "l"], "<" => [151, "l"], "=" => [153, "l"], ">" => [83, "l"], "?" => [10, "l"], "@" => [77, "m0"], "A" => [18, "m0"], "B" => [77, "m1"], "C" => [18, "m1"], "D" => [77, "m2"], "E" => [18, "m2"], "F" => [77, "ma"], "G" => [18, "ma"], "H" => [77, "mc"], "I" => [18, "mc"], "J" => [77, "me"], "K" => [18, "me"], "L" => [77, "mi"], "M" => [18, "mi"], "N" => [77, "mo"], "O" => [18, "mo"], "P" => [77, "ms"], "Q" => [18, "ms"], "R" => [77, "mt"], "S" => [18, "mt"], "T" => [0, "m "], "U" => [0, "m%"], "V" => [0, "m-"], "W" => [0, "m."], "X" => [0, "m/"], "Y" => [0, "m3"], "Z" => [0, "m4"], "[" => [0, "m5"], "\\" => [0, "m6"], "]" => [0, "m7"], "^" => [0, "m8"], "_" => [0, "m9"], "`" => [0, "m="], "a" => [0, "mA"], "b" => [0, "m_"], "c" => [0, "mb"], "d" => [0, "md"], "e" => [0, "mf"], "f" => [0, "mg"], "g" => [0, "mh"], "h" => [0, "ml"], "i" => [0, "mm"], "j" => [0, "mn"], "k" => [0, "mp"], "l" => [0, "mr"], "m" => [0, "mu"], "n" => [100, "m"], "o" => [110, "m"], "p" => [111, "m"], "q" => [115, "m"], "r" => [116, "m"], "s" => [118, "m"], "t" => [119, "m"], "u" => [122, "m"], "v" => [123, "m"], "w" => [125, "m"], "x" => [126, "m"], "y" => [129, "m"], "z" => [143, "m"], "{" => [148, "m"], "|" => [151, "m"], "}" => [153, "m"], "~" => [83, "m"], "" => [10, "m"], "\x80" => [77, "n0"], "\x81" => [18, "n0"], "\x82" => [77, "n1"], "\x83" => [18, "n1"], "\x84" => [77, "n2"], "\x85" => [18, "n2"], "\x86" => [77, "na"], "\x87" => [18, "na"], "\x88" => [77, "nc"], "\x89" => [18, "nc"], "\x8a" => [77, "ne"], "\x8b" => [18, "ne"], "\x8c" => [77, "ni"], "\x8d" => [18, "ni"], "\x8e" => [77, "no"], "\x8f" => [18, "no"], "\x90" => [77, "ns"], "\x91" => [18, "ns"], "\x92" => [77, "nt"], "\x93" => [18, "nt"], "\x94" => [0, "n "], "\x95" => [0, "n%"], "\x96" => [0, "n-"], "\x97" => [0, "n."], "\x98" => [0, "n/"], "\x99" => [0, "n3"], "\x9a" => [0, "n4"], "\x9b" => [0, "n5"], "\x9c" => [0, "n6"], "\x9d" => [0, "n7"], "\x9e" => [0, "n8"], "\x9f" => [0, "n9"], "\xa0" => [0, "n="], "\xa1" => [0, "nA"], "\xa2" => [0, "n_"], "\xa3" => [0, "nb"], "\xa4" => [0, "nd"], "\xa5" => [0, "nf"], "\xa6" => [0, "ng"], "\xa7" => [0, "nh"], "\xa8" => [0, "nl"], "\xa9" => [0, "nm"], "\xaa" => [0, "nn"], "\xab" => [0, "np"], "\xac" => [0, "nr"], "\xad" => [0, "nu"], "\xae" => [100, "n"], "\xaf" => [110, "n"], "\xb0" => [111, "n"], "\xb1" => [115, "n"], "\xb2" => [116, "n"], "\xb3" => [118, "n"], "\xb4" => [119, "n"], "\xb5" => [122, "n"], "\xb6" => [123, "n"], "\xb7" => [125, "n"], "\xb8" => [126, "n"], "\xb9" => [129, "n"], "\xba" => [143, "n"], "\xbb" => [148, "n"], "\xbc" => [151, "n"], "\xbd" => [153, "n"], "\xbe" => [83, "n"], "\xbf" => [10, "n"], "\xc0" => [77, "p0"], "\xc1" => [18, "p0"], "\xc2" => [77, "p1"], "\xc3" => [18, "p1"], "\xc4" => [77, "p2"], "\xc5" => [18, "p2"], "\xc6" => [77, "pa"], "\xc7" => [18, "pa"], "\xc8" => [77, "pc"], "\xc9" => [18, "pc"], "\xca" => [77, "pe"], "\xcb" => [18, "pe"], "\xcc" => [77, "pi"], "\xcd" => [18, "pi"], "\xce" => [77, "po"], "\xcf" => [18, "po"], "\xd0" => [77, "ps"], "\xd1" => [18, "ps"], "\xd2" => [77, "pt"], "\xd3" => [18, "pt"], "\xd4" => [0, "p "], "\xd5" => [0, "p%"], "\xd6" => [0, "p-"], "\xd7" => [0, "p."], "\xd8" => [0, "p/"], "\xd9" => [0, "p3"], "\xda" => [0, "p4"], "\xdb" => [0, "p5"], "\xdc" => [0, "p6"], "\xdd" => [0, "p7"], "\xde" => [0, "p8"], "\xdf" => [0, "p9"], "\xe0" => [0, "p="], "\xe1" => [0, "pA"], "\xe2" => [0, "p_"], "\xe3" => [0, "pb"], "\xe4" => [0, "pd"], "\xe5" => [0, "pf"], "\xe6" => [0, "pg"], "\xe7" => [0, "ph"], "\xe8" => [0, "pl"], "\xe9" => [0, "pm"], "\xea" => [0, "pn"], "\xeb" => [0, "pp"], "\xec" => [0, "pr"], "\xed" => [0, "pu"], "\xee" => [100, "p"], "\xef" => [110, "p"], "\xf0" => [111, "p"], "\xf1" => [115, "p"], "\xf2" => [116, "p"], "\xf3" => [118, "p"], "\xf4" => [119, "p"], "\xf5" => [122, "p"], "\xf6" => [123, "p"], "\xf7" => [125, "p"], "\xf8" => [126, "p"], "\xf9" => [129, "p"], "\xfa" => [143, "p"], "\xfb" => [148, "p"], "\xfc" => [151, "p"], "\xfd" => [153, "p"], "\xfe" => [83, "p"], "\xff" => [10, "p"]], ["\x00" => [94, "n0"], "\x01" => [76, "n0"], "\x02" => [104, "n0"], "\x03" => [16, "n0"], "\x04" => [94, "n1"], "\x05" => [76, "n1"], "\x06" => [104, "n1"], "\x07" => [16, "n1"], "\x08" => [94, "n2"], "\t" => [76, "n2"], "\n" => [104, "n2"], "\v" => [16, "n2"], "\f" => [94, "na"], "\r" => [76, "na"], "\x0e" => [104, "na"], "\x0f" => [16, "na"], "\x10" => [94, "nc"], "\x11" => [76, "nc"], "\x12" => [104, "nc"], "\x13" => [16, "nc"], "\x14" => [94, "ne"], "\x15" => [76, "ne"], "\x16" => [104, "ne"], "\x17" => [16, "ne"], "\x18" => [94, "ni"], "\x19" => [76, "ni"], "\x1a" => [104, "ni"], "\x1b" => [16, "ni"], "\x1c" => [94, "no"], "\x1d" => [76, "no"], "\x1e" => [104, "no"], "\x1f" => [16, "no"], " " => [94, "ns"], "!" => [76, "ns"], "\"" => [104, "ns"], "#" => [16, "ns"], "\$" => [94, "nt"], "%" => [76, "nt"], "&" => [104, "nt"], "'" => [16, "nt"], "(" => [77, "n "], ")" => [18, "n "], "*" => [77, "n%"], "+" => [18, "n%"], "," => [77, "n-"], "-" => [18, "n-"], "." => [77, "n."], "/" => [18, "n."], [77, "n/"], [18, "n/"], [77, "n3"], [18, "n3"], [77, "n4"], [18, "n4"], [77, "n5"], [18, "n5"], [77, "n6"], [18, "n6"], ":" => [77, "n7"], ";" => [18, "n7"], "<" => [77, "n8"], "=" => [18, "n8"], ">" => [77, "n9"], "?" => [18, "n9"], "@" => [77, "n="], "A" => [18, "n="], "B" => [77, "nA"], "C" => [18, "nA"], "D" => [77, "n_"], "E" => [18, "n_"], "F" => [77, "nb"], "G" => [18, "nb"], "H" => [77, "nd"], "I" => [18, "nd"], "J" => [77, "nf"], "K" => [18, "nf"], "L" => [77, "ng"], "M" => [18, "ng"], "N" => [77, "nh"], "O" => [18, "nh"], "P" => [77, "nl"], "Q" => [18, "nl"], "R" => [77, "nm"], "S" => [18, "nm"], "T" => [77, "nn"], "U" => [18, "nn"], "V" => [77, "np"], "W" => [18, "np"], "X" => [77, "nr"], "Y" => [18, "nr"], "Z" => [77, "nu"], "[" => [18, "nu"], "\\" => [0, "n:"], "]" => [0, "nB"], "^" => [0, "nC"], "_" => [0, "nD"], "`" => [0, "nE"], "a" => [0, "nF"], "b" => [0, "nG"], "c" => [0, "nH"], "d" => [0, "nI"], "e" => [0, "nJ"], "f" => [0, "nK"], "g" => [0, "nL"], "h" => [0, "nM"], "i" => [0, "nN"], "j" => [0, "nO"], "k" => [0, "nP"], "l" => [0, "nQ"], "m" => [0, "nR"], "n" => [0, "nS"], "o" => [0, "nT"], "p" => [0, "nU"], "q" => [0, "nV"], "r" => [0, "nW"], "s" => [0, "nY"], "t" => [0, "nj"], "u" => [0, "nk"], "v" => [0, "nq"], "w" => [0, "nv"], "x" => [0, "nw"], "y" => [0, "nx"], "z" => [0, "ny"], "{" => [0, "nz"], "|" => [82, "n"], "}" => [87, "n"], "~" => [130, "n"], "" => [9, "n"], "\x80" => [94, "p0"], "\x81" => [76, "p0"], "\x82" => [104, "p0"], "\x83" => [16, "p0"], "\x84" => [94, "p1"], "\x85" => [76, "p1"], "\x86" => [104, "p1"], "\x87" => [16, "p1"], "\x88" => [94, "p2"], "\x89" => [76, "p2"], "\x8a" => [104, "p2"], "\x8b" => [16, "p2"], "\x8c" => [94, "pa"], "\x8d" => [76, "pa"], "\x8e" => [104, "pa"], "\x8f" => [16, "pa"], "\x90" => [94, "pc"], "\x91" => [76, "pc"], "\x92" => [104, "pc"], "\x93" => [16, "pc"], "\x94" => [94, "pe"], "\x95" => [76, "pe"], "\x96" => [104, "pe"], "\x97" => [16, "pe"], "\x98" => [94, "pi"], "\x99" => [76, "pi"], "\x9a" => [104, "pi"], "\x9b" => [16, "pi"], "\x9c" => [94, "po"], "\x9d" => [76, "po"], "\x9e" => [104, "po"], "\x9f" => [16, "po"], "\xa0" => [94, "ps"], "\xa1" => [76, "ps"], "\xa2" => [104, "ps"], "\xa3" => [16, "ps"], "\xa4" => [94, "pt"], "\xa5" => [76, "pt"], "\xa6" => [104, "pt"], "\xa7" => [16, "pt"], "\xa8" => [77, "p "], "\xa9" => [18, "p "], "\xaa" => [77, "p%"], "\xab" => [18, "p%"], "\xac" => [77, "p-"], "\xad" => [18, "p-"], "\xae" => [77, "p."], "\xaf" => [18, "p."], "\xb0" => [77, "p/"], "\xb1" => [18, "p/"], "\xb2" => [77, "p3"], "\xb3" => [18, "p3"], "\xb4" => [77, "p4"], "\xb5" => [18, "p4"], "\xb6" => [77, "p5"], "\xb7" => [18, "p5"], "\xb8" => [77, "p6"], "\xb9" => [18, "p6"], "\xba" => [77, "p7"], "\xbb" => [18, "p7"], "\xbc" => [77, "p8"], "\xbd" => [18, "p8"], "\xbe" => [77, "p9"], "\xbf" => [18, "p9"], "\xc0" => [77, "p="], "\xc1" => [18, "p="], "\xc2" => [77, "pA"], "\xc3" => [18, "pA"], "\xc4" => [77, "p_"], "\xc5" => [18, "p_"], "\xc6" => [77, "pb"], "\xc7" => [18, "pb"], "\xc8" => [77, "pd"], "\xc9" => [18, "pd"], "\xca" => [77, "pf"], "\xcb" => [18, "pf"], "\xcc" => [77, "pg"], "\xcd" => [18, "pg"], "\xce" => [77, "ph"], "\xcf" => [18, "ph"], "\xd0" => [77, "pl"], "\xd1" => [18, "pl"], "\xd2" => [77, "pm"], "\xd3" => [18, "pm"], "\xd4" => [77, "pn"], "\xd5" => [18, "pn"], "\xd6" => [77, "pp"], "\xd7" => [18, "pp"], "\xd8" => [77, "pr"], "\xd9" => [18, "pr"], "\xda" => [77, "pu"], "\xdb" => [18, "pu"], "\xdc" => [0, "p:"], "\xdd" => [0, "pB"], "\xde" => [0, "pC"], "\xdf" => [0, "pD"], "\xe0" => [0, "pE"], "\xe1" => [0, "pF"], "\xe2" => [0, "pG"], "\xe3" => [0, "pH"], "\xe4" => [0, "pI"], "\xe5" => [0, "pJ"], "\xe6" => [0, "pK"], "\xe7" => [0, "pL"], "\xe8" => [0, "pM"], "\xe9" => [0, "pN"], "\xea" => [0, "pO"], "\xeb" => [0, "pP"], "\xec" => [0, "pQ"], "\xed" => [0, "pR"], "\xee" => [0, "pS"], "\xef" => [0, "pT"], "\xf0" => [0, "pU"], "\xf1" => [0, "pV"], "\xf2" => [0, "pW"], "\xf3" => [0, "pY"], "\xf4" => [0, "pj"], "\xf5" => [0, "pk"], "\xf6" => [0, "pq"], "\xf7" => [0, "pv"], "\xf8" => [0, "pw"], "\xf9" => [0, "px"], "\xfa" => [0, "py"], "\xfb" => [0, "pz"], "\xfc" => [82, "p"], "\xfd" => [87, "p"], "\xfe" => [130, "p"], "\xff" => [9, "p"]], ["\x00" => [94, "q0"], "\x01" => [76, "q0"], "\x02" => [104, "q0"], "\x03" => [16, "q0"], "\x04" => [94, "q1"], "\x05" => [76, "q1"], "\x06" => [104, "q1"], "\x07" => [16, "q1"], "\x08" => [94, "q2"], "\t" => [76, "q2"], "\n" => [104, "q2"], "\v" => [16, "q2"], "\f" => [94, "qa"], "\r" => [76, "qa"], "\x0e" => [104, "qa"], "\x0f" => [16, "qa"], "\x10" => [94, "qc"], "\x11" => [76, "qc"], "\x12" => [104, "qc"], "\x13" => [16, "qc"], "\x14" => [94, "qe"], "\x15" => [76, "qe"], "\x16" => [104, "qe"], "\x17" => [16, "qe"], "\x18" => [94, "qi"], "\x19" => [76, "qi"], "\x1a" => [104, "qi"], "\x1b" => [16, "qi"], "\x1c" => [94, "qo"], "\x1d" => [76, "qo"], "\x1e" => [104, "qo"], "\x1f" => [16, "qo"], " " => [94, "qs"], "!" => [76, "qs"], "\"" => [104, "qs"], "#" => [16, "qs"], "\$" => [94, "qt"], "%" => [76, "qt"], "&" => [104, "qt"], "'" => [16, "qt"], "(" => [77, "q "], ")" => [18, "q "], "*" => [77, "q%"], "+" => [18, "q%"], "," => [77, "q-"], "-" => [18, "q-"], "." => [77, "q."], "/" => [18, "q."], [77, "q/"], [18, "q/"], [77, "q3"], [18, "q3"], [77, "q4"], [18, "q4"], [77, "q5"], [18, "q5"], [77, "q6"], [18, "q6"], ":" => [77, "q7"], ";" => [18, "q7"], "<" => [77, "q8"], "=" => [18, "q8"], ">" => [77, "q9"], "?" => [18, "q9"], "@" => [77, "q="], "A" => [18, "q="], "B" => [77, "qA"], "C" => [18, "qA"], "D" => [77, "q_"], "E" => [18, "q_"], "F" => [77, "qb"], "G" => [18, "qb"], "H" => [77, "qd"], "I" => [18, "qd"], "J" => [77, "qf"], "K" => [18, "qf"], "L" => [77, "qg"], "M" => [18, "qg"], "N" => [77, "qh"], "O" => [18, "qh"], "P" => [77, "ql"], "Q" => [18, "ql"], "R" => [77, "qm"], "S" => [18, "qm"], "T" => [77, "qn"], "U" => [18, "qn"], "V" => [77, "qp"], "W" => [18, "qp"], "X" => [77, "qr"], "Y" => [18, "qr"], "Z" => [77, "qu"], "[" => [18, "qu"], "\\" => [0, "q:"], "]" => [0, "qB"], "^" => [0, "qC"], "_" => [0, "qD"], "`" => [0, "qE"], "a" => [0, "qF"], "b" => [0, "qG"], "c" => [0, "qH"], "d" => [0, "qI"], "e" => [0, "qJ"], "f" => [0, "qK"], "g" => [0, "qL"], "h" => [0, "qM"], "i" => [0, "qN"], "j" => [0, "qO"], "k" => [0, "qP"], "l" => [0, "qQ"], "m" => [0, "qR"], "n" => [0, "qS"], "o" => [0, "qT"], "p" => [0, "qU"], "q" => [0, "qV"], "r" => [0, "qW"], "s" => [0, "qY"], "t" => [0, "qj"], "u" => [0, "qk"], "v" => [0, "qq"], "w" => [0, "qv"], "x" => [0, "qw"], "y" => [0, "qx"], "z" => [0, "qy"], "{" => [0, "qz"], "|" => [82, "q"], "}" => [87, "q"], "~" => [130, "q"], "" => [9, "q"], "\x80" => [94, "v0"], "\x81" => [76, "v0"], "\x82" => [104, "v0"], "\x83" => [16, "v0"], "\x84" => [94, "v1"], "\x85" => [76, "v1"], "\x86" => [104, "v1"], "\x87" => [16, "v1"], "\x88" => [94, "v2"], "\x89" => [76, "v2"], "\x8a" => [104, "v2"], "\x8b" => [16, "v2"], "\x8c" => [94, "va"], "\x8d" => [76, "va"], "\x8e" => [104, "va"], "\x8f" => [16, "va"], "\x90" => [94, "vc"], "\x91" => [76, "vc"], "\x92" => [104, "vc"], "\x93" => [16, "vc"], "\x94" => [94, "ve"], "\x95" => [76, "ve"], "\x96" => [104, "ve"], "\x97" => [16, "ve"], "\x98" => [94, "vi"], "\x99" => [76, "vi"], "\x9a" => [104, "vi"], "\x9b" => [16, "vi"], "\x9c" => [94, "vo"], "\x9d" => [76, "vo"], "\x9e" => [104, "vo"], "\x9f" => [16, "vo"], "\xa0" => [94, "vs"], "\xa1" => [76, "vs"], "\xa2" => [104, "vs"], "\xa3" => [16, "vs"], "\xa4" => [94, "vt"], "\xa5" => [76, "vt"], "\xa6" => [104, "vt"], "\xa7" => [16, "vt"], "\xa8" => [77, "v "], "\xa9" => [18, "v "], "\xaa" => [77, "v%"], "\xab" => [18, "v%"], "\xac" => [77, "v-"], "\xad" => [18, "v-"], "\xae" => [77, "v."], "\xaf" => [18, "v."], "\xb0" => [77, "v/"], "\xb1" => [18, "v/"], "\xb2" => [77, "v3"], "\xb3" => [18, "v3"], "\xb4" => [77, "v4"], "\xb5" => [18, "v4"], "\xb6" => [77, "v5"], "\xb7" => [18, "v5"], "\xb8" => [77, "v6"], "\xb9" => [18, "v6"], "\xba" => [77, "v7"], "\xbb" => [18, "v7"], "\xbc" => [77, "v8"], "\xbd" => [18, "v8"], "\xbe" => [77, "v9"], "\xbf" => [18, "v9"], "\xc0" => [77, "v="], "\xc1" => [18, "v="], "\xc2" => [77, "vA"], "\xc3" => [18, "vA"], "\xc4" => [77, "v_"], "\xc5" => [18, "v_"], "\xc6" => [77, "vb"], "\xc7" => [18, "vb"], "\xc8" => [77, "vd"], "\xc9" => [18, "vd"], "\xca" => [77, "vf"], "\xcb" => [18, "vf"], "\xcc" => [77, "vg"], "\xcd" => [18, "vg"], "\xce" => [77, "vh"], "\xcf" => [18, "vh"], "\xd0" => [77, "vl"], "\xd1" => [18, "vl"], "\xd2" => [77, "vm"], "\xd3" => [18, "vm"], "\xd4" => [77, "vn"], "\xd5" => [18, "vn"], "\xd6" => [77, "vp"], "\xd7" => [18, "vp"], "\xd8" => [77, "vr"], "\xd9" => [18, "vr"], "\xda" => [77, "vu"], "\xdb" => [18, "vu"], "\xdc" => [0, "v:"], "\xdd" => [0, "vB"], "\xde" => [0, "vC"], "\xdf" => [0, "vD"], "\xe0" => [0, "vE"], "\xe1" => [0, "vF"], "\xe2" => [0, "vG"], "\xe3" => [0, "vH"], "\xe4" => [0, "vI"], "\xe5" => [0, "vJ"], "\xe6" => [0, "vK"], "\xe7" => [0, "vL"], "\xe8" => [0, "vM"], "\xe9" => [0, "vN"], "\xea" => [0, "vO"], "\xeb" => [0, "vP"], "\xec" => [0, "vQ"], "\xed" => [0, "vR"], "\xee" => [0, "vS"], "\xef" => [0, "vT"], "\xf0" => [0, "vU"], "\xf1" => [0, "vV"], "\xf2" => [0, "vW"], "\xf3" => [0, "vY"], "\xf4" => [0, "vj"], "\xf5" => [0, "vk"], "\xf6" => [0, "vq"], "\xf7" => [0, "vv"], "\xf8" => [0, "vw"], "\xf9" => [0, "vx"], "\xfa" => [0, "vy"], "\xfb" => [0, "vz"], "\xfc" => [82, "v"], "\xfd" => [87, "v"], "\xfe" => [130, "v"], "\xff" => [9, "v"]], ["\x00" => [94, "r0"], "\x01" => [76, "r0"], "\x02" => [104, "r0"], "\x03" => [16, "r0"], "\x04" => [94, "r1"], "\x05" => [76, "r1"], "\x06" => [104, "r1"], "\x07" => [16, "r1"], "\x08" => [94, "r2"], "\t" => [76, "r2"], "\n" => [104, "r2"], "\v" => [16, "r2"], "\f" => [94, "ra"], "\r" => [76, "ra"], "\x0e" => [104, "ra"], "\x0f" => [16, "ra"], "\x10" => [94, "rc"], "\x11" => [76, "rc"], "\x12" => [104, "rc"], "\x13" => [16, "rc"], "\x14" => [94, "re"], "\x15" => [76, "re"], "\x16" => [104, "re"], "\x17" => [16, "re"], "\x18" => [94, "ri"], "\x19" => [76, "ri"], "\x1a" => [104, "ri"], "\x1b" => [16, "ri"], "\x1c" => [94, "ro"], "\x1d" => [76, "ro"], "\x1e" => [104, "ro"], "\x1f" => [16, "ro"], " " => [94, "rs"], "!" => [76, "rs"], "\"" => [104, "rs"], "#" => [16, "rs"], "\$" => [94, "rt"], "%" => [76, "rt"], "&" => [104, "rt"], "'" => [16, "rt"], "(" => [77, "r "], ")" => [18, "r "], "*" => [77, "r%"], "+" => [18, "r%"], "," => [77, "r-"], "-" => [18, "r-"], "." => [77, "r."], "/" => [18, "r."], [77, "r/"], [18, "r/"], [77, "r3"], [18, "r3"], [77, "r4"], [18, "r4"], [77, "r5"], [18, "r5"], [77, "r6"], [18, "r6"], ":" => [77, "r7"], ";" => [18, "r7"], "<" => [77, "r8"], "=" => [18, "r8"], ">" => [77, "r9"], "?" => [18, "r9"], "@" => [77, "r="], "A" => [18, "r="], "B" => [77, "rA"], "C" => [18, "rA"], "D" => [77, "r_"], "E" => [18, "r_"], "F" => [77, "rb"], "G" => [18, "rb"], "H" => [77, "rd"], "I" => [18, "rd"], "J" => [77, "rf"], "K" => [18, "rf"], "L" => [77, "rg"], "M" => [18, "rg"], "N" => [77, "rh"], "O" => [18, "rh"], "P" => [77, "rl"], "Q" => [18, "rl"], "R" => [77, "rm"], "S" => [18, "rm"], "T" => [77, "rn"], "U" => [18, "rn"], "V" => [77, "rp"], "W" => [18, "rp"], "X" => [77, "rr"], "Y" => [18, "rr"], "Z" => [77, "ru"], "[" => [18, "ru"], "\\" => [0, "r:"], "]" => [0, "rB"], "^" => [0, "rC"], "_" => [0, "rD"], "`" => [0, "rE"], "a" => [0, "rF"], "b" => [0, "rG"], "c" => [0, "rH"], "d" => [0, "rI"], "e" => [0, "rJ"], "f" => [0, "rK"], "g" => [0, "rL"], "h" => [0, "rM"], "i" => [0, "rN"], "j" => [0, "rO"], "k" => [0, "rP"], "l" => [0, "rQ"], "m" => [0, "rR"], "n" => [0, "rS"], "o" => [0, "rT"], "p" => [0, "rU"], "q" => [0, "rV"], "r" => [0, "rW"], "s" => [0, "rY"], "t" => [0, "rj"], "u" => [0, "rk"], "v" => [0, "rq"], "w" => [0, "rv"], "x" => [0, "rw"], "y" => [0, "rx"], "z" => [0, "ry"], "{" => [0, "rz"], "|" => [82, "r"], "}" => [87, "r"], "~" => [130, "r"], "" => [9, "r"], "\x80" => [94, "u0"], "\x81" => [76, "u0"], "\x82" => [104, "u0"], "\x83" => [16, "u0"], "\x84" => [94, "u1"], "\x85" => [76, "u1"], "\x86" => [104, "u1"], "\x87" => [16, "u1"], "\x88" => [94, "u2"], "\x89" => [76, "u2"], "\x8a" => [104, "u2"], "\x8b" => [16, "u2"], "\x8c" => [94, "ua"], "\x8d" => [76, "ua"], "\x8e" => [104, "ua"], "\x8f" => [16, "ua"], "\x90" => [94, "uc"], "\x91" => [76, "uc"], "\x92" => [104, "uc"], "\x93" => [16, "uc"], "\x94" => [94, "ue"], "\x95" => [76, "ue"], "\x96" => [104, "ue"], "\x97" => [16, "ue"], "\x98" => [94, "ui"], "\x99" => [76, "ui"], "\x9a" => [104, "ui"], "\x9b" => [16, "ui"], "\x9c" => [94, "uo"], "\x9d" => [76, "uo"], "\x9e" => [104, "uo"], "\x9f" => [16, "uo"], "\xa0" => [94, "us"], "\xa1" => [76, "us"], "\xa2" => [104, "us"], "\xa3" => [16, "us"], "\xa4" => [94, "ut"], "\xa5" => [76, "ut"], "\xa6" => [104, "ut"], "\xa7" => [16, "ut"], "\xa8" => [77, "u "], "\xa9" => [18, "u "], "\xaa" => [77, "u%"], "\xab" => [18, "u%"], "\xac" => [77, "u-"], "\xad" => [18, "u-"], "\xae" => [77, "u."], "\xaf" => [18, "u."], "\xb0" => [77, "u/"], "\xb1" => [18, "u/"], "\xb2" => [77, "u3"], "\xb3" => [18, "u3"], "\xb4" => [77, "u4"], "\xb5" => [18, "u4"], "\xb6" => [77, "u5"], "\xb7" => [18, "u5"], "\xb8" => [77, "u6"], "\xb9" => [18, "u6"], "\xba" => [77, "u7"], "\xbb" => [18, "u7"], "\xbc" => [77, "u8"], "\xbd" => [18, "u8"], "\xbe" => [77, "u9"], "\xbf" => [18, "u9"], "\xc0" => [77, "u="], "\xc1" => [18, "u="], "\xc2" => [77, "uA"], "\xc3" => [18, "uA"], "\xc4" => [77, "u_"], "\xc5" => [18, "u_"], "\xc6" => [77, "ub"], "\xc7" => [18, "ub"], "\xc8" => [77, "ud"], "\xc9" => [18, "ud"], "\xca" => [77, "uf"], "\xcb" => [18, "uf"], "\xcc" => [77, "ug"], "\xcd" => [18, "ug"], "\xce" => [77, "uh"], "\xcf" => [18, "uh"], "\xd0" => [77, "ul"], "\xd1" => [18, "ul"], "\xd2" => [77, "um"], "\xd3" => [18, "um"], "\xd4" => [77, "un"], "\xd5" => [18, "un"], "\xd6" => [77, "up"], "\xd7" => [18, "up"], "\xd8" => [77, "ur"], "\xd9" => [18, "ur"], "\xda" => [77, "uu"], "\xdb" => [18, "uu"], "\xdc" => [0, "u:"], "\xdd" => [0, "uB"], "\xde" => [0, "uC"], "\xdf" => [0, "uD"], "\xe0" => [0, "uE"], "\xe1" => [0, "uF"], "\xe2" => [0, "uG"], "\xe3" => [0, "uH"], "\xe4" => [0, "uI"], "\xe5" => [0, "uJ"], "\xe6" => [0, "uK"], "\xe7" => [0, "uL"], "\xe8" => [0, "uM"], "\xe9" => [0, "uN"], "\xea" => [0, "uO"], "\xeb" => [0, "uP"], "\xec" => [0, "uQ"], "\xed" => [0, "uR"], "\xee" => [0, "uS"], "\xef" => [0, "uT"], "\xf0" => [0, "uU"], "\xf1" => [0, "uV"], "\xf2" => [0, "uW"], "\xf3" => [0, "uY"], "\xf4" => [0, "uj"], "\xf5" => [0, "uk"], "\xf6" => [0, "uq"], "\xf7" => [0, "uv"], "\xf8" => [0, "uw"], "\xf9" => [0, "ux"], "\xfa" => [0, "uy"], "\xfb" => [0, "uz"], "\xfc" => [82, "u"], "\xfd" => [87, "u"], "\xfe" => [130, "u"], "\xff" => [9, "u"]], ["\x00" => [94, "s0"], "\x01" => [76, "s0"], "\x02" => [104, "s0"], "\x03" => [16, "s0"], "\x04" => [94, "s1"], "\x05" => [76, "s1"], "\x06" => [104, "s1"], "\x07" => [16, "s1"], "\x08" => [94, "s2"], "\t" => [76, "s2"], "\n" => [104, "s2"], "\v" => [16, "s2"], "\f" => [94, "sa"], "\r" => [76, "sa"], "\x0e" => [104, "sa"], "\x0f" => [16, "sa"], "\x10" => [94, "sc"], "\x11" => [76, "sc"], "\x12" => [104, "sc"], "\x13" => [16, "sc"], "\x14" => [94, "se"], "\x15" => [76, "se"], "\x16" => [104, "se"], "\x17" => [16, "se"], "\x18" => [94, "si"], "\x19" => [76, "si"], "\x1a" => [104, "si"], "\x1b" => [16, "si"], "\x1c" => [94, "so"], "\x1d" => [76, "so"], "\x1e" => [104, "so"], "\x1f" => [16, "so"], " " => [94, "ss"], "!" => [76, "ss"], "\"" => [104, "ss"], "#" => [16, "ss"], "\$" => [94, "st"], "%" => [76, "st"], "&" => [104, "st"], "'" => [16, "st"], "(" => [77, "s "], ")" => [18, "s "], "*" => [77, "s%"], "+" => [18, "s%"], "," => [77, "s-"], "-" => [18, "s-"], "." => [77, "s."], "/" => [18, "s."], [77, "s/"], [18, "s/"], [77, "s3"], [18, "s3"], [77, "s4"], [18, "s4"], [77, "s5"], [18, "s5"], [77, "s6"], [18, "s6"], ":" => [77, "s7"], ";" => [18, "s7"], "<" => [77, "s8"], "=" => [18, "s8"], ">" => [77, "s9"], "?" => [18, "s9"], "@" => [77, "s="], "A" => [18, "s="], "B" => [77, "sA"], "C" => [18, "sA"], "D" => [77, "s_"], "E" => [18, "s_"], "F" => [77, "sb"], "G" => [18, "sb"], "H" => [77, "sd"], "I" => [18, "sd"], "J" => [77, "sf"], "K" => [18, "sf"], "L" => [77, "sg"], "M" => [18, "sg"], "N" => [77, "sh"], "O" => [18, "sh"], "P" => [77, "sl"], "Q" => [18, "sl"], "R" => [77, "sm"], "S" => [18, "sm"], "T" => [77, "sn"], "U" => [18, "sn"], "V" => [77, "sp"], "W" => [18, "sp"], "X" => [77, "sr"], "Y" => [18, "sr"], "Z" => [77, "su"], "[" => [18, "su"], "\\" => [0, "s:"], "]" => [0, "sB"], "^" => [0, "sC"], "_" => [0, "sD"], "`" => [0, "sE"], "a" => [0, "sF"], "b" => [0, "sG"], "c" => [0, "sH"], "d" => [0, "sI"], "e" => [0, "sJ"], "f" => [0, "sK"], "g" => [0, "sL"], "h" => [0, "sM"], "i" => [0, "sN"], "j" => [0, "sO"], "k" => [0, "sP"], "l" => [0, "sQ"], "m" => [0, "sR"], "n" => [0, "sS"], "o" => [0, "sT"], "p" => [0, "sU"], "q" => [0, "sV"], "r" => [0, "sW"], "s" => [0, "sY"], "t" => [0, "sj"], "u" => [0, "sk"], "v" => [0, "sq"], "w" => [0, "sv"], "x" => [0, "sw"], "y" => [0, "sx"], "z" => [0, "sy"], "{" => [0, "sz"], "|" => [82, "s"], "}" => [87, "s"], "~" => [130, "s"], "" => [9, "s"], "\x80" => [94, "t0"], "\x81" => [76, "t0"], "\x82" => [104, "t0"], "\x83" => [16, "t0"], "\x84" => [94, "t1"], "\x85" => [76, "t1"], "\x86" => [104, "t1"], "\x87" => [16, "t1"], "\x88" => [94, "t2"], "\x89" => [76, "t2"], "\x8a" => [104, "t2"], "\x8b" => [16, "t2"], "\x8c" => [94, "ta"], "\x8d" => [76, "ta"], "\x8e" => [104, "ta"], "\x8f" => [16, "ta"], "\x90" => [94, "tc"], "\x91" => [76, "tc"], "\x92" => [104, "tc"], "\x93" => [16, "tc"], "\x94" => [94, "te"], "\x95" => [76, "te"], "\x96" => [104, "te"], "\x97" => [16, "te"], "\x98" => [94, "ti"], "\x99" => [76, "ti"], "\x9a" => [104, "ti"], "\x9b" => [16, "ti"], "\x9c" => [94, "to"], "\x9d" => [76, "to"], "\x9e" => [104, "to"], "\x9f" => [16, "to"], "\xa0" => [94, "ts"], "\xa1" => [76, "ts"], "\xa2" => [104, "ts"], "\xa3" => [16, "ts"], "\xa4" => [94, "tt"], "\xa5" => [76, "tt"], "\xa6" => [104, "tt"], "\xa7" => [16, "tt"], "\xa8" => [77, "t "], "\xa9" => [18, "t "], "\xaa" => [77, "t%"], "\xab" => [18, "t%"], "\xac" => [77, "t-"], "\xad" => [18, "t-"], "\xae" => [77, "t."], "\xaf" => [18, "t."], "\xb0" => [77, "t/"], "\xb1" => [18, "t/"], "\xb2" => [77, "t3"], "\xb3" => [18, "t3"], "\xb4" => [77, "t4"], "\xb5" => [18, "t4"], "\xb6" => [77, "t5"], "\xb7" => [18, "t5"], "\xb8" => [77, "t6"], "\xb9" => [18, "t6"], "\xba" => [77, "t7"], "\xbb" => [18, "t7"], "\xbc" => [77, "t8"], "\xbd" => [18, "t8"], "\xbe" => [77, "t9"], "\xbf" => [18, "t9"], "\xc0" => [77, "t="], "\xc1" => [18, "t="], "\xc2" => [77, "tA"], "\xc3" => [18, "tA"], "\xc4" => [77, "t_"], "\xc5" => [18, "t_"], "\xc6" => [77, "tb"], "\xc7" => [18, "tb"], "\xc8" => [77, "td"], "\xc9" => [18, "td"], "\xca" => [77, "tf"], "\xcb" => [18, "tf"], "\xcc" => [77, "tg"], "\xcd" => [18, "tg"], "\xce" => [77, "th"], "\xcf" => [18, "th"], "\xd0" => [77, "tl"], "\xd1" => [18, "tl"], "\xd2" => [77, "tm"], "\xd3" => [18, "tm"], "\xd4" => [77, "tn"], "\xd5" => [18, "tn"], "\xd6" => [77, "tp"], "\xd7" => [18, "tp"], "\xd8" => [77, "tr"], "\xd9" => [18, "tr"], "\xda" => [77, "tu"], "\xdb" => [18, "tu"], "\xdc" => [0, "t:"], "\xdd" => [0, "tB"], "\xde" => [0, "tC"], "\xdf" => [0, "tD"], "\xe0" => [0, "tE"], "\xe1" => [0, "tF"], "\xe2" => [0, "tG"], "\xe3" => [0, "tH"], "\xe4" => [0, "tI"], "\xe5" => [0, "tJ"], "\xe6" => [0, "tK"], "\xe7" => [0, "tL"], "\xe8" => [0, "tM"], "\xe9" => [0, "tN"], "\xea" => [0, "tO"], "\xeb" => [0, "tP"], "\xec" => [0, "tQ"], "\xed" => [0, "tR"], "\xee" => [0, "tS"], "\xef" => [0, "tT"], "\xf0" => [0, "tU"], "\xf1" => [0, "tV"], "\xf2" => [0, "tW"], "\xf3" => [0, "tY"], "\xf4" => [0, "tj"], "\xf5" => [0, "tk"], "\xf6" => [0, "tq"], "\xf7" => [0, "tv"], "\xf8" => [0, "tw"], "\xf9" => [0, "tx"], "\xfa" => [0, "ty"], "\xfb" => [0, "tz"], "\xfc" => [82, "t"], "\xfd" => [87, "t"], "\xfe" => [130, "t"], "\xff" => [9, "t"]], ["\x00" => [94, "w0"], "\x01" => [76, "w0"], "\x02" => [104, "w0"], "\x03" => [16, "w0"], "\x04" => [94, "w1"], "\x05" => [76, "w1"], "\x06" => [104, "w1"], "\x07" => [16, "w1"], "\x08" => [94, "w2"], "\t" => [76, "w2"], "\n" => [104, "w2"], "\v" => [16, "w2"], "\f" => [94, "wa"], "\r" => [76, "wa"], "\x0e" => [104, "wa"], "\x0f" => [16, "wa"], "\x10" => [94, "wc"], "\x11" => [76, "wc"], "\x12" => [104, "wc"], "\x13" => [16, "wc"], "\x14" => [94, "we"], "\x15" => [76, "we"], "\x16" => [104, "we"], "\x17" => [16, "we"], "\x18" => [94, "wi"], "\x19" => [76, "wi"], "\x1a" => [104, "wi"], "\x1b" => [16, "wi"], "\x1c" => [94, "wo"], "\x1d" => [76, "wo"], "\x1e" => [104, "wo"], "\x1f" => [16, "wo"], " " => [94, "ws"], "!" => [76, "ws"], "\"" => [104, "ws"], "#" => [16, "ws"], "\$" => [94, "wt"], "%" => [76, "wt"], "&" => [104, "wt"], "'" => [16, "wt"], "(" => [77, "w "], ")" => [18, "w "], "*" => [77, "w%"], "+" => [18, "w%"], "," => [77, "w-"], "-" => [18, "w-"], "." => [77, "w."], "/" => [18, "w."], [77, "w/"], [18, "w/"], [77, "w3"], [18, "w3"], [77, "w4"], [18, "w4"], [77, "w5"], [18, "w5"], [77, "w6"], [18, "w6"], ":" => [77, "w7"], ";" => [18, "w7"], "<" => [77, "w8"], "=" => [18, "w8"], ">" => [77, "w9"], "?" => [18, "w9"], "@" => [77, "w="], "A" => [18, "w="], "B" => [77, "wA"], "C" => [18, "wA"], "D" => [77, "w_"], "E" => [18, "w_"], "F" => [77, "wb"], "G" => [18, "wb"], "H" => [77, "wd"], "I" => [18, "wd"], "J" => [77, "wf"], "K" => [18, "wf"], "L" => [77, "wg"], "M" => [18, "wg"], "N" => [77, "wh"], "O" => [18, "wh"], "P" => [77, "wl"], "Q" => [18, "wl"], "R" => [77, "wm"], "S" => [18, "wm"], "T" => [77, "wn"], "U" => [18, "wn"], "V" => [77, "wp"], "W" => [18, "wp"], "X" => [77, "wr"], "Y" => [18, "wr"], "Z" => [77, "wu"], "[" => [18, "wu"], "\\" => [0, "w:"], "]" => [0, "wB"], "^" => [0, "wC"], "_" => [0, "wD"], "`" => [0, "wE"], "a" => [0, "wF"], "b" => [0, "wG"], "c" => [0, "wH"], "d" => [0, "wI"], "e" => [0, "wJ"], "f" => [0, "wK"], "g" => [0, "wL"], "h" => [0, "wM"], "i" => [0, "wN"], "j" => [0, "wO"], "k" => [0, "wP"], "l" => [0, "wQ"], "m" => [0, "wR"], "n" => [0, "wS"], "o" => [0, "wT"], "p" => [0, "wU"], "q" => [0, "wV"], "r" => [0, "wW"], "s" => [0, "wY"], "t" => [0, "wj"], "u" => [0, "wk"], "v" => [0, "wq"], "w" => [0, "wv"], "x" => [0, "ww"], "y" => [0, "wx"], "z" => [0, "wy"], "{" => [0, "wz"], "|" => [82, "w"], "}" => [87, "w"], "~" => [130, "w"], "" => [9, "w"], "\x80" => [94, "x0"], "\x81" => [76, "x0"], "\x82" => [104, "x0"], "\x83" => [16, "x0"], "\x84" => [94, "x1"], "\x85" => [76, "x1"], "\x86" => [104, "x1"], "\x87" => [16, "x1"], "\x88" => [94, "x2"], "\x89" => [76, "x2"], "\x8a" => [104, "x2"], "\x8b" => [16, "x2"], "\x8c" => [94, "xa"], "\x8d" => [76, "xa"], "\x8e" => [104, "xa"], "\x8f" => [16, "xa"], "\x90" => [94, "xc"], "\x91" => [76, "xc"], "\x92" => [104, "xc"], "\x93" => [16, "xc"], "\x94" => [94, "xe"], "\x95" => [76, "xe"], "\x96" => [104, "xe"], "\x97" => [16, "xe"], "\x98" => [94, "xi"], "\x99" => [76, "xi"], "\x9a" => [104, "xi"], "\x9b" => [16, "xi"], "\x9c" => [94, "xo"], "\x9d" => [76, "xo"], "\x9e" => [104, "xo"], "\x9f" => [16, "xo"], "\xa0" => [94, "xs"], "\xa1" => [76, "xs"], "\xa2" => [104, "xs"], "\xa3" => [16, "xs"], "\xa4" => [94, "xt"], "\xa5" => [76, "xt"], "\xa6" => [104, "xt"], "\xa7" => [16, "xt"], "\xa8" => [77, "x "], "\xa9" => [18, "x "], "\xaa" => [77, "x%"], "\xab" => [18, "x%"], "\xac" => [77, "x-"], "\xad" => [18, "x-"], "\xae" => [77, "x."], "\xaf" => [18, "x."], "\xb0" => [77, "x/"], "\xb1" => [18, "x/"], "\xb2" => [77, "x3"], "\xb3" => [18, "x3"], "\xb4" => [77, "x4"], "\xb5" => [18, "x4"], "\xb6" => [77, "x5"], "\xb7" => [18, "x5"], "\xb8" => [77, "x6"], "\xb9" => [18, "x6"], "\xba" => [77, "x7"], "\xbb" => [18, "x7"], "\xbc" => [77, "x8"], "\xbd" => [18, "x8"], "\xbe" => [77, "x9"], "\xbf" => [18, "x9"], "\xc0" => [77, "x="], "\xc1" => [18, "x="], "\xc2" => [77, "xA"], "\xc3" => [18, "xA"], "\xc4" => [77, "x_"], "\xc5" => [18, "x_"], "\xc6" => [77, "xb"], "\xc7" => [18, "xb"], "\xc8" => [77, "xd"], "\xc9" => [18, "xd"], "\xca" => [77, "xf"], "\xcb" => [18, "xf"], "\xcc" => [77, "xg"], "\xcd" => [18, "xg"], "\xce" => [77, "xh"], "\xcf" => [18, "xh"], "\xd0" => [77, "xl"], "\xd1" => [18, "xl"], "\xd2" => [77, "xm"], "\xd3" => [18, "xm"], "\xd4" => [77, "xn"], "\xd5" => [18, "xn"], "\xd6" => [77, "xp"], "\xd7" => [18, "xp"], "\xd8" => [77, "xr"], "\xd9" => [18, "xr"], "\xda" => [77, "xu"], "\xdb" => [18, "xu"], "\xdc" => [0, "x:"], "\xdd" => [0, "xB"], "\xde" => [0, "xC"], "\xdf" => [0, "xD"], "\xe0" => [0, "xE"], "\xe1" => [0, "xF"], "\xe2" => [0, "xG"], "\xe3" => [0, "xH"], "\xe4" => [0, "xI"], "\xe5" => [0, "xJ"], "\xe6" => [0, "xK"], "\xe7" => [0, "xL"], "\xe8" => [0, "xM"], "\xe9" => [0, "xN"], "\xea" => [0, "xO"], "\xeb" => [0, "xP"], "\xec" => [0, "xQ"], "\xed" => [0, "xR"], "\xee" => [0, "xS"], "\xef" => [0, "xT"], "\xf0" => [0, "xU"], "\xf1" => [0, "xV"], "\xf2" => [0, "xW"], "\xf3" => [0, "xY"], "\xf4" => [0, "xj"], "\xf5" => [0, "xk"], "\xf6" => [0, "xq"], "\xf7" => [0, "xv"], "\xf8" => [0, "xw"], "\xf9" => [0, "xx"], "\xfa" => [0, "xy"], "\xfb" => [0, "xz"], "\xfc" => [82, "x"], "\xfd" => [87, "x"], "\xfe" => [130, "x"], "\xff" => [9, "x"]], ["\x00" => [77, "w0"], "\x01" => [18, "w0"], "\x02" => [77, "w1"], "\x03" => [18, "w1"], "\x04" => [77, "w2"], "\x05" => [18, "w2"], "\x06" => [77, "wa"], "\x07" => [18, "wa"], "\x08" => [77, "wc"], "\t" => [18, "wc"], "\n" => [77, "we"], "\v" => [18, "we"], "\f" => [77, "wi"], "\r" => [18, "wi"], "\x0e" => [77, "wo"], "\x0f" => [18, "wo"], "\x10" => [77, "ws"], "\x11" => [18, "ws"], "\x12" => [77, "wt"], "\x13" => [18, "wt"], "\x14" => [0, "w "], "\x15" => [0, "w%"], "\x16" => [0, "w-"], "\x17" => [0, "w."], "\x18" => [0, "w/"], "\x19" => [0, "w3"], "\x1a" => [0, "w4"], "\x1b" => [0, "w5"], "\x1c" => [0, "w6"], "\x1d" => [0, "w7"], "\x1e" => [0, "w8"], "\x1f" => [0, "w9"], " " => [0, "w="], "!" => [0, "wA"], "\"" => [0, "w_"], "#" => [0, "wb"], "\$" => [0, "wd"], "%" => [0, "wf"], "&" => [0, "wg"], "'" => [0, "wh"], "(" => [0, "wl"], ")" => [0, "wm"], "*" => [0, "wn"], "+" => [0, "wp"], "," => [0, "wr"], "-" => [0, "wu"], "." => [100, "w"], "/" => [110, "w"], [111, "w"], [115, "w"], [116, "w"], [118, "w"], [119, "w"], [122, "w"], [123, "w"], [125, "w"], [126, "w"], [129, "w"], ":" => [143, "w"], ";" => [148, "w"], "<" => [151, "w"], "=" => [153, "w"], ">" => [83, "w"], "?" => [10, "w"], "@" => [77, "x0"], "A" => [18, "x0"], "B" => [77, "x1"], "C" => [18, "x1"], "D" => [77, "x2"], "E" => [18, "x2"], "F" => [77, "xa"], "G" => [18, "xa"], "H" => [77, "xc"], "I" => [18, "xc"], "J" => [77, "xe"], "K" => [18, "xe"], "L" => [77, "xi"], "M" => [18, "xi"], "N" => [77, "xo"], "O" => [18, "xo"], "P" => [77, "xs"], "Q" => [18, "xs"], "R" => [77, "xt"], "S" => [18, "xt"], "T" => [0, "x "], "U" => [0, "x%"], "V" => [0, "x-"], "W" => [0, "x."], "X" => [0, "x/"], "Y" => [0, "x3"], "Z" => [0, "x4"], "[" => [0, "x5"], "\\" => [0, "x6"], "]" => [0, "x7"], "^" => [0, "x8"], "_" => [0, "x9"], "`" => [0, "x="], "a" => [0, "xA"], "b" => [0, "x_"], "c" => [0, "xb"], "d" => [0, "xd"], "e" => [0, "xf"], "f" => [0, "xg"], "g" => [0, "xh"], "h" => [0, "xl"], "i" => [0, "xm"], "j" => [0, "xn"], "k" => [0, "xp"], "l" => [0, "xr"], "m" => [0, "xu"], "n" => [100, "x"], "o" => [110, "x"], "p" => [111, "x"], "q" => [115, "x"], "r" => [116, "x"], "s" => [118, "x"], "t" => [119, "x"], "u" => [122, "x"], "v" => [123, "x"], "w" => [125, "x"], "x" => [126, "x"], "y" => [129, "x"], "z" => [143, "x"], "{" => [148, "x"], "|" => [151, "x"], "}" => [153, "x"], "~" => [83, "x"], "" => [10, "x"], "\x80" => [77, "y0"], "\x81" => [18, "y0"], "\x82" => [77, "y1"], "\x83" => [18, "y1"], "\x84" => [77, "y2"], "\x85" => [18, "y2"], "\x86" => [77, "ya"], "\x87" => [18, "ya"], "\x88" => [77, "yc"], "\x89" => [18, "yc"], "\x8a" => [77, "ye"], "\x8b" => [18, "ye"], "\x8c" => [77, "yi"], "\x8d" => [18, "yi"], "\x8e" => [77, "yo"], "\x8f" => [18, "yo"], "\x90" => [77, "ys"], "\x91" => [18, "ys"], "\x92" => [77, "yt"], "\x93" => [18, "yt"], "\x94" => [0, "y "], "\x95" => [0, "y%"], "\x96" => [0, "y-"], "\x97" => [0, "y."], "\x98" => [0, "y/"], "\x99" => [0, "y3"], "\x9a" => [0, "y4"], "\x9b" => [0, "y5"], "\x9c" => [0, "y6"], "\x9d" => [0, "y7"], "\x9e" => [0, "y8"], "\x9f" => [0, "y9"], "\xa0" => [0, "y="], "\xa1" => [0, "yA"], "\xa2" => [0, "y_"], "\xa3" => [0, "yb"], "\xa4" => [0, "yd"], "\xa5" => [0, "yf"], "\xa6" => [0, "yg"], "\xa7" => [0, "yh"], "\xa8" => [0, "yl"], "\xa9" => [0, "ym"], "\xaa" => [0, "yn"], "\xab" => [0, "yp"], "\xac" => [0, "yr"], "\xad" => [0, "yu"], "\xae" => [100, "y"], "\xaf" => [110, "y"], "\xb0" => [111, "y"], "\xb1" => [115, "y"], "\xb2" => [116, "y"], "\xb3" => [118, "y"], "\xb4" => [119, "y"], "\xb5" => [122, "y"], "\xb6" => [123, "y"], "\xb7" => [125, "y"], "\xb8" => [126, "y"], "\xb9" => [129, "y"], "\xba" => [143, "y"], "\xbb" => [148, "y"], "\xbc" => [151, "y"], "\xbd" => [153, "y"], "\xbe" => [83, "y"], "\xbf" => [10, "y"], "\xc0" => [77, "z0"], "\xc1" => [18, "z0"], "\xc2" => [77, "z1"], "\xc3" => [18, "z1"], "\xc4" => [77, "z2"], "\xc5" => [18, "z2"], "\xc6" => [77, "za"], "\xc7" => [18, "za"], "\xc8" => [77, "zc"], "\xc9" => [18, "zc"], "\xca" => [77, "ze"], "\xcb" => [18, "ze"], "\xcc" => [77, "zi"], "\xcd" => [18, "zi"], "\xce" => [77, "zo"], "\xcf" => [18, "zo"], "\xd0" => [77, "zs"], "\xd1" => [18, "zs"], "\xd2" => [77, "zt"], "\xd3" => [18, "zt"], "\xd4" => [0, "z "], "\xd5" => [0, "z%"], "\xd6" => [0, "z-"], "\xd7" => [0, "z."], "\xd8" => [0, "z/"], "\xd9" => [0, "z3"], "\xda" => [0, "z4"], "\xdb" => [0, "z5"], "\xdc" => [0, "z6"], "\xdd" => [0, "z7"], "\xde" => [0, "z8"], "\xdf" => [0, "z9"], "\xe0" => [0, "z="], "\xe1" => [0, "zA"], "\xe2" => [0, "z_"], "\xe3" => [0, "zb"], "\xe4" => [0, "zd"], "\xe5" => [0, "zf"], "\xe6" => [0, "zg"], "\xe7" => [0, "zh"], "\xe8" => [0, "zl"], "\xe9" => [0, "zm"], "\xea" => [0, "zn"], "\xeb" => [0, "zp"], "\xec" => [0, "zr"], "\xed" => [0, "zu"], "\xee" => [100, "z"], "\xef" => [110, "z"], "\xf0" => [111, "z"], "\xf1" => [115, "z"], "\xf2" => [116, "z"], "\xf3" => [118, "z"], "\xf4" => [119, "z"], "\xf5" => [122, "z"], "\xf6" => [123, "z"], "\xf7" => [125, "z"], "\xf8" => [126, "z"], "\xf9" => [129, "z"], "\xfa" => [143, "z"], "\xfb" => [148, "z"], "\xfc" => [151, "z"], "\xfd" => [153, "z"], "\xfe" => [83, "z"], "\xff" => [10, "z"]], ["\x00" => [94, "y0"], "\x01" => [76, "y0"], "\x02" => [104, "y0"], "\x03" => [16, "y0"], "\x04" => [94, "y1"], "\x05" => [76, "y1"], "\x06" => [104, "y1"], "\x07" => [16, "y1"], "\x08" => [94, "y2"], "\t" => [76, "y2"], "\n" => [104, "y2"], "\v" => [16, "y2"], "\f" => [94, "ya"], "\r" => [76, "ya"], "\x0e" => [104, "ya"], "\x0f" => [16, "ya"], "\x10" => [94, "yc"], "\x11" => [76, "yc"], "\x12" => [104, "yc"], "\x13" => [16, "yc"], "\x14" => [94, "ye"], "\x15" => [76, "ye"], "\x16" => [104, "ye"], "\x17" => [16, "ye"], "\x18" => [94, "yi"], "\x19" => [76, "yi"], "\x1a" => [104, "yi"], "\x1b" => [16, "yi"], "\x1c" => [94, "yo"], "\x1d" => [76, "yo"], "\x1e" => [104, "yo"], "\x1f" => [16, "yo"], " " => [94, "ys"], "!" => [76, "ys"], "\"" => [104, "ys"], "#" => [16, "ys"], "\$" => [94, "yt"], "%" => [76, "yt"], "&" => [104, "yt"], "'" => [16, "yt"], "(" => [77, "y "], ")" => [18, "y "], "*" => [77, "y%"], "+" => [18, "y%"], "," => [77, "y-"], "-" => [18, "y-"], "." => [77, "y."], "/" => [18, "y."], [77, "y/"], [18, "y/"], [77, "y3"], [18, "y3"], [77, "y4"], [18, "y4"], [77, "y5"], [18, "y5"], [77, "y6"], [18, "y6"], ":" => [77, "y7"], ";" => [18, "y7"], "<" => [77, "y8"], "=" => [18, "y8"], ">" => [77, "y9"], "?" => [18, "y9"], "@" => [77, "y="], "A" => [18, "y="], "B" => [77, "yA"], "C" => [18, "yA"], "D" => [77, "y_"], "E" => [18, "y_"], "F" => [77, "yb"], "G" => [18, "yb"], "H" => [77, "yd"], "I" => [18, "yd"], "J" => [77, "yf"], "K" => [18, "yf"], "L" => [77, "yg"], "M" => [18, "yg"], "N" => [77, "yh"], "O" => [18, "yh"], "P" => [77, "yl"], "Q" => [18, "yl"], "R" => [77, "ym"], "S" => [18, "ym"], "T" => [77, "yn"], "U" => [18, "yn"], "V" => [77, "yp"], "W" => [18, "yp"], "X" => [77, "yr"], "Y" => [18, "yr"], "Z" => [77, "yu"], "[" => [18, "yu"], "\\" => [0, "y:"], "]" => [0, "yB"], "^" => [0, "yC"], "_" => [0, "yD"], "`" => [0, "yE"], "a" => [0, "yF"], "b" => [0, "yG"], "c" => [0, "yH"], "d" => [0, "yI"], "e" => [0, "yJ"], "f" => [0, "yK"], "g" => [0, "yL"], "h" => [0, "yM"], "i" => [0, "yN"], "j" => [0, "yO"], "k" => [0, "yP"], "l" => [0, "yQ"], "m" => [0, "yR"], "n" => [0, "yS"], "o" => [0, "yT"], "p" => [0, "yU"], "q" => [0, "yV"], "r" => [0, "yW"], "s" => [0, "yY"], "t" => [0, "yj"], "u" => [0, "yk"], "v" => [0, "yq"], "w" => [0, "yv"], "x" => [0, "yw"], "y" => [0, "yx"], "z" => [0, "yy"], "{" => [0, "yz"], "|" => [82, "y"], "}" => [87, "y"], "~" => [130, "y"], "" => [9, "y"], "\x80" => [94, "z0"], "\x81" => [76, "z0"], "\x82" => [104, "z0"], "\x83" => [16, "z0"], "\x84" => [94, "z1"], "\x85" => [76, "z1"], "\x86" => [104, "z1"], "\x87" => [16, "z1"], "\x88" => [94, "z2"], "\x89" => [76, "z2"], "\x8a" => [104, "z2"], "\x8b" => [16, "z2"], "\x8c" => [94, "za"], "\x8d" => [76, "za"], "\x8e" => [104, "za"], "\x8f" => [16, "za"], "\x90" => [94, "zc"], "\x91" => [76, "zc"], "\x92" => [104, "zc"], "\x93" => [16, "zc"], "\x94" => [94, "ze"], "\x95" => [76, "ze"], "\x96" => [104, "ze"], "\x97" => [16, "ze"], "\x98" => [94, "zi"], "\x99" => [76, "zi"], "\x9a" => [104, "zi"], "\x9b" => [16, "zi"], "\x9c" => [94, "zo"], "\x9d" => [76, "zo"], "\x9e" => [104, "zo"], "\x9f" => [16, "zo"], "\xa0" => [94, "zs"], "\xa1" => [76, "zs"], "\xa2" => [104, "zs"], "\xa3" => [16, "zs"], "\xa4" => [94, "zt"], "\xa5" => [76, "zt"], "\xa6" => [104, "zt"], "\xa7" => [16, "zt"], "\xa8" => [77, "z "], "\xa9" => [18, "z "], "\xaa" => [77, "z%"], "\xab" => [18, "z%"], "\xac" => [77, "z-"], "\xad" => [18, "z-"], "\xae" => [77, "z."], "\xaf" => [18, "z."], "\xb0" => [77, "z/"], "\xb1" => [18, "z/"], "\xb2" => [77, "z3"], "\xb3" => [18, "z3"], "\xb4" => [77, "z4"], "\xb5" => [18, "z4"], "\xb6" => [77, "z5"], "\xb7" => [18, "z5"], "\xb8" => [77, "z6"], "\xb9" => [18, "z6"], "\xba" => [77, "z7"], "\xbb" => [18, "z7"], "\xbc" => [77, "z8"], "\xbd" => [18, "z8"], "\xbe" => [77, "z9"], "\xbf" => [18, "z9"], "\xc0" => [77, "z="], "\xc1" => [18, "z="], "\xc2" => [77, "zA"], "\xc3" => [18, "zA"], "\xc4" => [77, "z_"], "\xc5" => [18, "z_"], "\xc6" => [77, "zb"], "\xc7" => [18, "zb"], "\xc8" => [77, "zd"], "\xc9" => [18, "zd"], "\xca" => [77, "zf"], "\xcb" => [18, "zf"], "\xcc" => [77, "zg"], "\xcd" => [18, "zg"], "\xce" => [77, "zh"], "\xcf" => [18, "zh"], "\xd0" => [77, "zl"], "\xd1" => [18, "zl"], "\xd2" => [77, "zm"], "\xd3" => [18, "zm"], "\xd4" => [77, "zn"], "\xd5" => [18, "zn"], "\xd6" => [77, "zp"], "\xd7" => [18, "zp"], "\xd8" => [77, "zr"], "\xd9" => [18, "zr"], "\xda" => [77, "zu"], "\xdb" => [18, "zu"], "\xdc" => [0, "z:"], "\xdd" => [0, "zB"], "\xde" => [0, "zC"], "\xdf" => [0, "zD"], "\xe0" => [0, "zE"], "\xe1" => [0, "zF"], "\xe2" => [0, "zG"], "\xe3" => [0, "zH"], "\xe4" => [0, "zI"], "\xe5" => [0, "zJ"], "\xe6" => [0, "zK"], "\xe7" => [0, "zL"], "\xe8" => [0, "zM"], "\xe9" => [0, "zN"], "\xea" => [0, "zO"], "\xeb" => [0, "zP"], "\xec" => [0, "zQ"], "\xed" => [0, "zR"], "\xee" => [0, "zS"], "\xef" => [0, "zT"], "\xf0" => [0, "zU"], "\xf1" => [0, "zV"], "\xf2" => [0, "zW"], "\xf3" => [0, "zY"], "\xf4" => [0, "zj"], "\xf5" => [0, "zk"], "\xf6" => [0, "zq"], "\xf7" => [0, "zv"], "\xf8" => [0, "zw"], "\xf9" => [0, "zx"], "\xfa" => [0, "zy"], "\xfb" => [0, "zz"], "\xfc" => [82, "z"], "\xfd" => [87, "z"], "\xfe" => [130, "z"], "\xff" => [9, "z"]], ["\x00" => [94, "0"], "\x01" => [76, "0"], "\x02" => [104, "0"], "\x03" => [16, "0"], "\x04" => [94, "1"], "\x05" => [76, "1"], "\x06" => [104, "1"], "\x07" => [16, "1"], "\x08" => [94, "2"], "\t" => [76, "2"], "\n" => [104, "2"], "\v" => [16, "2"], "\f" => [94, "a"], "\r" => [76, "a"], "\x0e" => [104, "a"], "\x0f" => [16, "a"], "\x10" => [94, "c"], "\x11" => [76, "c"], "\x12" => [104, "c"], "\x13" => [16, "c"], "\x14" => [94, "e"], "\x15" => [76, "e"], "\x16" => [104, "e"], "\x17" => [16, "e"], "\x18" => [94, "i"], "\x19" => [76, "i"], "\x1a" => [104, "i"], "\x1b" => [16, "i"], "\x1c" => [94, "o"], "\x1d" => [76, "o"], "\x1e" => [104, "o"], "\x1f" => [16, "o"], " " => [94, "s"], "!" => [76, "s"], "\"" => [104, "s"], "#" => [16, "s"], "\$" => [94, "t"], "%" => [76, "t"], "&" => [104, "t"], "'" => [16, "t"], "(" => [77, " "], ")" => [18, " "], "*" => [77, "%"], "+" => [18, "%"], "," => [77, "-"], "-" => [18, "-"], "." => [77, "."], "/" => [18, "."], [77, "/"], [18, "/"], [77, "3"], [18, "3"], [77, "4"], [18, "4"], [77, "5"], [18, "5"], [77, "6"], [18, "6"], ":" => [77, "7"], ";" => [18, "7"], "<" => [77, "8"], "=" => [18, "8"], ">" => [77, "9"], "?" => [18, "9"], "@" => [77, "="], "A" => [18, "="], "B" => [77, "A"], "C" => [18, "A"], "D" => [77, "_"], "E" => [18, "_"], "F" => [77, "b"], "G" => [18, "b"], "H" => [77, "d"], "I" => [18, "d"], "J" => [77, "f"], "K" => [18, "f"], "L" => [77, "g"], "M" => [18, "g"], "N" => [77, "h"], "O" => [18, "h"], "P" => [77, "l"], "Q" => [18, "l"], "R" => [77, "m"], "S" => [18, "m"], "T" => [77, "n"], "U" => [18, "n"], "V" => [77, "p"], "W" => [18, "p"], "X" => [77, "r"], "Y" => [18, "r"], "Z" => [77, "u"], "[" => [18, "u"], "\\" => [0, ":"], "]" => [0, "B"], "^" => [0, "C"], "_" => [0, "D"], "`" => [0, "E"], "a" => [0, "F"], "b" => [0, "G"], "c" => [0, "H"], "d" => [0, "I"], "e" => [0, "J"], "f" => [0, "K"], "g" => [0, "L"], "h" => [0, "M"], "i" => [0, "N"], "j" => [0, "O"], "k" => [0, "P"], "l" => [0, "Q"], "m" => [0, "R"], "n" => [0, "S"], "o" => [0, "T"], "p" => [0, "U"], "q" => [0, "V"], "r" => [0, "W"], "s" => [0, "Y"], "t" => [0, "j"], "u" => [0, "k"], "v" => [0, "q"], "w" => [0, "v"], "x" => [0, "w"], "y" => [0, "x"], "z" => [0, "y"], "{" => [0, "z"], "|" => [82, ""], "}" => [87, ""], "~" => [130, ""], "" => [9, ""], "\x80" => [94, "\xdc0"], "\x81" => [76, "\xdc0"], "\x82" => [104, "\xdc0"], "\x83" => [16, "\xdc0"], "\x84" => [94, "\xdc1"], "\x85" => [76, "\xdc1"], "\x86" => [104, "\xdc1"], "\x87" => [16, "\xdc1"], "\x88" => [94, "\xdc2"], "\x89" => [76, "\xdc2"], "\x8a" => [104, "\xdc2"], "\x8b" => [16, "\xdc2"], "\x8c" => [94, "\xdca"], "\x8d" => [76, "\xdca"], "\x8e" => [104, "\xdca"], "\x8f" => [16, "\xdca"], "\x90" => [94, "\xdcc"], "\x91" => [76, "\xdcc"], "\x92" => [104, "\xdcc"], "\x93" => [16, "\xdcc"], "\x94" => [94, "\xdce"], "\x95" => [76, "\xdce"], "\x96" => [104, "\xdce"], "\x97" => [16, "\xdce"], "\x98" => [94, "\xdci"], "\x99" => [76, "\xdci"], "\x9a" => [104, "\xdci"], "\x9b" => [16, "\xdci"], "\x9c" => [94, "\xdco"], "\x9d" => [76, "\xdco"], "\x9e" => [104, "\xdco"], "\x9f" => [16, "\xdco"], "\xa0" => [94, "\xdcs"], "\xa1" => [76, "\xdcs"], "\xa2" => [104, "\xdcs"], "\xa3" => [16, "\xdcs"], "\xa4" => [94, "\xdct"], "\xa5" => [76, "\xdct"], "\xa6" => [104, "\xdct"], "\xa7" => [16, "\xdct"], "\xa8" => [77, "\xdc "], "\xa9" => [18, "\xdc "], "\xaa" => [77, "\xdc%"], "\xab" => [18, "\xdc%"], "\xac" => [77, "\xdc-"], "\xad" => [18, "\xdc-"], "\xae" => [77, "\xdc."], "\xaf" => [18, "\xdc."], "\xb0" => [77, "\xdc/"], "\xb1" => [18, "\xdc/"], "\xb2" => [77, "\xdc3"], "\xb3" => [18, "\xdc3"], "\xb4" => [77, "\xdc4"], "\xb5" => [18, "\xdc4"], "\xb6" => [77, "\xdc5"], "\xb7" => [18, "\xdc5"], "\xb8" => [77, "\xdc6"], "\xb9" => [18, "\xdc6"], "\xba" => [77, "\xdc7"], "\xbb" => [18, "\xdc7"], "\xbc" => [77, "\xdc8"], "\xbd" => [18, "\xdc8"], "\xbe" => [77, "\xdc9"], "\xbf" => [18, "\xdc9"], "\xc0" => [77, "\xdc="], "\xc1" => [18, "\xdc="], "\xc2" => [77, "\xdcA"], "\xc3" => [18, "\xdcA"], "\xc4" => [77, "\xdc_"], "\xc5" => [18, "\xdc_"], "\xc6" => [77, "\xdcb"], "\xc7" => [18, "\xdcb"], "\xc8" => [77, "\xdcd"], "\xc9" => [18, "\xdcd"], "\xca" => [77, "\xdcf"], "\xcb" => [18, "\xdcf"], "\xcc" => [77, "\xdcg"], "\xcd" => [18, "\xdcg"], "\xce" => [77, "\xdch"], "\xcf" => [18, "\xdch"], "\xd0" => [77, "\xdcl"], "\xd1" => [18, "\xdcl"], "\xd2" => [77, "\xdcm"], "\xd3" => [18, "\xdcm"], "\xd4" => [77, "\xdcn"], "\xd5" => [18, "\xdcn"], "\xd6" => [77, "\xdcp"], "\xd7" => [18, "\xdcp"], "\xd8" => [77, "\xdcr"], "\xd9" => [18, "\xdcr"], "\xda" => [77, "\xdcu"], "\xdb" => [18, "\xdcu"], "\xdc" => [0, "\xdc:"], "\xdd" => [0, "\xdcB"], "\xde" => [0, "\xdcC"], "\xdf" => [0, "\xdcD"], "\xe0" => [0, "\xdcE"], "\xe1" => [0, "\xdcF"], "\xe2" => [0, "\xdcG"], "\xe3" => [0, "\xdcH"], "\xe4" => [0, "\xdcI"], "\xe5" => [0, "\xdcJ"], "\xe6" => [0, "\xdcK"], "\xe7" => [0, "\xdcL"], "\xe8" => [0, "\xdcM"], "\xe9" => [0, "\xdcN"], "\xea" => [0, "\xdcO"], "\xeb" => [0, "\xdcP"], "\xec" => [0, "\xdcQ"], "\xed" => [0, "\xdcR"], "\xee" => [0, "\xdcS"], "\xef" => [0, "\xdcT"], "\xf0" => [0, "\xdcU"], "\xf1" => [0, "\xdcV"], "\xf2" => [0, "\xdcW"], "\xf3" => [0, "\xdcY"], "\xf4" => [0, "\xdcj"], "\xf5" => [0, "\xdck"], "\xf6" => [0, "\xdcq"], "\xf7" => [0, "\xdcv"], "\xf8" => [0, "\xdcw"], "\xf9" => [0, "\xdcx"], "\xfa" => [0, "\xdcy"], "\xfb" => [0, "\xdcz"], "\xfc" => [82, "\xdc"], "\xfd" => [87, "\xdc"], "\xfe" => [130, "\xdc"], "\xff" => [9, "\xdc"]], ["\x00" => [94, "\x800"], "\x01" => [76, "\x800"], "\x02" => [104, "\x800"], "\x03" => [16, "\x800"], "\x04" => [94, "\x801"], "\x05" => [76, "\x801"], "\x06" => [104, "\x801"], "\x07" => [16, "\x801"], "\x08" => [94, "\x802"], "\t" => [76, "\x802"], "\n" => [104, "\x802"], "\v" => [16, "\x802"], "\f" => [94, "\x80a"], "\r" => [76, "\x80a"], "\x0e" => [104, "\x80a"], "\x0f" => [16, "\x80a"], "\x10" => [94, "\x80c"], "\x11" => [76, "\x80c"], "\x12" => [104, "\x80c"], "\x13" => [16, "\x80c"], "\x14" => [94, "\x80e"], "\x15" => [76, "\x80e"], "\x16" => [104, "\x80e"], "\x17" => [16, "\x80e"], "\x18" => [94, "\x80i"], "\x19" => [76, "\x80i"], "\x1a" => [104, "\x80i"], "\x1b" => [16, "\x80i"], "\x1c" => [94, "\x80o"], "\x1d" => [76, "\x80o"], "\x1e" => [104, "\x80o"], "\x1f" => [16, "\x80o"], " " => [94, "\x80s"], "!" => [76, "\x80s"], "\"" => [104, "\x80s"], "#" => [16, "\x80s"], "\$" => [94, "\x80t"], "%" => [76, "\x80t"], "&" => [104, "\x80t"], "'" => [16, "\x80t"], "(" => [77, "\x80 "], ")" => [18, "\x80 "], "*" => [77, "\x80%"], "+" => [18, "\x80%"], "," => [77, "\x80-"], "-" => [18, "\x80-"], "." => [77, "\x80."], "/" => [18, "\x80."], [77, "\x80/"], [18, "\x80/"], [77, "\x803"], [18, "\x803"], [77, "\x804"], [18, "\x804"], [77, "\x805"], [18, "\x805"], [77, "\x806"], [18, "\x806"], ":" => [77, "\x807"], ";" => [18, "\x807"], "<" => [77, "\x808"], "=" => [18, "\x808"], ">" => [77, "\x809"], "?" => [18, "\x809"], "@" => [77, "\x80="], "A" => [18, "\x80="], "B" => [77, "\x80A"], "C" => [18, "\x80A"], "D" => [77, "\x80_"], "E" => [18, "\x80_"], "F" => [77, "\x80b"], "G" => [18, "\x80b"], "H" => [77, "\x80d"], "I" => [18, "\x80d"], "J" => [77, "\x80f"], "K" => [18, "\x80f"], "L" => [77, "\x80g"], "M" => [18, "\x80g"], "N" => [77, "\x80h"], "O" => [18, "\x80h"], "P" => [77, "\x80l"], "Q" => [18, "\x80l"], "R" => [77, "\x80m"], "S" => [18, "\x80m"], "T" => [77, "\x80n"], "U" => [18, "\x80n"], "V" => [77, "\x80p"], "W" => [18, "\x80p"], "X" => [77, "\x80r"], "Y" => [18, "\x80r"], "Z" => [77, "\x80u"], "[" => [18, "\x80u"], "\\" => [0, "\x80:"], "]" => [0, "\x80B"], "^" => [0, "\x80C"], "_" => [0, "\x80D"], "`" => [0, "\x80E"], "a" => [0, "\x80F"], "b" => [0, "\x80G"], "c" => [0, "\x80H"], "d" => [0, "\x80I"], "e" => [0, "\x80J"], "f" => [0, "\x80K"], "g" => [0, "\x80L"], "h" => [0, "\x80M"], "i" => [0, "\x80N"], "j" => [0, "\x80O"], "k" => [0, "\x80P"], "l" => [0, "\x80Q"], "m" => [0, "\x80R"], "n" => [0, "\x80S"], "o" => [0, "\x80T"], "p" => [0, "\x80U"], "q" => [0, "\x80V"], "r" => [0, "\x80W"], "s" => [0, "\x80Y"], "t" => [0, "\x80j"], "u" => [0, "\x80k"], "v" => [0, "\x80q"], "w" => [0, "\x80v"], "x" => [0, "\x80w"], "y" => [0, "\x80x"], "z" => [0, "\x80y"], "{" => [0, "\x80z"], "|" => [82, "\x80"], "}" => [87, "\x80"], "~" => [130, "\x80"], "" => [9, "\x80"], "\x80" => [94, "\x820"], "\x81" => [76, "\x820"], "\x82" => [104, "\x820"], "\x83" => [16, "\x820"], "\x84" => [94, "\x821"], "\x85" => [76, "\x821"], "\x86" => [104, "\x821"], "\x87" => [16, "\x821"], "\x88" => [94, "\x822"], "\x89" => [76, "\x822"], "\x8a" => [104, "\x822"], "\x8b" => [16, "\x822"], "\x8c" => [94, "\x82a"], "\x8d" => [76, "\x82a"], "\x8e" => [104, "\x82a"], "\x8f" => [16, "\x82a"], "\x90" => [94, "\x82c"], "\x91" => [76, "\x82c"], "\x92" => [104, "\x82c"], "\x93" => [16, "\x82c"], "\x94" => [94, "\x82e"], "\x95" => [76, "\x82e"], "\x96" => [104, "\x82e"], "\x97" => [16, "\x82e"], "\x98" => [94, "\x82i"], "\x99" => [76, "\x82i"], "\x9a" => [104, "\x82i"], "\x9b" => [16, "\x82i"], "\x9c" => [94, "\x82o"], "\x9d" => [76, "\x82o"], "\x9e" => [104, "\x82o"], "\x9f" => [16, "\x82o"], "\xa0" => [94, "\x82s"], "\xa1" => [76, "\x82s"], "\xa2" => [104, "\x82s"], "\xa3" => [16, "\x82s"], "\xa4" => [94, "\x82t"], "\xa5" => [76, "\x82t"], "\xa6" => [104, "\x82t"], "\xa7" => [16, "\x82t"], "\xa8" => [77, "\x82 "], "\xa9" => [18, "\x82 "], "\xaa" => [77, "\x82%"], "\xab" => [18, "\x82%"], "\xac" => [77, "\x82-"], "\xad" => [18, "\x82-"], "\xae" => [77, "\x82."], "\xaf" => [18, "\x82."], "\xb0" => [77, "\x82/"], "\xb1" => [18, "\x82/"], "\xb2" => [77, "\x823"], "\xb3" => [18, "\x823"], "\xb4" => [77, "\x824"], "\xb5" => [18, "\x824"], "\xb6" => [77, "\x825"], "\xb7" => [18, "\x825"], "\xb8" => [77, "\x826"], "\xb9" => [18, "\x826"], "\xba" => [77, "\x827"], "\xbb" => [18, "\x827"], "\xbc" => [77, "\x828"], "\xbd" => [18, "\x828"], "\xbe" => [77, "\x829"], "\xbf" => [18, "\x829"], "\xc0" => [77, "\x82="], "\xc1" => [18, "\x82="], "\xc2" => [77, "\x82A"], "\xc3" => [18, "\x82A"], "\xc4" => [77, "\x82_"], "\xc5" => [18, "\x82_"], "\xc6" => [77, "\x82b"], "\xc7" => [18, "\x82b"], "\xc8" => [77, "\x82d"], "\xc9" => [18, "\x82d"], "\xca" => [77, "\x82f"], "\xcb" => [18, "\x82f"], "\xcc" => [77, "\x82g"], "\xcd" => [18, "\x82g"], "\xce" => [77, "\x82h"], "\xcf" => [18, "\x82h"], "\xd0" => [77, "\x82l"], "\xd1" => [18, "\x82l"], "\xd2" => [77, "\x82m"], "\xd3" => [18, "\x82m"], "\xd4" => [77, "\x82n"], "\xd5" => [18, "\x82n"], "\xd6" => [77, "\x82p"], "\xd7" => [18, "\x82p"], "\xd8" => [77, "\x82r"], "\xd9" => [18, "\x82r"], "\xda" => [77, "\x82u"], "\xdb" => [18, "\x82u"], "\xdc" => [0, "\x82:"], "\xdd" => [0, "\x82B"], "\xde" => [0, "\x82C"], "\xdf" => [0, "\x82D"], "\xe0" => [0, "\x82E"], "\xe1" => [0, "\x82F"], "\xe2" => [0, "\x82G"], "\xe3" => [0, "\x82H"], "\xe4" => [0, "\x82I"], "\xe5" => [0, "\x82J"], "\xe6" => [0, "\x82K"], "\xe7" => [0, "\x82L"], "\xe8" => [0, "\x82M"], "\xe9" => [0, "\x82N"], "\xea" => [0, "\x82O"], "\xeb" => [0, "\x82P"], "\xec" => [0, "\x82Q"], "\xed" => [0, "\x82R"], "\xee" => [0, "\x82S"], "\xef" => [0, "\x82T"], "\xf0" => [0, "\x82U"], "\xf1" => [0, "\x82V"], "\xf2" => [0, "\x82W"], "\xf3" => [0, "\x82Y"], "\xf4" => [0, "\x82j"], "\xf5" => [0, "\x82k"], "\xf6" => [0, "\x82q"], "\xf7" => [0, "\x82v"], "\xf8" => [0, "\x82w"], "\xf9" => [0, "\x82x"], "\xfa" => [0, "\x82y"], "\xfb" => [0, "\x82z"], "\xfc" => [82, "\x82"], "\xfd" => [87, "\x82"], "\xfe" => [130, "\x82"], "\xff" => [9, "\x82"]], ["\x00" => [94, "\xd00"], "\x01" => [76, "\xd00"], "\x02" => [104, "\xd00"], "\x03" => [16, "\xd00"], "\x04" => [94, "\xd01"], "\x05" => [76, "\xd01"], "\x06" => [104, "\xd01"], "\x07" => [16, "\xd01"], "\x08" => [94, "\xd02"], "\t" => [76, "\xd02"], "\n" => [104, "\xd02"], "\v" => [16, "\xd02"], "\f" => [94, "\xd0a"], "\r" => [76, "\xd0a"], "\x0e" => [104, "\xd0a"], "\x0f" => [16, "\xd0a"], "\x10" => [94, "\xd0c"], "\x11" => [76, "\xd0c"], "\x12" => [104, "\xd0c"], "\x13" => [16, "\xd0c"], "\x14" => [94, "\xd0e"], "\x15" => [76, "\xd0e"], "\x16" => [104, "\xd0e"], "\x17" => [16, "\xd0e"], "\x18" => [94, "\xd0i"], "\x19" => [76, "\xd0i"], "\x1a" => [104, "\xd0i"], "\x1b" => [16, "\xd0i"], "\x1c" => [94, "\xd0o"], "\x1d" => [76, "\xd0o"], "\x1e" => [104, "\xd0o"], "\x1f" => [16, "\xd0o"], " " => [94, "\xd0s"], "!" => [76, "\xd0s"], "\"" => [104, "\xd0s"], "#" => [16, "\xd0s"], "\$" => [94, "\xd0t"], "%" => [76, "\xd0t"], "&" => [104, "\xd0t"], "'" => [16, "\xd0t"], "(" => [77, "\xd0 "], ")" => [18, "\xd0 "], "*" => [77, "\xd0%"], "+" => [18, "\xd0%"], "," => [77, "\xd0-"], "-" => [18, "\xd0-"], "." => [77, "\xd0."], "/" => [18, "\xd0."], [77, "\xd0/"], [18, "\xd0/"], [77, "\xd03"], [18, "\xd03"], [77, "\xd04"], [18, "\xd04"], [77, "\xd05"], [18, "\xd05"], [77, "\xd06"], [18, "\xd06"], ":" => [77, "\xd07"], ";" => [18, "\xd07"], "<" => [77, "\xd08"], "=" => [18, "\xd08"], ">" => [77, "\xd09"], "?" => [18, "\xd09"], "@" => [77, "\xd0="], "A" => [18, "\xd0="], "B" => [77, "\xd0A"], "C" => [18, "\xd0A"], "D" => [77, "\xd0_"], "E" => [18, "\xd0_"], "F" => [77, "\xd0b"], "G" => [18, "\xd0b"], "H" => [77, "\xd0d"], "I" => [18, "\xd0d"], "J" => [77, "\xd0f"], "K" => [18, "\xd0f"], "L" => [77, "\xd0g"], "M" => [18, "\xd0g"], "N" => [77, "\xd0h"], "O" => [18, "\xd0h"], "P" => [77, "\xd0l"], "Q" => [18, "\xd0l"], "R" => [77, "\xd0m"], "S" => [18, "\xd0m"], "T" => [77, "\xd0n"], "U" => [18, "\xd0n"], "V" => [77, "\xd0p"], "W" => [18, "\xd0p"], "X" => [77, "\xd0r"], "Y" => [18, "\xd0r"], "Z" => [77, "\xd0u"], "[" => [18, "\xd0u"], "\\" => [0, "\xd0:"], "]" => [0, "\xd0B"], "^" => [0, "\xd0C"], "_" => [0, "\xd0D"], "`" => [0, "\xd0E"], "a" => [0, "\xd0F"], "b" => [0, "\xd0G"], "c" => [0, "\xd0H"], "d" => [0, "\xd0I"], "e" => [0, "\xd0J"], "f" => [0, "\xd0K"], "g" => [0, "\xd0L"], "h" => [0, "\xd0M"], "i" => [0, "\xd0N"], "j" => [0, "\xd0O"], "k" => [0, "\xd0P"], "l" => [0, "\xd0Q"], "m" => [0, "\xd0R"], "n" => [0, "\xd0S"], "o" => [0, "\xd0T"], "p" => [0, "\xd0U"], "q" => [0, "\xd0V"], "r" => [0, "\xd0W"], "s" => [0, "\xd0Y"], "t" => [0, "\xd0j"], "u" => [0, "\xd0k"], "v" => [0, "\xd0q"], "w" => [0, "\xd0v"], "x" => [0, "\xd0w"], "y" => [0, "\xd0x"], "z" => [0, "\xd0y"], "{" => [0, "\xd0z"], "|" => [82, "\xd0"], "}" => [87, "\xd0"], "~" => [130, "\xd0"], "" => [9, "\xd0"], "\x80" => [77, "\x800"], "\x81" => [18, "\x800"], "\x82" => [77, "\x801"], "\x83" => [18, "\x801"], "\x84" => [77, "\x802"], "\x85" => [18, "\x802"], "\x86" => [77, "\x80a"], "\x87" => [18, "\x80a"], "\x88" => [77, "\x80c"], "\x89" => [18, "\x80c"], "\x8a" => [77, "\x80e"], "\x8b" => [18, "\x80e"], "\x8c" => [77, "\x80i"], "\x8d" => [18, "\x80i"], "\x8e" => [77, "\x80o"], "\x8f" => [18, "\x80o"], "\x90" => [77, "\x80s"], "\x91" => [18, "\x80s"], "\x92" => [77, "\x80t"], "\x93" => [18, "\x80t"], "\x94" => [0, "\x80 "], "\x95" => [0, "\x80%"], "\x96" => [0, "\x80-"], "\x97" => [0, "\x80."], "\x98" => [0, "\x80/"], "\x99" => [0, "\x803"], "\x9a" => [0, "\x804"], "\x9b" => [0, "\x805"], "\x9c" => [0, "\x806"], "\x9d" => [0, "\x807"], "\x9e" => [0, "\x808"], "\x9f" => [0, "\x809"], "\xa0" => [0, "\x80="], "\xa1" => [0, "\x80A"], "\xa2" => [0, "\x80_"], "\xa3" => [0, "\x80b"], "\xa4" => [0, "\x80d"], "\xa5" => [0, "\x80f"], "\xa6" => [0, "\x80g"], "\xa7" => [0, "\x80h"], "\xa8" => [0, "\x80l"], "\xa9" => [0, "\x80m"], "\xaa" => [0, "\x80n"], "\xab" => [0, "\x80p"], "\xac" => [0, "\x80r"], "\xad" => [0, "\x80u"], "\xae" => [100, "\x80"], "\xaf" => [110, "\x80"], "\xb0" => [111, "\x80"], "\xb1" => [115, "\x80"], "\xb2" => [116, "\x80"], "\xb3" => [118, "\x80"], "\xb4" => [119, "\x80"], "\xb5" => [122, "\x80"], "\xb6" => [123, "\x80"], "\xb7" => [125, "\x80"], "\xb8" => [126, "\x80"], "\xb9" => [129, "\x80"], "\xba" => [143, "\x80"], "\xbb" => [148, "\x80"], "\xbc" => [151, "\x80"], "\xbd" => [153, "\x80"], "\xbe" => [83, "\x80"], "\xbf" => [10, "\x80"], "\xc0" => [77, "\x820"], "\xc1" => [18, "\x820"], "\xc2" => [77, "\x821"], "\xc3" => [18, "\x821"], "\xc4" => [77, "\x822"], "\xc5" => [18, "\x822"], "\xc6" => [77, "\x82a"], "\xc7" => [18, "\x82a"], "\xc8" => [77, "\x82c"], "\xc9" => [18, "\x82c"], "\xca" => [77, "\x82e"], "\xcb" => [18, "\x82e"], "\xcc" => [77, "\x82i"], "\xcd" => [18, "\x82i"], "\xce" => [77, "\x82o"], "\xcf" => [18, "\x82o"], "\xd0" => [77, "\x82s"], "\xd1" => [18, "\x82s"], "\xd2" => [77, "\x82t"], "\xd3" => [18, "\x82t"], "\xd4" => [0, "\x82 "], "\xd5" => [0, "\x82%"], "\xd6" => [0, "\x82-"], "\xd7" => [0, "\x82."], "\xd8" => [0, "\x82/"], "\xd9" => [0, "\x823"], "\xda" => [0, "\x824"], "\xdb" => [0, "\x825"], "\xdc" => [0, "\x826"], "\xdd" => [0, "\x827"], "\xde" => [0, "\x828"], "\xdf" => [0, "\x829"], "\xe0" => [0, "\x82="], "\xe1" => [0, "\x82A"], "\xe2" => [0, "\x82_"], "\xe3" => [0, "\x82b"], "\xe4" => [0, "\x82d"], "\xe5" => [0, "\x82f"], "\xe6" => [0, "\x82g"], "\xe7" => [0, "\x82h"], "\xe8" => [0, "\x82l"], "\xe9" => [0, "\x82m"], "\xea" => [0, "\x82n"], "\xeb" => [0, "\x82p"], "\xec" => [0, "\x82r"], "\xed" => [0, "\x82u"], "\xee" => [100, "\x82"], "\xef" => [110, "\x82"], "\xf0" => [111, "\x82"], "\xf1" => [115, "\x82"], "\xf2" => [116, "\x82"], "\xf3" => [118, "\x82"], "\xf4" => [119, "\x82"], "\xf5" => [122, "\x82"], "\xf6" => [123, "\x82"], "\xf7" => [125, "\x82"], "\xf8" => [126, "\x82"], "\xf9" => [129, "\x82"], "\xfa" => [143, "\x82"], "\xfb" => [148, "\x82"], "\xfc" => [151, "\x82"], "\xfd" => [153, "\x82"], "\xfe" => [83, "\x82"], "\xff" => [10, "\x82"]], ["\x00" => [94, "\x810"], "\x01" => [76, "\x810"], "\x02" => [104, "\x810"], "\x03" => [16, "\x810"], "\x04" => [94, "\x811"], "\x05" => [76, "\x811"], "\x06" => [104, "\x811"], "\x07" => [16, "\x811"], "\x08" => [94, "\x812"], "\t" => [76, "\x812"], "\n" => [104, "\x812"], "\v" => [16, "\x812"], "\f" => [94, "\x81a"], "\r" => [76, "\x81a"], "\x0e" => [104, "\x81a"], "\x0f" => [16, "\x81a"], "\x10" => [94, "\x81c"], "\x11" => [76, "\x81c"], "\x12" => [104, "\x81c"], "\x13" => [16, "\x81c"], "\x14" => [94, "\x81e"], "\x15" => [76, "\x81e"], "\x16" => [104, "\x81e"], "\x17" => [16, "\x81e"], "\x18" => [94, "\x81i"], "\x19" => [76, "\x81i"], "\x1a" => [104, "\x81i"], "\x1b" => [16, "\x81i"], "\x1c" => [94, "\x81o"], "\x1d" => [76, "\x81o"], "\x1e" => [104, "\x81o"], "\x1f" => [16, "\x81o"], " " => [94, "\x81s"], "!" => [76, "\x81s"], "\"" => [104, "\x81s"], "#" => [16, "\x81s"], "\$" => [94, "\x81t"], "%" => [76, "\x81t"], "&" => [104, "\x81t"], "'" => [16, "\x81t"], "(" => [77, "\x81 "], ")" => [18, "\x81 "], "*" => [77, "\x81%"], "+" => [18, "\x81%"], "," => [77, "\x81-"], "-" => [18, "\x81-"], "." => [77, "\x81."], "/" => [18, "\x81."], [77, "\x81/"], [18, "\x81/"], [77, "\x813"], [18, "\x813"], [77, "\x814"], [18, "\x814"], [77, "\x815"], [18, "\x815"], [77, "\x816"], [18, "\x816"], ":" => [77, "\x817"], ";" => [18, "\x817"], "<" => [77, "\x818"], "=" => [18, "\x818"], ">" => [77, "\x819"], "?" => [18, "\x819"], "@" => [77, "\x81="], "A" => [18, "\x81="], "B" => [77, "\x81A"], "C" => [18, "\x81A"], "D" => [77, "\x81_"], "E" => [18, "\x81_"], "F" => [77, "\x81b"], "G" => [18, "\x81b"], "H" => [77, "\x81d"], "I" => [18, "\x81d"], "J" => [77, "\x81f"], "K" => [18, "\x81f"], "L" => [77, "\x81g"], "M" => [18, "\x81g"], "N" => [77, "\x81h"], "O" => [18, "\x81h"], "P" => [77, "\x81l"], "Q" => [18, "\x81l"], "R" => [77, "\x81m"], "S" => [18, "\x81m"], "T" => [77, "\x81n"], "U" => [18, "\x81n"], "V" => [77, "\x81p"], "W" => [18, "\x81p"], "X" => [77, "\x81r"], "Y" => [18, "\x81r"], "Z" => [77, "\x81u"], "[" => [18, "\x81u"], "\\" => [0, "\x81:"], "]" => [0, "\x81B"], "^" => [0, "\x81C"], "_" => [0, "\x81D"], "`" => [0, "\x81E"], "a" => [0, "\x81F"], "b" => [0, "\x81G"], "c" => [0, "\x81H"], "d" => [0, "\x81I"], "e" => [0, "\x81J"], "f" => [0, "\x81K"], "g" => [0, "\x81L"], "h" => [0, "\x81M"], "i" => [0, "\x81N"], "j" => [0, "\x81O"], "k" => [0, "\x81P"], "l" => [0, "\x81Q"], "m" => [0, "\x81R"], "n" => [0, "\x81S"], "o" => [0, "\x81T"], "p" => [0, "\x81U"], "q" => [0, "\x81V"], "r" => [0, "\x81W"], "s" => [0, "\x81Y"], "t" => [0, "\x81j"], "u" => [0, "\x81k"], "v" => [0, "\x81q"], "w" => [0, "\x81v"], "x" => [0, "\x81w"], "y" => [0, "\x81x"], "z" => [0, "\x81y"], "{" => [0, "\x81z"], "|" => [82, "\x81"], "}" => [87, "\x81"], "~" => [130, "\x81"], "" => [9, "\x81"], "\x80" => [94, "\x840"], "\x81" => [76, "\x840"], "\x82" => [104, "\x840"], "\x83" => [16, "\x840"], "\x84" => [94, "\x841"], "\x85" => [76, "\x841"], "\x86" => [104, "\x841"], "\x87" => [16, "\x841"], "\x88" => [94, "\x842"], "\x89" => [76, "\x842"], "\x8a" => [104, "\x842"], "\x8b" => [16, "\x842"], "\x8c" => [94, "\x84a"], "\x8d" => [76, "\x84a"], "\x8e" => [104, "\x84a"], "\x8f" => [16, "\x84a"], "\x90" => [94, "\x84c"], "\x91" => [76, "\x84c"], "\x92" => [104, "\x84c"], "\x93" => [16, "\x84c"], "\x94" => [94, "\x84e"], "\x95" => [76, "\x84e"], "\x96" => [104, "\x84e"], "\x97" => [16, "\x84e"], "\x98" => [94, "\x84i"], "\x99" => [76, "\x84i"], "\x9a" => [104, "\x84i"], "\x9b" => [16, "\x84i"], "\x9c" => [94, "\x84o"], "\x9d" => [76, "\x84o"], "\x9e" => [104, "\x84o"], "\x9f" => [16, "\x84o"], "\xa0" => [94, "\x84s"], "\xa1" => [76, "\x84s"], "\xa2" => [104, "\x84s"], "\xa3" => [16, "\x84s"], "\xa4" => [94, "\x84t"], "\xa5" => [76, "\x84t"], "\xa6" => [104, "\x84t"], "\xa7" => [16, "\x84t"], "\xa8" => [77, "\x84 "], "\xa9" => [18, "\x84 "], "\xaa" => [77, "\x84%"], "\xab" => [18, "\x84%"], "\xac" => [77, "\x84-"], "\xad" => [18, "\x84-"], "\xae" => [77, "\x84."], "\xaf" => [18, "\x84."], "\xb0" => [77, "\x84/"], "\xb1" => [18, "\x84/"], "\xb2" => [77, "\x843"], "\xb3" => [18, "\x843"], "\xb4" => [77, "\x844"], "\xb5" => [18, "\x844"], "\xb6" => [77, "\x845"], "\xb7" => [18, "\x845"], "\xb8" => [77, "\x846"], "\xb9" => [18, "\x846"], "\xba" => [77, "\x847"], "\xbb" => [18, "\x847"], "\xbc" => [77, "\x848"], "\xbd" => [18, "\x848"], "\xbe" => [77, "\x849"], "\xbf" => [18, "\x849"], "\xc0" => [77, "\x84="], "\xc1" => [18, "\x84="], "\xc2" => [77, "\x84A"], "\xc3" => [18, "\x84A"], "\xc4" => [77, "\x84_"], "\xc5" => [18, "\x84_"], "\xc6" => [77, "\x84b"], "\xc7" => [18, "\x84b"], "\xc8" => [77, "\x84d"], "\xc9" => [18, "\x84d"], "\xca" => [77, "\x84f"], "\xcb" => [18, "\x84f"], "\xcc" => [77, "\x84g"], "\xcd" => [18, "\x84g"], "\xce" => [77, "\x84h"], "\xcf" => [18, "\x84h"], "\xd0" => [77, "\x84l"], "\xd1" => [18, "\x84l"], "\xd2" => [77, "\x84m"], "\xd3" => [18, "\x84m"], "\xd4" => [77, "\x84n"], "\xd5" => [18, "\x84n"], "\xd6" => [77, "\x84p"], "\xd7" => [18, "\x84p"], "\xd8" => [77, "\x84r"], "\xd9" => [18, "\x84r"], "\xda" => [77, "\x84u"], "\xdb" => [18, "\x84u"], "\xdc" => [0, "\x84:"], "\xdd" => [0, "\x84B"], "\xde" => [0, "\x84C"], "\xdf" => [0, "\x84D"], "\xe0" => [0, "\x84E"], "\xe1" => [0, "\x84F"], "\xe2" => [0, "\x84G"], "\xe3" => [0, "\x84H"], "\xe4" => [0, "\x84I"], "\xe5" => [0, "\x84J"], "\xe6" => [0, "\x84K"], "\xe7" => [0, "\x84L"], "\xe8" => [0, "\x84M"], "\xe9" => [0, "\x84N"], "\xea" => [0, "\x84O"], "\xeb" => [0, "\x84P"], "\xec" => [0, "\x84Q"], "\xed" => [0, "\x84R"], "\xee" => [0, "\x84S"], "\xef" => [0, "\x84T"], "\xf0" => [0, "\x84U"], "\xf1" => [0, "\x84V"], "\xf2" => [0, "\x84W"], "\xf3" => [0, "\x84Y"], "\xf4" => [0, "\x84j"], "\xf5" => [0, "\x84k"], "\xf6" => [0, "\x84q"], "\xf7" => [0, "\x84v"], "\xf8" => [0, "\x84w"], "\xf9" => [0, "\x84x"], "\xfa" => [0, "\x84y"], "\xfb" => [0, "\x84z"], "\xfc" => [82, "\x84"], "\xfd" => [87, "\x84"], "\xfe" => [130, "\x84"], "\xff" => [9, "\x84"]], ["\x00" => [94, "\xe60"], "\x01" => [76, "\xe60"], "\x02" => [104, "\xe60"], "\x03" => [16, "\xe60"], "\x04" => [94, "\xe61"], "\x05" => [76, "\xe61"], "\x06" => [104, "\xe61"], "\x07" => [16, "\xe61"], "\x08" => [94, "\xe62"], "\t" => [76, "\xe62"], "\n" => [104, "\xe62"], "\v" => [16, "\xe62"], "\f" => [94, "\xe6a"], "\r" => [76, "\xe6a"], "\x0e" => [104, "\xe6a"], "\x0f" => [16, "\xe6a"], "\x10" => [94, "\xe6c"], "\x11" => [76, "\xe6c"], "\x12" => [104, "\xe6c"], "\x13" => [16, "\xe6c"], "\x14" => [94, "\xe6e"], "\x15" => [76, "\xe6e"], "\x16" => [104, "\xe6e"], "\x17" => [16, "\xe6e"], "\x18" => [94, "\xe6i"], "\x19" => [76, "\xe6i"], "\x1a" => [104, "\xe6i"], "\x1b" => [16, "\xe6i"], "\x1c" => [94, "\xe6o"], "\x1d" => [76, "\xe6o"], "\x1e" => [104, "\xe6o"], "\x1f" => [16, "\xe6o"], " " => [94, "\xe6s"], "!" => [76, "\xe6s"], "\"" => [104, "\xe6s"], "#" => [16, "\xe6s"], "\$" => [94, "\xe6t"], "%" => [76, "\xe6t"], "&" => [104, "\xe6t"], "'" => [16, "\xe6t"], "(" => [77, "\xe6 "], ")" => [18, "\xe6 "], "*" => [77, "\xe6%"], "+" => [18, "\xe6%"], "," => [77, "\xe6-"], "-" => [18, "\xe6-"], "." => [77, "\xe6."], "/" => [18, "\xe6."], [77, "\xe6/"], [18, "\xe6/"], [77, "\xe63"], [18, "\xe63"], [77, "\xe64"], [18, "\xe64"], [77, "\xe65"], [18, "\xe65"], [77, "\xe66"], [18, "\xe66"], ":" => [77, "\xe67"], ";" => [18, "\xe67"], "<" => [77, "\xe68"], "=" => [18, "\xe68"], ">" => [77, "\xe69"], "?" => [18, "\xe69"], "@" => [77, "\xe6="], "A" => [18, "\xe6="], "B" => [77, "\xe6A"], "C" => [18, "\xe6A"], "D" => [77, "\xe6_"], "E" => [18, "\xe6_"], "F" => [77, "\xe6b"], "G" => [18, "\xe6b"], "H" => [77, "\xe6d"], "I" => [18, "\xe6d"], "J" => [77, "\xe6f"], "K" => [18, "\xe6f"], "L" => [77, "\xe6g"], "M" => [18, "\xe6g"], "N" => [77, "\xe6h"], "O" => [18, "\xe6h"], "P" => [77, "\xe6l"], "Q" => [18, "\xe6l"], "R" => [77, "\xe6m"], "S" => [18, "\xe6m"], "T" => [77, "\xe6n"], "U" => [18, "\xe6n"], "V" => [77, "\xe6p"], "W" => [18, "\xe6p"], "X" => [77, "\xe6r"], "Y" => [18, "\xe6r"], "Z" => [77, "\xe6u"], "[" => [18, "\xe6u"], "\\" => [0, "\xe6:"], "]" => [0, "\xe6B"], "^" => [0, "\xe6C"], "_" => [0, "\xe6D"], "`" => [0, "\xe6E"], "a" => [0, "\xe6F"], "b" => [0, "\xe6G"], "c" => [0, "\xe6H"], "d" => [0, "\xe6I"], "e" => [0, "\xe6J"], "f" => [0, "\xe6K"], "g" => [0, "\xe6L"], "h" => [0, "\xe6M"], "i" => [0, "\xe6N"], "j" => [0, "\xe6O"], "k" => [0, "\xe6P"], "l" => [0, "\xe6Q"], "m" => [0, "\xe6R"], "n" => [0, "\xe6S"], "o" => [0, "\xe6T"], "p" => [0, "\xe6U"], "q" => [0, "\xe6V"], "r" => [0, "\xe6W"], "s" => [0, "\xe6Y"], "t" => [0, "\xe6j"], "u" => [0, "\xe6k"], "v" => [0, "\xe6q"], "w" => [0, "\xe6v"], "x" => [0, "\xe6w"], "y" => [0, "\xe6x"], "z" => [0, "\xe6y"], "{" => [0, "\xe6z"], "|" => [82, "\xe6"], "}" => [87, "\xe6"], "~" => [130, "\xe6"], "" => [9, "\xe6"], "\x80" => [77, "\x810"], "\x81" => [18, "\x810"], "\x82" => [77, "\x811"], "\x83" => [18, "\x811"], "\x84" => [77, "\x812"], "\x85" => [18, "\x812"], "\x86" => [77, "\x81a"], "\x87" => [18, "\x81a"], "\x88" => [77, "\x81c"], "\x89" => [18, "\x81c"], "\x8a" => [77, "\x81e"], "\x8b" => [18, "\x81e"], "\x8c" => [77, "\x81i"], "\x8d" => [18, "\x81i"], "\x8e" => [77, "\x81o"], "\x8f" => [18, "\x81o"], "\x90" => [77, "\x81s"], "\x91" => [18, "\x81s"], "\x92" => [77, "\x81t"], "\x93" => [18, "\x81t"], "\x94" => [0, "\x81 "], "\x95" => [0, "\x81%"], "\x96" => [0, "\x81-"], "\x97" => [0, "\x81."], "\x98" => [0, "\x81/"], "\x99" => [0, "\x813"], "\x9a" => [0, "\x814"], "\x9b" => [0, "\x815"], "\x9c" => [0, "\x816"], "\x9d" => [0, "\x817"], "\x9e" => [0, "\x818"], "\x9f" => [0, "\x819"], "\xa0" => [0, "\x81="], "\xa1" => [0, "\x81A"], "\xa2" => [0, "\x81_"], "\xa3" => [0, "\x81b"], "\xa4" => [0, "\x81d"], "\xa5" => [0, "\x81f"], "\xa6" => [0, "\x81g"], "\xa7" => [0, "\x81h"], "\xa8" => [0, "\x81l"], "\xa9" => [0, "\x81m"], "\xaa" => [0, "\x81n"], "\xab" => [0, "\x81p"], "\xac" => [0, "\x81r"], "\xad" => [0, "\x81u"], "\xae" => [100, "\x81"], "\xaf" => [110, "\x81"], "\xb0" => [111, "\x81"], "\xb1" => [115, "\x81"], "\xb2" => [116, "\x81"], "\xb3" => [118, "\x81"], "\xb4" => [119, "\x81"], "\xb5" => [122, "\x81"], "\xb6" => [123, "\x81"], "\xb7" => [125, "\x81"], "\xb8" => [126, "\x81"], "\xb9" => [129, "\x81"], "\xba" => [143, "\x81"], "\xbb" => [148, "\x81"], "\xbc" => [151, "\x81"], "\xbd" => [153, "\x81"], "\xbe" => [83, "\x81"], "\xbf" => [10, "\x81"], "\xc0" => [77, "\x840"], "\xc1" => [18, "\x840"], "\xc2" => [77, "\x841"], "\xc3" => [18, "\x841"], "\xc4" => [77, "\x842"], "\xc5" => [18, "\x842"], "\xc6" => [77, "\x84a"], "\xc7" => [18, "\x84a"], "\xc8" => [77, "\x84c"], "\xc9" => [18, "\x84c"], "\xca" => [77, "\x84e"], "\xcb" => [18, "\x84e"], "\xcc" => [77, "\x84i"], "\xcd" => [18, "\x84i"], "\xce" => [77, "\x84o"], "\xcf" => [18, "\x84o"], "\xd0" => [77, "\x84s"], "\xd1" => [18, "\x84s"], "\xd2" => [77, "\x84t"], "\xd3" => [18, "\x84t"], "\xd4" => [0, "\x84 "], "\xd5" => [0, "\x84%"], "\xd6" => [0, "\x84-"], "\xd7" => [0, "\x84."], "\xd8" => [0, "\x84/"], "\xd9" => [0, "\x843"], "\xda" => [0, "\x844"], "\xdb" => [0, "\x845"], "\xdc" => [0, "\x846"], "\xdd" => [0, "\x847"], "\xde" => [0, "\x848"], "\xdf" => [0, "\x849"], "\xe0" => [0, "\x84="], "\xe1" => [0, "\x84A"], "\xe2" => [0, "\x84_"], "\xe3" => [0, "\x84b"], "\xe4" => [0, "\x84d"], "\xe5" => [0, "\x84f"], "\xe6" => [0, "\x84g"], "\xe7" => [0, "\x84h"], "\xe8" => [0, "\x84l"], "\xe9" => [0, "\x84m"], "\xea" => [0, "\x84n"], "\xeb" => [0, "\x84p"], "\xec" => [0, "\x84r"], "\xed" => [0, "\x84u"], "\xee" => [100, "\x84"], "\xef" => [110, "\x84"], "\xf0" => [111, "\x84"], "\xf1" => [115, "\x84"], "\xf2" => [116, "\x84"], "\xf3" => [118, "\x84"], "\xf4" => [119, "\x84"], "\xf5" => [122, "\x84"], "\xf6" => [123, "\x84"], "\xf7" => [125, "\x84"], "\xf8" => [126, "\x84"], "\xf9" => [129, "\x84"], "\xfa" => [143, "\x84"], "\xfb" => [148, "\x84"], "\xfc" => [151, "\x84"], "\xfd" => [153, "\x84"], "\xfe" => [83, "\x84"], "\xff" => [10, "\x84"]], ["\x00" => [77, "\xe60"], "\x01" => [18, "\xe60"], "\x02" => [77, "\xe61"], "\x03" => [18, "\xe61"], "\x04" => [77, "\xe62"], "\x05" => [18, "\xe62"], "\x06" => [77, "\xe6a"], "\x07" => [18, "\xe6a"], "\x08" => [77, "\xe6c"], "\t" => [18, "\xe6c"], "\n" => [77, "\xe6e"], "\v" => [18, "\xe6e"], "\f" => [77, "\xe6i"], "\r" => [18, "\xe6i"], "\x0e" => [77, "\xe6o"], "\x0f" => [18, "\xe6o"], "\x10" => [77, "\xe6s"], "\x11" => [18, "\xe6s"], "\x12" => [77, "\xe6t"], "\x13" => [18, "\xe6t"], "\x14" => [0, "\xe6 "], "\x15" => [0, "\xe6%"], "\x16" => [0, "\xe6-"], "\x17" => [0, "\xe6."], "\x18" => [0, "\xe6/"], "\x19" => [0, "\xe63"], "\x1a" => [0, "\xe64"], "\x1b" => [0, "\xe65"], "\x1c" => [0, "\xe66"], "\x1d" => [0, "\xe67"], "\x1e" => [0, "\xe68"], "\x1f" => [0, "\xe69"], " " => [0, "\xe6="], "!" => [0, "\xe6A"], "\"" => [0, "\xe6_"], "#" => [0, "\xe6b"], "\$" => [0, "\xe6d"], "%" => [0, "\xe6f"], "&" => [0, "\xe6g"], "'" => [0, "\xe6h"], "(" => [0, "\xe6l"], ")" => [0, "\xe6m"], "*" => [0, "\xe6n"], "+" => [0, "\xe6p"], "," => [0, "\xe6r"], "-" => [0, "\xe6u"], "." => [100, "\xe6"], "/" => [110, "\xe6"], [111, "\xe6"], [115, "\xe6"], [116, "\xe6"], [118, "\xe6"], [119, "\xe6"], [122, "\xe6"], [123, "\xe6"], [125, "\xe6"], [126, "\xe6"], [129, "\xe6"], ":" => [143, "\xe6"], ";" => [148, "\xe6"], "<" => [151, "\xe6"], "=" => [153, "\xe6"], ">" => [83, "\xe6"], "?" => [10, "\xe6"], "@" => [0, "\x810"], "A" => [0, "\x811"], "B" => [0, "\x812"], "C" => [0, "\x81a"], "D" => [0, "\x81c"], "E" => [0, "\x81e"], "F" => [0, "\x81i"], "G" => [0, "\x81o"], "H" => [0, "\x81s"], "I" => [0, "\x81t"], "J" => [73, "\x81"], "K" => [88, "\x81"], "L" => [89, "\x81"], "M" => [96, "\x81"], "N" => [97, "\x81"], "O" => [99, "\x81"], "P" => [106, "\x81"], "Q" => [136, "\x81"], "R" => [139, "\x81"], "S" => [141, "\x81"], "T" => [145, "\x81"], "U" => [147, "\x81"], "V" => [149, "\x81"], "W" => [101, "\x81"], "X" => [112, "\x81"], "Y" => [117, "\x81"], "Z" => [120, "\x81"], "[" => [124, "\x81"], "\\" => [127, "\x81"], "]" => [144, "\x81"], "^" => [152, "\x81"], "_" => [11, "\x81"], "`" => [0, "\x840"], "a" => [0, "\x841"], "b" => [0, "\x842"], "c" => [0, "\x84a"], "d" => [0, "\x84c"], "e" => [0, "\x84e"], "f" => [0, "\x84i"], "g" => [0, "\x84o"], "h" => [0, "\x84s"], "i" => [0, "\x84t"], "j" => [73, "\x84"], "k" => [88, "\x84"], "l" => [89, "\x84"], "m" => [96, "\x84"], "n" => [97, "\x84"], "o" => [99, "\x84"], "p" => [106, "\x84"], "q" => [136, "\x84"], "r" => [139, "\x84"], "s" => [141, "\x84"], "t" => [145, "\x84"], "u" => [147, "\x84"], "v" => [149, "\x84"], "w" => [101, "\x84"], "x" => [112, "\x84"], "y" => [117, "\x84"], "z" => [120, "\x84"], "{" => [124, "\x84"], "|" => [127, "\x84"], "}" => [144, "\x84"], "~" => [152, "\x84"], "" => [11, "\x84"], "\x80" => [0, "\x850"], "\x81" => [0, "\x851"], "\x82" => [0, "\x852"], "\x83" => [0, "\x85a"], "\x84" => [0, "\x85c"], "\x85" => [0, "\x85e"], "\x86" => [0, "\x85i"], "\x87" => [0, "\x85o"], "\x88" => [0, "\x85s"], "\x89" => [0, "\x85t"], "\x8a" => [73, "\x85"], "\x8b" => [88, "\x85"], "\x8c" => [89, "\x85"], "\x8d" => [96, "\x85"], "\x8e" => [97, "\x85"], "\x8f" => [99, "\x85"], "\x90" => [106, "\x85"], "\x91" => [136, "\x85"], "\x92" => [139, "\x85"], "\x93" => [141, "\x85"], "\x94" => [145, "\x85"], "\x95" => [147, "\x85"], "\x96" => [149, "\x85"], "\x97" => [101, "\x85"], "\x98" => [112, "\x85"], "\x99" => [117, "\x85"], "\x9a" => [120, "\x85"], "\x9b" => [124, "\x85"], "\x9c" => [127, "\x85"], "\x9d" => [144, "\x85"], "\x9e" => [152, "\x85"], "\x9f" => [11, "\x85"], "\xa0" => [0, "\x860"], "\xa1" => [0, "\x861"], "\xa2" => [0, "\x862"], "\xa3" => [0, "\x86a"], "\xa4" => [0, "\x86c"], "\xa5" => [0, "\x86e"], "\xa6" => [0, "\x86i"], "\xa7" => [0, "\x86o"], "\xa8" => [0, "\x86s"], "\xa9" => [0, "\x86t"], "\xaa" => [73, "\x86"], "\xab" => [88, "\x86"], "\xac" => [89, "\x86"], "\xad" => [96, "\x86"], "\xae" => [97, "\x86"], "\xaf" => [99, "\x86"], "\xb0" => [106, "\x86"], "\xb1" => [136, "\x86"], "\xb2" => [139, "\x86"], "\xb3" => [141, "\x86"], "\xb4" => [145, "\x86"], "\xb5" => [147, "\x86"], "\xb6" => [149, "\x86"], "\xb7" => [101, "\x86"], "\xb8" => [112, "\x86"], "\xb9" => [117, "\x86"], "\xba" => [120, "\x86"], "\xbb" => [124, "\x86"], "\xbc" => [127, "\x86"], "\xbd" => [144, "\x86"], "\xbe" => [152, "\x86"], "\xbf" => [11, "\x86"], "\xc0" => [0, "\x880"], "\xc1" => [0, "\x881"], "\xc2" => [0, "\x882"], "\xc3" => [0, "\x88a"], "\xc4" => [0, "\x88c"], "\xc5" => [0, "\x88e"], "\xc6" => [0, "\x88i"], "\xc7" => [0, "\x88o"], "\xc8" => [0, "\x88s"], "\xc9" => [0, "\x88t"], "\xca" => [73, "\x88"], "\xcb" => [88, "\x88"], "\xcc" => [89, "\x88"], "\xcd" => [96, "\x88"], "\xce" => [97, "\x88"], "\xcf" => [99, "\x88"], "\xd0" => [106, "\x88"], "\xd1" => [136, "\x88"], "\xd2" => [139, "\x88"], "\xd3" => [141, "\x88"], "\xd4" => [145, "\x88"], "\xd5" => [147, "\x88"], "\xd6" => [149, "\x88"], "\xd7" => [101, "\x88"], "\xd8" => [112, "\x88"], "\xd9" => [117, "\x88"], "\xda" => [120, "\x88"], "\xdb" => [124, "\x88"], "\xdc" => [127, "\x88"], "\xdd" => [144, "\x88"], "\xde" => [152, "\x88"], "\xdf" => [11, "\x88"], "\xe0" => [0, "\x920"], "\xe1" => [0, "\x921"], "\xe2" => [0, "\x922"], "\xe3" => [0, "\x92a"], "\xe4" => [0, "\x92c"], "\xe5" => [0, "\x92e"], "\xe6" => [0, "\x92i"], "\xe7" => [0, "\x92o"], "\xe8" => [0, "\x92s"], "\xe9" => [0, "\x92t"], "\xea" => [73, "\x92"], "\xeb" => [88, "\x92"], "\xec" => [89, "\x92"], "\xed" => [96, "\x92"], "\xee" => [97, "\x92"], "\xef" => [99, "\x92"], "\xf0" => [106, "\x92"], "\xf1" => [136, "\x92"], "\xf2" => [139, "\x92"], "\xf3" => [141, "\x92"], "\xf4" => [145, "\x92"], "\xf5" => [147, "\x92"], "\xf6" => [149, "\x92"], "\xf7" => [101, "\x92"], "\xf8" => [112, "\x92"], "\xf9" => [117, "\x92"], "\xfa" => [120, "\x92"], "\xfb" => [124, "\x92"], "\xfc" => [127, "\x92"], "\xfd" => [144, "\x92"], "\xfe" => [152, "\x92"], "\xff" => [11, "\x92"]], ["\x00" => [0, "\xe60"], "\x01" => [0, "\xe61"], "\x02" => [0, "\xe62"], "\x03" => [0, "\xe6a"], "\x04" => [0, "\xe6c"], "\x05" => [0, "\xe6e"], "\x06" => [0, "\xe6i"], "\x07" => [0, "\xe6o"], "\x08" => [0, "\xe6s"], "\t" => [0, "\xe6t"], "\n" => [73, "\xe6"], "\v" => [88, "\xe6"], "\f" => [89, "\xe6"], "\r" => [96, "\xe6"], "\x0e" => [97, "\xe6"], "\x0f" => [99, "\xe6"], "\x10" => [106, "\xe6"], "\x11" => [136, "\xe6"], "\x12" => [139, "\xe6"], "\x13" => [141, "\xe6"], "\x14" => [145, "\xe6"], "\x15" => [147, "\xe6"], "\x16" => [149, "\xe6"], "\x17" => [101, "\xe6"], "\x18" => [112, "\xe6"], "\x19" => [117, "\xe6"], "\x1a" => [120, "\xe6"], "\x1b" => [124, "\xe6"], "\x1c" => [127, "\xe6"], "\x1d" => [144, "\xe6"], "\x1e" => [152, "\xe6"], "\x1f" => [11, "\xe6"], " " => [92, "\x81"], "!" => [95, "\x81"], "\"" => [137, "\x81"], "#" => [142, "\x81"], "\$" => [150, "\x81"], "%" => [74, "\x81"], "&" => [90, "\x81"], "'" => [98, "\x81"], "(" => [107, "\x81"], ")" => [140, "\x81"], "*" => [146, "\x81"], "+" => [102, "\x81"], "," => [113, "\x81"], "-" => [121, "\x81"], "." => [128, "\x81"], "/" => [12, "\x81"], [92, "\x84"], [95, "\x84"], [137, "\x84"], [142, "\x84"], [150, "\x84"], [74, "\x84"], [90, "\x84"], [98, "\x84"], [107, "\x84"], [140, "\x84"], ":" => [146, "\x84"], ";" => [102, "\x84"], "<" => [113, "\x84"], "=" => [121, "\x84"], ">" => [128, "\x84"], "?" => [12, "\x84"], "@" => [92, "\x85"], "A" => [95, "\x85"], "B" => [137, "\x85"], "C" => [142, "\x85"], "D" => [150, "\x85"], "E" => [74, "\x85"], "F" => [90, "\x85"], "G" => [98, "\x85"], "H" => [107, "\x85"], "I" => [140, "\x85"], "J" => [146, "\x85"], "K" => [102, "\x85"], "L" => [113, "\x85"], "M" => [121, "\x85"], "N" => [128, "\x85"], "O" => [12, "\x85"], "P" => [92, "\x86"], "Q" => [95, "\x86"], "R" => [137, "\x86"], "S" => [142, "\x86"], "T" => [150, "\x86"], "U" => [74, "\x86"], "V" => [90, "\x86"], "W" => [98, "\x86"], "X" => [107, "\x86"], "Y" => [140, "\x86"], "Z" => [146, "\x86"], "[" => [102, "\x86"], "\\" => [113, "\x86"], "]" => [121, "\x86"], "^" => [128, "\x86"], "_" => [12, "\x86"], "`" => [92, "\x88"], "a" => [95, "\x88"], "b" => [137, "\x88"], "c" => [142, "\x88"], "d" => [150, "\x88"], "e" => [74, "\x88"], "f" => [90, "\x88"], "g" => [98, "\x88"], "h" => [107, "\x88"], "i" => [140, "\x88"], "j" => [146, "\x88"], "k" => [102, "\x88"], "l" => [113, "\x88"], "m" => [121, "\x88"], "n" => [128, "\x88"], "o" => [12, "\x88"], "p" => [92, "\x92"], "q" => [95, "\x92"], "r" => [137, "\x92"], "s" => [142, "\x92"], "t" => [150, "\x92"], "u" => [74, "\x92"], "v" => [90, "\x92"], "w" => [98, "\x92"], "x" => [107, "\x92"], "y" => [140, "\x92"], "z" => [146, "\x92"], "{" => [102, "\x92"], "|" => [113, "\x92"], "}" => [121, "\x92"], "~" => [128, "\x92"], "" => [12, "\x92"], "\x80" => [92, "\x9a"], "\x81" => [95, "\x9a"], "\x82" => [137, "\x9a"], "\x83" => [142, "\x9a"], "\x84" => [150, "\x9a"], "\x85" => [74, "\x9a"], "\x86" => [90, "\x9a"], "\x87" => [98, "\x9a"], "\x88" => [107, "\x9a"], "\x89" => [140, "\x9a"], "\x8a" => [146, "\x9a"], "\x8b" => [102, "\x9a"], "\x8c" => [113, "\x9a"], "\x8d" => [121, "\x9a"], "\x8e" => [128, "\x9a"], "\x8f" => [12, "\x9a"], "\x90" => [92, "\x9c"], "\x91" => [95, "\x9c"], "\x92" => [137, "\x9c"], "\x93" => [142, "\x9c"], "\x94" => [150, "\x9c"], "\x95" => [74, "\x9c"], "\x96" => [90, "\x9c"], "\x97" => [98, "\x9c"], "\x98" => [107, "\x9c"], "\x99" => [140, "\x9c"], "\x9a" => [146, "\x9c"], "\x9b" => [102, "\x9c"], "\x9c" => [113, "\x9c"], "\x9d" => [121, "\x9c"], "\x9e" => [128, "\x9c"], "\x9f" => [12, "\x9c"], "\xa0" => [92, "\xa0"], "\xa1" => [95, "\xa0"], "\xa2" => [137, "\xa0"], "\xa3" => [142, "\xa0"], "\xa4" => [150, "\xa0"], "\xa5" => [74, "\xa0"], "\xa6" => [90, "\xa0"], "\xa7" => [98, "\xa0"], "\xa8" => [107, "\xa0"], "\xa9" => [140, "\xa0"], "\xaa" => [146, "\xa0"], "\xab" => [102, "\xa0"], "\xac" => [113, "\xa0"], "\xad" => [121, "\xa0"], "\xae" => [128, "\xa0"], "\xaf" => [12, "\xa0"], "\xb0" => [92, "\xa3"], "\xb1" => [95, "\xa3"], "\xb2" => [137, "\xa3"], "\xb3" => [142, "\xa3"], "\xb4" => [150, "\xa3"], "\xb5" => [74, "\xa3"], "\xb6" => [90, "\xa3"], "\xb7" => [98, "\xa3"], "\xb8" => [107, "\xa3"], "\xb9" => [140, "\xa3"], "\xba" => [146, "\xa3"], "\xbb" => [102, "\xa3"], "\xbc" => [113, "\xa3"], "\xbd" => [121, "\xa3"], "\xbe" => [128, "\xa3"], "\xbf" => [12, "\xa3"], "\xc0" => [92, "\xa4"], "\xc1" => [95, "\xa4"], "\xc2" => [137, "\xa4"], "\xc3" => [142, "\xa4"], "\xc4" => [150, "\xa4"], "\xc5" => [74, "\xa4"], "\xc6" => [90, "\xa4"], "\xc7" => [98, "\xa4"], "\xc8" => [107, "\xa4"], "\xc9" => [140, "\xa4"], "\xca" => [146, "\xa4"], "\xcb" => [102, "\xa4"], "\xcc" => [113, "\xa4"], "\xcd" => [121, "\xa4"], "\xce" => [128, "\xa4"], "\xcf" => [12, "\xa4"], "\xd0" => [92, "\xa9"], "\xd1" => [95, "\xa9"], "\xd2" => [137, "\xa9"], "\xd3" => [142, "\xa9"], "\xd4" => [150, "\xa9"], "\xd5" => [74, "\xa9"], "\xd6" => [90, "\xa9"], "\xd7" => [98, "\xa9"], "\xd8" => [107, "\xa9"], "\xd9" => [140, "\xa9"], "\xda" => [146, "\xa9"], "\xdb" => [102, "\xa9"], "\xdc" => [113, "\xa9"], "\xdd" => [121, "\xa9"], "\xde" => [128, "\xa9"], "\xdf" => [12, "\xa9"], "\xe0" => [92, "\xaa"], "\xe1" => [95, "\xaa"], "\xe2" => [137, "\xaa"], "\xe3" => [142, "\xaa"], "\xe4" => [150, "\xaa"], "\xe5" => [74, "\xaa"], "\xe6" => [90, "\xaa"], "\xe7" => [98, "\xaa"], "\xe8" => [107, "\xaa"], "\xe9" => [140, "\xaa"], "\xea" => [146, "\xaa"], "\xeb" => [102, "\xaa"], "\xec" => [113, "\xaa"], "\xed" => [121, "\xaa"], "\xee" => [128, "\xaa"], "\xef" => [12, "\xaa"], "\xf0" => [92, "\xad"], "\xf1" => [95, "\xad"], "\xf2" => [137, "\xad"], "\xf3" => [142, "\xad"], "\xf4" => [150, "\xad"], "\xf5" => [74, "\xad"], "\xf6" => [90, "\xad"], "\xf7" => [98, "\xad"], "\xf8" => [107, "\xad"], "\xf9" => [140, "\xad"], "\xfa" => [146, "\xad"], "\xfb" => [102, "\xad"], "\xfc" => [113, "\xad"], "\xfd" => [121, "\xad"], "\xfe" => [128, "\xad"], "\xff" => [12, "\xad"]], ["\x00" => [92, "\xb0"], "\x01" => [95, "\xb0"], "\x02" => [137, "\xb0"], "\x03" => [142, "\xb0"], "\x04" => [150, "\xb0"], "\x05" => [74, "\xb0"], "\x06" => [90, "\xb0"], "\x07" => [98, "\xb0"], "\x08" => [107, "\xb0"], "\t" => [140, "\xb0"], "\n" => [146, "\xb0"], "\v" => [102, "\xb0"], "\f" => [113, "\xb0"], "\r" => [121, "\xb0"], "\x0e" => [128, "\xb0"], "\x0f" => [12, "\xb0"], "\x10" => [92, "\xb1"], "\x11" => [95, "\xb1"], "\x12" => [137, "\xb1"], "\x13" => [142, "\xb1"], "\x14" => [150, "\xb1"], "\x15" => [74, "\xb1"], "\x16" => [90, "\xb1"], "\x17" => [98, "\xb1"], "\x18" => [107, "\xb1"], "\x19" => [140, "\xb1"], "\x1a" => [146, "\xb1"], "\x1b" => [102, "\xb1"], "\x1c" => [113, "\xb1"], "\x1d" => [121, "\xb1"], "\x1e" => [128, "\xb1"], "\x1f" => [12, "\xb1"], " " => [92, "\xb3"], "!" => [95, "\xb3"], "\"" => [137, "\xb3"], "#" => [142, "\xb3"], "\$" => [150, "\xb3"], "%" => [74, "\xb3"], "&" => [90, "\xb3"], "'" => [98, "\xb3"], "(" => [107, "\xb3"], ")" => [140, "\xb3"], "*" => [146, "\xb3"], "+" => [102, "\xb3"], "," => [113, "\xb3"], "-" => [121, "\xb3"], "." => [128, "\xb3"], "/" => [12, "\xb3"], [92, "\xd1"], [95, "\xd1"], [137, "\xd1"], [142, "\xd1"], [150, "\xd1"], [74, "\xd1"], [90, "\xd1"], [98, "\xd1"], [107, "\xd1"], [140, "\xd1"], ":" => [146, "\xd1"], ";" => [102, "\xd1"], "<" => [113, "\xd1"], "=" => [121, "\xd1"], ">" => [128, "\xd1"], "?" => [12, "\xd1"], "@" => [92, "\xd8"], "A" => [95, "\xd8"], "B" => [137, "\xd8"], "C" => [142, "\xd8"], "D" => [150, "\xd8"], "E" => [74, "\xd8"], "F" => [90, "\xd8"], "G" => [98, "\xd8"], "H" => [107, "\xd8"], "I" => [140, "\xd8"], "J" => [146, "\xd8"], "K" => [102, "\xd8"], "L" => [113, "\xd8"], "M" => [121, "\xd8"], "N" => [128, "\xd8"], "O" => [12, "\xd8"], "P" => [92, "\xd9"], "Q" => [95, "\xd9"], "R" => [137, "\xd9"], "S" => [142, "\xd9"], "T" => [150, "\xd9"], "U" => [74, "\xd9"], "V" => [90, "\xd9"], "W" => [98, "\xd9"], "X" => [107, "\xd9"], "Y" => [140, "\xd9"], "Z" => [146, "\xd9"], "[" => [102, "\xd9"], "\\" => [113, "\xd9"], "]" => [121, "\xd9"], "^" => [128, "\xd9"], "_" => [12, "\xd9"], "`" => [92, "\xe3"], "a" => [95, "\xe3"], "b" => [137, "\xe3"], "c" => [142, "\xe3"], "d" => [150, "\xe3"], "e" => [74, "\xe3"], "f" => [90, "\xe3"], "g" => [98, "\xe3"], "h" => [107, "\xe3"], "i" => [140, "\xe3"], "j" => [146, "\xe3"], "k" => [102, "\xe3"], "l" => [113, "\xe3"], "m" => [121, "\xe3"], "n" => [128, "\xe3"], "o" => [12, "\xe3"], "p" => [92, "\xe5"], "q" => [95, "\xe5"], "r" => [137, "\xe5"], "s" => [142, "\xe5"], "t" => [150, "\xe5"], "u" => [74, "\xe5"], "v" => [90, "\xe5"], "w" => [98, "\xe5"], "x" => [107, "\xe5"], "y" => [140, "\xe5"], "z" => [146, "\xe5"], "{" => [102, "\xe5"], "|" => [113, "\xe5"], "}" => [121, "\xe5"], "~" => [128, "\xe5"], "" => [12, "\xe5"], "\x80" => [92, "\xe6"], "\x81" => [95, "\xe6"], "\x82" => [137, "\xe6"], "\x83" => [142, "\xe6"], "\x84" => [150, "\xe6"], "\x85" => [74, "\xe6"], "\x86" => [90, "\xe6"], "\x87" => [98, "\xe6"], "\x88" => [107, "\xe6"], "\x89" => [140, "\xe6"], "\x8a" => [146, "\xe6"], "\x8b" => [102, "\xe6"], "\x8c" => [113, "\xe6"], "\x8d" => [121, "\xe6"], "\x8e" => [128, "\xe6"], "\x8f" => [12, "\xe6"], "\x90" => [93, "\x81"], "\x91" => [138, "\x81"], "\x92" => [75, "\x81"], "\x93" => [91, "\x81"], "\x94" => [108, "\x81"], "\x95" => [103, "\x81"], "\x96" => [114, "\x81"], "\x97" => [14, "\x81"], "\x98" => [93, "\x84"], "\x99" => [138, "\x84"], "\x9a" => [75, "\x84"], "\x9b" => [91, "\x84"], "\x9c" => [108, "\x84"], "\x9d" => [103, "\x84"], "\x9e" => [114, "\x84"], "\x9f" => [14, "\x84"], "\xa0" => [93, "\x85"], "\xa1" => [138, "\x85"], "\xa2" => [75, "\x85"], "\xa3" => [91, "\x85"], "\xa4" => [108, "\x85"], "\xa5" => [103, "\x85"], "\xa6" => [114, "\x85"], "\xa7" => [14, "\x85"], "\xa8" => [93, "\x86"], "\xa9" => [138, "\x86"], "\xaa" => [75, "\x86"], "\xab" => [91, "\x86"], "\xac" => [108, "\x86"], "\xad" => [103, "\x86"], "\xae" => [114, "\x86"], "\xaf" => [14, "\x86"], "\xb0" => [93, "\x88"], "\xb1" => [138, "\x88"], "\xb2" => [75, "\x88"], "\xb3" => [91, "\x88"], "\xb4" => [108, "\x88"], "\xb5" => [103, "\x88"], "\xb6" => [114, "\x88"], "\xb7" => [14, "\x88"], "\xb8" => [93, "\x92"], "\xb9" => [138, "\x92"], "\xba" => [75, "\x92"], "\xbb" => [91, "\x92"], "\xbc" => [108, "\x92"], "\xbd" => [103, "\x92"], "\xbe" => [114, "\x92"], "\xbf" => [14, "\x92"], "\xc0" => [93, "\x9a"], "\xc1" => [138, "\x9a"], "\xc2" => [75, "\x9a"], "\xc3" => [91, "\x9a"], "\xc4" => [108, "\x9a"], "\xc5" => [103, "\x9a"], "\xc6" => [114, "\x9a"], "\xc7" => [14, "\x9a"], "\xc8" => [93, "\x9c"], "\xc9" => [138, "\x9c"], "\xca" => [75, "\x9c"], "\xcb" => [91, "\x9c"], "\xcc" => [108, "\x9c"], "\xcd" => [103, "\x9c"], "\xce" => [114, "\x9c"], "\xcf" => [14, "\x9c"], "\xd0" => [93, "\xa0"], "\xd1" => [138, "\xa0"], "\xd2" => [75, "\xa0"], "\xd3" => [91, "\xa0"], "\xd4" => [108, "\xa0"], "\xd5" => [103, "\xa0"], "\xd6" => [114, "\xa0"], "\xd7" => [14, "\xa0"], "\xd8" => [93, "\xa3"], "\xd9" => [138, "\xa3"], "\xda" => [75, "\xa3"], "\xdb" => [91, "\xa3"], "\xdc" => [108, "\xa3"], "\xdd" => [103, "\xa3"], "\xde" => [114, "\xa3"], "\xdf" => [14, "\xa3"], "\xe0" => [93, "\xa4"], "\xe1" => [138, "\xa4"], "\xe2" => [75, "\xa4"], "\xe3" => [91, "\xa4"], "\xe4" => [108, "\xa4"], "\xe5" => [103, "\xa4"], "\xe6" => [114, "\xa4"], "\xe7" => [14, "\xa4"], "\xe8" => [93, "\xa9"], "\xe9" => [138, "\xa9"], "\xea" => [75, "\xa9"], "\xeb" => [91, "\xa9"], "\xec" => [108, "\xa9"], "\xed" => [103, "\xa9"], "\xee" => [114, "\xa9"], "\xef" => [14, "\xa9"], "\xf0" => [93, "\xaa"], "\xf1" => [138, "\xaa"], "\xf2" => [75, "\xaa"], "\xf3" => [91, "\xaa"], "\xf4" => [108, "\xaa"], "\xf5" => [103, "\xaa"], "\xf6" => [114, "\xaa"], "\xf7" => [14, "\xaa"], "\xf8" => [93, "\xad"], "\xf9" => [138, "\xad"], "\xfa" => [75, "\xad"], "\xfb" => [91, "\xad"], "\xfc" => [108, "\xad"], "\xfd" => [103, "\xad"], "\xfe" => [114, "\xad"], "\xff" => [14, "\xad"]], ["\x00" => [94, "\x830"], "\x01" => [76, "\x830"], "\x02" => [104, "\x830"], "\x03" => [16, "\x830"], "\x04" => [94, "\x831"], "\x05" => [76, "\x831"], "\x06" => [104, "\x831"], "\x07" => [16, "\x831"], "\x08" => [94, "\x832"], "\t" => [76, "\x832"], "\n" => [104, "\x832"], "\v" => [16, "\x832"], "\f" => [94, "\x83a"], "\r" => [76, "\x83a"], "\x0e" => [104, "\x83a"], "\x0f" => [16, "\x83a"], "\x10" => [94, "\x83c"], "\x11" => [76, "\x83c"], "\x12" => [104, "\x83c"], "\x13" => [16, "\x83c"], "\x14" => [94, "\x83e"], "\x15" => [76, "\x83e"], "\x16" => [104, "\x83e"], "\x17" => [16, "\x83e"], "\x18" => [94, "\x83i"], "\x19" => [76, "\x83i"], "\x1a" => [104, "\x83i"], "\x1b" => [16, "\x83i"], "\x1c" => [94, "\x83o"], "\x1d" => [76, "\x83o"], "\x1e" => [104, "\x83o"], "\x1f" => [16, "\x83o"], " " => [94, "\x83s"], "!" => [76, "\x83s"], "\"" => [104, "\x83s"], "#" => [16, "\x83s"], "\$" => [94, "\x83t"], "%" => [76, "\x83t"], "&" => [104, "\x83t"], "'" => [16, "\x83t"], "(" => [77, "\x83 "], ")" => [18, "\x83 "], "*" => [77, "\x83%"], "+" => [18, "\x83%"], "," => [77, "\x83-"], "-" => [18, "\x83-"], "." => [77, "\x83."], "/" => [18, "\x83."], [77, "\x83/"], [18, "\x83/"], [77, "\x833"], [18, "\x833"], [77, "\x834"], [18, "\x834"], [77, "\x835"], [18, "\x835"], [77, "\x836"], [18, "\x836"], ":" => [77, "\x837"], ";" => [18, "\x837"], "<" => [77, "\x838"], "=" => [18, "\x838"], ">" => [77, "\x839"], "?" => [18, "\x839"], "@" => [77, "\x83="], "A" => [18, "\x83="], "B" => [77, "\x83A"], "C" => [18, "\x83A"], "D" => [77, "\x83_"], "E" => [18, "\x83_"], "F" => [77, "\x83b"], "G" => [18, "\x83b"], "H" => [77, "\x83d"], "I" => [18, "\x83d"], "J" => [77, "\x83f"], "K" => [18, "\x83f"], "L" => [77, "\x83g"], "M" => [18, "\x83g"], "N" => [77, "\x83h"], "O" => [18, "\x83h"], "P" => [77, "\x83l"], "Q" => [18, "\x83l"], "R" => [77, "\x83m"], "S" => [18, "\x83m"], "T" => [77, "\x83n"], "U" => [18, "\x83n"], "V" => [77, "\x83p"], "W" => [18, "\x83p"], "X" => [77, "\x83r"], "Y" => [18, "\x83r"], "Z" => [77, "\x83u"], "[" => [18, "\x83u"], "\\" => [0, "\x83:"], "]" => [0, "\x83B"], "^" => [0, "\x83C"], "_" => [0, "\x83D"], "`" => [0, "\x83E"], "a" => [0, "\x83F"], "b" => [0, "\x83G"], "c" => [0, "\x83H"], "d" => [0, "\x83I"], "e" => [0, "\x83J"], "f" => [0, "\x83K"], "g" => [0, "\x83L"], "h" => [0, "\x83M"], "i" => [0, "\x83N"], "j" => [0, "\x83O"], "k" => [0, "\x83P"], "l" => [0, "\x83Q"], "m" => [0, "\x83R"], "n" => [0, "\x83S"], "o" => [0, "\x83T"], "p" => [0, "\x83U"], "q" => [0, "\x83V"], "r" => [0, "\x83W"], "s" => [0, "\x83Y"], "t" => [0, "\x83j"], "u" => [0, "\x83k"], "v" => [0, "\x83q"], "w" => [0, "\x83v"], "x" => [0, "\x83w"], "y" => [0, "\x83x"], "z" => [0, "\x83y"], "{" => [0, "\x83z"], "|" => [82, "\x83"], "}" => [87, "\x83"], "~" => [130, "\x83"], "" => [9, "\x83"], "\x80" => [94, "\xa20"], "\x81" => [76, "\xa20"], "\x82" => [104, "\xa20"], "\x83" => [16, "\xa20"], "\x84" => [94, "\xa21"], "\x85" => [76, "\xa21"], "\x86" => [104, "\xa21"], "\x87" => [16, "\xa21"], "\x88" => [94, "\xa22"], "\x89" => [76, "\xa22"], "\x8a" => [104, "\xa22"], "\x8b" => [16, "\xa22"], "\x8c" => [94, "\xa2a"], "\x8d" => [76, "\xa2a"], "\x8e" => [104, "\xa2a"], "\x8f" => [16, "\xa2a"], "\x90" => [94, "\xa2c"], "\x91" => [76, "\xa2c"], "\x92" => [104, "\xa2c"], "\x93" => [16, "\xa2c"], "\x94" => [94, "\xa2e"], "\x95" => [76, "\xa2e"], "\x96" => [104, "\xa2e"], "\x97" => [16, "\xa2e"], "\x98" => [94, "\xa2i"], "\x99" => [76, "\xa2i"], "\x9a" => [104, "\xa2i"], "\x9b" => [16, "\xa2i"], "\x9c" => [94, "\xa2o"], "\x9d" => [76, "\xa2o"], "\x9e" => [104, "\xa2o"], "\x9f" => [16, "\xa2o"], "\xa0" => [94, "\xa2s"], "\xa1" => [76, "\xa2s"], "\xa2" => [104, "\xa2s"], "\xa3" => [16, "\xa2s"], "\xa4" => [94, "\xa2t"], "\xa5" => [76, "\xa2t"], "\xa6" => [104, "\xa2t"], "\xa7" => [16, "\xa2t"], "\xa8" => [77, "\xa2 "], "\xa9" => [18, "\xa2 "], "\xaa" => [77, "\xa2%"], "\xab" => [18, "\xa2%"], "\xac" => [77, "\xa2-"], "\xad" => [18, "\xa2-"], "\xae" => [77, "\xa2."], "\xaf" => [18, "\xa2."], "\xb0" => [77, "\xa2/"], "\xb1" => [18, "\xa2/"], "\xb2" => [77, "\xa23"], "\xb3" => [18, "\xa23"], "\xb4" => [77, "\xa24"], "\xb5" => [18, "\xa24"], "\xb6" => [77, "\xa25"], "\xb7" => [18, "\xa25"], "\xb8" => [77, "\xa26"], "\xb9" => [18, "\xa26"], "\xba" => [77, "\xa27"], "\xbb" => [18, "\xa27"], "\xbc" => [77, "\xa28"], "\xbd" => [18, "\xa28"], "\xbe" => [77, "\xa29"], "\xbf" => [18, "\xa29"], "\xc0" => [77, "\xa2="], "\xc1" => [18, "\xa2="], "\xc2" => [77, "\xa2A"], "\xc3" => [18, "\xa2A"], "\xc4" => [77, "\xa2_"], "\xc5" => [18, "\xa2_"], "\xc6" => [77, "\xa2b"], "\xc7" => [18, "\xa2b"], "\xc8" => [77, "\xa2d"], "\xc9" => [18, "\xa2d"], "\xca" => [77, "\xa2f"], "\xcb" => [18, "\xa2f"], "\xcc" => [77, "\xa2g"], "\xcd" => [18, "\xa2g"], "\xce" => [77, "\xa2h"], "\xcf" => [18, "\xa2h"], "\xd0" => [77, "\xa2l"], "\xd1" => [18, "\xa2l"], "\xd2" => [77, "\xa2m"], "\xd3" => [18, "\xa2m"], "\xd4" => [77, "\xa2n"], "\xd5" => [18, "\xa2n"], "\xd6" => [77, "\xa2p"], "\xd7" => [18, "\xa2p"], "\xd8" => [77, "\xa2r"], "\xd9" => [18, "\xa2r"], "\xda" => [77, "\xa2u"], "\xdb" => [18, "\xa2u"], "\xdc" => [0, "\xa2:"], "\xdd" => [0, "\xa2B"], "\xde" => [0, "\xa2C"], "\xdf" => [0, "\xa2D"], "\xe0" => [0, "\xa2E"], "\xe1" => [0, "\xa2F"], "\xe2" => [0, "\xa2G"], "\xe3" => [0, "\xa2H"], "\xe4" => [0, "\xa2I"], "\xe5" => [0, "\xa2J"], "\xe6" => [0, "\xa2K"], "\xe7" => [0, "\xa2L"], "\xe8" => [0, "\xa2M"], "\xe9" => [0, "\xa2N"], "\xea" => [0, "\xa2O"], "\xeb" => [0, "\xa2P"], "\xec" => [0, "\xa2Q"], "\xed" => [0, "\xa2R"], "\xee" => [0, "\xa2S"], "\xef" => [0, "\xa2T"], "\xf0" => [0, "\xa2U"], "\xf1" => [0, "\xa2V"], "\xf2" => [0, "\xa2W"], "\xf3" => [0, "\xa2Y"], "\xf4" => [0, "\xa2j"], "\xf5" => [0, "\xa2k"], "\xf6" => [0, "\xa2q"], "\xf7" => [0, "\xa2v"], "\xf8" => [0, "\xa2w"], "\xf9" => [0, "\xa2x"], "\xfa" => [0, "\xa2y"], "\xfb" => [0, "\xa2z"], "\xfc" => [82, "\xa2"], "\xfd" => [87, "\xa2"], "\xfe" => [130, "\xa2"], "\xff" => [9, "\xa2"]], ["\x00" => [77, "\x830"], "\x01" => [18, "\x830"], "\x02" => [77, "\x831"], "\x03" => [18, "\x831"], "\x04" => [77, "\x832"], "\x05" => [18, "\x832"], "\x06" => [77, "\x83a"], "\x07" => [18, "\x83a"], "\x08" => [77, "\x83c"], "\t" => [18, "\x83c"], "\n" => [77, "\x83e"], "\v" => [18, "\x83e"], "\f" => [77, "\x83i"], "\r" => [18, "\x83i"], "\x0e" => [77, "\x83o"], "\x0f" => [18, "\x83o"], "\x10" => [77, "\x83s"], "\x11" => [18, "\x83s"], "\x12" => [77, "\x83t"], "\x13" => [18, "\x83t"], "\x14" => [0, "\x83 "], "\x15" => [0, "\x83%"], "\x16" => [0, "\x83-"], "\x17" => [0, "\x83."], "\x18" => [0, "\x83/"], "\x19" => [0, "\x833"], "\x1a" => [0, "\x834"], "\x1b" => [0, "\x835"], "\x1c" => [0, "\x836"], "\x1d" => [0, "\x837"], "\x1e" => [0, "\x838"], "\x1f" => [0, "\x839"], " " => [0, "\x83="], "!" => [0, "\x83A"], "\"" => [0, "\x83_"], "#" => [0, "\x83b"], "\$" => [0, "\x83d"], "%" => [0, "\x83f"], "&" => [0, "\x83g"], "'" => [0, "\x83h"], "(" => [0, "\x83l"], ")" => [0, "\x83m"], "*" => [0, "\x83n"], "+" => [0, "\x83p"], "," => [0, "\x83r"], "-" => [0, "\x83u"], "." => [100, "\x83"], "/" => [110, "\x83"], [111, "\x83"], [115, "\x83"], [116, "\x83"], [118, "\x83"], [119, "\x83"], [122, "\x83"], [123, "\x83"], [125, "\x83"], [126, "\x83"], [129, "\x83"], ":" => [143, "\x83"], ";" => [148, "\x83"], "<" => [151, "\x83"], "=" => [153, "\x83"], ">" => [83, "\x83"], "?" => [10, "\x83"], "@" => [77, "\xa20"], "A" => [18, "\xa20"], "B" => [77, "\xa21"], "C" => [18, "\xa21"], "D" => [77, "\xa22"], "E" => [18, "\xa22"], "F" => [77, "\xa2a"], "G" => [18, "\xa2a"], "H" => [77, "\xa2c"], "I" => [18, "\xa2c"], "J" => [77, "\xa2e"], "K" => [18, "\xa2e"], "L" => [77, "\xa2i"], "M" => [18, "\xa2i"], "N" => [77, "\xa2o"], "O" => [18, "\xa2o"], "P" => [77, "\xa2s"], "Q" => [18, "\xa2s"], "R" => [77, "\xa2t"], "S" => [18, "\xa2t"], "T" => [0, "\xa2 "], "U" => [0, "\xa2%"], "V" => [0, "\xa2-"], "W" => [0, "\xa2."], "X" => [0, "\xa2/"], "Y" => [0, "\xa23"], "Z" => [0, "\xa24"], "[" => [0, "\xa25"], "\\" => [0, "\xa26"], "]" => [0, "\xa27"], "^" => [0, "\xa28"], "_" => [0, "\xa29"], "`" => [0, "\xa2="], "a" => [0, "\xa2A"], "b" => [0, "\xa2_"], "c" => [0, "\xa2b"], "d" => [0, "\xa2d"], "e" => [0, "\xa2f"], "f" => [0, "\xa2g"], "g" => [0, "\xa2h"], "h" => [0, "\xa2l"], "i" => [0, "\xa2m"], "j" => [0, "\xa2n"], "k" => [0, "\xa2p"], "l" => [0, "\xa2r"], "m" => [0, "\xa2u"], "n" => [100, "\xa2"], "o" => [110, "\xa2"], "p" => [111, "\xa2"], "q" => [115, "\xa2"], "r" => [116, "\xa2"], "s" => [118, "\xa2"], "t" => [119, "\xa2"], "u" => [122, "\xa2"], "v" => [123, "\xa2"], "w" => [125, "\xa2"], "x" => [126, "\xa2"], "y" => [129, "\xa2"], "z" => [143, "\xa2"], "{" => [148, "\xa2"], "|" => [151, "\xa2"], "}" => [153, "\xa2"], "~" => [83, "\xa2"], "" => [10, "\xa2"], "\x80" => [77, "\xb80"], "\x81" => [18, "\xb80"], "\x82" => [77, "\xb81"], "\x83" => [18, "\xb81"], "\x84" => [77, "\xb82"], "\x85" => [18, "\xb82"], "\x86" => [77, "\xb8a"], "\x87" => [18, "\xb8a"], "\x88" => [77, "\xb8c"], "\x89" => [18, "\xb8c"], "\x8a" => [77, "\xb8e"], "\x8b" => [18, "\xb8e"], "\x8c" => [77, "\xb8i"], "\x8d" => [18, "\xb8i"], "\x8e" => [77, "\xb8o"], "\x8f" => [18, "\xb8o"], "\x90" => [77, "\xb8s"], "\x91" => [18, "\xb8s"], "\x92" => [77, "\xb8t"], "\x93" => [18, "\xb8t"], "\x94" => [0, "\xb8 "], "\x95" => [0, "\xb8%"], "\x96" => [0, "\xb8-"], "\x97" => [0, "\xb8."], "\x98" => [0, "\xb8/"], "\x99" => [0, "\xb83"], "\x9a" => [0, "\xb84"], "\x9b" => [0, "\xb85"], "\x9c" => [0, "\xb86"], "\x9d" => [0, "\xb87"], "\x9e" => [0, "\xb88"], "\x9f" => [0, "\xb89"], "\xa0" => [0, "\xb8="], "\xa1" => [0, "\xb8A"], "\xa2" => [0, "\xb8_"], "\xa3" => [0, "\xb8b"], "\xa4" => [0, "\xb8d"], "\xa5" => [0, "\xb8f"], "\xa6" => [0, "\xb8g"], "\xa7" => [0, "\xb8h"], "\xa8" => [0, "\xb8l"], "\xa9" => [0, "\xb8m"], "\xaa" => [0, "\xb8n"], "\xab" => [0, "\xb8p"], "\xac" => [0, "\xb8r"], "\xad" => [0, "\xb8u"], "\xae" => [100, "\xb8"], "\xaf" => [110, "\xb8"], "\xb0" => [111, "\xb8"], "\xb1" => [115, "\xb8"], "\xb2" => [116, "\xb8"], "\xb3" => [118, "\xb8"], "\xb4" => [119, "\xb8"], "\xb5" => [122, "\xb8"], "\xb6" => [123, "\xb8"], "\xb7" => [125, "\xb8"], "\xb8" => [126, "\xb8"], "\xb9" => [129, "\xb8"], "\xba" => [143, "\xb8"], "\xbb" => [148, "\xb8"], "\xbc" => [151, "\xb8"], "\xbd" => [153, "\xb8"], "\xbe" => [83, "\xb8"], "\xbf" => [10, "\xb8"], "\xc0" => [77, "\xc20"], "\xc1" => [18, "\xc20"], "\xc2" => [77, "\xc21"], "\xc3" => [18, "\xc21"], "\xc4" => [77, "\xc22"], "\xc5" => [18, "\xc22"], "\xc6" => [77, "\xc2a"], "\xc7" => [18, "\xc2a"], "\xc8" => [77, "\xc2c"], "\xc9" => [18, "\xc2c"], "\xca" => [77, "\xc2e"], "\xcb" => [18, "\xc2e"], "\xcc" => [77, "\xc2i"], "\xcd" => [18, "\xc2i"], "\xce" => [77, "\xc2o"], "\xcf" => [18, "\xc2o"], "\xd0" => [77, "\xc2s"], "\xd1" => [18, "\xc2s"], "\xd2" => [77, "\xc2t"], "\xd3" => [18, "\xc2t"], "\xd4" => [0, "\xc2 "], "\xd5" => [0, "\xc2%"], "\xd6" => [0, "\xc2-"], "\xd7" => [0, "\xc2."], "\xd8" => [0, "\xc2/"], "\xd9" => [0, "\xc23"], "\xda" => [0, "\xc24"], "\xdb" => [0, "\xc25"], "\xdc" => [0, "\xc26"], "\xdd" => [0, "\xc27"], "\xde" => [0, "\xc28"], "\xdf" => [0, "\xc29"], "\xe0" => [0, "\xc2="], "\xe1" => [0, "\xc2A"], "\xe2" => [0, "\xc2_"], "\xe3" => [0, "\xc2b"], "\xe4" => [0, "\xc2d"], "\xe5" => [0, "\xc2f"], "\xe6" => [0, "\xc2g"], "\xe7" => [0, "\xc2h"], "\xe8" => [0, "\xc2l"], "\xe9" => [0, "\xc2m"], "\xea" => [0, "\xc2n"], "\xeb" => [0, "\xc2p"], "\xec" => [0, "\xc2r"], "\xed" => [0, "\xc2u"], "\xee" => [100, "\xc2"], "\xef" => [110, "\xc2"], "\xf0" => [111, "\xc2"], "\xf1" => [115, "\xc2"], "\xf2" => [116, "\xc2"], "\xf3" => [118, "\xc2"], "\xf4" => [119, "\xc2"], "\xf5" => [122, "\xc2"], "\xf6" => [123, "\xc2"], "\xf7" => [125, "\xc2"], "\xf8" => [126, "\xc2"], "\xf9" => [129, "\xc2"], "\xfa" => [143, "\xc2"], "\xfb" => [148, "\xc2"], "\xfc" => [151, "\xc2"], "\xfd" => [153, "\xc2"], "\xfe" => [83, "\xc2"], "\xff" => [10, "\xc2"]], ["\x00" => [0, "\x830"], "\x01" => [0, "\x831"], "\x02" => [0, "\x832"], "\x03" => [0, "\x83a"], "\x04" => [0, "\x83c"], "\x05" => [0, "\x83e"], "\x06" => [0, "\x83i"], "\x07" => [0, "\x83o"], "\x08" => [0, "\x83s"], "\t" => [0, "\x83t"], "\n" => [73, "\x83"], "\v" => [88, "\x83"], "\f" => [89, "\x83"], "\r" => [96, "\x83"], "\x0e" => [97, "\x83"], "\x0f" => [99, "\x83"], "\x10" => [106, "\x83"], "\x11" => [136, "\x83"], "\x12" => [139, "\x83"], "\x13" => [141, "\x83"], "\x14" => [145, "\x83"], "\x15" => [147, "\x83"], "\x16" => [149, "\x83"], "\x17" => [101, "\x83"], "\x18" => [112, "\x83"], "\x19" => [117, "\x83"], "\x1a" => [120, "\x83"], "\x1b" => [124, "\x83"], "\x1c" => [127, "\x83"], "\x1d" => [144, "\x83"], "\x1e" => [152, "\x83"], "\x1f" => [11, "\x83"], " " => [0, "\xa20"], "!" => [0, "\xa21"], "\"" => [0, "\xa22"], "#" => [0, "\xa2a"], "\$" => [0, "\xa2c"], "%" => [0, "\xa2e"], "&" => [0, "\xa2i"], "'" => [0, "\xa2o"], "(" => [0, "\xa2s"], ")" => [0, "\xa2t"], "*" => [73, "\xa2"], "+" => [88, "\xa2"], "," => [89, "\xa2"], "-" => [96, "\xa2"], "." => [97, "\xa2"], "/" => [99, "\xa2"], [106, "\xa2"], [136, "\xa2"], [139, "\xa2"], [141, "\xa2"], [145, "\xa2"], [147, "\xa2"], [149, "\xa2"], [101, "\xa2"], [112, "\xa2"], [117, "\xa2"], ":" => [120, "\xa2"], ";" => [124, "\xa2"], "<" => [127, "\xa2"], "=" => [144, "\xa2"], ">" => [152, "\xa2"], "?" => [11, "\xa2"], "@" => [0, "\xb80"], "A" => [0, "\xb81"], "B" => [0, "\xb82"], "C" => [0, "\xb8a"], "D" => [0, "\xb8c"], "E" => [0, "\xb8e"], "F" => [0, "\xb8i"], "G" => [0, "\xb8o"], "H" => [0, "\xb8s"], "I" => [0, "\xb8t"], "J" => [73, "\xb8"], "K" => [88, "\xb8"], "L" => [89, "\xb8"], "M" => [96, "\xb8"], "N" => [97, "\xb8"], "O" => [99, "\xb8"], "P" => [106, "\xb8"], "Q" => [136, "\xb8"], "R" => [139, "\xb8"], "S" => [141, "\xb8"], "T" => [145, "\xb8"], "U" => [147, "\xb8"], "V" => [149, "\xb8"], "W" => [101, "\xb8"], "X" => [112, "\xb8"], "Y" => [117, "\xb8"], "Z" => [120, "\xb8"], "[" => [124, "\xb8"], "\\" => [127, "\xb8"], "]" => [144, "\xb8"], "^" => [152, "\xb8"], "_" => [11, "\xb8"], "`" => [0, "\xc20"], "a" => [0, "\xc21"], "b" => [0, "\xc22"], "c" => [0, "\xc2a"], "d" => [0, "\xc2c"], "e" => [0, "\xc2e"], "f" => [0, "\xc2i"], "g" => [0, "\xc2o"], "h" => [0, "\xc2s"], "i" => [0, "\xc2t"], "j" => [73, "\xc2"], "k" => [88, "\xc2"], "l" => [89, "\xc2"], "m" => [96, "\xc2"], "n" => [97, "\xc2"], "o" => [99, "\xc2"], "p" => [106, "\xc2"], "q" => [136, "\xc2"], "r" => [139, "\xc2"], "s" => [141, "\xc2"], "t" => [145, "\xc2"], "u" => [147, "\xc2"], "v" => [149, "\xc2"], "w" => [101, "\xc2"], "x" => [112, "\xc2"], "y" => [117, "\xc2"], "z" => [120, "\xc2"], "{" => [124, "\xc2"], "|" => [127, "\xc2"], "}" => [144, "\xc2"], "~" => [152, "\xc2"], "" => [11, "\xc2"], "\x80" => [0, "\xe00"], "\x81" => [0, "\xe01"], "\x82" => [0, "\xe02"], "\x83" => [0, "\xe0a"], "\x84" => [0, "\xe0c"], "\x85" => [0, "\xe0e"], "\x86" => [0, "\xe0i"], "\x87" => [0, "\xe0o"], "\x88" => [0, "\xe0s"], "\x89" => [0, "\xe0t"], "\x8a" => [73, "\xe0"], "\x8b" => [88, "\xe0"], "\x8c" => [89, "\xe0"], "\x8d" => [96, "\xe0"], "\x8e" => [97, "\xe0"], "\x8f" => [99, "\xe0"], "\x90" => [106, "\xe0"], "\x91" => [136, "\xe0"], "\x92" => [139, "\xe0"], "\x93" => [141, "\xe0"], "\x94" => [145, "\xe0"], "\x95" => [147, "\xe0"], "\x96" => [149, "\xe0"], "\x97" => [101, "\xe0"], "\x98" => [112, "\xe0"], "\x99" => [117, "\xe0"], "\x9a" => [120, "\xe0"], "\x9b" => [124, "\xe0"], "\x9c" => [127, "\xe0"], "\x9d" => [144, "\xe0"], "\x9e" => [152, "\xe0"], "\x9f" => [11, "\xe0"], "\xa0" => [0, "\xe20"], "\xa1" => [0, "\xe21"], "\xa2" => [0, "\xe22"], "\xa3" => [0, "\xe2a"], "\xa4" => [0, "\xe2c"], "\xa5" => [0, "\xe2e"], "\xa6" => [0, "\xe2i"], "\xa7" => [0, "\xe2o"], "\xa8" => [0, "\xe2s"], "\xa9" => [0, "\xe2t"], "\xaa" => [73, "\xe2"], "\xab" => [88, "\xe2"], "\xac" => [89, "\xe2"], "\xad" => [96, "\xe2"], "\xae" => [97, "\xe2"], "\xaf" => [99, "\xe2"], "\xb0" => [106, "\xe2"], "\xb1" => [136, "\xe2"], "\xb2" => [139, "\xe2"], "\xb3" => [141, "\xe2"], "\xb4" => [145, "\xe2"], "\xb5" => [147, "\xe2"], "\xb6" => [149, "\xe2"], "\xb7" => [101, "\xe2"], "\xb8" => [112, "\xe2"], "\xb9" => [117, "\xe2"], "\xba" => [120, "\xe2"], "\xbb" => [124, "\xe2"], "\xbc" => [127, "\xe2"], "\xbd" => [144, "\xe2"], "\xbe" => [152, "\xe2"], "\xbf" => [11, "\xe2"], "\xc0" => [92, "\x99"], "\xc1" => [95, "\x99"], "\xc2" => [137, "\x99"], "\xc3" => [142, "\x99"], "\xc4" => [150, "\x99"], "\xc5" => [74, "\x99"], "\xc6" => [90, "\x99"], "\xc7" => [98, "\x99"], "\xc8" => [107, "\x99"], "\xc9" => [140, "\x99"], "\xca" => [146, "\x99"], "\xcb" => [102, "\x99"], "\xcc" => [113, "\x99"], "\xcd" => [121, "\x99"], "\xce" => [128, "\x99"], "\xcf" => [12, "\x99"], "\xd0" => [92, "\xa1"], "\xd1" => [95, "\xa1"], "\xd2" => [137, "\xa1"], "\xd3" => [142, "\xa1"], "\xd4" => [150, "\xa1"], "\xd5" => [74, "\xa1"], "\xd6" => [90, "\xa1"], "\xd7" => [98, "\xa1"], "\xd8" => [107, "\xa1"], "\xd9" => [140, "\xa1"], "\xda" => [146, "\xa1"], "\xdb" => [102, "\xa1"], "\xdc" => [113, "\xa1"], "\xdd" => [121, "\xa1"], "\xde" => [128, "\xa1"], "\xdf" => [12, "\xa1"], "\xe0" => [92, "\xa7"], "\xe1" => [95, "\xa7"], "\xe2" => [137, "\xa7"], "\xe3" => [142, "\xa7"], "\xe4" => [150, "\xa7"], "\xe5" => [74, "\xa7"], "\xe6" => [90, "\xa7"], "\xe7" => [98, "\xa7"], "\xe8" => [107, "\xa7"], "\xe9" => [140, "\xa7"], "\xea" => [146, "\xa7"], "\xeb" => [102, "\xa7"], "\xec" => [113, "\xa7"], "\xed" => [121, "\xa7"], "\xee" => [128, "\xa7"], "\xef" => [12, "\xa7"], "\xf0" => [92, "\xac"], "\xf1" => [95, "\xac"], "\xf2" => [137, "\xac"], "\xf3" => [142, "\xac"], "\xf4" => [150, "\xac"], "\xf5" => [74, "\xac"], "\xf6" => [90, "\xac"], "\xf7" => [98, "\xac"], "\xf8" => [107, "\xac"], "\xf9" => [140, "\xac"], "\xfa" => [146, "\xac"], "\xfb" => [102, "\xac"], "\xfc" => [113, "\xac"], "\xfd" => [121, "\xac"], "\xfe" => [128, "\xac"], "\xff" => [12, "\xac"]], ["\x00" => [94, "\x850"], "\x01" => [76, "\x850"], "\x02" => [104, "\x850"], "\x03" => [16, "\x850"], "\x04" => [94, "\x851"], "\x05" => [76, "\x851"], "\x06" => [104, "\x851"], "\x07" => [16, "\x851"], "\x08" => [94, "\x852"], "\t" => [76, "\x852"], "\n" => [104, "\x852"], "\v" => [16, "\x852"], "\f" => [94, "\x85a"], "\r" => [76, "\x85a"], "\x0e" => [104, "\x85a"], "\x0f" => [16, "\x85a"], "\x10" => [94, "\x85c"], "\x11" => [76, "\x85c"], "\x12" => [104, "\x85c"], "\x13" => [16, "\x85c"], "\x14" => [94, "\x85e"], "\x15" => [76, "\x85e"], "\x16" => [104, "\x85e"], "\x17" => [16, "\x85e"], "\x18" => [94, "\x85i"], "\x19" => [76, "\x85i"], "\x1a" => [104, "\x85i"], "\x1b" => [16, "\x85i"], "\x1c" => [94, "\x85o"], "\x1d" => [76, "\x85o"], "\x1e" => [104, "\x85o"], "\x1f" => [16, "\x85o"], " " => [94, "\x85s"], "!" => [76, "\x85s"], "\"" => [104, "\x85s"], "#" => [16, "\x85s"], "\$" => [94, "\x85t"], "%" => [76, "\x85t"], "&" => [104, "\x85t"], "'" => [16, "\x85t"], "(" => [77, "\x85 "], ")" => [18, "\x85 "], "*" => [77, "\x85%"], "+" => [18, "\x85%"], "," => [77, "\x85-"], "-" => [18, "\x85-"], "." => [77, "\x85."], "/" => [18, "\x85."], [77, "\x85/"], [18, "\x85/"], [77, "\x853"], [18, "\x853"], [77, "\x854"], [18, "\x854"], [77, "\x855"], [18, "\x855"], [77, "\x856"], [18, "\x856"], ":" => [77, "\x857"], ";" => [18, "\x857"], "<" => [77, "\x858"], "=" => [18, "\x858"], ">" => [77, "\x859"], "?" => [18, "\x859"], "@" => [77, "\x85="], "A" => [18, "\x85="], "B" => [77, "\x85A"], "C" => [18, "\x85A"], "D" => [77, "\x85_"], "E" => [18, "\x85_"], "F" => [77, "\x85b"], "G" => [18, "\x85b"], "H" => [77, "\x85d"], "I" => [18, "\x85d"], "J" => [77, "\x85f"], "K" => [18, "\x85f"], "L" => [77, "\x85g"], "M" => [18, "\x85g"], "N" => [77, "\x85h"], "O" => [18, "\x85h"], "P" => [77, "\x85l"], "Q" => [18, "\x85l"], "R" => [77, "\x85m"], "S" => [18, "\x85m"], "T" => [77, "\x85n"], "U" => [18, "\x85n"], "V" => [77, "\x85p"], "W" => [18, "\x85p"], "X" => [77, "\x85r"], "Y" => [18, "\x85r"], "Z" => [77, "\x85u"], "[" => [18, "\x85u"], "\\" => [0, "\x85:"], "]" => [0, "\x85B"], "^" => [0, "\x85C"], "_" => [0, "\x85D"], "`" => [0, "\x85E"], "a" => [0, "\x85F"], "b" => [0, "\x85G"], "c" => [0, "\x85H"], "d" => [0, "\x85I"], "e" => [0, "\x85J"], "f" => [0, "\x85K"], "g" => [0, "\x85L"], "h" => [0, "\x85M"], "i" => [0, "\x85N"], "j" => [0, "\x85O"], "k" => [0, "\x85P"], "l" => [0, "\x85Q"], "m" => [0, "\x85R"], "n" => [0, "\x85S"], "o" => [0, "\x85T"], "p" => [0, "\x85U"], "q" => [0, "\x85V"], "r" => [0, "\x85W"], "s" => [0, "\x85Y"], "t" => [0, "\x85j"], "u" => [0, "\x85k"], "v" => [0, "\x85q"], "w" => [0, "\x85v"], "x" => [0, "\x85w"], "y" => [0, "\x85x"], "z" => [0, "\x85y"], "{" => [0, "\x85z"], "|" => [82, "\x85"], "}" => [87, "\x85"], "~" => [130, "\x85"], "" => [9, "\x85"], "\x80" => [94, "\x860"], "\x81" => [76, "\x860"], "\x82" => [104, "\x860"], "\x83" => [16, "\x860"], "\x84" => [94, "\x861"], "\x85" => [76, "\x861"], "\x86" => [104, "\x861"], "\x87" => [16, "\x861"], "\x88" => [94, "\x862"], "\x89" => [76, "\x862"], "\x8a" => [104, "\x862"], "\x8b" => [16, "\x862"], "\x8c" => [94, "\x86a"], "\x8d" => [76, "\x86a"], "\x8e" => [104, "\x86a"], "\x8f" => [16, "\x86a"], "\x90" => [94, "\x86c"], "\x91" => [76, "\x86c"], "\x92" => [104, "\x86c"], "\x93" => [16, "\x86c"], "\x94" => [94, "\x86e"], "\x95" => [76, "\x86e"], "\x96" => [104, "\x86e"], "\x97" => [16, "\x86e"], "\x98" => [94, "\x86i"], "\x99" => [76, "\x86i"], "\x9a" => [104, "\x86i"], "\x9b" => [16, "\x86i"], "\x9c" => [94, "\x86o"], "\x9d" => [76, "\x86o"], "\x9e" => [104, "\x86o"], "\x9f" => [16, "\x86o"], "\xa0" => [94, "\x86s"], "\xa1" => [76, "\x86s"], "\xa2" => [104, "\x86s"], "\xa3" => [16, "\x86s"], "\xa4" => [94, "\x86t"], "\xa5" => [76, "\x86t"], "\xa6" => [104, "\x86t"], "\xa7" => [16, "\x86t"], "\xa8" => [77, "\x86 "], "\xa9" => [18, "\x86 "], "\xaa" => [77, "\x86%"], "\xab" => [18, "\x86%"], "\xac" => [77, "\x86-"], "\xad" => [18, "\x86-"], "\xae" => [77, "\x86."], "\xaf" => [18, "\x86."], "\xb0" => [77, "\x86/"], "\xb1" => [18, "\x86/"], "\xb2" => [77, "\x863"], "\xb3" => [18, "\x863"], "\xb4" => [77, "\x864"], "\xb5" => [18, "\x864"], "\xb6" => [77, "\x865"], "\xb7" => [18, "\x865"], "\xb8" => [77, "\x866"], "\xb9" => [18, "\x866"], "\xba" => [77, "\x867"], "\xbb" => [18, "\x867"], "\xbc" => [77, "\x868"], "\xbd" => [18, "\x868"], "\xbe" => [77, "\x869"], "\xbf" => [18, "\x869"], "\xc0" => [77, "\x86="], "\xc1" => [18, "\x86="], "\xc2" => [77, "\x86A"], "\xc3" => [18, "\x86A"], "\xc4" => [77, "\x86_"], "\xc5" => [18, "\x86_"], "\xc6" => [77, "\x86b"], "\xc7" => [18, "\x86b"], "\xc8" => [77, "\x86d"], "\xc9" => [18, "\x86d"], "\xca" => [77, "\x86f"], "\xcb" => [18, "\x86f"], "\xcc" => [77, "\x86g"], "\xcd" => [18, "\x86g"], "\xce" => [77, "\x86h"], "\xcf" => [18, "\x86h"], "\xd0" => [77, "\x86l"], "\xd1" => [18, "\x86l"], "\xd2" => [77, "\x86m"], "\xd3" => [18, "\x86m"], "\xd4" => [77, "\x86n"], "\xd5" => [18, "\x86n"], "\xd6" => [77, "\x86p"], "\xd7" => [18, "\x86p"], "\xd8" => [77, "\x86r"], "\xd9" => [18, "\x86r"], "\xda" => [77, "\x86u"], "\xdb" => [18, "\x86u"], "\xdc" => [0, "\x86:"], "\xdd" => [0, "\x86B"], "\xde" => [0, "\x86C"], "\xdf" => [0, "\x86D"], "\xe0" => [0, "\x86E"], "\xe1" => [0, "\x86F"], "\xe2" => [0, "\x86G"], "\xe3" => [0, "\x86H"], "\xe4" => [0, "\x86I"], "\xe5" => [0, "\x86J"], "\xe6" => [0, "\x86K"], "\xe7" => [0, "\x86L"], "\xe8" => [0, "\x86M"], "\xe9" => [0, "\x86N"], "\xea" => [0, "\x86O"], "\xeb" => [0, "\x86P"], "\xec" => [0, "\x86Q"], "\xed" => [0, "\x86R"], "\xee" => [0, "\x86S"], "\xef" => [0, "\x86T"], "\xf0" => [0, "\x86U"], "\xf1" => [0, "\x86V"], "\xf2" => [0, "\x86W"], "\xf3" => [0, "\x86Y"], "\xf4" => [0, "\x86j"], "\xf5" => [0, "\x86k"], "\xf6" => [0, "\x86q"], "\xf7" => [0, "\x86v"], "\xf8" => [0, "\x86w"], "\xf9" => [0, "\x86x"], "\xfa" => [0, "\x86y"], "\xfb" => [0, "\x86z"], "\xfc" => [82, "\x86"], "\xfd" => [87, "\x86"], "\xfe" => [130, "\x86"], "\xff" => [9, "\x86"]], ["\x00" => [77, "\x850"], "\x01" => [18, "\x850"], "\x02" => [77, "\x851"], "\x03" => [18, "\x851"], "\x04" => [77, "\x852"], "\x05" => [18, "\x852"], "\x06" => [77, "\x85a"], "\x07" => [18, "\x85a"], "\x08" => [77, "\x85c"], "\t" => [18, "\x85c"], "\n" => [77, "\x85e"], "\v" => [18, "\x85e"], "\f" => [77, "\x85i"], "\r" => [18, "\x85i"], "\x0e" => [77, "\x85o"], "\x0f" => [18, "\x85o"], "\x10" => [77, "\x85s"], "\x11" => [18, "\x85s"], "\x12" => [77, "\x85t"], "\x13" => [18, "\x85t"], "\x14" => [0, "\x85 "], "\x15" => [0, "\x85%"], "\x16" => [0, "\x85-"], "\x17" => [0, "\x85."], "\x18" => [0, "\x85/"], "\x19" => [0, "\x853"], "\x1a" => [0, "\x854"], "\x1b" => [0, "\x855"], "\x1c" => [0, "\x856"], "\x1d" => [0, "\x857"], "\x1e" => [0, "\x858"], "\x1f" => [0, "\x859"], " " => [0, "\x85="], "!" => [0, "\x85A"], "\"" => [0, "\x85_"], "#" => [0, "\x85b"], "\$" => [0, "\x85d"], "%" => [0, "\x85f"], "&" => [0, "\x85g"], "'" => [0, "\x85h"], "(" => [0, "\x85l"], ")" => [0, "\x85m"], "*" => [0, "\x85n"], "+" => [0, "\x85p"], "," => [0, "\x85r"], "-" => [0, "\x85u"], "." => [100, "\x85"], "/" => [110, "\x85"], [111, "\x85"], [115, "\x85"], [116, "\x85"], [118, "\x85"], [119, "\x85"], [122, "\x85"], [123, "\x85"], [125, "\x85"], [126, "\x85"], [129, "\x85"], ":" => [143, "\x85"], ";" => [148, "\x85"], "<" => [151, "\x85"], "=" => [153, "\x85"], ">" => [83, "\x85"], "?" => [10, "\x85"], "@" => [77, "\x860"], "A" => [18, "\x860"], "B" => [77, "\x861"], "C" => [18, "\x861"], "D" => [77, "\x862"], "E" => [18, "\x862"], "F" => [77, "\x86a"], "G" => [18, "\x86a"], "H" => [77, "\x86c"], "I" => [18, "\x86c"], "J" => [77, "\x86e"], "K" => [18, "\x86e"], "L" => [77, "\x86i"], "M" => [18, "\x86i"], "N" => [77, "\x86o"], "O" => [18, "\x86o"], "P" => [77, "\x86s"], "Q" => [18, "\x86s"], "R" => [77, "\x86t"], "S" => [18, "\x86t"], "T" => [0, "\x86 "], "U" => [0, "\x86%"], "V" => [0, "\x86-"], "W" => [0, "\x86."], "X" => [0, "\x86/"], "Y" => [0, "\x863"], "Z" => [0, "\x864"], "[" => [0, "\x865"], "\\" => [0, "\x866"], "]" => [0, "\x867"], "^" => [0, "\x868"], "_" => [0, "\x869"], "`" => [0, "\x86="], "a" => [0, "\x86A"], "b" => [0, "\x86_"], "c" => [0, "\x86b"], "d" => [0, "\x86d"], "e" => [0, "\x86f"], "f" => [0, "\x86g"], "g" => [0, "\x86h"], "h" => [0, "\x86l"], "i" => [0, "\x86m"], "j" => [0, "\x86n"], "k" => [0, "\x86p"], "l" => [0, "\x86r"], "m" => [0, "\x86u"], "n" => [100, "\x86"], "o" => [110, "\x86"], "p" => [111, "\x86"], "q" => [115, "\x86"], "r" => [116, "\x86"], "s" => [118, "\x86"], "t" => [119, "\x86"], "u" => [122, "\x86"], "v" => [123, "\x86"], "w" => [125, "\x86"], "x" => [126, "\x86"], "y" => [129, "\x86"], "z" => [143, "\x86"], "{" => [148, "\x86"], "|" => [151, "\x86"], "}" => [153, "\x86"], "~" => [83, "\x86"], "" => [10, "\x86"], "\x80" => [77, "\x880"], "\x81" => [18, "\x880"], "\x82" => [77, "\x881"], "\x83" => [18, "\x881"], "\x84" => [77, "\x882"], "\x85" => [18, "\x882"], "\x86" => [77, "\x88a"], "\x87" => [18, "\x88a"], "\x88" => [77, "\x88c"], "\x89" => [18, "\x88c"], "\x8a" => [77, "\x88e"], "\x8b" => [18, "\x88e"], "\x8c" => [77, "\x88i"], "\x8d" => [18, "\x88i"], "\x8e" => [77, "\x88o"], "\x8f" => [18, "\x88o"], "\x90" => [77, "\x88s"], "\x91" => [18, "\x88s"], "\x92" => [77, "\x88t"], "\x93" => [18, "\x88t"], "\x94" => [0, "\x88 "], "\x95" => [0, "\x88%"], "\x96" => [0, "\x88-"], "\x97" => [0, "\x88."], "\x98" => [0, "\x88/"], "\x99" => [0, "\x883"], "\x9a" => [0, "\x884"], "\x9b" => [0, "\x885"], "\x9c" => [0, "\x886"], "\x9d" => [0, "\x887"], "\x9e" => [0, "\x888"], "\x9f" => [0, "\x889"], "\xa0" => [0, "\x88="], "\xa1" => [0, "\x88A"], "\xa2" => [0, "\x88_"], "\xa3" => [0, "\x88b"], "\xa4" => [0, "\x88d"], "\xa5" => [0, "\x88f"], "\xa6" => [0, "\x88g"], "\xa7" => [0, "\x88h"], "\xa8" => [0, "\x88l"], "\xa9" => [0, "\x88m"], "\xaa" => [0, "\x88n"], "\xab" => [0, "\x88p"], "\xac" => [0, "\x88r"], "\xad" => [0, "\x88u"], "\xae" => [100, "\x88"], "\xaf" => [110, "\x88"], "\xb0" => [111, "\x88"], "\xb1" => [115, "\x88"], "\xb2" => [116, "\x88"], "\xb3" => [118, "\x88"], "\xb4" => [119, "\x88"], "\xb5" => [122, "\x88"], "\xb6" => [123, "\x88"], "\xb7" => [125, "\x88"], "\xb8" => [126, "\x88"], "\xb9" => [129, "\x88"], "\xba" => [143, "\x88"], "\xbb" => [148, "\x88"], "\xbc" => [151, "\x88"], "\xbd" => [153, "\x88"], "\xbe" => [83, "\x88"], "\xbf" => [10, "\x88"], "\xc0" => [77, "\x920"], "\xc1" => [18, "\x920"], "\xc2" => [77, "\x921"], "\xc3" => [18, "\x921"], "\xc4" => [77, "\x922"], "\xc5" => [18, "\x922"], "\xc6" => [77, "\x92a"], "\xc7" => [18, "\x92a"], "\xc8" => [77, "\x92c"], "\xc9" => [18, "\x92c"], "\xca" => [77, "\x92e"], "\xcb" => [18, "\x92e"], "\xcc" => [77, "\x92i"], "\xcd" => [18, "\x92i"], "\xce" => [77, "\x92o"], "\xcf" => [18, "\x92o"], "\xd0" => [77, "\x92s"], "\xd1" => [18, "\x92s"], "\xd2" => [77, "\x92t"], "\xd3" => [18, "\x92t"], "\xd4" => [0, "\x92 "], "\xd5" => [0, "\x92%"], "\xd6" => [0, "\x92-"], "\xd7" => [0, "\x92."], "\xd8" => [0, "\x92/"], "\xd9" => [0, "\x923"], "\xda" => [0, "\x924"], "\xdb" => [0, "\x925"], "\xdc" => [0, "\x926"], "\xdd" => [0, "\x927"], "\xde" => [0, "\x928"], "\xdf" => [0, "\x929"], "\xe0" => [0, "\x92="], "\xe1" => [0, "\x92A"], "\xe2" => [0, "\x92_"], "\xe3" => [0, "\x92b"], "\xe4" => [0, "\x92d"], "\xe5" => [0, "\x92f"], "\xe6" => [0, "\x92g"], "\xe7" => [0, "\x92h"], "\xe8" => [0, "\x92l"], "\xe9" => [0, "\x92m"], "\xea" => [0, "\x92n"], "\xeb" => [0, "\x92p"], "\xec" => [0, "\x92r"], "\xed" => [0, "\x92u"], "\xee" => [100, "\x92"], "\xef" => [110, "\x92"], "\xf0" => [111, "\x92"], "\xf1" => [115, "\x92"], "\xf2" => [116, "\x92"], "\xf3" => [118, "\x92"], "\xf4" => [119, "\x92"], "\xf5" => [122, "\x92"], "\xf6" => [123, "\x92"], "\xf7" => [125, "\x92"], "\xf8" => [126, "\x92"], "\xf9" => [129, "\x92"], "\xfa" => [143, "\x92"], "\xfb" => [148, "\x92"], "\xfc" => [151, "\x92"], "\xfd" => [153, "\x92"], "\xfe" => [83, "\x92"], "\xff" => [10, "\x92"]], ["\x00" => [94, "\x880"], "\x01" => [76, "\x880"], "\x02" => [104, "\x880"], "\x03" => [16, "\x880"], "\x04" => [94, "\x881"], "\x05" => [76, "\x881"], "\x06" => [104, "\x881"], "\x07" => [16, "\x881"], "\x08" => [94, "\x882"], "\t" => [76, "\x882"], "\n" => [104, "\x882"], "\v" => [16, "\x882"], "\f" => [94, "\x88a"], "\r" => [76, "\x88a"], "\x0e" => [104, "\x88a"], "\x0f" => [16, "\x88a"], "\x10" => [94, "\x88c"], "\x11" => [76, "\x88c"], "\x12" => [104, "\x88c"], "\x13" => [16, "\x88c"], "\x14" => [94, "\x88e"], "\x15" => [76, "\x88e"], "\x16" => [104, "\x88e"], "\x17" => [16, "\x88e"], "\x18" => [94, "\x88i"], "\x19" => [76, "\x88i"], "\x1a" => [104, "\x88i"], "\x1b" => [16, "\x88i"], "\x1c" => [94, "\x88o"], "\x1d" => [76, "\x88o"], "\x1e" => [104, "\x88o"], "\x1f" => [16, "\x88o"], " " => [94, "\x88s"], "!" => [76, "\x88s"], "\"" => [104, "\x88s"], "#" => [16, "\x88s"], "\$" => [94, "\x88t"], "%" => [76, "\x88t"], "&" => [104, "\x88t"], "'" => [16, "\x88t"], "(" => [77, "\x88 "], ")" => [18, "\x88 "], "*" => [77, "\x88%"], "+" => [18, "\x88%"], "," => [77, "\x88-"], "-" => [18, "\x88-"], "." => [77, "\x88."], "/" => [18, "\x88."], [77, "\x88/"], [18, "\x88/"], [77, "\x883"], [18, "\x883"], [77, "\x884"], [18, "\x884"], [77, "\x885"], [18, "\x885"], [77, "\x886"], [18, "\x886"], ":" => [77, "\x887"], ";" => [18, "\x887"], "<" => [77, "\x888"], "=" => [18, "\x888"], ">" => [77, "\x889"], "?" => [18, "\x889"], "@" => [77, "\x88="], "A" => [18, "\x88="], "B" => [77, "\x88A"], "C" => [18, "\x88A"], "D" => [77, "\x88_"], "E" => [18, "\x88_"], "F" => [77, "\x88b"], "G" => [18, "\x88b"], "H" => [77, "\x88d"], "I" => [18, "\x88d"], "J" => [77, "\x88f"], "K" => [18, "\x88f"], "L" => [77, "\x88g"], "M" => [18, "\x88g"], "N" => [77, "\x88h"], "O" => [18, "\x88h"], "P" => [77, "\x88l"], "Q" => [18, "\x88l"], "R" => [77, "\x88m"], "S" => [18, "\x88m"], "T" => [77, "\x88n"], "U" => [18, "\x88n"], "V" => [77, "\x88p"], "W" => [18, "\x88p"], "X" => [77, "\x88r"], "Y" => [18, "\x88r"], "Z" => [77, "\x88u"], "[" => [18, "\x88u"], "\\" => [0, "\x88:"], "]" => [0, "\x88B"], "^" => [0, "\x88C"], "_" => [0, "\x88D"], "`" => [0, "\x88E"], "a" => [0, "\x88F"], "b" => [0, "\x88G"], "c" => [0, "\x88H"], "d" => [0, "\x88I"], "e" => [0, "\x88J"], "f" => [0, "\x88K"], "g" => [0, "\x88L"], "h" => [0, "\x88M"], "i" => [0, "\x88N"], "j" => [0, "\x88O"], "k" => [0, "\x88P"], "l" => [0, "\x88Q"], "m" => [0, "\x88R"], "n" => [0, "\x88S"], "o" => [0, "\x88T"], "p" => [0, "\x88U"], "q" => [0, "\x88V"], "r" => [0, "\x88W"], "s" => [0, "\x88Y"], "t" => [0, "\x88j"], "u" => [0, "\x88k"], "v" => [0, "\x88q"], "w" => [0, "\x88v"], "x" => [0, "\x88w"], "y" => [0, "\x88x"], "z" => [0, "\x88y"], "{" => [0, "\x88z"], "|" => [82, "\x88"], "}" => [87, "\x88"], "~" => [130, "\x88"], "" => [9, "\x88"], "\x80" => [94, "\x920"], "\x81" => [76, "\x920"], "\x82" => [104, "\x920"], "\x83" => [16, "\x920"], "\x84" => [94, "\x921"], "\x85" => [76, "\x921"], "\x86" => [104, "\x921"], "\x87" => [16, "\x921"], "\x88" => [94, "\x922"], "\x89" => [76, "\x922"], "\x8a" => [104, "\x922"], "\x8b" => [16, "\x922"], "\x8c" => [94, "\x92a"], "\x8d" => [76, "\x92a"], "\x8e" => [104, "\x92a"], "\x8f" => [16, "\x92a"], "\x90" => [94, "\x92c"], "\x91" => [76, "\x92c"], "\x92" => [104, "\x92c"], "\x93" => [16, "\x92c"], "\x94" => [94, "\x92e"], "\x95" => [76, "\x92e"], "\x96" => [104, "\x92e"], "\x97" => [16, "\x92e"], "\x98" => [94, "\x92i"], "\x99" => [76, "\x92i"], "\x9a" => [104, "\x92i"], "\x9b" => [16, "\x92i"], "\x9c" => [94, "\x92o"], "\x9d" => [76, "\x92o"], "\x9e" => [104, "\x92o"], "\x9f" => [16, "\x92o"], "\xa0" => [94, "\x92s"], "\xa1" => [76, "\x92s"], "\xa2" => [104, "\x92s"], "\xa3" => [16, "\x92s"], "\xa4" => [94, "\x92t"], "\xa5" => [76, "\x92t"], "\xa6" => [104, "\x92t"], "\xa7" => [16, "\x92t"], "\xa8" => [77, "\x92 "], "\xa9" => [18, "\x92 "], "\xaa" => [77, "\x92%"], "\xab" => [18, "\x92%"], "\xac" => [77, "\x92-"], "\xad" => [18, "\x92-"], "\xae" => [77, "\x92."], "\xaf" => [18, "\x92."], "\xb0" => [77, "\x92/"], "\xb1" => [18, "\x92/"], "\xb2" => [77, "\x923"], "\xb3" => [18, "\x923"], "\xb4" => [77, "\x924"], "\xb5" => [18, "\x924"], "\xb6" => [77, "\x925"], "\xb7" => [18, "\x925"], "\xb8" => [77, "\x926"], "\xb9" => [18, "\x926"], "\xba" => [77, "\x927"], "\xbb" => [18, "\x927"], "\xbc" => [77, "\x928"], "\xbd" => [18, "\x928"], "\xbe" => [77, "\x929"], "\xbf" => [18, "\x929"], "\xc0" => [77, "\x92="], "\xc1" => [18, "\x92="], "\xc2" => [77, "\x92A"], "\xc3" => [18, "\x92A"], "\xc4" => [77, "\x92_"], "\xc5" => [18, "\x92_"], "\xc6" => [77, "\x92b"], "\xc7" => [18, "\x92b"], "\xc8" => [77, "\x92d"], "\xc9" => [18, "\x92d"], "\xca" => [77, "\x92f"], "\xcb" => [18, "\x92f"], "\xcc" => [77, "\x92g"], "\xcd" => [18, "\x92g"], "\xce" => [77, "\x92h"], "\xcf" => [18, "\x92h"], "\xd0" => [77, "\x92l"], "\xd1" => [18, "\x92l"], "\xd2" => [77, "\x92m"], "\xd3" => [18, "\x92m"], "\xd4" => [77, "\x92n"], "\xd5" => [18, "\x92n"], "\xd6" => [77, "\x92p"], "\xd7" => [18, "\x92p"], "\xd8" => [77, "\x92r"], "\xd9" => [18, "\x92r"], "\xda" => [77, "\x92u"], "\xdb" => [18, "\x92u"], "\xdc" => [0, "\x92:"], "\xdd" => [0, "\x92B"], "\xde" => [0, "\x92C"], "\xdf" => [0, "\x92D"], "\xe0" => [0, "\x92E"], "\xe1" => [0, "\x92F"], "\xe2" => [0, "\x92G"], "\xe3" => [0, "\x92H"], "\xe4" => [0, "\x92I"], "\xe5" => [0, "\x92J"], "\xe6" => [0, "\x92K"], "\xe7" => [0, "\x92L"], "\xe8" => [0, "\x92M"], "\xe9" => [0, "\x92N"], "\xea" => [0, "\x92O"], "\xeb" => [0, "\x92P"], "\xec" => [0, "\x92Q"], "\xed" => [0, "\x92R"], "\xee" => [0, "\x92S"], "\xef" => [0, "\x92T"], "\xf0" => [0, "\x92U"], "\xf1" => [0, "\x92V"], "\xf2" => [0, "\x92W"], "\xf3" => [0, "\x92Y"], "\xf4" => [0, "\x92j"], "\xf5" => [0, "\x92k"], "\xf6" => [0, "\x92q"], "\xf7" => [0, "\x92v"], "\xf8" => [0, "\x92w"], "\xf9" => [0, "\x92x"], "\xfa" => [0, "\x92y"], "\xfb" => [0, "\x92z"], "\xfc" => [82, "\x92"], "\xfd" => [87, "\x92"], "\xfe" => [130, "\x92"], "\xff" => [9, "\x92"]], ["\x00" => [94, "\x890"], "\x01" => [76, "\x890"], "\x02" => [104, "\x890"], "\x03" => [16, "\x890"], "\x04" => [94, "\x891"], "\x05" => [76, "\x891"], "\x06" => [104, "\x891"], "\x07" => [16, "\x891"], "\x08" => [94, "\x892"], "\t" => [76, "\x892"], "\n" => [104, "\x892"], "\v" => [16, "\x892"], "\f" => [94, "\x89a"], "\r" => [76, "\x89a"], "\x0e" => [104, "\x89a"], "\x0f" => [16, "\x89a"], "\x10" => [94, "\x89c"], "\x11" => [76, "\x89c"], "\x12" => [104, "\x89c"], "\x13" => [16, "\x89c"], "\x14" => [94, "\x89e"], "\x15" => [76, "\x89e"], "\x16" => [104, "\x89e"], "\x17" => [16, "\x89e"], "\x18" => [94, "\x89i"], "\x19" => [76, "\x89i"], "\x1a" => [104, "\x89i"], "\x1b" => [16, "\x89i"], "\x1c" => [94, "\x89o"], "\x1d" => [76, "\x89o"], "\x1e" => [104, "\x89o"], "\x1f" => [16, "\x89o"], " " => [94, "\x89s"], "!" => [76, "\x89s"], "\"" => [104, "\x89s"], "#" => [16, "\x89s"], "\$" => [94, "\x89t"], "%" => [76, "\x89t"], "&" => [104, "\x89t"], "'" => [16, "\x89t"], "(" => [77, "\x89 "], ")" => [18, "\x89 "], "*" => [77, "\x89%"], "+" => [18, "\x89%"], "," => [77, "\x89-"], "-" => [18, "\x89-"], "." => [77, "\x89."], "/" => [18, "\x89."], [77, "\x89/"], [18, "\x89/"], [77, "\x893"], [18, "\x893"], [77, "\x894"], [18, "\x894"], [77, "\x895"], [18, "\x895"], [77, "\x896"], [18, "\x896"], ":" => [77, "\x897"], ";" => [18, "\x897"], "<" => [77, "\x898"], "=" => [18, "\x898"], ">" => [77, "\x899"], "?" => [18, "\x899"], "@" => [77, "\x89="], "A" => [18, "\x89="], "B" => [77, "\x89A"], "C" => [18, "\x89A"], "D" => [77, "\x89_"], "E" => [18, "\x89_"], "F" => [77, "\x89b"], "G" => [18, "\x89b"], "H" => [77, "\x89d"], "I" => [18, "\x89d"], "J" => [77, "\x89f"], "K" => [18, "\x89f"], "L" => [77, "\x89g"], "M" => [18, "\x89g"], "N" => [77, "\x89h"], "O" => [18, "\x89h"], "P" => [77, "\x89l"], "Q" => [18, "\x89l"], "R" => [77, "\x89m"], "S" => [18, "\x89m"], "T" => [77, "\x89n"], "U" => [18, "\x89n"], "V" => [77, "\x89p"], "W" => [18, "\x89p"], "X" => [77, "\x89r"], "Y" => [18, "\x89r"], "Z" => [77, "\x89u"], "[" => [18, "\x89u"], "\\" => [0, "\x89:"], "]" => [0, "\x89B"], "^" => [0, "\x89C"], "_" => [0, "\x89D"], "`" => [0, "\x89E"], "a" => [0, "\x89F"], "b" => [0, "\x89G"], "c" => [0, "\x89H"], "d" => [0, "\x89I"], "e" => [0, "\x89J"], "f" => [0, "\x89K"], "g" => [0, "\x89L"], "h" => [0, "\x89M"], "i" => [0, "\x89N"], "j" => [0, "\x89O"], "k" => [0, "\x89P"], "l" => [0, "\x89Q"], "m" => [0, "\x89R"], "n" => [0, "\x89S"], "o" => [0, "\x89T"], "p" => [0, "\x89U"], "q" => [0, "\x89V"], "r" => [0, "\x89W"], "s" => [0, "\x89Y"], "t" => [0, "\x89j"], "u" => [0, "\x89k"], "v" => [0, "\x89q"], "w" => [0, "\x89v"], "x" => [0, "\x89w"], "y" => [0, "\x89x"], "z" => [0, "\x89y"], "{" => [0, "\x89z"], "|" => [82, "\x89"], "}" => [87, "\x89"], "~" => [130, "\x89"], "" => [9, "\x89"], "\x80" => [94, "\x8a0"], "\x81" => [76, "\x8a0"], "\x82" => [104, "\x8a0"], "\x83" => [16, "\x8a0"], "\x84" => [94, "\x8a1"], "\x85" => [76, "\x8a1"], "\x86" => [104, "\x8a1"], "\x87" => [16, "\x8a1"], "\x88" => [94, "\x8a2"], "\x89" => [76, "\x8a2"], "\x8a" => [104, "\x8a2"], "\x8b" => [16, "\x8a2"], "\x8c" => [94, "\x8aa"], "\x8d" => [76, "\x8aa"], "\x8e" => [104, "\x8aa"], "\x8f" => [16, "\x8aa"], "\x90" => [94, "\x8ac"], "\x91" => [76, "\x8ac"], "\x92" => [104, "\x8ac"], "\x93" => [16, "\x8ac"], "\x94" => [94, "\x8ae"], "\x95" => [76, "\x8ae"], "\x96" => [104, "\x8ae"], "\x97" => [16, "\x8ae"], "\x98" => [94, "\x8ai"], "\x99" => [76, "\x8ai"], "\x9a" => [104, "\x8ai"], "\x9b" => [16, "\x8ai"], "\x9c" => [94, "\x8ao"], "\x9d" => [76, "\x8ao"], "\x9e" => [104, "\x8ao"], "\x9f" => [16, "\x8ao"], "\xa0" => [94, "\x8as"], "\xa1" => [76, "\x8as"], "\xa2" => [104, "\x8as"], "\xa3" => [16, "\x8as"], "\xa4" => [94, "\x8at"], "\xa5" => [76, "\x8at"], "\xa6" => [104, "\x8at"], "\xa7" => [16, "\x8at"], "\xa8" => [77, "\x8a "], "\xa9" => [18, "\x8a "], "\xaa" => [77, "\x8a%"], "\xab" => [18, "\x8a%"], "\xac" => [77, "\x8a-"], "\xad" => [18, "\x8a-"], "\xae" => [77, "\x8a."], "\xaf" => [18, "\x8a."], "\xb0" => [77, "\x8a/"], "\xb1" => [18, "\x8a/"], "\xb2" => [77, "\x8a3"], "\xb3" => [18, "\x8a3"], "\xb4" => [77, "\x8a4"], "\xb5" => [18, "\x8a4"], "\xb6" => [77, "\x8a5"], "\xb7" => [18, "\x8a5"], "\xb8" => [77, "\x8a6"], "\xb9" => [18, "\x8a6"], "\xba" => [77, "\x8a7"], "\xbb" => [18, "\x8a7"], "\xbc" => [77, "\x8a8"], "\xbd" => [18, "\x8a8"], "\xbe" => [77, "\x8a9"], "\xbf" => [18, "\x8a9"], "\xc0" => [77, "\x8a="], "\xc1" => [18, "\x8a="], "\xc2" => [77, "\x8aA"], "\xc3" => [18, "\x8aA"], "\xc4" => [77, "\x8a_"], "\xc5" => [18, "\x8a_"], "\xc6" => [77, "\x8ab"], "\xc7" => [18, "\x8ab"], "\xc8" => [77, "\x8ad"], "\xc9" => [18, "\x8ad"], "\xca" => [77, "\x8af"], "\xcb" => [18, "\x8af"], "\xcc" => [77, "\x8ag"], "\xcd" => [18, "\x8ag"], "\xce" => [77, "\x8ah"], "\xcf" => [18, "\x8ah"], "\xd0" => [77, "\x8al"], "\xd1" => [18, "\x8al"], "\xd2" => [77, "\x8am"], "\xd3" => [18, "\x8am"], "\xd4" => [77, "\x8an"], "\xd5" => [18, "\x8an"], "\xd6" => [77, "\x8ap"], "\xd7" => [18, "\x8ap"], "\xd8" => [77, "\x8ar"], "\xd9" => [18, "\x8ar"], "\xda" => [77, "\x8au"], "\xdb" => [18, "\x8au"], "\xdc" => [0, "\x8a:"], "\xdd" => [0, "\x8aB"], "\xde" => [0, "\x8aC"], "\xdf" => [0, "\x8aD"], "\xe0" => [0, "\x8aE"], "\xe1" => [0, "\x8aF"], "\xe2" => [0, "\x8aG"], "\xe3" => [0, "\x8aH"], "\xe4" => [0, "\x8aI"], "\xe5" => [0, "\x8aJ"], "\xe6" => [0, "\x8aK"], "\xe7" => [0, "\x8aL"], "\xe8" => [0, "\x8aM"], "\xe9" => [0, "\x8aN"], "\xea" => [0, "\x8aO"], "\xeb" => [0, "\x8aP"], "\xec" => [0, "\x8aQ"], "\xed" => [0, "\x8aR"], "\xee" => [0, "\x8aS"], "\xef" => [0, "\x8aT"], "\xf0" => [0, "\x8aU"], "\xf1" => [0, "\x8aV"], "\xf2" => [0, "\x8aW"], "\xf3" => [0, "\x8aY"], "\xf4" => [0, "\x8aj"], "\xf5" => [0, "\x8ak"], "\xf6" => [0, "\x8aq"], "\xf7" => [0, "\x8av"], "\xf8" => [0, "\x8aw"], "\xf9" => [0, "\x8ax"], "\xfa" => [0, "\x8ay"], "\xfb" => [0, "\x8az"], "\xfc" => [82, "\x8a"], "\xfd" => [87, "\x8a"], "\xfe" => [130, "\x8a"], "\xff" => [9, "\x8a"]], ["\x00" => [94, "\x8b0"], "\x01" => [76, "\x8b0"], "\x02" => [104, "\x8b0"], "\x03" => [16, "\x8b0"], "\x04" => [94, "\x8b1"], "\x05" => [76, "\x8b1"], "\x06" => [104, "\x8b1"], "\x07" => [16, "\x8b1"], "\x08" => [94, "\x8b2"], "\t" => [76, "\x8b2"], "\n" => [104, "\x8b2"], "\v" => [16, "\x8b2"], "\f" => [94, "\x8ba"], "\r" => [76, "\x8ba"], "\x0e" => [104, "\x8ba"], "\x0f" => [16, "\x8ba"], "\x10" => [94, "\x8bc"], "\x11" => [76, "\x8bc"], "\x12" => [104, "\x8bc"], "\x13" => [16, "\x8bc"], "\x14" => [94, "\x8be"], "\x15" => [76, "\x8be"], "\x16" => [104, "\x8be"], "\x17" => [16, "\x8be"], "\x18" => [94, "\x8bi"], "\x19" => [76, "\x8bi"], "\x1a" => [104, "\x8bi"], "\x1b" => [16, "\x8bi"], "\x1c" => [94, "\x8bo"], "\x1d" => [76, "\x8bo"], "\x1e" => [104, "\x8bo"], "\x1f" => [16, "\x8bo"], " " => [94, "\x8bs"], "!" => [76, "\x8bs"], "\"" => [104, "\x8bs"], "#" => [16, "\x8bs"], "\$" => [94, "\x8bt"], "%" => [76, "\x8bt"], "&" => [104, "\x8bt"], "'" => [16, "\x8bt"], "(" => [77, "\x8b "], ")" => [18, "\x8b "], "*" => [77, "\x8b%"], "+" => [18, "\x8b%"], "," => [77, "\x8b-"], "-" => [18, "\x8b-"], "." => [77, "\x8b."], "/" => [18, "\x8b."], [77, "\x8b/"], [18, "\x8b/"], [77, "\x8b3"], [18, "\x8b3"], [77, "\x8b4"], [18, "\x8b4"], [77, "\x8b5"], [18, "\x8b5"], [77, "\x8b6"], [18, "\x8b6"], ":" => [77, "\x8b7"], ";" => [18, "\x8b7"], "<" => [77, "\x8b8"], "=" => [18, "\x8b8"], ">" => [77, "\x8b9"], "?" => [18, "\x8b9"], "@" => [77, "\x8b="], "A" => [18, "\x8b="], "B" => [77, "\x8bA"], "C" => [18, "\x8bA"], "D" => [77, "\x8b_"], "E" => [18, "\x8b_"], "F" => [77, "\x8bb"], "G" => [18, "\x8bb"], "H" => [77, "\x8bd"], "I" => [18, "\x8bd"], "J" => [77, "\x8bf"], "K" => [18, "\x8bf"], "L" => [77, "\x8bg"], "M" => [18, "\x8bg"], "N" => [77, "\x8bh"], "O" => [18, "\x8bh"], "P" => [77, "\x8bl"], "Q" => [18, "\x8bl"], "R" => [77, "\x8bm"], "S" => [18, "\x8bm"], "T" => [77, "\x8bn"], "U" => [18, "\x8bn"], "V" => [77, "\x8bp"], "W" => [18, "\x8bp"], "X" => [77, "\x8br"], "Y" => [18, "\x8br"], "Z" => [77, "\x8bu"], "[" => [18, "\x8bu"], "\\" => [0, "\x8b:"], "]" => [0, "\x8bB"], "^" => [0, "\x8bC"], "_" => [0, "\x8bD"], "`" => [0, "\x8bE"], "a" => [0, "\x8bF"], "b" => [0, "\x8bG"], "c" => [0, "\x8bH"], "d" => [0, "\x8bI"], "e" => [0, "\x8bJ"], "f" => [0, "\x8bK"], "g" => [0, "\x8bL"], "h" => [0, "\x8bM"], "i" => [0, "\x8bN"], "j" => [0, "\x8bO"], "k" => [0, "\x8bP"], "l" => [0, "\x8bQ"], "m" => [0, "\x8bR"], "n" => [0, "\x8bS"], "o" => [0, "\x8bT"], "p" => [0, "\x8bU"], "q" => [0, "\x8bV"], "r" => [0, "\x8bW"], "s" => [0, "\x8bY"], "t" => [0, "\x8bj"], "u" => [0, "\x8bk"], "v" => [0, "\x8bq"], "w" => [0, "\x8bv"], "x" => [0, "\x8bw"], "y" => [0, "\x8bx"], "z" => [0, "\x8by"], "{" => [0, "\x8bz"], "|" => [82, "\x8b"], "}" => [87, "\x8b"], "~" => [130, "\x8b"], "" => [9, "\x8b"], "\x80" => [94, "\x8c0"], "\x81" => [76, "\x8c0"], "\x82" => [104, "\x8c0"], "\x83" => [16, "\x8c0"], "\x84" => [94, "\x8c1"], "\x85" => [76, "\x8c1"], "\x86" => [104, "\x8c1"], "\x87" => [16, "\x8c1"], "\x88" => [94, "\x8c2"], "\x89" => [76, "\x8c2"], "\x8a" => [104, "\x8c2"], "\x8b" => [16, "\x8c2"], "\x8c" => [94, "\x8ca"], "\x8d" => [76, "\x8ca"], "\x8e" => [104, "\x8ca"], "\x8f" => [16, "\x8ca"], "\x90" => [94, "\x8cc"], "\x91" => [76, "\x8cc"], "\x92" => [104, "\x8cc"], "\x93" => [16, "\x8cc"], "\x94" => [94, "\x8ce"], "\x95" => [76, "\x8ce"], "\x96" => [104, "\x8ce"], "\x97" => [16, "\x8ce"], "\x98" => [94, "\x8ci"], "\x99" => [76, "\x8ci"], "\x9a" => [104, "\x8ci"], "\x9b" => [16, "\x8ci"], "\x9c" => [94, "\x8co"], "\x9d" => [76, "\x8co"], "\x9e" => [104, "\x8co"], "\x9f" => [16, "\x8co"], "\xa0" => [94, "\x8cs"], "\xa1" => [76, "\x8cs"], "\xa2" => [104, "\x8cs"], "\xa3" => [16, "\x8cs"], "\xa4" => [94, "\x8ct"], "\xa5" => [76, "\x8ct"], "\xa6" => [104, "\x8ct"], "\xa7" => [16, "\x8ct"], "\xa8" => [77, "\x8c "], "\xa9" => [18, "\x8c "], "\xaa" => [77, "\x8c%"], "\xab" => [18, "\x8c%"], "\xac" => [77, "\x8c-"], "\xad" => [18, "\x8c-"], "\xae" => [77, "\x8c."], "\xaf" => [18, "\x8c."], "\xb0" => [77, "\x8c/"], "\xb1" => [18, "\x8c/"], "\xb2" => [77, "\x8c3"], "\xb3" => [18, "\x8c3"], "\xb4" => [77, "\x8c4"], "\xb5" => [18, "\x8c4"], "\xb6" => [77, "\x8c5"], "\xb7" => [18, "\x8c5"], "\xb8" => [77, "\x8c6"], "\xb9" => [18, "\x8c6"], "\xba" => [77, "\x8c7"], "\xbb" => [18, "\x8c7"], "\xbc" => [77, "\x8c8"], "\xbd" => [18, "\x8c8"], "\xbe" => [77, "\x8c9"], "\xbf" => [18, "\x8c9"], "\xc0" => [77, "\x8c="], "\xc1" => [18, "\x8c="], "\xc2" => [77, "\x8cA"], "\xc3" => [18, "\x8cA"], "\xc4" => [77, "\x8c_"], "\xc5" => [18, "\x8c_"], "\xc6" => [77, "\x8cb"], "\xc7" => [18, "\x8cb"], "\xc8" => [77, "\x8cd"], "\xc9" => [18, "\x8cd"], "\xca" => [77, "\x8cf"], "\xcb" => [18, "\x8cf"], "\xcc" => [77, "\x8cg"], "\xcd" => [18, "\x8cg"], "\xce" => [77, "\x8ch"], "\xcf" => [18, "\x8ch"], "\xd0" => [77, "\x8cl"], "\xd1" => [18, "\x8cl"], "\xd2" => [77, "\x8cm"], "\xd3" => [18, "\x8cm"], "\xd4" => [77, "\x8cn"], "\xd5" => [18, "\x8cn"], "\xd6" => [77, "\x8cp"], "\xd7" => [18, "\x8cp"], "\xd8" => [77, "\x8cr"], "\xd9" => [18, "\x8cr"], "\xda" => [77, "\x8cu"], "\xdb" => [18, "\x8cu"], "\xdc" => [0, "\x8c:"], "\xdd" => [0, "\x8cB"], "\xde" => [0, "\x8cC"], "\xdf" => [0, "\x8cD"], "\xe0" => [0, "\x8cE"], "\xe1" => [0, "\x8cF"], "\xe2" => [0, "\x8cG"], "\xe3" => [0, "\x8cH"], "\xe4" => [0, "\x8cI"], "\xe5" => [0, "\x8cJ"], "\xe6" => [0, "\x8cK"], "\xe7" => [0, "\x8cL"], "\xe8" => [0, "\x8cM"], "\xe9" => [0, "\x8cN"], "\xea" => [0, "\x8cO"], "\xeb" => [0, "\x8cP"], "\xec" => [0, "\x8cQ"], "\xed" => [0, "\x8cR"], "\xee" => [0, "\x8cS"], "\xef" => [0, "\x8cT"], "\xf0" => [0, "\x8cU"], "\xf1" => [0, "\x8cV"], "\xf2" => [0, "\x8cW"], "\xf3" => [0, "\x8cY"], "\xf4" => [0, "\x8cj"], "\xf5" => [0, "\x8ck"], "\xf6" => [0, "\x8cq"], "\xf7" => [0, "\x8cv"], "\xf8" => [0, "\x8cw"], "\xf9" => [0, "\x8cx"], "\xfa" => [0, "\x8cy"], "\xfb" => [0, "\x8cz"], "\xfc" => [82, "\x8c"], "\xfd" => [87, "\x8c"], "\xfe" => [130, "\x8c"], "\xff" => [9, "\x8c"]], ["\x00" => [77, "\x8b0"], "\x01" => [18, "\x8b0"], "\x02" => [77, "\x8b1"], "\x03" => [18, "\x8b1"], "\x04" => [77, "\x8b2"], "\x05" => [18, "\x8b2"], "\x06" => [77, "\x8ba"], "\x07" => [18, "\x8ba"], "\x08" => [77, "\x8bc"], "\t" => [18, "\x8bc"], "\n" => [77, "\x8be"], "\v" => [18, "\x8be"], "\f" => [77, "\x8bi"], "\r" => [18, "\x8bi"], "\x0e" => [77, "\x8bo"], "\x0f" => [18, "\x8bo"], "\x10" => [77, "\x8bs"], "\x11" => [18, "\x8bs"], "\x12" => [77, "\x8bt"], "\x13" => [18, "\x8bt"], "\x14" => [0, "\x8b "], "\x15" => [0, "\x8b%"], "\x16" => [0, "\x8b-"], "\x17" => [0, "\x8b."], "\x18" => [0, "\x8b/"], "\x19" => [0, "\x8b3"], "\x1a" => [0, "\x8b4"], "\x1b" => [0, "\x8b5"], "\x1c" => [0, "\x8b6"], "\x1d" => [0, "\x8b7"], "\x1e" => [0, "\x8b8"], "\x1f" => [0, "\x8b9"], " " => [0, "\x8b="], "!" => [0, "\x8bA"], "\"" => [0, "\x8b_"], "#" => [0, "\x8bb"], "\$" => [0, "\x8bd"], "%" => [0, "\x8bf"], "&" => [0, "\x8bg"], "'" => [0, "\x8bh"], "(" => [0, "\x8bl"], ")" => [0, "\x8bm"], "*" => [0, "\x8bn"], "+" => [0, "\x8bp"], "," => [0, "\x8br"], "-" => [0, "\x8bu"], "." => [100, "\x8b"], "/" => [110, "\x8b"], [111, "\x8b"], [115, "\x8b"], [116, "\x8b"], [118, "\x8b"], [119, "\x8b"], [122, "\x8b"], [123, "\x8b"], [125, "\x8b"], [126, "\x8b"], [129, "\x8b"], ":" => [143, "\x8b"], ";" => [148, "\x8b"], "<" => [151, "\x8b"], "=" => [153, "\x8b"], ">" => [83, "\x8b"], "?" => [10, "\x8b"], "@" => [77, "\x8c0"], "A" => [18, "\x8c0"], "B" => [77, "\x8c1"], "C" => [18, "\x8c1"], "D" => [77, "\x8c2"], "E" => [18, "\x8c2"], "F" => [77, "\x8ca"], "G" => [18, "\x8ca"], "H" => [77, "\x8cc"], "I" => [18, "\x8cc"], "J" => [77, "\x8ce"], "K" => [18, "\x8ce"], "L" => [77, "\x8ci"], "M" => [18, "\x8ci"], "N" => [77, "\x8co"], "O" => [18, "\x8co"], "P" => [77, "\x8cs"], "Q" => [18, "\x8cs"], "R" => [77, "\x8ct"], "S" => [18, "\x8ct"], "T" => [0, "\x8c "], "U" => [0, "\x8c%"], "V" => [0, "\x8c-"], "W" => [0, "\x8c."], "X" => [0, "\x8c/"], "Y" => [0, "\x8c3"], "Z" => [0, "\x8c4"], "[" => [0, "\x8c5"], "\\" => [0, "\x8c6"], "]" => [0, "\x8c7"], "^" => [0, "\x8c8"], "_" => [0, "\x8c9"], "`" => [0, "\x8c="], "a" => [0, "\x8cA"], "b" => [0, "\x8c_"], "c" => [0, "\x8cb"], "d" => [0, "\x8cd"], "e" => [0, "\x8cf"], "f" => [0, "\x8cg"], "g" => [0, "\x8ch"], "h" => [0, "\x8cl"], "i" => [0, "\x8cm"], "j" => [0, "\x8cn"], "k" => [0, "\x8cp"], "l" => [0, "\x8cr"], "m" => [0, "\x8cu"], "n" => [100, "\x8c"], "o" => [110, "\x8c"], "p" => [111, "\x8c"], "q" => [115, "\x8c"], "r" => [116, "\x8c"], "s" => [118, "\x8c"], "t" => [119, "\x8c"], "u" => [122, "\x8c"], "v" => [123, "\x8c"], "w" => [125, "\x8c"], "x" => [126, "\x8c"], "y" => [129, "\x8c"], "z" => [143, "\x8c"], "{" => [148, "\x8c"], "|" => [151, "\x8c"], "}" => [153, "\x8c"], "~" => [83, "\x8c"], "" => [10, "\x8c"], "\x80" => [77, "\x8d0"], "\x81" => [18, "\x8d0"], "\x82" => [77, "\x8d1"], "\x83" => [18, "\x8d1"], "\x84" => [77, "\x8d2"], "\x85" => [18, "\x8d2"], "\x86" => [77, "\x8da"], "\x87" => [18, "\x8da"], "\x88" => [77, "\x8dc"], "\x89" => [18, "\x8dc"], "\x8a" => [77, "\x8de"], "\x8b" => [18, "\x8de"], "\x8c" => [77, "\x8di"], "\x8d" => [18, "\x8di"], "\x8e" => [77, "\x8do"], "\x8f" => [18, "\x8do"], "\x90" => [77, "\x8ds"], "\x91" => [18, "\x8ds"], "\x92" => [77, "\x8dt"], "\x93" => [18, "\x8dt"], "\x94" => [0, "\x8d "], "\x95" => [0, "\x8d%"], "\x96" => [0, "\x8d-"], "\x97" => [0, "\x8d."], "\x98" => [0, "\x8d/"], "\x99" => [0, "\x8d3"], "\x9a" => [0, "\x8d4"], "\x9b" => [0, "\x8d5"], "\x9c" => [0, "\x8d6"], "\x9d" => [0, "\x8d7"], "\x9e" => [0, "\x8d8"], "\x9f" => [0, "\x8d9"], "\xa0" => [0, "\x8d="], "\xa1" => [0, "\x8dA"], "\xa2" => [0, "\x8d_"], "\xa3" => [0, "\x8db"], "\xa4" => [0, "\x8dd"], "\xa5" => [0, "\x8df"], "\xa6" => [0, "\x8dg"], "\xa7" => [0, "\x8dh"], "\xa8" => [0, "\x8dl"], "\xa9" => [0, "\x8dm"], "\xaa" => [0, "\x8dn"], "\xab" => [0, "\x8dp"], "\xac" => [0, "\x8dr"], "\xad" => [0, "\x8du"], "\xae" => [100, "\x8d"], "\xaf" => [110, "\x8d"], "\xb0" => [111, "\x8d"], "\xb1" => [115, "\x8d"], "\xb2" => [116, "\x8d"], "\xb3" => [118, "\x8d"], "\xb4" => [119, "\x8d"], "\xb5" => [122, "\x8d"], "\xb6" => [123, "\x8d"], "\xb7" => [125, "\x8d"], "\xb8" => [126, "\x8d"], "\xb9" => [129, "\x8d"], "\xba" => [143, "\x8d"], "\xbb" => [148, "\x8d"], "\xbc" => [151, "\x8d"], "\xbd" => [153, "\x8d"], "\xbe" => [83, "\x8d"], "\xbf" => [10, "\x8d"], "\xc0" => [77, "\x8f0"], "\xc1" => [18, "\x8f0"], "\xc2" => [77, "\x8f1"], "\xc3" => [18, "\x8f1"], "\xc4" => [77, "\x8f2"], "\xc5" => [18, "\x8f2"], "\xc6" => [77, "\x8fa"], "\xc7" => [18, "\x8fa"], "\xc8" => [77, "\x8fc"], "\xc9" => [18, "\x8fc"], "\xca" => [77, "\x8fe"], "\xcb" => [18, "\x8fe"], "\xcc" => [77, "\x8fi"], "\xcd" => [18, "\x8fi"], "\xce" => [77, "\x8fo"], "\xcf" => [18, "\x8fo"], "\xd0" => [77, "\x8fs"], "\xd1" => [18, "\x8fs"], "\xd2" => [77, "\x8ft"], "\xd3" => [18, "\x8ft"], "\xd4" => [0, "\x8f "], "\xd5" => [0, "\x8f%"], "\xd6" => [0, "\x8f-"], "\xd7" => [0, "\x8f."], "\xd8" => [0, "\x8f/"], "\xd9" => [0, "\x8f3"], "\xda" => [0, "\x8f4"], "\xdb" => [0, "\x8f5"], "\xdc" => [0, "\x8f6"], "\xdd" => [0, "\x8f7"], "\xde" => [0, "\x8f8"], "\xdf" => [0, "\x8f9"], "\xe0" => [0, "\x8f="], "\xe1" => [0, "\x8fA"], "\xe2" => [0, "\x8f_"], "\xe3" => [0, "\x8fb"], "\xe4" => [0, "\x8fd"], "\xe5" => [0, "\x8ff"], "\xe6" => [0, "\x8fg"], "\xe7" => [0, "\x8fh"], "\xe8" => [0, "\x8fl"], "\xe9" => [0, "\x8fm"], "\xea" => [0, "\x8fn"], "\xeb" => [0, "\x8fp"], "\xec" => [0, "\x8fr"], "\xed" => [0, "\x8fu"], "\xee" => [100, "\x8f"], "\xef" => [110, "\x8f"], "\xf0" => [111, "\x8f"], "\xf1" => [115, "\x8f"], "\xf2" => [116, "\x8f"], "\xf3" => [118, "\x8f"], "\xf4" => [119, "\x8f"], "\xf5" => [122, "\x8f"], "\xf6" => [123, "\x8f"], "\xf7" => [125, "\x8f"], "\xf8" => [126, "\x8f"], "\xf9" => [129, "\x8f"], "\xfa" => [143, "\x8f"], "\xfb" => [148, "\x8f"], "\xfc" => [151, "\x8f"], "\xfd" => [153, "\x8f"], "\xfe" => [83, "\x8f"], "\xff" => [10, "\x8f"]], ["\x00" => [94, "\x8d0"], "\x01" => [76, "\x8d0"], "\x02" => [104, "\x8d0"], "\x03" => [16, "\x8d0"], "\x04" => [94, "\x8d1"], "\x05" => [76, "\x8d1"], "\x06" => [104, "\x8d1"], "\x07" => [16, "\x8d1"], "\x08" => [94, "\x8d2"], "\t" => [76, "\x8d2"], "\n" => [104, "\x8d2"], "\v" => [16, "\x8d2"], "\f" => [94, "\x8da"], "\r" => [76, "\x8da"], "\x0e" => [104, "\x8da"], "\x0f" => [16, "\x8da"], "\x10" => [94, "\x8dc"], "\x11" => [76, "\x8dc"], "\x12" => [104, "\x8dc"], "\x13" => [16, "\x8dc"], "\x14" => [94, "\x8de"], "\x15" => [76, "\x8de"], "\x16" => [104, "\x8de"], "\x17" => [16, "\x8de"], "\x18" => [94, "\x8di"], "\x19" => [76, "\x8di"], "\x1a" => [104, "\x8di"], "\x1b" => [16, "\x8di"], "\x1c" => [94, "\x8do"], "\x1d" => [76, "\x8do"], "\x1e" => [104, "\x8do"], "\x1f" => [16, "\x8do"], " " => [94, "\x8ds"], "!" => [76, "\x8ds"], "\"" => [104, "\x8ds"], "#" => [16, "\x8ds"], "\$" => [94, "\x8dt"], "%" => [76, "\x8dt"], "&" => [104, "\x8dt"], "'" => [16, "\x8dt"], "(" => [77, "\x8d "], ")" => [18, "\x8d "], "*" => [77, "\x8d%"], "+" => [18, "\x8d%"], "," => [77, "\x8d-"], "-" => [18, "\x8d-"], "." => [77, "\x8d."], "/" => [18, "\x8d."], [77, "\x8d/"], [18, "\x8d/"], [77, "\x8d3"], [18, "\x8d3"], [77, "\x8d4"], [18, "\x8d4"], [77, "\x8d5"], [18, "\x8d5"], [77, "\x8d6"], [18, "\x8d6"], ":" => [77, "\x8d7"], ";" => [18, "\x8d7"], "<" => [77, "\x8d8"], "=" => [18, "\x8d8"], ">" => [77, "\x8d9"], "?" => [18, "\x8d9"], "@" => [77, "\x8d="], "A" => [18, "\x8d="], "B" => [77, "\x8dA"], "C" => [18, "\x8dA"], "D" => [77, "\x8d_"], "E" => [18, "\x8d_"], "F" => [77, "\x8db"], "G" => [18, "\x8db"], "H" => [77, "\x8dd"], "I" => [18, "\x8dd"], "J" => [77, "\x8df"], "K" => [18, "\x8df"], "L" => [77, "\x8dg"], "M" => [18, "\x8dg"], "N" => [77, "\x8dh"], "O" => [18, "\x8dh"], "P" => [77, "\x8dl"], "Q" => [18, "\x8dl"], "R" => [77, "\x8dm"], "S" => [18, "\x8dm"], "T" => [77, "\x8dn"], "U" => [18, "\x8dn"], "V" => [77, "\x8dp"], "W" => [18, "\x8dp"], "X" => [77, "\x8dr"], "Y" => [18, "\x8dr"], "Z" => [77, "\x8du"], "[" => [18, "\x8du"], "\\" => [0, "\x8d:"], "]" => [0, "\x8dB"], "^" => [0, "\x8dC"], "_" => [0, "\x8dD"], "`" => [0, "\x8dE"], "a" => [0, "\x8dF"], "b" => [0, "\x8dG"], "c" => [0, "\x8dH"], "d" => [0, "\x8dI"], "e" => [0, "\x8dJ"], "f" => [0, "\x8dK"], "g" => [0, "\x8dL"], "h" => [0, "\x8dM"], "i" => [0, "\x8dN"], "j" => [0, "\x8dO"], "k" => [0, "\x8dP"], "l" => [0, "\x8dQ"], "m" => [0, "\x8dR"], "n" => [0, "\x8dS"], "o" => [0, "\x8dT"], "p" => [0, "\x8dU"], "q" => [0, "\x8dV"], "r" => [0, "\x8dW"], "s" => [0, "\x8dY"], "t" => [0, "\x8dj"], "u" => [0, "\x8dk"], "v" => [0, "\x8dq"], "w" => [0, "\x8dv"], "x" => [0, "\x8dw"], "y" => [0, "\x8dx"], "z" => [0, "\x8dy"], "{" => [0, "\x8dz"], "|" => [82, "\x8d"], "}" => [87, "\x8d"], "~" => [130, "\x8d"], "" => [9, "\x8d"], "\x80" => [94, "\x8f0"], "\x81" => [76, "\x8f0"], "\x82" => [104, "\x8f0"], "\x83" => [16, "\x8f0"], "\x84" => [94, "\x8f1"], "\x85" => [76, "\x8f1"], "\x86" => [104, "\x8f1"], "\x87" => [16, "\x8f1"], "\x88" => [94, "\x8f2"], "\x89" => [76, "\x8f2"], "\x8a" => [104, "\x8f2"], "\x8b" => [16, "\x8f2"], "\x8c" => [94, "\x8fa"], "\x8d" => [76, "\x8fa"], "\x8e" => [104, "\x8fa"], "\x8f" => [16, "\x8fa"], "\x90" => [94, "\x8fc"], "\x91" => [76, "\x8fc"], "\x92" => [104, "\x8fc"], "\x93" => [16, "\x8fc"], "\x94" => [94, "\x8fe"], "\x95" => [76, "\x8fe"], "\x96" => [104, "\x8fe"], "\x97" => [16, "\x8fe"], "\x98" => [94, "\x8fi"], "\x99" => [76, "\x8fi"], "\x9a" => [104, "\x8fi"], "\x9b" => [16, "\x8fi"], "\x9c" => [94, "\x8fo"], "\x9d" => [76, "\x8fo"], "\x9e" => [104, "\x8fo"], "\x9f" => [16, "\x8fo"], "\xa0" => [94, "\x8fs"], "\xa1" => [76, "\x8fs"], "\xa2" => [104, "\x8fs"], "\xa3" => [16, "\x8fs"], "\xa4" => [94, "\x8ft"], "\xa5" => [76, "\x8ft"], "\xa6" => [104, "\x8ft"], "\xa7" => [16, "\x8ft"], "\xa8" => [77, "\x8f "], "\xa9" => [18, "\x8f "], "\xaa" => [77, "\x8f%"], "\xab" => [18, "\x8f%"], "\xac" => [77, "\x8f-"], "\xad" => [18, "\x8f-"], "\xae" => [77, "\x8f."], "\xaf" => [18, "\x8f."], "\xb0" => [77, "\x8f/"], "\xb1" => [18, "\x8f/"], "\xb2" => [77, "\x8f3"], "\xb3" => [18, "\x8f3"], "\xb4" => [77, "\x8f4"], "\xb5" => [18, "\x8f4"], "\xb6" => [77, "\x8f5"], "\xb7" => [18, "\x8f5"], "\xb8" => [77, "\x8f6"], "\xb9" => [18, "\x8f6"], "\xba" => [77, "\x8f7"], "\xbb" => [18, "\x8f7"], "\xbc" => [77, "\x8f8"], "\xbd" => [18, "\x8f8"], "\xbe" => [77, "\x8f9"], "\xbf" => [18, "\x8f9"], "\xc0" => [77, "\x8f="], "\xc1" => [18, "\x8f="], "\xc2" => [77, "\x8fA"], "\xc3" => [18, "\x8fA"], "\xc4" => [77, "\x8f_"], "\xc5" => [18, "\x8f_"], "\xc6" => [77, "\x8fb"], "\xc7" => [18, "\x8fb"], "\xc8" => [77, "\x8fd"], "\xc9" => [18, "\x8fd"], "\xca" => [77, "\x8ff"], "\xcb" => [18, "\x8ff"], "\xcc" => [77, "\x8fg"], "\xcd" => [18, "\x8fg"], "\xce" => [77, "\x8fh"], "\xcf" => [18, "\x8fh"], "\xd0" => [77, "\x8fl"], "\xd1" => [18, "\x8fl"], "\xd2" => [77, "\x8fm"], "\xd3" => [18, "\x8fm"], "\xd4" => [77, "\x8fn"], "\xd5" => [18, "\x8fn"], "\xd6" => [77, "\x8fp"], "\xd7" => [18, "\x8fp"], "\xd8" => [77, "\x8fr"], "\xd9" => [18, "\x8fr"], "\xda" => [77, "\x8fu"], "\xdb" => [18, "\x8fu"], "\xdc" => [0, "\x8f:"], "\xdd" => [0, "\x8fB"], "\xde" => [0, "\x8fC"], "\xdf" => [0, "\x8fD"], "\xe0" => [0, "\x8fE"], "\xe1" => [0, "\x8fF"], "\xe2" => [0, "\x8fG"], "\xe3" => [0, "\x8fH"], "\xe4" => [0, "\x8fI"], "\xe5" => [0, "\x8fJ"], "\xe6" => [0, "\x8fK"], "\xe7" => [0, "\x8fL"], "\xe8" => [0, "\x8fM"], "\xe9" => [0, "\x8fN"], "\xea" => [0, "\x8fO"], "\xeb" => [0, "\x8fP"], "\xec" => [0, "\x8fQ"], "\xed" => [0, "\x8fR"], "\xee" => [0, "\x8fS"], "\xef" => [0, "\x8fT"], "\xf0" => [0, "\x8fU"], "\xf1" => [0, "\x8fV"], "\xf2" => [0, "\x8fW"], "\xf3" => [0, "\x8fY"], "\xf4" => [0, "\x8fj"], "\xf5" => [0, "\x8fk"], "\xf6" => [0, "\x8fq"], "\xf7" => [0, "\x8fv"], "\xf8" => [0, "\x8fw"], "\xf9" => [0, "\x8fx"], "\xfa" => [0, "\x8fy"], "\xfb" => [0, "\x8fz"], "\xfc" => [82, "\x8f"], "\xfd" => [87, "\x8f"], "\xfe" => [130, "\x8f"], "\xff" => [9, "\x8f"]], ["\x00" => [94, "\x900"], "\x01" => [76, "\x900"], "\x02" => [104, "\x900"], "\x03" => [16, "\x900"], "\x04" => [94, "\x901"], "\x05" => [76, "\x901"], "\x06" => [104, "\x901"], "\x07" => [16, "\x901"], "\x08" => [94, "\x902"], "\t" => [76, "\x902"], "\n" => [104, "\x902"], "\v" => [16, "\x902"], "\f" => [94, "\x90a"], "\r" => [76, "\x90a"], "\x0e" => [104, "\x90a"], "\x0f" => [16, "\x90a"], "\x10" => [94, "\x90c"], "\x11" => [76, "\x90c"], "\x12" => [104, "\x90c"], "\x13" => [16, "\x90c"], "\x14" => [94, "\x90e"], "\x15" => [76, "\x90e"], "\x16" => [104, "\x90e"], "\x17" => [16, "\x90e"], "\x18" => [94, "\x90i"], "\x19" => [76, "\x90i"], "\x1a" => [104, "\x90i"], "\x1b" => [16, "\x90i"], "\x1c" => [94, "\x90o"], "\x1d" => [76, "\x90o"], "\x1e" => [104, "\x90o"], "\x1f" => [16, "\x90o"], " " => [94, "\x90s"], "!" => [76, "\x90s"], "\"" => [104, "\x90s"], "#" => [16, "\x90s"], "\$" => [94, "\x90t"], "%" => [76, "\x90t"], "&" => [104, "\x90t"], "'" => [16, "\x90t"], "(" => [77, "\x90 "], ")" => [18, "\x90 "], "*" => [77, "\x90%"], "+" => [18, "\x90%"], "," => [77, "\x90-"], "-" => [18, "\x90-"], "." => [77, "\x90."], "/" => [18, "\x90."], [77, "\x90/"], [18, "\x90/"], [77, "\x903"], [18, "\x903"], [77, "\x904"], [18, "\x904"], [77, "\x905"], [18, "\x905"], [77, "\x906"], [18, "\x906"], ":" => [77, "\x907"], ";" => [18, "\x907"], "<" => [77, "\x908"], "=" => [18, "\x908"], ">" => [77, "\x909"], "?" => [18, "\x909"], "@" => [77, "\x90="], "A" => [18, "\x90="], "B" => [77, "\x90A"], "C" => [18, "\x90A"], "D" => [77, "\x90_"], "E" => [18, "\x90_"], "F" => [77, "\x90b"], "G" => [18, "\x90b"], "H" => [77, "\x90d"], "I" => [18, "\x90d"], "J" => [77, "\x90f"], "K" => [18, "\x90f"], "L" => [77, "\x90g"], "M" => [18, "\x90g"], "N" => [77, "\x90h"], "O" => [18, "\x90h"], "P" => [77, "\x90l"], "Q" => [18, "\x90l"], "R" => [77, "\x90m"], "S" => [18, "\x90m"], "T" => [77, "\x90n"], "U" => [18, "\x90n"], "V" => [77, "\x90p"], "W" => [18, "\x90p"], "X" => [77, "\x90r"], "Y" => [18, "\x90r"], "Z" => [77, "\x90u"], "[" => [18, "\x90u"], "\\" => [0, "\x90:"], "]" => [0, "\x90B"], "^" => [0, "\x90C"], "_" => [0, "\x90D"], "`" => [0, "\x90E"], "a" => [0, "\x90F"], "b" => [0, "\x90G"], "c" => [0, "\x90H"], "d" => [0, "\x90I"], "e" => [0, "\x90J"], "f" => [0, "\x90K"], "g" => [0, "\x90L"], "h" => [0, "\x90M"], "i" => [0, "\x90N"], "j" => [0, "\x90O"], "k" => [0, "\x90P"], "l" => [0, "\x90Q"], "m" => [0, "\x90R"], "n" => [0, "\x90S"], "o" => [0, "\x90T"], "p" => [0, "\x90U"], "q" => [0, "\x90V"], "r" => [0, "\x90W"], "s" => [0, "\x90Y"], "t" => [0, "\x90j"], "u" => [0, "\x90k"], "v" => [0, "\x90q"], "w" => [0, "\x90v"], "x" => [0, "\x90w"], "y" => [0, "\x90x"], "z" => [0, "\x90y"], "{" => [0, "\x90z"], "|" => [82, "\x90"], "}" => [87, "\x90"], "~" => [130, "\x90"], "" => [9, "\x90"], "\x80" => [94, "\x910"], "\x81" => [76, "\x910"], "\x82" => [104, "\x910"], "\x83" => [16, "\x910"], "\x84" => [94, "\x911"], "\x85" => [76, "\x911"], "\x86" => [104, "\x911"], "\x87" => [16, "\x911"], "\x88" => [94, "\x912"], "\x89" => [76, "\x912"], "\x8a" => [104, "\x912"], "\x8b" => [16, "\x912"], "\x8c" => [94, "\x91a"], "\x8d" => [76, "\x91a"], "\x8e" => [104, "\x91a"], "\x8f" => [16, "\x91a"], "\x90" => [94, "\x91c"], "\x91" => [76, "\x91c"], "\x92" => [104, "\x91c"], "\x93" => [16, "\x91c"], "\x94" => [94, "\x91e"], "\x95" => [76, "\x91e"], "\x96" => [104, "\x91e"], "\x97" => [16, "\x91e"], "\x98" => [94, "\x91i"], "\x99" => [76, "\x91i"], "\x9a" => [104, "\x91i"], "\x9b" => [16, "\x91i"], "\x9c" => [94, "\x91o"], "\x9d" => [76, "\x91o"], "\x9e" => [104, "\x91o"], "\x9f" => [16, "\x91o"], "\xa0" => [94, "\x91s"], "\xa1" => [76, "\x91s"], "\xa2" => [104, "\x91s"], "\xa3" => [16, "\x91s"], "\xa4" => [94, "\x91t"], "\xa5" => [76, "\x91t"], "\xa6" => [104, "\x91t"], "\xa7" => [16, "\x91t"], "\xa8" => [77, "\x91 "], "\xa9" => [18, "\x91 "], "\xaa" => [77, "\x91%"], "\xab" => [18, "\x91%"], "\xac" => [77, "\x91-"], "\xad" => [18, "\x91-"], "\xae" => [77, "\x91."], "\xaf" => [18, "\x91."], "\xb0" => [77, "\x91/"], "\xb1" => [18, "\x91/"], "\xb2" => [77, "\x913"], "\xb3" => [18, "\x913"], "\xb4" => [77, "\x914"], "\xb5" => [18, "\x914"], "\xb6" => [77, "\x915"], "\xb7" => [18, "\x915"], "\xb8" => [77, "\x916"], "\xb9" => [18, "\x916"], "\xba" => [77, "\x917"], "\xbb" => [18, "\x917"], "\xbc" => [77, "\x918"], "\xbd" => [18, "\x918"], "\xbe" => [77, "\x919"], "\xbf" => [18, "\x919"], "\xc0" => [77, "\x91="], "\xc1" => [18, "\x91="], "\xc2" => [77, "\x91A"], "\xc3" => [18, "\x91A"], "\xc4" => [77, "\x91_"], "\xc5" => [18, "\x91_"], "\xc6" => [77, "\x91b"], "\xc7" => [18, "\x91b"], "\xc8" => [77, "\x91d"], "\xc9" => [18, "\x91d"], "\xca" => [77, "\x91f"], "\xcb" => [18, "\x91f"], "\xcc" => [77, "\x91g"], "\xcd" => [18, "\x91g"], "\xce" => [77, "\x91h"], "\xcf" => [18, "\x91h"], "\xd0" => [77, "\x91l"], "\xd1" => [18, "\x91l"], "\xd2" => [77, "\x91m"], "\xd3" => [18, "\x91m"], "\xd4" => [77, "\x91n"], "\xd5" => [18, "\x91n"], "\xd6" => [77, "\x91p"], "\xd7" => [18, "\x91p"], "\xd8" => [77, "\x91r"], "\xd9" => [18, "\x91r"], "\xda" => [77, "\x91u"], "\xdb" => [18, "\x91u"], "\xdc" => [0, "\x91:"], "\xdd" => [0, "\x91B"], "\xde" => [0, "\x91C"], "\xdf" => [0, "\x91D"], "\xe0" => [0, "\x91E"], "\xe1" => [0, "\x91F"], "\xe2" => [0, "\x91G"], "\xe3" => [0, "\x91H"], "\xe4" => [0, "\x91I"], "\xe5" => [0, "\x91J"], "\xe6" => [0, "\x91K"], "\xe7" => [0, "\x91L"], "\xe8" => [0, "\x91M"], "\xe9" => [0, "\x91N"], "\xea" => [0, "\x91O"], "\xeb" => [0, "\x91P"], "\xec" => [0, "\x91Q"], "\xed" => [0, "\x91R"], "\xee" => [0, "\x91S"], "\xef" => [0, "\x91T"], "\xf0" => [0, "\x91U"], "\xf1" => [0, "\x91V"], "\xf2" => [0, "\x91W"], "\xf3" => [0, "\x91Y"], "\xf4" => [0, "\x91j"], "\xf5" => [0, "\x91k"], "\xf6" => [0, "\x91q"], "\xf7" => [0, "\x91v"], "\xf8" => [0, "\x91w"], "\xf9" => [0, "\x91x"], "\xfa" => [0, "\x91y"], "\xfb" => [0, "\x91z"], "\xfc" => [82, "\x91"], "\xfd" => [87, "\x91"], "\xfe" => [130, "\x91"], "\xff" => [9, "\x91"]], ["\x00" => [77, "\x900"], "\x01" => [18, "\x900"], "\x02" => [77, "\x901"], "\x03" => [18, "\x901"], "\x04" => [77, "\x902"], "\x05" => [18, "\x902"], "\x06" => [77, "\x90a"], "\x07" => [18, "\x90a"], "\x08" => [77, "\x90c"], "\t" => [18, "\x90c"], "\n" => [77, "\x90e"], "\v" => [18, "\x90e"], "\f" => [77, "\x90i"], "\r" => [18, "\x90i"], "\x0e" => [77, "\x90o"], "\x0f" => [18, "\x90o"], "\x10" => [77, "\x90s"], "\x11" => [18, "\x90s"], "\x12" => [77, "\x90t"], "\x13" => [18, "\x90t"], "\x14" => [0, "\x90 "], "\x15" => [0, "\x90%"], "\x16" => [0, "\x90-"], "\x17" => [0, "\x90."], "\x18" => [0, "\x90/"], "\x19" => [0, "\x903"], "\x1a" => [0, "\x904"], "\x1b" => [0, "\x905"], "\x1c" => [0, "\x906"], "\x1d" => [0, "\x907"], "\x1e" => [0, "\x908"], "\x1f" => [0, "\x909"], " " => [0, "\x90="], "!" => [0, "\x90A"], "\"" => [0, "\x90_"], "#" => [0, "\x90b"], "\$" => [0, "\x90d"], "%" => [0, "\x90f"], "&" => [0, "\x90g"], "'" => [0, "\x90h"], "(" => [0, "\x90l"], ")" => [0, "\x90m"], "*" => [0, "\x90n"], "+" => [0, "\x90p"], "," => [0, "\x90r"], "-" => [0, "\x90u"], "." => [100, "\x90"], "/" => [110, "\x90"], [111, "\x90"], [115, "\x90"], [116, "\x90"], [118, "\x90"], [119, "\x90"], [122, "\x90"], [123, "\x90"], [125, "\x90"], [126, "\x90"], [129, "\x90"], ":" => [143, "\x90"], ";" => [148, "\x90"], "<" => [151, "\x90"], "=" => [153, "\x90"], ">" => [83, "\x90"], "?" => [10, "\x90"], "@" => [77, "\x910"], "A" => [18, "\x910"], "B" => [77, "\x911"], "C" => [18, "\x911"], "D" => [77, "\x912"], "E" => [18, "\x912"], "F" => [77, "\x91a"], "G" => [18, "\x91a"], "H" => [77, "\x91c"], "I" => [18, "\x91c"], "J" => [77, "\x91e"], "K" => [18, "\x91e"], "L" => [77, "\x91i"], "M" => [18, "\x91i"], "N" => [77, "\x91o"], "O" => [18, "\x91o"], "P" => [77, "\x91s"], "Q" => [18, "\x91s"], "R" => [77, "\x91t"], "S" => [18, "\x91t"], "T" => [0, "\x91 "], "U" => [0, "\x91%"], "V" => [0, "\x91-"], "W" => [0, "\x91."], "X" => [0, "\x91/"], "Y" => [0, "\x913"], "Z" => [0, "\x914"], "[" => [0, "\x915"], "\\" => [0, "\x916"], "]" => [0, "\x917"], "^" => [0, "\x918"], "_" => [0, "\x919"], "`" => [0, "\x91="], "a" => [0, "\x91A"], "b" => [0, "\x91_"], "c" => [0, "\x91b"], "d" => [0, "\x91d"], "e" => [0, "\x91f"], "f" => [0, "\x91g"], "g" => [0, "\x91h"], "h" => [0, "\x91l"], "i" => [0, "\x91m"], "j" => [0, "\x91n"], "k" => [0, "\x91p"], "l" => [0, "\x91r"], "m" => [0, "\x91u"], "n" => [100, "\x91"], "o" => [110, "\x91"], "p" => [111, "\x91"], "q" => [115, "\x91"], "r" => [116, "\x91"], "s" => [118, "\x91"], "t" => [119, "\x91"], "u" => [122, "\x91"], "v" => [123, "\x91"], "w" => [125, "\x91"], "x" => [126, "\x91"], "y" => [129, "\x91"], "z" => [143, "\x91"], "{" => [148, "\x91"], "|" => [151, "\x91"], "}" => [153, "\x91"], "~" => [83, "\x91"], "" => [10, "\x91"], "\x80" => [77, "\x940"], "\x81" => [18, "\x940"], "\x82" => [77, "\x941"], "\x83" => [18, "\x941"], "\x84" => [77, "\x942"], "\x85" => [18, "\x942"], "\x86" => [77, "\x94a"], "\x87" => [18, "\x94a"], "\x88" => [77, "\x94c"], "\x89" => [18, "\x94c"], "\x8a" => [77, "\x94e"], "\x8b" => [18, "\x94e"], "\x8c" => [77, "\x94i"], "\x8d" => [18, "\x94i"], "\x8e" => [77, "\x94o"], "\x8f" => [18, "\x94o"], "\x90" => [77, "\x94s"], "\x91" => [18, "\x94s"], "\x92" => [77, "\x94t"], "\x93" => [18, "\x94t"], "\x94" => [0, "\x94 "], "\x95" => [0, "\x94%"], "\x96" => [0, "\x94-"], "\x97" => [0, "\x94."], "\x98" => [0, "\x94/"], "\x99" => [0, "\x943"], "\x9a" => [0, "\x944"], "\x9b" => [0, "\x945"], "\x9c" => [0, "\x946"], "\x9d" => [0, "\x947"], "\x9e" => [0, "\x948"], "\x9f" => [0, "\x949"], "\xa0" => [0, "\x94="], "\xa1" => [0, "\x94A"], "\xa2" => [0, "\x94_"], "\xa3" => [0, "\x94b"], "\xa4" => [0, "\x94d"], "\xa5" => [0, "\x94f"], "\xa6" => [0, "\x94g"], "\xa7" => [0, "\x94h"], "\xa8" => [0, "\x94l"], "\xa9" => [0, "\x94m"], "\xaa" => [0, "\x94n"], "\xab" => [0, "\x94p"], "\xac" => [0, "\x94r"], "\xad" => [0, "\x94u"], "\xae" => [100, "\x94"], "\xaf" => [110, "\x94"], "\xb0" => [111, "\x94"], "\xb1" => [115, "\x94"], "\xb2" => [116, "\x94"], "\xb3" => [118, "\x94"], "\xb4" => [119, "\x94"], "\xb5" => [122, "\x94"], "\xb6" => [123, "\x94"], "\xb7" => [125, "\x94"], "\xb8" => [126, "\x94"], "\xb9" => [129, "\x94"], "\xba" => [143, "\x94"], "\xbb" => [148, "\x94"], "\xbc" => [151, "\x94"], "\xbd" => [153, "\x94"], "\xbe" => [83, "\x94"], "\xbf" => [10, "\x94"], "\xc0" => [77, "\x9f0"], "\xc1" => [18, "\x9f0"], "\xc2" => [77, "\x9f1"], "\xc3" => [18, "\x9f1"], "\xc4" => [77, "\x9f2"], "\xc5" => [18, "\x9f2"], "\xc6" => [77, "\x9fa"], "\xc7" => [18, "\x9fa"], "\xc8" => [77, "\x9fc"], "\xc9" => [18, "\x9fc"], "\xca" => [77, "\x9fe"], "\xcb" => [18, "\x9fe"], "\xcc" => [77, "\x9fi"], "\xcd" => [18, "\x9fi"], "\xce" => [77, "\x9fo"], "\xcf" => [18, "\x9fo"], "\xd0" => [77, "\x9fs"], "\xd1" => [18, "\x9fs"], "\xd2" => [77, "\x9ft"], "\xd3" => [18, "\x9ft"], "\xd4" => [0, "\x9f "], "\xd5" => [0, "\x9f%"], "\xd6" => [0, "\x9f-"], "\xd7" => [0, "\x9f."], "\xd8" => [0, "\x9f/"], "\xd9" => [0, "\x9f3"], "\xda" => [0, "\x9f4"], "\xdb" => [0, "\x9f5"], "\xdc" => [0, "\x9f6"], "\xdd" => [0, "\x9f7"], "\xde" => [0, "\x9f8"], "\xdf" => [0, "\x9f9"], "\xe0" => [0, "\x9f="], "\xe1" => [0, "\x9fA"], "\xe2" => [0, "\x9f_"], "\xe3" => [0, "\x9fb"], "\xe4" => [0, "\x9fd"], "\xe5" => [0, "\x9ff"], "\xe6" => [0, "\x9fg"], "\xe7" => [0, "\x9fh"], "\xe8" => [0, "\x9fl"], "\xe9" => [0, "\x9fm"], "\xea" => [0, "\x9fn"], "\xeb" => [0, "\x9fp"], "\xec" => [0, "\x9fr"], "\xed" => [0, "\x9fu"], "\xee" => [100, "\x9f"], "\xef" => [110, "\x9f"], "\xf0" => [111, "\x9f"], "\xf1" => [115, "\x9f"], "\xf2" => [116, "\x9f"], "\xf3" => [118, "\x9f"], "\xf4" => [119, "\x9f"], "\xf5" => [122, "\x9f"], "\xf6" => [123, "\x9f"], "\xf7" => [125, "\x9f"], "\xf8" => [126, "\x9f"], "\xf9" => [129, "\x9f"], "\xfa" => [143, "\x9f"], "\xfb" => [148, "\x9f"], "\xfc" => [151, "\x9f"], "\xfd" => [153, "\x9f"], "\xfe" => [83, "\x9f"], "\xff" => [10, "\x9f"]], ["\x00" => [94, "\x930"], "\x01" => [76, "\x930"], "\x02" => [104, "\x930"], "\x03" => [16, "\x930"], "\x04" => [94, "\x931"], "\x05" => [76, "\x931"], "\x06" => [104, "\x931"], "\x07" => [16, "\x931"], "\x08" => [94, "\x932"], "\t" => [76, "\x932"], "\n" => [104, "\x932"], "\v" => [16, "\x932"], "\f" => [94, "\x93a"], "\r" => [76, "\x93a"], "\x0e" => [104, "\x93a"], "\x0f" => [16, "\x93a"], "\x10" => [94, "\x93c"], "\x11" => [76, "\x93c"], "\x12" => [104, "\x93c"], "\x13" => [16, "\x93c"], "\x14" => [94, "\x93e"], "\x15" => [76, "\x93e"], "\x16" => [104, "\x93e"], "\x17" => [16, "\x93e"], "\x18" => [94, "\x93i"], "\x19" => [76, "\x93i"], "\x1a" => [104, "\x93i"], "\x1b" => [16, "\x93i"], "\x1c" => [94, "\x93o"], "\x1d" => [76, "\x93o"], "\x1e" => [104, "\x93o"], "\x1f" => [16, "\x93o"], " " => [94, "\x93s"], "!" => [76, "\x93s"], "\"" => [104, "\x93s"], "#" => [16, "\x93s"], "\$" => [94, "\x93t"], "%" => [76, "\x93t"], "&" => [104, "\x93t"], "'" => [16, "\x93t"], "(" => [77, "\x93 "], ")" => [18, "\x93 "], "*" => [77, "\x93%"], "+" => [18, "\x93%"], "," => [77, "\x93-"], "-" => [18, "\x93-"], "." => [77, "\x93."], "/" => [18, "\x93."], [77, "\x93/"], [18, "\x93/"], [77, "\x933"], [18, "\x933"], [77, "\x934"], [18, "\x934"], [77, "\x935"], [18, "\x935"], [77, "\x936"], [18, "\x936"], ":" => [77, "\x937"], ";" => [18, "\x937"], "<" => [77, "\x938"], "=" => [18, "\x938"], ">" => [77, "\x939"], "?" => [18, "\x939"], "@" => [77, "\x93="], "A" => [18, "\x93="], "B" => [77, "\x93A"], "C" => [18, "\x93A"], "D" => [77, "\x93_"], "E" => [18, "\x93_"], "F" => [77, "\x93b"], "G" => [18, "\x93b"], "H" => [77, "\x93d"], "I" => [18, "\x93d"], "J" => [77, "\x93f"], "K" => [18, "\x93f"], "L" => [77, "\x93g"], "M" => [18, "\x93g"], "N" => [77, "\x93h"], "O" => [18, "\x93h"], "P" => [77, "\x93l"], "Q" => [18, "\x93l"], "R" => [77, "\x93m"], "S" => [18, "\x93m"], "T" => [77, "\x93n"], "U" => [18, "\x93n"], "V" => [77, "\x93p"], "W" => [18, "\x93p"], "X" => [77, "\x93r"], "Y" => [18, "\x93r"], "Z" => [77, "\x93u"], "[" => [18, "\x93u"], "\\" => [0, "\x93:"], "]" => [0, "\x93B"], "^" => [0, "\x93C"], "_" => [0, "\x93D"], "`" => [0, "\x93E"], "a" => [0, "\x93F"], "b" => [0, "\x93G"], "c" => [0, "\x93H"], "d" => [0, "\x93I"], "e" => [0, "\x93J"], "f" => [0, "\x93K"], "g" => [0, "\x93L"], "h" => [0, "\x93M"], "i" => [0, "\x93N"], "j" => [0, "\x93O"], "k" => [0, "\x93P"], "l" => [0, "\x93Q"], "m" => [0, "\x93R"], "n" => [0, "\x93S"], "o" => [0, "\x93T"], "p" => [0, "\x93U"], "q" => [0, "\x93V"], "r" => [0, "\x93W"], "s" => [0, "\x93Y"], "t" => [0, "\x93j"], "u" => [0, "\x93k"], "v" => [0, "\x93q"], "w" => [0, "\x93v"], "x" => [0, "\x93w"], "y" => [0, "\x93x"], "z" => [0, "\x93y"], "{" => [0, "\x93z"], "|" => [82, "\x93"], "}" => [87, "\x93"], "~" => [130, "\x93"], "" => [9, "\x93"], "\x80" => [94, "\x950"], "\x81" => [76, "\x950"], "\x82" => [104, "\x950"], "\x83" => [16, "\x950"], "\x84" => [94, "\x951"], "\x85" => [76, "\x951"], "\x86" => [104, "\x951"], "\x87" => [16, "\x951"], "\x88" => [94, "\x952"], "\x89" => [76, "\x952"], "\x8a" => [104, "\x952"], "\x8b" => [16, "\x952"], "\x8c" => [94, "\x95a"], "\x8d" => [76, "\x95a"], "\x8e" => [104, "\x95a"], "\x8f" => [16, "\x95a"], "\x90" => [94, "\x95c"], "\x91" => [76, "\x95c"], "\x92" => [104, "\x95c"], "\x93" => [16, "\x95c"], "\x94" => [94, "\x95e"], "\x95" => [76, "\x95e"], "\x96" => [104, "\x95e"], "\x97" => [16, "\x95e"], "\x98" => [94, "\x95i"], "\x99" => [76, "\x95i"], "\x9a" => [104, "\x95i"], "\x9b" => [16, "\x95i"], "\x9c" => [94, "\x95o"], "\x9d" => [76, "\x95o"], "\x9e" => [104, "\x95o"], "\x9f" => [16, "\x95o"], "\xa0" => [94, "\x95s"], "\xa1" => [76, "\x95s"], "\xa2" => [104, "\x95s"], "\xa3" => [16, "\x95s"], "\xa4" => [94, "\x95t"], "\xa5" => [76, "\x95t"], "\xa6" => [104, "\x95t"], "\xa7" => [16, "\x95t"], "\xa8" => [77, "\x95 "], "\xa9" => [18, "\x95 "], "\xaa" => [77, "\x95%"], "\xab" => [18, "\x95%"], "\xac" => [77, "\x95-"], "\xad" => [18, "\x95-"], "\xae" => [77, "\x95."], "\xaf" => [18, "\x95."], "\xb0" => [77, "\x95/"], "\xb1" => [18, "\x95/"], "\xb2" => [77, "\x953"], "\xb3" => [18, "\x953"], "\xb4" => [77, "\x954"], "\xb5" => [18, "\x954"], "\xb6" => [77, "\x955"], "\xb7" => [18, "\x955"], "\xb8" => [77, "\x956"], "\xb9" => [18, "\x956"], "\xba" => [77, "\x957"], "\xbb" => [18, "\x957"], "\xbc" => [77, "\x958"], "\xbd" => [18, "\x958"], "\xbe" => [77, "\x959"], "\xbf" => [18, "\x959"], "\xc0" => [77, "\x95="], "\xc1" => [18, "\x95="], "\xc2" => [77, "\x95A"], "\xc3" => [18, "\x95A"], "\xc4" => [77, "\x95_"], "\xc5" => [18, "\x95_"], "\xc6" => [77, "\x95b"], "\xc7" => [18, "\x95b"], "\xc8" => [77, "\x95d"], "\xc9" => [18, "\x95d"], "\xca" => [77, "\x95f"], "\xcb" => [18, "\x95f"], "\xcc" => [77, "\x95g"], "\xcd" => [18, "\x95g"], "\xce" => [77, "\x95h"], "\xcf" => [18, "\x95h"], "\xd0" => [77, "\x95l"], "\xd1" => [18, "\x95l"], "\xd2" => [77, "\x95m"], "\xd3" => [18, "\x95m"], "\xd4" => [77, "\x95n"], "\xd5" => [18, "\x95n"], "\xd6" => [77, "\x95p"], "\xd7" => [18, "\x95p"], "\xd8" => [77, "\x95r"], "\xd9" => [18, "\x95r"], "\xda" => [77, "\x95u"], "\xdb" => [18, "\x95u"], "\xdc" => [0, "\x95:"], "\xdd" => [0, "\x95B"], "\xde" => [0, "\x95C"], "\xdf" => [0, "\x95D"], "\xe0" => [0, "\x95E"], "\xe1" => [0, "\x95F"], "\xe2" => [0, "\x95G"], "\xe3" => [0, "\x95H"], "\xe4" => [0, "\x95I"], "\xe5" => [0, "\x95J"], "\xe6" => [0, "\x95K"], "\xe7" => [0, "\x95L"], "\xe8" => [0, "\x95M"], "\xe9" => [0, "\x95N"], "\xea" => [0, "\x95O"], "\xeb" => [0, "\x95P"], "\xec" => [0, "\x95Q"], "\xed" => [0, "\x95R"], "\xee" => [0, "\x95S"], "\xef" => [0, "\x95T"], "\xf0" => [0, "\x95U"], "\xf1" => [0, "\x95V"], "\xf2" => [0, "\x95W"], "\xf3" => [0, "\x95Y"], "\xf4" => [0, "\x95j"], "\xf5" => [0, "\x95k"], "\xf6" => [0, "\x95q"], "\xf7" => [0, "\x95v"], "\xf8" => [0, "\x95w"], "\xf9" => [0, "\x95x"], "\xfa" => [0, "\x95y"], "\xfb" => [0, "\x95z"], "\xfc" => [82, "\x95"], "\xfd" => [87, "\x95"], "\xfe" => [130, "\x95"], "\xff" => [9, "\x95"]], ["\x00" => [77, "\x930"], "\x01" => [18, "\x930"], "\x02" => [77, "\x931"], "\x03" => [18, "\x931"], "\x04" => [77, "\x932"], "\x05" => [18, "\x932"], "\x06" => [77, "\x93a"], "\x07" => [18, "\x93a"], "\x08" => [77, "\x93c"], "\t" => [18, "\x93c"], "\n" => [77, "\x93e"], "\v" => [18, "\x93e"], "\f" => [77, "\x93i"], "\r" => [18, "\x93i"], "\x0e" => [77, "\x93o"], "\x0f" => [18, "\x93o"], "\x10" => [77, "\x93s"], "\x11" => [18, "\x93s"], "\x12" => [77, "\x93t"], "\x13" => [18, "\x93t"], "\x14" => [0, "\x93 "], "\x15" => [0, "\x93%"], "\x16" => [0, "\x93-"], "\x17" => [0, "\x93."], "\x18" => [0, "\x93/"], "\x19" => [0, "\x933"], "\x1a" => [0, "\x934"], "\x1b" => [0, "\x935"], "\x1c" => [0, "\x936"], "\x1d" => [0, "\x937"], "\x1e" => [0, "\x938"], "\x1f" => [0, "\x939"], " " => [0, "\x93="], "!" => [0, "\x93A"], "\"" => [0, "\x93_"], "#" => [0, "\x93b"], "\$" => [0, "\x93d"], "%" => [0, "\x93f"], "&" => [0, "\x93g"], "'" => [0, "\x93h"], "(" => [0, "\x93l"], ")" => [0, "\x93m"], "*" => [0, "\x93n"], "+" => [0, "\x93p"], "," => [0, "\x93r"], "-" => [0, "\x93u"], "." => [100, "\x93"], "/" => [110, "\x93"], [111, "\x93"], [115, "\x93"], [116, "\x93"], [118, "\x93"], [119, "\x93"], [122, "\x93"], [123, "\x93"], [125, "\x93"], [126, "\x93"], [129, "\x93"], ":" => [143, "\x93"], ";" => [148, "\x93"], "<" => [151, "\x93"], "=" => [153, "\x93"], ">" => [83, "\x93"], "?" => [10, "\x93"], "@" => [77, "\x950"], "A" => [18, "\x950"], "B" => [77, "\x951"], "C" => [18, "\x951"], "D" => [77, "\x952"], "E" => [18, "\x952"], "F" => [77, "\x95a"], "G" => [18, "\x95a"], "H" => [77, "\x95c"], "I" => [18, "\x95c"], "J" => [77, "\x95e"], "K" => [18, "\x95e"], "L" => [77, "\x95i"], "M" => [18, "\x95i"], "N" => [77, "\x95o"], "O" => [18, "\x95o"], "P" => [77, "\x95s"], "Q" => [18, "\x95s"], "R" => [77, "\x95t"], "S" => [18, "\x95t"], "T" => [0, "\x95 "], "U" => [0, "\x95%"], "V" => [0, "\x95-"], "W" => [0, "\x95."], "X" => [0, "\x95/"], "Y" => [0, "\x953"], "Z" => [0, "\x954"], "[" => [0, "\x955"], "\\" => [0, "\x956"], "]" => [0, "\x957"], "^" => [0, "\x958"], "_" => [0, "\x959"], "`" => [0, "\x95="], "a" => [0, "\x95A"], "b" => [0, "\x95_"], "c" => [0, "\x95b"], "d" => [0, "\x95d"], "e" => [0, "\x95f"], "f" => [0, "\x95g"], "g" => [0, "\x95h"], "h" => [0, "\x95l"], "i" => [0, "\x95m"], "j" => [0, "\x95n"], "k" => [0, "\x95p"], "l" => [0, "\x95r"], "m" => [0, "\x95u"], "n" => [100, "\x95"], "o" => [110, "\x95"], "p" => [111, "\x95"], "q" => [115, "\x95"], "r" => [116, "\x95"], "s" => [118, "\x95"], "t" => [119, "\x95"], "u" => [122, "\x95"], "v" => [123, "\x95"], "w" => [125, "\x95"], "x" => [126, "\x95"], "y" => [129, "\x95"], "z" => [143, "\x95"], "{" => [148, "\x95"], "|" => [151, "\x95"], "}" => [153, "\x95"], "~" => [83, "\x95"], "" => [10, "\x95"], "\x80" => [77, "\x960"], "\x81" => [18, "\x960"], "\x82" => [77, "\x961"], "\x83" => [18, "\x961"], "\x84" => [77, "\x962"], "\x85" => [18, "\x962"], "\x86" => [77, "\x96a"], "\x87" => [18, "\x96a"], "\x88" => [77, "\x96c"], "\x89" => [18, "\x96c"], "\x8a" => [77, "\x96e"], "\x8b" => [18, "\x96e"], "\x8c" => [77, "\x96i"], "\x8d" => [18, "\x96i"], "\x8e" => [77, "\x96o"], "\x8f" => [18, "\x96o"], "\x90" => [77, "\x96s"], "\x91" => [18, "\x96s"], "\x92" => [77, "\x96t"], "\x93" => [18, "\x96t"], "\x94" => [0, "\x96 "], "\x95" => [0, "\x96%"], "\x96" => [0, "\x96-"], "\x97" => [0, "\x96."], "\x98" => [0, "\x96/"], "\x99" => [0, "\x963"], "\x9a" => [0, "\x964"], "\x9b" => [0, "\x965"], "\x9c" => [0, "\x966"], "\x9d" => [0, "\x967"], "\x9e" => [0, "\x968"], "\x9f" => [0, "\x969"], "\xa0" => [0, "\x96="], "\xa1" => [0, "\x96A"], "\xa2" => [0, "\x96_"], "\xa3" => [0, "\x96b"], "\xa4" => [0, "\x96d"], "\xa5" => [0, "\x96f"], "\xa6" => [0, "\x96g"], "\xa7" => [0, "\x96h"], "\xa8" => [0, "\x96l"], "\xa9" => [0, "\x96m"], "\xaa" => [0, "\x96n"], "\xab" => [0, "\x96p"], "\xac" => [0, "\x96r"], "\xad" => [0, "\x96u"], "\xae" => [100, "\x96"], "\xaf" => [110, "\x96"], "\xb0" => [111, "\x96"], "\xb1" => [115, "\x96"], "\xb2" => [116, "\x96"], "\xb3" => [118, "\x96"], "\xb4" => [119, "\x96"], "\xb5" => [122, "\x96"], "\xb6" => [123, "\x96"], "\xb7" => [125, "\x96"], "\xb8" => [126, "\x96"], "\xb9" => [129, "\x96"], "\xba" => [143, "\x96"], "\xbb" => [148, "\x96"], "\xbc" => [151, "\x96"], "\xbd" => [153, "\x96"], "\xbe" => [83, "\x96"], "\xbf" => [10, "\x96"], "\xc0" => [77, "\x970"], "\xc1" => [18, "\x970"], "\xc2" => [77, "\x971"], "\xc3" => [18, "\x971"], "\xc4" => [77, "\x972"], "\xc5" => [18, "\x972"], "\xc6" => [77, "\x97a"], "\xc7" => [18, "\x97a"], "\xc8" => [77, "\x97c"], "\xc9" => [18, "\x97c"], "\xca" => [77, "\x97e"], "\xcb" => [18, "\x97e"], "\xcc" => [77, "\x97i"], "\xcd" => [18, "\x97i"], "\xce" => [77, "\x97o"], "\xcf" => [18, "\x97o"], "\xd0" => [77, "\x97s"], "\xd1" => [18, "\x97s"], "\xd2" => [77, "\x97t"], "\xd3" => [18, "\x97t"], "\xd4" => [0, "\x97 "], "\xd5" => [0, "\x97%"], "\xd6" => [0, "\x97-"], "\xd7" => [0, "\x97."], "\xd8" => [0, "\x97/"], "\xd9" => [0, "\x973"], "\xda" => [0, "\x974"], "\xdb" => [0, "\x975"], "\xdc" => [0, "\x976"], "\xdd" => [0, "\x977"], "\xde" => [0, "\x978"], "\xdf" => [0, "\x979"], "\xe0" => [0, "\x97="], "\xe1" => [0, "\x97A"], "\xe2" => [0, "\x97_"], "\xe3" => [0, "\x97b"], "\xe4" => [0, "\x97d"], "\xe5" => [0, "\x97f"], "\xe6" => [0, "\x97g"], "\xe7" => [0, "\x97h"], "\xe8" => [0, "\x97l"], "\xe9" => [0, "\x97m"], "\xea" => [0, "\x97n"], "\xeb" => [0, "\x97p"], "\xec" => [0, "\x97r"], "\xed" => [0, "\x97u"], "\xee" => [100, "\x97"], "\xef" => [110, "\x97"], "\xf0" => [111, "\x97"], "\xf1" => [115, "\x97"], "\xf2" => [116, "\x97"], "\xf3" => [118, "\x97"], "\xf4" => [119, "\x97"], "\xf5" => [122, "\x97"], "\xf6" => [123, "\x97"], "\xf7" => [125, "\x97"], "\xf8" => [126, "\x97"], "\xf9" => [129, "\x97"], "\xfa" => [143, "\x97"], "\xfb" => [148, "\x97"], "\xfc" => [151, "\x97"], "\xfd" => [153, "\x97"], "\xfe" => [83, "\x97"], "\xff" => [10, "\x97"]], ["\x00" => [0, "\x930"], "\x01" => [0, "\x931"], "\x02" => [0, "\x932"], "\x03" => [0, "\x93a"], "\x04" => [0, "\x93c"], "\x05" => [0, "\x93e"], "\x06" => [0, "\x93i"], "\x07" => [0, "\x93o"], "\x08" => [0, "\x93s"], "\t" => [0, "\x93t"], "\n" => [73, "\x93"], "\v" => [88, "\x93"], "\f" => [89, "\x93"], "\r" => [96, "\x93"], "\x0e" => [97, "\x93"], "\x0f" => [99, "\x93"], "\x10" => [106, "\x93"], "\x11" => [136, "\x93"], "\x12" => [139, "\x93"], "\x13" => [141, "\x93"], "\x14" => [145, "\x93"], "\x15" => [147, "\x93"], "\x16" => [149, "\x93"], "\x17" => [101, "\x93"], "\x18" => [112, "\x93"], "\x19" => [117, "\x93"], "\x1a" => [120, "\x93"], "\x1b" => [124, "\x93"], "\x1c" => [127, "\x93"], "\x1d" => [144, "\x93"], "\x1e" => [152, "\x93"], "\x1f" => [11, "\x93"], " " => [0, "\x950"], "!" => [0, "\x951"], "\"" => [0, "\x952"], "#" => [0, "\x95a"], "\$" => [0, "\x95c"], "%" => [0, "\x95e"], "&" => [0, "\x95i"], "'" => [0, "\x95o"], "(" => [0, "\x95s"], ")" => [0, "\x95t"], "*" => [73, "\x95"], "+" => [88, "\x95"], "," => [89, "\x95"], "-" => [96, "\x95"], "." => [97, "\x95"], "/" => [99, "\x95"], [106, "\x95"], [136, "\x95"], [139, "\x95"], [141, "\x95"], [145, "\x95"], [147, "\x95"], [149, "\x95"], [101, "\x95"], [112, "\x95"], [117, "\x95"], ":" => [120, "\x95"], ";" => [124, "\x95"], "<" => [127, "\x95"], "=" => [144, "\x95"], ">" => [152, "\x95"], "?" => [11, "\x95"], "@" => [0, "\x960"], "A" => [0, "\x961"], "B" => [0, "\x962"], "C" => [0, "\x96a"], "D" => [0, "\x96c"], "E" => [0, "\x96e"], "F" => [0, "\x96i"], "G" => [0, "\x96o"], "H" => [0, "\x96s"], "I" => [0, "\x96t"], "J" => [73, "\x96"], "K" => [88, "\x96"], "L" => [89, "\x96"], "M" => [96, "\x96"], "N" => [97, "\x96"], "O" => [99, "\x96"], "P" => [106, "\x96"], "Q" => [136, "\x96"], "R" => [139, "\x96"], "S" => [141, "\x96"], "T" => [145, "\x96"], "U" => [147, "\x96"], "V" => [149, "\x96"], "W" => [101, "\x96"], "X" => [112, "\x96"], "Y" => [117, "\x96"], "Z" => [120, "\x96"], "[" => [124, "\x96"], "\\" => [127, "\x96"], "]" => [144, "\x96"], "^" => [152, "\x96"], "_" => [11, "\x96"], "`" => [0, "\x970"], "a" => [0, "\x971"], "b" => [0, "\x972"], "c" => [0, "\x97a"], "d" => [0, "\x97c"], "e" => [0, "\x97e"], "f" => [0, "\x97i"], "g" => [0, "\x97o"], "h" => [0, "\x97s"], "i" => [0, "\x97t"], "j" => [73, "\x97"], "k" => [88, "\x97"], "l" => [89, "\x97"], "m" => [96, "\x97"], "n" => [97, "\x97"], "o" => [99, "\x97"], "p" => [106, "\x97"], "q" => [136, "\x97"], "r" => [139, "\x97"], "s" => [141, "\x97"], "t" => [145, "\x97"], "u" => [147, "\x97"], "v" => [149, "\x97"], "w" => [101, "\x97"], "x" => [112, "\x97"], "y" => [117, "\x97"], "z" => [120, "\x97"], "{" => [124, "\x97"], "|" => [127, "\x97"], "}" => [144, "\x97"], "~" => [152, "\x97"], "" => [11, "\x97"], "\x80" => [0, "\x980"], "\x81" => [0, "\x981"], "\x82" => [0, "\x982"], "\x83" => [0, "\x98a"], "\x84" => [0, "\x98c"], "\x85" => [0, "\x98e"], "\x86" => [0, "\x98i"], "\x87" => [0, "\x98o"], "\x88" => [0, "\x98s"], "\x89" => [0, "\x98t"], "\x8a" => [73, "\x98"], "\x8b" => [88, "\x98"], "\x8c" => [89, "\x98"], "\x8d" => [96, "\x98"], "\x8e" => [97, "\x98"], "\x8f" => [99, "\x98"], "\x90" => [106, "\x98"], "\x91" => [136, "\x98"], "\x92" => [139, "\x98"], "\x93" => [141, "\x98"], "\x94" => [145, "\x98"], "\x95" => [147, "\x98"], "\x96" => [149, "\x98"], "\x97" => [101, "\x98"], "\x98" => [112, "\x98"], "\x99" => [117, "\x98"], "\x9a" => [120, "\x98"], "\x9b" => [124, "\x98"], "\x9c" => [127, "\x98"], "\x9d" => [144, "\x98"], "\x9e" => [152, "\x98"], "\x9f" => [11, "\x98"], "\xa0" => [0, "\x9b0"], "\xa1" => [0, "\x9b1"], "\xa2" => [0, "\x9b2"], "\xa3" => [0, "\x9ba"], "\xa4" => [0, "\x9bc"], "\xa5" => [0, "\x9be"], "\xa6" => [0, "\x9bi"], "\xa7" => [0, "\x9bo"], "\xa8" => [0, "\x9bs"], "\xa9" => [0, "\x9bt"], "\xaa" => [73, "\x9b"], "\xab" => [88, "\x9b"], "\xac" => [89, "\x9b"], "\xad" => [96, "\x9b"], "\xae" => [97, "\x9b"], "\xaf" => [99, "\x9b"], "\xb0" => [106, "\x9b"], "\xb1" => [136, "\x9b"], "\xb2" => [139, "\x9b"], "\xb3" => [141, "\x9b"], "\xb4" => [145, "\x9b"], "\xb5" => [147, "\x9b"], "\xb6" => [149, "\x9b"], "\xb7" => [101, "\x9b"], "\xb8" => [112, "\x9b"], "\xb9" => [117, "\x9b"], "\xba" => [120, "\x9b"], "\xbb" => [124, "\x9b"], "\xbc" => [127, "\x9b"], "\xbd" => [144, "\x9b"], "\xbe" => [152, "\x9b"], "\xbf" => [11, "\x9b"], "\xc0" => [0, "\x9d0"], "\xc1" => [0, "\x9d1"], "\xc2" => [0, "\x9d2"], "\xc3" => [0, "\x9da"], "\xc4" => [0, "\x9dc"], "\xc5" => [0, "\x9de"], "\xc6" => [0, "\x9di"], "\xc7" => [0, "\x9do"], "\xc8" => [0, "\x9ds"], "\xc9" => [0, "\x9dt"], "\xca" => [73, "\x9d"], "\xcb" => [88, "\x9d"], "\xcc" => [89, "\x9d"], "\xcd" => [96, "\x9d"], "\xce" => [97, "\x9d"], "\xcf" => [99, "\x9d"], "\xd0" => [106, "\x9d"], "\xd1" => [136, "\x9d"], "\xd2" => [139, "\x9d"], "\xd3" => [141, "\x9d"], "\xd4" => [145, "\x9d"], "\xd5" => [147, "\x9d"], "\xd6" => [149, "\x9d"], "\xd7" => [101, "\x9d"], "\xd8" => [112, "\x9d"], "\xd9" => [117, "\x9d"], "\xda" => [120, "\x9d"], "\xdb" => [124, "\x9d"], "\xdc" => [127, "\x9d"], "\xdd" => [144, "\x9d"], "\xde" => [152, "\x9d"], "\xdf" => [11, "\x9d"], "\xe0" => [0, "\x9e0"], "\xe1" => [0, "\x9e1"], "\xe2" => [0, "\x9e2"], "\xe3" => [0, "\x9ea"], "\xe4" => [0, "\x9ec"], "\xe5" => [0, "\x9ee"], "\xe6" => [0, "\x9ei"], "\xe7" => [0, "\x9eo"], "\xe8" => [0, "\x9es"], "\xe9" => [0, "\x9et"], "\xea" => [73, "\x9e"], "\xeb" => [88, "\x9e"], "\xec" => [89, "\x9e"], "\xed" => [96, "\x9e"], "\xee" => [97, "\x9e"], "\xef" => [99, "\x9e"], "\xf0" => [106, "\x9e"], "\xf1" => [136, "\x9e"], "\xf2" => [139, "\x9e"], "\xf3" => [141, "\x9e"], "\xf4" => [145, "\x9e"], "\xf5" => [147, "\x9e"], "\xf6" => [149, "\x9e"], "\xf7" => [101, "\x9e"], "\xf8" => [112, "\x9e"], "\xf9" => [117, "\x9e"], "\xfa" => [120, "\x9e"], "\xfb" => [124, "\x9e"], "\xfc" => [127, "\x9e"], "\xfd" => [144, "\x9e"], "\xfe" => [152, "\x9e"], "\xff" => [11, "\x9e"]], ["\x00" => [92, "\x93"], "\x01" => [95, "\x93"], "\x02" => [137, "\x93"], "\x03" => [142, "\x93"], "\x04" => [150, "\x93"], "\x05" => [74, "\x93"], "\x06" => [90, "\x93"], "\x07" => [98, "\x93"], "\x08" => [107, "\x93"], "\t" => [140, "\x93"], "\n" => [146, "\x93"], "\v" => [102, "\x93"], "\f" => [113, "\x93"], "\r" => [121, "\x93"], "\x0e" => [128, "\x93"], "\x0f" => [12, "\x93"], "\x10" => [92, "\x95"], "\x11" => [95, "\x95"], "\x12" => [137, "\x95"], "\x13" => [142, "\x95"], "\x14" => [150, "\x95"], "\x15" => [74, "\x95"], "\x16" => [90, "\x95"], "\x17" => [98, "\x95"], "\x18" => [107, "\x95"], "\x19" => [140, "\x95"], "\x1a" => [146, "\x95"], "\x1b" => [102, "\x95"], "\x1c" => [113, "\x95"], "\x1d" => [121, "\x95"], "\x1e" => [128, "\x95"], "\x1f" => [12, "\x95"], " " => [92, "\x96"], "!" => [95, "\x96"], "\"" => [137, "\x96"], "#" => [142, "\x96"], "\$" => [150, "\x96"], "%" => [74, "\x96"], "&" => [90, "\x96"], "'" => [98, "\x96"], "(" => [107, "\x96"], ")" => [140, "\x96"], "*" => [146, "\x96"], "+" => [102, "\x96"], "," => [113, "\x96"], "-" => [121, "\x96"], "." => [128, "\x96"], "/" => [12, "\x96"], [92, "\x97"], [95, "\x97"], [137, "\x97"], [142, "\x97"], [150, "\x97"], [74, "\x97"], [90, "\x97"], [98, "\x97"], [107, "\x97"], [140, "\x97"], ":" => [146, "\x97"], ";" => [102, "\x97"], "<" => [113, "\x97"], "=" => [121, "\x97"], ">" => [128, "\x97"], "?" => [12, "\x97"], "@" => [92, "\x98"], "A" => [95, "\x98"], "B" => [137, "\x98"], "C" => [142, "\x98"], "D" => [150, "\x98"], "E" => [74, "\x98"], "F" => [90, "\x98"], "G" => [98, "\x98"], "H" => [107, "\x98"], "I" => [140, "\x98"], "J" => [146, "\x98"], "K" => [102, "\x98"], "L" => [113, "\x98"], "M" => [121, "\x98"], "N" => [128, "\x98"], "O" => [12, "\x98"], "P" => [92, "\x9b"], "Q" => [95, "\x9b"], "R" => [137, "\x9b"], "S" => [142, "\x9b"], "T" => [150, "\x9b"], "U" => [74, "\x9b"], "V" => [90, "\x9b"], "W" => [98, "\x9b"], "X" => [107, "\x9b"], "Y" => [140, "\x9b"], "Z" => [146, "\x9b"], "[" => [102, "\x9b"], "\\" => [113, "\x9b"], "]" => [121, "\x9b"], "^" => [128, "\x9b"], "_" => [12, "\x9b"], "`" => [92, "\x9d"], "a" => [95, "\x9d"], "b" => [137, "\x9d"], "c" => [142, "\x9d"], "d" => [150, "\x9d"], "e" => [74, "\x9d"], "f" => [90, "\x9d"], "g" => [98, "\x9d"], "h" => [107, "\x9d"], "i" => [140, "\x9d"], "j" => [146, "\x9d"], "k" => [102, "\x9d"], "l" => [113, "\x9d"], "m" => [121, "\x9d"], "n" => [128, "\x9d"], "o" => [12, "\x9d"], "p" => [92, "\x9e"], "q" => [95, "\x9e"], "r" => [137, "\x9e"], "s" => [142, "\x9e"], "t" => [150, "\x9e"], "u" => [74, "\x9e"], "v" => [90, "\x9e"], "w" => [98, "\x9e"], "x" => [107, "\x9e"], "y" => [140, "\x9e"], "z" => [146, "\x9e"], "{" => [102, "\x9e"], "|" => [113, "\x9e"], "}" => [121, "\x9e"], "~" => [128, "\x9e"], "" => [12, "\x9e"], "\x80" => [92, "\xa5"], "\x81" => [95, "\xa5"], "\x82" => [137, "\xa5"], "\x83" => [142, "\xa5"], "\x84" => [150, "\xa5"], "\x85" => [74, "\xa5"], "\x86" => [90, "\xa5"], "\x87" => [98, "\xa5"], "\x88" => [107, "\xa5"], "\x89" => [140, "\xa5"], "\x8a" => [146, "\xa5"], "\x8b" => [102, "\xa5"], "\x8c" => [113, "\xa5"], "\x8d" => [121, "\xa5"], "\x8e" => [128, "\xa5"], "\x8f" => [12, "\xa5"], "\x90" => [92, "\xa6"], "\x91" => [95, "\xa6"], "\x92" => [137, "\xa6"], "\x93" => [142, "\xa6"], "\x94" => [150, "\xa6"], "\x95" => [74, "\xa6"], "\x96" => [90, "\xa6"], "\x97" => [98, "\xa6"], "\x98" => [107, "\xa6"], "\x99" => [140, "\xa6"], "\x9a" => [146, "\xa6"], "\x9b" => [102, "\xa6"], "\x9c" => [113, "\xa6"], "\x9d" => [121, "\xa6"], "\x9e" => [128, "\xa6"], "\x9f" => [12, "\xa6"], "\xa0" => [92, "\xa8"], "\xa1" => [95, "\xa8"], "\xa2" => [137, "\xa8"], "\xa3" => [142, "\xa8"], "\xa4" => [150, "\xa8"], "\xa5" => [74, "\xa8"], "\xa6" => [90, "\xa8"], "\xa7" => [98, "\xa8"], "\xa8" => [107, "\xa8"], "\xa9" => [140, "\xa8"], "\xaa" => [146, "\xa8"], "\xab" => [102, "\xa8"], "\xac" => [113, "\xa8"], "\xad" => [121, "\xa8"], "\xae" => [128, "\xa8"], "\xaf" => [12, "\xa8"], "\xb0" => [92, "\xae"], "\xb1" => [95, "\xae"], "\xb2" => [137, "\xae"], "\xb3" => [142, "\xae"], "\xb4" => [150, "\xae"], "\xb5" => [74, "\xae"], "\xb6" => [90, "\xae"], "\xb7" => [98, "\xae"], "\xb8" => [107, "\xae"], "\xb9" => [140, "\xae"], "\xba" => [146, "\xae"], "\xbb" => [102, "\xae"], "\xbc" => [113, "\xae"], "\xbd" => [121, "\xae"], "\xbe" => [128, "\xae"], "\xbf" => [12, "\xae"], "\xc0" => [92, "\xaf"], "\xc1" => [95, "\xaf"], "\xc2" => [137, "\xaf"], "\xc3" => [142, "\xaf"], "\xc4" => [150, "\xaf"], "\xc5" => [74, "\xaf"], "\xc6" => [90, "\xaf"], "\xc7" => [98, "\xaf"], "\xc8" => [107, "\xaf"], "\xc9" => [140, "\xaf"], "\xca" => [146, "\xaf"], "\xcb" => [102, "\xaf"], "\xcc" => [113, "\xaf"], "\xcd" => [121, "\xaf"], "\xce" => [128, "\xaf"], "\xcf" => [12, "\xaf"], "\xd0" => [92, "\xb4"], "\xd1" => [95, "\xb4"], "\xd2" => [137, "\xb4"], "\xd3" => [142, "\xb4"], "\xd4" => [150, "\xb4"], "\xd5" => [74, "\xb4"], "\xd6" => [90, "\xb4"], "\xd7" => [98, "\xb4"], "\xd8" => [107, "\xb4"], "\xd9" => [140, "\xb4"], "\xda" => [146, "\xb4"], "\xdb" => [102, "\xb4"], "\xdc" => [113, "\xb4"], "\xdd" => [121, "\xb4"], "\xde" => [128, "\xb4"], "\xdf" => [12, "\xb4"], "\xe0" => [92, "\xb6"], "\xe1" => [95, "\xb6"], "\xe2" => [137, "\xb6"], "\xe3" => [142, "\xb6"], "\xe4" => [150, "\xb6"], "\xe5" => [74, "\xb6"], "\xe6" => [90, "\xb6"], "\xe7" => [98, "\xb6"], "\xe8" => [107, "\xb6"], "\xe9" => [140, "\xb6"], "\xea" => [146, "\xb6"], "\xeb" => [102, "\xb6"], "\xec" => [113, "\xb6"], "\xed" => [121, "\xb6"], "\xee" => [128, "\xb6"], "\xef" => [12, "\xb6"], "\xf0" => [92, "\xb7"], "\xf1" => [95, "\xb7"], "\xf2" => [137, "\xb7"], "\xf3" => [142, "\xb7"], "\xf4" => [150, "\xb7"], "\xf5" => [74, "\xb7"], "\xf6" => [90, "\xb7"], "\xf7" => [98, "\xb7"], "\xf8" => [107, "\xb7"], "\xf9" => [140, "\xb7"], "\xfa" => [146, "\xb7"], "\xfb" => [102, "\xb7"], "\xfc" => [113, "\xb7"], "\xfd" => [121, "\xb7"], "\xfe" => [128, "\xb7"], "\xff" => [12, "\xb7"]], ["\x00" => [94, "\x940"], "\x01" => [76, "\x940"], "\x02" => [104, "\x940"], "\x03" => [16, "\x940"], "\x04" => [94, "\x941"], "\x05" => [76, "\x941"], "\x06" => [104, "\x941"], "\x07" => [16, "\x941"], "\x08" => [94, "\x942"], "\t" => [76, "\x942"], "\n" => [104, "\x942"], "\v" => [16, "\x942"], "\f" => [94, "\x94a"], "\r" => [76, "\x94a"], "\x0e" => [104, "\x94a"], "\x0f" => [16, "\x94a"], "\x10" => [94, "\x94c"], "\x11" => [76, "\x94c"], "\x12" => [104, "\x94c"], "\x13" => [16, "\x94c"], "\x14" => [94, "\x94e"], "\x15" => [76, "\x94e"], "\x16" => [104, "\x94e"], "\x17" => [16, "\x94e"], "\x18" => [94, "\x94i"], "\x19" => [76, "\x94i"], "\x1a" => [104, "\x94i"], "\x1b" => [16, "\x94i"], "\x1c" => [94, "\x94o"], "\x1d" => [76, "\x94o"], "\x1e" => [104, "\x94o"], "\x1f" => [16, "\x94o"], " " => [94, "\x94s"], "!" => [76, "\x94s"], "\"" => [104, "\x94s"], "#" => [16, "\x94s"], "\$" => [94, "\x94t"], "%" => [76, "\x94t"], "&" => [104, "\x94t"], "'" => [16, "\x94t"], "(" => [77, "\x94 "], ")" => [18, "\x94 "], "*" => [77, "\x94%"], "+" => [18, "\x94%"], "," => [77, "\x94-"], "-" => [18, "\x94-"], "." => [77, "\x94."], "/" => [18, "\x94."], [77, "\x94/"], [18, "\x94/"], [77, "\x943"], [18, "\x943"], [77, "\x944"], [18, "\x944"], [77, "\x945"], [18, "\x945"], [77, "\x946"], [18, "\x946"], ":" => [77, "\x947"], ";" => [18, "\x947"], "<" => [77, "\x948"], "=" => [18, "\x948"], ">" => [77, "\x949"], "?" => [18, "\x949"], "@" => [77, "\x94="], "A" => [18, "\x94="], "B" => [77, "\x94A"], "C" => [18, "\x94A"], "D" => [77, "\x94_"], "E" => [18, "\x94_"], "F" => [77, "\x94b"], "G" => [18, "\x94b"], "H" => [77, "\x94d"], "I" => [18, "\x94d"], "J" => [77, "\x94f"], "K" => [18, "\x94f"], "L" => [77, "\x94g"], "M" => [18, "\x94g"], "N" => [77, "\x94h"], "O" => [18, "\x94h"], "P" => [77, "\x94l"], "Q" => [18, "\x94l"], "R" => [77, "\x94m"], "S" => [18, "\x94m"], "T" => [77, "\x94n"], "U" => [18, "\x94n"], "V" => [77, "\x94p"], "W" => [18, "\x94p"], "X" => [77, "\x94r"], "Y" => [18, "\x94r"], "Z" => [77, "\x94u"], "[" => [18, "\x94u"], "\\" => [0, "\x94:"], "]" => [0, "\x94B"], "^" => [0, "\x94C"], "_" => [0, "\x94D"], "`" => [0, "\x94E"], "a" => [0, "\x94F"], "b" => [0, "\x94G"], "c" => [0, "\x94H"], "d" => [0, "\x94I"], "e" => [0, "\x94J"], "f" => [0, "\x94K"], "g" => [0, "\x94L"], "h" => [0, "\x94M"], "i" => [0, "\x94N"], "j" => [0, "\x94O"], "k" => [0, "\x94P"], "l" => [0, "\x94Q"], "m" => [0, "\x94R"], "n" => [0, "\x94S"], "o" => [0, "\x94T"], "p" => [0, "\x94U"], "q" => [0, "\x94V"], "r" => [0, "\x94W"], "s" => [0, "\x94Y"], "t" => [0, "\x94j"], "u" => [0, "\x94k"], "v" => [0, "\x94q"], "w" => [0, "\x94v"], "x" => [0, "\x94w"], "y" => [0, "\x94x"], "z" => [0, "\x94y"], "{" => [0, "\x94z"], "|" => [82, "\x94"], "}" => [87, "\x94"], "~" => [130, "\x94"], "" => [9, "\x94"], "\x80" => [94, "\x9f0"], "\x81" => [76, "\x9f0"], "\x82" => [104, "\x9f0"], "\x83" => [16, "\x9f0"], "\x84" => [94, "\x9f1"], "\x85" => [76, "\x9f1"], "\x86" => [104, "\x9f1"], "\x87" => [16, "\x9f1"], "\x88" => [94, "\x9f2"], "\x89" => [76, "\x9f2"], "\x8a" => [104, "\x9f2"], "\x8b" => [16, "\x9f2"], "\x8c" => [94, "\x9fa"], "\x8d" => [76, "\x9fa"], "\x8e" => [104, "\x9fa"], "\x8f" => [16, "\x9fa"], "\x90" => [94, "\x9fc"], "\x91" => [76, "\x9fc"], "\x92" => [104, "\x9fc"], "\x93" => [16, "\x9fc"], "\x94" => [94, "\x9fe"], "\x95" => [76, "\x9fe"], "\x96" => [104, "\x9fe"], "\x97" => [16, "\x9fe"], "\x98" => [94, "\x9fi"], "\x99" => [76, "\x9fi"], "\x9a" => [104, "\x9fi"], "\x9b" => [16, "\x9fi"], "\x9c" => [94, "\x9fo"], "\x9d" => [76, "\x9fo"], "\x9e" => [104, "\x9fo"], "\x9f" => [16, "\x9fo"], "\xa0" => [94, "\x9fs"], "\xa1" => [76, "\x9fs"], "\xa2" => [104, "\x9fs"], "\xa3" => [16, "\x9fs"], "\xa4" => [94, "\x9ft"], "\xa5" => [76, "\x9ft"], "\xa6" => [104, "\x9ft"], "\xa7" => [16, "\x9ft"], "\xa8" => [77, "\x9f "], "\xa9" => [18, "\x9f "], "\xaa" => [77, "\x9f%"], "\xab" => [18, "\x9f%"], "\xac" => [77, "\x9f-"], "\xad" => [18, "\x9f-"], "\xae" => [77, "\x9f."], "\xaf" => [18, "\x9f."], "\xb0" => [77, "\x9f/"], "\xb1" => [18, "\x9f/"], "\xb2" => [77, "\x9f3"], "\xb3" => [18, "\x9f3"], "\xb4" => [77, "\x9f4"], "\xb5" => [18, "\x9f4"], "\xb6" => [77, "\x9f5"], "\xb7" => [18, "\x9f5"], "\xb8" => [77, "\x9f6"], "\xb9" => [18, "\x9f6"], "\xba" => [77, "\x9f7"], "\xbb" => [18, "\x9f7"], "\xbc" => [77, "\x9f8"], "\xbd" => [18, "\x9f8"], "\xbe" => [77, "\x9f9"], "\xbf" => [18, "\x9f9"], "\xc0" => [77, "\x9f="], "\xc1" => [18, "\x9f="], "\xc2" => [77, "\x9fA"], "\xc3" => [18, "\x9fA"], "\xc4" => [77, "\x9f_"], "\xc5" => [18, "\x9f_"], "\xc6" => [77, "\x9fb"], "\xc7" => [18, "\x9fb"], "\xc8" => [77, "\x9fd"], "\xc9" => [18, "\x9fd"], "\xca" => [77, "\x9ff"], "\xcb" => [18, "\x9ff"], "\xcc" => [77, "\x9fg"], "\xcd" => [18, "\x9fg"], "\xce" => [77, "\x9fh"], "\xcf" => [18, "\x9fh"], "\xd0" => [77, "\x9fl"], "\xd1" => [18, "\x9fl"], "\xd2" => [77, "\x9fm"], "\xd3" => [18, "\x9fm"], "\xd4" => [77, "\x9fn"], "\xd5" => [18, "\x9fn"], "\xd6" => [77, "\x9fp"], "\xd7" => [18, "\x9fp"], "\xd8" => [77, "\x9fr"], "\xd9" => [18, "\x9fr"], "\xda" => [77, "\x9fu"], "\xdb" => [18, "\x9fu"], "\xdc" => [0, "\x9f:"], "\xdd" => [0, "\x9fB"], "\xde" => [0, "\x9fC"], "\xdf" => [0, "\x9fD"], "\xe0" => [0, "\x9fE"], "\xe1" => [0, "\x9fF"], "\xe2" => [0, "\x9fG"], "\xe3" => [0, "\x9fH"], "\xe4" => [0, "\x9fI"], "\xe5" => [0, "\x9fJ"], "\xe6" => [0, "\x9fK"], "\xe7" => [0, "\x9fL"], "\xe8" => [0, "\x9fM"], "\xe9" => [0, "\x9fN"], "\xea" => [0, "\x9fO"], "\xeb" => [0, "\x9fP"], "\xec" => [0, "\x9fQ"], "\xed" => [0, "\x9fR"], "\xee" => [0, "\x9fS"], "\xef" => [0, "\x9fT"], "\xf0" => [0, "\x9fU"], "\xf1" => [0, "\x9fV"], "\xf2" => [0, "\x9fW"], "\xf3" => [0, "\x9fY"], "\xf4" => [0, "\x9fj"], "\xf5" => [0, "\x9fk"], "\xf6" => [0, "\x9fq"], "\xf7" => [0, "\x9fv"], "\xf8" => [0, "\x9fw"], "\xf9" => [0, "\x9fx"], "\xfa" => [0, "\x9fy"], "\xfb" => [0, "\x9fz"], "\xfc" => [82, "\x9f"], "\xfd" => [87, "\x9f"], "\xfe" => [130, "\x9f"], "\xff" => [9, "\x9f"]], ["\x00" => [94, "\x960"], "\x01" => [76, "\x960"], "\x02" => [104, "\x960"], "\x03" => [16, "\x960"], "\x04" => [94, "\x961"], "\x05" => [76, "\x961"], "\x06" => [104, "\x961"], "\x07" => [16, "\x961"], "\x08" => [94, "\x962"], "\t" => [76, "\x962"], "\n" => [104, "\x962"], "\v" => [16, "\x962"], "\f" => [94, "\x96a"], "\r" => [76, "\x96a"], "\x0e" => [104, "\x96a"], "\x0f" => [16, "\x96a"], "\x10" => [94, "\x96c"], "\x11" => [76, "\x96c"], "\x12" => [104, "\x96c"], "\x13" => [16, "\x96c"], "\x14" => [94, "\x96e"], "\x15" => [76, "\x96e"], "\x16" => [104, "\x96e"], "\x17" => [16, "\x96e"], "\x18" => [94, "\x96i"], "\x19" => [76, "\x96i"], "\x1a" => [104, "\x96i"], "\x1b" => [16, "\x96i"], "\x1c" => [94, "\x96o"], "\x1d" => [76, "\x96o"], "\x1e" => [104, "\x96o"], "\x1f" => [16, "\x96o"], " " => [94, "\x96s"], "!" => [76, "\x96s"], "\"" => [104, "\x96s"], "#" => [16, "\x96s"], "\$" => [94, "\x96t"], "%" => [76, "\x96t"], "&" => [104, "\x96t"], "'" => [16, "\x96t"], "(" => [77, "\x96 "], ")" => [18, "\x96 "], "*" => [77, "\x96%"], "+" => [18, "\x96%"], "," => [77, "\x96-"], "-" => [18, "\x96-"], "." => [77, "\x96."], "/" => [18, "\x96."], [77, "\x96/"], [18, "\x96/"], [77, "\x963"], [18, "\x963"], [77, "\x964"], [18, "\x964"], [77, "\x965"], [18, "\x965"], [77, "\x966"], [18, "\x966"], ":" => [77, "\x967"], ";" => [18, "\x967"], "<" => [77, "\x968"], "=" => [18, "\x968"], ">" => [77, "\x969"], "?" => [18, "\x969"], "@" => [77, "\x96="], "A" => [18, "\x96="], "B" => [77, "\x96A"], "C" => [18, "\x96A"], "D" => [77, "\x96_"], "E" => [18, "\x96_"], "F" => [77, "\x96b"], "G" => [18, "\x96b"], "H" => [77, "\x96d"], "I" => [18, "\x96d"], "J" => [77, "\x96f"], "K" => [18, "\x96f"], "L" => [77, "\x96g"], "M" => [18, "\x96g"], "N" => [77, "\x96h"], "O" => [18, "\x96h"], "P" => [77, "\x96l"], "Q" => [18, "\x96l"], "R" => [77, "\x96m"], "S" => [18, "\x96m"], "T" => [77, "\x96n"], "U" => [18, "\x96n"], "V" => [77, "\x96p"], "W" => [18, "\x96p"], "X" => [77, "\x96r"], "Y" => [18, "\x96r"], "Z" => [77, "\x96u"], "[" => [18, "\x96u"], "\\" => [0, "\x96:"], "]" => [0, "\x96B"], "^" => [0, "\x96C"], "_" => [0, "\x96D"], "`" => [0, "\x96E"], "a" => [0, "\x96F"], "b" => [0, "\x96G"], "c" => [0, "\x96H"], "d" => [0, "\x96I"], "e" => [0, "\x96J"], "f" => [0, "\x96K"], "g" => [0, "\x96L"], "h" => [0, "\x96M"], "i" => [0, "\x96N"], "j" => [0, "\x96O"], "k" => [0, "\x96P"], "l" => [0, "\x96Q"], "m" => [0, "\x96R"], "n" => [0, "\x96S"], "o" => [0, "\x96T"], "p" => [0, "\x96U"], "q" => [0, "\x96V"], "r" => [0, "\x96W"], "s" => [0, "\x96Y"], "t" => [0, "\x96j"], "u" => [0, "\x96k"], "v" => [0, "\x96q"], "w" => [0, "\x96v"], "x" => [0, "\x96w"], "y" => [0, "\x96x"], "z" => [0, "\x96y"], "{" => [0, "\x96z"], "|" => [82, "\x96"], "}" => [87, "\x96"], "~" => [130, "\x96"], "" => [9, "\x96"], "\x80" => [94, "\x970"], "\x81" => [76, "\x970"], "\x82" => [104, "\x970"], "\x83" => [16, "\x970"], "\x84" => [94, "\x971"], "\x85" => [76, "\x971"], "\x86" => [104, "\x971"], "\x87" => [16, "\x971"], "\x88" => [94, "\x972"], "\x89" => [76, "\x972"], "\x8a" => [104, "\x972"], "\x8b" => [16, "\x972"], "\x8c" => [94, "\x97a"], "\x8d" => [76, "\x97a"], "\x8e" => [104, "\x97a"], "\x8f" => [16, "\x97a"], "\x90" => [94, "\x97c"], "\x91" => [76, "\x97c"], "\x92" => [104, "\x97c"], "\x93" => [16, "\x97c"], "\x94" => [94, "\x97e"], "\x95" => [76, "\x97e"], "\x96" => [104, "\x97e"], "\x97" => [16, "\x97e"], "\x98" => [94, "\x97i"], "\x99" => [76, "\x97i"], "\x9a" => [104, "\x97i"], "\x9b" => [16, "\x97i"], "\x9c" => [94, "\x97o"], "\x9d" => [76, "\x97o"], "\x9e" => [104, "\x97o"], "\x9f" => [16, "\x97o"], "\xa0" => [94, "\x97s"], "\xa1" => [76, "\x97s"], "\xa2" => [104, "\x97s"], "\xa3" => [16, "\x97s"], "\xa4" => [94, "\x97t"], "\xa5" => [76, "\x97t"], "\xa6" => [104, "\x97t"], "\xa7" => [16, "\x97t"], "\xa8" => [77, "\x97 "], "\xa9" => [18, "\x97 "], "\xaa" => [77, "\x97%"], "\xab" => [18, "\x97%"], "\xac" => [77, "\x97-"], "\xad" => [18, "\x97-"], "\xae" => [77, "\x97."], "\xaf" => [18, "\x97."], "\xb0" => [77, "\x97/"], "\xb1" => [18, "\x97/"], "\xb2" => [77, "\x973"], "\xb3" => [18, "\x973"], "\xb4" => [77, "\x974"], "\xb5" => [18, "\x974"], "\xb6" => [77, "\x975"], "\xb7" => [18, "\x975"], "\xb8" => [77, "\x976"], "\xb9" => [18, "\x976"], "\xba" => [77, "\x977"], "\xbb" => [18, "\x977"], "\xbc" => [77, "\x978"], "\xbd" => [18, "\x978"], "\xbe" => [77, "\x979"], "\xbf" => [18, "\x979"], "\xc0" => [77, "\x97="], "\xc1" => [18, "\x97="], "\xc2" => [77, "\x97A"], "\xc3" => [18, "\x97A"], "\xc4" => [77, "\x97_"], "\xc5" => [18, "\x97_"], "\xc6" => [77, "\x97b"], "\xc7" => [18, "\x97b"], "\xc8" => [77, "\x97d"], "\xc9" => [18, "\x97d"], "\xca" => [77, "\x97f"], "\xcb" => [18, "\x97f"], "\xcc" => [77, "\x97g"], "\xcd" => [18, "\x97g"], "\xce" => [77, "\x97h"], "\xcf" => [18, "\x97h"], "\xd0" => [77, "\x97l"], "\xd1" => [18, "\x97l"], "\xd2" => [77, "\x97m"], "\xd3" => [18, "\x97m"], "\xd4" => [77, "\x97n"], "\xd5" => [18, "\x97n"], "\xd6" => [77, "\x97p"], "\xd7" => [18, "\x97p"], "\xd8" => [77, "\x97r"], "\xd9" => [18, "\x97r"], "\xda" => [77, "\x97u"], "\xdb" => [18, "\x97u"], "\xdc" => [0, "\x97:"], "\xdd" => [0, "\x97B"], "\xde" => [0, "\x97C"], "\xdf" => [0, "\x97D"], "\xe0" => [0, "\x97E"], "\xe1" => [0, "\x97F"], "\xe2" => [0, "\x97G"], "\xe3" => [0, "\x97H"], "\xe4" => [0, "\x97I"], "\xe5" => [0, "\x97J"], "\xe6" => [0, "\x97K"], "\xe7" => [0, "\x97L"], "\xe8" => [0, "\x97M"], "\xe9" => [0, "\x97N"], "\xea" => [0, "\x97O"], "\xeb" => [0, "\x97P"], "\xec" => [0, "\x97Q"], "\xed" => [0, "\x97R"], "\xee" => [0, "\x97S"], "\xef" => [0, "\x97T"], "\xf0" => [0, "\x97U"], "\xf1" => [0, "\x97V"], "\xf2" => [0, "\x97W"], "\xf3" => [0, "\x97Y"], "\xf4" => [0, "\x97j"], "\xf5" => [0, "\x97k"], "\xf6" => [0, "\x97q"], "\xf7" => [0, "\x97v"], "\xf8" => [0, "\x97w"], "\xf9" => [0, "\x97x"], "\xfa" => [0, "\x97y"], "\xfb" => [0, "\x97z"], "\xfc" => [82, "\x97"], "\xfd" => [87, "\x97"], "\xfe" => [130, "\x97"], "\xff" => [9, "\x97"]], ["\x00" => [94, "\x980"], "\x01" => [76, "\x980"], "\x02" => [104, "\x980"], "\x03" => [16, "\x980"], "\x04" => [94, "\x981"], "\x05" => [76, "\x981"], "\x06" => [104, "\x981"], "\x07" => [16, "\x981"], "\x08" => [94, "\x982"], "\t" => [76, "\x982"], "\n" => [104, "\x982"], "\v" => [16, "\x982"], "\f" => [94, "\x98a"], "\r" => [76, "\x98a"], "\x0e" => [104, "\x98a"], "\x0f" => [16, "\x98a"], "\x10" => [94, "\x98c"], "\x11" => [76, "\x98c"], "\x12" => [104, "\x98c"], "\x13" => [16, "\x98c"], "\x14" => [94, "\x98e"], "\x15" => [76, "\x98e"], "\x16" => [104, "\x98e"], "\x17" => [16, "\x98e"], "\x18" => [94, "\x98i"], "\x19" => [76, "\x98i"], "\x1a" => [104, "\x98i"], "\x1b" => [16, "\x98i"], "\x1c" => [94, "\x98o"], "\x1d" => [76, "\x98o"], "\x1e" => [104, "\x98o"], "\x1f" => [16, "\x98o"], " " => [94, "\x98s"], "!" => [76, "\x98s"], "\"" => [104, "\x98s"], "#" => [16, "\x98s"], "\$" => [94, "\x98t"], "%" => [76, "\x98t"], "&" => [104, "\x98t"], "'" => [16, "\x98t"], "(" => [77, "\x98 "], ")" => [18, "\x98 "], "*" => [77, "\x98%"], "+" => [18, "\x98%"], "," => [77, "\x98-"], "-" => [18, "\x98-"], "." => [77, "\x98."], "/" => [18, "\x98."], [77, "\x98/"], [18, "\x98/"], [77, "\x983"], [18, "\x983"], [77, "\x984"], [18, "\x984"], [77, "\x985"], [18, "\x985"], [77, "\x986"], [18, "\x986"], ":" => [77, "\x987"], ";" => [18, "\x987"], "<" => [77, "\x988"], "=" => [18, "\x988"], ">" => [77, "\x989"], "?" => [18, "\x989"], "@" => [77, "\x98="], "A" => [18, "\x98="], "B" => [77, "\x98A"], "C" => [18, "\x98A"], "D" => [77, "\x98_"], "E" => [18, "\x98_"], "F" => [77, "\x98b"], "G" => [18, "\x98b"], "H" => [77, "\x98d"], "I" => [18, "\x98d"], "J" => [77, "\x98f"], "K" => [18, "\x98f"], "L" => [77, "\x98g"], "M" => [18, "\x98g"], "N" => [77, "\x98h"], "O" => [18, "\x98h"], "P" => [77, "\x98l"], "Q" => [18, "\x98l"], "R" => [77, "\x98m"], "S" => [18, "\x98m"], "T" => [77, "\x98n"], "U" => [18, "\x98n"], "V" => [77, "\x98p"], "W" => [18, "\x98p"], "X" => [77, "\x98r"], "Y" => [18, "\x98r"], "Z" => [77, "\x98u"], "[" => [18, "\x98u"], "\\" => [0, "\x98:"], "]" => [0, "\x98B"], "^" => [0, "\x98C"], "_" => [0, "\x98D"], "`" => [0, "\x98E"], "a" => [0, "\x98F"], "b" => [0, "\x98G"], "c" => [0, "\x98H"], "d" => [0, "\x98I"], "e" => [0, "\x98J"], "f" => [0, "\x98K"], "g" => [0, "\x98L"], "h" => [0, "\x98M"], "i" => [0, "\x98N"], "j" => [0, "\x98O"], "k" => [0, "\x98P"], "l" => [0, "\x98Q"], "m" => [0, "\x98R"], "n" => [0, "\x98S"], "o" => [0, "\x98T"], "p" => [0, "\x98U"], "q" => [0, "\x98V"], "r" => [0, "\x98W"], "s" => [0, "\x98Y"], "t" => [0, "\x98j"], "u" => [0, "\x98k"], "v" => [0, "\x98q"], "w" => [0, "\x98v"], "x" => [0, "\x98w"], "y" => [0, "\x98x"], "z" => [0, "\x98y"], "{" => [0, "\x98z"], "|" => [82, "\x98"], "}" => [87, "\x98"], "~" => [130, "\x98"], "" => [9, "\x98"], "\x80" => [94, "\x9b0"], "\x81" => [76, "\x9b0"], "\x82" => [104, "\x9b0"], "\x83" => [16, "\x9b0"], "\x84" => [94, "\x9b1"], "\x85" => [76, "\x9b1"], "\x86" => [104, "\x9b1"], "\x87" => [16, "\x9b1"], "\x88" => [94, "\x9b2"], "\x89" => [76, "\x9b2"], "\x8a" => [104, "\x9b2"], "\x8b" => [16, "\x9b2"], "\x8c" => [94, "\x9ba"], "\x8d" => [76, "\x9ba"], "\x8e" => [104, "\x9ba"], "\x8f" => [16, "\x9ba"], "\x90" => [94, "\x9bc"], "\x91" => [76, "\x9bc"], "\x92" => [104, "\x9bc"], "\x93" => [16, "\x9bc"], "\x94" => [94, "\x9be"], "\x95" => [76, "\x9be"], "\x96" => [104, "\x9be"], "\x97" => [16, "\x9be"], "\x98" => [94, "\x9bi"], "\x99" => [76, "\x9bi"], "\x9a" => [104, "\x9bi"], "\x9b" => [16, "\x9bi"], "\x9c" => [94, "\x9bo"], "\x9d" => [76, "\x9bo"], "\x9e" => [104, "\x9bo"], "\x9f" => [16, "\x9bo"], "\xa0" => [94, "\x9bs"], "\xa1" => [76, "\x9bs"], "\xa2" => [104, "\x9bs"], "\xa3" => [16, "\x9bs"], "\xa4" => [94, "\x9bt"], "\xa5" => [76, "\x9bt"], "\xa6" => [104, "\x9bt"], "\xa7" => [16, "\x9bt"], "\xa8" => [77, "\x9b "], "\xa9" => [18, "\x9b "], "\xaa" => [77, "\x9b%"], "\xab" => [18, "\x9b%"], "\xac" => [77, "\x9b-"], "\xad" => [18, "\x9b-"], "\xae" => [77, "\x9b."], "\xaf" => [18, "\x9b."], "\xb0" => [77, "\x9b/"], "\xb1" => [18, "\x9b/"], "\xb2" => [77, "\x9b3"], "\xb3" => [18, "\x9b3"], "\xb4" => [77, "\x9b4"], "\xb5" => [18, "\x9b4"], "\xb6" => [77, "\x9b5"], "\xb7" => [18, "\x9b5"], "\xb8" => [77, "\x9b6"], "\xb9" => [18, "\x9b6"], "\xba" => [77, "\x9b7"], "\xbb" => [18, "\x9b7"], "\xbc" => [77, "\x9b8"], "\xbd" => [18, "\x9b8"], "\xbe" => [77, "\x9b9"], "\xbf" => [18, "\x9b9"], "\xc0" => [77, "\x9b="], "\xc1" => [18, "\x9b="], "\xc2" => [77, "\x9bA"], "\xc3" => [18, "\x9bA"], "\xc4" => [77, "\x9b_"], "\xc5" => [18, "\x9b_"], "\xc6" => [77, "\x9bb"], "\xc7" => [18, "\x9bb"], "\xc8" => [77, "\x9bd"], "\xc9" => [18, "\x9bd"], "\xca" => [77, "\x9bf"], "\xcb" => [18, "\x9bf"], "\xcc" => [77, "\x9bg"], "\xcd" => [18, "\x9bg"], "\xce" => [77, "\x9bh"], "\xcf" => [18, "\x9bh"], "\xd0" => [77, "\x9bl"], "\xd1" => [18, "\x9bl"], "\xd2" => [77, "\x9bm"], "\xd3" => [18, "\x9bm"], "\xd4" => [77, "\x9bn"], "\xd5" => [18, "\x9bn"], "\xd6" => [77, "\x9bp"], "\xd7" => [18, "\x9bp"], "\xd8" => [77, "\x9br"], "\xd9" => [18, "\x9br"], "\xda" => [77, "\x9bu"], "\xdb" => [18, "\x9bu"], "\xdc" => [0, "\x9b:"], "\xdd" => [0, "\x9bB"], "\xde" => [0, "\x9bC"], "\xdf" => [0, "\x9bD"], "\xe0" => [0, "\x9bE"], "\xe1" => [0, "\x9bF"], "\xe2" => [0, "\x9bG"], "\xe3" => [0, "\x9bH"], "\xe4" => [0, "\x9bI"], "\xe5" => [0, "\x9bJ"], "\xe6" => [0, "\x9bK"], "\xe7" => [0, "\x9bL"], "\xe8" => [0, "\x9bM"], "\xe9" => [0, "\x9bN"], "\xea" => [0, "\x9bO"], "\xeb" => [0, "\x9bP"], "\xec" => [0, "\x9bQ"], "\xed" => [0, "\x9bR"], "\xee" => [0, "\x9bS"], "\xef" => [0, "\x9bT"], "\xf0" => [0, "\x9bU"], "\xf1" => [0, "\x9bV"], "\xf2" => [0, "\x9bW"], "\xf3" => [0, "\x9bY"], "\xf4" => [0, "\x9bj"], "\xf5" => [0, "\x9bk"], "\xf6" => [0, "\x9bq"], "\xf7" => [0, "\x9bv"], "\xf8" => [0, "\x9bw"], "\xf9" => [0, "\x9bx"], "\xfa" => [0, "\x9by"], "\xfb" => [0, "\x9bz"], "\xfc" => [82, "\x9b"], "\xfd" => [87, "\x9b"], "\xfe" => [130, "\x9b"], "\xff" => [9, "\x9b"]], ["\x00" => [77, "\x980"], "\x01" => [18, "\x980"], "\x02" => [77, "\x981"], "\x03" => [18, "\x981"], "\x04" => [77, "\x982"], "\x05" => [18, "\x982"], "\x06" => [77, "\x98a"], "\x07" => [18, "\x98a"], "\x08" => [77, "\x98c"], "\t" => [18, "\x98c"], "\n" => [77, "\x98e"], "\v" => [18, "\x98e"], "\f" => [77, "\x98i"], "\r" => [18, "\x98i"], "\x0e" => [77, "\x98o"], "\x0f" => [18, "\x98o"], "\x10" => [77, "\x98s"], "\x11" => [18, "\x98s"], "\x12" => [77, "\x98t"], "\x13" => [18, "\x98t"], "\x14" => [0, "\x98 "], "\x15" => [0, "\x98%"], "\x16" => [0, "\x98-"], "\x17" => [0, "\x98."], "\x18" => [0, "\x98/"], "\x19" => [0, "\x983"], "\x1a" => [0, "\x984"], "\x1b" => [0, "\x985"], "\x1c" => [0, "\x986"], "\x1d" => [0, "\x987"], "\x1e" => [0, "\x988"], "\x1f" => [0, "\x989"], " " => [0, "\x98="], "!" => [0, "\x98A"], "\"" => [0, "\x98_"], "#" => [0, "\x98b"], "\$" => [0, "\x98d"], "%" => [0, "\x98f"], "&" => [0, "\x98g"], "'" => [0, "\x98h"], "(" => [0, "\x98l"], ")" => [0, "\x98m"], "*" => [0, "\x98n"], "+" => [0, "\x98p"], "," => [0, "\x98r"], "-" => [0, "\x98u"], "." => [100, "\x98"], "/" => [110, "\x98"], [111, "\x98"], [115, "\x98"], [116, "\x98"], [118, "\x98"], [119, "\x98"], [122, "\x98"], [123, "\x98"], [125, "\x98"], [126, "\x98"], [129, "\x98"], ":" => [143, "\x98"], ";" => [148, "\x98"], "<" => [151, "\x98"], "=" => [153, "\x98"], ">" => [83, "\x98"], "?" => [10, "\x98"], "@" => [77, "\x9b0"], "A" => [18, "\x9b0"], "B" => [77, "\x9b1"], "C" => [18, "\x9b1"], "D" => [77, "\x9b2"], "E" => [18, "\x9b2"], "F" => [77, "\x9ba"], "G" => [18, "\x9ba"], "H" => [77, "\x9bc"], "I" => [18, "\x9bc"], "J" => [77, "\x9be"], "K" => [18, "\x9be"], "L" => [77, "\x9bi"], "M" => [18, "\x9bi"], "N" => [77, "\x9bo"], "O" => [18, "\x9bo"], "P" => [77, "\x9bs"], "Q" => [18, "\x9bs"], "R" => [77, "\x9bt"], "S" => [18, "\x9bt"], "T" => [0, "\x9b "], "U" => [0, "\x9b%"], "V" => [0, "\x9b-"], "W" => [0, "\x9b."], "X" => [0, "\x9b/"], "Y" => [0, "\x9b3"], "Z" => [0, "\x9b4"], "[" => [0, "\x9b5"], "\\" => [0, "\x9b6"], "]" => [0, "\x9b7"], "^" => [0, "\x9b8"], "_" => [0, "\x9b9"], "`" => [0, "\x9b="], "a" => [0, "\x9bA"], "b" => [0, "\x9b_"], "c" => [0, "\x9bb"], "d" => [0, "\x9bd"], "e" => [0, "\x9bf"], "f" => [0, "\x9bg"], "g" => [0, "\x9bh"], "h" => [0, "\x9bl"], "i" => [0, "\x9bm"], "j" => [0, "\x9bn"], "k" => [0, "\x9bp"], "l" => [0, "\x9br"], "m" => [0, "\x9bu"], "n" => [100, "\x9b"], "o" => [110, "\x9b"], "p" => [111, "\x9b"], "q" => [115, "\x9b"], "r" => [116, "\x9b"], "s" => [118, "\x9b"], "t" => [119, "\x9b"], "u" => [122, "\x9b"], "v" => [123, "\x9b"], "w" => [125, "\x9b"], "x" => [126, "\x9b"], "y" => [129, "\x9b"], "z" => [143, "\x9b"], "{" => [148, "\x9b"], "|" => [151, "\x9b"], "}" => [153, "\x9b"], "~" => [83, "\x9b"], "" => [10, "\x9b"], "\x80" => [77, "\x9d0"], "\x81" => [18, "\x9d0"], "\x82" => [77, "\x9d1"], "\x83" => [18, "\x9d1"], "\x84" => [77, "\x9d2"], "\x85" => [18, "\x9d2"], "\x86" => [77, "\x9da"], "\x87" => [18, "\x9da"], "\x88" => [77, "\x9dc"], "\x89" => [18, "\x9dc"], "\x8a" => [77, "\x9de"], "\x8b" => [18, "\x9de"], "\x8c" => [77, "\x9di"], "\x8d" => [18, "\x9di"], "\x8e" => [77, "\x9do"], "\x8f" => [18, "\x9do"], "\x90" => [77, "\x9ds"], "\x91" => [18, "\x9ds"], "\x92" => [77, "\x9dt"], "\x93" => [18, "\x9dt"], "\x94" => [0, "\x9d "], "\x95" => [0, "\x9d%"], "\x96" => [0, "\x9d-"], "\x97" => [0, "\x9d."], "\x98" => [0, "\x9d/"], "\x99" => [0, "\x9d3"], "\x9a" => [0, "\x9d4"], "\x9b" => [0, "\x9d5"], "\x9c" => [0, "\x9d6"], "\x9d" => [0, "\x9d7"], "\x9e" => [0, "\x9d8"], "\x9f" => [0, "\x9d9"], "\xa0" => [0, "\x9d="], "\xa1" => [0, "\x9dA"], "\xa2" => [0, "\x9d_"], "\xa3" => [0, "\x9db"], "\xa4" => [0, "\x9dd"], "\xa5" => [0, "\x9df"], "\xa6" => [0, "\x9dg"], "\xa7" => [0, "\x9dh"], "\xa8" => [0, "\x9dl"], "\xa9" => [0, "\x9dm"], "\xaa" => [0, "\x9dn"], "\xab" => [0, "\x9dp"], "\xac" => [0, "\x9dr"], "\xad" => [0, "\x9du"], "\xae" => [100, "\x9d"], "\xaf" => [110, "\x9d"], "\xb0" => [111, "\x9d"], "\xb1" => [115, "\x9d"], "\xb2" => [116, "\x9d"], "\xb3" => [118, "\x9d"], "\xb4" => [119, "\x9d"], "\xb5" => [122, "\x9d"], "\xb6" => [123, "\x9d"], "\xb7" => [125, "\x9d"], "\xb8" => [126, "\x9d"], "\xb9" => [129, "\x9d"], "\xba" => [143, "\x9d"], "\xbb" => [148, "\x9d"], "\xbc" => [151, "\x9d"], "\xbd" => [153, "\x9d"], "\xbe" => [83, "\x9d"], "\xbf" => [10, "\x9d"], "\xc0" => [77, "\x9e0"], "\xc1" => [18, "\x9e0"], "\xc2" => [77, "\x9e1"], "\xc3" => [18, "\x9e1"], "\xc4" => [77, "\x9e2"], "\xc5" => [18, "\x9e2"], "\xc6" => [77, "\x9ea"], "\xc7" => [18, "\x9ea"], "\xc8" => [77, "\x9ec"], "\xc9" => [18, "\x9ec"], "\xca" => [77, "\x9ee"], "\xcb" => [18, "\x9ee"], "\xcc" => [77, "\x9ei"], "\xcd" => [18, "\x9ei"], "\xce" => [77, "\x9eo"], "\xcf" => [18, "\x9eo"], "\xd0" => [77, "\x9es"], "\xd1" => [18, "\x9es"], "\xd2" => [77, "\x9et"], "\xd3" => [18, "\x9et"], "\xd4" => [0, "\x9e "], "\xd5" => [0, "\x9e%"], "\xd6" => [0, "\x9e-"], "\xd7" => [0, "\x9e."], "\xd8" => [0, "\x9e/"], "\xd9" => [0, "\x9e3"], "\xda" => [0, "\x9e4"], "\xdb" => [0, "\x9e5"], "\xdc" => [0, "\x9e6"], "\xdd" => [0, "\x9e7"], "\xde" => [0, "\x9e8"], "\xdf" => [0, "\x9e9"], "\xe0" => [0, "\x9e="], "\xe1" => [0, "\x9eA"], "\xe2" => [0, "\x9e_"], "\xe3" => [0, "\x9eb"], "\xe4" => [0, "\x9ed"], "\xe5" => [0, "\x9ef"], "\xe6" => [0, "\x9eg"], "\xe7" => [0, "\x9eh"], "\xe8" => [0, "\x9el"], "\xe9" => [0, "\x9em"], "\xea" => [0, "\x9en"], "\xeb" => [0, "\x9ep"], "\xec" => [0, "\x9er"], "\xed" => [0, "\x9eu"], "\xee" => [100, "\x9e"], "\xef" => [110, "\x9e"], "\xf0" => [111, "\x9e"], "\xf1" => [115, "\x9e"], "\xf2" => [116, "\x9e"], "\xf3" => [118, "\x9e"], "\xf4" => [119, "\x9e"], "\xf5" => [122, "\x9e"], "\xf6" => [123, "\x9e"], "\xf7" => [125, "\x9e"], "\xf8" => [126, "\x9e"], "\xf9" => [129, "\x9e"], "\xfa" => [143, "\x9e"], "\xfb" => [148, "\x9e"], "\xfc" => [151, "\x9e"], "\xfd" => [153, "\x9e"], "\xfe" => [83, "\x9e"], "\xff" => [10, "\x9e"]], ["\x00" => [94, "\x990"], "\x01" => [76, "\x990"], "\x02" => [104, "\x990"], "\x03" => [16, "\x990"], "\x04" => [94, "\x991"], "\x05" => [76, "\x991"], "\x06" => [104, "\x991"], "\x07" => [16, "\x991"], "\x08" => [94, "\x992"], "\t" => [76, "\x992"], "\n" => [104, "\x992"], "\v" => [16, "\x992"], "\f" => [94, "\x99a"], "\r" => [76, "\x99a"], "\x0e" => [104, "\x99a"], "\x0f" => [16, "\x99a"], "\x10" => [94, "\x99c"], "\x11" => [76, "\x99c"], "\x12" => [104, "\x99c"], "\x13" => [16, "\x99c"], "\x14" => [94, "\x99e"], "\x15" => [76, "\x99e"], "\x16" => [104, "\x99e"], "\x17" => [16, "\x99e"], "\x18" => [94, "\x99i"], "\x19" => [76, "\x99i"], "\x1a" => [104, "\x99i"], "\x1b" => [16, "\x99i"], "\x1c" => [94, "\x99o"], "\x1d" => [76, "\x99o"], "\x1e" => [104, "\x99o"], "\x1f" => [16, "\x99o"], " " => [94, "\x99s"], "!" => [76, "\x99s"], "\"" => [104, "\x99s"], "#" => [16, "\x99s"], "\$" => [94, "\x99t"], "%" => [76, "\x99t"], "&" => [104, "\x99t"], "'" => [16, "\x99t"], "(" => [77, "\x99 "], ")" => [18, "\x99 "], "*" => [77, "\x99%"], "+" => [18, "\x99%"], "," => [77, "\x99-"], "-" => [18, "\x99-"], "." => [77, "\x99."], "/" => [18, "\x99."], [77, "\x99/"], [18, "\x99/"], [77, "\x993"], [18, "\x993"], [77, "\x994"], [18, "\x994"], [77, "\x995"], [18, "\x995"], [77, "\x996"], [18, "\x996"], ":" => [77, "\x997"], ";" => [18, "\x997"], "<" => [77, "\x998"], "=" => [18, "\x998"], ">" => [77, "\x999"], "?" => [18, "\x999"], "@" => [77, "\x99="], "A" => [18, "\x99="], "B" => [77, "\x99A"], "C" => [18, "\x99A"], "D" => [77, "\x99_"], "E" => [18, "\x99_"], "F" => [77, "\x99b"], "G" => [18, "\x99b"], "H" => [77, "\x99d"], "I" => [18, "\x99d"], "J" => [77, "\x99f"], "K" => [18, "\x99f"], "L" => [77, "\x99g"], "M" => [18, "\x99g"], "N" => [77, "\x99h"], "O" => [18, "\x99h"], "P" => [77, "\x99l"], "Q" => [18, "\x99l"], "R" => [77, "\x99m"], "S" => [18, "\x99m"], "T" => [77, "\x99n"], "U" => [18, "\x99n"], "V" => [77, "\x99p"], "W" => [18, "\x99p"], "X" => [77, "\x99r"], "Y" => [18, "\x99r"], "Z" => [77, "\x99u"], "[" => [18, "\x99u"], "\\" => [0, "\x99:"], "]" => [0, "\x99B"], "^" => [0, "\x99C"], "_" => [0, "\x99D"], "`" => [0, "\x99E"], "a" => [0, "\x99F"], "b" => [0, "\x99G"], "c" => [0, "\x99H"], "d" => [0, "\x99I"], "e" => [0, "\x99J"], "f" => [0, "\x99K"], "g" => [0, "\x99L"], "h" => [0, "\x99M"], "i" => [0, "\x99N"], "j" => [0, "\x99O"], "k" => [0, "\x99P"], "l" => [0, "\x99Q"], "m" => [0, "\x99R"], "n" => [0, "\x99S"], "o" => [0, "\x99T"], "p" => [0, "\x99U"], "q" => [0, "\x99V"], "r" => [0, "\x99W"], "s" => [0, "\x99Y"], "t" => [0, "\x99j"], "u" => [0, "\x99k"], "v" => [0, "\x99q"], "w" => [0, "\x99v"], "x" => [0, "\x99w"], "y" => [0, "\x99x"], "z" => [0, "\x99y"], "{" => [0, "\x99z"], "|" => [82, "\x99"], "}" => [87, "\x99"], "~" => [130, "\x99"], "" => [9, "\x99"], "\x80" => [94, "\xa10"], "\x81" => [76, "\xa10"], "\x82" => [104, "\xa10"], "\x83" => [16, "\xa10"], "\x84" => [94, "\xa11"], "\x85" => [76, "\xa11"], "\x86" => [104, "\xa11"], "\x87" => [16, "\xa11"], "\x88" => [94, "\xa12"], "\x89" => [76, "\xa12"], "\x8a" => [104, "\xa12"], "\x8b" => [16, "\xa12"], "\x8c" => [94, "\xa1a"], "\x8d" => [76, "\xa1a"], "\x8e" => [104, "\xa1a"], "\x8f" => [16, "\xa1a"], "\x90" => [94, "\xa1c"], "\x91" => [76, "\xa1c"], "\x92" => [104, "\xa1c"], "\x93" => [16, "\xa1c"], "\x94" => [94, "\xa1e"], "\x95" => [76, "\xa1e"], "\x96" => [104, "\xa1e"], "\x97" => [16, "\xa1e"], "\x98" => [94, "\xa1i"], "\x99" => [76, "\xa1i"], "\x9a" => [104, "\xa1i"], "\x9b" => [16, "\xa1i"], "\x9c" => [94, "\xa1o"], "\x9d" => [76, "\xa1o"], "\x9e" => [104, "\xa1o"], "\x9f" => [16, "\xa1o"], "\xa0" => [94, "\xa1s"], "\xa1" => [76, "\xa1s"], "\xa2" => [104, "\xa1s"], "\xa3" => [16, "\xa1s"], "\xa4" => [94, "\xa1t"], "\xa5" => [76, "\xa1t"], "\xa6" => [104, "\xa1t"], "\xa7" => [16, "\xa1t"], "\xa8" => [77, "\xa1 "], "\xa9" => [18, "\xa1 "], "\xaa" => [77, "\xa1%"], "\xab" => [18, "\xa1%"], "\xac" => [77, "\xa1-"], "\xad" => [18, "\xa1-"], "\xae" => [77, "\xa1."], "\xaf" => [18, "\xa1."], "\xb0" => [77, "\xa1/"], "\xb1" => [18, "\xa1/"], "\xb2" => [77, "\xa13"], "\xb3" => [18, "\xa13"], "\xb4" => [77, "\xa14"], "\xb5" => [18, "\xa14"], "\xb6" => [77, "\xa15"], "\xb7" => [18, "\xa15"], "\xb8" => [77, "\xa16"], "\xb9" => [18, "\xa16"], "\xba" => [77, "\xa17"], "\xbb" => [18, "\xa17"], "\xbc" => [77, "\xa18"], "\xbd" => [18, "\xa18"], "\xbe" => [77, "\xa19"], "\xbf" => [18, "\xa19"], "\xc0" => [77, "\xa1="], "\xc1" => [18, "\xa1="], "\xc2" => [77, "\xa1A"], "\xc3" => [18, "\xa1A"], "\xc4" => [77, "\xa1_"], "\xc5" => [18, "\xa1_"], "\xc6" => [77, "\xa1b"], "\xc7" => [18, "\xa1b"], "\xc8" => [77, "\xa1d"], "\xc9" => [18, "\xa1d"], "\xca" => [77, "\xa1f"], "\xcb" => [18, "\xa1f"], "\xcc" => [77, "\xa1g"], "\xcd" => [18, "\xa1g"], "\xce" => [77, "\xa1h"], "\xcf" => [18, "\xa1h"], "\xd0" => [77, "\xa1l"], "\xd1" => [18, "\xa1l"], "\xd2" => [77, "\xa1m"], "\xd3" => [18, "\xa1m"], "\xd4" => [77, "\xa1n"], "\xd5" => [18, "\xa1n"], "\xd6" => [77, "\xa1p"], "\xd7" => [18, "\xa1p"], "\xd8" => [77, "\xa1r"], "\xd9" => [18, "\xa1r"], "\xda" => [77, "\xa1u"], "\xdb" => [18, "\xa1u"], "\xdc" => [0, "\xa1:"], "\xdd" => [0, "\xa1B"], "\xde" => [0, "\xa1C"], "\xdf" => [0, "\xa1D"], "\xe0" => [0, "\xa1E"], "\xe1" => [0, "\xa1F"], "\xe2" => [0, "\xa1G"], "\xe3" => [0, "\xa1H"], "\xe4" => [0, "\xa1I"], "\xe5" => [0, "\xa1J"], "\xe6" => [0, "\xa1K"], "\xe7" => [0, "\xa1L"], "\xe8" => [0, "\xa1M"], "\xe9" => [0, "\xa1N"], "\xea" => [0, "\xa1O"], "\xeb" => [0, "\xa1P"], "\xec" => [0, "\xa1Q"], "\xed" => [0, "\xa1R"], "\xee" => [0, "\xa1S"], "\xef" => [0, "\xa1T"], "\xf0" => [0, "\xa1U"], "\xf1" => [0, "\xa1V"], "\xf2" => [0, "\xa1W"], "\xf3" => [0, "\xa1Y"], "\xf4" => [0, "\xa1j"], "\xf5" => [0, "\xa1k"], "\xf6" => [0, "\xa1q"], "\xf7" => [0, "\xa1v"], "\xf8" => [0, "\xa1w"], "\xf9" => [0, "\xa1x"], "\xfa" => [0, "\xa1y"], "\xfb" => [0, "\xa1z"], "\xfc" => [82, "\xa1"], "\xfd" => [87, "\xa1"], "\xfe" => [130, "\xa1"], "\xff" => [9, "\xa1"]], ["\x00" => [77, "\x990"], "\x01" => [18, "\x990"], "\x02" => [77, "\x991"], "\x03" => [18, "\x991"], "\x04" => [77, "\x992"], "\x05" => [18, "\x992"], "\x06" => [77, "\x99a"], "\x07" => [18, "\x99a"], "\x08" => [77, "\x99c"], "\t" => [18, "\x99c"], "\n" => [77, "\x99e"], "\v" => [18, "\x99e"], "\f" => [77, "\x99i"], "\r" => [18, "\x99i"], "\x0e" => [77, "\x99o"], "\x0f" => [18, "\x99o"], "\x10" => [77, "\x99s"], "\x11" => [18, "\x99s"], "\x12" => [77, "\x99t"], "\x13" => [18, "\x99t"], "\x14" => [0, "\x99 "], "\x15" => [0, "\x99%"], "\x16" => [0, "\x99-"], "\x17" => [0, "\x99."], "\x18" => [0, "\x99/"], "\x19" => [0, "\x993"], "\x1a" => [0, "\x994"], "\x1b" => [0, "\x995"], "\x1c" => [0, "\x996"], "\x1d" => [0, "\x997"], "\x1e" => [0, "\x998"], "\x1f" => [0, "\x999"], " " => [0, "\x99="], "!" => [0, "\x99A"], "\"" => [0, "\x99_"], "#" => [0, "\x99b"], "\$" => [0, "\x99d"], "%" => [0, "\x99f"], "&" => [0, "\x99g"], "'" => [0, "\x99h"], "(" => [0, "\x99l"], ")" => [0, "\x99m"], "*" => [0, "\x99n"], "+" => [0, "\x99p"], "," => [0, "\x99r"], "-" => [0, "\x99u"], "." => [100, "\x99"], "/" => [110, "\x99"], [111, "\x99"], [115, "\x99"], [116, "\x99"], [118, "\x99"], [119, "\x99"], [122, "\x99"], [123, "\x99"], [125, "\x99"], [126, "\x99"], [129, "\x99"], ":" => [143, "\x99"], ";" => [148, "\x99"], "<" => [151, "\x99"], "=" => [153, "\x99"], ">" => [83, "\x99"], "?" => [10, "\x99"], "@" => [77, "\xa10"], "A" => [18, "\xa10"], "B" => [77, "\xa11"], "C" => [18, "\xa11"], "D" => [77, "\xa12"], "E" => [18, "\xa12"], "F" => [77, "\xa1a"], "G" => [18, "\xa1a"], "H" => [77, "\xa1c"], "I" => [18, "\xa1c"], "J" => [77, "\xa1e"], "K" => [18, "\xa1e"], "L" => [77, "\xa1i"], "M" => [18, "\xa1i"], "N" => [77, "\xa1o"], "O" => [18, "\xa1o"], "P" => [77, "\xa1s"], "Q" => [18, "\xa1s"], "R" => [77, "\xa1t"], "S" => [18, "\xa1t"], "T" => [0, "\xa1 "], "U" => [0, "\xa1%"], "V" => [0, "\xa1-"], "W" => [0, "\xa1."], "X" => [0, "\xa1/"], "Y" => [0, "\xa13"], "Z" => [0, "\xa14"], "[" => [0, "\xa15"], "\\" => [0, "\xa16"], "]" => [0, "\xa17"], "^" => [0, "\xa18"], "_" => [0, "\xa19"], "`" => [0, "\xa1="], "a" => [0, "\xa1A"], "b" => [0, "\xa1_"], "c" => [0, "\xa1b"], "d" => [0, "\xa1d"], "e" => [0, "\xa1f"], "f" => [0, "\xa1g"], "g" => [0, "\xa1h"], "h" => [0, "\xa1l"], "i" => [0, "\xa1m"], "j" => [0, "\xa1n"], "k" => [0, "\xa1p"], "l" => [0, "\xa1r"], "m" => [0, "\xa1u"], "n" => [100, "\xa1"], "o" => [110, "\xa1"], "p" => [111, "\xa1"], "q" => [115, "\xa1"], "r" => [116, "\xa1"], "s" => [118, "\xa1"], "t" => [119, "\xa1"], "u" => [122, "\xa1"], "v" => [123, "\xa1"], "w" => [125, "\xa1"], "x" => [126, "\xa1"], "y" => [129, "\xa1"], "z" => [143, "\xa1"], "{" => [148, "\xa1"], "|" => [151, "\xa1"], "}" => [153, "\xa1"], "~" => [83, "\xa1"], "" => [10, "\xa1"], "\x80" => [77, "\xa70"], "\x81" => [18, "\xa70"], "\x82" => [77, "\xa71"], "\x83" => [18, "\xa71"], "\x84" => [77, "\xa72"], "\x85" => [18, "\xa72"], "\x86" => [77, "\xa7a"], "\x87" => [18, "\xa7a"], "\x88" => [77, "\xa7c"], "\x89" => [18, "\xa7c"], "\x8a" => [77, "\xa7e"], "\x8b" => [18, "\xa7e"], "\x8c" => [77, "\xa7i"], "\x8d" => [18, "\xa7i"], "\x8e" => [77, "\xa7o"], "\x8f" => [18, "\xa7o"], "\x90" => [77, "\xa7s"], "\x91" => [18, "\xa7s"], "\x92" => [77, "\xa7t"], "\x93" => [18, "\xa7t"], "\x94" => [0, "\xa7 "], "\x95" => [0, "\xa7%"], "\x96" => [0, "\xa7-"], "\x97" => [0, "\xa7."], "\x98" => [0, "\xa7/"], "\x99" => [0, "\xa73"], "\x9a" => [0, "\xa74"], "\x9b" => [0, "\xa75"], "\x9c" => [0, "\xa76"], "\x9d" => [0, "\xa77"], "\x9e" => [0, "\xa78"], "\x9f" => [0, "\xa79"], "\xa0" => [0, "\xa7="], "\xa1" => [0, "\xa7A"], "\xa2" => [0, "\xa7_"], "\xa3" => [0, "\xa7b"], "\xa4" => [0, "\xa7d"], "\xa5" => [0, "\xa7f"], "\xa6" => [0, "\xa7g"], "\xa7" => [0, "\xa7h"], "\xa8" => [0, "\xa7l"], "\xa9" => [0, "\xa7m"], "\xaa" => [0, "\xa7n"], "\xab" => [0, "\xa7p"], "\xac" => [0, "\xa7r"], "\xad" => [0, "\xa7u"], "\xae" => [100, "\xa7"], "\xaf" => [110, "\xa7"], "\xb0" => [111, "\xa7"], "\xb1" => [115, "\xa7"], "\xb2" => [116, "\xa7"], "\xb3" => [118, "\xa7"], "\xb4" => [119, "\xa7"], "\xb5" => [122, "\xa7"], "\xb6" => [123, "\xa7"], "\xb7" => [125, "\xa7"], "\xb8" => [126, "\xa7"], "\xb9" => [129, "\xa7"], "\xba" => [143, "\xa7"], "\xbb" => [148, "\xa7"], "\xbc" => [151, "\xa7"], "\xbd" => [153, "\xa7"], "\xbe" => [83, "\xa7"], "\xbf" => [10, "\xa7"], "\xc0" => [77, "\xac0"], "\xc1" => [18, "\xac0"], "\xc2" => [77, "\xac1"], "\xc3" => [18, "\xac1"], "\xc4" => [77, "\xac2"], "\xc5" => [18, "\xac2"], "\xc6" => [77, "\xaca"], "\xc7" => [18, "\xaca"], "\xc8" => [77, "\xacc"], "\xc9" => [18, "\xacc"], "\xca" => [77, "\xace"], "\xcb" => [18, "\xace"], "\xcc" => [77, "\xaci"], "\xcd" => [18, "\xaci"], "\xce" => [77, "\xaco"], "\xcf" => [18, "\xaco"], "\xd0" => [77, "\xacs"], "\xd1" => [18, "\xacs"], "\xd2" => [77, "\xact"], "\xd3" => [18, "\xact"], "\xd4" => [0, "\xac "], "\xd5" => [0, "\xac%"], "\xd6" => [0, "\xac-"], "\xd7" => [0, "\xac."], "\xd8" => [0, "\xac/"], "\xd9" => [0, "\xac3"], "\xda" => [0, "\xac4"], "\xdb" => [0, "\xac5"], "\xdc" => [0, "\xac6"], "\xdd" => [0, "\xac7"], "\xde" => [0, "\xac8"], "\xdf" => [0, "\xac9"], "\xe0" => [0, "\xac="], "\xe1" => [0, "\xacA"], "\xe2" => [0, "\xac_"], "\xe3" => [0, "\xacb"], "\xe4" => [0, "\xacd"], "\xe5" => [0, "\xacf"], "\xe6" => [0, "\xacg"], "\xe7" => [0, "\xach"], "\xe8" => [0, "\xacl"], "\xe9" => [0, "\xacm"], "\xea" => [0, "\xacn"], "\xeb" => [0, "\xacp"], "\xec" => [0, "\xacr"], "\xed" => [0, "\xacu"], "\xee" => [100, "\xac"], "\xef" => [110, "\xac"], "\xf0" => [111, "\xac"], "\xf1" => [115, "\xac"], "\xf2" => [116, "\xac"], "\xf3" => [118, "\xac"], "\xf4" => [119, "\xac"], "\xf5" => [122, "\xac"], "\xf6" => [123, "\xac"], "\xf7" => [125, "\xac"], "\xf8" => [126, "\xac"], "\xf9" => [129, "\xac"], "\xfa" => [143, "\xac"], "\xfb" => [148, "\xac"], "\xfc" => [151, "\xac"], "\xfd" => [153, "\xac"], "\xfe" => [83, "\xac"], "\xff" => [10, "\xac"]], ["\x00" => [77, "\xe00"], "\x01" => [18, "\xe00"], "\x02" => [77, "\xe01"], "\x03" => [18, "\xe01"], "\x04" => [77, "\xe02"], "\x05" => [18, "\xe02"], "\x06" => [77, "\xe0a"], "\x07" => [18, "\xe0a"], "\x08" => [77, "\xe0c"], "\t" => [18, "\xe0c"], "\n" => [77, "\xe0e"], "\v" => [18, "\xe0e"], "\f" => [77, "\xe0i"], "\r" => [18, "\xe0i"], "\x0e" => [77, "\xe0o"], "\x0f" => [18, "\xe0o"], "\x10" => [77, "\xe0s"], "\x11" => [18, "\xe0s"], "\x12" => [77, "\xe0t"], "\x13" => [18, "\xe0t"], "\x14" => [0, "\xe0 "], "\x15" => [0, "\xe0%"], "\x16" => [0, "\xe0-"], "\x17" => [0, "\xe0."], "\x18" => [0, "\xe0/"], "\x19" => [0, "\xe03"], "\x1a" => [0, "\xe04"], "\x1b" => [0, "\xe05"], "\x1c" => [0, "\xe06"], "\x1d" => [0, "\xe07"], "\x1e" => [0, "\xe08"], "\x1f" => [0, "\xe09"], " " => [0, "\xe0="], "!" => [0, "\xe0A"], "\"" => [0, "\xe0_"], "#" => [0, "\xe0b"], "\$" => [0, "\xe0d"], "%" => [0, "\xe0f"], "&" => [0, "\xe0g"], "'" => [0, "\xe0h"], "(" => [0, "\xe0l"], ")" => [0, "\xe0m"], "*" => [0, "\xe0n"], "+" => [0, "\xe0p"], "," => [0, "\xe0r"], "-" => [0, "\xe0u"], "." => [100, "\xe0"], "/" => [110, "\xe0"], [111, "\xe0"], [115, "\xe0"], [116, "\xe0"], [118, "\xe0"], [119, "\xe0"], [122, "\xe0"], [123, "\xe0"], [125, "\xe0"], [126, "\xe0"], [129, "\xe0"], ":" => [143, "\xe0"], ";" => [148, "\xe0"], "<" => [151, "\xe0"], "=" => [153, "\xe0"], ">" => [83, "\xe0"], "?" => [10, "\xe0"], "@" => [77, "\xe20"], "A" => [18, "\xe20"], "B" => [77, "\xe21"], "C" => [18, "\xe21"], "D" => [77, "\xe22"], "E" => [18, "\xe22"], "F" => [77, "\xe2a"], "G" => [18, "\xe2a"], "H" => [77, "\xe2c"], "I" => [18, "\xe2c"], "J" => [77, "\xe2e"], "K" => [18, "\xe2e"], "L" => [77, "\xe2i"], "M" => [18, "\xe2i"], "N" => [77, "\xe2o"], "O" => [18, "\xe2o"], "P" => [77, "\xe2s"], "Q" => [18, "\xe2s"], "R" => [77, "\xe2t"], "S" => [18, "\xe2t"], "T" => [0, "\xe2 "], "U" => [0, "\xe2%"], "V" => [0, "\xe2-"], "W" => [0, "\xe2."], "X" => [0, "\xe2/"], "Y" => [0, "\xe23"], "Z" => [0, "\xe24"], "[" => [0, "\xe25"], "\\" => [0, "\xe26"], "]" => [0, "\xe27"], "^" => [0, "\xe28"], "_" => [0, "\xe29"], "`" => [0, "\xe2="], "a" => [0, "\xe2A"], "b" => [0, "\xe2_"], "c" => [0, "\xe2b"], "d" => [0, "\xe2d"], "e" => [0, "\xe2f"], "f" => [0, "\xe2g"], "g" => [0, "\xe2h"], "h" => [0, "\xe2l"], "i" => [0, "\xe2m"], "j" => [0, "\xe2n"], "k" => [0, "\xe2p"], "l" => [0, "\xe2r"], "m" => [0, "\xe2u"], "n" => [100, "\xe2"], "o" => [110, "\xe2"], "p" => [111, "\xe2"], "q" => [115, "\xe2"], "r" => [116, "\xe2"], "s" => [118, "\xe2"], "t" => [119, "\xe2"], "u" => [122, "\xe2"], "v" => [123, "\xe2"], "w" => [125, "\xe2"], "x" => [126, "\xe2"], "y" => [129, "\xe2"], "z" => [143, "\xe2"], "{" => [148, "\xe2"], "|" => [151, "\xe2"], "}" => [153, "\xe2"], "~" => [83, "\xe2"], "" => [10, "\xe2"], "\x80" => [0, "\x990"], "\x81" => [0, "\x991"], "\x82" => [0, "\x992"], "\x83" => [0, "\x99a"], "\x84" => [0, "\x99c"], "\x85" => [0, "\x99e"], "\x86" => [0, "\x99i"], "\x87" => [0, "\x99o"], "\x88" => [0, "\x99s"], "\x89" => [0, "\x99t"], "\x8a" => [73, "\x99"], "\x8b" => [88, "\x99"], "\x8c" => [89, "\x99"], "\x8d" => [96, "\x99"], "\x8e" => [97, "\x99"], "\x8f" => [99, "\x99"], "\x90" => [106, "\x99"], "\x91" => [136, "\x99"], "\x92" => [139, "\x99"], "\x93" => [141, "\x99"], "\x94" => [145, "\x99"], "\x95" => [147, "\x99"], "\x96" => [149, "\x99"], "\x97" => [101, "\x99"], "\x98" => [112, "\x99"], "\x99" => [117, "\x99"], "\x9a" => [120, "\x99"], "\x9b" => [124, "\x99"], "\x9c" => [127, "\x99"], "\x9d" => [144, "\x99"], "\x9e" => [152, "\x99"], "\x9f" => [11, "\x99"], "\xa0" => [0, "\xa10"], "\xa1" => [0, "\xa11"], "\xa2" => [0, "\xa12"], "\xa3" => [0, "\xa1a"], "\xa4" => [0, "\xa1c"], "\xa5" => [0, "\xa1e"], "\xa6" => [0, "\xa1i"], "\xa7" => [0, "\xa1o"], "\xa8" => [0, "\xa1s"], "\xa9" => [0, "\xa1t"], "\xaa" => [73, "\xa1"], "\xab" => [88, "\xa1"], "\xac" => [89, "\xa1"], "\xad" => [96, "\xa1"], "\xae" => [97, "\xa1"], "\xaf" => [99, "\xa1"], "\xb0" => [106, "\xa1"], "\xb1" => [136, "\xa1"], "\xb2" => [139, "\xa1"], "\xb3" => [141, "\xa1"], "\xb4" => [145, "\xa1"], "\xb5" => [147, "\xa1"], "\xb6" => [149, "\xa1"], "\xb7" => [101, "\xa1"], "\xb8" => [112, "\xa1"], "\xb9" => [117, "\xa1"], "\xba" => [120, "\xa1"], "\xbb" => [124, "\xa1"], "\xbc" => [127, "\xa1"], "\xbd" => [144, "\xa1"], "\xbe" => [152, "\xa1"], "\xbf" => [11, "\xa1"], "\xc0" => [0, "\xa70"], "\xc1" => [0, "\xa71"], "\xc2" => [0, "\xa72"], "\xc3" => [0, "\xa7a"], "\xc4" => [0, "\xa7c"], "\xc5" => [0, "\xa7e"], "\xc6" => [0, "\xa7i"], "\xc7" => [0, "\xa7o"], "\xc8" => [0, "\xa7s"], "\xc9" => [0, "\xa7t"], "\xca" => [73, "\xa7"], "\xcb" => [88, "\xa7"], "\xcc" => [89, "\xa7"], "\xcd" => [96, "\xa7"], "\xce" => [97, "\xa7"], "\xcf" => [99, "\xa7"], "\xd0" => [106, "\xa7"], "\xd1" => [136, "\xa7"], "\xd2" => [139, "\xa7"], "\xd3" => [141, "\xa7"], "\xd4" => [145, "\xa7"], "\xd5" => [147, "\xa7"], "\xd6" => [149, "\xa7"], "\xd7" => [101, "\xa7"], "\xd8" => [112, "\xa7"], "\xd9" => [117, "\xa7"], "\xda" => [120, "\xa7"], "\xdb" => [124, "\xa7"], "\xdc" => [127, "\xa7"], "\xdd" => [144, "\xa7"], "\xde" => [152, "\xa7"], "\xdf" => [11, "\xa7"], "\xe0" => [0, "\xac0"], "\xe1" => [0, "\xac1"], "\xe2" => [0, "\xac2"], "\xe3" => [0, "\xaca"], "\xe4" => [0, "\xacc"], "\xe5" => [0, "\xace"], "\xe6" => [0, "\xaci"], "\xe7" => [0, "\xaco"], "\xe8" => [0, "\xacs"], "\xe9" => [0, "\xact"], "\xea" => [73, "\xac"], "\xeb" => [88, "\xac"], "\xec" => [89, "\xac"], "\xed" => [96, "\xac"], "\xee" => [97, "\xac"], "\xef" => [99, "\xac"], "\xf0" => [106, "\xac"], "\xf1" => [136, "\xac"], "\xf2" => [139, "\xac"], "\xf3" => [141, "\xac"], "\xf4" => [145, "\xac"], "\xf5" => [147, "\xac"], "\xf6" => [149, "\xac"], "\xf7" => [101, "\xac"], "\xf8" => [112, "\xac"], "\xf9" => [117, "\xac"], "\xfa" => [120, "\xac"], "\xfb" => [124, "\xac"], "\xfc" => [127, "\xac"], "\xfd" => [144, "\xac"], "\xfe" => [152, "\xac"], "\xff" => [11, "\xac"]], ["\x00" => [94, "\x9a0"], "\x01" => [76, "\x9a0"], "\x02" => [104, "\x9a0"], "\x03" => [16, "\x9a0"], "\x04" => [94, "\x9a1"], "\x05" => [76, "\x9a1"], "\x06" => [104, "\x9a1"], "\x07" => [16, "\x9a1"], "\x08" => [94, "\x9a2"], "\t" => [76, "\x9a2"], "\n" => [104, "\x9a2"], "\v" => [16, "\x9a2"], "\f" => [94, "\x9aa"], "\r" => [76, "\x9aa"], "\x0e" => [104, "\x9aa"], "\x0f" => [16, "\x9aa"], "\x10" => [94, "\x9ac"], "\x11" => [76, "\x9ac"], "\x12" => [104, "\x9ac"], "\x13" => [16, "\x9ac"], "\x14" => [94, "\x9ae"], "\x15" => [76, "\x9ae"], "\x16" => [104, "\x9ae"], "\x17" => [16, "\x9ae"], "\x18" => [94, "\x9ai"], "\x19" => [76, "\x9ai"], "\x1a" => [104, "\x9ai"], "\x1b" => [16, "\x9ai"], "\x1c" => [94, "\x9ao"], "\x1d" => [76, "\x9ao"], "\x1e" => [104, "\x9ao"], "\x1f" => [16, "\x9ao"], " " => [94, "\x9as"], "!" => [76, "\x9as"], "\"" => [104, "\x9as"], "#" => [16, "\x9as"], "\$" => [94, "\x9at"], "%" => [76, "\x9at"], "&" => [104, "\x9at"], "'" => [16, "\x9at"], "(" => [77, "\x9a "], ")" => [18, "\x9a "], "*" => [77, "\x9a%"], "+" => [18, "\x9a%"], "," => [77, "\x9a-"], "-" => [18, "\x9a-"], "." => [77, "\x9a."], "/" => [18, "\x9a."], [77, "\x9a/"], [18, "\x9a/"], [77, "\x9a3"], [18, "\x9a3"], [77, "\x9a4"], [18, "\x9a4"], [77, "\x9a5"], [18, "\x9a5"], [77, "\x9a6"], [18, "\x9a6"], ":" => [77, "\x9a7"], ";" => [18, "\x9a7"], "<" => [77, "\x9a8"], "=" => [18, "\x9a8"], ">" => [77, "\x9a9"], "?" => [18, "\x9a9"], "@" => [77, "\x9a="], "A" => [18, "\x9a="], "B" => [77, "\x9aA"], "C" => [18, "\x9aA"], "D" => [77, "\x9a_"], "E" => [18, "\x9a_"], "F" => [77, "\x9ab"], "G" => [18, "\x9ab"], "H" => [77, "\x9ad"], "I" => [18, "\x9ad"], "J" => [77, "\x9af"], "K" => [18, "\x9af"], "L" => [77, "\x9ag"], "M" => [18, "\x9ag"], "N" => [77, "\x9ah"], "O" => [18, "\x9ah"], "P" => [77, "\x9al"], "Q" => [18, "\x9al"], "R" => [77, "\x9am"], "S" => [18, "\x9am"], "T" => [77, "\x9an"], "U" => [18, "\x9an"], "V" => [77, "\x9ap"], "W" => [18, "\x9ap"], "X" => [77, "\x9ar"], "Y" => [18, "\x9ar"], "Z" => [77, "\x9au"], "[" => [18, "\x9au"], "\\" => [0, "\x9a:"], "]" => [0, "\x9aB"], "^" => [0, "\x9aC"], "_" => [0, "\x9aD"], "`" => [0, "\x9aE"], "a" => [0, "\x9aF"], "b" => [0, "\x9aG"], "c" => [0, "\x9aH"], "d" => [0, "\x9aI"], "e" => [0, "\x9aJ"], "f" => [0, "\x9aK"], "g" => [0, "\x9aL"], "h" => [0, "\x9aM"], "i" => [0, "\x9aN"], "j" => [0, "\x9aO"], "k" => [0, "\x9aP"], "l" => [0, "\x9aQ"], "m" => [0, "\x9aR"], "n" => [0, "\x9aS"], "o" => [0, "\x9aT"], "p" => [0, "\x9aU"], "q" => [0, "\x9aV"], "r" => [0, "\x9aW"], "s" => [0, "\x9aY"], "t" => [0, "\x9aj"], "u" => [0, "\x9ak"], "v" => [0, "\x9aq"], "w" => [0, "\x9av"], "x" => [0, "\x9aw"], "y" => [0, "\x9ax"], "z" => [0, "\x9ay"], "{" => [0, "\x9az"], "|" => [82, "\x9a"], "}" => [87, "\x9a"], "~" => [130, "\x9a"], "" => [9, "\x9a"], "\x80" => [94, "\x9c0"], "\x81" => [76, "\x9c0"], "\x82" => [104, "\x9c0"], "\x83" => [16, "\x9c0"], "\x84" => [94, "\x9c1"], "\x85" => [76, "\x9c1"], "\x86" => [104, "\x9c1"], "\x87" => [16, "\x9c1"], "\x88" => [94, "\x9c2"], "\x89" => [76, "\x9c2"], "\x8a" => [104, "\x9c2"], "\x8b" => [16, "\x9c2"], "\x8c" => [94, "\x9ca"], "\x8d" => [76, "\x9ca"], "\x8e" => [104, "\x9ca"], "\x8f" => [16, "\x9ca"], "\x90" => [94, "\x9cc"], "\x91" => [76, "\x9cc"], "\x92" => [104, "\x9cc"], "\x93" => [16, "\x9cc"], "\x94" => [94, "\x9ce"], "\x95" => [76, "\x9ce"], "\x96" => [104, "\x9ce"], "\x97" => [16, "\x9ce"], "\x98" => [94, "\x9ci"], "\x99" => [76, "\x9ci"], "\x9a" => [104, "\x9ci"], "\x9b" => [16, "\x9ci"], "\x9c" => [94, "\x9co"], "\x9d" => [76, "\x9co"], "\x9e" => [104, "\x9co"], "\x9f" => [16, "\x9co"], "\xa0" => [94, "\x9cs"], "\xa1" => [76, "\x9cs"], "\xa2" => [104, "\x9cs"], "\xa3" => [16, "\x9cs"], "\xa4" => [94, "\x9ct"], "\xa5" => [76, "\x9ct"], "\xa6" => [104, "\x9ct"], "\xa7" => [16, "\x9ct"], "\xa8" => [77, "\x9c "], "\xa9" => [18, "\x9c "], "\xaa" => [77, "\x9c%"], "\xab" => [18, "\x9c%"], "\xac" => [77, "\x9c-"], "\xad" => [18, "\x9c-"], "\xae" => [77, "\x9c."], "\xaf" => [18, "\x9c."], "\xb0" => [77, "\x9c/"], "\xb1" => [18, "\x9c/"], "\xb2" => [77, "\x9c3"], "\xb3" => [18, "\x9c3"], "\xb4" => [77, "\x9c4"], "\xb5" => [18, "\x9c4"], "\xb6" => [77, "\x9c5"], "\xb7" => [18, "\x9c5"], "\xb8" => [77, "\x9c6"], "\xb9" => [18, "\x9c6"], "\xba" => [77, "\x9c7"], "\xbb" => [18, "\x9c7"], "\xbc" => [77, "\x9c8"], "\xbd" => [18, "\x9c8"], "\xbe" => [77, "\x9c9"], "\xbf" => [18, "\x9c9"], "\xc0" => [77, "\x9c="], "\xc1" => [18, "\x9c="], "\xc2" => [77, "\x9cA"], "\xc3" => [18, "\x9cA"], "\xc4" => [77, "\x9c_"], "\xc5" => [18, "\x9c_"], "\xc6" => [77, "\x9cb"], "\xc7" => [18, "\x9cb"], "\xc8" => [77, "\x9cd"], "\xc9" => [18, "\x9cd"], "\xca" => [77, "\x9cf"], "\xcb" => [18, "\x9cf"], "\xcc" => [77, "\x9cg"], "\xcd" => [18, "\x9cg"], "\xce" => [77, "\x9ch"], "\xcf" => [18, "\x9ch"], "\xd0" => [77, "\x9cl"], "\xd1" => [18, "\x9cl"], "\xd2" => [77, "\x9cm"], "\xd3" => [18, "\x9cm"], "\xd4" => [77, "\x9cn"], "\xd5" => [18, "\x9cn"], "\xd6" => [77, "\x9cp"], "\xd7" => [18, "\x9cp"], "\xd8" => [77, "\x9cr"], "\xd9" => [18, "\x9cr"], "\xda" => [77, "\x9cu"], "\xdb" => [18, "\x9cu"], "\xdc" => [0, "\x9c:"], "\xdd" => [0, "\x9cB"], "\xde" => [0, "\x9cC"], "\xdf" => [0, "\x9cD"], "\xe0" => [0, "\x9cE"], "\xe1" => [0, "\x9cF"], "\xe2" => [0, "\x9cG"], "\xe3" => [0, "\x9cH"], "\xe4" => [0, "\x9cI"], "\xe5" => [0, "\x9cJ"], "\xe6" => [0, "\x9cK"], "\xe7" => [0, "\x9cL"], "\xe8" => [0, "\x9cM"], "\xe9" => [0, "\x9cN"], "\xea" => [0, "\x9cO"], "\xeb" => [0, "\x9cP"], "\xec" => [0, "\x9cQ"], "\xed" => [0, "\x9cR"], "\xee" => [0, "\x9cS"], "\xef" => [0, "\x9cT"], "\xf0" => [0, "\x9cU"], "\xf1" => [0, "\x9cV"], "\xf2" => [0, "\x9cW"], "\xf3" => [0, "\x9cY"], "\xf4" => [0, "\x9cj"], "\xf5" => [0, "\x9ck"], "\xf6" => [0, "\x9cq"], "\xf7" => [0, "\x9cv"], "\xf8" => [0, "\x9cw"], "\xf9" => [0, "\x9cx"], "\xfa" => [0, "\x9cy"], "\xfb" => [0, "\x9cz"], "\xfc" => [82, "\x9c"], "\xfd" => [87, "\x9c"], "\xfe" => [130, "\x9c"], "\xff" => [9, "\x9c"]], ["\x00" => [77, "\x9a0"], "\x01" => [18, "\x9a0"], "\x02" => [77, "\x9a1"], "\x03" => [18, "\x9a1"], "\x04" => [77, "\x9a2"], "\x05" => [18, "\x9a2"], "\x06" => [77, "\x9aa"], "\x07" => [18, "\x9aa"], "\x08" => [77, "\x9ac"], "\t" => [18, "\x9ac"], "\n" => [77, "\x9ae"], "\v" => [18, "\x9ae"], "\f" => [77, "\x9ai"], "\r" => [18, "\x9ai"], "\x0e" => [77, "\x9ao"], "\x0f" => [18, "\x9ao"], "\x10" => [77, "\x9as"], "\x11" => [18, "\x9as"], "\x12" => [77, "\x9at"], "\x13" => [18, "\x9at"], "\x14" => [0, "\x9a "], "\x15" => [0, "\x9a%"], "\x16" => [0, "\x9a-"], "\x17" => [0, "\x9a."], "\x18" => [0, "\x9a/"], "\x19" => [0, "\x9a3"], "\x1a" => [0, "\x9a4"], "\x1b" => [0, "\x9a5"], "\x1c" => [0, "\x9a6"], "\x1d" => [0, "\x9a7"], "\x1e" => [0, "\x9a8"], "\x1f" => [0, "\x9a9"], " " => [0, "\x9a="], "!" => [0, "\x9aA"], "\"" => [0, "\x9a_"], "#" => [0, "\x9ab"], "\$" => [0, "\x9ad"], "%" => [0, "\x9af"], "&" => [0, "\x9ag"], "'" => [0, "\x9ah"], "(" => [0, "\x9al"], ")" => [0, "\x9am"], "*" => [0, "\x9an"], "+" => [0, "\x9ap"], "," => [0, "\x9ar"], "-" => [0, "\x9au"], "." => [100, "\x9a"], "/" => [110, "\x9a"], [111, "\x9a"], [115, "\x9a"], [116, "\x9a"], [118, "\x9a"], [119, "\x9a"], [122, "\x9a"], [123, "\x9a"], [125, "\x9a"], [126, "\x9a"], [129, "\x9a"], ":" => [143, "\x9a"], ";" => [148, "\x9a"], "<" => [151, "\x9a"], "=" => [153, "\x9a"], ">" => [83, "\x9a"], "?" => [10, "\x9a"], "@" => [77, "\x9c0"], "A" => [18, "\x9c0"], "B" => [77, "\x9c1"], "C" => [18, "\x9c1"], "D" => [77, "\x9c2"], "E" => [18, "\x9c2"], "F" => [77, "\x9ca"], "G" => [18, "\x9ca"], "H" => [77, "\x9cc"], "I" => [18, "\x9cc"], "J" => [77, "\x9ce"], "K" => [18, "\x9ce"], "L" => [77, "\x9ci"], "M" => [18, "\x9ci"], "N" => [77, "\x9co"], "O" => [18, "\x9co"], "P" => [77, "\x9cs"], "Q" => [18, "\x9cs"], "R" => [77, "\x9ct"], "S" => [18, "\x9ct"], "T" => [0, "\x9c "], "U" => [0, "\x9c%"], "V" => [0, "\x9c-"], "W" => [0, "\x9c."], "X" => [0, "\x9c/"], "Y" => [0, "\x9c3"], "Z" => [0, "\x9c4"], "[" => [0, "\x9c5"], "\\" => [0, "\x9c6"], "]" => [0, "\x9c7"], "^" => [0, "\x9c8"], "_" => [0, "\x9c9"], "`" => [0, "\x9c="], "a" => [0, "\x9cA"], "b" => [0, "\x9c_"], "c" => [0, "\x9cb"], "d" => [0, "\x9cd"], "e" => [0, "\x9cf"], "f" => [0, "\x9cg"], "g" => [0, "\x9ch"], "h" => [0, "\x9cl"], "i" => [0, "\x9cm"], "j" => [0, "\x9cn"], "k" => [0, "\x9cp"], "l" => [0, "\x9cr"], "m" => [0, "\x9cu"], "n" => [100, "\x9c"], "o" => [110, "\x9c"], "p" => [111, "\x9c"], "q" => [115, "\x9c"], "r" => [116, "\x9c"], "s" => [118, "\x9c"], "t" => [119, "\x9c"], "u" => [122, "\x9c"], "v" => [123, "\x9c"], "w" => [125, "\x9c"], "x" => [126, "\x9c"], "y" => [129, "\x9c"], "z" => [143, "\x9c"], "{" => [148, "\x9c"], "|" => [151, "\x9c"], "}" => [153, "\x9c"], "~" => [83, "\x9c"], "" => [10, "\x9c"], "\x80" => [77, "\xa00"], "\x81" => [18, "\xa00"], "\x82" => [77, "\xa01"], "\x83" => [18, "\xa01"], "\x84" => [77, "\xa02"], "\x85" => [18, "\xa02"], "\x86" => [77, "\xa0a"], "\x87" => [18, "\xa0a"], "\x88" => [77, "\xa0c"], "\x89" => [18, "\xa0c"], "\x8a" => [77, "\xa0e"], "\x8b" => [18, "\xa0e"], "\x8c" => [77, "\xa0i"], "\x8d" => [18, "\xa0i"], "\x8e" => [77, "\xa0o"], "\x8f" => [18, "\xa0o"], "\x90" => [77, "\xa0s"], "\x91" => [18, "\xa0s"], "\x92" => [77, "\xa0t"], "\x93" => [18, "\xa0t"], "\x94" => [0, "\xa0 "], "\x95" => [0, "\xa0%"], "\x96" => [0, "\xa0-"], "\x97" => [0, "\xa0."], "\x98" => [0, "\xa0/"], "\x99" => [0, "\xa03"], "\x9a" => [0, "\xa04"], "\x9b" => [0, "\xa05"], "\x9c" => [0, "\xa06"], "\x9d" => [0, "\xa07"], "\x9e" => [0, "\xa08"], "\x9f" => [0, "\xa09"], "\xa0" => [0, "\xa0="], "\xa1" => [0, "\xa0A"], "\xa2" => [0, "\xa0_"], "\xa3" => [0, "\xa0b"], "\xa4" => [0, "\xa0d"], "\xa5" => [0, "\xa0f"], "\xa6" => [0, "\xa0g"], "\xa7" => [0, "\xa0h"], "\xa8" => [0, "\xa0l"], "\xa9" => [0, "\xa0m"], "\xaa" => [0, "\xa0n"], "\xab" => [0, "\xa0p"], "\xac" => [0, "\xa0r"], "\xad" => [0, "\xa0u"], "\xae" => [100, "\xa0"], "\xaf" => [110, "\xa0"], "\xb0" => [111, "\xa0"], "\xb1" => [115, "\xa0"], "\xb2" => [116, "\xa0"], "\xb3" => [118, "\xa0"], "\xb4" => [119, "\xa0"], "\xb5" => [122, "\xa0"], "\xb6" => [123, "\xa0"], "\xb7" => [125, "\xa0"], "\xb8" => [126, "\xa0"], "\xb9" => [129, "\xa0"], "\xba" => [143, "\xa0"], "\xbb" => [148, "\xa0"], "\xbc" => [151, "\xa0"], "\xbd" => [153, "\xa0"], "\xbe" => [83, "\xa0"], "\xbf" => [10, "\xa0"], "\xc0" => [77, "\xa30"], "\xc1" => [18, "\xa30"], "\xc2" => [77, "\xa31"], "\xc3" => [18, "\xa31"], "\xc4" => [77, "\xa32"], "\xc5" => [18, "\xa32"], "\xc6" => [77, "\xa3a"], "\xc7" => [18, "\xa3a"], "\xc8" => [77, "\xa3c"], "\xc9" => [18, "\xa3c"], "\xca" => [77, "\xa3e"], "\xcb" => [18, "\xa3e"], "\xcc" => [77, "\xa3i"], "\xcd" => [18, "\xa3i"], "\xce" => [77, "\xa3o"], "\xcf" => [18, "\xa3o"], "\xd0" => [77, "\xa3s"], "\xd1" => [18, "\xa3s"], "\xd2" => [77, "\xa3t"], "\xd3" => [18, "\xa3t"], "\xd4" => [0, "\xa3 "], "\xd5" => [0, "\xa3%"], "\xd6" => [0, "\xa3-"], "\xd7" => [0, "\xa3."], "\xd8" => [0, "\xa3/"], "\xd9" => [0, "\xa33"], "\xda" => [0, "\xa34"], "\xdb" => [0, "\xa35"], "\xdc" => [0, "\xa36"], "\xdd" => [0, "\xa37"], "\xde" => [0, "\xa38"], "\xdf" => [0, "\xa39"], "\xe0" => [0, "\xa3="], "\xe1" => [0, "\xa3A"], "\xe2" => [0, "\xa3_"], "\xe3" => [0, "\xa3b"], "\xe4" => [0, "\xa3d"], "\xe5" => [0, "\xa3f"], "\xe6" => [0, "\xa3g"], "\xe7" => [0, "\xa3h"], "\xe8" => [0, "\xa3l"], "\xe9" => [0, "\xa3m"], "\xea" => [0, "\xa3n"], "\xeb" => [0, "\xa3p"], "\xec" => [0, "\xa3r"], "\xed" => [0, "\xa3u"], "\xee" => [100, "\xa3"], "\xef" => [110, "\xa3"], "\xf0" => [111, "\xa3"], "\xf1" => [115, "\xa3"], "\xf2" => [116, "\xa3"], "\xf3" => [118, "\xa3"], "\xf4" => [119, "\xa3"], "\xf5" => [122, "\xa3"], "\xf6" => [123, "\xa3"], "\xf7" => [125, "\xa3"], "\xf8" => [126, "\xa3"], "\xf9" => [129, "\xa3"], "\xfa" => [143, "\xa3"], "\xfb" => [148, "\xa3"], "\xfc" => [151, "\xa3"], "\xfd" => [153, "\xa3"], "\xfe" => [83, "\xa3"], "\xff" => [10, "\xa3"]], ["\x00" => [0, "\x9a0"], "\x01" => [0, "\x9a1"], "\x02" => [0, "\x9a2"], "\x03" => [0, "\x9aa"], "\x04" => [0, "\x9ac"], "\x05" => [0, "\x9ae"], "\x06" => [0, "\x9ai"], "\x07" => [0, "\x9ao"], "\x08" => [0, "\x9as"], "\t" => [0, "\x9at"], "\n" => [73, "\x9a"], "\v" => [88, "\x9a"], "\f" => [89, "\x9a"], "\r" => [96, "\x9a"], "\x0e" => [97, "\x9a"], "\x0f" => [99, "\x9a"], "\x10" => [106, "\x9a"], "\x11" => [136, "\x9a"], "\x12" => [139, "\x9a"], "\x13" => [141, "\x9a"], "\x14" => [145, "\x9a"], "\x15" => [147, "\x9a"], "\x16" => [149, "\x9a"], "\x17" => [101, "\x9a"], "\x18" => [112, "\x9a"], "\x19" => [117, "\x9a"], "\x1a" => [120, "\x9a"], "\x1b" => [124, "\x9a"], "\x1c" => [127, "\x9a"], "\x1d" => [144, "\x9a"], "\x1e" => [152, "\x9a"], "\x1f" => [11, "\x9a"], " " => [0, "\x9c0"], "!" => [0, "\x9c1"], "\"" => [0, "\x9c2"], "#" => [0, "\x9ca"], "\$" => [0, "\x9cc"], "%" => [0, "\x9ce"], "&" => [0, "\x9ci"], "'" => [0, "\x9co"], "(" => [0, "\x9cs"], ")" => [0, "\x9ct"], "*" => [73, "\x9c"], "+" => [88, "\x9c"], "," => [89, "\x9c"], "-" => [96, "\x9c"], "." => [97, "\x9c"], "/" => [99, "\x9c"], [106, "\x9c"], [136, "\x9c"], [139, "\x9c"], [141, "\x9c"], [145, "\x9c"], [147, "\x9c"], [149, "\x9c"], [101, "\x9c"], [112, "\x9c"], [117, "\x9c"], ":" => [120, "\x9c"], ";" => [124, "\x9c"], "<" => [127, "\x9c"], "=" => [144, "\x9c"], ">" => [152, "\x9c"], "?" => [11, "\x9c"], "@" => [0, "\xa00"], "A" => [0, "\xa01"], "B" => [0, "\xa02"], "C" => [0, "\xa0a"], "D" => [0, "\xa0c"], "E" => [0, "\xa0e"], "F" => [0, "\xa0i"], "G" => [0, "\xa0o"], "H" => [0, "\xa0s"], "I" => [0, "\xa0t"], "J" => [73, "\xa0"], "K" => [88, "\xa0"], "L" => [89, "\xa0"], "M" => [96, "\xa0"], "N" => [97, "\xa0"], "O" => [99, "\xa0"], "P" => [106, "\xa0"], "Q" => [136, "\xa0"], "R" => [139, "\xa0"], "S" => [141, "\xa0"], "T" => [145, "\xa0"], "U" => [147, "\xa0"], "V" => [149, "\xa0"], "W" => [101, "\xa0"], "X" => [112, "\xa0"], "Y" => [117, "\xa0"], "Z" => [120, "\xa0"], "[" => [124, "\xa0"], "\\" => [127, "\xa0"], "]" => [144, "\xa0"], "^" => [152, "\xa0"], "_" => [11, "\xa0"], "`" => [0, "\xa30"], "a" => [0, "\xa31"], "b" => [0, "\xa32"], "c" => [0, "\xa3a"], "d" => [0, "\xa3c"], "e" => [0, "\xa3e"], "f" => [0, "\xa3i"], "g" => [0, "\xa3o"], "h" => [0, "\xa3s"], "i" => [0, "\xa3t"], "j" => [73, "\xa3"], "k" => [88, "\xa3"], "l" => [89, "\xa3"], "m" => [96, "\xa3"], "n" => [97, "\xa3"], "o" => [99, "\xa3"], "p" => [106, "\xa3"], "q" => [136, "\xa3"], "r" => [139, "\xa3"], "s" => [141, "\xa3"], "t" => [145, "\xa3"], "u" => [147, "\xa3"], "v" => [149, "\xa3"], "w" => [101, "\xa3"], "x" => [112, "\xa3"], "y" => [117, "\xa3"], "z" => [120, "\xa3"], "{" => [124, "\xa3"], "|" => [127, "\xa3"], "}" => [144, "\xa3"], "~" => [152, "\xa3"], "" => [11, "\xa3"], "\x80" => [0, "\xa40"], "\x81" => [0, "\xa41"], "\x82" => [0, "\xa42"], "\x83" => [0, "\xa4a"], "\x84" => [0, "\xa4c"], "\x85" => [0, "\xa4e"], "\x86" => [0, "\xa4i"], "\x87" => [0, "\xa4o"], "\x88" => [0, "\xa4s"], "\x89" => [0, "\xa4t"], "\x8a" => [73, "\xa4"], "\x8b" => [88, "\xa4"], "\x8c" => [89, "\xa4"], "\x8d" => [96, "\xa4"], "\x8e" => [97, "\xa4"], "\x8f" => [99, "\xa4"], "\x90" => [106, "\xa4"], "\x91" => [136, "\xa4"], "\x92" => [139, "\xa4"], "\x93" => [141, "\xa4"], "\x94" => [145, "\xa4"], "\x95" => [147, "\xa4"], "\x96" => [149, "\xa4"], "\x97" => [101, "\xa4"], "\x98" => [112, "\xa4"], "\x99" => [117, "\xa4"], "\x9a" => [120, "\xa4"], "\x9b" => [124, "\xa4"], "\x9c" => [127, "\xa4"], "\x9d" => [144, "\xa4"], "\x9e" => [152, "\xa4"], "\x9f" => [11, "\xa4"], "\xa0" => [0, "\xa90"], "\xa1" => [0, "\xa91"], "\xa2" => [0, "\xa92"], "\xa3" => [0, "\xa9a"], "\xa4" => [0, "\xa9c"], "\xa5" => [0, "\xa9e"], "\xa6" => [0, "\xa9i"], "\xa7" => [0, "\xa9o"], "\xa8" => [0, "\xa9s"], "\xa9" => [0, "\xa9t"], "\xaa" => [73, "\xa9"], "\xab" => [88, "\xa9"], "\xac" => [89, "\xa9"], "\xad" => [96, "\xa9"], "\xae" => [97, "\xa9"], "\xaf" => [99, "\xa9"], "\xb0" => [106, "\xa9"], "\xb1" => [136, "\xa9"], "\xb2" => [139, "\xa9"], "\xb3" => [141, "\xa9"], "\xb4" => [145, "\xa9"], "\xb5" => [147, "\xa9"], "\xb6" => [149, "\xa9"], "\xb7" => [101, "\xa9"], "\xb8" => [112, "\xa9"], "\xb9" => [117, "\xa9"], "\xba" => [120, "\xa9"], "\xbb" => [124, "\xa9"], "\xbc" => [127, "\xa9"], "\xbd" => [144, "\xa9"], "\xbe" => [152, "\xa9"], "\xbf" => [11, "\xa9"], "\xc0" => [0, "\xaa0"], "\xc1" => [0, "\xaa1"], "\xc2" => [0, "\xaa2"], "\xc3" => [0, "\xaaa"], "\xc4" => [0, "\xaac"], "\xc5" => [0, "\xaae"], "\xc6" => [0, "\xaai"], "\xc7" => [0, "\xaao"], "\xc8" => [0, "\xaas"], "\xc9" => [0, "\xaat"], "\xca" => [73, "\xaa"], "\xcb" => [88, "\xaa"], "\xcc" => [89, "\xaa"], "\xcd" => [96, "\xaa"], "\xce" => [97, "\xaa"], "\xcf" => [99, "\xaa"], "\xd0" => [106, "\xaa"], "\xd1" => [136, "\xaa"], "\xd2" => [139, "\xaa"], "\xd3" => [141, "\xaa"], "\xd4" => [145, "\xaa"], "\xd5" => [147, "\xaa"], "\xd6" => [149, "\xaa"], "\xd7" => [101, "\xaa"], "\xd8" => [112, "\xaa"], "\xd9" => [117, "\xaa"], "\xda" => [120, "\xaa"], "\xdb" => [124, "\xaa"], "\xdc" => [127, "\xaa"], "\xdd" => [144, "\xaa"], "\xde" => [152, "\xaa"], "\xdf" => [11, "\xaa"], "\xe0" => [0, "\xad0"], "\xe1" => [0, "\xad1"], "\xe2" => [0, "\xad2"], "\xe3" => [0, "\xada"], "\xe4" => [0, "\xadc"], "\xe5" => [0, "\xade"], "\xe6" => [0, "\xadi"], "\xe7" => [0, "\xado"], "\xe8" => [0, "\xads"], "\xe9" => [0, "\xadt"], "\xea" => [73, "\xad"], "\xeb" => [88, "\xad"], "\xec" => [89, "\xad"], "\xed" => [96, "\xad"], "\xee" => [97, "\xad"], "\xef" => [99, "\xad"], "\xf0" => [106, "\xad"], "\xf1" => [136, "\xad"], "\xf2" => [139, "\xad"], "\xf3" => [141, "\xad"], "\xf4" => [145, "\xad"], "\xf5" => [147, "\xad"], "\xf6" => [149, "\xad"], "\xf7" => [101, "\xad"], "\xf8" => [112, "\xad"], "\xf9" => [117, "\xad"], "\xfa" => [120, "\xad"], "\xfb" => [124, "\xad"], "\xfc" => [127, "\xad"], "\xfd" => [144, "\xad"], "\xfe" => [152, "\xad"], "\xff" => [11, "\xad"]], ["\x00" => [94, "\x9d0"], "\x01" => [76, "\x9d0"], "\x02" => [104, "\x9d0"], "\x03" => [16, "\x9d0"], "\x04" => [94, "\x9d1"], "\x05" => [76, "\x9d1"], "\x06" => [104, "\x9d1"], "\x07" => [16, "\x9d1"], "\x08" => [94, "\x9d2"], "\t" => [76, "\x9d2"], "\n" => [104, "\x9d2"], "\v" => [16, "\x9d2"], "\f" => [94, "\x9da"], "\r" => [76, "\x9da"], "\x0e" => [104, "\x9da"], "\x0f" => [16, "\x9da"], "\x10" => [94, "\x9dc"], "\x11" => [76, "\x9dc"], "\x12" => [104, "\x9dc"], "\x13" => [16, "\x9dc"], "\x14" => [94, "\x9de"], "\x15" => [76, "\x9de"], "\x16" => [104, "\x9de"], "\x17" => [16, "\x9de"], "\x18" => [94, "\x9di"], "\x19" => [76, "\x9di"], "\x1a" => [104, "\x9di"], "\x1b" => [16, "\x9di"], "\x1c" => [94, "\x9do"], "\x1d" => [76, "\x9do"], "\x1e" => [104, "\x9do"], "\x1f" => [16, "\x9do"], " " => [94, "\x9ds"], "!" => [76, "\x9ds"], "\"" => [104, "\x9ds"], "#" => [16, "\x9ds"], "\$" => [94, "\x9dt"], "%" => [76, "\x9dt"], "&" => [104, "\x9dt"], "'" => [16, "\x9dt"], "(" => [77, "\x9d "], ")" => [18, "\x9d "], "*" => [77, "\x9d%"], "+" => [18, "\x9d%"], "," => [77, "\x9d-"], "-" => [18, "\x9d-"], "." => [77, "\x9d."], "/" => [18, "\x9d."], [77, "\x9d/"], [18, "\x9d/"], [77, "\x9d3"], [18, "\x9d3"], [77, "\x9d4"], [18, "\x9d4"], [77, "\x9d5"], [18, "\x9d5"], [77, "\x9d6"], [18, "\x9d6"], ":" => [77, "\x9d7"], ";" => [18, "\x9d7"], "<" => [77, "\x9d8"], "=" => [18, "\x9d8"], ">" => [77, "\x9d9"], "?" => [18, "\x9d9"], "@" => [77, "\x9d="], "A" => [18, "\x9d="], "B" => [77, "\x9dA"], "C" => [18, "\x9dA"], "D" => [77, "\x9d_"], "E" => [18, "\x9d_"], "F" => [77, "\x9db"], "G" => [18, "\x9db"], "H" => [77, "\x9dd"], "I" => [18, "\x9dd"], "J" => [77, "\x9df"], "K" => [18, "\x9df"], "L" => [77, "\x9dg"], "M" => [18, "\x9dg"], "N" => [77, "\x9dh"], "O" => [18, "\x9dh"], "P" => [77, "\x9dl"], "Q" => [18, "\x9dl"], "R" => [77, "\x9dm"], "S" => [18, "\x9dm"], "T" => [77, "\x9dn"], "U" => [18, "\x9dn"], "V" => [77, "\x9dp"], "W" => [18, "\x9dp"], "X" => [77, "\x9dr"], "Y" => [18, "\x9dr"], "Z" => [77, "\x9du"], "[" => [18, "\x9du"], "\\" => [0, "\x9d:"], "]" => [0, "\x9dB"], "^" => [0, "\x9dC"], "_" => [0, "\x9dD"], "`" => [0, "\x9dE"], "a" => [0, "\x9dF"], "b" => [0, "\x9dG"], "c" => [0, "\x9dH"], "d" => [0, "\x9dI"], "e" => [0, "\x9dJ"], "f" => [0, "\x9dK"], "g" => [0, "\x9dL"], "h" => [0, "\x9dM"], "i" => [0, "\x9dN"], "j" => [0, "\x9dO"], "k" => [0, "\x9dP"], "l" => [0, "\x9dQ"], "m" => [0, "\x9dR"], "n" => [0, "\x9dS"], "o" => [0, "\x9dT"], "p" => [0, "\x9dU"], "q" => [0, "\x9dV"], "r" => [0, "\x9dW"], "s" => [0, "\x9dY"], "t" => [0, "\x9dj"], "u" => [0, "\x9dk"], "v" => [0, "\x9dq"], "w" => [0, "\x9dv"], "x" => [0, "\x9dw"], "y" => [0, "\x9dx"], "z" => [0, "\x9dy"], "{" => [0, "\x9dz"], "|" => [82, "\x9d"], "}" => [87, "\x9d"], "~" => [130, "\x9d"], "" => [9, "\x9d"], "\x80" => [94, "\x9e0"], "\x81" => [76, "\x9e0"], "\x82" => [104, "\x9e0"], "\x83" => [16, "\x9e0"], "\x84" => [94, "\x9e1"], "\x85" => [76, "\x9e1"], "\x86" => [104, "\x9e1"], "\x87" => [16, "\x9e1"], "\x88" => [94, "\x9e2"], "\x89" => [76, "\x9e2"], "\x8a" => [104, "\x9e2"], "\x8b" => [16, "\x9e2"], "\x8c" => [94, "\x9ea"], "\x8d" => [76, "\x9ea"], "\x8e" => [104, "\x9ea"], "\x8f" => [16, "\x9ea"], "\x90" => [94, "\x9ec"], "\x91" => [76, "\x9ec"], "\x92" => [104, "\x9ec"], "\x93" => [16, "\x9ec"], "\x94" => [94, "\x9ee"], "\x95" => [76, "\x9ee"], "\x96" => [104, "\x9ee"], "\x97" => [16, "\x9ee"], "\x98" => [94, "\x9ei"], "\x99" => [76, "\x9ei"], "\x9a" => [104, "\x9ei"], "\x9b" => [16, "\x9ei"], "\x9c" => [94, "\x9eo"], "\x9d" => [76, "\x9eo"], "\x9e" => [104, "\x9eo"], "\x9f" => [16, "\x9eo"], "\xa0" => [94, "\x9es"], "\xa1" => [76, "\x9es"], "\xa2" => [104, "\x9es"], "\xa3" => [16, "\x9es"], "\xa4" => [94, "\x9et"], "\xa5" => [76, "\x9et"], "\xa6" => [104, "\x9et"], "\xa7" => [16, "\x9et"], "\xa8" => [77, "\x9e "], "\xa9" => [18, "\x9e "], "\xaa" => [77, "\x9e%"], "\xab" => [18, "\x9e%"], "\xac" => [77, "\x9e-"], "\xad" => [18, "\x9e-"], "\xae" => [77, "\x9e."], "\xaf" => [18, "\x9e."], "\xb0" => [77, "\x9e/"], "\xb1" => [18, "\x9e/"], "\xb2" => [77, "\x9e3"], "\xb3" => [18, "\x9e3"], "\xb4" => [77, "\x9e4"], "\xb5" => [18, "\x9e4"], "\xb6" => [77, "\x9e5"], "\xb7" => [18, "\x9e5"], "\xb8" => [77, "\x9e6"], "\xb9" => [18, "\x9e6"], "\xba" => [77, "\x9e7"], "\xbb" => [18, "\x9e7"], "\xbc" => [77, "\x9e8"], "\xbd" => [18, "\x9e8"], "\xbe" => [77, "\x9e9"], "\xbf" => [18, "\x9e9"], "\xc0" => [77, "\x9e="], "\xc1" => [18, "\x9e="], "\xc2" => [77, "\x9eA"], "\xc3" => [18, "\x9eA"], "\xc4" => [77, "\x9e_"], "\xc5" => [18, "\x9e_"], "\xc6" => [77, "\x9eb"], "\xc7" => [18, "\x9eb"], "\xc8" => [77, "\x9ed"], "\xc9" => [18, "\x9ed"], "\xca" => [77, "\x9ef"], "\xcb" => [18, "\x9ef"], "\xcc" => [77, "\x9eg"], "\xcd" => [18, "\x9eg"], "\xce" => [77, "\x9eh"], "\xcf" => [18, "\x9eh"], "\xd0" => [77, "\x9el"], "\xd1" => [18, "\x9el"], "\xd2" => [77, "\x9em"], "\xd3" => [18, "\x9em"], "\xd4" => [77, "\x9en"], "\xd5" => [18, "\x9en"], "\xd6" => [77, "\x9ep"], "\xd7" => [18, "\x9ep"], "\xd8" => [77, "\x9er"], "\xd9" => [18, "\x9er"], "\xda" => [77, "\x9eu"], "\xdb" => [18, "\x9eu"], "\xdc" => [0, "\x9e:"], "\xdd" => [0, "\x9eB"], "\xde" => [0, "\x9eC"], "\xdf" => [0, "\x9eD"], "\xe0" => [0, "\x9eE"], "\xe1" => [0, "\x9eF"], "\xe2" => [0, "\x9eG"], "\xe3" => [0, "\x9eH"], "\xe4" => [0, "\x9eI"], "\xe5" => [0, "\x9eJ"], "\xe6" => [0, "\x9eK"], "\xe7" => [0, "\x9eL"], "\xe8" => [0, "\x9eM"], "\xe9" => [0, "\x9eN"], "\xea" => [0, "\x9eO"], "\xeb" => [0, "\x9eP"], "\xec" => [0, "\x9eQ"], "\xed" => [0, "\x9eR"], "\xee" => [0, "\x9eS"], "\xef" => [0, "\x9eT"], "\xf0" => [0, "\x9eU"], "\xf1" => [0, "\x9eV"], "\xf2" => [0, "\x9eW"], "\xf3" => [0, "\x9eY"], "\xf4" => [0, "\x9ej"], "\xf5" => [0, "\x9ek"], "\xf6" => [0, "\x9eq"], "\xf7" => [0, "\x9ev"], "\xf8" => [0, "\x9ew"], "\xf9" => [0, "\x9ex"], "\xfa" => [0, "\x9ey"], "\xfb" => [0, "\x9ez"], "\xfc" => [82, "\x9e"], "\xfd" => [87, "\x9e"], "\xfe" => [130, "\x9e"], "\xff" => [9, "\x9e"]], ["\x00" => [94, "\xa00"], "\x01" => [76, "\xa00"], "\x02" => [104, "\xa00"], "\x03" => [16, "\xa00"], "\x04" => [94, "\xa01"], "\x05" => [76, "\xa01"], "\x06" => [104, "\xa01"], "\x07" => [16, "\xa01"], "\x08" => [94, "\xa02"], "\t" => [76, "\xa02"], "\n" => [104, "\xa02"], "\v" => [16, "\xa02"], "\f" => [94, "\xa0a"], "\r" => [76, "\xa0a"], "\x0e" => [104, "\xa0a"], "\x0f" => [16, "\xa0a"], "\x10" => [94, "\xa0c"], "\x11" => [76, "\xa0c"], "\x12" => [104, "\xa0c"], "\x13" => [16, "\xa0c"], "\x14" => [94, "\xa0e"], "\x15" => [76, "\xa0e"], "\x16" => [104, "\xa0e"], "\x17" => [16, "\xa0e"], "\x18" => [94, "\xa0i"], "\x19" => [76, "\xa0i"], "\x1a" => [104, "\xa0i"], "\x1b" => [16, "\xa0i"], "\x1c" => [94, "\xa0o"], "\x1d" => [76, "\xa0o"], "\x1e" => [104, "\xa0o"], "\x1f" => [16, "\xa0o"], " " => [94, "\xa0s"], "!" => [76, "\xa0s"], "\"" => [104, "\xa0s"], "#" => [16, "\xa0s"], "\$" => [94, "\xa0t"], "%" => [76, "\xa0t"], "&" => [104, "\xa0t"], "'" => [16, "\xa0t"], "(" => [77, "\xa0 "], ")" => [18, "\xa0 "], "*" => [77, "\xa0%"], "+" => [18, "\xa0%"], "," => [77, "\xa0-"], "-" => [18, "\xa0-"], "." => [77, "\xa0."], "/" => [18, "\xa0."], [77, "\xa0/"], [18, "\xa0/"], [77, "\xa03"], [18, "\xa03"], [77, "\xa04"], [18, "\xa04"], [77, "\xa05"], [18, "\xa05"], [77, "\xa06"], [18, "\xa06"], ":" => [77, "\xa07"], ";" => [18, "\xa07"], "<" => [77, "\xa08"], "=" => [18, "\xa08"], ">" => [77, "\xa09"], "?" => [18, "\xa09"], "@" => [77, "\xa0="], "A" => [18, "\xa0="], "B" => [77, "\xa0A"], "C" => [18, "\xa0A"], "D" => [77, "\xa0_"], "E" => [18, "\xa0_"], "F" => [77, "\xa0b"], "G" => [18, "\xa0b"], "H" => [77, "\xa0d"], "I" => [18, "\xa0d"], "J" => [77, "\xa0f"], "K" => [18, "\xa0f"], "L" => [77, "\xa0g"], "M" => [18, "\xa0g"], "N" => [77, "\xa0h"], "O" => [18, "\xa0h"], "P" => [77, "\xa0l"], "Q" => [18, "\xa0l"], "R" => [77, "\xa0m"], "S" => [18, "\xa0m"], "T" => [77, "\xa0n"], "U" => [18, "\xa0n"], "V" => [77, "\xa0p"], "W" => [18, "\xa0p"], "X" => [77, "\xa0r"], "Y" => [18, "\xa0r"], "Z" => [77, "\xa0u"], "[" => [18, "\xa0u"], "\\" => [0, "\xa0:"], "]" => [0, "\xa0B"], "^" => [0, "\xa0C"], "_" => [0, "\xa0D"], "`" => [0, "\xa0E"], "a" => [0, "\xa0F"], "b" => [0, "\xa0G"], "c" => [0, "\xa0H"], "d" => [0, "\xa0I"], "e" => [0, "\xa0J"], "f" => [0, "\xa0K"], "g" => [0, "\xa0L"], "h" => [0, "\xa0M"], "i" => [0, "\xa0N"], "j" => [0, "\xa0O"], "k" => [0, "\xa0P"], "l" => [0, "\xa0Q"], "m" => [0, "\xa0R"], "n" => [0, "\xa0S"], "o" => [0, "\xa0T"], "p" => [0, "\xa0U"], "q" => [0, "\xa0V"], "r" => [0, "\xa0W"], "s" => [0, "\xa0Y"], "t" => [0, "\xa0j"], "u" => [0, "\xa0k"], "v" => [0, "\xa0q"], "w" => [0, "\xa0v"], "x" => [0, "\xa0w"], "y" => [0, "\xa0x"], "z" => [0, "\xa0y"], "{" => [0, "\xa0z"], "|" => [82, "\xa0"], "}" => [87, "\xa0"], "~" => [130, "\xa0"], "" => [9, "\xa0"], "\x80" => [94, "\xa30"], "\x81" => [76, "\xa30"], "\x82" => [104, "\xa30"], "\x83" => [16, "\xa30"], "\x84" => [94, "\xa31"], "\x85" => [76, "\xa31"], "\x86" => [104, "\xa31"], "\x87" => [16, "\xa31"], "\x88" => [94, "\xa32"], "\x89" => [76, "\xa32"], "\x8a" => [104, "\xa32"], "\x8b" => [16, "\xa32"], "\x8c" => [94, "\xa3a"], "\x8d" => [76, "\xa3a"], "\x8e" => [104, "\xa3a"], "\x8f" => [16, "\xa3a"], "\x90" => [94, "\xa3c"], "\x91" => [76, "\xa3c"], "\x92" => [104, "\xa3c"], "\x93" => [16, "\xa3c"], "\x94" => [94, "\xa3e"], "\x95" => [76, "\xa3e"], "\x96" => [104, "\xa3e"], "\x97" => [16, "\xa3e"], "\x98" => [94, "\xa3i"], "\x99" => [76, "\xa3i"], "\x9a" => [104, "\xa3i"], "\x9b" => [16, "\xa3i"], "\x9c" => [94, "\xa3o"], "\x9d" => [76, "\xa3o"], "\x9e" => [104, "\xa3o"], "\x9f" => [16, "\xa3o"], "\xa0" => [94, "\xa3s"], "\xa1" => [76, "\xa3s"], "\xa2" => [104, "\xa3s"], "\xa3" => [16, "\xa3s"], "\xa4" => [94, "\xa3t"], "\xa5" => [76, "\xa3t"], "\xa6" => [104, "\xa3t"], "\xa7" => [16, "\xa3t"], "\xa8" => [77, "\xa3 "], "\xa9" => [18, "\xa3 "], "\xaa" => [77, "\xa3%"], "\xab" => [18, "\xa3%"], "\xac" => [77, "\xa3-"], "\xad" => [18, "\xa3-"], "\xae" => [77, "\xa3."], "\xaf" => [18, "\xa3."], "\xb0" => [77, "\xa3/"], "\xb1" => [18, "\xa3/"], "\xb2" => [77, "\xa33"], "\xb3" => [18, "\xa33"], "\xb4" => [77, "\xa34"], "\xb5" => [18, "\xa34"], "\xb6" => [77, "\xa35"], "\xb7" => [18, "\xa35"], "\xb8" => [77, "\xa36"], "\xb9" => [18, "\xa36"], "\xba" => [77, "\xa37"], "\xbb" => [18, "\xa37"], "\xbc" => [77, "\xa38"], "\xbd" => [18, "\xa38"], "\xbe" => [77, "\xa39"], "\xbf" => [18, "\xa39"], "\xc0" => [77, "\xa3="], "\xc1" => [18, "\xa3="], "\xc2" => [77, "\xa3A"], "\xc3" => [18, "\xa3A"], "\xc4" => [77, "\xa3_"], "\xc5" => [18, "\xa3_"], "\xc6" => [77, "\xa3b"], "\xc7" => [18, "\xa3b"], "\xc8" => [77, "\xa3d"], "\xc9" => [18, "\xa3d"], "\xca" => [77, "\xa3f"], "\xcb" => [18, "\xa3f"], "\xcc" => [77, "\xa3g"], "\xcd" => [18, "\xa3g"], "\xce" => [77, "\xa3h"], "\xcf" => [18, "\xa3h"], "\xd0" => [77, "\xa3l"], "\xd1" => [18, "\xa3l"], "\xd2" => [77, "\xa3m"], "\xd3" => [18, "\xa3m"], "\xd4" => [77, "\xa3n"], "\xd5" => [18, "\xa3n"], "\xd6" => [77, "\xa3p"], "\xd7" => [18, "\xa3p"], "\xd8" => [77, "\xa3r"], "\xd9" => [18, "\xa3r"], "\xda" => [77, "\xa3u"], "\xdb" => [18, "\xa3u"], "\xdc" => [0, "\xa3:"], "\xdd" => [0, "\xa3B"], "\xde" => [0, "\xa3C"], "\xdf" => [0, "\xa3D"], "\xe0" => [0, "\xa3E"], "\xe1" => [0, "\xa3F"], "\xe2" => [0, "\xa3G"], "\xe3" => [0, "\xa3H"], "\xe4" => [0, "\xa3I"], "\xe5" => [0, "\xa3J"], "\xe6" => [0, "\xa3K"], "\xe7" => [0, "\xa3L"], "\xe8" => [0, "\xa3M"], "\xe9" => [0, "\xa3N"], "\xea" => [0, "\xa3O"], "\xeb" => [0, "\xa3P"], "\xec" => [0, "\xa3Q"], "\xed" => [0, "\xa3R"], "\xee" => [0, "\xa3S"], "\xef" => [0, "\xa3T"], "\xf0" => [0, "\xa3U"], "\xf1" => [0, "\xa3V"], "\xf2" => [0, "\xa3W"], "\xf3" => [0, "\xa3Y"], "\xf4" => [0, "\xa3j"], "\xf5" => [0, "\xa3k"], "\xf6" => [0, "\xa3q"], "\xf7" => [0, "\xa3v"], "\xf8" => [0, "\xa3w"], "\xf9" => [0, "\xa3x"], "\xfa" => [0, "\xa3y"], "\xfb" => [0, "\xa3z"], "\xfc" => [82, "\xa3"], "\xfd" => [87, "\xa3"], "\xfe" => [130, "\xa3"], "\xff" => [9, "\xa3"]], ["\x00" => [94, "\xa40"], "\x01" => [76, "\xa40"], "\x02" => [104, "\xa40"], "\x03" => [16, "\xa40"], "\x04" => [94, "\xa41"], "\x05" => [76, "\xa41"], "\x06" => [104, "\xa41"], "\x07" => [16, "\xa41"], "\x08" => [94, "\xa42"], "\t" => [76, "\xa42"], "\n" => [104, "\xa42"], "\v" => [16, "\xa42"], "\f" => [94, "\xa4a"], "\r" => [76, "\xa4a"], "\x0e" => [104, "\xa4a"], "\x0f" => [16, "\xa4a"], "\x10" => [94, "\xa4c"], "\x11" => [76, "\xa4c"], "\x12" => [104, "\xa4c"], "\x13" => [16, "\xa4c"], "\x14" => [94, "\xa4e"], "\x15" => [76, "\xa4e"], "\x16" => [104, "\xa4e"], "\x17" => [16, "\xa4e"], "\x18" => [94, "\xa4i"], "\x19" => [76, "\xa4i"], "\x1a" => [104, "\xa4i"], "\x1b" => [16, "\xa4i"], "\x1c" => [94, "\xa4o"], "\x1d" => [76, "\xa4o"], "\x1e" => [104, "\xa4o"], "\x1f" => [16, "\xa4o"], " " => [94, "\xa4s"], "!" => [76, "\xa4s"], "\"" => [104, "\xa4s"], "#" => [16, "\xa4s"], "\$" => [94, "\xa4t"], "%" => [76, "\xa4t"], "&" => [104, "\xa4t"], "'" => [16, "\xa4t"], "(" => [77, "\xa4 "], ")" => [18, "\xa4 "], "*" => [77, "\xa4%"], "+" => [18, "\xa4%"], "," => [77, "\xa4-"], "-" => [18, "\xa4-"], "." => [77, "\xa4."], "/" => [18, "\xa4."], [77, "\xa4/"], [18, "\xa4/"], [77, "\xa43"], [18, "\xa43"], [77, "\xa44"], [18, "\xa44"], [77, "\xa45"], [18, "\xa45"], [77, "\xa46"], [18, "\xa46"], ":" => [77, "\xa47"], ";" => [18, "\xa47"], "<" => [77, "\xa48"], "=" => [18, "\xa48"], ">" => [77, "\xa49"], "?" => [18, "\xa49"], "@" => [77, "\xa4="], "A" => [18, "\xa4="], "B" => [77, "\xa4A"], "C" => [18, "\xa4A"], "D" => [77, "\xa4_"], "E" => [18, "\xa4_"], "F" => [77, "\xa4b"], "G" => [18, "\xa4b"], "H" => [77, "\xa4d"], "I" => [18, "\xa4d"], "J" => [77, "\xa4f"], "K" => [18, "\xa4f"], "L" => [77, "\xa4g"], "M" => [18, "\xa4g"], "N" => [77, "\xa4h"], "O" => [18, "\xa4h"], "P" => [77, "\xa4l"], "Q" => [18, "\xa4l"], "R" => [77, "\xa4m"], "S" => [18, "\xa4m"], "T" => [77, "\xa4n"], "U" => [18, "\xa4n"], "V" => [77, "\xa4p"], "W" => [18, "\xa4p"], "X" => [77, "\xa4r"], "Y" => [18, "\xa4r"], "Z" => [77, "\xa4u"], "[" => [18, "\xa4u"], "\\" => [0, "\xa4:"], "]" => [0, "\xa4B"], "^" => [0, "\xa4C"], "_" => [0, "\xa4D"], "`" => [0, "\xa4E"], "a" => [0, "\xa4F"], "b" => [0, "\xa4G"], "c" => [0, "\xa4H"], "d" => [0, "\xa4I"], "e" => [0, "\xa4J"], "f" => [0, "\xa4K"], "g" => [0, "\xa4L"], "h" => [0, "\xa4M"], "i" => [0, "\xa4N"], "j" => [0, "\xa4O"], "k" => [0, "\xa4P"], "l" => [0, "\xa4Q"], "m" => [0, "\xa4R"], "n" => [0, "\xa4S"], "o" => [0, "\xa4T"], "p" => [0, "\xa4U"], "q" => [0, "\xa4V"], "r" => [0, "\xa4W"], "s" => [0, "\xa4Y"], "t" => [0, "\xa4j"], "u" => [0, "\xa4k"], "v" => [0, "\xa4q"], "w" => [0, "\xa4v"], "x" => [0, "\xa4w"], "y" => [0, "\xa4x"], "z" => [0, "\xa4y"], "{" => [0, "\xa4z"], "|" => [82, "\xa4"], "}" => [87, "\xa4"], "~" => [130, "\xa4"], "" => [9, "\xa4"], "\x80" => [94, "\xa90"], "\x81" => [76, "\xa90"], "\x82" => [104, "\xa90"], "\x83" => [16, "\xa90"], "\x84" => [94, "\xa91"], "\x85" => [76, "\xa91"], "\x86" => [104, "\xa91"], "\x87" => [16, "\xa91"], "\x88" => [94, "\xa92"], "\x89" => [76, "\xa92"], "\x8a" => [104, "\xa92"], "\x8b" => [16, "\xa92"], "\x8c" => [94, "\xa9a"], "\x8d" => [76, "\xa9a"], "\x8e" => [104, "\xa9a"], "\x8f" => [16, "\xa9a"], "\x90" => [94, "\xa9c"], "\x91" => [76, "\xa9c"], "\x92" => [104, "\xa9c"], "\x93" => [16, "\xa9c"], "\x94" => [94, "\xa9e"], "\x95" => [76, "\xa9e"], "\x96" => [104, "\xa9e"], "\x97" => [16, "\xa9e"], "\x98" => [94, "\xa9i"], "\x99" => [76, "\xa9i"], "\x9a" => [104, "\xa9i"], "\x9b" => [16, "\xa9i"], "\x9c" => [94, "\xa9o"], "\x9d" => [76, "\xa9o"], "\x9e" => [104, "\xa9o"], "\x9f" => [16, "\xa9o"], "\xa0" => [94, "\xa9s"], "\xa1" => [76, "\xa9s"], "\xa2" => [104, "\xa9s"], "\xa3" => [16, "\xa9s"], "\xa4" => [94, "\xa9t"], "\xa5" => [76, "\xa9t"], "\xa6" => [104, "\xa9t"], "\xa7" => [16, "\xa9t"], "\xa8" => [77, "\xa9 "], "\xa9" => [18, "\xa9 "], "\xaa" => [77, "\xa9%"], "\xab" => [18, "\xa9%"], "\xac" => [77, "\xa9-"], "\xad" => [18, "\xa9-"], "\xae" => [77, "\xa9."], "\xaf" => [18, "\xa9."], "\xb0" => [77, "\xa9/"], "\xb1" => [18, "\xa9/"], "\xb2" => [77, "\xa93"], "\xb3" => [18, "\xa93"], "\xb4" => [77, "\xa94"], "\xb5" => [18, "\xa94"], "\xb6" => [77, "\xa95"], "\xb7" => [18, "\xa95"], "\xb8" => [77, "\xa96"], "\xb9" => [18, "\xa96"], "\xba" => [77, "\xa97"], "\xbb" => [18, "\xa97"], "\xbc" => [77, "\xa98"], "\xbd" => [18, "\xa98"], "\xbe" => [77, "\xa99"], "\xbf" => [18, "\xa99"], "\xc0" => [77, "\xa9="], "\xc1" => [18, "\xa9="], "\xc2" => [77, "\xa9A"], "\xc3" => [18, "\xa9A"], "\xc4" => [77, "\xa9_"], "\xc5" => [18, "\xa9_"], "\xc6" => [77, "\xa9b"], "\xc7" => [18, "\xa9b"], "\xc8" => [77, "\xa9d"], "\xc9" => [18, "\xa9d"], "\xca" => [77, "\xa9f"], "\xcb" => [18, "\xa9f"], "\xcc" => [77, "\xa9g"], "\xcd" => [18, "\xa9g"], "\xce" => [77, "\xa9h"], "\xcf" => [18, "\xa9h"], "\xd0" => [77, "\xa9l"], "\xd1" => [18, "\xa9l"], "\xd2" => [77, "\xa9m"], "\xd3" => [18, "\xa9m"], "\xd4" => [77, "\xa9n"], "\xd5" => [18, "\xa9n"], "\xd6" => [77, "\xa9p"], "\xd7" => [18, "\xa9p"], "\xd8" => [77, "\xa9r"], "\xd9" => [18, "\xa9r"], "\xda" => [77, "\xa9u"], "\xdb" => [18, "\xa9u"], "\xdc" => [0, "\xa9:"], "\xdd" => [0, "\xa9B"], "\xde" => [0, "\xa9C"], "\xdf" => [0, "\xa9D"], "\xe0" => [0, "\xa9E"], "\xe1" => [0, "\xa9F"], "\xe2" => [0, "\xa9G"], "\xe3" => [0, "\xa9H"], "\xe4" => [0, "\xa9I"], "\xe5" => [0, "\xa9J"], "\xe6" => [0, "\xa9K"], "\xe7" => [0, "\xa9L"], "\xe8" => [0, "\xa9M"], "\xe9" => [0, "\xa9N"], "\xea" => [0, "\xa9O"], "\xeb" => [0, "\xa9P"], "\xec" => [0, "\xa9Q"], "\xed" => [0, "\xa9R"], "\xee" => [0, "\xa9S"], "\xef" => [0, "\xa9T"], "\xf0" => [0, "\xa9U"], "\xf1" => [0, "\xa9V"], "\xf2" => [0, "\xa9W"], "\xf3" => [0, "\xa9Y"], "\xf4" => [0, "\xa9j"], "\xf5" => [0, "\xa9k"], "\xf6" => [0, "\xa9q"], "\xf7" => [0, "\xa9v"], "\xf8" => [0, "\xa9w"], "\xf9" => [0, "\xa9x"], "\xfa" => [0, "\xa9y"], "\xfb" => [0, "\xa9z"], "\xfc" => [82, "\xa9"], "\xfd" => [87, "\xa9"], "\xfe" => [130, "\xa9"], "\xff" => [9, "\xa9"]], ["\x00" => [77, "\xa40"], "\x01" => [18, "\xa40"], "\x02" => [77, "\xa41"], "\x03" => [18, "\xa41"], "\x04" => [77, "\xa42"], "\x05" => [18, "\xa42"], "\x06" => [77, "\xa4a"], "\x07" => [18, "\xa4a"], "\x08" => [77, "\xa4c"], "\t" => [18, "\xa4c"], "\n" => [77, "\xa4e"], "\v" => [18, "\xa4e"], "\f" => [77, "\xa4i"], "\r" => [18, "\xa4i"], "\x0e" => [77, "\xa4o"], "\x0f" => [18, "\xa4o"], "\x10" => [77, "\xa4s"], "\x11" => [18, "\xa4s"], "\x12" => [77, "\xa4t"], "\x13" => [18, "\xa4t"], "\x14" => [0, "\xa4 "], "\x15" => [0, "\xa4%"], "\x16" => [0, "\xa4-"], "\x17" => [0, "\xa4."], "\x18" => [0, "\xa4/"], "\x19" => [0, "\xa43"], "\x1a" => [0, "\xa44"], "\x1b" => [0, "\xa45"], "\x1c" => [0, "\xa46"], "\x1d" => [0, "\xa47"], "\x1e" => [0, "\xa48"], "\x1f" => [0, "\xa49"], " " => [0, "\xa4="], "!" => [0, "\xa4A"], "\"" => [0, "\xa4_"], "#" => [0, "\xa4b"], "\$" => [0, "\xa4d"], "%" => [0, "\xa4f"], "&" => [0, "\xa4g"], "'" => [0, "\xa4h"], "(" => [0, "\xa4l"], ")" => [0, "\xa4m"], "*" => [0, "\xa4n"], "+" => [0, "\xa4p"], "," => [0, "\xa4r"], "-" => [0, "\xa4u"], "." => [100, "\xa4"], "/" => [110, "\xa4"], [111, "\xa4"], [115, "\xa4"], [116, "\xa4"], [118, "\xa4"], [119, "\xa4"], [122, "\xa4"], [123, "\xa4"], [125, "\xa4"], [126, "\xa4"], [129, "\xa4"], ":" => [143, "\xa4"], ";" => [148, "\xa4"], "<" => [151, "\xa4"], "=" => [153, "\xa4"], ">" => [83, "\xa4"], "?" => [10, "\xa4"], "@" => [77, "\xa90"], "A" => [18, "\xa90"], "B" => [77, "\xa91"], "C" => [18, "\xa91"], "D" => [77, "\xa92"], "E" => [18, "\xa92"], "F" => [77, "\xa9a"], "G" => [18, "\xa9a"], "H" => [77, "\xa9c"], "I" => [18, "\xa9c"], "J" => [77, "\xa9e"], "K" => [18, "\xa9e"], "L" => [77, "\xa9i"], "M" => [18, "\xa9i"], "N" => [77, "\xa9o"], "O" => [18, "\xa9o"], "P" => [77, "\xa9s"], "Q" => [18, "\xa9s"], "R" => [77, "\xa9t"], "S" => [18, "\xa9t"], "T" => [0, "\xa9 "], "U" => [0, "\xa9%"], "V" => [0, "\xa9-"], "W" => [0, "\xa9."], "X" => [0, "\xa9/"], "Y" => [0, "\xa93"], "Z" => [0, "\xa94"], "[" => [0, "\xa95"], "\\" => [0, "\xa96"], "]" => [0, "\xa97"], "^" => [0, "\xa98"], "_" => [0, "\xa99"], "`" => [0, "\xa9="], "a" => [0, "\xa9A"], "b" => [0, "\xa9_"], "c" => [0, "\xa9b"], "d" => [0, "\xa9d"], "e" => [0, "\xa9f"], "f" => [0, "\xa9g"], "g" => [0, "\xa9h"], "h" => [0, "\xa9l"], "i" => [0, "\xa9m"], "j" => [0, "\xa9n"], "k" => [0, "\xa9p"], "l" => [0, "\xa9r"], "m" => [0, "\xa9u"], "n" => [100, "\xa9"], "o" => [110, "\xa9"], "p" => [111, "\xa9"], "q" => [115, "\xa9"], "r" => [116, "\xa9"], "s" => [118, "\xa9"], "t" => [119, "\xa9"], "u" => [122, "\xa9"], "v" => [123, "\xa9"], "w" => [125, "\xa9"], "x" => [126, "\xa9"], "y" => [129, "\xa9"], "z" => [143, "\xa9"], "{" => [148, "\xa9"], "|" => [151, "\xa9"], "}" => [153, "\xa9"], "~" => [83, "\xa9"], "" => [10, "\xa9"], "\x80" => [77, "\xaa0"], "\x81" => [18, "\xaa0"], "\x82" => [77, "\xaa1"], "\x83" => [18, "\xaa1"], "\x84" => [77, "\xaa2"], "\x85" => [18, "\xaa2"], "\x86" => [77, "\xaaa"], "\x87" => [18, "\xaaa"], "\x88" => [77, "\xaac"], "\x89" => [18, "\xaac"], "\x8a" => [77, "\xaae"], "\x8b" => [18, "\xaae"], "\x8c" => [77, "\xaai"], "\x8d" => [18, "\xaai"], "\x8e" => [77, "\xaao"], "\x8f" => [18, "\xaao"], "\x90" => [77, "\xaas"], "\x91" => [18, "\xaas"], "\x92" => [77, "\xaat"], "\x93" => [18, "\xaat"], "\x94" => [0, "\xaa "], "\x95" => [0, "\xaa%"], "\x96" => [0, "\xaa-"], "\x97" => [0, "\xaa."], "\x98" => [0, "\xaa/"], "\x99" => [0, "\xaa3"], "\x9a" => [0, "\xaa4"], "\x9b" => [0, "\xaa5"], "\x9c" => [0, "\xaa6"], "\x9d" => [0, "\xaa7"], "\x9e" => [0, "\xaa8"], "\x9f" => [0, "\xaa9"], "\xa0" => [0, "\xaa="], "\xa1" => [0, "\xaaA"], "\xa2" => [0, "\xaa_"], "\xa3" => [0, "\xaab"], "\xa4" => [0, "\xaad"], "\xa5" => [0, "\xaaf"], "\xa6" => [0, "\xaag"], "\xa7" => [0, "\xaah"], "\xa8" => [0, "\xaal"], "\xa9" => [0, "\xaam"], "\xaa" => [0, "\xaan"], "\xab" => [0, "\xaap"], "\xac" => [0, "\xaar"], "\xad" => [0, "\xaau"], "\xae" => [100, "\xaa"], "\xaf" => [110, "\xaa"], "\xb0" => [111, "\xaa"], "\xb1" => [115, "\xaa"], "\xb2" => [116, "\xaa"], "\xb3" => [118, "\xaa"], "\xb4" => [119, "\xaa"], "\xb5" => [122, "\xaa"], "\xb6" => [123, "\xaa"], "\xb7" => [125, "\xaa"], "\xb8" => [126, "\xaa"], "\xb9" => [129, "\xaa"], "\xba" => [143, "\xaa"], "\xbb" => [148, "\xaa"], "\xbc" => [151, "\xaa"], "\xbd" => [153, "\xaa"], "\xbe" => [83, "\xaa"], "\xbf" => [10, "\xaa"], "\xc0" => [77, "\xad0"], "\xc1" => [18, "\xad0"], "\xc2" => [77, "\xad1"], "\xc3" => [18, "\xad1"], "\xc4" => [77, "\xad2"], "\xc5" => [18, "\xad2"], "\xc6" => [77, "\xada"], "\xc7" => [18, "\xada"], "\xc8" => [77, "\xadc"], "\xc9" => [18, "\xadc"], "\xca" => [77, "\xade"], "\xcb" => [18, "\xade"], "\xcc" => [77, "\xadi"], "\xcd" => [18, "\xadi"], "\xce" => [77, "\xado"], "\xcf" => [18, "\xado"], "\xd0" => [77, "\xads"], "\xd1" => [18, "\xads"], "\xd2" => [77, "\xadt"], "\xd3" => [18, "\xadt"], "\xd4" => [0, "\xad "], "\xd5" => [0, "\xad%"], "\xd6" => [0, "\xad-"], "\xd7" => [0, "\xad."], "\xd8" => [0, "\xad/"], "\xd9" => [0, "\xad3"], "\xda" => [0, "\xad4"], "\xdb" => [0, "\xad5"], "\xdc" => [0, "\xad6"], "\xdd" => [0, "\xad7"], "\xde" => [0, "\xad8"], "\xdf" => [0, "\xad9"], "\xe0" => [0, "\xad="], "\xe1" => [0, "\xadA"], "\xe2" => [0, "\xad_"], "\xe3" => [0, "\xadb"], "\xe4" => [0, "\xadd"], "\xe5" => [0, "\xadf"], "\xe6" => [0, "\xadg"], "\xe7" => [0, "\xadh"], "\xe8" => [0, "\xadl"], "\xe9" => [0, "\xadm"], "\xea" => [0, "\xadn"], "\xeb" => [0, "\xadp"], "\xec" => [0, "\xadr"], "\xed" => [0, "\xadu"], "\xee" => [100, "\xad"], "\xef" => [110, "\xad"], "\xf0" => [111, "\xad"], "\xf1" => [115, "\xad"], "\xf2" => [116, "\xad"], "\xf3" => [118, "\xad"], "\xf4" => [119, "\xad"], "\xf5" => [122, "\xad"], "\xf6" => [123, "\xad"], "\xf7" => [125, "\xad"], "\xf8" => [126, "\xad"], "\xf9" => [129, "\xad"], "\xfa" => [143, "\xad"], "\xfb" => [148, "\xad"], "\xfc" => [151, "\xad"], "\xfd" => [153, "\xad"], "\xfe" => [83, "\xad"], "\xff" => [10, "\xad"]], ["\x00" => [94, "\xa50"], "\x01" => [76, "\xa50"], "\x02" => [104, "\xa50"], "\x03" => [16, "\xa50"], "\x04" => [94, "\xa51"], "\x05" => [76, "\xa51"], "\x06" => [104, "\xa51"], "\x07" => [16, "\xa51"], "\x08" => [94, "\xa52"], "\t" => [76, "\xa52"], "\n" => [104, "\xa52"], "\v" => [16, "\xa52"], "\f" => [94, "\xa5a"], "\r" => [76, "\xa5a"], "\x0e" => [104, "\xa5a"], "\x0f" => [16, "\xa5a"], "\x10" => [94, "\xa5c"], "\x11" => [76, "\xa5c"], "\x12" => [104, "\xa5c"], "\x13" => [16, "\xa5c"], "\x14" => [94, "\xa5e"], "\x15" => [76, "\xa5e"], "\x16" => [104, "\xa5e"], "\x17" => [16, "\xa5e"], "\x18" => [94, "\xa5i"], "\x19" => [76, "\xa5i"], "\x1a" => [104, "\xa5i"], "\x1b" => [16, "\xa5i"], "\x1c" => [94, "\xa5o"], "\x1d" => [76, "\xa5o"], "\x1e" => [104, "\xa5o"], "\x1f" => [16, "\xa5o"], " " => [94, "\xa5s"], "!" => [76, "\xa5s"], "\"" => [104, "\xa5s"], "#" => [16, "\xa5s"], "\$" => [94, "\xa5t"], "%" => [76, "\xa5t"], "&" => [104, "\xa5t"], "'" => [16, "\xa5t"], "(" => [77, "\xa5 "], ")" => [18, "\xa5 "], "*" => [77, "\xa5%"], "+" => [18, "\xa5%"], "," => [77, "\xa5-"], "-" => [18, "\xa5-"], "." => [77, "\xa5."], "/" => [18, "\xa5."], [77, "\xa5/"], [18, "\xa5/"], [77, "\xa53"], [18, "\xa53"], [77, "\xa54"], [18, "\xa54"], [77, "\xa55"], [18, "\xa55"], [77, "\xa56"], [18, "\xa56"], ":" => [77, "\xa57"], ";" => [18, "\xa57"], "<" => [77, "\xa58"], "=" => [18, "\xa58"], ">" => [77, "\xa59"], "?" => [18, "\xa59"], "@" => [77, "\xa5="], "A" => [18, "\xa5="], "B" => [77, "\xa5A"], "C" => [18, "\xa5A"], "D" => [77, "\xa5_"], "E" => [18, "\xa5_"], "F" => [77, "\xa5b"], "G" => [18, "\xa5b"], "H" => [77, "\xa5d"], "I" => [18, "\xa5d"], "J" => [77, "\xa5f"], "K" => [18, "\xa5f"], "L" => [77, "\xa5g"], "M" => [18, "\xa5g"], "N" => [77, "\xa5h"], "O" => [18, "\xa5h"], "P" => [77, "\xa5l"], "Q" => [18, "\xa5l"], "R" => [77, "\xa5m"], "S" => [18, "\xa5m"], "T" => [77, "\xa5n"], "U" => [18, "\xa5n"], "V" => [77, "\xa5p"], "W" => [18, "\xa5p"], "X" => [77, "\xa5r"], "Y" => [18, "\xa5r"], "Z" => [77, "\xa5u"], "[" => [18, "\xa5u"], "\\" => [0, "\xa5:"], "]" => [0, "\xa5B"], "^" => [0, "\xa5C"], "_" => [0, "\xa5D"], "`" => [0, "\xa5E"], "a" => [0, "\xa5F"], "b" => [0, "\xa5G"], "c" => [0, "\xa5H"], "d" => [0, "\xa5I"], "e" => [0, "\xa5J"], "f" => [0, "\xa5K"], "g" => [0, "\xa5L"], "h" => [0, "\xa5M"], "i" => [0, "\xa5N"], "j" => [0, "\xa5O"], "k" => [0, "\xa5P"], "l" => [0, "\xa5Q"], "m" => [0, "\xa5R"], "n" => [0, "\xa5S"], "o" => [0, "\xa5T"], "p" => [0, "\xa5U"], "q" => [0, "\xa5V"], "r" => [0, "\xa5W"], "s" => [0, "\xa5Y"], "t" => [0, "\xa5j"], "u" => [0, "\xa5k"], "v" => [0, "\xa5q"], "w" => [0, "\xa5v"], "x" => [0, "\xa5w"], "y" => [0, "\xa5x"], "z" => [0, "\xa5y"], "{" => [0, "\xa5z"], "|" => [82, "\xa5"], "}" => [87, "\xa5"], "~" => [130, "\xa5"], "" => [9, "\xa5"], "\x80" => [94, "\xa60"], "\x81" => [76, "\xa60"], "\x82" => [104, "\xa60"], "\x83" => [16, "\xa60"], "\x84" => [94, "\xa61"], "\x85" => [76, "\xa61"], "\x86" => [104, "\xa61"], "\x87" => [16, "\xa61"], "\x88" => [94, "\xa62"], "\x89" => [76, "\xa62"], "\x8a" => [104, "\xa62"], "\x8b" => [16, "\xa62"], "\x8c" => [94, "\xa6a"], "\x8d" => [76, "\xa6a"], "\x8e" => [104, "\xa6a"], "\x8f" => [16, "\xa6a"], "\x90" => [94, "\xa6c"], "\x91" => [76, "\xa6c"], "\x92" => [104, "\xa6c"], "\x93" => [16, "\xa6c"], "\x94" => [94, "\xa6e"], "\x95" => [76, "\xa6e"], "\x96" => [104, "\xa6e"], "\x97" => [16, "\xa6e"], "\x98" => [94, "\xa6i"], "\x99" => [76, "\xa6i"], "\x9a" => [104, "\xa6i"], "\x9b" => [16, "\xa6i"], "\x9c" => [94, "\xa6o"], "\x9d" => [76, "\xa6o"], "\x9e" => [104, "\xa6o"], "\x9f" => [16, "\xa6o"], "\xa0" => [94, "\xa6s"], "\xa1" => [76, "\xa6s"], "\xa2" => [104, "\xa6s"], "\xa3" => [16, "\xa6s"], "\xa4" => [94, "\xa6t"], "\xa5" => [76, "\xa6t"], "\xa6" => [104, "\xa6t"], "\xa7" => [16, "\xa6t"], "\xa8" => [77, "\xa6 "], "\xa9" => [18, "\xa6 "], "\xaa" => [77, "\xa6%"], "\xab" => [18, "\xa6%"], "\xac" => [77, "\xa6-"], "\xad" => [18, "\xa6-"], "\xae" => [77, "\xa6."], "\xaf" => [18, "\xa6."], "\xb0" => [77, "\xa6/"], "\xb1" => [18, "\xa6/"], "\xb2" => [77, "\xa63"], "\xb3" => [18, "\xa63"], "\xb4" => [77, "\xa64"], "\xb5" => [18, "\xa64"], "\xb6" => [77, "\xa65"], "\xb7" => [18, "\xa65"], "\xb8" => [77, "\xa66"], "\xb9" => [18, "\xa66"], "\xba" => [77, "\xa67"], "\xbb" => [18, "\xa67"], "\xbc" => [77, "\xa68"], "\xbd" => [18, "\xa68"], "\xbe" => [77, "\xa69"], "\xbf" => [18, "\xa69"], "\xc0" => [77, "\xa6="], "\xc1" => [18, "\xa6="], "\xc2" => [77, "\xa6A"], "\xc3" => [18, "\xa6A"], "\xc4" => [77, "\xa6_"], "\xc5" => [18, "\xa6_"], "\xc6" => [77, "\xa6b"], "\xc7" => [18, "\xa6b"], "\xc8" => [77, "\xa6d"], "\xc9" => [18, "\xa6d"], "\xca" => [77, "\xa6f"], "\xcb" => [18, "\xa6f"], "\xcc" => [77, "\xa6g"], "\xcd" => [18, "\xa6g"], "\xce" => [77, "\xa6h"], "\xcf" => [18, "\xa6h"], "\xd0" => [77, "\xa6l"], "\xd1" => [18, "\xa6l"], "\xd2" => [77, "\xa6m"], "\xd3" => [18, "\xa6m"], "\xd4" => [77, "\xa6n"], "\xd5" => [18, "\xa6n"], "\xd6" => [77, "\xa6p"], "\xd7" => [18, "\xa6p"], "\xd8" => [77, "\xa6r"], "\xd9" => [18, "\xa6r"], "\xda" => [77, "\xa6u"], "\xdb" => [18, "\xa6u"], "\xdc" => [0, "\xa6:"], "\xdd" => [0, "\xa6B"], "\xde" => [0, "\xa6C"], "\xdf" => [0, "\xa6D"], "\xe0" => [0, "\xa6E"], "\xe1" => [0, "\xa6F"], "\xe2" => [0, "\xa6G"], "\xe3" => [0, "\xa6H"], "\xe4" => [0, "\xa6I"], "\xe5" => [0, "\xa6J"], "\xe6" => [0, "\xa6K"], "\xe7" => [0, "\xa6L"], "\xe8" => [0, "\xa6M"], "\xe9" => [0, "\xa6N"], "\xea" => [0, "\xa6O"], "\xeb" => [0, "\xa6P"], "\xec" => [0, "\xa6Q"], "\xed" => [0, "\xa6R"], "\xee" => [0, "\xa6S"], "\xef" => [0, "\xa6T"], "\xf0" => [0, "\xa6U"], "\xf1" => [0, "\xa6V"], "\xf2" => [0, "\xa6W"], "\xf3" => [0, "\xa6Y"], "\xf4" => [0, "\xa6j"], "\xf5" => [0, "\xa6k"], "\xf6" => [0, "\xa6q"], "\xf7" => [0, "\xa6v"], "\xf8" => [0, "\xa6w"], "\xf9" => [0, "\xa6x"], "\xfa" => [0, "\xa6y"], "\xfb" => [0, "\xa6z"], "\xfc" => [82, "\xa6"], "\xfd" => [87, "\xa6"], "\xfe" => [130, "\xa6"], "\xff" => [9, "\xa6"]], ["\x00" => [77, "\xa50"], "\x01" => [18, "\xa50"], "\x02" => [77, "\xa51"], "\x03" => [18, "\xa51"], "\x04" => [77, "\xa52"], "\x05" => [18, "\xa52"], "\x06" => [77, "\xa5a"], "\x07" => [18, "\xa5a"], "\x08" => [77, "\xa5c"], "\t" => [18, "\xa5c"], "\n" => [77, "\xa5e"], "\v" => [18, "\xa5e"], "\f" => [77, "\xa5i"], "\r" => [18, "\xa5i"], "\x0e" => [77, "\xa5o"], "\x0f" => [18, "\xa5o"], "\x10" => [77, "\xa5s"], "\x11" => [18, "\xa5s"], "\x12" => [77, "\xa5t"], "\x13" => [18, "\xa5t"], "\x14" => [0, "\xa5 "], "\x15" => [0, "\xa5%"], "\x16" => [0, "\xa5-"], "\x17" => [0, "\xa5."], "\x18" => [0, "\xa5/"], "\x19" => [0, "\xa53"], "\x1a" => [0, "\xa54"], "\x1b" => [0, "\xa55"], "\x1c" => [0, "\xa56"], "\x1d" => [0, "\xa57"], "\x1e" => [0, "\xa58"], "\x1f" => [0, "\xa59"], " " => [0, "\xa5="], "!" => [0, "\xa5A"], "\"" => [0, "\xa5_"], "#" => [0, "\xa5b"], "\$" => [0, "\xa5d"], "%" => [0, "\xa5f"], "&" => [0, "\xa5g"], "'" => [0, "\xa5h"], "(" => [0, "\xa5l"], ")" => [0, "\xa5m"], "*" => [0, "\xa5n"], "+" => [0, "\xa5p"], "," => [0, "\xa5r"], "-" => [0, "\xa5u"], "." => [100, "\xa5"], "/" => [110, "\xa5"], [111, "\xa5"], [115, "\xa5"], [116, "\xa5"], [118, "\xa5"], [119, "\xa5"], [122, "\xa5"], [123, "\xa5"], [125, "\xa5"], [126, "\xa5"], [129, "\xa5"], ":" => [143, "\xa5"], ";" => [148, "\xa5"], "<" => [151, "\xa5"], "=" => [153, "\xa5"], ">" => [83, "\xa5"], "?" => [10, "\xa5"], "@" => [77, "\xa60"], "A" => [18, "\xa60"], "B" => [77, "\xa61"], "C" => [18, "\xa61"], "D" => [77, "\xa62"], "E" => [18, "\xa62"], "F" => [77, "\xa6a"], "G" => [18, "\xa6a"], "H" => [77, "\xa6c"], "I" => [18, "\xa6c"], "J" => [77, "\xa6e"], "K" => [18, "\xa6e"], "L" => [77, "\xa6i"], "M" => [18, "\xa6i"], "N" => [77, "\xa6o"], "O" => [18, "\xa6o"], "P" => [77, "\xa6s"], "Q" => [18, "\xa6s"], "R" => [77, "\xa6t"], "S" => [18, "\xa6t"], "T" => [0, "\xa6 "], "U" => [0, "\xa6%"], "V" => [0, "\xa6-"], "W" => [0, "\xa6."], "X" => [0, "\xa6/"], "Y" => [0, "\xa63"], "Z" => [0, "\xa64"], "[" => [0, "\xa65"], "\\" => [0, "\xa66"], "]" => [0, "\xa67"], "^" => [0, "\xa68"], "_" => [0, "\xa69"], "`" => [0, "\xa6="], "a" => [0, "\xa6A"], "b" => [0, "\xa6_"], "c" => [0, "\xa6b"], "d" => [0, "\xa6d"], "e" => [0, "\xa6f"], "f" => [0, "\xa6g"], "g" => [0, "\xa6h"], "h" => [0, "\xa6l"], "i" => [0, "\xa6m"], "j" => [0, "\xa6n"], "k" => [0, "\xa6p"], "l" => [0, "\xa6r"], "m" => [0, "\xa6u"], "n" => [100, "\xa6"], "o" => [110, "\xa6"], "p" => [111, "\xa6"], "q" => [115, "\xa6"], "r" => [116, "\xa6"], "s" => [118, "\xa6"], "t" => [119, "\xa6"], "u" => [122, "\xa6"], "v" => [123, "\xa6"], "w" => [125, "\xa6"], "x" => [126, "\xa6"], "y" => [129, "\xa6"], "z" => [143, "\xa6"], "{" => [148, "\xa6"], "|" => [151, "\xa6"], "}" => [153, "\xa6"], "~" => [83, "\xa6"], "" => [10, "\xa6"], "\x80" => [77, "\xa80"], "\x81" => [18, "\xa80"], "\x82" => [77, "\xa81"], "\x83" => [18, "\xa81"], "\x84" => [77, "\xa82"], "\x85" => [18, "\xa82"], "\x86" => [77, "\xa8a"], "\x87" => [18, "\xa8a"], "\x88" => [77, "\xa8c"], "\x89" => [18, "\xa8c"], "\x8a" => [77, "\xa8e"], "\x8b" => [18, "\xa8e"], "\x8c" => [77, "\xa8i"], "\x8d" => [18, "\xa8i"], "\x8e" => [77, "\xa8o"], "\x8f" => [18, "\xa8o"], "\x90" => [77, "\xa8s"], "\x91" => [18, "\xa8s"], "\x92" => [77, "\xa8t"], "\x93" => [18, "\xa8t"], "\x94" => [0, "\xa8 "], "\x95" => [0, "\xa8%"], "\x96" => [0, "\xa8-"], "\x97" => [0, "\xa8."], "\x98" => [0, "\xa8/"], "\x99" => [0, "\xa83"], "\x9a" => [0, "\xa84"], "\x9b" => [0, "\xa85"], "\x9c" => [0, "\xa86"], "\x9d" => [0, "\xa87"], "\x9e" => [0, "\xa88"], "\x9f" => [0, "\xa89"], "\xa0" => [0, "\xa8="], "\xa1" => [0, "\xa8A"], "\xa2" => [0, "\xa8_"], "\xa3" => [0, "\xa8b"], "\xa4" => [0, "\xa8d"], "\xa5" => [0, "\xa8f"], "\xa6" => [0, "\xa8g"], "\xa7" => [0, "\xa8h"], "\xa8" => [0, "\xa8l"], "\xa9" => [0, "\xa8m"], "\xaa" => [0, "\xa8n"], "\xab" => [0, "\xa8p"], "\xac" => [0, "\xa8r"], "\xad" => [0, "\xa8u"], "\xae" => [100, "\xa8"], "\xaf" => [110, "\xa8"], "\xb0" => [111, "\xa8"], "\xb1" => [115, "\xa8"], "\xb2" => [116, "\xa8"], "\xb3" => [118, "\xa8"], "\xb4" => [119, "\xa8"], "\xb5" => [122, "\xa8"], "\xb6" => [123, "\xa8"], "\xb7" => [125, "\xa8"], "\xb8" => [126, "\xa8"], "\xb9" => [129, "\xa8"], "\xba" => [143, "\xa8"], "\xbb" => [148, "\xa8"], "\xbc" => [151, "\xa8"], "\xbd" => [153, "\xa8"], "\xbe" => [83, "\xa8"], "\xbf" => [10, "\xa8"], "\xc0" => [77, "\xae0"], "\xc1" => [18, "\xae0"], "\xc2" => [77, "\xae1"], "\xc3" => [18, "\xae1"], "\xc4" => [77, "\xae2"], "\xc5" => [18, "\xae2"], "\xc6" => [77, "\xaea"], "\xc7" => [18, "\xaea"], "\xc8" => [77, "\xaec"], "\xc9" => [18, "\xaec"], "\xca" => [77, "\xaee"], "\xcb" => [18, "\xaee"], "\xcc" => [77, "\xaei"], "\xcd" => [18, "\xaei"], "\xce" => [77, "\xaeo"], "\xcf" => [18, "\xaeo"], "\xd0" => [77, "\xaes"], "\xd1" => [18, "\xaes"], "\xd2" => [77, "\xaet"], "\xd3" => [18, "\xaet"], "\xd4" => [0, "\xae "], "\xd5" => [0, "\xae%"], "\xd6" => [0, "\xae-"], "\xd7" => [0, "\xae."], "\xd8" => [0, "\xae/"], "\xd9" => [0, "\xae3"], "\xda" => [0, "\xae4"], "\xdb" => [0, "\xae5"], "\xdc" => [0, "\xae6"], "\xdd" => [0, "\xae7"], "\xde" => [0, "\xae8"], "\xdf" => [0, "\xae9"], "\xe0" => [0, "\xae="], "\xe1" => [0, "\xaeA"], "\xe2" => [0, "\xae_"], "\xe3" => [0, "\xaeb"], "\xe4" => [0, "\xaed"], "\xe5" => [0, "\xaef"], "\xe6" => [0, "\xaeg"], "\xe7" => [0, "\xaeh"], "\xe8" => [0, "\xael"], "\xe9" => [0, "\xaem"], "\xea" => [0, "\xaen"], "\xeb" => [0, "\xaep"], "\xec" => [0, "\xaer"], "\xed" => [0, "\xaeu"], "\xee" => [100, "\xae"], "\xef" => [110, "\xae"], "\xf0" => [111, "\xae"], "\xf1" => [115, "\xae"], "\xf2" => [116, "\xae"], "\xf3" => [118, "\xae"], "\xf4" => [119, "\xae"], "\xf5" => [122, "\xae"], "\xf6" => [123, "\xae"], "\xf7" => [125, "\xae"], "\xf8" => [126, "\xae"], "\xf9" => [129, "\xae"], "\xfa" => [143, "\xae"], "\xfb" => [148, "\xae"], "\xfc" => [151, "\xae"], "\xfd" => [153, "\xae"], "\xfe" => [83, "\xae"], "\xff" => [10, "\xae"]], ["\x00" => [0, "\xa50"], "\x01" => [0, "\xa51"], "\x02" => [0, "\xa52"], "\x03" => [0, "\xa5a"], "\x04" => [0, "\xa5c"], "\x05" => [0, "\xa5e"], "\x06" => [0, "\xa5i"], "\x07" => [0, "\xa5o"], "\x08" => [0, "\xa5s"], "\t" => [0, "\xa5t"], "\n" => [73, "\xa5"], "\v" => [88, "\xa5"], "\f" => [89, "\xa5"], "\r" => [96, "\xa5"], "\x0e" => [97, "\xa5"], "\x0f" => [99, "\xa5"], "\x10" => [106, "\xa5"], "\x11" => [136, "\xa5"], "\x12" => [139, "\xa5"], "\x13" => [141, "\xa5"], "\x14" => [145, "\xa5"], "\x15" => [147, "\xa5"], "\x16" => [149, "\xa5"], "\x17" => [101, "\xa5"], "\x18" => [112, "\xa5"], "\x19" => [117, "\xa5"], "\x1a" => [120, "\xa5"], "\x1b" => [124, "\xa5"], "\x1c" => [127, "\xa5"], "\x1d" => [144, "\xa5"], "\x1e" => [152, "\xa5"], "\x1f" => [11, "\xa5"], " " => [0, "\xa60"], "!" => [0, "\xa61"], "\"" => [0, "\xa62"], "#" => [0, "\xa6a"], "\$" => [0, "\xa6c"], "%" => [0, "\xa6e"], "&" => [0, "\xa6i"], "'" => [0, "\xa6o"], "(" => [0, "\xa6s"], ")" => [0, "\xa6t"], "*" => [73, "\xa6"], "+" => [88, "\xa6"], "," => [89, "\xa6"], "-" => [96, "\xa6"], "." => [97, "\xa6"], "/" => [99, "\xa6"], [106, "\xa6"], [136, "\xa6"], [139, "\xa6"], [141, "\xa6"], [145, "\xa6"], [147, "\xa6"], [149, "\xa6"], [101, "\xa6"], [112, "\xa6"], [117, "\xa6"], ":" => [120, "\xa6"], ";" => [124, "\xa6"], "<" => [127, "\xa6"], "=" => [144, "\xa6"], ">" => [152, "\xa6"], "?" => [11, "\xa6"], "@" => [0, "\xa80"], "A" => [0, "\xa81"], "B" => [0, "\xa82"], "C" => [0, "\xa8a"], "D" => [0, "\xa8c"], "E" => [0, "\xa8e"], "F" => [0, "\xa8i"], "G" => [0, "\xa8o"], "H" => [0, "\xa8s"], "I" => [0, "\xa8t"], "J" => [73, "\xa8"], "K" => [88, "\xa8"], "L" => [89, "\xa8"], "M" => [96, "\xa8"], "N" => [97, "\xa8"], "O" => [99, "\xa8"], "P" => [106, "\xa8"], "Q" => [136, "\xa8"], "R" => [139, "\xa8"], "S" => [141, "\xa8"], "T" => [145, "\xa8"], "U" => [147, "\xa8"], "V" => [149, "\xa8"], "W" => [101, "\xa8"], "X" => [112, "\xa8"], "Y" => [117, "\xa8"], "Z" => [120, "\xa8"], "[" => [124, "\xa8"], "\\" => [127, "\xa8"], "]" => [144, "\xa8"], "^" => [152, "\xa8"], "_" => [11, "\xa8"], "`" => [0, "\xae0"], "a" => [0, "\xae1"], "b" => [0, "\xae2"], "c" => [0, "\xaea"], "d" => [0, "\xaec"], "e" => [0, "\xaee"], "f" => [0, "\xaei"], "g" => [0, "\xaeo"], "h" => [0, "\xaes"], "i" => [0, "\xaet"], "j" => [73, "\xae"], "k" => [88, "\xae"], "l" => [89, "\xae"], "m" => [96, "\xae"], "n" => [97, "\xae"], "o" => [99, "\xae"], "p" => [106, "\xae"], "q" => [136, "\xae"], "r" => [139, "\xae"], "s" => [141, "\xae"], "t" => [145, "\xae"], "u" => [147, "\xae"], "v" => [149, "\xae"], "w" => [101, "\xae"], "x" => [112, "\xae"], "y" => [117, "\xae"], "z" => [120, "\xae"], "{" => [124, "\xae"], "|" => [127, "\xae"], "}" => [144, "\xae"], "~" => [152, "\xae"], "" => [11, "\xae"], "\x80" => [0, "\xaf0"], "\x81" => [0, "\xaf1"], "\x82" => [0, "\xaf2"], "\x83" => [0, "\xafa"], "\x84" => [0, "\xafc"], "\x85" => [0, "\xafe"], "\x86" => [0, "\xafi"], "\x87" => [0, "\xafo"], "\x88" => [0, "\xafs"], "\x89" => [0, "\xaft"], "\x8a" => [73, "\xaf"], "\x8b" => [88, "\xaf"], "\x8c" => [89, "\xaf"], "\x8d" => [96, "\xaf"], "\x8e" => [97, "\xaf"], "\x8f" => [99, "\xaf"], "\x90" => [106, "\xaf"], "\x91" => [136, "\xaf"], "\x92" => [139, "\xaf"], "\x93" => [141, "\xaf"], "\x94" => [145, "\xaf"], "\x95" => [147, "\xaf"], "\x96" => [149, "\xaf"], "\x97" => [101, "\xaf"], "\x98" => [112, "\xaf"], "\x99" => [117, "\xaf"], "\x9a" => [120, "\xaf"], "\x9b" => [124, "\xaf"], "\x9c" => [127, "\xaf"], "\x9d" => [144, "\xaf"], "\x9e" => [152, "\xaf"], "\x9f" => [11, "\xaf"], "\xa0" => [0, "\xb40"], "\xa1" => [0, "\xb41"], "\xa2" => [0, "\xb42"], "\xa3" => [0, "\xb4a"], "\xa4" => [0, "\xb4c"], "\xa5" => [0, "\xb4e"], "\xa6" => [0, "\xb4i"], "\xa7" => [0, "\xb4o"], "\xa8" => [0, "\xb4s"], "\xa9" => [0, "\xb4t"], "\xaa" => [73, "\xb4"], "\xab" => [88, "\xb4"], "\xac" => [89, "\xb4"], "\xad" => [96, "\xb4"], "\xae" => [97, "\xb4"], "\xaf" => [99, "\xb4"], "\xb0" => [106, "\xb4"], "\xb1" => [136, "\xb4"], "\xb2" => [139, "\xb4"], "\xb3" => [141, "\xb4"], "\xb4" => [145, "\xb4"], "\xb5" => [147, "\xb4"], "\xb6" => [149, "\xb4"], "\xb7" => [101, "\xb4"], "\xb8" => [112, "\xb4"], "\xb9" => [117, "\xb4"], "\xba" => [120, "\xb4"], "\xbb" => [124, "\xb4"], "\xbc" => [127, "\xb4"], "\xbd" => [144, "\xb4"], "\xbe" => [152, "\xb4"], "\xbf" => [11, "\xb4"], "\xc0" => [0, "\xb60"], "\xc1" => [0, "\xb61"], "\xc2" => [0, "\xb62"], "\xc3" => [0, "\xb6a"], "\xc4" => [0, "\xb6c"], "\xc5" => [0, "\xb6e"], "\xc6" => [0, "\xb6i"], "\xc7" => [0, "\xb6o"], "\xc8" => [0, "\xb6s"], "\xc9" => [0, "\xb6t"], "\xca" => [73, "\xb6"], "\xcb" => [88, "\xb6"], "\xcc" => [89, "\xb6"], "\xcd" => [96, "\xb6"], "\xce" => [97, "\xb6"], "\xcf" => [99, "\xb6"], "\xd0" => [106, "\xb6"], "\xd1" => [136, "\xb6"], "\xd2" => [139, "\xb6"], "\xd3" => [141, "\xb6"], "\xd4" => [145, "\xb6"], "\xd5" => [147, "\xb6"], "\xd6" => [149, "\xb6"], "\xd7" => [101, "\xb6"], "\xd8" => [112, "\xb6"], "\xd9" => [117, "\xb6"], "\xda" => [120, "\xb6"], "\xdb" => [124, "\xb6"], "\xdc" => [127, "\xb6"], "\xdd" => [144, "\xb6"], "\xde" => [152, "\xb6"], "\xdf" => [11, "\xb6"], "\xe0" => [0, "\xb70"], "\xe1" => [0, "\xb71"], "\xe2" => [0, "\xb72"], "\xe3" => [0, "\xb7a"], "\xe4" => [0, "\xb7c"], "\xe5" => [0, "\xb7e"], "\xe6" => [0, "\xb7i"], "\xe7" => [0, "\xb7o"], "\xe8" => [0, "\xb7s"], "\xe9" => [0, "\xb7t"], "\xea" => [73, "\xb7"], "\xeb" => [88, "\xb7"], "\xec" => [89, "\xb7"], "\xed" => [96, "\xb7"], "\xee" => [97, "\xb7"], "\xef" => [99, "\xb7"], "\xf0" => [106, "\xb7"], "\xf1" => [136, "\xb7"], "\xf2" => [139, "\xb7"], "\xf3" => [141, "\xb7"], "\xf4" => [145, "\xb7"], "\xf5" => [147, "\xb7"], "\xf6" => [149, "\xb7"], "\xf7" => [101, "\xb7"], "\xf8" => [112, "\xb7"], "\xf9" => [117, "\xb7"], "\xfa" => [120, "\xb7"], "\xfb" => [124, "\xb7"], "\xfc" => [127, "\xb7"], "\xfd" => [144, "\xb7"], "\xfe" => [152, "\xb7"], "\xff" => [11, "\xb7"]], ["\x00" => [94, "\xa70"], "\x01" => [76, "\xa70"], "\x02" => [104, "\xa70"], "\x03" => [16, "\xa70"], "\x04" => [94, "\xa71"], "\x05" => [76, "\xa71"], "\x06" => [104, "\xa71"], "\x07" => [16, "\xa71"], "\x08" => [94, "\xa72"], "\t" => [76, "\xa72"], "\n" => [104, "\xa72"], "\v" => [16, "\xa72"], "\f" => [94, "\xa7a"], "\r" => [76, "\xa7a"], "\x0e" => [104, "\xa7a"], "\x0f" => [16, "\xa7a"], "\x10" => [94, "\xa7c"], "\x11" => [76, "\xa7c"], "\x12" => [104, "\xa7c"], "\x13" => [16, "\xa7c"], "\x14" => [94, "\xa7e"], "\x15" => [76, "\xa7e"], "\x16" => [104, "\xa7e"], "\x17" => [16, "\xa7e"], "\x18" => [94, "\xa7i"], "\x19" => [76, "\xa7i"], "\x1a" => [104, "\xa7i"], "\x1b" => [16, "\xa7i"], "\x1c" => [94, "\xa7o"], "\x1d" => [76, "\xa7o"], "\x1e" => [104, "\xa7o"], "\x1f" => [16, "\xa7o"], " " => [94, "\xa7s"], "!" => [76, "\xa7s"], "\"" => [104, "\xa7s"], "#" => [16, "\xa7s"], "\$" => [94, "\xa7t"], "%" => [76, "\xa7t"], "&" => [104, "\xa7t"], "'" => [16, "\xa7t"], "(" => [77, "\xa7 "], ")" => [18, "\xa7 "], "*" => [77, "\xa7%"], "+" => [18, "\xa7%"], "," => [77, "\xa7-"], "-" => [18, "\xa7-"], "." => [77, "\xa7."], "/" => [18, "\xa7."], [77, "\xa7/"], [18, "\xa7/"], [77, "\xa73"], [18, "\xa73"], [77, "\xa74"], [18, "\xa74"], [77, "\xa75"], [18, "\xa75"], [77, "\xa76"], [18, "\xa76"], ":" => [77, "\xa77"], ";" => [18, "\xa77"], "<" => [77, "\xa78"], "=" => [18, "\xa78"], ">" => [77, "\xa79"], "?" => [18, "\xa79"], "@" => [77, "\xa7="], "A" => [18, "\xa7="], "B" => [77, "\xa7A"], "C" => [18, "\xa7A"], "D" => [77, "\xa7_"], "E" => [18, "\xa7_"], "F" => [77, "\xa7b"], "G" => [18, "\xa7b"], "H" => [77, "\xa7d"], "I" => [18, "\xa7d"], "J" => [77, "\xa7f"], "K" => [18, "\xa7f"], "L" => [77, "\xa7g"], "M" => [18, "\xa7g"], "N" => [77, "\xa7h"], "O" => [18, "\xa7h"], "P" => [77, "\xa7l"], "Q" => [18, "\xa7l"], "R" => [77, "\xa7m"], "S" => [18, "\xa7m"], "T" => [77, "\xa7n"], "U" => [18, "\xa7n"], "V" => [77, "\xa7p"], "W" => [18, "\xa7p"], "X" => [77, "\xa7r"], "Y" => [18, "\xa7r"], "Z" => [77, "\xa7u"], "[" => [18, "\xa7u"], "\\" => [0, "\xa7:"], "]" => [0, "\xa7B"], "^" => [0, "\xa7C"], "_" => [0, "\xa7D"], "`" => [0, "\xa7E"], "a" => [0, "\xa7F"], "b" => [0, "\xa7G"], "c" => [0, "\xa7H"], "d" => [0, "\xa7I"], "e" => [0, "\xa7J"], "f" => [0, "\xa7K"], "g" => [0, "\xa7L"], "h" => [0, "\xa7M"], "i" => [0, "\xa7N"], "j" => [0, "\xa7O"], "k" => [0, "\xa7P"], "l" => [0, "\xa7Q"], "m" => [0, "\xa7R"], "n" => [0, "\xa7S"], "o" => [0, "\xa7T"], "p" => [0, "\xa7U"], "q" => [0, "\xa7V"], "r" => [0, "\xa7W"], "s" => [0, "\xa7Y"], "t" => [0, "\xa7j"], "u" => [0, "\xa7k"], "v" => [0, "\xa7q"], "w" => [0, "\xa7v"], "x" => [0, "\xa7w"], "y" => [0, "\xa7x"], "z" => [0, "\xa7y"], "{" => [0, "\xa7z"], "|" => [82, "\xa7"], "}" => [87, "\xa7"], "~" => [130, "\xa7"], "" => [9, "\xa7"], "\x80" => [94, "\xac0"], "\x81" => [76, "\xac0"], "\x82" => [104, "\xac0"], "\x83" => [16, "\xac0"], "\x84" => [94, "\xac1"], "\x85" => [76, "\xac1"], "\x86" => [104, "\xac1"], "\x87" => [16, "\xac1"], "\x88" => [94, "\xac2"], "\x89" => [76, "\xac2"], "\x8a" => [104, "\xac2"], "\x8b" => [16, "\xac2"], "\x8c" => [94, "\xaca"], "\x8d" => [76, "\xaca"], "\x8e" => [104, "\xaca"], "\x8f" => [16, "\xaca"], "\x90" => [94, "\xacc"], "\x91" => [76, "\xacc"], "\x92" => [104, "\xacc"], "\x93" => [16, "\xacc"], "\x94" => [94, "\xace"], "\x95" => [76, "\xace"], "\x96" => [104, "\xace"], "\x97" => [16, "\xace"], "\x98" => [94, "\xaci"], "\x99" => [76, "\xaci"], "\x9a" => [104, "\xaci"], "\x9b" => [16, "\xaci"], "\x9c" => [94, "\xaco"], "\x9d" => [76, "\xaco"], "\x9e" => [104, "\xaco"], "\x9f" => [16, "\xaco"], "\xa0" => [94, "\xacs"], "\xa1" => [76, "\xacs"], "\xa2" => [104, "\xacs"], "\xa3" => [16, "\xacs"], "\xa4" => [94, "\xact"], "\xa5" => [76, "\xact"], "\xa6" => [104, "\xact"], "\xa7" => [16, "\xact"], "\xa8" => [77, "\xac "], "\xa9" => [18, "\xac "], "\xaa" => [77, "\xac%"], "\xab" => [18, "\xac%"], "\xac" => [77, "\xac-"], "\xad" => [18, "\xac-"], "\xae" => [77, "\xac."], "\xaf" => [18, "\xac."], "\xb0" => [77, "\xac/"], "\xb1" => [18, "\xac/"], "\xb2" => [77, "\xac3"], "\xb3" => [18, "\xac3"], "\xb4" => [77, "\xac4"], "\xb5" => [18, "\xac4"], "\xb6" => [77, "\xac5"], "\xb7" => [18, "\xac5"], "\xb8" => [77, "\xac6"], "\xb9" => [18, "\xac6"], "\xba" => [77, "\xac7"], "\xbb" => [18, "\xac7"], "\xbc" => [77, "\xac8"], "\xbd" => [18, "\xac8"], "\xbe" => [77, "\xac9"], "\xbf" => [18, "\xac9"], "\xc0" => [77, "\xac="], "\xc1" => [18, "\xac="], "\xc2" => [77, "\xacA"], "\xc3" => [18, "\xacA"], "\xc4" => [77, "\xac_"], "\xc5" => [18, "\xac_"], "\xc6" => [77, "\xacb"], "\xc7" => [18, "\xacb"], "\xc8" => [77, "\xacd"], "\xc9" => [18, "\xacd"], "\xca" => [77, "\xacf"], "\xcb" => [18, "\xacf"], "\xcc" => [77, "\xacg"], "\xcd" => [18, "\xacg"], "\xce" => [77, "\xach"], "\xcf" => [18, "\xach"], "\xd0" => [77, "\xacl"], "\xd1" => [18, "\xacl"], "\xd2" => [77, "\xacm"], "\xd3" => [18, "\xacm"], "\xd4" => [77, "\xacn"], "\xd5" => [18, "\xacn"], "\xd6" => [77, "\xacp"], "\xd7" => [18, "\xacp"], "\xd8" => [77, "\xacr"], "\xd9" => [18, "\xacr"], "\xda" => [77, "\xacu"], "\xdb" => [18, "\xacu"], "\xdc" => [0, "\xac:"], "\xdd" => [0, "\xacB"], "\xde" => [0, "\xacC"], "\xdf" => [0, "\xacD"], "\xe0" => [0, "\xacE"], "\xe1" => [0, "\xacF"], "\xe2" => [0, "\xacG"], "\xe3" => [0, "\xacH"], "\xe4" => [0, "\xacI"], "\xe5" => [0, "\xacJ"], "\xe6" => [0, "\xacK"], "\xe7" => [0, "\xacL"], "\xe8" => [0, "\xacM"], "\xe9" => [0, "\xacN"], "\xea" => [0, "\xacO"], "\xeb" => [0, "\xacP"], "\xec" => [0, "\xacQ"], "\xed" => [0, "\xacR"], "\xee" => [0, "\xacS"], "\xef" => [0, "\xacT"], "\xf0" => [0, "\xacU"], "\xf1" => [0, "\xacV"], "\xf2" => [0, "\xacW"], "\xf3" => [0, "\xacY"], "\xf4" => [0, "\xacj"], "\xf5" => [0, "\xack"], "\xf6" => [0, "\xacq"], "\xf7" => [0, "\xacv"], "\xf8" => [0, "\xacw"], "\xf9" => [0, "\xacx"], "\xfa" => [0, "\xacy"], "\xfb" => [0, "\xacz"], "\xfc" => [82, "\xac"], "\xfd" => [87, "\xac"], "\xfe" => [130, "\xac"], "\xff" => [9, "\xac"]], ["\x00" => [94, "\xa80"], "\x01" => [76, "\xa80"], "\x02" => [104, "\xa80"], "\x03" => [16, "\xa80"], "\x04" => [94, "\xa81"], "\x05" => [76, "\xa81"], "\x06" => [104, "\xa81"], "\x07" => [16, "\xa81"], "\x08" => [94, "\xa82"], "\t" => [76, "\xa82"], "\n" => [104, "\xa82"], "\v" => [16, "\xa82"], "\f" => [94, "\xa8a"], "\r" => [76, "\xa8a"], "\x0e" => [104, "\xa8a"], "\x0f" => [16, "\xa8a"], "\x10" => [94, "\xa8c"], "\x11" => [76, "\xa8c"], "\x12" => [104, "\xa8c"], "\x13" => [16, "\xa8c"], "\x14" => [94, "\xa8e"], "\x15" => [76, "\xa8e"], "\x16" => [104, "\xa8e"], "\x17" => [16, "\xa8e"], "\x18" => [94, "\xa8i"], "\x19" => [76, "\xa8i"], "\x1a" => [104, "\xa8i"], "\x1b" => [16, "\xa8i"], "\x1c" => [94, "\xa8o"], "\x1d" => [76, "\xa8o"], "\x1e" => [104, "\xa8o"], "\x1f" => [16, "\xa8o"], " " => [94, "\xa8s"], "!" => [76, "\xa8s"], "\"" => [104, "\xa8s"], "#" => [16, "\xa8s"], "\$" => [94, "\xa8t"], "%" => [76, "\xa8t"], "&" => [104, "\xa8t"], "'" => [16, "\xa8t"], "(" => [77, "\xa8 "], ")" => [18, "\xa8 "], "*" => [77, "\xa8%"], "+" => [18, "\xa8%"], "," => [77, "\xa8-"], "-" => [18, "\xa8-"], "." => [77, "\xa8."], "/" => [18, "\xa8."], [77, "\xa8/"], [18, "\xa8/"], [77, "\xa83"], [18, "\xa83"], [77, "\xa84"], [18, "\xa84"], [77, "\xa85"], [18, "\xa85"], [77, "\xa86"], [18, "\xa86"], ":" => [77, "\xa87"], ";" => [18, "\xa87"], "<" => [77, "\xa88"], "=" => [18, "\xa88"], ">" => [77, "\xa89"], "?" => [18, "\xa89"], "@" => [77, "\xa8="], "A" => [18, "\xa8="], "B" => [77, "\xa8A"], "C" => [18, "\xa8A"], "D" => [77, "\xa8_"], "E" => [18, "\xa8_"], "F" => [77, "\xa8b"], "G" => [18, "\xa8b"], "H" => [77, "\xa8d"], "I" => [18, "\xa8d"], "J" => [77, "\xa8f"], "K" => [18, "\xa8f"], "L" => [77, "\xa8g"], "M" => [18, "\xa8g"], "N" => [77, "\xa8h"], "O" => [18, "\xa8h"], "P" => [77, "\xa8l"], "Q" => [18, "\xa8l"], "R" => [77, "\xa8m"], "S" => [18, "\xa8m"], "T" => [77, "\xa8n"], "U" => [18, "\xa8n"], "V" => [77, "\xa8p"], "W" => [18, "\xa8p"], "X" => [77, "\xa8r"], "Y" => [18, "\xa8r"], "Z" => [77, "\xa8u"], "[" => [18, "\xa8u"], "\\" => [0, "\xa8:"], "]" => [0, "\xa8B"], "^" => [0, "\xa8C"], "_" => [0, "\xa8D"], "`" => [0, "\xa8E"], "a" => [0, "\xa8F"], "b" => [0, "\xa8G"], "c" => [0, "\xa8H"], "d" => [0, "\xa8I"], "e" => [0, "\xa8J"], "f" => [0, "\xa8K"], "g" => [0, "\xa8L"], "h" => [0, "\xa8M"], "i" => [0, "\xa8N"], "j" => [0, "\xa8O"], "k" => [0, "\xa8P"], "l" => [0, "\xa8Q"], "m" => [0, "\xa8R"], "n" => [0, "\xa8S"], "o" => [0, "\xa8T"], "p" => [0, "\xa8U"], "q" => [0, "\xa8V"], "r" => [0, "\xa8W"], "s" => [0, "\xa8Y"], "t" => [0, "\xa8j"], "u" => [0, "\xa8k"], "v" => [0, "\xa8q"], "w" => [0, "\xa8v"], "x" => [0, "\xa8w"], "y" => [0, "\xa8x"], "z" => [0, "\xa8y"], "{" => [0, "\xa8z"], "|" => [82, "\xa8"], "}" => [87, "\xa8"], "~" => [130, "\xa8"], "" => [9, "\xa8"], "\x80" => [94, "\xae0"], "\x81" => [76, "\xae0"], "\x82" => [104, "\xae0"], "\x83" => [16, "\xae0"], "\x84" => [94, "\xae1"], "\x85" => [76, "\xae1"], "\x86" => [104, "\xae1"], "\x87" => [16, "\xae1"], "\x88" => [94, "\xae2"], "\x89" => [76, "\xae2"], "\x8a" => [104, "\xae2"], "\x8b" => [16, "\xae2"], "\x8c" => [94, "\xaea"], "\x8d" => [76, "\xaea"], "\x8e" => [104, "\xaea"], "\x8f" => [16, "\xaea"], "\x90" => [94, "\xaec"], "\x91" => [76, "\xaec"], "\x92" => [104, "\xaec"], "\x93" => [16, "\xaec"], "\x94" => [94, "\xaee"], "\x95" => [76, "\xaee"], "\x96" => [104, "\xaee"], "\x97" => [16, "\xaee"], "\x98" => [94, "\xaei"], "\x99" => [76, "\xaei"], "\x9a" => [104, "\xaei"], "\x9b" => [16, "\xaei"], "\x9c" => [94, "\xaeo"], "\x9d" => [76, "\xaeo"], "\x9e" => [104, "\xaeo"], "\x9f" => [16, "\xaeo"], "\xa0" => [94, "\xaes"], "\xa1" => [76, "\xaes"], "\xa2" => [104, "\xaes"], "\xa3" => [16, "\xaes"], "\xa4" => [94, "\xaet"], "\xa5" => [76, "\xaet"], "\xa6" => [104, "\xaet"], "\xa7" => [16, "\xaet"], "\xa8" => [77, "\xae "], "\xa9" => [18, "\xae "], "\xaa" => [77, "\xae%"], "\xab" => [18, "\xae%"], "\xac" => [77, "\xae-"], "\xad" => [18, "\xae-"], "\xae" => [77, "\xae."], "\xaf" => [18, "\xae."], "\xb0" => [77, "\xae/"], "\xb1" => [18, "\xae/"], "\xb2" => [77, "\xae3"], "\xb3" => [18, "\xae3"], "\xb4" => [77, "\xae4"], "\xb5" => [18, "\xae4"], "\xb6" => [77, "\xae5"], "\xb7" => [18, "\xae5"], "\xb8" => [77, "\xae6"], "\xb9" => [18, "\xae6"], "\xba" => [77, "\xae7"], "\xbb" => [18, "\xae7"], "\xbc" => [77, "\xae8"], "\xbd" => [18, "\xae8"], "\xbe" => [77, "\xae9"], "\xbf" => [18, "\xae9"], "\xc0" => [77, "\xae="], "\xc1" => [18, "\xae="], "\xc2" => [77, "\xaeA"], "\xc3" => [18, "\xaeA"], "\xc4" => [77, "\xae_"], "\xc5" => [18, "\xae_"], "\xc6" => [77, "\xaeb"], "\xc7" => [18, "\xaeb"], "\xc8" => [77, "\xaed"], "\xc9" => [18, "\xaed"], "\xca" => [77, "\xaef"], "\xcb" => [18, "\xaef"], "\xcc" => [77, "\xaeg"], "\xcd" => [18, "\xaeg"], "\xce" => [77, "\xaeh"], "\xcf" => [18, "\xaeh"], "\xd0" => [77, "\xael"], "\xd1" => [18, "\xael"], "\xd2" => [77, "\xaem"], "\xd3" => [18, "\xaem"], "\xd4" => [77, "\xaen"], "\xd5" => [18, "\xaen"], "\xd6" => [77, "\xaep"], "\xd7" => [18, "\xaep"], "\xd8" => [77, "\xaer"], "\xd9" => [18, "\xaer"], "\xda" => [77, "\xaeu"], "\xdb" => [18, "\xaeu"], "\xdc" => [0, "\xae:"], "\xdd" => [0, "\xaeB"], "\xde" => [0, "\xaeC"], "\xdf" => [0, "\xaeD"], "\xe0" => [0, "\xaeE"], "\xe1" => [0, "\xaeF"], "\xe2" => [0, "\xaeG"], "\xe3" => [0, "\xaeH"], "\xe4" => [0, "\xaeI"], "\xe5" => [0, "\xaeJ"], "\xe6" => [0, "\xaeK"], "\xe7" => [0, "\xaeL"], "\xe8" => [0, "\xaeM"], "\xe9" => [0, "\xaeN"], "\xea" => [0, "\xaeO"], "\xeb" => [0, "\xaeP"], "\xec" => [0, "\xaeQ"], "\xed" => [0, "\xaeR"], "\xee" => [0, "\xaeS"], "\xef" => [0, "\xaeT"], "\xf0" => [0, "\xaeU"], "\xf1" => [0, "\xaeV"], "\xf2" => [0, "\xaeW"], "\xf3" => [0, "\xaeY"], "\xf4" => [0, "\xaej"], "\xf5" => [0, "\xaek"], "\xf6" => [0, "\xaeq"], "\xf7" => [0, "\xaev"], "\xf8" => [0, "\xaew"], "\xf9" => [0, "\xaex"], "\xfa" => [0, "\xaey"], "\xfb" => [0, "\xaez"], "\xfc" => [82, "\xae"], "\xfd" => [87, "\xae"], "\xfe" => [130, "\xae"], "\xff" => [9, "\xae"]], ["\x00" => [94, "\xaa0"], "\x01" => [76, "\xaa0"], "\x02" => [104, "\xaa0"], "\x03" => [16, "\xaa0"], "\x04" => [94, "\xaa1"], "\x05" => [76, "\xaa1"], "\x06" => [104, "\xaa1"], "\x07" => [16, "\xaa1"], "\x08" => [94, "\xaa2"], "\t" => [76, "\xaa2"], "\n" => [104, "\xaa2"], "\v" => [16, "\xaa2"], "\f" => [94, "\xaaa"], "\r" => [76, "\xaaa"], "\x0e" => [104, "\xaaa"], "\x0f" => [16, "\xaaa"], "\x10" => [94, "\xaac"], "\x11" => [76, "\xaac"], "\x12" => [104, "\xaac"], "\x13" => [16, "\xaac"], "\x14" => [94, "\xaae"], "\x15" => [76, "\xaae"], "\x16" => [104, "\xaae"], "\x17" => [16, "\xaae"], "\x18" => [94, "\xaai"], "\x19" => [76, "\xaai"], "\x1a" => [104, "\xaai"], "\x1b" => [16, "\xaai"], "\x1c" => [94, "\xaao"], "\x1d" => [76, "\xaao"], "\x1e" => [104, "\xaao"], "\x1f" => [16, "\xaao"], " " => [94, "\xaas"], "!" => [76, "\xaas"], "\"" => [104, "\xaas"], "#" => [16, "\xaas"], "\$" => [94, "\xaat"], "%" => [76, "\xaat"], "&" => [104, "\xaat"], "'" => [16, "\xaat"], "(" => [77, "\xaa "], ")" => [18, "\xaa "], "*" => [77, "\xaa%"], "+" => [18, "\xaa%"], "," => [77, "\xaa-"], "-" => [18, "\xaa-"], "." => [77, "\xaa."], "/" => [18, "\xaa."], [77, "\xaa/"], [18, "\xaa/"], [77, "\xaa3"], [18, "\xaa3"], [77, "\xaa4"], [18, "\xaa4"], [77, "\xaa5"], [18, "\xaa5"], [77, "\xaa6"], [18, "\xaa6"], ":" => [77, "\xaa7"], ";" => [18, "\xaa7"], "<" => [77, "\xaa8"], "=" => [18, "\xaa8"], ">" => [77, "\xaa9"], "?" => [18, "\xaa9"], "@" => [77, "\xaa="], "A" => [18, "\xaa="], "B" => [77, "\xaaA"], "C" => [18, "\xaaA"], "D" => [77, "\xaa_"], "E" => [18, "\xaa_"], "F" => [77, "\xaab"], "G" => [18, "\xaab"], "H" => [77, "\xaad"], "I" => [18, "\xaad"], "J" => [77, "\xaaf"], "K" => [18, "\xaaf"], "L" => [77, "\xaag"], "M" => [18, "\xaag"], "N" => [77, "\xaah"], "O" => [18, "\xaah"], "P" => [77, "\xaal"], "Q" => [18, "\xaal"], "R" => [77, "\xaam"], "S" => [18, "\xaam"], "T" => [77, "\xaan"], "U" => [18, "\xaan"], "V" => [77, "\xaap"], "W" => [18, "\xaap"], "X" => [77, "\xaar"], "Y" => [18, "\xaar"], "Z" => [77, "\xaau"], "[" => [18, "\xaau"], "\\" => [0, "\xaa:"], "]" => [0, "\xaaB"], "^" => [0, "\xaaC"], "_" => [0, "\xaaD"], "`" => [0, "\xaaE"], "a" => [0, "\xaaF"], "b" => [0, "\xaaG"], "c" => [0, "\xaaH"], "d" => [0, "\xaaI"], "e" => [0, "\xaaJ"], "f" => [0, "\xaaK"], "g" => [0, "\xaaL"], "h" => [0, "\xaaM"], "i" => [0, "\xaaN"], "j" => [0, "\xaaO"], "k" => [0, "\xaaP"], "l" => [0, "\xaaQ"], "m" => [0, "\xaaR"], "n" => [0, "\xaaS"], "o" => [0, "\xaaT"], "p" => [0, "\xaaU"], "q" => [0, "\xaaV"], "r" => [0, "\xaaW"], "s" => [0, "\xaaY"], "t" => [0, "\xaaj"], "u" => [0, "\xaak"], "v" => [0, "\xaaq"], "w" => [0, "\xaav"], "x" => [0, "\xaaw"], "y" => [0, "\xaax"], "z" => [0, "\xaay"], "{" => [0, "\xaaz"], "|" => [82, "\xaa"], "}" => [87, "\xaa"], "~" => [130, "\xaa"], "" => [9, "\xaa"], "\x80" => [94, "\xad0"], "\x81" => [76, "\xad0"], "\x82" => [104, "\xad0"], "\x83" => [16, "\xad0"], "\x84" => [94, "\xad1"], "\x85" => [76, "\xad1"], "\x86" => [104, "\xad1"], "\x87" => [16, "\xad1"], "\x88" => [94, "\xad2"], "\x89" => [76, "\xad2"], "\x8a" => [104, "\xad2"], "\x8b" => [16, "\xad2"], "\x8c" => [94, "\xada"], "\x8d" => [76, "\xada"], "\x8e" => [104, "\xada"], "\x8f" => [16, "\xada"], "\x90" => [94, "\xadc"], "\x91" => [76, "\xadc"], "\x92" => [104, "\xadc"], "\x93" => [16, "\xadc"], "\x94" => [94, "\xade"], "\x95" => [76, "\xade"], "\x96" => [104, "\xade"], "\x97" => [16, "\xade"], "\x98" => [94, "\xadi"], "\x99" => [76, "\xadi"], "\x9a" => [104, "\xadi"], "\x9b" => [16, "\xadi"], "\x9c" => [94, "\xado"], "\x9d" => [76, "\xado"], "\x9e" => [104, "\xado"], "\x9f" => [16, "\xado"], "\xa0" => [94, "\xads"], "\xa1" => [76, "\xads"], "\xa2" => [104, "\xads"], "\xa3" => [16, "\xads"], "\xa4" => [94, "\xadt"], "\xa5" => [76, "\xadt"], "\xa6" => [104, "\xadt"], "\xa7" => [16, "\xadt"], "\xa8" => [77, "\xad "], "\xa9" => [18, "\xad "], "\xaa" => [77, "\xad%"], "\xab" => [18, "\xad%"], "\xac" => [77, "\xad-"], "\xad" => [18, "\xad-"], "\xae" => [77, "\xad."], "\xaf" => [18, "\xad."], "\xb0" => [77, "\xad/"], "\xb1" => [18, "\xad/"], "\xb2" => [77, "\xad3"], "\xb3" => [18, "\xad3"], "\xb4" => [77, "\xad4"], "\xb5" => [18, "\xad4"], "\xb6" => [77, "\xad5"], "\xb7" => [18, "\xad5"], "\xb8" => [77, "\xad6"], "\xb9" => [18, "\xad6"], "\xba" => [77, "\xad7"], "\xbb" => [18, "\xad7"], "\xbc" => [77, "\xad8"], "\xbd" => [18, "\xad8"], "\xbe" => [77, "\xad9"], "\xbf" => [18, "\xad9"], "\xc0" => [77, "\xad="], "\xc1" => [18, "\xad="], "\xc2" => [77, "\xadA"], "\xc3" => [18, "\xadA"], "\xc4" => [77, "\xad_"], "\xc5" => [18, "\xad_"], "\xc6" => [77, "\xadb"], "\xc7" => [18, "\xadb"], "\xc8" => [77, "\xadd"], "\xc9" => [18, "\xadd"], "\xca" => [77, "\xadf"], "\xcb" => [18, "\xadf"], "\xcc" => [77, "\xadg"], "\xcd" => [18, "\xadg"], "\xce" => [77, "\xadh"], "\xcf" => [18, "\xadh"], "\xd0" => [77, "\xadl"], "\xd1" => [18, "\xadl"], "\xd2" => [77, "\xadm"], "\xd3" => [18, "\xadm"], "\xd4" => [77, "\xadn"], "\xd5" => [18, "\xadn"], "\xd6" => [77, "\xadp"], "\xd7" => [18, "\xadp"], "\xd8" => [77, "\xadr"], "\xd9" => [18, "\xadr"], "\xda" => [77, "\xadu"], "\xdb" => [18, "\xadu"], "\xdc" => [0, "\xad:"], "\xdd" => [0, "\xadB"], "\xde" => [0, "\xadC"], "\xdf" => [0, "\xadD"], "\xe0" => [0, "\xadE"], "\xe1" => [0, "\xadF"], "\xe2" => [0, "\xadG"], "\xe3" => [0, "\xadH"], "\xe4" => [0, "\xadI"], "\xe5" => [0, "\xadJ"], "\xe6" => [0, "\xadK"], "\xe7" => [0, "\xadL"], "\xe8" => [0, "\xadM"], "\xe9" => [0, "\xadN"], "\xea" => [0, "\xadO"], "\xeb" => [0, "\xadP"], "\xec" => [0, "\xadQ"], "\xed" => [0, "\xadR"], "\xee" => [0, "\xadS"], "\xef" => [0, "\xadT"], "\xf0" => [0, "\xadU"], "\xf1" => [0, "\xadV"], "\xf2" => [0, "\xadW"], "\xf3" => [0, "\xadY"], "\xf4" => [0, "\xadj"], "\xf5" => [0, "\xadk"], "\xf6" => [0, "\xadq"], "\xf7" => [0, "\xadv"], "\xf8" => [0, "\xadw"], "\xf9" => [0, "\xadx"], "\xfa" => [0, "\xady"], "\xfb" => [0, "\xadz"], "\xfc" => [82, "\xad"], "\xfd" => [87, "\xad"], "\xfe" => [130, "\xad"], "\xff" => [9, "\xad"]], ["\x00" => [94, "\xab0"], "\x01" => [76, "\xab0"], "\x02" => [104, "\xab0"], "\x03" => [16, "\xab0"], "\x04" => [94, "\xab1"], "\x05" => [76, "\xab1"], "\x06" => [104, "\xab1"], "\x07" => [16, "\xab1"], "\x08" => [94, "\xab2"], "\t" => [76, "\xab2"], "\n" => [104, "\xab2"], "\v" => [16, "\xab2"], "\f" => [94, "\xaba"], "\r" => [76, "\xaba"], "\x0e" => [104, "\xaba"], "\x0f" => [16, "\xaba"], "\x10" => [94, "\xabc"], "\x11" => [76, "\xabc"], "\x12" => [104, "\xabc"], "\x13" => [16, "\xabc"], "\x14" => [94, "\xabe"], "\x15" => [76, "\xabe"], "\x16" => [104, "\xabe"], "\x17" => [16, "\xabe"], "\x18" => [94, "\xabi"], "\x19" => [76, "\xabi"], "\x1a" => [104, "\xabi"], "\x1b" => [16, "\xabi"], "\x1c" => [94, "\xabo"], "\x1d" => [76, "\xabo"], "\x1e" => [104, "\xabo"], "\x1f" => [16, "\xabo"], " " => [94, "\xabs"], "!" => [76, "\xabs"], "\"" => [104, "\xabs"], "#" => [16, "\xabs"], "\$" => [94, "\xabt"], "%" => [76, "\xabt"], "&" => [104, "\xabt"], "'" => [16, "\xabt"], "(" => [77, "\xab "], ")" => [18, "\xab "], "*" => [77, "\xab%"], "+" => [18, "\xab%"], "," => [77, "\xab-"], "-" => [18, "\xab-"], "." => [77, "\xab."], "/" => [18, "\xab."], [77, "\xab/"], [18, "\xab/"], [77, "\xab3"], [18, "\xab3"], [77, "\xab4"], [18, "\xab4"], [77, "\xab5"], [18, "\xab5"], [77, "\xab6"], [18, "\xab6"], ":" => [77, "\xab7"], ";" => [18, "\xab7"], "<" => [77, "\xab8"], "=" => [18, "\xab8"], ">" => [77, "\xab9"], "?" => [18, "\xab9"], "@" => [77, "\xab="], "A" => [18, "\xab="], "B" => [77, "\xabA"], "C" => [18, "\xabA"], "D" => [77, "\xab_"], "E" => [18, "\xab_"], "F" => [77, "\xabb"], "G" => [18, "\xabb"], "H" => [77, "\xabd"], "I" => [18, "\xabd"], "J" => [77, "\xabf"], "K" => [18, "\xabf"], "L" => [77, "\xabg"], "M" => [18, "\xabg"], "N" => [77, "\xabh"], "O" => [18, "\xabh"], "P" => [77, "\xabl"], "Q" => [18, "\xabl"], "R" => [77, "\xabm"], "S" => [18, "\xabm"], "T" => [77, "\xabn"], "U" => [18, "\xabn"], "V" => [77, "\xabp"], "W" => [18, "\xabp"], "X" => [77, "\xabr"], "Y" => [18, "\xabr"], "Z" => [77, "\xabu"], "[" => [18, "\xabu"], "\\" => [0, "\xab:"], "]" => [0, "\xabB"], "^" => [0, "\xabC"], "_" => [0, "\xabD"], "`" => [0, "\xabE"], "a" => [0, "\xabF"], "b" => [0, "\xabG"], "c" => [0, "\xabH"], "d" => [0, "\xabI"], "e" => [0, "\xabJ"], "f" => [0, "\xabK"], "g" => [0, "\xabL"], "h" => [0, "\xabM"], "i" => [0, "\xabN"], "j" => [0, "\xabO"], "k" => [0, "\xabP"], "l" => [0, "\xabQ"], "m" => [0, "\xabR"], "n" => [0, "\xabS"], "o" => [0, "\xabT"], "p" => [0, "\xabU"], "q" => [0, "\xabV"], "r" => [0, "\xabW"], "s" => [0, "\xabY"], "t" => [0, "\xabj"], "u" => [0, "\xabk"], "v" => [0, "\xabq"], "w" => [0, "\xabv"], "x" => [0, "\xabw"], "y" => [0, "\xabx"], "z" => [0, "\xaby"], "{" => [0, "\xabz"], "|" => [82, "\xab"], "}" => [87, "\xab"], "~" => [130, "\xab"], "" => [9, "\xab"], "\x80" => [94, "\xce0"], "\x81" => [76, "\xce0"], "\x82" => [104, "\xce0"], "\x83" => [16, "\xce0"], "\x84" => [94, "\xce1"], "\x85" => [76, "\xce1"], "\x86" => [104, "\xce1"], "\x87" => [16, "\xce1"], "\x88" => [94, "\xce2"], "\x89" => [76, "\xce2"], "\x8a" => [104, "\xce2"], "\x8b" => [16, "\xce2"], "\x8c" => [94, "\xcea"], "\x8d" => [76, "\xcea"], "\x8e" => [104, "\xcea"], "\x8f" => [16, "\xcea"], "\x90" => [94, "\xcec"], "\x91" => [76, "\xcec"], "\x92" => [104, "\xcec"], "\x93" => [16, "\xcec"], "\x94" => [94, "\xcee"], "\x95" => [76, "\xcee"], "\x96" => [104, "\xcee"], "\x97" => [16, "\xcee"], "\x98" => [94, "\xcei"], "\x99" => [76, "\xcei"], "\x9a" => [104, "\xcei"], "\x9b" => [16, "\xcei"], "\x9c" => [94, "\xceo"], "\x9d" => [76, "\xceo"], "\x9e" => [104, "\xceo"], "\x9f" => [16, "\xceo"], "\xa0" => [94, "\xces"], "\xa1" => [76, "\xces"], "\xa2" => [104, "\xces"], "\xa3" => [16, "\xces"], "\xa4" => [94, "\xcet"], "\xa5" => [76, "\xcet"], "\xa6" => [104, "\xcet"], "\xa7" => [16, "\xcet"], "\xa8" => [77, "\xce "], "\xa9" => [18, "\xce "], "\xaa" => [77, "\xce%"], "\xab" => [18, "\xce%"], "\xac" => [77, "\xce-"], "\xad" => [18, "\xce-"], "\xae" => [77, "\xce."], "\xaf" => [18, "\xce."], "\xb0" => [77, "\xce/"], "\xb1" => [18, "\xce/"], "\xb2" => [77, "\xce3"], "\xb3" => [18, "\xce3"], "\xb4" => [77, "\xce4"], "\xb5" => [18, "\xce4"], "\xb6" => [77, "\xce5"], "\xb7" => [18, "\xce5"], "\xb8" => [77, "\xce6"], "\xb9" => [18, "\xce6"], "\xba" => [77, "\xce7"], "\xbb" => [18, "\xce7"], "\xbc" => [77, "\xce8"], "\xbd" => [18, "\xce8"], "\xbe" => [77, "\xce9"], "\xbf" => [18, "\xce9"], "\xc0" => [77, "\xce="], "\xc1" => [18, "\xce="], "\xc2" => [77, "\xceA"], "\xc3" => [18, "\xceA"], "\xc4" => [77, "\xce_"], "\xc5" => [18, "\xce_"], "\xc6" => [77, "\xceb"], "\xc7" => [18, "\xceb"], "\xc8" => [77, "\xced"], "\xc9" => [18, "\xced"], "\xca" => [77, "\xcef"], "\xcb" => [18, "\xcef"], "\xcc" => [77, "\xceg"], "\xcd" => [18, "\xceg"], "\xce" => [77, "\xceh"], "\xcf" => [18, "\xceh"], "\xd0" => [77, "\xcel"], "\xd1" => [18, "\xcel"], "\xd2" => [77, "\xcem"], "\xd3" => [18, "\xcem"], "\xd4" => [77, "\xcen"], "\xd5" => [18, "\xcen"], "\xd6" => [77, "\xcep"], "\xd7" => [18, "\xcep"], "\xd8" => [77, "\xcer"], "\xd9" => [18, "\xcer"], "\xda" => [77, "\xceu"], "\xdb" => [18, "\xceu"], "\xdc" => [0, "\xce:"], "\xdd" => [0, "\xceB"], "\xde" => [0, "\xceC"], "\xdf" => [0, "\xceD"], "\xe0" => [0, "\xceE"], "\xe1" => [0, "\xceF"], "\xe2" => [0, "\xceG"], "\xe3" => [0, "\xceH"], "\xe4" => [0, "\xceI"], "\xe5" => [0, "\xceJ"], "\xe6" => [0, "\xceK"], "\xe7" => [0, "\xceL"], "\xe8" => [0, "\xceM"], "\xe9" => [0, "\xceN"], "\xea" => [0, "\xceO"], "\xeb" => [0, "\xceP"], "\xec" => [0, "\xceQ"], "\xed" => [0, "\xceR"], "\xee" => [0, "\xceS"], "\xef" => [0, "\xceT"], "\xf0" => [0, "\xceU"], "\xf1" => [0, "\xceV"], "\xf2" => [0, "\xceW"], "\xf3" => [0, "\xceY"], "\xf4" => [0, "\xcej"], "\xf5" => [0, "\xcek"], "\xf6" => [0, "\xceq"], "\xf7" => [0, "\xcev"], "\xf8" => [0, "\xcew"], "\xf9" => [0, "\xcex"], "\xfa" => [0, "\xcey"], "\xfb" => [0, "\xcez"], "\xfc" => [82, "\xce"], "\xfd" => [87, "\xce"], "\xfe" => [130, "\xce"], "\xff" => [9, "\xce"]], ["\x00" => [77, "\xab0"], "\x01" => [18, "\xab0"], "\x02" => [77, "\xab1"], "\x03" => [18, "\xab1"], "\x04" => [77, "\xab2"], "\x05" => [18, "\xab2"], "\x06" => [77, "\xaba"], "\x07" => [18, "\xaba"], "\x08" => [77, "\xabc"], "\t" => [18, "\xabc"], "\n" => [77, "\xabe"], "\v" => [18, "\xabe"], "\f" => [77, "\xabi"], "\r" => [18, "\xabi"], "\x0e" => [77, "\xabo"], "\x0f" => [18, "\xabo"], "\x10" => [77, "\xabs"], "\x11" => [18, "\xabs"], "\x12" => [77, "\xabt"], "\x13" => [18, "\xabt"], "\x14" => [0, "\xab "], "\x15" => [0, "\xab%"], "\x16" => [0, "\xab-"], "\x17" => [0, "\xab."], "\x18" => [0, "\xab/"], "\x19" => [0, "\xab3"], "\x1a" => [0, "\xab4"], "\x1b" => [0, "\xab5"], "\x1c" => [0, "\xab6"], "\x1d" => [0, "\xab7"], "\x1e" => [0, "\xab8"], "\x1f" => [0, "\xab9"], " " => [0, "\xab="], "!" => [0, "\xabA"], "\"" => [0, "\xab_"], "#" => [0, "\xabb"], "\$" => [0, "\xabd"], "%" => [0, "\xabf"], "&" => [0, "\xabg"], "'" => [0, "\xabh"], "(" => [0, "\xabl"], ")" => [0, "\xabm"], "*" => [0, "\xabn"], "+" => [0, "\xabp"], "," => [0, "\xabr"], "-" => [0, "\xabu"], "." => [100, "\xab"], "/" => [110, "\xab"], [111, "\xab"], [115, "\xab"], [116, "\xab"], [118, "\xab"], [119, "\xab"], [122, "\xab"], [123, "\xab"], [125, "\xab"], [126, "\xab"], [129, "\xab"], ":" => [143, "\xab"], ";" => [148, "\xab"], "<" => [151, "\xab"], "=" => [153, "\xab"], ">" => [83, "\xab"], "?" => [10, "\xab"], "@" => [77, "\xce0"], "A" => [18, "\xce0"], "B" => [77, "\xce1"], "C" => [18, "\xce1"], "D" => [77, "\xce2"], "E" => [18, "\xce2"], "F" => [77, "\xcea"], "G" => [18, "\xcea"], "H" => [77, "\xcec"], "I" => [18, "\xcec"], "J" => [77, "\xcee"], "K" => [18, "\xcee"], "L" => [77, "\xcei"], "M" => [18, "\xcei"], "N" => [77, "\xceo"], "O" => [18, "\xceo"], "P" => [77, "\xces"], "Q" => [18, "\xces"], "R" => [77, "\xcet"], "S" => [18, "\xcet"], "T" => [0, "\xce "], "U" => [0, "\xce%"], "V" => [0, "\xce-"], "W" => [0, "\xce."], "X" => [0, "\xce/"], "Y" => [0, "\xce3"], "Z" => [0, "\xce4"], "[" => [0, "\xce5"], "\\" => [0, "\xce6"], "]" => [0, "\xce7"], "^" => [0, "\xce8"], "_" => [0, "\xce9"], "`" => [0, "\xce="], "a" => [0, "\xceA"], "b" => [0, "\xce_"], "c" => [0, "\xceb"], "d" => [0, "\xced"], "e" => [0, "\xcef"], "f" => [0, "\xceg"], "g" => [0, "\xceh"], "h" => [0, "\xcel"], "i" => [0, "\xcem"], "j" => [0, "\xcen"], "k" => [0, "\xcep"], "l" => [0, "\xcer"], "m" => [0, "\xceu"], "n" => [100, "\xce"], "o" => [110, "\xce"], "p" => [111, "\xce"], "q" => [115, "\xce"], "r" => [116, "\xce"], "s" => [118, "\xce"], "t" => [119, "\xce"], "u" => [122, "\xce"], "v" => [123, "\xce"], "w" => [125, "\xce"], "x" => [126, "\xce"], "y" => [129, "\xce"], "z" => [143, "\xce"], "{" => [148, "\xce"], "|" => [151, "\xce"], "}" => [153, "\xce"], "~" => [83, "\xce"], "" => [10, "\xce"], "\x80" => [77, "\xd70"], "\x81" => [18, "\xd70"], "\x82" => [77, "\xd71"], "\x83" => [18, "\xd71"], "\x84" => [77, "\xd72"], "\x85" => [18, "\xd72"], "\x86" => [77, "\xd7a"], "\x87" => [18, "\xd7a"], "\x88" => [77, "\xd7c"], "\x89" => [18, "\xd7c"], "\x8a" => [77, "\xd7e"], "\x8b" => [18, "\xd7e"], "\x8c" => [77, "\xd7i"], "\x8d" => [18, "\xd7i"], "\x8e" => [77, "\xd7o"], "\x8f" => [18, "\xd7o"], "\x90" => [77, "\xd7s"], "\x91" => [18, "\xd7s"], "\x92" => [77, "\xd7t"], "\x93" => [18, "\xd7t"], "\x94" => [0, "\xd7 "], "\x95" => [0, "\xd7%"], "\x96" => [0, "\xd7-"], "\x97" => [0, "\xd7."], "\x98" => [0, "\xd7/"], "\x99" => [0, "\xd73"], "\x9a" => [0, "\xd74"], "\x9b" => [0, "\xd75"], "\x9c" => [0, "\xd76"], "\x9d" => [0, "\xd77"], "\x9e" => [0, "\xd78"], "\x9f" => [0, "\xd79"], "\xa0" => [0, "\xd7="], "\xa1" => [0, "\xd7A"], "\xa2" => [0, "\xd7_"], "\xa3" => [0, "\xd7b"], "\xa4" => [0, "\xd7d"], "\xa5" => [0, "\xd7f"], "\xa6" => [0, "\xd7g"], "\xa7" => [0, "\xd7h"], "\xa8" => [0, "\xd7l"], "\xa9" => [0, "\xd7m"], "\xaa" => [0, "\xd7n"], "\xab" => [0, "\xd7p"], "\xac" => [0, "\xd7r"], "\xad" => [0, "\xd7u"], "\xae" => [100, "\xd7"], "\xaf" => [110, "\xd7"], "\xb0" => [111, "\xd7"], "\xb1" => [115, "\xd7"], "\xb2" => [116, "\xd7"], "\xb3" => [118, "\xd7"], "\xb4" => [119, "\xd7"], "\xb5" => [122, "\xd7"], "\xb6" => [123, "\xd7"], "\xb7" => [125, "\xd7"], "\xb8" => [126, "\xd7"], "\xb9" => [129, "\xd7"], "\xba" => [143, "\xd7"], "\xbb" => [148, "\xd7"], "\xbc" => [151, "\xd7"], "\xbd" => [153, "\xd7"], "\xbe" => [83, "\xd7"], "\xbf" => [10, "\xd7"], "\xc0" => [77, "\xe10"], "\xc1" => [18, "\xe10"], "\xc2" => [77, "\xe11"], "\xc3" => [18, "\xe11"], "\xc4" => [77, "\xe12"], "\xc5" => [18, "\xe12"], "\xc6" => [77, "\xe1a"], "\xc7" => [18, "\xe1a"], "\xc8" => [77, "\xe1c"], "\xc9" => [18, "\xe1c"], "\xca" => [77, "\xe1e"], "\xcb" => [18, "\xe1e"], "\xcc" => [77, "\xe1i"], "\xcd" => [18, "\xe1i"], "\xce" => [77, "\xe1o"], "\xcf" => [18, "\xe1o"], "\xd0" => [77, "\xe1s"], "\xd1" => [18, "\xe1s"], "\xd2" => [77, "\xe1t"], "\xd3" => [18, "\xe1t"], "\xd4" => [0, "\xe1 "], "\xd5" => [0, "\xe1%"], "\xd6" => [0, "\xe1-"], "\xd7" => [0, "\xe1."], "\xd8" => [0, "\xe1/"], "\xd9" => [0, "\xe13"], "\xda" => [0, "\xe14"], "\xdb" => [0, "\xe15"], "\xdc" => [0, "\xe16"], "\xdd" => [0, "\xe17"], "\xde" => [0, "\xe18"], "\xdf" => [0, "\xe19"], "\xe0" => [0, "\xe1="], "\xe1" => [0, "\xe1A"], "\xe2" => [0, "\xe1_"], "\xe3" => [0, "\xe1b"], "\xe4" => [0, "\xe1d"], "\xe5" => [0, "\xe1f"], "\xe6" => [0, "\xe1g"], "\xe7" => [0, "\xe1h"], "\xe8" => [0, "\xe1l"], "\xe9" => [0, "\xe1m"], "\xea" => [0, "\xe1n"], "\xeb" => [0, "\xe1p"], "\xec" => [0, "\xe1r"], "\xed" => [0, "\xe1u"], "\xee" => [100, "\xe1"], "\xef" => [110, "\xe1"], "\xf0" => [111, "\xe1"], "\xf1" => [115, "\xe1"], "\xf2" => [116, "\xe1"], "\xf3" => [118, "\xe1"], "\xf4" => [119, "\xe1"], "\xf5" => [122, "\xe1"], "\xf6" => [123, "\xe1"], "\xf7" => [125, "\xe1"], "\xf8" => [126, "\xe1"], "\xf9" => [129, "\xe1"], "\xfa" => [143, "\xe1"], "\xfb" => [148, "\xe1"], "\xfc" => [151, "\xe1"], "\xfd" => [153, "\xe1"], "\xfe" => [83, "\xe1"], "\xff" => [10, "\xe1"]], ["\x00" => [0, "\xab0"], "\x01" => [0, "\xab1"], "\x02" => [0, "\xab2"], "\x03" => [0, "\xaba"], "\x04" => [0, "\xabc"], "\x05" => [0, "\xabe"], "\x06" => [0, "\xabi"], "\x07" => [0, "\xabo"], "\x08" => [0, "\xabs"], "\t" => [0, "\xabt"], "\n" => [73, "\xab"], "\v" => [88, "\xab"], "\f" => [89, "\xab"], "\r" => [96, "\xab"], "\x0e" => [97, "\xab"], "\x0f" => [99, "\xab"], "\x10" => [106, "\xab"], "\x11" => [136, "\xab"], "\x12" => [139, "\xab"], "\x13" => [141, "\xab"], "\x14" => [145, "\xab"], "\x15" => [147, "\xab"], "\x16" => [149, "\xab"], "\x17" => [101, "\xab"], "\x18" => [112, "\xab"], "\x19" => [117, "\xab"], "\x1a" => [120, "\xab"], "\x1b" => [124, "\xab"], "\x1c" => [127, "\xab"], "\x1d" => [144, "\xab"], "\x1e" => [152, "\xab"], "\x1f" => [11, "\xab"], " " => [0, "\xce0"], "!" => [0, "\xce1"], "\"" => [0, "\xce2"], "#" => [0, "\xcea"], "\$" => [0, "\xcec"], "%" => [0, "\xcee"], "&" => [0, "\xcei"], "'" => [0, "\xceo"], "(" => [0, "\xces"], ")" => [0, "\xcet"], "*" => [73, "\xce"], "+" => [88, "\xce"], "," => [89, "\xce"], "-" => [96, "\xce"], "." => [97, "\xce"], "/" => [99, "\xce"], [106, "\xce"], [136, "\xce"], [139, "\xce"], [141, "\xce"], [145, "\xce"], [147, "\xce"], [149, "\xce"], [101, "\xce"], [112, "\xce"], [117, "\xce"], ":" => [120, "\xce"], ";" => [124, "\xce"], "<" => [127, "\xce"], "=" => [144, "\xce"], ">" => [152, "\xce"], "?" => [11, "\xce"], "@" => [0, "\xd70"], "A" => [0, "\xd71"], "B" => [0, "\xd72"], "C" => [0, "\xd7a"], "D" => [0, "\xd7c"], "E" => [0, "\xd7e"], "F" => [0, "\xd7i"], "G" => [0, "\xd7o"], "H" => [0, "\xd7s"], "I" => [0, "\xd7t"], "J" => [73, "\xd7"], "K" => [88, "\xd7"], "L" => [89, "\xd7"], "M" => [96, "\xd7"], "N" => [97, "\xd7"], "O" => [99, "\xd7"], "P" => [106, "\xd7"], "Q" => [136, "\xd7"], "R" => [139, "\xd7"], "S" => [141, "\xd7"], "T" => [145, "\xd7"], "U" => [147, "\xd7"], "V" => [149, "\xd7"], "W" => [101, "\xd7"], "X" => [112, "\xd7"], "Y" => [117, "\xd7"], "Z" => [120, "\xd7"], "[" => [124, "\xd7"], "\\" => [127, "\xd7"], "]" => [144, "\xd7"], "^" => [152, "\xd7"], "_" => [11, "\xd7"], "`" => [0, "\xe10"], "a" => [0, "\xe11"], "b" => [0, "\xe12"], "c" => [0, "\xe1a"], "d" => [0, "\xe1c"], "e" => [0, "\xe1e"], "f" => [0, "\xe1i"], "g" => [0, "\xe1o"], "h" => [0, "\xe1s"], "i" => [0, "\xe1t"], "j" => [73, "\xe1"], "k" => [88, "\xe1"], "l" => [89, "\xe1"], "m" => [96, "\xe1"], "n" => [97, "\xe1"], "o" => [99, "\xe1"], "p" => [106, "\xe1"], "q" => [136, "\xe1"], "r" => [139, "\xe1"], "s" => [141, "\xe1"], "t" => [145, "\xe1"], "u" => [147, "\xe1"], "v" => [149, "\xe1"], "w" => [101, "\xe1"], "x" => [112, "\xe1"], "y" => [117, "\xe1"], "z" => [120, "\xe1"], "{" => [124, "\xe1"], "|" => [127, "\xe1"], "}" => [144, "\xe1"], "~" => [152, "\xe1"], "" => [11, "\xe1"], "\x80" => [0, "\xec0"], "\x81" => [0, "\xec1"], "\x82" => [0, "\xec2"], "\x83" => [0, "\xeca"], "\x84" => [0, "\xecc"], "\x85" => [0, "\xece"], "\x86" => [0, "\xeci"], "\x87" => [0, "\xeco"], "\x88" => [0, "\xecs"], "\x89" => [0, "\xect"], "\x8a" => [73, "\xec"], "\x8b" => [88, "\xec"], "\x8c" => [89, "\xec"], "\x8d" => [96, "\xec"], "\x8e" => [97, "\xec"], "\x8f" => [99, "\xec"], "\x90" => [106, "\xec"], "\x91" => [136, "\xec"], "\x92" => [139, "\xec"], "\x93" => [141, "\xec"], "\x94" => [145, "\xec"], "\x95" => [147, "\xec"], "\x96" => [149, "\xec"], "\x97" => [101, "\xec"], "\x98" => [112, "\xec"], "\x99" => [117, "\xec"], "\x9a" => [120, "\xec"], "\x9b" => [124, "\xec"], "\x9c" => [127, "\xec"], "\x9d" => [144, "\xec"], "\x9e" => [152, "\xec"], "\x9f" => [11, "\xec"], "\xa0" => [0, "\xed0"], "\xa1" => [0, "\xed1"], "\xa2" => [0, "\xed2"], "\xa3" => [0, "\xeda"], "\xa4" => [0, "\xedc"], "\xa5" => [0, "\xede"], "\xa6" => [0, "\xedi"], "\xa7" => [0, "\xedo"], "\xa8" => [0, "\xeds"], "\xa9" => [0, "\xedt"], "\xaa" => [73, "\xed"], "\xab" => [88, "\xed"], "\xac" => [89, "\xed"], "\xad" => [96, "\xed"], "\xae" => [97, "\xed"], "\xaf" => [99, "\xed"], "\xb0" => [106, "\xed"], "\xb1" => [136, "\xed"], "\xb2" => [139, "\xed"], "\xb3" => [141, "\xed"], "\xb4" => [145, "\xed"], "\xb5" => [147, "\xed"], "\xb6" => [149, "\xed"], "\xb7" => [101, "\xed"], "\xb8" => [112, "\xed"], "\xb9" => [117, "\xed"], "\xba" => [120, "\xed"], "\xbb" => [124, "\xed"], "\xbc" => [127, "\xed"], "\xbd" => [144, "\xed"], "\xbe" => [152, "\xed"], "\xbf" => [11, "\xed"], "\xc0" => [92, "\xc7"], "\xc1" => [95, "\xc7"], "\xc2" => [137, "\xc7"], "\xc3" => [142, "\xc7"], "\xc4" => [150, "\xc7"], "\xc5" => [74, "\xc7"], "\xc6" => [90, "\xc7"], "\xc7" => [98, "\xc7"], "\xc8" => [107, "\xc7"], "\xc9" => [140, "\xc7"], "\xca" => [146, "\xc7"], "\xcb" => [102, "\xc7"], "\xcc" => [113, "\xc7"], "\xcd" => [121, "\xc7"], "\xce" => [128, "\xc7"], "\xcf" => [12, "\xc7"], "\xd0" => [92, "\xcf"], "\xd1" => [95, "\xcf"], "\xd2" => [137, "\xcf"], "\xd3" => [142, "\xcf"], "\xd4" => [150, "\xcf"], "\xd5" => [74, "\xcf"], "\xd6" => [90, "\xcf"], "\xd7" => [98, "\xcf"], "\xd8" => [107, "\xcf"], "\xd9" => [140, "\xcf"], "\xda" => [146, "\xcf"], "\xdb" => [102, "\xcf"], "\xdc" => [113, "\xcf"], "\xdd" => [121, "\xcf"], "\xde" => [128, "\xcf"], "\xdf" => [12, "\xcf"], "\xe0" => [92, "\xea"], "\xe1" => [95, "\xea"], "\xe2" => [137, "\xea"], "\xe3" => [142, "\xea"], "\xe4" => [150, "\xea"], "\xe5" => [74, "\xea"], "\xe6" => [90, "\xea"], "\xe7" => [98, "\xea"], "\xe8" => [107, "\xea"], "\xe9" => [140, "\xea"], "\xea" => [146, "\xea"], "\xeb" => [102, "\xea"], "\xec" => [113, "\xea"], "\xed" => [121, "\xea"], "\xee" => [128, "\xea"], "\xef" => [12, "\xea"], "\xf0" => [92, "\xeb"], "\xf1" => [95, "\xeb"], "\xf2" => [137, "\xeb"], "\xf3" => [142, "\xeb"], "\xf4" => [150, "\xeb"], "\xf5" => [74, "\xeb"], "\xf6" => [90, "\xeb"], "\xf7" => [98, "\xeb"], "\xf8" => [107, "\xeb"], "\xf9" => [140, "\xeb"], "\xfa" => [146, "\xeb"], "\xfb" => [102, "\xeb"], "\xfc" => [113, "\xeb"], "\xfd" => [121, "\xeb"], "\xfe" => [128, "\xeb"], "\xff" => [12, "\xeb"]], ["\x00" => [94, "\xaf0"], "\x01" => [76, "\xaf0"], "\x02" => [104, "\xaf0"], "\x03" => [16, "\xaf0"], "\x04" => [94, "\xaf1"], "\x05" => [76, "\xaf1"], "\x06" => [104, "\xaf1"], "\x07" => [16, "\xaf1"], "\x08" => [94, "\xaf2"], "\t" => [76, "\xaf2"], "\n" => [104, "\xaf2"], "\v" => [16, "\xaf2"], "\f" => [94, "\xafa"], "\r" => [76, "\xafa"], "\x0e" => [104, "\xafa"], "\x0f" => [16, "\xafa"], "\x10" => [94, "\xafc"], "\x11" => [76, "\xafc"], "\x12" => [104, "\xafc"], "\x13" => [16, "\xafc"], "\x14" => [94, "\xafe"], "\x15" => [76, "\xafe"], "\x16" => [104, "\xafe"], "\x17" => [16, "\xafe"], "\x18" => [94, "\xafi"], "\x19" => [76, "\xafi"], "\x1a" => [104, "\xafi"], "\x1b" => [16, "\xafi"], "\x1c" => [94, "\xafo"], "\x1d" => [76, "\xafo"], "\x1e" => [104, "\xafo"], "\x1f" => [16, "\xafo"], " " => [94, "\xafs"], "!" => [76, "\xafs"], "\"" => [104, "\xafs"], "#" => [16, "\xafs"], "\$" => [94, "\xaft"], "%" => [76, "\xaft"], "&" => [104, "\xaft"], "'" => [16, "\xaft"], "(" => [77, "\xaf "], ")" => [18, "\xaf "], "*" => [77, "\xaf%"], "+" => [18, "\xaf%"], "," => [77, "\xaf-"], "-" => [18, "\xaf-"], "." => [77, "\xaf."], "/" => [18, "\xaf."], [77, "\xaf/"], [18, "\xaf/"], [77, "\xaf3"], [18, "\xaf3"], [77, "\xaf4"], [18, "\xaf4"], [77, "\xaf5"], [18, "\xaf5"], [77, "\xaf6"], [18, "\xaf6"], ":" => [77, "\xaf7"], ";" => [18, "\xaf7"], "<" => [77, "\xaf8"], "=" => [18, "\xaf8"], ">" => [77, "\xaf9"], "?" => [18, "\xaf9"], "@" => [77, "\xaf="], "A" => [18, "\xaf="], "B" => [77, "\xafA"], "C" => [18, "\xafA"], "D" => [77, "\xaf_"], "E" => [18, "\xaf_"], "F" => [77, "\xafb"], "G" => [18, "\xafb"], "H" => [77, "\xafd"], "I" => [18, "\xafd"], "J" => [77, "\xaff"], "K" => [18, "\xaff"], "L" => [77, "\xafg"], "M" => [18, "\xafg"], "N" => [77, "\xafh"], "O" => [18, "\xafh"], "P" => [77, "\xafl"], "Q" => [18, "\xafl"], "R" => [77, "\xafm"], "S" => [18, "\xafm"], "T" => [77, "\xafn"], "U" => [18, "\xafn"], "V" => [77, "\xafp"], "W" => [18, "\xafp"], "X" => [77, "\xafr"], "Y" => [18, "\xafr"], "Z" => [77, "\xafu"], "[" => [18, "\xafu"], "\\" => [0, "\xaf:"], "]" => [0, "\xafB"], "^" => [0, "\xafC"], "_" => [0, "\xafD"], "`" => [0, "\xafE"], "a" => [0, "\xafF"], "b" => [0, "\xafG"], "c" => [0, "\xafH"], "d" => [0, "\xafI"], "e" => [0, "\xafJ"], "f" => [0, "\xafK"], "g" => [0, "\xafL"], "h" => [0, "\xafM"], "i" => [0, "\xafN"], "j" => [0, "\xafO"], "k" => [0, "\xafP"], "l" => [0, "\xafQ"], "m" => [0, "\xafR"], "n" => [0, "\xafS"], "o" => [0, "\xafT"], "p" => [0, "\xafU"], "q" => [0, "\xafV"], "r" => [0, "\xafW"], "s" => [0, "\xafY"], "t" => [0, "\xafj"], "u" => [0, "\xafk"], "v" => [0, "\xafq"], "w" => [0, "\xafv"], "x" => [0, "\xafw"], "y" => [0, "\xafx"], "z" => [0, "\xafy"], "{" => [0, "\xafz"], "|" => [82, "\xaf"], "}" => [87, "\xaf"], "~" => [130, "\xaf"], "" => [9, "\xaf"], "\x80" => [94, "\xb40"], "\x81" => [76, "\xb40"], "\x82" => [104, "\xb40"], "\x83" => [16, "\xb40"], "\x84" => [94, "\xb41"], "\x85" => [76, "\xb41"], "\x86" => [104, "\xb41"], "\x87" => [16, "\xb41"], "\x88" => [94, "\xb42"], "\x89" => [76, "\xb42"], "\x8a" => [104, "\xb42"], "\x8b" => [16, "\xb42"], "\x8c" => [94, "\xb4a"], "\x8d" => [76, "\xb4a"], "\x8e" => [104, "\xb4a"], "\x8f" => [16, "\xb4a"], "\x90" => [94, "\xb4c"], "\x91" => [76, "\xb4c"], "\x92" => [104, "\xb4c"], "\x93" => [16, "\xb4c"], "\x94" => [94, "\xb4e"], "\x95" => [76, "\xb4e"], "\x96" => [104, "\xb4e"], "\x97" => [16, "\xb4e"], "\x98" => [94, "\xb4i"], "\x99" => [76, "\xb4i"], "\x9a" => [104, "\xb4i"], "\x9b" => [16, "\xb4i"], "\x9c" => [94, "\xb4o"], "\x9d" => [76, "\xb4o"], "\x9e" => [104, "\xb4o"], "\x9f" => [16, "\xb4o"], "\xa0" => [94, "\xb4s"], "\xa1" => [76, "\xb4s"], "\xa2" => [104, "\xb4s"], "\xa3" => [16, "\xb4s"], "\xa4" => [94, "\xb4t"], "\xa5" => [76, "\xb4t"], "\xa6" => [104, "\xb4t"], "\xa7" => [16, "\xb4t"], "\xa8" => [77, "\xb4 "], "\xa9" => [18, "\xb4 "], "\xaa" => [77, "\xb4%"], "\xab" => [18, "\xb4%"], "\xac" => [77, "\xb4-"], "\xad" => [18, "\xb4-"], "\xae" => [77, "\xb4."], "\xaf" => [18, "\xb4."], "\xb0" => [77, "\xb4/"], "\xb1" => [18, "\xb4/"], "\xb2" => [77, "\xb43"], "\xb3" => [18, "\xb43"], "\xb4" => [77, "\xb44"], "\xb5" => [18, "\xb44"], "\xb6" => [77, "\xb45"], "\xb7" => [18, "\xb45"], "\xb8" => [77, "\xb46"], "\xb9" => [18, "\xb46"], "\xba" => [77, "\xb47"], "\xbb" => [18, "\xb47"], "\xbc" => [77, "\xb48"], "\xbd" => [18, "\xb48"], "\xbe" => [77, "\xb49"], "\xbf" => [18, "\xb49"], "\xc0" => [77, "\xb4="], "\xc1" => [18, "\xb4="], "\xc2" => [77, "\xb4A"], "\xc3" => [18, "\xb4A"], "\xc4" => [77, "\xb4_"], "\xc5" => [18, "\xb4_"], "\xc6" => [77, "\xb4b"], "\xc7" => [18, "\xb4b"], "\xc8" => [77, "\xb4d"], "\xc9" => [18, "\xb4d"], "\xca" => [77, "\xb4f"], "\xcb" => [18, "\xb4f"], "\xcc" => [77, "\xb4g"], "\xcd" => [18, "\xb4g"], "\xce" => [77, "\xb4h"], "\xcf" => [18, "\xb4h"], "\xd0" => [77, "\xb4l"], "\xd1" => [18, "\xb4l"], "\xd2" => [77, "\xb4m"], "\xd3" => [18, "\xb4m"], "\xd4" => [77, "\xb4n"], "\xd5" => [18, "\xb4n"], "\xd6" => [77, "\xb4p"], "\xd7" => [18, "\xb4p"], "\xd8" => [77, "\xb4r"], "\xd9" => [18, "\xb4r"], "\xda" => [77, "\xb4u"], "\xdb" => [18, "\xb4u"], "\xdc" => [0, "\xb4:"], "\xdd" => [0, "\xb4B"], "\xde" => [0, "\xb4C"], "\xdf" => [0, "\xb4D"], "\xe0" => [0, "\xb4E"], "\xe1" => [0, "\xb4F"], "\xe2" => [0, "\xb4G"], "\xe3" => [0, "\xb4H"], "\xe4" => [0, "\xb4I"], "\xe5" => [0, "\xb4J"], "\xe6" => [0, "\xb4K"], "\xe7" => [0, "\xb4L"], "\xe8" => [0, "\xb4M"], "\xe9" => [0, "\xb4N"], "\xea" => [0, "\xb4O"], "\xeb" => [0, "\xb4P"], "\xec" => [0, "\xb4Q"], "\xed" => [0, "\xb4R"], "\xee" => [0, "\xb4S"], "\xef" => [0, "\xb4T"], "\xf0" => [0, "\xb4U"], "\xf1" => [0, "\xb4V"], "\xf2" => [0, "\xb4W"], "\xf3" => [0, "\xb4Y"], "\xf4" => [0, "\xb4j"], "\xf5" => [0, "\xb4k"], "\xf6" => [0, "\xb4q"], "\xf7" => [0, "\xb4v"], "\xf8" => [0, "\xb4w"], "\xf9" => [0, "\xb4x"], "\xfa" => [0, "\xb4y"], "\xfb" => [0, "\xb4z"], "\xfc" => [82, "\xb4"], "\xfd" => [87, "\xb4"], "\xfe" => [130, "\xb4"], "\xff" => [9, "\xb4"]], ["\x00" => [77, "\xaf0"], "\x01" => [18, "\xaf0"], "\x02" => [77, "\xaf1"], "\x03" => [18, "\xaf1"], "\x04" => [77, "\xaf2"], "\x05" => [18, "\xaf2"], "\x06" => [77, "\xafa"], "\x07" => [18, "\xafa"], "\x08" => [77, "\xafc"], "\t" => [18, "\xafc"], "\n" => [77, "\xafe"], "\v" => [18, "\xafe"], "\f" => [77, "\xafi"], "\r" => [18, "\xafi"], "\x0e" => [77, "\xafo"], "\x0f" => [18, "\xafo"], "\x10" => [77, "\xafs"], "\x11" => [18, "\xafs"], "\x12" => [77, "\xaft"], "\x13" => [18, "\xaft"], "\x14" => [0, "\xaf "], "\x15" => [0, "\xaf%"], "\x16" => [0, "\xaf-"], "\x17" => [0, "\xaf."], "\x18" => [0, "\xaf/"], "\x19" => [0, "\xaf3"], "\x1a" => [0, "\xaf4"], "\x1b" => [0, "\xaf5"], "\x1c" => [0, "\xaf6"], "\x1d" => [0, "\xaf7"], "\x1e" => [0, "\xaf8"], "\x1f" => [0, "\xaf9"], " " => [0, "\xaf="], "!" => [0, "\xafA"], "\"" => [0, "\xaf_"], "#" => [0, "\xafb"], "\$" => [0, "\xafd"], "%" => [0, "\xaff"], "&" => [0, "\xafg"], "'" => [0, "\xafh"], "(" => [0, "\xafl"], ")" => [0, "\xafm"], "*" => [0, "\xafn"], "+" => [0, "\xafp"], "," => [0, "\xafr"], "-" => [0, "\xafu"], "." => [100, "\xaf"], "/" => [110, "\xaf"], [111, "\xaf"], [115, "\xaf"], [116, "\xaf"], [118, "\xaf"], [119, "\xaf"], [122, "\xaf"], [123, "\xaf"], [125, "\xaf"], [126, "\xaf"], [129, "\xaf"], ":" => [143, "\xaf"], ";" => [148, "\xaf"], "<" => [151, "\xaf"], "=" => [153, "\xaf"], ">" => [83, "\xaf"], "?" => [10, "\xaf"], "@" => [77, "\xb40"], "A" => [18, "\xb40"], "B" => [77, "\xb41"], "C" => [18, "\xb41"], "D" => [77, "\xb42"], "E" => [18, "\xb42"], "F" => [77, "\xb4a"], "G" => [18, "\xb4a"], "H" => [77, "\xb4c"], "I" => [18, "\xb4c"], "J" => [77, "\xb4e"], "K" => [18, "\xb4e"], "L" => [77, "\xb4i"], "M" => [18, "\xb4i"], "N" => [77, "\xb4o"], "O" => [18, "\xb4o"], "P" => [77, "\xb4s"], "Q" => [18, "\xb4s"], "R" => [77, "\xb4t"], "S" => [18, "\xb4t"], "T" => [0, "\xb4 "], "U" => [0, "\xb4%"], "V" => [0, "\xb4-"], "W" => [0, "\xb4."], "X" => [0, "\xb4/"], "Y" => [0, "\xb43"], "Z" => [0, "\xb44"], "[" => [0, "\xb45"], "\\" => [0, "\xb46"], "]" => [0, "\xb47"], "^" => [0, "\xb48"], "_" => [0, "\xb49"], "`" => [0, "\xb4="], "a" => [0, "\xb4A"], "b" => [0, "\xb4_"], "c" => [0, "\xb4b"], "d" => [0, "\xb4d"], "e" => [0, "\xb4f"], "f" => [0, "\xb4g"], "g" => [0, "\xb4h"], "h" => [0, "\xb4l"], "i" => [0, "\xb4m"], "j" => [0, "\xb4n"], "k" => [0, "\xb4p"], "l" => [0, "\xb4r"], "m" => [0, "\xb4u"], "n" => [100, "\xb4"], "o" => [110, "\xb4"], "p" => [111, "\xb4"], "q" => [115, "\xb4"], "r" => [116, "\xb4"], "s" => [118, "\xb4"], "t" => [119, "\xb4"], "u" => [122, "\xb4"], "v" => [123, "\xb4"], "w" => [125, "\xb4"], "x" => [126, "\xb4"], "y" => [129, "\xb4"], "z" => [143, "\xb4"], "{" => [148, "\xb4"], "|" => [151, "\xb4"], "}" => [153, "\xb4"], "~" => [83, "\xb4"], "" => [10, "\xb4"], "\x80" => [77, "\xb60"], "\x81" => [18, "\xb60"], "\x82" => [77, "\xb61"], "\x83" => [18, "\xb61"], "\x84" => [77, "\xb62"], "\x85" => [18, "\xb62"], "\x86" => [77, "\xb6a"], "\x87" => [18, "\xb6a"], "\x88" => [77, "\xb6c"], "\x89" => [18, "\xb6c"], "\x8a" => [77, "\xb6e"], "\x8b" => [18, "\xb6e"], "\x8c" => [77, "\xb6i"], "\x8d" => [18, "\xb6i"], "\x8e" => [77, "\xb6o"], "\x8f" => [18, "\xb6o"], "\x90" => [77, "\xb6s"], "\x91" => [18, "\xb6s"], "\x92" => [77, "\xb6t"], "\x93" => [18, "\xb6t"], "\x94" => [0, "\xb6 "], "\x95" => [0, "\xb6%"], "\x96" => [0, "\xb6-"], "\x97" => [0, "\xb6."], "\x98" => [0, "\xb6/"], "\x99" => [0, "\xb63"], "\x9a" => [0, "\xb64"], "\x9b" => [0, "\xb65"], "\x9c" => [0, "\xb66"], "\x9d" => [0, "\xb67"], "\x9e" => [0, "\xb68"], "\x9f" => [0, "\xb69"], "\xa0" => [0, "\xb6="], "\xa1" => [0, "\xb6A"], "\xa2" => [0, "\xb6_"], "\xa3" => [0, "\xb6b"], "\xa4" => [0, "\xb6d"], "\xa5" => [0, "\xb6f"], "\xa6" => [0, "\xb6g"], "\xa7" => [0, "\xb6h"], "\xa8" => [0, "\xb6l"], "\xa9" => [0, "\xb6m"], "\xaa" => [0, "\xb6n"], "\xab" => [0, "\xb6p"], "\xac" => [0, "\xb6r"], "\xad" => [0, "\xb6u"], "\xae" => [100, "\xb6"], "\xaf" => [110, "\xb6"], "\xb0" => [111, "\xb6"], "\xb1" => [115, "\xb6"], "\xb2" => [116, "\xb6"], "\xb3" => [118, "\xb6"], "\xb4" => [119, "\xb6"], "\xb5" => [122, "\xb6"], "\xb6" => [123, "\xb6"], "\xb7" => [125, "\xb6"], "\xb8" => [126, "\xb6"], "\xb9" => [129, "\xb6"], "\xba" => [143, "\xb6"], "\xbb" => [148, "\xb6"], "\xbc" => [151, "\xb6"], "\xbd" => [153, "\xb6"], "\xbe" => [83, "\xb6"], "\xbf" => [10, "\xb6"], "\xc0" => [77, "\xb70"], "\xc1" => [18, "\xb70"], "\xc2" => [77, "\xb71"], "\xc3" => [18, "\xb71"], "\xc4" => [77, "\xb72"], "\xc5" => [18, "\xb72"], "\xc6" => [77, "\xb7a"], "\xc7" => [18, "\xb7a"], "\xc8" => [77, "\xb7c"], "\xc9" => [18, "\xb7c"], "\xca" => [77, "\xb7e"], "\xcb" => [18, "\xb7e"], "\xcc" => [77, "\xb7i"], "\xcd" => [18, "\xb7i"], "\xce" => [77, "\xb7o"], "\xcf" => [18, "\xb7o"], "\xd0" => [77, "\xb7s"], "\xd1" => [18, "\xb7s"], "\xd2" => [77, "\xb7t"], "\xd3" => [18, "\xb7t"], "\xd4" => [0, "\xb7 "], "\xd5" => [0, "\xb7%"], "\xd6" => [0, "\xb7-"], "\xd7" => [0, "\xb7."], "\xd8" => [0, "\xb7/"], "\xd9" => [0, "\xb73"], "\xda" => [0, "\xb74"], "\xdb" => [0, "\xb75"], "\xdc" => [0, "\xb76"], "\xdd" => [0, "\xb77"], "\xde" => [0, "\xb78"], "\xdf" => [0, "\xb79"], "\xe0" => [0, "\xb7="], "\xe1" => [0, "\xb7A"], "\xe2" => [0, "\xb7_"], "\xe3" => [0, "\xb7b"], "\xe4" => [0, "\xb7d"], "\xe5" => [0, "\xb7f"], "\xe6" => [0, "\xb7g"], "\xe7" => [0, "\xb7h"], "\xe8" => [0, "\xb7l"], "\xe9" => [0, "\xb7m"], "\xea" => [0, "\xb7n"], "\xeb" => [0, "\xb7p"], "\xec" => [0, "\xb7r"], "\xed" => [0, "\xb7u"], "\xee" => [100, "\xb7"], "\xef" => [110, "\xb7"], "\xf0" => [111, "\xb7"], "\xf1" => [115, "\xb7"], "\xf2" => [116, "\xb7"], "\xf3" => [118, "\xb7"], "\xf4" => [119, "\xb7"], "\xf5" => [122, "\xb7"], "\xf6" => [123, "\xb7"], "\xf7" => [125, "\xb7"], "\xf8" => [126, "\xb7"], "\xf9" => [129, "\xb7"], "\xfa" => [143, "\xb7"], "\xfb" => [148, "\xb7"], "\xfc" => [151, "\xb7"], "\xfd" => [153, "\xb7"], "\xfe" => [83, "\xb7"], "\xff" => [10, "\xb7"]], ["\x00" => [94, "\xb00"], "\x01" => [76, "\xb00"], "\x02" => [104, "\xb00"], "\x03" => [16, "\xb00"], "\x04" => [94, "\xb01"], "\x05" => [76, "\xb01"], "\x06" => [104, "\xb01"], "\x07" => [16, "\xb01"], "\x08" => [94, "\xb02"], "\t" => [76, "\xb02"], "\n" => [104, "\xb02"], "\v" => [16, "\xb02"], "\f" => [94, "\xb0a"], "\r" => [76, "\xb0a"], "\x0e" => [104, "\xb0a"], "\x0f" => [16, "\xb0a"], "\x10" => [94, "\xb0c"], "\x11" => [76, "\xb0c"], "\x12" => [104, "\xb0c"], "\x13" => [16, "\xb0c"], "\x14" => [94, "\xb0e"], "\x15" => [76, "\xb0e"], "\x16" => [104, "\xb0e"], "\x17" => [16, "\xb0e"], "\x18" => [94, "\xb0i"], "\x19" => [76, "\xb0i"], "\x1a" => [104, "\xb0i"], "\x1b" => [16, "\xb0i"], "\x1c" => [94, "\xb0o"], "\x1d" => [76, "\xb0o"], "\x1e" => [104, "\xb0o"], "\x1f" => [16, "\xb0o"], " " => [94, "\xb0s"], "!" => [76, "\xb0s"], "\"" => [104, "\xb0s"], "#" => [16, "\xb0s"], "\$" => [94, "\xb0t"], "%" => [76, "\xb0t"], "&" => [104, "\xb0t"], "'" => [16, "\xb0t"], "(" => [77, "\xb0 "], ")" => [18, "\xb0 "], "*" => [77, "\xb0%"], "+" => [18, "\xb0%"], "," => [77, "\xb0-"], "-" => [18, "\xb0-"], "." => [77, "\xb0."], "/" => [18, "\xb0."], [77, "\xb0/"], [18, "\xb0/"], [77, "\xb03"], [18, "\xb03"], [77, "\xb04"], [18, "\xb04"], [77, "\xb05"], [18, "\xb05"], [77, "\xb06"], [18, "\xb06"], ":" => [77, "\xb07"], ";" => [18, "\xb07"], "<" => [77, "\xb08"], "=" => [18, "\xb08"], ">" => [77, "\xb09"], "?" => [18, "\xb09"], "@" => [77, "\xb0="], "A" => [18, "\xb0="], "B" => [77, "\xb0A"], "C" => [18, "\xb0A"], "D" => [77, "\xb0_"], "E" => [18, "\xb0_"], "F" => [77, "\xb0b"], "G" => [18, "\xb0b"], "H" => [77, "\xb0d"], "I" => [18, "\xb0d"], "J" => [77, "\xb0f"], "K" => [18, "\xb0f"], "L" => [77, "\xb0g"], "M" => [18, "\xb0g"], "N" => [77, "\xb0h"], "O" => [18, "\xb0h"], "P" => [77, "\xb0l"], "Q" => [18, "\xb0l"], "R" => [77, "\xb0m"], "S" => [18, "\xb0m"], "T" => [77, "\xb0n"], "U" => [18, "\xb0n"], "V" => [77, "\xb0p"], "W" => [18, "\xb0p"], "X" => [77, "\xb0r"], "Y" => [18, "\xb0r"], "Z" => [77, "\xb0u"], "[" => [18, "\xb0u"], "\\" => [0, "\xb0:"], "]" => [0, "\xb0B"], "^" => [0, "\xb0C"], "_" => [0, "\xb0D"], "`" => [0, "\xb0E"], "a" => [0, "\xb0F"], "b" => [0, "\xb0G"], "c" => [0, "\xb0H"], "d" => [0, "\xb0I"], "e" => [0, "\xb0J"], "f" => [0, "\xb0K"], "g" => [0, "\xb0L"], "h" => [0, "\xb0M"], "i" => [0, "\xb0N"], "j" => [0, "\xb0O"], "k" => [0, "\xb0P"], "l" => [0, "\xb0Q"], "m" => [0, "\xb0R"], "n" => [0, "\xb0S"], "o" => [0, "\xb0T"], "p" => [0, "\xb0U"], "q" => [0, "\xb0V"], "r" => [0, "\xb0W"], "s" => [0, "\xb0Y"], "t" => [0, "\xb0j"], "u" => [0, "\xb0k"], "v" => [0, "\xb0q"], "w" => [0, "\xb0v"], "x" => [0, "\xb0w"], "y" => [0, "\xb0x"], "z" => [0, "\xb0y"], "{" => [0, "\xb0z"], "|" => [82, "\xb0"], "}" => [87, "\xb0"], "~" => [130, "\xb0"], "" => [9, "\xb0"], "\x80" => [94, "\xb10"], "\x81" => [76, "\xb10"], "\x82" => [104, "\xb10"], "\x83" => [16, "\xb10"], "\x84" => [94, "\xb11"], "\x85" => [76, "\xb11"], "\x86" => [104, "\xb11"], "\x87" => [16, "\xb11"], "\x88" => [94, "\xb12"], "\x89" => [76, "\xb12"], "\x8a" => [104, "\xb12"], "\x8b" => [16, "\xb12"], "\x8c" => [94, "\xb1a"], "\x8d" => [76, "\xb1a"], "\x8e" => [104, "\xb1a"], "\x8f" => [16, "\xb1a"], "\x90" => [94, "\xb1c"], "\x91" => [76, "\xb1c"], "\x92" => [104, "\xb1c"], "\x93" => [16, "\xb1c"], "\x94" => [94, "\xb1e"], "\x95" => [76, "\xb1e"], "\x96" => [104, "\xb1e"], "\x97" => [16, "\xb1e"], "\x98" => [94, "\xb1i"], "\x99" => [76, "\xb1i"], "\x9a" => [104, "\xb1i"], "\x9b" => [16, "\xb1i"], "\x9c" => [94, "\xb1o"], "\x9d" => [76, "\xb1o"], "\x9e" => [104, "\xb1o"], "\x9f" => [16, "\xb1o"], "\xa0" => [94, "\xb1s"], "\xa1" => [76, "\xb1s"], "\xa2" => [104, "\xb1s"], "\xa3" => [16, "\xb1s"], "\xa4" => [94, "\xb1t"], "\xa5" => [76, "\xb1t"], "\xa6" => [104, "\xb1t"], "\xa7" => [16, "\xb1t"], "\xa8" => [77, "\xb1 "], "\xa9" => [18, "\xb1 "], "\xaa" => [77, "\xb1%"], "\xab" => [18, "\xb1%"], "\xac" => [77, "\xb1-"], "\xad" => [18, "\xb1-"], "\xae" => [77, "\xb1."], "\xaf" => [18, "\xb1."], "\xb0" => [77, "\xb1/"], "\xb1" => [18, "\xb1/"], "\xb2" => [77, "\xb13"], "\xb3" => [18, "\xb13"], "\xb4" => [77, "\xb14"], "\xb5" => [18, "\xb14"], "\xb6" => [77, "\xb15"], "\xb7" => [18, "\xb15"], "\xb8" => [77, "\xb16"], "\xb9" => [18, "\xb16"], "\xba" => [77, "\xb17"], "\xbb" => [18, "\xb17"], "\xbc" => [77, "\xb18"], "\xbd" => [18, "\xb18"], "\xbe" => [77, "\xb19"], "\xbf" => [18, "\xb19"], "\xc0" => [77, "\xb1="], "\xc1" => [18, "\xb1="], "\xc2" => [77, "\xb1A"], "\xc3" => [18, "\xb1A"], "\xc4" => [77, "\xb1_"], "\xc5" => [18, "\xb1_"], "\xc6" => [77, "\xb1b"], "\xc7" => [18, "\xb1b"], "\xc8" => [77, "\xb1d"], "\xc9" => [18, "\xb1d"], "\xca" => [77, "\xb1f"], "\xcb" => [18, "\xb1f"], "\xcc" => [77, "\xb1g"], "\xcd" => [18, "\xb1g"], "\xce" => [77, "\xb1h"], "\xcf" => [18, "\xb1h"], "\xd0" => [77, "\xb1l"], "\xd1" => [18, "\xb1l"], "\xd2" => [77, "\xb1m"], "\xd3" => [18, "\xb1m"], "\xd4" => [77, "\xb1n"], "\xd5" => [18, "\xb1n"], "\xd6" => [77, "\xb1p"], "\xd7" => [18, "\xb1p"], "\xd8" => [77, "\xb1r"], "\xd9" => [18, "\xb1r"], "\xda" => [77, "\xb1u"], "\xdb" => [18, "\xb1u"], "\xdc" => [0, "\xb1:"], "\xdd" => [0, "\xb1B"], "\xde" => [0, "\xb1C"], "\xdf" => [0, "\xb1D"], "\xe0" => [0, "\xb1E"], "\xe1" => [0, "\xb1F"], "\xe2" => [0, "\xb1G"], "\xe3" => [0, "\xb1H"], "\xe4" => [0, "\xb1I"], "\xe5" => [0, "\xb1J"], "\xe6" => [0, "\xb1K"], "\xe7" => [0, "\xb1L"], "\xe8" => [0, "\xb1M"], "\xe9" => [0, "\xb1N"], "\xea" => [0, "\xb1O"], "\xeb" => [0, "\xb1P"], "\xec" => [0, "\xb1Q"], "\xed" => [0, "\xb1R"], "\xee" => [0, "\xb1S"], "\xef" => [0, "\xb1T"], "\xf0" => [0, "\xb1U"], "\xf1" => [0, "\xb1V"], "\xf2" => [0, "\xb1W"], "\xf3" => [0, "\xb1Y"], "\xf4" => [0, "\xb1j"], "\xf5" => [0, "\xb1k"], "\xf6" => [0, "\xb1q"], "\xf7" => [0, "\xb1v"], "\xf8" => [0, "\xb1w"], "\xf9" => [0, "\xb1x"], "\xfa" => [0, "\xb1y"], "\xfb" => [0, "\xb1z"], "\xfc" => [82, "\xb1"], "\xfd" => [87, "\xb1"], "\xfe" => [130, "\xb1"], "\xff" => [9, "\xb1"]], ["\x00" => [77, "\xb00"], "\x01" => [18, "\xb00"], "\x02" => [77, "\xb01"], "\x03" => [18, "\xb01"], "\x04" => [77, "\xb02"], "\x05" => [18, "\xb02"], "\x06" => [77, "\xb0a"], "\x07" => [18, "\xb0a"], "\x08" => [77, "\xb0c"], "\t" => [18, "\xb0c"], "\n" => [77, "\xb0e"], "\v" => [18, "\xb0e"], "\f" => [77, "\xb0i"], "\r" => [18, "\xb0i"], "\x0e" => [77, "\xb0o"], "\x0f" => [18, "\xb0o"], "\x10" => [77, "\xb0s"], "\x11" => [18, "\xb0s"], "\x12" => [77, "\xb0t"], "\x13" => [18, "\xb0t"], "\x14" => [0, "\xb0 "], "\x15" => [0, "\xb0%"], "\x16" => [0, "\xb0-"], "\x17" => [0, "\xb0."], "\x18" => [0, "\xb0/"], "\x19" => [0, "\xb03"], "\x1a" => [0, "\xb04"], "\x1b" => [0, "\xb05"], "\x1c" => [0, "\xb06"], "\x1d" => [0, "\xb07"], "\x1e" => [0, "\xb08"], "\x1f" => [0, "\xb09"], " " => [0, "\xb0="], "!" => [0, "\xb0A"], "\"" => [0, "\xb0_"], "#" => [0, "\xb0b"], "\$" => [0, "\xb0d"], "%" => [0, "\xb0f"], "&" => [0, "\xb0g"], "'" => [0, "\xb0h"], "(" => [0, "\xb0l"], ")" => [0, "\xb0m"], "*" => [0, "\xb0n"], "+" => [0, "\xb0p"], "," => [0, "\xb0r"], "-" => [0, "\xb0u"], "." => [100, "\xb0"], "/" => [110, "\xb0"], [111, "\xb0"], [115, "\xb0"], [116, "\xb0"], [118, "\xb0"], [119, "\xb0"], [122, "\xb0"], [123, "\xb0"], [125, "\xb0"], [126, "\xb0"], [129, "\xb0"], ":" => [143, "\xb0"], ";" => [148, "\xb0"], "<" => [151, "\xb0"], "=" => [153, "\xb0"], ">" => [83, "\xb0"], "?" => [10, "\xb0"], "@" => [77, "\xb10"], "A" => [18, "\xb10"], "B" => [77, "\xb11"], "C" => [18, "\xb11"], "D" => [77, "\xb12"], "E" => [18, "\xb12"], "F" => [77, "\xb1a"], "G" => [18, "\xb1a"], "H" => [77, "\xb1c"], "I" => [18, "\xb1c"], "J" => [77, "\xb1e"], "K" => [18, "\xb1e"], "L" => [77, "\xb1i"], "M" => [18, "\xb1i"], "N" => [77, "\xb1o"], "O" => [18, "\xb1o"], "P" => [77, "\xb1s"], "Q" => [18, "\xb1s"], "R" => [77, "\xb1t"], "S" => [18, "\xb1t"], "T" => [0, "\xb1 "], "U" => [0, "\xb1%"], "V" => [0, "\xb1-"], "W" => [0, "\xb1."], "X" => [0, "\xb1/"], "Y" => [0, "\xb13"], "Z" => [0, "\xb14"], "[" => [0, "\xb15"], "\\" => [0, "\xb16"], "]" => [0, "\xb17"], "^" => [0, "\xb18"], "_" => [0, "\xb19"], "`" => [0, "\xb1="], "a" => [0, "\xb1A"], "b" => [0, "\xb1_"], "c" => [0, "\xb1b"], "d" => [0, "\xb1d"], "e" => [0, "\xb1f"], "f" => [0, "\xb1g"], "g" => [0, "\xb1h"], "h" => [0, "\xb1l"], "i" => [0, "\xb1m"], "j" => [0, "\xb1n"], "k" => [0, "\xb1p"], "l" => [0, "\xb1r"], "m" => [0, "\xb1u"], "n" => [100, "\xb1"], "o" => [110, "\xb1"], "p" => [111, "\xb1"], "q" => [115, "\xb1"], "r" => [116, "\xb1"], "s" => [118, "\xb1"], "t" => [119, "\xb1"], "u" => [122, "\xb1"], "v" => [123, "\xb1"], "w" => [125, "\xb1"], "x" => [126, "\xb1"], "y" => [129, "\xb1"], "z" => [143, "\xb1"], "{" => [148, "\xb1"], "|" => [151, "\xb1"], "}" => [153, "\xb1"], "~" => [83, "\xb1"], "" => [10, "\xb1"], "\x80" => [77, "\xb30"], "\x81" => [18, "\xb30"], "\x82" => [77, "\xb31"], "\x83" => [18, "\xb31"], "\x84" => [77, "\xb32"], "\x85" => [18, "\xb32"], "\x86" => [77, "\xb3a"], "\x87" => [18, "\xb3a"], "\x88" => [77, "\xb3c"], "\x89" => [18, "\xb3c"], "\x8a" => [77, "\xb3e"], "\x8b" => [18, "\xb3e"], "\x8c" => [77, "\xb3i"], "\x8d" => [18, "\xb3i"], "\x8e" => [77, "\xb3o"], "\x8f" => [18, "\xb3o"], "\x90" => [77, "\xb3s"], "\x91" => [18, "\xb3s"], "\x92" => [77, "\xb3t"], "\x93" => [18, "\xb3t"], "\x94" => [0, "\xb3 "], "\x95" => [0, "\xb3%"], "\x96" => [0, "\xb3-"], "\x97" => [0, "\xb3."], "\x98" => [0, "\xb3/"], "\x99" => [0, "\xb33"], "\x9a" => [0, "\xb34"], "\x9b" => [0, "\xb35"], "\x9c" => [0, "\xb36"], "\x9d" => [0, "\xb37"], "\x9e" => [0, "\xb38"], "\x9f" => [0, "\xb39"], "\xa0" => [0, "\xb3="], "\xa1" => [0, "\xb3A"], "\xa2" => [0, "\xb3_"], "\xa3" => [0, "\xb3b"], "\xa4" => [0, "\xb3d"], "\xa5" => [0, "\xb3f"], "\xa6" => [0, "\xb3g"], "\xa7" => [0, "\xb3h"], "\xa8" => [0, "\xb3l"], "\xa9" => [0, "\xb3m"], "\xaa" => [0, "\xb3n"], "\xab" => [0, "\xb3p"], "\xac" => [0, "\xb3r"], "\xad" => [0, "\xb3u"], "\xae" => [100, "\xb3"], "\xaf" => [110, "\xb3"], "\xb0" => [111, "\xb3"], "\xb1" => [115, "\xb3"], "\xb2" => [116, "\xb3"], "\xb3" => [118, "\xb3"], "\xb4" => [119, "\xb3"], "\xb5" => [122, "\xb3"], "\xb6" => [123, "\xb3"], "\xb7" => [125, "\xb3"], "\xb8" => [126, "\xb3"], "\xb9" => [129, "\xb3"], "\xba" => [143, "\xb3"], "\xbb" => [148, "\xb3"], "\xbc" => [151, "\xb3"], "\xbd" => [153, "\xb3"], "\xbe" => [83, "\xb3"], "\xbf" => [10, "\xb3"], "\xc0" => [77, "\xd10"], "\xc1" => [18, "\xd10"], "\xc2" => [77, "\xd11"], "\xc3" => [18, "\xd11"], "\xc4" => [77, "\xd12"], "\xc5" => [18, "\xd12"], "\xc6" => [77, "\xd1a"], "\xc7" => [18, "\xd1a"], "\xc8" => [77, "\xd1c"], "\xc9" => [18, "\xd1c"], "\xca" => [77, "\xd1e"], "\xcb" => [18, "\xd1e"], "\xcc" => [77, "\xd1i"], "\xcd" => [18, "\xd1i"], "\xce" => [77, "\xd1o"], "\xcf" => [18, "\xd1o"], "\xd0" => [77, "\xd1s"], "\xd1" => [18, "\xd1s"], "\xd2" => [77, "\xd1t"], "\xd3" => [18, "\xd1t"], "\xd4" => [0, "\xd1 "], "\xd5" => [0, "\xd1%"], "\xd6" => [0, "\xd1-"], "\xd7" => [0, "\xd1."], "\xd8" => [0, "\xd1/"], "\xd9" => [0, "\xd13"], "\xda" => [0, "\xd14"], "\xdb" => [0, "\xd15"], "\xdc" => [0, "\xd16"], "\xdd" => [0, "\xd17"], "\xde" => [0, "\xd18"], "\xdf" => [0, "\xd19"], "\xe0" => [0, "\xd1="], "\xe1" => [0, "\xd1A"], "\xe2" => [0, "\xd1_"], "\xe3" => [0, "\xd1b"], "\xe4" => [0, "\xd1d"], "\xe5" => [0, "\xd1f"], "\xe6" => [0, "\xd1g"], "\xe7" => [0, "\xd1h"], "\xe8" => [0, "\xd1l"], "\xe9" => [0, "\xd1m"], "\xea" => [0, "\xd1n"], "\xeb" => [0, "\xd1p"], "\xec" => [0, "\xd1r"], "\xed" => [0, "\xd1u"], "\xee" => [100, "\xd1"], "\xef" => [110, "\xd1"], "\xf0" => [111, "\xd1"], "\xf1" => [115, "\xd1"], "\xf2" => [116, "\xd1"], "\xf3" => [118, "\xd1"], "\xf4" => [119, "\xd1"], "\xf5" => [122, "\xd1"], "\xf6" => [123, "\xd1"], "\xf7" => [125, "\xd1"], "\xf8" => [126, "\xd1"], "\xf9" => [129, "\xd1"], "\xfa" => [143, "\xd1"], "\xfb" => [148, "\xd1"], "\xfc" => [151, "\xd1"], "\xfd" => [153, "\xd1"], "\xfe" => [83, "\xd1"], "\xff" => [10, "\xd1"]], ["\x00" => [0, "\xb00"], "\x01" => [0, "\xb01"], "\x02" => [0, "\xb02"], "\x03" => [0, "\xb0a"], "\x04" => [0, "\xb0c"], "\x05" => [0, "\xb0e"], "\x06" => [0, "\xb0i"], "\x07" => [0, "\xb0o"], "\x08" => [0, "\xb0s"], "\t" => [0, "\xb0t"], "\n" => [73, "\xb0"], "\v" => [88, "\xb0"], "\f" => [89, "\xb0"], "\r" => [96, "\xb0"], "\x0e" => [97, "\xb0"], "\x0f" => [99, "\xb0"], "\x10" => [106, "\xb0"], "\x11" => [136, "\xb0"], "\x12" => [139, "\xb0"], "\x13" => [141, "\xb0"], "\x14" => [145, "\xb0"], "\x15" => [147, "\xb0"], "\x16" => [149, "\xb0"], "\x17" => [101, "\xb0"], "\x18" => [112, "\xb0"], "\x19" => [117, "\xb0"], "\x1a" => [120, "\xb0"], "\x1b" => [124, "\xb0"], "\x1c" => [127, "\xb0"], "\x1d" => [144, "\xb0"], "\x1e" => [152, "\xb0"], "\x1f" => [11, "\xb0"], " " => [0, "\xb10"], "!" => [0, "\xb11"], "\"" => [0, "\xb12"], "#" => [0, "\xb1a"], "\$" => [0, "\xb1c"], "%" => [0, "\xb1e"], "&" => [0, "\xb1i"], "'" => [0, "\xb1o"], "(" => [0, "\xb1s"], ")" => [0, "\xb1t"], "*" => [73, "\xb1"], "+" => [88, "\xb1"], "," => [89, "\xb1"], "-" => [96, "\xb1"], "." => [97, "\xb1"], "/" => [99, "\xb1"], [106, "\xb1"], [136, "\xb1"], [139, "\xb1"], [141, "\xb1"], [145, "\xb1"], [147, "\xb1"], [149, "\xb1"], [101, "\xb1"], [112, "\xb1"], [117, "\xb1"], ":" => [120, "\xb1"], ";" => [124, "\xb1"], "<" => [127, "\xb1"], "=" => [144, "\xb1"], ">" => [152, "\xb1"], "?" => [11, "\xb1"], "@" => [0, "\xb30"], "A" => [0, "\xb31"], "B" => [0, "\xb32"], "C" => [0, "\xb3a"], "D" => [0, "\xb3c"], "E" => [0, "\xb3e"], "F" => [0, "\xb3i"], "G" => [0, "\xb3o"], "H" => [0, "\xb3s"], "I" => [0, "\xb3t"], "J" => [73, "\xb3"], "K" => [88, "\xb3"], "L" => [89, "\xb3"], "M" => [96, "\xb3"], "N" => [97, "\xb3"], "O" => [99, "\xb3"], "P" => [106, "\xb3"], "Q" => [136, "\xb3"], "R" => [139, "\xb3"], "S" => [141, "\xb3"], "T" => [145, "\xb3"], "U" => [147, "\xb3"], "V" => [149, "\xb3"], "W" => [101, "\xb3"], "X" => [112, "\xb3"], "Y" => [117, "\xb3"], "Z" => [120, "\xb3"], "[" => [124, "\xb3"], "\\" => [127, "\xb3"], "]" => [144, "\xb3"], "^" => [152, "\xb3"], "_" => [11, "\xb3"], "`" => [0, "\xd10"], "a" => [0, "\xd11"], "b" => [0, "\xd12"], "c" => [0, "\xd1a"], "d" => [0, "\xd1c"], "e" => [0, "\xd1e"], "f" => [0, "\xd1i"], "g" => [0, "\xd1o"], "h" => [0, "\xd1s"], "i" => [0, "\xd1t"], "j" => [73, "\xd1"], "k" => [88, "\xd1"], "l" => [89, "\xd1"], "m" => [96, "\xd1"], "n" => [97, "\xd1"], "o" => [99, "\xd1"], "p" => [106, "\xd1"], "q" => [136, "\xd1"], "r" => [139, "\xd1"], "s" => [141, "\xd1"], "t" => [145, "\xd1"], "u" => [147, "\xd1"], "v" => [149, "\xd1"], "w" => [101, "\xd1"], "x" => [112, "\xd1"], "y" => [117, "\xd1"], "z" => [120, "\xd1"], "{" => [124, "\xd1"], "|" => [127, "\xd1"], "}" => [144, "\xd1"], "~" => [152, "\xd1"], "" => [11, "\xd1"], "\x80" => [0, "\xd80"], "\x81" => [0, "\xd81"], "\x82" => [0, "\xd82"], "\x83" => [0, "\xd8a"], "\x84" => [0, "\xd8c"], "\x85" => [0, "\xd8e"], "\x86" => [0, "\xd8i"], "\x87" => [0, "\xd8o"], "\x88" => [0, "\xd8s"], "\x89" => [0, "\xd8t"], "\x8a" => [73, "\xd8"], "\x8b" => [88, "\xd8"], "\x8c" => [89, "\xd8"], "\x8d" => [96, "\xd8"], "\x8e" => [97, "\xd8"], "\x8f" => [99, "\xd8"], "\x90" => [106, "\xd8"], "\x91" => [136, "\xd8"], "\x92" => [139, "\xd8"], "\x93" => [141, "\xd8"], "\x94" => [145, "\xd8"], "\x95" => [147, "\xd8"], "\x96" => [149, "\xd8"], "\x97" => [101, "\xd8"], "\x98" => [112, "\xd8"], "\x99" => [117, "\xd8"], "\x9a" => [120, "\xd8"], "\x9b" => [124, "\xd8"], "\x9c" => [127, "\xd8"], "\x9d" => [144, "\xd8"], "\x9e" => [152, "\xd8"], "\x9f" => [11, "\xd8"], "\xa0" => [0, "\xd90"], "\xa1" => [0, "\xd91"], "\xa2" => [0, "\xd92"], "\xa3" => [0, "\xd9a"], "\xa4" => [0, "\xd9c"], "\xa5" => [0, "\xd9e"], "\xa6" => [0, "\xd9i"], "\xa7" => [0, "\xd9o"], "\xa8" => [0, "\xd9s"], "\xa9" => [0, "\xd9t"], "\xaa" => [73, "\xd9"], "\xab" => [88, "\xd9"], "\xac" => [89, "\xd9"], "\xad" => [96, "\xd9"], "\xae" => [97, "\xd9"], "\xaf" => [99, "\xd9"], "\xb0" => [106, "\xd9"], "\xb1" => [136, "\xd9"], "\xb2" => [139, "\xd9"], "\xb3" => [141, "\xd9"], "\xb4" => [145, "\xd9"], "\xb5" => [147, "\xd9"], "\xb6" => [149, "\xd9"], "\xb7" => [101, "\xd9"], "\xb8" => [112, "\xd9"], "\xb9" => [117, "\xd9"], "\xba" => [120, "\xd9"], "\xbb" => [124, "\xd9"], "\xbc" => [127, "\xd9"], "\xbd" => [144, "\xd9"], "\xbe" => [152, "\xd9"], "\xbf" => [11, "\xd9"], "\xc0" => [0, "\xe30"], "\xc1" => [0, "\xe31"], "\xc2" => [0, "\xe32"], "\xc3" => [0, "\xe3a"], "\xc4" => [0, "\xe3c"], "\xc5" => [0, "\xe3e"], "\xc6" => [0, "\xe3i"], "\xc7" => [0, "\xe3o"], "\xc8" => [0, "\xe3s"], "\xc9" => [0, "\xe3t"], "\xca" => [73, "\xe3"], "\xcb" => [88, "\xe3"], "\xcc" => [89, "\xe3"], "\xcd" => [96, "\xe3"], "\xce" => [97, "\xe3"], "\xcf" => [99, "\xe3"], "\xd0" => [106, "\xe3"], "\xd1" => [136, "\xe3"], "\xd2" => [139, "\xe3"], "\xd3" => [141, "\xe3"], "\xd4" => [145, "\xe3"], "\xd5" => [147, "\xe3"], "\xd6" => [149, "\xe3"], "\xd7" => [101, "\xe3"], "\xd8" => [112, "\xe3"], "\xd9" => [117, "\xe3"], "\xda" => [120, "\xe3"], "\xdb" => [124, "\xe3"], "\xdc" => [127, "\xe3"], "\xdd" => [144, "\xe3"], "\xde" => [152, "\xe3"], "\xdf" => [11, "\xe3"], "\xe0" => [0, "\xe50"], "\xe1" => [0, "\xe51"], "\xe2" => [0, "\xe52"], "\xe3" => [0, "\xe5a"], "\xe4" => [0, "\xe5c"], "\xe5" => [0, "\xe5e"], "\xe6" => [0, "\xe5i"], "\xe7" => [0, "\xe5o"], "\xe8" => [0, "\xe5s"], "\xe9" => [0, "\xe5t"], "\xea" => [73, "\xe5"], "\xeb" => [88, "\xe5"], "\xec" => [89, "\xe5"], "\xed" => [96, "\xe5"], "\xee" => [97, "\xe5"], "\xef" => [99, "\xe5"], "\xf0" => [106, "\xe5"], "\xf1" => [136, "\xe5"], "\xf2" => [139, "\xe5"], "\xf3" => [141, "\xe5"], "\xf4" => [145, "\xe5"], "\xf5" => [147, "\xe5"], "\xf6" => [149, "\xe5"], "\xf7" => [101, "\xe5"], "\xf8" => [112, "\xe5"], "\xf9" => [117, "\xe5"], "\xfa" => [120, "\xe5"], "\xfb" => [124, "\xe5"], "\xfc" => [127, "\xe5"], "\xfd" => [144, "\xe5"], "\xfe" => [152, "\xe5"], "\xff" => [11, "\xe5"]], ["\x00" => [94, "\xb20"], "\x01" => [76, "\xb20"], "\x02" => [104, "\xb20"], "\x03" => [16, "\xb20"], "\x04" => [94, "\xb21"], "\x05" => [76, "\xb21"], "\x06" => [104, "\xb21"], "\x07" => [16, "\xb21"], "\x08" => [94, "\xb22"], "\t" => [76, "\xb22"], "\n" => [104, "\xb22"], "\v" => [16, "\xb22"], "\f" => [94, "\xb2a"], "\r" => [76, "\xb2a"], "\x0e" => [104, "\xb2a"], "\x0f" => [16, "\xb2a"], "\x10" => [94, "\xb2c"], "\x11" => [76, "\xb2c"], "\x12" => [104, "\xb2c"], "\x13" => [16, "\xb2c"], "\x14" => [94, "\xb2e"], "\x15" => [76, "\xb2e"], "\x16" => [104, "\xb2e"], "\x17" => [16, "\xb2e"], "\x18" => [94, "\xb2i"], "\x19" => [76, "\xb2i"], "\x1a" => [104, "\xb2i"], "\x1b" => [16, "\xb2i"], "\x1c" => [94, "\xb2o"], "\x1d" => [76, "\xb2o"], "\x1e" => [104, "\xb2o"], "\x1f" => [16, "\xb2o"], " " => [94, "\xb2s"], "!" => [76, "\xb2s"], "\"" => [104, "\xb2s"], "#" => [16, "\xb2s"], "\$" => [94, "\xb2t"], "%" => [76, "\xb2t"], "&" => [104, "\xb2t"], "'" => [16, "\xb2t"], "(" => [77, "\xb2 "], ")" => [18, "\xb2 "], "*" => [77, "\xb2%"], "+" => [18, "\xb2%"], "," => [77, "\xb2-"], "-" => [18, "\xb2-"], "." => [77, "\xb2."], "/" => [18, "\xb2."], [77, "\xb2/"], [18, "\xb2/"], [77, "\xb23"], [18, "\xb23"], [77, "\xb24"], [18, "\xb24"], [77, "\xb25"], [18, "\xb25"], [77, "\xb26"], [18, "\xb26"], ":" => [77, "\xb27"], ";" => [18, "\xb27"], "<" => [77, "\xb28"], "=" => [18, "\xb28"], ">" => [77, "\xb29"], "?" => [18, "\xb29"], "@" => [77, "\xb2="], "A" => [18, "\xb2="], "B" => [77, "\xb2A"], "C" => [18, "\xb2A"], "D" => [77, "\xb2_"], "E" => [18, "\xb2_"], "F" => [77, "\xb2b"], "G" => [18, "\xb2b"], "H" => [77, "\xb2d"], "I" => [18, "\xb2d"], "J" => [77, "\xb2f"], "K" => [18, "\xb2f"], "L" => [77, "\xb2g"], "M" => [18, "\xb2g"], "N" => [77, "\xb2h"], "O" => [18, "\xb2h"], "P" => [77, "\xb2l"], "Q" => [18, "\xb2l"], "R" => [77, "\xb2m"], "S" => [18, "\xb2m"], "T" => [77, "\xb2n"], "U" => [18, "\xb2n"], "V" => [77, "\xb2p"], "W" => [18, "\xb2p"], "X" => [77, "\xb2r"], "Y" => [18, "\xb2r"], "Z" => [77, "\xb2u"], "[" => [18, "\xb2u"], "\\" => [0, "\xb2:"], "]" => [0, "\xb2B"], "^" => [0, "\xb2C"], "_" => [0, "\xb2D"], "`" => [0, "\xb2E"], "a" => [0, "\xb2F"], "b" => [0, "\xb2G"], "c" => [0, "\xb2H"], "d" => [0, "\xb2I"], "e" => [0, "\xb2J"], "f" => [0, "\xb2K"], "g" => [0, "\xb2L"], "h" => [0, "\xb2M"], "i" => [0, "\xb2N"], "j" => [0, "\xb2O"], "k" => [0, "\xb2P"], "l" => [0, "\xb2Q"], "m" => [0, "\xb2R"], "n" => [0, "\xb2S"], "o" => [0, "\xb2T"], "p" => [0, "\xb2U"], "q" => [0, "\xb2V"], "r" => [0, "\xb2W"], "s" => [0, "\xb2Y"], "t" => [0, "\xb2j"], "u" => [0, "\xb2k"], "v" => [0, "\xb2q"], "w" => [0, "\xb2v"], "x" => [0, "\xb2w"], "y" => [0, "\xb2x"], "z" => [0, "\xb2y"], "{" => [0, "\xb2z"], "|" => [82, "\xb2"], "}" => [87, "\xb2"], "~" => [130, "\xb2"], "" => [9, "\xb2"], "\x80" => [94, "\xb50"], "\x81" => [76, "\xb50"], "\x82" => [104, "\xb50"], "\x83" => [16, "\xb50"], "\x84" => [94, "\xb51"], "\x85" => [76, "\xb51"], "\x86" => [104, "\xb51"], "\x87" => [16, "\xb51"], "\x88" => [94, "\xb52"], "\x89" => [76, "\xb52"], "\x8a" => [104, "\xb52"], "\x8b" => [16, "\xb52"], "\x8c" => [94, "\xb5a"], "\x8d" => [76, "\xb5a"], "\x8e" => [104, "\xb5a"], "\x8f" => [16, "\xb5a"], "\x90" => [94, "\xb5c"], "\x91" => [76, "\xb5c"], "\x92" => [104, "\xb5c"], "\x93" => [16, "\xb5c"], "\x94" => [94, "\xb5e"], "\x95" => [76, "\xb5e"], "\x96" => [104, "\xb5e"], "\x97" => [16, "\xb5e"], "\x98" => [94, "\xb5i"], "\x99" => [76, "\xb5i"], "\x9a" => [104, "\xb5i"], "\x9b" => [16, "\xb5i"], "\x9c" => [94, "\xb5o"], "\x9d" => [76, "\xb5o"], "\x9e" => [104, "\xb5o"], "\x9f" => [16, "\xb5o"], "\xa0" => [94, "\xb5s"], "\xa1" => [76, "\xb5s"], "\xa2" => [104, "\xb5s"], "\xa3" => [16, "\xb5s"], "\xa4" => [94, "\xb5t"], "\xa5" => [76, "\xb5t"], "\xa6" => [104, "\xb5t"], "\xa7" => [16, "\xb5t"], "\xa8" => [77, "\xb5 "], "\xa9" => [18, "\xb5 "], "\xaa" => [77, "\xb5%"], "\xab" => [18, "\xb5%"], "\xac" => [77, "\xb5-"], "\xad" => [18, "\xb5-"], "\xae" => [77, "\xb5."], "\xaf" => [18, "\xb5."], "\xb0" => [77, "\xb5/"], "\xb1" => [18, "\xb5/"], "\xb2" => [77, "\xb53"], "\xb3" => [18, "\xb53"], "\xb4" => [77, "\xb54"], "\xb5" => [18, "\xb54"], "\xb6" => [77, "\xb55"], "\xb7" => [18, "\xb55"], "\xb8" => [77, "\xb56"], "\xb9" => [18, "\xb56"], "\xba" => [77, "\xb57"], "\xbb" => [18, "\xb57"], "\xbc" => [77, "\xb58"], "\xbd" => [18, "\xb58"], "\xbe" => [77, "\xb59"], "\xbf" => [18, "\xb59"], "\xc0" => [77, "\xb5="], "\xc1" => [18, "\xb5="], "\xc2" => [77, "\xb5A"], "\xc3" => [18, "\xb5A"], "\xc4" => [77, "\xb5_"], "\xc5" => [18, "\xb5_"], "\xc6" => [77, "\xb5b"], "\xc7" => [18, "\xb5b"], "\xc8" => [77, "\xb5d"], "\xc9" => [18, "\xb5d"], "\xca" => [77, "\xb5f"], "\xcb" => [18, "\xb5f"], "\xcc" => [77, "\xb5g"], "\xcd" => [18, "\xb5g"], "\xce" => [77, "\xb5h"], "\xcf" => [18, "\xb5h"], "\xd0" => [77, "\xb5l"], "\xd1" => [18, "\xb5l"], "\xd2" => [77, "\xb5m"], "\xd3" => [18, "\xb5m"], "\xd4" => [77, "\xb5n"], "\xd5" => [18, "\xb5n"], "\xd6" => [77, "\xb5p"], "\xd7" => [18, "\xb5p"], "\xd8" => [77, "\xb5r"], "\xd9" => [18, "\xb5r"], "\xda" => [77, "\xb5u"], "\xdb" => [18, "\xb5u"], "\xdc" => [0, "\xb5:"], "\xdd" => [0, "\xb5B"], "\xde" => [0, "\xb5C"], "\xdf" => [0, "\xb5D"], "\xe0" => [0, "\xb5E"], "\xe1" => [0, "\xb5F"], "\xe2" => [0, "\xb5G"], "\xe3" => [0, "\xb5H"], "\xe4" => [0, "\xb5I"], "\xe5" => [0, "\xb5J"], "\xe6" => [0, "\xb5K"], "\xe7" => [0, "\xb5L"], "\xe8" => [0, "\xb5M"], "\xe9" => [0, "\xb5N"], "\xea" => [0, "\xb5O"], "\xeb" => [0, "\xb5P"], "\xec" => [0, "\xb5Q"], "\xed" => [0, "\xb5R"], "\xee" => [0, "\xb5S"], "\xef" => [0, "\xb5T"], "\xf0" => [0, "\xb5U"], "\xf1" => [0, "\xb5V"], "\xf2" => [0, "\xb5W"], "\xf3" => [0, "\xb5Y"], "\xf4" => [0, "\xb5j"], "\xf5" => [0, "\xb5k"], "\xf6" => [0, "\xb5q"], "\xf7" => [0, "\xb5v"], "\xf8" => [0, "\xb5w"], "\xf9" => [0, "\xb5x"], "\xfa" => [0, "\xb5y"], "\xfb" => [0, "\xb5z"], "\xfc" => [82, "\xb5"], "\xfd" => [87, "\xb5"], "\xfe" => [130, "\xb5"], "\xff" => [9, "\xb5"]], ["\x00" => [77, "\xb20"], "\x01" => [18, "\xb20"], "\x02" => [77, "\xb21"], "\x03" => [18, "\xb21"], "\x04" => [77, "\xb22"], "\x05" => [18, "\xb22"], "\x06" => [77, "\xb2a"], "\x07" => [18, "\xb2a"], "\x08" => [77, "\xb2c"], "\t" => [18, "\xb2c"], "\n" => [77, "\xb2e"], "\v" => [18, "\xb2e"], "\f" => [77, "\xb2i"], "\r" => [18, "\xb2i"], "\x0e" => [77, "\xb2o"], "\x0f" => [18, "\xb2o"], "\x10" => [77, "\xb2s"], "\x11" => [18, "\xb2s"], "\x12" => [77, "\xb2t"], "\x13" => [18, "\xb2t"], "\x14" => [0, "\xb2 "], "\x15" => [0, "\xb2%"], "\x16" => [0, "\xb2-"], "\x17" => [0, "\xb2."], "\x18" => [0, "\xb2/"], "\x19" => [0, "\xb23"], "\x1a" => [0, "\xb24"], "\x1b" => [0, "\xb25"], "\x1c" => [0, "\xb26"], "\x1d" => [0, "\xb27"], "\x1e" => [0, "\xb28"], "\x1f" => [0, "\xb29"], " " => [0, "\xb2="], "!" => [0, "\xb2A"], "\"" => [0, "\xb2_"], "#" => [0, "\xb2b"], "\$" => [0, "\xb2d"], "%" => [0, "\xb2f"], "&" => [0, "\xb2g"], "'" => [0, "\xb2h"], "(" => [0, "\xb2l"], ")" => [0, "\xb2m"], "*" => [0, "\xb2n"], "+" => [0, "\xb2p"], "," => [0, "\xb2r"], "-" => [0, "\xb2u"], "." => [100, "\xb2"], "/" => [110, "\xb2"], [111, "\xb2"], [115, "\xb2"], [116, "\xb2"], [118, "\xb2"], [119, "\xb2"], [122, "\xb2"], [123, "\xb2"], [125, "\xb2"], [126, "\xb2"], [129, "\xb2"], ":" => [143, "\xb2"], ";" => [148, "\xb2"], "<" => [151, "\xb2"], "=" => [153, "\xb2"], ">" => [83, "\xb2"], "?" => [10, "\xb2"], "@" => [77, "\xb50"], "A" => [18, "\xb50"], "B" => [77, "\xb51"], "C" => [18, "\xb51"], "D" => [77, "\xb52"], "E" => [18, "\xb52"], "F" => [77, "\xb5a"], "G" => [18, "\xb5a"], "H" => [77, "\xb5c"], "I" => [18, "\xb5c"], "J" => [77, "\xb5e"], "K" => [18, "\xb5e"], "L" => [77, "\xb5i"], "M" => [18, "\xb5i"], "N" => [77, "\xb5o"], "O" => [18, "\xb5o"], "P" => [77, "\xb5s"], "Q" => [18, "\xb5s"], "R" => [77, "\xb5t"], "S" => [18, "\xb5t"], "T" => [0, "\xb5 "], "U" => [0, "\xb5%"], "V" => [0, "\xb5-"], "W" => [0, "\xb5."], "X" => [0, "\xb5/"], "Y" => [0, "\xb53"], "Z" => [0, "\xb54"], "[" => [0, "\xb55"], "\\" => [0, "\xb56"], "]" => [0, "\xb57"], "^" => [0, "\xb58"], "_" => [0, "\xb59"], "`" => [0, "\xb5="], "a" => [0, "\xb5A"], "b" => [0, "\xb5_"], "c" => [0, "\xb5b"], "d" => [0, "\xb5d"], "e" => [0, "\xb5f"], "f" => [0, "\xb5g"], "g" => [0, "\xb5h"], "h" => [0, "\xb5l"], "i" => [0, "\xb5m"], "j" => [0, "\xb5n"], "k" => [0, "\xb5p"], "l" => [0, "\xb5r"], "m" => [0, "\xb5u"], "n" => [100, "\xb5"], "o" => [110, "\xb5"], "p" => [111, "\xb5"], "q" => [115, "\xb5"], "r" => [116, "\xb5"], "s" => [118, "\xb5"], "t" => [119, "\xb5"], "u" => [122, "\xb5"], "v" => [123, "\xb5"], "w" => [125, "\xb5"], "x" => [126, "\xb5"], "y" => [129, "\xb5"], "z" => [143, "\xb5"], "{" => [148, "\xb5"], "|" => [151, "\xb5"], "}" => [153, "\xb5"], "~" => [83, "\xb5"], "" => [10, "\xb5"], "\x80" => [77, "\xb90"], "\x81" => [18, "\xb90"], "\x82" => [77, "\xb91"], "\x83" => [18, "\xb91"], "\x84" => [77, "\xb92"], "\x85" => [18, "\xb92"], "\x86" => [77, "\xb9a"], "\x87" => [18, "\xb9a"], "\x88" => [77, "\xb9c"], "\x89" => [18, "\xb9c"], "\x8a" => [77, "\xb9e"], "\x8b" => [18, "\xb9e"], "\x8c" => [77, "\xb9i"], "\x8d" => [18, "\xb9i"], "\x8e" => [77, "\xb9o"], "\x8f" => [18, "\xb9o"], "\x90" => [77, "\xb9s"], "\x91" => [18, "\xb9s"], "\x92" => [77, "\xb9t"], "\x93" => [18, "\xb9t"], "\x94" => [0, "\xb9 "], "\x95" => [0, "\xb9%"], "\x96" => [0, "\xb9-"], "\x97" => [0, "\xb9."], "\x98" => [0, "\xb9/"], "\x99" => [0, "\xb93"], "\x9a" => [0, "\xb94"], "\x9b" => [0, "\xb95"], "\x9c" => [0, "\xb96"], "\x9d" => [0, "\xb97"], "\x9e" => [0, "\xb98"], "\x9f" => [0, "\xb99"], "\xa0" => [0, "\xb9="], "\xa1" => [0, "\xb9A"], "\xa2" => [0, "\xb9_"], "\xa3" => [0, "\xb9b"], "\xa4" => [0, "\xb9d"], "\xa5" => [0, "\xb9f"], "\xa6" => [0, "\xb9g"], "\xa7" => [0, "\xb9h"], "\xa8" => [0, "\xb9l"], "\xa9" => [0, "\xb9m"], "\xaa" => [0, "\xb9n"], "\xab" => [0, "\xb9p"], "\xac" => [0, "\xb9r"], "\xad" => [0, "\xb9u"], "\xae" => [100, "\xb9"], "\xaf" => [110, "\xb9"], "\xb0" => [111, "\xb9"], "\xb1" => [115, "\xb9"], "\xb2" => [116, "\xb9"], "\xb3" => [118, "\xb9"], "\xb4" => [119, "\xb9"], "\xb5" => [122, "\xb9"], "\xb6" => [123, "\xb9"], "\xb7" => [125, "\xb9"], "\xb8" => [126, "\xb9"], "\xb9" => [129, "\xb9"], "\xba" => [143, "\xb9"], "\xbb" => [148, "\xb9"], "\xbc" => [151, "\xb9"], "\xbd" => [153, "\xb9"], "\xbe" => [83, "\xb9"], "\xbf" => [10, "\xb9"], "\xc0" => [77, "\xba0"], "\xc1" => [18, "\xba0"], "\xc2" => [77, "\xba1"], "\xc3" => [18, "\xba1"], "\xc4" => [77, "\xba2"], "\xc5" => [18, "\xba2"], "\xc6" => [77, "\xbaa"], "\xc7" => [18, "\xbaa"], "\xc8" => [77, "\xbac"], "\xc9" => [18, "\xbac"], "\xca" => [77, "\xbae"], "\xcb" => [18, "\xbae"], "\xcc" => [77, "\xbai"], "\xcd" => [18, "\xbai"], "\xce" => [77, "\xbao"], "\xcf" => [18, "\xbao"], "\xd0" => [77, "\xbas"], "\xd1" => [18, "\xbas"], "\xd2" => [77, "\xbat"], "\xd3" => [18, "\xbat"], "\xd4" => [0, "\xba "], "\xd5" => [0, "\xba%"], "\xd6" => [0, "\xba-"], "\xd7" => [0, "\xba."], "\xd8" => [0, "\xba/"], "\xd9" => [0, "\xba3"], "\xda" => [0, "\xba4"], "\xdb" => [0, "\xba5"], "\xdc" => [0, "\xba6"], "\xdd" => [0, "\xba7"], "\xde" => [0, "\xba8"], "\xdf" => [0, "\xba9"], "\xe0" => [0, "\xba="], "\xe1" => [0, "\xbaA"], "\xe2" => [0, "\xba_"], "\xe3" => [0, "\xbab"], "\xe4" => [0, "\xbad"], "\xe5" => [0, "\xbaf"], "\xe6" => [0, "\xbag"], "\xe7" => [0, "\xbah"], "\xe8" => [0, "\xbal"], "\xe9" => [0, "\xbam"], "\xea" => [0, "\xban"], "\xeb" => [0, "\xbap"], "\xec" => [0, "\xbar"], "\xed" => [0, "\xbau"], "\xee" => [100, "\xba"], "\xef" => [110, "\xba"], "\xf0" => [111, "\xba"], "\xf1" => [115, "\xba"], "\xf2" => [116, "\xba"], "\xf3" => [118, "\xba"], "\xf4" => [119, "\xba"], "\xf5" => [122, "\xba"], "\xf6" => [123, "\xba"], "\xf7" => [125, "\xba"], "\xf8" => [126, "\xba"], "\xf9" => [129, "\xba"], "\xfa" => [143, "\xba"], "\xfb" => [148, "\xba"], "\xfc" => [151, "\xba"], "\xfd" => [153, "\xba"], "\xfe" => [83, "\xba"], "\xff" => [10, "\xba"]], ["\x00" => [0, "\xb20"], "\x01" => [0, "\xb21"], "\x02" => [0, "\xb22"], "\x03" => [0, "\xb2a"], "\x04" => [0, "\xb2c"], "\x05" => [0, "\xb2e"], "\x06" => [0, "\xb2i"], "\x07" => [0, "\xb2o"], "\x08" => [0, "\xb2s"], "\t" => [0, "\xb2t"], "\n" => [73, "\xb2"], "\v" => [88, "\xb2"], "\f" => [89, "\xb2"], "\r" => [96, "\xb2"], "\x0e" => [97, "\xb2"], "\x0f" => [99, "\xb2"], "\x10" => [106, "\xb2"], "\x11" => [136, "\xb2"], "\x12" => [139, "\xb2"], "\x13" => [141, "\xb2"], "\x14" => [145, "\xb2"], "\x15" => [147, "\xb2"], "\x16" => [149, "\xb2"], "\x17" => [101, "\xb2"], "\x18" => [112, "\xb2"], "\x19" => [117, "\xb2"], "\x1a" => [120, "\xb2"], "\x1b" => [124, "\xb2"], "\x1c" => [127, "\xb2"], "\x1d" => [144, "\xb2"], "\x1e" => [152, "\xb2"], "\x1f" => [11, "\xb2"], " " => [0, "\xb50"], "!" => [0, "\xb51"], "\"" => [0, "\xb52"], "#" => [0, "\xb5a"], "\$" => [0, "\xb5c"], "%" => [0, "\xb5e"], "&" => [0, "\xb5i"], "'" => [0, "\xb5o"], "(" => [0, "\xb5s"], ")" => [0, "\xb5t"], "*" => [73, "\xb5"], "+" => [88, "\xb5"], "," => [89, "\xb5"], "-" => [96, "\xb5"], "." => [97, "\xb5"], "/" => [99, "\xb5"], [106, "\xb5"], [136, "\xb5"], [139, "\xb5"], [141, "\xb5"], [145, "\xb5"], [147, "\xb5"], [149, "\xb5"], [101, "\xb5"], [112, "\xb5"], [117, "\xb5"], ":" => [120, "\xb5"], ";" => [124, "\xb5"], "<" => [127, "\xb5"], "=" => [144, "\xb5"], ">" => [152, "\xb5"], "?" => [11, "\xb5"], "@" => [0, "\xb90"], "A" => [0, "\xb91"], "B" => [0, "\xb92"], "C" => [0, "\xb9a"], "D" => [0, "\xb9c"], "E" => [0, "\xb9e"], "F" => [0, "\xb9i"], "G" => [0, "\xb9o"], "H" => [0, "\xb9s"], "I" => [0, "\xb9t"], "J" => [73, "\xb9"], "K" => [88, "\xb9"], "L" => [89, "\xb9"], "M" => [96, "\xb9"], "N" => [97, "\xb9"], "O" => [99, "\xb9"], "P" => [106, "\xb9"], "Q" => [136, "\xb9"], "R" => [139, "\xb9"], "S" => [141, "\xb9"], "T" => [145, "\xb9"], "U" => [147, "\xb9"], "V" => [149, "\xb9"], "W" => [101, "\xb9"], "X" => [112, "\xb9"], "Y" => [117, "\xb9"], "Z" => [120, "\xb9"], "[" => [124, "\xb9"], "\\" => [127, "\xb9"], "]" => [144, "\xb9"], "^" => [152, "\xb9"], "_" => [11, "\xb9"], "`" => [0, "\xba0"], "a" => [0, "\xba1"], "b" => [0, "\xba2"], "c" => [0, "\xbaa"], "d" => [0, "\xbac"], "e" => [0, "\xbae"], "f" => [0, "\xbai"], "g" => [0, "\xbao"], "h" => [0, "\xbas"], "i" => [0, "\xbat"], "j" => [73, "\xba"], "k" => [88, "\xba"], "l" => [89, "\xba"], "m" => [96, "\xba"], "n" => [97, "\xba"], "o" => [99, "\xba"], "p" => [106, "\xba"], "q" => [136, "\xba"], "r" => [139, "\xba"], "s" => [141, "\xba"], "t" => [145, "\xba"], "u" => [147, "\xba"], "v" => [149, "\xba"], "w" => [101, "\xba"], "x" => [112, "\xba"], "y" => [117, "\xba"], "z" => [120, "\xba"], "{" => [124, "\xba"], "|" => [127, "\xba"], "}" => [144, "\xba"], "~" => [152, "\xba"], "" => [11, "\xba"], "\x80" => [0, "\xbb0"], "\x81" => [0, "\xbb1"], "\x82" => [0, "\xbb2"], "\x83" => [0, "\xbba"], "\x84" => [0, "\xbbc"], "\x85" => [0, "\xbbe"], "\x86" => [0, "\xbbi"], "\x87" => [0, "\xbbo"], "\x88" => [0, "\xbbs"], "\x89" => [0, "\xbbt"], "\x8a" => [73, "\xbb"], "\x8b" => [88, "\xbb"], "\x8c" => [89, "\xbb"], "\x8d" => [96, "\xbb"], "\x8e" => [97, "\xbb"], "\x8f" => [99, "\xbb"], "\x90" => [106, "\xbb"], "\x91" => [136, "\xbb"], "\x92" => [139, "\xbb"], "\x93" => [141, "\xbb"], "\x94" => [145, "\xbb"], "\x95" => [147, "\xbb"], "\x96" => [149, "\xbb"], "\x97" => [101, "\xbb"], "\x98" => [112, "\xbb"], "\x99" => [117, "\xbb"], "\x9a" => [120, "\xbb"], "\x9b" => [124, "\xbb"], "\x9c" => [127, "\xbb"], "\x9d" => [144, "\xbb"], "\x9e" => [152, "\xbb"], "\x9f" => [11, "\xbb"], "\xa0" => [0, "\xbd0"], "\xa1" => [0, "\xbd1"], "\xa2" => [0, "\xbd2"], "\xa3" => [0, "\xbda"], "\xa4" => [0, "\xbdc"], "\xa5" => [0, "\xbde"], "\xa6" => [0, "\xbdi"], "\xa7" => [0, "\xbdo"], "\xa8" => [0, "\xbds"], "\xa9" => [0, "\xbdt"], "\xaa" => [73, "\xbd"], "\xab" => [88, "\xbd"], "\xac" => [89, "\xbd"], "\xad" => [96, "\xbd"], "\xae" => [97, "\xbd"], "\xaf" => [99, "\xbd"], "\xb0" => [106, "\xbd"], "\xb1" => [136, "\xbd"], "\xb2" => [139, "\xbd"], "\xb3" => [141, "\xbd"], "\xb4" => [145, "\xbd"], "\xb5" => [147, "\xbd"], "\xb6" => [149, "\xbd"], "\xb7" => [101, "\xbd"], "\xb8" => [112, "\xbd"], "\xb9" => [117, "\xbd"], "\xba" => [120, "\xbd"], "\xbb" => [124, "\xbd"], "\xbc" => [127, "\xbd"], "\xbd" => [144, "\xbd"], "\xbe" => [152, "\xbd"], "\xbf" => [11, "\xbd"], "\xc0" => [0, "\xbe0"], "\xc1" => [0, "\xbe1"], "\xc2" => [0, "\xbe2"], "\xc3" => [0, "\xbea"], "\xc4" => [0, "\xbec"], "\xc5" => [0, "\xbee"], "\xc6" => [0, "\xbei"], "\xc7" => [0, "\xbeo"], "\xc8" => [0, "\xbes"], "\xc9" => [0, "\xbet"], "\xca" => [73, "\xbe"], "\xcb" => [88, "\xbe"], "\xcc" => [89, "\xbe"], "\xcd" => [96, "\xbe"], "\xce" => [97, "\xbe"], "\xcf" => [99, "\xbe"], "\xd0" => [106, "\xbe"], "\xd1" => [136, "\xbe"], "\xd2" => [139, "\xbe"], "\xd3" => [141, "\xbe"], "\xd4" => [145, "\xbe"], "\xd5" => [147, "\xbe"], "\xd6" => [149, "\xbe"], "\xd7" => [101, "\xbe"], "\xd8" => [112, "\xbe"], "\xd9" => [117, "\xbe"], "\xda" => [120, "\xbe"], "\xdb" => [124, "\xbe"], "\xdc" => [127, "\xbe"], "\xdd" => [144, "\xbe"], "\xde" => [152, "\xbe"], "\xdf" => [11, "\xbe"], "\xe0" => [0, "\xc40"], "\xe1" => [0, "\xc41"], "\xe2" => [0, "\xc42"], "\xe3" => [0, "\xc4a"], "\xe4" => [0, "\xc4c"], "\xe5" => [0, "\xc4e"], "\xe6" => [0, "\xc4i"], "\xe7" => [0, "\xc4o"], "\xe8" => [0, "\xc4s"], "\xe9" => [0, "\xc4t"], "\xea" => [73, "\xc4"], "\xeb" => [88, "\xc4"], "\xec" => [89, "\xc4"], "\xed" => [96, "\xc4"], "\xee" => [97, "\xc4"], "\xef" => [99, "\xc4"], "\xf0" => [106, "\xc4"], "\xf1" => [136, "\xc4"], "\xf2" => [139, "\xc4"], "\xf3" => [141, "\xc4"], "\xf4" => [145, "\xc4"], "\xf5" => [147, "\xc4"], "\xf6" => [149, "\xc4"], "\xf7" => [101, "\xc4"], "\xf8" => [112, "\xc4"], "\xf9" => [117, "\xc4"], "\xfa" => [120, "\xc4"], "\xfb" => [124, "\xc4"], "\xfc" => [127, "\xc4"], "\xfd" => [144, "\xc4"], "\xfe" => [152, "\xc4"], "\xff" => [11, "\xc4"]], ["\x00" => [94, "\xb30"], "\x01" => [76, "\xb30"], "\x02" => [104, "\xb30"], "\x03" => [16, "\xb30"], "\x04" => [94, "\xb31"], "\x05" => [76, "\xb31"], "\x06" => [104, "\xb31"], "\x07" => [16, "\xb31"], "\x08" => [94, "\xb32"], "\t" => [76, "\xb32"], "\n" => [104, "\xb32"], "\v" => [16, "\xb32"], "\f" => [94, "\xb3a"], "\r" => [76, "\xb3a"], "\x0e" => [104, "\xb3a"], "\x0f" => [16, "\xb3a"], "\x10" => [94, "\xb3c"], "\x11" => [76, "\xb3c"], "\x12" => [104, "\xb3c"], "\x13" => [16, "\xb3c"], "\x14" => [94, "\xb3e"], "\x15" => [76, "\xb3e"], "\x16" => [104, "\xb3e"], "\x17" => [16, "\xb3e"], "\x18" => [94, "\xb3i"], "\x19" => [76, "\xb3i"], "\x1a" => [104, "\xb3i"], "\x1b" => [16, "\xb3i"], "\x1c" => [94, "\xb3o"], "\x1d" => [76, "\xb3o"], "\x1e" => [104, "\xb3o"], "\x1f" => [16, "\xb3o"], " " => [94, "\xb3s"], "!" => [76, "\xb3s"], "\"" => [104, "\xb3s"], "#" => [16, "\xb3s"], "\$" => [94, "\xb3t"], "%" => [76, "\xb3t"], "&" => [104, "\xb3t"], "'" => [16, "\xb3t"], "(" => [77, "\xb3 "], ")" => [18, "\xb3 "], "*" => [77, "\xb3%"], "+" => [18, "\xb3%"], "," => [77, "\xb3-"], "-" => [18, "\xb3-"], "." => [77, "\xb3."], "/" => [18, "\xb3."], [77, "\xb3/"], [18, "\xb3/"], [77, "\xb33"], [18, "\xb33"], [77, "\xb34"], [18, "\xb34"], [77, "\xb35"], [18, "\xb35"], [77, "\xb36"], [18, "\xb36"], ":" => [77, "\xb37"], ";" => [18, "\xb37"], "<" => [77, "\xb38"], "=" => [18, "\xb38"], ">" => [77, "\xb39"], "?" => [18, "\xb39"], "@" => [77, "\xb3="], "A" => [18, "\xb3="], "B" => [77, "\xb3A"], "C" => [18, "\xb3A"], "D" => [77, "\xb3_"], "E" => [18, "\xb3_"], "F" => [77, "\xb3b"], "G" => [18, "\xb3b"], "H" => [77, "\xb3d"], "I" => [18, "\xb3d"], "J" => [77, "\xb3f"], "K" => [18, "\xb3f"], "L" => [77, "\xb3g"], "M" => [18, "\xb3g"], "N" => [77, "\xb3h"], "O" => [18, "\xb3h"], "P" => [77, "\xb3l"], "Q" => [18, "\xb3l"], "R" => [77, "\xb3m"], "S" => [18, "\xb3m"], "T" => [77, "\xb3n"], "U" => [18, "\xb3n"], "V" => [77, "\xb3p"], "W" => [18, "\xb3p"], "X" => [77, "\xb3r"], "Y" => [18, "\xb3r"], "Z" => [77, "\xb3u"], "[" => [18, "\xb3u"], "\\" => [0, "\xb3:"], "]" => [0, "\xb3B"], "^" => [0, "\xb3C"], "_" => [0, "\xb3D"], "`" => [0, "\xb3E"], "a" => [0, "\xb3F"], "b" => [0, "\xb3G"], "c" => [0, "\xb3H"], "d" => [0, "\xb3I"], "e" => [0, "\xb3J"], "f" => [0, "\xb3K"], "g" => [0, "\xb3L"], "h" => [0, "\xb3M"], "i" => [0, "\xb3N"], "j" => [0, "\xb3O"], "k" => [0, "\xb3P"], "l" => [0, "\xb3Q"], "m" => [0, "\xb3R"], "n" => [0, "\xb3S"], "o" => [0, "\xb3T"], "p" => [0, "\xb3U"], "q" => [0, "\xb3V"], "r" => [0, "\xb3W"], "s" => [0, "\xb3Y"], "t" => [0, "\xb3j"], "u" => [0, "\xb3k"], "v" => [0, "\xb3q"], "w" => [0, "\xb3v"], "x" => [0, "\xb3w"], "y" => [0, "\xb3x"], "z" => [0, "\xb3y"], "{" => [0, "\xb3z"], "|" => [82, "\xb3"], "}" => [87, "\xb3"], "~" => [130, "\xb3"], "" => [9, "\xb3"], "\x80" => [94, "\xd10"], "\x81" => [76, "\xd10"], "\x82" => [104, "\xd10"], "\x83" => [16, "\xd10"], "\x84" => [94, "\xd11"], "\x85" => [76, "\xd11"], "\x86" => [104, "\xd11"], "\x87" => [16, "\xd11"], "\x88" => [94, "\xd12"], "\x89" => [76, "\xd12"], "\x8a" => [104, "\xd12"], "\x8b" => [16, "\xd12"], "\x8c" => [94, "\xd1a"], "\x8d" => [76, "\xd1a"], "\x8e" => [104, "\xd1a"], "\x8f" => [16, "\xd1a"], "\x90" => [94, "\xd1c"], "\x91" => [76, "\xd1c"], "\x92" => [104, "\xd1c"], "\x93" => [16, "\xd1c"], "\x94" => [94, "\xd1e"], "\x95" => [76, "\xd1e"], "\x96" => [104, "\xd1e"], "\x97" => [16, "\xd1e"], "\x98" => [94, "\xd1i"], "\x99" => [76, "\xd1i"], "\x9a" => [104, "\xd1i"], "\x9b" => [16, "\xd1i"], "\x9c" => [94, "\xd1o"], "\x9d" => [76, "\xd1o"], "\x9e" => [104, "\xd1o"], "\x9f" => [16, "\xd1o"], "\xa0" => [94, "\xd1s"], "\xa1" => [76, "\xd1s"], "\xa2" => [104, "\xd1s"], "\xa3" => [16, "\xd1s"], "\xa4" => [94, "\xd1t"], "\xa5" => [76, "\xd1t"], "\xa6" => [104, "\xd1t"], "\xa7" => [16, "\xd1t"], "\xa8" => [77, "\xd1 "], "\xa9" => [18, "\xd1 "], "\xaa" => [77, "\xd1%"], "\xab" => [18, "\xd1%"], "\xac" => [77, "\xd1-"], "\xad" => [18, "\xd1-"], "\xae" => [77, "\xd1."], "\xaf" => [18, "\xd1."], "\xb0" => [77, "\xd1/"], "\xb1" => [18, "\xd1/"], "\xb2" => [77, "\xd13"], "\xb3" => [18, "\xd13"], "\xb4" => [77, "\xd14"], "\xb5" => [18, "\xd14"], "\xb6" => [77, "\xd15"], "\xb7" => [18, "\xd15"], "\xb8" => [77, "\xd16"], "\xb9" => [18, "\xd16"], "\xba" => [77, "\xd17"], "\xbb" => [18, "\xd17"], "\xbc" => [77, "\xd18"], "\xbd" => [18, "\xd18"], "\xbe" => [77, "\xd19"], "\xbf" => [18, "\xd19"], "\xc0" => [77, "\xd1="], "\xc1" => [18, "\xd1="], "\xc2" => [77, "\xd1A"], "\xc3" => [18, "\xd1A"], "\xc4" => [77, "\xd1_"], "\xc5" => [18, "\xd1_"], "\xc6" => [77, "\xd1b"], "\xc7" => [18, "\xd1b"], "\xc8" => [77, "\xd1d"], "\xc9" => [18, "\xd1d"], "\xca" => [77, "\xd1f"], "\xcb" => [18, "\xd1f"], "\xcc" => [77, "\xd1g"], "\xcd" => [18, "\xd1g"], "\xce" => [77, "\xd1h"], "\xcf" => [18, "\xd1h"], "\xd0" => [77, "\xd1l"], "\xd1" => [18, "\xd1l"], "\xd2" => [77, "\xd1m"], "\xd3" => [18, "\xd1m"], "\xd4" => [77, "\xd1n"], "\xd5" => [18, "\xd1n"], "\xd6" => [77, "\xd1p"], "\xd7" => [18, "\xd1p"], "\xd8" => [77, "\xd1r"], "\xd9" => [18, "\xd1r"], "\xda" => [77, "\xd1u"], "\xdb" => [18, "\xd1u"], "\xdc" => [0, "\xd1:"], "\xdd" => [0, "\xd1B"], "\xde" => [0, "\xd1C"], "\xdf" => [0, "\xd1D"], "\xe0" => [0, "\xd1E"], "\xe1" => [0, "\xd1F"], "\xe2" => [0, "\xd1G"], "\xe3" => [0, "\xd1H"], "\xe4" => [0, "\xd1I"], "\xe5" => [0, "\xd1J"], "\xe6" => [0, "\xd1K"], "\xe7" => [0, "\xd1L"], "\xe8" => [0, "\xd1M"], "\xe9" => [0, "\xd1N"], "\xea" => [0, "\xd1O"], "\xeb" => [0, "\xd1P"], "\xec" => [0, "\xd1Q"], "\xed" => [0, "\xd1R"], "\xee" => [0, "\xd1S"], "\xef" => [0, "\xd1T"], "\xf0" => [0, "\xd1U"], "\xf1" => [0, "\xd1V"], "\xf2" => [0, "\xd1W"], "\xf3" => [0, "\xd1Y"], "\xf4" => [0, "\xd1j"], "\xf5" => [0, "\xd1k"], "\xf6" => [0, "\xd1q"], "\xf7" => [0, "\xd1v"], "\xf8" => [0, "\xd1w"], "\xf9" => [0, "\xd1x"], "\xfa" => [0, "\xd1y"], "\xfb" => [0, "\xd1z"], "\xfc" => [82, "\xd1"], "\xfd" => [87, "\xd1"], "\xfe" => [130, "\xd1"], "\xff" => [9, "\xd1"]], ["\x00" => [94, "\xb60"], "\x01" => [76, "\xb60"], "\x02" => [104, "\xb60"], "\x03" => [16, "\xb60"], "\x04" => [94, "\xb61"], "\x05" => [76, "\xb61"], "\x06" => [104, "\xb61"], "\x07" => [16, "\xb61"], "\x08" => [94, "\xb62"], "\t" => [76, "\xb62"], "\n" => [104, "\xb62"], "\v" => [16, "\xb62"], "\f" => [94, "\xb6a"], "\r" => [76, "\xb6a"], "\x0e" => [104, "\xb6a"], "\x0f" => [16, "\xb6a"], "\x10" => [94, "\xb6c"], "\x11" => [76, "\xb6c"], "\x12" => [104, "\xb6c"], "\x13" => [16, "\xb6c"], "\x14" => [94, "\xb6e"], "\x15" => [76, "\xb6e"], "\x16" => [104, "\xb6e"], "\x17" => [16, "\xb6e"], "\x18" => [94, "\xb6i"], "\x19" => [76, "\xb6i"], "\x1a" => [104, "\xb6i"], "\x1b" => [16, "\xb6i"], "\x1c" => [94, "\xb6o"], "\x1d" => [76, "\xb6o"], "\x1e" => [104, "\xb6o"], "\x1f" => [16, "\xb6o"], " " => [94, "\xb6s"], "!" => [76, "\xb6s"], "\"" => [104, "\xb6s"], "#" => [16, "\xb6s"], "\$" => [94, "\xb6t"], "%" => [76, "\xb6t"], "&" => [104, "\xb6t"], "'" => [16, "\xb6t"], "(" => [77, "\xb6 "], ")" => [18, "\xb6 "], "*" => [77, "\xb6%"], "+" => [18, "\xb6%"], "," => [77, "\xb6-"], "-" => [18, "\xb6-"], "." => [77, "\xb6."], "/" => [18, "\xb6."], [77, "\xb6/"], [18, "\xb6/"], [77, "\xb63"], [18, "\xb63"], [77, "\xb64"], [18, "\xb64"], [77, "\xb65"], [18, "\xb65"], [77, "\xb66"], [18, "\xb66"], ":" => [77, "\xb67"], ";" => [18, "\xb67"], "<" => [77, "\xb68"], "=" => [18, "\xb68"], ">" => [77, "\xb69"], "?" => [18, "\xb69"], "@" => [77, "\xb6="], "A" => [18, "\xb6="], "B" => [77, "\xb6A"], "C" => [18, "\xb6A"], "D" => [77, "\xb6_"], "E" => [18, "\xb6_"], "F" => [77, "\xb6b"], "G" => [18, "\xb6b"], "H" => [77, "\xb6d"], "I" => [18, "\xb6d"], "J" => [77, "\xb6f"], "K" => [18, "\xb6f"], "L" => [77, "\xb6g"], "M" => [18, "\xb6g"], "N" => [77, "\xb6h"], "O" => [18, "\xb6h"], "P" => [77, "\xb6l"], "Q" => [18, "\xb6l"], "R" => [77, "\xb6m"], "S" => [18, "\xb6m"], "T" => [77, "\xb6n"], "U" => [18, "\xb6n"], "V" => [77, "\xb6p"], "W" => [18, "\xb6p"], "X" => [77, "\xb6r"], "Y" => [18, "\xb6r"], "Z" => [77, "\xb6u"], "[" => [18, "\xb6u"], "\\" => [0, "\xb6:"], "]" => [0, "\xb6B"], "^" => [0, "\xb6C"], "_" => [0, "\xb6D"], "`" => [0, "\xb6E"], "a" => [0, "\xb6F"], "b" => [0, "\xb6G"], "c" => [0, "\xb6H"], "d" => [0, "\xb6I"], "e" => [0, "\xb6J"], "f" => [0, "\xb6K"], "g" => [0, "\xb6L"], "h" => [0, "\xb6M"], "i" => [0, "\xb6N"], "j" => [0, "\xb6O"], "k" => [0, "\xb6P"], "l" => [0, "\xb6Q"], "m" => [0, "\xb6R"], "n" => [0, "\xb6S"], "o" => [0, "\xb6T"], "p" => [0, "\xb6U"], "q" => [0, "\xb6V"], "r" => [0, "\xb6W"], "s" => [0, "\xb6Y"], "t" => [0, "\xb6j"], "u" => [0, "\xb6k"], "v" => [0, "\xb6q"], "w" => [0, "\xb6v"], "x" => [0, "\xb6w"], "y" => [0, "\xb6x"], "z" => [0, "\xb6y"], "{" => [0, "\xb6z"], "|" => [82, "\xb6"], "}" => [87, "\xb6"], "~" => [130, "\xb6"], "" => [9, "\xb6"], "\x80" => [94, "\xb70"], "\x81" => [76, "\xb70"], "\x82" => [104, "\xb70"], "\x83" => [16, "\xb70"], "\x84" => [94, "\xb71"], "\x85" => [76, "\xb71"], "\x86" => [104, "\xb71"], "\x87" => [16, "\xb71"], "\x88" => [94, "\xb72"], "\x89" => [76, "\xb72"], "\x8a" => [104, "\xb72"], "\x8b" => [16, "\xb72"], "\x8c" => [94, "\xb7a"], "\x8d" => [76, "\xb7a"], "\x8e" => [104, "\xb7a"], "\x8f" => [16, "\xb7a"], "\x90" => [94, "\xb7c"], "\x91" => [76, "\xb7c"], "\x92" => [104, "\xb7c"], "\x93" => [16, "\xb7c"], "\x94" => [94, "\xb7e"], "\x95" => [76, "\xb7e"], "\x96" => [104, "\xb7e"], "\x97" => [16, "\xb7e"], "\x98" => [94, "\xb7i"], "\x99" => [76, "\xb7i"], "\x9a" => [104, "\xb7i"], "\x9b" => [16, "\xb7i"], "\x9c" => [94, "\xb7o"], "\x9d" => [76, "\xb7o"], "\x9e" => [104, "\xb7o"], "\x9f" => [16, "\xb7o"], "\xa0" => [94, "\xb7s"], "\xa1" => [76, "\xb7s"], "\xa2" => [104, "\xb7s"], "\xa3" => [16, "\xb7s"], "\xa4" => [94, "\xb7t"], "\xa5" => [76, "\xb7t"], "\xa6" => [104, "\xb7t"], "\xa7" => [16, "\xb7t"], "\xa8" => [77, "\xb7 "], "\xa9" => [18, "\xb7 "], "\xaa" => [77, "\xb7%"], "\xab" => [18, "\xb7%"], "\xac" => [77, "\xb7-"], "\xad" => [18, "\xb7-"], "\xae" => [77, "\xb7."], "\xaf" => [18, "\xb7."], "\xb0" => [77, "\xb7/"], "\xb1" => [18, "\xb7/"], "\xb2" => [77, "\xb73"], "\xb3" => [18, "\xb73"], "\xb4" => [77, "\xb74"], "\xb5" => [18, "\xb74"], "\xb6" => [77, "\xb75"], "\xb7" => [18, "\xb75"], "\xb8" => [77, "\xb76"], "\xb9" => [18, "\xb76"], "\xba" => [77, "\xb77"], "\xbb" => [18, "\xb77"], "\xbc" => [77, "\xb78"], "\xbd" => [18, "\xb78"], "\xbe" => [77, "\xb79"], "\xbf" => [18, "\xb79"], "\xc0" => [77, "\xb7="], "\xc1" => [18, "\xb7="], "\xc2" => [77, "\xb7A"], "\xc3" => [18, "\xb7A"], "\xc4" => [77, "\xb7_"], "\xc5" => [18, "\xb7_"], "\xc6" => [77, "\xb7b"], "\xc7" => [18, "\xb7b"], "\xc8" => [77, "\xb7d"], "\xc9" => [18, "\xb7d"], "\xca" => [77, "\xb7f"], "\xcb" => [18, "\xb7f"], "\xcc" => [77, "\xb7g"], "\xcd" => [18, "\xb7g"], "\xce" => [77, "\xb7h"], "\xcf" => [18, "\xb7h"], "\xd0" => [77, "\xb7l"], "\xd1" => [18, "\xb7l"], "\xd2" => [77, "\xb7m"], "\xd3" => [18, "\xb7m"], "\xd4" => [77, "\xb7n"], "\xd5" => [18, "\xb7n"], "\xd6" => [77, "\xb7p"], "\xd7" => [18, "\xb7p"], "\xd8" => [77, "\xb7r"], "\xd9" => [18, "\xb7r"], "\xda" => [77, "\xb7u"], "\xdb" => [18, "\xb7u"], "\xdc" => [0, "\xb7:"], "\xdd" => [0, "\xb7B"], "\xde" => [0, "\xb7C"], "\xdf" => [0, "\xb7D"], "\xe0" => [0, "\xb7E"], "\xe1" => [0, "\xb7F"], "\xe2" => [0, "\xb7G"], "\xe3" => [0, "\xb7H"], "\xe4" => [0, "\xb7I"], "\xe5" => [0, "\xb7J"], "\xe6" => [0, "\xb7K"], "\xe7" => [0, "\xb7L"], "\xe8" => [0, "\xb7M"], "\xe9" => [0, "\xb7N"], "\xea" => [0, "\xb7O"], "\xeb" => [0, "\xb7P"], "\xec" => [0, "\xb7Q"], "\xed" => [0, "\xb7R"], "\xee" => [0, "\xb7S"], "\xef" => [0, "\xb7T"], "\xf0" => [0, "\xb7U"], "\xf1" => [0, "\xb7V"], "\xf2" => [0, "\xb7W"], "\xf3" => [0, "\xb7Y"], "\xf4" => [0, "\xb7j"], "\xf5" => [0, "\xb7k"], "\xf6" => [0, "\xb7q"], "\xf7" => [0, "\xb7v"], "\xf8" => [0, "\xb7w"], "\xf9" => [0, "\xb7x"], "\xfa" => [0, "\xb7y"], "\xfb" => [0, "\xb7z"], "\xfc" => [82, "\xb7"], "\xfd" => [87, "\xb7"], "\xfe" => [130, "\xb7"], "\xff" => [9, "\xb7"]], ["\x00" => [94, "\xb80"], "\x01" => [76, "\xb80"], "\x02" => [104, "\xb80"], "\x03" => [16, "\xb80"], "\x04" => [94, "\xb81"], "\x05" => [76, "\xb81"], "\x06" => [104, "\xb81"], "\x07" => [16, "\xb81"], "\x08" => [94, "\xb82"], "\t" => [76, "\xb82"], "\n" => [104, "\xb82"], "\v" => [16, "\xb82"], "\f" => [94, "\xb8a"], "\r" => [76, "\xb8a"], "\x0e" => [104, "\xb8a"], "\x0f" => [16, "\xb8a"], "\x10" => [94, "\xb8c"], "\x11" => [76, "\xb8c"], "\x12" => [104, "\xb8c"], "\x13" => [16, "\xb8c"], "\x14" => [94, "\xb8e"], "\x15" => [76, "\xb8e"], "\x16" => [104, "\xb8e"], "\x17" => [16, "\xb8e"], "\x18" => [94, "\xb8i"], "\x19" => [76, "\xb8i"], "\x1a" => [104, "\xb8i"], "\x1b" => [16, "\xb8i"], "\x1c" => [94, "\xb8o"], "\x1d" => [76, "\xb8o"], "\x1e" => [104, "\xb8o"], "\x1f" => [16, "\xb8o"], " " => [94, "\xb8s"], "!" => [76, "\xb8s"], "\"" => [104, "\xb8s"], "#" => [16, "\xb8s"], "\$" => [94, "\xb8t"], "%" => [76, "\xb8t"], "&" => [104, "\xb8t"], "'" => [16, "\xb8t"], "(" => [77, "\xb8 "], ")" => [18, "\xb8 "], "*" => [77, "\xb8%"], "+" => [18, "\xb8%"], "," => [77, "\xb8-"], "-" => [18, "\xb8-"], "." => [77, "\xb8."], "/" => [18, "\xb8."], [77, "\xb8/"], [18, "\xb8/"], [77, "\xb83"], [18, "\xb83"], [77, "\xb84"], [18, "\xb84"], [77, "\xb85"], [18, "\xb85"], [77, "\xb86"], [18, "\xb86"], ":" => [77, "\xb87"], ";" => [18, "\xb87"], "<" => [77, "\xb88"], "=" => [18, "\xb88"], ">" => [77, "\xb89"], "?" => [18, "\xb89"], "@" => [77, "\xb8="], "A" => [18, "\xb8="], "B" => [77, "\xb8A"], "C" => [18, "\xb8A"], "D" => [77, "\xb8_"], "E" => [18, "\xb8_"], "F" => [77, "\xb8b"], "G" => [18, "\xb8b"], "H" => [77, "\xb8d"], "I" => [18, "\xb8d"], "J" => [77, "\xb8f"], "K" => [18, "\xb8f"], "L" => [77, "\xb8g"], "M" => [18, "\xb8g"], "N" => [77, "\xb8h"], "O" => [18, "\xb8h"], "P" => [77, "\xb8l"], "Q" => [18, "\xb8l"], "R" => [77, "\xb8m"], "S" => [18, "\xb8m"], "T" => [77, "\xb8n"], "U" => [18, "\xb8n"], "V" => [77, "\xb8p"], "W" => [18, "\xb8p"], "X" => [77, "\xb8r"], "Y" => [18, "\xb8r"], "Z" => [77, "\xb8u"], "[" => [18, "\xb8u"], "\\" => [0, "\xb8:"], "]" => [0, "\xb8B"], "^" => [0, "\xb8C"], "_" => [0, "\xb8D"], "`" => [0, "\xb8E"], "a" => [0, "\xb8F"], "b" => [0, "\xb8G"], "c" => [0, "\xb8H"], "d" => [0, "\xb8I"], "e" => [0, "\xb8J"], "f" => [0, "\xb8K"], "g" => [0, "\xb8L"], "h" => [0, "\xb8M"], "i" => [0, "\xb8N"], "j" => [0, "\xb8O"], "k" => [0, "\xb8P"], "l" => [0, "\xb8Q"], "m" => [0, "\xb8R"], "n" => [0, "\xb8S"], "o" => [0, "\xb8T"], "p" => [0, "\xb8U"], "q" => [0, "\xb8V"], "r" => [0, "\xb8W"], "s" => [0, "\xb8Y"], "t" => [0, "\xb8j"], "u" => [0, "\xb8k"], "v" => [0, "\xb8q"], "w" => [0, "\xb8v"], "x" => [0, "\xb8w"], "y" => [0, "\xb8x"], "z" => [0, "\xb8y"], "{" => [0, "\xb8z"], "|" => [82, "\xb8"], "}" => [87, "\xb8"], "~" => [130, "\xb8"], "" => [9, "\xb8"], "\x80" => [94, "\xc20"], "\x81" => [76, "\xc20"], "\x82" => [104, "\xc20"], "\x83" => [16, "\xc20"], "\x84" => [94, "\xc21"], "\x85" => [76, "\xc21"], "\x86" => [104, "\xc21"], "\x87" => [16, "\xc21"], "\x88" => [94, "\xc22"], "\x89" => [76, "\xc22"], "\x8a" => [104, "\xc22"], "\x8b" => [16, "\xc22"], "\x8c" => [94, "\xc2a"], "\x8d" => [76, "\xc2a"], "\x8e" => [104, "\xc2a"], "\x8f" => [16, "\xc2a"], "\x90" => [94, "\xc2c"], "\x91" => [76, "\xc2c"], "\x92" => [104, "\xc2c"], "\x93" => [16, "\xc2c"], "\x94" => [94, "\xc2e"], "\x95" => [76, "\xc2e"], "\x96" => [104, "\xc2e"], "\x97" => [16, "\xc2e"], "\x98" => [94, "\xc2i"], "\x99" => [76, "\xc2i"], "\x9a" => [104, "\xc2i"], "\x9b" => [16, "\xc2i"], "\x9c" => [94, "\xc2o"], "\x9d" => [76, "\xc2o"], "\x9e" => [104, "\xc2o"], "\x9f" => [16, "\xc2o"], "\xa0" => [94, "\xc2s"], "\xa1" => [76, "\xc2s"], "\xa2" => [104, "\xc2s"], "\xa3" => [16, "\xc2s"], "\xa4" => [94, "\xc2t"], "\xa5" => [76, "\xc2t"], "\xa6" => [104, "\xc2t"], "\xa7" => [16, "\xc2t"], "\xa8" => [77, "\xc2 "], "\xa9" => [18, "\xc2 "], "\xaa" => [77, "\xc2%"], "\xab" => [18, "\xc2%"], "\xac" => [77, "\xc2-"], "\xad" => [18, "\xc2-"], "\xae" => [77, "\xc2."], "\xaf" => [18, "\xc2."], "\xb0" => [77, "\xc2/"], "\xb1" => [18, "\xc2/"], "\xb2" => [77, "\xc23"], "\xb3" => [18, "\xc23"], "\xb4" => [77, "\xc24"], "\xb5" => [18, "\xc24"], "\xb6" => [77, "\xc25"], "\xb7" => [18, "\xc25"], "\xb8" => [77, "\xc26"], "\xb9" => [18, "\xc26"], "\xba" => [77, "\xc27"], "\xbb" => [18, "\xc27"], "\xbc" => [77, "\xc28"], "\xbd" => [18, "\xc28"], "\xbe" => [77, "\xc29"], "\xbf" => [18, "\xc29"], "\xc0" => [77, "\xc2="], "\xc1" => [18, "\xc2="], "\xc2" => [77, "\xc2A"], "\xc3" => [18, "\xc2A"], "\xc4" => [77, "\xc2_"], "\xc5" => [18, "\xc2_"], "\xc6" => [77, "\xc2b"], "\xc7" => [18, "\xc2b"], "\xc8" => [77, "\xc2d"], "\xc9" => [18, "\xc2d"], "\xca" => [77, "\xc2f"], "\xcb" => [18, "\xc2f"], "\xcc" => [77, "\xc2g"], "\xcd" => [18, "\xc2g"], "\xce" => [77, "\xc2h"], "\xcf" => [18, "\xc2h"], "\xd0" => [77, "\xc2l"], "\xd1" => [18, "\xc2l"], "\xd2" => [77, "\xc2m"], "\xd3" => [18, "\xc2m"], "\xd4" => [77, "\xc2n"], "\xd5" => [18, "\xc2n"], "\xd6" => [77, "\xc2p"], "\xd7" => [18, "\xc2p"], "\xd8" => [77, "\xc2r"], "\xd9" => [18, "\xc2r"], "\xda" => [77, "\xc2u"], "\xdb" => [18, "\xc2u"], "\xdc" => [0, "\xc2:"], "\xdd" => [0, "\xc2B"], "\xde" => [0, "\xc2C"], "\xdf" => [0, "\xc2D"], "\xe0" => [0, "\xc2E"], "\xe1" => [0, "\xc2F"], "\xe2" => [0, "\xc2G"], "\xe3" => [0, "\xc2H"], "\xe4" => [0, "\xc2I"], "\xe5" => [0, "\xc2J"], "\xe6" => [0, "\xc2K"], "\xe7" => [0, "\xc2L"], "\xe8" => [0, "\xc2M"], "\xe9" => [0, "\xc2N"], "\xea" => [0, "\xc2O"], "\xeb" => [0, "\xc2P"], "\xec" => [0, "\xc2Q"], "\xed" => [0, "\xc2R"], "\xee" => [0, "\xc2S"], "\xef" => [0, "\xc2T"], "\xf0" => [0, "\xc2U"], "\xf1" => [0, "\xc2V"], "\xf2" => [0, "\xc2W"], "\xf3" => [0, "\xc2Y"], "\xf4" => [0, "\xc2j"], "\xf5" => [0, "\xc2k"], "\xf6" => [0, "\xc2q"], "\xf7" => [0, "\xc2v"], "\xf8" => [0, "\xc2w"], "\xf9" => [0, "\xc2x"], "\xfa" => [0, "\xc2y"], "\xfb" => [0, "\xc2z"], "\xfc" => [82, "\xc2"], "\xfd" => [87, "\xc2"], "\xfe" => [130, "\xc2"], "\xff" => [9, "\xc2"]], ["\x00" => [94, "\xb90"], "\x01" => [76, "\xb90"], "\x02" => [104, "\xb90"], "\x03" => [16, "\xb90"], "\x04" => [94, "\xb91"], "\x05" => [76, "\xb91"], "\x06" => [104, "\xb91"], "\x07" => [16, "\xb91"], "\x08" => [94, "\xb92"], "\t" => [76, "\xb92"], "\n" => [104, "\xb92"], "\v" => [16, "\xb92"], "\f" => [94, "\xb9a"], "\r" => [76, "\xb9a"], "\x0e" => [104, "\xb9a"], "\x0f" => [16, "\xb9a"], "\x10" => [94, "\xb9c"], "\x11" => [76, "\xb9c"], "\x12" => [104, "\xb9c"], "\x13" => [16, "\xb9c"], "\x14" => [94, "\xb9e"], "\x15" => [76, "\xb9e"], "\x16" => [104, "\xb9e"], "\x17" => [16, "\xb9e"], "\x18" => [94, "\xb9i"], "\x19" => [76, "\xb9i"], "\x1a" => [104, "\xb9i"], "\x1b" => [16, "\xb9i"], "\x1c" => [94, "\xb9o"], "\x1d" => [76, "\xb9o"], "\x1e" => [104, "\xb9o"], "\x1f" => [16, "\xb9o"], " " => [94, "\xb9s"], "!" => [76, "\xb9s"], "\"" => [104, "\xb9s"], "#" => [16, "\xb9s"], "\$" => [94, "\xb9t"], "%" => [76, "\xb9t"], "&" => [104, "\xb9t"], "'" => [16, "\xb9t"], "(" => [77, "\xb9 "], ")" => [18, "\xb9 "], "*" => [77, "\xb9%"], "+" => [18, "\xb9%"], "," => [77, "\xb9-"], "-" => [18, "\xb9-"], "." => [77, "\xb9."], "/" => [18, "\xb9."], [77, "\xb9/"], [18, "\xb9/"], [77, "\xb93"], [18, "\xb93"], [77, "\xb94"], [18, "\xb94"], [77, "\xb95"], [18, "\xb95"], [77, "\xb96"], [18, "\xb96"], ":" => [77, "\xb97"], ";" => [18, "\xb97"], "<" => [77, "\xb98"], "=" => [18, "\xb98"], ">" => [77, "\xb99"], "?" => [18, "\xb99"], "@" => [77, "\xb9="], "A" => [18, "\xb9="], "B" => [77, "\xb9A"], "C" => [18, "\xb9A"], "D" => [77, "\xb9_"], "E" => [18, "\xb9_"], "F" => [77, "\xb9b"], "G" => [18, "\xb9b"], "H" => [77, "\xb9d"], "I" => [18, "\xb9d"], "J" => [77, "\xb9f"], "K" => [18, "\xb9f"], "L" => [77, "\xb9g"], "M" => [18, "\xb9g"], "N" => [77, "\xb9h"], "O" => [18, "\xb9h"], "P" => [77, "\xb9l"], "Q" => [18, "\xb9l"], "R" => [77, "\xb9m"], "S" => [18, "\xb9m"], "T" => [77, "\xb9n"], "U" => [18, "\xb9n"], "V" => [77, "\xb9p"], "W" => [18, "\xb9p"], "X" => [77, "\xb9r"], "Y" => [18, "\xb9r"], "Z" => [77, "\xb9u"], "[" => [18, "\xb9u"], "\\" => [0, "\xb9:"], "]" => [0, "\xb9B"], "^" => [0, "\xb9C"], "_" => [0, "\xb9D"], "`" => [0, "\xb9E"], "a" => [0, "\xb9F"], "b" => [0, "\xb9G"], "c" => [0, "\xb9H"], "d" => [0, "\xb9I"], "e" => [0, "\xb9J"], "f" => [0, "\xb9K"], "g" => [0, "\xb9L"], "h" => [0, "\xb9M"], "i" => [0, "\xb9N"], "j" => [0, "\xb9O"], "k" => [0, "\xb9P"], "l" => [0, "\xb9Q"], "m" => [0, "\xb9R"], "n" => [0, "\xb9S"], "o" => [0, "\xb9T"], "p" => [0, "\xb9U"], "q" => [0, "\xb9V"], "r" => [0, "\xb9W"], "s" => [0, "\xb9Y"], "t" => [0, "\xb9j"], "u" => [0, "\xb9k"], "v" => [0, "\xb9q"], "w" => [0, "\xb9v"], "x" => [0, "\xb9w"], "y" => [0, "\xb9x"], "z" => [0, "\xb9y"], "{" => [0, "\xb9z"], "|" => [82, "\xb9"], "}" => [87, "\xb9"], "~" => [130, "\xb9"], "" => [9, "\xb9"], "\x80" => [94, "\xba0"], "\x81" => [76, "\xba0"], "\x82" => [104, "\xba0"], "\x83" => [16, "\xba0"], "\x84" => [94, "\xba1"], "\x85" => [76, "\xba1"], "\x86" => [104, "\xba1"], "\x87" => [16, "\xba1"], "\x88" => [94, "\xba2"], "\x89" => [76, "\xba2"], "\x8a" => [104, "\xba2"], "\x8b" => [16, "\xba2"], "\x8c" => [94, "\xbaa"], "\x8d" => [76, "\xbaa"], "\x8e" => [104, "\xbaa"], "\x8f" => [16, "\xbaa"], "\x90" => [94, "\xbac"], "\x91" => [76, "\xbac"], "\x92" => [104, "\xbac"], "\x93" => [16, "\xbac"], "\x94" => [94, "\xbae"], "\x95" => [76, "\xbae"], "\x96" => [104, "\xbae"], "\x97" => [16, "\xbae"], "\x98" => [94, "\xbai"], "\x99" => [76, "\xbai"], "\x9a" => [104, "\xbai"], "\x9b" => [16, "\xbai"], "\x9c" => [94, "\xbao"], "\x9d" => [76, "\xbao"], "\x9e" => [104, "\xbao"], "\x9f" => [16, "\xbao"], "\xa0" => [94, "\xbas"], "\xa1" => [76, "\xbas"], "\xa2" => [104, "\xbas"], "\xa3" => [16, "\xbas"], "\xa4" => [94, "\xbat"], "\xa5" => [76, "\xbat"], "\xa6" => [104, "\xbat"], "\xa7" => [16, "\xbat"], "\xa8" => [77, "\xba "], "\xa9" => [18, "\xba "], "\xaa" => [77, "\xba%"], "\xab" => [18, "\xba%"], "\xac" => [77, "\xba-"], "\xad" => [18, "\xba-"], "\xae" => [77, "\xba."], "\xaf" => [18, "\xba."], "\xb0" => [77, "\xba/"], "\xb1" => [18, "\xba/"], "\xb2" => [77, "\xba3"], "\xb3" => [18, "\xba3"], "\xb4" => [77, "\xba4"], "\xb5" => [18, "\xba4"], "\xb6" => [77, "\xba5"], "\xb7" => [18, "\xba5"], "\xb8" => [77, "\xba6"], "\xb9" => [18, "\xba6"], "\xba" => [77, "\xba7"], "\xbb" => [18, "\xba7"], "\xbc" => [77, "\xba8"], "\xbd" => [18, "\xba8"], "\xbe" => [77, "\xba9"], "\xbf" => [18, "\xba9"], "\xc0" => [77, "\xba="], "\xc1" => [18, "\xba="], "\xc2" => [77, "\xbaA"], "\xc3" => [18, "\xbaA"], "\xc4" => [77, "\xba_"], "\xc5" => [18, "\xba_"], "\xc6" => [77, "\xbab"], "\xc7" => [18, "\xbab"], "\xc8" => [77, "\xbad"], "\xc9" => [18, "\xbad"], "\xca" => [77, "\xbaf"], "\xcb" => [18, "\xbaf"], "\xcc" => [77, "\xbag"], "\xcd" => [18, "\xbag"], "\xce" => [77, "\xbah"], "\xcf" => [18, "\xbah"], "\xd0" => [77, "\xbal"], "\xd1" => [18, "\xbal"], "\xd2" => [77, "\xbam"], "\xd3" => [18, "\xbam"], "\xd4" => [77, "\xban"], "\xd5" => [18, "\xban"], "\xd6" => [77, "\xbap"], "\xd7" => [18, "\xbap"], "\xd8" => [77, "\xbar"], "\xd9" => [18, "\xbar"], "\xda" => [77, "\xbau"], "\xdb" => [18, "\xbau"], "\xdc" => [0, "\xba:"], "\xdd" => [0, "\xbaB"], "\xde" => [0, "\xbaC"], "\xdf" => [0, "\xbaD"], "\xe0" => [0, "\xbaE"], "\xe1" => [0, "\xbaF"], "\xe2" => [0, "\xbaG"], "\xe3" => [0, "\xbaH"], "\xe4" => [0, "\xbaI"], "\xe5" => [0, "\xbaJ"], "\xe6" => [0, "\xbaK"], "\xe7" => [0, "\xbaL"], "\xe8" => [0, "\xbaM"], "\xe9" => [0, "\xbaN"], "\xea" => [0, "\xbaO"], "\xeb" => [0, "\xbaP"], "\xec" => [0, "\xbaQ"], "\xed" => [0, "\xbaR"], "\xee" => [0, "\xbaS"], "\xef" => [0, "\xbaT"], "\xf0" => [0, "\xbaU"], "\xf1" => [0, "\xbaV"], "\xf2" => [0, "\xbaW"], "\xf3" => [0, "\xbaY"], "\xf4" => [0, "\xbaj"], "\xf5" => [0, "\xbak"], "\xf6" => [0, "\xbaq"], "\xf7" => [0, "\xbav"], "\xf8" => [0, "\xbaw"], "\xf9" => [0, "\xbax"], "\xfa" => [0, "\xbay"], "\xfb" => [0, "\xbaz"], "\xfc" => [82, "\xba"], "\xfd" => [87, "\xba"], "\xfe" => [130, "\xba"], "\xff" => [9, "\xba"]], ["\x00" => [94, "\xbb0"], "\x01" => [76, "\xbb0"], "\x02" => [104, "\xbb0"], "\x03" => [16, "\xbb0"], "\x04" => [94, "\xbb1"], "\x05" => [76, "\xbb1"], "\x06" => [104, "\xbb1"], "\x07" => [16, "\xbb1"], "\x08" => [94, "\xbb2"], "\t" => [76, "\xbb2"], "\n" => [104, "\xbb2"], "\v" => [16, "\xbb2"], "\f" => [94, "\xbba"], "\r" => [76, "\xbba"], "\x0e" => [104, "\xbba"], "\x0f" => [16, "\xbba"], "\x10" => [94, "\xbbc"], "\x11" => [76, "\xbbc"], "\x12" => [104, "\xbbc"], "\x13" => [16, "\xbbc"], "\x14" => [94, "\xbbe"], "\x15" => [76, "\xbbe"], "\x16" => [104, "\xbbe"], "\x17" => [16, "\xbbe"], "\x18" => [94, "\xbbi"], "\x19" => [76, "\xbbi"], "\x1a" => [104, "\xbbi"], "\x1b" => [16, "\xbbi"], "\x1c" => [94, "\xbbo"], "\x1d" => [76, "\xbbo"], "\x1e" => [104, "\xbbo"], "\x1f" => [16, "\xbbo"], " " => [94, "\xbbs"], "!" => [76, "\xbbs"], "\"" => [104, "\xbbs"], "#" => [16, "\xbbs"], "\$" => [94, "\xbbt"], "%" => [76, "\xbbt"], "&" => [104, "\xbbt"], "'" => [16, "\xbbt"], "(" => [77, "\xbb "], ")" => [18, "\xbb "], "*" => [77, "\xbb%"], "+" => [18, "\xbb%"], "," => [77, "\xbb-"], "-" => [18, "\xbb-"], "." => [77, "\xbb."], "/" => [18, "\xbb."], [77, "\xbb/"], [18, "\xbb/"], [77, "\xbb3"], [18, "\xbb3"], [77, "\xbb4"], [18, "\xbb4"], [77, "\xbb5"], [18, "\xbb5"], [77, "\xbb6"], [18, "\xbb6"], ":" => [77, "\xbb7"], ";" => [18, "\xbb7"], "<" => [77, "\xbb8"], "=" => [18, "\xbb8"], ">" => [77, "\xbb9"], "?" => [18, "\xbb9"], "@" => [77, "\xbb="], "A" => [18, "\xbb="], "B" => [77, "\xbbA"], "C" => [18, "\xbbA"], "D" => [77, "\xbb_"], "E" => [18, "\xbb_"], "F" => [77, "\xbbb"], "G" => [18, "\xbbb"], "H" => [77, "\xbbd"], "I" => [18, "\xbbd"], "J" => [77, "\xbbf"], "K" => [18, "\xbbf"], "L" => [77, "\xbbg"], "M" => [18, "\xbbg"], "N" => [77, "\xbbh"], "O" => [18, "\xbbh"], "P" => [77, "\xbbl"], "Q" => [18, "\xbbl"], "R" => [77, "\xbbm"], "S" => [18, "\xbbm"], "T" => [77, "\xbbn"], "U" => [18, "\xbbn"], "V" => [77, "\xbbp"], "W" => [18, "\xbbp"], "X" => [77, "\xbbr"], "Y" => [18, "\xbbr"], "Z" => [77, "\xbbu"], "[" => [18, "\xbbu"], "\\" => [0, "\xbb:"], "]" => [0, "\xbbB"], "^" => [0, "\xbbC"], "_" => [0, "\xbbD"], "`" => [0, "\xbbE"], "a" => [0, "\xbbF"], "b" => [0, "\xbbG"], "c" => [0, "\xbbH"], "d" => [0, "\xbbI"], "e" => [0, "\xbbJ"], "f" => [0, "\xbbK"], "g" => [0, "\xbbL"], "h" => [0, "\xbbM"], "i" => [0, "\xbbN"], "j" => [0, "\xbbO"], "k" => [0, "\xbbP"], "l" => [0, "\xbbQ"], "m" => [0, "\xbbR"], "n" => [0, "\xbbS"], "o" => [0, "\xbbT"], "p" => [0, "\xbbU"], "q" => [0, "\xbbV"], "r" => [0, "\xbbW"], "s" => [0, "\xbbY"], "t" => [0, "\xbbj"], "u" => [0, "\xbbk"], "v" => [0, "\xbbq"], "w" => [0, "\xbbv"], "x" => [0, "\xbbw"], "y" => [0, "\xbbx"], "z" => [0, "\xbby"], "{" => [0, "\xbbz"], "|" => [82, "\xbb"], "}" => [87, "\xbb"], "~" => [130, "\xbb"], "" => [9, "\xbb"], "\x80" => [94, "\xbd0"], "\x81" => [76, "\xbd0"], "\x82" => [104, "\xbd0"], "\x83" => [16, "\xbd0"], "\x84" => [94, "\xbd1"], "\x85" => [76, "\xbd1"], "\x86" => [104, "\xbd1"], "\x87" => [16, "\xbd1"], "\x88" => [94, "\xbd2"], "\x89" => [76, "\xbd2"], "\x8a" => [104, "\xbd2"], "\x8b" => [16, "\xbd2"], "\x8c" => [94, "\xbda"], "\x8d" => [76, "\xbda"], "\x8e" => [104, "\xbda"], "\x8f" => [16, "\xbda"], "\x90" => [94, "\xbdc"], "\x91" => [76, "\xbdc"], "\x92" => [104, "\xbdc"], "\x93" => [16, "\xbdc"], "\x94" => [94, "\xbde"], "\x95" => [76, "\xbde"], "\x96" => [104, "\xbde"], "\x97" => [16, "\xbde"], "\x98" => [94, "\xbdi"], "\x99" => [76, "\xbdi"], "\x9a" => [104, "\xbdi"], "\x9b" => [16, "\xbdi"], "\x9c" => [94, "\xbdo"], "\x9d" => [76, "\xbdo"], "\x9e" => [104, "\xbdo"], "\x9f" => [16, "\xbdo"], "\xa0" => [94, "\xbds"], "\xa1" => [76, "\xbds"], "\xa2" => [104, "\xbds"], "\xa3" => [16, "\xbds"], "\xa4" => [94, "\xbdt"], "\xa5" => [76, "\xbdt"], "\xa6" => [104, "\xbdt"], "\xa7" => [16, "\xbdt"], "\xa8" => [77, "\xbd "], "\xa9" => [18, "\xbd "], "\xaa" => [77, "\xbd%"], "\xab" => [18, "\xbd%"], "\xac" => [77, "\xbd-"], "\xad" => [18, "\xbd-"], "\xae" => [77, "\xbd."], "\xaf" => [18, "\xbd."], "\xb0" => [77, "\xbd/"], "\xb1" => [18, "\xbd/"], "\xb2" => [77, "\xbd3"], "\xb3" => [18, "\xbd3"], "\xb4" => [77, "\xbd4"], "\xb5" => [18, "\xbd4"], "\xb6" => [77, "\xbd5"], "\xb7" => [18, "\xbd5"], "\xb8" => [77, "\xbd6"], "\xb9" => [18, "\xbd6"], "\xba" => [77, "\xbd7"], "\xbb" => [18, "\xbd7"], "\xbc" => [77, "\xbd8"], "\xbd" => [18, "\xbd8"], "\xbe" => [77, "\xbd9"], "\xbf" => [18, "\xbd9"], "\xc0" => [77, "\xbd="], "\xc1" => [18, "\xbd="], "\xc2" => [77, "\xbdA"], "\xc3" => [18, "\xbdA"], "\xc4" => [77, "\xbd_"], "\xc5" => [18, "\xbd_"], "\xc6" => [77, "\xbdb"], "\xc7" => [18, "\xbdb"], "\xc8" => [77, "\xbdd"], "\xc9" => [18, "\xbdd"], "\xca" => [77, "\xbdf"], "\xcb" => [18, "\xbdf"], "\xcc" => [77, "\xbdg"], "\xcd" => [18, "\xbdg"], "\xce" => [77, "\xbdh"], "\xcf" => [18, "\xbdh"], "\xd0" => [77, "\xbdl"], "\xd1" => [18, "\xbdl"], "\xd2" => [77, "\xbdm"], "\xd3" => [18, "\xbdm"], "\xd4" => [77, "\xbdn"], "\xd5" => [18, "\xbdn"], "\xd6" => [77, "\xbdp"], "\xd7" => [18, "\xbdp"], "\xd8" => [77, "\xbdr"], "\xd9" => [18, "\xbdr"], "\xda" => [77, "\xbdu"], "\xdb" => [18, "\xbdu"], "\xdc" => [0, "\xbd:"], "\xdd" => [0, "\xbdB"], "\xde" => [0, "\xbdC"], "\xdf" => [0, "\xbdD"], "\xe0" => [0, "\xbdE"], "\xe1" => [0, "\xbdF"], "\xe2" => [0, "\xbdG"], "\xe3" => [0, "\xbdH"], "\xe4" => [0, "\xbdI"], "\xe5" => [0, "\xbdJ"], "\xe6" => [0, "\xbdK"], "\xe7" => [0, "\xbdL"], "\xe8" => [0, "\xbdM"], "\xe9" => [0, "\xbdN"], "\xea" => [0, "\xbdO"], "\xeb" => [0, "\xbdP"], "\xec" => [0, "\xbdQ"], "\xed" => [0, "\xbdR"], "\xee" => [0, "\xbdS"], "\xef" => [0, "\xbdT"], "\xf0" => [0, "\xbdU"], "\xf1" => [0, "\xbdV"], "\xf2" => [0, "\xbdW"], "\xf3" => [0, "\xbdY"], "\xf4" => [0, "\xbdj"], "\xf5" => [0, "\xbdk"], "\xf6" => [0, "\xbdq"], "\xf7" => [0, "\xbdv"], "\xf8" => [0, "\xbdw"], "\xf9" => [0, "\xbdx"], "\xfa" => [0, "\xbdy"], "\xfb" => [0, "\xbdz"], "\xfc" => [82, "\xbd"], "\xfd" => [87, "\xbd"], "\xfe" => [130, "\xbd"], "\xff" => [9, "\xbd"]], ["\x00" => [77, "\xbb0"], "\x01" => [18, "\xbb0"], "\x02" => [77, "\xbb1"], "\x03" => [18, "\xbb1"], "\x04" => [77, "\xbb2"], "\x05" => [18, "\xbb2"], "\x06" => [77, "\xbba"], "\x07" => [18, "\xbba"], "\x08" => [77, "\xbbc"], "\t" => [18, "\xbbc"], "\n" => [77, "\xbbe"], "\v" => [18, "\xbbe"], "\f" => [77, "\xbbi"], "\r" => [18, "\xbbi"], "\x0e" => [77, "\xbbo"], "\x0f" => [18, "\xbbo"], "\x10" => [77, "\xbbs"], "\x11" => [18, "\xbbs"], "\x12" => [77, "\xbbt"], "\x13" => [18, "\xbbt"], "\x14" => [0, "\xbb "], "\x15" => [0, "\xbb%"], "\x16" => [0, "\xbb-"], "\x17" => [0, "\xbb."], "\x18" => [0, "\xbb/"], "\x19" => [0, "\xbb3"], "\x1a" => [0, "\xbb4"], "\x1b" => [0, "\xbb5"], "\x1c" => [0, "\xbb6"], "\x1d" => [0, "\xbb7"], "\x1e" => [0, "\xbb8"], "\x1f" => [0, "\xbb9"], " " => [0, "\xbb="], "!" => [0, "\xbbA"], "\"" => [0, "\xbb_"], "#" => [0, "\xbbb"], "\$" => [0, "\xbbd"], "%" => [0, "\xbbf"], "&" => [0, "\xbbg"], "'" => [0, "\xbbh"], "(" => [0, "\xbbl"], ")" => [0, "\xbbm"], "*" => [0, "\xbbn"], "+" => [0, "\xbbp"], "," => [0, "\xbbr"], "-" => [0, "\xbbu"], "." => [100, "\xbb"], "/" => [110, "\xbb"], [111, "\xbb"], [115, "\xbb"], [116, "\xbb"], [118, "\xbb"], [119, "\xbb"], [122, "\xbb"], [123, "\xbb"], [125, "\xbb"], [126, "\xbb"], [129, "\xbb"], ":" => [143, "\xbb"], ";" => [148, "\xbb"], "<" => [151, "\xbb"], "=" => [153, "\xbb"], ">" => [83, "\xbb"], "?" => [10, "\xbb"], "@" => [77, "\xbd0"], "A" => [18, "\xbd0"], "B" => [77, "\xbd1"], "C" => [18, "\xbd1"], "D" => [77, "\xbd2"], "E" => [18, "\xbd2"], "F" => [77, "\xbda"], "G" => [18, "\xbda"], "H" => [77, "\xbdc"], "I" => [18, "\xbdc"], "J" => [77, "\xbde"], "K" => [18, "\xbde"], "L" => [77, "\xbdi"], "M" => [18, "\xbdi"], "N" => [77, "\xbdo"], "O" => [18, "\xbdo"], "P" => [77, "\xbds"], "Q" => [18, "\xbds"], "R" => [77, "\xbdt"], "S" => [18, "\xbdt"], "T" => [0, "\xbd "], "U" => [0, "\xbd%"], "V" => [0, "\xbd-"], "W" => [0, "\xbd."], "X" => [0, "\xbd/"], "Y" => [0, "\xbd3"], "Z" => [0, "\xbd4"], "[" => [0, "\xbd5"], "\\" => [0, "\xbd6"], "]" => [0, "\xbd7"], "^" => [0, "\xbd8"], "_" => [0, "\xbd9"], "`" => [0, "\xbd="], "a" => [0, "\xbdA"], "b" => [0, "\xbd_"], "c" => [0, "\xbdb"], "d" => [0, "\xbdd"], "e" => [0, "\xbdf"], "f" => [0, "\xbdg"], "g" => [0, "\xbdh"], "h" => [0, "\xbdl"], "i" => [0, "\xbdm"], "j" => [0, "\xbdn"], "k" => [0, "\xbdp"], "l" => [0, "\xbdr"], "m" => [0, "\xbdu"], "n" => [100, "\xbd"], "o" => [110, "\xbd"], "p" => [111, "\xbd"], "q" => [115, "\xbd"], "r" => [116, "\xbd"], "s" => [118, "\xbd"], "t" => [119, "\xbd"], "u" => [122, "\xbd"], "v" => [123, "\xbd"], "w" => [125, "\xbd"], "x" => [126, "\xbd"], "y" => [129, "\xbd"], "z" => [143, "\xbd"], "{" => [148, "\xbd"], "|" => [151, "\xbd"], "}" => [153, "\xbd"], "~" => [83, "\xbd"], "" => [10, "\xbd"], "\x80" => [77, "\xbe0"], "\x81" => [18, "\xbe0"], "\x82" => [77, "\xbe1"], "\x83" => [18, "\xbe1"], "\x84" => [77, "\xbe2"], "\x85" => [18, "\xbe2"], "\x86" => [77, "\xbea"], "\x87" => [18, "\xbea"], "\x88" => [77, "\xbec"], "\x89" => [18, "\xbec"], "\x8a" => [77, "\xbee"], "\x8b" => [18, "\xbee"], "\x8c" => [77, "\xbei"], "\x8d" => [18, "\xbei"], "\x8e" => [77, "\xbeo"], "\x8f" => [18, "\xbeo"], "\x90" => [77, "\xbes"], "\x91" => [18, "\xbes"], "\x92" => [77, "\xbet"], "\x93" => [18, "\xbet"], "\x94" => [0, "\xbe "], "\x95" => [0, "\xbe%"], "\x96" => [0, "\xbe-"], "\x97" => [0, "\xbe."], "\x98" => [0, "\xbe/"], "\x99" => [0, "\xbe3"], "\x9a" => [0, "\xbe4"], "\x9b" => [0, "\xbe5"], "\x9c" => [0, "\xbe6"], "\x9d" => [0, "\xbe7"], "\x9e" => [0, "\xbe8"], "\x9f" => [0, "\xbe9"], "\xa0" => [0, "\xbe="], "\xa1" => [0, "\xbeA"], "\xa2" => [0, "\xbe_"], "\xa3" => [0, "\xbeb"], "\xa4" => [0, "\xbed"], "\xa5" => [0, "\xbef"], "\xa6" => [0, "\xbeg"], "\xa7" => [0, "\xbeh"], "\xa8" => [0, "\xbel"], "\xa9" => [0, "\xbem"], "\xaa" => [0, "\xben"], "\xab" => [0, "\xbep"], "\xac" => [0, "\xber"], "\xad" => [0, "\xbeu"], "\xae" => [100, "\xbe"], "\xaf" => [110, "\xbe"], "\xb0" => [111, "\xbe"], "\xb1" => [115, "\xbe"], "\xb2" => [116, "\xbe"], "\xb3" => [118, "\xbe"], "\xb4" => [119, "\xbe"], "\xb5" => [122, "\xbe"], "\xb6" => [123, "\xbe"], "\xb7" => [125, "\xbe"], "\xb8" => [126, "\xbe"], "\xb9" => [129, "\xbe"], "\xba" => [143, "\xbe"], "\xbb" => [148, "\xbe"], "\xbc" => [151, "\xbe"], "\xbd" => [153, "\xbe"], "\xbe" => [83, "\xbe"], "\xbf" => [10, "\xbe"], "\xc0" => [77, "\xc40"], "\xc1" => [18, "\xc40"], "\xc2" => [77, "\xc41"], "\xc3" => [18, "\xc41"], "\xc4" => [77, "\xc42"], "\xc5" => [18, "\xc42"], "\xc6" => [77, "\xc4a"], "\xc7" => [18, "\xc4a"], "\xc8" => [77, "\xc4c"], "\xc9" => [18, "\xc4c"], "\xca" => [77, "\xc4e"], "\xcb" => [18, "\xc4e"], "\xcc" => [77, "\xc4i"], "\xcd" => [18, "\xc4i"], "\xce" => [77, "\xc4o"], "\xcf" => [18, "\xc4o"], "\xd0" => [77, "\xc4s"], "\xd1" => [18, "\xc4s"], "\xd2" => [77, "\xc4t"], "\xd3" => [18, "\xc4t"], "\xd4" => [0, "\xc4 "], "\xd5" => [0, "\xc4%"], "\xd6" => [0, "\xc4-"], "\xd7" => [0, "\xc4."], "\xd8" => [0, "\xc4/"], "\xd9" => [0, "\xc43"], "\xda" => [0, "\xc44"], "\xdb" => [0, "\xc45"], "\xdc" => [0, "\xc46"], "\xdd" => [0, "\xc47"], "\xde" => [0, "\xc48"], "\xdf" => [0, "\xc49"], "\xe0" => [0, "\xc4="], "\xe1" => [0, "\xc4A"], "\xe2" => [0, "\xc4_"], "\xe3" => [0, "\xc4b"], "\xe4" => [0, "\xc4d"], "\xe5" => [0, "\xc4f"], "\xe6" => [0, "\xc4g"], "\xe7" => [0, "\xc4h"], "\xe8" => [0, "\xc4l"], "\xe9" => [0, "\xc4m"], "\xea" => [0, "\xc4n"], "\xeb" => [0, "\xc4p"], "\xec" => [0, "\xc4r"], "\xed" => [0, "\xc4u"], "\xee" => [100, "\xc4"], "\xef" => [110, "\xc4"], "\xf0" => [111, "\xc4"], "\xf1" => [115, "\xc4"], "\xf2" => [116, "\xc4"], "\xf3" => [118, "\xc4"], "\xf4" => [119, "\xc4"], "\xf5" => [122, "\xc4"], "\xf6" => [123, "\xc4"], "\xf7" => [125, "\xc4"], "\xf8" => [126, "\xc4"], "\xf9" => [129, "\xc4"], "\xfa" => [143, "\xc4"], "\xfb" => [148, "\xc4"], "\xfc" => [151, "\xc4"], "\xfd" => [153, "\xc4"], "\xfe" => [83, "\xc4"], "\xff" => [10, "\xc4"]], ["\x00" => [94, "\xbc0"], "\x01" => [76, "\xbc0"], "\x02" => [104, "\xbc0"], "\x03" => [16, "\xbc0"], "\x04" => [94, "\xbc1"], "\x05" => [76, "\xbc1"], "\x06" => [104, "\xbc1"], "\x07" => [16, "\xbc1"], "\x08" => [94, "\xbc2"], "\t" => [76, "\xbc2"], "\n" => [104, "\xbc2"], "\v" => [16, "\xbc2"], "\f" => [94, "\xbca"], "\r" => [76, "\xbca"], "\x0e" => [104, "\xbca"], "\x0f" => [16, "\xbca"], "\x10" => [94, "\xbcc"], "\x11" => [76, "\xbcc"], "\x12" => [104, "\xbcc"], "\x13" => [16, "\xbcc"], "\x14" => [94, "\xbce"], "\x15" => [76, "\xbce"], "\x16" => [104, "\xbce"], "\x17" => [16, "\xbce"], "\x18" => [94, "\xbci"], "\x19" => [76, "\xbci"], "\x1a" => [104, "\xbci"], "\x1b" => [16, "\xbci"], "\x1c" => [94, "\xbco"], "\x1d" => [76, "\xbco"], "\x1e" => [104, "\xbco"], "\x1f" => [16, "\xbco"], " " => [94, "\xbcs"], "!" => [76, "\xbcs"], "\"" => [104, "\xbcs"], "#" => [16, "\xbcs"], "\$" => [94, "\xbct"], "%" => [76, "\xbct"], "&" => [104, "\xbct"], "'" => [16, "\xbct"], "(" => [77, "\xbc "], ")" => [18, "\xbc "], "*" => [77, "\xbc%"], "+" => [18, "\xbc%"], "," => [77, "\xbc-"], "-" => [18, "\xbc-"], "." => [77, "\xbc."], "/" => [18, "\xbc."], [77, "\xbc/"], [18, "\xbc/"], [77, "\xbc3"], [18, "\xbc3"], [77, "\xbc4"], [18, "\xbc4"], [77, "\xbc5"], [18, "\xbc5"], [77, "\xbc6"], [18, "\xbc6"], ":" => [77, "\xbc7"], ";" => [18, "\xbc7"], "<" => [77, "\xbc8"], "=" => [18, "\xbc8"], ">" => [77, "\xbc9"], "?" => [18, "\xbc9"], "@" => [77, "\xbc="], "A" => [18, "\xbc="], "B" => [77, "\xbcA"], "C" => [18, "\xbcA"], "D" => [77, "\xbc_"], "E" => [18, "\xbc_"], "F" => [77, "\xbcb"], "G" => [18, "\xbcb"], "H" => [77, "\xbcd"], "I" => [18, "\xbcd"], "J" => [77, "\xbcf"], "K" => [18, "\xbcf"], "L" => [77, "\xbcg"], "M" => [18, "\xbcg"], "N" => [77, "\xbch"], "O" => [18, "\xbch"], "P" => [77, "\xbcl"], "Q" => [18, "\xbcl"], "R" => [77, "\xbcm"], "S" => [18, "\xbcm"], "T" => [77, "\xbcn"], "U" => [18, "\xbcn"], "V" => [77, "\xbcp"], "W" => [18, "\xbcp"], "X" => [77, "\xbcr"], "Y" => [18, "\xbcr"], "Z" => [77, "\xbcu"], "[" => [18, "\xbcu"], "\\" => [0, "\xbc:"], "]" => [0, "\xbcB"], "^" => [0, "\xbcC"], "_" => [0, "\xbcD"], "`" => [0, "\xbcE"], "a" => [0, "\xbcF"], "b" => [0, "\xbcG"], "c" => [0, "\xbcH"], "d" => [0, "\xbcI"], "e" => [0, "\xbcJ"], "f" => [0, "\xbcK"], "g" => [0, "\xbcL"], "h" => [0, "\xbcM"], "i" => [0, "\xbcN"], "j" => [0, "\xbcO"], "k" => [0, "\xbcP"], "l" => [0, "\xbcQ"], "m" => [0, "\xbcR"], "n" => [0, "\xbcS"], "o" => [0, "\xbcT"], "p" => [0, "\xbcU"], "q" => [0, "\xbcV"], "r" => [0, "\xbcW"], "s" => [0, "\xbcY"], "t" => [0, "\xbcj"], "u" => [0, "\xbck"], "v" => [0, "\xbcq"], "w" => [0, "\xbcv"], "x" => [0, "\xbcw"], "y" => [0, "\xbcx"], "z" => [0, "\xbcy"], "{" => [0, "\xbcz"], "|" => [82, "\xbc"], "}" => [87, "\xbc"], "~" => [130, "\xbc"], "" => [9, "\xbc"], "\x80" => [94, "\xbf0"], "\x81" => [76, "\xbf0"], "\x82" => [104, "\xbf0"], "\x83" => [16, "\xbf0"], "\x84" => [94, "\xbf1"], "\x85" => [76, "\xbf1"], "\x86" => [104, "\xbf1"], "\x87" => [16, "\xbf1"], "\x88" => [94, "\xbf2"], "\x89" => [76, "\xbf2"], "\x8a" => [104, "\xbf2"], "\x8b" => [16, "\xbf2"], "\x8c" => [94, "\xbfa"], "\x8d" => [76, "\xbfa"], "\x8e" => [104, "\xbfa"], "\x8f" => [16, "\xbfa"], "\x90" => [94, "\xbfc"], "\x91" => [76, "\xbfc"], "\x92" => [104, "\xbfc"], "\x93" => [16, "\xbfc"], "\x94" => [94, "\xbfe"], "\x95" => [76, "\xbfe"], "\x96" => [104, "\xbfe"], "\x97" => [16, "\xbfe"], "\x98" => [94, "\xbfi"], "\x99" => [76, "\xbfi"], "\x9a" => [104, "\xbfi"], "\x9b" => [16, "\xbfi"], "\x9c" => [94, "\xbfo"], "\x9d" => [76, "\xbfo"], "\x9e" => [104, "\xbfo"], "\x9f" => [16, "\xbfo"], "\xa0" => [94, "\xbfs"], "\xa1" => [76, "\xbfs"], "\xa2" => [104, "\xbfs"], "\xa3" => [16, "\xbfs"], "\xa4" => [94, "\xbft"], "\xa5" => [76, "\xbft"], "\xa6" => [104, "\xbft"], "\xa7" => [16, "\xbft"], "\xa8" => [77, "\xbf "], "\xa9" => [18, "\xbf "], "\xaa" => [77, "\xbf%"], "\xab" => [18, "\xbf%"], "\xac" => [77, "\xbf-"], "\xad" => [18, "\xbf-"], "\xae" => [77, "\xbf."], "\xaf" => [18, "\xbf."], "\xb0" => [77, "\xbf/"], "\xb1" => [18, "\xbf/"], "\xb2" => [77, "\xbf3"], "\xb3" => [18, "\xbf3"], "\xb4" => [77, "\xbf4"], "\xb5" => [18, "\xbf4"], "\xb6" => [77, "\xbf5"], "\xb7" => [18, "\xbf5"], "\xb8" => [77, "\xbf6"], "\xb9" => [18, "\xbf6"], "\xba" => [77, "\xbf7"], "\xbb" => [18, "\xbf7"], "\xbc" => [77, "\xbf8"], "\xbd" => [18, "\xbf8"], "\xbe" => [77, "\xbf9"], "\xbf" => [18, "\xbf9"], "\xc0" => [77, "\xbf="], "\xc1" => [18, "\xbf="], "\xc2" => [77, "\xbfA"], "\xc3" => [18, "\xbfA"], "\xc4" => [77, "\xbf_"], "\xc5" => [18, "\xbf_"], "\xc6" => [77, "\xbfb"], "\xc7" => [18, "\xbfb"], "\xc8" => [77, "\xbfd"], "\xc9" => [18, "\xbfd"], "\xca" => [77, "\xbff"], "\xcb" => [18, "\xbff"], "\xcc" => [77, "\xbfg"], "\xcd" => [18, "\xbfg"], "\xce" => [77, "\xbfh"], "\xcf" => [18, "\xbfh"], "\xd0" => [77, "\xbfl"], "\xd1" => [18, "\xbfl"], "\xd2" => [77, "\xbfm"], "\xd3" => [18, "\xbfm"], "\xd4" => [77, "\xbfn"], "\xd5" => [18, "\xbfn"], "\xd6" => [77, "\xbfp"], "\xd7" => [18, "\xbfp"], "\xd8" => [77, "\xbfr"], "\xd9" => [18, "\xbfr"], "\xda" => [77, "\xbfu"], "\xdb" => [18, "\xbfu"], "\xdc" => [0, "\xbf:"], "\xdd" => [0, "\xbfB"], "\xde" => [0, "\xbfC"], "\xdf" => [0, "\xbfD"], "\xe0" => [0, "\xbfE"], "\xe1" => [0, "\xbfF"], "\xe2" => [0, "\xbfG"], "\xe3" => [0, "\xbfH"], "\xe4" => [0, "\xbfI"], "\xe5" => [0, "\xbfJ"], "\xe6" => [0, "\xbfK"], "\xe7" => [0, "\xbfL"], "\xe8" => [0, "\xbfM"], "\xe9" => [0, "\xbfN"], "\xea" => [0, "\xbfO"], "\xeb" => [0, "\xbfP"], "\xec" => [0, "\xbfQ"], "\xed" => [0, "\xbfR"], "\xee" => [0, "\xbfS"], "\xef" => [0, "\xbfT"], "\xf0" => [0, "\xbfU"], "\xf1" => [0, "\xbfV"], "\xf2" => [0, "\xbfW"], "\xf3" => [0, "\xbfY"], "\xf4" => [0, "\xbfj"], "\xf5" => [0, "\xbfk"], "\xf6" => [0, "\xbfq"], "\xf7" => [0, "\xbfv"], "\xf8" => [0, "\xbfw"], "\xf9" => [0, "\xbfx"], "\xfa" => [0, "\xbfy"], "\xfb" => [0, "\xbfz"], "\xfc" => [82, "\xbf"], "\xfd" => [87, "\xbf"], "\xfe" => [130, "\xbf"], "\xff" => [9, "\xbf"]], ["\x00" => [77, "\xbc0"], "\x01" => [18, "\xbc0"], "\x02" => [77, "\xbc1"], "\x03" => [18, "\xbc1"], "\x04" => [77, "\xbc2"], "\x05" => [18, "\xbc2"], "\x06" => [77, "\xbca"], "\x07" => [18, "\xbca"], "\x08" => [77, "\xbcc"], "\t" => [18, "\xbcc"], "\n" => [77, "\xbce"], "\v" => [18, "\xbce"], "\f" => [77, "\xbci"], "\r" => [18, "\xbci"], "\x0e" => [77, "\xbco"], "\x0f" => [18, "\xbco"], "\x10" => [77, "\xbcs"], "\x11" => [18, "\xbcs"], "\x12" => [77, "\xbct"], "\x13" => [18, "\xbct"], "\x14" => [0, "\xbc "], "\x15" => [0, "\xbc%"], "\x16" => [0, "\xbc-"], "\x17" => [0, "\xbc."], "\x18" => [0, "\xbc/"], "\x19" => [0, "\xbc3"], "\x1a" => [0, "\xbc4"], "\x1b" => [0, "\xbc5"], "\x1c" => [0, "\xbc6"], "\x1d" => [0, "\xbc7"], "\x1e" => [0, "\xbc8"], "\x1f" => [0, "\xbc9"], " " => [0, "\xbc="], "!" => [0, "\xbcA"], "\"" => [0, "\xbc_"], "#" => [0, "\xbcb"], "\$" => [0, "\xbcd"], "%" => [0, "\xbcf"], "&" => [0, "\xbcg"], "'" => [0, "\xbch"], "(" => [0, "\xbcl"], ")" => [0, "\xbcm"], "*" => [0, "\xbcn"], "+" => [0, "\xbcp"], "," => [0, "\xbcr"], "-" => [0, "\xbcu"], "." => [100, "\xbc"], "/" => [110, "\xbc"], [111, "\xbc"], [115, "\xbc"], [116, "\xbc"], [118, "\xbc"], [119, "\xbc"], [122, "\xbc"], [123, "\xbc"], [125, "\xbc"], [126, "\xbc"], [129, "\xbc"], ":" => [143, "\xbc"], ";" => [148, "\xbc"], "<" => [151, "\xbc"], "=" => [153, "\xbc"], ">" => [83, "\xbc"], "?" => [10, "\xbc"], "@" => [77, "\xbf0"], "A" => [18, "\xbf0"], "B" => [77, "\xbf1"], "C" => [18, "\xbf1"], "D" => [77, "\xbf2"], "E" => [18, "\xbf2"], "F" => [77, "\xbfa"], "G" => [18, "\xbfa"], "H" => [77, "\xbfc"], "I" => [18, "\xbfc"], "J" => [77, "\xbfe"], "K" => [18, "\xbfe"], "L" => [77, "\xbfi"], "M" => [18, "\xbfi"], "N" => [77, "\xbfo"], "O" => [18, "\xbfo"], "P" => [77, "\xbfs"], "Q" => [18, "\xbfs"], "R" => [77, "\xbft"], "S" => [18, "\xbft"], "T" => [0, "\xbf "], "U" => [0, "\xbf%"], "V" => [0, "\xbf-"], "W" => [0, "\xbf."], "X" => [0, "\xbf/"], "Y" => [0, "\xbf3"], "Z" => [0, "\xbf4"], "[" => [0, "\xbf5"], "\\" => [0, "\xbf6"], "]" => [0, "\xbf7"], "^" => [0, "\xbf8"], "_" => [0, "\xbf9"], "`" => [0, "\xbf="], "a" => [0, "\xbfA"], "b" => [0, "\xbf_"], "c" => [0, "\xbfb"], "d" => [0, "\xbfd"], "e" => [0, "\xbff"], "f" => [0, "\xbfg"], "g" => [0, "\xbfh"], "h" => [0, "\xbfl"], "i" => [0, "\xbfm"], "j" => [0, "\xbfn"], "k" => [0, "\xbfp"], "l" => [0, "\xbfr"], "m" => [0, "\xbfu"], "n" => [100, "\xbf"], "o" => [110, "\xbf"], "p" => [111, "\xbf"], "q" => [115, "\xbf"], "r" => [116, "\xbf"], "s" => [118, "\xbf"], "t" => [119, "\xbf"], "u" => [122, "\xbf"], "v" => [123, "\xbf"], "w" => [125, "\xbf"], "x" => [126, "\xbf"], "y" => [129, "\xbf"], "z" => [143, "\xbf"], "{" => [148, "\xbf"], "|" => [151, "\xbf"], "}" => [153, "\xbf"], "~" => [83, "\xbf"], "" => [10, "\xbf"], "\x80" => [77, "\xc50"], "\x81" => [18, "\xc50"], "\x82" => [77, "\xc51"], "\x83" => [18, "\xc51"], "\x84" => [77, "\xc52"], "\x85" => [18, "\xc52"], "\x86" => [77, "\xc5a"], "\x87" => [18, "\xc5a"], "\x88" => [77, "\xc5c"], "\x89" => [18, "\xc5c"], "\x8a" => [77, "\xc5e"], "\x8b" => [18, "\xc5e"], "\x8c" => [77, "\xc5i"], "\x8d" => [18, "\xc5i"], "\x8e" => [77, "\xc5o"], "\x8f" => [18, "\xc5o"], "\x90" => [77, "\xc5s"], "\x91" => [18, "\xc5s"], "\x92" => [77, "\xc5t"], "\x93" => [18, "\xc5t"], "\x94" => [0, "\xc5 "], "\x95" => [0, "\xc5%"], "\x96" => [0, "\xc5-"], "\x97" => [0, "\xc5."], "\x98" => [0, "\xc5/"], "\x99" => [0, "\xc53"], "\x9a" => [0, "\xc54"], "\x9b" => [0, "\xc55"], "\x9c" => [0, "\xc56"], "\x9d" => [0, "\xc57"], "\x9e" => [0, "\xc58"], "\x9f" => [0, "\xc59"], "\xa0" => [0, "\xc5="], "\xa1" => [0, "\xc5A"], "\xa2" => [0, "\xc5_"], "\xa3" => [0, "\xc5b"], "\xa4" => [0, "\xc5d"], "\xa5" => [0, "\xc5f"], "\xa6" => [0, "\xc5g"], "\xa7" => [0, "\xc5h"], "\xa8" => [0, "\xc5l"], "\xa9" => [0, "\xc5m"], "\xaa" => [0, "\xc5n"], "\xab" => [0, "\xc5p"], "\xac" => [0, "\xc5r"], "\xad" => [0, "\xc5u"], "\xae" => [100, "\xc5"], "\xaf" => [110, "\xc5"], "\xb0" => [111, "\xc5"], "\xb1" => [115, "\xc5"], "\xb2" => [116, "\xc5"], "\xb3" => [118, "\xc5"], "\xb4" => [119, "\xc5"], "\xb5" => [122, "\xc5"], "\xb6" => [123, "\xc5"], "\xb7" => [125, "\xc5"], "\xb8" => [126, "\xc5"], "\xb9" => [129, "\xc5"], "\xba" => [143, "\xc5"], "\xbb" => [148, "\xc5"], "\xbc" => [151, "\xc5"], "\xbd" => [153, "\xc5"], "\xbe" => [83, "\xc5"], "\xbf" => [10, "\xc5"], "\xc0" => [77, "\xe70"], "\xc1" => [18, "\xe70"], "\xc2" => [77, "\xe71"], "\xc3" => [18, "\xe71"], "\xc4" => [77, "\xe72"], "\xc5" => [18, "\xe72"], "\xc6" => [77, "\xe7a"], "\xc7" => [18, "\xe7a"], "\xc8" => [77, "\xe7c"], "\xc9" => [18, "\xe7c"], "\xca" => [77, "\xe7e"], "\xcb" => [18, "\xe7e"], "\xcc" => [77, "\xe7i"], "\xcd" => [18, "\xe7i"], "\xce" => [77, "\xe7o"], "\xcf" => [18, "\xe7o"], "\xd0" => [77, "\xe7s"], "\xd1" => [18, "\xe7s"], "\xd2" => [77, "\xe7t"], "\xd3" => [18, "\xe7t"], "\xd4" => [0, "\xe7 "], "\xd5" => [0, "\xe7%"], "\xd6" => [0, "\xe7-"], "\xd7" => [0, "\xe7."], "\xd8" => [0, "\xe7/"], "\xd9" => [0, "\xe73"], "\xda" => [0, "\xe74"], "\xdb" => [0, "\xe75"], "\xdc" => [0, "\xe76"], "\xdd" => [0, "\xe77"], "\xde" => [0, "\xe78"], "\xdf" => [0, "\xe79"], "\xe0" => [0, "\xe7="], "\xe1" => [0, "\xe7A"], "\xe2" => [0, "\xe7_"], "\xe3" => [0, "\xe7b"], "\xe4" => [0, "\xe7d"], "\xe5" => [0, "\xe7f"], "\xe6" => [0, "\xe7g"], "\xe7" => [0, "\xe7h"], "\xe8" => [0, "\xe7l"], "\xe9" => [0, "\xe7m"], "\xea" => [0, "\xe7n"], "\xeb" => [0, "\xe7p"], "\xec" => [0, "\xe7r"], "\xed" => [0, "\xe7u"], "\xee" => [100, "\xe7"], "\xef" => [110, "\xe7"], "\xf0" => [111, "\xe7"], "\xf1" => [115, "\xe7"], "\xf2" => [116, "\xe7"], "\xf3" => [118, "\xe7"], "\xf4" => [119, "\xe7"], "\xf5" => [122, "\xe7"], "\xf6" => [123, "\xe7"], "\xf7" => [125, "\xe7"], "\xf8" => [126, "\xe7"], "\xf9" => [129, "\xe7"], "\xfa" => [143, "\xe7"], "\xfb" => [148, "\xe7"], "\xfc" => [151, "\xe7"], "\xfd" => [153, "\xe7"], "\xfe" => [83, "\xe7"], "\xff" => [10, "\xe7"]], ["\x00" => [94, "\xbe0"], "\x01" => [76, "\xbe0"], "\x02" => [104, "\xbe0"], "\x03" => [16, "\xbe0"], "\x04" => [94, "\xbe1"], "\x05" => [76, "\xbe1"], "\x06" => [104, "\xbe1"], "\x07" => [16, "\xbe1"], "\x08" => [94, "\xbe2"], "\t" => [76, "\xbe2"], "\n" => [104, "\xbe2"], "\v" => [16, "\xbe2"], "\f" => [94, "\xbea"], "\r" => [76, "\xbea"], "\x0e" => [104, "\xbea"], "\x0f" => [16, "\xbea"], "\x10" => [94, "\xbec"], "\x11" => [76, "\xbec"], "\x12" => [104, "\xbec"], "\x13" => [16, "\xbec"], "\x14" => [94, "\xbee"], "\x15" => [76, "\xbee"], "\x16" => [104, "\xbee"], "\x17" => [16, "\xbee"], "\x18" => [94, "\xbei"], "\x19" => [76, "\xbei"], "\x1a" => [104, "\xbei"], "\x1b" => [16, "\xbei"], "\x1c" => [94, "\xbeo"], "\x1d" => [76, "\xbeo"], "\x1e" => [104, "\xbeo"], "\x1f" => [16, "\xbeo"], " " => [94, "\xbes"], "!" => [76, "\xbes"], "\"" => [104, "\xbes"], "#" => [16, "\xbes"], "\$" => [94, "\xbet"], "%" => [76, "\xbet"], "&" => [104, "\xbet"], "'" => [16, "\xbet"], "(" => [77, "\xbe "], ")" => [18, "\xbe "], "*" => [77, "\xbe%"], "+" => [18, "\xbe%"], "," => [77, "\xbe-"], "-" => [18, "\xbe-"], "." => [77, "\xbe."], "/" => [18, "\xbe."], [77, "\xbe/"], [18, "\xbe/"], [77, "\xbe3"], [18, "\xbe3"], [77, "\xbe4"], [18, "\xbe4"], [77, "\xbe5"], [18, "\xbe5"], [77, "\xbe6"], [18, "\xbe6"], ":" => [77, "\xbe7"], ";" => [18, "\xbe7"], "<" => [77, "\xbe8"], "=" => [18, "\xbe8"], ">" => [77, "\xbe9"], "?" => [18, "\xbe9"], "@" => [77, "\xbe="], "A" => [18, "\xbe="], "B" => [77, "\xbeA"], "C" => [18, "\xbeA"], "D" => [77, "\xbe_"], "E" => [18, "\xbe_"], "F" => [77, "\xbeb"], "G" => [18, "\xbeb"], "H" => [77, "\xbed"], "I" => [18, "\xbed"], "J" => [77, "\xbef"], "K" => [18, "\xbef"], "L" => [77, "\xbeg"], "M" => [18, "\xbeg"], "N" => [77, "\xbeh"], "O" => [18, "\xbeh"], "P" => [77, "\xbel"], "Q" => [18, "\xbel"], "R" => [77, "\xbem"], "S" => [18, "\xbem"], "T" => [77, "\xben"], "U" => [18, "\xben"], "V" => [77, "\xbep"], "W" => [18, "\xbep"], "X" => [77, "\xber"], "Y" => [18, "\xber"], "Z" => [77, "\xbeu"], "[" => [18, "\xbeu"], "\\" => [0, "\xbe:"], "]" => [0, "\xbeB"], "^" => [0, "\xbeC"], "_" => [0, "\xbeD"], "`" => [0, "\xbeE"], "a" => [0, "\xbeF"], "b" => [0, "\xbeG"], "c" => [0, "\xbeH"], "d" => [0, "\xbeI"], "e" => [0, "\xbeJ"], "f" => [0, "\xbeK"], "g" => [0, "\xbeL"], "h" => [0, "\xbeM"], "i" => [0, "\xbeN"], "j" => [0, "\xbeO"], "k" => [0, "\xbeP"], "l" => [0, "\xbeQ"], "m" => [0, "\xbeR"], "n" => [0, "\xbeS"], "o" => [0, "\xbeT"], "p" => [0, "\xbeU"], "q" => [0, "\xbeV"], "r" => [0, "\xbeW"], "s" => [0, "\xbeY"], "t" => [0, "\xbej"], "u" => [0, "\xbek"], "v" => [0, "\xbeq"], "w" => [0, "\xbev"], "x" => [0, "\xbew"], "y" => [0, "\xbex"], "z" => [0, "\xbey"], "{" => [0, "\xbez"], "|" => [82, "\xbe"], "}" => [87, "\xbe"], "~" => [130, "\xbe"], "" => [9, "\xbe"], "\x80" => [94, "\xc40"], "\x81" => [76, "\xc40"], "\x82" => [104, "\xc40"], "\x83" => [16, "\xc40"], "\x84" => [94, "\xc41"], "\x85" => [76, "\xc41"], "\x86" => [104, "\xc41"], "\x87" => [16, "\xc41"], "\x88" => [94, "\xc42"], "\x89" => [76, "\xc42"], "\x8a" => [104, "\xc42"], "\x8b" => [16, "\xc42"], "\x8c" => [94, "\xc4a"], "\x8d" => [76, "\xc4a"], "\x8e" => [104, "\xc4a"], "\x8f" => [16, "\xc4a"], "\x90" => [94, "\xc4c"], "\x91" => [76, "\xc4c"], "\x92" => [104, "\xc4c"], "\x93" => [16, "\xc4c"], "\x94" => [94, "\xc4e"], "\x95" => [76, "\xc4e"], "\x96" => [104, "\xc4e"], "\x97" => [16, "\xc4e"], "\x98" => [94, "\xc4i"], "\x99" => [76, "\xc4i"], "\x9a" => [104, "\xc4i"], "\x9b" => [16, "\xc4i"], "\x9c" => [94, "\xc4o"], "\x9d" => [76, "\xc4o"], "\x9e" => [104, "\xc4o"], "\x9f" => [16, "\xc4o"], "\xa0" => [94, "\xc4s"], "\xa1" => [76, "\xc4s"], "\xa2" => [104, "\xc4s"], "\xa3" => [16, "\xc4s"], "\xa4" => [94, "\xc4t"], "\xa5" => [76, "\xc4t"], "\xa6" => [104, "\xc4t"], "\xa7" => [16, "\xc4t"], "\xa8" => [77, "\xc4 "], "\xa9" => [18, "\xc4 "], "\xaa" => [77, "\xc4%"], "\xab" => [18, "\xc4%"], "\xac" => [77, "\xc4-"], "\xad" => [18, "\xc4-"], "\xae" => [77, "\xc4."], "\xaf" => [18, "\xc4."], "\xb0" => [77, "\xc4/"], "\xb1" => [18, "\xc4/"], "\xb2" => [77, "\xc43"], "\xb3" => [18, "\xc43"], "\xb4" => [77, "\xc44"], "\xb5" => [18, "\xc44"], "\xb6" => [77, "\xc45"], "\xb7" => [18, "\xc45"], "\xb8" => [77, "\xc46"], "\xb9" => [18, "\xc46"], "\xba" => [77, "\xc47"], "\xbb" => [18, "\xc47"], "\xbc" => [77, "\xc48"], "\xbd" => [18, "\xc48"], "\xbe" => [77, "\xc49"], "\xbf" => [18, "\xc49"], "\xc0" => [77, "\xc4="], "\xc1" => [18, "\xc4="], "\xc2" => [77, "\xc4A"], "\xc3" => [18, "\xc4A"], "\xc4" => [77, "\xc4_"], "\xc5" => [18, "\xc4_"], "\xc6" => [77, "\xc4b"], "\xc7" => [18, "\xc4b"], "\xc8" => [77, "\xc4d"], "\xc9" => [18, "\xc4d"], "\xca" => [77, "\xc4f"], "\xcb" => [18, "\xc4f"], "\xcc" => [77, "\xc4g"], "\xcd" => [18, "\xc4g"], "\xce" => [77, "\xc4h"], "\xcf" => [18, "\xc4h"], "\xd0" => [77, "\xc4l"], "\xd1" => [18, "\xc4l"], "\xd2" => [77, "\xc4m"], "\xd3" => [18, "\xc4m"], "\xd4" => [77, "\xc4n"], "\xd5" => [18, "\xc4n"], "\xd6" => [77, "\xc4p"], "\xd7" => [18, "\xc4p"], "\xd8" => [77, "\xc4r"], "\xd9" => [18, "\xc4r"], "\xda" => [77, "\xc4u"], "\xdb" => [18, "\xc4u"], "\xdc" => [0, "\xc4:"], "\xdd" => [0, "\xc4B"], "\xde" => [0, "\xc4C"], "\xdf" => [0, "\xc4D"], "\xe0" => [0, "\xc4E"], "\xe1" => [0, "\xc4F"], "\xe2" => [0, "\xc4G"], "\xe3" => [0, "\xc4H"], "\xe4" => [0, "\xc4I"], "\xe5" => [0, "\xc4J"], "\xe6" => [0, "\xc4K"], "\xe7" => [0, "\xc4L"], "\xe8" => [0, "\xc4M"], "\xe9" => [0, "\xc4N"], "\xea" => [0, "\xc4O"], "\xeb" => [0, "\xc4P"], "\xec" => [0, "\xc4Q"], "\xed" => [0, "\xc4R"], "\xee" => [0, "\xc4S"], "\xef" => [0, "\xc4T"], "\xf0" => [0, "\xc4U"], "\xf1" => [0, "\xc4V"], "\xf2" => [0, "\xc4W"], "\xf3" => [0, "\xc4Y"], "\xf4" => [0, "\xc4j"], "\xf5" => [0, "\xc4k"], "\xf6" => [0, "\xc4q"], "\xf7" => [0, "\xc4v"], "\xf8" => [0, "\xc4w"], "\xf9" => [0, "\xc4x"], "\xfa" => [0, "\xc4y"], "\xfb" => [0, "\xc4z"], "\xfc" => [82, "\xc4"], "\xfd" => [87, "\xc4"], "\xfe" => [130, "\xc4"], "\xff" => [9, "\xc4"]], ["\x00" => [77, "\xc00"], "\x01" => [18, "\xc00"], "\x02" => [77, "\xc01"], "\x03" => [18, "\xc01"], "\x04" => [77, "\xc02"], "\x05" => [18, "\xc02"], "\x06" => [77, "\xc0a"], "\x07" => [18, "\xc0a"], "\x08" => [77, "\xc0c"], "\t" => [18, "\xc0c"], "\n" => [77, "\xc0e"], "\v" => [18, "\xc0e"], "\f" => [77, "\xc0i"], "\r" => [18, "\xc0i"], "\x0e" => [77, "\xc0o"], "\x0f" => [18, "\xc0o"], "\x10" => [77, "\xc0s"], "\x11" => [18, "\xc0s"], "\x12" => [77, "\xc0t"], "\x13" => [18, "\xc0t"], "\x14" => [0, "\xc0 "], "\x15" => [0, "\xc0%"], "\x16" => [0, "\xc0-"], "\x17" => [0, "\xc0."], "\x18" => [0, "\xc0/"], "\x19" => [0, "\xc03"], "\x1a" => [0, "\xc04"], "\x1b" => [0, "\xc05"], "\x1c" => [0, "\xc06"], "\x1d" => [0, "\xc07"], "\x1e" => [0, "\xc08"], "\x1f" => [0, "\xc09"], " " => [0, "\xc0="], "!" => [0, "\xc0A"], "\"" => [0, "\xc0_"], "#" => [0, "\xc0b"], "\$" => [0, "\xc0d"], "%" => [0, "\xc0f"], "&" => [0, "\xc0g"], "'" => [0, "\xc0h"], "(" => [0, "\xc0l"], ")" => [0, "\xc0m"], "*" => [0, "\xc0n"], "+" => [0, "\xc0p"], "," => [0, "\xc0r"], "-" => [0, "\xc0u"], "." => [100, "\xc0"], "/" => [110, "\xc0"], [111, "\xc0"], [115, "\xc0"], [116, "\xc0"], [118, "\xc0"], [119, "\xc0"], [122, "\xc0"], [123, "\xc0"], [125, "\xc0"], [126, "\xc0"], [129, "\xc0"], ":" => [143, "\xc0"], ";" => [148, "\xc0"], "<" => [151, "\xc0"], "=" => [153, "\xc0"], ">" => [83, "\xc0"], "?" => [10, "\xc0"], "@" => [77, "\xc10"], "A" => [18, "\xc10"], "B" => [77, "\xc11"], "C" => [18, "\xc11"], "D" => [77, "\xc12"], "E" => [18, "\xc12"], "F" => [77, "\xc1a"], "G" => [18, "\xc1a"], "H" => [77, "\xc1c"], "I" => [18, "\xc1c"], "J" => [77, "\xc1e"], "K" => [18, "\xc1e"], "L" => [77, "\xc1i"], "M" => [18, "\xc1i"], "N" => [77, "\xc1o"], "O" => [18, "\xc1o"], "P" => [77, "\xc1s"], "Q" => [18, "\xc1s"], "R" => [77, "\xc1t"], "S" => [18, "\xc1t"], "T" => [0, "\xc1 "], "U" => [0, "\xc1%"], "V" => [0, "\xc1-"], "W" => [0, "\xc1."], "X" => [0, "\xc1/"], "Y" => [0, "\xc13"], "Z" => [0, "\xc14"], "[" => [0, "\xc15"], "\\" => [0, "\xc16"], "]" => [0, "\xc17"], "^" => [0, "\xc18"], "_" => [0, "\xc19"], "`" => [0, "\xc1="], "a" => [0, "\xc1A"], "b" => [0, "\xc1_"], "c" => [0, "\xc1b"], "d" => [0, "\xc1d"], "e" => [0, "\xc1f"], "f" => [0, "\xc1g"], "g" => [0, "\xc1h"], "h" => [0, "\xc1l"], "i" => [0, "\xc1m"], "j" => [0, "\xc1n"], "k" => [0, "\xc1p"], "l" => [0, "\xc1r"], "m" => [0, "\xc1u"], "n" => [100, "\xc1"], "o" => [110, "\xc1"], "p" => [111, "\xc1"], "q" => [115, "\xc1"], "r" => [116, "\xc1"], "s" => [118, "\xc1"], "t" => [119, "\xc1"], "u" => [122, "\xc1"], "v" => [123, "\xc1"], "w" => [125, "\xc1"], "x" => [126, "\xc1"], "y" => [129, "\xc1"], "z" => [143, "\xc1"], "{" => [148, "\xc1"], "|" => [151, "\xc1"], "}" => [153, "\xc1"], "~" => [83, "\xc1"], "" => [10, "\xc1"], "\x80" => [77, "\xc80"], "\x81" => [18, "\xc80"], "\x82" => [77, "\xc81"], "\x83" => [18, "\xc81"], "\x84" => [77, "\xc82"], "\x85" => [18, "\xc82"], "\x86" => [77, "\xc8a"], "\x87" => [18, "\xc8a"], "\x88" => [77, "\xc8c"], "\x89" => [18, "\xc8c"], "\x8a" => [77, "\xc8e"], "\x8b" => [18, "\xc8e"], "\x8c" => [77, "\xc8i"], "\x8d" => [18, "\xc8i"], "\x8e" => [77, "\xc8o"], "\x8f" => [18, "\xc8o"], "\x90" => [77, "\xc8s"], "\x91" => [18, "\xc8s"], "\x92" => [77, "\xc8t"], "\x93" => [18, "\xc8t"], "\x94" => [0, "\xc8 "], "\x95" => [0, "\xc8%"], "\x96" => [0, "\xc8-"], "\x97" => [0, "\xc8."], "\x98" => [0, "\xc8/"], "\x99" => [0, "\xc83"], "\x9a" => [0, "\xc84"], "\x9b" => [0, "\xc85"], "\x9c" => [0, "\xc86"], "\x9d" => [0, "\xc87"], "\x9e" => [0, "\xc88"], "\x9f" => [0, "\xc89"], "\xa0" => [0, "\xc8="], "\xa1" => [0, "\xc8A"], "\xa2" => [0, "\xc8_"], "\xa3" => [0, "\xc8b"], "\xa4" => [0, "\xc8d"], "\xa5" => [0, "\xc8f"], "\xa6" => [0, "\xc8g"], "\xa7" => [0, "\xc8h"], "\xa8" => [0, "\xc8l"], "\xa9" => [0, "\xc8m"], "\xaa" => [0, "\xc8n"], "\xab" => [0, "\xc8p"], "\xac" => [0, "\xc8r"], "\xad" => [0, "\xc8u"], "\xae" => [100, "\xc8"], "\xaf" => [110, "\xc8"], "\xb0" => [111, "\xc8"], "\xb1" => [115, "\xc8"], "\xb2" => [116, "\xc8"], "\xb3" => [118, "\xc8"], "\xb4" => [119, "\xc8"], "\xb5" => [122, "\xc8"], "\xb6" => [123, "\xc8"], "\xb7" => [125, "\xc8"], "\xb8" => [126, "\xc8"], "\xb9" => [129, "\xc8"], "\xba" => [143, "\xc8"], "\xbb" => [148, "\xc8"], "\xbc" => [151, "\xc8"], "\xbd" => [153, "\xc8"], "\xbe" => [83, "\xc8"], "\xbf" => [10, "\xc8"], "\xc0" => [77, "\xc90"], "\xc1" => [18, "\xc90"], "\xc2" => [77, "\xc91"], "\xc3" => [18, "\xc91"], "\xc4" => [77, "\xc92"], "\xc5" => [18, "\xc92"], "\xc6" => [77, "\xc9a"], "\xc7" => [18, "\xc9a"], "\xc8" => [77, "\xc9c"], "\xc9" => [18, "\xc9c"], "\xca" => [77, "\xc9e"], "\xcb" => [18, "\xc9e"], "\xcc" => [77, "\xc9i"], "\xcd" => [18, "\xc9i"], "\xce" => [77, "\xc9o"], "\xcf" => [18, "\xc9o"], "\xd0" => [77, "\xc9s"], "\xd1" => [18, "\xc9s"], "\xd2" => [77, "\xc9t"], "\xd3" => [18, "\xc9t"], "\xd4" => [0, "\xc9 "], "\xd5" => [0, "\xc9%"], "\xd6" => [0, "\xc9-"], "\xd7" => [0, "\xc9."], "\xd8" => [0, "\xc9/"], "\xd9" => [0, "\xc93"], "\xda" => [0, "\xc94"], "\xdb" => [0, "\xc95"], "\xdc" => [0, "\xc96"], "\xdd" => [0, "\xc97"], "\xde" => [0, "\xc98"], "\xdf" => [0, "\xc99"], "\xe0" => [0, "\xc9="], "\xe1" => [0, "\xc9A"], "\xe2" => [0, "\xc9_"], "\xe3" => [0, "\xc9b"], "\xe4" => [0, "\xc9d"], "\xe5" => [0, "\xc9f"], "\xe6" => [0, "\xc9g"], "\xe7" => [0, "\xc9h"], "\xe8" => [0, "\xc9l"], "\xe9" => [0, "\xc9m"], "\xea" => [0, "\xc9n"], "\xeb" => [0, "\xc9p"], "\xec" => [0, "\xc9r"], "\xed" => [0, "\xc9u"], "\xee" => [100, "\xc9"], "\xef" => [110, "\xc9"], "\xf0" => [111, "\xc9"], "\xf1" => [115, "\xc9"], "\xf2" => [116, "\xc9"], "\xf3" => [118, "\xc9"], "\xf4" => [119, "\xc9"], "\xf5" => [122, "\xc9"], "\xf6" => [123, "\xc9"], "\xf7" => [125, "\xc9"], "\xf8" => [126, "\xc9"], "\xf9" => [129, "\xc9"], "\xfa" => [143, "\xc9"], "\xfb" => [148, "\xc9"], "\xfc" => [151, "\xc9"], "\xfd" => [153, "\xc9"], "\xfe" => [83, "\xc9"], "\xff" => [10, "\xc9"]], ["\x00" => [0, "\xc00"], "\x01" => [0, "\xc01"], "\x02" => [0, "\xc02"], "\x03" => [0, "\xc0a"], "\x04" => [0, "\xc0c"], "\x05" => [0, "\xc0e"], "\x06" => [0, "\xc0i"], "\x07" => [0, "\xc0o"], "\x08" => [0, "\xc0s"], "\t" => [0, "\xc0t"], "\n" => [73, "\xc0"], "\v" => [88, "\xc0"], "\f" => [89, "\xc0"], "\r" => [96, "\xc0"], "\x0e" => [97, "\xc0"], "\x0f" => [99, "\xc0"], "\x10" => [106, "\xc0"], "\x11" => [136, "\xc0"], "\x12" => [139, "\xc0"], "\x13" => [141, "\xc0"], "\x14" => [145, "\xc0"], "\x15" => [147, "\xc0"], "\x16" => [149, "\xc0"], "\x17" => [101, "\xc0"], "\x18" => [112, "\xc0"], "\x19" => [117, "\xc0"], "\x1a" => [120, "\xc0"], "\x1b" => [124, "\xc0"], "\x1c" => [127, "\xc0"], "\x1d" => [144, "\xc0"], "\x1e" => [152, "\xc0"], "\x1f" => [11, "\xc0"], " " => [0, "\xc10"], "!" => [0, "\xc11"], "\"" => [0, "\xc12"], "#" => [0, "\xc1a"], "\$" => [0, "\xc1c"], "%" => [0, "\xc1e"], "&" => [0, "\xc1i"], "'" => [0, "\xc1o"], "(" => [0, "\xc1s"], ")" => [0, "\xc1t"], "*" => [73, "\xc1"], "+" => [88, "\xc1"], "," => [89, "\xc1"], "-" => [96, "\xc1"], "." => [97, "\xc1"], "/" => [99, "\xc1"], [106, "\xc1"], [136, "\xc1"], [139, "\xc1"], [141, "\xc1"], [145, "\xc1"], [147, "\xc1"], [149, "\xc1"], [101, "\xc1"], [112, "\xc1"], [117, "\xc1"], ":" => [120, "\xc1"], ";" => [124, "\xc1"], "<" => [127, "\xc1"], "=" => [144, "\xc1"], ">" => [152, "\xc1"], "?" => [11, "\xc1"], "@" => [0, "\xc80"], "A" => [0, "\xc81"], "B" => [0, "\xc82"], "C" => [0, "\xc8a"], "D" => [0, "\xc8c"], "E" => [0, "\xc8e"], "F" => [0, "\xc8i"], "G" => [0, "\xc8o"], "H" => [0, "\xc8s"], "I" => [0, "\xc8t"], "J" => [73, "\xc8"], "K" => [88, "\xc8"], "L" => [89, "\xc8"], "M" => [96, "\xc8"], "N" => [97, "\xc8"], "O" => [99, "\xc8"], "P" => [106, "\xc8"], "Q" => [136, "\xc8"], "R" => [139, "\xc8"], "S" => [141, "\xc8"], "T" => [145, "\xc8"], "U" => [147, "\xc8"], "V" => [149, "\xc8"], "W" => [101, "\xc8"], "X" => [112, "\xc8"], "Y" => [117, "\xc8"], "Z" => [120, "\xc8"], "[" => [124, "\xc8"], "\\" => [127, "\xc8"], "]" => [144, "\xc8"], "^" => [152, "\xc8"], "_" => [11, "\xc8"], "`" => [0, "\xc90"], "a" => [0, "\xc91"], "b" => [0, "\xc92"], "c" => [0, "\xc9a"], "d" => [0, "\xc9c"], "e" => [0, "\xc9e"], "f" => [0, "\xc9i"], "g" => [0, "\xc9o"], "h" => [0, "\xc9s"], "i" => [0, "\xc9t"], "j" => [73, "\xc9"], "k" => [88, "\xc9"], "l" => [89, "\xc9"], "m" => [96, "\xc9"], "n" => [97, "\xc9"], "o" => [99, "\xc9"], "p" => [106, "\xc9"], "q" => [136, "\xc9"], "r" => [139, "\xc9"], "s" => [141, "\xc9"], "t" => [145, "\xc9"], "u" => [147, "\xc9"], "v" => [149, "\xc9"], "w" => [101, "\xc9"], "x" => [112, "\xc9"], "y" => [117, "\xc9"], "z" => [120, "\xc9"], "{" => [124, "\xc9"], "|" => [127, "\xc9"], "}" => [144, "\xc9"], "~" => [152, "\xc9"], "" => [11, "\xc9"], "\x80" => [0, "\xca0"], "\x81" => [0, "\xca1"], "\x82" => [0, "\xca2"], "\x83" => [0, "\xcaa"], "\x84" => [0, "\xcac"], "\x85" => [0, "\xcae"], "\x86" => [0, "\xcai"], "\x87" => [0, "\xcao"], "\x88" => [0, "\xcas"], "\x89" => [0, "\xcat"], "\x8a" => [73, "\xca"], "\x8b" => [88, "\xca"], "\x8c" => [89, "\xca"], "\x8d" => [96, "\xca"], "\x8e" => [97, "\xca"], "\x8f" => [99, "\xca"], "\x90" => [106, "\xca"], "\x91" => [136, "\xca"], "\x92" => [139, "\xca"], "\x93" => [141, "\xca"], "\x94" => [145, "\xca"], "\x95" => [147, "\xca"], "\x96" => [149, "\xca"], "\x97" => [101, "\xca"], "\x98" => [112, "\xca"], "\x99" => [117, "\xca"], "\x9a" => [120, "\xca"], "\x9b" => [124, "\xca"], "\x9c" => [127, "\xca"], "\x9d" => [144, "\xca"], "\x9e" => [152, "\xca"], "\x9f" => [11, "\xca"], "\xa0" => [0, "\xcd0"], "\xa1" => [0, "\xcd1"], "\xa2" => [0, "\xcd2"], "\xa3" => [0, "\xcda"], "\xa4" => [0, "\xcdc"], "\xa5" => [0, "\xcde"], "\xa6" => [0, "\xcdi"], "\xa7" => [0, "\xcdo"], "\xa8" => [0, "\xcds"], "\xa9" => [0, "\xcdt"], "\xaa" => [73, "\xcd"], "\xab" => [88, "\xcd"], "\xac" => [89, "\xcd"], "\xad" => [96, "\xcd"], "\xae" => [97, "\xcd"], "\xaf" => [99, "\xcd"], "\xb0" => [106, "\xcd"], "\xb1" => [136, "\xcd"], "\xb2" => [139, "\xcd"], "\xb3" => [141, "\xcd"], "\xb4" => [145, "\xcd"], "\xb5" => [147, "\xcd"], "\xb6" => [149, "\xcd"], "\xb7" => [101, "\xcd"], "\xb8" => [112, "\xcd"], "\xb9" => [117, "\xcd"], "\xba" => [120, "\xcd"], "\xbb" => [124, "\xcd"], "\xbc" => [127, "\xcd"], "\xbd" => [144, "\xcd"], "\xbe" => [152, "\xcd"], "\xbf" => [11, "\xcd"], "\xc0" => [0, "\xd20"], "\xc1" => [0, "\xd21"], "\xc2" => [0, "\xd22"], "\xc3" => [0, "\xd2a"], "\xc4" => [0, "\xd2c"], "\xc5" => [0, "\xd2e"], "\xc6" => [0, "\xd2i"], "\xc7" => [0, "\xd2o"], "\xc8" => [0, "\xd2s"], "\xc9" => [0, "\xd2t"], "\xca" => [73, "\xd2"], "\xcb" => [88, "\xd2"], "\xcc" => [89, "\xd2"], "\xcd" => [96, "\xd2"], "\xce" => [97, "\xd2"], "\xcf" => [99, "\xd2"], "\xd0" => [106, "\xd2"], "\xd1" => [136, "\xd2"], "\xd2" => [139, "\xd2"], "\xd3" => [141, "\xd2"], "\xd4" => [145, "\xd2"], "\xd5" => [147, "\xd2"], "\xd6" => [149, "\xd2"], "\xd7" => [101, "\xd2"], "\xd8" => [112, "\xd2"], "\xd9" => [117, "\xd2"], "\xda" => [120, "\xd2"], "\xdb" => [124, "\xd2"], "\xdc" => [127, "\xd2"], "\xdd" => [144, "\xd2"], "\xde" => [152, "\xd2"], "\xdf" => [11, "\xd2"], "\xe0" => [0, "\xd50"], "\xe1" => [0, "\xd51"], "\xe2" => [0, "\xd52"], "\xe3" => [0, "\xd5a"], "\xe4" => [0, "\xd5c"], "\xe5" => [0, "\xd5e"], "\xe6" => [0, "\xd5i"], "\xe7" => [0, "\xd5o"], "\xe8" => [0, "\xd5s"], "\xe9" => [0, "\xd5t"], "\xea" => [73, "\xd5"], "\xeb" => [88, "\xd5"], "\xec" => [89, "\xd5"], "\xed" => [96, "\xd5"], "\xee" => [97, "\xd5"], "\xef" => [99, "\xd5"], "\xf0" => [106, "\xd5"], "\xf1" => [136, "\xd5"], "\xf2" => [139, "\xd5"], "\xf3" => [141, "\xd5"], "\xf4" => [145, "\xd5"], "\xf5" => [147, "\xd5"], "\xf6" => [149, "\xd5"], "\xf7" => [101, "\xd5"], "\xf8" => [112, "\xd5"], "\xf9" => [117, "\xd5"], "\xfa" => [120, "\xd5"], "\xfb" => [124, "\xd5"], "\xfc" => [127, "\xd5"], "\xfd" => [144, "\xd5"], "\xfe" => [152, "\xd5"], "\xff" => [11, "\xd5"]], ["\x00" => [92, "\xc0"], "\x01" => [95, "\xc0"], "\x02" => [137, "\xc0"], "\x03" => [142, "\xc0"], "\x04" => [150, "\xc0"], "\x05" => [74, "\xc0"], "\x06" => [90, "\xc0"], "\x07" => [98, "\xc0"], "\x08" => [107, "\xc0"], "\t" => [140, "\xc0"], "\n" => [146, "\xc0"], "\v" => [102, "\xc0"], "\f" => [113, "\xc0"], "\r" => [121, "\xc0"], "\x0e" => [128, "\xc0"], "\x0f" => [12, "\xc0"], "\x10" => [92, "\xc1"], "\x11" => [95, "\xc1"], "\x12" => [137, "\xc1"], "\x13" => [142, "\xc1"], "\x14" => [150, "\xc1"], "\x15" => [74, "\xc1"], "\x16" => [90, "\xc1"], "\x17" => [98, "\xc1"], "\x18" => [107, "\xc1"], "\x19" => [140, "\xc1"], "\x1a" => [146, "\xc1"], "\x1b" => [102, "\xc1"], "\x1c" => [113, "\xc1"], "\x1d" => [121, "\xc1"], "\x1e" => [128, "\xc1"], "\x1f" => [12, "\xc1"], " " => [92, "\xc8"], "!" => [95, "\xc8"], "\"" => [137, "\xc8"], "#" => [142, "\xc8"], "\$" => [150, "\xc8"], "%" => [74, "\xc8"], "&" => [90, "\xc8"], "'" => [98, "\xc8"], "(" => [107, "\xc8"], ")" => [140, "\xc8"], "*" => [146, "\xc8"], "+" => [102, "\xc8"], "," => [113, "\xc8"], "-" => [121, "\xc8"], "." => [128, "\xc8"], "/" => [12, "\xc8"], [92, "\xc9"], [95, "\xc9"], [137, "\xc9"], [142, "\xc9"], [150, "\xc9"], [74, "\xc9"], [90, "\xc9"], [98, "\xc9"], [107, "\xc9"], [140, "\xc9"], ":" => [146, "\xc9"], ";" => [102, "\xc9"], "<" => [113, "\xc9"], "=" => [121, "\xc9"], ">" => [128, "\xc9"], "?" => [12, "\xc9"], "@" => [92, "\xca"], "A" => [95, "\xca"], "B" => [137, "\xca"], "C" => [142, "\xca"], "D" => [150, "\xca"], "E" => [74, "\xca"], "F" => [90, "\xca"], "G" => [98, "\xca"], "H" => [107, "\xca"], "I" => [140, "\xca"], "J" => [146, "\xca"], "K" => [102, "\xca"], "L" => [113, "\xca"], "M" => [121, "\xca"], "N" => [128, "\xca"], "O" => [12, "\xca"], "P" => [92, "\xcd"], "Q" => [95, "\xcd"], "R" => [137, "\xcd"], "S" => [142, "\xcd"], "T" => [150, "\xcd"], "U" => [74, "\xcd"], "V" => [90, "\xcd"], "W" => [98, "\xcd"], "X" => [107, "\xcd"], "Y" => [140, "\xcd"], "Z" => [146, "\xcd"], "[" => [102, "\xcd"], "\\" => [113, "\xcd"], "]" => [121, "\xcd"], "^" => [128, "\xcd"], "_" => [12, "\xcd"], "`" => [92, "\xd2"], "a" => [95, "\xd2"], "b" => [137, "\xd2"], "c" => [142, "\xd2"], "d" => [150, "\xd2"], "e" => [74, "\xd2"], "f" => [90, "\xd2"], "g" => [98, "\xd2"], "h" => [107, "\xd2"], "i" => [140, "\xd2"], "j" => [146, "\xd2"], "k" => [102, "\xd2"], "l" => [113, "\xd2"], "m" => [121, "\xd2"], "n" => [128, "\xd2"], "o" => [12, "\xd2"], "p" => [92, "\xd5"], "q" => [95, "\xd5"], "r" => [137, "\xd5"], "s" => [142, "\xd5"], "t" => [150, "\xd5"], "u" => [74, "\xd5"], "v" => [90, "\xd5"], "w" => [98, "\xd5"], "x" => [107, "\xd5"], "y" => [140, "\xd5"], "z" => [146, "\xd5"], "{" => [102, "\xd5"], "|" => [113, "\xd5"], "}" => [121, "\xd5"], "~" => [128, "\xd5"], "" => [12, "\xd5"], "\x80" => [92, "\xda"], "\x81" => [95, "\xda"], "\x82" => [137, "\xda"], "\x83" => [142, "\xda"], "\x84" => [150, "\xda"], "\x85" => [74, "\xda"], "\x86" => [90, "\xda"], "\x87" => [98, "\xda"], "\x88" => [107, "\xda"], "\x89" => [140, "\xda"], "\x8a" => [146, "\xda"], "\x8b" => [102, "\xda"], "\x8c" => [113, "\xda"], "\x8d" => [121, "\xda"], "\x8e" => [128, "\xda"], "\x8f" => [12, "\xda"], "\x90" => [92, "\xdb"], "\x91" => [95, "\xdb"], "\x92" => [137, "\xdb"], "\x93" => [142, "\xdb"], "\x94" => [150, "\xdb"], "\x95" => [74, "\xdb"], "\x96" => [90, "\xdb"], "\x97" => [98, "\xdb"], "\x98" => [107, "\xdb"], "\x99" => [140, "\xdb"], "\x9a" => [146, "\xdb"], "\x9b" => [102, "\xdb"], "\x9c" => [113, "\xdb"], "\x9d" => [121, "\xdb"], "\x9e" => [128, "\xdb"], "\x9f" => [12, "\xdb"], "\xa0" => [92, "\xee"], "\xa1" => [95, "\xee"], "\xa2" => [137, "\xee"], "\xa3" => [142, "\xee"], "\xa4" => [150, "\xee"], "\xa5" => [74, "\xee"], "\xa6" => [90, "\xee"], "\xa7" => [98, "\xee"], "\xa8" => [107, "\xee"], "\xa9" => [140, "\xee"], "\xaa" => [146, "\xee"], "\xab" => [102, "\xee"], "\xac" => [113, "\xee"], "\xad" => [121, "\xee"], "\xae" => [128, "\xee"], "\xaf" => [12, "\xee"], "\xb0" => [92, "\xf0"], "\xb1" => [95, "\xf0"], "\xb2" => [137, "\xf0"], "\xb3" => [142, "\xf0"], "\xb4" => [150, "\xf0"], "\xb5" => [74, "\xf0"], "\xb6" => [90, "\xf0"], "\xb7" => [98, "\xf0"], "\xb8" => [107, "\xf0"], "\xb9" => [140, "\xf0"], "\xba" => [146, "\xf0"], "\xbb" => [102, "\xf0"], "\xbc" => [113, "\xf0"], "\xbd" => [121, "\xf0"], "\xbe" => [128, "\xf0"], "\xbf" => [12, "\xf0"], "\xc0" => [92, "\xf2"], "\xc1" => [95, "\xf2"], "\xc2" => [137, "\xf2"], "\xc3" => [142, "\xf2"], "\xc4" => [150, "\xf2"], "\xc5" => [74, "\xf2"], "\xc6" => [90, "\xf2"], "\xc7" => [98, "\xf2"], "\xc8" => [107, "\xf2"], "\xc9" => [140, "\xf2"], "\xca" => [146, "\xf2"], "\xcb" => [102, "\xf2"], "\xcc" => [113, "\xf2"], "\xcd" => [121, "\xf2"], "\xce" => [128, "\xf2"], "\xcf" => [12, "\xf2"], "\xd0" => [92, "\xf3"], "\xd1" => [95, "\xf3"], "\xd2" => [137, "\xf3"], "\xd3" => [142, "\xf3"], "\xd4" => [150, "\xf3"], "\xd5" => [74, "\xf3"], "\xd6" => [90, "\xf3"], "\xd7" => [98, "\xf3"], "\xd8" => [107, "\xf3"], "\xd9" => [140, "\xf3"], "\xda" => [146, "\xf3"], "\xdb" => [102, "\xf3"], "\xdc" => [113, "\xf3"], "\xdd" => [121, "\xf3"], "\xde" => [128, "\xf3"], "\xdf" => [12, "\xf3"], "\xe0" => [92, "\xff"], "\xe1" => [95, "\xff"], "\xe2" => [137, "\xff"], "\xe3" => [142, "\xff"], "\xe4" => [150, "\xff"], "\xe5" => [74, "\xff"], "\xe6" => [90, "\xff"], "\xe7" => [98, "\xff"], "\xe8" => [107, "\xff"], "\xe9" => [140, "\xff"], "\xea" => [146, "\xff"], "\xeb" => [102, "\xff"], "\xec" => [113, "\xff"], "\xed" => [121, "\xff"], "\xee" => [128, "\xff"], "\xef" => [12, "\xff"], "\xf0" => [93, "\xcb"], "\xf1" => [138, "\xcb"], "\xf2" => [75, "\xcb"], "\xf3" => [91, "\xcb"], "\xf4" => [108, "\xcb"], "\xf5" => [103, "\xcb"], "\xf6" => [114, "\xcb"], "\xf7" => [14, "\xcb"], "\xf8" => [93, "\xcc"], "\xf9" => [138, "\xcc"], "\xfa" => [75, "\xcc"], "\xfb" => [91, "\xcc"], "\xfc" => [108, "\xcc"], "\xfd" => [103, "\xcc"], "\xfe" => [114, "\xcc"], "\xff" => [14, "\xcc"]], ["\x00" => [94, "\xc00"], "\x01" => [76, "\xc00"], "\x02" => [104, "\xc00"], "\x03" => [16, "\xc00"], "\x04" => [94, "\xc01"], "\x05" => [76, "\xc01"], "\x06" => [104, "\xc01"], "\x07" => [16, "\xc01"], "\x08" => [94, "\xc02"], "\t" => [76, "\xc02"], "\n" => [104, "\xc02"], "\v" => [16, "\xc02"], "\f" => [94, "\xc0a"], "\r" => [76, "\xc0a"], "\x0e" => [104, "\xc0a"], "\x0f" => [16, "\xc0a"], "\x10" => [94, "\xc0c"], "\x11" => [76, "\xc0c"], "\x12" => [104, "\xc0c"], "\x13" => [16, "\xc0c"], "\x14" => [94, "\xc0e"], "\x15" => [76, "\xc0e"], "\x16" => [104, "\xc0e"], "\x17" => [16, "\xc0e"], "\x18" => [94, "\xc0i"], "\x19" => [76, "\xc0i"], "\x1a" => [104, "\xc0i"], "\x1b" => [16, "\xc0i"], "\x1c" => [94, "\xc0o"], "\x1d" => [76, "\xc0o"], "\x1e" => [104, "\xc0o"], "\x1f" => [16, "\xc0o"], " " => [94, "\xc0s"], "!" => [76, "\xc0s"], "\"" => [104, "\xc0s"], "#" => [16, "\xc0s"], "\$" => [94, "\xc0t"], "%" => [76, "\xc0t"], "&" => [104, "\xc0t"], "'" => [16, "\xc0t"], "(" => [77, "\xc0 "], ")" => [18, "\xc0 "], "*" => [77, "\xc0%"], "+" => [18, "\xc0%"], "," => [77, "\xc0-"], "-" => [18, "\xc0-"], "." => [77, "\xc0."], "/" => [18, "\xc0."], [77, "\xc0/"], [18, "\xc0/"], [77, "\xc03"], [18, "\xc03"], [77, "\xc04"], [18, "\xc04"], [77, "\xc05"], [18, "\xc05"], [77, "\xc06"], [18, "\xc06"], ":" => [77, "\xc07"], ";" => [18, "\xc07"], "<" => [77, "\xc08"], "=" => [18, "\xc08"], ">" => [77, "\xc09"], "?" => [18, "\xc09"], "@" => [77, "\xc0="], "A" => [18, "\xc0="], "B" => [77, "\xc0A"], "C" => [18, "\xc0A"], "D" => [77, "\xc0_"], "E" => [18, "\xc0_"], "F" => [77, "\xc0b"], "G" => [18, "\xc0b"], "H" => [77, "\xc0d"], "I" => [18, "\xc0d"], "J" => [77, "\xc0f"], "K" => [18, "\xc0f"], "L" => [77, "\xc0g"], "M" => [18, "\xc0g"], "N" => [77, "\xc0h"], "O" => [18, "\xc0h"], "P" => [77, "\xc0l"], "Q" => [18, "\xc0l"], "R" => [77, "\xc0m"], "S" => [18, "\xc0m"], "T" => [77, "\xc0n"], "U" => [18, "\xc0n"], "V" => [77, "\xc0p"], "W" => [18, "\xc0p"], "X" => [77, "\xc0r"], "Y" => [18, "\xc0r"], "Z" => [77, "\xc0u"], "[" => [18, "\xc0u"], "\\" => [0, "\xc0:"], "]" => [0, "\xc0B"], "^" => [0, "\xc0C"], "_" => [0, "\xc0D"], "`" => [0, "\xc0E"], "a" => [0, "\xc0F"], "b" => [0, "\xc0G"], "c" => [0, "\xc0H"], "d" => [0, "\xc0I"], "e" => [0, "\xc0J"], "f" => [0, "\xc0K"], "g" => [0, "\xc0L"], "h" => [0, "\xc0M"], "i" => [0, "\xc0N"], "j" => [0, "\xc0O"], "k" => [0, "\xc0P"], "l" => [0, "\xc0Q"], "m" => [0, "\xc0R"], "n" => [0, "\xc0S"], "o" => [0, "\xc0T"], "p" => [0, "\xc0U"], "q" => [0, "\xc0V"], "r" => [0, "\xc0W"], "s" => [0, "\xc0Y"], "t" => [0, "\xc0j"], "u" => [0, "\xc0k"], "v" => [0, "\xc0q"], "w" => [0, "\xc0v"], "x" => [0, "\xc0w"], "y" => [0, "\xc0x"], "z" => [0, "\xc0y"], "{" => [0, "\xc0z"], "|" => [82, "\xc0"], "}" => [87, "\xc0"], "~" => [130, "\xc0"], "" => [9, "\xc0"], "\x80" => [94, "\xc10"], "\x81" => [76, "\xc10"], "\x82" => [104, "\xc10"], "\x83" => [16, "\xc10"], "\x84" => [94, "\xc11"], "\x85" => [76, "\xc11"], "\x86" => [104, "\xc11"], "\x87" => [16, "\xc11"], "\x88" => [94, "\xc12"], "\x89" => [76, "\xc12"], "\x8a" => [104, "\xc12"], "\x8b" => [16, "\xc12"], "\x8c" => [94, "\xc1a"], "\x8d" => [76, "\xc1a"], "\x8e" => [104, "\xc1a"], "\x8f" => [16, "\xc1a"], "\x90" => [94, "\xc1c"], "\x91" => [76, "\xc1c"], "\x92" => [104, "\xc1c"], "\x93" => [16, "\xc1c"], "\x94" => [94, "\xc1e"], "\x95" => [76, "\xc1e"], "\x96" => [104, "\xc1e"], "\x97" => [16, "\xc1e"], "\x98" => [94, "\xc1i"], "\x99" => [76, "\xc1i"], "\x9a" => [104, "\xc1i"], "\x9b" => [16, "\xc1i"], "\x9c" => [94, "\xc1o"], "\x9d" => [76, "\xc1o"], "\x9e" => [104, "\xc1o"], "\x9f" => [16, "\xc1o"], "\xa0" => [94, "\xc1s"], "\xa1" => [76, "\xc1s"], "\xa2" => [104, "\xc1s"], "\xa3" => [16, "\xc1s"], "\xa4" => [94, "\xc1t"], "\xa5" => [76, "\xc1t"], "\xa6" => [104, "\xc1t"], "\xa7" => [16, "\xc1t"], "\xa8" => [77, "\xc1 "], "\xa9" => [18, "\xc1 "], "\xaa" => [77, "\xc1%"], "\xab" => [18, "\xc1%"], "\xac" => [77, "\xc1-"], "\xad" => [18, "\xc1-"], "\xae" => [77, "\xc1."], "\xaf" => [18, "\xc1."], "\xb0" => [77, "\xc1/"], "\xb1" => [18, "\xc1/"], "\xb2" => [77, "\xc13"], "\xb3" => [18, "\xc13"], "\xb4" => [77, "\xc14"], "\xb5" => [18, "\xc14"], "\xb6" => [77, "\xc15"], "\xb7" => [18, "\xc15"], "\xb8" => [77, "\xc16"], "\xb9" => [18, "\xc16"], "\xba" => [77, "\xc17"], "\xbb" => [18, "\xc17"], "\xbc" => [77, "\xc18"], "\xbd" => [18, "\xc18"], "\xbe" => [77, "\xc19"], "\xbf" => [18, "\xc19"], "\xc0" => [77, "\xc1="], "\xc1" => [18, "\xc1="], "\xc2" => [77, "\xc1A"], "\xc3" => [18, "\xc1A"], "\xc4" => [77, "\xc1_"], "\xc5" => [18, "\xc1_"], "\xc6" => [77, "\xc1b"], "\xc7" => [18, "\xc1b"], "\xc8" => [77, "\xc1d"], "\xc9" => [18, "\xc1d"], "\xca" => [77, "\xc1f"], "\xcb" => [18, "\xc1f"], "\xcc" => [77, "\xc1g"], "\xcd" => [18, "\xc1g"], "\xce" => [77, "\xc1h"], "\xcf" => [18, "\xc1h"], "\xd0" => [77, "\xc1l"], "\xd1" => [18, "\xc1l"], "\xd2" => [77, "\xc1m"], "\xd3" => [18, "\xc1m"], "\xd4" => [77, "\xc1n"], "\xd5" => [18, "\xc1n"], "\xd6" => [77, "\xc1p"], "\xd7" => [18, "\xc1p"], "\xd8" => [77, "\xc1r"], "\xd9" => [18, "\xc1r"], "\xda" => [77, "\xc1u"], "\xdb" => [18, "\xc1u"], "\xdc" => [0, "\xc1:"], "\xdd" => [0, "\xc1B"], "\xde" => [0, "\xc1C"], "\xdf" => [0, "\xc1D"], "\xe0" => [0, "\xc1E"], "\xe1" => [0, "\xc1F"], "\xe2" => [0, "\xc1G"], "\xe3" => [0, "\xc1H"], "\xe4" => [0, "\xc1I"], "\xe5" => [0, "\xc1J"], "\xe6" => [0, "\xc1K"], "\xe7" => [0, "\xc1L"], "\xe8" => [0, "\xc1M"], "\xe9" => [0, "\xc1N"], "\xea" => [0, "\xc1O"], "\xeb" => [0, "\xc1P"], "\xec" => [0, "\xc1Q"], "\xed" => [0, "\xc1R"], "\xee" => [0, "\xc1S"], "\xef" => [0, "\xc1T"], "\xf0" => [0, "\xc1U"], "\xf1" => [0, "\xc1V"], "\xf2" => [0, "\xc1W"], "\xf3" => [0, "\xc1Y"], "\xf4" => [0, "\xc1j"], "\xf5" => [0, "\xc1k"], "\xf6" => [0, "\xc1q"], "\xf7" => [0, "\xc1v"], "\xf8" => [0, "\xc1w"], "\xf9" => [0, "\xc1x"], "\xfa" => [0, "\xc1y"], "\xfb" => [0, "\xc1z"], "\xfc" => [82, "\xc1"], "\xfd" => [87, "\xc1"], "\xfe" => [130, "\xc1"], "\xff" => [9, "\xc1"]], ["\x00" => [94, "\xc50"], "\x01" => [76, "\xc50"], "\x02" => [104, "\xc50"], "\x03" => [16, "\xc50"], "\x04" => [94, "\xc51"], "\x05" => [76, "\xc51"], "\x06" => [104, "\xc51"], "\x07" => [16, "\xc51"], "\x08" => [94, "\xc52"], "\t" => [76, "\xc52"], "\n" => [104, "\xc52"], "\v" => [16, "\xc52"], "\f" => [94, "\xc5a"], "\r" => [76, "\xc5a"], "\x0e" => [104, "\xc5a"], "\x0f" => [16, "\xc5a"], "\x10" => [94, "\xc5c"], "\x11" => [76, "\xc5c"], "\x12" => [104, "\xc5c"], "\x13" => [16, "\xc5c"], "\x14" => [94, "\xc5e"], "\x15" => [76, "\xc5e"], "\x16" => [104, "\xc5e"], "\x17" => [16, "\xc5e"], "\x18" => [94, "\xc5i"], "\x19" => [76, "\xc5i"], "\x1a" => [104, "\xc5i"], "\x1b" => [16, "\xc5i"], "\x1c" => [94, "\xc5o"], "\x1d" => [76, "\xc5o"], "\x1e" => [104, "\xc5o"], "\x1f" => [16, "\xc5o"], " " => [94, "\xc5s"], "!" => [76, "\xc5s"], "\"" => [104, "\xc5s"], "#" => [16, "\xc5s"], "\$" => [94, "\xc5t"], "%" => [76, "\xc5t"], "&" => [104, "\xc5t"], "'" => [16, "\xc5t"], "(" => [77, "\xc5 "], ")" => [18, "\xc5 "], "*" => [77, "\xc5%"], "+" => [18, "\xc5%"], "," => [77, "\xc5-"], "-" => [18, "\xc5-"], "." => [77, "\xc5."], "/" => [18, "\xc5."], [77, "\xc5/"], [18, "\xc5/"], [77, "\xc53"], [18, "\xc53"], [77, "\xc54"], [18, "\xc54"], [77, "\xc55"], [18, "\xc55"], [77, "\xc56"], [18, "\xc56"], ":" => [77, "\xc57"], ";" => [18, "\xc57"], "<" => [77, "\xc58"], "=" => [18, "\xc58"], ">" => [77, "\xc59"], "?" => [18, "\xc59"], "@" => [77, "\xc5="], "A" => [18, "\xc5="], "B" => [77, "\xc5A"], "C" => [18, "\xc5A"], "D" => [77, "\xc5_"], "E" => [18, "\xc5_"], "F" => [77, "\xc5b"], "G" => [18, "\xc5b"], "H" => [77, "\xc5d"], "I" => [18, "\xc5d"], "J" => [77, "\xc5f"], "K" => [18, "\xc5f"], "L" => [77, "\xc5g"], "M" => [18, "\xc5g"], "N" => [77, "\xc5h"], "O" => [18, "\xc5h"], "P" => [77, "\xc5l"], "Q" => [18, "\xc5l"], "R" => [77, "\xc5m"], "S" => [18, "\xc5m"], "T" => [77, "\xc5n"], "U" => [18, "\xc5n"], "V" => [77, "\xc5p"], "W" => [18, "\xc5p"], "X" => [77, "\xc5r"], "Y" => [18, "\xc5r"], "Z" => [77, "\xc5u"], "[" => [18, "\xc5u"], "\\" => [0, "\xc5:"], "]" => [0, "\xc5B"], "^" => [0, "\xc5C"], "_" => [0, "\xc5D"], "`" => [0, "\xc5E"], "a" => [0, "\xc5F"], "b" => [0, "\xc5G"], "c" => [0, "\xc5H"], "d" => [0, "\xc5I"], "e" => [0, "\xc5J"], "f" => [0, "\xc5K"], "g" => [0, "\xc5L"], "h" => [0, "\xc5M"], "i" => [0, "\xc5N"], "j" => [0, "\xc5O"], "k" => [0, "\xc5P"], "l" => [0, "\xc5Q"], "m" => [0, "\xc5R"], "n" => [0, "\xc5S"], "o" => [0, "\xc5T"], "p" => [0, "\xc5U"], "q" => [0, "\xc5V"], "r" => [0, "\xc5W"], "s" => [0, "\xc5Y"], "t" => [0, "\xc5j"], "u" => [0, "\xc5k"], "v" => [0, "\xc5q"], "w" => [0, "\xc5v"], "x" => [0, "\xc5w"], "y" => [0, "\xc5x"], "z" => [0, "\xc5y"], "{" => [0, "\xc5z"], "|" => [82, "\xc5"], "}" => [87, "\xc5"], "~" => [130, "\xc5"], "" => [9, "\xc5"], "\x80" => [94, "\xe70"], "\x81" => [76, "\xe70"], "\x82" => [104, "\xe70"], "\x83" => [16, "\xe70"], "\x84" => [94, "\xe71"], "\x85" => [76, "\xe71"], "\x86" => [104, "\xe71"], "\x87" => [16, "\xe71"], "\x88" => [94, "\xe72"], "\x89" => [76, "\xe72"], "\x8a" => [104, "\xe72"], "\x8b" => [16, "\xe72"], "\x8c" => [94, "\xe7a"], "\x8d" => [76, "\xe7a"], "\x8e" => [104, "\xe7a"], "\x8f" => [16, "\xe7a"], "\x90" => [94, "\xe7c"], "\x91" => [76, "\xe7c"], "\x92" => [104, "\xe7c"], "\x93" => [16, "\xe7c"], "\x94" => [94, "\xe7e"], "\x95" => [76, "\xe7e"], "\x96" => [104, "\xe7e"], "\x97" => [16, "\xe7e"], "\x98" => [94, "\xe7i"], "\x99" => [76, "\xe7i"], "\x9a" => [104, "\xe7i"], "\x9b" => [16, "\xe7i"], "\x9c" => [94, "\xe7o"], "\x9d" => [76, "\xe7o"], "\x9e" => [104, "\xe7o"], "\x9f" => [16, "\xe7o"], "\xa0" => [94, "\xe7s"], "\xa1" => [76, "\xe7s"], "\xa2" => [104, "\xe7s"], "\xa3" => [16, "\xe7s"], "\xa4" => [94, "\xe7t"], "\xa5" => [76, "\xe7t"], "\xa6" => [104, "\xe7t"], "\xa7" => [16, "\xe7t"], "\xa8" => [77, "\xe7 "], "\xa9" => [18, "\xe7 "], "\xaa" => [77, "\xe7%"], "\xab" => [18, "\xe7%"], "\xac" => [77, "\xe7-"], "\xad" => [18, "\xe7-"], "\xae" => [77, "\xe7."], "\xaf" => [18, "\xe7."], "\xb0" => [77, "\xe7/"], "\xb1" => [18, "\xe7/"], "\xb2" => [77, "\xe73"], "\xb3" => [18, "\xe73"], "\xb4" => [77, "\xe74"], "\xb5" => [18, "\xe74"], "\xb6" => [77, "\xe75"], "\xb7" => [18, "\xe75"], "\xb8" => [77, "\xe76"], "\xb9" => [18, "\xe76"], "\xba" => [77, "\xe77"], "\xbb" => [18, "\xe77"], "\xbc" => [77, "\xe78"], "\xbd" => [18, "\xe78"], "\xbe" => [77, "\xe79"], "\xbf" => [18, "\xe79"], "\xc0" => [77, "\xe7="], "\xc1" => [18, "\xe7="], "\xc2" => [77, "\xe7A"], "\xc3" => [18, "\xe7A"], "\xc4" => [77, "\xe7_"], "\xc5" => [18, "\xe7_"], "\xc6" => [77, "\xe7b"], "\xc7" => [18, "\xe7b"], "\xc8" => [77, "\xe7d"], "\xc9" => [18, "\xe7d"], "\xca" => [77, "\xe7f"], "\xcb" => [18, "\xe7f"], "\xcc" => [77, "\xe7g"], "\xcd" => [18, "\xe7g"], "\xce" => [77, "\xe7h"], "\xcf" => [18, "\xe7h"], "\xd0" => [77, "\xe7l"], "\xd1" => [18, "\xe7l"], "\xd2" => [77, "\xe7m"], "\xd3" => [18, "\xe7m"], "\xd4" => [77, "\xe7n"], "\xd5" => [18, "\xe7n"], "\xd6" => [77, "\xe7p"], "\xd7" => [18, "\xe7p"], "\xd8" => [77, "\xe7r"], "\xd9" => [18, "\xe7r"], "\xda" => [77, "\xe7u"], "\xdb" => [18, "\xe7u"], "\xdc" => [0, "\xe7:"], "\xdd" => [0, "\xe7B"], "\xde" => [0, "\xe7C"], "\xdf" => [0, "\xe7D"], "\xe0" => [0, "\xe7E"], "\xe1" => [0, "\xe7F"], "\xe2" => [0, "\xe7G"], "\xe3" => [0, "\xe7H"], "\xe4" => [0, "\xe7I"], "\xe5" => [0, "\xe7J"], "\xe6" => [0, "\xe7K"], "\xe7" => [0, "\xe7L"], "\xe8" => [0, "\xe7M"], "\xe9" => [0, "\xe7N"], "\xea" => [0, "\xe7O"], "\xeb" => [0, "\xe7P"], "\xec" => [0, "\xe7Q"], "\xed" => [0, "\xe7R"], "\xee" => [0, "\xe7S"], "\xef" => [0, "\xe7T"], "\xf0" => [0, "\xe7U"], "\xf1" => [0, "\xe7V"], "\xf2" => [0, "\xe7W"], "\xf3" => [0, "\xe7Y"], "\xf4" => [0, "\xe7j"], "\xf5" => [0, "\xe7k"], "\xf6" => [0, "\xe7q"], "\xf7" => [0, "\xe7v"], "\xf8" => [0, "\xe7w"], "\xf9" => [0, "\xe7x"], "\xfa" => [0, "\xe7y"], "\xfb" => [0, "\xe7z"], "\xfc" => [82, "\xe7"], "\xfd" => [87, "\xe7"], "\xfe" => [130, "\xe7"], "\xff" => [9, "\xe7"]], ["\x00" => [94, "\xc60"], "\x01" => [76, "\xc60"], "\x02" => [104, "\xc60"], "\x03" => [16, "\xc60"], "\x04" => [94, "\xc61"], "\x05" => [76, "\xc61"], "\x06" => [104, "\xc61"], "\x07" => [16, "\xc61"], "\x08" => [94, "\xc62"], "\t" => [76, "\xc62"], "\n" => [104, "\xc62"], "\v" => [16, "\xc62"], "\f" => [94, "\xc6a"], "\r" => [76, "\xc6a"], "\x0e" => [104, "\xc6a"], "\x0f" => [16, "\xc6a"], "\x10" => [94, "\xc6c"], "\x11" => [76, "\xc6c"], "\x12" => [104, "\xc6c"], "\x13" => [16, "\xc6c"], "\x14" => [94, "\xc6e"], "\x15" => [76, "\xc6e"], "\x16" => [104, "\xc6e"], "\x17" => [16, "\xc6e"], "\x18" => [94, "\xc6i"], "\x19" => [76, "\xc6i"], "\x1a" => [104, "\xc6i"], "\x1b" => [16, "\xc6i"], "\x1c" => [94, "\xc6o"], "\x1d" => [76, "\xc6o"], "\x1e" => [104, "\xc6o"], "\x1f" => [16, "\xc6o"], " " => [94, "\xc6s"], "!" => [76, "\xc6s"], "\"" => [104, "\xc6s"], "#" => [16, "\xc6s"], "\$" => [94, "\xc6t"], "%" => [76, "\xc6t"], "&" => [104, "\xc6t"], "'" => [16, "\xc6t"], "(" => [77, "\xc6 "], ")" => [18, "\xc6 "], "*" => [77, "\xc6%"], "+" => [18, "\xc6%"], "," => [77, "\xc6-"], "-" => [18, "\xc6-"], "." => [77, "\xc6."], "/" => [18, "\xc6."], [77, "\xc6/"], [18, "\xc6/"], [77, "\xc63"], [18, "\xc63"], [77, "\xc64"], [18, "\xc64"], [77, "\xc65"], [18, "\xc65"], [77, "\xc66"], [18, "\xc66"], ":" => [77, "\xc67"], ";" => [18, "\xc67"], "<" => [77, "\xc68"], "=" => [18, "\xc68"], ">" => [77, "\xc69"], "?" => [18, "\xc69"], "@" => [77, "\xc6="], "A" => [18, "\xc6="], "B" => [77, "\xc6A"], "C" => [18, "\xc6A"], "D" => [77, "\xc6_"], "E" => [18, "\xc6_"], "F" => [77, "\xc6b"], "G" => [18, "\xc6b"], "H" => [77, "\xc6d"], "I" => [18, "\xc6d"], "J" => [77, "\xc6f"], "K" => [18, "\xc6f"], "L" => [77, "\xc6g"], "M" => [18, "\xc6g"], "N" => [77, "\xc6h"], "O" => [18, "\xc6h"], "P" => [77, "\xc6l"], "Q" => [18, "\xc6l"], "R" => [77, "\xc6m"], "S" => [18, "\xc6m"], "T" => [77, "\xc6n"], "U" => [18, "\xc6n"], "V" => [77, "\xc6p"], "W" => [18, "\xc6p"], "X" => [77, "\xc6r"], "Y" => [18, "\xc6r"], "Z" => [77, "\xc6u"], "[" => [18, "\xc6u"], "\\" => [0, "\xc6:"], "]" => [0, "\xc6B"], "^" => [0, "\xc6C"], "_" => [0, "\xc6D"], "`" => [0, "\xc6E"], "a" => [0, "\xc6F"], "b" => [0, "\xc6G"], "c" => [0, "\xc6H"], "d" => [0, "\xc6I"], "e" => [0, "\xc6J"], "f" => [0, "\xc6K"], "g" => [0, "\xc6L"], "h" => [0, "\xc6M"], "i" => [0, "\xc6N"], "j" => [0, "\xc6O"], "k" => [0, "\xc6P"], "l" => [0, "\xc6Q"], "m" => [0, "\xc6R"], "n" => [0, "\xc6S"], "o" => [0, "\xc6T"], "p" => [0, "\xc6U"], "q" => [0, "\xc6V"], "r" => [0, "\xc6W"], "s" => [0, "\xc6Y"], "t" => [0, "\xc6j"], "u" => [0, "\xc6k"], "v" => [0, "\xc6q"], "w" => [0, "\xc6v"], "x" => [0, "\xc6w"], "y" => [0, "\xc6x"], "z" => [0, "\xc6y"], "{" => [0, "\xc6z"], "|" => [82, "\xc6"], "}" => [87, "\xc6"], "~" => [130, "\xc6"], "" => [9, "\xc6"], "\x80" => [94, "\xe40"], "\x81" => [76, "\xe40"], "\x82" => [104, "\xe40"], "\x83" => [16, "\xe40"], "\x84" => [94, "\xe41"], "\x85" => [76, "\xe41"], "\x86" => [104, "\xe41"], "\x87" => [16, "\xe41"], "\x88" => [94, "\xe42"], "\x89" => [76, "\xe42"], "\x8a" => [104, "\xe42"], "\x8b" => [16, "\xe42"], "\x8c" => [94, "\xe4a"], "\x8d" => [76, "\xe4a"], "\x8e" => [104, "\xe4a"], "\x8f" => [16, "\xe4a"], "\x90" => [94, "\xe4c"], "\x91" => [76, "\xe4c"], "\x92" => [104, "\xe4c"], "\x93" => [16, "\xe4c"], "\x94" => [94, "\xe4e"], "\x95" => [76, "\xe4e"], "\x96" => [104, "\xe4e"], "\x97" => [16, "\xe4e"], "\x98" => [94, "\xe4i"], "\x99" => [76, "\xe4i"], "\x9a" => [104, "\xe4i"], "\x9b" => [16, "\xe4i"], "\x9c" => [94, "\xe4o"], "\x9d" => [76, "\xe4o"], "\x9e" => [104, "\xe4o"], "\x9f" => [16, "\xe4o"], "\xa0" => [94, "\xe4s"], "\xa1" => [76, "\xe4s"], "\xa2" => [104, "\xe4s"], "\xa3" => [16, "\xe4s"], "\xa4" => [94, "\xe4t"], "\xa5" => [76, "\xe4t"], "\xa6" => [104, "\xe4t"], "\xa7" => [16, "\xe4t"], "\xa8" => [77, "\xe4 "], "\xa9" => [18, "\xe4 "], "\xaa" => [77, "\xe4%"], "\xab" => [18, "\xe4%"], "\xac" => [77, "\xe4-"], "\xad" => [18, "\xe4-"], "\xae" => [77, "\xe4."], "\xaf" => [18, "\xe4."], "\xb0" => [77, "\xe4/"], "\xb1" => [18, "\xe4/"], "\xb2" => [77, "\xe43"], "\xb3" => [18, "\xe43"], "\xb4" => [77, "\xe44"], "\xb5" => [18, "\xe44"], "\xb6" => [77, "\xe45"], "\xb7" => [18, "\xe45"], "\xb8" => [77, "\xe46"], "\xb9" => [18, "\xe46"], "\xba" => [77, "\xe47"], "\xbb" => [18, "\xe47"], "\xbc" => [77, "\xe48"], "\xbd" => [18, "\xe48"], "\xbe" => [77, "\xe49"], "\xbf" => [18, "\xe49"], "\xc0" => [77, "\xe4="], "\xc1" => [18, "\xe4="], "\xc2" => [77, "\xe4A"], "\xc3" => [18, "\xe4A"], "\xc4" => [77, "\xe4_"], "\xc5" => [18, "\xe4_"], "\xc6" => [77, "\xe4b"], "\xc7" => [18, "\xe4b"], "\xc8" => [77, "\xe4d"], "\xc9" => [18, "\xe4d"], "\xca" => [77, "\xe4f"], "\xcb" => [18, "\xe4f"], "\xcc" => [77, "\xe4g"], "\xcd" => [18, "\xe4g"], "\xce" => [77, "\xe4h"], "\xcf" => [18, "\xe4h"], "\xd0" => [77, "\xe4l"], "\xd1" => [18, "\xe4l"], "\xd2" => [77, "\xe4m"], "\xd3" => [18, "\xe4m"], "\xd4" => [77, "\xe4n"], "\xd5" => [18, "\xe4n"], "\xd6" => [77, "\xe4p"], "\xd7" => [18, "\xe4p"], "\xd8" => [77, "\xe4r"], "\xd9" => [18, "\xe4r"], "\xda" => [77, "\xe4u"], "\xdb" => [18, "\xe4u"], "\xdc" => [0, "\xe4:"], "\xdd" => [0, "\xe4B"], "\xde" => [0, "\xe4C"], "\xdf" => [0, "\xe4D"], "\xe0" => [0, "\xe4E"], "\xe1" => [0, "\xe4F"], "\xe2" => [0, "\xe4G"], "\xe3" => [0, "\xe4H"], "\xe4" => [0, "\xe4I"], "\xe5" => [0, "\xe4J"], "\xe6" => [0, "\xe4K"], "\xe7" => [0, "\xe4L"], "\xe8" => [0, "\xe4M"], "\xe9" => [0, "\xe4N"], "\xea" => [0, "\xe4O"], "\xeb" => [0, "\xe4P"], "\xec" => [0, "\xe4Q"], "\xed" => [0, "\xe4R"], "\xee" => [0, "\xe4S"], "\xef" => [0, "\xe4T"], "\xf0" => [0, "\xe4U"], "\xf1" => [0, "\xe4V"], "\xf2" => [0, "\xe4W"], "\xf3" => [0, "\xe4Y"], "\xf4" => [0, "\xe4j"], "\xf5" => [0, "\xe4k"], "\xf6" => [0, "\xe4q"], "\xf7" => [0, "\xe4v"], "\xf8" => [0, "\xe4w"], "\xf9" => [0, "\xe4x"], "\xfa" => [0, "\xe4y"], "\xfb" => [0, "\xe4z"], "\xfc" => [82, "\xe4"], "\xfd" => [87, "\xe4"], "\xfe" => [130, "\xe4"], "\xff" => [9, "\xe4"]], ["\x00" => [77, "\xc60"], "\x01" => [18, "\xc60"], "\x02" => [77, "\xc61"], "\x03" => [18, "\xc61"], "\x04" => [77, "\xc62"], "\x05" => [18, "\xc62"], "\x06" => [77, "\xc6a"], "\x07" => [18, "\xc6a"], "\x08" => [77, "\xc6c"], "\t" => [18, "\xc6c"], "\n" => [77, "\xc6e"], "\v" => [18, "\xc6e"], "\f" => [77, "\xc6i"], "\r" => [18, "\xc6i"], "\x0e" => [77, "\xc6o"], "\x0f" => [18, "\xc6o"], "\x10" => [77, "\xc6s"], "\x11" => [18, "\xc6s"], "\x12" => [77, "\xc6t"], "\x13" => [18, "\xc6t"], "\x14" => [0, "\xc6 "], "\x15" => [0, "\xc6%"], "\x16" => [0, "\xc6-"], "\x17" => [0, "\xc6."], "\x18" => [0, "\xc6/"], "\x19" => [0, "\xc63"], "\x1a" => [0, "\xc64"], "\x1b" => [0, "\xc65"], "\x1c" => [0, "\xc66"], "\x1d" => [0, "\xc67"], "\x1e" => [0, "\xc68"], "\x1f" => [0, "\xc69"], " " => [0, "\xc6="], "!" => [0, "\xc6A"], "\"" => [0, "\xc6_"], "#" => [0, "\xc6b"], "\$" => [0, "\xc6d"], "%" => [0, "\xc6f"], "&" => [0, "\xc6g"], "'" => [0, "\xc6h"], "(" => [0, "\xc6l"], ")" => [0, "\xc6m"], "*" => [0, "\xc6n"], "+" => [0, "\xc6p"], "," => [0, "\xc6r"], "-" => [0, "\xc6u"], "." => [100, "\xc6"], "/" => [110, "\xc6"], [111, "\xc6"], [115, "\xc6"], [116, "\xc6"], [118, "\xc6"], [119, "\xc6"], [122, "\xc6"], [123, "\xc6"], [125, "\xc6"], [126, "\xc6"], [129, "\xc6"], ":" => [143, "\xc6"], ";" => [148, "\xc6"], "<" => [151, "\xc6"], "=" => [153, "\xc6"], ">" => [83, "\xc6"], "?" => [10, "\xc6"], "@" => [77, "\xe40"], "A" => [18, "\xe40"], "B" => [77, "\xe41"], "C" => [18, "\xe41"], "D" => [77, "\xe42"], "E" => [18, "\xe42"], "F" => [77, "\xe4a"], "G" => [18, "\xe4a"], "H" => [77, "\xe4c"], "I" => [18, "\xe4c"], "J" => [77, "\xe4e"], "K" => [18, "\xe4e"], "L" => [77, "\xe4i"], "M" => [18, "\xe4i"], "N" => [77, "\xe4o"], "O" => [18, "\xe4o"], "P" => [77, "\xe4s"], "Q" => [18, "\xe4s"], "R" => [77, "\xe4t"], "S" => [18, "\xe4t"], "T" => [0, "\xe4 "], "U" => [0, "\xe4%"], "V" => [0, "\xe4-"], "W" => [0, "\xe4."], "X" => [0, "\xe4/"], "Y" => [0, "\xe43"], "Z" => [0, "\xe44"], "[" => [0, "\xe45"], "\\" => [0, "\xe46"], "]" => [0, "\xe47"], "^" => [0, "\xe48"], "_" => [0, "\xe49"], "`" => [0, "\xe4="], "a" => [0, "\xe4A"], "b" => [0, "\xe4_"], "c" => [0, "\xe4b"], "d" => [0, "\xe4d"], "e" => [0, "\xe4f"], "f" => [0, "\xe4g"], "g" => [0, "\xe4h"], "h" => [0, "\xe4l"], "i" => [0, "\xe4m"], "j" => [0, "\xe4n"], "k" => [0, "\xe4p"], "l" => [0, "\xe4r"], "m" => [0, "\xe4u"], "n" => [100, "\xe4"], "o" => [110, "\xe4"], "p" => [111, "\xe4"], "q" => [115, "\xe4"], "r" => [116, "\xe4"], "s" => [118, "\xe4"], "t" => [119, "\xe4"], "u" => [122, "\xe4"], "v" => [123, "\xe4"], "w" => [125, "\xe4"], "x" => [126, "\xe4"], "y" => [129, "\xe4"], "z" => [143, "\xe4"], "{" => [148, "\xe4"], "|" => [151, "\xe4"], "}" => [153, "\xe4"], "~" => [83, "\xe4"], "" => [10, "\xe4"], "\x80" => [77, "\xe80"], "\x81" => [18, "\xe80"], "\x82" => [77, "\xe81"], "\x83" => [18, "\xe81"], "\x84" => [77, "\xe82"], "\x85" => [18, "\xe82"], "\x86" => [77, "\xe8a"], "\x87" => [18, "\xe8a"], "\x88" => [77, "\xe8c"], "\x89" => [18, "\xe8c"], "\x8a" => [77, "\xe8e"], "\x8b" => [18, "\xe8e"], "\x8c" => [77, "\xe8i"], "\x8d" => [18, "\xe8i"], "\x8e" => [77, "\xe8o"], "\x8f" => [18, "\xe8o"], "\x90" => [77, "\xe8s"], "\x91" => [18, "\xe8s"], "\x92" => [77, "\xe8t"], "\x93" => [18, "\xe8t"], "\x94" => [0, "\xe8 "], "\x95" => [0, "\xe8%"], "\x96" => [0, "\xe8-"], "\x97" => [0, "\xe8."], "\x98" => [0, "\xe8/"], "\x99" => [0, "\xe83"], "\x9a" => [0, "\xe84"], "\x9b" => [0, "\xe85"], "\x9c" => [0, "\xe86"], "\x9d" => [0, "\xe87"], "\x9e" => [0, "\xe88"], "\x9f" => [0, "\xe89"], "\xa0" => [0, "\xe8="], "\xa1" => [0, "\xe8A"], "\xa2" => [0, "\xe8_"], "\xa3" => [0, "\xe8b"], "\xa4" => [0, "\xe8d"], "\xa5" => [0, "\xe8f"], "\xa6" => [0, "\xe8g"], "\xa7" => [0, "\xe8h"], "\xa8" => [0, "\xe8l"], "\xa9" => [0, "\xe8m"], "\xaa" => [0, "\xe8n"], "\xab" => [0, "\xe8p"], "\xac" => [0, "\xe8r"], "\xad" => [0, "\xe8u"], "\xae" => [100, "\xe8"], "\xaf" => [110, "\xe8"], "\xb0" => [111, "\xe8"], "\xb1" => [115, "\xe8"], "\xb2" => [116, "\xe8"], "\xb3" => [118, "\xe8"], "\xb4" => [119, "\xe8"], "\xb5" => [122, "\xe8"], "\xb6" => [123, "\xe8"], "\xb7" => [125, "\xe8"], "\xb8" => [126, "\xe8"], "\xb9" => [129, "\xe8"], "\xba" => [143, "\xe8"], "\xbb" => [148, "\xe8"], "\xbc" => [151, "\xe8"], "\xbd" => [153, "\xe8"], "\xbe" => [83, "\xe8"], "\xbf" => [10, "\xe8"], "\xc0" => [77, "\xe90"], "\xc1" => [18, "\xe90"], "\xc2" => [77, "\xe91"], "\xc3" => [18, "\xe91"], "\xc4" => [77, "\xe92"], "\xc5" => [18, "\xe92"], "\xc6" => [77, "\xe9a"], "\xc7" => [18, "\xe9a"], "\xc8" => [77, "\xe9c"], "\xc9" => [18, "\xe9c"], "\xca" => [77, "\xe9e"], "\xcb" => [18, "\xe9e"], "\xcc" => [77, "\xe9i"], "\xcd" => [18, "\xe9i"], "\xce" => [77, "\xe9o"], "\xcf" => [18, "\xe9o"], "\xd0" => [77, "\xe9s"], "\xd1" => [18, "\xe9s"], "\xd2" => [77, "\xe9t"], "\xd3" => [18, "\xe9t"], "\xd4" => [0, "\xe9 "], "\xd5" => [0, "\xe9%"], "\xd6" => [0, "\xe9-"], "\xd7" => [0, "\xe9."], "\xd8" => [0, "\xe9/"], "\xd9" => [0, "\xe93"], "\xda" => [0, "\xe94"], "\xdb" => [0, "\xe95"], "\xdc" => [0, "\xe96"], "\xdd" => [0, "\xe97"], "\xde" => [0, "\xe98"], "\xdf" => [0, "\xe99"], "\xe0" => [0, "\xe9="], "\xe1" => [0, "\xe9A"], "\xe2" => [0, "\xe9_"], "\xe3" => [0, "\xe9b"], "\xe4" => [0, "\xe9d"], "\xe5" => [0, "\xe9f"], "\xe6" => [0, "\xe9g"], "\xe7" => [0, "\xe9h"], "\xe8" => [0, "\xe9l"], "\xe9" => [0, "\xe9m"], "\xea" => [0, "\xe9n"], "\xeb" => [0, "\xe9p"], "\xec" => [0, "\xe9r"], "\xed" => [0, "\xe9u"], "\xee" => [100, "\xe9"], "\xef" => [110, "\xe9"], "\xf0" => [111, "\xe9"], "\xf1" => [115, "\xe9"], "\xf2" => [116, "\xe9"], "\xf3" => [118, "\xe9"], "\xf4" => [119, "\xe9"], "\xf5" => [122, "\xe9"], "\xf6" => [123, "\xe9"], "\xf7" => [125, "\xe9"], "\xf8" => [126, "\xe9"], "\xf9" => [129, "\xe9"], "\xfa" => [143, "\xe9"], "\xfb" => [148, "\xe9"], "\xfc" => [151, "\xe9"], "\xfd" => [153, "\xe9"], "\xfe" => [83, "\xe9"], "\xff" => [10, "\xe9"]], ["\x00" => [94, "\xc70"], "\x01" => [76, "\xc70"], "\x02" => [104, "\xc70"], "\x03" => [16, "\xc70"], "\x04" => [94, "\xc71"], "\x05" => [76, "\xc71"], "\x06" => [104, "\xc71"], "\x07" => [16, "\xc71"], "\x08" => [94, "\xc72"], "\t" => [76, "\xc72"], "\n" => [104, "\xc72"], "\v" => [16, "\xc72"], "\f" => [94, "\xc7a"], "\r" => [76, "\xc7a"], "\x0e" => [104, "\xc7a"], "\x0f" => [16, "\xc7a"], "\x10" => [94, "\xc7c"], "\x11" => [76, "\xc7c"], "\x12" => [104, "\xc7c"], "\x13" => [16, "\xc7c"], "\x14" => [94, "\xc7e"], "\x15" => [76, "\xc7e"], "\x16" => [104, "\xc7e"], "\x17" => [16, "\xc7e"], "\x18" => [94, "\xc7i"], "\x19" => [76, "\xc7i"], "\x1a" => [104, "\xc7i"], "\x1b" => [16, "\xc7i"], "\x1c" => [94, "\xc7o"], "\x1d" => [76, "\xc7o"], "\x1e" => [104, "\xc7o"], "\x1f" => [16, "\xc7o"], " " => [94, "\xc7s"], "!" => [76, "\xc7s"], "\"" => [104, "\xc7s"], "#" => [16, "\xc7s"], "\$" => [94, "\xc7t"], "%" => [76, "\xc7t"], "&" => [104, "\xc7t"], "'" => [16, "\xc7t"], "(" => [77, "\xc7 "], ")" => [18, "\xc7 "], "*" => [77, "\xc7%"], "+" => [18, "\xc7%"], "," => [77, "\xc7-"], "-" => [18, "\xc7-"], "." => [77, "\xc7."], "/" => [18, "\xc7."], [77, "\xc7/"], [18, "\xc7/"], [77, "\xc73"], [18, "\xc73"], [77, "\xc74"], [18, "\xc74"], [77, "\xc75"], [18, "\xc75"], [77, "\xc76"], [18, "\xc76"], ":" => [77, "\xc77"], ";" => [18, "\xc77"], "<" => [77, "\xc78"], "=" => [18, "\xc78"], ">" => [77, "\xc79"], "?" => [18, "\xc79"], "@" => [77, "\xc7="], "A" => [18, "\xc7="], "B" => [77, "\xc7A"], "C" => [18, "\xc7A"], "D" => [77, "\xc7_"], "E" => [18, "\xc7_"], "F" => [77, "\xc7b"], "G" => [18, "\xc7b"], "H" => [77, "\xc7d"], "I" => [18, "\xc7d"], "J" => [77, "\xc7f"], "K" => [18, "\xc7f"], "L" => [77, "\xc7g"], "M" => [18, "\xc7g"], "N" => [77, "\xc7h"], "O" => [18, "\xc7h"], "P" => [77, "\xc7l"], "Q" => [18, "\xc7l"], "R" => [77, "\xc7m"], "S" => [18, "\xc7m"], "T" => [77, "\xc7n"], "U" => [18, "\xc7n"], "V" => [77, "\xc7p"], "W" => [18, "\xc7p"], "X" => [77, "\xc7r"], "Y" => [18, "\xc7r"], "Z" => [77, "\xc7u"], "[" => [18, "\xc7u"], "\\" => [0, "\xc7:"], "]" => [0, "\xc7B"], "^" => [0, "\xc7C"], "_" => [0, "\xc7D"], "`" => [0, "\xc7E"], "a" => [0, "\xc7F"], "b" => [0, "\xc7G"], "c" => [0, "\xc7H"], "d" => [0, "\xc7I"], "e" => [0, "\xc7J"], "f" => [0, "\xc7K"], "g" => [0, "\xc7L"], "h" => [0, "\xc7M"], "i" => [0, "\xc7N"], "j" => [0, "\xc7O"], "k" => [0, "\xc7P"], "l" => [0, "\xc7Q"], "m" => [0, "\xc7R"], "n" => [0, "\xc7S"], "o" => [0, "\xc7T"], "p" => [0, "\xc7U"], "q" => [0, "\xc7V"], "r" => [0, "\xc7W"], "s" => [0, "\xc7Y"], "t" => [0, "\xc7j"], "u" => [0, "\xc7k"], "v" => [0, "\xc7q"], "w" => [0, "\xc7v"], "x" => [0, "\xc7w"], "y" => [0, "\xc7x"], "z" => [0, "\xc7y"], "{" => [0, "\xc7z"], "|" => [82, "\xc7"], "}" => [87, "\xc7"], "~" => [130, "\xc7"], "" => [9, "\xc7"], "\x80" => [94, "\xcf0"], "\x81" => [76, "\xcf0"], "\x82" => [104, "\xcf0"], "\x83" => [16, "\xcf0"], "\x84" => [94, "\xcf1"], "\x85" => [76, "\xcf1"], "\x86" => [104, "\xcf1"], "\x87" => [16, "\xcf1"], "\x88" => [94, "\xcf2"], "\x89" => [76, "\xcf2"], "\x8a" => [104, "\xcf2"], "\x8b" => [16, "\xcf2"], "\x8c" => [94, "\xcfa"], "\x8d" => [76, "\xcfa"], "\x8e" => [104, "\xcfa"], "\x8f" => [16, "\xcfa"], "\x90" => [94, "\xcfc"], "\x91" => [76, "\xcfc"], "\x92" => [104, "\xcfc"], "\x93" => [16, "\xcfc"], "\x94" => [94, "\xcfe"], "\x95" => [76, "\xcfe"], "\x96" => [104, "\xcfe"], "\x97" => [16, "\xcfe"], "\x98" => [94, "\xcfi"], "\x99" => [76, "\xcfi"], "\x9a" => [104, "\xcfi"], "\x9b" => [16, "\xcfi"], "\x9c" => [94, "\xcfo"], "\x9d" => [76, "\xcfo"], "\x9e" => [104, "\xcfo"], "\x9f" => [16, "\xcfo"], "\xa0" => [94, "\xcfs"], "\xa1" => [76, "\xcfs"], "\xa2" => [104, "\xcfs"], "\xa3" => [16, "\xcfs"], "\xa4" => [94, "\xcft"], "\xa5" => [76, "\xcft"], "\xa6" => [104, "\xcft"], "\xa7" => [16, "\xcft"], "\xa8" => [77, "\xcf "], "\xa9" => [18, "\xcf "], "\xaa" => [77, "\xcf%"], "\xab" => [18, "\xcf%"], "\xac" => [77, "\xcf-"], "\xad" => [18, "\xcf-"], "\xae" => [77, "\xcf."], "\xaf" => [18, "\xcf."], "\xb0" => [77, "\xcf/"], "\xb1" => [18, "\xcf/"], "\xb2" => [77, "\xcf3"], "\xb3" => [18, "\xcf3"], "\xb4" => [77, "\xcf4"], "\xb5" => [18, "\xcf4"], "\xb6" => [77, "\xcf5"], "\xb7" => [18, "\xcf5"], "\xb8" => [77, "\xcf6"], "\xb9" => [18, "\xcf6"], "\xba" => [77, "\xcf7"], "\xbb" => [18, "\xcf7"], "\xbc" => [77, "\xcf8"], "\xbd" => [18, "\xcf8"], "\xbe" => [77, "\xcf9"], "\xbf" => [18, "\xcf9"], "\xc0" => [77, "\xcf="], "\xc1" => [18, "\xcf="], "\xc2" => [77, "\xcfA"], "\xc3" => [18, "\xcfA"], "\xc4" => [77, "\xcf_"], "\xc5" => [18, "\xcf_"], "\xc6" => [77, "\xcfb"], "\xc7" => [18, "\xcfb"], "\xc8" => [77, "\xcfd"], "\xc9" => [18, "\xcfd"], "\xca" => [77, "\xcff"], "\xcb" => [18, "\xcff"], "\xcc" => [77, "\xcfg"], "\xcd" => [18, "\xcfg"], "\xce" => [77, "\xcfh"], "\xcf" => [18, "\xcfh"], "\xd0" => [77, "\xcfl"], "\xd1" => [18, "\xcfl"], "\xd2" => [77, "\xcfm"], "\xd3" => [18, "\xcfm"], "\xd4" => [77, "\xcfn"], "\xd5" => [18, "\xcfn"], "\xd6" => [77, "\xcfp"], "\xd7" => [18, "\xcfp"], "\xd8" => [77, "\xcfr"], "\xd9" => [18, "\xcfr"], "\xda" => [77, "\xcfu"], "\xdb" => [18, "\xcfu"], "\xdc" => [0, "\xcf:"], "\xdd" => [0, "\xcfB"], "\xde" => [0, "\xcfC"], "\xdf" => [0, "\xcfD"], "\xe0" => [0, "\xcfE"], "\xe1" => [0, "\xcfF"], "\xe2" => [0, "\xcfG"], "\xe3" => [0, "\xcfH"], "\xe4" => [0, "\xcfI"], "\xe5" => [0, "\xcfJ"], "\xe6" => [0, "\xcfK"], "\xe7" => [0, "\xcfL"], "\xe8" => [0, "\xcfM"], "\xe9" => [0, "\xcfN"], "\xea" => [0, "\xcfO"], "\xeb" => [0, "\xcfP"], "\xec" => [0, "\xcfQ"], "\xed" => [0, "\xcfR"], "\xee" => [0, "\xcfS"], "\xef" => [0, "\xcfT"], "\xf0" => [0, "\xcfU"], "\xf1" => [0, "\xcfV"], "\xf2" => [0, "\xcfW"], "\xf3" => [0, "\xcfY"], "\xf4" => [0, "\xcfj"], "\xf5" => [0, "\xcfk"], "\xf6" => [0, "\xcfq"], "\xf7" => [0, "\xcfv"], "\xf8" => [0, "\xcfw"], "\xf9" => [0, "\xcfx"], "\xfa" => [0, "\xcfy"], "\xfb" => [0, "\xcfz"], "\xfc" => [82, "\xcf"], "\xfd" => [87, "\xcf"], "\xfe" => [130, "\xcf"], "\xff" => [9, "\xcf"]], ["\x00" => [77, "\xc70"], "\x01" => [18, "\xc70"], "\x02" => [77, "\xc71"], "\x03" => [18, "\xc71"], "\x04" => [77, "\xc72"], "\x05" => [18, "\xc72"], "\x06" => [77, "\xc7a"], "\x07" => [18, "\xc7a"], "\x08" => [77, "\xc7c"], "\t" => [18, "\xc7c"], "\n" => [77, "\xc7e"], "\v" => [18, "\xc7e"], "\f" => [77, "\xc7i"], "\r" => [18, "\xc7i"], "\x0e" => [77, "\xc7o"], "\x0f" => [18, "\xc7o"], "\x10" => [77, "\xc7s"], "\x11" => [18, "\xc7s"], "\x12" => [77, "\xc7t"], "\x13" => [18, "\xc7t"], "\x14" => [0, "\xc7 "], "\x15" => [0, "\xc7%"], "\x16" => [0, "\xc7-"], "\x17" => [0, "\xc7."], "\x18" => [0, "\xc7/"], "\x19" => [0, "\xc73"], "\x1a" => [0, "\xc74"], "\x1b" => [0, "\xc75"], "\x1c" => [0, "\xc76"], "\x1d" => [0, "\xc77"], "\x1e" => [0, "\xc78"], "\x1f" => [0, "\xc79"], " " => [0, "\xc7="], "!" => [0, "\xc7A"], "\"" => [0, "\xc7_"], "#" => [0, "\xc7b"], "\$" => [0, "\xc7d"], "%" => [0, "\xc7f"], "&" => [0, "\xc7g"], "'" => [0, "\xc7h"], "(" => [0, "\xc7l"], ")" => [0, "\xc7m"], "*" => [0, "\xc7n"], "+" => [0, "\xc7p"], "," => [0, "\xc7r"], "-" => [0, "\xc7u"], "." => [100, "\xc7"], "/" => [110, "\xc7"], [111, "\xc7"], [115, "\xc7"], [116, "\xc7"], [118, "\xc7"], [119, "\xc7"], [122, "\xc7"], [123, "\xc7"], [125, "\xc7"], [126, "\xc7"], [129, "\xc7"], ":" => [143, "\xc7"], ";" => [148, "\xc7"], "<" => [151, "\xc7"], "=" => [153, "\xc7"], ">" => [83, "\xc7"], "?" => [10, "\xc7"], "@" => [77, "\xcf0"], "A" => [18, "\xcf0"], "B" => [77, "\xcf1"], "C" => [18, "\xcf1"], "D" => [77, "\xcf2"], "E" => [18, "\xcf2"], "F" => [77, "\xcfa"], "G" => [18, "\xcfa"], "H" => [77, "\xcfc"], "I" => [18, "\xcfc"], "J" => [77, "\xcfe"], "K" => [18, "\xcfe"], "L" => [77, "\xcfi"], "M" => [18, "\xcfi"], "N" => [77, "\xcfo"], "O" => [18, "\xcfo"], "P" => [77, "\xcfs"], "Q" => [18, "\xcfs"], "R" => [77, "\xcft"], "S" => [18, "\xcft"], "T" => [0, "\xcf "], "U" => [0, "\xcf%"], "V" => [0, "\xcf-"], "W" => [0, "\xcf."], "X" => [0, "\xcf/"], "Y" => [0, "\xcf3"], "Z" => [0, "\xcf4"], "[" => [0, "\xcf5"], "\\" => [0, "\xcf6"], "]" => [0, "\xcf7"], "^" => [0, "\xcf8"], "_" => [0, "\xcf9"], "`" => [0, "\xcf="], "a" => [0, "\xcfA"], "b" => [0, "\xcf_"], "c" => [0, "\xcfb"], "d" => [0, "\xcfd"], "e" => [0, "\xcff"], "f" => [0, "\xcfg"], "g" => [0, "\xcfh"], "h" => [0, "\xcfl"], "i" => [0, "\xcfm"], "j" => [0, "\xcfn"], "k" => [0, "\xcfp"], "l" => [0, "\xcfr"], "m" => [0, "\xcfu"], "n" => [100, "\xcf"], "o" => [110, "\xcf"], "p" => [111, "\xcf"], "q" => [115, "\xcf"], "r" => [116, "\xcf"], "s" => [118, "\xcf"], "t" => [119, "\xcf"], "u" => [122, "\xcf"], "v" => [123, "\xcf"], "w" => [125, "\xcf"], "x" => [126, "\xcf"], "y" => [129, "\xcf"], "z" => [143, "\xcf"], "{" => [148, "\xcf"], "|" => [151, "\xcf"], "}" => [153, "\xcf"], "~" => [83, "\xcf"], "" => [10, "\xcf"], "\x80" => [77, "\xea0"], "\x81" => [18, "\xea0"], "\x82" => [77, "\xea1"], "\x83" => [18, "\xea1"], "\x84" => [77, "\xea2"], "\x85" => [18, "\xea2"], "\x86" => [77, "\xeaa"], "\x87" => [18, "\xeaa"], "\x88" => [77, "\xeac"], "\x89" => [18, "\xeac"], "\x8a" => [77, "\xeae"], "\x8b" => [18, "\xeae"], "\x8c" => [77, "\xeai"], "\x8d" => [18, "\xeai"], "\x8e" => [77, "\xeao"], "\x8f" => [18, "\xeao"], "\x90" => [77, "\xeas"], "\x91" => [18, "\xeas"], "\x92" => [77, "\xeat"], "\x93" => [18, "\xeat"], "\x94" => [0, "\xea "], "\x95" => [0, "\xea%"], "\x96" => [0, "\xea-"], "\x97" => [0, "\xea."], "\x98" => [0, "\xea/"], "\x99" => [0, "\xea3"], "\x9a" => [0, "\xea4"], "\x9b" => [0, "\xea5"], "\x9c" => [0, "\xea6"], "\x9d" => [0, "\xea7"], "\x9e" => [0, "\xea8"], "\x9f" => [0, "\xea9"], "\xa0" => [0, "\xea="], "\xa1" => [0, "\xeaA"], "\xa2" => [0, "\xea_"], "\xa3" => [0, "\xeab"], "\xa4" => [0, "\xead"], "\xa5" => [0, "\xeaf"], "\xa6" => [0, "\xeag"], "\xa7" => [0, "\xeah"], "\xa8" => [0, "\xeal"], "\xa9" => [0, "\xeam"], "\xaa" => [0, "\xean"], "\xab" => [0, "\xeap"], "\xac" => [0, "\xear"], "\xad" => [0, "\xeau"], "\xae" => [100, "\xea"], "\xaf" => [110, "\xea"], "\xb0" => [111, "\xea"], "\xb1" => [115, "\xea"], "\xb2" => [116, "\xea"], "\xb3" => [118, "\xea"], "\xb4" => [119, "\xea"], "\xb5" => [122, "\xea"], "\xb6" => [123, "\xea"], "\xb7" => [125, "\xea"], "\xb8" => [126, "\xea"], "\xb9" => [129, "\xea"], "\xba" => [143, "\xea"], "\xbb" => [148, "\xea"], "\xbc" => [151, "\xea"], "\xbd" => [153, "\xea"], "\xbe" => [83, "\xea"], "\xbf" => [10, "\xea"], "\xc0" => [77, "\xeb0"], "\xc1" => [18, "\xeb0"], "\xc2" => [77, "\xeb1"], "\xc3" => [18, "\xeb1"], "\xc4" => [77, "\xeb2"], "\xc5" => [18, "\xeb2"], "\xc6" => [77, "\xeba"], "\xc7" => [18, "\xeba"], "\xc8" => [77, "\xebc"], "\xc9" => [18, "\xebc"], "\xca" => [77, "\xebe"], "\xcb" => [18, "\xebe"], "\xcc" => [77, "\xebi"], "\xcd" => [18, "\xebi"], "\xce" => [77, "\xebo"], "\xcf" => [18, "\xebo"], "\xd0" => [77, "\xebs"], "\xd1" => [18, "\xebs"], "\xd2" => [77, "\xebt"], "\xd3" => [18, "\xebt"], "\xd4" => [0, "\xeb "], "\xd5" => [0, "\xeb%"], "\xd6" => [0, "\xeb-"], "\xd7" => [0, "\xeb."], "\xd8" => [0, "\xeb/"], "\xd9" => [0, "\xeb3"], "\xda" => [0, "\xeb4"], "\xdb" => [0, "\xeb5"], "\xdc" => [0, "\xeb6"], "\xdd" => [0, "\xeb7"], "\xde" => [0, "\xeb8"], "\xdf" => [0, "\xeb9"], "\xe0" => [0, "\xeb="], "\xe1" => [0, "\xebA"], "\xe2" => [0, "\xeb_"], "\xe3" => [0, "\xebb"], "\xe4" => [0, "\xebd"], "\xe5" => [0, "\xebf"], "\xe6" => [0, "\xebg"], "\xe7" => [0, "\xebh"], "\xe8" => [0, "\xebl"], "\xe9" => [0, "\xebm"], "\xea" => [0, "\xebn"], "\xeb" => [0, "\xebp"], "\xec" => [0, "\xebr"], "\xed" => [0, "\xebu"], "\xee" => [100, "\xeb"], "\xef" => [110, "\xeb"], "\xf0" => [111, "\xeb"], "\xf1" => [115, "\xeb"], "\xf2" => [116, "\xeb"], "\xf3" => [118, "\xeb"], "\xf4" => [119, "\xeb"], "\xf5" => [122, "\xeb"], "\xf6" => [123, "\xeb"], "\xf7" => [125, "\xeb"], "\xf8" => [126, "\xeb"], "\xf9" => [129, "\xeb"], "\xfa" => [143, "\xeb"], "\xfb" => [148, "\xeb"], "\xfc" => [151, "\xeb"], "\xfd" => [153, "\xeb"], "\xfe" => [83, "\xeb"], "\xff" => [10, "\xeb"]], ["\x00" => [77, "\xec0"], "\x01" => [18, "\xec0"], "\x02" => [77, "\xec1"], "\x03" => [18, "\xec1"], "\x04" => [77, "\xec2"], "\x05" => [18, "\xec2"], "\x06" => [77, "\xeca"], "\x07" => [18, "\xeca"], "\x08" => [77, "\xecc"], "\t" => [18, "\xecc"], "\n" => [77, "\xece"], "\v" => [18, "\xece"], "\f" => [77, "\xeci"], "\r" => [18, "\xeci"], "\x0e" => [77, "\xeco"], "\x0f" => [18, "\xeco"], "\x10" => [77, "\xecs"], "\x11" => [18, "\xecs"], "\x12" => [77, "\xect"], "\x13" => [18, "\xect"], "\x14" => [0, "\xec "], "\x15" => [0, "\xec%"], "\x16" => [0, "\xec-"], "\x17" => [0, "\xec."], "\x18" => [0, "\xec/"], "\x19" => [0, "\xec3"], "\x1a" => [0, "\xec4"], "\x1b" => [0, "\xec5"], "\x1c" => [0, "\xec6"], "\x1d" => [0, "\xec7"], "\x1e" => [0, "\xec8"], "\x1f" => [0, "\xec9"], " " => [0, "\xec="], "!" => [0, "\xecA"], "\"" => [0, "\xec_"], "#" => [0, "\xecb"], "\$" => [0, "\xecd"], "%" => [0, "\xecf"], "&" => [0, "\xecg"], "'" => [0, "\xech"], "(" => [0, "\xecl"], ")" => [0, "\xecm"], "*" => [0, "\xecn"], "+" => [0, "\xecp"], "," => [0, "\xecr"], "-" => [0, "\xecu"], "." => [100, "\xec"], "/" => [110, "\xec"], [111, "\xec"], [115, "\xec"], [116, "\xec"], [118, "\xec"], [119, "\xec"], [122, "\xec"], [123, "\xec"], [125, "\xec"], [126, "\xec"], [129, "\xec"], ":" => [143, "\xec"], ";" => [148, "\xec"], "<" => [151, "\xec"], "=" => [153, "\xec"], ">" => [83, "\xec"], "?" => [10, "\xec"], "@" => [77, "\xed0"], "A" => [18, "\xed0"], "B" => [77, "\xed1"], "C" => [18, "\xed1"], "D" => [77, "\xed2"], "E" => [18, "\xed2"], "F" => [77, "\xeda"], "G" => [18, "\xeda"], "H" => [77, "\xedc"], "I" => [18, "\xedc"], "J" => [77, "\xede"], "K" => [18, "\xede"], "L" => [77, "\xedi"], "M" => [18, "\xedi"], "N" => [77, "\xedo"], "O" => [18, "\xedo"], "P" => [77, "\xeds"], "Q" => [18, "\xeds"], "R" => [77, "\xedt"], "S" => [18, "\xedt"], "T" => [0, "\xed "], "U" => [0, "\xed%"], "V" => [0, "\xed-"], "W" => [0, "\xed."], "X" => [0, "\xed/"], "Y" => [0, "\xed3"], "Z" => [0, "\xed4"], "[" => [0, "\xed5"], "\\" => [0, "\xed6"], "]" => [0, "\xed7"], "^" => [0, "\xed8"], "_" => [0, "\xed9"], "`" => [0, "\xed="], "a" => [0, "\xedA"], "b" => [0, "\xed_"], "c" => [0, "\xedb"], "d" => [0, "\xedd"], "e" => [0, "\xedf"], "f" => [0, "\xedg"], "g" => [0, "\xedh"], "h" => [0, "\xedl"], "i" => [0, "\xedm"], "j" => [0, "\xedn"], "k" => [0, "\xedp"], "l" => [0, "\xedr"], "m" => [0, "\xedu"], "n" => [100, "\xed"], "o" => [110, "\xed"], "p" => [111, "\xed"], "q" => [115, "\xed"], "r" => [116, "\xed"], "s" => [118, "\xed"], "t" => [119, "\xed"], "u" => [122, "\xed"], "v" => [123, "\xed"], "w" => [125, "\xed"], "x" => [126, "\xed"], "y" => [129, "\xed"], "z" => [143, "\xed"], "{" => [148, "\xed"], "|" => [151, "\xed"], "}" => [153, "\xed"], "~" => [83, "\xed"], "" => [10, "\xed"], "\x80" => [0, "\xc70"], "\x81" => [0, "\xc71"], "\x82" => [0, "\xc72"], "\x83" => [0, "\xc7a"], "\x84" => [0, "\xc7c"], "\x85" => [0, "\xc7e"], "\x86" => [0, "\xc7i"], "\x87" => [0, "\xc7o"], "\x88" => [0, "\xc7s"], "\x89" => [0, "\xc7t"], "\x8a" => [73, "\xc7"], "\x8b" => [88, "\xc7"], "\x8c" => [89, "\xc7"], "\x8d" => [96, "\xc7"], "\x8e" => [97, "\xc7"], "\x8f" => [99, "\xc7"], "\x90" => [106, "\xc7"], "\x91" => [136, "\xc7"], "\x92" => [139, "\xc7"], "\x93" => [141, "\xc7"], "\x94" => [145, "\xc7"], "\x95" => [147, "\xc7"], "\x96" => [149, "\xc7"], "\x97" => [101, "\xc7"], "\x98" => [112, "\xc7"], "\x99" => [117, "\xc7"], "\x9a" => [120, "\xc7"], "\x9b" => [124, "\xc7"], "\x9c" => [127, "\xc7"], "\x9d" => [144, "\xc7"], "\x9e" => [152, "\xc7"], "\x9f" => [11, "\xc7"], "\xa0" => [0, "\xcf0"], "\xa1" => [0, "\xcf1"], "\xa2" => [0, "\xcf2"], "\xa3" => [0, "\xcfa"], "\xa4" => [0, "\xcfc"], "\xa5" => [0, "\xcfe"], "\xa6" => [0, "\xcfi"], "\xa7" => [0, "\xcfo"], "\xa8" => [0, "\xcfs"], "\xa9" => [0, "\xcft"], "\xaa" => [73, "\xcf"], "\xab" => [88, "\xcf"], "\xac" => [89, "\xcf"], "\xad" => [96, "\xcf"], "\xae" => [97, "\xcf"], "\xaf" => [99, "\xcf"], "\xb0" => [106, "\xcf"], "\xb1" => [136, "\xcf"], "\xb2" => [139, "\xcf"], "\xb3" => [141, "\xcf"], "\xb4" => [145, "\xcf"], "\xb5" => [147, "\xcf"], "\xb6" => [149, "\xcf"], "\xb7" => [101, "\xcf"], "\xb8" => [112, "\xcf"], "\xb9" => [117, "\xcf"], "\xba" => [120, "\xcf"], "\xbb" => [124, "\xcf"], "\xbc" => [127, "\xcf"], "\xbd" => [144, "\xcf"], "\xbe" => [152, "\xcf"], "\xbf" => [11, "\xcf"], "\xc0" => [0, "\xea0"], "\xc1" => [0, "\xea1"], "\xc2" => [0, "\xea2"], "\xc3" => [0, "\xeaa"], "\xc4" => [0, "\xeac"], "\xc5" => [0, "\xeae"], "\xc6" => [0, "\xeai"], "\xc7" => [0, "\xeao"], "\xc8" => [0, "\xeas"], "\xc9" => [0, "\xeat"], "\xca" => [73, "\xea"], "\xcb" => [88, "\xea"], "\xcc" => [89, "\xea"], "\xcd" => [96, "\xea"], "\xce" => [97, "\xea"], "\xcf" => [99, "\xea"], "\xd0" => [106, "\xea"], "\xd1" => [136, "\xea"], "\xd2" => [139, "\xea"], "\xd3" => [141, "\xea"], "\xd4" => [145, "\xea"], "\xd5" => [147, "\xea"], "\xd6" => [149, "\xea"], "\xd7" => [101, "\xea"], "\xd8" => [112, "\xea"], "\xd9" => [117, "\xea"], "\xda" => [120, "\xea"], "\xdb" => [124, "\xea"], "\xdc" => [127, "\xea"], "\xdd" => [144, "\xea"], "\xde" => [152, "\xea"], "\xdf" => [11, "\xea"], "\xe0" => [0, "\xeb0"], "\xe1" => [0, "\xeb1"], "\xe2" => [0, "\xeb2"], "\xe3" => [0, "\xeba"], "\xe4" => [0, "\xebc"], "\xe5" => [0, "\xebe"], "\xe6" => [0, "\xebi"], "\xe7" => [0, "\xebo"], "\xe8" => [0, "\xebs"], "\xe9" => [0, "\xebt"], "\xea" => [73, "\xeb"], "\xeb" => [88, "\xeb"], "\xec" => [89, "\xeb"], "\xed" => [96, "\xeb"], "\xee" => [97, "\xeb"], "\xef" => [99, "\xeb"], "\xf0" => [106, "\xeb"], "\xf1" => [136, "\xeb"], "\xf2" => [139, "\xeb"], "\xf3" => [141, "\xeb"], "\xf4" => [145, "\xeb"], "\xf5" => [147, "\xeb"], "\xf6" => [149, "\xeb"], "\xf7" => [101, "\xeb"], "\xf8" => [112, "\xeb"], "\xf9" => [117, "\xeb"], "\xfa" => [120, "\xeb"], "\xfb" => [124, "\xeb"], "\xfc" => [127, "\xeb"], "\xfd" => [144, "\xeb"], "\xfe" => [152, "\xeb"], "\xff" => [11, "\xeb"]], ["\x00" => [94, "\xc80"], "\x01" => [76, "\xc80"], "\x02" => [104, "\xc80"], "\x03" => [16, "\xc80"], "\x04" => [94, "\xc81"], "\x05" => [76, "\xc81"], "\x06" => [104, "\xc81"], "\x07" => [16, "\xc81"], "\x08" => [94, "\xc82"], "\t" => [76, "\xc82"], "\n" => [104, "\xc82"], "\v" => [16, "\xc82"], "\f" => [94, "\xc8a"], "\r" => [76, "\xc8a"], "\x0e" => [104, "\xc8a"], "\x0f" => [16, "\xc8a"], "\x10" => [94, "\xc8c"], "\x11" => [76, "\xc8c"], "\x12" => [104, "\xc8c"], "\x13" => [16, "\xc8c"], "\x14" => [94, "\xc8e"], "\x15" => [76, "\xc8e"], "\x16" => [104, "\xc8e"], "\x17" => [16, "\xc8e"], "\x18" => [94, "\xc8i"], "\x19" => [76, "\xc8i"], "\x1a" => [104, "\xc8i"], "\x1b" => [16, "\xc8i"], "\x1c" => [94, "\xc8o"], "\x1d" => [76, "\xc8o"], "\x1e" => [104, "\xc8o"], "\x1f" => [16, "\xc8o"], " " => [94, "\xc8s"], "!" => [76, "\xc8s"], "\"" => [104, "\xc8s"], "#" => [16, "\xc8s"], "\$" => [94, "\xc8t"], "%" => [76, "\xc8t"], "&" => [104, "\xc8t"], "'" => [16, "\xc8t"], "(" => [77, "\xc8 "], ")" => [18, "\xc8 "], "*" => [77, "\xc8%"], "+" => [18, "\xc8%"], "," => [77, "\xc8-"], "-" => [18, "\xc8-"], "." => [77, "\xc8."], "/" => [18, "\xc8."], [77, "\xc8/"], [18, "\xc8/"], [77, "\xc83"], [18, "\xc83"], [77, "\xc84"], [18, "\xc84"], [77, "\xc85"], [18, "\xc85"], [77, "\xc86"], [18, "\xc86"], ":" => [77, "\xc87"], ";" => [18, "\xc87"], "<" => [77, "\xc88"], "=" => [18, "\xc88"], ">" => [77, "\xc89"], "?" => [18, "\xc89"], "@" => [77, "\xc8="], "A" => [18, "\xc8="], "B" => [77, "\xc8A"], "C" => [18, "\xc8A"], "D" => [77, "\xc8_"], "E" => [18, "\xc8_"], "F" => [77, "\xc8b"], "G" => [18, "\xc8b"], "H" => [77, "\xc8d"], "I" => [18, "\xc8d"], "J" => [77, "\xc8f"], "K" => [18, "\xc8f"], "L" => [77, "\xc8g"], "M" => [18, "\xc8g"], "N" => [77, "\xc8h"], "O" => [18, "\xc8h"], "P" => [77, "\xc8l"], "Q" => [18, "\xc8l"], "R" => [77, "\xc8m"], "S" => [18, "\xc8m"], "T" => [77, "\xc8n"], "U" => [18, "\xc8n"], "V" => [77, "\xc8p"], "W" => [18, "\xc8p"], "X" => [77, "\xc8r"], "Y" => [18, "\xc8r"], "Z" => [77, "\xc8u"], "[" => [18, "\xc8u"], "\\" => [0, "\xc8:"], "]" => [0, "\xc8B"], "^" => [0, "\xc8C"], "_" => [0, "\xc8D"], "`" => [0, "\xc8E"], "a" => [0, "\xc8F"], "b" => [0, "\xc8G"], "c" => [0, "\xc8H"], "d" => [0, "\xc8I"], "e" => [0, "\xc8J"], "f" => [0, "\xc8K"], "g" => [0, "\xc8L"], "h" => [0, "\xc8M"], "i" => [0, "\xc8N"], "j" => [0, "\xc8O"], "k" => [0, "\xc8P"], "l" => [0, "\xc8Q"], "m" => [0, "\xc8R"], "n" => [0, "\xc8S"], "o" => [0, "\xc8T"], "p" => [0, "\xc8U"], "q" => [0, "\xc8V"], "r" => [0, "\xc8W"], "s" => [0, "\xc8Y"], "t" => [0, "\xc8j"], "u" => [0, "\xc8k"], "v" => [0, "\xc8q"], "w" => [0, "\xc8v"], "x" => [0, "\xc8w"], "y" => [0, "\xc8x"], "z" => [0, "\xc8y"], "{" => [0, "\xc8z"], "|" => [82, "\xc8"], "}" => [87, "\xc8"], "~" => [130, "\xc8"], "" => [9, "\xc8"], "\x80" => [94, "\xc90"], "\x81" => [76, "\xc90"], "\x82" => [104, "\xc90"], "\x83" => [16, "\xc90"], "\x84" => [94, "\xc91"], "\x85" => [76, "\xc91"], "\x86" => [104, "\xc91"], "\x87" => [16, "\xc91"], "\x88" => [94, "\xc92"], "\x89" => [76, "\xc92"], "\x8a" => [104, "\xc92"], "\x8b" => [16, "\xc92"], "\x8c" => [94, "\xc9a"], "\x8d" => [76, "\xc9a"], "\x8e" => [104, "\xc9a"], "\x8f" => [16, "\xc9a"], "\x90" => [94, "\xc9c"], "\x91" => [76, "\xc9c"], "\x92" => [104, "\xc9c"], "\x93" => [16, "\xc9c"], "\x94" => [94, "\xc9e"], "\x95" => [76, "\xc9e"], "\x96" => [104, "\xc9e"], "\x97" => [16, "\xc9e"], "\x98" => [94, "\xc9i"], "\x99" => [76, "\xc9i"], "\x9a" => [104, "\xc9i"], "\x9b" => [16, "\xc9i"], "\x9c" => [94, "\xc9o"], "\x9d" => [76, "\xc9o"], "\x9e" => [104, "\xc9o"], "\x9f" => [16, "\xc9o"], "\xa0" => [94, "\xc9s"], "\xa1" => [76, "\xc9s"], "\xa2" => [104, "\xc9s"], "\xa3" => [16, "\xc9s"], "\xa4" => [94, "\xc9t"], "\xa5" => [76, "\xc9t"], "\xa6" => [104, "\xc9t"], "\xa7" => [16, "\xc9t"], "\xa8" => [77, "\xc9 "], "\xa9" => [18, "\xc9 "], "\xaa" => [77, "\xc9%"], "\xab" => [18, "\xc9%"], "\xac" => [77, "\xc9-"], "\xad" => [18, "\xc9-"], "\xae" => [77, "\xc9."], "\xaf" => [18, "\xc9."], "\xb0" => [77, "\xc9/"], "\xb1" => [18, "\xc9/"], "\xb2" => [77, "\xc93"], "\xb3" => [18, "\xc93"], "\xb4" => [77, "\xc94"], "\xb5" => [18, "\xc94"], "\xb6" => [77, "\xc95"], "\xb7" => [18, "\xc95"], "\xb8" => [77, "\xc96"], "\xb9" => [18, "\xc96"], "\xba" => [77, "\xc97"], "\xbb" => [18, "\xc97"], "\xbc" => [77, "\xc98"], "\xbd" => [18, "\xc98"], "\xbe" => [77, "\xc99"], "\xbf" => [18, "\xc99"], "\xc0" => [77, "\xc9="], "\xc1" => [18, "\xc9="], "\xc2" => [77, "\xc9A"], "\xc3" => [18, "\xc9A"], "\xc4" => [77, "\xc9_"], "\xc5" => [18, "\xc9_"], "\xc6" => [77, "\xc9b"], "\xc7" => [18, "\xc9b"], "\xc8" => [77, "\xc9d"], "\xc9" => [18, "\xc9d"], "\xca" => [77, "\xc9f"], "\xcb" => [18, "\xc9f"], "\xcc" => [77, "\xc9g"], "\xcd" => [18, "\xc9g"], "\xce" => [77, "\xc9h"], "\xcf" => [18, "\xc9h"], "\xd0" => [77, "\xc9l"], "\xd1" => [18, "\xc9l"], "\xd2" => [77, "\xc9m"], "\xd3" => [18, "\xc9m"], "\xd4" => [77, "\xc9n"], "\xd5" => [18, "\xc9n"], "\xd6" => [77, "\xc9p"], "\xd7" => [18, "\xc9p"], "\xd8" => [77, "\xc9r"], "\xd9" => [18, "\xc9r"], "\xda" => [77, "\xc9u"], "\xdb" => [18, "\xc9u"], "\xdc" => [0, "\xc9:"], "\xdd" => [0, "\xc9B"], "\xde" => [0, "\xc9C"], "\xdf" => [0, "\xc9D"], "\xe0" => [0, "\xc9E"], "\xe1" => [0, "\xc9F"], "\xe2" => [0, "\xc9G"], "\xe3" => [0, "\xc9H"], "\xe4" => [0, "\xc9I"], "\xe5" => [0, "\xc9J"], "\xe6" => [0, "\xc9K"], "\xe7" => [0, "\xc9L"], "\xe8" => [0, "\xc9M"], "\xe9" => [0, "\xc9N"], "\xea" => [0, "\xc9O"], "\xeb" => [0, "\xc9P"], "\xec" => [0, "\xc9Q"], "\xed" => [0, "\xc9R"], "\xee" => [0, "\xc9S"], "\xef" => [0, "\xc9T"], "\xf0" => [0, "\xc9U"], "\xf1" => [0, "\xc9V"], "\xf2" => [0, "\xc9W"], "\xf3" => [0, "\xc9Y"], "\xf4" => [0, "\xc9j"], "\xf5" => [0, "\xc9k"], "\xf6" => [0, "\xc9q"], "\xf7" => [0, "\xc9v"], "\xf8" => [0, "\xc9w"], "\xf9" => [0, "\xc9x"], "\xfa" => [0, "\xc9y"], "\xfb" => [0, "\xc9z"], "\xfc" => [82, "\xc9"], "\xfd" => [87, "\xc9"], "\xfe" => [130, "\xc9"], "\xff" => [9, "\xc9"]], ["\x00" => [77, "\xca0"], "\x01" => [18, "\xca0"], "\x02" => [77, "\xca1"], "\x03" => [18, "\xca1"], "\x04" => [77, "\xca2"], "\x05" => [18, "\xca2"], "\x06" => [77, "\xcaa"], "\x07" => [18, "\xcaa"], "\x08" => [77, "\xcac"], "\t" => [18, "\xcac"], "\n" => [77, "\xcae"], "\v" => [18, "\xcae"], "\f" => [77, "\xcai"], "\r" => [18, "\xcai"], "\x0e" => [77, "\xcao"], "\x0f" => [18, "\xcao"], "\x10" => [77, "\xcas"], "\x11" => [18, "\xcas"], "\x12" => [77, "\xcat"], "\x13" => [18, "\xcat"], "\x14" => [0, "\xca "], "\x15" => [0, "\xca%"], "\x16" => [0, "\xca-"], "\x17" => [0, "\xca."], "\x18" => [0, "\xca/"], "\x19" => [0, "\xca3"], "\x1a" => [0, "\xca4"], "\x1b" => [0, "\xca5"], "\x1c" => [0, "\xca6"], "\x1d" => [0, "\xca7"], "\x1e" => [0, "\xca8"], "\x1f" => [0, "\xca9"], " " => [0, "\xca="], "!" => [0, "\xcaA"], "\"" => [0, "\xca_"], "#" => [0, "\xcab"], "\$" => [0, "\xcad"], "%" => [0, "\xcaf"], "&" => [0, "\xcag"], "'" => [0, "\xcah"], "(" => [0, "\xcal"], ")" => [0, "\xcam"], "*" => [0, "\xcan"], "+" => [0, "\xcap"], "," => [0, "\xcar"], "-" => [0, "\xcau"], "." => [100, "\xca"], "/" => [110, "\xca"], [111, "\xca"], [115, "\xca"], [116, "\xca"], [118, "\xca"], [119, "\xca"], [122, "\xca"], [123, "\xca"], [125, "\xca"], [126, "\xca"], [129, "\xca"], ":" => [143, "\xca"], ";" => [148, "\xca"], "<" => [151, "\xca"], "=" => [153, "\xca"], ">" => [83, "\xca"], "?" => [10, "\xca"], "@" => [77, "\xcd0"], "A" => [18, "\xcd0"], "B" => [77, "\xcd1"], "C" => [18, "\xcd1"], "D" => [77, "\xcd2"], "E" => [18, "\xcd2"], "F" => [77, "\xcda"], "G" => [18, "\xcda"], "H" => [77, "\xcdc"], "I" => [18, "\xcdc"], "J" => [77, "\xcde"], "K" => [18, "\xcde"], "L" => [77, "\xcdi"], "M" => [18, "\xcdi"], "N" => [77, "\xcdo"], "O" => [18, "\xcdo"], "P" => [77, "\xcds"], "Q" => [18, "\xcds"], "R" => [77, "\xcdt"], "S" => [18, "\xcdt"], "T" => [0, "\xcd "], "U" => [0, "\xcd%"], "V" => [0, "\xcd-"], "W" => [0, "\xcd."], "X" => [0, "\xcd/"], "Y" => [0, "\xcd3"], "Z" => [0, "\xcd4"], "[" => [0, "\xcd5"], "\\" => [0, "\xcd6"], "]" => [0, "\xcd7"], "^" => [0, "\xcd8"], "_" => [0, "\xcd9"], "`" => [0, "\xcd="], "a" => [0, "\xcdA"], "b" => [0, "\xcd_"], "c" => [0, "\xcdb"], "d" => [0, "\xcdd"], "e" => [0, "\xcdf"], "f" => [0, "\xcdg"], "g" => [0, "\xcdh"], "h" => [0, "\xcdl"], "i" => [0, "\xcdm"], "j" => [0, "\xcdn"], "k" => [0, "\xcdp"], "l" => [0, "\xcdr"], "m" => [0, "\xcdu"], "n" => [100, "\xcd"], "o" => [110, "\xcd"], "p" => [111, "\xcd"], "q" => [115, "\xcd"], "r" => [116, "\xcd"], "s" => [118, "\xcd"], "t" => [119, "\xcd"], "u" => [122, "\xcd"], "v" => [123, "\xcd"], "w" => [125, "\xcd"], "x" => [126, "\xcd"], "y" => [129, "\xcd"], "z" => [143, "\xcd"], "{" => [148, "\xcd"], "|" => [151, "\xcd"], "}" => [153, "\xcd"], "~" => [83, "\xcd"], "" => [10, "\xcd"], "\x80" => [77, "\xd20"], "\x81" => [18, "\xd20"], "\x82" => [77, "\xd21"], "\x83" => [18, "\xd21"], "\x84" => [77, "\xd22"], "\x85" => [18, "\xd22"], "\x86" => [77, "\xd2a"], "\x87" => [18, "\xd2a"], "\x88" => [77, "\xd2c"], "\x89" => [18, "\xd2c"], "\x8a" => [77, "\xd2e"], "\x8b" => [18, "\xd2e"], "\x8c" => [77, "\xd2i"], "\x8d" => [18, "\xd2i"], "\x8e" => [77, "\xd2o"], "\x8f" => [18, "\xd2o"], "\x90" => [77, "\xd2s"], "\x91" => [18, "\xd2s"], "\x92" => [77, "\xd2t"], "\x93" => [18, "\xd2t"], "\x94" => [0, "\xd2 "], "\x95" => [0, "\xd2%"], "\x96" => [0, "\xd2-"], "\x97" => [0, "\xd2."], "\x98" => [0, "\xd2/"], "\x99" => [0, "\xd23"], "\x9a" => [0, "\xd24"], "\x9b" => [0, "\xd25"], "\x9c" => [0, "\xd26"], "\x9d" => [0, "\xd27"], "\x9e" => [0, "\xd28"], "\x9f" => [0, "\xd29"], "\xa0" => [0, "\xd2="], "\xa1" => [0, "\xd2A"], "\xa2" => [0, "\xd2_"], "\xa3" => [0, "\xd2b"], "\xa4" => [0, "\xd2d"], "\xa5" => [0, "\xd2f"], "\xa6" => [0, "\xd2g"], "\xa7" => [0, "\xd2h"], "\xa8" => [0, "\xd2l"], "\xa9" => [0, "\xd2m"], "\xaa" => [0, "\xd2n"], "\xab" => [0, "\xd2p"], "\xac" => [0, "\xd2r"], "\xad" => [0, "\xd2u"], "\xae" => [100, "\xd2"], "\xaf" => [110, "\xd2"], "\xb0" => [111, "\xd2"], "\xb1" => [115, "\xd2"], "\xb2" => [116, "\xd2"], "\xb3" => [118, "\xd2"], "\xb4" => [119, "\xd2"], "\xb5" => [122, "\xd2"], "\xb6" => [123, "\xd2"], "\xb7" => [125, "\xd2"], "\xb8" => [126, "\xd2"], "\xb9" => [129, "\xd2"], "\xba" => [143, "\xd2"], "\xbb" => [148, "\xd2"], "\xbc" => [151, "\xd2"], "\xbd" => [153, "\xd2"], "\xbe" => [83, "\xd2"], "\xbf" => [10, "\xd2"], "\xc0" => [77, "\xd50"], "\xc1" => [18, "\xd50"], "\xc2" => [77, "\xd51"], "\xc3" => [18, "\xd51"], "\xc4" => [77, "\xd52"], "\xc5" => [18, "\xd52"], "\xc6" => [77, "\xd5a"], "\xc7" => [18, "\xd5a"], "\xc8" => [77, "\xd5c"], "\xc9" => [18, "\xd5c"], "\xca" => [77, "\xd5e"], "\xcb" => [18, "\xd5e"], "\xcc" => [77, "\xd5i"], "\xcd" => [18, "\xd5i"], "\xce" => [77, "\xd5o"], "\xcf" => [18, "\xd5o"], "\xd0" => [77, "\xd5s"], "\xd1" => [18, "\xd5s"], "\xd2" => [77, "\xd5t"], "\xd3" => [18, "\xd5t"], "\xd4" => [0, "\xd5 "], "\xd5" => [0, "\xd5%"], "\xd6" => [0, "\xd5-"], "\xd7" => [0, "\xd5."], "\xd8" => [0, "\xd5/"], "\xd9" => [0, "\xd53"], "\xda" => [0, "\xd54"], "\xdb" => [0, "\xd55"], "\xdc" => [0, "\xd56"], "\xdd" => [0, "\xd57"], "\xde" => [0, "\xd58"], "\xdf" => [0, "\xd59"], "\xe0" => [0, "\xd5="], "\xe1" => [0, "\xd5A"], "\xe2" => [0, "\xd5_"], "\xe3" => [0, "\xd5b"], "\xe4" => [0, "\xd5d"], "\xe5" => [0, "\xd5f"], "\xe6" => [0, "\xd5g"], "\xe7" => [0, "\xd5h"], "\xe8" => [0, "\xd5l"], "\xe9" => [0, "\xd5m"], "\xea" => [0, "\xd5n"], "\xeb" => [0, "\xd5p"], "\xec" => [0, "\xd5r"], "\xed" => [0, "\xd5u"], "\xee" => [100, "\xd5"], "\xef" => [110, "\xd5"], "\xf0" => [111, "\xd5"], "\xf1" => [115, "\xd5"], "\xf2" => [116, "\xd5"], "\xf3" => [118, "\xd5"], "\xf4" => [119, "\xd5"], "\xf5" => [122, "\xd5"], "\xf6" => [123, "\xd5"], "\xf7" => [125, "\xd5"], "\xf8" => [126, "\xd5"], "\xf9" => [129, "\xd5"], "\xfa" => [143, "\xd5"], "\xfb" => [148, "\xd5"], "\xfc" => [151, "\xd5"], "\xfd" => [153, "\xd5"], "\xfe" => [83, "\xd5"], "\xff" => [10, "\xd5"]], ["\x00" => [94, "\xca0"], "\x01" => [76, "\xca0"], "\x02" => [104, "\xca0"], "\x03" => [16, "\xca0"], "\x04" => [94, "\xca1"], "\x05" => [76, "\xca1"], "\x06" => [104, "\xca1"], "\x07" => [16, "\xca1"], "\x08" => [94, "\xca2"], "\t" => [76, "\xca2"], "\n" => [104, "\xca2"], "\v" => [16, "\xca2"], "\f" => [94, "\xcaa"], "\r" => [76, "\xcaa"], "\x0e" => [104, "\xcaa"], "\x0f" => [16, "\xcaa"], "\x10" => [94, "\xcac"], "\x11" => [76, "\xcac"], "\x12" => [104, "\xcac"], "\x13" => [16, "\xcac"], "\x14" => [94, "\xcae"], "\x15" => [76, "\xcae"], "\x16" => [104, "\xcae"], "\x17" => [16, "\xcae"], "\x18" => [94, "\xcai"], "\x19" => [76, "\xcai"], "\x1a" => [104, "\xcai"], "\x1b" => [16, "\xcai"], "\x1c" => [94, "\xcao"], "\x1d" => [76, "\xcao"], "\x1e" => [104, "\xcao"], "\x1f" => [16, "\xcao"], " " => [94, "\xcas"], "!" => [76, "\xcas"], "\"" => [104, "\xcas"], "#" => [16, "\xcas"], "\$" => [94, "\xcat"], "%" => [76, "\xcat"], "&" => [104, "\xcat"], "'" => [16, "\xcat"], "(" => [77, "\xca "], ")" => [18, "\xca "], "*" => [77, "\xca%"], "+" => [18, "\xca%"], "," => [77, "\xca-"], "-" => [18, "\xca-"], "." => [77, "\xca."], "/" => [18, "\xca."], [77, "\xca/"], [18, "\xca/"], [77, "\xca3"], [18, "\xca3"], [77, "\xca4"], [18, "\xca4"], [77, "\xca5"], [18, "\xca5"], [77, "\xca6"], [18, "\xca6"], ":" => [77, "\xca7"], ";" => [18, "\xca7"], "<" => [77, "\xca8"], "=" => [18, "\xca8"], ">" => [77, "\xca9"], "?" => [18, "\xca9"], "@" => [77, "\xca="], "A" => [18, "\xca="], "B" => [77, "\xcaA"], "C" => [18, "\xcaA"], "D" => [77, "\xca_"], "E" => [18, "\xca_"], "F" => [77, "\xcab"], "G" => [18, "\xcab"], "H" => [77, "\xcad"], "I" => [18, "\xcad"], "J" => [77, "\xcaf"], "K" => [18, "\xcaf"], "L" => [77, "\xcag"], "M" => [18, "\xcag"], "N" => [77, "\xcah"], "O" => [18, "\xcah"], "P" => [77, "\xcal"], "Q" => [18, "\xcal"], "R" => [77, "\xcam"], "S" => [18, "\xcam"], "T" => [77, "\xcan"], "U" => [18, "\xcan"], "V" => [77, "\xcap"], "W" => [18, "\xcap"], "X" => [77, "\xcar"], "Y" => [18, "\xcar"], "Z" => [77, "\xcau"], "[" => [18, "\xcau"], "\\" => [0, "\xca:"], "]" => [0, "\xcaB"], "^" => [0, "\xcaC"], "_" => [0, "\xcaD"], "`" => [0, "\xcaE"], "a" => [0, "\xcaF"], "b" => [0, "\xcaG"], "c" => [0, "\xcaH"], "d" => [0, "\xcaI"], "e" => [0, "\xcaJ"], "f" => [0, "\xcaK"], "g" => [0, "\xcaL"], "h" => [0, "\xcaM"], "i" => [0, "\xcaN"], "j" => [0, "\xcaO"], "k" => [0, "\xcaP"], "l" => [0, "\xcaQ"], "m" => [0, "\xcaR"], "n" => [0, "\xcaS"], "o" => [0, "\xcaT"], "p" => [0, "\xcaU"], "q" => [0, "\xcaV"], "r" => [0, "\xcaW"], "s" => [0, "\xcaY"], "t" => [0, "\xcaj"], "u" => [0, "\xcak"], "v" => [0, "\xcaq"], "w" => [0, "\xcav"], "x" => [0, "\xcaw"], "y" => [0, "\xcax"], "z" => [0, "\xcay"], "{" => [0, "\xcaz"], "|" => [82, "\xca"], "}" => [87, "\xca"], "~" => [130, "\xca"], "" => [9, "\xca"], "\x80" => [94, "\xcd0"], "\x81" => [76, "\xcd0"], "\x82" => [104, "\xcd0"], "\x83" => [16, "\xcd0"], "\x84" => [94, "\xcd1"], "\x85" => [76, "\xcd1"], "\x86" => [104, "\xcd1"], "\x87" => [16, "\xcd1"], "\x88" => [94, "\xcd2"], "\x89" => [76, "\xcd2"], "\x8a" => [104, "\xcd2"], "\x8b" => [16, "\xcd2"], "\x8c" => [94, "\xcda"], "\x8d" => [76, "\xcda"], "\x8e" => [104, "\xcda"], "\x8f" => [16, "\xcda"], "\x90" => [94, "\xcdc"], "\x91" => [76, "\xcdc"], "\x92" => [104, "\xcdc"], "\x93" => [16, "\xcdc"], "\x94" => [94, "\xcde"], "\x95" => [76, "\xcde"], "\x96" => [104, "\xcde"], "\x97" => [16, "\xcde"], "\x98" => [94, "\xcdi"], "\x99" => [76, "\xcdi"], "\x9a" => [104, "\xcdi"], "\x9b" => [16, "\xcdi"], "\x9c" => [94, "\xcdo"], "\x9d" => [76, "\xcdo"], "\x9e" => [104, "\xcdo"], "\x9f" => [16, "\xcdo"], "\xa0" => [94, "\xcds"], "\xa1" => [76, "\xcds"], "\xa2" => [104, "\xcds"], "\xa3" => [16, "\xcds"], "\xa4" => [94, "\xcdt"], "\xa5" => [76, "\xcdt"], "\xa6" => [104, "\xcdt"], "\xa7" => [16, "\xcdt"], "\xa8" => [77, "\xcd "], "\xa9" => [18, "\xcd "], "\xaa" => [77, "\xcd%"], "\xab" => [18, "\xcd%"], "\xac" => [77, "\xcd-"], "\xad" => [18, "\xcd-"], "\xae" => [77, "\xcd."], "\xaf" => [18, "\xcd."], "\xb0" => [77, "\xcd/"], "\xb1" => [18, "\xcd/"], "\xb2" => [77, "\xcd3"], "\xb3" => [18, "\xcd3"], "\xb4" => [77, "\xcd4"], "\xb5" => [18, "\xcd4"], "\xb6" => [77, "\xcd5"], "\xb7" => [18, "\xcd5"], "\xb8" => [77, "\xcd6"], "\xb9" => [18, "\xcd6"], "\xba" => [77, "\xcd7"], "\xbb" => [18, "\xcd7"], "\xbc" => [77, "\xcd8"], "\xbd" => [18, "\xcd8"], "\xbe" => [77, "\xcd9"], "\xbf" => [18, "\xcd9"], "\xc0" => [77, "\xcd="], "\xc1" => [18, "\xcd="], "\xc2" => [77, "\xcdA"], "\xc3" => [18, "\xcdA"], "\xc4" => [77, "\xcd_"], "\xc5" => [18, "\xcd_"], "\xc6" => [77, "\xcdb"], "\xc7" => [18, "\xcdb"], "\xc8" => [77, "\xcdd"], "\xc9" => [18, "\xcdd"], "\xca" => [77, "\xcdf"], "\xcb" => [18, "\xcdf"], "\xcc" => [77, "\xcdg"], "\xcd" => [18, "\xcdg"], "\xce" => [77, "\xcdh"], "\xcf" => [18, "\xcdh"], "\xd0" => [77, "\xcdl"], "\xd1" => [18, "\xcdl"], "\xd2" => [77, "\xcdm"], "\xd3" => [18, "\xcdm"], "\xd4" => [77, "\xcdn"], "\xd5" => [18, "\xcdn"], "\xd6" => [77, "\xcdp"], "\xd7" => [18, "\xcdp"], "\xd8" => [77, "\xcdr"], "\xd9" => [18, "\xcdr"], "\xda" => [77, "\xcdu"], "\xdb" => [18, "\xcdu"], "\xdc" => [0, "\xcd:"], "\xdd" => [0, "\xcdB"], "\xde" => [0, "\xcdC"], "\xdf" => [0, "\xcdD"], "\xe0" => [0, "\xcdE"], "\xe1" => [0, "\xcdF"], "\xe2" => [0, "\xcdG"], "\xe3" => [0, "\xcdH"], "\xe4" => [0, "\xcdI"], "\xe5" => [0, "\xcdJ"], "\xe6" => [0, "\xcdK"], "\xe7" => [0, "\xcdL"], "\xe8" => [0, "\xcdM"], "\xe9" => [0, "\xcdN"], "\xea" => [0, "\xcdO"], "\xeb" => [0, "\xcdP"], "\xec" => [0, "\xcdQ"], "\xed" => [0, "\xcdR"], "\xee" => [0, "\xcdS"], "\xef" => [0, "\xcdT"], "\xf0" => [0, "\xcdU"], "\xf1" => [0, "\xcdV"], "\xf2" => [0, "\xcdW"], "\xf3" => [0, "\xcdY"], "\xf4" => [0, "\xcdj"], "\xf5" => [0, "\xcdk"], "\xf6" => [0, "\xcdq"], "\xf7" => [0, "\xcdv"], "\xf8" => [0, "\xcdw"], "\xf9" => [0, "\xcdx"], "\xfa" => [0, "\xcdy"], "\xfb" => [0, "\xcdz"], "\xfc" => [82, "\xcd"], "\xfd" => [87, "\xcd"], "\xfe" => [130, "\xcd"], "\xff" => [9, "\xcd"]], ["\x00" => [77, "\xf20"], "\x01" => [18, "\xf20"], "\x02" => [77, "\xf21"], "\x03" => [18, "\xf21"], "\x04" => [77, "\xf22"], "\x05" => [18, "\xf22"], "\x06" => [77, "\xf2a"], "\x07" => [18, "\xf2a"], "\x08" => [77, "\xf2c"], "\t" => [18, "\xf2c"], "\n" => [77, "\xf2e"], "\v" => [18, "\xf2e"], "\f" => [77, "\xf2i"], "\r" => [18, "\xf2i"], "\x0e" => [77, "\xf2o"], "\x0f" => [18, "\xf2o"], "\x10" => [77, "\xf2s"], "\x11" => [18, "\xf2s"], "\x12" => [77, "\xf2t"], "\x13" => [18, "\xf2t"], "\x14" => [0, "\xf2 "], "\x15" => [0, "\xf2%"], "\x16" => [0, "\xf2-"], "\x17" => [0, "\xf2."], "\x18" => [0, "\xf2/"], "\x19" => [0, "\xf23"], "\x1a" => [0, "\xf24"], "\x1b" => [0, "\xf25"], "\x1c" => [0, "\xf26"], "\x1d" => [0, "\xf27"], "\x1e" => [0, "\xf28"], "\x1f" => [0, "\xf29"], " " => [0, "\xf2="], "!" => [0, "\xf2A"], "\"" => [0, "\xf2_"], "#" => [0, "\xf2b"], "\$" => [0, "\xf2d"], "%" => [0, "\xf2f"], "&" => [0, "\xf2g"], "'" => [0, "\xf2h"], "(" => [0, "\xf2l"], ")" => [0, "\xf2m"], "*" => [0, "\xf2n"], "+" => [0, "\xf2p"], "," => [0, "\xf2r"], "-" => [0, "\xf2u"], "." => [100, "\xf2"], "/" => [110, "\xf2"], [111, "\xf2"], [115, "\xf2"], [116, "\xf2"], [118, "\xf2"], [119, "\xf2"], [122, "\xf2"], [123, "\xf2"], [125, "\xf2"], [126, "\xf2"], [129, "\xf2"], ":" => [143, "\xf2"], ";" => [148, "\xf2"], "<" => [151, "\xf2"], "=" => [153, "\xf2"], ">" => [83, "\xf2"], "?" => [10, "\xf2"], "@" => [77, "\xf30"], "A" => [18, "\xf30"], "B" => [77, "\xf31"], "C" => [18, "\xf31"], "D" => [77, "\xf32"], "E" => [18, "\xf32"], "F" => [77, "\xf3a"], "G" => [18, "\xf3a"], "H" => [77, "\xf3c"], "I" => [18, "\xf3c"], "J" => [77, "\xf3e"], "K" => [18, "\xf3e"], "L" => [77, "\xf3i"], "M" => [18, "\xf3i"], "N" => [77, "\xf3o"], "O" => [18, "\xf3o"], "P" => [77, "\xf3s"], "Q" => [18, "\xf3s"], "R" => [77, "\xf3t"], "S" => [18, "\xf3t"], "T" => [0, "\xf3 "], "U" => [0, "\xf3%"], "V" => [0, "\xf3-"], "W" => [0, "\xf3."], "X" => [0, "\xf3/"], "Y" => [0, "\xf33"], "Z" => [0, "\xf34"], "[" => [0, "\xf35"], "\\" => [0, "\xf36"], "]" => [0, "\xf37"], "^" => [0, "\xf38"], "_" => [0, "\xf39"], "`" => [0, "\xf3="], "a" => [0, "\xf3A"], "b" => [0, "\xf3_"], "c" => [0, "\xf3b"], "d" => [0, "\xf3d"], "e" => [0, "\xf3f"], "f" => [0, "\xf3g"], "g" => [0, "\xf3h"], "h" => [0, "\xf3l"], "i" => [0, "\xf3m"], "j" => [0, "\xf3n"], "k" => [0, "\xf3p"], "l" => [0, "\xf3r"], "m" => [0, "\xf3u"], "n" => [100, "\xf3"], "o" => [110, "\xf3"], "p" => [111, "\xf3"], "q" => [115, "\xf3"], "r" => [116, "\xf3"], "s" => [118, "\xf3"], "t" => [119, "\xf3"], "u" => [122, "\xf3"], "v" => [123, "\xf3"], "w" => [125, "\xf3"], "x" => [126, "\xf3"], "y" => [129, "\xf3"], "z" => [143, "\xf3"], "{" => [148, "\xf3"], "|" => [151, "\xf3"], "}" => [153, "\xf3"], "~" => [83, "\xf3"], "" => [10, "\xf3"], "\x80" => [77, "\xff0"], "\x81" => [18, "\xff0"], "\x82" => [77, "\xff1"], "\x83" => [18, "\xff1"], "\x84" => [77, "\xff2"], "\x85" => [18, "\xff2"], "\x86" => [77, "\xffa"], "\x87" => [18, "\xffa"], "\x88" => [77, "\xffc"], "\x89" => [18, "\xffc"], "\x8a" => [77, "\xffe"], "\x8b" => [18, "\xffe"], "\x8c" => [77, "\xffi"], "\x8d" => [18, "\xffi"], "\x8e" => [77, "\xffo"], "\x8f" => [18, "\xffo"], "\x90" => [77, "\xffs"], "\x91" => [18, "\xffs"], "\x92" => [77, "\xfft"], "\x93" => [18, "\xfft"], "\x94" => [0, "\xff "], "\x95" => [0, "\xff%"], "\x96" => [0, "\xff-"], "\x97" => [0, "\xff."], "\x98" => [0, "\xff/"], "\x99" => [0, "\xff3"], "\x9a" => [0, "\xff4"], "\x9b" => [0, "\xff5"], "\x9c" => [0, "\xff6"], "\x9d" => [0, "\xff7"], "\x9e" => [0, "\xff8"], "\x9f" => [0, "\xff9"], "\xa0" => [0, "\xff="], "\xa1" => [0, "\xffA"], "\xa2" => [0, "\xff_"], "\xa3" => [0, "\xffb"], "\xa4" => [0, "\xffd"], "\xa5" => [0, "\xfff"], "\xa6" => [0, "\xffg"], "\xa7" => [0, "\xffh"], "\xa8" => [0, "\xffl"], "\xa9" => [0, "\xffm"], "\xaa" => [0, "\xffn"], "\xab" => [0, "\xffp"], "\xac" => [0, "\xffr"], "\xad" => [0, "\xffu"], "\xae" => [100, "\xff"], "\xaf" => [110, "\xff"], "\xb0" => [111, "\xff"], "\xb1" => [115, "\xff"], "\xb2" => [116, "\xff"], "\xb3" => [118, "\xff"], "\xb4" => [119, "\xff"], "\xb5" => [122, "\xff"], "\xb6" => [123, "\xff"], "\xb7" => [125, "\xff"], "\xb8" => [126, "\xff"], "\xb9" => [129, "\xff"], "\xba" => [143, "\xff"], "\xbb" => [148, "\xff"], "\xbc" => [151, "\xff"], "\xbd" => [153, "\xff"], "\xbe" => [83, "\xff"], "\xbf" => [10, "\xff"], "\xc0" => [0, "\xcb0"], "\xc1" => [0, "\xcb1"], "\xc2" => [0, "\xcb2"], "\xc3" => [0, "\xcba"], "\xc4" => [0, "\xcbc"], "\xc5" => [0, "\xcbe"], "\xc6" => [0, "\xcbi"], "\xc7" => [0, "\xcbo"], "\xc8" => [0, "\xcbs"], "\xc9" => [0, "\xcbt"], "\xca" => [73, "\xcb"], "\xcb" => [88, "\xcb"], "\xcc" => [89, "\xcb"], "\xcd" => [96, "\xcb"], "\xce" => [97, "\xcb"], "\xcf" => [99, "\xcb"], "\xd0" => [106, "\xcb"], "\xd1" => [136, "\xcb"], "\xd2" => [139, "\xcb"], "\xd3" => [141, "\xcb"], "\xd4" => [145, "\xcb"], "\xd5" => [147, "\xcb"], "\xd6" => [149, "\xcb"], "\xd7" => [101, "\xcb"], "\xd8" => [112, "\xcb"], "\xd9" => [117, "\xcb"], "\xda" => [120, "\xcb"], "\xdb" => [124, "\xcb"], "\xdc" => [127, "\xcb"], "\xdd" => [144, "\xcb"], "\xde" => [152, "\xcb"], "\xdf" => [11, "\xcb"], "\xe0" => [0, "\xcc0"], "\xe1" => [0, "\xcc1"], "\xe2" => [0, "\xcc2"], "\xe3" => [0, "\xcca"], "\xe4" => [0, "\xccc"], "\xe5" => [0, "\xcce"], "\xe6" => [0, "\xcci"], "\xe7" => [0, "\xcco"], "\xe8" => [0, "\xccs"], "\xe9" => [0, "\xcct"], "\xea" => [73, "\xcc"], "\xeb" => [88, "\xcc"], "\xec" => [89, "\xcc"], "\xed" => [96, "\xcc"], "\xee" => [97, "\xcc"], "\xef" => [99, "\xcc"], "\xf0" => [106, "\xcc"], "\xf1" => [136, "\xcc"], "\xf2" => [139, "\xcc"], "\xf3" => [141, "\xcc"], "\xf4" => [145, "\xcc"], "\xf5" => [147, "\xcc"], "\xf6" => [149, "\xcc"], "\xf7" => [101, "\xcc"], "\xf8" => [112, "\xcc"], "\xf9" => [117, "\xcc"], "\xfa" => [120, "\xcc"], "\xfb" => [124, "\xcc"], "\xfc" => [127, "\xcc"], "\xfd" => [144, "\xcc"], "\xfe" => [152, "\xcc"], "\xff" => [11, "\xcc"]], ["\x00" => [0, "\xda0"], "\x01" => [0, "\xda1"], "\x02" => [0, "\xda2"], "\x03" => [0, "\xdaa"], "\x04" => [0, "\xdac"], "\x05" => [0, "\xdae"], "\x06" => [0, "\xdai"], "\x07" => [0, "\xdao"], "\x08" => [0, "\xdas"], "\t" => [0, "\xdat"], "\n" => [73, "\xda"], "\v" => [88, "\xda"], "\f" => [89, "\xda"], "\r" => [96, "\xda"], "\x0e" => [97, "\xda"], "\x0f" => [99, "\xda"], "\x10" => [106, "\xda"], "\x11" => [136, "\xda"], "\x12" => [139, "\xda"], "\x13" => [141, "\xda"], "\x14" => [145, "\xda"], "\x15" => [147, "\xda"], "\x16" => [149, "\xda"], "\x17" => [101, "\xda"], "\x18" => [112, "\xda"], "\x19" => [117, "\xda"], "\x1a" => [120, "\xda"], "\x1b" => [124, "\xda"], "\x1c" => [127, "\xda"], "\x1d" => [144, "\xda"], "\x1e" => [152, "\xda"], "\x1f" => [11, "\xda"], " " => [0, "\xdb0"], "!" => [0, "\xdb1"], "\"" => [0, "\xdb2"], "#" => [0, "\xdba"], "\$" => [0, "\xdbc"], "%" => [0, "\xdbe"], "&" => [0, "\xdbi"], "'" => [0, "\xdbo"], "(" => [0, "\xdbs"], ")" => [0, "\xdbt"], "*" => [73, "\xdb"], "+" => [88, "\xdb"], "," => [89, "\xdb"], "-" => [96, "\xdb"], "." => [97, "\xdb"], "/" => [99, "\xdb"], [106, "\xdb"], [136, "\xdb"], [139, "\xdb"], [141, "\xdb"], [145, "\xdb"], [147, "\xdb"], [149, "\xdb"], [101, "\xdb"], [112, "\xdb"], [117, "\xdb"], ":" => [120, "\xdb"], ";" => [124, "\xdb"], "<" => [127, "\xdb"], "=" => [144, "\xdb"], ">" => [152, "\xdb"], "?" => [11, "\xdb"], "@" => [0, "\xee0"], "A" => [0, "\xee1"], "B" => [0, "\xee2"], "C" => [0, "\xeea"], "D" => [0, "\xeec"], "E" => [0, "\xeee"], "F" => [0, "\xeei"], "G" => [0, "\xeeo"], "H" => [0, "\xees"], "I" => [0, "\xeet"], "J" => [73, "\xee"], "K" => [88, "\xee"], "L" => [89, "\xee"], "M" => [96, "\xee"], "N" => [97, "\xee"], "O" => [99, "\xee"], "P" => [106, "\xee"], "Q" => [136, "\xee"], "R" => [139, "\xee"], "S" => [141, "\xee"], "T" => [145, "\xee"], "U" => [147, "\xee"], "V" => [149, "\xee"], "W" => [101, "\xee"], "X" => [112, "\xee"], "Y" => [117, "\xee"], "Z" => [120, "\xee"], "[" => [124, "\xee"], "\\" => [127, "\xee"], "]" => [144, "\xee"], "^" => [152, "\xee"], "_" => [11, "\xee"], "`" => [0, "\xf00"], "a" => [0, "\xf01"], "b" => [0, "\xf02"], "c" => [0, "\xf0a"], "d" => [0, "\xf0c"], "e" => [0, "\xf0e"], "f" => [0, "\xf0i"], "g" => [0, "\xf0o"], "h" => [0, "\xf0s"], "i" => [0, "\xf0t"], "j" => [73, "\xf0"], "k" => [88, "\xf0"], "l" => [89, "\xf0"], "m" => [96, "\xf0"], "n" => [97, "\xf0"], "o" => [99, "\xf0"], "p" => [106, "\xf0"], "q" => [136, "\xf0"], "r" => [139, "\xf0"], "s" => [141, "\xf0"], "t" => [145, "\xf0"], "u" => [147, "\xf0"], "v" => [149, "\xf0"], "w" => [101, "\xf0"], "x" => [112, "\xf0"], "y" => [117, "\xf0"], "z" => [120, "\xf0"], "{" => [124, "\xf0"], "|" => [127, "\xf0"], "}" => [144, "\xf0"], "~" => [152, "\xf0"], "" => [11, "\xf0"], "\x80" => [0, "\xf20"], "\x81" => [0, "\xf21"], "\x82" => [0, "\xf22"], "\x83" => [0, "\xf2a"], "\x84" => [0, "\xf2c"], "\x85" => [0, "\xf2e"], "\x86" => [0, "\xf2i"], "\x87" => [0, "\xf2o"], "\x88" => [0, "\xf2s"], "\x89" => [0, "\xf2t"], "\x8a" => [73, "\xf2"], "\x8b" => [88, "\xf2"], "\x8c" => [89, "\xf2"], "\x8d" => [96, "\xf2"], "\x8e" => [97, "\xf2"], "\x8f" => [99, "\xf2"], "\x90" => [106, "\xf2"], "\x91" => [136, "\xf2"], "\x92" => [139, "\xf2"], "\x93" => [141, "\xf2"], "\x94" => [145, "\xf2"], "\x95" => [147, "\xf2"], "\x96" => [149, "\xf2"], "\x97" => [101, "\xf2"], "\x98" => [112, "\xf2"], "\x99" => [117, "\xf2"], "\x9a" => [120, "\xf2"], "\x9b" => [124, "\xf2"], "\x9c" => [127, "\xf2"], "\x9d" => [144, "\xf2"], "\x9e" => [152, "\xf2"], "\x9f" => [11, "\xf2"], "\xa0" => [0, "\xf30"], "\xa1" => [0, "\xf31"], "\xa2" => [0, "\xf32"], "\xa3" => [0, "\xf3a"], "\xa4" => [0, "\xf3c"], "\xa5" => [0, "\xf3e"], "\xa6" => [0, "\xf3i"], "\xa7" => [0, "\xf3o"], "\xa8" => [0, "\xf3s"], "\xa9" => [0, "\xf3t"], "\xaa" => [73, "\xf3"], "\xab" => [88, "\xf3"], "\xac" => [89, "\xf3"], "\xad" => [96, "\xf3"], "\xae" => [97, "\xf3"], "\xaf" => [99, "\xf3"], "\xb0" => [106, "\xf3"], "\xb1" => [136, "\xf3"], "\xb2" => [139, "\xf3"], "\xb3" => [141, "\xf3"], "\xb4" => [145, "\xf3"], "\xb5" => [147, "\xf3"], "\xb6" => [149, "\xf3"], "\xb7" => [101, "\xf3"], "\xb8" => [112, "\xf3"], "\xb9" => [117, "\xf3"], "\xba" => [120, "\xf3"], "\xbb" => [124, "\xf3"], "\xbc" => [127, "\xf3"], "\xbd" => [144, "\xf3"], "\xbe" => [152, "\xf3"], "\xbf" => [11, "\xf3"], "\xc0" => [0, "\xff0"], "\xc1" => [0, "\xff1"], "\xc2" => [0, "\xff2"], "\xc3" => [0, "\xffa"], "\xc4" => [0, "\xffc"], "\xc5" => [0, "\xffe"], "\xc6" => [0, "\xffi"], "\xc7" => [0, "\xffo"], "\xc8" => [0, "\xffs"], "\xc9" => [0, "\xfft"], "\xca" => [73, "\xff"], "\xcb" => [88, "\xff"], "\xcc" => [89, "\xff"], "\xcd" => [96, "\xff"], "\xce" => [97, "\xff"], "\xcf" => [99, "\xff"], "\xd0" => [106, "\xff"], "\xd1" => [136, "\xff"], "\xd2" => [139, "\xff"], "\xd3" => [141, "\xff"], "\xd4" => [145, "\xff"], "\xd5" => [147, "\xff"], "\xd6" => [149, "\xff"], "\xd7" => [101, "\xff"], "\xd8" => [112, "\xff"], "\xd9" => [117, "\xff"], "\xda" => [120, "\xff"], "\xdb" => [124, "\xff"], "\xdc" => [127, "\xff"], "\xdd" => [144, "\xff"], "\xde" => [152, "\xff"], "\xdf" => [11, "\xff"], "\xe0" => [92, "\xcb"], "\xe1" => [95, "\xcb"], "\xe2" => [137, "\xcb"], "\xe3" => [142, "\xcb"], "\xe4" => [150, "\xcb"], "\xe5" => [74, "\xcb"], "\xe6" => [90, "\xcb"], "\xe7" => [98, "\xcb"], "\xe8" => [107, "\xcb"], "\xe9" => [140, "\xcb"], "\xea" => [146, "\xcb"], "\xeb" => [102, "\xcb"], "\xec" => [113, "\xcb"], "\xed" => [121, "\xcb"], "\xee" => [128, "\xcb"], "\xef" => [12, "\xcb"], "\xf0" => [92, "\xcc"], "\xf1" => [95, "\xcc"], "\xf2" => [137, "\xcc"], "\xf3" => [142, "\xcc"], "\xf4" => [150, "\xcc"], "\xf5" => [74, "\xcc"], "\xf6" => [90, "\xcc"], "\xf7" => [98, "\xcc"], "\xf8" => [107, "\xcc"], "\xf9" => [140, "\xcc"], "\xfa" => [146, "\xcc"], "\xfb" => [102, "\xcc"], "\xfc" => [113, "\xcc"], "\xfd" => [121, "\xcc"], "\xfe" => [128, "\xcc"], "\xff" => [12, "\xcc"]], ["\x00" => [94, "\xcb0"], "\x01" => [76, "\xcb0"], "\x02" => [104, "\xcb0"], "\x03" => [16, "\xcb0"], "\x04" => [94, "\xcb1"], "\x05" => [76, "\xcb1"], "\x06" => [104, "\xcb1"], "\x07" => [16, "\xcb1"], "\x08" => [94, "\xcb2"], "\t" => [76, "\xcb2"], "\n" => [104, "\xcb2"], "\v" => [16, "\xcb2"], "\f" => [94, "\xcba"], "\r" => [76, "\xcba"], "\x0e" => [104, "\xcba"], "\x0f" => [16, "\xcba"], "\x10" => [94, "\xcbc"], "\x11" => [76, "\xcbc"], "\x12" => [104, "\xcbc"], "\x13" => [16, "\xcbc"], "\x14" => [94, "\xcbe"], "\x15" => [76, "\xcbe"], "\x16" => [104, "\xcbe"], "\x17" => [16, "\xcbe"], "\x18" => [94, "\xcbi"], "\x19" => [76, "\xcbi"], "\x1a" => [104, "\xcbi"], "\x1b" => [16, "\xcbi"], "\x1c" => [94, "\xcbo"], "\x1d" => [76, "\xcbo"], "\x1e" => [104, "\xcbo"], "\x1f" => [16, "\xcbo"], " " => [94, "\xcbs"], "!" => [76, "\xcbs"], "\"" => [104, "\xcbs"], "#" => [16, "\xcbs"], "\$" => [94, "\xcbt"], "%" => [76, "\xcbt"], "&" => [104, "\xcbt"], "'" => [16, "\xcbt"], "(" => [77, "\xcb "], ")" => [18, "\xcb "], "*" => [77, "\xcb%"], "+" => [18, "\xcb%"], "," => [77, "\xcb-"], "-" => [18, "\xcb-"], "." => [77, "\xcb."], "/" => [18, "\xcb."], [77, "\xcb/"], [18, "\xcb/"], [77, "\xcb3"], [18, "\xcb3"], [77, "\xcb4"], [18, "\xcb4"], [77, "\xcb5"], [18, "\xcb5"], [77, "\xcb6"], [18, "\xcb6"], ":" => [77, "\xcb7"], ";" => [18, "\xcb7"], "<" => [77, "\xcb8"], "=" => [18, "\xcb8"], ">" => [77, "\xcb9"], "?" => [18, "\xcb9"], "@" => [77, "\xcb="], "A" => [18, "\xcb="], "B" => [77, "\xcbA"], "C" => [18, "\xcbA"], "D" => [77, "\xcb_"], "E" => [18, "\xcb_"], "F" => [77, "\xcbb"], "G" => [18, "\xcbb"], "H" => [77, "\xcbd"], "I" => [18, "\xcbd"], "J" => [77, "\xcbf"], "K" => [18, "\xcbf"], "L" => [77, "\xcbg"], "M" => [18, "\xcbg"], "N" => [77, "\xcbh"], "O" => [18, "\xcbh"], "P" => [77, "\xcbl"], "Q" => [18, "\xcbl"], "R" => [77, "\xcbm"], "S" => [18, "\xcbm"], "T" => [77, "\xcbn"], "U" => [18, "\xcbn"], "V" => [77, "\xcbp"], "W" => [18, "\xcbp"], "X" => [77, "\xcbr"], "Y" => [18, "\xcbr"], "Z" => [77, "\xcbu"], "[" => [18, "\xcbu"], "\\" => [0, "\xcb:"], "]" => [0, "\xcbB"], "^" => [0, "\xcbC"], "_" => [0, "\xcbD"], "`" => [0, "\xcbE"], "a" => [0, "\xcbF"], "b" => [0, "\xcbG"], "c" => [0, "\xcbH"], "d" => [0, "\xcbI"], "e" => [0, "\xcbJ"], "f" => [0, "\xcbK"], "g" => [0, "\xcbL"], "h" => [0, "\xcbM"], "i" => [0, "\xcbN"], "j" => [0, "\xcbO"], "k" => [0, "\xcbP"], "l" => [0, "\xcbQ"], "m" => [0, "\xcbR"], "n" => [0, "\xcbS"], "o" => [0, "\xcbT"], "p" => [0, "\xcbU"], "q" => [0, "\xcbV"], "r" => [0, "\xcbW"], "s" => [0, "\xcbY"], "t" => [0, "\xcbj"], "u" => [0, "\xcbk"], "v" => [0, "\xcbq"], "w" => [0, "\xcbv"], "x" => [0, "\xcbw"], "y" => [0, "\xcbx"], "z" => [0, "\xcby"], "{" => [0, "\xcbz"], "|" => [82, "\xcb"], "}" => [87, "\xcb"], "~" => [130, "\xcb"], "" => [9, "\xcb"], "\x80" => [94, "\xcc0"], "\x81" => [76, "\xcc0"], "\x82" => [104, "\xcc0"], "\x83" => [16, "\xcc0"], "\x84" => [94, "\xcc1"], "\x85" => [76, "\xcc1"], "\x86" => [104, "\xcc1"], "\x87" => [16, "\xcc1"], "\x88" => [94, "\xcc2"], "\x89" => [76, "\xcc2"], "\x8a" => [104, "\xcc2"], "\x8b" => [16, "\xcc2"], "\x8c" => [94, "\xcca"], "\x8d" => [76, "\xcca"], "\x8e" => [104, "\xcca"], "\x8f" => [16, "\xcca"], "\x90" => [94, "\xccc"], "\x91" => [76, "\xccc"], "\x92" => [104, "\xccc"], "\x93" => [16, "\xccc"], "\x94" => [94, "\xcce"], "\x95" => [76, "\xcce"], "\x96" => [104, "\xcce"], "\x97" => [16, "\xcce"], "\x98" => [94, "\xcci"], "\x99" => [76, "\xcci"], "\x9a" => [104, "\xcci"], "\x9b" => [16, "\xcci"], "\x9c" => [94, "\xcco"], "\x9d" => [76, "\xcco"], "\x9e" => [104, "\xcco"], "\x9f" => [16, "\xcco"], "\xa0" => [94, "\xccs"], "\xa1" => [76, "\xccs"], "\xa2" => [104, "\xccs"], "\xa3" => [16, "\xccs"], "\xa4" => [94, "\xcct"], "\xa5" => [76, "\xcct"], "\xa6" => [104, "\xcct"], "\xa7" => [16, "\xcct"], "\xa8" => [77, "\xcc "], "\xa9" => [18, "\xcc "], "\xaa" => [77, "\xcc%"], "\xab" => [18, "\xcc%"], "\xac" => [77, "\xcc-"], "\xad" => [18, "\xcc-"], "\xae" => [77, "\xcc."], "\xaf" => [18, "\xcc."], "\xb0" => [77, "\xcc/"], "\xb1" => [18, "\xcc/"], "\xb2" => [77, "\xcc3"], "\xb3" => [18, "\xcc3"], "\xb4" => [77, "\xcc4"], "\xb5" => [18, "\xcc4"], "\xb6" => [77, "\xcc5"], "\xb7" => [18, "\xcc5"], "\xb8" => [77, "\xcc6"], "\xb9" => [18, "\xcc6"], "\xba" => [77, "\xcc7"], "\xbb" => [18, "\xcc7"], "\xbc" => [77, "\xcc8"], "\xbd" => [18, "\xcc8"], "\xbe" => [77, "\xcc9"], "\xbf" => [18, "\xcc9"], "\xc0" => [77, "\xcc="], "\xc1" => [18, "\xcc="], "\xc2" => [77, "\xccA"], "\xc3" => [18, "\xccA"], "\xc4" => [77, "\xcc_"], "\xc5" => [18, "\xcc_"], "\xc6" => [77, "\xccb"], "\xc7" => [18, "\xccb"], "\xc8" => [77, "\xccd"], "\xc9" => [18, "\xccd"], "\xca" => [77, "\xccf"], "\xcb" => [18, "\xccf"], "\xcc" => [77, "\xccg"], "\xcd" => [18, "\xccg"], "\xce" => [77, "\xcch"], "\xcf" => [18, "\xcch"], "\xd0" => [77, "\xccl"], "\xd1" => [18, "\xccl"], "\xd2" => [77, "\xccm"], "\xd3" => [18, "\xccm"], "\xd4" => [77, "\xccn"], "\xd5" => [18, "\xccn"], "\xd6" => [77, "\xccp"], "\xd7" => [18, "\xccp"], "\xd8" => [77, "\xccr"], "\xd9" => [18, "\xccr"], "\xda" => [77, "\xccu"], "\xdb" => [18, "\xccu"], "\xdc" => [0, "\xcc:"], "\xdd" => [0, "\xccB"], "\xde" => [0, "\xccC"], "\xdf" => [0, "\xccD"], "\xe0" => [0, "\xccE"], "\xe1" => [0, "\xccF"], "\xe2" => [0, "\xccG"], "\xe3" => [0, "\xccH"], "\xe4" => [0, "\xccI"], "\xe5" => [0, "\xccJ"], "\xe6" => [0, "\xccK"], "\xe7" => [0, "\xccL"], "\xe8" => [0, "\xccM"], "\xe9" => [0, "\xccN"], "\xea" => [0, "\xccO"], "\xeb" => [0, "\xccP"], "\xec" => [0, "\xccQ"], "\xed" => [0, "\xccR"], "\xee" => [0, "\xccS"], "\xef" => [0, "\xccT"], "\xf0" => [0, "\xccU"], "\xf1" => [0, "\xccV"], "\xf2" => [0, "\xccW"], "\xf3" => [0, "\xccY"], "\xf4" => [0, "\xccj"], "\xf5" => [0, "\xcck"], "\xf6" => [0, "\xccq"], "\xf7" => [0, "\xccv"], "\xf8" => [0, "\xccw"], "\xf9" => [0, "\xccx"], "\xfa" => [0, "\xccy"], "\xfb" => [0, "\xccz"], "\xfc" => [82, "\xcc"], "\xfd" => [87, "\xcc"], "\xfe" => [130, "\xcc"], "\xff" => [9, "\xcc"]], ["\x00" => [94, "\xff0"], "\x01" => [76, "\xff0"], "\x02" => [104, "\xff0"], "\x03" => [16, "\xff0"], "\x04" => [94, "\xff1"], "\x05" => [76, "\xff1"], "\x06" => [104, "\xff1"], "\x07" => [16, "\xff1"], "\x08" => [94, "\xff2"], "\t" => [76, "\xff2"], "\n" => [104, "\xff2"], "\v" => [16, "\xff2"], "\f" => [94, "\xffa"], "\r" => [76, "\xffa"], "\x0e" => [104, "\xffa"], "\x0f" => [16, "\xffa"], "\x10" => [94, "\xffc"], "\x11" => [76, "\xffc"], "\x12" => [104, "\xffc"], "\x13" => [16, "\xffc"], "\x14" => [94, "\xffe"], "\x15" => [76, "\xffe"], "\x16" => [104, "\xffe"], "\x17" => [16, "\xffe"], "\x18" => [94, "\xffi"], "\x19" => [76, "\xffi"], "\x1a" => [104, "\xffi"], "\x1b" => [16, "\xffi"], "\x1c" => [94, "\xffo"], "\x1d" => [76, "\xffo"], "\x1e" => [104, "\xffo"], "\x1f" => [16, "\xffo"], " " => [94, "\xffs"], "!" => [76, "\xffs"], "\"" => [104, "\xffs"], "#" => [16, "\xffs"], "\$" => [94, "\xfft"], "%" => [76, "\xfft"], "&" => [104, "\xfft"], "'" => [16, "\xfft"], "(" => [77, "\xff "], ")" => [18, "\xff "], "*" => [77, "\xff%"], "+" => [18, "\xff%"], "," => [77, "\xff-"], "-" => [18, "\xff-"], "." => [77, "\xff."], "/" => [18, "\xff."], [77, "\xff/"], [18, "\xff/"], [77, "\xff3"], [18, "\xff3"], [77, "\xff4"], [18, "\xff4"], [77, "\xff5"], [18, "\xff5"], [77, "\xff6"], [18, "\xff6"], ":" => [77, "\xff7"], ";" => [18, "\xff7"], "<" => [77, "\xff8"], "=" => [18, "\xff8"], ">" => [77, "\xff9"], "?" => [18, "\xff9"], "@" => [77, "\xff="], "A" => [18, "\xff="], "B" => [77, "\xffA"], "C" => [18, "\xffA"], "D" => [77, "\xff_"], "E" => [18, "\xff_"], "F" => [77, "\xffb"], "G" => [18, "\xffb"], "H" => [77, "\xffd"], "I" => [18, "\xffd"], "J" => [77, "\xfff"], "K" => [18, "\xfff"], "L" => [77, "\xffg"], "M" => [18, "\xffg"], "N" => [77, "\xffh"], "O" => [18, "\xffh"], "P" => [77, "\xffl"], "Q" => [18, "\xffl"], "R" => [77, "\xffm"], "S" => [18, "\xffm"], "T" => [77, "\xffn"], "U" => [18, "\xffn"], "V" => [77, "\xffp"], "W" => [18, "\xffp"], "X" => [77, "\xffr"], "Y" => [18, "\xffr"], "Z" => [77, "\xffu"], "[" => [18, "\xffu"], "\\" => [0, "\xff:"], "]" => [0, "\xffB"], "^" => [0, "\xffC"], "_" => [0, "\xffD"], "`" => [0, "\xffE"], "a" => [0, "\xffF"], "b" => [0, "\xffG"], "c" => [0, "\xffH"], "d" => [0, "\xffI"], "e" => [0, "\xffJ"], "f" => [0, "\xffK"], "g" => [0, "\xffL"], "h" => [0, "\xffM"], "i" => [0, "\xffN"], "j" => [0, "\xffO"], "k" => [0, "\xffP"], "l" => [0, "\xffQ"], "m" => [0, "\xffR"], "n" => [0, "\xffS"], "o" => [0, "\xffT"], "p" => [0, "\xffU"], "q" => [0, "\xffV"], "r" => [0, "\xffW"], "s" => [0, "\xffY"], "t" => [0, "\xffj"], "u" => [0, "\xffk"], "v" => [0, "\xffq"], "w" => [0, "\xffv"], "x" => [0, "\xffw"], "y" => [0, "\xffx"], "z" => [0, "\xffy"], "{" => [0, "\xffz"], "|" => [82, "\xff"], "}" => [87, "\xff"], "~" => [130, "\xff"], "" => [9, "\xff"], "\x80" => [77, "\xcb0"], "\x81" => [18, "\xcb0"], "\x82" => [77, "\xcb1"], "\x83" => [18, "\xcb1"], "\x84" => [77, "\xcb2"], "\x85" => [18, "\xcb2"], "\x86" => [77, "\xcba"], "\x87" => [18, "\xcba"], "\x88" => [77, "\xcbc"], "\x89" => [18, "\xcbc"], "\x8a" => [77, "\xcbe"], "\x8b" => [18, "\xcbe"], "\x8c" => [77, "\xcbi"], "\x8d" => [18, "\xcbi"], "\x8e" => [77, "\xcbo"], "\x8f" => [18, "\xcbo"], "\x90" => [77, "\xcbs"], "\x91" => [18, "\xcbs"], "\x92" => [77, "\xcbt"], "\x93" => [18, "\xcbt"], "\x94" => [0, "\xcb "], "\x95" => [0, "\xcb%"], "\x96" => [0, "\xcb-"], "\x97" => [0, "\xcb."], "\x98" => [0, "\xcb/"], "\x99" => [0, "\xcb3"], "\x9a" => [0, "\xcb4"], "\x9b" => [0, "\xcb5"], "\x9c" => [0, "\xcb6"], "\x9d" => [0, "\xcb7"], "\x9e" => [0, "\xcb8"], "\x9f" => [0, "\xcb9"], "\xa0" => [0, "\xcb="], "\xa1" => [0, "\xcbA"], "\xa2" => [0, "\xcb_"], "\xa3" => [0, "\xcbb"], "\xa4" => [0, "\xcbd"], "\xa5" => [0, "\xcbf"], "\xa6" => [0, "\xcbg"], "\xa7" => [0, "\xcbh"], "\xa8" => [0, "\xcbl"], "\xa9" => [0, "\xcbm"], "\xaa" => [0, "\xcbn"], "\xab" => [0, "\xcbp"], "\xac" => [0, "\xcbr"], "\xad" => [0, "\xcbu"], "\xae" => [100, "\xcb"], "\xaf" => [110, "\xcb"], "\xb0" => [111, "\xcb"], "\xb1" => [115, "\xcb"], "\xb2" => [116, "\xcb"], "\xb3" => [118, "\xcb"], "\xb4" => [119, "\xcb"], "\xb5" => [122, "\xcb"], "\xb6" => [123, "\xcb"], "\xb7" => [125, "\xcb"], "\xb8" => [126, "\xcb"], "\xb9" => [129, "\xcb"], "\xba" => [143, "\xcb"], "\xbb" => [148, "\xcb"], "\xbc" => [151, "\xcb"], "\xbd" => [153, "\xcb"], "\xbe" => [83, "\xcb"], "\xbf" => [10, "\xcb"], "\xc0" => [77, "\xcc0"], "\xc1" => [18, "\xcc0"], "\xc2" => [77, "\xcc1"], "\xc3" => [18, "\xcc1"], "\xc4" => [77, "\xcc2"], "\xc5" => [18, "\xcc2"], "\xc6" => [77, "\xcca"], "\xc7" => [18, "\xcca"], "\xc8" => [77, "\xccc"], "\xc9" => [18, "\xccc"], "\xca" => [77, "\xcce"], "\xcb" => [18, "\xcce"], "\xcc" => [77, "\xcci"], "\xcd" => [18, "\xcci"], "\xce" => [77, "\xcco"], "\xcf" => [18, "\xcco"], "\xd0" => [77, "\xccs"], "\xd1" => [18, "\xccs"], "\xd2" => [77, "\xcct"], "\xd3" => [18, "\xcct"], "\xd4" => [0, "\xcc "], "\xd5" => [0, "\xcc%"], "\xd6" => [0, "\xcc-"], "\xd7" => [0, "\xcc."], "\xd8" => [0, "\xcc/"], "\xd9" => [0, "\xcc3"], "\xda" => [0, "\xcc4"], "\xdb" => [0, "\xcc5"], "\xdc" => [0, "\xcc6"], "\xdd" => [0, "\xcc7"], "\xde" => [0, "\xcc8"], "\xdf" => [0, "\xcc9"], "\xe0" => [0, "\xcc="], "\xe1" => [0, "\xccA"], "\xe2" => [0, "\xcc_"], "\xe3" => [0, "\xccb"], "\xe4" => [0, "\xccd"], "\xe5" => [0, "\xccf"], "\xe6" => [0, "\xccg"], "\xe7" => [0, "\xcch"], "\xe8" => [0, "\xccl"], "\xe9" => [0, "\xccm"], "\xea" => [0, "\xccn"], "\xeb" => [0, "\xccp"], "\xec" => [0, "\xccr"], "\xed" => [0, "\xccu"], "\xee" => [100, "\xcc"], "\xef" => [110, "\xcc"], "\xf0" => [111, "\xcc"], "\xf1" => [115, "\xcc"], "\xf2" => [116, "\xcc"], "\xf3" => [118, "\xcc"], "\xf4" => [119, "\xcc"], "\xf5" => [122, "\xcc"], "\xf6" => [123, "\xcc"], "\xf7" => [125, "\xcc"], "\xf8" => [126, "\xcc"], "\xf9" => [129, "\xcc"], "\xfa" => [143, "\xcc"], "\xfb" => [148, "\xcc"], "\xfc" => [151, "\xcc"], "\xfd" => [153, "\xcc"], "\xfe" => [83, "\xcc"], "\xff" => [10, "\xcc"]], ["\x00" => [94, "\xd20"], "\x01" => [76, "\xd20"], "\x02" => [104, "\xd20"], "\x03" => [16, "\xd20"], "\x04" => [94, "\xd21"], "\x05" => [76, "\xd21"], "\x06" => [104, "\xd21"], "\x07" => [16, "\xd21"], "\x08" => [94, "\xd22"], "\t" => [76, "\xd22"], "\n" => [104, "\xd22"], "\v" => [16, "\xd22"], "\f" => [94, "\xd2a"], "\r" => [76, "\xd2a"], "\x0e" => [104, "\xd2a"], "\x0f" => [16, "\xd2a"], "\x10" => [94, "\xd2c"], "\x11" => [76, "\xd2c"], "\x12" => [104, "\xd2c"], "\x13" => [16, "\xd2c"], "\x14" => [94, "\xd2e"], "\x15" => [76, "\xd2e"], "\x16" => [104, "\xd2e"], "\x17" => [16, "\xd2e"], "\x18" => [94, "\xd2i"], "\x19" => [76, "\xd2i"], "\x1a" => [104, "\xd2i"], "\x1b" => [16, "\xd2i"], "\x1c" => [94, "\xd2o"], "\x1d" => [76, "\xd2o"], "\x1e" => [104, "\xd2o"], "\x1f" => [16, "\xd2o"], " " => [94, "\xd2s"], "!" => [76, "\xd2s"], "\"" => [104, "\xd2s"], "#" => [16, "\xd2s"], "\$" => [94, "\xd2t"], "%" => [76, "\xd2t"], "&" => [104, "\xd2t"], "'" => [16, "\xd2t"], "(" => [77, "\xd2 "], ")" => [18, "\xd2 "], "*" => [77, "\xd2%"], "+" => [18, "\xd2%"], "," => [77, "\xd2-"], "-" => [18, "\xd2-"], "." => [77, "\xd2."], "/" => [18, "\xd2."], [77, "\xd2/"], [18, "\xd2/"], [77, "\xd23"], [18, "\xd23"], [77, "\xd24"], [18, "\xd24"], [77, "\xd25"], [18, "\xd25"], [77, "\xd26"], [18, "\xd26"], ":" => [77, "\xd27"], ";" => [18, "\xd27"], "<" => [77, "\xd28"], "=" => [18, "\xd28"], ">" => [77, "\xd29"], "?" => [18, "\xd29"], "@" => [77, "\xd2="], "A" => [18, "\xd2="], "B" => [77, "\xd2A"], "C" => [18, "\xd2A"], "D" => [77, "\xd2_"], "E" => [18, "\xd2_"], "F" => [77, "\xd2b"], "G" => [18, "\xd2b"], "H" => [77, "\xd2d"], "I" => [18, "\xd2d"], "J" => [77, "\xd2f"], "K" => [18, "\xd2f"], "L" => [77, "\xd2g"], "M" => [18, "\xd2g"], "N" => [77, "\xd2h"], "O" => [18, "\xd2h"], "P" => [77, "\xd2l"], "Q" => [18, "\xd2l"], "R" => [77, "\xd2m"], "S" => [18, "\xd2m"], "T" => [77, "\xd2n"], "U" => [18, "\xd2n"], "V" => [77, "\xd2p"], "W" => [18, "\xd2p"], "X" => [77, "\xd2r"], "Y" => [18, "\xd2r"], "Z" => [77, "\xd2u"], "[" => [18, "\xd2u"], "\\" => [0, "\xd2:"], "]" => [0, "\xd2B"], "^" => [0, "\xd2C"], "_" => [0, "\xd2D"], "`" => [0, "\xd2E"], "a" => [0, "\xd2F"], "b" => [0, "\xd2G"], "c" => [0, "\xd2H"], "d" => [0, "\xd2I"], "e" => [0, "\xd2J"], "f" => [0, "\xd2K"], "g" => [0, "\xd2L"], "h" => [0, "\xd2M"], "i" => [0, "\xd2N"], "j" => [0, "\xd2O"], "k" => [0, "\xd2P"], "l" => [0, "\xd2Q"], "m" => [0, "\xd2R"], "n" => [0, "\xd2S"], "o" => [0, "\xd2T"], "p" => [0, "\xd2U"], "q" => [0, "\xd2V"], "r" => [0, "\xd2W"], "s" => [0, "\xd2Y"], "t" => [0, "\xd2j"], "u" => [0, "\xd2k"], "v" => [0, "\xd2q"], "w" => [0, "\xd2v"], "x" => [0, "\xd2w"], "y" => [0, "\xd2x"], "z" => [0, "\xd2y"], "{" => [0, "\xd2z"], "|" => [82, "\xd2"], "}" => [87, "\xd2"], "~" => [130, "\xd2"], "" => [9, "\xd2"], "\x80" => [94, "\xd50"], "\x81" => [76, "\xd50"], "\x82" => [104, "\xd50"], "\x83" => [16, "\xd50"], "\x84" => [94, "\xd51"], "\x85" => [76, "\xd51"], "\x86" => [104, "\xd51"], "\x87" => [16, "\xd51"], "\x88" => [94, "\xd52"], "\x89" => [76, "\xd52"], "\x8a" => [104, "\xd52"], "\x8b" => [16, "\xd52"], "\x8c" => [94, "\xd5a"], "\x8d" => [76, "\xd5a"], "\x8e" => [104, "\xd5a"], "\x8f" => [16, "\xd5a"], "\x90" => [94, "\xd5c"], "\x91" => [76, "\xd5c"], "\x92" => [104, "\xd5c"], "\x93" => [16, "\xd5c"], "\x94" => [94, "\xd5e"], "\x95" => [76, "\xd5e"], "\x96" => [104, "\xd5e"], "\x97" => [16, "\xd5e"], "\x98" => [94, "\xd5i"], "\x99" => [76, "\xd5i"], "\x9a" => [104, "\xd5i"], "\x9b" => [16, "\xd5i"], "\x9c" => [94, "\xd5o"], "\x9d" => [76, "\xd5o"], "\x9e" => [104, "\xd5o"], "\x9f" => [16, "\xd5o"], "\xa0" => [94, "\xd5s"], "\xa1" => [76, "\xd5s"], "\xa2" => [104, "\xd5s"], "\xa3" => [16, "\xd5s"], "\xa4" => [94, "\xd5t"], "\xa5" => [76, "\xd5t"], "\xa6" => [104, "\xd5t"], "\xa7" => [16, "\xd5t"], "\xa8" => [77, "\xd5 "], "\xa9" => [18, "\xd5 "], "\xaa" => [77, "\xd5%"], "\xab" => [18, "\xd5%"], "\xac" => [77, "\xd5-"], "\xad" => [18, "\xd5-"], "\xae" => [77, "\xd5."], "\xaf" => [18, "\xd5."], "\xb0" => [77, "\xd5/"], "\xb1" => [18, "\xd5/"], "\xb2" => [77, "\xd53"], "\xb3" => [18, "\xd53"], "\xb4" => [77, "\xd54"], "\xb5" => [18, "\xd54"], "\xb6" => [77, "\xd55"], "\xb7" => [18, "\xd55"], "\xb8" => [77, "\xd56"], "\xb9" => [18, "\xd56"], "\xba" => [77, "\xd57"], "\xbb" => [18, "\xd57"], "\xbc" => [77, "\xd58"], "\xbd" => [18, "\xd58"], "\xbe" => [77, "\xd59"], "\xbf" => [18, "\xd59"], "\xc0" => [77, "\xd5="], "\xc1" => [18, "\xd5="], "\xc2" => [77, "\xd5A"], "\xc3" => [18, "\xd5A"], "\xc4" => [77, "\xd5_"], "\xc5" => [18, "\xd5_"], "\xc6" => [77, "\xd5b"], "\xc7" => [18, "\xd5b"], "\xc8" => [77, "\xd5d"], "\xc9" => [18, "\xd5d"], "\xca" => [77, "\xd5f"], "\xcb" => [18, "\xd5f"], "\xcc" => [77, "\xd5g"], "\xcd" => [18, "\xd5g"], "\xce" => [77, "\xd5h"], "\xcf" => [18, "\xd5h"], "\xd0" => [77, "\xd5l"], "\xd1" => [18, "\xd5l"], "\xd2" => [77, "\xd5m"], "\xd3" => [18, "\xd5m"], "\xd4" => [77, "\xd5n"], "\xd5" => [18, "\xd5n"], "\xd6" => [77, "\xd5p"], "\xd7" => [18, "\xd5p"], "\xd8" => [77, "\xd5r"], "\xd9" => [18, "\xd5r"], "\xda" => [77, "\xd5u"], "\xdb" => [18, "\xd5u"], "\xdc" => [0, "\xd5:"], "\xdd" => [0, "\xd5B"], "\xde" => [0, "\xd5C"], "\xdf" => [0, "\xd5D"], "\xe0" => [0, "\xd5E"], "\xe1" => [0, "\xd5F"], "\xe2" => [0, "\xd5G"], "\xe3" => [0, "\xd5H"], "\xe4" => [0, "\xd5I"], "\xe5" => [0, "\xd5J"], "\xe6" => [0, "\xd5K"], "\xe7" => [0, "\xd5L"], "\xe8" => [0, "\xd5M"], "\xe9" => [0, "\xd5N"], "\xea" => [0, "\xd5O"], "\xeb" => [0, "\xd5P"], "\xec" => [0, "\xd5Q"], "\xed" => [0, "\xd5R"], "\xee" => [0, "\xd5S"], "\xef" => [0, "\xd5T"], "\xf0" => [0, "\xd5U"], "\xf1" => [0, "\xd5V"], "\xf2" => [0, "\xd5W"], "\xf3" => [0, "\xd5Y"], "\xf4" => [0, "\xd5j"], "\xf5" => [0, "\xd5k"], "\xf6" => [0, "\xd5q"], "\xf7" => [0, "\xd5v"], "\xf8" => [0, "\xd5w"], "\xf9" => [0, "\xd5x"], "\xfa" => [0, "\xd5y"], "\xfb" => [0, "\xd5z"], "\xfc" => [82, "\xd5"], "\xfd" => [87, "\xd5"], "\xfe" => [130, "\xd5"], "\xff" => [9, "\xd5"]], ["\x00" => [0, "\xd30"], "\x01" => [0, "\xd31"], "\x02" => [0, "\xd32"], "\x03" => [0, "\xd3a"], "\x04" => [0, "\xd3c"], "\x05" => [0, "\xd3e"], "\x06" => [0, "\xd3i"], "\x07" => [0, "\xd3o"], "\x08" => [0, "\xd3s"], "\t" => [0, "\xd3t"], "\n" => [73, "\xd3"], "\v" => [88, "\xd3"], "\f" => [89, "\xd3"], "\r" => [96, "\xd3"], "\x0e" => [97, "\xd3"], "\x0f" => [99, "\xd3"], "\x10" => [106, "\xd3"], "\x11" => [136, "\xd3"], "\x12" => [139, "\xd3"], "\x13" => [141, "\xd3"], "\x14" => [145, "\xd3"], "\x15" => [147, "\xd3"], "\x16" => [149, "\xd3"], "\x17" => [101, "\xd3"], "\x18" => [112, "\xd3"], "\x19" => [117, "\xd3"], "\x1a" => [120, "\xd3"], "\x1b" => [124, "\xd3"], "\x1c" => [127, "\xd3"], "\x1d" => [144, "\xd3"], "\x1e" => [152, "\xd3"], "\x1f" => [11, "\xd3"], " " => [0, "\xd40"], "!" => [0, "\xd41"], "\"" => [0, "\xd42"], "#" => [0, "\xd4a"], "\$" => [0, "\xd4c"], "%" => [0, "\xd4e"], "&" => [0, "\xd4i"], "'" => [0, "\xd4o"], "(" => [0, "\xd4s"], ")" => [0, "\xd4t"], "*" => [73, "\xd4"], "+" => [88, "\xd4"], "," => [89, "\xd4"], "-" => [96, "\xd4"], "." => [97, "\xd4"], "/" => [99, "\xd4"], [106, "\xd4"], [136, "\xd4"], [139, "\xd4"], [141, "\xd4"], [145, "\xd4"], [147, "\xd4"], [149, "\xd4"], [101, "\xd4"], [112, "\xd4"], [117, "\xd4"], ":" => [120, "\xd4"], ";" => [124, "\xd4"], "<" => [127, "\xd4"], "=" => [144, "\xd4"], ">" => [152, "\xd4"], "?" => [11, "\xd4"], "@" => [0, "\xd60"], "A" => [0, "\xd61"], "B" => [0, "\xd62"], "C" => [0, "\xd6a"], "D" => [0, "\xd6c"], "E" => [0, "\xd6e"], "F" => [0, "\xd6i"], "G" => [0, "\xd6o"], "H" => [0, "\xd6s"], "I" => [0, "\xd6t"], "J" => [73, "\xd6"], "K" => [88, "\xd6"], "L" => [89, "\xd6"], "M" => [96, "\xd6"], "N" => [97, "\xd6"], "O" => [99, "\xd6"], "P" => [106, "\xd6"], "Q" => [136, "\xd6"], "R" => [139, "\xd6"], "S" => [141, "\xd6"], "T" => [145, "\xd6"], "U" => [147, "\xd6"], "V" => [149, "\xd6"], "W" => [101, "\xd6"], "X" => [112, "\xd6"], "Y" => [117, "\xd6"], "Z" => [120, "\xd6"], "[" => [124, "\xd6"], "\\" => [127, "\xd6"], "]" => [144, "\xd6"], "^" => [152, "\xd6"], "_" => [11, "\xd6"], "`" => [0, "\xdd0"], "a" => [0, "\xdd1"], "b" => [0, "\xdd2"], "c" => [0, "\xdda"], "d" => [0, "\xddc"], "e" => [0, "\xdde"], "f" => [0, "\xddi"], "g" => [0, "\xddo"], "h" => [0, "\xdds"], "i" => [0, "\xddt"], "j" => [73, "\xdd"], "k" => [88, "\xdd"], "l" => [89, "\xdd"], "m" => [96, "\xdd"], "n" => [97, "\xdd"], "o" => [99, "\xdd"], "p" => [106, "\xdd"], "q" => [136, "\xdd"], "r" => [139, "\xdd"], "s" => [141, "\xdd"], "t" => [145, "\xdd"], "u" => [147, "\xdd"], "v" => [149, "\xdd"], "w" => [101, "\xdd"], "x" => [112, "\xdd"], "y" => [117, "\xdd"], "z" => [120, "\xdd"], "{" => [124, "\xdd"], "|" => [127, "\xdd"], "}" => [144, "\xdd"], "~" => [152, "\xdd"], "" => [11, "\xdd"], "\x80" => [0, "\xde0"], "\x81" => [0, "\xde1"], "\x82" => [0, "\xde2"], "\x83" => [0, "\xdea"], "\x84" => [0, "\xdec"], "\x85" => [0, "\xdee"], "\x86" => [0, "\xdei"], "\x87" => [0, "\xdeo"], "\x88" => [0, "\xdes"], "\x89" => [0, "\xdet"], "\x8a" => [73, "\xde"], "\x8b" => [88, "\xde"], "\x8c" => [89, "\xde"], "\x8d" => [96, "\xde"], "\x8e" => [97, "\xde"], "\x8f" => [99, "\xde"], "\x90" => [106, "\xde"], "\x91" => [136, "\xde"], "\x92" => [139, "\xde"], "\x93" => [141, "\xde"], "\x94" => [145, "\xde"], "\x95" => [147, "\xde"], "\x96" => [149, "\xde"], "\x97" => [101, "\xde"], "\x98" => [112, "\xde"], "\x99" => [117, "\xde"], "\x9a" => [120, "\xde"], "\x9b" => [124, "\xde"], "\x9c" => [127, "\xde"], "\x9d" => [144, "\xde"], "\x9e" => [152, "\xde"], "\x9f" => [11, "\xde"], "\xa0" => [0, "\xdf0"], "\xa1" => [0, "\xdf1"], "\xa2" => [0, "\xdf2"], "\xa3" => [0, "\xdfa"], "\xa4" => [0, "\xdfc"], "\xa5" => [0, "\xdfe"], "\xa6" => [0, "\xdfi"], "\xa7" => [0, "\xdfo"], "\xa8" => [0, "\xdfs"], "\xa9" => [0, "\xdft"], "\xaa" => [73, "\xdf"], "\xab" => [88, "\xdf"], "\xac" => [89, "\xdf"], "\xad" => [96, "\xdf"], "\xae" => [97, "\xdf"], "\xaf" => [99, "\xdf"], "\xb0" => [106, "\xdf"], "\xb1" => [136, "\xdf"], "\xb2" => [139, "\xdf"], "\xb3" => [141, "\xdf"], "\xb4" => [145, "\xdf"], "\xb5" => [147, "\xdf"], "\xb6" => [149, "\xdf"], "\xb7" => [101, "\xdf"], "\xb8" => [112, "\xdf"], "\xb9" => [117, "\xdf"], "\xba" => [120, "\xdf"], "\xbb" => [124, "\xdf"], "\xbc" => [127, "\xdf"], "\xbd" => [144, "\xdf"], "\xbe" => [152, "\xdf"], "\xbf" => [11, "\xdf"], "\xc0" => [0, "\xf10"], "\xc1" => [0, "\xf11"], "\xc2" => [0, "\xf12"], "\xc3" => [0, "\xf1a"], "\xc4" => [0, "\xf1c"], "\xc5" => [0, "\xf1e"], "\xc6" => [0, "\xf1i"], "\xc7" => [0, "\xf1o"], "\xc8" => [0, "\xf1s"], "\xc9" => [0, "\xf1t"], "\xca" => [73, "\xf1"], "\xcb" => [88, "\xf1"], "\xcc" => [89, "\xf1"], "\xcd" => [96, "\xf1"], "\xce" => [97, "\xf1"], "\xcf" => [99, "\xf1"], "\xd0" => [106, "\xf1"], "\xd1" => [136, "\xf1"], "\xd2" => [139, "\xf1"], "\xd3" => [141, "\xf1"], "\xd4" => [145, "\xf1"], "\xd5" => [147, "\xf1"], "\xd6" => [149, "\xf1"], "\xd7" => [101, "\xf1"], "\xd8" => [112, "\xf1"], "\xd9" => [117, "\xf1"], "\xda" => [120, "\xf1"], "\xdb" => [124, "\xf1"], "\xdc" => [127, "\xf1"], "\xdd" => [144, "\xf1"], "\xde" => [152, "\xf1"], "\xdf" => [11, "\xf1"], "\xe0" => [0, "\xf40"], "\xe1" => [0, "\xf41"], "\xe2" => [0, "\xf42"], "\xe3" => [0, "\xf4a"], "\xe4" => [0, "\xf4c"], "\xe5" => [0, "\xf4e"], "\xe6" => [0, "\xf4i"], "\xe7" => [0, "\xf4o"], "\xe8" => [0, "\xf4s"], "\xe9" => [0, "\xf4t"], "\xea" => [73, "\xf4"], "\xeb" => [88, "\xf4"], "\xec" => [89, "\xf4"], "\xed" => [96, "\xf4"], "\xee" => [97, "\xf4"], "\xef" => [99, "\xf4"], "\xf0" => [106, "\xf4"], "\xf1" => [136, "\xf4"], "\xf2" => [139, "\xf4"], "\xf3" => [141, "\xf4"], "\xf4" => [145, "\xf4"], "\xf5" => [147, "\xf4"], "\xf6" => [149, "\xf4"], "\xf7" => [101, "\xf4"], "\xf8" => [112, "\xf4"], "\xf9" => [117, "\xf4"], "\xfa" => [120, "\xf4"], "\xfb" => [124, "\xf4"], "\xfc" => [127, "\xf4"], "\xfd" => [144, "\xf4"], "\xfe" => [152, "\xf4"], "\xff" => [11, "\xf4"]], ["\x00" => [92, "\xd3"], "\x01" => [95, "\xd3"], "\x02" => [137, "\xd3"], "\x03" => [142, "\xd3"], "\x04" => [150, "\xd3"], "\x05" => [74, "\xd3"], "\x06" => [90, "\xd3"], "\x07" => [98, "\xd3"], "\x08" => [107, "\xd3"], "\t" => [140, "\xd3"], "\n" => [146, "\xd3"], "\v" => [102, "\xd3"], "\f" => [113, "\xd3"], "\r" => [121, "\xd3"], "\x0e" => [128, "\xd3"], "\x0f" => [12, "\xd3"], "\x10" => [92, "\xd4"], "\x11" => [95, "\xd4"], "\x12" => [137, "\xd4"], "\x13" => [142, "\xd4"], "\x14" => [150, "\xd4"], "\x15" => [74, "\xd4"], "\x16" => [90, "\xd4"], "\x17" => [98, "\xd4"], "\x18" => [107, "\xd4"], "\x19" => [140, "\xd4"], "\x1a" => [146, "\xd4"], "\x1b" => [102, "\xd4"], "\x1c" => [113, "\xd4"], "\x1d" => [121, "\xd4"], "\x1e" => [128, "\xd4"], "\x1f" => [12, "\xd4"], " " => [92, "\xd6"], "!" => [95, "\xd6"], "\"" => [137, "\xd6"], "#" => [142, "\xd6"], "\$" => [150, "\xd6"], "%" => [74, "\xd6"], "&" => [90, "\xd6"], "'" => [98, "\xd6"], "(" => [107, "\xd6"], ")" => [140, "\xd6"], "*" => [146, "\xd6"], "+" => [102, "\xd6"], "," => [113, "\xd6"], "-" => [121, "\xd6"], "." => [128, "\xd6"], "/" => [12, "\xd6"], [92, "\xdd"], [95, "\xdd"], [137, "\xdd"], [142, "\xdd"], [150, "\xdd"], [74, "\xdd"], [90, "\xdd"], [98, "\xdd"], [107, "\xdd"], [140, "\xdd"], ":" => [146, "\xdd"], ";" => [102, "\xdd"], "<" => [113, "\xdd"], "=" => [121, "\xdd"], ">" => [128, "\xdd"], "?" => [12, "\xdd"], "@" => [92, "\xde"], "A" => [95, "\xde"], "B" => [137, "\xde"], "C" => [142, "\xde"], "D" => [150, "\xde"], "E" => [74, "\xde"], "F" => [90, "\xde"], "G" => [98, "\xde"], "H" => [107, "\xde"], "I" => [140, "\xde"], "J" => [146, "\xde"], "K" => [102, "\xde"], "L" => [113, "\xde"], "M" => [121, "\xde"], "N" => [128, "\xde"], "O" => [12, "\xde"], "P" => [92, "\xdf"], "Q" => [95, "\xdf"], "R" => [137, "\xdf"], "S" => [142, "\xdf"], "T" => [150, "\xdf"], "U" => [74, "\xdf"], "V" => [90, "\xdf"], "W" => [98, "\xdf"], "X" => [107, "\xdf"], "Y" => [140, "\xdf"], "Z" => [146, "\xdf"], "[" => [102, "\xdf"], "\\" => [113, "\xdf"], "]" => [121, "\xdf"], "^" => [128, "\xdf"], "_" => [12, "\xdf"], "`" => [92, "\xf1"], "a" => [95, "\xf1"], "b" => [137, "\xf1"], "c" => [142, "\xf1"], "d" => [150, "\xf1"], "e" => [74, "\xf1"], "f" => [90, "\xf1"], "g" => [98, "\xf1"], "h" => [107, "\xf1"], "i" => [140, "\xf1"], "j" => [146, "\xf1"], "k" => [102, "\xf1"], "l" => [113, "\xf1"], "m" => [121, "\xf1"], "n" => [128, "\xf1"], "o" => [12, "\xf1"], "p" => [92, "\xf4"], "q" => [95, "\xf4"], "r" => [137, "\xf4"], "s" => [142, "\xf4"], "t" => [150, "\xf4"], "u" => [74, "\xf4"], "v" => [90, "\xf4"], "w" => [98, "\xf4"], "x" => [107, "\xf4"], "y" => [140, "\xf4"], "z" => [146, "\xf4"], "{" => [102, "\xf4"], "|" => [113, "\xf4"], "}" => [121, "\xf4"], "~" => [128, "\xf4"], "" => [12, "\xf4"], "\x80" => [92, "\xf5"], "\x81" => [95, "\xf5"], "\x82" => [137, "\xf5"], "\x83" => [142, "\xf5"], "\x84" => [150, "\xf5"], "\x85" => [74, "\xf5"], "\x86" => [90, "\xf5"], "\x87" => [98, "\xf5"], "\x88" => [107, "\xf5"], "\x89" => [140, "\xf5"], "\x8a" => [146, "\xf5"], "\x8b" => [102, "\xf5"], "\x8c" => [113, "\xf5"], "\x8d" => [121, "\xf5"], "\x8e" => [128, "\xf5"], "\x8f" => [12, "\xf5"], "\x90" => [92, "\xf6"], "\x91" => [95, "\xf6"], "\x92" => [137, "\xf6"], "\x93" => [142, "\xf6"], "\x94" => [150, "\xf6"], "\x95" => [74, "\xf6"], "\x96" => [90, "\xf6"], "\x97" => [98, "\xf6"], "\x98" => [107, "\xf6"], "\x99" => [140, "\xf6"], "\x9a" => [146, "\xf6"], "\x9b" => [102, "\xf6"], "\x9c" => [113, "\xf6"], "\x9d" => [121, "\xf6"], "\x9e" => [128, "\xf6"], "\x9f" => [12, "\xf6"], "\xa0" => [92, "\xf7"], "\xa1" => [95, "\xf7"], "\xa2" => [137, "\xf7"], "\xa3" => [142, "\xf7"], "\xa4" => [150, "\xf7"], "\xa5" => [74, "\xf7"], "\xa6" => [90, "\xf7"], "\xa7" => [98, "\xf7"], "\xa8" => [107, "\xf7"], "\xa9" => [140, "\xf7"], "\xaa" => [146, "\xf7"], "\xab" => [102, "\xf7"], "\xac" => [113, "\xf7"], "\xad" => [121, "\xf7"], "\xae" => [128, "\xf7"], "\xaf" => [12, "\xf7"], "\xb0" => [92, "\xf8"], "\xb1" => [95, "\xf8"], "\xb2" => [137, "\xf8"], "\xb3" => [142, "\xf8"], "\xb4" => [150, "\xf8"], "\xb5" => [74, "\xf8"], "\xb6" => [90, "\xf8"], "\xb7" => [98, "\xf8"], "\xb8" => [107, "\xf8"], "\xb9" => [140, "\xf8"], "\xba" => [146, "\xf8"], "\xbb" => [102, "\xf8"], "\xbc" => [113, "\xf8"], "\xbd" => [121, "\xf8"], "\xbe" => [128, "\xf8"], "\xbf" => [12, "\xf8"], "\xc0" => [92, "\xfa"], "\xc1" => [95, "\xfa"], "\xc2" => [137, "\xfa"], "\xc3" => [142, "\xfa"], "\xc4" => [150, "\xfa"], "\xc5" => [74, "\xfa"], "\xc6" => [90, "\xfa"], "\xc7" => [98, "\xfa"], "\xc8" => [107, "\xfa"], "\xc9" => [140, "\xfa"], "\xca" => [146, "\xfa"], "\xcb" => [102, "\xfa"], "\xcc" => [113, "\xfa"], "\xcd" => [121, "\xfa"], "\xce" => [128, "\xfa"], "\xcf" => [12, "\xfa"], "\xd0" => [92, "\xfb"], "\xd1" => [95, "\xfb"], "\xd2" => [137, "\xfb"], "\xd3" => [142, "\xfb"], "\xd4" => [150, "\xfb"], "\xd5" => [74, "\xfb"], "\xd6" => [90, "\xfb"], "\xd7" => [98, "\xfb"], "\xd8" => [107, "\xfb"], "\xd9" => [140, "\xfb"], "\xda" => [146, "\xfb"], "\xdb" => [102, "\xfb"], "\xdc" => [113, "\xfb"], "\xdd" => [121, "\xfb"], "\xde" => [128, "\xfb"], "\xdf" => [12, "\xfb"], "\xe0" => [92, "\xfc"], "\xe1" => [95, "\xfc"], "\xe2" => [137, "\xfc"], "\xe3" => [142, "\xfc"], "\xe4" => [150, "\xfc"], "\xe5" => [74, "\xfc"], "\xe6" => [90, "\xfc"], "\xe7" => [98, "\xfc"], "\xe8" => [107, "\xfc"], "\xe9" => [140, "\xfc"], "\xea" => [146, "\xfc"], "\xeb" => [102, "\xfc"], "\xec" => [113, "\xfc"], "\xed" => [121, "\xfc"], "\xee" => [128, "\xfc"], "\xef" => [12, "\xfc"], "\xf0" => [92, "\xfd"], "\xf1" => [95, "\xfd"], "\xf2" => [137, "\xfd"], "\xf3" => [142, "\xfd"], "\xf4" => [150, "\xfd"], "\xf5" => [74, "\xfd"], "\xf6" => [90, "\xfd"], "\xf7" => [98, "\xfd"], "\xf8" => [107, "\xfd"], "\xf9" => [140, "\xfd"], "\xfa" => [146, "\xfd"], "\xfb" => [102, "\xfd"], "\xfc" => [113, "\xfd"], "\xfd" => [121, "\xfd"], "\xfe" => [128, "\xfd"], "\xff" => [12, "\xfd"]], ["\x00" => [94, "\xd30"], "\x01" => [76, "\xd30"], "\x02" => [104, "\xd30"], "\x03" => [16, "\xd30"], "\x04" => [94, "\xd31"], "\x05" => [76, "\xd31"], "\x06" => [104, "\xd31"], "\x07" => [16, "\xd31"], "\x08" => [94, "\xd32"], "\t" => [76, "\xd32"], "\n" => [104, "\xd32"], "\v" => [16, "\xd32"], "\f" => [94, "\xd3a"], "\r" => [76, "\xd3a"], "\x0e" => [104, "\xd3a"], "\x0f" => [16, "\xd3a"], "\x10" => [94, "\xd3c"], "\x11" => [76, "\xd3c"], "\x12" => [104, "\xd3c"], "\x13" => [16, "\xd3c"], "\x14" => [94, "\xd3e"], "\x15" => [76, "\xd3e"], "\x16" => [104, "\xd3e"], "\x17" => [16, "\xd3e"], "\x18" => [94, "\xd3i"], "\x19" => [76, "\xd3i"], "\x1a" => [104, "\xd3i"], "\x1b" => [16, "\xd3i"], "\x1c" => [94, "\xd3o"], "\x1d" => [76, "\xd3o"], "\x1e" => [104, "\xd3o"], "\x1f" => [16, "\xd3o"], " " => [94, "\xd3s"], "!" => [76, "\xd3s"], "\"" => [104, "\xd3s"], "#" => [16, "\xd3s"], "\$" => [94, "\xd3t"], "%" => [76, "\xd3t"], "&" => [104, "\xd3t"], "'" => [16, "\xd3t"], "(" => [77, "\xd3 "], ")" => [18, "\xd3 "], "*" => [77, "\xd3%"], "+" => [18, "\xd3%"], "," => [77, "\xd3-"], "-" => [18, "\xd3-"], "." => [77, "\xd3."], "/" => [18, "\xd3."], [77, "\xd3/"], [18, "\xd3/"], [77, "\xd33"], [18, "\xd33"], [77, "\xd34"], [18, "\xd34"], [77, "\xd35"], [18, "\xd35"], [77, "\xd36"], [18, "\xd36"], ":" => [77, "\xd37"], ";" => [18, "\xd37"], "<" => [77, "\xd38"], "=" => [18, "\xd38"], ">" => [77, "\xd39"], "?" => [18, "\xd39"], "@" => [77, "\xd3="], "A" => [18, "\xd3="], "B" => [77, "\xd3A"], "C" => [18, "\xd3A"], "D" => [77, "\xd3_"], "E" => [18, "\xd3_"], "F" => [77, "\xd3b"], "G" => [18, "\xd3b"], "H" => [77, "\xd3d"], "I" => [18, "\xd3d"], "J" => [77, "\xd3f"], "K" => [18, "\xd3f"], "L" => [77, "\xd3g"], "M" => [18, "\xd3g"], "N" => [77, "\xd3h"], "O" => [18, "\xd3h"], "P" => [77, "\xd3l"], "Q" => [18, "\xd3l"], "R" => [77, "\xd3m"], "S" => [18, "\xd3m"], "T" => [77, "\xd3n"], "U" => [18, "\xd3n"], "V" => [77, "\xd3p"], "W" => [18, "\xd3p"], "X" => [77, "\xd3r"], "Y" => [18, "\xd3r"], "Z" => [77, "\xd3u"], "[" => [18, "\xd3u"], "\\" => [0, "\xd3:"], "]" => [0, "\xd3B"], "^" => [0, "\xd3C"], "_" => [0, "\xd3D"], "`" => [0, "\xd3E"], "a" => [0, "\xd3F"], "b" => [0, "\xd3G"], "c" => [0, "\xd3H"], "d" => [0, "\xd3I"], "e" => [0, "\xd3J"], "f" => [0, "\xd3K"], "g" => [0, "\xd3L"], "h" => [0, "\xd3M"], "i" => [0, "\xd3N"], "j" => [0, "\xd3O"], "k" => [0, "\xd3P"], "l" => [0, "\xd3Q"], "m" => [0, "\xd3R"], "n" => [0, "\xd3S"], "o" => [0, "\xd3T"], "p" => [0, "\xd3U"], "q" => [0, "\xd3V"], "r" => [0, "\xd3W"], "s" => [0, "\xd3Y"], "t" => [0, "\xd3j"], "u" => [0, "\xd3k"], "v" => [0, "\xd3q"], "w" => [0, "\xd3v"], "x" => [0, "\xd3w"], "y" => [0, "\xd3x"], "z" => [0, "\xd3y"], "{" => [0, "\xd3z"], "|" => [82, "\xd3"], "}" => [87, "\xd3"], "~" => [130, "\xd3"], "" => [9, "\xd3"], "\x80" => [94, "\xd40"], "\x81" => [76, "\xd40"], "\x82" => [104, "\xd40"], "\x83" => [16, "\xd40"], "\x84" => [94, "\xd41"], "\x85" => [76, "\xd41"], "\x86" => [104, "\xd41"], "\x87" => [16, "\xd41"], "\x88" => [94, "\xd42"], "\x89" => [76, "\xd42"], "\x8a" => [104, "\xd42"], "\x8b" => [16, "\xd42"], "\x8c" => [94, "\xd4a"], "\x8d" => [76, "\xd4a"], "\x8e" => [104, "\xd4a"], "\x8f" => [16, "\xd4a"], "\x90" => [94, "\xd4c"], "\x91" => [76, "\xd4c"], "\x92" => [104, "\xd4c"], "\x93" => [16, "\xd4c"], "\x94" => [94, "\xd4e"], "\x95" => [76, "\xd4e"], "\x96" => [104, "\xd4e"], "\x97" => [16, "\xd4e"], "\x98" => [94, "\xd4i"], "\x99" => [76, "\xd4i"], "\x9a" => [104, "\xd4i"], "\x9b" => [16, "\xd4i"], "\x9c" => [94, "\xd4o"], "\x9d" => [76, "\xd4o"], "\x9e" => [104, "\xd4o"], "\x9f" => [16, "\xd4o"], "\xa0" => [94, "\xd4s"], "\xa1" => [76, "\xd4s"], "\xa2" => [104, "\xd4s"], "\xa3" => [16, "\xd4s"], "\xa4" => [94, "\xd4t"], "\xa5" => [76, "\xd4t"], "\xa6" => [104, "\xd4t"], "\xa7" => [16, "\xd4t"], "\xa8" => [77, "\xd4 "], "\xa9" => [18, "\xd4 "], "\xaa" => [77, "\xd4%"], "\xab" => [18, "\xd4%"], "\xac" => [77, "\xd4-"], "\xad" => [18, "\xd4-"], "\xae" => [77, "\xd4."], "\xaf" => [18, "\xd4."], "\xb0" => [77, "\xd4/"], "\xb1" => [18, "\xd4/"], "\xb2" => [77, "\xd43"], "\xb3" => [18, "\xd43"], "\xb4" => [77, "\xd44"], "\xb5" => [18, "\xd44"], "\xb6" => [77, "\xd45"], "\xb7" => [18, "\xd45"], "\xb8" => [77, "\xd46"], "\xb9" => [18, "\xd46"], "\xba" => [77, "\xd47"], "\xbb" => [18, "\xd47"], "\xbc" => [77, "\xd48"], "\xbd" => [18, "\xd48"], "\xbe" => [77, "\xd49"], "\xbf" => [18, "\xd49"], "\xc0" => [77, "\xd4="], "\xc1" => [18, "\xd4="], "\xc2" => [77, "\xd4A"], "\xc3" => [18, "\xd4A"], "\xc4" => [77, "\xd4_"], "\xc5" => [18, "\xd4_"], "\xc6" => [77, "\xd4b"], "\xc7" => [18, "\xd4b"], "\xc8" => [77, "\xd4d"], "\xc9" => [18, "\xd4d"], "\xca" => [77, "\xd4f"], "\xcb" => [18, "\xd4f"], "\xcc" => [77, "\xd4g"], "\xcd" => [18, "\xd4g"], "\xce" => [77, "\xd4h"], "\xcf" => [18, "\xd4h"], "\xd0" => [77, "\xd4l"], "\xd1" => [18, "\xd4l"], "\xd2" => [77, "\xd4m"], "\xd3" => [18, "\xd4m"], "\xd4" => [77, "\xd4n"], "\xd5" => [18, "\xd4n"], "\xd6" => [77, "\xd4p"], "\xd7" => [18, "\xd4p"], "\xd8" => [77, "\xd4r"], "\xd9" => [18, "\xd4r"], "\xda" => [77, "\xd4u"], "\xdb" => [18, "\xd4u"], "\xdc" => [0, "\xd4:"], "\xdd" => [0, "\xd4B"], "\xde" => [0, "\xd4C"], "\xdf" => [0, "\xd4D"], "\xe0" => [0, "\xd4E"], "\xe1" => [0, "\xd4F"], "\xe2" => [0, "\xd4G"], "\xe3" => [0, "\xd4H"], "\xe4" => [0, "\xd4I"], "\xe5" => [0, "\xd4J"], "\xe6" => [0, "\xd4K"], "\xe7" => [0, "\xd4L"], "\xe8" => [0, "\xd4M"], "\xe9" => [0, "\xd4N"], "\xea" => [0, "\xd4O"], "\xeb" => [0, "\xd4P"], "\xec" => [0, "\xd4Q"], "\xed" => [0, "\xd4R"], "\xee" => [0, "\xd4S"], "\xef" => [0, "\xd4T"], "\xf0" => [0, "\xd4U"], "\xf1" => [0, "\xd4V"], "\xf2" => [0, "\xd4W"], "\xf3" => [0, "\xd4Y"], "\xf4" => [0, "\xd4j"], "\xf5" => [0, "\xd4k"], "\xf6" => [0, "\xd4q"], "\xf7" => [0, "\xd4v"], "\xf8" => [0, "\xd4w"], "\xf9" => [0, "\xd4x"], "\xfa" => [0, "\xd4y"], "\xfb" => [0, "\xd4z"], "\xfc" => [82, "\xd4"], "\xfd" => [87, "\xd4"], "\xfe" => [130, "\xd4"], "\xff" => [9, "\xd4"]], ["\x00" => [77, "\xd30"], "\x01" => [18, "\xd30"], "\x02" => [77, "\xd31"], "\x03" => [18, "\xd31"], "\x04" => [77, "\xd32"], "\x05" => [18, "\xd32"], "\x06" => [77, "\xd3a"], "\x07" => [18, "\xd3a"], "\x08" => [77, "\xd3c"], "\t" => [18, "\xd3c"], "\n" => [77, "\xd3e"], "\v" => [18, "\xd3e"], "\f" => [77, "\xd3i"], "\r" => [18, "\xd3i"], "\x0e" => [77, "\xd3o"], "\x0f" => [18, "\xd3o"], "\x10" => [77, "\xd3s"], "\x11" => [18, "\xd3s"], "\x12" => [77, "\xd3t"], "\x13" => [18, "\xd3t"], "\x14" => [0, "\xd3 "], "\x15" => [0, "\xd3%"], "\x16" => [0, "\xd3-"], "\x17" => [0, "\xd3."], "\x18" => [0, "\xd3/"], "\x19" => [0, "\xd33"], "\x1a" => [0, "\xd34"], "\x1b" => [0, "\xd35"], "\x1c" => [0, "\xd36"], "\x1d" => [0, "\xd37"], "\x1e" => [0, "\xd38"], "\x1f" => [0, "\xd39"], " " => [0, "\xd3="], "!" => [0, "\xd3A"], "\"" => [0, "\xd3_"], "#" => [0, "\xd3b"], "\$" => [0, "\xd3d"], "%" => [0, "\xd3f"], "&" => [0, "\xd3g"], "'" => [0, "\xd3h"], "(" => [0, "\xd3l"], ")" => [0, "\xd3m"], "*" => [0, "\xd3n"], "+" => [0, "\xd3p"], "," => [0, "\xd3r"], "-" => [0, "\xd3u"], "." => [100, "\xd3"], "/" => [110, "\xd3"], [111, "\xd3"], [115, "\xd3"], [116, "\xd3"], [118, "\xd3"], [119, "\xd3"], [122, "\xd3"], [123, "\xd3"], [125, "\xd3"], [126, "\xd3"], [129, "\xd3"], ":" => [143, "\xd3"], ";" => [148, "\xd3"], "<" => [151, "\xd3"], "=" => [153, "\xd3"], ">" => [83, "\xd3"], "?" => [10, "\xd3"], "@" => [77, "\xd40"], "A" => [18, "\xd40"], "B" => [77, "\xd41"], "C" => [18, "\xd41"], "D" => [77, "\xd42"], "E" => [18, "\xd42"], "F" => [77, "\xd4a"], "G" => [18, "\xd4a"], "H" => [77, "\xd4c"], "I" => [18, "\xd4c"], "J" => [77, "\xd4e"], "K" => [18, "\xd4e"], "L" => [77, "\xd4i"], "M" => [18, "\xd4i"], "N" => [77, "\xd4o"], "O" => [18, "\xd4o"], "P" => [77, "\xd4s"], "Q" => [18, "\xd4s"], "R" => [77, "\xd4t"], "S" => [18, "\xd4t"], "T" => [0, "\xd4 "], "U" => [0, "\xd4%"], "V" => [0, "\xd4-"], "W" => [0, "\xd4."], "X" => [0, "\xd4/"], "Y" => [0, "\xd43"], "Z" => [0, "\xd44"], "[" => [0, "\xd45"], "\\" => [0, "\xd46"], "]" => [0, "\xd47"], "^" => [0, "\xd48"], "_" => [0, "\xd49"], "`" => [0, "\xd4="], "a" => [0, "\xd4A"], "b" => [0, "\xd4_"], "c" => [0, "\xd4b"], "d" => [0, "\xd4d"], "e" => [0, "\xd4f"], "f" => [0, "\xd4g"], "g" => [0, "\xd4h"], "h" => [0, "\xd4l"], "i" => [0, "\xd4m"], "j" => [0, "\xd4n"], "k" => [0, "\xd4p"], "l" => [0, "\xd4r"], "m" => [0, "\xd4u"], "n" => [100, "\xd4"], "o" => [110, "\xd4"], "p" => [111, "\xd4"], "q" => [115, "\xd4"], "r" => [116, "\xd4"], "s" => [118, "\xd4"], "t" => [119, "\xd4"], "u" => [122, "\xd4"], "v" => [123, "\xd4"], "w" => [125, "\xd4"], "x" => [126, "\xd4"], "y" => [129, "\xd4"], "z" => [143, "\xd4"], "{" => [148, "\xd4"], "|" => [151, "\xd4"], "}" => [153, "\xd4"], "~" => [83, "\xd4"], "" => [10, "\xd4"], "\x80" => [77, "\xd60"], "\x81" => [18, "\xd60"], "\x82" => [77, "\xd61"], "\x83" => [18, "\xd61"], "\x84" => [77, "\xd62"], "\x85" => [18, "\xd62"], "\x86" => [77, "\xd6a"], "\x87" => [18, "\xd6a"], "\x88" => [77, "\xd6c"], "\x89" => [18, "\xd6c"], "\x8a" => [77, "\xd6e"], "\x8b" => [18, "\xd6e"], "\x8c" => [77, "\xd6i"], "\x8d" => [18, "\xd6i"], "\x8e" => [77, "\xd6o"], "\x8f" => [18, "\xd6o"], "\x90" => [77, "\xd6s"], "\x91" => [18, "\xd6s"], "\x92" => [77, "\xd6t"], "\x93" => [18, "\xd6t"], "\x94" => [0, "\xd6 "], "\x95" => [0, "\xd6%"], "\x96" => [0, "\xd6-"], "\x97" => [0, "\xd6."], "\x98" => [0, "\xd6/"], "\x99" => [0, "\xd63"], "\x9a" => [0, "\xd64"], "\x9b" => [0, "\xd65"], "\x9c" => [0, "\xd66"], "\x9d" => [0, "\xd67"], "\x9e" => [0, "\xd68"], "\x9f" => [0, "\xd69"], "\xa0" => [0, "\xd6="], "\xa1" => [0, "\xd6A"], "\xa2" => [0, "\xd6_"], "\xa3" => [0, "\xd6b"], "\xa4" => [0, "\xd6d"], "\xa5" => [0, "\xd6f"], "\xa6" => [0, "\xd6g"], "\xa7" => [0, "\xd6h"], "\xa8" => [0, "\xd6l"], "\xa9" => [0, "\xd6m"], "\xaa" => [0, "\xd6n"], "\xab" => [0, "\xd6p"], "\xac" => [0, "\xd6r"], "\xad" => [0, "\xd6u"], "\xae" => [100, "\xd6"], "\xaf" => [110, "\xd6"], "\xb0" => [111, "\xd6"], "\xb1" => [115, "\xd6"], "\xb2" => [116, "\xd6"], "\xb3" => [118, "\xd6"], "\xb4" => [119, "\xd6"], "\xb5" => [122, "\xd6"], "\xb6" => [123, "\xd6"], "\xb7" => [125, "\xd6"], "\xb8" => [126, "\xd6"], "\xb9" => [129, "\xd6"], "\xba" => [143, "\xd6"], "\xbb" => [148, "\xd6"], "\xbc" => [151, "\xd6"], "\xbd" => [153, "\xd6"], "\xbe" => [83, "\xd6"], "\xbf" => [10, "\xd6"], "\xc0" => [77, "\xdd0"], "\xc1" => [18, "\xdd0"], "\xc2" => [77, "\xdd1"], "\xc3" => [18, "\xdd1"], "\xc4" => [77, "\xdd2"], "\xc5" => [18, "\xdd2"], "\xc6" => [77, "\xdda"], "\xc7" => [18, "\xdda"], "\xc8" => [77, "\xddc"], "\xc9" => [18, "\xddc"], "\xca" => [77, "\xdde"], "\xcb" => [18, "\xdde"], "\xcc" => [77, "\xddi"], "\xcd" => [18, "\xddi"], "\xce" => [77, "\xddo"], "\xcf" => [18, "\xddo"], "\xd0" => [77, "\xdds"], "\xd1" => [18, "\xdds"], "\xd2" => [77, "\xddt"], "\xd3" => [18, "\xddt"], "\xd4" => [0, "\xdd "], "\xd5" => [0, "\xdd%"], "\xd6" => [0, "\xdd-"], "\xd7" => [0, "\xdd."], "\xd8" => [0, "\xdd/"], "\xd9" => [0, "\xdd3"], "\xda" => [0, "\xdd4"], "\xdb" => [0, "\xdd5"], "\xdc" => [0, "\xdd6"], "\xdd" => [0, "\xdd7"], "\xde" => [0, "\xdd8"], "\xdf" => [0, "\xdd9"], "\xe0" => [0, "\xdd="], "\xe1" => [0, "\xddA"], "\xe2" => [0, "\xdd_"], "\xe3" => [0, "\xddb"], "\xe4" => [0, "\xddd"], "\xe5" => [0, "\xddf"], "\xe6" => [0, "\xddg"], "\xe7" => [0, "\xddh"], "\xe8" => [0, "\xddl"], "\xe9" => [0, "\xddm"], "\xea" => [0, "\xddn"], "\xeb" => [0, "\xddp"], "\xec" => [0, "\xddr"], "\xed" => [0, "\xddu"], "\xee" => [100, "\xdd"], "\xef" => [110, "\xdd"], "\xf0" => [111, "\xdd"], "\xf1" => [115, "\xdd"], "\xf2" => [116, "\xdd"], "\xf3" => [118, "\xdd"], "\xf4" => [119, "\xdd"], "\xf5" => [122, "\xdd"], "\xf6" => [123, "\xdd"], "\xf7" => [125, "\xdd"], "\xf8" => [126, "\xdd"], "\xf9" => [129, "\xdd"], "\xfa" => [143, "\xdd"], "\xfb" => [148, "\xdd"], "\xfc" => [151, "\xdd"], "\xfd" => [153, "\xdd"], "\xfe" => [83, "\xdd"], "\xff" => [10, "\xdd"]], ["\x00" => [94, "\xd60"], "\x01" => [76, "\xd60"], "\x02" => [104, "\xd60"], "\x03" => [16, "\xd60"], "\x04" => [94, "\xd61"], "\x05" => [76, "\xd61"], "\x06" => [104, "\xd61"], "\x07" => [16, "\xd61"], "\x08" => [94, "\xd62"], "\t" => [76, "\xd62"], "\n" => [104, "\xd62"], "\v" => [16, "\xd62"], "\f" => [94, "\xd6a"], "\r" => [76, "\xd6a"], "\x0e" => [104, "\xd6a"], "\x0f" => [16, "\xd6a"], "\x10" => [94, "\xd6c"], "\x11" => [76, "\xd6c"], "\x12" => [104, "\xd6c"], "\x13" => [16, "\xd6c"], "\x14" => [94, "\xd6e"], "\x15" => [76, "\xd6e"], "\x16" => [104, "\xd6e"], "\x17" => [16, "\xd6e"], "\x18" => [94, "\xd6i"], "\x19" => [76, "\xd6i"], "\x1a" => [104, "\xd6i"], "\x1b" => [16, "\xd6i"], "\x1c" => [94, "\xd6o"], "\x1d" => [76, "\xd6o"], "\x1e" => [104, "\xd6o"], "\x1f" => [16, "\xd6o"], " " => [94, "\xd6s"], "!" => [76, "\xd6s"], "\"" => [104, "\xd6s"], "#" => [16, "\xd6s"], "\$" => [94, "\xd6t"], "%" => [76, "\xd6t"], "&" => [104, "\xd6t"], "'" => [16, "\xd6t"], "(" => [77, "\xd6 "], ")" => [18, "\xd6 "], "*" => [77, "\xd6%"], "+" => [18, "\xd6%"], "," => [77, "\xd6-"], "-" => [18, "\xd6-"], "." => [77, "\xd6."], "/" => [18, "\xd6."], [77, "\xd6/"], [18, "\xd6/"], [77, "\xd63"], [18, "\xd63"], [77, "\xd64"], [18, "\xd64"], [77, "\xd65"], [18, "\xd65"], [77, "\xd66"], [18, "\xd66"], ":" => [77, "\xd67"], ";" => [18, "\xd67"], "<" => [77, "\xd68"], "=" => [18, "\xd68"], ">" => [77, "\xd69"], "?" => [18, "\xd69"], "@" => [77, "\xd6="], "A" => [18, "\xd6="], "B" => [77, "\xd6A"], "C" => [18, "\xd6A"], "D" => [77, "\xd6_"], "E" => [18, "\xd6_"], "F" => [77, "\xd6b"], "G" => [18, "\xd6b"], "H" => [77, "\xd6d"], "I" => [18, "\xd6d"], "J" => [77, "\xd6f"], "K" => [18, "\xd6f"], "L" => [77, "\xd6g"], "M" => [18, "\xd6g"], "N" => [77, "\xd6h"], "O" => [18, "\xd6h"], "P" => [77, "\xd6l"], "Q" => [18, "\xd6l"], "R" => [77, "\xd6m"], "S" => [18, "\xd6m"], "T" => [77, "\xd6n"], "U" => [18, "\xd6n"], "V" => [77, "\xd6p"], "W" => [18, "\xd6p"], "X" => [77, "\xd6r"], "Y" => [18, "\xd6r"], "Z" => [77, "\xd6u"], "[" => [18, "\xd6u"], "\\" => [0, "\xd6:"], "]" => [0, "\xd6B"], "^" => [0, "\xd6C"], "_" => [0, "\xd6D"], "`" => [0, "\xd6E"], "a" => [0, "\xd6F"], "b" => [0, "\xd6G"], "c" => [0, "\xd6H"], "d" => [0, "\xd6I"], "e" => [0, "\xd6J"], "f" => [0, "\xd6K"], "g" => [0, "\xd6L"], "h" => [0, "\xd6M"], "i" => [0, "\xd6N"], "j" => [0, "\xd6O"], "k" => [0, "\xd6P"], "l" => [0, "\xd6Q"], "m" => [0, "\xd6R"], "n" => [0, "\xd6S"], "o" => [0, "\xd6T"], "p" => [0, "\xd6U"], "q" => [0, "\xd6V"], "r" => [0, "\xd6W"], "s" => [0, "\xd6Y"], "t" => [0, "\xd6j"], "u" => [0, "\xd6k"], "v" => [0, "\xd6q"], "w" => [0, "\xd6v"], "x" => [0, "\xd6w"], "y" => [0, "\xd6x"], "z" => [0, "\xd6y"], "{" => [0, "\xd6z"], "|" => [82, "\xd6"], "}" => [87, "\xd6"], "~" => [130, "\xd6"], "" => [9, "\xd6"], "\x80" => [94, "\xdd0"], "\x81" => [76, "\xdd0"], "\x82" => [104, "\xdd0"], "\x83" => [16, "\xdd0"], "\x84" => [94, "\xdd1"], "\x85" => [76, "\xdd1"], "\x86" => [104, "\xdd1"], "\x87" => [16, "\xdd1"], "\x88" => [94, "\xdd2"], "\x89" => [76, "\xdd2"], "\x8a" => [104, "\xdd2"], "\x8b" => [16, "\xdd2"], "\x8c" => [94, "\xdda"], "\x8d" => [76, "\xdda"], "\x8e" => [104, "\xdda"], "\x8f" => [16, "\xdda"], "\x90" => [94, "\xddc"], "\x91" => [76, "\xddc"], "\x92" => [104, "\xddc"], "\x93" => [16, "\xddc"], "\x94" => [94, "\xdde"], "\x95" => [76, "\xdde"], "\x96" => [104, "\xdde"], "\x97" => [16, "\xdde"], "\x98" => [94, "\xddi"], "\x99" => [76, "\xddi"], "\x9a" => [104, "\xddi"], "\x9b" => [16, "\xddi"], "\x9c" => [94, "\xddo"], "\x9d" => [76, "\xddo"], "\x9e" => [104, "\xddo"], "\x9f" => [16, "\xddo"], "\xa0" => [94, "\xdds"], "\xa1" => [76, "\xdds"], "\xa2" => [104, "\xdds"], "\xa3" => [16, "\xdds"], "\xa4" => [94, "\xddt"], "\xa5" => [76, "\xddt"], "\xa6" => [104, "\xddt"], "\xa7" => [16, "\xddt"], "\xa8" => [77, "\xdd "], "\xa9" => [18, "\xdd "], "\xaa" => [77, "\xdd%"], "\xab" => [18, "\xdd%"], "\xac" => [77, "\xdd-"], "\xad" => [18, "\xdd-"], "\xae" => [77, "\xdd."], "\xaf" => [18, "\xdd."], "\xb0" => [77, "\xdd/"], "\xb1" => [18, "\xdd/"], "\xb2" => [77, "\xdd3"], "\xb3" => [18, "\xdd3"], "\xb4" => [77, "\xdd4"], "\xb5" => [18, "\xdd4"], "\xb6" => [77, "\xdd5"], "\xb7" => [18, "\xdd5"], "\xb8" => [77, "\xdd6"], "\xb9" => [18, "\xdd6"], "\xba" => [77, "\xdd7"], "\xbb" => [18, "\xdd7"], "\xbc" => [77, "\xdd8"], "\xbd" => [18, "\xdd8"], "\xbe" => [77, "\xdd9"], "\xbf" => [18, "\xdd9"], "\xc0" => [77, "\xdd="], "\xc1" => [18, "\xdd="], "\xc2" => [77, "\xddA"], "\xc3" => [18, "\xddA"], "\xc4" => [77, "\xdd_"], "\xc5" => [18, "\xdd_"], "\xc6" => [77, "\xddb"], "\xc7" => [18, "\xddb"], "\xc8" => [77, "\xddd"], "\xc9" => [18, "\xddd"], "\xca" => [77, "\xddf"], "\xcb" => [18, "\xddf"], "\xcc" => [77, "\xddg"], "\xcd" => [18, "\xddg"], "\xce" => [77, "\xddh"], "\xcf" => [18, "\xddh"], "\xd0" => [77, "\xddl"], "\xd1" => [18, "\xddl"], "\xd2" => [77, "\xddm"], "\xd3" => [18, "\xddm"], "\xd4" => [77, "\xddn"], "\xd5" => [18, "\xddn"], "\xd6" => [77, "\xddp"], "\xd7" => [18, "\xddp"], "\xd8" => [77, "\xddr"], "\xd9" => [18, "\xddr"], "\xda" => [77, "\xddu"], "\xdb" => [18, "\xddu"], "\xdc" => [0, "\xdd:"], "\xdd" => [0, "\xddB"], "\xde" => [0, "\xddC"], "\xdf" => [0, "\xddD"], "\xe0" => [0, "\xddE"], "\xe1" => [0, "\xddF"], "\xe2" => [0, "\xddG"], "\xe3" => [0, "\xddH"], "\xe4" => [0, "\xddI"], "\xe5" => [0, "\xddJ"], "\xe6" => [0, "\xddK"], "\xe7" => [0, "\xddL"], "\xe8" => [0, "\xddM"], "\xe9" => [0, "\xddN"], "\xea" => [0, "\xddO"], "\xeb" => [0, "\xddP"], "\xec" => [0, "\xddQ"], "\xed" => [0, "\xddR"], "\xee" => [0, "\xddS"], "\xef" => [0, "\xddT"], "\xf0" => [0, "\xddU"], "\xf1" => [0, "\xddV"], "\xf2" => [0, "\xddW"], "\xf3" => [0, "\xddY"], "\xf4" => [0, "\xddj"], "\xf5" => [0, "\xddk"], "\xf6" => [0, "\xddq"], "\xf7" => [0, "\xddv"], "\xf8" => [0, "\xddw"], "\xf9" => [0, "\xddx"], "\xfa" => [0, "\xddy"], "\xfb" => [0, "\xddz"], "\xfc" => [82, "\xdd"], "\xfd" => [87, "\xdd"], "\xfe" => [130, "\xdd"], "\xff" => [9, "\xdd"]], ["\x00" => [94, "\xd70"], "\x01" => [76, "\xd70"], "\x02" => [104, "\xd70"], "\x03" => [16, "\xd70"], "\x04" => [94, "\xd71"], "\x05" => [76, "\xd71"], "\x06" => [104, "\xd71"], "\x07" => [16, "\xd71"], "\x08" => [94, "\xd72"], "\t" => [76, "\xd72"], "\n" => [104, "\xd72"], "\v" => [16, "\xd72"], "\f" => [94, "\xd7a"], "\r" => [76, "\xd7a"], "\x0e" => [104, "\xd7a"], "\x0f" => [16, "\xd7a"], "\x10" => [94, "\xd7c"], "\x11" => [76, "\xd7c"], "\x12" => [104, "\xd7c"], "\x13" => [16, "\xd7c"], "\x14" => [94, "\xd7e"], "\x15" => [76, "\xd7e"], "\x16" => [104, "\xd7e"], "\x17" => [16, "\xd7e"], "\x18" => [94, "\xd7i"], "\x19" => [76, "\xd7i"], "\x1a" => [104, "\xd7i"], "\x1b" => [16, "\xd7i"], "\x1c" => [94, "\xd7o"], "\x1d" => [76, "\xd7o"], "\x1e" => [104, "\xd7o"], "\x1f" => [16, "\xd7o"], " " => [94, "\xd7s"], "!" => [76, "\xd7s"], "\"" => [104, "\xd7s"], "#" => [16, "\xd7s"], "\$" => [94, "\xd7t"], "%" => [76, "\xd7t"], "&" => [104, "\xd7t"], "'" => [16, "\xd7t"], "(" => [77, "\xd7 "], ")" => [18, "\xd7 "], "*" => [77, "\xd7%"], "+" => [18, "\xd7%"], "," => [77, "\xd7-"], "-" => [18, "\xd7-"], "." => [77, "\xd7."], "/" => [18, "\xd7."], [77, "\xd7/"], [18, "\xd7/"], [77, "\xd73"], [18, "\xd73"], [77, "\xd74"], [18, "\xd74"], [77, "\xd75"], [18, "\xd75"], [77, "\xd76"], [18, "\xd76"], ":" => [77, "\xd77"], ";" => [18, "\xd77"], "<" => [77, "\xd78"], "=" => [18, "\xd78"], ">" => [77, "\xd79"], "?" => [18, "\xd79"], "@" => [77, "\xd7="], "A" => [18, "\xd7="], "B" => [77, "\xd7A"], "C" => [18, "\xd7A"], "D" => [77, "\xd7_"], "E" => [18, "\xd7_"], "F" => [77, "\xd7b"], "G" => [18, "\xd7b"], "H" => [77, "\xd7d"], "I" => [18, "\xd7d"], "J" => [77, "\xd7f"], "K" => [18, "\xd7f"], "L" => [77, "\xd7g"], "M" => [18, "\xd7g"], "N" => [77, "\xd7h"], "O" => [18, "\xd7h"], "P" => [77, "\xd7l"], "Q" => [18, "\xd7l"], "R" => [77, "\xd7m"], "S" => [18, "\xd7m"], "T" => [77, "\xd7n"], "U" => [18, "\xd7n"], "V" => [77, "\xd7p"], "W" => [18, "\xd7p"], "X" => [77, "\xd7r"], "Y" => [18, "\xd7r"], "Z" => [77, "\xd7u"], "[" => [18, "\xd7u"], "\\" => [0, "\xd7:"], "]" => [0, "\xd7B"], "^" => [0, "\xd7C"], "_" => [0, "\xd7D"], "`" => [0, "\xd7E"], "a" => [0, "\xd7F"], "b" => [0, "\xd7G"], "c" => [0, "\xd7H"], "d" => [0, "\xd7I"], "e" => [0, "\xd7J"], "f" => [0, "\xd7K"], "g" => [0, "\xd7L"], "h" => [0, "\xd7M"], "i" => [0, "\xd7N"], "j" => [0, "\xd7O"], "k" => [0, "\xd7P"], "l" => [0, "\xd7Q"], "m" => [0, "\xd7R"], "n" => [0, "\xd7S"], "o" => [0, "\xd7T"], "p" => [0, "\xd7U"], "q" => [0, "\xd7V"], "r" => [0, "\xd7W"], "s" => [0, "\xd7Y"], "t" => [0, "\xd7j"], "u" => [0, "\xd7k"], "v" => [0, "\xd7q"], "w" => [0, "\xd7v"], "x" => [0, "\xd7w"], "y" => [0, "\xd7x"], "z" => [0, "\xd7y"], "{" => [0, "\xd7z"], "|" => [82, "\xd7"], "}" => [87, "\xd7"], "~" => [130, "\xd7"], "" => [9, "\xd7"], "\x80" => [94, "\xe10"], "\x81" => [76, "\xe10"], "\x82" => [104, "\xe10"], "\x83" => [16, "\xe10"], "\x84" => [94, "\xe11"], "\x85" => [76, "\xe11"], "\x86" => [104, "\xe11"], "\x87" => [16, "\xe11"], "\x88" => [94, "\xe12"], "\x89" => [76, "\xe12"], "\x8a" => [104, "\xe12"], "\x8b" => [16, "\xe12"], "\x8c" => [94, "\xe1a"], "\x8d" => [76, "\xe1a"], "\x8e" => [104, "\xe1a"], "\x8f" => [16, "\xe1a"], "\x90" => [94, "\xe1c"], "\x91" => [76, "\xe1c"], "\x92" => [104, "\xe1c"], "\x93" => [16, "\xe1c"], "\x94" => [94, "\xe1e"], "\x95" => [76, "\xe1e"], "\x96" => [104, "\xe1e"], "\x97" => [16, "\xe1e"], "\x98" => [94, "\xe1i"], "\x99" => [76, "\xe1i"], "\x9a" => [104, "\xe1i"], "\x9b" => [16, "\xe1i"], "\x9c" => [94, "\xe1o"], "\x9d" => [76, "\xe1o"], "\x9e" => [104, "\xe1o"], "\x9f" => [16, "\xe1o"], "\xa0" => [94, "\xe1s"], "\xa1" => [76, "\xe1s"], "\xa2" => [104, "\xe1s"], "\xa3" => [16, "\xe1s"], "\xa4" => [94, "\xe1t"], "\xa5" => [76, "\xe1t"], "\xa6" => [104, "\xe1t"], "\xa7" => [16, "\xe1t"], "\xa8" => [77, "\xe1 "], "\xa9" => [18, "\xe1 "], "\xaa" => [77, "\xe1%"], "\xab" => [18, "\xe1%"], "\xac" => [77, "\xe1-"], "\xad" => [18, "\xe1-"], "\xae" => [77, "\xe1."], "\xaf" => [18, "\xe1."], "\xb0" => [77, "\xe1/"], "\xb1" => [18, "\xe1/"], "\xb2" => [77, "\xe13"], "\xb3" => [18, "\xe13"], "\xb4" => [77, "\xe14"], "\xb5" => [18, "\xe14"], "\xb6" => [77, "\xe15"], "\xb7" => [18, "\xe15"], "\xb8" => [77, "\xe16"], "\xb9" => [18, "\xe16"], "\xba" => [77, "\xe17"], "\xbb" => [18, "\xe17"], "\xbc" => [77, "\xe18"], "\xbd" => [18, "\xe18"], "\xbe" => [77, "\xe19"], "\xbf" => [18, "\xe19"], "\xc0" => [77, "\xe1="], "\xc1" => [18, "\xe1="], "\xc2" => [77, "\xe1A"], "\xc3" => [18, "\xe1A"], "\xc4" => [77, "\xe1_"], "\xc5" => [18, "\xe1_"], "\xc6" => [77, "\xe1b"], "\xc7" => [18, "\xe1b"], "\xc8" => [77, "\xe1d"], "\xc9" => [18, "\xe1d"], "\xca" => [77, "\xe1f"], "\xcb" => [18, "\xe1f"], "\xcc" => [77, "\xe1g"], "\xcd" => [18, "\xe1g"], "\xce" => [77, "\xe1h"], "\xcf" => [18, "\xe1h"], "\xd0" => [77, "\xe1l"], "\xd1" => [18, "\xe1l"], "\xd2" => [77, "\xe1m"], "\xd3" => [18, "\xe1m"], "\xd4" => [77, "\xe1n"], "\xd5" => [18, "\xe1n"], "\xd6" => [77, "\xe1p"], "\xd7" => [18, "\xe1p"], "\xd8" => [77, "\xe1r"], "\xd9" => [18, "\xe1r"], "\xda" => [77, "\xe1u"], "\xdb" => [18, "\xe1u"], "\xdc" => [0, "\xe1:"], "\xdd" => [0, "\xe1B"], "\xde" => [0, "\xe1C"], "\xdf" => [0, "\xe1D"], "\xe0" => [0, "\xe1E"], "\xe1" => [0, "\xe1F"], "\xe2" => [0, "\xe1G"], "\xe3" => [0, "\xe1H"], "\xe4" => [0, "\xe1I"], "\xe5" => [0, "\xe1J"], "\xe6" => [0, "\xe1K"], "\xe7" => [0, "\xe1L"], "\xe8" => [0, "\xe1M"], "\xe9" => [0, "\xe1N"], "\xea" => [0, "\xe1O"], "\xeb" => [0, "\xe1P"], "\xec" => [0, "\xe1Q"], "\xed" => [0, "\xe1R"], "\xee" => [0, "\xe1S"], "\xef" => [0, "\xe1T"], "\xf0" => [0, "\xe1U"], "\xf1" => [0, "\xe1V"], "\xf2" => [0, "\xe1W"], "\xf3" => [0, "\xe1Y"], "\xf4" => [0, "\xe1j"], "\xf5" => [0, "\xe1k"], "\xf6" => [0, "\xe1q"], "\xf7" => [0, "\xe1v"], "\xf8" => [0, "\xe1w"], "\xf9" => [0, "\xe1x"], "\xfa" => [0, "\xe1y"], "\xfb" => [0, "\xe1z"], "\xfc" => [82, "\xe1"], "\xfd" => [87, "\xe1"], "\xfe" => [130, "\xe1"], "\xff" => [9, "\xe1"]], ["\x00" => [94, "\xd80"], "\x01" => [76, "\xd80"], "\x02" => [104, "\xd80"], "\x03" => [16, "\xd80"], "\x04" => [94, "\xd81"], "\x05" => [76, "\xd81"], "\x06" => [104, "\xd81"], "\x07" => [16, "\xd81"], "\x08" => [94, "\xd82"], "\t" => [76, "\xd82"], "\n" => [104, "\xd82"], "\v" => [16, "\xd82"], "\f" => [94, "\xd8a"], "\r" => [76, "\xd8a"], "\x0e" => [104, "\xd8a"], "\x0f" => [16, "\xd8a"], "\x10" => [94, "\xd8c"], "\x11" => [76, "\xd8c"], "\x12" => [104, "\xd8c"], "\x13" => [16, "\xd8c"], "\x14" => [94, "\xd8e"], "\x15" => [76, "\xd8e"], "\x16" => [104, "\xd8e"], "\x17" => [16, "\xd8e"], "\x18" => [94, "\xd8i"], "\x19" => [76, "\xd8i"], "\x1a" => [104, "\xd8i"], "\x1b" => [16, "\xd8i"], "\x1c" => [94, "\xd8o"], "\x1d" => [76, "\xd8o"], "\x1e" => [104, "\xd8o"], "\x1f" => [16, "\xd8o"], " " => [94, "\xd8s"], "!" => [76, "\xd8s"], "\"" => [104, "\xd8s"], "#" => [16, "\xd8s"], "\$" => [94, "\xd8t"], "%" => [76, "\xd8t"], "&" => [104, "\xd8t"], "'" => [16, "\xd8t"], "(" => [77, "\xd8 "], ")" => [18, "\xd8 "], "*" => [77, "\xd8%"], "+" => [18, "\xd8%"], "," => [77, "\xd8-"], "-" => [18, "\xd8-"], "." => [77, "\xd8."], "/" => [18, "\xd8."], [77, "\xd8/"], [18, "\xd8/"], [77, "\xd83"], [18, "\xd83"], [77, "\xd84"], [18, "\xd84"], [77, "\xd85"], [18, "\xd85"], [77, "\xd86"], [18, "\xd86"], ":" => [77, "\xd87"], ";" => [18, "\xd87"], "<" => [77, "\xd88"], "=" => [18, "\xd88"], ">" => [77, "\xd89"], "?" => [18, "\xd89"], "@" => [77, "\xd8="], "A" => [18, "\xd8="], "B" => [77, "\xd8A"], "C" => [18, "\xd8A"], "D" => [77, "\xd8_"], "E" => [18, "\xd8_"], "F" => [77, "\xd8b"], "G" => [18, "\xd8b"], "H" => [77, "\xd8d"], "I" => [18, "\xd8d"], "J" => [77, "\xd8f"], "K" => [18, "\xd8f"], "L" => [77, "\xd8g"], "M" => [18, "\xd8g"], "N" => [77, "\xd8h"], "O" => [18, "\xd8h"], "P" => [77, "\xd8l"], "Q" => [18, "\xd8l"], "R" => [77, "\xd8m"], "S" => [18, "\xd8m"], "T" => [77, "\xd8n"], "U" => [18, "\xd8n"], "V" => [77, "\xd8p"], "W" => [18, "\xd8p"], "X" => [77, "\xd8r"], "Y" => [18, "\xd8r"], "Z" => [77, "\xd8u"], "[" => [18, "\xd8u"], "\\" => [0, "\xd8:"], "]" => [0, "\xd8B"], "^" => [0, "\xd8C"], "_" => [0, "\xd8D"], "`" => [0, "\xd8E"], "a" => [0, "\xd8F"], "b" => [0, "\xd8G"], "c" => [0, "\xd8H"], "d" => [0, "\xd8I"], "e" => [0, "\xd8J"], "f" => [0, "\xd8K"], "g" => [0, "\xd8L"], "h" => [0, "\xd8M"], "i" => [0, "\xd8N"], "j" => [0, "\xd8O"], "k" => [0, "\xd8P"], "l" => [0, "\xd8Q"], "m" => [0, "\xd8R"], "n" => [0, "\xd8S"], "o" => [0, "\xd8T"], "p" => [0, "\xd8U"], "q" => [0, "\xd8V"], "r" => [0, "\xd8W"], "s" => [0, "\xd8Y"], "t" => [0, "\xd8j"], "u" => [0, "\xd8k"], "v" => [0, "\xd8q"], "w" => [0, "\xd8v"], "x" => [0, "\xd8w"], "y" => [0, "\xd8x"], "z" => [0, "\xd8y"], "{" => [0, "\xd8z"], "|" => [82, "\xd8"], "}" => [87, "\xd8"], "~" => [130, "\xd8"], "" => [9, "\xd8"], "\x80" => [94, "\xd90"], "\x81" => [76, "\xd90"], "\x82" => [104, "\xd90"], "\x83" => [16, "\xd90"], "\x84" => [94, "\xd91"], "\x85" => [76, "\xd91"], "\x86" => [104, "\xd91"], "\x87" => [16, "\xd91"], "\x88" => [94, "\xd92"], "\x89" => [76, "\xd92"], "\x8a" => [104, "\xd92"], "\x8b" => [16, "\xd92"], "\x8c" => [94, "\xd9a"], "\x8d" => [76, "\xd9a"], "\x8e" => [104, "\xd9a"], "\x8f" => [16, "\xd9a"], "\x90" => [94, "\xd9c"], "\x91" => [76, "\xd9c"], "\x92" => [104, "\xd9c"], "\x93" => [16, "\xd9c"], "\x94" => [94, "\xd9e"], "\x95" => [76, "\xd9e"], "\x96" => [104, "\xd9e"], "\x97" => [16, "\xd9e"], "\x98" => [94, "\xd9i"], "\x99" => [76, "\xd9i"], "\x9a" => [104, "\xd9i"], "\x9b" => [16, "\xd9i"], "\x9c" => [94, "\xd9o"], "\x9d" => [76, "\xd9o"], "\x9e" => [104, "\xd9o"], "\x9f" => [16, "\xd9o"], "\xa0" => [94, "\xd9s"], "\xa1" => [76, "\xd9s"], "\xa2" => [104, "\xd9s"], "\xa3" => [16, "\xd9s"], "\xa4" => [94, "\xd9t"], "\xa5" => [76, "\xd9t"], "\xa6" => [104, "\xd9t"], "\xa7" => [16, "\xd9t"], "\xa8" => [77, "\xd9 "], "\xa9" => [18, "\xd9 "], "\xaa" => [77, "\xd9%"], "\xab" => [18, "\xd9%"], "\xac" => [77, "\xd9-"], "\xad" => [18, "\xd9-"], "\xae" => [77, "\xd9."], "\xaf" => [18, "\xd9."], "\xb0" => [77, "\xd9/"], "\xb1" => [18, "\xd9/"], "\xb2" => [77, "\xd93"], "\xb3" => [18, "\xd93"], "\xb4" => [77, "\xd94"], "\xb5" => [18, "\xd94"], "\xb6" => [77, "\xd95"], "\xb7" => [18, "\xd95"], "\xb8" => [77, "\xd96"], "\xb9" => [18, "\xd96"], "\xba" => [77, "\xd97"], "\xbb" => [18, "\xd97"], "\xbc" => [77, "\xd98"], "\xbd" => [18, "\xd98"], "\xbe" => [77, "\xd99"], "\xbf" => [18, "\xd99"], "\xc0" => [77, "\xd9="], "\xc1" => [18, "\xd9="], "\xc2" => [77, "\xd9A"], "\xc3" => [18, "\xd9A"], "\xc4" => [77, "\xd9_"], "\xc5" => [18, "\xd9_"], "\xc6" => [77, "\xd9b"], "\xc7" => [18, "\xd9b"], "\xc8" => [77, "\xd9d"], "\xc9" => [18, "\xd9d"], "\xca" => [77, "\xd9f"], "\xcb" => [18, "\xd9f"], "\xcc" => [77, "\xd9g"], "\xcd" => [18, "\xd9g"], "\xce" => [77, "\xd9h"], "\xcf" => [18, "\xd9h"], "\xd0" => [77, "\xd9l"], "\xd1" => [18, "\xd9l"], "\xd2" => [77, "\xd9m"], "\xd3" => [18, "\xd9m"], "\xd4" => [77, "\xd9n"], "\xd5" => [18, "\xd9n"], "\xd6" => [77, "\xd9p"], "\xd7" => [18, "\xd9p"], "\xd8" => [77, "\xd9r"], "\xd9" => [18, "\xd9r"], "\xda" => [77, "\xd9u"], "\xdb" => [18, "\xd9u"], "\xdc" => [0, "\xd9:"], "\xdd" => [0, "\xd9B"], "\xde" => [0, "\xd9C"], "\xdf" => [0, "\xd9D"], "\xe0" => [0, "\xd9E"], "\xe1" => [0, "\xd9F"], "\xe2" => [0, "\xd9G"], "\xe3" => [0, "\xd9H"], "\xe4" => [0, "\xd9I"], "\xe5" => [0, "\xd9J"], "\xe6" => [0, "\xd9K"], "\xe7" => [0, "\xd9L"], "\xe8" => [0, "\xd9M"], "\xe9" => [0, "\xd9N"], "\xea" => [0, "\xd9O"], "\xeb" => [0, "\xd9P"], "\xec" => [0, "\xd9Q"], "\xed" => [0, "\xd9R"], "\xee" => [0, "\xd9S"], "\xef" => [0, "\xd9T"], "\xf0" => [0, "\xd9U"], "\xf1" => [0, "\xd9V"], "\xf2" => [0, "\xd9W"], "\xf3" => [0, "\xd9Y"], "\xf4" => [0, "\xd9j"], "\xf5" => [0, "\xd9k"], "\xf6" => [0, "\xd9q"], "\xf7" => [0, "\xd9v"], "\xf8" => [0, "\xd9w"], "\xf9" => [0, "\xd9x"], "\xfa" => [0, "\xd9y"], "\xfb" => [0, "\xd9z"], "\xfc" => [82, "\xd9"], "\xfd" => [87, "\xd9"], "\xfe" => [130, "\xd9"], "\xff" => [9, "\xd9"]], ["\x00" => [77, "\xd80"], "\x01" => [18, "\xd80"], "\x02" => [77, "\xd81"], "\x03" => [18, "\xd81"], "\x04" => [77, "\xd82"], "\x05" => [18, "\xd82"], "\x06" => [77, "\xd8a"], "\x07" => [18, "\xd8a"], "\x08" => [77, "\xd8c"], "\t" => [18, "\xd8c"], "\n" => [77, "\xd8e"], "\v" => [18, "\xd8e"], "\f" => [77, "\xd8i"], "\r" => [18, "\xd8i"], "\x0e" => [77, "\xd8o"], "\x0f" => [18, "\xd8o"], "\x10" => [77, "\xd8s"], "\x11" => [18, "\xd8s"], "\x12" => [77, "\xd8t"], "\x13" => [18, "\xd8t"], "\x14" => [0, "\xd8 "], "\x15" => [0, "\xd8%"], "\x16" => [0, "\xd8-"], "\x17" => [0, "\xd8."], "\x18" => [0, "\xd8/"], "\x19" => [0, "\xd83"], "\x1a" => [0, "\xd84"], "\x1b" => [0, "\xd85"], "\x1c" => [0, "\xd86"], "\x1d" => [0, "\xd87"], "\x1e" => [0, "\xd88"], "\x1f" => [0, "\xd89"], " " => [0, "\xd8="], "!" => [0, "\xd8A"], "\"" => [0, "\xd8_"], "#" => [0, "\xd8b"], "\$" => [0, "\xd8d"], "%" => [0, "\xd8f"], "&" => [0, "\xd8g"], "'" => [0, "\xd8h"], "(" => [0, "\xd8l"], ")" => [0, "\xd8m"], "*" => [0, "\xd8n"], "+" => [0, "\xd8p"], "," => [0, "\xd8r"], "-" => [0, "\xd8u"], "." => [100, "\xd8"], "/" => [110, "\xd8"], [111, "\xd8"], [115, "\xd8"], [116, "\xd8"], [118, "\xd8"], [119, "\xd8"], [122, "\xd8"], [123, "\xd8"], [125, "\xd8"], [126, "\xd8"], [129, "\xd8"], ":" => [143, "\xd8"], ";" => [148, "\xd8"], "<" => [151, "\xd8"], "=" => [153, "\xd8"], ">" => [83, "\xd8"], "?" => [10, "\xd8"], "@" => [77, "\xd90"], "A" => [18, "\xd90"], "B" => [77, "\xd91"], "C" => [18, "\xd91"], "D" => [77, "\xd92"], "E" => [18, "\xd92"], "F" => [77, "\xd9a"], "G" => [18, "\xd9a"], "H" => [77, "\xd9c"], "I" => [18, "\xd9c"], "J" => [77, "\xd9e"], "K" => [18, "\xd9e"], "L" => [77, "\xd9i"], "M" => [18, "\xd9i"], "N" => [77, "\xd9o"], "O" => [18, "\xd9o"], "P" => [77, "\xd9s"], "Q" => [18, "\xd9s"], "R" => [77, "\xd9t"], "S" => [18, "\xd9t"], "T" => [0, "\xd9 "], "U" => [0, "\xd9%"], "V" => [0, "\xd9-"], "W" => [0, "\xd9."], "X" => [0, "\xd9/"], "Y" => [0, "\xd93"], "Z" => [0, "\xd94"], "[" => [0, "\xd95"], "\\" => [0, "\xd96"], "]" => [0, "\xd97"], "^" => [0, "\xd98"], "_" => [0, "\xd99"], "`" => [0, "\xd9="], "a" => [0, "\xd9A"], "b" => [0, "\xd9_"], "c" => [0, "\xd9b"], "d" => [0, "\xd9d"], "e" => [0, "\xd9f"], "f" => [0, "\xd9g"], "g" => [0, "\xd9h"], "h" => [0, "\xd9l"], "i" => [0, "\xd9m"], "j" => [0, "\xd9n"], "k" => [0, "\xd9p"], "l" => [0, "\xd9r"], "m" => [0, "\xd9u"], "n" => [100, "\xd9"], "o" => [110, "\xd9"], "p" => [111, "\xd9"], "q" => [115, "\xd9"], "r" => [116, "\xd9"], "s" => [118, "\xd9"], "t" => [119, "\xd9"], "u" => [122, "\xd9"], "v" => [123, "\xd9"], "w" => [125, "\xd9"], "x" => [126, "\xd9"], "y" => [129, "\xd9"], "z" => [143, "\xd9"], "{" => [148, "\xd9"], "|" => [151, "\xd9"], "}" => [153, "\xd9"], "~" => [83, "\xd9"], "" => [10, "\xd9"], "\x80" => [77, "\xe30"], "\x81" => [18, "\xe30"], "\x82" => [77, "\xe31"], "\x83" => [18, "\xe31"], "\x84" => [77, "\xe32"], "\x85" => [18, "\xe32"], "\x86" => [77, "\xe3a"], "\x87" => [18, "\xe3a"], "\x88" => [77, "\xe3c"], "\x89" => [18, "\xe3c"], "\x8a" => [77, "\xe3e"], "\x8b" => [18, "\xe3e"], "\x8c" => [77, "\xe3i"], "\x8d" => [18, "\xe3i"], "\x8e" => [77, "\xe3o"], "\x8f" => [18, "\xe3o"], "\x90" => [77, "\xe3s"], "\x91" => [18, "\xe3s"], "\x92" => [77, "\xe3t"], "\x93" => [18, "\xe3t"], "\x94" => [0, "\xe3 "], "\x95" => [0, "\xe3%"], "\x96" => [0, "\xe3-"], "\x97" => [0, "\xe3."], "\x98" => [0, "\xe3/"], "\x99" => [0, "\xe33"], "\x9a" => [0, "\xe34"], "\x9b" => [0, "\xe35"], "\x9c" => [0, "\xe36"], "\x9d" => [0, "\xe37"], "\x9e" => [0, "\xe38"], "\x9f" => [0, "\xe39"], "\xa0" => [0, "\xe3="], "\xa1" => [0, "\xe3A"], "\xa2" => [0, "\xe3_"], "\xa3" => [0, "\xe3b"], "\xa4" => [0, "\xe3d"], "\xa5" => [0, "\xe3f"], "\xa6" => [0, "\xe3g"], "\xa7" => [0, "\xe3h"], "\xa8" => [0, "\xe3l"], "\xa9" => [0, "\xe3m"], "\xaa" => [0, "\xe3n"], "\xab" => [0, "\xe3p"], "\xac" => [0, "\xe3r"], "\xad" => [0, "\xe3u"], "\xae" => [100, "\xe3"], "\xaf" => [110, "\xe3"], "\xb0" => [111, "\xe3"], "\xb1" => [115, "\xe3"], "\xb2" => [116, "\xe3"], "\xb3" => [118, "\xe3"], "\xb4" => [119, "\xe3"], "\xb5" => [122, "\xe3"], "\xb6" => [123, "\xe3"], "\xb7" => [125, "\xe3"], "\xb8" => [126, "\xe3"], "\xb9" => [129, "\xe3"], "\xba" => [143, "\xe3"], "\xbb" => [148, "\xe3"], "\xbc" => [151, "\xe3"], "\xbd" => [153, "\xe3"], "\xbe" => [83, "\xe3"], "\xbf" => [10, "\xe3"], "\xc0" => [77, "\xe50"], "\xc1" => [18, "\xe50"], "\xc2" => [77, "\xe51"], "\xc3" => [18, "\xe51"], "\xc4" => [77, "\xe52"], "\xc5" => [18, "\xe52"], "\xc6" => [77, "\xe5a"], "\xc7" => [18, "\xe5a"], "\xc8" => [77, "\xe5c"], "\xc9" => [18, "\xe5c"], "\xca" => [77, "\xe5e"], "\xcb" => [18, "\xe5e"], "\xcc" => [77, "\xe5i"], "\xcd" => [18, "\xe5i"], "\xce" => [77, "\xe5o"], "\xcf" => [18, "\xe5o"], "\xd0" => [77, "\xe5s"], "\xd1" => [18, "\xe5s"], "\xd2" => [77, "\xe5t"], "\xd3" => [18, "\xe5t"], "\xd4" => [0, "\xe5 "], "\xd5" => [0, "\xe5%"], "\xd6" => [0, "\xe5-"], "\xd7" => [0, "\xe5."], "\xd8" => [0, "\xe5/"], "\xd9" => [0, "\xe53"], "\xda" => [0, "\xe54"], "\xdb" => [0, "\xe55"], "\xdc" => [0, "\xe56"], "\xdd" => [0, "\xe57"], "\xde" => [0, "\xe58"], "\xdf" => [0, "\xe59"], "\xe0" => [0, "\xe5="], "\xe1" => [0, "\xe5A"], "\xe2" => [0, "\xe5_"], "\xe3" => [0, "\xe5b"], "\xe4" => [0, "\xe5d"], "\xe5" => [0, "\xe5f"], "\xe6" => [0, "\xe5g"], "\xe7" => [0, "\xe5h"], "\xe8" => [0, "\xe5l"], "\xe9" => [0, "\xe5m"], "\xea" => [0, "\xe5n"], "\xeb" => [0, "\xe5p"], "\xec" => [0, "\xe5r"], "\xed" => [0, "\xe5u"], "\xee" => [100, "\xe5"], "\xef" => [110, "\xe5"], "\xf0" => [111, "\xe5"], "\xf1" => [115, "\xe5"], "\xf2" => [116, "\xe5"], "\xf3" => [118, "\xe5"], "\xf4" => [119, "\xe5"], "\xf5" => [122, "\xe5"], "\xf6" => [123, "\xe5"], "\xf7" => [125, "\xe5"], "\xf8" => [126, "\xe5"], "\xf9" => [129, "\xe5"], "\xfa" => [143, "\xe5"], "\xfb" => [148, "\xe5"], "\xfc" => [151, "\xe5"], "\xfd" => [153, "\xe5"], "\xfe" => [83, "\xe5"], "\xff" => [10, "\xe5"]], ["\x00" => [77, "\xda0"], "\x01" => [18, "\xda0"], "\x02" => [77, "\xda1"], "\x03" => [18, "\xda1"], "\x04" => [77, "\xda2"], "\x05" => [18, "\xda2"], "\x06" => [77, "\xdaa"], "\x07" => [18, "\xdaa"], "\x08" => [77, "\xdac"], "\t" => [18, "\xdac"], "\n" => [77, "\xdae"], "\v" => [18, "\xdae"], "\f" => [77, "\xdai"], "\r" => [18, "\xdai"], "\x0e" => [77, "\xdao"], "\x0f" => [18, "\xdao"], "\x10" => [77, "\xdas"], "\x11" => [18, "\xdas"], "\x12" => [77, "\xdat"], "\x13" => [18, "\xdat"], "\x14" => [0, "\xda "], "\x15" => [0, "\xda%"], "\x16" => [0, "\xda-"], "\x17" => [0, "\xda."], "\x18" => [0, "\xda/"], "\x19" => [0, "\xda3"], "\x1a" => [0, "\xda4"], "\x1b" => [0, "\xda5"], "\x1c" => [0, "\xda6"], "\x1d" => [0, "\xda7"], "\x1e" => [0, "\xda8"], "\x1f" => [0, "\xda9"], " " => [0, "\xda="], "!" => [0, "\xdaA"], "\"" => [0, "\xda_"], "#" => [0, "\xdab"], "\$" => [0, "\xdad"], "%" => [0, "\xdaf"], "&" => [0, "\xdag"], "'" => [0, "\xdah"], "(" => [0, "\xdal"], ")" => [0, "\xdam"], "*" => [0, "\xdan"], "+" => [0, "\xdap"], "," => [0, "\xdar"], "-" => [0, "\xdau"], "." => [100, "\xda"], "/" => [110, "\xda"], [111, "\xda"], [115, "\xda"], [116, "\xda"], [118, "\xda"], [119, "\xda"], [122, "\xda"], [123, "\xda"], [125, "\xda"], [126, "\xda"], [129, "\xda"], ":" => [143, "\xda"], ";" => [148, "\xda"], "<" => [151, "\xda"], "=" => [153, "\xda"], ">" => [83, "\xda"], "?" => [10, "\xda"], "@" => [77, "\xdb0"], "A" => [18, "\xdb0"], "B" => [77, "\xdb1"], "C" => [18, "\xdb1"], "D" => [77, "\xdb2"], "E" => [18, "\xdb2"], "F" => [77, "\xdba"], "G" => [18, "\xdba"], "H" => [77, "\xdbc"], "I" => [18, "\xdbc"], "J" => [77, "\xdbe"], "K" => [18, "\xdbe"], "L" => [77, "\xdbi"], "M" => [18, "\xdbi"], "N" => [77, "\xdbo"], "O" => [18, "\xdbo"], "P" => [77, "\xdbs"], "Q" => [18, "\xdbs"], "R" => [77, "\xdbt"], "S" => [18, "\xdbt"], "T" => [0, "\xdb "], "U" => [0, "\xdb%"], "V" => [0, "\xdb-"], "W" => [0, "\xdb."], "X" => [0, "\xdb/"], "Y" => [0, "\xdb3"], "Z" => [0, "\xdb4"], "[" => [0, "\xdb5"], "\\" => [0, "\xdb6"], "]" => [0, "\xdb7"], "^" => [0, "\xdb8"], "_" => [0, "\xdb9"], "`" => [0, "\xdb="], "a" => [0, "\xdbA"], "b" => [0, "\xdb_"], "c" => [0, "\xdbb"], "d" => [0, "\xdbd"], "e" => [0, "\xdbf"], "f" => [0, "\xdbg"], "g" => [0, "\xdbh"], "h" => [0, "\xdbl"], "i" => [0, "\xdbm"], "j" => [0, "\xdbn"], "k" => [0, "\xdbp"], "l" => [0, "\xdbr"], "m" => [0, "\xdbu"], "n" => [100, "\xdb"], "o" => [110, "\xdb"], "p" => [111, "\xdb"], "q" => [115, "\xdb"], "r" => [116, "\xdb"], "s" => [118, "\xdb"], "t" => [119, "\xdb"], "u" => [122, "\xdb"], "v" => [123, "\xdb"], "w" => [125, "\xdb"], "x" => [126, "\xdb"], "y" => [129, "\xdb"], "z" => [143, "\xdb"], "{" => [148, "\xdb"], "|" => [151, "\xdb"], "}" => [153, "\xdb"], "~" => [83, "\xdb"], "" => [10, "\xdb"], "\x80" => [77, "\xee0"], "\x81" => [18, "\xee0"], "\x82" => [77, "\xee1"], "\x83" => [18, "\xee1"], "\x84" => [77, "\xee2"], "\x85" => [18, "\xee2"], "\x86" => [77, "\xeea"], "\x87" => [18, "\xeea"], "\x88" => [77, "\xeec"], "\x89" => [18, "\xeec"], "\x8a" => [77, "\xeee"], "\x8b" => [18, "\xeee"], "\x8c" => [77, "\xeei"], "\x8d" => [18, "\xeei"], "\x8e" => [77, "\xeeo"], "\x8f" => [18, "\xeeo"], "\x90" => [77, "\xees"], "\x91" => [18, "\xees"], "\x92" => [77, "\xeet"], "\x93" => [18, "\xeet"], "\x94" => [0, "\xee "], "\x95" => [0, "\xee%"], "\x96" => [0, "\xee-"], "\x97" => [0, "\xee."], "\x98" => [0, "\xee/"], "\x99" => [0, "\xee3"], "\x9a" => [0, "\xee4"], "\x9b" => [0, "\xee5"], "\x9c" => [0, "\xee6"], "\x9d" => [0, "\xee7"], "\x9e" => [0, "\xee8"], "\x9f" => [0, "\xee9"], "\xa0" => [0, "\xee="], "\xa1" => [0, "\xeeA"], "\xa2" => [0, "\xee_"], "\xa3" => [0, "\xeeb"], "\xa4" => [0, "\xeed"], "\xa5" => [0, "\xeef"], "\xa6" => [0, "\xeeg"], "\xa7" => [0, "\xeeh"], "\xa8" => [0, "\xeel"], "\xa9" => [0, "\xeem"], "\xaa" => [0, "\xeen"], "\xab" => [0, "\xeep"], "\xac" => [0, "\xeer"], "\xad" => [0, "\xeeu"], "\xae" => [100, "\xee"], "\xaf" => [110, "\xee"], "\xb0" => [111, "\xee"], "\xb1" => [115, "\xee"], "\xb2" => [116, "\xee"], "\xb3" => [118, "\xee"], "\xb4" => [119, "\xee"], "\xb5" => [122, "\xee"], "\xb6" => [123, "\xee"], "\xb7" => [125, "\xee"], "\xb8" => [126, "\xee"], "\xb9" => [129, "\xee"], "\xba" => [143, "\xee"], "\xbb" => [148, "\xee"], "\xbc" => [151, "\xee"], "\xbd" => [153, "\xee"], "\xbe" => [83, "\xee"], "\xbf" => [10, "\xee"], "\xc0" => [77, "\xf00"], "\xc1" => [18, "\xf00"], "\xc2" => [77, "\xf01"], "\xc3" => [18, "\xf01"], "\xc4" => [77, "\xf02"], "\xc5" => [18, "\xf02"], "\xc6" => [77, "\xf0a"], "\xc7" => [18, "\xf0a"], "\xc8" => [77, "\xf0c"], "\xc9" => [18, "\xf0c"], "\xca" => [77, "\xf0e"], "\xcb" => [18, "\xf0e"], "\xcc" => [77, "\xf0i"], "\xcd" => [18, "\xf0i"], "\xce" => [77, "\xf0o"], "\xcf" => [18, "\xf0o"], "\xd0" => [77, "\xf0s"], "\xd1" => [18, "\xf0s"], "\xd2" => [77, "\xf0t"], "\xd3" => [18, "\xf0t"], "\xd4" => [0, "\xf0 "], "\xd5" => [0, "\xf0%"], "\xd6" => [0, "\xf0-"], "\xd7" => [0, "\xf0."], "\xd8" => [0, "\xf0/"], "\xd9" => [0, "\xf03"], "\xda" => [0, "\xf04"], "\xdb" => [0, "\xf05"], "\xdc" => [0, "\xf06"], "\xdd" => [0, "\xf07"], "\xde" => [0, "\xf08"], "\xdf" => [0, "\xf09"], "\xe0" => [0, "\xf0="], "\xe1" => [0, "\xf0A"], "\xe2" => [0, "\xf0_"], "\xe3" => [0, "\xf0b"], "\xe4" => [0, "\xf0d"], "\xe5" => [0, "\xf0f"], "\xe6" => [0, "\xf0g"], "\xe7" => [0, "\xf0h"], "\xe8" => [0, "\xf0l"], "\xe9" => [0, "\xf0m"], "\xea" => [0, "\xf0n"], "\xeb" => [0, "\xf0p"], "\xec" => [0, "\xf0r"], "\xed" => [0, "\xf0u"], "\xee" => [100, "\xf0"], "\xef" => [110, "\xf0"], "\xf0" => [111, "\xf0"], "\xf1" => [115, "\xf0"], "\xf2" => [116, "\xf0"], "\xf3" => [118, "\xf0"], "\xf4" => [119, "\xf0"], "\xf5" => [122, "\xf0"], "\xf6" => [123, "\xf0"], "\xf7" => [125, "\xf0"], "\xf8" => [126, "\xf0"], "\xf9" => [129, "\xf0"], "\xfa" => [143, "\xf0"], "\xfb" => [148, "\xf0"], "\xfc" => [151, "\xf0"], "\xfd" => [153, "\xf0"], "\xfe" => [83, "\xf0"], "\xff" => [10, "\xf0"]], ["\x00" => [94, "\xda0"], "\x01" => [76, "\xda0"], "\x02" => [104, "\xda0"], "\x03" => [16, "\xda0"], "\x04" => [94, "\xda1"], "\x05" => [76, "\xda1"], "\x06" => [104, "\xda1"], "\x07" => [16, "\xda1"], "\x08" => [94, "\xda2"], "\t" => [76, "\xda2"], "\n" => [104, "\xda2"], "\v" => [16, "\xda2"], "\f" => [94, "\xdaa"], "\r" => [76, "\xdaa"], "\x0e" => [104, "\xdaa"], "\x0f" => [16, "\xdaa"], "\x10" => [94, "\xdac"], "\x11" => [76, "\xdac"], "\x12" => [104, "\xdac"], "\x13" => [16, "\xdac"], "\x14" => [94, "\xdae"], "\x15" => [76, "\xdae"], "\x16" => [104, "\xdae"], "\x17" => [16, "\xdae"], "\x18" => [94, "\xdai"], "\x19" => [76, "\xdai"], "\x1a" => [104, "\xdai"], "\x1b" => [16, "\xdai"], "\x1c" => [94, "\xdao"], "\x1d" => [76, "\xdao"], "\x1e" => [104, "\xdao"], "\x1f" => [16, "\xdao"], " " => [94, "\xdas"], "!" => [76, "\xdas"], "\"" => [104, "\xdas"], "#" => [16, "\xdas"], "\$" => [94, "\xdat"], "%" => [76, "\xdat"], "&" => [104, "\xdat"], "'" => [16, "\xdat"], "(" => [77, "\xda "], ")" => [18, "\xda "], "*" => [77, "\xda%"], "+" => [18, "\xda%"], "," => [77, "\xda-"], "-" => [18, "\xda-"], "." => [77, "\xda."], "/" => [18, "\xda."], [77, "\xda/"], [18, "\xda/"], [77, "\xda3"], [18, "\xda3"], [77, "\xda4"], [18, "\xda4"], [77, "\xda5"], [18, "\xda5"], [77, "\xda6"], [18, "\xda6"], ":" => [77, "\xda7"], ";" => [18, "\xda7"], "<" => [77, "\xda8"], "=" => [18, "\xda8"], ">" => [77, "\xda9"], "?" => [18, "\xda9"], "@" => [77, "\xda="], "A" => [18, "\xda="], "B" => [77, "\xdaA"], "C" => [18, "\xdaA"], "D" => [77, "\xda_"], "E" => [18, "\xda_"], "F" => [77, "\xdab"], "G" => [18, "\xdab"], "H" => [77, "\xdad"], "I" => [18, "\xdad"], "J" => [77, "\xdaf"], "K" => [18, "\xdaf"], "L" => [77, "\xdag"], "M" => [18, "\xdag"], "N" => [77, "\xdah"], "O" => [18, "\xdah"], "P" => [77, "\xdal"], "Q" => [18, "\xdal"], "R" => [77, "\xdam"], "S" => [18, "\xdam"], "T" => [77, "\xdan"], "U" => [18, "\xdan"], "V" => [77, "\xdap"], "W" => [18, "\xdap"], "X" => [77, "\xdar"], "Y" => [18, "\xdar"], "Z" => [77, "\xdau"], "[" => [18, "\xdau"], "\\" => [0, "\xda:"], "]" => [0, "\xdaB"], "^" => [0, "\xdaC"], "_" => [0, "\xdaD"], "`" => [0, "\xdaE"], "a" => [0, "\xdaF"], "b" => [0, "\xdaG"], "c" => [0, "\xdaH"], "d" => [0, "\xdaI"], "e" => [0, "\xdaJ"], "f" => [0, "\xdaK"], "g" => [0, "\xdaL"], "h" => [0, "\xdaM"], "i" => [0, "\xdaN"], "j" => [0, "\xdaO"], "k" => [0, "\xdaP"], "l" => [0, "\xdaQ"], "m" => [0, "\xdaR"], "n" => [0, "\xdaS"], "o" => [0, "\xdaT"], "p" => [0, "\xdaU"], "q" => [0, "\xdaV"], "r" => [0, "\xdaW"], "s" => [0, "\xdaY"], "t" => [0, "\xdaj"], "u" => [0, "\xdak"], "v" => [0, "\xdaq"], "w" => [0, "\xdav"], "x" => [0, "\xdaw"], "y" => [0, "\xdax"], "z" => [0, "\xday"], "{" => [0, "\xdaz"], "|" => [82, "\xda"], "}" => [87, "\xda"], "~" => [130, "\xda"], "" => [9, "\xda"], "\x80" => [94, "\xdb0"], "\x81" => [76, "\xdb0"], "\x82" => [104, "\xdb0"], "\x83" => [16, "\xdb0"], "\x84" => [94, "\xdb1"], "\x85" => [76, "\xdb1"], "\x86" => [104, "\xdb1"], "\x87" => [16, "\xdb1"], "\x88" => [94, "\xdb2"], "\x89" => [76, "\xdb2"], "\x8a" => [104, "\xdb2"], "\x8b" => [16, "\xdb2"], "\x8c" => [94, "\xdba"], "\x8d" => [76, "\xdba"], "\x8e" => [104, "\xdba"], "\x8f" => [16, "\xdba"], "\x90" => [94, "\xdbc"], "\x91" => [76, "\xdbc"], "\x92" => [104, "\xdbc"], "\x93" => [16, "\xdbc"], "\x94" => [94, "\xdbe"], "\x95" => [76, "\xdbe"], "\x96" => [104, "\xdbe"], "\x97" => [16, "\xdbe"], "\x98" => [94, "\xdbi"], "\x99" => [76, "\xdbi"], "\x9a" => [104, "\xdbi"], "\x9b" => [16, "\xdbi"], "\x9c" => [94, "\xdbo"], "\x9d" => [76, "\xdbo"], "\x9e" => [104, "\xdbo"], "\x9f" => [16, "\xdbo"], "\xa0" => [94, "\xdbs"], "\xa1" => [76, "\xdbs"], "\xa2" => [104, "\xdbs"], "\xa3" => [16, "\xdbs"], "\xa4" => [94, "\xdbt"], "\xa5" => [76, "\xdbt"], "\xa6" => [104, "\xdbt"], "\xa7" => [16, "\xdbt"], "\xa8" => [77, "\xdb "], "\xa9" => [18, "\xdb "], "\xaa" => [77, "\xdb%"], "\xab" => [18, "\xdb%"], "\xac" => [77, "\xdb-"], "\xad" => [18, "\xdb-"], "\xae" => [77, "\xdb."], "\xaf" => [18, "\xdb."], "\xb0" => [77, "\xdb/"], "\xb1" => [18, "\xdb/"], "\xb2" => [77, "\xdb3"], "\xb3" => [18, "\xdb3"], "\xb4" => [77, "\xdb4"], "\xb5" => [18, "\xdb4"], "\xb6" => [77, "\xdb5"], "\xb7" => [18, "\xdb5"], "\xb8" => [77, "\xdb6"], "\xb9" => [18, "\xdb6"], "\xba" => [77, "\xdb7"], "\xbb" => [18, "\xdb7"], "\xbc" => [77, "\xdb8"], "\xbd" => [18, "\xdb8"], "\xbe" => [77, "\xdb9"], "\xbf" => [18, "\xdb9"], "\xc0" => [77, "\xdb="], "\xc1" => [18, "\xdb="], "\xc2" => [77, "\xdbA"], "\xc3" => [18, "\xdbA"], "\xc4" => [77, "\xdb_"], "\xc5" => [18, "\xdb_"], "\xc6" => [77, "\xdbb"], "\xc7" => [18, "\xdbb"], "\xc8" => [77, "\xdbd"], "\xc9" => [18, "\xdbd"], "\xca" => [77, "\xdbf"], "\xcb" => [18, "\xdbf"], "\xcc" => [77, "\xdbg"], "\xcd" => [18, "\xdbg"], "\xce" => [77, "\xdbh"], "\xcf" => [18, "\xdbh"], "\xd0" => [77, "\xdbl"], "\xd1" => [18, "\xdbl"], "\xd2" => [77, "\xdbm"], "\xd3" => [18, "\xdbm"], "\xd4" => [77, "\xdbn"], "\xd5" => [18, "\xdbn"], "\xd6" => [77, "\xdbp"], "\xd7" => [18, "\xdbp"], "\xd8" => [77, "\xdbr"], "\xd9" => [18, "\xdbr"], "\xda" => [77, "\xdbu"], "\xdb" => [18, "\xdbu"], "\xdc" => [0, "\xdb:"], "\xdd" => [0, "\xdbB"], "\xde" => [0, "\xdbC"], "\xdf" => [0, "\xdbD"], "\xe0" => [0, "\xdbE"], "\xe1" => [0, "\xdbF"], "\xe2" => [0, "\xdbG"], "\xe3" => [0, "\xdbH"], "\xe4" => [0, "\xdbI"], "\xe5" => [0, "\xdbJ"], "\xe6" => [0, "\xdbK"], "\xe7" => [0, "\xdbL"], "\xe8" => [0, "\xdbM"], "\xe9" => [0, "\xdbN"], "\xea" => [0, "\xdbO"], "\xeb" => [0, "\xdbP"], "\xec" => [0, "\xdbQ"], "\xed" => [0, "\xdbR"], "\xee" => [0, "\xdbS"], "\xef" => [0, "\xdbT"], "\xf0" => [0, "\xdbU"], "\xf1" => [0, "\xdbV"], "\xf2" => [0, "\xdbW"], "\xf3" => [0, "\xdbY"], "\xf4" => [0, "\xdbj"], "\xf5" => [0, "\xdbk"], "\xf6" => [0, "\xdbq"], "\xf7" => [0, "\xdbv"], "\xf8" => [0, "\xdbw"], "\xf9" => [0, "\xdbx"], "\xfa" => [0, "\xdby"], "\xfb" => [0, "\xdbz"], "\xfc" => [82, "\xdb"], "\xfd" => [87, "\xdb"], "\xfe" => [130, "\xdb"], "\xff" => [9, "\xdb"]], ["\x00" => [94, "\xde0"], "\x01" => [76, "\xde0"], "\x02" => [104, "\xde0"], "\x03" => [16, "\xde0"], "\x04" => [94, "\xde1"], "\x05" => [76, "\xde1"], "\x06" => [104, "\xde1"], "\x07" => [16, "\xde1"], "\x08" => [94, "\xde2"], "\t" => [76, "\xde2"], "\n" => [104, "\xde2"], "\v" => [16, "\xde2"], "\f" => [94, "\xdea"], "\r" => [76, "\xdea"], "\x0e" => [104, "\xdea"], "\x0f" => [16, "\xdea"], "\x10" => [94, "\xdec"], "\x11" => [76, "\xdec"], "\x12" => [104, "\xdec"], "\x13" => [16, "\xdec"], "\x14" => [94, "\xdee"], "\x15" => [76, "\xdee"], "\x16" => [104, "\xdee"], "\x17" => [16, "\xdee"], "\x18" => [94, "\xdei"], "\x19" => [76, "\xdei"], "\x1a" => [104, "\xdei"], "\x1b" => [16, "\xdei"], "\x1c" => [94, "\xdeo"], "\x1d" => [76, "\xdeo"], "\x1e" => [104, "\xdeo"], "\x1f" => [16, "\xdeo"], " " => [94, "\xdes"], "!" => [76, "\xdes"], "\"" => [104, "\xdes"], "#" => [16, "\xdes"], "\$" => [94, "\xdet"], "%" => [76, "\xdet"], "&" => [104, "\xdet"], "'" => [16, "\xdet"], "(" => [77, "\xde "], ")" => [18, "\xde "], "*" => [77, "\xde%"], "+" => [18, "\xde%"], "," => [77, "\xde-"], "-" => [18, "\xde-"], "." => [77, "\xde."], "/" => [18, "\xde."], [77, "\xde/"], [18, "\xde/"], [77, "\xde3"], [18, "\xde3"], [77, "\xde4"], [18, "\xde4"], [77, "\xde5"], [18, "\xde5"], [77, "\xde6"], [18, "\xde6"], ":" => [77, "\xde7"], ";" => [18, "\xde7"], "<" => [77, "\xde8"], "=" => [18, "\xde8"], ">" => [77, "\xde9"], "?" => [18, "\xde9"], "@" => [77, "\xde="], "A" => [18, "\xde="], "B" => [77, "\xdeA"], "C" => [18, "\xdeA"], "D" => [77, "\xde_"], "E" => [18, "\xde_"], "F" => [77, "\xdeb"], "G" => [18, "\xdeb"], "H" => [77, "\xded"], "I" => [18, "\xded"], "J" => [77, "\xdef"], "K" => [18, "\xdef"], "L" => [77, "\xdeg"], "M" => [18, "\xdeg"], "N" => [77, "\xdeh"], "O" => [18, "\xdeh"], "P" => [77, "\xdel"], "Q" => [18, "\xdel"], "R" => [77, "\xdem"], "S" => [18, "\xdem"], "T" => [77, "\xden"], "U" => [18, "\xden"], "V" => [77, "\xdep"], "W" => [18, "\xdep"], "X" => [77, "\xder"], "Y" => [18, "\xder"], "Z" => [77, "\xdeu"], "[" => [18, "\xdeu"], "\\" => [0, "\xde:"], "]" => [0, "\xdeB"], "^" => [0, "\xdeC"], "_" => [0, "\xdeD"], "`" => [0, "\xdeE"], "a" => [0, "\xdeF"], "b" => [0, "\xdeG"], "c" => [0, "\xdeH"], "d" => [0, "\xdeI"], "e" => [0, "\xdeJ"], "f" => [0, "\xdeK"], "g" => [0, "\xdeL"], "h" => [0, "\xdeM"], "i" => [0, "\xdeN"], "j" => [0, "\xdeO"], "k" => [0, "\xdeP"], "l" => [0, "\xdeQ"], "m" => [0, "\xdeR"], "n" => [0, "\xdeS"], "o" => [0, "\xdeT"], "p" => [0, "\xdeU"], "q" => [0, "\xdeV"], "r" => [0, "\xdeW"], "s" => [0, "\xdeY"], "t" => [0, "\xdej"], "u" => [0, "\xdek"], "v" => [0, "\xdeq"], "w" => [0, "\xdev"], "x" => [0, "\xdew"], "y" => [0, "\xdex"], "z" => [0, "\xdey"], "{" => [0, "\xdez"], "|" => [82, "\xde"], "}" => [87, "\xde"], "~" => [130, "\xde"], "" => [9, "\xde"], "\x80" => [94, "\xdf0"], "\x81" => [76, "\xdf0"], "\x82" => [104, "\xdf0"], "\x83" => [16, "\xdf0"], "\x84" => [94, "\xdf1"], "\x85" => [76, "\xdf1"], "\x86" => [104, "\xdf1"], "\x87" => [16, "\xdf1"], "\x88" => [94, "\xdf2"], "\x89" => [76, "\xdf2"], "\x8a" => [104, "\xdf2"], "\x8b" => [16, "\xdf2"], "\x8c" => [94, "\xdfa"], "\x8d" => [76, "\xdfa"], "\x8e" => [104, "\xdfa"], "\x8f" => [16, "\xdfa"], "\x90" => [94, "\xdfc"], "\x91" => [76, "\xdfc"], "\x92" => [104, "\xdfc"], "\x93" => [16, "\xdfc"], "\x94" => [94, "\xdfe"], "\x95" => [76, "\xdfe"], "\x96" => [104, "\xdfe"], "\x97" => [16, "\xdfe"], "\x98" => [94, "\xdfi"], "\x99" => [76, "\xdfi"], "\x9a" => [104, "\xdfi"], "\x9b" => [16, "\xdfi"], "\x9c" => [94, "\xdfo"], "\x9d" => [76, "\xdfo"], "\x9e" => [104, "\xdfo"], "\x9f" => [16, "\xdfo"], "\xa0" => [94, "\xdfs"], "\xa1" => [76, "\xdfs"], "\xa2" => [104, "\xdfs"], "\xa3" => [16, "\xdfs"], "\xa4" => [94, "\xdft"], "\xa5" => [76, "\xdft"], "\xa6" => [104, "\xdft"], "\xa7" => [16, "\xdft"], "\xa8" => [77, "\xdf "], "\xa9" => [18, "\xdf "], "\xaa" => [77, "\xdf%"], "\xab" => [18, "\xdf%"], "\xac" => [77, "\xdf-"], "\xad" => [18, "\xdf-"], "\xae" => [77, "\xdf."], "\xaf" => [18, "\xdf."], "\xb0" => [77, "\xdf/"], "\xb1" => [18, "\xdf/"], "\xb2" => [77, "\xdf3"], "\xb3" => [18, "\xdf3"], "\xb4" => [77, "\xdf4"], "\xb5" => [18, "\xdf4"], "\xb6" => [77, "\xdf5"], "\xb7" => [18, "\xdf5"], "\xb8" => [77, "\xdf6"], "\xb9" => [18, "\xdf6"], "\xba" => [77, "\xdf7"], "\xbb" => [18, "\xdf7"], "\xbc" => [77, "\xdf8"], "\xbd" => [18, "\xdf8"], "\xbe" => [77, "\xdf9"], "\xbf" => [18, "\xdf9"], "\xc0" => [77, "\xdf="], "\xc1" => [18, "\xdf="], "\xc2" => [77, "\xdfA"], "\xc3" => [18, "\xdfA"], "\xc4" => [77, "\xdf_"], "\xc5" => [18, "\xdf_"], "\xc6" => [77, "\xdfb"], "\xc7" => [18, "\xdfb"], "\xc8" => [77, "\xdfd"], "\xc9" => [18, "\xdfd"], "\xca" => [77, "\xdff"], "\xcb" => [18, "\xdff"], "\xcc" => [77, "\xdfg"], "\xcd" => [18, "\xdfg"], "\xce" => [77, "\xdfh"], "\xcf" => [18, "\xdfh"], "\xd0" => [77, "\xdfl"], "\xd1" => [18, "\xdfl"], "\xd2" => [77, "\xdfm"], "\xd3" => [18, "\xdfm"], "\xd4" => [77, "\xdfn"], "\xd5" => [18, "\xdfn"], "\xd6" => [77, "\xdfp"], "\xd7" => [18, "\xdfp"], "\xd8" => [77, "\xdfr"], "\xd9" => [18, "\xdfr"], "\xda" => [77, "\xdfu"], "\xdb" => [18, "\xdfu"], "\xdc" => [0, "\xdf:"], "\xdd" => [0, "\xdfB"], "\xde" => [0, "\xdfC"], "\xdf" => [0, "\xdfD"], "\xe0" => [0, "\xdfE"], "\xe1" => [0, "\xdfF"], "\xe2" => [0, "\xdfG"], "\xe3" => [0, "\xdfH"], "\xe4" => [0, "\xdfI"], "\xe5" => [0, "\xdfJ"], "\xe6" => [0, "\xdfK"], "\xe7" => [0, "\xdfL"], "\xe8" => [0, "\xdfM"], "\xe9" => [0, "\xdfN"], "\xea" => [0, "\xdfO"], "\xeb" => [0, "\xdfP"], "\xec" => [0, "\xdfQ"], "\xed" => [0, "\xdfR"], "\xee" => [0, "\xdfS"], "\xef" => [0, "\xdfT"], "\xf0" => [0, "\xdfU"], "\xf1" => [0, "\xdfV"], "\xf2" => [0, "\xdfW"], "\xf3" => [0, "\xdfY"], "\xf4" => [0, "\xdfj"], "\xf5" => [0, "\xdfk"], "\xf6" => [0, "\xdfq"], "\xf7" => [0, "\xdfv"], "\xf8" => [0, "\xdfw"], "\xf9" => [0, "\xdfx"], "\xfa" => [0, "\xdfy"], "\xfb" => [0, "\xdfz"], "\xfc" => [82, "\xdf"], "\xfd" => [87, "\xdf"], "\xfe" => [130, "\xdf"], "\xff" => [9, "\xdf"]], ["\x00" => [77, "\xde0"], "\x01" => [18, "\xde0"], "\x02" => [77, "\xde1"], "\x03" => [18, "\xde1"], "\x04" => [77, "\xde2"], "\x05" => [18, "\xde2"], "\x06" => [77, "\xdea"], "\x07" => [18, "\xdea"], "\x08" => [77, "\xdec"], "\t" => [18, "\xdec"], "\n" => [77, "\xdee"], "\v" => [18, "\xdee"], "\f" => [77, "\xdei"], "\r" => [18, "\xdei"], "\x0e" => [77, "\xdeo"], "\x0f" => [18, "\xdeo"], "\x10" => [77, "\xdes"], "\x11" => [18, "\xdes"], "\x12" => [77, "\xdet"], "\x13" => [18, "\xdet"], "\x14" => [0, "\xde "], "\x15" => [0, "\xde%"], "\x16" => [0, "\xde-"], "\x17" => [0, "\xde."], "\x18" => [0, "\xde/"], "\x19" => [0, "\xde3"], "\x1a" => [0, "\xde4"], "\x1b" => [0, "\xde5"], "\x1c" => [0, "\xde6"], "\x1d" => [0, "\xde7"], "\x1e" => [0, "\xde8"], "\x1f" => [0, "\xde9"], " " => [0, "\xde="], "!" => [0, "\xdeA"], "\"" => [0, "\xde_"], "#" => [0, "\xdeb"], "\$" => [0, "\xded"], "%" => [0, "\xdef"], "&" => [0, "\xdeg"], "'" => [0, "\xdeh"], "(" => [0, "\xdel"], ")" => [0, "\xdem"], "*" => [0, "\xden"], "+" => [0, "\xdep"], "," => [0, "\xder"], "-" => [0, "\xdeu"], "." => [100, "\xde"], "/" => [110, "\xde"], [111, "\xde"], [115, "\xde"], [116, "\xde"], [118, "\xde"], [119, "\xde"], [122, "\xde"], [123, "\xde"], [125, "\xde"], [126, "\xde"], [129, "\xde"], ":" => [143, "\xde"], ";" => [148, "\xde"], "<" => [151, "\xde"], "=" => [153, "\xde"], ">" => [83, "\xde"], "?" => [10, "\xde"], "@" => [77, "\xdf0"], "A" => [18, "\xdf0"], "B" => [77, "\xdf1"], "C" => [18, "\xdf1"], "D" => [77, "\xdf2"], "E" => [18, "\xdf2"], "F" => [77, "\xdfa"], "G" => [18, "\xdfa"], "H" => [77, "\xdfc"], "I" => [18, "\xdfc"], "J" => [77, "\xdfe"], "K" => [18, "\xdfe"], "L" => [77, "\xdfi"], "M" => [18, "\xdfi"], "N" => [77, "\xdfo"], "O" => [18, "\xdfo"], "P" => [77, "\xdfs"], "Q" => [18, "\xdfs"], "R" => [77, "\xdft"], "S" => [18, "\xdft"], "T" => [0, "\xdf "], "U" => [0, "\xdf%"], "V" => [0, "\xdf-"], "W" => [0, "\xdf."], "X" => [0, "\xdf/"], "Y" => [0, "\xdf3"], "Z" => [0, "\xdf4"], "[" => [0, "\xdf5"], "\\" => [0, "\xdf6"], "]" => [0, "\xdf7"], "^" => [0, "\xdf8"], "_" => [0, "\xdf9"], "`" => [0, "\xdf="], "a" => [0, "\xdfA"], "b" => [0, "\xdf_"], "c" => [0, "\xdfb"], "d" => [0, "\xdfd"], "e" => [0, "\xdff"], "f" => [0, "\xdfg"], "g" => [0, "\xdfh"], "h" => [0, "\xdfl"], "i" => [0, "\xdfm"], "j" => [0, "\xdfn"], "k" => [0, "\xdfp"], "l" => [0, "\xdfr"], "m" => [0, "\xdfu"], "n" => [100, "\xdf"], "o" => [110, "\xdf"], "p" => [111, "\xdf"], "q" => [115, "\xdf"], "r" => [116, "\xdf"], "s" => [118, "\xdf"], "t" => [119, "\xdf"], "u" => [122, "\xdf"], "v" => [123, "\xdf"], "w" => [125, "\xdf"], "x" => [126, "\xdf"], "y" => [129, "\xdf"], "z" => [143, "\xdf"], "{" => [148, "\xdf"], "|" => [151, "\xdf"], "}" => [153, "\xdf"], "~" => [83, "\xdf"], "" => [10, "\xdf"], "\x80" => [77, "\xf10"], "\x81" => [18, "\xf10"], "\x82" => [77, "\xf11"], "\x83" => [18, "\xf11"], "\x84" => [77, "\xf12"], "\x85" => [18, "\xf12"], "\x86" => [77, "\xf1a"], "\x87" => [18, "\xf1a"], "\x88" => [77, "\xf1c"], "\x89" => [18, "\xf1c"], "\x8a" => [77, "\xf1e"], "\x8b" => [18, "\xf1e"], "\x8c" => [77, "\xf1i"], "\x8d" => [18, "\xf1i"], "\x8e" => [77, "\xf1o"], "\x8f" => [18, "\xf1o"], "\x90" => [77, "\xf1s"], "\x91" => [18, "\xf1s"], "\x92" => [77, "\xf1t"], "\x93" => [18, "\xf1t"], "\x94" => [0, "\xf1 "], "\x95" => [0, "\xf1%"], "\x96" => [0, "\xf1-"], "\x97" => [0, "\xf1."], "\x98" => [0, "\xf1/"], "\x99" => [0, "\xf13"], "\x9a" => [0, "\xf14"], "\x9b" => [0, "\xf15"], "\x9c" => [0, "\xf16"], "\x9d" => [0, "\xf17"], "\x9e" => [0, "\xf18"], "\x9f" => [0, "\xf19"], "\xa0" => [0, "\xf1="], "\xa1" => [0, "\xf1A"], "\xa2" => [0, "\xf1_"], "\xa3" => [0, "\xf1b"], "\xa4" => [0, "\xf1d"], "\xa5" => [0, "\xf1f"], "\xa6" => [0, "\xf1g"], "\xa7" => [0, "\xf1h"], "\xa8" => [0, "\xf1l"], "\xa9" => [0, "\xf1m"], "\xaa" => [0, "\xf1n"], "\xab" => [0, "\xf1p"], "\xac" => [0, "\xf1r"], "\xad" => [0, "\xf1u"], "\xae" => [100, "\xf1"], "\xaf" => [110, "\xf1"], "\xb0" => [111, "\xf1"], "\xb1" => [115, "\xf1"], "\xb2" => [116, "\xf1"], "\xb3" => [118, "\xf1"], "\xb4" => [119, "\xf1"], "\xb5" => [122, "\xf1"], "\xb6" => [123, "\xf1"], "\xb7" => [125, "\xf1"], "\xb8" => [126, "\xf1"], "\xb9" => [129, "\xf1"], "\xba" => [143, "\xf1"], "\xbb" => [148, "\xf1"], "\xbc" => [151, "\xf1"], "\xbd" => [153, "\xf1"], "\xbe" => [83, "\xf1"], "\xbf" => [10, "\xf1"], "\xc0" => [77, "\xf40"], "\xc1" => [18, "\xf40"], "\xc2" => [77, "\xf41"], "\xc3" => [18, "\xf41"], "\xc4" => [77, "\xf42"], "\xc5" => [18, "\xf42"], "\xc6" => [77, "\xf4a"], "\xc7" => [18, "\xf4a"], "\xc8" => [77, "\xf4c"], "\xc9" => [18, "\xf4c"], "\xca" => [77, "\xf4e"], "\xcb" => [18, "\xf4e"], "\xcc" => [77, "\xf4i"], "\xcd" => [18, "\xf4i"], "\xce" => [77, "\xf4o"], "\xcf" => [18, "\xf4o"], "\xd0" => [77, "\xf4s"], "\xd1" => [18, "\xf4s"], "\xd2" => [77, "\xf4t"], "\xd3" => [18, "\xf4t"], "\xd4" => [0, "\xf4 "], "\xd5" => [0, "\xf4%"], "\xd6" => [0, "\xf4-"], "\xd7" => [0, "\xf4."], "\xd8" => [0, "\xf4/"], "\xd9" => [0, "\xf43"], "\xda" => [0, "\xf44"], "\xdb" => [0, "\xf45"], "\xdc" => [0, "\xf46"], "\xdd" => [0, "\xf47"], "\xde" => [0, "\xf48"], "\xdf" => [0, "\xf49"], "\xe0" => [0, "\xf4="], "\xe1" => [0, "\xf4A"], "\xe2" => [0, "\xf4_"], "\xe3" => [0, "\xf4b"], "\xe4" => [0, "\xf4d"], "\xe5" => [0, "\xf4f"], "\xe6" => [0, "\xf4g"], "\xe7" => [0, "\xf4h"], "\xe8" => [0, "\xf4l"], "\xe9" => [0, "\xf4m"], "\xea" => [0, "\xf4n"], "\xeb" => [0, "\xf4p"], "\xec" => [0, "\xf4r"], "\xed" => [0, "\xf4u"], "\xee" => [100, "\xf4"], "\xef" => [110, "\xf4"], "\xf0" => [111, "\xf4"], "\xf1" => [115, "\xf4"], "\xf2" => [116, "\xf4"], "\xf3" => [118, "\xf4"], "\xf4" => [119, "\xf4"], "\xf5" => [122, "\xf4"], "\xf6" => [123, "\xf4"], "\xf7" => [125, "\xf4"], "\xf8" => [126, "\xf4"], "\xf9" => [129, "\xf4"], "\xfa" => [143, "\xf4"], "\xfb" => [148, "\xf4"], "\xfc" => [151, "\xf4"], "\xfd" => [153, "\xf4"], "\xfe" => [83, "\xf4"], "\xff" => [10, "\xf4"]], ["\x00" => [94, "\xe00"], "\x01" => [76, "\xe00"], "\x02" => [104, "\xe00"], "\x03" => [16, "\xe00"], "\x04" => [94, "\xe01"], "\x05" => [76, "\xe01"], "\x06" => [104, "\xe01"], "\x07" => [16, "\xe01"], "\x08" => [94, "\xe02"], "\t" => [76, "\xe02"], "\n" => [104, "\xe02"], "\v" => [16, "\xe02"], "\f" => [94, "\xe0a"], "\r" => [76, "\xe0a"], "\x0e" => [104, "\xe0a"], "\x0f" => [16, "\xe0a"], "\x10" => [94, "\xe0c"], "\x11" => [76, "\xe0c"], "\x12" => [104, "\xe0c"], "\x13" => [16, "\xe0c"], "\x14" => [94, "\xe0e"], "\x15" => [76, "\xe0e"], "\x16" => [104, "\xe0e"], "\x17" => [16, "\xe0e"], "\x18" => [94, "\xe0i"], "\x19" => [76, "\xe0i"], "\x1a" => [104, "\xe0i"], "\x1b" => [16, "\xe0i"], "\x1c" => [94, "\xe0o"], "\x1d" => [76, "\xe0o"], "\x1e" => [104, "\xe0o"], "\x1f" => [16, "\xe0o"], " " => [94, "\xe0s"], "!" => [76, "\xe0s"], "\"" => [104, "\xe0s"], "#" => [16, "\xe0s"], "\$" => [94, "\xe0t"], "%" => [76, "\xe0t"], "&" => [104, "\xe0t"], "'" => [16, "\xe0t"], "(" => [77, "\xe0 "], ")" => [18, "\xe0 "], "*" => [77, "\xe0%"], "+" => [18, "\xe0%"], "," => [77, "\xe0-"], "-" => [18, "\xe0-"], "." => [77, "\xe0."], "/" => [18, "\xe0."], [77, "\xe0/"], [18, "\xe0/"], [77, "\xe03"], [18, "\xe03"], [77, "\xe04"], [18, "\xe04"], [77, "\xe05"], [18, "\xe05"], [77, "\xe06"], [18, "\xe06"], ":" => [77, "\xe07"], ";" => [18, "\xe07"], "<" => [77, "\xe08"], "=" => [18, "\xe08"], ">" => [77, "\xe09"], "?" => [18, "\xe09"], "@" => [77, "\xe0="], "A" => [18, "\xe0="], "B" => [77, "\xe0A"], "C" => [18, "\xe0A"], "D" => [77, "\xe0_"], "E" => [18, "\xe0_"], "F" => [77, "\xe0b"], "G" => [18, "\xe0b"], "H" => [77, "\xe0d"], "I" => [18, "\xe0d"], "J" => [77, "\xe0f"], "K" => [18, "\xe0f"], "L" => [77, "\xe0g"], "M" => [18, "\xe0g"], "N" => [77, "\xe0h"], "O" => [18, "\xe0h"], "P" => [77, "\xe0l"], "Q" => [18, "\xe0l"], "R" => [77, "\xe0m"], "S" => [18, "\xe0m"], "T" => [77, "\xe0n"], "U" => [18, "\xe0n"], "V" => [77, "\xe0p"], "W" => [18, "\xe0p"], "X" => [77, "\xe0r"], "Y" => [18, "\xe0r"], "Z" => [77, "\xe0u"], "[" => [18, "\xe0u"], "\\" => [0, "\xe0:"], "]" => [0, "\xe0B"], "^" => [0, "\xe0C"], "_" => [0, "\xe0D"], "`" => [0, "\xe0E"], "a" => [0, "\xe0F"], "b" => [0, "\xe0G"], "c" => [0, "\xe0H"], "d" => [0, "\xe0I"], "e" => [0, "\xe0J"], "f" => [0, "\xe0K"], "g" => [0, "\xe0L"], "h" => [0, "\xe0M"], "i" => [0, "\xe0N"], "j" => [0, "\xe0O"], "k" => [0, "\xe0P"], "l" => [0, "\xe0Q"], "m" => [0, "\xe0R"], "n" => [0, "\xe0S"], "o" => [0, "\xe0T"], "p" => [0, "\xe0U"], "q" => [0, "\xe0V"], "r" => [0, "\xe0W"], "s" => [0, "\xe0Y"], "t" => [0, "\xe0j"], "u" => [0, "\xe0k"], "v" => [0, "\xe0q"], "w" => [0, "\xe0v"], "x" => [0, "\xe0w"], "y" => [0, "\xe0x"], "z" => [0, "\xe0y"], "{" => [0, "\xe0z"], "|" => [82, "\xe0"], "}" => [87, "\xe0"], "~" => [130, "\xe0"], "" => [9, "\xe0"], "\x80" => [94, "\xe20"], "\x81" => [76, "\xe20"], "\x82" => [104, "\xe20"], "\x83" => [16, "\xe20"], "\x84" => [94, "\xe21"], "\x85" => [76, "\xe21"], "\x86" => [104, "\xe21"], "\x87" => [16, "\xe21"], "\x88" => [94, "\xe22"], "\x89" => [76, "\xe22"], "\x8a" => [104, "\xe22"], "\x8b" => [16, "\xe22"], "\x8c" => [94, "\xe2a"], "\x8d" => [76, "\xe2a"], "\x8e" => [104, "\xe2a"], "\x8f" => [16, "\xe2a"], "\x90" => [94, "\xe2c"], "\x91" => [76, "\xe2c"], "\x92" => [104, "\xe2c"], "\x93" => [16, "\xe2c"], "\x94" => [94, "\xe2e"], "\x95" => [76, "\xe2e"], "\x96" => [104, "\xe2e"], "\x97" => [16, "\xe2e"], "\x98" => [94, "\xe2i"], "\x99" => [76, "\xe2i"], "\x9a" => [104, "\xe2i"], "\x9b" => [16, "\xe2i"], "\x9c" => [94, "\xe2o"], "\x9d" => [76, "\xe2o"], "\x9e" => [104, "\xe2o"], "\x9f" => [16, "\xe2o"], "\xa0" => [94, "\xe2s"], "\xa1" => [76, "\xe2s"], "\xa2" => [104, "\xe2s"], "\xa3" => [16, "\xe2s"], "\xa4" => [94, "\xe2t"], "\xa5" => [76, "\xe2t"], "\xa6" => [104, "\xe2t"], "\xa7" => [16, "\xe2t"], "\xa8" => [77, "\xe2 "], "\xa9" => [18, "\xe2 "], "\xaa" => [77, "\xe2%"], "\xab" => [18, "\xe2%"], "\xac" => [77, "\xe2-"], "\xad" => [18, "\xe2-"], "\xae" => [77, "\xe2."], "\xaf" => [18, "\xe2."], "\xb0" => [77, "\xe2/"], "\xb1" => [18, "\xe2/"], "\xb2" => [77, "\xe23"], "\xb3" => [18, "\xe23"], "\xb4" => [77, "\xe24"], "\xb5" => [18, "\xe24"], "\xb6" => [77, "\xe25"], "\xb7" => [18, "\xe25"], "\xb8" => [77, "\xe26"], "\xb9" => [18, "\xe26"], "\xba" => [77, "\xe27"], "\xbb" => [18, "\xe27"], "\xbc" => [77, "\xe28"], "\xbd" => [18, "\xe28"], "\xbe" => [77, "\xe29"], "\xbf" => [18, "\xe29"], "\xc0" => [77, "\xe2="], "\xc1" => [18, "\xe2="], "\xc2" => [77, "\xe2A"], "\xc3" => [18, "\xe2A"], "\xc4" => [77, "\xe2_"], "\xc5" => [18, "\xe2_"], "\xc6" => [77, "\xe2b"], "\xc7" => [18, "\xe2b"], "\xc8" => [77, "\xe2d"], "\xc9" => [18, "\xe2d"], "\xca" => [77, "\xe2f"], "\xcb" => [18, "\xe2f"], "\xcc" => [77, "\xe2g"], "\xcd" => [18, "\xe2g"], "\xce" => [77, "\xe2h"], "\xcf" => [18, "\xe2h"], "\xd0" => [77, "\xe2l"], "\xd1" => [18, "\xe2l"], "\xd2" => [77, "\xe2m"], "\xd3" => [18, "\xe2m"], "\xd4" => [77, "\xe2n"], "\xd5" => [18, "\xe2n"], "\xd6" => [77, "\xe2p"], "\xd7" => [18, "\xe2p"], "\xd8" => [77, "\xe2r"], "\xd9" => [18, "\xe2r"], "\xda" => [77, "\xe2u"], "\xdb" => [18, "\xe2u"], "\xdc" => [0, "\xe2:"], "\xdd" => [0, "\xe2B"], "\xde" => [0, "\xe2C"], "\xdf" => [0, "\xe2D"], "\xe0" => [0, "\xe2E"], "\xe1" => [0, "\xe2F"], "\xe2" => [0, "\xe2G"], "\xe3" => [0, "\xe2H"], "\xe4" => [0, "\xe2I"], "\xe5" => [0, "\xe2J"], "\xe6" => [0, "\xe2K"], "\xe7" => [0, "\xe2L"], "\xe8" => [0, "\xe2M"], "\xe9" => [0, "\xe2N"], "\xea" => [0, "\xe2O"], "\xeb" => [0, "\xe2P"], "\xec" => [0, "\xe2Q"], "\xed" => [0, "\xe2R"], "\xee" => [0, "\xe2S"], "\xef" => [0, "\xe2T"], "\xf0" => [0, "\xe2U"], "\xf1" => [0, "\xe2V"], "\xf2" => [0, "\xe2W"], "\xf3" => [0, "\xe2Y"], "\xf4" => [0, "\xe2j"], "\xf5" => [0, "\xe2k"], "\xf6" => [0, "\xe2q"], "\xf7" => [0, "\xe2v"], "\xf8" => [0, "\xe2w"], "\xf9" => [0, "\xe2x"], "\xfa" => [0, "\xe2y"], "\xfb" => [0, "\xe2z"], "\xfc" => [82, "\xe2"], "\xfd" => [87, "\xe2"], "\xfe" => [130, "\xe2"], "\xff" => [9, "\xe2"]], ["\x00" => [94, "\xe30"], "\x01" => [76, "\xe30"], "\x02" => [104, "\xe30"], "\x03" => [16, "\xe30"], "\x04" => [94, "\xe31"], "\x05" => [76, "\xe31"], "\x06" => [104, "\xe31"], "\x07" => [16, "\xe31"], "\x08" => [94, "\xe32"], "\t" => [76, "\xe32"], "\n" => [104, "\xe32"], "\v" => [16, "\xe32"], "\f" => [94, "\xe3a"], "\r" => [76, "\xe3a"], "\x0e" => [104, "\xe3a"], "\x0f" => [16, "\xe3a"], "\x10" => [94, "\xe3c"], "\x11" => [76, "\xe3c"], "\x12" => [104, "\xe3c"], "\x13" => [16, "\xe3c"], "\x14" => [94, "\xe3e"], "\x15" => [76, "\xe3e"], "\x16" => [104, "\xe3e"], "\x17" => [16, "\xe3e"], "\x18" => [94, "\xe3i"], "\x19" => [76, "\xe3i"], "\x1a" => [104, "\xe3i"], "\x1b" => [16, "\xe3i"], "\x1c" => [94, "\xe3o"], "\x1d" => [76, "\xe3o"], "\x1e" => [104, "\xe3o"], "\x1f" => [16, "\xe3o"], " " => [94, "\xe3s"], "!" => [76, "\xe3s"], "\"" => [104, "\xe3s"], "#" => [16, "\xe3s"], "\$" => [94, "\xe3t"], "%" => [76, "\xe3t"], "&" => [104, "\xe3t"], "'" => [16, "\xe3t"], "(" => [77, "\xe3 "], ")" => [18, "\xe3 "], "*" => [77, "\xe3%"], "+" => [18, "\xe3%"], "," => [77, "\xe3-"], "-" => [18, "\xe3-"], "." => [77, "\xe3."], "/" => [18, "\xe3."], [77, "\xe3/"], [18, "\xe3/"], [77, "\xe33"], [18, "\xe33"], [77, "\xe34"], [18, "\xe34"], [77, "\xe35"], [18, "\xe35"], [77, "\xe36"], [18, "\xe36"], ":" => [77, "\xe37"], ";" => [18, "\xe37"], "<" => [77, "\xe38"], "=" => [18, "\xe38"], ">" => [77, "\xe39"], "?" => [18, "\xe39"], "@" => [77, "\xe3="], "A" => [18, "\xe3="], "B" => [77, "\xe3A"], "C" => [18, "\xe3A"], "D" => [77, "\xe3_"], "E" => [18, "\xe3_"], "F" => [77, "\xe3b"], "G" => [18, "\xe3b"], "H" => [77, "\xe3d"], "I" => [18, "\xe3d"], "J" => [77, "\xe3f"], "K" => [18, "\xe3f"], "L" => [77, "\xe3g"], "M" => [18, "\xe3g"], "N" => [77, "\xe3h"], "O" => [18, "\xe3h"], "P" => [77, "\xe3l"], "Q" => [18, "\xe3l"], "R" => [77, "\xe3m"], "S" => [18, "\xe3m"], "T" => [77, "\xe3n"], "U" => [18, "\xe3n"], "V" => [77, "\xe3p"], "W" => [18, "\xe3p"], "X" => [77, "\xe3r"], "Y" => [18, "\xe3r"], "Z" => [77, "\xe3u"], "[" => [18, "\xe3u"], "\\" => [0, "\xe3:"], "]" => [0, "\xe3B"], "^" => [0, "\xe3C"], "_" => [0, "\xe3D"], "`" => [0, "\xe3E"], "a" => [0, "\xe3F"], "b" => [0, "\xe3G"], "c" => [0, "\xe3H"], "d" => [0, "\xe3I"], "e" => [0, "\xe3J"], "f" => [0, "\xe3K"], "g" => [0, "\xe3L"], "h" => [0, "\xe3M"], "i" => [0, "\xe3N"], "j" => [0, "\xe3O"], "k" => [0, "\xe3P"], "l" => [0, "\xe3Q"], "m" => [0, "\xe3R"], "n" => [0, "\xe3S"], "o" => [0, "\xe3T"], "p" => [0, "\xe3U"], "q" => [0, "\xe3V"], "r" => [0, "\xe3W"], "s" => [0, "\xe3Y"], "t" => [0, "\xe3j"], "u" => [0, "\xe3k"], "v" => [0, "\xe3q"], "w" => [0, "\xe3v"], "x" => [0, "\xe3w"], "y" => [0, "\xe3x"], "z" => [0, "\xe3y"], "{" => [0, "\xe3z"], "|" => [82, "\xe3"], "}" => [87, "\xe3"], "~" => [130, "\xe3"], "" => [9, "\xe3"], "\x80" => [94, "\xe50"], "\x81" => [76, "\xe50"], "\x82" => [104, "\xe50"], "\x83" => [16, "\xe50"], "\x84" => [94, "\xe51"], "\x85" => [76, "\xe51"], "\x86" => [104, "\xe51"], "\x87" => [16, "\xe51"], "\x88" => [94, "\xe52"], "\x89" => [76, "\xe52"], "\x8a" => [104, "\xe52"], "\x8b" => [16, "\xe52"], "\x8c" => [94, "\xe5a"], "\x8d" => [76, "\xe5a"], "\x8e" => [104, "\xe5a"], "\x8f" => [16, "\xe5a"], "\x90" => [94, "\xe5c"], "\x91" => [76, "\xe5c"], "\x92" => [104, "\xe5c"], "\x93" => [16, "\xe5c"], "\x94" => [94, "\xe5e"], "\x95" => [76, "\xe5e"], "\x96" => [104, "\xe5e"], "\x97" => [16, "\xe5e"], "\x98" => [94, "\xe5i"], "\x99" => [76, "\xe5i"], "\x9a" => [104, "\xe5i"], "\x9b" => [16, "\xe5i"], "\x9c" => [94, "\xe5o"], "\x9d" => [76, "\xe5o"], "\x9e" => [104, "\xe5o"], "\x9f" => [16, "\xe5o"], "\xa0" => [94, "\xe5s"], "\xa1" => [76, "\xe5s"], "\xa2" => [104, "\xe5s"], "\xa3" => [16, "\xe5s"], "\xa4" => [94, "\xe5t"], "\xa5" => [76, "\xe5t"], "\xa6" => [104, "\xe5t"], "\xa7" => [16, "\xe5t"], "\xa8" => [77, "\xe5 "], "\xa9" => [18, "\xe5 "], "\xaa" => [77, "\xe5%"], "\xab" => [18, "\xe5%"], "\xac" => [77, "\xe5-"], "\xad" => [18, "\xe5-"], "\xae" => [77, "\xe5."], "\xaf" => [18, "\xe5."], "\xb0" => [77, "\xe5/"], "\xb1" => [18, "\xe5/"], "\xb2" => [77, "\xe53"], "\xb3" => [18, "\xe53"], "\xb4" => [77, "\xe54"], "\xb5" => [18, "\xe54"], "\xb6" => [77, "\xe55"], "\xb7" => [18, "\xe55"], "\xb8" => [77, "\xe56"], "\xb9" => [18, "\xe56"], "\xba" => [77, "\xe57"], "\xbb" => [18, "\xe57"], "\xbc" => [77, "\xe58"], "\xbd" => [18, "\xe58"], "\xbe" => [77, "\xe59"], "\xbf" => [18, "\xe59"], "\xc0" => [77, "\xe5="], "\xc1" => [18, "\xe5="], "\xc2" => [77, "\xe5A"], "\xc3" => [18, "\xe5A"], "\xc4" => [77, "\xe5_"], "\xc5" => [18, "\xe5_"], "\xc6" => [77, "\xe5b"], "\xc7" => [18, "\xe5b"], "\xc8" => [77, "\xe5d"], "\xc9" => [18, "\xe5d"], "\xca" => [77, "\xe5f"], "\xcb" => [18, "\xe5f"], "\xcc" => [77, "\xe5g"], "\xcd" => [18, "\xe5g"], "\xce" => [77, "\xe5h"], "\xcf" => [18, "\xe5h"], "\xd0" => [77, "\xe5l"], "\xd1" => [18, "\xe5l"], "\xd2" => [77, "\xe5m"], "\xd3" => [18, "\xe5m"], "\xd4" => [77, "\xe5n"], "\xd5" => [18, "\xe5n"], "\xd6" => [77, "\xe5p"], "\xd7" => [18, "\xe5p"], "\xd8" => [77, "\xe5r"], "\xd9" => [18, "\xe5r"], "\xda" => [77, "\xe5u"], "\xdb" => [18, "\xe5u"], "\xdc" => [0, "\xe5:"], "\xdd" => [0, "\xe5B"], "\xde" => [0, "\xe5C"], "\xdf" => [0, "\xe5D"], "\xe0" => [0, "\xe5E"], "\xe1" => [0, "\xe5F"], "\xe2" => [0, "\xe5G"], "\xe3" => [0, "\xe5H"], "\xe4" => [0, "\xe5I"], "\xe5" => [0, "\xe5J"], "\xe6" => [0, "\xe5K"], "\xe7" => [0, "\xe5L"], "\xe8" => [0, "\xe5M"], "\xe9" => [0, "\xe5N"], "\xea" => [0, "\xe5O"], "\xeb" => [0, "\xe5P"], "\xec" => [0, "\xe5Q"], "\xed" => [0, "\xe5R"], "\xee" => [0, "\xe5S"], "\xef" => [0, "\xe5T"], "\xf0" => [0, "\xe5U"], "\xf1" => [0, "\xe5V"], "\xf2" => [0, "\xe5W"], "\xf3" => [0, "\xe5Y"], "\xf4" => [0, "\xe5j"], "\xf5" => [0, "\xe5k"], "\xf6" => [0, "\xe5q"], "\xf7" => [0, "\xe5v"], "\xf8" => [0, "\xe5w"], "\xf9" => [0, "\xe5x"], "\xfa" => [0, "\xe5y"], "\xfb" => [0, "\xe5z"], "\xfc" => [82, "\xe5"], "\xfd" => [87, "\xe5"], "\xfe" => [130, "\xe5"], "\xff" => [9, "\xe5"]], ["\x00" => [94, "\xe80"], "\x01" => [76, "\xe80"], "\x02" => [104, "\xe80"], "\x03" => [16, "\xe80"], "\x04" => [94, "\xe81"], "\x05" => [76, "\xe81"], "\x06" => [104, "\xe81"], "\x07" => [16, "\xe81"], "\x08" => [94, "\xe82"], "\t" => [76, "\xe82"], "\n" => [104, "\xe82"], "\v" => [16, "\xe82"], "\f" => [94, "\xe8a"], "\r" => [76, "\xe8a"], "\x0e" => [104, "\xe8a"], "\x0f" => [16, "\xe8a"], "\x10" => [94, "\xe8c"], "\x11" => [76, "\xe8c"], "\x12" => [104, "\xe8c"], "\x13" => [16, "\xe8c"], "\x14" => [94, "\xe8e"], "\x15" => [76, "\xe8e"], "\x16" => [104, "\xe8e"], "\x17" => [16, "\xe8e"], "\x18" => [94, "\xe8i"], "\x19" => [76, "\xe8i"], "\x1a" => [104, "\xe8i"], "\x1b" => [16, "\xe8i"], "\x1c" => [94, "\xe8o"], "\x1d" => [76, "\xe8o"], "\x1e" => [104, "\xe8o"], "\x1f" => [16, "\xe8o"], " " => [94, "\xe8s"], "!" => [76, "\xe8s"], "\"" => [104, "\xe8s"], "#" => [16, "\xe8s"], "\$" => [94, "\xe8t"], "%" => [76, "\xe8t"], "&" => [104, "\xe8t"], "'" => [16, "\xe8t"], "(" => [77, "\xe8 "], ")" => [18, "\xe8 "], "*" => [77, "\xe8%"], "+" => [18, "\xe8%"], "," => [77, "\xe8-"], "-" => [18, "\xe8-"], "." => [77, "\xe8."], "/" => [18, "\xe8."], [77, "\xe8/"], [18, "\xe8/"], [77, "\xe83"], [18, "\xe83"], [77, "\xe84"], [18, "\xe84"], [77, "\xe85"], [18, "\xe85"], [77, "\xe86"], [18, "\xe86"], ":" => [77, "\xe87"], ";" => [18, "\xe87"], "<" => [77, "\xe88"], "=" => [18, "\xe88"], ">" => [77, "\xe89"], "?" => [18, "\xe89"], "@" => [77, "\xe8="], "A" => [18, "\xe8="], "B" => [77, "\xe8A"], "C" => [18, "\xe8A"], "D" => [77, "\xe8_"], "E" => [18, "\xe8_"], "F" => [77, "\xe8b"], "G" => [18, "\xe8b"], "H" => [77, "\xe8d"], "I" => [18, "\xe8d"], "J" => [77, "\xe8f"], "K" => [18, "\xe8f"], "L" => [77, "\xe8g"], "M" => [18, "\xe8g"], "N" => [77, "\xe8h"], "O" => [18, "\xe8h"], "P" => [77, "\xe8l"], "Q" => [18, "\xe8l"], "R" => [77, "\xe8m"], "S" => [18, "\xe8m"], "T" => [77, "\xe8n"], "U" => [18, "\xe8n"], "V" => [77, "\xe8p"], "W" => [18, "\xe8p"], "X" => [77, "\xe8r"], "Y" => [18, "\xe8r"], "Z" => [77, "\xe8u"], "[" => [18, "\xe8u"], "\\" => [0, "\xe8:"], "]" => [0, "\xe8B"], "^" => [0, "\xe8C"], "_" => [0, "\xe8D"], "`" => [0, "\xe8E"], "a" => [0, "\xe8F"], "b" => [0, "\xe8G"], "c" => [0, "\xe8H"], "d" => [0, "\xe8I"], "e" => [0, "\xe8J"], "f" => [0, "\xe8K"], "g" => [0, "\xe8L"], "h" => [0, "\xe8M"], "i" => [0, "\xe8N"], "j" => [0, "\xe8O"], "k" => [0, "\xe8P"], "l" => [0, "\xe8Q"], "m" => [0, "\xe8R"], "n" => [0, "\xe8S"], "o" => [0, "\xe8T"], "p" => [0, "\xe8U"], "q" => [0, "\xe8V"], "r" => [0, "\xe8W"], "s" => [0, "\xe8Y"], "t" => [0, "\xe8j"], "u" => [0, "\xe8k"], "v" => [0, "\xe8q"], "w" => [0, "\xe8v"], "x" => [0, "\xe8w"], "y" => [0, "\xe8x"], "z" => [0, "\xe8y"], "{" => [0, "\xe8z"], "|" => [82, "\xe8"], "}" => [87, "\xe8"], "~" => [130, "\xe8"], "" => [9, "\xe8"], "\x80" => [94, "\xe90"], "\x81" => [76, "\xe90"], "\x82" => [104, "\xe90"], "\x83" => [16, "\xe90"], "\x84" => [94, "\xe91"], "\x85" => [76, "\xe91"], "\x86" => [104, "\xe91"], "\x87" => [16, "\xe91"], "\x88" => [94, "\xe92"], "\x89" => [76, "\xe92"], "\x8a" => [104, "\xe92"], "\x8b" => [16, "\xe92"], "\x8c" => [94, "\xe9a"], "\x8d" => [76, "\xe9a"], "\x8e" => [104, "\xe9a"], "\x8f" => [16, "\xe9a"], "\x90" => [94, "\xe9c"], "\x91" => [76, "\xe9c"], "\x92" => [104, "\xe9c"], "\x93" => [16, "\xe9c"], "\x94" => [94, "\xe9e"], "\x95" => [76, "\xe9e"], "\x96" => [104, "\xe9e"], "\x97" => [16, "\xe9e"], "\x98" => [94, "\xe9i"], "\x99" => [76, "\xe9i"], "\x9a" => [104, "\xe9i"], "\x9b" => [16, "\xe9i"], "\x9c" => [94, "\xe9o"], "\x9d" => [76, "\xe9o"], "\x9e" => [104, "\xe9o"], "\x9f" => [16, "\xe9o"], "\xa0" => [94, "\xe9s"], "\xa1" => [76, "\xe9s"], "\xa2" => [104, "\xe9s"], "\xa3" => [16, "\xe9s"], "\xa4" => [94, "\xe9t"], "\xa5" => [76, "\xe9t"], "\xa6" => [104, "\xe9t"], "\xa7" => [16, "\xe9t"], "\xa8" => [77, "\xe9 "], "\xa9" => [18, "\xe9 "], "\xaa" => [77, "\xe9%"], "\xab" => [18, "\xe9%"], "\xac" => [77, "\xe9-"], "\xad" => [18, "\xe9-"], "\xae" => [77, "\xe9."], "\xaf" => [18, "\xe9."], "\xb0" => [77, "\xe9/"], "\xb1" => [18, "\xe9/"], "\xb2" => [77, "\xe93"], "\xb3" => [18, "\xe93"], "\xb4" => [77, "\xe94"], "\xb5" => [18, "\xe94"], "\xb6" => [77, "\xe95"], "\xb7" => [18, "\xe95"], "\xb8" => [77, "\xe96"], "\xb9" => [18, "\xe96"], "\xba" => [77, "\xe97"], "\xbb" => [18, "\xe97"], "\xbc" => [77, "\xe98"], "\xbd" => [18, "\xe98"], "\xbe" => [77, "\xe99"], "\xbf" => [18, "\xe99"], "\xc0" => [77, "\xe9="], "\xc1" => [18, "\xe9="], "\xc2" => [77, "\xe9A"], "\xc3" => [18, "\xe9A"], "\xc4" => [77, "\xe9_"], "\xc5" => [18, "\xe9_"], "\xc6" => [77, "\xe9b"], "\xc7" => [18, "\xe9b"], "\xc8" => [77, "\xe9d"], "\xc9" => [18, "\xe9d"], "\xca" => [77, "\xe9f"], "\xcb" => [18, "\xe9f"], "\xcc" => [77, "\xe9g"], "\xcd" => [18, "\xe9g"], "\xce" => [77, "\xe9h"], "\xcf" => [18, "\xe9h"], "\xd0" => [77, "\xe9l"], "\xd1" => [18, "\xe9l"], "\xd2" => [77, "\xe9m"], "\xd3" => [18, "\xe9m"], "\xd4" => [77, "\xe9n"], "\xd5" => [18, "\xe9n"], "\xd6" => [77, "\xe9p"], "\xd7" => [18, "\xe9p"], "\xd8" => [77, "\xe9r"], "\xd9" => [18, "\xe9r"], "\xda" => [77, "\xe9u"], "\xdb" => [18, "\xe9u"], "\xdc" => [0, "\xe9:"], "\xdd" => [0, "\xe9B"], "\xde" => [0, "\xe9C"], "\xdf" => [0, "\xe9D"], "\xe0" => [0, "\xe9E"], "\xe1" => [0, "\xe9F"], "\xe2" => [0, "\xe9G"], "\xe3" => [0, "\xe9H"], "\xe4" => [0, "\xe9I"], "\xe5" => [0, "\xe9J"], "\xe6" => [0, "\xe9K"], "\xe7" => [0, "\xe9L"], "\xe8" => [0, "\xe9M"], "\xe9" => [0, "\xe9N"], "\xea" => [0, "\xe9O"], "\xeb" => [0, "\xe9P"], "\xec" => [0, "\xe9Q"], "\xed" => [0, "\xe9R"], "\xee" => [0, "\xe9S"], "\xef" => [0, "\xe9T"], "\xf0" => [0, "\xe9U"], "\xf1" => [0, "\xe9V"], "\xf2" => [0, "\xe9W"], "\xf3" => [0, "\xe9Y"], "\xf4" => [0, "\xe9j"], "\xf5" => [0, "\xe9k"], "\xf6" => [0, "\xe9q"], "\xf7" => [0, "\xe9v"], "\xf8" => [0, "\xe9w"], "\xf9" => [0, "\xe9x"], "\xfa" => [0, "\xe9y"], "\xfb" => [0, "\xe9z"], "\xfc" => [82, "\xe9"], "\xfd" => [87, "\xe9"], "\xfe" => [130, "\xe9"], "\xff" => [9, "\xe9"]], ["\x00" => [94, "\xea0"], "\x01" => [76, "\xea0"], "\x02" => [104, "\xea0"], "\x03" => [16, "\xea0"], "\x04" => [94, "\xea1"], "\x05" => [76, "\xea1"], "\x06" => [104, "\xea1"], "\x07" => [16, "\xea1"], "\x08" => [94, "\xea2"], "\t" => [76, "\xea2"], "\n" => [104, "\xea2"], "\v" => [16, "\xea2"], "\f" => [94, "\xeaa"], "\r" => [76, "\xeaa"], "\x0e" => [104, "\xeaa"], "\x0f" => [16, "\xeaa"], "\x10" => [94, "\xeac"], "\x11" => [76, "\xeac"], "\x12" => [104, "\xeac"], "\x13" => [16, "\xeac"], "\x14" => [94, "\xeae"], "\x15" => [76, "\xeae"], "\x16" => [104, "\xeae"], "\x17" => [16, "\xeae"], "\x18" => [94, "\xeai"], "\x19" => [76, "\xeai"], "\x1a" => [104, "\xeai"], "\x1b" => [16, "\xeai"], "\x1c" => [94, "\xeao"], "\x1d" => [76, "\xeao"], "\x1e" => [104, "\xeao"], "\x1f" => [16, "\xeao"], " " => [94, "\xeas"], "!" => [76, "\xeas"], "\"" => [104, "\xeas"], "#" => [16, "\xeas"], "\$" => [94, "\xeat"], "%" => [76, "\xeat"], "&" => [104, "\xeat"], "'" => [16, "\xeat"], "(" => [77, "\xea "], ")" => [18, "\xea "], "*" => [77, "\xea%"], "+" => [18, "\xea%"], "," => [77, "\xea-"], "-" => [18, "\xea-"], "." => [77, "\xea."], "/" => [18, "\xea."], [77, "\xea/"], [18, "\xea/"], [77, "\xea3"], [18, "\xea3"], [77, "\xea4"], [18, "\xea4"], [77, "\xea5"], [18, "\xea5"], [77, "\xea6"], [18, "\xea6"], ":" => [77, "\xea7"], ";" => [18, "\xea7"], "<" => [77, "\xea8"], "=" => [18, "\xea8"], ">" => [77, "\xea9"], "?" => [18, "\xea9"], "@" => [77, "\xea="], "A" => [18, "\xea="], "B" => [77, "\xeaA"], "C" => [18, "\xeaA"], "D" => [77, "\xea_"], "E" => [18, "\xea_"], "F" => [77, "\xeab"], "G" => [18, "\xeab"], "H" => [77, "\xead"], "I" => [18, "\xead"], "J" => [77, "\xeaf"], "K" => [18, "\xeaf"], "L" => [77, "\xeag"], "M" => [18, "\xeag"], "N" => [77, "\xeah"], "O" => [18, "\xeah"], "P" => [77, "\xeal"], "Q" => [18, "\xeal"], "R" => [77, "\xeam"], "S" => [18, "\xeam"], "T" => [77, "\xean"], "U" => [18, "\xean"], "V" => [77, "\xeap"], "W" => [18, "\xeap"], "X" => [77, "\xear"], "Y" => [18, "\xear"], "Z" => [77, "\xeau"], "[" => [18, "\xeau"], "\\" => [0, "\xea:"], "]" => [0, "\xeaB"], "^" => [0, "\xeaC"], "_" => [0, "\xeaD"], "`" => [0, "\xeaE"], "a" => [0, "\xeaF"], "b" => [0, "\xeaG"], "c" => [0, "\xeaH"], "d" => [0, "\xeaI"], "e" => [0, "\xeaJ"], "f" => [0, "\xeaK"], "g" => [0, "\xeaL"], "h" => [0, "\xeaM"], "i" => [0, "\xeaN"], "j" => [0, "\xeaO"], "k" => [0, "\xeaP"], "l" => [0, "\xeaQ"], "m" => [0, "\xeaR"], "n" => [0, "\xeaS"], "o" => [0, "\xeaT"], "p" => [0, "\xeaU"], "q" => [0, "\xeaV"], "r" => [0, "\xeaW"], "s" => [0, "\xeaY"], "t" => [0, "\xeaj"], "u" => [0, "\xeak"], "v" => [0, "\xeaq"], "w" => [0, "\xeav"], "x" => [0, "\xeaw"], "y" => [0, "\xeax"], "z" => [0, "\xeay"], "{" => [0, "\xeaz"], "|" => [82, "\xea"], "}" => [87, "\xea"], "~" => [130, "\xea"], "" => [9, "\xea"], "\x80" => [94, "\xeb0"], "\x81" => [76, "\xeb0"], "\x82" => [104, "\xeb0"], "\x83" => [16, "\xeb0"], "\x84" => [94, "\xeb1"], "\x85" => [76, "\xeb1"], "\x86" => [104, "\xeb1"], "\x87" => [16, "\xeb1"], "\x88" => [94, "\xeb2"], "\x89" => [76, "\xeb2"], "\x8a" => [104, "\xeb2"], "\x8b" => [16, "\xeb2"], "\x8c" => [94, "\xeba"], "\x8d" => [76, "\xeba"], "\x8e" => [104, "\xeba"], "\x8f" => [16, "\xeba"], "\x90" => [94, "\xebc"], "\x91" => [76, "\xebc"], "\x92" => [104, "\xebc"], "\x93" => [16, "\xebc"], "\x94" => [94, "\xebe"], "\x95" => [76, "\xebe"], "\x96" => [104, "\xebe"], "\x97" => [16, "\xebe"], "\x98" => [94, "\xebi"], "\x99" => [76, "\xebi"], "\x9a" => [104, "\xebi"], "\x9b" => [16, "\xebi"], "\x9c" => [94, "\xebo"], "\x9d" => [76, "\xebo"], "\x9e" => [104, "\xebo"], "\x9f" => [16, "\xebo"], "\xa0" => [94, "\xebs"], "\xa1" => [76, "\xebs"], "\xa2" => [104, "\xebs"], "\xa3" => [16, "\xebs"], "\xa4" => [94, "\xebt"], "\xa5" => [76, "\xebt"], "\xa6" => [104, "\xebt"], "\xa7" => [16, "\xebt"], "\xa8" => [77, "\xeb "], "\xa9" => [18, "\xeb "], "\xaa" => [77, "\xeb%"], "\xab" => [18, "\xeb%"], "\xac" => [77, "\xeb-"], "\xad" => [18, "\xeb-"], "\xae" => [77, "\xeb."], "\xaf" => [18, "\xeb."], "\xb0" => [77, "\xeb/"], "\xb1" => [18, "\xeb/"], "\xb2" => [77, "\xeb3"], "\xb3" => [18, "\xeb3"], "\xb4" => [77, "\xeb4"], "\xb5" => [18, "\xeb4"], "\xb6" => [77, "\xeb5"], "\xb7" => [18, "\xeb5"], "\xb8" => [77, "\xeb6"], "\xb9" => [18, "\xeb6"], "\xba" => [77, "\xeb7"], "\xbb" => [18, "\xeb7"], "\xbc" => [77, "\xeb8"], "\xbd" => [18, "\xeb8"], "\xbe" => [77, "\xeb9"], "\xbf" => [18, "\xeb9"], "\xc0" => [77, "\xeb="], "\xc1" => [18, "\xeb="], "\xc2" => [77, "\xebA"], "\xc3" => [18, "\xebA"], "\xc4" => [77, "\xeb_"], "\xc5" => [18, "\xeb_"], "\xc6" => [77, "\xebb"], "\xc7" => [18, "\xebb"], "\xc8" => [77, "\xebd"], "\xc9" => [18, "\xebd"], "\xca" => [77, "\xebf"], "\xcb" => [18, "\xebf"], "\xcc" => [77, "\xebg"], "\xcd" => [18, "\xebg"], "\xce" => [77, "\xebh"], "\xcf" => [18, "\xebh"], "\xd0" => [77, "\xebl"], "\xd1" => [18, "\xebl"], "\xd2" => [77, "\xebm"], "\xd3" => [18, "\xebm"], "\xd4" => [77, "\xebn"], "\xd5" => [18, "\xebn"], "\xd6" => [77, "\xebp"], "\xd7" => [18, "\xebp"], "\xd8" => [77, "\xebr"], "\xd9" => [18, "\xebr"], "\xda" => [77, "\xebu"], "\xdb" => [18, "\xebu"], "\xdc" => [0, "\xeb:"], "\xdd" => [0, "\xebB"], "\xde" => [0, "\xebC"], "\xdf" => [0, "\xebD"], "\xe0" => [0, "\xebE"], "\xe1" => [0, "\xebF"], "\xe2" => [0, "\xebG"], "\xe3" => [0, "\xebH"], "\xe4" => [0, "\xebI"], "\xe5" => [0, "\xebJ"], "\xe6" => [0, "\xebK"], "\xe7" => [0, "\xebL"], "\xe8" => [0, "\xebM"], "\xe9" => [0, "\xebN"], "\xea" => [0, "\xebO"], "\xeb" => [0, "\xebP"], "\xec" => [0, "\xebQ"], "\xed" => [0, "\xebR"], "\xee" => [0, "\xebS"], "\xef" => [0, "\xebT"], "\xf0" => [0, "\xebU"], "\xf1" => [0, "\xebV"], "\xf2" => [0, "\xebW"], "\xf3" => [0, "\xebY"], "\xf4" => [0, "\xebj"], "\xf5" => [0, "\xebk"], "\xf6" => [0, "\xebq"], "\xf7" => [0, "\xebv"], "\xf8" => [0, "\xebw"], "\xf9" => [0, "\xebx"], "\xfa" => [0, "\xeby"], "\xfb" => [0, "\xebz"], "\xfc" => [82, "\xeb"], "\xfd" => [87, "\xeb"], "\xfe" => [130, "\xeb"], "\xff" => [9, "\xeb"]], ["\x00" => [94, "\xec0"], "\x01" => [76, "\xec0"], "\x02" => [104, "\xec0"], "\x03" => [16, "\xec0"], "\x04" => [94, "\xec1"], "\x05" => [76, "\xec1"], "\x06" => [104, "\xec1"], "\x07" => [16, "\xec1"], "\x08" => [94, "\xec2"], "\t" => [76, "\xec2"], "\n" => [104, "\xec2"], "\v" => [16, "\xec2"], "\f" => [94, "\xeca"], "\r" => [76, "\xeca"], "\x0e" => [104, "\xeca"], "\x0f" => [16, "\xeca"], "\x10" => [94, "\xecc"], "\x11" => [76, "\xecc"], "\x12" => [104, "\xecc"], "\x13" => [16, "\xecc"], "\x14" => [94, "\xece"], "\x15" => [76, "\xece"], "\x16" => [104, "\xece"], "\x17" => [16, "\xece"], "\x18" => [94, "\xeci"], "\x19" => [76, "\xeci"], "\x1a" => [104, "\xeci"], "\x1b" => [16, "\xeci"], "\x1c" => [94, "\xeco"], "\x1d" => [76, "\xeco"], "\x1e" => [104, "\xeco"], "\x1f" => [16, "\xeco"], " " => [94, "\xecs"], "!" => [76, "\xecs"], "\"" => [104, "\xecs"], "#" => [16, "\xecs"], "\$" => [94, "\xect"], "%" => [76, "\xect"], "&" => [104, "\xect"], "'" => [16, "\xect"], "(" => [77, "\xec "], ")" => [18, "\xec "], "*" => [77, "\xec%"], "+" => [18, "\xec%"], "," => [77, "\xec-"], "-" => [18, "\xec-"], "." => [77, "\xec."], "/" => [18, "\xec."], [77, "\xec/"], [18, "\xec/"], [77, "\xec3"], [18, "\xec3"], [77, "\xec4"], [18, "\xec4"], [77, "\xec5"], [18, "\xec5"], [77, "\xec6"], [18, "\xec6"], ":" => [77, "\xec7"], ";" => [18, "\xec7"], "<" => [77, "\xec8"], "=" => [18, "\xec8"], ">" => [77, "\xec9"], "?" => [18, "\xec9"], "@" => [77, "\xec="], "A" => [18, "\xec="], "B" => [77, "\xecA"], "C" => [18, "\xecA"], "D" => [77, "\xec_"], "E" => [18, "\xec_"], "F" => [77, "\xecb"], "G" => [18, "\xecb"], "H" => [77, "\xecd"], "I" => [18, "\xecd"], "J" => [77, "\xecf"], "K" => [18, "\xecf"], "L" => [77, "\xecg"], "M" => [18, "\xecg"], "N" => [77, "\xech"], "O" => [18, "\xech"], "P" => [77, "\xecl"], "Q" => [18, "\xecl"], "R" => [77, "\xecm"], "S" => [18, "\xecm"], "T" => [77, "\xecn"], "U" => [18, "\xecn"], "V" => [77, "\xecp"], "W" => [18, "\xecp"], "X" => [77, "\xecr"], "Y" => [18, "\xecr"], "Z" => [77, "\xecu"], "[" => [18, "\xecu"], "\\" => [0, "\xec:"], "]" => [0, "\xecB"], "^" => [0, "\xecC"], "_" => [0, "\xecD"], "`" => [0, "\xecE"], "a" => [0, "\xecF"], "b" => [0, "\xecG"], "c" => [0, "\xecH"], "d" => [0, "\xecI"], "e" => [0, "\xecJ"], "f" => [0, "\xecK"], "g" => [0, "\xecL"], "h" => [0, "\xecM"], "i" => [0, "\xecN"], "j" => [0, "\xecO"], "k" => [0, "\xecP"], "l" => [0, "\xecQ"], "m" => [0, "\xecR"], "n" => [0, "\xecS"], "o" => [0, "\xecT"], "p" => [0, "\xecU"], "q" => [0, "\xecV"], "r" => [0, "\xecW"], "s" => [0, "\xecY"], "t" => [0, "\xecj"], "u" => [0, "\xeck"], "v" => [0, "\xecq"], "w" => [0, "\xecv"], "x" => [0, "\xecw"], "y" => [0, "\xecx"], "z" => [0, "\xecy"], "{" => [0, "\xecz"], "|" => [82, "\xec"], "}" => [87, "\xec"], "~" => [130, "\xec"], "" => [9, "\xec"], "\x80" => [94, "\xed0"], "\x81" => [76, "\xed0"], "\x82" => [104, "\xed0"], "\x83" => [16, "\xed0"], "\x84" => [94, "\xed1"], "\x85" => [76, "\xed1"], "\x86" => [104, "\xed1"], "\x87" => [16, "\xed1"], "\x88" => [94, "\xed2"], "\x89" => [76, "\xed2"], "\x8a" => [104, "\xed2"], "\x8b" => [16, "\xed2"], "\x8c" => [94, "\xeda"], "\x8d" => [76, "\xeda"], "\x8e" => [104, "\xeda"], "\x8f" => [16, "\xeda"], "\x90" => [94, "\xedc"], "\x91" => [76, "\xedc"], "\x92" => [104, "\xedc"], "\x93" => [16, "\xedc"], "\x94" => [94, "\xede"], "\x95" => [76, "\xede"], "\x96" => [104, "\xede"], "\x97" => [16, "\xede"], "\x98" => [94, "\xedi"], "\x99" => [76, "\xedi"], "\x9a" => [104, "\xedi"], "\x9b" => [16, "\xedi"], "\x9c" => [94, "\xedo"], "\x9d" => [76, "\xedo"], "\x9e" => [104, "\xedo"], "\x9f" => [16, "\xedo"], "\xa0" => [94, "\xeds"], "\xa1" => [76, "\xeds"], "\xa2" => [104, "\xeds"], "\xa3" => [16, "\xeds"], "\xa4" => [94, "\xedt"], "\xa5" => [76, "\xedt"], "\xa6" => [104, "\xedt"], "\xa7" => [16, "\xedt"], "\xa8" => [77, "\xed "], "\xa9" => [18, "\xed "], "\xaa" => [77, "\xed%"], "\xab" => [18, "\xed%"], "\xac" => [77, "\xed-"], "\xad" => [18, "\xed-"], "\xae" => [77, "\xed."], "\xaf" => [18, "\xed."], "\xb0" => [77, "\xed/"], "\xb1" => [18, "\xed/"], "\xb2" => [77, "\xed3"], "\xb3" => [18, "\xed3"], "\xb4" => [77, "\xed4"], "\xb5" => [18, "\xed4"], "\xb6" => [77, "\xed5"], "\xb7" => [18, "\xed5"], "\xb8" => [77, "\xed6"], "\xb9" => [18, "\xed6"], "\xba" => [77, "\xed7"], "\xbb" => [18, "\xed7"], "\xbc" => [77, "\xed8"], "\xbd" => [18, "\xed8"], "\xbe" => [77, "\xed9"], "\xbf" => [18, "\xed9"], "\xc0" => [77, "\xed="], "\xc1" => [18, "\xed="], "\xc2" => [77, "\xedA"], "\xc3" => [18, "\xedA"], "\xc4" => [77, "\xed_"], "\xc5" => [18, "\xed_"], "\xc6" => [77, "\xedb"], "\xc7" => [18, "\xedb"], "\xc8" => [77, "\xedd"], "\xc9" => [18, "\xedd"], "\xca" => [77, "\xedf"], "\xcb" => [18, "\xedf"], "\xcc" => [77, "\xedg"], "\xcd" => [18, "\xedg"], "\xce" => [77, "\xedh"], "\xcf" => [18, "\xedh"], "\xd0" => [77, "\xedl"], "\xd1" => [18, "\xedl"], "\xd2" => [77, "\xedm"], "\xd3" => [18, "\xedm"], "\xd4" => [77, "\xedn"], "\xd5" => [18, "\xedn"], "\xd6" => [77, "\xedp"], "\xd7" => [18, "\xedp"], "\xd8" => [77, "\xedr"], "\xd9" => [18, "\xedr"], "\xda" => [77, "\xedu"], "\xdb" => [18, "\xedu"], "\xdc" => [0, "\xed:"], "\xdd" => [0, "\xedB"], "\xde" => [0, "\xedC"], "\xdf" => [0, "\xedD"], "\xe0" => [0, "\xedE"], "\xe1" => [0, "\xedF"], "\xe2" => [0, "\xedG"], "\xe3" => [0, "\xedH"], "\xe4" => [0, "\xedI"], "\xe5" => [0, "\xedJ"], "\xe6" => [0, "\xedK"], "\xe7" => [0, "\xedL"], "\xe8" => [0, "\xedM"], "\xe9" => [0, "\xedN"], "\xea" => [0, "\xedO"], "\xeb" => [0, "\xedP"], "\xec" => [0, "\xedQ"], "\xed" => [0, "\xedR"], "\xee" => [0, "\xedS"], "\xef" => [0, "\xedT"], "\xf0" => [0, "\xedU"], "\xf1" => [0, "\xedV"], "\xf2" => [0, "\xedW"], "\xf3" => [0, "\xedY"], "\xf4" => [0, "\xedj"], "\xf5" => [0, "\xedk"], "\xf6" => [0, "\xedq"], "\xf7" => [0, "\xedv"], "\xf8" => [0, "\xedw"], "\xf9" => [0, "\xedx"], "\xfa" => [0, "\xedy"], "\xfb" => [0, "\xedz"], "\xfc" => [82, "\xed"], "\xfd" => [87, "\xed"], "\xfe" => [130, "\xed"], "\xff" => [9, "\xed"]], ["\x00" => [94, "\xee0"], "\x01" => [76, "\xee0"], "\x02" => [104, "\xee0"], "\x03" => [16, "\xee0"], "\x04" => [94, "\xee1"], "\x05" => [76, "\xee1"], "\x06" => [104, "\xee1"], "\x07" => [16, "\xee1"], "\x08" => [94, "\xee2"], "\t" => [76, "\xee2"], "\n" => [104, "\xee2"], "\v" => [16, "\xee2"], "\f" => [94, "\xeea"], "\r" => [76, "\xeea"], "\x0e" => [104, "\xeea"], "\x0f" => [16, "\xeea"], "\x10" => [94, "\xeec"], "\x11" => [76, "\xeec"], "\x12" => [104, "\xeec"], "\x13" => [16, "\xeec"], "\x14" => [94, "\xeee"], "\x15" => [76, "\xeee"], "\x16" => [104, "\xeee"], "\x17" => [16, "\xeee"], "\x18" => [94, "\xeei"], "\x19" => [76, "\xeei"], "\x1a" => [104, "\xeei"], "\x1b" => [16, "\xeei"], "\x1c" => [94, "\xeeo"], "\x1d" => [76, "\xeeo"], "\x1e" => [104, "\xeeo"], "\x1f" => [16, "\xeeo"], " " => [94, "\xees"], "!" => [76, "\xees"], "\"" => [104, "\xees"], "#" => [16, "\xees"], "\$" => [94, "\xeet"], "%" => [76, "\xeet"], "&" => [104, "\xeet"], "'" => [16, "\xeet"], "(" => [77, "\xee "], ")" => [18, "\xee "], "*" => [77, "\xee%"], "+" => [18, "\xee%"], "," => [77, "\xee-"], "-" => [18, "\xee-"], "." => [77, "\xee."], "/" => [18, "\xee."], [77, "\xee/"], [18, "\xee/"], [77, "\xee3"], [18, "\xee3"], [77, "\xee4"], [18, "\xee4"], [77, "\xee5"], [18, "\xee5"], [77, "\xee6"], [18, "\xee6"], ":" => [77, "\xee7"], ";" => [18, "\xee7"], "<" => [77, "\xee8"], "=" => [18, "\xee8"], ">" => [77, "\xee9"], "?" => [18, "\xee9"], "@" => [77, "\xee="], "A" => [18, "\xee="], "B" => [77, "\xeeA"], "C" => [18, "\xeeA"], "D" => [77, "\xee_"], "E" => [18, "\xee_"], "F" => [77, "\xeeb"], "G" => [18, "\xeeb"], "H" => [77, "\xeed"], "I" => [18, "\xeed"], "J" => [77, "\xeef"], "K" => [18, "\xeef"], "L" => [77, "\xeeg"], "M" => [18, "\xeeg"], "N" => [77, "\xeeh"], "O" => [18, "\xeeh"], "P" => [77, "\xeel"], "Q" => [18, "\xeel"], "R" => [77, "\xeem"], "S" => [18, "\xeem"], "T" => [77, "\xeen"], "U" => [18, "\xeen"], "V" => [77, "\xeep"], "W" => [18, "\xeep"], "X" => [77, "\xeer"], "Y" => [18, "\xeer"], "Z" => [77, "\xeeu"], "[" => [18, "\xeeu"], "\\" => [0, "\xee:"], "]" => [0, "\xeeB"], "^" => [0, "\xeeC"], "_" => [0, "\xeeD"], "`" => [0, "\xeeE"], "a" => [0, "\xeeF"], "b" => [0, "\xeeG"], "c" => [0, "\xeeH"], "d" => [0, "\xeeI"], "e" => [0, "\xeeJ"], "f" => [0, "\xeeK"], "g" => [0, "\xeeL"], "h" => [0, "\xeeM"], "i" => [0, "\xeeN"], "j" => [0, "\xeeO"], "k" => [0, "\xeeP"], "l" => [0, "\xeeQ"], "m" => [0, "\xeeR"], "n" => [0, "\xeeS"], "o" => [0, "\xeeT"], "p" => [0, "\xeeU"], "q" => [0, "\xeeV"], "r" => [0, "\xeeW"], "s" => [0, "\xeeY"], "t" => [0, "\xeej"], "u" => [0, "\xeek"], "v" => [0, "\xeeq"], "w" => [0, "\xeev"], "x" => [0, "\xeew"], "y" => [0, "\xeex"], "z" => [0, "\xeey"], "{" => [0, "\xeez"], "|" => [82, "\xee"], "}" => [87, "\xee"], "~" => [130, "\xee"], "" => [9, "\xee"], "\x80" => [94, "\xf00"], "\x81" => [76, "\xf00"], "\x82" => [104, "\xf00"], "\x83" => [16, "\xf00"], "\x84" => [94, "\xf01"], "\x85" => [76, "\xf01"], "\x86" => [104, "\xf01"], "\x87" => [16, "\xf01"], "\x88" => [94, "\xf02"], "\x89" => [76, "\xf02"], "\x8a" => [104, "\xf02"], "\x8b" => [16, "\xf02"], "\x8c" => [94, "\xf0a"], "\x8d" => [76, "\xf0a"], "\x8e" => [104, "\xf0a"], "\x8f" => [16, "\xf0a"], "\x90" => [94, "\xf0c"], "\x91" => [76, "\xf0c"], "\x92" => [104, "\xf0c"], "\x93" => [16, "\xf0c"], "\x94" => [94, "\xf0e"], "\x95" => [76, "\xf0e"], "\x96" => [104, "\xf0e"], "\x97" => [16, "\xf0e"], "\x98" => [94, "\xf0i"], "\x99" => [76, "\xf0i"], "\x9a" => [104, "\xf0i"], "\x9b" => [16, "\xf0i"], "\x9c" => [94, "\xf0o"], "\x9d" => [76, "\xf0o"], "\x9e" => [104, "\xf0o"], "\x9f" => [16, "\xf0o"], "\xa0" => [94, "\xf0s"], "\xa1" => [76, "\xf0s"], "\xa2" => [104, "\xf0s"], "\xa3" => [16, "\xf0s"], "\xa4" => [94, "\xf0t"], "\xa5" => [76, "\xf0t"], "\xa6" => [104, "\xf0t"], "\xa7" => [16, "\xf0t"], "\xa8" => [77, "\xf0 "], "\xa9" => [18, "\xf0 "], "\xaa" => [77, "\xf0%"], "\xab" => [18, "\xf0%"], "\xac" => [77, "\xf0-"], "\xad" => [18, "\xf0-"], "\xae" => [77, "\xf0."], "\xaf" => [18, "\xf0."], "\xb0" => [77, "\xf0/"], "\xb1" => [18, "\xf0/"], "\xb2" => [77, "\xf03"], "\xb3" => [18, "\xf03"], "\xb4" => [77, "\xf04"], "\xb5" => [18, "\xf04"], "\xb6" => [77, "\xf05"], "\xb7" => [18, "\xf05"], "\xb8" => [77, "\xf06"], "\xb9" => [18, "\xf06"], "\xba" => [77, "\xf07"], "\xbb" => [18, "\xf07"], "\xbc" => [77, "\xf08"], "\xbd" => [18, "\xf08"], "\xbe" => [77, "\xf09"], "\xbf" => [18, "\xf09"], "\xc0" => [77, "\xf0="], "\xc1" => [18, "\xf0="], "\xc2" => [77, "\xf0A"], "\xc3" => [18, "\xf0A"], "\xc4" => [77, "\xf0_"], "\xc5" => [18, "\xf0_"], "\xc6" => [77, "\xf0b"], "\xc7" => [18, "\xf0b"], "\xc8" => [77, "\xf0d"], "\xc9" => [18, "\xf0d"], "\xca" => [77, "\xf0f"], "\xcb" => [18, "\xf0f"], "\xcc" => [77, "\xf0g"], "\xcd" => [18, "\xf0g"], "\xce" => [77, "\xf0h"], "\xcf" => [18, "\xf0h"], "\xd0" => [77, "\xf0l"], "\xd1" => [18, "\xf0l"], "\xd2" => [77, "\xf0m"], "\xd3" => [18, "\xf0m"], "\xd4" => [77, "\xf0n"], "\xd5" => [18, "\xf0n"], "\xd6" => [77, "\xf0p"], "\xd7" => [18, "\xf0p"], "\xd8" => [77, "\xf0r"], "\xd9" => [18, "\xf0r"], "\xda" => [77, "\xf0u"], "\xdb" => [18, "\xf0u"], "\xdc" => [0, "\xf0:"], "\xdd" => [0, "\xf0B"], "\xde" => [0, "\xf0C"], "\xdf" => [0, "\xf0D"], "\xe0" => [0, "\xf0E"], "\xe1" => [0, "\xf0F"], "\xe2" => [0, "\xf0G"], "\xe3" => [0, "\xf0H"], "\xe4" => [0, "\xf0I"], "\xe5" => [0, "\xf0J"], "\xe6" => [0, "\xf0K"], "\xe7" => [0, "\xf0L"], "\xe8" => [0, "\xf0M"], "\xe9" => [0, "\xf0N"], "\xea" => [0, "\xf0O"], "\xeb" => [0, "\xf0P"], "\xec" => [0, "\xf0Q"], "\xed" => [0, "\xf0R"], "\xee" => [0, "\xf0S"], "\xef" => [0, "\xf0T"], "\xf0" => [0, "\xf0U"], "\xf1" => [0, "\xf0V"], "\xf2" => [0, "\xf0W"], "\xf3" => [0, "\xf0Y"], "\xf4" => [0, "\xf0j"], "\xf5" => [0, "\xf0k"], "\xf6" => [0, "\xf0q"], "\xf7" => [0, "\xf0v"], "\xf8" => [0, "\xf0w"], "\xf9" => [0, "\xf0x"], "\xfa" => [0, "\xf0y"], "\xfb" => [0, "\xf0z"], "\xfc" => [82, "\xf0"], "\xfd" => [87, "\xf0"], "\xfe" => [130, "\xf0"], "\xff" => [9, "\xf0"]], ["\x00" => [94, "\xf10"], "\x01" => [76, "\xf10"], "\x02" => [104, "\xf10"], "\x03" => [16, "\xf10"], "\x04" => [94, "\xf11"], "\x05" => [76, "\xf11"], "\x06" => [104, "\xf11"], "\x07" => [16, "\xf11"], "\x08" => [94, "\xf12"], "\t" => [76, "\xf12"], "\n" => [104, "\xf12"], "\v" => [16, "\xf12"], "\f" => [94, "\xf1a"], "\r" => [76, "\xf1a"], "\x0e" => [104, "\xf1a"], "\x0f" => [16, "\xf1a"], "\x10" => [94, "\xf1c"], "\x11" => [76, "\xf1c"], "\x12" => [104, "\xf1c"], "\x13" => [16, "\xf1c"], "\x14" => [94, "\xf1e"], "\x15" => [76, "\xf1e"], "\x16" => [104, "\xf1e"], "\x17" => [16, "\xf1e"], "\x18" => [94, "\xf1i"], "\x19" => [76, "\xf1i"], "\x1a" => [104, "\xf1i"], "\x1b" => [16, "\xf1i"], "\x1c" => [94, "\xf1o"], "\x1d" => [76, "\xf1o"], "\x1e" => [104, "\xf1o"], "\x1f" => [16, "\xf1o"], " " => [94, "\xf1s"], "!" => [76, "\xf1s"], "\"" => [104, "\xf1s"], "#" => [16, "\xf1s"], "\$" => [94, "\xf1t"], "%" => [76, "\xf1t"], "&" => [104, "\xf1t"], "'" => [16, "\xf1t"], "(" => [77, "\xf1 "], ")" => [18, "\xf1 "], "*" => [77, "\xf1%"], "+" => [18, "\xf1%"], "," => [77, "\xf1-"], "-" => [18, "\xf1-"], "." => [77, "\xf1."], "/" => [18, "\xf1."], [77, "\xf1/"], [18, "\xf1/"], [77, "\xf13"], [18, "\xf13"], [77, "\xf14"], [18, "\xf14"], [77, "\xf15"], [18, "\xf15"], [77, "\xf16"], [18, "\xf16"], ":" => [77, "\xf17"], ";" => [18, "\xf17"], "<" => [77, "\xf18"], "=" => [18, "\xf18"], ">" => [77, "\xf19"], "?" => [18, "\xf19"], "@" => [77, "\xf1="], "A" => [18, "\xf1="], "B" => [77, "\xf1A"], "C" => [18, "\xf1A"], "D" => [77, "\xf1_"], "E" => [18, "\xf1_"], "F" => [77, "\xf1b"], "G" => [18, "\xf1b"], "H" => [77, "\xf1d"], "I" => [18, "\xf1d"], "J" => [77, "\xf1f"], "K" => [18, "\xf1f"], "L" => [77, "\xf1g"], "M" => [18, "\xf1g"], "N" => [77, "\xf1h"], "O" => [18, "\xf1h"], "P" => [77, "\xf1l"], "Q" => [18, "\xf1l"], "R" => [77, "\xf1m"], "S" => [18, "\xf1m"], "T" => [77, "\xf1n"], "U" => [18, "\xf1n"], "V" => [77, "\xf1p"], "W" => [18, "\xf1p"], "X" => [77, "\xf1r"], "Y" => [18, "\xf1r"], "Z" => [77, "\xf1u"], "[" => [18, "\xf1u"], "\\" => [0, "\xf1:"], "]" => [0, "\xf1B"], "^" => [0, "\xf1C"], "_" => [0, "\xf1D"], "`" => [0, "\xf1E"], "a" => [0, "\xf1F"], "b" => [0, "\xf1G"], "c" => [0, "\xf1H"], "d" => [0, "\xf1I"], "e" => [0, "\xf1J"], "f" => [0, "\xf1K"], "g" => [0, "\xf1L"], "h" => [0, "\xf1M"], "i" => [0, "\xf1N"], "j" => [0, "\xf1O"], "k" => [0, "\xf1P"], "l" => [0, "\xf1Q"], "m" => [0, "\xf1R"], "n" => [0, "\xf1S"], "o" => [0, "\xf1T"], "p" => [0, "\xf1U"], "q" => [0, "\xf1V"], "r" => [0, "\xf1W"], "s" => [0, "\xf1Y"], "t" => [0, "\xf1j"], "u" => [0, "\xf1k"], "v" => [0, "\xf1q"], "w" => [0, "\xf1v"], "x" => [0, "\xf1w"], "y" => [0, "\xf1x"], "z" => [0, "\xf1y"], "{" => [0, "\xf1z"], "|" => [82, "\xf1"], "}" => [87, "\xf1"], "~" => [130, "\xf1"], "" => [9, "\xf1"], "\x80" => [94, "\xf40"], "\x81" => [76, "\xf40"], "\x82" => [104, "\xf40"], "\x83" => [16, "\xf40"], "\x84" => [94, "\xf41"], "\x85" => [76, "\xf41"], "\x86" => [104, "\xf41"], "\x87" => [16, "\xf41"], "\x88" => [94, "\xf42"], "\x89" => [76, "\xf42"], "\x8a" => [104, "\xf42"], "\x8b" => [16, "\xf42"], "\x8c" => [94, "\xf4a"], "\x8d" => [76, "\xf4a"], "\x8e" => [104, "\xf4a"], "\x8f" => [16, "\xf4a"], "\x90" => [94, "\xf4c"], "\x91" => [76, "\xf4c"], "\x92" => [104, "\xf4c"], "\x93" => [16, "\xf4c"], "\x94" => [94, "\xf4e"], "\x95" => [76, "\xf4e"], "\x96" => [104, "\xf4e"], "\x97" => [16, "\xf4e"], "\x98" => [94, "\xf4i"], "\x99" => [76, "\xf4i"], "\x9a" => [104, "\xf4i"], "\x9b" => [16, "\xf4i"], "\x9c" => [94, "\xf4o"], "\x9d" => [76, "\xf4o"], "\x9e" => [104, "\xf4o"], "\x9f" => [16, "\xf4o"], "\xa0" => [94, "\xf4s"], "\xa1" => [76, "\xf4s"], "\xa2" => [104, "\xf4s"], "\xa3" => [16, "\xf4s"], "\xa4" => [94, "\xf4t"], "\xa5" => [76, "\xf4t"], "\xa6" => [104, "\xf4t"], "\xa7" => [16, "\xf4t"], "\xa8" => [77, "\xf4 "], "\xa9" => [18, "\xf4 "], "\xaa" => [77, "\xf4%"], "\xab" => [18, "\xf4%"], "\xac" => [77, "\xf4-"], "\xad" => [18, "\xf4-"], "\xae" => [77, "\xf4."], "\xaf" => [18, "\xf4."], "\xb0" => [77, "\xf4/"], "\xb1" => [18, "\xf4/"], "\xb2" => [77, "\xf43"], "\xb3" => [18, "\xf43"], "\xb4" => [77, "\xf44"], "\xb5" => [18, "\xf44"], "\xb6" => [77, "\xf45"], "\xb7" => [18, "\xf45"], "\xb8" => [77, "\xf46"], "\xb9" => [18, "\xf46"], "\xba" => [77, "\xf47"], "\xbb" => [18, "\xf47"], "\xbc" => [77, "\xf48"], "\xbd" => [18, "\xf48"], "\xbe" => [77, "\xf49"], "\xbf" => [18, "\xf49"], "\xc0" => [77, "\xf4="], "\xc1" => [18, "\xf4="], "\xc2" => [77, "\xf4A"], "\xc3" => [18, "\xf4A"], "\xc4" => [77, "\xf4_"], "\xc5" => [18, "\xf4_"], "\xc6" => [77, "\xf4b"], "\xc7" => [18, "\xf4b"], "\xc8" => [77, "\xf4d"], "\xc9" => [18, "\xf4d"], "\xca" => [77, "\xf4f"], "\xcb" => [18, "\xf4f"], "\xcc" => [77, "\xf4g"], "\xcd" => [18, "\xf4g"], "\xce" => [77, "\xf4h"], "\xcf" => [18, "\xf4h"], "\xd0" => [77, "\xf4l"], "\xd1" => [18, "\xf4l"], "\xd2" => [77, "\xf4m"], "\xd3" => [18, "\xf4m"], "\xd4" => [77, "\xf4n"], "\xd5" => [18, "\xf4n"], "\xd6" => [77, "\xf4p"], "\xd7" => [18, "\xf4p"], "\xd8" => [77, "\xf4r"], "\xd9" => [18, "\xf4r"], "\xda" => [77, "\xf4u"], "\xdb" => [18, "\xf4u"], "\xdc" => [0, "\xf4:"], "\xdd" => [0, "\xf4B"], "\xde" => [0, "\xf4C"], "\xdf" => [0, "\xf4D"], "\xe0" => [0, "\xf4E"], "\xe1" => [0, "\xf4F"], "\xe2" => [0, "\xf4G"], "\xe3" => [0, "\xf4H"], "\xe4" => [0, "\xf4I"], "\xe5" => [0, "\xf4J"], "\xe6" => [0, "\xf4K"], "\xe7" => [0, "\xf4L"], "\xe8" => [0, "\xf4M"], "\xe9" => [0, "\xf4N"], "\xea" => [0, "\xf4O"], "\xeb" => [0, "\xf4P"], "\xec" => [0, "\xf4Q"], "\xed" => [0, "\xf4R"], "\xee" => [0, "\xf4S"], "\xef" => [0, "\xf4T"], "\xf0" => [0, "\xf4U"], "\xf1" => [0, "\xf4V"], "\xf2" => [0, "\xf4W"], "\xf3" => [0, "\xf4Y"], "\xf4" => [0, "\xf4j"], "\xf5" => [0, "\xf4k"], "\xf6" => [0, "\xf4q"], "\xf7" => [0, "\xf4v"], "\xf8" => [0, "\xf4w"], "\xf9" => [0, "\xf4x"], "\xfa" => [0, "\xf4y"], "\xfb" => [0, "\xf4z"], "\xfc" => [82, "\xf4"], "\xfd" => [87, "\xf4"], "\xfe" => [130, "\xf4"], "\xff" => [9, "\xf4"]], ["\x00" => [94, "\xf20"], "\x01" => [76, "\xf20"], "\x02" => [104, "\xf20"], "\x03" => [16, "\xf20"], "\x04" => [94, "\xf21"], "\x05" => [76, "\xf21"], "\x06" => [104, "\xf21"], "\x07" => [16, "\xf21"], "\x08" => [94, "\xf22"], "\t" => [76, "\xf22"], "\n" => [104, "\xf22"], "\v" => [16, "\xf22"], "\f" => [94, "\xf2a"], "\r" => [76, "\xf2a"], "\x0e" => [104, "\xf2a"], "\x0f" => [16, "\xf2a"], "\x10" => [94, "\xf2c"], "\x11" => [76, "\xf2c"], "\x12" => [104, "\xf2c"], "\x13" => [16, "\xf2c"], "\x14" => [94, "\xf2e"], "\x15" => [76, "\xf2e"], "\x16" => [104, "\xf2e"], "\x17" => [16, "\xf2e"], "\x18" => [94, "\xf2i"], "\x19" => [76, "\xf2i"], "\x1a" => [104, "\xf2i"], "\x1b" => [16, "\xf2i"], "\x1c" => [94, "\xf2o"], "\x1d" => [76, "\xf2o"], "\x1e" => [104, "\xf2o"], "\x1f" => [16, "\xf2o"], " " => [94, "\xf2s"], "!" => [76, "\xf2s"], "\"" => [104, "\xf2s"], "#" => [16, "\xf2s"], "\$" => [94, "\xf2t"], "%" => [76, "\xf2t"], "&" => [104, "\xf2t"], "'" => [16, "\xf2t"], "(" => [77, "\xf2 "], ")" => [18, "\xf2 "], "*" => [77, "\xf2%"], "+" => [18, "\xf2%"], "," => [77, "\xf2-"], "-" => [18, "\xf2-"], "." => [77, "\xf2."], "/" => [18, "\xf2."], [77, "\xf2/"], [18, "\xf2/"], [77, "\xf23"], [18, "\xf23"], [77, "\xf24"], [18, "\xf24"], [77, "\xf25"], [18, "\xf25"], [77, "\xf26"], [18, "\xf26"], ":" => [77, "\xf27"], ";" => [18, "\xf27"], "<" => [77, "\xf28"], "=" => [18, "\xf28"], ">" => [77, "\xf29"], "?" => [18, "\xf29"], "@" => [77, "\xf2="], "A" => [18, "\xf2="], "B" => [77, "\xf2A"], "C" => [18, "\xf2A"], "D" => [77, "\xf2_"], "E" => [18, "\xf2_"], "F" => [77, "\xf2b"], "G" => [18, "\xf2b"], "H" => [77, "\xf2d"], "I" => [18, "\xf2d"], "J" => [77, "\xf2f"], "K" => [18, "\xf2f"], "L" => [77, "\xf2g"], "M" => [18, "\xf2g"], "N" => [77, "\xf2h"], "O" => [18, "\xf2h"], "P" => [77, "\xf2l"], "Q" => [18, "\xf2l"], "R" => [77, "\xf2m"], "S" => [18, "\xf2m"], "T" => [77, "\xf2n"], "U" => [18, "\xf2n"], "V" => [77, "\xf2p"], "W" => [18, "\xf2p"], "X" => [77, "\xf2r"], "Y" => [18, "\xf2r"], "Z" => [77, "\xf2u"], "[" => [18, "\xf2u"], "\\" => [0, "\xf2:"], "]" => [0, "\xf2B"], "^" => [0, "\xf2C"], "_" => [0, "\xf2D"], "`" => [0, "\xf2E"], "a" => [0, "\xf2F"], "b" => [0, "\xf2G"], "c" => [0, "\xf2H"], "d" => [0, "\xf2I"], "e" => [0, "\xf2J"], "f" => [0, "\xf2K"], "g" => [0, "\xf2L"], "h" => [0, "\xf2M"], "i" => [0, "\xf2N"], "j" => [0, "\xf2O"], "k" => [0, "\xf2P"], "l" => [0, "\xf2Q"], "m" => [0, "\xf2R"], "n" => [0, "\xf2S"], "o" => [0, "\xf2T"], "p" => [0, "\xf2U"], "q" => [0, "\xf2V"], "r" => [0, "\xf2W"], "s" => [0, "\xf2Y"], "t" => [0, "\xf2j"], "u" => [0, "\xf2k"], "v" => [0, "\xf2q"], "w" => [0, "\xf2v"], "x" => [0, "\xf2w"], "y" => [0, "\xf2x"], "z" => [0, "\xf2y"], "{" => [0, "\xf2z"], "|" => [82, "\xf2"], "}" => [87, "\xf2"], "~" => [130, "\xf2"], "" => [9, "\xf2"], "\x80" => [94, "\xf30"], "\x81" => [76, "\xf30"], "\x82" => [104, "\xf30"], "\x83" => [16, "\xf30"], "\x84" => [94, "\xf31"], "\x85" => [76, "\xf31"], "\x86" => [104, "\xf31"], "\x87" => [16, "\xf31"], "\x88" => [94, "\xf32"], "\x89" => [76, "\xf32"], "\x8a" => [104, "\xf32"], "\x8b" => [16, "\xf32"], "\x8c" => [94, "\xf3a"], "\x8d" => [76, "\xf3a"], "\x8e" => [104, "\xf3a"], "\x8f" => [16, "\xf3a"], "\x90" => [94, "\xf3c"], "\x91" => [76, "\xf3c"], "\x92" => [104, "\xf3c"], "\x93" => [16, "\xf3c"], "\x94" => [94, "\xf3e"], "\x95" => [76, "\xf3e"], "\x96" => [104, "\xf3e"], "\x97" => [16, "\xf3e"], "\x98" => [94, "\xf3i"], "\x99" => [76, "\xf3i"], "\x9a" => [104, "\xf3i"], "\x9b" => [16, "\xf3i"], "\x9c" => [94, "\xf3o"], "\x9d" => [76, "\xf3o"], "\x9e" => [104, "\xf3o"], "\x9f" => [16, "\xf3o"], "\xa0" => [94, "\xf3s"], "\xa1" => [76, "\xf3s"], "\xa2" => [104, "\xf3s"], "\xa3" => [16, "\xf3s"], "\xa4" => [94, "\xf3t"], "\xa5" => [76, "\xf3t"], "\xa6" => [104, "\xf3t"], "\xa7" => [16, "\xf3t"], "\xa8" => [77, "\xf3 "], "\xa9" => [18, "\xf3 "], "\xaa" => [77, "\xf3%"], "\xab" => [18, "\xf3%"], "\xac" => [77, "\xf3-"], "\xad" => [18, "\xf3-"], "\xae" => [77, "\xf3."], "\xaf" => [18, "\xf3."], "\xb0" => [77, "\xf3/"], "\xb1" => [18, "\xf3/"], "\xb2" => [77, "\xf33"], "\xb3" => [18, "\xf33"], "\xb4" => [77, "\xf34"], "\xb5" => [18, "\xf34"], "\xb6" => [77, "\xf35"], "\xb7" => [18, "\xf35"], "\xb8" => [77, "\xf36"], "\xb9" => [18, "\xf36"], "\xba" => [77, "\xf37"], "\xbb" => [18, "\xf37"], "\xbc" => [77, "\xf38"], "\xbd" => [18, "\xf38"], "\xbe" => [77, "\xf39"], "\xbf" => [18, "\xf39"], "\xc0" => [77, "\xf3="], "\xc1" => [18, "\xf3="], "\xc2" => [77, "\xf3A"], "\xc3" => [18, "\xf3A"], "\xc4" => [77, "\xf3_"], "\xc5" => [18, "\xf3_"], "\xc6" => [77, "\xf3b"], "\xc7" => [18, "\xf3b"], "\xc8" => [77, "\xf3d"], "\xc9" => [18, "\xf3d"], "\xca" => [77, "\xf3f"], "\xcb" => [18, "\xf3f"], "\xcc" => [77, "\xf3g"], "\xcd" => [18, "\xf3g"], "\xce" => [77, "\xf3h"], "\xcf" => [18, "\xf3h"], "\xd0" => [77, "\xf3l"], "\xd1" => [18, "\xf3l"], "\xd2" => [77, "\xf3m"], "\xd3" => [18, "\xf3m"], "\xd4" => [77, "\xf3n"], "\xd5" => [18, "\xf3n"], "\xd6" => [77, "\xf3p"], "\xd7" => [18, "\xf3p"], "\xd8" => [77, "\xf3r"], "\xd9" => [18, "\xf3r"], "\xda" => [77, "\xf3u"], "\xdb" => [18, "\xf3u"], "\xdc" => [0, "\xf3:"], "\xdd" => [0, "\xf3B"], "\xde" => [0, "\xf3C"], "\xdf" => [0, "\xf3D"], "\xe0" => [0, "\xf3E"], "\xe1" => [0, "\xf3F"], "\xe2" => [0, "\xf3G"], "\xe3" => [0, "\xf3H"], "\xe4" => [0, "\xf3I"], "\xe5" => [0, "\xf3J"], "\xe6" => [0, "\xf3K"], "\xe7" => [0, "\xf3L"], "\xe8" => [0, "\xf3M"], "\xe9" => [0, "\xf3N"], "\xea" => [0, "\xf3O"], "\xeb" => [0, "\xf3P"], "\xec" => [0, "\xf3Q"], "\xed" => [0, "\xf3R"], "\xee" => [0, "\xf3S"], "\xef" => [0, "\xf3T"], "\xf0" => [0, "\xf3U"], "\xf1" => [0, "\xf3V"], "\xf2" => [0, "\xf3W"], "\xf3" => [0, "\xf3Y"], "\xf4" => [0, "\xf3j"], "\xf5" => [0, "\xf3k"], "\xf6" => [0, "\xf3q"], "\xf7" => [0, "\xf3v"], "\xf8" => [0, "\xf3w"], "\xf9" => [0, "\xf3x"], "\xfa" => [0, "\xf3y"], "\xfb" => [0, "\xf3z"], "\xfc" => [82, "\xf3"], "\xfd" => [87, "\xf3"], "\xfe" => [130, "\xf3"], "\xff" => [9, "\xf3"]], ["\x00" => [0, "\xf50"], "\x01" => [0, "\xf51"], "\x02" => [0, "\xf52"], "\x03" => [0, "\xf5a"], "\x04" => [0, "\xf5c"], "\x05" => [0, "\xf5e"], "\x06" => [0, "\xf5i"], "\x07" => [0, "\xf5o"], "\x08" => [0, "\xf5s"], "\t" => [0, "\xf5t"], "\n" => [73, "\xf5"], "\v" => [88, "\xf5"], "\f" => [89, "\xf5"], "\r" => [96, "\xf5"], "\x0e" => [97, "\xf5"], "\x0f" => [99, "\xf5"], "\x10" => [106, "\xf5"], "\x11" => [136, "\xf5"], "\x12" => [139, "\xf5"], "\x13" => [141, "\xf5"], "\x14" => [145, "\xf5"], "\x15" => [147, "\xf5"], "\x16" => [149, "\xf5"], "\x17" => [101, "\xf5"], "\x18" => [112, "\xf5"], "\x19" => [117, "\xf5"], "\x1a" => [120, "\xf5"], "\x1b" => [124, "\xf5"], "\x1c" => [127, "\xf5"], "\x1d" => [144, "\xf5"], "\x1e" => [152, "\xf5"], "\x1f" => [11, "\xf5"], " " => [0, "\xf60"], "!" => [0, "\xf61"], "\"" => [0, "\xf62"], "#" => [0, "\xf6a"], "\$" => [0, "\xf6c"], "%" => [0, "\xf6e"], "&" => [0, "\xf6i"], "'" => [0, "\xf6o"], "(" => [0, "\xf6s"], ")" => [0, "\xf6t"], "*" => [73, "\xf6"], "+" => [88, "\xf6"], "," => [89, "\xf6"], "-" => [96, "\xf6"], "." => [97, "\xf6"], "/" => [99, "\xf6"], [106, "\xf6"], [136, "\xf6"], [139, "\xf6"], [141, "\xf6"], [145, "\xf6"], [147, "\xf6"], [149, "\xf6"], [101, "\xf6"], [112, "\xf6"], [117, "\xf6"], ":" => [120, "\xf6"], ";" => [124, "\xf6"], "<" => [127, "\xf6"], "=" => [144, "\xf6"], ">" => [152, "\xf6"], "?" => [11, "\xf6"], "@" => [0, "\xf70"], "A" => [0, "\xf71"], "B" => [0, "\xf72"], "C" => [0, "\xf7a"], "D" => [0, "\xf7c"], "E" => [0, "\xf7e"], "F" => [0, "\xf7i"], "G" => [0, "\xf7o"], "H" => [0, "\xf7s"], "I" => [0, "\xf7t"], "J" => [73, "\xf7"], "K" => [88, "\xf7"], "L" => [89, "\xf7"], "M" => [96, "\xf7"], "N" => [97, "\xf7"], "O" => [99, "\xf7"], "P" => [106, "\xf7"], "Q" => [136, "\xf7"], "R" => [139, "\xf7"], "S" => [141, "\xf7"], "T" => [145, "\xf7"], "U" => [147, "\xf7"], "V" => [149, "\xf7"], "W" => [101, "\xf7"], "X" => [112, "\xf7"], "Y" => [117, "\xf7"], "Z" => [120, "\xf7"], "[" => [124, "\xf7"], "\\" => [127, "\xf7"], "]" => [144, "\xf7"], "^" => [152, "\xf7"], "_" => [11, "\xf7"], "`" => [0, "\xf80"], "a" => [0, "\xf81"], "b" => [0, "\xf82"], "c" => [0, "\xf8a"], "d" => [0, "\xf8c"], "e" => [0, "\xf8e"], "f" => [0, "\xf8i"], "g" => [0, "\xf8o"], "h" => [0, "\xf8s"], "i" => [0, "\xf8t"], "j" => [73, "\xf8"], "k" => [88, "\xf8"], "l" => [89, "\xf8"], "m" => [96, "\xf8"], "n" => [97, "\xf8"], "o" => [99, "\xf8"], "p" => [106, "\xf8"], "q" => [136, "\xf8"], "r" => [139, "\xf8"], "s" => [141, "\xf8"], "t" => [145, "\xf8"], "u" => [147, "\xf8"], "v" => [149, "\xf8"], "w" => [101, "\xf8"], "x" => [112, "\xf8"], "y" => [117, "\xf8"], "z" => [120, "\xf8"], "{" => [124, "\xf8"], "|" => [127, "\xf8"], "}" => [144, "\xf8"], "~" => [152, "\xf8"], "" => [11, "\xf8"], "\x80" => [0, "\xfa0"], "\x81" => [0, "\xfa1"], "\x82" => [0, "\xfa2"], "\x83" => [0, "\xfaa"], "\x84" => [0, "\xfac"], "\x85" => [0, "\xfae"], "\x86" => [0, "\xfai"], "\x87" => [0, "\xfao"], "\x88" => [0, "\xfas"], "\x89" => [0, "\xfat"], "\x8a" => [73, "\xfa"], "\x8b" => [88, "\xfa"], "\x8c" => [89, "\xfa"], "\x8d" => [96, "\xfa"], "\x8e" => [97, "\xfa"], "\x8f" => [99, "\xfa"], "\x90" => [106, "\xfa"], "\x91" => [136, "\xfa"], "\x92" => [139, "\xfa"], "\x93" => [141, "\xfa"], "\x94" => [145, "\xfa"], "\x95" => [147, "\xfa"], "\x96" => [149, "\xfa"], "\x97" => [101, "\xfa"], "\x98" => [112, "\xfa"], "\x99" => [117, "\xfa"], "\x9a" => [120, "\xfa"], "\x9b" => [124, "\xfa"], "\x9c" => [127, "\xfa"], "\x9d" => [144, "\xfa"], "\x9e" => [152, "\xfa"], "\x9f" => [11, "\xfa"], "\xa0" => [0, "\xfb0"], "\xa1" => [0, "\xfb1"], "\xa2" => [0, "\xfb2"], "\xa3" => [0, "\xfba"], "\xa4" => [0, "\xfbc"], "\xa5" => [0, "\xfbe"], "\xa6" => [0, "\xfbi"], "\xa7" => [0, "\xfbo"], "\xa8" => [0, "\xfbs"], "\xa9" => [0, "\xfbt"], "\xaa" => [73, "\xfb"], "\xab" => [88, "\xfb"], "\xac" => [89, "\xfb"], "\xad" => [96, "\xfb"], "\xae" => [97, "\xfb"], "\xaf" => [99, "\xfb"], "\xb0" => [106, "\xfb"], "\xb1" => [136, "\xfb"], "\xb2" => [139, "\xfb"], "\xb3" => [141, "\xfb"], "\xb4" => [145, "\xfb"], "\xb5" => [147, "\xfb"], "\xb6" => [149, "\xfb"], "\xb7" => [101, "\xfb"], "\xb8" => [112, "\xfb"], "\xb9" => [117, "\xfb"], "\xba" => [120, "\xfb"], "\xbb" => [124, "\xfb"], "\xbc" => [127, "\xfb"], "\xbd" => [144, "\xfb"], "\xbe" => [152, "\xfb"], "\xbf" => [11, "\xfb"], "\xc0" => [0, "\xfc0"], "\xc1" => [0, "\xfc1"], "\xc2" => [0, "\xfc2"], "\xc3" => [0, "\xfca"], "\xc4" => [0, "\xfcc"], "\xc5" => [0, "\xfce"], "\xc6" => [0, "\xfci"], "\xc7" => [0, "\xfco"], "\xc8" => [0, "\xfcs"], "\xc9" => [0, "\xfct"], "\xca" => [73, "\xfc"], "\xcb" => [88, "\xfc"], "\xcc" => [89, "\xfc"], "\xcd" => [96, "\xfc"], "\xce" => [97, "\xfc"], "\xcf" => [99, "\xfc"], "\xd0" => [106, "\xfc"], "\xd1" => [136, "\xfc"], "\xd2" => [139, "\xfc"], "\xd3" => [141, "\xfc"], "\xd4" => [145, "\xfc"], "\xd5" => [147, "\xfc"], "\xd6" => [149, "\xfc"], "\xd7" => [101, "\xfc"], "\xd8" => [112, "\xfc"], "\xd9" => [117, "\xfc"], "\xda" => [120, "\xfc"], "\xdb" => [124, "\xfc"], "\xdc" => [127, "\xfc"], "\xdd" => [144, "\xfc"], "\xde" => [152, "\xfc"], "\xdf" => [11, "\xfc"], "\xe0" => [0, "\xfd0"], "\xe1" => [0, "\xfd1"], "\xe2" => [0, "\xfd2"], "\xe3" => [0, "\xfda"], "\xe4" => [0, "\xfdc"], "\xe5" => [0, "\xfde"], "\xe6" => [0, "\xfdi"], "\xe7" => [0, "\xfdo"], "\xe8" => [0, "\xfds"], "\xe9" => [0, "\xfdt"], "\xea" => [73, "\xfd"], "\xeb" => [88, "\xfd"], "\xec" => [89, "\xfd"], "\xed" => [96, "\xfd"], "\xee" => [97, "\xfd"], "\xef" => [99, "\xfd"], "\xf0" => [106, "\xfd"], "\xf1" => [136, "\xfd"], "\xf2" => [139, "\xfd"], "\xf3" => [141, "\xfd"], "\xf4" => [145, "\xfd"], "\xf5" => [147, "\xfd"], "\xf6" => [149, "\xfd"], "\xf7" => [101, "\xfd"], "\xf8" => [112, "\xfd"], "\xf9" => [117, "\xfd"], "\xfa" => [120, "\xfd"], "\xfb" => [124, "\xfd"], "\xfc" => [127, "\xfd"], "\xfd" => [144, "\xfd"], "\xfe" => [152, "\xfd"], "\xff" => [11, "\xfd"]], ["\x00" => [94, "\xf50"], "\x01" => [76, "\xf50"], "\x02" => [104, "\xf50"], "\x03" => [16, "\xf50"], "\x04" => [94, "\xf51"], "\x05" => [76, "\xf51"], "\x06" => [104, "\xf51"], "\x07" => [16, "\xf51"], "\x08" => [94, "\xf52"], "\t" => [76, "\xf52"], "\n" => [104, "\xf52"], "\v" => [16, "\xf52"], "\f" => [94, "\xf5a"], "\r" => [76, "\xf5a"], "\x0e" => [104, "\xf5a"], "\x0f" => [16, "\xf5a"], "\x10" => [94, "\xf5c"], "\x11" => [76, "\xf5c"], "\x12" => [104, "\xf5c"], "\x13" => [16, "\xf5c"], "\x14" => [94, "\xf5e"], "\x15" => [76, "\xf5e"], "\x16" => [104, "\xf5e"], "\x17" => [16, "\xf5e"], "\x18" => [94, "\xf5i"], "\x19" => [76, "\xf5i"], "\x1a" => [104, "\xf5i"], "\x1b" => [16, "\xf5i"], "\x1c" => [94, "\xf5o"], "\x1d" => [76, "\xf5o"], "\x1e" => [104, "\xf5o"], "\x1f" => [16, "\xf5o"], " " => [94, "\xf5s"], "!" => [76, "\xf5s"], "\"" => [104, "\xf5s"], "#" => [16, "\xf5s"], "\$" => [94, "\xf5t"], "%" => [76, "\xf5t"], "&" => [104, "\xf5t"], "'" => [16, "\xf5t"], "(" => [77, "\xf5 "], ")" => [18, "\xf5 "], "*" => [77, "\xf5%"], "+" => [18, "\xf5%"], "," => [77, "\xf5-"], "-" => [18, "\xf5-"], "." => [77, "\xf5."], "/" => [18, "\xf5."], [77, "\xf5/"], [18, "\xf5/"], [77, "\xf53"], [18, "\xf53"], [77, "\xf54"], [18, "\xf54"], [77, "\xf55"], [18, "\xf55"], [77, "\xf56"], [18, "\xf56"], ":" => [77, "\xf57"], ";" => [18, "\xf57"], "<" => [77, "\xf58"], "=" => [18, "\xf58"], ">" => [77, "\xf59"], "?" => [18, "\xf59"], "@" => [77, "\xf5="], "A" => [18, "\xf5="], "B" => [77, "\xf5A"], "C" => [18, "\xf5A"], "D" => [77, "\xf5_"], "E" => [18, "\xf5_"], "F" => [77, "\xf5b"], "G" => [18, "\xf5b"], "H" => [77, "\xf5d"], "I" => [18, "\xf5d"], "J" => [77, "\xf5f"], "K" => [18, "\xf5f"], "L" => [77, "\xf5g"], "M" => [18, "\xf5g"], "N" => [77, "\xf5h"], "O" => [18, "\xf5h"], "P" => [77, "\xf5l"], "Q" => [18, "\xf5l"], "R" => [77, "\xf5m"], "S" => [18, "\xf5m"], "T" => [77, "\xf5n"], "U" => [18, "\xf5n"], "V" => [77, "\xf5p"], "W" => [18, "\xf5p"], "X" => [77, "\xf5r"], "Y" => [18, "\xf5r"], "Z" => [77, "\xf5u"], "[" => [18, "\xf5u"], "\\" => [0, "\xf5:"], "]" => [0, "\xf5B"], "^" => [0, "\xf5C"], "_" => [0, "\xf5D"], "`" => [0, "\xf5E"], "a" => [0, "\xf5F"], "b" => [0, "\xf5G"], "c" => [0, "\xf5H"], "d" => [0, "\xf5I"], "e" => [0, "\xf5J"], "f" => [0, "\xf5K"], "g" => [0, "\xf5L"], "h" => [0, "\xf5M"], "i" => [0, "\xf5N"], "j" => [0, "\xf5O"], "k" => [0, "\xf5P"], "l" => [0, "\xf5Q"], "m" => [0, "\xf5R"], "n" => [0, "\xf5S"], "o" => [0, "\xf5T"], "p" => [0, "\xf5U"], "q" => [0, "\xf5V"], "r" => [0, "\xf5W"], "s" => [0, "\xf5Y"], "t" => [0, "\xf5j"], "u" => [0, "\xf5k"], "v" => [0, "\xf5q"], "w" => [0, "\xf5v"], "x" => [0, "\xf5w"], "y" => [0, "\xf5x"], "z" => [0, "\xf5y"], "{" => [0, "\xf5z"], "|" => [82, "\xf5"], "}" => [87, "\xf5"], "~" => [130, "\xf5"], "" => [9, "\xf5"], "\x80" => [94, "\xf60"], "\x81" => [76, "\xf60"], "\x82" => [104, "\xf60"], "\x83" => [16, "\xf60"], "\x84" => [94, "\xf61"], "\x85" => [76, "\xf61"], "\x86" => [104, "\xf61"], "\x87" => [16, "\xf61"], "\x88" => [94, "\xf62"], "\x89" => [76, "\xf62"], "\x8a" => [104, "\xf62"], "\x8b" => [16, "\xf62"], "\x8c" => [94, "\xf6a"], "\x8d" => [76, "\xf6a"], "\x8e" => [104, "\xf6a"], "\x8f" => [16, "\xf6a"], "\x90" => [94, "\xf6c"], "\x91" => [76, "\xf6c"], "\x92" => [104, "\xf6c"], "\x93" => [16, "\xf6c"], "\x94" => [94, "\xf6e"], "\x95" => [76, "\xf6e"], "\x96" => [104, "\xf6e"], "\x97" => [16, "\xf6e"], "\x98" => [94, "\xf6i"], "\x99" => [76, "\xf6i"], "\x9a" => [104, "\xf6i"], "\x9b" => [16, "\xf6i"], "\x9c" => [94, "\xf6o"], "\x9d" => [76, "\xf6o"], "\x9e" => [104, "\xf6o"], "\x9f" => [16, "\xf6o"], "\xa0" => [94, "\xf6s"], "\xa1" => [76, "\xf6s"], "\xa2" => [104, "\xf6s"], "\xa3" => [16, "\xf6s"], "\xa4" => [94, "\xf6t"], "\xa5" => [76, "\xf6t"], "\xa6" => [104, "\xf6t"], "\xa7" => [16, "\xf6t"], "\xa8" => [77, "\xf6 "], "\xa9" => [18, "\xf6 "], "\xaa" => [77, "\xf6%"], "\xab" => [18, "\xf6%"], "\xac" => [77, "\xf6-"], "\xad" => [18, "\xf6-"], "\xae" => [77, "\xf6."], "\xaf" => [18, "\xf6."], "\xb0" => [77, "\xf6/"], "\xb1" => [18, "\xf6/"], "\xb2" => [77, "\xf63"], "\xb3" => [18, "\xf63"], "\xb4" => [77, "\xf64"], "\xb5" => [18, "\xf64"], "\xb6" => [77, "\xf65"], "\xb7" => [18, "\xf65"], "\xb8" => [77, "\xf66"], "\xb9" => [18, "\xf66"], "\xba" => [77, "\xf67"], "\xbb" => [18, "\xf67"], "\xbc" => [77, "\xf68"], "\xbd" => [18, "\xf68"], "\xbe" => [77, "\xf69"], "\xbf" => [18, "\xf69"], "\xc0" => [77, "\xf6="], "\xc1" => [18, "\xf6="], "\xc2" => [77, "\xf6A"], "\xc3" => [18, "\xf6A"], "\xc4" => [77, "\xf6_"], "\xc5" => [18, "\xf6_"], "\xc6" => [77, "\xf6b"], "\xc7" => [18, "\xf6b"], "\xc8" => [77, "\xf6d"], "\xc9" => [18, "\xf6d"], "\xca" => [77, "\xf6f"], "\xcb" => [18, "\xf6f"], "\xcc" => [77, "\xf6g"], "\xcd" => [18, "\xf6g"], "\xce" => [77, "\xf6h"], "\xcf" => [18, "\xf6h"], "\xd0" => [77, "\xf6l"], "\xd1" => [18, "\xf6l"], "\xd2" => [77, "\xf6m"], "\xd3" => [18, "\xf6m"], "\xd4" => [77, "\xf6n"], "\xd5" => [18, "\xf6n"], "\xd6" => [77, "\xf6p"], "\xd7" => [18, "\xf6p"], "\xd8" => [77, "\xf6r"], "\xd9" => [18, "\xf6r"], "\xda" => [77, "\xf6u"], "\xdb" => [18, "\xf6u"], "\xdc" => [0, "\xf6:"], "\xdd" => [0, "\xf6B"], "\xde" => [0, "\xf6C"], "\xdf" => [0, "\xf6D"], "\xe0" => [0, "\xf6E"], "\xe1" => [0, "\xf6F"], "\xe2" => [0, "\xf6G"], "\xe3" => [0, "\xf6H"], "\xe4" => [0, "\xf6I"], "\xe5" => [0, "\xf6J"], "\xe6" => [0, "\xf6K"], "\xe7" => [0, "\xf6L"], "\xe8" => [0, "\xf6M"], "\xe9" => [0, "\xf6N"], "\xea" => [0, "\xf6O"], "\xeb" => [0, "\xf6P"], "\xec" => [0, "\xf6Q"], "\xed" => [0, "\xf6R"], "\xee" => [0, "\xf6S"], "\xef" => [0, "\xf6T"], "\xf0" => [0, "\xf6U"], "\xf1" => [0, "\xf6V"], "\xf2" => [0, "\xf6W"], "\xf3" => [0, "\xf6Y"], "\xf4" => [0, "\xf6j"], "\xf5" => [0, "\xf6k"], "\xf6" => [0, "\xf6q"], "\xf7" => [0, "\xf6v"], "\xf8" => [0, "\xf6w"], "\xf9" => [0, "\xf6x"], "\xfa" => [0, "\xf6y"], "\xfb" => [0, "\xf6z"], "\xfc" => [82, "\xf6"], "\xfd" => [87, "\xf6"], "\xfe" => [130, "\xf6"], "\xff" => [9, "\xf6"]], ["\x00" => [77, "\xf50"], "\x01" => [18, "\xf50"], "\x02" => [77, "\xf51"], "\x03" => [18, "\xf51"], "\x04" => [77, "\xf52"], "\x05" => [18, "\xf52"], "\x06" => [77, "\xf5a"], "\x07" => [18, "\xf5a"], "\x08" => [77, "\xf5c"], "\t" => [18, "\xf5c"], "\n" => [77, "\xf5e"], "\v" => [18, "\xf5e"], "\f" => [77, "\xf5i"], "\r" => [18, "\xf5i"], "\x0e" => [77, "\xf5o"], "\x0f" => [18, "\xf5o"], "\x10" => [77, "\xf5s"], "\x11" => [18, "\xf5s"], "\x12" => [77, "\xf5t"], "\x13" => [18, "\xf5t"], "\x14" => [0, "\xf5 "], "\x15" => [0, "\xf5%"], "\x16" => [0, "\xf5-"], "\x17" => [0, "\xf5."], "\x18" => [0, "\xf5/"], "\x19" => [0, "\xf53"], "\x1a" => [0, "\xf54"], "\x1b" => [0, "\xf55"], "\x1c" => [0, "\xf56"], "\x1d" => [0, "\xf57"], "\x1e" => [0, "\xf58"], "\x1f" => [0, "\xf59"], " " => [0, "\xf5="], "!" => [0, "\xf5A"], "\"" => [0, "\xf5_"], "#" => [0, "\xf5b"], "\$" => [0, "\xf5d"], "%" => [0, "\xf5f"], "&" => [0, "\xf5g"], "'" => [0, "\xf5h"], "(" => [0, "\xf5l"], ")" => [0, "\xf5m"], "*" => [0, "\xf5n"], "+" => [0, "\xf5p"], "," => [0, "\xf5r"], "-" => [0, "\xf5u"], "." => [100, "\xf5"], "/" => [110, "\xf5"], [111, "\xf5"], [115, "\xf5"], [116, "\xf5"], [118, "\xf5"], [119, "\xf5"], [122, "\xf5"], [123, "\xf5"], [125, "\xf5"], [126, "\xf5"], [129, "\xf5"], ":" => [143, "\xf5"], ";" => [148, "\xf5"], "<" => [151, "\xf5"], "=" => [153, "\xf5"], ">" => [83, "\xf5"], "?" => [10, "\xf5"], "@" => [77, "\xf60"], "A" => [18, "\xf60"], "B" => [77, "\xf61"], "C" => [18, "\xf61"], "D" => [77, "\xf62"], "E" => [18, "\xf62"], "F" => [77, "\xf6a"], "G" => [18, "\xf6a"], "H" => [77, "\xf6c"], "I" => [18, "\xf6c"], "J" => [77, "\xf6e"], "K" => [18, "\xf6e"], "L" => [77, "\xf6i"], "M" => [18, "\xf6i"], "N" => [77, "\xf6o"], "O" => [18, "\xf6o"], "P" => [77, "\xf6s"], "Q" => [18, "\xf6s"], "R" => [77, "\xf6t"], "S" => [18, "\xf6t"], "T" => [0, "\xf6 "], "U" => [0, "\xf6%"], "V" => [0, "\xf6-"], "W" => [0, "\xf6."], "X" => [0, "\xf6/"], "Y" => [0, "\xf63"], "Z" => [0, "\xf64"], "[" => [0, "\xf65"], "\\" => [0, "\xf66"], "]" => [0, "\xf67"], "^" => [0, "\xf68"], "_" => [0, "\xf69"], "`" => [0, "\xf6="], "a" => [0, "\xf6A"], "b" => [0, "\xf6_"], "c" => [0, "\xf6b"], "d" => [0, "\xf6d"], "e" => [0, "\xf6f"], "f" => [0, "\xf6g"], "g" => [0, "\xf6h"], "h" => [0, "\xf6l"], "i" => [0, "\xf6m"], "j" => [0, "\xf6n"], "k" => [0, "\xf6p"], "l" => [0, "\xf6r"], "m" => [0, "\xf6u"], "n" => [100, "\xf6"], "o" => [110, "\xf6"], "p" => [111, "\xf6"], "q" => [115, "\xf6"], "r" => [116, "\xf6"], "s" => [118, "\xf6"], "t" => [119, "\xf6"], "u" => [122, "\xf6"], "v" => [123, "\xf6"], "w" => [125, "\xf6"], "x" => [126, "\xf6"], "y" => [129, "\xf6"], "z" => [143, "\xf6"], "{" => [148, "\xf6"], "|" => [151, "\xf6"], "}" => [153, "\xf6"], "~" => [83, "\xf6"], "" => [10, "\xf6"], "\x80" => [77, "\xf70"], "\x81" => [18, "\xf70"], "\x82" => [77, "\xf71"], "\x83" => [18, "\xf71"], "\x84" => [77, "\xf72"], "\x85" => [18, "\xf72"], "\x86" => [77, "\xf7a"], "\x87" => [18, "\xf7a"], "\x88" => [77, "\xf7c"], "\x89" => [18, "\xf7c"], "\x8a" => [77, "\xf7e"], "\x8b" => [18, "\xf7e"], "\x8c" => [77, "\xf7i"], "\x8d" => [18, "\xf7i"], "\x8e" => [77, "\xf7o"], "\x8f" => [18, "\xf7o"], "\x90" => [77, "\xf7s"], "\x91" => [18, "\xf7s"], "\x92" => [77, "\xf7t"], "\x93" => [18, "\xf7t"], "\x94" => [0, "\xf7 "], "\x95" => [0, "\xf7%"], "\x96" => [0, "\xf7-"], "\x97" => [0, "\xf7."], "\x98" => [0, "\xf7/"], "\x99" => [0, "\xf73"], "\x9a" => [0, "\xf74"], "\x9b" => [0, "\xf75"], "\x9c" => [0, "\xf76"], "\x9d" => [0, "\xf77"], "\x9e" => [0, "\xf78"], "\x9f" => [0, "\xf79"], "\xa0" => [0, "\xf7="], "\xa1" => [0, "\xf7A"], "\xa2" => [0, "\xf7_"], "\xa3" => [0, "\xf7b"], "\xa4" => [0, "\xf7d"], "\xa5" => [0, "\xf7f"], "\xa6" => [0, "\xf7g"], "\xa7" => [0, "\xf7h"], "\xa8" => [0, "\xf7l"], "\xa9" => [0, "\xf7m"], "\xaa" => [0, "\xf7n"], "\xab" => [0, "\xf7p"], "\xac" => [0, "\xf7r"], "\xad" => [0, "\xf7u"], "\xae" => [100, "\xf7"], "\xaf" => [110, "\xf7"], "\xb0" => [111, "\xf7"], "\xb1" => [115, "\xf7"], "\xb2" => [116, "\xf7"], "\xb3" => [118, "\xf7"], "\xb4" => [119, "\xf7"], "\xb5" => [122, "\xf7"], "\xb6" => [123, "\xf7"], "\xb7" => [125, "\xf7"], "\xb8" => [126, "\xf7"], "\xb9" => [129, "\xf7"], "\xba" => [143, "\xf7"], "\xbb" => [148, "\xf7"], "\xbc" => [151, "\xf7"], "\xbd" => [153, "\xf7"], "\xbe" => [83, "\xf7"], "\xbf" => [10, "\xf7"], "\xc0" => [77, "\xf80"], "\xc1" => [18, "\xf80"], "\xc2" => [77, "\xf81"], "\xc3" => [18, "\xf81"], "\xc4" => [77, "\xf82"], "\xc5" => [18, "\xf82"], "\xc6" => [77, "\xf8a"], "\xc7" => [18, "\xf8a"], "\xc8" => [77, "\xf8c"], "\xc9" => [18, "\xf8c"], "\xca" => [77, "\xf8e"], "\xcb" => [18, "\xf8e"], "\xcc" => [77, "\xf8i"], "\xcd" => [18, "\xf8i"], "\xce" => [77, "\xf8o"], "\xcf" => [18, "\xf8o"], "\xd0" => [77, "\xf8s"], "\xd1" => [18, "\xf8s"], "\xd2" => [77, "\xf8t"], "\xd3" => [18, "\xf8t"], "\xd4" => [0, "\xf8 "], "\xd5" => [0, "\xf8%"], "\xd6" => [0, "\xf8-"], "\xd7" => [0, "\xf8."], "\xd8" => [0, "\xf8/"], "\xd9" => [0, "\xf83"], "\xda" => [0, "\xf84"], "\xdb" => [0, "\xf85"], "\xdc" => [0, "\xf86"], "\xdd" => [0, "\xf87"], "\xde" => [0, "\xf88"], "\xdf" => [0, "\xf89"], "\xe0" => [0, "\xf8="], "\xe1" => [0, "\xf8A"], "\xe2" => [0, "\xf8_"], "\xe3" => [0, "\xf8b"], "\xe4" => [0, "\xf8d"], "\xe5" => [0, "\xf8f"], "\xe6" => [0, "\xf8g"], "\xe7" => [0, "\xf8h"], "\xe8" => [0, "\xf8l"], "\xe9" => [0, "\xf8m"], "\xea" => [0, "\xf8n"], "\xeb" => [0, "\xf8p"], "\xec" => [0, "\xf8r"], "\xed" => [0, "\xf8u"], "\xee" => [100, "\xf8"], "\xef" => [110, "\xf8"], "\xf0" => [111, "\xf8"], "\xf1" => [115, "\xf8"], "\xf2" => [116, "\xf8"], "\xf3" => [118, "\xf8"], "\xf4" => [119, "\xf8"], "\xf5" => [122, "\xf8"], "\xf6" => [123, "\xf8"], "\xf7" => [125, "\xf8"], "\xf8" => [126, "\xf8"], "\xf9" => [129, "\xf8"], "\xfa" => [143, "\xf8"], "\xfb" => [148, "\xf8"], "\xfc" => [151, "\xf8"], "\xfd" => [153, "\xf8"], "\xfe" => [83, "\xf8"], "\xff" => [10, "\xf8"]], ["\x00" => [94, "\xf70"], "\x01" => [76, "\xf70"], "\x02" => [104, "\xf70"], "\x03" => [16, "\xf70"], "\x04" => [94, "\xf71"], "\x05" => [76, "\xf71"], "\x06" => [104, "\xf71"], "\x07" => [16, "\xf71"], "\x08" => [94, "\xf72"], "\t" => [76, "\xf72"], "\n" => [104, "\xf72"], "\v" => [16, "\xf72"], "\f" => [94, "\xf7a"], "\r" => [76, "\xf7a"], "\x0e" => [104, "\xf7a"], "\x0f" => [16, "\xf7a"], "\x10" => [94, "\xf7c"], "\x11" => [76, "\xf7c"], "\x12" => [104, "\xf7c"], "\x13" => [16, "\xf7c"], "\x14" => [94, "\xf7e"], "\x15" => [76, "\xf7e"], "\x16" => [104, "\xf7e"], "\x17" => [16, "\xf7e"], "\x18" => [94, "\xf7i"], "\x19" => [76, "\xf7i"], "\x1a" => [104, "\xf7i"], "\x1b" => [16, "\xf7i"], "\x1c" => [94, "\xf7o"], "\x1d" => [76, "\xf7o"], "\x1e" => [104, "\xf7o"], "\x1f" => [16, "\xf7o"], " " => [94, "\xf7s"], "!" => [76, "\xf7s"], "\"" => [104, "\xf7s"], "#" => [16, "\xf7s"], "\$" => [94, "\xf7t"], "%" => [76, "\xf7t"], "&" => [104, "\xf7t"], "'" => [16, "\xf7t"], "(" => [77, "\xf7 "], ")" => [18, "\xf7 "], "*" => [77, "\xf7%"], "+" => [18, "\xf7%"], "," => [77, "\xf7-"], "-" => [18, "\xf7-"], "." => [77, "\xf7."], "/" => [18, "\xf7."], [77, "\xf7/"], [18, "\xf7/"], [77, "\xf73"], [18, "\xf73"], [77, "\xf74"], [18, "\xf74"], [77, "\xf75"], [18, "\xf75"], [77, "\xf76"], [18, "\xf76"], ":" => [77, "\xf77"], ";" => [18, "\xf77"], "<" => [77, "\xf78"], "=" => [18, "\xf78"], ">" => [77, "\xf79"], "?" => [18, "\xf79"], "@" => [77, "\xf7="], "A" => [18, "\xf7="], "B" => [77, "\xf7A"], "C" => [18, "\xf7A"], "D" => [77, "\xf7_"], "E" => [18, "\xf7_"], "F" => [77, "\xf7b"], "G" => [18, "\xf7b"], "H" => [77, "\xf7d"], "I" => [18, "\xf7d"], "J" => [77, "\xf7f"], "K" => [18, "\xf7f"], "L" => [77, "\xf7g"], "M" => [18, "\xf7g"], "N" => [77, "\xf7h"], "O" => [18, "\xf7h"], "P" => [77, "\xf7l"], "Q" => [18, "\xf7l"], "R" => [77, "\xf7m"], "S" => [18, "\xf7m"], "T" => [77, "\xf7n"], "U" => [18, "\xf7n"], "V" => [77, "\xf7p"], "W" => [18, "\xf7p"], "X" => [77, "\xf7r"], "Y" => [18, "\xf7r"], "Z" => [77, "\xf7u"], "[" => [18, "\xf7u"], "\\" => [0, "\xf7:"], "]" => [0, "\xf7B"], "^" => [0, "\xf7C"], "_" => [0, "\xf7D"], "`" => [0, "\xf7E"], "a" => [0, "\xf7F"], "b" => [0, "\xf7G"], "c" => [0, "\xf7H"], "d" => [0, "\xf7I"], "e" => [0, "\xf7J"], "f" => [0, "\xf7K"], "g" => [0, "\xf7L"], "h" => [0, "\xf7M"], "i" => [0, "\xf7N"], "j" => [0, "\xf7O"], "k" => [0, "\xf7P"], "l" => [0, "\xf7Q"], "m" => [0, "\xf7R"], "n" => [0, "\xf7S"], "o" => [0, "\xf7T"], "p" => [0, "\xf7U"], "q" => [0, "\xf7V"], "r" => [0, "\xf7W"], "s" => [0, "\xf7Y"], "t" => [0, "\xf7j"], "u" => [0, "\xf7k"], "v" => [0, "\xf7q"], "w" => [0, "\xf7v"], "x" => [0, "\xf7w"], "y" => [0, "\xf7x"], "z" => [0, "\xf7y"], "{" => [0, "\xf7z"], "|" => [82, "\xf7"], "}" => [87, "\xf7"], "~" => [130, "\xf7"], "" => [9, "\xf7"], "\x80" => [94, "\xf80"], "\x81" => [76, "\xf80"], "\x82" => [104, "\xf80"], "\x83" => [16, "\xf80"], "\x84" => [94, "\xf81"], "\x85" => [76, "\xf81"], "\x86" => [104, "\xf81"], "\x87" => [16, "\xf81"], "\x88" => [94, "\xf82"], "\x89" => [76, "\xf82"], "\x8a" => [104, "\xf82"], "\x8b" => [16, "\xf82"], "\x8c" => [94, "\xf8a"], "\x8d" => [76, "\xf8a"], "\x8e" => [104, "\xf8a"], "\x8f" => [16, "\xf8a"], "\x90" => [94, "\xf8c"], "\x91" => [76, "\xf8c"], "\x92" => [104, "\xf8c"], "\x93" => [16, "\xf8c"], "\x94" => [94, "\xf8e"], "\x95" => [76, "\xf8e"], "\x96" => [104, "\xf8e"], "\x97" => [16, "\xf8e"], "\x98" => [94, "\xf8i"], "\x99" => [76, "\xf8i"], "\x9a" => [104, "\xf8i"], "\x9b" => [16, "\xf8i"], "\x9c" => [94, "\xf8o"], "\x9d" => [76, "\xf8o"], "\x9e" => [104, "\xf8o"], "\x9f" => [16, "\xf8o"], "\xa0" => [94, "\xf8s"], "\xa1" => [76, "\xf8s"], "\xa2" => [104, "\xf8s"], "\xa3" => [16, "\xf8s"], "\xa4" => [94, "\xf8t"], "\xa5" => [76, "\xf8t"], "\xa6" => [104, "\xf8t"], "\xa7" => [16, "\xf8t"], "\xa8" => [77, "\xf8 "], "\xa9" => [18, "\xf8 "], "\xaa" => [77, "\xf8%"], "\xab" => [18, "\xf8%"], "\xac" => [77, "\xf8-"], "\xad" => [18, "\xf8-"], "\xae" => [77, "\xf8."], "\xaf" => [18, "\xf8."], "\xb0" => [77, "\xf8/"], "\xb1" => [18, "\xf8/"], "\xb2" => [77, "\xf83"], "\xb3" => [18, "\xf83"], "\xb4" => [77, "\xf84"], "\xb5" => [18, "\xf84"], "\xb6" => [77, "\xf85"], "\xb7" => [18, "\xf85"], "\xb8" => [77, "\xf86"], "\xb9" => [18, "\xf86"], "\xba" => [77, "\xf87"], "\xbb" => [18, "\xf87"], "\xbc" => [77, "\xf88"], "\xbd" => [18, "\xf88"], "\xbe" => [77, "\xf89"], "\xbf" => [18, "\xf89"], "\xc0" => [77, "\xf8="], "\xc1" => [18, "\xf8="], "\xc2" => [77, "\xf8A"], "\xc3" => [18, "\xf8A"], "\xc4" => [77, "\xf8_"], "\xc5" => [18, "\xf8_"], "\xc6" => [77, "\xf8b"], "\xc7" => [18, "\xf8b"], "\xc8" => [77, "\xf8d"], "\xc9" => [18, "\xf8d"], "\xca" => [77, "\xf8f"], "\xcb" => [18, "\xf8f"], "\xcc" => [77, "\xf8g"], "\xcd" => [18, "\xf8g"], "\xce" => [77, "\xf8h"], "\xcf" => [18, "\xf8h"], "\xd0" => [77, "\xf8l"], "\xd1" => [18, "\xf8l"], "\xd2" => [77, "\xf8m"], "\xd3" => [18, "\xf8m"], "\xd4" => [77, "\xf8n"], "\xd5" => [18, "\xf8n"], "\xd6" => [77, "\xf8p"], "\xd7" => [18, "\xf8p"], "\xd8" => [77, "\xf8r"], "\xd9" => [18, "\xf8r"], "\xda" => [77, "\xf8u"], "\xdb" => [18, "\xf8u"], "\xdc" => [0, "\xf8:"], "\xdd" => [0, "\xf8B"], "\xde" => [0, "\xf8C"], "\xdf" => [0, "\xf8D"], "\xe0" => [0, "\xf8E"], "\xe1" => [0, "\xf8F"], "\xe2" => [0, "\xf8G"], "\xe3" => [0, "\xf8H"], "\xe4" => [0, "\xf8I"], "\xe5" => [0, "\xf8J"], "\xe6" => [0, "\xf8K"], "\xe7" => [0, "\xf8L"], "\xe8" => [0, "\xf8M"], "\xe9" => [0, "\xf8N"], "\xea" => [0, "\xf8O"], "\xeb" => [0, "\xf8P"], "\xec" => [0, "\xf8Q"], "\xed" => [0, "\xf8R"], "\xee" => [0, "\xf8S"], "\xef" => [0, "\xf8T"], "\xf0" => [0, "\xf8U"], "\xf1" => [0, "\xf8V"], "\xf2" => [0, "\xf8W"], "\xf3" => [0, "\xf8Y"], "\xf4" => [0, "\xf8j"], "\xf5" => [0, "\xf8k"], "\xf6" => [0, "\xf8q"], "\xf7" => [0, "\xf8v"], "\xf8" => [0, "\xf8w"], "\xf9" => [0, "\xf8x"], "\xfa" => [0, "\xf8y"], "\xfb" => [0, "\xf8z"], "\xfc" => [82, "\xf8"], "\xfd" => [87, "\xf8"], "\xfe" => [130, "\xf8"], "\xff" => [9, "\xf8"]], ["\x00" => [94, "\xfa0"], "\x01" => [76, "\xfa0"], "\x02" => [104, "\xfa0"], "\x03" => [16, "\xfa0"], "\x04" => [94, "\xfa1"], "\x05" => [76, "\xfa1"], "\x06" => [104, "\xfa1"], "\x07" => [16, "\xfa1"], "\x08" => [94, "\xfa2"], "\t" => [76, "\xfa2"], "\n" => [104, "\xfa2"], "\v" => [16, "\xfa2"], "\f" => [94, "\xfaa"], "\r" => [76, "\xfaa"], "\x0e" => [104, "\xfaa"], "\x0f" => [16, "\xfaa"], "\x10" => [94, "\xfac"], "\x11" => [76, "\xfac"], "\x12" => [104, "\xfac"], "\x13" => [16, "\xfac"], "\x14" => [94, "\xfae"], "\x15" => [76, "\xfae"], "\x16" => [104, "\xfae"], "\x17" => [16, "\xfae"], "\x18" => [94, "\xfai"], "\x19" => [76, "\xfai"], "\x1a" => [104, "\xfai"], "\x1b" => [16, "\xfai"], "\x1c" => [94, "\xfao"], "\x1d" => [76, "\xfao"], "\x1e" => [104, "\xfao"], "\x1f" => [16, "\xfao"], " " => [94, "\xfas"], "!" => [76, "\xfas"], "\"" => [104, "\xfas"], "#" => [16, "\xfas"], "\$" => [94, "\xfat"], "%" => [76, "\xfat"], "&" => [104, "\xfat"], "'" => [16, "\xfat"], "(" => [77, "\xfa "], ")" => [18, "\xfa "], "*" => [77, "\xfa%"], "+" => [18, "\xfa%"], "," => [77, "\xfa-"], "-" => [18, "\xfa-"], "." => [77, "\xfa."], "/" => [18, "\xfa."], [77, "\xfa/"], [18, "\xfa/"], [77, "\xfa3"], [18, "\xfa3"], [77, "\xfa4"], [18, "\xfa4"], [77, "\xfa5"], [18, "\xfa5"], [77, "\xfa6"], [18, "\xfa6"], ":" => [77, "\xfa7"], ";" => [18, "\xfa7"], "<" => [77, "\xfa8"], "=" => [18, "\xfa8"], ">" => [77, "\xfa9"], "?" => [18, "\xfa9"], "@" => [77, "\xfa="], "A" => [18, "\xfa="], "B" => [77, "\xfaA"], "C" => [18, "\xfaA"], "D" => [77, "\xfa_"], "E" => [18, "\xfa_"], "F" => [77, "\xfab"], "G" => [18, "\xfab"], "H" => [77, "\xfad"], "I" => [18, "\xfad"], "J" => [77, "\xfaf"], "K" => [18, "\xfaf"], "L" => [77, "\xfag"], "M" => [18, "\xfag"], "N" => [77, "\xfah"], "O" => [18, "\xfah"], "P" => [77, "\xfal"], "Q" => [18, "\xfal"], "R" => [77, "\xfam"], "S" => [18, "\xfam"], "T" => [77, "\xfan"], "U" => [18, "\xfan"], "V" => [77, "\xfap"], "W" => [18, "\xfap"], "X" => [77, "\xfar"], "Y" => [18, "\xfar"], "Z" => [77, "\xfau"], "[" => [18, "\xfau"], "\\" => [0, "\xfa:"], "]" => [0, "\xfaB"], "^" => [0, "\xfaC"], "_" => [0, "\xfaD"], "`" => [0, "\xfaE"], "a" => [0, "\xfaF"], "b" => [0, "\xfaG"], "c" => [0, "\xfaH"], "d" => [0, "\xfaI"], "e" => [0, "\xfaJ"], "f" => [0, "\xfaK"], "g" => [0, "\xfaL"], "h" => [0, "\xfaM"], "i" => [0, "\xfaN"], "j" => [0, "\xfaO"], "k" => [0, "\xfaP"], "l" => [0, "\xfaQ"], "m" => [0, "\xfaR"], "n" => [0, "\xfaS"], "o" => [0, "\xfaT"], "p" => [0, "\xfaU"], "q" => [0, "\xfaV"], "r" => [0, "\xfaW"], "s" => [0, "\xfaY"], "t" => [0, "\xfaj"], "u" => [0, "\xfak"], "v" => [0, "\xfaq"], "w" => [0, "\xfav"], "x" => [0, "\xfaw"], "y" => [0, "\xfax"], "z" => [0, "\xfay"], "{" => [0, "\xfaz"], "|" => [82, "\xfa"], "}" => [87, "\xfa"], "~" => [130, "\xfa"], "" => [9, "\xfa"], "\x80" => [94, "\xfb0"], "\x81" => [76, "\xfb0"], "\x82" => [104, "\xfb0"], "\x83" => [16, "\xfb0"], "\x84" => [94, "\xfb1"], "\x85" => [76, "\xfb1"], "\x86" => [104, "\xfb1"], "\x87" => [16, "\xfb1"], "\x88" => [94, "\xfb2"], "\x89" => [76, "\xfb2"], "\x8a" => [104, "\xfb2"], "\x8b" => [16, "\xfb2"], "\x8c" => [94, "\xfba"], "\x8d" => [76, "\xfba"], "\x8e" => [104, "\xfba"], "\x8f" => [16, "\xfba"], "\x90" => [94, "\xfbc"], "\x91" => [76, "\xfbc"], "\x92" => [104, "\xfbc"], "\x93" => [16, "\xfbc"], "\x94" => [94, "\xfbe"], "\x95" => [76, "\xfbe"], "\x96" => [104, "\xfbe"], "\x97" => [16, "\xfbe"], "\x98" => [94, "\xfbi"], "\x99" => [76, "\xfbi"], "\x9a" => [104, "\xfbi"], "\x9b" => [16, "\xfbi"], "\x9c" => [94, "\xfbo"], "\x9d" => [76, "\xfbo"], "\x9e" => [104, "\xfbo"], "\x9f" => [16, "\xfbo"], "\xa0" => [94, "\xfbs"], "\xa1" => [76, "\xfbs"], "\xa2" => [104, "\xfbs"], "\xa3" => [16, "\xfbs"], "\xa4" => [94, "\xfbt"], "\xa5" => [76, "\xfbt"], "\xa6" => [104, "\xfbt"], "\xa7" => [16, "\xfbt"], "\xa8" => [77, "\xfb "], "\xa9" => [18, "\xfb "], "\xaa" => [77, "\xfb%"], "\xab" => [18, "\xfb%"], "\xac" => [77, "\xfb-"], "\xad" => [18, "\xfb-"], "\xae" => [77, "\xfb."], "\xaf" => [18, "\xfb."], "\xb0" => [77, "\xfb/"], "\xb1" => [18, "\xfb/"], "\xb2" => [77, "\xfb3"], "\xb3" => [18, "\xfb3"], "\xb4" => [77, "\xfb4"], "\xb5" => [18, "\xfb4"], "\xb6" => [77, "\xfb5"], "\xb7" => [18, "\xfb5"], "\xb8" => [77, "\xfb6"], "\xb9" => [18, "\xfb6"], "\xba" => [77, "\xfb7"], "\xbb" => [18, "\xfb7"], "\xbc" => [77, "\xfb8"], "\xbd" => [18, "\xfb8"], "\xbe" => [77, "\xfb9"], "\xbf" => [18, "\xfb9"], "\xc0" => [77, "\xfb="], "\xc1" => [18, "\xfb="], "\xc2" => [77, "\xfbA"], "\xc3" => [18, "\xfbA"], "\xc4" => [77, "\xfb_"], "\xc5" => [18, "\xfb_"], "\xc6" => [77, "\xfbb"], "\xc7" => [18, "\xfbb"], "\xc8" => [77, "\xfbd"], "\xc9" => [18, "\xfbd"], "\xca" => [77, "\xfbf"], "\xcb" => [18, "\xfbf"], "\xcc" => [77, "\xfbg"], "\xcd" => [18, "\xfbg"], "\xce" => [77, "\xfbh"], "\xcf" => [18, "\xfbh"], "\xd0" => [77, "\xfbl"], "\xd1" => [18, "\xfbl"], "\xd2" => [77, "\xfbm"], "\xd3" => [18, "\xfbm"], "\xd4" => [77, "\xfbn"], "\xd5" => [18, "\xfbn"], "\xd6" => [77, "\xfbp"], "\xd7" => [18, "\xfbp"], "\xd8" => [77, "\xfbr"], "\xd9" => [18, "\xfbr"], "\xda" => [77, "\xfbu"], "\xdb" => [18, "\xfbu"], "\xdc" => [0, "\xfb:"], "\xdd" => [0, "\xfbB"], "\xde" => [0, "\xfbC"], "\xdf" => [0, "\xfbD"], "\xe0" => [0, "\xfbE"], "\xe1" => [0, "\xfbF"], "\xe2" => [0, "\xfbG"], "\xe3" => [0, "\xfbH"], "\xe4" => [0, "\xfbI"], "\xe5" => [0, "\xfbJ"], "\xe6" => [0, "\xfbK"], "\xe7" => [0, "\xfbL"], "\xe8" => [0, "\xfbM"], "\xe9" => [0, "\xfbN"], "\xea" => [0, "\xfbO"], "\xeb" => [0, "\xfbP"], "\xec" => [0, "\xfbQ"], "\xed" => [0, "\xfbR"], "\xee" => [0, "\xfbS"], "\xef" => [0, "\xfbT"], "\xf0" => [0, "\xfbU"], "\xf1" => [0, "\xfbV"], "\xf2" => [0, "\xfbW"], "\xf3" => [0, "\xfbY"], "\xf4" => [0, "\xfbj"], "\xf5" => [0, "\xfbk"], "\xf6" => [0, "\xfbq"], "\xf7" => [0, "\xfbv"], "\xf8" => [0, "\xfbw"], "\xf9" => [0, "\xfbx"], "\xfa" => [0, "\xfby"], "\xfb" => [0, "\xfbz"], "\xfc" => [82, "\xfb"], "\xfd" => [87, "\xfb"], "\xfe" => [130, "\xfb"], "\xff" => [9, "\xfb"]], ["\x00" => [77, "\xfa0"], "\x01" => [18, "\xfa0"], "\x02" => [77, "\xfa1"], "\x03" => [18, "\xfa1"], "\x04" => [77, "\xfa2"], "\x05" => [18, "\xfa2"], "\x06" => [77, "\xfaa"], "\x07" => [18, "\xfaa"], "\x08" => [77, "\xfac"], "\t" => [18, "\xfac"], "\n" => [77, "\xfae"], "\v" => [18, "\xfae"], "\f" => [77, "\xfai"], "\r" => [18, "\xfai"], "\x0e" => [77, "\xfao"], "\x0f" => [18, "\xfao"], "\x10" => [77, "\xfas"], "\x11" => [18, "\xfas"], "\x12" => [77, "\xfat"], "\x13" => [18, "\xfat"], "\x14" => [0, "\xfa "], "\x15" => [0, "\xfa%"], "\x16" => [0, "\xfa-"], "\x17" => [0, "\xfa."], "\x18" => [0, "\xfa/"], "\x19" => [0, "\xfa3"], "\x1a" => [0, "\xfa4"], "\x1b" => [0, "\xfa5"], "\x1c" => [0, "\xfa6"], "\x1d" => [0, "\xfa7"], "\x1e" => [0, "\xfa8"], "\x1f" => [0, "\xfa9"], " " => [0, "\xfa="], "!" => [0, "\xfaA"], "\"" => [0, "\xfa_"], "#" => [0, "\xfab"], "\$" => [0, "\xfad"], "%" => [0, "\xfaf"], "&" => [0, "\xfag"], "'" => [0, "\xfah"], "(" => [0, "\xfal"], ")" => [0, "\xfam"], "*" => [0, "\xfan"], "+" => [0, "\xfap"], "," => [0, "\xfar"], "-" => [0, "\xfau"], "." => [100, "\xfa"], "/" => [110, "\xfa"], [111, "\xfa"], [115, "\xfa"], [116, "\xfa"], [118, "\xfa"], [119, "\xfa"], [122, "\xfa"], [123, "\xfa"], [125, "\xfa"], [126, "\xfa"], [129, "\xfa"], ":" => [143, "\xfa"], ";" => [148, "\xfa"], "<" => [151, "\xfa"], "=" => [153, "\xfa"], ">" => [83, "\xfa"], "?" => [10, "\xfa"], "@" => [77, "\xfb0"], "A" => [18, "\xfb0"], "B" => [77, "\xfb1"], "C" => [18, "\xfb1"], "D" => [77, "\xfb2"], "E" => [18, "\xfb2"], "F" => [77, "\xfba"], "G" => [18, "\xfba"], "H" => [77, "\xfbc"], "I" => [18, "\xfbc"], "J" => [77, "\xfbe"], "K" => [18, "\xfbe"], "L" => [77, "\xfbi"], "M" => [18, "\xfbi"], "N" => [77, "\xfbo"], "O" => [18, "\xfbo"], "P" => [77, "\xfbs"], "Q" => [18, "\xfbs"], "R" => [77, "\xfbt"], "S" => [18, "\xfbt"], "T" => [0, "\xfb "], "U" => [0, "\xfb%"], "V" => [0, "\xfb-"], "W" => [0, "\xfb."], "X" => [0, "\xfb/"], "Y" => [0, "\xfb3"], "Z" => [0, "\xfb4"], "[" => [0, "\xfb5"], "\\" => [0, "\xfb6"], "]" => [0, "\xfb7"], "^" => [0, "\xfb8"], "_" => [0, "\xfb9"], "`" => [0, "\xfb="], "a" => [0, "\xfbA"], "b" => [0, "\xfb_"], "c" => [0, "\xfbb"], "d" => [0, "\xfbd"], "e" => [0, "\xfbf"], "f" => [0, "\xfbg"], "g" => [0, "\xfbh"], "h" => [0, "\xfbl"], "i" => [0, "\xfbm"], "j" => [0, "\xfbn"], "k" => [0, "\xfbp"], "l" => [0, "\xfbr"], "m" => [0, "\xfbu"], "n" => [100, "\xfb"], "o" => [110, "\xfb"], "p" => [111, "\xfb"], "q" => [115, "\xfb"], "r" => [116, "\xfb"], "s" => [118, "\xfb"], "t" => [119, "\xfb"], "u" => [122, "\xfb"], "v" => [123, "\xfb"], "w" => [125, "\xfb"], "x" => [126, "\xfb"], "y" => [129, "\xfb"], "z" => [143, "\xfb"], "{" => [148, "\xfb"], "|" => [151, "\xfb"], "}" => [153, "\xfb"], "~" => [83, "\xfb"], "" => [10, "\xfb"], "\x80" => [77, "\xfc0"], "\x81" => [18, "\xfc0"], "\x82" => [77, "\xfc1"], "\x83" => [18, "\xfc1"], "\x84" => [77, "\xfc2"], "\x85" => [18, "\xfc2"], "\x86" => [77, "\xfca"], "\x87" => [18, "\xfca"], "\x88" => [77, "\xfcc"], "\x89" => [18, "\xfcc"], "\x8a" => [77, "\xfce"], "\x8b" => [18, "\xfce"], "\x8c" => [77, "\xfci"], "\x8d" => [18, "\xfci"], "\x8e" => [77, "\xfco"], "\x8f" => [18, "\xfco"], "\x90" => [77, "\xfcs"], "\x91" => [18, "\xfcs"], "\x92" => [77, "\xfct"], "\x93" => [18, "\xfct"], "\x94" => [0, "\xfc "], "\x95" => [0, "\xfc%"], "\x96" => [0, "\xfc-"], "\x97" => [0, "\xfc."], "\x98" => [0, "\xfc/"], "\x99" => [0, "\xfc3"], "\x9a" => [0, "\xfc4"], "\x9b" => [0, "\xfc5"], "\x9c" => [0, "\xfc6"], "\x9d" => [0, "\xfc7"], "\x9e" => [0, "\xfc8"], "\x9f" => [0, "\xfc9"], "\xa0" => [0, "\xfc="], "\xa1" => [0, "\xfcA"], "\xa2" => [0, "\xfc_"], "\xa3" => [0, "\xfcb"], "\xa4" => [0, "\xfcd"], "\xa5" => [0, "\xfcf"], "\xa6" => [0, "\xfcg"], "\xa7" => [0, "\xfch"], "\xa8" => [0, "\xfcl"], "\xa9" => [0, "\xfcm"], "\xaa" => [0, "\xfcn"], "\xab" => [0, "\xfcp"], "\xac" => [0, "\xfcr"], "\xad" => [0, "\xfcu"], "\xae" => [100, "\xfc"], "\xaf" => [110, "\xfc"], "\xb0" => [111, "\xfc"], "\xb1" => [115, "\xfc"], "\xb2" => [116, "\xfc"], "\xb3" => [118, "\xfc"], "\xb4" => [119, "\xfc"], "\xb5" => [122, "\xfc"], "\xb6" => [123, "\xfc"], "\xb7" => [125, "\xfc"], "\xb8" => [126, "\xfc"], "\xb9" => [129, "\xfc"], "\xba" => [143, "\xfc"], "\xbb" => [148, "\xfc"], "\xbc" => [151, "\xfc"], "\xbd" => [153, "\xfc"], "\xbe" => [83, "\xfc"], "\xbf" => [10, "\xfc"], "\xc0" => [77, "\xfd0"], "\xc1" => [18, "\xfd0"], "\xc2" => [77, "\xfd1"], "\xc3" => [18, "\xfd1"], "\xc4" => [77, "\xfd2"], "\xc5" => [18, "\xfd2"], "\xc6" => [77, "\xfda"], "\xc7" => [18, "\xfda"], "\xc8" => [77, "\xfdc"], "\xc9" => [18, "\xfdc"], "\xca" => [77, "\xfde"], "\xcb" => [18, "\xfde"], "\xcc" => [77, "\xfdi"], "\xcd" => [18, "\xfdi"], "\xce" => [77, "\xfdo"], "\xcf" => [18, "\xfdo"], "\xd0" => [77, "\xfds"], "\xd1" => [18, "\xfds"], "\xd2" => [77, "\xfdt"], "\xd3" => [18, "\xfdt"], "\xd4" => [0, "\xfd "], "\xd5" => [0, "\xfd%"], "\xd6" => [0, "\xfd-"], "\xd7" => [0, "\xfd."], "\xd8" => [0, "\xfd/"], "\xd9" => [0, "\xfd3"], "\xda" => [0, "\xfd4"], "\xdb" => [0, "\xfd5"], "\xdc" => [0, "\xfd6"], "\xdd" => [0, "\xfd7"], "\xde" => [0, "\xfd8"], "\xdf" => [0, "\xfd9"], "\xe0" => [0, "\xfd="], "\xe1" => [0, "\xfdA"], "\xe2" => [0, "\xfd_"], "\xe3" => [0, "\xfdb"], "\xe4" => [0, "\xfdd"], "\xe5" => [0, "\xfdf"], "\xe6" => [0, "\xfdg"], "\xe7" => [0, "\xfdh"], "\xe8" => [0, "\xfdl"], "\xe9" => [0, "\xfdm"], "\xea" => [0, "\xfdn"], "\xeb" => [0, "\xfdp"], "\xec" => [0, "\xfdr"], "\xed" => [0, "\xfdu"], "\xee" => [100, "\xfd"], "\xef" => [110, "\xfd"], "\xf0" => [111, "\xfd"], "\xf1" => [115, "\xfd"], "\xf2" => [116, "\xfd"], "\xf3" => [118, "\xfd"], "\xf4" => [119, "\xfd"], "\xf5" => [122, "\xfd"], "\xf6" => [123, "\xfd"], "\xf7" => [125, "\xfd"], "\xf8" => [126, "\xfd"], "\xf9" => [129, "\xfd"], "\xfa" => [143, "\xfd"], "\xfb" => [148, "\xfd"], "\xfc" => [151, "\xfd"], "\xfd" => [153, "\xfd"], "\xfe" => [83, "\xfd"], "\xff" => [10, "\xfd"]], ["\x00" => [94, "\xfc0"], "\x01" => [76, "\xfc0"], "\x02" => [104, "\xfc0"], "\x03" => [16, "\xfc0"], "\x04" => [94, "\xfc1"], "\x05" => [76, "\xfc1"], "\x06" => [104, "\xfc1"], "\x07" => [16, "\xfc1"], "\x08" => [94, "\xfc2"], "\t" => [76, "\xfc2"], "\n" => [104, "\xfc2"], "\v" => [16, "\xfc2"], "\f" => [94, "\xfca"], "\r" => [76, "\xfca"], "\x0e" => [104, "\xfca"], "\x0f" => [16, "\xfca"], "\x10" => [94, "\xfcc"], "\x11" => [76, "\xfcc"], "\x12" => [104, "\xfcc"], "\x13" => [16, "\xfcc"], "\x14" => [94, "\xfce"], "\x15" => [76, "\xfce"], "\x16" => [104, "\xfce"], "\x17" => [16, "\xfce"], "\x18" => [94, "\xfci"], "\x19" => [76, "\xfci"], "\x1a" => [104, "\xfci"], "\x1b" => [16, "\xfci"], "\x1c" => [94, "\xfco"], "\x1d" => [76, "\xfco"], "\x1e" => [104, "\xfco"], "\x1f" => [16, "\xfco"], " " => [94, "\xfcs"], "!" => [76, "\xfcs"], "\"" => [104, "\xfcs"], "#" => [16, "\xfcs"], "\$" => [94, "\xfct"], "%" => [76, "\xfct"], "&" => [104, "\xfct"], "'" => [16, "\xfct"], "(" => [77, "\xfc "], ")" => [18, "\xfc "], "*" => [77, "\xfc%"], "+" => [18, "\xfc%"], "," => [77, "\xfc-"], "-" => [18, "\xfc-"], "." => [77, "\xfc."], "/" => [18, "\xfc."], [77, "\xfc/"], [18, "\xfc/"], [77, "\xfc3"], [18, "\xfc3"], [77, "\xfc4"], [18, "\xfc4"], [77, "\xfc5"], [18, "\xfc5"], [77, "\xfc6"], [18, "\xfc6"], ":" => [77, "\xfc7"], ";" => [18, "\xfc7"], "<" => [77, "\xfc8"], "=" => [18, "\xfc8"], ">" => [77, "\xfc9"], "?" => [18, "\xfc9"], "@" => [77, "\xfc="], "A" => [18, "\xfc="], "B" => [77, "\xfcA"], "C" => [18, "\xfcA"], "D" => [77, "\xfc_"], "E" => [18, "\xfc_"], "F" => [77, "\xfcb"], "G" => [18, "\xfcb"], "H" => [77, "\xfcd"], "I" => [18, "\xfcd"], "J" => [77, "\xfcf"], "K" => [18, "\xfcf"], "L" => [77, "\xfcg"], "M" => [18, "\xfcg"], "N" => [77, "\xfch"], "O" => [18, "\xfch"], "P" => [77, "\xfcl"], "Q" => [18, "\xfcl"], "R" => [77, "\xfcm"], "S" => [18, "\xfcm"], "T" => [77, "\xfcn"], "U" => [18, "\xfcn"], "V" => [77, "\xfcp"], "W" => [18, "\xfcp"], "X" => [77, "\xfcr"], "Y" => [18, "\xfcr"], "Z" => [77, "\xfcu"], "[" => [18, "\xfcu"], "\\" => [0, "\xfc:"], "]" => [0, "\xfcB"], "^" => [0, "\xfcC"], "_" => [0, "\xfcD"], "`" => [0, "\xfcE"], "a" => [0, "\xfcF"], "b" => [0, "\xfcG"], "c" => [0, "\xfcH"], "d" => [0, "\xfcI"], "e" => [0, "\xfcJ"], "f" => [0, "\xfcK"], "g" => [0, "\xfcL"], "h" => [0, "\xfcM"], "i" => [0, "\xfcN"], "j" => [0, "\xfcO"], "k" => [0, "\xfcP"], "l" => [0, "\xfcQ"], "m" => [0, "\xfcR"], "n" => [0, "\xfcS"], "o" => [0, "\xfcT"], "p" => [0, "\xfcU"], "q" => [0, "\xfcV"], "r" => [0, "\xfcW"], "s" => [0, "\xfcY"], "t" => [0, "\xfcj"], "u" => [0, "\xfck"], "v" => [0, "\xfcq"], "w" => [0, "\xfcv"], "x" => [0, "\xfcw"], "y" => [0, "\xfcx"], "z" => [0, "\xfcy"], "{" => [0, "\xfcz"], "|" => [82, "\xfc"], "}" => [87, "\xfc"], "~" => [130, "\xfc"], "" => [9, "\xfc"], "\x80" => [94, "\xfd0"], "\x81" => [76, "\xfd0"], "\x82" => [104, "\xfd0"], "\x83" => [16, "\xfd0"], "\x84" => [94, "\xfd1"], "\x85" => [76, "\xfd1"], "\x86" => [104, "\xfd1"], "\x87" => [16, "\xfd1"], "\x88" => [94, "\xfd2"], "\x89" => [76, "\xfd2"], "\x8a" => [104, "\xfd2"], "\x8b" => [16, "\xfd2"], "\x8c" => [94, "\xfda"], "\x8d" => [76, "\xfda"], "\x8e" => [104, "\xfda"], "\x8f" => [16, "\xfda"], "\x90" => [94, "\xfdc"], "\x91" => [76, "\xfdc"], "\x92" => [104, "\xfdc"], "\x93" => [16, "\xfdc"], "\x94" => [94, "\xfde"], "\x95" => [76, "\xfde"], "\x96" => [104, "\xfde"], "\x97" => [16, "\xfde"], "\x98" => [94, "\xfdi"], "\x99" => [76, "\xfdi"], "\x9a" => [104, "\xfdi"], "\x9b" => [16, "\xfdi"], "\x9c" => [94, "\xfdo"], "\x9d" => [76, "\xfdo"], "\x9e" => [104, "\xfdo"], "\x9f" => [16, "\xfdo"], "\xa0" => [94, "\xfds"], "\xa1" => [76, "\xfds"], "\xa2" => [104, "\xfds"], "\xa3" => [16, "\xfds"], "\xa4" => [94, "\xfdt"], "\xa5" => [76, "\xfdt"], "\xa6" => [104, "\xfdt"], "\xa7" => [16, "\xfdt"], "\xa8" => [77, "\xfd "], "\xa9" => [18, "\xfd "], "\xaa" => [77, "\xfd%"], "\xab" => [18, "\xfd%"], "\xac" => [77, "\xfd-"], "\xad" => [18, "\xfd-"], "\xae" => [77, "\xfd."], "\xaf" => [18, "\xfd."], "\xb0" => [77, "\xfd/"], "\xb1" => [18, "\xfd/"], "\xb2" => [77, "\xfd3"], "\xb3" => [18, "\xfd3"], "\xb4" => [77, "\xfd4"], "\xb5" => [18, "\xfd4"], "\xb6" => [77, "\xfd5"], "\xb7" => [18, "\xfd5"], "\xb8" => [77, "\xfd6"], "\xb9" => [18, "\xfd6"], "\xba" => [77, "\xfd7"], "\xbb" => [18, "\xfd7"], "\xbc" => [77, "\xfd8"], "\xbd" => [18, "\xfd8"], "\xbe" => [77, "\xfd9"], "\xbf" => [18, "\xfd9"], "\xc0" => [77, "\xfd="], "\xc1" => [18, "\xfd="], "\xc2" => [77, "\xfdA"], "\xc3" => [18, "\xfdA"], "\xc4" => [77, "\xfd_"], "\xc5" => [18, "\xfd_"], "\xc6" => [77, "\xfdb"], "\xc7" => [18, "\xfdb"], "\xc8" => [77, "\xfdd"], "\xc9" => [18, "\xfdd"], "\xca" => [77, "\xfdf"], "\xcb" => [18, "\xfdf"], "\xcc" => [77, "\xfdg"], "\xcd" => [18, "\xfdg"], "\xce" => [77, "\xfdh"], "\xcf" => [18, "\xfdh"], "\xd0" => [77, "\xfdl"], "\xd1" => [18, "\xfdl"], "\xd2" => [77, "\xfdm"], "\xd3" => [18, "\xfdm"], "\xd4" => [77, "\xfdn"], "\xd5" => [18, "\xfdn"], "\xd6" => [77, "\xfdp"], "\xd7" => [18, "\xfdp"], "\xd8" => [77, "\xfdr"], "\xd9" => [18, "\xfdr"], "\xda" => [77, "\xfdu"], "\xdb" => [18, "\xfdu"], "\xdc" => [0, "\xfd:"], "\xdd" => [0, "\xfdB"], "\xde" => [0, "\xfdC"], "\xdf" => [0, "\xfdD"], "\xe0" => [0, "\xfdE"], "\xe1" => [0, "\xfdF"], "\xe2" => [0, "\xfdG"], "\xe3" => [0, "\xfdH"], "\xe4" => [0, "\xfdI"], "\xe5" => [0, "\xfdJ"], "\xe6" => [0, "\xfdK"], "\xe7" => [0, "\xfdL"], "\xe8" => [0, "\xfdM"], "\xe9" => [0, "\xfdN"], "\xea" => [0, "\xfdO"], "\xeb" => [0, "\xfdP"], "\xec" => [0, "\xfdQ"], "\xed" => [0, "\xfdR"], "\xee" => [0, "\xfdS"], "\xef" => [0, "\xfdT"], "\xf0" => [0, "\xfdU"], "\xf1" => [0, "\xfdV"], "\xf2" => [0, "\xfdW"], "\xf3" => [0, "\xfdY"], "\xf4" => [0, "\xfdj"], "\xf5" => [0, "\xfdk"], "\xf6" => [0, "\xfdq"], "\xf7" => [0, "\xfdv"], "\xf8" => [0, "\xfdw"], "\xf9" => [0, "\xfdx"], "\xfa" => [0, "\xfdy"], "\xfb" => [0, "\xfdz"], "\xfc" => [82, "\xfd"], "\xfd" => [87, "\xfd"], "\xfe" => [130, "\xfd"], "\xff" => [9, "\xfd"]]];
#define FFI_SCOPE "amphp-hpack-nghttp2"
#define FFI_LIB "libnghttp2.so"

typedef struct nghttp2_hd_deflater nghttp2_hd_deflater;

typedef struct nghttp2_hd_inflater nghttp2_hd_inflater;

typedef struct {
  uint8_t *name;
  uint8_t *value;

  size_t namelen;
  size_t valuelen;

  uint8_t flags;
} nghttp2_nv;

int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max);

ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, size_t buflen, const nghttp2_nv *nva, size_t nvlen);

size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen);

int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);

ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, const uint8_t *in, size_t inlen, int in_final);

int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
<?php

return [["\x00" => ["\xff", "\xc0"], "\x01" => ["\xff", "\xff", "\xb0"], "\x02" => ["\xff", "\xff", "\xfe", " "], "\x03" => ["\xff", "\xff", "\xfe", "0"], "\x04" => ["\xff", "\xff", "\xfe", "@"], "\x05" => ["\xff", "\xff", "\xfe", "P"], "\x06" => ["\xff", "\xff", "\xfe", "`"], "\x07" => ["\xff", "\xff", "\xfe", "p"], "\x08" => ["\xff", "\xff", "\xfe", "\x80"], "\t" => ["\xff", "\xff", "\xea"], "\n" => ["\xff", "\xff", "\xff", "\xf0"], "\v" => ["\xff", "\xff", "\xfe", "\x90"], "\f" => ["\xff", "\xff", "\xfe", "\xa0"], "\r" => ["\xff", "\xff", "\xff", "\xf4"], "\x0e" => ["\xff", "\xff", "\xfe", "\xb0"], "\x0f" => ["\xff", "\xff", "\xfe", "\xc0"], "\x10" => ["\xff", "\xff", "\xfe", "\xd0"], "\x11" => ["\xff", "\xff", "\xfe", "\xe0"], "\x12" => ["\xff", "\xff", "\xfe", "\xf0"], "\x13" => ["\xff", "\xff", "\xff", "\x00"], "\x14" => ["\xff", "\xff", "\xff", "\x10"], "\x15" => ["\xff", "\xff", "\xff", " "], "\x16" => ["\xff", "\xff", "\xff", "\xf8"], "\x17" => ["\xff", "\xff", "\xff", "0"], "\x18" => ["\xff", "\xff", "\xff", "@"], "\x19" => ["\xff", "\xff", "\xff", "P"], "\x1a" => ["\xff", "\xff", "\xff", "`"], "\x1b" => ["\xff", "\xff", "\xff", "p"], "\x1c" => ["\xff", "\xff", "\xff", "\x80"], "\x1d" => ["\xff", "\xff", "\xff", "\x90"], "\x1e" => ["\xff", "\xff", "\xff", "\xa0"], "\x1f" => ["\xff", "\xff", "\xff", "\xb0"], " " => ["P"], "!" => ["\xfe", "\x00"], "\"" => ["\xfe", "@"], "#" => ["\xff", "\xa0"], "\$" => ["\xff", "\xc8"], "%" => ["T"], "&" => ["\xf8"], "'" => ["\xff", "@"], "(" => ["\xfe", "\x80"], ")" => ["\xfe", "\xc0"], "*" => ["\xf9"], "+" => ["\xff", "`"], "," => ["\xfa"], "-" => ["X"], "." => ["\\"], "/" => ["`"], ["\x00"], ["\x08"], ["\x10"], ["d"], ["h"], ["l"], ["p"], ["t"], ["x"], ["|"], ":" => ["\xb8"], ";" => ["\xfb"], "<" => ["\xff", "\xf8"], "=" => ["\x80"], ">" => ["\xff", "\xb0"], "?" => ["\xff", "\x00"], "@" => ["\xff", "\xd0"], "A" => ["\x84"], "B" => ["\xba"], "C" => ["\xbc"], "D" => ["\xbe"], "E" => ["\xc0"], "F" => ["\xc2"], "G" => ["\xc4"], "H" => ["\xc6"], "I" => ["\xc8"], "J" => ["\xca"], "K" => ["\xcc"], "L" => ["\xce"], "M" => ["\xd0"], "N" => ["\xd2"], "O" => ["\xd4"], "P" => ["\xd6"], "Q" => ["\xd8"], "R" => ["\xda"], "S" => ["\xdc"], "T" => ["\xde"], "U" => ["\xe0"], "V" => ["\xe2"], "W" => ["\xe4"], "X" => ["\xfc"], "Y" => ["\xe6"], "Z" => ["\xfd"], "[" => ["\xff", "\xd8"], "\\" => ["\xff", "\xfe", "\x00"], "]" => ["\xff", "\xe0"], "^" => ["\xff", "\xf0"], "_" => ["\x88"], "`" => ["\xff", "\xfa"], "a" => ["\x18"], "b" => ["\x8c"], "c" => [" "], "d" => ["\x90"], "e" => ["("], "f" => ["\x94"], "g" => ["\x98"], "h" => ["\x9c"], "i" => ["0"], "j" => ["\xe8"], "k" => ["\xea"], "l" => ["\xa0"], "m" => ["\xa4"], "n" => ["\xa8"], "o" => ["8"], "p" => ["\xac"], "q" => ["\xec"], "r" => ["\xb0"], "s" => ["@"], "t" => ["H"], "u" => ["\xb4"], "v" => ["\xee"], "w" => ["\xf0"], "x" => ["\xf2"], "y" => ["\xf4"], "z" => ["\xf6"], "{" => ["\xff", "\xfc"], "|" => ["\xff", "\x80"], "}" => ["\xff", "\xf4"], "~" => ["\xff", "\xe8"], "" => ["\xff", "\xff", "\xff", "\xc0"], "\x80" => ["\xff", "\xfe", "`"], "\x81" => ["\xff", "\xff", "H"], "\x82" => ["\xff", "\xfe", "p"], "\x83" => ["\xff", "\xfe", "\x80"], "\x84" => ["\xff", "\xff", "L"], "\x85" => ["\xff", "\xff", "P"], "\x86" => ["\xff", "\xff", "T"], "\x87" => ["\xff", "\xff", "\xb2"], "\x88" => ["\xff", "\xff", "X"], "\x89" => ["\xff", "\xff", "\xb4"], "\x8a" => ["\xff", "\xff", "\xb6"], "\x8b" => ["\xff", "\xff", "\xb8"], "\x8c" => ["\xff", "\xff", "\xba"], "\x8d" => ["\xff", "\xff", "\xbc"], "\x8e" => ["\xff", "\xff", "\xeb"], "\x8f" => ["\xff", "\xff", "\xbe"], "\x90" => ["\xff", "\xff", "\xec"], "\x91" => ["\xff", "\xff", "\xed"], "\x92" => ["\xff", "\xff", "\\"], "\x93" => ["\xff", "\xff", "\xc0"], "\x94" => ["\xff", "\xff", "\xee"], "\x95" => ["\xff", "\xff", "\xc2"], "\x96" => ["\xff", "\xff", "\xc4"], "\x97" => ["\xff", "\xff", "\xc6"], "\x98" => ["\xff", "\xff", "\xc8"], "\x99" => ["\xff", "\xfe", "\xe0"], "\x9a" => ["\xff", "\xff", "`"], "\x9b" => ["\xff", "\xff", "\xca"], "\x9c" => ["\xff", "\xff", "d"], "\x9d" => ["\xff", "\xff", "\xcc"], "\x9e" => ["\xff", "\xff", "\xce"], "\x9f" => ["\xff", "\xff", "\xef"], "\xa0" => ["\xff", "\xff", "h"], "\xa1" => ["\xff", "\xfe", "\xe8"], "\xa2" => ["\xff", "\xfe", "\x90"], "\xa3" => ["\xff", "\xff", "l"], "\xa4" => ["\xff", "\xff", "p"], "\xa5" => ["\xff", "\xff", "\xd0"], "\xa6" => ["\xff", "\xff", "\xd2"], "\xa7" => ["\xff", "\xfe", "\xf0"], "\xa8" => ["\xff", "\xff", "\xd4"], "\xa9" => ["\xff", "\xff", "t"], "\xaa" => ["\xff", "\xff", "x"], "\xab" => ["\xff", "\xff", "\xf0"], "\xac" => ["\xff", "\xfe", "\xf8"], "\xad" => ["\xff", "\xff", "|"], "\xae" => ["\xff", "\xff", "\xd6"], "\xaf" => ["\xff", "\xff", "\xd8"], "\xb0" => ["\xff", "\xff", "\x00"], "\xb1" => ["\xff", "\xff", "\x08"], "\xb2" => ["\xff", "\xff", "\x80"], "\xb3" => ["\xff", "\xff", "\x10"], "\xb4" => ["\xff", "\xff", "\xda"], "\xb5" => ["\xff", "\xff", "\x84"], "\xb6" => ["\xff", "\xff", "\xdc"], "\xb7" => ["\xff", "\xff", "\xde"], "\xb8" => ["\xff", "\xfe", "\xa0"], "\xb9" => ["\xff", "\xff", "\x88"], "\xba" => ["\xff", "\xff", "\x8c"], "\xbb" => ["\xff", "\xff", "\x90"], "\xbc" => ["\xff", "\xff", "\xe0"], "\xbd" => ["\xff", "\xff", "\x94"], "\xbe" => ["\xff", "\xff", "\x98"], "\xbf" => ["\xff", "\xff", "\xe2"], "\xc0" => ["\xff", "\xff", "\xf8", "\x00"], "\xc1" => ["\xff", "\xff", "\xf8", "@"], "\xc2" => ["\xff", "\xfe", "\xb0"], "\xc3" => ["\xff", "\xfe", " "], "\xc4" => ["\xff", "\xff", "\x9c"], "\xc5" => ["\xff", "\xff", "\xe4"], "\xc6" => ["\xff", "\xff", "\xa0"], "\xc7" => ["\xff", "\xff", "\xf6", "\x00"], "\xc8" => ["\xff", "\xff", "\xf8", "\x80"], "\xc9" => ["\xff", "\xff", "\xf8", "\xc0"], "\xca" => ["\xff", "\xff", "\xf9", "\x00"], "\xcb" => ["\xff", "\xff", "\xfb", "\xc0"], "\xcc" => ["\xff", "\xff", "\xfb", "\xe0"], "\xcd" => ["\xff", "\xff", "\xf9", "@"], "\xce" => ["\xff", "\xff", "\xf1"], "\xcf" => ["\xff", "\xff", "\xf6", "\x80"], "\xd0" => ["\xff", "\xfe", "@"], "\xd1" => ["\xff", "\xff", "\x18"], "\xd2" => ["\xff", "\xff", "\xf9", "\x80"], "\xd3" => ["\xff", "\xff", "\xfc", "\x00"], "\xd4" => ["\xff", "\xff", "\xfc", " "], "\xd5" => ["\xff", "\xff", "\xf9", "\xc0"], "\xd6" => ["\xff", "\xff", "\xfc", "@"], "\xd7" => ["\xff", "\xff", "\xf2"], "\xd8" => ["\xff", "\xff", " "], "\xd9" => ["\xff", "\xff", "("], "\xda" => ["\xff", "\xff", "\xfa", "\x00"], "\xdb" => ["\xff", "\xff", "\xfa", "@"], "\xdc" => ["\xff", "\xff", "\xff", "\xd0"], "\xdd" => ["\xff", "\xff", "\xfc", "`"], "\xde" => ["\xff", "\xff", "\xfc", "\x80"], "\xdf" => ["\xff", "\xff", "\xfc", "\xa0"], "\xe0" => ["\xff", "\xfe", "\xc0"], "\xe1" => ["\xff", "\xff", "\xf3"], "\xe2" => ["\xff", "\xfe", "\xd0"], "\xe3" => ["\xff", "\xff", "0"], "\xe4" => ["\xff", "\xff", "\xa4"], "\xe5" => ["\xff", "\xff", "8"], "\xe6" => ["\xff", "\xff", "@"], "\xe7" => ["\xff", "\xff", "\xe6"], "\xe8" => ["\xff", "\xff", "\xa8"], "\xe9" => ["\xff", "\xff", "\xac"], "\xea" => ["\xff", "\xff", "\xf7", "\x00"], "\xeb" => ["\xff", "\xff", "\xf7", "\x80"], "\xec" => ["\xff", "\xff", "\xf4"], "\xed" => ["\xff", "\xff", "\xf5"], "\xee" => ["\xff", "\xff", "\xfa", "\x80"], "\xef" => ["\xff", "\xff", "\xe8"], "\xf0" => ["\xff", "\xff", "\xfa", "\xc0"], "\xf1" => ["\xff", "\xff", "\xfc", "\xc0"], "\xf2" => ["\xff", "\xff", "\xfb", "\x00"], "\xf3" => ["\xff", "\xff", "\xfb", "@"], "\xf4" => ["\xff", "\xff", "\xfc", "\xe0"], "\xf5" => ["\xff", "\xff", "\xfd", "\x00"], "\xf6" => ["\xff", "\xff", "\xfd", " "], "\xf7" => ["\xff", "\xff", "\xfd", "@"], "\xf8" => ["\xff", "\xff", "\xfd", "`"], "\xf9" => ["\xff", "\xff", "\xff", "\xe0"], "\xfa" => ["\xff", "\xff", "\xfd", "\x80"], "\xfb" => ["\xff", "\xff", "\xfd", "\xa0"], "\xfc" => ["\xff", "\xff", "\xfd", "\xc0"], "\xfd" => ["\xff", "\xff", "\xfd", "\xe0"], "\xfe" => ["\xff", "\xff", "\xfe", "\x00"], "\xff" => ["\xff", "\xff", "\xfb", "\x80"]], ["\x00" => ["", "\xe0"], "\x01" => ["", "\xff", "\xd8"], "\x02" => ["", "\xff", "\xff", "\x10"], "\x03" => ["", "\xff", "\xff", "\x18"], "\x04" => ["", "\xff", "\xff", " "], "\x05" => ["", "\xff", "\xff", "("], "\x06" => ["", "\xff", "\xff", "0"], "\x07" => ["", "\xff", "\xff", "8"], "\x08" => ["", "\xff", "\xff", "@"], "\t" => ["", "\xff", "\xf5", "\x00"], "\n" => ["", "\xff", "\xff", "\xf8"], "\v" => ["", "\xff", "\xff", "H"], "\f" => ["", "\xff", "\xff", "P"], "\r" => ["", "\xff", "\xff", "\xfa"], "\x0e" => ["", "\xff", "\xff", "X"], "\x0f" => ["", "\xff", "\xff", "`"], "\x10" => ["", "\xff", "\xff", "h"], "\x11" => ["", "\xff", "\xff", "p"], "\x12" => ["", "\xff", "\xff", "x"], "\x13" => ["", "\xff", "\xff", "\x80"], "\x14" => ["", "\xff", "\xff", "\x88"], "\x15" => ["", "\xff", "\xff", "\x90"], "\x16" => ["", "\xff", "\xff", "\xfc"], "\x17" => ["", "\xff", "\xff", "\x98"], "\x18" => ["", "\xff", "\xff", "\xa0"], "\x19" => ["", "\xff", "\xff", "\xa8"], "\x1a" => ["", "\xff", "\xff", "\xb0"], "\x1b" => ["", "\xff", "\xff", "\xb8"], "\x1c" => ["", "\xff", "\xff", "\xc0"], "\x1d" => ["", "\xff", "\xff", "\xc8"], "\x1e" => ["", "\xff", "\xff", "\xd0"], "\x1f" => ["", "\xff", "\xff", "\xd8"], " " => ["("], "!" => ["", "\x00"], "\"" => ["", " "], "#" => ["", "\xd0"], "\$" => ["", "\xe4"], "%" => ["*"], "&" => ["|", "\x00"], "'" => ["", "\xa0"], "(" => ["", "@"], ")" => ["", "`"], "*" => ["|", "\x80"], "+" => ["", "\xb0"], "," => ["}", "\x00"], "-" => [","], "." => ["."], "/" => ["0"], ["\x00"], ["\x04"], ["\x08"], ["2"], ["4"], ["6"], ["8"], [":"], ["<"], [">"], ":" => ["\\"], ";" => ["}", "\x80"], "<" => ["", "\xfc"], "=" => ["@"], ">" => ["", "\xd8"], "?" => ["", "\x80"], "@" => ["", "\xe8"], "A" => ["B"], "B" => ["]"], "C" => ["^"], "D" => ["_"], "E" => ["`"], "F" => ["a"], "G" => ["b"], "H" => ["c"], "I" => ["d"], "J" => ["e"], "K" => ["f"], "L" => ["g"], "M" => ["h"], "N" => ["i"], "O" => ["j"], "P" => ["k"], "Q" => ["l"], "R" => ["m"], "S" => ["n"], "T" => ["o"], "U" => ["p"], "V" => ["q"], "W" => ["r"], "X" => ["~", "\x00"], "Y" => ["s"], "Z" => ["~", "\x80"], "[" => ["", "\xec"], "\\" => ["", "\xff", "\x00"], "]" => ["", "\xf0"], "^" => ["", "\xf8"], "_" => ["D"], "`" => ["", "\xfd"], "a" => ["\f"], "b" => ["F"], "c" => ["\x10"], "d" => ["H"], "e" => ["\x14"], "f" => ["J"], "g" => ["L"], "h" => ["N"], "i" => ["\x18"], "j" => ["t"], "k" => ["u"], "l" => ["P"], "m" => ["R"], "n" => ["T"], "o" => ["\x1c"], "p" => ["V"], "q" => ["v"], "r" => ["X"], "s" => [" "], "t" => ["\$"], "u" => ["Z"], "v" => ["w"], "w" => ["x"], "x" => ["y"], "y" => ["z"], "z" => ["{"], "{" => ["", "\xfe"], "|" => ["", "\xc0"], "}" => ["", "\xfa"], "~" => ["", "\xf4"], "" => ["", "\xff", "\xff", "\xe0"], "\x80" => ["", "\xff", "0"], "\x81" => ["", "\xff", "\xa4"], "\x82" => ["", "\xff", "8"], "\x83" => ["", "\xff", "@"], "\x84" => ["", "\xff", "\xa6"], "\x85" => ["", "\xff", "\xa8"], "\x86" => ["", "\xff", "\xaa"], "\x87" => ["", "\xff", "\xd9"], "\x88" => ["", "\xff", "\xac"], "\x89" => ["", "\xff", "\xda"], "\x8a" => ["", "\xff", "\xdb"], "\x8b" => ["", "\xff", "\xdc"], "\x8c" => ["", "\xff", "\xdd"], "\x8d" => ["", "\xff", "\xde"], "\x8e" => ["", "\xff", "\xf5", "\x80"], "\x8f" => ["", "\xff", "\xdf"], "\x90" => ["", "\xff", "\xf6", "\x00"], "\x91" => ["", "\xff", "\xf6", "\x80"], "\x92" => ["", "\xff", "\xae"], "\x93" => ["", "\xff", "\xe0"], "\x94" => ["", "\xff", "\xf7", "\x00"], "\x95" => ["", "\xff", "\xe1"], "\x96" => ["", "\xff", "\xe2"], "\x97" => ["", "\xff", "\xe3"], "\x98" => ["", "\xff", "\xe4"], "\x99" => ["", "\xff", "p"], "\x9a" => ["", "\xff", "\xb0"], "\x9b" => ["", "\xff", "\xe5"], "\x9c" => ["", "\xff", "\xb2"], "\x9d" => ["", "\xff", "\xe6"], "\x9e" => ["", "\xff", "\xe7"], "\x9f" => ["", "\xff", "\xf7", "\x80"], "\xa0" => ["", "\xff", "\xb4"], "\xa1" => ["", "\xff", "t"], "\xa2" => ["", "\xff", "H"], "\xa3" => ["", "\xff", "\xb6"], "\xa4" => ["", "\xff", "\xb8"], "\xa5" => ["", "\xff", "\xe8"], "\xa6" => ["", "\xff", "\xe9"], "\xa7" => ["", "\xff", "x"], "\xa8" => ["", "\xff", "\xea"], "\xa9" => ["", "\xff", "\xba"], "\xaa" => ["", "\xff", "\xbc"], "\xab" => ["", "\xff", "\xf8", "\x00"], "\xac" => ["", "\xff", "|"], "\xad" => ["", "\xff", "\xbe"], "\xae" => ["", "\xff", "\xeb"], "\xaf" => ["", "\xff", "\xec"], "\xb0" => ["", "\xff", "\x80"], "\xb1" => ["", "\xff", "\x84"], "\xb2" => ["", "\xff", "\xc0"], "\xb3" => ["", "\xff", "\x88"], "\xb4" => ["", "\xff", "\xed"], "\xb5" => ["", "\xff", "\xc2"], "\xb6" => ["", "\xff", "\xee"], "\xb7" => ["", "\xff", "\xef"], "\xb8" => ["", "\xff", "P"], "\xb9" => ["", "\xff", "\xc4"], "\xba" => ["", "\xff", "\xc6"], "\xbb" => ["", "\xff", "\xc8"], "\xbc" => ["", "\xff", "\xf0"], "\xbd" => ["", "\xff", "\xca"], "\xbe" => ["", "\xff", "\xcc"], "\xbf" => ["", "\xff", "\xf1"], "\xc0" => ["", "\xff", "\xfc", "\x00"], "\xc1" => ["", "\xff", "\xfc", " "], "\xc2" => ["", "\xff", "X"], "\xc3" => ["", "\xff", "\x10"], "\xc4" => ["", "\xff", "\xce"], "\xc5" => ["", "\xff", "\xf2"], "\xc6" => ["", "\xff", "\xd0"], "\xc7" => ["", "\xff", "\xfb", "\x00"], "\xc8" => ["", "\xff", "\xfc", "@"], "\xc9" => ["", "\xff", "\xfc", "`"], "\xca" => ["", "\xff", "\xfc", "\x80"], "\xcb" => ["", "\xff", "\xfd", "\xe0"], "\xcc" => ["", "\xff", "\xfd", "\xf0"], "\xcd" => ["", "\xff", "\xfc", "\xa0"], "\xce" => ["", "\xff", "\xf8", "\x80"], "\xcf" => ["", "\xff", "\xfb", "@"], "\xd0" => ["", "\xff", " "], "\xd1" => ["", "\xff", "\x8c"], "\xd2" => ["", "\xff", "\xfc", "\xc0"], "\xd3" => ["", "\xff", "\xfe", "\x00"], "\xd4" => ["", "\xff", "\xfe", "\x10"], "\xd5" => ["", "\xff", "\xfc", "\xe0"], "\xd6" => ["", "\xff", "\xfe", " "], "\xd7" => ["", "\xff", "\xf9", "\x00"], "\xd8" => ["", "\xff", "\x90"], "\xd9" => ["", "\xff", "\x94"], "\xda" => ["", "\xff", "\xfd", "\x00"], "\xdb" => ["", "\xff", "\xfd", " "], "\xdc" => ["", "\xff", "\xff", "\xe8"], "\xdd" => ["", "\xff", "\xfe", "0"], "\xde" => ["", "\xff", "\xfe", "@"], "\xdf" => ["", "\xff", "\xfe", "P"], "\xe0" => ["", "\xff", "`"], "\xe1" => ["", "\xff", "\xf9", "\x80"], "\xe2" => ["", "\xff", "h"], "\xe3" => ["", "\xff", "\x98"], "\xe4" => ["", "\xff", "\xd2"], "\xe5" => ["", "\xff", "\x9c"], "\xe6" => ["", "\xff", "\xa0"], "\xe7" => ["", "\xff", "\xf3"], "\xe8" => ["", "\xff", "\xd4"], "\xe9" => ["", "\xff", "\xd6"], "\xea" => ["", "\xff", "\xfb", "\x80"], "\xeb" => ["", "\xff", "\xfb", "\xc0"], "\xec" => ["", "\xff", "\xfa", "\x00"], "\xed" => ["", "\xff", "\xfa", "\x80"], "\xee" => ["", "\xff", "\xfd", "@"], "\xef" => ["", "\xff", "\xf4"], "\xf0" => ["", "\xff", "\xfd", "`"], "\xf1" => ["", "\xff", "\xfe", "`"], "\xf2" => ["", "\xff", "\xfd", "\x80"], "\xf3" => ["", "\xff", "\xfd", "\xa0"], "\xf4" => ["", "\xff", "\xfe", "p"], "\xf5" => ["", "\xff", "\xfe", "\x80"], "\xf6" => ["", "\xff", "\xfe", "\x90"], "\xf7" => ["", "\xff", "\xfe", "\xa0"], "\xf8" => ["", "\xff", "\xfe", "\xb0"], "\xf9" => ["", "\xff", "\xff", "\xf0"], "\xfa" => ["", "\xff", "\xfe", "\xc0"], "\xfb" => ["", "\xff", "\xfe", "\xd0"], "\xfc" => ["", "\xff", "\xfe", "\xe0"], "\xfd" => ["", "\xff", "\xfe", "\xf0"], "\xfe" => ["", "\xff", "\xff", "\x00"], "\xff" => ["", "\xff", "\xfd", "\xc0"]], ["\x00" => ["?", "\xf0"], "\x01" => ["?", "\xff", "\xec", "\x00"], "\x02" => ["?", "\xff", "\xff", "\x88"], "\x03" => ["?", "\xff", "\xff", "\x8c"], "\x04" => ["?", "\xff", "\xff", "\x90"], "\x05" => ["?", "\xff", "\xff", "\x94"], "\x06" => ["?", "\xff", "\xff", "\x98"], "\x07" => ["?", "\xff", "\xff", "\x9c"], "\x08" => ["?", "\xff", "\xff", "\xa0"], "\t" => ["?", "\xff", "\xfa", "\x80"], "\n" => ["?", "\xff", "\xff", "\xfc"], "\v" => ["?", "\xff", "\xff", "\xa4"], "\f" => ["?", "\xff", "\xff", "\xa8"], "\r" => ["?", "\xff", "\xff", "\xfd"], "\x0e" => ["?", "\xff", "\xff", "\xac"], "\x0f" => ["?", "\xff", "\xff", "\xb0"], "\x10" => ["?", "\xff", "\xff", "\xb4"], "\x11" => ["?", "\xff", "\xff", "\xb8"], "\x12" => ["?", "\xff", "\xff", "\xbc"], "\x13" => ["?", "\xff", "\xff", "\xc0"], "\x14" => ["?", "\xff", "\xff", "\xc4"], "\x15" => ["?", "\xff", "\xff", "\xc8"], "\x16" => ["?", "\xff", "\xff", "\xfe"], "\x17" => ["?", "\xff", "\xff", "\xcc"], "\x18" => ["?", "\xff", "\xff", "\xd0"], "\x19" => ["?", "\xff", "\xff", "\xd4"], "\x1a" => ["?", "\xff", "\xff", "\xd8"], "\x1b" => ["?", "\xff", "\xff", "\xdc"], "\x1c" => ["?", "\xff", "\xff", "\xe0"], "\x1d" => ["?", "\xff", "\xff", "\xe4"], "\x1e" => ["?", "\xff", "\xff", "\xe8"], "\x1f" => ["?", "\xff", "\xff", "\xec"], " " => ["\x14"], "!" => ["?", "\x80"], "\"" => ["?", "\x90"], "#" => ["?", "\xe8"], "\$" => ["?", "\xf2"], "%" => ["\x15"], "&" => [">", "\x00"], "'" => ["?", "\xd0"], "(" => ["?", "\xa0"], ")" => ["?", "\xb0"], "*" => [">", "@"], "+" => ["?", "\xd8"], "," => [">", "\x80"], "-" => ["\x16"], "." => ["\x17"], "/" => ["\x18"], ["\x00"], ["\x02"], ["\x04"], ["\x19"], ["\x1a"], ["\x1b"], ["\x1c"], ["\x1d"], ["\x1e"], ["\x1f"], ":" => [".", "\x00"], ";" => [">", "\xc0"], "<" => ["?", "\xfe", "\x00"], "=" => [" "], ">" => ["?", "\xec"], "?" => ["?", "\xc0"], "@" => ["?", "\xf4"], "A" => ["!"], "B" => [".", "\x80"], "C" => ["/", "\x00"], "D" => ["/", "\x80"], "E" => ["0", "\x00"], "F" => ["0", "\x80"], "G" => ["1", "\x00"], "H" => ["1", "\x80"], "I" => ["2", "\x00"], "J" => ["2", "\x80"], "K" => ["3", "\x00"], "L" => ["3", "\x80"], "M" => ["4", "\x00"], "N" => ["4", "\x80"], "O" => ["5", "\x00"], "P" => ["5", "\x80"], "Q" => ["6", "\x00"], "R" => ["6", "\x80"], "S" => ["7", "\x00"], "T" => ["7", "\x80"], "U" => ["8", "\x00"], "V" => ["8", "\x80"], "W" => ["9", "\x00"], "X" => ["?", "\x00"], "Y" => ["9", "\x80"], "Z" => ["?", "@"], "[" => ["?", "\xf6"], "\\" => ["?", "\xff", "\x80"], "]" => ["?", "\xf8"], "^" => ["?", "\xfc"], "_" => ["\""], "`" => ["?", "\xfe", "\x80"], "a" => ["\x06"], "b" => ["#"], "c" => ["\x08"], "d" => ["\$"], "e" => ["\n"], "f" => ["%"], "g" => ["&"], "h" => ["'"], "i" => ["\f"], "j" => [":", "\x00"], "k" => [":", "\x80"], "l" => ["("], "m" => [")"], "n" => ["*"], "o" => ["\x0e"], "p" => ["+"], "q" => [";", "\x00"], "r" => [","], "s" => ["\x10"], "t" => ["\x12"], "u" => ["-"], "v" => [";", "\x80"], "w" => ["<", "\x00"], "x" => ["<", "\x80"], "y" => ["=", "\x00"], "z" => ["=", "\x80"], "{" => ["?", "\xff", "\x00"], "|" => ["?", "\xe0"], "}" => ["?", "\xfd"], "~" => ["?", "\xfa"], "" => ["?", "\xff", "\xff", "\xf0"], "\x80" => ["?", "\xff", "\x98"], "\x81" => ["?", "\xff", "\xd2"], "\x82" => ["?", "\xff", "\x9c"], "\x83" => ["?", "\xff", "\xa0"], "\x84" => ["?", "\xff", "\xd3"], "\x85" => ["?", "\xff", "\xd4"], "\x86" => ["?", "\xff", "\xd5"], "\x87" => ["?", "\xff", "\xec", "\x80"], "\x88" => ["?", "\xff", "\xd6"], "\x89" => ["?", "\xff", "\xed", "\x00"], "\x8a" => ["?", "\xff", "\xed", "\x80"], "\x8b" => ["?", "\xff", "\xee", "\x00"], "\x8c" => ["?", "\xff", "\xee", "\x80"], "\x8d" => ["?", "\xff", "\xef", "\x00"], "\x8e" => ["?", "\xff", "\xfa", "\xc0"], "\x8f" => ["?", "\xff", "\xef", "\x80"], "\x90" => ["?", "\xff", "\xfb", "\x00"], "\x91" => ["?", "\xff", "\xfb", "@"], "\x92" => ["?", "\xff", "\xd7"], "\x93" => ["?", "\xff", "\xf0", "\x00"], "\x94" => ["?", "\xff", "\xfb", "\x80"], "\x95" => ["?", "\xff", "\xf0", "\x80"], "\x96" => ["?", "\xff", "\xf1", "\x00"], "\x97" => ["?", "\xff", "\xf1", "\x80"], "\x98" => ["?", "\xff", "\xf2", "\x00"], "\x99" => ["?", "\xff", "\xb8"], "\x9a" => ["?", "\xff", "\xd8"], "\x9b" => ["?", "\xff", "\xf2", "\x80"], "\x9c" => ["?", "\xff", "\xd9"], "\x9d" => ["?", "\xff", "\xf3", "\x00"], "\x9e" => ["?", "\xff", "\xf3", "\x80"], "\x9f" => ["?", "\xff", "\xfb", "\xc0"], "\xa0" => ["?", "\xff", "\xda"], "\xa1" => ["?", "\xff", "\xba"], "\xa2" => ["?", "\xff", "\xa4"], "\xa3" => ["?", "\xff", "\xdb"], "\xa4" => ["?", "\xff", "\xdc"], "\xa5" => ["?", "\xff", "\xf4", "\x00"], "\xa6" => ["?", "\xff", "\xf4", "\x80"], "\xa7" => ["?", "\xff", "\xbc"], "\xa8" => ["?", "\xff", "\xf5", "\x00"], "\xa9" => ["?", "\xff", "\xdd"], "\xaa" => ["?", "\xff", "\xde"], "\xab" => ["?", "\xff", "\xfc", "\x00"], "\xac" => ["?", "\xff", "\xbe"], "\xad" => ["?", "\xff", "\xdf"], "\xae" => ["?", "\xff", "\xf5", "\x80"], "\xaf" => ["?", "\xff", "\xf6", "\x00"], "\xb0" => ["?", "\xff", "\xc0"], "\xb1" => ["?", "\xff", "\xc2"], "\xb2" => ["?", "\xff", "\xe0"], "\xb3" => ["?", "\xff", "\xc4"], "\xb4" => ["?", "\xff", "\xf6", "\x80"], "\xb5" => ["?", "\xff", "\xe1"], "\xb6" => ["?", "\xff", "\xf7", "\x00"], "\xb7" => ["?", "\xff", "\xf7", "\x80"], "\xb8" => ["?", "\xff", "\xa8"], "\xb9" => ["?", "\xff", "\xe2"], "\xba" => ["?", "\xff", "\xe3"], "\xbb" => ["?", "\xff", "\xe4"], "\xbc" => ["?", "\xff", "\xf8", "\x00"], "\xbd" => ["?", "\xff", "\xe5"], "\xbe" => ["?", "\xff", "\xe6"], "\xbf" => ["?", "\xff", "\xf8", "\x80"], "\xc0" => ["?", "\xff", "\xfe", "\x00"], "\xc1" => ["?", "\xff", "\xfe", "\x10"], "\xc2" => ["?", "\xff", "\xac"], "\xc3" => ["?", "\xff", "\x88"], "\xc4" => ["?", "\xff", "\xe7"], "\xc5" => ["?", "\xff", "\xf9", "\x00"], "\xc6" => ["?", "\xff", "\xe8"], "\xc7" => ["?", "\xff", "\xfd", "\x80"], "\xc8" => ["?", "\xff", "\xfe", " "], "\xc9" => ["?", "\xff", "\xfe", "0"], "\xca" => ["?", "\xff", "\xfe", "@"], "\xcb" => ["?", "\xff", "\xfe", "\xf0"], "\xcc" => ["?", "\xff", "\xfe", "\xf8"], "\xcd" => ["?", "\xff", "\xfe", "P"], "\xce" => ["?", "\xff", "\xfc", "@"], "\xcf" => ["?", "\xff", "\xfd", "\xa0"], "\xd0" => ["?", "\xff", "\x90"], "\xd1" => ["?", "\xff", "\xc6"], "\xd2" => ["?", "\xff", "\xfe", "`"], "\xd3" => ["?", "\xff", "\xff", "\x00"], "\xd4" => ["?", "\xff", "\xff", "\x08"], "\xd5" => ["?", "\xff", "\xfe", "p"], "\xd6" => ["?", "\xff", "\xff", "\x10"], "\xd7" => ["?", "\xff", "\xfc", "\x80"], "\xd8" => ["?", "\xff", "\xc8"], "\xd9" => ["?", "\xff", "\xca"], "\xda" => ["?", "\xff", "\xfe", "\x80"], "\xdb" => ["?", "\xff", "\xfe", "\x90"], "\xdc" => ["?", "\xff", "\xff", "\xf4"], "\xdd" => ["?", "\xff", "\xff", "\x18"], "\xde" => ["?", "\xff", "\xff", " "], "\xdf" => ["?", "\xff", "\xff", "("], "\xe0" => ["?", "\xff", "\xb0"], "\xe1" => ["?", "\xff", "\xfc", "\xc0"], "\xe2" => ["?", "\xff", "\xb4"], "\xe3" => ["?", "\xff", "\xcc"], "\xe4" => ["?", "\xff", "\xe9"], "\xe5" => ["?", "\xff", "\xce"], "\xe6" => ["?", "\xff", "\xd0"], "\xe7" => ["?", "\xff", "\xf9", "\x80"], "\xe8" => ["?", "\xff", "\xea"], "\xe9" => ["?", "\xff", "\xeb"], "\xea" => ["?", "\xff", "\xfd", "\xc0"], "\xeb" => ["?", "\xff", "\xfd", "\xe0"], "\xec" => ["?", "\xff", "\xfd", "\x00"], "\xed" => ["?", "\xff", "\xfd", "@"], "\xee" => ["?", "\xff", "\xfe", "\xa0"], "\xef" => ["?", "\xff", "\xfa", "\x00"], "\xf0" => ["?", "\xff", "\xfe", "\xb0"], "\xf1" => ["?", "\xff", "\xff", "0"], "\xf2" => ["?", "\xff", "\xfe", "\xc0"], "\xf3" => ["?", "\xff", "\xfe", "\xd0"], "\xf4" => ["?", "\xff", "\xff", "8"], "\xf5" => ["?", "\xff", "\xff", "@"], "\xf6" => ["?", "\xff", "\xff", "H"], "\xf7" => ["?", "\xff", "\xff", "P"], "\xf8" => ["?", "\xff", "\xff", "X"], "\xf9" => ["?", "\xff", "\xff", "\xf8"], "\xfa" => ["?", "\xff", "\xff", "`"], "\xfb" => ["?", "\xff", "\xff", "h"], "\xfc" => ["?", "\xff", "\xff", "p"], "\xfd" => ["?", "\xff", "\xff", "x"], "\xfe" => ["?", "\xff", "\xff", "\x80"], "\xff" => ["?", "\xff", "\xfe", "\xe0"]], ["\x00" => ["\x1f", "\xf8"], "\x01" => ["\x1f", "\xff", "\xf6", "\x00"], "\x02" => ["\x1f", "\xff", "\xff", "\xc4"], "\x03" => ["\x1f", "\xff", "\xff", "\xc6"], "\x04" => ["\x1f", "\xff", "\xff", "\xc8"], "\x05" => ["\x1f", "\xff", "\xff", "\xca"], "\x06" => ["\x1f", "\xff", "\xff", "\xcc"], "\x07" => ["\x1f", "\xff", "\xff", "\xce"], "\x08" => ["\x1f", "\xff", "\xff", "\xd0"], "\t" => ["\x1f", "\xff", "\xfd", "@"], "\n" => ["\x1f", "\xff", "\xff", "\xfe", "\x00"], "\v" => ["\x1f", "\xff", "\xff", "\xd2"], "\f" => ["\x1f", "\xff", "\xff", "\xd4"], "\r" => ["\x1f", "\xff", "\xff", "\xfe", "\x80"], "\x0e" => ["\x1f", "\xff", "\xff", "\xd6"], "\x0f" => ["\x1f", "\xff", "\xff", "\xd8"], "\x10" => ["\x1f", "\xff", "\xff", "\xda"], "\x11" => ["\x1f", "\xff", "\xff", "\xdc"], "\x12" => ["\x1f", "\xff", "\xff", "\xde"], "\x13" => ["\x1f", "\xff", "\xff", "\xe0"], "\x14" => ["\x1f", "\xff", "\xff", "\xe2"], "\x15" => ["\x1f", "\xff", "\xff", "\xe4"], "\x16" => ["\x1f", "\xff", "\xff", "\xff", "\x00"], "\x17" => ["\x1f", "\xff", "\xff", "\xe6"], "\x18" => ["\x1f", "\xff", "\xff", "\xe8"], "\x19" => ["\x1f", "\xff", "\xff", "\xea"], "\x1a" => ["\x1f", "\xff", "\xff", "\xec"], "\x1b" => ["\x1f", "\xff", "\xff", "\xee"], "\x1c" => ["\x1f", "\xff", "\xff", "\xf0"], "\x1d" => ["\x1f", "\xff", "\xff", "\xf2"], "\x1e" => ["\x1f", "\xff", "\xff", "\xf4"], "\x1f" => ["\x1f", "\xff", "\xff", "\xf6"], " " => ["\n", "\x00"], "!" => ["\x1f", "\xc0"], "\"" => ["\x1f", "\xc8"], "#" => ["\x1f", "\xf4"], "\$" => ["\x1f", "\xf9"], "%" => ["\n", "\x80"], "&" => ["\x1f", "\x00"], "'" => ["\x1f", "\xe8"], "(" => ["\x1f", "\xd0"], ")" => ["\x1f", "\xd8"], "*" => ["\x1f", " "], "+" => ["\x1f", "\xec"], "," => ["\x1f", "@"], "-" => ["\v", "\x00"], "." => ["\v", "\x80"], "/" => ["\f", "\x00"], ["\x00"], ["\x01"], ["\x02"], ["\f", "\x80"], ["\r", "\x00"], ["\r", "\x80"], ["\x0e", "\x00"], ["\x0e", "\x80"], ["\x0f", "\x00"], ["\x0f", "\x80"], ":" => ["\x17", "\x00"], ";" => ["\x1f", "`"], "<" => ["\x1f", "\xff", "\x00"], "=" => ["\x10", "\x00"], ">" => ["\x1f", "\xf6"], "?" => ["\x1f", "\xe0"], "@" => ["\x1f", "\xfa"], "A" => ["\x10", "\x80"], "B" => ["\x17", "@"], "C" => ["\x17", "\x80"], "D" => ["\x17", "\xc0"], "E" => ["\x18", "\x00"], "F" => ["\x18", "@"], "G" => ["\x18", "\x80"], "H" => ["\x18", "\xc0"], "I" => ["\x19", "\x00"], "J" => ["\x19", "@"], "K" => ["\x19", "\x80"], "L" => ["\x19", "\xc0"], "M" => ["\x1a", "\x00"], "N" => ["\x1a", "@"], "O" => ["\x1a", "\x80"], "P" => ["\x1a", "\xc0"], "Q" => ["\x1b", "\x00"], "R" => ["\x1b", "@"], "S" => ["\x1b", "\x80"], "T" => ["\x1b", "\xc0"], "U" => ["\x1c", "\x00"], "V" => ["\x1c", "@"], "W" => ["\x1c", "\x80"], "X" => ["\x1f", "\x80"], "Y" => ["\x1c", "\xc0"], "Z" => ["\x1f", "\xa0"], "[" => ["\x1f", "\xfb"], "\\" => ["\x1f", "\xff", "\xc0"], "]" => ["\x1f", "\xfc"], "^" => ["\x1f", "\xfe", "\x00"], "_" => ["\x11", "\x00"], "`" => ["\x1f", "\xff", "@"], "a" => ["\x03"], "b" => ["\x11", "\x80"], "c" => ["\x04"], "d" => ["\x12", "\x00"], "e" => ["\x05"], "f" => ["\x12", "\x80"], "g" => ["\x13", "\x00"], "h" => ["\x13", "\x80"], "i" => ["\x06"], "j" => ["\x1d", "\x00"], "k" => ["\x1d", "@"], "l" => ["\x14", "\x00"], "m" => ["\x14", "\x80"], "n" => ["\x15", "\x00"], "o" => ["\x07"], "p" => ["\x15", "\x80"], "q" => ["\x1d", "\x80"], "r" => ["\x16", "\x00"], "s" => ["\x08"], "t" => ["\t"], "u" => ["\x16", "\x80"], "v" => ["\x1d", "\xc0"], "w" => ["\x1e", "\x00"], "x" => ["\x1e", "@"], "y" => ["\x1e", "\x80"], "z" => ["\x1e", "\xc0"], "{" => ["\x1f", "\xff", "\x80"], "|" => ["\x1f", "\xf0"], "}" => ["\x1f", "\xfe", "\x80"], "~" => ["\x1f", "\xfd"], "" => ["\x1f", "\xff", "\xff", "\xf8"], "\x80" => ["\x1f", "\xff", "\xcc"], "\x81" => ["\x1f", "\xff", "\xe9", "\x00"], "\x82" => ["\x1f", "\xff", "\xce"], "\x83" => ["\x1f", "\xff", "\xd0"], "\x84" => ["\x1f", "\xff", "\xe9", "\x80"], "\x85" => ["\x1f", "\xff", "\xea", "\x00"], "\x86" => ["\x1f", "\xff", "\xea", "\x80"], "\x87" => ["\x1f", "\xff", "\xf6", "@"], "\x88" => ["\x1f", "\xff", "\xeb", "\x00"], "\x89" => ["\x1f", "\xff", "\xf6", "\x80"], "\x8a" => ["\x1f", "\xff", "\xf6", "\xc0"], "\x8b" => ["\x1f", "\xff", "\xf7", "\x00"], "\x8c" => ["\x1f", "\xff", "\xf7", "@"], "\x8d" => ["\x1f", "\xff", "\xf7", "\x80"], "\x8e" => ["\x1f", "\xff", "\xfd", "`"], "\x8f" => ["\x1f", "\xff", "\xf7", "\xc0"], "\x90" => ["\x1f", "\xff", "\xfd", "\x80"], "\x91" => ["\x1f", "\xff", "\xfd", "\xa0"], "\x92" => ["\x1f", "\xff", "\xeb", "\x80"], "\x93" => ["\x1f", "\xff", "\xf8", "\x00"], "\x94" => ["\x1f", "\xff", "\xfd", "\xc0"], "\x95" => ["\x1f", "\xff", "\xf8", "@"], "\x96" => ["\x1f", "\xff", "\xf8", "\x80"], "\x97" => ["\x1f", "\xff", "\xf8", "\xc0"], "\x98" => ["\x1f", "\xff", "\xf9", "\x00"], "\x99" => ["\x1f", "\xff", "\xdc"], "\x9a" => ["\x1f", "\xff", "\xec", "\x00"], "\x9b" => ["\x1f", "\xff", "\xf9", "@"], "\x9c" => ["\x1f", "\xff", "\xec", "\x80"], "\x9d" => ["\x1f", "\xff", "\xf9", "\x80"], "\x9e" => ["\x1f", "\xff", "\xf9", "\xc0"], "\x9f" => ["\x1f", "\xff", "\xfd", "\xe0"], "\xa0" => ["\x1f", "\xff", "\xed", "\x00"], "\xa1" => ["\x1f", "\xff", "\xdd"], "\xa2" => ["\x1f", "\xff", "\xd2"], "\xa3" => ["\x1f", "\xff", "\xed", "\x80"], "\xa4" => ["\x1f", "\xff", "\xee", "\x00"], "\xa5" => ["\x1f", "\xff", "\xfa", "\x00"], "\xa6" => ["\x1f", "\xff", "\xfa", "@"], "\xa7" => ["\x1f", "\xff", "\xde"], "\xa8" => ["\x1f", "\xff", "\xfa", "\x80"], "\xa9" => ["\x1f", "\xff", "\xee", "\x80"], "\xaa" => ["\x1f", "\xff", "\xef", "\x00"], "\xab" => ["\x1f", "\xff", "\xfe", "\x00"], "\xac" => ["\x1f", "\xff", "\xdf"], "\xad" => ["\x1f", "\xff", "\xef", "\x80"], "\xae" => ["\x1f", "\xff", "\xfa", "\xc0"], "\xaf" => ["\x1f", "\xff", "\xfb", "\x00"], "\xb0" => ["\x1f", "\xff", "\xe0"], "\xb1" => ["\x1f", "\xff", "\xe1"], "\xb2" => ["\x1f", "\xff", "\xf0", "\x00"], "\xb3" => ["\x1f", "\xff", "\xe2"], "\xb4" => ["\x1f", "\xff", "\xfb", "@"], "\xb5" => ["\x1f", "\xff", "\xf0", "\x80"], "\xb6" => ["\x1f", "\xff", "\xfb", "\x80"], "\xb7" => ["\x1f", "\xff", "\xfb", "\xc0"], "\xb8" => ["\x1f", "\xff", "\xd4"], "\xb9" => ["\x1f", "\xff", "\xf1", "\x00"], "\xba" => ["\x1f", "\xff", "\xf1", "\x80"], "\xbb" => ["\x1f", "\xff", "\xf2", "\x00"], "\xbc" => ["\x1f", "\xff", "\xfc", "\x00"], "\xbd" => ["\x1f", "\xff", "\xf2", "\x80"], "\xbe" => ["\x1f", "\xff", "\xf3", "\x00"], "\xbf" => ["\x1f", "\xff", "\xfc", "@"], "\xc0" => ["\x1f", "\xff", "\xff", "\x00"], "\xc1" => ["\x1f", "\xff", "\xff", "\x08"], "\xc2" => ["\x1f", "\xff", "\xd6"], "\xc3" => ["\x1f", "\xff", "\xc4"], "\xc4" => ["\x1f", "\xff", "\xf3", "\x80"], "\xc5" => ["\x1f", "\xff", "\xfc", "\x80"], "\xc6" => ["\x1f", "\xff", "\xf4", "\x00"], "\xc7" => ["\x1f", "\xff", "\xfe", "\xc0"], "\xc8" => ["\x1f", "\xff", "\xff", "\x10"], "\xc9" => ["\x1f", "\xff", "\xff", "\x18"], "\xca" => ["\x1f", "\xff", "\xff", " "], "\xcb" => ["\x1f", "\xff", "\xff", "x"], "\xcc" => ["\x1f", "\xff", "\xff", "|"], "\xcd" => ["\x1f", "\xff", "\xff", "("], "\xce" => ["\x1f", "\xff", "\xfe", " "], "\xcf" => ["\x1f", "\xff", "\xfe", "\xd0"], "\xd0" => ["\x1f", "\xff", "\xc8"], "\xd1" => ["\x1f", "\xff", "\xe3"], "\xd2" => ["\x1f", "\xff", "\xff", "0"], "\xd3" => ["\x1f", "\xff", "\xff", "\x80"], "\xd4" => ["\x1f", "\xff", "\xff", "\x84"], "\xd5" => ["\x1f", "\xff", "\xff", "8"], "\xd6" => ["\x1f", "\xff", "\xff", "\x88"], "\xd7" => ["\x1f", "\xff", "\xfe", "@"], "\xd8" => ["\x1f", "\xff", "\xe4"], "\xd9" => ["\x1f", "\xff", "\xe5"], "\xda" => ["\x1f", "\xff", "\xff", "@"], "\xdb" => ["\x1f", "\xff", "\xff", "H"], "\xdc" => ["\x1f", "\xff", "\xff", "\xfa"], "\xdd" => ["\x1f", "\xff", "\xff", "\x8c"], "\xde" => ["\x1f", "\xff", "\xff", "\x90"], "\xdf" => ["\x1f", "\xff", "\xff", "\x94"], "\xe0" => ["\x1f", "\xff", "\xd8"], "\xe1" => ["\x1f", "\xff", "\xfe", "`"], "\xe2" => ["\x1f", "\xff", "\xda"], "\xe3" => ["\x1f", "\xff", "\xe6"], "\xe4" => ["\x1f", "\xff", "\xf4", "\x80"], "\xe5" => ["\x1f", "\xff", "\xe7"], "\xe6" => ["\x1f", "\xff", "\xe8"], "\xe7" => ["\x1f", "\xff", "\xfc", "\xc0"], "\xe8" => ["\x1f", "\xff", "\xf5", "\x00"], "\xe9" => ["\x1f", "\xff", "\xf5", "\x80"], "\xea" => ["\x1f", "\xff", "\xfe", "\xe0"], "\xeb" => ["\x1f", "\xff", "\xfe", "\xf0"], "\xec" => ["\x1f", "\xff", "\xfe", "\x80"], "\xed" => ["\x1f", "\xff", "\xfe", "\xa0"], "\xee" => ["\x1f", "\xff", "\xff", "P"], "\xef" => ["\x1f", "\xff", "\xfd", "\x00"], "\xf0" => ["\x1f", "\xff", "\xff", "X"], "\xf1" => ["\x1f", "\xff", "\xff", "\x98"], "\xf2" => ["\x1f", "\xff", "\xff", "`"], "\xf3" => ["\x1f", "\xff", "\xff", "h"], "\xf4" => ["\x1f", "\xff", "\xff", "\x9c"], "\xf5" => ["\x1f", "\xff", "\xff", "\xa0"], "\xf6" => ["\x1f", "\xff", "\xff", "\xa4"], "\xf7" => ["\x1f", "\xff", "\xff", "\xa8"], "\xf8" => ["\x1f", "\xff", "\xff", "\xac"], "\xf9" => ["\x1f", "\xff", "\xff", "\xfc"], "\xfa" => ["\x1f", "\xff", "\xff", "\xb0"], "\xfb" => ["\x1f", "\xff", "\xff", "\xb4"], "\xfc" => ["\x1f", "\xff", "\xff", "\xb8"], "\xfd" => ["\x1f", "\xff", "\xff", "\xbc"], "\xfe" => ["\x1f", "\xff", "\xff", "\xc0"], "\xff" => ["\x1f", "\xff", "\xff", "p"]], ["\x00" => ["\x0f", "\xfc", "\x00"], "\x01" => ["\x0f", "\xff", "\xfb", "\x00"], "\x02" => ["\x0f", "\xff", "\xff", "\xe2"], "\x03" => ["\x0f", "\xff", "\xff", "\xe3"], "\x04" => ["\x0f", "\xff", "\xff", "\xe4"], "\x05" => ["\x0f", "\xff", "\xff", "\xe5"], "\x06" => ["\x0f", "\xff", "\xff", "\xe6"], "\x07" => ["\x0f", "\xff", "\xff", "\xe7"], "\x08" => ["\x0f", "\xff", "\xff", "\xe8"], "\t" => ["\x0f", "\xff", "\xfe", "\xa0"], "\n" => ["\x0f", "\xff", "\xff", "\xff", "\x00"], "\v" => ["\x0f", "\xff", "\xff", "\xe9"], "\f" => ["\x0f", "\xff", "\xff", "\xea"], "\r" => ["\x0f", "\xff", "\xff", "\xff", "@"], "\x0e" => ["\x0f", "\xff", "\xff", "\xeb"], "\x0f" => ["\x0f", "\xff", "\xff", "\xec"], "\x10" => ["\x0f", "\xff", "\xff", "\xed"], "\x11" => ["\x0f", "\xff", "\xff", "\xee"], "\x12" => ["\x0f", "\xff", "\xff", "\xef"], "\x13" => ["\x0f", "\xff", "\xff", "\xf0"], "\x14" => ["\x0f", "\xff", "\xff", "\xf1"], "\x15" => ["\x0f", "\xff", "\xff", "\xf2"], "\x16" => ["\x0f", "\xff", "\xff", "\xff", "\x80"], "\x17" => ["\x0f", "\xff", "\xff", "\xf3"], "\x18" => ["\x0f", "\xff", "\xff", "\xf4"], "\x19" => ["\x0f", "\xff", "\xff", "\xf5"], "\x1a" => ["\x0f", "\xff", "\xff", "\xf6"], "\x1b" => ["\x0f", "\xff", "\xff", "\xf7"], "\x1c" => ["\x0f", "\xff", "\xff", "\xf8"], "\x1d" => ["\x0f", "\xff", "\xff", "\xf9"], "\x1e" => ["\x0f", "\xff", "\xff", "\xfa"], "\x1f" => ["\x0f", "\xff", "\xff", "\xfb"], " " => ["\x05", "\x00"], "!" => ["\x0f", "\xe0"], "\"" => ["\x0f", "\xe4"], "#" => ["\x0f", "\xfa"], "\$" => ["\x0f", "\xfc", "\x80"], "%" => ["\x05", "@"], "&" => ["\x0f", "\x80"], "'" => ["\x0f", "\xf4"], "(" => ["\x0f", "\xe8"], ")" => ["\x0f", "\xec"], "*" => ["\x0f", "\x90"], "+" => ["\x0f", "\xf6"], "," => ["\x0f", "\xa0"], "-" => ["\x05", "\x80"], "." => ["\x05", "\xc0"], "/" => ["\x06", "\x00"], ["\x00", "\x00"], ["\x00", "\x80"], ["\x01", "\x00"], ["\x06", "@"], ["\x06", "\x80"], ["\x06", "\xc0"], ["\x07", "\x00"], ["\x07", "@"], ["\x07", "\x80"], ["\x07", "\xc0"], ":" => ["\v", "\x80"], ";" => ["\x0f", "\xb0"], "<" => ["\x0f", "\xff", "\x80"], "=" => ["\x08", "\x00"], ">" => ["\x0f", "\xfb"], "?" => ["\x0f", "\xf0"], "@" => ["\x0f", "\xfd", "\x00"], "A" => ["\x08", "@"], "B" => ["\v", "\xa0"], "C" => ["\v", "\xc0"], "D" => ["\v", "\xe0"], "E" => ["\f", "\x00"], "F" => ["\f", " "], "G" => ["\f", "@"], "H" => ["\f", "`"], "I" => ["\f", "\x80"], "J" => ["\f", "\xa0"], "K" => ["\f", "\xc0"], "L" => ["\f", "\xe0"], "M" => ["\r", "\x00"], "N" => ["\r", " "], "O" => ["\r", "@"], "P" => ["\r", "`"], "Q" => ["\r", "\x80"], "R" => ["\r", "\xa0"], "S" => ["\r", "\xc0"], "T" => ["\r", "\xe0"], "U" => ["\x0e", "\x00"], "V" => ["\x0e", " "], "W" => ["\x0e", "@"], "X" => ["\x0f", "\xc0"], "Y" => ["\x0e", "`"], "Z" => ["\x0f", "\xd0"], "[" => ["\x0f", "\xfd", "\x80"], "\\" => ["\x0f", "\xff", "\xe0"], "]" => ["\x0f", "\xfe", "\x00"], "^" => ["\x0f", "\xff", "\x00"], "_" => ["\x08", "\x80"], "`" => ["\x0f", "\xff", "\xa0"], "a" => ["\x01", "\x80"], "b" => ["\x08", "\xc0"], "c" => ["\x02", "\x00"], "d" => ["\t", "\x00"], "e" => ["\x02", "\x80"], "f" => ["\t", "@"], "g" => ["\t", "\x80"], "h" => ["\t", "\xc0"], "i" => ["\x03", "\x00"], "j" => ["\x0e", "\x80"], "k" => ["\x0e", "\xa0"], "l" => ["\n", "\x00"], "m" => ["\n", "@"], "n" => ["\n", "\x80"], "o" => ["\x03", "\x80"], "p" => ["\n", "\xc0"], "q" => ["\x0e", "\xc0"], "r" => ["\v", "\x00"], "s" => ["\x04", "\x00"], "t" => ["\x04", "\x80"], "u" => ["\v", "@"], "v" => ["\x0e", "\xe0"], "w" => ["\x0f", "\x00"], "x" => ["\x0f", " "], "y" => ["\x0f", "@"], "z" => ["\x0f", "`"], "{" => ["\x0f", "\xff", "\xc0"], "|" => ["\x0f", "\xf8"], "}" => ["\x0f", "\xff", "@"], "~" => ["\x0f", "\xfe", "\x80"], "" => ["\x0f", "\xff", "\xff", "\xfc"], "\x80" => ["\x0f", "\xff", "\xe6"], "\x81" => ["\x0f", "\xff", "\xf4", "\x80"], "\x82" => ["\x0f", "\xff", "\xe7"], "\x83" => ["\x0f", "\xff", "\xe8"], "\x84" => ["\x0f", "\xff", "\xf4", "\xc0"], "\x85" => ["\x0f", "\xff", "\xf5", "\x00"], "\x86" => ["\x0f", "\xff", "\xf5", "@"], "\x87" => ["\x0f", "\xff", "\xfb", " "], "\x88" => ["\x0f", "\xff", "\xf5", "\x80"], "\x89" => ["\x0f", "\xff", "\xfb", "@"], "\x8a" => ["\x0f", "\xff", "\xfb", "`"], "\x8b" => ["\x0f", "\xff", "\xfb", "\x80"], "\x8c" => ["\x0f", "\xff", "\xfb", "\xa0"], "\x8d" => ["\x0f", "\xff", "\xfb", "\xc0"], "\x8e" => ["\x0f", "\xff", "\xfe", "\xb0"], "\x8f" => ["\x0f", "\xff", "\xfb", "\xe0"], "\x90" => ["\x0f", "\xff", "\xfe", "\xc0"], "\x91" => ["\x0f", "\xff", "\xfe", "\xd0"], "\x92" => ["\x0f", "\xff", "\xf5", "\xc0"], "\x93" => ["\x0f", "\xff", "\xfc", "\x00"], "\x94" => ["\x0f", "\xff", "\xfe", "\xe0"], "\x95" => ["\x0f", "\xff", "\xfc", " "], "\x96" => ["\x0f", "\xff", "\xfc", "@"], "\x97" => ["\x0f", "\xff", "\xfc", "`"], "\x98" => ["\x0f", "\xff", "\xfc", "\x80"], "\x99" => ["\x0f", "\xff", "\xee", "\x00"], "\x9a" => ["\x0f", "\xff", "\xf6", "\x00"], "\x9b" => ["\x0f", "\xff", "\xfc", "\xa0"], "\x9c" => ["\x0f", "\xff", "\xf6", "@"], "\x9d" => ["\x0f", "\xff", "\xfc", "\xc0"], "\x9e" => ["\x0f", "\xff", "\xfc", "\xe0"], "\x9f" => ["\x0f", "\xff", "\xfe", "\xf0"], "\xa0" => ["\x0f", "\xff", "\xf6", "\x80"], "\xa1" => ["\x0f", "\xff", "\xee", "\x80"], "\xa2" => ["\x0f", "\xff", "\xe9"], "\xa3" => ["\x0f", "\xff", "\xf6", "\xc0"], "\xa4" => ["\x0f", "\xff", "\xf7", "\x00"], "\xa5" => ["\x0f", "\xff", "\xfd", "\x00"], "\xa6" => ["\x0f", "\xff", "\xfd", " "], "\xa7" => ["\x0f", "\xff", "\xef", "\x00"], "\xa8" => ["\x0f", "\xff", "\xfd", "@"], "\xa9" => ["\x0f", "\xff", "\xf7", "@"], "\xaa" => ["\x0f", "\xff", "\xf7", "\x80"], "\xab" => ["\x0f", "\xff", "\xff", "\x00"], "\xac" => ["\x0f", "\xff", "\xef", "\x80"], "\xad" => ["\x0f", "\xff", "\xf7", "\xc0"], "\xae" => ["\x0f", "\xff", "\xfd", "`"], "\xaf" => ["\x0f", "\xff", "\xfd", "\x80"], "\xb0" => ["\x0f", "\xff", "\xf0", "\x00"], "\xb1" => ["\x0f", "\xff", "\xf0", "\x80"], "\xb2" => ["\x0f", "\xff", "\xf8", "\x00"], "\xb3" => ["\x0f", "\xff", "\xf1", "\x00"], "\xb4" => ["\x0f", "\xff", "\xfd", "\xa0"], "\xb5" => ["\x0f", "\xff", "\xf8", "@"], "\xb6" => ["\x0f", "\xff", "\xfd", "\xc0"], "\xb7" => ["\x0f", "\xff", "\xfd", "\xe0"], "\xb8" => ["\x0f", "\xff", "\xea"], "\xb9" => ["\x0f", "\xff", "\xf8", "\x80"], "\xba" => ["\x0f", "\xff", "\xf8", "\xc0"], "\xbb" => ["\x0f", "\xff", "\xf9", "\x00"], "\xbc" => ["\x0f", "\xff", "\xfe", "\x00"], "\xbd" => ["\x0f", "\xff", "\xf9", "@"], "\xbe" => ["\x0f", "\xff", "\xf9", "\x80"], "\xbf" => ["\x0f", "\xff", "\xfe", " "], "\xc0" => ["\x0f", "\xff", "\xff", "\x80"], "\xc1" => ["\x0f", "\xff", "\xff", "\x84"], "\xc2" => ["\x0f", "\xff", "\xeb"], "\xc3" => ["\x0f", "\xff", "\xe2"], "\xc4" => ["\x0f", "\xff", "\xf9", "\xc0"], "\xc5" => ["\x0f", "\xff", "\xfe", "@"], "\xc6" => ["\x0f", "\xff", "\xfa", "\x00"], "\xc7" => ["\x0f", "\xff", "\xff", "`"], "\xc8" => ["\x0f", "\xff", "\xff", "\x88"], "\xc9" => ["\x0f", "\xff", "\xff", "\x8c"], "\xca" => ["\x0f", "\xff", "\xff", "\x90"], "\xcb" => ["\x0f", "\xff", "\xff", "\xbc"], "\xcc" => ["\x0f", "\xff", "\xff", "\xbe"], "\xcd" => ["\x0f", "\xff", "\xff", "\x94"], "\xce" => ["\x0f", "\xff", "\xff", "\x10"], "\xcf" => ["\x0f", "\xff", "\xff", "h"], "\xd0" => ["\x0f", "\xff", "\xe4"], "\xd1" => ["\x0f", "\xff", "\xf1", "\x80"], "\xd2" => ["\x0f", "\xff", "\xff", "\x98"], "\xd3" => ["\x0f", "\xff", "\xff", "\xc0"], "\xd4" => ["\x0f", "\xff", "\xff", "\xc2"], "\xd5" => ["\x0f", "\xff", "\xff", "\x9c"], "\xd6" => ["\x0f", "\xff", "\xff", "\xc4"], "\xd7" => ["\x0f", "\xff", "\xff", " "], "\xd8" => ["\x0f", "\xff", "\xf2", "\x00"], "\xd9" => ["\x0f", "\xff", "\xf2", "\x80"], "\xda" => ["\x0f", "\xff", "\xff", "\xa0"], "\xdb" => ["\x0f", "\xff", "\xff", "\xa4"], "\xdc" => ["\x0f", "\xff", "\xff", "\xfd"], "\xdd" => ["\x0f", "\xff", "\xff", "\xc6"], "\xde" => ["\x0f", "\xff", "\xff", "\xc8"], "\xdf" => ["\x0f", "\xff", "\xff", "\xca"], "\xe0" => ["\x0f", "\xff", "\xec"], "\xe1" => ["\x0f", "\xff", "\xff", "0"], "\xe2" => ["\x0f", "\xff", "\xed"], "\xe3" => ["\x0f", "\xff", "\xf3", "\x00"], "\xe4" => ["\x0f", "\xff", "\xfa", "@"], "\xe5" => ["\x0f", "\xff", "\xf3", "\x80"], "\xe6" => ["\x0f", "\xff", "\xf4", "\x00"], "\xe7" => ["\x0f", "\xff", "\xfe", "`"], "\xe8" => ["\x0f", "\xff", "\xfa", "\x80"], "\xe9" => ["\x0f", "\xff", "\xfa", "\xc0"], "\xea" => ["\x0f", "\xff", "\xff", "p"], "\xeb" => ["\x0f", "\xff", "\xff", "x"], "\xec" => ["\x0f", "\xff", "\xff", "@"], "\xed" => ["\x0f", "\xff", "\xff", "P"], "\xee" => ["\x0f", "\xff", "\xff", "\xa8"], "\xef" => ["\x0f", "\xff", "\xfe", "\x80"], "\xf0" => ["\x0f", "\xff", "\xff", "\xac"], "\xf1" => ["\x0f", "\xff", "\xff", "\xcc"], "\xf2" => ["\x0f", "\xff", "\xff", "\xb0"], "\xf3" => ["\x0f", "\xff", "\xff", "\xb4"], "\xf4" => ["\x0f", "\xff", "\xff", "\xce"], "\xf5" => ["\x0f", "\xff", "\xff", "\xd0"], "\xf6" => ["\x0f", "\xff", "\xff", "\xd2"], "\xf7" => ["\x0f", "\xff", "\xff", "\xd4"], "\xf8" => ["\x0f", "\xff", "\xff", "\xd6"], "\xf9" => ["\x0f", "\xff", "\xff", "\xfe"], "\xfa" => ["\x0f", "\xff", "\xff", "\xd8"], "\xfb" => ["\x0f", "\xff", "\xff", "\xda"], "\xfc" => ["\x0f", "\xff", "\xff", "\xdc"], "\xfd" => ["\x0f", "\xff", "\xff", "\xde"], "\xfe" => ["\x0f", "\xff", "\xff", "\xe0"], "\xff" => ["\x0f", "\xff", "\xff", "\xb8"]], ["\x00" => ["\x07", "\xfe", "\x00"], "\x01" => ["\x07", "\xff", "\xfd", "\x80"], "\x02" => ["\x07", "\xff", "\xff", "\xf1", "\x00"], "\x03" => ["\x07", "\xff", "\xff", "\xf1", "\x80"], "\x04" => ["\x07", "\xff", "\xff", "\xf2", "\x00"], "\x05" => ["\x07", "\xff", "\xff", "\xf2", "\x80"], "\x06" => ["\x07", "\xff", "\xff", "\xf3", "\x00"], "\x07" => ["\x07", "\xff", "\xff", "\xf3", "\x80"], "\x08" => ["\x07", "\xff", "\xff", "\xf4", "\x00"], "\t" => ["\x07", "\xff", "\xff", "P"], "\n" => ["\x07", "\xff", "\xff", "\xff", "\x80"], "\v" => ["\x07", "\xff", "\xff", "\xf4", "\x80"], "\f" => ["\x07", "\xff", "\xff", "\xf5", "\x00"], "\r" => ["\x07", "\xff", "\xff", "\xff", "\xa0"], "\x0e" => ["\x07", "\xff", "\xff", "\xf5", "\x80"], "\x0f" => ["\x07", "\xff", "\xff", "\xf6", "\x00"], "\x10" => ["\x07", "\xff", "\xff", "\xf6", "\x80"], "\x11" => ["\x07", "\xff", "\xff", "\xf7", "\x00"], "\x12" => ["\x07", "\xff", "\xff", "\xf7", "\x80"], "\x13" => ["\x07", "\xff", "\xff", "\xf8", "\x00"], "\x14" => ["\x07", "\xff", "\xff", "\xf8", "\x80"], "\x15" => ["\x07", "\xff", "\xff", "\xf9", "\x00"], "\x16" => ["\x07", "\xff", "\xff", "\xff", "\xc0"], "\x17" => ["\x07", "\xff", "\xff", "\xf9", "\x80"], "\x18" => ["\x07", "\xff", "\xff", "\xfa", "\x00"], "\x19" => ["\x07", "\xff", "\xff", "\xfa", "\x80"], "\x1a" => ["\x07", "\xff", "\xff", "\xfb", "\x00"], "\x1b" => ["\x07", "\xff", "\xff", "\xfb", "\x80"], "\x1c" => ["\x07", "\xff", "\xff", "\xfc", "\x00"], "\x1d" => ["\x07", "\xff", "\xff", "\xfc", "\x80"], "\x1e" => ["\x07", "\xff", "\xff", "\xfd", "\x00"], "\x1f" => ["\x07", "\xff", "\xff", "\xfd", "\x80"], " " => ["\x02", "\x80"], "!" => ["\x07", "\xf0"], "\"" => ["\x07", "\xf2"], "#" => ["\x07", "\xfd", "\x00"], "\$" => ["\x07", "\xfe", "@"], "%" => ["\x02", "\xa0"], "&" => ["\x07", "\xc0"], "'" => ["\x07", "\xfa"], "(" => ["\x07", "\xf4"], ")" => ["\x07", "\xf6"], "*" => ["\x07", "\xc8"], "+" => ["\x07", "\xfb"], "," => ["\x07", "\xd0"], "-" => ["\x02", "\xc0"], "." => ["\x02", "\xe0"], "/" => ["\x03", "\x00"], ["\x00", "\x00"], ["\x00", "@"], ["\x00", "\x80"], ["\x03", " "], ["\x03", "@"], ["\x03", "`"], ["\x03", "\x80"], ["\x03", "\xa0"], ["\x03", "\xc0"], ["\x03", "\xe0"], ":" => ["\x05", "\xc0"], ";" => ["\x07", "\xd8"], "<" => ["\x07", "\xff", "\xc0"], "=" => ["\x04", "\x00"], ">" => ["\x07", "\xfd", "\x80"], "?" => ["\x07", "\xf8"], "@" => ["\x07", "\xfe", "\x80"], "A" => ["\x04", " "], "B" => ["\x05", "\xd0"], "C" => ["\x05", "\xe0"], "D" => ["\x05", "\xf0"], "E" => ["\x06", "\x00"], "F" => ["\x06", "\x10"], "G" => ["\x06", " "], "H" => ["\x06", "0"], "I" => ["\x06", "@"], "J" => ["\x06", "P"], "K" => ["\x06", "`"], "L" => ["\x06", "p"], "M" => ["\x06", "\x80"], "N" => ["\x06", "\x90"], "O" => ["\x06", "\xa0"], "P" => ["\x06", "\xb0"], "Q" => ["\x06", "\xc0"], "R" => ["\x06", "\xd0"], "S" => ["\x06", "\xe0"], "T" => ["\x06", "\xf0"], "U" => ["\x07", "\x00"], "V" => ["\x07", "\x10"], "W" => ["\x07", " "], "X" => ["\x07", "\xe0"], "Y" => ["\x07", "0"], "Z" => ["\x07", "\xe8"], "[" => ["\x07", "\xfe", "\xc0"], "\\" => ["\x07", "\xff", "\xf0"], "]" => ["\x07", "\xff", "\x00"], "^" => ["\x07", "\xff", "\x80"], "_" => ["\x04", "@"], "`" => ["\x07", "\xff", "\xd0"], "a" => ["\x00", "\xc0"], "b" => ["\x04", "`"], "c" => ["\x01", "\x00"], "d" => ["\x04", "\x80"], "e" => ["\x01", "@"], "f" => ["\x04", "\xa0"], "g" => ["\x04", "\xc0"], "h" => ["\x04", "\xe0"], "i" => ["\x01", "\x80"], "j" => ["\x07", "@"], "k" => ["\x07", "P"], "l" => ["\x05", "\x00"], "m" => ["\x05", " "], "n" => ["\x05", "@"], "o" => ["\x01", "\xc0"], "p" => ["\x05", "`"], "q" => ["\x07", "`"], "r" => ["\x05", "\x80"], "s" => ["\x02", "\x00"], "t" => ["\x02", "@"], "u" => ["\x05", "\xa0"], "v" => ["\x07", "p"], "w" => ["\x07", "\x80"], "x" => ["\x07", "\x90"], "y" => ["\x07", "\xa0"], "z" => ["\x07", "\xb0"], "{" => ["\x07", "\xff", "\xe0"], "|" => ["\x07", "\xfc"], "}" => ["\x07", "\xff", "\xa0"], "~" => ["\x07", "\xff", "@"], "" => ["\x07", "\xff", "\xff", "\xfe", "\x00"], "\x80" => ["\x07", "\xff", "\xf3", "\x00"], "\x81" => ["\x07", "\xff", "\xfa", "@"], "\x82" => ["\x07", "\xff", "\xf3", "\x80"], "\x83" => ["\x07", "\xff", "\xf4", "\x00"], "\x84" => ["\x07", "\xff", "\xfa", "`"], "\x85" => ["\x07", "\xff", "\xfa", "\x80"], "\x86" => ["\x07", "\xff", "\xfa", "\xa0"], "\x87" => ["\x07", "\xff", "\xfd", "\x90"], "\x88" => ["\x07", "\xff", "\xfa", "\xc0"], "\x89" => ["\x07", "\xff", "\xfd", "\xa0"], "\x8a" => ["\x07", "\xff", "\xfd", "\xb0"], "\x8b" => ["\x07", "\xff", "\xfd", "\xc0"], "\x8c" => ["\x07", "\xff", "\xfd", "\xd0"], "\x8d" => ["\x07", "\xff", "\xfd", "\xe0"], "\x8e" => ["\x07", "\xff", "\xff", "X"], "\x8f" => ["\x07", "\xff", "\xfd", "\xf0"], "\x90" => ["\x07", "\xff", "\xff", "`"], "\x91" => ["\x07", "\xff", "\xff", "h"], "\x92" => ["\x07", "\xff", "\xfa", "\xe0"], "\x93" => ["\x07", "\xff", "\xfe", "\x00"], "\x94" => ["\x07", "\xff", "\xff", "p"], "\x95" => ["\x07", "\xff", "\xfe", "\x10"], "\x96" => ["\x07", "\xff", "\xfe", " "], "\x97" => ["\x07", "\xff", "\xfe", "0"], "\x98" => ["\x07", "\xff", "\xfe", "@"], "\x99" => ["\x07", "\xff", "\xf7", "\x00"], "\x9a" => ["\x07", "\xff", "\xfb", "\x00"], "\x9b" => ["\x07", "\xff", "\xfe", "P"], "\x9c" => ["\x07", "\xff", "\xfb", " "], "\x9d" => ["\x07", "\xff", "\xfe", "`"], "\x9e" => ["\x07", "\xff", "\xfe", "p"], "\x9f" => ["\x07", "\xff", "\xff", "x"], "\xa0" => ["\x07", "\xff", "\xfb", "@"], "\xa1" => ["\x07", "\xff", "\xf7", "@"], "\xa2" => ["\x07", "\xff", "\xf4", "\x80"], "\xa3" => ["\x07", "\xff", "\xfb", "`"], "\xa4" => ["\x07", "\xff", "\xfb", "\x80"], "\xa5" => ["\x07", "\xff", "\xfe", "\x80"], "\xa6" => ["\x07", "\xff", "\xfe", "\x90"], "\xa7" => ["\x07", "\xff", "\xf7", "\x80"], "\xa8" => ["\x07", "\xff", "\xfe", "\xa0"], "\xa9" => ["\x07", "\xff", "\xfb", "\xa0"], "\xaa" => ["\x07", "\xff", "\xfb", "\xc0"], "\xab" => ["\x07", "\xff", "\xff", "\x80"], "\xac" => ["\x07", "\xff", "\xf7", "\xc0"], "\xad" => ["\x07", "\xff", "\xfb", "\xe0"], "\xae" => ["\x07", "\xff", "\xfe", "\xb0"], "\xaf" => ["\x07", "\xff", "\xfe", "\xc0"], "\xb0" => ["\x07", "\xff", "\xf8", "\x00"], "\xb1" => ["\x07", "\xff", "\xf8", "@"], "\xb2" => ["\x07", "\xff", "\xfc", "\x00"], "\xb3" => ["\x07", "\xff", "\xf8", "\x80"], "\xb4" => ["\x07", "\xff", "\xfe", "\xd0"], "\xb5" => ["\x07", "\xff", "\xfc", " "], "\xb6" => ["\x07", "\xff", "\xfe", "\xe0"], "\xb7" => ["\x07", "\xff", "\xfe", "\xf0"], "\xb8" => ["\x07", "\xff", "\xf5", "\x00"], "\xb9" => ["\x07", "\xff", "\xfc", "@"], "\xba" => ["\x07", "\xff", "\xfc", "`"], "\xbb" => ["\x07", "\xff", "\xfc", "\x80"], "\xbc" => ["\x07", "\xff", "\xff", "\x00"], "\xbd" => ["\x07", "\xff", "\xfc", "\xa0"], "\xbe" => ["\x07", "\xff", "\xfc", "\xc0"], "\xbf" => ["\x07", "\xff", "\xff", "\x10"], "\xc0" => ["\x07", "\xff", "\xff", "\xc0"], "\xc1" => ["\x07", "\xff", "\xff", "\xc2"], "\xc2" => ["\x07", "\xff", "\xf5", "\x80"], "\xc3" => ["\x07", "\xff", "\xf1"], "\xc4" => ["\x07", "\xff", "\xfc", "\xe0"], "\xc5" => ["\x07", "\xff", "\xff", " "], "\xc6" => ["\x07", "\xff", "\xfd", "\x00"], "\xc7" => ["\x07", "\xff", "\xff", "\xb0"], "\xc8" => ["\x07", "\xff", "\xff", "\xc4"], "\xc9" => ["\x07", "\xff", "\xff", "\xc6"], "\xca" => ["\x07", "\xff", "\xff", "\xc8"], "\xcb" => ["\x07", "\xff", "\xff", "\xde"], "\xcc" => ["\x07", "\xff", "\xff", "\xdf"], "\xcd" => ["\x07", "\xff", "\xff", "\xca"], "\xce" => ["\x07", "\xff", "\xff", "\x88"], "\xcf" => ["\x07", "\xff", "\xff", "\xb4"], "\xd0" => ["\x07", "\xff", "\xf2"], "\xd1" => ["\x07", "\xff", "\xf8", "\xc0"], "\xd2" => ["\x07", "\xff", "\xff", "\xcc"], "\xd3" => ["\x07", "\xff", "\xff", "\xe0"], "\xd4" => ["\x07", "\xff", "\xff", "\xe1"], "\xd5" => ["\x07", "\xff", "\xff", "\xce"], "\xd6" => ["\x07", "\xff", "\xff", "\xe2"], "\xd7" => ["\x07", "\xff", "\xff", "\x90"], "\xd8" => ["\x07", "\xff", "\xf9", "\x00"], "\xd9" => ["\x07", "\xff", "\xf9", "@"], "\xda" => ["\x07", "\xff", "\xff", "\xd0"], "\xdb" => ["\x07", "\xff", "\xff", "\xd2"], "\xdc" => ["\x07", "\xff", "\xff", "\xfe", "\x80"], "\xdd" => ["\x07", "\xff", "\xff", "\xe3"], "\xde" => ["\x07", "\xff", "\xff", "\xe4"], "\xdf" => ["\x07", "\xff", "\xff", "\xe5"], "\xe0" => ["\x07", "\xff", "\xf6", "\x00"], "\xe1" => ["\x07", "\xff", "\xff", "\x98"], "\xe2" => ["\x07", "\xff", "\xf6", "\x80"], "\xe3" => ["\x07", "\xff", "\xf9", "\x80"], "\xe4" => ["\x07", "\xff", "\xfd", " "], "\xe5" => ["\x07", "\xff", "\xf9", "\xc0"], "\xe6" => ["\x07", "\xff", "\xfa", "\x00"], "\xe7" => ["\x07", "\xff", "\xff", "0"], "\xe8" => ["\x07", "\xff", "\xfd", "@"], "\xe9" => ["\x07", "\xff", "\xfd", "`"], "\xea" => ["\x07", "\xff", "\xff", "\xb8"], "\xeb" => ["\x07", "\xff", "\xff", "\xbc"], "\xec" => ["\x07", "\xff", "\xff", "\xa0"], "\xed" => ["\x07", "\xff", "\xff", "\xa8"], "\xee" => ["\x07", "\xff", "\xff", "\xd4"], "\xef" => ["\x07", "\xff", "\xff", "@"], "\xf0" => ["\x07", "\xff", "\xff", "\xd6"], "\xf1" => ["\x07", "\xff", "\xff", "\xe6"], "\xf2" => ["\x07", "\xff", "\xff", "\xd8"], "\xf3" => ["\x07", "\xff", "\xff", "\xda"], "\xf4" => ["\x07", "\xff", "\xff", "\xe7"], "\xf5" => ["\x07", "\xff", "\xff", "\xe8"], "\xf6" => ["\x07", "\xff", "\xff", "\xe9"], "\xf7" => ["\x07", "\xff", "\xff", "\xea"], "\xf8" => ["\x07", "\xff", "\xff", "\xeb"], "\xf9" => ["\x07", "\xff", "\xff", "\xff", "\x00"], "\xfa" => ["\x07", "\xff", "\xff", "\xec"], "\xfb" => ["\x07", "\xff", "\xff", "\xed"], "\xfc" => ["\x07", "\xff", "\xff", "\xee"], "\xfd" => ["\x07", "\xff", "\xff", "\xef"], "\xfe" => ["\x07", "\xff", "\xff", "\xf0"], "\xff" => ["\x07", "\xff", "\xff", "\xdc"]], ["\x00" => ["\x03", "\xff", "\x00"], "\x01" => ["\x03", "\xff", "\xfe", "\xc0"], "\x02" => ["\x03", "\xff", "\xff", "\xf8", "\x80"], "\x03" => ["\x03", "\xff", "\xff", "\xf8", "\xc0"], "\x04" => ["\x03", "\xff", "\xff", "\xf9", "\x00"], "\x05" => ["\x03", "\xff", "\xff", "\xf9", "@"], "\x06" => ["\x03", "\xff", "\xff", "\xf9", "\x80"], "\x07" => ["\x03", "\xff", "\xff", "\xf9", "\xc0"], "\x08" => ["\x03", "\xff", "\xff", "\xfa", "\x00"], "\t" => ["\x03", "\xff", "\xff", "\xa8"], "\n" => ["\x03", "\xff", "\xff", "\xff", "\xc0"], "\v" => ["\x03", "\xff", "\xff", "\xfa", "@"], "\f" => ["\x03", "\xff", "\xff", "\xfa", "\x80"], "\r" => ["\x03", "\xff", "\xff", "\xff", "\xd0"], "\x0e" => ["\x03", "\xff", "\xff", "\xfa", "\xc0"], "\x0f" => ["\x03", "\xff", "\xff", "\xfb", "\x00"], "\x10" => ["\x03", "\xff", "\xff", "\xfb", "@"], "\x11" => ["\x03", "\xff", "\xff", "\xfb", "\x80"], "\x12" => ["\x03", "\xff", "\xff", "\xfb", "\xc0"], "\x13" => ["\x03", "\xff", "\xff", "\xfc", "\x00"], "\x14" => ["\x03", "\xff", "\xff", "\xfc", "@"], "\x15" => ["\x03", "\xff", "\xff", "\xfc", "\x80"], "\x16" => ["\x03", "\xff", "\xff", "\xff", "\xe0"], "\x17" => ["\x03", "\xff", "\xff", "\xfc", "\xc0"], "\x18" => ["\x03", "\xff", "\xff", "\xfd", "\x00"], "\x19" => ["\x03", "\xff", "\xff", "\xfd", "@"], "\x1a" => ["\x03", "\xff", "\xff", "\xfd", "\x80"], "\x1b" => ["\x03", "\xff", "\xff", "\xfd", "\xc0"], "\x1c" => ["\x03", "\xff", "\xff", "\xfe", "\x00"], "\x1d" => ["\x03", "\xff", "\xff", "\xfe", "@"], "\x1e" => ["\x03", "\xff", "\xff", "\xfe", "\x80"], "\x1f" => ["\x03", "\xff", "\xff", "\xfe", "\xc0"], " " => ["\x01", "@"], "!" => ["\x03", "\xf8"], "\"" => ["\x03", "\xf9"], "#" => ["\x03", "\xfe", "\x80"], "\$" => ["\x03", "\xff", " "], "%" => ["\x01", "P"], "&" => ["\x03", "\xe0"], "'" => ["\x03", "\xfd", "\x00"], "(" => ["\x03", "\xfa"], ")" => ["\x03", "\xfb"], "*" => ["\x03", "\xe4"], "+" => ["\x03", "\xfd", "\x80"], "," => ["\x03", "\xe8"], "-" => ["\x01", "`"], "." => ["\x01", "p"], "/" => ["\x01", "\x80"], ["\x00", "\x00"], ["\x00", " "], ["\x00", "@"], ["\x01", "\x90"], ["\x01", "\xa0"], ["\x01", "\xb0"], ["\x01", "\xc0"], ["\x01", "\xd0"], ["\x01", "\xe0"], ["\x01", "\xf0"], ":" => ["\x02", "\xe0"], ";" => ["\x03", "\xec"], "<" => ["\x03", "\xff", "\xe0"], "=" => ["\x02", "\x00"], ">" => ["\x03", "\xfe", "\xc0"], "?" => ["\x03", "\xfc"], "@" => ["\x03", "\xff", "@"], "A" => ["\x02", "\x10"], "B" => ["\x02", "\xe8"], "C" => ["\x02", "\xf0"], "D" => ["\x02", "\xf8"], "E" => ["\x03", "\x00"], "F" => ["\x03", "\x08"], "G" => ["\x03", "\x10"], "H" => ["\x03", "\x18"], "I" => ["\x03", " "], "J" => ["\x03", "("], "K" => ["\x03", "0"], "L" => ["\x03", "8"], "M" => ["\x03", "@"], "N" => ["\x03", "H"], "O" => ["\x03", "P"], "P" => ["\x03", "X"], "Q" => ["\x03", "`"], "R" => ["\x03", "h"], "S" => ["\x03", "p"], "T" => ["\x03", "x"], "U" => ["\x03", "\x80"], "V" => ["\x03", "\x88"], "W" => ["\x03", "\x90"], "X" => ["\x03", "\xf0"], "Y" => ["\x03", "\x98"], "Z" => ["\x03", "\xf4"], "[" => ["\x03", "\xff", "`"], "\\" => ["\x03", "\xff", "\xf8", "\x00"], "]" => ["\x03", "\xff", "\x80"], "^" => ["\x03", "\xff", "\xc0"], "_" => ["\x02", " "], "`" => ["\x03", "\xff", "\xe8"], "a" => ["\x00", "`"], "b" => ["\x02", "0"], "c" => ["\x00", "\x80"], "d" => ["\x02", "@"], "e" => ["\x00", "\xa0"], "f" => ["\x02", "P"], "g" => ["\x02", "`"], "h" => ["\x02", "p"], "i" => ["\x00", "\xc0"], "j" => ["\x03", "\xa0"], "k" => ["\x03", "\xa8"], "l" => ["\x02", "\x80"], "m" => ["\x02", "\x90"], "n" => ["\x02", "\xa0"], "o" => ["\x00", "\xe0"], "p" => ["\x02", "\xb0"], "q" => ["\x03", "\xb0"], "r" => ["\x02", "\xc0"], "s" => ["\x01", "\x00"], "t" => ["\x01", " "], "u" => ["\x02", "\xd0"], "v" => ["\x03", "\xb8"], "w" => ["\x03", "\xc0"], "x" => ["\x03", "\xc8"], "y" => ["\x03", "\xd0"], "z" => ["\x03", "\xd8"], "{" => ["\x03", "\xff", "\xf0"], "|" => ["\x03", "\xfe", "\x00"], "}" => ["\x03", "\xff", "\xd0"], "~" => ["\x03", "\xff", "\xa0"], "" => ["\x03", "\xff", "\xff", "\xff", "\x00"], "\x80" => ["\x03", "\xff", "\xf9", "\x80"], "\x81" => ["\x03", "\xff", "\xfd", " "], "\x82" => ["\x03", "\xff", "\xf9", "\xc0"], "\x83" => ["\x03", "\xff", "\xfa", "\x00"], "\x84" => ["\x03", "\xff", "\xfd", "0"], "\x85" => ["\x03", "\xff", "\xfd", "@"], "\x86" => ["\x03", "\xff", "\xfd", "P"], "\x87" => ["\x03", "\xff", "\xfe", "\xc8"], "\x88" => ["\x03", "\xff", "\xfd", "`"], "\x89" => ["\x03", "\xff", "\xfe", "\xd0"], "\x8a" => ["\x03", "\xff", "\xfe", "\xd8"], "\x8b" => ["\x03", "\xff", "\xfe", "\xe0"], "\x8c" => ["\x03", "\xff", "\xfe", "\xe8"], "\x8d" => ["\x03", "\xff", "\xfe", "\xf0"], "\x8e" => ["\x03", "\xff", "\xff", "\xac"], "\x8f" => ["\x03", "\xff", "\xfe", "\xf8"], "\x90" => ["\x03", "\xff", "\xff", "\xb0"], "\x91" => ["\x03", "\xff", "\xff", "\xb4"], "\x92" => ["\x03", "\xff", "\xfd", "p"], "\x93" => ["\x03", "\xff", "\xff", "\x00"], "\x94" => ["\x03", "\xff", "\xff", "\xb8"], "\x95" => ["\x03", "\xff", "\xff", "\x08"], "\x96" => ["\x03", "\xff", "\xff", "\x10"], "\x97" => ["\x03", "\xff", "\xff", "\x18"], "\x98" => ["\x03", "\xff", "\xff", " "], "\x99" => ["\x03", "\xff", "\xfb", "\x80"], "\x9a" => ["\x03", "\xff", "\xfd", "\x80"], "\x9b" => ["\x03", "\xff", "\xff", "("], "\x9c" => ["\x03", "\xff", "\xfd", "\x90"], "\x9d" => ["\x03", "\xff", "\xff", "0"], "\x9e" => ["\x03", "\xff", "\xff", "8"], "\x9f" => ["\x03", "\xff", "\xff", "\xbc"], "\xa0" => ["\x03", "\xff", "\xfd", "\xa0"], "\xa1" => ["\x03", "\xff", "\xfb", "\xa0"], "\xa2" => ["\x03", "\xff", "\xfa", "@"], "\xa3" => ["\x03", "\xff", "\xfd", "\xb0"], "\xa4" => ["\x03", "\xff", "\xfd", "\xc0"], "\xa5" => ["\x03", "\xff", "\xff", "@"], "\xa6" => ["\x03", "\xff", "\xff", "H"], "\xa7" => ["\x03", "\xff", "\xfb", "\xc0"], "\xa8" => ["\x03", "\xff", "\xff", "P"], "\xa9" => ["\x03", "\xff", "\xfd", "\xd0"], "\xaa" => ["\x03", "\xff", "\xfd", "\xe0"], "\xab" => ["\x03", "\xff", "\xff", "\xc0"], "\xac" => ["\x03", "\xff", "\xfb", "\xe0"], "\xad" => ["\x03", "\xff", "\xfd", "\xf0"], "\xae" => ["\x03", "\xff", "\xff", "X"], "\xaf" => ["\x03", "\xff", "\xff", "`"], "\xb0" => ["\x03", "\xff", "\xfc", "\x00"], "\xb1" => ["\x03", "\xff", "\xfc", " "], "\xb2" => ["\x03", "\xff", "\xfe", "\x00"], "\xb3" => ["\x03", "\xff", "\xfc", "@"], "\xb4" => ["\x03", "\xff", "\xff", "h"], "\xb5" => ["\x03", "\xff", "\xfe", "\x10"], "\xb6" => ["\x03", "\xff", "\xff", "p"], "\xb7" => ["\x03", "\xff", "\xff", "x"], "\xb8" => ["\x03", "\xff", "\xfa", "\x80"], "\xb9" => ["\x03", "\xff", "\xfe", " "], "\xba" => ["\x03", "\xff", "\xfe", "0"], "\xbb" => ["\x03", "\xff", "\xfe", "@"], "\xbc" => ["\x03", "\xff", "\xff", "\x80"], "\xbd" => ["\x03", "\xff", "\xfe", "P"], "\xbe" => ["\x03", "\xff", "\xfe", "`"], "\xbf" => ["\x03", "\xff", "\xff", "\x88"], "\xc0" => ["\x03", "\xff", "\xff", "\xe0"], "\xc1" => ["\x03", "\xff", "\xff", "\xe1"], "\xc2" => ["\x03", "\xff", "\xfa", "\xc0"], "\xc3" => ["\x03", "\xff", "\xf8", "\x80"], "\xc4" => ["\x03", "\xff", "\xfe", "p"], "\xc5" => ["\x03", "\xff", "\xff", "\x90"], "\xc6" => ["\x03", "\xff", "\xfe", "\x80"], "\xc7" => ["\x03", "\xff", "\xff", "\xd8"], "\xc8" => ["\x03", "\xff", "\xff", "\xe2"], "\xc9" => ["\x03", "\xff", "\xff", "\xe3"], "\xca" => ["\x03", "\xff", "\xff", "\xe4"], "\xcb" => ["\x03", "\xff", "\xff", "\xef", "\x00"], "\xcc" => ["\x03", "\xff", "\xff", "\xef", "\x80"], "\xcd" => ["\x03", "\xff", "\xff", "\xe5"], "\xce" => ["\x03", "\xff", "\xff", "\xc4"], "\xcf" => ["\x03", "\xff", "\xff", "\xda"], "\xd0" => ["\x03", "\xff", "\xf9", "\x00"], "\xd1" => ["\x03", "\xff", "\xfc", "`"], "\xd2" => ["\x03", "\xff", "\xff", "\xe6"], "\xd3" => ["\x03", "\xff", "\xff", "\xf0", "\x00"], "\xd4" => ["\x03", "\xff", "\xff", "\xf0", "\x80"], "\xd5" => ["\x03", "\xff", "\xff", "\xe7"], "\xd6" => ["\x03", "\xff", "\xff", "\xf1", "\x00"], "\xd7" => ["\x03", "\xff", "\xff", "\xc8"], "\xd8" => ["\x03", "\xff", "\xfc", "\x80"], "\xd9" => ["\x03", "\xff", "\xfc", "\xa0"], "\xda" => ["\x03", "\xff", "\xff", "\xe8"], "\xdb" => ["\x03", "\xff", "\xff", "\xe9"], "\xdc" => ["\x03", "\xff", "\xff", "\xff", "@"], "\xdd" => ["\x03", "\xff", "\xff", "\xf1", "\x80"], "\xde" => ["\x03", "\xff", "\xff", "\xf2", "\x00"], "\xdf" => ["\x03", "\xff", "\xff", "\xf2", "\x80"], "\xe0" => ["\x03", "\xff", "\xfb", "\x00"], "\xe1" => ["\x03", "\xff", "\xff", "\xcc"], "\xe2" => ["\x03", "\xff", "\xfb", "@"], "\xe3" => ["\x03", "\xff", "\xfc", "\xc0"], "\xe4" => ["\x03", "\xff", "\xfe", "\x90"], "\xe5" => ["\x03", "\xff", "\xfc", "\xe0"], "\xe6" => ["\x03", "\xff", "\xfd", "\x00"], "\xe7" => ["\x03", "\xff", "\xff", "\x98"], "\xe8" => ["\x03", "\xff", "\xfe", "\xa0"], "\xe9" => ["\x03", "\xff", "\xfe", "\xb0"], "\xea" => ["\x03", "\xff", "\xff", "\xdc"], "\xeb" => ["\x03", "\xff", "\xff", "\xde"], "\xec" => ["\x03", "\xff", "\xff", "\xd0"], "\xed" => ["\x03", "\xff", "\xff", "\xd4"], "\xee" => ["\x03", "\xff", "\xff", "\xea"], "\xef" => ["\x03", "\xff", "\xff", "\xa0"], "\xf0" => ["\x03", "\xff", "\xff", "\xeb"], "\xf1" => ["\x03", "\xff", "\xff", "\xf3", "\x00"], "\xf2" => ["\x03", "\xff", "\xff", "\xec"], "\xf3" => ["\x03", "\xff", "\xff", "\xed"], "\xf4" => ["\x03", "\xff", "\xff", "\xf3", "\x80"], "\xf5" => ["\x03", "\xff", "\xff", "\xf4", "\x00"], "\xf6" => ["\x03", "\xff", "\xff", "\xf4", "\x80"], "\xf7" => ["\x03", "\xff", "\xff", "\xf5", "\x00"], "\xf8" => ["\x03", "\xff", "\xff", "\xf5", "\x80"], "\xf9" => ["\x03", "\xff", "\xff", "\xff", "\x80"], "\xfa" => ["\x03", "\xff", "\xff", "\xf6", "\x00"], "\xfb" => ["\x03", "\xff", "\xff", "\xf6", "\x80"], "\xfc" => ["\x03", "\xff", "\xff", "\xf7", "\x00"], "\xfd" => ["\x03", "\xff", "\xff", "\xf7", "\x80"], "\xfe" => ["\x03", "\xff", "\xff", "\xf8", "\x00"], "\xff" => ["\x03", "\xff", "\xff", "\xee"]], ["\x00" => ["\x01", "\xff", "\x80"], "\x01" => ["\x01", "\xff", "\xff", "`"], "\x02" => ["\x01", "\xff", "\xff", "\xfc", "@"], "\x03" => ["\x01", "\xff", "\xff", "\xfc", "`"], "\x04" => ["\x01", "\xff", "\xff", "\xfc", "\x80"], "\x05" => ["\x01", "\xff", "\xff", "\xfc", "\xa0"], "\x06" => ["\x01", "\xff", "\xff", "\xfc", "\xc0"], "\x07" => ["\x01", "\xff", "\xff", "\xfc", "\xe0"], "\x08" => ["\x01", "\xff", "\xff", "\xfd", "\x00"], "\t" => ["\x01", "\xff", "\xff", "\xd4"], "\n" => ["\x01", "\xff", "\xff", "\xff", "\xe0"], "\v" => ["\x01", "\xff", "\xff", "\xfd", " "], "\f" => ["\x01", "\xff", "\xff", "\xfd", "@"], "\r" => ["\x01", "\xff", "\xff", "\xff", "\xe8"], "\x0e" => ["\x01", "\xff", "\xff", "\xfd", "`"], "\x0f" => ["\x01", "\xff", "\xff", "\xfd", "\x80"], "\x10" => ["\x01", "\xff", "\xff", "\xfd", "\xa0"], "\x11" => ["\x01", "\xff", "\xff", "\xfd", "\xc0"], "\x12" => ["\x01", "\xff", "\xff", "\xfd", "\xe0"], "\x13" => ["\x01", "\xff", "\xff", "\xfe", "\x00"], "\x14" => ["\x01", "\xff", "\xff", "\xfe", " "], "\x15" => ["\x01", "\xff", "\xff", "\xfe", "@"], "\x16" => ["\x01", "\xff", "\xff", "\xff", "\xf0"], "\x17" => ["\x01", "\xff", "\xff", "\xfe", "`"], "\x18" => ["\x01", "\xff", "\xff", "\xfe", "\x80"], "\x19" => ["\x01", "\xff", "\xff", "\xfe", "\xa0"], "\x1a" => ["\x01", "\xff", "\xff", "\xfe", "\xc0"], "\x1b" => ["\x01", "\xff", "\xff", "\xfe", "\xe0"], "\x1c" => ["\x01", "\xff", "\xff", "\xff", "\x00"], "\x1d" => ["\x01", "\xff", "\xff", "\xff", " "], "\x1e" => ["\x01", "\xff", "\xff", "\xff", "@"], "\x1f" => ["\x01", "\xff", "\xff", "\xff", "`"], " " => ["\x00", "\xa0"], "!" => ["\x01", "\xfc", "\x00"], "\"" => ["\x01", "\xfc", "\x80"], "#" => ["\x01", "\xff", "@"], "\$" => ["\x01", "\xff", "\x90"], "%" => ["\x00", "\xa8"], "&" => ["\x01", "\xf0"], "'" => ["\x01", "\xfe", "\x80"], "(" => ["\x01", "\xfd", "\x00"], ")" => ["\x01", "\xfd", "\x80"], "*" => ["\x01", "\xf2"], "+" => ["\x01", "\xfe", "\xc0"], "," => ["\x01", "\xf4"], "-" => ["\x00", "\xb0"], "." => ["\x00", "\xb8"], "/" => ["\x00", "\xc0"], ["\x00", "\x00"], ["\x00", "\x10"], ["\x00", " "], ["\x00", "\xc8"], ["\x00", "\xd0"], ["\x00", "\xd8"], ["\x00", "\xe0"], ["\x00", "\xe8"], ["\x00", "\xf0"], ["\x00", "\xf8"], ":" => ["\x01", "p"], ";" => ["\x01", "\xf6"], "<" => ["\x01", "\xff", "\xf0"], "=" => ["\x01", "\x00"], ">" => ["\x01", "\xff", "`"], "?" => ["\x01", "\xfe", "\x00"], "@" => ["\x01", "\xff", "\xa0"], "A" => ["\x01", "\x08"], "B" => ["\x01", "t"], "C" => ["\x01", "x"], "D" => ["\x01", "|"], "E" => ["\x01", "\x80"], "F" => ["\x01", "\x84"], "G" => ["\x01", "\x88"], "H" => ["\x01", "\x8c"], "I" => ["\x01", "\x90"], "J" => ["\x01", "\x94"], "K" => ["\x01", "\x98"], "L" => ["\x01", "\x9c"], "M" => ["\x01", "\xa0"], "N" => ["\x01", "\xa4"], "O" => ["\x01", "\xa8"], "P" => ["\x01", "\xac"], "Q" => ["\x01", "\xb0"], "R" => ["\x01", "\xb4"], "S" => ["\x01", "\xb8"], "T" => ["\x01", "\xbc"], "U" => ["\x01", "\xc0"], "V" => ["\x01", "\xc4"], "W" => ["\x01", "\xc8"], "X" => ["\x01", "\xf8"], "Y" => ["\x01", "\xcc"], "Z" => ["\x01", "\xfa"], "[" => ["\x01", "\xff", "\xb0"], "\\" => ["\x01", "\xff", "\xfc", "\x00"], "]" => ["\x01", "\xff", "\xc0"], "^" => ["\x01", "\xff", "\xe0"], "_" => ["\x01", "\x10"], "`" => ["\x01", "\xff", "\xf4"], "a" => ["\x00", "0"], "b" => ["\x01", "\x18"], "c" => ["\x00", "@"], "d" => ["\x01", " "], "e" => ["\x00", "P"], "f" => ["\x01", "("], "g" => ["\x01", "0"], "h" => ["\x01", "8"], "i" => ["\x00", "`"], "j" => ["\x01", "\xd0"], "k" => ["\x01", "\xd4"], "l" => ["\x01", "@"], "m" => ["\x01", "H"], "n" => ["\x01", "P"], "o" => ["\x00", "p"], "p" => ["\x01", "X"], "q" => ["\x01", "\xd8"], "r" => ["\x01", "`"], "s" => ["\x00", "\x80"], "t" => ["\x00", "\x90"], "u" => ["\x01", "h"], "v" => ["\x01", "\xdc"], "w" => ["\x01", "\xe0"], "x" => ["\x01", "\xe4"], "y" => ["\x01", "\xe8"], "z" => ["\x01", "\xec"], "{" => ["\x01", "\xff", "\xf8"], "|" => ["\x01", "\xff", "\x00"], "}" => ["\x01", "\xff", "\xe8"], "~" => ["\x01", "\xff", "\xd0"], "" => ["\x01", "\xff", "\xff", "\xff", "\x80"], "\x80" => ["\x01", "\xff", "\xfc", "\xc0"], "\x81" => ["\x01", "\xff", "\xfe", "\x90"], "\x82" => ["\x01", "\xff", "\xfc", "\xe0"], "\x83" => ["\x01", "\xff", "\xfd", "\x00"], "\x84" => ["\x01", "\xff", "\xfe", "\x98"], "\x85" => ["\x01", "\xff", "\xfe", "\xa0"], "\x86" => ["\x01", "\xff", "\xfe", "\xa8"], "\x87" => ["\x01", "\xff", "\xff", "d"], "\x88" => ["\x01", "\xff", "\xfe", "\xb0"], "\x89" => ["\x01", "\xff", "\xff", "h"], "\x8a" => ["\x01", "\xff", "\xff", "l"], "\x8b" => ["\x01", "\xff", "\xff", "p"], "\x8c" => ["\x01", "\xff", "\xff", "t"], "\x8d" => ["\x01", "\xff", "\xff", "x"], "\x8e" => ["\x01", "\xff", "\xff", "\xd6"], "\x8f" => ["\x01", "\xff", "\xff", "|"], "\x90" => ["\x01", "\xff", "\xff", "\xd8"], "\x91" => ["\x01", "\xff", "\xff", "\xda"], "\x92" => ["\x01", "\xff", "\xfe", "\xb8"], "\x93" => ["\x01", "\xff", "\xff", "\x80"], "\x94" => ["\x01", "\xff", "\xff", "\xdc"], "\x95" => ["\x01", "\xff", "\xff", "\x84"], "\x96" => ["\x01", "\xff", "\xff", "\x88"], "\x97" => ["\x01", "\xff", "\xff", "\x8c"], "\x98" => ["\x01", "\xff", "\xff", "\x90"], "\x99" => ["\x01", "\xff", "\xfd", "\xc0"], "\x9a" => ["\x01", "\xff", "\xfe", "\xc0"], "\x9b" => ["\x01", "\xff", "\xff", "\x94"], "\x9c" => ["\x01", "\xff", "\xfe", "\xc8"], "\x9d" => ["\x01", "\xff", "\xff", "\x98"], "\x9e" => ["\x01", "\xff", "\xff", "\x9c"], "\x9f" => ["\x01", "\xff", "\xff", "\xde"], "\xa0" => ["\x01", "\xff", "\xfe", "\xd0"], "\xa1" => ["\x01", "\xff", "\xfd", "\xd0"], "\xa2" => ["\x01", "\xff", "\xfd", " "], "\xa3" => ["\x01", "\xff", "\xfe", "\xd8"], "\xa4" => ["\x01", "\xff", "\xfe", "\xe0"], "\xa5" => ["\x01", "\xff", "\xff", "\xa0"], "\xa6" => ["\x01", "\xff", "\xff", "\xa4"], "\xa7" => ["\x01", "\xff", "\xfd", "\xe0"], "\xa8" => ["\x01", "\xff", "\xff", "\xa8"], "\xa9" => ["\x01", "\xff", "\xfe", "\xe8"], "\xaa" => ["\x01", "\xff", "\xfe", "\xf0"], "\xab" => ["\x01", "\xff", "\xff", "\xe0"], "\xac" => ["\x01", "\xff", "\xfd", "\xf0"], "\xad" => ["\x01", "\xff", "\xfe", "\xf8"], "\xae" => ["\x01", "\xff", "\xff", "\xac"], "\xaf" => ["\x01", "\xff", "\xff", "\xb0"], "\xb0" => ["\x01", "\xff", "\xfe", "\x00"], "\xb1" => ["\x01", "\xff", "\xfe", "\x10"], "\xb2" => ["\x01", "\xff", "\xff", "\x00"], "\xb3" => ["\x01", "\xff", "\xfe", " "], "\xb4" => ["\x01", "\xff", "\xff", "\xb4"], "\xb5" => ["\x01", "\xff", "\xff", "\x08"], "\xb6" => ["\x01", "\xff", "\xff", "\xb8"], "\xb7" => ["\x01", "\xff", "\xff", "\xbc"], "\xb8" => ["\x01", "\xff", "\xfd", "@"], "\xb9" => ["\x01", "\xff", "\xff", "\x10"], "\xba" => ["\x01", "\xff", "\xff", "\x18"], "\xbb" => ["\x01", "\xff", "\xff", " "], "\xbc" => ["\x01", "\xff", "\xff", "\xc0"], "\xbd" => ["\x01", "\xff", "\xff", "("], "\xbe" => ["\x01", "\xff", "\xff", "0"], "\xbf" => ["\x01", "\xff", "\xff", "\xc4"], "\xc0" => ["\x01", "\xff", "\xff", "\xf0", "\x00"], "\xc1" => ["\x01", "\xff", "\xff", "\xf0", "\x80"], "\xc2" => ["\x01", "\xff", "\xfd", "`"], "\xc3" => ["\x01", "\xff", "\xfc", "@"], "\xc4" => ["\x01", "\xff", "\xff", "8"], "\xc5" => ["\x01", "\xff", "\xff", "\xc8"], "\xc6" => ["\x01", "\xff", "\xff", "@"], "\xc7" => ["\x01", "\xff", "\xff", "\xec"], "\xc8" => ["\x01", "\xff", "\xff", "\xf1", "\x00"], "\xc9" => ["\x01", "\xff", "\xff", "\xf1", "\x80"], "\xca" => ["\x01", "\xff", "\xff", "\xf2", "\x00"], "\xcb" => ["\x01", "\xff", "\xff", "\xf7", "\x80"], "\xcc" => ["\x01", "\xff", "\xff", "\xf7", "\xc0"], "\xcd" => ["\x01", "\xff", "\xff", "\xf2", "\x80"], "\xce" => ["\x01", "\xff", "\xff", "\xe2"], "\xcf" => ["\x01", "\xff", "\xff", "\xed"], "\xd0" => ["\x01", "\xff", "\xfc", "\x80"], "\xd1" => ["\x01", "\xff", "\xfe", "0"], "\xd2" => ["\x01", "\xff", "\xff", "\xf3", "\x00"], "\xd3" => ["\x01", "\xff", "\xff", "\xf8", "\x00"], "\xd4" => ["\x01", "\xff", "\xff", "\xf8", "@"], "\xd5" => ["\x01", "\xff", "\xff", "\xf3", "\x80"], "\xd6" => ["\x01", "\xff", "\xff", "\xf8", "\x80"], "\xd7" => ["\x01", "\xff", "\xff", "\xe4"], "\xd8" => ["\x01", "\xff", "\xfe", "@"], "\xd9" => ["\x01", "\xff", "\xfe", "P"], "\xda" => ["\x01", "\xff", "\xff", "\xf4", "\x00"], "\xdb" => ["\x01", "\xff", "\xff", "\xf4", "\x80"], "\xdc" => ["\x01", "\xff", "\xff", "\xff", "\xa0"], "\xdd" => ["\x01", "\xff", "\xff", "\xf8", "\xc0"], "\xde" => ["\x01", "\xff", "\xff", "\xf9", "\x00"], "\xdf" => ["\x01", "\xff", "\xff", "\xf9", "@"], "\xe0" => ["\x01", "\xff", "\xfd", "\x80"], "\xe1" => ["\x01", "\xff", "\xff", "\xe6"], "\xe2" => ["\x01", "\xff", "\xfd", "\xa0"], "\xe3" => ["\x01", "\xff", "\xfe", "`"], "\xe4" => ["\x01", "\xff", "\xff", "H"], "\xe5" => ["\x01", "\xff", "\xfe", "p"], "\xe6" => ["\x01", "\xff", "\xfe", "\x80"], "\xe7" => ["\x01", "\xff", "\xff", "\xcc"], "\xe8" => ["\x01", "\xff", "\xff", "P"], "\xe9" => ["\x01", "\xff", "\xff", "X"], "\xea" => ["\x01", "\xff", "\xff", "\xee"], "\xeb" => ["\x01", "\xff", "\xff", "\xef"], "\xec" => ["\x01", "\xff", "\xff", "\xe8"], "\xed" => ["\x01", "\xff", "\xff", "\xea"], "\xee" => ["\x01", "\xff", "\xff", "\xf5", "\x00"], "\xef" => ["\x01", "\xff", "\xff", "\xd0"], "\xf0" => ["\x01", "\xff", "\xff", "\xf5", "\x80"], "\xf1" => ["\x01", "\xff", "\xff", "\xf9", "\x80"], "\xf2" => ["\x01", "\xff", "\xff", "\xf6", "\x00"], "\xf3" => ["\x01", "\xff", "\xff", "\xf6", "\x80"], "\xf4" => ["\x01", "\xff", "\xff", "\xf9", "\xc0"], "\xf5" => ["\x01", "\xff", "\xff", "\xfa", "\x00"], "\xf6" => ["\x01", "\xff", "\xff", "\xfa", "@"], "\xf7" => ["\x01", "\xff", "\xff", "\xfa", "\x80"], "\xf8" => ["\x01", "\xff", "\xff", "\xfa", "\xc0"], "\xf9" => ["\x01", "\xff", "\xff", "\xff", "\xc0"], "\xfa" => ["\x01", "\xff", "\xff", "\xfb", "\x00"], "\xfb" => ["\x01", "\xff", "\xff", "\xfb", "@"], "\xfc" => ["\x01", "\xff", "\xff", "\xfb", "\x80"], "\xfd" => ["\x01", "\xff", "\xff", "\xfb", "\xc0"], "\xfe" => ["\x01", "\xff", "\xff", "\xfc", "\x00"], "\xff" => ["\x01", "\xff", "\xff", "\xf7", "\x00"]]];<?php

namespace Amp\Http;

final class HPackException extends \Exception
{
}<?php

namespace Amp\Http;

use Amp\Http\Internal\HPackNative;
use Amp\Http\Internal\HPackNghttp2;
final class HPack
{
    /** @var HPackNative|HPackNghttp2 */
    private $implementation;
    /**
     *
     */
    public function __construct(int $tableSizeLimit = 4096)
    {
        if (HPackNghttp2::isSupported()) {
            $this->implementation = new HPackNghttp2($tableSizeLimit);
        } else {
            $this->implementation = new HPackNative($tableSizeLimit);
        }
    }
    /**
     * @param string $input Input to decode.
     * @param int $maxSize Maximum deflated size.
     *
     * @return (array | null) Decoded headers.
     */
    public function decode(string $input, int $maxSize) : ?array
    {
        return $this->implementation->decode($input, $maxSize);
    }
    /**
     * @param array $headers Headers to encode.
     *
     * @return string Encoded headers.
     *
     * @throws HPackException If encoding fails.
     */
    public function encode(array $headers) : string
    {
        return $this->implementation->encode($headers);
    }
}<?php

require __DIR__ . '/../vendor/autoload.php';
$root = __DIR__ . "/../vendor/http2jp/hpack-test-case";
$paths = \glob("{$root}/*/*.json");
foreach ($paths as $path) {
    if (\basename(\dirname($path)) === "raw-data") {
        continue;
    }
    $data = \json_decode(\file_get_contents($path));
    $cases = [];
    foreach ($data->cases as $case) {
        foreach ($case->headers as &$header) {
            $header = (array) $header;
            $header = [\key($header), \current($header)];
        }
        $cases[$case->seqno] = [\hex2bin($case->wire), $case->headers];
    }
    $tests[] = $cases;
}
$minDuration = \PHP_INT_MAX;
$minOps = \PHP_INT_MAX;
for ($i = 0; $i < 10; $i++) {
    $start = \microtime(true);
    $ops = 0;
    foreach ($tests as $test) {
        $hpack = new Amp\Http\Internal\HPackNative();
        foreach ($cases as [$input, $output]) {
            $headers = $hpack->decode($input, 4096);
            $hpack->encode($headers);
            if ($headers !== $output) {
                print 'Invalid headers' . \PHP_EOL;
                exit(1);
            }
            $ops++;
        }
    }
    $duration = \microtime(true) - $start;
    $minDuration = \min($minDuration, $duration);
    $minOps = \min($ops, $minOps);
}
print "{$minOps} in {$minDuration} seconds" . \PHP_EOL;<?php

require __DIR__ . '/../../vendor/autoload.php';
use Amp\Http\HPack;
$fuzzer->setTarget(function (string $input) {
    (new HPack())->decode($input, 8192);
});
$fuzzer->setMaxLen(1024);<?php

require __DIR__ . '/../../vendor/autoload.php';
use Amp\Http\HPack;
(new HPack())->decode(\file_get_contents($argv[1]), 8192);<?php

/**
 * The MIT License (MIT).
 *
 * Copyright (c) 2017 Christian LÃ¼ck
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
// Taken from https://github.com/leproxy/leproxy/blob/e2ca7917c17ac8b853800f5b390297a2a1525cf7/compile.php
$small = '';
$all = \token_get_all(\file_get_contents($argv[1]));
// search next non-whitespace/non-comment token
$next = function ($i) use(&$all) {
    for ($i = $i + 1; !isset($all[$i]) || \is_array($all[$i]) && ($all[$i][0] === T_COMMENT || $all[$i][0] === T_DOC_COMMENT || $all[$i][0] === T_WHITESPACE); ++$i) {
    }
    return $i;
};
// search previous non-whitespace/non-comment token
$prev = function ($i) use(&$all) {
    for ($i = $i - 1; $i >= 0 && (!isset($all[$i]) || \is_array($all[$i]) && ($all[$i][0] === T_COMMENT || $all[$i][0] === T_DOC_COMMENT || $all[$i][0] === T_WHITESPACE)); --$i) {
    }
    return $i;
};
$first = true;
foreach ($all as $i => $token) {
    if (\is_array($token) && ($token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT)) {
        // remove all comments except first
        if ($first === true) {
            $first = false;
            continue;
        }
        unset($all[$i]);
    } elseif (\is_array($token) && $token[0] === T_PUBLIC) {
        // get next non-whitespace token after `public` visibility
        $token = $all[$next($i)];
        if (\is_array($token) && $token[0] === T_VARIABLE) {
            // use shorter variable notation `public $a` => `var $a`
            $all[$i] = [T_VAR, 'var'];
        } else {
            // remove unneeded public identifier `public static function a()` => `static function a()`
            unset($all[$i]);
        }
    } elseif (\is_array($token) && $token[0] === T_LNUMBER) {
        // Use shorter integer notation `0x0F` => `15` and `011` => `9`.
        // Technically, hex codes may be shorter for very large ints, but adding
        // another 2 leading chars is rarely worth it.
        // Optimizing floats is not really worth it, as they have many special
        // cases, such as e-notation and we would lose types for `0.0` => `0`.
        $all[$i][1] = (string) \intval($token[1], 0);
    } elseif (\is_array($token) && $token[0] === T_NEW) {
        // remove unneeded parenthesis for constructors without args `new a();` => `new a;`
        // jump over next token (class name), then next must be open parenthesis, followed by closing
        $open = $next($next($i));
        $close = $next($open);
        if ($all[$open] === '(' && $all[$close] === ')') {
            unset($all[$open], $all[$close]);
        }
    } elseif (\is_array($token) && $token[0] === T_STRING) {
        // replace certain functions with their shorter alias function name
        // http://php.net/manual/en/aliases.php
        static $replace = ['implode' => 'join', 'fwrite' => 'fputs', 'array_key_exists' => 'key_exists', 'current' => 'pos'];
        // check this has a replacement and "looks like" a function call
        // this works on a number of assumptions, such as not being aliased/namespaced
        if (isset($replace[$token[1]])) {
            $p = $all[$prev($i)];
            if ($all[$next($i)] === '(' && (!\is_array($p) || !\in_array($p[0], [T_FUNCTION, T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_NEW]))) {
                $all[$i][1] = $replace[$all[$i][1]];
            }
        }
    } elseif (\is_array($token) && $token[0] === T_EXIT) {
        // replace `exit` with shorter alias `die`
        // it's a language construct, not a function (see above)
        $all[$i][1] = 'die';
    } elseif (\is_array($token) && $token[0] === T_RETURN) {
        // replace `return null;` with `return;`
        $t = $next($i);
        if (\is_array($all[$t]) && $all[$t][0] === T_STRING && $all[$t][1] === 'null' && $all[$next($t)] === ';') {
            unset($all[$t]);
        }
    }
}
$all = \array_values($all);
foreach ($all as $i => $token) {
    if (\is_array($token) && $token[0] === T_WHITESPACE) {
        if (\strpos($token[1], "\n") !== false) {
            $token = \strpos("()[]<>=+-*/%|,.:?!'\"\n", \Phabel\Target\Php80\Polyfill::substr($small, -1)) === false ? "\n" : '';
        } else {
            $last = \Phabel\Target\Php80\Polyfill::substr($small, -1);
            $next = isset($all[$i + 1]) ? \Phabel\Target\Php80\Polyfill::substr(\is_array($all[$i + 1]) ? $all[$i + 1][1] : $all[$i + 1], 0, 1) : ' ';
            $token = \strpos('()[]{}<>;=+-*/%&|,.:?!@\'"
', $last) !== false || \strpos('()[]{}<>;=+-*/%&|,.:?!@\'"\\$', $next) !== false ? '' : ' ';
        }
    }
    $small .= isset($token[1]) ? $token[1] : $token;
}
\file_put_contents($argv[1], $small);{
    "name": "amphp/hpack",
    "homepage": "https://github.com/amphp/hpack",
    "description": "HTTP/2 HPack implementation.",
    "keywords": [
        "http-2",
        "hpack",
        "headers"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Bob Weinand"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master",
        "http2jp/hpack-test-case": "^1",
        "phpunit/phpunit": "^6 | ^7"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Http\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Http\\": "test"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "3.x-dev"
        }
    },
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "http2jp/hpack-test-case",
                "version": "1.0",
                "source": {
                    "url": "https://github.com/http2jp/hpack-test-case",
                    "type": "git",
                    "reference": "origin/master"
                }
            }
        }
    ]
}
<?php

namespace Amp\Socket;

use Amp\ByteStream\StreamException;
class SocketException extends StreamException
{
}<?php

namespace Amp\Socket;

use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
final class DatagramSocket
{
    public const DEFAULT_CHUNK_SIZE = 8192;
    /**
     * Create a new Datagram (UDP server) on the specified server address.
     *
     * @param string $uri URI in scheme://host:port format. UDP is assumed if no scheme is present.
     * @param (BindContext | null) $context Context options for listening.
     *
     * @return DatagramSocket
     *
     * @throws SocketException If binding to the specified URI failed.
     * @throws \Error If an invalid scheme is given.
     */
    public static function bind(string $uri, ?BindContext $context = null) : self
    {
        $context = $context ?? new BindContext();
        $scheme = \strstr($uri, '://', true);
        if ($scheme === false) {
            $uri = 'udp://' . $uri;
        } elseif ($scheme !== 'udp') {
            throw new \Error('Only udp scheme allowed for datagram creation');
        }
        $streamContext = \stream_context_create($context->toStreamContextArray());
        // Error reporting suppressed since stream_socket_server() emits an E_WARNING on failure (checked below).
        $server = @\stream_socket_server($uri, $errno, $errstr, STREAM_SERVER_BIND, $streamContext);
        if (!$server || $errno) {
            throw new SocketException(\sprintf('Could not create datagram %s: [Error: #%d] %s', $uri, $errno, $errstr), $errno);
        }
        return new self($server, $context->getChunkSize());
    }
    /** @var resource|null UDP socket resource. */
    private $socket;
    /** @var string Watcher ID. */
    private $watcher;
    /** @var SocketAddress */
    private $address;
    /** @var Deferred|null */
    private $reader;
    /** @var int */
    private $chunkSize;
    /**
     * @param resource $socket A bound udp socket resource
     * @param int $chunkSize Maximum chunk size for the
     *
     * @throws \Error If a stream resource is not given for $socket.
     */
    public function __construct($socket, int $chunkSize = self::DEFAULT_CHUNK_SIZE)
    {
        if (!\is_resource($socket) || \get_resource_type($socket) !== 'stream') {
            throw new \Error('Invalid resource given to constructor!');
        }
        $this->socket = $socket;
        $this->address = SocketAddress::fromLocalResource($socket);
        $this->chunkSize =& $chunkSize;
        \stream_set_blocking($this->socket, false);
        $reader =& $this->reader;
        $this->watcher = Loop::onReadable($this->socket, static function ($watcher, $socket) use(&$reader, &$chunkSize) {
            $deferred = $reader;
            $reader = null;
            \assert($deferred !== null);
            $data = @\stream_socket_recvfrom($socket, $chunkSize, 0, $address);
            /** @psalm-suppress TypeDoesNotContainType */
            if ($data === false) {
                Loop::cancel($watcher);
                $deferred->resolve();
                return;
            }
            $deferred->resolve([SocketAddress::fromSocketName($address), $data]);
            /** @psalm-suppress RedundantCondition Resolution of the deferred above might read immediately again */
            if (!$reader) {
                Loop::disable($watcher);
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     * Automatically cancels the loop watcher.
     */
    public function __destruct()
    {
        if (!$this->socket) {
            return;
        }
        $this->free();
    }
    /**
     * @return Promise<(array{0: SocketAddress, 1: string} | null)> Resolves with null if the socket is closed.
     *
     * @throws PendingReceiveError If a receive request is already pending.
     */
    public function receive() : Promise
    {
        if ($this->reader) {
            throw new PendingReceiveError();
        }
        if (!$this->socket) {
            return new Success();
            // Resolve with null when endpoint is closed.
        }
        $this->reader = new Deferred();
        Loop::enable($this->watcher);
        return $this->reader->promise();
    }
    /**
     * @param SocketAddress $address
     * @param string $data
     *
     * @return Promise<int> Resolves with the number of bytes written to the socket.
     *
     * @throws SocketException If the UDP socket closes before the data can be sent.
     */
    public function send(SocketAddress $address, string $data) : Promise
    {
        if (!$this->socket) {
            return new Failure(new SocketException('The endpoint is not writable'));
        }
        try {
            try {
                \set_error_handler(static function (int $errno, string $errstr) {
                    throw new SocketException(\sprintf('Could not send packet on endpoint: %s', $errstr));
                });
                $result = \stream_socket_sendto($this->socket, $data, 0, $address->toString());
                /** @psalm-suppress TypeDoesNotContainType */
                if ($result < 0 || $result === false) {
                    throw new SocketException('Could not send packet on endpoint: Unknown error');
                }
            } finally {
                \restore_error_handler();
            }
        } catch (SocketException $e) {
            return new Failure($e);
        }
        return new Success($result);
    }
    /**
     * Raw stream socket resource.
     *
     * @return (resource | null)
     */
    public final function getResource()
    {
        return $this->socket;
    }
    /**
     * References the receive watcher.
     *
     * @see Loop::reference()
     */
    public final function reference() : void
    {
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the receive watcher.
     *
     * @see Loop::unreference()
     */
    public final function unreference() : void
    {
        Loop::unreference($this->watcher);
    }
    /**
     * Closes the datagram socket and stops receiving data. Any pending read is resolved with null.
     */
    public function close() : void
    {
        if ($this->socket) {
            /** @psalm-suppress InvalidPropertyAssignmentValue */
            \fclose($this->socket);
        }
        $this->free();
    }
    /**
     * @return bool
     */
    public function isClosed() : bool
    {
        return $this->socket === null;
    }
    /**
     * @return SocketAddress
     */
    public function getAddress() : SocketAddress
    {
        return $this->address;
    }
    /**
     * @param int $chunkSize The new maximum packet size to receive.
     */
    public function setChunkSize(int $chunkSize) : void
    {
        $this->chunkSize = $chunkSize;
    }
    /**
     *
     */
    private function free() : void
    {
        Loop::cancel($this->watcher);
        $this->socket = null;
        if ($this->reader) {
            $this->reader->resolve();
            $this->reader = null;
        }
    }
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use Amp\Struct;
use Amp\Success;
use League\Uri;
use function Amp\call;
/**
 * SocketPool implementation that doesn't impose any limits on concurrent open connections.
 */
final class UnlimitedSocketPool implements SocketPool
{
    private const ALLOWED_SCHEMES = ['tcp' => null, 'unix' => null];
    /** @var object[][] */
    private $sockets = [];
    /** @var string[] */
    private $objectIdCacheKeyMap = [];
    /** @var int[] */
    private $pendingCount = [];
    /** @var int */
    private $idleTimeout;
    /** @var Connector */
    private $connector;
    /**
     *
     */
    public function __construct(int $idleTimeout = 10000, ?Connector $connector = null)
    {
        $this->idleTimeout = $idleTimeout;
        $this->connector = $connector ?? connector();
    }
    /**
     * @inheritdoc
     */
    public function checkout(string $uri, ConnectContext $context = null, CancellationToken $token = null) : Promise
    {
        // A request might already be cancelled before we reach the checkout, so do not even attempt to checkout in that
        // case. The weird logic is required to throw the token's exception instead of creating a new one.
        if ($token && $token->isRequested()) {
            try {
                $token->throwIfRequested();
            } catch (CancelledException $e) {
                return new Failure($e);
            }
        }
        [$uri, $fragment] = $this->normalizeUri($uri);
        $cacheKey = $uri;
        if ($context && ($tlsContext = $context->getTlsContext())) {
            $cacheKey .= ' + ' . \serialize($tlsContext->toStreamContextArray());
        }
        if ($fragment !== null) {
            $cacheKey .= ' # ' . $fragment;
        }
        if (empty($this->sockets[$cacheKey])) {
            return $this->checkoutNewSocket($uri, $cacheKey, $context, $token);
        }
        foreach ($this->sockets[$cacheKey] as $socketId => $socket) {
            if (!$socket->isAvailable) {
                continue;
            }
            if ($socket->object instanceof ResourceSocket) {
                $resource = $socket->object->getResource();
                if (!$resource || !\is_resource($resource) || \feof($resource)) {
                    $this->clearFromId(\spl_object_hash($socket->object));
                    continue;
                }
            } elseif ($socket->object->isClosed()) {
                $this->clearFromId(\spl_object_hash($socket->object));
                continue;
            }
            $socket->isAvailable = false;
            if ($socket->idleWatcher !== null) {
                Loop::disable($socket->idleWatcher);
            }
            return new Success($socket->object);
        }
        return $this->checkoutNewSocket($uri, $cacheKey, $context, $token);
    }
    /**
     * @inheritdoc
     */
    public function clear(EncryptableSocket $socket) : void
    {
        $this->clearFromId(\spl_object_hash($socket));
    }
    /**
     * @inheritdoc
     */
    public function checkin(EncryptableSocket $socket) : void
    {
        $objectId = \spl_object_hash($socket);
        if (!isset($this->objectIdCacheKeyMap[$objectId])) {
            throw new \Error(\sprintf('Unknown socket: %d', $objectId));
        }
        $cacheKey = $this->objectIdCacheKeyMap[$objectId];
        if ($socket instanceof ResourceSocket) {
            $resource = $socket->getResource();
            if (!$resource || !\is_resource($resource) || \feof($resource)) {
                $this->clearFromId(\spl_object_hash($socket));
                return;
            }
        } elseif ($socket->isClosed()) {
            $this->clearFromId(\spl_object_hash($socket));
            return;
        }
        $socket = $this->sockets[$cacheKey][$objectId];
        $socket->isAvailable = true;
        if (isset($socket->idleWatcher)) {
            Loop::enable($socket->idleWatcher);
        } else {
            $socket->idleWatcher = Loop::delay($this->idleTimeout, function () use($socket) {
                $this->clearFromId(\spl_object_hash($socket->object));
            });
            Loop::unreference($socket->idleWatcher);
        }
    }
    /**
     * @param string $uri
     *
     * @return array
     *
     * @throws SocketException
     */
    private function normalizeUri(string $uri) : array
    {
        if (\stripos($uri, 'unix://') === 0) {
            return \explode('#', $uri) + [null, null];
        }
        try {
            $parts = Uri\parse($uri);
        } catch (\Exception $exception) {
            throw new SocketException('Could not parse URI', 0, $exception);
        }
        if ($parts['scheme'] === null) {
            throw new SocketException('Invalid URI for socket pool; no scheme given');
        }
        $port = $parts['port'] ?? 0;
        if ($port === 0 || $parts['host'] === null) {
            throw new SocketException('Invalid URI for socket pool; missing host or port');
        }
        $scheme = \strtolower($parts['scheme']);
        $host = \strtolower($parts['host']);
        if (!\array_key_exists($scheme, self::ALLOWED_SCHEMES)) {
            throw new SocketException(\sprintf("Invalid URI for socket pool; '%s' scheme not allowed - scheme must be one of %s", $scheme, \implode(', ', \array_keys(self::ALLOWED_SCHEMES))));
        }
        if ($parts['query'] !== null) {
            throw new SocketException('Invalid URI for socket pool; query component not allowed');
        }
        if ($parts['path'] !== '') {
            throw new SocketException('Invalid URI for socket pool; path component must be empty');
        }
        if ($parts['user'] !== null) {
            throw new SocketException('Invalid URI for socket pool; user component not allowed');
        }
        return [$scheme . '://' . $host . ':' . $port, $parts['fragment']];
    }
    /**
     *
     */
    private function checkoutNewSocket(string $uri, string $cacheKey, ConnectContext $connectContext = null, CancellationToken $token = null) : Promise
    {
        return call(function () use($uri, $cacheKey, $connectContext, $token) {
            $this->pendingCount[$uri] = ($this->pendingCount[$uri] ?? 0) + 1;
            try {
                /** @var EncryptableSocket $socket */
                $socket = (yield $this->connector->connect($uri, $connectContext, $token));
            } finally {
                if (--$this->pendingCount[$uri] === 0) {
                    unset($this->pendingCount[$uri]);
                }
            }
            /** @psalm-suppress MissingConstructor */
            $socketEntry = new class
            {
                use Struct;
                /** @var string */
                public $uri;
                /** @var EncryptableSocket */
                public $object;
                /** @var bool */
                public $isAvailable;
                /** @var string|null */
                public $idleWatcher;
            };
            $socketEntry->uri = $uri;
            $socketEntry->isAvailable = false;
            $socketEntry->object = $socket;
            $objectId = \spl_object_hash($socket);
            $this->sockets[$cacheKey][$objectId] = $socketEntry;
            $this->objectIdCacheKeyMap[$objectId] = $cacheKey;
            return $socket;
        });
    }
    /**
     *
     */
    private function clearFromId(string $objectId) : void
    {
        if (!isset($this->objectIdCacheKeyMap[$objectId])) {
            throw new \Error(\sprintf('Unknown socket: %d', $objectId));
        }
        $cacheKey = $this->objectIdCacheKeyMap[$objectId];
        $socket = $this->sockets[$cacheKey][$objectId];
        if ($socket->idleWatcher) {
            Loop::cancel($socket->idleWatcher);
        }
        unset($this->sockets[$cacheKey][$objectId], $this->objectIdCacheKeyMap[$objectId]);
        if (empty($this->sockets[$cacheKey])) {
            unset($this->sockets[$cacheKey]);
        }
    }
}<?php

namespace Amp\Socket\Internal;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Socket\TlsException;
use Amp\Success;
use League\Uri;
use function Amp\call;
/**
 * Parse an URI into [scheme, host, port].
 *
 * @param string $uri
 *
 * @return array
 *
 * @throws \Error If an invalid URI has been passed.
 *
 * @internal
 */
function parseUri(string $uri) : array
{
    if (\stripos($uri, 'unix://') === 0 || \stripos($uri, 'udg://') === 0) {
        [$scheme, $path] = \explode('://', $uri, 2);
        return [$scheme, \ltrim($path, '/'), 0];
    }
    if (\strpos($uri, '://') === false) {
        // Set a default scheme of tcp if none was given.
        $uri = 'tcp://' . $uri;
    }
    try {
        $uriParts = Uri\parse($uri);
    } catch (\Exception $exception) {
        throw new \Error("Invalid URI: {$uri}", 0, $exception);
    }
    $scheme = $uriParts['scheme'];
    $host = $uriParts['host'] ?? '';
    $port = $uriParts['port'] ?? 0;
    if (!\in_array($scheme, ['tcp', 'udp', 'unix', 'udg'], true)) {
        throw new \Error("Invalid URI scheme ({$scheme}); tcp, udp, unix or udg scheme expected");
    }
    if ($host === '' || $port === 0) {
        throw new \Error("Invalid URI: {$uri}; host and port components required");
    }
    if (\strpos($host, ':') !== false) {
        // IPv6 address
        $host = \sprintf('[%s]', \trim($host, '[]'));
    }
    return [$scheme, $host, $port];
}
/**
 * Enable encryption on an existing socket stream.
 *
 * @param resource $socket
 * @param array $options
 * @param CancellationToken $cancellationToken
 *
 * @return Promise<void>
 *
 * @internal
 */
function setupTls($socket, array $options, ?CancellationToken $cancellationToken) : Promise
{
    $cancellationToken = $cancellationToken ?? new NullCancellationToken();
    if (isset(\stream_get_meta_data($socket)['crypto'])) {
        return new Failure(new TlsException("Can't setup TLS, because it has already been set up"));
    }
    \error_clear_last();
    \stream_context_set_option($socket, $options);
    try {
        \set_error_handler(static function (int $errno, string $errstr) {
            new TlsException('TLS negotiation failed: ' . $errstr);
        });
        $result = \stream_socket_enable_crypto($socket, $enable = true);
        if ($result === false) {
            throw new TlsException('TLS negotiation failed: Unknown error');
        }
    } catch (TlsException $e) {
        return new Failure($e);
    } finally {
        \restore_error_handler();
    }
    // Yes, that function can return true / false / 0, don't use weak comparisons.
    if ($result === true) {
        /** @psalm-suppress InvalidReturnStatement */
        return new Success();
    }
    return call(static function () use($socket, $cancellationToken) {
        $cancellationToken->throwIfRequested();
        $deferred = new Deferred();
        // Watcher is guaranteed to be created, because we throw above if cancellation has already been requested
        $id = $cancellationToken->subscribe(static function ($e) use($deferred, &$watcher) {
            Loop::cancel($watcher);
            $deferred->fail($e);
        });
        $watcher = Loop::onReadable($socket, static function (string $watcher, $socket, Deferred $deferred) use($cancellationToken, $id) {
            try {
                try {
                    \set_error_handler(static function (int $errno, string $errstr) use($socket) {
                        if (\feof($socket)) {
                            $errstr = 'Connection reset by peer';
                        }
                        throw new TlsException('TLS negotiation failed: ' . $errstr);
                    });
                    $result = \stream_socket_enable_crypto($socket, true);
                    if ($result === false) {
                        $message = \feof($socket) ? 'Connection reset by peer' : 'Unknown error';
                        throw new TlsException('TLS negotiation failed: ' . $message);
                    }
                } finally {
                    \restore_error_handler();
                }
            } catch (TlsException $e) {
                Loop::cancel($watcher);
                $cancellationToken->unsubscribe($id);
                $deferred->fail($e);
                return;
            }
            // If $result is 0, just wait for the next invocation
            if ($result === true) {
                Loop::cancel($watcher);
                $cancellationToken->unsubscribe($id);
                $deferred->resolve();
            }
        }, $deferred);
        return $deferred->promise();
    });
}
/**
 * Disable encryption on an existing socket stream.
 *
 * @param resource $socket
 *
 * @return Promise<void>
 *
 * @internal
 * @psalm-suppress InvalidReturnType
 */
function shutdownTls($socket) : Promise
{
    // note that disabling crypto *ALWAYS* returns false, immediately
    // don't set _enabled to false, TLS can be setup only once
    @\stream_socket_enable_crypto($socket, false);
    /** @psalm-suppress InvalidReturnStatement */
    return new Success();
}
/**
 * Normalizes "bindto" options to add a ":0" in case no port is present, otherwise PHP will silently ignore those.
 *
 * @param (string | null) $bindTo
 *
 * @return (string | null)
 *
 * @throws \Error If an invalid option has been passed.
 */
function normalizeBindToOption(string $bindTo = null)
{
    if ($bindTo === null) {
        return null;
    }
    if (\preg_match("/\\[(?P<ip>[0-9a-f:]+)\\](:(?P<port>\\d+))?\$/", $bindTo, $match)) {
        $ip = $match['ip'];
        $port = $match['port'] ?? 0;
        if (@\inet_pton($ip) === false) {
            throw new \Error("Invalid IPv6 address: {$ip}");
        }
        if ($port < 0 || $port > 65535) {
            throw new \Error("Invalid port: {$port}");
        }
        return "[{$ip}]:{$port}";
    }
    if (\preg_match("/(?P<ip>\\d+\\.\\d+\\.\\d+\\.\\d+)(:(?P<port>\\d+))?\$/", $bindTo, $match)) {
        $ip = $match['ip'];
        $port = $match['port'] ?? 0;
        if (@\inet_pton($ip) === false) {
            throw new \Error("Invalid IPv4 address: {$ip}");
        }
        if ($port < 0 || $port > 65535) {
            throw new \Error("Invalid port: {$port}");
        }
        return "{$ip}:{$port}";
    }
    throw new \Error("Invalid bindTo value: {$bindTo}");
}
/**
 * Cleans up return values of stream_socket_get_name.
 *
 * @param (string | false) $address
 *
 * @return (string | null)
 */
function cleanupSocketName($address)
{
    // https://3v4l.org/5C1lo
    if ($address === false || $address === "\x00") {
        return null;
    }
    // Check if this is an IPv6 address which includes multiple colons but no square brackets
    // @see https://github.com/reactphp/socket/blob/v0.8.10/src/TcpServer.php#L179-L184
    // @license https://github.com/reactphp/socket/blob/v0.8.10/LICENSE
    $pos = \strrpos($address, ':');
    if ($pos !== false && \strpos($address, ':') < $pos && $address[0] !== '[') {
        $port = \Phabel\Target\Php80\Polyfill::substr($address, $pos + 1);
        $address = '[' . \Phabel\Target\Php80\Polyfill::substr($address, 0, $pos) . ']:' . $port;
    }
    // -- End of imported code ----- //
    return $address;
}<?php

namespace Amp\Socket;

use Kelunik\Certificate\Certificate;
/**
 * Exposes a connection's negotiated TLS parameters.
 */
final class TlsInfo
{
    /** @var string */
    private $version;
    /** @var string */
    private $cipherName;
    /** @var int */
    private $cipherBits;
    /** @var string */
    private $cipherVersion;
    /** @var string|null */
    private $alpnProtocol;
    /** @var array|null */
    private $certificates;
    /** @var Certificate[]|null */
    private $parsedCertificates;
    /**
     * Constructs a new instance from a stream socket resource.
     *
     * @param resource $resource Stream socket resource.
     *
     * @return (self | null) Returns null if TLS is not enabled on the stream socket.
     */
    public static function fromStreamResource($resource) : ?self
    {
        if (!\is_resource($resource) || \get_resource_type($resource) !== 'stream') {
            throw new \Error("Expected a valid stream resource");
        }
        $metadata = \stream_get_meta_data($resource)['crypto'] ?? [];
        $tlsContext = \stream_context_get_options($resource)['ssl'] ?? [];
        return empty($metadata) ? null : self::fromMetaData($metadata, $tlsContext);
    }
    /**
     * Constructs a new instance from PHP's internal info.
     *
     * Always pass the info as obtained from PHP as this method might extract additional fields in the future.
     *
     * @param array $cryptoInfo Crypto info obtained via `stream_get_meta_data($socket->getResource())["crypto"]`.
     * @param array $tlsContext Context obtained via `stream_context_get_options($socket->getResource())["ssl"])`.
     *
     * @return self
     */
    public static function fromMetaData(array $cryptoInfo, array $tlsContext) : self
    {
        if (isset($tlsContext["peer_certificate"])) {
            $certificates = \array_merge([$tlsContext["peer_certificate"]], $tlsContext["peer_certificate_chain"] ?? []);
        } else {
            $certificates = $tlsContext["peer_certificate_chain"] ?? [];
        }
        return new self($cryptoInfo["protocol"], $cryptoInfo["cipher_name"], $cryptoInfo["cipher_bits"], $cryptoInfo["cipher_version"], $cryptoInfo["alpn_protocol"] ?? null, empty($certificates) ? null : $certificates);
    }
    /**
     *
     */
    private function __construct(string $version, string $cipherName, int $cipherBits, string $cipherVersion, ?string $alpnProtocol, ?array $certificates)
    {
        $this->version = $version;
        $this->cipherName = $cipherName;
        $this->cipherBits = $cipherBits;
        $this->cipherVersion = $cipherVersion;
        $this->alpnProtocol = $alpnProtocol;
        $this->certificates = $certificates;
    }
    /**
     *
     */
    public function getVersion() : string
    {
        return $this->version;
    }
    /**
     *
     */
    public function getCipherName() : string
    {
        return $this->cipherName;
    }
    /**
     *
     */
    public function getCipherBits() : int
    {
        return $this->cipherBits;
    }
    /**
     *
     */
    public function getCipherVersion() : string
    {
        return $this->cipherVersion;
    }
    /**
     *
     */
    public function getApplicationLayerProtocol() : ?string
    {
        return $this->alpnProtocol;
    }
    /**
     * @return Certificate[]
     *
     * @throws SocketException If peer certificates were not captured.
     */
    public function getPeerCertificates() : array
    {
        if ($this->certificates === null) {
            throw new SocketException("Peer certificates not captured; use ClientTlsContext::withPeerCapturing() to capture peer certificates");
        }
        if ($this->parsedCertificates === null) {
            $this->parsedCertificates = \array_map(static function ($resource) {
                return new Certificate($resource);
            }, $this->certificates);
        }
        return $this->parsedCertificates;
    }
}<?php

namespace Amp\Socket;

use Amp\Dns\Record;
use function Amp\Socket\Internal\normalizeBindToOption;
final class ConnectContext
{
    /** @var string|null */
    private $bindTo;
    /** @var int */
    private $connectTimeout = 10000;
    /** @var int */
    private $maxAttempts = 2;
    /** @var null|int */
    private $typeRestriction;
    /** @var bool */
    private $tcpNoDelay = false;
    /** @var ClientTlsContext|null */
    private $tlsContext;
    /**
     *
     */
    public function withoutBindTo() : self
    {
        return $this->withBindTo(null);
    }
    /**
     *
     */
    public function withBindTo(?string $bindTo) : self
    {
        $bindTo = normalizeBindToOption($bindTo);
        $clone = clone $this;
        $clone->bindTo = $bindTo;
        return $clone;
    }
    /**
     *
     */
    public function getBindTo() : ?string
    {
        return $this->bindTo;
    }
    /**
     *
     */
    public function withConnectTimeout(int $timeout) : self
    {
        if ($timeout <= 0) {
            throw new \Error("Invalid connect timeout ({$timeout}), must be greater than 0");
        }
        $clone = clone $this;
        $clone->connectTimeout = $timeout;
        return $clone;
    }
    /**
     *
     */
    public function getConnectTimeout() : int
    {
        return $this->connectTimeout;
    }
    /**
     *
     */
    public function withMaxAttempts(int $maxAttempts) : self
    {
        if ($maxAttempts <= 0) {
            throw new \Error("Invalid max attempts ({$maxAttempts}), must be greater than 0");
        }
        $clone = clone $this;
        $clone->maxAttempts = $maxAttempts;
        return $clone;
    }
    /**
     *
     */
    public function getMaxAttempts() : int
    {
        return $this->maxAttempts;
    }
    /**
     *
     */
    public function withoutDnsTypeRestriction() : self
    {
        return $this->withDnsTypeRestriction(null);
    }
    /**
     *
     */
    public function withDnsTypeRestriction(?int $type) : self
    {
        if ($type !== null && $type !== Record::AAAA && $type !== Record::A) {
            throw new \Error('Invalid resolver type restriction');
        }
        $clone = clone $this;
        $clone->typeRestriction = $type;
        return $clone;
    }
    /**
     *
     */
    public function getDnsTypeRestriction() : ?int
    {
        return $this->typeRestriction;
    }
    /**
     *
     */
    public function hasTcpNoDelay() : bool
    {
        return $this->tcpNoDelay;
    }
    /**
     *
     */
    public function withTcpNoDelay() : self
    {
        $clone = clone $this;
        $clone->tcpNoDelay = true;
        return $clone;
    }
    /**
     *
     */
    public function withoutTcpNoDelay() : self
    {
        $clone = clone $this;
        $clone->tcpNoDelay = false;
        return $clone;
    }
    /**
     *
     */
    public function withoutTlsContext() : self
    {
        return $this->withTlsContext(null);
    }
    /**
     *
     */
    public function withTlsContext(?ClientTlsContext $tlsContext) : self
    {
        $clone = clone $this;
        $clone->tlsContext = $tlsContext;
        return $clone;
    }
    /**
     *
     */
    public function getTlsContext() : ?ClientTlsContext
    {
        return $this->tlsContext;
    }
    /**
     *
     */
    public function toStreamContextArray() : array
    {
        $options = ['tcp_nodelay' => $this->tcpNoDelay];
        if ($this->bindTo !== null) {
            $options['bindto'] = $this->bindTo;
        }
        $array = ['socket' => $options];
        if ($this->tlsContext) {
            $array = \array_merge($array, $this->tlsContext->toStreamContextArray());
        }
        return $array;
    }
}<?php

namespace Amp\Socket;

/**
 * Thrown if TLS can't be properly negotiated or is not supported on the given socket.
 */
class TlsException extends SocketException
{
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\Promise;
interface Connector
{
    /**
     * Asynchronously establish a socket connection to the specified URI.
     *
     * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
     * @param ConnectContext $context Socket connect context to use when connecting.
     * @param (CancellationToken | null) $token
     *
     * @return Promise<EncryptableSocket>
     *
     * @throws ConnectException
     * @throws CancelledException
     */
    public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null) : Promise;
}<?php

namespace Amp\Socket;

/**
 * Thrown in case a second read operation is attempted while another receive operation is still pending.
 */
final class PendingReceiveError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = 'The previous receive operation must complete before receive can be called again', int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Socket;

final class ServerTlsContext
{
    public const TLSv1_0 = \STREAM_CRYPTO_METHOD_TLSv1_0_SERVER;
    public const TLSv1_1 = \STREAM_CRYPTO_METHOD_TLSv1_1_SERVER;
    public const TLSv1_2 = \STREAM_CRYPTO_METHOD_TLSv1_2_SERVER;
    public const TLSv1_3 = \PHP_VERSION_ID >= 70400 ? \STREAM_CRYPTO_METHOD_TLSv1_3_SERVER : 0;
    private const TLS_VERSIONS = \PHP_VERSION_ID >= 70400 ? ['TLSv1.0' => self::TLSv1_0, 'TLSv1.1' => self::TLSv1_1, 'TLSv1.2' => self::TLSv1_2, 'TLSv1.3' => self::TLSv1_3] : ['TLSv1.0' => self::TLSv1_0, 'TLSv1.1' => self::TLSv1_1, 'TLSv1.2' => self::TLSv1_2];
    /** @var int */
    private $minVersion = self::TLSv1_0;
    /** @var null|string */
    private $peerName;
    /** @var bool */
    private $verifyPeer = false;
    /** @var int */
    private $verifyDepth = 10;
    /** @var null|string */
    private $ciphers;
    /** @var null|string */
    private $caFile;
    /** @var null|string */
    private $caPath;
    /** @var bool */
    private $capturePeer = false;
    /** @var null|Certificate */
    private $defaultCertificate;
    /** @var Certificate[] */
    private $certificates = [];
    /** @var int */
    private $securityLevel = 2;
    /** @var string[] */
    private $alpnProtocols = [];
    /**
     * Minimum TLS version to negotiate.
     *
     * Defaults to TLS 1.0.
     *
     * @param int $version One of the `ServerTlsContext::TLSv*` constants.
     *
     * @return self Cloned, modified instance.
     * @throws \Error If an invalid minimum version is given.
     */
    public function withMinimumVersion(int $version) : self
    {
        if (!\in_array($version, self::TLS_VERSIONS, true)) {
            throw new \Error(\sprintf('Invalid minimum version, only %s allowed', implode(', ', \array_keys(self::TLS_VERSIONS))));
        }
        $clone = clone $this;
        $clone->minVersion = $version;
        return $clone;
    }
    /**
     * Returns the minimum TLS version to negotiate.
     *
     * @return int
     */
    public function getMinimumVersion() : int
    {
        return $this->minVersion;
    }
    /**
     * Expected name of the peer.
     *
     * @param (string | null) $peerName
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerName(string $peerName = null) : self
    {
        $clone = clone $this;
        $clone->peerName = $peerName;
        return $clone;
    }
    /**
     * @return (null | string) Expected name of the peer or `null` if such an expectation doesn't exist.
     */
    public function getPeerName() : ?string
    {
        return $this->peerName;
    }
    /**
     * Enable peer verification.
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerVerification() : self
    {
        $clone = clone $this;
        $clone->verifyPeer = true;
        return $clone;
    }
    /**
     * Disable peer verification, this is the default for servers.
     *
     * @return self Cloned, modified instance.
     */
    public function withoutPeerVerification() : self
    {
        $clone = clone $this;
        $clone->verifyPeer = false;
        return $clone;
    }
    /**
     * @return bool Whether peer verification is enabled.
     */
    public function hasPeerVerification() : bool
    {
        return $this->verifyPeer;
    }
    /**
     * Maximum chain length the peer might present including the certificates in the local trust store.
     *
     * @param int $verifyDepth Maximum length of the certificate chain.
     *
     * @return self Cloned, modified instance.
     */
    public function withVerificationDepth(int $verifyDepth) : self
    {
        if ($verifyDepth < 0) {
            throw new \Error("Invalid verification depth ({$verifyDepth}), must be greater than or equal to 0");
        }
        $clone = clone $this;
        $clone->verifyDepth = $verifyDepth;
        return $clone;
    }
    /**
     * @return int Maximum length of the certificate chain.
     */
    public function getVerificationDepth() : int
    {
        return $this->verifyDepth;
    }
    /**
     * List of ciphers to negotiate, the server's order is always preferred.
     *
     * @param (string | null) $ciphers List of ciphers in OpenSSL's format (colon separated).
     *
     * @return self Cloned, modified instance.
     */
    public function withCiphers(string $ciphers = null) : self
    {
        $clone = clone $this;
        $clone->ciphers = $ciphers;
        return $clone;
    }
    /**
     * @return string List of ciphers in OpenSSL's format (colon separated).
     */
    public function getCiphers() : string
    {
        return $this->ciphers ?? \OPENSSL_DEFAULT_STREAM_CIPHERS;
    }
    /**
     * CAFile to check for trusted certificates.
     *
     * @param (string | null) $cafile Path to the file or `null` to unset.
     *
     * @return self Cloned, modified instance.
     */
    public function withCaFile(string $cafile = null) : self
    {
        $clone = clone $this;
        $clone->caFile = $cafile;
        return $clone;
    }
    /**
     * @return (null | string) Path to the file if one is set, otherwise `null`.
     */
    public function getCaFile() : ?string
    {
        return $this->caFile;
    }
    /**
     * CAPath to check for trusted certificates.
     *
     * @param (string | null) $capath Path to the file or `null` to unset.
     *
     * @return self Cloned, modified instance.
     */
    public function withCaPath(string $capath = null) : self
    {
        $clone = clone $this;
        $clone->caPath = $capath;
        return $clone;
    }
    /**
     * @return (null | string) Path to the file if one is set, otherwise `null`.
     */
    public function getCaPath() : ?string
    {
        return $this->caPath;
    }
    /**
     * Capture the certificates sent by the peer.
     *
     * Note: This is the chain as sent by the peer, NOT the verified chain.
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerCapturing() : self
    {
        $clone = clone $this;
        $clone->capturePeer = true;
        return $clone;
    }
    /**
     * Don't capture the certificates sent by the peer.
     *
     * @return self Cloned, modified instance.
     */
    public function withoutPeerCapturing() : self
    {
        $clone = clone $this;
        $clone->capturePeer = false;
        return $clone;
    }
    /**
     * @return bool Whether to capture the certificates sent by the peer.
     */
    public function hasPeerCapturing() : bool
    {
        return $this->capturePeer;
    }
    /**
     * Default certificate to use in case no SNI certificate matches.
     *
     * @param (Certificate | null) $defaultCertificate
     *
     * @return self Cloned, modified instance.
     */
    public function withDefaultCertificate(Certificate $defaultCertificate = null) : self
    {
        $clone = clone $this;
        $clone->defaultCertificate = $defaultCertificate;
        return $clone;
    }
    /**
     * @return (Certificate | null) Default certificate to use in case no SNI certificate matches, or `null` if unset.
     */
    public function getDefaultCertificate() : ?Certificate
    {
        return $this->defaultCertificate;
    }
    /**
     * Certificates to use for the given host names.
     *
     * @param array $certificates Must be a associative array mapping hostnames to certificate instances.
     *
     * @return self Cloned, modified instance.
     */
    public function withCertificates(array $certificates) : self
    {
        foreach ($certificates as $key => $certificate) {
            if (!\is_string($key)) {
                throw new \TypeError('Expected an array mapping domain names to Certificate instances');
            }
            if (!$certificate instanceof Certificate) {
                throw new \TypeError('Expected an array of Certificate instances');
            }
            if (\PHP_VERSION_ID < 70200 && $certificate->getCertFile() !== $certificate->getKeyFile()) {
                throw new \Error('Different files for cert and key are not supported on this version of PHP. Please upgrade to PHP 7.2 or later.');
            }
        }
        $clone = clone $this;
        $clone->certificates = $certificates;
        return $clone;
    }
    /**
     * @return array Associative array mapping hostnames to certificate instances.
     */
    public function getCertificates() : array
    {
        return $this->certificates;
    }
    /**
     * Security level to use.
     *
     * Requires OpenSSL 1.1.0 or higher.
     *
     * @param int $level Must be between 0 and 5.
     *
     * @return self Cloned, modified instance.
     */
    public function withSecurityLevel(int $level) : self
    {
        // See https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_security_level.html
        // Level 2 is not recommended, because of SHA-1 by that document,
        // but SHA-1 should be phased out now on general internet use.
        // We therefore default to level 2.
        if ($level < 0 || $level > 5) {
            throw new \Error("Invalid security level ({$level}), must be between 0 and 5.");
        }
        if (!hasTlsSecurityLevelSupport()) {
            throw new \Error("Can't set a security level, as PHP is compiled with OpenSSL < 1.1.0.");
        }
        $clone = clone $this;
        $clone->securityLevel = $level;
        return $clone;
    }
    /**
     * @return int Security level between 0 and 5. Always 0 for OpenSSL < 1.1.0.
     */
    public function getSecurityLevel() : int
    {
        // 0 is equivalent to previous versions of OpenSSL and just does nothing
        if (!hasTlsSecurityLevelSupport()) {
            return 0;
        }
        return $this->securityLevel;
    }
    /**
     * @param string[] $protocols
     *
     * @return self Cloned, modified instance.
     */
    public function withApplicationLayerProtocols(array $protocols) : self
    {
        if (!hasTlsAlpnSupport()) {
            throw new \Error("Can't set an application layer protocol list, as PHP is compiled with OpenSSL < 1.0.2.");
        }
        foreach ($protocols as $protocol) {
            if (!\is_string($protocol)) {
                throw new \TypeError("Protocol names must be strings");
            }
        }
        $clone = clone $this;
        $clone->alpnProtocols = $protocols;
        return $clone;
    }
    /**
     * @return string[]
     */
    public function getApplicationLayerProtocols() : array
    {
        return $this->alpnProtocols;
    }
    /**
     * Converts this TLS context into PHP's equivalent stream context array.
     *
     * @return array Stream context array compatible with PHP's streams.
     */
    public function toStreamContextArray() : array
    {
        $options = ['crypto_method' => $this->toStreamCryptoMethod(), 'peer_name' => $this->peerName, 'verify_peer' => $this->verifyPeer, 'verify_peer_name' => $this->verifyPeer, 'verify_depth' => $this->verifyDepth, 'ciphers' => $this->ciphers ?? \OPENSSL_DEFAULT_STREAM_CIPHERS, 'honor_cipher_order' => true, 'single_dh_use' => true, 'no_ticket' => true, 'capture_peer_cert' => $this->capturePeer, 'capture_peer_chain' => $this->capturePeer];
        if (!empty($this->alpnProtocols)) {
            $options['alpn_protocols'] = \implode(',', $this->alpnProtocols);
        }
        if ($this->defaultCertificate !== null) {
            $options['local_cert'] = $this->defaultCertificate->getCertFile();
            if ($this->defaultCertificate->getCertFile() !== $this->defaultCertificate->getKeyFile()) {
                $options['local_pk'] = $this->defaultCertificate->getKeyFile();
            }
        }
        if ($this->certificates) {
            $options['SNI_server_certs'] = \array_map(static function (Certificate $certificate) {
                if ($certificate->getCertFile() === $certificate->getKeyFile()) {
                    return $certificate->getCertFile();
                }
                return ['local_cert' => $certificate->getCertFile(), 'local_pk' => $certificate->getKeyFile()];
            }, $this->certificates);
        }
        if ($this->caFile !== null) {
            $options['cafile'] = $this->caFile;
        }
        if ($this->caPath !== null) {
            $options['capath'] = $this->caPath;
        }
        if (\OPENSSL_VERSION_NUMBER >= 0x10100000) {
            $options['security_level'] = $this->securityLevel;
        }
        return ['ssl' => $options];
    }
    /**
     * @return int Crypto method compatible with PHP's streams.
     */
    public function toStreamCryptoMethod() : int
    {
        switch ($this->minVersion) {
            case self::TLSv1_0:
                return self::TLSv1_0 | self::TLSv1_1 | self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_1:
                return self::TLSv1_1 | self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_2:
                return self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_3:
                return self::TLSv1_3;
            default:
                throw new \RuntimeException('Unknown minimum TLS version: ' . $this->minVersion);
        }
    }
}<?php

namespace Amp\Socket;

use function Amp\Socket\Internal\normalizeBindToOption;
final class BindContext
{
    /** @var string|null */
    private $bindTo;
    /** @var int */
    private $backlog = 128;
    /** @var bool */
    private $reusePort = false;
    /** @var bool */
    private $broadcast = false;
    /** @var bool */
    private $tcpNoDelay = false;
    /** @var int */
    private $chunkSize = 8192;
    /** @var ServerTlsContext|null */
    private $tlsContext;
    /**
     *
     */
    public function withoutBindTo() : self
    {
        return $this->withBindTo(null);
    }
    /**
     *
     */
    public function withBindTo(?string $bindTo) : self
    {
        $bindTo = normalizeBindToOption($bindTo);
        $clone = clone $this;
        $clone->bindTo = $bindTo;
        return $clone;
    }
    /**
     *
     */
    public function getBindTo() : ?string
    {
        return $this->bindTo;
    }
    /**
     *
     */
    public function getBacklog() : int
    {
        return $this->backlog;
    }
    /**
     *
     */
    public function withBacklog(int $backlog) : self
    {
        $clone = clone $this;
        $clone->backlog = $backlog;
        return $clone;
    }
    /**
     *
     */
    public function hasReusePort() : bool
    {
        return $this->reusePort;
    }
    /**
     *
     */
    public function withReusePort() : self
    {
        $clone = clone $this;
        $clone->reusePort = true;
        return $clone;
    }
    /**
     *
     */
    public function withoutReusePort() : self
    {
        $clone = clone $this;
        $clone->reusePort = false;
        return $clone;
    }
    /**
     *
     */
    public function hasBroadcast() : bool
    {
        return $this->broadcast;
    }
    /**
     *
     */
    public function withBroadcast() : self
    {
        $clone = clone $this;
        $clone->broadcast = true;
        return $clone;
    }
    /**
     *
     */
    public function withoutBroadcast() : self
    {
        $clone = clone $this;
        $clone->broadcast = false;
        return $clone;
    }
    /**
     *
     */
    public function hasTcpNoDelay() : bool
    {
        return $this->tcpNoDelay;
    }
    /**
     *
     */
    public function withTcpNoDelay() : self
    {
        $clone = clone $this;
        $clone->tcpNoDelay = true;
        return $clone;
    }
    /**
     *
     */
    public function withoutTcpNoDelay() : self
    {
        $clone = clone $this;
        $clone->tcpNoDelay = false;
        return $clone;
    }
    /**
     *
     */
    public function getTlsContext() : ?ServerTlsContext
    {
        return $this->tlsContext;
    }
    /**
     *
     */
    public function withoutTlsContext() : self
    {
        return $this->withTlsContext(null);
    }
    /**
     *
     */
    public function withTlsContext(?ServerTlsContext $tlsContext) : self
    {
        $clone = clone $this;
        $clone->tlsContext = $tlsContext;
        return $clone;
    }
    /**
     *
     */
    public function getChunkSize() : int
    {
        return $this->chunkSize;
    }
    /**
     *
     */
    public function withChunkSize(int $chunkSize) : self
    {
        $clone = clone $this;
        $clone->chunkSize = $chunkSize;
        return $clone;
    }
    /**
     *
     */
    public function toStreamContextArray() : array
    {
        $array = ['socket' => [
            'bindto' => $this->bindTo,
            'backlog' => $this->backlog,
            'ipv6_v6only' => true,
            // SO_REUSEADDR has SO_REUSEPORT semantics on Windows
            'so_reuseaddr' => $this->reusePort && \stripos(\PHP_OS, 'WIN') === 0,
            'so_reuseport' => $this->reusePort,
            'so_broadcast' => $this->broadcast,
            'tcp_nodelay' => $this->tcpNoDelay,
        ]];
        if ($this->tlsContext) {
            $array = \array_merge($array, $this->tlsContext->toStreamContextArray());
        }
        return $array;
    }
}<?php

namespace Amp\Socket;

/**
 * Thrown in case a second read operation is attempted while another read operation is still pending.
 */
final class PendingAcceptError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = 'The previous accept operation must complete before accept can be called again', int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Socket;

/**
 * Thrown if connecting fails.
 */
class ConnectException extends SocketException
{
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\Promise;
/**
 * Connector that connects to a statically defined URI instead of the URI passed to the connect() call.
 */
final class StaticConnector implements Connector
{
    private $uri;
    private $connector;
    /**
     *
     */
    public function __construct(string $uri, Connector $connector)
    {
        $this->uri = $uri;
        $this->connector = $connector;
    }
    /**
     *
     */
    public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null) : Promise
    {
        return $this->connector->connect($this->uri, $context, $token);
    }
}<?php

namespace Amp\Socket;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\CancellationToken;
use Amp\Failure;
use Amp\Promise;
use function Amp\call;
final class ResourceSocket implements EncryptableSocket
{
    public const DEFAULT_CHUNK_SIZE = ResourceInputStream::DEFAULT_CHUNK_SIZE;
    /**
     * @param resource $resource Stream resource.
     * @param int $chunkSize Read and write chunk size.
     *
     * @return self
     */
    public static function fromServerSocket($resource, int $chunkSize = self::DEFAULT_CHUNK_SIZE) : self
    {
        return new self($resource, $chunkSize);
    }
    /**
     * @param resource $resource Stream resource.
     * @param int $chunkSize Read and write chunk size.
     * @param (ClientTlsContext | null) $tlsContext
     *
     * @return self
     */
    public static function fromClientSocket($resource, ?ClientTlsContext $tlsContext = null, int $chunkSize = self::DEFAULT_CHUNK_SIZE) : self
    {
        return new self($resource, $chunkSize, $tlsContext);
    }
    /** @var ClientTlsContext|null */
    private $tlsContext;
    /** @var int */
    private $tlsState;
    /** @var ResourceInputStream */
    private $reader;
    /** @var ResourceOutputStream */
    private $writer;
    /** @var SocketAddress */
    private $localAddress;
    /** @var SocketAddress */
    private $remoteAddress;
    /** @var TlsInfo|null */
    private $tlsInfo;
    /**
     * @param resource $resource Stream resource.
     * @param int $chunkSize Read and write chunk size.
     * @param (ClientTlsContext | null) $tlsContext
     */
    private function __construct($resource, int $chunkSize = self::DEFAULT_CHUNK_SIZE, ?ClientTlsContext $tlsContext = null)
    {
        $this->tlsContext = $tlsContext;
        $this->reader = new ResourceInputStream($resource, $chunkSize);
        $this->writer = new ResourceOutputStream($resource, $chunkSize);
        $this->remoteAddress = SocketAddress::fromPeerResource($resource);
        $this->localAddress = SocketAddress::fromLocalResource($resource);
        $this->tlsState = self::TLS_STATE_DISABLED;
    }
    /**
     * @inheritDoc
     */
    public function setupTls(?CancellationToken $cancellationToken = null) : Promise
    {
        $resource = $this->getResource();
        if ($resource === null) {
            return new Failure(new ClosedException("Can't setup TLS, because the socket has already been closed"));
        }
        $this->tlsState = self::TLS_STATE_SETUP_PENDING;
        if ($this->tlsContext) {
            $promise = Internal\setupTls($resource, $this->tlsContext->toStreamContextArray(), $cancellationToken);
        } else {
            $context = @\stream_context_get_options($resource);
            if (empty($context['ssl'])) {
                return new Failure(new TlsException('Can\'t enable TLS without configuration. If you used Amp\\Socket\\listen(), be sure to pass a ServerTlsContext within the BindContext in the second argument, otherwise set the \'ssl\' context option to the PHP stream resource.'));
            }
            $promise = Internal\setupTls($resource, $context, $cancellationToken);
        }
        return call(function () use($promise) {
            try {
                (yield $promise);
                $this->tlsState = self::TLS_STATE_ENABLED;
            } catch (\Throwable $exception) {
                $this->close();
                throw $exception;
            }
        });
    }
    /**
     * @inheritDoc
     */
    public function shutdownTls(?CancellationToken $cancellationToken = null) : Promise
    {
        if (($resource = $this->reader->getResource()) === null) {
            return new Failure(new ClosedException("Can't shutdown TLS, because the socket has already been closed"));
        }
        $this->tlsState = self::TLS_STATE_SHUTDOWN_PENDING;
        return call(function () use($resource) {
            try {
                (yield Internal\shutdownTls($resource));
            } finally {
                $this->tlsState = self::TLS_STATE_DISABLED;
            }
        });
    }
    /**
     * @inheritDoc
     */
    public function read() : Promise
    {
        return $this->reader->read();
    }
    /**
     * @inheritDoc
     */
    public function write(string $data) : Promise
    {
        return $this->writer->write($data);
    }
    /**
     * @inheritDoc
     */
    public function end(string $data = '') : Promise
    {
        $promise = $this->writer->end($data);
        $promise->onResolve(function () {
            $this->close();
        });
        return $promise;
    }
    /**
     * @inheritDoc
     */
    public function close() : void
    {
        $this->reader->close();
        $this->writer->close();
    }
    /**
     * @inheritDoc
     */
    public function reference() : void
    {
        $this->reader->reference();
    }
    /**
     * @inheritDoc
     */
    public function unreference() : void
    {
        $this->reader->unreference();
    }
    /**
     * @inheritDoc
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->localAddress;
    }
    /**
     * @inheritDoc
     *
     * @return (resource | null)
     */
    public function getResource()
    {
        return $this->reader->getResource();
    }
    /**
     * @inheritDoc
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->remoteAddress;
    }
    /**
     * @inheritDoc
     */
    public function getTlsState() : int
    {
        return $this->tlsState;
    }
    /**
     * @inheritDoc
     */
    public function getTlsInfo() : ?TlsInfo
    {
        if (null !== $this->tlsInfo) {
            return $this->tlsInfo;
        }
        $resource = $this->getResource();
        if ($resource === null || !\is_resource($resource)) {
            return null;
        }
        return $this->tlsInfo = TlsInfo::fromStreamResource($resource);
    }
    /**
     * @inheritDoc
     */
    public function isClosed() : bool
    {
        return $this->getResource() === null;
    }
    /**
     * @param int $chunkSize New chunk size for reading and writing.
     */
    public function setChunkSize(int $chunkSize) : void
    {
        $this->reader->setChunkSize($chunkSize);
        $this->writer->setChunkSize($chunkSize);
    }
}<?php

namespace Amp\Socket;

final class SocketAddress
{
    /** @var string */
    private $host;
    /** @var int|null */
    private $port;
    /**
     * @param resource $resource
     *
     * @return self
     */
    public static function fromPeerResource($resource) : self
    {
        $name = @\stream_socket_get_name($resource, true);
        /** @psalm-suppress TypeDoesNotContainType */
        if ($name === false || $name === "\x00") {
            return self::fromLocalResource($resource);
        }
        return self::fromSocketName($name);
    }
    /**
     * @param resource $resource
     *
     * @return self
     */
    public static function fromLocalResource($resource) : self
    {
        $wantPeer = false;
        do {
            $name = @\stream_socket_get_name($resource, $wantPeer);
            /** @psalm-suppress RedundantCondition */
            if ($name !== false && $name !== "\x00") {
                return self::fromSocketName($name);
            }
        } while ($wantPeer = !$wantPeer);
        return new self('');
    }
    /**
     * @param string $name
     *
     * @return self
     */
    public static function fromSocketName(string $name) : self
    {
        if ($portStartPos = \strrpos($name, ':')) {
            $host = \Phabel\Target\Php80\Polyfill::substr($name, 0, $portStartPos);
            $port = (int) \Phabel\Target\Php80\Polyfill::substr($name, $portStartPos + 1);
            return new self($host, $port);
        }
        return new self($name);
    }
    /**
     * @param string $host
     * @param (int | null) $port
     */
    public function __construct(string $host, ?int $port = null)
    {
        if ($port !== null && ($port < 1 || $port > 65535)) {
            throw new \Error('Port number must be null or an integer between 1 and 65535');
        }
        if (\strrpos($host, ':')) {
            $host = \trim($host, '[]');
        }
        $this->host = $host;
        $this->port = $port;
    }
    /**
     * @return string
     */
    public function getHost() : string
    {
        return $this->host;
    }
    /**
     * @return int
     */
    public function getPort() : ?int
    {
        return $this->port;
    }
    /**
     * @return string host:port formatted string.
     */
    public function toString() : string
    {
        $host = $this->host;
        if (\strrpos($host, ':')) {
            $host = '[' . $host . ']';
        }
        if ($this->port === null) {
            return $host;
        }
        return $host . ':' . $this->port;
    }
    /**
     * @see toString
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->toString();
    }
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\Loop;
use Amp\Promise;
const LOOP_CONNECTOR_IDENTIFIER = Connector::class;
/**
 * Listen for client connections on the specified server address.
 *
 * If you want to accept TLS connections, you have to use `yield $socket->setupTls()` after accepting new clients.
 *
 * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
 * @param (BindContext | null) $context Context options for listening.
 *
 * @return Server
 *
 * @throws SocketException If binding to the specified URI failed.
 * @throws \Error If an invalid scheme is given.
 * @see Server::listen()
 *
 * @deprecated Use Server::listen() instead.
 */
function listen(string $uri, ?BindContext $context = null) : Server
{
    return Server::listen($uri, $context);
}
/**
 * Set or access the global socket Connector instance.
 *
 * @param (Connector | null) $connector
 *
 * @return Connector
 */
function connector(Connector $connector = null) : Connector
{
    if ($connector === null) {
        if ($connector = Loop::getState(LOOP_CONNECTOR_IDENTIFIER)) {
            return $connector;
        }
        $connector = new DnsConnector();
    }
    Loop::setState(LOOP_CONNECTOR_IDENTIFIER, $connector);
    return $connector;
}
/**
 * Asynchronously establish a socket connection to the specified URI.
 *
 * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
 * @param ConnectContext $context Socket connect context to use when connecting.
 * @param (CancellationToken | null) $token
 *
 * @return Promise<EncryptableSocket>
 *
 * @throws ConnectException
 * @throws CancelledException
 */
function connect(string $uri, ConnectContext $context = null, CancellationToken $token = null) : Promise
{
    return connector()->connect($uri, $context, $token);
}
/**
 * Returns a pair of connected stream socket resources.
 *
 * @return ResourceSocket[] Pair of socket resources.
 *
 * @throws SocketException If creating the sockets fails.
 */
function createPair() : array
{
    try {
        \set_error_handler(static function (int $errno, string $errstr) {
            throw new SocketException(\sprintf('Failed to create socket pair.  Errno: %d; %s', $errno, $errstr));
        });
        $sockets = \stream_socket_pair(\stripos(PHP_OS, 'win') === 0 ? STREAM_PF_INET : STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
        if ($sockets === false) {
            throw new SocketException('Failed to create socket pair.');
        }
    } finally {
        \restore_error_handler();
    }
    return [ResourceSocket::fromClientSocket($sockets[0]), ResourceSocket::fromClientSocket($sockets[1])];
}
/**
 * @see https://wiki.openssl.org/index.php/Manual:OPENSSL_VERSION_NUMBER(3)
 * @return bool
 */
function hasTlsAlpnSupport() : bool
{
    return \defined('OPENSSL_VERSION_NUMBER') && \OPENSSL_VERSION_NUMBER >= 0x10002000;
}
/**
 *
 */
function hasTlsSecurityLevelSupport() : bool
{
    return \defined('OPENSSL_VERSION_NUMBER') && \OPENSSL_VERSION_NUMBER >= 0x10100000;
}<?php

namespace Amp\Socket;

final class ClientTlsContext
{
    public const TLSv1_0 = \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
    public const TLSv1_1 = \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
    public const TLSv1_2 = \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
    public const TLSv1_3 = \PHP_VERSION_ID >= 70400 ? \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT : 0;
    private const TLS_VERSIONS = \PHP_VERSION_ID >= 70400 ? ['TLSv1.0' => self::TLSv1_0, 'TLSv1.1' => self::TLSv1_1, 'TLSv1.2' => self::TLSv1_2, 'TLSv1.3' => self::TLSv1_3] : ['TLSv1.0' => self::TLSv1_0, 'TLSv1.1' => self::TLSv1_1, 'TLSv1.2' => self::TLSv1_2];
    /** @var int */
    private $minVersion = self::TLSv1_0;
    /** @var string|null */
    private $peerName;
    /** @var bool */
    private $verifyPeer = true;
    /** @var int */
    private $verifyDepth = 10;
    /** @var string|null */
    private $ciphers;
    /** @var string|null */
    private $caFile;
    /** @var string|null */
    private $caPath;
    /** @var bool */
    private $capturePeer = false;
    /** @var bool */
    private $sniEnabled = true;
    /** @var int */
    private $securityLevel = 2;
    /** @var Certificate|null */
    private $certificate;
    /** @var string[] */
    private $alpnProtocols = [];
    /**
     *
     */
    public function __construct(string $peerName)
    {
        $this->peerName = $peerName;
    }
    /**
     * Minimum TLS version to negotiate.
     *
     * Defaults to TLS 1.0.
     *
     * @param int $version One of the `ClientTlsContext::TLSv*` constants.
     *
     * @return self Cloned, modified instance.
     * @throws \Error If an invalid minimum version is given.
     */
    public function withMinimumVersion(int $version) : self
    {
        if (!\in_array($version, self::TLS_VERSIONS, true)) {
            throw new \Error(\sprintf('Invalid minimum version, only %s allowed', implode(', ', \array_keys(self::TLS_VERSIONS))));
        }
        $clone = clone $this;
        $clone->minVersion = $version;
        return $clone;
    }
    /**
     * Returns the minimum TLS version to negotiate.
     *
     * @return int
     */
    public function getMinimumVersion() : int
    {
        return $this->minVersion;
    }
    /**
     * Expected name of the peer.
     *
     * @param string $peerName
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerName(string $peerName) : self
    {
        $clone = clone $this;
        $clone->peerName = $peerName;
        return $clone;
    }
    /**
     * @return (null | string) Expected name of the peer or `null` if such an expectation doesn't exist.
     */
    public function getPeerName() : ?string
    {
        return $this->peerName;
    }
    /**
     * Enable peer verification.
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerVerification() : self
    {
        $clone = clone $this;
        $clone->verifyPeer = true;
        return $clone;
    }
    /**
    * Disable peer verification, this is the default for servers.
    *
    * Warning: You usually shouldn't disable this setting for clients, because it allows active MitM attackers to
    intercept the communication and change it without anyone noticing.
    *
    * @return self Cloned, modified instance.
    */
    public function withoutPeerVerification() : self
    {
        $clone = clone $this;
        $clone->verifyPeer = false;
        return $clone;
    }
    /**
     * @return bool Whether peer verification is enabled.
     */
    public function hasPeerVerification() : bool
    {
        return $this->verifyPeer;
    }
    /**
     * Maximum chain length the peer might present including the certificates in the local trust store.
     *
     * @param int $verifyDepth Maximum length of the certificate chain.
     *
     * @return self Cloned, modified instance.
     */
    public function withVerificationDepth(int $verifyDepth) : self
    {
        if ($verifyDepth < 0) {
            throw new \Error("Invalid verification depth ({$verifyDepth}), must be greater than or equal to 0");
        }
        $clone = clone $this;
        $clone->verifyDepth = $verifyDepth;
        return $clone;
    }
    /**
     * @return int Maximum length of the certificate chain.
     */
    public function getVerificationDepth() : int
    {
        return $this->verifyDepth;
    }
    /**
     * List of ciphers to negotiate, the server's order is always preferred.
     *
     * @param (string | null) $ciphers List of ciphers in OpenSSL's format (colon separated).
     *
     * @return self Cloned, modified instance.
     */
    public function withCiphers(string $ciphers = null) : self
    {
        $clone = clone $this;
        $clone->ciphers = $ciphers;
        return $clone;
    }
    /**
     * @return string List of ciphers in OpenSSL's format (colon separated).
     */
    public function getCiphers() : string
    {
        return $this->ciphers ?? \OPENSSL_DEFAULT_STREAM_CIPHERS;
    }
    /**
     * CAFile to check for trusted certificates.
     *
     * @param (string | null) $cafile Path to the file or `null` to unset.
     *
     * @return self Cloned, modified instance.
     */
    public function withCaFile(string $cafile = null) : self
    {
        $clone = clone $this;
        $clone->caFile = $cafile;
        return $clone;
    }
    /**
     * @return (null | string) Path to the file if one is set, otherwise `null`.
     */
    public function getCaFile() : ?string
    {
        return $this->caFile;
    }
    /**
     * CAPath to check for trusted certificates.
     *
     * @param (string | null) $capath Path to the file or `null` to unset.
     *
     * @return self Cloned, modified instance.
     */
    public function withCaPath(string $capath = null) : self
    {
        $clone = clone $this;
        $clone->caPath = $capath;
        return $clone;
    }
    /**
     * @return (null | string) Path to the file if one is set, otherwise `null`.
     */
    public function getCaPath() : ?string
    {
        return $this->caPath;
    }
    /**
     * Capture the certificates sent by the peer.
     *
     * Note: This is the chain as sent by the peer, NOT the verified chain.
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerCapturing() : self
    {
        $clone = clone $this;
        $clone->capturePeer = true;
        return $clone;
    }
    /**
     * Don't capture the certificates sent by the peer.
     *
     * @return self Cloned, modified instance.
     */
    public function withoutPeerCapturing() : self
    {
        $clone = clone $this;
        $clone->capturePeer = false;
        return $clone;
    }
    /**
     * @return bool Whether to capture the certificates sent by the peer.
     */
    public function hasPeerCapturing() : bool
    {
        return $this->capturePeer;
    }
    /**
     * Enable SNI.
     *
     * @return self Cloned, modified instance.
     */
    public function withSni() : self
    {
        $clone = clone $this;
        $clone->sniEnabled = true;
        return $clone;
    }
    /**
     * Disable SNI.
     *
     * @return self Cloned, modified instance.
     */
    public function withoutSni() : self
    {
        $clone = clone $this;
        $clone->sniEnabled = false;
        return $clone;
    }
    /**
     * @return bool Whether SNI is enabled or not.
     */
    public function hasSni() : bool
    {
        return $this->sniEnabled;
    }
    /**
     * Security level to use.
     *
     * Requires OpenSSL 1.1.0 or higher.
     *
     * @param int $level Must be between 0 and 5.
     *
     * @return self Cloned, modified instance.
     */
    public function withSecurityLevel(int $level) : self
    {
        // See https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_security_level.html
        // Level 2 is not recommended, because of SHA-1 by that document,
        // but SHA-1 should be phased out now on general internet use.
        // We therefore default to level 2.
        if ($level < 0 || $level > 5) {
            throw new \Error("Invalid security level ({$level}), must be between 0 and 5.");
        }
        if (!hasTlsSecurityLevelSupport()) {
            throw new \Error("Can't set a security level, as PHP is compiled with OpenSSL < 1.1.0.");
        }
        $clone = clone $this;
        $clone->securityLevel = $level;
        return $clone;
    }
    /**
     * @return int Security level between 0 and 5. Always 0 for OpenSSL < 1.1.0.
     */
    public function getSecurityLevel() : int
    {
        // 0 is equivalent to previous versions of OpenSSL and just does nothing
        if (!hasTlsSecurityLevelSupport()) {
            return 0;
        }
        return $this->securityLevel;
    }
    /**
     * Client certificate to use, if key is no present it assumes it is present in the same file as the certificate.
     *
     * @param Certificate $certificate Certificate and private key info
     *
     * @return self Cloned, modified instance.
     */
    public function withCertificate(Certificate $certificate = null) : self
    {
        $clone = clone $this;
        $clone->certificate = $certificate;
        return $clone;
    }
    /**
     *
     */
    public function getCertificate() : ?Certificate
    {
        return $this->certificate;
    }
    /**
     * @param string[] $protocols
     *
     * @return self Cloned, modified instance.
     */
    public function withApplicationLayerProtocols(array $protocols) : self
    {
        if (!hasTlsAlpnSupport()) {
            throw new \Error("Can't set an application layer protocol list, as PHP is compiled with OpenSSL < 1.0.2.");
        }
        foreach ($protocols as $protocol) {
            if (!\is_string($protocol)) {
                throw new \TypeError("Protocol names must be strings");
            }
        }
        $clone = clone $this;
        $clone->alpnProtocols = $protocols;
        return $clone;
    }
    /**
     * @return string[]
     */
    public function getApplicationLayerProtocols() : array
    {
        return $this->alpnProtocols;
    }
    /**
     * Converts this TLS context into PHP's equivalent stream context array.
     *
     * @return array Stream context array compatible with PHP's streams.
     */
    public function toStreamContextArray() : array
    {
        $options = ['crypto_method' => $this->toStreamCryptoMethod(), 'peer_name' => $this->peerName, 'verify_peer' => $this->verifyPeer, 'verify_peer_name' => $this->verifyPeer, 'verify_depth' => $this->verifyDepth, 'ciphers' => $this->ciphers ?? \OPENSSL_DEFAULT_STREAM_CIPHERS, 'capture_peer_cert' => $this->capturePeer, 'capture_peer_cert_chain' => $this->capturePeer, 'SNI_enabled' => $this->sniEnabled];
        if ($this->certificate !== null) {
            $options['local_cert'] = $this->certificate->getCertFile();
            if ($this->certificate->getCertFile() !== $this->certificate->getKeyFile()) {
                $options['local_pk'] = $this->certificate->getKeyFile();
            }
        }
        if ($this->caFile !== null) {
            $options['cafile'] = $this->caFile;
        }
        if ($this->caPath !== null) {
            $options['capath'] = $this->caPath;
        }
        if (hasTlsSecurityLevelSupport()) {
            $options['security_level'] = $this->securityLevel;
        }
        if (!empty($this->alpnProtocols)) {
            $options['alpn_protocols'] = \implode(',', $this->alpnProtocols);
        }
        return ['ssl' => $options];
    }
    /**
     * @return int Crypto method compatible with PHP's streams.
     */
    public function toStreamCryptoMethod() : int
    {
        switch ($this->minVersion) {
            case self::TLSv1_0:
                return self::TLSv1_0 | self::TLSv1_1 | self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_1:
                return self::TLSv1_1 | self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_2:
                return self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_3:
                return self::TLSv1_3;
            default:
                throw new \RuntimeException('Unknown minimum TLS version: ' . $this->minVersion);
        }
    }
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\Promise;
interface EncryptableSocket extends Socket
{
    public const TLS_STATE_DISABLED = 0;
    public const TLS_STATE_SETUP_PENDING = 1;
    public const TLS_STATE_ENABLED = 2;
    public const TLS_STATE_SHUTDOWN_PENDING = 3;
    /**
     * @param (CancellationToken | null) $cancellationToken
     *
     * @return Promise<void> Resolved when TLS is successfully set up on the socket.
     *
     * @throws SocketException Promise fails and the socket is closed if setting up TLS fails.
     */
    public function setupTls(?CancellationToken $cancellationToken = null) : Promise;
    /**
     * @param (CancellationToken | null) $cancellationToken
     *
     * @return Promise<void> Resolved when TLS is successfully shutdown.
     *
     * @throws SocketException Promise fails and the socket is closed if shutting down TLS fails.
     */
    public function shutdownTls(?CancellationToken $cancellationToken = null) : Promise;
    /**
     * @return int One of the TLS_STATE_* constants defined in this interface.
     */
    public function getTlsState() : int;
    /**
     * @return (TlsInfo | null) The TLS (crypto) context info if TLS is enabled on the socket or null otherwise.
     */
    public function getTlsInfo() : ?TlsInfo;
}<?php

namespace Amp\Socket;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
interface Socket extends InputStream, OutputStream
{
    /**
     * References the read watcher, so the loop keeps running in case there's an active read.
     *
     * @see Loop::reference()
     */
    public function reference() : void;
    /**
     * Unreferences the read watcher, so the loop doesn't keep running even if there are active reads.
     *
     * @see Loop::unreference()
     */
    public function unreference() : void;
    /**
     * Force closes the socket, failing any pending reads or writes.
     */
    public function close() : void;
    /**
     * Returns whether the socket has been closed.
     *
     * @return bool {@code true} if closed, otherwise {@code false}
     */
    public function isClosed() : bool;
    /**
     * @return SocketAddress
     */
    public function getLocalAddress() : SocketAddress;
    /**
     * @return SocketAddress
     */
    public function getRemoteAddress() : SocketAddress;
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Dns;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\TimeoutException;
use function Amp\call;
final class DnsConnector implements Connector
{
    private $resolver;
    /**
     *
     */
    public function __construct(?Dns\Resolver $resolver = null)
    {
        $this->resolver = $resolver;
    }
    /**
     *
     */
    public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null) : Promise
    {
        $resolver = $this->resolver;
        return call(static function () use($uri, $context, $token, $resolver) {
            $context = $context ?? new ConnectContext();
            $token = $token ?? new NullCancellationToken();
            $attempt = 0;
            $uris = [];
            $failures = [];
            [$scheme, $host, $port] = Internal\parseUri($uri);
            if ($host[0] === '[') {
                $host = \Phabel\Target\Php80\Polyfill::substr($host, 1, -1);
            }
            if ($port === 0 || @\inet_pton($host)) {
                // Host is already an IP address or file path.
                $uris = [$uri];
            } else {
                // Host is not an IP address, so resolve the domain name.
                $records = (yield ($resolver ?? Dns\resolver())->resolve($host, $context->getDnsTypeRestriction()));
                // Usually the faster response should be preferred, but we don't have a reliable way of determining IPv6
                // support, so we always prefer IPv4 here.
                \usort($records, static function (Dns\Record $a, Dns\Record $b) {
                    return $a->getType() - $b->getType();
                });
                foreach ($records as $record) {
                    /** @var Dns\Record $record */
                    if ($record->getType() === Dns\Record::AAAA) {
                        $uris[] = \sprintf('%s://[%s]:%d', $scheme, $record->getValue(), $port);
                    } else {
                        $uris[] = \sprintf('%s://%s:%d', $scheme, $record->getValue(), $port);
                    }
                }
            }
            $flags = \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT;
            $timeout = $context->getConnectTimeout();
            foreach ($uris as $builtUri) {
                try {
                    $streamContext = \stream_context_create($context->withoutTlsContext()->toStreamContextArray());
                    /** @psalm-suppress NullArgument */
                    if (!($socket = @\stream_socket_client($builtUri, $errno, $errstr, null, $flags, $streamContext))) {
                        throw new ConnectException(\sprintf('Connection to %s failed: [Error #%d] %s%s', $uri, $errno, $errstr, $failures ? '; previous attempts: ' . \implode($failures) : ''), $errno);
                    }
                    \stream_set_blocking($socket, false);
                    $deferred = new Deferred();
                    $watcher = Loop::onWritable($socket, static function () use($deferred) {
                        $deferred->resolve();
                    });
                    $id = $token->subscribe([$deferred, 'fail']);
                    try {
                        (yield Promise\timeout($deferred->promise(), $timeout));
                    } catch (TimeoutException $e) {
                        throw new ConnectException(\sprintf('Connecting to %s failed: timeout exceeded (%d ms)%s', $uri, $timeout, $failures ? '; previous attempts: ' . \implode($failures) : ''), 110);
                        // See ETIMEDOUT in http://www.virtsync.com/c-error-codes-include-errno
                    } finally {
                        Loop::cancel($watcher);
                        $token->unsubscribe($id);
                    }
                    // The following hack looks like the only way to detect connection refused errors with PHP's stream sockets.
                    /** @psalm-suppress TypeDoesNotContainType */
                    if (\stream_socket_get_name($socket, true) === false) {
                        \fclose($socket);
                        throw new ConnectException(\sprintf('Connection to %s refused%s', $uri, $failures ? '; previous attempts: ' . \implode($failures) : ''), 111);
                        // See ECONNREFUSED in http://www.virtsync.com/c-error-codes-include-errno
                    }
                } catch (ConnectException $e) {
                    // Includes only error codes used in this file, as error codes on other OS families might be different.
                    // In fact, this might show a confusing error message on OS families that return 110 or 111 by itself.
                    $knownReasons = [110 => 'connection timeout', 111 => 'connection refused'];
                    $code = $e->getCode();
                    $reason = $knownReasons[$code] ?? 'Error #' . $code;
                    if (++$attempt === $context->getMaxAttempts()) {
                        break;
                    }
                    $failures[] = "{$uri} ({$reason})";
                    continue;
                    // Could not connect to host, try next host in the list.
                }
                return ResourceSocket::fromClientSocket($socket, $context->getTlsContext());
            }
            /**
             * This is reached if either all URIs failed or the maximum number of attempts is reached.
             *
             * @noinspection PhpUndefinedVariableInspection
             * @psalm-suppress PossiblyUndefinedVariable
             */
            throw $e;
        });
    }
}<?php

namespace Amp\Socket;

/**
 * @see ServerTlsContext::withDefaultCertificate()
 * @see ServerTlsContext::withCertificates()
 */
final class Certificate
{
    /** @var string */
    private $certFile;
    /** @var string */
    private $keyFile;
    /**
     * @param string $certFile Certificate file with the certificate + intermediaries.
     * @param (string | null) $keyFile Key file with the corresponding private key or `null` if the key is in $certFile.
     */
    public function __construct(string $certFile, string $keyFile = null)
    {
        $this->certFile = $certFile;
        $this->keyFile = $keyFile ?? $certFile;
    }
    /**
     * @return string
     */
    public function getCertFile() : string
    {
        return $this->certFile;
    }
    /**
     * @return string
     */
    public function getKeyFile() : string
    {
        return $this->keyFile;
    }
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\Promise;
/**
 * Allows pooling of connections for stateless protocols.
 */
interface SocketPool
{
    /**
    * Checkout a socket from the specified URI authority.
    *
    * The resulting socket resource should be checked back in via `SocketPool::checkin()` once the calling code is
    finished with the stream (even if the socket has been closed). Failure to checkin sockets will result in memory
    leaks and socket queue blockage. Instead of checking the socket in again, it can also be cleared to prevent
    re-use.
    *
    * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present. An
    optional fragment component can be used to differentiate different socket groups connected to the same URI.
    Connections to the same host with a different ConnectContext must use separate socket groups internally to
    prevent TLS negotiation with the wrong peer name or other TLS settings.
    * @param ConnectContext $context Socket connect context to use when connecting.
    * @param (CancellationToken | null) $token Optional cancellation token to cancel the checkout request.
    *
    * @return Promise<EncryptableSocket> Resolves to an EncryptableSocket instance once a connection is available.
    *
    * @throws SocketException
    * @throws CancelledException
    */
    public function checkout(string $uri, ConnectContext $context = null, CancellationToken $token = null) : Promise;
    /**
     * Return a previously checked-out socket to the pool so it can be reused.
     *
     * @param EncryptableSocket $socket Socket instance.
     *
     * @throws \Error If the provided resource is unknown to the pool.
     */
    public function checkin(EncryptableSocket $socket) : void;
    /**
     * Remove the specified socket from the pool.
     *
     * @param EncryptableSocket $socket Socket instance.
     *
     * @throws \Error If the provided resource is unknown to the pool.
     */
    public function clear(EncryptableSocket $socket) : void;
}<?php

namespace Amp\Socket;

use Amp\Deferred;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
final class Server
{
    /** @var resource|null Stream socket server resource. */
    private $socket;
    /** @var string Watcher ID. */
    private $watcher;
    /** @var SocketAddress Stream socket name */
    private $address;
    /** @var int */
    private $chunkSize;
    /** @var Deferred|null */
    private $acceptor;
    /**
     * Listen for client connections on the specified server address.
     *
     * If you want to accept TLS connections, you have to use `yield $socket->setupTls()` after accepting new clients.
     *
     * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
     * @param (BindContext | null) $context Context options for listening.
     *
     * @return Server
     *
     * @throws SocketException If binding to the specified URI failed.
     * @throws \Error If an invalid scheme is given.
     */
    public static function listen(string $uri, ?BindContext $context = null) : self
    {
        $context = $context ?? new BindContext();
        $scheme = \strstr($uri, '://', true);
        if ($scheme === false) {
            $uri = 'tcp://' . $uri;
        } elseif (!\in_array($scheme, ['tcp', 'unix'])) {
            throw new \Error('Only tcp and unix schemes allowed for server creation');
        }
        $streamContext = \stream_context_create($context->toStreamContextArray());
        // Error reporting suppressed since stream_socket_server() emits an E_WARNING on failure (checked below).
        $server = @\stream_socket_server($uri, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $streamContext);
        if (!$server || $errno) {
            throw new SocketException(\sprintf('Could not create server %s: [Error: #%d] %s', $uri, $errno, $errstr), $errno);
        }
        return new self($server, $context->getChunkSize());
    }
    /**
     * @param resource $socket A bound socket server resource
     * @param int $chunkSize Chunk size for the input and output stream.
     *
     * @throws \Error If a stream resource is not given for $socket.
     */
    public function __construct($socket, int $chunkSize = ResourceSocket::DEFAULT_CHUNK_SIZE)
    {
        if (!\is_resource($socket) || \get_resource_type($socket) !== 'stream') {
            throw new \Error('Invalid resource given to constructor!');
        }
        $this->socket = $socket;
        $this->chunkSize = $chunkSize;
        $this->address = SocketAddress::fromLocalResource($socket);
        \stream_set_blocking($this->socket, false);
        $acceptor =& $this->acceptor;
        $this->watcher = Loop::onReadable($this->socket, static function ($watcher, $socket) use(&$acceptor, $chunkSize) {
            // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
            if (!($client = @\stream_socket_accept($socket, 0))) {
                // Timeout of 0 to be non-blocking.
                return;
                // Accepting client failed.
            }
            $deferred = $acceptor;
            $acceptor = null;
            \assert($deferred !== null);
            $deferred->resolve(ResourceSocket::fromServerSocket($client, $chunkSize));
            /** @psalm-suppress RedundantCondition Resolution of the deferred above might accept immediately again */
            if (!$acceptor) {
                Loop::disable($watcher);
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     * Automatically cancels the loop watcher.
     */
    public function __destruct()
    {
        if (!$this->socket) {
            return;
        }
        $this->free();
    }
    /**
     *
     */
    private function free() : void
    {
        Loop::cancel($this->watcher);
        $this->socket = null;
        if ($this->acceptor) {
            $this->acceptor->resolve();
            $this->acceptor = null;
        }
    }
    /**
     * @return Promise<(ResourceSocket | null)>
     *
     * @throws PendingAcceptError If another accept request is pending.
     */
    public function accept() : Promise
    {
        if ($this->acceptor) {
            throw new PendingAcceptError();
        }
        if (!$this->socket) {
            return new Success();
            // Resolve with null when server is closed.
        }
        // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
        if ($client = @\stream_socket_accept($this->socket, 0)) {
            // Timeout of 0 to be non-blocking.
            return new Success(ResourceSocket::fromServerSocket($client, $this->chunkSize));
        }
        $this->acceptor = new Deferred();
        Loop::enable($this->watcher);
        return $this->acceptor->promise();
    }
    /**
     * Closes the server and stops accepting connections. Any socket clients accepted will not be closed.
     */
    public function close() : void
    {
        if ($this->socket) {
            /** @psalm-suppress InvalidPropertyAssignmentValue */
            \fclose($this->socket);
        }
        $this->free();
    }
    /**
     * @return bool
     */
    public function isClosed() : bool
    {
        return $this->socket === null;
    }
    /**
     * References the accept watcher.
     *
     * @see Loop::reference()
     */
    public final function reference() : void
    {
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the accept watcher.
     *
     * @see Loop::unreference()
     */
    public final function unreference() : void
    {
        Loop::unreference($this->watcher);
    }
    /**
     * @return SocketAddress
     */
    public function getAddress() : SocketAddress
    {
        return $this->address;
    }
    /**
     * Raw stream socket resource.
     *
     * @return (resource | null)
     */
    public final function getResource()
    {
        return $this->socket;
    }
}{
    "name": "amphp/socket",
    "homepage": "https://github.com/amphp/socket",
    "description": "Async socket connection / server tools for Amp.",
    "support": {
        "issues": "https://github.com/amphp/socket/issues"
    },
    "keywords": [
        "tcp",
        "sockets",
        "tls",
        "encryption",
        "async",
        "non-blocking",
        "amp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@gmail.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "ext-openssl": "*",
        "amphp/amp": "^2",
        "amphp/dns": "^1 || ^0.9",
        "amphp/byte-stream": "^1.6",
        "kelunik/certificate": "^1.1",
        "league/uri-parser": "^1.4"
    },
    "require-dev": {
        "phpunit/phpunit": "^6 || ^7 || ^8",
        "amphp/phpunit-util": "^1",
        "amphp/php-cs-fixer-config": "dev-master",
        "vimeo/psalm": "^3.9@dev"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Socket\\": "src"
        },
        "files": [
            "src/functions.php",
            "src/Internal/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Socket\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    }
}
{
    "symbol-whitelist": [
        "null",
        "true",
        "false",
        "static",
        "self",
        "parent",
        "array",
        "string",
        "int",
        "float",
        "bool",
        "iterable",
        "callable",
        "void",
        "object",
        "MSG_EAGAIN",
        "MSG_ENOMSG",
        "msg_get_queue",
        "MSG_IPC_NOWAIT",
        "msg_queue_exists",
        "msg_receive",
        "msg_remove_queue",
        "msg_send",
        "msg_set_queue",
        "msg_stat_queue",
        "Threaded",
        "transform",
        "SysvMessageQueue"
    ],
    "php-core-extensions": [
        "Core",
        "date",
        "pcre",
        "Phar",
        "Reflection",
        "SPL",
        "standard"
    ]
}
<?php

namespace Amp\Sync;

use Amp\Promise;
final class PrefixedKeyedSemaphore implements KeyedSemaphore
{
    /** @var KeyedSemaphore */
    private $semaphore;
    /** @var string */
    private $prefix;
    /**
     *
     */
    public function __construct(KeyedSemaphore $semaphore, string $prefix)
    {
        $this->semaphore = $semaphore;
        $this->prefix = $prefix;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        return $this->semaphore->acquire($this->prefix . $key);
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
use function Amp\call;
final class LocalKeyedSemaphore implements KeyedSemaphore
{
    /** @var LocalSemaphore[] */
    private $semaphore = [];
    /** @var int[] */
    private $locks = [];
    /** @var int */
    private $maxLocks;
    /**
     *
     */
    public function __construct(int $maxLocks)
    {
        $this->maxLocks = $maxLocks;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        if (!isset($this->semaphore[$key])) {
            $this->semaphore[$key] = new LocalSemaphore($this->maxLocks);
            $this->locks[$key] = 0;
        }
        return call(function () use($key) {
            $this->locks[$key]++;
            /** @var Lock $lock */
            $lock = (yield $this->semaphore[$key]->acquire());
            return new Lock(0, function () use($lock, $key) {
                if (--$this->locks[$key] === 0) {
                    unset($this->semaphore[$key], $this->locks[$key]);
                }
                $lock->release();
            });
        });
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A non-blocking counting semaphore.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface Semaphore
{
    /**
    * Acquires a lock on the semaphore.
    *
    * @return Promise<Lock> Resolves with an integer keyed lock object. Identifiers returned by the
    locks should be 0-indexed. Releasing an identifier MUST make that same identifier available. May fail with
    a SyncException if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire() : Promise;
}<?php

namespace Amp\Sync\Internal;

use Amp\Delayed;
use Amp\Promise;
use Amp\Sync\Lock;
use function Amp\call;
/** @internal */
final class SemaphoreStorage extends \Threaded
{
    public const LATENCY_TIMEOUT = 10;
    /**
     * Creates a new semaphore with a given number of locks.
     *
     * @param int $locks The maximum number of locks that can be acquired from the semaphore.
     */
    public function __construct(int $locks)
    {
        foreach (\range(0, $locks - 1) as $lock) {
            $this[] = $lock;
        }
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        /**
         * Uses a double locking mechanism to acquire a lock without blocking. A
         * synchronous mutex is used to make sure that the semaphore is queried one
         * at a time to preserve the integrity of the semaphore itself. Then a lock
         * count is used to check if a lock is available without blocking.
         *
         * If a lock is not available, we add the request to a queue and set a timer
         * to check again in the future.
         */
        return call(function () : \Generator {
            $tsl = function () : ?int {
                // If there are no locks available or the wait queue is not empty,
                // we need to wait our turn to acquire a lock.
                if (!$this->count()) {
                    return null;
                }
                return $this->shift();
            };
            while (!$this->count() || ($id = $this->synchronized($tsl)) === null) {
                (yield new Delayed(self::LATENCY_TIMEOUT));
            }
            return new Lock($id, function (Lock $lock) : void {
                $id = $lock->getId();
                $this->synchronized(function () use($id) {
                    $this[] = $id;
                });
            });
        });
    }
}<?php

namespace Amp\Sync\Internal;

use Amp\Delayed;
use Amp\Promise;
use Amp\Sync\Lock;
use function Amp\call;
/** @internal */
final class MutexStorage extends \Threaded
{
    public const LATENCY_TIMEOUT = 10;
    /** @var bool */
    private $locked = false;
    /**
     *
     */
    public function acquire() : Promise
    {
        return call(function () : \Generator {
            $tsl = function () : bool {
                if ($this->locked) {
                    return true;
                }
                $this->locked = true;
                return false;
            };
            while ($this->locked || $this->synchronized($tsl)) {
                (yield new Delayed(self::LATENCY_TIMEOUT));
            }
            return new Lock(0, function () : void {
                $this->locked = false;
            });
        });
    }
}<?php

namespace Amp\Sync;

class SyncException extends \Exception
{
}<?php

namespace Amp\Sync\ConcurrentIterator;

use Amp\CancelledException;
use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use Amp\Sync\Barrier;
use Amp\Sync\Lock;
use Amp\Sync\Semaphore;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\coroutine;
/**
* Concurrently act on iterator values using {@code $processor}.
*
* @param Iterator $iterator Values to process.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Iterator Result values.
*/
function transform(Iterator $iterator, Semaphore $semaphore, callable $processor) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $semaphore, $processor) {
        // one dummy item, because we can't start the barrier with a count of zero
        $barrier = new Barrier(1);
        /** @var \Throwable|null $error */
        $error = null;
        $locks = [];
        $gc = false;
        $processor = coroutine($processor);
        $processor = static function (Lock $lock, $currentElement) use($processor, $emit, $barrier, &$locks, &$error, &$gc) {
            $done = false;
            try {
                (yield $processor($currentElement, $emit));
                $done = true;
            } catch (\Throwable $e) {
                $error = $error ?? $e;
                $done = true;
            } finally {
                if (!$done) {
                    $gc = true;
                }
                unset($locks[$lock->getId()]);
                $lock->release();
                $barrier->arrive();
            }
        };
        while ((yield $iterator->advance())) {
            if ($error) {
                break;
            }
            /** @var Lock $lock */
            $lock = (yield $semaphore->acquire());
            if ($gc || isset($locks[$lock->getId()])) {
                // Throwing here causes a segfault on PHP 7.3
                return;
                // throw new CancelledException; // producer and locks have been GCed
            }
            $locks[$lock->getId()] = true;
            $barrier->register();
            asyncCall($processor, $lock, $iterator->getCurrent());
        }
        $barrier->arrive();
        // remove dummy item
        (yield $barrier->await());
        if ($error) {
            throw $error;
        }
    });
}
/**
* Concurrently map all iterator values using {@code $processor}.
*
* The order of the items in the resulting iterator is not guaranteed in any way.
*
* @param Iterator $iterator Values to map.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Iterator Mapped values.
*/
function map(Iterator $iterator, Semaphore $semaphore, callable $processor) : Iterator
{
    $processor = coroutine($processor);
    return transform($iterator, $semaphore, static function ($value, callable $emit) use($processor) {
        $value = (yield $processor($value));
        (yield $emit($value));
    });
}
/**
* Concurrently filter all iterator values using {@code $filter}.
*
* The order of the items in the resulting iterator is not guaranteed in any way.
*
* @param Iterator $iterator Values to map.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $filter Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted. Must resolve to a boolean, true to keep values in the resulting
iterator.
*
* @return Iterator Values, where {@code $filter} resolved to {@code true}.
*/
function filter(Iterator $iterator, Semaphore $semaphore, callable $filter) : Iterator
{
    $filter = coroutine($filter);
    return transform($iterator, $semaphore, static function ($value, callable $emit) use($filter) {
        $keep = (yield $filter($value));
        if (!\is_bool($keep)) {
            throw new \TypeError(__NAMESPACE__ . '\\filter\'s callable must resolve to a boolean value, got ' . \gettype($keep));
        }
        if ($keep) {
            (yield $emit($value));
        }
    });
}
/**
* Concurrently invoke a callback on all iterator values using {@code $processor}.
*
* @param Iterator $iterator Values to act on.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Promise
*/
function each(Iterator $iterator, Semaphore $semaphore, callable $processor) : Promise
{
    $processor = coroutine($processor);
    $iterator = transform($iterator, $semaphore, static function ($value, callable $emit) use($processor) {
        (yield $processor($value));
        (yield $emit(null));
    });
    // Use Amp\Iterator\discard in the future
    return call(static function () use($iterator) {
        $count = 0;
        while ((yield $iterator->advance())) {
            $count++;
        }
        return $count;
    });
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A non-blocking synchronization primitive that can be used for mutual exclusion across contexts.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface Mutex extends Semaphore
{
    /**
    * Acquires a lock on the mutex.
    *
    * @return Promise<Lock> Resolves with a lock object with an ID of 0. May fail with a SyncException
    if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire() : Promise;
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * An asynchronous semaphore based on pthreads' synchronization methods.
 *
 * This is an implementation of a thread-safe semaphore that has non-blocking
 * acquire methods. There is a small tradeoff for asynchronous semaphores; you
 * may not acquire a lock immediately when one is available and there may be a
 * small delay. However, the small delay will not block the thread.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
class ThreadedSemaphore implements Semaphore
{
    /** @var \Threaded */
    private $semaphore;
    /**
     * Creates a new semaphore with a given number of locks.
     *
     * @param int $locks The maximum number of locks that can be acquired from the semaphore.
     */
    public function __construct(int $locks)
    {
        if ($locks < 1) {
            throw new \Error("The number of locks should be a positive integer");
        }
        $this->semaphore = new Internal\SemaphoreStorage($locks);
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return $this->semaphore->acquire();
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
final class StaticKeyMutex implements Mutex
{
    /** @var KeyedMutex */
    private $mutex;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(KeyedMutex $mutex, string $key)
    {
        $this->mutex = $mutex;
        $this->key = $key;
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        return $this->mutex->acquire($this->key);
    }
}<?php

namespace Amp\Sync;

use Amp\Coroutine;
use Amp\Delayed;
use Amp\Promise;
/**
 * A non-blocking, inter-process POSIX semaphore.
 *
 * Uses a POSIX message queue to store a queue of permits in a lock-free data structure. This semaphore implementation
 * is preferred over other implementations when available, as it provides the best performance.
 *
 * Not compatible with Windows.
 */
class PosixSemaphore implements Semaphore
{
    public const LATENCY_TIMEOUT = 10;
    /** @var string */
    private $id;
    /** @var int The semaphore key. */
    private $key;
    /** @var int PID of the process that created the semaphore. */
    private $initializer = 0;
    /** @var resource A message queue of available locks. */
    private $queue;
    /**
     * Creates a new semaphore with a given ID and number of locks.
     *
     * @param string $id The unique name for the new semaphore.
     * @param int $maxLocks The maximum number of locks that can be acquired from the semaphore.
     * @param int $permissions Permissions to access the semaphore. Use file permission format specified as 0xxx.
     *
     * @return PosixSemaphore
     * @throws SyncException If the semaphore could not be created due to an internal error.
     */
    public static function create(string $id, int $maxLocks, int $permissions = 0600) : self
    {
        if ($maxLocks < 1) {
            throw new \Error('Number of locks must be greater than 0');
        }
        $semaphore = new self($id);
        $semaphore->init($maxLocks, $permissions);
        return $semaphore;
    }
    /**
     * @param string $id The unique name of the semaphore to use.
     *
     * @return \Amp\Sync\PosixSemaphore
     */
    public static function use(string $id) : self
    {
        $semaphore = new self($id);
        $semaphore->open();
        return $semaphore;
    }
    /**
     * @param string $id
     *
     * @throws \Error If the sysvmsg extension is not loaded.
     */
    private function __construct(string $id)
    {
        if (!\extension_loaded("sysvmsg")) {
            throw new \Error(__CLASS__ . " requires the sysvmsg extension.");
        }
        $this->id = $id;
        $this->key = self::makeKey($this->id);
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * Prevent serialization.
     */
    public function __sleep()
    {
        throw new \Error('A semaphore cannot be serialized!');
    }
    /**
     *
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     *
     */
    private function open() : void
    {
        if (!\msg_queue_exists($this->key)) {
            throw new SyncException('No semaphore with that ID found');
        }
        $this->queue = \msg_get_queue($this->key);
        if (!$this->queue) {
            throw new SyncException('Failed to open the semaphore.');
        }
    }
    /**
     * @param int $maxLocks The maximum number of locks that can be acquired from the semaphore.
     * @param int $permissions Permissions to access the semaphore.
     *
     * @throws SyncException If the semaphore could not be created due to an internal error.
     */
    private function init(int $maxLocks, int $permissions) : void
    {
        if (\msg_queue_exists($this->key)) {
            throw new SyncException('A semaphore with that ID already exists');
        }
        $this->queue = \msg_get_queue($this->key, $permissions);
        if (!$this->queue) {
            throw new SyncException('Failed to create the semaphore.');
        }
        $this->initializer = \getmypid();
        // Fill the semaphore with locks.
        while (--$maxLocks >= 0) {
            $this->release($maxLocks);
        }
    }
    /**
     * Gets the access permissions of the semaphore.
     *
     * @return int A permissions mode.
     */
    public function getPermissions() : int
    {
        $stat = \msg_stat_queue($this->queue);
        return $stat['msg_perm.mode'];
    }
    /**
     * Sets the access permissions of the semaphore.
     *
     * The current user must have access to the semaphore in order to change the permissions.
     *
     * @param int $mode A permissions mode to set.
     *
     * @throws SyncException If the operation failed.
     */
    public function setPermissions(int $mode)
    {
        if (!\msg_set_queue($this->queue, ['msg_perm.mode' => $mode])) {
            throw new SyncException('Failed to change the semaphore permissions.');
        }
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        return new Coroutine($this->doAcquire());
    }
    /**
     * {@inheritdoc}
     */
    private function doAcquire() : \Generator
    {
        do {
            // Attempt to acquire a lock from the semaphore.
            if (@\msg_receive($this->queue, 0, $type, 1, $id, false, \MSG_IPC_NOWAIT, $errno)) {
                // A free lock was found, so resolve with a lock object that can
                // be used to release the lock.
                return new Lock(\unpack("C", $id)[1], function (Lock $lock) {
                    $this->release($lock->getId());
                });
            }
            // Check for unusual errors.
            if ($errno !== \MSG_ENOMSG) {
                throw new SyncException(\sprintf('Failed to acquire a lock; errno: %d', $errno));
            }
        } while ((yield new Delayed(self::LATENCY_TIMEOUT, true)));
    }
    /**
     * Removes the semaphore if it still exists.
     *
     * @throws SyncException If the operation failed.
     */
    public function __destruct()
    {
        if ($this->initializer === 0 || $this->initializer !== \getmypid()) {
            return;
        }
        if (\PHP_VERSION_ID < 80000 && (!\is_resource($this->queue) || !\msg_queue_exists($this->key))) {
            return;
        }
        if (\PHP_VERSION_ID >= 80000 && (!$this->queue instanceof \SysvMessageQueue || !\msg_queue_exists($this->key))) {
            return;
        }
        \msg_remove_queue($this->queue);
    }
    /**
     * Releases a lock from the semaphore.
     *
     * @param int $id Lock identifier.
     *
     * @throws SyncException If the operation failed.
     */
    protected function release(int $id)
    {
        if (!$this->queue) {
            return;
            // Queue already destroyed.
        }
        // Call send in non-blocking mode. If the call fails because the queue
        // is full, then the number of locks configured is too large.
        if (!@\msg_send($this->queue, 1, \pack("C", $id), false, false, $errno)) {
            if ($errno === \MSG_EAGAIN) {
                throw new SyncException('The semaphore size is larger than the system allows.');
            }
            throw new SyncException('Failed to release the lock.');
        }
    }
    /**
     *
     */
    private static function makeKey(string $id) : int
    {
        return \abs(\unpack("l", \md5($id, true))[1]);
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
use function Amp\call;
final class LocalKeyedMutex implements KeyedMutex
{
    /** @var LocalMutex[] */
    private $mutex = [];
    /** @var int[] */
    private $locks = [];
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        if (!isset($this->mutex[$key])) {
            $this->mutex[$key] = new LocalMutex();
            $this->locks[$key] = 0;
        }
        return call(function () use($key) {
            $this->locks[$key]++;
            /** @var Lock $lock */
            $lock = (yield $this->mutex[$key]->acquire());
            return new Lock(0, function () use($lock, $key) {
                if (--$this->locks[$key] === 0) {
                    unset($this->mutex[$key], $this->locks[$key]);
                }
                $lock->release();
            });
        });
    }
}<?php

namespace Amp\Sync;

use Amp\Deferred;
use Amp\Promise;
/**
 * A barrier is a synchronization primitive.
 *
 * The barrier is initialized with a certain count, which can be increased and decreased until it reaches zero.
 *
 * A count of one can be used to block multiple coroutines until a certain condition is met.
 *
 * A count of N can be used to await multiple coroutines doing an action to complete.
 *
 * **Example**
 *
 * ```php
 * $barrier = new Amp\Sync\Barrier(2);
 * $barrier->arrive();
 * $barrier->arrive(); // promise returned from Barrier::await() is now resolved
 *
 * yield $barrier->await();
 * ```
 */
final class Barrier
{
    /** @var int */
    private $count;
    /** @var Deferred */
    private $deferred;
    /**
     *
     */
    public function __construct(int $count)
    {
        if ($count < 1) {
            throw new \Error('Count must be positive, got ' . $count);
        }
        $this->count = $count;
        $this->deferred = new Deferred();
    }
    /**
     *
     */
    public function getCount() : int
    {
        return $this->count;
    }
    /**
     *
     */
    public function arrive(int $count = 1) : void
    {
        if ($count < 1) {
            throw new \Error('Count must be at least 1, got ' . $count);
        }
        if ($count > $this->count) {
            throw new \Error('Count cannot be greater than remaining count: ' . $count . ' > ' . $this->count);
        }
        $this->count -= $count;
        if ($this->count === 0) {
            $this->deferred->resolve();
        }
    }
    /**
     *
     */
    public function register(int $count = 1) : void
    {
        if ($count < 1) {
            throw new \Error('Count must be at least 1, got ' . $count);
        }
        if ($this->count === 0) {
            throw new \Error('Can\'t increase count, because the barrier already broke');
        }
        $this->count += $count;
    }
    /**
     *
     */
    public function await() : Promise
    {
        return $this->deferred->promise();
    }
}<?php

namespace Amp\Sync;

use Amp\CallableMaker;
use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
class LocalSemaphore implements Semaphore
{
    use CallableMaker;
    // kept for BC only
    /** @var int[] */
    private $locks;
    /** @var Deferred[] */
    private $queue = [];
    /**
     *
     */
    public function __construct(int $maxLocks)
    {
        if ($maxLocks < 1) {
            throw new \Error('The number of locks must be greater than 0');
        }
        $this->locks = \range(0, $maxLocks - 1);
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        if (!empty($this->locks)) {
            return new Success(new Lock(\array_shift($this->locks), \Closure::fromCallable([$this, 'release'])));
        }
        $this->queue[] = $deferred = new Deferred();
        return $deferred->promise();
    }
    /**
     *
     */
    private function release(Lock $lock) : void
    {
        $id = $lock->getId();
        if (!empty($this->queue)) {
            $deferred = \array_shift($this->queue);
            $deferred->resolve(new Lock($id, \Closure::fromCallable([$this, 'release'])));
            return;
        }
        $this->locks[] = $id;
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
final class PrefixedKeyedMutex implements KeyedMutex
{
    /** @var KeyedMutex */
    private $mutex;
    /** @var string */
    private $prefix;
    /**
     *
     */
    public function __construct(KeyedMutex $mutex, string $prefix)
    {
        $this->mutex = $mutex;
        $this->prefix = $prefix;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        return $this->mutex->acquire($this->prefix . $key);
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A thread-safe, asynchronous mutex using the pthreads locking mechanism.
 *
 * Compatible with POSIX systems and Microsoft Windows.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
class ThreadedMutex implements Mutex
{
    /** @var Internal\MutexStorage */
    private $mutex;
    /**
     * Creates a new threaded mutex.
     */
    public function __construct()
    {
        $this->mutex = new Internal\MutexStorage();
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return $this->mutex->acquire();
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A non-blocking counting semaphore based on keys.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface KeyedSemaphore
{
    /**
    * Acquires a lock on the semaphore.
    *
    * @param string $key Lock key
    *
    * @return Promise<Lock> Resolves with an integer keyed lock object. Identifiers returned by the
    locks should be 0-indexed. Releasing an identifier MUST make that same identifier available. May fail with
    a SyncException if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire(string $key) : Promise;
}<?php

namespace Amp\Sync;

use Amp\Coroutine;
use Amp\Delayed;
use Amp\Promise;
/**
 * A cross-platform mutex that uses exclusive files as the lock mechanism.
 *
 * This mutex implementation is not always atomic and depends on the operating
 * system's implementation of file creation operations. Use this implementation
 * only if no other mutex types are available.
 *
 * This implementation avoids using [flock()](https://www.php.net/flock)
 * because flock() is known to have some atomicity issues on some systems. In
 * addition, flock() does not work as expected when trying to lock a file
 * multiple times in the same process on Linux. Instead, exclusive file creation
 * is used to create a lock file, which is atomic on most systems.
 *
 * @see https://www.php.net/fopen
 */
class FileMutex implements Mutex
{
    public const LATENCY_TIMEOUT = 10;
    /** @var string The full path to the lock file. */
    private $fileName;
    /**
     * @param string $fileName Name of temporary file to use as a mutex.
     */
    public function __construct(string $fileName)
    {
        $this->fileName = $fileName;
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return new Coroutine($this->doAcquire());
    }
    /**
     * @coroutine
     *
     * @return \Generator
     */
    private function doAcquire() : \Generator
    {
        // Try to create the lock file. If the file already exists, someone else
        // has the lock, so set an asynchronous timer and try again.
        while (($handle = @\fopen($this->fileName, 'x')) === false) {
            (yield new Delayed(self::LATENCY_TIMEOUT));
        }
        // Return a lock object that can be used to release the lock on the mutex.
        $lock = new Lock(0, function () : void {
            $this->release();
        });
        \fclose($handle);
        return $lock;
    }
    /**
     * Releases the lock on the mutex.
     *
     * @throws SyncException If the unlock operation failed.
     */
    protected function release()
    {
        $success = @\unlink($this->fileName);
        if (!$success) {
            throw new SyncException('Failed to unlock the mutex file.');
        }
    }
}<?php

namespace Amp\Sync;

/**
 * A handle on an acquired lock from a synchronization object.
 *
 * This object is not thread-safe; after acquiring a lock from a mutex or
 * semaphore, the lock should reside in the same thread or process until it is
 * released.
 */
class Lock
{
    /** @var callable|null The function to be called on release or null if the lock has been released. */
    private $releaser;
    /** @var int */
    private $id;
    /**
     * Creates a new lock permit object.
     *
     * @param int $id The lock identifier.
     * @param callable(self ): void $releaser A function to be called upon release.
     */
    public function __construct(int $id, callable $releaser)
    {
        $this->id = $id;
        $this->releaser = $releaser;
    }
    /**
     * Checks if the lock has already been released.
     *
     * @return bool True if the lock has already been released, otherwise false.
     */
    public function isReleased() : bool
    {
        return !$this->releaser;
    }
    /**
     * @return int Lock identifier.
     */
    public function getId() : int
    {
        return $this->id;
    }
    /**
     * Releases the lock. No-op if the lock has already been released.
     */
    public function release()
    {
        if (!$this->releaser) {
            return;
        }
        // Invoke the releaser function given to us by the synchronization source
        // to release the lock.
        $releaser = $this->releaser;
        $this->releaser = null;
        $releaser($this);
    }
    /**
     * Releases the lock when there are no more references to it.
     */
    public function __destruct()
    {
        if (!$this->isReleased()) {
            $this->release();
        }
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
use function Amp\call;
class SemaphoreMutex implements Mutex
{
    /** @var Semaphore */
    private $semaphore;
    /**
     * @param Semaphore $semaphore A semaphore with a single lock.
     */
    public function __construct(Semaphore $semaphore)
    {
        $this->semaphore = $semaphore;
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return call(function () : \Generator {
            /** @var \Amp\Sync\Lock $lock */
            $lock = (yield $this->semaphore->acquire());
            if ($lock->getId() !== 0) {
                $lock->release();
                throw new \Error("Cannot use a semaphore with more than a single lock");
            }
            return $lock;
        });
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
use function Amp\call;
/**
* Invokes the given callback while maintaining a lock from the provided mutex. The lock is automatically released after
invoking the callback or once the promise returned by the callback is resolved. If the callback returns a Generator,
it will be run as a coroutine. See Amp\call().
*
* @param Mutex $mutex
* @param callable $callback
* @param array ...$args
*
* @return Promise Resolves with the return value of the callback.
*/
function synchronized(Mutex $mutex, callable $callback, ...$args) : Promise
{
    return call(static function () use($mutex, $callback, $args) : \Generator {
        /** @var Lock $lock */
        $lock = (yield $mutex->acquire());
        try {
            return (yield call($callback, ...$args));
        } finally {
            $lock->release();
        }
    });
}<?php

namespace Amp\Sync;

use Amp\CallableMaker;
use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
class LocalMutex implements Mutex
{
    use CallableMaker;
    // kept for BC only
    /** @var bool */
    private $locked = false;
    /** @var Deferred[] */
    private $queue = [];
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        if (!$this->locked) {
            $this->locked = true;
            return new Success(new Lock(0, \Closure::fromCallable([$this, 'release'])));
        }
        $this->queue[] = $deferred = new Deferred();
        return $deferred->promise();
    }
    /**
     *
     */
    private function release() : void
    {
        if (!empty($this->queue)) {
            $deferred = \array_shift($this->queue);
            $deferred->resolve(new Lock(0, \Closure::fromCallable([$this, 'release'])));
            return;
        }
        $this->locked = false;
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A non-blocking synchronization primitive that can be used for mutual exclusion across contexts based on keys.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface KeyedMutex extends KeyedSemaphore
{
    /**
    * Acquires a lock on the mutex.
    *
    * @param string $key Lock key
    *
    * @return Promise<Lock> Resolves with a lock object with an ID of 0. May fail with a SyncException
    if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire(string $key) : Promise;
}{
    "name": "amphp/sync",
    "description": "Mutex, Semaphore, and other synchronization tools for Amp.",
    "keywords": [
        "asynchronous",
        "async",
        "mutex",
        "semaphore",
        "synchronization"
    ],
    "homepage": "https://github.com/amphp/sync",
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Stephen Coakley",
            "email": "me@stephencoakley.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2.2"
    },
    "require-dev": {
        "phpunit/phpunit": "^9 || ^8 || ^7",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Sync\\": "src"
        },
        "files": [
            "src/functions.php",
            "src/ConcurrentIterator/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Sync\\Test\\": "test"
        }
    }
}
{
    "name": "amphp/cache",
    "homepage": "https://github.com/amphp/cache",
    "description": "A promise-aware caching API for Amp.",
    "license": "MIT",
    "support": {
        "issues": "https://github.com/amphp/cache/issues",
        "irc": "irc://irc.freenode.org/amphp"
    },
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/serialization": "^1",
        "amphp/sync": "^1.2"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1.1",
        "phpunit/phpunit": "^6 | ^7 | ^8 | ^9",
        "amphp/php-cs-fixer-config": "dev-master",
        "amphp/file": "^1 || ^2",
        "vimeo/psalm": "^4"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Cache\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Cache\\Test\\": "test"
        }
    },
    "conflict": {
        "amphp/file": "<0.2 || >=3"
    }
}
<?php

namespace Amp\Cache;

use Amp\Loop;
use Amp\Promise;
use Amp\Struct;
use Amp\Success;
final class ArrayCache implements Cache
{
    /** @var object */
    private $sharedState;
    /** @var string */
    private $ttlWatcherId;
    /** @var int|null */
    private $maxSize;
    /**
     * @param int $gcInterval The frequency in milliseconds at which expired cache entries should be garbage collected.
     * @param int $maxSize The maximum size of cache array (number of elements).
     */
    public function __construct(int $gcInterval = 5000, int $maxSize = null)
    {
        // By using a shared state object we're able to use `__destruct()` for "normal" garbage collection of both this
        // instance and the loop's watcher. Otherwise this object could only be GC'd when the TTL watcher was cancelled
        // at the loop layer.
        $this->sharedState = $sharedState = new class
        {
            use Struct;
            /** @var string[] */
            public $cache = [];
            /** @var int[] */
            public $cacheTimeouts = [];
            /** @var bool */
            public $isSortNeeded = false;
            /**
             *
             */
            public function collectGarbage() : void
            {
                $now = \time();
                if ($this->isSortNeeded) {
                    \asort($this->cacheTimeouts);
                    $this->isSortNeeded = false;
                }
                foreach ($this->cacheTimeouts as $key => $expiry) {
                    if ($now <= $expiry) {
                        break;
                    }
                    unset($this->cache[$key], $this->cacheTimeouts[$key]);
                }
            }
        };
        $this->ttlWatcherId = Loop::repeat($gcInterval, [$sharedState, "collectGarbage"]);
        $this->maxSize = $maxSize;
        Loop::unreference($this->ttlWatcherId);
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->sharedState->cache = [];
        $this->sharedState->cacheTimeouts = [];
        Loop::cancel($this->ttlWatcherId);
    }
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        if (!isset($this->sharedState->cache[$key])) {
            return new Success(null);
        }
        if (isset($this->sharedState->cacheTimeouts[$key]) && \time() > $this->sharedState->cacheTimeouts[$key]) {
            unset($this->sharedState->cache[$key], $this->sharedState->cacheTimeouts[$key]);
            return new Success(null);
        }
        return new Success($this->sharedState->cache[$key]);
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        if ($ttl === null) {
            unset($this->sharedState->cacheTimeouts[$key]);
        } elseif ($ttl >= 0) {
            $expiry = \time() + $ttl;
            $this->sharedState->cacheTimeouts[$key] = $expiry;
            $this->sharedState->isSortNeeded = true;
        } else {
            throw new \Error("Invalid cache TTL ({$ttl}; integer >= 0 or null required");
        }
        unset($this->sharedState->cache[$key]);
        if (\count($this->sharedState->cache) === $this->maxSize) {
            \array_shift($this->sharedState->cache);
        }
        $this->sharedState->cache[$key] = $value;
        /** @var Promise<void> */
        return new Success();
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        $exists = isset($this->sharedState->cache[$key]);
        unset($this->sharedState->cache[$key], $this->sharedState->cacheTimeouts[$key]);
        return new Success($exists);
    }
}<?php

namespace Amp\Cache;

use Amp\Failure;
use Amp\Promise;
use Amp\Serialization\SerializationException;
use Amp\Serialization\Serializer;
use function Amp\call;
/**
 * @template TValue
 */
final class SerializedCache
{
    /** @var Cache */
    private $cache;
    /** @var Serializer */
    private $serializer;
    /**
     *
     */
    public function __construct(Cache $cache, Serializer $serializer)
    {
        $this->cache = $cache;
        $this->serializer = $serializer;
    }
    /**
    * Fetch a value from the cache and unserialize it.
    *
    * @param $key string Cache key.
    *
    * @return Promise<(mixed | null)> Resolves to the cached value or `null` if it doesn't exist. Fails with a
    CacheException or SerializationException on failure.
    *
    * @psalm-return Promise<(TValue | null)>
    *
    * @see Cache::get()
    */
    public function get(string $key) : Promise
    {
        return call(function () use($key) {
            $data = (yield $this->cache->get($key));
            if ($data === null) {
                return null;
            }
            return $this->serializer->unserialize($data);
        });
    }
    /**
    * Serializes a value and stores its serialization to the cache.
    *
    * @param $key   string Cache key.
    * @param $value mixed Value to cache.
    * @param $ttl   int Timeout in seconds. The default `null` $ttl value indicates no timeout. Values less than 0 MUST
    throw an \Error.
    *
    * @psalm-param TValue $value
    *
    * @return Promise<void> Resolves either successfully or fails with a CacheException or SerializationException.
    *
    * @see Cache::set()
    */
    public function set(string $key, $value, int $ttl = null) : Promise
    {
        if ($value === null) {
            return new Failure(new CacheException('Cannot store NULL in serialized cache'));
        }
        try {
            $value = $this->serializer->serialize($value);
        } catch (SerializationException $exception) {
            return new Failure($exception);
        }
        return $this->cache->set($key, $value, $ttl);
    }
    /**
    * Deletes a value associated with the given key if it exists.
    *
    * @param $key string Cache key.
    *
    * @return Promise<(bool | null)> Resolves to `true` / `false` to indicate whether the key existed or fails with a
    CacheException on failure. May also resolve with `null` if that information is not available.
    *
    * @see Cache::delete()
    */
    public function delete(string $key) : Promise
    {
        return $this->cache->delete($key);
    }
}<?php

namespace Amp\Cache;

use Amp\Promise;
use Amp\Serialization\SerializationException;
use Amp\Sync\KeyedMutex;
use Amp\Sync\Lock;
use function Amp\call;
/**
 * @template TValue
 */
final class AtomicCache
{
    /** @var SerializedCache<TValue> */
    private $cache;
    /** @var KeyedMutex */
    private $mutex;
    /**
     * @param SerializedCache<TValue> $cache
     * @param KeyedMutex $mutex
     */
    public function __construct(SerializedCache $cache, KeyedMutex $mutex)
    {
        $this->cache = $cache;
        $this->mutex = $mutex;
    }
    /**
    * Obtains the lock for the given key, then invokes the $create callback with the current cached value (which may
    be null if the key did not exist in the cache). The value returned from the callback is stored in the cache and
    the promise returned from this method is resolved with the value.
    *
    * @param string $key
    * @param callable(string , (mixed | null) ): mixed $create Receives $key and $value as parameters.
    * @param (int | null) $ttl Timeout in seconds. The default `null` $ttl value indicates no timeout.
    *
    * @return Promise<mixed>
    *
    * @psalm-param callable(string, TValue|null):(TValue|Promise<TValue>|\Generator<mixed, mixed, mixed, TValue>)
    $create
    * @psalm-return Promise<TValue>
    *
    * @throws CacheException If the $create callback throws an exception while generating the value.
    * @throws SerializationException If serializing the value returned from the callback fails.
    */
    public function compute(string $key, callable $create, ?int $ttl = null) : Promise
    {
        return call(function () use($key, $create, $ttl) : \Generator {
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                $value = (yield $this->cache->get($key));
                return yield from $this->create($create, $key, $value, $ttl);
            } finally {
                $lock->release();
            }
        });
    }
    /**
    * Attempts to get the value for the given key. If the key is not found, the key is locked, the $create callback
    is invoked with the key as the first parameter. The value returned from the callback is stored in the cache and
    the promise returned from this method is resolved with the value.
    *
    * @param string $key Cache key.
    * @param callable(string ): mixed $create Receives $key as parameter.
    * @param (int | null) $ttl Timeout in seconds. The default `null` $ttl value indicates no timeout.
    *
    * @return Promise<mixed>
    *
    * @psalm-param callable(string, TValue|null):(TValue|Promise<TValue>|\Generator<mixed, mixed, mixed, TValue>)
    $create
    * @psalm-return Promise<TValue>
    *
    * @throws CacheException If the $create callback throws an exception while generating the value.
    * @throws SerializationException If serializing the value returned from the callback fails.
    */
    public function computeIfAbsent(string $key, callable $create, ?int $ttl = null) : Promise
    {
        return call(function () use($key, $create, $ttl) : \Generator {
            $value = (yield $this->cache->get($key));
            if ($value !== null) {
                return $value;
            }
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                // Attempt to get the value again, since it may have been set while obtaining the lock.
                $value = (yield $this->cache->get($key));
                if ($value !== null) {
                    return $value;
                }
                return yield from $this->create($create, $key, null, $ttl);
            } finally {
                $lock->release();
            }
        });
    }
    /**
    * Attempts to get the value for the given key. If the key exists, the key is locked, the $create callback
    is invoked with the key as the first parameter and the current key value as the second parameter. The value
    returned from the callback is stored in the cache and the promise returned from this method is resolved with
    the value.
    *
    * @param string $key Cache key.
    * @param callable(string , mixed ): mixed $create Receives $key and $value as parameters.
    * @param (int | null) $ttl Timeout in seconds. The default `null` $ttl value indicates no timeout.
    *
    * @return Promise<mixed>
    *
    * @psalm-param callable(string , (TValue | null) ): (TValue | Promise<TValue> | \Generator<mixed, mixed, mixed, TValue>) $create
    * @psalm-return Promise<TValue>
    *
    * @throws CacheException If the $create callback throws an exception while generating the value.
    * @throws SerializationException If serializing the value returned from the callback fails.
    */
    public function computeIfPresent(string $key, callable $create, ?int $ttl = null) : Promise
    {
        return call(function () use($key, $create, $ttl) : \Generator {
            $value = (yield $this->cache->get($key));
            if ($value === null) {
                return null;
            }
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                // Attempt to get the value again, since it may have been set while obtaining the lock.
                $value = (yield $this->cache->get($key));
                if ($value === null) {
                    return null;
                }
                return yield from $this->create($create, $key, $value, $ttl);
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * The lock is obtained for the key before setting the value.
     *
     * @param string $key Cache key.
     * @param mixed $value Value to cache.
     * @param (int | null) $ttl Timeout in seconds. The default `null` $ttl value indicates no timeout.
     *
     * @return Promise<void> Resolves either successfully or fails with a CacheException on failure.
     *
     * @psalm-param TValue $value
     * @psalm-return Promise<void>
     *
     * @throws CacheException
     * @throws SerializationException
     *
     * @see SerializedCache::set()
     */
    public function set(string $key, $value, ?int $ttl = null) : Promise
    {
        return call(function () use($key, $value, $ttl) : \Generator {
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                (yield $this->cache->set($key, $value, $ttl));
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * Returns the cached value for the key or the given default value if the key does not exist.
     *
     * @template TDefault
     *
     * @param string $key Cache key.
     * @param mixed $default Default value returned if the key does not exist. Null by default.
     *
     * @return Promise<(mixed | null)> Resolved with null iff $default is null.
     *
     * @psalm-param TDefault $default
     * @psalm-return Promise<(TValue | TDefault)>
     *
     * @throws CacheException
     * @throws SerializationException
     *
     * @see SerializedCache::get()
     */
    public function get(string $key, $default = null) : Promise
    {
        return call(function () use($key, $default) : \Generator {
            $value = (yield $this->cache->get($key));
            if ($value === null) {
                return $default;
            }
            return $value;
        });
    }
    /**
     * The lock is obtained for the key before deleting the key.
     *
     * @param string $key
     *
     * @return Promise<(bool | null)>
     *
     * @see SerializedCache::delete()
     */
    public function delete(string $key) : Promise
    {
        return call(function () use($key) : \Generator {
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                return (yield $this->cache->delete($key));
            } finally {
                $lock->release();
            }
        });
    }
    /**
     *
     */
    private function lock(string $key) : \Generator
    {
        try {
            return (yield $this->mutex->acquire($key));
        } catch (\Throwable $exception) {
            throw new CacheException(\sprintf('Exception thrown when obtaining the lock for key "%s"', $key), 0, $exception);
        }
    }
    /**
     * @psalm-param (TValue | null) $value
     * @psalm-return \Generator<mixed, mixed, mixed, TValue>
     */
    private function create(callable $create, string $key, $value, ?int $ttl) : \Generator
    {
        try {
            $value = (yield call($create, $key, $value));
        } catch (\Throwable $exception) {
            throw new CacheException(\sprintf('Exception thrown while creating the value for key "%s"', $key), 0, $exception);
        }
        (yield $this->cache->set($key, $value, $ttl));
        return $value;
    }
}<?php

namespace Amp\Cache;

use Amp\Promise;
use Amp\Success;
/**
 * Cache implementation that just ignores all operations and always resolves to `null`.
 */
class NullCache implements Cache
{
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        return new Success();
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        /** @var Promise<void> */
        return new Success();
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        return new Success(false);
    }
}<?php

/** @noinspection PhpUndefinedFunctionInspection */
namespace Amp\Cache;

use Amp\File;
use Amp\File\Driver;
use Amp\Loop;
use Amp\Promise;
use Amp\Sync\KeyedMutex;
use Amp\Sync\Lock;
use function Amp\call;
final class FileCache implements Cache
{
    /**
     *
     */
    private static function getFilename(string $key) : string
    {
        return \hash('sha256', $key) . '.cache';
    }
    /** @var string */
    private $directory;
    /** @var KeyedMutex */
    private $mutex;
    /** @var string */
    private $gcWatcher;
    /** @var bool */
    private $ampFileVersion2;
    /**
     *
     */
    public function __construct(string $directory, KeyedMutex $mutex)
    {
        $this->directory = $directory = \rtrim($directory, "/\\");
        $this->mutex = $mutex;
        if (!\interface_exists(Driver::class)) {
            throw new \Error(__CLASS__ . ' requires amphp/file to be installed');
        }
        $this->ampFileVersion2 = $ampFileVersion2 = \function_exists('Amp\\File\\listFiles');
        $gcWatcher = static function () use($directory, $mutex, $ampFileVersion2) : \Generator {
            try {
                /** @psalm-suppress UndefinedFunction */
                $files = (yield $ampFileVersion2 ? File\listFiles($directory) : File\scandir($directory));
                foreach ($files as $file) {
                    if (\strlen($file) !== 70 || \Phabel\Target\Php80\Polyfill::substr($file, -\strlen('.cache')) !== '.cache') {
                        continue;
                    }
                    /** @var Lock $lock */
                    $lock = (yield $mutex->acquire($file));
                    try {
                        /** @var File\File $handle */
                        /** @psalm-suppress UndefinedFunction */
                        $handle = (yield $ampFileVersion2 ? File\openFile($directory . '/' . $file, 'r') : File\open($directory . '/' . $file, 'r'));
                        $ttl = (yield $handle->read(4));
                        if ($ttl === null || \strlen($ttl) !== 4) {
                            (yield $handle->close());
                            continue;
                        }
                        $ttl = \unpack('Nttl', $ttl)['ttl'];
                        if ($ttl < \time()) {
                            /** @psalm-suppress UndefinedFunction */
                            (yield $ampFileVersion2 ? File\deleteFile($directory . '/' . $file) : File\unlink($directory . '/' . $file));
                        }
                    } catch (\Throwable $e) {
                        // ignore
                    } finally {
                        $lock->release();
                    }
                }
            } catch (\Throwable $e) {
                // ignore
            }
        };
        // trigger once, so short running scripts also GC and don't grow forever
        Loop::defer($gcWatcher);
        $this->gcWatcher = Loop::repeat(300000, $gcWatcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->gcWatcher !== null) {
            Loop::cancel($this->gcWatcher);
        }
    }
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        return call(function () use($key) {
            $filename = $this->getFilename($key);
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire($filename));
            try {
                /** @psalm-suppress UndefinedFunction */
                $cacheContent = (yield $this->ampFileVersion2 ? File\read($this->directory . '/' . $filename) : File\get($this->directory . '/' . $filename));
                if (\strlen($cacheContent) < 4) {
                    return null;
                }
                $ttl = \unpack('Nttl', \Phabel\Target\Php80\Polyfill::substr($cacheContent, 0, 4))['ttl'];
                if ($ttl < \time()) {
                    /** @psalm-suppress UndefinedFunction */
                    (yield $this->ampFileVersion2 ? File\deleteFile($this->directory . '/' . $filename) : File\unlink($this->directory . '/' . $filename));
                    return null;
                }
                $value = \Phabel\Target\Php80\Polyfill::substr($cacheContent, 4);
                \assert(\is_string($value));
                return $value;
            } catch (\Throwable $e) {
                return null;
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        if ($ttl < 0) {
            throw new \Error("Invalid cache TTL ({$ttl}); integer >= 0 or null required");
        }
        return call(function () use($key, $value, $ttl) {
            $filename = $this->getFilename($key);
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire($filename));
            if ($ttl === null) {
                $ttl = \PHP_INT_MAX;
            } else {
                $ttl = \time() + $ttl;
            }
            $encodedTtl = \pack('N', $ttl);
            try {
                /** @psalm-suppress UndefinedFunction */
                (yield $this->ampFileVersion2 ? File\write($this->directory . '/' . $filename, $encodedTtl . $value) : File\put($this->directory . '/' . $filename, $encodedTtl . $value));
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        return call(function () use($key) {
            $filename = $this->getFilename($key);
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire($filename));
            try {
                /** @psalm-suppress UndefinedFunction */
                return (yield $this->ampFileVersion2 ? File\deleteFile($this->directory . '/' . $filename) : File\unlink($this->directory . '/' . $filename));
            } finally {
                $lock->release();
            }
        });
    }
}<?php

namespace Amp\Cache;

use Amp\Promise;
final class PrefixCache implements Cache
{
    private $cache;
    private $keyPrefix;
    /**
     *
     */
    public function __construct(Cache $cache, string $keyPrefix)
    {
        $this->cache = $cache;
        $this->keyPrefix = $keyPrefix;
    }
    /**
     * Gets the specified key prefix.
     *
     * @return string
     */
    public function getKeyPrefix() : string
    {
        return $this->keyPrefix;
    }
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        return $this->cache->get($this->keyPrefix . $key);
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        return $this->cache->set($this->keyPrefix . $key, $value, $ttl);
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        return $this->cache->delete($this->keyPrefix . $key);
    }
}<?php

namespace Amp\Cache;

/**
 * MUST be thrown in case a cache operation fails.
 */
class CacheException extends \Exception
{
}<?php

namespace Amp\Cache;

use Amp\Promise;
interface Cache
{
    /**
    * Gets a value associated with the given key.
    *
    * If the specified key doesn't exist implementations MUST succeed the resulting promise with `null`.
    *
    * @param $key string Cache key.
    *
    * @return Promise<(string | null)> Resolves to the cached value nor `null` if it doesn't exist or fails with a
    CacheException on failure.
    */
    public function get(string $key) : Promise;
    /**
    * Sets a value associated with the given key. Overrides existing values (if they exist).
    *
    * The eventual resolution value of the resulting promise is unimportant. The success or failure of the promise
    indicates the operation's success.
    *
    * @param $key string Cache key.
    * @param $value string Value to cache.
    * @param $ttl int Timeout in seconds. The default `null` $ttl value indicates no timeout. Values less than 0 MUST
    throw an \Error.
    *
    * @return Promise<void> Resolves either successfully or fails with a CacheException on failure.
    */
    public function set(string $key, string $value, int $ttl = null) : Promise;
    /**
    * Deletes a value associated with the given key if it exists.
    *
    * Implementations SHOULD return boolean `true` or `false` to indicate whether the specified key existed at the time
    the delete operation was requested. If such information is not available, the implementation MUST resolve the
    promise with `null`.
    *
    * Implementations MUST transparently succeed operations for non-existent keys.
    *
    * @param $key string Cache key.
    *
    * @return Promise<(bool | null)> Resolves to `true` / `false` to indicate whether the key existed or fails with a
    CacheException on failure. May also resolve with `null` if that information is not available.
    */
    public function delete(string $key) : Promise;
}<?php

namespace Amp\Log;

use Amp\ByteStream\OutputStream;
use Monolog\Handler\AbstractProcessingHandler;
use Psr\Log\LogLevel;
final class StreamHandler extends AbstractProcessingHandler
{
    /** @var OutputStream */
    private $stream;
    /** @var callable */
    private $onResolve;
    /** @var \Throwable|null */
    private $exception;
    /**
     * @param OutputStream $outputStream
     * @param string $level
     * @param bool $bubble
     */
    public function __construct(OutputStream $outputStream, string $level = LogLevel::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->stream = $outputStream;
        $stream =& $this->stream;
        $exception =& $this->exception;
        $this->onResolve = static function (\Throwable $e = null) use(&$stream, &$exception) {
            if (!$stream) {
                return;
                // Prior write already failed, ignore this failure.
            }
            if ($e) {
                $stream = null;
                $exception = $e;
                throw $e;
            }
        };
    }
    /**
     * Writes the record down to the log of the implementing handler.
     *
     * @param array $record
     *
     * @return void
     */
    protected function write(array $record) : void
    {
        if ($this->exception) {
            throw $this->exception;
        }
        $this->stream->write((string) $record['formatted'])->onResolve($this->onResolve);
    }
}<?php

namespace Amp\Log;

/**
 *
 */
function hasColorSupport() : bool
{
    $os = \stripos(\PHP_OS, "WIN") === 0 ? "win" : \strtolower(\PHP_OS);
    // @see https://github.com/symfony/symfony/blob/v4.0.6/src/Symfony/Component/Console/Output/StreamOutput.php#L91
    // @license https://github.com/symfony/symfony/blob/v4.0.6/LICENSE
    if ($os === 'win') {
        $windowsVersion = PHP_WINDOWS_VERSION_MAJOR . '.' . PHP_WINDOWS_VERSION_MINOR . '.' . PHP_WINDOWS_VERSION_BUILD;
        return \function_exists('sapi_windows_vt100_support') && @\sapi_windows_vt100_support(\STDOUT) || $windowsVersion === '10.0.10586' || false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM');
    }
    if (\function_exists('posix_isatty')) {
        return @\posix_isatty(\STDOUT);
    }
    return false;
}<?php

namespace Amp\Log;

use Monolog\Formatter\LineFormatter;
use Psr\Log\LogLevel;
final class ConsoleFormatter extends LineFormatter
{
    const DEFAULT_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\r\n";
    /** @var bool */
    private $colors;
    /**
     *
     */
    public function __construct(string $format = null, string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false)
    {
        parent::__construct($format ?? self::DEFAULT_FORMAT, $dateFormat, $allowInlineLineBreaks, $ignoreEmptyContextAndExtra);
        $this->setAnsiColorOption();
    }
    /**
     *
     */
    public function format(array $record) : string
    {
        if ($this->colors) {
            $record['level_name'] = $this->ansifyLevel($record['level_name']);
            $record['channel'] = "\x1b[1m{$record['channel']}\x1b[0m";
        }
        return parent::format($record);
    }
    /**
     *
     */
    private function setAnsiColorOption() : void
    {
        $value = \getenv("AMP_LOG_COLOR");
        if ($value === false || $value === '') {
            $value = "auto";
        }
        $value = \strtolower($value);
        switch ($value) {
            case "1":
            case "true":
            case "on":
                $this->colors = true;
                break;
            case "0":
            case "false":
            case "off":
                $this->colors = false;
                break;
            default:
                $this->colors = hasColorSupport();
                break;
        }
    }
    /**
     *
     */
    private function ansifyLevel(string $level) : string
    {
        $level = \strtolower($level);
        switch ($level) {
            case LogLevel::EMERGENCY:
            case LogLevel::ALERT:
            case LogLevel::CRITICAL:
            case LogLevel::ERROR:
                return "\x1b[1;31m{$level}\x1b[0m";
            // bold + red
            case LogLevel::WARNING:
                return "\x1b[1;33m{$level}\x1b[0m";
            // bold + yellow
            case LogLevel::NOTICE:
                return "\x1b[1;32m{$level}\x1b[0m";
            // bold + green
            case LogLevel::INFO:
                return "\x1b[1;35m{$level}\x1b[0m";
            // bold + magenta
            case LogLevel::DEBUG:
                return "\x1b[1;36m{$level}\x1b[0m";
            // bold + cyan
            default:
                return "\x1b[1m{$level}\x1b[0m";
        }
    }
}<?php

use Amp\ByteStream\ResourceOutputStream;
use Amp\Log\ConsoleFormatter;
use Amp\Log\StreamHandler;
use Monolog\Logger;
require dirname(__DIR__) . '/vendor/autoload.php';
$handler = new StreamHandler(new ResourceOutputStream(\STDOUT));
$handler->setFormatter(new ConsoleFormatter());
$logger = new Logger('hello-world');
$logger->pushHandler($handler);
$logger->debug("Hello, world!");
$logger->info("Hello, world!");
$logger->notice("Hello, world!");
$logger->error("Hello, world!");
$logger->alert("Hello, world!");{
    "name": "amphp/log",
    "homepage": "https://github.com/amphp/log",
    "description": "Non-blocking logging for PHP based on Amp and Monolog.",
    "keywords": [
        "log",
        "logging",
        "logger",
        "async",
        "non-blocking",
        "amp",
        "amphp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.3",
        "monolog/monolog": "^2 || ^1.23"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^8 || ^7"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Log\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Log\\Test\\": "test"
        }
    },
    "scripts": {
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit",
        "code-style": "@php ./vendor/bin/php-cs-fixer fix"
    }
}
<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriInterface;
use League\Uri\Exceptions\SyntaxError;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use function is_object;
use function is_scalar;
use function method_exists;
use function sprintf;
final class Http implements Psr7UriInterface, \JsonSerializable
{
    /**
     * @var UriInterface
     */
    private $uri;
    /**
     * New instance.
     */
    private function __construct(UriInterface $uri)
    {
        $this->validate($uri);
        $this->uri = $uri;
    }
    /**
     * Validate the submitted uri against PSR-7 UriInterface.
     *
     * @throws SyntaxError if the given URI does not follow PSR-7 UriInterface rules
     */
    private function validate(UriInterface $uri) : void
    {
        $scheme = $uri->getScheme();
        if (null === $scheme && '' === $uri->getHost()) {
            throw new SyntaxError(sprintf('an URI without scheme can not contains a empty host string according to PSR-7: %s', (string) $uri));
        }
        $port = $uri->getPort();
        if (null !== $port && ($port < 0 || $port > 65535)) {
            throw new SyntaxError(sprintf('The URI port is outside the established TCP and UDP port ranges: %s', (string) $uri->getPort()));
        }
    }
    /**
     * Static method called by PHP's var export.
     */
    public static function __set_state(array $components) : self
    {
        return new self($components['uri']);
    }
    /**
     * Create a new instance from a string.
     *
     * @param (string | mixed) $uri
     */
    public static function createFromString($uri = '') : self
    {
        return new self(Uri::createFromString($uri));
    }
    /**
    * Create a new instance from a hash of parse_url parts.
    *
    * @param array $components a hash representation of the URI similar
    to PHP parse_url function result
    */
    public static function createFromComponents(array $components) : self
    {
        return new self(Uri::createFromComponents($components));
    }
    /**
     * Create a new instance from the environment.
     */
    public static function createFromServer(array $server) : self
    {
        return new self(Uri::createFromServer($server));
    }
    /**
     * Create a new instance from a URI and a Base URI.
     *
     * The returned URI must be absolute.
     *
     * @param mixed $uri the input URI to create
     * @param mixed $base_uri the base URI used for reference
     */
    public static function createFromBaseUri($uri, $base_uri = null) : self
    {
        return new self(Uri::createFromBaseUri($uri, $base_uri));
    }
    /**
     * Create a new instance from a URI object.
     *
     * @param (Psr7UriInterface | UriInterface) $uri the input URI to create
     */
    public static function createFromUri($uri) : self
    {
        if ($uri instanceof UriInterface) {
            return new self($uri);
        }
        return new self(Uri::createFromUri($uri));
    }
    /**
     * {@inheritDoc}
     */
    public function getScheme() : string
    {
        return (string) $this->uri->getScheme();
    }
    /**
     * {@inheritDoc}
     */
    public function getAuthority() : string
    {
        return (string) $this->uri->getAuthority();
    }
    /**
     * {@inheritDoc}
     */
    public function getUserInfo() : string
    {
        return (string) $this->uri->getUserInfo();
    }
    /**
     * {@inheritDoc}
     */
    public function getHost() : string
    {
        return (string) $this->uri->getHost();
    }
    /**
     * {@inheritDoc}
     */
    public function getPort() : ?int
    {
        return $this->uri->getPort();
    }
    /**
     * {@inheritDoc}
     */
    public function getPath() : string
    {
        return $this->uri->getPath();
    }
    /**
     * {@inheritDoc}
     */
    public function getQuery() : string
    {
        return (string) $this->uri->getQuery();
    }
    /**
     * {@inheritDoc}
     */
    public function getFragment() : string
    {
        return (string) $this->uri->getFragment();
    }
    /**
     * {@inheritDoc}
     */
    public function withScheme($scheme) : self
    {
        $scheme = $this->filterInput($scheme);
        if ('' === $scheme) {
            $scheme = null;
        }
        $uri = $this->uri->withScheme($scheme);
        if ($uri->getScheme() === $this->uri->getScheme()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * Safely stringify input when possible.
     *
     * @param mixed $str the value to evaluate as a string
     *
     * @throws SyntaxError if the submitted data can not be converted to string
     *
     * @return (string | mixed)
     */
    private function filterInput($str)
    {
        if (is_scalar($str) || is_object($str) && method_exists($str, '__toString')) {
            return (string) $str;
        }
        return $str;
    }
    /**
     * {@inheritDoc}
     */
    public function withUserInfo($user, $password = null) : self
    {
        $user = $this->filterInput($user);
        if ('' === $user) {
            $user = null;
        }
        $uri = $this->uri->withUserInfo($user, $password);
        if ($uri->getUserInfo() === $this->uri->getUserInfo()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withHost($host) : self
    {
        $host = $this->filterInput($host);
        if ('' === $host) {
            $host = null;
        }
        $uri = $this->uri->withHost($host);
        if ($uri->getHost() === $this->uri->getHost()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withPort($port) : self
    {
        $uri = $this->uri->withPort($port);
        if ($uri->getPort() === $this->uri->getPort()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withPath($path) : self
    {
        $uri = $this->uri->withPath($path);
        if ($uri->getPath() === $this->uri->getPath()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withQuery($query) : self
    {
        $query = $this->filterInput($query);
        if ('' === $query) {
            $query = null;
        }
        $uri = $this->uri->withQuery($query);
        if ($uri->getQuery() === $this->uri->getQuery()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withFragment($fragment) : self
    {
        $fragment = $this->filterInput($fragment);
        if ('' === $fragment) {
            $fragment = null;
        }
        $uri = $this->uri->withFragment($fragment);
        if ($uri->getFragment() === $this->uri->getFragment()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function __toString() : string
    {
        return $this->uri->__toString();
    }
    /**
     * {@inheritDoc}
     */
    public function jsonSerialize() : string
    {
        return $this->uri->__toString();
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriInterface;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use function explode;
use function implode;
use function preg_replace_callback;
use function rawurldecode;
use function sprintf;
final class UriInfo
{
    private const REGEXP_ENCODED_CHARS = ',%(2[D|E]|3[0-9]|4[1-9|A-F]|5[0-9|A|F]|6[1-9|A-F]|7[0-9|E]),i';
    private const WHATWG_SPECIAL_SCHEMES = ['ftp', 'http', 'https', 'ws', 'wss'];
    /**
     * @codeCoverageIgnore
     */
    private function __construct()
    {
    }
    /**
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    private static function emptyComponentValue($uri) : ?string
    {
        return $uri instanceof Psr7UriInterface ? '' : null;
    }
    /**
    * Filter the URI object.
    *
    * To be valid an URI MUST implement at least one of the following interface:
    - League\Uri\UriInterface
    - Psr\Http\Message\UriInterface
    *
    * @param mixed $uri the URI to validate
    *
    * @throws \TypeError if the URI object does not implements the supported interfaces.
    *
    * @return (Psr7UriInterface | UriInterface)
    */
    private static function filterUri($uri)
    {
        if ($uri instanceof Psr7UriInterface || $uri instanceof UriInterface) {
            return $uri;
        }
        throw new \TypeError(sprintf('The uri must be a valid URI object received `%s`', is_object($uri) ? get_class($uri) : gettype($uri)));
    }
    /**
     * Normalize an URI for comparison.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     *
     * @return (Psr7UriInterface | UriInterface)
     */
    private static function normalize($uri)
    {
        $uri = self::filterUri($uri);
        $null = self::emptyComponentValue($uri);
        $path = $uri->getPath();
        if ('/' === ($path[0] ?? '') || '' !== $uri->getScheme() . $uri->getAuthority()) {
            $path = UriResolver::resolve($uri, $uri->withPath('')->withQuery($null))->getPath();
        }
        $query = $uri->getQuery();
        $fragment = $uri->getFragment();
        $fragmentOrig = $fragment;
        $pairs = null === $query ? [] : explode('&', $query);
        sort($pairs, SORT_REGULAR);
        $replace = static function (array $matches) : string {
            return rawurldecode($matches[0]);
        };
        $retval = preg_replace_callback(self::REGEXP_ENCODED_CHARS, $replace, [$path, implode('&', $pairs), $fragment]);
        if (null !== $retval) {
            [$path, $query, $fragment] = $retval + ['', $null, $null];
        }
        if ($null !== $uri->getAuthority() && '' === $path) {
            $path = '/';
        }
        return $uri->withHost(Uri::createFromComponents(['host' => $uri->getHost()])->getHost())->withPath($path)->withQuery([] === $pairs ? $null : $query)->withFragment($null === $fragmentOrig ? $fragmentOrig : $fragment);
    }
    /**
     * Tell whether the URI represents an absolute URI.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    public static function isAbsolute($uri) : bool
    {
        return self::emptyComponentValue($uri) !== self::filterUri($uri)->getScheme();
    }
    /**
     * Tell whether the URI represents a network path.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    public static function isNetworkPath($uri) : bool
    {
        $uri = self::filterUri($uri);
        $null = self::emptyComponentValue($uri);
        return $null === $uri->getScheme() && $null !== $uri->getAuthority();
    }
    /**
     * Tell whether the URI represents an absolute path.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    public static function isAbsolutePath($uri) : bool
    {
        $uri = self::filterUri($uri);
        $null = self::emptyComponentValue($uri);
        return $null === $uri->getScheme() && $null === $uri->getAuthority() && '/' === ($uri->getPath()[0] ?? '');
    }
    /**
     * Tell whether the URI represents a relative path.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    public static function isRelativePath($uri) : bool
    {
        $uri = self::filterUri($uri);
        $null = self::emptyComponentValue($uri);
        return $null === $uri->getScheme() && $null === $uri->getAuthority() && '/' !== ($uri->getPath()[0] ?? '');
    }
    /**
     * Tell whether both URI refers to the same document.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     * @param (Psr7UriInterface | UriInterface) $base_uri
     */
    public static function isSameDocument($uri, $base_uri) : bool
    {
        $uri = self::normalize($uri);
        $base_uri = self::normalize($base_uri);
        return (string) $uri->withFragment($uri instanceof Psr7UriInterface ? '' : null) === (string) $base_uri->withFragment($base_uri instanceof Psr7UriInterface ? '' : null);
    }
    /**
    * Returns the URI origin property as defined by WHATWG URL living standard.
    *
    * {@see https://url.spec.whatwg.org/#origin}
    *
    * For URI without a special scheme the method returns null
    For URI with the file scheme the method will return null (as this is left to the implementation decision)
    For URI with a special scheme the method returns the scheme followed by its authority (without the userinfo part)
    *
    * @param (Psr7UriInterface | UriInterface) $uri
    */
    public static function getOrigin($uri) : ?string
    {
        $scheme = self::filterUri($uri)->getScheme();
        if ('blob' === $scheme) {
            $uri = Uri::createFromString($uri->getPath());
            $scheme = $uri->getScheme();
        }
        if (in_array($scheme, self::WHATWG_SPECIAL_SCHEMES, true)) {
            $null = self::emptyComponentValue($uri);
            return (string) $uri->withFragment($null)->withQuery($null)->withPath('')->withUserInfo($null, null);
        }
        return null;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriInterface;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use function array_pop;
use function array_reduce;
use function count;
use function end;
use function explode;
use function gettype;
use function implode;
use function in_array;
use function sprintf;
use function str_repeat;
use function strpos;
use function substr;
final class UriResolver
{
    /**
     * @var array<string,int>
     */
    const DOT_SEGMENTS = ['.' => 1, '..' => 1];
    /**
     * @codeCoverageIgnore
     */
    private function __construct()
    {
    }
    /**
    * Resolve an URI against a base URI using RFC3986 rules.
    *
    * If the first argument is a UriInterface the method returns a UriInterface object
    If the first argument is a Psr7UriInterface the method returns a Psr7UriInterface object
    *
    * @param (Psr7UriInterface | UriInterface) $uri
    * @param (Psr7UriInterface | UriInterface) $base_uri
    *
    * @return (Psr7UriInterface | UriInterface)
    */
    public static function resolve($uri, $base_uri)
    {
        self::filterUri($uri);
        self::filterUri($base_uri);
        $null = $uri instanceof Psr7UriInterface ? '' : null;
        if ($null !== $uri->getScheme()) {
            return $uri->withPath(self::removeDotSegments($uri->getPath()));
        }
        if ($null !== $uri->getAuthority()) {
            return $uri->withScheme($base_uri->getScheme())->withPath(self::removeDotSegments($uri->getPath()));
        }
        $user = $null;
        $pass = null;
        $userInfo = $base_uri->getUserInfo();
        if (null !== $userInfo) {
            [$user, $pass] = explode(':', $userInfo, 2) + [1 => null];
        }
        [$uri_path, $uri_query] = self::resolvePathAndQuery($uri, $base_uri);
        return $uri->withPath(self::removeDotSegments($uri_path))->withQuery($uri_query)->withHost($base_uri->getHost())->withPort($base_uri->getPort())->withUserInfo((string) $user, $pass)->withScheme($base_uri->getScheme());
    }
    /**
     * Filter the URI object.
     *
     * @param mixed $uri an URI object
     *
     * @throws \TypeError if the URI object does not implements the supported interfaces.
     */
    private static function filterUri($uri) : void
    {
        if (!$uri instanceof UriInterface && !$uri instanceof Psr7UriInterface) {
            throw new \TypeError(sprintf('The uri must be a valid URI object received `%s`', gettype($uri)));
        }
    }
    /**
     * Remove dot segments from the URI path.
     */
    private static function removeDotSegments(string $path) : string
    {
        if (false === strpos($path, '.')) {
            return $path;
        }
        $old_segments = explode('/', $path);
        $new_path = implode('/', array_reduce($old_segments, [UriResolver::class, 'reducer'], []));
        if (isset(self::DOT_SEGMENTS[end($old_segments)])) {
            $new_path .= '/';
        }
        // @codeCoverageIgnoreStart
        // added because some PSR-7 implementations do not respect RFC3986
        if (0 === strpos($path, '/') && 0 !== strpos($new_path, '/')) {
            return '/' . $new_path;
        }
        // @codeCoverageIgnoreEnd
        return $new_path;
    }
    /**
     * Remove dot segments.
     *
     * @return array<int, string>
     */
    private static function reducer(array $carry, string $segment) : array
    {
        if ('..' === $segment) {
            array_pop($carry);
            return $carry;
        }
        if (!isset(self::DOT_SEGMENTS[$segment])) {
            $carry[] = $segment;
        }
        return $carry;
    }
    /**
     * Resolve an URI path and query component.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     * @param (Psr7UriInterface | UriInterface) $base_uri
     *
     * @return array{0: string, 1: (string | null)}
     */
    private static function resolvePathAndQuery($uri, $base_uri) : array
    {
        $target_path = $uri->getPath();
        $target_query = $uri->getQuery();
        $null = $uri instanceof Psr7UriInterface ? '' : null;
        $baseNull = $base_uri instanceof Psr7UriInterface ? '' : null;
        if (0 === strpos($target_path, '/')) {
            return [$target_path, $target_query];
        }
        if ('' === $target_path) {
            if ($null === $target_query) {
                $target_query = $base_uri->getQuery();
            }
            $target_path = $base_uri->getPath();
            //@codeCoverageIgnoreStart
            //because some PSR-7 Uri implementations allow this RFC3986 forbidden construction
            if ($baseNull !== $base_uri->getAuthority() && 0 !== strpos($target_path, '/')) {
                $target_path = '/' . $target_path;
            }
            //@codeCoverageIgnoreEnd
            return [$target_path, $target_query];
        }
        $base_path = $base_uri->getPath();
        if ($baseNull !== $base_uri->getAuthority() && '' === $base_path) {
            $target_path = '/' . $target_path;
        }
        if ('' !== $base_path) {
            $segments = explode('/', $base_path);
            array_pop($segments);
            if ([] !== $segments) {
                $target_path = implode('/', $segments) . '/' . $target_path;
            }
        }
        return [$target_path, $target_query];
    }
    /**
    * Relativize an URI according to a base URI.
    *
    * This method MUST retain the state of the submitted URI instance, and return
    an URI instance of the same type that contains the applied modifications.
    *
    * This method MUST be transparent when dealing with error and exceptions.
    It MUST not alter of silence them apart from validating its own parameters.
    *
    * @param (Psr7UriInterface | UriInterface) $uri
    * @param (Psr7UriInterface | UriInterface) $base_uri
    *
    * @return (Psr7UriInterface | UriInterface)
    */
    public static function relativize($uri, $base_uri)
    {
        self::filterUri($uri);
        self::filterUri($base_uri);
        $uri = self::formatHost($uri);
        $base_uri = self::formatHost($base_uri);
        if (!self::isRelativizable($uri, $base_uri)) {
            return $uri;
        }
        $null = $uri instanceof Psr7UriInterface ? '' : null;
        $uri = $uri->withScheme($null)->withPort(null)->withUserInfo($null)->withHost($null);
        $target_path = $uri->getPath();
        if ($target_path !== $base_uri->getPath()) {
            return $uri->withPath(self::relativizePath($target_path, $base_uri->getPath()));
        }
        if (self::componentEquals('getQuery', $uri, $base_uri)) {
            return $uri->withPath('')->withQuery($null);
        }
        if ($null === $uri->getQuery()) {
            return $uri->withPath(self::formatPathWithEmptyBaseQuery($target_path));
        }
        return $uri->withPath('');
    }
    /**
     * Tells whether the component value from both URI object equals.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     * @param (Psr7UriInterface | UriInterface) $base_uri
     */
    private static function componentEquals(string $method, $uri, $base_uri) : bool
    {
        return self::getComponent($method, $uri) === self::getComponent($method, $base_uri);
    }
    /**
     * Returns the component value from the submitted URI object.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    private static function getComponent(string $method, $uri) : ?string
    {
        $component = $uri->{$method}();
        if ($uri instanceof Psr7UriInterface && '' === $component) {
            return null;
        }
        return $component;
    }
    /**
     * Filter the URI object.
     *
     * @param (null | mixed) $uri
     *
     * @throws \TypeError if the URI object does not implements the supported interfaces.
     *
     * @return (Psr7UriInterface | UriInterface)
     */
    private static function formatHost($uri)
    {
        if (!$uri instanceof Psr7UriInterface) {
            return $uri;
        }
        $host = $uri->getHost();
        if ('' === $host) {
            return $uri;
        }
        return $uri->withHost((string) Uri::createFromComponents(['host' => $host])->getHost());
    }
    /**
     * Tell whether the submitted URI object can be relativize.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     * @param (Psr7UriInterface | UriInterface) $base_uri
     */
    private static function isRelativizable($uri, $base_uri) : bool
    {
        return !UriInfo::isRelativePath($uri) && self::componentEquals('getScheme', $uri, $base_uri) && self::componentEquals('getAuthority', $uri, $base_uri);
    }
    /**
     * Relative the URI for a authority-less target URI.
     */
    private static function relativizePath(string $path, string $basepath) : string
    {
        $base_segments = self::getSegments($basepath);
        $target_segments = self::getSegments($path);
        $target_basename = array_pop($target_segments);
        array_pop($base_segments);
        foreach ($base_segments as $offset => $segment) {
            if (!isset($target_segments[$offset]) || $segment !== $target_segments[$offset]) {
                break;
            }
            unset($base_segments[$offset], $target_segments[$offset]);
        }
        $target_segments[] = $target_basename;
        return self::formatPath(str_repeat('../', count($base_segments)) . implode('/', $target_segments), $basepath);
    }
    /**
     * returns the path segments.
     *
     * @return string[]
     */
    private static function getSegments(string $path) : array
    {
        if ('' !== $path && '/' === $path[0]) {
            $path = \Phabel\Target\Php80\Polyfill::substr($path, 1);
        }
        return explode('/', $path);
    }
    /**
     * Formatting the path to keep a valid URI.
     */
    private static function formatPath(string $path, string $basepath) : string
    {
        if ('' === $path) {
            return in_array($basepath, ['', '/'], true) ? $basepath : './';
        }
        if (false === ($colon_pos = strpos($path, ':'))) {
            return $path;
        }
        $slash_pos = strpos($path, '/');
        if (false === $slash_pos || $colon_pos < $slash_pos) {
            return "./{$path}";
        }
        return $path;
    }
    /**
     * Formatting the path to keep a resolvable URI.
     */
    private static function formatPathWithEmptyBaseQuery(string $path) : string
    {
        $target_segments = self::getSegments($path);
        /** @var string $basename */
        $basename = end($target_segments);
        return '' === $basename ? './' : $basename;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriInterface;
use League\Uri\Exceptions\FileinfoSupportMissing;
use League\Uri\Exceptions\IdnaConversionFailed;
use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
use League\Uri\Idna\Idna;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use function array_filter;
use function array_map;
use function base64_decode;
use function base64_encode;
use function count;
use function explode;
use function file_get_contents;
use function filter_var;
use function implode;
use function in_array;
use function inet_pton;
use function is_object;
use function is_scalar;
use function method_exists;
use function preg_match;
use function preg_replace;
use function preg_replace_callback;
use function rawurlencode;
use function sprintf;
use function str_replace;
use function strlen;
use function strpos;
use function strspn;
use function strtolower;
use function substr;
use const FILEINFO_MIME;
use const FILTER_FLAG_IPV4;
use const FILTER_FLAG_IPV6;
use const FILTER_NULL_ON_FAILURE;
use const FILTER_VALIDATE_BOOLEAN;
use const FILTER_VALIDATE_IP;
final class Uri implements UriInterface
{
    /**
     * RFC3986 invalid characters.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-2.2
     *
     * @var string
     */
    private const REGEXP_INVALID_CHARS = '/[\\x00-\\x1f\\x7f]/';
    /**
     * RFC3986 Sub delimiter characters regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-2.2
     *
     * @var string
     */
    private const REGEXP_CHARS_SUBDELIM = "\\!\$&'\\(\\)\\*\\+,;\\=%";
    /**
     * RFC3986 unreserved characters regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-2.3
     *
     * @var string
     */
    private const REGEXP_CHARS_UNRESERVED = 'A-Za-z0-9_\\-\\.~';
    /**
     * RFC3986 schema regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.1
     */
    private const REGEXP_SCHEME = ',^[a-z]([-a-z0-9+.]+)?$,i';
    /**
     * RFC3986 host identified by a registered name regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_HOST_REGNAME = '/^(
        (?<unreserved>[a-z0-9_~\\-\\.])|
        (?<sub_delims>[!$&\'()*+,;=])|
        (?<encoded>%[A-F0-9]{2})
    )+$/x';
    /**
     * RFC3986 delimiters of the generic URI components regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-2.2
     */
    private const REGEXP_HOST_GEN_DELIMS = '/[:\\/?#\\[\\]@ ]/';
    // Also includes space.
    /**
     * RFC3986 IPvFuture regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_HOST_IPFUTURE = '/^
        v(?<version>[A-F0-9])+\\.
        (?:
            (?<unreserved>[a-z0-9_~\\-\\.])|
            (?<sub_delims>[!$&\'()*+,;=:])  # also include the : character
        )+
    $/ix';
    /**
     * RFC3986 IPvFuture host and port component.
     */
    private const REGEXP_HOST_PORT = ',^(?<host>(\\[.*]|[^:])*)(:(?<port>[^/?#]*))?$,x';
    /**
     * Significant 10 bits of IP to detect Zone ID regular expression pattern.
     */
    private const HOST_ADDRESS_BLOCK = "\xfe\x80";
    /**
     * Regular expression pattern to for file URI.
     * <volume> contains the volume but not the volume separator.
     * The volume separator may be URL-encoded (`|` as `%7C`) by ::formatPath(),
     * so we account for that here.
     */
    private const REGEXP_FILE_PATH = ',^(?<delim>/)?(?<volume>[a-zA-Z])(?:[:|\\|]|%7C)(?<rest>.*)?,';
    /**
     * Mimetype regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc2397
     */
    private const REGEXP_MIMETYPE = ',^\\w+/[-.\\w]+(?:\\+[-.\\w]+)?$,';
    /**
     * Base64 content regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc2397
     */
    private const REGEXP_BINARY = ',(;|^)base64$,';
    /**
     * Windows file path string regular expression pattern.
     * <root> contains both the volume and volume separator.
     */
    private const REGEXP_WINDOW_PATH = ',^(?<root>[a-zA-Z][:|\\|]),';
    /**
     * Supported schemes and corresponding default port.
     *
     * @var array
     */
    private const SCHEME_DEFAULT_PORT = ['data' => null, 'file' => null, 'ftp' => 21, 'gopher' => 70, 'http' => 80, 'https' => 443, 'ws' => 80, 'wss' => 443];
    /**
     * URI validation methods per scheme.
     *
     * @var array
     */
    private const SCHEME_VALIDATION_METHOD = ['data' => 'isUriWithSchemeAndPathOnly', 'file' => 'isUriWithSchemeHostAndPathOnly', 'ftp' => 'isNonEmptyHostUriWithoutFragmentAndQuery', 'gopher' => 'isNonEmptyHostUriWithoutFragmentAndQuery', 'http' => 'isNonEmptyHostUri', 'https' => 'isNonEmptyHostUri', 'ws' => 'isNonEmptyHostUriWithoutFragment', 'wss' => 'isNonEmptyHostUriWithoutFragment'];
    /**
     * All ASCII letters sorted by typical frequency of occurrence.
     *
     * @var string
     */
    private const ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T<D4}B{8FwR67UGN;JzV#HOW_&!K?XQ%Y\\\tZ+~^\$@`\x00\x01\x02\x03\x04\x05\x06\x07\x08\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
    /**
     * URI scheme component.
     *
     * @var string|null
     */
    private $scheme;
    /**
     * URI user info part.
     *
     * @var string|null
     */
    private $user_info;
    /**
     * URI host component.
     *
     * @var string|null
     */
    private $host;
    /**
     * URI port component.
     *
     * @var int|null
     */
    private $port;
    /**
     * URI authority string representation.
     *
     * @var string|null
     */
    private $authority;
    /**
     * URI path component.
     *
     * @var string
     */
    private $path = '';
    /**
     * URI query component.
     *
     * @var string|null
     */
    private $query;
    /**
     * URI fragment component.
     *
     * @var string|null
     */
    private $fragment;
    /**
     * URI string representation.
     *
     * @var string|null
     */
    private $uri;
    /**
     * Create a new instance.
     *
     * @param ?string $scheme
     * @param ?string $user
     * @param ?string $pass
     * @param ?string $host
     * @param ?int $port
     * @param ?string $query
     * @param ?string $fragment
     */
    private function __construct(?string $scheme, ?string $user, ?string $pass, ?string $host, ?int $port, string $path, ?string $query, ?string $fragment)
    {
        $this->scheme = $this->formatScheme($scheme);
        $this->user_info = $this->formatUserInfo($user, $pass);
        $this->host = $this->formatHost($host);
        $this->port = $this->formatPort($port);
        $this->authority = $this->setAuthority();
        $this->path = $this->formatPath($path);
        $this->query = $this->formatQueryAndFragment($query);
        $this->fragment = $this->formatQueryAndFragment($fragment);
        $this->assertValidState();
    }
    /**
     * Format the Scheme and Host component.
     *
     * @param ?string $scheme
     *
     * @throws SyntaxError if the scheme is invalid
     */
    private function formatScheme(?string $scheme) : ?string
    {
        if (null === $scheme) {
            return $scheme;
        }
        $formatted_scheme = strtolower($scheme);
        if (1 === preg_match(self::REGEXP_SCHEME, $formatted_scheme)) {
            return $formatted_scheme;
        }
        throw new SyntaxError(sprintf('The scheme `%s` is invalid.', $scheme));
    }
    /**
     * Set the UserInfo component.
     *
     * @param ?string $user
     * @param ?string $password
     */
    private function formatUserInfo(?string $user, ?string $password) : ?string
    {
        if (null === $user) {
            return $user;
        }
        static $user_pattern = '/(?:[^%' . self::REGEXP_CHARS_UNRESERVED . self::REGEXP_CHARS_SUBDELIM . ']++|%(?![A-Fa-f0-9]{2}))/';
        $user = preg_replace_callback($user_pattern, [Uri::class, 'urlEncodeMatch'], $user);
        if (null === $password) {
            return $user;
        }
        static $password_pattern = '/(?:[^%:' . self::REGEXP_CHARS_UNRESERVED . self::REGEXP_CHARS_SUBDELIM . ']++|%(?![A-Fa-f0-9]{2}))/';
        return $user . ':' . preg_replace_callback($password_pattern, [Uri::class, 'urlEncodeMatch'], $password);
    }
    /**
     * Returns the RFC3986 encoded string matched.
     */
    private static function urlEncodeMatch(array $matches) : string
    {
        return rawurlencode($matches[0]);
    }
    /**
     * Validate and Format the Host component.
     *
     * @param ?string $host
     */
    private function formatHost(?string $host) : ?string
    {
        if (null === $host || '' === $host) {
            return $host;
        }
        if ('[' !== $host[0]) {
            return $this->formatRegisteredName($host);
        }
        return $this->formatIp($host);
    }
    /**
     * Validate and format a registered name.
     *
     * The host is converted to its ascii representation if needed
     *
     * @throws IdnSupportMissing if the submitted host required missing or misconfigured IDN support
     * @throws SyntaxError if the submitted host is not a valid registered name
     */
    private function formatRegisteredName(string $host) : string
    {
        $formatted_host = rawurldecode($host);
        if (1 === preg_match(self::REGEXP_HOST_REGNAME, $formatted_host)) {
            return $formatted_host;
        }
        if (1 === preg_match(self::REGEXP_HOST_GEN_DELIMS, $formatted_host)) {
            throw new SyntaxError(sprintf('The host `%s` is invalid : a registered name can not contain URI delimiters or spaces', $host));
        }
        $info = Idna::toAscii($host, Idna::IDNA2008_ASCII);
        if (0 !== $info->errors()) {
            throw IdnaConversionFailed::dueToIDNAError($host, $info);
        }
        return $info->result();
    }
    /**
     * Validate and Format the IPv6/IPvfuture host.
     *
     * @throws SyntaxError if the submitted host is not a valid IP host
     */
    private function formatIp(string $host) : string
    {
        $ip = \Phabel\Target\Php80\Polyfill::substr($host, 1, -1);
        if (false !== filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return $host;
        }
        if (1 === preg_match(self::REGEXP_HOST_IPFUTURE, $ip, $matches) && !in_array($matches['version'], ['4', '6'], true)) {
            return $host;
        }
        $pos = strpos($ip, '%');
        if (false === $pos) {
            throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host));
        }
        if (1 === preg_match(self::REGEXP_HOST_GEN_DELIMS, rawurldecode(\Phabel\Target\Php80\Polyfill::substr($ip, $pos)))) {
            throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host));
        }
        $ip = \Phabel\Target\Php80\Polyfill::substr($ip, 0, $pos);
        if (false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host));
        }
        //Only the address block fe80::/10 can have a Zone ID attach to
        //let's detect the link local significant 10 bits
        if (0 === strpos((string) inet_pton($ip), self::HOST_ADDRESS_BLOCK)) {
            return $host;
        }
        throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host));
    }
    /**
     * Format the Port component.
     *
     * @param (null | mixed) $port
     *
     * @throws SyntaxError
     */
    private function formatPort($port = null) : ?int
    {
        if (null === $port || '' === $port) {
            return null;
        }
        if (!is_int($port) && !(is_string($port) && 1 === preg_match('/^\\d*$/', $port))) {
            throw new SyntaxError(sprintf('The port `%s` is invalid', $port));
        }
        $port = (int) $port;
        if (0 > $port) {
            throw new SyntaxError(sprintf('The port `%s` is invalid', $port));
        }
        $defaultPort = self::SCHEME_DEFAULT_PORT[$this->scheme] ?? null;
        if ($defaultPort === $port) {
            return null;
        }
        return $port;
    }
    /**
     * {@inheritDoc}
     */
    public static function __set_state(array $components) : self
    {
        $components['user'] = null;
        $components['pass'] = null;
        if (null !== $components['user_info']) {
            [$components['user'], $components['pass']] = explode(':', $components['user_info'], 2) + [1 => null];
        }
        return new self($components['scheme'], $components['user'], $components['pass'], $components['host'], $components['port'], $components['path'], $components['query'], $components['fragment']);
    }
    /**
     * Create a new instance from a URI and a Base URI.
     *
     * The returned URI must be absolute.
     *
     * @param mixed $uri the input URI to create
     * @param (null | mixed) $base_uri the base URI used for reference
     */
    public static function createFromBaseUri($uri, $base_uri = null) : UriInterface
    {
        if (!$uri instanceof UriInterface) {
            $uri = self::createFromString($uri);
        }
        if (null === $base_uri) {
            if (null === $uri->getScheme()) {
                throw new SyntaxError(sprintf('the URI `%s` must be absolute', (string) $uri));
            }
            if (null === $uri->getAuthority()) {
                return $uri;
            }
            /** @var UriInterface $uri */
            $uri = UriResolver::resolve($uri, $uri->withFragment(null)->withQuery(null)->withPath(''));
            return $uri;
        }
        if (!$base_uri instanceof UriInterface) {
            $base_uri = self::createFromString($base_uri);
        }
        if (null === $base_uri->getScheme()) {
            throw new SyntaxError(sprintf('the base URI `%s` must be absolute', (string) $base_uri));
        }
        /** @var UriInterface $uri */
        $uri = UriResolver::resolve($uri, $base_uri);
        return $uri;
    }
    /**
     * Create a new instance from a string.
     *
     * @param (string | mixed) $uri
     */
    public static function createFromString($uri = '') : self
    {
        $components = UriString::parse($uri);
        return new self($components['scheme'], $components['user'], $components['pass'], $components['host'], $components['port'], $components['path'], $components['query'], $components['fragment']);
    }
    /**
    * Create a new instance from a hash of parse_url parts.
    *
    * Create an new instance from a hash representation of the URI similar
    to PHP parse_url function result
    *
    * @param array<string, mixed> $components
    */
    public static function createFromComponents(array $components = []) : self
    {
        $components += ['scheme' => null, 'user' => null, 'pass' => null, 'host' => null, 'port' => null, 'path' => '', 'query' => null, 'fragment' => null];
        return new self($components['scheme'], $components['user'], $components['pass'], $components['host'], $components['port'], $components['path'], $components['query'], $components['fragment']);
    }
    /**
     * Create a new instance from a data file path.
     *
     * @param (resource | null) $context
     *
     * @throws FileinfoSupportMissing If ext/fileinfo is not installed
     * @throws SyntaxError If the file does not exist or is not readable
     */
    public static function createFromDataPath(string $path, $context = null) : self
    {
        static $finfo_support = null;
        $finfo_support = $finfo_support ?? class_exists(\finfo::class);
        // @codeCoverageIgnoreStart
        if (!$finfo_support) {
            throw new FileinfoSupportMissing(sprintf('Please install ext/fileinfo to use the %s() method.', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $file_args = [$path, false];
        $mime_args = [$path, FILEINFO_MIME];
        if (null !== $context) {
            $file_args[] = $context;
            $mime_args[] = $context;
        }
        $raw = @file_get_contents(...$file_args);
        if (false === $raw) {
            throw new SyntaxError(sprintf('The file `%s` does not exist or is not readable', $path));
        }
        $mimetype = (string) (new \finfo(FILEINFO_MIME))->file(...$mime_args);
        return Uri::createFromComponents(['scheme' => 'data', 'path' => str_replace(' ', '', $mimetype . ';base64,' . base64_encode($raw))]);
    }
    /**
     * Create a new instance from a Unix path string.
     */
    public static function createFromUnixPath(string $uri = '') : self
    {
        $uri = implode('/', array_map('rawurlencode', explode('/', $uri)));
        if ('/' !== ($uri[0] ?? '')) {
            return Uri::createFromComponents(['path' => $uri]);
        }
        return Uri::createFromComponents(['path' => $uri, 'scheme' => 'file', 'host' => '']);
    }
    /**
     * Create a new instance from a local Windows path string.
     */
    public static function createFromWindowsPath(string $uri = '') : self
    {
        $root = '';
        if (1 === preg_match(self::REGEXP_WINDOW_PATH, $uri, $matches)) {
            $root = \Phabel\Target\Php80\Polyfill::substr($matches['root'], 0, -1) . ':';
            $uri = \Phabel\Target\Php80\Polyfill::substr($uri, strlen($root));
        }
        $uri = str_replace('\\', '/', $uri);
        $uri = implode('/', array_map('rawurlencode', explode('/', $uri)));
        //Local Windows absolute path
        if ('' !== $root) {
            return Uri::createFromComponents(['path' => '/' . $root . $uri, 'scheme' => 'file', 'host' => '']);
        }
        //UNC Windows Path
        if ('//' !== \Phabel\Target\Php80\Polyfill::substr($uri, 0, 2)) {
            return Uri::createFromComponents(['path' => $uri]);
        }
        $parts = explode('/', \Phabel\Target\Php80\Polyfill::substr($uri, 2), 2) + [1 => null];
        return Uri::createFromComponents(['host' => $parts[0], 'path' => '/' . $parts[1], 'scheme' => 'file']);
    }
    /**
     * Create a new instance from a URI object.
     *
     * @param (Psr7UriInterface | UriInterface) $uri the input URI to create
     */
    public static function createFromUri($uri) : self
    {
        if ($uri instanceof UriInterface) {
            $user_info = $uri->getUserInfo();
            $user = null;
            $pass = null;
            if (null !== $user_info) {
                [$user, $pass] = explode(':', $user_info, 2) + [1 => null];
            }
            return new self($uri->getScheme(), $user, $pass, $uri->getHost(), $uri->getPort(), $uri->getPath(), $uri->getQuery(), $uri->getFragment());
        }
        if (!$uri instanceof Psr7UriInterface) {
            throw new \TypeError(sprintf('The object must implement the `%s` or the `%s`', Psr7UriInterface::class, UriInterface::class));
        }
        $scheme = $uri->getScheme();
        if ('' === $scheme) {
            $scheme = null;
        }
        $fragment = $uri->getFragment();
        if ('' === $fragment) {
            $fragment = null;
        }
        $query = $uri->getQuery();
        if ('' === $query) {
            $query = null;
        }
        $host = $uri->getHost();
        if ('' === $host) {
            $host = null;
        }
        $user_info = $uri->getUserInfo();
        $user = null;
        $pass = null;
        if ('' !== $user_info) {
            [$user, $pass] = explode(':', $user_info, 2) + [1 => null];
        }
        return new self($scheme, $user, $pass, $host, $uri->getPort(), $uri->getPath(), $query, $fragment);
    }
    /**
     * Create a new instance from the environment.
     */
    public static function createFromServer(array $server) : self
    {
        [$user, $pass] = self::fetchUserInfo($server);
        [$host, $port] = self::fetchHostname($server);
        [$path, $query] = self::fetchRequestUri($server);
        return Uri::createFromComponents(['scheme' => self::fetchScheme($server), 'user' => $user, 'pass' => $pass, 'host' => $host, 'port' => $port, 'path' => $path, 'query' => $query]);
    }
    /**
     * Returns the environment scheme.
     */
    private static function fetchScheme(array $server) : string
    {
        $server += ['HTTPS' => ''];
        $res = filter_var($server['HTTPS'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
        return false !== $res ? 'https' : 'http';
    }
    /**
     * Returns the environment user info.
     *
     * @return array{0: ?string, 1: ?string}
     */
    private static function fetchUserInfo(array $server) : array
    {
        $server += ['PHP_AUTH_USER' => null, 'PHP_AUTH_PW' => null, 'HTTP_AUTHORIZATION' => ''];
        $user = $server['PHP_AUTH_USER'];
        $pass = $server['PHP_AUTH_PW'];
        if (0 === strpos(strtolower($server['HTTP_AUTHORIZATION']), 'basic')) {
            $userinfo = base64_decode(\Phabel\Target\Php80\Polyfill::substr($server['HTTP_AUTHORIZATION'], 6), true);
            if (false === $userinfo) {
                throw new SyntaxError('The user info could not be detected');
            }
            [$user, $pass] = explode(':', $userinfo, 2) + [1 => null];
        }
        if (null !== $user) {
            $user = rawurlencode($user);
        }
        if (null !== $pass) {
            $pass = rawurlencode($pass);
        }
        return [$user, $pass];
    }
    /**
     * Returns the environment host.
     *
     * @throws SyntaxError If the host can not be detected
     *
     * @return array{0: ?string, 1: ?string}
     */
    private static function fetchHostname(array $server) : array
    {
        $server += ['SERVER_PORT' => null];
        if (null !== $server['SERVER_PORT']) {
            $server['SERVER_PORT'] = (int) $server['SERVER_PORT'];
        }
        if (isset($server['HTTP_HOST']) && 1 === preg_match(self::REGEXP_HOST_PORT, $server['HTTP_HOST'], $matches)) {
            return [$matches['host'], isset($matches['port']) ? (int) $matches['port'] : $server['SERVER_PORT']];
        }
        if (!isset($server['SERVER_ADDR'])) {
            throw new SyntaxError('The host could not be detected');
        }
        if (false === filter_var($server['SERVER_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            $server['SERVER_ADDR'] = '[' . $server['SERVER_ADDR'] . ']';
        }
        return [$server['SERVER_ADDR'], $server['SERVER_PORT']];
    }
    /**
     * Returns the environment path.
     *
     * @return array{0: ?string, 1: ?string}
     */
    private static function fetchRequestUri(array $server) : array
    {
        $server += ['IIS_WasUrlRewritten' => null, 'UNENCODED_URL' => '', 'PHP_SELF' => '', 'QUERY_STRING' => null];
        if ('1' === $server['IIS_WasUrlRewritten'] && '' !== $server['UNENCODED_URL']) {
            /** @var array{0:?string, 1:?string} $retval */
            $retval = explode('?', $server['UNENCODED_URL'], 2) + [1 => null];
            return $retval;
        }
        if (isset($server['REQUEST_URI'])) {
            [$path] = explode('?', $server['REQUEST_URI'], 2);
            $query = '' !== $server['QUERY_STRING'] ? $server['QUERY_STRING'] : null;
            return [$path, $query];
        }
        return [$server['PHP_SELF'], $server['QUERY_STRING']];
    }
    /**
     * Generate the URI authority part.
     */
    private function setAuthority() : ?string
    {
        $authority = null;
        if (null !== $this->user_info) {
            $authority = $this->user_info . '@';
        }
        if (null !== $this->host) {
            $authority .= $this->host;
        }
        if (null !== $this->port) {
            $authority .= ':' . $this->port;
        }
        return $authority;
    }
    /**
     * Format the Path component.
     */
    private function formatPath(string $path) : string
    {
        $path = $this->formatDataPath($path);
        static $pattern = '/(?:[^' . self::REGEXP_CHARS_UNRESERVED . self::REGEXP_CHARS_SUBDELIM . '%:@\\/}{]++|%(?![A-Fa-f0-9]{2}))/';
        $path = (string) preg_replace_callback($pattern, [Uri::class, 'urlEncodeMatch'], $path);
        return $this->formatFilePath($path);
    }
    /**
     * Filter the Path component.
     *
     * @link https://tools.ietf.org/html/rfc2397
     *
     * @throws SyntaxError If the path is not compliant with RFC2397
     */
    private function formatDataPath(string $path) : string
    {
        if ('data' !== $this->scheme) {
            return $path;
        }
        if ('' == $path) {
            return 'text/plain;charset=us-ascii,';
        }
        if (strlen($path) !== \Phabel\Target\Php80\Polyfill::strspn($path, self::ASCII) || false === strpos($path, ',')) {
            throw new SyntaxError(sprintf('The path `%s` is invalid according to RFC2937', $path));
        }
        $parts = explode(',', $path, 2) + [1 => null];
        $mediatype = explode(';', (string) $parts[0], 2) + [1 => null];
        $data = (string) $parts[1];
        $mimetype = $mediatype[0];
        if (null === $mimetype || '' === $mimetype) {
            $mimetype = 'text/plain';
        }
        $parameters = $mediatype[1];
        if (null === $parameters || '' === $parameters) {
            $parameters = 'charset=us-ascii';
        }
        $this->assertValidPath($mimetype, $parameters, $data);
        return $mimetype . ';' . $parameters . ',' . $data;
    }
    /**
     * Assert the path is a compliant with RFC2397.
     *
     * @link https://tools.ietf.org/html/rfc2397
     *
     * @throws SyntaxError If the mediatype or the data are not compliant with the RFC2397
     */
    private function assertValidPath(string $mimetype, string $parameters, string $data) : void
    {
        if (1 !== preg_match(self::REGEXP_MIMETYPE, $mimetype)) {
            throw new SyntaxError(sprintf('The path mimetype `%s` is invalid', $mimetype));
        }
        $is_binary = 1 === preg_match(self::REGEXP_BINARY, $parameters, $matches);
        if ($is_binary) {
            $parameters = \Phabel\Target\Php80\Polyfill::substr($parameters, 0, -strlen($matches[0]));
        }
        $res = array_filter(array_filter(explode(';', $parameters), [$this, 'validateParameter']));
        if ([] !== $res) {
            throw new SyntaxError(sprintf('The path paremeters `%s` is invalid', $parameters));
        }
        if (!$is_binary) {
            return;
        }
        $res = base64_decode($data, true);
        if (false === $res || $data !== base64_encode($res)) {
            throw new SyntaxError(sprintf('The path data `%s` is invalid', $data));
        }
    }
    /**
     * Validate mediatype parameter.
     */
    private function validateParameter(string $parameter) : bool
    {
        $properties = explode('=', $parameter);
        return 2 != count($properties) || 'base64' === strtolower($properties[0]);
    }
    /**
     * Format path component for file scheme.
     */
    private function formatFilePath(string $path) : string
    {
        if ('file' !== $this->scheme) {
            return $path;
        }
        $replace = static function (array $matches) : string {
            return $matches['delim'] . $matches['volume'] . ':' . $matches['rest'];
        };
        return (string) preg_replace_callback(self::REGEXP_FILE_PATH, $replace, $path);
    }
    /**
    * Format the Query or the Fragment component.
    *
    * Returns a array containing:
    <ul>
    <li> the formatted component (a string or null)</li>
    <li> a boolean flag telling wether the delimiter is to be added to the component
    when building the URI string representation</li>
    </ul>
    *
    * @param ?string $component
    */
    private function formatQueryAndFragment(?string $component) : ?string
    {
        if (null === $component || '' === $component) {
            return $component;
        }
        static $pattern = '/(?:[^' . self::REGEXP_CHARS_UNRESERVED . self::REGEXP_CHARS_SUBDELIM . '%:@\\/\\?]++|%(?![A-Fa-f0-9]{2}))/';
        return preg_replace_callback($pattern, [Uri::class, 'urlEncodeMatch'], $component);
    }
    /**
     * assert the URI internal state is valid.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3
     * @link https://tools.ietf.org/html/rfc3986#section-3.3
     *
     * @throws SyntaxError if the URI is in an invalid state according to RFC3986
     * @throws SyntaxError if the URI is in an invalid state according to scheme specific rules
     */
    private function assertValidState() : void
    {
        if (null !== $this->authority && ('' !== $this->path && '/' !== $this->path[0])) {
            throw new SyntaxError('If an authority is present the path must be empty or start with a `/`.');
        }
        if (null === $this->authority && 0 === strpos($this->path, '//')) {
            throw new SyntaxError(sprintf('If there is no authority the path `%s` can not start with a `//`.', $this->path));
        }
        $pos = strpos($this->path, ':');
        if (null === $this->authority && null === $this->scheme && false !== $pos && false === strpos(\Phabel\Target\Php80\Polyfill::substr($this->path, 0, $pos), '/')) {
            throw new SyntaxError('In absence of a scheme and an authority the first path segment cannot contain a colon (":") character.');
        }
        $validationMethod = self::SCHEME_VALIDATION_METHOD[$this->scheme] ?? null;
        if (null === $validationMethod || true === $this->{$validationMethod}()) {
            $this->uri = null;
            return;
        }
        throw new SyntaxError(sprintf('The uri `%s` is invalid for the `%s` scheme.', (string) $this, $this->scheme));
    }
    /**
     * URI validation for URI schemes which allows only scheme and path components.
     */
    private function isUriWithSchemeAndPathOnly() : bool
    {
        return null === $this->authority && null === $this->query && null === $this->fragment;
    }
    /**
     * URI validation for URI schemes which allows only scheme, host and path components.
     */
    private function isUriWithSchemeHostAndPathOnly() : bool
    {
        return null === $this->user_info && null === $this->port && null === $this->query && null === $this->fragment && !('' != $this->scheme && null === $this->host);
    }
    /**
     * URI validation for URI schemes which disallow the empty '' host.
     */
    private function isNonEmptyHostUri() : bool
    {
        return '' !== $this->host && !(null !== $this->scheme && null === $this->host);
    }
    /**
    * URI validation for URIs schemes which disallow the empty '' host
    and forbids the fragment component.
    */
    private function isNonEmptyHostUriWithoutFragment() : bool
    {
        return $this->isNonEmptyHostUri() && null === $this->fragment;
    }
    /**
    * URI validation for URIs schemes which disallow the empty '' host
    and forbids fragment and query components.
    */
    private function isNonEmptyHostUriWithoutFragmentAndQuery() : bool
    {
        return $this->isNonEmptyHostUri() && null === $this->fragment && null === $this->query;
    }
    /**
     * Generate the URI string representation from its components.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-5.3
     *
     * @param ?string $scheme
     * @param ?string $authority
     * @param ?string $query
     * @param ?string $fragment
     */
    private function getUriString(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment) : string
    {
        if (null !== $scheme) {
            $scheme = $scheme . ':';
        }
        if (null !== $authority) {
            $authority = '//' . $authority;
        }
        if (null !== $query) {
            $query = '?' . $query;
        }
        if (null !== $fragment) {
            $fragment = '#' . $fragment;
        }
        return $scheme . $authority . $path . $query . $fragment;
    }
    /**
     *
     */
    public function toString() : string
    {
        $this->uri = $this->uri ?? $this->getUriString($this->scheme, $this->authority, $this->path, $this->query, $this->fragment);
        return $this->uri;
    }
    /**
     * {@inheritDoc}
     */
    public function __toString() : string
    {
        return $this->toString();
    }
    /**
     * {@inheritDoc}
     */
    public function jsonSerialize() : string
    {
        return $this->toString();
    }
    /**
     * {@inheritDoc}
     *
     * @return array{scheme: ?string, user_info: ?string, host: ?string, port: ?int, path: string, query: ?string, fragment: ?string}
     */
    public function __debugInfo() : array
    {
        return ['scheme' => $this->scheme, 'user_info' => isset($this->user_info) ? preg_replace(',:(.*).?$,', ':***', $this->user_info) : null, 'host' => $this->host, 'port' => $this->port, 'path' => $this->path, 'query' => $this->query, 'fragment' => $this->fragment];
    }
    /**
     * {@inheritDoc}
     */
    public function getScheme() : ?string
    {
        return $this->scheme;
    }
    /**
     * {@inheritDoc}
     */
    public function getAuthority() : ?string
    {
        return $this->authority;
    }
    /**
     * {@inheritDoc}
     */
    public function getUserInfo() : ?string
    {
        return $this->user_info;
    }
    /**
     * {@inheritDoc}
     */
    public function getHost() : ?string
    {
        return $this->host;
    }
    /**
     * {@inheritDoc}
     */
    public function getPort() : ?int
    {
        return $this->port;
    }
    /**
     * {@inheritDoc}
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     * {@inheritDoc}
     */
    public function getQuery() : ?string
    {
        return $this->query;
    }
    /**
     * {@inheritDoc}
     */
    public function getFragment() : ?string
    {
        return $this->fragment;
    }
    /**
     * {@inheritDoc}
     */
    public function withScheme($scheme) : UriInterface
    {
        $scheme = $this->formatScheme($this->filterString($scheme));
        if ($scheme === $this->scheme) {
            return $this;
        }
        $clone = clone $this;
        $clone->scheme = $scheme;
        $clone->port = $clone->formatPort($clone->port);
        $clone->authority = $clone->setAuthority();
        $clone->assertValidState();
        return $clone;
    }
    /**
     * Filter a string.
     *
     * @param mixed $str the value to evaluate as a string
     *
     * @throws SyntaxError if the submitted data can not be converted to string
     */
    private function filterString($str) : ?string
    {
        if (null === $str) {
            return $str;
        }
        if (is_object($str) && method_exists($str, '__toString')) {
            $str = (string) $str;
        }
        if (!is_scalar($str)) {
            throw new \TypeError(sprintf('The component must be a string, a scalar or a stringable object %s given.', gettype($str)));
        }
        $str = (string) $str;
        if (1 !== preg_match(self::REGEXP_INVALID_CHARS, $str)) {
            return $str;
        }
        throw new SyntaxError(sprintf('The component `%s` contains invalid characters.', $str));
    }
    /**
     * {@inheritDoc}
     */
    public function withUserInfo($user, $password = null) : UriInterface
    {
        $user_info = null;
        $user = $this->filterString($user);
        if (null !== $password) {
            $password = $this->filterString($password);
        }
        if ('' !== $user) {
            $user_info = $this->formatUserInfo($user, $password);
        }
        if ($user_info === $this->user_info) {
            return $this;
        }
        $clone = clone $this;
        $clone->user_info = $user_info;
        $clone->authority = $clone->setAuthority();
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withHost($host) : UriInterface
    {
        $host = $this->formatHost($this->filterString($host));
        if ($host === $this->host) {
            return $this;
        }
        $clone = clone $this;
        $clone->host = $host;
        $clone->authority = $clone->setAuthority();
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withPort($port) : UriInterface
    {
        $port = $this->formatPort($port);
        if ($port === $this->port) {
            return $this;
        }
        $clone = clone $this;
        $clone->port = $port;
        $clone->authority = $clone->setAuthority();
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withPath($path) : UriInterface
    {
        $path = $this->filterString($path);
        if (null === $path) {
            throw new \TypeError('A path must be a string NULL given.');
        }
        $path = $this->formatPath($path);
        if ($path === $this->path) {
            return $this;
        }
        $clone = clone $this;
        $clone->path = $path;
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withQuery($query) : UriInterface
    {
        $query = $this->formatQueryAndFragment($this->filterString($query));
        if ($query === $this->query) {
            return $this;
        }
        $clone = clone $this;
        $clone->query = $query;
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withFragment($fragment) : UriInterface
    {
        $fragment = $this->formatQueryAndFragment($this->filterString($fragment));
        if ($fragment === $this->fragment) {
            return $this;
        }
        $clone = clone $this;
        $clone->fragment = $fragment;
        $clone->assertValidState();
        return $clone;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Contracts\UriException;
class TemplateCanNotBeExpanded extends \InvalidArgumentException implements UriException
{
    /**
     *
     */
    public static function dueToUnableToProcessValueListWithPrefix(string $variableName) : self
    {
        return new self('The ":" modifier can not be applied on "' . $variableName . '" since it is a list of values.');
    }
    /**
     *
     */
    public static function dueToNestedListOfValue(string $variableName) : self
    {
        return new self('The "' . $variableName . '" can not be a nested list.');
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\UriTemplate;

use League\Uri\Exceptions\SyntaxError;
use League\Uri\Exceptions\TemplateCanNotBeExpanded;
use function array_filter;
use function array_keys;
use function array_map;
use function array_unique;
use function explode;
use function implode;
use function preg_match;
use function rawurlencode;
use function str_replace;
use function strpos;
use function substr;
final class Expression
{
    /**
     * Expression regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc6570#section-2.2
     */
    private const REGEXP_EXPRESSION = '/^\\{
        (?:
            (?<operator>[\\.\\/;\\?&\\=,\\!@\\|\\+#])?
            (?<variables>[^\\}]*)
        )
    \\}$/x';
    /**
     * Reserved Operator characters.
     *
     * @link https://tools.ietf.org/html/rfc6570#section-2.2
     */
    private const RESERVED_OPERATOR = '=,!@|';
    /**
     * Processing behavior according to the expression type operator.
     *
     * @link https://tools.ietf.org/html/rfc6570#appendix-A
     */
    private const OPERATOR_HASH_LOOKUP = ['' => ['prefix' => '', 'joiner' => ',', 'query' => false], '+' => ['prefix' => '', 'joiner' => ',', 'query' => false], '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false], '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false], '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false], ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true], '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true], '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]];
    /**
     * @var string
     */
    private $operator;
    /**
     * @var string
     */
    private $joiner;
    /**
     * @var array<VarSpecifier>
     */
    private $varSpecifiers;
    /**
     * @var array<string>
     */
    private $variableNames;
    /**
     * @var string
     */
    private $expressionString;
    /**
     *
     */
    private function __construct(string $operator, VarSpecifier ...$varSpecifiers)
    {
        $this->operator = $operator;
        $this->varSpecifiers = $varSpecifiers;
        $this->joiner = self::OPERATOR_HASH_LOOKUP[$operator]['joiner'];
        $this->variableNames = $this->setVariableNames();
        $this->expressionString = $this->setExpressionString();
    }
    /**
     * @return array<string>
     */
    private function setVariableNames() : array
    {
        $mapper = static function (VarSpecifier $varSpecifier) : string {
            return $varSpecifier->name();
        };
        return array_unique(array_map($mapper, $this->varSpecifiers));
    }
    /**
     *
     */
    private function setExpressionString() : string
    {
        $mapper = static function (VarSpecifier $variable) : string {
            return $variable->toString();
        };
        $varSpecifierString = implode(',', array_map($mapper, $this->varSpecifiers));
        return '{' . $this->operator . $varSpecifierString . '}';
    }
    /**
     * {@inheritDoc}
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['operator'], ...$properties['varSpecifiers']);
    }
    /**
     * @throws SyntaxError if the expression is invalid
     * @throws SyntaxError if the operator used in the expression is invalid
     * @throws SyntaxError if the variable specifiers is invalid
     */
    public static function createFromString(string $expression) : self
    {
        if (1 !== preg_match(self::REGEXP_EXPRESSION, $expression, $parts)) {
            throw new SyntaxError('The expression "' . $expression . '" is invalid.');
        }
        /** @var array{operator:string, variables:string} $parts */
        $parts = $parts + ['operator' => ''];
        if ('' !== $parts['operator'] && false !== strpos(self::RESERVED_OPERATOR, $parts['operator'])) {
            throw new SyntaxError('The operator used in the expression "' . $expression . '" is reserved.');
        }
        $mapper = static function (string $varSpec) : VarSpecifier {
            return VarSpecifier::createFromString($varSpec);
        };
        return new Expression($parts['operator'], ...array_map($mapper, explode(',', $parts['variables'])));
    }
    /**
     * Returns the expression string representation.
     *
     */
    public function toString() : string
    {
        return $this->expressionString;
    }
    /**
     * @return array<string>
     */
    public function variableNames() : array
    {
        return $this->variableNames;
    }
    /**
     *
     */
    public function expand(VariableBag $variables) : string
    {
        $parts = [];
        foreach ($this->varSpecifiers as $varSpecifier) {
            $parts[] = $this->replace($varSpecifier, $variables);
        }
        $nullFilter = static function ($value) : bool {
            return '' !== $value;
        };
        $expanded = implode($this->joiner, array_filter($parts, $nullFilter));
        if ('' === $expanded) {
            return $expanded;
        }
        $prefix = self::OPERATOR_HASH_LOOKUP[$this->operator]['prefix'];
        if ('' === $prefix) {
            return $expanded;
        }
        return $prefix . $expanded;
    }
    /**
     * Replaces an expression with the given variables.
     *
     * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied
     * @throws TemplateCanNotBeExpanded if the variables contains nested array values
     */
    private function replace(VarSpecifier $varSpec, VariableBag $variables) : string
    {
        $value = $variables->fetch($varSpec->name());
        if (null === $value) {
            return '';
        }
        $useQuery = self::OPERATOR_HASH_LOOKUP[$this->operator]['query'];
        [$expanded, $actualQuery] = $this->inject($value, $varSpec, $useQuery);
        if (!$actualQuery) {
            return $expanded;
        }
        if ('&' !== $this->joiner && '' === $expanded) {
            return $varSpec->name();
        }
        return $varSpec->name() . '=' . $expanded;
    }
    /**
     * @param (string | array<string>) $value
     *
     * @return array{0: string, 1: bool}
     */
    private function inject($value, VarSpecifier $varSpec, bool $useQuery) : array
    {
        if (is_string($value)) {
            return $this->replaceString($value, $varSpec, $useQuery);
        }
        return $this->replaceList($value, $varSpec, $useQuery);
    }
    /**
     * Expands an expression using a string value.
     *
     * @return array{0: string, 1: bool}
     */
    private function replaceString(string $value, VarSpecifier $varSpec, bool $useQuery) : array
    {
        if (':' === $varSpec->modifier()) {
            $value = \Phabel\Target\Php80\Polyfill::substr($value, 0, $varSpec->position());
        }
        $expanded = rawurlencode($value);
        if ('+' === $this->operator || '#' === $this->operator) {
            return [$this->decodeReserved($expanded), $useQuery];
        }
        return [$expanded, $useQuery];
    }
    /**
     * Expands an expression using a list of values.
     *
     * @param array<string> $value
     *
     * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied
     *
     * @return array{0: string, 1: bool}
     */
    private function replaceList(array $value, VarSpecifier $varSpec, bool $useQuery) : array
    {
        if ([] === $value) {
            return ['', false];
        }
        if (':' === $varSpec->modifier()) {
            throw TemplateCanNotBeExpanded::dueToUnableToProcessValueListWithPrefix($varSpec->name());
        }
        $pairs = [];
        $isAssoc = $this->isAssoc($value);
        foreach ($value as $key => $var) {
            if ($isAssoc) {
                $key = rawurlencode((string) $key);
            }
            $var = rawurlencode($var);
            if ('+' === $this->operator || '#' === $this->operator) {
                $var = $this->decodeReserved($var);
            }
            if ('*' === $varSpec->modifier()) {
                if ($isAssoc) {
                    $var = $key . '=' . $var;
                } elseif ($key > 0 && $useQuery) {
                    $var = $varSpec->name() . '=' . $var;
                }
            }
            $pairs[$key] = $var;
        }
        if ('*' === $varSpec->modifier()) {
            if ($isAssoc) {
                // Don't prepend the value name when using the explode
                // modifier with an associative array.
                $useQuery = false;
            }
            return [implode($this->joiner, $pairs), $useQuery];
        }
        if ($isAssoc) {
            // When an associative array is encountered and the
            // explode modifier is not set, then the result must be
            // a comma separated list of keys followed by their
            // respective values.
            foreach ($pairs as $offset => &$data) {
                $data = $offset . ',' . $data;
            }
            unset($data);
        }
        return [implode(',', $pairs), $useQuery];
    }
    /**
    * Determines if an array is associative.
    *
    * This makes the assumption that input arrays are sequences or hashes.
    This assumption is a trade-off for accuracy in favor of speed, but it
    should work in almost every case where input is supplied for a URI
    template.
    */
    private function isAssoc(array $array) : bool
    {
        return [] !== $array && 0 !== array_keys($array)[0];
    }
    /**
     * Removes percent encoding on reserved characters (used with + and # modifiers).
     */
    private function decodeReserved(string $str) : string
    {
        static $delimiters = [':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='];
        static $delimitersEncoded = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%3B', '%3D'];
        return str_replace($delimitersEncoded, $delimiters, $str);
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\UriTemplate;

use League\Uri\Exceptions\SyntaxError;
use function preg_match;
final class VarSpecifier
{
    /**
     * Variables specification regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc6570#section-2.3
     */
    private const REGEXP_VARSPEC = '/^
        (?<name>(?:[A-z0-9_\\.]|%[0-9a-fA-F]{2})+)
        (?<modifier>\\:(?<position>\\d+)|\\*)?
    $/x';
    /**
     * @var string
     */
    private $name;
    /**
     * @var string
     */
    private $modifier;
    /**
     * @var int
     */
    private $position;
    /**
     *
     */
    private function __construct(string $name, string $modifier, int $position)
    {
        $this->name = $name;
        $this->modifier = $modifier;
        $this->position = $position;
    }
    /**
     * {@inheritDoc}
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['name'], $properties['modifier'], $properties['position']);
    }
    /**
     *
     */
    public static function createFromString(string $specification) : self
    {
        if (1 !== preg_match(self::REGEXP_VARSPEC, $specification, $parsed)) {
            throw new SyntaxError('The variable specification "' . $specification . '" is invalid.');
        }
        $parsed += ['modifier' => '', 'position' => ''];
        if ('' !== $parsed['position']) {
            $parsed['position'] = (int) $parsed['position'];
            $parsed['modifier'] = ':';
        }
        if ('' === $parsed['position']) {
            $parsed['position'] = 0;
        }
        if (10000 <= $parsed['position']) {
            throw new SyntaxError('The variable specification "' . $specification . '" is invalid the position modifier must be lower than 10000.');
        }
        return new self($parsed['name'], $parsed['modifier'], $parsed['position']);
    }
    /**
     *
     */
    public function toString() : string
    {
        if (0 < $this->position) {
            return $this->name . $this->modifier . $this->position;
        }
        return $this->name . $this->modifier;
    }
    /**
     *
     */
    public function name() : string
    {
        return $this->name;
    }
    /**
     *
     */
    public function modifier() : string
    {
        return $this->modifier;
    }
    /**
     *
     */
    public function position() : int
    {
        return $this->position;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\UriTemplate;

use League\Uri\Exceptions\TemplateCanNotBeExpanded;
use function gettype;
use function is_array;
use function is_bool;
use function is_object;
use function is_scalar;
use function method_exists;
use function sprintf;
final class VariableBag
{
    /**
     * @var array<string,string|array<string>>
     */
    private $variables = [];
    /**
     * @param iterable<string, mixed> $variables
     */
    public function __construct(iterable $variables = [])
    {
        foreach ($variables as $name => $value) {
            $this->assign($name, $value);
        }
    }
    /**
     *
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['variables']);
    }
    /**
     * @return array<string, (string | array<string>)>
     */
    public function all() : array
    {
        return $this->variables;
    }
    /**
     * Fetches the variable value if none found returns null.
     *
     * @return (null | string | array<string>)
     */
    public function fetch(string $name)
    {
        return $this->variables[$name] ?? null;
    }
    /**
     * @param (string | array<string>) $value
     */
    public function assign(string $name, $value) : void
    {
        $this->variables[$name] = $this->normalizeValue($value, $name, true);
    }
    /**
     * @param mixed $value the value to be expanded
     *
     * @throws TemplateCanNotBeExpanded if the value contains nested list
     *
     * @return (string | array<string>)
     */
    private function normalizeValue($value, string $name, bool $isNestedListAllowed)
    {
        if (is_bool($value)) {
            return true === $value ? '1' : '0';
        }
        if (null === $value || is_scalar($value) || is_object($value) && method_exists($value, '__toString')) {
            return (string) $value;
        }
        if (!is_array($value)) {
            throw new \TypeError(sprintf('The variable ' . $name . ' must be NULL, a scalar or a stringable object `%s` given', gettype($value)));
        }
        if (!$isNestedListAllowed) {
            throw TemplateCanNotBeExpanded::dueToNestedListOfValue($name);
        }
        foreach ($value as &$var) {
            $var = self::normalizeValue($var, $name, false);
        }
        unset($var);
        return $value;
    }
    /**
     * Replaces elements from passed variables into the current instance.
     */
    public function replace(VariableBag $variables) : self
    {
        $instance = clone $this;
        $instance->variables += $variables->variables;
        return $instance;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\UriTemplate;

use League\Uri\Exceptions\SyntaxError;
use League\Uri\Exceptions\TemplateCanNotBeExpanded;
use function array_merge;
use function array_unique;
use function gettype;
use function is_object;
use function is_string;
use function method_exists;
use function preg_match_all;
use function preg_replace;
use function sprintf;
use function strpos;
use const PREG_SET_ORDER;
final class Template
{
    /**
     * Expression regular expression pattern.
     */
    private const REGEXP_EXPRESSION_DETECTOR = '/\\{[^\\}]*\\}/x';
    /**
     * @var string
     */
    private $template;
    /**
     * @var array<string, Expression>
     */
    private $expressions = [];
    /**
     * @var array<string>
     */
    private $variableNames;
    /**
     *
     */
    private function __construct(string $template, Expression ...$expressions)
    {
        $this->template = $template;
        $variableNames = [];
        foreach ($expressions as $expression) {
            $this->expressions[$expression->toString()] = $expression;
            $variableNames[] = $expression->variableNames();
        }
        $this->variableNames = array_unique(array_merge([], ...$variableNames));
    }
    /**
     * {@inheritDoc}
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['template'], ...array_values($properties['expressions']));
    }
    /**
     * @param (object | string) $template a string or an object with the __toString method
     *
     * @throws \TypeError if the template is not a string or an object with the __toString method
     * @throws SyntaxError if the template contains invalid expressions
     * @throws SyntaxError if the template contains invalid variable specification
     */
    public static function createFromString($template) : self
    {
        if (is_object($template) && method_exists($template, '__toString')) {
            $template = (string) $template;
        }
        if (!is_string($template)) {
            throw new \TypeError(sprintf('The template must be a string or a stringable object %s given.', gettype($template)));
        }
        /** @var string $remainder */
        $remainder = preg_replace(self::REGEXP_EXPRESSION_DETECTOR, '', $template);
        if (false !== strpos($remainder, '{') || false !== strpos($remainder, '}')) {
            throw new SyntaxError('The template "' . $template . '" contains invalid expressions.');
        }
        $names = [];
        preg_match_all(self::REGEXP_EXPRESSION_DETECTOR, $template, $findings, PREG_SET_ORDER);
        $arguments = [];
        foreach ($findings as $finding) {
            if (!isset($names[$finding[0]])) {
                $arguments[] = Expression::createFromString($finding[0]);
                $names[$finding[0]] = 1;
            }
        }
        return new self($template, ...$arguments);
    }
    /**
     *
     */
    public function toString() : string
    {
        return $this->template;
    }
    /**
     * @return array<string>
     */
    public function variableNames() : array
    {
        return $this->variableNames;
    }
    /**
     * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied
     * @throws TemplateCanNotBeExpanded if the variables contains nested array values
     */
    public function expand(VariableBag $variables) : string
    {
        $uriString = $this->template;
        /** @var Expression $expression */
        foreach ($this->expressions as $pattern => $expression) {
            $uriString = str_replace($pattern, $expression->expand($variables), $uriString);
        }
        return $uriString;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Exceptions\IdnaConversionFailed;
use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
use League\Uri\Idna\Idna;
use function array_merge;
use function explode;
use function filter_var;
use function gettype;
use function inet_pton;
use function is_object;
use function is_scalar;
use function method_exists;
use function preg_match;
use function rawurldecode;
use function sprintf;
use function strpos;
use function substr;
use const FILTER_FLAG_IPV6;
use const FILTER_VALIDATE_IP;
/**
 * A class to parse a URI string according to RFC3986.
 *
 * @link    https://tools.ietf.org/html/rfc3986
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   6.0.0
 */
final class UriString
{
    /**
     * Default URI component values.
     */
    private const URI_COMPONENTS = ['scheme' => null, 'user' => null, 'pass' => null, 'host' => null, 'port' => null, 'path' => '', 'query' => null, 'fragment' => null];
    /**
     * Simple URI which do not need any parsing.
     */
    private const URI_SCHORTCUTS = ['' => [], '#' => ['fragment' => ''], '?' => ['query' => ''], '?#' => ['query' => '', 'fragment' => ''], '/' => ['path' => '/'], '//' => ['host' => '']];
    /**
     * Range of invalid characters in URI string.
     */
    private const REGEXP_INVALID_URI_CHARS = '/[\\x00-\\x1f\\x7f]/';
    /**
     * RFC3986 regular expression URI splitter.
     *
     * @link https://tools.ietf.org/html/rfc3986#appendix-B
     */
    private const REGEXP_URI_PARTS = ',^
        (?<scheme>(?<scontent>[^:/?\\#]+):)?    # URI scheme component
        (?<authority>//(?<acontent>[^/?\\#]*))? # URI authority part
        (?<path>[^?\\#]*)                       # URI path component
        (?<query>\\?(?<qcontent>[^\\#]*))?       # URI query component
        (?<fragment>\\#(?<fcontent>.*))?        # URI fragment component
    ,x';
    /**
     * URI scheme regular expresssion.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.1
     */
    private const REGEXP_URI_SCHEME = '/^([a-z][a-z\\d\\+\\.\\-]*)?$/i';
    /**
     * IPvFuture regular expression.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_IP_FUTURE = '/^
        v(?<version>[A-F0-9])+\\.
        (?:
            (?<unreserved>[a-z0-9_~\\-\\.])|
            (?<sub_delims>[!$&\'()*+,;=:])  # also include the : character
        )+
    $/ix';
    /**
     * General registered name regular expression.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_REGISTERED_NAME = '/(?(DEFINE)
        (?<unreserved>[a-z0-9_~\\-])   # . is missing as it is used to separate labels
        (?<sub_delims>[!$&\'()*+,;=])
        (?<encoded>%[A-F0-9]{2})
        (?<reg_name>(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*)
    )
    ^(?:(?&reg_name)\\.)*(?&reg_name)\\.?$/ix';
    /**
     * Invalid characters in host regular expression.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_INVALID_HOST_CHARS = '/
        [:\\/?#\\[\\]@ ]  # gen-delims characters as well as the space character
    /ix';
    /**
     * Invalid path for URI without scheme and authority regular expression.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.3
     */
    private const REGEXP_INVALID_PATH = ',^(([^/]*):)(.*)?/,';
    /**
     * Host and Port splitter regular expression.
     */
    private const REGEXP_HOST_PORT = ',^(?<host>\\[.*\\]|[^:]*)(:(?<port>.*))?$,';
    /**
     * IDN Host detector regular expression.
     */
    private const REGEXP_IDN_PATTERN = '/[^\\x20-\\x7f]/';
    /**
     * Only the address block fe80::/10 can have a Zone ID attach to
     * let's detect the link local significant 10 bits.
     */
    private const ZONE_ID_ADDRESS_BLOCK = "\xfe\x80";
    /**
    * Generate an URI string representation from its parsed representation
    returned by League\Uri\parse() or PHP's parse_url.
    *
    * If you supply your own array, you are responsible for providing
    valid components without their URI delimiters.
    *
    * @link https://tools.ietf.org/html/rfc3986#section-5.3
    * @link https://tools.ietf.org/html/rfc3986#section-7.5
    *
    * @param array{scheme: ?string, user: ?string, pass: ?string, host: ?string, port: ?int, path: string, query: ?string, fragment: ?string} $components
    */
    public static function build(array $components) : string
    {
        $result = $components['path'] ?? '';
        if (isset($components['query'])) {
            $result .= '?' . $components['query'];
        }
        if (isset($components['fragment'])) {
            $result .= '#' . $components['fragment'];
        }
        $scheme = null;
        if (isset($components['scheme'])) {
            $scheme = $components['scheme'] . ':';
        }
        if (!isset($components['host'])) {
            return $scheme . $result;
        }
        $scheme .= '//';
        $authority = $components['host'];
        if (isset($components['port'])) {
            $authority .= ':' . $components['port'];
        }
        if (!isset($components['user'])) {
            return $scheme . $authority . $result;
        }
        $authority = '@' . $authority;
        if (!isset($components['pass'])) {
            return $scheme . $components['user'] . $authority . $result;
        }
        return $scheme . $components['user'] . ':' . $components['pass'] . $authority . $result;
    }
    /**
    * Parse an URI string into its components.
    *
    * This method parses a URI and returns an associative array containing any
    of the various components of the URI that are present.
    *
    * <code>
    $components = (new Parser())->parse('http://foo@test.example.com:42?query#');
    var_export($components);
    //will display
    array(
    'scheme' => 'http',           // the URI scheme component
    'user' => 'foo',              // the URI user component
    'pass' => null,               // the URI pass component
    'host' => 'test.example.com', // the URI host component
    'port' => 42,                 // the URI port component
    'path' => '',                 // the URI path component
    'query' => 'query',           // the URI query component
    'fragment' => '',             // the URI fragment component
    );
    </code>
    *
    * The returned array is similar to PHP's parse_url return value with the following
    differences:
    *
    * <ul>
    <li>All components are always present in the returned array</li>
    <li>Empty and undefined component are treated differently. And empty component is
    set to the empty string while an undefined component is set to the `null` value.</li>
    <li>The path component is never undefined</li>
    <li>The method parses the URI following the RFC3986 rules but you are still
    required to validate the returned components against its related scheme specific rules.</li>
    </ul>
    *
    * @link https://tools.ietf.org/html/rfc3986
    *
    * @param mixed $uri any scalar or stringable object
    *
    * @throws SyntaxError if the URI contains invalid characters
    * @throws SyntaxError if the URI contains an invalid scheme
    * @throws SyntaxError if the URI contains an invalid path
    *
    * @return array{scheme: ?string, user: ?string, pass: ?string, host: ?string, port: ?int, path: string, query: ?string, fragment: ?string}
    */
    public static function parse($uri) : array
    {
        if (is_object($uri) && method_exists($uri, '__toString')) {
            $uri = (string) $uri;
        }
        if (!is_scalar($uri)) {
            throw new \TypeError(sprintf('The uri must be a scalar or a stringable object `%s` given', gettype($uri)));
        }
        $uri = (string) $uri;
        if (isset(self::URI_SCHORTCUTS[$uri])) {
            /** @var array{scheme:?string, user:?string, pass:?string, host:?string, port:?int, path:string, query:?string, fragment:?string} $components */
            $components = array_merge(self::URI_COMPONENTS, self::URI_SCHORTCUTS[$uri]);
            return $components;
        }
        if (1 === preg_match(self::REGEXP_INVALID_URI_CHARS, $uri)) {
            throw new SyntaxError(sprintf('The uri `%s` contains invalid characters', $uri));
        }
        //if the first character is a known URI delimiter parsing can be simplified
        $first_char = $uri[0];
        //The URI is made of the fragment only
        if ('#' === $first_char) {
            [, $fragment] = explode('#', $uri, 2);
            $components = self::URI_COMPONENTS;
            $components['fragment'] = $fragment;
            return $components;
        }
        //The URI is made of the query and fragment
        if ('?' === $first_char) {
            [, $partial] = explode('?', $uri, 2);
            [$query, $fragment] = explode('#', $partial, 2) + [1 => null];
            $components = self::URI_COMPONENTS;
            $components['query'] = $query;
            $components['fragment'] = $fragment;
            return $components;
        }
        //use RFC3986 URI regexp to split the URI
        preg_match(self::REGEXP_URI_PARTS, $uri, $parts);
        $parts += ['query' => '', 'fragment' => ''];
        if (':' === $parts['scheme'] || 1 !== preg_match(self::REGEXP_URI_SCHEME, $parts['scontent'])) {
            throw new SyntaxError(sprintf('The uri `%s` contains an invalid scheme', $uri));
        }
        if ('' === $parts['scheme'] . $parts['authority'] && 1 === preg_match(self::REGEXP_INVALID_PATH, $parts['path'])) {
            throw new SyntaxError(sprintf('The uri `%s` contains an invalid path.', $uri));
        }
        /** @var array{scheme:?string, user:?string, pass:?string, host:?string, port:?int, path:string, query:?string, fragment:?string} $components */
        $components = array_merge(self::URI_COMPONENTS, '' === $parts['authority'] ? [] : self::parseAuthority($parts['acontent']), ['path' => $parts['path'], 'scheme' => '' === $parts['scheme'] ? null : $parts['scontent'], 'query' => '' === $parts['query'] ? null : $parts['qcontent'], 'fragment' => '' === $parts['fragment'] ? null : $parts['fcontent']]);
        return $components;
    }
    /**
     * Parses the URI authority part.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2
     *
     * @throws SyntaxError If the port component is invalid
     *
     * @return array{user: ?string, pass: ?string, host: ?string, port: ?int}
     */
    private static function parseAuthority(string $authority) : array
    {
        $components = ['user' => null, 'pass' => null, 'host' => '', 'port' => null];
        if ('' === $authority) {
            return $components;
        }
        $parts = explode('@', $authority, 2);
        if (isset($parts[1])) {
            [$components['user'], $components['pass']] = explode(':', $parts[0], 2) + [1 => null];
        }
        preg_match(self::REGEXP_HOST_PORT, $parts[1] ?? $parts[0], $matches);
        $matches += ['port' => ''];
        $components['port'] = self::filterPort($matches['port']);
        $components['host'] = self::filterHost($matches['host']);
        return $components;
    }
    /**
     * Filter and format the port component.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     *
     * @throws SyntaxError if the registered name is invalid
     */
    private static function filterPort(string $port) : ?int
    {
        if ('' === $port) {
            return null;
        }
        if (1 === preg_match('/^\\d*$/', $port)) {
            return (int) $port;
        }
        throw new SyntaxError(sprintf('The port `%s` is invalid', $port));
    }
    /**
     * Returns whether a hostname is valid.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     *
     * @throws SyntaxError if the registered name is invalid
     */
    private static function filterHost(string $host) : string
    {
        if ('' === $host) {
            return $host;
        }
        if ('[' !== $host[0] || ']' !== \Phabel\Target\Php80\Polyfill::substr($host, -1)) {
            return self::filterRegisteredName($host);
        }
        if (!self::isIpHost(\Phabel\Target\Php80\Polyfill::substr($host, 1, -1))) {
            throw new SyntaxError(sprintf('Host `%s` is invalid : the IP host is malformed', $host));
        }
        return $host;
    }
    /**
     * Returns whether the host is an IPv4 or a registered named.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     *
     * @throws SyntaxError if the registered name is invalid
     * @throws IdnSupportMissing if IDN support or ICU requirement are not available or met.
     */
    private static function filterRegisteredName(string $host) : string
    {
        $formatted_host = rawurldecode($host);
        if (1 === preg_match(self::REGEXP_REGISTERED_NAME, $formatted_host)) {
            return $host;
        }
        //to test IDN host non-ascii characters must be present in the host
        if (1 !== preg_match(self::REGEXP_IDN_PATTERN, $formatted_host)) {
            throw new SyntaxError(sprintf('Host `%s` is invalid : the host is not a valid registered name', $host));
        }
        $info = Idna::toAscii($host, Idna::IDNA2008_ASCII);
        if (0 !== $info->errors()) {
            throw IdnaConversionFailed::dueToIDNAError($host, $info);
        }
        return $host;
    }
    /**
     * Validates a IPv6/IPvfuture host.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     * @link https://tools.ietf.org/html/rfc6874#section-2
     * @link https://tools.ietf.org/html/rfc6874#section-4
     */
    private static function isIpHost(string $ip_host) : bool
    {
        if (false !== filter_var($ip_host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return true;
        }
        if (1 === preg_match(self::REGEXP_IP_FUTURE, $ip_host, $matches)) {
            return !in_array($matches['version'], ['4', '6'], true);
        }
        $pos = strpos($ip_host, '%');
        if (false === $pos || 1 === preg_match(self::REGEXP_INVALID_HOST_CHARS, rawurldecode(\Phabel\Target\Php80\Polyfill::substr($ip_host, $pos)))) {
            return false;
        }
        $ip_host = \Phabel\Target\Php80\Polyfill::substr($ip_host, 0, $pos);
        return false !== filter_var($ip_host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && 0 === strpos((string) inet_pton($ip_host), self::ZONE_ID_ADDRESS_BLOCK);
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use Psr\Http\Message\UriFactoryInterface;
use Psr\Http\Message\UriInterface;
final class HttpFactory implements UriFactoryInterface
{
    /**
     *
     */
    public function createUri(string $uri = '') : UriInterface
    {
        return Http::createFromString($uri);
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriException;
use League\Uri\Contracts\UriInterface;
use League\Uri\Exceptions\SyntaxError;
use League\Uri\Exceptions\TemplateCanNotBeExpanded;
use League\Uri\UriTemplate\Template;
use League\Uri\UriTemplate\VariableBag;
/**
 * Defines the URI Template syntax and the process for expanding a URI Template into a URI reference.
 *
 * @link    https://tools.ietf.org/html/rfc6570
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   6.1.0
 *
 * Based on GuzzleHttp\UriTemplate class in Guzzle v6.5.
 * @link https://github.com/guzzle/guzzle/blob/6.5/src/UriTemplate.php
 */
final class UriTemplate
{
    /**
     * @var Template
     */
    private $template;
    /**
     * @var VariableBag
     */
    private $defaultVariables;
    /**
     * @param (object | string) $template a string or an object with the __toString method
     *
     * @throws \TypeError if the template is not a string or an object with the __toString method
     * @throws SyntaxError if the template syntax is invalid
     * @throws TemplateCanNotBeExpanded if the template variables are invalid
     */
    public function __construct($template, array $defaultVariables = [])
    {
        $this->template = Template::createFromString($template);
        $this->defaultVariables = $this->filterVariables($defaultVariables);
    }
    /**
     *
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['template']->toString(), $properties['defaultVariables']->all());
    }
    /**
     * Filters out variables for the given template.
     *
     * @param array<string, (string | array<string>)> $variables
     */
    private function filterVariables(array $variables) : VariableBag
    {
        $output = new VariableBag();
        foreach ($this->template->variableNames() as $name) {
            if (isset($variables[$name])) {
                $output->assign($name, $variables[$name]);
            }
        }
        return $output;
    }
    /**
     * The template string.
     */
    public function getTemplate() : string
    {
        return $this->template->toString();
    }
    /**
     * Returns the names of the variables in the template, in order.
     *
     * @return string[]
     */
    public function getVariableNames() : array
    {
        return $this->template->variableNames();
    }
    /**
     * Returns the default values used to expand the template.
     *
     * The returned list only contains variables whose name is part of the current template.
     *
     * @return array<string, (string | array)>
     */
    public function getDefaultVariables() : array
    {
        return $this->defaultVariables->all();
    }
    /**
    * Returns a new instance with the updated default variables.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified default variables.
    *
    * If present, variables whose name is not part of the current template
    possible variable names are removed.
    */
    public function withDefaultVariables(array $defaultDefaultVariables) : self
    {
        $clone = clone $this;
        $clone->defaultVariables = $this->filterVariables($defaultDefaultVariables);
        return $clone;
    }
    /**
     * @throws TemplateCanNotBeExpanded if the variable contains nested array values
     * @throws UriException if the resulting expansion can not be converted to a UriInterface instance
     */
    public function expand(array $variables = []) : UriInterface
    {
        $uriString = $this->template->expand($this->filterVariables($variables)->replace($this->defaultVariables));
        return Uri::createFromString($uriString);
    }
}<?php

$header = <<<EOF
League.Uri (https://uri.thephpleague.com)

(c) Ignace Nyamagana Butera <nyamsprod@gmail.com>

For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
EOF;
$finder = PhpCsFixer\Finder::create()->in(__DIR__ . '/src')->in(__DIR__ . '/benchmark');
$config = new PhpCsFixer\Config();
return $config->setRules(['@PSR2' => true, 'array_syntax' => ['syntax' => 'short'], 'concat_space' => ['spacing' => 'none'], 'header_comment' => ['comment_type' => 'PHPDoc', 'header' => $header, 'location' => 'after_open', 'separate' => 'both'], 'new_with_braces' => true, 'no_blank_lines_after_phpdoc' => true, 'no_empty_phpdoc' => true, 'no_empty_comment' => true, 'no_leading_import_slash' => true, 'no_superfluous_phpdoc_tags' => true, 'no_trailing_comma_in_singleline_array' => true, 'no_unused_imports' => true, 'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'], 'phpdoc_add_missing_param_annotation' => ['only_untyped' => false], 'phpdoc_align' => true, 'phpdoc_no_empty_return' => true, 'phpdoc_order' => true, 'phpdoc_scalar' => true, 'phpdoc_to_comment' => true, 'phpdoc_summary' => true, 'psr_autoloading' => true, 'return_type_declaration' => ['space_before' => 'none'], 'single_blank_line_before_namespace' => true, 'single_quote' => true, 'space_after_semicolon' => true, 'ternary_operator_spaces' => true, 'trailing_comma_in_multiline' => true, 'trim_array_spaces' => true, 'whitespace_after_comma_in_array' => true, 'yoda_style' => true])->setFinder($finder);{
    "name": "league/uri",
    "type": "library",
    "description" : "URI manipulation library",
    "keywords": [
        "url",
        "uri",
        "rfc3986",
        "rfc3987",
        "rfc6570",
        "psr-7",
        "parse_url",
        "http",
        "https",
        "ws",
        "ftp",
        "data-uri",
        "file-uri",
        "middleware",
        "parse_str",
        "query-string",
        "querystring",
        "hostname",
        "uri-template"
    ],
    "license": "MIT",
    "homepage": "http://uri.thephpleague.com",
    "authors": [
        {
            "name" : "Ignace Nyamagana Butera",
            "email" : "nyamsprod@gmail.com",
            "homepage" : "https://nyamsprod.com"
        }
    ],
    "support": {
        "forum": "https://thephpleague.slack.com",
        "docs": "https://uri.thephpleague.com",
        "issues": "https://github.com/thephpleague/uri/issues"
    },
    "funding": [
        {
            "type": "github",
            "url": "https://github.com/sponsors/nyamsprod"
        }
    ],
    "require": {
        "php": "^7.3 || ^8.0",
        "ext-json": "*",
        "psr/http-message": "^1.0",
        "league/uri-interfaces": "^2.3"
    },
    "require-dev": {
        "friendsofphp/php-cs-fixer": "^2.19 || ^3.0",
        "phpunit/phpunit" : "^8.0 || ^9.0",
        "phpstan/phpstan": "^0.12.90",
        "phpstan/phpstan-strict-rules": "^0.12.11",
        "phpstan/phpstan-phpunit": "^0.12.22",
        "psr/http-factory": "^1.0"
    },
    "autoload": {
        "psr-4": {
            "League\\Uri\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "LeagueTest\\Uri\\": "tests"
        }
    },
    "conflict": {
        "league/uri-schemes": "^1.0"
    },
    "scripts": {
        "phpcs": "php-cs-fixer fix -v --diff --dry-run --allow-risky=yes --ansi",
        "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi",
        "phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi --memory-limit=256M",
        "phpunit": "phpunit --coverage-text",
        "test": [
            "@phpunit",
            "@phpstan",
            "@phpcs"
        ]
    },
    "scripts-descriptions": {
        "phpcs": "Runs coding style test suite",
        "phpstan": "Runs complete codebase static analysis",
        "phpunit": "Runs unit and functional testing",
        "test": "Runs full test suite"
    },
    "suggest": {
        "league/uri-components" : "Needed to easily manipulate URI objects",
        "ext-intl" : "Needed to improve host validation",
        "ext-fileinfo": "Needed to create Data URI from a filepath",
        "psr/http-factory": "Needed to use the URI factory"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "6.x-dev"
        }
    },
    "config": {
        "sort-packages": true
    }
}
<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

/**
 * An exception thrown if the IDN support is missing or
 * the ICU is not at least version 4.6.
 *
 * @see     https://tools.ietf.org/html/rfc3986
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   1.4.0
 */
class MissingIdnSupport extends Exception
{
}<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use InvalidArgumentException;
/**
 * An exception thrown on parse attempts of invalid URIs.
 *
 * @see     https://tools.ietf.org/html/rfc3986
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   0.2.0
 */
class Exception extends InvalidArgumentException
{
    /**
     * Returns a new Instance from an error in URI characters.
     *
     * @return static
     */
    public static function createFromInvalidCharacters(string $uri)
    {
        return new static(sprintf('The submitted uri `%s` contains invalid characters', $uri));
    }
    /**
     * Returns a new Instance from an error in URI characters.
     *
     * @return static
     */
    public static function createFromInvalidScheme(string $uri)
    {
        return new static(sprintf('The submitted uri `%s` contains an invalid scheme', $uri));
    }
    /**
     * Returns a new Instance from an error in Host validation.
     *
     * @return static
     */
    public static function createFromInvalidHost(string $host)
    {
        return new static(sprintf('The submitted host `%s` is invalid', $host));
    }
    /**
     * Returns a new Instance from an error in port validation.
     *
     * @return static
     */
    public static function createFromInvalidHostname(string $hostname)
    {
        return new static(sprintf('The submitted hostname `%s` is invalid', $hostname));
    }
    /**
     * Returns a new Instance from an error in port validation.
     *
     * @param (string | int) $port
     *
     * @return static
     */
    public static function createFromInvalidPort($port)
    {
        return new static(sprintf('The submitted port `%s` is invalid', $port));
    }
    /**
     * Returns a new Instance from an error in Uri path component.
     *
     * @return static
     */
    public static function createFromInvalidPath(string $uri)
    {
        return new static(sprintf('The submitted uri `%s` contains an invalid path', $uri));
    }
}<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

/**
 * Returns whether the URI host component is valid according to RFC3986.
 *
 * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
 * @see Parser::isHost()
 */
function is_host(string $host) : bool
{
    static $parser;
    $parser = $parser ?? new Parser();
    return $parser->isHost($host);
}
/**
 * Returns whether the URI port component is valid according to RFC3986.
 *
 * @see https://tools.ietf.org/html/rfc3986#section-3.2.3
 * @see Parser::isPort()
 */
function is_port($port) : bool
{
    static $parser;
    $parser = $parser ?? new Parser();
    return $parser->isPort($port);
}
/**
 * Returns whether the URI scheme component is valid according to RFC3986.
 *
 * @see https://tools.ietf.org/html/rfc3986#section-3.1
 * @see Parser::isScheme()
 */
function is_scheme(string $scheme) : bool
{
    static $parser;
    $parser = $parser ?? new Parser();
    return $parser->isScheme($scheme);
}
/**
* Parse an URI string into its components.
*
* This method parses a URL and returns an associative array containing any
of the various components of the URL that are present.
*
* @see https://tools.ietf.org/html/rfc3986
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see Parser::parse()
*
* @throws Exception if the URI contains invalid characters
*/
function parse(string $uri) : array
{
    static $parser;
    $parser = $parser ?? new Parser();
    return $parser->parse($uri);
}
/**
* Generate an URI string representation from its parsed representation
returned by League\Uri\Parser::parse() or PHP's parse_url.
*
* If you supply your own array, you are responsible for providing
valid components without their URI delimiters.
*
* For security reasons the password (pass) component has been deprecated
as per RFC3986 and is never returned in the URI string
*
* @see https://tools.ietf.org/html/rfc3986#section-5.3
* @see https://tools.ietf.org/html/rfc3986#section-7.5
*/
function build(array $components) : string
{
    $uri = $components['path'] ?? '';
    if (isset($components['query'])) {
        $uri .= '?' . $components['query'];
    }
    if (isset($components['fragment'])) {
        $uri .= '#' . $components['fragment'];
    }
    if (isset($components['host'])) {
        $authority = $components['host'];
        if (isset($components['port'])) {
            $authority .= ':' . $components['port'];
        }
        if (isset($components['user'])) {
            $authority = $components['user'] . '@' . $authority;
        }
        $uri = '//' . $authority . $uri;
    }
    if (isset($components['scheme'])) {
        return $components['scheme'] . ':' . $uri;
    }
    return $uri;
}<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if (!function_exists('League\\Uri\\parse')) {
    require __DIR__ . '/functions.php';
}<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use UnexpectedValueException;
/**
 * A class to parse a URI string according to RFC3986.
 *
 * @see     https://tools.ietf.org/html/rfc3986
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   0.1.0
 */
class Parser
{
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const INVALID_URI_CHARS = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const SCHEME_VALID_STARTING_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const SCHEME_VALID_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-';
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const LABEL_VALID_STARTING_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const LOCAL_LINK_PREFIX = '1111111010';
    const URI_COMPONENTS = ['scheme' => null, 'user' => null, 'pass' => null, 'host' => null, 'port' => null, 'path' => '', 'query' => null, 'fragment' => null];
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const SUB_DELIMITERS = '!$&\'()*+,;=';
    /**
     * Returns whether a scheme is valid.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.1
     */
    public function isScheme(string $scheme) : bool
    {
        static $pattern = '/^[a-z][a-z0-9\\+\\.\\-]*$/i';
        return '' === $scheme || 1 === preg_match($pattern, $scheme);
    }
    /**
     * Returns whether a hostname is valid.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    public function isHost(string $host) : bool
    {
        return '' === $host || $this->isIpHost($host) || $this->isRegisteredName($host);
    }
    /**
     * Validate a IPv6/IPvfuture host.
     *
     * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
     * @see http://tools.ietf.org/html/rfc6874#section-2
     * @see http://tools.ietf.org/html/rfc6874#section-4
     */
    private function isIpHost(string $host) : bool
    {
        if ('[' !== ($host[0] ?? '') || ']' !== \Phabel\Target\Php80\Polyfill::substr($host, -1)) {
            return false;
        }
        $ip = \Phabel\Target\Php80\Polyfill::substr($host, 1, -1);
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return true;
        }
        static $ip_future = '/^
            v(?<version>[A-F0-9])+\\.
            (?:
                (?<unreserved>[a-z0-9_~\\-\\.])|
                (?<sub_delims>[!$&\'()*+,;=:])  # also include the : character
            )+
        $/ix';
        if (1 === preg_match($ip_future, $ip, $matches) && !in_array($matches['version'], ['4', '6'], true)) {
            return true;
        }
        if (false === ($pos = strpos($ip, '%'))) {
            return false;
        }
        static $gen_delims = '/[:\\/?#\\[\\]@ ]/';
        // Also includes space.
        if (1 === preg_match($gen_delims, rawurldecode(\Phabel\Target\Php80\Polyfill::substr($ip, $pos)))) {
            return false;
        }
        $ip = \Phabel\Target\Php80\Polyfill::substr($ip, 0, $pos);
        if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return false;
        }
        //Only the address block fe80::/10 can have a Zone ID attach to
        //let's detect the link local significant 10 bits
        static $address_block = "\xfe\x80";
        return 0 === strpos((string) inet_pton($ip), $address_block);
    }
    /**
    * Returns whether the host is an IPv4 or a registered named.
    *
    * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
    *
    * @throws MissingIdnSupport if the registered name contains non-ASCII characters
    and IDN support or ICU requirement are not available or met.
    *
    */
    protected function isRegisteredName(string $host) : bool
    {
        // Note that unreserved is purposely missing . as it is used to separate labels.
        static $reg_name = '/(?(DEFINE)
                (?<unreserved>[a-z0-9_~\\-])
                (?<sub_delims>[!$&\'()*+,;=])
                (?<encoded>%[A-F0-9]{2})
                (?<reg_name>(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*)
            )
            ^(?:(?&reg_name)\\.)*(?&reg_name)\\.?$/ix';
        if (1 === preg_match($reg_name, $host)) {
            return true;
        }
        //to test IDN host non-ascii characters must be present in the host
        static $idn_pattern = '/[^\\x20-\\x7f]/';
        if (1 !== preg_match($idn_pattern, $host)) {
            return false;
        }
        static $idn_support = null;
        $idn_support = $idn_support ?? function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46');
        // @codeCoverageIgnoreStart
        // added because it is not possible in travis to disabled the ext/intl extension
        // see travis issue https://github.com/travis-ci/travis-ci/issues/4701
        if (!$idn_support) {
            throw new MissingIdnSupport(sprintf('the host `%s` could not be processed for IDN. Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.', $host));
        }
        // @codeCoverageIgnoreEnd
        $ascii_host = idn_to_ascii($host, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46, $arr);
        // @codeCoverageIgnoreStart
        if (false === $ascii_host && 0 === $arr['errors']) {
            throw new UnexpectedValueException(sprintf('The Intl extension is misconfigured for %s, please correct this issue before proceeding.', PHP_OS));
        }
        // @codeCoverageIgnoreEnd
        return 0 === $arr['errors'];
    }
    /**
     * Returns whether a port is valid.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    public function isPort($port) : bool
    {
        static $pattern = '/^[0-9]+$/';
        if (null === $port || '' === $port) {
            return true;
        }
        return 1 === preg_match($pattern, (string) $port);
    }
    /**
     * Parse a URI string into its components.
     *
     * @see Parser::parse
     *
     * @throws Exception if the URI contains invalid characters
     */
    public function __invoke(string $uri) : array
    {
        return $this->parse($uri);
    }
    /**
    * Parse an URI string into its components.
    *
    * This method parses a URI and returns an associative array containing any
    of the various components of the URI that are present.
    *
    * <code>
    $components = (new Parser())->parse('http://foo@test.example.com:42?query#');
    var_export($components);
    //will display
    array(
    'scheme' => 'http',           // the URI scheme component
    'user' => 'foo',              // the URI user component
    'pass' => null,               // the URI pass component
    'host' => 'test.example.com', // the URI host component
    'port' => 42,                 // the URI port component
    'path' => '',                 // the URI path component
    'query' => 'query',           // the URI query component
    'fragment' => '',             // the URI fragment component
    );
    </code>
    *
    * The returned array is similar to PHP's parse_url return value with the following
    differences:
    *
    * <ul>
    <li>All components are always present in the returned array</li>
    <li>Empty and undefined component are treated differently. And empty component is
    set to the empty string while an undefined component is set to the `null` value.</li>
    <li>The path component is never undefined</li>
    <li>The method parses the URI following the RFC3986 rules but you are still
    required to validate the returned components against its related scheme specific rules.</li>
    </ul>
    *
    * @see https://tools.ietf.org/html/rfc3986
    * @see https://tools.ietf.org/html/rfc3986#section-2
    *
    * @throws Exception if the URI contains invalid characters
    */
    public function parse(string $uri) : array
    {
        static $pattern = '/[\\x00-\\x1f\\x7f]/';
        //simple URI which do not need any parsing
        static $simple_uri = ['' => [], '#' => ['fragment' => ''], '?' => ['query' => ''], '?#' => ['query' => '', 'fragment' => ''], '/' => ['path' => '/'], '//' => ['host' => '']];
        if (isset($simple_uri[$uri])) {
            return array_merge(self::URI_COMPONENTS, $simple_uri[$uri]);
        }
        if (1 === preg_match($pattern, $uri)) {
            throw Exception::createFromInvalidCharacters($uri);
        }
        //if the first character is a known URI delimiter parsing can be simplified
        $first_char = $uri[0];
        //The URI is made of the fragment only
        if ('#' === $first_char) {
            $components = self::URI_COMPONENTS;
            $components['fragment'] = (string) \Phabel\Target\Php80\Polyfill::substr($uri, 1);
            return $components;
        }
        //The URI is made of the query and fragment
        if ('?' === $first_char) {
            $components = self::URI_COMPONENTS;
            list($components['query'], $components['fragment']) = explode('#', \Phabel\Target\Php80\Polyfill::substr($uri, 1), 2) + [1 => null];
            return $components;
        }
        //The URI does not contain any scheme part
        if (0 === strpos($uri, '//')) {
            return $this->parseSchemeSpecificPart($uri);
        }
        //The URI is made of a path, query and fragment
        if ('/' === $first_char || false === strpos($uri, ':')) {
            return $this->parsePathQueryAndFragment($uri);
        }
        //Fallback parser
        return $this->fallbackParser($uri);
    }
    /**
    * Extract components from a URI without a scheme part.
    *
    * The URI MUST start with the authority component
    preceded by its delimiter the double slash ('//')
    *
    * Example: //user:pass@host:42/path?query#fragment
    *
    * The authority MUST adhere to the RFC3986 requirements.
    *
    * If the URI contains a path component, it MUST be empty or absolute
    according to RFC3986 path classification.
    *
    * This method returns an associative array containing all URI components.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.2
    * @see https://tools.ietf.org/html/rfc3986#section-3.3
    *
    * @throws Exception If any component of the URI is invalid
    */
    protected function parseSchemeSpecificPart(string $uri) : array
    {
        //We remove the authority delimiter
        $remaining_uri = (string) \Phabel\Target\Php80\Polyfill::substr($uri, 2);
        $components = self::URI_COMPONENTS;
        //Parsing is done from the right upmost part to the left
        //1 - detect fragment, query and path part if any
        list($remaining_uri, $components['fragment']) = explode('#', $remaining_uri, 2) + [1 => null];
        list($remaining_uri, $components['query']) = explode('?', $remaining_uri, 2) + [1 => null];
        if (false !== strpos($remaining_uri, '/')) {
            list($remaining_uri, $components['path']) = explode('/', $remaining_uri, 2) + [1 => null];
            $components['path'] = '/' . $components['path'];
        }
        //2 - The $remaining_uri represents the authority part
        //if the authority part is empty parsing is simplified
        if ('' === $remaining_uri) {
            $components['host'] = '';
            return $components;
        }
        //otherwise we split the authority into the user information and the hostname parts
        $parts = explode('@', $remaining_uri, 2);
        $hostname = $parts[1] ?? $parts[0];
        $user_info = isset($parts[1]) ? $parts[0] : null;
        if (null !== $user_info) {
            list($components['user'], $components['pass']) = explode(':', $user_info, 2) + [1 => null];
        }
        list($components['host'], $components['port']) = $this->parseHostname($hostname);
        return $components;
    }
    /**
     * Parse and validate the URI hostname.
     *
     * @throws Exception If the hostname is invalid
     */
    protected function parseHostname(string $hostname) : array
    {
        if (false === strpos($hostname, '[')) {
            list($host, $port) = explode(':', $hostname, 2) + [1 => null];
            return [$this->filterHost($host), $this->filterPort($port)];
        }
        $delimiter_offset = strpos($hostname, ']') + 1;
        if (isset($hostname[$delimiter_offset]) && ':' !== $hostname[$delimiter_offset]) {
            throw Exception::createFromInvalidHostname($hostname);
        }
        return [$this->filterHost(\Phabel\Target\Php80\Polyfill::substr($hostname, 0, $delimiter_offset)), $this->filterPort(\Phabel\Target\Php80\Polyfill::substr($hostname, ++$delimiter_offset))];
    }
    /**
     * validate the host component.
     *
     * @param (string | null) $host
     *
     * @throws Exception If the hostname is invalid
     *
     * @return (string | null)
     */
    protected function filterHost($host)
    {
        if (null === $host || $this->isHost($host)) {
            return $host;
        }
        throw Exception::createFromInvalidHost($host);
    }
    /**
     * Validate a port number.
     *
     * An exception is raised for ports outside the established TCP and UDP port ranges.
     *
     * @param mixed $port the port number
     *
     * @throws Exception If the port number is invalid.
     *
     * @return (null | int)
     */
    protected function filterPort($port)
    {
        static $pattern = '/^[0-9]+$/';
        if (null === $port || false === $port || '' === $port) {
            return null;
        }
        if (1 !== preg_match($pattern, (string) $port)) {
            throw Exception::createFromInvalidPort($port);
        }
        return (int) $port;
    }
    /**
    * Extract Components from an URI without scheme or authority part.
    *
    * The URI contains a path component and MUST adhere to path requirements
    of RFC3986. The path can be
    *
    * <code>
    path   = path-abempty    ; begins with "/" or is empty
    / path-absolute   ; begins with "/" but not "//"
    / path-noscheme   ; begins with a non-colon segment
    / path-rootless   ; begins with a segment
    / path-empty      ; zero characters
    </code>
    *
    * ex: path?q#f
    ex: /path
    ex: /pa:th#f
    *
    * This method returns an associative array containing all URI components.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.3
    *
    * @throws Exception If the path component is invalid
    */
    protected function parsePathQueryAndFragment(string $uri) : array
    {
        //No scheme is present so we ensure that the path respects RFC3986
        if (false !== ($pos = strpos($uri, ':')) && false === strpos(\Phabel\Target\Php80\Polyfill::substr($uri, 0, $pos), '/')) {
            throw Exception::createFromInvalidPath($uri);
        }
        $components = self::URI_COMPONENTS;
        //Parsing is done from the right upmost part to the left
        //1 - detect the fragment part if any
        list($remaining_uri, $components['fragment']) = explode('#', $uri, 2) + [1 => null];
        //2 - detect the query and the path part
        list($components['path'], $components['query']) = explode('?', $remaining_uri, 2) + [1 => null];
        return $components;
    }
    /**
    * Extract components from an URI containing a colon.
    *
    * Depending on the colon ":" position and on the string
    composition before the presence of the colon, the URI
    will be considered to have an scheme or not.
    *
    * <ul>
    <li>In case no valid scheme is found according to RFC3986 the URI will
    be parsed as an URI without a scheme and an authority</li>
    <li>In case an authority part is detected the URI specific part is parsed
    as an URI without scheme</li>
    </ul>
    *
    * ex: email:johndoe@thephpleague.com?subject=Hellow%20World!
    *
    * This method returns an associative array containing all
    the URI components.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.1
    * @see Parser::parsePathQueryAndFragment
    * @see Parser::parseSchemeSpecificPart
    *
    * @throws Exception If the URI scheme component is empty
    */
    protected function fallbackParser(string $uri) : array
    {
        //1 - we split the URI on the first detected colon character
        $parts = explode(':', $uri, 2);
        $remaining_uri = $parts[1] ?? $parts[0];
        $scheme = isset($parts[1]) ? $parts[0] : null;
        //1.1 - a scheme can not be empty (ie a URI can not start with a colon)
        if ('' === $scheme) {
            throw Exception::createFromInvalidScheme($uri);
        }
        //2 - depending on the scheme presence and validity we will differ the parsing
        //2.1 - If the scheme part is invalid the URI may be an URI with a path-noscheme
        //      let's differ the parsing to the Parser::parsePathQueryAndFragment method
        if (!$this->isScheme($scheme)) {
            return $this->parsePathQueryAndFragment($uri);
        }
        $components = self::URI_COMPONENTS;
        $components['scheme'] = $scheme;
        //2.2 - if no scheme specific part is detect parsing is finished
        if ('' == $remaining_uri) {
            return $components;
        }
        //2.3 - if the scheme specific part is a double forward slash
        if ('//' === $remaining_uri) {
            $components['host'] = '';
            return $components;
        }
        //2.4 - if the scheme specific part starts with double forward slash
        //      we differ the remaining parsing to the Parser::parseSchemeSpecificPart method
        if (0 === strpos($remaining_uri, '//')) {
            $components = $this->parseSchemeSpecificPart($remaining_uri);
            $components['scheme'] = $scheme;
            return $components;
        }
        //2.5 - Parsing is done from the right upmost part to the left from the scheme specific part
        //2.5.1 - detect the fragment part if any
        list($remaining_uri, $components['fragment']) = explode('#', $remaining_uri, 2) + [1 => null];
        //2.5.2 - detect the part and query part if any
        list($components['path'], $components['query']) = explode('?', $remaining_uri, 2) + [1 => null];
        return $components;
    }
    /**
    * Convert a registered name label to its IDNA ASCII form.
    *
    * DEPRECATION WARNING! This method will be removed in the next major point release
    *
    * @deprecated 1.4.0 this method is no longer used to validate RFC3987 compliant host component
    * @codeCoverageIgnore
    *
    * Conversion is done only if the label contains none valid label characters
    if a '%' sub delimiter is detected the label MUST be rawurldecode prior to
    making the conversion
    *
    * @return (string | false)
    */
    protected function toAscii(string $label)
    {
        trigger_error(self::class . '::' . __METHOD__ . ' is deprecated and will be removed in the next major point release', E_USER_DEPRECATED);
        if (false !== strpos($label, '%')) {
            $label = rawurldecode($label);
        }
        static $idn_support = null;
        $idn_support = $idn_support ?? function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46');
        if (!$idn_support) {
            throw new MissingIdnSupport(sprintf('the label `%s` could not be processed for IDN. Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.', $label));
        }
        $ascii_host = idn_to_ascii($label, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46, $arr);
        if (false === $ascii_host && 0 === $arr['errors']) {
            throw new UnexpectedValueException(sprintf('The Intl extension is misconfigured for %s, please correct this issue before proceeding.', PHP_OS));
        }
        return $ascii_host;
    }
    /**
     * Returns whether the registered name label is valid.
     *
     * DEPRECATION WARNING! This method will be removed in the next major point release
     *
     * @deprecated 1.4.0 this method is no longer used to validated the host component
     * @codeCoverageIgnore
     *
     * A valid registered name label MUST conform to the following ABNF
     *
     * reg-name = *( unreserved / pct-encoded / sub-delims )
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     *
     * @param string $label
     */
    protected function isHostLabel($label) : bool
    {
        trigger_error(self::class . '::' . __METHOD__ . ' is deprecated and will be removed in the next major point release', E_USER_DEPRECATED);
        return '' != $label && 63 >= strlen($label) && strlen($label) == \Phabel\Target\Php80\Polyfill::strspn($label, self::LABEL_VALID_STARTING_CHARS . '-_~' . self::SUB_DELIMITERS);
    }
    /**
     * Validate an IPv6 host.
     *
     * DEPRECATION WARNING! This method will be removed in the next major point release
     *
     * @deprecated 1.4.0 this method is no longer used to validated the host component
     * @codeCoverageIgnore
     *
     * @see http://tools.ietf.org/html/rfc6874#section-2
     * @see http://tools.ietf.org/html/rfc6874#section-4
     */
    protected function isIpv6Host(string $ipv6) : bool
    {
        trigger_error(self::class . '::' . __METHOD__ . ' is deprecated and will be removed in the next major point release', E_USER_DEPRECATED);
        if ('[' !== ($ipv6[0] ?? '') || ']' !== \Phabel\Target\Php80\Polyfill::substr($ipv6, -1)) {
            return false;
        }
        $ipv6 = \Phabel\Target\Php80\Polyfill::substr($ipv6, 1, -1);
        if (false === ($pos = strpos($ipv6, '%'))) {
            return (bool) filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
        }
        $scope = rawurldecode(\Phabel\Target\Php80\Polyfill::substr($ipv6, $pos));
        if (strlen($scope) !== \Phabel\Target\Php80\Polyfill::strcspn($scope, '?#@[]')) {
            return false;
        }
        $ipv6 = \Phabel\Target\Php80\Polyfill::substr($ipv6, 0, $pos);
        if (!filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return false;
        }
        //Only the address block fe80::/10 can have a Zone ID attach to
        //let's detect the link local significant 10 bits
        return 0 === strpos((string) inet_pton($ipv6), "\xfe\x80");
    }
}{
    "name": "league/uri-parser",
    "type": "library",
    "description" : "userland URI parser RFC 3986 compliant",
    "keywords": [
        "url",
        "uri",
        "rfc3986",
        "rfc3987",
        "parse_url",
        "parser"
    ],
    "license": "MIT",
    "homepage": "https://github.com/thephpleague/uri-parser",
    "authors": [
        {
            "name" : "Ignace Nyamagana Butera",
            "email" : "nyamsprod@gmail.com",
            "homepage" : "https://nyamsprod.com"
        }
    ],
    "require": {
        "php" : ">=7.0.0"
    },
    "require-dev": {
        "friendsofphp/php-cs-fixer": "^2.0",
        "phpunit/phpunit" : "^6.0",
        "phpstan/phpstan": "^0.9.2",
        "phpstan/phpstan-strict-rules": "^0.9.0",
        "phpstan/phpstan-phpunit": "^0.9.4"
    },
    "autoload": {
        "psr-4": {
            "League\\Uri\\": "src"
        },
        "files": ["src/functions_include.php"]
    },
    "autoload-dev": {
        "psr-4": {
            "LeagueTest\\Uri\\Parser\\": "tests"
        }
    },
    "suggest": {
        "ext-intl" : "Allow parsing RFC3987 compliant hosts",
        "league/uri-schemes": "Allow validating and normalizing URI parsing results"
    },
    "scripts": {
        "phpcs": "php-cs-fixer fix -v --diff --dry-run --allow-risky=yes;",
        "phpstan-src": "phpstan analyse -l 7 -c phpstan.src.neon src",
        "phpstan-tests": "phpstan analyse -l 7 -c phpstan.tests.neon tests",
        "phpstan": [
            "@phpstan-src",
            "@phpstan-tests"
        ],
        "phpunit": "phpunit --coverage-text",
        "test": [
            "@phpunit",
            "@phpcs",
            "@phpstan"
        ]
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    },
    "config": {
        "sort-packages": true
    }
}
<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Idna;

use function array_filter;
use const ARRAY_FILTER_USE_KEY;
/**
 * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html
 */
final class IdnaInfo
{
    private const ERRORS = [Idna::ERROR_EMPTY_LABEL => 'a non-final domain name label (or the whole domain name) is empty', Idna::ERROR_LABEL_TOO_LONG => 'a domain name label is longer than 63 bytes', Idna::ERROR_DOMAIN_NAME_TOO_LONG => 'a domain name is longer than 255 bytes in its storage form', Idna::ERROR_LEADING_HYPHEN => 'a label starts with a hyphen-minus ("-")', Idna::ERROR_TRAILING_HYPHEN => 'a label ends with a hyphen-minus ("-")', Idna::ERROR_HYPHEN_3_4 => 'a label contains hyphen-minus ("-") in the third and fourth positions', Idna::ERROR_LEADING_COMBINING_MARK => 'a label starts with a combining mark', Idna::ERROR_DISALLOWED => 'a label or domain name contains disallowed characters', Idna::ERROR_PUNYCODE => 'a label starts with "xn--" but does not contain valid Punycode', Idna::ERROR_LABEL_HAS_DOT => 'a label contains a dot=full stop', Idna::ERROR_INVALID_ACE_LABEL => 'An ACE label does not contain a valid label string', Idna::ERROR_BIDI => 'a label does not meet the IDNA BiDi requirements (for right-to-left characters)', Idna::ERROR_CONTEXTJ => 'a label does not meet the IDNA CONTEXTJ requirements', Idna::ERROR_CONTEXTO_DIGITS => 'a label does not meet the IDNA CONTEXTO requirements for digits', Idna::ERROR_CONTEXTO_PUNCTUATION => 'a label does not meet the IDNA CONTEXTO requirements for punctuation characters. Some punctuation characters "Would otherwise have been DISALLOWED" but are allowed in certain contexts'];
    /** @var string */
    private $result;
    /** @var bool */
    private $isTransitionalDifferent;
    /** @var int */
    private $errors;
    /**
     * @var array<int, string>
     */
    private $errorList;
    /**
     *
     */
    private function __construct(string $result, bool $isTransitionalDifferent, int $errors)
    {
        $this->result = $result;
        $this->errors = $errors;
        $this->isTransitionalDifferent = $isTransitionalDifferent;
        $this->errorList = array_filter(self::ERRORS, function (int $error) : bool {
            return 0 !== ($error & $this->errors);
        }, ARRAY_FILTER_USE_KEY);
    }
    /**
     * @param array{result: string, isTransitionalDifferent: bool, errors: int} $infos
     */
    public static function fromIntl(array $infos) : self
    {
        return new self($infos['result'], $infos['isTransitionalDifferent'], $infos['errors']);
    }
    /**
     * @param array{result: string, isTransitionalDifferent: bool, errors: int} $properties
     */
    public static function __set_state(array $properties) : self
    {
        return self::fromIntl($properties);
    }
    /**
     *
     */
    public function result() : string
    {
        return $this->result;
    }
    /**
     *
     */
    public function isTransitionalDifferent() : bool
    {
        return $this->isTransitionalDifferent;
    }
    /**
     *
     */
    public function errors() : int
    {
        return $this->errors;
    }
    /**
     *
     */
    public function error(int $error) : ?string
    {
        return $this->errorList[$error] ?? null;
    }
    /**
     * @return array<int, string>
     */
    public function errorList() : array
    {
        return $this->errorList;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Idna;

use League\Uri\Exceptions\IdnaConversionFailed;
use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
use function defined;
use function function_exists;
use function idn_to_ascii;
use function idn_to_utf8;
use function rawurldecode;
use const INTL_IDNA_VARIANT_UTS46;
/**
 * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html
 */
final class Idna
{
    private const REGEXP_IDNA_PATTERN = '/[^\\x20-\\x7f]/';
    private const MAX_DOMAIN_LENGTH = 253;
    private const MAX_LABEL_LENGTH = 63;
    /**
     * General registered name regular expression.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     * @see https://regex101.com/r/fptU8V/1
     */
    private const REGEXP_REGISTERED_NAME = '/
        (?(DEFINE)
            (?<unreserved>[a-z0-9_~\\-])   # . is missing as it is used to separate labels
            (?<sub_delims>[!$&\'()*+,;=])
            (?<encoded>%[A-F0-9]{2})
            (?<reg_name>(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*)
        )
            ^(?:(?&reg_name)\\.)*(?&reg_name)\\.?$
        /ix';
    /**
     * IDNA options.
     */
    public const IDNA_DEFAULT = 0;
    public const IDNA_ALLOW_UNASSIGNED = 1;
    public const IDNA_USE_STD3_RULES = 2;
    public const IDNA_CHECK_BIDI = 4;
    public const IDNA_CHECK_CONTEXTJ = 8;
    public const IDNA_NONTRANSITIONAL_TO_ASCII = 0x10;
    public const IDNA_NONTRANSITIONAL_TO_UNICODE = 0x20;
    public const IDNA_CHECK_CONTEXTO = 0x40;
    /**
     * IDNA errors.
     */
    public const ERROR_NONE = 0;
    public const ERROR_EMPTY_LABEL = 1;
    public const ERROR_LABEL_TOO_LONG = 2;
    public const ERROR_DOMAIN_NAME_TOO_LONG = 4;
    public const ERROR_LEADING_HYPHEN = 8;
    public const ERROR_TRAILING_HYPHEN = 0x10;
    public const ERROR_HYPHEN_3_4 = 0x20;
    public const ERROR_LEADING_COMBINING_MARK = 0x40;
    public const ERROR_DISALLOWED = 0x80;
    public const ERROR_PUNYCODE = 0x100;
    public const ERROR_LABEL_HAS_DOT = 0x200;
    public const ERROR_INVALID_ACE_LABEL = 0x400;
    public const ERROR_BIDI = 0x800;
    public const ERROR_CONTEXTJ = 0x1000;
    public const ERROR_CONTEXTO_PUNCTUATION = 0x2000;
    public const ERROR_CONTEXTO_DIGITS = 0x4000;
    /**
     * IDNA default options.
     */
    public const IDNA2008_ASCII = self::IDNA_NONTRANSITIONAL_TO_ASCII | self::IDNA_CHECK_BIDI | self::IDNA_USE_STD3_RULES | self::IDNA_CHECK_CONTEXTJ;
    public const IDNA2008_UNICODE = self::IDNA_NONTRANSITIONAL_TO_UNICODE | self::IDNA_CHECK_BIDI | self::IDNA_USE_STD3_RULES | self::IDNA_CHECK_CONTEXTJ;
    /**
     * @codeCoverageIgnore
     */
    private static function supportsIdna() : void
    {
        static $idnSupport;
        if (null === $idnSupport) {
            $idnSupport = function_exists('\\idn_to_ascii') && defined('\\INTL_IDNA_VARIANT_UTS46');
        }
        if (!$idnSupport) {
            throw new IdnSupportMissing('IDN host can not be processed. Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.');
        }
    }
    /**
     * Converts the input to its IDNA ASCII form.
     *
     * This method returns the string converted to IDN ASCII form
     *
     * @throws SyntaxError if the string can not be converted to ASCII using IDN UTS46 algorithm
     */
    public static function toAscii(string $domain, int $options) : IdnaInfo
    {
        $domain = rawurldecode($domain);
        if (1 === preg_match(self::REGEXP_IDNA_PATTERN, $domain)) {
            self::supportsIdna();
            /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */
            idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
            if ([] === $idnaInfo) {
                return IdnaInfo::fromIntl(['result' => strtolower($domain), 'isTransitionalDifferent' => false, 'errors' => self::validateDomainAndLabelLength($domain)]);
            }
            /* @var array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */
            return IdnaInfo::fromIntl($idnaInfo);
        }
        $error = self::ERROR_NONE;
        if (1 !== preg_match(self::REGEXP_REGISTERED_NAME, $domain)) {
            $error |= self::ERROR_DISALLOWED;
        }
        return IdnaInfo::fromIntl(['result' => strtolower($domain), 'isTransitionalDifferent' => false, 'errors' => self::validateDomainAndLabelLength($domain) | $error]);
    }
    /**
     * Converts the input to its IDNA UNICODE form.
     *
     * This method returns the string converted to IDN UNICODE form
     *
     * @throws SyntaxError if the string can not be converted to UNICODE using IDN UTS46 algorithm
     */
    public static function toUnicode(string $domain, int $options) : IdnaInfo
    {
        $domain = rawurldecode($domain);
        if (false === stripos($domain, 'xn--')) {
            return IdnaInfo::fromIntl(['result' => $domain, 'isTransitionalDifferent' => false, 'errors' => self::ERROR_NONE]);
        }
        self::supportsIdna();
        /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */
        idn_to_utf8($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
        if ([] === $idnaInfo) {
            throw IdnaConversionFailed::dueToInvalidHost($domain);
        }
        /* @var array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */
        return IdnaInfo::fromIntl($idnaInfo);
    }
    /**
     * Adapted from https://github.com/TRowbotham/idna.
     *
     * @see https://github.com/TRowbotham/idna/blob/master/src/Idna.php#L236
     */
    private static function validateDomainAndLabelLength(string $domain) : int
    {
        $error = self::ERROR_NONE;
        $labels = explode('.', $domain);
        $maxDomainSize = self::MAX_DOMAIN_LENGTH;
        $length = count($labels);
        // If the last label is empty and it is not the first label, then it is the root label.
        // Increase the max size by 1, making it 254, to account for the root label's "."
        // delimiter. This also means we don't need to check the last label's length for being too
        // long.
        if ($length > 1 && $labels[$length - 1] === '') {
            ++$maxDomainSize;
            array_pop($labels);
        }
        if (strlen($domain) > $maxDomainSize) {
            $error |= self::ERROR_DOMAIN_NAME_TOO_LONG;
        }
        foreach ($labels as $label) {
            if (strlen($label) > self::MAX_LABEL_LENGTH) {
                $error |= self::ERROR_LABEL_TOO_LONG;
                break;
            }
        }
        return $error;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Contracts\UriException;
class FileinfoSupportMissing extends \RuntimeException implements UriException
{
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Contracts\UriException;
class SyntaxError extends \InvalidArgumentException implements UriException
{
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Contracts\UriException;
class IdnSupportMissing extends \RuntimeException implements UriException
{
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Idna\IdnaInfo;
final class IdnaConversionFailed extends SyntaxError
{
    /** @var IdnaInfo|null  */
    private $idnaInfo;
    /**
     *
     */
    private function __construct(string $message, IdnaInfo $idnaInfo = null)
    {
        parent::__construct($message);
        $this->idnaInfo = $idnaInfo;
    }
    /**
     *
     */
    public static function dueToIDNAError(string $domain, IdnaInfo $idnaInfo) : self
    {
        return new self('The host `' . $domain . '` is invalid : ' . implode(', ', $idnaInfo->errorList()) . ' .', $idnaInfo);
    }
    /**
     *
     */
    public static function dueToInvalidHost(string $domain) : self
    {
        return new self('The host `' . $domain . '` is not a valid IDN host');
    }
    /**
     *
     */
    public function idnaInfo() : ?IdnaInfo
    {
        return $this->idnaInfo;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\SyntaxError;
/**
 * @extends \IteratorAggregate<string>
 */
interface DomainHostInterface extends \Countable, HostInterface, \IteratorAggregate
{
    /**
     * Returns the labels total number.
     */
    public function count() : int;
    /**
     * Iterate over the Domain labels.
     *
     * @return \Iterator<string>
     */
    public function getIterator() : \Iterator;
    /**
     * Retrieves a single host label.
     *
     * If the label offset has not been set, returns the null value.
     */
    public function get(int $offset) : ?string;
    /**
     * Returns the associated key for a specific label or all the keys.
     *
     * @param ?string $label
     *
     * @return int[]
     */
    public function keys(?string $label = null) : array;
    /**
     * Tells whether the domain is absolute.
     */
    public function isAbsolute() : bool;
    /**
     * Prepends a label to the host.
     */
    public function prepend(string $label) : self;
    /**
     * Appends a label to the host.
     */
    public function append(string $label) : self;
    /**
     * Returns an instance with its Root label.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    public function withRootLabel() : self;
    /**
     * Returns an instance without its Root label.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    public function withoutRootLabel() : self;
    /**
    * Returns an instance with the modified label.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the new label
    *
    * If $key is non-negative, the added label will be the label at $key position from the start.
    If $key is negative, the added label will be the label at $key position from the end.
    *
    * @throws SyntaxError If the key is invalid
    */
    public function withLabel(int $key, string $label) : self;
    /**
    * Returns an instance without the specified label.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified component
    *
    * If $key is non-negative, the removed label will be the label at $key position from the start.
    If $key is negative, the removed label will be the label at $key position from the end.
    *
    * @param int ...$keys
    *
    * @throws SyntaxError If the key is invalid
    */
    public function withoutLabel(int ...$keys) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface PortInterface extends UriComponentInterface
{
    /**
     * Returns the integer representation of the Port.
     */
    public function toInt() : ?int;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
interface UriInterface extends \JsonSerializable
{
    /**
     * Returns the string representation as a URI reference.
     *
     * @see http://tools.ietf.org/html/rfc3986#section-4.1
     */
    public function __toString() : string;
    /**
     * Returns the string representation as a URI reference.
     *
     * @see http://tools.ietf.org/html/rfc3986#section-4.1
     * @see ::__toString
     */
    public function jsonSerialize() : string;
    /**
    * Retrieve the scheme component of the URI.
    *
    * If no scheme is present, this method MUST return a null value.
    *
    * The value returned MUST be normalized to lowercase, per RFC 3986
    Section 3.1.
    *
    * The trailing ":" character is not part of the scheme and MUST NOT be
    added.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.1
    */
    public function getScheme() : ?string;
    /**
    * Retrieve the authority component of the URI.
    *
    * If no scheme is present, this method MUST return a null value.
    *
    * If the port component is not set or is the standard port for the current
    scheme, it SHOULD NOT be included.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.2
    */
    public function getAuthority() : ?string;
    /**
    * Retrieve the user information component of the URI.
    *
    * If no scheme is present, this method MUST return a null value.
    *
    * If a user is present in the URI, this will return that value;
    additionally, if the password is also present, it will be appended to the
    user value, with a colon (":") separating the values.
    *
    * The trailing "@" character is not part of the user information and MUST
    NOT be added.
    */
    public function getUserInfo() : ?string;
    /**
    * Retrieve the host component of the URI.
    *
    * If no host is present this method MUST return a null value.
    *
    * The value returned MUST be normalized to lowercase, per RFC 3986
    Section 3.2.2.
    *
    * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
    */
    public function getHost() : ?string;
    /**
    * Retrieve the port component of the URI.
    *
    * If a port is present, and it is non-standard for the current scheme,
    this method MUST return it as an integer. If the port is the standard port
    used with the current scheme, this method SHOULD return null.
    *
    * If no port is present, and no scheme is present, this method MUST return
    a null value.
    *
    * If no port is present, but a scheme is present, this method MAY return
    the standard port for that scheme, but SHOULD return null.
    */
    public function getPort() : ?int;
    /**
    * Retrieve the path component of the URI.
    *
    * The path can either be empty or absolute (starting with a slash) or
    rootless (not starting with a slash). Implementations MUST support all
    three syntaxes.
    *
    * Normally, the empty path "" and absolute path "/" are considered equal as
    defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
    do this normalization because in contexts with a trimmed base path, e.g.
    the front controller, this difference becomes significant. It's the task
    of the user to handle both "" and "/".
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.3.
    *
    * As an example, if the value should include a slash ("/") not intended as
    delimiter between path segments, that value MUST be passed in encoded
    form (e.g., "%2F") to the instance.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.3
    */
    public function getPath() : string;
    /**
    * Retrieve the query string of the URI.
    *
    * If no host is present this method MUST return a null value.
    *
    * The leading "?" character is not part of the query and MUST NOT be
    added.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.4.
    *
    * As an example, if a value in a key/value pair of the query string should
    include an ampersand ("&") not intended as a delimiter between values,
    that value MUST be passed in encoded form (e.g., "%26") to the instance.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.4
    */
    public function getQuery() : ?string;
    /**
    * Retrieve the fragment component of the URI.
    *
    * If no host is present this method MUST return a null value.
    *
    * The leading "#" character is not part of the fragment and MUST NOT be
    added.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.5.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.5
    */
    public function getFragment() : ?string;
    /**
    * Return an instance with the specified scheme.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified scheme.
    *
    * A null value provided for the scheme is equivalent to removing the scheme
    information.
    *
    * @param ?string $scheme
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withScheme(?string $scheme) : self;
    /**
    * Return an instance with the specified user information.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified user information.
    *
    * Password is optional, but the user information MUST include the
    user; a null value for the user is equivalent to removing user
    information.
    *
    * @param ?string $user
    * @param ?string $password
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withUserInfo(?string $user, ?string $password = null) : self;
    /**
    * Return an instance with the specified host.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified host.
    *
    * A null value provided for the host is equivalent to removing the host
    information.
    *
    * @param ?string $host
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    * @throws IdnSupportMissing for component or transformations
    requiring IDN support when IDN support is not present
    or misconfigured.
    */
    public function withHost(?string $host) : self;
    /**
    * Return an instance with the specified port.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified port.
    *
    * A null value provided for the port is equivalent to removing the port
    information.
    *
    * @param ?int $port
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withPort(?int $port) : self;
    /**
    * Return an instance with the specified path.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified path.
    *
    * The path can either be empty or absolute (starting with a slash) or
    rootless (not starting with a slash). Implementations MUST support all
    three syntaxes.
    *
    * Users can provide both encoded and decoded path characters.
    Implementations ensure the correct encoding as outlined in getPath().
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withPath(string $path) : self;
    /**
    * Return an instance with the specified query string.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified query string.
    *
    * Users can provide both encoded and decoded query characters.
    Implementations ensure the correct encoding as outlined in getQuery().
    *
    * A null value provided for the query is equivalent to removing the query
    information.
    *
    * @param ?string $query
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withQuery(?string $query) : self;
    /**
    * Return an instance with the specified URI fragment.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified URI fragment.
    *
    * Users can provide both encoded and decoded fragment characters.
    Implementations ensure the correct encoding as outlined in getFragment().
    *
    * A null value provided for the fragment is equivalent to removing the fragment
    information.
    *
    * @param ?string $fragment
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withFragment(?string $fragment) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface UserInfoInterface extends UriComponentInterface
{
    /**
     * Returns the user component part.
     */
    public function getUser() : ?string;
    /**
     * Returns the pass component part.
     */
    public function getPass() : ?string;
    /**
    * Returns an instance with the specified user and/or pass.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified user.
    *
    * An empty user is equivalent to removing the user information.
    *
    * @param ?string $user
    * @param ?string $pass
    */
    public function withUserInfo(?string $user, ?string $pass = null) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use Throwable;
interface UriException extends Throwable
{
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
interface UriComponentInterface extends \JsonSerializable
{
    /**
    * Returns the instance content.
    *
    * If the instance is defined, the value returned MUST be encoded according to the
    selected encoding algorithm. In any case, the value MUST NOT double-encode any character
    depending on the selected encoding algorithm.
    *
    * To determine what characters to encode, please refer to RFC 3986, Sections 2 and 3.
    or RFC 3987 Section 3. By default the content is encoded according to RFC3986
    *
    * If the instance is not defined null is returned
    */
    public function getContent() : ?string;
    /**
    * Returns the instance string representation.
    *
    * If the instance is defined, the value returned MUST be percent-encoded,
    but MUST NOT double-encode any characters. To determine what characters
    to encode, please refer to RFC 3986, Sections 2 and 3.
    *
    * If the instance is not defined an empty string is returned
    */
    public function __toString() : string;
    /**
    * Returns the instance json representation.
    *
    * If the instance is defined, the value returned MUST be percent-encoded,
    but MUST NOT double-encode any characters. To determine what characters
    to encode, please refer to RFC 3986 or RFC 1738.
    *
    * If the instance is not defined null is returned
    */
    public function jsonSerialize() : ?string;
    /**
    * Returns the instance string representation with its optional URI delimiters.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode any
    characters. To determine what characters to encode, please refer to RFC 3986,
    Sections 2 and 3.
    *
    * If the instance is not defined an empty string is returned
    */
    public function getUriComponent() : string;
    /**
    * Returns an instance with the specified content.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified content.
    *
    * Users can provide both encoded and decoded content characters.
    *
    * A null value is equivalent to removing the component content.
    *
    *
    * @param ?string $content
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    * @throws IdnSupportMissing for component or transformations
    requiring IDN support when IDN support is not present
    or misconfigured.
    */
    public function withContent(?string $content) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface DataPathInterface extends PathInterface
{
    /**
     * Retrieve the data mime type associated to the URI.
     *
     * If no mimetype is present, this method MUST return the default mimetype 'text/plain'.
     *
     * @see http://tools.ietf.org/html/rfc2397#section-2
     */
    public function getMimeType() : string;
    /**
     * Retrieve the parameters associated with the Mime Type of the URI.
     *
     * If no parameters is present, this method MUST return the default parameter 'charset=US-ASCII'.
     *
     * @see http://tools.ietf.org/html/rfc2397#section-2
     */
    public function getParameters() : string;
    /**
     * Retrieve the mediatype associated with the URI.
     *
     * If no mediatype is present, this method MUST return the default parameter 'text/plain;charset=US-ASCII'.
     *
     * @see http://tools.ietf.org/html/rfc2397#section-3
     *
     * @return string The URI scheme.
     */
    public function getMediaType() : string;
    /**
    * Retrieves the data string.
    *
    * Retrieves the data part of the path. If no data part is provided return
    a empty string
    */
    public function getData() : string;
    /**
     * Tells whether the data is binary safe encoded.
     */
    public function isBinaryData() : bool;
    /**
     * Save the data to a specific file.
     */
    public function save(string $path, string $mode = 'w') : \SplFileObject;
    /**
    * Returns an instance where the data part is base64 encoded.
    *
    * This method MUST retain the state of the current instance, and return
    an instance where the data part is base64 encoded
    */
    public function toBinary() : self;
    /**
    * Returns an instance where the data part is url encoded following RFC3986 rules.
    *
    * This method MUST retain the state of the current instance, and return
    an instance where the data part is url encoded
    */
    public function toAscii() : self;
    /**
    * Return an instance with the specified mediatype parameters.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified mediatype parameters.
    *
    * Users must provide encoded characters.
    *
    * An empty parameters value is equivalent to removing the parameter.
    */
    public function withParameters(string $parameters) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
interface AuthorityInterface extends UriComponentInterface
{
    /**
     * Returns the host component of the authority.
     */
    public function getHost() : ?string;
    /**
     * Returns the port component of the authority.
     */
    public function getPort() : ?int;
    /**
     * Returns the user information component of the authority.
     */
    public function getUserInfo() : ?string;
    /**
    * Return an instance with the specified host.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified host.
    *
    * A null value provided for the host is equivalent to removing the host
    information.
    *
    * @param ?string $host
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    * @throws IdnSupportMissing for component or transformations
    requiring IDN support when IDN support is not present
    or misconfigured.
    */
    public function withHost(?string $host) : self;
    /**
    * Return an instance with the specified port.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified port.
    *
    * A null value provided for the port is equivalent to removing the port
    information.
    *
    * @param ?int $port
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withPort(?int $port) : self;
    /**
    * Return an instance with the specified user information.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified user information.
    *
    * Password is optional, but the user information MUST include the
    user; a null value for the user is equivalent to removing user
    information.
    *
    * @param ?string $user
    * @param ?string $password
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withUserInfo(?string $user, ?string $password = null) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface IpHostInterface extends HostInterface
{
    /**
     * Returns whether or not the host is an IPv4 address.
     */
    public function isIpv4() : bool;
    /**
     * Returns whether or not the host is an IPv6 address.
     */
    public function isIpv6() : bool;
    /**
     * Returns whether or not the host is an IPv6 address.
     */
    public function isIpFuture() : bool;
    /**
     * Returns whether or not the host has a ZoneIdentifier.
     *
     * @see http://tools.ietf.org/html/rfc6874#section-4
     */
    public function hasZoneIdentifier() : bool;
    /**
    * Returns an host without its zone identifier according to RFC6874.
    *
    * This method MUST retain the state of the current instance, and return
    an instance without the host zone identifier according to RFC6874
    *
    * @see http://tools.ietf.org/html/rfc6874#section-4
    */
    public function withoutZoneIdentifier() : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface HostInterface extends UriComponentInterface
{
    /**
     * Returns the ascii representation.
     */
    public function toAscii() : ?string;
    /**
     * Returns the unicode representation.
     */
    public function toUnicode() : ?string;
    /**
     * Returns the IP version.
     *
     * If the host is a not an IP this method will return null
     */
    public function getIpVersion() : ?string;
    /**
     * Returns the IP component If the Host is an IP address.
     *
     * If the host is a not an IP this method will return null
     */
    public function getIp() : ?string;
    /**
     * Tells whether the host is a domain name.
     */
    public function isDomain() : bool;
    /**
     * Tells whether the host is an IP Address.
     */
    public function isIp() : bool;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\SyntaxError;
/**
 * @extends \IteratorAggregate<string>
 */
interface SegmentedPathInterface extends \Countable, \IteratorAggregate, PathInterface
{
    /**
     * Returns the total number of segments in the path.
     */
    public function count() : int;
    /**
     * Iterate over the path segment.
     *
     * @return \Iterator<string>
     */
    public function getIterator() : \Iterator;
    /**
     * Returns parent directory's path.
     */
    public function getDirname() : string;
    /**
     * Returns the path basename.
     */
    public function getBasename() : string;
    /**
     * Returns the basename extension.
     */
    public function getExtension() : string;
    /**
     * Retrieves a single path segment.
     *
     * If the segment offset has not been set, returns null.
     */
    public function get(int $offset) : ?string;
    /**
    * Returns the associated key for a specific segment.
    *
    * If a value is specified only the keys associated with
    the given value will be returned
    *
    * @param ?string $segment
    *
    * @return int[]
    */
    public function keys(?string $segment = null) : array;
    /**
     * Appends a segment to the path.
     */
    public function append(string $segment) : self;
    /**
     * Prepends a segment to the path.
     */
    public function prepend(string $segment) : self;
    /**
    * Returns an instance with the modified segment.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the new segment
    *
    * If $key is non-negative, the added segment will be the segment at $key position from the start.
    If $key is negative, the added segment will be the segment at $key position from the end.
    *
    * @param ?string $segment
    *
    * @throws SyntaxError If the key is invalid
    */
    public function withSegment(int $key, ?string $segment) : self;
    /**
    * Returns an instance without the specified segment.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified component
    *
    * If $key is non-negative, the removed segment will be the segment at $key position from the start.
    If $key is negative, the removed segment will be the segment at $key position from the end.
    *
    * @param int ...$keys remaining keys to remove
    *
    * @throws SyntaxError If the key is invalid
    */
    public function withoutSegment(int ...$keys) : self;
    /**
    * Returns an instance without duplicate delimiters.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component normalized by removing
    multiple consecutive empty segment
    */
    public function withoutEmptySegments() : self;
    /**
    * Returns an instance with the specified parent directory's path.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the extension basename modified.
    *
    * @param ?string $path
    */
    public function withDirname(?string $path) : self;
    /**
    * Returns an instance with the specified basename.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the extension basename modified.
    *
    * @param ?string $basename
    */
    public function withBasename(?string $basename) : self;
    /**
    * Returns an instance with the specified basename extension.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the extension basename modified.
    *
    * @param ?string $extension
    */
    public function withExtension(?string $extension) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

/**
 * @extends \IteratorAggregate<array{0:string, 1:string|null}>
 */
interface QueryInterface extends \Countable, \IteratorAggregate, UriComponentInterface
{
    /**
     * Returns the query separator.
     */
    public function getSeparator() : string;
    /**
     * Returns the number of key/value pairs present in the object.
     */
    public function count() : int;
    /**
    * Returns an iterator allowing to go through all key/value pairs contained in this object.
    *
    * The pair is represented as an array where the first value is the pair key
    and the second value the pair value.
    *
    * The key of each pair is a string
    The value of each pair is a scalar or the null value
    *
    * @return \Iterator<int, array{0: string, 1: (string | null)}>
    */
    public function getIterator() : \Iterator;
    /**
    * Returns an iterator allowing to go through all key/value pairs contained in this object.
    *
    * The return type is as a Iterator where its offset is the pair key and its value the pair value.
    *
    * The key of each pair is a string
    The value of each pair is a scalar or the null value
    *
    * @return iterable<string, (string | null)>
    */
    public function pairs() : iterable;
    /**
     * Tells whether a pair with a specific name exists.
     *
     * @see https://url.spec.whatwg.org/#dom-urlsearchparams-has
     */
    public function has(string $key) : bool;
    /**
     * Returns the first value associated to the given pair name.
     *
     * If no value is found null is returned
     *
     * @see https://url.spec.whatwg.org/#dom-urlsearchparams-get
     */
    public function get(string $key) : ?string;
    /**
    * Returns all the values associated to the given pair name as an array or all
    the instance pairs.
    *
    * If no value is found an empty array is returned
    *
    * @see https://url.spec.whatwg.org/#dom-urlsearchparams-getall
    *
    * @return array<int, (string | null)>
    */
    public function getAll(string $key) : array;
    /**
    * Returns the store PHP variables as elements of an array.
    *
    * The result is similar as PHP parse_str when used with its
    second argument with the difference that variable names are
    not mangled.
    *
    * If a key is submitted it will returns the value attached to it or null
    *
    * @see http://php.net/parse_str
    * @see https://wiki.php.net/rfc/on_demand_name_mangling
    *
    * @param ?string $key
    * @return mixed the collection of stored PHP variables or the empty array if no input is given,
    the single value of a stored PHP variable or null if the variable is not present in the collection
    */
    public function params(?string $key = null);
    /**
     * Returns the RFC1738 encoded query.
     */
    public function toRFC1738() : ?string;
    /**
     * Returns the RFC3986 encoded query.
     *
     * @see ::getContent
     */
    public function toRFC3986() : ?string;
    /**
    * Returns an instance with a different separator.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the query component with a different separator
    */
    public function withSeparator(string $separator) : self;
    /**
    * Sorts the query string by offset, maintaining offset to data correlations.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * @see https://url.spec.whatwg.org/#dom-urlsearchparams-sort
    */
    public function sort() : self;
    /**
    * Returns an instance without duplicate key/value pair.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the query component normalized by removing
    duplicate pairs whose key/value are the same.
    */
    public function withoutDuplicates() : self;
    /**
    * Returns an instance without empty key/value where the value is the null value.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the query component normalized by removing
    empty pairs.
    *
    * A pair is considered empty if its value is equal to the null value
    */
    public function withoutEmptyPairs() : self;
    /**
    * Returns an instance where numeric indices associated to PHP's array like key are removed.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the query component normalized so that numeric indexes
    are removed from the pair key value.
    *
    * ie.: toto[3]=bar[3]&foo=bar becomes toto[]=bar[3]&foo=bar
    */
    public function withoutNumericIndices() : self;
    /**
    * Returns an instance with the a new key/value pair added to it.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * If the pair already exists the value will replace the existing value.
    *
    * @see https://url.spec.whatwg.org/#dom-urlsearchparams-set
    *
    * @param ?string $value
    */
    public function withPair(string $key, ?string $value) : self;
    /**
    * Returns an instance with the new pairs set to it.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * @see ::withPair
    */
    public function merge(string $query) : self;
    /**
    * Returns an instance without the specified keys.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified component
    *
    * @param string ...$keys
    */
    public function withoutPair(string ...$keys) : self;
    /**
    * Returns a new instance with a specified key/value pair appended as a new pair.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * @param ?string $value
    */
    public function appendTo(string $key, ?string $value) : self;
    /**
    * Returns an instance with the new pairs appended to it.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * If the pair already exists the value will be added to it.
    */
    public function append(string $query) : self;
    /**
    * Returns an instance without the specified params.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified component without PHP's value.
    PHP's mangled is not taken into account.
    *
    * @param string ...$keys
    */
    public function withoutParam(string ...$keys) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface FragmentInterface extends UriComponentInterface
{
    /**
     * Returns the decoded fragment.
     */
    public function decoded() : ?string;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\SyntaxError;
interface PathInterface extends UriComponentInterface
{
    /**
     * Returns the decoded path.
     */
    public function decoded() : string;
    /**
     * Returns whether or not the path is absolute or relative.
     */
    public function isAbsolute() : bool;
    /**
     * Returns whether or not the path has a trailing delimiter.
     */
    public function hasTrailingSlash() : bool;
    /**
    * Returns an instance without dot segments.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component normalized by removing
    the dot segment.
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withoutDotSegments() : self;
    /**
    * Returns an instance with a leading slash.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component with a leading slash
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withLeadingSlash() : self;
    /**
    * Returns an instance without a leading slash.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component without a leading slash
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withoutLeadingSlash() : self;
    /**
    * Returns an instance with a trailing slash.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component with a trailing slash
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withTrailingSlash() : self;
    /**
    * Returns an instance without a trailing slash.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component without a trailing slash
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withoutTrailingSlash() : self;
}{
    "name": "league/uri-interfaces",
    "description" : "Common interface for URI representation",
    "keywords": [
        "url",
        "uri",
        "rfc3986",
        "rfc3987"
    ],
    "license": "MIT",
    "homepage": "http://github.com/thephpleague/uri-interfaces",
    "authors": [
        {
            "name" : "Ignace Nyamagana Butera",
            "email" : "nyamsprod@gmail.com",
            "homepage" : "https://nyamsprod.com"
        }
    ],
    "funding": [
        {
            "type": "github",
            "url": "https://github.com/sponsors/nyamsprod"
        }
    ],
    "require": {
        "php" : "^7.2 || ^8.0",
        "ext-json": "*"
    },
    "require-dev": {
        "friendsofphp/php-cs-fixer": "^2.19",
        "phpstan/phpstan": "^0.12.90",
        "phpstan/phpstan-strict-rules": "^0.12.9",
        "phpstan/phpstan-phpunit": "^0.12.19",
        "phpunit/phpunit": "^8.5.15 || ^9.5"
    },
    "autoload": {
        "psr-4": {
            "League\\Uri\\": "src/"
        }
    },
    "scripts": {
        "phpunit": "phpunit --coverage-text",
        "phpcs": "php-cs-fixer fix --dry-run --diff -vvv --allow-risky=yes --ansi",
        "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi",
        "phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi --memory-limit 192M",
        "test": [
            "@phpunit",
            "@phpstan",
            "@phpcs:fix"
        ]
    },
    "scripts-descriptions": {
        "phpunit": "Runs package test suite",
        "phpstan": "Runs complete codebase static analysis",
        "phpcs": "Runs coding style testing",
        "phpcs:fix": "Fix coding style issues",
        "test": "Runs all tests"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.x-dev"
        }
    },
    "suggest": {
        "ext-intl": "to use the IDNA feature",
        "symfony/intl": "to use the IDNA feature via Symfony Polyfill"
    }
}
<?php

// autoload_real.php @generated by Composer

class ComposerAutoloaderInita56f38b10c587f7d23477ad1951b93ea
{
    private static $loader;

    public static function loadClassLoader($class)
    {
        if ('Composer\Autoload\ClassLoader' === $class) {
            require __DIR__ . '/ClassLoader.php';
        }
    }

    /**
     * @return \Composer\Autoload\ClassLoader
     */
    public static function getLoader()
    {
        if (null !== self::$loader) {
            return self::$loader;
        }

        require __DIR__ . '/platform_check.php';

        spl_autoload_register(array('ComposerAutoloaderInita56f38b10c587f7d23477ad1951b93ea', 'loadClassLoader'), true, true);
        self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
        spl_autoload_unregister(array('ComposerAutoloaderInita56f38b10c587f7d23477ad1951b93ea', 'loadClassLoader'));

        $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
        if ($useStaticLoader) {
            require __DIR__ . '/autoload_static.php';

            call_user_func(\Composer\Autoload\ComposerStaticInita56f38b10c587f7d23477ad1951b93ea::getInitializer($loader));
        } else {
            $map = require __DIR__ . '/autoload_namespaces.php';
            foreach ($map as $namespace => $path) {
                $loader->set($namespace, $path);
            }

            $map = require __DIR__ . '/autoload_psr4.php';
            foreach ($map as $namespace => $path) {
                $loader->setPsr4($namespace, $path);
            }

            $classMap = require __DIR__ . '/autoload_classmap.php';
            if ($classMap) {
                $loader->addClassMap($classMap);
            }
        }

        $loader->register(true);

        if ($useStaticLoader) {
            $includeFiles = Composer\Autoload\ComposerStaticInita56f38b10c587f7d23477ad1951b93ea::$files;
        } else {
            $includeFiles = require __DIR__ . '/autoload_files.php';
        }
        foreach ($includeFiles as $fileIdentifier => $file) {
            composerRequirea56f38b10c587f7d23477ad1951b93ea($fileIdentifier, $file);
        }

        return $loader;
    }
}

function composerRequirea56f38b10c587f7d23477ad1951b93ea($fileIdentifier, $file)
{
    if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
        require $file;

        $GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
    }
}
<?php

// platform_check.php @generated by Composer

$issues = array();

if (!(PHP_VERSION_ID >= 70400)) {
    $issues[] = 'Your Composer dependencies require a PHP version ">= 7.4.0". You are running ' . PHP_VERSION . '.';
}

if ($issues) {
    if (!headers_sent()) {
        header('HTTP/1.1 500 Internal Server Error');
    }
    if (!ini_get('display_errors')) {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            fwrite(STDERR, 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . implode(PHP_EOL, $issues) . PHP_EOL.PHP_EOL);
        } elseif (!headers_sent()) {
            echo 'Composer detected issues in your platform:' . PHP_EOL.PHP_EOL . str_replace('You are running '.PHP_VERSION.'.', '', implode(PHP_EOL, $issues)) . PHP_EOL.PHP_EOL;
        }
    }
    trigger_error(
        'Composer detected issues in your platform: ' . implode(' ', $issues),
        E_USER_ERROR
    );
}
<?php

// autoload_psr4.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'phpseclib3\\' => array($vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib'),
    'danog\\MadelineProto\\' => array($vendorDir . '/danog/madelineproto/src/danog/MadelineProto'),
    'danog\\Loop\\' => array($vendorDir . '/phabel-transpiler74.danog/loop/lib'),
    'danog\\LibDNSJson\\' => array($vendorDir . '/phabel-transpiler74.danog/libdns-json/lib'),
    'danog\\Decoder\\' => array($vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src'),
    'Symfony\\Polyfill\\Php80\\' => array($vendorDir . '/phabel-transpiler74.symfony/polyfill-php80', $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-php80'),
    'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-php73'),
    'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/phabel-transpiler74.symfony/polyfill-mbstring', $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring'),
    'Symfony\\Polyfill\\Intl\\Normalizer\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer'),
    'Symfony\\Polyfill\\Intl\\Grapheme\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme'),
    'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-ctype'),
    'Psr\\Log\\' => array($vendorDir . '/phabel-transpiler74.psr/log/Psr/Log'),
    'Psr\\Http\\Message\\' => array($vendorDir . '/phabel-transpiler74.psr/http-factory/src', $vendorDir . '/phabel-transpiler74.psr/http-message/src'),
    'Phabel\\' => array($vendorDir . '/phabel/phabel/src'),
    'PhabelVendor\\Symfony\\Contracts\\Service\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts'),
    'PhabelVendor\\Symfony\\Component\\String\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/symfony/string'),
    'PhabelVendor\\Symfony\\Component\\Process\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/symfony/process'),
    'PhabelVendor\\Symfony\\Component\\Console\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/symfony/console'),
    'PhabelVendor\\Psr\\Log\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log'),
    'PhabelVendor\\Psr\\Container\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/psr/container/src'),
    'PhabelVendor\\PhpParser\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser'),
    'PhabelVendor\\PHPStan\\PhpDocParser\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src'),
    'PhabelVendor\\Amp\\Sync\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src'),
    'PhabelVendor\\Amp\\Serialization\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/amphp/serialization/src'),
    'PhabelVendor\\Amp\\Process\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib'),
    'PhabelVendor\\Amp\\Parser\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/amphp/parser/lib'),
    'PhabelVendor\\Amp\\Parallel\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib'),
    'PhabelVendor\\Amp\\ByteStream\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib'),
    'PhabelVendor\\Amp\\' => array($vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib'),
    'ParagonIE\\ConstantTime\\' => array($vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src'),
    'Monolog\\' => array($vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog'),
    'LibDNS\\' => array($vendorDir . '/phabel-transpiler74.daverandom/libdns/src'),
    'League\\Uri\\' => array($vendorDir . '/phabel-transpiler74.league/uri/src', $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src', $vendorDir . '/phabel-transpiler74.league/uri-parser/src'),
    'Kelunik\\Certificate\\' => array($vendorDir . '/phabel-transpiler74.kelunik/certificate/lib'),
    'Amp\\WindowsRegistry\\' => array($vendorDir . '/phabel-transpiler74.amphp/windows-registry/lib'),
    'Amp\\Websocket\\Client\\' => array($vendorDir . '/phabel-transpiler74.amphp/websocket-client/src'),
    'Amp\\Websocket\\' => array($vendorDir . '/phabel-transpiler74.amphp/websocket/src'),
    'Amp\\Sync\\' => array($vendorDir . '/phabel-transpiler74.amphp/sync/src'),
    'Amp\\Sql\\Common\\' => array($vendorDir . '/phabel-transpiler74.amphp/sql-common/src'),
    'Amp\\Sql\\' => array($vendorDir . '/phabel-transpiler74.amphp/sql/src'),
    'Amp\\Socket\\' => array($vendorDir . '/phabel-transpiler74.amphp/socket/src'),
    'Amp\\Serialization\\' => array($vendorDir . '/phabel-transpiler74.amphp/serialization/src'),
    'Amp\\Redis\\' => array($vendorDir . '/phabel-transpiler74.amphp/redis/src'),
    'Amp\\Process\\' => array($vendorDir . '/phabel-transpiler74.amphp/process/lib'),
    'Amp\\Postgres\\' => array($vendorDir . '/phabel-transpiler74.amphp/postgres/src'),
    'Amp\\Parser\\' => array($vendorDir . '/phabel-transpiler74.amphp/parser/lib'),
    'Amp\\Parallel\\' => array($vendorDir . '/phabel-transpiler74.amphp/parallel/lib'),
    'Amp\\Mysql\\' => array($vendorDir . '/phabel-transpiler74.amphp/mysql/src'),
    'Amp\\Log\\' => array($vendorDir . '/phabel-transpiler74.amphp/log/src'),
    'Amp\\Ipc\\' => array($vendorDir . '/phabel-transpiler74.danog/ipc/lib'),
    'Amp\\Http\\Client\\Cookie\\' => array($vendorDir . '/phabel-transpiler74.amphp/http-client-cookies/src'),
    'Amp\\Http\\Client\\' => array($vendorDir . '/phabel-transpiler74.amphp/http-client/src'),
    'Amp\\Http\\' => array($vendorDir . '/phabel-transpiler74.amphp/hpack/src', $vendorDir . '/phabel-transpiler74.amphp/http/src'),
    'Amp\\File\\' => array($vendorDir . '/phabel-transpiler74.amphp/file/src'),
    'Amp\\DoH\\' => array($vendorDir . '/phabel-transpiler74.danog/dns-over-https/lib'),
    'Amp\\Dns\\' => array($vendorDir . '/phabel-transpiler74.amphp/dns/lib'),
    'Amp\\Cache\\' => array($vendorDir . '/phabel-transpiler74.amphp/cache/lib'),
    'Amp\\ByteStream\\' => array($vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib'),
    'Amp\\' => array($vendorDir . '/phabel-transpiler74.amphp/amp/lib'),
);
<?php

// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Amp\\ByteStream\\Base64\\Base64DecodingInputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64DecodingInputStream.php',
    'Amp\\ByteStream\\Base64\\Base64DecodingOutputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php',
    'Amp\\ByteStream\\Base64\\Base64EncodingInputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php',
    'Amp\\ByteStream\\Base64\\Base64EncodingOutputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.php',
    'Amp\\ByteStream\\ClosedException' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/ClosedException.php',
    'Amp\\ByteStream\\InMemoryStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/InMemoryStream.php',
    'Amp\\ByteStream\\InputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/InputStream.php',
    'Amp\\ByteStream\\InputStreamChain' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/InputStreamChain.php',
    'Amp\\ByteStream\\IteratorStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/IteratorStream.php',
    'Amp\\ByteStream\\LineReader' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/LineReader.php',
    'Amp\\ByteStream\\Message' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/Message.php',
    'Amp\\ByteStream\\OutputBuffer' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/OutputBuffer.php',
    'Amp\\ByteStream\\OutputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/OutputStream.php',
    'Amp\\ByteStream\\Payload' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/Payload.php',
    'Amp\\ByteStream\\PendingReadError' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/PendingReadError.php',
    'Amp\\ByteStream\\ResourceInputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/ResourceInputStream.php',
    'Amp\\ByteStream\\ResourceOutputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/ResourceOutputStream.php',
    'Amp\\ByteStream\\StreamException' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/StreamException.php',
    'Amp\\ByteStream\\ZlibInputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/ZlibInputStream.php',
    'Amp\\ByteStream\\ZlibOutputStream' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/ZlibOutputStream.php',
    'Amp\\Cache\\ArrayCache' => $vendorDir . '/phabel-transpiler74.amphp/cache/lib/ArrayCache.php',
    'Amp\\Cache\\AtomicCache' => $vendorDir . '/phabel-transpiler74.amphp/cache/lib/AtomicCache.php',
    'Amp\\Cache\\Cache' => $vendorDir . '/phabel-transpiler74.amphp/cache/lib/Cache.php',
    'Amp\\Cache\\CacheException' => $vendorDir . '/phabel-transpiler74.amphp/cache/lib/CacheException.php',
    'Amp\\Cache\\FileCache' => $vendorDir . '/phabel-transpiler74.amphp/cache/lib/FileCache.php',
    'Amp\\Cache\\NullCache' => $vendorDir . '/phabel-transpiler74.amphp/cache/lib/NullCache.php',
    'Amp\\Cache\\PrefixCache' => $vendorDir . '/phabel-transpiler74.amphp/cache/lib/PrefixCache.php',
    'Amp\\Cache\\SerializedCache' => $vendorDir . '/phabel-transpiler74.amphp/cache/lib/SerializedCache.php',
    'Amp\\CallableMaker' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/CallableMaker.php',
    'Amp\\CancellationToken' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/CancellationToken.php',
    'Amp\\CancellationTokenSource' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/CancellationTokenSource.php',
    'Amp\\CancelledException' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/CancelledException.php',
    'Amp\\CombinedCancellationToken' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/CombinedCancellationToken.php',
    'Amp\\Coroutine' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Coroutine.php',
    'Amp\\Deferred' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Deferred.php',
    'Amp\\Delayed' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Delayed.php',
    'Amp\\Dns\\BlockingFallbackResolver' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/BlockingFallbackResolver.php',
    'Amp\\Dns\\Config' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/Config.php',
    'Amp\\Dns\\ConfigException' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/ConfigException.php',
    'Amp\\Dns\\ConfigLoader' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/ConfigLoader.php',
    'Amp\\Dns\\DnsException' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/DnsException.php',
    'Amp\\Dns\\HostLoader' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/HostLoader.php',
    'Amp\\Dns\\Internal\\Socket' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/Internal/Socket.php',
    'Amp\\Dns\\Internal\\TcpSocket' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/Internal/TcpSocket.php',
    'Amp\\Dns\\Internal\\UdpSocket' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/Internal/UdpSocket.php',
    'Amp\\Dns\\InvalidNameException' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/InvalidNameException.php',
    'Amp\\Dns\\NoRecordException' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/NoRecordException.php',
    'Amp\\Dns\\Record' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/Record.php',
    'Amp\\Dns\\Resolver' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/Resolver.php',
    'Amp\\Dns\\Rfc1035StubResolver' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/Rfc1035StubResolver.php',
    'Amp\\Dns\\TimeoutException' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/TimeoutException.php',
    'Amp\\Dns\\UnixConfigLoader' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/UnixConfigLoader.php',
    'Amp\\Dns\\WindowsConfigLoader' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/WindowsConfigLoader.php',
    'Amp\\DoH\\DoHConfig' => $vendorDir . '/phabel-transpiler74.danog/dns-over-https/lib/DoHConfig.php',
    'Amp\\DoH\\DoHException' => $vendorDir . '/phabel-transpiler74.danog/dns-over-https/lib/DoHException.php',
    'Amp\\DoH\\Internal\\HttpsSocket' => $vendorDir . '/phabel-transpiler74.danog/dns-over-https/lib/Internal/HttpsSocket.php',
    'Amp\\DoH\\Internal\\Socket' => $vendorDir . '/phabel-transpiler74.danog/dns-over-https/lib/Internal/Socket.php',
    'Amp\\DoH\\Nameserver' => $vendorDir . '/phabel-transpiler74.danog/dns-over-https/lib/Nameserver.php',
    'Amp\\DoH\\Rfc8484StubResolver' => $vendorDir . '/phabel-transpiler74.danog/dns-over-https/lib/Rfc8484StubResolver.php',
    'Amp\\Emitter' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Emitter.php',
    'Amp\\Failure' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Failure.php',
    'Amp\\File\\Driver' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver.php',
    'Amp\\File\\Driver\\BlockingDriver' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/BlockingDriver.php',
    'Amp\\File\\Driver\\BlockingFile' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/BlockingFile.php',
    'Amp\\File\\Driver\\EioDriver' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/EioDriver.php',
    'Amp\\File\\Driver\\EioFile' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/EioFile.php',
    'Amp\\File\\Driver\\ParallelDriver' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/ParallelDriver.php',
    'Amp\\File\\Driver\\ParallelFile' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/ParallelFile.php',
    'Amp\\File\\Driver\\StatusCachingDriver' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/StatusCachingDriver.php',
    'Amp\\File\\Driver\\StatusCachingFile' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/StatusCachingFile.php',
    'Amp\\File\\Driver\\UvDriver' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/UvDriver.php',
    'Amp\\File\\Driver\\UvFile' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Driver/UvFile.php',
    'Amp\\File\\File' => $vendorDir . '/phabel-transpiler74.amphp/file/src/File.php',
    'Amp\\File\\Filesystem' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Filesystem.php',
    'Amp\\File\\FilesystemException' => $vendorDir . '/phabel-transpiler74.amphp/file/src/FilesystemException.php',
    'Amp\\File\\Internal\\Cache' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Internal/Cache.php',
    'Amp\\File\\Internal\\EioPoll' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Internal/EioPoll.php',
    'Amp\\File\\Internal\\FileTask' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Internal/FileTask.php',
    'Amp\\File\\Internal\\UvPoll' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Internal/UvPoll.php',
    'Amp\\File\\PendingOperationError' => $vendorDir . '/phabel-transpiler74.amphp/file/src/PendingOperationError.php',
    'Amp\\File\\Sync\\AsyncFileMutex' => $vendorDir . '/phabel-transpiler74.amphp/file/src/Sync/AsyncFileMutex.php',
    'Amp\\Http\\Client\\ApplicationInterceptor' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/ApplicationInterceptor.php',
    'Amp\\Http\\Client\\Body\\FileBody' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Body/FileBody.php',
    'Amp\\Http\\Client\\Body\\FormBody' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Body/FormBody.php',
    'Amp\\Http\\Client\\Body\\JsonBody' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Body/JsonBody.php',
    'Amp\\Http\\Client\\Body\\StringBody' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Body/StringBody.php',
    'Amp\\Http\\Client\\Connection\\Connection' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Connection.php',
    'Amp\\Http\\Client\\Connection\\ConnectionFactory' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionFactory.php',
    'Amp\\Http\\Client\\Connection\\ConnectionLimitingPool' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionLimitingPool.php',
    'Amp\\Http\\Client\\Connection\\ConnectionPool' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionPool.php',
    'Amp\\Http\\Client\\Connection\\DefaultConnectionFactory' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/DefaultConnectionFactory.php',
    'Amp\\Http\\Client\\Connection\\Http1Connection' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Http1Connection.php',
    'Amp\\Http\\Client\\Connection\\Http2Connection' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Http2Connection.php',
    'Amp\\Http\\Client\\Connection\\Http2ConnectionException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Http2ConnectionException.php',
    'Amp\\Http\\Client\\Connection\\Http2StreamException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Http2StreamException.php',
    'Amp\\Http\\Client\\Connection\\HttpStream' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/HttpStream.php',
    'Amp\\Http\\Client\\Connection\\InterceptedStream' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/InterceptedStream.php',
    'Amp\\Http\\Client\\Connection\\Internal\\Http1Parser' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http1Parser.php',
    'Amp\\Http\\Client\\Connection\\Internal\\Http2ConnectionProcessor' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http2ConnectionProcessor.php',
    'Amp\\Http\\Client\\Connection\\Internal\\Http2Stream' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http2Stream.php',
    'Amp\\Http\\Client\\Connection\\Internal\\RequestNormalizer' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Internal/RequestNormalizer.php',
    'Amp\\Http\\Client\\Connection\\Stream' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/Stream.php',
    'Amp\\Http\\Client\\Connection\\StreamLimitingPool' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/StreamLimitingPool.php',
    'Amp\\Http\\Client\\Connection\\UnlimitedConnectionPool' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/UnlimitedConnectionPool.php',
    'Amp\\Http\\Client\\Connection\\UnprocessedRequestException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/UnprocessedRequestException.php',
    'Amp\\Http\\Client\\Connection\\UpgradedSocket' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Connection/UpgradedSocket.php',
    'Amp\\Http\\Client\\Cookie\\CookieInterceptor' => $vendorDir . '/phabel-transpiler74.amphp/http-client-cookies/src/CookieInterceptor.php',
    'Amp\\Http\\Client\\Cookie\\CookieJar' => $vendorDir . '/phabel-transpiler74.amphp/http-client-cookies/src/CookieJar.php',
    'Amp\\Http\\Client\\Cookie\\FileCookieJar' => $vendorDir . '/phabel-transpiler74.amphp/http-client-cookies/src/FileCookieJar.php',
    'Amp\\Http\\Client\\Cookie\\InMemoryCookieJar' => $vendorDir . '/phabel-transpiler74.amphp/http-client-cookies/src/InMemoryCookieJar.php',
    'Amp\\Http\\Client\\Cookie\\Internal\\PublicSuffixList' => $vendorDir . '/phabel-transpiler74.amphp/http-client-cookies/src/Internal/PublicSuffixList.php',
    'Amp\\Http\\Client\\Cookie\\NullCookieJar' => $vendorDir . '/phabel-transpiler74.amphp/http-client-cookies/src/NullCookieJar.php',
    'Amp\\Http\\Client\\DelegateHttpClient' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/DelegateHttpClient.php',
    'Amp\\Http\\Client\\EventListener' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/EventListener.php',
    'Amp\\Http\\Client\\EventListener\\RecordHarAttributes' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/EventListener/RecordHarAttributes.php',
    'Amp\\Http\\Client\\HttpClient' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/HttpClient.php',
    'Amp\\Http\\Client\\HttpClientBuilder' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/HttpClientBuilder.php',
    'Amp\\Http\\Client\\HttpException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/HttpException.php',
    'Amp\\Http\\Client\\InterceptedHttpClient' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/InterceptedHttpClient.php',
    'Amp\\Http\\Client\\Interceptor\\AddRequestHeader' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/AddRequestHeader.php',
    'Amp\\Http\\Client\\Interceptor\\AddResponseHeader' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/AddResponseHeader.php',
    'Amp\\Http\\Client\\Interceptor\\DecompressResponse' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/DecompressResponse.php',
    'Amp\\Http\\Client\\Interceptor\\FollowRedirects' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/FollowRedirects.php',
    'Amp\\Http\\Client\\Interceptor\\ForbidUriUserInfo' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/ForbidUriUserInfo.php',
    'Amp\\Http\\Client\\Interceptor\\LogHttpArchive' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/LogHttpArchive.php',
    'Amp\\Http\\Client\\Interceptor\\MatchOrigin' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/MatchOrigin.php',
    'Amp\\Http\\Client\\Interceptor\\ModifyRequest' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/ModifyRequest.php',
    'Amp\\Http\\Client\\Interceptor\\ModifyResponse' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/ModifyResponse.php',
    'Amp\\Http\\Client\\Interceptor\\RemoveRequestHeader' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/RemoveRequestHeader.php',
    'Amp\\Http\\Client\\Interceptor\\RemoveResponseHeader' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/RemoveResponseHeader.php',
    'Amp\\Http\\Client\\Interceptor\\RetryRequests' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/RetryRequests.php',
    'Amp\\Http\\Client\\Interceptor\\SetRequestHeader' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestHeader.php',
    'Amp\\Http\\Client\\Interceptor\\SetRequestHeaderIfUnset' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestHeaderIfUnset.php',
    'Amp\\Http\\Client\\Interceptor\\SetRequestTimeout' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestTimeout.php',
    'Amp\\Http\\Client\\Interceptor\\SetResponseHeader' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetResponseHeader.php',
    'Amp\\Http\\Client\\Interceptor\\SetResponseHeaderIfUnset' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetResponseHeaderIfUnset.php',
    'Amp\\Http\\Client\\Interceptor\\TooManyRedirectsException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Interceptor/TooManyRedirectsException.php',
    'Amp\\Http\\Client\\Internal\\ForbidCloning' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Internal/ForbidCloning.php',
    'Amp\\Http\\Client\\Internal\\ForbidSerialization' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Internal/ForbidSerialization.php',
    'Amp\\Http\\Client\\Internal\\HarAttributes' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Internal/HarAttributes.php',
    'Amp\\Http\\Client\\Internal\\ResponseBodyStream' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Internal/ResponseBodyStream.php',
    'Amp\\Http\\Client\\Internal\\SizeLimitingInputStream' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Internal/SizeLimitingInputStream.php',
    'Amp\\Http\\Client\\InvalidRequestException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/InvalidRequestException.php',
    'Amp\\Http\\Client\\MissingAttributeError' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/MissingAttributeError.php',
    'Amp\\Http\\Client\\NetworkInterceptor' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/NetworkInterceptor.php',
    'Amp\\Http\\Client\\ParseException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/ParseException.php',
    'Amp\\Http\\Client\\PooledHttpClient' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/PooledHttpClient.php',
    'Amp\\Http\\Client\\Request' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Request.php',
    'Amp\\Http\\Client\\RequestBody' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/RequestBody.php',
    'Amp\\Http\\Client\\Response' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Response.php',
    'Amp\\Http\\Client\\SocketException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/SocketException.php',
    'Amp\\Http\\Client\\TimeoutException' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/TimeoutException.php',
    'Amp\\Http\\Client\\Trailers' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Trailers.php',
    'Amp\\Http\\Cookie\\CookieAttributes' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Cookie/CookieAttributes.php',
    'Amp\\Http\\Cookie\\InvalidCookieException' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Cookie/InvalidCookieException.php',
    'Amp\\Http\\Cookie\\RequestCookie' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Cookie/RequestCookie.php',
    'Amp\\Http\\Cookie\\ResponseCookie' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Cookie/ResponseCookie.php',
    'Amp\\Http\\HPack' => $vendorDir . '/phabel-transpiler74.amphp/hpack/src/HPack.php',
    'Amp\\Http\\HPackException' => $vendorDir . '/phabel-transpiler74.amphp/hpack/src/HPackException.php',
    'Amp\\Http\\Http2\\Http2ConnectionException' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Http2/Http2ConnectionException.php',
    'Amp\\Http\\Http2\\Http2Parser' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Http2/Http2Parser.php',
    'Amp\\Http\\Http2\\Http2Processor' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Http2/Http2Processor.php',
    'Amp\\Http\\Http2\\Http2StreamException' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Http2/Http2StreamException.php',
    'Amp\\Http\\Internal\\HPackNative' => $vendorDir . '/phabel-transpiler74.amphp/hpack/src/Internal/HPackNative.php',
    'Amp\\Http\\Internal\\HPackNghttp2' => $vendorDir . '/phabel-transpiler74.amphp/hpack/src/Internal/HPackNghttp2.php',
    'Amp\\Http\\InvalidHeaderException' => $vendorDir . '/phabel-transpiler74.amphp/http/src/InvalidHeaderException.php',
    'Amp\\Http\\Message' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Message.php',
    'Amp\\Http\\Rfc7230' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Rfc7230.php',
    'Amp\\Http\\Status' => $vendorDir . '/phabel-transpiler74.amphp/http/src/Status.php',
    'Amp\\Internal\\Placeholder' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Internal/Placeholder.php',
    'Amp\\Internal\\PrivateIterator' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Internal/PrivateIterator.php',
    'Amp\\Internal\\PrivatePromise' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Internal/PrivatePromise.php',
    'Amp\\Internal\\Producer' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Internal/Producer.php',
    'Amp\\Internal\\ResolutionQueue' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Internal/ResolutionQueue.php',
    'Amp\\InvalidYieldError' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/InvalidYieldError.php',
    'Amp\\Ipc\\IpcServer' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/IpcServer.php',
    'Amp\\Ipc\\IpcServerException' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/IpcServerException.php',
    'Amp\\Ipc\\PendingAcceptError' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/PendingAcceptError.php',
    'Amp\\Ipc\\Sync\\Channel' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/Channel.php',
    'Amp\\Ipc\\Sync\\ChannelCloseAck' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseAck.php',
    'Amp\\Ipc\\Sync\\ChannelCloseMsg' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseMsg.php',
    'Amp\\Ipc\\Sync\\ChannelCloseReq' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseReq.php',
    'Amp\\Ipc\\Sync\\ChannelException' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelException.php',
    'Amp\\Ipc\\Sync\\ChannelParser' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelParser.php',
    'Amp\\Ipc\\Sync\\ChannelledSocket' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelledSocket.php',
    'Amp\\Ipc\\Sync\\ChannelledStream' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelledStream.php',
    'Amp\\Ipc\\Sync\\PanicError' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/PanicError.php',
    'Amp\\Ipc\\Sync\\Parcel' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/Parcel.php',
    'Amp\\Ipc\\Sync\\SerializationException' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/SerializationException.php',
    'Amp\\Ipc\\Sync\\SynchronizationError' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/Sync/SynchronizationError.php',
    'Amp\\Iterator' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Iterator.php',
    'Amp\\LazyPromise' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/LazyPromise.php',
    'Amp\\Log\\ConsoleFormatter' => $vendorDir . '/phabel-transpiler74.amphp/log/src/ConsoleFormatter.php',
    'Amp\\Log\\StreamHandler' => $vendorDir . '/phabel-transpiler74.amphp/log/src/StreamHandler.php',
    'Amp\\Loop' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop.php',
    'Amp\\Loop\\Driver' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/Driver.php',
    'Amp\\Loop\\DriverFactory' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/DriverFactory.php',
    'Amp\\Loop\\EvDriver' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/EvDriver.php',
    'Amp\\Loop\\EventDriver' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/EventDriver.php',
    'Amp\\Loop\\Internal\\TimerQueue' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/Internal/TimerQueue.php',
    'Amp\\Loop\\InvalidWatcherError' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/InvalidWatcherError.php',
    'Amp\\Loop\\NativeDriver' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/NativeDriver.php',
    'Amp\\Loop\\TracingDriver' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/TracingDriver.php',
    'Amp\\Loop\\UnsupportedFeatureException' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/UnsupportedFeatureException.php',
    'Amp\\Loop\\UvDriver' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/UvDriver.php',
    'Amp\\Loop\\Watcher' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Loop/Watcher.php',
    'Amp\\MultiReasonException' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/MultiReasonException.php',
    'Amp\\Mysql\\CancellableConnector' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/CancellableConnector.php',
    'Amp\\Mysql\\CommandResult' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/CommandResult.php',
    'Amp\\Mysql\\Connection' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/Connection.php',
    'Amp\\Mysql\\ConnectionConfig' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/ConnectionConfig.php',
    'Amp\\Mysql\\ConnectionResultSet' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/ConnectionResultSet.php',
    'Amp\\Mysql\\ConnectionStatement' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/ConnectionStatement.php',
    'Amp\\Mysql\\ConnectionTransaction' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/ConnectionTransaction.php',
    'Amp\\Mysql\\DataTypes' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/DataTypes.php',
    'Amp\\Mysql\\InitializationException' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/InitializationException.php',
    'Amp\\Mysql\\Internal\\ConnectionState' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/Internal/ConnectionState.php',
    'Amp\\Mysql\\Internal\\Processor' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/Internal/Processor.php',
    'Amp\\Mysql\\Internal\\ResultProxy' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/Internal/ResultProxy.php',
    'Amp\\Mysql\\Pool' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/Pool.php',
    'Amp\\Mysql\\PooledResultSet' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/PooledResultSet.php',
    'Amp\\Mysql\\PooledStatement' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/PooledStatement.php',
    'Amp\\Mysql\\PooledTransaction' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/PooledTransaction.php',
    'Amp\\Mysql\\RefreshTypes' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/RefreshTypes.php',
    'Amp\\Mysql\\ResultSet' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/ResultSet.php',
    'Amp\\Mysql\\Statement' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/Statement.php',
    'Amp\\Mysql\\StatementPool' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/StatementPool.php',
    'Amp\\Mysql\\TransactionError' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/TransactionError.php',
    'Amp\\NullCancellationToken' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/NullCancellationToken.php',
    'Amp\\Parallel\\Context\\Context' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/Context.php',
    'Amp\\Parallel\\Context\\ContextException' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/ContextException.php',
    'Amp\\Parallel\\Context\\ContextFactory' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/ContextFactory.php',
    'Amp\\Parallel\\Context\\DefaultContextFactory' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/DefaultContextFactory.php',
    'Amp\\Parallel\\Context\\Internal\\ParallelHub' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/Internal/ParallelHub.php',
    'Amp\\Parallel\\Context\\Internal\\ProcessHub' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/Internal/ProcessHub.php',
    'Amp\\Parallel\\Context\\Internal\\Thread' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/Internal/Thread.php',
    'Amp\\Parallel\\Context\\Parallel' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/Parallel.php',
    'Amp\\Parallel\\Context\\Process' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/Process.php',
    'Amp\\Parallel\\Context\\StatusError' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/StatusError.php',
    'Amp\\Parallel\\Context\\Thread' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/Thread.php',
    'Amp\\Parallel\\Sync\\Channel' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/Channel.php',
    'Amp\\Parallel\\Sync\\ChannelException' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelException.php',
    'Amp\\Parallel\\Sync\\ChannelParser' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelParser.php',
    'Amp\\Parallel\\Sync\\ChannelledSocket' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelledSocket.php',
    'Amp\\Parallel\\Sync\\ChannelledStream' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelledStream.php',
    'Amp\\Parallel\\Sync\\ContextPanicError' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ContextPanicError.php',
    'Amp\\Parallel\\Sync\\ExitFailure' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ExitFailure.php',
    'Amp\\Parallel\\Sync\\ExitResult' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ExitResult.php',
    'Amp\\Parallel\\Sync\\ExitSuccess' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ExitSuccess.php',
    'Amp\\Parallel\\Sync\\Internal\\ParcelStorage' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/Internal/ParcelStorage.php',
    'Amp\\Parallel\\Sync\\PanicError' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/PanicError.php',
    'Amp\\Parallel\\Sync\\Parcel' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/Parcel.php',
    'Amp\\Parallel\\Sync\\ParcelException' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ParcelException.php',
    'Amp\\Parallel\\Sync\\SharedMemoryException' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/SharedMemoryException.php',
    'Amp\\Parallel\\Sync\\SharedMemoryParcel' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/SharedMemoryParcel.php',
    'Amp\\Parallel\\Sync\\SynchronizationError' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/SynchronizationError.php',
    'Amp\\Parallel\\Sync\\ThreadedParcel' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/ThreadedParcel.php',
    'Amp\\Parallel\\Worker\\BasicEnvironment' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/BasicEnvironment.php',
    'Amp\\Parallel\\Worker\\BootstrapWorkerFactory' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/BootstrapWorkerFactory.php',
    'Amp\\Parallel\\Worker\\CallableTask' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/CallableTask.php',
    'Amp\\Parallel\\Worker\\DefaultPool' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/DefaultPool.php',
    'Amp\\Parallel\\Worker\\DefaultWorkerFactory' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/DefaultWorkerFactory.php',
    'Amp\\Parallel\\Worker\\Environment' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Environment.php',
    'Amp\\Parallel\\Worker\\Internal\\Job' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/Job.php',
    'Amp\\Parallel\\Worker\\Internal\\PooledWorker' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/PooledWorker.php',
    'Amp\\Parallel\\Worker\\Internal\\TaskFailure' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskFailure.php',
    'Amp\\Parallel\\Worker\\Internal\\TaskResult' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskResult.php',
    'Amp\\Parallel\\Worker\\Internal\\TaskSuccess' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskSuccess.php',
    'Amp\\Parallel\\Worker\\Internal\\WorkerProcess' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/WorkerProcess.php',
    'Amp\\Parallel\\Worker\\Pool' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Pool.php',
    'Amp\\Parallel\\Worker\\Task' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Task.php',
    'Amp\\Parallel\\Worker\\TaskError' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskError.php',
    'Amp\\Parallel\\Worker\\TaskException' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskException.php',
    'Amp\\Parallel\\Worker\\TaskFailureError' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureError.php',
    'Amp\\Parallel\\Worker\\TaskFailureException' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureException.php',
    'Amp\\Parallel\\Worker\\TaskFailureThrowable' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureThrowable.php',
    'Amp\\Parallel\\Worker\\TaskRunner' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskRunner.php',
    'Amp\\Parallel\\Worker\\TaskWorker' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskWorker.php',
    'Amp\\Parallel\\Worker\\Worker' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/Worker.php',
    'Amp\\Parallel\\Worker\\WorkerException' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerException.php',
    'Amp\\Parallel\\Worker\\WorkerFactory' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerFactory.php',
    'Amp\\Parallel\\Worker\\WorkerParallel' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerParallel.php',
    'Amp\\Parallel\\Worker\\WorkerProcess' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerProcess.php',
    'Amp\\Parallel\\Worker\\WorkerThread' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerThread.php',
    'Amp\\Parser\\InvalidDelimiterError' => $vendorDir . '/phabel-transpiler74.amphp/parser/lib/InvalidDelimiterError.php',
    'Amp\\Parser\\Parser' => $vendorDir . '/phabel-transpiler74.amphp/parser/lib/Parser.php',
    'Amp\\Postgres\\Connection' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Connection.php',
    'Amp\\Postgres\\ConnectionConfig' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/ConnectionConfig.php',
    'Amp\\Postgres\\ConnectionListener' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/ConnectionListener.php',
    'Amp\\Postgres\\ConnectionTransaction' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/ConnectionTransaction.php',
    'Amp\\Postgres\\Executor' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Executor.php',
    'Amp\\Postgres\\Handle' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Handle.php',
    'Amp\\Postgres\\Internal\\ArrayParser' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Internal/ArrayParser.php',
    'Amp\\Postgres\\Link' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Link.php',
    'Amp\\Postgres\\Listener' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Listener.php',
    'Amp\\Postgres\\Notification' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Notification.php',
    'Amp\\Postgres\\ParseException' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/ParseException.php',
    'Amp\\Postgres\\PgSqlCommandResult' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PgSqlCommandResult.php',
    'Amp\\Postgres\\PgSqlConnection' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PgSqlConnection.php',
    'Amp\\Postgres\\PgSqlHandle' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PgSqlHandle.php',
    'Amp\\Postgres\\PgSqlResultSet' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PgSqlResultSet.php',
    'Amp\\Postgres\\PgSqlStatement' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PgSqlStatement.php',
    'Amp\\Postgres\\Pool' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Pool.php',
    'Amp\\Postgres\\PooledListener' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PooledListener.php',
    'Amp\\Postgres\\PooledResultSet' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PooledResultSet.php',
    'Amp\\Postgres\\PooledStatement' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PooledStatement.php',
    'Amp\\Postgres\\PooledTransaction' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PooledTransaction.php',
    'Amp\\Postgres\\PqBufferedResultSet' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PqBufferedResultSet.php',
    'Amp\\Postgres\\PqCommandResult' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PqCommandResult.php',
    'Amp\\Postgres\\PqConnection' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PqConnection.php',
    'Amp\\Postgres\\PqHandle' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PqHandle.php',
    'Amp\\Postgres\\PqStatement' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PqStatement.php',
    'Amp\\Postgres\\PqUnbufferedResultSet' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/PqUnbufferedResultSet.php',
    'Amp\\Postgres\\QueryExecutionError' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/QueryExecutionError.php',
    'Amp\\Postgres\\Quoter' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Quoter.php',
    'Amp\\Postgres\\Receiver' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Receiver.php',
    'Amp\\Postgres\\ResultSet' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/ResultSet.php',
    'Amp\\Postgres\\StatementPool' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/StatementPool.php',
    'Amp\\Postgres\\TimeoutConnector' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/TimeoutConnector.php',
    'Amp\\Postgres\\Transaction' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Transaction.php',
    'Amp\\Process\\Internal\\Posix\\Handle' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/Posix/Handle.php',
    'Amp\\Process\\Internal\\Posix\\Runner' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/Posix/Runner.php',
    'Amp\\Process\\Internal\\ProcessHandle' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/ProcessHandle.php',
    'Amp\\Process\\Internal\\ProcessRunner' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/ProcessRunner.php',
    'Amp\\Process\\Internal\\ProcessStatus' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/ProcessStatus.php',
    'Amp\\Process\\Internal\\Windows\\Handle' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/Handle.php',
    'Amp\\Process\\Internal\\Windows\\HandshakeStatus' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/HandshakeStatus.php',
    'Amp\\Process\\Internal\\Windows\\PendingSocketClient' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/PendingSocketClient.php',
    'Amp\\Process\\Internal\\Windows\\Runner' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/Runner.php',
    'Amp\\Process\\Internal\\Windows\\SignalCode' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/SignalCode.php',
    'Amp\\Process\\Internal\\Windows\\SocketConnector' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/SocketConnector.php',
    'Amp\\Process\\Process' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/Process.php',
    'Amp\\Process\\ProcessException' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/ProcessException.php',
    'Amp\\Process\\ProcessInputStream' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/ProcessInputStream.php',
    'Amp\\Process\\ProcessOutputStream' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/ProcessOutputStream.php',
    'Amp\\Process\\StatusError' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/StatusError.php',
    'Amp\\Producer' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Producer.php',
    'Amp\\Promise' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Promise.php',
    'Amp\\Redis\\Cache' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Cache.php',
    'Amp\\Redis\\Config' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Config.php',
    'Amp\\Redis\\Mutex\\ConnectionLimitException' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Mutex/ConnectionLimitException.php',
    'Amp\\Redis\\Mutex\\LockException' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Mutex/LockException.php',
    'Amp\\Redis\\Mutex\\Mutex' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Mutex/Mutex.php',
    'Amp\\Redis\\Mutex\\MutexException' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Mutex/MutexException.php',
    'Amp\\Redis\\Mutex\\MutexOptions' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Mutex/MutexOptions.php',
    'Amp\\Redis\\ParserException' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/ParserException.php',
    'Amp\\Redis\\QueryException' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/QueryException.php',
    'Amp\\Redis\\QueryExecutor' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/QueryExecutor.php',
    'Amp\\Redis\\QueryExecutorFactory' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/QueryExecutorFactory.php',
    'Amp\\Redis\\Redis' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Redis.php',
    'Amp\\Redis\\RedisException' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RedisException.php',
    'Amp\\Redis\\RedisHyperLogLog' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RedisHyperLogLog.php',
    'Amp\\Redis\\RedisList' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RedisList.php',
    'Amp\\Redis\\RedisMap' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RedisMap.php',
    'Amp\\Redis\\RedisSet' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RedisSet.php',
    'Amp\\Redis\\RedisSortedSet' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RedisSortedSet.php',
    'Amp\\Redis\\RemoteExecutor' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RemoteExecutor.php',
    'Amp\\Redis\\RemoteExecutorFactory' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RemoteExecutorFactory.php',
    'Amp\\Redis\\RespParser' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RespParser.php',
    'Amp\\Redis\\RespSocket' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/RespSocket.php',
    'Amp\\Redis\\SetOptions' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/SetOptions.php',
    'Amp\\Redis\\SocketException' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/SocketException.php',
    'Amp\\Redis\\SortOptions' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/SortOptions.php',
    'Amp\\Redis\\Subscriber' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Subscriber.php',
    'Amp\\Redis\\Subscription' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/Subscription.php',
    'Amp\\Serialization\\CompressingSerializer' => $vendorDir . '/phabel-transpiler74.amphp/serialization/src/CompressingSerializer.php',
    'Amp\\Serialization\\JsonSerializer' => $vendorDir . '/phabel-transpiler74.amphp/serialization/src/JsonSerializer.php',
    'Amp\\Serialization\\NativeSerializer' => $vendorDir . '/phabel-transpiler74.amphp/serialization/src/NativeSerializer.php',
    'Amp\\Serialization\\PassthroughSerializer' => $vendorDir . '/phabel-transpiler74.amphp/serialization/src/PassthroughSerializer.php',
    'Amp\\Serialization\\SerializationException' => $vendorDir . '/phabel-transpiler74.amphp/serialization/src/SerializationException.php',
    'Amp\\Serialization\\Serializer' => $vendorDir . '/phabel-transpiler74.amphp/serialization/src/Serializer.php',
    'Amp\\Socket\\BindContext' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/BindContext.php',
    'Amp\\Socket\\Certificate' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/Certificate.php',
    'Amp\\Socket\\ClientTlsContext' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/ClientTlsContext.php',
    'Amp\\Socket\\ConnectContext' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/ConnectContext.php',
    'Amp\\Socket\\ConnectException' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/ConnectException.php',
    'Amp\\Socket\\Connector' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/Connector.php',
    'Amp\\Socket\\DatagramSocket' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/DatagramSocket.php',
    'Amp\\Socket\\DnsConnector' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/DnsConnector.php',
    'Amp\\Socket\\EncryptableSocket' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/EncryptableSocket.php',
    'Amp\\Socket\\PendingAcceptError' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/PendingAcceptError.php',
    'Amp\\Socket\\PendingReceiveError' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/PendingReceiveError.php',
    'Amp\\Socket\\ResourceSocket' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/ResourceSocket.php',
    'Amp\\Socket\\Server' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/Server.php',
    'Amp\\Socket\\ServerTlsContext' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/ServerTlsContext.php',
    'Amp\\Socket\\Socket' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/Socket.php',
    'Amp\\Socket\\SocketAddress' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/SocketAddress.php',
    'Amp\\Socket\\SocketException' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/SocketException.php',
    'Amp\\Socket\\SocketPool' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/SocketPool.php',
    'Amp\\Socket\\StaticConnector' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/StaticConnector.php',
    'Amp\\Socket\\TlsException' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/TlsException.php',
    'Amp\\Socket\\TlsInfo' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/TlsInfo.php',
    'Amp\\Socket\\UnlimitedSocketPool' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/UnlimitedSocketPool.php',
    'Amp\\Sql\\CommandResult' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/CommandResult.php',
    'Amp\\Sql\\Common\\ConnectionPool' => $vendorDir . '/phabel-transpiler74.amphp/sql-common/src/ConnectionPool.php',
    'Amp\\Sql\\Common\\PooledResultSet' => $vendorDir . '/phabel-transpiler74.amphp/sql-common/src/PooledResultSet.php',
    'Amp\\Sql\\Common\\PooledStatement' => $vendorDir . '/phabel-transpiler74.amphp/sql-common/src/PooledStatement.php',
    'Amp\\Sql\\Common\\PooledTransaction' => $vendorDir . '/phabel-transpiler74.amphp/sql-common/src/PooledTransaction.php',
    'Amp\\Sql\\Common\\RetryConnector' => $vendorDir . '/phabel-transpiler74.amphp/sql-common/src/RetryConnector.php',
    'Amp\\Sql\\Common\\StatementPool' => $vendorDir . '/phabel-transpiler74.amphp/sql-common/src/StatementPool.php',
    'Amp\\Sql\\ConnectionConfig' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/ConnectionConfig.php',
    'Amp\\Sql\\ConnectionException' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/ConnectionException.php',
    'Amp\\Sql\\Connector' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/Connector.php',
    'Amp\\Sql\\Executor' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/Executor.php',
    'Amp\\Sql\\FailureException' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/FailureException.php',
    'Amp\\Sql\\Link' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/Link.php',
    'Amp\\Sql\\Pool' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/Pool.php',
    'Amp\\Sql\\PoolError' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/PoolError.php',
    'Amp\\Sql\\QueryError' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/QueryError.php',
    'Amp\\Sql\\ResultSet' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/ResultSet.php',
    'Amp\\Sql\\Statement' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/Statement.php',
    'Amp\\Sql\\Transaction' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/Transaction.php',
    'Amp\\Sql\\TransactionError' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/TransactionError.php',
    'Amp\\Sql\\TransientResource' => $vendorDir . '/phabel-transpiler74.amphp/sql/src/TransientResource.php',
    'Amp\\Struct' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Struct.php',
    'Amp\\Success' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Success.php',
    'Amp\\Sync\\Barrier' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/Barrier.php',
    'Amp\\Sync\\FileMutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/FileMutex.php',
    'Amp\\Sync\\Internal\\MutexStorage' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/Internal/MutexStorage.php',
    'Amp\\Sync\\Internal\\SemaphoreStorage' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/Internal/SemaphoreStorage.php',
    'Amp\\Sync\\KeyedMutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/KeyedMutex.php',
    'Amp\\Sync\\KeyedSemaphore' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/KeyedSemaphore.php',
    'Amp\\Sync\\LocalKeyedMutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/LocalKeyedMutex.php',
    'Amp\\Sync\\LocalKeyedSemaphore' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/LocalKeyedSemaphore.php',
    'Amp\\Sync\\LocalMutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/LocalMutex.php',
    'Amp\\Sync\\LocalSemaphore' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/LocalSemaphore.php',
    'Amp\\Sync\\Lock' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/Lock.php',
    'Amp\\Sync\\Mutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/Mutex.php',
    'Amp\\Sync\\PosixSemaphore' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/PosixSemaphore.php',
    'Amp\\Sync\\PrefixedKeyedMutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/PrefixedKeyedMutex.php',
    'Amp\\Sync\\PrefixedKeyedSemaphore' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/PrefixedKeyedSemaphore.php',
    'Amp\\Sync\\Semaphore' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/Semaphore.php',
    'Amp\\Sync\\SemaphoreMutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/SemaphoreMutex.php',
    'Amp\\Sync\\StaticKeyMutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/StaticKeyMutex.php',
    'Amp\\Sync\\SyncException' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/SyncException.php',
    'Amp\\Sync\\ThreadedMutex' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/ThreadedMutex.php',
    'Amp\\Sync\\ThreadedSemaphore' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/ThreadedSemaphore.php',
    'Amp\\TimeoutCancellationToken' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/TimeoutCancellationToken.php',
    'Amp\\TimeoutException' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/TimeoutException.php',
    'Amp\\Websocket\\Client' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/Client.php',
    'Amp\\Websocket\\ClientMetadata' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/ClientMetadata.php',
    'Amp\\Websocket\\Client\\Connection' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/Connection.php',
    'Amp\\Websocket\\Client\\ConnectionException' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/ConnectionException.php',
    'Amp\\Websocket\\Client\\ConnectionFactory' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/ConnectionFactory.php',
    'Amp\\Websocket\\Client\\Connector' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/Connector.php',
    'Amp\\Websocket\\Client\\Handshake' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/Handshake.php',
    'Amp\\Websocket\\Client\\Rfc6455Connection' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/Rfc6455Connection.php',
    'Amp\\Websocket\\Client\\Rfc6455ConnectionFactory' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/Rfc6455ConnectionFactory.php',
    'Amp\\Websocket\\Client\\Rfc6455Connector' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/Rfc6455Connector.php',
    'Amp\\Websocket\\ClosedException' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/ClosedException.php',
    'Amp\\Websocket\\Code' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/Code.php',
    'Amp\\Websocket\\CompressionContext' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/CompressionContext.php',
    'Amp\\Websocket\\CompressionContextFactory' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/CompressionContextFactory.php',
    'Amp\\Websocket\\Message' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/Message.php',
    'Amp\\Websocket\\Opcode' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/Opcode.php',
    'Amp\\Websocket\\Options' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/Options.php',
    'Amp\\Websocket\\Rfc6455Client' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/Rfc6455Client.php',
    'Amp\\Websocket\\Rfc7692Compression' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/Rfc7692Compression.php',
    'Amp\\Websocket\\Rfc7692CompressionFactory' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/Rfc7692CompressionFactory.php',
    'Amp\\WindowsRegistry\\KeyNotFoundException' => $vendorDir . '/phabel-transpiler74.amphp/windows-registry/lib/KeyNotFoundException.php',
    'Amp\\WindowsRegistry\\WindowsRegistry' => $vendorDir . '/phabel-transpiler74.amphp/windows-registry/lib/WindowsRegistry.php',
    'Attribute' => $vendorDir . '/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/Attribute.php',
    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    'JsonException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-php73/Resources/stubs/JsonException.php',
    'Kelunik\\Certificate\\Certificate' => $vendorDir . '/phabel-transpiler74.kelunik/certificate/lib/Certificate.php',
    'Kelunik\\Certificate\\FieldNotSupportedException' => $vendorDir . '/phabel-transpiler74.kelunik/certificate/lib/FieldNotSupportedException.php',
    'Kelunik\\Certificate\\InvalidCertificateException' => $vendorDir . '/phabel-transpiler74.kelunik/certificate/lib/InvalidCertificateException.php',
    'Kelunik\\Certificate\\Profile' => $vendorDir . '/phabel-transpiler74.kelunik/certificate/lib/Profile.php',
    'League\\Uri\\Contracts\\AuthorityInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/AuthorityInterface.php',
    'League\\Uri\\Contracts\\DataPathInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/DataPathInterface.php',
    'League\\Uri\\Contracts\\DomainHostInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/DomainHostInterface.php',
    'League\\Uri\\Contracts\\FragmentInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/FragmentInterface.php',
    'League\\Uri\\Contracts\\HostInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/HostInterface.php',
    'League\\Uri\\Contracts\\IpHostInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/IpHostInterface.php',
    'League\\Uri\\Contracts\\PathInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/PathInterface.php',
    'League\\Uri\\Contracts\\PortInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/PortInterface.php',
    'League\\Uri\\Contracts\\QueryInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/QueryInterface.php',
    'League\\Uri\\Contracts\\SegmentedPathInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/SegmentedPathInterface.php',
    'League\\Uri\\Contracts\\UriComponentInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriComponentInterface.php',
    'League\\Uri\\Contracts\\UriException' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriException.php',
    'League\\Uri\\Contracts\\UriInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriInterface.php',
    'League\\Uri\\Contracts\\UserInfoInterface' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/UserInfoInterface.php',
    'League\\Uri\\Exception' => $vendorDir . '/phabel-transpiler74.league/uri-parser/src/Exception.php',
    'League\\Uri\\Exceptions\\FileinfoSupportMissing' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php',
    'League\\Uri\\Exceptions\\IdnSupportMissing' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Exceptions/IdnSupportMissing.php',
    'League\\Uri\\Exceptions\\IdnaConversionFailed' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php',
    'League\\Uri\\Exceptions\\SyntaxError' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Exceptions/SyntaxError.php',
    'League\\Uri\\Exceptions\\TemplateCanNotBeExpanded' => $vendorDir . '/phabel-transpiler74.league/uri/src/Exceptions/TemplateCanNotBeExpanded.php',
    'League\\Uri\\Http' => $vendorDir . '/phabel-transpiler74.league/uri/src/Http.php',
    'League\\Uri\\HttpFactory' => $vendorDir . '/phabel-transpiler74.league/uri/src/HttpFactory.php',
    'League\\Uri\\Idna\\Idna' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Idna/Idna.php',
    'League\\Uri\\Idna\\IdnaInfo' => $vendorDir . '/phabel-transpiler74.league/uri-interfaces/src/Idna/IdnaInfo.php',
    'League\\Uri\\MissingIdnSupport' => $vendorDir . '/phabel-transpiler74.league/uri-parser/src/MissingIdnSupport.php',
    'League\\Uri\\Parser' => $vendorDir . '/phabel-transpiler74.league/uri-parser/src/Parser.php',
    'League\\Uri\\Uri' => $vendorDir . '/phabel-transpiler74.league/uri/src/Uri.php',
    'League\\Uri\\UriInfo' => $vendorDir . '/phabel-transpiler74.league/uri/src/UriInfo.php',
    'League\\Uri\\UriResolver' => $vendorDir . '/phabel-transpiler74.league/uri/src/UriResolver.php',
    'League\\Uri\\UriString' => $vendorDir . '/phabel-transpiler74.league/uri/src/UriString.php',
    'League\\Uri\\UriTemplate' => $vendorDir . '/phabel-transpiler74.league/uri/src/UriTemplate.php',
    'League\\Uri\\UriTemplate\\Expression' => $vendorDir . '/phabel-transpiler74.league/uri/src/UriTemplate/Expression.php',
    'League\\Uri\\UriTemplate\\Template' => $vendorDir . '/phabel-transpiler74.league/uri/src/UriTemplate/Template.php',
    'League\\Uri\\UriTemplate\\VarSpecifier' => $vendorDir . '/phabel-transpiler74.league/uri/src/UriTemplate/VarSpecifier.php',
    'League\\Uri\\UriTemplate\\VariableBag' => $vendorDir . '/phabel-transpiler74.league/uri/src/UriTemplate/VariableBag.php',
    'LibDNS\\Decoder\\Decoder' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Decoder/Decoder.php',
    'LibDNS\\Decoder\\DecoderFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Decoder/DecoderFactory.php',
    'LibDNS\\Decoder\\DecodingContext' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Decoder/DecodingContext.php',
    'LibDNS\\Decoder\\DecodingContextFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Decoder/DecodingContextFactory.php',
    'LibDNS\\Encoder\\Encoder' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Encoder/Encoder.php',
    'LibDNS\\Encoder\\EncoderFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Encoder/EncoderFactory.php',
    'LibDNS\\Encoder\\EncodingContext' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Encoder/EncodingContext.php',
    'LibDNS\\Encoder\\EncodingContextFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Encoder/EncodingContextFactory.php',
    'LibDNS\\Enumeration' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Enumeration.php',
    'LibDNS\\Messages\\Message' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Messages/Message.php',
    'LibDNS\\Messages\\MessageFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Messages/MessageFactory.php',
    'LibDNS\\Messages\\MessageOpCodes' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Messages/MessageOpCodes.php',
    'LibDNS\\Messages\\MessageResponseCodes' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Messages/MessageResponseCodes.php',
    'LibDNS\\Messages\\MessageTypes' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Messages/MessageTypes.php',
    'LibDNS\\Packets\\LabelRegistry' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Packets/LabelRegistry.php',
    'LibDNS\\Packets\\Packet' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Packets/Packet.php',
    'LibDNS\\Packets\\PacketFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Packets/PacketFactory.php',
    'LibDNS\\Records\\Question' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Question.php',
    'LibDNS\\Records\\QuestionFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/QuestionFactory.php',
    'LibDNS\\Records\\RData' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/RData.php',
    'LibDNS\\Records\\RDataBuilder' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/RDataBuilder.php',
    'LibDNS\\Records\\RDataFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/RDataFactory.php',
    'LibDNS\\Records\\Record' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Record.php',
    'LibDNS\\Records\\RecordCollection' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/RecordCollection.php',
    'LibDNS\\Records\\RecordCollectionFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/RecordCollectionFactory.php',
    'LibDNS\\Records\\RecordTypes' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/RecordTypes.php',
    'LibDNS\\Records\\Resource' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Resource.php',
    'LibDNS\\Records\\ResourceBuilder' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceBuilder.php',
    'LibDNS\\Records\\ResourceBuilderFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceBuilderFactory.php',
    'LibDNS\\Records\\ResourceClasses' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceClasses.php',
    'LibDNS\\Records\\ResourceFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceFactory.php',
    'LibDNS\\Records\\ResourceQClasses' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceQClasses.php',
    'LibDNS\\Records\\ResourceQTypes' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceQTypes.php',
    'LibDNS\\Records\\ResourceTypes' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceTypes.php',
    'LibDNS\\Records\\TypeDefinitions\\FieldDefinition' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/FieldDefinition.php',
    'LibDNS\\Records\\TypeDefinitions\\FieldDefinitionFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/FieldDefinitionFactory.php',
    'LibDNS\\Records\\TypeDefinitions\\TypeDefinition' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinition.php',
    'LibDNS\\Records\\TypeDefinitions\\TypeDefinitionFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionFactory.php',
    'LibDNS\\Records\\TypeDefinitions\\TypeDefinitionManager' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionManager.php',
    'LibDNS\\Records\\TypeDefinitions\\TypeDefinitionManagerFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionManagerFactory.php',
    'LibDNS\\Records\\Types\\Anything' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Anything.php',
    'LibDNS\\Records\\Types\\BitMap' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/BitMap.php',
    'LibDNS\\Records\\Types\\Char' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Char.php',
    'LibDNS\\Records\\Types\\CharacterString' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/CharacterString.php',
    'LibDNS\\Records\\Types\\DomainName' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/DomainName.php',
    'LibDNS\\Records\\Types\\IPv4Address' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/IPv4Address.php',
    'LibDNS\\Records\\Types\\IPv6Address' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/IPv6Address.php',
    'LibDNS\\Records\\Types\\Long' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Long.php',
    'LibDNS\\Records\\Types\\Short' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Short.php',
    'LibDNS\\Records\\Types\\Type' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Type.php',
    'LibDNS\\Records\\Types\\TypeBuilder' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/TypeBuilder.php',
    'LibDNS\\Records\\Types\\TypeFactory' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/TypeFactory.php',
    'LibDNS\\Records\\Types\\Types' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Types.php',
    'Monolog\\DateTimeImmutable' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/DateTimeImmutable.php',
    'Monolog\\ErrorHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/ErrorHandler.php',
    'Monolog\\Formatter\\ChromePHPFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php',
    'Monolog\\Formatter\\ElasticaFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php',
    'Monolog\\Formatter\\ElasticsearchFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php',
    'Monolog\\Formatter\\FlowdockFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php',
    'Monolog\\Formatter\\FluentdFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php',
    'Monolog\\Formatter\\FormatterInterface' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FormatterInterface.php',
    'Monolog\\Formatter\\GelfMessageFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php',
    'Monolog\\Formatter\\HtmlFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php',
    'Monolog\\Formatter\\JsonFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/JsonFormatter.php',
    'Monolog\\Formatter\\LineFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LineFormatter.php',
    'Monolog\\Formatter\\LogglyFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php',
    'Monolog\\Formatter\\LogmaticFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php',
    'Monolog\\Formatter\\LogstashFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php',
    'Monolog\\Formatter\\MongoDBFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
    'Monolog\\Formatter\\NormalizerFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
    'Monolog\\Formatter\\ScalarFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
    'Monolog\\Formatter\\WildfireFormatter' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
    'Monolog\\Handler\\AbstractHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
    'Monolog\\Handler\\AbstractProcessingHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
    'Monolog\\Handler\\AbstractSyslogHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php',
    'Monolog\\Handler\\AmqpHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AmqpHandler.php',
    'Monolog\\Handler\\BrowserConsoleHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php',
    'Monolog\\Handler\\BufferHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/BufferHandler.php',
    'Monolog\\Handler\\ChromePHPHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php',
    'Monolog\\Handler\\CouchDBHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/CouchDBHandler.php',
    'Monolog\\Handler\\CubeHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/CubeHandler.php',
    'Monolog\\Handler\\Curl\\Util' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Curl/Util.php',
    'Monolog\\Handler\\DeduplicationHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php',
    'Monolog\\Handler\\DoctrineCouchDBHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php',
    'Monolog\\Handler\\DynamoDbHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php',
    'Monolog\\Handler\\ElasticaHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ElasticaHandler.php',
    'Monolog\\Handler\\ElasticsearchHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php',
    'Monolog\\Handler\\ErrorLogHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php',
    'Monolog\\Handler\\FallbackGroupHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php',
    'Monolog\\Handler\\FilterHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FilterHandler.php',
    'Monolog\\Handler\\FingersCrossedHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php',
    'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php',
    'Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php',
    'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php',
    'Monolog\\Handler\\FirePHPHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FirePHPHandler.php',
    'Monolog\\Handler\\FleepHookHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FleepHookHandler.php',
    'Monolog\\Handler\\FlowdockHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FlowdockHandler.php',
    'Monolog\\Handler\\FormattableHandlerInterface' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php',
    'Monolog\\Handler\\FormattableHandlerTrait' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php',
    'Monolog\\Handler\\GelfHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/GelfHandler.php',
    'Monolog\\Handler\\GroupHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/GroupHandler.php',
    'Monolog\\Handler\\Handler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Handler.php',
    'Monolog\\Handler\\HandlerInterface' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/HandlerInterface.php',
    'Monolog\\Handler\\HandlerWrapper' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
    'Monolog\\Handler\\IFTTTHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
    'Monolog\\Handler\\InsightOpsHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php',
    'Monolog\\Handler\\LogEntriesHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
    'Monolog\\Handler\\LogglyHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
    'Monolog\\Handler\\LogmaticHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogmaticHandler.php',
    'Monolog\\Handler\\MailHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MailHandler.php',
    'Monolog\\Handler\\MandrillHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MandrillHandler.php',
    'Monolog\\Handler\\MissingExtensionException' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MissingExtensionException.php',
    'Monolog\\Handler\\MongoDBHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MongoDBHandler.php',
    'Monolog\\Handler\\NativeMailerHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php',
    'Monolog\\Handler\\NewRelicHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NewRelicHandler.php',
    'Monolog\\Handler\\NoopHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NoopHandler.php',
    'Monolog\\Handler\\NullHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NullHandler.php',
    'Monolog\\Handler\\OverflowHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/OverflowHandler.php',
    'Monolog\\Handler\\PHPConsoleHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php',
    'Monolog\\Handler\\ProcessHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessHandler.php',
    'Monolog\\Handler\\ProcessableHandlerInterface' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php',
    'Monolog\\Handler\\ProcessableHandlerTrait' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php',
    'Monolog\\Handler\\PsrHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PsrHandler.php',
    'Monolog\\Handler\\PushoverHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PushoverHandler.php',
    'Monolog\\Handler\\RedisHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RedisHandler.php',
    'Monolog\\Handler\\RedisPubSubHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php',
    'Monolog\\Handler\\RollbarHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RollbarHandler.php',
    'Monolog\\Handler\\RotatingFileHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php',
    'Monolog\\Handler\\SamplingHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SamplingHandler.php',
    'Monolog\\Handler\\SendGridHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SendGridHandler.php',
    'Monolog\\Handler\\SlackHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SlackHandler.php',
    'Monolog\\Handler\\SlackWebhookHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php',
    'Monolog\\Handler\\Slack\\SlackRecord' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php',
    'Monolog\\Handler\\SocketHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SocketHandler.php',
    'Monolog\\Handler\\SqsHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SqsHandler.php',
    'Monolog\\Handler\\StreamHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/StreamHandler.php',
    'Monolog\\Handler\\SwiftMailerHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php',
    'Monolog\\Handler\\SyslogHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
    'Monolog\\Handler\\SyslogUdpHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
    'Monolog\\Handler\\SyslogUdp\\UdpSocket' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php',
    'Monolog\\Handler\\TelegramBotHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php',
    'Monolog\\Handler\\TestHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/TestHandler.php',
    'Monolog\\Handler\\WebRequestRecognizerTrait' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php',
    'Monolog\\Handler\\WhatFailureGroupHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php',
    'Monolog\\Handler\\ZendMonitorHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php',
    'Monolog\\Logger' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Logger.php',
    'Monolog\\Processor\\GitProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/GitProcessor.php',
    'Monolog\\Processor\\HostnameProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/HostnameProcessor.php',
    'Monolog\\Processor\\IntrospectionProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php',
    'Monolog\\Processor\\MemoryPeakUsageProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php',
    'Monolog\\Processor\\MemoryProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryProcessor.php',
    'Monolog\\Processor\\MemoryUsageProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
    'Monolog\\Processor\\MercurialProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
    'Monolog\\Processor\\ProcessIdProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
    'Monolog\\Processor\\ProcessorInterface' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/ProcessorInterface.php',
    'Monolog\\Processor\\PsrLogMessageProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
    'Monolog\\Processor\\TagProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/TagProcessor.php',
    'Monolog\\Processor\\UidProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/UidProcessor.php',
    'Monolog\\Processor\\WebProcessor' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/WebProcessor.php',
    'Monolog\\Registry' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Registry.php',
    'Monolog\\ResettableInterface' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/ResettableInterface.php',
    'Monolog\\SignalHandler' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/SignalHandler.php',
    'Monolog\\Test\\TestCase' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Test/TestCase.php',
    'Monolog\\Utils' => $vendorDir . '/phabel-transpiler74.monolog/monolog/src/Monolog/Utils.php',
    'Normalizer' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
    'ParagonIE\\ConstantTime\\Base32' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base32.php',
    'ParagonIE\\ConstantTime\\Base32Hex' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base32Hex.php',
    'ParagonIE\\ConstantTime\\Base64' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64.php',
    'ParagonIE\\ConstantTime\\Base64DotSlash' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64DotSlash.php',
    'ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php',
    'ParagonIE\\ConstantTime\\Base64UrlSafe' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64UrlSafe.php',
    'ParagonIE\\ConstantTime\\Binary' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Binary.php',
    'ParagonIE\\ConstantTime\\EncoderInterface' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/EncoderInterface.php',
    'ParagonIE\\ConstantTime\\Encoding' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Encoding.php',
    'ParagonIE\\ConstantTime\\Hex' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Hex.php',
    'ParagonIE\\ConstantTime\\RFC4648' => $vendorDir . '/phabel-transpiler74.paragonie/constant_time_encoding/src/RFC4648.php',
    'Parsedown' => $vendorDir . '/phabel-transpiler74.erusev/parsedown/Parsedown.php',
    'PhabelVendor\\Amp\\ByteStream\\Base64\\Base64DecodingInputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64DecodingInputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\Base64\\Base64DecodingOutputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\Base64\\Base64EncodingInputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\Base64\\Base64EncodingOutputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\ClosedException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ClosedException.php',
    'PhabelVendor\\Amp\\ByteStream\\InMemoryStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InMemoryStream.php',
    'PhabelVendor\\Amp\\ByteStream\\InputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\InputStreamChain' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InputStreamChain.php',
    'PhabelVendor\\Amp\\ByteStream\\IteratorStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/IteratorStream.php',
    'PhabelVendor\\Amp\\ByteStream\\LineReader' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/LineReader.php',
    'PhabelVendor\\Amp\\ByteStream\\Message' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Message.php',
    'PhabelVendor\\Amp\\ByteStream\\OutputBuffer' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/OutputBuffer.php',
    'PhabelVendor\\Amp\\ByteStream\\OutputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/OutputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\Payload' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Payload.php',
    'PhabelVendor\\Amp\\ByteStream\\PendingReadError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/PendingReadError.php',
    'PhabelVendor\\Amp\\ByteStream\\ResourceInputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ResourceInputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\ResourceOutputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ResourceOutputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\StreamException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/StreamException.php',
    'PhabelVendor\\Amp\\ByteStream\\ZlibInputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ZlibInputStream.php',
    'PhabelVendor\\Amp\\ByteStream\\ZlibOutputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ZlibOutputStream.php',
    'PhabelVendor\\Amp\\CallableMaker' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CallableMaker.php',
    'PhabelVendor\\Amp\\CancellationToken' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CancellationToken.php',
    'PhabelVendor\\Amp\\CancellationTokenSource' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CancellationTokenSource.php',
    'PhabelVendor\\Amp\\CancelledException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CancelledException.php',
    'PhabelVendor\\Amp\\CombinedCancellationToken' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CombinedCancellationToken.php',
    'PhabelVendor\\Amp\\Coroutine' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Coroutine.php',
    'PhabelVendor\\Amp\\Deferred' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Deferred.php',
    'PhabelVendor\\Amp\\Delayed' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Delayed.php',
    'PhabelVendor\\Amp\\Emitter' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Emitter.php',
    'PhabelVendor\\Amp\\Failure' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Failure.php',
    'PhabelVendor\\Amp\\Internal\\Placeholder' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/Placeholder.php',
    'PhabelVendor\\Amp\\Internal\\PrivateIterator' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/PrivateIterator.php',
    'PhabelVendor\\Amp\\Internal\\PrivatePromise' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/PrivatePromise.php',
    'PhabelVendor\\Amp\\Internal\\Producer' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/Producer.php',
    'PhabelVendor\\Amp\\Internal\\ResolutionQueue' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/ResolutionQueue.php',
    'PhabelVendor\\Amp\\InvalidYieldError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/InvalidYieldError.php',
    'PhabelVendor\\Amp\\Iterator' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Iterator.php',
    'PhabelVendor\\Amp\\LazyPromise' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/LazyPromise.php',
    'PhabelVendor\\Amp\\Loop' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop.php',
    'PhabelVendor\\Amp\\Loop\\Driver' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Driver.php',
    'PhabelVendor\\Amp\\Loop\\DriverFactory' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/DriverFactory.php',
    'PhabelVendor\\Amp\\Loop\\EvDriver' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/EvDriver.php',
    'PhabelVendor\\Amp\\Loop\\EventDriver' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/EventDriver.php',
    'PhabelVendor\\Amp\\Loop\\Internal\\TimerQueue' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Internal/TimerQueue.php',
    'PhabelVendor\\Amp\\Loop\\InvalidWatcherError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/InvalidWatcherError.php',
    'PhabelVendor\\Amp\\Loop\\NativeDriver' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/NativeDriver.php',
    'PhabelVendor\\Amp\\Loop\\TracingDriver' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/TracingDriver.php',
    'PhabelVendor\\Amp\\Loop\\UnsupportedFeatureException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/UnsupportedFeatureException.php',
    'PhabelVendor\\Amp\\Loop\\UvDriver' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/UvDriver.php',
    'PhabelVendor\\Amp\\Loop\\Watcher' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Watcher.php',
    'PhabelVendor\\Amp\\MultiReasonException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/MultiReasonException.php',
    'PhabelVendor\\Amp\\NullCancellationToken' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/NullCancellationToken.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\Context' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Context.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\ContextException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/ContextException.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\ContextFactory' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/ContextFactory.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\DefaultContextFactory' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/DefaultContextFactory.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\Internal\\ParallelHub' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/ParallelHub.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\Internal\\ProcessHub' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/ProcessHub.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\Internal\\Thread' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/Thread.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\Parallel' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Parallel.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\Process' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Process.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\StatusError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/StatusError.php',
    'PhabelVendor\\Amp\\Parallel\\Context\\Thread' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Thread.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\Channel' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Channel.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ChannelException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelException.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ChannelParser' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelParser.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ChannelledSocket' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelledSocket.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ChannelledStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelledStream.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ContextPanicError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ContextPanicError.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ExitFailure' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitFailure.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ExitResult' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitResult.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ExitSuccess' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitSuccess.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\Internal\\ParcelStorage' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Internal/ParcelStorage.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\PanicError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/PanicError.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\Parcel' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Parcel.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ParcelException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ParcelException.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\SharedMemoryException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SharedMemoryException.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\SharedMemoryParcel' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SharedMemoryParcel.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\SynchronizationError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SynchronizationError.php',
    'PhabelVendor\\Amp\\Parallel\\Sync\\ThreadedParcel' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ThreadedParcel.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\BasicEnvironment' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/BasicEnvironment.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\BootstrapWorkerFactory' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/BootstrapWorkerFactory.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\CallableTask' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/CallableTask.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\DefaultPool' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/DefaultPool.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\DefaultWorkerFactory' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/DefaultWorkerFactory.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Environment' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Environment.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\Job' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/Job.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\PooledWorker' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/PooledWorker.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\TaskFailure' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskFailure.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\TaskResult' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskResult.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\TaskSuccess' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskSuccess.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\WorkerProcess' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/WorkerProcess.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Pool' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Pool.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Task' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Task.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\TaskError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskError.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\TaskException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskException.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\TaskFailureError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureError.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\TaskFailureException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureException.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\TaskFailureThrowable' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureThrowable.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\TaskRunner' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskRunner.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\TaskWorker' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskWorker.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\Worker' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Worker.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerException.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerFactory' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerFactory.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerParallel' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerParallel.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerProcess' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerProcess.php',
    'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerThread' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerThread.php',
    'PhabelVendor\\Amp\\Parser\\InvalidDelimiterError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parser/lib/InvalidDelimiterError.php',
    'PhabelVendor\\Amp\\Parser\\Parser' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parser/lib/Parser.php',
    'PhabelVendor\\Amp\\Process\\Internal\\Posix\\Handle' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Posix/Handle.php',
    'PhabelVendor\\Amp\\Process\\Internal\\Posix\\Runner' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Posix/Runner.php',
    'PhabelVendor\\Amp\\Process\\Internal\\ProcessHandle' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessHandle.php',
    'PhabelVendor\\Amp\\Process\\Internal\\ProcessRunner' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessRunner.php',
    'PhabelVendor\\Amp\\Process\\Internal\\ProcessStatus' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessStatus.php',
    'PhabelVendor\\Amp\\Process\\Internal\\Windows\\Handle' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/Handle.php',
    'PhabelVendor\\Amp\\Process\\Internal\\Windows\\HandshakeStatus' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/HandshakeStatus.php',
    'PhabelVendor\\Amp\\Process\\Internal\\Windows\\PendingSocketClient' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/PendingSocketClient.php',
    'PhabelVendor\\Amp\\Process\\Internal\\Windows\\Runner' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/Runner.php',
    'PhabelVendor\\Amp\\Process\\Internal\\Windows\\SignalCode' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/SignalCode.php',
    'PhabelVendor\\Amp\\Process\\Internal\\Windows\\SocketConnector' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/SocketConnector.php',
    'PhabelVendor\\Amp\\Process\\Process' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/Process.php',
    'PhabelVendor\\Amp\\Process\\ProcessException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessException.php',
    'PhabelVendor\\Amp\\Process\\ProcessInputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessInputStream.php',
    'PhabelVendor\\Amp\\Process\\ProcessOutputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessOutputStream.php',
    'PhabelVendor\\Amp\\Process\\StatusError' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/StatusError.php',
    'PhabelVendor\\Amp\\Producer' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Producer.php',
    'PhabelVendor\\Amp\\Promise' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Promise.php',
    'PhabelVendor\\Amp\\Serialization\\CompressingSerializer' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/serialization/src/CompressingSerializer.php',
    'PhabelVendor\\Amp\\Serialization\\JsonSerializer' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/serialization/src/JsonSerializer.php',
    'PhabelVendor\\Amp\\Serialization\\NativeSerializer' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/serialization/src/NativeSerializer.php',
    'PhabelVendor\\Amp\\Serialization\\PassthroughSerializer' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/serialization/src/PassthroughSerializer.php',
    'PhabelVendor\\Amp\\Serialization\\SerializationException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/serialization/src/SerializationException.php',
    'PhabelVendor\\Amp\\Serialization\\Serializer' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/serialization/src/Serializer.php',
    'PhabelVendor\\Amp\\Struct' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Struct.php',
    'PhabelVendor\\Amp\\Success' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Success.php',
    'PhabelVendor\\Amp\\Sync\\Barrier' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/Barrier.php',
    'PhabelVendor\\Amp\\Sync\\FileMutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/FileMutex.php',
    'PhabelVendor\\Amp\\Sync\\Internal\\MutexStorage' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/Internal/MutexStorage.php',
    'PhabelVendor\\Amp\\Sync\\Internal\\SemaphoreStorage' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/Internal/SemaphoreStorage.php',
    'PhabelVendor\\Amp\\Sync\\KeyedMutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/KeyedMutex.php',
    'PhabelVendor\\Amp\\Sync\\KeyedSemaphore' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/KeyedSemaphore.php',
    'PhabelVendor\\Amp\\Sync\\LocalKeyedMutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/LocalKeyedMutex.php',
    'PhabelVendor\\Amp\\Sync\\LocalKeyedSemaphore' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/LocalKeyedSemaphore.php',
    'PhabelVendor\\Amp\\Sync\\LocalMutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/LocalMutex.php',
    'PhabelVendor\\Amp\\Sync\\LocalSemaphore' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/LocalSemaphore.php',
    'PhabelVendor\\Amp\\Sync\\Lock' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/Lock.php',
    'PhabelVendor\\Amp\\Sync\\Mutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/Mutex.php',
    'PhabelVendor\\Amp\\Sync\\PosixSemaphore' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/PosixSemaphore.php',
    'PhabelVendor\\Amp\\Sync\\PrefixedKeyedMutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/PrefixedKeyedMutex.php',
    'PhabelVendor\\Amp\\Sync\\PrefixedKeyedSemaphore' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/PrefixedKeyedSemaphore.php',
    'PhabelVendor\\Amp\\Sync\\Semaphore' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/Semaphore.php',
    'PhabelVendor\\Amp\\Sync\\SemaphoreMutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/SemaphoreMutex.php',
    'PhabelVendor\\Amp\\Sync\\StaticKeyMutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/StaticKeyMutex.php',
    'PhabelVendor\\Amp\\Sync\\SyncException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/SyncException.php',
    'PhabelVendor\\Amp\\Sync\\ThreadedMutex' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/ThreadedMutex.php',
    'PhabelVendor\\Amp\\Sync\\ThreadedSemaphore' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/ThreadedSemaphore.php',
    'PhabelVendor\\Amp\\TimeoutCancellationToken' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/TimeoutCancellationToken.php',
    'PhabelVendor\\Amp\\TimeoutException' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/TimeoutException.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Node' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Node.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Lexer\\Lexer' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Lexer/Lexer.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\ParserException' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/ParserException.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\TokenIterator' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/TokenIterator.php',
    'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\TypeParser' => $vendorDir . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/TypeParser.php',
    'PhabelVendor\\PhpParser\\Builder' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder.php',
    'PhabelVendor\\PhpParser\\BuilderFactory' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/BuilderFactory.php',
    'PhabelVendor\\PhpParser\\BuilderHelpers' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/BuilderHelpers.php',
    'PhabelVendor\\PhpParser\\Builder\\ClassConst' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/ClassConst.php',
    'PhabelVendor\\PhpParser\\Builder\\Class_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Class_.php',
    'PhabelVendor\\PhpParser\\Builder\\Declaration' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Declaration.php',
    'PhabelVendor\\PhpParser\\Builder\\EnumCase' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/EnumCase.php',
    'PhabelVendor\\PhpParser\\Builder\\Enum_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Enum_.php',
    'PhabelVendor\\PhpParser\\Builder\\FunctionLike' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/FunctionLike.php',
    'PhabelVendor\\PhpParser\\Builder\\Function_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Function_.php',
    'PhabelVendor\\PhpParser\\Builder\\Interface_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Interface_.php',
    'PhabelVendor\\PhpParser\\Builder\\Method' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Method.php',
    'PhabelVendor\\PhpParser\\Builder\\Namespace_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Namespace_.php',
    'PhabelVendor\\PhpParser\\Builder\\Param' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Param.php',
    'PhabelVendor\\PhpParser\\Builder\\Property' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Property.php',
    'PhabelVendor\\PhpParser\\Builder\\TraitUse' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/TraitUse.php',
    'PhabelVendor\\PhpParser\\Builder\\TraitUseAdaptation' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php',
    'PhabelVendor\\PhpParser\\Builder\\Trait_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Trait_.php',
    'PhabelVendor\\PhpParser\\Builder\\Use_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Use_.php',
    'PhabelVendor\\PhpParser\\Comment' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Comment.php',
    'PhabelVendor\\PhpParser\\Comment\\Doc' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Comment/Doc.php',
    'PhabelVendor\\PhpParser\\ConstExprEvaluationException' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ConstExprEvaluationException.php',
    'PhabelVendor\\PhpParser\\ConstExprEvaluator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ConstExprEvaluator.php',
    'PhabelVendor\\PhpParser\\Error' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Error.php',
    'PhabelVendor\\PhpParser\\ErrorHandler' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler.php',
    'PhabelVendor\\PhpParser\\ErrorHandler\\Collecting' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler/Collecting.php',
    'PhabelVendor\\PhpParser\\ErrorHandler\\Throwing' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler/Throwing.php',
    'PhabelVendor\\PhpParser\\Internal\\DiffElem' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/DiffElem.php',
    'PhabelVendor\\PhpParser\\Internal\\Differ' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/Differ.php',
    'PhabelVendor\\PhpParser\\Internal\\PrintableNewAnonClassNode' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php',
    'PhabelVendor\\PhpParser\\Internal\\TokenStream' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/TokenStream.php',
    'PhabelVendor\\PhpParser\\JsonDecoder' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/JsonDecoder.php',
    'PhabelVendor\\PhpParser\\Lexer' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer.php',
    'PhabelVendor\\PhpParser\\Lexer\\Emulative' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/Emulative.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\AwaitTokenEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/AwaitTokenEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\CoaleseEqualTokenEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\EnumTokenEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\ExplicitOctalEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\FlexibleDocStringEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\FnTokenEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\NumericLiteralSeparatorEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\ReadonlyTokenEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php',
    'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php',
    'PhabelVendor\\PhpParser\\NameContext' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NameContext.php',
    'PhabelVendor\\PhpParser\\Node' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node.php',
    'PhabelVendor\\PhpParser\\NodeAbstract' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeAbstract.php',
    'PhabelVendor\\PhpParser\\NodeDumper' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeDumper.php',
    'PhabelVendor\\PhpParser\\NodeFinder' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeFinder.php',
    'PhabelVendor\\PhpParser\\NodeTraverser' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeTraverser.php',
    'PhabelVendor\\PhpParser\\NodeTraverserInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeTraverserInterface.php',
    'PhabelVendor\\PhpParser\\NodeVisitor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor.php',
    'PhabelVendor\\PhpParser\\NodeVisitorAbstract' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitorAbstract.php',
    'PhabelVendor\\PhpParser\\NodeVisitor\\CloningVisitor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php',
    'PhabelVendor\\PhpParser\\NodeVisitor\\FindingVisitor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php',
    'PhabelVendor\\PhpParser\\NodeVisitor\\FirstFindingVisitor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php',
    'PhabelVendor\\PhpParser\\NodeVisitor\\NameResolver' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php',
    'PhabelVendor\\PhpParser\\NodeVisitor\\NodeConnectingVisitor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php',
    'PhabelVendor\\PhpParser\\NodeVisitor\\ParentConnectingVisitor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php',
    'PhabelVendor\\PhpParser\\Node\\Arg' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Arg.php',
    'PhabelVendor\\PhpParser\\Node\\Attribute' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Attribute.php',
    'PhabelVendor\\PhpParser\\Node\\AttributeGroup' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/AttributeGroup.php',
    'PhabelVendor\\PhpParser\\Node\\ComplexType' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/ComplexType.php',
    'PhabelVendor\\PhpParser\\Node\\Const_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Const_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\ArrayDimFetch' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\ArrayItem' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Array_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Array_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\ArrowFunction' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Assign.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignRef.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\CallLike' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/CallLike.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Cast' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Unset_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Clone_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Closure.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\ConstFetch' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Empty_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Error' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Error.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Eval_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Exit_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Exit_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/FuncCall.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Include_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Isset_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\List_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/List_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Match_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Match_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/MethodCall.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/New_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\NullsafeMethodCall' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\NullsafePropertyFetch' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PostDec.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PostInc.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PreDec.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PreInc.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Print_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ShellExec.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/StaticCall.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Ternary.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Throw_.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Variable' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Variable.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\YieldFrom' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php',
    'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Yield_.php',
    'PhabelVendor\\PhpParser\\Node\\FunctionLike' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/FunctionLike.php',
    'PhabelVendor\\PhpParser\\Node\\Identifier' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Identifier.php',
    'PhabelVendor\\PhpParser\\Node\\IntersectionType' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/IntersectionType.php',
    'PhabelVendor\\PhpParser\\Node\\MatchArm' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/MatchArm.php',
    'PhabelVendor\\PhpParser\\Node\\Name' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name.php',
    'PhabelVendor\\PhpParser\\Node\\Name\\FullyQualified' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name/FullyQualified.php',
    'PhabelVendor\\PhpParser\\Node\\Name\\Relative' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name/Relative.php',
    'PhabelVendor\\PhpParser\\Node\\NullableType' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/NullableType.php',
    'PhabelVendor\\PhpParser\\Node\\Param' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Param.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/DNumber.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\EncapsedStringPart' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/LNumber.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php',
    'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/String_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Break_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Break_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Case_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Case_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Catch_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Catch_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\ClassConst' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\ClassLike' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\ClassMethod' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Class_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Class_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Const_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Const_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Continue_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Continue_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\DeclareDeclare' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Declare_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Declare_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Do_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Do_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Echo_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Echo_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\ElseIf_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Else_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Else_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\EnumCase' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Enum_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Enum_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Expression' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Expression.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Finally_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Finally_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\For_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/For_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Foreach_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Function_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Function_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Global_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Global_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Goto_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Goto_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\GroupUse' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\HaltCompiler' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\If_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/If_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\InlineHTML' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Interface_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Interface_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Label' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Label.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Namespace_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Nop' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Nop.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Property' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Property.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\PropertyProperty' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Return_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Return_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\StaticVar' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Static_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Static_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Switch_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Switch_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Throw_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Throw_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\TraitUse' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\TraitUseAdaptation' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Trait_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Trait_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\TryCatch' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Unset_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Unset_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\UseUse' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/UseUse.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\Use_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Use_.php',
    'PhabelVendor\\PhpParser\\Node\\Stmt\\While_' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/While_.php',
    'PhabelVendor\\PhpParser\\Node\\UnionType' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/UnionType.php',
    'PhabelVendor\\PhpParser\\Node\\VarLikeIdentifier' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php',
    'PhabelVendor\\PhpParser\\Node\\VariadicPlaceholder' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php',
    'PhabelVendor\\PhpParser\\Parser' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser.php',
    'PhabelVendor\\PhpParser\\ParserAbstract' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ParserAbstract.php',
    'PhabelVendor\\PhpParser\\ParserFactory' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ParserFactory.php',
    'PhabelVendor\\PhpParser\\Parser\\Multiple' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Multiple.php',
    'PhabelVendor\\PhpParser\\Parser\\Php5' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Php5.php',
    'PhabelVendor\\PhpParser\\Parser\\Php7' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Php7.php',
    'PhabelVendor\\PhpParser\\Parser\\Tokens' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Tokens.php',
    'PhabelVendor\\PhpParser\\PrettyPrinterAbstract' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/PrettyPrinterAbstract.php',
    'PhabelVendor\\PhpParser\\PrettyPrinter\\Standard' => $vendorDir . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/PrettyPrinter/Standard.php',
    'PhabelVendor\\Psr\\Container\\ContainerExceptionInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/container/src/ContainerExceptionInterface.php',
    'PhabelVendor\\Psr\\Container\\ContainerInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/container/src/ContainerInterface.php',
    'PhabelVendor\\Psr\\Container\\NotFoundExceptionInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/container/src/NotFoundExceptionInterface.php',
    'PhabelVendor\\Psr\\Log\\AbstractLogger' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/AbstractLogger.php',
    'PhabelVendor\\Psr\\Log\\InvalidArgumentException' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/InvalidArgumentException.php',
    'PhabelVendor\\Psr\\Log\\LogLevel' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LogLevel.php',
    'PhabelVendor\\Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerAwareInterface.php',
    'PhabelVendor\\Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerAwareTrait.php',
    'PhabelVendor\\Psr\\Log\\LoggerInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerInterface.php',
    'PhabelVendor\\Psr\\Log\\LoggerTrait' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerTrait.php',
    'PhabelVendor\\Psr\\Log\\NullLogger' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/NullLogger.php',
    'PhabelVendor\\Psr\\Log\\Test\\DummyTest' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/DummyTest.php',
    'PhabelVendor\\Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
    'PhabelVendor\\Psr\\Log\\Test\\TestLogger' => $vendorDir . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/TestLogger.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Application' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Application.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Attribute\\AsCommand' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Attribute/AsCommand.php',
    'PhabelVendor\\Symfony\\Component\\Console\\CI\\GithubActionReporter' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/CI/GithubActionReporter.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Color' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Color.php',
    'PhabelVendor\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/CommandLoaderInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/ContainerCommandLoader.php',
    'PhabelVendor\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/FactoryCommandLoader.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Command\\Command' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Command/Command.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Command\\CompleteCommand' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Command/CompleteCommand.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Command/DumpCompletionCommand.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Command\\HelpCommand' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Command/HelpCommand.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Command\\LazyCommand' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Command/LazyCommand.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Command\\ListCommand' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Command/ListCommand.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Command\\LockableTrait' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Command/LockableTrait.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Command/SignalableCommandInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Completion\\CompletionInput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Completion/CompletionInput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Completion/CompletionSuggestions.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Completion/Output/BashCompletionOutput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Completion/Output/CompletionOutputInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Completion\\Suggestion' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Completion/Suggestion.php',
    'PhabelVendor\\Symfony\\Component\\Console\\ConsoleEvents' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/ConsoleEvents.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Cursor' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Cursor.php',
    'PhabelVendor\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/DependencyInjection/AddConsoleCommandPass.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/ApplicationDescription.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/Descriptor.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/DescriptorInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/JsonDescriptor.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/MarkdownDescriptor.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/TextDescriptor.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/XmlDescriptor.php',
    'PhabelVendor\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/EventListener/ErrorListener.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleCommandEvent.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleErrorEvent.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleEvent.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleSignalEvent.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleTerminateEvent.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Exception/CommandNotFoundException.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Exception/ExceptionInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Exception/InvalidArgumentException.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Exception/InvalidOptionException.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Exception\\LogicException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Exception/LogicException.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Exception\\MissingInputException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Exception/MissingInputException.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Exception/NamespaceNotFoundException.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Exception\\RuntimeException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Exception/RuntimeException.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/NullOutputFormatter.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/NullOutputFormatterStyle.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatter.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyle.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyleInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyleStack.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/WrappableOutputFormatterInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/DebugFormatterHelper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/DescriptorHelper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\Dumper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/Dumper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/FormatterHelper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\Helper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/Helper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\HelperInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/HelperInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\HelperSet' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/HelperSet.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/InputAwareHelper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/ProcessHelper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\ProgressBar' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/ProgressBar.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/ProgressIndicator.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/QuestionHelper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/SymfonyQuestionHelper.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\Table' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/Table.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableCell' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableCell.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableCellStyle' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableCellStyle.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableRows' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableRows.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableSeparator' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableSeparator.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableStyle' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableStyle.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\ArgvInput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/ArgvInput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\ArrayInput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/ArrayInput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\Input' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/Input.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputArgument' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputArgument.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputAwareInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputDefinition' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputDefinition.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputOption' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputOption.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/StreamableInputInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Input\\StringInput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Input/StringInput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Logger/ConsoleLogger.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\BufferedOutput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/BufferedOutput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleOutput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleOutputInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleSectionOutput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\NullOutput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/NullOutput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\Output' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/Output.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\OutputInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/OutputInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\StreamOutput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/StreamOutput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Output/TrimmedBufferOutput.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Question/ChoiceQuestion.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Question/ConfirmationQuestion.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Question\\Question' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Question/Question.php',
    'PhabelVendor\\Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/SignalRegistry/SignalRegistry.php',
    'PhabelVendor\\Symfony\\Component\\Console\\SingleCommandApplication' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/SingleCommandApplication.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Style\\OutputStyle' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Style/OutputStyle.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Style\\StyleInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Style/StyleInterface.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Style/SymfonyStyle.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Terminal' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Terminal.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Tester/ApplicationTester.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Tester/CommandCompletionTester.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Tester\\CommandTester' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Tester/CommandTester.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Tester/Constraint/CommandIsSuccessful.php',
    'PhabelVendor\\Symfony\\Component\\Console\\Tester\\TesterTrait' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/console/Tester/TesterTrait.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Exception\\ExceptionInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Exception/ExceptionInterface.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Exception/InvalidArgumentException.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Exception\\LogicException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Exception/LogicException.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Exception\\ProcessFailedException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessFailedException.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessSignaledException.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessTimedOutException.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Exception\\RuntimeException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Exception/RuntimeException.php',
    'PhabelVendor\\Symfony\\Component\\Process\\ExecutableFinder' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/ExecutableFinder.php',
    'PhabelVendor\\Symfony\\Component\\Process\\InputStream' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/InputStream.php',
    'PhabelVendor\\Symfony\\Component\\Process\\PhpExecutableFinder' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/PhpExecutableFinder.php',
    'PhabelVendor\\Symfony\\Component\\Process\\PhpProcess' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/PhpProcess.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Pipes\\AbstractPipes' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Pipes/AbstractPipes.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Pipes\\PipesInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Pipes/PipesInterface.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Pipes\\UnixPipes' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Pipes/UnixPipes.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Pipes\\WindowsPipes' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Pipes/WindowsPipes.php',
    'PhabelVendor\\Symfony\\Component\\Process\\Process' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/Process.php',
    'PhabelVendor\\Symfony\\Component\\Process\\ProcessUtils' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/process/ProcessUtils.php',
    'PhabelVendor\\Symfony\\Component\\String\\AbstractString' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/AbstractString.php',
    'PhabelVendor\\Symfony\\Component\\String\\AbstractUnicodeString' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/AbstractUnicodeString.php',
    'PhabelVendor\\Symfony\\Component\\String\\ByteString' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/ByteString.php',
    'PhabelVendor\\Symfony\\Component\\String\\CodePointString' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/CodePointString.php',
    'PhabelVendor\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Exception/ExceptionInterface.php',
    'PhabelVendor\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Exception/InvalidArgumentException.php',
    'PhabelVendor\\Symfony\\Component\\String\\Exception\\RuntimeException' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Exception/RuntimeException.php',
    'PhabelVendor\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Inflector/EnglishInflector.php',
    'PhabelVendor\\Symfony\\Component\\String\\Inflector\\FrenchInflector' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Inflector/FrenchInflector.php',
    'PhabelVendor\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Inflector/InflectorInterface.php',
    'PhabelVendor\\Symfony\\Component\\String\\LazyString' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/LazyString.php',
    'PhabelVendor\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Slugger/AsciiSlugger.php',
    'PhabelVendor\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Slugger/SluggerInterface.php',
    'PhabelVendor\\Symfony\\Component\\String\\UnicodeString' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/UnicodeString.php',
    'PhabelVendor\\Symfony\\Contracts\\Service\\Attribute\\Required' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts/Attribute/Required.php',
    'PhabelVendor\\Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts/Attribute/SubscribedService.php',
    'PhabelVendor\\Symfony\\Contracts\\Service\\ResetInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ResetInterface.php',
    'PhabelVendor\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceLocatorTrait.php',
    'PhabelVendor\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceProviderInterface.php',
    'PhabelVendor\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceSubscriberInterface.php',
    'PhabelVendor\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceSubscriberTrait.php',
    'PhabelVendor\\Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/service-contracts/Test/ServiceLocatorTest.php',
    'Phabel\\ClassStorage' => $vendorDir . '/phabel/phabel/src/ClassStorage.php',
    'Phabel\\ClassStorageProvider' => $vendorDir . '/phabel/phabel/src/ClassStorageProvider.php',
    'Phabel\\ClassStorage\\Builder' => $vendorDir . '/phabel/phabel/src/ClassStorage/Builder.php',
    'Phabel\\ClassStorage\\FunctionStorage' => $vendorDir . '/phabel/phabel/src/ClassStorage/FunctionStorage.php',
    'Phabel\\ClassStorage\\Storage' => $vendorDir . '/phabel/phabel/src/ClassStorage/Storage.php',
    'Phabel\\Cli\\EventHandler' => $vendorDir . '/phabel/phabel/src/Cli/EventHandler.php',
    'Phabel\\Cli\\Formatter' => $vendorDir . '/phabel/phabel/src/Cli/Formatter.php',
    'Phabel\\Cli\\SimpleConsoleLogger' => $vendorDir . '/phabel/phabel/src/Cli/SimpleConsoleLogger.php',
    'Phabel\\Commands\\BaseCommand' => $vendorDir . '/phabel/phabel/src/Commands/BaseCommand.php',
    'Phabel\\Commands\\Publish' => $vendorDir . '/phabel/phabel/src/Commands/Publish.php',
    'Phabel\\Commands\\Run' => $vendorDir . '/phabel/phabel/src/Commands/Run.php',
    'Phabel\\Composer\\EventHandler' => $vendorDir . '/phabel/phabel/src/Composer/EventHandler.php',
    'Phabel\\Composer\\Plugin' => $vendorDir . '/phabel/phabel/src/Composer/Plugin.php',
    'Phabel\\Composer\\Repository' => $vendorDir . '/phabel/phabel/src/Composer/Repository.php',
    'Phabel\\Composer\\Transformer' => $vendorDir . '/phabel/phabel/src/Composer/Transformer.php',
    'Phabel\\Context' => $vendorDir . '/phabel/phabel/src/Context.php',
    'Phabel\\EventHandler' => $vendorDir . '/phabel/phabel/src/EventHandler.php',
    'Phabel\\EventHandlerInterface' => $vendorDir . '/phabel/phabel/src/EventHandlerInterface.php',
    'Phabel\\Exception' => $vendorDir . '/phabel/phabel/src/Exception.php',
    'Phabel\\ExceptionWrapper' => $vendorDir . '/phabel/phabel/src/ExceptionWrapper.php',
    'Phabel\\PhpDocParser' => $vendorDir . '/phabel/phabel/src/PhpDocParser.php',
    'Phabel\\Plugin' => $vendorDir . '/phabel/phabel/src/Plugin.php',
    'Phabel\\PluginCache' => $vendorDir . '/phabel/phabel/src/PluginCache.php',
    'Phabel\\PluginGraph\\CircularException' => $vendorDir . '/phabel/phabel/src/PluginGraph/CircularException.php',
    'Phabel\\PluginGraph\\Graph' => $vendorDir . '/phabel/phabel/src/PluginGraph/Graph.php',
    'Phabel\\PluginGraph\\GraphInternal' => $vendorDir . '/phabel/phabel/src/PluginGraph/GraphInternal.php',
    'Phabel\\PluginGraph\\Node' => $vendorDir . '/phabel/phabel/src/PluginGraph/Node.php',
    'Phabel\\PluginGraph\\PackageContext' => $vendorDir . '/phabel/phabel/src/PluginGraph/PackageContext.php',
    'Phabel\\PluginGraph\\Plugins' => $vendorDir . '/phabel/phabel/src/PluginGraph/Plugins.php',
    'Phabel\\PluginGraph\\ResolvedGraph' => $vendorDir . '/phabel/phabel/src/PluginGraph/ResolvedGraph.php',
    'Phabel\\PluginInterface' => $vendorDir . '/phabel/phabel/src/PluginInterface.php',
    'Phabel\\Plugin\\ClassStoragePlugin' => $vendorDir . '/phabel/phabel/src/Plugin/ClassStoragePlugin.php',
    'Phabel\\Plugin\\ComposerSanitizer' => $vendorDir . '/phabel/phabel/src/Plugin/ComposerSanitizer.php',
    'Phabel\\Plugin\\GeneratorDetector' => $vendorDir . '/phabel/phabel/src/Plugin/GeneratorDetector.php',
    'Phabel\\Plugin\\IssetExpressionFixer' => $vendorDir . '/phabel/phabel/src/Plugin/IssetExpressionFixer.php',
    'Phabel\\Plugin\\ListSplitter' => $vendorDir . '/phabel/phabel/src/Plugin/ListSplitter.php',
    'Phabel\\Plugin\\Memoization' => $vendorDir . '/phabel/phabel/src/Plugin/Memoization.php',
    'Phabel\\Plugin\\NestedExpressionFixer' => $vendorDir . '/phabel/phabel/src/Plugin/NestedExpressionFixer.php',
    'Phabel\\Plugin\\NewFixer' => $vendorDir . '/phabel/phabel/src/Plugin/NewFixer.php',
    'Phabel\\Plugin\\PhabelTestGenerator' => $vendorDir . '/phabel/phabel/src/Plugin/PhabelTestGenerator.php',
    'Phabel\\Plugin\\ReGenerator' => $vendorDir . '/phabel/phabel/src/Plugin/ReGenerator.php',
    'Phabel\\Plugin\\ReGeneratorInternal' => $vendorDir . '/phabel/phabel/src/Plugin/ReGeneratorInternal.php',
    'Phabel\\Plugin\\ReGenerator\\ReGenerator' => $vendorDir . '/phabel/phabel/src/Plugin/ReGenerator/ReGenerator.php',
    'Phabel\\Plugin\\StmtExprWrapper' => $vendorDir . '/phabel/phabel/src/Plugin/StmtExprWrapper.php',
    'Phabel\\Plugin\\StringConcatOptimizer' => $vendorDir . '/phabel/phabel/src/Plugin/StringConcatOptimizer.php',
    'Phabel\\Plugin\\TypeHintReplacer' => $vendorDir . '/phabel/phabel/src/Plugin/TypeHintReplacer.php',
    'Phabel\\Plugin\\VariableFinder' => $vendorDir . '/phabel/phabel/src/Plugin/VariableFinder.php',
    'Phabel\\Plugin\\YieldDetector' => $vendorDir . '/phabel/phabel/src/Plugin/YieldDetector.php',
    'Phabel\\RootNode' => $vendorDir . '/phabel/phabel/src/RootNode.php',
    'Phabel\\Target\\Php' => $vendorDir . '/phabel/phabel/src/Target/Php.php',
    'Phabel\\Target\\Php56\\IssetExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php56/IssetExpressionFixer.php',
    'Phabel\\Target\\Php56\\NestedExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php56/NestedExpressionFixer.php',
    'Phabel\\Target\\Php70\\AnonymousClassReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php70/AnonymousClassReplacer.php',
    'Phabel\\Target\\Php70\\AnonymousClass\\AnonymousClassInterface' => $vendorDir . '/phabel/phabel/src/Target/Php70/AnonymousClass/AnonymousClassInterface.php',
    'Phabel\\Target\\Php70\\DefineArrayReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php70/DefineArrayReplacer.php',
    'Phabel\\Target\\Php70\\GroupUseReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php70/GroupUseReplacer.php',
    'Phabel\\Target\\Php70\\IssetExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php70/IssetExpressionFixer.php',
    'Phabel\\Target\\Php70\\NestedExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php70/NestedExpressionFixer.php',
    'Phabel\\Target\\Php70\\NullCoalesceReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php70/NullCoalesceReplacer.php',
    'Phabel\\Target\\Php70\\NullCoalesce\\DisallowedExpressions' => $vendorDir . '/phabel/phabel/src/Target/Php70/NullCoalesce/DisallowedExpressions.php',
    'Phabel\\Target\\Php70\\Polyfill' => $vendorDir . '/phabel/phabel/src/Target/Php70/Polyfill.php',
    'Phabel\\Target\\Php70\\ReservedNameReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php70/ReservedNameReplacer.php',
    'Phabel\\Target\\Php70\\ReturnTypeHints' => $vendorDir . '/phabel/phabel/src/Target/Php70/ReturnTypeHints.php',
    'Phabel\\Target\\Php70\\ScalarTypeHints' => $vendorDir . '/phabel/phabel/src/Target/Php70/ScalarTypeHints.php',
    'Phabel\\Target\\Php70\\SpaceshipOperatorReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php70/SpaceshipOperatorReplacer.php',
    'Phabel\\Target\\Php70\\StrictTypesDeclareStatementRemover' => $vendorDir . '/phabel/phabel/src/Target/Php70/StrictTypesDeclareStatementRemover.php',
    'Phabel\\Target\\Php70\\ThrowableReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php70/ThrowableReplacer.php',
    'Phabel\\Target\\Php71\\ArrayList' => $vendorDir . '/phabel/phabel/src/Target/Php71/ArrayList.php',
    'Phabel\\Target\\Php71\\ClassConstantVisibilityModifiersRemover' => $vendorDir . '/phabel/phabel/src/Target/Php71/ClassConstantVisibilityModifiersRemover.php',
    'Phabel\\Target\\Php71\\ClosureFromCallable' => $vendorDir . '/phabel/phabel/src/Target/Php71/ClosureFromCallable.php',
    'Phabel\\Target\\Php71\\IssetExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php71/IssetExpressionFixer.php',
    'Phabel\\Target\\Php71\\IterableHint' => $vendorDir . '/phabel/phabel/src/Target/Php71/IterableHint.php',
    'Phabel\\Target\\Php71\\ListExpression' => $vendorDir . '/phabel/phabel/src/Target/Php71/ListExpression.php',
    'Phabel\\Target\\Php71\\ListKey' => $vendorDir . '/phabel/phabel/src/Target/Php71/ListKey.php',
    'Phabel\\Target\\Php71\\MultipleCatchReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php71/MultipleCatchReplacer.php',
    'Phabel\\Target\\Php71\\NestedExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php71/NestedExpressionFixer.php',
    'Phabel\\Target\\Php71\\NullableType' => $vendorDir . '/phabel/phabel/src/Target/Php71/NullableType.php',
    'Phabel\\Target\\Php71\\Polyfill' => $vendorDir . '/phabel/phabel/src/Target/Php71/Polyfill.php',
    'Phabel\\Target\\Php71\\VoidReturnType' => $vendorDir . '/phabel/phabel/src/Target/Php71/VoidReturnType.php',
    'Phabel\\Target\\Php72\\IssetExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php72/IssetExpressionFixer.php',
    'Phabel\\Target\\Php72\\NestedExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php72/NestedExpressionFixer.php',
    'Phabel\\Target\\Php72\\ObjectTypeHintReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php72/ObjectTypeHintReplacer.php',
    'Phabel\\Target\\Php72\\Polyfill' => $vendorDir . '/phabel/phabel/src/Target/Php72/Polyfill.php',
    'Phabel\\Target\\Php72\\TypeContravariance' => $vendorDir . '/phabel/phabel/src/Target/Php72/TypeContravariance.php',
    'Phabel\\Target\\Php72\\TypeContravariance\\TypeContravariance' => $vendorDir . '/phabel/phabel/src/Target/Php72/TypeContravariance/TypeContravariance.php',
    'Phabel\\Target\\Php73\\IssetExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php73/IssetExpressionFixer.php',
    'Phabel\\Target\\Php73\\ListReference' => $vendorDir . '/phabel/phabel/src/Target/Php73/ListReference.php',
    'Phabel\\Target\\Php73\\NestedExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php73/NestedExpressionFixer.php',
    'Phabel\\Target\\Php73\\Polyfill' => $vendorDir . '/phabel/phabel/src/Target/Php73/Polyfill.php',
    'Phabel\\Target\\Php74\\ArrayUnpack' => $vendorDir . '/phabel/phabel/src/Target/Php74/ArrayUnpack.php',
    'Phabel\\Target\\Php74\\ArrowClosure' => $vendorDir . '/phabel/phabel/src/Target/Php74/ArrowClosure.php',
    'Phabel\\Target\\Php74\\IssetExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php74/IssetExpressionFixer.php',
    'Phabel\\Target\\Php74\\NestedExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php74/NestedExpressionFixer.php',
    'Phabel\\Target\\Php74\\NullCoalesceAssignment' => $vendorDir . '/phabel/phabel/src/Target/Php74/NullCoalesceAssignment.php',
    'Phabel\\Target\\Php74\\Polyfill' => $vendorDir . '/phabel/phabel/src/Target/Php74/Polyfill.php',
    'Phabel\\Target\\Php74\\Serializable' => $vendorDir . '/phabel/phabel/src/Target/Php74/Serializable.php',
    'Phabel\\Target\\Php74\\TypeContracovariance' => $vendorDir . '/phabel/phabel/src/Target/Php74/TypeContracovariance.php',
    'Phabel\\Target\\Php74\\TypeContracovariance\\TypeContracovariance' => $vendorDir . '/phabel/phabel/src/Target/Php74/TypeContracovariance/TypeContracovariance.php',
    'Phabel\\Target\\Php74\\TypedProperty' => $vendorDir . '/phabel/phabel/src/Target/Php74/TypedProperty.php',
    'Phabel\\Target\\Php80\\CatchEmpty' => $vendorDir . '/phabel/phabel/src/Target/Php80/CatchEmpty.php',
    'Phabel\\Target\\Php80\\ClassName' => $vendorDir . '/phabel/phabel/src/Target/Php80/ClassName.php',
    'Phabel\\Target\\Php80\\ConstructorPromotion' => $vendorDir . '/phabel/phabel/src/Target/Php80/ConstructorPromotion.php',
    'Phabel\\Target\\Php80\\IssetExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php80/IssetExpressionFixer.php',
    'Phabel\\Target\\Php80\\MatchTransformer' => $vendorDir . '/phabel/phabel/src/Target/Php80/MatchTransformer.php',
    'Phabel\\Target\\Php80\\NestedExpressionFixer' => $vendorDir . '/phabel/phabel/src/Target/Php80/NestedExpressionFixer.php',
    'Phabel\\Target\\Php80\\NullSafeTransformer' => $vendorDir . '/phabel/phabel/src/Target/Php80/NullSafeTransformer.php',
    'Phabel\\Target\\Php80\\NullSafe\\NullSafe' => $vendorDir . '/phabel/phabel/src/Target/Php80/NullSafe/NullSafe.php',
    'Phabel\\Target\\Php80\\Polyfill' => $vendorDir . '/phabel/phabel/src/Target/Php80/Polyfill.php',
    'Phabel\\Target\\Php80\\StaticMixedFalseReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php80/StaticMixedFalseReplacer.php',
    'Phabel\\Target\\Php80\\ThrowExprReplacer' => $vendorDir . '/phabel/phabel/src/Target/Php80/ThrowExprReplacer.php',
    'Phabel\\Target\\Php80\\UnionTypeStripper' => $vendorDir . '/phabel/phabel/src/Target/Php80/UnionTypeStripper.php',
    'Phabel\\Target\\Polyfill' => $vendorDir . '/phabel/phabel/src/Target/Polyfill.php',
    'Phabel\\Tasks\\Init' => $vendorDir . '/phabel/phabel/src/Tasks/Init.php',
    'Phabel\\Tasks\\Run' => $vendorDir . '/phabel/phabel/src/Tasks/Run.php',
    'Phabel\\Tasks\\Shutdown' => $vendorDir . '/phabel/phabel/src/Tasks/Shutdown.php',
    'Phabel\\Tools' => $vendorDir . '/phabel/phabel/src/Tools.php',
    'Phabel\\Traverser' => $vendorDir . '/phabel/phabel/src/Traverser.php',
    'Phabel\\UnresolvedNameException' => $vendorDir . '/phabel/phabel/src/UnresolvedNameException.php',
    'Phabel\\VariableContext' => $vendorDir . '/phabel/phabel/src/VariableContext.php',
    'Phabel\\Version' => $vendorDir . '/phabel/phabel/src/Version.php',
    'Psr\\Http\\Message\\MessageInterface' => $vendorDir . '/phabel-transpiler74.psr/http-message/src/MessageInterface.php',
    'Psr\\Http\\Message\\RequestFactoryInterface' => $vendorDir . '/phabel-transpiler74.psr/http-factory/src/RequestFactoryInterface.php',
    'Psr\\Http\\Message\\RequestInterface' => $vendorDir . '/phabel-transpiler74.psr/http-message/src/RequestInterface.php',
    'Psr\\Http\\Message\\ResponseFactoryInterface' => $vendorDir . '/phabel-transpiler74.psr/http-factory/src/ResponseFactoryInterface.php',
    'Psr\\Http\\Message\\ResponseInterface' => $vendorDir . '/phabel-transpiler74.psr/http-message/src/ResponseInterface.php',
    'Psr\\Http\\Message\\ServerRequestFactoryInterface' => $vendorDir . '/phabel-transpiler74.psr/http-factory/src/ServerRequestFactoryInterface.php',
    'Psr\\Http\\Message\\ServerRequestInterface' => $vendorDir . '/phabel-transpiler74.psr/http-message/src/ServerRequestInterface.php',
    'Psr\\Http\\Message\\StreamFactoryInterface' => $vendorDir . '/phabel-transpiler74.psr/http-factory/src/StreamFactoryInterface.php',
    'Psr\\Http\\Message\\StreamInterface' => $vendorDir . '/phabel-transpiler74.psr/http-message/src/StreamInterface.php',
    'Psr\\Http\\Message\\UploadedFileFactoryInterface' => $vendorDir . '/phabel-transpiler74.psr/http-factory/src/UploadedFileFactoryInterface.php',
    'Psr\\Http\\Message\\UploadedFileInterface' => $vendorDir . '/phabel-transpiler74.psr/http-message/src/UploadedFileInterface.php',
    'Psr\\Http\\Message\\UriFactoryInterface' => $vendorDir . '/phabel-transpiler74.psr/http-factory/src/UriFactoryInterface.php',
    'Psr\\Http\\Message\\UriInterface' => $vendorDir . '/phabel-transpiler74.psr/http-message/src/UriInterface.php',
    'Psr\\Log\\AbstractLogger' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/AbstractLogger.php',
    'Psr\\Log\\InvalidArgumentException' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/InvalidArgumentException.php',
    'Psr\\Log\\LogLevel' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/LogLevel.php',
    'Psr\\Log\\LoggerAwareInterface' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/LoggerAwareInterface.php',
    'Psr\\Log\\LoggerAwareTrait' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/LoggerAwareTrait.php',
    'Psr\\Log\\LoggerInterface' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/LoggerInterface.php',
    'Psr\\Log\\LoggerTrait' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/LoggerTrait.php',
    'Psr\\Log\\NullLogger' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/NullLogger.php',
    'Psr\\Log\\Test\\DummyTest' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/Test/DummyTest.php',
    'Psr\\Log\\Test\\LoggerInterfaceTest' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
    'Psr\\Log\\Test\\TestLogger' => $vendorDir . '/phabel-transpiler74.psr/log/Psr/Log/Test/TestLogger.php',
    'Stringable' => $vendorDir . '/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/Stringable.php',
    'Symfony\\Polyfill\\Ctype\\Ctype' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/Ctype.php',
    'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/Grapheme.php',
    'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Normalizer.php',
    'Symfony\\Polyfill\\Mbstring\\Mbstring' => $vendorDir . '/phabel-transpiler74.symfony/polyfill-mbstring/Mbstring.php',
    'Symfony\\Polyfill\\Php73\\Php73' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-php73/Php73.php',
    'Symfony\\Polyfill\\Php80\\Php80' => $vendorDir . '/phabel-transpiler74.symfony/polyfill-php80/Php80.php',
    'UnhandledMatchError' => $vendorDir . '/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
    'ValueError' => $vendorDir . '/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/ValueError.php',
    'cash\\LRUCache' => $vendorDir . '/phabel-transpiler74.cash/lrucache/src/cash/LRUCache.php',
    'danog\\Decoder\\FileId' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/FileId.php',
    'danog\\Decoder\\PhotoSizeSource' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource.php',
    'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceDialogPhoto' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceDialogPhoto.php',
    'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceLegacy' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceLegacy.php',
    'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceStickersetThumbnail' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceStickersetThumbnail.php',
    'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceStickersetThumbnailVersion' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceStickersetThumbnailVersion.php',
    'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceThumbnail' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceThumbnail.php',
    'danog\\Decoder\\UniqueFileId' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/UniqueFileId.php',
    'danog\\LibDNSJson\\JsonDecoder' => $vendorDir . '/phabel-transpiler74.danog/libdns-json/lib/JsonDecoder.php',
    'danog\\LibDNSJson\\JsonDecoderFactory' => $vendorDir . '/phabel-transpiler74.danog/libdns-json/lib/JsonDecoderFactory.php',
    'danog\\LibDNSJson\\QueryEncoder' => $vendorDir . '/phabel-transpiler74.danog/libdns-json/lib/QueryEncoder.php',
    'danog\\LibDNSJson\\QueryEncoderFactory' => $vendorDir . '/phabel-transpiler74.danog/libdns-json/lib/QueryEncoderFactory.php',
    'danog\\Loop\\Generic\\GenericLoop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Generic/GenericLoop.php',
    'danog\\Loop\\Generic\\PeriodicLoop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Generic/PeriodicLoop.php',
    'danog\\Loop\\Interfaces\\LoopInterface' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Interfaces/LoopInterface.php',
    'danog\\Loop\\Interfaces\\ResumableLoopInterface' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Interfaces/ResumableLoopInterface.php',
    'danog\\Loop\\Interfaces\\SignalLoopInterface' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Interfaces/SignalLoopInterface.php',
    'danog\\Loop\\Loop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Loop.php',
    'danog\\Loop\\ResumableLoop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/ResumableLoop.php',
    'danog\\Loop\\ResumableSignalLoop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/ResumableSignalLoop.php',
    'danog\\Loop\\SignalLoop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/SignalLoop.php',
    'danog\\Loop\\Traits\\Loop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Traits/Loop.php',
    'danog\\Loop\\Traits\\ResumableLoop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Traits/ResumableLoop.php',
    'danog\\Loop\\Traits\\SignalLoop' => $vendorDir . '/phabel-transpiler74.danog/loop/lib/Traits/SignalLoop.php',
    'danog\\MadelineProto\\API' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/API.php',
    'danog\\MadelineProto\\APIFactory' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/APIFactory.php',
    'danog\\MadelineProto\\APIWrapper' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/APIWrapper.php',
    'danog\\MadelineProto\\AbstractAPIFactory' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/AbstractAPIFactory.php',
    'danog\\MadelineProto\\AnnotationsBuilder' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/AnnotationsBuilder.php',
    'danog\\MadelineProto\\ApiWrappers\\Start' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/ApiWrappers/Start.php',
    'danog\\MadelineProto\\ApiWrappers\\Templates' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/ApiWrappers/Templates.php',
    'danog\\MadelineProto\\Async\\AsyncConstruct' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Async/AsyncConstruct.php',
    'danog\\MadelineProto\\Bug74586Exception' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Bug74586Exception.php',
    'danog\\MadelineProto\\Connection' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Connection.php',
    'danog\\MadelineProto\\ContextConnector' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/ContextConnector.php',
    'danog\\MadelineProto\\Conversion' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Conversion.php',
    'danog\\MadelineProto\\Coroutine' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Coroutine.php',
    'danog\\MadelineProto\\DataCenter' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/DataCenter.php',
    'danog\\MadelineProto\\DataCenterConnection' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/DataCenterConnection.php',
    'danog\\MadelineProto\\Db\\ArrayCacheTrait' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/ArrayCacheTrait.php',
    'danog\\MadelineProto\\Db\\DbArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/DbArray.php',
    'danog\\MadelineProto\\Db\\DbPropertiesFactory' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/DbPropertiesFactory.php',
    'danog\\MadelineProto\\Db\\DbPropertiesTrait' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/DbPropertiesTrait.php',
    'danog\\MadelineProto\\Db\\DbType' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/DbType.php',
    'danog\\MadelineProto\\Db\\DriverArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/DriverArray.php',
    'danog\\MadelineProto\\Db\\Driver\\Mysql' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Mysql.php',
    'danog\\MadelineProto\\Db\\Driver\\Postgres' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Postgres.php',
    'danog\\MadelineProto\\Db\\Driver\\Redis' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Redis.php',
    'danog\\MadelineProto\\Db\\MemoryArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/MemoryArray.php',
    'danog\\MadelineProto\\Db\\MysqlArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/MysqlArray.php',
    'danog\\MadelineProto\\Db\\NullCache\\MysqlArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/MysqlArray.php',
    'danog\\MadelineProto\\Db\\NullCache\\NullCacheTrait' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/NullCacheTrait.php',
    'danog\\MadelineProto\\Db\\NullCache\\PostgresArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/PostgresArray.php',
    'danog\\MadelineProto\\Db\\NullCache\\RedisArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/RedisArray.php',
    'danog\\MadelineProto\\Db\\PostgresArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/PostgresArray.php',
    'danog\\MadelineProto\\Db\\RedisArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/RedisArray.php',
    'danog\\MadelineProto\\Db\\SqlArray' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Db/SqlArray.php',
    'danog\\MadelineProto\\DoHConnector' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/DoHConnector.php',
    'danog\\MadelineProto\\DocsBuilder' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/DocsBuilder.php',
    'danog\\MadelineProto\\DocsBuilder\\Constructors' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/DocsBuilder/Constructors.php',
    'danog\\MadelineProto\\DocsBuilder\\Methods' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/DocsBuilder/Methods.php',
    'danog\\MadelineProto\\EventHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/EventHandler.php',
    'danog\\MadelineProto\\Exception' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Exception.php',
    'danog\\MadelineProto\\FileCallback' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/FileCallback.php',
    'danog\\MadelineProto\\FileCallbackInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/FileCallbackInterface.php',
    'danog\\MadelineProto\\Files\\Server' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Files/Server.php',
    'danog\\MadelineProto\\GarbageCollector' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/GarbageCollector.php',
    'danog\\MadelineProto\\InternalDoc' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/InternalDoc.php',
    'danog\\MadelineProto\\Ipc\\Client' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Client.php',
    'danog\\MadelineProto\\Ipc\\ClientAbstract' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/ClientAbstract.php',
    'danog\\MadelineProto\\Ipc\\ExitFailure' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/ExitFailure.php',
    'danog\\MadelineProto\\Ipc\\IpcState' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/IpcState.php',
    'danog\\MadelineProto\\Ipc\\Runner\\ProcessRunner' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/ProcessRunner.php',
    'danog\\MadelineProto\\Ipc\\Runner\\RunnerAbstract' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/RunnerAbstract.php',
    'danog\\MadelineProto\\Ipc\\Runner\\WebRunner' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/WebRunner.php',
    'danog\\MadelineProto\\Ipc\\Server' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Server.php',
    'danog\\MadelineProto\\Ipc\\ServerCallback' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/ServerCallback.php',
    'danog\\MadelineProto\\Ipc\\Wrapper' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper.php',
    'danog\\MadelineProto\\Ipc\\Wrapper\\FileCallback' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/FileCallback.php',
    'danog\\MadelineProto\\Ipc\\Wrapper\\InputStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/InputStream.php',
    'danog\\MadelineProto\\Ipc\\Wrapper\\Obj' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/Obj.php',
    'danog\\MadelineProto\\Ipc\\Wrapper\\OutputStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/OutputStream.php',
    'danog\\MadelineProto\\Ipc\\Wrapper\\SeekableInputStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableInputStream.php',
    'danog\\MadelineProto\\Ipc\\Wrapper\\SeekableOutputStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableOutputStream.php',
    'danog\\MadelineProto\\Ipc\\Wrapper\\SeekableTrait' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableTrait.php',
    'danog\\MadelineProto\\Ipc\\Wrapper\\WrapMethodTrait' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/WrapMethodTrait.php',
    'danog\\MadelineProto\\Lang' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Lang.php',
    'danog\\MadelineProto\\LightState' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/LightState.php',
    'danog\\MadelineProto\\Logger' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Logger.php',
    'danog\\MadelineProto\\Loop\\APILoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/APILoop.php',
    'danog\\MadelineProto\\Loop\\Connection\\CheckLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/CheckLoop.php',
    'danog\\MadelineProto\\Loop\\Connection\\CleanupLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/CleanupLoop.php',
    'danog\\MadelineProto\\Loop\\Connection\\Common' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/Common.php',
    'danog\\MadelineProto\\Loop\\Connection\\HttpWaitLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/HttpWaitLoop.php',
    'danog\\MadelineProto\\Loop\\Connection\\PingLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/PingLoop.php',
    'danog\\MadelineProto\\Loop\\Connection\\ReadLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/ReadLoop.php',
    'danog\\MadelineProto\\Loop\\Connection\\WriteLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/WriteLoop.php',
    'danog\\MadelineProto\\Loop\\Generic\\GenericLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/GenericLoop.php',
    'danog\\MadelineProto\\Loop\\Generic\\PeriodicLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/PeriodicLoop.php',
    'danog\\MadelineProto\\Loop\\Generic\\PeriodicLoopInternal' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/PeriodicLoopInternal.php',
    'danog\\MadelineProto\\Loop\\InternalLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/InternalLoop.php',
    'danog\\MadelineProto\\Loop\\LoggerLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/LoggerLoop.php',
    'danog\\MadelineProto\\Loop\\Update\\FeedLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Update/FeedLoop.php',
    'danog\\MadelineProto\\Loop\\Update\\SecretFeedLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Update/SecretFeedLoop.php',
    'danog\\MadelineProto\\Loop\\Update\\SeqLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Update/SeqLoop.php',
    'danog\\MadelineProto\\Loop\\Update\\UpdateLoop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Loop/Update/UpdateLoop.php',
    'danog\\MadelineProto\\Lua' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Lua.php',
    'danog\\MadelineProto\\MTProto' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProto.php',
    'danog\\MadelineProto\\MTProtoSession\\AckHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/AckHandler.php',
    'danog\\MadelineProto\\MTProtoSession\\CallHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/CallHandler.php',
    'danog\\MadelineProto\\MTProtoSession\\MsgIdHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/MsgIdHandler.php',
    'danog\\MadelineProto\\MTProtoSession\\MsgIdHandler\\MsgIdHandler64' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/MsgIdHandler/MsgIdHandler64.php',
    'danog\\MadelineProto\\MTProtoSession\\Reliable' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/Reliable.php',
    'danog\\MadelineProto\\MTProtoSession\\ResponseHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/ResponseHandler.php',
    'danog\\MadelineProto\\MTProtoSession\\SeqNoHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/SeqNoHandler.php',
    'danog\\MadelineProto\\MTProtoSession\\Session' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/Session.php',
    'danog\\MadelineProto\\MTProtoTools\\AuthKeyHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php',
    'danog\\MadelineProto\\MTProtoTools\\CallHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/CallHandler.php',
    'danog\\MadelineProto\\MTProtoTools\\CombinedUpdatesState' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/CombinedUpdatesState.php',
    'danog\\MadelineProto\\MTProtoTools\\Crypt' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt.php',
    'danog\\MadelineProto\\MTProtoTools\\Crypt\\IGE' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGE.php',
    'danog\\MadelineProto\\MTProtoTools\\Crypt\\IGEOpenssl' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGEOpenssl.php',
    'danog\\MadelineProto\\MTProtoTools\\Crypt\\IGEPhpseclib' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGEPhpseclib.php',
    'danog\\MadelineProto\\MTProtoTools\\Files' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Files.php',
    'danog\\MadelineProto\\MTProtoTools\\FilesLogic' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/FilesLogic.php',
    'danog\\MadelineProto\\MTProtoTools\\MinDatabase' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/MinDatabase.php',
    'danog\\MadelineProto\\MTProtoTools\\PasswordCalculator' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/PasswordCalculator.php',
    'danog\\MadelineProto\\MTProtoTools\\PeerHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/PeerHandler.php',
    'danog\\MadelineProto\\MTProtoTools\\ReferenceDatabase' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/ReferenceDatabase.php',
    'danog\\MadelineProto\\MTProtoTools\\ResponseInfo' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/ResponseInfo.php',
    'danog\\MadelineProto\\MTProtoTools\\UpdateHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php',
    'danog\\MadelineProto\\MTProtoTools\\UpdatesState' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/UpdatesState.php',
    'danog\\MadelineProto\\MTProto\\AuthKey' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProto/AuthKey.php',
    'danog\\MadelineProto\\MTProto\\Container' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProto/Container.php',
    'danog\\MadelineProto\\MTProto\\IncomingMessage' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProto/IncomingMessage.php',
    'danog\\MadelineProto\\MTProto\\Message' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProto/Message.php',
    'danog\\MadelineProto\\MTProto\\OutgoingMessage' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProto/OutgoingMessage.php',
    'danog\\MadelineProto\\MTProto\\PermAuthKey' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProto/PermAuthKey.php',
    'danog\\MadelineProto\\MTProto\\TempAuthKey' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MTProto/TempAuthKey.php',
    'danog\\MadelineProto\\Magic' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Magic.php',
    'danog\\MadelineProto\\MyTelegramOrgWrapper' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/MyTelegramOrgWrapper.php',
    'danog\\MadelineProto\\NothingInTheSocketException' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/NothingInTheSocketException.php',
    'danog\\MadelineProto\\PTSException' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/PTSException.php',
    'danog\\MadelineProto\\PsrLogger' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/PsrLogger.php',
    'danog\\MadelineProto\\RPCErrorException' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/RPCErrorException.php',
    'danog\\MadelineProto\\RSA' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/RSA.php',
    'danog\\MadelineProto\\ResponseException' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/ResponseException.php',
    'danog\\MadelineProto\\SecretChats\\AuthKeyHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php',
    'danog\\MadelineProto\\SecretChats\\MessageHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/SecretChats/MessageHandler.php',
    'danog\\MadelineProto\\SecretChats\\ResponseHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/SecretChats/ResponseHandler.php',
    'danog\\MadelineProto\\SecretChats\\SeqNoHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/SecretChats/SeqNoHandler.php',
    'danog\\MadelineProto\\SecurityException' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/SecurityException.php',
    'danog\\MadelineProto\\Serialization' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Serialization.php',
    'danog\\MadelineProto\\SessionPaths' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/SessionPaths.php',
    'danog\\MadelineProto\\Settings' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings.php',
    'danog\\MadelineProto\\SettingsAbstract' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/SettingsAbstract.php',
    'danog\\MadelineProto\\SettingsEmpty' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/SettingsEmpty.php',
    'danog\\MadelineProto\\Settings\\AppInfo' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/AppInfo.php',
    'danog\\MadelineProto\\Settings\\Auth' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Auth.php',
    'danog\\MadelineProto\\Settings\\Connection' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Connection.php',
    'danog\\MadelineProto\\Settings\\DatabaseAbstract' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/DatabaseAbstract.php',
    'danog\\MadelineProto\\Settings\\Database\\DatabaseAbstract' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/DatabaseAbstract.php',
    'danog\\MadelineProto\\Settings\\Database\\Memory' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Memory.php',
    'danog\\MadelineProto\\Settings\\Database\\Mysql' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Mysql.php',
    'danog\\MadelineProto\\Settings\\Database\\Postgres' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Postgres.php',
    'danog\\MadelineProto\\Settings\\Database\\Redis' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Redis.php',
    'danog\\MadelineProto\\Settings\\Database\\SqlAbstract' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/SqlAbstract.php',
    'danog\\MadelineProto\\Settings\\Files' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Files.php',
    'danog\\MadelineProto\\Settings\\Ipc' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Ipc.php',
    'danog\\MadelineProto\\Settings\\Logger' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Logger.php',
    'danog\\MadelineProto\\Settings\\Peer' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Peer.php',
    'danog\\MadelineProto\\Settings\\Pwr' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Pwr.php',
    'danog\\MadelineProto\\Settings\\RPC' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/RPC.php',
    'danog\\MadelineProto\\Settings\\SecretChats' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/SecretChats.php',
    'danog\\MadelineProto\\Settings\\Serialization' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Serialization.php',
    'danog\\MadelineProto\\Settings\\TLSchema' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/TLSchema.php',
    'danog\\MadelineProto\\Settings\\Templates' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/Templates.php',
    'danog\\MadelineProto\\Settings\\VoIP' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Settings/VoIP.php',
    'danog\\MadelineProto\\Shutdown' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Shutdown.php',
    'danog\\MadelineProto\\Snitch' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Snitch.php',
    'danog\\MadelineProto\\StrTools' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/StrTools.php',
    'danog\\MadelineProto\\Stream\\ADNLTransport\\ADNLStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/ADNLTransport/ADNLStream.php',
    'danog\\MadelineProto\\Stream\\Async\\Buffer' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Async/Buffer.php',
    'danog\\MadelineProto\\Stream\\Async\\BufferedStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Async/BufferedStream.php',
    'danog\\MadelineProto\\Stream\\Async\\RawStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Async/RawStream.php',
    'danog\\MadelineProto\\Stream\\BufferInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/BufferInterface.php',
    'danog\\MadelineProto\\Stream\\BufferedProxyStreamInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/BufferedProxyStreamInterface.php',
    'danog\\MadelineProto\\Stream\\BufferedStreamInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/BufferedStreamInterface.php',
    'danog\\MadelineProto\\Stream\\Common\\BufferedRawStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/BufferedRawStream.php',
    'danog\\MadelineProto\\Stream\\Common\\CtrStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/CtrStream.php',
    'danog\\MadelineProto\\Stream\\Common\\FileBufferedStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/FileBufferedStream.php',
    'danog\\MadelineProto\\Stream\\Common\\HashedBufferedStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/HashedBufferedStream.php',
    'danog\\MadelineProto\\Stream\\Common\\SimpleBufferedRawStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/SimpleBufferedRawStream.php',
    'danog\\MadelineProto\\Stream\\Common\\UdpBufferedStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/UdpBufferedStream.php',
    'danog\\MadelineProto\\Stream\\ConnectionContext' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/ConnectionContext.php',
    'danog\\MadelineProto\\Stream\\MTProtoBufferInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoBufferInterface.php',
    'danog\\MadelineProto\\Stream\\MTProtoTransport\\AbridgedStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/AbridgedStream.php',
    'danog\\MadelineProto\\Stream\\MTProtoTransport\\FullStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/FullStream.php',
    'danog\\MadelineProto\\Stream\\MTProtoTransport\\HttpStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/HttpStream.php',
    'danog\\MadelineProto\\Stream\\MTProtoTransport\\HttpsStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/HttpsStream.php',
    'danog\\MadelineProto\\Stream\\MTProtoTransport\\IntermediatePaddedStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/IntermediatePaddedStream.php',
    'danog\\MadelineProto\\Stream\\MTProtoTransport\\IntermediateStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/IntermediateStream.php',
    'danog\\MadelineProto\\Stream\\MTProtoTransport\\ObfuscatedStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/ObfuscatedStream.php',
    'danog\\MadelineProto\\Stream\\Ogg\\Ogg' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Ogg/Ogg.php',
    'danog\\MadelineProto\\Stream\\ProxyStreamInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/ProxyStreamInterface.php',
    'danog\\MadelineProto\\Stream\\Proxy\\HttpProxy' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Proxy/HttpProxy.php',
    'danog\\MadelineProto\\Stream\\Proxy\\SocksProxy' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Proxy/SocksProxy.php',
    'danog\\MadelineProto\\Stream\\RawProxyStreamInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/RawProxyStreamInterface.php',
    'danog\\MadelineProto\\Stream\\RawStreamInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/RawStreamInterface.php',
    'danog\\MadelineProto\\Stream\\ReadBufferInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/ReadBufferInterface.php',
    'danog\\MadelineProto\\Stream\\StreamInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/StreamInterface.php',
    'danog\\MadelineProto\\Stream\\Transport\\DefaultStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/DefaultStream.php',
    'danog\\MadelineProto\\Stream\\Transport\\PremadeStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/PremadeStream.php',
    'danog\\MadelineProto\\Stream\\Transport\\WsStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/WsStream.php',
    'danog\\MadelineProto\\Stream\\Transport\\WssStream' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/WssStream.php',
    'danog\\MadelineProto\\Stream\\WriteBufferInterface' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Stream/WriteBufferInterface.php',
    'danog\\MadelineProto\\TL\\Conversion\\BotAPI' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/BotAPI.php',
    'danog\\MadelineProto\\TL\\Conversion\\BotAPIFiles' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php',
    'danog\\MadelineProto\\TL\\Conversion\\Exception' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/Exception.php',
    'danog\\MadelineProto\\TL\\Conversion\\Extension' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/Extension.php',
    'danog\\MadelineProto\\TL\\Conversion\\TD' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/TD.php',
    'danog\\MadelineProto\\TL\\Exception' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/Exception.php',
    'danog\\MadelineProto\\TL\\PrettyException' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/PrettyException.php',
    'danog\\MadelineProto\\TL\\TL' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/TL.php',
    'danog\\MadelineProto\\TL\\TLCallback' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/TLCallback.php',
    'danog\\MadelineProto\\TL\\TLConstructors' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/TLConstructors.php',
    'danog\\MadelineProto\\TL\\TLMethods' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/TLMethods.php',
    'danog\\MadelineProto\\TL\\TLParams' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/TLParams.php',
    'danog\\MadelineProto\\TL\\Types\\Button' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/Types/Button.php',
    'danog\\MadelineProto\\TL\\Types\\Bytes' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TL/Types/Bytes.php',
    'danog\\MadelineProto\\TON\\ADNLConnection' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TON/ADNLConnection.php',
    'danog\\MadelineProto\\TON\\API' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TON/API.php',
    'danog\\MadelineProto\\TON\\APIFactory' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TON/APIFactory.php',
    'danog\\MadelineProto\\TON\\InternalDoc' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TON/InternalDoc.php',
    'danog\\MadelineProto\\TON\\Lite' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/TON/Lite.php',
    'danog\\MadelineProto\\Tools' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Tools.php',
    'danog\\MadelineProto\\VoIP' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/VoIP.php',
    'danog\\MadelineProto\\VoIPServerConfig' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/VoIPServerConfig.php',
    'danog\\MadelineProto\\VoIP\\AckHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/VoIP/AckHandler.php',
    'danog\\MadelineProto\\VoIP\\AuthKeyHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/VoIP/AuthKeyHandler.php',
    'danog\\MadelineProto\\VoIP\\Endpoint' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/VoIP/Endpoint.php',
    'danog\\MadelineProto\\VoIP\\MessageHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/VoIP/MessageHandler.php',
    'danog\\MadelineProto\\Wrappers\\Ads' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Ads.php',
    'danog\\MadelineProto\\Wrappers\\Button' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Button.php',
    'danog\\MadelineProto\\Wrappers\\Callback' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Callback.php',
    'danog\\MadelineProto\\Wrappers\\DialogHandler' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/DialogHandler.php',
    'danog\\MadelineProto\\Wrappers\\Events' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Events.php',
    'danog\\MadelineProto\\Wrappers\\Login' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Login.php',
    'danog\\MadelineProto\\Wrappers\\Loop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Loop.php',
    'danog\\MadelineProto\\Wrappers\\Noop' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Noop.php',
    'danog\\MadelineProto\\Wrappers\\Start' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Start.php',
    'danog\\MadelineProto\\Wrappers\\TOS' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/TOS.php',
    'danog\\MadelineProto\\Wrappers\\Templates' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Templates.php',
    'danog\\MadelineProto\\Wrappers\\Webhook' => $vendorDir . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Webhook.php',
    'danog\\PlaceHolder' => $vendorDir . '/phabel-transpiler74.danog/magicalserializer/src/danog/PlaceHolder.php',
    'danog\\PrimeModule' => $vendorDir . '/phabel-transpiler74.danog/primemodule/lib/danog/PrimeModule.php',
    'danog\\Serializable' => $vendorDir . '/phabel-transpiler74.danog/magicalserializer/src/danog/Serializable.php',
    'danog\\Serialization' => $vendorDir . '/phabel-transpiler74.danog/magicalserializer/src/danog/Serialization.php',
    'phpseclib3\\Common\\Functions\\Strings' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php',
    'phpseclib3\\Crypt\\AES' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/AES.php',
    'phpseclib3\\Crypt\\Blowfish' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
    'phpseclib3\\Crypt\\ChaCha20' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php',
    'phpseclib3\\Crypt\\Common\\AsymmetricKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php',
    'phpseclib3\\Crypt\\Common\\BlockCipher' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/BlockCipher.php',
    'phpseclib3\\Crypt\\Common\\Formats\\Keys\\OpenSSH' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php',
    'phpseclib3\\Crypt\\Common\\Formats\\Keys\\PKCS' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS.php',
    'phpseclib3\\Crypt\\Common\\Formats\\Keys\\PKCS1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php',
    'phpseclib3\\Crypt\\Common\\Formats\\Keys\\PKCS8' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php',
    'phpseclib3\\Crypt\\Common\\Formats\\Keys\\PuTTY' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php',
    'phpseclib3\\Crypt\\Common\\Formats\\Signature\\Raw' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Signature/Raw.php',
    'phpseclib3\\Crypt\\Common\\PrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/PrivateKey.php',
    'phpseclib3\\Crypt\\Common\\PublicKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/PublicKey.php',
    'phpseclib3\\Crypt\\Common\\StreamCipher' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php',
    'phpseclib3\\Crypt\\Common\\SymmetricKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php',
    'phpseclib3\\Crypt\\Common\\Traits\\Fingerprint' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/Fingerprint.php',
    'phpseclib3\\Crypt\\Common\\Traits\\PasswordProtected' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/PasswordProtected.php',
    'phpseclib3\\Crypt\\DES' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DES.php',
    'phpseclib3\\Crypt\\DH' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH.php',
    'phpseclib3\\Crypt\\DH\\Formats\\Keys\\PKCS1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php',
    'phpseclib3\\Crypt\\DH\\Formats\\Keys\\PKCS8' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php',
    'phpseclib3\\Crypt\\DH\\Parameters' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Parameters.php',
    'phpseclib3\\Crypt\\DH\\PrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/PrivateKey.php',
    'phpseclib3\\Crypt\\DH\\PublicKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/PublicKey.php',
    'phpseclib3\\Crypt\\DSA' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\OpenSSH' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/OpenSSH.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\PKCS1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\PKCS8' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\PuTTY' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\Raw' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/Raw.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\XML' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/XML.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Signature\\ASN1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/ASN1.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Signature\\Raw' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/Raw.php',
    'phpseclib3\\Crypt\\DSA\\Formats\\Signature\\SSH2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/SSH2.php',
    'phpseclib3\\Crypt\\DSA\\Parameters' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Parameters.php',
    'phpseclib3\\Crypt\\DSA\\PrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php',
    'phpseclib3\\Crypt\\DSA\\PublicKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php',
    'phpseclib3\\Crypt\\EC' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC.php',
    'phpseclib3\\Crypt\\EC\\BaseCurves\\Base' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Base.php',
    'phpseclib3\\Crypt\\EC\\BaseCurves\\Binary' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Binary.php',
    'phpseclib3\\Crypt\\EC\\BaseCurves\\KoblitzPrime' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php',
    'phpseclib3\\Crypt\\EC\\BaseCurves\\Montgomery' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php',
    'phpseclib3\\Crypt\\EC\\BaseCurves\\Prime' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php',
    'phpseclib3\\Crypt\\EC\\BaseCurves\\TwistedEdwards' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php',
    'phpseclib3\\Crypt\\EC\\Curves\\Curve25519' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php',
    'phpseclib3\\Crypt\\EC\\Curves\\Curve448' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php',
    'phpseclib3\\Crypt\\EC\\Curves\\Ed25519' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed25519.php',
    'phpseclib3\\Crypt\\EC\\Curves\\Ed448' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed448.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP160r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP160t1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160t1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP192r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP192t1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192t1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP224r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP224t1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224t1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP256r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP256t1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256t1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP320r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP320t1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320t1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP384r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP384t1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384t1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP512r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP512t1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512t1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistb233' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb233.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistb409' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb409.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistk163' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk163.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistk233' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk233.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistk283' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk283.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistk409' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk409.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistp192' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp192.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistp224' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp224.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistp256' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp256.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistp384' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp384.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistp521' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp521.php',
    'phpseclib3\\Crypt\\EC\\Curves\\nistt571' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistt571.php',
    'phpseclib3\\Crypt\\EC\\Curves\\prime192v1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\prime192v2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\prime192v3' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v3.php',
    'phpseclib3\\Crypt\\EC\\Curves\\prime239v1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\prime239v2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\prime239v3' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v3.php',
    'phpseclib3\\Crypt\\EC\\Curves\\prime256v1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime256v1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp112r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp112r2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp128r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp128r2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp160k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp160r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp160r2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp192k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp192r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp224k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp224r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp256k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp256r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp384r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp384r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\secp521r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp521r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect113r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect113r2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect131r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect131r2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect163k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect163r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect163r2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect193r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect193r2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r2.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect233k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect233r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect239k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect239k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect283k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect283r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect409k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect409r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409r1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect571k1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571k1.php',
    'phpseclib3\\Crypt\\EC\\Curves\\sect571r1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571r1.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\Common' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\MontgomeryPrivate' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\MontgomeryPublic' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPublic.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\OpenSSH' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\PKCS1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\PKCS8' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\PuTTY' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\XML' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Keys\\libsodium' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/libsodium.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Signature\\ASN1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/ASN1.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Signature\\Raw' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/Raw.php',
    'phpseclib3\\Crypt\\EC\\Formats\\Signature\\SSH2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/SSH2.php',
    'phpseclib3\\Crypt\\EC\\Parameters' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Parameters.php',
    'phpseclib3\\Crypt\\EC\\PrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php',
    'phpseclib3\\Crypt\\EC\\PublicKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php',
    'phpseclib3\\Crypt\\Hash' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
    'phpseclib3\\Crypt\\PublicKeyLoader' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php',
    'phpseclib3\\Crypt\\RC2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
    'phpseclib3\\Crypt\\RC4' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
    'phpseclib3\\Crypt\\RSA' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
    'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\MSBLOB' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php',
    'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\OpenSSH' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.php',
    'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\PKCS1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php',
    'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\PKCS8' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php',
    'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\PSS' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php',
    'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\PuTTY' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php',
    'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\Raw' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/Raw.php',
    'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\XML' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/XML.php',
    'phpseclib3\\Crypt\\RSA\\PrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php',
    'phpseclib3\\Crypt\\RSA\\PublicKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php',
    'phpseclib3\\Crypt\\Random' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Random.php',
    'phpseclib3\\Crypt\\Rijndael' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
    'phpseclib3\\Crypt\\Salsa20' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php',
    'phpseclib3\\Crypt\\TripleDES' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
    'phpseclib3\\Crypt\\Twofish' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
    'phpseclib3\\Exception\\BadConfigurationException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php',
    'phpseclib3\\Exception\\BadDecryptionException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadDecryptionException.php',
    'phpseclib3\\Exception\\BadModeException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadModeException.php',
    'phpseclib3\\Exception\\ConnectionClosedException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/ConnectionClosedException.php',
    'phpseclib3\\Exception\\FileNotFoundException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php',
    'phpseclib3\\Exception\\InconsistentSetupException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/InconsistentSetupException.php',
    'phpseclib3\\Exception\\InsufficientSetupException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/InsufficientSetupException.php',
    'phpseclib3\\Exception\\NoKeyLoadedException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/NoKeyLoadedException.php',
    'phpseclib3\\Exception\\NoSupportedAlgorithmsException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php',
    'phpseclib3\\Exception\\UnableToConnectException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnableToConnectException.php',
    'phpseclib3\\Exception\\UnsupportedAlgorithmException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php',
    'phpseclib3\\Exception\\UnsupportedCurveException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedCurveException.php',
    'phpseclib3\\Exception\\UnsupportedFormatException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedFormatException.php',
    'phpseclib3\\Exception\\UnsupportedOperationException' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedOperationException.php',
    'phpseclib3\\File\\ANSI' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ANSI.php',
    'phpseclib3\\File\\ASN1' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1.php',
    'phpseclib3\\File\\ASN1\\Element' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Element.php',
    'phpseclib3\\File\\ASN1\\Maps\\AccessDescription' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AccessDescription.php',
    'phpseclib3\\File\\ASN1\\Maps\\AdministrationDomainName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AdministrationDomainName.php',
    'phpseclib3\\File\\ASN1\\Maps\\AlgorithmIdentifier' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php',
    'phpseclib3\\File\\ASN1\\Maps\\AnotherName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AnotherName.php',
    'phpseclib3\\File\\ASN1\\Maps\\Attribute' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attribute.php',
    'phpseclib3\\File\\ASN1\\Maps\\AttributeType' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeType.php',
    'phpseclib3\\File\\ASN1\\Maps\\AttributeTypeAndValue' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php',
    'phpseclib3\\File\\ASN1\\Maps\\AttributeValue' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeValue.php',
    'phpseclib3\\File\\ASN1\\Maps\\Attributes' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attributes.php',
    'phpseclib3\\File\\ASN1\\Maps\\AuthorityInfoAccessSyntax' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php',
    'phpseclib3\\File\\ASN1\\Maps\\AuthorityKeyIdentifier' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php',
    'phpseclib3\\File\\ASN1\\Maps\\BaseDistance' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BaseDistance.php',
    'phpseclib3\\File\\ASN1\\Maps\\BasicConstraints' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BasicConstraints.php',
    'phpseclib3\\File\\ASN1\\Maps\\BuiltInDomainDefinedAttribute' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php',
    'phpseclib3\\File\\ASN1\\Maps\\BuiltInDomainDefinedAttributes' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php',
    'phpseclib3\\File\\ASN1\\Maps\\BuiltInStandardAttributes' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php',
    'phpseclib3\\File\\ASN1\\Maps\\CPSuri' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CPSuri.php',
    'phpseclib3\\File\\ASN1\\Maps\\CRLDistributionPoints' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php',
    'phpseclib3\\File\\ASN1\\Maps\\CRLNumber' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLNumber.php',
    'phpseclib3\\File\\ASN1\\Maps\\CRLReason' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLReason.php',
    'phpseclib3\\File\\ASN1\\Maps\\CertPolicyId' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertPolicyId.php',
    'phpseclib3\\File\\ASN1\\Maps\\Certificate' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Certificate.php',
    'phpseclib3\\File\\ASN1\\Maps\\CertificateIssuer' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateIssuer.php',
    'phpseclib3\\File\\ASN1\\Maps\\CertificateList' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateList.php',
    'phpseclib3\\File\\ASN1\\Maps\\CertificatePolicies' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificatePolicies.php',
    'phpseclib3\\File\\ASN1\\Maps\\CertificateSerialNumber' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php',
    'phpseclib3\\File\\ASN1\\Maps\\CertificationRequest' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequest.php',
    'phpseclib3\\File\\ASN1\\Maps\\CertificationRequestInfo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php',
    'phpseclib3\\File\\ASN1\\Maps\\Characteristic_two' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Characteristic_two.php',
    'phpseclib3\\File\\ASN1\\Maps\\CountryName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CountryName.php',
    'phpseclib3\\File\\ASN1\\Maps\\Curve' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Curve.php',
    'phpseclib3\\File\\ASN1\\Maps\\DHParameter' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DHParameter.php',
    'phpseclib3\\File\\ASN1\\Maps\\DSAParams' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAParams.php',
    'phpseclib3\\File\\ASN1\\Maps\\DSAPrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPrivateKey.php',
    'phpseclib3\\File\\ASN1\\Maps\\DSAPublicKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPublicKey.php',
    'phpseclib3\\File\\ASN1\\Maps\\DigestInfo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DigestInfo.php',
    'phpseclib3\\File\\ASN1\\Maps\\DirectoryString' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DirectoryString.php',
    'phpseclib3\\File\\ASN1\\Maps\\DisplayText' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DisplayText.php',
    'phpseclib3\\File\\ASN1\\Maps\\DistributionPoint' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPoint.php',
    'phpseclib3\\File\\ASN1\\Maps\\DistributionPointName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPointName.php',
    'phpseclib3\\File\\ASN1\\Maps\\DssSigValue' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DssSigValue.php',
    'phpseclib3\\File\\ASN1\\Maps\\ECParameters' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECParameters.php',
    'phpseclib3\\File\\ASN1\\Maps\\ECPoint' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPoint.php',
    'phpseclib3\\File\\ASN1\\Maps\\ECPrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPrivateKey.php',
    'phpseclib3\\File\\ASN1\\Maps\\EDIPartyName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EDIPartyName.php',
    'phpseclib3\\File\\ASN1\\Maps\\EcdsaSigValue' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EcdsaSigValue.php',
    'phpseclib3\\File\\ASN1\\Maps\\EncryptedData' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedData.php',
    'phpseclib3\\File\\ASN1\\Maps\\EncryptedPrivateKeyInfo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php',
    'phpseclib3\\File\\ASN1\\Maps\\ExtKeyUsageSyntax' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php',
    'phpseclib3\\File\\ASN1\\Maps\\Extension' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extension.php',
    'phpseclib3\\File\\ASN1\\Maps\\ExtensionAttribute' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttribute.php',
    'phpseclib3\\File\\ASN1\\Maps\\ExtensionAttributes' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttributes.php',
    'phpseclib3\\File\\ASN1\\Maps\\Extensions' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extensions.php',
    'phpseclib3\\File\\ASN1\\Maps\\FieldElement' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldElement.php',
    'phpseclib3\\File\\ASN1\\Maps\\FieldID' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldID.php',
    'phpseclib3\\File\\ASN1\\Maps\\GeneralName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralName.php',
    'phpseclib3\\File\\ASN1\\Maps\\GeneralNames' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralNames.php',
    'phpseclib3\\File\\ASN1\\Maps\\GeneralSubtree' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtree.php',
    'phpseclib3\\File\\ASN1\\Maps\\GeneralSubtrees' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtrees.php',
    'phpseclib3\\File\\ASN1\\Maps\\HashAlgorithm' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HashAlgorithm.php',
    'phpseclib3\\File\\ASN1\\Maps\\HoldInstructionCode' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HoldInstructionCode.php',
    'phpseclib3\\File\\ASN1\\Maps\\InvalidityDate' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/InvalidityDate.php',
    'phpseclib3\\File\\ASN1\\Maps\\IssuerAltName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuerAltName.php',
    'phpseclib3\\File\\ASN1\\Maps\\IssuingDistributionPoint' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php',
    'phpseclib3\\File\\ASN1\\Maps\\KeyIdentifier' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyIdentifier.php',
    'phpseclib3\\File\\ASN1\\Maps\\KeyPurposeId' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyPurposeId.php',
    'phpseclib3\\File\\ASN1\\Maps\\KeyUsage' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyUsage.php',
    'phpseclib3\\File\\ASN1\\Maps\\MaskGenAlgorithm' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php',
    'phpseclib3\\File\\ASN1\\Maps\\Name' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Name.php',
    'phpseclib3\\File\\ASN1\\Maps\\NameConstraints' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NameConstraints.php',
    'phpseclib3\\File\\ASN1\\Maps\\NetworkAddress' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NetworkAddress.php',
    'phpseclib3\\File\\ASN1\\Maps\\NoticeReference' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NoticeReference.php',
    'phpseclib3\\File\\ASN1\\Maps\\NumericUserIdentifier' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php',
    'phpseclib3\\File\\ASN1\\Maps\\ORAddress' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ORAddress.php',
    'phpseclib3\\File\\ASN1\\Maps\\OneAsymmetricKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OneAsymmetricKey.php',
    'phpseclib3\\File\\ASN1\\Maps\\OrganizationName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationName.php',
    'phpseclib3\\File\\ASN1\\Maps\\OrganizationalUnitNames' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php',
    'phpseclib3\\File\\ASN1\\Maps\\OtherPrimeInfo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php',
    'phpseclib3\\File\\ASN1\\Maps\\OtherPrimeInfos' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php',
    'phpseclib3\\File\\ASN1\\Maps\\PBEParameter' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBEParameter.php',
    'phpseclib3\\File\\ASN1\\Maps\\PBES2params' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBES2params.php',
    'phpseclib3\\File\\ASN1\\Maps\\PBKDF2params' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBKDF2params.php',
    'phpseclib3\\File\\ASN1\\Maps\\PBMAC1params' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBMAC1params.php',
    'phpseclib3\\File\\ASN1\\Maps\\PKCS9String' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PKCS9String.php',
    'phpseclib3\\File\\ASN1\\Maps\\Pentanomial' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Pentanomial.php',
    'phpseclib3\\File\\ASN1\\Maps\\PersonalName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PersonalName.php',
    'phpseclib3\\File\\ASN1\\Maps\\PolicyInformation' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyInformation.php',
    'phpseclib3\\File\\ASN1\\Maps\\PolicyMappings' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyMappings.php',
    'phpseclib3\\File\\ASN1\\Maps\\PolicyQualifierId' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierId.php',
    'phpseclib3\\File\\ASN1\\Maps\\PolicyQualifierInfo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php',
    'phpseclib3\\File\\ASN1\\Maps\\PostalAddress' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PostalAddress.php',
    'phpseclib3\\File\\ASN1\\Maps\\Prime_p' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Prime_p.php',
    'phpseclib3\\File\\ASN1\\Maps\\PrivateDomainName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateDomainName.php',
    'phpseclib3\\File\\ASN1\\Maps\\PrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKey.php',
    'phpseclib3\\File\\ASN1\\Maps\\PrivateKeyInfo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php',
    'phpseclib3\\File\\ASN1\\Maps\\PrivateKeyUsagePeriod' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php',
    'phpseclib3\\File\\ASN1\\Maps\\PublicKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKey.php',
    'phpseclib3\\File\\ASN1\\Maps\\PublicKeyAndChallenge' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php',
    'phpseclib3\\File\\ASN1\\Maps\\PublicKeyInfo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyInfo.php',
    'phpseclib3\\File\\ASN1\\Maps\\RC2CBCParameter' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RC2CBCParameter.php',
    'phpseclib3\\File\\ASN1\\Maps\\RDNSequence' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RDNSequence.php',
    'phpseclib3\\File\\ASN1\\Maps\\RSAPrivateKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPrivateKey.php',
    'phpseclib3\\File\\ASN1\\Maps\\RSAPublicKey' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPublicKey.php',
    'phpseclib3\\File\\ASN1\\Maps\\RSASSA_PSS_params' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSASSA_PSS_params.php',
    'phpseclib3\\File\\ASN1\\Maps\\ReasonFlags' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ReasonFlags.php',
    'phpseclib3\\File\\ASN1\\Maps\\RelativeDistinguishedName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php',
    'phpseclib3\\File\\ASN1\\Maps\\RevokedCertificate' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RevokedCertificate.php',
    'phpseclib3\\File\\ASN1\\Maps\\SignedPublicKeyAndChallenge' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php',
    'phpseclib3\\File\\ASN1\\Maps\\SpecifiedECDomain' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SpecifiedECDomain.php',
    'phpseclib3\\File\\ASN1\\Maps\\SubjectAltName' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectAltName.php',
    'phpseclib3\\File\\ASN1\\Maps\\SubjectDirectoryAttributes' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php',
    'phpseclib3\\File\\ASN1\\Maps\\SubjectInfoAccessSyntax' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectInfoAccessSyntax.php',
    'phpseclib3\\File\\ASN1\\Maps\\SubjectPublicKeyInfo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php',
    'phpseclib3\\File\\ASN1\\Maps\\TBSCertList' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertList.php',
    'phpseclib3\\File\\ASN1\\Maps\\TBSCertificate' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertificate.php',
    'phpseclib3\\File\\ASN1\\Maps\\TerminalIdentifier' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TerminalIdentifier.php',
    'phpseclib3\\File\\ASN1\\Maps\\Time' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Time.php',
    'phpseclib3\\File\\ASN1\\Maps\\Trinomial' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Trinomial.php',
    'phpseclib3\\File\\ASN1\\Maps\\UniqueIdentifier' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UniqueIdentifier.php',
    'phpseclib3\\File\\ASN1\\Maps\\UserNotice' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UserNotice.php',
    'phpseclib3\\File\\ASN1\\Maps\\Validity' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Validity.php',
    'phpseclib3\\File\\ASN1\\Maps\\netscape_ca_policy_url' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php',
    'phpseclib3\\File\\ASN1\\Maps\\netscape_cert_type' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_cert_type.php',
    'phpseclib3\\File\\ASN1\\Maps\\netscape_comment' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_comment.php',
    'phpseclib3\\File\\X509' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/X509.php',
    'phpseclib3\\Math\\BigInteger' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\BCMath' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\Base' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\BuiltIn' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\DefaultEngine' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/DefaultEngine.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\OpenSSL' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/OpenSSL.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\Reductions\\Barrett' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\Reductions\\EvalBarrett' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\Engine' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\GMP' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\GMP\\DefaultEngine' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP/DefaultEngine.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\OpenSSL' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/OpenSSL.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP32' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP64' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP64.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Base' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Base.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\DefaultEngine' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/DefaultEngine.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Montgomery' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Montgomery.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\OpenSSL' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/OpenSSL.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\Barrett' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\Classic' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Classic.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\EvalBarrett' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/EvalBarrett.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\Montgomery' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Montgomery.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\MontgomeryMult' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/MontgomeryMult.php',
    'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\PowerOfTwo' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/PowerOfTwo.php',
    'phpseclib3\\Math\\BinaryField' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BinaryField.php',
    'phpseclib3\\Math\\BinaryField\\Integer' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BinaryField/Integer.php',
    'phpseclib3\\Math\\Common\\FiniteField' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/Common/FiniteField.php',
    'phpseclib3\\Math\\Common\\FiniteField\\Integer' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/Common/FiniteField/Integer.php',
    'phpseclib3\\Math\\PrimeField' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/PrimeField.php',
    'phpseclib3\\Math\\PrimeField\\Integer' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php',
    'phpseclib3\\Net\\SFTP' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SFTP.php',
    'phpseclib3\\Net\\SFTP\\Stream' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php',
    'phpseclib3\\Net\\SSH2' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SSH2.php',
    'phpseclib3\\System\\SSH\\Agent' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Agent.php',
    'phpseclib3\\System\\SSH\\Agent\\Identity' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php',
    'phpseclib3\\System\\SSH\\Common\\Traits\\ReadBytes' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Common/Traits/ReadBytes.php',
);
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer\Autoload;

/**
 * ClassLoader implements a PSR-0, PSR-4 and classmap class loader.
 *
 *     $loader = new \Composer\Autoload\ClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->add('Symfony\Component', __DIR__.'/component');
 *     $loader->add('Symfony',           __DIR__.'/framework');
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 *     // to enable searching the include path (eg. for PEAR packages)
 *     $loader->setUseIncludePath(true);
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * This class is loosely based on the Symfony UniversalClassLoader.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @see    https://www.php-fig.org/psr/psr-0/
 * @see    https://www.php-fig.org/psr/psr-4/
 */
class ClassLoader
{
    private $vendorDir;

    // PSR-4
    private $prefixLengthsPsr4 = array();
    private $prefixDirsPsr4 = array();
    private $fallbackDirsPsr4 = array();

    // PSR-0
    private $prefixesPsr0 = array();
    private $fallbackDirsPsr0 = array();

    private $useIncludePath = false;
    private $classMap = array();
    private $classMapAuthoritative = false;
    private $missingClasses = array();
    private $apcuPrefix;

    private static $registeredLoaders = array();

    public function __construct($vendorDir = null)
    {
        $this->vendorDir = $vendorDir;
    }

    public function getPrefixes()
    {
        if (!empty($this->prefixesPsr0)) {
            return call_user_func_array('array_merge', array_values($this->prefixesPsr0));
        }

        return array();
    }

    public function getPrefixesPsr4()
    {
        return $this->prefixDirsPsr4;
    }

    public function getFallbackDirs()
    {
        return $this->fallbackDirsPsr0;
    }

    public function getFallbackDirsPsr4()
    {
        return $this->fallbackDirsPsr4;
    }

    public function getClassMap()
    {
        return $this->classMap;
    }

    /**
     * @param array $classMap Class to filename map
     */
    public function addClassMap(array $classMap)
    {
        if ($this->classMap) {
            $this->classMap = array_merge($this->classMap, $classMap);
        } else {
            $this->classMap = $classMap;
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix, either
     * appending or prepending to the ones previously set for this prefix.
     *
     * @param string       $prefix  The prefix
     * @param array|string $paths   The PSR-0 root directories
     * @param bool         $prepend Whether to prepend the directories
     */
    public function add($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            if ($prepend) {
                $this->fallbackDirsPsr0 = array_merge(
                    (array) $paths,
                    $this->fallbackDirsPsr0
                );
            } else {
                $this->fallbackDirsPsr0 = array_merge(
                    $this->fallbackDirsPsr0,
                    (array) $paths
                );
            }

            return;
        }

        $first = $prefix[0];
        if (!isset($this->prefixesPsr0[$first][$prefix])) {
            $this->prefixesPsr0[$first][$prefix] = (array) $paths;

            return;
        }
        if ($prepend) {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                (array) $paths,
                $this->prefixesPsr0[$first][$prefix]
            );
        } else {
            $this->prefixesPsr0[$first][$prefix] = array_merge(
                $this->prefixesPsr0[$first][$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace, either
     * appending or prepending to the ones previously set for this namespace.
     *
     * @param string       $prefix  The prefix/namespace, with trailing '\\'
     * @param array|string $paths   The PSR-4 base directories
     * @param bool         $prepend Whether to prepend the directories
     *
     * @throws \InvalidArgumentException
     */
    public function addPsr4($prefix, $paths, $prepend = false)
    {
        if (!$prefix) {
            // Register directories for the root namespace.
            if ($prepend) {
                $this->fallbackDirsPsr4 = array_merge(
                    (array) $paths,
                    $this->fallbackDirsPsr4
                );
            } else {
                $this->fallbackDirsPsr4 = array_merge(
                    $this->fallbackDirsPsr4,
                    (array) $paths
                );
            }
        } elseif (!isset($this->prefixDirsPsr4[$prefix])) {
            // Register directories for a new namespace.
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        } elseif ($prepend) {
            // Prepend directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                (array) $paths,
                $this->prefixDirsPsr4[$prefix]
            );
        } else {
            // Append directories for an already registered namespace.
            $this->prefixDirsPsr4[$prefix] = array_merge(
                $this->prefixDirsPsr4[$prefix],
                (array) $paths
            );
        }
    }

    /**
     * Registers a set of PSR-0 directories for a given prefix,
     * replacing any others previously set for this prefix.
     *
     * @param string       $prefix The prefix
     * @param array|string $paths  The PSR-0 base directories
     */
    public function set($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr0 = (array) $paths;
        } else {
            $this->prefixesPsr0[$prefix[0]][$prefix] = (array) $paths;
        }
    }

    /**
     * Registers a set of PSR-4 directories for a given namespace,
     * replacing any others previously set for this namespace.
     *
     * @param string       $prefix The prefix/namespace, with trailing '\\'
     * @param array|string $paths  The PSR-4 base directories
     *
     * @throws \InvalidArgumentException
     */
    public function setPsr4($prefix, $paths)
    {
        if (!$prefix) {
            $this->fallbackDirsPsr4 = (array) $paths;
        } else {
            $length = strlen($prefix);
            if ('\\' !== $prefix[$length - 1]) {
                throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
            }
            $this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
            $this->prefixDirsPsr4[$prefix] = (array) $paths;
        }
    }

    /**
     * Turns on searching the include path for class files.
     *
     * @param bool $useIncludePath
     */
    public function setUseIncludePath($useIncludePath)
    {
        $this->useIncludePath = $useIncludePath;
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return bool
     */
    public function getUseIncludePath()
    {
        return $this->useIncludePath;
    }

    /**
     * Turns off searching the prefix and fallback directories for classes
     * that have not been registered with the class map.
     *
     * @param bool $classMapAuthoritative
     */
    public function setClassMapAuthoritative($classMapAuthoritative)
    {
        $this->classMapAuthoritative = $classMapAuthoritative;
    }

    /**
     * Should class lookup fail if not found in the current class map?
     *
     * @return bool
     */
    public function isClassMapAuthoritative()
    {
        return $this->classMapAuthoritative;
    }

    /**
     * APCu prefix to use to cache found/not-found classes, if the extension is enabled.
     *
     * @param string|null $apcuPrefix
     */
    public function setApcuPrefix($apcuPrefix)
    {
        $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
    }

    /**
     * The APCu prefix in use, or null if APCu caching is not enabled.
     *
     * @return string|null
     */
    public function getApcuPrefix()
    {
        return $this->apcuPrefix;
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param bool $prepend Whether to prepend the autoloader or not
     */
    public function register($prepend = false)
    {
        spl_autoload_register(array($this, 'loadClass'), true, $prepend);

        if (null === $this->vendorDir) {
            //no-op
        } elseif ($prepend) {
            self::$registeredLoaders = array($this->vendorDir => $this) + self::$registeredLoaders;
        } else {
            unset(self::$registeredLoaders[$this->vendorDir]);
            self::$registeredLoaders[$this->vendorDir] = $this;
        }
    }

    /**
     * Unregisters this instance as an autoloader.
     */
    public function unregister()
    {
        spl_autoload_unregister(array($this, 'loadClass'));

        if (null !== $this->vendorDir) {
            unset(self::$registeredLoaders[$this->vendorDir]);
        }
    }

    /**
     * Loads the given class or interface.
     *
     * @param  string    $class The name of the class
     * @return bool|null True if loaded, null otherwise
     */
    public function loadClass($class)
    {
        if ($file = $this->findFile($class)) {
            includeFile($file);

            return true;
        }
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|false The path if found, false otherwise
     */
    public function findFile($class)
    {
        // class map lookup
        if (isset($this->classMap[$class])) {
            return $this->classMap[$class];
        }
        if ($this->classMapAuthoritative || isset($this->missingClasses[$class])) {
            return false;
        }
        if (null !== $this->apcuPrefix) {
            $file = apcu_fetch($this->apcuPrefix.$class, $hit);
            if ($hit) {
                return $file;
            }
        }

        $file = $this->findFileWithExtension($class, '.php');

        // Search for Hack files if we are running on HHVM
        if (false === $file && defined('HHVM_VERSION')) {
            $file = $this->findFileWithExtension($class, '.hh');
        }

        if (null !== $this->apcuPrefix) {
            apcu_add($this->apcuPrefix.$class, $file);
        }

        if (false === $file) {
            // Remember that this class does not exist.
            $this->missingClasses[$class] = true;
        }

        return $file;
    }

    /**
     * Returns the currently registered loaders indexed by their corresponding vendor directories.
     *
     * @return self[]
     */
    public static function getRegisteredLoaders()
    {
        return self::$registeredLoaders;
    }

    private function findFileWithExtension($class, $ext)
    {
        // PSR-4 lookup
        $logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . $ext;

        $first = $class[0];
        if (isset($this->prefixLengthsPsr4[$first])) {
            $subPath = $class;
            while (false !== $lastPos = strrpos($subPath, '\\')) {
                $subPath = substr($subPath, 0, $lastPos);
                $search = $subPath . '\\';
                if (isset($this->prefixDirsPsr4[$search])) {
                    $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
                    foreach ($this->prefixDirsPsr4[$search] as $dir) {
                        if (file_exists($file = $dir . $pathEnd)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-4 fallback dirs
        foreach ($this->fallbackDirsPsr4 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr4)) {
                return $file;
            }
        }

        // PSR-0 lookup
        if (false !== $pos = strrpos($class, '\\')) {
            // namespaced class name
            $logicalPathPsr0 = substr($logicalPathPsr4, 0, $pos + 1)
                . strtr(substr($logicalPathPsr4, $pos + 1), '_', DIRECTORY_SEPARATOR);
        } else {
            // PEAR-like class name
            $logicalPathPsr0 = strtr($class, '_', DIRECTORY_SEPARATOR) . $ext;
        }

        if (isset($this->prefixesPsr0[$first])) {
            foreach ($this->prefixesPsr0[$first] as $prefix => $dirs) {
                if (0 === strpos($class, $prefix)) {
                    foreach ($dirs as $dir) {
                        if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                            return $file;
                        }
                    }
                }
            }
        }

        // PSR-0 fallback dirs
        foreach ($this->fallbackDirsPsr0 as $dir) {
            if (file_exists($file = $dir . DIRECTORY_SEPARATOR . $logicalPathPsr0)) {
                return $file;
            }
        }

        // PSR-0 include paths.
        if ($this->useIncludePath && $file = stream_resolve_include_path($logicalPathPsr0)) {
            return $file;
        }

        return false;
    }
}

/**
 * Scope isolated include.
 *
 * Prevents access to $this/self from included files.
 */
function includeFile($file)
{
    include $file;
}
<?php

// autoload_namespaces.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'danog\\' => array($vendorDir . '/phabel-transpiler74.danog/magicalserializer/src', $vendorDir . '/phabel-transpiler74.danog/primemodule/lib'),
    'cash' => array($vendorDir . '/phabel-transpiler74.cash/lrucache/src'),
    'Parsedown' => array($vendorDir . '/phabel-transpiler74.erusev/parsedown'),
);
<?php

// autoload_files.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    '1944e8e40cfc429875d669aee5fdd4f1' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/functions.php',
    '959559a3322c2eacf0f8ef99323aa33c' => $vendorDir . '/phabel-transpiler74.amphp/amp/lib/Internal/functions.php',
    '337832e3085ca913146b09d18026641f' => $vendorDir . '/phabel-transpiler74.amphp/byte-stream/lib/functions.php',
    'e13fce1d372f05d9ecf880d1d986384b' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/functions.php',
    'd055e0f274ab4d44d36881790cb19437' => $vendorDir . '/phabel-transpiler74.amphp/sync/src/ConcurrentIterator/functions.php',
    'efd364050677d9b147ba336dd3f38f66' => $vendorDir . '/phabel-transpiler74.amphp/serialization/src/functions.php',
    '974b0c87d7b032bde57f38101fa54459' => $vendorDir . '/phabel-transpiler74.amphp/process/lib/functions.php',
    'c46c98b3fd9abf68272d96b3b6c55953' => $vendorDir . '/phabel-transpiler74.daverandom/libdns/src/functions.php',
    '5928839827f1df9c1a35fbc8d6db9083' => $vendorDir . '/phabel-transpiler74.amphp/dns/lib/functions.php',
    'ab09d39c59caaab6c218695e30b517e5' => $vendorDir . '/phabel-transpiler74.league/uri-parser/src/functions_include.php',
    '4975dbff6fcdafa23521b86231c3f11a' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/functions.php',
    '13d12e9375443f0715f74a5cdfd7d29a' => $vendorDir . '/phabel-transpiler74.amphp/socket/src/Internal/functions.php',
    '467c471869e273fef35cbdac3b321aaa' => $vendorDir . '/phabel-transpiler74.amphp/http/src/functions.php',
    '81b4a065660f769474a1b44409ba67d0' => $vendorDir . '/phabel-transpiler74.amphp/http-client/src/Internal/functions.php',
    '59df0d81c6f6635e410fb2011905d9a3' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Context/functions.php',
    '1b1a476c34a66fac967f9dc6c7de97aa' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Sync/functions.php',
    '8b5477bc3ab7198820591b86ae455c67' => $vendorDir . '/phabel-transpiler74.amphp/parallel/lib/Worker/functions.php',
    'de3d50bd7dd06587d950b3334c5d9997' => $vendorDir . '/phabel-transpiler74.amphp/websocket/src/functions.php',
    'ea96aee3c0f3e23532e421dc01ed42e2' => $vendorDir . '/phabel/phabel/src/guard.php',
    '83c9d7ad8f44e5d18d8ac0fce9352ab4' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/functions.php',
    'e4b185cf9baaa4124e65c0410725c682' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/functions.php',
    'e9a086974097c2fca999f5382afe0ad9' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/functions.php',
    'e1898fbaa10220763250b2592f369252' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/functions.php',
    'cfe921138c514716c263a58c2d98f760' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/functions.php',
    'd203c3486a85d400e3733541217f093c' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/functions.php',
    'd41a69ebafe1edd8dcd68635730d15d4' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/process/lib/functions.php',
    'e0c78ad74f01d85a1132da076233e5a2' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/serialization/src/functions.php',
    'f20ae55593ad53f603dc63533604e080' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/functions.php',
    '62df8fb75da78c47f3c607c25a1779c6' => $vendorDir . '/phabel/phabel/vendor-bundle/amphp/sync/src/ConcurrentIterator/functions.php',
    '04a4c9904846b673c2f7817f7aba8537' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/deprecation-contracts/function.php',
    'f734cf7f28ac98ed983f9a47be95157c' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/bootstrap.php',
    '5e602578fb1d64183e214b756fb20489' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/bootstrap.php',
    '0da2120711fcb264b7a01bf532b5531f' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/bootstrap.php',
    '7a2a9d56352c9f1a5b7eb15ac87f11d8' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/bootstrap.php',
    '140c83e8303155983e29d3a1f7271049' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-php73/bootstrap.php',
    'e41a6845efa8c3520413bb40b45af1a0' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/polyfill-php80/bootstrap.php',
    '8da33189b858455f169a357e32f9edfa' => $vendorDir . '/phabel/phabel/vendor-bundle/symfony/string/Resources/functions.php',
    'efa3b80c61fb35e374f529ec349af098' => $vendorDir . '/danog/madelineproto/src/BigIntegor.php',
    '81f2b6c0f9b646f6cc1f1a36118d70e9' => $vendorDir . '/danog/madelineproto/src/YieldReturnValue.php',
    'cad60ee4f0892badc28f3feef7cce08d' => $vendorDir . '/danog/madelineproto/src/polyfill.php',
    '548109ddbe517701334a1e51249ea7c0' => $vendorDir . '/danog/madelineproto/___transpiledWithPhabel.php',
    'dcade6ba7f9867d0c78aa3b61a2869f5' => $vendorDir . '/phabel-transpiler74.amphp/file/src/functions.php',
    'f70e433f7f4faadba6bf38f259d6fb45' => $vendorDir . '/phabel-transpiler74.amphp/log/src/functions.php',
    '23af9e8657c93dee5b655d7d1ce26679' => $vendorDir . '/phabel-transpiler74.amphp/mysql/src/functions.php',
    '7d703c3d2933982d063c55f026ffe38f' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/functions.php',
    '7eec800e6f9770dc2022606fd1c98f28' => $vendorDir . '/phabel-transpiler74.amphp/postgres/src/Internal/functions.php',
    '1084a2a9a4ddf73388926865f8161143' => $vendorDir . '/phabel-transpiler74.amphp/redis/src/functions.php',
    'e4ac8f79c3ed731facc73ed05d25cc6e' => $vendorDir . '/phabel-transpiler74.amphp/websocket-client/src/functions.php',
    '837ae511679cfc0c00321a097e189d33' => $vendorDir . '/phabel-transpiler74.danog/ipc/lib/functions.php',
    '2a091f5aa7f0e6ae37a16af254df5005' => $vendorDir . '/phabel-transpiler74.danog/tg-file-decoder/src/type.php',
    'db03a443514775d2d4dfbad5c6f13507' => $vendorDir . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/bootstrap.php',
    'f3e4018d16719bbf7a9a1862c24d86ab' => $vendorDir . '/phabel-transpiler74.symfony/polyfill-mbstring/bootstrap.php',
    'ab05c1b4356d9f7c11b512eef3c48bed' => $vendorDir . '/phabel-transpiler74.symfony/polyfill-php80/bootstrap.php',
);
<?php

// autoload_static.php @generated by Composer

namespace Composer\Autoload;

class ComposerStaticInita56f38b10c587f7d23477ad1951b93ea
{
    public static $files = array (
        '1944e8e40cfc429875d669aee5fdd4f1' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/functions.php',
        '959559a3322c2eacf0f8ef99323aa33c' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Internal/functions.php',
        '337832e3085ca913146b09d18026641f' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/functions.php',
        'e13fce1d372f05d9ecf880d1d986384b' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/functions.php',
        'd055e0f274ab4d44d36881790cb19437' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/ConcurrentIterator/functions.php',
        'efd364050677d9b147ba336dd3f38f66' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/serialization/src/functions.php',
        '974b0c87d7b032bde57f38101fa54459' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/functions.php',
        'c46c98b3fd9abf68272d96b3b6c55953' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/functions.php',
        '5928839827f1df9c1a35fbc8d6db9083' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/functions.php',
        'ab09d39c59caaab6c218695e30b517e5' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-parser/src/functions_include.php',
        '4975dbff6fcdafa23521b86231c3f11a' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/functions.php',
        '13d12e9375443f0715f74a5cdfd7d29a' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/Internal/functions.php',
        '467c471869e273fef35cbdac3b321aaa' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/functions.php',
        '81b4a065660f769474a1b44409ba67d0' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Internal/functions.php',
        '59df0d81c6f6635e410fb2011905d9a3' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/functions.php',
        '1b1a476c34a66fac967f9dc6c7de97aa' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/functions.php',
        '8b5477bc3ab7198820591b86ae455c67' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/functions.php',
        'de3d50bd7dd06587d950b3334c5d9997' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/functions.php',
        'ea96aee3c0f3e23532e421dc01ed42e2' => __DIR__ . '/..' . '/phabel/phabel/src/guard.php',
        '83c9d7ad8f44e5d18d8ac0fce9352ab4' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/functions.php',
        'e4b185cf9baaa4124e65c0410725c682' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/functions.php',
        'e9a086974097c2fca999f5382afe0ad9' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/functions.php',
        'e1898fbaa10220763250b2592f369252' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/functions.php',
        'cfe921138c514716c263a58c2d98f760' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/functions.php',
        'd203c3486a85d400e3733541217f093c' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/functions.php',
        'd41a69ebafe1edd8dcd68635730d15d4' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/functions.php',
        'e0c78ad74f01d85a1132da076233e5a2' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/serialization/src/functions.php',
        'f20ae55593ad53f603dc63533604e080' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/functions.php',
        '62df8fb75da78c47f3c607c25a1779c6' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/ConcurrentIterator/functions.php',
        '04a4c9904846b673c2f7817f7aba8537' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/deprecation-contracts/function.php',
        'f734cf7f28ac98ed983f9a47be95157c' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/bootstrap.php',
        '5e602578fb1d64183e214b756fb20489' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/bootstrap.php',
        '0da2120711fcb264b7a01bf532b5531f' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/bootstrap.php',
        '7a2a9d56352c9f1a5b7eb15ac87f11d8' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring/bootstrap.php',
        '140c83e8303155983e29d3a1f7271049' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-php73/bootstrap.php',
        'e41a6845efa8c3520413bb40b45af1a0' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-php80/bootstrap.php',
        '8da33189b858455f169a357e32f9edfa' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Resources/functions.php',
        'efa3b80c61fb35e374f529ec349af098' => __DIR__ . '/..' . '/danog/madelineproto/src/BigIntegor.php',
        '81f2b6c0f9b646f6cc1f1a36118d70e9' => __DIR__ . '/..' . '/danog/madelineproto/src/YieldReturnValue.php',
        'cad60ee4f0892badc28f3feef7cce08d' => __DIR__ . '/..' . '/danog/madelineproto/src/polyfill.php',
        '548109ddbe517701334a1e51249ea7c0' => __DIR__ . '/..' . '/danog/madelineproto/___transpiledWithPhabel.php',
        'dcade6ba7f9867d0c78aa3b61a2869f5' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/functions.php',
        'f70e433f7f4faadba6bf38f259d6fb45' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/log/src/functions.php',
        '23af9e8657c93dee5b655d7d1ce26679' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/functions.php',
        '7d703c3d2933982d063c55f026ffe38f' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/functions.php',
        '7eec800e6f9770dc2022606fd1c98f28' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Internal/functions.php',
        '1084a2a9a4ddf73388926865f8161143' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/functions.php',
        'e4ac8f79c3ed731facc73ed05d25cc6e' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/functions.php',
        '837ae511679cfc0c00321a097e189d33' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/functions.php',
        '2a091f5aa7f0e6ae37a16af254df5005' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/type.php',
        'db03a443514775d2d4dfbad5c6f13507' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/bootstrap.php',
        'f3e4018d16719bbf7a9a1862c24d86ab' => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-mbstring/bootstrap.php',
        'ab05c1b4356d9f7c11b512eef3c48bed' => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-php80/bootstrap.php',
    );

    public static $prefixLengthsPsr4 = array (
        'p' => 
        array (
            'phpseclib3\\' => 11,
        ),
        'd' => 
        array (
            'danog\\MadelineProto\\' => 20,
            'danog\\Loop\\' => 11,
            'danog\\LibDNSJson\\' => 17,
            'danog\\Decoder\\' => 14,
        ),
        'S' => 
        array (
            'Symfony\\Polyfill\\Php80\\' => 23,
            'Symfony\\Polyfill\\Php73\\' => 23,
            'Symfony\\Polyfill\\Mbstring\\' => 26,
            'Symfony\\Polyfill\\Intl\\Normalizer\\' => 33,
            'Symfony\\Polyfill\\Intl\\Grapheme\\' => 31,
            'Symfony\\Polyfill\\Ctype\\' => 23,
        ),
        'P' => 
        array (
            'Psr\\Log\\' => 8,
            'Psr\\Http\\Message\\' => 17,
            'Phabel\\' => 7,
            'PhabelVendor\\Symfony\\Contracts\\Service\\' => 39,
            'PhabelVendor\\Symfony\\Component\\String\\' => 38,
            'PhabelVendor\\Symfony\\Component\\Process\\' => 39,
            'PhabelVendor\\Symfony\\Component\\Console\\' => 39,
            'PhabelVendor\\Psr\\Log\\' => 21,
            'PhabelVendor\\Psr\\Container\\' => 27,
            'PhabelVendor\\PhpParser\\' => 23,
            'PhabelVendor\\PHPStan\\PhpDocParser\\' => 34,
            'PhabelVendor\\Amp\\Sync\\' => 22,
            'PhabelVendor\\Amp\\Serialization\\' => 31,
            'PhabelVendor\\Amp\\Process\\' => 25,
            'PhabelVendor\\Amp\\Parser\\' => 24,
            'PhabelVendor\\Amp\\Parallel\\' => 26,
            'PhabelVendor\\Amp\\ByteStream\\' => 28,
            'PhabelVendor\\Amp\\' => 17,
            'ParagonIE\\ConstantTime\\' => 23,
        ),
        'M' => 
        array (
            'Monolog\\' => 8,
        ),
        'L' => 
        array (
            'LibDNS\\' => 7,
            'League\\Uri\\' => 11,
        ),
        'K' => 
        array (
            'Kelunik\\Certificate\\' => 20,
        ),
        'A' => 
        array (
            'Amp\\WindowsRegistry\\' => 20,
            'Amp\\Websocket\\Client\\' => 21,
            'Amp\\Websocket\\' => 14,
            'Amp\\Sync\\' => 9,
            'Amp\\Sql\\Common\\' => 15,
            'Amp\\Sql\\' => 8,
            'Amp\\Socket\\' => 11,
            'Amp\\Serialization\\' => 18,
            'Amp\\Redis\\' => 10,
            'Amp\\Process\\' => 12,
            'Amp\\Postgres\\' => 13,
            'Amp\\Parser\\' => 11,
            'Amp\\Parallel\\' => 13,
            'Amp\\Mysql\\' => 10,
            'Amp\\Log\\' => 8,
            'Amp\\Ipc\\' => 8,
            'Amp\\Http\\Client\\Cookie\\' => 23,
            'Amp\\Http\\Client\\' => 16,
            'Amp\\Http\\' => 9,
            'Amp\\File\\' => 9,
            'Amp\\DoH\\' => 8,
            'Amp\\Dns\\' => 8,
            'Amp\\Cache\\' => 10,
            'Amp\\ByteStream\\' => 15,
            'Amp\\' => 4,
        ),
    );

    public static $prefixDirsPsr4 = array (
        'phpseclib3\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib',
        ),
        'danog\\MadelineProto\\' => 
        array (
            0 => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto',
        ),
        'danog\\Loop\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib',
        ),
        'danog\\LibDNSJson\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.danog/libdns-json/lib',
        ),
        'danog\\Decoder\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src',
        ),
        'Symfony\\Polyfill\\Php80\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-php80',
            1 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-php80',
        ),
        'Symfony\\Polyfill\\Php73\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-php73',
        ),
        'Symfony\\Polyfill\\Mbstring\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-mbstring',
            1 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-mbstring',
        ),
        'Symfony\\Polyfill\\Intl\\Normalizer\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer',
        ),
        'Symfony\\Polyfill\\Intl\\Grapheme\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme',
        ),
        'Symfony\\Polyfill\\Ctype\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-ctype',
        ),
        'Psr\\Log\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log',
        ),
        'Psr\\Http\\Message\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-factory/src',
            1 => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-message/src',
        ),
        'Phabel\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/src',
        ),
        'PhabelVendor\\Symfony\\Contracts\\Service\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts',
        ),
        'PhabelVendor\\Symfony\\Component\\String\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string',
        ),
        'PhabelVendor\\Symfony\\Component\\Process\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process',
        ),
        'PhabelVendor\\Symfony\\Component\\Console\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console',
        ),
        'PhabelVendor\\Psr\\Log\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log',
        ),
        'PhabelVendor\\Psr\\Container\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/container/src',
        ),
        'PhabelVendor\\PhpParser\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser',
        ),
        'PhabelVendor\\PHPStan\\PhpDocParser\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src',
        ),
        'PhabelVendor\\Amp\\Sync\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src',
        ),
        'PhabelVendor\\Amp\\Serialization\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/serialization/src',
        ),
        'PhabelVendor\\Amp\\Process\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib',
        ),
        'PhabelVendor\\Amp\\Parser\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parser/lib',
        ),
        'PhabelVendor\\Amp\\Parallel\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib',
        ),
        'PhabelVendor\\Amp\\ByteStream\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib',
        ),
        'PhabelVendor\\Amp\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib',
        ),
        'ParagonIE\\ConstantTime\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src',
        ),
        'Monolog\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog',
        ),
        'LibDNS\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src',
        ),
        'League\\Uri\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src',
            1 => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src',
            2 => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-parser/src',
        ),
        'Kelunik\\Certificate\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.kelunik/certificate/lib',
        ),
        'Amp\\WindowsRegistry\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/windows-registry/lib',
        ),
        'Amp\\Websocket\\Client\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src',
        ),
        'Amp\\Websocket\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src',
        ),
        'Amp\\Sync\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src',
        ),
        'Amp\\Sql\\Common\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql-common/src',
        ),
        'Amp\\Sql\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src',
        ),
        'Amp\\Socket\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src',
        ),
        'Amp\\Serialization\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/serialization/src',
        ),
        'Amp\\Redis\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src',
        ),
        'Amp\\Process\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib',
        ),
        'Amp\\Postgres\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src',
        ),
        'Amp\\Parser\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parser/lib',
        ),
        'Amp\\Parallel\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib',
        ),
        'Amp\\Mysql\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src',
        ),
        'Amp\\Log\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/log/src',
        ),
        'Amp\\Ipc\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib',
        ),
        'Amp\\Http\\Client\\Cookie\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client-cookies/src',
        ),
        'Amp\\Http\\Client\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src',
        ),
        'Amp\\Http\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/hpack/src',
            1 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src',
        ),
        'Amp\\File\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src',
        ),
        'Amp\\DoH\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.danog/dns-over-https/lib',
        ),
        'Amp\\Dns\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib',
        ),
        'Amp\\Cache\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib',
        ),
        'Amp\\ByteStream\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib',
        ),
        'Amp\\' => 
        array (
            0 => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib',
        ),
    );

    public static $prefixesPsr0 = array (
        'd' => 
        array (
            'danog\\' => 
            array (
                0 => __DIR__ . '/..' . '/phabel-transpiler74.danog/magicalserializer/src',
                1 => __DIR__ . '/..' . '/phabel-transpiler74.danog/primemodule/lib',
            ),
        ),
        'c' => 
        array (
            'cash' => 
            array (
                0 => __DIR__ . '/..' . '/phabel-transpiler74.cash/lrucache/src',
            ),
        ),
        'P' => 
        array (
            'Parsedown' => 
            array (
                0 => __DIR__ . '/..' . '/phabel-transpiler74.erusev/parsedown',
            ),
        ),
    );

    public static $classMap = array (
        'Amp\\ByteStream\\Base64\\Base64DecodingInputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64DecodingInputStream.php',
        'Amp\\ByteStream\\Base64\\Base64DecodingOutputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php',
        'Amp\\ByteStream\\Base64\\Base64EncodingInputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php',
        'Amp\\ByteStream\\Base64\\Base64EncodingOutputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.php',
        'Amp\\ByteStream\\ClosedException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/ClosedException.php',
        'Amp\\ByteStream\\InMemoryStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/InMemoryStream.php',
        'Amp\\ByteStream\\InputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/InputStream.php',
        'Amp\\ByteStream\\InputStreamChain' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/InputStreamChain.php',
        'Amp\\ByteStream\\IteratorStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/IteratorStream.php',
        'Amp\\ByteStream\\LineReader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/LineReader.php',
        'Amp\\ByteStream\\Message' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/Message.php',
        'Amp\\ByteStream\\OutputBuffer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/OutputBuffer.php',
        'Amp\\ByteStream\\OutputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/OutputStream.php',
        'Amp\\ByteStream\\Payload' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/Payload.php',
        'Amp\\ByteStream\\PendingReadError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/PendingReadError.php',
        'Amp\\ByteStream\\ResourceInputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/ResourceInputStream.php',
        'Amp\\ByteStream\\ResourceOutputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/ResourceOutputStream.php',
        'Amp\\ByteStream\\StreamException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/StreamException.php',
        'Amp\\ByteStream\\ZlibInputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/ZlibInputStream.php',
        'Amp\\ByteStream\\ZlibOutputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/byte-stream/lib/ZlibOutputStream.php',
        'Amp\\Cache\\ArrayCache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib/ArrayCache.php',
        'Amp\\Cache\\AtomicCache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib/AtomicCache.php',
        'Amp\\Cache\\Cache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib/Cache.php',
        'Amp\\Cache\\CacheException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib/CacheException.php',
        'Amp\\Cache\\FileCache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib/FileCache.php',
        'Amp\\Cache\\NullCache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib/NullCache.php',
        'Amp\\Cache\\PrefixCache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib/PrefixCache.php',
        'Amp\\Cache\\SerializedCache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/cache/lib/SerializedCache.php',
        'Amp\\CallableMaker' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/CallableMaker.php',
        'Amp\\CancellationToken' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/CancellationToken.php',
        'Amp\\CancellationTokenSource' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/CancellationTokenSource.php',
        'Amp\\CancelledException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/CancelledException.php',
        'Amp\\CombinedCancellationToken' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/CombinedCancellationToken.php',
        'Amp\\Coroutine' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Coroutine.php',
        'Amp\\Deferred' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Deferred.php',
        'Amp\\Delayed' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Delayed.php',
        'Amp\\Dns\\BlockingFallbackResolver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/BlockingFallbackResolver.php',
        'Amp\\Dns\\Config' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/Config.php',
        'Amp\\Dns\\ConfigException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/ConfigException.php',
        'Amp\\Dns\\ConfigLoader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/ConfigLoader.php',
        'Amp\\Dns\\DnsException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/DnsException.php',
        'Amp\\Dns\\HostLoader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/HostLoader.php',
        'Amp\\Dns\\Internal\\Socket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/Internal/Socket.php',
        'Amp\\Dns\\Internal\\TcpSocket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/Internal/TcpSocket.php',
        'Amp\\Dns\\Internal\\UdpSocket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/Internal/UdpSocket.php',
        'Amp\\Dns\\InvalidNameException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/InvalidNameException.php',
        'Amp\\Dns\\NoRecordException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/NoRecordException.php',
        'Amp\\Dns\\Record' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/Record.php',
        'Amp\\Dns\\Resolver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/Resolver.php',
        'Amp\\Dns\\Rfc1035StubResolver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/Rfc1035StubResolver.php',
        'Amp\\Dns\\TimeoutException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/TimeoutException.php',
        'Amp\\Dns\\UnixConfigLoader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/UnixConfigLoader.php',
        'Amp\\Dns\\WindowsConfigLoader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/dns/lib/WindowsConfigLoader.php',
        'Amp\\DoH\\DoHConfig' => __DIR__ . '/..' . '/phabel-transpiler74.danog/dns-over-https/lib/DoHConfig.php',
        'Amp\\DoH\\DoHException' => __DIR__ . '/..' . '/phabel-transpiler74.danog/dns-over-https/lib/DoHException.php',
        'Amp\\DoH\\Internal\\HttpsSocket' => __DIR__ . '/..' . '/phabel-transpiler74.danog/dns-over-https/lib/Internal/HttpsSocket.php',
        'Amp\\DoH\\Internal\\Socket' => __DIR__ . '/..' . '/phabel-transpiler74.danog/dns-over-https/lib/Internal/Socket.php',
        'Amp\\DoH\\Nameserver' => __DIR__ . '/..' . '/phabel-transpiler74.danog/dns-over-https/lib/Nameserver.php',
        'Amp\\DoH\\Rfc8484StubResolver' => __DIR__ . '/..' . '/phabel-transpiler74.danog/dns-over-https/lib/Rfc8484StubResolver.php',
        'Amp\\Emitter' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Emitter.php',
        'Amp\\Failure' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Failure.php',
        'Amp\\File\\Driver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver.php',
        'Amp\\File\\Driver\\BlockingDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/BlockingDriver.php',
        'Amp\\File\\Driver\\BlockingFile' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/BlockingFile.php',
        'Amp\\File\\Driver\\EioDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/EioDriver.php',
        'Amp\\File\\Driver\\EioFile' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/EioFile.php',
        'Amp\\File\\Driver\\ParallelDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/ParallelDriver.php',
        'Amp\\File\\Driver\\ParallelFile' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/ParallelFile.php',
        'Amp\\File\\Driver\\StatusCachingDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/StatusCachingDriver.php',
        'Amp\\File\\Driver\\StatusCachingFile' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/StatusCachingFile.php',
        'Amp\\File\\Driver\\UvDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/UvDriver.php',
        'Amp\\File\\Driver\\UvFile' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Driver/UvFile.php',
        'Amp\\File\\File' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/File.php',
        'Amp\\File\\Filesystem' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Filesystem.php',
        'Amp\\File\\FilesystemException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/FilesystemException.php',
        'Amp\\File\\Internal\\Cache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Internal/Cache.php',
        'Amp\\File\\Internal\\EioPoll' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Internal/EioPoll.php',
        'Amp\\File\\Internal\\FileTask' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Internal/FileTask.php',
        'Amp\\File\\Internal\\UvPoll' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Internal/UvPoll.php',
        'Amp\\File\\PendingOperationError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/PendingOperationError.php',
        'Amp\\File\\Sync\\AsyncFileMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/file/src/Sync/AsyncFileMutex.php',
        'Amp\\Http\\Client\\ApplicationInterceptor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/ApplicationInterceptor.php',
        'Amp\\Http\\Client\\Body\\FileBody' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Body/FileBody.php',
        'Amp\\Http\\Client\\Body\\FormBody' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Body/FormBody.php',
        'Amp\\Http\\Client\\Body\\JsonBody' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Body/JsonBody.php',
        'Amp\\Http\\Client\\Body\\StringBody' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Body/StringBody.php',
        'Amp\\Http\\Client\\Connection\\Connection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Connection.php',
        'Amp\\Http\\Client\\Connection\\ConnectionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionFactory.php',
        'Amp\\Http\\Client\\Connection\\ConnectionLimitingPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionLimitingPool.php',
        'Amp\\Http\\Client\\Connection\\ConnectionPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/ConnectionPool.php',
        'Amp\\Http\\Client\\Connection\\DefaultConnectionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/DefaultConnectionFactory.php',
        'Amp\\Http\\Client\\Connection\\Http1Connection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Http1Connection.php',
        'Amp\\Http\\Client\\Connection\\Http2Connection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Http2Connection.php',
        'Amp\\Http\\Client\\Connection\\Http2ConnectionException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Http2ConnectionException.php',
        'Amp\\Http\\Client\\Connection\\Http2StreamException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Http2StreamException.php',
        'Amp\\Http\\Client\\Connection\\HttpStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/HttpStream.php',
        'Amp\\Http\\Client\\Connection\\InterceptedStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/InterceptedStream.php',
        'Amp\\Http\\Client\\Connection\\Internal\\Http1Parser' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http1Parser.php',
        'Amp\\Http\\Client\\Connection\\Internal\\Http2ConnectionProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http2ConnectionProcessor.php',
        'Amp\\Http\\Client\\Connection\\Internal\\Http2Stream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Internal/Http2Stream.php',
        'Amp\\Http\\Client\\Connection\\Internal\\RequestNormalizer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Internal/RequestNormalizer.php',
        'Amp\\Http\\Client\\Connection\\Stream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/Stream.php',
        'Amp\\Http\\Client\\Connection\\StreamLimitingPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/StreamLimitingPool.php',
        'Amp\\Http\\Client\\Connection\\UnlimitedConnectionPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/UnlimitedConnectionPool.php',
        'Amp\\Http\\Client\\Connection\\UnprocessedRequestException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/UnprocessedRequestException.php',
        'Amp\\Http\\Client\\Connection\\UpgradedSocket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Connection/UpgradedSocket.php',
        'Amp\\Http\\Client\\Cookie\\CookieInterceptor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client-cookies/src/CookieInterceptor.php',
        'Amp\\Http\\Client\\Cookie\\CookieJar' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client-cookies/src/CookieJar.php',
        'Amp\\Http\\Client\\Cookie\\FileCookieJar' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client-cookies/src/FileCookieJar.php',
        'Amp\\Http\\Client\\Cookie\\InMemoryCookieJar' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client-cookies/src/InMemoryCookieJar.php',
        'Amp\\Http\\Client\\Cookie\\Internal\\PublicSuffixList' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client-cookies/src/Internal/PublicSuffixList.php',
        'Amp\\Http\\Client\\Cookie\\NullCookieJar' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client-cookies/src/NullCookieJar.php',
        'Amp\\Http\\Client\\DelegateHttpClient' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/DelegateHttpClient.php',
        'Amp\\Http\\Client\\EventListener' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/EventListener.php',
        'Amp\\Http\\Client\\EventListener\\RecordHarAttributes' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/EventListener/RecordHarAttributes.php',
        'Amp\\Http\\Client\\HttpClient' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/HttpClient.php',
        'Amp\\Http\\Client\\HttpClientBuilder' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/HttpClientBuilder.php',
        'Amp\\Http\\Client\\HttpException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/HttpException.php',
        'Amp\\Http\\Client\\InterceptedHttpClient' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/InterceptedHttpClient.php',
        'Amp\\Http\\Client\\Interceptor\\AddRequestHeader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/AddRequestHeader.php',
        'Amp\\Http\\Client\\Interceptor\\AddResponseHeader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/AddResponseHeader.php',
        'Amp\\Http\\Client\\Interceptor\\DecompressResponse' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/DecompressResponse.php',
        'Amp\\Http\\Client\\Interceptor\\FollowRedirects' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/FollowRedirects.php',
        'Amp\\Http\\Client\\Interceptor\\ForbidUriUserInfo' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/ForbidUriUserInfo.php',
        'Amp\\Http\\Client\\Interceptor\\LogHttpArchive' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/LogHttpArchive.php',
        'Amp\\Http\\Client\\Interceptor\\MatchOrigin' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/MatchOrigin.php',
        'Amp\\Http\\Client\\Interceptor\\ModifyRequest' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/ModifyRequest.php',
        'Amp\\Http\\Client\\Interceptor\\ModifyResponse' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/ModifyResponse.php',
        'Amp\\Http\\Client\\Interceptor\\RemoveRequestHeader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/RemoveRequestHeader.php',
        'Amp\\Http\\Client\\Interceptor\\RemoveResponseHeader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/RemoveResponseHeader.php',
        'Amp\\Http\\Client\\Interceptor\\RetryRequests' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/RetryRequests.php',
        'Amp\\Http\\Client\\Interceptor\\SetRequestHeader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestHeader.php',
        'Amp\\Http\\Client\\Interceptor\\SetRequestHeaderIfUnset' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestHeaderIfUnset.php',
        'Amp\\Http\\Client\\Interceptor\\SetRequestTimeout' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetRequestTimeout.php',
        'Amp\\Http\\Client\\Interceptor\\SetResponseHeader' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetResponseHeader.php',
        'Amp\\Http\\Client\\Interceptor\\SetResponseHeaderIfUnset' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/SetResponseHeaderIfUnset.php',
        'Amp\\Http\\Client\\Interceptor\\TooManyRedirectsException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Interceptor/TooManyRedirectsException.php',
        'Amp\\Http\\Client\\Internal\\ForbidCloning' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Internal/ForbidCloning.php',
        'Amp\\Http\\Client\\Internal\\ForbidSerialization' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Internal/ForbidSerialization.php',
        'Amp\\Http\\Client\\Internal\\HarAttributes' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Internal/HarAttributes.php',
        'Amp\\Http\\Client\\Internal\\ResponseBodyStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Internal/ResponseBodyStream.php',
        'Amp\\Http\\Client\\Internal\\SizeLimitingInputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Internal/SizeLimitingInputStream.php',
        'Amp\\Http\\Client\\InvalidRequestException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/InvalidRequestException.php',
        'Amp\\Http\\Client\\MissingAttributeError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/MissingAttributeError.php',
        'Amp\\Http\\Client\\NetworkInterceptor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/NetworkInterceptor.php',
        'Amp\\Http\\Client\\ParseException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/ParseException.php',
        'Amp\\Http\\Client\\PooledHttpClient' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/PooledHttpClient.php',
        'Amp\\Http\\Client\\Request' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Request.php',
        'Amp\\Http\\Client\\RequestBody' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/RequestBody.php',
        'Amp\\Http\\Client\\Response' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Response.php',
        'Amp\\Http\\Client\\SocketException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/SocketException.php',
        'Amp\\Http\\Client\\TimeoutException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/TimeoutException.php',
        'Amp\\Http\\Client\\Trailers' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http-client/src/Trailers.php',
        'Amp\\Http\\Cookie\\CookieAttributes' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Cookie/CookieAttributes.php',
        'Amp\\Http\\Cookie\\InvalidCookieException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Cookie/InvalidCookieException.php',
        'Amp\\Http\\Cookie\\RequestCookie' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Cookie/RequestCookie.php',
        'Amp\\Http\\Cookie\\ResponseCookie' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Cookie/ResponseCookie.php',
        'Amp\\Http\\HPack' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/hpack/src/HPack.php',
        'Amp\\Http\\HPackException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/hpack/src/HPackException.php',
        'Amp\\Http\\Http2\\Http2ConnectionException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Http2/Http2ConnectionException.php',
        'Amp\\Http\\Http2\\Http2Parser' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Http2/Http2Parser.php',
        'Amp\\Http\\Http2\\Http2Processor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Http2/Http2Processor.php',
        'Amp\\Http\\Http2\\Http2StreamException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Http2/Http2StreamException.php',
        'Amp\\Http\\Internal\\HPackNative' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/hpack/src/Internal/HPackNative.php',
        'Amp\\Http\\Internal\\HPackNghttp2' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/hpack/src/Internal/HPackNghttp2.php',
        'Amp\\Http\\InvalidHeaderException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/InvalidHeaderException.php',
        'Amp\\Http\\Message' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Message.php',
        'Amp\\Http\\Rfc7230' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Rfc7230.php',
        'Amp\\Http\\Status' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/http/src/Status.php',
        'Amp\\Internal\\Placeholder' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Internal/Placeholder.php',
        'Amp\\Internal\\PrivateIterator' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Internal/PrivateIterator.php',
        'Amp\\Internal\\PrivatePromise' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Internal/PrivatePromise.php',
        'Amp\\Internal\\Producer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Internal/Producer.php',
        'Amp\\Internal\\ResolutionQueue' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Internal/ResolutionQueue.php',
        'Amp\\InvalidYieldError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/InvalidYieldError.php',
        'Amp\\Ipc\\IpcServer' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/IpcServer.php',
        'Amp\\Ipc\\IpcServerException' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/IpcServerException.php',
        'Amp\\Ipc\\PendingAcceptError' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/PendingAcceptError.php',
        'Amp\\Ipc\\Sync\\Channel' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/Channel.php',
        'Amp\\Ipc\\Sync\\ChannelCloseAck' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseAck.php',
        'Amp\\Ipc\\Sync\\ChannelCloseMsg' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseMsg.php',
        'Amp\\Ipc\\Sync\\ChannelCloseReq' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelCloseReq.php',
        'Amp\\Ipc\\Sync\\ChannelException' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelException.php',
        'Amp\\Ipc\\Sync\\ChannelParser' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelParser.php',
        'Amp\\Ipc\\Sync\\ChannelledSocket' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelledSocket.php',
        'Amp\\Ipc\\Sync\\ChannelledStream' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/ChannelledStream.php',
        'Amp\\Ipc\\Sync\\PanicError' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/PanicError.php',
        'Amp\\Ipc\\Sync\\Parcel' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/Parcel.php',
        'Amp\\Ipc\\Sync\\SerializationException' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/SerializationException.php',
        'Amp\\Ipc\\Sync\\SynchronizationError' => __DIR__ . '/..' . '/phabel-transpiler74.danog/ipc/lib/Sync/SynchronizationError.php',
        'Amp\\Iterator' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Iterator.php',
        'Amp\\LazyPromise' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/LazyPromise.php',
        'Amp\\Log\\ConsoleFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/log/src/ConsoleFormatter.php',
        'Amp\\Log\\StreamHandler' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/log/src/StreamHandler.php',
        'Amp\\Loop' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop.php',
        'Amp\\Loop\\Driver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/Driver.php',
        'Amp\\Loop\\DriverFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/DriverFactory.php',
        'Amp\\Loop\\EvDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/EvDriver.php',
        'Amp\\Loop\\EventDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/EventDriver.php',
        'Amp\\Loop\\Internal\\TimerQueue' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/Internal/TimerQueue.php',
        'Amp\\Loop\\InvalidWatcherError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/InvalidWatcherError.php',
        'Amp\\Loop\\NativeDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/NativeDriver.php',
        'Amp\\Loop\\TracingDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/TracingDriver.php',
        'Amp\\Loop\\UnsupportedFeatureException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/UnsupportedFeatureException.php',
        'Amp\\Loop\\UvDriver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/UvDriver.php',
        'Amp\\Loop\\Watcher' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Loop/Watcher.php',
        'Amp\\MultiReasonException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/MultiReasonException.php',
        'Amp\\Mysql\\CancellableConnector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/CancellableConnector.php',
        'Amp\\Mysql\\CommandResult' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/CommandResult.php',
        'Amp\\Mysql\\Connection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/Connection.php',
        'Amp\\Mysql\\ConnectionConfig' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/ConnectionConfig.php',
        'Amp\\Mysql\\ConnectionResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/ConnectionResultSet.php',
        'Amp\\Mysql\\ConnectionStatement' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/ConnectionStatement.php',
        'Amp\\Mysql\\ConnectionTransaction' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/ConnectionTransaction.php',
        'Amp\\Mysql\\DataTypes' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/DataTypes.php',
        'Amp\\Mysql\\InitializationException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/InitializationException.php',
        'Amp\\Mysql\\Internal\\ConnectionState' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/Internal/ConnectionState.php',
        'Amp\\Mysql\\Internal\\Processor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/Internal/Processor.php',
        'Amp\\Mysql\\Internal\\ResultProxy' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/Internal/ResultProxy.php',
        'Amp\\Mysql\\Pool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/Pool.php',
        'Amp\\Mysql\\PooledResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/PooledResultSet.php',
        'Amp\\Mysql\\PooledStatement' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/PooledStatement.php',
        'Amp\\Mysql\\PooledTransaction' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/PooledTransaction.php',
        'Amp\\Mysql\\RefreshTypes' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/RefreshTypes.php',
        'Amp\\Mysql\\ResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/ResultSet.php',
        'Amp\\Mysql\\Statement' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/Statement.php',
        'Amp\\Mysql\\StatementPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/StatementPool.php',
        'Amp\\Mysql\\TransactionError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/mysql/src/TransactionError.php',
        'Amp\\NullCancellationToken' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/NullCancellationToken.php',
        'Amp\\Parallel\\Context\\Context' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/Context.php',
        'Amp\\Parallel\\Context\\ContextException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/ContextException.php',
        'Amp\\Parallel\\Context\\ContextFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/ContextFactory.php',
        'Amp\\Parallel\\Context\\DefaultContextFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/DefaultContextFactory.php',
        'Amp\\Parallel\\Context\\Internal\\ParallelHub' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/Internal/ParallelHub.php',
        'Amp\\Parallel\\Context\\Internal\\ProcessHub' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/Internal/ProcessHub.php',
        'Amp\\Parallel\\Context\\Internal\\Thread' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/Internal/Thread.php',
        'Amp\\Parallel\\Context\\Parallel' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/Parallel.php',
        'Amp\\Parallel\\Context\\Process' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/Process.php',
        'Amp\\Parallel\\Context\\StatusError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/StatusError.php',
        'Amp\\Parallel\\Context\\Thread' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Context/Thread.php',
        'Amp\\Parallel\\Sync\\Channel' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/Channel.php',
        'Amp\\Parallel\\Sync\\ChannelException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelException.php',
        'Amp\\Parallel\\Sync\\ChannelParser' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelParser.php',
        'Amp\\Parallel\\Sync\\ChannelledSocket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelledSocket.php',
        'Amp\\Parallel\\Sync\\ChannelledStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ChannelledStream.php',
        'Amp\\Parallel\\Sync\\ContextPanicError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ContextPanicError.php',
        'Amp\\Parallel\\Sync\\ExitFailure' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ExitFailure.php',
        'Amp\\Parallel\\Sync\\ExitResult' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ExitResult.php',
        'Amp\\Parallel\\Sync\\ExitSuccess' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ExitSuccess.php',
        'Amp\\Parallel\\Sync\\Internal\\ParcelStorage' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/Internal/ParcelStorage.php',
        'Amp\\Parallel\\Sync\\PanicError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/PanicError.php',
        'Amp\\Parallel\\Sync\\Parcel' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/Parcel.php',
        'Amp\\Parallel\\Sync\\ParcelException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ParcelException.php',
        'Amp\\Parallel\\Sync\\SharedMemoryException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/SharedMemoryException.php',
        'Amp\\Parallel\\Sync\\SharedMemoryParcel' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/SharedMemoryParcel.php',
        'Amp\\Parallel\\Sync\\SynchronizationError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/SynchronizationError.php',
        'Amp\\Parallel\\Sync\\ThreadedParcel' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Sync/ThreadedParcel.php',
        'Amp\\Parallel\\Worker\\BasicEnvironment' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/BasicEnvironment.php',
        'Amp\\Parallel\\Worker\\BootstrapWorkerFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/BootstrapWorkerFactory.php',
        'Amp\\Parallel\\Worker\\CallableTask' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/CallableTask.php',
        'Amp\\Parallel\\Worker\\DefaultPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/DefaultPool.php',
        'Amp\\Parallel\\Worker\\DefaultWorkerFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/DefaultWorkerFactory.php',
        'Amp\\Parallel\\Worker\\Environment' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Environment.php',
        'Amp\\Parallel\\Worker\\Internal\\Job' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/Job.php',
        'Amp\\Parallel\\Worker\\Internal\\PooledWorker' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/PooledWorker.php',
        'Amp\\Parallel\\Worker\\Internal\\TaskFailure' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskFailure.php',
        'Amp\\Parallel\\Worker\\Internal\\TaskResult' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskResult.php',
        'Amp\\Parallel\\Worker\\Internal\\TaskSuccess' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/TaskSuccess.php',
        'Amp\\Parallel\\Worker\\Internal\\WorkerProcess' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Internal/WorkerProcess.php',
        'Amp\\Parallel\\Worker\\Pool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Pool.php',
        'Amp\\Parallel\\Worker\\Task' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Task.php',
        'Amp\\Parallel\\Worker\\TaskError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskError.php',
        'Amp\\Parallel\\Worker\\TaskException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskException.php',
        'Amp\\Parallel\\Worker\\TaskFailureError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureError.php',
        'Amp\\Parallel\\Worker\\TaskFailureException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureException.php',
        'Amp\\Parallel\\Worker\\TaskFailureThrowable' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskFailureThrowable.php',
        'Amp\\Parallel\\Worker\\TaskRunner' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskRunner.php',
        'Amp\\Parallel\\Worker\\TaskWorker' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/TaskWorker.php',
        'Amp\\Parallel\\Worker\\Worker' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/Worker.php',
        'Amp\\Parallel\\Worker\\WorkerException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerException.php',
        'Amp\\Parallel\\Worker\\WorkerFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerFactory.php',
        'Amp\\Parallel\\Worker\\WorkerParallel' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerParallel.php',
        'Amp\\Parallel\\Worker\\WorkerProcess' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerProcess.php',
        'Amp\\Parallel\\Worker\\WorkerThread' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parallel/lib/Worker/WorkerThread.php',
        'Amp\\Parser\\InvalidDelimiterError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parser/lib/InvalidDelimiterError.php',
        'Amp\\Parser\\Parser' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/parser/lib/Parser.php',
        'Amp\\Postgres\\Connection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Connection.php',
        'Amp\\Postgres\\ConnectionConfig' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/ConnectionConfig.php',
        'Amp\\Postgres\\ConnectionListener' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/ConnectionListener.php',
        'Amp\\Postgres\\ConnectionTransaction' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/ConnectionTransaction.php',
        'Amp\\Postgres\\Executor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Executor.php',
        'Amp\\Postgres\\Handle' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Handle.php',
        'Amp\\Postgres\\Internal\\ArrayParser' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Internal/ArrayParser.php',
        'Amp\\Postgres\\Link' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Link.php',
        'Amp\\Postgres\\Listener' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Listener.php',
        'Amp\\Postgres\\Notification' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Notification.php',
        'Amp\\Postgres\\ParseException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/ParseException.php',
        'Amp\\Postgres\\PgSqlCommandResult' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PgSqlCommandResult.php',
        'Amp\\Postgres\\PgSqlConnection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PgSqlConnection.php',
        'Amp\\Postgres\\PgSqlHandle' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PgSqlHandle.php',
        'Amp\\Postgres\\PgSqlResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PgSqlResultSet.php',
        'Amp\\Postgres\\PgSqlStatement' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PgSqlStatement.php',
        'Amp\\Postgres\\Pool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Pool.php',
        'Amp\\Postgres\\PooledListener' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PooledListener.php',
        'Amp\\Postgres\\PooledResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PooledResultSet.php',
        'Amp\\Postgres\\PooledStatement' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PooledStatement.php',
        'Amp\\Postgres\\PooledTransaction' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PooledTransaction.php',
        'Amp\\Postgres\\PqBufferedResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PqBufferedResultSet.php',
        'Amp\\Postgres\\PqCommandResult' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PqCommandResult.php',
        'Amp\\Postgres\\PqConnection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PqConnection.php',
        'Amp\\Postgres\\PqHandle' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PqHandle.php',
        'Amp\\Postgres\\PqStatement' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PqStatement.php',
        'Amp\\Postgres\\PqUnbufferedResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/PqUnbufferedResultSet.php',
        'Amp\\Postgres\\QueryExecutionError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/QueryExecutionError.php',
        'Amp\\Postgres\\Quoter' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Quoter.php',
        'Amp\\Postgres\\Receiver' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Receiver.php',
        'Amp\\Postgres\\ResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/ResultSet.php',
        'Amp\\Postgres\\StatementPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/StatementPool.php',
        'Amp\\Postgres\\TimeoutConnector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/TimeoutConnector.php',
        'Amp\\Postgres\\Transaction' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/postgres/src/Transaction.php',
        'Amp\\Process\\Internal\\Posix\\Handle' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/Posix/Handle.php',
        'Amp\\Process\\Internal\\Posix\\Runner' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/Posix/Runner.php',
        'Amp\\Process\\Internal\\ProcessHandle' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/ProcessHandle.php',
        'Amp\\Process\\Internal\\ProcessRunner' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/ProcessRunner.php',
        'Amp\\Process\\Internal\\ProcessStatus' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/ProcessStatus.php',
        'Amp\\Process\\Internal\\Windows\\Handle' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/Handle.php',
        'Amp\\Process\\Internal\\Windows\\HandshakeStatus' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/HandshakeStatus.php',
        'Amp\\Process\\Internal\\Windows\\PendingSocketClient' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/PendingSocketClient.php',
        'Amp\\Process\\Internal\\Windows\\Runner' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/Runner.php',
        'Amp\\Process\\Internal\\Windows\\SignalCode' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/SignalCode.php',
        'Amp\\Process\\Internal\\Windows\\SocketConnector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Internal/Windows/SocketConnector.php',
        'Amp\\Process\\Process' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/Process.php',
        'Amp\\Process\\ProcessException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/ProcessException.php',
        'Amp\\Process\\ProcessInputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/ProcessInputStream.php',
        'Amp\\Process\\ProcessOutputStream' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/ProcessOutputStream.php',
        'Amp\\Process\\StatusError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/process/lib/StatusError.php',
        'Amp\\Producer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Producer.php',
        'Amp\\Promise' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Promise.php',
        'Amp\\Redis\\Cache' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Cache.php',
        'Amp\\Redis\\Config' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Config.php',
        'Amp\\Redis\\Mutex\\ConnectionLimitException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Mutex/ConnectionLimitException.php',
        'Amp\\Redis\\Mutex\\LockException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Mutex/LockException.php',
        'Amp\\Redis\\Mutex\\Mutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Mutex/Mutex.php',
        'Amp\\Redis\\Mutex\\MutexException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Mutex/MutexException.php',
        'Amp\\Redis\\Mutex\\MutexOptions' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Mutex/MutexOptions.php',
        'Amp\\Redis\\ParserException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/ParserException.php',
        'Amp\\Redis\\QueryException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/QueryException.php',
        'Amp\\Redis\\QueryExecutor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/QueryExecutor.php',
        'Amp\\Redis\\QueryExecutorFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/QueryExecutorFactory.php',
        'Amp\\Redis\\Redis' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Redis.php',
        'Amp\\Redis\\RedisException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RedisException.php',
        'Amp\\Redis\\RedisHyperLogLog' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RedisHyperLogLog.php',
        'Amp\\Redis\\RedisList' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RedisList.php',
        'Amp\\Redis\\RedisMap' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RedisMap.php',
        'Amp\\Redis\\RedisSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RedisSet.php',
        'Amp\\Redis\\RedisSortedSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RedisSortedSet.php',
        'Amp\\Redis\\RemoteExecutor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RemoteExecutor.php',
        'Amp\\Redis\\RemoteExecutorFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RemoteExecutorFactory.php',
        'Amp\\Redis\\RespParser' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RespParser.php',
        'Amp\\Redis\\RespSocket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/RespSocket.php',
        'Amp\\Redis\\SetOptions' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/SetOptions.php',
        'Amp\\Redis\\SocketException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/SocketException.php',
        'Amp\\Redis\\SortOptions' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/SortOptions.php',
        'Amp\\Redis\\Subscriber' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Subscriber.php',
        'Amp\\Redis\\Subscription' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/redis/src/Subscription.php',
        'Amp\\Serialization\\CompressingSerializer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/serialization/src/CompressingSerializer.php',
        'Amp\\Serialization\\JsonSerializer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/serialization/src/JsonSerializer.php',
        'Amp\\Serialization\\NativeSerializer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/serialization/src/NativeSerializer.php',
        'Amp\\Serialization\\PassthroughSerializer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/serialization/src/PassthroughSerializer.php',
        'Amp\\Serialization\\SerializationException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/serialization/src/SerializationException.php',
        'Amp\\Serialization\\Serializer' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/serialization/src/Serializer.php',
        'Amp\\Socket\\BindContext' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/BindContext.php',
        'Amp\\Socket\\Certificate' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/Certificate.php',
        'Amp\\Socket\\ClientTlsContext' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/ClientTlsContext.php',
        'Amp\\Socket\\ConnectContext' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/ConnectContext.php',
        'Amp\\Socket\\ConnectException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/ConnectException.php',
        'Amp\\Socket\\Connector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/Connector.php',
        'Amp\\Socket\\DatagramSocket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/DatagramSocket.php',
        'Amp\\Socket\\DnsConnector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/DnsConnector.php',
        'Amp\\Socket\\EncryptableSocket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/EncryptableSocket.php',
        'Amp\\Socket\\PendingAcceptError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/PendingAcceptError.php',
        'Amp\\Socket\\PendingReceiveError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/PendingReceiveError.php',
        'Amp\\Socket\\ResourceSocket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/ResourceSocket.php',
        'Amp\\Socket\\Server' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/Server.php',
        'Amp\\Socket\\ServerTlsContext' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/ServerTlsContext.php',
        'Amp\\Socket\\Socket' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/Socket.php',
        'Amp\\Socket\\SocketAddress' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/SocketAddress.php',
        'Amp\\Socket\\SocketException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/SocketException.php',
        'Amp\\Socket\\SocketPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/SocketPool.php',
        'Amp\\Socket\\StaticConnector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/StaticConnector.php',
        'Amp\\Socket\\TlsException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/TlsException.php',
        'Amp\\Socket\\TlsInfo' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/TlsInfo.php',
        'Amp\\Socket\\UnlimitedSocketPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/socket/src/UnlimitedSocketPool.php',
        'Amp\\Sql\\CommandResult' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/CommandResult.php',
        'Amp\\Sql\\Common\\ConnectionPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql-common/src/ConnectionPool.php',
        'Amp\\Sql\\Common\\PooledResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql-common/src/PooledResultSet.php',
        'Amp\\Sql\\Common\\PooledStatement' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql-common/src/PooledStatement.php',
        'Amp\\Sql\\Common\\PooledTransaction' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql-common/src/PooledTransaction.php',
        'Amp\\Sql\\Common\\RetryConnector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql-common/src/RetryConnector.php',
        'Amp\\Sql\\Common\\StatementPool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql-common/src/StatementPool.php',
        'Amp\\Sql\\ConnectionConfig' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/ConnectionConfig.php',
        'Amp\\Sql\\ConnectionException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/ConnectionException.php',
        'Amp\\Sql\\Connector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/Connector.php',
        'Amp\\Sql\\Executor' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/Executor.php',
        'Amp\\Sql\\FailureException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/FailureException.php',
        'Amp\\Sql\\Link' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/Link.php',
        'Amp\\Sql\\Pool' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/Pool.php',
        'Amp\\Sql\\PoolError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/PoolError.php',
        'Amp\\Sql\\QueryError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/QueryError.php',
        'Amp\\Sql\\ResultSet' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/ResultSet.php',
        'Amp\\Sql\\Statement' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/Statement.php',
        'Amp\\Sql\\Transaction' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/Transaction.php',
        'Amp\\Sql\\TransactionError' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/TransactionError.php',
        'Amp\\Sql\\TransientResource' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sql/src/TransientResource.php',
        'Amp\\Struct' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Struct.php',
        'Amp\\Success' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/Success.php',
        'Amp\\Sync\\Barrier' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/Barrier.php',
        'Amp\\Sync\\FileMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/FileMutex.php',
        'Amp\\Sync\\Internal\\MutexStorage' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/Internal/MutexStorage.php',
        'Amp\\Sync\\Internal\\SemaphoreStorage' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/Internal/SemaphoreStorage.php',
        'Amp\\Sync\\KeyedMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/KeyedMutex.php',
        'Amp\\Sync\\KeyedSemaphore' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/KeyedSemaphore.php',
        'Amp\\Sync\\LocalKeyedMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/LocalKeyedMutex.php',
        'Amp\\Sync\\LocalKeyedSemaphore' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/LocalKeyedSemaphore.php',
        'Amp\\Sync\\LocalMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/LocalMutex.php',
        'Amp\\Sync\\LocalSemaphore' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/LocalSemaphore.php',
        'Amp\\Sync\\Lock' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/Lock.php',
        'Amp\\Sync\\Mutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/Mutex.php',
        'Amp\\Sync\\PosixSemaphore' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/PosixSemaphore.php',
        'Amp\\Sync\\PrefixedKeyedMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/PrefixedKeyedMutex.php',
        'Amp\\Sync\\PrefixedKeyedSemaphore' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/PrefixedKeyedSemaphore.php',
        'Amp\\Sync\\Semaphore' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/Semaphore.php',
        'Amp\\Sync\\SemaphoreMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/SemaphoreMutex.php',
        'Amp\\Sync\\StaticKeyMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/StaticKeyMutex.php',
        'Amp\\Sync\\SyncException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/SyncException.php',
        'Amp\\Sync\\ThreadedMutex' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/ThreadedMutex.php',
        'Amp\\Sync\\ThreadedSemaphore' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/sync/src/ThreadedSemaphore.php',
        'Amp\\TimeoutCancellationToken' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/TimeoutCancellationToken.php',
        'Amp\\TimeoutException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/amp/lib/TimeoutException.php',
        'Amp\\Websocket\\Client' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/Client.php',
        'Amp\\Websocket\\ClientMetadata' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/ClientMetadata.php',
        'Amp\\Websocket\\Client\\Connection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/Connection.php',
        'Amp\\Websocket\\Client\\ConnectionException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/ConnectionException.php',
        'Amp\\Websocket\\Client\\ConnectionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/ConnectionFactory.php',
        'Amp\\Websocket\\Client\\Connector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/Connector.php',
        'Amp\\Websocket\\Client\\Handshake' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/Handshake.php',
        'Amp\\Websocket\\Client\\Rfc6455Connection' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/Rfc6455Connection.php',
        'Amp\\Websocket\\Client\\Rfc6455ConnectionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/Rfc6455ConnectionFactory.php',
        'Amp\\Websocket\\Client\\Rfc6455Connector' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket-client/src/Rfc6455Connector.php',
        'Amp\\Websocket\\ClosedException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/ClosedException.php',
        'Amp\\Websocket\\Code' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/Code.php',
        'Amp\\Websocket\\CompressionContext' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/CompressionContext.php',
        'Amp\\Websocket\\CompressionContextFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/CompressionContextFactory.php',
        'Amp\\Websocket\\Message' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/Message.php',
        'Amp\\Websocket\\Opcode' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/Opcode.php',
        'Amp\\Websocket\\Options' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/Options.php',
        'Amp\\Websocket\\Rfc6455Client' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/Rfc6455Client.php',
        'Amp\\Websocket\\Rfc7692Compression' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/Rfc7692Compression.php',
        'Amp\\Websocket\\Rfc7692CompressionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/websocket/src/Rfc7692CompressionFactory.php',
        'Amp\\WindowsRegistry\\KeyNotFoundException' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/windows-registry/lib/KeyNotFoundException.php',
        'Amp\\WindowsRegistry\\WindowsRegistry' => __DIR__ . '/..' . '/phabel-transpiler74.amphp/windows-registry/lib/WindowsRegistry.php',
        'Attribute' => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/Attribute.php',
        'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
        'JsonException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-php73/Resources/stubs/JsonException.php',
        'Kelunik\\Certificate\\Certificate' => __DIR__ . '/..' . '/phabel-transpiler74.kelunik/certificate/lib/Certificate.php',
        'Kelunik\\Certificate\\FieldNotSupportedException' => __DIR__ . '/..' . '/phabel-transpiler74.kelunik/certificate/lib/FieldNotSupportedException.php',
        'Kelunik\\Certificate\\InvalidCertificateException' => __DIR__ . '/..' . '/phabel-transpiler74.kelunik/certificate/lib/InvalidCertificateException.php',
        'Kelunik\\Certificate\\Profile' => __DIR__ . '/..' . '/phabel-transpiler74.kelunik/certificate/lib/Profile.php',
        'League\\Uri\\Contracts\\AuthorityInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/AuthorityInterface.php',
        'League\\Uri\\Contracts\\DataPathInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/DataPathInterface.php',
        'League\\Uri\\Contracts\\DomainHostInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/DomainHostInterface.php',
        'League\\Uri\\Contracts\\FragmentInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/FragmentInterface.php',
        'League\\Uri\\Contracts\\HostInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/HostInterface.php',
        'League\\Uri\\Contracts\\IpHostInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/IpHostInterface.php',
        'League\\Uri\\Contracts\\PathInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/PathInterface.php',
        'League\\Uri\\Contracts\\PortInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/PortInterface.php',
        'League\\Uri\\Contracts\\QueryInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/QueryInterface.php',
        'League\\Uri\\Contracts\\SegmentedPathInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/SegmentedPathInterface.php',
        'League\\Uri\\Contracts\\UriComponentInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriComponentInterface.php',
        'League\\Uri\\Contracts\\UriException' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriException.php',
        'League\\Uri\\Contracts\\UriInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/UriInterface.php',
        'League\\Uri\\Contracts\\UserInfoInterface' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Contracts/UserInfoInterface.php',
        'League\\Uri\\Exception' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-parser/src/Exception.php',
        'League\\Uri\\Exceptions\\FileinfoSupportMissing' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Exceptions/FileinfoSupportMissing.php',
        'League\\Uri\\Exceptions\\IdnSupportMissing' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Exceptions/IdnSupportMissing.php',
        'League\\Uri\\Exceptions\\IdnaConversionFailed' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Exceptions/IdnaConversionFailed.php',
        'League\\Uri\\Exceptions\\SyntaxError' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Exceptions/SyntaxError.php',
        'League\\Uri\\Exceptions\\TemplateCanNotBeExpanded' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/Exceptions/TemplateCanNotBeExpanded.php',
        'League\\Uri\\Http' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/Http.php',
        'League\\Uri\\HttpFactory' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/HttpFactory.php',
        'League\\Uri\\Idna\\Idna' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Idna/Idna.php',
        'League\\Uri\\Idna\\IdnaInfo' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-interfaces/src/Idna/IdnaInfo.php',
        'League\\Uri\\MissingIdnSupport' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-parser/src/MissingIdnSupport.php',
        'League\\Uri\\Parser' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri-parser/src/Parser.php',
        'League\\Uri\\Uri' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/Uri.php',
        'League\\Uri\\UriInfo' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/UriInfo.php',
        'League\\Uri\\UriResolver' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/UriResolver.php',
        'League\\Uri\\UriString' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/UriString.php',
        'League\\Uri\\UriTemplate' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/UriTemplate.php',
        'League\\Uri\\UriTemplate\\Expression' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/UriTemplate/Expression.php',
        'League\\Uri\\UriTemplate\\Template' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/UriTemplate/Template.php',
        'League\\Uri\\UriTemplate\\VarSpecifier' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/UriTemplate/VarSpecifier.php',
        'League\\Uri\\UriTemplate\\VariableBag' => __DIR__ . '/..' . '/phabel-transpiler74.league/uri/src/UriTemplate/VariableBag.php',
        'LibDNS\\Decoder\\Decoder' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Decoder/Decoder.php',
        'LibDNS\\Decoder\\DecoderFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Decoder/DecoderFactory.php',
        'LibDNS\\Decoder\\DecodingContext' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Decoder/DecodingContext.php',
        'LibDNS\\Decoder\\DecodingContextFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Decoder/DecodingContextFactory.php',
        'LibDNS\\Encoder\\Encoder' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Encoder/Encoder.php',
        'LibDNS\\Encoder\\EncoderFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Encoder/EncoderFactory.php',
        'LibDNS\\Encoder\\EncodingContext' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Encoder/EncodingContext.php',
        'LibDNS\\Encoder\\EncodingContextFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Encoder/EncodingContextFactory.php',
        'LibDNS\\Enumeration' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Enumeration.php',
        'LibDNS\\Messages\\Message' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Messages/Message.php',
        'LibDNS\\Messages\\MessageFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Messages/MessageFactory.php',
        'LibDNS\\Messages\\MessageOpCodes' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Messages/MessageOpCodes.php',
        'LibDNS\\Messages\\MessageResponseCodes' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Messages/MessageResponseCodes.php',
        'LibDNS\\Messages\\MessageTypes' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Messages/MessageTypes.php',
        'LibDNS\\Packets\\LabelRegistry' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Packets/LabelRegistry.php',
        'LibDNS\\Packets\\Packet' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Packets/Packet.php',
        'LibDNS\\Packets\\PacketFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Packets/PacketFactory.php',
        'LibDNS\\Records\\Question' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Question.php',
        'LibDNS\\Records\\QuestionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/QuestionFactory.php',
        'LibDNS\\Records\\RData' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/RData.php',
        'LibDNS\\Records\\RDataBuilder' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/RDataBuilder.php',
        'LibDNS\\Records\\RDataFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/RDataFactory.php',
        'LibDNS\\Records\\Record' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Record.php',
        'LibDNS\\Records\\RecordCollection' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/RecordCollection.php',
        'LibDNS\\Records\\RecordCollectionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/RecordCollectionFactory.php',
        'LibDNS\\Records\\RecordTypes' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/RecordTypes.php',
        'LibDNS\\Records\\Resource' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Resource.php',
        'LibDNS\\Records\\ResourceBuilder' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceBuilder.php',
        'LibDNS\\Records\\ResourceBuilderFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceBuilderFactory.php',
        'LibDNS\\Records\\ResourceClasses' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceClasses.php',
        'LibDNS\\Records\\ResourceFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceFactory.php',
        'LibDNS\\Records\\ResourceQClasses' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceQClasses.php',
        'LibDNS\\Records\\ResourceQTypes' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceQTypes.php',
        'LibDNS\\Records\\ResourceTypes' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/ResourceTypes.php',
        'LibDNS\\Records\\TypeDefinitions\\FieldDefinition' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/FieldDefinition.php',
        'LibDNS\\Records\\TypeDefinitions\\FieldDefinitionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/FieldDefinitionFactory.php',
        'LibDNS\\Records\\TypeDefinitions\\TypeDefinition' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinition.php',
        'LibDNS\\Records\\TypeDefinitions\\TypeDefinitionFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionFactory.php',
        'LibDNS\\Records\\TypeDefinitions\\TypeDefinitionManager' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionManager.php',
        'LibDNS\\Records\\TypeDefinitions\\TypeDefinitionManagerFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/TypeDefinitions/TypeDefinitionManagerFactory.php',
        'LibDNS\\Records\\Types\\Anything' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Anything.php',
        'LibDNS\\Records\\Types\\BitMap' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/BitMap.php',
        'LibDNS\\Records\\Types\\Char' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Char.php',
        'LibDNS\\Records\\Types\\CharacterString' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/CharacterString.php',
        'LibDNS\\Records\\Types\\DomainName' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/DomainName.php',
        'LibDNS\\Records\\Types\\IPv4Address' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/IPv4Address.php',
        'LibDNS\\Records\\Types\\IPv6Address' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/IPv6Address.php',
        'LibDNS\\Records\\Types\\Long' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Long.php',
        'LibDNS\\Records\\Types\\Short' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Short.php',
        'LibDNS\\Records\\Types\\Type' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Type.php',
        'LibDNS\\Records\\Types\\TypeBuilder' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/TypeBuilder.php',
        'LibDNS\\Records\\Types\\TypeFactory' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/TypeFactory.php',
        'LibDNS\\Records\\Types\\Types' => __DIR__ . '/..' . '/phabel-transpiler74.daverandom/libdns/src/Records/Types/Types.php',
        'Monolog\\DateTimeImmutable' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/DateTimeImmutable.php',
        'Monolog\\ErrorHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/ErrorHandler.php',
        'Monolog\\Formatter\\ChromePHPFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ChromePHPFormatter.php',
        'Monolog\\Formatter\\ElasticaFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ElasticaFormatter.php',
        'Monolog\\Formatter\\ElasticsearchFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ElasticsearchFormatter.php',
        'Monolog\\Formatter\\FlowdockFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FlowdockFormatter.php',
        'Monolog\\Formatter\\FluentdFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FluentdFormatter.php',
        'Monolog\\Formatter\\FormatterInterface' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/FormatterInterface.php',
        'Monolog\\Formatter\\GelfMessageFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/GelfMessageFormatter.php',
        'Monolog\\Formatter\\HtmlFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/HtmlFormatter.php',
        'Monolog\\Formatter\\JsonFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/JsonFormatter.php',
        'Monolog\\Formatter\\LineFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LineFormatter.php',
        'Monolog\\Formatter\\LogglyFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogglyFormatter.php',
        'Monolog\\Formatter\\LogmaticFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogmaticFormatter.php',
        'Monolog\\Formatter\\LogstashFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/LogstashFormatter.php',
        'Monolog\\Formatter\\MongoDBFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/MongoDBFormatter.php',
        'Monolog\\Formatter\\NormalizerFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/NormalizerFormatter.php',
        'Monolog\\Formatter\\ScalarFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/ScalarFormatter.php',
        'Monolog\\Formatter\\WildfireFormatter' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Formatter/WildfireFormatter.php',
        'Monolog\\Handler\\AbstractHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractHandler.php',
        'Monolog\\Handler\\AbstractProcessingHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractProcessingHandler.php',
        'Monolog\\Handler\\AbstractSyslogHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AbstractSyslogHandler.php',
        'Monolog\\Handler\\AmqpHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/AmqpHandler.php',
        'Monolog\\Handler\\BrowserConsoleHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/BrowserConsoleHandler.php',
        'Monolog\\Handler\\BufferHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/BufferHandler.php',
        'Monolog\\Handler\\ChromePHPHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ChromePHPHandler.php',
        'Monolog\\Handler\\CouchDBHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/CouchDBHandler.php',
        'Monolog\\Handler\\CubeHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/CubeHandler.php',
        'Monolog\\Handler\\Curl\\Util' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Curl/Util.php',
        'Monolog\\Handler\\DeduplicationHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DeduplicationHandler.php',
        'Monolog\\Handler\\DoctrineCouchDBHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DoctrineCouchDBHandler.php',
        'Monolog\\Handler\\DynamoDbHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/DynamoDbHandler.php',
        'Monolog\\Handler\\ElasticaHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ElasticaHandler.php',
        'Monolog\\Handler\\ElasticsearchHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ElasticsearchHandler.php',
        'Monolog\\Handler\\ErrorLogHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ErrorLogHandler.php',
        'Monolog\\Handler\\FallbackGroupHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FallbackGroupHandler.php',
        'Monolog\\Handler\\FilterHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FilterHandler.php',
        'Monolog\\Handler\\FingersCrossedHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossedHandler.php',
        'Monolog\\Handler\\FingersCrossed\\ActivationStrategyInterface' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ActivationStrategyInterface.php',
        'Monolog\\Handler\\FingersCrossed\\ChannelLevelActivationStrategy' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ChannelLevelActivationStrategy.php',
        'Monolog\\Handler\\FingersCrossed\\ErrorLevelActivationStrategy' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FingersCrossed/ErrorLevelActivationStrategy.php',
        'Monolog\\Handler\\FirePHPHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FirePHPHandler.php',
        'Monolog\\Handler\\FleepHookHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FleepHookHandler.php',
        'Monolog\\Handler\\FlowdockHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FlowdockHandler.php',
        'Monolog\\Handler\\FormattableHandlerInterface' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FormattableHandlerInterface.php',
        'Monolog\\Handler\\FormattableHandlerTrait' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/FormattableHandlerTrait.php',
        'Monolog\\Handler\\GelfHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/GelfHandler.php',
        'Monolog\\Handler\\GroupHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/GroupHandler.php',
        'Monolog\\Handler\\Handler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Handler.php',
        'Monolog\\Handler\\HandlerInterface' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/HandlerInterface.php',
        'Monolog\\Handler\\HandlerWrapper' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/HandlerWrapper.php',
        'Monolog\\Handler\\IFTTTHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/IFTTTHandler.php',
        'Monolog\\Handler\\InsightOpsHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/InsightOpsHandler.php',
        'Monolog\\Handler\\LogEntriesHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogEntriesHandler.php',
        'Monolog\\Handler\\LogglyHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogglyHandler.php',
        'Monolog\\Handler\\LogmaticHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/LogmaticHandler.php',
        'Monolog\\Handler\\MailHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MailHandler.php',
        'Monolog\\Handler\\MandrillHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MandrillHandler.php',
        'Monolog\\Handler\\MissingExtensionException' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MissingExtensionException.php',
        'Monolog\\Handler\\MongoDBHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/MongoDBHandler.php',
        'Monolog\\Handler\\NativeMailerHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NativeMailerHandler.php',
        'Monolog\\Handler\\NewRelicHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NewRelicHandler.php',
        'Monolog\\Handler\\NoopHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NoopHandler.php',
        'Monolog\\Handler\\NullHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/NullHandler.php',
        'Monolog\\Handler\\OverflowHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/OverflowHandler.php',
        'Monolog\\Handler\\PHPConsoleHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PHPConsoleHandler.php',
        'Monolog\\Handler\\ProcessHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessHandler.php',
        'Monolog\\Handler\\ProcessableHandlerInterface' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessableHandlerInterface.php',
        'Monolog\\Handler\\ProcessableHandlerTrait' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ProcessableHandlerTrait.php',
        'Monolog\\Handler\\PsrHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PsrHandler.php',
        'Monolog\\Handler\\PushoverHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/PushoverHandler.php',
        'Monolog\\Handler\\RedisHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RedisHandler.php',
        'Monolog\\Handler\\RedisPubSubHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RedisPubSubHandler.php',
        'Monolog\\Handler\\RollbarHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RollbarHandler.php',
        'Monolog\\Handler\\RotatingFileHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/RotatingFileHandler.php',
        'Monolog\\Handler\\SamplingHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SamplingHandler.php',
        'Monolog\\Handler\\SendGridHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SendGridHandler.php',
        'Monolog\\Handler\\SlackHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SlackHandler.php',
        'Monolog\\Handler\\SlackWebhookHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SlackWebhookHandler.php',
        'Monolog\\Handler\\Slack\\SlackRecord' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/Slack/SlackRecord.php',
        'Monolog\\Handler\\SocketHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SocketHandler.php',
        'Monolog\\Handler\\SqsHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SqsHandler.php',
        'Monolog\\Handler\\StreamHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/StreamHandler.php',
        'Monolog\\Handler\\SwiftMailerHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SwiftMailerHandler.php',
        'Monolog\\Handler\\SyslogHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogHandler.php',
        'Monolog\\Handler\\SyslogUdpHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogUdpHandler.php',
        'Monolog\\Handler\\SyslogUdp\\UdpSocket' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/SyslogUdp/UdpSocket.php',
        'Monolog\\Handler\\TelegramBotHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/TelegramBotHandler.php',
        'Monolog\\Handler\\TestHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/TestHandler.php',
        'Monolog\\Handler\\WebRequestRecognizerTrait' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/WebRequestRecognizerTrait.php',
        'Monolog\\Handler\\WhatFailureGroupHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/WhatFailureGroupHandler.php',
        'Monolog\\Handler\\ZendMonitorHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Handler/ZendMonitorHandler.php',
        'Monolog\\Logger' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Logger.php',
        'Monolog\\Processor\\GitProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/GitProcessor.php',
        'Monolog\\Processor\\HostnameProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/HostnameProcessor.php',
        'Monolog\\Processor\\IntrospectionProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/IntrospectionProcessor.php',
        'Monolog\\Processor\\MemoryPeakUsageProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryPeakUsageProcessor.php',
        'Monolog\\Processor\\MemoryProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryProcessor.php',
        'Monolog\\Processor\\MemoryUsageProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MemoryUsageProcessor.php',
        'Monolog\\Processor\\MercurialProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/MercurialProcessor.php',
        'Monolog\\Processor\\ProcessIdProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/ProcessIdProcessor.php',
        'Monolog\\Processor\\ProcessorInterface' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/ProcessorInterface.php',
        'Monolog\\Processor\\PsrLogMessageProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/PsrLogMessageProcessor.php',
        'Monolog\\Processor\\TagProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/TagProcessor.php',
        'Monolog\\Processor\\UidProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/UidProcessor.php',
        'Monolog\\Processor\\WebProcessor' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Processor/WebProcessor.php',
        'Monolog\\Registry' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Registry.php',
        'Monolog\\ResettableInterface' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/ResettableInterface.php',
        'Monolog\\SignalHandler' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/SignalHandler.php',
        'Monolog\\Test\\TestCase' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Test/TestCase.php',
        'Monolog\\Utils' => __DIR__ . '/..' . '/phabel-transpiler74.monolog/monolog/src/Monolog/Utils.php',
        'Normalizer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Resources/stubs/Normalizer.php',
        'ParagonIE\\ConstantTime\\Base32' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base32.php',
        'ParagonIE\\ConstantTime\\Base32Hex' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base32Hex.php',
        'ParagonIE\\ConstantTime\\Base64' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64.php',
        'ParagonIE\\ConstantTime\\Base64DotSlash' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64DotSlash.php',
        'ParagonIE\\ConstantTime\\Base64DotSlashOrdered' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64DotSlashOrdered.php',
        'ParagonIE\\ConstantTime\\Base64UrlSafe' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Base64UrlSafe.php',
        'ParagonIE\\ConstantTime\\Binary' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Binary.php',
        'ParagonIE\\ConstantTime\\EncoderInterface' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/EncoderInterface.php',
        'ParagonIE\\ConstantTime\\Encoding' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Encoding.php',
        'ParagonIE\\ConstantTime\\Hex' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/Hex.php',
        'ParagonIE\\ConstantTime\\RFC4648' => __DIR__ . '/..' . '/phabel-transpiler74.paragonie/constant_time_encoding/src/RFC4648.php',
        'Parsedown' => __DIR__ . '/..' . '/phabel-transpiler74.erusev/parsedown/Parsedown.php',
        'PhabelVendor\\Amp\\ByteStream\\Base64\\Base64DecodingInputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64DecodingInputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\Base64\\Base64DecodingOutputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64DecodingOutputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\Base64\\Base64EncodingInputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64EncodingInputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\Base64\\Base64EncodingOutputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Base64/Base64EncodingOutputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\ClosedException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ClosedException.php',
        'PhabelVendor\\Amp\\ByteStream\\InMemoryStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InMemoryStream.php',
        'PhabelVendor\\Amp\\ByteStream\\InputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\InputStreamChain' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/InputStreamChain.php',
        'PhabelVendor\\Amp\\ByteStream\\IteratorStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/IteratorStream.php',
        'PhabelVendor\\Amp\\ByteStream\\LineReader' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/LineReader.php',
        'PhabelVendor\\Amp\\ByteStream\\Message' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Message.php',
        'PhabelVendor\\Amp\\ByteStream\\OutputBuffer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/OutputBuffer.php',
        'PhabelVendor\\Amp\\ByteStream\\OutputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/OutputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\Payload' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/Payload.php',
        'PhabelVendor\\Amp\\ByteStream\\PendingReadError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/PendingReadError.php',
        'PhabelVendor\\Amp\\ByteStream\\ResourceInputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ResourceInputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\ResourceOutputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ResourceOutputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\StreamException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/StreamException.php',
        'PhabelVendor\\Amp\\ByteStream\\ZlibInputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ZlibInputStream.php',
        'PhabelVendor\\Amp\\ByteStream\\ZlibOutputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/byte-stream/lib/ZlibOutputStream.php',
        'PhabelVendor\\Amp\\CallableMaker' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CallableMaker.php',
        'PhabelVendor\\Amp\\CancellationToken' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CancellationToken.php',
        'PhabelVendor\\Amp\\CancellationTokenSource' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CancellationTokenSource.php',
        'PhabelVendor\\Amp\\CancelledException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CancelledException.php',
        'PhabelVendor\\Amp\\CombinedCancellationToken' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/CombinedCancellationToken.php',
        'PhabelVendor\\Amp\\Coroutine' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Coroutine.php',
        'PhabelVendor\\Amp\\Deferred' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Deferred.php',
        'PhabelVendor\\Amp\\Delayed' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Delayed.php',
        'PhabelVendor\\Amp\\Emitter' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Emitter.php',
        'PhabelVendor\\Amp\\Failure' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Failure.php',
        'PhabelVendor\\Amp\\Internal\\Placeholder' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/Placeholder.php',
        'PhabelVendor\\Amp\\Internal\\PrivateIterator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/PrivateIterator.php',
        'PhabelVendor\\Amp\\Internal\\PrivatePromise' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/PrivatePromise.php',
        'PhabelVendor\\Amp\\Internal\\Producer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/Producer.php',
        'PhabelVendor\\Amp\\Internal\\ResolutionQueue' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Internal/ResolutionQueue.php',
        'PhabelVendor\\Amp\\InvalidYieldError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/InvalidYieldError.php',
        'PhabelVendor\\Amp\\Iterator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Iterator.php',
        'PhabelVendor\\Amp\\LazyPromise' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/LazyPromise.php',
        'PhabelVendor\\Amp\\Loop' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop.php',
        'PhabelVendor\\Amp\\Loop\\Driver' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Driver.php',
        'PhabelVendor\\Amp\\Loop\\DriverFactory' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/DriverFactory.php',
        'PhabelVendor\\Amp\\Loop\\EvDriver' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/EvDriver.php',
        'PhabelVendor\\Amp\\Loop\\EventDriver' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/EventDriver.php',
        'PhabelVendor\\Amp\\Loop\\Internal\\TimerQueue' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Internal/TimerQueue.php',
        'PhabelVendor\\Amp\\Loop\\InvalidWatcherError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/InvalidWatcherError.php',
        'PhabelVendor\\Amp\\Loop\\NativeDriver' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/NativeDriver.php',
        'PhabelVendor\\Amp\\Loop\\TracingDriver' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/TracingDriver.php',
        'PhabelVendor\\Amp\\Loop\\UnsupportedFeatureException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/UnsupportedFeatureException.php',
        'PhabelVendor\\Amp\\Loop\\UvDriver' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/UvDriver.php',
        'PhabelVendor\\Amp\\Loop\\Watcher' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Loop/Watcher.php',
        'PhabelVendor\\Amp\\MultiReasonException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/MultiReasonException.php',
        'PhabelVendor\\Amp\\NullCancellationToken' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/NullCancellationToken.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\Context' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Context.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\ContextException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/ContextException.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\ContextFactory' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/ContextFactory.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\DefaultContextFactory' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/DefaultContextFactory.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\Internal\\ParallelHub' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/ParallelHub.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\Internal\\ProcessHub' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/ProcessHub.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\Internal\\Thread' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Internal/Thread.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\Parallel' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Parallel.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\Process' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Process.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\StatusError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/StatusError.php',
        'PhabelVendor\\Amp\\Parallel\\Context\\Thread' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Context/Thread.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\Channel' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Channel.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ChannelException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelException.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ChannelParser' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelParser.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ChannelledSocket' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelledSocket.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ChannelledStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ChannelledStream.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ContextPanicError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ContextPanicError.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ExitFailure' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitFailure.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ExitResult' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitResult.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ExitSuccess' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ExitSuccess.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\Internal\\ParcelStorage' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Internal/ParcelStorage.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\PanicError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/PanicError.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\Parcel' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/Parcel.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ParcelException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ParcelException.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\SharedMemoryException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SharedMemoryException.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\SharedMemoryParcel' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SharedMemoryParcel.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\SynchronizationError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/SynchronizationError.php',
        'PhabelVendor\\Amp\\Parallel\\Sync\\ThreadedParcel' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Sync/ThreadedParcel.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\BasicEnvironment' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/BasicEnvironment.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\BootstrapWorkerFactory' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/BootstrapWorkerFactory.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\CallableTask' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/CallableTask.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\DefaultPool' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/DefaultPool.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\DefaultWorkerFactory' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/DefaultWorkerFactory.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Environment' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Environment.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\Job' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/Job.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\PooledWorker' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/PooledWorker.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\TaskFailure' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskFailure.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\TaskResult' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskResult.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\TaskSuccess' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/TaskSuccess.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Internal\\WorkerProcess' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Internal/WorkerProcess.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Pool' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Pool.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Task' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Task.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\TaskError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskError.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\TaskException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskException.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\TaskFailureError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureError.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\TaskFailureException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureException.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\TaskFailureThrowable' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskFailureThrowable.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\TaskRunner' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskRunner.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\TaskWorker' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/TaskWorker.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\Worker' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/Worker.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerException.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerFactory' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerFactory.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerParallel' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerParallel.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerProcess' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerProcess.php',
        'PhabelVendor\\Amp\\Parallel\\Worker\\WorkerThread' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parallel/lib/Worker/WorkerThread.php',
        'PhabelVendor\\Amp\\Parser\\InvalidDelimiterError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parser/lib/InvalidDelimiterError.php',
        'PhabelVendor\\Amp\\Parser\\Parser' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/parser/lib/Parser.php',
        'PhabelVendor\\Amp\\Process\\Internal\\Posix\\Handle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Posix/Handle.php',
        'PhabelVendor\\Amp\\Process\\Internal\\Posix\\Runner' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Posix/Runner.php',
        'PhabelVendor\\Amp\\Process\\Internal\\ProcessHandle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessHandle.php',
        'PhabelVendor\\Amp\\Process\\Internal\\ProcessRunner' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessRunner.php',
        'PhabelVendor\\Amp\\Process\\Internal\\ProcessStatus' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/ProcessStatus.php',
        'PhabelVendor\\Amp\\Process\\Internal\\Windows\\Handle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/Handle.php',
        'PhabelVendor\\Amp\\Process\\Internal\\Windows\\HandshakeStatus' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/HandshakeStatus.php',
        'PhabelVendor\\Amp\\Process\\Internal\\Windows\\PendingSocketClient' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/PendingSocketClient.php',
        'PhabelVendor\\Amp\\Process\\Internal\\Windows\\Runner' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/Runner.php',
        'PhabelVendor\\Amp\\Process\\Internal\\Windows\\SignalCode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/SignalCode.php',
        'PhabelVendor\\Amp\\Process\\Internal\\Windows\\SocketConnector' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Internal/Windows/SocketConnector.php',
        'PhabelVendor\\Amp\\Process\\Process' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/Process.php',
        'PhabelVendor\\Amp\\Process\\ProcessException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessException.php',
        'PhabelVendor\\Amp\\Process\\ProcessInputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessInputStream.php',
        'PhabelVendor\\Amp\\Process\\ProcessOutputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/ProcessOutputStream.php',
        'PhabelVendor\\Amp\\Process\\StatusError' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/process/lib/StatusError.php',
        'PhabelVendor\\Amp\\Producer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Producer.php',
        'PhabelVendor\\Amp\\Promise' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Promise.php',
        'PhabelVendor\\Amp\\Serialization\\CompressingSerializer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/serialization/src/CompressingSerializer.php',
        'PhabelVendor\\Amp\\Serialization\\JsonSerializer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/serialization/src/JsonSerializer.php',
        'PhabelVendor\\Amp\\Serialization\\NativeSerializer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/serialization/src/NativeSerializer.php',
        'PhabelVendor\\Amp\\Serialization\\PassthroughSerializer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/serialization/src/PassthroughSerializer.php',
        'PhabelVendor\\Amp\\Serialization\\SerializationException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/serialization/src/SerializationException.php',
        'PhabelVendor\\Amp\\Serialization\\Serializer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/serialization/src/Serializer.php',
        'PhabelVendor\\Amp\\Struct' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Struct.php',
        'PhabelVendor\\Amp\\Success' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/Success.php',
        'PhabelVendor\\Amp\\Sync\\Barrier' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/Barrier.php',
        'PhabelVendor\\Amp\\Sync\\FileMutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/FileMutex.php',
        'PhabelVendor\\Amp\\Sync\\Internal\\MutexStorage' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/Internal/MutexStorage.php',
        'PhabelVendor\\Amp\\Sync\\Internal\\SemaphoreStorage' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/Internal/SemaphoreStorage.php',
        'PhabelVendor\\Amp\\Sync\\KeyedMutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/KeyedMutex.php',
        'PhabelVendor\\Amp\\Sync\\KeyedSemaphore' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/KeyedSemaphore.php',
        'PhabelVendor\\Amp\\Sync\\LocalKeyedMutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/LocalKeyedMutex.php',
        'PhabelVendor\\Amp\\Sync\\LocalKeyedSemaphore' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/LocalKeyedSemaphore.php',
        'PhabelVendor\\Amp\\Sync\\LocalMutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/LocalMutex.php',
        'PhabelVendor\\Amp\\Sync\\LocalSemaphore' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/LocalSemaphore.php',
        'PhabelVendor\\Amp\\Sync\\Lock' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/Lock.php',
        'PhabelVendor\\Amp\\Sync\\Mutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/Mutex.php',
        'PhabelVendor\\Amp\\Sync\\PosixSemaphore' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/PosixSemaphore.php',
        'PhabelVendor\\Amp\\Sync\\PrefixedKeyedMutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/PrefixedKeyedMutex.php',
        'PhabelVendor\\Amp\\Sync\\PrefixedKeyedSemaphore' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/PrefixedKeyedSemaphore.php',
        'PhabelVendor\\Amp\\Sync\\Semaphore' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/Semaphore.php',
        'PhabelVendor\\Amp\\Sync\\SemaphoreMutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/SemaphoreMutex.php',
        'PhabelVendor\\Amp\\Sync\\StaticKeyMutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/StaticKeyMutex.php',
        'PhabelVendor\\Amp\\Sync\\SyncException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/SyncException.php',
        'PhabelVendor\\Amp\\Sync\\ThreadedMutex' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/ThreadedMutex.php',
        'PhabelVendor\\Amp\\Sync\\ThreadedSemaphore' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/sync/src/ThreadedSemaphore.php',
        'PhabelVendor\\Amp\\TimeoutCancellationToken' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/TimeoutCancellationToken.php',
        'PhabelVendor\\Amp\\TimeoutException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/amphp/amp/lib/TimeoutException.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayItemNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayItemNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprArrayNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprArrayNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFalseNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFalseNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprFloatNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprFloatNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprIntegerNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprIntegerNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprNullNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprNullNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprStringNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprStringNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstExprTrueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstExprTrueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\ConstExpr\\ConstFetchNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/ConstExpr/ConstFetchNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Node' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Node.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\NodeAttributes' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/NodeAttributes.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\DeprecatedTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/DeprecatedTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ExtendsTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ExtendsTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\GenericTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/GenericTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ImplementsTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ImplementsTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\InvalidTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/InvalidTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MethodTagValueParameterNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MethodTagValueParameterNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\MixinTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/MixinTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ParamTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ParamTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocChildNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocChildNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PhpDocTextNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PhpDocTextNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\PropertyTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/PropertyTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ReturnTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ReturnTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TemplateTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TemplateTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\ThrowsTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/ThrowsTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasImportTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasImportTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\TypeAliasTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/TypeAliasTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\UsesTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/UsesTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\PhpDoc\\VarTagValueNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/PhpDoc/VarTagValueNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeItemNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeItemNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayShapeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayShapeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ArrayTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ArrayTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\CallableTypeParameterNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/CallableTypeParameterNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ConstTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ConstTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\GenericTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/GenericTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\IdentifierTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/IdentifierTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\IntersectionTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/IntersectionTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\NullableTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/NullableTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\ThisTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/ThisTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\TypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/TypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Ast\\Type\\UnionTypeNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Ast/Type/UnionTypeNode.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Lexer\\Lexer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Lexer/Lexer.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\ConstExprParser' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/ConstExprParser.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\ParserException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/ParserException.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\PhpDocParser' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/PhpDocParser.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\TokenIterator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/TokenIterator.php',
        'PhabelVendor\\PHPStan\\PhpDocParser\\Parser\\TypeParser' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phpstan/phpdoc-parser/src/Parser/TypeParser.php',
        'PhabelVendor\\PhpParser\\Builder' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder.php',
        'PhabelVendor\\PhpParser\\BuilderFactory' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/BuilderFactory.php',
        'PhabelVendor\\PhpParser\\BuilderHelpers' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/BuilderHelpers.php',
        'PhabelVendor\\PhpParser\\Builder\\ClassConst' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/ClassConst.php',
        'PhabelVendor\\PhpParser\\Builder\\Class_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Class_.php',
        'PhabelVendor\\PhpParser\\Builder\\Declaration' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Declaration.php',
        'PhabelVendor\\PhpParser\\Builder\\EnumCase' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/EnumCase.php',
        'PhabelVendor\\PhpParser\\Builder\\Enum_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Enum_.php',
        'PhabelVendor\\PhpParser\\Builder\\FunctionLike' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/FunctionLike.php',
        'PhabelVendor\\PhpParser\\Builder\\Function_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Function_.php',
        'PhabelVendor\\PhpParser\\Builder\\Interface_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Interface_.php',
        'PhabelVendor\\PhpParser\\Builder\\Method' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Method.php',
        'PhabelVendor\\PhpParser\\Builder\\Namespace_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Namespace_.php',
        'PhabelVendor\\PhpParser\\Builder\\Param' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Param.php',
        'PhabelVendor\\PhpParser\\Builder\\Property' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Property.php',
        'PhabelVendor\\PhpParser\\Builder\\TraitUse' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/TraitUse.php',
        'PhabelVendor\\PhpParser\\Builder\\TraitUseAdaptation' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/TraitUseAdaptation.php',
        'PhabelVendor\\PhpParser\\Builder\\Trait_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Trait_.php',
        'PhabelVendor\\PhpParser\\Builder\\Use_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Builder/Use_.php',
        'PhabelVendor\\PhpParser\\Comment' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Comment.php',
        'PhabelVendor\\PhpParser\\Comment\\Doc' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Comment/Doc.php',
        'PhabelVendor\\PhpParser\\ConstExprEvaluationException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ConstExprEvaluationException.php',
        'PhabelVendor\\PhpParser\\ConstExprEvaluator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ConstExprEvaluator.php',
        'PhabelVendor\\PhpParser\\Error' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Error.php',
        'PhabelVendor\\PhpParser\\ErrorHandler' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler.php',
        'PhabelVendor\\PhpParser\\ErrorHandler\\Collecting' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler/Collecting.php',
        'PhabelVendor\\PhpParser\\ErrorHandler\\Throwing' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ErrorHandler/Throwing.php',
        'PhabelVendor\\PhpParser\\Internal\\DiffElem' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/DiffElem.php',
        'PhabelVendor\\PhpParser\\Internal\\Differ' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/Differ.php',
        'PhabelVendor\\PhpParser\\Internal\\PrintableNewAnonClassNode' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/PrintableNewAnonClassNode.php',
        'PhabelVendor\\PhpParser\\Internal\\TokenStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Internal/TokenStream.php',
        'PhabelVendor\\PhpParser\\JsonDecoder' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/JsonDecoder.php',
        'PhabelVendor\\PhpParser\\Lexer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer.php',
        'PhabelVendor\\PhpParser\\Lexer\\Emulative' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/Emulative.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\AttributeEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/AttributeEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\AwaitTokenEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/AwaitTokenEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\CoaleseEqualTokenEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/CoaleseEqualTokenEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\EnumTokenEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/EnumTokenEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\ExplicitOctalEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ExplicitOctalEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\FlexibleDocStringEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/FlexibleDocStringEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\FnTokenEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/FnTokenEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\KeywordEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/KeywordEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\MatchTokenEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/MatchTokenEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\NullsafeTokenEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/NullsafeTokenEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\NumericLiteralSeparatorEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/NumericLiteralSeparatorEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\ReadonlyTokenEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReadonlyTokenEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\ReverseEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/ReverseEmulator.php',
        'PhabelVendor\\PhpParser\\Lexer\\TokenEmulator\\TokenEmulator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Lexer/TokenEmulator/TokenEmulator.php',
        'PhabelVendor\\PhpParser\\NameContext' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NameContext.php',
        'PhabelVendor\\PhpParser\\Node' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node.php',
        'PhabelVendor\\PhpParser\\NodeAbstract' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeAbstract.php',
        'PhabelVendor\\PhpParser\\NodeDumper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeDumper.php',
        'PhabelVendor\\PhpParser\\NodeFinder' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeFinder.php',
        'PhabelVendor\\PhpParser\\NodeTraverser' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeTraverser.php',
        'PhabelVendor\\PhpParser\\NodeTraverserInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeTraverserInterface.php',
        'PhabelVendor\\PhpParser\\NodeVisitor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor.php',
        'PhabelVendor\\PhpParser\\NodeVisitorAbstract' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitorAbstract.php',
        'PhabelVendor\\PhpParser\\NodeVisitor\\CloningVisitor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/CloningVisitor.php',
        'PhabelVendor\\PhpParser\\NodeVisitor\\FindingVisitor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/FindingVisitor.php',
        'PhabelVendor\\PhpParser\\NodeVisitor\\FirstFindingVisitor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/FirstFindingVisitor.php',
        'PhabelVendor\\PhpParser\\NodeVisitor\\NameResolver' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/NameResolver.php',
        'PhabelVendor\\PhpParser\\NodeVisitor\\NodeConnectingVisitor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/NodeConnectingVisitor.php',
        'PhabelVendor\\PhpParser\\NodeVisitor\\ParentConnectingVisitor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/NodeVisitor/ParentConnectingVisitor.php',
        'PhabelVendor\\PhpParser\\Node\\Arg' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Arg.php',
        'PhabelVendor\\PhpParser\\Node\\Attribute' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Attribute.php',
        'PhabelVendor\\PhpParser\\Node\\AttributeGroup' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/AttributeGroup.php',
        'PhabelVendor\\PhpParser\\Node\\ComplexType' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/ComplexType.php',
        'PhabelVendor\\PhpParser\\Node\\Const_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Const_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\ArrayDimFetch' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrayDimFetch.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\ArrayItem' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrayItem.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Array_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Array_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\ArrowFunction' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ArrowFunction.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Assign.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseAnd.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseOr.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/BitwiseXor.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Coalesce.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Concat.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Div.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Minus.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mod.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Mul.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Plus.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/Pow.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftLeft.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignOp/ShiftRight.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/AssignRef.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseAnd.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseOr.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BitwiseXor.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanAnd.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/BooleanOr.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Coalesce.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Concat.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Div.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Equal.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Greater.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/GreaterOrEqual.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Identical.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalAnd.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalOr.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/LogicalXor.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Minus.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mod.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Mul.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotEqual.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/NotIdentical.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Plus.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Pow.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftLeft.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/ShiftRight.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Smaller.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/SmallerOrEqual.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BinaryOp/Spaceship.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BitwiseNot.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/BooleanNot.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\CallLike' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/CallLike.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Cast' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Array_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Bool_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Double.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Int_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Object_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/String_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Unset_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Cast/Unset_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ClassConstFetch.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Clone_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Closure.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ClosureUse.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\ConstFetch' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ConstFetch.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Empty_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Error' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Error.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ErrorSuppress.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Eval_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Exit_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Exit_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/FuncCall.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Include_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Instanceof_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Isset_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\List_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/List_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Match_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Match_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/MethodCall.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/New_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\NullsafeMethodCall' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/NullsafeMethodCall.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\NullsafePropertyFetch' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/NullsafePropertyFetch.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PostDec.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PostInc.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PreDec.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PreInc.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Print_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/PropertyFetch.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/ShellExec.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/StaticCall.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/StaticPropertyFetch.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Ternary.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Throw_.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/UnaryMinus.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/UnaryPlus.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Variable' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Variable.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\YieldFrom' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/YieldFrom.php',
        'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Expr/Yield_.php',
        'PhabelVendor\\PhpParser\\Node\\FunctionLike' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/FunctionLike.php',
        'PhabelVendor\\PhpParser\\Node\\Identifier' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Identifier.php',
        'PhabelVendor\\PhpParser\\Node\\IntersectionType' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/IntersectionType.php',
        'PhabelVendor\\PhpParser\\Node\\MatchArm' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/MatchArm.php',
        'PhabelVendor\\PhpParser\\Node\\Name' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name.php',
        'PhabelVendor\\PhpParser\\Node\\Name\\FullyQualified' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name/FullyQualified.php',
        'PhabelVendor\\PhpParser\\Node\\Name\\Relative' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Name/Relative.php',
        'PhabelVendor\\PhpParser\\Node\\NullableType' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/NullableType.php',
        'PhabelVendor\\PhpParser\\Node\\Param' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Param.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/DNumber.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/Encapsed.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\EncapsedStringPart' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/EncapsedStringPart.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/LNumber.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Class_.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Dir.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/File.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Function_.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Line.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Method.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Namespace_.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/MagicConst/Trait_.php',
        'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Scalar/String_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Break_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Break_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Case_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Case_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Catch_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Catch_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\ClassConst' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassConst.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\ClassLike' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassLike.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\ClassMethod' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ClassMethod.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Class_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Class_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Const_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Const_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Continue_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Continue_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\DeclareDeclare' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/DeclareDeclare.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Declare_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Declare_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Do_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Do_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Echo_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Echo_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\ElseIf_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/ElseIf_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Else_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Else_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\EnumCase' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/EnumCase.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Enum_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Enum_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Expression' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Expression.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Finally_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Finally_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\For_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/For_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Foreach_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Foreach_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Function_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Function_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Global_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Global_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Goto_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Goto_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\GroupUse' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/GroupUse.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\HaltCompiler' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/HaltCompiler.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\If_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/If_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\InlineHTML' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/InlineHTML.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Interface_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Interface_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Label' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Label.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Namespace_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Namespace_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Nop' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Nop.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Property' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Property.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\PropertyProperty' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/PropertyProperty.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Return_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Return_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\StaticVar' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/StaticVar.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Static_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Static_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Switch_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Switch_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Throw_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Throw_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\TraitUse' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUse.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\TraitUseAdaptation' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Alias' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Alias.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\TraitUseAdaptation\\Precedence' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TraitUseAdaptation/Precedence.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Trait_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Trait_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\TryCatch' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/TryCatch.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Unset_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Unset_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\UseUse' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/UseUse.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\Use_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/Use_.php',
        'PhabelVendor\\PhpParser\\Node\\Stmt\\While_' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/Stmt/While_.php',
        'PhabelVendor\\PhpParser\\Node\\UnionType' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/UnionType.php',
        'PhabelVendor\\PhpParser\\Node\\VarLikeIdentifier' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/VarLikeIdentifier.php',
        'PhabelVendor\\PhpParser\\Node\\VariadicPlaceholder' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Node/VariadicPlaceholder.php',
        'PhabelVendor\\PhpParser\\Parser' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser.php',
        'PhabelVendor\\PhpParser\\ParserAbstract' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ParserAbstract.php',
        'PhabelVendor\\PhpParser\\ParserFactory' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/ParserFactory.php',
        'PhabelVendor\\PhpParser\\Parser\\Multiple' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Multiple.php',
        'PhabelVendor\\PhpParser\\Parser\\Php5' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Php5.php',
        'PhabelVendor\\PhpParser\\Parser\\Php7' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Php7.php',
        'PhabelVendor\\PhpParser\\Parser\\Tokens' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/Parser/Tokens.php',
        'PhabelVendor\\PhpParser\\PrettyPrinterAbstract' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/PrettyPrinterAbstract.php',
        'PhabelVendor\\PhpParser\\PrettyPrinter\\Standard' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/phabel/php-parser/lib/PhpParser/PrettyPrinter/Standard.php',
        'PhabelVendor\\Psr\\Container\\ContainerExceptionInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/container/src/ContainerExceptionInterface.php',
        'PhabelVendor\\Psr\\Container\\ContainerInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/container/src/ContainerInterface.php',
        'PhabelVendor\\Psr\\Container\\NotFoundExceptionInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/container/src/NotFoundExceptionInterface.php',
        'PhabelVendor\\Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/AbstractLogger.php',
        'PhabelVendor\\Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/InvalidArgumentException.php',
        'PhabelVendor\\Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LogLevel.php',
        'PhabelVendor\\Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerAwareInterface.php',
        'PhabelVendor\\Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerAwareTrait.php',
        'PhabelVendor\\Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerInterface.php',
        'PhabelVendor\\Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/LoggerTrait.php',
        'PhabelVendor\\Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/NullLogger.php',
        'PhabelVendor\\Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/DummyTest.php',
        'PhabelVendor\\Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
        'PhabelVendor\\Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/psr/log/Psr/Log/Test/TestLogger.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Application' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Application.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Attribute\\AsCommand' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Attribute/AsCommand.php',
        'PhabelVendor\\Symfony\\Component\\Console\\CI\\GithubActionReporter' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/CI/GithubActionReporter.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Color' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Color.php',
        'PhabelVendor\\Symfony\\Component\\Console\\CommandLoader\\CommandLoaderInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/CommandLoaderInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\CommandLoader\\ContainerCommandLoader' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/ContainerCommandLoader.php',
        'PhabelVendor\\Symfony\\Component\\Console\\CommandLoader\\FactoryCommandLoader' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/CommandLoader/FactoryCommandLoader.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Command\\Command' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Command/Command.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Command\\CompleteCommand' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Command/CompleteCommand.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Command\\DumpCompletionCommand' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Command/DumpCompletionCommand.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Command\\HelpCommand' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Command/HelpCommand.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Command\\LazyCommand' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Command/LazyCommand.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Command\\ListCommand' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Command/ListCommand.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Command\\LockableTrait' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Command/LockableTrait.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Command\\SignalableCommandInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Command/SignalableCommandInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Completion\\CompletionInput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Completion/CompletionInput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Completion\\CompletionSuggestions' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Completion/CompletionSuggestions.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Completion\\Output\\BashCompletionOutput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Completion/Output/BashCompletionOutput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Completion\\Output\\CompletionOutputInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Completion/Output/CompletionOutputInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Completion\\Suggestion' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Completion/Suggestion.php',
        'PhabelVendor\\Symfony\\Component\\Console\\ConsoleEvents' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/ConsoleEvents.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Cursor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Cursor.php',
        'PhabelVendor\\Symfony\\Component\\Console\\DependencyInjection\\AddConsoleCommandPass' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/DependencyInjection/AddConsoleCommandPass.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\ApplicationDescription' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/ApplicationDescription.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\Descriptor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/Descriptor.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\DescriptorInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/DescriptorInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\JsonDescriptor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/JsonDescriptor.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\MarkdownDescriptor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/MarkdownDescriptor.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\TextDescriptor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/TextDescriptor.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Descriptor\\XmlDescriptor' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Descriptor/XmlDescriptor.php',
        'PhabelVendor\\Symfony\\Component\\Console\\EventListener\\ErrorListener' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/EventListener/ErrorListener.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleCommandEvent' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleCommandEvent.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleErrorEvent' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleErrorEvent.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleEvent' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleEvent.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleSignalEvent' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleSignalEvent.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Event\\ConsoleTerminateEvent' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Event/ConsoleTerminateEvent.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Exception\\CommandNotFoundException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Exception/CommandNotFoundException.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Exception/ExceptionInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Exception/InvalidArgumentException.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Exception\\InvalidOptionException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Exception/InvalidOptionException.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Exception\\LogicException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Exception/LogicException.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Exception\\MissingInputException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Exception/MissingInputException.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Exception\\NamespaceNotFoundException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Exception/NamespaceNotFoundException.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Exception\\RuntimeException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Exception/RuntimeException.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatter' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/NullOutputFormatter.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\NullOutputFormatterStyle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/NullOutputFormatterStyle.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatter' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatter.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyle.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyleInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\OutputFormatterStyleStack' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/OutputFormatterStyleStack.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Formatter\\WrappableOutputFormatterInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Formatter/WrappableOutputFormatterInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\DebugFormatterHelper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/DebugFormatterHelper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\DescriptorHelper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/DescriptorHelper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\Dumper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/Dumper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\FormatterHelper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/FormatterHelper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\Helper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/Helper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\HelperInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/HelperInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\HelperSet' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/HelperSet.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\InputAwareHelper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/InputAwareHelper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\ProcessHelper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/ProcessHelper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\ProgressBar' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/ProgressBar.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\ProgressIndicator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/ProgressIndicator.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\QuestionHelper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/QuestionHelper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\SymfonyQuestionHelper' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/SymfonyQuestionHelper.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\Table' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/Table.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableCell' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableCell.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableCellStyle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableCellStyle.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableRows' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableRows.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableSeparator' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableSeparator.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Helper\\TableStyle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Helper/TableStyle.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\ArgvInput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/ArgvInput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\ArrayInput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/ArrayInput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\Input' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/Input.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputArgument' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputArgument.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputAwareInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputAwareInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputDefinition' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputDefinition.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\InputOption' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/InputOption.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\StreamableInputInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/StreamableInputInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Input\\StringInput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Input/StringInput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Logger\\ConsoleLogger' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Logger/ConsoleLogger.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\BufferedOutput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/BufferedOutput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\ConsoleOutput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleOutput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\ConsoleOutputInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleOutputInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\ConsoleSectionOutput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/ConsoleSectionOutput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\NullOutput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/NullOutput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\Output' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/Output.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\OutputInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/OutputInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\StreamOutput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/StreamOutput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Output\\TrimmedBufferOutput' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Output/TrimmedBufferOutput.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Question\\ChoiceQuestion' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Question/ChoiceQuestion.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Question\\ConfirmationQuestion' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Question/ConfirmationQuestion.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Question\\Question' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Question/Question.php',
        'PhabelVendor\\Symfony\\Component\\Console\\SignalRegistry\\SignalRegistry' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/SignalRegistry/SignalRegistry.php',
        'PhabelVendor\\Symfony\\Component\\Console\\SingleCommandApplication' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/SingleCommandApplication.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Style\\OutputStyle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Style/OutputStyle.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Style\\StyleInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Style/StyleInterface.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Style\\SymfonyStyle' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Style/SymfonyStyle.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Terminal' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Terminal.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Tester\\ApplicationTester' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Tester/ApplicationTester.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Tester\\CommandCompletionTester' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Tester/CommandCompletionTester.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Tester\\CommandTester' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Tester/CommandTester.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Tester\\Constraint\\CommandIsSuccessful' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Tester/Constraint/CommandIsSuccessful.php',
        'PhabelVendor\\Symfony\\Component\\Console\\Tester\\TesterTrait' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/console/Tester/TesterTrait.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Exception/ExceptionInterface.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Exception/InvalidArgumentException.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Exception\\LogicException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Exception/LogicException.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Exception\\ProcessFailedException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessFailedException.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Exception\\ProcessSignaledException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessSignaledException.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Exception\\ProcessTimedOutException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Exception/ProcessTimedOutException.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Exception\\RuntimeException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Exception/RuntimeException.php',
        'PhabelVendor\\Symfony\\Component\\Process\\ExecutableFinder' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/ExecutableFinder.php',
        'PhabelVendor\\Symfony\\Component\\Process\\InputStream' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/InputStream.php',
        'PhabelVendor\\Symfony\\Component\\Process\\PhpExecutableFinder' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/PhpExecutableFinder.php',
        'PhabelVendor\\Symfony\\Component\\Process\\PhpProcess' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/PhpProcess.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Pipes\\AbstractPipes' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Pipes/AbstractPipes.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Pipes\\PipesInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Pipes/PipesInterface.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Pipes\\UnixPipes' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Pipes/UnixPipes.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Pipes\\WindowsPipes' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Pipes/WindowsPipes.php',
        'PhabelVendor\\Symfony\\Component\\Process\\Process' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/Process.php',
        'PhabelVendor\\Symfony\\Component\\Process\\ProcessUtils' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/process/ProcessUtils.php',
        'PhabelVendor\\Symfony\\Component\\String\\AbstractString' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/AbstractString.php',
        'PhabelVendor\\Symfony\\Component\\String\\AbstractUnicodeString' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/AbstractUnicodeString.php',
        'PhabelVendor\\Symfony\\Component\\String\\ByteString' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/ByteString.php',
        'PhabelVendor\\Symfony\\Component\\String\\CodePointString' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/CodePointString.php',
        'PhabelVendor\\Symfony\\Component\\String\\Exception\\ExceptionInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Exception/ExceptionInterface.php',
        'PhabelVendor\\Symfony\\Component\\String\\Exception\\InvalidArgumentException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Exception/InvalidArgumentException.php',
        'PhabelVendor\\Symfony\\Component\\String\\Exception\\RuntimeException' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Exception/RuntimeException.php',
        'PhabelVendor\\Symfony\\Component\\String\\Inflector\\EnglishInflector' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Inflector/EnglishInflector.php',
        'PhabelVendor\\Symfony\\Component\\String\\Inflector\\FrenchInflector' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Inflector/FrenchInflector.php',
        'PhabelVendor\\Symfony\\Component\\String\\Inflector\\InflectorInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Inflector/InflectorInterface.php',
        'PhabelVendor\\Symfony\\Component\\String\\LazyString' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/LazyString.php',
        'PhabelVendor\\Symfony\\Component\\String\\Slugger\\AsciiSlugger' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Slugger/AsciiSlugger.php',
        'PhabelVendor\\Symfony\\Component\\String\\Slugger\\SluggerInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/Slugger/SluggerInterface.php',
        'PhabelVendor\\Symfony\\Component\\String\\UnicodeString' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/string/UnicodeString.php',
        'PhabelVendor\\Symfony\\Contracts\\Service\\Attribute\\Required' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts/Attribute/Required.php',
        'PhabelVendor\\Symfony\\Contracts\\Service\\Attribute\\SubscribedService' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts/Attribute/SubscribedService.php',
        'PhabelVendor\\Symfony\\Contracts\\Service\\ResetInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ResetInterface.php',
        'PhabelVendor\\Symfony\\Contracts\\Service\\ServiceLocatorTrait' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceLocatorTrait.php',
        'PhabelVendor\\Symfony\\Contracts\\Service\\ServiceProviderInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceProviderInterface.php',
        'PhabelVendor\\Symfony\\Contracts\\Service\\ServiceSubscriberInterface' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceSubscriberInterface.php',
        'PhabelVendor\\Symfony\\Contracts\\Service\\ServiceSubscriberTrait' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts/ServiceSubscriberTrait.php',
        'PhabelVendor\\Symfony\\Contracts\\Service\\Test\\ServiceLocatorTest' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/service-contracts/Test/ServiceLocatorTest.php',
        'Phabel\\ClassStorage' => __DIR__ . '/..' . '/phabel/phabel/src/ClassStorage.php',
        'Phabel\\ClassStorageProvider' => __DIR__ . '/..' . '/phabel/phabel/src/ClassStorageProvider.php',
        'Phabel\\ClassStorage\\Builder' => __DIR__ . '/..' . '/phabel/phabel/src/ClassStorage/Builder.php',
        'Phabel\\ClassStorage\\FunctionStorage' => __DIR__ . '/..' . '/phabel/phabel/src/ClassStorage/FunctionStorage.php',
        'Phabel\\ClassStorage\\Storage' => __DIR__ . '/..' . '/phabel/phabel/src/ClassStorage/Storage.php',
        'Phabel\\Cli\\EventHandler' => __DIR__ . '/..' . '/phabel/phabel/src/Cli/EventHandler.php',
        'Phabel\\Cli\\Formatter' => __DIR__ . '/..' . '/phabel/phabel/src/Cli/Formatter.php',
        'Phabel\\Cli\\SimpleConsoleLogger' => __DIR__ . '/..' . '/phabel/phabel/src/Cli/SimpleConsoleLogger.php',
        'Phabel\\Commands\\BaseCommand' => __DIR__ . '/..' . '/phabel/phabel/src/Commands/BaseCommand.php',
        'Phabel\\Commands\\Publish' => __DIR__ . '/..' . '/phabel/phabel/src/Commands/Publish.php',
        'Phabel\\Commands\\Run' => __DIR__ . '/..' . '/phabel/phabel/src/Commands/Run.php',
        'Phabel\\Composer\\EventHandler' => __DIR__ . '/..' . '/phabel/phabel/src/Composer/EventHandler.php',
        'Phabel\\Composer\\Plugin' => __DIR__ . '/..' . '/phabel/phabel/src/Composer/Plugin.php',
        'Phabel\\Composer\\Repository' => __DIR__ . '/..' . '/phabel/phabel/src/Composer/Repository.php',
        'Phabel\\Composer\\Transformer' => __DIR__ . '/..' . '/phabel/phabel/src/Composer/Transformer.php',
        'Phabel\\Context' => __DIR__ . '/..' . '/phabel/phabel/src/Context.php',
        'Phabel\\EventHandler' => __DIR__ . '/..' . '/phabel/phabel/src/EventHandler.php',
        'Phabel\\EventHandlerInterface' => __DIR__ . '/..' . '/phabel/phabel/src/EventHandlerInterface.php',
        'Phabel\\Exception' => __DIR__ . '/..' . '/phabel/phabel/src/Exception.php',
        'Phabel\\ExceptionWrapper' => __DIR__ . '/..' . '/phabel/phabel/src/ExceptionWrapper.php',
        'Phabel\\PhpDocParser' => __DIR__ . '/..' . '/phabel/phabel/src/PhpDocParser.php',
        'Phabel\\Plugin' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin.php',
        'Phabel\\PluginCache' => __DIR__ . '/..' . '/phabel/phabel/src/PluginCache.php',
        'Phabel\\PluginGraph\\CircularException' => __DIR__ . '/..' . '/phabel/phabel/src/PluginGraph/CircularException.php',
        'Phabel\\PluginGraph\\Graph' => __DIR__ . '/..' . '/phabel/phabel/src/PluginGraph/Graph.php',
        'Phabel\\PluginGraph\\GraphInternal' => __DIR__ . '/..' . '/phabel/phabel/src/PluginGraph/GraphInternal.php',
        'Phabel\\PluginGraph\\Node' => __DIR__ . '/..' . '/phabel/phabel/src/PluginGraph/Node.php',
        'Phabel\\PluginGraph\\PackageContext' => __DIR__ . '/..' . '/phabel/phabel/src/PluginGraph/PackageContext.php',
        'Phabel\\PluginGraph\\Plugins' => __DIR__ . '/..' . '/phabel/phabel/src/PluginGraph/Plugins.php',
        'Phabel\\PluginGraph\\ResolvedGraph' => __DIR__ . '/..' . '/phabel/phabel/src/PluginGraph/ResolvedGraph.php',
        'Phabel\\PluginInterface' => __DIR__ . '/..' . '/phabel/phabel/src/PluginInterface.php',
        'Phabel\\Plugin\\ClassStoragePlugin' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/ClassStoragePlugin.php',
        'Phabel\\Plugin\\ComposerSanitizer' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/ComposerSanitizer.php',
        'Phabel\\Plugin\\GeneratorDetector' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/GeneratorDetector.php',
        'Phabel\\Plugin\\IssetExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/IssetExpressionFixer.php',
        'Phabel\\Plugin\\ListSplitter' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/ListSplitter.php',
        'Phabel\\Plugin\\Memoization' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/Memoization.php',
        'Phabel\\Plugin\\NestedExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/NestedExpressionFixer.php',
        'Phabel\\Plugin\\NewFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/NewFixer.php',
        'Phabel\\Plugin\\PhabelTestGenerator' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/PhabelTestGenerator.php',
        'Phabel\\Plugin\\ReGenerator' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/ReGenerator.php',
        'Phabel\\Plugin\\ReGeneratorInternal' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/ReGeneratorInternal.php',
        'Phabel\\Plugin\\ReGenerator\\ReGenerator' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/ReGenerator/ReGenerator.php',
        'Phabel\\Plugin\\StmtExprWrapper' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/StmtExprWrapper.php',
        'Phabel\\Plugin\\StringConcatOptimizer' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/StringConcatOptimizer.php',
        'Phabel\\Plugin\\TypeHintReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/TypeHintReplacer.php',
        'Phabel\\Plugin\\VariableFinder' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/VariableFinder.php',
        'Phabel\\Plugin\\YieldDetector' => __DIR__ . '/..' . '/phabel/phabel/src/Plugin/YieldDetector.php',
        'Phabel\\RootNode' => __DIR__ . '/..' . '/phabel/phabel/src/RootNode.php',
        'Phabel\\Target\\Php' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php.php',
        'Phabel\\Target\\Php56\\IssetExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php56/IssetExpressionFixer.php',
        'Phabel\\Target\\Php56\\NestedExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php56/NestedExpressionFixer.php',
        'Phabel\\Target\\Php70\\AnonymousClassReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/AnonymousClassReplacer.php',
        'Phabel\\Target\\Php70\\AnonymousClass\\AnonymousClassInterface' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/AnonymousClass/AnonymousClassInterface.php',
        'Phabel\\Target\\Php70\\DefineArrayReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/DefineArrayReplacer.php',
        'Phabel\\Target\\Php70\\GroupUseReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/GroupUseReplacer.php',
        'Phabel\\Target\\Php70\\IssetExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/IssetExpressionFixer.php',
        'Phabel\\Target\\Php70\\NestedExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/NestedExpressionFixer.php',
        'Phabel\\Target\\Php70\\NullCoalesceReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/NullCoalesceReplacer.php',
        'Phabel\\Target\\Php70\\NullCoalesce\\DisallowedExpressions' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/NullCoalesce/DisallowedExpressions.php',
        'Phabel\\Target\\Php70\\Polyfill' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/Polyfill.php',
        'Phabel\\Target\\Php70\\ReservedNameReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/ReservedNameReplacer.php',
        'Phabel\\Target\\Php70\\ReturnTypeHints' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/ReturnTypeHints.php',
        'Phabel\\Target\\Php70\\ScalarTypeHints' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/ScalarTypeHints.php',
        'Phabel\\Target\\Php70\\SpaceshipOperatorReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/SpaceshipOperatorReplacer.php',
        'Phabel\\Target\\Php70\\StrictTypesDeclareStatementRemover' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/StrictTypesDeclareStatementRemover.php',
        'Phabel\\Target\\Php70\\ThrowableReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php70/ThrowableReplacer.php',
        'Phabel\\Target\\Php71\\ArrayList' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/ArrayList.php',
        'Phabel\\Target\\Php71\\ClassConstantVisibilityModifiersRemover' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/ClassConstantVisibilityModifiersRemover.php',
        'Phabel\\Target\\Php71\\ClosureFromCallable' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/ClosureFromCallable.php',
        'Phabel\\Target\\Php71\\IssetExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/IssetExpressionFixer.php',
        'Phabel\\Target\\Php71\\IterableHint' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/IterableHint.php',
        'Phabel\\Target\\Php71\\ListExpression' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/ListExpression.php',
        'Phabel\\Target\\Php71\\ListKey' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/ListKey.php',
        'Phabel\\Target\\Php71\\MultipleCatchReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/MultipleCatchReplacer.php',
        'Phabel\\Target\\Php71\\NestedExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/NestedExpressionFixer.php',
        'Phabel\\Target\\Php71\\NullableType' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/NullableType.php',
        'Phabel\\Target\\Php71\\Polyfill' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/Polyfill.php',
        'Phabel\\Target\\Php71\\VoidReturnType' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php71/VoidReturnType.php',
        'Phabel\\Target\\Php72\\IssetExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php72/IssetExpressionFixer.php',
        'Phabel\\Target\\Php72\\NestedExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php72/NestedExpressionFixer.php',
        'Phabel\\Target\\Php72\\ObjectTypeHintReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php72/ObjectTypeHintReplacer.php',
        'Phabel\\Target\\Php72\\Polyfill' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php72/Polyfill.php',
        'Phabel\\Target\\Php72\\TypeContravariance' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php72/TypeContravariance.php',
        'Phabel\\Target\\Php72\\TypeContravariance\\TypeContravariance' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php72/TypeContravariance/TypeContravariance.php',
        'Phabel\\Target\\Php73\\IssetExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php73/IssetExpressionFixer.php',
        'Phabel\\Target\\Php73\\ListReference' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php73/ListReference.php',
        'Phabel\\Target\\Php73\\NestedExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php73/NestedExpressionFixer.php',
        'Phabel\\Target\\Php73\\Polyfill' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php73/Polyfill.php',
        'Phabel\\Target\\Php74\\ArrayUnpack' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/ArrayUnpack.php',
        'Phabel\\Target\\Php74\\ArrowClosure' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/ArrowClosure.php',
        'Phabel\\Target\\Php74\\IssetExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/IssetExpressionFixer.php',
        'Phabel\\Target\\Php74\\NestedExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/NestedExpressionFixer.php',
        'Phabel\\Target\\Php74\\NullCoalesceAssignment' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/NullCoalesceAssignment.php',
        'Phabel\\Target\\Php74\\Polyfill' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/Polyfill.php',
        'Phabel\\Target\\Php74\\Serializable' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/Serializable.php',
        'Phabel\\Target\\Php74\\TypeContracovariance' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/TypeContracovariance.php',
        'Phabel\\Target\\Php74\\TypeContracovariance\\TypeContracovariance' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/TypeContracovariance/TypeContracovariance.php',
        'Phabel\\Target\\Php74\\TypedProperty' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php74/TypedProperty.php',
        'Phabel\\Target\\Php80\\CatchEmpty' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/CatchEmpty.php',
        'Phabel\\Target\\Php80\\ClassName' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/ClassName.php',
        'Phabel\\Target\\Php80\\ConstructorPromotion' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/ConstructorPromotion.php',
        'Phabel\\Target\\Php80\\IssetExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/IssetExpressionFixer.php',
        'Phabel\\Target\\Php80\\MatchTransformer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/MatchTransformer.php',
        'Phabel\\Target\\Php80\\NestedExpressionFixer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/NestedExpressionFixer.php',
        'Phabel\\Target\\Php80\\NullSafeTransformer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/NullSafeTransformer.php',
        'Phabel\\Target\\Php80\\NullSafe\\NullSafe' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/NullSafe/NullSafe.php',
        'Phabel\\Target\\Php80\\Polyfill' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/Polyfill.php',
        'Phabel\\Target\\Php80\\StaticMixedFalseReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/StaticMixedFalseReplacer.php',
        'Phabel\\Target\\Php80\\ThrowExprReplacer' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/ThrowExprReplacer.php',
        'Phabel\\Target\\Php80\\UnionTypeStripper' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Php80/UnionTypeStripper.php',
        'Phabel\\Target\\Polyfill' => __DIR__ . '/..' . '/phabel/phabel/src/Target/Polyfill.php',
        'Phabel\\Tasks\\Init' => __DIR__ . '/..' . '/phabel/phabel/src/Tasks/Init.php',
        'Phabel\\Tasks\\Run' => __DIR__ . '/..' . '/phabel/phabel/src/Tasks/Run.php',
        'Phabel\\Tasks\\Shutdown' => __DIR__ . '/..' . '/phabel/phabel/src/Tasks/Shutdown.php',
        'Phabel\\Tools' => __DIR__ . '/..' . '/phabel/phabel/src/Tools.php',
        'Phabel\\Traverser' => __DIR__ . '/..' . '/phabel/phabel/src/Traverser.php',
        'Phabel\\UnresolvedNameException' => __DIR__ . '/..' . '/phabel/phabel/src/UnresolvedNameException.php',
        'Phabel\\VariableContext' => __DIR__ . '/..' . '/phabel/phabel/src/VariableContext.php',
        'Phabel\\Version' => __DIR__ . '/..' . '/phabel/phabel/src/Version.php',
        'Psr\\Http\\Message\\MessageInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-message/src/MessageInterface.php',
        'Psr\\Http\\Message\\RequestFactoryInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-factory/src/RequestFactoryInterface.php',
        'Psr\\Http\\Message\\RequestInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-message/src/RequestInterface.php',
        'Psr\\Http\\Message\\ResponseFactoryInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-factory/src/ResponseFactoryInterface.php',
        'Psr\\Http\\Message\\ResponseInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-message/src/ResponseInterface.php',
        'Psr\\Http\\Message\\ServerRequestFactoryInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-factory/src/ServerRequestFactoryInterface.php',
        'Psr\\Http\\Message\\ServerRequestInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-message/src/ServerRequestInterface.php',
        'Psr\\Http\\Message\\StreamFactoryInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-factory/src/StreamFactoryInterface.php',
        'Psr\\Http\\Message\\StreamInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-message/src/StreamInterface.php',
        'Psr\\Http\\Message\\UploadedFileFactoryInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-factory/src/UploadedFileFactoryInterface.php',
        'Psr\\Http\\Message\\UploadedFileInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-message/src/UploadedFileInterface.php',
        'Psr\\Http\\Message\\UriFactoryInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-factory/src/UriFactoryInterface.php',
        'Psr\\Http\\Message\\UriInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/http-message/src/UriInterface.php',
        'Psr\\Log\\AbstractLogger' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/AbstractLogger.php',
        'Psr\\Log\\InvalidArgumentException' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/InvalidArgumentException.php',
        'Psr\\Log\\LogLevel' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/LogLevel.php',
        'Psr\\Log\\LoggerAwareInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/LoggerAwareInterface.php',
        'Psr\\Log\\LoggerAwareTrait' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/LoggerAwareTrait.php',
        'Psr\\Log\\LoggerInterface' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/LoggerInterface.php',
        'Psr\\Log\\LoggerTrait' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/LoggerTrait.php',
        'Psr\\Log\\NullLogger' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/NullLogger.php',
        'Psr\\Log\\Test\\DummyTest' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/Test/DummyTest.php',
        'Psr\\Log\\Test\\LoggerInterfaceTest' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/Test/LoggerInterfaceTest.php',
        'Psr\\Log\\Test\\TestLogger' => __DIR__ . '/..' . '/phabel-transpiler74.psr/log/Psr/Log/Test/TestLogger.php',
        'Stringable' => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/Stringable.php',
        'Symfony\\Polyfill\\Ctype\\Ctype' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-ctype/Ctype.php',
        'Symfony\\Polyfill\\Intl\\Grapheme\\Grapheme' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-grapheme/Grapheme.php',
        'Symfony\\Polyfill\\Intl\\Normalizer\\Normalizer' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-intl-normalizer/Normalizer.php',
        'Symfony\\Polyfill\\Mbstring\\Mbstring' => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-mbstring/Mbstring.php',
        'Symfony\\Polyfill\\Php73\\Php73' => __DIR__ . '/..' . '/phabel/phabel/vendor-bundle/symfony/polyfill-php73/Php73.php',
        'Symfony\\Polyfill\\Php80\\Php80' => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-php80/Php80.php',
        'UnhandledMatchError' => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/UnhandledMatchError.php',
        'ValueError' => __DIR__ . '/..' . '/phabel-transpiler74.symfony/polyfill-php80/Resources/stubs/ValueError.php',
        'cash\\LRUCache' => __DIR__ . '/..' . '/phabel-transpiler74.cash/lrucache/src/cash/LRUCache.php',
        'danog\\Decoder\\FileId' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/FileId.php',
        'danog\\Decoder\\PhotoSizeSource' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource.php',
        'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceDialogPhoto' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceDialogPhoto.php',
        'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceLegacy' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceLegacy.php',
        'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceStickersetThumbnail' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceStickersetThumbnail.php',
        'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceStickersetThumbnailVersion' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceStickersetThumbnailVersion.php',
        'danog\\Decoder\\PhotoSizeSource\\PhotoSizeSourceThumbnail' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/PhotoSizeSource/PhotoSizeSourceThumbnail.php',
        'danog\\Decoder\\UniqueFileId' => __DIR__ . '/..' . '/phabel-transpiler74.danog/tg-file-decoder/src/UniqueFileId.php',
        'danog\\LibDNSJson\\JsonDecoder' => __DIR__ . '/..' . '/phabel-transpiler74.danog/libdns-json/lib/JsonDecoder.php',
        'danog\\LibDNSJson\\JsonDecoderFactory' => __DIR__ . '/..' . '/phabel-transpiler74.danog/libdns-json/lib/JsonDecoderFactory.php',
        'danog\\LibDNSJson\\QueryEncoder' => __DIR__ . '/..' . '/phabel-transpiler74.danog/libdns-json/lib/QueryEncoder.php',
        'danog\\LibDNSJson\\QueryEncoderFactory' => __DIR__ . '/..' . '/phabel-transpiler74.danog/libdns-json/lib/QueryEncoderFactory.php',
        'danog\\Loop\\Generic\\GenericLoop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Generic/GenericLoop.php',
        'danog\\Loop\\Generic\\PeriodicLoop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Generic/PeriodicLoop.php',
        'danog\\Loop\\Interfaces\\LoopInterface' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Interfaces/LoopInterface.php',
        'danog\\Loop\\Interfaces\\ResumableLoopInterface' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Interfaces/ResumableLoopInterface.php',
        'danog\\Loop\\Interfaces\\SignalLoopInterface' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Interfaces/SignalLoopInterface.php',
        'danog\\Loop\\Loop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Loop.php',
        'danog\\Loop\\ResumableLoop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/ResumableLoop.php',
        'danog\\Loop\\ResumableSignalLoop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/ResumableSignalLoop.php',
        'danog\\Loop\\SignalLoop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/SignalLoop.php',
        'danog\\Loop\\Traits\\Loop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Traits/Loop.php',
        'danog\\Loop\\Traits\\ResumableLoop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Traits/ResumableLoop.php',
        'danog\\Loop\\Traits\\SignalLoop' => __DIR__ . '/..' . '/phabel-transpiler74.danog/loop/lib/Traits/SignalLoop.php',
        'danog\\MadelineProto\\API' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/API.php',
        'danog\\MadelineProto\\APIFactory' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/APIFactory.php',
        'danog\\MadelineProto\\APIWrapper' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/APIWrapper.php',
        'danog\\MadelineProto\\AbstractAPIFactory' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/AbstractAPIFactory.php',
        'danog\\MadelineProto\\AnnotationsBuilder' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/AnnotationsBuilder.php',
        'danog\\MadelineProto\\ApiWrappers\\Start' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/ApiWrappers/Start.php',
        'danog\\MadelineProto\\ApiWrappers\\Templates' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/ApiWrappers/Templates.php',
        'danog\\MadelineProto\\Async\\AsyncConstruct' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Async/AsyncConstruct.php',
        'danog\\MadelineProto\\Bug74586Exception' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Bug74586Exception.php',
        'danog\\MadelineProto\\Connection' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Connection.php',
        'danog\\MadelineProto\\ContextConnector' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/ContextConnector.php',
        'danog\\MadelineProto\\Conversion' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Conversion.php',
        'danog\\MadelineProto\\Coroutine' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Coroutine.php',
        'danog\\MadelineProto\\DataCenter' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/DataCenter.php',
        'danog\\MadelineProto\\DataCenterConnection' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/DataCenterConnection.php',
        'danog\\MadelineProto\\Db\\ArrayCacheTrait' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/ArrayCacheTrait.php',
        'danog\\MadelineProto\\Db\\DbArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/DbArray.php',
        'danog\\MadelineProto\\Db\\DbPropertiesFactory' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/DbPropertiesFactory.php',
        'danog\\MadelineProto\\Db\\DbPropertiesTrait' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/DbPropertiesTrait.php',
        'danog\\MadelineProto\\Db\\DbType' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/DbType.php',
        'danog\\MadelineProto\\Db\\DriverArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/DriverArray.php',
        'danog\\MadelineProto\\Db\\Driver\\Mysql' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Mysql.php',
        'danog\\MadelineProto\\Db\\Driver\\Postgres' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Postgres.php',
        'danog\\MadelineProto\\Db\\Driver\\Redis' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/Driver/Redis.php',
        'danog\\MadelineProto\\Db\\MemoryArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/MemoryArray.php',
        'danog\\MadelineProto\\Db\\MysqlArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/MysqlArray.php',
        'danog\\MadelineProto\\Db\\NullCache\\MysqlArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/MysqlArray.php',
        'danog\\MadelineProto\\Db\\NullCache\\NullCacheTrait' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/NullCacheTrait.php',
        'danog\\MadelineProto\\Db\\NullCache\\PostgresArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/PostgresArray.php',
        'danog\\MadelineProto\\Db\\NullCache\\RedisArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/NullCache/RedisArray.php',
        'danog\\MadelineProto\\Db\\PostgresArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/PostgresArray.php',
        'danog\\MadelineProto\\Db\\RedisArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/RedisArray.php',
        'danog\\MadelineProto\\Db\\SqlArray' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Db/SqlArray.php',
        'danog\\MadelineProto\\DoHConnector' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/DoHConnector.php',
        'danog\\MadelineProto\\DocsBuilder' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/DocsBuilder.php',
        'danog\\MadelineProto\\DocsBuilder\\Constructors' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/DocsBuilder/Constructors.php',
        'danog\\MadelineProto\\DocsBuilder\\Methods' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/DocsBuilder/Methods.php',
        'danog\\MadelineProto\\EventHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/EventHandler.php',
        'danog\\MadelineProto\\Exception' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Exception.php',
        'danog\\MadelineProto\\FileCallback' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/FileCallback.php',
        'danog\\MadelineProto\\FileCallbackInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/FileCallbackInterface.php',
        'danog\\MadelineProto\\Files\\Server' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Files/Server.php',
        'danog\\MadelineProto\\GarbageCollector' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/GarbageCollector.php',
        'danog\\MadelineProto\\InternalDoc' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/InternalDoc.php',
        'danog\\MadelineProto\\Ipc\\Client' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Client.php',
        'danog\\MadelineProto\\Ipc\\ClientAbstract' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/ClientAbstract.php',
        'danog\\MadelineProto\\Ipc\\ExitFailure' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/ExitFailure.php',
        'danog\\MadelineProto\\Ipc\\IpcState' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/IpcState.php',
        'danog\\MadelineProto\\Ipc\\Runner\\ProcessRunner' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/ProcessRunner.php',
        'danog\\MadelineProto\\Ipc\\Runner\\RunnerAbstract' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/RunnerAbstract.php',
        'danog\\MadelineProto\\Ipc\\Runner\\WebRunner' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/WebRunner.php',
        'danog\\MadelineProto\\Ipc\\Server' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Server.php',
        'danog\\MadelineProto\\Ipc\\ServerCallback' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/ServerCallback.php',
        'danog\\MadelineProto\\Ipc\\Wrapper' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper.php',
        'danog\\MadelineProto\\Ipc\\Wrapper\\FileCallback' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/FileCallback.php',
        'danog\\MadelineProto\\Ipc\\Wrapper\\InputStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/InputStream.php',
        'danog\\MadelineProto\\Ipc\\Wrapper\\Obj' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/Obj.php',
        'danog\\MadelineProto\\Ipc\\Wrapper\\OutputStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/OutputStream.php',
        'danog\\MadelineProto\\Ipc\\Wrapper\\SeekableInputStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableInputStream.php',
        'danog\\MadelineProto\\Ipc\\Wrapper\\SeekableOutputStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableOutputStream.php',
        'danog\\MadelineProto\\Ipc\\Wrapper\\SeekableTrait' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/SeekableTrait.php',
        'danog\\MadelineProto\\Ipc\\Wrapper\\WrapMethodTrait' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Ipc/Wrapper/WrapMethodTrait.php',
        'danog\\MadelineProto\\Lang' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Lang.php',
        'danog\\MadelineProto\\LightState' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/LightState.php',
        'danog\\MadelineProto\\Logger' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Logger.php',
        'danog\\MadelineProto\\Loop\\APILoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/APILoop.php',
        'danog\\MadelineProto\\Loop\\Connection\\CheckLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/CheckLoop.php',
        'danog\\MadelineProto\\Loop\\Connection\\CleanupLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/CleanupLoop.php',
        'danog\\MadelineProto\\Loop\\Connection\\Common' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/Common.php',
        'danog\\MadelineProto\\Loop\\Connection\\HttpWaitLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/HttpWaitLoop.php',
        'danog\\MadelineProto\\Loop\\Connection\\PingLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/PingLoop.php',
        'danog\\MadelineProto\\Loop\\Connection\\ReadLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/ReadLoop.php',
        'danog\\MadelineProto\\Loop\\Connection\\WriteLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Connection/WriteLoop.php',
        'danog\\MadelineProto\\Loop\\Generic\\GenericLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/GenericLoop.php',
        'danog\\MadelineProto\\Loop\\Generic\\PeriodicLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/PeriodicLoop.php',
        'danog\\MadelineProto\\Loop\\Generic\\PeriodicLoopInternal' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Generic/PeriodicLoopInternal.php',
        'danog\\MadelineProto\\Loop\\InternalLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/InternalLoop.php',
        'danog\\MadelineProto\\Loop\\LoggerLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/LoggerLoop.php',
        'danog\\MadelineProto\\Loop\\Update\\FeedLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Update/FeedLoop.php',
        'danog\\MadelineProto\\Loop\\Update\\SecretFeedLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Update/SecretFeedLoop.php',
        'danog\\MadelineProto\\Loop\\Update\\SeqLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Update/SeqLoop.php',
        'danog\\MadelineProto\\Loop\\Update\\UpdateLoop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Loop/Update/UpdateLoop.php',
        'danog\\MadelineProto\\Lua' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Lua.php',
        'danog\\MadelineProto\\MTProto' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProto.php',
        'danog\\MadelineProto\\MTProtoSession\\AckHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/AckHandler.php',
        'danog\\MadelineProto\\MTProtoSession\\CallHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/CallHandler.php',
        'danog\\MadelineProto\\MTProtoSession\\MsgIdHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/MsgIdHandler.php',
        'danog\\MadelineProto\\MTProtoSession\\MsgIdHandler\\MsgIdHandler64' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/MsgIdHandler/MsgIdHandler64.php',
        'danog\\MadelineProto\\MTProtoSession\\Reliable' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/Reliable.php',
        'danog\\MadelineProto\\MTProtoSession\\ResponseHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/ResponseHandler.php',
        'danog\\MadelineProto\\MTProtoSession\\SeqNoHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/SeqNoHandler.php',
        'danog\\MadelineProto\\MTProtoSession\\Session' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoSession/Session.php',
        'danog\\MadelineProto\\MTProtoTools\\AuthKeyHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/AuthKeyHandler.php',
        'danog\\MadelineProto\\MTProtoTools\\CallHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/CallHandler.php',
        'danog\\MadelineProto\\MTProtoTools\\CombinedUpdatesState' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/CombinedUpdatesState.php',
        'danog\\MadelineProto\\MTProtoTools\\Crypt' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt.php',
        'danog\\MadelineProto\\MTProtoTools\\Crypt\\IGE' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGE.php',
        'danog\\MadelineProto\\MTProtoTools\\Crypt\\IGEOpenssl' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGEOpenssl.php',
        'danog\\MadelineProto\\MTProtoTools\\Crypt\\IGEPhpseclib' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Crypt/IGEPhpseclib.php',
        'danog\\MadelineProto\\MTProtoTools\\Files' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/Files.php',
        'danog\\MadelineProto\\MTProtoTools\\FilesLogic' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/FilesLogic.php',
        'danog\\MadelineProto\\MTProtoTools\\MinDatabase' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/MinDatabase.php',
        'danog\\MadelineProto\\MTProtoTools\\PasswordCalculator' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/PasswordCalculator.php',
        'danog\\MadelineProto\\MTProtoTools\\PeerHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/PeerHandler.php',
        'danog\\MadelineProto\\MTProtoTools\\ReferenceDatabase' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/ReferenceDatabase.php',
        'danog\\MadelineProto\\MTProtoTools\\ResponseInfo' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/ResponseInfo.php',
        'danog\\MadelineProto\\MTProtoTools\\UpdateHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/UpdateHandler.php',
        'danog\\MadelineProto\\MTProtoTools\\UpdatesState' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProtoTools/UpdatesState.php',
        'danog\\MadelineProto\\MTProto\\AuthKey' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProto/AuthKey.php',
        'danog\\MadelineProto\\MTProto\\Container' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProto/Container.php',
        'danog\\MadelineProto\\MTProto\\IncomingMessage' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProto/IncomingMessage.php',
        'danog\\MadelineProto\\MTProto\\Message' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProto/Message.php',
        'danog\\MadelineProto\\MTProto\\OutgoingMessage' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProto/OutgoingMessage.php',
        'danog\\MadelineProto\\MTProto\\PermAuthKey' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProto/PermAuthKey.php',
        'danog\\MadelineProto\\MTProto\\TempAuthKey' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MTProto/TempAuthKey.php',
        'danog\\MadelineProto\\Magic' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Magic.php',
        'danog\\MadelineProto\\MyTelegramOrgWrapper' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/MyTelegramOrgWrapper.php',
        'danog\\MadelineProto\\NothingInTheSocketException' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/NothingInTheSocketException.php',
        'danog\\MadelineProto\\PTSException' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/PTSException.php',
        'danog\\MadelineProto\\PsrLogger' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/PsrLogger.php',
        'danog\\MadelineProto\\RPCErrorException' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/RPCErrorException.php',
        'danog\\MadelineProto\\RSA' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/RSA.php',
        'danog\\MadelineProto\\ResponseException' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/ResponseException.php',
        'danog\\MadelineProto\\SecretChats\\AuthKeyHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/SecretChats/AuthKeyHandler.php',
        'danog\\MadelineProto\\SecretChats\\MessageHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/SecretChats/MessageHandler.php',
        'danog\\MadelineProto\\SecretChats\\ResponseHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/SecretChats/ResponseHandler.php',
        'danog\\MadelineProto\\SecretChats\\SeqNoHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/SecretChats/SeqNoHandler.php',
        'danog\\MadelineProto\\SecurityException' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/SecurityException.php',
        'danog\\MadelineProto\\Serialization' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Serialization.php',
        'danog\\MadelineProto\\SessionPaths' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/SessionPaths.php',
        'danog\\MadelineProto\\Settings' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings.php',
        'danog\\MadelineProto\\SettingsAbstract' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/SettingsAbstract.php',
        'danog\\MadelineProto\\SettingsEmpty' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/SettingsEmpty.php',
        'danog\\MadelineProto\\Settings\\AppInfo' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/AppInfo.php',
        'danog\\MadelineProto\\Settings\\Auth' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Auth.php',
        'danog\\MadelineProto\\Settings\\Connection' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Connection.php',
        'danog\\MadelineProto\\Settings\\DatabaseAbstract' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/DatabaseAbstract.php',
        'danog\\MadelineProto\\Settings\\Database\\DatabaseAbstract' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/DatabaseAbstract.php',
        'danog\\MadelineProto\\Settings\\Database\\Memory' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Memory.php',
        'danog\\MadelineProto\\Settings\\Database\\Mysql' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Mysql.php',
        'danog\\MadelineProto\\Settings\\Database\\Postgres' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Postgres.php',
        'danog\\MadelineProto\\Settings\\Database\\Redis' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/Redis.php',
        'danog\\MadelineProto\\Settings\\Database\\SqlAbstract' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Database/SqlAbstract.php',
        'danog\\MadelineProto\\Settings\\Files' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Files.php',
        'danog\\MadelineProto\\Settings\\Ipc' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Ipc.php',
        'danog\\MadelineProto\\Settings\\Logger' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Logger.php',
        'danog\\MadelineProto\\Settings\\Peer' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Peer.php',
        'danog\\MadelineProto\\Settings\\Pwr' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Pwr.php',
        'danog\\MadelineProto\\Settings\\RPC' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/RPC.php',
        'danog\\MadelineProto\\Settings\\SecretChats' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/SecretChats.php',
        'danog\\MadelineProto\\Settings\\Serialization' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Serialization.php',
        'danog\\MadelineProto\\Settings\\TLSchema' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/TLSchema.php',
        'danog\\MadelineProto\\Settings\\Templates' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/Templates.php',
        'danog\\MadelineProto\\Settings\\VoIP' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Settings/VoIP.php',
        'danog\\MadelineProto\\Shutdown' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Shutdown.php',
        'danog\\MadelineProto\\Snitch' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Snitch.php',
        'danog\\MadelineProto\\StrTools' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/StrTools.php',
        'danog\\MadelineProto\\Stream\\ADNLTransport\\ADNLStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/ADNLTransport/ADNLStream.php',
        'danog\\MadelineProto\\Stream\\Async\\Buffer' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Async/Buffer.php',
        'danog\\MadelineProto\\Stream\\Async\\BufferedStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Async/BufferedStream.php',
        'danog\\MadelineProto\\Stream\\Async\\RawStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Async/RawStream.php',
        'danog\\MadelineProto\\Stream\\BufferInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/BufferInterface.php',
        'danog\\MadelineProto\\Stream\\BufferedProxyStreamInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/BufferedProxyStreamInterface.php',
        'danog\\MadelineProto\\Stream\\BufferedStreamInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/BufferedStreamInterface.php',
        'danog\\MadelineProto\\Stream\\Common\\BufferedRawStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/BufferedRawStream.php',
        'danog\\MadelineProto\\Stream\\Common\\CtrStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/CtrStream.php',
        'danog\\MadelineProto\\Stream\\Common\\FileBufferedStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/FileBufferedStream.php',
        'danog\\MadelineProto\\Stream\\Common\\HashedBufferedStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/HashedBufferedStream.php',
        'danog\\MadelineProto\\Stream\\Common\\SimpleBufferedRawStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/SimpleBufferedRawStream.php',
        'danog\\MadelineProto\\Stream\\Common\\UdpBufferedStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Common/UdpBufferedStream.php',
        'danog\\MadelineProto\\Stream\\ConnectionContext' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/ConnectionContext.php',
        'danog\\MadelineProto\\Stream\\MTProtoBufferInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoBufferInterface.php',
        'danog\\MadelineProto\\Stream\\MTProtoTransport\\AbridgedStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/AbridgedStream.php',
        'danog\\MadelineProto\\Stream\\MTProtoTransport\\FullStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/FullStream.php',
        'danog\\MadelineProto\\Stream\\MTProtoTransport\\HttpStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/HttpStream.php',
        'danog\\MadelineProto\\Stream\\MTProtoTransport\\HttpsStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/HttpsStream.php',
        'danog\\MadelineProto\\Stream\\MTProtoTransport\\IntermediatePaddedStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/IntermediatePaddedStream.php',
        'danog\\MadelineProto\\Stream\\MTProtoTransport\\IntermediateStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/IntermediateStream.php',
        'danog\\MadelineProto\\Stream\\MTProtoTransport\\ObfuscatedStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/MTProtoTransport/ObfuscatedStream.php',
        'danog\\MadelineProto\\Stream\\Ogg\\Ogg' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Ogg/Ogg.php',
        'danog\\MadelineProto\\Stream\\ProxyStreamInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/ProxyStreamInterface.php',
        'danog\\MadelineProto\\Stream\\Proxy\\HttpProxy' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Proxy/HttpProxy.php',
        'danog\\MadelineProto\\Stream\\Proxy\\SocksProxy' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Proxy/SocksProxy.php',
        'danog\\MadelineProto\\Stream\\RawProxyStreamInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/RawProxyStreamInterface.php',
        'danog\\MadelineProto\\Stream\\RawStreamInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/RawStreamInterface.php',
        'danog\\MadelineProto\\Stream\\ReadBufferInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/ReadBufferInterface.php',
        'danog\\MadelineProto\\Stream\\StreamInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/StreamInterface.php',
        'danog\\MadelineProto\\Stream\\Transport\\DefaultStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/DefaultStream.php',
        'danog\\MadelineProto\\Stream\\Transport\\PremadeStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/PremadeStream.php',
        'danog\\MadelineProto\\Stream\\Transport\\WsStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/WsStream.php',
        'danog\\MadelineProto\\Stream\\Transport\\WssStream' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/Transport/WssStream.php',
        'danog\\MadelineProto\\Stream\\WriteBufferInterface' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Stream/WriteBufferInterface.php',
        'danog\\MadelineProto\\TL\\Conversion\\BotAPI' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/BotAPI.php',
        'danog\\MadelineProto\\TL\\Conversion\\BotAPIFiles' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/BotAPIFiles.php',
        'danog\\MadelineProto\\TL\\Conversion\\Exception' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/Exception.php',
        'danog\\MadelineProto\\TL\\Conversion\\Extension' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/Extension.php',
        'danog\\MadelineProto\\TL\\Conversion\\TD' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/Conversion/TD.php',
        'danog\\MadelineProto\\TL\\Exception' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/Exception.php',
        'danog\\MadelineProto\\TL\\PrettyException' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/PrettyException.php',
        'danog\\MadelineProto\\TL\\TL' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/TL.php',
        'danog\\MadelineProto\\TL\\TLCallback' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/TLCallback.php',
        'danog\\MadelineProto\\TL\\TLConstructors' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/TLConstructors.php',
        'danog\\MadelineProto\\TL\\TLMethods' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/TLMethods.php',
        'danog\\MadelineProto\\TL\\TLParams' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/TLParams.php',
        'danog\\MadelineProto\\TL\\Types\\Button' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/Types/Button.php',
        'danog\\MadelineProto\\TL\\Types\\Bytes' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TL/Types/Bytes.php',
        'danog\\MadelineProto\\TON\\ADNLConnection' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TON/ADNLConnection.php',
        'danog\\MadelineProto\\TON\\API' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TON/API.php',
        'danog\\MadelineProto\\TON\\APIFactory' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TON/APIFactory.php',
        'danog\\MadelineProto\\TON\\InternalDoc' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TON/InternalDoc.php',
        'danog\\MadelineProto\\TON\\Lite' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/TON/Lite.php',
        'danog\\MadelineProto\\Tools' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Tools.php',
        'danog\\MadelineProto\\VoIP' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/VoIP.php',
        'danog\\MadelineProto\\VoIPServerConfig' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/VoIPServerConfig.php',
        'danog\\MadelineProto\\VoIP\\AckHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/VoIP/AckHandler.php',
        'danog\\MadelineProto\\VoIP\\AuthKeyHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/VoIP/AuthKeyHandler.php',
        'danog\\MadelineProto\\VoIP\\Endpoint' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/VoIP/Endpoint.php',
        'danog\\MadelineProto\\VoIP\\MessageHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/VoIP/MessageHandler.php',
        'danog\\MadelineProto\\Wrappers\\Ads' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Ads.php',
        'danog\\MadelineProto\\Wrappers\\Button' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Button.php',
        'danog\\MadelineProto\\Wrappers\\Callback' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Callback.php',
        'danog\\MadelineProto\\Wrappers\\DialogHandler' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/DialogHandler.php',
        'danog\\MadelineProto\\Wrappers\\Events' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Events.php',
        'danog\\MadelineProto\\Wrappers\\Login' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Login.php',
        'danog\\MadelineProto\\Wrappers\\Loop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Loop.php',
        'danog\\MadelineProto\\Wrappers\\Noop' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Noop.php',
        'danog\\MadelineProto\\Wrappers\\Start' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Start.php',
        'danog\\MadelineProto\\Wrappers\\TOS' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/TOS.php',
        'danog\\MadelineProto\\Wrappers\\Templates' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Templates.php',
        'danog\\MadelineProto\\Wrappers\\Webhook' => __DIR__ . '/..' . '/danog/madelineproto/src/danog/MadelineProto/Wrappers/Webhook.php',
        'danog\\PlaceHolder' => __DIR__ . '/..' . '/phabel-transpiler74.danog/magicalserializer/src/danog/PlaceHolder.php',
        'danog\\PrimeModule' => __DIR__ . '/..' . '/phabel-transpiler74.danog/primemodule/lib/danog/PrimeModule.php',
        'danog\\Serializable' => __DIR__ . '/..' . '/phabel-transpiler74.danog/magicalserializer/src/danog/Serializable.php',
        'danog\\Serialization' => __DIR__ . '/..' . '/phabel-transpiler74.danog/magicalserializer/src/danog/Serialization.php',
        'phpseclib3\\Common\\Functions\\Strings' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Common/Functions/Strings.php',
        'phpseclib3\\Crypt\\AES' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/AES.php',
        'phpseclib3\\Crypt\\Blowfish' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Blowfish.php',
        'phpseclib3\\Crypt\\ChaCha20' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/ChaCha20.php',
        'phpseclib3\\Crypt\\Common\\AsymmetricKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/AsymmetricKey.php',
        'phpseclib3\\Crypt\\Common\\BlockCipher' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/BlockCipher.php',
        'phpseclib3\\Crypt\\Common\\Formats\\Keys\\OpenSSH' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/OpenSSH.php',
        'phpseclib3\\Crypt\\Common\\Formats\\Keys\\PKCS' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS.php',
        'phpseclib3\\Crypt\\Common\\Formats\\Keys\\PKCS1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS1.php',
        'phpseclib3\\Crypt\\Common\\Formats\\Keys\\PKCS8' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PKCS8.php',
        'phpseclib3\\Crypt\\Common\\Formats\\Keys\\PuTTY' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Keys/PuTTY.php',
        'phpseclib3\\Crypt\\Common\\Formats\\Signature\\Raw' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Formats/Signature/Raw.php',
        'phpseclib3\\Crypt\\Common\\PrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/PrivateKey.php',
        'phpseclib3\\Crypt\\Common\\PublicKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/PublicKey.php',
        'phpseclib3\\Crypt\\Common\\StreamCipher' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/StreamCipher.php',
        'phpseclib3\\Crypt\\Common\\SymmetricKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/SymmetricKey.php',
        'phpseclib3\\Crypt\\Common\\Traits\\Fingerprint' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/Fingerprint.php',
        'phpseclib3\\Crypt\\Common\\Traits\\PasswordProtected' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Common/Traits/PasswordProtected.php',
        'phpseclib3\\Crypt\\DES' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DES.php',
        'phpseclib3\\Crypt\\DH' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH.php',
        'phpseclib3\\Crypt\\DH\\Formats\\Keys\\PKCS1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS1.php',
        'phpseclib3\\Crypt\\DH\\Formats\\Keys\\PKCS8' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Formats/Keys/PKCS8.php',
        'phpseclib3\\Crypt\\DH\\Parameters' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/Parameters.php',
        'phpseclib3\\Crypt\\DH\\PrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/PrivateKey.php',
        'phpseclib3\\Crypt\\DH\\PublicKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DH/PublicKey.php',
        'phpseclib3\\Crypt\\DSA' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\OpenSSH' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/OpenSSH.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\PKCS1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS1.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\PKCS8' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PKCS8.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\PuTTY' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/PuTTY.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\Raw' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/Raw.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\XML' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Keys/XML.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Signature\\ASN1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/ASN1.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Signature\\Raw' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/Raw.php',
        'phpseclib3\\Crypt\\DSA\\Formats\\Signature\\SSH2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Formats/Signature/SSH2.php',
        'phpseclib3\\Crypt\\DSA\\Parameters' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/Parameters.php',
        'phpseclib3\\Crypt\\DSA\\PrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/PrivateKey.php',
        'phpseclib3\\Crypt\\DSA\\PublicKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/DSA/PublicKey.php',
        'phpseclib3\\Crypt\\EC' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC.php',
        'phpseclib3\\Crypt\\EC\\BaseCurves\\Base' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Base.php',
        'phpseclib3\\Crypt\\EC\\BaseCurves\\Binary' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Binary.php',
        'phpseclib3\\Crypt\\EC\\BaseCurves\\KoblitzPrime' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/KoblitzPrime.php',
        'phpseclib3\\Crypt\\EC\\BaseCurves\\Montgomery' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Montgomery.php',
        'phpseclib3\\Crypt\\EC\\BaseCurves\\Prime' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/Prime.php',
        'phpseclib3\\Crypt\\EC\\BaseCurves\\TwistedEdwards' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/BaseCurves/TwistedEdwards.php',
        'phpseclib3\\Crypt\\EC\\Curves\\Curve25519' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve25519.php',
        'phpseclib3\\Crypt\\EC\\Curves\\Curve448' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Curve448.php',
        'phpseclib3\\Crypt\\EC\\Curves\\Ed25519' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed25519.php',
        'phpseclib3\\Crypt\\EC\\Curves\\Ed448' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/Ed448.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP160r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP160t1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP160t1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP192r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP192t1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP192t1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP224r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP224t1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP224t1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP256r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP256t1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP256t1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP320r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP320t1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP320t1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP384r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP384t1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP384t1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP512r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\brainpoolP512t1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/brainpoolP512t1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistb233' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb233.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistb409' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistb409.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistk163' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk163.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistk233' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk233.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistk283' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk283.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistk409' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistk409.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistp192' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp192.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistp224' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp224.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistp256' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp256.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistp384' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp384.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistp521' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistp521.php',
        'phpseclib3\\Crypt\\EC\\Curves\\nistt571' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/nistt571.php',
        'phpseclib3\\Crypt\\EC\\Curves\\prime192v1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\prime192v2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\prime192v3' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime192v3.php',
        'phpseclib3\\Crypt\\EC\\Curves\\prime239v1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\prime239v2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\prime239v3' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime239v3.php',
        'phpseclib3\\Crypt\\EC\\Curves\\prime256v1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/prime256v1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp112r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp112r2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp112r2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp128r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp128r2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp128r2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp160k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp160r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp160r2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp160r2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp192k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp192r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp192r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp224k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp224r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp224r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp256k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp256r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp256r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp384r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp384r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\secp521r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/secp521r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect113r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect113r2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect113r2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect131r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect131r2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect131r2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect163k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect163r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect163r2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect163r2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect193r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect193r2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect193r2.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect233k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect233r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect233r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect239k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect239k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect283k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect283r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect283r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect409k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect409r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect409r1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect571k1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571k1.php',
        'phpseclib3\\Crypt\\EC\\Curves\\sect571r1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Curves/sect571r1.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\Common' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/Common.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\MontgomeryPrivate' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPrivate.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\MontgomeryPublic' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/MontgomeryPublic.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\OpenSSH' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/OpenSSH.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\PKCS1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS1.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\PKCS8' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PKCS8.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\PuTTY' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/PuTTY.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\XML' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/XML.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Keys\\libsodium' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Keys/libsodium.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Signature\\ASN1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/ASN1.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Signature\\Raw' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/Raw.php',
        'phpseclib3\\Crypt\\EC\\Formats\\Signature\\SSH2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Formats/Signature/SSH2.php',
        'phpseclib3\\Crypt\\EC\\Parameters' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/Parameters.php',
        'phpseclib3\\Crypt\\EC\\PrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/PrivateKey.php',
        'phpseclib3\\Crypt\\EC\\PublicKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/EC/PublicKey.php',
        'phpseclib3\\Crypt\\Hash' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Hash.php',
        'phpseclib3\\Crypt\\PublicKeyLoader' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/PublicKeyLoader.php',
        'phpseclib3\\Crypt\\RC2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RC2.php',
        'phpseclib3\\Crypt\\RC4' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RC4.php',
        'phpseclib3\\Crypt\\RSA' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA.php',
        'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\MSBLOB' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/MSBLOB.php',
        'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\OpenSSH' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/OpenSSH.php',
        'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\PKCS1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS1.php',
        'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\PKCS8' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PKCS8.php',
        'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\PSS' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PSS.php',
        'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\PuTTY' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/PuTTY.php',
        'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\Raw' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/Raw.php',
        'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\XML' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/Formats/Keys/XML.php',
        'phpseclib3\\Crypt\\RSA\\PrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/PrivateKey.php',
        'phpseclib3\\Crypt\\RSA\\PublicKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/RSA/PublicKey.php',
        'phpseclib3\\Crypt\\Random' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Random.php',
        'phpseclib3\\Crypt\\Rijndael' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Rijndael.php',
        'phpseclib3\\Crypt\\Salsa20' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Salsa20.php',
        'phpseclib3\\Crypt\\TripleDES' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/TripleDES.php',
        'phpseclib3\\Crypt\\Twofish' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Crypt/Twofish.php',
        'phpseclib3\\Exception\\BadConfigurationException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadConfigurationException.php',
        'phpseclib3\\Exception\\BadDecryptionException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadDecryptionException.php',
        'phpseclib3\\Exception\\BadModeException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/BadModeException.php',
        'phpseclib3\\Exception\\ConnectionClosedException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/ConnectionClosedException.php',
        'phpseclib3\\Exception\\FileNotFoundException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/FileNotFoundException.php',
        'phpseclib3\\Exception\\InconsistentSetupException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/InconsistentSetupException.php',
        'phpseclib3\\Exception\\InsufficientSetupException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/InsufficientSetupException.php',
        'phpseclib3\\Exception\\NoKeyLoadedException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/NoKeyLoadedException.php',
        'phpseclib3\\Exception\\NoSupportedAlgorithmsException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/NoSupportedAlgorithmsException.php',
        'phpseclib3\\Exception\\UnableToConnectException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnableToConnectException.php',
        'phpseclib3\\Exception\\UnsupportedAlgorithmException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedAlgorithmException.php',
        'phpseclib3\\Exception\\UnsupportedCurveException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedCurveException.php',
        'phpseclib3\\Exception\\UnsupportedFormatException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedFormatException.php',
        'phpseclib3\\Exception\\UnsupportedOperationException' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Exception/UnsupportedOperationException.php',
        'phpseclib3\\File\\ANSI' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ANSI.php',
        'phpseclib3\\File\\ASN1' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1.php',
        'phpseclib3\\File\\ASN1\\Element' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Element.php',
        'phpseclib3\\File\\ASN1\\Maps\\AccessDescription' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AccessDescription.php',
        'phpseclib3\\File\\ASN1\\Maps\\AdministrationDomainName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AdministrationDomainName.php',
        'phpseclib3\\File\\ASN1\\Maps\\AlgorithmIdentifier' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AlgorithmIdentifier.php',
        'phpseclib3\\File\\ASN1\\Maps\\AnotherName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AnotherName.php',
        'phpseclib3\\File\\ASN1\\Maps\\Attribute' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attribute.php',
        'phpseclib3\\File\\ASN1\\Maps\\AttributeType' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeType.php',
        'phpseclib3\\File\\ASN1\\Maps\\AttributeTypeAndValue' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeTypeAndValue.php',
        'phpseclib3\\File\\ASN1\\Maps\\AttributeValue' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AttributeValue.php',
        'phpseclib3\\File\\ASN1\\Maps\\Attributes' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Attributes.php',
        'phpseclib3\\File\\ASN1\\Maps\\AuthorityInfoAccessSyntax' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityInfoAccessSyntax.php',
        'phpseclib3\\File\\ASN1\\Maps\\AuthorityKeyIdentifier' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/AuthorityKeyIdentifier.php',
        'phpseclib3\\File\\ASN1\\Maps\\BaseDistance' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BaseDistance.php',
        'phpseclib3\\File\\ASN1\\Maps\\BasicConstraints' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BasicConstraints.php',
        'phpseclib3\\File\\ASN1\\Maps\\BuiltInDomainDefinedAttribute' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttribute.php',
        'phpseclib3\\File\\ASN1\\Maps\\BuiltInDomainDefinedAttributes' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInDomainDefinedAttributes.php',
        'phpseclib3\\File\\ASN1\\Maps\\BuiltInStandardAttributes' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/BuiltInStandardAttributes.php',
        'phpseclib3\\File\\ASN1\\Maps\\CPSuri' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CPSuri.php',
        'phpseclib3\\File\\ASN1\\Maps\\CRLDistributionPoints' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLDistributionPoints.php',
        'phpseclib3\\File\\ASN1\\Maps\\CRLNumber' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLNumber.php',
        'phpseclib3\\File\\ASN1\\Maps\\CRLReason' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CRLReason.php',
        'phpseclib3\\File\\ASN1\\Maps\\CertPolicyId' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertPolicyId.php',
        'phpseclib3\\File\\ASN1\\Maps\\Certificate' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Certificate.php',
        'phpseclib3\\File\\ASN1\\Maps\\CertificateIssuer' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateIssuer.php',
        'phpseclib3\\File\\ASN1\\Maps\\CertificateList' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateList.php',
        'phpseclib3\\File\\ASN1\\Maps\\CertificatePolicies' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificatePolicies.php',
        'phpseclib3\\File\\ASN1\\Maps\\CertificateSerialNumber' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificateSerialNumber.php',
        'phpseclib3\\File\\ASN1\\Maps\\CertificationRequest' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequest.php',
        'phpseclib3\\File\\ASN1\\Maps\\CertificationRequestInfo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CertificationRequestInfo.php',
        'phpseclib3\\File\\ASN1\\Maps\\Characteristic_two' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Characteristic_two.php',
        'phpseclib3\\File\\ASN1\\Maps\\CountryName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/CountryName.php',
        'phpseclib3\\File\\ASN1\\Maps\\Curve' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Curve.php',
        'phpseclib3\\File\\ASN1\\Maps\\DHParameter' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DHParameter.php',
        'phpseclib3\\File\\ASN1\\Maps\\DSAParams' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAParams.php',
        'phpseclib3\\File\\ASN1\\Maps\\DSAPrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPrivateKey.php',
        'phpseclib3\\File\\ASN1\\Maps\\DSAPublicKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DSAPublicKey.php',
        'phpseclib3\\File\\ASN1\\Maps\\DigestInfo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DigestInfo.php',
        'phpseclib3\\File\\ASN1\\Maps\\DirectoryString' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DirectoryString.php',
        'phpseclib3\\File\\ASN1\\Maps\\DisplayText' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DisplayText.php',
        'phpseclib3\\File\\ASN1\\Maps\\DistributionPoint' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPoint.php',
        'phpseclib3\\File\\ASN1\\Maps\\DistributionPointName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DistributionPointName.php',
        'phpseclib3\\File\\ASN1\\Maps\\DssSigValue' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/DssSigValue.php',
        'phpseclib3\\File\\ASN1\\Maps\\ECParameters' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECParameters.php',
        'phpseclib3\\File\\ASN1\\Maps\\ECPoint' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPoint.php',
        'phpseclib3\\File\\ASN1\\Maps\\ECPrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ECPrivateKey.php',
        'phpseclib3\\File\\ASN1\\Maps\\EDIPartyName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EDIPartyName.php',
        'phpseclib3\\File\\ASN1\\Maps\\EcdsaSigValue' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EcdsaSigValue.php',
        'phpseclib3\\File\\ASN1\\Maps\\EncryptedData' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedData.php',
        'phpseclib3\\File\\ASN1\\Maps\\EncryptedPrivateKeyInfo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/EncryptedPrivateKeyInfo.php',
        'phpseclib3\\File\\ASN1\\Maps\\ExtKeyUsageSyntax' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtKeyUsageSyntax.php',
        'phpseclib3\\File\\ASN1\\Maps\\Extension' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extension.php',
        'phpseclib3\\File\\ASN1\\Maps\\ExtensionAttribute' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttribute.php',
        'phpseclib3\\File\\ASN1\\Maps\\ExtensionAttributes' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ExtensionAttributes.php',
        'phpseclib3\\File\\ASN1\\Maps\\Extensions' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Extensions.php',
        'phpseclib3\\File\\ASN1\\Maps\\FieldElement' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldElement.php',
        'phpseclib3\\File\\ASN1\\Maps\\FieldID' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/FieldID.php',
        'phpseclib3\\File\\ASN1\\Maps\\GeneralName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralName.php',
        'phpseclib3\\File\\ASN1\\Maps\\GeneralNames' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralNames.php',
        'phpseclib3\\File\\ASN1\\Maps\\GeneralSubtree' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtree.php',
        'phpseclib3\\File\\ASN1\\Maps\\GeneralSubtrees' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/GeneralSubtrees.php',
        'phpseclib3\\File\\ASN1\\Maps\\HashAlgorithm' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HashAlgorithm.php',
        'phpseclib3\\File\\ASN1\\Maps\\HoldInstructionCode' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/HoldInstructionCode.php',
        'phpseclib3\\File\\ASN1\\Maps\\InvalidityDate' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/InvalidityDate.php',
        'phpseclib3\\File\\ASN1\\Maps\\IssuerAltName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuerAltName.php',
        'phpseclib3\\File\\ASN1\\Maps\\IssuingDistributionPoint' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/IssuingDistributionPoint.php',
        'phpseclib3\\File\\ASN1\\Maps\\KeyIdentifier' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyIdentifier.php',
        'phpseclib3\\File\\ASN1\\Maps\\KeyPurposeId' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyPurposeId.php',
        'phpseclib3\\File\\ASN1\\Maps\\KeyUsage' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/KeyUsage.php',
        'phpseclib3\\File\\ASN1\\Maps\\MaskGenAlgorithm' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/MaskGenAlgorithm.php',
        'phpseclib3\\File\\ASN1\\Maps\\Name' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Name.php',
        'phpseclib3\\File\\ASN1\\Maps\\NameConstraints' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NameConstraints.php',
        'phpseclib3\\File\\ASN1\\Maps\\NetworkAddress' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NetworkAddress.php',
        'phpseclib3\\File\\ASN1\\Maps\\NoticeReference' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NoticeReference.php',
        'phpseclib3\\File\\ASN1\\Maps\\NumericUserIdentifier' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/NumericUserIdentifier.php',
        'phpseclib3\\File\\ASN1\\Maps\\ORAddress' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ORAddress.php',
        'phpseclib3\\File\\ASN1\\Maps\\OneAsymmetricKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OneAsymmetricKey.php',
        'phpseclib3\\File\\ASN1\\Maps\\OrganizationName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationName.php',
        'phpseclib3\\File\\ASN1\\Maps\\OrganizationalUnitNames' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OrganizationalUnitNames.php',
        'phpseclib3\\File\\ASN1\\Maps\\OtherPrimeInfo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfo.php',
        'phpseclib3\\File\\ASN1\\Maps\\OtherPrimeInfos' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/OtherPrimeInfos.php',
        'phpseclib3\\File\\ASN1\\Maps\\PBEParameter' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBEParameter.php',
        'phpseclib3\\File\\ASN1\\Maps\\PBES2params' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBES2params.php',
        'phpseclib3\\File\\ASN1\\Maps\\PBKDF2params' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBKDF2params.php',
        'phpseclib3\\File\\ASN1\\Maps\\PBMAC1params' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PBMAC1params.php',
        'phpseclib3\\File\\ASN1\\Maps\\PKCS9String' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PKCS9String.php',
        'phpseclib3\\File\\ASN1\\Maps\\Pentanomial' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Pentanomial.php',
        'phpseclib3\\File\\ASN1\\Maps\\PersonalName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PersonalName.php',
        'phpseclib3\\File\\ASN1\\Maps\\PolicyInformation' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyInformation.php',
        'phpseclib3\\File\\ASN1\\Maps\\PolicyMappings' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyMappings.php',
        'phpseclib3\\File\\ASN1\\Maps\\PolicyQualifierId' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierId.php',
        'phpseclib3\\File\\ASN1\\Maps\\PolicyQualifierInfo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PolicyQualifierInfo.php',
        'phpseclib3\\File\\ASN1\\Maps\\PostalAddress' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PostalAddress.php',
        'phpseclib3\\File\\ASN1\\Maps\\Prime_p' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Prime_p.php',
        'phpseclib3\\File\\ASN1\\Maps\\PrivateDomainName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateDomainName.php',
        'phpseclib3\\File\\ASN1\\Maps\\PrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKey.php',
        'phpseclib3\\File\\ASN1\\Maps\\PrivateKeyInfo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyInfo.php',
        'phpseclib3\\File\\ASN1\\Maps\\PrivateKeyUsagePeriod' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PrivateKeyUsagePeriod.php',
        'phpseclib3\\File\\ASN1\\Maps\\PublicKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKey.php',
        'phpseclib3\\File\\ASN1\\Maps\\PublicKeyAndChallenge' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyAndChallenge.php',
        'phpseclib3\\File\\ASN1\\Maps\\PublicKeyInfo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/PublicKeyInfo.php',
        'phpseclib3\\File\\ASN1\\Maps\\RC2CBCParameter' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RC2CBCParameter.php',
        'phpseclib3\\File\\ASN1\\Maps\\RDNSequence' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RDNSequence.php',
        'phpseclib3\\File\\ASN1\\Maps\\RSAPrivateKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPrivateKey.php',
        'phpseclib3\\File\\ASN1\\Maps\\RSAPublicKey' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSAPublicKey.php',
        'phpseclib3\\File\\ASN1\\Maps\\RSASSA_PSS_params' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RSASSA_PSS_params.php',
        'phpseclib3\\File\\ASN1\\Maps\\ReasonFlags' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/ReasonFlags.php',
        'phpseclib3\\File\\ASN1\\Maps\\RelativeDistinguishedName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RelativeDistinguishedName.php',
        'phpseclib3\\File\\ASN1\\Maps\\RevokedCertificate' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/RevokedCertificate.php',
        'phpseclib3\\File\\ASN1\\Maps\\SignedPublicKeyAndChallenge' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SignedPublicKeyAndChallenge.php',
        'phpseclib3\\File\\ASN1\\Maps\\SpecifiedECDomain' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SpecifiedECDomain.php',
        'phpseclib3\\File\\ASN1\\Maps\\SubjectAltName' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectAltName.php',
        'phpseclib3\\File\\ASN1\\Maps\\SubjectDirectoryAttributes' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectDirectoryAttributes.php',
        'phpseclib3\\File\\ASN1\\Maps\\SubjectInfoAccessSyntax' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectInfoAccessSyntax.php',
        'phpseclib3\\File\\ASN1\\Maps\\SubjectPublicKeyInfo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/SubjectPublicKeyInfo.php',
        'phpseclib3\\File\\ASN1\\Maps\\TBSCertList' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertList.php',
        'phpseclib3\\File\\ASN1\\Maps\\TBSCertificate' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TBSCertificate.php',
        'phpseclib3\\File\\ASN1\\Maps\\TerminalIdentifier' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/TerminalIdentifier.php',
        'phpseclib3\\File\\ASN1\\Maps\\Time' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Time.php',
        'phpseclib3\\File\\ASN1\\Maps\\Trinomial' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Trinomial.php',
        'phpseclib3\\File\\ASN1\\Maps\\UniqueIdentifier' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UniqueIdentifier.php',
        'phpseclib3\\File\\ASN1\\Maps\\UserNotice' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/UserNotice.php',
        'phpseclib3\\File\\ASN1\\Maps\\Validity' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/Validity.php',
        'phpseclib3\\File\\ASN1\\Maps\\netscape_ca_policy_url' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_ca_policy_url.php',
        'phpseclib3\\File\\ASN1\\Maps\\netscape_cert_type' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_cert_type.php',
        'phpseclib3\\File\\ASN1\\Maps\\netscape_comment' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/ASN1/Maps/netscape_comment.php',
        'phpseclib3\\File\\X509' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/File/X509.php',
        'phpseclib3\\Math\\BigInteger' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\BCMath' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\Base' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Base.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\BuiltIn' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/BuiltIn.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\DefaultEngine' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/DefaultEngine.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\OpenSSL' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/OpenSSL.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\Reductions\\Barrett' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/Barrett.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\BCMath\\Reductions\\EvalBarrett' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/BCMath/Reductions/EvalBarrett.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\Engine' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/Engine.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\GMP' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\GMP\\DefaultEngine' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/GMP/DefaultEngine.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\OpenSSL' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/OpenSSL.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP32' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP32.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP64' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP64.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Base' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Base.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\DefaultEngine' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/DefaultEngine.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Montgomery' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Montgomery.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\OpenSSL' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/OpenSSL.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\Barrett' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Barrett.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\Classic' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Classic.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\EvalBarrett' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/EvalBarrett.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\Montgomery' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/Montgomery.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\MontgomeryMult' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/MontgomeryMult.php',
        'phpseclib3\\Math\\BigInteger\\Engines\\PHP\\Reductions\\PowerOfTwo' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BigInteger/Engines/PHP/Reductions/PowerOfTwo.php',
        'phpseclib3\\Math\\BinaryField' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BinaryField.php',
        'phpseclib3\\Math\\BinaryField\\Integer' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/BinaryField/Integer.php',
        'phpseclib3\\Math\\Common\\FiniteField' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/Common/FiniteField.php',
        'phpseclib3\\Math\\Common\\FiniteField\\Integer' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/Common/FiniteField/Integer.php',
        'phpseclib3\\Math\\PrimeField' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/PrimeField.php',
        'phpseclib3\\Math\\PrimeField\\Integer' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Math/PrimeField/Integer.php',
        'phpseclib3\\Net\\SFTP' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SFTP.php',
        'phpseclib3\\Net\\SFTP\\Stream' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SFTP/Stream.php',
        'phpseclib3\\Net\\SSH2' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/Net/SSH2.php',
        'phpseclib3\\System\\SSH\\Agent' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Agent.php',
        'phpseclib3\\System\\SSH\\Agent\\Identity' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Agent/Identity.php',
        'phpseclib3\\System\\SSH\\Common\\Traits\\ReadBytes' => __DIR__ . '/..' . '/phabel-transpiler74.phpseclib/phpseclib/phpseclib/System/SSH/Common/Traits/ReadBytes.php',
    );

    public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInita56f38b10c587f7d23477ad1951b93ea::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInita56f38b10c587f7d23477ad1951b93ea::$prefixDirsPsr4;
            $loader->prefixesPsr0 = ComposerStaticInita56f38b10c587f7d23477ad1951b93ea::$prefixesPsr0;
            $loader->classMap = ComposerStaticInita56f38b10c587f7d23477ad1951b93ea::$classMap;

        }, null, ClassLoader::class);
    }
}
{
    "packages": [
        {
            "name": "danog/madelineproto",
            "version": "907.0.50.9998",
            "version_normalized": "907.0.50.9998",
            "dist": {
                "type": "path",
                "url": "/home/daniil/actions/madeline_6/_work_6/MadelineProto/MadelineProto",
                "reference": "78415171d2099c1c24d6c113217ebba7888309ad"
            },
            "require": {
                "ext-dom": "*",
                "ext-fileinfo": "*",
                "ext-filter": "*",
                "ext-hash": "*",
                "ext-json": "*",
                "ext-mbstring": "*",
                "ext-xml": "*",
                "ext-zlib": "*",
                "phabel/phabel": "^1.0",
                "php": "*"
            },
            "conflict": {
                "ext-pthreads": "*",
                "krakjoe/pthreads-polyfill": "*"
            },
            "require-dev": {
                "bamarni/composer-bin-plugin": "^1.4",
                "danog/phpdoc": "^0.1.7",
                "ext-ctype": "*",
                "phabel/phabel": "^1",
                "phpdocumentor/reflection-docblock": "^5.2",
                "phpunit/phpunit": "^9",
                "roave/security-advisories": "dev-latest",
                "symfony/yaml": "^6.0"
            },
            "suggest": {
                "ext-gmp": "Install the gmp extension for faster crypto",
                "ext-libtgvoip": "Install the php-libtgvoip extension to make phone calls (https://github.com/danog/php-libtgvoip)",
                "ext-openssl": "Install the openssl extension for faster crypto",
                "ext-pdo": "Install pdo extension to support database used as cache"
            },
            "type": "project",
            "extra": {
                "phabel": {
                    "revision": 0,
                    "require": {
                        "danog/primemodule": "^1",
                        "erusev/parsedown": "^1.7",
                        "symfony/polyfill-mbstring": "*",
                        "amphp/amp": "^2",
                        "amphp/http-client": "^4",
                        "amphp/socket": "^1",
                        "amphp/dns": "^1",
                        "amphp/byte-stream": "^1",
                        "amphp/file": "^2",
                        "amphp/mysql": "^2",
                        "amphp/postgres": "^1.2",
                        "danog/dns-over-https": "^0.2",
                        "amphp/http-client-cookies": "^1",
                        "danog/tg-file-decoder": "^0.1",
                        "danog/magicalserializer": "^1.0",
                        "league/uri": "^6",
                        "danog/ipc": "^0.1",
                        "amphp/log": "^1.1",
                        "danog/loop": "^0.1.0",
                        "phpseclib/phpseclib": "^3",
                        "amphp/redis": "^1.0",
                        "symfony/polyfill-php80": "^1.18",
                        "amphp/websocket-client": "^1.0",
                        "psr/http-factory": "^1.0",
                        "psr/log": "^1"
                    }
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "danog\\MadelineProto\\": "src/danog/MadelineProto"
                },
                "files": [
                    "src/BigIntegor.php",
                    "src/YieldReturnValue.php",
                    "src/polyfill.php",
                    "___transpiledWithPhabel.php"
                ]
            },
            "autoload-dev": {
                "psr-4": {
                    "danog\\MadelineProto\\Test\\": "tests/danog/"
                },
                "files": [
                    "tools/build_docs/schemas.php",
                    "tools/build_docs/merge.php",
                    "tools/build_docs/layerUpgrade.php"
                ]
            },
            "scripts": {
                "build": [
                    "@docs",
                    "@phpdoc",
                    "@cs-fix",
                    "@psalm"
                ],
                "phpdoc": [
                    "@phpdocInternal",
                    "@phpdocMain"
                ],
                "check": [
                    "@cs",
                    "@test"
                ],
                "test-php7": [
                    "tests/test-conversion.sh 70"
                ],
                "test-php56": [
                    "tests/test-conversion.sh 5"
                ],
                "cs": [
                    "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run"
                ],
                "cs-fix": [
                    "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff"
                ],
                "psalm": [
                    "psalm"
                ],
                "phpdocMain": [
                    "php tools/phpdoc.php"
                ],
                "docs": [
                    "php tools/build_docs.php"
                ],
                "test": [
                    "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text --config tests/phpunit.xml"
                ],
                "bin": [
                    "echo 'bin not installed'"
                ],
                "post-install-cmd": [
                    "@composer bin all install --ansi"
                ],
                "post-update-cmd": [
                    "@composer bin all update --ansi"
                ]
            },
            "license": [
                "AGPL-3.0-only"
            ],
            "authors": [
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                }
            ],
            "description": "PHP implementation of telegram's MTProto protocol.",
            "homepage": "https://docs.madelineproto.xyz",
            "keywords": [
                "GB",
                "PHP",
                "audio",
                "bytes",
                "client",
                "files",
                "messenger",
                "mtproto",
                "protocol",
                "stickers",
                "telegram",
                "video"
            ],
            "transport-options": {
                "symlink": false,
                "relative": false
            },
            "install-path": "../danog/madelineproto"
        },
        {
            "name": "phabel-transpiler74.amphp/amp",
            "version": "v2.6.1",
            "version_normalized": "2.6.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/amp.git",
                "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/amp/zipball/c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae",
                "reference": "c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/amp": "*"
            },
            "provide": {
                "amphp/amp": "2.6.1.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1",
                "ext-json": "*",
                "jetbrains/phpstorm-stubs": "^2019.3",
                "phpunit/phpunit": "^7 | ^8 | ^9",
                "psalm/phar": "^3.11@dev",
                "react/promise": "^2"
            },
            "time": "2021-09-23T18:43:08+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\": "lib"
                },
                "files": [
                    "lib/functions.php",
                    "lib/Internal/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@php.net"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Bob Weinand",
                    "email": "bobwei9@hotmail.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "A non-blocking concurrency framework for PHP applications.",
            "homepage": "http://amphp.org/amp",
            "keywords": [
                "async",
                "asynchronous",
                "awaitable",
                "concurrency",
                "event",
                "event-loop",
                "future",
                "non-blocking",
                "promise"
            ],
            "support": {
                "irc": "irc://irc.freenode.org/amphp",
                "issues": "https://github.com/amphp/amp/issues",
                "source": "https://github.com/amphp/amp/tree/v2.6.1"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/amp"
        },
        {
            "name": "phabel-transpiler74.amphp/byte-stream",
            "version": "v1.8.1",
            "version_normalized": "1.8.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/byte-stream.git",
                "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/byte-stream/zipball/acbd8002b3536485c997c4e019206b3f10ca15bd",
                "reference": "acbd8002b3536485c997c4e019206b3f10ca15bd",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/byte-stream": "*"
            },
            "provide": {
                "amphp/byte-stream": "1.8.1.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.4",
                "friendsofphp/php-cs-fixer": "^2.3",
                "jetbrains/phpstorm-stubs": "^2019.3",
                "phpunit/phpunit": "^6 || ^7 || ^8",
                "psalm/phar": "^3.11.4"
            },
            "time": "2021-03-30T17:13:30+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\ByteStream\\": "lib"
                },
                "files": [
                    "lib/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "A stream abstraction to make working with non-blocking I/O simple.",
            "homepage": "http://amphp.org/byte-stream",
            "keywords": [
                "amp",
                "amphp",
                "async",
                "io",
                "non-blocking",
                "stream"
            ],
            "support": {
                "irc": "irc://irc.freenode.org/amphp",
                "issues": "https://github.com/amphp/byte-stream/issues",
                "source": "https://github.com/amphp/byte-stream/tree/v1.8.1"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/byte-stream"
        },
        {
            "name": "phabel-transpiler74.amphp/cache",
            "version": "v1.5.0",
            "version_normalized": "1.5.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/cache.git",
                "reference": "2b6b5dbb70e54cc914df9952ba7c012bc4cbcd28"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/cache/zipball/2b6b5dbb70e54cc914df9952ba7c012bc4cbcd28",
                "reference": "2b6b5dbb70e54cc914df9952ba7c012bc4cbcd28",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/serialization": "^1",
                "phabel-transpiler74.amphp/sync": "^1.2",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/cache": "*",
                "amphp/file": "<0.2 || >=3"
            },
            "provide": {
                "amphp/cache": "1.5.0.0"
            },
            "require-dev": {
                "amphp/file": "^1 || ^2",
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1",
                "phpunit/phpunit": "^6 | ^7 | ^8 | ^9",
                "vimeo/psalm": "^4"
            },
            "time": "2021-06-29T17:12:43+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Cache\\": "lib"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                },
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@php.net"
                }
            ],
            "description": "A promise-aware caching API for Amp.",
            "homepage": "https://github.com/amphp/cache",
            "support": {
                "irc": "irc://irc.freenode.org/amphp",
                "issues": "https://github.com/amphp/cache/issues",
                "source": "https://github.com/amphp/cache/tree/v1.5.0"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/cache"
        },
        {
            "name": "phabel-transpiler74.amphp/dns",
            "version": "v1.2.3",
            "version_normalized": "1.2.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/dns.git",
                "reference": "852292532294d7972c729a96b49756d781f7c59d"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/dns/zipball/852292532294d7972c729a96b49756d781f7c59d",
                "reference": "852292532294d7972c729a96b49756d781f7c59d",
                "shasum": ""
            },
            "require": {
                "ext-filter": "*",
                "ext-json": "*",
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/byte-stream": "^1.1",
                "phabel-transpiler74.amphp/cache": "^1.2",
                "phabel-transpiler74.amphp/parser": "^1",
                "phabel-transpiler74.amphp/windows-registry": "^0.3",
                "phabel-transpiler74.daverandom/libdns": "^2.0.1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/dns": "*"
            },
            "provide": {
                "amphp/dns": "1.2.3.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1",
                "phpunit/phpunit": "^6 || ^7 || ^8 || ^9"
            },
            "time": "2020-07-21T19:04:57+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Dns\\": "lib"
                },
                "files": [
                    "lib/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Chris Wright",
                    "email": "addr@daverandom.com"
                },
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@php.net"
                },
                {
                    "name": "Bob Weinand",
                    "email": "bobwei9@hotmail.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                }
            ],
            "description": "Async DNS resolution for Amp.",
            "homepage": "https://github.com/amphp/dns",
            "keywords": [
                "amp",
                "amphp",
                "async",
                "client",
                "dns",
                "resolve"
            ],
            "support": {
                "issues": "https://github.com/amphp/dns/issues",
                "source": "https://github.com/amphp/dns/tree/v1.2.3"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/dns"
        },
        {
            "name": "phabel-transpiler74.amphp/file",
            "version": "v2.0.2",
            "version_normalized": "2.0.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/file.git",
                "reference": "3d3d084b81a5322d203e11617f7cbe3ea16c40ca"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/file/zipball/3d3d084b81a5322d203e11617f7cbe3ea16c40ca",
                "reference": "3d3d084b81a5322d203e11617f7cbe3ea16c40ca",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2.5.2",
                "phabel-transpiler74.amphp/byte-stream": "^1.8.1",
                "phabel-transpiler74.amphp/parallel": "^1.4",
                "phabel-transpiler74.amphp/sync": "^1.4",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/file": "*"
            },
            "provide": {
                "amphp/file": "2.0.2.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1",
                "ext-eio": "^2 || ^3",
                "ext-uv": "^0.3 || ^0.2",
                "phpunit/phpunit": "^9 || ^8 || ^7"
            },
            "time": "2021-09-20T04:35:03+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\File\\": "src"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@php.net"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Allows non-blocking access to the filesystem for Amp.",
            "homepage": "https://github.com/amphp/file",
            "keywords": [
                "amp",
                "amphp",
                "async",
                "disk",
                "file",
                "filesystem",
                "io",
                "non-blocking",
                "static"
            ],
            "support": {
                "issues": "https://github.com/amphp/file/issues",
                "source": "https://github.com/amphp/file/tree/v2.0.2"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/file"
        },
        {
            "name": "phabel-transpiler74.amphp/hpack",
            "version": "v3.1.1",
            "version_normalized": "3.1.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/hpack.git",
                "reference": "cf4f1663e9fd58f60258c06177098655ca6377a5"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/hpack/zipball/cf4f1663e9fd58f60258c06177098655ca6377a5",
                "reference": "cf4f1663e9fd58f60258c06177098655ca6377a5",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/hpack": "*"
            },
            "provide": {
                "amphp/hpack": "3.1.1.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "http2jp/hpack-test-case": "^1",
                "phpunit/phpunit": "^6 | ^7"
            },
            "time": "2021-06-11T20:03:34+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "3.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Http\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@php.net"
                },
                {
                    "name": "Bob Weinand"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                }
            ],
            "description": "HTTP/2 HPack implementation.",
            "homepage": "https://github.com/amphp/hpack",
            "keywords": [
                "headers",
                "hpack",
                "http-2"
            ],
            "support": {
                "issues": "https://github.com/amphp/hpack/issues",
                "source": "https://github.com/amphp/hpack/tree/v3.1.1"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/hpack"
        },
        {
            "name": "phabel-transpiler74.amphp/http",
            "version": "v1.6.3",
            "version_normalized": "1.6.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/http.git",
                "reference": "e2b75561011a9596e4574cc867e07a706d56394b"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/http/zipball/e2b75561011a9596e4574cc867e07a706d56394b",
                "reference": "e2b75561011a9596e4574cc867e07a706d56394b",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/hpack": "^3",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/http": "*"
            },
            "provide": {
                "amphp/http": "1.6.3.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "phpunit/phpunit": "^7 || ^6.5"
            },
            "time": "2020-11-28T17:04:34+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Http\\": "src"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Basic HTTP primitives which can be shared by servers and clients.",
            "support": {
                "issues": "https://github.com/amphp/http/issues",
                "source": "https://github.com/amphp/http/tree/v1.6.3"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/http"
        },
        {
            "name": "phabel-transpiler74.amphp/http-client",
            "version": "v4.6.2",
            "version_normalized": "4.6.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/http-client.git",
                "reference": "453f84f623e409889168351e60246f5feddc1b3c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/http-client/zipball/453f84f623e409889168351e60246f5feddc1b3c",
                "reference": "453f84f623e409889168351e60246f5feddc1b3c",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2.4",
                "phabel-transpiler74.amphp/byte-stream": "^1.6",
                "phabel-transpiler74.amphp/hpack": "^3",
                "phabel-transpiler74.amphp/http": "^1.6",
                "phabel-transpiler74.amphp/socket": "^1",
                "phabel-transpiler74.amphp/sync": "^1.3",
                "phabel-transpiler74.league/uri": "^6",
                "phabel-transpiler74.psr/http-message": "^1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/file": "<0.2 || >=3",
                "amphp/http-client": "*"
            },
            "provide": {
                "amphp/http-client": "4.6.2.0"
            },
            "require-dev": {
                "amphp/file": "^0.2 || ^0.3 || ^1 || ^2",
                "amphp/http-server": "^2",
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1",
                "amphp/react-adapter": "^2.1",
                "clue/socks-react": "^1.0",
                "ext-json": "*",
                "kelunik/link-header-rfc5988": "^1.0",
                "laminas/laminas-diactoros": "^2.3",
                "phpunit/phpunit": "^7 || ^8 || ^9",
                "vimeo/psalm": "^4"
            },
            "suggest": {
                "amphp/file": "Required for file request bodies and HTTP archive logging",
                "ext-json": "Required for logging HTTP archives",
                "ext-zlib": "Allows using compression for response bodies."
            },
            "time": "2021-10-09T14:11:46+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "4.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Http\\Client\\": "src"
                },
                "files": [
                    "src/Internal/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@gmail.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                }
            ],
            "description": "Asynchronous concurrent HTTP/2 and HTTP/1.1 client built on the Amp concurrency framework",
            "homepage": "https://github.com/amphp/http-client",
            "keywords": [
                "async",
                "client",
                "concurrent",
                "http",
                "non-blocking",
                "rest"
            ],
            "support": {
                "issues": "https://github.com/amphp/http-client/issues",
                "source": "https://github.com/amphp/http-client/tree/v4.6.2"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/http-client"
        },
        {
            "name": "phabel-transpiler74.amphp/http-client-cookies",
            "version": "v1.2.0",
            "version_normalized": "1.2.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/http-client-cookies.git",
                "reference": "ab7e498bb6c4e389e2b9880727d6470997189d87"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/http-client-cookies/zipball/ab7e498bb6c4e389e2b9880727d6470997189d87",
                "reference": "ab7e498bb6c4e389e2b9880727d6470997189d87",
                "shasum": ""
            },
            "require": {
                "ext-filter": "*",
                "phabel-transpiler74.amphp/amp": "^2.3",
                "phabel-transpiler74.amphp/dns": "^1.2",
                "phabel-transpiler74.amphp/http": "^1.5",
                "phabel-transpiler74.amphp/http-client": "^4",
                "phabel-transpiler74.amphp/sync": "^1.3",
                "phabel-transpiler74.psr/http-message": "^1.0",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/file": "<1 || >=3",
                "amphp/http-client-cookies": "*"
            },
            "provide": {
                "amphp/http-client-cookies": "1.2.0.0"
            },
            "require-dev": {
                "amphp/file": "^2",
                "amphp/http-server": "dev-master",
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1",
                "amphp/socket": "^1",
                "friendsofphp/php-cs-fixer": "^2.3",
                "phpunit/phpunit": "^7 || ^8"
            },
            "time": "2021-10-21T20:53:46+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Http\\Client\\Cookie\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@gmail.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Automatic cookie handling for Amp's HTTP client.",
            "homepage": "https://github.com/amphp/http-client-cookies",
            "keywords": [
                "async",
                "client",
                "cookie",
                "cookies",
                "http"
            ],
            "support": {
                "issues": "https://github.com/amphp/http-client-cookies/issues",
                "source": "https://github.com/amphp/http-client-cookies/tree/v1.2.0"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/http-client-cookies"
        },
        {
            "name": "phabel-transpiler74.amphp/log",
            "version": "v1.1.0",
            "version_normalized": "1.1.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/log.git",
                "reference": "25dcd3b58622bd22ffa7129288edb85e0c17081a"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/log/zipball/25dcd3b58622bd22ffa7129288edb85e0c17081a",
                "reference": "25dcd3b58622bd22ffa7129288edb85e0c17081a",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/byte-stream": "^1.3",
                "phabel-transpiler74.monolog/monolog": "^2 || ^1.23",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/log": "*"
            },
            "provide": {
                "amphp/log": "1.1.0.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1",
                "phpunit/phpunit": "^8 || ^7"
            },
            "time": "2019-09-04T15:31:40+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Log\\": "src"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Non-blocking logging for PHP based on Amp and Monolog.",
            "homepage": "https://github.com/amphp/log",
            "keywords": [
                "amp",
                "amphp",
                "async",
                "log",
                "logger",
                "logging",
                "non-blocking"
            ],
            "support": {
                "issues": "https://github.com/amphp/log/issues",
                "source": "https://github.com/amphp/log/tree/master"
            },
            "install-path": "../phabel-transpiler74.amphp/log"
        },
        {
            "name": "phabel-transpiler74.amphp/mysql",
            "version": "v2.1.2",
            "version_normalized": "2.1.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/mysql.git",
                "reference": "d0b9a618b45ad3a10452a3860056db76a6930a75"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/mysql/zipball/d0b9a618b45ad3a10452a3860056db76a6930a75",
                "reference": "d0b9a618b45ad3a10452a3860056db76a6930a75",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/socket": "^1",
                "phabel-transpiler74.amphp/sql": "^1",
                "phabel-transpiler74.amphp/sql-common": "^1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/mysql": "*"
            },
            "provide": {
                "amphp/mysql": "2.1.2.0"
            },
            "require-dev": {
                "amphp/file": "^2 || ^1 || ^0.3.5",
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1.2",
                "amphp/process": "^1",
                "ext-openssl": "*",
                "phpbench/phpbench": "^0.13.0",
                "phpunit/phpunit": "^9 || ^8 || ^7"
            },
            "time": "2021-12-01T17:38:48+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Mysql\\": "src"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Bob Weinand",
                    "email": "bobwei9@hotmail.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                }
            ],
            "description": "Asynchronous MySQL client for PHP based on Amp.",
            "support": {
                "issues": "https://github.com/amphp/mysql/issues",
                "source": "https://github.com/amphp/mysql/tree/v2.1.2"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/mysql"
        },
        {
            "name": "phabel-transpiler74.amphp/parallel",
            "version": "v1.4.1",
            "version_normalized": "1.4.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/parallel.git",
                "reference": "fbc128383c1ffb3823866f71b88d8c4722a25ce9"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/parallel/zipball/fbc128383c1ffb3823866f71b88d8c4722a25ce9",
                "reference": "fbc128383c1ffb3823866f71b88d8c4722a25ce9",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/byte-stream": "^1.6.1",
                "phabel-transpiler74.amphp/parser": "^1",
                "phabel-transpiler74.amphp/process": "^1",
                "phabel-transpiler74.amphp/serialization": "^1",
                "phabel-transpiler74.amphp/sync": "^1.0.1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/parallel": "*"
            },
            "provide": {
                "amphp/parallel": "1.4.1.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1",
                "phpunit/phpunit": "^8 || ^7"
            },
            "time": "2021-10-25T19:16:02+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Parallel\\": "lib"
                },
                "files": [
                    "lib/Context/functions.php",
                    "lib/Sync/functions.php",
                    "lib/Worker/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Stephen Coakley",
                    "email": "me@stephencoakley.com"
                }
            ],
            "description": "Parallel processing component for Amp.",
            "homepage": "https://github.com/amphp/parallel",
            "keywords": [
                "async",
                "asynchronous",
                "concurrent",
                "multi-processing",
                "multi-threading"
            ],
            "support": {
                "issues": "https://github.com/amphp/parallel/issues",
                "source": "https://github.com/amphp/parallel/tree/v1.4.1"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/parallel"
        },
        {
            "name": "phabel-transpiler74.amphp/parser",
            "version": "v1.0.0",
            "version_normalized": "1.0.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/parser.git",
                "reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/parser/zipball/f83e68f03d5b8e8e0365b8792985a7f341c57ae1",
                "reference": "f83e68f03d5b8e8e0365b8792985a7f341c57ae1",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/parser": "*"
            },
            "provide": {
                "amphp/parser": "1.0.0.0"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "^2.3",
                "phpunit/phpunit": "^6"
            },
            "time": "2017-06-06T05:29:10+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Parser\\": "lib"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                }
            ],
            "description": "A generator parser to make streaming parsers simple.",
            "homepage": "https://github.com/amphp/parser",
            "keywords": [
                "async",
                "non-blocking",
                "parser",
                "stream"
            ],
            "support": {
                "issues": "https://github.com/amphp/parser/issues",
                "source": "https://github.com/amphp/parser/tree/is-valid"
            },
            "install-path": "../phabel-transpiler74.amphp/parser"
        },
        {
            "name": "phabel-transpiler74.amphp/postgres",
            "version": "v1.4.3",
            "version_normalized": "1.4.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/postgres.git",
                "reference": "f52cc35ef02ee4ad709083e0432c2288d4df7de0"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/postgres/zipball/f52cc35ef02ee4ad709083e0432c2288d4df7de0",
                "reference": "f52cc35ef02ee4ad709083e0432c2288d4df7de0",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/sql": "^1",
                "phabel-transpiler74.amphp/sql-common": "^1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/postgres": "*"
            },
            "provide": {
                "amphp/postgres": "1.4.3.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1.2",
                "ext-pgsql": "*",
                "ext-pq": "*",
                "phpunit/phpunit": "^8 | ^7"
            },
            "time": "2021-12-04T16:46:00+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Postgres\\": "src"
                },
                "files": [
                    "src/functions.php",
                    "src/Internal/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                }
            ],
            "description": "Asynchronous PostgreSQL client for Amp.",
            "homepage": "http://amphp.org",
            "keywords": [
                "async",
                "asynchronous",
                "database",
                "db",
                "pgsql",
                "postgre",
                "postgresql"
            ],
            "support": {
                "issues": "https://github.com/amphp/postgres/issues",
                "source": "https://github.com/amphp/postgres/tree/v1.4.3"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/postgres"
        },
        {
            "name": "phabel-transpiler74.amphp/process",
            "version": "v1.1.3",
            "version_normalized": "1.1.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/process.git",
                "reference": "f09e3ed3b0a953ccbfff1140f12be4a884f0aa83"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/process/zipball/f09e3ed3b0a953ccbfff1140f12be4a884f0aa83",
                "reference": "f09e3ed3b0a953ccbfff1140f12be4a884f0aa83",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/byte-stream": "^1.4",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/process": "*"
            },
            "provide": {
                "amphp/process": "1.1.3.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1",
                "phpunit/phpunit": "^6"
            },
            "time": "2021-12-17T19:09:33+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Process\\": "lib"
                },
                "files": [
                    "lib/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Bob Weinand",
                    "email": "bobwei9@hotmail.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Asynchronous process manager.",
            "homepage": "https://github.com/amphp/process",
            "support": {
                "issues": "https://github.com/amphp/process/issues",
                "source": "https://github.com/amphp/process/tree/v1.1.3"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/process"
        },
        {
            "name": "phabel-transpiler74.amphp/redis",
            "version": "v1.0.6",
            "version_normalized": "1.0.6.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/redis.git",
                "reference": "1eade91c18aecd4708ea35e2d745a71e8a5c1354"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/redis/zipball/1eade91c18aecd4708ea35e2d745a71e8a5c1354",
                "reference": "1eade91c18aecd4708ea35e2d745a71e8a5c1354",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2.2.1",
                "phabel-transpiler74.amphp/cache": "^1.2.1",
                "phabel-transpiler74.amphp/socket": "^1",
                "phabel-transpiler74.amphp/sync": "^1.1",
                "phabel-transpiler74.league/uri-parser": "^1.4",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/redis": "*"
            },
            "provide": {
                "amphp/redis": "1.0.6.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1.2",
                "phpunit/phpunit": "^7 | ^8"
            },
            "time": "2021-10-18T15:18:29+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Redis\\": "src"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "A non-blocking Redis client for Amp.",
            "homepage": "https://github.com/amphp/redis",
            "keywords": [
                "amp",
                "amphp",
                "async",
                "client",
                "redis"
            ],
            "support": {
                "issues": "https://github.com/amphp/redis/issues",
                "source": "https://github.com/amphp/redis/tree/v1.0.6"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/redis"
        },
        {
            "name": "phabel-transpiler74.amphp/serialization",
            "version": "v1.0.0",
            "version_normalized": "1.0.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/serialization.git",
                "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/serialization/zipball/693e77b2fb0b266c3c7d622317f881de44ae94a1",
                "reference": "693e77b2fb0b266c3c7d622317f881de44ae94a1",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/serialization": "*"
            },
            "provide": {
                "amphp/serialization": "1.0.0.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "phpunit/phpunit": "^9 || ^8 || ^7"
            },
            "time": "2020-03-25T21:39:07+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Serialization\\": "src"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Serialization tools for IPC and data storage in PHP.",
            "homepage": "https://github.com/amphp/serialization",
            "keywords": [
                "async",
                "asynchronous",
                "serialization",
                "serialize"
            ],
            "support": {
                "issues": "https://github.com/amphp/serialization/issues",
                "source": "https://github.com/amphp/serialization/tree/master"
            },
            "install-path": "../phabel-transpiler74.amphp/serialization"
        },
        {
            "name": "phabel-transpiler74.amphp/socket",
            "version": "v1.2.0",
            "version_normalized": "1.2.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/socket.git",
                "reference": "a8af9f5d0a66c5fe9567da45a51509e592788fe6"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/socket/zipball/a8af9f5d0a66c5fe9567da45a51509e592788fe6",
                "reference": "a8af9f5d0a66c5fe9567da45a51509e592788fe6",
                "shasum": ""
            },
            "require": {
                "ext-openssl": "*",
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/byte-stream": "^1.6",
                "phabel-transpiler74.amphp/dns": "^1 || ^0.9",
                "phabel-transpiler74.kelunik/certificate": "^1.1",
                "phabel-transpiler74.league/uri-parser": "^1.4",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/socket": "*"
            },
            "provide": {
                "amphp/socket": "1.2.0.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1",
                "phpunit/phpunit": "^6 || ^7 || ^8",
                "vimeo/psalm": "^3.9@dev"
            },
            "time": "2021-07-09T18:18:48+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Socket\\": "src"
                },
                "files": [
                    "src/functions.php",
                    "src/Internal/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@gmail.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Async socket connection / server tools for Amp.",
            "homepage": "https://github.com/amphp/socket",
            "keywords": [
                "amp",
                "async",
                "encryption",
                "non-blocking",
                "sockets",
                "tcp",
                "tls"
            ],
            "support": {
                "issues": "https://github.com/amphp/socket/issues",
                "source": "https://github.com/amphp/socket/tree/v1.2.0"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/socket"
        },
        {
            "name": "phabel-transpiler74.amphp/sql",
            "version": "v1.0.1",
            "version_normalized": "1.0.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/sql.git",
                "reference": "0445ac35623a18105efeac93364288434430a4d8"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/sql/zipball/0445ac35623a18105efeac93364288434430a4d8",
                "reference": "0445ac35623a18105efeac93364288434430a4d8",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/sql": "*"
            },
            "provide": {
                "amphp/sql": "1.0.1.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1",
                "phpunit/phpunit": "^6"
            },
            "time": "2019-09-26T16:23:02+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Sql\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Asynchronous SQL client for Amp.",
            "homepage": "http://amphp.org",
            "keywords": [
                "async",
                "asynchronous",
                "database",
                "db",
                "sql"
            ],
            "support": {
                "issues": "https://github.com/amphp/sql/issues",
                "source": "https://github.com/amphp/sql/tree/v1.0.1"
            },
            "install-path": "../phabel-transpiler74.amphp/sql"
        },
        {
            "name": "phabel-transpiler74.amphp/sql-common",
            "version": "v1.1.2",
            "version_normalized": "1.1.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/sql-common.git",
                "reference": "1c3b86970373d2ae00482300cae1442d4e9bd782"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/sql-common/zipball/1c3b86970373d2ae00482300cae1442d4e9bd782",
                "reference": "1c3b86970373d2ae00482300cae1442d4e9bd782",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/sql": "^1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/sql-common": "*"
            },
            "provide": {
                "amphp/sql-common": "1.1.2.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.3",
                "phpunit/phpunit": "^6 || ^7 || ^8 || ^9"
            },
            "time": "2020-11-09T23:11:50+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Sql\\Common\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "Common classes for non-blocking SQL implementations.",
            "homepage": "http://amphp.org",
            "keywords": [
                "async",
                "asynchronous",
                "database",
                "db",
                "sql"
            ],
            "support": {
                "issues": "https://github.com/amphp/sql-common/issues",
                "source": "https://github.com/amphp/sql-common/tree/v1.1.2"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/sql-common"
        },
        {
            "name": "phabel-transpiler74.amphp/sync",
            "version": "v1.4.2",
            "version_normalized": "1.4.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/sync.git",
                "reference": "85ab06764f4f36d63b1356b466df6111cf4b89cf"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/sync/zipball/85ab06764f4f36d63b1356b466df6111cf4b89cf",
                "reference": "85ab06764f4f36d63b1356b466df6111cf4b89cf",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2.2",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/sync": "*"
            },
            "provide": {
                "amphp/sync": "1.4.2.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1",
                "phpunit/phpunit": "^9 || ^8 || ^7"
            },
            "time": "2021-10-25T18:29:10+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Sync\\": "src"
                },
                "files": [
                    "src/functions.php",
                    "src/ConcurrentIterator/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Stephen Coakley",
                    "email": "me@stephencoakley.com"
                }
            ],
            "description": "Mutex, Semaphore, and other synchronization tools for Amp.",
            "homepage": "https://github.com/amphp/sync",
            "keywords": [
                "async",
                "asynchronous",
                "mutex",
                "semaphore",
                "synchronization"
            ],
            "support": {
                "issues": "https://github.com/amphp/sync/issues",
                "source": "https://github.com/amphp/sync/tree/v1.4.2"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/sync"
        },
        {
            "name": "phabel-transpiler74.amphp/websocket",
            "version": "v1.0.2",
            "version_normalized": "1.0.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/websocket.git",
                "reference": "d0e61e3e34ac09ec230ae0eff2b8beaf8f83a8f9"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/websocket/zipball/d0e61e3e34ac09ec230ae0eff2b8beaf8f83a8f9",
                "reference": "d0e61e3e34ac09ec230ae0eff2b8beaf8f83a8f9",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2.2",
                "phabel-transpiler74.amphp/byte-stream": "^1.6.1",
                "phabel-transpiler74.amphp/socket": "^1",
                "phabel-transpiler74.cash/lrucache": "^1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/websocket": "*"
            },
            "provide": {
                "amphp/websocket": "1.0.2.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1.2",
                "phpunit/phpunit": "^8 || ^7",
                "vimeo/psalm": "^3.11@dev"
            },
            "suggest": {
                "ext-zlib": "Required for compression"
            },
            "time": "2021-10-26T14:32:35+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Websocket\\": "src"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                },
                {
                    "name": "Bob Weinand",
                    "email": "bobwei9@hotmail.com"
                }
            ],
            "description": "Shared code for websocket servers and clients.",
            "homepage": "https://github.com/amphp/websocket",
            "keywords": [
                "amp",
                "amphp",
                "async",
                "http",
                "non-blocking",
                "websocket"
            ],
            "support": {
                "issues": "https://github.com/amphp/websocket/issues",
                "source": "https://github.com/amphp/websocket/tree/v1.0.2"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/websocket"
        },
        {
            "name": "phabel-transpiler74.amphp/websocket-client",
            "version": "v1.0.0",
            "version_normalized": "1.0.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/websocket-client.git",
                "reference": "173b54137cdcd4288702f615f05c1029e613ba37"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/websocket-client/zipball/173b54137cdcd4288702f615f05c1029e613ba37",
                "reference": "173b54137cdcd4288702f615f05c1029e613ba37",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2.2",
                "phabel-transpiler74.amphp/http": "^1.3",
                "phabel-transpiler74.amphp/http-client": "^4",
                "phabel-transpiler74.amphp/socket": "^1",
                "phabel-transpiler74.amphp/websocket": "^1",
                "phabel-transpiler74.league/uri": "^6",
                "phabel-transpiler74.psr/http-message": "^1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/websocket-client": "*"
            },
            "provide": {
                "amphp/websocket-client": "1.0.0.0"
            },
            "require-dev": {
                "amphp/http-server": "^2",
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.1",
                "amphp/websocket-server": "dev-master as 2.0-rc4",
                "phpunit/phpunit": "^8 || ^7",
                "psr/log": "^1",
                "vimeo/psalm": "^3.11@dev"
            },
            "time": "2020-07-05T17:36:04+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Websocket\\Client\\": "src"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Bob Weinand",
                    "email": "bobwei9@hotmail.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Async WebSocket client for PHP based on Amp.",
            "keywords": [
                "amp",
                "amphp",
                "async",
                "client",
                "http",
                "non-blocking",
                "websocket"
            ],
            "support": {
                "issues": "https://github.com/amphp/websocket-client/issues",
                "source": "https://github.com/amphp/websocket-client/tree/v1.0.0"
            },
            "install-path": "../phabel-transpiler74.amphp/websocket-client"
        },
        {
            "name": "phabel-transpiler74.amphp/windows-registry",
            "version": "v0.3.3",
            "version_normalized": "0.3.3.0",
            "source": {
                "type": "git",
                "url": "https://github.com/amphp/windows-registry.git",
                "reference": "0f56438b9197e224325e88f305346f0221df1f71"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/amphp/windows-registry/zipball/0f56438b9197e224325e88f305346f0221df1f71",
                "reference": "0f56438b9197e224325e88f305346f0221df1f71",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/byte-stream": "^1.4",
                "phabel-transpiler74.amphp/process": "^1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "amphp/windows-registry": "*"
            },
            "provide": {
                "amphp/windows-registry": "0.3.3.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master"
            },
            "time": "2020-07-10T16:13:29+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\WindowsRegistry\\": "lib"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Windows Registry Reader.",
            "support": {
                "issues": "https://github.com/amphp/windows-registry/issues",
                "source": "https://github.com/amphp/windows-registry/tree/master"
            },
            "funding": [
                {
                    "url": "https://github.com/amphp",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.amphp/windows-registry"
        },
        {
            "name": "phabel-transpiler74.cash/lrucache",
            "version": "1.0.0",
            "version_normalized": "1.0.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/cash/LRUCache.git",
                "reference": "4fa4c6834cec59690b43526c4da41d6153026289"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/cash/LRUCache/zipball/4fa4c6834cec59690b43526c4da41d6153026289",
                "reference": "4fa4c6834cec59690b43526c4da41d6153026289",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "cash/lrucache": "*"
            },
            "provide": {
                "cash/lrucache": "1.0.0.0"
            },
            "time": "2013-09-20T18:59:12+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-0": {
                    "cash": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Cash Costello",
                    "email": "cash.costello@gmail.com"
                }
            ],
            "description": "An efficient memory-based Least Recently Used (LRU) cache",
            "homepage": "https://github.com/cash/LRUCache",
            "keywords": [
                "cache",
                "lru"
            ],
            "support": {
                "issues": "https://github.com/cash/LRUCache/issues",
                "source": "https://github.com/cash/LRUCache/tree/1.0.0"
            },
            "install-path": "../phabel-transpiler74.cash/lrucache"
        },
        {
            "name": "phabel-transpiler74.danog/dns-over-https",
            "version": "0.2.6",
            "version_normalized": "0.2.6.0",
            "source": {
                "type": "git",
                "url": "https://github.com/danog/dns-over-https.git",
                "reference": "a288be1f4fdd4ce9838e98bfa96407fcfdd099b3"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/danog/dns-over-https/zipball/a288be1f4fdd4ce9838e98bfa96407fcfdd099b3",
                "reference": "a288be1f4fdd4ce9838e98bfa96407fcfdd099b3",
                "shasum": ""
            },
            "require": {
                "ext-filter": "*",
                "ext-json": "*",
                "phabel-transpiler74.amphp/amp": "^2",
                "phabel-transpiler74.amphp/cache": "^1",
                "phabel-transpiler74.amphp/dns": "^1",
                "phabel-transpiler74.amphp/http-client": "^4",
                "phabel-transpiler74.amphp/parser": "^1",
                "phabel-transpiler74.danog/libdns-json": "^0.1",
                "phabel-transpiler74.daverandom/libdns": "^2.0.1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "danog/dns-over-https": "*"
            },
            "provide": {
                "danog/dns-over-https": "0.2.6.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1",
                "phpunit/phpunit": "^6"
            },
            "time": "2019-12-27T14:35:55+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\DoH\\": "lib"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                },
                {
                    "name": "Chris Wright",
                    "email": "addr@daverandom.com"
                },
                {
                    "name": "Daniel Lowrey",
                    "email": "rdlowrey@php.net"
                },
                {
                    "name": "Bob Weinand",
                    "email": "bobwei9@hotmail.com"
                },
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                }
            ],
            "description": "Async DNS-over-HTTPS resolution for Amp.",
            "homepage": "https://github.com/danog/dns-over-https",
            "keywords": [
                "amp",
                "amphp",
                "async",
                "client",
                "dns",
                "dns-over-https",
                "doh",
                "https",
                "resolve"
            ],
            "support": {
                "issues": "https://github.com/danog/dns-over-https/issues",
                "source": "https://github.com/danog/dns-over-https/tree/0.2.6"
            },
            "install-path": "../phabel-transpiler74.danog/dns-over-https"
        },
        {
            "name": "phabel-transpiler74.danog/ipc",
            "version": "0.1.15",
            "version_normalized": "0.1.15.0",
            "source": {
                "type": "git",
                "url": "https://github.com/danog/ipc.git",
                "reference": "6bbd35f057746dba2baad58465fca1a93302bf67"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/danog/ipc/zipball/6bbd35f057746dba2baad58465fca1a93302bf67",
                "reference": "6bbd35f057746dba2baad58465fca1a93302bf67",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/byte-stream": "^1",
                "phabel-transpiler74.amphp/parser": "^1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "danog/ipc": "*"
            },
            "provide": {
                "danog/ipc": "0.1.15.0"
            },
            "require-dev": {
                "amphp/amp": "^2.4",
                "amphp/parallel": "^1.3",
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.3",
                "phpunit/phpunit": "^7 | ^8 | ^9"
            },
            "time": "2021-09-24T16:32:52+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Amp\\Ipc\\": "lib"
                },
                "files": [
                    "lib/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                },
                {
                    "name": "Aaron Piotrowski",
                    "email": "aaron@trowski.com"
                },
                {
                    "name": "Stephen Coakley",
                    "email": "me@stephencoakley.com"
                }
            ],
            "description": "IPC component for Amp.",
            "homepage": "https://github.com/danog/ipc",
            "keywords": [
                "async",
                "asynchronous",
                "concurrent",
                "multi-processing",
                "multi-threading"
            ],
            "support": {
                "issues": "https://github.com/danog/ipc/issues",
                "source": "https://github.com/danog/ipc/tree/0.1.15"
            },
            "install-path": "../phabel-transpiler74.danog/ipc"
        },
        {
            "name": "phabel-transpiler74.danog/libdns-json",
            "version": "0.1.1",
            "version_normalized": "0.1.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/danog/LibDNSJson.git",
                "reference": "7d5e07815d57afa64ef7cdbe1a65fbead9a3e7bd"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/danog/LibDNSJson/zipball/7d5e07815d57afa64ef7cdbe1a65fbead9a3e7bd",
                "reference": "7d5e07815d57afa64ef7cdbe1a65fbead9a3e7bd",
                "shasum": ""
            },
            "require": {
                "ext-json": "*",
                "phabel-transpiler74.daverandom/libdns": "^2.0.1",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "danog/libdns-json": "*"
            },
            "provide": {
                "danog/libdns-json": "0.1.1.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "phpunit/phpunit": "^6"
            },
            "time": "2019-07-14T14:59:51+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "danog\\LibDNSJson\\": "lib"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Chris Wright",
                    "email": "addr@daverandom.com"
                },
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                }
            ],
            "description": "Encoder/decoder for google's JSON DNS message format based on libdns",
            "homepage": "https://github.com/danog/libdns-json",
            "keywords": [
                "dns",
                "dns-over-https",
                "doh",
                "https",
                "json",
                "libdns",
                "message"
            ],
            "support": {
                "issues": "https://github.com/danog/LibDNSJson/issues",
                "source": "https://github.com/danog/LibDNSJson/tree/master"
            },
            "install-path": "../phabel-transpiler74.danog/libdns-json"
        },
        {
            "name": "phabel-transpiler74.danog/loop",
            "version": "0.1.1",
            "version_normalized": "0.1.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/danog/loop.git",
                "reference": "b1941cc6a7b2eede57d11a6ead464ee70793bc3f"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/danog/loop/zipball/b1941cc6a7b2eede57d11a6ead464ee70793bc3f",
                "reference": "b1941cc6a7b2eede57d11a6ead464ee70793bc3f",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.amphp/amp": "^2",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "danog/loop": "*"
            },
            "provide": {
                "danog/loop": "0.1.1.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "amphp/phpunit-util": "^1.3",
                "phpunit/phpunit": "^7 | ^8 | ^9",
                "vimeo/psalm": "dev-master"
            },
            "time": "2021-04-21T13:41:15+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "danog\\Loop\\": "lib"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                }
            ],
            "description": "Loop abstraction for AMPHP.",
            "homepage": "https://github.com/danog/loop",
            "keywords": [
                "async",
                "asynchronous",
                "concurrent",
                "multi-processing",
                "multi-threading"
            ],
            "support": {
                "issues": "https://github.com/danog/loop/issues",
                "source": "https://github.com/danog/loop/tree/0.1.1"
            },
            "funding": [
                {
                    "url": "https://github.com/danog",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.danog/loop"
        },
        {
            "name": "phabel-transpiler74.danog/magicalserializer",
            "version": "1.0",
            "version_normalized": "1.0.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/danog/MagicalSerializer.git",
                "reference": "87b6ed05a86021e9364f31133089bb83980d5e24"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/danog/MagicalSerializer/zipball/87b6ed05a86021e9364f31133089bb83980d5e24",
                "reference": "87b6ed05a86021e9364f31133089bb83980d5e24",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "danog/magicalserializer": "*"
            },
            "provide": {
                "danog/magicalserializer": "1.0.0.0"
            },
            "time": "2018-02-20T10:35:49+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-0": {
                    "danog\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "AGPL-3.0-only"
            ],
            "authors": [
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                }
            ],
            "description": "Serialize Volatile, Threaded or any other internal PHP class!",
            "homepage": "https://daniil.it/MagicalSerializer",
            "keywords": [
                "pthreads",
                "serializable",
                "serialize",
                "threading",
                "volatile"
            ],
            "support": {
                "issues": "https://github.com/danog/MagicalSerializer/issues",
                "source": "https://github.com/danog/MagicalSerializer/tree/master"
            },
            "install-path": "../phabel-transpiler74.danog/magicalserializer"
        },
        {
            "name": "phabel-transpiler74.danog/primemodule",
            "version": "1.0.7",
            "version_normalized": "1.0.7.0",
            "source": {
                "type": "git",
                "url": "https://github.com/danog/PrimeModule.git",
                "reference": "371cf2521dc665875cac5765259240c0666de69c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/danog/PrimeModule/zipball/371cf2521dc665875cac5765259240c0666de69c",
                "reference": "371cf2521dc665875cac5765259240c0666de69c",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "danog/primemodule": "*"
            },
            "provide": {
                "danog/primemodule": "1.0.7.0"
            },
            "suggest": {
                "ext-primemodule": "Install the native C++ extension for extremely fast factorization (https://github.com/danog/PrimeModule-ext)"
            },
            "time": "2021-10-24T16:51:03+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-0": {
                    "danog\\": "lib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "AGPL-3.0-only"
            ],
            "authors": [
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                }
            ],
            "description": "Prime module capable of doing prime factorization of huge numbers very quickly.\"",
            "support": {
                "issues": "https://github.com/danog/PrimeModule/issues",
                "source": "https://github.com/danog/PrimeModule/tree/1.0.7"
            },
            "install-path": "../phabel-transpiler74.danog/primemodule"
        },
        {
            "name": "phabel-transpiler74.danog/tg-file-decoder",
            "version": "0.1.8",
            "version_normalized": "0.1.8.0",
            "source": {
                "type": "git",
                "url": "https://github.com/danog/tg-file-decoder.git",
                "reference": "336d0bd69f3eb0592fab7c3e934cdd0e4a8acf61"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/danog/tg-file-decoder/zipball/336d0bd69f3eb0592fab7c3e934cdd0e4a8acf61",
                "reference": "336d0bd69f3eb0592fab7c3e934cdd0e4a8acf61",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "danog/tg-file-decoder": "*"
            },
            "provide": {
                "danog/tg-file-decoder": "0.1.8.0"
            },
            "require-dev": {
                "amphp/php-cs-fixer-config": "dev-master",
                "phpunit/phpunit": "^8|^6"
            },
            "time": "2021-08-14T15:11:43+00:00",
            "type": "project",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "danog\\Decoder\\": "src/"
                },
                "files": [
                    "src/type.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "AGPL-3.0-only"
            ],
            "authors": [
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                }
            ],
            "description": "Decode Telegram bot API file IDs",
            "keywords": [
                "audio",
                "bot api",
                "file ID",
                "files",
                "mtproto",
                "stickers",
                "telegram",
                "video"
            ],
            "support": {
                "issues": "https://github.com/danog/tg-file-decoder/issues",
                "source": "https://github.com/danog/tg-file-decoder/tree/0.1.8"
            },
            "funding": [
                {
                    "url": "https://github.com/danog",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.danog/tg-file-decoder"
        },
        {
            "name": "phabel-transpiler74.daverandom/libdns",
            "version": "v2.0.2",
            "version_normalized": "2.0.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/DaveRandom/LibDNS.git",
                "reference": "e8b6d6593d18ac3a6a14666d8a68a4703b2e05f9"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/DaveRandom/LibDNS/zipball/e8b6d6593d18ac3a6a14666d8a68a4703b2e05f9",
                "reference": "e8b6d6593d18ac3a6a14666d8a68a4703b2e05f9",
                "shasum": ""
            },
            "require": {
                "ext-ctype": "*",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "daverandom/libdns": "*"
            },
            "provide": {
                "daverandom/libdns": "2.0.2.0"
            },
            "suggest": {
                "ext-intl": "Required for IDN support"
            },
            "time": "2019-12-03T09:12:46+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "LibDNS\\": "src/"
                },
                "files": [
                    "src/functions.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "description": "DNS protocol implementation written in pure PHP",
            "keywords": [
                "dns"
            ],
            "support": {
                "issues": "https://github.com/DaveRandom/LibDNS/issues",
                "source": "https://github.com/DaveRandom/LibDNS/tree/v2.0.2"
            },
            "install-path": "../phabel-transpiler74.daverandom/libdns"
        },
        {
            "name": "phabel-transpiler74.erusev/parsedown",
            "version": "1.7.4",
            "version_normalized": "1.7.4.0",
            "source": {
                "type": "git",
                "url": "https://github.com/erusev/parsedown.git",
                "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/erusev/parsedown/zipball/cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
                "reference": "cb17b6477dfff935958ba01325f2e8a2bfa6dab3",
                "shasum": ""
            },
            "require": {
                "ext-mbstring": "*",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "erusev/parsedown": "*"
            },
            "provide": {
                "erusev/parsedown": "1.7.4.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^4.8.35"
            },
            "time": "2019-12-30T22:54:17+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-0": {
                    "Parsedown": ""
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Emanuil Rusev",
                    "email": "hello@erusev.com",
                    "homepage": "http://erusev.com"
                }
            ],
            "description": "Parser for Markdown.",
            "homepage": "http://parsedown.org",
            "keywords": [
                "markdown",
                "parser"
            ],
            "support": {
                "issues": "https://github.com/erusev/parsedown/issues",
                "source": "https://github.com/erusev/parsedown/tree/1.7.x"
            },
            "install-path": "../phabel-transpiler74.erusev/parsedown"
        },
        {
            "name": "phabel-transpiler74.kelunik/certificate",
            "version": "v1.1.2",
            "version_normalized": "1.1.2.0",
            "source": {
                "type": "git",
                "url": "https://github.com/kelunik/certificate.git",
                "reference": "56542e62d51533d04d0a9713261fea546bff80f6"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/kelunik/certificate/zipball/56542e62d51533d04d0a9713261fea546bff80f6",
                "reference": "56542e62d51533d04d0a9713261fea546bff80f6",
                "shasum": ""
            },
            "require": {
                "ext-openssl": "*",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "kelunik/certificate": "*"
            },
            "provide": {
                "kelunik/certificate": "1.1.2.0"
            },
            "require-dev": {
                "fabpot/php-cs-fixer": "^1.9",
                "phpunit/phpunit": "^4.8"
            },
            "time": "2019-05-29T19:02:31+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Kelunik\\Certificate\\": "lib"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Niklas Keller",
                    "email": "me@kelunik.com"
                }
            ],
            "description": "Access certificate details and transform between different formats.",
            "keywords": [
                "DER",
                "certificate",
                "certificates",
                "openssl",
                "pem",
                "x509"
            ],
            "support": {
                "issues": "https://github.com/kelunik/certificate/issues",
                "source": "https://github.com/kelunik/certificate/tree/v1.1.2"
            },
            "install-path": "../phabel-transpiler74.kelunik/certificate"
        },
        {
            "name": "phabel-transpiler74.league/uri",
            "version": "6.5.0",
            "version_normalized": "6.5.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/thephpleague/uri.git",
                "reference": "c68ca445abb04817d740ddd6d0b3551826ef0c5a"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/thephpleague/uri/zipball/c68ca445abb04817d740ddd6d0b3551826ef0c5a",
                "reference": "c68ca445abb04817d740ddd6d0b3551826ef0c5a",
                "shasum": ""
            },
            "require": {
                "ext-json": "*",
                "phabel-transpiler74.league/uri-interfaces": "^2.3",
                "phabel-transpiler74.psr/http-message": "^1.0",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "league/uri": "*",
                "league/uri-schemes": "^1.0"
            },
            "provide": {
                "league/uri": "6.5.0.0"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "^2.19 || ^3.0",
                "phpstan/phpstan": "^0.12.90",
                "phpstan/phpstan-phpunit": "^0.12.22",
                "phpstan/phpstan-strict-rules": "^0.12.11",
                "phpunit/phpunit": "^8.0 || ^9.0",
                "psr/http-factory": "^1.0"
            },
            "suggest": {
                "ext-fileinfo": "Needed to create Data URI from a filepath",
                "ext-intl": "Needed to improve host validation",
                "league/uri-components": "Needed to easily manipulate URI objects",
                "psr/http-factory": "Needed to use the URI factory"
            },
            "time": "2021-08-27T09:54:07+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "6.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "League\\Uri\\": "src"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Ignace Nyamagana Butera",
                    "email": "nyamsprod@gmail.com",
                    "homepage": "https://nyamsprod.com"
                }
            ],
            "description": "URI manipulation library",
            "homepage": "http://uri.thephpleague.com",
            "keywords": [
                "data-uri",
                "file-uri",
                "ftp",
                "hostname",
                "http",
                "https",
                "middleware",
                "parse_str",
                "parse_url",
                "psr-7",
                "query-string",
                "querystring",
                "rfc3986",
                "rfc3987",
                "rfc6570",
                "uri",
                "uri-template",
                "url",
                "ws"
            ],
            "support": {
                "docs": "https://uri.thephpleague.com",
                "forum": "https://thephpleague.slack.com",
                "issues": "https://github.com/thephpleague/uri/issues",
                "source": "https://github.com/thephpleague/uri/tree/6.5.0"
            },
            "funding": [
                {
                    "url": "https://github.com/sponsors/nyamsprod",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.league/uri"
        },
        {
            "name": "phabel-transpiler74.league/uri-interfaces",
            "version": "2.3.0",
            "version_normalized": "2.3.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/thephpleague/uri-interfaces.git",
                "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/thephpleague/uri-interfaces/zipball/00e7e2943f76d8cb50c7dfdc2f6dee356e15e383",
                "reference": "00e7e2943f76d8cb50c7dfdc2f6dee356e15e383",
                "shasum": ""
            },
            "require": {
                "ext-json": "*",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "league/uri-interfaces": "*"
            },
            "provide": {
                "league/uri-interfaces": "2.3.0.0"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "^2.19",
                "phpstan/phpstan": "^0.12.90",
                "phpstan/phpstan-phpunit": "^0.12.19",
                "phpstan/phpstan-strict-rules": "^0.12.9",
                "phpunit/phpunit": "^8.5.15 || ^9.5"
            },
            "suggest": {
                "ext-intl": "to use the IDNA feature",
                "symfony/intl": "to use the IDNA feature via Symfony Polyfill"
            },
            "time": "2021-06-28T04:27:21+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "2.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "League\\Uri\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Ignace Nyamagana Butera",
                    "email": "nyamsprod@gmail.com",
                    "homepage": "https://nyamsprod.com"
                }
            ],
            "description": "Common interface for URI representation",
            "homepage": "http://github.com/thephpleague/uri-interfaces",
            "keywords": [
                "rfc3986",
                "rfc3987",
                "uri",
                "url"
            ],
            "support": {
                "issues": "https://github.com/thephpleague/uri-interfaces/issues",
                "source": "https://github.com/thephpleague/uri-interfaces/tree/2.3.0"
            },
            "funding": [
                {
                    "url": "https://github.com/sponsors/nyamsprod",
                    "type": "github"
                }
            ],
            "install-path": "../phabel-transpiler74.league/uri-interfaces"
        },
        {
            "name": "phabel-transpiler74.league/uri-parser",
            "version": "1.4.1",
            "version_normalized": "1.4.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/thephpleague/uri-parser.git",
                "reference": "671548427e4c932352d9b9279fdfa345bf63fa00"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/thephpleague/uri-parser/zipball/671548427e4c932352d9b9279fdfa345bf63fa00",
                "reference": "671548427e4c932352d9b9279fdfa345bf63fa00",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "league/uri-parser": "*"
            },
            "provide": {
                "league/uri-parser": "1.4.1.0"
            },
            "require-dev": {
                "friendsofphp/php-cs-fixer": "^2.0",
                "phpstan/phpstan": "^0.9.2",
                "phpstan/phpstan-phpunit": "^0.9.4",
                "phpstan/phpstan-strict-rules": "^0.9.0",
                "phpunit/phpunit": "^6.0"
            },
            "suggest": {
                "ext-intl": "Allow parsing RFC3987 compliant hosts",
                "league/uri-schemes": "Allow validating and normalizing URI parsing results"
            },
            "time": "2018-11-22T07:55:51+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "League\\Uri\\": "src"
                },
                "files": [
                    "src/functions_include.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Ignace Nyamagana Butera",
                    "email": "nyamsprod@gmail.com",
                    "homepage": "https://nyamsprod.com"
                }
            ],
            "description": "userland URI parser RFC 3986 compliant",
            "homepage": "https://github.com/thephpleague/uri-parser",
            "keywords": [
                "parse_url",
                "parser",
                "rfc3986",
                "rfc3987",
                "uri",
                "url"
            ],
            "support": {
                "issues": "https://github.com/thephpleague/uri-parser/issues",
                "source": "https://github.com/thephpleague/uri-parser/tree/master"
            },
            "install-path": "../phabel-transpiler74.league/uri-parser"
        },
        {
            "name": "phabel-transpiler74.monolog/monolog",
            "version": "2.3.5",
            "version_normalized": "2.3.5.0",
            "source": {
                "type": "git",
                "url": "https://github.com/Seldaek/monolog.git",
                "reference": "fd4380d6fc37626e2f799f29d91195040137eba9"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/Seldaek/monolog/zipball/fd4380d6fc37626e2f799f29d91195040137eba9",
                "reference": "fd4380d6fc37626e2f799f29d91195040137eba9",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.psr/log": "^1.0.1 || ^2.0 || ^3.0",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "monolog/monolog": "*"
            },
            "provide": {
                "monolog/monolog": "2.3.5.0",
                "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
            },
            "require-dev": {
                "aws/aws-sdk-php": "^2.4.9 || ^3.0",
                "doctrine/couchdb": "~1.0@dev",
                "elasticsearch/elasticsearch": "^7",
                "graylog2/gelf-php": "^1.4.2",
                "mongodb/mongodb": "^1.8",
                "php-amqplib/php-amqplib": "~2.4 || ^3",
                "php-console/php-console": "^3.1.3",
                "phpspec/prophecy": "^1.6.1",
                "phpstan/phpstan": "^0.12.91",
                "phpunit/phpunit": "^8.5",
                "predis/predis": "^1.1",
                "rollbar/rollbar": "^1.3",
                "ruflin/elastica": ">=0.90@dev",
                "swiftmailer/swiftmailer": "^5.3|^6.0"
            },
            "suggest": {
                "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
                "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
                "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
                "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
                "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
                "ext-mbstring": "Allow to work properly with unicode symbols",
                "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
                "ext-openssl": "Required to send log messages using SSL",
                "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
                "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
                "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
                "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
                "php-console/php-console": "Allow sending log messages to Google Chrome",
                "rollbar/rollbar": "Allow sending log messages to Rollbar",
                "ruflin/elastica": "Allow sending log messages to an Elastic Search server"
            },
            "time": "2021-10-01T21:08:31+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "2.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Monolog\\": "src/Monolog"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jordi Boggiano",
                    "email": "j.boggiano@seld.be",
                    "homepage": "https://seld.be"
                }
            ],
            "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
            "homepage": "https://github.com/Seldaek/monolog",
            "keywords": [
                "log",
                "logging",
                "psr-3"
            ],
            "support": {
                "issues": "https://github.com/Seldaek/monolog/issues",
                "source": "https://github.com/Seldaek/monolog/tree/2.3.5"
            },
            "funding": [
                {
                    "url": "https://github.com/Seldaek",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/monolog/monolog",
                    "type": "tidelift"
                }
            ],
            "install-path": "../phabel-transpiler74.monolog/monolog"
        },
        {
            "name": "phabel-transpiler74.paragonie/constant_time_encoding",
            "version": "v2.4.0",
            "version_normalized": "2.4.0.0",
            "source": {
                "type": "git",
                "url": "https://github.com/paragonie/constant_time_encoding.git",
                "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c",
                "reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "paragonie/constant_time_encoding": "*"
            },
            "provide": {
                "paragonie/constant_time_encoding": "2.4.0.0"
            },
            "require-dev": {
                "phpunit/phpunit": "^6|^7|^8|^9",
                "vimeo/psalm": "^1|^2|^3|^4"
            },
            "time": "2020-12-06T15:14:20+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "ParagonIE\\ConstantTime\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Paragon Initiative Enterprises",
                    "email": "security@paragonie.com",
                    "homepage": "https://paragonie.com",
                    "role": "Maintainer"
                },
                {
                    "name": "Steve 'Sc00bz' Thomas",
                    "email": "steve@tobtu.com",
                    "homepage": "https://www.tobtu.com",
                    "role": "Original Developer"
                }
            ],
            "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
            "keywords": [
                "base16",
                "base32",
                "base32_decode",
                "base32_encode",
                "base64",
                "base64_decode",
                "base64_encode",
                "bin2hex",
                "encoding",
                "hex",
                "hex2bin",
                "rfc4648"
            ],
            "support": {
                "email": "info@paragonie.com",
                "issues": "https://github.com/paragonie/constant_time_encoding/issues",
                "source": "https://github.com/paragonie/constant_time_encoding"
            },
            "install-path": "../phabel-transpiler74.paragonie/constant_time_encoding"
        },
        {
            "name": "phabel-transpiler74.paragonie/random_compat",
            "version": "v9.99.100",
            "version_normalized": "9.99.100.0",
            "source": {
                "type": "git",
                "url": "https://github.com/paragonie/random_compat.git",
                "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
                "reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "paragonie/random_compat": "*"
            },
            "provide": {
                "paragonie/random_compat": "9.99.100.0"
            },
            "require-dev": {
                "phpunit/phpunit": "4.*|5.*",
                "vimeo/psalm": "^1"
            },
            "suggest": {
                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
            },
            "time": "2020-10-15T08:29:30+00:00",
            "type": "library",
            "installation-source": "dist",
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Paragon Initiative Enterprises",
                    "email": "security@paragonie.com",
                    "homepage": "https://paragonie.com"
                }
            ],
            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
            "keywords": [
                "csprng",
                "polyfill",
                "pseudorandom",
                "random"
            ],
            "support": {
                "email": "info@paragonie.com",
                "issues": "https://github.com/paragonie/random_compat/issues",
                "source": "https://github.com/paragonie/random_compat"
            },
            "install-path": "../phabel-transpiler74.paragonie/random_compat"
        },
        {
            "name": "phabel-transpiler74.phpseclib/phpseclib",
            "version": "3.0.12",
            "version_normalized": "3.0.12.0",
            "source": {
                "type": "git",
                "url": "https://github.com/phpseclib/phpseclib.git",
                "reference": "89bfb45bd8b1abc3b37e910d57f5dbd3174f40fb"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/89bfb45bd8b1abc3b37e910d57f5dbd3174f40fb",
                "reference": "89bfb45bd8b1abc3b37e910d57f5dbd3174f40fb",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.paragonie/constant_time_encoding": "^1|^2",
                "phabel-transpiler74.paragonie/random_compat": "^1.4|^2.0|^9.99.99",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "phpseclib/phpseclib": "*"
            },
            "provide": {
                "phpseclib/phpseclib": "3.0.12.0"
            },
            "require-dev": {
                "phing/phing": "~2.7",
                "phpunit/phpunit": "^5.7|^6.0|^9.4",
                "squizlabs/php_codesniffer": "~2.0"
            },
            "suggest": {
                "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
                "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
                "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
                "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
            },
            "time": "2021-11-28T23:46:03+00:00",
            "type": "library",
            "installation-source": "dist",
            "autoload": {
                "files": [
                    "phpseclib/bootstrap.php"
                ],
                "psr-4": {
                    "phpseclib3\\": "phpseclib/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Jim Wigginton",
                    "email": "terrafrost@php.net",
                    "role": "Lead Developer"
                },
                {
                    "name": "Patrick Monnerat",
                    "email": "pm@datasphere.ch",
                    "role": "Developer"
                },
                {
                    "name": "Andreas Fischer",
                    "email": "bantu@phpbb.com",
                    "role": "Developer"
                },
                {
                    "name": "Hans-JÃ¼rgen Petrich",
                    "email": "petrich@tronic-media.com",
                    "role": "Developer"
                },
                {
                    "name": "Graham Campbell",
                    "email": "graham@alt-three.com",
                    "role": "Developer"
                }
            ],
            "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
            "homepage": "http://phpseclib.sourceforge.net",
            "keywords": [
                "BigInteger",
                "aes",
                "asn.1",
                "asn1",
                "blowfish",
                "crypto",
                "cryptography",
                "encryption",
                "rsa",
                "security",
                "sftp",
                "signature",
                "signing",
                "ssh",
                "twofish",
                "x.509",
                "x509"
            ],
            "support": {
                "issues": "https://github.com/phpseclib/phpseclib/issues",
                "source": "https://github.com/phpseclib/phpseclib/tree/3.0.12"
            },
            "funding": [
                {
                    "url": "https://github.com/terrafrost",
                    "type": "github"
                },
                {
                    "url": "https://www.patreon.com/phpseclib",
                    "type": "patreon"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
                    "type": "tidelift"
                }
            ],
            "install-path": "../phabel-transpiler74.phpseclib/phpseclib"
        },
        {
            "name": "phabel-transpiler74.psr/http-factory",
            "version": "1.0.1",
            "version_normalized": "1.0.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/http-factory.git",
                "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/http-factory/zipball/12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
                "reference": "12ac7fcd07e5b077433f5f2bee95b3a771bf61be",
                "shasum": ""
            },
            "require": {
                "phabel-transpiler74.psr/http-message": "^1.0",
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "psr/http-factory": "*"
            },
            "provide": {
                "psr/http-factory": "1.0.1.0"
            },
            "time": "2019-04-30T12:38:16+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Psr\\Http\\Message\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "http://www.php-fig.org/"
                }
            ],
            "description": "Common interfaces for PSR-7 HTTP message factories",
            "keywords": [
                "factory",
                "http",
                "message",
                "psr",
                "psr-17",
                "psr-7",
                "request",
                "response"
            ],
            "support": {
                "source": "https://github.com/php-fig/http-factory/tree/master"
            },
            "install-path": "../phabel-transpiler74.psr/http-factory"
        },
        {
            "name": "phabel-transpiler74.psr/http-message",
            "version": "1.0.1",
            "version_normalized": "1.0.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/http-message.git",
                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
                "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "psr/http-message": "*"
            },
            "provide": {
                "psr/http-message": "1.0.1.0"
            },
            "time": "2016-08-06T14:39:51+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.0.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Psr\\Http\\Message\\": "src/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "http://www.php-fig.org/"
                }
            ],
            "description": "Common interface for HTTP messages",
            "homepage": "https://github.com/php-fig/http-message",
            "keywords": [
                "http",
                "http-message",
                "psr",
                "psr-7",
                "request",
                "response"
            ],
            "support": {
                "source": "https://github.com/php-fig/http-message/tree/master"
            },
            "install-path": "../phabel-transpiler74.psr/http-message"
        },
        {
            "name": "phabel-transpiler74.psr/log",
            "version": "1.1.4",
            "version_normalized": "1.1.4.0",
            "source": {
                "type": "git",
                "url": "https://github.com/php-fig/log.git",
                "reference": "d49695b909c3b7628b6289db5479a1c204601f11"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/php-fig/log/zipball/d49695b909c3b7628b6289db5479a1c204601f11",
                "reference": "d49695b909c3b7628b6289db5479a1c204601f11",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "psr/log": "*"
            },
            "provide": {
                "psr/log": "1.1.4.0"
            },
            "time": "2021-05-03T11:20:27+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-master": "1.1.x-dev"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Psr\\Log\\": "Psr/Log/"
                }
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "PHP-FIG",
                    "homepage": "https://www.php-fig.org/"
                }
            ],
            "description": "Common interface for logging libraries",
            "homepage": "https://github.com/php-fig/log",
            "keywords": [
                "log",
                "psr",
                "psr-3"
            ],
            "support": {
                "source": "https://github.com/php-fig/log/tree/1.1.4"
            },
            "install-path": "../phabel-transpiler74.psr/log"
        },
        {
            "name": "phabel-transpiler74.symfony/polyfill-mbstring",
            "version": "v1.23.1",
            "version_normalized": "1.23.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-mbstring.git",
                "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/9174a3d80210dca8daa7f31fec659150bbeabfc6",
                "reference": "9174a3d80210dca8daa7f31fec659150bbeabfc6",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "symfony/polyfill-mbstring": "*"
            },
            "provide": {
                "symfony/polyfill-mbstring": "1.23.1.0"
            },
            "suggest": {
                "ext-mbstring": "For best performance"
            },
            "time": "2021-05-27T12:26:48+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.23-dev"
                },
                "thanks": {
                    "name": "symfony/polyfill",
                    "url": "https://github.com/symfony/polyfill"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Symfony\\Polyfill\\Mbstring\\": ""
                },
                "files": [
                    "bootstrap.php"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill for the Mbstring extension",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "mbstring",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.23.1"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "install-path": "../phabel-transpiler74.symfony/polyfill-mbstring"
        },
        {
            "name": "phabel-transpiler74.symfony/polyfill-php80",
            "version": "v1.23.1",
            "version_normalized": "1.23.1.0",
            "source": {
                "type": "git",
                "url": "https://github.com/symfony/polyfill-php80.git",
                "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/1100343ed1a92e3a38f9ae122fc0eb21602547be",
                "reference": "1100343ed1a92e3a38f9ae122fc0eb21602547be",
                "shasum": ""
            },
            "require": {
                "php": ">=7.4 <7.5"
            },
            "conflict": {
                "symfony/polyfill-php80": "*"
            },
            "provide": {
                "symfony/polyfill-php80": "1.23.1.0"
            },
            "time": "2021-07-28T13:41:28+00:00",
            "type": "library",
            "extra": {
                "branch-alias": {
                    "dev-main": "1.23-dev"
                },
                "thanks": {
                    "name": "symfony/polyfill",
                    "url": "https://github.com/symfony/polyfill"
                }
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Symfony\\Polyfill\\Php80\\": ""
                },
                "files": [
                    "bootstrap.php"
                ],
                "classmap": [
                    "Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Ion Bazan",
                    "email": "ion.bazan@gmail.com"
                },
                {
                    "name": "Nicolas Grekas",
                    "email": "p@tchwork.com"
                },
                {
                    "name": "Symfony Community",
                    "homepage": "https://symfony.com/contributors"
                }
            ],
            "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
            "homepage": "https://symfony.com",
            "keywords": [
                "compatibility",
                "polyfill",
                "portable",
                "shim"
            ],
            "support": {
                "source": "https://github.com/symfony/polyfill-php80/tree/v1.23.1"
            },
            "funding": [
                {
                    "url": "https://symfony.com/sponsor",
                    "type": "custom"
                },
                {
                    "url": "https://github.com/fabpot",
                    "type": "github"
                },
                {
                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
                    "type": "tidelift"
                }
            ],
            "install-path": "../phabel-transpiler74.symfony/polyfill-php80"
        },
        {
            "name": "phabel/phabel",
            "version": "1.0.49.74",
            "version_normalized": "1.0.49.74",
            "source": {
                "type": "git",
                "url": "https://github.com/phabelio/phabel.git",
                "reference": "129bb83be33fb0cb5ddcf4a1ffe9d7843c176ba7"
            },
            "dist": {
                "type": "zip",
                "url": "https://api.github.com/repos/phabelio/phabel/zipball/129bb83be33fb0cb5ddcf4a1ffe9d7843c176ba7",
                "reference": "129bb83be33fb0cb5ddcf4a1ffe9d7843c176ba7",
                "shasum": ""
            },
            "require": {
                "composer-plugin-api": "^2.0",
                "ext-json": "*",
                "ext-tokenizer": "*",
                "php": ">=7.4 <7.5"
            },
            "provide": {
                "phabelio/phabel": "self.version"
            },
            "require-dev": {
                "amphp/file": "^2.0",
                "bamarni/composer-bin-plugin": "^1.4"
            },
            "time": "2021-12-22T13:39:52+00:00",
            "bin": [
                "bin/phabel"
            ],
            "type": "composer-plugin",
            "extra": {
                "class": "Phabel\\Composer\\Plugin",
                "plugin-modifies-downloads": true
            },
            "installation-source": "dist",
            "autoload": {
                "psr-4": {
                    "Phabel\\": "src",
                    "PhabelVendor\\Amp\\": [
                        "vendor-bundle/amphp/amp/lib"
                    ],
                    "PhabelVendor\\Amp\\ByteStream\\": [
                        "vendor-bundle/amphp/byte-stream/lib"
                    ],
                    "PhabelVendor\\Amp\\Parallel\\": [
                        "vendor-bundle/amphp/parallel/lib"
                    ],
                    "PhabelVendor\\Amp\\Parser\\": [
                        "vendor-bundle/amphp/parser/lib"
                    ],
                    "PhabelVendor\\Amp\\Process\\": [
                        "vendor-bundle/amphp/process/lib"
                    ],
                    "PhabelVendor\\Amp\\Serialization\\": [
                        "vendor-bundle/amphp/serialization/src"
                    ],
                    "PhabelVendor\\Amp\\Sync\\": [
                        "vendor-bundle/amphp/sync/src"
                    ],
                    "PhabelVendor\\PhpParser\\": [
                        "vendor-bundle/phabel/php-parser/lib/PhpParser"
                    ],
                    "PhabelVendor\\PHPStan\\PhpDocParser\\": [
                        "vendor-bundle/phpstan/phpdoc-parser/src/"
                    ],
                    "PhabelVendor\\Psr\\Container\\": [
                        "vendor-bundle/psr/container/src/"
                    ],
                    "PhabelVendor\\Psr\\Log\\": [
                        "vendor-bundle/psr/log/Psr/Log/"
                    ],
                    "PhabelVendor\\Symfony\\Component\\Console\\": [
                        "vendor-bundle/symfony/console/"
                    ],
                    "Symfony\\Polyfill\\Ctype\\": [
                        "vendor-bundle/symfony/polyfill-ctype/"
                    ],
                    "Symfony\\Polyfill\\Intl\\Grapheme\\": [
                        "vendor-bundle/symfony/polyfill-intl-grapheme/"
                    ],
                    "Symfony\\Polyfill\\Intl\\Normalizer\\": [
                        "vendor-bundle/symfony/polyfill-intl-normalizer/"
                    ],
                    "Symfony\\Polyfill\\Mbstring\\": [
                        "vendor-bundle/symfony/polyfill-mbstring/"
                    ],
                    "Symfony\\Polyfill\\Php73\\": [
                        "vendor-bundle/symfony/polyfill-php73/"
                    ],
                    "Symfony\\Polyfill\\Php80\\": [
                        "vendor-bundle/symfony/polyfill-php80/"
                    ],
                    "PhabelVendor\\Symfony\\Component\\Process\\": [
                        "vendor-bundle/symfony/process/"
                    ],
                    "PhabelVendor\\Symfony\\Contracts\\Service\\": [
                        "vendor-bundle/symfony/service-contracts/"
                    ],
                    "PhabelVendor\\Symfony\\Component\\String\\": [
                        "vendor-bundle/symfony/string/"
                    ]
                },
                "files": [
                    "src/guard.php",
                    "vendor-bundle/amphp/amp/lib/functions.php",
                    "vendor-bundle/amphp/amp/lib/Internal/functions.php",
                    "vendor-bundle/amphp/byte-stream/lib/functions.php",
                    "vendor-bundle/amphp/parallel/lib/Context/functions.php",
                    "vendor-bundle/amphp/parallel/lib/Sync/functions.php",
                    "vendor-bundle/amphp/parallel/lib/Worker/functions.php",
                    "vendor-bundle/amphp/process/lib/functions.php",
                    "vendor-bundle/amphp/serialization/src/functions.php",
                    "vendor-bundle/amphp/sync/src/functions.php",
                    "vendor-bundle/amphp/sync/src/ConcurrentIterator/functions.php",
                    "vendor-bundle/symfony/deprecation-contracts/function.php",
                    "vendor-bundle/symfony/polyfill-ctype/bootstrap.php",
                    "vendor-bundle/symfony/polyfill-intl-grapheme/bootstrap.php",
                    "vendor-bundle/symfony/polyfill-intl-normalizer/bootstrap.php",
                    "vendor-bundle/symfony/polyfill-mbstring/bootstrap.php",
                    "vendor-bundle/symfony/polyfill-php73/bootstrap.php",
                    "vendor-bundle/symfony/polyfill-php80/bootstrap.php",
                    "vendor-bundle/symfony/string/Resources/functions.php"
                ],
                "classmap": [
                    "vendor-bundle/symfony/polyfill-intl-normalizer/Resources/stubs",
                    "vendor-bundle/symfony/polyfill-php73/Resources/stubs",
                    "vendor-bundle/symfony/polyfill-php80/Resources/stubs"
                ]
            },
            "notification-url": "https://packagist.org/downloads/",
            "license": [
                "MIT"
            ],
            "authors": [
                {
                    "name": "Daniil Gentili",
                    "email": "daniil@daniil.it"
                }
            ],
            "description": "Write and deploy modern PHP 8 code, today.",
            "support": {
                "issues": "https://github.com/phabelio/phabel/issues",
                "source": "https://github.com/phabelio/phabel/tree/1.0.49.74"
            },
            "funding": [
                {
                    "url": "https://github.com/danog",
                    "type": "github"
                }
            ],
            "install-path": "../phabel/phabel"
        }
    ],
    "dev": true,
    "dev-package-names": []
}
<?php return array (
  'root' => 
  array (
    'pretty_version' => '1.0.0+no-version-set',
    'version' => '1.0.0.0',
    'aliases' => 
    array (
    ),
    'reference' => NULL,
    'name' => 'danog/madelineprotophar',
  ),
  'versions' => 
  array (
    'amphp/amp' => 
    array (
      'provided' => 
      array (
        0 => '2.6.1.0',
      ),
    ),
    'amphp/byte-stream' => 
    array (
      'provided' => 
      array (
        0 => '1.8.1.0',
      ),
    ),
    'amphp/cache' => 
    array (
      'provided' => 
      array (
        0 => '1.5.0.0',
      ),
    ),
    'amphp/dns' => 
    array (
      'provided' => 
      array (
        0 => '1.2.3.0',
      ),
    ),
    'amphp/file' => 
    array (
      'provided' => 
      array (
        0 => '2.0.2.0',
      ),
    ),
    'amphp/hpack' => 
    array (
      'provided' => 
      array (
        0 => '3.1.1.0',
      ),
    ),
    'amphp/http' => 
    array (
      'provided' => 
      array (
        0 => '1.6.3.0',
      ),
    ),
    'amphp/http-client' => 
    array (
      'provided' => 
      array (
        0 => '4.6.2.0',
      ),
    ),
    'amphp/http-client-cookies' => 
    array (
      'provided' => 
      array (
        0 => '1.2.0.0',
      ),
    ),
    'amphp/log' => 
    array (
      'provided' => 
      array (
        0 => '1.1.0.0',
      ),
    ),
    'amphp/mysql' => 
    array (
      'provided' => 
      array (
        0 => '2.1.2.0',
      ),
    ),
    'amphp/parallel' => 
    array (
      'provided' => 
      array (
        0 => '1.4.1.0',
      ),
    ),
    'amphp/parser' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'amphp/postgres' => 
    array (
      'provided' => 
      array (
        0 => '1.4.3.0',
      ),
    ),
    'amphp/process' => 
    array (
      'provided' => 
      array (
        0 => '1.1.3.0',
      ),
    ),
    'amphp/redis' => 
    array (
      'provided' => 
      array (
        0 => '1.0.6.0',
      ),
    ),
    'amphp/serialization' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'amphp/socket' => 
    array (
      'provided' => 
      array (
        0 => '1.2.0.0',
      ),
    ),
    'amphp/sql' => 
    array (
      'provided' => 
      array (
        0 => '1.0.1.0',
      ),
    ),
    'amphp/sql-common' => 
    array (
      'provided' => 
      array (
        0 => '1.1.2.0',
      ),
    ),
    'amphp/sync' => 
    array (
      'provided' => 
      array (
        0 => '1.4.2.0',
      ),
    ),
    'amphp/websocket' => 
    array (
      'provided' => 
      array (
        0 => '1.0.2.0',
      ),
    ),
    'amphp/websocket-client' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'amphp/windows-registry' => 
    array (
      'provided' => 
      array (
        0 => '0.3.3.0',
      ),
    ),
    'cash/lrucache' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'danog/dns-over-https' => 
    array (
      'provided' => 
      array (
        0 => '0.2.6.0',
      ),
    ),
    'danog/ipc' => 
    array (
      'provided' => 
      array (
        0 => '0.1.15.0',
      ),
    ),
    'danog/libdns-json' => 
    array (
      'provided' => 
      array (
        0 => '0.1.1.0',
      ),
    ),
    'danog/loop' => 
    array (
      'provided' => 
      array (
        0 => '0.1.1.0',
      ),
    ),
    'danog/madelineproto' => 
    array (
      'pretty_version' => '907.0.50.9998',
      'version' => '907.0.50.9998',
      'aliases' => 
      array (
      ),
      'reference' => '78415171d2099c1c24d6c113217ebba7888309ad',
    ),
    'danog/madelineprotophar' => 
    array (
      'pretty_version' => '1.0.0+no-version-set',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => NULL,
    ),
    'danog/magicalserializer' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'danog/primemodule' => 
    array (
      'provided' => 
      array (
        0 => '1.0.7.0',
      ),
    ),
    'danog/tg-file-decoder' => 
    array (
      'provided' => 
      array (
        0 => '0.1.8.0',
      ),
    ),
    'daverandom/libdns' => 
    array (
      'provided' => 
      array (
        0 => '2.0.2.0',
      ),
    ),
    'erusev/parsedown' => 
    array (
      'provided' => 
      array (
        0 => '1.7.4.0',
      ),
    ),
    'kelunik/certificate' => 
    array (
      'provided' => 
      array (
        0 => '1.1.2.0',
      ),
    ),
    'league/uri' => 
    array (
      'provided' => 
      array (
        0 => '6.5.0.0',
      ),
    ),
    'league/uri-interfaces' => 
    array (
      'provided' => 
      array (
        0 => '2.3.0.0',
      ),
    ),
    'league/uri-parser' => 
    array (
      'provided' => 
      array (
        0 => '1.4.1.0',
      ),
    ),
    'monolog/monolog' => 
    array (
      'provided' => 
      array (
        0 => '2.3.5.0',
      ),
    ),
    'paragonie/constant_time_encoding' => 
    array (
      'provided' => 
      array (
        0 => '2.4.0.0',
      ),
    ),
    'paragonie/random_compat' => 
    array (
      'provided' => 
      array (
        0 => '9.99.100.0',
      ),
    ),
    'phabel-transpiler74.amphp/amp' => 
    array (
      'pretty_version' => 'v2.6.1',
      'version' => '2.6.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae',
    ),
    'phabel-transpiler74.amphp/byte-stream' => 
    array (
      'pretty_version' => 'v1.8.1',
      'version' => '1.8.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'acbd8002b3536485c997c4e019206b3f10ca15bd',
    ),
    'phabel-transpiler74.amphp/cache' => 
    array (
      'pretty_version' => 'v1.5.0',
      'version' => '1.5.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '2b6b5dbb70e54cc914df9952ba7c012bc4cbcd28',
    ),
    'phabel-transpiler74.amphp/dns' => 
    array (
      'pretty_version' => 'v1.2.3',
      'version' => '1.2.3.0',
      'aliases' => 
      array (
      ),
      'reference' => '852292532294d7972c729a96b49756d781f7c59d',
    ),
    'phabel-transpiler74.amphp/file' => 
    array (
      'pretty_version' => 'v2.0.2',
      'version' => '2.0.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '3d3d084b81a5322d203e11617f7cbe3ea16c40ca',
    ),
    'phabel-transpiler74.amphp/hpack' => 
    array (
      'pretty_version' => 'v3.1.1',
      'version' => '3.1.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'cf4f1663e9fd58f60258c06177098655ca6377a5',
    ),
    'phabel-transpiler74.amphp/http' => 
    array (
      'pretty_version' => 'v1.6.3',
      'version' => '1.6.3.0',
      'aliases' => 
      array (
      ),
      'reference' => 'e2b75561011a9596e4574cc867e07a706d56394b',
    ),
    'phabel-transpiler74.amphp/http-client' => 
    array (
      'pretty_version' => 'v4.6.2',
      'version' => '4.6.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '453f84f623e409889168351e60246f5feddc1b3c',
    ),
    'phabel-transpiler74.amphp/http-client-cookies' => 
    array (
      'pretty_version' => 'v1.2.0',
      'version' => '1.2.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'ab7e498bb6c4e389e2b9880727d6470997189d87',
    ),
    'phabel-transpiler74.amphp/log' => 
    array (
      'pretty_version' => 'v1.1.0',
      'version' => '1.1.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '25dcd3b58622bd22ffa7129288edb85e0c17081a',
    ),
    'phabel-transpiler74.amphp/mysql' => 
    array (
      'pretty_version' => 'v2.1.2',
      'version' => '2.1.2.0',
      'aliases' => 
      array (
      ),
      'reference' => 'd0b9a618b45ad3a10452a3860056db76a6930a75',
    ),
    'phabel-transpiler74.amphp/parallel' => 
    array (
      'pretty_version' => 'v1.4.1',
      'version' => '1.4.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'fbc128383c1ffb3823866f71b88d8c4722a25ce9',
    ),
    'phabel-transpiler74.amphp/parser' => 
    array (
      'pretty_version' => 'v1.0.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f83e68f03d5b8e8e0365b8792985a7f341c57ae1',
    ),
    'phabel-transpiler74.amphp/postgres' => 
    array (
      'pretty_version' => 'v1.4.3',
      'version' => '1.4.3.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f52cc35ef02ee4ad709083e0432c2288d4df7de0',
    ),
    'phabel-transpiler74.amphp/process' => 
    array (
      'pretty_version' => 'v1.1.3',
      'version' => '1.1.3.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f09e3ed3b0a953ccbfff1140f12be4a884f0aa83',
    ),
    'phabel-transpiler74.amphp/redis' => 
    array (
      'pretty_version' => 'v1.0.6',
      'version' => '1.0.6.0',
      'aliases' => 
      array (
      ),
      'reference' => '1eade91c18aecd4708ea35e2d745a71e8a5c1354',
    ),
    'phabel-transpiler74.amphp/serialization' => 
    array (
      'pretty_version' => 'v1.0.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '693e77b2fb0b266c3c7d622317f881de44ae94a1',
    ),
    'phabel-transpiler74.amphp/socket' => 
    array (
      'pretty_version' => 'v1.2.0',
      'version' => '1.2.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'a8af9f5d0a66c5fe9567da45a51509e592788fe6',
    ),
    'phabel-transpiler74.amphp/sql' => 
    array (
      'pretty_version' => 'v1.0.1',
      'version' => '1.0.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '0445ac35623a18105efeac93364288434430a4d8',
    ),
    'phabel-transpiler74.amphp/sql-common' => 
    array (
      'pretty_version' => 'v1.1.2',
      'version' => '1.1.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '1c3b86970373d2ae00482300cae1442d4e9bd782',
    ),
    'phabel-transpiler74.amphp/sync' => 
    array (
      'pretty_version' => 'v1.4.2',
      'version' => '1.4.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '85ab06764f4f36d63b1356b466df6111cf4b89cf',
    ),
    'phabel-transpiler74.amphp/websocket' => 
    array (
      'pretty_version' => 'v1.0.2',
      'version' => '1.0.2.0',
      'aliases' => 
      array (
      ),
      'reference' => 'd0e61e3e34ac09ec230ae0eff2b8beaf8f83a8f9',
    ),
    'phabel-transpiler74.amphp/websocket-client' => 
    array (
      'pretty_version' => 'v1.0.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '173b54137cdcd4288702f615f05c1029e613ba37',
    ),
    'phabel-transpiler74.amphp/windows-registry' => 
    array (
      'pretty_version' => 'v0.3.3',
      'version' => '0.3.3.0',
      'aliases' => 
      array (
      ),
      'reference' => '0f56438b9197e224325e88f305346f0221df1f71',
    ),
    'phabel-transpiler74.cash/lrucache' => 
    array (
      'pretty_version' => '1.0.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '4fa4c6834cec59690b43526c4da41d6153026289',
    ),
    'phabel-transpiler74.danog/dns-over-https' => 
    array (
      'pretty_version' => '0.2.6',
      'version' => '0.2.6.0',
      'aliases' => 
      array (
      ),
      'reference' => 'a288be1f4fdd4ce9838e98bfa96407fcfdd099b3',
    ),
    'phabel-transpiler74.danog/ipc' => 
    array (
      'pretty_version' => '0.1.15',
      'version' => '0.1.15.0',
      'aliases' => 
      array (
      ),
      'reference' => '6bbd35f057746dba2baad58465fca1a93302bf67',
    ),
    'phabel-transpiler74.danog/libdns-json' => 
    array (
      'pretty_version' => '0.1.1',
      'version' => '0.1.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '7d5e07815d57afa64ef7cdbe1a65fbead9a3e7bd',
    ),
    'phabel-transpiler74.danog/loop' => 
    array (
      'pretty_version' => '0.1.1',
      'version' => '0.1.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'b1941cc6a7b2eede57d11a6ead464ee70793bc3f',
    ),
    'phabel-transpiler74.danog/magicalserializer' => 
    array (
      'pretty_version' => '1.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '87b6ed05a86021e9364f31133089bb83980d5e24',
    ),
    'phabel-transpiler74.danog/primemodule' => 
    array (
      'pretty_version' => '1.0.7',
      'version' => '1.0.7.0',
      'aliases' => 
      array (
      ),
      'reference' => '371cf2521dc665875cac5765259240c0666de69c',
    ),
    'phabel-transpiler74.danog/tg-file-decoder' => 
    array (
      'pretty_version' => '0.1.8',
      'version' => '0.1.8.0',
      'aliases' => 
      array (
      ),
      'reference' => '336d0bd69f3eb0592fab7c3e934cdd0e4a8acf61',
    ),
    'phabel-transpiler74.daverandom/libdns' => 
    array (
      'pretty_version' => 'v2.0.2',
      'version' => '2.0.2.0',
      'aliases' => 
      array (
      ),
      'reference' => 'e8b6d6593d18ac3a6a14666d8a68a4703b2e05f9',
    ),
    'phabel-transpiler74.erusev/parsedown' => 
    array (
      'pretty_version' => '1.7.4',
      'version' => '1.7.4.0',
      'aliases' => 
      array (
      ),
      'reference' => 'cb17b6477dfff935958ba01325f2e8a2bfa6dab3',
    ),
    'phabel-transpiler74.kelunik/certificate' => 
    array (
      'pretty_version' => 'v1.1.2',
      'version' => '1.1.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '56542e62d51533d04d0a9713261fea546bff80f6',
    ),
    'phabel-transpiler74.league/uri' => 
    array (
      'pretty_version' => '6.5.0',
      'version' => '6.5.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'c68ca445abb04817d740ddd6d0b3551826ef0c5a',
    ),
    'phabel-transpiler74.league/uri-interfaces' => 
    array (
      'pretty_version' => '2.3.0',
      'version' => '2.3.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '00e7e2943f76d8cb50c7dfdc2f6dee356e15e383',
    ),
    'phabel-transpiler74.league/uri-parser' => 
    array (
      'pretty_version' => '1.4.1',
      'version' => '1.4.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '671548427e4c932352d9b9279fdfa345bf63fa00',
    ),
    'phabel-transpiler74.monolog/monolog' => 
    array (
      'pretty_version' => '2.3.5',
      'version' => '2.3.5.0',
      'aliases' => 
      array (
      ),
      'reference' => 'fd4380d6fc37626e2f799f29d91195040137eba9',
    ),
    'phabel-transpiler74.paragonie/constant_time_encoding' => 
    array (
      'pretty_version' => 'v2.4.0',
      'version' => '2.4.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c',
    ),
    'phabel-transpiler74.paragonie/random_compat' => 
    array (
      'pretty_version' => 'v9.99.100',
      'version' => '9.99.100.0',
      'aliases' => 
      array (
      ),
      'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
    ),
    'phabel-transpiler74.phpseclib/phpseclib' => 
    array (
      'pretty_version' => '3.0.12',
      'version' => '3.0.12.0',
      'aliases' => 
      array (
      ),
      'reference' => '89bfb45bd8b1abc3b37e910d57f5dbd3174f40fb',
    ),
    'phabel-transpiler74.psr/http-factory' => 
    array (
      'pretty_version' => '1.0.1',
      'version' => '1.0.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
    ),
    'phabel-transpiler74.psr/http-message' => 
    array (
      'pretty_version' => '1.0.1',
      'version' => '1.0.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
    ),
    'phabel-transpiler74.psr/log' => 
    array (
      'pretty_version' => '1.1.4',
      'version' => '1.1.4.0',
      'aliases' => 
      array (
      ),
      'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
    ),
    'phabel-transpiler74.symfony/polyfill-mbstring' => 
    array (
      'pretty_version' => 'v1.23.1',
      'version' => '1.23.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
    ),
    'phabel-transpiler74.symfony/polyfill-php80' => 
    array (
      'pretty_version' => 'v1.23.1',
      'version' => '1.23.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '1100343ed1a92e3a38f9ae122fc0eb21602547be',
    ),
    'phabel/phabel' => 
    array (
      'pretty_version' => '1.0.49.74',
      'version' => '1.0.49.74',
      'aliases' => 
      array (
      ),
      'reference' => '129bb83be33fb0cb5ddcf4a1ffe9d7843c176ba7',
    ),
    'phabelio/phabel' => 
    array (
      'provided' => 
      array (
        0 => '1.0.49.74',
      ),
    ),
    'phpseclib/phpseclib' => 
    array (
      'provided' => 
      array (
        0 => '3.0.12.0',
      ),
    ),
    'psr/http-factory' => 
    array (
      'provided' => 
      array (
        0 => '1.0.1.0',
      ),
    ),
    'psr/http-message' => 
    array (
      'provided' => 
      array (
        0 => '1.0.1.0',
      ),
    ),
    'psr/log' => 
    array (
      'provided' => 
      array (
        0 => '1.1.4.0',
      ),
    ),
    'psr/log-implementation' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0 || 2.0.0 || 3.0.0',
      ),
    ),
    'symfony/polyfill-mbstring' => 
    array (
      'provided' => 
      array (
        0 => '1.23.1.0',
      ),
    ),
    'symfony/polyfill-php80' => 
    array (
      'provided' => 
      array (
        0 => '1.23.1.0',
      ),
    ),
  ),
);
<?php

/*
 * This file is part of Composer.
 *
 * (c) Nils Adermann <naderman@naderman.de>
 *     Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Composer;

use Composer\Autoload\ClassLoader;
use Composer\Semver\VersionParser;

/**
 * This class is copied in every Composer installed project and available to all
 *
 * To require it's presence, you can require `composer-runtime-api ^2.0`
 */
class InstalledVersions
{
    private static $installed = array (
  'root' => 
  array (
    'pretty_version' => '1.0.0+no-version-set',
    'version' => '1.0.0.0',
    'aliases' => 
    array (
    ),
    'reference' => NULL,
    'name' => 'danog/madelineprotophar',
  ),
  'versions' => 
  array (
    'amphp/amp' => 
    array (
      'provided' => 
      array (
        0 => '2.6.1.0',
      ),
    ),
    'amphp/byte-stream' => 
    array (
      'provided' => 
      array (
        0 => '1.8.1.0',
      ),
    ),
    'amphp/cache' => 
    array (
      'provided' => 
      array (
        0 => '1.5.0.0',
      ),
    ),
    'amphp/dns' => 
    array (
      'provided' => 
      array (
        0 => '1.2.3.0',
      ),
    ),
    'amphp/file' => 
    array (
      'provided' => 
      array (
        0 => '2.0.2.0',
      ),
    ),
    'amphp/hpack' => 
    array (
      'provided' => 
      array (
        0 => '3.1.1.0',
      ),
    ),
    'amphp/http' => 
    array (
      'provided' => 
      array (
        0 => '1.6.3.0',
      ),
    ),
    'amphp/http-client' => 
    array (
      'provided' => 
      array (
        0 => '4.6.2.0',
      ),
    ),
    'amphp/http-client-cookies' => 
    array (
      'provided' => 
      array (
        0 => '1.2.0.0',
      ),
    ),
    'amphp/log' => 
    array (
      'provided' => 
      array (
        0 => '1.1.0.0',
      ),
    ),
    'amphp/mysql' => 
    array (
      'provided' => 
      array (
        0 => '2.1.2.0',
      ),
    ),
    'amphp/parallel' => 
    array (
      'provided' => 
      array (
        0 => '1.4.1.0',
      ),
    ),
    'amphp/parser' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'amphp/postgres' => 
    array (
      'provided' => 
      array (
        0 => '1.4.3.0',
      ),
    ),
    'amphp/process' => 
    array (
      'provided' => 
      array (
        0 => '1.1.3.0',
      ),
    ),
    'amphp/redis' => 
    array (
      'provided' => 
      array (
        0 => '1.0.6.0',
      ),
    ),
    'amphp/serialization' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'amphp/socket' => 
    array (
      'provided' => 
      array (
        0 => '1.2.0.0',
      ),
    ),
    'amphp/sql' => 
    array (
      'provided' => 
      array (
        0 => '1.0.1.0',
      ),
    ),
    'amphp/sql-common' => 
    array (
      'provided' => 
      array (
        0 => '1.1.2.0',
      ),
    ),
    'amphp/sync' => 
    array (
      'provided' => 
      array (
        0 => '1.4.2.0',
      ),
    ),
    'amphp/websocket' => 
    array (
      'provided' => 
      array (
        0 => '1.0.2.0',
      ),
    ),
    'amphp/websocket-client' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'amphp/windows-registry' => 
    array (
      'provided' => 
      array (
        0 => '0.3.3.0',
      ),
    ),
    'cash/lrucache' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'danog/dns-over-https' => 
    array (
      'provided' => 
      array (
        0 => '0.2.6.0',
      ),
    ),
    'danog/ipc' => 
    array (
      'provided' => 
      array (
        0 => '0.1.15.0',
      ),
    ),
    'danog/libdns-json' => 
    array (
      'provided' => 
      array (
        0 => '0.1.1.0',
      ),
    ),
    'danog/loop' => 
    array (
      'provided' => 
      array (
        0 => '0.1.1.0',
      ),
    ),
    'danog/madelineproto' => 
    array (
      'pretty_version' => '907.0.50.9998',
      'version' => '907.0.50.9998',
      'aliases' => 
      array (
      ),
      'reference' => '78415171d2099c1c24d6c113217ebba7888309ad',
    ),
    'danog/madelineprotophar' => 
    array (
      'pretty_version' => '1.0.0+no-version-set',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => NULL,
    ),
    'danog/magicalserializer' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0.0',
      ),
    ),
    'danog/primemodule' => 
    array (
      'provided' => 
      array (
        0 => '1.0.7.0',
      ),
    ),
    'danog/tg-file-decoder' => 
    array (
      'provided' => 
      array (
        0 => '0.1.8.0',
      ),
    ),
    'daverandom/libdns' => 
    array (
      'provided' => 
      array (
        0 => '2.0.2.0',
      ),
    ),
    'erusev/parsedown' => 
    array (
      'provided' => 
      array (
        0 => '1.7.4.0',
      ),
    ),
    'kelunik/certificate' => 
    array (
      'provided' => 
      array (
        0 => '1.1.2.0',
      ),
    ),
    'league/uri' => 
    array (
      'provided' => 
      array (
        0 => '6.5.0.0',
      ),
    ),
    'league/uri-interfaces' => 
    array (
      'provided' => 
      array (
        0 => '2.3.0.0',
      ),
    ),
    'league/uri-parser' => 
    array (
      'provided' => 
      array (
        0 => '1.4.1.0',
      ),
    ),
    'monolog/monolog' => 
    array (
      'provided' => 
      array (
        0 => '2.3.5.0',
      ),
    ),
    'paragonie/constant_time_encoding' => 
    array (
      'provided' => 
      array (
        0 => '2.4.0.0',
      ),
    ),
    'paragonie/random_compat' => 
    array (
      'provided' => 
      array (
        0 => '9.99.100.0',
      ),
    ),
    'phabel-transpiler74.amphp/amp' => 
    array (
      'pretty_version' => 'v2.6.1',
      'version' => '2.6.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'c5fc66a78ee38d7ac9195a37bacaf940eb3f65ae',
    ),
    'phabel-transpiler74.amphp/byte-stream' => 
    array (
      'pretty_version' => 'v1.8.1',
      'version' => '1.8.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'acbd8002b3536485c997c4e019206b3f10ca15bd',
    ),
    'phabel-transpiler74.amphp/cache' => 
    array (
      'pretty_version' => 'v1.5.0',
      'version' => '1.5.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '2b6b5dbb70e54cc914df9952ba7c012bc4cbcd28',
    ),
    'phabel-transpiler74.amphp/dns' => 
    array (
      'pretty_version' => 'v1.2.3',
      'version' => '1.2.3.0',
      'aliases' => 
      array (
      ),
      'reference' => '852292532294d7972c729a96b49756d781f7c59d',
    ),
    'phabel-transpiler74.amphp/file' => 
    array (
      'pretty_version' => 'v2.0.2',
      'version' => '2.0.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '3d3d084b81a5322d203e11617f7cbe3ea16c40ca',
    ),
    'phabel-transpiler74.amphp/hpack' => 
    array (
      'pretty_version' => 'v3.1.1',
      'version' => '3.1.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'cf4f1663e9fd58f60258c06177098655ca6377a5',
    ),
    'phabel-transpiler74.amphp/http' => 
    array (
      'pretty_version' => 'v1.6.3',
      'version' => '1.6.3.0',
      'aliases' => 
      array (
      ),
      'reference' => 'e2b75561011a9596e4574cc867e07a706d56394b',
    ),
    'phabel-transpiler74.amphp/http-client' => 
    array (
      'pretty_version' => 'v4.6.2',
      'version' => '4.6.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '453f84f623e409889168351e60246f5feddc1b3c',
    ),
    'phabel-transpiler74.amphp/http-client-cookies' => 
    array (
      'pretty_version' => 'v1.2.0',
      'version' => '1.2.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'ab7e498bb6c4e389e2b9880727d6470997189d87',
    ),
    'phabel-transpiler74.amphp/log' => 
    array (
      'pretty_version' => 'v1.1.0',
      'version' => '1.1.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '25dcd3b58622bd22ffa7129288edb85e0c17081a',
    ),
    'phabel-transpiler74.amphp/mysql' => 
    array (
      'pretty_version' => 'v2.1.2',
      'version' => '2.1.2.0',
      'aliases' => 
      array (
      ),
      'reference' => 'd0b9a618b45ad3a10452a3860056db76a6930a75',
    ),
    'phabel-transpiler74.amphp/parallel' => 
    array (
      'pretty_version' => 'v1.4.1',
      'version' => '1.4.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'fbc128383c1ffb3823866f71b88d8c4722a25ce9',
    ),
    'phabel-transpiler74.amphp/parser' => 
    array (
      'pretty_version' => 'v1.0.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f83e68f03d5b8e8e0365b8792985a7f341c57ae1',
    ),
    'phabel-transpiler74.amphp/postgres' => 
    array (
      'pretty_version' => 'v1.4.3',
      'version' => '1.4.3.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f52cc35ef02ee4ad709083e0432c2288d4df7de0',
    ),
    'phabel-transpiler74.amphp/process' => 
    array (
      'pretty_version' => 'v1.1.3',
      'version' => '1.1.3.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f09e3ed3b0a953ccbfff1140f12be4a884f0aa83',
    ),
    'phabel-transpiler74.amphp/redis' => 
    array (
      'pretty_version' => 'v1.0.6',
      'version' => '1.0.6.0',
      'aliases' => 
      array (
      ),
      'reference' => '1eade91c18aecd4708ea35e2d745a71e8a5c1354',
    ),
    'phabel-transpiler74.amphp/serialization' => 
    array (
      'pretty_version' => 'v1.0.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '693e77b2fb0b266c3c7d622317f881de44ae94a1',
    ),
    'phabel-transpiler74.amphp/socket' => 
    array (
      'pretty_version' => 'v1.2.0',
      'version' => '1.2.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'a8af9f5d0a66c5fe9567da45a51509e592788fe6',
    ),
    'phabel-transpiler74.amphp/sql' => 
    array (
      'pretty_version' => 'v1.0.1',
      'version' => '1.0.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '0445ac35623a18105efeac93364288434430a4d8',
    ),
    'phabel-transpiler74.amphp/sql-common' => 
    array (
      'pretty_version' => 'v1.1.2',
      'version' => '1.1.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '1c3b86970373d2ae00482300cae1442d4e9bd782',
    ),
    'phabel-transpiler74.amphp/sync' => 
    array (
      'pretty_version' => 'v1.4.2',
      'version' => '1.4.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '85ab06764f4f36d63b1356b466df6111cf4b89cf',
    ),
    'phabel-transpiler74.amphp/websocket' => 
    array (
      'pretty_version' => 'v1.0.2',
      'version' => '1.0.2.0',
      'aliases' => 
      array (
      ),
      'reference' => 'd0e61e3e34ac09ec230ae0eff2b8beaf8f83a8f9',
    ),
    'phabel-transpiler74.amphp/websocket-client' => 
    array (
      'pretty_version' => 'v1.0.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '173b54137cdcd4288702f615f05c1029e613ba37',
    ),
    'phabel-transpiler74.amphp/windows-registry' => 
    array (
      'pretty_version' => 'v0.3.3',
      'version' => '0.3.3.0',
      'aliases' => 
      array (
      ),
      'reference' => '0f56438b9197e224325e88f305346f0221df1f71',
    ),
    'phabel-transpiler74.cash/lrucache' => 
    array (
      'pretty_version' => '1.0.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '4fa4c6834cec59690b43526c4da41d6153026289',
    ),
    'phabel-transpiler74.danog/dns-over-https' => 
    array (
      'pretty_version' => '0.2.6',
      'version' => '0.2.6.0',
      'aliases' => 
      array (
      ),
      'reference' => 'a288be1f4fdd4ce9838e98bfa96407fcfdd099b3',
    ),
    'phabel-transpiler74.danog/ipc' => 
    array (
      'pretty_version' => '0.1.15',
      'version' => '0.1.15.0',
      'aliases' => 
      array (
      ),
      'reference' => '6bbd35f057746dba2baad58465fca1a93302bf67',
    ),
    'phabel-transpiler74.danog/libdns-json' => 
    array (
      'pretty_version' => '0.1.1',
      'version' => '0.1.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '7d5e07815d57afa64ef7cdbe1a65fbead9a3e7bd',
    ),
    'phabel-transpiler74.danog/loop' => 
    array (
      'pretty_version' => '0.1.1',
      'version' => '0.1.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'b1941cc6a7b2eede57d11a6ead464ee70793bc3f',
    ),
    'phabel-transpiler74.danog/magicalserializer' => 
    array (
      'pretty_version' => '1.0',
      'version' => '1.0.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '87b6ed05a86021e9364f31133089bb83980d5e24',
    ),
    'phabel-transpiler74.danog/primemodule' => 
    array (
      'pretty_version' => '1.0.7',
      'version' => '1.0.7.0',
      'aliases' => 
      array (
      ),
      'reference' => '371cf2521dc665875cac5765259240c0666de69c',
    ),
    'phabel-transpiler74.danog/tg-file-decoder' => 
    array (
      'pretty_version' => '0.1.8',
      'version' => '0.1.8.0',
      'aliases' => 
      array (
      ),
      'reference' => '336d0bd69f3eb0592fab7c3e934cdd0e4a8acf61',
    ),
    'phabel-transpiler74.daverandom/libdns' => 
    array (
      'pretty_version' => 'v2.0.2',
      'version' => '2.0.2.0',
      'aliases' => 
      array (
      ),
      'reference' => 'e8b6d6593d18ac3a6a14666d8a68a4703b2e05f9',
    ),
    'phabel-transpiler74.erusev/parsedown' => 
    array (
      'pretty_version' => '1.7.4',
      'version' => '1.7.4.0',
      'aliases' => 
      array (
      ),
      'reference' => 'cb17b6477dfff935958ba01325f2e8a2bfa6dab3',
    ),
    'phabel-transpiler74.kelunik/certificate' => 
    array (
      'pretty_version' => 'v1.1.2',
      'version' => '1.1.2.0',
      'aliases' => 
      array (
      ),
      'reference' => '56542e62d51533d04d0a9713261fea546bff80f6',
    ),
    'phabel-transpiler74.league/uri' => 
    array (
      'pretty_version' => '6.5.0',
      'version' => '6.5.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'c68ca445abb04817d740ddd6d0b3551826ef0c5a',
    ),
    'phabel-transpiler74.league/uri-interfaces' => 
    array (
      'pretty_version' => '2.3.0',
      'version' => '2.3.0.0',
      'aliases' => 
      array (
      ),
      'reference' => '00e7e2943f76d8cb50c7dfdc2f6dee356e15e383',
    ),
    'phabel-transpiler74.league/uri-parser' => 
    array (
      'pretty_version' => '1.4.1',
      'version' => '1.4.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '671548427e4c932352d9b9279fdfa345bf63fa00',
    ),
    'phabel-transpiler74.monolog/monolog' => 
    array (
      'pretty_version' => '2.3.5',
      'version' => '2.3.5.0',
      'aliases' => 
      array (
      ),
      'reference' => 'fd4380d6fc37626e2f799f29d91195040137eba9',
    ),
    'phabel-transpiler74.paragonie/constant_time_encoding' => 
    array (
      'pretty_version' => 'v2.4.0',
      'version' => '2.4.0.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c',
    ),
    'phabel-transpiler74.paragonie/random_compat' => 
    array (
      'pretty_version' => 'v9.99.100',
      'version' => '9.99.100.0',
      'aliases' => 
      array (
      ),
      'reference' => '996434e5492cb4c3edcb9168db6fbb1359ef965a',
    ),
    'phabel-transpiler74.phpseclib/phpseclib' => 
    array (
      'pretty_version' => '3.0.12',
      'version' => '3.0.12.0',
      'aliases' => 
      array (
      ),
      'reference' => '89bfb45bd8b1abc3b37e910d57f5dbd3174f40fb',
    ),
    'phabel-transpiler74.psr/http-factory' => 
    array (
      'pretty_version' => '1.0.1',
      'version' => '1.0.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '12ac7fcd07e5b077433f5f2bee95b3a771bf61be',
    ),
    'phabel-transpiler74.psr/http-message' => 
    array (
      'pretty_version' => '1.0.1',
      'version' => '1.0.1.0',
      'aliases' => 
      array (
      ),
      'reference' => 'f6561bf28d520154e4b0ec72be95418abe6d9363',
    ),
    'phabel-transpiler74.psr/log' => 
    array (
      'pretty_version' => '1.1.4',
      'version' => '1.1.4.0',
      'aliases' => 
      array (
      ),
      'reference' => 'd49695b909c3b7628b6289db5479a1c204601f11',
    ),
    'phabel-transpiler74.symfony/polyfill-mbstring' => 
    array (
      'pretty_version' => 'v1.23.1',
      'version' => '1.23.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '9174a3d80210dca8daa7f31fec659150bbeabfc6',
    ),
    'phabel-transpiler74.symfony/polyfill-php80' => 
    array (
      'pretty_version' => 'v1.23.1',
      'version' => '1.23.1.0',
      'aliases' => 
      array (
      ),
      'reference' => '1100343ed1a92e3a38f9ae122fc0eb21602547be',
    ),
    'phabel/phabel' => 
    array (
      'pretty_version' => '1.0.49.74',
      'version' => '1.0.49.74',
      'aliases' => 
      array (
      ),
      'reference' => '129bb83be33fb0cb5ddcf4a1ffe9d7843c176ba7',
    ),
    'phabelio/phabel' => 
    array (
      'provided' => 
      array (
        0 => '1.0.49.74',
      ),
    ),
    'phpseclib/phpseclib' => 
    array (
      'provided' => 
      array (
        0 => '3.0.12.0',
      ),
    ),
    'psr/http-factory' => 
    array (
      'provided' => 
      array (
        0 => '1.0.1.0',
      ),
    ),
    'psr/http-message' => 
    array (
      'provided' => 
      array (
        0 => '1.0.1.0',
      ),
    ),
    'psr/log' => 
    array (
      'provided' => 
      array (
        0 => '1.1.4.0',
      ),
    ),
    'psr/log-implementation' => 
    array (
      'provided' => 
      array (
        0 => '1.0.0 || 2.0.0 || 3.0.0',
      ),
    ),
    'symfony/polyfill-mbstring' => 
    array (
      'provided' => 
      array (
        0 => '1.23.1.0',
      ),
    ),
    'symfony/polyfill-php80' => 
    array (
      'provided' => 
      array (
        0 => '1.23.1.0',
      ),
    ),
  ),
);
    private static $canGetVendors;
    private static $installedByVendor = array();

    /**
     * Returns a list of all package names which are present, either by being installed, replaced or provided
     *
     * @return string[]
     * @psalm-return list<string>
     */
    public static function getInstalledPackages()
    {
        $packages = array();
        foreach (self::getInstalled() as $installed) {
            $packages[] = array_keys($installed['versions']);
        }


        if (1 === \count($packages)) {
            return $packages[0];
        }

        return array_keys(array_flip(\call_user_func_array('array_merge', $packages)));
    }

    /**
     * Checks whether the given package is installed
     *
     * This also returns true if the package name is provided or replaced by another package
     *
     * @param  string $packageName
     * @return bool
     */
    public static function isInstalled($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (isset($installed['versions'][$packageName])) {
                return true;
            }
        }

        return false;
    }

    /**
     * Checks whether the given package satisfies a version constraint
     *
     * e.g. If you want to know whether version 2.3+ of package foo/bar is installed, you would call:
     *
     *   Composer\InstalledVersions::satisfies(new VersionParser, 'foo/bar', '^2.3')
     *
     * @param VersionParser $parser      Install composer/semver to have access to this class and functionality
     * @param string        $packageName
     * @param string|null   $constraint  A version constraint to check for, if you pass one you have to make sure composer/semver is required by your package
     *
     * @return bool
     */
    public static function satisfies(VersionParser $parser, $packageName, $constraint)
    {
        $constraint = $parser->parseConstraints($constraint);
        $provided = $parser->parseConstraints(self::getVersionRanges($packageName));

        return $provided->matches($constraint);
    }

    /**
     * Returns a version constraint representing all the range(s) which are installed for a given package
     *
     * It is easier to use this via isInstalled() with the $constraint argument if you need to check
     * whether a given version of a package is installed, and not just whether it exists
     *
     * @param  string $packageName
     * @return string Version constraint usable with composer/semver
     */
    public static function getVersionRanges($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            $ranges = array();
            if (isset($installed['versions'][$packageName]['pretty_version'])) {
                $ranges[] = $installed['versions'][$packageName]['pretty_version'];
            }
            if (array_key_exists('aliases', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['aliases']);
            }
            if (array_key_exists('replaced', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['replaced']);
            }
            if (array_key_exists('provided', $installed['versions'][$packageName])) {
                $ranges = array_merge($ranges, $installed['versions'][$packageName]['provided']);
            }

            return implode(' || ', $ranges);
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['version'])) {
                return null;
            }

            return $installed['versions'][$packageName]['version'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as version, use satisfies or getVersionRanges if you need to know if a given version is present
     */
    public static function getPrettyVersion($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['pretty_version'])) {
                return null;
            }

            return $installed['versions'][$packageName]['pretty_version'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @param  string      $packageName
     * @return string|null If the package is being replaced or provided but is not really installed, null will be returned as reference
     */
    public static function getReference($packageName)
    {
        foreach (self::getInstalled() as $installed) {
            if (!isset($installed['versions'][$packageName])) {
                continue;
            }

            if (!isset($installed['versions'][$packageName]['reference'])) {
                return null;
            }

            return $installed['versions'][$packageName]['reference'];
        }

        throw new \OutOfBoundsException('Package "' . $packageName . '" is not installed');
    }

    /**
     * @return array
     * @psalm-return array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}
     */
    public static function getRootPackage()
    {
        $installed = self::getInstalled();

        return $installed[0]['root'];
    }

    /**
     * Returns the raw installed.php data for custom implementations
     *
     * @return array[]
     * @psalm-return array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}, versions: list<string, array{pretty_version: ?string, version: ?string, aliases: ?string[], reference: ?string, replaced: ?string[], provided: ?string[]}>}
     */
    public static function getRawData()
    {
        return self::$installed;
    }

    /**
     * Lets you reload the static array from another file
     *
     * This is only useful for complex integrations in which a project needs to use
     * this class but then also needs to execute another project's autoloader in process,
     * and wants to ensure both projects have access to their version of installed.php.
     *
     * A typical case would be PHPUnit, where it would need to make sure it reads all
     * the data it needs from this class, then call reload() with
     * `require $CWD/vendor/composer/installed.php` (or similar) as input to make sure
     * the project in which it runs can then also use this class safely, without
     * interference between PHPUnit's dependencies and the project's dependencies.
     *
     * @param  array[] $data A vendor/composer/installed.php data set
     * @return void
     *
     * @psalm-param array{root: array{name: string, version: string, reference: string, pretty_version: string, aliases: string[]}, versions: list<string, array{pretty_version: ?string, version: ?string, aliases: ?string[], reference: ?string, replaced: ?string[], provided: ?string[]}>} $data
     */
    public static function reload($data)
    {
        self::$installed = $data;
        self::$installedByVendor = array();
    }

    /**
     * @return array[]
     */
    private static function getInstalled()
    {
        if (null === self::$canGetVendors) {
            self::$canGetVendors = method_exists('Composer\Autoload\ClassLoader', 'getRegisteredLoaders');
        }

        $installed = array();

        if (self::$canGetVendors) {
            // @phpstan-ignore-next-line
            foreach (ClassLoader::getRegisteredLoaders() as $vendorDir => $loader) {
                if (isset(self::$installedByVendor[$vendorDir])) {
                    $installed[] = self::$installedByVendor[$vendorDir];
                } elseif (is_file($vendorDir.'/composer/installed.php')) {
                    $installed[] = self::$installedByVendor[$vendorDir] = require $vendorDir.'/composer/installed.php';
                }
            }
        }

        $installed[] = self::$installed;

        return $installed;
    }
}
<?php

require 'vendor/autoload.php';
use Amp\Loop;
use danog\Loop\Generic\GenericLoop;
use function Amp\delay;
Loop::run(function () {
    /** @var GenericLoop[] */
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $callable = function () {
            static $number = 0;
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
            return $number < 10 ? 1000 : GenericLoop::STOP;
        };
        $loop = new GenericLoop($callable, "Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Resuming prematurely all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->resume();
    }
    echo "OK done, waiting 5 more seconds!" . PHP_EOL;
    (yield delay(5000));
    echo "Closing all loops!" . PHP_EOL;
    (yield delay(10));
});<?php

require 'vendor/autoload.php';
use Amp\Loop;
use danog\Loop\Generic\PeriodicLoop;
use function Amp\delay;
Loop::run(function () {
    /** @var PeriodicLoop[] */
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $callable = function () {
            static $number = 0;
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
            return $number == 10;
        };
        $loop = new PeriodicLoop($callable, "Loop number {$x}", 1000);
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Resuming prematurely all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->resume();
    }
    echo "OK done, waiting 5 more seconds!" . PHP_EOL;
    (yield delay(5000));
    echo "Closing all loops!" . PHP_EOL;
    (yield delay(10));
});<?php

require 'vendor/autoload.php';
use Amp\Loop as AmpLoop;
use danog\Loop\ResumableLoop;
use function Amp\delay;
class MyLoop extends ResumableLoop
{
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Constructor.
     *
     * @param string $name Loop name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $number = 0;
        while (true) {
            (yield $this->pause(1000));
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
        }
    }
    // Optionally, we can also define logging methods
    /**
     * Started loop.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        parent::startedLoop();
        echo "Started loop {$this}!" . PHP_EOL;
    }
    /**
     * Exited loop.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        parent::exitedLoop();
        echo "Exited loop {$this}!" . PHP_EOL;
    }
    // End of logging methods
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
AmpLoop::run(function () {
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $loop = new MyLoop("Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Resuming prematurely all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->resume();
    }
});<?php

require 'vendor/autoload.php';
use Amp\Loop;
use danog\Loop\SignalLoop;
use function Amp\delay;
class SigLoop extends SignalLoop
{
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Constructor.
     *
     * @param string $name Loop name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $number = 0;
        while (true) {
            if ((yield $this->waitSignal(delay(1000)))) {
                echo "Got exit signal in {$this}!" . PHP_EOL;
                return;
            }
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
        }
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
Loop::run(function () {
    /** @var SigLoop[] */
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $loop = new SigLoop("Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Closing all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->signal(true);
    }
});<?php

require 'vendor/autoload.php';
use Amp\Loop;
use danog\Loop\ResumableSignalLoop;
use function Amp\delay;
class ResSigLoop extends ResumableSignalLoop
{
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Constructor.
     *
     * @param string $name Loop name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $number = 0;
        while (true) {
            if ((yield $this->waitSignal($this->pause(1000)))) {
                echo "Got exit signal in {$this}!" . PHP_EOL;
                return;
            }
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
        }
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
Loop::run(function () {
    /** @var ResSigLoop[] */
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $loop = new ResSigLoop("Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Resuming prematurely all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->resume();
    }
    echo "OK done, waiting 5 more seconds!" . PHP_EOL;
    (yield delay(5000));
    echo "Closing all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->signal(true);
    }
});<?php

require 'vendor/autoload.php';
use Amp\Loop as AmpLoop;
use danog\Loop\Loop;
use function Amp\delay;
class MyLoop extends Loop
{
    /**
     * Callable.
     *
     * @var callable
     */
    private $callable;
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Constructor.
     *
     * @param callable $callable Callable
     * @param string $name Loop name
     */
    public function __construct(callable $callable, string $name)
    {
        $this->callable = $callable;
        $this->name = $name;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $callable = $this->callable;
        $number = 0;
        while (true) {
            $number = (yield from $callable($number));
            echo "{$this}: {$number}" . PHP_EOL;
        }
    }
    // Optionally, we can also define logging methods
    /**
     * Started loop.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        parent::startedLoop();
        echo "Started loop {$this}!" . PHP_EOL;
    }
    /**
     * Exited loop.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        parent::exitedLoop();
        echo "Exited loop {$this}!" . PHP_EOL;
    }
    // End of logging methods
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
AmpLoop::run(function () {
    $function = function (int $number) : \Generator {
        (yield delay(1000));
        return $number + 1;
    };
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $loop = new MyLoop($function, "Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
});{
    "name": "danog/loop",
    "description": "Loop abstraction for AMPHP.",
    "keywords": [
        "asynchronous",
        "async",
        "concurrent",
        "multi-threading",
        "multi-processing"
    ],
    "homepage": "https://github.com/danog/loop",
    "license": "MIT",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2"
    },
    "require-dev": {
        "phpunit/phpunit": "^7 | ^8 | ^9",
        "amphp/phpunit-util": "^1.3",
        "amphp/php-cs-fixer-config": "dev-master",
        "vimeo/psalm": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "danog\\Loop\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "danog\\Loop\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "phpdbg -qrr -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

/**
 * Generic loop.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Generic;

use Amp\Promise;
use danog\Loop\ResumableSignalLoop;
/**
 * Generic loop, runs single callable.
 *
 * The return value of the callable can be:
 * * A number - the loop will be paused for the specified number of seconds
 * * GenericLoop::STOP - The loop will stop
 * * GenericLoop::PAUSE - The loop will pause forever (or until loop is `resumed()`
 *                        from outside the loop)
 * * GenericLoop::CONTINUE - Return this if you want to rerun the loop immediately
 *
 * If the callable does not return anything,
 * the loop will behave is if GenericLoop::PAUSE was returned.
 *
 * The loop can be stopped from the outside by signaling `true`.
 *
 * @template T as int|null
 * @template TGenerator as \Generator<mixed,Promise|array<array-key,Promise>,mixed,Promise<T>|T>
 * @template TPromise as Promise<T>
 *
 * @template TCallable as T|TPromise|TGenerator
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class GenericLoop extends ResumableSignalLoop
{
    /**
     * Stop the loop.
     */
    const STOP = -1;
    /**
     * Pause the loop.
     */
    const PAUSE = null;
    /**
     * Rerun the loop.
     */
    const CONTINUE = 0;
    /**
     * Callable.
     *
     * @var callable
     *
     * @psalm-var callable():TCallable
     */
    protected $callable;
    /**
     * Loop name.
     *
     * @var string
     */
    protected $name;
    /**
     * Constructor.
     *
     * If possible, the callable will be bound to the current instance of the loop.
     *
     * @param callable $callable Callable to run
     * @param string $name Loop name
     *
     * @psalm-param callable(): TCallable $callable Callable to run
     */
    public function __construct(callable $callable, string $name)
    {
        if ($callable instanceof \Closure) {
            try {
                $callable = $callable->bindTo($this);
            } catch (\Throwable $e) {
                // Might cause an error for wrapped object methods
            }
        }
        $this->callable = $callable;
        $this->name = $name;
    }
    /**
     * Loop implementation.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $callable = $this->callable;
        while (true) {
            /** @psalm-var ?int|TGenerator|TPromise */
            $timeout = $callable();
            if ($timeout instanceof \Generator) {
                /** @psalm-var ?int */
                $timeout = (yield from $timeout);
            } elseif ($timeout instanceof Promise) {
                /** @psalm-var ?int */
                $timeout = (yield $timeout);
            }
            if ($timeout === self::PAUSE) {
                $this->reportPause(0);
            } elseif ($timeout > 0) {
                $this->reportPause($timeout);
            }
            /** @psalm-suppress MixedArgument */
            if ($timeout === self::STOP || (yield $this->waitSignal($this->pause($timeout)))) {
                break;
            }
        }
    }
    /**
     * Report pause, can be overriden for logging.
     *
     * @param integer $timeout Pause duration, 0 = forever
     *
     * @return void
     */
    protected function reportPause(int $timeout) : void
    {
    }
    /**
     * Get loop name, provided to constructor.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}<?php

/**
 * Periodic loop.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Generic;

use Amp\Promise;
use danog\Loop\ResumableSignalLoop;
/**
 * Periodic loop.
 *
 * Runs a callback at a periodic interval.
 *
 * The loop can be stopped from the outside or
 * from the inside by signaling or returning `true`.
 *
 * @template T as bool
 * @template TGenerator as \Generator<mixed,Promise|array<array-key,Promise>,mixed,Promise<T>|T>
 * @template TPromise as Promise<T>
 *
 * @template TCallable as T|TPromise|TGenerator
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class PeriodicLoop extends ResumableSignalLoop
{
    /**
     * Callback.
     *
     * @var callable
     *
     * @psalm-var callable():TCallable
     */
    private $callback;
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Loop interval.
     *
     * @var ?int
     */
    private $interval;
    /**
     * Constructor.
     *
     * If possible, the callable will be bound to the current instance of the loop.
     *
     * @param callable $callback Callback to call
     * @param string $name Loop name
     * @param ?int $interval Loop interval
     *
     * @psalm-param callable(): TCallable $callback Callable to run
     */
    public function __construct(callable $callback, string $name, ?int $interval)
    {
        if ($callback instanceof \Closure) {
            try {
                $callback = $callback->bindTo($this);
            } catch (\Throwable $e) {
                // Might cause an error for wrapped object methods
            }
        }
        $this->callback = $callback;
        $this->name = $name;
        $this->interval = $interval;
    }
    /**
     * Loop implementation.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $callback = $this->callback;
        while (true) {
            $result = $callback();
            if ($result instanceof \Generator) {
                /** @psalm-var TGenerator */
                $result = (yield from $result);
            } elseif ($result instanceof Promise) {
                /** @psalm-var TPromise */
                $result = (yield $result);
            }
            if ($result === true) {
                break;
            }
            /** @var ?bool */
            $result = (yield $this->waitSignal($this->pause($this->interval)));
            if ($result === true) {
                break;
            }
        }
    }
    /**
     * Get name of the loop, passed to the constructor.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}<?php

/**
 * Resumable loop class.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop;

use danog\Loop\Interfaces\ResumableLoopInterface;
use danog\Loop\Traits\ResumableLoop as TraitsResumableLoop;
/**
 * Resumable loop abstract class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
abstract class ResumableLoop implements ResumableLoopInterface
{
    use TraitsResumableLoop;
}<?php

/**
 * Signal loop class.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop;

use danog\Loop\Interfaces\SignalLoopInterface;
use danog\Loop\Traits\Loop;
use danog\Loop\Traits\SignalLoop as TraitsSignalLoop;
/**
 * Signal loop abstract class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
abstract class SignalLoop implements SignalLoopInterface
{
    use Loop;
    use TraitsSignalLoop;
}<?php

/**
 * Resumable signal loop class.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop;

use danog\Loop\Interfaces\ResumableLoopInterface;
use danog\Loop\Interfaces\SignalLoopInterface;
use danog\Loop\Traits\ResumableLoop;
use danog\Loop\Traits\SignalLoop;
/**
 * Resumable signal loop abstract class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
abstract class ResumableSignalLoop implements ResumableLoopInterface, SignalLoopInterface
{
    use ResumableLoop;
    use SignalLoop;
}<?php

/**
 * Loop class.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop;

use danog\Loop\Interfaces\LoopInterface;
use danog\Loop\Traits\Loop as TraitsLoop;
/**
 * Loop abstract class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
abstract class Loop implements LoopInterface
{
    use TraitsLoop;
}<?php

/**
 * Loop interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Interfaces;

/**
 * Loop interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface LoopInterface
{
    /**
     * Start the loop.
     *
     * Returns false if the loop is already running.
     *
     * @return bool
     */
    public function start() : bool;
    /**
     * The actual loop function.
     *
     * @return \Generator
     */
    public function loop() : \Generator;
    /**
     * Get name of the loop.
     *
     * @return string
     */
    public function __toString() : string;
    /**
     * Check whether loop is running.
     *
     * @return boolean
     */
    public function isRunning() : bool;
}<?php

/**
 * Resumable loop interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Interfaces;

use Amp\Promise;
/**
 * Resumable loop interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface ResumableLoopInterface extends LoopInterface
{
    /**
     * Pause the loop.
     *
     * @param ?int $time Milliseconds for how long to pause the loop, if null will pause forever (until resume is called from outside of the loop)
     *
     * @return Promise Resolved when the loop is resumed
     */
    public function pause(?int $time = null) : Promise;
    /**
     * Resume the loop.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resume() : Promise;
    /**
     * Defer resuming the loop to next tick.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resumeDefer() : Promise;
    /**
     * Defer resuming the loop to next tick.
     *
     * Multiple consecutive calls will yield only one resume.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resumeDeferOnce() : Promise;
}<?php

/**
 * Signal loop interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Interfaces;

use Amp\Promise;
/**
 * Signal loop interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface SignalLoopInterface extends LoopInterface
{
    /**
     * Send a signal to the the loop.
     *
     * @param (\Throwable | mixed) $data Signal to send
     *
     * @return void
     */
    public function signal($data) : void;
    /**
     * Resolve the promise or return|throw the signal.
     *
     * @param (Promise | \Generator) $promise The original promise or generator
     *
     * @return Promise
     *
     * @template T
     *
     * @psalm-param (Promise<T> | \Generator<mixed, (Promise | array<array-key, Promise>), mixed, (Promise<T> | T)>) $promise The original promise or generator
     *
     * @psalm-return Promise<(T | mixed)>
     */
    public function waitSignal($promise) : Promise;
}<?php

/**
 * Loop helper trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Traits;

use Amp\Deferred;
use Amp\Loop as AmpLoop;
use Amp\Promise;
use Amp\Success;
use Closure;
/**
 * Resumable loop helper trait.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait ResumableLoop
{
    use Loop {
        exitedLoop as private parentExitedLoop;
    }
    /**
     * Resume deferred.
     *
     * @var ?Deferred
     */
    private $resume;
    /**
     * Pause deferred.
     *
     * @var ?Deferred
     */
    private $pause;
    /**
     * Resume timer ID.
     *
     * @var ?string
     */
    private $resumeTimer;
    /**
     * Resume deferred ID.
     *
     * @var ?string
     */
    private $resumeDeferred;
    /**
     * Pause the loop.
     *
     * @param ?int $time For how long to pause the loop, if null will pause forever (until resume is called from outside of the loop)
     *
     * @return Promise Resolved when the loop is resumed
     */
    public function pause(?int $time = null) : Promise
    {
        if (!\is_null($time)) {
            if ($time <= 0) {
                return new Success(0);
            }
            if ($this->resumeTimer) {
                AmpLoop::cancel($this->resumeTimer);
                $this->resumeTimer = null;
            }
            /** @psalm-suppress MixedArgumentTypeCoercion */
            $this->resumeTimer = AmpLoop::delay($time, \Closure::fromCallable([$this, 'resumeInternal']));
        }
        $pause = $this->pause;
        $this->pause = new Deferred();
        if ($pause) {
            /**
             * @psalm-suppress InvalidArgument
             */
            AmpLoop::defer([$pause, 'resolve']);
        }
        $this->resume = new Deferred();
        return $this->resume->promise();
    }
    /**
     * Resume the loop.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resume() : Promise
    {
        if (!$this->pause) {
            $this->pause = new Deferred();
        }
        $promise = $this->pause->promise();
        $this->resumeInternal();
        return $promise;
    }
    /**
     * Defer resuming the loop to next tick.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resumeDefer() : Promise
    {
        /** @psalm-suppress MixedArgumentTypeCoercion */
        AmpLoop::defer(Closure::fromCallable([$this, 'resumeInternal']));
        if (!$this->pause) {
            $this->pause = new Deferred();
        }
        return $this->pause->promise();
    }
    /**
     * Defer resuming the loop to next tick.
     *
     * Multiple consecutive calls will yield only one resume.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resumeDeferOnce() : Promise
    {
        if (!$this->resumeDeferred) {
            $this->resumeDeferred = AmpLoop::defer(function () {
                $this->resumeDeferred = null;
                $this->resumeInternal();
            });
        }
        if (!$this->pause) {
            $this->pause = new Deferred();
        }
        return $this->pause->promise();
    }
    /**
     * Internal resume function.
     *
     * @return void
     */
    private function resumeInternal() : void
    {
        if ($this->resumeTimer) {
            $storedWatcherId = $this->resumeTimer;
            AmpLoop::cancel($storedWatcherId);
            $this->resumeTimer = null;
        }
        if ($this->resume) {
            $resume = $this->resume;
            $this->resume = null;
            $resume->resolve();
        }
    }
    /**
     * Signal that loop has exIited.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        $this->parentExitedLoop();
        if ($this->resumeTimer) {
            AmpLoop::cancel($this->resumeTimer);
            $this->resumeTimer = null;
        }
    }
}<?php

/**
 * Loop helper trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Traits;

use Amp\Coroutine;
use Amp\Deferred;
use Amp\Promise;
/**
 * Signal loop helper trait.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait SignalLoop
{
    /**
     * Signal deferred.
     *
     * @var ?Deferred
     */
    private $signalDeferred;
    /**
     * Send signal to loop.
     *
     * @param (mixed | \Throwable) $what Data to signal
     *
     * @return void
     */
    public function signal($what) : void
    {
        if ($this->signalDeferred) {
            $deferred = $this->signalDeferred;
            $this->signalDeferred = null;
            if ($what instanceof \Throwable) {
                $deferred->fail($what);
            } else {
                $deferred->resolve($what);
            }
        }
    }
    /**
     * Resolve the promise or return|throw the signal.
     *
     * @param (Promise | \Generator) $promise The original promise or generator
     *
     * @return Promise
     *
     * @template T
     *
     * @psalm-param (Promise<T> | \Generator<mixed, (Promise | array<array-key, Promise>), mixed, (Promise<T> | T)>) $promise The original promise or generator
     *
     * @psalm-return Promise<(T | mixed)>
     */
    public function waitSignal($promise) : Promise
    {
        if ($promise instanceof \Generator) {
            /** @psalm-suppress MixedArgumentTypeCoercion */
            $promise = new Coroutine($promise);
        }
        $this->signalDeferred = new Deferred();
        $combinedPromise = $this->signalDeferred->promise();
        $promise->onResolve(function () use($promise) {
            if ($this->signalDeferred !== null) {
                $deferred = $this->signalDeferred;
                $this->signalDeferred = null;
                $deferred->resolve($promise);
            }
        });
        return $combinedPromise;
    }
}<?php

/**
 * Loop helper trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Traits;

use Amp\Promise;
use function Amp\asyncCall;
/**
 * Loop helper trait.
 *
 * Wraps the asynchronous generator methods with asynchronous promise-based methods
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait Loop
{
    /**
     * Whether the loop was started.
     *
     * @var bool
     */
    private $started = false;
    /**
     * Start the loop.
     *
     * Returns false if the loop is already running.
     *
     * @return bool
     */
    public function start() : bool
    {
        if ($this->started) {
            return false;
        }
        asyncCall(function () : \Generator {
            $this->startedLoop();
            try {
                yield from $this->loop();
            } finally {
                $this->exitedLoop();
            }
        });
        return true;
    }
    /**
     * Signal that loop has exIited.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        $this->started = false;
    }
    /**
     * Signal that loop has started.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        $this->started = true;
    }
    /**
     * Check whether loop is running.
     *
     * @return boolean
     */
    public function isRunning() : bool
    {
        return $this->started;
    }
}<?php

/**
 * Signal loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use Amp\Loop;
use danog\Loop\ResumableSignalLoop;
use danog\Loop\SignalLoop;
use danog\Loop\Test\Interfaces\SignalInterface;
use danog\Loop\Test\Traits\Signal;
use function Amp\delay;
class SignalTest extends Fixtures
{
    /**
     * Test signaling loop.
     *
     * @param SignalInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideSignal
     */
    public function testSignal(SignalInterface $loop) : \Generator
    {
        $loop->setInterval(500);
        // Wait 0.5 seconds before returning null
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        $loop->signal(true);
        $this->assertTrue($loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->signal(false);
        $this->assertFalse($loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->signal(null);
        $this->assertNull($loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->signal("test");
        $this->assertEquals("test", $loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->signal($obj = new class
        {
        });
        $this->assertEquals($obj, $loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->setInterval(100);
        // Wait 0.1 seconds before returning null
        $loop->signal(true);
        // Move along loop to apply new interval
        (yield delay(110));
        $this->assertNull($loop->getPayload());
        // Result of sleep
        $loop->signal($e = new \RuntimeException('Test'));
        $this->assertEquals($e, $loop->getException());
        $this->assertFinal($loop);
        $loop = null;
    }
    /**
     * Provide resumable loop implementations.
     *
     * @return array
     */
    public function provideSignal() : array
    {
        return [[new class extends SignalLoop implements SignalInterface
        {
            use Signal;
        }], [new class extends ResumableSignalLoop implements SignalInterface
        {
            use Signal;
        }]];
    }
}<?php

/**
 * Loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use Amp\PHPUnit\AsyncTestCase;
use Amp\Promise;
use Amp\Success;
use danog\Loop\Generic\PeriodicLoop;
use danog\Loop\Loop;
use danog\Loop\Test\Interfaces\LoggingInterface;
use danog\Loop\Test\Traits\Basic;
use danog\Loop\Test\Traits\Logging;
use function Amp\delay;
class PeriodicTest extends AsyncTestCase
{
    /**
     * Test basic loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testGeneric(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $retValue = false;
        $callable = function () use(&$runCount, &$retValue, &$zis) {
            $zis = $this;
            $runCount++;
            return $retValue;
        };
        yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig, $zis, true);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run()
            {
                $this->runCount++;
                return $this->retValue;
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run()
            {
                $this->runCount++;
                return $this->retValue;
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
    }
    /**
     * Test generator loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testGenerator(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $retValue = false;
        $callable = function () use(&$runCount, &$retValue, &$zis) : \Generator {
            $zis = $this;
            (yield delay(1));
            $runCount++;
            return $retValue;
        };
        yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig, $zis, true);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run() : \Generator
            {
                (yield delay(1));
                $this->runCount++;
                return $this->retValue;
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run() : \Generator
            {
                (yield delay(1));
                $this->runCount++;
                return $this->retValue;
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
    }
    /**
     * Test promise loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testPromise(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $retValue = false;
        $callable = function () use(&$runCount, &$retValue, &$zis) : Promise {
            $zis = $this;
            $runCount++;
            return new Success($retValue);
        };
        yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig, $zis, true);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run() : Promise
            {
                $this->runCount++;
                return new Success($this->retValue);
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run() : Promise
            {
                $this->runCount++;
                return new Success($this->retValue);
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
    }
    /**
     * Fixture assertions for started loop.
     *
     * @param LoggingInterface $loop Loop
     *
     * @return void
     */
    private function fixtureStarted(LoggingInterface $loop) : void
    {
        $this->assertTrue($loop->isRunning());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
    }
    /**
     * Run fixture assertions.
     *
     * @param callable $closure Closure
     * @param integer $runCount Run count
     * @param bool $retValue Pause time
     * @param bool $stopSig Whether to stop with signal
     * @param bool $zis Reference to closure's this
     * @param bool $checkZis Whether to check zis
     *
     * @return \Generator
     */
    private function fixtureAssertions(callable $closure, int &$runCount, bool &$retValue, bool $stopSig, &$zis, bool $checkZis) : \Generator
    {
        $loop = new class($closure, Fixtures::LOOP_NAME, 100) extends PeriodicLoop implements LoggingInterface
        {
            use Logging;
        };
        $this->assertEquals(Fixtures::LOOP_NAME, "{$loop}");
        $this->assertFalse($loop->isRunning());
        $this->assertEquals(0, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
        $this->assertEquals(0, $runCount);
        $loop->start();
        (yield delay(2));
        if ($checkZis) {
            $this->assertEquals($loop, $zis);
        } else {
            $this->assertNull($zis);
        }
        $this->fixtureStarted($loop);
        $this->assertEquals(1, $runCount);
        (yield delay(48));
        $this->fixtureStarted($loop);
        $this->assertEquals(1, $runCount);
        (yield delay(60));
        $this->fixtureStarted($loop);
        $this->assertEquals(2, $runCount);
        $loop->resume();
        (yield delay(1));
        $this->assertEquals(3, $runCount);
        if ($stopSig) {
            $loop->signal(true);
        } else {
            $retValue = true;
            $loop->resume();
        }
        (yield delay(1));
        $this->assertEquals($stopSig ? 3 : 4, $runCount);
        $this->assertFalse($loop->isRunning());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(1, $loop->endCounter());
    }
    /**
     * Provide true false.
     *
     * @return array
     */
    public function provideTrueFalse() : array
    {
        return [[true], [false]];
    }
}<?php

/**
 * Resumable loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use danog\Loop\Interfaces\ResumableLoopInterface;
use danog\Loop\ResumableLoop;
use danog\Loop\ResumableSignalLoop;
use danog\Loop\Test\Interfaces\ResumableInterface;
use danog\Loop\Test\Traits\Resumable;
use function Amp\delay;
class ResumableTest extends Fixtures
{
    /**
     * Test pausing loop.
     *
     * @param ResumableInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideResumable
     */
    public function testResumable(ResumableInterface $loop) : \Generator
    {
        $paused = $loop->resume();
        // Returned promise will resolve on next pause
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        (yield delay(10));
        $this->assertTrue(self::isResolved($paused));
        (yield delay(100));
        $this->assertFinal($loop);
    }
    /**
     * Test pausing loop with negative value.
     *
     * @param ResumableInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideResumable
     */
    public function testResumableNegative(ResumableInterface $loop)
    {
        $paused = $loop->resume();
        // Will resolve on next pause
        $loop->setInterval(-1);
        // Will not pause, and finish right away!
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        (yield delay(1));
        $this->assertFalse(self::isResolved($paused));
        // Did not pause
        // Invert the order as the afterTest assertions will begin the test anew
        $this->assertFinal($loop);
        $this->assertAfterStart($loop, false);
    }
    /**
     * Test pausing loop forever, or for 10 seconds, prematurely resuming it.
     *
     * @param ResumableInterface $loop Loop
     * @param ?int $interval Interval
     * @param bool $deferred Deferred
     *
     * @return \Generator
     *
     * @dataProvider provideResumableInterval
     */
    public function testResumableForeverPremature(ResumableInterface $loop, ?int $interval, bool $deferred) : \Generator
    {
        $paused = $deferred ? $loop->resumeDefer() : $loop->resume();
        // Will resolve on next pause
        if ($deferred) {
            (yield delay(1));
            // Avoid resuming after starting
        }
        $loop->setInterval($interval);
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        (yield delay(1));
        $this->assertTrue(self::isResolved($paused));
        // Did pause
        $paused = $deferred ? $loop->resumeDefer() : $loop->resume();
        if ($deferred) {
            $this->assertAfterStart($loop);
            (yield delay(1));
        }
        $this->assertFinal($loop);
        (yield delay(1));
        $this->assertFalse(self::isResolved($paused));
        // Did not pause again
    }
    /**
     * Test pausing loop and then resuming it with deferOnce.
     *
     * @param ResumableInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideResumable
     */
    public function testResumableDeferOnce(ResumableInterface $loop) : \Generator
    {
        $paused1 = $loop->resumeDeferOnce();
        // Will resolve on next pause
        $paused2 = $loop->resumeDeferOnce();
        // Will resolve on next pause
        (yield delay(1));
        // Avoid resuming after starting
        $loop->setInterval(10000);
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        (yield delay(1));
        $this->assertTrue(self::isResolved($paused1));
        // Did pause
        $this->assertTrue(self::isResolved($paused2));
        // Did pause
        $paused1 = $loop->resumeDeferOnce();
        $paused2 = $loop->resumeDeferOnce();
        $this->assertAfterStart($loop);
        (yield delay(1));
        $this->assertFinal($loop);
        (yield delay(1));
        $this->assertFalse(self::isResolved($paused1));
        // Did not pause again
        $this->assertFalse(self::isResolved($paused2));
        // Did not pause again
    }
    /**
     * Provide resumable loop implementations.
     *
     * @return array
     *
     * @psalm-return array<int, array<int, ResumableInterface>>
     */
    public function provideResumable() : array
    {
        return [[new class extends ResumableLoop implements ResumableInterface, ResumableLoopInterface
        {
            use Resumable;
        }], [new class extends ResumableSignalLoop implements ResumableInterface, ResumableLoopInterface
        {
            use Resumable;
        }]];
    }
    /**
     * Provide resumable loop implementations and interval.
     *
     * @return \Generator
     */
    public function provideResumableInterval() : \Generator
    {
        foreach ([true, false] as $deferred) {
            foreach ([10000, null] as $interval) {
                foreach ($this->provideResumable() as $params) {
                    $params[] = $interval;
                    $params[] = $deferred;
                    (yield $params);
                }
            }
        }
    }
}<?php

/**
 * Loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use Amp\PHPUnit\AsyncTestCase;
use Amp\Promise;
use danog\Loop\Test\Interfaces\BasicInterface;
/**
 * Fixtures.
 */
abstract class Fixtures extends AsyncTestCase
{
    const LOOP_NAME = 'PONY';
    /**
     * Check if promise has been resolved afterwards.
     *
     * @param Promise $promise Promise
     *
     * @return boolean
     */
    protected static function isResolved(Promise $promise) : bool
    {
        $resolved = false;
        $promise->onResolve(static function ($e, $res) use(&$resolved) {
            if ($e) {
                throw $e;
            }
            $resolved = true;
        });
        return $resolved;
    }
    /**
     * Execute pre-start assertions.
     *
     * @param BasicInterface $loop Loop
     *
     * @return void
     */
    protected function assertPreStart(BasicInterface $loop)
    {
        $this->assertEquals(self::LOOP_NAME, "{$loop}");
        $this->assertFalse($loop->isRunning());
        $this->assertFalse($loop->ran());
        $this->assertFalse($loop->inited());
        $this->assertEquals(0, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
    }
    /**
     * Execute after-start assertions.
     *
     * @param BasicInterface $loop Loop
     * @param bool $running Whether we should expect the loop to be running
     *
     * @return void
     */
    protected function assertAfterStart(BasicInterface $loop, bool $running = true)
    {
        $this->assertTrue($loop->inited());
        if ($running) {
            $this->assertFalse($loop->ran());
        }
        $this->assertEquals($running, $loop->isRunning(), $running);
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals($running ? 0 : 1, $loop->endCounter());
        $this->assertEquals($running, !$loop->start());
    }
    /**
     * Execute final assertions.
     *
     * @param BasicInterface $loop Loop
     *
     * @return void
     */
    protected function assertFinal(BasicInterface $loop)
    {
        $this->assertTrue($loop->ran());
        $this->assertFalse($loop->isRunning());
        $this->assertTrue($loop->inited());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(1, $loop->endCounter());
    }
}<?php

/**
 * Basic loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\LoopInterface;
/**
 * Basic loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface LoggingInterface extends LoopInterface
{
    /**
     * Get start counter.
     *
     * @return integer
     */
    public function startCounter() : int;
    /**
     * Get end counter.
     *
     * @return integer
     */
    public function endCounter() : int;
}<?php

/**
 * Resumable loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

/**
 * Resumable loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface IntervalInterface
{
    /**
     * Set sleep interval.
     *
     * @param ?int $interval Interval
     *
     * @return void
     */
    public function setInterval(?int $interval) : void;
}<?php

/**
 * Basic loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\LoopInterface;
/**
 * Basic loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface BasicInterface extends LoopInterface, LoggingInterface
{
    /**
     * Check whether the loop inited.
     *
     * @return boolean
     */
    public function inited() : bool;
    /**
     * Check whether the loop ran.
     *
     * @return boolean
     */
    public function ran() : bool;
}<?php

/**
 * Basic loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\LoopInterface;
/**
 * Basic loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface LoggingPauseInterface extends LoopInterface, LoggingInterface
{
    /**
     * Get number of times loop was paused.
     *
     * @return integer
     */
    public function getPauseCount() : int;
    /**
     * Get last pause.
     *
     * @return integer
     */
    public function getLastPause() : int;
}<?php

/**
 * Signal loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\SignalLoopInterface;
/**
 * Signal loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface SignalInterface extends BasicInterface, IntervalInterface, SignalLoopInterface
{
    /**
     * Get signaled payload.
     *
     * @return mixed
     */
    public function getPayload();
    /**
     * Get signaled exception.
     *
     * @return ?\Throwable
     */
    public function getException() : ?\Throwable;
}<?php

/**
 * Resumable loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\ResumableLoopInterface;
/**
 * Resumable loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface ResumableInterface extends BasicInterface, IntervalInterface, ResumableLoopInterface
{
}<?php

/**
 * Loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use Amp\PHPUnit\AsyncTestCase;
use Amp\Promise;
use Amp\Success;
use danog\Loop\Generic\GenericLoop;
use danog\Loop\Loop;
use danog\Loop\Test\Interfaces\LoggingPauseInterface;
use danog\Loop\Test\Traits\Basic;
use danog\Loop\Test\Traits\LoggingPause;
use function Amp\delay;
class GenericTest extends AsyncTestCase
{
    /**
     * Test basic loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testGeneric(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $pauseTime = GenericLoop::PAUSE;
        $callable = function () use(&$runCount, &$pauseTime, &$zis) {
            $zis = $this;
            $runCount++;
            return $pauseTime;
        };
        yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig, $zis, true);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run()
            {
                $this->runCount++;
                return $this->pauseTime;
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run()
            {
                $this->runCount++;
                return $this->pauseTime;
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
    }
    /**
     * Test generator loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testGenerator(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $pauseTime = GenericLoop::PAUSE;
        $callable = function () use(&$runCount, &$pauseTime, &$zis) : \Generator {
            $zis = $this;
            (yield delay(1));
            $runCount++;
            return $pauseTime;
        };
        yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig, $zis, true);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run() : \Generator
            {
                (yield delay(1));
                $this->runCount++;
                return $this->pauseTime;
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run() : \Generator
            {
                (yield delay(1));
                $this->runCount++;
                return $this->pauseTime;
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
    }
    /**
     * Test promise loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testPromise(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $pauseTime = GenericLoop::PAUSE;
        $callable = function () use(&$runCount, &$pauseTime, &$zis) : Promise {
            $zis = $this;
            $runCount++;
            return new Success($pauseTime);
        };
        yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig, $zis, true);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run() : Promise
            {
                $this->runCount++;
                return new Success($this->pauseTime);
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run() : Promise
            {
                $this->runCount++;
                return new Success($this->pauseTime);
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
    }
    /**
     * Fixture assertions for started loop.
     *
     * @param LoggingPauseInterface $loop Loop
     *
     * @return void
     */
    private function fixtureStarted(LoggingPauseInterface $loop) : void
    {
        $this->assertTrue($loop->isRunning());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
    }
    /**
     * Run fixture assertions.
     *
     * @param callable $closure Closure
     * @param integer $runCount Run count
     * @param ?integer $pauseTime Pause time
     * @param bool $stopSig Whether to stop with signal
     * @param bool $zis Reference to closure's this
     * @param bool $checkZis Whether to check zis
     *
     * @return \Generator
     */
    private function fixtureAssertions(callable $closure, int &$runCount, ?int &$pauseTime, bool $stopSig, &$zis, bool $checkZis) : \Generator
    {
        $loop = new class($closure, Fixtures::LOOP_NAME) extends GenericLoop implements LoggingPauseInterface
        {
            use LoggingPause;
        };
        $this->assertEquals(Fixtures::LOOP_NAME, "{$loop}");
        $this->assertFalse($loop->isRunning());
        $this->assertEquals(0, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
        $this->assertEquals(0, $runCount);
        $this->assertEquals(0, $loop->getPauseCount());
        $loop->start();
        (yield delay(2));
        if ($checkZis) {
            $this->assertEquals($loop, $zis);
        } else {
            $this->assertNull($zis);
        }
        $this->fixtureStarted($loop);
        $this->assertEquals(1, $runCount);
        $this->assertEquals(1, $loop->getPauseCount());
        $this->assertEquals(0, $loop->getLastPause());
        $pauseTime = 100;
        $loop->resume();
        (yield delay(2));
        $this->fixtureStarted($loop);
        $this->assertEquals(2, $runCount);
        $this->assertEquals(2, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        (yield delay(48));
        $this->fixtureStarted($loop);
        $this->assertEquals(2, $runCount);
        $this->assertEquals(2, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        (yield delay(60));
        $this->fixtureStarted($loop);
        $this->assertEquals(3, $runCount);
        $this->assertEquals(3, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        $loop->resume();
        (yield delay(1));
        $this->assertEquals(4, $runCount);
        $this->assertEquals(4, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        if ($stopSig) {
            $loop->signal(true);
        } else {
            $pauseTime = GenericLoop::STOP;
            $loop->resume();
        }
        (yield delay(1));
        $this->assertEquals($stopSig ? 4 : 5, $runCount);
        $this->assertEquals(4, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        $this->assertFalse($loop->isRunning());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(1, $loop->endCounter());
    }
    /**
     * Provide true false.
     *
     * @return array
     */
    public function provideTrueFalse() : array
    {
        return [[true], [false]];
    }
}<?php

/**
 * Exception test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use Generator;
trait BasicException
{
    use Basic;
    /**
     * Loop implementation.
     *
     * @return Generator
     */
    public function loop() : Generator
    {
        $this->inited = true;
        throw new \RuntimeException('Threw exception!');
        $this->ran = true;
    }
}<?php

/**
 * Loop test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use danog\Loop\Test\LoopTest;
use Generator;
use function Amp\delay;
trait Basic
{
    use Logging;
    /**
     * Check whether the loop inited.
     *
     * @var bool
     */
    private $inited = false;
    /**
     * Check whether the loop ran.
     *
     * @var bool
     */
    private $ran = false;
    /**
     * Check whether the loop inited.
     *
     * @return boolean
     */
    public function inited() : bool
    {
        return $this->inited;
    }
    /**
     * Check whether the loop ran.
     *
     * @return boolean
     */
    public function ran() : bool
    {
        return $this->ran;
    }
    /**
     * Loop implementation.
     *
     * @return Generator
     */
    public function loop() : Generator
    {
        $this->inited = true;
        (yield delay(100));
        $this->ran = true;
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return LoopTest::LOOP_NAME;
    }
}<?php

/**
 * Resumable test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use danog\Loop\Interfaces\ResumableLoopInterface;
use Generator;
use function Amp\delay;
trait Signal
{
    use Resumable;
    /**
     * Signaled payload.
     *
     * @var mixed
     */
    private $payload;
    /**
     * Signaled exception.
     *
     * @var ?\Throwable
     */
    private $exception;
    /**
     * Get signaled payload.
     *
     * @return mixed
     */
    public function getPayload()
    {
        return $this->payload;
    }
    /**
     * Get signaled exception.
     *
     * @return \Throwable
     */
    public function getException() : ?\Throwable
    {
        return $this->exception;
    }
    /**
     * Test waiting signal on interval.
     *
     * @param integer $interval Interval
     *
     * @return \Generator
     */
    private function testGenerator(int $interval) : \Generator
    {
        (yield delay($interval));
    }
    /**
     * Loop implementation.
     *
     * @return Generator
     */
    public function loop() : Generator
    {
        $this->inited = true;
        try {
            while (true) {
                $this->payload = (yield $this->waitSignal($this instanceof ResumableLoopInterface ? $this->pause($this->interval) : $this->testGenerator($this->interval)));
            }
        } catch (\Throwable $e) {
            $this->exception = $e;
        }
        $this->ran = true;
    }
}<?php

/**
 * Loop test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

trait Logging
{
    /**
     * Check whether the loop started.
     *
     * @var int
     */
    private $startCounter = 0;
    /**
     * Check whether the loop ended.
     *
     * @var int
     */
    private $endCounter = 0;
    /**
     * Signal that loop started.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        $this->startCounter++;
        parent::startedLoop();
    }
    /**
     * Signal that loop ended.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        $this->endCounter++;
        parent::exitedLoop();
    }
    /**
     * Get start counter.
     *
     * @return integer
     */
    public function startCounter() : int
    {
        return $this->startCounter;
    }
    /**
     * Get end counter.
     *
     * @return integer
     */
    public function endCounter() : int
    {
        return $this->endCounter;
    }
}<?php

/**
 * Loop test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use function Amp\delay;
trait LoggingPause
{
    use Logging;
    /**
     * Number of times loop was paused.
     *
     * @var integer
     */
    private $pauseCount = 0;
    /**
     * Last pause delay.
     *
     * @var int
     */
    private $lastPause = 0;
    /**
     * Get number of times loop was paused.
     *
     * @return integer
     */
    public function getPauseCount() : int
    {
        return $this->pauseCount;
    }
    /**
     * Get last pause.
     *
     * @return integer
     */
    public function getLastPause() : int
    {
        return $this->lastPause;
    }
    /**
     * Report pause, can be overriden for logging.
     *
     * @param integer $timeout Pause duration, 0 = forever
     *
     * @return void
     */
    protected function reportPause(int $timeout) : void
    {
        parent::reportPause($timeout);
        $this->pauseCount++;
        $this->lastPause = $timeout;
    }
}<?php

/**
 * Resumable test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use Generator;
trait Resumable
{
    use Basic;
    /**
     * Set interval.
     *
     * @var ?int
     */
    protected $interval = 100;
    /**
     * Set sleep interval.
     *
     * @param ?int $interval Interval
     *
     * @return void
     */
    public function setInterval(?int $interval) : void
    {
        $this->interval = $interval;
    }
    /**
     * Loop implementation.
     *
     * @return Generator
     */
    public function loop() : Generator
    {
        $this->inited = true;
        (yield $this->pause($this->interval));
        $this->ran = true;
    }
}<?php

/**
 * Loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use danog\Loop\Loop;
use danog\Loop\ResumableLoop;
use danog\Loop\ResumableSignalLoop;
use danog\Loop\SignalLoop;
use danog\Loop\Test\Interfaces\BasicInterface;
use danog\Loop\Test\Traits\Basic;
use danog\Loop\Test\Traits\BasicException;
use function Amp\delay;
class LoopTest extends Fixtures
{
    /**
     * Test basic loop.
     *
     * @param BasicInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideBasic
     */
    public function testLoop(BasicInterface $loop) : \Generator
    {
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        (yield delay(110));
        $this->assertFinal($loop);
    }
    /**
     * Test basic exception in loop.
     *
     * @param BasicInterface $loop Loop
     *
     * @return void
     *
     * @dataProvider provideBasicExceptions
     */
    public function testException(BasicInterface $loop) : void
    {
        $this->expectException(\RuntimeException::class);
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertFalse($loop->isRunning());
        $this->assertTrue($loop->inited());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(1, $loop->endCounter());
    }
    /**
     * Provide loop implementations.
     *
     * @return array
     */
    public function provideBasic() : array
    {
        return [[new class extends Loop implements BasicInterface
        {
            use Basic;
        }], [new class extends SignalLoop implements BasicInterface
        {
            use Basic;
        }], [new class extends ResumableLoop implements BasicInterface
        {
            use Basic;
        }], [new class extends ResumableSignalLoop implements BasicInterface
        {
            use Basic;
        }]];
    }
    /**
     * Provide loop implementations.
     *
     * @return array
     */
    public function provideBasicExceptions() : array
    {
        return [[new class extends Loop implements BasicInterface
        {
            use BasicException;
        }], [new class extends SignalLoop implements BasicInterface
        {
            use BasicException;
        }], [new class extends ResumableLoop implements BasicInterface
        {
            use BasicException;
        }], [new class extends ResumableSignalLoop implements BasicInterface
        {
            use BasicException;
        }]];
    }
}{
    "name": "danog/dns-over-https",
    "homepage": "https://github.com/danog/dns-over-https",
    "description": "Async DNS-over-HTTPS resolution for Amp.",
    "keywords": [
        "dns",
        "doh",
        "dns-over-https",
        "https",
        "resolve",
        "client",
        "async",
        "amp",
        "amphp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        },
        {
            "name": "Chris Wright",
            "email": "addr@daverandom.com"
        },
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.0",
        "amphp/cache": "^1",
        "amphp/parser": "^1",
        "danog/libdns-json": "^0.1",
        "daverandom/libdns": "^2.0.1",
        "amphp/amp": "^2",
        "amphp/http-client": "^4",
        "amphp/dns": "^1",
        "ext-filter": "*",
        "ext-json": "*"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1",
        "phpunit/phpunit": "^6",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\DoH\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\DoH\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\DoH;

use Amp\Cache\ArrayCache;
use Amp\Cache\Cache;
use Amp\Dns\ConfigException;
use Amp\Dns\ConfigLoader;
use Amp\Dns\Resolver;
use Amp\Dns\Rfc1035StubResolver;
use Amp\Dns\UnixConfigLoader;
use Amp\Dns\WindowsConfigLoader;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\HttpClientBuilder;
final class DoHConfig
{
    private $nameservers;
    private $httpClient;
    private $subResolver;
    private $configLoader;
    private $cache;
    /**
     *
     */
    public function __construct(array $nameservers, DelegateHttpClient $httpClient = null, Resolver $resolver = null, ConfigLoader $configLoader = null, Cache $cache = null)
    {
        if (\count($nameservers) < 1) {
            throw new ConfigException("At least one nameserver is required for a valid config");
        }
        foreach ($nameservers as $nameserver) {
            $this->validateNameserver($nameserver);
        }
        $this->nameservers = $nameservers;
        $this->httpClient = $httpClient ?? HttpClientBuilder::buildDefault();
        $this->cache = $cache ?? new ArrayCache(5000, 256);
        $this->configLoader = $configLoader ?? (\stripos(PHP_OS, "win") === 0 ? new WindowsConfigLoader() : new UnixConfigLoader());
        $this->subResolver = $resolver ?? new Rfc1035StubResolver(null, $this->configLoader);
    }
    /**
     *
     */
    private function validateNameserver($nameserver)
    {
        if (!$nameserver instanceof Nameserver) {
            throw new ConfigException("Invalid nameserver: {$nameserver}");
        }
    }
    /**
     *
     */
    public function getNameservers() : array
    {
        return $this->nameservers;
    }
    /**
     *
     */
    public function isNameserver($string) : bool
    {
        foreach ($this->nameservers as $nameserver) {
            if ($nameserver->getHost() === $string) {
                return true;
            }
        }
        return false;
    }
    /**
     *
     */
    public function getHttpClient() : DelegateHttpClient
    {
        return $this->httpClient;
    }
    /**
     *
     */
    public function getCache() : Cache
    {
        return $this->cache;
    }
    /**
     *
     */
    public function getConfigLoader() : ConfigLoader
    {
        return $this->configLoader;
    }
    /**
     *
     */
    public function getSubResolver() : Resolver
    {
        return $this->subResolver;
    }
}<?php

namespace Amp\DoH;

/**
 * Throw when DoH resolution fails.
 */
class DoHException extends \Exception
{
}<?php

namespace Amp\DoH\Internal;

use Amp\DoH\DoHException;
use Amp\DoH\Nameserver;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Request;
use Amp\Promise;
use danog\LibDNSJson\JsonDecoderFactory;
use danog\LibDNSJson\QueryEncoderFactory;
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Messages\Message;
use function Amp\call;
/** @internal */
final class HttpsSocket extends Socket
{
    /** @var \Amp\Http\HttpClient */
    private $httpClient;
    /** @var \Amp\DoH\Nameserver */
    private $nameserver;
    /** @var \LibDNS\Encoder\Encoder */
    private $encoder;
    /** @var \LibDNS\Decoder\Decoder */
    private $decoder;
    /** @var \Amp\Deferred */
    private $responseDeferred;
    /**
     *
     */
    public static function connect(DelegateHttpClient $httpClient, Nameserver $nameserver) : Socket
    {
        return new self($httpClient, $nameserver);
    }
    /**
     *
     */
    protected function __construct(DelegateHttpClient $httpClient, Nameserver $nameserver)
    {
        $this->httpClient = $httpClient;
        $this->nameserver = $nameserver;
        if ($nameserver->getType() !== Nameserver::GOOGLE_JSON) {
            $this->encoder = (new EncoderFactory())->create();
            $this->decoder = (new DecoderFactory())->create();
        } else {
            $this->encoder = (new QueryEncoderFactory())->create();
            $this->decoder = (new JsonDecoderFactory())->create();
        }
        parent::__construct();
    }
    /**
     *
     */
    protected function resolve(Message $message) : Promise
    {
        $id = $message->getID();
        switch ($this->nameserver->getType()) {
            case Nameserver::RFC8484_GET:
                $data = $this->encoder->encode($message);
                $request = new Request($this->nameserver->getUri() . '?' . \http_build_query(['dns' => \base64_encode($data), 'ct' => 'application/dns-message']), "GET");
                $request->setHeader('accept', 'application/dns-message');
                $request->setHeaders($this->nameserver->getHeaders());
                break;
            case Nameserver::RFC8484_POST:
                $data = $this->encoder->encode($message);
                $request = new Request($this->nameserver->getUri(), "POST");
                $request->setBody($data);
                $request->setHeader('content-type', 'application/dns-message');
                $request->setHeader('accept', 'application/dns-message');
                $request->setHeader('content-length', \strlen($data));
                $request->setHeaders($this->nameserver->getHeaders());
                break;
            case Nameserver::GOOGLE_JSON:
                $data = $this->encoder->encode($message);
                $request = new Request($this->nameserver->getUri() . '?' . $data, "GET");
                $request->setHeader('accept', 'application/dns-json');
                $request->setHeaders($this->nameserver->getHeaders());
                break;
        }
        $response = $this->httpClient->request($request);
        return call(function () use($response, $id) {
            $response = (yield $response);
            if ($response->getStatus() !== 200) {
                throw new DoHException("HTTP result !== 200: " . $response->getStatus() . " " . $response->getReason(), $response->getStatus());
            }
            $response = (yield $response->getBody()->buffer());
            switch ($this->nameserver->getType()) {
                case Nameserver::RFC8484_GET:
                case Nameserver::RFC8484_POST:
                    return $this->decoder->decode($response);
                case Nameserver::GOOGLE_JSON:
                    return $this->decoder->decode($response, $id);
            }
        });
    }
}<?php

namespace Amp\DoH\Internal;

use Amp;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Dns\DnsException;
use Amp\Dns\TimeoutException;
use Amp\DoH\DoHException;
use Amp\DoH\Nameserver;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Promise;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Records\Question;
use function Amp\call;
/** @internal */
abstract class Socket
{
    const MAX_CONCURRENT_REQUESTS = 500;
    /** @var array Contains already sent queries with no response yet. For UDP this is exactly zero or one item. */
    private $pending = [];
    /** @var MessageFactory */
    private $messageFactory;
    /** @var callable */
    private $onResolve;
    /** @var array Queued requests if the number of concurrent requests is too large. */
    private $queue = [];
    /**
     * @param string $uri
     *
     * @return Promise<self>
     */
    public static abstract function connect(DelegateHttpClient $httpClient, Nameserver $nameserver) : self;
    /**
     * @param Message $message
     *
     * @return Promise<int>
     */
    protected abstract function resolve(Message $message) : Promise;
    /**
     *
     */
    protected function __construct()
    {
        $this->messageFactory = new MessageFactory();
        $this->onResolve = function (\Throwable $exception = null, Message $message = null) {
            if ($exception) {
                $this->error($exception);
                return;
            }
            \assert($message instanceof Message);
            $id = $message->getId();
            // Ignore duplicate and invalid responses.
            if (isset($this->pending[$id]) && $this->matchesQuestion($message, $this->pending[$id]->question)) {
                /** @var Deferred $deferred */
                $deferred = $this->pending[$id]->deferred;
                unset($this->pending[$id]);
                $deferred->resolve($message);
            }
        };
    }
    /**
     * @param \LibDNS\Records\Question $question
     * @param int $timeout
     *
     * @return \Amp\Promise<\LibDNS\Messages\Message>
     */
    public final function ask(Question $question, int $timeout) : Promise
    {
        return call(function () use($question, $timeout) {
            if (\count($this->pending) > self::MAX_CONCURRENT_REQUESTS) {
                $deferred = new Deferred();
                $this->queue[] = $deferred;
                (yield $deferred->promise());
            }
            do {
                $id = \random_int(0, 0xffff);
            } while (isset($this->pending[$id]));
            $deferred = new Deferred();
            $pending = new class
            {
                use Amp\Struct;
                public $deferred;
                public $question;
            };
            $pending->deferred = $deferred;
            $pending->question = $question;
            $this->pending[$id] = $pending;
            $message = $this->createMessage($question, $id);
            try {
                $response = $this->resolve($message);
            } catch (StreamException $exception) {
                $exception = new DnsException("Sending the request failed", 0, $exception);
                $this->error($exception);
                throw $exception;
            }
            $response->onResolve($this->onResolve);
            try {
                // Work around an OPCache issue that returns an empty array with "return yield ...",
                // so assign to a variable first and return after the try block.
                //
                // See https://github.com/amphp/dns/issues/58.
                // See https://bugs.php.net/bug.php?id=74840.
                $result = (yield Promise\timeout($deferred->promise(), $timeout));
            } catch (Amp\TimeoutException $exception) {
                unset($this->pending[$id]);
                throw new TimeoutException("Didn't receive a response within {$timeout} milliseconds.");
            } finally {
                if ($this->queue) {
                    $deferred = \array_shift($this->queue);
                    $deferred->resolve();
                }
            }
            return $result;
        });
    }
    /**
     *
     */
    private function error(\Throwable $exception)
    {
        if (empty($this->pending)) {
            return;
        }
        if (!$exception instanceof DnsException && !$exception instanceof DoHException) {
            $message = "Unexpected error during resolution: " . $exception->getMessage();
            $exception = new DnsException($message, 0, $exception);
        }
        $pending = $this->pending;
        $this->pending = [];
        foreach ($pending as $pendingQuestion) {
            /** @var Deferred $deferred */
            $deferred = $pendingQuestion->deferred;
            $deferred->fail($exception);
        }
    }
    /**
     *
     */
    protected final function createMessage(Question $question, int $id) : Message
    {
        $request = $this->messageFactory->create(MessageTypes::QUERY);
        $request->getQuestionRecords()->add($question);
        $request->isRecursionDesired(true);
        $request->setID($id);
        return $request;
    }
    /**
     *
     */
    private function matchesQuestion(Message $message, Question $question) : bool
    {
        if ($message->getType() !== MessageTypes::RESPONSE) {
            return false;
        }
        $questionRecords = $message->getQuestionRecords();
        // We only ever ask one question at a time
        if (\count($questionRecords) !== 1) {
            return false;
        }
        $questionRecord = $questionRecords->getIterator()->current();
        if ($questionRecord->getClass() !== $question->getClass()) {
            return false;
        }
        if ($questionRecord->getType() !== $question->getType()) {
            return false;
        }
        if ($questionRecord->getName()->getValue() !== $question->getName()->getValue()) {
            return false;
        }
        return true;
    }
}<?php

namespace Amp\DoH;

use Amp\Cache\Cache;
use Amp\Dns\Config;
use Amp\Dns\ConfigException;
use Amp\Dns\DnsException;
use Amp\Dns\NoRecordException;
use Amp\Dns\Record;
use Amp\Dns\Resolver;
use Amp\Dns\TimeoutException;
use Amp\DoH\Internal\HttpsSocket;
use Amp\DoH\Internal\Socket;
use Amp\MultiReasonException;
use Amp\Promise;
use LibDNS\Messages\Message;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use function Amp\call;
use function Amp\Dns\normalizeName;
final class Rfc8484StubResolver implements Resolver
{
    const CACHE_PREFIX = "amphp.doh.";
    /** @var \Amp\Dns\ConfigLoader */
    private $configLoader;
    /** @var \LibDNS\Records\QuestionFactory */
    private $questionFactory;
    /** @var \Amp\Dns\Config|null */
    private $config;
    /** @var Promise|null */
    private $pendingConfig;
    /** @var \Amp\DoH\DoHConfig */
    private $dohConfig;
    /** @var Cache */
    private $cache;
    /** @var Promise[] */
    private $pendingQueries = [];
    /** @var \Amp\Dns\Rfc1035StubResolver */
    private $subResolver;
    /**
     *
     */
    public function __construct(DoHConfig $config)
    {
        $resolver = $config->getSubResolver();
        if ($resolver instanceof Rfc8484StubResolver) {
            throw new ConfigException("Can't use Rfc8484StubResolver as subresolver for Rfc8484StubResolver");
        }
        $this->cache = $config->getCache();
        $this->configLoader = $config->getConfigLoader();
        $this->subResolver = $resolver;
        $this->dohConfig = $config;
        $this->questionFactory = new QuestionFactory();
    }
    /**
     * @inheritdoc
     */
    public function resolve(string $name, int $typeRestriction = null) : Promise
    {
        if ($typeRestriction !== null && $typeRestriction !== Record::A && $typeRestriction !== Record::AAAA) {
            throw new \Error("Invalid value for parameter 2: null|Record::A|Record::AAAA expected");
        }
        return call(function () use($name, $typeRestriction) {
            if (!$this->config) {
                try {
                    (yield $this->reloadConfig());
                } catch (ConfigException $e) {
                    $this->config = new Config(['0.0.0.0'], []);
                }
            }
            switch ($typeRestriction) {
                case Record::A:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        return [new Record($name, Record::A, null)];
                    } elseif (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        throw new DnsException("Got an IPv6 address, but type is restricted to IPv4");
                    }
                    break;
                case Record::AAAA:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        return [new Record($name, Record::AAAA, null)];
                    } elseif (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        throw new DnsException("Got an IPv4 address, but type is restricted to IPv6");
                    }
                    break;
                default:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        return [new Record($name, Record::A, null)];
                    } elseif (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        return [new Record($name, Record::AAAA, null)];
                    }
                    break;
            }
            $name = normalizeName($name);
            if ($records = $this->queryHosts($name, $typeRestriction)) {
                return $records;
            }
            // Follow RFC 6761 and never send queries for localhost to the caching DNS server
            // Usually, these queries are already resolved via queryHosts()
            if ($name === 'localhost') {
                return $typeRestriction === Record::AAAA ? [new Record('::1', Record::AAAA, null)] : [new Record('127.0.0.1', Record::A, null)];
            }
            if ($this->dohConfig->isNameserver($name)) {
                // Work around an OPCache issue that returns an empty array with "return yield ...",
                // so assign to a variable first and return after the try block.
                //
                // See https://github.com/amphp/dns/issues/58.
                // See https://bugs.php.net/bug.php?id=74840.
                $records = (yield $this->subResolver->resolve($name, $typeRestriction));
                return $records;
            }
            for ($redirects = 0; $redirects < 5; $redirects++) {
                try {
                    if ($typeRestriction) {
                        $records = (yield $this->query($name, $typeRestriction));
                    } else {
                        try {
                            list(, $records) = (yield Promise\some([$this->query($name, Record::A), $this->query($name, Record::AAAA)]));
                            $records = \array_merge(...$records);
                            break;
                            // Break redirect loop, otherwise we query the same records 5 times
                        } catch (MultiReasonException $e) {
                            $errors = [];
                            foreach ($e->getReasons() as $reason) {
                                if ($reason instanceof NoRecordException) {
                                    throw $reason;
                                }
                                $error = (string) $reason;
                                //->getMessage();
                                if ($reason instanceof MultiReasonException) {
                                    $reasons = [];
                                    foreach ($reason->getReasons() as $reason) {
                                        $reasons[] = (string) $reason;
                                        //->getMessage();
                                    }
                                    $error .= " (" . \implode(", ", $reasons) . ")";
                                }
                                $errors[] = $error;
                            }
                            throw new DnsException("All query attempts failed for {$name}: " . \implode(", ", $errors), 0, $e);
                        }
                    }
                } catch (NoRecordException $e) {
                    try {
                        /** @var Record[] $cnameRecords */
                        $cnameRecords = (yield $this->query($name, Record::CNAME));
                        $name = $cnameRecords[0]->getValue();
                        continue;
                    } catch (NoRecordException $e) {
                        /** @var Record[] $dnameRecords */
                        $dnameRecords = (yield $this->query($name, Record::DNAME));
                        $name = $dnameRecords[0]->getValue();
                        continue;
                    }
                }
            }
            return $records;
        });
    }
    /**
     * Reloads the configuration in the background.
     *
     * Once it's finished, the configuration will be used for new requests.
     *
     * @return Promise
     */
    public function reloadConfig() : Promise
    {
        if ($this->pendingConfig) {
            return $this->pendingConfig;
        }
        $promise = call(function () {
            (yield $this->subResolver->reloadConfig());
            $this->config = (yield $this->configLoader->loadConfig());
        });
        $this->pendingConfig = $promise;
        $promise->onResolve(function () {
            $this->pendingConfig = null;
        });
        return $promise;
    }
    /**
     *
     */
    private function queryHosts(string $name, int $typeRestriction = null) : array
    {
        $hosts = $this->config->getKnownHosts();
        $records = [];
        $returnIPv4 = $typeRestriction === null || $typeRestriction === Record::A;
        $returnIPv6 = $typeRestriction === null || $typeRestriction === Record::AAAA;
        if ($returnIPv4 && isset($hosts[Record::A][$name])) {
            $records[] = new Record($hosts[Record::A][$name], Record::A, null);
        }
        if ($returnIPv6 && isset($hosts[Record::AAAA][$name])) {
            $records[] = new Record($hosts[Record::AAAA][$name], Record::AAAA, null);
        }
        return $records;
    }
    /**
     * @inheritdoc
     */
    public function query(string $name, int $type) : Promise
    {
        $pendingQueryKey = $type . " " . $name;
        if (isset($this->pendingQueries[$pendingQueryKey])) {
            return $this->pendingQueries[$pendingQueryKey];
        }
        $promise = call(function () use($name, $type) {
            if (!$this->config) {
                try {
                    (yield $this->reloadConfig());
                } catch (ConfigException $e) {
                    $this->config = new Config(['0.0.0.0'], []);
                }
            }
            $name = $this->normalizeName($name, $type);
            $question = $this->createQuestion($name, $type);
            if (null !== ($cachedValue = (yield $this->cache->get($this->getCacheKey($name, $type))))) {
                return $this->decodeCachedResult($name, $type, $cachedValue);
            }
            /** @var Nameserver[] $nameservers */
            $nameservers = $this->dohConfig->getNameservers();
            $attempts = $this->config->getAttempts() * \count($nameservers);
            $attempt = 0;
            /** @var Socket $socket */
            $nameserver = $nameservers[0];
            $socket = $this->getSocket($nameserver);
            $attemptDescription = [];
            $exceptions = [];
            while ($attempt < $attempts) {
                try {
                    $attemptDescription[] = $nameserver;
                    /** @var Message $response */
                    try {
                        $response = (yield $socket->ask($question, $this->config->getTimeout()));
                    } catch (DoHException $e) {
                        // Defer call, because it might interfere with the unreference() call in Internal\Socket otherwise
                        $exceptions[] = $e;
                        $i = ++$attempt % \count($nameservers);
                        $nameserver = $nameservers[$i];
                        $socket = $this->getSocket($nameserver);
                        continue;
                    } catch (NoRecordException $e) {
                        // Defer call, because it might interfere with the unreference() call in Internal\Socket otherwise
                        $i = ++$attempt % \count($nameservers);
                        $nameserver = $nameservers[$i];
                        $socket = $this->getSocket($nameserver);
                        continue;
                    }
                    $this->assertAcceptableResponse($response);
                    if ($response->isTruncated()) {
                        throw new DnsException("Server returned a truncated response for '{$name}' (" . Record::getName($type) . ")");
                    }
                    $answers = $response->getAnswerRecords();
                    $result = [];
                    $ttls = [];
                    /** @var \LibDNS\Records\Resource $record */
                    foreach ($answers as $record) {
                        $recordType = $record->getType();
                        $result[$recordType][] = (string) $record->getData();
                        // Cache for max one day
                        $ttls[$recordType] = \min($ttls[$recordType] ?? 86400, $record->getTTL());
                    }
                    foreach ($result as $recordType => $records) {
                        // We don't care here whether storing in the cache fails
                        $this->cache->set($this->getCacheKey($name, $recordType), \json_encode($records), $ttls[$recordType]);
                    }
                    if (!isset($result[$type])) {
                        // "it MUST NOT cache it for longer than five (5) minutes" per RFC 2308 section 7.1
                        $this->cache->set($this->getCacheKey($name, $type), \json_encode([]), 300);
                        throw new NoRecordException("No records returned for '{$name}' (" . Record::getName($type) . ")");
                    }
                    return \array_map(function ($data) use($type, $ttls) {
                        return new Record($data, $type, $ttls[$type]);
                    }, $result[$type]);
                } catch (TimeoutException $e) {
                    // Defer call, because it might interfere with the unreference() call in Internal\Socket otherwise
                    $i = ++$attempt % \count($nameservers);
                    $nameserver = $nameservers[$i];
                    $socket = $this->getSocket($nameserver);
                    continue;
                }
            }
            $timeout = new TimeoutException(\sprintf("No response for '%s' (%s) from any nameserver after %d attempts, tried %s", $name, Record::getName($type), $attempts, \implode(", ", $attemptDescription)));
            if (!$exceptions) {
                throw $timeout;
            }
            throw new MultiReasonException($exceptions, $timeout->getMessage());
        });
        $this->pendingQueries[$type . " " . $name] = $promise;
        $promise->onResolve(function () use($name, $type) {
            unset($this->pendingQueries[$type . " " . $name]);
        });
        return $promise;
    }
    /**
     *
     */
    private function normalizeName(string $name, int $type)
    {
        if ($type === Record::PTR) {
            if (($packedIp = @\inet_pton($name)) !== false) {
                if (isset($packedIp[4])) {
                    // IPv6
                    $name = \wordwrap(\strrev(\bin2hex($packedIp)), 1, ".", true) . ".ip6.arpa";
                } else {
                    // IPv4
                    $name = \inet_ntop(\strrev($packedIp)) . ".in-addr.arpa";
                }
            }
        } elseif (\in_array($type, [Record::A, Record::AAAA])) {
            $name = normalizeName($name);
        }
        return $name;
    }
    /**
     * @param string $name
     * @param int $type
     *
     * @return \LibDNS\Records\Question
     */
    private function createQuestion(string $name, int $type) : Question
    {
        if (0 > $type || 0xffff < $type) {
            $message = \sprintf('%d does not correspond to a valid record type (must be between 0 and 65535).', $type);
            throw new \Error($message);
        }
        $question = $this->questionFactory->create($type);
        $question->setName($name);
        return $question;
    }
    /**
     *
     */
    private function getCacheKey(string $name, int $type) : string
    {
        return self::CACHE_PREFIX . $name . "#" . $type;
    }
    /**
     *
     */
    private function decodeCachedResult(string $name, int $type, string $encoded)
    {
        $decoded = \json_decode($encoded, true);
        if (!$decoded) {
            throw new NoRecordException("No records returned for {$name} (cached result)");
        }
        $result = [];
        foreach ($decoded as $data) {
            $result[] = new Record($data, $type);
        }
        return $result;
    }
    /**
     *
     */
    private function getSocket(Nameserver $nameserver)
    {
        $uri = $nameserver->getUri();
        if (isset($this->sockets[$uri])) {
            return $this->sockets[$uri];
        }
        $this->sockets[$uri] = HttpsSocket::connect($this->dohConfig->getHttpClient(), $nameserver);
        return $this->sockets[$uri];
    }
    /**
     *
     */
    private function assertAcceptableResponse(Message $response)
    {
        if ($response->getResponseCode() !== 0) {
            throw new DnsException(\sprintf("Server returned error code: %d", $response->getResponseCode()));
        }
    }
}<?php

namespace Amp\DoH;

use Amp\Dns\ConfigException;
final class Nameserver
{
    const RFC8484_GET = 0;
    const RFC8484_POST = 1;
    const GOOGLE_JSON = 2;
    private $type;
    private $uri;
    private $host;
    private $headers = [];
    /**
     *
     */
    public function __construct(string $uri, int $type = self::RFC8484_POST, array $headers = [])
    {
        if (\parse_url($uri, PHP_URL_SCHEME) !== 'https') {
            throw new ConfigException('Did not provide a valid HTTPS url!');
        }
        if (!\in_array($type, [self::RFC8484_GET, self::RFC8484_POST, self::GOOGLE_JSON])) {
            throw new ConfigException('Invalid nameserver type provided!');
        }
        $this->uri = $uri;
        $this->type = $type;
        $this->headers = $headers;
        $this->host = \parse_url($uri, PHP_URL_HOST);
    }
    /**
     *
     */
    public function getUri() : string
    {
        return $this->uri;
    }
    /**
     *
     */
    public function getHost() : string
    {
        return $this->host;
    }
    /**
     *
     */
    public function getHeaders() : array
    {
        return $this->headers;
    }
    /**
     *
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->uri;
        /*
                switch ($this->type) {
                    case self::RFC8484_GET:
                        return "{$this->uri} RFC 8484 GET";
                    case self::RFC8484_POST:
                        return "{$this->uri} RFC 8484 POST";
                    case self::GOOGLE_JSON:
                        return "{$this->uri} google JSON";
                }*/
    }
}<?php

$config = new Amp\CodeStyle\Config();
$config->getFinder()->in(__DIR__ . '/src')->in(__DIR__ . '/tests');
$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;
$config->setCacheFile($cacheDir . '/.php_cs.cache');
return $config;<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
use const danog\Decoder\TYPES;
/**
 * Represents source of photosize.
 */
class PhotoSizeSourceThumbnail extends PhotoSizeSource
{
    /**
     * File type of original file.
     *
     * @var int
     */
    private $_thumbFileType;
    /**
     * Thumbnail size.
     *
     * @var string
     */
    private $_thumbType;
    /**
     * Get file type of original file.
     *
     * @return int
     */
    public function getThumbFileType() : int
    {
        return $this->_thumbFileType;
    }
    /**
     * Get file type of original file as string.
     *
     * @return string
     */
    public function getThumbFileTypeString() : string
    {
        return TYPES[$this->_thumbFileType];
    }
    /**
     * Set file type of original file.
     *
     * @param int $_thumbFileType File type of original file
     *
     * @return self
     */
    public function setThumbFileType(int $_thumbFileType) : self
    {
        $this->_thumbFileType = $_thumbFileType;
        return $this;
    }
    /**
     * Get thumbnail size.
     *
     * @return string
     */
    public function getThumbType() : string
    {
        return $this->_thumbType;
    }
    /**
     * Set thumbnail size.
     *
     * @param string $_thumbType Thumbnail size
     *
     * @return self
     */
    public function setThumbType(string $_thumbType) : self
    {
        $this->_thumbType = $_thumbType;
        return $this;
    }
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
/**
 * Represents source of photosize.
 *
 * @extends PhotoSizeSource<PhotoSizeSourceStickersetThumbnailVersion>
 */
class PhotoSizeSourceStickersetThumbnailVersion extends PhotoSizeSource
{
    /**
     * Stickerset ID.
     *
     * @var int
     */
    private $_stickerSetId;
    /**
     * Stickerset access hash.
     *
     * @var int
     */
    private $_stickerSetAccessHash;
    /**
     * Stickerset version.
     *
     * @var int
     */
    private $_stickerSetVersion;
    /**
     * Get stickerset ID.
     *
     * @return int
     */
    public function getStickerSetId()
    {
        return $this->_stickerSetId;
    }
    /**
     * Set stickerset ID.
     *
     * @param int $_stickerSetId Stickerset ID
     *
     * @return self
     */
    public function setStickerSetId($_stickerSetId) : self
    {
        $this->_stickerSetId = $_stickerSetId;
        return $this;
    }
    /**
     * Get stickerset access hash.
     *
     * @return int
     */
    public function getStickerSetAccessHash()
    {
        return $this->_stickerSetAccessHash;
    }
    /**
     * Set stickerset access hash.
     *
     * @param int $_stickerSetAccessHash Stickerset access hash
     *
     * @return self
     */
    public function setStickerSetAccessHash($_stickerSetAccessHash) : self
    {
        $this->_stickerSetAccessHash = $_stickerSetAccessHash;
        return $this;
    }
    /**
     * Get stickerset version.
     *
     * @return int
     */
    public function getStickerSetVersion() : int
    {
        return $this->_stickerSetVersion;
    }
    /**
     * Set stickerset version.
     *
     * @param int $_stickerSetVersion Stickerset version.
     *
     * @return self
     */
    public function setStickerSetVersion(int $_stickerSetVersion) : self
    {
        $this->_stickerSetVersion = $_stickerSetVersion;
        return $this;
    }
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
use const danog\Decoder\PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL;
use const danog\Decoder\PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY;
/**
 * Represents source of photosize.
 *
 * @extends PhotoSizeSource<PhotoSizeSourceDialogPhoto>
 */
class PhotoSizeSourceDialogPhoto extends PhotoSizeSource
{
    /**
     * ID of dialog.
     *
     * @var int
     */
    private $_dialogId;
    /**
     * Access hash of dialog.
     *
     * @var int
     */
    private $_dialogAccessHash;
    /**
     * Get dialog ID.
     *
     * @return int
     */
    public function getDialogId()
    {
        return $this->_dialogId;
    }
    /**
     * Set dialog ID.
     *
     * @param int $id Dialog ID
     *
     * @return self
     */
    public function setDialogId($id) : self
    {
        $this->_dialogId = $id;
        return $this;
    }
    /**
     * Get access hash of dialog.
     *
     * @return int
     */
    public function getDialogAccessHash()
    {
        return $this->_dialogAccessHash;
    }
    /**
     * Set access hash of dialog.
     *
     * @param int $dialogAccessHash Access hash of dialog
     *
     * @return self
     */
    public function setDialogAccessHash($dialogAccessHash) : self
    {
        $this->_dialogAccessHash = $dialogAccessHash;
        return $this;
    }
    /**
     * Get whether the big or small version of the photo is being used.
     *
     * @return bool
     */
    public function isSmallDialogPhoto() : bool
    {
        return \in_array($this->getType(), [PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY, PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL]);
    }
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
/**
 * Represents source of photosize.
 *
 * @extends PhotoSizeSource<PhotoSizeSourceLegacy>
 */
class PhotoSizeSourceLegacy extends PhotoSizeSource
{
    /**
     * Secret legacy ID.
     *
     * @var int
     */
    private $_secret;
    /**
     * Get secret legacy ID.
     *
     * @return int
     */
    public function getSecret()
    {
        return $this->_secret;
    }
    /**
     * Set secret legacy ID.
     *
     * @param int $_secret Secret legacy ID
     *
     * @return self
     */
    public function setSecret($_secret) : self
    {
        $this->_secret = $_secret;
        return $this;
    }
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
/**
 * Represents source of photosize.
 *
 * @extends PhotoSizeSource<PhotoSizeSourceStickersetThumbnail>
 */
class PhotoSizeSourceStickersetThumbnail extends PhotoSizeSource
{
    /**
     * Stickerset ID.
     *
     * @var int
     */
    private $_stickerSetId;
    /**
     * Stickerset access hash.
     *
     * @var int
     */
    private $_stickerSetAccessHash;
    /**
     * Get stickerset ID.
     *
     * @return int
     */
    public function getStickerSetId()
    {
        return $this->_stickerSetId;
    }
    /**
     * Set stickerset ID.
     *
     * @param int $_stickerSetId Stickerset ID
     *
     * @return self
     */
    public function setStickerSetId($_stickerSetId) : self
    {
        $this->_stickerSetId = $_stickerSetId;
        return $this;
    }
    /**
     * Get stickerset access hash.
     *
     * @return int
     */
    public function getStickerSetAccessHash()
    {
        return $this->_stickerSetAccessHash;
    }
    /**
     * Set stickerset access hash.
     *
     * @param int $_stickerSetAccessHash Stickerset access hash
     *
     * @return self
     */
    public function setStickerSetAccessHash($_stickerSetAccessHash) : self
    {
        $this->_stickerSetAccessHash = $_stickerSetAccessHash;
        return $this;
    }
}<?php

/**
 * Decoded FileId class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder;

use danog\Decoder\PhotoSizeSource\PhotoSizeSourceDialogPhoto;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceLegacy;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceStickersetThumbnail;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceStickersetThumbnailVersion;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceThumbnail;
/**
 * Represents decoded bot API file ID.
 */
class FileId
{
    /**
     * Bot API file ID version.
     *
     * @var int
     */
    private $_version = 4;
    /**
     * Bot API file ID subversion.
     *
     * @var int
     */
    private $_subVersion = 32;
    /**
     * DC ID.
     *
     * @var int
     */
    private $_dcId = 0;
    /**
     * File type.
     *
     * @var int
     */
    private $_type = 0;
    /**
     * File reference.
     *
     * @var string
     */
    private $_fileReference = '';
    /**
     * File URL for weblocation.
     *
     * @var string
     */
    private $_url = '';
    /**
     * File id.
     *
     * @var int
     */
    private $_id;
    /**
     * File access hash.
     *
     * @var int
     */
    private $_accessHash;
    /**
     * Photo volume ID.
     *
     * @var int
     */
    private $_volumeId;
    /**
     * Photo local ID.
     *
     * @var int
     */
    private $_localId;
    /**
     * Photo size source.
     *
     * @var PhotoSizeSource
     */
    private $_photoSizeSource;
    /**
     * Basic constructor function.
     */
    public function __construct()
    {
    }
    /**
     * Decode file ID from bot API file ID.
     *
     * @param string $fileId File ID
     *
     * @return self
     */
    public static function fromBotAPI(string $fileId) : self
    {
        $result = new self();
        $resultArray = internalDecode($fileId);
        $result->setVersion($resultArray['version']);
        $result->setSubVersion($resultArray['subVersion']);
        $result->setType($resultArray['typeId']);
        $result->setDcId($resultArray['dc_id']);
        $result->setAccessHash($resultArray['access_hash']);
        if ($resultArray['hasReference']) {
            $result->setFileReference($resultArray['fileReference']);
        }
        if ($resultArray['hasWebLocation']) {
            $result->setUrl($resultArray['webLocation']);
            return $result;
        }
        $result->setId($resultArray['id']);
        if ($result->getType() <= PHOTO) {
            if (isset($resultArray['volume_id'])) {
                $result->setVolumeId($resultArray['volume_id']);
            }
            if (isset($resultArray['local_id'])) {
                $result->setLocalId($resultArray['local_id']);
            }
            switch ($resultArray['photosize_source']) {
                case PHOTOSIZE_SOURCE_LEGACY:
                case PHOTOSIZE_SOURCE_FULL_LEGACY:
                    $photoSizeSource = new PhotoSizeSourceLegacy($resultArray['photosize_source']);
                    $photoSizeSource->setSecret($resultArray['secret']);
                    break;
                case PHOTOSIZE_SOURCE_THUMBNAIL:
                    $photoSizeSource = new PhotoSizeSourceThumbnail($resultArray['photosize_source']);
                    $photoSizeSource->setThumbType($resultArray['thumbnail_type']);
                    $photoSizeSource->setThumbFileType($resultArray['file_type']);
                    break;
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG_LEGACY:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL:
                    $photoSizeSource = new PhotoSizeSourceDialogPhoto($resultArray['photosize_source']);
                    $photoSizeSource->setDialogId($resultArray['dialog_id']);
                    $photoSizeSource->setDialogAccessHash($resultArray['dialog_access_hash']);
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL:
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY:
                    $photoSizeSource = new PhotoSizeSourceStickersetThumbnail($resultArray['photosize_source']);
                    $photoSizeSource->setStickerSetId($resultArray['sticker_set_id']);
                    $photoSizeSource->setStickerSetAccessHash($resultArray['sticker_set_access_hash']);
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_VERSION:
                    $photoSizeSource = new PhotoSizeSourceStickersetThumbnailVersion($resultArray['photosize_source']);
                    $photoSizeSource->setStickerSetId($resultArray['sticker_set_id']);
                    $photoSizeSource->setStickerSetAccessHash($resultArray['sticker_set_access_hash']);
                    $photoSizeSource->setStickerSetVersion($resultArray['sticker_version']);
                    break;
            }
            $result->setPhotoSizeSource($photoSizeSource);
        }
        return $result;
    }
    /**
     * Get bot API file ID.
     *
     * @return string
     */
    public function getBotAPI() : string
    {
        $type = $this->getType();
        if ($this->hasFileReference()) {
            $type |= FILE_REFERENCE_FLAG;
        }
        if ($this->hasUrl()) {
            $type |= WEB_LOCATION_FLAG;
        }
        $fileId = \pack('VV', $type, $this->getDcId());
        if ($this->hasFileReference()) {
            $fileId .= packTLString($this->getFileReference());
        }
        if ($this->hasUrl()) {
            $fileId .= packTLString($this->getUrl());
            $fileId .= packLong($this->getAccessHash());
            return base64urlEncode(rleEncode($fileId));
        }
        $fileId .= packLong($this->getId());
        $fileId .= packLong($this->getAccessHash());
        if ($this->getType() <= PHOTO) {
            $photoSize = $this->getPhotoSizeSource();
            $fileId .= \pack('V', $photoSize->getType());
            switch ($photoSize->getType()) {
                case PHOTOSIZE_SOURCE_LEGACY:
                    $fileId .= packLong($photoSize->getSecret());
                    break;
                case PHOTOSIZE_SOURCE_FULL_LEGACY:
                    $fileId .= packLong($this->getVolumeId());
                    $fileId .= packLong($photoSize->getSecret());
                    $fileId .= \pack('l', $this->getLocalId());
                    break;
                case PHOTOSIZE_SOURCE_THUMBNAIL:
                    $fileId .= \pack('Va4', $photoSize->getThumbFileType(), $photoSize->getThumbType());
                    break;
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG_LEGACY:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY:
                    $fileId .= packLongBig($photoSize->getDialogId());
                    $fileId .= packLong($photoSize->getDialogAccessHash());
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL:
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY:
                    $fileId .= packLong($photoSize->getStickerSetId());
                    $fileId .= packLong($photoSize->getStickerSetAccessHash());
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_VERSION:
                    $fileId .= packLong($photoSize->getStickerSetId());
                    $fileId .= packLong($photoSize->getStickerSetAccessHash());
                    $fileId .= \pack('l', $photoSize->getStickerSetVersion());
                    break;
            }
            if ($photoSize->getType() >= PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY && $photoSize->getType() <= PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY) {
                $fileId .= packLong($this->getVolumeId());
                $fileId .= \pack('l', $this->getLocalId());
            }
        }
        if ($this->getVersion() >= 4) {
            $fileId .= \chr($this->getSubVersion());
        }
        $fileId .= \chr($this->getVersion());
        return base64urlEncode(rleEncode($fileId));
    }
    /**
     * Get unique file ID from file ID.
     *
     * @return UniqueFileId
     */
    public function getUnique() : UniqueFileId
    {
        return UniqueFileId::fromFileId($this);
    }
    /**
     * Get unique bot API file ID from file ID.
     *
     * @return string
     */
    public function getUniqueBotAPI() : string
    {
        return UniqueFileId::fromFileId($this)->getUniqueBotAPI();
    }
    /**
     * Get bot API file ID.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->getBotAPI();
    }
    /**
     * Get bot API file ID version.
     *
     * @return int
     */
    public function getVersion() : int
    {
        return $this->_version;
    }
    /**
     * Set bot API file ID version.
     *
     * @param int $_version Bot API file ID version.
     *
     * @return self
     */
    public function setVersion(int $_version) : self
    {
        $this->_version = $_version;
        return $this;
    }
    /**
     * Get bot API file ID subversion.
     *
     * @return int
     */
    public function getSubVersion() : int
    {
        return $this->_subVersion;
    }
    /**
     * Set bot API file ID subversion.
     *
     * @param int $_subVersion Bot API file ID subversion.
     *
     * @return self
     */
    public function setSubVersion(int $_subVersion) : self
    {
        $this->_subVersion = $_subVersion;
        return $this;
    }
    /**
     * Get file type.
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->_type;
    }
    /**
     * Get file type as string.
     *
     * @return string
     */
    public function getTypeName() : string
    {
        return TYPES[$this->_type];
    }
    /**
     * Set file type.
     *
     * @param int $_type File type.
     *
     * @return self
     */
    public function setType(int $_type) : self
    {
        $this->_type = $_type;
        return $this;
    }
    /**
     * Get file reference.
     *
     * @return string
     */
    public function getFileReference() : string
    {
        return $this->_fileReference;
    }
    /**
     * Set file reference.
     *
     * @param string $_fileReference File reference.
     *
     * @return self
     */
    public function setFileReference(string $_fileReference) : self
    {
        $this->_fileReference = $_fileReference;
        return $this;
    }
    /**
     * Check if has file reference.
     *
     * @return boolean
     */
    public function hasFileReference() : bool
    {
        return !empty($this->_fileReference);
    }
    /**
     * Get file URL for weblocation.
     *
     * @return string
     */
    public function getUrl() : string
    {
        return $this->_url;
    }
    /**
     * Check if has file URL.
     *
     * @return boolean
     */
    public function hasUrl() : bool
    {
        return !empty($this->_url);
    }
    /**
     * Set file URL for weblocation.
     *
     * @param string $_url File URL for weblocation.
     *
     * @return self
     */
    public function setUrl(string $_url) : self
    {
        $this->_url = $_url;
        return $this;
    }
    /**
     * Get file id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->_id;
    }
    /**
     * Set file id.
     *
     * @param int $_id File id.
     *
     * @return self
     */
    public function setId($_id) : self
    {
        $this->_id = $_id;
        return $this;
    }
    /**
     * Check if has file id.
     *
     * @return bool
     */
    public function hasId() : bool
    {
        return isset($this->_id);
    }
    /**
     * Get file access hash.
     *
     * @return int
     */
    public function getAccessHash()
    {
        return $this->_accessHash;
    }
    /**
     * Set file access hash.
     *
     * @param int $_accessHash File access hash.
     *
     * @return self
     */
    public function setAccessHash($_accessHash) : self
    {
        $this->_accessHash = $_accessHash;
        return $this;
    }
    /**
     * Get photo volume ID.
     *
     * @return int
     */
    public function getVolumeId()
    {
        return $this->_volumeId;
    }
    /**
     * Set photo volume ID.
     *
     * @param int $_volumeId Photo volume ID.
     *
     * @return self
     */
    public function setVolumeId($_volumeId) : self
    {
        $this->_volumeId = $_volumeId;
        return $this;
    }
    /**
     * Check if has volume ID.
     *
     * @return boolean
     */
    public function hasVolumeId() : bool
    {
        return isset($this->_volumeId);
    }
    /**
     * Get photo local ID.
     *
     * @return int
     */
    public function getLocalId() : int
    {
        return $this->_localId;
    }
    /**
     * Set photo local ID.
     *
     * @param int $_localId Photo local ID.
     *
     * @return self
     */
    public function setLocalId(int $_localId) : self
    {
        $this->_localId = $_localId;
        return $this;
    }
    /**
     * Check if has local ID.
     *
     * @return boolean
     */
    public function hasLocalId() : bool
    {
        return isset($this->_localId);
    }
    /**
     * Get photo size source.
     *
     * @return PhotoSizeSource
     */
    public function getPhotoSizeSource() : PhotoSizeSource
    {
        return $this->_photoSizeSource;
    }
    /**
     * Set photo size source.
     *
     * @param PhotoSizeSource $_photoSizeSource Photo size source.
     *
     * @return self
     */
    public function setPhotoSizeSource(PhotoSizeSource $_photoSizeSource) : self
    {
        $this->_photoSizeSource = $_photoSizeSource;
        return $this;
    }
    /**
     * Check if has photo size source.
     *
     * @return boolean
     */
    public function hasPhotoSizeSource() : bool
    {
        return isset($this->_photoSizeSource);
    }
    /**
     * Get dC ID.
     *
     * @return int
     */
    public function getDcId() : int
    {
        return $this->_dcId;
    }
    /**
     * Set dC ID.
     *
     * @param int $_dcId DC ID.
     *
     * @return self
     */
    public function setDcId(int $_dcId) : self
    {
        $this->_dcId = $_dcId;
        return $this;
    }
}<?php

/**
 * Type enum + helper functions.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder;

/**
 * Thumbnail.
 */
const THUMBNAIL = 0;
/**
 * Profile photo.
 * Used for users and channels, chat photos are normal PHOTOs.
 */
const PROFILE_PHOTO = 1;
/**
 * Normal photos.
 */
const PHOTO = 2;
/**
 * Voice messages.
 */
const VOICE = 3;
/**
 * Video.
 */
const VIDEO = 4;
/**
 * Document.
 */
const DOCUMENT = 5;
/**
 * Secret chat document.
 */
const ENCRYPTED = 6;
/**
 * Temporary document.
 */
const TEMP = 7;
/**
 * Sticker.
 */
const STICKER = 8;
/**
 * Music.
 */
const AUDIO = 9;
/**
 * GIF.
 */
const ANIMATION = 10;
/**
 * Encrypted thumbnail.
 */
const ENCRYPTED_THUMBNAIL = 11;
/**
 * Wallpaper.
 */
const WALLPAPER = 12;
/**
 * Round video.
 */
const VIDEO_NOTE = 13;
/**
 * Passport raw file.
 */
const SECURE_RAW = 14;
/**
 * Passport file.
 */
const SECURE = 15;
/**
 * Background.
 */
const BACKGROUND = 16;
/**
 * Size.
 */
const SIZE = 17;
const NONE = 18;
const TYPES = [THUMBNAIL => 'thumbnail', PROFILE_PHOTO => 'profile_photo', PHOTO => 'photo', VOICE => 'voice', VIDEO => 'video', DOCUMENT => 'document', ENCRYPTED => 'encrypted', TEMP => 'temp', STICKER => 'sticker', AUDIO => 'audio', ANIMATION => 'animation', ENCRYPTED_THUMBNAIL => 'encrypted_thumbnail', WALLPAPER => 'wallpaper', VIDEO_NOTE => 'video_note', SECURE_RAW => 'secure_raw', SECURE => 'secure', BACKGROUND => 'background', SIZE => 'size'];
const TYPES_IDS = ['thumbnail' => THUMBNAIL, 'profile_photo' => PROFILE_PHOTO, 'photo' => PHOTO, 'voice' => VOICE, 'video' => VIDEO, 'document' => DOCUMENT, 'encrypted' => ENCRYPTED, 'temp' => TEMP, 'sticker' => STICKER, 'audio' => AUDIO, 'animation' => ANIMATION, 'encrypted_thumbnail' => ENCRYPTED_THUMBNAIL, 'wallpaper' => WALLPAPER, 'video_note' => VIDEO_NOTE, 'secure_raw' => SECURE_RAW, 'secure' => SECURE, 'background' => BACKGROUND, 'size' => SIZE];
const UNIQUE_WEB = 0;
const UNIQUE_PHOTO = 1;
const UNIQUE_DOCUMENT = 2;
const UNIQUE_SECURE = 3;
const UNIQUE_ENCRYPTED = 4;
const UNIQUE_TEMP = 5;
const UNIQUE_TYPES = [UNIQUE_WEB => 'web', UNIQUE_PHOTO => 'photo', UNIQUE_DOCUMENT => 'document', UNIQUE_SECURE => 'secure', UNIQUE_ENCRYPTED => 'encrypted', UNIQUE_TEMP => 'temp'];
const UNIQUE_TYPES_IDS = ['web' => UNIQUE_WEB, 'photo' => UNIQUE_PHOTO, 'document' => UNIQUE_DOCUMENT, 'secure' => UNIQUE_SECURE, 'encrypted' => UNIQUE_ENCRYPTED, 'temp' => UNIQUE_TEMP];
const FULL_UNIQUE_MAP = [PHOTO => UNIQUE_PHOTO, PROFILE_PHOTO => UNIQUE_PHOTO, THUMBNAIL => UNIQUE_PHOTO, ENCRYPTED_THUMBNAIL => UNIQUE_PHOTO, WALLPAPER => UNIQUE_PHOTO, VIDEO => UNIQUE_DOCUMENT, VOICE => UNIQUE_DOCUMENT, DOCUMENT => UNIQUE_DOCUMENT, STICKER => UNIQUE_DOCUMENT, AUDIO => UNIQUE_DOCUMENT, ANIMATION => UNIQUE_DOCUMENT, VIDEO_NOTE => UNIQUE_DOCUMENT, BACKGROUND => UNIQUE_DOCUMENT, SECURE => UNIQUE_SECURE, SECURE_RAW => UNIQUE_SECURE, ENCRYPTED => UNIQUE_ENCRYPTED, TEMP => UNIQUE_TEMP];
const PHOTOSIZE_SOURCE_LEGACY = 0;
const PHOTOSIZE_SOURCE_THUMBNAIL = 1;
const PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL = 2;
const PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG = 3;
const PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL = 4;
const PHOTOSIZE_SOURCE_FULL_LEGACY = 5;
const PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY = 6;
const PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG_LEGACY = 7;
const PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY = 8;
const PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_VERSION = 9;
const WEB_LOCATION_FLAG = 1 << 24;
const FILE_REFERENCE_FLAG = 1 << 25;
const LONG = PHP_INT_SIZE === 8 ? 'Q' : 'l2';
$BIG_ENDIAN = \pack('L', 1) === \pack('N', 1);
/**
 * Unpack long properly, returns an actual number in any case.
 *
 * @param string $field Field to unpack
 *
 * @return (string | int)
 */
function unpackLong(string $field)
{
    if (PHP_INT_SIZE === 8) {
        /** @psalm-suppress InvalidGlobal */
        global $BIG_ENDIAN;
        // Evil
        return \unpack('q', $BIG_ENDIAN ? \strrev($field) : $field)[1];
    }
    if (\class_exists(\tgseclib\Math\BigInteger::class)) {
        return (string) new \tgseclib\Math\BigInteger(\strrev($field), -256);
    }
    if (\class_exists(\phpseclib\Math\BigInteger::class)) {
        return (string) new \phpseclib\Math\BigInteger(\strrev($field), -256);
    }
    throw new \Error('Please install phpseclib to unpack bot API file IDs');
}
/**
 * Pack string long.
 *
 * @param (string | int) $field
 *
 * @return string
 */
function packLongBig($field) : string
{
    if (PHP_INT_SIZE === 8) {
        /** @psalm-suppress InvalidGlobal */
        global $BIG_ENDIAN;
        // Evil
        $res = \pack('q', $field);
        return $BIG_ENDIAN ? \strrev($res) : $res;
    }
    if (\class_exists(\tgseclib\Math\BigInteger::class)) {
        return (new \tgseclib\Math\BigInteger($field))->toBytes();
    }
    if (\class_exists(\phpseclib\Math\BigInteger::class)) {
        return (new \phpseclib\Math\BigInteger($field))->toBytes();
    }
    throw new \Error('Please install phpseclib to unpack bot API file IDs');
}
/**
 * Fix long parameters in case of 32 bit systems.
 *
 * @param array $params Parameters
 * @param string $field 64-bit field
 *
 * @return void
 */
function fixLong(array &$params, string $field)
{
    if (PHP_INT_SIZE === 8) {
        return;
    }
    $params[$field] = [$params[$field . '1'], $params[$field . '2']];
    unset($params[$field . '1'], $params[$field . '2']);
}
/**
 * Encode long to string.
 *
 * @param (string | int | int[]) $fields Fields to encode
 *
 * @return string
 */
function packLong($fields) : string
{
    if (\is_string($fields)) {
        // Already encoded, we hope
        return $fields;
    }
    if (PHP_INT_SIZE === 8) {
        return \pack(LONG, $fields);
    }
    return \pack(LONG, ...$fields);
}
/**
 * Base64URL decode.
 *
 * @param string $data Data to decode
 *
 * @internal
 *
 * @return string
 */
function base64urlDecode(string $data) : string
{
    return \base64_decode(\str_pad(\strtr($data, '-_', '+/'), \strlen($data) % 4, '=', STR_PAD_RIGHT));
}
/**
 * Base64URL encode.
 *
 * @param string $data Data to encode
 *
 * @internal
 *
 * @return string
 */
function base64urlEncode(string $data) : string
{
    return \rtrim(\strtr(\base64_encode($data), '+/', '-_'), '=');
}
/**
 * Null-byte RLE decode.
 *
 * @param string $string Data to decode
 *
 * @internal
 *
 * @return string
 */
function rleDecode(string $string) : string
{
    $new = '';
    $last = '';
    $null = "\x00";
    foreach (\str_split($string) as $cur) {
        if ($last === $null) {
            $new .= \str_repeat($last, \ord($cur));
            $last = '';
        } else {
            $new .= $last;
            $last = $cur;
        }
    }
    $string = $new . $last;
    return $string;
}
/**
 * Null-byte RLE encode.
 *
 * @param string $string Data to encode
 *
 * @internal
 *
 * @return string
 */
function rleEncode(string $string) : string
{
    $new = '';
    $count = 0;
    $null = "\x00";
    foreach (\str_split($string) as $cur) {
        if ($cur === $null) {
            ++$count;
        } else {
            if ($count > 0) {
                $new .= $null . \chr($count);
                $count = 0;
            }
            $new .= $cur;
        }
    }
    if ($count > 0) {
        $new .= $null . \chr($count);
        $count = 0;
    }
    return $new;
}
/**
* Positive modulo
Works just like the % (modulus) operator, only returns always a postive number.
*
* @param int $a A
* @param int $b B
*
* @internal
*
* @return int Modulo
*/
function posmod(int $a, int $b) : int
{
    $resto = $a % $b;
    return $resto < 0 ? $resto + \abs($b) : $resto;
}
/**
 * Read TL string.
 *
 * @param mixed $stream Byte stream
 *
 * @internal
 *
 * @return string
 */
function readTLString($stream) : string
{
    $l = \ord(\stream_get_contents($stream, 1));
    if ($l > 254) {
        throw new \InvalidArgumentException("Length too big!");
    }
    if ($l === 254) {
        $long_len = \unpack('V', \stream_get_contents($stream, 3) . \chr(0))[1];
        $x = \stream_get_contents($stream, $long_len);
        $resto = posmod(-$long_len, 4);
        if ($resto > 0) {
            \stream_get_contents($stream, $resto);
        }
    } else {
        $x = $l ? \stream_get_contents($stream, $l) : '';
        $resto = posmod(-($l + 1), 4);
        if ($resto > 0) {
            \stream_get_contents($stream, $resto);
        }
    }
    return $x;
}
/**
 * Pack TL string.
 *
 * @param string $string String
 *
 * @return string
 */
function packTLString(string $string) : string
{
    $l = \strlen($string);
    $concat = '';
    if ($l <= 253) {
        $concat .= \chr($l);
        $concat .= $string;
        $concat .= \pack('@' . posmod(-$l - 1, 4));
    } else {
        $concat .= \chr(254);
        $concat .= \Phabel\Target\Php80\Polyfill::substr(\pack('V', $l), 0, 3);
        $concat .= $string;
        $concat .= \pack('@' . posmod(-$l, 4));
    }
    return $concat;
}
/**
 * Internal decode function.
 *
 * I know that you will use this directly giuseppe
 *
 * @param string $fileId Bot API file ID
 *
 * @internal
 *
 * @return array
 */
function internalDecode(string $fileId) : array
{
    $orig = $fileId;
    $fileId = rleDecode(base64urlDecode($fileId));
    $result = [];
    $result['version'] = \ord($fileId[\strlen($fileId) - 1]);
    $result['subVersion'] = $result['version'] === 4 ? \ord($fileId[\strlen($fileId) - 2]) : 0;
    $result += \unpack('VtypeId/Vdc_id', $fileId);
    $result['hasReference'] = (bool) ($result['typeId'] & FILE_REFERENCE_FLAG);
    $result['hasWebLocation'] = (bool) ($result['typeId'] & WEB_LOCATION_FLAG);
    $result['typeId'] &= ~FILE_REFERENCE_FLAG;
    $result['typeId'] &= ~WEB_LOCATION_FLAG;
    if (!isset(TYPES[$result['typeId']])) {
        throw new \InvalidArgumentException("Invalid file type provided: {$result['typeId']}");
    }
    $result['type'] = TYPES[$result['typeId']];
    $res = \fopen('php://memory', 'rw+b');
    \fwrite($res, \Phabel\Target\Php80\Polyfill::substr($fileId, 8));
    \fseek($res, 0);
    $fileId = $res;
    if ($result['hasReference']) {
        $result['fileReference'] = readTLString($fileId);
    }
    if ($result['hasWebLocation']) {
        $result['url'] = readTLString($fileId);
        $result['access_hash'] = \unpack(LONG . 'access_hash', \stream_get_contents($fileId, 8));
        fixLong($result, 'access_hash');
        return $result;
    }
    $result += \unpack(LONG . 'id/' . LONG . 'access_hash', \stream_get_contents($fileId, 16));
    fixLong($result, 'id');
    fixLong($result, 'access_hash');
    if ($result['typeId'] <= PHOTO) {
        $parsePhotoSize = function () use(&$result, &$fileId) {
            $result['photosize_source'] = $result['subVersion'] >= 4 ? \unpack('V', \stream_get_contents($fileId, 4))[1] : 0;
            switch ($result['photosize_source']) {
                case PHOTOSIZE_SOURCE_LEGACY:
                    $result += \unpack(LONG . 'secret', \stream_get_contents($fileId, 8));
                    fixLong($result, 'secret');
                    break;
                case PHOTOSIZE_SOURCE_THUMBNAIL:
                    $result += \unpack('Vfile_type/athumbnail_type', \stream_get_contents($fileId, 8));
                    break;
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL:
                    $result['photo_size'] = $result['photosize_source'] === PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL ? 'photo_small' : 'photo_big';
                    $result['dialog_id'] = unpackLong(\stream_get_contents($fileId, 8));
                    $result['dialog_access_hash'] = \unpack(LONG, \stream_get_contents($fileId, 8))[1];
                    fixLong($result, 'dialog_access_hash');
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL:
                    $result += \unpack(LONG . 'sticker_set_id/' . LONG . 'sticker_set_access_hash', \stream_get_contents($fileId, 16));
                    fixLong($result, 'sticker_set_id');
                    fixLong($result, 'sticker_set_access_hash');
                    break;
                case PHOTOSIZE_SOURCE_FULL_LEGACY:
                    $result += \unpack(LONG . 'volume_id/' . LONG . 'secret/llocal_id', \stream_get_contents($fileId, 20));
                    fixLong($result, 'volume_id');
                    fixLong($result, 'secret');
                    break;
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG_LEGACY:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY:
                    $result['photo_size'] = $result['photosize_source'] === PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY ? 'photo_small' : 'photo_big';
                    $result['dialog_id'] = unpackLong(\stream_get_contents($fileId, 8));
                    $result['dialog_access_hash'] = \unpack(LONG, \stream_get_contents($fileId, 8))[1];
                    fixLong($result, 'dialog_access_hash');
                    $result += \unpack(LONG . 'volume_id/llocal_id', \stream_get_contents($fileId, 12));
                    fixLong($result, 'volume_id');
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY:
                    $result += \unpack(LONG . 'sticker_set_id/' . LONG . 'sticker_set_access_hash', \stream_get_contents($fileId, 16));
                    fixLong($result, 'sticker_set_id');
                    fixLong($result, 'sticker_set_access_hash');
                    $result += \unpack(LONG . 'volume_id/llocal_id', \stream_get_contents($fileId, 12));
                    fixLong($result, 'volume_id');
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_VERSION:
                    $result += \unpack(LONG . 'sticker_set_id/' . LONG . 'sticker_set_access_hash/lsticker_version', \stream_get_contents($fileId, 20));
                    fixLong($result, 'sticker_set_id');
                    fixLong($result, 'sticker_set_access_hash');
                    break;
            }
        };
        if ($result['subVersion'] >= 32) {
            $parsePhotoSize();
        } else {
            $result += \unpack(LONG . 'volume_id', \stream_get_contents($fileId, 8));
            fixLong($result, 'volume_id');
            if ($result['subVersion'] >= 22) {
                $parsePhotoSize();
                $result += \unpack('llocal_id', \stream_get_contents($fileId, 4));
            } else {
                $result += \unpack(LONG . 'secret/llocal_id', \stream_get_contents($fileId, 12));
                fixLong($result, 'volume_id');
                fixLong($result, 'secret');
            }
        }
    }
    $l = \fstat($fileId)['size'] - \ftell($fileId);
    $l -= $result['version'] >= 4 ? 2 : 1;
    if ($l > 0) {
        \trigger_error("File ID {$orig} has {$l} bytes of leftover data");
    }
    return $result;
}
/**
 * Internal decode function.
 *
 * I know that you will use this directly giuseppe
 *
 * @param string $fileId Bot API file ID
 *
 * @internal
 *
 * @return array
 */
function internalDecodeUnique(string $fileId) : array
{
    $orig = $fileId;
    $fileId = rleDecode(base64urlDecode($fileId));
    $result = \unpack('VtypeId', $fileId);
    if (!isset(UNIQUE_TYPES[$result['typeId']])) {
        throw new \InvalidArgumentException("Invalid file type provided: {$result['typeId']}");
    }
    $result['type'] = UNIQUE_TYPES[$result['typeId']];
    $fileId = \Phabel\Target\Php80\Polyfill::substr($fileId, 4);
    if ($result['typeId'] === UNIQUE_WEB) {
        $res = \fopen('php://memory', 'rw+b');
        \fwrite($res, $fileId);
        \fseek($res, 0);
        $fileId = $res;
        $result['url'] = readTLString($fileId);
        $l = \fstat($fileId)['size'] - \ftell($fileId);
    } elseif (\strlen($fileId) === 12) {
        // Legacy photos
        $result += \unpack(LONG . 'volume_id/llocal_id', $fileId);
        fixLong($result, 'volume_id');
        $l = 0;
    } elseif (\strlen($fileId) === 9) {
        // Dialog photos/thumbnails
        $result += \unpack(LONG . 'id/CsubType', $fileId);
        fixLong($result, 'id');
        $l = 0;
    } elseif (\strlen($fileId) === 13) {
        // Stickerset ID/version
        $result += \unpack('CsubType/' . LONG . 'sticker_set_id/lsticker_set_version', $fileId);
        fixLong($result, 'sticker_set_id');
        $l = 0;
    } elseif (\strlen($fileId) === 8) {
        // Any other document
        $result += \unpack(LONG . 'id', $fileId);
        fixLong($result, 'id');
        $l = 0;
    } else {
        $l = \strlen($fileId);
    }
    if ($l > 0) {
        \trigger_error("Unique file ID {$orig} has {$l} bytes of leftover data");
    }
    return $result;
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder;

use danog\Decoder\PhotoSizeSource\PhotoSizeSourceLegacy;
/**
 * Represents source of photosize.
 *
 * @template T
 */
abstract class PhotoSizeSource
{
    /**
     * Source type.
     *
     * @var int
     */
    private $_type;
    /**
     * Set photosize source type.
     *
     * @param integer $type Type
     */
    public function __construct(int $type)
    {
        $this->_type = $type;
        return $this;
    }
    /**
    * Get photosize source type.
    *
    * @return integer
    *
    * @psalm-return (
    T is PhotoSizeSourceLegacy ?
    ? \danog\Decoder\PHOTOSIZE_SOURCE_LEGACY
    : (T is PhotoSizeSourceDialogPhoto
    ? \danog\Decoder\PHOTOSIZE_SOURCE_DIALOGPHOTO_*
    (T is PhotoSizeSourceStickersetThumbnail
    ? \danog\Decoder\PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL
    : \danog\Decoder\PHOTOSIZE_SOURCE_THUMBNAIL
    )
    )
    *
    * @internal Internal use
    */
    public function getType() : int
    {
        return $this->_type;
    }
}<?php

/**
 * Decoded UniqueFileId class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder;

use danog\Decoder\PhotoSizeSource\PhotoSizeSourceDialogPhoto;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceStickersetThumbnailVersion;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceThumbnail;
/**
 * Represents decoded unique bot API file ID.
 */
class UniqueFileId
{
    /**
     * File type.
     *
     * @var int
     */
    private $_type = NONE;
    /**
     * File ID.
     *
     * @var int
     */
    private $_id;
    /**
     * Photo volume ID.
     *
     * @var int
     */
    private $_volumeId;
    /**
     * Photo local ID.
     *
     * @var int
     */
    private $_localId;
    /**
     * Photo subtype.
     *
     * @var int
     */
    private $_subType;
    /**
     * Sticker set ID.
     *
     * @var int
     */
    private $_stickerSetId;
    /**
     * Sticker set version.
     *
     * @var int
     */
    private $_stickerSetVersion;
    /**
     * Weblocation URL.
     *
     * @var string
     */
    private $_url;
    /**
     * Basic constructor function.
     */
    public function __construct()
    {
    }
    /**
     * Get unique bot API file ID.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->getUniqueBotAPI();
    }
    /**
     * Get unique bot API file ID.
     *
     * @return string
     */
    public function getUniqueBotAPI() : string
    {
        $fileId = \pack('V', $this->getType());
        if ($this->getType() === UNIQUE_WEB) {
            $fileId .= packTLString($this->getUrl());
        } elseif ($this->getType() === UNIQUE_PHOTO) {
            if ($this->hasVolumeId()) {
                $fileId .= packLong($this->getVolumeId());
                $fileId .= \pack('l', $this->getLocalId());
            } elseif ($this->hasStickerSetId()) {
                $fileId .= \chr($this->getSubType());
                $fileId .= packLong($this->getStickerSetId());
                $fileId .= \pack('l', $this->getStickerSetVersion());
            } else {
                $fileId .= packLong($this->getId());
                $fileId .= \chr($this->getSubType());
            }
        } elseif ($this->hasId()) {
            $fileId .= packLong($this->getId());
        }
        return base64urlEncode(rleEncode($fileId));
    }
    /**
     * Decode unique bot API file ID.
     *
     * @param string $fileId Bot API file ID
     *
     * @return self
     */
    public static function fromUniqueBotAPI(string $fileId) : self
    {
        $result = new self();
        $resultArray = internalDecodeUnique($fileId);
        $result->setType($resultArray['typeId']);
        if ($result->getType() === UNIQUE_WEB) {
            $result->setUrl($resultArray['url']);
        } elseif ($result->getType() === UNIQUE_PHOTO) {
            if (isset($resultArray['volume_id'])) {
                $result->setVolumeId($resultArray['volume_id']);
                $result->setLocalId($resultArray['local_id']);
            } elseif (isset($resultArray['id'])) {
                $result->setId($resultArray['id']);
                $result->setSubType($resultArray['subType']);
            } elseif (isset($resultArray['sticker_set_id'])) {
                $result->setStickerSetId($resultArray['sticker_set_id']);
                $result->setStickerSetVersion($resultArray['sticker_set_version']);
                $result->setSubType($resultArray['subType']);
            }
        } elseif (isset($resultArray['id'])) {
            $result->setId($resultArray['id']);
        }
        return $result;
    }
    /**
     * Convert full bot API file ID to unique file ID.
     *
     * @param string $fileId Full bot API file ID
     *
     * @return self
     */
    public static function fromBotAPI(string $fileId) : self
    {
        return FileId::fromBotAPI($fileId)->getUnique();
    }
    /**
     * Turn full file ID into unique file ID.
     *
     * @param FileId $fileId Full file ID
     *
     * @return self
     */
    public static function fromFileId(FileId $fileId) : self
    {
        $result = new self();
        $result->setType(FULL_UNIQUE_MAP[$fileId->getType()]);
        if ($result->hasUrl()) {
            $result->setType(UNIQUE_WEB);
        }
        if ($result->getType() === UNIQUE_WEB) {
            $result->setUrl($fileId->getUrl());
        } elseif ($result->getType() === UNIQUE_PHOTO) {
            if ($fileId->hasVolumeId()) {
                $result->setVolumeId($fileId->getVolumeId());
                $result->setLocalId($fileId->getLocalId());
            } elseif ($fileId->hasId()) {
                $result->setId($fileId->getId());
                $photoSize = $fileId->getPhotoSizeSource();
                if ($photoSize instanceof PhotoSizeSourceThumbnail) {
                    $type = $photoSize->getThumbType();
                    if ($type === 'a') {
                        $type = \chr(0);
                    } elseif ($type === 'c') {
                        $type = \chr(1);
                    } else {
                        $type = \chr(\ord($type) + 5);
                    }
                    $result->setSubType(\ord($type));
                } elseif ($photoSize instanceof PhotoSizeSourceDialogPhoto) {
                    $result->setSubType($photoSize->isSmallDialogPhoto() ? 0 : 1);
                } elseif ($photoSize instanceof PhotoSizeSourceStickersetThumbnailVersion) {
                    $result->setSubType(2);
                    $result->setStickerSetId($photoSize->getStickerSetId());
                    $result->setStickerSetVersion($photoSize->getStickerSetVersion());
                }
            }
        } elseif ($fileId->hasId()) {
            $result->setId($fileId->getId());
        }
        return $result;
    }
    /**
     * Get unique file type as string.
     *
     * @return string
     */
    public function getTypeName() : string
    {
        return UNIQUE_TYPES[$this->_type];
    }
    /**
     * Get unique file type.
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->_type;
    }
    /**
     * Set file type.
     *
     * @param int $_type File type.
     *
     * @return self
     */
    public function setType(int $_type) : self
    {
        $this->_type = $_type;
        return $this;
    }
    /**
     * Get file ID.
     *
     * @return int
     */
    public function getId()
    {
        return $this->_id;
    }
    /**
     * Set file ID.
     *
     * @param int $_id File ID.
     *
     * @return self
     */
    public function setId($_id) : self
    {
        $this->_id = $_id;
        return $this;
    }
    /**
     * Check if has ID.
     *
     * @return boolean
     */
    public function hasId() : bool
    {
        return isset($this->_id);
    }
    /**
     * Get photo volume ID.
     *
     * @return int
     */
    public function getVolumeId()
    {
        return $this->_volumeId;
    }
    /**
     * Set photo volume ID.
     *
     * @param int $_volumeId Photo volume ID.
     *
     * @return self
     */
    public function setVolumeId($_volumeId) : self
    {
        $this->_volumeId = $_volumeId;
        return $this;
    }
    /**
     * Check if has volume ID.
     *
     * @return boolean
     */
    public function hasVolumeId() : bool
    {
        return isset($this->_volumeId);
    }
    /**
     * Get photo local ID.
     *
     * @return int
     */
    public function getLocalId() : int
    {
        return $this->_localId;
    }
    /**
     * Set photo local ID.
     *
     * @param int $_localId Photo local ID.
     *
     * @return self
     */
    public function setLocalId(int $_localId) : self
    {
        $this->_localId = $_localId;
        return $this;
    }
    /**
     * Check if has local ID.
     *
     * @return boolean
     */
    public function hasLocalId() : bool
    {
        return isset($this->_localId);
    }
    /**
     * Get weblocation URL.
     *
     * @return string
     */
    public function getUrl() : string
    {
        return $this->_url;
    }
    /**
     * Set weblocation URL.
     *
     * @param string $_url Weblocation URL
     *
     * @return self
     */
    public function setUrl(string $_url) : self
    {
        $this->_url = $_url;
        return $this;
    }
    /**
     * Check if has weblocation URL.
     *
     * @return boolean
     */
    public function hasUrl() : bool
    {
        return isset($this->_url);
    }
    /**
     * Get photo subtype.
     *
     * @return int
     */
    public function getSubType() : int
    {
        return $this->_subType;
    }
    /**
     * Has photo subtype?
     *
     * @return bool
     */
    public function hasSubType() : bool
    {
        return isset($this->_subType);
    }
    /**
     * Set photo subtype.
     *
     * @param int $_subType Photo subtype
     *
     * @return self
     */
    public function setSubType(int $_subType) : self
    {
        $this->_subType = $_subType;
        return $this;
    }
    /**
     * Get sticker set ID.
     *
     * @return int
     */
    public function getStickerSetId()
    {
        return $this->_stickerSetId;
    }
    /**
     * Has sticker set ID?
     *
     * @return bool
     */
    public function hasStickerSetId() : bool
    {
        return isset($this->_stickerSetId);
    }
    /**
     * Set sticker set ID.
     *
     * @param int $_stickerSetId Sticker set ID
     *
     * @return self
     */
    public function setStickerSetId($_stickerSetId) : self
    {
        $this->_stickerSetId = $_stickerSetId;
        return $this;
    }
    /**
     * Get sticker set version.
     *
     * @return int
     */
    public function getStickerSetVersion() : int
    {
        return $this->_stickerSetVersion;
    }
    /**
     * Has sticker set version.
     *
     * @return bool
     */
    public function hasStickerSetVersion() : bool
    {
        return isset($this->_stickerSetVersion);
    }
    /**
     * Set sticker set version.
     *
     * @param int $_stickerSetVersion Sticker set version
     *
     * @return self
     */
    public function setStickerSetVersion(int $_stickerSetVersion) : self
    {
        $this->_stickerSetVersion = $_stickerSetVersion;
        return $this;
    }
}{
    "name": "danog/tg-file-decoder",
    "description": "Decode Telegram bot API file IDs",
    "type": "project",
    "license": "AGPL-3.0-only",
    "keywords": ["telegram", "mtproto", "bot API", "file ID", "video", "stickers", "audio", "files"],
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "require": {
        "php": ">=7.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^8|^6",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "danog\\Decoder\\": "src/"
        },
        "files": [
            "src/type.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "danog\\Decoder\\Test\\": "tests"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text  --configuration phpunit.xml.dist"
    }
}
{
    "name": "danog/libdns-json",
    "homepage": "https://github.com/danog/libdns-json",
    "description": "Encoder/decoder for google's JSON DNS message format based on libdns",
    "keywords": [
        "dns",
        "doh",
        "dns-over-https",
        "https",
        "json",
        "libdns",
        "message"
    ],
    "license": "MIT",
    "authors": [{
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        },
        {
            "name": "Chris Wright",
            "email": "addr@daverandom.com"
        }
    ],
    "require": {
        "php": ">=7.0",
        "daverandom/libdns": "^2.0.1",
        "ext-json": "*"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^6"
    },
    "autoload": {
        "psr-4": {
            "danog\\LibDNSJson\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "danog\\LibDNSJson\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}<?php

namespace danog\LibDNSJson;

use LibDNS\Decoder\DecodingContextFactory;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Packets\PacketFactory;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\Resource;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\Types;
/**
 * Decodes JSON DNS strings to Message objects.
 *
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 */
class JsonDecoder
{
    /**
     * @var \LibDNS\Packets\PacketFactory
     */
    private $packetFactory;
    /**
     * @var \LibDNS\Messages\MessageFactory
     */
    private $messageFactory;
    /**
     * @var \LibDNS\Records\QuestionFactory
     */
    private $questionFactory;
    /**
     * @var \LibDNS\Records\ResourceBuilder
     */
    private $resourceBuilder;
    /**
     * @var \LibDNS\Records\Types\TypeBuilder
     */
    private $typeBuilder;
    /**
     * @var \LibDNS\Decoder\DecodingContextFactory
     */
    private $decodingContextFactory;
    /**
     * Constructor.
     *
     * @param \LibDNS\Packets\PacketFactory $packetFactory
     * @param \LibDNS\Messages\MessageFactory $messageFactory
     * @param \LibDNS\Records\QuestionFactory $questionFactory
     * @param \LibDNS\Records\ResourceBuilder $resourceBuilder
     * @param \LibDNS\Records\Types\TypeBuilder $typeBuilder
     * @param \LibDNS\Decoder\DecodingContextFactory $decodingContextFactory
     * @param bool $allowTrailingData
     */
    public function __construct(PacketFactory $packetFactory, MessageFactory $messageFactory, QuestionFactory $questionFactory, ResourceBuilder $resourceBuilder, TypeBuilder $typeBuilder, DecodingContextFactory $decodingContextFactory)
    {
        $this->packetFactory = $packetFactory;
        $this->messageFactory = $messageFactory;
        $this->questionFactory = $questionFactory;
        $this->resourceBuilder = $resourceBuilder;
        $this->typeBuilder = $typeBuilder;
        $this->decodingContextFactory = $decodingContextFactory;
    }
    /**
     * Decode a question record.
     *
     *
     * @return \LibDNS\Records\Question
     * @throws \UnexpectedValueException When the record is invalid
     */
    private function decodeQuestionRecord(array $record) : Question
    {
        /** @var \LibDNS\Records\Types\DomainName $domainName */
        $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
        $labels = \explode('.', $record['name']);
        if (!empty($last = \array_pop($labels))) {
            $labels[] = $last;
        }
        $domainName->setLabels($labels);
        $question = $this->questionFactory->create($record['type']);
        $question->setName($domainName);
        //$question->setClass($meta['class']);
        return $question;
    }
    /**
     * Decode a resource record.
     *
     *
     * @return \LibDNS\Records\Resource
     * @throws \UnexpectedValueException When the record is invalid
     * @throws \InvalidArgumentException When a type subtype is unknown
     */
    private function decodeResourceRecord(array $record) : Resource
    {
        /** @var \LibDNS\Records\Types\DomainName $domainName */
        $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
        $labels = \explode('.', $record['name']);
        if (!empty($last = \array_pop($labels))) {
            $labels[] = $last;
        }
        $domainName->setLabels($labels);
        /* @var \LibDNS\Records\Resource $resource */
        $resource = $this->resourceBuilder->build($record['type']);
        $resource->setName($domainName);
        //$resource->setClass($meta['class']);
        $resource->setTTL($record['TTL']);
        $data = $resource->getData();
        $typeDef = $data->getTypeDefinition();
        $record['data'] = explode(' ', $record['data'], $typeDef->count());
        $fieldDef = $index = null;
        foreach ($data->getTypeDefinition() as $index => $fieldDef) {
            $field = $this->typeBuilder->build($fieldDef->getType());
            $this->decodeType($field, $record['data'][$index]);
            $data->setField($index, $field);
        }
        return $resource;
    }
    /**
     * Decode a Type field.
     *
     *
     * @param \LibDNS\Records\Types\Type $type The object to populate with the result
     * @throws \UnexpectedValueException When the packet data is invalid
     * @throws \InvalidArgumentException When the Type subtype is unknown
     */
    private function decodeType(Type $type, $data)
    {
        if ($type instanceof Anything) {
            $this->decodeAnything($type, $data);
        } elseif ($type instanceof BitMap) {
            $this->decodeBitMap($type, $data);
        } elseif ($type instanceof Char) {
            $this->decodeChar($type, $data);
        } elseif ($type instanceof CharacterString) {
            $this->decodeCharacterString($type, $data);
        } elseif ($type instanceof DomainName) {
            $this->decodeDomainName($type, $data);
        } elseif ($type instanceof IPv4Address) {
            $this->decodeIPv4Address($type, $data);
        } elseif ($type instanceof IPv6Address) {
            $this->decodeIPv6Address($type, $data);
        } elseif ($type instanceof Long) {
            $this->decodeLong($type, $data);
        } elseif ($type instanceof Short) {
            $this->decodeShort($type, $data);
        } else {
            throw new \InvalidArgumentException('Unknown Type ' . \get_class($type));
        }
    }
    /**
     * Decode an Anything field.
     *
     *
     * @param \LibDNS\Records\Types\Anything $anything The object to populate with the result
     * @param int $length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeAnything(Anything $anything, $data)
    {
        $anything->setValue(\hex2bin($data));
    }
    /**
     * Decode a BitMap field.
     *
     *
     * @param \LibDNS\Records\Types\BitMap $bitMap The object to populate with the result
     * @param int $length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeBitMap(BitMap $bitMap, $data)
    {
        $bitMap->setValue(\hex2bin($data));
    }
    /**
     * Decode a Char field.
     *
     *
     * @param \LibDNS\Records\Types\Char $char The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeChar(Char $char, $result)
    {
        $value = \unpack('C', $result)[1];
        $char->setValue($value);
    }
    /**
     * Decode a CharacterString field.
     *
     *
     * @param \LibDNS\Records\Types\CharacterString $characterString The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeCharacterString(CharacterString $characterString, $result)
    {
        $characterString->setValue($result);
    }
    /**
     * Decode a DomainName field.
     *
     *
     * @param \LibDNS\Records\Types\DomainName $domainName The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeDomainName(DomainName $domainName, $result)
    {
        $labels = \explode('.', $result);
        if (!empty($last = \array_pop($labels))) {
            $labels[] = $last;
        }
        $domainName->setLabels($labels);
    }
    /**
     * Decode an IPv4Address field.
     *
     *
     * @param \LibDNS\Records\Types\IPv4Address $ipv4Address The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeIPv4Address(IPv4Address $ipv4Address, $result)
    {
        $octets = \unpack('C4', \inet_pton($result));
        $ipv4Address->setOctets($octets);
    }
    /**
     * Decode an IPv6Address field.
     *
     *
     * @param \LibDNS\Records\Types\IPv6Address $ipv6Address The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeIPv6Address(IPv6Address $ipv6Address, $result)
    {
        $shorts = \unpack('n8', \inet_pton($result));
        $ipv6Address->setShorts($shorts);
    }
    /**
     * Decode a Long field.
     *
     *
     * @param \LibDNS\Records\Types\Long $long The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeLong(Long $long, $result)
    {
        $long->setValue((int) $result);
    }
    /**
     * Decode a Short field.
     *
     *
     * @param \LibDNS\Records\Types\Short $short The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeShort(Short $short, $result)
    {
        $short->setValue((int) $result);
    }
    /**
     * Decode a Message from JSON-encoded string.
     *
     * @param string $data The data string to decode
     * @param int $requestId The message ID to set
     * @return \LibDNS\Messages\Message
     * @throws \UnexpectedValueException When the packet data is invalid
     * @throws \InvalidArgumentException When a type subtype is unknown
     */
    public function decode(string $result, int $requestId) : Message
    {
        $result = \json_decode($result, true);
        if ($result === false) {
            $error = \json_last_error_msg();
            throw new \InvalidArgumentException("Could not decode JSON DNS payload ({$error})");
        }
        if (!isset($result['Status'], $result['TC'], $result['RD'], $result['RA'])) {
            throw new \InvalidArgumentException('Wrong reply from server, missing required fields');
        }
        $message = $this->messageFactory->create();
        $decodingContext = $this->decodingContextFactory->create($this->packetFactory->create());
        //$message->isAuthoritative(true);
        $message->setType(MessageTypes::RESPONSE);
        $message->setID($requestId);
        $message->setResponseCode($result['Status']);
        $message->isTruncated($result['TC']);
        $message->isRecursionDesired($result['RD']);
        $message->isRecursionAvailable($result['RA']);
        $decodingContext->setExpectedQuestionRecords(isset($result['Question']) ? \count($result['Question']) : 0);
        $decodingContext->setExpectedAnswerRecords(isset($result['Answer']) ? \count($result['Answer']) : 0);
        $decodingContext->setExpectedAuthorityRecords(0);
        $decodingContext->setExpectedAdditionalRecords(isset($result['Additional']) ? \count($result['Additional']) : 0);
        $questionRecords = $message->getQuestionRecords();
        $expected = $decodingContext->getExpectedQuestionRecords();
        for ($i = 0; $i < $expected; $i++) {
            $questionRecords->add($this->decodeQuestionRecord($result['Question'][$i]));
        }
        $answerRecords = $message->getAnswerRecords();
        $expected = $decodingContext->getExpectedAnswerRecords();
        for ($i = 0; $i < $expected; $i++) {
            $answerRecords->add($this->decodeResourceRecord($result['Answer'][$i]));
        }
        $authorityRecords = $message->getAuthorityRecords();
        $expected = $decodingContext->getExpectedAuthorityRecords();
        for ($i = 0; $i < $expected; $i++) {
            $authorityRecords->add($this->decodeResourceRecord($result['Authority'][$i]));
        }
        $additionalRecords = $message->getAdditionalRecords();
        $expected = $decodingContext->getExpectedAdditionalRecords();
        for ($i = 0; $i < $expected; $i++) {
            $additionalRecords->add($this->decodeResourceRecord($result['Additional'][$i]));
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/**
 * Encodes Message objects to query strings.
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace danog\LibDNSJson;

use LibDNS\Messages\Message;
use LibDNS\Messages\MessageTypes;
/**
 * Encodes Message objects to query strings.
 *
 * @category LibDNS
 * @package Encoder
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 */
class QueryEncoder
{
    /**
     * Encode a Message to URL payload.
     *
     * @param \LibDNS\Messages\Message $message The Message to encode
     * @return string
     */
    public function encode(Message $message) : string
    {
        if ($message->getType() !== MessageTypes::QUERY) {
            throw new \InvalidArgumentException('Invalid question: is not a question record');
        }
        $questions = $message->getQuestionRecords();
        if ($questions->count() === 0) {
            throw new \InvalidArgumentException('Invalid question: 0 question records provided');
        }
        $question = $questions->getRecordByIndex(0);
        return \http_build_query([
            'cd' => 0,
            // Do not disable result validation
            'do' => 0,
            // Do not send me DNSSEC data
            'type' => $question->getType(),
            // Record type being requested
            'name' => \implode('.', $question->getName()->getLabels()),
            // Record name being requested
            'ct' => 'application/dns-json',
        ]);
    }
}<?php

declare (strict_types=1);
/**
 * Creates QueryEncoder objects.
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace danog\LibDNSJson;

/**
 * Creates QueryEncoder objects.
 *
 * @category LibDNS
 * @package Encoder
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 */
class QueryEncoderFactory
{
    /**
     * Create a new Encoder object.
     *
     * @return \LibDNS\Encoder\Encoder
     */
    public function create() : QueryEncoder
    {
        return new QueryEncoder();
    }
}<?php

/**
 * Creates JsonDecoder objects.
 *
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>,
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 */
namespace danog\LibDNSJson;

use LibDNS\Messages\MessageFactory;
use LibDNS\Packets\PacketFactory;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\RDataBuilder;
use LibDNS\Records\RDataFactory;
use LibDNS\Records\RecordCollectionFactory;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\ResourceFactory;
use LibDNS\Records\TypeDefinitions\FieldDefinitionFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionManager;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\TypeFactory;
use LibDNS\Decoder\DecodingContextFactory;
/**
 * Creates JsonDecoder objects.
 *
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 */
class JsonDecoderFactory
{
    /**
     * Create a new JsonDecoder object.
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager
     * @return JsonDecoder
     */
    public function create(TypeDefinitionManager $typeDefinitionManager = null) : JsonDecoder
    {
        $typeBuilder = new TypeBuilder(new TypeFactory());
        return new JsonDecoder(new PacketFactory(), new MessageFactory(new RecordCollectionFactory()), new QuestionFactory(), new ResourceBuilder(new ResourceFactory(), new RDataBuilder(new RDataFactory(), $typeBuilder), $typeDefinitionManager ?: new TypeDefinitionManager(new TypeDefinitionFactory(), new FieldDefinitionFactory())), $typeBuilder, new DecodingContextFactory());
    }
}<?php

namespace danog\LibDNSJson\Test;

use danog\LibDNSJson\JsonDecoder;
use danog\LibDNSJson\JsonDecoderFactory;
use PHPUnit\Framework\TestCase;
class JsonDecoderFactoryTest extends TestCase
{
    /**
     *
     */
    public function testJsonDecoderFactoryWorks()
    {
        $this->assertInstanceOf(JsonDecoder::class, (new JsonDecoderFactory())->create());
    }
}<?php

namespace danog\LibDNSJson\Test;

use danog\LibDNSJson\JsonDecoderFactory;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageTypes;
use PHPUnit\Framework\TestCase;
class JsonDecoderTest extends TestCase
{
    /**
     * Test decoding of valid JSON DNS payloads.
     *
     * @param string $message
     * @param int $requestId
     * @return void
     *
     * @dataProvider provideValidJsonPayloads
     */
    public function testDecodesValidJsonPayloads(string $message, int $requestId)
    {
        $decoder = (new JsonDecoderFactory())->create();
        $response = $decoder->decode($message, $requestId);
        $this->assertInstanceOf(Message::class, $response);
        $this->assertEquals(MessageTypes::RESPONSE, $response->getType());
    }
    /**
     *
     */
    public function provideValidJsonPayloads()
    {
        return [['{
                    "Status": 0,
                    "TC": false,
                    "RD": true,
                    "RA": true,
                    "AD": false,
                    "CD": false,
                    "Question":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1
                    }
                    ],
                    "Answer":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.178.96.59"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.172.224.47"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.142.160.59"
                    }
                    ],
                    "Additional": [ ],
                    "edns_client_subnet": "12.34.56.78/0"
                }', 2], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"Status": 0,"TC": false,"RD": true,"RA": true,"AD": false,"CD": false,"Question":[ {"name": "daniil.it.","type": 6}],"Answer":[ {"name": "daniil.it.","type": 6,"TTL": 3493,"data": "cruz.ns.cloudflare.com. dns.cloudflare.com. 2031387933 10000 2400 604800 3600"}]}', 3]];
    }
    /**
     * Test decoding of invalid JSON DNS payloads.
     *
     * @param string $message
     * @param int $requestId
     * @return void
     *
     * @dataProvider provideInvalidJsonPayloads
     */
    public function testDecodesInvalidJsonPayloads($message, $requestId)
    {
        $decoder = (new JsonDecoderFactory())->create();
        $this->expectException(\InvalidArgumentException::class);
        $decoder->decode($message, $requestId);
    }
    /**
     *
     */
    public function provideInvalidJsonPayloads()
    {
        return [['{lmfao
                    "Status": 0,
                    "TC": false,
                    "RD": true,
                    "RA": true,
                    "AD": false,
                    "CD": false,
                    "Question":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1
                    }
                    ],
                    "Answer":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.178.96.59"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.172.224.47"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.142.160.59"
                    }
                    ],
                    "Additional": [ ],
                    "edns_client_subnet": "12.34.56.78/0"
                }', 2], ['xd{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', 3], ['whaaa{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', 3], ['xdxdxxxxx{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"Status": 0,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"Status": 0,"TC": false,"RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['xd', 0]];
    }
}<?php

namespace danog\LibDNSJson\Test;

use danog\LibDNSJson\QueryEncoder;
use danog\LibDNSJson\QueryEncoderFactory;
use PHPUnit\Framework\TestCase;
class QueryEncoderFactoryTest extends TestCase
{
    /**
     *
     */
    public function testQueryEncoderFactoryWorks()
    {
        $this->assertInstanceOf(QueryEncoder::class, (new QueryEncoderFactory())->create());
    }
}<?php

namespace danog\LibDNSJson\Test;

use danog\LibDNSJson\JsonDecoderFactory;
use danog\LibDNSJson\QueryEncoderFactory;
use LibDNS\Messages\MessageTypes;
use PHPUnit\Framework\TestCase;
class QueryEncoderTest extends TestCase
{
    /**
     * Test encoding of valid DNS message payloads.
     *
     * @param string $message
     * @return void
     *
     * @dataProvider provideValidQueryPayloads
     */
    public function testEncodesValidQueryPayloads(string $message)
    {
        $decoder = (new JsonDecoderFactory())->create();
        $response = $decoder->decode($message, 0);
        $response->setType(MessageTypes::QUERY);
        $encoder = (new QueryEncoderFactory())->create();
        $request = $encoder->encode($response);
        $this->assertInternalType('string', $request, "Got a " . \gettype($request) . " instead of a string");
        \parse_str($request, $output);
        $this->assertNotEmpty($output);
        $this->assertArrayHasKey('cd', $output);
        $this->assertArrayHasKey('do', $output);
        $this->assertArrayHasKey('ct', $output);
        $this->assertArrayHasKey('type', $output);
        $this->assertArrayHasKey('name', $output);
        $this->assertEquals($output['cd'], 0);
        $this->assertEquals($output['do'], 0);
        $this->assertEquals($output['ct'], 'application/dns-json');
        $this->assertEquals($output['type'], $response->getQuestionRecords()->getRecordByIndex(0)->getType());
        $this->assertEquals($output['name'], \implode('.', $response->getQuestionRecords()->getRecordByIndex(0)->getName()->getLabels()));
    }
    /**
     *
     */
    public function provideValidQueryPayloads()
    {
        return [['{
                    "Status": 0,
                    "TC": false,
                    "RD": true,
                    "RA": true,
                    "AD": false,
                    "CD": false,
                    "Question":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1
                    }
                    ],
                    "Answer":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.178.96.59"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.172.224.47"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.142.160.59"
                    }
                    ],
                    "Additional": [ ],
                    "edns_client_subnet": "12.34.56.78/0"
                }', 2], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3]];
    }
    /**
     * Test query encoding of invalid DNS payloads.
     *
     * @param $request
     * @return void
     *
     * @dataProvider provideInvalidQueryPayloads
     */
    public function testEncodesInvalidQueryPayloads($request)
    {
        $encoder = (new QueryEncoderFactory())->create();
        $this->expectException(\InvalidArgumentException::class);
        $encoder->encode($request);
    }
    /**
     *
     */
    public function provideInvalidQueryPayloads()
    {
        $decoder = (new JsonDecoderFactory())->create();
        return [[$decoder->decode('{
                        "Status": 0,
                        "TC": false,
                        "RD": true,
                        "RA": true,
                        "AD": false,
                        "CD": false,
                        "Question":
                        [
                        {
                            "name": "apple.com.",
                            "type": 1
                        }
                        ],
                        "Answer":
                        [
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.178.96.59"
                        },
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.172.224.47"
                        },
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.142.160.59"
                        }
                        ],
                        "Additional": [ ],
                        "edns_client_subnet": "12.34.56.78/0"
                    }', 2)], [$decoder->decode('{
                        "Status": 0,
                        "TC": false,
                        "RD": true,
                        "RA": true,
                        "AD": false,
                        "CD": false,
                        "Question":
                        [
                        ],
                        "Answer":
                        [
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.178.96.59"
                        },
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.172.224.47"
                        },
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.142.160.59"
                        }
                        ],
                        "Additional": [ ],
                        "edns_client_subnet": "12.34.56.78/0"
                    }', 2)]];
    }
}{
    "name": "danog/primemodule",
    "description": "Prime module capable of doing prime factorization of huge numbers very quickly.\"",
    "type": "library",
    "license": "AGPL-3.0-only",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "require": {
        "php": ">=7.0"
    },
    "suggest": {
        "ext-primemodule": "Install the native C++ extension for extremely fast factorization (https://github.com/danog/PrimeModule-ext)"
    },
    "autoload": {
        "psr-0": {
            "danog\\": "lib/"
        }
    }
}
# NOTICE!!! This is copied from https://stackoverflow.com/questions/4643647/fast-prime-factorization-module
import sys
import random

def primesbelow(N):
    # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    #""" Input N>=6, Returns a list of primes, 2 <= p < N """
    correction = N % 6 > 1
    N = {0:N, 1:N-1, 2:N+4, 3:N+3, 4:N+2, 5:N+1}[N%6]
    sieve = [True] * (N // 3)
    sieve[0] = False
    for i in range(int(N ** .5) // 3 + 1):
        if sieve[i]:
            k = (3 * i + 1) | 1
            sieve[k*k // 3::2*k] = [False] * ((N//6 - (k*k)//6 - 1)//k + 1)
            sieve[(k*k + 4*k - 2*k*(i%2)) // 3::2*k] = [False] * ((N // 6 - (k*k + 4*k - 2*k*(i%2))//6 - 1) // k + 1)
    return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]]

smallprimeset = set(primesbelow(100000))
_smallprimeset = 100000

def isprime(n, precision=7):
    # http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
    if n == 1 or n % 2 == 0:
        return False
    elif n < 1:
        raise ValueError("Out of bounds, first argument must be > 0")
    elif n < _smallprimeset:
        return n in smallprimeset


    d = n - 1
    s = 0
    while d % 2 == 0:
        d //= 2
        s += 1

    for repeat in range(precision):
        a = random.randrange(2, n - 2)
        x = pow(a, d, n)

        if x == 1 or x == n - 1: continue

        for r in range(s - 1):
            x = pow(x, 2, n)
            if x == 1: return False
            if x == n - 1: break
        else: return False

    return True

# https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
def pollard_brent(n):
    if n % 2 == 0: return 2
    if n % 3 == 0: return 3

    y, c, m = random.randint(1, n-1), random.randint(1, n-1), random.randint(1, n-1)

    g, r, q = 1, 1, 1
    while g == 1:
        x = y
        for i in range(r):
            y = (pow(y, 2, n) + c) % n

        k = 0
        while k < r and g==1:
            ys = y
            for i in range(min(m, r-k)):
                y = (pow(y, 2, n) + c) % n
                q = q * abs(x-y) % n

            g = gcd(q, n)
            k += m
        r *= 2
    if g == n:
        while True:
            ys = (pow(ys, 2, n) + c) % n
            g = gcd(abs(x - ys), n)
            if g > 1:
                break

    return g

smallprimes = primesbelow(10000) # might seem low, but 1000*1000 = 1000000, so this will fully factor every composite < 1000000
def primefactors(n, sort=False):
    factors = []

    limit = int(n ** .5) + 1
    for checker in smallprimes:
        if checker > limit: break
        while n % checker == 0:
            factors.append(checker)
            n //= checker
            limit = int(n ** .5) + 1
            if checker > limit: break

    if n < 2: return factors

    while n > 1:
        if isprime(n):
            factors.append(n)
            break
        factor = pollard_brent(n) # trial division did not fully factor, switch to pollard-brent
        factors.extend(primefactors(factor)) # recurse to factor the not necessarily prime factor returned by pollard-brent
        n //= factor

    if sort: factors.sort()

    return factors

def factorization(n):
    factors = {}
    for p1 in primefactors(n):
        try:
            factors[p1] += 1
        except KeyError:
            factors[p1] = 1
    return factors

totients = {}
def totient(n):
    if n == 0: return 1

    try: return totients[n]
    except KeyError: pass

    tot = 1
    for p, exp in factorization(n).items():
        tot *= (p - 1)  *  p ** (exp - 1)

    totients[n] = tot
    return tot

def gcd(a, b):
    if a == b: return a
    while b > 0: a, b = b, a % b
    return a

def lcm(a, b):
    return abs(a * b) // gcd(a, b)

print(primefactors(int(sys.argv[1]))[0])<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with the MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog;

use FFI;
class PrimeModule
{
    /**
     *
     */
    public static function native_single($what)
    {
        if (!is_int($what)) {
            return false;
        }
        foreach ([2, 3, 5, 7, 11, 13, 17, 19, 23] as $s) {
            if ($what % $s === 0) {
                return $s;
            }
        }
        $g = 0;
        $it = 0;
        for ($i = 0; $i < 3 || $it < 1000; $i++) {
            $t = ((rand(0, 127) & 15) + 17) % $what;
            $x = rand(0, 1 << 31) % ($what - 1) + 1;
            $y = $x;
            $lim = 1 << $i + 18;
            for ($j = 1; $j <= $lim; $j++) {
                $it++;
                $a = $x;
                $b = $x;
                $c = $t;
                while ($b) {
                    if ($b & 1) {
                        $c += $a;
                        if ($c >= $what) {
                            $c -= $what;
                        }
                    }
                    $a += $a;
                    if ($a >= $what) {
                        $a -= $what;
                    }
                    $b >>= 1;
                }
                $x = $c;
                $z = $x < $y ? $what + $x - $y : $x - $y;
                $g = self::gcd($z, $what);
                if ($g != 1) {
                    break;
                }
                if (!($j & $j - 1)) {
                    $y = $x;
                }
            }
            if ($g > 1 && $g < $what) {
                break;
            }
        }
        if ($g > 1 && $g < $what) {
            return $g;
        }
        return $what;
    }
    /**
     *
     */
    public static function native($what)
    {
        $res = [self::native_single($what)];
        while (array_product($res) !== $what) {
            $res[] = self::native_single($what / array_product($res));
        }
        return $res;
    }
    /**
     *
     */
    public static function python_single($what)
    {
        if (function_exists('shell_exec')) {
            $res = trim(shell_exec('timeout 10 python2 ' . __DIR__ . '/prime.py ' . $what . ' 2>&1'));
            if ($res == '' || is_null($res) || !is_numeric($res)) {
                copy(__DIR__ . '/prime.py', getcwd() . '/.prime.py');
                $res = trim(shell_exec('timeout 10 python2 ' . getcwd() . '/.prime.py ' . $what . ' 2>&1'));
                unlink(getcwd() . '/.prime.py');
                if ($res == '' || is_null($res) || !is_numeric($res)) {
                    return false;
                }
            }
            $newval = intval($res);
            if (is_int($newval)) {
                $res = $newval;
            }
            if ($res === 0) {
                return false;
            }
            return $res;
        }
        return false;
    }
    /**
     *
     */
    public static function python($what)
    {
        $res = [self::python_single($what)];
        if ($res[0] === false) {
            return false;
        }
        while (array_product($res) !== $what) {
            $res[] = self::python_single($what / array_product($res));
        }
        return $res;
    }
    /**
     *
     */
    public static function python_single_alt($what)
    {
        if (function_exists('shell_exec')) {
            $res = trim(shell_exec('python ' . __DIR__ . '/alt_prime.py ' . $what . ' 2>&1'));
            if ($res == '' || is_null($res) || !is_numeric($res)) {
                copy(__DIR__ . '/alt_prime.py', getcwd() . '/.alt_prime.py');
                $res = trim(shell_exec('python ' . getcwd() . '/.alt_prime.py ' . $what . ' 2>&1'));
                unlink(getcwd() . '/.alt_prime.py');
                if ($res == '' || is_null($res) || !is_numeric($res)) {
                    return false;
                }
            }
            $newval = intval($res);
            if (is_int($newval)) {
                $res = $newval;
            }
            if ($res === 0) {
                return false;
            }
            return $res;
        }
        return false;
    }
    /**
     *
     */
    public static function python_alt($what)
    {
        $res = [self::python_single_alt($what)];
        if ($res[0] === false) {
            return false;
        }
        while (array_product($res) !== $what) {
            $res[] = self::python_single_alt($what / array_product($res));
        }
        return $res;
    }
    /**
     *
     */
    public static function wolfram_single($what)
    {
        $query = 'Do prime factorization of ' . $what;
        $params = ['async' => true, 'banners' => 'raw', 'debuggingdata' => false, 'format' => 'moutput', 'formattimeout' => 8, 'input' => $query, 'output' => 'JSON', 'proxycode' => json_decode(file_get_contents('http://www.wolframalpha.com/api/v1/code'), true)['code']];
        $url = 'https://www.wolframalpha.com/input/json.jsp?' . http_build_query($params);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Referer: https://www.wolframalpha.com/input/?i=' . urlencode($query)]);
        curl_setopt($ch, CURLOPT_URL, $url);
        $res = json_decode(curl_exec($ch), true);
        curl_close($ch);
        $fres = false;
        if (!isset($res['queryresult']['pods'])) {
            return false;
        }
        foreach ($res['queryresult']['pods'] as $cur) {
            if ($cur['id'] === 'Divisors') {
                $fres = explode(', ', preg_replace(["/{\\d+, /", "/, \\d+}\$/"], '', $cur['subpods'][0]['moutput']));
                break;
            }
        }
        if (is_array($fres)) {
            $fres = $fres[0];
            $newval = intval($fres);
            if (is_int($newval)) {
                $fres = $newval;
            }
            return $fres;
        }
        return false;
    }
    /**
     *
     */
    public static function wolfram($what)
    {
        $res = [self::wolfram_single($what)];
        while (array_product($res) !== $what) {
            $res[] = self::wolfram_single($what / array_product($res));
        }
        return $res;
    }
    /**
     *
     */
    public static function native_single_cpp($what)
    {
        if (!extension_loaded('primemodule')) {
            if (class_exists(FFI::class)) {
                try {
                    $ffi = FFI::load("/usr/include/primemodule-ffi.h");
                    $result = $ffi->factorizeFFI((string) $what);
                    if ($result > 0) {
                        return $result;
                    }
                } catch (\Throwable $e) {
                }
                return false;
            }
            return false;
        }
        try {
            return factorize($what);
        } catch (\Exception $e) {
            return false;
        }
    }
    /**
     *
     */
    public static function native_cpp($what)
    {
        $res = [self::native_single_cpp($what)];
        if ($res[0] == false) {
            return false;
        }
        while (($product = array_product($res)) !== $what) {
            if ($product == 0) {
                return false;
            }
            $res[] = self::native_single_cpp($what / $product);
        }
        return $res;
    }
    /**
     *
     */
    public static function auto_single($what)
    {
        $res = self::native_single_cpp($what);
        if ($res !== false) {
            return $res;
        }
        $res = self::python_single_alt($what);
        if ($res !== false) {
            return $res;
        }
        $res = self::python_single($what);
        if ($res !== false) {
            return $res;
        }
        $res = self::native_single((int) $what);
        if ($res !== false) {
            return $res;
        }
        $res = self::wolfram_single($what);
        if ($res !== false) {
            return $res;
        }
        return false;
    }
    /**
     *
     */
    public static function auto($what)
    {
        $res = self::native_cpp($what);
        if (is_array($res)) {
            return $res;
        }
        $res = self::python_alt($what);
        if (is_array($res)) {
            return $res;
        }
        $res = self::python($what);
        if (is_array($res)) {
            return $res;
        }
        $res = self::native((int) $what);
        if (is_array($res)) {
            return $res;
        }
        $res = self::wolfram($what);
        if (is_array($res)) {
            return $res;
        }
        return false;
    }
    /**
     *
     */
    private static function gcd($a, $b)
    {
        if ($a == $b) {
            return $a;
        }
        while ($b > 0) {
            list($a, $b) = [$b, self::posmod($a, $b)];
        }
        return $a;
    }
    /**
     *
     */
    private static function posmod($a, $b)
    {
        $resto = $a % $b;
        if ($resto < 0) {
            $resto += abs($b);
        }
        return $resto;
    }
    /**
     *
     */
    private function primesbelow($N)
    {
        $correction = $N % 6 > 1 ? true : false;
        $N_Array = [$N, $N - 1, $N + 4, $N + 3, $N + 2, $N + 1];
        $N = $N_Array[$N % 6];
        $sieve = [];
        for ($i = 0; $i < (int) $N / 3; $i++) {
            $sieve[$i] = true;
        }
        $sieve[0] = false;
        for ($i = 0; $i < (int) ((int) pow($N, 0.5) / 3) + 1; $i++) {
            if ($sieve[$i]) {
                $k = 3 * $i + 1 | 1;
                $startIndex1 = (int) ($k * $k / 3);
                $period = 2 * $k;
                for ($j = $startIndex1; $j < count($sieve); $j = $j + $period) {
                    $sieve[$j] = false;
                }
                $startIndex2 = (int) (($k * $k + 4 * $k - 2 * $k * ($i % 2)) / 3);
                $period = 2 * $k;
                for ($k = $startIndex2; $k < count($sieve); $k = $k + $period) {
                    $sieve[$k] = false;
                }
            }
        }
        $resultArray = [2, 3];
        $t = 1;
        for ($i = 1; $i < (int) ($N / 3) - $correction; $i++) {
            if ($sieve[$i]) {
                $resultArray[$t + 1] = 3 * $i + 1 | 1;
                $t++;
            }
        }
        return $resultArray;
    }
    /**
     *
     */
    private function isprime($n, $precision = 7)
    {
        $smallprimeset = $this->primesbelow(100000);
        $_smallprimeset = 100000;
        if ($n == 1 || $n % 2 == 0) {
            return false;
        } elseif ($n < 1) {
            throw new Exception('Out of bounds, first argument must be > 0');
        } elseif ($n < $_smallprimeset) {
            return in_array($n, $smallprimeset);
        }
        $d = $n - 1;
        $s = 0;
        while ($d % 2 == 0) {
            $d = (int) ($d / 2);
            $s += 1;
        }
        for ($i = 0; $i < $precision; $i++) {
            // random.randrange(2, n - 2) means:
            // $a = mt_rand(2, $n - 3);
            // maybe $n would be bigger that PHP_MAX_INT
            $a = mt_rand(2, 1084);
            $x = bcpowmod($a, $d, $n);
            if ($x == 1 || $x == $n - 1) {
                continue;
            }
            $flagfound = 0;
            for ($j = 0; $j < $s - 1; $j++) {
                $x = bcpowmod($x, 2, $n);
                if ($x == 1) {
                    return false;
                }
                if ($x == $n - 1) {
                    $flagfound = 1;
                    break;
                }
            }
            if ($flagfound == 0) {
                return false;
            }
        }
        return true;
    }
    /**
     *
     */
    private function pollard_brent($n)
    {
        $n = (int) $n;
        if ($n % 2 == 0) {
            return 2;
        }
        if (bcmod($n, 2) == 0) {
            return 2;
        }
        if (bcmod($n, 3) == 0) {
            return 3;
        }
        // $y = mt_rand(1, $n-1);
        // $c = mt_rand(1, $n-1);
        // $m = mt_rand(1, $n-1);
        // Again, $n may be bigger than PHP_MAX_INT
        // also, small numbers has a big affect in a good performance
        $y = 2;
        $c = 3;
        $m = 4;
        $g = 1;
        $r = 1;
        $q = 1;
        while ($g == 1) {
            $x = $y;
            for ($i = 0; $i < $r; $i++) {
                // $y = gmp_mod( (bcpowmod($y, 2, $n) + $c) , $n);
                $y = bcmod(bcpowmod($y, 2, $n) + $c, $n);
            }
            $k = 0;
            while ($k < $r && $g == 1) {
                $ys = $y;
                for ($j = 0; $j < min($m, $r - $k); $j++) {
                    // $y = gmp_mod( (bcpowmod($y, 2, $n) + $c), $n );
                    $y = bcmod(bcpowmod($y, 2, $n) + $c, $n);
                    // $q = gmp_mod($q * abs($x-$y), $n);
                    $mul = bcmul($q, abs($x - $y));
                    $q = bcmod($mul, $n);
                }
                $g = $this->gcd2($q, $n);
                $k += $m;
            }
            $r *= 2;
        }
        if ($g == $n) {
            while (true) {
                // $ys = ( bcpowmod($ys, 2, $n) + $c ) % $n;
                $ys = bcmod(bcpowmod($ys, 2, $n) + $c, $n);
                $g = $this->gcd2(abs($x - $ys), $n);
                if ($g > 1) {
                    break;
                }
            }
        }
        return $g;
    }
    /**
     *
     */
    public function primefactors($n, $sort = false)
    {
        $smallprimes = $this->primesbelow(10000);
        $factors = [];
        $limit = bcadd(bcsqrt($n), 1);
        foreach ($smallprimes as $checker) {
            if ($checker > $limit) {
                break;
            }
            // while (gmp_mod($n, $checker) == 0) {
            while (bcmod($n, $checker) == 0) {
                array_push($factors, $checker);
                $n = bcdiv($n, $checker);
                $limit = bcadd(bcsqrt($n), 1);
                if ($checker > $limit) {
                    break;
                }
            }
        }
        if ($n < 2) {
            return $factors;
        }
        while ($n > 1) {
            if ($this->isprime($n)) {
                array_push($factors, $n);
                break;
            }
            $factor = $this->pollard_brent($n);
            $factors = array_merge($factors, $this->primefactors($factor));
            $n = (int) ($n / $factor);
        }
        if ($sort) {
            sort($factors);
        }
        return $factors;
    }
    /**
     *
     */
    private function gcd2($a, $b)
    {
        if ($a == $b) {
            return $a;
        }
        while ($b > 0) {
            $a2 = $a;
            $a = $b;
            $b = bcmod($a2, $b);
        }
        return $a;
    }
}import sys
from math import log

# Multiple Polynomial Quadratic Sieve
def mpqs(n, verbose=False):
  if verbose:
    time1 = clock()

  root_n = isqrt(n)
  root_2n = isqrt(n+n)

  # formula chosen by experimentation
  # seems to be close to optimal for n < 10^50
  bound = int(5 * log(n, 10)**2)

  prime = []
  mod_root = []
  log_p = []
  num_prime = 0

  # find a number of small primes for which n is a quadratic residue
  p = 2
  while p < bound or num_prime < 3:

    # legendre (n|p) is only defined for odd p
    if p > 2:
      leg = legendre(n, p)
    else:
      leg = n & 1
    if leg == 1:
      prime += [p]
      mod_root += [int(mod_sqrt(n, p))]
      log_p += [log(p, 10)]
      num_prime += 1
    elif leg == 0:
      return p

    p = next_prime(p)

  # size of the sieve
  x_max = len(prime)*60

  # maximum value on the sieved range
  m_val = (x_max * root_2n) >> 1

  # fudging the threshold down a bit makes it easier to find powers of primes as factors
  # as well as partial-partial relationships, but it also makes the smoothness check slower.
  # there's a happy medium somewhere, depending on how efficient the smoothness check is
  thresh = log(m_val, 10) * 0.735

  # skip small primes. they contribute very little to the log sum
  # and add a lot of unnecessary entries to the table
  # instead, fudge the threshold down a bit, assuming ~1/4 of them pass
  min_prime = int(thresh*3)
  fudge = sum(log_p[i] for i,p in enumerate(prime) if p < min_prime)/4
  thresh -= fudge

  smooth = []
  used_prime = set()
  partial = {}
  num_smooth = 0
  num_used_prime = 0
  num_partial = 0
  num_poly = 0
  root_A = isqrt(root_2n / x_max)

  while True:
    # find an integer value A such that:
    # A is =~ sqrt(2*n) / x_max
    # A is a perfect square
    # sqrt(A) is prime, and n is a quadratic residue mod sqrt(A)
    while True:
      root_A = next_prime(root_A)
      leg = legendre(n, root_A)
      if leg == 1:
        break
      elif leg == 0:
        return root_A

    A = root_A * root_A

    # solve for an adequate B
    # B*B is a quadratic residue mod n, such that B*B-A*C = n
    # this is unsolvable if n is not a quadratic residue mod sqrt(A)
    b = mod_sqrt(n, root_A)
    B = (b + (n - b*b) * mod_inv(b + b, root_A))%A

    # B*B-A*C = n <=> C = (B*B-n)/A
    C = (B*B - n) / A

    num_poly += 1

    # sieve for prime factors
    sums = [0.0]*(2*x_max)
    i = 0
    for p in prime:
      if p < min_prime:
        i += 1
        continue
      logp = log_p[i]

      inv_A = mod_inv(A, p)
      # modular root of the quadratic
      a = int(((mod_root[i] - B) * inv_A)%p)
      b = int(((p - mod_root[i] - B) * inv_A)%p)

      k = 0
      while k < x_max:
        if k+a < x_max:
          sums[k+a] += logp
        if k+b < x_max:
          sums[k+b] += logp
        if k:
          sums[k-a+x_max] += logp
          sums[k-b+x_max] += logp

        k += p
      i += 1

    # check for smooths
    i = 0
    for v in sums:
      if v > thresh:
        x = x_max-i if i > x_max else i
        vec = set()
        sqr = []
        # because B*B-n = A*C
        # (A*x+B)^2 - n = A*A*x*x+2*A*B*x + B*B - n
        #               = A*(A*x*x+2*B*x+C)
        # gives the congruency
        # (A*x+B)^2 = A*(A*x*x+2*B*x+C) (mod n)
        # because A is chosen to be square, it doesn't need to be sieved
        val = sieve_val = A*x*x + 2*B*x + C

        if sieve_val < 0:
          vec = set([-1])
          sieve_val = -sieve_val

        for p in prime:
          while sieve_val%p == 0:
            if p in vec:
              # keep track of perfect square factors
              # to avoid taking the sqrt of a gigantic number at the end
              sqr += [p]
            vec ^= set([p])
            sieve_val = int(sieve_val / p)

        if sieve_val == 1:
          # smooth
          smooth += [(vec, (sqr, (A*x+B), root_A))]
          used_prime |= vec
        elif sieve_val in partial:
          # combine two partials to make a (xor) smooth
          # that is, every prime factor with an odd power is in our factor base
          pair_vec, pair_vals = partial[sieve_val]
          sqr += list(vec & pair_vec) + [sieve_val]
          vec ^= pair_vec
          smooth += [(vec, (sqr + pair_vals[0], (A*x+B)*pair_vals[1], root_A*pair_vals[2]))]
          used_prime |= vec
          num_partial += 1
        else:
          # save partial for later pairing
          partial[sieve_val] = (vec, (sqr, A*x+B, root_A))
      i += 1

    num_smooth = len(smooth)
    num_used_prime = len(used_prime)


    if num_smooth > num_used_prime:

      used_prime_list = sorted(list(used_prime))

      # set up bit fields for gaussian elimination
      masks = []
      mask = 1
      bit_fields = [0]*num_used_prime
      for vec, vals in smooth:
        masks += [mask]
        i = 0
        for p in used_prime_list:
          if p in vec: bit_fields[i] |= mask
          i += 1
        mask <<= 1

      # row echelon form
      col_offset = 0
      null_cols = []
      for col in xrange(num_smooth):
        pivot = col-col_offset == num_used_prime or bit_fields[col-col_offset] & masks[col] == 0
        for row in xrange(col+1-col_offset, num_used_prime):
          if bit_fields[row] & masks[col]:
            if pivot:
              bit_fields[col-col_offset], bit_fields[row] = bit_fields[row], bit_fields[col-col_offset]
              pivot = False
            else:
              bit_fields[row] ^= bit_fields[col-col_offset]
        if pivot:
          null_cols += [col]
          col_offset += 1

      # reduced row echelon form
      for row in xrange(num_used_prime):
        # lowest set bit
        mask = bit_fields[row] & -bit_fields[row]
        for up_row in xrange(row):
          if bit_fields[up_row] & mask:
            bit_fields[up_row] ^= bit_fields[row]

      # check for non-trivial congruencies
      for col in null_cols:
        all_vec, (lh, rh, rA) = smooth[col]
        lhs = lh   # sieved values (left hand side)
        rhs = [rh] # sieved values - n (right hand side)
        rAs = [rA] # root_As (cofactor of lhs)
        i = 0
        for field in bit_fields:
          if field & masks[col]:
            vec, (lh, rh, rA) = smooth[i]
            lhs += list(all_vec & vec) + lh
            all_vec ^= vec
            rhs += [rh]
            rAs += [rA]
          i += 1

        factor = gcd(list_prod(rAs)*list_prod(lhs) - list_prod(rhs), n)
        if factor != 1 and factor != n:
          break
      else:
        continue
      break

  return factor

# divide and conquer list product
def list_prod(a):
  size = len(a)
  if size == 1:
    return a[0]
  return list_prod(a[:size>>1]) * list_prod(a[size>>1:])

# greatest common divisor of a and b
def gcd(a, b):
  while b:
    a, b = b, a%b
  return a

# modular inverse of a mod m
def mod_inv(a, m):
  a = int(a%m)
  x, u = 0, 1
  while a:
    x, u = u, x - (m/a)*u
    m, a = a, m%a
  return x

# legendre symbol (a|m)
# note: returns m-1 if a is a non-residue, instead of -1
def legendre(a, m):
  return pow(a, (m-1) >> 1, m)

# modular sqrt(n) mod p
# p must be prime
def mod_sqrt(n, p):
  a = n%p
  if p%4 == 3:
    return pow(a, (p+1) >> 2, p)
  elif p%8 == 5:
    v = pow(a << 1, (p-5) >> 3, p)
    i = ((a*v*v << 1) % p) - 1
    return (a*v*i)%p
  elif p%8 == 1:
    # Shank's method
    q = p-1
    e = 0
    while q&1 == 0:
      e += 1
      q >>= 1

    n = 2
    while legendre(n, p) != p-1:
      n += 1

    w = pow(a, q, p)
    x = pow(a, (q+1) >> 1, p)
    y = pow(n, q, p)
    r = e
    while True:
      if w == 1:
        return x

      v = w
      k = 0
      while v != 1 and k+1 < r:
        v = (v*v)%p
        k += 1

      if k == 0:
        return x

      d = pow(y, 1 << (r-k-1), p)
      x = (x*d)%p
      y = (d*d)%p
      w = (w*y)%p
      r = k
  else: # p == 2
    return a

#integer sqrt of n
def isqrt(n):
  n = int(n)
  c = int(n*4/3)
  d = c.bit_length()

  a = d>>1
  if d&1:
    x = 1 << a
    y = (x + (n >> a)) >> 1
  else:
    x = (3 << a) >> 2
    y = (x + (c >> a)) >> 1

  if x != y:
    x = y
    y = int(x + n/x) >> 1
    while y < x:
      x = y
      y = int(x + n/x) >> 1
  return x

# strong probable prime
def is_sprp(n, b=2):
  if n < 2: return False
  d = n-1
  s = 0
  while d&1 == 0:
    s += 1
    d >>= 1

  x = pow(b, d, n)
  if x == 1 or x == n-1:
    return True

  for r in xrange(1, s):
    x = (x * x)%n
    if x == 1:
      return False
    elif x == n-1:
      return True

  return False

# lucas probable prime
# assumes D = 1 (mod 4), (D|n) = -1
def is_lucas_prp(n, D):
  P = 1
  Q = (1-D) >> 2

  # n+1 = 2**r*s where s is odd
  s = n+1
  r = 0
  while s&1 == 0:
    r += 1
    s >>= 1

  # calculate the bit reversal of (odd) s
  # e.g. 19 (10011) <=> 25 (11001)
  t = 0
  while s:
    if s&1:
      t += 1
      s -= 1
    else:
      t <<= 1
      s >>= 1

  # use the same bit reversal process to calculate the sth Lucas number
  # keep track of q = Q**n as we go
  U = 0
  V = 2
  q = 1
  # mod_inv(2, n)
  inv_2 = (n+1) >> 1
  while t:
    if t&1:
      # U, V of n+1
      U, V = ((U + V) * inv_2)%n, ((D*U + V) * inv_2)%n
      q = (q * Q)%n
      t -= 1
    else:
      # U, V of n*2
      U, V = (U * V)%n, (V * V - 2 * q)%n
      q = (q * q)%n
      t >>= 1

  # double s until we have the 2**r*sth Lucas number
  while r:
    U, V = (U * V)%n, (V * V - 2 * q)%n
    q = (q * q)%n
    r -= 1

  # primality check
  # if n is prime, n divides the n+1st Lucas number, given the assumptions
  return U == 0

# primes less than 212
small_primes = set([
    2,  3,  5,  7, 11, 13, 17, 19, 23, 29,
   31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
   73, 79, 83, 89, 97,101,103,107,109,113,
  127,131,137,139,149,151,157,163,167,173,
  179,181,191,193,197,199,211])

# pre-calced sieve of eratosthenes for n = 2, 3, 5, 7
indices = [
    1, 11, 13, 17, 19, 23, 29, 31, 37, 41,
   43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
   89, 97,101,103,107,109,113,121,127,131,
  137,139,143,149,151,157,163,167,169,173,
  179,181,187,191,193,197,199,209]

# distances between sieve values
offsets = [
  10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6,
   6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4,
   2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6,
   4, 2, 4, 6, 2, 6, 4, 2, 4, 2,10, 2]

max_int = 2147483647

# an 'almost certain' primality check
def is_prime(n):
  if n < 212:
    return n in small_primes

  for p in small_primes:
    if n%p == 0:
      return False

  # if n is a 32-bit integer, perform full trial division
  if n <= max_int:
    i = 211
    while i*i < n:
      for o in offsets:
        i += o
        if n%i == 0:
          return False
    return True

  # Baillie-PSW
  # this is technically a probabalistic test, but there are no known pseudoprimes
  if not is_sprp(n, 2): return False

  # idea shamelessly stolen from Mathmatica
  # if n is a 2-sprp and a 3-sprp, n is necessarily square-free
  if not is_sprp(n, 3): return False

  a = 5
  s = 2
  # if n is a perfect square, this will never terminate
  while legendre(a, n) != n-1:
    s = -s
    a = s-a
  return is_lucas_prp(n, a)

# next prime strictly larger than n
def next_prime(n):
  if n < 2:
    return 2
  # first odd larger than n
  n = (n + 1) | 1
  if n < 212:
    while True:
      if n in small_primes:
        return n
      n += 2

  # find our position in the sieve rotation via binary search
  x = int(n%210)
  s = 0
  e = 47
  m = 24
  while m != e:
    if indices[m] < x:
      s = m
      m = (s + e + 1) >> 1
    else:
      e = m
      m = (s + e) >> 1

  i = int(n + (indices[m] - x))
  # adjust offsets
  offs = offsets[m:] + offsets[:m]
  while True:
    for o in offs:
      if is_prime(i):
        return i
      i += o

print(mpqs(int(sys.argv[1])))
<?php

$config = new Amp\CodeStyle\Config();
$config->getFinder()->in(__DIR__ . '/src')->in(__DIR__ . '/tests')->in(__DIR__ . '/examples')->in(__DIR__ . '/tools');
$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;
$config->setCacheFile($cacheDir . '/.php_cs.cache');
return $config;<?php

/**
 * Serialization module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Deferred;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use Amp\Promise;
use danog\MadelineProto\Db\DbPropertiesFactory;
use danog\MadelineProto\Db\DriverArray;
use danog\MadelineProto\Ipc\Server;
use danog\MadelineProto\MTProtoSession\Session;
use danog\MadelineProto\Settings\DatabaseAbstract;
use function Amp\File\exists;
use function Amp\File\read;
use function Amp\Ipc\connect;
/**
 * Manages serialization of the MadelineProto instance.
 */
abstract class Serialization
{
    /**
     * Header for session files.
     */
    const PHP_HEADER = '<?php __HALT_COMPILER();';
    /**
     * Serialization version.
     */
    const VERSION = 2;
    /**
    * Unserialize session.
    *
    * Logic for deserialization is as follows.
    - If the session is unlocked
    - Try starting IPC server:
    - Fetch light state
    - If don't need event handler
    - Unlock
    - Fork
    - Lock (fork)
    - Deserialize full (fork)
    - Start IPC server (fork)
    - Store IPC state (fork)
    - If need event handler
    - If have event handler class
    - Deserialize full
    - Start IPC server
    - Store IPC state
    - Else Fallthrough
    - Wait for a new IPC state for a maximum of 30 seconds, then throw
    - Execute original request via IPC
    *
    * - If the session is locked
    - In parallel (concurrent):
    - The IPC server should be running, connect
    - Try starting full session
    - Fetch light state
    - If don't need event handler
    - Wait lock
    - Unlock
    - Fork
    - Lock (fork)
    - Deserialize full (fork)
    - Start IPC server (fork)
    - Store IPC state (fork)
    - If need event handler and have event handler class
    - Wait lock
    - Deserialize full
    - Start IPC server
    - Store IPC state
    - Wait for a new IPC session for a maximum of 30 seconds, then throw
    - Execute original request via IPC
    *
    *
    *
    * - If receiving a startAndLoop or setEventHandler request on an IPC session:
    - Shutdown remote IPC server
    - Deserialize full
    - Start IPC server
    - Store IPC state
    *
    * @param SessionPaths $session Session name
    * @param SettingsAbstract $settings Settings
    * @param bool $forceFull Whether to force full session deserialization
    *
    * @internal
    *
    * @return \Generator
    *
    * @psalm-return \Generator<void, mixed, mixed, array{0: (ChannelledSocket | APIWrapper | \Throwable | null | 0), 1: (callable | null)}>
    */
    public static function unserialize(SessionPaths $session, SettingsAbstract $settings, bool $forceFull = false) : \Generator
    {
        if ((yield exists($session->getSessionPath()))) {
            // Is new session
            $isNew = true;
        } elseif ((yield exists($session->getLegacySessionPath()))) {
            // Is old session
            $isNew = false;
        } else {
            // No session exists yet, lock for when we create it
            return [null, yield from Tools::flockGenerator($session->getLockPath(), LOCK_EX, 1)];
        }
        //Logger::log('Waiting for exclusive session lock...');
        $warningId = Loop::delay(1000, static function () use(&$warningId) {
            Logger::log("It seems like the session is busy.");
            /*if (\defined(\MADELINE_WORKER::class)) {
                  Logger::log("Exiting since we're in a worker");
                  Magic::shutdown(1);
              }*/
            Logger::log("Telegram does not support starting multiple instances of the same session, make sure no other instance of the session is running.");
            $warningId = Loop::repeat(5000, fn() => Logger::log('Still waiting for exclusive session lock...'));
            Loop::unreference($warningId);
        });
        Loop::unreference($warningId);
        $lightState = null;
        $cancelFlock = new Deferred();
        $cancelIpc = new Deferred();
        $canContinue = true;
        $ipcSocket = null;
        $unlock = (yield from Tools::flockGenerator($session->getLockPath(), LOCK_EX, 1, $cancelFlock->promise(), $forceFull ? null : static function () use($session, $cancelFlock, $cancelIpc, &$canContinue, &$ipcSocket, &$lightState) {
            $cancelFull = static function () use(&$cancelFlock) : void {
                if ($cancelFlock !== null) {
                    $copy = $cancelFlock;
                    $cancelFlock = null;
                    $copy->resolve(true);
                }
            };
            $ipcSocket = Tools::call(self::tryConnect($session->getIpcPath(), $cancelIpc->promise(), $cancelFull));
            $session->getLightState()->onResolve(static function (?\Throwable $e, ?LightState $res) use($cancelFull, &$canContinue, &$lightState) {
                if ($res) {
                    $lightState = $res;
                    if (!$res->canStartIpc()) {
                        $canContinue = false;
                        $cancelFull();
                    }
                } else {
                    $lightState = false;
                }
            });
        }));
        Loop::cancel($warningId);
        if (!$unlock) {
            // Canceled, don't have lock
            return $ipcSocket;
        }
        if (!$canContinue) {
            // Have lock, can't use it
            Logger::log("Session has event handler, but it's not started.", Logger::ERROR);
            Logger::log("We don't have access to the event handler class, so we can't start it.", Logger::ERROR);
            Logger::log("Please start the event handler or unset it to use the IPC server.", Logger::ERROR);
            $unlock();
            return $ipcSocket;
        }
        try {
            /** @var LightState */
            $lightState ??= (yield $session->getLightState());
        } catch (\Throwable $e) {
        }
        if ($lightState && !$forceFull) {
            if (!($class = $lightState->getEventHandler())) {
                // Unlock and fork
                $unlock();
                $cancelIpc->resolve(Server::startMe($session));
                return $ipcSocket ?? (yield from self::tryConnect($session->getIpcPath(), $cancelIpc->promise()));
            } elseif (!\class_exists($class)) {
                // Have lock, can't use it
                $unlock();
                Logger::log("Session has event handler, but it's not started.", Logger::ERROR);
                Logger::log("We don't have access to the event handler class, so we can't start it.", Logger::ERROR);
                Logger::log("Please start the event handler or unset it to use the IPC server.", Logger::ERROR);
                return $ipcSocket ?? (yield from self::tryConnect($session->getIpcPath(), $cancelIpc->promise()));
            }
        }
        $tempId = Shutdown::addCallback($unlock = static function () use($unlock) {
            Logger::log("Unlocking exclusive session lock!");
            $unlock();
            Logger::log("Unlocked exclusive session lock!");
        });
        Logger::log("Got exclusive session lock!");
        if ($isNew) {
            $unserialized = (yield from $session->unserialize());
            if ($unserialized instanceof DriverArray) {
                Logger::log("Extracting session from database...");
                if ($settings instanceof Settings) {
                    $settings = $settings->getDb();
                }
                if ($settings instanceof DatabaseAbstract) {
                    $tableName = (string) $unserialized;
                    $unserialized = (yield DbPropertiesFactory::get($settings, $tableName, DbPropertiesFactory::TYPE_ARRAY, $unserialized));
                } else {
                    yield from $unserialized->initStartup();
                }
                $unserialized = (yield $unserialized['data']);
                if (!$unserialized) {
                    throw new Exception("Could not extract session from database!");
                }
            }
        } else {
            $unserialized = (yield from self::legacyUnserialize($session->getLegacySessionPath()));
        }
        if ($unserialized === false) {
            throw new Exception(\danog\MadelineProto\Lang::$current_lang['deserialization_error']);
        }
        Shutdown::removeCallback($tempId);
        return [$unserialized, $unlock];
    }
    /**
     * Try connecting to IPC socket.
     *
     * @param string $ipcPath IPC path
     * @param Promise $cancelConnect Cancelation token (triggers cancellation of connection)
     * @param ?callable(): void $cancelFull    Cancelation token source (can trigger cancellation of full unserialization)
     *
     * @psalm-param Promise<(\Throwable | null)> $cancelConnect
     *
     * @return \Generator
     * @psalm-return \Generator<mixed, mixed, mixed, array{0: (ChannelledSocket | \Throwable | 0), 1: null}>
     */
    public static function tryConnect(string $ipcPath, Promise $cancelConnect, ?callable $cancelFull = null) : \Generator
    {
        for ($x = 0; $x < 60; $x++) {
            Logger::log("MadelineProto is starting, please wait...");
            try {
                \clearstatcache(true, $ipcPath);
                $socket = (yield connect($ipcPath));
                Logger::log("Connected to IPC socket!");
                if ($cancelFull) {
                    $cancelFull();
                }
                return [$socket, null];
            } catch (\Throwable $e) {
                $e = $e->getMessage();
                if ($e !== 'The endpoint does not exist!') {
                    Logger::log("{$e} while connecting to IPC socket");
                }
            }
            if ($res = (yield Tools::timeoutWithDefault($cancelConnect, 1000, null))) {
                if ($res instanceof \Throwable) {
                    return [$res, null];
                }
                $cancelConnect = (new Deferred())->promise();
            }
        }
        return [0, null];
    }
    /**
     * Deserialize legacy session.
     *
     * @param string $session
     * @return \Generator
     */
    private static function legacyUnserialize(string $session) : \Generator
    {
        $tounserialize = (yield read($session));
        try {
            $unserialized = \unserialize($tounserialize);
        } catch (\danog\MadelineProto\Bug74586Exception $e) {
            \class_exists('\\Volatile');
            $tounserialize = \str_replace('O:26:"danog\\MadelineProto\\Button":', 'O:35:"danog\\MadelineProto\\TL\\Types\\Button":', $tounserialize);
            foreach (['RSA', 'TL\\TLMethods', 'TL\\TLConstructors', 'MTProto', 'API', 'DataCenter', 'Connection', 'TL\\Types\\Button', 'TL\\Types\\Bytes', 'APIFactory'] as $class) {
                \class_exists('\\danog\\MadelineProto\\' . $class);
            }
            $unserialized = \danog\Serialization::unserialize($tounserialize);
        } catch (\danog\MadelineProto\Exception $e) {
            if ($e->getFile() === 'MadelineProto' && $e->getLine() === 1) {
                throw $e;
            }
            if (\defined('MADELINEPROTO_TEST') && \constant("MADELINEPROTO_TEST") === 'pony') {
                throw $e;
            }
            \class_exists('\\Volatile');
            foreach (['RSA', 'TL\\TLMethods', 'TL\\TLConstructors', 'MTProto', 'API', 'DataCenter', 'Connection', 'TL\\Types\\Button', 'TL\\Types\\Bytes', 'APIFactory'] as $class) {
                \class_exists('\\danog\\MadelineProto\\' . $class);
            }
            $changed = false;
            if (\strpos($tounserialize, 'O:26:"danog\\MadelineProto\\Button":') !== false) {
                Logger::log("SUBBING BUTTONS!");
                $tounserialize = \str_replace('O:26:"danog\\MadelineProto\\Button":', 'O:35:"danog\\MadelineProto\\TL\\Types\\Button":', $tounserialize);
                $changed = true;
            }
            if (\strpos($e->getMessage(), "Erroneous data format for unserializing 'phpseclib\\Math\\BigInteger'") === 0) {
                Logger::log("SUBBING BIGINTEGOR!");
                $tounserialize = \str_replace('phpseclib\\Math\\BigInteger', 'phpseclib\\Math\\BigIntegor', $tounserialize);
                $changed = true;
            }
            if (\strpos($tounserialize, 'C:25:"phpseclib\\Math\\BigInteger"') !== false) {
                Logger::log("SUBBING TGSECLIB old!");
                $tounserialize = \str_replace('C:25:"phpseclib\\Math\\BigInteger"', 'C:26:"phpseclib3\\Math\\BigInteger"', $tounserialize);
                $changed = true;
            }
            Logger::log((string) $e, Logger::ERROR);
            if (!$changed) {
                throw $e;
            }
            try {
                $unserialized = \danog\Serialization::unserialize($tounserialize);
            } catch (\Throwable $e) {
                $unserialized = \unserialize($tounserialize);
            }
        } catch (\Throwable $e) {
            Logger::log((string) $e, Logger::ERROR);
            throw $e;
        }
        if ($unserialized instanceof \danog\PlaceHolder) {
            $unserialized = \danog\Serialization::unserialize($tounserialize);
        }
        return $unserialized;
    }
}<?php

namespace danog\MadelineProto\Stream\Ogg;

use Amp\Emitter;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\BufferInterface;
/**
 * Async OGG stream reader.
 *
 * @author Charles-Ã‰douard Coste <contact@ccoste.fr>
 * @author Daniil Gentili <daniil@daniil.it>
 */
class Ogg
{
    private const CAPTURE_PATTERN = "OggS";
    // ASCII encoded "OggS" string
    private const BOS = 2;
    private const EOS = 4;
    const STATE_READ_HEADER = 0;
    const STATE_READ_COMMENT = 1;
    const STATE_STREAMING = 3;
    const STATE_END = 4;
    /**
     * Required frame duration in microseconds.
     */
    private int $frameDuration = 60000;
    /**
     * Current total frame duration in microseconds.
     */
    private int $currentDuration = 0;
    /**
     * Current OPUS payload.
     */
    private string $opusPayload = '';
    /**
     * OGG Stream count.
     */
    private int $streamCount;
    /**
     * Buffered stream interface.
     */
    private BufferInterface $stream;
    /**
     * Pack format.
     */
    private string $packFormat;
    /**
     * OPUS packet emitter.
     */
    private Emitter $emitter;
    /**
     *
     */
    private function __construct()
    {
    }
    /**
     * Constructor.
     *
     * @param BufferedStreamInterface $stream The stream
     * @param int $frameDuration Required frame duration, microseconds
     *
     * @return \Generator
     * @psalm-return \Generator<mixed, mixed, mixed, self>
     */
    public static function init(BufferedStreamInterface $stream, int $frameDuration) : \Generator
    {
        $self = new self();
        $self->frameDuration = $frameDuration;
        $self->stream = (yield $stream->getReadBuffer($l));
        $self->emitter = new Emitter();
        $pack_format = ['stream_structure_version' => 'C', 'header_type_flag' => 'C', 'granule_position' => 'P', 'bitstream_serial_number' => 'V', 'page_sequence_number' => 'V', 'CRC_checksum' => 'V', 'number_page_segments' => 'C'];
        $self->packFormat = \implode('/', \array_map(fn(string $v, string $k): string => ($v . $k), $pack_format, \array_keys($pack_format)));
        return $self;
    }
    /**
     * Read OPUS length.
     *
     * @param string $content
     * @param integer $offset
     * @return integer
     */
    private function readLen(string $content, int &$offset) : int
    {
        $len = \ord($content[$offset++]);
        if ($len > 251) {
            $len += \ord($content[$offset++]) << 2;
        }
        return $len;
    }
    /**
     * OPUS state machine.
     *
     * @param string $content
     * @return \Generator
     */
    private function opusStateMachine(string $content) : \Generator
    {
        $curStream = 0;
        $offset = 0;
        $len = \strlen($content);
        while ($offset < $len) {
            $selfDelimited = $curStream++ < $this->streamCount - 1;
            $sizes = [];
            $preOffset = $offset;
            $toc = \ord($content[$offset++]);
            $stereo = $toc & 4;
            $conf = $toc >> 3;
            $c = $toc & 3;
            if ($conf < 12) {
                $frameDuration = $conf % 4;
                if ($frameDuration === 0) {
                    $frameDuration = 10000;
                } else {
                    $frameDuration *= 20000;
                }
            } elseif ($conf < 16) {
                $frameDuration = 2 ** ($conf % 2) * 10000;
            } else {
                $frameDuration = 2 ** ($conf % 4) * 2500;
            }
            $paddingLen = 0;
            if ($c === 0) {
                // Exactly 1 frame
                $sizes[] = $selfDelimited ? $this->readLen($content, $offset) : $len - $offset;
            } elseif ($c === 1) {
                // Exactly 2 frames, equal size
                $size = $selfDelimited ? $this->readLen($content, $offset) : ($len - $offset) / 2;
                $sizes[] = $size;
                $sizes[] = $size;
            } elseif ($c === 2) {
                // Exactly 2 frames, different size
                $size = $this->readLen($content, $offset);
                $sizes[] = $size;
                $sizes[] = $selfDelimited ? $this->readLen($content, $offset) : $len - ($offset + $size);
            } else {
                // Arbitrary number of frames
                $ch = \ord($content[$offset++]);
                $len--;
                $count = $ch & 0x3f;
                $vbr = $ch & 0x80;
                $padding = $ch & 0x40;
                if ($padding) {
                    $paddingLen = $padding = \ord($content[$offset++]);
                    while ($padding === 255) {
                        $padding = \ord($content[$offset++]);
                        $paddingLen += $padding - 1;
                    }
                }
                if ($vbr) {
                    if (!$selfDelimited) {
                        $count -= 1;
                    }
                    for ($x = 0; $x < $count; $x++) {
                        $sizes[] = $this->readLen($content, $offset);
                    }
                    if (!$selfDelimited) {
                        $sizes[] = $len - ($offset + $padding);
                    }
                } else {
                    // CBR
                    $size = $selfDelimited ? $this->readLen($content, $offset) : ($len - ($offset + $padding)) / $count;
                    \array_push($sizes, ...\array_fill(0, $count, $size));
                }
            }
            $totalDuration = \count($sizes) * $frameDuration;
            if (!$selfDelimited && $totalDuration + $this->currentDuration <= $this->frameDuration) {
                $this->currentDuration += $totalDuration;
                $sum = \array_sum($sizes);
                $this->opusPayload .= \Phabel\Target\Php80\Polyfill::substr($content, $preOffset, $offset - $preOffset + $sum + $paddingLen);
                if ($this->currentDuration === $this->frameDuration) {
                    (yield $this->emitter->emit($this->opusPayload));
                    $this->opusPayload = '';
                    $this->currentDuration = 0;
                }
                $offset += $sum;
                $offset += $paddingLen;
                continue;
            }
            foreach ($sizes as $size) {
                $this->opusPayload .= \chr($toc & ~3);
                $this->opusPayload .= \Phabel\Target\Php80\Polyfill::substr($content, $offset, $size);
                $offset += $size;
                $this->currentDuration += $frameDuration;
                if ($this->currentDuration >= $this->frameDuration) {
                    if ($this->currentDuration > $this->frameDuration) {
                        Logger::log("Emitting packet with duration {$this->currentDuration} but need {$this->frameDuration}, please reconvert the OGG file with a proper frame size.", Logger::WARNING);
                    }
                    (yield $this->emitter->emit($this->opusPayload));
                    $this->opusPayload = '';
                    $this->currentDuration = 0;
                }
            }
            $offset += $paddingLen;
        }
    }
    /**
     * Read frames.
     *
     * @return \Generator
     */
    public function read() : \Generator
    {
        $state = self::STATE_READ_HEADER;
        $content = '';
        while (true) {
            $init = (yield $this->stream->bufferRead(4 + 23));
            if (empty($init)) {
                $this->emitter->complete();
                return false;
                // EOF
            }
            if (\Phabel\Target\Php80\Polyfill::substr($init, 0, 4) !== self::CAPTURE_PATTERN) {
                throw new Exception("Bad capture pattern");
            }
            /*$headers = \unpack(
                            $this->packFormat,
                            \substr($init, 4)
                        );
            
                        if ($headers['stream_structure_version'] != 0x00) {
                            throw new Exception("Bad stream version");
                        }
                        $granule_diff = $headers['granule_position'] - $granule;
                        $granule = $headers['granule_position'];
            
                        $continuation = (bool) ($headers['header_type_flag'] & 0x01);
                        $firstPage = (bool) ($headers['header_type_flag'] & 0x02);
                        $lastPage = (bool) ($headers['header_type_flag'] & 0x04);
                        */
            $segments = \unpack('C*', (yield $this->stream->bufferRead(\ord($init[26]))));
            //$serial = $headers['bitstream_serial_number'];
            /*if ($headers['header_type_flag'] & Ogg::BOS) {
                  $this->emit('ogg:stream:start', [$serial]);
              } elseif ($headers['header_type_flag'] & Ogg::EOS) {
                  $this->emit('ogg:stream:end', [$serial]);
              } else {
                  $this->emit('ogg:stream:continue', [$serial]);
              }*/
            $sizeAccumulated = 0;
            foreach ($segments as $segment_size) {
                $sizeAccumulated += $segment_size;
                if ($segment_size < 255) {
                    $content .= (yield $this->stream->bufferRead($sizeAccumulated));
                    if ($state === self::STATE_STREAMING) {
                        yield from $this->opusStateMachine($content);
                    } elseif ($state === self::STATE_READ_HEADER) {
                        if (\Phabel\Target\Php80\Polyfill::substr($content, 0, 8) !== 'OpusHead') {
                            throw new \RuntimeException("This is not an OPUS stream!");
                        }
                        $opus_head = \unpack('Cversion/Cchannel_count/vpre_skip/Vsample_rate/voutput_gain/Cchannel_mapping_family/', \Phabel\Target\Php80\Polyfill::substr($content, 8));
                        if ($opus_head['channel_mapping_family']) {
                            $opus_head['channel_mapping'] = \unpack('Cstream_count/Ccoupled_count/C*channel_mapping', \Phabel\Target\Php80\Polyfill::substr($content, 19));
                        } else {
                            $opus_head['channel_mapping'] = ['stream_count' => 1, 'coupled_count' => $opus_head['channel_count'] - 1, 'channel_mapping' => [0]];
                            if ($opus_head['channel_count'] === 2) {
                                $opus_head['channel_mapping']['channel_mapping'][] = 1;
                            }
                        }
                        $this->streamCount = $opus_head['channel_mapping']['stream_count'];
                        $state = self::STATE_READ_COMMENT;
                    } elseif ($state === self::STATE_READ_COMMENT) {
                        $vendor_string_length = \unpack('V', \Phabel\Target\Php80\Polyfill::substr($content, 8, 4))[1];
                        $result = [];
                        $result['vendor_string'] = \Phabel\Target\Php80\Polyfill::substr($content, 12, $vendor_string_length);
                        $comment_count = \unpack('V', \Phabel\Target\Php80\Polyfill::substr($content, 12 + $vendor_string_length, 4))[1];
                        $offset = 16 + $vendor_string_length;
                        for ($x = 0; $x < $comment_count; $x++) {
                            $length = \unpack('V', \Phabel\Target\Php80\Polyfill::substr($content, $offset, 4))[1];
                            $result['comments'][$x] = \Phabel\Target\Php80\Polyfill::substr($content, $offset += 4, $length);
                            $offset += $length;
                        }
                        $state = self::STATE_STREAMING;
                    }
                    $content = '';
                    $sizeAccumulated = 0;
                }
            }
        }
    }
    /**
     * Get OPUS packet emitter.
     *
     * @return Emitter
     */
    public function getEmitter() : Emitter
    {
        return $this->emitter;
    }
}<?php

/**
 * Websocket TLS stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Transport;

use danog\MadelineProto\Stream\ConnectionContext;
/**
 * Websocket TLS stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class WssStream extends WsStream
{
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        return parent::connect($ctx->getCtx()->secure(true), $header);
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Default stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Transport;

use Amp\ByteStream\ClosedException;
use Amp\CancellationToken;
use Amp\Promise;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\Connector;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\Socket;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\ProxyStreamInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
use function Amp\Socket\connector;
/**
 * Default stream wrapper.
 *
 * Manages reading data in chunks
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class DefaultStream implements RawStreamInterface, ProxyStreamInterface
{
    use RawStream;
    /**
     * Socket.
     *
     * @var ?EncryptableSocket
     */
    protected $stream;
    /**
     * Connector.
     *
     * @var Connector
     */
    private $connector;
    /**
     *
     */
    public function setupTls(?CancellationToken $cancellationToken = null) : \Amp\Promise
    {
        return $this->stream->setupTls($cancellationToken);
    }
    /**
     * @return EncryptableSocket
     */
    public function getStream()
    {
        return $this->stream;
    }
    /**
     *
     */
    public function connect(\danog\MadelineProto\Stream\ConnectionContext $ctx, string $header = '') : \Generator
    {
        $ctx = $ctx->getCtx();
        $uri = $ctx->getUri();
        $secure = $ctx->isSecure();
        if ($secure) {
            $ctx->setSocketContext($ctx->getSocketContext()->withTlsContext(new ClientTlsContext($uri->getHost())));
        }
        $this->stream = (yield ($this->connector ?? connector())->connect((string) $uri, $ctx->getSocketContext(), $ctx->getCancellationToken()));
        if ($secure) {
            (yield $this->stream->setupTls());
        }
        (yield $this->stream->write($header));
    }
    /**
     * Async chunked read.
     *
     * @return Promise
     */
    public function read() : Promise
    {
        return $this->stream ? $this->stream->read() : new \Amp\Success(null);
    }
    /**
     * Async write.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function write(string $data) : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        return $this->stream->write($data);
    }
    /**
     * Close.
     *
     * @return void
     */
    public function disconnect()
    {
        try {
            if ($this->stream) {
                $this->stream->close();
                $this->stream = null;
            }
        } catch (\Throwable $e) {
            \danog\MadelineProto\Logger::log('Got exception while closing stream: ' . $e->getMessage());
        }
    }
    /**
     * Close.
     *
     * @return void
     */
    public function close()
    {
        $this->disconnect();
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream;
    }
    /**
     *
     */
    public function setExtra($extra)
    {
        $this->connector = $extra;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Premade stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Transport;

use Amp\ByteStream\ClosedException;
use Amp\CancellationToken;
use Amp\Promise;
use Amp\Socket\Socket;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\ProxyStreamInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * Premade stream wrapper.
 *
 * Manages reading data in chunks
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class PremadeStream implements RawStreamInterface, ProxyStreamInterface
{
    use RawStream;
    private $stream;
    /**
     *
     */
    public function __construct()
    {
    }
    /**
     *
     */
    public function setupTls(?CancellationToken $cancellationToken = null) : \Amp\Promise
    {
        return $this->stream->setupTls($cancellationToken);
    }
    /**
     *
     */
    public function getStream()
    {
        return $this->stream;
    }
    /**
     *
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        if ($header !== '') {
            (yield $this->stream->write($header));
        }
    }
    /**
     * Async chunked read.
     *
     * @return Promise
     */
    public function read() : Promise
    {
        return $this->stream ? $this->stream->read() : new \Amp\Success(null);
    }
    /**
     * Async write.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function write(string $data) : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        return $this->stream->write($data);
    }
    /**
     * Async close.
     *
     * @return void
     */
    public function disconnect()
    {
        try {
            if ($this->stream) {
                if (\method_exists($this->stream, 'close')) {
                    $this->stream->close();
                }
                $this->stream = null;
            }
        } catch (\Throwable $e) {
            \danog\MadelineProto\Logger::log('Got exception while closing stream: ' . $e->getMessage());
        }
    }
    /**
     *
     */
    public function close() : void
    {
        $this->disconnect();
    }
    /**
     * {@inheritdoc}
     *
     * @return \Amp\Socket\Socket
     */
    public function getSocket() : Socket
    {
        return $this->stream;
    }
    /**
     * {@inheritdoc}
     */
    public function setExtra($extra)
    {
        $this->stream = $extra;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Websocket stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Transport;

use Amp\Http\Client\HttpClientBuilder;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Websocket\Client\Connection;
use Amp\Websocket\Client\Connector;
use Amp\Websocket\Client\Handshake;
use Amp\Websocket\Client\Rfc6455Connector;
use Amp\Websocket\ClosedException;
use Amp\Websocket\Message;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\ProxyStreamInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
use function Amp\Websocket\Client\connector;
/**
 * Websocket stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class WsStream implements RawStreamInterface, ProxyStreamInterface
{
    use RawStream;
    /**
     * Websocket stream.
     *
     * @var Connection
     */
    private $stream;
    /**
     * Websocket message.
     *
     * @var Message
     */
    private $message;
    /**
     * Websocket Connector.
     *
     * @var Connector
     */
    private $connector;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        if (!\class_exists(Handshake::class)) {
            throw new \danog\MadelineProto\Exception('Please install amphp/websocket-client by running "composer require amphp/websocket-client:dev-master"');
        }
        $this->dc = $ctx->getIntDc();
        $uri = $ctx->getStringUri();
        $uri = \str_replace('tcp://', $ctx->isSecure() ? 'wss://' : 'ws://', $uri);
        $handshake = new Handshake($uri);
        $this->stream = (yield ($this->connector ?? new Rfc6455Connector(HttpClientBuilder::buildDefault()))->connect($handshake, $ctx->getCancellationToken()));
        if (\strlen($header)) {
            (yield $this->write($header));
        }
    }
    /**
     * Async close.
     */
    public function disconnect()
    {
        try {
            $this->stream->close();
        } catch (\Throwable $e) {
        }
    }
    /**
     *
     */
    public function readGenerator() : \Generator
    {
        try {
            if (!$this->message || ($data = (yield $this->message->buffer())) === null) {
                $this->message = (yield $this->stream->receive());
                if (!$this->message) {
                    return null;
                }
                $data = (yield $this->message->buffer());
                $this->message = null;
            }
        } catch (\Throwable $e) {
            if ($e instanceof ClosedException && $e->getReason() !== 'Client closed the underlying TCP connection') {
                throw $e;
            }
            return null;
        }
        return $data;
    }
    /**
     * Async write.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function write(string $data) : \Amp\Promise
    {
        return $this->stream->sendBinary($data);
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     *
     */
    public function setExtra($extra)
    {
        if ($extra instanceof Connector) {
            $this->connector = $extra;
        }
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Raw stream helper trait.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Async;

use Amp\Promise;
/**
 * Raw stream helper trait.
 *
 * Wraps the asynchronous generator methods with asynchronous promise-based methods
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait RawStream
{
    /**
     *
     */
    public function read() : Promise
    {
        return \danog\MadelineProto\Tools::call($this->readGenerator());
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        return \danog\MadelineProto\Tools::call($this->writeGenerator($data));
    }
    /**
     *
     */
    public function end(string $finalData = '') : Promise
    {
        if (\method_exists($this, 'endGenerator')) {
            return \danog\MadelineProto\Tools::call($this->endGenerator($finalData));
        }
        $promise = $this->write($finalData);
        $promise->onResolve(fn() => $this->disconnect());
        return $promise;
    }
}<?php

/**
 * Buffer helper trait.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Async;

use Amp\Promise;
/**
 * Buffer helper trait.
 *
 * Wraps the asynchronous generator methods with asynchronous promise-based methods
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait Buffer
{
    /**
     *
     */
    public function bufferRead(int $length) : Promise
    {
        return \danog\MadelineProto\Tools::call($this->bufferReadGenerator($length));
    }
    /**
     *
     */
    public function bufferWrite(string $data) : Promise
    {
        return \danog\MadelineProto\Tools::call($this->bufferWriteGenerator($data));
    }
}<?php

/**
 * Buffered stream helper trait.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Async;

use Amp\Promise;
/**
 * Buffered stream helper trait.
 *
 * Wraps the asynchronous generator methods with asynchronous promise-based methods
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait BufferedStream
{
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return Promise
     */
    public function getReadBuffer(&$length) : Promise
    {
        return \danog\MadelineProto\Tools::call($this->getReadBufferGenerator($length));
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Total length of data that is going to be piped in the buffer
     * @param string $append Data to append after entire buffer is written
     *
     * @return Promise
     */
    public function getWriteBuffer(int $length, string $append = '') : Promise
    {
        return \danog\MadelineProto\Tools::call($this->getWriteBufferGenerator($length, $append));
    }
}<?php

/**
 * Connection context.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

use Amp\CancellationToken;
use Amp\Socket\ConnectContext;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Stream\MTProtoTransport\ObfuscatedStream;
use danog\MadelineProto\Stream\Transport\DefaultStream;
use League\Uri\Http;
use Psr\Http\Message\UriInterface;
/**
 * Connection context class.
 *
 * Is responsible for maintaining state about a certain connection to a DC.
 * That includes the Stream chain that is required to use the connection, the connection URI, and other connection-related data.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class ConnectionContext
{
    /**
     * Whether to use a secure socket.
     *
     * @var bool
     */
    private $secure = false;
    /**
     * Whether to use test servers.
     *
     * @var bool
     */
    private $test = false;
    /**
     * Whether to use media servers.
     *
     * @var bool
     */
    private $media = false;
    /**
     * Whether to use CDN servers.
     *
     * @var bool
     */
    private $cdn = false;
    /**
     * The connection URI.
     *
     * @var UriInterface
     */
    private $uri;
    /**
     * Whether this connection context will be used by the DNS client.
     *
     * @var bool
     */
    private $isDns = false;
    /**
     * Socket context.
     *
     * @var \Amp\Socket\ConnectContext
     */
    private $socketContext;
    /**
     * Cancellation token.
     *
     * @var \Amp\CancellationToken
     */
    private $cancellationToken;
    /**
     * The telegram DC ID.
     *
     * @var int
     */
    private $dc = 0;
    /**
     * Whether to use IPv6.
     *
     * @var bool
     */
    private $ipv6 = false;
    /**
     * An array of arrays containing an array with the stream name and the extra parameter to pass to it.
     *
     * @var array<0: class-string, 1: mixed>[]
     */
    private $nextStreams = [];
    /**
     * The current stream key.
     *
     * @var int
     */
    private $key = 0;
    /**
     * Read callback.
     *
     * @var callable
     */
    private $readCallback;
    /**
     * Set the socket context.
     *
     * @param ConnectContext $socketContext
     *
     * @return self
     */
    public function setSocketContext(ConnectContext $socketContext) : self
    {
        $this->socketContext = $socketContext;
        return $this;
    }
    /**
     * Get the socket context.
     *
     * @return ConnectContext
     */
    public function getSocketContext() : ConnectContext
    {
        return $this->socketContext;
    }
    /**
     * Set the connection URI.
     *
     * @param (string | UriInterface) $uri
     *
     * @return self
     */
    public function setUri($uri) : self
    {
        $this->uri = $uri instanceof UriInterface ? $uri : Http::createFromString($uri);
        return $this;
    }
    /**
     * Get the URI as a string.
     *
     * @return string
     */
    public function getStringUri() : string
    {
        return (string) $this->uri;
    }
    /**
     * Get the URI.
     *
     * @return UriInterface
     */
    public function getUri() : UriInterface
    {
        return $this->uri;
    }
    /**
     * Set the cancellation token.
     *
     * @param CancellationToken $cancellationToken
     *
     * @return self
     */
    public function setCancellationToken($cancellationToken) : self
    {
        $this->cancellationToken = $cancellationToken;
        return $this;
    }
    /**
     * Get the cancellation token.
     *
     * @return CancellationToken
     */
    public function getCancellationToken()
    {
        return $this->cancellationToken;
    }
    /**
     * Return a clone of the current connection context.
     *
     * @return self
     */
    public function getCtx() : self
    {
        return clone $this;
    }
    /**
     * Set the test boolean.
     *
     * @param bool $test
     *
     * @return self
     */
    public function setTest(bool $test) : self
    {
        $this->test = $test;
        return $this;
    }
    /**
     * Whether this is a test connection.
     *
     * @return bool
     */
    public function isTest() : bool
    {
        return $this->test;
    }
    /**
     * Whether this is a media connection.
     *
     * @return bool
     */
    public function isMedia() : bool
    {
        return $this->media;
    }
    /**
     * Whether this is a CDN connection.
     *
     * @return bool
     */
    public function isCDN() : bool
    {
        return $this->cdn;
    }
    /**
     * Whether this connection context will only be used by the DNS client.
     *
     * @return bool
     */
    public function isDns() : bool
    {
        return $this->isDns;
    }
    /**
     * Whether this connection context will only be used by the DNS client.
     *
     * @param boolean $isDns
     * @return self
     */
    public function setIsDns(bool $isDns) : self
    {
        $this->isDns = $isDns;
        return $this;
    }
    /**
     * Set the secure boolean.
     *
     * @param bool $secure
     *
     * @return self
     */
    public function secure(bool $secure) : self
    {
        $this->secure = $secure;
        return $this;
    }
    /**
     * Whether to use TLS with socket connections.
     *
     * @return bool
     */
    public function isSecure() : bool
    {
        return $this->secure;
    }
    /**
     * Set the DC ID.
     *
     * @param (string | int) $dc
     *
     * @return self
     */
    public function setDc($dc) : self
    {
        $int = \intval($dc);
        if (!(1 <= $int && $int <= 1000)) {
            throw new Exception("Invalid DC id provided: {$dc}");
        }
        $this->dc = $dc;
        $this->media = \strpos($dc, '_media') !== false;
        $this->cdn = \strpos($dc, '_cdn') !== false;
        return $this;
    }
    /**
     * Get the DC ID.
     *
     * @return (string | int)
     */
    public function getDc()
    {
        return $this->dc;
    }
    /**
     * Get the int DC ID.
     *
     * @return (string | int)
     */
    public function getIntDc()
    {
        $dc = \intval($this->dc);
        if ($this->test) {
            $dc += 10000;
        }
        if ($this->media) {
            $dc = -$dc;
        }
        return $dc;
    }
    /**
     * Whether to use ipv6.
     *
     * @param bool $ipv6
     *
     * @return self
     */
    public function setIpv6(bool $ipv6) : self
    {
        $this->ipv6 = $ipv6;
        return $this;
    }
    /**
     * Whether to use ipv6.
     *
     * @return bool
     */
    public function getIpv6() : bool
    {
        return $this->ipv6;
    }
    /**
     * Add a stream to the stream chain.
     *
     * @param string $streamName
     * @param mixed $extra
     *
     * @psalm-param class-string $streamName
     *
     * @return self
     */
    public function addStream(string $streamName, $extra = null) : self
    {
        $this->nextStreams[] = [$streamName, $extra];
        $this->key = \count($this->nextStreams) - 1;
        return $this;
    }
    /**
     * Set read callback, called every time the socket reads at least a byte.
     *
     * @param callable $callable Read callback
     *
     * @return void
     */
    public function setReadCallback(callable $callable)
    {
        $this->readCallback = $callable;
    }
    /**
     * Check if a read callback is present.
     *
     * @return boolean
     */
    public function hasReadCallback() : bool
    {
        return $this->readCallback !== null;
    }
    /**
     * Get read callback.
     *
     * @return callable
     */
    public function getReadCallback() : callable
    {
        return $this->readCallback;
    }
    /**
     * Get the current stream name from the stream chain.
     *
     * @return string
     */
    public function getStreamName() : string
    {
        return $this->nextStreams[$this->key][0];
    }
    /**
     * Check if has stream within stream chain.
     *
     * @param string $stream Stream name
     *
     * @return boolean
     */
    public function hasStreamName(string $stream) : bool
    {
        foreach ($this->nextStreams as list($name)) {
            if ($name === $stream) {
                return true;
            }
        }
        return false;
    }
    /**
     * Get a stream from the stream chain.
     *
     * @return \Generator<StreamInterface>
     */
    public function getStream(string $buffer = '') : \Generator
    {
        list($clazz, $extra) = $this->nextStreams[$this->key--];
        $obj = new $clazz();
        if ($obj instanceof ProxyStreamInterface) {
            $obj->setExtra($extra);
        }
        yield from $obj->connect($this, $buffer);
        return $obj;
    }
    /**
     * Get the inputClientProxy proxy MTProto object.
     *
     * @return array
     */
    public function getInputClientProxy() : ?array
    {
        foreach ($this->nextStreams as $couple) {
            list($streamName, $extra) = $couple;
            if ($streamName === ObfuscatedStream::class && isset($extra['address'])) {
                $extra['_'] = 'inputClientProxy';
                return $extra;
            }
        }
        return null;
    }
    /**
     * Get a description "name" of the context.
     *
     * @return string
     */
    public function getName() : string
    {
        $string = $this->getStringUri();
        if ($this->isSecure()) {
            $string .= ' (TLS)';
        }
        $string .= $this->isTest() ? ' test' : ' main';
        $string .= ' DC ';
        $string .= $this->getDc();
        $string .= ', via ';
        $string .= $this->getIpv6() ? 'ipv6' : 'ipv4';
        $string .= ' using ';
        foreach (\array_reverse($this->nextStreams) as $k => $stream) {
            if ($k) {
                $string .= ' => ';
            }
            $string .= \preg_replace('/.*\\\\/', '', $stream[0]);
            if ($stream[1] && $stream[0] !== DefaultStream::class) {
                $string .= ' (' . \json_encode($stream[1]) . ')';
            }
        }
        return $string;
    }
    /**
     * Returns a representation of the context.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->getName();
    }
}<?php

/**
 * Socks5 stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Proxy;

use Amp\Promise;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\EncryptableSocket;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\RawProxyStreamInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * Socks5 stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class SocksProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
{
    private const REPS = [0 => 'succeeded', 1 => 'general SOCKS server failure', 2 => 'connection not allowed by ruleset', 3 => 'Network unreachable', 4 => 'Host unreachable', 5 => 'Connection refused', 6 => 'TTL expired', 7 => 'Command not supported', 8 => 'Address type not supported'];
    use RawStream;
    /**
     * Stream.
     *
     * @var RawStreamInterface
     */
    protected $stream;
    private $extra;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $ctx = $ctx->getCtx();
        $uri = $ctx->getUri();
        $secure = $ctx->isSecure();
        if ($secure) {
            $ctx->setSocketContext($ctx->getSocketContext()->withTlsContext(new ClientTlsContext($uri->getHost())));
        }
        $ctx->setUri('tcp://' . $this->extra['address'] . ':' . $this->extra['port'])->secure(false);
        $methods = \chr(0);
        if (isset($this->extra['username']) && isset($this->extra['password'])) {
            $methods .= \chr(2);
        }
        $this->stream = (yield from $ctx->getStream(\chr(5) . \chr(\strlen($methods)) . $methods));
        $l = 2;
        $buffer = (yield $this->stream->getReadBuffer($l));
        $version = \ord((yield $buffer->bufferRead(1)));
        $method = \ord((yield $buffer->bufferRead(1)));
        if ($version !== 5) {
            throw new \danog\MadelineProto\Exception("Wrong SOCKS5 version: {$version}");
        }
        if ($method === 2) {
            $auth = \chr(1) . \chr(\strlen($this->extra['username'])) . $this->extra['username'] . \chr(\strlen($this->extra['password'])) . $this->extra['password'];
            (yield $this->stream->write($auth));
            $buffer = (yield $this->stream->getReadBuffer($l));
            $version = \ord((yield $buffer->bufferRead(1)));
            $result = \ord((yield $buffer->bufferRead(1)));
            if ($version !== 1) {
                throw new \danog\MadelineProto\Exception("Wrong authorized SOCKS version: {$version}");
            }
            if ($result !== 0) {
                throw new \danog\MadelineProto\Exception("Wrong authorization status: {$version}");
            }
        } elseif ($method !== 0) {
            throw new \danog\MadelineProto\Exception("Wrong method: {$method}");
        }
        $payload = \pack('C3', 0x5, 0x1, 0x0);
        try {
            $ip = \inet_pton($uri->getHost());
            $payload .= $ip ? \pack('C1', \strlen($ip) === 4 ? 0x1 : 0x4) . $ip : \pack('C2', 0x3, \strlen($uri->getHost())) . $uri->getHost();
        } catch (\danog\MadelineProto\Exception $e) {
            $payload .= \pack('C2', 0x3, \strlen($uri->getHost())) . $uri->getHost();
        }
        $payload .= \pack('n', $uri->getPort());
        (yield $this->stream->write($payload));
        $l = 4;
        $buffer = (yield $this->stream->getReadBuffer($l));
        $version = \ord((yield $buffer->bufferRead(1)));
        if ($version !== 5) {
            throw new \danog\MadelineProto\Exception("Wrong SOCKS5 version: {$version}");
        }
        $rep = \ord((yield $buffer->bufferRead(1)));
        if ($rep !== 0) {
            $rep = self::REPS[$rep] ?? $rep;
            throw new \danog\MadelineProto\Exception("Wrong SOCKS5 rep: {$rep}");
        }
        $rsv = \ord((yield $buffer->bufferRead(1)));
        if ($rsv !== 0) {
            throw new \danog\MadelineProto\Exception("Wrong socks5 final RSV: {$rsv}");
        }
        switch (\ord((yield $buffer->bufferRead(1)))) {
            case 1:
                $buffer = (yield $this->stream->getReadBuffer($l));
                $ip = \inet_ntop((yield $buffer->bufferRead(4)));
                break;
            case 4:
                $l = 16;
                $buffer = (yield $this->stream->getReadBuffer($l));
                $ip = \inet_ntop((yield $buffer->bufferRead(16)));
                break;
            case 3:
                $l = 1;
                $buffer = (yield $this->stream->getReadBuffer($l));
                $length = \ord((yield $buffer->bufferRead(1)));
                $buffer = (yield $this->stream->getReadBuffer($length));
                $ip = (yield $buffer->bufferRead($length));
                break;
        }
        $l = 2;
        $buffer = (yield $this->stream->getReadBuffer($l));
        $port = \unpack('n', (yield $buffer->bufferRead(2)))[1];
        \danog\MadelineProto\Logger::log(['Connected to ' . $ip . ':' . $port . ' via socks5']);
        if ($secure) {
            (yield $this->getSocket()->setupTls());
        }
        if (\strlen($header)) {
            (yield ((yield $this->stream->getWriteBuffer(\strlen($header))))->bufferWrite($header));
        }
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return Promise
     */
    public function getWriteBuffer(int $length, string $append = '') : Promise
    {
        return $this->stream->getWriteBuffer($length, $append);
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return Promise
     */
    public function getReadBuffer(&$length) : Promise
    {
        return $this->stream->getReadBuffer($length);
    }
    /**
     *
     */
    public function read() : Promise
    {
        return $this->stream->read();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        return $this->stream->write($data);
    }
    /**
     * Sets proxy data.
     *
     * @param array $extra Proxy data
     *
     * @return void
     */
    public function setExtra($extra)
    {
        $this->extra = $extra;
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * HTTP proxy stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Proxy;

use Amp\Promise;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\EncryptableSocket;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\RawProxyStreamInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * HTTP proxy stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class HttpProxy implements RawProxyStreamInterface, BufferedProxyStreamInterface
{
    use RawStream;
    /**
     * Stream.
     *
     * @var RawStreamInterface
     */
    protected $stream;
    private $extra;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $ctx = $ctx->getCtx();
        $uri = $ctx->getUri();
        $secure = $ctx->isSecure();
        if ($secure) {
            $ctx->setSocketContext($ctx->getSocketContext()->withTlsContext(new ClientTlsContext($uri->getHost())));
        }
        $ctx->setUri('tcp://' . $this->extra['address'] . ':' . $this->extra['port'])->secure(false);
        $this->stream = (yield from $ctx->getStream());
        $address = $uri->getHost();
        $port = $uri->getPort();
        try {
            if (\strlen(\inet_pton($address) === 16)) {
                $address = '[' . $address . ']';
            }
        } catch (\danog\MadelineProto\Exception $e) {
        }
        (yield $this->stream->write("CONNECT {$address}:{$port} HTTP/1.1\r\nHost: {$address}:{$port}\r\nAccept: */*\r\n" . $this->getProxyAuthHeader() . "Connection: keep-Alive\r\n\r\n"));
        $buffer = (yield $this->stream->getReadBuffer($l));
        $headers = '';
        $was_crlf = false;
        while (true) {
            $piece = (yield $buffer->bufferRead(2));
            $headers .= $piece;
            if ($piece === "\n\r") {
                // Assume end of headers with \r\n\r\n
                $headers .= (yield $buffer->bufferRead(1));
                break;
            }
            if ($was_crlf && $piece === "\r\n") {
                break;
            }
            $was_crlf = $piece === "\r\n";
        }
        $headers = \explode("\r\n", $headers);
        list($protocol, $code, $description) = \explode(' ', $headers[0], 3);
        list($protocol, $protocol_version) = \explode('/', $protocol);
        if ($protocol !== 'HTTP') {
            throw new \danog\MadelineProto\Exception('Wrong protocol');
        }
        $code = (int) $code;
        unset($headers[0]);
        if (\array_pop($headers) . \array_pop($headers) !== '') {
            throw new \danog\MadelineProto\Exception('Wrong last header');
        }
        foreach ($headers as $key => $current_header) {
            unset($headers[$key]);
            $current_header = \explode(':', $current_header, 2);
            $headers[\strtolower($current_header[0])] = \trim($current_header[1]);
        }
        $close = $protocol === 'HTTP/1.0';
        if (isset($headers['connection'])) {
            $close = \strtolower($headers['connection']) === 'close';
        }
        if ($code !== 200) {
            $read = '';
            if (isset($headers['content-length'])) {
                $read = (yield $buffer->bufferRead((int) $headers['content-length']));
            }
            if ($close) {
                $this->disconnect();
                (yield $this->connect($ctx));
            }
            \danog\MadelineProto\Logger::log(\trim($read));
            throw new \danog\MadelineProto\Exception($description, $code);
        }
        if ($close) {
            (yield $this->stream->disconnect());
            (yield $this->stream->connect($ctx));
        }
        if (isset($headers['content-length'])) {
            $length = (int) $headers['content-length'];
            $read = (yield $buffer->bufferRead($length));
        }
        if ($secure) {
            (yield $this->getSocket()->setupTls());
        }
        \danog\MadelineProto\Logger::log('Connected to ' . $address . ':' . $port . ' via http');
        if (\strlen($header)) {
            (yield ((yield $this->stream->getWriteBuffer(\strlen($header))))->bufferWrite($header));
        }
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return Promise
     */
    public function getWriteBuffer(int $length, string $append = '') : Promise
    {
        return $this->stream->getWriteBuffer($length, $append);
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return Promise
     */
    public function getReadBuffer(&$length) : Promise
    {
        return $this->stream->getReadBuffer($length);
    }
    /**
     *
     */
    public function read() : Promise
    {
        return $this->stream->read();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        return $this->stream->write($data);
    }
    /**
     *
     */
    private function getProxyAuthHeader() : string
    {
        if (!isset($this->extra['username']) || !isset($this->extra['password'])) {
            return '';
        }
        return 'Proxy-Authorization: Basic ' . \base64_encode($this->extra['username'] . ':' . $this->extra['password']) . "\r\n";
    }
    /**
     * Sets proxy data.
     *
     * @param array $extra Proxy data
     *
     * @return void
     */
    public function setExtra($extra)
    {
        $this->extra = $extra;
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Buffered proxy stream interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

/**
 * Buffered proxy stream interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface BufferedProxyStreamInterface extends BufferedStreamInterface, ProxyStreamInterface
{
}<?php

/**
 * ADNL stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\ADNLTransport;

use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
use danog\MadelineProto\Tools;
/**
 * ADNL stream wrapper.
 *
 * Manages ADNL envelope
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class ADNLStream implements BufferedStreamInterface, MTProtoBufferInterface
{
    use BufferedStream;
    private $stream;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->stream = (yield from $ctx->getStream($header));
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return \Generator
     */
    public function getWriteBufferGenerator(int $length, string $append = '') : \Generator
    {
        $length += 64;
        $buffer = (yield $this->stream->getWriteBuffer($length + 4, $append));
        (yield $buffer->bufferWrite(\pack('V', $length)));
        $this->stream->startWriteHash();
        $this->stream->checkWriteHash($length - 32);
        (yield $buffer->bufferWrite(Tools::random(32)));
        return $buffer;
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        $buffer = (yield $this->stream->getReadBuffer($l));
        $length = \unpack('V', (yield $buffer->bufferRead(4)))[1] - 32;
        $this->stream->startReadHash();
        $this->stream->checkReadHash($length);
        (yield $buffer->bufferRead(32));
        $length -= 32;
        return $buffer;
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Generic stream proxy interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

/**
 * Stream proxy interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface ProxyStreamInterface
{
    /**
     * Set extra proxy data.
     *
     * @param mixed $extra Proxy data
     *
     * @return void
     */
    public function setExtra($extra);
}<?php

/**
 * Buffered raw stream.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Common;

use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\BufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * Buffered raw stream, that simply returns less data on EOF instead of throwing.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class SimpleBufferedRawStream extends BufferedRawStream implements BufferedStreamInterface, BufferInterface, RawStreamInterface
{
    /**
     * Read data asynchronously.
     *
     * @param int $length Amount of data to read
     *
     * @return \Generator
     */
    public function bufferReadGenerator(int $length) : \Generator
    {
        $size = \fstat($this->memory_stream)['size'];
        $offset = \ftell($this->memory_stream);
        $buffer_length = $size - $offset;
        if ($buffer_length < $length && $buffer_length) {
            \fseek($this->memory_stream, $offset + $buffer_length);
        }
        while ($buffer_length < $length) {
            $chunk = (yield $this->read());
            if ($chunk === null) {
                break;
            }
            \fwrite($this->memory_stream, $chunk);
            $buffer_length += \strlen($chunk);
        }
        \fseek($this->memory_stream, $offset);
        return \fread($this->memory_stream, $length);
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     * Get class name.
     *
     * @return string
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Buffered raw stream.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Common;

use Amp\ByteStream\ClosedException;
use Amp\File\File;
use Amp\Promise;
use Amp\Socket\Socket;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\BufferInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\ProxyStreamInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * Buffered raw stream.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class FileBufferedStream implements BufferedStreamInterface, BufferInterface, ProxyStreamInterface, RawStreamInterface
{
    /**
     *
     */
    private File $stream;
    /**
     *
     */
    private int $append_after;
    /**
     *
     */
    private string $append;
    /**
     * Connect.
     *
     * @param ConnectionContext $ctx
     * @param string $header
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        if ($header !== '') {
            (yield $this->stream->write($header));
        }
    }
    /**
     * Async chunked read.
     *
     * @return Promise
     */
    public function read() : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        return $this->stream->read();
    }
    /**
     * Async write.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function write(string $data) : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        return $this->stream->write($data);
    }
    /**
     * Async write.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function end(string $finalData = '') : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        return $this->stream->end($finalData);
    }
    /**
     * Async close.
     *
     * @return void
     */
    public function disconnect()
    {
        if ($this->stream) {
            $this->stream = null;
        }
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return Promise
     */
    public function getReadBuffer(&$length) : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        return new \Amp\Success($this);
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Total length of data that is going to be piped in the buffer
     *
     * @return Promise
     */
    public function getWriteBuffer(int $length, string $append = '') : Promise
    {
        if (\strlen($append)) {
            $this->append = $append;
            $this->append_after = $length - \strlen($append);
        }
        return new \Amp\Success($this);
    }
    /**
     * Read data asynchronously.
     *
     * @param int $length Amount of data to read
     *
     * @return Promise
     */
    public function bufferRead(int $length) : Promise
    {
        return $this->stream->read($length);
    }
    /**
     * Async write.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function bufferWrite(string $data) : Promise
    {
        if ($this->append_after) {
            $this->append_after -= \strlen($data);
            if ($this->append_after === 0) {
                $data .= $this->append;
                $this->append = '';
            } elseif ($this->append_after < 0) {
                $this->append_after = 0;
                $this->append = '';
                throw new Exception('Tried to send too much out of frame data, cannot append');
            }
        }
        return $this->write($data);
    }
    /**
     * Set file handle.
     *
     * @param File $extra
     * @return void
     */
    public function setExtra($extra)
    {
        $this->stream = $extra;
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        throw new \RuntimeException("Can't get underlying RawStreamInterface, is a File handle!");
    }
    /**
     * {@inheritDoc}
     */
    public function getSocket() : Socket
    {
        throw new \RuntimeException("Can't get underlying socket, is a File handle!");
    }
    /**
     * Get class name.
     *
     * @return string
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Hash stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Common;

use Amp\Promise;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
use danog\MadelineProto\Stream\BufferInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * Hash stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class HashedBufferedStream implements BufferedProxyStreamInterface, BufferInterface
{
    use BufferedStream;
    private $hash_name;
    private $read_hash;
    private $write_hash;
    private $write_buffer;
    private $write_check_after = 0;
    private $write_check_pos = 0;
    private $read_buffer;
    private $read_check_after = 0;
    private $read_check_pos = 0;
    private $stream;
    private $rev = false;
    /**
     * Enable read hashing.
     *
     * @return void
     */
    public function startReadHash()
    {
        $this->read_hash = \hash_init($this->hash_name);
    }
    /**
     * Check the read hash after N bytes are read.
     *
     * @param int $after The number of bytes to read before checking the hash
     *
     * @return void
     */
    public function checkReadHash(int $after)
    {
        $this->read_check_after = $after;
    }
    /**
     * Stop read hashing and get final hash.
     *
     * @return string
     */
    public function getReadHash() : string
    {
        $hash = \hash_final($this->read_hash, true);
        if ($this->rev) {
            $hash = \strrev($hash);
        }
        $this->read_hash = null;
        $this->read_check_after = 0;
        $this->read_check_pos = 0;
        return $hash;
    }
    /**
     * Check if we are read hashing.
     *
     * @return bool
     */
    public function hasReadHash() : bool
    {
        return $this->read_hash !== null;
    }
    /**
     * Enable write hashing.
     *
     * @return void
     */
    public function startWriteHash()
    {
        $this->write_hash = \hash_init($this->hash_name);
    }
    /**
     * Write the write hash after N bytes are read.
     *
     * @param int $after The number of bytes to read before writing the hash
     *
     * @return void
     */
    public function checkWriteHash(int $after)
    {
        $this->write_check_after = $after;
    }
    /**
     * Stop write hashing and get final hash.
     *
     * @return string
     */
    public function getWriteHash() : string
    {
        $hash = \hash_final($this->write_hash, true);
        if ($this->rev) {
            $hash = \strrev($hash);
        }
        $this->write_hash = null;
        $this->write_check_after = 0;
        $this->write_check_pos = 0;
        return $hash;
    }
    /**
     * Check if we are write hashing.
     *
     * @return bool
     */
    public function hasWriteHash() : bool
    {
        return $this->write_hash !== null;
    }
    /**
     * Hashes read data asynchronously.
     *
     * @param int $length Read and hash $length bytes
     *
     * @return \Generator That resolves with a string when the provided promise is resolved and the data is added to the hashing context
     */
    public function bufferReadGenerator(int $length) : \Generator
    {
        if ($this->read_check_after && $length + $this->read_check_pos >= $this->read_check_after) {
            if ($length + $this->read_check_pos > $this->read_check_after) {
                throw new \danog\MadelineProto\Exception('Tried to read too much out of frame data');
            }
            $data = (yield $this->read_buffer->bufferRead($length));
            \hash_update($this->read_hash, $data);
            $hash = $this->getReadHash();
            if ($hash !== (yield $this->read_buffer->bufferRead(\strlen($hash)))) {
                throw new \danog\MadelineProto\Exception('Hash mismatch');
            }
            return $data;
        }
        $data = (yield $this->read_buffer->bufferRead($length));
        \hash_update($this->read_hash, $data);
        if ($this->read_check_after) {
            $this->read_check_pos += $length;
        }
        return $data;
    }
    /**
     * Set the hash algorithm.
     *
     * @param string $hash Algorithm name
     *
     * @return void
     */
    public function setExtra($hash)
    {
        $rev = \strpos($hash, '_rev');
        $this->rev = false;
        if ($rev !== false) {
            $hash = \Phabel\Target\Php80\Polyfill::substr($hash, 0, $rev);
            $this->rev = true;
        }
        $this->hash_name = $hash;
    }
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->write_hash = null;
        $this->write_check_after = 0;
        $this->write_check_pos = 0;
        $this->read_hash = null;
        $this->read_check_after = 0;
        $this->read_check_pos = 0;
        $this->stream = (yield from $ctx->getStream($header));
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        //if ($this->read_hash) {
        $this->read_buffer = (yield $this->stream->getReadBuffer($length));
        return $this;
        //}
        //return yield $this->stream->getReadBuffer($length);
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return \Generator
     */
    public function getWriteBufferGenerator(int $length, string $append = '') : \Generator
    {
        //if ($this->write_hash) {
        $this->write_buffer = (yield $this->stream->getWriteBuffer($length, $append));
        return $this;
        //}
        //return yield $this->stream->getWriteBuffer($length, $append);
    }
    /**
     * Reads data from the stream.
     *
     * @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
     */
    public function bufferRead(int $length) : Promise
    {
        if ($this->read_hash === null) {
            return $this->read_buffer->bufferRead($length);
        }
        return \danog\MadelineProto\Tools::call($this->bufferReadGenerator($length));
    }
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     */
    public function bufferWrite(string $data) : Promise
    {
        if ($this->write_hash === null) {
            return $this->write_buffer->bufferWrite($data);
        }
        $length = \strlen($data);
        if ($this->write_check_after && $length + $this->write_check_pos >= $this->write_check_after) {
            if ($length + $this->write_check_pos > $this->write_check_after) {
                throw new \danog\MadelineProto\Exception('Too much out of frame data was sent, cannot check hash');
            }
            \hash_update($this->write_hash, $data);
            return $this->write_buffer->bufferWrite($data . $this->getWriteHash());
        }
        if ($this->write_check_after) {
            $this->write_check_pos += $length;
        }
        if ($this->write_hash) {
            \hash_update($this->write_hash, $data);
        }
        return $this->write_buffer->bufferWrite($data);
    }
    /**
     * {@inheritdoc}
     *
     * @return \Amp\Socket\Socket
     */
    public function getSocket() : \Amp\Socket\Socket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * AES CTR stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Common;

use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use danog\MadelineProto\Stream\Async\Buffer;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
use danog\MadelineProto\Stream\BufferInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\RawStreamInterface;
use phpseclib3\Crypt\AES;
/**
 * AES CTR stream wrapper.
 *
 * Manages AES CTR encryption/decryption
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class CtrStream implements BufferedProxyStreamInterface, BufferInterface
{
    use Buffer;
    use BufferedStream;
    private $encrypt;
    private $decrypt;
    private $stream;
    private $write_buffer;
    private $read_buffer;
    private $extra;
    private $append = '';
    private $append_after = 0;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->encrypt = new \phpseclib3\Crypt\AES('ctr');
        $this->encrypt->enableContinuousBuffer();
        $this->encrypt->setKey($this->extra['encrypt']['key']);
        $this->encrypt->setIV($this->extra['encrypt']['iv']);
        $this->decrypt = new \phpseclib3\Crypt\AES('ctr');
        $this->decrypt->enableContinuousBuffer();
        $this->decrypt->setKey($this->extra['decrypt']['key']);
        $this->decrypt->setIV($this->extra['decrypt']['iv']);
        $this->stream = (yield from $ctx->getStream($header));
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return \Generator
     */
    public function getWriteBufferGenerator(int $length, string $append = '') : \Generator
    {
        $this->write_buffer = (yield $this->stream->getWriteBuffer($length));
        if (\strlen($append)) {
            $this->append = $append;
            $this->append_after = $length - \strlen($append);
        }
        return $this;
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        $this->read_buffer = (yield $this->stream->getReadBuffer($length));
        return $this;
    }
    /**
     * Decrypts read data asynchronously.
     *
     * @param Promise $promise Promise that resolves with a string when new data is available or `null` if the stream has closed.
     *
     * @return \Generator That resolves with a string when the provided promise is resolved and the data is decrypted
     */
    public function bufferReadGenerator(int $length) : \Generator
    {
        return @$this->decrypt->encrypt((yield $this->read_buffer->bufferRead($length)));
    }
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     */
    public function bufferWrite(string $data) : Promise
    {
        if ($this->append_after) {
            $this->append_after -= \strlen($data);
            if ($this->append_after === 0) {
                $data .= $this->append;
                $this->append = '';
            } elseif ($this->append_after < 0) {
                $this->append_after = 0;
                $this->append = '';
                throw new \danog\MadelineProto\Exception('Tried to send too much out of frame data, cannot append');
            }
        }
        return $this->write_buffer->bufferWrite(@$this->encrypt->encrypt($data));
    }
    /**
     * Set obfuscation keys/IVs.
     *
     * @param array $data Keys
     *
     * @return void
     */
    public function setExtra($data)
    {
        $this->extra = $data;
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public function getEncryptor() : AES
    {
        return $this->encrypt;
    }
    /**
     *
     */
    public function getDecryptor() : AES
    {
        return $this->decrypt;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Buffered raw stream.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Common;

use Amp\ByteStream\ClosedException;
use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Stream\Async\RawStream;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\BufferInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * Buffered raw stream.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class BufferedRawStream implements BufferedStreamInterface, BufferInterface, RawStreamInterface
{
    use RawStream;
    private const MAX_SIZE = 10 * 1024 * 1024;
    protected $stream;
    protected $memory_stream;
    private $append = '';
    private $append_after = 0;
    /**
     * Asynchronously connect to a TCP/TLS server.
     *
     * @param ConnectionContext $ctx Connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->stream = (yield from $ctx->getStream($header));
        $this->memory_stream = \fopen('php://memory', 'r+');
        return true;
    }
    /**
     * Async chunked read.
     *
     * @return Promise
     */
    public function read() : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        return $this->stream->read();
    }
    /**
     * Async write.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function write(string $data) : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        return $this->stream->write($data);
    }
    /**
     * Async close.
     *
     * @return void
     */
    public function disconnect()
    {
        if ($this->memory_stream) {
            \fclose($this->memory_stream);
            $this->memory_stream = null;
        }
        if ($this->stream) {
            $this->stream->disconnect();
            $this->stream = null;
        }
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return Promise
     */
    public function getReadBuffer(&$length) : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        $size = \fstat($this->memory_stream)['size'];
        $offset = \ftell($this->memory_stream);
        $length = $size - $offset;
        if ($length === 0 || $size > self::MAX_SIZE) {
            $new_memory_stream = \fopen('php://memory', 'r+');
            if ($length) {
                \fwrite($new_memory_stream, \fread($this->memory_stream, $length));
                \fseek($new_memory_stream, 0);
            }
            \fclose($this->memory_stream);
            $this->memory_stream = $new_memory_stream;
        }
        return new \Amp\Success($this);
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Total length of data that is going to be piped in the buffer
     *
     * @return Promise
     */
    public function getWriteBuffer(int $length, string $append = '') : Promise
    {
        if (\strlen($append)) {
            $this->append = $append;
            $this->append_after = $length - \strlen($append);
        }
        return new \Amp\Success($this);
    }
    /**
     * Read data asynchronously.
     *
     * @param int $length Amount of data to read
     *
     * @return Promise
     */
    public function bufferRead(int $length) : Promise
    {
        if (!$this->stream) {
            throw new ClosedException("MadelineProto stream was disconnected");
        }
        $size = \fstat($this->memory_stream)['size'];
        $offset = \ftell($this->memory_stream);
        $buffer_length = $size - $offset;
        if ($buffer_length >= $length) {
            return new Success(\fread($this->memory_stream, $length));
        }
        return \danog\MadelineProto\Tools::call($this->bufferReadGenerator($length));
    }
    /**
     * Read data asynchronously.
     *
     * @param int $length Amount of data to read
     *
     * @return \Generator
     */
    public function bufferReadGenerator(int $length) : \Generator
    {
        $size = \fstat($this->memory_stream)['size'];
        $offset = \ftell($this->memory_stream);
        $buffer_length = $size - $offset;
        if ($buffer_length < $length && $buffer_length) {
            \fseek($this->memory_stream, $offset + $buffer_length);
        }
        while ($buffer_length < $length) {
            $chunk = (yield $this->read());
            if ($chunk === null) {
                $this->disconnect();
                throw new \danog\MadelineProto\NothingInTheSocketException();
            }
            \fwrite($this->memory_stream, $chunk);
            $buffer_length += \strlen($chunk);
        }
        \fseek($this->memory_stream, $offset);
        return \fread($this->memory_stream, $length);
    }
    /**
     * Async write.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function bufferWrite(string $data) : Promise
    {
        if ($this->append_after) {
            $this->append_after -= \strlen($data);
            if ($this->append_after === 0) {
                $data .= $this->append;
                $this->append = '';
            } elseif ($this->append_after < 0) {
                $this->append_after = 0;
                $this->append = '';
                throw new Exception('Tried to send too much out of frame data, cannot append');
            }
        }
        return $this->write($data);
    }
    /**
     * Get remaining data from buffer.
     *
     * @return string
     */
    public function bufferClear() : string
    {
        $size = \fstat($this->memory_stream)['size'];
        $offset = \ftell($this->memory_stream);
        $buffer_length = $size - $offset;
        $data = \fread($this->memory_stream, $buffer_length);
        \fclose($this->memory_stream);
        $this->memory_stream = null;
        return $data;
    }
    /**
     * {@inheritdoc}
     *
     * @return \Amp\Socket\Socket
     */
    public function getSocket() : \Amp\Socket\Socket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     * Get class name.
     *
     * @return string
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * UDP stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\Common;

use Amp\ByteStream\ClosedException;
use Amp\Failure;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Success;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
use danog\MadelineProto\Stream\ReadBufferInterface;
use danog\MadelineProto\Stream\Transport\DefaultStream;
use danog\MadelineProto\Stream\WriteBufferInterface;
/**
 * UDP stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class UdpBufferedStream extends DefaultStream implements BufferedStreamInterface, MTProtoBufferInterface
{
    use BufferedStream;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->stream = (yield from $ctx->getStream($header));
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, Promise, mixed, (Failure<mixed> | Success<object>)>
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        if (!$this->stream) {
            return new Failure(new ClosedException("MadelineProto stream was disconnected"));
        }
        $chunk = (yield $this->read());
        if ($chunk === null) {
            $this->disconnect();
            throw new \danog\MadelineProto\NothingInTheSocketException();
        }
        $length = \strlen($chunk);
        return new Success(new class($chunk) implements ReadBufferInterface
        {
            /**
             * Buffer.
             *
             * @var resource
             */
            private $buffer;
            /**
             * Constructor function.
             *
             * @param string $buf Buffer
             */
            public function __construct(string $buf)
            {
                $this->buffer = \fopen('php://memory', 'r+');
                \fwrite($this->buffer, $buf);
                \fseek($this->buffer, 0);
            }
            /**
             * Read data from buffer.
             *
             * @param integer $length Length
             *
             * @return Promise<string>
             */
            public function bufferRead(int $length) : Promise
            {
                return new Success(\fread($this->buffer, $length));
            }
            /**
             * Destructor function.
             */
            public function __destruct()
            {
                \fclose($this->buffer);
            }
        });
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Total length of data that is going to be piped in the buffer
     *
     * @return Promise
     */
    public function getWriteBuffer(int $length, string $append = '') : Promise
    {
        return new Success(new class($length, $append, $this) implements WriteBufferInterface
        {
            /**
             *
             */
            private int $length;
            /**
             *
             */
            private string $append;
            /**
             *
             */
            private int $append_after;
            /**
             *
             */
            private RawStreamInterface $stream;
            /**
             *
             */
            private string $data = '';
            /**
             * Constructor function.
             *
             * @param integer $length
             * @param string $append
             * @param RawStreamInterface $rawStreamInterface
             */
            public function __construct(int $length, string $append, RawStreamInterface $rawStreamInterface)
            {
                $this->stream = $rawStreamInterface;
                $this->length = $length;
                if (\strlen($append)) {
                    $this->append = $append;
                    $this->append_after = $length - \strlen($append);
                }
            }
            /**
             * Async write.
             *
             * @param string $data Data to write
             *
             * @return Promise
             */
            public function bufferWrite(string $data) : Promise
            {
                $this->data .= $data;
                if ($this->append_after) {
                    $this->append_after -= \strlen($data);
                    if ($this->append_after === 0) {
                        $this->data .= $this->append;
                        $this->append = '';
                        return $this->stream->write($this->data);
                    } elseif ($this->append_after < 0) {
                        $this->append_after = 0;
                        $this->append = '';
                        throw new Exception('Tried to send too much out of frame data, cannot append');
                    }
                }
                return new Success(\strlen($data));
            }
        });
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Raw stream interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
/**
 * Raw stream interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface RawStreamInterface extends InputStream, OutputStream, StreamInterface
{
}<?php

/**
 * Buffer interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

use Amp\Promise;
/**
 * Write buffer interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface WriteBufferInterface
{
    /**
     * Write data asynchronously.
     *
     * @param string $data Data to write
     *
     * @return Promise
     */
    public function bufferWrite(string $data) : Promise;
}<?php

/**
 * Generic stream interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

use Amp\Socket\EncryptableSocket;
use Amp\Socket\Socket;
/**
 * Generic stream interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface StreamInterface
{
    /**
     * Connect to a server.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator;
    /**
     * Disconnect from the server.
     *
     * @return void
     */
    public function disconnect();
    /**
     * Get underlying AMPHP socket resource.
     *
     * @return EncryptableSocket
     */
    public function getSocket() : Socket;
}<?php

/**
 * Buffer interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

use Amp\Promise;
/**
 * Read buffer interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface ReadBufferInterface
{
    /**
     * Read data asynchronously.
     *
     * @param int $length How much data to read
     *
     * @return Promise
     */
    public function bufferRead(int $length) : Promise;
}<?php

/**
 * Buffered stream interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

use Amp\Promise;
/**
 * Buffered stream interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface BufferedStreamInterface extends StreamInterface
{
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return Promise
     * @psalm-return Promise<BufferInterface>
     */
    public function getReadBuffer(&$length) : Promise;
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Total length of data that is going to be piped in the buffer
     *
     * @return Promise
     */
    public function getWriteBuffer(int $length, string $append = '') : Promise;
    /**
     * Get stream name.
     *
     * Is supposed to return __CLASS__
     *
     * @return string
     */
    public static function getName() : string;
    /**
     * Get underlying stream resource.
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface;
}<?php

/**
 * Buffer interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

/**
 * Buffer interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface BufferInterface extends ReadBufferInterface, WriteBufferInterface
{
}<?php

/**
 * Raw stream proxy interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

/**
 * Raw stream proxy interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface RawProxyStreamInterface extends RawStreamInterface, ProxyStreamInterface
{
}<?php

/**
 * MTProto buffer interface.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream;

/**
 * MTProto buffer interface, for reading transport MTProto header info.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface MTProtoBufferInterface
{
}<?php

/**
 * Abridged stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\MTProtoTransport;

use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * Abridged stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class AbridgedStream implements BufferedStreamInterface, MTProtoBufferInterface
{
    use BufferedStream;
    private $stream;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->stream = (yield from $ctx->getStream(\chr(239) . $header));
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return \Generator
     */
    public function getWriteBufferGenerator(int $length, string $append = '') : \Generator
    {
        $length >>= 2;
        if ($length < 127) {
            $message = \chr($length);
        } else {
            $message = \chr(127) . \Phabel\Target\Php80\Polyfill::substr(\pack('V', $length), 0, 3);
        }
        $buffer = (yield $this->stream->getWriteBuffer(\strlen($message) + $length, $append));
        (yield $buffer->bufferWrite($message));
        return $buffer;
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        $buffer = (yield $this->stream->getReadBuffer($l));
        $length = \ord((yield $buffer->bufferRead(1)));
        if ($length >= 127) {
            $length = \unpack('V', (yield $buffer->bufferRead(3)) . "\x00")[1];
        }
        $length <<= 2;
        return $buffer;
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Obfuscated2 stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\MTProtoTransport;

use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
use danog\MadelineProto\Stream\Common\CtrStream;
use danog\MadelineProto\Stream\ConnectionContext;
/**
 * Obfuscated2 stream wrapper.
 *
 * Manages obfuscated2 encryption/decryption
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class ObfuscatedStream extends CtrStream implements BufferedProxyStreamInterface
{
    private $stream;
    private $extra;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        if (isset($this->extra['address'])) {
            $ctx = $ctx->getCtx();
            $ctx->setUri('tcp://' . $this->extra['address'] . ':' . $this->extra['port']);
        }
        do {
            $random = \danog\MadelineProto\Tools::random(64);
        } while (\in_array(\Phabel\Target\Php80\Polyfill::substr($random, 0, 4), ['PVrG', 'GET ', 'POST', 'HEAD', \str_repeat(\chr(238), 4), \str_repeat(\chr(221), 4)]) || $random[0] === \chr(0xef) || \Phabel\Target\Php80\Polyfill::substr($random, 4, 4) === "\x00\x00\x00\x00");
        if (\strlen($header) === 1) {
            $header = \str_repeat($header, 4);
        }
        $random = \Phabel\Target\Php80\Polyfill::substr_replace($random, $header . \Phabel\Target\Php80\Polyfill::substr($random, 56 + \strlen($header)), 56);
        $random = \Phabel\Target\Php80\Polyfill::substr_replace($random, \pack('s', $ctx->getIntDc()) . \Phabel\Target\Php80\Polyfill::substr($random, 60 + 2), 60);
        $reversed = \strrev($random);
        $key = \Phabel\Target\Php80\Polyfill::substr($random, 8, 32);
        $keyRev = \Phabel\Target\Php80\Polyfill::substr($reversed, 8, 32);
        if (isset($this->extra['secret'])) {
            $key = \hash('sha256', $key . $this->extra['secret'], true);
            $keyRev = \hash('sha256', $keyRev . $this->extra['secret'], true);
        }
        $iv = \Phabel\Target\Php80\Polyfill::substr($random, 40, 16);
        $ivRev = \Phabel\Target\Php80\Polyfill::substr($reversed, 40, 16);
        parent::setExtra(['encrypt' => ['key' => $key, 'iv' => $iv], 'decrypt' => ['key' => $keyRev, 'iv' => $ivRev]]);
        yield from parent::connect($ctx);
        $random = \Phabel\Target\Php80\Polyfill::substr_replace($random, \Phabel\Target\Php80\Polyfill::substr(@$this->getEncryptor()->encrypt($random), 56, 8), 56, 8);
        (yield $this->getStream()->write($random));
    }
    /**
     * Set extra.
     *
     * @param array $extra Extra
     *
     * @return void
     */
    public function setExtra($extra)
    {
        if (isset($extra['secret'])) {
            if (\strlen($extra['secret']) > 17) {
                $extra['secret'] = \hex2bin($extra['secret']);
            }
            if (\strlen($extra['secret']) == 17) {
                $extra['secret'] = \Phabel\Target\Php80\Polyfill::substr($extra['secret'], 1, 16);
            }
        }
        $this->extra = $extra;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * TCP Intermediate stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\MTProtoTransport;

use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * TCP Intermediate stream wrapper.
 *
 * Manages obfuscated2 encryption/decryption
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class IntermediateStream implements BufferedStreamInterface, MTProtoBufferInterface
{
    use BufferedStream;
    private $stream;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->stream = (yield from $ctx->getStream(\str_repeat(\chr(238), 4) . $header));
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return \Generator
     */
    public function getWriteBufferGenerator(int $length, string $append = '') : \Generator
    {
        $buffer = (yield $this->stream->getWriteBuffer($length + 4, $append));
        (yield $buffer->bufferWrite(\pack('V', $length)));
        return $buffer;
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        $buffer = (yield $this->stream->getReadBuffer($l));
        $length = \unpack('V', (yield $buffer->bufferRead(4)))[1];
        return $buffer;
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * HTTP stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\MTProtoTransport;

use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Success;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedProxyStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
use Psr\Http\Message\UriInterface;
/**
 * HTTP stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class HttpStream implements MTProtoBufferInterface, BufferedProxyStreamInterface
{
    use BufferedStream;
    /**
     * Stream.
     *
     * @var RawStreamInterface
     */
    protected $stream;
    private $code;
    private $ctx;
    private $header = '';
    /**
     * URI of the HTTP API.
     */
    private UriInterface $uri;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->ctx = $ctx->getCtx();
        $this->stream = (yield from $ctx->getStream($header));
        $this->uri = $ctx->getUri();
    }
    /**
     * Set proxy data.
     *
     * @param array $extra Proxy parameters
     *
     * @return void
     */
    public function setExtra($extra)
    {
        if (isset($extra['user']) && isset($extra['password'])) {
            $this->header = \base64_encode($extra['user'] . ':' . $extra['password']) . "\r\n";
        }
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return \Generator
     */
    public function getWriteBufferGenerator(int $length, string $append = '') : \Generator
    {
        $headers = 'POST ' . $this->uri->getPath() . " HTTP/1.1\r\nHost: " . $this->uri->getHost() . ':' . $this->uri->getPort() . '
Content-Type: application/x-www-form-urlencoded
Connection: keep-alive
Keep-Alive: timeout=100000, max=10000000
Content-Length: ' . $length . $this->header . "\r\n\r\n";
        $buffer = (yield $this->stream->getWriteBuffer(\strlen($headers) + $length, $append));
        (yield $buffer->bufferWrite($headers));
        return $buffer;
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        $buffer = (yield $this->stream->getReadBuffer($l));
        $headers = '';
        $was_crlf = false;
        while (true) {
            $piece = (yield $buffer->bufferRead(2));
            $headers .= $piece;
            if ($piece === "\n\r") {
                // Assume end of headers with \r\n\r\n
                $headers .= (yield $buffer->bufferRead(1));
                break;
            }
            if ($was_crlf && $piece === "\r\n") {
                break;
            }
            $was_crlf = $piece === "\r\n";
        }
        $headers = \explode("\r\n", $headers);
        list($protocol, $code, $description) = \explode(' ', $headers[0], 3);
        list($protocol, $protocol_version) = \explode('/', $protocol);
        if ($protocol !== 'HTTP') {
            throw new \danog\MadelineProto\Exception('Wrong protocol');
        }
        $code = (int) $code;
        unset($headers[0]);
        if (\array_pop($headers) . \array_pop($headers) !== '') {
            throw new \danog\MadelineProto\Exception('Wrong last header');
        }
        foreach ($headers as $key => $current_header) {
            unset($headers[$key]);
            $current_header = \explode(':', $current_header, 2);
            $headers[\strtolower($current_header[0])] = \trim($current_header[1]);
        }
        $close = $protocol === 'HTTP/1.0';
        if (isset($headers['connection'])) {
            $close = \strtolower($headers['connection']) === 'close';
        }
        if ($code !== 200) {
            $read = '';
            if (isset($headers['content-length'])) {
                $read = (yield $buffer->bufferRead((int) $headers['content-length']));
            }
            if ($close) {
                $this->disconnect();
                yield from $this->connect($this->ctx);
            }
            \danog\MadelineProto\Logger::log($read);
            $this->code = \danog\MadelineProto\Tools::packSignedInt(-$code);
            $length = 4;
            return $this;
        }
        if ($close) {
            $this->stream->disconnect();
            (yield $this->stream->connect($this->ctx));
        }
        if (isset($headers['content-length'])) {
            $length = (int) $headers['content-length'];
        }
        return $buffer;
    }
    /**
     *
     */
    public function bufferRead(int $length) : Promise
    {
        return new Success($this->code);
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * HTTPS stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\MTProtoTransport;

use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * HTTPS stream wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class HttpsStream extends HttpStream implements MTProtoBufferInterface
{
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        return parent::connect($ctx->getCtx()->secure(true), $header);
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * TCP full stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\MTProtoTransport;

use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\Common\HashedBufferedStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * TCP full stream wrapper.
 *
 * Manages obfuscated2 encryption/decryption
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class FullStream implements BufferedStreamInterface, MTProtoBufferInterface
{
    use BufferedStream;
    private $stream;
    private $in_seq_no = -1;
    private $out_seq_no = -1;
    /**
     * Stream to use as data source.
     *
     * @param ConnectionContext $ctx
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->in_seq_no = -1;
        $this->out_seq_no = -1;
        $this->stream = new HashedBufferedStream();
        $this->stream->setExtra('crc32b_rev');
        return $this->stream->connect($ctx, $header);
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return \Generator
     */
    public function getWriteBufferGenerator(int $length, string $append = '') : \Generator
    {
        $this->stream->startWriteHash();
        $this->stream->checkWriteHash($length + 8);
        $buffer = (yield $this->stream->getWriteBuffer($length + 12, $append));
        $this->out_seq_no++;
        $buffer->bufferWrite(\pack('VV', $length + 12, $this->out_seq_no));
        return $buffer;
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        $this->stream->startReadHash();
        $buffer = (yield $this->stream->getReadBuffer($l));
        $read_length = \unpack('V', (yield $buffer->bufferRead(4)))[1];
        $length = $read_length - 12;
        $this->stream->checkReadHash($read_length - 8);
        $this->in_seq_no++;
        $in_seq_no = \unpack('V', (yield $buffer->bufferRead(4)))[1];
        if ($in_seq_no != $this->in_seq_no) {
            throw new \danog\MadelineProto\Exception('Incoming seq_no mismatch');
        }
        return $buffer;
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * TCP Intermediate stream wrapper.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Stream\MTProtoTransport;

use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use danog\MadelineProto\Stream\Async\BufferedStream;
use danog\MadelineProto\Stream\BufferedStreamInterface;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\RawStreamInterface;
/**
 * TCP Intermediate stream wrapper.
 *
 * Manages obfuscated2 encryption/decryption
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class IntermediatePaddedStream implements BufferedStreamInterface, MTProtoBufferInterface
{
    use BufferedStream;
    private $stream;
    /**
     * Connect to stream.
     *
     * @param ConnectionContext $ctx The connection context
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, string $header = '') : \Generator
    {
        $this->stream = (yield from $ctx->getStream(\str_repeat(\chr(221), 4) . $header));
    }
    /**
     * Async close.
     *
     * @return Promise
     */
    public function disconnect()
    {
        return $this->stream->disconnect();
    }
    /**
     * Get write buffer asynchronously.
     *
     * @param int $length Length of data that is going to be written to the write buffer
     *
     * @return \Generator
     */
    public function getWriteBufferGenerator(int $length, string $append = '') : \Generator
    {
        $padding_length = \danog\MadelineProto\Tools::randomInt($modulus = 16);
        $buffer = (yield $this->stream->getWriteBuffer(4 + $length + $padding_length, $append . \danog\MadelineProto\Tools::random($padding_length)));
        (yield $buffer->bufferWrite(\pack('V', $padding_length + $length)));
        return $buffer;
    }
    /**
     * Get read buffer asynchronously.
     *
     * @param int $length Length of payload, as detected by this layer
     *
     * @return \Generator
     */
    public function getReadBufferGenerator(&$length) : \Generator
    {
        $buffer = (yield $this->stream->getReadBuffer($l));
        $length = \unpack('V', (yield $buffer->bufferRead(4)))[1];
        return $buffer;
    }
    /**
     * {@inheritdoc}
     *
     * @return EncryptableSocket
     */
    public function getSocket() : EncryptableSocket
    {
        return $this->stream->getSocket();
    }
    /**
     * {@inheritDoc}
     *
     * @return RawStreamInterface
     */
    public function getStream() : RawStreamInterface
    {
        return $this->stream;
    }
    /**
     *
     */
    public static function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * EventHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use danog\MadelineProto\Db\DbPropertiesTrait;
/**
 * Event handler.
 */
abstract class EventHandler extends InternalDoc
{
    use DbPropertiesTrait {
        DbPropertiesTrait::initDb as private internalInitDb;
    }
    /**
     * Whether the event handler was started.
     */
    private bool $startedInternal = false;
    /**
     * API instance.
     */
    protected MTProto $API;
    /**
     *
     */
    public function __construct($API)
    {
    }
    /**
     * Start MadelineProto and the event handler (enables async).
     *
     * Also initializes error reporting, catching and reporting all errors surfacing from the event loop.
     *
     * @param string $session Session name
     * @param SettingsAbstract $settings Settings
     *
     * @return void
     */
    public static final function startAndLoop(string $session, SettingsAbstract $settings) : void
    {
        $API = new API($session, $settings);
        $API->startAndLoop(static::class);
    }
    /**
     * Internal constructor.
     *
     * @internal
     *
     * @param APIWrapper $MadelineProto MadelineProto instance
     *
     * @return void
     */
    public function initInternal(APIWrapper $MadelineProto) : void
    {
        self::link($this, $MadelineProto->getFactory());
        $this->API =& $MadelineProto->getAPI();
        foreach ($this->API->getMethodNamespaces() as $namespace) {
            $this->{$namespace} = $this->exportNamespace($namespace);
        }
    }
    /**
     * Start method handler.
     *
     * @internal
     *
     * @return \Generator
     */
    public function startInternal() : \Generator
    {
        if ($this->startedInternal) {
            return;
        }
        if (isset(static::$dbProperties)) {
            yield from $this->internalInitDb($this->API);
        }
        if (\method_exists($this, 'onStart')) {
            (yield $this->onStart());
        }
        $this->startedInternal = true;
    }
    /**
     * Get peers where to send error reports.
     *
     * @return (array | string | int)
     */
    public function getReportPeers()
    {
        return [];
    }
    /**
     * Get API instance.
     *
     * @return MTProto
     */
    public function getAPI() : MTProto
    {
        return $this->API;
    }
}<?php

/**
 * API wrapper module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Ipc\Client;
use function Amp\File\openFile;
final class APIWrapper
{
    /**
     * MTProto instance.
     *
     * @var MTProto|null|Client
     */
    private $API = null;
    /**
     * Session path.
     */
    public SessionPaths $session;
    /**
     * Getting API ID flag.
     *
     * @var bool
     */
    private bool $gettingApiId = false;
    /**
     * Web API template.
     *
     * @var string
     */
    private string $webApiTemplate = '';
    /**
     * My.telegram.org wrapper.
     *
     * @var ?MyTelegramOrgWrapper
     */
    private $myTelegramOrgWrapper;
    /**
     * Serialization date.
     *
     * @var integer
     */
    private int $serialized = 0;
    /**
     * Whether lua is being used.
     *
     * @internal
     *
     * @var boolean
     */
    private bool $lua = false;
    /**
     * Whether async is enabled.
     *
     * @internal
     *
     * @var boolean
     */
    private bool $async = false;
    /**
     * AbstractAPIFactory instance.
     *
     * @var AbstractAPIFactory
     */
    private AbstractAPIFactory $factory;
    /**
     * Property storage.
     */
    public array $storage = [];
    /**
     * API wrapper.
     *
     * @param API $API API instance to wrap
     * @param AbstractAPIFactory $factory Factory
     */
    public function __construct(API $API, AbstractAPIFactory $factory)
    {
        self::link($this, $API);
        $this->factory = $factory;
    }
    /**
     * Link two APIWrapper and API instances.
     *
     * @param (API | APIWrapper) $a Instance to which link
     * @param (API | APIWrapper) $b Instance from which link
     *
     * @return void
     */
    public static function link($a, $b) : void
    {
        foreach (self::properties() as $var) {
            Tools::setVar($a, $var, Tools::getVar($b, $var));
        }
        Tools::setVar($a, 'session', Tools::getVar($b, 'session'));
    }
    /**
     * Property list.
     *
     * @return array
     */
    public static function properties() : array
    {
        return ['API', 'webApiTemplate', 'gettingApiId', 'myTelegramOrgWrapper', 'storage', 'lua'];
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep() : array
    {
        return self::properties();
    }
    /**
     * Get MTProto instance.
     *
     * @return (Client | MTProto | null)
     */
    public function &getAPI()
    {
        return $this->API;
    }
    /**
     * Whether async is being used.
     *
     * @return boolean
     */
    public function isAsync() : bool
    {
        return $this->async;
    }
    /**
     * Get API factory.
     *
     * @return AbstractAPIFactory
     */
    public function getFactory() : AbstractAPIFactory
    {
        return $this->factory;
    }
    /**
     * Get IPC path.
     *
     * @internal
     *
     * @return string
     */
    public function getIpcPath() : string
    {
        return $this->session->getIpcPath();
    }
    /**
     * Serialize session.
     *
     * @return Promise<bool>
     */
    public function serialize() : Promise
    {
        if ($this->API === null && !$this->gettingApiId) {
            return new Success(false);
        }
        if ($this->API instanceof Client) {
            return new Success(false);
        }
        return Tools::callFork((function () : \Generator {
            if ($this->API) {
                yield from $this->API->initAsynchronously();
            }
            yield from $this->session->serialize($this->API ? yield from $this->API->serializeSession($this) : $this, $this->session->getSessionPath());
            if ($this->API) {
                yield from $this->session->storeLightState($this->API);
            }
            // Truncate legacy session
            (yield ((yield openFile($this->session->getLegacySessionPath(), 'w')))->close());
            if (!Magic::$suspendPeriodicLogging) {
                Logger::log('Saved session!');
            }
            return true;
        })());
    }
    /**
     * Get session path.
     *
     * @return SessionPaths
     */
    public function getSession() : SessionPaths
    {
        return $this->session;
    }
}<?php

/**
 * VoIPServerConfig.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

if (\class_exists(VoIPServerConfig::class)) {
    return;
}
/**
 * Manages storage of VoIP server config.
 */
class VoIPServerConfig
{
    /**
     * The configuration.
     *
     * @var array
     */
    private static $_config = [];
    /**
     * The default configuration.
     *
     * @var array
     */
    private static $_configDefault = [];
    /**
     * Update shared call settings.
     *
     * @param array $config The settings
     *
     * @return void
     */
    public static function update(array $config)
    {
        self::$_config = $config;
    }
    /**
     * Get shared call settings.
     *
     * @return array The settings
     */
    public static function get() : array
    {
        return self::$_config;
    }
    /**
     * Update default shared call settings.
     *
     * @param array $configDefault The settings
     *
     * @return void
     */
    public static function updateDefault(array $configDefault)
    {
        self::$_configDefault = $configDefault;
    }
    /**
     * Get default shared call settings.
     *
     * @return array The settings
     */
    public static function getDefault() : array
    {
        return self::$_configDefault;
    }
    /**
     * Get final settings.
     *
     * @return array
     */
    public static function getFinal() : array
    {
        return \array_merge(self::$_configDefault, self::$_config);
    }
}<?php

/**
 * IPC light state.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * Light state.
 *
 * @internal
 */
final class LightState
{
    /**
     * Event handler class name.
     *
     * @var (null | class-string<EventHandler>)
     */
    private ?string $eventHandler = null;
    /**
     *
     */
    public function __construct(MTProto $API)
    {
        if ($API->hasEventHandler()) {
            $this->eventHandler = \get_class($API->getEventHandler());
        }
    }
    /**
     * Check whether we can start IPC.
     *
     * @return boolean
     */
    public function canStartIpc() : bool
    {
        return !$this->eventHandler || \class_exists($this->eventHandler);
    }
    /**
     * Get event handler class name.
     *
     * @return (null | class-string<EventHandler>)
     */
    public function getEventHandler() : ?string
    {
        return $this->eventHandler;
    }
}<?php

/**
 * DataCenter DoH proxying AMPHP connector.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Dns\Record;
use Amp\Dns\TimeoutException;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Socket\ConnectContext;
use Amp\Socket\ConnectException;
use Amp\Socket\Connector;
use Amp\Socket\ResourceSocket;
use danog\MadelineProto\Stream\ConnectionContext;
use function Amp\Socket\Internal\parseUri;
class DoHConnector implements Connector
{
    /**
     * Datacenter instance.
     *
     * @property DataCenter $dataCenter
     */
    private $dataCenter;
    /**
     * Connection context.
     *
     * @var ConnectionContext
     */
    private $ctx;
    /**
     *
     */
    public function __construct(DataCenter $dataCenter, ConnectionContext $ctx)
    {
        $this->dataCenter = $dataCenter;
        $this->ctx = $ctx;
    }
    /**
     *
     */
    public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null) : Promise
    {
        return Tools::call((function () use($uri, $context, $token) : \Generator {
            $socketContext = $context ?? new ConnectContext();
            $token = $token ?? new NullCancellationToken();
            $attempt = 0;
            $uris = [];
            $failures = [];
            [$scheme, $host, $port] = parseUri($uri);
            if ($host[0] === '[') {
                $host = \Phabel\Target\Php80\Polyfill::substr($host, 1, -1);
            }
            if ($port === 0 || @\inet_pton($host)) {
                // Host is already an IP address or file path.
                $uris = [$uri];
            } else {
                // Host is not an IP address, so resolve the domain name.
                // When we're connecting to a host, we may need to resolve the domain name, first.
                // The resolution is usually done using DNS over HTTPS.
                //
                // The DNS over HTTPS resolver needs to resolve the domain name of the DOH server:
                // this is handled internally by the DNS over HTTPS client,
                // by redirecting the resolution request to the plain DNS client.
                //
                // However, if the DoH connection is proxied with a proxy that has a domain name itself,
                // we cannot resolve it with the DoH resolver, since this will cause an infinite loop
                //
                // resolve host.com => (DoH resolver) => resolve dohserver.com => (simple resolver) => OK
                //
                //                                     |> resolve dohserver.com => (simple resolver) => OK
                // resolve host.com => (DoH resolver) =|
                //                                     |> resolve proxy.com => (non-proxied resolver) => OK
                //
                //
                // This means that we must detect if the domain name we're trying to resolve is a proxy domain name.
                //
                // Here, we simply check if the connection URI has changed since we first set it:
                // this would indicate that a proxy class has changed the connection URI to the proxy URI.
                //
                if ($this->ctx->isDns()) {
                    $records = (yield $this->dataCenter->getNonProxiedDNSClient()->resolve($host, $socketContext->getDnsTypeRestriction()));
                } else {
                    $records = (yield $this->dataCenter->getDNSClient()->resolve($host, $socketContext->getDnsTypeRestriction()));
                }
                \usort($records, function (Record $a, Record $b) {
                    return $a->getType() - $b->getType();
                });
                if ($this->ctx->getIpv6()) {
                    $records = \array_reverse($records);
                }
                foreach ($records as $record) {
                    /** @var Record $record */
                    if ($record->getType() === Record::AAAA) {
                        $uris[] = \sprintf("%s://[%s]:%d", $scheme, $record->getValue(), $port);
                    } else {
                        $uris[] = \sprintf("%s://%s:%d", $scheme, $record->getValue(), $port);
                    }
                }
            }
            $flags = \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT;
            $timeout = $socketContext->getConnectTimeout();
            $e = null;
            foreach ($uris as $builtUri) {
                try {
                    $streamContext = \stream_context_create($socketContext->withoutTlsContext()->toStreamContextArray());
                    /** @psalm-suppress NullArgument */
                    if (!($socket = @\stream_socket_client($builtUri, $errno, $errstr, null, $flags, $streamContext))) {
                        throw new ConnectException(\sprintf('Connection to %s failed: [Error #%d] %s%s', $uri, $errno, $errstr, $failures ? '; previous attempts: ' . \implode($failures) : ''), $errno);
                    }
                    \stream_set_blocking($socket, false);
                    $deferred = new Deferred();
                    /** @psalm-suppress InvalidArgument */
                    $watcher = Loop::onWritable($socket, [$deferred, 'resolve']);
                    $id = $token->subscribe([$deferred, 'fail']);
                    try {
                        (yield Promise\timeout($deferred->promise(), $timeout));
                    } catch (TimeoutException $e) {
                        throw new ConnectException(\sprintf('Connecting to %s failed: timeout exceeded (%d ms)%s', $uri, $timeout, $failures ? '; previous attempts: ' . \implode($failures) : ''), 110);
                        // See ETIMEDOUT in http://www.virtsync.com/c-error-codes-include-errno
                    } finally {
                        Loop::cancel($watcher);
                        $token->unsubscribe($id);
                    }
                    // The following hack looks like the only way to detect connection refused errors with PHP's stream sockets.
                    if (\stream_socket_get_name($socket, true) === false) {
                        \fclose($socket);
                        throw new ConnectException(\sprintf('Connection to %s refused%s', $uri, $failures ? '; previous attempts: ' . \implode($failures) : ''), 111);
                        // See ECONNREFUSED in http://www.virtsync.com/c-error-codes-include-errno
                    }
                } catch (ConnectException $e) {
                    // Includes only error codes used in this file, as error codes on other OS families might be different.
                    // In fact, this might show a confusing error message on OS families that return 110 or 111 by itself.
                    $knownReasons = [110 => 'connection timeout', 111 => 'connection refused'];
                    $code = $e->getCode();
                    $reason = $knownReasons[$code] ?? 'Error #' . $code;
                    if (++$attempt === $socketContext->getMaxAttempts()) {
                        break;
                    }
                    $failures[] = "{$uri} ({$reason})";
                    continue;
                    // Could not connect to host, try next host in the list.
                }
                return ResourceSocket::fromClientSocket($socket, $socketContext->getTlsContext());
            }
            // This is reached if either all URIs failed or the maximum number of attempts is reached.
            /** @noinspection PhpUndefinedVariableInspection */
            if ($e) {
                throw $e;
            }
        })());
    }
}<?php

namespace danog\MadelineProto\Ipc;

use danog\MadelineProto\RPCErrorException;
use function Amp\Parallel\Sync\flattenThrowableBacktrace;
final class ExitFailure
{
    /** @var string */
    private $type;
    /** @var string */
    private $message;
    /** @var int|string */
    private $code;
    /** @var string[] */
    private $trace;
    /** @var string */
    private $tlTrace;
    /** @var self|null */
    private $previous;
    /** @var string|null */
    private $localized;
    /**
     *
     */
    public function __construct(\Throwable $exception)
    {
        $this->type = \get_class($exception);
        $this->message = $exception->getMessage();
        $this->code = $exception->getCode();
        $this->trace = flattenThrowableBacktrace($exception);
        if (\method_exists($exception, 'getTLTrace')) {
            $this->tlTrace = $exception->getTLTrace();
        }
        if ($exception instanceof RPCErrorException) {
            $this->localized = $exception->getLocalization();
        }
        if ($previous = $exception->getPrevious()) {
            $this->previous = new self($previous);
        }
    }
    /**
     *
     */
    public function getException() : object
    {
        $previous = $this->previous ? $this->previous->getException() : null;
        $exception = ($phabel_0994a32b8400d3ed = $this->type) || true ? new $phabel_0994a32b8400d3ed($this->message, $this->code, $previous) : false;
        if ($this->tlTrace) {
            $exception->setTLTrace($this->tlTrace);
        }
        if ($this->localized) {
            $exception->setLocalization($this->localized);
        }
        return $exception;
    }
}<?php

namespace danog\MadelineProto\Ipc;

/**
 * IPC state class.
 */
final class IpcState
{
    /**
     * Startup time.
     */
    private float $startupTime;
    /**
     * Startup ID.
     */
    private int $startupId;
    /**
     * Exception.
     */
    private ?ExitFailure $exception;
    /**
     * Construct.
     *
     * @param integer $startupId
     * @param \Throwable $exception
     */
    public function __construct(int $startupId, \Throwable $exception = null)
    {
        $this->startupTime = \microtime(true);
        $this->startupId = $startupId;
        $this->exception = $exception ? new ExitFailure($exception) : null;
    }
    /**
     * Get startup time.
     *
     * @return float
     */
    public function getStartupTime() : float
    {
        return $this->startupTime;
    }
    /**
     * Get startup ID.
     *
     * @return int
     */
    public function getStartupId() : int
    {
        return $this->startupId;
    }
    /**
     * Get exception.
     *
     * @return ?\Throwable
     */
    public function getException() : ?\Throwable
    {
        return $this->exception ? $this->exception->getException() : null;
    }
}<?php

/**
 * IPC callback server.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Ipc;

use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use Amp\Promise;
use danog\MadelineProto\Exception;
use danog\MadelineProto\SessionPaths;
/**
 * IPC callback server.
 */
class ServerCallback extends Server
{
    /**
     * Timeout watcher list, indexed by socket ID.
     *
     * @var array<int, string>
     */
    private $watcherList = [];
    /**
     * Timeout watcher list, indexed by socket ID.
     *
     * @var array<int, ChannelledSocket>
     */
    private $socketList = [];
    /**
     * Counter.
     */
    private int $id = 0;
    /**
     * Set IPC path.
     *
     * @param SessionPaths $session Session
     *
     * @return void
     */
    public function setIpcPath(SessionPaths $session) : void
    {
        $this->server = new IpcServer($session->getIpcCallbackPath());
    }
    /**
     * Client handler loop.
     *
     * @param ChannelledSocket $socket Client
     *
     * @return Promise
     */
    protected function clientLoop(ChannelledSocket $socket)
    {
        $id = $this->id++;
        $this->API->logger("Accepted IPC callback connection, assigning ID {$id}!");
        $this->socketList[$id] = $socket;
        $this->watcherList[$id] = Loop::delay(30 * 1000, function () use($id) {
            unset($this->watcherList[$id], $this->socketList[$id]);
        });
        return $socket->send($id);
    }
    /**
     * Unwrap value.
     *
     * @param Wrapper $wrapper
     * @return mixed
     */
    protected function unwrap(Wrapper $wrapper)
    {
        $id = $wrapper->getRemoteId();
        if (!isset($this->socketList[$id])) {
            throw new Exception("IPC timeout, could not find callback socket!");
        }
        $socket = $this->socketList[$id];
        Loop::cancel($this->watcherList[$id]);
        unset($this->watcherList[$id], $this->socketList[$id]);
        return $wrapper->unwrap($socket);
    }
}<?php

/**
 * API wrapper module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Ipc;

use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Promise;
use danog\MadelineProto\Exception;
use danog\MadelineProto\FileCallbackInterface;
use danog\MadelineProto\Logger;
use danog\MadelineProto\MTProtoTools\FilesLogic;
use danog\MadelineProto\SessionPaths;
use danog\MadelineProto\Tools;
/**
 * IPC client.
 */
class Client extends ClientAbstract
{
    use \danog\MadelineProto\Wrappers\Start;
    use \danog\MadelineProto\Wrappers\Templates;
    use FilesLogic;
    /**
     * Instances.
     */
    private static array $instances = [];
    /**
     * Returns an instance of a client by session name.
     *
     * @param string $session
     * @return Client
     */
    public static function giveInstanceBySession(string $session) : Client
    {
        return self::$instances[$session];
    }
    /**
     * Whether the wrapper API is async.
     */
    public bool $async;
    /**
     * Session.
     */
    protected SessionPaths $session;
    /**
     * Constructor function.
     *
     * @param ChannelledSocket $socket IPC client socket
     * @param SessionPaths $session Session paths
     * @param Logger $logger Logger
     * @param bool $async Whether the wrapper API is async
     */
    public function __construct(ChannelledSocket $server, SessionPaths $session, Logger $logger, bool &$async)
    {
        $this->async =& $async;
        $this->logger = $logger;
        $this->server = $server;
        $this->session = $session;
        self::$instances[$session->getLegacySessionPath()] = $this;
        Tools::callFork($this->loopInternal());
    }
    /**
     * Run the provided async callable.
     *
     * @param callable $callback Async callable to run
     *
     * @return \Generator
     */
    public function loop(callable $callback) : \Generator
    {
        return (yield $callback());
    }
    /**
     * Unreference.
     *
     * @return void
     */
    public function unreference() : void
    {
        try {
            Tools::wait($this->disconnect());
        } catch (\Throwable $e) {
            $this->logger("An error occurred while disconnecting the client: {$e}");
        }
        if (isset(self::$instances[$this->session->getLegacySessionPath()])) {
            unset(self::$instances[$this->session->getLegacySessionPath()]);
        }
    }
    /**
     * Stop IPC server instance.
     *
     * @internal
     */
    public function stopIpcServer() : Promise
    {
        $this->run = false;
        return $this->server->send(Server::SHUTDOWN);
    }
    /**
     * Restart IPC server instance.
     *
     * @internal
     */
    public function restartIpcServer() : Promise
    {
        return $this->server->send(Server::SHUTDOWN);
    }
    /**
     * Whether we're an IPC client instance.
     *
     * @return boolean
     */
    public function isIpc() : bool
    {
        return true;
    }
    /**
     * Upload file from URL.
     *
     * @param (string | FileCallbackInterface) $url URL of file
     * @param integer $size Size of file
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Generator
     */
    public function uploadFromUrl($url, int $size = 0, string $fileName = '', $cb = null, bool $encrypted = false) : \Generator
    {
        if (\is_object($url) && $url instanceof FileCallbackInterface) {
            $cb = $url;
            $url = (yield $url->getFile());
        }
        $params = [$url, $size, $fileName, &$cb, $encrypted];
        $wrapper = (yield from Wrapper::create($params, $this->session, $this->logger));
        $wrapper->wrap($cb, false);
        return yield from $this->__call('uploadFromUrl', $wrapper);
    }
    /**
    * Upload file from callable.
    *
    * The callable must accept two parameters: int $offset, int $size
    The callable must return a string with the contest of the file at the specified offset and size.
    *
    * @param mixed $callable Callable
    * @param integer $size File size
    * @param string $mime Mime type
    * @param string $fileName File name
    * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
    * @param boolean $seekable Whether chunks can be fetched out of order
    * @param boolean $encrypted Whether to encrypt file for secret chats
    *
    * @return \Generator
    *
    * @psalm-return \Generator<int, (Promise<ChannelledSocket> | Promise<mixed>), mixed, mixed>
    */
    public function uploadFromCallable(callable $callable, int $size, string $mime, string $fileName = '', $cb = null, bool $seekable = true, bool $encrypted = false) : \Generator
    {
        if (\is_object($callable) && $callable instanceof FileCallbackInterface) {
            $cb = $callable;
            $callable = (yield $callable->getFile());
        }
        $params = [&$callable, $size, $mime, $fileName, &$cb, $seekable, $encrypted];
        $wrapper = (yield from Wrapper::create($params, $this->session, $this->logger));
        $wrapper->wrap($cb, false);
        $wrapper->wrap($callable, false);
        return yield from $this->__call('uploadFromCallable', $wrapper);
    }
    /**
     * Reupload telegram file.
     *
     * @param mixed $media Telegram file
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, (Promise<ChannelledSocket> | Promise<mixed>), mixed, mixed>
     */
    public function uploadFromTgfile($media, $cb = null, bool $encrypted = false) : \Generator
    {
        if (\is_object($media) && $media instanceof FileCallbackInterface) {
            $cb = $media;
            $media = (yield $media->getFile());
        }
        $params = [$media, &$cb, $encrypted];
        $wrapper = (yield from Wrapper::create($params, $this->session, $this->logger));
        $wrapper->wrap($cb, false);
        return yield from $this->__call('uploadFromTgfile', $wrapper);
    }
    /**
     * Call method and wait asynchronously for response.
     *
     * If the $aargs['noResponse'] is true, will not wait for a response.
     *
     * @param string $method Method name
     * @param (array | \Generator) $args Arguments
     * @param array $aargs Additional arguments
     *
     * @psalm-param (array | \Generator<mixed, mixed, mixed, array>) $args
     *
     * @return \Generator
     */
    public function methodCallAsyncRead(string $method, $args, array $aargs)
    {
        if (\is_array($args)) {
            if (($method === 'messages.editInlineBotMessage' || $method === 'messages.uploadMedia' || $method === 'messages.sendMedia' || $method === 'messages.editMessage') && isset($args['media']['file']) && $args['media']['file'] instanceof FileCallbackInterface) {
                $params = [$method, &$args, $aargs];
                $wrapper = (yield from Wrapper::create($params, $this->session, $this->logger));
                $wrapper->wrap($args['media']['file'], true);
                return yield from $this->__call('methodCallAsyncRead', $wrapper);
            } elseif ($method === 'messages.sendMultiMedia' && isset($args['multi_media'])) {
                $params = [$method, &$args, $aargs];
                $wrapper = (yield from Wrapper::create($params, $this->session, $this->logger));
                foreach ($args['multi_media'] as &$media) {
                    if (isset($media['media']['file']) && $media['media']['file'] instanceof FileCallbackInterface) {
                        $wrapper->wrap($media['media']['file'], true);
                    }
                }
                return yield from $this->__call('methodCallAsyncRead', $wrapper);
            }
        }
        return yield from $this->__call('methodCallAsyncRead', [$method, $args, $aargs]);
    }
    /**
     * Download file to directory.
     *
     * @param mixed $messageMedia File to download
     * @param (string | FileCallbackInterface) $dir Directory where to download the file
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     *
     * @return \Generator Downloaded file path
     *
     * @psalm-return \Generator<int, (Promise<ChannelledSocket> | Promise<mixed>), mixed, mixed>
     */
    public function downloadToDir($messageMedia, $dir, $cb = null) : \Generator
    {
        if (\is_object($dir) && $dir instanceof FileCallbackInterface) {
            $cb = $dir;
            $dir = (yield $dir->getFile());
        }
        $params = [$messageMedia, $dir, &$cb];
        $wrapper = (yield from Wrapper::create($params, $this->session, $this->logger));
        $wrapper->wrap($cb, false);
        return yield from $this->__call('downloadToDir', $wrapper);
    }
    /**
     * Download file.
     *
     * @param mixed $messageMedia File to download
     * @param (string | FileCallbackInterface) $file Downloaded file path
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     *
     * @return \Generator Downloaded file path
     *
     * @psalm-return \Generator<int, (Promise<ChannelledSocket> | Promise<mixed>), mixed, mixed>
     */
    public function downloadToFile($messageMedia, $file, $cb = null) : \Generator
    {
        if (\is_object($file) && $file instanceof FileCallbackInterface) {
            $cb = $file;
            $file = (yield $file->getFile());
        }
        $params = [$messageMedia, $file, &$cb];
        $wrapper = (yield from Wrapper::create($params, $this->session, $this->logger));
        $wrapper->wrap($cb, false);
        return yield from $this->__call('downloadToFile', $wrapper);
    }
    /**
    * Download file to callable.
    The callable must accept two parameters: string $payload, int $offset
    The callable will be called (possibly out of order, depending on the value of $seekable).
    The callable should return the number of written bytes.
    *
    * @param mixed $messageMedia File to download
    * @param (callable | FileCallbackInterface) $callable Chunk callback
    * @param callable $cb Status callback (DEPRECATED, use FileCallbackInterface)
    * @param bool $seekable Whether the callable can be called out of order
    * @param int $offset Offset where to start downloading
    * @param int $end Offset where to stop downloading (inclusive)
    * @param int $part_size Size of each chunk
    *
    * @return \Generator
    *
    * @psalm-return \Generator<int, (Promise<ChannelledSocket> | Promise<mixed>), mixed, mixed>
    */
    public function downloadToCallable($messageMedia, callable $callable, $cb = null, bool $seekable = true, int $offset = 0, int $end = -1, int $part_size = null) : \Generator
    {
        $messageMedia = (yield from $this->getDownloadInfo($messageMedia));
        if (\is_object($callable) && $callable instanceof FileCallbackInterface) {
            $cb = $callable;
            $callable = (yield $callable->getFile());
        }
        $params = [$messageMedia, &$callable, &$cb, $seekable, $offset, $end, $part_size];
        $wrapper = (yield from Wrapper::create($params, $this->session, $this->logger));
        $wrapper->wrap($callable, false);
        $wrapper->wrap($cb, false);
        return yield from $this->__call('downloadToCallable', $wrapper);
    }
    /**
     * Placeholder.
     *
     * @param mixed ...$params Params
     *
     * @return void
     */
    public function setEventHandler(...$params) : void
    {
        throw new Exception("Can't use " . __FUNCTION__ . " in an IPC client instance, please use startAndLoop, instead!");
    }
    /**
     * Placeholder.
     *
     * @param mixed ...$params Params
     *
     * @return void
     */
    public function getEventHandler(...$params) : void
    {
        throw new Exception("Can't use " . __FUNCTION__ . " in an IPC client instance, please use startAndLoop, instead!");
    }
}<?php

namespace danog\MadelineProto\Ipc\Wrapper;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\OutputStream as AmpOutputStream;
use Amp\ByteStream\StreamException;
use Amp\Promise;
use danog\MadelineProto\Tools;
class OutputStream extends Obj implements AmpOutputStream
{
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     * @throws StreamException If writing to the stream fails.
     */
    public function write(string $data) : Promise
    {
        return Tools::call($this->__call('write', [$data]));
    }
    /**
    * Marks the stream as no longer writable. Optionally writes a final data chunk before. Note that this is not the
    same as forcefully closing the stream. This method waits for all pending writes to complete before closing the
    stream. Socket streams implementing this interface should only close the writable side of the stream.
    *
    * @param string $finalData Bytes to write.
    *
    * @return Promise Succeeds once the data has been successfully written to the stream.
    *
    * @throws ClosedException If the stream has already been closed.
    * @throws StreamException If writing to the stream fails.
    */
    public function end(string $finalData = "") : Promise
    {
        return Tools::call($this->__call('write', [$finalData]));
    }
}<?php

namespace danog\MadelineProto\Ipc\Wrapper;

use Amp\Promise;
use danog\MadelineProto\Tools;
trait SeekableTrait
{
    /**
    * Set the handle's internal pointer position.
    *
    * $whence values:
    *
    * SEEK_SET - Set position equal to offset bytes.
    SEEK_CUR - Set position to current location plus offset.
    SEEK_END - Set position to end-of-file plus offset.
    *
    * @param int $position
    * @param int $whence
    * @return \Amp\Promise<int> New offset position.
    */
    public function seek(int $position, int $whence = \SEEK_SET) : Promise
    {
        return Tools::call($this->__call('seek', [$position, $whence]));
    }
}<?php

namespace danog\MadelineProto\Ipc\Wrapper;

use Amp\ByteStream\InputStream as AmpInputStream;
use Amp\ByteStream\PendingReadError;
use Amp\Promise;
use danog\MadelineProto\Tools;
class InputStream extends Obj implements AmpInputStream
{
    /**
     * Reads data from the stream.
     *
     * @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
     *
     * @psalm-return Promise<(string | null)>
     *
     * @throws PendingReadError Thrown if another read operation is still pending.
     */
    public function read() : Promise
    {
        return Tools::call($this->__call('read'));
    }
}<?php

namespace danog\MadelineProto\Ipc\Wrapper;

use danog\MadelineProto\FileCallbackInterface;
class FileCallback extends Obj implements FileCallbackInterface
{
    /**
     * Get file.
     *
     * @return mixed
     */
    public function getFile()
    {
        return $this->__call('getFile');
    }
    /**
     * Invoke callback.
     *
     * @param float $percent Percent
     * @param float $speed Speed in mbps
     * @param float $time Time
     *
     * @psalm-suppress MethodSignatureMismatch
     *
     * @return mixed
     */
    public function __invoke($percent, $speed, $time)
    {
        return $this->__call('__invoke', [$percent, $speed, $time]);
    }
}<?php

namespace danog\MadelineProto\Ipc\Wrapper;

class SeekableInputStream extends InputStream
{
    use SeekableTrait;
}<?php

namespace danog\MadelineProto\Ipc\Wrapper;

use danog\MadelineProto\Ipc\Wrapper;
/**
 * Generic callback wrapper object.
 */
class Obj
{
    /**
     * Method list.
     *
     * @var array<string, int>
     */
    private array $methods = [];
    /**
     * Wrapper.
     */
    private Wrapper $wrapper;
    /**
     * Constructor.
     *
     * @param Wrapper $wrapper
     * @param array $methods
     */
    public function __construct(Wrapper $wrapper, array $methods)
    {
        $this->wrapper = $wrapper;
        $this->methods = $methods;
    }
    /**
     * Call method.
     *
     * @param string $name
     * @param array $arguments
     *
     * @return \Generator<mixed, mixed, mixed, mixed>
     */
    public function __call(string $name, array $arguments = []) : \Generator
    {
        return $this->wrapper->__call($this->methods[$name], $arguments);
    }
}<?php

namespace danog\MadelineProto\Ipc\Wrapper;

class SeekableOutputStream extends OutputStream
{
    use SeekableTrait;
}<?php

namespace danog\MadelineProto\Ipc\Wrapper;

use danog\MadelineProto\Ipc\Wrapper;
trait WrapMethodTrait
{
    /**
     *
     */
    public abstract function __call($name, $args);
    /**
     *
     */
    public function wrap(...$args) : \Generator
    {
        $new = (yield from Wrapper::create($args, $this->session->getIpcCallbackPath(), $this->logger));
        foreach ($args as &$arg) {
            $new->wrap($arg);
        }
        return $this->__call(__FUNCTION__, $new);
    }
}<?php

namespace danog\MadelineProto\Ipc;

use Amp\ByteStream\InputStream as ByteStreamInputStream;
use Amp\ByteStream\OutputStream as ByteStreamOutputStream;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitFailure;
use Amp\Promise;
use danog\MadelineProto\FileCallbackInterface;
use danog\MadelineProto\Ipc\Wrapper\FileCallback;
use danog\MadelineProto\Ipc\Wrapper\InputStream;
use danog\MadelineProto\Ipc\Wrapper\Obj;
use danog\MadelineProto\Ipc\Wrapper\OutputStream;
use danog\MadelineProto\Ipc\Wrapper\SeekableInputStream;
use danog\MadelineProto\Ipc\Wrapper\SeekableOutputStream;
use danog\MadelineProto\Logger;
use danog\MadelineProto\SessionPaths;
use danog\MadelineProto\Tools;
use function Amp\Ipc\connect;
/**
 * Callback payload wrapper.
 */
class Wrapper extends ClientAbstract
{
    /**
     * Payload data.
     *
     * @var mixed
     */
    private $data;
    /**
     * Callbacks.
     *
     * @var callable[]
     */
    private array $callbacks = [];
    /**
     * Callbacks IDs.
     *
     * @var (int | array{0: class-string<Obj>, array<string, int>})[]
     */
    private array $callbackIds = [];
    /**
     * Callback ID.
     */
    private int $id = 0;
    /**
     * Remote socket ID.
     */
    private int $remoteId = 0;
    /**
     * Constructor.
     *
     * @param mixed $data Payload data
     * @param SessionPaths $ipc IPC URI
     *
     * @return \Generator
     * @psalm-return \Generator<int, (Promise<ChannelledSocket> | Promise<mixed>), mixed, Wrapper>
     */
    public static function create(&$data, SessionPaths $session, Logger $logger) : \Generator
    {
        $instance = new self();
        $instance->data =& $data;
        $instance->logger = $logger;
        $instance->run = false;
        $logger->logger("Connecting to callback IPC server...");
        $instance->server = (yield connect($session->getIpcCallbackPath()));
        $logger->logger("Connected to callback IPC server!");
        $instance->remoteId = (yield $instance->server->receive());
        $logger->logger("Got ID {$instance->remoteId} from callback IPC server!");
        Tools::callFork($instance->receiverLoop());
        return $instance;
    }
    /**
     * Serialization function.
     *
     * @return array
     */
    public function __sleep() : array
    {
        return ['data', 'callbackIds', 'remoteId'];
    }
    /**
     * Wrap a certain callback object.
     *
     * @param (object | callable) $callback Callback to wrap
     * @param bool $wrapObjects Whether to wrap object methods, too
     *
     * @param-out int $callback Callback ID
     *
     * @return void
     */
    public function wrap(&$callback, bool $wrapObjects = true) : void
    {
        if (\is_object($callback) && $wrapObjects) {
            $ids = [];
            foreach (\get_class_methods($callback) as $method) {
                $id = $this->id++;
                $this->callbacks[$id] = [$callback, $method];
                $ids[$method] = $id;
            }
            $class = Obj::class;
            if ($callback instanceof ByteStreamInputStream) {
                $class = \method_exists($callback, 'seek') ? InputStream::class : SeekableInputStream::class;
            } elseif ($callback instanceof ByteStreamOutputStream) {
                $class = \method_exists($callback, 'seek') ? OutputStream::class : SeekableOutputStream::class;
            } elseif ($callback instanceof FileCallbackInterface) {
                $class = FileCallback::class;
            }
            $callback = [$class, $ids];
            // Will be re-filled later
            $this->callbackIds[] =& $callback;
        } elseif (\is_callable($callback)) {
            $id = $this->id++;
            $this->callbacks[$id] = self::copy($callback);
            $callback = $id;
            $this->callbackIds[] =& $callback;
        }
    }
    /**
     * Get copy of data.
     *
     * @param mixed $data
     * @return mixed
     */
    private static function copy($data)
    {
        return $data;
    }
    /**
     * Receiver loop.
     *
     * @return \Generator
     */
    private function receiverLoop() : \Generator
    {
        $id = 0;
        $payload = null;
        try {
            while ($payload = (yield $this->server->receive())) {
                Tools::callFork($this->clientRequest($id++, $payload));
            }
        } finally {
            (yield $this->server->disconnect());
        }
    }
    /**
     * Handle client request.
     *
     * @param integer $id Request ID
     * @param array $payload Payload
     *
     * @return \Generator
     */
    private function clientRequest(int $id, $payload) : \Generator
    {
        try {
            $result = $this->callbacks[$payload[0]](...$payload[1]);
            $result = $result instanceof \Generator ? yield from $result : (yield $result);
        } catch (\Throwable $e) {
            $this->logger->logger("Got error while calling reverse IPC method: {$e}", Logger::ERROR);
            $result = new ExitFailure($e);
        }
        try {
            (yield $this->server->send([$id, $result]));
        } catch (\Throwable $e) {
            $this->logger->logger("Got error while trying to send result of reverse method: {$e}", Logger::ERROR);
            try {
                (yield $this->server->send([$id, new ExitFailure($e)]));
            } catch (\Throwable $e) {
                $this->logger->logger("Got error while trying to send error of error of reverse method: {$e}", Logger::ERROR);
            }
        }
    }
    /**
     * Get remote socket ID.
     *
     * @internal
     *
     * @return int
     */
    public function getRemoteId() : int
    {
        return $this->remoteId;
    }
    /**
     * Set socket and unwrap data.
     *
     * @param ChannelledSocket $server Socket.
     *
     * @internal
     *
     * @return mixed
     */
    public function unwrap(ChannelledSocket $server)
    {
        $this->server = $server;
        Tools::callFork($this->loopInternal());
        foreach ($this->callbackIds as &$id) {
            if (\is_int($id)) {
                $id = fn(...$args): \Generator => $this->__call($id, $args);
            } else {
                [$class, $ids] = $id;
                $id = new $class($this, $ids);
            }
        }
        return $this->data;
    }
}<?php

/**
 * API wrapper module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Ipc;

use Amp\Deferred;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Promise;
use danog\MadelineProto\Logger;
use function Amp\Ipc\connect;
/**
 * IPC client.
 */
abstract class ClientAbstract
{
    /**
     * IPC server socket.
     */
    protected ChannelledSocket $server;
    /**
     * Requests promise array.
     *
     * @var Deferred[]
     */
    private array $requests = [];
    /**
     * Wrappers array.
     *
     * @var Wrapper[]
     */
    private array $wrappers = [];
    /**
     * Whether to run loop.
     */
    protected bool $run = true;
    /**
     * Logger instance.
     */
    public Logger $logger;
    /**
     *
     */
    protected function __construct()
    {
    }
    /**
     * Logger.
     *
     * @param string $param Parameter
     * @param int $level Logging level
     * @param string $file File where the message originated
     *
     * @return void
     */
    public function logger($param, int $level = Logger::NOTICE, string $file = '') : void
    {
        if ($file === null) {
            $file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
        }
        isset($this->logger) ? $this->logger->logger($param, $level, $file) : Logger::$default->logger($param, $level, $file);
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    protected function loopInternal() : \Generator
    {
        do {
            while (true) {
                $payload = null;
                try {
                    $payload = (yield $this->server->receive());
                } catch (\Throwable $e) {
                    Logger::log("Got exception while receiving in IPC client: {$e}");
                }
                if (!$payload) {
                    break;
                }
                [$id, $payload] = $payload;
                if (!isset($this->requests[$id])) {
                    Logger::log("Got response for non-existing ID {$id}!");
                } else {
                    $promise = $this->requests[$id];
                    unset($this->requests[$id]);
                    if (isset($this->wrappers[$id])) {
                        (yield $this->wrappers[$id]->disconnect());
                        unset($this->wrappers[$id]);
                    }
                    if ($payload instanceof ExitFailure) {
                        $promise->fail($payload->getException());
                    } else {
                        $promise->resolve($payload);
                    }
                    unset($promise);
                }
            }
            if ($this->run) {
                $this->logger("Reconnecting to IPC server!");
                try {
                    (yield $this->server->disconnect());
                } catch (\Throwable $e) {
                }
                if ($this instanceof Client) {
                    try {
                        (yield Server::startMe($this->session));
                        $this->server = (yield connect($this->session->getIpcPath()));
                    } catch (\Throwable $e) {
                        Logger::log("Got exception while reconnecting in IPC client: {$e}");
                    }
                } else {
                    return;
                }
            }
        } while ($this->run);
    }
    /**
     * Disconnect cleanly from main instance.
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, Promise, mixed, void>
     */
    public function disconnect() : \Generator
    {
        $this->run = false;
        (yield $this->server->disconnect());
        foreach ($this->wrappers as $w) {
            yield from $w->disconnect();
        }
    }
    /**
     * Call function.
     *
     * @param (string | int) $function Function name
     * @param (array | Wrapper) $arguments Arguments
     *
     * @return \Generator
     */
    public function __call($function, $arguments) : \Generator
    {
        $this->requests[] = $deferred = new Deferred();
        if ($arguments instanceof Wrapper) {
            $this->wrappers[\count($this->requests) - 1] = $arguments;
        }
        (yield $this->server->send([$function, $arguments]));
        return (yield $deferred->promise());
    }
}<?php

namespace danog\MadelineProto\Ipc\Runner;

use Amp\Failure;
use Amp\Parallel\Context\ContextException;
use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Magic;
final class WebRunner extends RunnerAbstract
{
    /** @var string|null Cached path to the runner script. */
    private static $runPath;
    /**
     * Resources.
     */
    private static array $resources = [];
    /**
     * Start.
     *
     * @param string $session Session path
     *
     * @return Promise<bool>
     */
    public static function start(string $session, int $startupId) : Promise
    {
        if (!isset($_SERVER['SERVER_NAME']) || !$_SERVER['SERVER_NAME']) {
            return new Failure(new \Exception("Can't start the web runner!"));
        }
        if (!self::$runPath) {
            $uri = \parse_url('tcp://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'], PHP_URL_PATH);
            if (\Phabel\Target\Php80\Polyfill::substr($uri, -1) === '/') {
                // http://example.com/path/ (assumed index.php)
                $uri .= 'index';
                // Add fake file name
            }
            $uri = \str_replace('//', '/', $uri);
            $rootDir = \debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
            $rootDir = \end($rootDir)['file'] ?? '';
            if (!$rootDir) {
                throw new ContextException('Could not get entry file!');
            }
            $rootDir = \dirname($rootDir) . DIRECTORY_SEPARATOR;
            $uriDir = \str_replace('/', DIRECTORY_SEPARATOR, \dirname($uri));
            if ($uriDir !== '/' && $uriDir !== '\\') {
                $uriDir .= DIRECTORY_SEPARATOR;
            }
            if (\Phabel\Target\Php80\Polyfill::substr($rootDir, -\strlen($uriDir)) !== $uriDir) {
                throw new ContextException("Mismatch between absolute root dir ({$rootDir}) and URI dir ({$uriDir})");
            }
            // Absolute root of (presumably) readable document root
            $absoluteRootDir = \Phabel\Target\Php80\Polyfill::substr($rootDir, 0, \strlen($rootDir) - \strlen($uriDir)) . DIRECTORY_SEPARATOR;
            $runPath = self::getScriptPath($absoluteRootDir);
            if (\Phabel\Target\Php80\Polyfill::substr($runPath, 0, \strlen($absoluteRootDir)) === $absoluteRootDir) {
                // Process runner is within readable document root
                self::$runPath = \Phabel\Target\Php80\Polyfill::substr($runPath, \strlen($absoluteRootDir) - 1);
            } else {
                $contents = \file_get_contents(self::SCRIPT_PATH);
                $contents = \str_replace("__DIR__", \var_export($absoluteRootDir, true), $contents);
                $suffix = \bin2hex(\random_bytes(10));
                $runPath = $absoluteRootDir . "/madeline-ipc-" . $suffix . ".php";
                \file_put_contents($runPath, $contents);
                self::$runPath = \Phabel\Target\Php80\Polyfill::substr($runPath, \strlen($absoluteRootDir) - 1);
                \register_shutdown_function(static function () use($runPath) : void {
                    @\unlink($runPath);
                });
            }
            self::$runPath = \str_replace(DIRECTORY_SEPARATOR, '/', self::$runPath);
            self::$runPath = \str_replace('//', '/', self::$runPath);
        }
        $params = ['argv' => ['madeline-ipc', $session, $startupId], 'cwd' => Magic::getcwd()];
        $params = \http_build_query($params);
        foreach (($_SERVER['HTTPS'] ?? 'off') === 'on' ? ['tls', 'tcp'] : ['tcp', 'tls'] as $proto) {
            try {
                $address = $proto . '://' . $_SERVER['SERVER_NAME'];
                $port = $_SERVER['SERVER_PORT'];
                $res = \Phabel\Target\Php80\Polyfill::fsockopen($address, $port);
                break;
            } catch (\Throwable $e) {
                Logger::log("Error while connecting to ourselves: {$e}");
            }
        }
        if (!isset($res)) {
            throw new Exception("Could not connect to ourselves, please check the server configuration!");
        }
        $uri = self::$runPath . '?' . $params;
        $payload = "GET {$uri} HTTP/1.1\r\nHost: {$_SERVER['SERVER_NAME']}\r\n\r\n";
        // We don't care for results or timeouts here, PHP doesn't count IOwait time as execution time anyway
        // Technically should use amphp/socket, but I guess it's OK to not introduce another dependency just for a socket that will be used once.
        \fwrite($res, $payload);
        self::$resources[] = $res;
        return new Success(true);
    }
}<?php

/**
 * IPC server entry module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
use danog\MadelineProto\API;
use danog\MadelineProto\Ipc\IpcState;
use danog\MadelineProto\Ipc\Server;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Magic;
use danog\MadelineProto\SessionPaths;
use danog\MadelineProto\Settings\Ipc;
use danog\MadelineProto\Shutdown;
use danog\MadelineProto\Tools;
(static function () : void {
    if (\defined('MADELINE_ENTRY')) {
        // Already called
        return;
    }
    \define('MADELINE_ENTRY', 1);
    if (!\defined('MADELINE_WORKER_TYPE')) {
        if (\count(\debug_backtrace(0)) !== 1) {
            // We're not being included directly
            return;
        }
        $arguments = [];
        if (isset($GLOBALS['argv']) && !empty($GLOBALS['argv'])) {
            $arguments = \array_slice($GLOBALS['argv'], 1);
        } elseif (isset($_GET['argv']) && !empty($_GET['argv'])) {
            $arguments = $_GET['argv'];
        }
        if (\count($arguments) < 2) {
            \trigger_error("Not enough arguments!", E_USER_ERROR);
            exit(1);
        }
        \define('MADELINE_WORKER_TYPE', \array_shift($arguments));
        \define('MADELINE_WORKER_ARGS', $arguments);
    }
    if (\defined('SIGHUP')) {
        try {
            \pcntl_signal(SIGHUP, fn() => null);
        } catch (\Throwable $e) {
        }
    }
    if (!\class_exists(API::class)) {
        $paths = [\dirname(__DIR__, 7) . "/autoload.php", \dirname(__DIR__, 5) . "/vendor/autoload.php"];
        foreach ($paths as $path) {
            if (\file_exists($path)) {
                $autoloadPath = $path;
                break;
            }
        }
        if (!isset($autoloadPath)) {
            \trigger_error("Could not locate autoload.php in any of the following files: " . \implode(", ", $paths), E_USER_ERROR);
            exit(1);
        }
        include $autoloadPath;
    }
    if (\MADELINE_WORKER_TYPE === 'madeline-ipc') {
        $ipcPath = \MADELINE_WORKER_ARGS[0];
        if (!\file_exists($ipcPath)) {
            \trigger_error("IPC session {$ipcPath} does not exist!", E_USER_ERROR);
            exit(1);
        }
        if (\function_exists('cli_set_process_title')) {
            @\cli_set_process_title("MadelineProto worker {$ipcPath}");
        }
        if (\function_exists('posix_setsid')) {
            @\posix_setsid();
        }
        if (isset($_GET['cwd'])) {
            @\chdir($_GET['cwd']);
        }
        \define('MADELINE_WORKER', 1);
        $runnerId = \MADELINE_WORKER_ARGS[1];
        $session = new SessionPaths($ipcPath);
        try {
            Magic::start();
            Magic::$script_cwd = $_GET['cwd'] ?? Magic::getcwd();
            $API = new API($ipcPath, (new Ipc())->setSlow(true));
            $API->init();
            $API->initSelfRestart();
            while (true) {
                try {
                    Tools::wait($session->storeIpcState(new IpcState($runnerId)));
                    Tools::wait(Server::waitShutdown());
                    Shutdown::removeCallback('restarter');
                    return;
                } catch (\Throwable $e) {
                    Logger::log((string) $e, Logger::FATAL_ERROR);
                    Tools::wait($API->report("Surfaced: {$e}"));
                }
            }
        } catch (\Throwable $e) {
            echo "{$e}";
            echo "Got exception in IPC server, exiting...";
            Logger::log("{$e}", Logger::FATAL_ERROR);
            Logger::log("Got exception in IPC server, exiting...", Logger::FATAL_ERROR);
            $ipc = Tools::wait($session->getIpcState());
            if (!($ipc && $ipc->getStartupId() === $runnerId && !$ipc->getException())) {
                Logger::log("Reporting error!");
                Tools::wait($session->storeIpcState(new IpcState($runnerId, $e)));
                Logger::log("Reported error!");
            } else {
                Logger::log("Not reporting error!");
            }
        }
    }
})();<?php

namespace danog\MadelineProto\Ipc\Runner;

use Amp\Deferred;
use Amp\Process\Internal\Posix\Runner;
use Amp\Process\Internal\Windows\Runner as WindowsRunner;
use Amp\Process\ProcessInputStream;
use Amp\Promise;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Magic;
use danog\MadelineProto\Tools;
use const Amp\Process\IS_WINDOWS;
final class ProcessRunner extends RunnerAbstract
{
    private const CGI_VARS = ["AUTH_TYPE", "CONTENT_LENGTH", "CONTENT_TYPE", "GATEWAY_INTERFACE", "PATH_INFO", "PATH_TRANSLATED", "QUERY_STRING", "REMOTE_ADDR", "REMOTE_HOST", "REMOTE_IDENT", "REMOTE_USER", "REQUEST_METHOD", "SCRIPT_NAME", "SERVER_NAME", "SERVER_PORT", "SERVER_PROTOCOL", "SERVER_SOFTWARE"];
    /** @var string|null Cached path to located PHP binary. */
    private static $binaryPath;
    /**
     * Runner.
     *
     * @param string $session Session path
     *
     * @return Promise<true>
     */
    public static function start(string $session, int $startupId) : Promise
    {
        if (\PHP_SAPI === "cli") {
            $binary = \PHP_BINARY;
        } else {
            $binary = self::$binaryPath ?? self::locateBinary();
        }
        $options = ["html_errors" => "0", "display_errors" => "0", "log_errors" => "1"];
        $runner = self::getScriptPath();
        $command = [$binary, ...self::formatOptions($options), $runner, 'madeline-ipc', $session, $startupId];
        $command = \implode(" ", \array_map('Amp\\Process\\escapeArguments', $command));
        Logger::log("Starting process with {$command}");
        $params = ['argv' => ['madeline-ipc', $session, $startupId], 'cwd' => Magic::getcwd()];
        $envVars = \array_merge(\array_filter($_SERVER, fn($v, $k): bool => (\is_string($v) && !\in_array($k, self::CGI_VARS)), ARRAY_FILTER_USE_BOTH), ['QUERY_STRING' => \http_build_query($params)]);
        $resDeferred = new Deferred();
        $runner = IS_WINDOWS ? new WindowsRunner() : new Runner();
        $handle = $runner->start($command, null, $envVars);
        $handle->pidDeferred->promise()->onResolve(function (?\Throwable $e, ?int $pid) use($handle, $runner, $resDeferred) {
            if ($e) {
                Logger::log("Got exception while starting process worker: {$e}");
                $resDeferred->resolve($e);
                return;
            }
            Tools::callFork(self::readUnref($handle->stdout));
            Tools::callFork(self::readUnref($handle->stderr));
            $runner->join($handle)->onResolve(function (?\Throwable $e, ?int $res) use($runner, $handle, $resDeferred) {
                $runner->destroy($handle);
                if ($e) {
                    Logger::log("Got exception from process worker: {$e}");
                    $resDeferred->fail($e);
                } else {
                    Logger::log("Process worker exited with {$res}!");
                    $resDeferred->fail(new Exception("Process worker exited with {$res}!"));
                }
            });
        });
        return $resDeferred->promise();
    }
    /**
     * Unreference and read data from fd, logging results.
     *
     * @param ProcessInputStream $stream
     * @return \Generator
     */
    private static function readUnref(ProcessInputStream $stream) : \Generator
    {
        $stream->unreference();
        $lastLine = '';
        try {
            while (($chunk = (yield $stream->read())) !== null) {
                $chunk = \explode("\n", \str_replace(["\r", "\n\n"], "\n", $chunk));
                $lastLine .= \array_shift($chunk);
                while ($chunk) {
                    Logger::log("Got message from worker: {$lastLine}");
                    $lastLine = \array_shift($chunk);
                }
            }
        } catch (\Throwable $e) {
            Logger::log("An error occurred while reading the process status: {$e}");
        } finally {
            Logger::log("Got final message from worker: {$lastLine}");
        }
    }
    /**
     *
     */
    private static function locateBinary() : string
    {
        $executable = \strncasecmp(\PHP_OS, "WIN", 3) === 0 ? "php.exe" : "php";
        $paths = \array_filter(\explode(\PATH_SEPARATOR, \getenv("PATH")));
        $paths[] = \PHP_BINDIR;
        $paths = \array_unique($paths);
        foreach ($paths as $path) {
            $path .= \DIRECTORY_SEPARATOR . $executable;
            if (\is_executable($path)) {
                return self::$binaryPath = $path;
            }
        }
        throw new \Error("Could not locate PHP executable binary");
    }
    /**
     * Format PHP options.
     *
     * @param array $options
     * @return list<string>
     */
    private static function formatOptions(array $options) : array
    {
        $result = [];
        foreach ($options as $option => $value) {
            $result[] = \sprintf("-d%s=%s", $option, $value);
        }
        return $result;
    }
}<?php

namespace danog\MadelineProto\Ipc\Runner;

use Amp\Promise;
abstract class RunnerAbstract
{
    const SCRIPT_PATH = __DIR__ . "/entry.php";
    /** @var string|null External version of SCRIPT_PATH if inside a PHAR. */
    protected static $pharScriptPath;
    /** @var string|null PHAR path with a '.phar' extension. */
    protected static $pharCopy;
    /**
     *
     */
    protected static function getScriptPath(string $alternateTmpDir = '')
    {
        /**
         * If using madeline.php, simply return madeline.php path.
         */
        if (\defined('MADELINE_PHP')) {
            return \MADELINE_PHP;
        }
        // Write process runner to external file if inside a PHAR different from madeline.phar,
        // because PHP can't open files inside a PHAR directly except for the stub.
        if (\strpos(self::SCRIPT_PATH, "phar://") === 0) {
            $alternateTmpDir = $alternateTmpDir ?: \sys_get_temp_dir();
            if (self::$pharScriptPath) {
                $scriptPath = self::$pharScriptPath;
            } else {
                $path = \dirname(self::SCRIPT_PATH);
                if (\Phabel\Target\Php80\Polyfill::substr(\Phar::running(false), -5) !== ".phar") {
                    self::$pharCopy = $alternateTmpDir . "/phar-" . \bin2hex(\random_bytes(10)) . ".phar";
                    \copy(\Phar::running(false), self::$pharCopy);
                    \register_shutdown_function(static function () : void {
                        @\unlink(self::$pharCopy);
                    });
                    $path = "phar://" . self::$pharCopy . "/" . \Phabel\Target\Php80\Polyfill::substr($path, \strlen(\Phar::running(true)));
                }
                $contents = \file_get_contents(self::SCRIPT_PATH);
                $contents = \str_replace("__DIR__", \var_export($path, true), $contents);
                $suffix = \bin2hex(\random_bytes(10));
                self::$pharScriptPath = $scriptPath = $alternateTmpDir . "/madeline-ipc-" . $suffix . ".php";
                \file_put_contents($scriptPath, $contents);
                \register_shutdown_function(static function () : void {
                    @\unlink(self::$pharScriptPath);
                });
            }
        } else {
            $scriptPath = self::SCRIPT_PATH;
        }
        return $scriptPath;
    }
    /**
     * Runner.
     *
     * @param string $session Session path
     * @param int $startup ID
     *
     * @return Promise<true>
     */
    public static abstract function start(string $session, int $startupId) : Promise;
}<?php

/**
 * API wrapper module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Ipc;

use Amp\Deferred;
use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Promise;
use Amp\Success;
use danog\Loop\SignalLoop;
use danog\MadelineProto\Exception as Exception;
use danog\MadelineProto\Ipc\Runner\ProcessRunner;
use danog\MadelineProto\Ipc\Runner\WebRunner;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\SessionPaths;
use danog\MadelineProto\Settings\Ipc;
use danog\MadelineProto\Tools;
use function Amp\Promise\first;
/**
 * IPC server.
 */
class Server extends SignalLoop
{
    use InternalLoop;
    /**
     * Server version.
     */
    const VERSION = 1;
    /**
     * Shutdown server.
     */
    const SHUTDOWN = 0;
    /**
     * Boolean to shut down worker, if started.
     */
    private static bool $shutdown = false;
    /**
     * Deferred to shut down worker, if started.
     */
    private static ?Deferred $shutdownDeferred = null;
    /**
     * Boolean whether to shut down worker, if started.
     */
    private static bool $shutdownNow = false;
    /**
     * IPC server.
     */
    protected IpcServer $server;
    /**
     * Callback IPC server.
     */
    private ServerCallback $callback;
    /**
     * IPC settings.
     */
    private Ipc $settings;
    /**
     * Set IPC path.
     *
     * @param SessionPaths $session Session
     *
     * @return void
     */
    public function setIpcPath(SessionPaths $session) : void
    {
        self::$shutdownDeferred ??= new Deferred();
        $this->server = new IpcServer($session->getIpcPath());
        $this->callback = new ServerCallback($this->API);
        $this->callback->setIpcPath($session);
    }
    /**
     *
     */
    public function start() : bool
    {
        return $this instanceof ServerCallback ? parent::start() : $this->callback->start() && parent::start();
    }
    /**
     * Start IPC server in background.
     *
     * @param SessionPaths $session Session path
     *
     * @return Promise
     */
    public static function startMe(SessionPaths $session) : Promise
    {
        $id = Tools::randomInt(2000000000);
        $started = false;
        $promises = [];
        try {
            Logger::log("Starting IPC server {$session} (process)");
            $promises[] = ProcessRunner::start($session, $id);
            $started = true;
            $promises[] = WebRunner::start($session, $id);
            return Tools::call(self::monitor($session, $id, $started, first($promises)));
        } catch (\Throwable $e) {
            Logger::log($e);
        }
        try {
            Logger::log("Starting IPC server {$session} (web)");
            $promises[] = WebRunner::start($session, $id);
            $started = true;
        } catch (\Throwable $e) {
            Logger::log($e);
        }
        return Tools::call(self::monitor($session, $id, $started, $promises ? first($promises) : (new Deferred())->promise()));
    }
    /**
     * Monitor session.
     *
     * @param SessionPaths $session
     * @param int $id
     * @param bool $started
     * @param Promise<bool> $cancelConnect
     *
     * @return \Generator
     */
    private static function monitor(SessionPaths $session, int $id, bool $started, Promise $cancelConnect) : \Generator
    {
        if (!$started) {
            Logger::log("It looks like the server couldn't be started, trying to connect anyway...");
        }
        $count = 0;
        while (true) {
            $state = (yield $session->getIpcState());
            if ($state && $state->getStartupId() === $id) {
                if ($e = $state->getException()) {
                    Logger::log("IPC server got exception {$e}");
                    return $e;
                }
                Logger::log("IPC server started successfully!");
                return true;
            } elseif (!$started && $count > 0 && $count > 2 * ($state ? 3 : 1)) {
                return new Exception("We couldn't start the IPC server, please check the logs!");
            }
            try {
                (yield Tools::timeoutWithDefault($cancelConnect, 500, null));
                $cancelConnect = (new Deferred())->promise();
            } catch (\Throwable $e) {
                Logger::log("{$e}");
                Logger::log("Could not start IPC server, please check the logs for more details!");
                return $e;
            }
            $count++;
        }
        return false;
    }
    /**
     * Wait for shutdown.
     *
     * @return Promise
     */
    public static function waitShutdown() : Promise
    {
        if (self::$shutdownNow) {
            return new Success();
        }
        self::$shutdownDeferred ??= new Deferred();
        return self::$shutdownDeferred->promise();
    }
    /**
     * Shutdown.
     *
     * @return void
     */
    public final function shutdown() : void
    {
        $this->signal(null);
        if (self::$shutdownDeferred) {
            self::$shutdownNow = true;
            $deferred = self::$shutdownDeferred;
            self::$shutdownDeferred = null;
            $deferred->resolve();
        }
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        while ($socket = (yield $this->waitSignal($this->server->accept()))) {
            Tools::callFork($this->clientLoop($socket));
        }
        $this->server->close();
        if (isset($this->callback)) {
            $this->callback->signal(null);
        }
    }
    /**
     * Client handler loop.
     *
     * @param ChannelledSocket $socket Client
     *
     * @return (\Generator | Promise)
     */
    protected function clientLoop(ChannelledSocket $socket)
    {
        $this->API->logger("Accepted IPC client connection!");
        $id = 0;
        $payload = null;
        try {
            while ($payload = (yield $socket->receive())) {
                Tools::callFork($this->clientRequest($socket, $id++, $payload));
            }
        } catch (\Throwable $e) {
            Logger::log("Exception in IPC connection: {$e}");
        } finally {
            try {
                (yield $socket->disconnect());
            } catch (\Throwable $e) {
            }
            if ($payload === self::SHUTDOWN) {
                $this->shutdown();
            }
        }
    }
    /**
     * Handle client request.
     *
     * @param ChannelledSocket $socket Socket
     * @param array{0: string, 1: (array | Wrapper)} $payload Payload
     *
     * @return \Generator
     */
    private function clientRequest(ChannelledSocket $socket, int $id, $payload) : \Generator
    {
        try {
            yield from $this->API->initAsynchronously();
            if ($payload[1] instanceof Wrapper) {
                $wrapper = $payload[1];
                $payload[1] = $this->callback->unwrap($wrapper);
            }
            $result = $this->API->{$payload[0]}(...$payload[1]);
            $result = $result instanceof \Generator ? yield from $result : ($result instanceof Promise ? (yield $result) : $result);
        } catch (\Throwable $e) {
            $this->API->logger("Got error while calling IPC method: {$e}", Logger::ERROR);
            $result = new ExitFailure($e);
        } finally {
            if (isset($wrapper)) {
                try {
                    (yield $wrapper->disconnect());
                } catch (\Throwable $e) {
                }
            }
        }
        try {
            (yield $socket->send([$id, $result]));
        } catch (\Throwable $e) {
            $this->API->logger("Got error while trying to send result of {$payload[0]}: {$e}", Logger::ERROR);
            try {
                (yield $socket->send([$id, new ExitFailure($e)]));
            } catch (\Throwable $e) {
                $this->API->logger("Got error while trying to send error of error of {$payload[0]}: {$e}", Logger::ERROR);
            }
        }
    }
    /**
     * Get the name of the loop.
     *
     * @return string
     */
    public function __toString() : string
    {
        return "IPC server";
    }
    /**
     * Set IPC settings.
     *
     * @param Ipc $settings IPC settings
     *
     * @return self
     */
    public function setSettings(Ipc $settings) : self
    {
        $this->settings = $settings;
        return $this;
    }
}<?php

/**
 * This file is automatic generated by build_docs.php file
 * and is used only for autocomplete in multiple IDE
 * don't modify manually.
 */
namespace danog\MadelineProto;

interface auth
{
    /**
    * Send the verification code for login.
    *
    * Parameters:
    `string`       **phone_number** - Phone number in international format
    `int`          **api_id**       - Application identifier (see [App configuration](https://core.telegram.org/myapp))
    `string`       **api_hash**     - Application secret hash (see [App configuration](https://core.telegram.org/myapp))
    `CodeSettings` **settings**     - Settings for the code type to send
    *
    * @param array $params Parameters
    *
    * @return auth .SentCode
    */
    public function sendCode($params);
    /**
    * Registers a validated phone number in the system.
    *
    * Parameters:
    `string` **phone_number**    - Phone number in the international format
    `string` **phone_code_hash** - SMS-message ID
    `string` **first_name**      - New user first name
    `string` **last_name**       - New user last name
    *
    * @param array $params Parameters
    *
    * @return auth .Authorization
    */
    public function signUp($params);
    /**
    * Signs in a user with a validated phone number.
    *
    * Parameters:
    `string` **phone_number**    - Phone number in the international format
    `string` **phone_code_hash** - SMS-message ID, obtained from [auth.sendCode](https://docs.madelineproto.xyz/API_docs/methods/auth.sendCode.html)
    `string` **phone_code**      - Valid numerical code from the SMS-message
    *
    * @param array $params Parameters
    *
    * @return auth .Authorization
    */
    public function signIn($params);
    /**
     * Logs out the user.
     *
     * @return auth .LoggedOut
     */
    public function logOut();
    /**
     * Terminates all user's authorized sessions except for the current one.
     *
     * After calling this method it is necessary to reregister the current device using the method [account.registerDevice](https://docs.madelineproto.xyz/API_docs/methods/account.registerDevice.html)
     *
     * @return bool
     */
    public function resetAuthorizations();
    /**
    * Returns data for copying authorization to another data-centre.
    *
    * Parameters:
    `int` **dc_id** - Number of a target data-centre
    *
    * @param array $params Parameters
    *
    * @return auth .ExportedAuthorization
    */
    public function exportAuthorization($params);
    /**
    * Logs in a user using a key transmitted from his native data-centre.
    *
    * Parameters:
    `long`  **id**    -
    `bytes` **bytes** - Authorization key
    *
    * @param array $params Parameters
    *
    * @return auth .Authorization
    */
    public function importAuthorization($params);
    /**
    * Binds a temporary authorization key `temp_auth_key_id` to the permanent authorization key `perm_auth_key_id`. Each permanent key may only be bound to one temporary key at a time, binding a new temporary key overwrites the previous one.
    *
    * For more information, see [Perfect Forward Secrecy](https://core.telegram.org/api/pfs).
    *
    * Parameters:
    `long`  **perm_auth_key_id**  - Permanent auth\_key\_id to bind to
    `long`  **nonce**             - Random long from [Binding message contents](#binding-message-contents)
    `int`   **expires_at**        - Unix timestamp to invalidate temporary key, see [Binding message contents](#binding-message-contents)
    `bytes` **encrypted_message** - See [Generating encrypted\_message](#generating-encrypted-message)
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function bindTempAuthKey($params);
    /**
    * Login as a bot.
    *
    * Parameters:
    `int`    **api_id**         - Application identifier (see. [App configuration](https://core.telegram.org/myapp))
    `string` **api_hash**       - Application identifier hash (see. [App configuration](https://core.telegram.org/myapp))
    `string` **bot_auth_token** - Bot token (see [bots](https://core.telegram.org/bots))
    *
    * @param array $params Parameters
    *
    * @return auth .Authorization
    */
    public function importBotAuthorization($params);
    /**
    * Try logging to an account protected by a [2FA password](https://core.telegram.org/api/srp).
    *
    * Parameters:
    `InputCheckPasswordSRP` **password** - The account's password (see [SRP](https://core.telegram.org/api/srp))
    *
    * @param array $params Parameters
    *
    * @return auth .Authorization
    */
    public function checkPassword($params);
    /**
     * Request recovery code of a [2FA password](https://core.telegram.org/api/srp), only for accounts with a [recovery email configured](https://core.telegram.org/api/srp#email-verification).
     *
     * @return auth .PasswordRecovery
     */
    public function requestPasswordRecovery();
    /**
    * Reset the [2FA password](https://core.telegram.org/api/srp) using the recovery code sent using [auth.requestPasswordRecovery](https://docs.madelineproto.xyz/API_docs/methods/auth.requestPasswordRecovery.html).
    *
    * Parameters:
    `string`                        **code**         - Code received via email
    `account.PasswordInputSettings` **new_settings** - Optional:
    *
    * @param array $params Parameters
    *
    * @return auth .Authorization
    */
    public function recoverPassword($params);
    /**
    * Resend the login code via another medium, the phone code type is determined by the return value of the previous auth.sendCode/auth.resendCode: see [login](https://core.telegram.org/api/auth) for more info.
    *
    * Parameters:
    `string` **phone_number**    - The phone number
    `string` **phone_code_hash** - The phone code hash obtained from [auth.sendCode](https://docs.madelineproto.xyz/API_docs/methods/auth.sendCode.html)
    *
    * @param array $params Parameters
    *
    * @return auth .SentCode
    */
    public function resendCode($params);
    /**
    * Cancel the login verification code.
    *
    * Parameters:
    `string` **phone_number**    - Phone number
    `string` **phone_code_hash** - Phone code hash from [auth.sendCode](https://docs.madelineproto.xyz/API_docs/methods/auth.sendCode.html)
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function cancelCode($params);
    /**
    * Delete all temporary authorization keys **except for** the ones specified.
    *
    * Parameters:
    `[long]` **except_auth_keys** - The auth keys that **shouldn't** be dropped.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function dropTempAuthKeys($params);
    /**
    * Generate a login token, for [login via QR code](https://core.telegram.org/api/qr-login).
    The generated login token should be encoded using base64url, then shown as a `tg://login?token=base64encodedtoken` URL in the QR code.
    *
    * For more info, see [login via QR code](https://core.telegram.org/api/qr-login).
    *
    * Parameters:
    `int`    **api_id**     - Application identifier (see. [App configuration](https://core.telegram.org/myapp))
    `string` **api_hash**   - Application identifier hash (see. [App configuration](https://core.telegram.org/myapp))
    `[long]` **except_ids** - List of already logged-in user IDs, to prevent logging in twice with the same user
    *
    * @param array $params Parameters
    *
    * @return auth .LoginToken
    */
    public function exportLoginToken($params);
    /**
    * Login using a redirected login token, generated in case of DC mismatch during [QR code login](https://core.telegram.org/api/qr-login).
    *
    * For more info, see [login via QR code](https://core.telegram.org/api/qr-login).
    *
    * Parameters:
    `bytes` **token** - Login token
    *
    * @param array $params Parameters
    *
    * @return auth .LoginToken
    */
    public function importLoginToken($params);
    /**
    * Accept QR code login token, logging in the app that generated it.
    *
    * Returns info about the new session.
    *
    * For more info, see [login via QR code](https://core.telegram.org/api/qr-login).
    *
    * Parameters:
    `bytes` **token** - Login token embedded in QR code, for more info, see [login via QR code](https://core.telegram.org/api/qr-login).
    *
    * @param array $params Parameters
    *
    * @return Authorization
    */
    public function acceptLoginToken($params);
    /**
    *
    *
    * Parameters:
    `string` **code** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function checkRecoveryPassword($params);
}
interface account
{
    /**
    * Register device to receive [PUSH notifications](https://core.telegram.org/api/push-updates).
    *
    * Parameters:
    `boolean` **no_muted**    - Optional: Avoid receiving (silent and invisible background) notifications. Useful to save battery.
    `int`     **token_type**  - Device token type.<br>**Possible values**:<br>`1` \- APNS (device token for apple push)<br>`2` \- FCM (firebase token for google firebase)<br>`3` \- MPNS (channel URI for microsoft push)<br>`4` \- Simple push (endpoint for firefox's simple push API)<br>`5` \- Ubuntu phone (token for ubuntu push)<br>`6` \- Blackberry (token for blackberry push)<br>`7` \- Unused<br>`8` \- WNS (windows push)<br>`9` \- APNS VoIP (token for apple push VoIP)<br>`10` \- Web push (web push, see below)<br>`11` \- MPNS VoIP (token for microsoft push VoIP)<br>`12` \- Tizen (token for tizen push)<br><br>For `10` web push, the token must be a JSON-encoded object containing the keys described in [PUSH updates](https://core.telegram.org/api/push-updates)
    `string`  **token**       - Device token
    `Bool`    **app_sandbox** - If [(boolTrue)](https://docs.madelineproto.xyz/API_docs/constructors/boolTrue.html) is transmitted, a sandbox-certificate will be used during transmission.
    `bytes`   **secret**      - For FCM and APNS VoIP, optional encryption key used to encrypt push notifications
    `[long]`  **other_uids**  - List of user identifiers of other users currently using the client
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function registerDevice($params);
    /**
    * Deletes a device by its token, stops sending PUSH-notifications to it.
    *
    * Parameters:
    `int`    **token_type** - Device token type.<br>**Possible values**:<br>`1` \- APNS (device token for apple push)<br>`2` \- FCM (firebase token for google firebase)<br>`3` \- MPNS (channel URI for microsoft push)<br>`4` \- Simple push (endpoint for firefox's simple push API)<br>`5` \- Ubuntu phone (token for ubuntu push)<br>`6` \- Blackberry (token for blackberry push)<br>`7` \- Unused<br>`8` \- WNS (windows push)<br>`9` \- APNS VoIP (token for apple push VoIP)<br>`10` \- Web push (web push, see below)<br>`11` \- MPNS VoIP (token for microsoft push VoIP)<br>`12` \- Tizen (token for tizen push)<br><br>For `10` web push, the token must be a JSON-encoded object containing the keys described in [PUSH updates](https://core.telegram.org/api/push-updates)
    `string` **token**      - Device token
    `[long]` **other_uids** - List of user identifiers of other users currently using the client
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function unregisterDevice($params);
    /**
    * Edits notification settings from a given user/group, from all users/all groups.
    *
    * Parameters:
    `InputNotifyPeer`         **peer**     - Notification source
    `InputPeerNotifySettings` **settings** - Notification settings
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function updateNotifySettings($params);
    /**
    * Gets current notification settings for a given user/group, from all users/all groups.
    *
    * Parameters:
    `InputNotifyPeer` **peer** - Notification source
    *
    * @param array $params Parameters
    *
    * @return PeerNotifySettings
    */
    public function getNotifySettings($params);
    /**
     * Resets all notification settings from users and groups.
     *
     * @return bool
     */
    public function resetNotifySettings();
    /**
    * Updates user profile.
    *
    * Parameters:
    `string` **first_name** - Optional: New user first name
    `string` **last_name**  - Optional: New user last name
    `string` **about**      - Optional: New bio
    *
    * @param array $params Parameters
    *
    * @return User
    */
    public function updateProfile($params);
    /**
    * Updates online user status.
    *
    * Parameters:
    `Bool` **offline** - If [(boolTrue)](https://docs.madelineproto.xyz/API_docs/constructors/boolTrue.html) is transmitted, user status will change to [(userStatusOffline)](https://docs.madelineproto.xyz/API_docs/constructors/userStatusOffline.html).
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function updateStatus($params);
    /**
    * Returns a list of available wallpapers.
    *
    * Parameters:
    `long` **hash** -
    *
    * @param array $params Parameters
    *
    * @return account .WallPapers
    */
    public function getWallPapers($params);
    /**
    * Report a peer for violation of telegram's Terms of Service.
    *
    * Parameters:
    `InputPeer`    **peer**    - The peer to report
    `ReportReason` **reason**  - The reason why this peer is being reported
    `string`       **message** -
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function reportPeer($params);
    /**
    * Validates a username and checks availability.
    *
    * Parameters:
    `string` **username** - username<br>Accepted characters: A-z (case-insensitive), 0-9 and underscores.<br>Length: 5-32 characters.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function checkUsername($params);
    /**
    * Changes username for the current user.
    *
    * Parameters:
    `string` **username** - username or empty string if username is to be removed<br>Accepted characters: a-z (case-insensitive), 0-9 and underscores.<br>Length: 5-32 characters.
    *
    * @param array $params Parameters
    *
    * @return User
    */
    public function updateUsername($params);
    /**
    * Get privacy settings of current account.
    *
    * Parameters:
    `InputPrivacyKey` **key** - Peer category whose privacy settings should be fetched
    *
    * @param array $params Parameters
    *
    * @return account .PrivacyRules
    */
    public function getPrivacy($params);
    /**
    * Change privacy settings of current account.
    *
    * Parameters:
    `InputPrivacyKey`    **key**   - Peers to which the privacy rules apply
    `[InputPrivacyRule]` **rules** - New privacy rules
    *
    * @param array $params Parameters
    *
    * @return account .PrivacyRules
    */
    public function setPrivacy($params);
    /**
    * Delete the user's account from the telegram servers. Can be used, for example, to delete the account of a user that provided the login code, but forgot the [2FA password and no recovery method is configured](https://core.telegram.org/api/srp).
    *
    * Parameters:
    `string` **reason** - Why is the account being deleted, can be empty
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function deleteAccount($params);
    /**
     * Get days to live of account.
     *
     * @return AccountDaysTTL
     */
    public function getAccountTTL();
    /**
    * Set account self-destruction period.
    *
    * Parameters:
    `AccountDaysTTL` **ttl** - Time to live in days
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setAccountTTL($params);
    /**
    * Verify a new phone number to associate to the current account.
    *
    * Parameters:
    `string`       **phone_number** - New phone number
    `CodeSettings` **settings**     - Phone code settings
    *
    * @param array $params Parameters
    *
    * @return auth .SentCode
    */
    public function sendChangePhoneCode($params);
    /**
    * Change the phone number of the current account.
    *
    * Parameters:
    `string` **phone_number**    - New phone number
    `string` **phone_code_hash** - Phone code hash received when calling [account.sendChangePhoneCode](https://docs.madelineproto.xyz/API_docs/methods/account.sendChangePhoneCode.html)
    `string` **phone_code**      - Phone code received when calling [account.sendChangePhoneCode](https://docs.madelineproto.xyz/API_docs/methods/account.sendChangePhoneCode.html)
    *
    * @param array $params Parameters
    *
    * @return User
    */
    public function changePhone($params);
    /**
    * When client-side passcode lock feature is enabled, will not show message texts in incoming [PUSH notifications](https://core.telegram.org/api/push-updates).
    *
    * Parameters:
    `int` **period** - Inactivity period after which to start hiding message texts in [PUSH notifications](https://core.telegram.org/api/push-updates).
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function updateDeviceLocked($params);
    /**
     * Get logged-in sessions.
     *
     * @return account .Authorizations
     */
    public function getAuthorizations();
    /**
    * Log out an active [authorized session](https://core.telegram.org/api/auth) by its hash.
    *
    * Parameters:
    `long` **hash** - Session hash
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function resetAuthorization($params);
    /**
     * Obtain configuration for two-factor authorization with password.
     *
     * @return account .Password
     */
    public function getPassword();
    /**
    * Get private info associated to the password info (recovery email, telegram [passport](https://core.telegram.org/passport) info &amp; so on).
    *
    * Parameters:
    `InputCheckPasswordSRP` **password** - The password (see [SRP](https://core.telegram.org/api/srp))
    *
    * @param array $params Parameters
    *
    * @return account .PasswordSettings
    */
    public function getPasswordSettings($params);
    /**
    * Set a new 2FA password.
    *
    * Parameters:
    `InputCheckPasswordSRP`         **password**     - The old password (see [SRP](https://core.telegram.org/api/srp))
    `account.PasswordInputSettings` **new_settings** - The new password (see [SRP](https://core.telegram.org/api/srp))
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function updatePasswordSettings($params);
    /**
    * Send confirmation code to cancel account deletion, for more info [click here Â»](https://core.telegram.org/api/account-deletion).
    *
    * Parameters:
    `string`       **hash**     - The hash from the service notification, for more info [click here Â»](https://core.telegram.org/api/account-deletion)
    `CodeSettings` **settings** - Phone code settings
    *
    * @param array $params Parameters
    *
    * @return auth .SentCode
    */
    public function sendConfirmPhoneCode($params);
    /**
    * Confirm a phone number to cancel account deletion, for more info [click here Â»](https://core.telegram.org/api/account-deletion).
    *
    * Parameters:
    `string` **phone_code_hash** - Phone code hash, for more info [click here Â»](https://core.telegram.org/api/account-deletion)
    `string` **phone_code**      - SMS code, for more info [click here Â»](https://core.telegram.org/api/account-deletion)
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function confirmPhone($params);
    /**
    * Get temporary payment password.
    *
    * Parameters:
    `InputCheckPasswordSRP` **password** - SRP password parameters
    `int`                   **period**   - Time during which the temporary password will be valid, in seconds; should be between 60 and 86400
    *
    * @param array $params Parameters
    *
    * @return account .TmpPassword
    */
    public function getTmpPassword($params);
    /**
     * Get web [login widget](https://core.telegram.org/widgets/login) authorizations.
     *
     * @return account .WebAuthorizations
     */
    public function getWebAuthorizations();
    /**
    * Log out an active web [telegram login](https://core.telegram.org/widgets/login) session.
    *
    * Parameters:
    `long` **hash** - [Session](https://docs.madelineproto.xyz/API_docs/constructors/webAuthorization.html) hash
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function resetWebAuthorization($params);
    /**
     * Reset all active web [telegram login](https://core.telegram.org/widgets/login) sessions.
     *
     * @return bool
     */
    public function resetWebAuthorizations();
    /**
     * Get all saved [Telegram Passport](https://core.telegram.org/passport) documents, [for more info see the passport docs Â»](https://core.telegram.org/passport/encryption#encryption).
     *
     * @return of SecureValue[]
     */
    public function getAllSecureValues();
    /**
    * Get saved [Telegram Passport](https://core.telegram.org/passport) document, [for more info see the passport docs Â»](https://core.telegram.org/passport/encryption#encryption).
    *
    * Parameters:
    `[SecureValueType]` **types** - Requested value types
    *
    * @param array $params Parameters
    *
    * @return of SecureValue[]
    */
    public function getSecureValue($params);
    /**
    * Securely save [Telegram Passport](https://core.telegram.org/passport) document, [for more info see the passport docs Â»](https://core.telegram.org/passport/encryption#encryption).
    *
    * Parameters:
    `InputSecureValue` **value**            - Secure value, [for more info see the passport docs Â»](https://core.telegram.org/passport/encryption#encryption)
    `long`             **secure_secret_id** - Passport secret hash, [for more info see the passport docs Â»](https://core.telegram.org/passport/encryption#encryption)
    *
    * @param array $params Parameters
    *
    * @return SecureValue
    */
    public function saveSecureValue($params);
    /**
    * Delete stored [Telegram Passport](https://core.telegram.org/passport) documents, [for more info see the passport docs Â»](https://core.telegram.org/passport/encryption#encryption).
    *
    * Parameters:
    `[SecureValueType]` **types** - Document types to delete
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function deleteSecureValue($params);
    /**
    * Returns a Telegram Passport authorization form for sharing data with a service.
    *
    * Parameters:
    `long`   **bot_id**     -
    `string` **scope**      - Telegram Passport element types requested by the service
    `string` **public_key** - Service's public key
    *
    * @param array $params Parameters
    *
    * @return account .AuthorizationForm
    */
    public function getAuthorizationForm($params);
    /**
    * Sends a Telegram Passport authorization form, effectively sharing data with the service.
    *
    * Parameters:
    `long`                       **bot_id**       -
    `string`                     **scope**        - Telegram Passport element types requested by the service
    `string`                     **public_key**   - Service's public key
    `[SecureValueHash]`          **value_hashes** - Types of values sent and their hashes
    `SecureCredentialsEncrypted` **credentials**  - Encrypted values
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function acceptAuthorization($params);
    /**
    * Send the verification phone code for telegram [passport](https://core.telegram.org/passport).
    *
    * Parameters:
    `string`       **phone_number** - The phone number to verify
    `CodeSettings` **settings**     - Phone code settings
    *
    * @param array $params Parameters
    *
    * @return auth .SentCode
    */
    public function sendVerifyPhoneCode($params);
    /**
    * Verify a phone number for telegram [passport](https://core.telegram.org/passport).
    *
    * Parameters:
    `string` **phone_number**    - Phone number
    `string` **phone_code_hash** - Phone code hash received from the call to [account.sendVerifyPhoneCode](https://docs.madelineproto.xyz/API_docs/methods/account.sendVerifyPhoneCode.html)
    `string` **phone_code**      - Code received after the call to [account.sendVerifyPhoneCode](https://docs.madelineproto.xyz/API_docs/methods/account.sendVerifyPhoneCode.html)
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function verifyPhone($params);
    /**
    * Send the verification email code for telegram [passport](https://core.telegram.org/passport).
    *
    * Parameters:
    `string` **email** - The email where to send the code
    *
    * @param array $params Parameters
    *
    * @return account .SentEmailCode
    */
    public function sendVerifyEmailCode($params);
    /**
    * Verify an email address for telegram [passport](https://core.telegram.org/passport).
    *
    * Parameters:
    `string` **email** - The email to verify
    `string` **code**  - The verification code that was received
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function verifyEmail($params);
    /**
    * Intialize account takeout session.
    *
    * Parameters:
    `boolean` **contacts**           - Optional: Whether to export contacts
    `boolean` **message_users**      - Optional: Whether to export messages in private chats
    `boolean` **message_chats**      - Optional: Whether to export messages in [legacy groups](https://core.telegram.org/api/channel)
    `boolean` **message_megagroups** - Optional: Whether to export messages in [supergroups](https://core.telegram.org/api/channel)
    `boolean` **message_channels**   - Optional: Whether to export messages in [channels](https://core.telegram.org/api/channel)
    `boolean` **files**              - Optional: Whether to export files
    `int`     **file_max_size**      - Optional: Maximum size of files to export
    *
    * @param array $params Parameters
    *
    * @return account .Takeout
    */
    public function initTakeoutSession($params);
    /**
    * Finish account takeout session.
    *
    * Parameters:
    `boolean` **success** - Optional: Data exported successfully
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function finishTakeoutSession($params);
    /**
    * Verify an email to use as [2FA recovery method](https://core.telegram.org/api/srp).
    *
    * Parameters:
    `string` **code** - The phone code that was received after [setting a recovery email](https://core.telegram.org/api/srp#email-verification)
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function confirmPasswordEmail($params);
    /**
     * Resend the code to verify an email to use as [2FA recovery method](https://core.telegram.org/api/srp).
     *
     * @return bool
     */
    public function resendPasswordEmail();
    /**
     * Cancel the code that was sent to verify an email to use as [2FA recovery method](https://core.telegram.org/api/srp).
     *
     * @return bool
     */
    public function cancelPasswordEmail();
    /**
     * Whether the user will receive notifications when contacts sign up.
     *
     * @return bool
     */
    public function getContactSignUpNotification();
    /**
    * Toggle contact sign up notifications.
    *
    * Parameters:
    `Bool` **silent** - Whether to disable contact sign up notifications
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setContactSignUpNotification($params);
    /**
    * Returns list of chats with non-default notification settings.
    *
    * Parameters:
    `boolean`         **compare_sound** - Optional: If true, chats with non-default sound will also be returned
    `InputNotifyPeer` **peer**          - Optional: If specified, only chats of the specified category will be returned
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function getNotifyExceptions($params);
    /**
    * Get info about a certain wallpaper.
    *
    * Parameters:
    `InputWallPaper` **wallpaper** - The wallpaper to get info about
    *
    * @param array $params Parameters
    *
    * @return WallPaper
    */
    public function getWallPaper($params);
    /**
    * Create and upload a new wallpaper.
    *
    * Parameters:
    `InputFile`         **file**      - The JPG/PNG wallpaper
    `string`            **mime_type** - MIME type of uploaded wallpaper
    `WallPaperSettings` **settings**  - Wallpaper settings
    *
    * @param array $params Parameters
    *
    * @return WallPaper
    */
    public function uploadWallPaper($params);
    /**
    * Install/uninstall wallpaper.
    *
    * Parameters:
    `InputWallPaper`    **wallpaper** - Wallpaper to save
    `Bool`              **unsave**    - Uninstall wallpaper?
    `WallPaperSettings` **settings**  - Wallpaper settings
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveWallPaper($params);
    /**
    * Install wallpaper.
    *
    * Parameters:
    `InputWallPaper`    **wallpaper** - Wallpaper to install
    `WallPaperSettings` **settings**  - Wallpaper settings
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function installWallPaper($params);
    /**
     * Delete installed wallpapers.
     *
     * @return bool
     */
    public function resetWallPapers();
    /**
     * Get media autodownload settings.
     *
     * @return account .AutoDownloadSettings
     */
    public function getAutoDownloadSettings();
    /**
    * Change media autodownload settings.
    *
    * Parameters:
    `boolean`              **low**      - Optional: Whether to save settings in the low data usage preset
    `boolean`              **high**     - Optional: Whether to save settings in the high data usage preset
    `AutoDownloadSettings` **settings** - Media autodownload settings
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveAutoDownloadSettings($params);
    /**
    * Upload theme.
    *
    * Parameters:
    `InputFile` **file**      - Theme file uploaded as described in [files Â»](https://core.telegram.org/api/files)
    `InputFile` **thumb**     - Optional: Thumbnail
    `string`    **file_name** - File name
    `string`    **mime_type** - MIME type, must be `application/x-tgtheme-{format}`, where `format` depends on the client
    *
    * @param array $params Parameters
    *
    * @return Document
    */
    public function uploadTheme($params);
    /**
    * Create a theme.
    *
    * Parameters:
    `string`               **slug**     - Unique theme ID
    `string`               **title**    - Theme name
    `InputDocument`        **document** - Optional: Theme file
    `[InputThemeSettings]` **settings** - Optional:
    *
    * @param array $params Parameters
    *
    * @return Theme
    */
    public function createTheme($params);
    /**
    * Update theme.
    *
    * Parameters:
    `string`               **format**   - Theme format, a string that identifies the theming engines supported by the client
    `InputTheme`           **theme**    - Theme to update
    `string`               **slug**     - Optional: Unique theme ID
    `string`               **title**    - Optional: Theme name
    `InputDocument`        **document** - Optional: Theme file
    `[InputThemeSettings]` **settings** - Optional:
    *
    * @param array $params Parameters
    *
    * @return Theme
    */
    public function updateTheme($params);
    /**
    * Save a theme.
    *
    * Parameters:
    `InputTheme` **theme**  - Theme to save
    `Bool`       **unsave** - Unsave
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveTheme($params);
    /**
    * Install a theme.
    *
    * Parameters:
    `boolean`    **dark**       - Optional: Whether to install the dark version
    `InputTheme` **theme**      - Optional: Theme to install
    `string`     **format**     - Optional: Theme format, a string that identifies the theming engines supported by the client
    `BaseTheme`  **base_theme** - Optional:
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function installTheme($params);
    /**
    * Get theme information.
    *
    * Parameters:
    `string`     **format**      - Theme format, a string that identifies the theming engines supported by the client
    `InputTheme` **theme**       - Theme
    `long`       **document_id** - Document ID
    *
    * @param array $params Parameters
    *
    * @return Theme
    */
    public function getTheme($params);
    /**
    * Get installed themes.
    *
    * Parameters:
    `string` **format** - Theme format, a string that identifies the theming engines supported by the client
    `long`   **hash**   -
    *
    * @param array $params Parameters
    *
    * @return account .Themes
    */
    public function getThemes($params);
    /**
    * Set sensitive content settings (for viewing or hiding NSFW content).
    *
    * Parameters:
    `boolean` **sensitive_enabled** - Optional: Enable NSFW content
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setContentSettings($params);
    /**
     * Get sensitive content settings.
     *
     * @return account .ContentSettings
     */
    public function getContentSettings();
    /**
    * Get info about multiple wallpapers.
    *
    * Parameters:
    `[InputWallPaper]` **wallpapers** - Wallpapers to fetch info about
    *
    * @param array $params Parameters
    *
    * @return of WallPaper[]
    */
    public function getMultiWallPapers($params);
    /**
     * Get global privacy settings.
     *
     * @return GlobalPrivacySettings
     */
    public function getGlobalPrivacySettings();
    /**
    * Set global privacy settings.
    *
    * Parameters:
    `GlobalPrivacySettings` **settings** - Global privacy settings
    *
    * @param array $params Parameters
    *
    * @return GlobalPrivacySettings
    */
    public function setGlobalPrivacySettings($params);
    /**
    *
    *
    * Parameters:
    `InputPeer`    **peer**     -
    `InputPhoto`   **photo_id** -
    `ReportReason` **reason**   -
    `string`       **message**  -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function reportProfilePhoto($params);
    /**
     *
     *
     * @return account .ResetPasswordResult
     */
    public function resetPassword();
    /**
     *
     *
     * @return bool
     */
    public function declinePasswordReset();
    /**
    *
    *
    * Parameters:
    `long` **hash** -.
    *
    * @param array $params Parameters
    *
    * @return account .Themes
    */
    public function getChatThemes($params);
    /**
    *
    *
    * Parameters:
    `int` **authorization_ttl_days** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setAuthorizationTTL($params);
    /**
    *
    *
    * Parameters:
    `long` **hash**                        -
    `Bool` **encrypted_requests_disabled** - Optional:
    `Bool` **call_requests_disabled**      - Optional:.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function changeAuthorizationSettings($params);
}
interface users
{
    /**
    * Returns basic user info according to their identifiers.
    *
    * Parameters:
    `[InputUser]` **id** - List of user identifiers
    *
    * @param array $params Parameters
    *
    * @return of User[]
    */
    public function getUsers($params);
    /**
    * Returns extended user info by ID.
    *
    * Parameters:
    `InputUser` **id** - User ID
    *
    * @param array $params Parameters
    *
    * @return users .UserFull
    */
    public function getFullUser($params);
    /**
    * Notify the user that the sent [passport](https://core.telegram.org/passport) data contains some errors The user will not be able to re-submit their Passport data to you until the errors are fixed (the contents of the field for which you returned the error must change).
    *
    * Use this if the data submitted by the user doesn't satisfy the standards your service requires for any reason. For example, if a birthday date seems invalid, a submitted document is blurry, a scan shows evidence of tampering, etc. Supply some details in the error message to make sure the user knows how to correct the issues.
    *
    * Parameters:
    `InputUser`          **id**     - The user
    `[SecureValueError]` **errors** - Errors
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setSecureValueErrors($params);
}
interface contacts
{
    /**
    * Get contact by telegram IDs.
    *
    * Parameters:
    `long` **hash** -
    *
    * @param array $params Parameters
    *
    * @return of int[]
    */
    public function getContactIDs($params);
    /**
     * Returns the list of contact statuses.
     *
     * @return of ContactStatus[]
     */
    public function getStatuses();
    /**
    * Returns the current user's contact list.
    *
    * Parameters:
    `long` **hash** -
    *
    * @param array $params Parameters
    *
    * @return contacts .Contacts
    */
    public function getContacts($params);
    /**
    * Imports contacts: saves a full list on the server, adds already registered contacts to the contact list, returns added contacts and their info.
    *
    * Use [contacts.addContact](https://docs.madelineproto.xyz/API_docs/methods/contacts.addContact.html) to add Telegram contacts without actually using their phone number.
    *
    * Parameters:
    `[InputContact]` **contacts** - List of contacts to import
    *
    * @param array $params Parameters
    *
    * @return contacts .ImportedContacts
    */
    public function importContacts($params);
    /**
    * Deletes several contacts from the list.
    *
    * Parameters:
    `[InputUser]` **id** - User ID list
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function deleteContacts($params);
    /**
    * Delete contacts by phone number.
    *
    * Parameters:
    `[string]` **phones** - Phone numbers
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function deleteByPhones($params);
    /**
    * Adds the user to the blacklist.
    *
    * Parameters:
    `InputPeer` **id** - User ID
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function block($params);
    /**
    * Deletes the user from the blacklist.
    *
    * Parameters:
    `InputPeer` **id** - User ID
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function unblock($params);
    /**
    * Returns the list of blocked users.
    *
    * Parameters:
    `int` **offset** - The number of list elements to be skipped
    `int` **limit**  - The number of list elements to be returned
    *
    * @param array $params Parameters
    *
    * @return contacts .Blocked
    */
    public function getBlocked($params);
    /**
    * Returns users found by username substring.
    *
    * Parameters:
    `string` **q**     - Target substring
    `int`    **limit** - Maximum number of users to be returned
    *
    * @param array $params Parameters
    *
    * @return contacts .Found
    */
    public function search($params);
    /**
    * Resolve a @username to get peer info.
    *
    * Parameters:
    `string` **username** - @username to resolve
    *
    * @param array $params Parameters
    *
    * @return contacts .ResolvedPeer
    */
    public function resolveUsername($params);
    /**
    * Get most used peers.
    *
    * Parameters:
    `boolean` **correspondents** - Optional: Users we've chatted most frequently with
    `boolean` **bots_pm**        - Optional: Most used bots
    `boolean` **bots_inline**    - Optional: Most used inline bots
    `boolean` **phone_calls**    - Optional: Most frequently called users
    `boolean` **forward_users**  - Optional: Users to which the users often forwards messages to
    `boolean` **forward_chats**  - Optional: Chats to which the users often forwards messages to
    `boolean` **groups**         - Optional: Often-opened groups and supergroups
    `boolean` **channels**       - Optional: Most frequently visited channels
    `int`     **offset**         - Offset for [pagination](https://core.telegram.org/api/offsets)
    `int`     **limit**          - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    `long`    **hash**           -
    *
    * @param array $params Parameters
    *
    * @return contacts .TopPeers
    */
    public function getTopPeers($params);
    /**
    * Reset [rating](https://core.telegram.org/api/top-rating) of top peer.
    *
    * Parameters:
    `TopPeerCategory` **category** - Top peer category
    `InputPeer`       **peer**     - Peer whose rating should be reset
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function resetTopPeerRating($params);
    /**
     * Delete saved contacts.
     *
     * @return bool
     */
    public function resetSaved();
    /**
     * Get all contacts.
     *
     * @return of SavedContact[]
     */
    public function getSaved();
    /**
    * Enable/disable [top peers](https://core.telegram.org/api/top-rating).
    *
    * Parameters:
    `Bool` **enabled** - Enable/disable
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function toggleTopPeers($params);
    /**
    * Add an existing telegram user as contact.
    *
    * Use [contacts.importContacts](https://docs.madelineproto.xyz/API_docs/methods/contacts.importContacts.html) to add contacts by phone number, without knowing their Telegram ID.
    *
    * Parameters:
    `boolean`   **add_phone_privacy_exception** - Optional: Allow the other user to see our phone number?
    `InputUser` **id**                          - Telegram ID of the other user
    `string`    **first_name**                  - First name
    `string`    **last_name**                   - Last name
    `string`    **phone**                       - User's phone number
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function addContact($params);
    /**
    * If the [peer settings](https://docs.madelineproto.xyz/API_docs/constructors/peerSettings.html) of a new user allow us to add him as contact, add that user as contact.
    *
    * Parameters:
    `InputUser` **id** - The user to add as contact
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function acceptContact($params);
    /**
    * Get contacts near you.
    *
    * Parameters:
    `boolean`       **background**   - Optional: While the geolocation of the current user is public, clients should update it in the background every half-an-hour or so, while setting this flag. <br>Do this only if the new location is more than 1 KM away from the previous one, or if the previous location is unknown.
    `InputGeoPoint` **geo_point**    - Geolocation
    `int`           **self_expires** - Optional: If set, the geolocation of the current user will be public for the specified number of seconds; pass 0x7fffffff to disable expiry, 0 to make the current geolocation private; if the flag isn't set, no changes will be applied.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function getLocated($params);
    /**
    * Stop getting notifications about [thread replies](https://core.telegram.org/api/threads) of a certain user in `@replies`.
    *
    * Parameters:
    `boolean` **delete_message** - Optional: Whether to delete the specified message as well
    `boolean` **delete_history** - Optional: Whether to delete all `@replies` messages from this user as well
    `boolean` **report_spam**    - Optional: Whether to also report this user for spam
    `int`     **msg_id**         - ID of the message in the [@replies](https://core.telegram.org/api/threads#replies) chat
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function blockFromReplies($params);
}
interface messages
{
    /**
    * Returns the list of messages by their IDs.
    *
    * Parameters:
    `[InputMessage]` **id** - Message ID list
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getMessages($params);
    /**
    * Returns the current user dialog list.
    *
    * Parameters:
    `boolean`   **exclude_pinned** - Optional: Exclude pinned dialogs
    `int`       **folder_id**      - Optional: [Peer folder ID, for more info click here](https://core.telegram.org/api/folders#peer-folders)
    `int`       **offset_date**    - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`       **offset_id**      - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `InputPeer` **offset_peer**    - [Offset peer for pagination](https://core.telegram.org/api/offsets)
    `int`       **limit**          - Number of list elements to be returned
    `long`      **hash**           -
    *
    * @param array $params Parameters
    *
    * @return messages .Dialogs
    */
    public function getDialogs($params);
    /**
    * Gets back the conversation history with one interlocutor / within a chat.
    *
    * Parameters:
    `InputPeer` **peer**        - Target peer
    `int`       **offset_id**   - Only return messages starting from the specified message ID
    `int`       **offset_date** - Only return messages sent before the specified date
    `int`       **add_offset**  - Number of list elements to be skipped, negative values are also accepted.
    `int`       **limit**       - Number of results to return
    `int`       **max_id**      - If a positive value was transferred, the method will return only messages with IDs less than **max\_id**
    `int`       **min_id**      - If a positive value was transferred, the method will return only messages with IDs more than **min\_id**
    `long`      **hash**        -
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getHistory($params);
    /**
    * Gets back found messages.
    *
    * Parameters:
    `InputPeer`      **peer**       - User or chat, histories with which are searched, or [(inputPeerEmpty)](https://docs.madelineproto.xyz/API_docs/constructors/inputPeerEmpty.html) constructor for global search
    `string`         **q**          - Text search request
    `InputPeer`      **from_id**    - Optional: Only return messages sent by the specified user ID
    `int`            **top_msg_id** - Optional: [Thread ID](https://core.telegram.org/api/threads)
    `MessagesFilter` **filter**     - Filter to return only specified message types
    `int`            **min_date**   - If a positive value was transferred, only messages with a sending date bigger than the transferred one will be returned
    `int`            **max_date**   - If a positive value was transferred, only messages with a sending date smaller than the transferred one will be returned
    `int`            **offset_id**  - Only return messages starting from the specified message ID
    `int`            **add_offset** - [Additional offset](https://core.telegram.org/api/offsets)
    `int`            **limit**      - [Number of results to return](https://core.telegram.org/api/offsets)
    `int`            **max_id**     - [Maximum message ID to return](https://core.telegram.org/api/offsets)
    `int`            **min_id**     - [Minimum message ID to return](https://core.telegram.org/api/offsets)
    `long`           **hash**       -
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function search($params);
    /**
    * Marks message history as read.
    *
    * Parameters:
    `InputPeer` **peer**   - Target user or group
    `int`       **max_id** - If a positive value is passed, only messages with identifiers less or equal than the given one will be read
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedMessages
    */
    public function readHistory($params);
    /**
    * Deletes communication history.
    *
    * Parameters:
    `boolean`   **just_clear** - Optional: Just clear history for the current user, without actually removing messages for every chat user
    `boolean`   **revoke**     - Optional: Whether to delete the message history for all chat participants
    `InputPeer` **peer**       - User or chat, communication history of which will be deleted
    `int`       **max_id**     - Maximum ID of message to delete
    `int`       **min_date**   - Optional:
    `int`       **max_date**   - Optional:
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedHistory
    */
    public function deleteHistory($params);
    /**
    * Deletes messages by their identifiers.
    *
    * Parameters:
    `boolean` **revoke** - Optional: Whether to delete messages for all participants of the chat
    `[int]`   **id**     - Message ID list
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedMessages
    */
    public function deleteMessages($params);
    /**
    * Confirms receipt of messages by a client, cancels PUSH-notification sending.
    *
    * Parameters:
    `int` **max_id** - Maximum message ID available in a client.
    *
    * @param array $params Parameters
    *
    * @return of ReceivedNotifyMessage[]
    */
    public function receivedMessages($params);
    /**
    * Sends a current user typing event (see [SendMessageAction](https://docs.madelineproto.xyz/API_docs/types/SendMessageAction.html) for all event types) to a conversation partner or group.
    *
    * Parameters:
    `InputPeer`         **peer**       - Target user or group
    `int`               **top_msg_id** - Optional: [Thread ID](https://core.telegram.org/api/threads)
    `SendMessageAction` **action**     - Type of action<br>Parameter added in [Layer 17](https://core.telegram.org/api/layers#layer-17).
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setTyping($params);
    /**
    * Sends a message to a chat.
    *
    * Parameters:
    `boolean`         **no_webpage**      - Optional: Set this flag to disable generation of the webpage preview
    `boolean`         **silent**          - Optional: Send this message silently (no notifications for the receivers)
    `boolean`         **background**      - Optional: Send this message as background message
    `boolean`         **clear_draft**     - Optional: Clear the draft field
    `InputPeer`       **peer**            - The destination where the message will be sent
    `int`             **reply_to_msg_id** - Optional: The message ID to which this message will reply to
    `string`          **message**         - The message
    `ReplyMarkup`     **reply_markup**    - Optional: Reply markup for sending bot buttons
    `[MessageEntity]` **entities**        - Optional: Message [entities](https://core.telegram.org/api/entities) for sending styled text
    `int`             **schedule_date**   - Optional: Scheduled message date for [scheduled messages](https://core.telegram.org/api/scheduled-messages)
    `InputPeer`       **send_as**         - Optional:
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function sendMessage($params);
    /**
    * Send a media.
    *
    * Parameters:
    `boolean`         **silent**          - Optional: Send message silently (no notification should be triggered)
    `boolean`         **background**      - Optional: Send message in background
    `boolean`         **clear_draft**     - Optional: Clear the draft
    `InputPeer`       **peer**            - Destination
    `int`             **reply_to_msg_id** - Optional: Message ID to which this message should reply to
    `InputMedia`      **media**           - Attached media
    `string`          **message**         - Caption
    `ReplyMarkup`     **reply_markup**    - Optional: Reply markup for bot keyboards
    `[MessageEntity]` **entities**        - Optional: Message [entities](https://core.telegram.org/api/entities) for styled text
    `int`             **schedule_date**   - Optional: Scheduled message date for [scheduled messages](https://core.telegram.org/api/scheduled-messages)
    `InputPeer`       **send_as**         - Optional:
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function sendMedia($params);
    /**
    * Forwards messages by their IDs.
    *
    * Parameters:
    `boolean`   **silent**              - Optional: Whether to send messages silently (no notification will be triggered on the destination clients)
    `boolean`   **background**          - Optional: Whether to send the message in background
    `boolean`   **with_my_score**       - Optional: When forwarding games, whether to include your score in the game
    `boolean`   **drop_author**         - Optional:
    `boolean`   **drop_media_captions** - Optional:
    `InputPeer` **from_peer**           - Source of messages
    `[int]`     **id**                  - IDs of messages
    `InputPeer` **to_peer**             - Destination peer
    `int`       **schedule_date**       - Optional: Scheduled message date for scheduled messages
    `InputPeer` **send_as**             - Optional:
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function forwardMessages($params);
    /**
    * Report a new incoming chat for spam, if the [peer settings](https://docs.madelineproto.xyz/API_docs/constructors/peerSettings.html) of the chat allow us to do that.
    *
    * Parameters:
    `InputPeer` **peer** - Peer to report
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function reportSpam($params);
    /**
    * Get peer settings.
    *
    * Parameters:
    `InputPeer` **peer** - The peer
    *
    * @param array $params Parameters
    *
    * @return messages .PeerSettings
    */
    public function getPeerSettings($params);
    /**
    * Report a message in a chat for violation of telegram's Terms of Service.
    *
    * Parameters:
    `InputPeer`    **peer**    - Peer
    `[int]`        **id**      - IDs of messages to report
    `ReportReason` **reason**  - Why are these messages being reported
    `string`       **message** -
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function report($params);
    /**
    * Returns chat basic info on their IDs.
    *
    * Parameters:
    `[long]` **id** - List of chat IDs
    *
    * @param array $params Parameters
    *
    * @return messages .Chats
    */
    public function getChats($params);
    /**
    * Returns full chat info according to its ID.
    *
    * Parameters:
    `InputPeer` **chat_id** -
    *
    * @param array $params Parameters
    *
    * @return messages .ChatFull
    */
    public function getFullChat($params);
    /**
    * Chanages chat name and sends a service message on it.
    *
    * Parameters:
    `InputPeer` **chat_id** -
    `string`    **title**   - New chat name, different from the old one
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editChatTitle($params);
    /**
    * Changes chat photo and sends a service message on it.
    *
    * Parameters:
    `InputPeer`      **chat_id** -
    `InputChatPhoto` **photo**   - Photo to be set
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editChatPhoto($params);
    /**
    * Adds a user to a chat and sends a service message on it.
    *
    * Parameters:
    `InputPeer` **chat_id**   -
    `InputUser` **user_id**   - User ID to be added
    `int`       **fwd_limit** - Number of last messages to be forwarded
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function addChatUser($params);
    /**
    * Deletes a user from a chat and sends a service message on it.
    *
    * Parameters:
    `boolean`   **revoke_history** - Optional:
    `InputPeer` **chat_id**        -
    `InputUser` **user_id**        - User ID to be deleted
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function deleteChatUser($params);
    /**
    * Creates a new chat.
    *
    * Parameters:
    `[InputUser]` **users** - List of user IDs to be invited
    `string`      **title** - Chat name
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function createChat($params);
    /**
    * Returns configuration parameters for Diffie-Hellman key generation. Can also return a random sequence of bytes of required length.
    *
    * Parameters:
    `int` **version**       - Value of the **version** parameter from [messages.dhConfig](https://docs.madelineproto.xyz/API_docs/constructors/messages.dhConfig.html), avialable at the client
    `int` **random_length** - Length of the required random sequence
    *
    * @param array $params Parameters
    *
    * @return messages .DhConfig
    */
    public function getDhConfig($params);
    /**
    * Sends a request to start a secret chat to the user.
    *
    * Parameters:
    `InputUser` **user_id** - User ID
    `bytes`     **g_a**     - `A = g ^ a mod p`, see [Wikipedia](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)
    *
    * @param array $params Parameters
    *
    * @return EncryptedChat
    */
    public function requestEncryption($params);
    /**
    * Confirms creation of a secret chat.
    *
    * Parameters:
    `InputEncryptedChat` **peer**            - Secret chat ID
    `bytes`              **g_b**             - `B = g ^ b mod p`, see [Wikipedia](https://en.wikipedia.org/wiki/Diffie%E2%80%93Hellman_key_exchange)
    `long`               **key_fingerprint** - 64-bit fingerprint of the received key
    *
    * @param array $params Parameters
    *
    * @return EncryptedChat
    */
    public function acceptEncryption($params);
    /**
    * Cancels a request for creation and/or delete info on secret chat.
    *
    * Parameters:
    `boolean` **delete_history** - Optional:
    `int`     **chat_id**        - Secret chat ID
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function discardEncryption($params);
    /**
    * Send typing event by the current user to a secret chat.
    *
    * Parameters:
    `InputEncryptedChat` **peer**   - Secret chat ID
    `Bool`               **typing** - Typing.<br>**Possible values**:<br>[(boolTrue)](https://docs.madelineproto.xyz/API_docs/constructors/boolTrue.html), if the user started typing and more than **5 seconds** have passed since the last request<br>[(boolFalse)](https://docs.madelineproto.xyz/API_docs/constructors/boolFalse.html), if the user stopped typing
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setEncryptedTyping($params);
    /**
    * Marks message history within a secret chat as read.
    *
    * Parameters:
    `InputEncryptedChat` **peer**     - Secret chat ID
    `int`                **max_date** - Maximum date value for received messages in history
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function readEncryptedHistory($params);
    /**
    * Sends a text message to a secret chat.
    *
    * Parameters:
    `boolean`            **silent**  - Optional: Send encrypted message without a notification
    `InputEncryptedChat` **peer**    - Secret chat ID
    `DecryptedMessage`   **message** -
    *
    * @param array $params Parameters
    *
    * @return messages .SentEncryptedMessage
    */
    public function sendEncrypted($params);
    /**
    * Sends a message with a file attachment to a secret chat.
    *
    * Parameters:
    `boolean`            **silent**  - Optional: Whether to send the file without triggering a notification
    `InputEncryptedChat` **peer**    - Secret chat ID
    `DecryptedMessage`   **message** -
    `InputEncryptedFile` **file**    - File attachment for the secret chat
    *
    * @param array $params Parameters
    *
    * @return messages .SentEncryptedMessage
    */
    public function sendEncryptedFile($params);
    /**
    * Sends a service message to a secret chat.
    *
    * Parameters:
    `InputEncryptedChat` **peer**    - Secret chat ID
    `DecryptedMessage`   **message** -
    *
    * @param array $params Parameters
    *
    * @return messages .SentEncryptedMessage
    */
    public function sendEncryptedService($params);
    /**
    * Confirms receipt of messages in a secret chat by client, cancels push notifications.
    *
    * Parameters:
    `int` **max_qts** - Maximum qts value available at the client
    *
    * @param array $params Parameters
    *
    * @return of long[]
    */
    public function receivedQueue($params);
    /**
    * Report a secret chat for spam.
    *
    * Parameters:
    `InputEncryptedChat` **peer** - The secret chat to report
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function reportEncryptedSpam($params);
    /**
    * Notifies the sender about the recipient having listened a voice message or watched a video.
    *
    * Parameters:
    `[int]` **id** - Message ID list
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedMessages
    */
    public function readMessageContents($params);
    /**
    * Get stickers by emoji.
    *
    * Parameters:
    `string` **emoticon** - The emoji
    `long`   **hash**     -
    *
    * @param array $params Parameters
    *
    * @return messages .Stickers
    */
    public function getStickers($params);
    /**
    * Get all installed stickers.
    *
    * Parameters:
    `long` **hash** -
    *
    * @param array $params Parameters
    *
    * @return messages .AllStickers
    */
    public function getAllStickers($params);
    /**
    * Get preview of webpage.
    *
    * Parameters:
    `string`          **message**  - Message from which to extract the preview
    `[MessageEntity]` **entities** - Optional: [Message entities for styled text](https://core.telegram.org/api/entities)
    *
    * @param array $params Parameters
    *
    * @return MessageMedia
    */
    public function getWebPagePreview($params);
    /**
    * Export an invite link for a chat.
    *
    * Parameters:
    `boolean`   **legacy_revoke_permanent** - Optional:
    `boolean`   **request_needed**          - Optional:
    `InputPeer` **peer**                    - Chat
    `int`       **expire_date**             - Optional:
    `int`       **usage_limit**             - Optional:
    `string`    **title**                   - Optional:
    *
    * @param array $params Parameters
    *
    * @return ExportedChatInvite
    */
    public function exportChatInvite($params);
    /**
    * Check the validity of a chat invite link and get basic info about it.
    *
    * Parameters:
    `string` **hash** - Invite hash in `t.me/joinchat/hash`
    *
    * @param array $params Parameters
    *
    * @return ChatInvite
    */
    public function checkChatInvite($params);
    /**
    * Import a chat invite and join a private chat/supergroup/channel.
    *
    * Parameters:
    `string` **hash** - `hash` from `t.me/joinchat/hash`
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function importChatInvite($params);
    /**
    * Get info about a stickerset.
    *
    * Parameters:
    `InputStickerSet` **stickerset** - Stickerset
    `[int]`           **hash**       - Optional:
    *
    * @param array $params Parameters
    *
    * @return messages .StickerSet
    */
    public function getStickerSet($params);
    /**
    * Install a stickerset.
    *
    * Parameters:
    `InputStickerSet` **stickerset** - Stickerset to install
    `Bool`            **archived**   - Whether to archive stickerset
    *
    * @param array $params Parameters
    *
    * @return messages .StickerSetInstallResult
    */
    public function installStickerSet($params);
    /**
    * Uninstall a stickerset.
    *
    * Parameters:
    `InputStickerSet` **stickerset** - The stickerset to uninstall
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function uninstallStickerSet($params);
    /**
    * Start a conversation with a bot using a [deep linking parameter](https://core.telegram.org/bots#deep-linking).
    *
    * Parameters:
    `InputUser` **bot**         - The bot
    `InputPeer` **peer**        - The chat where to start the bot, can be the bot's private chat or a group
    `string`    **start_param** - [Deep linking parameter](https://core.telegram.org/bots#deep-linking)
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function startBot($params);
    /**
    * Get and increase the view counter of a message sent or forwarded from a [channel](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputPeer` **peer**      - Peer where the message was found
    `[int]`     **id**        - ID of message
    `Bool`      **increment** - Whether to mark the message as viewed and increment the view counter
    *
    * @param array $params Parameters
    *
    * @return messages .MessageViews
    */
    public function getMessagesViews($params);
    /**
    * Make a user admin in a [legacy group](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputPeer` **chat_id**  -
    `InputUser` **user_id**  - The user to make admin
    `Bool`      **is_admin** - Whether to make him admin
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function editChatAdmin($params);
    /**
    * Turn a [legacy group into a supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputPeer` **chat_id** -
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function migrateChat($params);
    /**
    * Search for messages and peers globally.
    *
    * Parameters:
    `int`            **folder_id**   - Optional: [Peer folder ID, for more info click here](https://core.telegram.org/api/folders#peer-folders)
    `string`         **q**           - Query
    `MessagesFilter` **filter**      - Global search filter
    `int`            **min_date**    - If a positive value was specified, the method will return only messages with date bigger than min\_date
    `int`            **max_date**    - If a positive value was transferred, the method will return only messages with date smaller than max\_date
    `int`            **offset_rate** - Initially 0, then set to the [`next_rate` parameter of messages.messagesSlice](https://docs.madelineproto.xyz/API_docs/constructors/messages.messagesSlice.html)
    `InputPeer`      **offset_peer** - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`            **offset_id**   - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`            **limit**       - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function searchGlobal($params);
    /**
    * Reorder installed stickersets.
    *
    * Parameters:
    `boolean` **masks** - Optional: Reorder mask stickersets
    `[long]`  **order** - New stickerset order by stickerset IDs
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function reorderStickerSets($params);
    /**
    * Get a document by its SHA256 hash, mainly used for gifs.
    *
    * Parameters:
    `bytes`  **sha256**    - SHA256 of file
    `int`    **size**      - Size of the file in bytes
    `string` **mime_type** - Mime type
    *
    * @param array $params Parameters
    *
    * @return Document
    */
    public function getDocumentByHash($params);
    /**
    * Get saved GIFs.
    *
    * Parameters:
    `long` **hash** -
    *
    * @param array $params Parameters
    *
    * @return messages .SavedGifs
    */
    public function getSavedGifs($params);
    /**
    * Add GIF to saved gifs list.
    *
    * Parameters:
    `InputDocument` **id**     - GIF to save
    `Bool`          **unsave** - Whether to remove GIF from saved gifs list
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveGif($params);
    /**
    * Query an inline bot.
    *
    * Parameters:
    `InputUser`     **bot**       - The bot to query
    `InputPeer`     **peer**      - The currently opened chat
    `InputGeoPoint` **geo_point** - Optional: The geolocation, if requested
    `string`        **query**     - The query
    `string`        **offset**    - The offset within the results, will be passed directly as-is to the bot.
    *
    * @param array $params Parameters
    *
    * @return messages .BotResults
    */
    public function getInlineBotResults($params);
    /**
    * Answer an inline query, for bots only.
    *
    * Parameters:
    `boolean`                **gallery**     - Optional: Set this flag if the results are composed of media files
    `boolean`                **private**     - Optional: Set this flag if results may be cached on the server side only for the user that sent the query. By default, results may be returned to any user who sends the same query
    `long`                   **query_id**    - Unique identifier for the answered query
    `[InputBotInlineResult]` **results**     - Vector of results for the inline query
    `int`                    **cache_time**  - The maximum amount of time in seconds that the result of the inline query may be cached on the server. Defaults to 300.
    `string`                 **next_offset** - Optional: Pass the offset that a client should send in the next query with the same text to receive more results. Pass an empty string if there are no more results or if you donâ€˜t support pagination. Offset length canâ€™t exceed 64 bytes.
    `InlineBotSwitchPM`      **switch_pm**   - Optional: If passed, clients will display a button with specified text that switches the user to a private chat with the bot and sends the bot a start message with a certain parameter.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setInlineBotResults($params);
    /**
    * Send a result obtained using [messages.getInlineBotResults](https://docs.madelineproto.xyz/API_docs/methods/messages.getInlineBotResults.html).
    *
    * Parameters:
    `boolean`   **silent**          - Optional: Whether to send the message silently (no notification will be triggered on the other client)
    `boolean`   **background**      - Optional: Whether to send the message in background
    `boolean`   **clear_draft**     - Optional: Whether to clear the [draft](https://core.telegram.org/api/drafts)
    `boolean`   **hide_via**        - Optional: Whether to hide the `via @botname` in the resulting message (only for bot usernames encountered in the [config](https://docs.madelineproto.xyz/API_docs/constructors/config.html))
    `InputPeer` **peer**            - Destination
    `int`       **reply_to_msg_id** - Optional: ID of the message this message should reply to
    `long`      **query_id**        - Query ID from [messages.getInlineBotResults](https://docs.madelineproto.xyz/API_docs/methods/messages.getInlineBotResults.html)
    `string`    **id**              - Result ID from [messages.getInlineBotResults](https://docs.madelineproto.xyz/API_docs/methods/messages.getInlineBotResults.html)
    `int`       **schedule_date**   - Optional: Scheduled message date for scheduled messages
    `InputPeer` **send_as**         - Optional:
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function sendInlineBotResult($params);
    /**
    * Find out if a media message's caption can be edited.
    *
    * Parameters:
    `InputPeer` **peer** - Peer where the media was sent
    `int`       **id**   - ID of message
    *
    * @param array $params Parameters
    *
    * @return messages .MessageEditData
    */
    public function getMessageEditData($params);
    /**
    * Edit message.
    *
    * Parameters:
    `boolean`         **no_webpage**    - Optional: Disable webpage preview
    `InputPeer`       **peer**          - Where was the message sent
    `int`             **id**            - ID of the message to edit
    `string`          **message**       - Optional: New message
    `InputMedia`      **media**         - Optional: New attached media
    `ReplyMarkup`     **reply_markup**  - Optional: Reply markup for inline keyboards
    `[MessageEntity]` **entities**      - Optional: [Message entities for styled text](https://core.telegram.org/api/entities)
    `int`             **schedule_date** - Optional: Scheduled message date for [scheduled messages](https://core.telegram.org/api/scheduled-messages)
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editMessage($params);
    /**
    * Edit an inline bot message.
    *
    * Parameters:
    `boolean`                 **no_webpage**   - Optional: Disable webpage preview
    `InputBotInlineMessageID` **id**           - Sent inline message ID
    `string`                  **message**      - Optional: Message
    `InputMedia`              **media**        - Optional: Media
    `ReplyMarkup`             **reply_markup** - Optional: Reply markup for inline keyboards
    `[MessageEntity]`         **entities**     - Optional: [Message entities for styled text](https://core.telegram.org/api/entities)
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function editInlineBotMessage($params);
    /**
    * Press an inline callback button and get a callback answer from the bot.
    *
    * Parameters:
    `boolean`               **game**     - Optional: Whether this is a "play game" button
    `InputPeer`             **peer**     - Where was the inline keyboard sent
    `int`                   **msg_id**   - ID of the Message with the inline keyboard
    `bytes`                 **data**     - Optional: Callback data
    `InputCheckPasswordSRP` **password** - Optional: For buttons [requiring you to verify your identity with your 2FA password](https://docs.madelineproto.xyz/API_docs/constructors/keyboardButtonCallback.html), the SRP payload generated using [SRP](https://core.telegram.org/api/srp).
    *
    * @param array $params Parameters
    *
    * @return messages .BotCallbackAnswer
    */
    public function getBotCallbackAnswer($params);
    /**
    * Set the callback answer to a user button press (bots only).
    *
    * Parameters:
    `boolean` **alert**      - Optional: Whether to show the message as a popup instead of a toast notification
    `long`    **query_id**   - Query ID
    `string`  **message**    - Optional: Popup to show
    `string`  **url**        - Optional: URL to open
    `int`     **cache_time** - Cache validity
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setBotCallbackAnswer($params);
    /**
    * Get dialog info of specified peers.
    *
    * Parameters:
    `[InputDialogPeer]` **peers** - Peers
    *
    * @param array $params Parameters
    *
    * @return messages .PeerDialogs
    */
    public function getPeerDialogs($params);
    /**
    * Save a message [draft](https://core.telegram.org/api/drafts) associated to a chat.
    *
    * Parameters:
    `boolean`         **no_webpage**      - Optional: Disable generation of the webpage preview
    `int`             **reply_to_msg_id** - Optional: Message ID the message should reply to
    `InputPeer`       **peer**            - Destination of the message that should be sent
    `string`          **message**         - The draft
    `[MessageEntity]` **entities**        - Optional: Message [entities](https://core.telegram.org/api/entities) for styled text
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveDraft($params);
    /**
     * Save get all message [drafts](https://core.telegram.org/api/drafts).
     *
     * @return Updates
     */
    public function getAllDrafts();
    /**
    * Get featured stickers.
    *
    * Parameters:
    `long` **hash** -
    *
    * @param array $params Parameters
    *
    * @return messages .FeaturedStickers
    */
    public function getFeaturedStickers($params);
    /**
    * Mark new featured stickers as read.
    *
    * Parameters:
    `[long]` **id** - IDs of stickersets to mark as read
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function readFeaturedStickers($params);
    /**
    * Get recent stickers.
    *
    * Parameters:
    `boolean` **attached** - Optional: Get stickers recently attached to photo or video files
    `long`    **hash**     -
    *
    * @param array $params Parameters
    *
    * @return messages .RecentStickers
    */
    public function getRecentStickers($params);
    /**
    * Add/remove sticker from recent stickers list.
    *
    * Parameters:
    `boolean`       **attached** - Optional: Whether to add/remove stickers recently attached to photo or video files
    `InputDocument` **id**       - Sticker
    `Bool`          **unsave**   - Whether to save or unsave the sticker
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveRecentSticker($params);
    /**
    * Clear recent stickers.
    *
    * Parameters:
    `boolean` **attached** - Optional: Set this flag to clear the list of stickers recently attached to photo or video files
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function clearRecentStickers($params);
    /**
    * Get all archived stickers.
    *
    * Parameters:
    `boolean` **masks**     - Optional: Get mask stickers
    `long`    **offset_id** - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`     **limit**     - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    *
    * @param array $params Parameters
    *
    * @return messages .ArchivedStickers
    */
    public function getArchivedStickers($params);
    /**
    * Get installed mask stickers.
    *
    * Parameters:
    `long` **hash** -
    *
    * @param array $params Parameters
    *
    * @return messages .AllStickers
    */
    public function getMaskStickers($params);
    /**
    * Get stickers attached to a photo or video.
    *
    * Parameters:
    `InputStickeredMedia` **media** - Stickered media
    *
    * @param array $params Parameters
    *
    * @return of StickerSetCovered[]
    */
    public function getAttachedStickers($params);
    /**
    * Use this method to set the score of the specified user in a game sent as a normal message (bots only).
    *
    * Parameters:
    `boolean`   **edit_message** - Optional: Set this flag if the game message should be automatically edited to include the current scoreboard
    `boolean`   **force**        - Optional: Set this flag if the high score is allowed to decrease. This can be useful when fixing mistakes or banning cheaters
    `InputPeer` **peer**         - Unique identifier of target chat
    `int`       **id**           - Identifier of the sent message
    `InputUser` **user_id**      - User identifier
    `int`       **score**        - New score
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function setGameScore($params);
    /**
    * Use this method to set the score of the specified user in a game sent as an inline message (bots only).
    *
    * Parameters:
    `boolean`                 **edit_message** - Optional: Set this flag if the game message should be automatically edited to include the current scoreboard
    `boolean`                 **force**        - Optional: Set this flag if the high score is allowed to decrease. This can be useful when fixing mistakes or banning cheaters
    `InputBotInlineMessageID` **id**           - ID of the inline message
    `InputUser`               **user_id**      - User identifier
    `int`                     **score**        - New score
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setInlineGameScore($params);
    /**
    * Get highscores of a game.
    *
    * Parameters:
    `InputPeer` **peer**    - Where was the game sent
    `int`       **id**      - ID of message with game media attachment
    `InputUser` **user_id** - Get high scores made by a certain user
    *
    * @param array $params Parameters
    *
    * @return messages .HighScores
    */
    public function getGameHighScores($params);
    /**
    * Get highscores of a game sent using an inline bot.
    *
    * Parameters:
    `InputBotInlineMessageID` **id**      - ID of inline message
    `InputUser`               **user_id** - Get high scores of a certain user
    *
    * @param array $params Parameters
    *
    * @return messages .HighScores
    */
    public function getInlineGameHighScores($params);
    /**
    * Get chats in common with a user.
    *
    * Parameters:
    `InputUser` **user_id** - User ID
    `long`      **max_id**  -
    `int`       **limit**   - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    *
    * @param array $params Parameters
    *
    * @return messages .Chats
    */
    public function getCommonChats($params);
    /**
    * Get all chats, channels and supergroups.
    *
    * Parameters:
    `[long]` **except_ids** - Except these chats/channels/supergroups
    *
    * @param array $params Parameters
    *
    * @return messages .Chats
    */
    public function getAllChats($params);
    /**
    * Get [instant view](https://instantview.telegram.org) page.
    *
    * Parameters:
    `string` **url**  - URL of IV page to fetch
    `[int]`  **hash** - Optional: [Hash for pagination, for more info click here](https://core.telegram.org/api/offsets#hash-generation)
    *
    * @param array $params Parameters
    *
    * @return WebPage
    */
    public function getWebPage($params);
    /**
    * Pin/unpin a dialog.
    *
    * Parameters:
    `boolean`         **pinned** - Optional: Whether to pin or unpin the dialog
    `InputDialogPeer` **peer**   - The dialog to pin
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function toggleDialogPin($params);
    /**
    * Reorder pinned dialogs.
    *
    * Parameters:
    `boolean`           **force**     - Optional: If set, dialogs pinned server-side but not present in the `order` field will be unpinned.
    `int`               **folder_id** - [Peer folder ID, for more info click here](https://core.telegram.org/api/folders#peer-folders)
    `[InputDialogPeer]` **order**     - New dialog order
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function reorderPinnedDialogs($params);
    /**
    * Get pinned dialogs.
    *
    * Parameters:
    `int` **folder_id** - [Peer folder ID, for more info click here](https://core.telegram.org/api/folders#peer-folders)
    *
    * @param array $params Parameters
    *
    * @return messages .PeerDialogs
    */
    public function getPinnedDialogs($params);
    /**
    * If you sent an invoice requesting a shipping address and the parameter is\_flexible was specified, the bot will receive an [updateBotShippingQuery](https://docs.madelineproto.xyz/API_docs/constructors/updateBotShippingQuery.html) update. Use this method to reply to shipping queries.
    *
    * Parameters:
    `long`             **query_id**         - Unique identifier for the query to be answered
    `string`           **error**            - Optional: Error message in human readable form that explains why it is impossible to complete the order (e.g. "Sorry, delivery to your desired address is unavailable'). Telegram will display this message to the user.
    `[ShippingOption]` **shipping_options** - Optional: A vector of available shipping options.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setBotShippingResults($params);
    /**
    * Once the user has confirmed their payment and shipping details, the bot receives an [updateBotPrecheckoutQuery](https://docs.madelineproto.xyz/API_docs/constructors/updateBotPrecheckoutQuery.html) update.
    Use this method to respond to such pre-checkout queries.
    Note**: Telegram must receive an answer within 10 seconds after the pre-checkout query was sent.
    *
    * Parameters:
    `boolean` **success**  - Optional: Set this flag if everything is alright (goods are available, etc.) and the bot is ready to proceed with the order, otherwise do not set it, and set the `error` field, instead
    `long`    **query_id** - Unique identifier for the query to be answered
    `string`  **error**    - Optional: Required if the `success` isn't set. Error message in human readable form that explains the reason for failure to proceed with the checkout (e.g. "Sorry, somebody just bought the last of our amazing black T-shirts while you were busy filling out your payment details. Please choose a different color or garment!"). Telegram will display this message to the user.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setBotPrecheckoutResults($params);
    /**
    * Upload a file and associate it to a chat (without actually sending it to the chat).
    *
    * Parameters:
    `InputPeer`  **peer**  - The chat, can be an [inputPeerEmpty](https://docs.madelineproto.xyz/API_docs/constructors/inputPeerEmpty.html) for bots
    `InputMedia` **media** - File uploaded in chunks as described in [files Â»](https://core.telegram.org/api/files)
    *
    * @param array $params Parameters
    *
    * @return MessageMedia
    */
    public function uploadMedia($params);
    /**
    * Notify the other user in a private chat that a screenshot of the chat was taken.
    *
    * Parameters:
    `InputPeer` **peer**            - Other user
    `int`       **reply_to_msg_id** - ID of message that was screenshotted, can be 0
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function sendScreenshotNotification($params);
    /**
    * Get faved stickers.
    *
    * Parameters:
    `long` **hash** -
    *
    * @param array $params Parameters
    *
    * @return messages .FavedStickers
    */
    public function getFavedStickers($params);
    /**
    * Mark a sticker as favorite.
    *
    * Parameters:
    `InputDocument` **id**     - Sticker to mark as favorite
    `Bool`          **unfave** - Unfavorite
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function faveSticker($params);
    /**
    * Get unread messages where we were mentioned.
    *
    * Parameters:
    `InputPeer` **peer**       - Peer where to look for mentions
    `int`       **offset_id**  - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`       **add_offset** - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`       **limit**      - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    `int`       **max_id**     - Maximum message ID to return, [see pagination](https://core.telegram.org/api/offsets)
    `int`       **min_id**     - Minimum message ID to return, [see pagination](https://core.telegram.org/api/offsets)
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getUnreadMentions($params);
    /**
    * Mark mentions as read.
    *
    * Parameters:
    `InputPeer` **peer** - Dialog
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedHistory
    */
    public function readMentions($params);
    /**
    * Get live location history of a certain user.
    *
    * Parameters:
    `InputPeer` **peer**  - User
    `int`       **limit** - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    `long`      **hash**  -
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getRecentLocations($params);
    /**
    * Send an [album or grouped media](https://core.telegram.org/api/files#albums-grouped-media).
    *
    * Parameters:
    `boolean`            **silent**          - Optional: Whether to send the album silently (no notification triggered)
    `boolean`            **background**      - Optional: Send in background?
    `boolean`            **clear_draft**     - Optional: Whether to clear [drafts](https://core.telegram.org/api/drafts)
    `InputPeer`          **peer**            - The destination chat
    `int`                **reply_to_msg_id** - Optional: The message to reply to
    `[InputSingleMedia]` **multi_media**     - The medias to send
    `int`                **schedule_date**   - Optional: Scheduled message date for scheduled messages
    `InputPeer`          **send_as**         - Optional:
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function sendMultiMedia($params);
    /**
    * Upload encrypted file and associate it to a secret chat.
    *
    * Parameters:
    `InputEncryptedChat` **peer** - The secret chat to associate the file to
    `InputEncryptedFile` **file** - The file
    *
    * @param array $params Parameters
    *
    * @return EncryptedFile
    */
    public function uploadEncryptedFile($params);
    /**
    * Search for stickersets.
    *
    * Parameters:
    `boolean` **exclude_featured** - Optional: Exclude featured stickersets from results
    `string`  **q**                - Query string
    `long`    **hash**             -
    *
    * @param array $params Parameters
    *
    * @return messages .FoundStickerSets
    */
    public function searchStickerSets($params);
    /**
     * Get message ranges for saving the user's chat history.
     *
     * @return of MessageRange[]
     */
    public function getSplitRanges();
    /**
    * Manually mark dialog as unread.
    *
    * Parameters:
    `boolean`         **unread** - Optional: Mark as unread/read
    `InputDialogPeer` **peer**   - Dialog
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function markDialogUnread($params);
    /**
     * Get dialogs manually marked as unread.
     *
     * @return of DialogPeer[]
     */
    public function getDialogUnreadMarks();
    /**
     * Clear all [drafts](https://core.telegram.org/api/drafts).
     *
     * @return bool
     */
    public function clearAllDrafts();
    /**
    * Pin a message.
    *
    * Parameters:
    `boolean`   **silent**     - Optional: Pin the message silently, without triggering a notification
    `boolean`   **unpin**      - Optional: Whether the message should unpinned or pinned
    `boolean`   **pm_oneside** - Optional: Whether the message should only be pinned on the local side of a one-to-one chat
    `InputPeer` **peer**       - The peer where to pin the message
    `int`       **id**         - The message to pin or unpin
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function updatePinnedMessage($params);
    /**
    * Vote in a [poll](https://docs.madelineproto.xyz/API_docs/constructors/poll.html).
    *
    * Parameters:
    `InputPeer` **peer**    - The chat where the poll was sent
    `int`       **msg_id**  - The message ID of the poll
    `[bytes]`   **options** - The options that were chosen
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function sendVote($params);
    /**
    * Get poll results.
    *
    * Parameters:
    `InputPeer` **peer**   - Peer where the poll was found
    `int`       **msg_id** - Message ID of poll message
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function getPollResults($params);
    /**
    * Get count of online users in a chat.
    *
    * Parameters:
    `InputPeer` **peer** - The chat
    *
    * @param array $params Parameters
    *
    * @return ChatOnlines
    */
    public function getOnlines($params);
    /**
    * Edit the description of a [group/supergroup/channel](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputPeer` **peer**  - The [group/supergroup/channel](https://core.telegram.org/api/channel).
    `string`    **about** - The new description
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function editChatAbout($params);
    /**
    * Edit the default banned rights of a [channel/supergroup/group](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputPeer`        **peer**          - The peer
    `ChatBannedRights` **banned_rights** - The new global rights
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editChatDefaultBannedRights($params);
    /**
    * Get localized emoji keywords.
    *
    * Parameters:
    `string` **lang_code** - Language code
    *
    * @param array $params Parameters
    *
    * @return EmojiKeywordsDifference
    */
    public function getEmojiKeywords($params);
    /**
    * Get changed emoji keywords.
    *
    * Parameters:
    `string` **lang_code**    - Language code
    `int`    **from_version** - Previous emoji keyword localization version
    *
    * @param array $params Parameters
    *
    * @return EmojiKeywordsDifference
    */
    public function getEmojiKeywordsDifference($params);
    /**
    * Get info about an emoji keyword localization.
    *
    * Parameters:
    `[string]` **lang_codes** - Language codes
    *
    * @param array $params Parameters
    *
    * @return of EmojiLanguage[]
    */
    public function getEmojiKeywordsLanguages($params);
    /**
    * Returns an HTTP URL which can be used to automatically log in into translation platform and suggest new emoji replacements. The URL will be valid for 30 seconds after generation.
    *
    * Parameters:
    `string` **lang_code** - Language code for which the emoji replacements will be suggested
    *
    * @param array $params Parameters
    *
    * @return EmojiURL
    */
    public function getEmojiURL($params);
    /**
    * Get the number of results that would be found by a [messages.search](https://docs.madelineproto.xyz/API_docs/methods/messages.search.html) call with the same parameters.
    *
    * Parameters:
    `InputPeer`        **peer**    - Peer where to search
    `[MessagesFilter]` **filters** - Search filters
    *
    * @param array $params Parameters
    *
    * @return of messages.SearchCounter[]
    */
    public function getSearchCounters($params);
    /**
    * Get more info about a Seamless Telegram Login authorization request, for more info [click here Â»](https://core.telegram.org/api/url-authorization).
    *
    * Parameters:
    `InputPeer` **peer**      - Optional: Peer where the message is located
    `int`       **msg_id**    - Optional: The message
    `int`       **button_id** - Optional: The ID of the button with the authorization request
    `string`    **url**       - Optional:
    *
    * @param array $params Parameters
    *
    * @return UrlAuthResult
    */
    public function requestUrlAuth($params);
    /**
    * Use this to accept a Seamless Telegram Login authorization request, for more info [click here Â»](https://core.telegram.org/api/url-authorization).
    *
    * Parameters:
    `boolean`   **write_allowed** - Optional: Set this flag to allow the bot to send messages to you (if requested)
    `InputPeer` **peer**          - Optional: The location of the message
    `int`       **msg_id**        - Optional: Message ID of the message with the login button
    `int`       **button_id**     - Optional: ID of the login button
    `string`    **url**           - Optional:
    *
    * @param array $params Parameters
    *
    * @return UrlAuthResult
    */
    public function acceptUrlAuth($params);
    /**
    * Should be called after the user hides the report spam/add as contact bar of a new chat, effectively prevents the user from executing the actions specified in the [peer's settings](https://docs.madelineproto.xyz/API_docs/constructors/peerSettings.html).
    *
    * Parameters:
    `InputPeer` **peer** - Peer
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function hidePeerSettingsBar($params);
    /**
    * Get scheduled messages.
    *
    * Parameters:
    `InputPeer` **peer** - Peer
    `long`      **hash** -
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getScheduledHistory($params);
    /**
    * Get scheduled messages.
    *
    * Parameters:
    `InputPeer` **peer** - Peer
    `[int]`     **id**   - IDs of scheduled messages
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getScheduledMessages($params);
    /**
    * Send scheduled messages right away.
    *
    * Parameters:
    `InputPeer` **peer** - Peer
    `[int]`     **id**   - Scheduled message IDs
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function sendScheduledMessages($params);
    /**
    * Delete scheduled messages.
    *
    * Parameters:
    `InputPeer` **peer** - Peer
    `[int]`     **id**   - Scheduled message IDs
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function deleteScheduledMessages($params);
    /**
    * Get poll results for non-anonymous polls.
    *
    * Parameters:
    `InputPeer` **peer**   - Chat where the poll was sent
    `int`       **id**     - Message ID
    `bytes`     **option** - Optional: Get only results for the specified poll `option`
    `string`    **offset** - Optional: Offset for results, taken from the `next_offset` field of [messages.votesList](https://docs.madelineproto.xyz/API_docs/constructors/messages.votesList.html), initially an empty string. <br>Note: if no more results are available, the method call will return an empty `next_offset`; thus, avoid providing the `next_offset` returned in [messages.votesList](https://docs.madelineproto.xyz/API_docs/constructors/messages.votesList.html) if it is empty, to avoid an infinite loop.
    `int`       **limit**  - Number of results to return
    *
    * @param array $params Parameters
    *
    * @return messages .VotesList
    */
    public function getPollVotes($params);
    /**
    * Apply changes to multiple stickersets.
    *
    * Parameters:
    `boolean`           **uninstall**   - Optional: Uninstall the specified stickersets
    `boolean`           **archive**     - Optional: Archive the specified stickersets
    `boolean`           **unarchive**   - Optional: Unarchive the specified stickersets
    `[InputStickerSet]` **stickersets** - Stickersets to act upon
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function toggleStickerSets($params);
    /**
     * Get [folders](https://core.telegram.org/api/folders).
     *
     * @return of DialogFilter[]
     */
    public function getDialogFilters();
    /**
     * Get [suggested folders](https://core.telegram.org/api/folders).
     *
     * @return of DialogFilterSuggested[]
     */
    public function getSuggestedDialogFilters();
    /**
    * Update [folder](https://core.telegram.org/api/folders).
    *
    * Parameters:
    `int`          **id**     - [Folder](https://core.telegram.org/api/folders) ID
    `DialogFilter` **filter** - Optional: [Folder](https://core.telegram.org/api/folders) info
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function updateDialogFilter($params);
    /**
    * Reorder [folders](https://core.telegram.org/api/folders).
    *
    * Parameters:
    `[int]` **order** - New [folder](https://core.telegram.org/api/folders) order
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function updateDialogFiltersOrder($params);
    /**
    * Method for fetching previously featured stickers.
    *
    * Parameters:
    `int`  **offset** - Offset
    `int`  **limit**  - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    `long` **hash**   -
    *
    * @param array $params Parameters
    *
    * @return messages .FeaturedStickers
    */
    public function getOldFeaturedStickers($params);
    /**
    * Get messages in a reply thread.
    *
    * Parameters:
    `InputPeer` **peer**        - Peer
    `int`       **msg_id**      - Message ID
    `int`       **offset_id**   - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`       **offset_date** - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`       **add_offset**  - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`       **limit**       - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    `int`       **max_id**      - If a positive value was transferred, the method will return only messages with ID smaller than max\_id
    `int`       **min_id**      - If a positive value was transferred, the method will return only messages with ID bigger than min\_id
    `long`      **hash**        -
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getReplies($params);
    /**
    * Get [discussion message](https://core.telegram.org/api/threads) from the [associated discussion group](https://core.telegram.org/api/discussion) of a channel to show it on top of the comment section, without actually joining the group.
    *
    * Parameters:
    `InputPeer` **peer**   - [Channel ID](https://core.telegram.org/api/channel)
    `int`       **msg_id** - Message ID
    *
    * @param array $params Parameters
    *
    * @return messages .DiscussionMessage
    */
    public function getDiscussionMessage($params);
    /**
    * Mark a [thread](https://core.telegram.org/api/threads) as read.
    *
    * Parameters:
    `InputPeer` **peer**        - Group ID
    `int`       **msg_id**      - ID of message that started the thread
    `int`       **read_max_id** - ID up to which thread messages were read
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function readDiscussion($params);
    /**
    * [Unpin](https://core.telegram.org/api/pin) all pinned messages.
    *
    * Parameters:
    `InputPeer` **peer** - Chat where to unpin
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedHistory
    */
    public function unpinAllMessages($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **chat_id** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function deleteChat($params);
    /**
    *
    *
    * Parameters:
    `boolean` **revoke** - Optional:.
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedFoundMessages
    */
    public function deletePhoneCallHistory($params);
    /**
    *
    *
    * Parameters:
    `string` **import_head** -.
    *
    * @param array $params Parameters
    *
    * @return messages .HistoryImportParsed
    */
    public function checkHistoryImport($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**        -
    `InputFile` **file**        -
    `int`       **media_count** -.
    *
    * @param array $params Parameters
    *
    * @return messages .HistoryImport
    */
    public function initHistoryImport($params);
    /**
    *
    *
    * Parameters:
    `InputPeer`  **peer**      -
    `long`       **import_id** -
    `string`     **file_name** -
    `InputMedia` **media**     -.
    *
    * @param array $params Parameters
    *
    * @return MessageMedia
    */
    public function uploadImportedMedia($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**      -
    `long`      **import_id** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function startHistoryImport($params);
    /**
    *
    *
    * Parameters:
    `boolean`   **revoked**     - Optional:
    `InputPeer` **peer**        -
    `InputUser` **admin_id**    -
    `int`       **offset_date** - Optional:
    `string`    **offset_link** - Optional:
    `int`       **limit**       -.
    *
    * @param array $params Parameters
    *
    * @return messages .ExportedChatInvites
    */
    public function getExportedChatInvites($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer** -
    `string`    **link** -.
    *
    * @param array $params Parameters
    *
    * @return messages .ExportedChatInvite
    */
    public function getExportedChatInvite($params);
    /**
    *
    *
    * Parameters:
    `boolean`   **revoked**        - Optional:
    `InputPeer` **peer**           -
    `string`    **link**           -
    `int`       **expire_date**    - Optional:
    `int`       **usage_limit**    - Optional:
    `Bool`      **request_needed** - Optional:
    `string`    **title**          - Optional:.
    *
    * @param array $params Parameters
    *
    * @return messages .ExportedChatInvite
    */
    public function editExportedChatInvite($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**     -
    `InputUser` **admin_id** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function deleteRevokedExportedChatInvites($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer** -
    `string`    **link** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function deleteExportedChatInvite($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer** -.
    *
    * @param array $params Parameters
    *
    * @return messages .ChatAdminsWithInvites
    */
    public function getAdminsWithInvites($params);
    /**
    *
    *
    * Parameters:
    `boolean`   **requested**   - Optional:
    `InputPeer` **peer**        -
    `string`    **link**        - Optional:
    `string`    **q**           - Optional:
    `int`       **offset_date** -
    `InputUser` **offset_user** -
    `int`       **limit**       -.
    *
    * @param array $params Parameters
    *
    * @return messages .ChatInviteImporters
    */
    public function getChatInviteImporters($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**   -
    `int`       **period** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function setHistoryTTL($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer** -.
    *
    * @param array $params Parameters
    *
    * @return messages .CheckedHistoryImportPeer
    */
    public function checkHistoryImportPeer($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**     -
    `string`    **emoticon** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function setChatTheme($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**   -
    `int`       **msg_id** -.
    *
    * @param array $params Parameters
    *
    * @return of long[]
    */
    public function getMessageReadParticipants($params);
    /**
    *
    *
    * Parameters:
    `InputPeer`      **peer**        -
    `MessagesFilter` **filter**      -
    `int`            **offset_id**   -
    `int`            **offset_date** -.
    *
    * @param array $params Parameters
    *
    * @return messages .SearchResultsCalendar
    */
    public function getSearchResultsCalendar($params);
    /**
    *
    *
    * Parameters:
    `InputPeer`      **peer**      -
    `MessagesFilter` **filter**    -
    `int`            **offset_id** -
    `int`            **limit**     -.
    *
    * @param array $params Parameters
    *
    * @return messages .SearchResultsPositions
    */
    public function getSearchResultsPositions($params);
    /**
    *
    *
    * Parameters:
    `boolean`   **approved** - Optional:
    `InputPeer` **peer**     -
    `InputUser` **user_id**  -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function hideChatJoinRequest($params);
    /**
    *
    *
    * Parameters:
    `boolean`   **approved** - Optional:
    `InputPeer` **peer**     -
    `string`    **link**     - Optional:.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function hideAllChatJoinRequests($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**    -
    `Bool`      **enabled** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function toggleNoForwards($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**    -
    `InputPeer` **send_as** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveDefaultSendAs($params);
}
interface updates
{
    /**
     * Returns a current state of updates.
     *
     * @return updates .State
     */
    public function getState();
    /**
    * Get new [updates](https://core.telegram.org/api/updates).
    *
    * Parameters:
    `int` **pts**             - PTS, see [updates](https://core.telegram.org/api/updates).
    `int` **pts_total_limit** - Optional: For fast updating: if provided and `pts + pts_total_limit < remote pts`, [updates.differenceTooLong](https://docs.madelineproto.xyz/API_docs/constructors/updates.differenceTooLong.html) will be returned.<br>Simply tells the server to not return the difference if it is bigger than `pts_total_limit`<br>If the remote pts is too big (&gt; ~4000000), this field will default to 1000000
    `int` **date**            - date, see [updates](https://core.telegram.org/api/updates).
    `int` **qts**             - QTS, see [updates](https://core.telegram.org/api/updates).
    *
    * @param array $params Parameters
    *
    * @return updates .Difference
    */
    public function getDifference($params);
    /**
    * Returns the difference between the current state of updates of a certain channel and transmitted.
    *
    * Parameters:
    `boolean`               **force**   - Optional: Set to true to skip some possibly unneeded updates and reduce server-side load
    `InputChannel`          **channel** - The channel
    `ChannelMessagesFilter` **filter**  - Messsage filter
    `int`                   **pts**     - Persistent timestamp (see [updates](https://core.telegram.org/api/updates))
    `int`                   **limit**   - How many updates to fetch, max `100000`<br>Ordinary (non-bot) users are supposed to pass `10-100`
    *
    * @param array $params Parameters
    *
    * @return updates .ChannelDifference
    */
    public function getChannelDifference($params);
}
interface photos
{
    /**
    * Installs a previously uploaded photo as a profile photo.
    *
    * Parameters:
    `InputPhoto` **id** - Input photo
    *
    * @param array $params Parameters
    *
    * @return photos .Photo
    */
    public function updateProfilePhoto($params);
    /**
    * Updates current user profile photo.
    *
    * Parameters:
    `InputFile` **file**           - Optional: File saved in parts by means of [upload.saveFilePart](https://docs.madelineproto.xyz/API_docs/methods/upload.saveFilePart.html) method
    `InputFile` **video**          - Optional: [Animated profile picture](https://core.telegram.org/api/files#animated-profile-pictures) video
    `double`    **video_start_ts** - Optional: Floating point UNIX timestamp in seconds, indicating the frame of the video that should be used as static preview.
    *
    * @param array $params Parameters
    *
    * @return photos .Photo
    */
    public function uploadProfilePhoto($params);
    /**
    * Deletes profile photos.
    *
    * Parameters:
    `[InputPhoto]` **id** - Input photos to delete
    *
    * @param array $params Parameters
    *
    * @return of long[]
    */
    public function deletePhotos($params);
    /**
    * Returns the list of user photos.
    *
    * Parameters:
    `InputUser` **user_id** - User ID
    `int`       **offset**  - Number of list elements to be skipped
    `long`      **max_id**  - If a positive value was transferred, the method will return only photos with IDs less than the set one
    `int`       **limit**   - Number of list elements to be returned
    *
    * @param array $params Parameters
    *
    * @return photos .Photos
    */
    public function getUserPhotos($params);
}
interface upload
{
    /**
    * Saves a part of file for futher sending to one of the methods.
    *
    * Parameters:
    `long`  **file_id**   - Random file identifier created by the client
    `int`   **file_part** - Numerical order of a part
    `bytes` **bytes**     - Binary data, contend of a part
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveFilePart($params);
    /**
    * Returns content of a whole file or its part.
    *
    * Parameters:
    `boolean`           **precise**       - Optional: Disable some checks on limit and offset values, useful for example to stream videos by keyframes
    `boolean`           **cdn_supported** - Optional: Whether the current client supports [CDN downloads](https://core.telegram.org/cdn)
    `InputFileLocation` **location**      - File location
    `int`               **offset**        - Number of bytes to be skipped
    `int`               **limit**         - Number of bytes to be returned
    *
    * @param array $params Parameters
    *
    * @return upload .File
    */
    public function getFile($params);
    /**
    * Saves a part of a large file (over 10Mb in size) to be later passed to one of the methods.
    *
    * Parameters:
    `long`  **file_id**          - Random file id, created by the client
    `int`   **file_part**        - Part sequence number
    `int`   **file_total_parts** - Total number of parts
    `bytes` **bytes**            - Binary data, part contents
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveBigFilePart($params);
    /**
    * Returns content of an HTTP file or a part, by proxying the request through telegram.
    *
    * Parameters:
    `InputWebFileLocation` **location** - The file to download
    `int`                  **offset**   - Number of bytes to be skipped
    `int`                  **limit**    - Number of bytes to be returned
    *
    * @param array $params Parameters
    *
    * @return upload .WebFile
    */
    public function getWebFile($params);
    /**
    * Download a [CDN](https://core.telegram.org/cdn) file.
    *
    * Parameters:
    `bytes` **file_token** - File token
    `int`   **offset**     - Offset of chunk to download
    `int`   **limit**      - Length of chunk to download
    *
    * @param array $params Parameters
    *
    * @return upload .CdnFile
    */
    public function getCdnFile($params);
    /**
    * Request a reupload of a certain file to a [CDN DC](https://core.telegram.org/cdn).
    *
    * Parameters:
    `bytes` **file_token**    - File token
    `bytes` **request_token** - Request token
    *
    * @param array $params Parameters
    *
    * @return of FileHash[]
    */
    public function reuploadCdnFile($params);
    /**
    * Get SHA256 hashes for verifying downloaded [CDN](https://core.telegram.org/cdn) files.
    *
    * Parameters:
    `bytes` **file_token** - File
    `int`   **offset**     - Offset from which to start getting hashes
    *
    * @param array $params Parameters
    *
    * @return of FileHash[]
    */
    public function getCdnFileHashes($params);
    /**
    * Get SHA256 hashes for verifying downloaded files.
    *
    * Parameters:
    `InputFileLocation` **location** - File
    `int`               **offset**   - Offset from which to get file hashes
    *
    * @param array $params Parameters
    *
    * @return of FileHash[]
    */
    public function getFileHashes($params);
}
interface help
{
    /**
     * Returns current configuration, including data center configuration.
     *
     * @return Config
     */
    public function getConfig();
    /**
     * Returns info on data centre nearest to the user.
     *
     * @return NearestDc
     */
    public function getNearestDc();
    /**
    * Returns information on update availability for the current application.
    *
    * Parameters:
    `string` **source** - Source
    *
    * @param array $params Parameters
    *
    * @return help .AppUpdate
    */
    public function getAppUpdate($params);
    /**
     * Returns localized text of a text message with an invitation.
     *
     * @return help .InviteText
     */
    public function getInviteText();
    /**
     * Returns the support user for the 'ask a question' feature.
     *
     * @return help .Support
     */
    public function getSupport();
    /**
    * Get changelog of current app.
    Typically, an [updates](https://docs.madelineproto.xyz/API_docs/constructors/updates.html) constructor will be returned, containing one or more [updateServiceNotification](https://docs.madelineproto.xyz/API_docs/constructors/updateServiceNotification.html) updates with app-specific changelogs.
    *
    * Parameters:
    `string` **prev_app_version** - Previous app version
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function getAppChangelog($params);
    /**
    * Informs the server about the number of pending bot updates if they haven't been processed for a long time; for bots only.
    *
    * Parameters:
    `int`    **pending_updates_count** - Number of pending updates
    `string` **message**               - Error message, if present
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setBotUpdatesStatus($params);
    /**
     * Get configuration for [CDN](https://core.telegram.org/cdn) file downloads.
     *
     * @return CdnConfig
     */
    public function getCdnConfig();
    /**
    * Get recently used `t.me` links.
    *
    * Parameters:
    `string` **referer** - Referer
    *
    * @param array $params Parameters
    *
    * @return help .RecentMeUrls
    */
    public function getRecentMeUrls($params);
    /**
     * Look for updates of telegram's terms of service.
     *
     * @return help .TermsOfServiceUpdate
     */
    public function getTermsOfServiceUpdate();
    /**
    * Accept the new terms of service.
    *
    * Parameters:
    `DataJSON` **id** - ID of terms of service
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function acceptTermsOfService($params);
    /**
    * Get info about a `t.me` link.
    *
    * Parameters:
    `string` **path** - Path in `t.me/path`
    *
    * @param array $params Parameters
    *
    * @return help .DeepLinkInfo
    */
    public function getDeepLinkInfo($params);
    /**
     * Get app-specific configuration, see [client configuration](https://core.telegram.org/api/config#client-configuration) for more info on the result.
     *
     * @return JSONValue
     */
    public function getAppConfig();
    /**
    * Saves logs of application on the server.
    *
    * Parameters:
    `[InputAppEvent]` **events** - List of input events
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveAppLog($params);
    /**
    * Get [passport](https://core.telegram.org/passport) configuration.
    *
    * Parameters:
    `[int]` **hash** - Optional: [Hash for pagination, for more info click here](https://core.telegram.org/api/offsets#hash-generation)
    *
    * @param array $params Parameters
    *
    * @return help .PassportConfig
    */
    public function getPassportConfig($params);
    /**
     * Get localized name of the telegram support user.
     *
     * @return help .SupportName
     */
    public function getSupportName();
    /**
    * Internal use.
    *
    * Parameters:
    `InputUser` **user_id** - User ID
    *
    * @param array $params Parameters
    *
    * @return help .UserInfo
    */
    public function getUserInfo($params);
    /**
    * Internal use.
    *
    * Parameters:
    `InputUser`       **user_id**  - User
    `string`          **message**  - Message
    `[MessageEntity]` **entities** - [Message entities for styled text](https://core.telegram.org/api/entities)
    *
    * @param array $params Parameters
    *
    * @return help .UserInfo
    */
    public function editUserInfo($params);
    /**
     * Get MTProxy/Public Service Announcement information.
     *
     * @return help .PromoData
     */
    public function getPromoData();
    /**
    * Hide MTProxy/Public Service Announcement information.
    *
    * Parameters:
    `InputPeer` **peer** - Peer to hide
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function hidePromoData($params);
    /**
    * Dismiss a suggestion.
    *
    * Parameters:
    `InputPeer` **peer**       -
    `string`    **suggestion** - Suggestion
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function dismissSuggestion($params);
    /**
    * Get name, ISO code, localized name and phone codes/patterns of all available countries.
    *
    * Parameters:
    `string` **lang_code** - Language code of the current user
    `[int]`  **hash**      - Optional: [Hash for pagination, for more info click here](https://core.telegram.org/api/offsets#hash-generation)
    *
    * @param array $params Parameters
    *
    * @return help .CountriesList
    */
    public function getCountriesList($params);
}
interface channels
{
    /**
    * Mark [channel/supergroup](https://core.telegram.org/api/channel) history as read.
    *
    * Parameters:
    `InputChannel` **channel** - [Channel/supergroup](https://core.telegram.org/api/channel)
    `int`          **max_id**  - ID of message up to which messages should be marked as read
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function readHistory($params);
    /**
    * Delete messages in a [channel/supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel` **channel** - [Channel/supergroup](https://core.telegram.org/api/channel)
    `[int]`        **id**      - IDs of messages to delete
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedMessages
    */
    public function deleteMessages($params);
    /**
    * Reports some messages from a user in a supergroup as spam; requires administrator rights in the supergroup.
    *
    * Parameters:
    `InputChannel` **channel**     - Supergroup
    `InputPeer`    **participant** -
    `[int]`        **id**          - IDs of spam messages
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function reportSpam($params);
    /**
    * Get [channel/supergroup](https://core.telegram.org/api/channel) messages.
    *
    * Parameters:
    `InputChannel`   **channel** - Channel/supergroup
    `[InputMessage]` **id**      - IDs of messages to get
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getMessages($params);
    /**
    * Get the participants of a [supergroup/channel](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel`              **channel** - Channel
    `ChannelParticipantsFilter` **filter**  - Which participant types to fetch
    `int`                       **offset**  - [Offset](https://core.telegram.org/api/offsets)
    `int`                       **limit**   - [Limit](https://core.telegram.org/api/offsets)
    `long`                      **hash**    -
    *
    * @param array $params Parameters
    *
    * @return channels .ChannelParticipants
    */
    public function getParticipants($params);
    /**
    * Get info about a [channel/supergroup](https://core.telegram.org/api/channel) participant.
    *
    * Parameters:
    `InputChannel` **channel**     - Channel/supergroup
    `InputPeer`    **participant** -
    *
    * @param array $params Parameters
    *
    * @return channels .ChannelParticipant
    */
    public function getParticipant($params);
    /**
    * Get info about [channels/supergroups](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `[InputChannel]` **id** - IDs of channels/supergroups to get info about
    *
    * @param array $params Parameters
    *
    * @return messages .Chats
    */
    public function getChannels($params);
    /**
    * Get full info about a channel.
    *
    * Parameters:
    `InputChannel` **channel** - The channel to get info about
    *
    * @param array $params Parameters
    *
    * @return messages .ChatFull
    */
    public function getFullChannel($params);
    /**
    * Create a [supergroup/channel](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `boolean`       **broadcast**  - Optional: Whether to create a [channel](https://core.telegram.org/api/channel)
    `boolean`       **megagroup**  - Optional: Whether to create a [supergroup](https://core.telegram.org/api/channel)
    `boolean`       **for_import** - Optional:
    `string`        **title**      - Channel title
    `string`        **about**      - Channel description
    `InputGeoPoint` **geo_point**  - Optional: Geogroup location
    `string`        **address**    - Optional: Geogroup address
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function createChannel($params);
    /**
    * Modify the admin rights of a user in a [supergroup/channel](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel`    **channel**      - The [supergroup/channel](https://core.telegram.org/api/channel).
    `InputUser`       **user_id**      - The ID of the user whose admin rights should be modified
    `ChatAdminRights` **admin_rights** - The admin rights
    `string`          **rank**         - Indicates the role (rank) of the admin in the group: just an arbitrary string
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editAdmin($params);
    /**
    * Edit the name of a [channel/supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel` **channel** - Channel/supergroup
    `string`       **title**   - New name
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editTitle($params);
    /**
    * Change the photo of a [channel/supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel`   **channel** - Channel/supergroup whose photo should be edited
    `InputChatPhoto` **photo**   - New photo
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editPhoto($params);
    /**
    * Check if a username is free and can be assigned to a channel/supergroup.
    *
    * Parameters:
    `InputChannel` **channel**  - The [channel/supergroup](https://core.telegram.org/api/channel) that will assigned the specified username
    `string`       **username** - The username to check
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function checkUsername($params);
    /**
    * Change the username of a supergroup/channel.
    *
    * Parameters:
    `InputChannel` **channel**  - Channel
    `string`       **username** - New username
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function updateUsername($params);
    /**
    * Join a channel/supergroup.
    *
    * Parameters:
    `InputChannel` **channel** - Channel/supergroup to join
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function joinChannel($params);
    /**
    * Leave a [channel/supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel` **channel** - [Channel/supergroup](https://core.telegram.org/api/channel) to leave
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function leaveChannel($params);
    /**
    * Invite users to a channel/supergroup.
    *
    * Parameters:
    `InputChannel` **channel** - Channel/supergroup
    `[InputUser]`  **users**   - Users to invite
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function inviteToChannel($params);
    /**
    * Delete a [channel/supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel` **channel** - [Channel/supergroup](https://core.telegram.org/api/channel) to delete
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function deleteChannel($params);
    /**
    * Get link and embed info of a message in a [channel/supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `boolean`      **grouped** - Optional: Whether to include other grouped media (for albums)
    `boolean`      **thread**  - Optional: Whether to also include a thread ID, if available, inside of the link
    `InputChannel` **channel** - Channel
    `int`          **id**      - Message ID
    *
    * @param array $params Parameters
    *
    * @return ExportedMessageLink
    */
    public function exportMessageLink($params);
    /**
    * Enable/disable message signatures in channels.
    *
    * Parameters:
    `InputChannel` **channel** - Channel
    `Bool`         **enabled** - Value
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function toggleSignatures($params);
    /**
    * Get [channels/supergroups/geogroups](https://core.telegram.org/api/channel) we're admin in. Usually called when the user exceeds the [limit](https://docs.madelineproto.xyz/API_docs/constructors/config.html) for owned public [channels/supergroups/geogroups](https://core.telegram.org/api/channel), and the user is given the choice to remove one of his channels/supergroups/geogroups.
    *
    * Parameters:
    `boolean` **by_location** - Optional: Get geogroups
    `boolean` **check_limit** - Optional: If set and the user has reached the limit of owned public [channels/supergroups/geogroups](https://core.telegram.org/api/channel), instead of returning the channel list one of the specified [errors](#possible-errors) will be returned.<br>Useful to check if a new public channel can indeed be created, even before asking the user to enter a channel username to use in [channels.checkUsername](https://docs.madelineproto.xyz/API_docs/methods/channels.checkUsername.html)/[channels.updateUsername](https://docs.madelineproto.xyz/API_docs/methods/channels.updateUsername.html).
    *
    * @param array $params Parameters
    *
    * @return messages .Chats
    */
    public function getAdminedPublicChannels($params);
    /**
    * Ban/unban/kick a user in a [supergroup/channel](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel`     **channel**       - The [supergroup/channel](https://core.telegram.org/api/channel).
    `InputPeer`        **participant**   -
    `ChatBannedRights` **banned_rights** - The banned rights
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editBanned($params);
    /**
    * Get the admin log of a [channel/supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel`                **channel**       - Channel
    `string`                      **q**             - Search query, can be empty
    `ChannelAdminLogEventsFilter` **events_filter** - Optional: Event filter
    `[InputUser]`                 **admins**        - Optional: Only show events from these admins
    `long`                        **max_id**        - Maximum ID of message to return (see [pagination](https://core.telegram.org/api/offsets))
    `long`                        **min_id**        - Minimum ID of message to return (see [pagination](https://core.telegram.org/api/offsets))
    `int`                         **limit**         - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    *
    * @param array $params Parameters
    *
    * @return channels .AdminLogResults
    */
    public function getAdminLog($params);
    /**
    * Associate a stickerset to the supergroup.
    *
    * Parameters:
    `InputChannel`    **channel**    - Supergroup
    `InputStickerSet` **stickerset** - The stickerset to associate
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setStickers($params);
    /**
    * Mark [channel/supergroup](https://core.telegram.org/api/channel) message contents as read.
    *
    * Parameters:
    `InputChannel` **channel** - [Channel/supergroup](https://core.telegram.org/api/channel)
    `[int]`        **id**      - IDs of messages whose contents should be marked as read
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function readMessageContents($params);
    /**
    * Delete the history of a [supergroup](https://core.telegram.org/api/channel).
    *
    * Parameters:
    `InputChannel` **channel** - [Supergroup](https://core.telegram.org/api/channel) whose history must be deleted
    `int`          **max_id**  - ID of message **up to which** the history must be deleted
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function deleteHistory($params);
    /**
    * Hide/unhide message history for new channel/supergroup users.
    *
    * Parameters:
    `InputChannel` **channel** - Channel/supergroup
    `Bool`         **enabled** - Hide/unhide
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function togglePreHistoryHidden($params);
    /**
    * Get a list of [channels/supergroups](https://core.telegram.org/api/channel) we left.
    *
    * Parameters:
    `int` **offset** - Offset for [pagination](https://core.telegram.org/api/offsets)
    *
    * @param array $params Parameters
    *
    * @return messages .Chats
    */
    public function getLeftChannels($params);
    /**
    * Get all groups that can be used as [discussion groups](https://core.telegram.org/api/discussion).
    *
    * Returned [legacy group chats](https://core.telegram.org/api/channel) must be first upgraded to [supergroups](https://core.telegram.org/api/channel) before they can be set as a discussion group.
    To set a returned supergroup as a discussion group, access to its old messages must be enabled using [channels.togglePreHistoryHidden](https://docs.madelineproto.xyz/API_docs/methods/channels.togglePreHistoryHidden.html), first.
    *
    * @return messages .Chats
    */
    public function getGroupsForDiscussion();
    /**
    * Associate a group to a channel as [discussion group](https://core.telegram.org/api/discussion) for that channel.
    *
    * Parameters:
    `InputChannel` **broadcast** - Channel
    `InputChannel` **group**     - [Discussion group](https://core.telegram.org/api/discussion) to associate to the channel
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setDiscussionGroup($params);
    /**
    * Transfer channel ownership.
    *
    * Parameters:
    `InputChannel`          **channel**  - Channel
    `InputUser`             **user_id**  - New channel owner
    `InputCheckPasswordSRP` **password** - [2FA password](https://core.telegram.org/api/srp) of account
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editCreator($params);
    /**
    * Edit location of geogroup.
    *
    * Parameters:
    `InputChannel`  **channel**   - [Geogroup](https://core.telegram.org/api/channel)
    `InputGeoPoint` **geo_point** - New geolocation
    `string`        **address**   - Address string
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function editLocation($params);
    /**
    * Toggle supergroup slow mode: if enabled, users will only be able to send one message every `seconds` seconds.
    *
    * Parameters:
    `InputChannel` **channel** - The [supergroup](https://core.telegram.org/api/channel)
    `int`          **seconds** - Users will only be able to send one message every `seconds` seconds, `0` to disable the limitation
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function toggleSlowMode($params);
    /**
     * Get inactive channels and supergroups.
     *
     * @return messages .InactiveChats
     */
    public function getInactiveChannels();
    /**
    *
    *
    * Parameters:
    `InputChannel` **channel** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function convertToGigagroup($params);
    /**
    *
    *
    * Parameters:
    `InputChannel` **channel** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function viewSponsoredMessage($params);
    /**
    *
    *
    * Parameters:
    `InputChannel` **channel** -.
    *
    * @param array $params Parameters
    *
    * @return messages .SponsoredMessages
    */
    public function getSponsoredMessages($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer** -.
    *
    * @param array $params Parameters
    *
    * @return channels .SendAsPeers
    */
    public function getSendAs($params);
    /**
    *
    *
    * Parameters:
    `InputChannel` **channel**     -
    `InputPeer`    **participant** -.
    *
    * @param array $params Parameters
    *
    * @return messages .AffectedHistory
    */
    public function deleteParticipantHistory($params);
}
interface bots
{
    /**
    * Sends a custom request; for bots only.
    *
    * Parameters:
    `string`   **custom_method** - The method name
    `DataJSON` **params**        - JSON-serialized method parameters
    *
    * @param array $params Parameters
    *
    * @return DataJSON
    */
    public function sendCustomRequest($params);
    /**
    * Answers a custom query; for bots only.
    *
    * Parameters:
    `long`     **query_id** - Identifier of a custom query
    `DataJSON` **data**     - JSON-serialized answer to the query
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function answerWebhookJSONQuery($params);
    /**
    * Set bot command list.
    *
    * Parameters:
    `BotCommandScope` **scope**     -
    `string`          **lang_code** -
    `[BotCommand]`    **commands**  - Bot commands
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function setBotCommands($params);
    /**
    *
    *
    * Parameters:
    `BotCommandScope` **scope**     -
    `string`          **lang_code** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function resetBotCommands($params);
    /**
    *
    *
    * Parameters:
    `BotCommandScope` **scope**     -
    `string`          **lang_code** -.
    *
    * @param array $params Parameters
    *
    * @return of BotCommand[]
    */
    public function getBotCommands($params);
}
interface payments
{
    /**
    * Get a payment form.
    *
    * Parameters:
    `InputPeer` **peer**         -
    `int`       **msg_id**       - Message ID of payment form
    `DataJSON`  **theme_params** - Optional:
    *
    * @param array $params Parameters
    *
    * @return payments .PaymentForm
    */
    public function getPaymentForm($params);
    /**
    * Get payment receipt.
    *
    * Parameters:
    `InputPeer` **peer**   -
    `int`       **msg_id** - Message ID of receipt
    *
    * @param array $params Parameters
    *
    * @return payments .PaymentReceipt
    */
    public function getPaymentReceipt($params);
    /**
    * Submit requested order information for validation.
    *
    * Parameters:
    `boolean`              **save**   - Optional: Save order information to re-use it for future orders
    `InputPeer`            **peer**   -
    `int`                  **msg_id** - Message ID of payment form
    `PaymentRequestedInfo` **info**   - Requested order information
    *
    * @param array $params Parameters
    *
    * @return payments .ValidatedRequestedInfo
    */
    public function validateRequestedInfo($params);
    /**
    * Send compiled payment form.
    *
    * Parameters:
    `long`                    **form_id**            -
    `InputPeer`               **peer**               -
    `int`                     **msg_id**             - Message ID of form
    `string`                  **requested_info_id**  - Optional: ID of saved and validated [order info](https://docs.madelineproto.xyz/API_docs/constructors/payments.validatedRequestedInfo.html)
    `string`                  **shipping_option_id** - Optional: Chosen shipping option ID
    `InputPaymentCredentials` **credentials**        - Payment credentials
    `long`                    **tip_amount**         - Optional:
    *
    * @param array $params Parameters
    *
    * @return payments .PaymentResult
    */
    public function sendPaymentForm($params);
    /**
     * Get saved payment information.
     *
     * @return payments .SavedInfo
     */
    public function getSavedInfo();
    /**
    * Clear saved payment information.
    *
    * Parameters:
    `boolean` **credentials** - Optional: Remove saved payment credentials
    `boolean` **info**        - Optional: Clear the last order settings saved by the user
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function clearSavedInfo($params);
    /**
    * Get info about a credit card.
    *
    * Parameters:
    `string` **number** - Credit card number
    *
    * @param array $params Parameters
    *
    * @return payments .BankCardData
    */
    public function getBankCardData($params);
}
interface stickers
{
    /**
    * Create a stickerset, bots only.
    *
    * Parameters:
    `boolean`               **masks**      - Optional: Whether this is a mask stickerset
    `boolean`               **animated**   - Optional: Whether this is an animated stickerset
    `InputUser`             **user_id**    - Stickerset owner
    `string`                **title**      - Stickerset name, `1-64` chars
    `string`                **short_name** - Sticker set name. Can contain only English letters, digits and underscores. Must end with *"*by*<bot username="">"</bot>* (*<bot_username></bot_username>* is case insensitive); 1-64 characters
    `InputDocument`         **thumb**      - Optional: Thumbnail
    `[InputStickerSetItem]` **stickers**   - Stickers
    `string`                **software**   - Optional:
    *
    * @param array $params Parameters
    *
    * @return messages .StickerSet
    */
    public function createStickerSet($params);
    /**
    * Remove a sticker from the set where it belongs, bots only. The sticker set must have been created by the bot.
    *
    * Parameters:
    `InputDocument` **sticker** - The sticker to remove
    *
    * @param array $params Parameters
    *
    * @return messages .StickerSet
    */
    public function removeStickerFromSet($params);
    /**
    * Changes the absolute position of a sticker in the set to which it belongs; for bots only. The sticker set must have been created by the bot.
    *
    * Parameters:
    `InputDocument` **sticker**  - The sticker
    `int`           **position** - The new position of the sticker, zero-based
    *
    * @param array $params Parameters
    *
    * @return messages .StickerSet
    */
    public function changeStickerPosition($params);
    /**
    * Add a sticker to a stickerset, bots only. The sticker set must have been created by the bot.
    *
    * Parameters:
    `InputStickerSet`     **stickerset** - The stickerset
    `InputStickerSetItem` **sticker**    - The sticker
    *
    * @param array $params Parameters
    *
    * @return messages .StickerSet
    */
    public function addStickerToSet($params);
    /**
    * Set stickerset thumbnail.
    *
    * Parameters:
    `InputStickerSet` **stickerset** - Stickerset
    `InputDocument`   **thumb**      - Thumbnail
    *
    * @param array $params Parameters
    *
    * @return messages .StickerSet
    */
    public function setStickerSetThumb($params);
    /**
    *
    *
    * Parameters:
    `string` **short_name** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function checkShortName($params);
    /**
    *
    *
    * Parameters:
    `string` **title** -.
    *
    * @param array $params Parameters
    *
    * @return stickers .SuggestedShortName
    */
    public function suggestShortName($params);
}
interface phone
{
    /**
     * Get phone call configuration to be passed to libtgvoip's shared config.
     *
     * @return DataJSON
     */
    public function getCallConfig();
    /**
    * Start a telegram phone call.
    *
    * Parameters:
    `boolean`           **video**    - Optional: Whether to start a video call
    `InputUser`         **user_id**  - Destination of the phone call
    `bytes`             **g_a_hash** - [Parameter for E2E encryption key exchange Â»](https://core.telegram.org/api/end-to-end/voice-calls)
    `PhoneCallProtocol` **protocol** - Phone call settings
    *
    * @param array $params Parameters
    *
    * @return phone .PhoneCall
    */
    public function requestCall($params);
    /**
    * Accept incoming call.
    *
    * Parameters:
    `InputPhoneCall`    **peer**     - The call to accept
    `bytes`             **g_b**      - [Parameter for E2E encryption key exchange Â»](https://core.telegram.org/api/end-to-end/voice-calls)
    `PhoneCallProtocol` **protocol** - Phone call settings
    *
    * @param array $params Parameters
    *
    * @return phone .PhoneCall
    */
    public function acceptCall($params);
    /**
    * [Complete phone call E2E encryption key exchange Â»](https://core.telegram.org/api/end-to-end/voice-calls).
    *
    * Parameters:
    `InputPhoneCall`    **peer**            - The phone call
    `bytes`             **g_a**             - [Parameter for E2E encryption key exchange Â»](https://core.telegram.org/api/end-to-end/voice-calls)
    `long`              **key_fingerprint** - Key fingerprint
    `PhoneCallProtocol` **protocol**        - Phone call settings
    *
    * @param array $params Parameters
    *
    * @return phone .PhoneCall
    */
    public function confirmCall($params);
    /**
    * Optional: notify the server that the user is currently busy in a call: this will automatically refuse all incoming phone calls until the current phone call is ended.
    *
    * Parameters:
    `InputPhoneCall` **peer** - The phone call we're currently in
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function receivedCall($params);
    /**
    * Refuse or end running call.
    *
    * Parameters:
    `boolean`                **video**         - Optional: Whether this is a video call
    `InputPhoneCall`         **peer**          - The phone call
    `int`                    **duration**      - Call duration
    `PhoneCallDiscardReason` **reason**        - Why was the call discarded
    `long`                   **connection_id** - Preferred libtgvoip relay ID
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function discardCall($params);
    /**
    * Rate a call.
    *
    * Parameters:
    `boolean`        **user_initiative** - Optional: Whether the user decided on their own initiative to rate the call
    `InputPhoneCall` **peer**            - The call to rate
    `int`            **rating**          - Rating in `1-5` stars
    `string`         **comment**         - An additional comment
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function setCallRating($params);
    /**
    * Send phone call debug data to server.
    *
    * Parameters:
    `InputPhoneCall` **peer**  - Phone call
    `DataJSON`       **debug** - Debug statistics obtained from libtgvoip
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveCallDebug($params);
    /**
    * Send VoIP signaling data.
    *
    * Parameters:
    `InputPhoneCall` **peer** - Phone call
    `bytes`          **data** - Signaling payload
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function sendSignalingData($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**          -
    `string`    **title**         - Optional:
    `int`       **schedule_date** - Optional:.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function createGroupCall($params);
    /**
    *
    *
    * Parameters:
    `boolean`        **muted**         - Optional:
    `boolean`        **video_stopped** - Optional:
    `InputGroupCall` **call**          -
    `InputPeer`      **join_as**       -
    `string`         **invite_hash**   - Optional:
    `DataJSON`       **params**        -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function joinGroupCall($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**   -
    `int`            **source** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function leaveGroupCall($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**  -
    `[InputUser]`    **users** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function inviteToGroupCall($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function discardGroupCall($params);
    /**
    *
    *
    * Parameters:
    `boolean`        **reset_invite_hash** - Optional:
    `InputGroupCall` **call**              -
    `Bool`           **join_muted**        - Optional:.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function toggleGroupCallSettings($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**  -
    `int`            **limit** -.
    *
    * @param array $params Parameters
    *
    * @return phone .GroupCall
    */
    public function getGroupCall($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**    -
    `[InputPeer]`    **ids**     -
    `[int]`          **sources** -
    `string`         **offset**  -
    `int`            **limit**   -.
    *
    * @param array $params Parameters
    *
    * @return phone .GroupParticipants
    */
    public function getGroupParticipants($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**    -
    `[int]`          **sources** -.
    *
    * @param array $params Parameters
    *
    * @return of int[]
    */
    public function checkGroupCall($params);
    /**
    *
    *
    * Parameters:
    `boolean`        **start**          - Optional:
    `boolean`        **video**          - Optional:
    `InputGroupCall` **call**           -
    `string`         **title**          - Optional:
    `Bool`           **video_portrait** - Optional:.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function toggleGroupCallRecord($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**                -
    `InputPeer`      **participant**         -
    `Bool`           **muted**               - Optional:
    `int`            **volume**              - Optional:
    `Bool`           **raise_hand**          - Optional:
    `Bool`           **video_stopped**       - Optional:
    `Bool`           **video_paused**        - Optional:
    `Bool`           **presentation_paused** - Optional:.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editGroupCallParticipant($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**  -
    `string`         **title** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editGroupCallTitle($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer** -.
    *
    * @param array $params Parameters
    *
    * @return phone .JoinAsPeers
    */
    public function getGroupCallJoinAs($params);
    /**
    *
    *
    * Parameters:
    `boolean`        **can_self_unmute** - Optional:
    `InputGroupCall` **call**            -.
    *
    * @param array $params Parameters
    *
    * @return phone .ExportedGroupCallInvite
    */
    public function exportGroupCallInvite($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**       -
    `Bool`           **subscribed** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function toggleGroupCallStartSubscription($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function startScheduledGroupCall($params);
    /**
    *
    *
    * Parameters:
    `InputPeer` **peer**    -
    `InputPeer` **join_as** -.
    *
    * @param array $params Parameters
    *
    * @return bool
    */
    public function saveDefaultGroupCallJoinAs($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call**   -
    `DataJSON`       **params** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function joinGroupCallPresentation($params);
    /**
    *
    *
    * Parameters:
    `InputGroupCall` **call** -.
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function leaveGroupCallPresentation($params);
}
interface langpack
{
    /**
    * Get localization pack strings.
    *
    * Parameters:
    `string` **lang_pack** - Language pack name
    `string` **lang_code** - Language code
    *
    * @param array $params Parameters
    *
    * @return LangPackDifference
    */
    public function getLangPack($params);
    /**
    * Get strings from a language pack.
    *
    * Parameters:
    `string`   **lang_pack** - Language pack name
    `string`   **lang_code** - Language code
    `[string]` **keys**      - Strings to get
    *
    * @param array $params Parameters
    *
    * @return of LangPackString[]
    */
    public function getStrings($params);
    /**
    * Get new strings in languagepack.
    *
    * Parameters:
    `string` **lang_pack**    - Language pack
    `string` **lang_code**    - Language code
    `int`    **from_version** - Previous localization pack version
    *
    * @param array $params Parameters
    *
    * @return LangPackDifference
    */
    public function getDifference($params);
    /**
    * Get information about all languages in a localization pack.
    *
    * Parameters:
    `string` **lang_pack** - Language pack
    *
    * @param array $params Parameters
    *
    * @return of LangPackLanguage[]
    */
    public function getLanguages($params);
    /**
    * Get information about a language in a localization pack.
    *
    * Parameters:
    `string` **lang_pack** - Language pack name
    `string` **lang_code** - Language code
    *
    * @param array $params Parameters
    *
    * @return LangPackLanguage
    */
    public function getLanguage($params);
}
interface folders
{
    /**
    * Edit peers in [peer folder](https://core.telegram.org/api/folders#peer-folders).
    *
    * Parameters:
    `[InputFolderPeer]` **folder_peers** - New peer list
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function editPeerFolders($params);
    /**
    * Delete a [peer folder](https://core.telegram.org/api/folders#peer-folders).
    *
    * Parameters:
    `int` **folder_id** - [Peer folder ID, for more info click here](https://core.telegram.org/api/folders#peer-folders)
    *
    * @param array $params Parameters
    *
    * @return Updates
    */
    public function deleteFolder($params);
}
interface stats
{
    /**
    * Get [channel statistics](https://core.telegram.org/api/stats).
    *
    * Parameters:
    `boolean`      **dark**    - Optional: Whether to enable dark theme for graph colors
    `InputChannel` **channel** - The channel
    *
    * @param array $params Parameters
    *
    * @return stats .BroadcastStats
    */
    public function getBroadcastStats($params);
    /**
    * Load [channel statistics graph](https://core.telegram.org/api/stats) asynchronously.
    *
    * Parameters:
    `string` **token** - Graph token from [statsGraphAsync](https://docs.madelineproto.xyz/API_docs/constructors/statsGraphAsync.html) constructor
    `long`   **x**     - Optional: Zoom value, if required
    *
    * @param array $params Parameters
    *
    * @return StatsGraph
    */
    public function loadAsyncGraph($params);
    /**
    * Get [supergroup statistics](https://core.telegram.org/api/stats).
    *
    * Parameters:
    `boolean`      **dark**    - Optional: Whether to enable dark theme for graph colors
    `InputChannel` **channel** - [Supergroup ID](https://core.telegram.org/api/channel)
    *
    * @param array $params Parameters
    *
    * @return stats .MegagroupStats
    */
    public function getMegagroupStats($params);
    /**
    * Obtains a list of messages, indicating to which other public channels was a channel message forwarded.
    Will return a list of [messages](https://docs.madelineproto.xyz/API_docs/constructors/message.html) with `peer_id` equal to the public channel to which this message was forwarded.
    *
    * Parameters:
    `InputChannel` **channel**     - Source channel
    `int`          **msg_id**      - Source message ID
    `int`          **offset_rate** - Initially 0, then set to the `next_rate` parameter of [messages.messagesSlice](https://docs.madelineproto.xyz/API_docs/constructors/messages.messagesSlice.html)
    `InputPeer`    **offset_peer** - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`          **offset_id**   - [Offsets for pagination, for more info click here](https://core.telegram.org/api/offsets)
    `int`          **limit**       - Maximum number of results to return, [see pagination](https://core.telegram.org/api/offsets)
    *
    * @param array $params Parameters
    *
    * @return messages .Messages
    */
    public function getMessagePublicForwards($params);
    /**
    * Get [message statistics](https://core.telegram.org/api/stats).
    *
    * Parameters:
    `boolean`      **dark**    - Optional: Whether to enable dark theme for graph colors
    `InputChannel` **channel** - Channel ID
    `int`          **msg_id**  - Message ID
    *
    * @param array $params Parameters
    *
    * @return stats .MessageStats
    */
    public function getMessageStats($params);
}
class InternalDoc extends APIFactory
{
    /**
     * Convert MTProto parameters to bot API parameters.
     *
     * @param array $data Data
     *
     * @return \Amp\Promise<array>
     */
    public function MTProtoToBotAPI(array $data, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$data, $extra]);
    }
    /**
     * MTProto to TD params.
     *
     * @param mixed $params Params
     *
     * @return \Amp\Promise
     */
    public function MTProtoToTd(&$params, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$params, $extra]);
    }
    /**
     * MTProto to TDCLI params.
     *
     * @param mixed $params Params
     *
     * @return \Amp\Promise
     */
    public function MTProtoToTdcli($params, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$params, $extra]);
    }
    /**
     * Accept call.
     *
     * @param array $call Call
     *
     * @return \Amp\Promise
     */
    public function acceptCall(array $call, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$call, $extra]);
    }
    /**
     * Accept secret chat.
     *
     * @param array $params Secret chat ID
     *
     * @return \Amp\Promise
     */
    public function acceptSecretChat($params, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$params, $extra]);
    }
    /**
     * Accept terms of service update.
     *
     * @return \Amp\Promise
     */
    public function acceptTos(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Add user info.
     *
     * @param array $user User info
     *
     * @return \Amp\Promise
     * @throws \danog\MadelineProto\Exception
     */
    public function addUser(array $user, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$user, $extra]);
    }
    /**
     * Call promise $b after promise $a.
     *
     * @param (\Generator | Promise) $a Promise A
     * @param (\Generator | Promise) $b Promise B
     *
     * @psalm-suppress InvalidScope
     *
     * @return \Amp\Promise
     */
    public function after($a, $b)
    {
        return \danog\MadelineProto\Tools::after($a, $b);
    }
    /**
    * Returns a promise that succeeds when all promises succeed, and fails if any promise fails.
    Returned promise succeeds with an array of values used to succeed each contained promise, with keys corresponding to the array of promises.
    *
    * @param array<(\Generator | Promise)> $promises Promises
    *
    * @return \Amp\Promise
    */
    public function all(array $promises)
    {
        return \danog\MadelineProto\Tools::all($promises);
    }
    /**
     * Returns a promise that is resolved when all promises are resolved. The returned promise will not fail.
     *
     * @param array<(Promise | \Generator)> $promises Promises
     *
     * @return \Amp\Promise
     */
    public function any(array $promises)
    {
        return \danog\MadelineProto\Tools::any($promises);
    }
    /**
     * Create array.
     *
     * @param mixed ...$params Params
     *
     * @return array
     */
    public function arr(...$params) : array
    {
        return \danog\MadelineProto\Tools::arr(...$params);
    }
    /**
     * base64URL decode.
     *
     * @param string $data Data to decode
     *
     * @return string
     */
    public function base64urlDecode(string $data) : string
    {
        return \danog\MadelineProto\Tools::base64urlDecode($data);
    }
    /**
     * Base64URL encode.
     *
     * @param string $data Data to encode
     *
     * @return string
     */
    public function base64urlEncode(string $data) : string
    {
        return \danog\MadelineProto\Tools::base64urlEncode($data);
    }
    /**
     * Convert bot API parameters to MTProto parameters.
     *
     * @param array $arguments Arguments
     *
     * @return \Amp\Promise<array>
     */
    public function botAPIToMTProto(array $arguments, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$arguments, $extra]);
    }
    /**
     * Login as bot.
     *
     * @param string $token Bot token
     *
     * @return \Amp\Promise
     */
    public function botLogin(string $token, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$token, $extra]);
    }
    /**
     * Convert generator, promise or any other value to a promise.
     *
     * @param (\Generator | Promise | mixed) $promise
     *
     * @template TReturn
     * @psalm-param (\Generator<mixed, mixed, mixed, TReturn> | Promise<TReturn> | TReturn) $promise
     *
     * @return \Amp\Promise
     * @psalm-return Promise<TReturn>
     */
    public function call($promise)
    {
        return \danog\MadelineProto\Tools::call($promise);
    }
    /**
     * Call promise in background.
     *
     * @param (\Generator | Promise) $promise Promise to resolve
     * @param ?\Generator|Promise $actual  Promise to resolve instead of $promise
     * @param string $file File
     *
     * @psalm-suppress InvalidScope
     *
     * @return (\Amp\Promise | mixed)
     */
    public function callFork($promise, $actual = null, $file = '')
    {
        return \danog\MadelineProto\Tools::callFork($promise, $actual, $file);
    }
    /**
     * Call promise in background, deferring execution.
     *
     * @param (\Generator | Promise) $promise Promise to resolve
     *
     * @return void
     */
    public function callForkDefer($promise) : void
    {
        \danog\MadelineProto\Tools::callForkDefer($promise);
    }
    /**
     * Get call status.
     *
     * @param int $id Call ID
     *
     * @psalm-return (int | \Amp\Promise<int>)
     * @return mixed
     */
    public function callStatus($id)
    {
        return $this->__call(__FUNCTION__, [$id]);
    }
    /**
     * Check for terms of service update.
     *
     * @return \Amp\Promise
     */
    public function checkTos(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Cleanup memory and session file.
     *
     * @return \Amp\Promise
     */
    public function cleanup(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Close connection with client, connected via web.
     *
     * @param string $message Message
     *
     * @return void
     */
    public function closeConnection($message)
    {
        return \danog\MadelineProto\Tools::closeConnection($message);
    }
    /**
     * Complete 2FA login.
     *
     * @param string $password Password
     *
     * @return \Amp\Promise
     */
    public function complete2faLogin(string $password, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$password, $extra]);
    }
    /**
     * Complete call handshake.
     *
     * @param array $params Params
     *
     * @return \Amp\Promise
     */
    public function completeCall(array $params, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$params, $extra]);
    }
    /**
     * Complet user login using login code.
     *
     * @param string $code Login code
     *
     * @return \Amp\Promise
     */
    public function completePhoneLogin($code, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$code, $extra]);
    }
    /**
     * Complete signup to Telegram.
     *
     * @param string $first_name First name
     * @param string $last_name Last name
     *
     * @return \Amp\Promise
     */
    public function completeSignup(string $first_name, string $last_name = '', array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$first_name, $last_name, $extra]);
    }
    /**
     * Confirm call.
     *
     * @param array $params Params
     *
     * @return \Amp\Promise
     */
    public function confirmCall(array $params, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$params, $extra]);
    }
    /**
     * Connects to all datacenters and if necessary creates authorization keys, binds them and writes client info.
     *
     * @param boolean $reconnectAll Whether to reconnect to all DCs
     *
     * @return \Amp\Promise
     */
    public function connectToAllDcs(bool $reconnectAll = true, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$reconnectAll, $extra]);
    }
    /**
     * Decline terms of service update.
     *
     * THIS WILL DELETE YOUR ACCOUNT!
     *
     * @return \Amp\Promise
     */
    public function declineTos(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Discard call.
     *
     * @param array $call Call
     * @param array $reason
     * @param array $rating Rating
     * @param boolean $need_debug Need debug?
     *
     * @return \Amp\Promise
     */
    public function discardCall(array $call, array $reason, array $rating = [], bool $need_debug = true, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$call, $reason, $rating, $need_debug, $extra]);
    }
    /**
     * Discard secret chat.
     *
     * @param int $chat Secret chat ID
     *
     * @return \Amp\Promise
     */
    public function discardSecretChat(int $chat, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$chat, $extra]);
    }
    /**
     * Download file to browser.
     *
     * Supports HEAD requests and content-ranges for parallel and resumed downloads.
     *
     * @param (array | string) $messageMedia File to download
     * @param callable $cb Status callback (can also use FileCallback)
     *
     * @return \Amp\Promise
     */
    public function downloadToBrowser($messageMedia, ?callable $cb = null, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$messageMedia, $cb, $extra]);
    }
    /**
    * Download file to callable.
    The callable must accept two parameters: string $payload, int $offset
    The callable will be called (possibly out of order, depending on the value of $seekable).
    The callable should return the number of written bytes.
    *
    * @param mixed $messageMedia File to download
    * @param (callable | FileCallbackInterface) $callable Chunk callback
    * @param callable $cb Status callback (DEPRECATED, use FileCallbackInterface)
    * @param bool $seekable Whether the callable can be called out of order
    * @param int $offset Offset where to start downloading
    * @param int $end Offset where to stop downloading (inclusive)
    * @param int $part_size Size of each chunk
    *
    * @return \Amp\Promise
    *
    * @psalm-return \Amp\Promise<true>
    */
    public function downloadToCallable($messageMedia, callable $callable, $cb = null, bool $seekable = true, int $offset = 0, int $end = -1, ?int $part_size = null, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$messageMedia, $callable, $cb, $seekable, $offset, $end, $part_size, $extra]);
    }
    /**
     * Download file to directory.
     *
     * @param mixed $messageMedia File to download
     * @param (string | FileCallbackInterface) $dir Directory where to download the file
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<(false | string)>
     */
    public function downloadToDir($messageMedia, $dir, $cb = null, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$messageMedia, $dir, $cb, $extra]);
    }
    /**
     * Download file.
     *
     * @param mixed $messageMedia File to download
     * @param (string | FileCallbackInterface) $file Downloaded file path
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     *
     * @return \Amp\Promise Downloaded file path
     *
     * @psalm-return \Amp\Promise<(false | string)>
     */
    public function downloadToFile($messageMedia, $file, $cb = null, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$messageMedia, $file, $cb, $extra]);
    }
    /**
     * Download file to amphp/http-server response.
     *
     * Supports HEAD requests and content-ranges for parallel and resumed downloads.
     *
     * @param (array | string) $messageMedia File to download
     * @param ServerRequest $request Request
     * @param callable $cb Status callback (can also use FileCallback)
     *
     * @return \Amp\Promise Returned response
     *
     * @psalm-return \Amp\Promise<\Amp\Http\Server\Response>
     */
    public function downloadToResponse($messageMedia, \Amp\Http\Server\Request $request, ?callable $cb = null, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$messageMedia, $request, $cb, $extra]);
    }
    /**
     * Download file to stream.
     *
     * @param mixed $messageMedia File to download
     * @param (mixed | FileCallbackInterface) $stream Stream where to download file
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param int $offset Offset where to start downloading
     * @param int $end Offset where to end download
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<mixed>
     */
    public function downloadToStream($messageMedia, $stream, $cb = null, int $offset = 0, int $end = -1, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$messageMedia, $stream, $cb, $offset, $end, $extra]);
    }
    /**
     * Asynchronously write to stdout/browser.
     *
     * @param string $string Message to echo
     *
     * @return \Amp\Promise
     */
    public function echo(string $string)
    {
        return \danog\MadelineProto\Tools::echo($string);
    }
    /**
     * Get final element of array.
     *
     * @param array $what Array
     *
     * @return mixed
     */
    public function end(array $what)
    {
        return \danog\MadelineProto\Tools::end($what);
    }
    /**
     * Export authorization.
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<array{0: (int | string), 1: string}>
     */
    public function exportAuthorization(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Extract file info from bot API message.
     *
     * @param array $info Bot API message object
     *
     * @return ?array
     */
    public function extractBotAPIFile(array $info) : ?array
    {
        return \danog\MadelineProto\MTProto::extractBotAPIFile($info);
    }
    /**
     * Get contents of remote file asynchronously.
     *
     * @param string $url URL
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<string>
     */
    public function fileGetContents(string $url, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$url, $extra]);
    }
    /**
     * Returns a promise that succeeds when the first promise succeeds, and fails only if all promises fail.
     *
     * @param array<(Promise | \Generator)> $promises Promises
     *
     * @return \Amp\Promise
     */
    public function first(array $promises)
    {
        return \danog\MadelineProto\Tools::first($promises);
    }
    /**
    * Asynchronously lock a file
    Resolves with a callbable that MUST eventually be called in order to release the lock.
    *
    * @param string $file File to lock
    * @param integer $operation Locking mode
    * @param float $polling Polling interval
    * @param ?Promise $token Cancellation token
    * @param ?callable $failureCb Failure callback, called only once if the first locking attempt fails.
    *
    * @return \Amp\Promise<$token is null ? callable : ?callable>
    */
    public function flock(string $file, int $operation, float $polling = 0.1, ?\Amp\Promise $token = null, $failureCb = null)
    {
        return \danog\MadelineProto\Tools::flock($file, $operation, $polling, $token, $failureCb);
    }
    /**
     * Convert bot API channel ID to MTProto channel ID.
     *
     * @param int $id Bot API channel ID
     *
     * @return int
     */
    public function fromSupergroup($id) : int
    {
        return \danog\MadelineProto\MTProto::fromSupergroup($id);
    }
    /**
     * When were full info for this chat last cached.
     *
     * @param mixed $id Chat ID
     *
     * @return \Amp\Promise<integer>
     */
    public function fullChatLastUpdated($id, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$id, $extra]);
    }
    /**
     * Get info about the logged-in user, not cached.
     *
     * @return \Amp\Promise<(array | bool)>
     */
    public function fullGetSelf(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Generate MTProto vector hash.
     *
     * @param array $ints IDs
     *
     * @return string Vector hash
     */
    public function genVectorHash(array $ints) : string
    {
        return \danog\MadelineProto\Tools::genVectorHash($ints);
    }
    /**
     * Get full list of MTProto and API methods.
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function getAllMethods()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get authorization info.
     *
     * @psalm-return (int | \Amp\Promise<int>)
     * @return mixed
     */
    public function getAuthorization()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get cached server-side config.
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function getCachedConfig()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get call info.
     *
     * @param int $call Call ID
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function getCall($call)
    {
        return $this->__call(__FUNCTION__, [$call]);
    }
    /**
     * Store RSA keys for CDN datacenters.
     *
     * @param string $datacenter DC ID
     *
     * @return \Amp\Promise
     */
    public function getCdnConfig(string $datacenter, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$datacenter, $extra]);
    }
    /**
     * Get cached (or eventually re-fetch) server-side config.
     *
     * @param array $config Current config
     * @param array $options Options for method call
     *
     * @return \Amp\Promise
     */
    public function getConfig(array $config = [], array $options = [], array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$config, $options, $extra]);
    }
    /**
     * Get async DNS client.
     *
     * @psalm-return (\Amp\Dns\Resolver | \Amp\Promise<\Amp\Dns\Resolver>)
     * @return mixed
     */
    public function getDNSClient()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get all datacenter connections.
     *
     * @psalm-return (array<DataCenterConnection> | \Amp\Promise<array<DataCenterConnection>>)
     * @return mixed
     */
    public function getDataCenterConnections()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get main DC ID.
     *
     * @return (int | string)
     */
    public function getDataCenterId(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Get dialog peers.
     *
     * @param boolean $force Whether to refetch all dialogs ignoring cache
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<list<mixed>>
     */
    public function getDialogs(bool $force = true, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$force, $extra]);
    }
    /**
    * Get download info of file
    Returns an array with the following structure:.
    *
    * `$info['ext']` - The file extension
    `$info['name']` - The file name, without the extension
    `$info['mime']` - The file mime type
    `$info['size']` - The file size
    *
    * @param mixed $messageMedia File ID
    *
    * @return \Amp\Promise<array>
    */
    public function getDownloadInfo($messageMedia, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$messageMedia, $extra]);
    }
    /**
     * Get event handler.
     *
     * @psalm-return (\danog\MadelineProto\EventHandler | \Amp\Promise<\danog\MadelineProto\EventHandler>)
     * @return mixed
     */
    public function getEventHandler()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get extension from file location.
     *
     * @param mixed $location File location
     * @param string $default Default extension
     *
     * @return string
     */
    public function getExtensionFromLocation($location, string $default) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromLocation($location, $default);
    }
    /**
     * Get extension from mime type.
     *
     * @param string $mime MIME type
     *
     * @return string
     */
    public function getExtensionFromMime(string $mime) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromMime($mime);
    }
    /**
     * Get info about file.
     *
     * @param mixed $constructor File ID
     *
     * @return \Amp\Promise<array>
     */
    public function getFileInfo($constructor, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$constructor, $extra]);
    }
    /**
     * Get folder ID from object.
     *
     * @param mixed $id Object
     *
     * @return ?int
     */
    public function getFolderId($id) : ?int
    {
        return \danog\MadelineProto\MTProto::getFolderId($id);
    }
    /**
     * Get full info of all dialogs.
     *
     * @param boolean $force Whether to refetch all dialogs ignoring cache
     *
     * @return \Amp\Promise
     */
    public function getFullDialogs(bool $force = true, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$force, $extra]);
    }
    /**
     * Get full info about peer, returns an FullInfo object.
     *
     * @param mixed $id Peer
     *
     * @see https://docs.madelineproto.xyz/FullInfo.html
     *
     * @return \Amp\Promise FullInfo object
     *
     * @psalm-return \Amp\Promise<array>
     */
    public function getFullInfo($id, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$id, $extra]);
    }
    /**
     * Get async HTTP client.
     *
     * @psalm-return (\Amp\Http\Client\HttpClient | \Amp\Promise<\Amp\Http\Client\HttpClient>)
     * @return mixed
     */
    public function getHTTPClient()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get current password hint.
     *
     * @psalm-return (string | \Amp\Promise<string>)
     * @return mixed
     */
    public function getHint()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get bot API ID from peer object.
     *
     * @param mixed $id Peer
     *
     * @return int
     */
    public function getId($id, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$id, $extra]);
    }
    /**
    * Get info about peer, returns an Info object.
    *
    * @param mixed $id Peer
    * @param MTProto::INFO_TYPE_* $type Whether to generate an Input*, an InputPeer or the full set of constructors
    * @param boolean $recursive Internal
    *
    * @see https://docs.madelineproto.xyz/Info.html
    *
    * @return \Amp\Promise Info object
    *
    * @template TConstructor
    * @psalm-param $id array{_: TConstructor}|mixed
    *
    * @return (((mixed | string)[] | mixed | string)[] | int | mixed | string)[]
    *
    * @psalm-return \Generator<int|mixed, \Amp\Promise|\Amp\Promise<string>|array, mixed, array{
    TConstructor: array
    InputPeer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed},
    Peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed},
    DialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
    NotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
    InputDialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
    InputNotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
    bot_api_id: int|string,
    user_id?: int,
    chat_id?: int,
    channel_id?: int,
    InputUser?: array{_: string, user_id?: int, access_hash?: mixed, min?: bool},
    InputChannel?: array{_: string, channel_id: int, access_hash: mixed, min: bool},
    type: string
    }>|int|array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}|array{_: string, user_id?: int, access_hash?: mixed, min?: bool}|array{_: string, channel_id: int, access_hash: mixed, min: bool}
    */
    public function getInfo($id, int $type = \danog\MadelineProto\MTProto::INFO_TYPE_ALL, $recursive = true, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$id, $type, $recursive, $extra]);
    }
    /**
     * Get logger.
     */
    public function getLogger()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get TL namespaces.
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function getMethodNamespaces()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get namespaced methods (method => namespace).
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function getMethodsNamespaced()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get mime type from buffer.
     *
     * @param string $buffer Buffer
     *
     * @return string
     */
    public function getMimeFromBuffer(string $buffer) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromBuffer($buffer);
    }
    /**
     * Get mime type from file extension.
     *
     * @param string $extension File extension
     * @param string $default Default mime type
     *
     * @return string
     */
    public function getMimeFromExtension(string $extension, string $default) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromExtension($extension, $default);
    }
    /**
     * Get mime type of file.
     *
     * @param string $file File
     *
     * @return string
     */
    public function getMimeFromFile(string $file) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromFile($file);
    }
    /**
    * Get download info of the propic of a user
    Returns an array with the following structure:.
    *
    * `$info['ext']` - The file extension
    `$info['name']` - The file name, without the extension
    `$info['mime']` - The file mime type
    `$info['size']` - The file size
    *
    * @param mixed $messageMedia File ID
    *
    * @return \Amp\Promise<array>
    */
    public function getPropicInfo($data, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$data, $extra]);
    }
    /**
     * Get PSR logger.
     */
    public function getPsrLogger()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get full info about peer (including full list of channel members), returns a Chat object.
     *
     * @param mixed $id Peer
     *
     * @see https://docs.madelineproto.xyz/Chat.html
     *
     * @return \Amp\Promise Chat object
     */
    public function getPwrChat($id, bool $fullfetch = true, bool $send = true, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$id, $fullfetch, $send, $extra]);
    }
    /**
     * Get secret chat.
     *
     * @param (array | int) $chat Secret chat ID
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function getSecretChat($chat)
    {
        return $this->__call(__FUNCTION__, [$chat]);
    }
    /**
     * Get info about the logged-in user, cached.
     *
     * @return (array | bool)
     */
    public function getSelf(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Return current settings.
     *
     * @psalm-return (\danog\MadelineProto\Settings | \Amp\Promise<\danog\MadelineProto\Settings>)
     * @return mixed
     */
    public function getSettings()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
    * Get sponsored messages for channel.
    This method will return an array of [sponsored message objects](https://docs.madelineproto.xyz/API_docs/constructors/sponsoredMessage.html).
    *
    * See [the API documentation](https://core.telegram.org/api/sponsored-messages) for more info on how to handle sponsored messages.
    *
    * @param (int | array) $peer Channel ID, or Update, or Message, or Peer.
    * @return \Amp\Promise
    */
    public function getSponsoredMessages($peer, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$peer, $extra]);
    }
    /**
     * Get TL serializer.
     *
     * @psalm-return (\danog\MadelineProto\TL\TL | \Amp\Promise<\danog\MadelineProto\TL\TL>)
     * @return mixed
     */
    public function getTL()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Accesses a private variable from an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     *
     * @psalm-suppress InvalidScope
     *
     * @return mixed
     * @access public
     */
    public function getVar($obj, string $var)
    {
        return \danog\MadelineProto\Tools::getVar($obj, $var);
    }
    /**
     * Get a message to show to the user when starting the bot.
     *
     * @param string $message
     */
    public function getWebMessage(string $message)
    {
        return $this->__call(__FUNCTION__, [$message]);
    }
    /**
     * Get web template.
     *
     * @psalm-return (string | \Amp\Promise<string>)
     * @return mixed
     */
    public function getWebTemplate()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Checks whether all datacenters are authorized.
     *
     * @psalm-return (bool | \Amp\Promise<bool>)
     * @return mixed
     */
    public function hasAllAuth()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Check if an event handler instance is present.
     *
     * @psalm-return (bool | \Amp\Promise<bool>)
     * @return mixed
     */
    public function hasEventHandler()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Check if has report peers.
     *
     * @psalm-return (bool | \Amp\Promise<bool>)
     * @return mixed
     */
    public function hasReportPeers()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Check whether secret chat exists.
     *
     * @param (array | int) $chat Secret chat ID
     *
     * @psalm-return (bool | \Amp\Promise<bool>)
     * @return mixed
     */
    public function hasSecretChat($chat)
    {
        return $this->__call(__FUNCTION__, [$chat]);
    }
    /**
     * Checks private property exists in an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     *
     * @psalm-suppress InvalidScope
     *
     * @return bool
     * @access public
     */
    public function hasVar($obj, string $var) : bool
    {
        return \danog\MadelineProto\Tools::hasVar($obj, $var);
    }
    /**
     * Import authorization.
     *
     * @param array<int, string> $authorization Authorization info
     * @param int $mainDcID Main DC ID
     *
     * @return \Amp\Promise
     */
    public function importAuthorization(array $authorization, int $mainDcID, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$authorization, $mainDcID, $extra]);
    }
    /**
     * Inflate stripped photosize to full JPG payload.
     *
     * @param string $stripped Stripped photosize
     *
     * @return string JPG payload
     */
    public function inflateStripped(string $stripped) : string
    {
        return \danog\MadelineProto\Tools::inflateStripped($stripped);
    }
    /**
     * Initialize self-restart hack.
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function initSelfRestart()
    {
        $this->__call(__FUNCTION__, []);
    }
    /**
     * Whether this is altervista.
     *
     * @return boolean
     */
    public function isAltervista() : bool
    {
        return \danog\MadelineProto\Tools::isAltervista();
    }
    /**
     * Check if is array or similar (traversable && countable && arrayAccess).
     *
     * @param mixed $var Value to check
     *
     * @return boolean
     */
    public function isArrayOrAlike($var) : bool
    {
        return \danog\MadelineProto\Tools::isArrayOrAlike($var);
    }
    /**
     * Whether we're an IPC client instance.
     *
     * @psalm-return (bool | \Amp\Promise<bool>)
     * @return mixed
     */
    public function isIpc()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Whether we're an IPC server process (as opposed to an event handler).
     *
     * @psalm-return (bool | \Amp\Promise<bool>)
     * @return mixed
     */
    public function isIpcWorker()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Check whether provided bot API ID is a channel.
     *
     * @param int $id Bot API ID
     *
     * @return boolean
     */
    public function isSupergroup($id) : bool
    {
        return \danog\MadelineProto\MTProto::isSupergroup($id);
    }
    /**
     * Logger.
     *
     * @param string $param Parameter
     * @param int $level Logging level
     * @param string $file File where the message originated
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function logger($param, int $level = \danog\MadelineProto\Logger::NOTICE, string $file = '')
    {
        $this->__call(__FUNCTION__, [$param, $level, $file]);
    }
    /**
     * Log out currently logged in user.
     *
     * @return \Amp\Promise
     */
    public function logout(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Start MadelineProto's update handling loop, or run the provided async callable.
     *
     * @param (callable | null) $callback Async callable to run
     *
     * @return \Amp\Promise
     */
    public function loop($callback = null, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$callback, $extra]);
    }
    /**
     * Start MadelineProto's update handling loop in background.
     *
     * @return \Amp\Promise
     */
    public function loopFork(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Escape string for markdown.
     *
     * @param string $hwat String to escape
     *
     * @return string
     */
    public function markdownEscape(string $hwat) : string
    {
        return \danog\MadelineProto\StrTools::markdownEscape($hwat);
    }
    /**
     * Telegram UTF-8 multibyte split.
     *
     * @param string $text Text
     * @param integer $length Length
     *
     * @return array
     */
    public function mbStrSplit(string $text, int $length) : array
    {
        return \danog\MadelineProto\MTProto::mbStrSplit($text, $length);
    }
    /**
     * Get Telegram UTF-8 length of string.
     *
     * @param string $text Text
     *
     * @return (float | int)
     */
    public function mbStrlen(string $text)
    {
        return $this->__call(__FUNCTION__, [$text]);
    }
    /**
     * Telegram UTF-8 multibyte substring.
     *
     * @param string $text Text to substring
     * @param integer $offset Offset
     * @param ?int $length Length
     *
     * @return string
     */
    public function mbSubstr(string $text, int $offset, $length = null) : string
    {
        return \danog\MadelineProto\MTProto::mbSubstr($text, $offset, $length);
    }
    /**
     * Call method and wait asynchronously for response.
     *
     * If the $aargs['noResponse'] is true, will not wait for a response.
     *
     * @param string $method Method name
     * @param (array | \Generator) $args Arguments
     * @param array $aargs Additional arguments
     *
     * @psalm-param (array | \Generator<mixed, mixed, mixed, array>) $args
     *
     * @return \Amp\Promise
     */
    public function methodCall(string $method, $args = [], array $aargs = ['msg_id' => null], array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$method, $args, $aargs, $extra]);
    }
    /**
     * Call method and make sure it is asynchronously sent.
     *
     * @param string $method Method name
     * @param (array | \Generator) $args Arguments
     * @param array $aargs Additional arguments
     *
     * @psalm-param (array | \Generator<mixed, mixed, mixed, array>) $args
     *
     * @return \Amp\Promise
     */
    public function methodCallWrite(string $method, $args = [], array $aargs = ['msg_id' => null], array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$method, $args, $aargs, $extra]);
    }
    /**
     * Escape method name.
     *
     * @param string $method Method name
     *
     * @return string
     */
    public function methodEscape(string $method) : string
    {
        return \danog\MadelineProto\StrTools::methodEscape($method);
    }
    /**
     * Convert double to binary version.
     *
     * @param float $value Value to convert
     *
     * @return string
     */
    public function packDouble(float $value) : string
    {
        return \danog\MadelineProto\Tools::packDouble($value);
    }
    /**
     * Convert integer to base256 signed int.
     *
     * @param integer $value Value to convert
     *
     * @return string
     */
    public function packSignedInt(int $value) : string
    {
        return \danog\MadelineProto\Tools::packSignedInt($value);
    }
    /**
     * Convert integer to base256 long.
     *
     * @param int $value Value to convert
     *
     * @return string
     */
    public function packSignedLong(int $value) : string
    {
        return \danog\MadelineProto\Tools::packSignedLong($value);
    }
    /**
     * Convert value to unsigned base256 int.
     *
     * @param int $value Value
     *
     * @return string
     */
    public function packUnsignedInt(int $value) : string
    {
        return \danog\MadelineProto\Tools::packUnsignedInt($value);
    }
    /**
     * Check if peer is present in internal peer database.
     *
     * @param mixed $id Peer
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<bool>
     */
    public function peerIsset($id, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$id, $extra]);
    }
    /**
     * Login as user.
     *
     * @param string $number Phone number
     * @param integer $sms_type SMS type
     *
     * @return \Amp\Promise
     */
    public function phoneLogin($number, $sms_type = 5, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$number, $sms_type, $extra]);
    }
    /**
    * Positive modulo
    Works just like the % (modulus) operator, only returns always a postive number.
    *
    * @param int $a A
    * @param int $b B
    *
    * @return int Modulo
    */
    public function posmod(int $a, int $b) : int
    {
        return \danog\MadelineProto\Tools::posmod($a, $b);
    }
    /**
     * Get random string of specified length.
     *
     * @param integer $length Length
     *
     * @return string Random string
     */
    public function random(int $length) : string
    {
        return \danog\MadelineProto\Tools::random($length);
    }
    /**
     * Get random integer.
     *
     * @param integer $modulus Modulus
     *
     * @return int
     */
    public function randomInt(int $modulus = 0) : int
    {
        return \danog\MadelineProto\Tools::randomInt($modulus);
    }
    /**
     * Asynchronously read line.
     *
     * @param string $prompt Prompt
     *
     * @return \Amp\Promise<string>
     */
    public function readLine(string $prompt = '')
    {
        return \danog\MadelineProto\Tools::readLine($prompt);
    }
    /**
     * Rekey secret chat.
     *
     * @param int $chat Secret chat to rekey
     *
     * @return \Amp\Promise
     */
    public function rekey(int $chat, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$chat, $extra]);
    }
    /**
     * Report an error to the previously set peer.
     *
     * @param string $message Error to report
     * @param string $parseMode Parse mode
     *
     * @return \Amp\Promise
     */
    public function report(string $message, string $parseMode = '', array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$message, $parseMode, $extra]);
    }
    /**
     * Request VoIP call.
     *
     * @param mixed $user User
     *
     * @return \Amp\Promise
     */
    public function requestCall($user, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$user, $extra]);
    }
    /**
     * Request secret chat.
     *
     * @param mixed $user User to start secret chat with
     *
     * @return \Amp\Promise
     */
    public function requestSecretChat($user, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$user, $extra]);
    }
    /**
     * Reset the update state and fetch all updates from the beginning.
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function resetUpdateState()
    {
        $this->__call(__FUNCTION__, []);
    }
    /**
     * Resolve username (use getInfo instead).
     *
     * @param string $username Username
     *
     * @return \Amp\Promise
     */
    public function resolveUsername(string $username, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$username, $extra]);
    }
    /**
     * Restart update loop.
     *
     * @return void
     */
    public function restart(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Rethrow error catched in strand.
     *
     * @param \Throwable $e Exception
     * @param string $file File where the strand started
     *
     * @psalm-suppress InvalidScope
     *
     * @return void
     */
    public function rethrow(\Throwable $e, $file = '') : void
    {
        \danog\MadelineProto\Tools::rethrow($e, $file);
    }
    /**
     * null-byte RLE decode.
     *
     * @param string $string Data to decode
     *
     * @return string
     */
    public function rleDecode(string $string) : string
    {
        return \danog\MadelineProto\Tools::rleDecode($string);
    }
    /**
     * null-byte RLE encode.
     *
     * @param string $string Data to encode
     *
     * @return string
     */
    public function rleEncode(string $string) : string
    {
        return \danog\MadelineProto\Tools::rleEncode($string);
    }
    /**
     * Get secret chat status.
     *
     * @param int $chat Chat ID
     *
     * @psalm-return (int | \Amp\Promise<int>)
     * @return mixed
     */
    public function secretChatStatus(int $chat)
    {
        return $this->__call(__FUNCTION__, [$chat]);
    }
    /**
     * Serialize all instances.
     *
     * CALLED ONLY ON SHUTDOWN.
     *
     * @return void
     */
    public function serializeAll() : void
    {
        \danog\MadelineProto\MTProto::serializeAll();
    }
    /**
     * Set update handling callback.
     *
     * @param callable $callback Callback
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function setCallback($callback)
    {
        $this->__call(__FUNCTION__, [$callback]);
    }
    /**
     * Set event handler.
     *
     * @param class-string<EventHandler> $eventHandler Event handler
     *
     * @return \Amp\Promise
     */
    public function setEventHandler(string $eventHandler, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$eventHandler, $extra]);
    }
    /**
     * Set NOOP update handler, ignoring all updates.
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function setNoop()
    {
        $this->__call(__FUNCTION__, []);
    }
    /**
     * Set peer(s) where to send errors occurred in the event loop.
     *
     * @param (int | string) $userOrId Username(s) or peer ID(s)
     *
     * @return \Amp\Promise
     */
    public function setReportPeers($userOrId, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$userOrId, $extra]);
    }
    /**
     * Sets a private variable in an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     * @param mixed $val Attribute value
     *
     * @psalm-suppress InvalidScope
     *
     * @return void
     *
     * @access public
     */
    public function setVar($obj, string $var, &$val) : void
    {
        \danog\MadelineProto\Tools::setVar($obj, $var, $val);
    }
    /**
     * Set web template.
     *
     * @param string $template Template
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function setWebTemplate(string $template)
    {
        $this->__call(__FUNCTION__, [$template]);
    }
    /**
     * Set webhook update handler.
     *
     * @param string $hook_url Webhook URL
     * @param string $pem_path PEM path for self-signed certificate
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function setWebhook(string $hook_url, string $pem_path = '')
    {
        $this->__call(__FUNCTION__, [$hook_url, $pem_path]);
    }
    /**
     * Setup logger.
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function setupLogger()
    {
        $this->__call(__FUNCTION__, []);
    }
    /**
     * Asynchronously sleep.
     *
     * @param (int | float) $time Number of seconds to sleep for
     *
     * @return \Amp\Promise
     */
    public function sleep($time)
    {
        return \danog\MadelineProto\Tools::sleep($time);
    }
    /**
    * Resolves with a two-item array delineating successful and failed Promise results.
    The returned promise will only fail if the given number of required promises fail.
    *
    * @param array<(Promise | \Generator)> $promises Promises
    *
    * @return \Amp\Promise
    */
    public function some(array $promises)
    {
        return \danog\MadelineProto\Tools::some($promises);
    }
    /**
     * Log in to telegram (via CLI or web).
     *
     * @return \Amp\Promise
     */
    public function start(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Stop update loop.
     *
     * @return void
     */
    public function stop(array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$extra]);
    }
    /**
     * Convert TD to MTProto parameters.
     *
     * @param array $params Parameters
     *
     * @return \Amp\Promise<array>
     */
    public function tdToMTProto(array $params, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$params, $extra]);
    }
    /**
     * Convert TD parameters to tdcli.
     *
     * @param mixed $params Parameters
     *
     * @return mixed
     */
    public function tdToTdcli($params, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$params, $extra]);
    }
    /**
     * Convert tdcli parameters to tdcli.
     *
     * @param array $params Params
     * @param array $key Key
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function tdcliToTd(&$params, $key = null)
    {
        return $this->__call(__FUNCTION__, [$params, $key]);
    }
    /**
     * Create an artificial timeout for any \Generator or Promise.
     *
     * @param (\Generator | Promise) $promise
     * @param integer $timeout
     *
     * @return \Amp\Promise
     */
    public function timeout($promise, int $timeout)
    {
        return \danog\MadelineProto\Tools::timeout($promise, $timeout);
    }
    /**
     * Creates an artificial timeout for any `Promise`.
     *
     * If the promise is resolved before the timeout expires, the result is returned
     *
     * If the timeout expires before the promise is resolved, a default value is returned
     *
     * @template TReturnAlt
     * @template TReturn
     * @template TGenerator of \Generator<mixed, mixed, mixed, TReturn>
     *
     * @param (Promise | Generator) $promise Promise to which the timeout is applied.
     * @param int $timeout Timeout in milliseconds.
     * @param mixed $default
     *
     * @psalm-param (Promise<TReturn> | TGenerator) $promise Promise to which the timeout is applied.
     * @psalm-param TReturnAlt $default
     *
     * @return (\Amp\Promise<TReturn> | Promise<TReturnAlt>)
     *
     * @throws \TypeError If $promise is not an instance of \Amp\Promise, \Generator or \React\Promise\PromiseInterface.
     */
    public function timeoutWithDefault($promise, int $timeout, $default = null)
    {
        return \danog\MadelineProto\Tools::timeoutWithDefault($promise, $timeout, $default);
    }
    /**
     * Convert to camelCase.
     *
     * @param string $input String
     *
     * @return string
     */
    public function toCamelCase(string $input) : string
    {
        return \danog\MadelineProto\StrTools::toCamelCase($input);
    }
    /**
     * Convert to snake_case.
     *
     * @param string $input String
     *
     * @return string
     */
    public function toSnakeCase(string $input) : string
    {
        return \danog\MadelineProto\StrTools::toSnakeCase($input);
    }
    /**
     * Convert MTProto channel ID to bot API channel ID.
     *
     * @param int $id MTProto channel ID
     *
     * @return int
     */
    public function toSupergroup($id) : int
    {
        return \danog\MadelineProto\MTProto::toSupergroup($id);
    }
    /**
     * Escape type name.
     *
     * @param string $type String to escape
     *
     * @return string
     */
    public function typeEscape(string $type) : string
    {
        return \danog\MadelineProto\StrTools::typeEscape($type);
    }
    /**
     * Unpack binary double.
     *
     * @param string $value Value to unpack
     *
     * @return float
     */
    public function unpackDouble(string $value) : float
    {
        return \danog\MadelineProto\Tools::unpackDouble($value);
    }
    /**
     * Unpack bot API file ID.
     *
     * @param string $fileId Bot API file ID
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function unpackFileId(string $fileId)
    {
        return $this->__call(__FUNCTION__, [$fileId]);
    }
    /**
     * Unpack base256 signed int.
     *
     * @param string $value base256 int
     *
     * @return integer
     */
    public function unpackSignedInt(string $value) : int
    {
        return \danog\MadelineProto\Tools::unpackSignedInt($value);
    }
    /**
     * Unpack base256 signed long.
     *
     * @param string $value base256 long
     *
     * @return integer
     */
    public function unpackSignedLong(string $value) : int
    {
        return \danog\MadelineProto\Tools::unpackSignedLong($value);
    }
    /**
     * Unpack base256 signed long to string.
     *
     * @param (string | int | array) $value base256 long
     *
     * @return string
     */
    public function unpackSignedLongString($value) : string
    {
        return \danog\MadelineProto\Tools::unpackSignedLongString($value);
    }
    /**
     * Unset event handler.
     *
     * @param bool $disableUpdateHandling Whether to also disable internal update handling (will cause errors, otherwise will simply use the NOOP handler)
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function unsetEventHandler(bool $disableUpdateHandling = false)
    {
        $this->__call(__FUNCTION__, [$disableUpdateHandling]);
    }
    /**
     * Update the 2FA password.
     *
     * The params array can contain password, new_password, email and hint params.
     *
     * @param array $params The params
     *
     * @return \Amp\Promise
     */
    public function update2fa(array $params, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$params, $extra]);
    }
    /**
     * Parse, update and store settings.
     *
     * @param SettingsAbstract $settings Settings
     *
     * @return \Amp\Promise
     */
    public function updateSettings(\danog\MadelineProto\SettingsAbstract $settings, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$settings, $extra]);
    }
    /**
     * Upload file.
     *
     * @param (FileCallbackInterface | string | array) $file File, URL or Telegram file to upload
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<mixed>
     */
    public function upload($file, string $fileName = '', $cb = null, bool $encrypted = false, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$file, $fileName, $cb, $encrypted, $extra]);
    }
    /**
     * Upload file to secret chat.
     *
     * @param (FileCallbackInterface | string | array) $file File, URL or Telegram file to upload
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<mixed>
     */
    public function uploadEncrypted($file, string $fileName = '', $cb = null, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$file, $fileName, $cb, $extra]);
    }
    /**
    * Upload file from callable.
    *
    * The callable must accept two parameters: int $offset, int $size
    The callable must return a string with the contest of the file at the specified offset and size.
    *
    * @param mixed $callable Callable
    * @param integer $size File size
    * @param string $mime Mime type
    * @param string $fileName File name
    * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
    * @param boolean $seekable Whether chunks can be fetched out of order
    * @param boolean $encrypted Whether to encrypt file for secret chats
    *
    * @return \Amp\Promise
    *
    * @psalm-return \Amp\Promise<array{_: string, id: string, parts: int, name: string, mime_type: string, key_fingerprint?: mixed, key?: mixed, iv?: mixed, md5_checksum: string}>
    */
    public function uploadFromCallable(callable $callable, int $size, string $mime, string $fileName = '', $cb = null, bool $seekable = true, bool $encrypted = false, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$callable, $size, $mime, $fileName, $cb, $seekable, $encrypted, $extra]);
    }
    /**
     * Upload file from stream.
     *
     * @param mixed $stream PHP resource or AMPHP async stream
     * @param integer $size File size
     * @param string $mime Mime type
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<mixed>
     */
    public function uploadFromStream($stream, int $size, string $mime, string $fileName = '', $cb = null, bool $encrypted = false, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$stream, $size, $mime, $fileName, $cb, $encrypted, $extra]);
    }
    /**
     * Reupload telegram file.
     *
     * @param mixed $media Telegram file
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<mixed>
     */
    public function uploadFromTgfile($media, $cb = null, bool $encrypted = false, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$media, $cb, $encrypted, $extra]);
    }
    /**
     * Upload file from URL.
     *
     * @param (string | FileCallbackInterface) $url URL of file
     * @param integer $size Size of file
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Amp\Promise
     *
     * @psalm-return \Amp\Promise<mixed>
     */
    public function uploadFromUrl($url, int $size = 0, string $fileName = '', $cb = null, bool $encrypted = false, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$url, $size, $fileName, $cb, $encrypted, $extra]);
    }
    /**
     * Mark sponsored message as read.
     *
     * @param (int | array) $peer Channel ID, or Update, or Message, or Peer.
     * @param (string | array{random_id: string}) $message Random ID or sponsored message to mark as read.
     *
     * @return \Amp\Promise Bool
     */
    public function viewSponsoredMessage($peer, $message, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$peer, $message, $extra]);
    }
    /**
     * Synchronously wait for a promise|generator.
     *
     * @param (\Generator | Promise) $promise The promise to wait for
     * @param boolean $ignoreSignal Whether to ignore shutdown signals
     *
     * @return mixed
     */
    public function wait($promise, $ignoreSignal = false)
    {
        return \danog\MadelineProto\Tools::wait($promise, $ignoreSignal);
    }
}///////////////////////////////
/////////////////// Layer cons
///////////////////////////////

//invokeAfterMsg#cb9f372d msg_id:long query:!X = X;
//invokeAfterMsgs#3dc4b4f0 msg_ids:Vector<long> query:!X = X;
//invokeWithLayer1#53835315 query:!X = X;
//invokeWithLayer2#289dd1f6 query:!X = X;
//invokeWithLayer3#b7475268 query:!X = X;
//invokeWithLayer4#dea0d430 query:!X = X;
//invokeWithLayer5#417a57ae query:!X = X;
//invokeWithLayer6#3a64d54d query:!X = X;
//invokeWithLayer7#a5be56d3 query:!X = X;
//invokeWithLayer8#e9abd9fd query:!X = X;
//invokeWithLayer9#76715a63 query:!X = X;
//invokeWithLayer10#39620c41 query:!X = X;
//invokeWithLayer11#a6b88fdf query:!X = X;
//invokeWithLayer12#dda60d3c query:!X = X;
//invokeWithLayer13#427c8ea2 query:!X = X;
//invokeWithLayer14#2b9b08fa query:!X = X;
//invokeWithLayer15#b4418b64 query:!X = X;
//invokeWithLayer16#cf5f0987 query:!X = X;
//invokeWithLayer17#50858a19 query:!X = X;
//invokeWithLayer18#1c900537 query:!X = X;
//invokeWithLayer#da9b0d0d layer:int query:!X = X; // after 18 layer

///////////////////////////////
///////// Main application API
///////////////////////////////

boolFalse#bc799737 = Bool;
boolTrue#997275b5 = Bool;

true#3fedd339 = True;

vector#1cb5c415 {t:Type} # [ t ] = Vector t;

error#c4b9f9bb code:int text:string = Error;

null#56730bcc = Null;

inputPeerEmpty#7f3b18ea = InputPeer;
inputPeerSelf#7da07ec9 = InputPeer;
inputPeerChat#35a95cb9 chat_id:long = InputPeer;
inputPeerUser#dde8a54c user_id:long access_hash:long = InputPeer;
inputPeerChannel#27bcbbfc channel_id:long access_hash:long = InputPeer;
inputPeerUserFromMessage#a87b0a1c peer:InputPeer msg_id:int user_id:long = InputPeer;
inputPeerChannelFromMessage#bd2a0840 peer:InputPeer msg_id:int channel_id:long = InputPeer;

inputUserEmpty#b98886cf = InputUser;
inputUserSelf#f7c1b13f = InputUser;
inputUser#f21158c6 user_id:long access_hash:long = InputUser;
inputUserFromMessage#1da448e2 peer:InputPeer msg_id:int user_id:long = InputUser;

inputPhoneContact#f392b7f4 client_id:long phone:string first_name:string last_name:string = InputContact;

inputFile#f52ff27f id:long parts:int name:string md5_checksum:string = InputFile;
inputFileBig#fa4f0bb5 id:long parts:int name:string = InputFile;

inputMediaEmpty#9664f57f = InputMedia;
inputMediaUploadedPhoto#1e287d04 flags:# file:InputFile stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaPhoto#b3ba0635 flags:# id:InputPhoto ttl_seconds:flags.0?int = InputMedia;
inputMediaGeoPoint#f9c44144 geo_point:InputGeoPoint = InputMedia;
inputMediaContact#f8ab7dfb phone_number:string first_name:string last_name:string vcard:string = InputMedia;
inputMediaUploadedDocument#5b38c6c1 flags:# nosound_video:flags.3?true force_file:flags.4?true file:InputFile thumb:flags.2?InputFile mime_type:string attributes:Vector<DocumentAttribute> stickers:flags.0?Vector<InputDocument> ttl_seconds:flags.1?int = InputMedia;
inputMediaDocument#33473058 flags:# id:InputDocument ttl_seconds:flags.0?int query:flags.1?string = InputMedia;
inputMediaVenue#c13d1c11 geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string = InputMedia;
inputMediaPhotoExternal#e5bbfe1a flags:# url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaDocumentExternal#fb52dc99 flags:# url:string ttl_seconds:flags.0?int = InputMedia;
inputMediaGame#d33f43f3 id:InputGame = InputMedia;
inputMediaInvoice#d9799874 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON start_param:flags.1?string = InputMedia;
inputMediaGeoLive#971fa843 flags:# stopped:flags.0?true geo_point:InputGeoPoint heading:flags.2?int period:flags.1?int proximity_notification_radius:flags.3?int = InputMedia;
inputMediaPoll#f94e5f1 flags:# poll:Poll correct_answers:flags.0?Vector<bytes> solution:flags.1?string solution_entities:flags.1?Vector<MessageEntity> = InputMedia;
inputMediaDice#e66fbf7b emoticon:string = InputMedia;

inputChatPhotoEmpty#1ca48f57 = InputChatPhoto;
inputChatUploadedPhoto#c642724e flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = InputChatPhoto;
inputChatPhoto#8953ad37 id:InputPhoto = InputChatPhoto;

inputGeoPointEmpty#e4c123d6 = InputGeoPoint;
inputGeoPoint#48222faf flags:# lat:double long:double accuracy_radius:flags.0?int = InputGeoPoint;

inputPhotoEmpty#1cd7bf0d = InputPhoto;
inputPhoto#3bb3b94a id:long access_hash:long file_reference:bytes = InputPhoto;

inputFileLocation#dfdaabe1 volume_id:long local_id:int secret:long file_reference:bytes = InputFileLocation;
inputEncryptedFileLocation#f5235d55 id:long access_hash:long = InputFileLocation;
inputDocumentFileLocation#bad07584 id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
inputSecureFileLocation#cbc7ee28 id:long access_hash:long = InputFileLocation;
inputTakeoutFileLocation#29be5899 = InputFileLocation;
inputPhotoFileLocation#40181ffe id:long access_hash:long file_reference:bytes thumb_size:string = InputFileLocation;
inputPhotoLegacyFileLocation#d83466f3 id:long access_hash:long file_reference:bytes volume_id:long local_id:int secret:long = InputFileLocation;
inputPeerPhotoFileLocation#37257e99 flags:# big:flags.0?true peer:InputPeer photo_id:long = InputFileLocation;
inputStickerSetThumb#9d84f3db stickerset:InputStickerSet thumb_version:int = InputFileLocation;
inputGroupCallStream#598a92a flags:# call:InputGroupCall time_ms:long scale:int video_channel:flags.0?int video_quality:flags.0?int = InputFileLocation;

peerUser#59511722 user_id:long = Peer;
peerChat#36c6019a chat_id:long = Peer;
peerChannel#a2a5371e channel_id:long = Peer;

storage.fileUnknown#aa963b05 = storage.FileType;
storage.filePartial#40bc6f52 = storage.FileType;
storage.fileJpeg#7efe0e = storage.FileType;
storage.fileGif#cae1aadf = storage.FileType;
storage.filePng#a4f63c0 = storage.FileType;
storage.filePdf#ae1e508d = storage.FileType;
storage.fileMp3#528a0677 = storage.FileType;
storage.fileMov#4b09ebbc = storage.FileType;
storage.fileMp4#b3cea0e4 = storage.FileType;
storage.fileWebp#1081464c = storage.FileType;

userEmpty#d3bc4b7a id:long = User;
user#3ff6ecb0 flags:# self:flags.10?true contact:flags.11?true mutual_contact:flags.12?true deleted:flags.13?true bot:flags.14?true bot_chat_history:flags.15?true bot_nochats:flags.16?true verified:flags.17?true restricted:flags.18?true min:flags.20?true bot_inline_geo:flags.21?true support:flags.23?true scam:flags.24?true apply_min_photo:flags.25?true fake:flags.26?true id:long access_hash:flags.0?long first_name:flags.1?string last_name:flags.2?string username:flags.3?string phone:flags.4?string photo:flags.5?UserProfilePhoto status:flags.6?UserStatus bot_info_version:flags.14?int restriction_reason:flags.18?Vector<RestrictionReason> bot_inline_placeholder:flags.19?string lang_code:flags.22?string = User;

userProfilePhotoEmpty#4f11bae1 = UserProfilePhoto;
userProfilePhoto#82d1f706 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = UserProfilePhoto;

userStatusEmpty#9d05049 = UserStatus;
userStatusOnline#edb93949 expires:int = UserStatus;
userStatusOffline#8c703f was_online:int = UserStatus;
userStatusRecently#e26f42f1 = UserStatus;
userStatusLastWeek#7bf09fc = UserStatus;
userStatusLastMonth#77ebc742 = UserStatus;

chatEmpty#29562865 id:long = Chat;
chat#41cbf256 flags:# creator:flags.0?true kicked:flags.1?true left:flags.2?true deactivated:flags.5?true call_active:flags.23?true call_not_empty:flags.24?true noforwards:flags.25?true id:long title:string photo:ChatPhoto participants_count:int date:int version:int migrated_to:flags.6?InputChannel admin_rights:flags.14?ChatAdminRights default_banned_rights:flags.18?ChatBannedRights = Chat;
chatForbidden#6592a1a7 id:long title:string = Chat;
channel#8261ac61 flags:# creator:flags.0?true left:flags.2?true broadcast:flags.5?true verified:flags.7?true megagroup:flags.8?true restricted:flags.9?true signatures:flags.11?true min:flags.12?true scam:flags.19?true has_link:flags.20?true has_geo:flags.21?true slowmode_enabled:flags.22?true call_active:flags.23?true call_not_empty:flags.24?true fake:flags.25?true gigagroup:flags.26?true noforwards:flags.27?true id:long access_hash:flags.13?long title:string username:flags.6?string photo:ChatPhoto date:int restriction_reason:flags.9?Vector<RestrictionReason> admin_rights:flags.14?ChatAdminRights banned_rights:flags.15?ChatBannedRights default_banned_rights:flags.18?ChatBannedRights participants_count:flags.17?int = Chat;
channelForbidden#17d493d5 flags:# broadcast:flags.5?true megagroup:flags.8?true id:long access_hash:long title:string until_date:flags.16?int = Chat;

chatFull#46a6ffb4 flags:# can_set_username:flags.7?true has_scheduled:flags.8?true id:long about:string participants:ChatParticipants chat_photo:flags.2?Photo notify_settings:PeerNotifySettings exported_invite:flags.13?ExportedChatInvite bot_info:flags.3?Vector<BotInfo> pinned_msg_id:flags.6?int folder_id:flags.11?int call:flags.12?InputGroupCall ttl_period:flags.14?int groupcall_default_join_as:flags.15?Peer theme_emoticon:flags.16?string requests_pending:flags.17?int recent_requesters:flags.17?Vector<long> = ChatFull;
channelFull#56662e2e flags:# can_view_participants:flags.3?true can_set_username:flags.6?true can_set_stickers:flags.7?true hidden_prehistory:flags.10?true can_set_location:flags.16?true has_scheduled:flags.19?true can_view_stats:flags.20?true blocked:flags.22?true id:long about:string participants_count:flags.0?int admins_count:flags.1?int kicked_count:flags.2?int banned_count:flags.2?int online_count:flags.13?int read_inbox_max_id:int read_outbox_max_id:int unread_count:int chat_photo:Photo notify_settings:PeerNotifySettings exported_invite:flags.23?ExportedChatInvite bot_info:Vector<BotInfo> migrated_from_chat_id:flags.4?long migrated_from_max_id:flags.4?int pinned_msg_id:flags.5?int stickerset:flags.8?StickerSet available_min_id:flags.9?int folder_id:flags.11?int linked_chat_id:flags.14?long location:flags.15?ChannelLocation slowmode_seconds:flags.17?int slowmode_next_send_date:flags.18?int stats_dc:flags.12?int pts:int call:flags.21?InputGroupCall ttl_period:flags.24?int pending_suggestions:flags.25?Vector<string> groupcall_default_join_as:flags.26?Peer theme_emoticon:flags.27?string requests_pending:flags.28?int recent_requesters:flags.28?Vector<long> default_send_as:flags.29?Peer = ChatFull;

chatParticipant#c02d4007 user_id:long inviter_id:long date:int = ChatParticipant;
chatParticipantCreator#e46bcee4 user_id:long = ChatParticipant;
chatParticipantAdmin#a0933f5b user_id:long inviter_id:long date:int = ChatParticipant;

chatParticipantsForbidden#8763d3e1 flags:# chat_id:long self_participant:flags.0?ChatParticipant = ChatParticipants;
chatParticipants#3cbc93f8 chat_id:long participants:Vector<ChatParticipant> version:int = ChatParticipants;

chatPhotoEmpty#37c1011c = ChatPhoto;
chatPhoto#1c6e1c11 flags:# has_video:flags.0?true photo_id:long stripped_thumb:flags.1?bytes dc_id:int = ChatPhoto;

messageEmpty#90a6ca84 flags:# id:int peer_id:flags.0?Peer = Message;
message#85d6cbe2 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true from_scheduled:flags.18?true legacy:flags.19?true edit_hide:flags.21?true pinned:flags.24?true noforwards:flags.26?true id:int from_id:flags.8?Peer peer_id:Peer fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader date:int message:string media:flags.9?MessageMedia reply_markup:flags.6?ReplyMarkup entities:flags.7?Vector<MessageEntity> views:flags.10?int forwards:flags.10?int replies:flags.23?MessageReplies edit_date:flags.15?int post_author:flags.16?string grouped_id:flags.17?long restriction_reason:flags.22?Vector<RestrictionReason> ttl_period:flags.25?int = Message;
messageService#2b085862 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true post:flags.14?true legacy:flags.19?true id:int from_id:flags.8?Peer peer_id:Peer reply_to:flags.3?MessageReplyHeader date:int action:MessageAction ttl_period:flags.25?int = Message;

messageMediaEmpty#3ded6320 = MessageMedia;
messageMediaPhoto#695150d7 flags:# photo:flags.0?Photo ttl_seconds:flags.2?int = MessageMedia;
messageMediaGeo#56e0d474 geo:GeoPoint = MessageMedia;
messageMediaContact#70322949 phone_number:string first_name:string last_name:string vcard:string user_id:long = MessageMedia;
messageMediaUnsupported#9f84f49e = MessageMedia;
messageMediaDocument#9cb070d7 flags:# document:flags.0?Document ttl_seconds:flags.2?int = MessageMedia;
messageMediaWebPage#a32dd600 webpage:WebPage = MessageMedia;
messageMediaVenue#2ec0533f geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string = MessageMedia;
messageMediaGame#fdb19008 game:Game = MessageMedia;
messageMediaInvoice#84551347 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument receipt_msg_id:flags.2?int currency:string total_amount:long start_param:string = MessageMedia;
messageMediaGeoLive#b940c666 flags:# geo:GeoPoint heading:flags.0?int period:int proximity_notification_radius:flags.1?int = MessageMedia;
messageMediaPoll#4bd6e798 poll:Poll results:PollResults = MessageMedia;
messageMediaDice#3f7ee58b value:int emoticon:string = MessageMedia;

messageActionEmpty#b6aef7b0 = MessageAction;
messageActionChatCreate#bd47cbad title:string users:Vector<long> = MessageAction;
messageActionChatEditTitle#b5a1ce5a title:string = MessageAction;
messageActionChatEditPhoto#7fcb13a8 photo:Photo = MessageAction;
messageActionChatDeletePhoto#95e3fbef = MessageAction;
messageActionChatAddUser#15cefd00 users:Vector<long> = MessageAction;
messageActionChatDeleteUser#a43f30cc user_id:long = MessageAction;
messageActionChatJoinedByLink#31224c3 inviter_id:long = MessageAction;
messageActionChannelCreate#95d2ac92 title:string = MessageAction;
messageActionChatMigrateTo#e1037f92 channel_id:long = MessageAction;
messageActionChannelMigrateFrom#ea3948e9 title:string chat_id:long = MessageAction;
messageActionPinMessage#94bd38ed = MessageAction;
messageActionHistoryClear#9fbab604 = MessageAction;
messageActionGameScore#92a72876 game_id:long score:int = MessageAction;
messageActionPaymentSentMe#8f31b327 flags:# currency:string total_amount:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string charge:PaymentCharge = MessageAction;
messageActionPaymentSent#40699cd0 currency:string total_amount:long = MessageAction;
messageActionPhoneCall#80e11a7f flags:# video:flags.2?true call_id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = MessageAction;
messageActionScreenshotTaken#4792929b = MessageAction;
messageActionCustomAction#fae69f56 message:string = MessageAction;
messageActionBotAllowed#abe9affe domain:string = MessageAction;
messageActionSecureValuesSentMe#1b287353 values:Vector<SecureValue> credentials:SecureCredentialsEncrypted = MessageAction;
messageActionSecureValuesSent#d95c6154 types:Vector<SecureValueType> = MessageAction;
messageActionContactSignUp#f3f25f76 = MessageAction;
messageActionGeoProximityReached#98e0d697 from_id:Peer to_id:Peer distance:int = MessageAction;
messageActionGroupCall#7a0d7f42 flags:# call:InputGroupCall duration:flags.0?int = MessageAction;
messageActionInviteToGroupCall#502f92f7 call:InputGroupCall users:Vector<long> = MessageAction;
messageActionSetMessagesTTL#aa1afbfd period:int = MessageAction;
messageActionGroupCallScheduled#b3a07661 call:InputGroupCall schedule_date:int = MessageAction;
messageActionSetChatTheme#aa786345 emoticon:string = MessageAction;
messageActionChatJoinedByRequest#ebbca3cb = MessageAction;

dialog#2c171f72 flags:# pinned:flags.2?true unread_mark:flags.3?true peer:Peer top_message:int read_inbox_max_id:int read_outbox_max_id:int unread_count:int unread_mentions_count:int notify_settings:PeerNotifySettings pts:flags.0?int draft:flags.1?DraftMessage folder_id:flags.4?int = Dialog;
dialogFolder#71bd134c flags:# pinned:flags.2?true folder:Folder peer:Peer top_message:int unread_muted_peers_count:int unread_unmuted_peers_count:int unread_muted_messages_count:int unread_unmuted_messages_count:int = Dialog;

photoEmpty#2331b22d id:long = Photo;
photo#fb197a65 flags:# has_stickers:flags.0?true id:long access_hash:long file_reference:bytes date:int sizes:Vector<PhotoSize> video_sizes:flags.1?Vector<VideoSize> dc_id:int = Photo;

photoSizeEmpty#e17e23c type:string = PhotoSize;
photoSize#75c78e60 type:string w:int h:int size:int = PhotoSize;
photoCachedSize#21e1ad6 type:string w:int h:int bytes:bytes = PhotoSize;
photoStrippedSize#e0b0bc2e type:string bytes:bytes = PhotoSize;
photoSizeProgressive#fa3efb95 type:string w:int h:int sizes:Vector<int> = PhotoSize;
photoPathSize#d8214d41 type:string bytes:bytes = PhotoSize;

geoPointEmpty#1117dd5f = GeoPoint;
geoPoint#b2a2f663 flags:# long:double lat:double access_hash:long accuracy_radius:flags.0?int = GeoPoint;

auth.sentCode#5e002502 flags:# type:auth.SentCodeType phone_code_hash:string next_type:flags.1?auth.CodeType timeout:flags.2?int = auth.SentCode;

auth.authorization#33fb7bb8 flags:# setup_password_required:flags.1?true otherwise_relogin_days:flags.1?int tmp_sessions:flags.0?int user:User = auth.Authorization;
auth.authorizationSignUpRequired#44747e9a flags:# terms_of_service:flags.0?help.TermsOfService = auth.Authorization;

auth.exportedAuthorization#b434e2b8 id:long bytes:bytes = auth.ExportedAuthorization;

inputNotifyPeer#b8bc5b0c peer:InputPeer = InputNotifyPeer;
inputNotifyUsers#193b4417 = InputNotifyPeer;
inputNotifyChats#4a95e84e = InputNotifyPeer;
inputNotifyBroadcasts#b1db7c7e = InputNotifyPeer;

inputPeerNotifySettings#9c3d198e flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = InputPeerNotifySettings;

peerNotifySettings#af509d20 flags:# show_previews:flags.0?Bool silent:flags.1?Bool mute_until:flags.2?int sound:flags.3?string = PeerNotifySettings;

peerSettings#a518110d flags:# report_spam:flags.0?true add_contact:flags.1?true block_contact:flags.2?true share_contact:flags.3?true need_contacts_exception:flags.4?true report_geo:flags.5?true autoarchived:flags.7?true invite_members:flags.8?true request_chat_broadcast:flags.10?true geo_distance:flags.6?int request_chat_title:flags.9?string request_chat_date:flags.9?int = PeerSettings;

wallPaper#a437c3ed id:long flags:# creator:flags.0?true default:flags.1?true pattern:flags.3?true dark:flags.4?true access_hash:long slug:string document:Document settings:flags.2?WallPaperSettings = WallPaper;
wallPaperNoFile#e0804116 id:long flags:# default:flags.1?true dark:flags.4?true settings:flags.2?WallPaperSettings = WallPaper;

inputReportReasonSpam#58dbcab8 = ReportReason;
inputReportReasonViolence#1e22c78d = ReportReason;
inputReportReasonPornography#2e59d922 = ReportReason;
inputReportReasonChildAbuse#adf44ee3 = ReportReason;
inputReportReasonOther#c1e4a2b1 = ReportReason;
inputReportReasonCopyright#9b89f93a = ReportReason;
inputReportReasonGeoIrrelevant#dbd4feed = ReportReason;
inputReportReasonFake#f5ddd6e7 = ReportReason;

userFull#cf366521 flags:# blocked:flags.0?true phone_calls_available:flags.4?true phone_calls_private:flags.5?true can_pin_message:flags.7?true has_scheduled:flags.12?true video_calls_available:flags.13?true id:long about:flags.1?string settings:PeerSettings profile_photo:flags.2?Photo notify_settings:PeerNotifySettings bot_info:flags.3?BotInfo pinned_msg_id:flags.6?int common_chats_count:int folder_id:flags.11?int ttl_period:flags.14?int theme_emoticon:flags.15?string private_forward_name:flags.16?string = UserFull;

contact#145ade0b user_id:long mutual:Bool = Contact;

importedContact#c13e3c50 user_id:long client_id:long = ImportedContact;

contactStatus#16d9703b user_id:long status:UserStatus = ContactStatus;

contacts.contactsNotModified#b74ba9d2 = contacts.Contacts;
contacts.contacts#eae87e42 contacts:Vector<Contact> saved_count:int users:Vector<User> = contacts.Contacts;

contacts.importedContacts#77d01c3b imported:Vector<ImportedContact> popular_invites:Vector<PopularContact> retry_contacts:Vector<long> users:Vector<User> = contacts.ImportedContacts;

contacts.blocked#ade1591 blocked:Vector<PeerBlocked> chats:Vector<Chat> users:Vector<User> = contacts.Blocked;
contacts.blockedSlice#e1664194 count:int blocked:Vector<PeerBlocked> chats:Vector<Chat> users:Vector<User> = contacts.Blocked;

messages.dialogs#15ba6c40 dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;
messages.dialogsSlice#71e094f3 count:int dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Dialogs;
messages.dialogsNotModified#f0e3e596 count:int = messages.Dialogs;

messages.messages#8c718e87 messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesSlice#3a54685e flags:# inexact:flags.1?true count:int next_rate:flags.0?int offset_id_offset:flags.2?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.channelMessages#64479808 flags:# inexact:flags.1?true pts:int count:int offset_id_offset:flags.2?int messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.Messages;
messages.messagesNotModified#74535f21 count:int = messages.Messages;

messages.chats#64ff9fd5 chats:Vector<Chat> = messages.Chats;
messages.chatsSlice#9cd81144 count:int chats:Vector<Chat> = messages.Chats;

messages.chatFull#e5d7d19c full_chat:ChatFull chats:Vector<Chat> users:Vector<User> = messages.ChatFull;

messages.affectedHistory#b45c69d1 pts:int pts_count:int offset:int = messages.AffectedHistory;

inputMessagesFilterEmpty#57e2f66c = MessagesFilter;
inputMessagesFilterPhotos#9609a51c = MessagesFilter;
inputMessagesFilterVideo#9fc00e65 = MessagesFilter;
inputMessagesFilterPhotoVideo#56e9f0e4 = MessagesFilter;
inputMessagesFilterDocument#9eddf188 = MessagesFilter;
inputMessagesFilterUrl#7ef0dd87 = MessagesFilter;
inputMessagesFilterGif#ffc86587 = MessagesFilter;
inputMessagesFilterVoice#50f5c392 = MessagesFilter;
inputMessagesFilterMusic#3751b49e = MessagesFilter;
inputMessagesFilterChatPhotos#3a20ecb8 = MessagesFilter;
inputMessagesFilterPhoneCalls#80c99768 flags:# missed:flags.0?true = MessagesFilter;
inputMessagesFilterRoundVoice#7a7c17a4 = MessagesFilter;
inputMessagesFilterRoundVideo#b549da53 = MessagesFilter;
inputMessagesFilterMyMentions#c1f8e69a = MessagesFilter;
inputMessagesFilterGeo#e7026d0d = MessagesFilter;
inputMessagesFilterContacts#e062db83 = MessagesFilter;
inputMessagesFilterPinned#1bb00451 = MessagesFilter;

updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;
updateDeleteMessages#a20db0e5 messages:Vector<int> pts:int pts_count:int = Update;
updateUserTyping#c01e857f user_id:long action:SendMessageAction = Update;
updateChatUserTyping#83487af0 chat_id:long from_id:Peer action:SendMessageAction = Update;
updateChatParticipants#7761198 participants:ChatParticipants = Update;
updateUserStatus#e5bdf8de user_id:long status:UserStatus = Update;
updateUserName#c3f202e0 user_id:long first_name:string last_name:string username:string = Update;
updateUserPhoto#f227868c user_id:long date:int photo:UserProfilePhoto previous:Bool = Update;
updateNewEncryptedMessage#12bcbd9a message:EncryptedMessage qts:int = Update;
updateEncryptedChatTyping#1710f156 chat_id:int = Update;
updateEncryption#b4a2e88d chat:EncryptedChat date:int = Update;
updateEncryptedMessagesRead#38fe25b7 chat_id:int max_date:int date:int = Update;
updateChatParticipantAdd#3dda5451 chat_id:long user_id:long inviter_id:long date:int version:int = Update;
updateChatParticipantDelete#e32f3d77 chat_id:long user_id:long version:int = Update;
updateDcOptions#8e5e9873 dc_options:Vector<DcOption> = Update;
updateNotifySettings#bec268ef peer:NotifyPeer notify_settings:PeerNotifySettings = Update;
updateServiceNotification#ebe46819 flags:# popup:flags.0?true inbox_date:flags.1?int type:string message:string media:MessageMedia entities:Vector<MessageEntity> = Update;
updatePrivacy#ee3b272a key:PrivacyKey rules:Vector<PrivacyRule> = Update;
updateUserPhone#5492a13 user_id:long phone:string = Update;
updateReadHistoryInbox#9c974fdf flags:# folder_id:flags.0?int peer:Peer max_id:int still_unread_count:int pts:int pts_count:int = Update;
updateReadHistoryOutbox#2f2f21bf peer:Peer max_id:int pts:int pts_count:int = Update;
updateWebPage#7f891213 webpage:WebPage pts:int pts_count:int = Update;
updateReadMessagesContents#68c13933 messages:Vector<int> pts:int pts_count:int = Update;
updateChannelTooLong#108d941f flags:# channel_id:long pts:flags.0?int = Update;
updateChannel#635b4c09 channel_id:long = Update;
updateNewChannelMessage#62ba04d9 message:Message pts:int pts_count:int = Update;
updateReadChannelInbox#922e6e10 flags:# folder_id:flags.0?int channel_id:long max_id:int still_unread_count:int pts:int = Update;
updateDeleteChannelMessages#c32d5b12 channel_id:long messages:Vector<int> pts:int pts_count:int = Update;
updateChannelMessageViews#f226ac08 channel_id:long id:int views:int = Update;
updateChatParticipantAdmin#d7ca61a2 chat_id:long user_id:long is_admin:Bool version:int = Update;
updateNewStickerSet#688a30aa stickerset:messages.StickerSet = Update;
updateStickerSetsOrder#bb2d201 flags:# masks:flags.0?true order:Vector<long> = Update;
updateStickerSets#43ae3dec = Update;
updateSavedGifs#9375341e = Update;
updateBotInlineQuery#496f379c flags:# query_id:long user_id:long query:string geo:flags.0?GeoPoint peer_type:flags.1?InlineQueryPeerType offset:string = Update;
updateBotInlineSend#12f12a07 flags:# user_id:long query:string geo:flags.0?GeoPoint id:string msg_id:flags.1?InputBotInlineMessageID = Update;
updateEditChannelMessage#1b3f4df7 message:Message pts:int pts_count:int = Update;
updateBotCallbackQuery#b9cfc48d flags:# query_id:long user_id:long peer:Peer msg_id:int chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update;
updateInlineBotCallbackQuery#691e9052 flags:# query_id:long user_id:long msg_id:InputBotInlineMessageID chat_instance:long data:flags.0?bytes game_short_name:flags.1?string = Update;
updateReadChannelOutbox#b75f99a9 channel_id:long max_id:int = Update;
updateDraftMessage#ee2bb969 peer:Peer draft:DraftMessage = Update;
updateReadFeaturedStickers#571d2742 = Update;
updateRecentStickers#9a422c20 = Update;
updateConfig#a229dd06 = Update;
updatePtsChanged#3354678f = Update;
updateChannelWebPage#2f2ba99f channel_id:long webpage:WebPage pts:int pts_count:int = Update;
updateDialogPinned#6e6fe51c flags:# pinned:flags.0?true folder_id:flags.1?int peer:DialogPeer = Update;
updatePinnedDialogs#fa0f3ca2 flags:# folder_id:flags.1?int order:flags.0?Vector<DialogPeer> = Update;
updateBotWebhookJSON#8317c0c3 data:DataJSON = Update;
updateBotWebhookJSONQuery#9b9240a6 query_id:long data:DataJSON timeout:int = Update;
updateBotShippingQuery#b5aefd7d query_id:long user_id:long payload:bytes shipping_address:PostAddress = Update;
updateBotPrecheckoutQuery#8caa9a96 flags:# query_id:long user_id:long payload:bytes info:flags.0?PaymentRequestedInfo shipping_option_id:flags.1?string currency:string total_amount:long = Update;
updatePhoneCall#ab0f6b1e phone_call:PhoneCall = Update;
updateLangPackTooLong#46560264 lang_code:string = Update;
updateLangPack#56022f4d difference:LangPackDifference = Update;
updateFavedStickers#e511996d = Update;
updateChannelReadMessagesContents#44bdd535 channel_id:long messages:Vector<int> = Update;
updateContactsReset#7084a7be = Update;
updateChannelAvailableMessages#b23fc698 channel_id:long available_min_id:int = Update;
updateDialogUnreadMark#e16459c3 flags:# unread:flags.0?true peer:DialogPeer = Update;
updateMessagePoll#aca1657b flags:# poll_id:long poll:flags.0?Poll results:PollResults = Update;
updateChatDefaultBannedRights#54c01850 peer:Peer default_banned_rights:ChatBannedRights version:int = Update;
updateFolderPeers#19360dc0 folder_peers:Vector<FolderPeer> pts:int pts_count:int = Update;
updatePeerSettings#6a7e7366 peer:Peer settings:PeerSettings = Update;
updatePeerLocated#b4afcfb0 peers:Vector<PeerLocated> = Update;
updateNewScheduledMessage#39a51dfb message:Message = Update;
updateDeleteScheduledMessages#90866cee peer:Peer messages:Vector<int> = Update;
updateTheme#8216fba3 theme:Theme = Update;
updateGeoLiveViewed#871fb939 peer:Peer msg_id:int = Update;
updateLoginToken#564fe691 = Update;
updateMessagePollVote#106395c9 poll_id:long user_id:long options:Vector<bytes> qts:int = Update;
updateDialogFilter#26ffde7d flags:# id:int filter:flags.0?DialogFilter = Update;
updateDialogFilterOrder#a5d72105 order:Vector<int> = Update;
updateDialogFilters#3504914f = Update;
updatePhoneCallSignalingData#2661bf09 phone_call_id:long data:bytes = Update;
updateChannelMessageForwards#d29a27f4 channel_id:long id:int forwards:int = Update;
updateReadChannelDiscussionInbox#d6b19546 flags:# channel_id:long top_msg_id:int read_max_id:int broadcast_id:flags.0?long broadcast_post:flags.0?int = Update;
updateReadChannelDiscussionOutbox#695c9e7c channel_id:long top_msg_id:int read_max_id:int = Update;
updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
updateChannelUserTyping#8c88c923 flags:# channel_id:long top_msg_id:flags.0?int from_id:Peer action:SendMessageAction = Update;
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
updatePinnedChannelMessages#5bb98608 flags:# pinned:flags.0?true channel_id:long messages:Vector<int> pts:int pts_count:int = Update;
updateChat#f89a6a4e chat_id:long = Update;
updateGroupCallParticipants#f2ebdb4e call:InputGroupCall participants:Vector<GroupCallParticipant> version:int = Update;
updateGroupCall#14b24500 chat_id:long call:GroupCall = Update;
updatePeerHistoryTTL#bb9bb9a5 flags:# peer:Peer ttl_period:flags.0?int = Update;
updateChatParticipant#d087663a flags:# chat_id:long date:int actor_id:long user_id:long prev_participant:flags.0?ChatParticipant new_participant:flags.1?ChatParticipant invite:flags.2?ExportedChatInvite qts:int = Update;
updateChannelParticipant#985d3abb flags:# channel_id:long date:int actor_id:long user_id:long prev_participant:flags.0?ChannelParticipant new_participant:flags.1?ChannelParticipant invite:flags.2?ExportedChatInvite qts:int = Update;
updateBotStopped#c4870a49 user_id:long date:int stopped:Bool qts:int = Update;
updateGroupCallConnection#b783982 flags:# presentation:flags.0?true params:DataJSON = Update;
updateBotCommands#4d712f2e peer:Peer bot_id:long commands:Vector<BotCommand> = Update;
updatePendingJoinRequests#7063c3db peer:Peer requests_pending:int recent_requesters:Vector<long> = Update;
updateBotChatInviteRequester#11dfa986 peer:Peer date:int user_id:long about:string invite:ExportedChatInvite qts:int = Update;

updates.state#a56c2a3e pts:int qts:int date:int seq:int unread_count:int = updates.State;

updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference;
updates.difference#f49ca0 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference;
updates.differenceSlice#a8fb1981 new_messages:Vector<Message> new_encrypted_messages:Vector<EncryptedMessage> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference;
updates.differenceTooLong#4afe8f6d pts:int = updates.Difference;

updatesTooLong#e317af7e = Updates;
updateShortMessage#313bc7f8 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true id:int user_id:long message:string pts:int pts_count:int date:int fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader entities:flags.7?Vector<MessageEntity> ttl_period:flags.25?int = Updates;
updateShortChatMessage#4d6deea5 flags:# out:flags.1?true mentioned:flags.4?true media_unread:flags.5?true silent:flags.13?true id:int from_id:long chat_id:long message:string pts:int pts_count:int date:int fwd_from:flags.2?MessageFwdHeader via_bot_id:flags.11?long reply_to:flags.3?MessageReplyHeader entities:flags.7?Vector<MessageEntity> ttl_period:flags.25?int = Updates;
updateShort#78d4dec1 update:Update date:int = Updates;
updatesCombined#725b04c3 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq_start:int seq:int = Updates;
updates#74ae4240 updates:Vector<Update> users:Vector<User> chats:Vector<Chat> date:int seq:int = Updates;
updateShortSentMessage#9015e101 flags:# out:flags.1?true id:int pts:int pts_count:int date:int media:flags.9?MessageMedia entities:flags.7?Vector<MessageEntity> ttl_period:flags.25?int = Updates;

photos.photos#8dca6aa5 photos:Vector<Photo> users:Vector<User> = photos.Photos;
photos.photosSlice#15051f54 count:int photos:Vector<Photo> users:Vector<User> = photos.Photos;

photos.photo#20212ca8 photo:Photo users:Vector<User> = photos.Photo;

upload.file#96a18d5 type:storage.FileType mtime:int bytes:bytes = upload.File;
upload.fileCdnRedirect#f18cda44 dc_id:int file_token:bytes encryption_key:bytes encryption_iv:bytes file_hashes:Vector<FileHash> = upload.File;

dcOption#18b7a10d flags:# ipv6:flags.0?true media_only:flags.1?true tcpo_only:flags.2?true cdn:flags.3?true static:flags.4?true id:int ip_address:string port:int secret:flags.10?bytes = DcOption;

config#330b4067 flags:# phonecalls_enabled:flags.1?true default_p2p_contacts:flags.3?true preload_featured_stickers:flags.4?true ignore_phone_entities:flags.5?true revoke_pm_inbox:flags.6?true blocked_mode:flags.8?true pfs_enabled:flags.13?true date:int expires:int test_mode:Bool this_dc:int dc_options:Vector<DcOption> dc_txt_domain_name:string chat_size_max:int megagroup_size_max:int forwarded_count_max:int online_update_period_ms:int offline_blur_timeout_ms:int offline_idle_timeout_ms:int online_cloud_timeout_ms:int notify_cloud_delay_ms:int notify_default_delay_ms:int push_chat_period_ms:int push_chat_limit:int saved_gifs_limit:int edit_time_limit:int revoke_time_limit:int revoke_pm_time_limit:int rating_e_decay:int stickers_recent_limit:int stickers_faved_limit:int channels_read_media_period:int tmp_sessions:flags.0?int pinned_dialogs_count_max:int pinned_infolder_count_max:int call_receive_timeout_ms:int call_ring_timeout_ms:int call_connect_timeout_ms:int call_packet_timeout_ms:int me_url_prefix:string autoupdate_url_prefix:flags.7?string gif_search_username:flags.9?string venue_search_username:flags.10?string img_search_username:flags.11?string static_maps_provider:flags.12?string caption_length_max:int message_length_max:int webfile_dc_id:int suggested_lang_code:flags.2?string lang_pack_version:flags.2?int base_lang_pack_version:flags.2?int = Config;

nearestDc#8e1a1775 country:string this_dc:int nearest_dc:int = NearestDc;

help.appUpdate#ccbbce30 flags:# can_not_skip:flags.0?true id:int version:string text:string entities:Vector<MessageEntity> document:flags.1?Document url:flags.2?string sticker:flags.3?Document = help.AppUpdate;
help.noAppUpdate#c45a6536 = help.AppUpdate;

help.inviteText#18cb9f78 message:string = help.InviteText;

encryptedChatEmpty#ab7ec0a0 id:int = EncryptedChat;
encryptedChatWaiting#66b25953 id:int access_hash:long date:int admin_id:long participant_id:long = EncryptedChat;
encryptedChatRequested#48f1d94c flags:# folder_id:flags.0?int id:int access_hash:long date:int admin_id:long participant_id:long g_a:bytes = EncryptedChat;
encryptedChat#61f0d4c7 id:int access_hash:long date:int admin_id:long participant_id:long g_a_or_b:bytes key_fingerprint:long = EncryptedChat;
encryptedChatDiscarded#1e1c7c45 flags:# history_deleted:flags.0?true id:int = EncryptedChat;

inputEncryptedChat#f141b5e1 chat_id:int access_hash:long = InputEncryptedChat;

encryptedFileEmpty#c21f497e = EncryptedFile;
encryptedFile#4a70994c id:long access_hash:long size:int dc_id:int key_fingerprint:int = EncryptedFile;

inputEncryptedFileEmpty#1837c364 = InputEncryptedFile;
inputEncryptedFileUploaded#64bd0306 id:long parts:int md5_checksum:string key_fingerprint:int = InputEncryptedFile;
inputEncryptedFile#5a17b5e5 id:long access_hash:long = InputEncryptedFile;
inputEncryptedFileBigUploaded#2dc173c8 id:long parts:int key_fingerprint:int = InputEncryptedFile;

encryptedMessage#ed18c118 random_id:long chat_id:int date:int bytes:bytes file:EncryptedFile = EncryptedMessage;
encryptedMessageService#23734b06 random_id:long chat_id:int date:int bytes:bytes = EncryptedMessage;

messages.dhConfigNotModified#c0e24635 random:bytes = messages.DhConfig;
messages.dhConfig#2c221edd g:int p:bytes version:int random:bytes = messages.DhConfig;

messages.sentEncryptedMessage#560f8935 date:int = messages.SentEncryptedMessage;
messages.sentEncryptedFile#9493ff32 date:int file:EncryptedFile = messages.SentEncryptedMessage;

inputDocumentEmpty#72f0eaae = InputDocument;
inputDocument#1abfb575 id:long access_hash:long file_reference:bytes = InputDocument;

documentEmpty#36f8c871 id:long = Document;
document#1e87342b flags:# id:long access_hash:long file_reference:bytes date:int mime_type:string size:int thumbs:flags.0?Vector<PhotoSize> video_thumbs:flags.1?Vector<VideoSize> dc_id:int attributes:Vector<DocumentAttribute> = Document;

help.support#17c6b5f6 phone_number:string user:User = help.Support;

notifyPeer#9fd40bd8 peer:Peer = NotifyPeer;
notifyUsers#b4c83b4c = NotifyPeer;
notifyChats#c007cec3 = NotifyPeer;
notifyBroadcasts#d612e8ef = NotifyPeer;

sendMessageTypingAction#16bf744e = SendMessageAction;
sendMessageCancelAction#fd5ec8f5 = SendMessageAction;
sendMessageRecordVideoAction#a187d66f = SendMessageAction;
sendMessageUploadVideoAction#e9763aec progress:int = SendMessageAction;
sendMessageRecordAudioAction#d52f73f7 = SendMessageAction;
sendMessageUploadAudioAction#f351d7ab progress:int = SendMessageAction;
sendMessageUploadPhotoAction#d1d34a26 progress:int = SendMessageAction;
sendMessageUploadDocumentAction#aa0cd9e4 progress:int = SendMessageAction;
sendMessageGeoLocationAction#176f8ba1 = SendMessageAction;
sendMessageChooseContactAction#628cbc6f = SendMessageAction;
sendMessageGamePlayAction#dd6a8f48 = SendMessageAction;
sendMessageRecordRoundAction#88f27fbc = SendMessageAction;
sendMessageUploadRoundAction#243e1c66 progress:int = SendMessageAction;
speakingInGroupCallAction#d92c2285 = SendMessageAction;
sendMessageHistoryImportAction#dbda9246 progress:int = SendMessageAction;
sendMessageChooseStickerAction#b05ac6b1 = SendMessageAction;
sendMessageEmojiInteraction#25972bcb emoticon:string msg_id:int interaction:DataJSON = SendMessageAction;
sendMessageEmojiInteractionSeen#b665902e emoticon:string = SendMessageAction;

contacts.found#b3134d9d my_results:Vector<Peer> results:Vector<Peer> chats:Vector<Chat> users:Vector<User> = contacts.Found;

inputPrivacyKeyStatusTimestamp#4f96cb18 = InputPrivacyKey;
inputPrivacyKeyChatInvite#bdfb0426 = InputPrivacyKey;
inputPrivacyKeyPhoneCall#fabadc5f = InputPrivacyKey;
inputPrivacyKeyPhoneP2P#db9e70d2 = InputPrivacyKey;
inputPrivacyKeyForwards#a4dd4c08 = InputPrivacyKey;
inputPrivacyKeyProfilePhoto#5719bacc = InputPrivacyKey;
inputPrivacyKeyPhoneNumber#352dafa = InputPrivacyKey;
inputPrivacyKeyAddedByPhone#d1219bdd = InputPrivacyKey;

privacyKeyStatusTimestamp#bc2eab30 = PrivacyKey;
privacyKeyChatInvite#500e6dfa = PrivacyKey;
privacyKeyPhoneCall#3d662b7b = PrivacyKey;
privacyKeyPhoneP2P#39491cc8 = PrivacyKey;
privacyKeyForwards#69ec56a3 = PrivacyKey;
privacyKeyProfilePhoto#96151fed = PrivacyKey;
privacyKeyPhoneNumber#d19ae46d = PrivacyKey;
privacyKeyAddedByPhone#42ffd42b = PrivacyKey;

inputPrivacyValueAllowContacts#d09e07b = InputPrivacyRule;
inputPrivacyValueAllowAll#184b35ce = InputPrivacyRule;
inputPrivacyValueAllowUsers#131cc67f users:Vector<InputUser> = InputPrivacyRule;
inputPrivacyValueDisallowContacts#ba52007 = InputPrivacyRule;
inputPrivacyValueDisallowAll#d66b66c9 = InputPrivacyRule;
inputPrivacyValueDisallowUsers#90110467 users:Vector<InputUser> = InputPrivacyRule;
inputPrivacyValueAllowChatParticipants#840649cf chats:Vector<long> = InputPrivacyRule;
inputPrivacyValueDisallowChatParticipants#e94f0f86 chats:Vector<long> = InputPrivacyRule;

privacyValueAllowContacts#fffe1bac = PrivacyRule;
privacyValueAllowAll#65427b82 = PrivacyRule;
privacyValueAllowUsers#b8905fb2 users:Vector<long> = PrivacyRule;
privacyValueDisallowContacts#f888fa1a = PrivacyRule;
privacyValueDisallowAll#8b73e763 = PrivacyRule;
privacyValueDisallowUsers#e4621141 users:Vector<long> = PrivacyRule;
privacyValueAllowChatParticipants#6b134e8e chats:Vector<long> = PrivacyRule;
privacyValueDisallowChatParticipants#41c87565 chats:Vector<long> = PrivacyRule;

account.privacyRules#50a04e45 rules:Vector<PrivacyRule> chats:Vector<Chat> users:Vector<User> = account.PrivacyRules;

accountDaysTTL#b8d0afdf days:int = AccountDaysTTL;

documentAttributeImageSize#6c37c15c w:int h:int = DocumentAttribute;
documentAttributeAnimated#11b58939 = DocumentAttribute;
documentAttributeSticker#6319d612 flags:# mask:flags.1?true alt:string stickerset:InputStickerSet mask_coords:flags.0?MaskCoords = DocumentAttribute;
documentAttributeVideo#ef02ce6 flags:# round_message:flags.0?true supports_streaming:flags.1?true duration:int w:int h:int = DocumentAttribute;
documentAttributeAudio#9852f9c6 flags:# voice:flags.10?true duration:int title:flags.0?string performer:flags.1?string waveform:flags.2?bytes = DocumentAttribute;
documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
documentAttributeHasStickers#9801d2f7 = DocumentAttribute;

messages.stickersNotModified#f1749a22 = messages.Stickers;
messages.stickers#30a6ec7e hash:long stickers:Vector<Document> = messages.Stickers;

stickerPack#12b299d4 emoticon:string documents:Vector<long> = StickerPack;

messages.allStickersNotModified#e86602c3 = messages.AllStickers;
messages.allStickers#cdbbcebb hash:long sets:Vector<StickerSet> = messages.AllStickers;

messages.affectedMessages#84d19185 pts:int pts_count:int = messages.AffectedMessages;

webPageEmpty#eb1477e8 id:long = WebPage;
webPagePending#c586da1c id:long date:int = WebPage;
webPage#e89c45b2 flags:# id:long url:string display_url:string hash:int type:flags.0?string site_name:flags.1?string title:flags.2?string description:flags.3?string photo:flags.4?Photo embed_url:flags.5?string embed_type:flags.5?string embed_width:flags.6?int embed_height:flags.6?int duration:flags.7?int author:flags.8?string document:flags.9?Document cached_page:flags.10?Page attributes:flags.12?Vector<WebPageAttribute> = WebPage;
webPageNotModified#7311ca11 flags:# cached_page_views:flags.0?int = WebPage;

authorization#ad01d61d flags:# current:flags.0?true official_app:flags.1?true password_pending:flags.2?true encrypted_requests_disabled:flags.3?true call_requests_disabled:flags.4?true hash:long device_model:string platform:string system_version:string api_id:int app_name:string app_version:string date_created:int date_active:int ip:string country:string region:string = Authorization;

account.authorizations#4bff8ea0 authorization_ttl_days:int authorizations:Vector<Authorization> = account.Authorizations;

account.password#185b184f flags:# has_recovery:flags.0?true has_secure_values:flags.1?true has_password:flags.2?true current_algo:flags.2?PasswordKdfAlgo srp_B:flags.2?bytes srp_id:flags.2?long hint:flags.3?string email_unconfirmed_pattern:flags.4?string new_algo:PasswordKdfAlgo new_secure_algo:SecurePasswordKdfAlgo secure_random:bytes pending_reset_date:flags.5?int = account.Password;

account.passwordSettings#9a5c33e5 flags:# email:flags.0?string secure_settings:flags.1?SecureSecretSettings = account.PasswordSettings;

account.passwordInputSettings#c23727c9 flags:# new_algo:flags.0?PasswordKdfAlgo new_password_hash:flags.0?bytes hint:flags.0?string email:flags.1?string new_secure_settings:flags.2?SecureSecretSettings = account.PasswordInputSettings;

auth.passwordRecovery#137948a5 email_pattern:string = auth.PasswordRecovery;

receivedNotifyMessage#a384b779 id:int flags:int = ReceivedNotifyMessage;

chatInviteExported#ab4a819 flags:# revoked:flags.0?true permanent:flags.5?true request_needed:flags.6?true link:string admin_id:long date:int start_date:flags.4?int expire_date:flags.1?int usage_limit:flags.2?int usage:flags.3?int requested:flags.7?int title:flags.8?string = ExportedChatInvite;

chatInviteAlready#5a686d7c chat:Chat = ChatInvite;
chatInvite#300c44c1 flags:# channel:flags.0?true broadcast:flags.1?true public:flags.2?true megagroup:flags.3?true request_needed:flags.6?true title:string about:flags.5?string photo:Photo participants_count:int participants:flags.4?Vector<User> = ChatInvite;
chatInvitePeek#61695cb0 chat:Chat expires:int = ChatInvite;

inputStickerSetEmpty#ffb62b95 = InputStickerSet;
inputStickerSetID#9de7a269 id:long access_hash:long = InputStickerSet;
inputStickerSetShortName#861cc8a0 short_name:string = InputStickerSet;
inputStickerSetAnimatedEmoji#28703c8 = InputStickerSet;
inputStickerSetDice#e67f520e emoticon:string = InputStickerSet;
inputStickerSetAnimatedEmojiAnimations#cde3739 = InputStickerSet;

stickerSet#d7df217a flags:# archived:flags.1?true official:flags.2?true masks:flags.3?true animated:flags.5?true installed_date:flags.0?int id:long access_hash:long title:string short_name:string thumbs:flags.4?Vector<PhotoSize> thumb_dc_id:flags.4?int thumb_version:flags.4?int count:int hash:int = StickerSet;

messages.stickerSet#b60a24a6 set:StickerSet packs:Vector<StickerPack> documents:Vector<Document> = messages.StickerSet;
messages.stickerSetNotModified#d3f924eb = messages.StickerSet;

botCommand#c27ac8c7 command:string description:string = BotCommand;

botInfo#1b74b335 user_id:long description:string commands:Vector<BotCommand> = BotInfo;

keyboardButton#a2fa4880 text:string = KeyboardButton;
keyboardButtonUrl#258aff05 text:string url:string = KeyboardButton;
keyboardButtonCallback#35bbdb6b flags:# requires_password:flags.0?true text:string data:bytes = KeyboardButton;
keyboardButtonRequestPhone#b16a6c29 text:string = KeyboardButton;
keyboardButtonRequestGeoLocation#fc796b3f text:string = KeyboardButton;
keyboardButtonSwitchInline#568a748 flags:# same_peer:flags.0?true text:string query:string = KeyboardButton;
keyboardButtonGame#50f41ccf text:string = KeyboardButton;
keyboardButtonBuy#afd93fbb text:string = KeyboardButton;
keyboardButtonUrlAuth#10b78d29 flags:# text:string fwd_text:flags.0?string url:string button_id:int = KeyboardButton;
inputKeyboardButtonUrlAuth#d02e7fd4 flags:# request_write_access:flags.0?true text:string fwd_text:flags.1?string url:string bot:InputUser = KeyboardButton;
keyboardButtonRequestPoll#bbc7515d flags:# quiz:flags.0?Bool text:string = KeyboardButton;
inputKeyboardButtonUserProfile#e988037b text:string user_id:InputUser = KeyboardButton;
keyboardButtonUserProfile#308660c1 text:string user_id:long = KeyboardButton;

keyboardButtonRow#77608b83 buttons:Vector<KeyboardButton> = KeyboardButtonRow;

replyKeyboardHide#a03e5b85 flags:# selective:flags.2?true = ReplyMarkup;
replyKeyboardForceReply#86b40b08 flags:# single_use:flags.1?true selective:flags.2?true placeholder:flags.3?string = ReplyMarkup;
replyKeyboardMarkup#85dd99d1 flags:# resize:flags.0?true single_use:flags.1?true selective:flags.2?true rows:Vector<KeyboardButtonRow> placeholder:flags.3?string = ReplyMarkup;
replyInlineMarkup#48a30254 rows:Vector<KeyboardButtonRow> = ReplyMarkup;

messageEntityUnknown#bb92ba95 offset:int length:int = MessageEntity;
messageEntityMention#fa04579d offset:int length:int = MessageEntity;
messageEntityHashtag#6f635b0d offset:int length:int = MessageEntity;
messageEntityBotCommand#6cef8ac7 offset:int length:int = MessageEntity;
messageEntityUrl#6ed02538 offset:int length:int = MessageEntity;
messageEntityEmail#64e475c2 offset:int length:int = MessageEntity;
messageEntityBold#bd610bc9 offset:int length:int = MessageEntity;
messageEntityItalic#826f8b60 offset:int length:int = MessageEntity;
messageEntityCode#28a20571 offset:int length:int = MessageEntity;
messageEntityPre#73924be0 offset:int length:int language:string = MessageEntity;
messageEntityTextUrl#76a6d327 offset:int length:int url:string = MessageEntity;
messageEntityMentionName#dc7b1140 offset:int length:int user_id:long = MessageEntity;
inputMessageEntityMentionName#208e68c9 offset:int length:int user_id:InputUser = MessageEntity;
messageEntityPhone#9b69e34b offset:int length:int = MessageEntity;
messageEntityCashtag#4c4e743f offset:int length:int = MessageEntity;
messageEntityUnderline#9c4e7e8b offset:int length:int = MessageEntity;
messageEntityStrike#bf0693d4 offset:int length:int = MessageEntity;
messageEntityBlockquote#20df5d0 offset:int length:int = MessageEntity;
messageEntityBankCard#761e6af4 offset:int length:int = MessageEntity;

inputChannelEmpty#ee8c1e86 = InputChannel;
inputChannel#f35aec28 channel_id:long access_hash:long = InputChannel;
inputChannelFromMessage#5b934f9d peer:InputPeer msg_id:int channel_id:long = InputChannel;

contacts.resolvedPeer#7f077ad9 peer:Peer chats:Vector<Chat> users:Vector<User> = contacts.ResolvedPeer;

messageRange#ae30253 min_id:int max_id:int = MessageRange;

updates.channelDifferenceEmpty#3e11affb flags:# final:flags.0?true pts:int timeout:flags.1?int = updates.ChannelDifference;
updates.channelDifferenceTooLong#a4bcc6fe flags:# final:flags.0?true timeout:flags.1?int dialog:Dialog messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;
updates.channelDifference#2064674e flags:# final:flags.0?true pts:int timeout:flags.1?int new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> = updates.ChannelDifference;

channelMessagesFilterEmpty#94d42ee7 = ChannelMessagesFilter;
channelMessagesFilter#cd77d957 flags:# exclude_new_messages:flags.1?true ranges:Vector<MessageRange> = ChannelMessagesFilter;

channelParticipant#c00c07c0 user_id:long date:int = ChannelParticipant;
channelParticipantSelf#35a8bfa7 flags:# via_request:flags.0?true user_id:long inviter_id:long date:int = ChannelParticipant;
channelParticipantCreator#2fe601d3 flags:# user_id:long admin_rights:ChatAdminRights rank:flags.0?string = ChannelParticipant;
channelParticipantAdmin#34c3bb53 flags:# can_edit:flags.0?true self:flags.1?true user_id:long inviter_id:flags.1?long promoted_by:long date:int admin_rights:ChatAdminRights rank:flags.2?string = ChannelParticipant;
channelParticipantBanned#6df8014e flags:# left:flags.0?true peer:Peer kicked_by:long date:int banned_rights:ChatBannedRights = ChannelParticipant;
channelParticipantLeft#1b03f006 peer:Peer = ChannelParticipant;

channelParticipantsRecent#de3f3c79 = ChannelParticipantsFilter;
channelParticipantsAdmins#b4608969 = ChannelParticipantsFilter;
channelParticipantsKicked#a3b54985 q:string = ChannelParticipantsFilter;
channelParticipantsBots#b0d1865b = ChannelParticipantsFilter;
channelParticipantsBanned#1427a5e1 q:string = ChannelParticipantsFilter;
channelParticipantsSearch#656ac4b q:string = ChannelParticipantsFilter;
channelParticipantsContacts#bb6ae88d q:string = ChannelParticipantsFilter;
channelParticipantsMentions#e04b5ceb flags:# q:flags.0?string top_msg_id:flags.1?int = ChannelParticipantsFilter;

channels.channelParticipants#9ab0feaf count:int participants:Vector<ChannelParticipant> chats:Vector<Chat> users:Vector<User> = channels.ChannelParticipants;
channels.channelParticipantsNotModified#f0173fe9 = channels.ChannelParticipants;

channels.channelParticipant#dfb80317 participant:ChannelParticipant chats:Vector<Chat> users:Vector<User> = channels.ChannelParticipant;

help.termsOfService#780a0310 flags:# popup:flags.0?true id:DataJSON text:string entities:Vector<MessageEntity> min_age_confirm:flags.1?int = help.TermsOfService;

messages.savedGifsNotModified#e8025ca2 = messages.SavedGifs;
messages.savedGifs#84a02a0d hash:long gifs:Vector<Document> = messages.SavedGifs;

inputBotInlineMessageMediaAuto#3380c786 flags:# message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageText#3dcd7a87 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaGeo#96929a85 flags:# geo_point:InputGeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaVenue#417bbf11 flags:# geo_point:InputGeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaContact#a6edbffd flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageGame#4b425864 flags:# reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;
inputBotInlineMessageMediaInvoice#d7e78225 flags:# title:string description:string photo:flags.0?InputWebDocument invoice:Invoice payload:bytes provider:string provider_data:DataJSON reply_markup:flags.2?ReplyMarkup = InputBotInlineMessage;

inputBotInlineResult#88bf9319 flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?InputWebDocument content:flags.5?InputWebDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultPhoto#a8d864a7 id:string type:string photo:InputPhoto send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultDocument#fff8fdc4 flags:# id:string type:string title:flags.1?string description:flags.2?string document:InputDocument send_message:InputBotInlineMessage = InputBotInlineResult;
inputBotInlineResultGame#4fa417f2 id:string short_name:string send_message:InputBotInlineMessage = InputBotInlineResult;

botInlineMessageMediaAuto#764cf810 flags:# message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageText#8c7f65e2 flags:# no_webpage:flags.0?true message:string entities:flags.1?Vector<MessageEntity> reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaGeo#51846fd flags:# geo:GeoPoint heading:flags.0?int period:flags.1?int proximity_notification_radius:flags.3?int reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaVenue#8a86659c flags:# geo:GeoPoint title:string address:string provider:string venue_id:string venue_type:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaContact#18d1cdc2 flags:# phone_number:string first_name:string last_name:string vcard:string reply_markup:flags.2?ReplyMarkup = BotInlineMessage;
botInlineMessageMediaInvoice#354a9b09 flags:# shipping_address_requested:flags.1?true test:flags.3?true title:string description:string photo:flags.0?WebDocument currency:string total_amount:long reply_markup:flags.2?ReplyMarkup = BotInlineMessage;

botInlineResult#11965f3a flags:# id:string type:string title:flags.1?string description:flags.2?string url:flags.3?string thumb:flags.4?WebDocument content:flags.5?WebDocument send_message:BotInlineMessage = BotInlineResult;
botInlineMediaResult#17db940b flags:# id:string type:string photo:flags.0?Photo document:flags.1?Document title:flags.2?string description:flags.3?string send_message:BotInlineMessage = BotInlineResult;

messages.botResults#947ca848 flags:# gallery:flags.0?true query_id:long next_offset:flags.1?string switch_pm:flags.2?InlineBotSwitchPM results:Vector<BotInlineResult> cache_time:int users:Vector<User> = messages.BotResults;

exportedMessageLink#5dab1af4 link:string html:string = ExportedMessageLink;

messageFwdHeader#5f777dce flags:# imported:flags.7?true from_id:flags.0?Peer from_name:flags.5?string date:int channel_post:flags.2?int post_author:flags.3?string saved_from_peer:flags.4?Peer saved_from_msg_id:flags.4?int psa_type:flags.6?string = MessageFwdHeader;

auth.codeTypeSms#72a3158c = auth.CodeType;
auth.codeTypeCall#741cd3e3 = auth.CodeType;
auth.codeTypeFlashCall#226ccefb = auth.CodeType;
auth.codeTypeMissedCall#d61ad6ee = auth.CodeType;

auth.sentCodeTypeApp#3dbb5986 length:int = auth.SentCodeType;
auth.sentCodeTypeSms#c000bba2 length:int = auth.SentCodeType;
auth.sentCodeTypeCall#5353e5a7 length:int = auth.SentCodeType;
auth.sentCodeTypeFlashCall#ab03c6d9 pattern:string = auth.SentCodeType;
auth.sentCodeTypeMissedCall#82006484 prefix:string length:int = auth.SentCodeType;

messages.botCallbackAnswer#36585ea4 flags:# alert:flags.1?true has_url:flags.3?true native_ui:flags.4?true message:flags.0?string url:flags.2?string cache_time:int = messages.BotCallbackAnswer;

messages.messageEditData#26b5dde6 flags:# caption:flags.0?true = messages.MessageEditData;

inputBotInlineMessageID#890c3d89 dc_id:int id:long access_hash:long = InputBotInlineMessageID;
inputBotInlineMessageID64#b6d915d7 dc_id:int owner_id:long id:int access_hash:long = InputBotInlineMessageID;

inlineBotSwitchPM#3c20629f text:string start_param:string = InlineBotSwitchPM;

messages.peerDialogs#3371c354 dialogs:Vector<Dialog> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> state:updates.State = messages.PeerDialogs;

topPeer#edcdc05b peer:Peer rating:double = TopPeer;

topPeerCategoryBotsPM#ab661b5b = TopPeerCategory;
topPeerCategoryBotsInline#148677e2 = TopPeerCategory;
topPeerCategoryCorrespondents#637b7ed = TopPeerCategory;
topPeerCategoryGroups#bd17a14a = TopPeerCategory;
topPeerCategoryChannels#161d9628 = TopPeerCategory;
topPeerCategoryPhoneCalls#1e76a78c = TopPeerCategory;
topPeerCategoryForwardUsers#a8406ca9 = TopPeerCategory;
topPeerCategoryForwardChats#fbeec0f0 = TopPeerCategory;

topPeerCategoryPeers#fb834291 category:TopPeerCategory count:int peers:Vector<TopPeer> = TopPeerCategoryPeers;

contacts.topPeersNotModified#de266ef5 = contacts.TopPeers;
contacts.topPeers#70b772a8 categories:Vector<TopPeerCategoryPeers> chats:Vector<Chat> users:Vector<User> = contacts.TopPeers;
contacts.topPeersDisabled#b52c939d = contacts.TopPeers;

draftMessageEmpty#1b0c841a flags:# date:flags.0?int = DraftMessage;
draftMessage#fd8e711f flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int message:string entities:flags.3?Vector<MessageEntity> date:int = DraftMessage;

messages.featuredStickersNotModified#c6dc0c66 count:int = messages.FeaturedStickers;
messages.featuredStickers#84c02310 hash:long count:int sets:Vector<StickerSetCovered> unread:Vector<long> = messages.FeaturedStickers;

messages.recentStickersNotModified#b17f890 = messages.RecentStickers;
messages.recentStickers#88d37c56 hash:long packs:Vector<StickerPack> stickers:Vector<Document> dates:Vector<int> = messages.RecentStickers;

messages.archivedStickers#4fcba9c8 count:int sets:Vector<StickerSetCovered> = messages.ArchivedStickers;

messages.stickerSetInstallResultSuccess#38641628 = messages.StickerSetInstallResult;
messages.stickerSetInstallResultArchive#35e410a8 sets:Vector<StickerSetCovered> = messages.StickerSetInstallResult;

stickerSetCovered#6410a5d2 set:StickerSet cover:Document = StickerSetCovered;
stickerSetMultiCovered#3407e51b set:StickerSet covers:Vector<Document> = StickerSetCovered;

maskCoords#aed6dbb2 n:int x:double y:double zoom:double = MaskCoords;

inputStickeredMediaPhoto#4a992157 id:InputPhoto = InputStickeredMedia;
inputStickeredMediaDocument#438865b id:InputDocument = InputStickeredMedia;

game#bdf9653b flags:# id:long access_hash:long short_name:string title:string description:string photo:Photo document:flags.0?Document = Game;

inputGameID#32c3e77 id:long access_hash:long = InputGame;
inputGameShortName#c331e80a bot_id:InputUser short_name:string = InputGame;

highScore#73a379eb pos:int user_id:long score:int = HighScore;

messages.highScores#9a3bfd99 scores:Vector<HighScore> users:Vector<User> = messages.HighScores;

textEmpty#dc3d824f = RichText;
textPlain#744694e0 text:string = RichText;
textBold#6724abc4 text:RichText = RichText;
textItalic#d912a59c text:RichText = RichText;
textUnderline#c12622c4 text:RichText = RichText;
textStrike#9bf8bb95 text:RichText = RichText;
textFixed#6c3f19b9 text:RichText = RichText;
textUrl#3c2884c1 text:RichText url:string webpage_id:long = RichText;
textEmail#de5a0dd6 text:RichText email:string = RichText;
textConcat#7e6260d7 texts:Vector<RichText> = RichText;
textSubscript#ed6a8504 text:RichText = RichText;
textSuperscript#c7fb5e01 text:RichText = RichText;
textMarked#34b8621 text:RichText = RichText;
textPhone#1ccb966a text:RichText phone:string = RichText;
textImage#81ccf4f document_id:long w:int h:int = RichText;
textAnchor#35553762 text:RichText name:string = RichText;

pageBlockUnsupported#13567e8a = PageBlock;
pageBlockTitle#70abc3fd text:RichText = PageBlock;
pageBlockSubtitle#8ffa9a1f text:RichText = PageBlock;
pageBlockAuthorDate#baafe5e0 author:RichText published_date:int = PageBlock;
pageBlockHeader#bfd064ec text:RichText = PageBlock;
pageBlockSubheader#f12bb6e1 text:RichText = PageBlock;
pageBlockParagraph#467a0766 text:RichText = PageBlock;
pageBlockPreformatted#c070d93e text:RichText language:string = PageBlock;
pageBlockFooter#48870999 text:RichText = PageBlock;
pageBlockDivider#db20b188 = PageBlock;
pageBlockAnchor#ce0d37b0 name:string = PageBlock;
pageBlockList#e4e88011 items:Vector<PageListItem> = PageBlock;
pageBlockBlockquote#263d7c26 text:RichText caption:RichText = PageBlock;
pageBlockPullquote#4f4456d3 text:RichText caption:RichText = PageBlock;
pageBlockPhoto#1759c560 flags:# photo_id:long caption:PageCaption url:flags.0?string webpage_id:flags.0?long = PageBlock;
pageBlockVideo#7c8fe7b6 flags:# autoplay:flags.0?true loop:flags.1?true video_id:long caption:PageCaption = PageBlock;
pageBlockCover#39f23300 cover:PageBlock = PageBlock;
pageBlockEmbed#a8718dc5 flags:# full_width:flags.0?true allow_scrolling:flags.3?true url:flags.1?string html:flags.2?string poster_photo_id:flags.4?long w:flags.5?int h:flags.5?int caption:PageCaption = PageBlock;
pageBlockEmbedPost#f259a80b url:string webpage_id:long author_photo_id:long author:string date:int blocks:Vector<PageBlock> caption:PageCaption = PageBlock;
pageBlockCollage#65a0fa4d items:Vector<PageBlock> caption:PageCaption = PageBlock;
pageBlockSlideshow#31f9590 items:Vector<PageBlock> caption:PageCaption = PageBlock;
pageBlockChannel#ef1751b5 channel:Chat = PageBlock;
pageBlockAudio#804361ea audio_id:long caption:PageCaption = PageBlock;
pageBlockKicker#1e148390 text:RichText = PageBlock;
pageBlockTable#bf4dea82 flags:# bordered:flags.0?true striped:flags.1?true title:RichText rows:Vector<PageTableRow> = PageBlock;
pageBlockOrderedList#9a8ae1e1 items:Vector<PageListOrderedItem> = PageBlock;
pageBlockDetails#76768bed flags:# open:flags.0?true blocks:Vector<PageBlock> title:RichText = PageBlock;
pageBlockRelatedArticles#16115a96 title:RichText articles:Vector<PageRelatedArticle> = PageBlock;
pageBlockMap#a44f3ef6 geo:GeoPoint zoom:int w:int h:int caption:PageCaption = PageBlock;

phoneCallDiscardReasonMissed#85e42301 = PhoneCallDiscardReason;
phoneCallDiscardReasonDisconnect#e095c1a0 = PhoneCallDiscardReason;
phoneCallDiscardReasonHangup#57adc690 = PhoneCallDiscardReason;
phoneCallDiscardReasonBusy#faf7e8c9 = PhoneCallDiscardReason;

dataJSON#7d748d04 data:string = DataJSON;

labeledPrice#cb296bf8 label:string amount:long = LabeledPrice;

invoice#cd886e0 flags:# test:flags.0?true name_requested:flags.1?true phone_requested:flags.2?true email_requested:flags.3?true shipping_address_requested:flags.4?true flexible:flags.5?true phone_to_provider:flags.6?true email_to_provider:flags.7?true currency:string prices:Vector<LabeledPrice> max_tip_amount:flags.8?long suggested_tip_amounts:flags.8?Vector<long> = Invoice;

paymentCharge#ea02c27e id:string provider_charge_id:string = PaymentCharge;

postAddress#1e8caaeb street_line1:string street_line2:string city:string state:string country_iso2:string post_code:string = PostAddress;

paymentRequestedInfo#909c3f94 flags:# name:flags.0?string phone:flags.1?string email:flags.2?string shipping_address:flags.3?PostAddress = PaymentRequestedInfo;

paymentSavedCredentialsCard#cdc27a1f id:string title:string = PaymentSavedCredentials;

webDocument#1c570ed1 url:string access_hash:long size:int mime_type:string attributes:Vector<DocumentAttribute> = WebDocument;
webDocumentNoProxy#f9c8bcc6 url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = WebDocument;

inputWebDocument#9bed434d url:string size:int mime_type:string attributes:Vector<DocumentAttribute> = InputWebDocument;

inputWebFileLocation#c239d686 url:string access_hash:long = InputWebFileLocation;
inputWebFileGeoPointLocation#9f2221c9 geo_point:InputGeoPoint access_hash:long w:int h:int zoom:int scale:int = InputWebFileLocation;

upload.webFile#21e753bc size:int mime_type:string file_type:storage.FileType mtime:int bytes:bytes = upload.WebFile;

payments.paymentForm#1694761b flags:# can_save_credentials:flags.2?true password_missing:flags.3?true form_id:long bot_id:long invoice:Invoice provider_id:long url:string native_provider:flags.4?string native_params:flags.4?DataJSON saved_info:flags.0?PaymentRequestedInfo saved_credentials:flags.1?PaymentSavedCredentials users:Vector<User> = payments.PaymentForm;

payments.validatedRequestedInfo#d1451883 flags:# id:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = payments.ValidatedRequestedInfo;

payments.paymentResult#4e5f810d updates:Updates = payments.PaymentResult;
payments.paymentVerificationNeeded#d8411139 url:string = payments.PaymentResult;

payments.paymentReceipt#70c4fe03 flags:# date:int bot_id:long provider_id:long title:string description:string photo:flags.2?WebDocument invoice:Invoice info:flags.0?PaymentRequestedInfo shipping:flags.1?ShippingOption tip_amount:flags.3?long currency:string total_amount:long credentials_title:string users:Vector<User> = payments.PaymentReceipt;

payments.savedInfo#fb8fe43c flags:# has_saved_credentials:flags.1?true saved_info:flags.0?PaymentRequestedInfo = payments.SavedInfo;

inputPaymentCredentialsSaved#c10eb2cf id:string tmp_password:bytes = InputPaymentCredentials;
inputPaymentCredentials#3417d728 flags:# save:flags.0?true data:DataJSON = InputPaymentCredentials;
inputPaymentCredentialsApplePay#aa1c39f payment_data:DataJSON = InputPaymentCredentials;
inputPaymentCredentialsGooglePay#8ac32801 payment_token:DataJSON = InputPaymentCredentials;

account.tmpPassword#db64fd34 tmp_password:bytes valid_until:int = account.TmpPassword;

shippingOption#b6213cdf id:string title:string prices:Vector<LabeledPrice> = ShippingOption;

inputStickerSetItem#ffa0a496 flags:# document:InputDocument emoji:string mask_coords:flags.0?MaskCoords = InputStickerSetItem;

inputPhoneCall#1e36fded id:long access_hash:long = InputPhoneCall;

phoneCallEmpty#5366c915 id:long = PhoneCall;
phoneCallWaiting#c5226f17 flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long protocol:PhoneCallProtocol receive_date:flags.0?int = PhoneCall;
phoneCallRequested#14b0ed0c flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_a_hash:bytes protocol:PhoneCallProtocol = PhoneCall;
phoneCallAccepted#3660c311 flags:# video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_b:bytes protocol:PhoneCallProtocol = PhoneCall;
phoneCall#967f7c67 flags:# p2p_allowed:flags.5?true video:flags.6?true id:long access_hash:long date:int admin_id:long participant_id:long g_a_or_b:bytes key_fingerprint:long protocol:PhoneCallProtocol connections:Vector<PhoneConnection> start_date:int = PhoneCall;
phoneCallDiscarded#50ca4de1 flags:# need_rating:flags.2?true need_debug:flags.3?true video:flags.6?true id:long reason:flags.0?PhoneCallDiscardReason duration:flags.1?int = PhoneCall;

phoneConnection#9d4c17c0 id:long ip:string ipv6:string port:int peer_tag:bytes = PhoneConnection;
phoneConnectionWebrtc#635fe375 flags:# turn:flags.0?true stun:flags.1?true id:long ip:string ipv6:string port:int username:string password:string = PhoneConnection;

phoneCallProtocol#fc878fc8 flags:# udp_p2p:flags.0?true udp_reflector:flags.1?true min_layer:int max_layer:int library_versions:Vector<string> = PhoneCallProtocol;

phone.phoneCall#ec82e140 phone_call:PhoneCall users:Vector<User> = phone.PhoneCall;

upload.cdnFileReuploadNeeded#eea8e46e request_token:bytes = upload.CdnFile;
upload.cdnFile#a99fca4f bytes:bytes = upload.CdnFile;

cdnPublicKey#c982eaba dc_id:int public_key:string = CdnPublicKey;

cdnConfig#5725e40a public_keys:Vector<CdnPublicKey> = CdnConfig;

langPackString#cad181f6 key:string value:string = LangPackString;
langPackStringPluralized#6c47ac9f flags:# key:string zero_value:flags.0?string one_value:flags.1?string two_value:flags.2?string few_value:flags.3?string many_value:flags.4?string other_value:string = LangPackString;
langPackStringDeleted#2979eeb2 key:string = LangPackString;

langPackDifference#f385c1f6 lang_code:string from_version:int version:int strings:Vector<LangPackString> = LangPackDifference;

langPackLanguage#eeca5ce3 flags:# official:flags.0?true rtl:flags.2?true beta:flags.3?true name:string native_name:string lang_code:string base_lang_code:flags.1?string plural_code:string strings_count:int translated_count:int translations_url:string = LangPackLanguage;

channelAdminLogEventActionChangeTitle#e6dfb825 prev_value:string new_value:string = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeAbout#55188a2e prev_value:string new_value:string = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeUsername#6a4afc38 prev_value:string new_value:string = ChannelAdminLogEventAction;
channelAdminLogEventActionChangePhoto#434bd2af prev_photo:Photo new_photo:Photo = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleInvites#1b7907ae new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleSignatures#26ae0971 new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionUpdatePinned#e9e82c18 message:Message = ChannelAdminLogEventAction;
channelAdminLogEventActionEditMessage#709b2405 prev_message:Message new_message:Message = ChannelAdminLogEventAction;
channelAdminLogEventActionDeleteMessage#42e047bb message:Message = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantJoin#183040d3 = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantLeave#f89777f2 = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantInvite#e31c34d8 participant:ChannelParticipant = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantToggleBan#e6d83d7e prev_participant:ChannelParticipant new_participant:ChannelParticipant = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantToggleAdmin#d5676710 prev_participant:ChannelParticipant new_participant:ChannelParticipant = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeStickerSet#b1c3caa7 prev_stickerset:InputStickerSet new_stickerset:InputStickerSet = ChannelAdminLogEventAction;
channelAdminLogEventActionTogglePreHistoryHidden#5f5c95f1 new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionDefaultBannedRights#2df5fc0a prev_banned_rights:ChatBannedRights new_banned_rights:ChatBannedRights = ChannelAdminLogEventAction;
channelAdminLogEventActionStopPoll#8f079643 message:Message = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeLinkedChat#50c7ac8 prev_value:long new_value:long = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeLocation#e6b76ae prev_value:ChannelLocation new_value:ChannelLocation = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleSlowMode#53909779 prev_value:int new_value:int = ChannelAdminLogEventAction;
channelAdminLogEventActionStartGroupCall#23209745 call:InputGroupCall = ChannelAdminLogEventAction;
channelAdminLogEventActionDiscardGroupCall#db9f9140 call:InputGroupCall = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantMute#f92424d2 participant:GroupCallParticipant = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantUnmute#e64429c0 participant:GroupCallParticipant = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleGroupCallSetting#56d6a247 join_muted:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantJoinByInvite#5cdada77 invite:ExportedChatInvite = ChannelAdminLogEventAction;
channelAdminLogEventActionExportedInviteDelete#5a50fca4 invite:ExportedChatInvite = ChannelAdminLogEventAction;
channelAdminLogEventActionExportedInviteRevoke#410a134e invite:ExportedChatInvite = ChannelAdminLogEventAction;
channelAdminLogEventActionExportedInviteEdit#e90ebb59 prev_invite:ExportedChatInvite new_invite:ExportedChatInvite = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantVolume#3e7f6847 participant:GroupCallParticipant = ChannelAdminLogEventAction;
channelAdminLogEventActionChangeHistoryTTL#6e941a38 prev_value:int new_value:int = ChannelAdminLogEventAction;
channelAdminLogEventActionParticipantJoinByRequest#afb6144a invite:ExportedChatInvite approved_by:long = ChannelAdminLogEventAction;
channelAdminLogEventActionToggleNoForwards#cb2ac766 new_value:Bool = ChannelAdminLogEventAction;
channelAdminLogEventActionSendMessage#278f2868 message:Message = ChannelAdminLogEventAction;

channelAdminLogEvent#1fad68cd id:long date:int user_id:long action:ChannelAdminLogEventAction = ChannelAdminLogEvent;

channels.adminLogResults#ed8af74d events:Vector<ChannelAdminLogEvent> chats:Vector<Chat> users:Vector<User> = channels.AdminLogResults;

channelAdminLogEventsFilter#ea107ae4 flags:# join:flags.0?true leave:flags.1?true invite:flags.2?true ban:flags.3?true unban:flags.4?true kick:flags.5?true unkick:flags.6?true promote:flags.7?true demote:flags.8?true info:flags.9?true settings:flags.10?true pinned:flags.11?true edit:flags.12?true delete:flags.13?true group_call:flags.14?true invites:flags.15?true send:flags.16?true = ChannelAdminLogEventsFilter;

popularContact#5ce14175 client_id:long importers:int = PopularContact;

messages.favedStickersNotModified#9e8fa6d3 = messages.FavedStickers;
messages.favedStickers#2cb51097 hash:long packs:Vector<StickerPack> stickers:Vector<Document> = messages.FavedStickers;

recentMeUrlUnknown#46e1d13d url:string = RecentMeUrl;
recentMeUrlUser#b92c09e2 url:string user_id:long = RecentMeUrl;
recentMeUrlChat#b2da71d2 url:string chat_id:long = RecentMeUrl;
recentMeUrlChatInvite#eb49081d url:string chat_invite:ChatInvite = RecentMeUrl;
recentMeUrlStickerSet#bc0a57dc url:string set:StickerSetCovered = RecentMeUrl;

help.recentMeUrls#e0310d7 urls:Vector<RecentMeUrl> chats:Vector<Chat> users:Vector<User> = help.RecentMeUrls;

inputSingleMedia#1cc6e91f flags:# media:InputMedia random_id:long message:string entities:flags.0?Vector<MessageEntity> = InputSingleMedia;

webAuthorization#a6f8f452 hash:long bot_id:long domain:string browser:string platform:string date_created:int date_active:int ip:string region:string = WebAuthorization;

account.webAuthorizations#ed56c9fc authorizations:Vector<WebAuthorization> users:Vector<User> = account.WebAuthorizations;

inputMessageID#a676a322 id:int = InputMessage;
inputMessageReplyTo#bad88395 id:int = InputMessage;
inputMessagePinned#86872538 = InputMessage;
inputMessageCallbackQuery#acfa1a7e id:int query_id:long = InputMessage;

inputDialogPeer#fcaafeb7 peer:InputPeer = InputDialogPeer;
inputDialogPeerFolder#64600527 folder_id:int = InputDialogPeer;

dialogPeer#e56dbf05 peer:Peer = DialogPeer;
dialogPeerFolder#514519e2 folder_id:int = DialogPeer;

messages.foundStickerSetsNotModified#d54b65d = messages.FoundStickerSets;
messages.foundStickerSets#8af09dd2 hash:long sets:Vector<StickerSetCovered> = messages.FoundStickerSets;

fileHash#6242c773 offset:int limit:int hash:bytes = FileHash;

inputClientProxy#75588b3f address:string port:int = InputClientProxy;

help.termsOfServiceUpdateEmpty#e3309f7f expires:int = help.TermsOfServiceUpdate;
help.termsOfServiceUpdate#28ecf961 expires:int terms_of_service:help.TermsOfService = help.TermsOfServiceUpdate;

inputSecureFileUploaded#3334b0f0 id:long parts:int md5_checksum:string file_hash:bytes secret:bytes = InputSecureFile;
inputSecureFile#5367e5be id:long access_hash:long = InputSecureFile;

secureFileEmpty#64199744 = SecureFile;
secureFile#e0277a62 id:long access_hash:long size:int dc_id:int date:int file_hash:bytes secret:bytes = SecureFile;

secureData#8aeabec3 data:bytes data_hash:bytes secret:bytes = SecureData;

securePlainPhone#7d6099dd phone:string = SecurePlainData;
securePlainEmail#21ec5a5f email:string = SecurePlainData;

secureValueTypePersonalDetails#9d2a81e3 = SecureValueType;
secureValueTypePassport#3dac6a00 = SecureValueType;
secureValueTypeDriverLicense#6e425c4 = SecureValueType;
secureValueTypeIdentityCard#a0d0744b = SecureValueType;
secureValueTypeInternalPassport#99a48f23 = SecureValueType;
secureValueTypeAddress#cbe31e26 = SecureValueType;
secureValueTypeUtilityBill#fc36954e = SecureValueType;
secureValueTypeBankStatement#89137c0d = SecureValueType;
secureValueTypeRentalAgreement#8b883488 = SecureValueType;
secureValueTypePassportRegistration#99e3806a = SecureValueType;
secureValueTypeTemporaryRegistration#ea02ec33 = SecureValueType;
secureValueTypePhone#b320aadb = SecureValueType;
secureValueTypeEmail#8e3ca7ee = SecureValueType;

secureValue#187fa0ca flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?SecureFile reverse_side:flags.2?SecureFile selfie:flags.3?SecureFile translation:flags.6?Vector<SecureFile> files:flags.4?Vector<SecureFile> plain_data:flags.5?SecurePlainData hash:bytes = SecureValue;

inputSecureValue#db21d0a7 flags:# type:SecureValueType data:flags.0?SecureData front_side:flags.1?InputSecureFile reverse_side:flags.2?InputSecureFile selfie:flags.3?InputSecureFile translation:flags.6?Vector<InputSecureFile> files:flags.4?Vector<InputSecureFile> plain_data:flags.5?SecurePlainData = InputSecureValue;

secureValueHash#ed1ecdb0 type:SecureValueType hash:bytes = SecureValueHash;

secureValueErrorData#e8a40bd9 type:SecureValueType data_hash:bytes field:string text:string = SecureValueError;
secureValueErrorFrontSide#be3dfa type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorReverseSide#868a2aa5 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorSelfie#e537ced6 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorFile#7a700873 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorFiles#666220e9 type:SecureValueType file_hash:Vector<bytes> text:string = SecureValueError;
secureValueError#869d758f type:SecureValueType hash:bytes text:string = SecureValueError;
secureValueErrorTranslationFile#a1144770 type:SecureValueType file_hash:bytes text:string = SecureValueError;
secureValueErrorTranslationFiles#34636dd8 type:SecureValueType file_hash:Vector<bytes> text:string = SecureValueError;

secureCredentialsEncrypted#33f0ea47 data:bytes hash:bytes secret:bytes = SecureCredentialsEncrypted;

account.authorizationForm#ad2e1cd8 flags:# required_types:Vector<SecureRequiredType> values:Vector<SecureValue> errors:Vector<SecureValueError> users:Vector<User> privacy_policy_url:flags.0?string = account.AuthorizationForm;

account.sentEmailCode#811f854f email_pattern:string length:int = account.SentEmailCode;

help.deepLinkInfoEmpty#66afa166 = help.DeepLinkInfo;
help.deepLinkInfo#6a4ee832 flags:# update_app:flags.0?true message:string entities:flags.1?Vector<MessageEntity> = help.DeepLinkInfo;

savedPhoneContact#1142bd56 phone:string first_name:string last_name:string date:int = SavedContact;

account.takeout#4dba4501 id:long = account.Takeout;

passwordKdfAlgoUnknown#d45ab096 = PasswordKdfAlgo;
passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow#3a912d4a salt1:bytes salt2:bytes g:int p:bytes = PasswordKdfAlgo;

securePasswordKdfAlgoUnknown#4a8537 = SecurePasswordKdfAlgo;
securePasswordKdfAlgoPBKDF2HMACSHA512iter100000#bbf2dda0 salt:bytes = SecurePasswordKdfAlgo;
securePasswordKdfAlgoSHA512#86471d92 salt:bytes = SecurePasswordKdfAlgo;

secureSecretSettings#1527bcac secure_algo:SecurePasswordKdfAlgo secure_secret:bytes secure_secret_id:long = SecureSecretSettings;

inputCheckPasswordEmpty#9880f658 = InputCheckPasswordSRP;
inputCheckPasswordSRP#d27ff082 srp_id:long A:bytes M1:bytes = InputCheckPasswordSRP;

secureRequiredType#829d99da flags:# native_names:flags.0?true selfie_required:flags.1?true translation_required:flags.2?true type:SecureValueType = SecureRequiredType;
secureRequiredTypeOneOf#27477b4 types:Vector<SecureRequiredType> = SecureRequiredType;

help.passportConfigNotModified#bfb9f457 = help.PassportConfig;
help.passportConfig#a098d6af hash:int countries_langs:DataJSON = help.PassportConfig;

inputAppEvent#1d1b1245 time:double type:string peer:long data:JSONValue = InputAppEvent;

jsonObjectValue#c0de1bd9 key:string value:JSONValue = JSONObjectValue;

jsonNull#3f6d7b68 = JSONValue;
jsonBool#c7345e6a value:Bool = JSONValue;
jsonNumber#2be0dfa4 value:double = JSONValue;
jsonString#b71e767a value:string = JSONValue;
jsonArray#f7444763 value:Vector<JSONValue> = JSONValue;
jsonObject#99c1d49d value:Vector<JSONObjectValue> = JSONValue;

pageTableCell#34566b6a flags:# header:flags.0?true align_center:flags.3?true align_right:flags.4?true valign_middle:flags.5?true valign_bottom:flags.6?true text:flags.7?RichText colspan:flags.1?int rowspan:flags.2?int = PageTableCell;

pageTableRow#e0c0c5e5 cells:Vector<PageTableCell> = PageTableRow;

pageCaption#6f747657 text:RichText credit:RichText = PageCaption;

pageListItemText#b92fb6cd text:RichText = PageListItem;
pageListItemBlocks#25e073fc blocks:Vector<PageBlock> = PageListItem;

pageListOrderedItemText#5e068047 num:string text:RichText = PageListOrderedItem;
pageListOrderedItemBlocks#98dd8936 num:string blocks:Vector<PageBlock> = PageListOrderedItem;

pageRelatedArticle#b390dc08 flags:# url:string webpage_id:long title:flags.0?string description:flags.1?string photo_id:flags.2?long author:flags.3?string published_date:flags.4?int = PageRelatedArticle;

page#98657f0d flags:# part:flags.0?true rtl:flags.1?true v2:flags.2?true url:string blocks:Vector<PageBlock> photos:Vector<Photo> documents:Vector<Document> views:flags.3?int = Page;

help.supportName#8c05f1c9 name:string = help.SupportName;

help.userInfoEmpty#f3ae2eed = help.UserInfo;
help.userInfo#1eb3758 message:string entities:Vector<MessageEntity> author:string date:int = help.UserInfo;

pollAnswer#6ca9c2e9 text:string option:bytes = PollAnswer;

poll#86e18161 id:long flags:# closed:flags.0?true public_voters:flags.1?true multiple_choice:flags.2?true quiz:flags.3?true question:string answers:Vector<PollAnswer> close_period:flags.4?int close_date:flags.5?int = Poll;

pollAnswerVoters#3b6ddad2 flags:# chosen:flags.0?true correct:flags.1?true option:bytes voters:int = PollAnswerVoters;

pollResults#dcb82ea3 flags:# min:flags.0?true results:flags.1?Vector<PollAnswerVoters> total_voters:flags.2?int recent_voters:flags.3?Vector<long> solution:flags.4?string solution_entities:flags.4?Vector<MessageEntity> = PollResults;

chatOnlines#f041e250 onlines:int = ChatOnlines;

statsURL#47a971e0 url:string = StatsURL;

chatAdminRights#5fb224d5 flags:# change_info:flags.0?true post_messages:flags.1?true edit_messages:flags.2?true delete_messages:flags.3?true ban_users:flags.4?true invite_users:flags.5?true pin_messages:flags.7?true add_admins:flags.9?true anonymous:flags.10?true manage_call:flags.11?true other:flags.12?true = ChatAdminRights;

chatBannedRights#9f120418 flags:# view_messages:flags.0?true send_messages:flags.1?true send_media:flags.2?true send_stickers:flags.3?true send_gifs:flags.4?true send_games:flags.5?true send_inline:flags.6?true embed_links:flags.7?true send_polls:flags.8?true change_info:flags.10?true invite_users:flags.15?true pin_messages:flags.17?true until_date:int = ChatBannedRights;

inputWallPaper#e630b979 id:long access_hash:long = InputWallPaper;
inputWallPaperSlug#72091c80 slug:string = InputWallPaper;
inputWallPaperNoFile#967a462e id:long = InputWallPaper;

account.wallPapersNotModified#1c199183 = account.WallPapers;
account.wallPapers#cdc3858c hash:long wallpapers:Vector<WallPaper> = account.WallPapers;

codeSettings#8a6469c2 flags:# allow_flashcall:flags.0?true current_number:flags.1?true allow_app_hash:flags.4?true allow_missed_call:flags.5?true logout_tokens:flags.6?Vector<bytes> = CodeSettings;

wallPaperSettings#1dc1bca4 flags:# blur:flags.1?true motion:flags.2?true background_color:flags.0?int second_background_color:flags.4?int third_background_color:flags.5?int fourth_background_color:flags.6?int intensity:flags.3?int rotation:flags.4?int = WallPaperSettings;

autoDownloadSettings#e04232f3 flags:# disabled:flags.0?true video_preload_large:flags.1?true audio_preload_next:flags.2?true phonecalls_less_data:flags.3?true photo_size_max:int video_size_max:int file_size_max:int video_upload_maxbitrate:int = AutoDownloadSettings;

account.autoDownloadSettings#63cacf26 low:AutoDownloadSettings medium:AutoDownloadSettings high:AutoDownloadSettings = account.AutoDownloadSettings;

emojiKeyword#d5b3b9f9 keyword:string emoticons:Vector<string> = EmojiKeyword;
emojiKeywordDeleted#236df622 keyword:string emoticons:Vector<string> = EmojiKeyword;

emojiKeywordsDifference#5cc761bd lang_code:string from_version:int version:int keywords:Vector<EmojiKeyword> = EmojiKeywordsDifference;

emojiURL#a575739d url:string = EmojiURL;

emojiLanguage#b3fb5361 lang_code:string = EmojiLanguage;

folder#ff544e65 flags:# autofill_new_broadcasts:flags.0?true autofill_public_groups:flags.1?true autofill_new_correspondents:flags.2?true id:int title:string photo:flags.3?ChatPhoto = Folder;

inputFolderPeer#fbd2c296 peer:InputPeer folder_id:int = InputFolderPeer;

folderPeer#e9baa668 peer:Peer folder_id:int = FolderPeer;

messages.searchCounter#e844ebff flags:# inexact:flags.1?true filter:MessagesFilter count:int = messages.SearchCounter;

urlAuthResultRequest#92d33a0e flags:# request_write_access:flags.0?true bot:User domain:string = UrlAuthResult;
urlAuthResultAccepted#8f8c0e4e url:string = UrlAuthResult;
urlAuthResultDefault#a9d6db1f = UrlAuthResult;

channelLocationEmpty#bfb5ad8b = ChannelLocation;
channelLocation#209b82db geo_point:GeoPoint address:string = ChannelLocation;

peerLocated#ca461b5d peer:Peer expires:int distance:int = PeerLocated;
peerSelfLocated#f8ec284b expires:int = PeerLocated;

restrictionReason#d072acb4 platform:string reason:string text:string = RestrictionReason;

inputTheme#3c5693e9 id:long access_hash:long = InputTheme;
inputThemeSlug#f5890df1 slug:string = InputTheme;

theme#a00e67d6 flags:# creator:flags.0?true default:flags.1?true for_chat:flags.5?true id:long access_hash:long slug:string title:string document:flags.2?Document settings:flags.3?Vector<ThemeSettings> emoticon:flags.6?string installs_count:flags.4?int = Theme;

account.themesNotModified#f41eb622 = account.Themes;
account.themes#9a3d8c6d hash:long themes:Vector<Theme> = account.Themes;

auth.loginToken#629f1980 expires:int token:bytes = auth.LoginToken;
auth.loginTokenMigrateTo#68e9916 dc_id:int token:bytes = auth.LoginToken;
auth.loginTokenSuccess#390d5c5e authorization:auth.Authorization = auth.LoginToken;

account.contentSettings#57e28221 flags:# sensitive_enabled:flags.0?true sensitive_can_change:flags.1?true = account.ContentSettings;

messages.inactiveChats#a927fec5 dates:Vector<int> chats:Vector<Chat> users:Vector<User> = messages.InactiveChats;

baseThemeClassic#c3a12462 = BaseTheme;
baseThemeDay#fbd81688 = BaseTheme;
baseThemeNight#b7b31ea8 = BaseTheme;
baseThemeTinted#6d5f77ee = BaseTheme;
baseThemeArctic#5b11125a = BaseTheme;

inputThemeSettings#8fde504f flags:# message_colors_animated:flags.2?true base_theme:BaseTheme accent_color:int outbox_accent_color:flags.3?int message_colors:flags.0?Vector<int> wallpaper:flags.1?InputWallPaper wallpaper_settings:flags.1?WallPaperSettings = InputThemeSettings;

themeSettings#fa58b6d4 flags:# message_colors_animated:flags.2?true base_theme:BaseTheme accent_color:int outbox_accent_color:flags.3?int message_colors:flags.0?Vector<int> wallpaper:flags.1?WallPaper = ThemeSettings;

webPageAttributeTheme#54b56617 flags:# documents:flags.0?Vector<Document> settings:flags.1?ThemeSettings = WebPageAttribute;

messageUserVote#34d247b4 user_id:long option:bytes date:int = MessageUserVote;
messageUserVoteInputOption#3ca5b0ec user_id:long date:int = MessageUserVote;
messageUserVoteMultiple#8a65e557 user_id:long options:Vector<bytes> date:int = MessageUserVote;

messages.votesList#823f649 flags:# count:int votes:Vector<MessageUserVote> users:Vector<User> next_offset:flags.0?string = messages.VotesList;

bankCardOpenUrl#f568028a url:string name:string = BankCardOpenUrl;

payments.bankCardData#3e24e573 title:string open_urls:Vector<BankCardOpenUrl> = payments.BankCardData;

dialogFilter#7438f7e8 flags:# contacts:flags.0?true non_contacts:flags.1?true groups:flags.2?true broadcasts:flags.3?true bots:flags.4?true exclude_muted:flags.11?true exclude_read:flags.12?true exclude_archived:flags.13?true id:int title:string emoticon:flags.25?string pinned_peers:Vector<InputPeer> include_peers:Vector<InputPeer> exclude_peers:Vector<InputPeer> = DialogFilter;

dialogFilterSuggested#77744d4a filter:DialogFilter description:string = DialogFilterSuggested;

statsDateRangeDays#b637edaf min_date:int max_date:int = StatsDateRangeDays;

statsAbsValueAndPrev#cb43acde current:double previous:double = StatsAbsValueAndPrev;

statsPercentValue#cbce2fe0 part:double total:double = StatsPercentValue;

statsGraphAsync#4a27eb2d token:string = StatsGraph;
statsGraphError#bedc9822 error:string = StatsGraph;
statsGraph#8ea464b6 flags:# json:DataJSON zoom_token:flags.0?string = StatsGraph;

messageInteractionCounters#ad4fc9bd msg_id:int views:int forwards:int = MessageInteractionCounters;

stats.broadcastStats#bdf78394 period:StatsDateRangeDays followers:StatsAbsValueAndPrev views_per_post:StatsAbsValueAndPrev shares_per_post:StatsAbsValueAndPrev enabled_notifications:StatsPercentValue growth_graph:StatsGraph followers_graph:StatsGraph mute_graph:StatsGraph top_hours_graph:StatsGraph interactions_graph:StatsGraph iv_interactions_graph:StatsGraph views_by_source_graph:StatsGraph new_followers_by_source_graph:StatsGraph languages_graph:StatsGraph recent_message_interactions:Vector<MessageInteractionCounters> = stats.BroadcastStats;

help.promoDataEmpty#98f6ac75 expires:int = help.PromoData;
help.promoData#8c39793f flags:# proxy:flags.0?true expires:int peer:Peer chats:Vector<Chat> users:Vector<User> psa_type:flags.1?string psa_message:flags.2?string = help.PromoData;

videoSize#de33b094 flags:# type:string w:int h:int size:int video_start_ts:flags.0?double = VideoSize;

statsGroupTopPoster#9d04af9b user_id:long messages:int avg_chars:int = StatsGroupTopPoster;

statsGroupTopAdmin#d7584c87 user_id:long deleted:int kicked:int banned:int = StatsGroupTopAdmin;

statsGroupTopInviter#535f779d user_id:long invitations:int = StatsGroupTopInviter;

stats.megagroupStats#ef7ff916 period:StatsDateRangeDays members:StatsAbsValueAndPrev messages:StatsAbsValueAndPrev viewers:StatsAbsValueAndPrev posters:StatsAbsValueAndPrev growth_graph:StatsGraph members_graph:StatsGraph new_members_by_source_graph:StatsGraph languages_graph:StatsGraph messages_graph:StatsGraph actions_graph:StatsGraph top_hours_graph:StatsGraph weekdays_graph:StatsGraph top_posters:Vector<StatsGroupTopPoster> top_admins:Vector<StatsGroupTopAdmin> top_inviters:Vector<StatsGroupTopInviter> users:Vector<User> = stats.MegagroupStats;

globalPrivacySettings#bea2f424 flags:# archive_and_mute_new_noncontact_peers:flags.0?Bool = GlobalPrivacySettings;

help.countryCode#4203c5ef flags:# country_code:string prefixes:flags.0?Vector<string> patterns:flags.1?Vector<string> = help.CountryCode;

help.country#c3878e23 flags:# hidden:flags.0?true iso2:string default_name:string name:flags.1?string country_codes:Vector<help.CountryCode> = help.Country;

help.countriesListNotModified#93cc1f32 = help.CountriesList;
help.countriesList#87d0759e countries:Vector<help.Country> hash:int = help.CountriesList;

messageViews#455b853d flags:# views:flags.0?int forwards:flags.1?int replies:flags.2?MessageReplies = MessageViews;

messages.messageViews#b6c4f543 views:Vector<MessageViews> chats:Vector<Chat> users:Vector<User> = messages.MessageViews;

messages.discussionMessage#a6341782 flags:# messages:Vector<Message> max_id:flags.0?int read_inbox_max_id:flags.1?int read_outbox_max_id:flags.2?int unread_count:int chats:Vector<Chat> users:Vector<User> = messages.DiscussionMessage;

messageReplyHeader#a6d57763 flags:# reply_to_msg_id:int reply_to_peer_id:flags.0?Peer reply_to_top_id:flags.1?int = MessageReplyHeader;

messageReplies#83d60fc2 flags:# comments:flags.0?true replies:int replies_pts:int recent_repliers:flags.1?Vector<Peer> channel_id:flags.0?long max_id:flags.2?int read_max_id:flags.3?int = MessageReplies;

peerBlocked#e8fd8014 peer_id:Peer date:int = PeerBlocked;

stats.messageStats#8999f295 views_graph:StatsGraph = stats.MessageStats;

groupCallDiscarded#7780bcb4 id:long access_hash:long duration:int = GroupCall;
groupCall#d597650c flags:# join_muted:flags.1?true can_change_join_muted:flags.2?true join_date_asc:flags.6?true schedule_start_subscribed:flags.8?true can_start_video:flags.9?true record_video_active:flags.11?true id:long access_hash:long participants_count:int title:flags.3?string stream_dc_id:flags.4?int record_start_date:flags.5?int schedule_date:flags.7?int unmuted_video_count:flags.10?int unmuted_video_limit:int version:int = GroupCall;

inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;

groupCallParticipant#eba636fe flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true video_joined:flags.15?true peer:Peer date:int active_date:flags.3?int source:int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long video:flags.6?GroupCallParticipantVideo presentation:flags.14?GroupCallParticipantVideo = GroupCallParticipant;

phone.groupCall#9e727aad call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string chats:Vector<Chat> users:Vector<User> = phone.GroupCall;

phone.groupParticipants#f47751b6 count:int participants:Vector<GroupCallParticipant> next_offset:string chats:Vector<Chat> users:Vector<User> version:int = phone.GroupParticipants;

inlineQueryPeerTypeSameBotPM#3081ed9d = InlineQueryPeerType;
inlineQueryPeerTypePM#833c0fac = InlineQueryPeerType;
inlineQueryPeerTypeChat#d766c50a = InlineQueryPeerType;
inlineQueryPeerTypeMegagroup#5ec4be43 = InlineQueryPeerType;
inlineQueryPeerTypeBroadcast#6334ee9a = InlineQueryPeerType;

messages.historyImport#1662af0b id:long = messages.HistoryImport;

messages.historyImportParsed#5e0fb7b9 flags:# pm:flags.0?true group:flags.1?true title:flags.2?string = messages.HistoryImportParsed;

messages.affectedFoundMessages#ef8d3e6c pts:int pts_count:int offset:int messages:Vector<int> = messages.AffectedFoundMessages;

chatInviteImporter#8c5adfd9 flags:# requested:flags.0?true user_id:long date:int about:flags.2?string approved_by:flags.1?long = ChatInviteImporter;

messages.exportedChatInvites#bdc62dcc count:int invites:Vector<ExportedChatInvite> users:Vector<User> = messages.ExportedChatInvites;

messages.exportedChatInvite#1871be50 invite:ExportedChatInvite users:Vector<User> = messages.ExportedChatInvite;
messages.exportedChatInviteReplaced#222600ef invite:ExportedChatInvite new_invite:ExportedChatInvite users:Vector<User> = messages.ExportedChatInvite;

messages.chatInviteImporters#81b6b00a count:int importers:Vector<ChatInviteImporter> users:Vector<User> = messages.ChatInviteImporters;

chatAdminWithInvites#f2ecef23 admin_id:long invites_count:int revoked_invites_count:int = ChatAdminWithInvites;

messages.chatAdminsWithInvites#b69b72d7 admins:Vector<ChatAdminWithInvites> users:Vector<User> = messages.ChatAdminsWithInvites;

messages.checkedHistoryImportPeer#a24de717 confirm_text:string = messages.CheckedHistoryImportPeer;

phone.joinAsPeers#afe5623f peers:Vector<Peer> chats:Vector<Chat> users:Vector<User> = phone.JoinAsPeers;

phone.exportedGroupCallInvite#204bd158 link:string = phone.ExportedGroupCallInvite;

groupCallParticipantVideoSourceGroup#dcb118b7 semantics:string sources:Vector<int> = GroupCallParticipantVideoSourceGroup;

groupCallParticipantVideo#67753ac8 flags:# paused:flags.0?true endpoint:string source_groups:Vector<GroupCallParticipantVideoSourceGroup> audio_source:flags.1?int = GroupCallParticipantVideo;

stickers.suggestedShortName#85fea03f short_name:string = stickers.SuggestedShortName;

botCommandScopeDefault#2f6cb2ab = BotCommandScope;
botCommandScopeUsers#3c4f04d8 = BotCommandScope;
botCommandScopeChats#6fe1a881 = BotCommandScope;
botCommandScopeChatAdmins#b9aa606a = BotCommandScope;
botCommandScopePeer#db9d897d peer:InputPeer = BotCommandScope;
botCommandScopePeerAdmins#3fd863d1 peer:InputPeer = BotCommandScope;
botCommandScopePeerUser#a1321f3 peer:InputPeer user_id:InputUser = BotCommandScope;

account.resetPasswordFailedWait#e3779861 retry_date:int = account.ResetPasswordResult;
account.resetPasswordRequestedWait#e9effc7d until_date:int = account.ResetPasswordResult;
account.resetPasswordOk#e926d63e = account.ResetPasswordResult;

sponsoredMessage#d151e19a flags:# random_id:bytes from_id:Peer channel_post:flags.2?int start_param:flags.0?string message:string entities:flags.1?Vector<MessageEntity> = SponsoredMessage;

messages.sponsoredMessages#65a4c7d5 messages:Vector<SponsoredMessage> chats:Vector<Chat> users:Vector<User> = messages.SponsoredMessages;

searchResultsCalendarPeriod#c9b0539f date:int min_msg_id:int max_msg_id:int count:int = SearchResultsCalendarPeriod;

messages.searchResultsCalendar#147ee23c flags:# inexact:flags.0?true count:int min_date:int min_msg_id:int offset_id_offset:flags.1?int periods:Vector<SearchResultsCalendarPeriod> messages:Vector<Message> chats:Vector<Chat> users:Vector<User> = messages.SearchResultsCalendar;

searchResultPosition#7f648b67 msg_id:int date:int offset:int = SearchResultsPosition;

messages.searchResultsPositions#53b22baf count:int positions:Vector<SearchResultsPosition> = messages.SearchResultsPositions;

channels.sendAsPeers#8356cda9 peers:Vector<Peer> chats:Vector<Chat> users:Vector<User> = channels.SendAsPeers;

users.userFull#3b6d152e full_user:UserFull chats:Vector<Chat> users:Vector<User> = users.UserFull;

messages.peerSettings#6880b94d settings:PeerSettings chats:Vector<Chat> users:Vector<User> = messages.PeerSettings;

auth.loggedOut#c3a2835f flags:# future_auth_token:flags.0?bytes = auth.LoggedOut;

---functions---

invokeAfterMsg#cb9f372d {X:Type} msg_id:long query:!X = X;
invokeAfterMsgs#3dc4b4f0 {X:Type} msg_ids:Vector<long> query:!X = X;
initConnection#c1cd5ea9 {X:Type} flags:# api_id:int device_model:string system_version:string app_version:string system_lang_code:string lang_pack:string lang_code:string proxy:flags.0?InputClientProxy params:flags.1?JSONValue query:!X = X;
invokeWithLayer#da9b0d0d {X:Type} layer:int query:!X = X;
invokeWithoutUpdates#bf9459b7 {X:Type} query:!X = X;
invokeWithMessagesRange#365275f2 {X:Type} range:MessageRange query:!X = X;
invokeWithTakeout#aca9fd2e {X:Type} takeout_id:long query:!X = X;

auth.sendCode#a677244f phone_number:string api_id:int api_hash:string settings:CodeSettings = auth.SentCode;
auth.signUp#80eee427 phone_number:string phone_code_hash:string first_name:string last_name:string = auth.Authorization;
auth.signIn#bcd51581 phone_number:string phone_code_hash:string phone_code:string = auth.Authorization;
auth.logOut#3e72ba19 = auth.LoggedOut;
auth.resetAuthorizations#9fab0d1a = Bool;
auth.exportAuthorization#e5bfffcd dc_id:int = auth.ExportedAuthorization;
auth.importAuthorization#a57a7dad id:long bytes:bytes = auth.Authorization;
auth.bindTempAuthKey#cdd42a05 perm_auth_key_id:long nonce:long expires_at:int encrypted_message:bytes = Bool;
auth.importBotAuthorization#67a3ff2c flags:int api_id:int api_hash:string bot_auth_token:string = auth.Authorization;
auth.checkPassword#d18b4d16 password:InputCheckPasswordSRP = auth.Authorization;
auth.requestPasswordRecovery#d897bc66 = auth.PasswordRecovery;
auth.recoverPassword#37096c70 flags:# code:string new_settings:flags.0?account.PasswordInputSettings = auth.Authorization;
auth.resendCode#3ef1a9bf phone_number:string phone_code_hash:string = auth.SentCode;
auth.cancelCode#1f040578 phone_number:string phone_code_hash:string = Bool;
auth.dropTempAuthKeys#8e48a188 except_auth_keys:Vector<long> = Bool;
auth.exportLoginToken#b7e085fe api_id:int api_hash:string except_ids:Vector<long> = auth.LoginToken;
auth.importLoginToken#95ac5ce4 token:bytes = auth.LoginToken;
auth.acceptLoginToken#e894ad4d token:bytes = Authorization;
auth.checkRecoveryPassword#d36bf79 code:string = Bool;

account.registerDevice#ec86017a flags:# no_muted:flags.0?true token_type:int token:string app_sandbox:Bool secret:bytes other_uids:Vector<long> = Bool;
account.unregisterDevice#6a0d3206 token_type:int token:string other_uids:Vector<long> = Bool;
account.updateNotifySettings#84be5b93 peer:InputNotifyPeer settings:InputPeerNotifySettings = Bool;
account.getNotifySettings#12b3ad31 peer:InputNotifyPeer = PeerNotifySettings;
account.resetNotifySettings#db7e1747 = Bool;
account.updateProfile#78515775 flags:# first_name:flags.0?string last_name:flags.1?string about:flags.2?string = User;
account.updateStatus#6628562c offline:Bool = Bool;
account.getWallPapers#7967d36 hash:long = account.WallPapers;
account.reportPeer#c5ba3d86 peer:InputPeer reason:ReportReason message:string = Bool;
account.checkUsername#2714d86c username:string = Bool;
account.updateUsername#3e0bdd7c username:string = User;
account.getPrivacy#dadbc950 key:InputPrivacyKey = account.PrivacyRules;
account.setPrivacy#c9f81ce8 key:InputPrivacyKey rules:Vector<InputPrivacyRule> = account.PrivacyRules;
account.deleteAccount#418d4e0b reason:string = Bool;
account.getAccountTTL#8fc711d = AccountDaysTTL;
account.setAccountTTL#2442485e ttl:AccountDaysTTL = Bool;
account.sendChangePhoneCode#82574ae5 phone_number:string settings:CodeSettings = auth.SentCode;
account.changePhone#70c32edb phone_number:string phone_code_hash:string phone_code:string = User;
account.updateDeviceLocked#38df3532 period:int = Bool;
account.getAuthorizations#e320c158 = account.Authorizations;
account.resetAuthorization#df77f3bc hash:long = Bool;
account.getPassword#548a30f5 = account.Password;
account.getPasswordSettings#9cd4eaf9 password:InputCheckPasswordSRP = account.PasswordSettings;
account.updatePasswordSettings#a59b102f password:InputCheckPasswordSRP new_settings:account.PasswordInputSettings = Bool;
account.sendConfirmPhoneCode#1b3faa88 hash:string settings:CodeSettings = auth.SentCode;
account.confirmPhone#5f2178c3 phone_code_hash:string phone_code:string = Bool;
account.getTmpPassword#449e0b51 password:InputCheckPasswordSRP period:int = account.TmpPassword;
account.getWebAuthorizations#182e6d6f = account.WebAuthorizations;
account.resetWebAuthorization#2d01b9ef hash:long = Bool;
account.resetWebAuthorizations#682d2594 = Bool;
account.getAllSecureValues#b288bc7d = Vector<SecureValue>;
account.getSecureValue#73665bc2 types:Vector<SecureValueType> = Vector<SecureValue>;
account.saveSecureValue#899fe31d value:InputSecureValue secure_secret_id:long = SecureValue;
account.deleteSecureValue#b880bc4b types:Vector<SecureValueType> = Bool;
account.getAuthorizationForm#a929597a bot_id:long scope:string public_key:string = account.AuthorizationForm;
account.acceptAuthorization#f3ed4c73 bot_id:long scope:string public_key:string value_hashes:Vector<SecureValueHash> credentials:SecureCredentialsEncrypted = Bool;
account.sendVerifyPhoneCode#a5a356f9 phone_number:string settings:CodeSettings = auth.SentCode;
account.verifyPhone#4dd3a7f6 phone_number:string phone_code_hash:string phone_code:string = Bool;
account.sendVerifyEmailCode#7011509f email:string = account.SentEmailCode;
account.verifyEmail#ecba39db email:string code:string = Bool;
account.initTakeoutSession#f05b4804 flags:# contacts:flags.0?true message_users:flags.1?true message_chats:flags.2?true message_megagroups:flags.3?true message_channels:flags.4?true files:flags.5?true file_max_size:flags.5?int = account.Takeout;
account.finishTakeoutSession#1d2652ee flags:# success:flags.0?true = Bool;
account.confirmPasswordEmail#8fdf1920 code:string = Bool;
account.resendPasswordEmail#7a7f2a15 = Bool;
account.cancelPasswordEmail#c1cbd5b6 = Bool;
account.getContactSignUpNotification#9f07c728 = Bool;
account.setContactSignUpNotification#cff43f61 silent:Bool = Bool;
account.getNotifyExceptions#53577479 flags:# compare_sound:flags.1?true peer:flags.0?InputNotifyPeer = Updates;
account.getWallPaper#fc8ddbea wallpaper:InputWallPaper = WallPaper;
account.uploadWallPaper#dd853661 file:InputFile mime_type:string settings:WallPaperSettings = WallPaper;
account.saveWallPaper#6c5a5b37 wallpaper:InputWallPaper unsave:Bool settings:WallPaperSettings = Bool;
account.installWallPaper#feed5769 wallpaper:InputWallPaper settings:WallPaperSettings = Bool;
account.resetWallPapers#bb3b9804 = Bool;
account.getAutoDownloadSettings#56da0b3f = account.AutoDownloadSettings;
account.saveAutoDownloadSettings#76f36233 flags:# low:flags.0?true high:flags.1?true settings:AutoDownloadSettings = Bool;
account.uploadTheme#1c3db333 flags:# file:InputFile thumb:flags.0?InputFile file_name:string mime_type:string = Document;
account.createTheme#652e4400 flags:# slug:string title:string document:flags.2?InputDocument settings:flags.3?Vector<InputThemeSettings> = Theme;
account.updateTheme#2bf40ccc flags:# format:string theme:InputTheme slug:flags.0?string title:flags.1?string document:flags.2?InputDocument settings:flags.3?Vector<InputThemeSettings> = Theme;
account.saveTheme#f257106c theme:InputTheme unsave:Bool = Bool;
account.installTheme#c727bb3b flags:# dark:flags.0?true theme:flags.1?InputTheme format:flags.2?string base_theme:flags.3?BaseTheme = Bool;
account.getTheme#8d9d742b format:string theme:InputTheme document_id:long = Theme;
account.getThemes#7206e458 format:string hash:long = account.Themes;
account.setContentSettings#b574b16b flags:# sensitive_enabled:flags.0?true = Bool;
account.getContentSettings#8b9b4dae = account.ContentSettings;
account.getMultiWallPapers#65ad71dc wallpapers:Vector<InputWallPaper> = Vector<WallPaper>;
account.getGlobalPrivacySettings#eb2b4cf6 = GlobalPrivacySettings;
account.setGlobalPrivacySettings#1edaaac2 settings:GlobalPrivacySettings = GlobalPrivacySettings;
account.reportProfilePhoto#fa8cc6f5 peer:InputPeer photo_id:InputPhoto reason:ReportReason message:string = Bool;
account.resetPassword#9308ce1b = account.ResetPasswordResult;
account.declinePasswordReset#4c9409f6 = Bool;
account.getChatThemes#d638de89 hash:long = account.Themes;
account.setAuthorizationTTL#bf899aa0 authorization_ttl_days:int = Bool;
account.changeAuthorizationSettings#40f48462 flags:# hash:long encrypted_requests_disabled:flags.0?Bool call_requests_disabled:flags.1?Bool = Bool;

users.getUsers#d91a548 id:Vector<InputUser> = Vector<User>;
users.getFullUser#b60f5918 id:InputUser = users.UserFull;
users.setSecureValueErrors#90c894b5 id:InputUser errors:Vector<SecureValueError> = Bool;

contacts.getContactIDs#7adc669d hash:long = Vector<int>;
contacts.getStatuses#c4a353ee = Vector<ContactStatus>;
contacts.getContacts#5dd69e12 hash:long = contacts.Contacts;
contacts.importContacts#2c800be5 contacts:Vector<InputContact> = contacts.ImportedContacts;
contacts.deleteContacts#96a0e00 id:Vector<InputUser> = Updates;
contacts.deleteByPhones#1013fd9e phones:Vector<string> = Bool;
contacts.block#68cc1411 id:InputPeer = Bool;
contacts.unblock#bea65d50 id:InputPeer = Bool;
contacts.getBlocked#f57c350f offset:int limit:int = contacts.Blocked;
contacts.search#11f812d8 q:string limit:int = contacts.Found;
contacts.resolveUsername#f93ccba3 username:string = contacts.ResolvedPeer;
contacts.getTopPeers#973478b6 flags:# correspondents:flags.0?true bots_pm:flags.1?true bots_inline:flags.2?true phone_calls:flags.3?true forward_users:flags.4?true forward_chats:flags.5?true groups:flags.10?true channels:flags.15?true offset:int limit:int hash:long = contacts.TopPeers;
contacts.resetTopPeerRating#1ae373ac category:TopPeerCategory peer:InputPeer = Bool;
contacts.resetSaved#879537f1 = Bool;
contacts.getSaved#82f1e39f = Vector<SavedContact>;
contacts.toggleTopPeers#8514bdda enabled:Bool = Bool;
contacts.addContact#e8f463d0 flags:# add_phone_privacy_exception:flags.0?true id:InputUser first_name:string last_name:string phone:string = Updates;
contacts.acceptContact#f831a20f id:InputUser = Updates;
contacts.getLocated#d348bc44 flags:# background:flags.1?true geo_point:InputGeoPoint self_expires:flags.0?int = Updates;
contacts.blockFromReplies#29a8962c flags:# delete_message:flags.0?true delete_history:flags.1?true report_spam:flags.2?true msg_id:int = Updates;

messages.getMessages#63c66506 id:Vector<InputMessage> = messages.Messages;
messages.getDialogs#a0f4cb4f flags:# exclude_pinned:flags.0?true folder_id:flags.1?int offset_date:int offset_id:int offset_peer:InputPeer limit:int hash:long = messages.Dialogs;
messages.getHistory#4423e6c5 peer:InputPeer offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
messages.search#a0fda762 flags:# peer:InputPeer q:string from_id:flags.0?InputPeer top_msg_id:flags.1?int filter:MessagesFilter min_date:int max_date:int offset_id:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
messages.readHistory#e306d3a peer:InputPeer max_id:int = messages.AffectedMessages;
messages.deleteHistory#b08f922a flags:# just_clear:flags.0?true revoke:flags.1?true peer:InputPeer max_id:int min_date:flags.2?int max_date:flags.3?int = messages.AffectedHistory;
messages.deleteMessages#e58e95d2 flags:# revoke:flags.0?true id:Vector<int> = messages.AffectedMessages;
messages.receivedMessages#5a954c0 max_id:int = Vector<ReceivedNotifyMessage>;
messages.setTyping#58943ee2 flags:# peer:InputPeer top_msg_id:flags.0?int action:SendMessageAction = Bool;
messages.sendMessage#d9d75a4 flags:# no_webpage:flags.1?true silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.sendMedia#e25ff8e0 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int media:InputMedia message:string random_id:long reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.forwardMessages#cc30290b flags:# silent:flags.5?true background:flags.6?true with_my_score:flags.8?true drop_author:flags.11?true drop_media_captions:flags.12?true from_peer:InputPeer id:Vector<int> random_id:Vector<long> to_peer:InputPeer schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.reportSpam#cf1592db peer:InputPeer = Bool;
messages.getPeerSettings#efd9a6a2 peer:InputPeer = messages.PeerSettings;
messages.report#8953ab4e peer:InputPeer id:Vector<int> reason:ReportReason message:string = Bool;
messages.getChats#49e9528f id:Vector<long> = messages.Chats;
messages.getFullChat#aeb00b34 chat_id:long = messages.ChatFull;
messages.editChatTitle#73783ffd chat_id:long title:string = Updates;
messages.editChatPhoto#35ddd674 chat_id:long photo:InputChatPhoto = Updates;
messages.addChatUser#f24753e3 chat_id:long user_id:InputUser fwd_limit:int = Updates;
messages.deleteChatUser#a2185cab flags:# revoke_history:flags.0?true chat_id:long user_id:InputUser = Updates;
messages.createChat#9cb126e users:Vector<InputUser> title:string = Updates;
messages.getDhConfig#26cf8950 version:int random_length:int = messages.DhConfig;
messages.requestEncryption#f64daf43 user_id:InputUser random_id:int g_a:bytes = EncryptedChat;
messages.acceptEncryption#3dbc0415 peer:InputEncryptedChat g_b:bytes key_fingerprint:long = EncryptedChat;
messages.discardEncryption#f393aea0 flags:# delete_history:flags.0?true chat_id:int = Bool;
messages.setEncryptedTyping#791451ed peer:InputEncryptedChat typing:Bool = Bool;
messages.readEncryptedHistory#7f4b690a peer:InputEncryptedChat max_date:int = Bool;
messages.sendEncrypted#44fa7a15 flags:# silent:flags.0?true peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage;
messages.sendEncryptedFile#5559481d flags:# silent:flags.0?true peer:InputEncryptedChat random_id:long data:bytes file:InputEncryptedFile = messages.SentEncryptedMessage;
messages.sendEncryptedService#32d439a4 peer:InputEncryptedChat random_id:long data:bytes = messages.SentEncryptedMessage;
messages.receivedQueue#55a5bb66 max_qts:int = Vector<long>;
messages.reportEncryptedSpam#4b0c8c0f peer:InputEncryptedChat = Bool;
messages.readMessageContents#36a73f77 id:Vector<int> = messages.AffectedMessages;
messages.getStickers#d5a5d3a1 emoticon:string hash:long = messages.Stickers;
messages.getAllStickers#b8a0a1a8 hash:long = messages.AllStickers;
messages.getWebPagePreview#8b68b0cc flags:# message:string entities:flags.3?Vector<MessageEntity> = MessageMedia;
messages.exportChatInvite#a02ce5d5 flags:# legacy_revoke_permanent:flags.2?true request_needed:flags.3?true peer:InputPeer expire_date:flags.0?int usage_limit:flags.1?int title:flags.4?string = ExportedChatInvite;
messages.checkChatInvite#3eadb1bb hash:string = ChatInvite;
messages.importChatInvite#6c50051c hash:string = Updates;
messages.getStickerSet#c8a0ec74 stickerset:InputStickerSet hash:int = messages.StickerSet;
messages.installStickerSet#c78fe460 stickerset:InputStickerSet archived:Bool = messages.StickerSetInstallResult;
messages.uninstallStickerSet#f96e55de stickerset:InputStickerSet = Bool;
messages.startBot#e6df7378 bot:InputUser peer:InputPeer random_id:long start_param:string = Updates;
messages.getMessagesViews#5784d3e1 peer:InputPeer id:Vector<int> increment:Bool = messages.MessageViews;
messages.editChatAdmin#a85bd1c2 chat_id:long user_id:InputUser is_admin:Bool = Bool;
messages.migrateChat#a2875319 chat_id:long = Updates;
messages.searchGlobal#4bc6589a flags:# folder_id:flags.0?int q:string filter:MessagesFilter min_date:int max_date:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
messages.reorderStickerSets#78337739 flags:# masks:flags.0?true order:Vector<long> = Bool;
messages.getDocumentByHash#338e2464 sha256:bytes size:int mime_type:string = Document;
messages.getSavedGifs#5cf09635 hash:long = messages.SavedGifs;
messages.saveGif#327a30cb id:InputDocument unsave:Bool = Bool;
messages.getInlineBotResults#514e999d flags:# bot:InputUser peer:InputPeer geo_point:flags.0?InputGeoPoint query:string offset:string = messages.BotResults;
messages.setInlineBotResults#eb5ea206 flags:# gallery:flags.0?true private:flags.1?true query_id:long results:Vector<InputBotInlineResult> cache_time:int next_offset:flags.2?string switch_pm:flags.3?InlineBotSwitchPM = Bool;
messages.sendInlineBotResult#7aa11297 flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true hide_via:flags.11?true peer:InputPeer reply_to_msg_id:flags.0?int random_id:long query_id:long id:string schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.getMessageEditData#fda68d36 peer:InputPeer id:int = messages.MessageEditData;
messages.editMessage#48f71778 flags:# no_webpage:flags.1?true peer:InputPeer id:int message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> schedule_date:flags.15?int = Updates;
messages.editInlineBotMessage#83557dba flags:# no_webpage:flags.1?true id:InputBotInlineMessageID message:flags.11?string media:flags.14?InputMedia reply_markup:flags.2?ReplyMarkup entities:flags.3?Vector<MessageEntity> = Bool;
messages.getBotCallbackAnswer#9342ca07 flags:# game:flags.1?true peer:InputPeer msg_id:int data:flags.0?bytes password:flags.2?InputCheckPasswordSRP = messages.BotCallbackAnswer;
messages.setBotCallbackAnswer#d58f130a flags:# alert:flags.1?true query_id:long message:flags.0?string url:flags.2?string cache_time:int = Bool;
messages.getPeerDialogs#e470bcfd peers:Vector<InputDialogPeer> = messages.PeerDialogs;
messages.saveDraft#bc39e14b flags:# no_webpage:flags.1?true reply_to_msg_id:flags.0?int peer:InputPeer message:string entities:flags.3?Vector<MessageEntity> = Bool;
messages.getAllDrafts#6a3f8d65 = Updates;
messages.getFeaturedStickers#64780b14 hash:long = messages.FeaturedStickers;
messages.readFeaturedStickers#5b118126 id:Vector<long> = Bool;
messages.getRecentStickers#9da9403b flags:# attached:flags.0?true hash:long = messages.RecentStickers;
messages.saveRecentSticker#392718f8 flags:# attached:flags.0?true id:InputDocument unsave:Bool = Bool;
messages.clearRecentStickers#8999602d flags:# attached:flags.0?true = Bool;
messages.getArchivedStickers#57f17692 flags:# masks:flags.0?true offset_id:long limit:int = messages.ArchivedStickers;
messages.getMaskStickers#640f82b8 hash:long = messages.AllStickers;
messages.getAttachedStickers#cc5b67cc media:InputStickeredMedia = Vector<StickerSetCovered>;
messages.setGameScore#8ef8ecc0 flags:# edit_message:flags.0?true force:flags.1?true peer:InputPeer id:int user_id:InputUser score:int = Updates;
messages.setInlineGameScore#15ad9f64 flags:# edit_message:flags.0?true force:flags.1?true id:InputBotInlineMessageID user_id:InputUser score:int = Bool;
messages.getGameHighScores#e822649d peer:InputPeer id:int user_id:InputUser = messages.HighScores;
messages.getInlineGameHighScores#f635e1b id:InputBotInlineMessageID user_id:InputUser = messages.HighScores;
messages.getCommonChats#e40ca104 user_id:InputUser max_id:long limit:int = messages.Chats;
messages.getAllChats#875f74be except_ids:Vector<long> = messages.Chats;
messages.getWebPage#32ca8f91 url:string hash:int = WebPage;
messages.toggleDialogPin#a731e257 flags:# pinned:flags.0?true peer:InputDialogPeer = Bool;
messages.reorderPinnedDialogs#3b1adf37 flags:# force:flags.0?true folder_id:int order:Vector<InputDialogPeer> = Bool;
messages.getPinnedDialogs#d6b94df2 folder_id:int = messages.PeerDialogs;
messages.setBotShippingResults#e5f672fa flags:# query_id:long error:flags.0?string shipping_options:flags.1?Vector<ShippingOption> = Bool;
messages.setBotPrecheckoutResults#9c2dd95 flags:# success:flags.1?true query_id:long error:flags.0?string = Bool;
messages.uploadMedia#519bc2b1 peer:InputPeer media:InputMedia = MessageMedia;
messages.sendScreenshotNotification#c97df020 peer:InputPeer reply_to_msg_id:int random_id:long = Updates;
messages.getFavedStickers#4f1aaa9 hash:long = messages.FavedStickers;
messages.faveSticker#b9ffc55b id:InputDocument unfave:Bool = Bool;
messages.getUnreadMentions#46578472 peer:InputPeer offset_id:int add_offset:int limit:int max_id:int min_id:int = messages.Messages;
messages.readMentions#f0189d3 peer:InputPeer = messages.AffectedHistory;
messages.getRecentLocations#702a40e0 peer:InputPeer limit:int hash:long = messages.Messages;
messages.sendMultiMedia#f803138f flags:# silent:flags.5?true background:flags.6?true clear_draft:flags.7?true peer:InputPeer reply_to_msg_id:flags.0?int multi_media:Vector<InputSingleMedia> schedule_date:flags.10?int send_as:flags.13?InputPeer = Updates;
messages.uploadEncryptedFile#5057c497 peer:InputEncryptedChat file:InputEncryptedFile = EncryptedFile;
messages.searchStickerSets#35705b8a flags:# exclude_featured:flags.0?true q:string hash:long = messages.FoundStickerSets;
messages.getSplitRanges#1cff7e08 = Vector<MessageRange>;
messages.markDialogUnread#c286d98f flags:# unread:flags.0?true peer:InputDialogPeer = Bool;
messages.getDialogUnreadMarks#22e24e22 = Vector<DialogPeer>;
messages.clearAllDrafts#7e58ee9c = Bool;
messages.updatePinnedMessage#d2aaf7ec flags:# silent:flags.0?true unpin:flags.1?true pm_oneside:flags.2?true peer:InputPeer id:int = Updates;
messages.sendVote#10ea6184 peer:InputPeer msg_id:int options:Vector<bytes> = Updates;
messages.getPollResults#73bb643b peer:InputPeer msg_id:int = Updates;
messages.getOnlines#6e2be050 peer:InputPeer = ChatOnlines;
messages.editChatAbout#def60797 peer:InputPeer about:string = Bool;
messages.editChatDefaultBannedRights#a5866b41 peer:InputPeer banned_rights:ChatBannedRights = Updates;
messages.getEmojiKeywords#35a0e062 lang_code:string = EmojiKeywordsDifference;
messages.getEmojiKeywordsDifference#1508b6af lang_code:string from_version:int = EmojiKeywordsDifference;
messages.getEmojiKeywordsLanguages#4e9963b2 lang_codes:Vector<string> = Vector<EmojiLanguage>;
messages.getEmojiURL#d5b10c26 lang_code:string = EmojiURL;
messages.getSearchCounters#732eef00 peer:InputPeer filters:Vector<MessagesFilter> = Vector<messages.SearchCounter>;
messages.requestUrlAuth#198fb446 flags:# peer:flags.1?InputPeer msg_id:flags.1?int button_id:flags.1?int url:flags.2?string = UrlAuthResult;
messages.acceptUrlAuth#b12c7125 flags:# write_allowed:flags.0?true peer:flags.1?InputPeer msg_id:flags.1?int button_id:flags.1?int url:flags.2?string = UrlAuthResult;
messages.hidePeerSettingsBar#4facb138 peer:InputPeer = Bool;
messages.getScheduledHistory#f516760b peer:InputPeer hash:long = messages.Messages;
messages.getScheduledMessages#bdbb0464 peer:InputPeer id:Vector<int> = messages.Messages;
messages.sendScheduledMessages#bd38850a peer:InputPeer id:Vector<int> = Updates;
messages.deleteScheduledMessages#59ae2b16 peer:InputPeer id:Vector<int> = Updates;
messages.getPollVotes#b86e380e flags:# peer:InputPeer id:int option:flags.0?bytes offset:flags.1?string limit:int = messages.VotesList;
messages.toggleStickerSets#b5052fea flags:# uninstall:flags.0?true archive:flags.1?true unarchive:flags.2?true stickersets:Vector<InputStickerSet> = Bool;
messages.getDialogFilters#f19ed96d = Vector<DialogFilter>;
messages.getSuggestedDialogFilters#a29cd42c = Vector<DialogFilterSuggested>;
messages.updateDialogFilter#1ad4a04a flags:# id:int filter:flags.0?DialogFilter = Bool;
messages.updateDialogFiltersOrder#c563c1e4 order:Vector<int> = Bool;
messages.getOldFeaturedStickers#7ed094a1 offset:int limit:int hash:long = messages.FeaturedStickers;
messages.getReplies#22ddd30c peer:InputPeer msg_id:int offset_id:int offset_date:int add_offset:int limit:int max_id:int min_id:int hash:long = messages.Messages;
messages.getDiscussionMessage#446972fd peer:InputPeer msg_id:int = messages.DiscussionMessage;
messages.readDiscussion#f731a9f4 peer:InputPeer msg_id:int read_max_id:int = Bool;
messages.unpinAllMessages#f025bc8b peer:InputPeer = messages.AffectedHistory;
messages.deleteChat#5bd0ee50 chat_id:long = Bool;
messages.deletePhoneCallHistory#f9cbe409 flags:# revoke:flags.0?true = messages.AffectedFoundMessages;
messages.checkHistoryImport#43fe19f3 import_head:string = messages.HistoryImportParsed;
messages.initHistoryImport#34090c3b peer:InputPeer file:InputFile media_count:int = messages.HistoryImport;
messages.uploadImportedMedia#2a862092 peer:InputPeer import_id:long file_name:string media:InputMedia = MessageMedia;
messages.startHistoryImport#b43df344 peer:InputPeer import_id:long = Bool;
messages.getExportedChatInvites#a2b5a3f6 flags:# revoked:flags.3?true peer:InputPeer admin_id:InputUser offset_date:flags.2?int offset_link:flags.2?string limit:int = messages.ExportedChatInvites;
messages.getExportedChatInvite#73746f5c peer:InputPeer link:string = messages.ExportedChatInvite;
messages.editExportedChatInvite#bdca2f75 flags:# revoked:flags.2?true peer:InputPeer link:string expire_date:flags.0?int usage_limit:flags.1?int request_needed:flags.3?Bool title:flags.4?string = messages.ExportedChatInvite;
messages.deleteRevokedExportedChatInvites#56987bd5 peer:InputPeer admin_id:InputUser = Bool;
messages.deleteExportedChatInvite#d464a42b peer:InputPeer link:string = Bool;
messages.getAdminsWithInvites#3920e6ef peer:InputPeer = messages.ChatAdminsWithInvites;
messages.getChatInviteImporters#df04dd4e flags:# requested:flags.0?true peer:InputPeer link:flags.1?string q:flags.2?string offset_date:int offset_user:InputUser limit:int = messages.ChatInviteImporters;
messages.setHistoryTTL#b80e5fe4 peer:InputPeer period:int = Updates;
messages.checkHistoryImportPeer#5dc60f03 peer:InputPeer = messages.CheckedHistoryImportPeer;
messages.setChatTheme#e63be13f peer:InputPeer emoticon:string = Updates;
messages.getMessageReadParticipants#2c6f97b7 peer:InputPeer msg_id:int = Vector<long>;
messages.getSearchResultsCalendar#49f0bde9 peer:InputPeer filter:MessagesFilter offset_id:int offset_date:int = messages.SearchResultsCalendar;
messages.getSearchResultsPositions#6e9583a3 peer:InputPeer filter:MessagesFilter offset_id:int limit:int = messages.SearchResultsPositions;
messages.hideChatJoinRequest#7fe7e815 flags:# approved:flags.0?true peer:InputPeer user_id:InputUser = Updates;
messages.hideAllChatJoinRequests#e085f4ea flags:# approved:flags.0?true peer:InputPeer link:flags.1?string = Updates;
messages.toggleNoForwards#b11eafa2 peer:InputPeer enabled:Bool = Updates;
messages.saveDefaultSendAs#ccfddf96 peer:InputPeer send_as:InputPeer = Bool;

updates.getState#edd4882a = updates.State;
updates.getDifference#25939651 flags:# pts:int pts_total_limit:flags.0?int date:int qts:int = updates.Difference;
updates.getChannelDifference#3173d78 flags:# force:flags.0?true channel:InputChannel filter:ChannelMessagesFilter pts:int limit:int = updates.ChannelDifference;

photos.updateProfilePhoto#72d4742c id:InputPhoto = photos.Photo;
photos.uploadProfilePhoto#89f30f69 flags:# file:flags.0?InputFile video:flags.1?InputFile video_start_ts:flags.2?double = photos.Photo;
photos.deletePhotos#87cf7f2f id:Vector<InputPhoto> = Vector<long>;
photos.getUserPhotos#91cd32a8 user_id:InputUser offset:int max_id:long limit:int = photos.Photos;

upload.saveFilePart#b304a621 file_id:long file_part:int bytes:bytes = Bool;
upload.getFile#b15a9afc flags:# precise:flags.0?true cdn_supported:flags.1?true location:InputFileLocation offset:int limit:int = upload.File;
upload.saveBigFilePart#de7b673d file_id:long file_part:int file_total_parts:int bytes:bytes = Bool;
upload.getWebFile#24e6818d location:InputWebFileLocation offset:int limit:int = upload.WebFile;
upload.getCdnFile#2000bcc3 file_token:bytes offset:int limit:int = upload.CdnFile;
upload.reuploadCdnFile#9b2754a8 file_token:bytes request_token:bytes = Vector<FileHash>;
upload.getCdnFileHashes#4da54231 file_token:bytes offset:int = Vector<FileHash>;
upload.getFileHashes#c7025931 location:InputFileLocation offset:int = Vector<FileHash>;

help.getConfig#c4f9186b = Config;
help.getNearestDc#1fb33026 = NearestDc;
help.getAppUpdate#522d5a7d source:string = help.AppUpdate;
help.getInviteText#4d392343 = help.InviteText;
help.getSupport#9cdf08cd = help.Support;
help.getAppChangelog#9010ef6f prev_app_version:string = Updates;
help.setBotUpdatesStatus#ec22cfcd pending_updates_count:int message:string = Bool;
help.getCdnConfig#52029342 = CdnConfig;
help.getRecentMeUrls#3dc0f114 referer:string = help.RecentMeUrls;
help.getTermsOfServiceUpdate#2ca51fd1 = help.TermsOfServiceUpdate;
help.acceptTermsOfService#ee72f79a id:DataJSON = Bool;
help.getDeepLinkInfo#3fedc75f path:string = help.DeepLinkInfo;
help.getAppConfig#98914110 = JSONValue;
help.saveAppLog#6f02f748 events:Vector<InputAppEvent> = Bool;
help.getPassportConfig#c661ad08 hash:int = help.PassportConfig;
help.getSupportName#d360e72c = help.SupportName;
help.getUserInfo#38a08d3 user_id:InputUser = help.UserInfo;
help.editUserInfo#66b91b70 user_id:InputUser message:string entities:Vector<MessageEntity> = help.UserInfo;
help.getPromoData#c0977421 = help.PromoData;
help.hidePromoData#1e251c95 peer:InputPeer = Bool;
help.dismissSuggestion#f50dbaa1 peer:InputPeer suggestion:string = Bool;
help.getCountriesList#735787a8 lang_code:string hash:int = help.CountriesList;

channels.readHistory#cc104937 channel:InputChannel max_id:int = Bool;
channels.deleteMessages#84c1fd4e channel:InputChannel id:Vector<int> = messages.AffectedMessages;
channels.reportSpam#f44a8315 channel:InputChannel participant:InputPeer id:Vector<int> = Bool;
channels.getMessages#ad8c9a23 channel:InputChannel id:Vector<InputMessage> = messages.Messages;
channels.getParticipants#77ced9d0 channel:InputChannel filter:ChannelParticipantsFilter offset:int limit:int hash:long = channels.ChannelParticipants;
channels.getParticipant#a0ab6cc6 channel:InputChannel participant:InputPeer = channels.ChannelParticipant;
channels.getChannels#a7f6bbb id:Vector<InputChannel> = messages.Chats;
channels.getFullChannel#8736a09 channel:InputChannel = messages.ChatFull;
channels.createChannel#3d5fb10f flags:# broadcast:flags.0?true megagroup:flags.1?true for_import:flags.3?true title:string about:string geo_point:flags.2?InputGeoPoint address:flags.2?string = Updates;
channels.editAdmin#d33c8902 channel:InputChannel user_id:InputUser admin_rights:ChatAdminRights rank:string = Updates;
channels.editTitle#566decd0 channel:InputChannel title:string = Updates;
channels.editPhoto#f12e57c9 channel:InputChannel photo:InputChatPhoto = Updates;
channels.checkUsername#10e6bd2c channel:InputChannel username:string = Bool;
channels.updateUsername#3514b3de channel:InputChannel username:string = Bool;
channels.joinChannel#24b524c5 channel:InputChannel = Updates;
channels.leaveChannel#f836aa95 channel:InputChannel = Updates;
channels.inviteToChannel#199f3a6c channel:InputChannel users:Vector<InputUser> = Updates;
channels.deleteChannel#c0111fe3 channel:InputChannel = Updates;
channels.exportMessageLink#e63fadeb flags:# grouped:flags.0?true thread:flags.1?true channel:InputChannel id:int = ExportedMessageLink;
channels.toggleSignatures#1f69b606 channel:InputChannel enabled:Bool = Updates;
channels.getAdminedPublicChannels#f8b036af flags:# by_location:flags.0?true check_limit:flags.1?true = messages.Chats;
channels.editBanned#96e6cd81 channel:InputChannel participant:InputPeer banned_rights:ChatBannedRights = Updates;
channels.getAdminLog#33ddf480 flags:# channel:InputChannel q:string events_filter:flags.0?ChannelAdminLogEventsFilter admins:flags.1?Vector<InputUser> max_id:long min_id:long limit:int = channels.AdminLogResults;
channels.setStickers#ea8ca4f9 channel:InputChannel stickerset:InputStickerSet = Bool;
channels.readMessageContents#eab5dc38 channel:InputChannel id:Vector<int> = Bool;
channels.deleteHistory#af369d42 channel:InputChannel max_id:int = Bool;
channels.togglePreHistoryHidden#eabbb94c channel:InputChannel enabled:Bool = Updates;
channels.getLeftChannels#8341ecc0 offset:int = messages.Chats;
channels.getGroupsForDiscussion#f5dad378 = messages.Chats;
channels.setDiscussionGroup#40582bb2 broadcast:InputChannel group:InputChannel = Bool;
channels.editCreator#8f38cd1f channel:InputChannel user_id:InputUser password:InputCheckPasswordSRP = Updates;
channels.editLocation#58e63f6d channel:InputChannel geo_point:InputGeoPoint address:string = Bool;
channels.toggleSlowMode#edd49ef0 channel:InputChannel seconds:int = Updates;
channels.getInactiveChannels#11e831ee = messages.InactiveChats;
channels.convertToGigagroup#b290c69 channel:InputChannel = Updates;
channels.viewSponsoredMessage#beaedb94 channel:InputChannel random_id:bytes = Bool;
channels.getSponsoredMessages#ec210fbf channel:InputChannel = messages.SponsoredMessages;
channels.getSendAs#dc770ee peer:InputPeer = channels.SendAsPeers;
channels.deleteParticipantHistory#367544db channel:InputChannel participant:InputPeer = messages.AffectedHistory;

bots.sendCustomRequest#aa2769ed custom_method:string params:DataJSON = DataJSON;
bots.answerWebhookJSONQuery#e6213f4d query_id:long data:DataJSON = Bool;
bots.setBotCommands#517165a scope:BotCommandScope lang_code:string commands:Vector<BotCommand> = Bool;
bots.resetBotCommands#3d8de0f9 scope:BotCommandScope lang_code:string = Bool;
bots.getBotCommands#e34c0dd6 scope:BotCommandScope lang_code:string = Vector<BotCommand>;

payments.getPaymentForm#8a333c8d flags:# peer:InputPeer msg_id:int theme_params:flags.0?DataJSON = payments.PaymentForm;
payments.getPaymentReceipt#2478d1cc peer:InputPeer msg_id:int = payments.PaymentReceipt;
payments.validateRequestedInfo#db103170 flags:# save:flags.0?true peer:InputPeer msg_id:int info:PaymentRequestedInfo = payments.ValidatedRequestedInfo;
payments.sendPaymentForm#30c3bc9d flags:# form_id:long peer:InputPeer msg_id:int requested_info_id:flags.0?string shipping_option_id:flags.1?string credentials:InputPaymentCredentials tip_amount:flags.2?long = payments.PaymentResult;
payments.getSavedInfo#227d824b = payments.SavedInfo;
payments.clearSavedInfo#d83d70c1 flags:# credentials:flags.0?true info:flags.1?true = Bool;
payments.getBankCardData#2e79d779 number:string = payments.BankCardData;

stickers.createStickerSet#9021ab67 flags:# masks:flags.0?true animated:flags.1?true user_id:InputUser title:string short_name:string thumb:flags.2?InputDocument stickers:Vector<InputStickerSetItem> software:flags.3?string = messages.StickerSet;
stickers.removeStickerFromSet#f7760f51 sticker:InputDocument = messages.StickerSet;
stickers.changeStickerPosition#ffb6d4ca sticker:InputDocument position:int = messages.StickerSet;
stickers.addStickerToSet#8653febe stickerset:InputStickerSet sticker:InputStickerSetItem = messages.StickerSet;
stickers.setStickerSetThumb#9a364e30 stickerset:InputStickerSet thumb:InputDocument = messages.StickerSet;
stickers.checkShortName#284b3639 short_name:string = Bool;
stickers.suggestShortName#4dafc503 title:string = stickers.SuggestedShortName;

phone.getCallConfig#55451fa9 = DataJSON;
phone.requestCall#42ff96ed flags:# video:flags.0?true user_id:InputUser random_id:int g_a_hash:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
phone.acceptCall#3bd2b4a0 peer:InputPhoneCall g_b:bytes protocol:PhoneCallProtocol = phone.PhoneCall;
phone.confirmCall#2efe1722 peer:InputPhoneCall g_a:bytes key_fingerprint:long protocol:PhoneCallProtocol = phone.PhoneCall;
phone.receivedCall#17d54f61 peer:InputPhoneCall = Bool;
phone.discardCall#b2cbc1c0 flags:# video:flags.0?true peer:InputPhoneCall duration:int reason:PhoneCallDiscardReason connection_id:long = Updates;
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
phone.sendSignalingData#ff7a9383 peer:InputPhoneCall data:bytes = Bool;
phone.createGroupCall#48cdc6d8 flags:# peer:InputPeer random_id:int title:flags.0?string schedule_date:flags.1?int = Updates;
phone.joinGroupCall#b132ff7b flags:# muted:flags.0?true video_stopped:flags.2?true call:InputGroupCall join_as:InputPeer invite_hash:flags.1?string params:DataJSON = Updates;
phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates;
phone.inviteToGroupCall#7b393160 call:InputGroupCall users:Vector<InputUser> = Updates;
phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
phone.toggleGroupCallSettings#74bbb43d flags:# reset_invite_hash:flags.1?true call:InputGroupCall join_muted:flags.0?Bool = Updates;
phone.getGroupCall#41845db call:InputGroupCall limit:int = phone.GroupCall;
phone.getGroupParticipants#c558d8ab call:InputGroupCall ids:Vector<InputPeer> sources:Vector<int> offset:string limit:int = phone.GroupParticipants;
phone.checkGroupCall#b59cf977 call:InputGroupCall sources:Vector<int> = Vector<int>;
phone.toggleGroupCallRecord#f128c708 flags:# start:flags.0?true video:flags.2?true call:InputGroupCall title:flags.1?string video_portrait:flags.2?Bool = Updates;
phone.editGroupCallParticipant#a5273abf flags:# call:InputGroupCall participant:InputPeer muted:flags.0?Bool volume:flags.1?int raise_hand:flags.2?Bool video_stopped:flags.3?Bool video_paused:flags.4?Bool presentation_paused:flags.5?Bool = Updates;
phone.editGroupCallTitle#1ca6ac0a call:InputGroupCall title:string = Updates;
phone.getGroupCallJoinAs#ef7c213a peer:InputPeer = phone.JoinAsPeers;
phone.exportGroupCallInvite#e6aa647f flags:# can_self_unmute:flags.0?true call:InputGroupCall = phone.ExportedGroupCallInvite;
phone.toggleGroupCallStartSubscription#219c34e6 call:InputGroupCall subscribed:Bool = Updates;
phone.startScheduledGroupCall#5680e342 call:InputGroupCall = Updates;
phone.saveDefaultGroupCallJoinAs#575e1f8c peer:InputPeer join_as:InputPeer = Bool;
phone.joinGroupCallPresentation#cbea6bc4 call:InputGroupCall params:DataJSON = Updates;
phone.leaveGroupCallPresentation#1c50d144 call:InputGroupCall = Updates;

langpack.getLangPack#f2f2330a lang_pack:string lang_code:string = LangPackDifference;
langpack.getStrings#efea3803 lang_pack:string lang_code:string keys:Vector<string> = Vector<LangPackString>;
langpack.getDifference#cd984aa5 lang_pack:string lang_code:string from_version:int = LangPackDifference;
langpack.getLanguages#42c6978f lang_pack:string = Vector<LangPackLanguage>;
langpack.getLanguage#6a596502 lang_pack:string lang_code:string = LangPackLanguage;

folders.editPeerFolders#6847d0ab folder_peers:Vector<InputFolderPeer> = Updates;
folders.deleteFolder#1c295881 folder_id:int = Updates;

stats.getBroadcastStats#ab42441a flags:# dark:flags.0?true channel:InputChannel = stats.BroadcastStats;
stats.loadAsyncGraph#621d5fa0 flags:# token:string x:flags.0?long = StatsGraph;
stats.getMegagroupStats#dcdf8607 flags:# dark:flags.0?true channel:InputChannel = stats.MegagroupStats;
stats.getMessagePublicForwards#5630281b channel:InputChannel msg_id:int offset_rate:int offset_peer:InputPeer offset_id:int limit:int = messages.Messages;
stats.getMessageStats#b6e0a3f5 flags:# dark:flags.0?true channel:InputChannel msg_id:int = stats.MessageStats;

// LAYER 135
<?php

/**
 * RSA module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use danog\MadelineProto\TL\TL;
use phpseclib3\Math\BigInteger;
/**
 * RSA class.
 */
class RSA
{
    use \danog\Serializable;
    /**
     * Exponent.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    public $e;
    /**
     * Modulus.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    public $n;
    /**
     * Fingerprint.
     *
     * @var string
     */
    public $fp;
    /**
     * Load RSA key.
     *
     * @param TL $TL TL serializer
     * @param string $rsa_key RSA key
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (array | mixed), mixed, self>
     */
    public static function load(TL $TL, string $rsa_key) : \Generator
    {
        $key = \phpseclib3\Crypt\RSA::load($rsa_key);
        $instance = new self();
        $instance->n = Tools::getVar($key, 'modulus');
        $instance->e = Tools::getVar($key, 'exponent');
        $instance->fp = \Phabel\Target\Php80\Polyfill::substr(\sha1((yield from $TL->serializeObject(['type' => 'bytes'], $instance->n->toBytes(), 'key')) . (yield from $TL->serializeObject(['type' => 'bytes'], $instance->e->toBytes(), 'key')), true), -8);
        return $instance;
    }
    /**
     * Private constructor.
     */
    private function __construct()
    {
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep() : array
    {
        return ['e', 'n', 'fp'];
    }
    /**
     *
     */
    public function __wakeup()
    {
        foreach ($this->__sleep() as $bigint) {
            if ($this->{$bigint} instanceof \tgseclib\Math\BigInteger) {
                $this->{$bigint} = $this->{$bigint}->real;
            }
        }
    }
    /**
     * Encrypt data.
     *
     * @param BigInteger $data Data to encrypt
     *
     * @return string
     */
    public function encrypt(BigInteger $data) : string
    {
        return \str_pad($data->powMod($this->e, $this->n)->toBytes(), 256, "\x00", STR_PAD_LEFT);
    }
}<?php

/**
 * Exception module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * Basic exception.
 */
class Exception extends \Exception
{
    use TL\PrettyException;
    /**
     *
     */
    public function __toString()
    {
        return $this->file === 'MadelineProto' ? $this->message : '\\danog\\MadelineProto\\Exception' . ($this->message !== '' ? ': ' : '') . $this->message . ' in ' . $this->file . ':' . $this->line . PHP_EOL . \danog\MadelineProto\Magic::$revision . PHP_EOL . 'TL Trace:' . PHP_EOL . $this->getTLTrace();
    }
    /**
     *
     */
    public function __construct($message = null, $code = 0, self $previous = null, $file = null, $line = null)
    {
        $this->prettifyTL();
        if ($file !== null) {
            $this->file = $file;
        }
        if ($line !== null) {
            $this->line = $line;
        }
        parent::__construct($message, $code, $previous);
        if (\strpos($message, 'socket_accept') === false && !\in_array(\basename($this->file), ['PKCS8.php', 'PSS.php'])) {
            \danog\MadelineProto\Logger::log($message . ' in ' . \basename($this->file) . ':' . $this->line, \danog\MadelineProto\Logger::FATAL_ERROR);
        }
        if (\in_array($message, ['The session is corrupted!', 'Re-executing query...', 'I had to recreate the temporary authorization key', 'This peer is not present in the internal peer database', "Couldn't get response", 'Chat forbidden', 'The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.', 'File does not exist', 'Please install this fork of phpseclib: https://github.com/danog/tgseclib'])) {
            return;
        }
        if (\strpos($message, 'pg_query') !== false || \strpos($message, 'Undefined variable: ') !== false || \strpos($message, 'socket_write') !== false || \strpos($message, 'socket_read') !== false || \strpos($message, 'Received request to switch to DC ') !== false || \strpos($message, "Couldn't get response") !== false || \strpos($message, 'Re-executing query...') !== false || \strpos($message, "Couldn't find peer by provided") !== false || \strpos($message, 'id.pwrtelegram.xyz') !== false || \strpos($message, 'Please update ') !== false || \strpos($message, 'posix_isatty') !== false) {
            return;
        }
    }
    /**
     * Complain about missing extensions.
     *
     * @param string $extensionName Extension name
     *
     * @return self
     */
    public static function extension(string $extensionName) : self
    {
        $additional = 'Try running sudo apt-get install php' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '-' . $extensionName . '.';
        if ($extensionName === 'libtgvoip') {
            $additional = 'Follow the instructions @ https://voip.madelineproto.xyz to install it.';
        } elseif ($extensionName === 'prime') {
            $additional = 'Follow the instructions @ https://prime.madelineproto.xyz to install it.';
        }
        $message = 'MadelineProto requires the ' . $extensionName . ' extension to run. ' . $additional;
        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
            echo $message . '<br>';
        }
        $file = 'MadelineProto';
        $line = 1;
        return new self($message, 0, null, $file, $line);
    }
    /**
     * ExceptionErrorHandler.
     *
     * Error handler
     *
     * @return false
     */
    public static function exceptionErrorHandler($errno = 0, $errstr = null, $errfile = null, $errline = null) : bool
    {
        $errfileReplaced = \preg_replace('/phabel-transpiler\\d+\\./', '', $errfile ?? '');
        // If error is suppressed with @, don't throw an exception
        if (\Phabel\Target\Php80\Polyfill::error_reporting() === 0 || \strpos($errstr, 'headers already sent') || \strpos($errstr, 'Creation of dynamic property') !== false || $errfileReplaced && (\strpos($errfileReplaced, DIRECTORY_SEPARATOR . 'amphp' . DIRECTORY_SEPARATOR) !== false || \strpos($errfileReplaced, DIRECTORY_SEPARATOR . 'league' . DIRECTORY_SEPARATOR) !== false || \strpos($errfileReplaced, DIRECTORY_SEPARATOR . 'phpseclib' . DIRECTORY_SEPARATOR) !== false)) {
            return false;
        }
        throw new self($errstr, $errno, null, $errfile, $errline);
    }
    /**
     * ExceptionErrorHandler.
     *
     * Error handler
     *
     * @return void
     */
    public static function exceptionHandler($exception) : void
    {
        Logger::log($exception, Logger::FATAL_ERROR);
        Magic::shutdown(1);
    }
}<?php

/**
 * Reliable module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoSession;

use danog\MadelineProto\MTProto;
use danog\MadelineProto\Tools;
/**
 * Manages responses.
 */
trait Reliable
{
    /**
     * Called when receiving a new_msg_detailed_info.
     *
     * @param array $content
     * @return void
     */
    public function onNewMsgDetailedInfo(array $content) : void
    {
        if (isset($this->incoming_messages[$content['answer_msg_id']])) {
            $this->ackIncomingMessage($this->incoming_messages[$content['answer_msg_id']]);
        } else {
            Tools::callFork($this->objectCall('msg_resend_req', ['msg_ids' => [$content['answer_msg_id']]], ['postpone' => true]));
        }
    }
    /**
     * Called when receiving a msg_detailed_info.
     *
     * @param array $content
     * @return void
     */
    public function onMsgDetailedInfo(array $content) : void
    {
        if (isset($this->outgoing_messages[$content['msg_id']])) {
            $this->onNewMsgDetailedInfo($content);
        }
    }
    /**
     * Called when receiving a msg_resend_req.
     *
     * @param array $content
     * @param string $current_msg_id
     * @return void
     */
    public function onMsgResendReq(array $content, $current_msg_id) : void
    {
        $ok = true;
        foreach ($content['msg_ids'] as $msg_id) {
            if (!isset($this->outgoing_messages[$msg_id]) || isset($this->incoming_messages[$msg_id])) {
                $ok = false;
            }
        }
        if ($ok) {
            foreach ($content['msg_ids'] as $msg_id) {
                $this->methodRecall('', ['message_id' => $msg_id, 'postpone' => true]);
            }
        } else {
            $this->sendMsgsStateInfo($content['msg_ids'], $current_msg_id);
        }
    }
    /**
     * Called when receiving a msg_resend_ans_req.
     *
     * @param array $content
     * @param string $current_msg_id
     * @return void
     */
    public function onMsgResendAnsReq(array $content, $current_msg_id) : void
    {
        $this->sendMsgsStateInfo($content['msg_ids'], $current_msg_id);
    }
    /**
     * Called when receiving a msgs_all_info.
     *
     * @param array $content
     * @return void
     */
    public function onMsgsAllInfo(array $content) : void
    {
        foreach ($content['msg_ids'] as $key => $msg_id) {
            $info = \ord($content['info'][$key]);
            $msg_id = MsgIdHandler::toString($msg_id);
            $status = 'Status for message id ' . $msg_id . ': ';
            /*if ($info & 4) {
             *$this->gotResponseForOutgoingMessageId($msg_id);
             *}
             */
            foreach (MTProto::MSGS_INFO_FLAGS as $flag => $description) {
                if (($info & $flag) !== 0) {
                    $status .= $description;
                }
            }
            $this->logger->logger($status, \danog\MadelineProto\Logger::NOTICE);
        }
    }
    /**
     * Send state info for message IDs.
     *
     * @param array $msg_ids Message IDs to send info about
     * @param (string | int) $req_msg_id Message ID of msgs_state_req that initiated this
     *
     * @return void
     */
    public function sendMsgsStateInfo(array $msg_ids, $req_msg_id) : void
    {
        $this->logger->logger('Sending state info for ' . \count($msg_ids) . ' message IDs');
        $info = '';
        foreach ($msg_ids as $msg_id) {
            $cur_info = 0;
            if (!isset($this->incoming_messages[$msg_id])) {
                $msg_id = new \phpseclib3\Math\BigInteger(\strrev($msg_id), 256);
                if ((new \phpseclib3\Math\BigInteger(\time() + $this->time_delta + 30))->bitwise_leftShift(32)->compare($msg_id) < 0) {
                    $this->logger->logger("Do not know anything about {$msg_id} and it is too big");
                    $cur_info |= 3;
                } elseif ((new \phpseclib3\Math\BigInteger(\time() + $this->time_delta - 300))->bitwise_leftShift(32)->compare($msg_id) > 0) {
                    $this->logger->logger("Do not know anything about {$msg_id} and it is too small");
                    $cur_info |= 1;
                } else {
                    $this->logger->logger("Do not know anything about {$msg_id}");
                    $cur_info |= 2;
                }
            } else {
                $this->logger->logger("Know about {$msg_id}");
                $cur_info = $this->incoming_messages[$msg_id]->getState();
            }
            $info .= \chr($cur_info);
        }
        Tools::callFork($this->objectCall('msgs_state_info', ['req_msg_id' => $req_msg_id, 'info' => $info], ['postpone' => true]));
    }
}<?php

/**
 * Session module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoSession;

use danog\MadelineProto\Connection;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProto\IncomingMessage;
use danog\MadelineProto\MTProto\OutgoingMessage;
/**
 * Manages MTProto session-specific data.
 *
 * @extends Connection
 */
trait Session
{
    use AckHandler;
    use ResponseHandler;
    use SeqNoHandler;
    use CallHandler;
    use Reliable;
    /**
     * Incoming message array.
     *
     * @var IncomingMessage[]
     */
    public $incoming_messages = [];
    /**
     * Outgoing message array.
     *
     * @var OutgoingMessage[]
     */
    public $outgoing_messages = [];
    /**
     * New incoming message ID array.
     *
     * @var IncomingMessage[]
     */
    public $new_incoming = [];
    /**
     * New outgoing message array.
     *
     * @var OutgoingMessage[]
     */
    public $new_outgoing = [];
    /**
     * Pending outgoing messages.
     *
     * @var OutgoingMessage[]
     */
    public $pendingOutgoing = [];
    /**
     * Pending outgoing key.
     *
     * @var string
     */
    public $pendingOutgoingKey = 'a';
    /**
     * Time delta with server.
     *
     * @var integer
     */
    public $time_delta = 0;
    /**
     * Call queue.
     *
     * @var array
     */
    public $call_queue = [];
    /**
     * Ack queue.
     *
     * @var array
     */
    public $ack_queue = [];
    /**
     * Message ID handler.
     *
     * @var MsgIdHandler
     */
    public $msgIdHandler;
    /**
     * Reset MTProto session.
     *
     * @return void
     */
    public function resetSession() : void
    {
        $this->API->logger->logger("Resetting session in DC {$this->datacenterId}...", \danog\MadelineProto\Logger::WARNING);
        $this->session_id = \danog\MadelineProto\Tools::random(8);
        $this->session_in_seq_no = 0;
        $this->session_out_seq_no = 0;
        if (!isset($this->msgIdHandler)) {
            $this->msgIdHandler = MsgIdHandler::createInstance($this);
        }
        foreach ($this->outgoing_messages as &$msg) {
            if ($msg->hasMsgId()) {
                $msg->setMsgId(null);
            }
            if ($msg->hasSeqNo()) {
                $msg->setSeqNo(null);
            }
        }
    }
    /**
     * Cleanup incoming and outgoing messages.
     *
     * @return void
     */
    public function cleanupSession() : void
    {
        $count = 0;
        $incoming = [];
        foreach ($this->incoming_messages as $key => $message) {
            if ($message->canGarbageCollect()) {
                $count++;
            } else {
                $this->API->logger->logger("Can't garbage collect {$message}, not handled yet!", \danog\MadelineProto\Logger::VERBOSE);
                $incoming[$key] = $message;
            }
        }
        $this->incoming_messages = $incoming;
        $total = \count($this->incoming_messages);
        if ($count + $total) {
            $this->API->logger->logger("Garbage collected {$count} incoming messages, {$total} left", \danog\MadelineProto\Logger::VERBOSE);
        }
        $count = 0;
        $outgoing = [];
        foreach ($this->outgoing_messages as $key => $message) {
            if ($message->canGarbageCollect()) {
                $count++;
            } else {
                $ago = \time() - $message->getSent();
                if ($ago > 2) {
                    $this->API->logger->logger("Can't garbage collect {$message} sent {$ago} seconds ago, no response has been received or it wasn't yet handled!", \danog\MadelineProto\Logger::VERBOSE);
                }
                $outgoing[$key] = $message;
            }
        }
        $this->outgoing_messages = $outgoing;
        $total = \count($this->outgoing_messages);
        if ($count + $total) {
            $this->API->logger->logger("Garbage collected {$count} outgoing messages, {$total} left", \danog\MadelineProto\Logger::VERBOSE);
        }
    }
    /**
     * Create MTProto session if needed.
     *
     * @return void
     */
    public function createSession() : void
    {
        if ($this->session_id === null) {
            $this->resetSession();
        }
    }
    /**
     * Backup eventual unsent messages before session deletion.
     *
     * @return OutgoingMessage[]
     */
    public function backupSession() : array
    {
        $pending = \array_values($this->pendingOutgoing);
        return \array_merge($pending, $this->new_outgoing);
    }
}<?php

/**
 * SeqNoHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoSession;

use danog\MadelineProto\MTProto\IncomingMessage;
/**
 * Manages sequence number.
 */
trait SeqNoHandler
{
    public $session_out_seq_no = 0;
    public $session_in_seq_no = 0;
    public $session_id;
    /**
     *
     */
    public function generateOutSeqNo($contentRelated)
    {
        $in = $contentRelated ? 1 : 0;
        $value = $this->session_out_seq_no;
        $this->session_out_seq_no += $in;
        //$this->API->logger->logger("OUT: $value + $in = ".$this->session_out_seq_no);
        return $value * 2 + $in;
    }
    /**
     *
     */
    public function checkInSeqNo(IncomingMessage $message) : void
    {
        if ($message->hasSeqNo()) {
            $seq_no = $this->generateInSeqNo($message->isContentRelated());
            if ($seq_no !== $message->getSeqNo()) {
                if ($message->isContentRelated()) {
                    $this->session_in_seq_no -= 1;
                }
                $this->API->logger->logger('SECURITY WARNING: Seqno mismatch (should be ' . $seq_no . ', is ' . $message->getSeqNo() . ", {$message})", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
            }
        }
    }
    /**
     *
     */
    public function generateInSeqNo($contentRelated)
    {
        $in = $contentRelated ? 1 : 0;
        $value = $this->session_in_seq_no;
        $this->session_in_seq_no += $in;
        //$this->API->logger->logger("IN: $value + $in = ".$this->session_in_seq_no);
        return $value * 2 + $in;
    }
    /**
     *
     */
    public function contentRelated($method) : bool
    {
        $method = \is_array($method) && isset($method['_']) ? $method['_'] : $method;
        return \is_string($method) ? !\in_array($method, [
            //'rpc_result',
            //'rpc_error',
            'rpc_drop_answer',
            'rpc_answer_unknown',
            'rpc_answer_dropped_running',
            'rpc_answer_dropped',
            'get_future_salts',
            'future_salt',
            'future_salts',
            'ping',
            'pong',
            'ping_delay_disconnect',
            'destroy_session',
            'destroy_session_ok',
            'destroy_session_none',
            //'new_session_created',
            'msg_container',
            'msg_copy',
            'gzip_packed',
            'http_wait',
            'msgs_ack',
            'bad_msg_notification',
            'bad_server_salt',
            'msgs_state_req',
            'msgs_state_info',
            'msgs_all_info',
            'msg_detailed_info',
            'msg_new_detailed_info',
            'msg_resend_req',
            'msg_resend_ans_req',
        ]) : true;
    }
}<?php

/**
 * CallHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoSession;

use Amp\Deferred;
use danog\MadelineProto\MTProto\Container;
use danog\MadelineProto\MTProto\OutgoingMessage;
use danog\MadelineProto\TL\Exception;
use danog\MadelineProto\Tools;
/**
 * Manages method and object calls.
 */
trait CallHandler
{
    /**
     * Recall method.
     *
     * @param string $watcherId Watcher ID for defer
     * @param array $args Args
     *
     * @return void
     */
    public function methodRecall(string $watcherId, array $args) : void
    {
        $message_id = $args['message_id'];
        $postpone = $args['postpone'] ?? false;
        $datacenter = $args['datacenter'] ?? false;
        if ($datacenter === $this->datacenter) {
            $datacenter = false;
        }
        $message_ids = ($this->outgoing_messages[$message_id] ?? null) instanceof Container ? $this->outgoing_messages[$message_id]->getIds() : [$message_id];
        foreach ($message_ids as $message_id) {
            if (isset($this->outgoing_messages[$message_id]) && !$this->outgoing_messages[$message_id]->canGarbageCollect()) {
                if ($datacenter) {
                    /** @var OutgoingMessage */
                    $message = $this->outgoing_messages[$message_id];
                    $this->gotResponseForOutgoingMessage($message);
                    $message->setMsgId(null);
                    $message->setSeqNo(null);
                    Tools::call($this->API->datacenter->waitGetConnection($datacenter))->onResolve(function ($e, $r) use($message) {
                        Tools::callFork($r->sendMessage($message, false));
                    });
                } else {
                    /** @var OutgoingMessage */
                    $message = $this->outgoing_messages[$message_id];
                    if (!$message->hasSeqNo()) {
                        $this->gotResponseForOutgoingMessage($message);
                    }
                    Tools::callFork($this->sendMessage($message, false));
                }
            } else {
                $this->logger->logger('Could not resend ' . ($this->outgoing_messages[$message_id] ?? $message_id));
            }
        }
        if (!$postpone) {
            if ($datacenter) {
                $this->API->datacenter->getDataCenterConnection($datacenter)->flush();
            } else {
                $this->flush();
            }
        }
    }
    /**
     * Call method and wait asynchronously for response.
     *
     * If the $aargs['noResponse'] is true, will not wait for a response.
     *
     * @param string $method Method name
     * @param (array | \Generator) $args Arguments
     * @param array $aargs Additional arguments
     *
     * @psalm-param (array | \Generator<mixed, mixed, mixed, array>) $args
     *
     * @return \Generator
     */
    public function methodCallAsyncRead(string $method, $args = [], array $aargs = ['msg_id' => null]) : \Generator
    {
        $readDeferred = (yield from $this->methodCallAsyncWrite($method, $args, $aargs));
        if (\is_array($readDeferred)) {
            $readDeferred = Tools::all(\array_map(fn(Deferred $value) => $value->promise(), $readDeferred));
        } else {
            $readDeferred = $readDeferred->promise();
        }
        if (!($aargs['noResponse'] ?? false)) {
            return (yield $readDeferred);
        }
    }
    /**
     * Call method and make sure it is asynchronously sent (generator).
     *
     * @param string $method Method name
     * @param (array | \Generator) $args Arguments
     * @param array $aargs Additional arguments
     *
     * @psalm-param (array | \Generator<mixed, mixed, mixed, array>) $args
     *
     * @return \Generator
     */
    public function methodCallAsyncWrite(string $method, $args = [], array $aargs = ['msg_id' => null]) : \Generator
    {
        if (\is_array($args) && isset($args['id']['_']) && isset($args['id']['dc_id']) && ($args['id']['_'] === 'inputBotInlineMessageID' || $args['id']['_'] === 'inputBotInlineMessageID64') && $this->datacenter != $args['id']['dc_id']) {
            $aargs['datacenter'] = $args['id']['dc_id'];
            return yield from $this->API->methodCallAsyncWrite($method, $args, $aargs);
        }
        if (($aargs['file'] ?? false) && !$this->isMedia() && $this->API->datacenter->has($this->datacenter . '_media')) {
            $this->logger->logger('Using media DC');
            $aargs['datacenter'] = $this->datacenter . '_media';
            return yield from $this->API->methodCallAsyncWrite($method, $args, $aargs);
        }
        if (\in_array($method, ['messages.setEncryptedTyping', 'messages.readEncryptedHistory', 'messages.sendEncrypted', 'messages.sendEncryptedFile', 'messages.sendEncryptedService', 'messages.receivedQueue'])) {
            $aargs['queue'] = 'secret';
        }
        if (\is_array($args)) {
            if (isset($args['multiple'])) {
                $aargs['multiple'] = true;
            }
            if (isset($args['message']) && \is_string($args['message']) && \mb_strlen($args['message'], 'UTF-8') > (yield from $this->API->getConfig())['message_length_max'] && \mb_strlen((yield from $this->API->parseMode($args))['message'], 'UTF-8') > (yield from $this->API->getConfig())['message_length_max']) {
                $args = (yield from $this->API->splitToChunks($args));
                $promises = [];
                $aargs['queue'] = $method;
                $aargs['multiple'] = true;
            }
            if (isset($aargs['multiple'])) {
                $new_aargs = $aargs;
                $new_aargs['postpone'] = true;
                unset($new_aargs['multiple']);
                if (isset($args['multiple'])) {
                    unset($args['multiple']);
                }
                $promises = [];
                foreach ($args as $single_args) {
                    $promises[] = Tools::call($this->methodCallAsyncWrite($method, $single_args, $new_aargs));
                }
                if (!isset($aargs['postpone'])) {
                    $this->writer->resume();
                }
                return (yield Tools::all($promises));
            }
            $args = (yield from $this->API->botAPIToMTProto($args));
            if (isset($args['ping_id']) && \is_int($args['ping_id'])) {
                $args['ping_id'] = Tools::packSignedLong($args['ping_id']);
            }
        }
        $methodInfo = $this->API->getTL()->getMethods()->findByMethod($method);
        if (!$methodInfo) {
            throw new Exception("Could not find method {$method}!");
        }
        $message = new OutgoingMessage($args, $method, $methodInfo['type'], true, !$this->shared->hasTempAuthKey() && \strpos($method, '.') === false);
        if ($method === 'users.getUsers' && $args === ['id' => [['_' => 'inputUserSelf']]] || $method === 'auth.exportAuthorization' || $method === 'updates.getDifference') {
            $message->setUserRelated(true);
        }
        if (isset($aargs['msg_id'])) {
            $message->setMsgId($aargs['msg_id']);
        }
        if ($aargs['file'] ?? false) {
            $message->setFileRelated(true);
        }
        if ($aargs['botAPI'] ?? false) {
            $message->setBotAPI(true);
        }
        if (isset($aargs['FloodWaitLimit'])) {
            $message->setFloodWaitLimit($aargs['FloodWaitLimit']);
        }
        $aargs['postpone'] = $aargs['postpone'] ?? false;
        $deferred = (yield from $this->sendMessage($message, !$aargs['postpone']));
        $this->checker->resume();
        return $deferred;
    }
    /**
     * Send object and make sure it is asynchronously sent (generator).
     *
     * @param string $object Object name
     * @param array $args Arguments
     * @param array $aargs Additional arguments
     *
     * @return \Generator
     */
    public function objectCall(string $object, $args = [], array $aargs = ['msg_id' => null]) : \Generator
    {
        $message = new OutgoingMessage($args, $object, '', false, !$this->shared->hasTempAuthKey());
        if (isset($aargs['promise'])) {
            $message->setPromise($aargs['promise']);
        }
        $aargs['postpone'] = $aargs['postpone'] ?? false;
        return yield from $this->sendMessage($message, !$aargs['postpone']);
    }
}<?php

/**
 * AckHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoSession;

use danog\MadelineProto\DataCenterConnection;
use danog\MadelineProto\Logger;
use danog\MadelineProto\MTProto\IncomingMessage;
use danog\MadelineProto\MTProto\OutgoingMessage;
/**
 * Manages acknowledgement of messages.
 *
 * @property DataCenterConnection $shared
 */
trait AckHandler
{
    /**
     * Acknowledge outgoing message ID.
     *
     * @param (string | int) $message_id Message Id
     *
     * @return boolean
     */
    public function ackOutgoingMessageId($message_id) : bool
    {
        // The server acknowledges that it received my message
        if (!isset($this->outgoing_messages[$message_id])) {
            $this->logger->logger("WARNING: Couldn't find message id " . $message_id . ' in the array of outgoing messages. Maybe try to increase its size?', \danog\MadelineProto\Logger::WARNING);
            return false;
        }
        return true;
    }
    /**
     * We have gotten a response for an outgoing message.
     *
     * @param OutgoingMessage $message Message
     *
     * @return void
     */
    public function gotResponseForOutgoingMessage(OutgoingMessage $outgoingMessage) : void
    {
        // The server acknowledges that it received my message
        if (isset($this->new_outgoing[$outgoingMessage->getMsgId()])) {
            unset($this->new_outgoing[$outgoingMessage->getMsgId()]);
        } else {
            $this->logger->logger("Could not find {$outgoingMessage} in new_outgoing!", Logger::FATAL_ERROR);
        }
    }
    /**
     * Acknowledge incoming message ID.
     *
     * @param IncomingMessage $message Message
     *
     * @return void
     */
    public function ackIncomingMessage(IncomingMessage $message) : void
    {
        // Not exactly true, but we don't care
        $message->ack();
        $message_id = $message->getMsgId();
        // I let the server know that I received its message
        $this->ack_queue[$message_id] = $message_id;
    }
    /**
     * Check if there are some pending calls.
     *
     * @return boolean
     */
    public function hasPendingCalls() : bool
    {
        $timeout = $this->shared->getSettings()->getTimeout();
        $pfs = $this->shared->getGenericSettings()->getAuth()->getPfs();
        $unencrypted = !$this->shared->hasTempAuthKey();
        $notBound = !$this->shared->isBound();
        $pfsNotBound = $pfs && $notBound;
        /** @var OutgoingMessage */
        foreach ($this->new_outgoing as $message) {
            if ($message->wasSent() && $message->getSent() + $timeout < \time() && $message->isUnencrypted() === $unencrypted && $message->getConstructor() !== 'msgs_state_req') {
                if ($pfsNotBound && $message->getConstructor() !== 'auth.bindTempAuthKey') {
                    continue;
                }
                return true;
            }
        }
        return false;
    }
    /**
     * Get all pending calls (also clear pending state requests).
     *
     * @return array
     */
    public function getPendingCalls() : array
    {
        $settings = $this->shared->getSettings();
        $global = $this->shared->getGenericSettings();
        $dropTimeout = $global->getRpc()->getRpcTimeout();
        $timeout = $settings->getTimeout();
        $pfs = $global->getAuth()->getPfs();
        $unencrypted = !$this->shared->hasTempAuthKey();
        $notBound = !$this->shared->isBound();
        $pfsNotBound = $pfs && $notBound;
        $result = [];
        /** @var OutgoingMessage $message */
        foreach ($this->new_outgoing as $message_id => $message) {
            if ($message->wasSent() && $message->getSent() + $timeout < \time() && $message->isUnencrypted() === $unencrypted) {
                if ($pfsNotBound && $message->getConstructor() !== 'auth.bindTempAuthKey') {
                    continue;
                }
                if ($message->getConstructor() === 'msgs_state_req') {
                    unset($this->new_outgoing[$message_id], $this->outgoing_messages[$message_id]);
                    continue;
                }
                if ($message->getSent() + $dropTimeout < \time()) {
                    $this->handleReject($message, new \danog\MadelineProto\Exception("Request timeout"));
                    continue;
                }
                if ($message->getState() & OutgoingMessage::STATE_REPLIED) {
                    $this->logger->logger("Already replied to message {$message}, but still in new_outgoing");
                    unset($this->new_outgoing[$message_id]);
                    continue;
                }
                $result[] = $message_id;
            }
        }
        return $result;
    }
}<?php

/**
 * MsgIdHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoSession\MsgIdHandler;

use danog\MadelineProto\MTProtoSession\MsgIdHandler;
use danog\MadelineProto\Tools;
/**
 * Manages message ids.
 */
class MsgIdHandler64 extends MsgIdHandler
{
    /**
     * Maximum incoming ID.
     *
     * @var int
     */
    private $maxIncomingId = 0;
    /**
     * Maximum outgoing ID.
     *
     * @var int
     */
    private $maxOutgoingId = 0;
    /**
     * Check validity of given message ID.
     *
     * @param string $newMessageId New message ID
     * @param array $aargs Params
     *
     * @return void
     */
    public function checkMessageId($newMessageId, array $aargs) : void
    {
        $newMessageId = \is_integer($newMessageId) ? $newMessageId : Tools::unpackSignedLong($newMessageId);
        $minMessageId = \time() + $this->session->time_delta - 300 << 32;
        if ($newMessageId < $minMessageId) {
            $this->session->API->logger->logger('Given message id (' . $newMessageId . ') is too old compared to the min value (' . $minMessageId . ').', \danog\MadelineProto\Logger::WARNING);
        }
        $maxMessageId = \time() + $this->session->time_delta + 30 << 32;
        if ($newMessageId > $maxMessageId) {
            throw new \danog\MadelineProto\Exception('Given message id (' . $newMessageId . ') is too new compared to the max value (' . $maxMessageId . '). Please sync your date using NTP.');
        }
        if ($aargs['outgoing']) {
            if ($newMessageId % 4) {
                throw new \danog\MadelineProto\Exception('Given message id (' . $newMessageId . ') is not divisible by 4. Please sync your date using NTP.');
            }
            if ($newMessageId <= $this->maxOutgoingId) {
                throw new \danog\MadelineProto\Exception('Given message id (' . $newMessageId . ') is lower than or equal to the current limit (' . $this->maxOutgoingId . '). Please sync your date using NTP.');
            }
            $this->maxOutgoingId = $newMessageId;
        } else {
            if (!($newMessageId % 2)) {
                throw new \danog\MadelineProto\Exception('message id mod 4 != 1 or 3');
            }
            $key = $this->maxIncomingId;
            if ($aargs['container']) {
                if ($newMessageId >= $key) {
                    $this->session->API->logger->logger('Given message id (' . $newMessageId . ') is bigger than or equal to the current limit (' . $key . '). Please sync your date using NTP.', \danog\MadelineProto\Logger::NOTICE);
                }
            } else {
                if ($newMessageId <= $key) {
                    $this->session->API->logger->logger('Given message id (' . $newMessageId . ') is lower than or equal to the current limit (' . $key . '). Please sync your date using NTP.', \danog\MadelineProto\Logger::NOTICE);
                }
            }
            $this->maxIncomingId = $newMessageId;
        }
    }
    /**
     * Generate message ID.
     *
     * @return string
     */
    public function generateMessageId() : string
    {
        $messageId = \time() + $this->session->time_delta << 32;
        if ($messageId <= $this->maxOutgoingId) {
            $messageId = $this->maxOutgoingId + 4;
        }
        $this->checkMessageId($messageId, ['outgoing' => true, 'container' => false]);
        return Tools::packSignedLong($messageId);
    }
    /**
     * Get maximum message ID.
     *
     * @param boolean $incoming Incoming or outgoing message ID
     *
     * @return mixed
     */
    public function getMaxId(bool $incoming)
    {
        return $this->{$incoming ? 'maxIncomingId' : 'maxOutgoingId'};
    }
    /**
     * Get readable representation of message ID.
     *
     * @param string $messageId
     * @return string
     */
    protected static function toStringInternal(string $messageId) : string
    {
        return (string) Tools::unpackSignedLong($messageId);
    }
}<?php

/**
 * MsgIdHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoSession;

use danog\MadelineProto\Connection;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Magic;
use danog\MadelineProto\MTProtoSession\MsgIdHandler\MsgIdHandler32;
use danog\MadelineProto\MTProtoSession\MsgIdHandler\MsgIdHandler64;
/**
 * Manages message ids.
 */
abstract class MsgIdHandler
{
    /**
     * Session instance.
     */
    protected Connection $session;
    /**
     * Constructor.
     *
     * @param Connection $session Session
     */
    private function __construct(Connection $session)
    {
        $this->session = $session;
    }
    /**
     * Create MsgIdHandler instance.
     *
     * @param Connection $session Session
     *
     * @return self
     */
    public static function createInstance(Connection $session) : self
    {
        return new MsgIdHandler64($session);
    }
    /**
     * Check validity of given message ID.
     *
     * @param string $newMessageId New message ID
     * @param array $aargs Params
     *
     * @return void
     */
    public abstract function checkMessageId($newMessageId, array $aargs) : void;
    /**
     * Generate outgoing message ID.
     *
     * @return string
     */
    public abstract function generateMessageId() : string;
    /**
     * Get maximum message ID.
     *
     * @param boolean $incoming Incoming or outgoing message ID
     *
     * @return mixed
     */
    public abstract function getMaxId(bool $incoming);
    /**
     * Get readable representation of message ID.
     *
     * @param string $messageId
     * @return string
     */
    protected static abstract function toStringInternal(string $messageId) : string;
    /**
     * Cleanup incoming and outgoing messages.
     *
     * @return void
     */
    public function cleanup() : void
    {
        $usage = \memory_get_usage();
        $this->session->cleanupSession();
        $cleaned = \round(($usage - \memory_get_usage()) / 1024 / 1024, 1);
        if ($cleaned && !Magic::$suspendPeriodicLogging) {
            $this->session->API->logger->logger("Zend hashmap reallocation done. Cleaned memory: {$cleaned} Mb", Logger::VERBOSE);
        }
    }
    /**
     * Get readable representation of message ID.
     *
     * @param string $messageId
     * @return string
     */
    public static function toString(string $messageId) : string
    {
        return PHP_INT_SIZE === 8 ? MsgIdHandler64::toStringInternal($messageId) : MsgIdHandler32::toStringInternal($messageId);
    }
}<?php

/**
 * ResponseHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoSession;

use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use danog\MadelineProto\Coroutine;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Loop\Update\UpdateLoop;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProto\IncomingMessage;
use danog\MadelineProto\MTProto\OutgoingMessage;
use danog\MadelineProto\Tools;
/**
 * Manages responses.
 *
 * @extend Session
 */
trait ResponseHandler
{
    public $n = 0;
    /**
     *
     */
    public function handleMessages() : void
    {
        while ($this->new_incoming) {
            \reset($this->new_incoming);
            $current_msg_id = \key($this->new_incoming);
            /** @var IncomingMessage */
            $message = $this->new_incoming[$current_msg_id];
            unset($this->new_incoming[$current_msg_id]);
            $this->logger->logger($message->log($this->datacenter), Logger::ULTRA_VERBOSE);
            $type = $message->getType();
            if ($type !== 'msg_container') {
                $this->checkInSeqNo($message);
            }
            switch ($type) {
                case 'msgs_ack':
                    foreach ($message->read()['msg_ids'] as $msg_id) {
                        // Acknowledge that the server received my message
                        $this->ackOutgoingMessageId($msg_id);
                    }
                    break;
                case 'rpc_result':
                    $this->ackIncomingMessage($message);
                // no break
                case 'future_salts':
                case 'msgs_state_info':
                case 'bad_server_salt':
                case 'bad_msg_notification':
                case 'pong':
                    $this->handleResponse($message);
                    break;
                case 'new_session_created':
                    $this->ackIncomingMessage($message);
                    $this->shared->getTempAuthKey()->setServerSalt($message->read()['server_salt']);
                    if ($this->API->authorized === MTProto::LOGGED_IN && !$this->API->isInitingAuthorization() && $this->API->datacenter->getDataCenterConnection($this->API->datacenter->curdc)->hasTempAuthKey() && isset($this->API->updaters[UpdateLoop::GENERIC])) {
                        $this->API->updaters[UpdateLoop::GENERIC]->resumeDefer();
                    }
                    break;
                case 'msg_container':
                    foreach ($message->read()['messages'] as $message) {
                        $this->msgIdHandler->checkMessageId($message['msg_id'], ['outgoing' => false, 'container' => true]);
                        $newMessage = new IncomingMessage($message['body'], $message['msg_id'], true);
                        $newMessage->setSeqNo($message['seqno']);
                        $this->new_incoming[$message['msg_id']] = $this->incoming_messages[$message['msg_id']] = $newMessage;
                    }
                    unset($newMessage, $message);
                    \ksort($this->new_incoming);
                    break;
                case 'msg_copy':
                    $this->ackIncomingMessage($message);
                    $content = $message->read();
                    $referencedMsgId = $content['msg_id'];
                    if (isset($this->incoming_messages[$referencedMsgId])) {
                        $this->ackIncomingMessage($this->incoming_messages[$referencedMsgId]);
                    } else {
                        $this->msgIdHandler->checkMessageId($referencedMsgId, ['outgoing' => false, 'container' => true]);
                        $message = new IncomingMessage($content['orig_message'], $referencedMsgId);
                        $this->new_incoming[$referencedMsgId] = $this->incoming_messages[$referencedMsgId] = $message;
                        unset($message);
                    }
                    unset($content, $referencedMsgId);
                    break;
                case 'http_wait':
                    $this->logger->logger($message->read(), Logger::NOTICE);
                    break;
                case 'msgs_state_req':
                    $this->sendMsgsStateInfo($message->read()['msg_ids'], $current_msg_id);
                    break;
                case 'msgs_all_info':
                    $this->onMsgsAllInfo($message->read());
                    break;
                case 'msg_detailed_info':
                    $this->onMsgDetailedInfo($message->read());
                    break;
                case 'msg_new_detailed_info':
                    $this->onNewMsgDetailedInfo($message->read());
                    break;
                case 'msg_resend_req':
                    $this->onMsgResendReq($message->read(), $current_msg_id);
                    break;
                case 'msg_resend_ans_req':
                    $this->onMsgResendAnsReq($message->read(), $current_msg_id);
                    break;
                default:
                    $this->ackIncomingMessage($message);
                    $response_type = $this->API->getTL()->getConstructors()->findByPredicate($message->getContent()['_'])['type'];
                    if ($response_type == 'Updates') {
                        if (!$this->isCdn()) {
                            Tools::callForkDefer($this->API->handleUpdates($message->read()));
                        }
                        break;
                    }
                    $this->logger->logger('Trying to assign a response of type ' . $response_type . ' to its request...', Logger::VERBOSE);
                    foreach ($this->new_outgoing as $expecting_msg_id => $expecting) {
                        if (!($type = $expecting->getType())) {
                            continue;
                        }
                        $this->logger->logger("Does the request of return type {$type} match?", Logger::VERBOSE);
                        if ($response_type === $type) {
                            $this->logger->logger('Yes', Logger::VERBOSE);
                            $this->handleResponse($message, $expecting_msg_id);
                            break 2;
                        }
                        $this->logger->logger('No', Logger::VERBOSE);
                    }
                    $this->logger->logger('Dunno how to handle ' . PHP_EOL . \var_export($message->read(), true), Logger::FATAL_ERROR);
                    break;
            }
        }
        $this->new_incoming = [];
        if ($this->pendingOutgoing) {
            $this->writer->resume();
        }
    }
    /**
     *
     */
    public function handleReject(OutgoingMessage $message, \Throwable $data) : void
    {
        $this->gotResponseForOutgoingMessage($message);
        $message->reply(new Failure($data));
    }
    /**
     * Handle RPC response.
     *
     * @param IncomingMessage $message Incoming message
     * @param string $requestId Request ID
     *
     * @return void
     */
    private function handleResponse(IncomingMessage $message, $requestId = null) : void
    {
        $requestId ??= $message->getRequestId();
        $response = $message->read();
        if (!isset($this->outgoing_messages[$requestId])) {
            $requestId = MsgIdHandler::toString($requestId);
            $this->logger->logger("Got a reponse {$message} with message ID {$requestId}, but there is no request!", Logger::FATAL_ERROR);
            return;
        }
        /** @var OutgoingMessage */
        $request = $this->outgoing_messages[$requestId];
        if ($request->getState() & OutgoingMessage::STATE_REPLIED) {
            $this->logger->logger("Already got a response to {$request}, but there is another reply {$message} with message ID {$requestId}!", Logger::FATAL_ERROR);
            return;
        }
        if ($response['_'] === 'rpc_result') {
            $response = $response['result'];
        }
        $constructor = $response['_'] ?? '';
        if ($constructor === 'rpc_error') {
            try {
                $exception = $this->handleRpcError($request, $response);
            } catch (\Throwable $e) {
                $exception = $e;
            }
            if ($exception) {
                $this->handleReject($request, $exception);
            }
            return;
        }
        if ($constructor === 'bad_server_salt' || $constructor === 'bad_msg_notification') {
            $this->logger->logger('Received bad_msg_notification: ' . MTProto::BAD_MSG_ERROR_CODES[$response['error_code']], Logger::WARNING);
            switch ($response['error_code']) {
                case 48:
                    $this->shared->getTempAuthKey()->setServerSalt($response['new_server_salt']);
                    $this->methodRecall('', ['message_id' => $requestId, 'postpone' => true]);
                    return;
                case 20:
                    $request->setMsgId(null);
                    $request->setSeqNo(null);
                    $this->methodRecall('', ['message_id' => $requestId, 'postpone' => true]);
                    return;
                case 16:
                case 17:
                    $this->time_delta = (int) (new \phpseclib3\Math\BigInteger(\strrev($message->getMsgId()), 256))->bitwise_rightShift(32)->subtract(new \phpseclib3\Math\BigInteger(\time()))->toString();
                    $this->logger->logger('Set time delta to ' . $this->time_delta, Logger::WARNING);
                    $this->API->resetMTProtoSession();
                    $this->shared->setTempAuthKey(null);
                    Tools::callFork((function () use($requestId) : \Generator {
                        yield from $this->API->initAuthorization();
                        $this->methodRecall('', ['message_id' => $requestId]);
                    })());
                    return;
            }
            $this->handleReject($request, new \danog\MadelineProto\RPCErrorException('Received bad_msg_notification: ' . MTProto::BAD_MSG_ERROR_CODES[$response['error_code']], $response['error_code'], $request->getConstructor()));
            return;
        }
        if ($request->isMethod() && $request->getConstructor() !== 'auth.bindTempAuthKey' && $this->shared->hasTempAuthKey() && !$this->shared->getTempAuthKey()->isInited()) {
            $this->shared->getTempAuthKey()->init(true);
        }
        $botAPI = $request->getBotAPI();
        if (isset($response['_']) && !$this->isCdn() && $this->API->getTL()->getConstructors()->findByPredicate($response['_'])['type'] === 'Updates') {
            $body = $request->getBodyOrEmpty();
            $trimmed = [];
            if (isset($body['peer'])) {
                try {
                    $trimmed['peer'] = \is_string($body['peer']) ? $body['peer'] : $this->API->getId($body['peer']);
                } catch (\Throwable $e) {
                }
            }
            if (isset($body['message'])) {
                $trimmed['message'] = (string) $body['message'];
            }
            $response['request'] = ['_' => $request->getConstructor(), 'body' => $trimmed];
            unset($body);
            Tools::callForkDefer($this->API->handleUpdates($response));
        }
        $this->gotResponseForOutgoingMessage($request);
        if ($side = $message->getSideEffects($response)) {
            if ($botAPI) {
                $deferred = new Deferred();
                $promise = $deferred->promise();
                $side->onResolve(function (?\Throwable $error, $result) use($deferred) : void {
                    if ($error) {
                        $deferred->fail($error);
                        return;
                    }
                    $deferred->resolve(new Coroutine($this->API->MTProtoToBotAPI($result)));
                });
                $request->reply($promise);
            } else {
                $request->reply($side);
            }
        } else {
            if ($botAPI) {
                $request->reply(new Coroutine($this->API->MTProtoToBotAPI($response)));
            } else {
                $request->reply($response);
            }
        }
    }
    /**
     *
     */
    public function handleRpcError(OutgoingMessage $request, array $response) : ?\Throwable
    {
        if ($request->isMethod() && $request->getConstructor() !== 'auth.bindTempAuthKey' && $this->shared->hasTempAuthKey() && !$this->shared->getTempAuthKey()->isInited()) {
            $this->shared->getTempAuthKey()->init(true);
        }
        if (\in_array($response['error_message'], ['PERSISTENT_TIMESTAMP_EMPTY', 'PERSISTENT_TIMESTAMP_INVALID'])) {
            return new \danog\MadelineProto\PTSException($response['error_message']);
        }
        if ($response['error_message'] === 'PERSISTENT_TIMESTAMP_OUTDATED') {
            $response['error_code'] = 500;
        }
        if (\strpos($response['error_message'], 'FILE_REFERENCE_') === 0) {
            $this->logger->logger("Got {$response['error_message']}, refreshing file reference and repeating method call...");
            $this->gotResponseForOutgoingMessage($request);
            $msgId = $request->getMsgId();
            $request->setRefreshReferences(true);
            $request->setMsgId(null);
            $request->setSeqNo(null);
            $this->methodRecall('', ['message_id' => $msgId, 'postpone' => true]);
            return null;
        }
        switch ($response['error_code']) {
            case 500:
            case -500:
                if ($response['error_message'] === 'MSG_WAIT_FAILED') {
                    $this->call_queue[$request->getQueueId()] = [];
                    $this->methodRecall('', ['message_id' => $request->getMsgId(), 'postpone' => true]);
                    return null;
                }
                if (\in_array($response['error_message'], ['MSGID_DECREASE_RETRY', 'HISTORY_GET_FAILED', 'RPC_CONNECT_FAILED', 'RPC_CALL_FAIL', 'PERSISTENT_TIMESTAMP_OUTDATED', 'RPC_MCGET_FAIL', 'no workers running', 'No workers running'])) {
                    Loop::delay(1 * 1000, [$this, 'methodRecall'], ['message_id' => $request->getMsgId()]);
                    return null;
                }
                return new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
            case 303:
                $this->API->datacenter->curdc = $datacenter = (int) \preg_replace('/[^0-9]+/', '', $response['error_message']);
                if ($request->isFileRelated() && $this->API->datacenter->has($datacenter . '_media')) {
                    $datacenter .= '_media';
                }
                if ($request->isUserRelated()) {
                    $this->API->settings->setDefaultDc($this->API->authorized_dc = $this->API->datacenter->curdc);
                }
                Loop::defer([$this, 'methodRecall'], ['message_id' => $request->getMsgId(), 'datacenter' => $datacenter]);
                //$this->API->methodRecall('', ['message_id' => $requestId, 'datacenter' => $datacenter, 'postpone' => true]);
                return null;
            case 401:
                switch ($response['error_message']) {
                    case 'USER_DEACTIVATED':
                    case 'USER_DEACTIVATED_BAN':
                    case 'SESSION_REVOKED':
                    case 'SESSION_EXPIRED':
                        $this->logger->logger($response['error_message'], Logger::FATAL_ERROR);
                        if (\in_array($response['error_message'], ['USER_DEACTIVATED', 'USER_DEACTIVATED_BAN'], true)) {
                            $this->logger->logger('!!!!!!! WARNING !!!!!!!', Logger::FATAL_ERROR);
                            $this->logger->logger("Telegram's flood prevention system suspended this account.", Logger::ERROR);
                            $this->logger->logger('To continue, manual verification is required.', Logger::FATAL_ERROR);
                            $phone = isset($this->API->authorization['user']['phone']) ? '+' . $this->API->authorization['user']['phone'] : 'you are currently using';
                            $this->logger->logger('Send an email to recover@telegram.org, asking to unban the phone number ' . $phone . ', and shortly describe what will you do with this phone number.', Logger::FATAL_ERROR);
                            $this->logger->logger('Then login again.', Logger::FATAL_ERROR);
                            $this->logger->logger('If you intentionally deleted this account, ignore this message.', Logger::FATAL_ERROR);
                        }
                        throw new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
                    case 'AUTH_KEY_UNREGISTERED':
                    case 'AUTH_KEY_INVALID':
                        if ($this->API->authorized !== MTProto::LOGGED_IN) {
                            $this->gotResponseForOutgoingMessage($request);
                            Tools::callFork((function () use($request, $response) : \Generator {
                                yield from $this->API->initAuthorization();
                                $this->handleReject($request, new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor()));
                            })());
                            return null;
                        }
                        $this->session_id = null;
                        $this->shared->setTempAuthKey(null);
                        $this->shared->setPermAuthKey(null);
                        $this->logger->logger("Auth key not registered in DC {$this->datacenter} with RPC error {$response['error_message']}, resetting temporary and permanent auth keys...", Logger::ERROR);
                        if ($this->API->authorized_dc == $this->datacenter && $this->API->authorized === MTProto::LOGGED_IN) {
                            $this->logger->logger('Permanent auth key was main authorized key, logging out...', Logger::FATAL_ERROR);
                            $this->logger->logger('!!!!!!! WARNING !!!!!!!', Logger::FATAL_ERROR);
                            $this->logger->logger("Telegram's flood prevention system suspended this account.", Logger::ERROR);
                            $this->logger->logger('To continue, manual verification is required.', Logger::FATAL_ERROR);
                            $phone = isset($this->API->authorization['user']['phone']) ? '+' . $this->API->authorization['user']['phone'] : 'you are currently using';
                            $this->logger->logger('Send an email to recover@telegram.org, asking to unban the phone number ' . $phone . ', and quickly describe what will you do with this phone number.', Logger::FATAL_ERROR);
                            $this->logger->logger('Then login again.', Logger::FATAL_ERROR);
                            $this->logger->logger('If you intentionally deleted this account, ignore this message.', Logger::FATAL_ERROR);
                            throw new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
                        }
                        Tools::callFork((function () use($request) : \Generator {
                            yield from $this->API->initAuthorization();
                            $this->methodRecall('', ['message_id' => $request->getMsgId()]);
                        })());
                        return null;
                    case 'AUTH_KEY_PERM_EMPTY':
                        $this->logger->logger('Temporary auth key not bound, resetting temporary auth key...', Logger::ERROR);
                        $this->shared->setTempAuthKey(null);
                        Tools::callFork((function () use($request) : \Generator {
                            yield from $this->API->initAuthorization();
                            $this->methodRecall('', ['message_id' => $request->getMsgId()]);
                        })());
                        return null;
                }
                return new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
            case 420:
                $seconds = \preg_replace('/[^0-9]+/', '', $response['error_message']);
                $limit = $request->getFloodWaitLimit() ?? $this->API->settings->getRPC()->getFloodTimeout();
                if (\is_numeric($seconds) && $seconds < $limit) {
                    $this->logger->logger("Flood, waiting {$seconds} seconds before repeating async call of {$request}...", Logger::NOTICE);
                    $this->gotResponseForOutgoingMessage($request);
                    $msgId = $request->getMsgId();
                    $request->setSent(($request->getSent() ?? \time()) + $seconds);
                    $request->setMsgId(null);
                    $request->setSeqNo(null);
                    Loop::delay($seconds * 1000, [$this, 'methodRecall'], ['message_id' => $msgId]);
                    return null;
                }
            // no break
            default:
                return new \danog\MadelineProto\RPCErrorException($response['error_message'], $response['error_code'], $request->getConstructor());
        }
    }
}<?php

/**
 * Container message.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProto;

/**
 * Outgoing container message.
 *
 * @internal
 */
class Container extends OutgoingMessage
{
    /**
     * Message IDs.
     *
     */
    private array $ids = [];
    /**
     * Constructor.
     *
     * @param array $ids
     */
    public function __construct(array $ids)
    {
        $this->ids = $ids;
        parent::__construct([], 'msg_container', '', false, false);
    }
    /**
     * Get message IDs.
     *
     * @return array
     */
    public function getIds() : array
    {
        return $this->ids;
    }
}<?php

/**
 * Outgoing message.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProto;

use Amp\Deferred;
use Amp\Loop;
use Amp\Promise;
use danog\MadelineProto\Exception;
use danog\MadelineProto\MTProtoSession\MsgIdHandler;
/**
 * Outgoing message.
 *
 * @internal
 */
class OutgoingMessage extends Message
{
    /**
     * The message was created.
     */
    const STATE_PENDING = 0;
    /**
     * The message was sent.
     */
    const STATE_SENT = 1;
    /**
     * The message was acked.
     */
    const STATE_ACKED = 2;
    /**
     * We got a reply to the message.
     */
    const STATE_REPLIED = self::STATE_ACKED | 4;
    /**
     * State of message.
     *
     * @var int
     * @psalm-var self::STATE_*
     */
    private int $state = self::STATE_PENDING;
    /**
     * Constructor name.
     */
    private string $constructor;
    /**
     * Constructor type.
     */
    private string $type;
    /**
     * Whether this is a method.
     */
    private bool $method;
    /**
     * Resolution deferred.
     */
    private ?Deferred $promise = null;
    /**
     * Send deferred.
     */
    private ?Deferred $sendPromise = null;
    /**
     * Whether this is an unencrypted message.
     */
    private bool $unencrypted;
    /**
     * Message body.
     *
     * @var \Generator|array|null
     */
    private $body;
    /**
     * Serialized body.
     */
    private ?string $serializedBody = null;
    /**
     * Whether this message is related to a user, as in getting a successful reply means we have auth.
     */
    private bool $userRelated = false;
    /**
     * Whether this message is related to a file upload, as in getting a redirect should redirect to a media server.
     */
    private bool $fileRelated = false;
    /**
     * Custom flood wait limit for this bot.
     */
    private ?int $floodWaitLimit = null;
    /**
     * Whether we should try converting the result to a bot API object.
     */
    private bool $botAPI = false;
    /**
     * Whether we should refresh references upon serialization of this message.
     */
    private bool $refreshReferences = false;
    /**
     * Queue ID.
     */
    private ?string $queueId = null;
    /**
     * When was this message sent.
     */
    private int $sent = 0;
    /**
     * Number of times this message was sent.
     */
    private int $tries = 0;
    /**
     * Create outgoing message.
     *
     * @param (\Generator | array) $body Body
     * @param string $constructor Constructor name
     * @param string $type Constructor type
     * @param boolean $method Is this a method?
     * @param boolean $unencrypted Is this an unencrypted message?
     */
    public function __construct($body, string $constructor, string $type, bool $method, bool $unencrypted)
    {
        $this->body = $body;
        $this->constructor = $constructor;
        $this->type = $type;
        $this->method = $method;
        $this->unencrypted = $unencrypted;
        if ($method) {
            $this->promise = new Deferred();
        }
        $this->contentRelated = !isset(Message::NOT_CONTENT_RELATED[$constructor]);
    }
    /**
     * Signal that we're trying to send the message.
     *
     * @return void
     */
    public function trySend() : void
    {
        if (!isset($this->sendPromise)) {
            $this->sendPromise = new Deferred();
        }
        $this->tries++;
    }
    /**
     * Signal that the message was sent.
     *
     * @return void
     */
    public function sent() : void
    {
        if ($this->state & self::STATE_REPLIED) {
            //throw new Exception("Trying to resend already replied message $this!");
        }
        $this->state |= self::STATE_SENT;
        $this->sent = \time();
        if (isset($this->sendPromise)) {
            $sendPromise = $this->sendPromise;
            $this->sendPromise = null;
            $sendPromise->resolve($this->promise ?? true);
        }
    }
    /**
     * Set reply to message.
     *
     * @param (Promise | mixed) $result
     * @return void
     */
    public function reply($result) : void
    {
        if ($this->state & self::STATE_REPLIED) {
            throw new Exception("Trying to double reply to message {$this}!");
        }
        $this->serializedBody = null;
        $this->body = null;
        $this->state |= self::STATE_REPLIED;
        if ($this->promise) {
            // Sometimes can get an RPC error for constructors
            $promise = $this->promise;
            $this->promise = null;
            Loop::defer(fn() => $promise->resolve($result));
        }
    }
    /**
     * ACK message.
     *
     * @return void
     */
    public function ack() : void
    {
        $this->state |= self::STATE_ACKED;
    }
    /**
     * Get state of message.
     *
     * @return int
     * @psalm-return self::STATE_*
     */
    public function getState() : int
    {
        return $this->state;
    }
    /**
     * Get message body.
     *
     * @return \Generator
     */
    public function getBody() : \Generator
    {
        return $this->body instanceof \Generator ? yield from $this->body : $this->body;
    }
    /**
     * Get message body or empty array.
     *
     * @return array
     */
    public function getBodyOrEmpty() : array
    {
        return \is_array($this->body) ? $this->body : [];
    }
    /**
     * Check if we have a body.
     *
     * @return boolean
     */
    public function hasBody() : bool
    {
        return $this->body !== null;
    }
    /**
     * Get serialized body.
     *
     * @return ?string
     */
    public function getSerializedBody() : ?string
    {
        return $this->serializedBody;
    }
    /**
     * Check if we have a serialized body.
     *
     * @return boolean
     */
    public function hasSerializedBody() : bool
    {
        return $this->serializedBody !== null;
    }
    /**
     * Get number of times this message was sent.
     *
     * @return int
     */
    public function getTries() : int
    {
        return $this->tries;
    }
    /**
     * Get constructor name.
     *
     * @return string
     */
    public function getConstructor() : string
    {
        return $this->constructor;
    }
    /**
     * Get constructor type.
     *
     * @return string
     */
    public function getType() : string
    {
        return $this->type;
    }
    /**
     * Get whether this is a method.
     *
     * @return bool
     */
    public function isMethod() : bool
    {
        return $this->method;
    }
    /**
     * Get whether this is an unencrypted message.
     *
     * @return bool
     */
    public function isUnencrypted() : bool
    {
        return $this->unencrypted;
    }
    /**
     * Get whether this is an encrypted message.
     *
     * @return bool
     */
    public function isEncrypted() : bool
    {
        return !$this->unencrypted;
    }
    /**
     * Get whether this message is related to a user, as in getting a successful reply means we have auth.
     *
     * @return bool
     */
    public function isUserRelated() : bool
    {
        return $this->userRelated;
    }
    /**
     * Get whether we should refresh references upon serialization of this message.
     *
     * @return bool
     */
    public function shouldRefreshReferences() : bool
    {
        return $this->refreshReferences;
    }
    /**
     * Get queue ID.
     *
     * @return ?string
     */
    public function getQueueId() : ?string
    {
        return $this->queueId;
    }
    /**
     * Get whether we have a queue ID.
     *
     * @return bool
     */
    public function hasQueue() : bool
    {
        return $this->queueId !== null;
    }
    /**
     * Set serialized body.
     *
     * @param string $serializedBody Serialized body.
     *
     * @return self
     */
    public function setSerializedBody(string $serializedBody) : self
    {
        $this->serializedBody = $serializedBody;
        return $this;
    }
    /**
     * Set whether this message is related to a user, as in getting a successful reply means we have auth.
     *
     * @param bool $userRelated Whether this message is related to a user, as in getting a successful reply means we have auth.
     *
     * @return self
     */
    public function setUserRelated(bool $userRelated) : self
    {
        $this->userRelated = $userRelated;
        return $this;
    }
    /**
     * Set whether we should refresh references upon serialization of this message.
     *
     * @param bool $refreshReferences Whether we should refresh references upon serialization of this message.
     *
     * @return self
     */
    public function setRefreshReferences(bool $refreshReferences) : self
    {
        $this->refreshReferences = $refreshReferences;
        return $this;
    }
    /**
     * Set queue ID.
     *
     * @param ?string $queueId Queue ID.
     *
     * @return self
     */
    public function setQueueId(?string $queueId) : self
    {
        $this->queueId = $queueId;
        return $this;
    }
    /**
     * Get when was this message sent.
     *
     * @return int
     */
    public function getSent() : int
    {
        return $this->sent;
    }
    /**
     * Check if the message was sent.
     *
     * @return boolean
     */
    public function wasSent() : bool
    {
        return (bool) ($this->state & self::STATE_SENT);
    }
    /**
     * Check if can garbage collect this message.
     *
     * @return boolean
     */
    public function canGarbageCollect() : bool
    {
        if ($this->state & self::STATE_REPLIED) {
            return true;
        }
        if (!$this->hasPromise()) {
            return true;
        }
        return false;
    }
    /**
     * For logging.
     *
     * @return string
     */
    public function __toString()
    {
        if ($this->msgId) {
            $msgId = MsgIdHandler::toString($this->msgId);
            return "{$this->constructor} with message ID {$msgId}";
        }
        return $this->constructor;
    }
    /**
     * Set resolution deferred.
     *
     * @param Deferred $promise Resolution deferred.
     *
     * @return self
     */
    public function setPromise(Deferred $promise) : self
    {
        $this->promise = $promise;
        return $this;
    }
    /**
     * Wait for message to be sent.
     *
     * @return Promise
     */
    public function getSendPromise() : Promise
    {
        if (!$this->sendPromise) {
            throw new Exception("Message was already sent, can't get send promise!");
        }
        return $this->sendPromise->promise();
    }
    /**
     * Check if we have a promise.
     *
     * @return bool
     */
    public function hasPromise() : bool
    {
        return $this->promise !== null;
    }
    /**
     * Reset sent time to trigger resending.
     *
     * @return self
     */
    public function resetSent() : self
    {
        $this->sent = 0;
        return $this;
    }
    /**
     * Get whether we should try converting the result to a bot API object.
     *
     * @return bool
     */
    public function getBotAPI() : bool
    {
        return $this->botAPI;
    }
    /**
     * Set whether we should try converting the result to a bot API object.
     *
     * @param bool $botAPI Whether we should try converting the result to a bot API object
     *
     * @return self
     */
    public function setBotAPI(bool $botAPI) : self
    {
        $this->botAPI = $botAPI;
        return $this;
    }
    /**
     * Get whether this message is related to a file upload, as in getting a redirect should redirect to a media server.
     *
     * @return bool
     */
    public function isFileRelated() : bool
    {
        return $this->fileRelated;
    }
    /**
     * Set whether this message is related to a file upload, as in getting a redirect should redirect to a media server.
     *
     * @param bool $fileRelated Whether this message is related to a file upload, as in getting a redirect should redirect to a media server.
     *
     * @return self
     */
    public function setFileRelated(bool $fileRelated) : self
    {
        $this->fileRelated = $fileRelated;
        return $this;
    }
    /**
     * Get custom flood wait limit for this bot.
     *
     * @return ?int
     */
    public function getFloodWaitLimit() : ?int
    {
        return $this->floodWaitLimit;
    }
    /**
     * Set custom flood wait limit for this bot.
     *
     * @param ?int $floodWaitLimit Custom flood wait limit for this bot
     *
     * @return self
     */
    public function setFloodWaitLimit(?int $floodWaitLimit) : self
    {
        $this->floodWaitLimit = $floodWaitLimit;
        return $this;
    }
    /**
     * Set when was this message sent.
     *
     * @param int $sent When was this message sent.
     *
     * @return self
     */
    public function setSent(int $sent) : self
    {
        $this->sent = $sent;
        return $this;
    }
}<?php

/**
 * Outgoing message.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProto;

use Amp\Deferred;
use Amp\Promise;
use danog\MadelineProto\Tools;
/**
 * Incoming message.
 *
 * @internal
 */
class IncomingMessage extends Message
{
    /**
     * We have received this message.
     */
    const STATE_RECEIVED = 4;
    /**
     * We have acknowledged this message.
     */
    const STATE_ACKED = 8;
    /**
     * We have read the contents of this message.
     */
    const STATE_READ = 128;
    /**
     * Response field map.
     */
    private const RESPONSE_ID_MAP = ['rpc_result' => 'req_msg_id', 'future_salts' => 'req_msg_id', 'msgs_state_info' => 'req_msg_id', 'bad_server_salt' => 'bad_msg_id', 'bad_msg_notification' => 'bad_msg_id', 'pong' => 'msg_id'];
    /**
     * State.
     */
    private int $state = self::STATE_RECEIVED;
    /**
     * Receive date.
     */
    private int $received;
    /**
     * Deserialized response content.
     */
    private array $content;
    /**
     * Was present in container.
     */
    private bool $fromContainer;
    /**
     * DB side effects to be resolved before using the content.
     *
     * @var Promise[]
     */
    private $sideEffects = [];
    /**
     * Constructor.
     *
     * @param array $content Content
     * @param boolean $fromContainer Whether this message was in a container
     */
    public function __construct(array $content, string $msgId, bool $fromContainer = false)
    {
        $this->content = $content;
        $this->fromContainer = $fromContainer;
        $this->msgId = $msgId;
        $this->received = \time();
        $this->contentRelated = !isset(Message::NOT_CONTENT_RELATED[$content['_']]);
        if (!$this->contentRelated) {
            $this->state |= 16;
            // message not requiring acknowledgment
        }
    }
    /**
     * Get deserialized response content.
     *
     * @return array
     */
    public function getContent() : array
    {
        return $this->content;
    }
    /**
     * Get was present in container.
     *
     * @return bool
     */
    public function isFromContainer() : bool
    {
        return $this->fromContainer;
    }
    /**
     * Get log line.
     *
     * @param (int | string) $dc DC ID
     *
     * @return string
     */
    public function log($dc) : string
    {
        if ($this->fromContainer) {
            return "Inside of container, received {$this->content['_']} from DC {$dc}";
        }
        return "Received {$this->content['_']} from DC {$dc}";
    }
    /**
     * Get message type.
     *
     * @return string
     */
    public function getType() : string
    {
        return $this->content['_'];
    }
    /**
     * Get message type.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->content['_'];
    }
    /**
     * We have acked this message.
     *
     * @return void
     */
    public function ack() : void
    {
        $this->state |= self::STATE_ACKED;
    }
    /**
     * Read this message, clearing its contents.
     *
     * @return array
     */
    public function read() : array
    {
        $this->state |= self::STATE_READ;
        $content = $this->content;
        $this->content = ['_' => $content['_']];
        return $content;
    }
    /**
     * Check if this message can be garbage collected.
     *
     * @return boolean
     */
    public function canGarbageCollect() : bool
    {
        return (bool) ($this->state & self::STATE_READ);
    }
    /**
     * Get ID of message to which this message replies.
     *
     * @return string
     */
    public function getRequestId() : string
    {
        return $this->content[self::RESPONSE_ID_MAP[$this->content['_']]];
    }
    /**
     * Get state.
     *
     * @return int
     */
    public function getState() : int
    {
        return $this->state;
    }
    /**
     * Set DB side effects to be resolved before using the content.
     *
     * @param Promise[] $sideEffects DB side effects to be resolved before using the content
     *
     * @return self
     */
    public function setSideEffects(array $sideEffects) : self
    {
        $this->sideEffects = $sideEffects;
        return $this;
    }
    /**
     * Get DB side effects to be resolved before using the specified content.
     *
     * @template T
     *
     * @param T $return Return value
     *
     * @psalm-return ?Promise<T>
     */
    public function getSideEffects($return) : ?Promise
    {
        if (!$this->sideEffects) {
            return null;
        }
        $deferred = new Deferred();
        $result = $deferred->promise();
        $pending = \count($this->sideEffects);
        foreach ($this->sideEffects as $promise) {
            $promise = Tools::call($promise);
            $promise->onResolve(function ($exception, $value) use(&$deferred, &$pending, $return) {
                if ($pending === 0) {
                    return;
                }
                if ($exception) {
                    $pending = 0;
                    $deferred->fail($exception);
                    $deferred = null;
                    return;
                }
                if (0 === --$pending) {
                    $deferred->resolve($return);
                }
            });
        }
        $this->sideEffects = [];
        return $result;
    }
    /**
     * Get receive date.
     *
     * @return int
     */
    public function getReceived() : int
    {
        return $this->received;
    }
}<?php

/**
 * Message.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProto;

/**
 * MTProto message.
 *
 * @internal
 */
abstract class Message
{
    protected const NOT_CONTENT_RELATED = [
        //'rpc_result' => true,
        //'rpc_error' => true,
        'rpc_drop_answer' => true,
        'rpc_answer_unknown' => true,
        'rpc_answer_dropped_running' => true,
        'rpc_answer_dropped' => true,
        'get_future_salts' => true,
        'future_salt' => true,
        'future_salts' => true,
        'ping' => true,
        'pong' => true,
        'ping_delay_disconnect' => true,
        'destroy_session' => true,
        'destroy_session_ok' => true,
        'destroy_session_none' => true,
        //'new_session_created' => true,
        'msg_container' => true,
        'msg_copy' => true,
        'gzip_packed' => true,
        'http_wait' => true,
        'msgs_ack' => true,
        'bad_msg_notification' => true,
        'bad_server_salt' => true,
        'msgs_state_req' => true,
        'msgs_state_info' => true,
        'msgs_all_info' => true,
        'msg_detailed_info' => true,
        'msg_new_detailed_info' => true,
        'msg_resend_req' => true,
        'msg_resend_ans_req' => true,
    ];
    /**
     * My message ID.
     */
    protected $msgId = null;
    /**
     * Sequence number.
     */
    protected ?int $seqNo = null;
    /**
     * Whether constructor is content related.
     */
    protected bool $contentRelated;
    /**
     * Get whether constructor is content related.
     *
     * @return bool
     */
    public function isContentRelated() : bool
    {
        return $this->contentRelated;
    }
    /**
     * Get my message ID.
     *
     * @return mixed
     */
    public function getMsgId()
    {
        return $this->msgId;
    }
    /**
     * Set my message ID.
     *
     * @param mixed $msgId My message ID
     *
     * @return self
     */
    public function setMsgId($msgId) : self
    {
        $this->msgId = $msgId;
        return $this;
    }
    /**
     * Check if we have a message ID.
     *
     * @return boolean
     */
    public function hasMsgId() : bool
    {
        return $this->msgId !== null;
    }
    /**
     * Get sequence number.
     *
     * @return ?int
     */
    public function getSeqNo() : ?int
    {
        return $this->seqNo;
    }
    /**
     * Has sequence number.
     *
     * @return bool
     */
    public function hasSeqNo() : bool
    {
        return isset($this->seqNo);
    }
    /**
     * Set sequence number.
     *
     * @param ?int $seqNo Sequence number
     *
     * @return self
     */
    public function setSeqNo(?int $seqNo) : self
    {
        $this->seqNo = $seqNo;
        return $this;
    }
    /**
     * Check whether this message can be garbage collected.
     *
     * @return boolean
     */
    public abstract function canGarbageCollect() : bool;
}<?php

/**
 * MTProto Auth key.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProto;

use JsonSerializable;
/**
 * MTProto auth key.
 */
abstract class AuthKey implements JsonSerializable
{
    /**
     * Auth key.
     *
     * @var string
     */
    protected $authKey;
    /**
     * Auth key ID.
     *
     * @var string
     */
    protected $id;
    /**
     * Server salt.
     *
     * @var string
     */
    protected $serverSalt;
    /**
     * Constructor function.
     *
     * @param array $old Old auth key array
     */
    public function __construct(array $old = [])
    {
        if (isset($old['auth_key'])) {
            if (\strlen($old['auth_key']) !== 2048 / 8 && \strpos($old['authkey'], 'pony') === 0) {
                $old['auth_key'] = \base64_decode(\Phabel\Target\Php80\Polyfill::substr($old['auth_key'], 4));
            }
            $this->setAuthKey($old['auth_key']);
        }
        if (isset($old['server_salt'])) {
            $this->setServerSalt($old['server_salt']);
        }
    }
    /**
     * Set auth key.
     *
     * @param string $authKey Authorization key
     *
     * @return void
     */
    public function setAuthKey(string $authKey)
    {
        $this->authKey = $authKey;
        $this->id = \Phabel\Target\Php80\Polyfill::substr(\sha1($authKey, true), -8);
    }
    /**
     * Check if auth key is present.
     *
     * @return boolean
     */
    public function hasAuthKey() : bool
    {
        return $this->authKey !== null;
    }
    /**
     * Get auth key.
     *
     * @return string
     */
    public function getAuthKey() : string
    {
        return $this->authKey;
    }
    /**
     * Get auth key ID.
     *
     * @return string
     */
    public function getID() : string
    {
        return $this->id;
    }
    /**
     * Set server salt.
     *
     * @param string $salt Server salt
     *
     * @return void
     */
    public function setServerSalt(string $salt)
    {
        $this->serverSalt = $salt;
    }
    /**
     * Get server salt.
     *
     * @return string
     */
    public function getServerSalt() : string
    {
        return $this->serverSalt;
    }
    /**
     * Check if has server salt.
     *
     * @return boolean
     */
    public function hasServerSalt() : bool
    {
        return $this->serverSalt !== null;
    }
    /**
     * Check if we are logged in.
     *
     * @return boolean
     */
    public abstract function isAuthorized() : bool;
    /**
     * Set the authorized boolean.
     *
     * @param boolean $authorized Whether we are authorized
     *
     * @return void
     */
    public abstract function authorized(bool $authorized);
}<?php

/**
 * MTProto permanent auth key.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProto;

/**
 * MTProto permanent auth key.
 */
class PermAuthKey extends AuthKey
{
    /**
     * Whether this auth key is authorized (as in associated to an account on Telegram).
     *
     * @var boolean
     */
    private $authorized = false;
    /**
     * Constructor function.
     *
     * @param array $old Old auth key array
     */
    public function __construct(array $old = [])
    {
        parent::__construct($old);
        if (isset($old['authorized'])) {
            $this->authorized($old['authorized']);
        }
    }
    /**
     * Check if we are logged in.
     *
     * @return boolean
     */
    public function isAuthorized() : bool
    {
        return $this->authorized;
    }
    /**
     * Set the authorized boolean.
     *
     * @param boolean $authorized Whether we are authorized
     *
     * @return void
     */
    public function authorized(bool $authorized)
    {
        $this->authorized = $authorized;
    }
    /**
     * JSON serialization function.
     *
     * @return array
     */
    public function jsonSerialize() : array
    {
        return ['auth_key' => 'pony' . \base64_encode($this->authKey), 'server_salt' => $this->serverSalt, 'authorized' => $this->authorized];
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep()
    {
        return ['authKey', 'id', 'serverSalt', 'authorized'];
    }
}<?php

/**
 * MTProto temporary auth key.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProto;

use JsonSerializable;
/**
 * MTProto temporary auth key.
 */
class TempAuthKey extends AuthKey implements JsonSerializable
{
    /**
     * Bound auth key instance.
     *
     * @var PermAuthKey|null
     */
    private $bound;
    /**
     * Expiration date.
     *
     * @var int
     */
    private $expires = 0;
    /**
     * Whether the connection is inited for this auth key.
     *
     * @var boolean
     */
    protected $inited = false;
    /**
     * Constructor function.
     *
     * @param array $old Old auth key array
     */
    public function __construct(array $old = [])
    {
        parent::__construct($old);
        if (isset($old['expires'])) {
            $this->expires($old['expires']);
        }
        if (isset($old['connection_inited']) && $old['connection_inited']) {
            $this->init($old['connection_inited']);
        }
    }
    /**
     * Init or deinit connection for auth key.
     *
     * @param boolean $init Init or deinit
     *
     * @return void
     */
    public function init(bool $init = true)
    {
        $this->inited = $init;
    }
    /**
     * Check if connection is inited for auth key.
     *
     * @return boolean
     */
    public function isInited() : bool
    {
        return $this->inited;
    }
    /**
     * Bind auth key.
     *
     * @param (PermAuthKey | null) $bound Permanent auth key
     * @param bool $pfs Whether to bind using PFS
     *
     * @return void
     */
    public function bind(?PermAuthKey $bound, bool $pfs = true)
    {
        $this->bound = $bound;
        if (!$pfs) {
            foreach (['authKey', 'id', 'serverSalt'] as $key) {
                $this->{$key} =& $bound->{$key};
            }
        }
    }
    /**
     * Check if auth key is bound.
     *
     * @return boolean
     */
    public function isBound() : bool
    {
        return $this->bound !== null;
    }
    /**
     * Check if we are logged in.
     *
     * @return boolean
     */
    public function isAuthorized() : bool
    {
        return $this->bound ? $this->bound->isAuthorized() : false;
    }
    /**
     * Set the authorized boolean.
     *
     * @param boolean $authorized Whether we are authorized
     *
     * @return void
     */
    public function authorized(bool $authorized)
    {
        $this->bound->authorized($authorized);
    }
    /**
     * Set expiration date of temporary auth key.
     *
     * @param integer $expires Expiration date
     *
     * @return void
     */
    public function expires(int $expires)
    {
        $this->expires = $expires;
    }
    /**
     * Check if auth key has expired.
     *
     * @return boolean
     */
    public function expired() : bool
    {
        return \time() > $this->expires;
    }
    /**
     * JSON serialization function.
     *
     * @return array
     */
    public function jsonSerialize() : array
    {
        return ['auth_key' => 'pony' . \base64_encode($this->authKey), 'server_salt' => $this->serverSalt, 'bound' => $this->isBound(), 'expires' => $this->expires, 'connection_inited' => $this->inited];
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep()
    {
        return ['authKey', 'id', 'serverSalt', 'bound', 'expires', 'inited'];
    }
    /**
     * Wakeup function.
     *
     * @return void
     */
    public function __wakeup() : void
    {
        $this->inited = (bool) $this->inited;
    }
}<?php

/**
 * RPCErrorException module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
/**
 * Indicates an error returned by Telegram's API.
 */
class RPCErrorException extends \Exception
{
    use TL\PrettyException;
    /**
     * RPC error code.
     */
    public string $rpc = '';
    private $fetched = false;
    public static $descriptions = ['RPC_MCGET_FAIL' => 'Telegram is having internal issues, please try again later.', 'RPC_CALL_FAIL' => 'Telegram is having internal issues, please try again later.', 'USER_PRIVACY_RESTRICTED' => "The user's privacy settings do not allow you to do this", 'CHANNEL_PRIVATE' => "You haven't joined this channel/supergroup", 'USER_IS_BOT' => "Bots can't send messages to other bots", 'BOT_METHOD_INVALID' => 'This method cannot be run by a bot', 'PHONE_CODE_EXPIRED' => 'The phone code you provided has expired, this may happen if it was sent to any chat on telegram (if the code is sent through a telegram chat (not the official account) to avoid it append or prepend to the code some chars)', 'USERNAME_INVALID' => 'The provided username is not valid', 'ACCESS_TOKEN_INVALID' => 'The provided token is not valid', 'ACTIVE_USER_REQUIRED' => 'The method is only available to already activated users', 'FIRSTNAME_INVALID' => 'The first name is invalid', 'LASTNAME_INVALID' => 'The last name is invalid', 'PHONE_NUMBER_INVALID' => 'The phone number is invalid', 'PHONE_CODE_HASH_EMPTY' => 'phone_code_hash is missing', 'PHONE_CODE_EMPTY' => 'phone_code is missing', 'API_ID_INVALID' => 'The api_id/api_hash combination is invalid', 'PHONE_NUMBER_OCCUPIED' => 'The phone number is already in use', 'PHONE_NUMBER_UNOCCUPIED' => 'The phone number is not yet being used', 'USERS_TOO_FEW' => 'Not enough users (to create a chat, for example)', 'USERS_TOO_MUCH' => 'The maximum number of users has been exceeded (to create a chat, for example)', 'TYPE_CONSTRUCTOR_INVALID' => 'The type constructor is invalid', 'FILE_PART_INVALID' => 'The file part number is invalid', 'FILE_PARTS_INVALID' => 'The number of file parts is invalid', 'MD5_CHECKSUM_INVALID' => 'The MD5 checksums do not match', 'PHOTO_INVALID_DIMENSIONS' => 'The photo dimensions are invalid', 'FIELD_NAME_INVALID' => 'The field with the name FIELD_NAME is invalid', 'FIELD_NAME_EMPTY' => 'The field with the name FIELD_NAME is missing', 'MSG_WAIT_FAILED' => 'A waiting call returned an error', 'USERNAME_NOT_OCCUPIED' => 'The provided username is not occupied', 'PHONE_NUMBER_BANNED' => 'The provided phone number is banned from telegram', 'AUTH_KEY_UNREGISTERED' => 'The authorization key has expired', 'INVITE_HASH_EXPIRED' => 'The invite link has expired', 'USER_DEACTIVATED' => 'The user was deactivated', 'USER_ALREADY_PARTICIPANT' => 'The user is already in the group', 'MESSAGE_ID_INVALID' => 'The provided message id is invalid', 'PEER_ID_INVALID' => 'The provided peer id is invalid', 'CHAT_ID_INVALID' => 'The provided chat id is invalid', 'MESSAGE_DELETE_FORBIDDEN' => "You can't delete one of the messages you tried to delete, most likely because it is a service message.", 'CHAT_ADMIN_REQUIRED' => 'You must be an admin in this chat to do this', -429 => 'Too many requests', 'PEER_FLOOD' => "You are spamreported, you can't do this"];
    public static $errorMethodMap = [];
    private $caller = '';
    /**
     *
     */
    public static function localizeMessage($method, int $code, string $error)
    {
        if (!$method || !$code || !$error) {
            return $error;
        }
        $error = \preg_replace('/\\d+$/', "X", $error);
        $description = self::$descriptions[$error] ?? '';
        if (!isset(self::$errorMethodMap[$code][$method][$error]) || !isset(self::$descriptions[$error]) || $code === 500) {
            Tools::callFork((function () use($method, $code, $error) {
                try {
                    $res = \json_decode((yield ((yield HttpClientBuilder::buildDefault()->request(new Request('https://rpc.pwrtelegram.xyz/?method=' . $method . '&code=' . $code . '&error=' . $error))))->getBody()->buffer()), true);
                    if (isset($res['ok']) && $res['ok'] && isset($res['result'])) {
                        $description = $res['result'];
                        RPCErrorException::$descriptions[$error] = $description;
                        RPCErrorException::$errorMethodMap[$code][$method][$error] = $error;
                    }
                } catch (\Throwable $e) {
                }
            })());
        }
        if (!$description) {
            return $error;
        }
        return $description;
    }
    /**
     *
     */
    public function __toString()
    {
        $this->localized ??= self::localizeMessage($this->caller, $this->code, $this->message);
        $result = \sprintf(\danog\MadelineProto\Lang::$current_lang['rpc_tg_error'], $this->localized . " ({$this->code})", $this->rpc, $this->file, $this->line . PHP_EOL, \danog\MadelineProto\Magic::$revision . PHP_EOL . PHP_EOL) . PHP_EOL . $this->getTLTrace() . PHP_EOL;
        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
            $result = \str_replace(PHP_EOL, '<br>' . PHP_EOL, $result);
        }
        return $result;
    }
    /**
     * Get localized error name.
     *
     * @return string
     */
    public function getLocalization() : string
    {
        $this->localized ??= self::localizeMessage($this->caller, $this->code, $this->message);
        return $this->localized;
    }
    /**
     * Set localized error name.
     *
     * @param string $localization
     * @return void
     */
    public function setLocalization(string $localization) : void
    {
        $this->localized = $localization;
    }
    /**
     *
     */
    public function __construct($message = null, $code = 0, $caller = '', Exception $previous = null)
    {
        $this->rpc = $message;
        parent::__construct($message, $code, $previous);
        if (\is_string($caller)) {
            $this->prettifyTL($caller);
            $this->caller = $caller;
            $additional = [];
            foreach ($this->getTrace() as $level) {
                if (isset($level['function']) && $level['function'] === 'methodCall') {
                    $this->line = $level['line'];
                    $this->file = $level['file'];
                    $additional = $level['args'];
                }
            }
        }
        /*
        if (\in_array($this->rpc, ['CHANNEL_PRIVATE', -404, -429, 'USERNAME_NOT_OCCUPIED', 'ACCESS_TOKEN_INVALID', 'AUTH_KEY_UNREGISTERED', 'SESSION_PASSWORD_NEEDED', 'PHONE_NUMBER_UNOCCUPIED', 'PEER_ID_INVALID', 'CHAT_ID_INVALID', 'USERNAME_INVALID', 'CHAT_WRITE_FORBIDDEN', 'CHAT_ADMIN_REQUIRED', 'PEER_FLOOD'])) {
            return;
        }
        if (\strpos($this->rpc, 'FLOOD_WAIT_') !== false) {
            return;
        }
        $message === 'Telegram is having internal issues, please try again later.' ? \Rollbar\Rollbar::log(\Rollbar\Payload\Level::critical(), $message) : \Rollbar\Rollbar::log(\Rollbar\Payload\Level::error(), $this, $additional);
        */
    }
}<?php

/**
 * API module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Deferred;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use danog\MadelineProto\Ipc\Client;
use danog\MadelineProto\Ipc\Server;
use danog\MadelineProto\Settings\Ipc as SettingsIpc;
use danog\MadelineProto\Settings\Logger as SettingsLogger;
/**
 * Main API wrapper for MadelineProto.
 */
class API extends InternalDoc
{
    /**
     * Release version.
     *
     * @var string
     */
    const RELEASE = MTProto::RELEASE;
    /**
     * We're not logged in.
     *
     * @var int
     */
    const NOT_LOGGED_IN = MTProto::NOT_LOGGED_IN;
    /**
     * We're waiting for the login code.
     *
     * @var int
     */
    const WAITING_CODE = MTProto::WAITING_CODE;
    /**
     * We're waiting for parameters to sign up.
     *
     * @var int
     */
    const WAITING_SIGNUP = MTProto::WAITING_SIGNUP;
    /**
     * We're waiting for the 2FA password.
     *
     * @var int
     */
    const WAITING_PASSWORD = MTProto::WAITING_PASSWORD;
    /**
     * We're logged in.
     *
     * @var int
     */
    const LOGGED_IN = MTProto::LOGGED_IN;
    /**
     * Secret chat was not found.
     *
     * @var int
     */
    const SECRET_EMPTY = MTProto::SECRET_EMPTY;
    /**
     * Secret chat was requested.
     *
     * @var int
     */
    const SECRET_REQUESTED = MTProto::SECRET_REQUESTED;
    /**
     * Secret chat was found.
     *
     * @var int
     */
    const SECRET_READY = MTProto::SECRET_READY;
    use \danog\Serializable;
    use \danog\MadelineProto\ApiWrappers\Start;
    use \danog\MadelineProto\ApiWrappers\Templates;
    /**
     * Session paths.
     *
     * @internal
     * @var SessionPaths
     */
    public $session;
    /**
     * Instance of MadelineProto.
     *
     * @var null|MTProto|Client
     */
    public $API;
    /**
     * Storage for externally set properties to be serialized.
     *
     * @var array
     */
    protected array $storage = [];
    /**
     * Whether we're getting our API ID.
     *
     * @internal
     *
     * @var boolean
     */
    private bool $gettingApiId = false;
    /**
     * my.telegram.org API wrapper.
     *
     * @internal
     *
     * @var null|MyTelegramOrgWrapper
     */
    private $myTelegramOrgWrapper;
    /**
     * Whether this is an old instance.
     *
     * @var boolean
     */
    private bool $oldInstance = false;
    /**
     * Whether we're destructing.
     *
     * @var boolean
     */
    private bool $destructing = false;
    /**
     * API wrapper (to avoid circular references).
     *
     * @var APIWrapper
     */
    private $wrapper;
    /**
     * Unlock callback.
     *
     * @var ?callable
     */
    private $unlock = null;
    /**
     * Magic constructor function.
     *
     * @param string $session Session name
     * @param (array | Settings) $settings Settings
     *
     * @return void
     */
    public function __magic_construct(string $session, $settings = []) : void
    {
        Magic::start(true);
        $settings = Settings::parseFromLegacy($settings);
        $this->session = new SessionPaths($session);
        $this->wrapper = new APIWrapper($this, $this->exportNamespace());
        $this->setInitPromise($this->internalInitAPI($settings));
        foreach (\get_class_vars(APIFactory::class) as $key => $var) {
            if (\in_array($key, ['namespace', 'API', 'lua', 'async', 'asyncAPIPromise', 'methods'])) {
                continue;
            }
            if (!$this->{$key}) {
                $this->{$key} = $this->exportNamespace($key);
            }
        }
    }
    /**
     * Async constructor function.
     *
     * @param (Settings | SettingsEmpty | SettingsIpc) $settings Settings
     *
     * @return \Generator
     */
    private function internalInitAPI(SettingsAbstract $settings) : \Generator
    {
        Logger::constructorFromSettings($settings instanceof Settings ? $settings->getLogger() : ($settings instanceof SettingsLogger ? $settings : new SettingsLogger()));
        if (yield from $this->connectToMadelineProto($settings)) {
            return;
            // OK
        }
        if (!$settings instanceof Settings) {
            $newSettings = new Settings();
            $newSettings->merge($settings);
            $settings = $newSettings;
        }
        $appInfo = $settings->getAppInfo();
        if (!$appInfo->hasApiInfo()) {
            $app = (yield from $this->APIStart($settings));
            if (!$app) {
                $this->forceInit(true);
                die;
            }
            $appInfo->setApiId($app['api_id']);
            $appInfo->setApiHash($app['api_hash']);
        }
        $this->API = new MTProto($settings, $this->wrapper);
        yield from $this->API->initAsynchronously();
        $this->APIFactory();
        $this->logger->logger(Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
    }
    /**
     * Reconnect to full instance.
     *
     * @return \Generator
     */
    protected function reconnectFull() : \Generator
    {
        if (!$this->API) {
            yield from $this->initAsynchronously();
        }
        if ($this->API instanceof Client) {
            $this->logger->logger("Restarting to full instance...");
            try {
                if (!isset($_GET['MadelineSelfRestart']) && ((yield $this->hasEventHandler()) || !(yield $this->isIpcWorker()))) {
                    $this->logger->logger("Restarting to full instance: the bot is already running!");
                    Tools::closeConnection((yield $this->getWebMessage("The bot is already running!")));
                    return false;
                }
                $this->logger->logger("Restarting to full instance: stopping IPC server...");
                (yield $this->API->stopIpcServer());
                $this->logger->logger("Restarting to full instance: disconnecting from IPC server...");
                (yield $this->API->disconnect());
            } catch (SecurityException $e) {
                throw $e;
            } catch (\Throwable $e) {
                $this->logger->logger("Restarting to full instance: error {$e}");
            }
            $this->logger->logger("Restarting to full instance: reconnecting...");
            $cancel = new Deferred();
            $cb = function () use($cancel, &$cb) : \Generator {
                [$result] = (yield from Serialization::tryConnect($this->session->getIpcPath(), $cancel->promise()));
                if ($result instanceof ChannelledSocket) {
                    try {
                        if (!$this->API instanceof Client) {
                            $this->logger->logger("Restarting to full instance (again): the bot is already running!");
                            (yield $result->disconnect());
                            return;
                        }
                        $API = new Client($result, $this->session, Logger::$default, $this->async);
                        if ((yield from $API->hasEventHandler()) || !(yield from $API->isIpcWorker())) {
                            $this->logger->logger("Restarting to full instance (again): the bot is already running!");
                            (yield $API->disconnect());
                            $API->unreference();
                            return;
                        }
                        $this->logger->logger("Restarting to full instance: stopping another IPC server...");
                        (yield $API->stopIpcServer());
                        $this->logger->logger("Restarting to full instance: disconnecting from IPC server...");
                        (yield $API->disconnect());
                        $API->unreference();
                    } catch (SecurityException $e) {
                        throw $e;
                    } catch (\Throwable $e) {
                        $this->logger->logger("Restarting to full instance: error in stop loop {$e}");
                    }
                    Tools::callFork($cb());
                }
            };
            Tools::callFork($cb());
            yield from $this->connectToMadelineProto(new SettingsEmpty(), true);
            $cancel->resolve(new Exception('Connected!'));
        }
        return true;
    }
    /**
     * Connect to MadelineProto.
     *
     * @param SettingsAbstract $settings Settings
     * @param bool $forceFull Whether to force full initialization
     *
     * @return \Generator
     */
    protected function connectToMadelineProto(SettingsAbstract $settings, bool $forceFull = false, bool $tryReconnect = true) : \Generator
    {
        if ($settings instanceof SettingsIpc) {
            $forceFull = $forceFull || $settings->getSlow();
        } elseif ($settings instanceof Settings) {
            $forceFull = $forceFull || $settings->getIpc()->getSlow();
        }
        $forceFull = $forceFull || isset($_GET['MadelineSelfRestart']) || Magic::$altervista;
        [$unserialized, $this->unlock] = (yield Tools::timeoutWithDefault(Serialization::unserialize($this->session, $settings, $forceFull), 30000, [0, null]));
        if ($unserialized === 0) {
            // Timeout
            Logger::log("!!! Could not connect to MadelineProto, please check and report the logs for more details. !!!", Logger::FATAL_ERROR);
            if (!$tryReconnect || \defined('MADELINEPROTO_TEST') && \constant("MADELINEPROTO_TEST") === 'testing') {
                throw new Exception('Could not connect to MadelineProto, please check the MadelineProto.log file to debug!');
            }
            Logger::log("!!! Reconnecting using slower method. !!!", Logger::FATAL_ERROR);
            // IPC server error, try fetching full session
            return yield from $this->connectToMadelineProto($settings, true, false);
        } elseif ($unserialized instanceof \Throwable) {
            // IPC server error, try fetching full session
            return yield from $this->connectToMadelineProto($settings, true);
        } elseif ($unserialized instanceof ChannelledSocket) {
            // Success, IPC client
            $this->API = new Client($unserialized, $this->session, Logger::$default, $this->async);
            $this->APIFactory();
            return true;
        } elseif ($unserialized) {
            // Success, full session
            if ($this->API) {
                $this->API->unreference();
                $this->API = null;
            }
            $unserialized->storage = $unserialized->storage ?? [];
            $unserialized->session = $this->session;
            APIWrapper::link($this, $unserialized);
            APIWrapper::link($this->wrapper, $this);
            AbstractAPIFactory::link($this->wrapper->getFactory(), $this);
            if (isset($this->API)) {
                $this->storage = $this->API->storage ?? $this->storage;
                unset($unserialized);
                if ($settings instanceof SettingsIpc) {
                    $settings = new SettingsEmpty();
                }
                $this->methods = self::getInternalMethodList($this->API, MTProto::class);
                yield from $this->API->wakeup($settings, $this->wrapper);
                $this->APIFactory();
                $this->logger->logger(Lang::$current_lang['madelineproto_ready'], Logger::NOTICE);
                return true;
            }
        }
        return false;
    }
    /**
     * Wakeup function.
     *
     * @return void
     */
    public function __wakeup() : void
    {
        $this->oldInstance = true;
    }
    /**
     * Destruct function.
     *
     * @internal
     */
    public function __destruct()
    {
        $this->init();
        if (!$this->oldInstance) {
            $this->logger->logger('Shutting down MadelineProto (' . static::class . ')');
            $this->destructing = true;
            if ($this->API) {
                if ($this->API instanceof Tools) {
                    $this->API->destructing = true;
                }
                $this->API->unreference();
            }
            if (isset($this->wrapper) && (!Magic::$signaled || $this->gettingApiId)) {
                $this->logger->logger('Prompting final serialization...');
                Tools::wait($this->wrapper->serialize());
                $this->logger->logger('Done final serialization!');
            }
            if ($this->unlock) {
                ($this->unlock)();
            }
        } elseif ($this->logger) {
            $this->logger->logger('Shutting down MadelineProto (old deserialized instance of API)');
        }
    }
    /**
     * Init API wrapper.
     *
     * @return void
     */
    private function APIFactory() : void
    {
        if ($this->API && $this->API->inited()) {
            if ($this->API instanceof MTProto) {
                foreach ($this->API->getMethodNamespaces() as $namespace) {
                    if (!$this->{$namespace}) {
                        $this->{$namespace} = $this->exportNamespace($namespace);
                    }
                }
            }
            $this->methods = self::getInternalMethodList($this->API, MTProto::class);
        }
    }
    /**
     * Start MadelineProto and the event handler (enables async).
     *
     * Also initializes error reporting, catching and reporting all errors surfacing from the event loop.
     *
     * @param string $eventHandler Event handler class name
     *
     * @return void
     */
    public function startAndLoop(string $eventHandler) : void
    {
        $errors = [];
        $started = false;
        while (true) {
            try {
                Tools::wait($this->startAndLoopAsyncInternal($eventHandler, $started));
                return;
            } catch (SecurityException $e) {
                throw $e;
            } catch (\Throwable $e) {
                $t = \time();
                $errors = [$t => $errors[$t] ?? 0];
                $errors[$t]++;
                if ($errors[$t] > 10 && (!$this->inited() || !$started)) {
                    $this->logger->logger("More than 10 errors in a second and not inited, exiting!", Logger::FATAL_ERROR);
                    return;
                }
                echo $e;
                $this->logger->logger((string) $e, Logger::FATAL_ERROR);
                $this->report("Surfaced: {$e}");
            }
        }
    }
    /**
     * Start multiple instances of MadelineProto and the event handlers (enables async).
     *
     * @param API[] $instances Instances of madeline
     * @param (string[] | string) $eventHandler Event handler(s)
     *
     * @return void
     */
    public static function startAndLoopMulti(array $instances, $eventHandler) : void
    {
        if (\is_string($eventHandler)) {
            $eventHandler = \array_fill_keys(\array_keys($instances), $eventHandler);
        }
        $errors = [];
        $started = \array_fill_keys(\array_keys($instances), false);
        $instanceOne = \array_values($instances)[0];
        while (true) {
            try {
                $promises = [];
                foreach ($instances as $k => $instance) {
                    $instance->start(['async' => false]);
                    $promises[] = $instance->startAndLoopAsyncInternal($eventHandler[$k], $started[$k]);
                }
                Tools::wait(Tools::all($promises));
                return;
            } catch (SecurityException $e) {
                throw $e;
            } catch (\Throwable $e) {
                $t = \time();
                $errors = [$t => $errors[$t] ?? 0];
                $errors[$t]++;
                if ($errors[$t] > 10 && \array_sum($started) !== \count($eventHandler)) {
                    $instanceOne->logger("More than 10 errors in a second and not inited, exiting!", Logger::FATAL_ERROR);
                    return;
                }
                echo $e;
                $instanceOne->logger((string) $e, Logger::FATAL_ERROR);
                $instanceOne->report("Surfaced: {$e}");
            }
        }
    }
    /**
     * Start MadelineProto and the event handler (enables async).
     *
     * Also initializes error reporting, catching and reporting all errors surfacing from the event loop.
     *
     * @param string $eventHandler Event handler class name
     *
     * @return \Generator
     */
    public function startAndLoopAsync(string $eventHandler) : \Generator
    {
        $started = false;
        return $this->startAndLoopAsyncInternal($eventHandler, $started);
    }
    /**
     * Start MadelineProto and the event handler (enables async).
     *
     * Also initializes error reporting, catching and reporting all errors surfacing from the event loop.
     *
     * @param string $eventHandler Event handler class name
     *
     * @return \Generator
     */
    private function startAndLoopAsyncInternal(string $eventHandler, bool &$started) : \Generator
    {
        $this->async(true);
        (yield $this->start());
        if (!(yield from $this->reconnectFull())) {
            return;
        }
        $errors = [];
        while (true) {
            try {
                (yield $this->setEventHandler($eventHandler));
                $started = true;
                /** @var API $this->API */
                return yield from $this->API->loop();
            } catch (SecurityException $e) {
                throw $e;
            } catch (\Throwable $e) {
                $t = \time();
                $errors = [$t => $errors[$t] ?? 0];
                $errors[$t]++;
                if ($errors[$t] > 10 && (!$this->inited() || !$started)) {
                    $this->logger->logger("More than 10 errors in a second and not inited, exiting!", Logger::FATAL_ERROR);
                    return;
                }
                echo $e;
                $this->logger->logger((string) $e, Logger::FATAL_ERROR);
                $this->report("Surfaced: {$e}");
            }
        }
    }
    /**
     * Get attribute.
     *
     * @param string $name Attribute nam
     *
     * @internal
     *
     * @return mixed
     */
    public function &__get(string $name)
    {
        if ($name === 'logger') {
            if (isset($this->API)) {
                return $this->API->logger;
            }
            return Logger::$default;
        }
        return $this->storage[$name];
    }
    /**
     * Set an attribute.
     *
     * @param string $name Name
     * @param mixed $value Value
     *
     * @internal
     *
     * @return mixed
     */
    public function __set(string $name, $value)
    {
        return $this->storage[$name] = $value;
    }
    /**
     * Whether an attribute exists.
     *
     * @param string $name Attribute name
     *
     * @return boolean
     */
    public function __isset(string $name) : bool
    {
        return isset($this->storage[$name]);
    }
    /**
     * Unset attribute.
     *
     * @param string $name Attribute name
     *
     * @return void
     */
    public function __unset(string $name) : void
    {
        unset($this->storage[$name]);
    }
}<?php

/**
 * Session paths module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Ipc\IpcState;
use function Amp\File\exists;
use function Amp\File\openFile;
use function Amp\File\put;
use function Amp\File\rename as renameAsync;
use function Amp\File\stat;
/**
 * Session path information.
 */
class SessionPaths
{
    /**
     * Legacy session path.
     */
    private string $legacySessionPath;
    /**
     * Session path.
     */
    private string $sessionPath;
    /**
     * Session lock path.
     */
    private string $lockPath;
    /**
     * IPC socket path.
     */
    private string $ipcPath;
    /**
     * IPC callback socket path.
     */
    private string $ipcCallbackPath;
    /**
     * IPC light state path.
     */
    private string $ipcStatePath;
    /**
     * Light state path.
     */
    private string $lightStatePath;
    /**
     * Light state.
     */
    private ?LightState $lightState = null;
    /**
     * Construct session info from session name.
     *
     * @param string $session Session name
     */
    public function __construct(string $session)
    {
        $session = Tools::absolute($session);
        $this->legacySessionPath = $session;
        $this->sessionPath = "{$session}.safe.php";
        $this->lightStatePath = "{$session}.lightState.php";
        $this->lockPath = "{$session}.lock";
        $this->ipcPath = "{$session}.ipc";
        $this->ipcCallbackPath = "{$session}.callback.ipc";
        $this->ipcStatePath = "{$session}.ipcState.php";
    }
    /**
     * Serialize object to file.
     *
     * @param object $object
     * @param string $path
     * @return \Generator
     */
    public function serialize(object $object, string $path) : \Generator
    {
        Logger::log("Waiting for exclusive lock of {$path}.lock...");
        $unlock = (yield from Tools::flockGenerator("{$path}.lock", LOCK_EX, 0.1));
        try {
            Logger::log("Got exclusive lock of {$path}.lock...");
            $object = Serialization::PHP_HEADER . \chr(Serialization::VERSION) . \chr(PHP_MAJOR_VERSION) . \chr(PHP_MINOR_VERSION) . \serialize($object);
            (yield put("{$path}.temp.php", $object));
            (yield renameAsync("{$path}.temp.php", $path));
        } finally {
            $unlock();
        }
    }
    /**
     * Deserialize new object.
     *
     * @param string $path Object path, defaults to session path
     *
     * @return \Generator
     *
     * @psalm-return \Generator<mixed, mixed, mixed, object>
     */
    public function unserialize(string $path = '') : \Generator
    {
        $path = $path ?: $this->sessionPath;
        if (!(yield exists($path))) {
            return null;
        }
        $headerLen = \strlen(Serialization::PHP_HEADER);
        Logger::log("Waiting for shared lock of {$path}.lock...", Logger::ULTRA_VERBOSE);
        $unlock = (yield from Tools::flockGenerator("{$path}.lock", LOCK_SH, 0.1));
        try {
            Logger::log("Got shared lock of {$path}.lock...", Logger::ULTRA_VERBOSE);
            $file = (yield openFile($path, 'rb'));
            $size = (yield stat($path));
            $size = $size['size'] ?? $headerLen;
            (yield $file->seek($headerLen++));
            $v = \ord((yield $file->read(1)));
            if ($v === Serialization::VERSION) {
                $php = (yield $file->read(2));
                $major = \ord($php[0]);
                $minor = \ord($php[1]);
                if (\version_compare("{$major}.{$minor}", PHP_VERSION) > 0) {
                    throw new Exception("Cannot deserialize session created on newer PHP {$major}.{$minor}, currently using PHP " . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . ', please upgrade to the latest version of PHP!');
                }
                $headerLen += 2;
            }
            $unserialized = \unserialize((yield $file->read($size - $headerLen)) ?? '');
            (yield $file->close());
        } finally {
            $unlock();
        }
        return $unserialized;
    }
    /**
     * Get session path.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->legacySessionPath;
    }
    /**
     * Get legacy session path.
     *
     * @return string
     */
    public function getLegacySessionPath() : string
    {
        return $this->legacySessionPath;
    }
    /**
     * Get session path.
     *
     * @return string
     */
    public function getSessionPath() : string
    {
        return $this->sessionPath;
    }
    /**
     * Get lock path.
     *
     * @return string
     */
    public function getLockPath() : string
    {
        return $this->lockPath;
    }
    /**
     * Get IPC socket path.
     *
     * @return string
     */
    public function getIpcPath() : string
    {
        return $this->ipcPath;
    }
    /**
     * Get IPC light state path.
     *
     * @return string
     */
    public function getIpcStatePath() : string
    {
        return $this->ipcStatePath;
    }
    /**
     * Get IPC state.
     *
     * @psalm-suppress InvalidReturnType
     * @return Promise<?IpcState>
     */
    public function getIpcState() : Promise
    {
        return Tools::call($this->unserialize($this->ipcStatePath));
    }
    /**
     * Store IPC state.
     *
     * @return \Generator
     */
    public function storeIpcState(IpcState $state) : \Generator
    {
        return $this->serialize($state, $this->getIpcStatePath());
    }
    /**
     * Get light state path.
     *
     * @return string
     */
    public function getLightStatePath() : string
    {
        return $this->lightStatePath;
    }
    /**
     * Get light state.
     *
     * @psalm-suppress InvalidReturnType
     * @return Promise<LightState>
     */
    public function getLightState() : Promise
    {
        if ($this->lightState) {
            return new Success($this->lightState);
        }
        $promise = Tools::call($this->unserialize($this->lightStatePath));
        $promise->onResolve(function (?\Throwable $e, ?LightState $res) {
            if ($res) {
                $this->lightState = $res;
            }
        });
        return $promise;
    }
    /**
     * Store light state.
     *
     * @return \Generator
     */
    public function storeLightState(MTProto $state) : \Generator
    {
        $this->lightState = new LightState($state);
        return $this->serialize($this->lightState, $this->getLightStatePath());
    }
    /**
     * Get IPC callback socket path.
     *
     * @return string
     */
    public function getIpcCallbackPath() : string
    {
        return $this->ipcCallbackPath;
    }
}<?php

namespace danog\MadelineProto;

use ReflectionClass;
use ReflectionProperty;
abstract class SettingsAbstract
{
    /**
     * Whether this setting was changed.
     *
     * @var boolean
     */
    protected $changed = true;
    /**
     * Merge legacy settings array.
     *
     * @param array $settings Settings array
     *
     * @internal
     *
     * @return void
     */
    public function mergeArray(array $settings) : void
    {
    }
    /**
     * Merge with other settings instance.
     *
     * @param self $other
     *
     * @internal
     *
     * @return void
     */
    public function merge(self $other) : void
    {
        $class = new ReflectionClass($other);
        $defaults = $class->getDefaultProperties();
        foreach ($class->getProperties(ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PUBLIC) as $property) {
            $name = $property->getName();
            if ($name === 'changed') {
                continue;
            }
            $uc = \ucfirst($name);
            if (isset($other->{$name}) && (!isset($defaults[$name]) || ($other->{$name} !== $defaults[$name] || $other->{$name} !== $this->{$name})) && (!isset($this->{$name}) || $other->{$name} !== $this->{$name})) {
                $this->{"set{$uc}"}($other->{$name});
                $this->changed = true;
            }
        }
    }
    /**
     * Convert array of legacy array property names to new camel case names.
     *
     * @param array $properties Properties
     *
     * @return array
     */
    protected static function toCamel(array $properties) : array
    {
        $result = [];
        foreach ($properties as $prop) {
            $result['set' . \ucfirst(Tools::toCamelCase($prop))] = $prop;
        }
        return $result;
    }
    /**
     * Get whether this setting was changed, also applies changes.
     *
     * @internal
     *
     * @return boolean
     */
    public function hasChanged() : bool
    {
        return $this->changed;
    }
    /**
     * Apply changes.
     *
     * @internal
     *
     * @return static
     */
    public function applyChanges() : self
    {
        $this->changed = false;
        return $this;
    }
    /**
     * @deprecated
     *
     * @param string $name
     * @param array $arguments
     * @return static
     */
    public function __call(string $name, array $arguments)
    {
        $phabelReturn = $this;
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
}<?php

/**
 * Async constructor abstract class.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Async;

use Amp\Promise;
use danog\MadelineProto\Tools;
/**
 * Async constructor class.
 *
 * Manages asynchronous construction and wakeup of classes
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class AsyncConstruct
{
    /**
     * Async init promise.
     *
     * @var Promise|\Generator|null|boolean
     */
    private $asyncInitPromise;
    /**
     * Blockingly init.
     *
     * @return void
     */
    public function init() : void
    {
        if ($this->asyncInitPromise) {
            Tools::wait($this->asyncInitPromise);
            $this->asyncInitPromise = null;
        }
    }
    /**
     * Asynchronously init.
     *
     * @return \Generator
     */
    public function initAsynchronously() : \Generator
    {
        if ($this->asyncInitPromise) {
            (yield $this->asyncInitPromise);
            $this->asyncInitPromise = null;
        }
    }
    /**
     * Check if we've already inited.
     *
     * @return boolean
     */
    public function inited() : bool
    {
        return !$this->asyncInitPromise;
    }
    /**
     * Mark instance as (de)inited forcefully.
     *
     * @param boolean $inited Whether to mark the instance as inited or deinited
     *
     * @return void
     */
    public function forceInit(bool $inited) : void
    {
        $this->asyncInitPromise = $inited ? null : true;
    }
    /**
     * Set init promise.
     *
     * @param (Promise | \Generator) $promise Promise
     *
     * @internal
     *
     * @return void
     */
    public function setInitPromise($promise) : void
    {
        $this->asyncInitPromise = Tools::call($promise);
    }
}<?php

/**
 * This file is automatic generated by build_docs.php file
 * and is used only for autocomplete in multiple IDE
 * don't modify manually.
 */
namespace danog\MadelineProto\TON;

interface liteServer
{
    /**
     *
     *
     * @return liteServer .MasterchainInfo
     */
    public function getMasterchainInfo();
    /**
    *
    *
    * Parameters:
    `#` **mode** -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .MasterchainInfoExt
    */
    public function getMasterchainInfoExt($params);
    /**
     *
     *
     * @return liteServer .CurrentTime
     */
    public function getTime();
    /**
     *
     *
     * @return liteServer .Version
     */
    public function getVersion();
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **id** -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .BlockData
    */
    public function getBlock($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **id** -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .BlockState
    */
    public function getState($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **id**   -
    `#`                  **mode** -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .BlockHeader
    */
    public function getBlockHeader($params);
    /**
    *
    *
    * Parameters:
    `bytes` **body** -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .SendMsgStatus
    */
    public function sendMessage($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt`   **id**      -
    `liteServer.accountId` **account** -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .AccountState
    */
    public function getAccountState($params);
    /**
    *
    *
    * Parameters:
    `#`                    **mode**      -
    `tonNode.blockIdExt`   **id**        -
    `liteServer.accountId` **account**   -
    `long`                 **method_id** -
    `bytes`                **params**    -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .RunMethodResult
    */
    public function runSmcMethod($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **id**        -
    `int`                **workchain** -
    `long`               **shard**     -
    `Bool`               **exact**     -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .ShardInfo
    */
    public function getShardInfo($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **id** -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .AllShardsInfo
    */
    public function getAllShardsInfo($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt`   **id**      -
    `liteServer.accountId` **account** -
    `long`                 **lt**      -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .TransactionInfo
    */
    public function getOneTransaction($params);
    /**
    *
    *
    * Parameters:
    `#`                    **count**   -
    `liteServer.accountId` **account** -
    `long`                 **lt**      -
    `int256`               **hash**    -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .TransactionList
    */
    public function getTransactions($params);
    /**
    *
    *
    * Parameters:
    `#`               **mode**  -
    `tonNode.blockId` **id**    -
    `long`            **lt**    - Optional:
    `int`             **utime** - Optional:.
    *
    * @param array $params Parameters
    *
    * @return liteServer .BlockHeader
    */
    public function lookupBlock($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt`        **id**            -
    `#`                         **mode**          -
    `#`                         **count**         -
    `liteServer.transactionId3` **after**         - Optional:
    `boolean`                   **reverse_order** - Optional:
    `boolean`                   **want_proof**    - Optional:.
    *
    * @param array $params Parameters
    *
    * @return liteServer .BlockTransactions
    */
    public function listBlockTransactions($params);
    /**
    *
    *
    * Parameters:
    `#`                  **mode**         -
    `tonNode.blockIdExt` **known_block**  -
    `tonNode.blockIdExt` **target_block** - Optional:.
    *
    * @param array $params Parameters
    *
    * @return liteServer .PartialBlockProof
    */
    public function getBlockProof($params);
    /**
    *
    *
    * Parameters:
    `#`                  **mode** -
    `tonNode.blockIdExt` **id**   -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .ConfigInfo
    */
    public function getConfigAll($params);
    /**
    *
    *
    * Parameters:
    `#`                  **mode**       -
    `tonNode.blockIdExt` **id**         -
    `[int]`              **param_list** -.
    *
    * @param array $params Parameters
    *
    * @return liteServer .ConfigInfo
    */
    public function getConfigParams($params);
    /**
    *
    *
    * Parameters:
    `#`                  **mode**           -
    `tonNode.blockIdExt` **id**             -
    `int`                **limit**          -
    `int256`             **start_after**    - Optional:
    `int`                **modified_after** - Optional:.
    *
    * @param array $params Parameters
    *
    * @return liteServer .ValidatorStats
    */
    public function getValidatorStats($params);
    /**
     *
     *
     * @return object
     */
    public function queryPrefix();
    /**
    *
    *
    * Parameters:
    `bytes` **data** -.
    *
    * @param array $params Parameters
    *
    * @return object
    */
    public function query($params);
    /**
    *
    *
    * Parameters:
    `int` **seqno**      -
    `int` **timeout_ms** -.
    *
    * @param array $params Parameters
    *
    * @return object
    */
    public function waitMasterchainSeqno($params);
}
interface tcp
{
    /**
     *
     *
     * @return tcp .Pong
     */
    public function ping();
}
interface dht
{
    /**
     *
     *
     * @return dht .Pong
     */
    public function ping();
    /**
    *
    *
    * Parameters:
    `dht.value` **value** -.
    *
    * @param array $params Parameters
    *
    * @return dht .Stored
    */
    public function store($params);
    /**
    *
    *
    * Parameters:
    `int256` **key** -
    `int`    **k**   -.
    *
    * @param array $params Parameters
    *
    * @return dht .Nodes
    */
    public function findNode($params);
    /**
    *
    *
    * Parameters:
    `int256` **key** -
    `int`    **k**   -.
    *
    * @param array $params Parameters
    *
    * @return dht .ValueResult
    */
    public function findValue($params);
    /**
     *
     *
     * @return dht .Node
     */
    public function getSignedAddressList();
    /**
    *
    *
    * Parameters:
    `dht.node` **node** -.
    *
    * @param array $params Parameters
    *
    * @return true
    */
    public function query($params);
}
interface overlay
{
    /**
    *
    *
    * Parameters:
    `overlay.nodes` **peers** -.
    *
    * @param array $params Parameters
    *
    * @return overlay .Nodes
    */
    public function getRandomPeers($params);
    /**
    *
    *
    * Parameters:
    `int256` **overlay** -.
    *
    * @param array $params Parameters
    *
    * @return true
    */
    public function query($params);
    /**
    *
    *
    * Parameters:
    `int256` **hash** -.
    *
    * @param array $params Parameters
    *
    * @return overlay .Broadcast
    */
    public function getBroadcast($params);
    /**
    *
    *
    * Parameters:
    `overlay.broadcastList` **list** -.
    *
    * @param array $params Parameters
    *
    * @return overlay .BroadcastList
    */
    public function getBroadcastList($params);
}
interface catchain
{
    /**
    *
    *
    * Parameters:
    `int256` **block** -.
    *
    * @param array $params Parameters
    *
    * @return catchain .BlockResult
    */
    public function getBlock($params);
    /**
    *
    *
    * Parameters:
    `[int256]` **blocks** -.
    *
    * @param array $params Parameters
    *
    * @return catchain .Sent
    */
    public function getBlocks($params);
    /**
    *
    *
    * Parameters:
    `[int]` **rt** -.
    *
    * @param array $params Parameters
    *
    * @return catchain .Difference
    */
    public function getDifference($params);
    /**
    *
    *
    * Parameters:
    `int256`   **block**   -
    `long`     **height**  -
    `[int256]` **stop_if** -.
    *
    * @param array $params Parameters
    *
    * @return catchain .Sent
    */
    public function getBlockHistory($params);
}
interface validatorSession
{
    /**
    *
    *
    * Parameters:
    `long` **hash** -.
    *
    * @param array $params Parameters
    *
    * @return validatorSession .Pong
    */
    public function ping($params);
    /**
    *
    *
    * Parameters:
    `int`                          **round** -
    `validatorSession.candidateId` **id**    -.
    *
    * @param array $params Parameters
    *
    * @return validatorSession .Candidate
    */
    public function downloadCandidate($params);
}
interface tonNode
{
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **prev_block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .BlockDescription
    */
    public function getNextBlockDescription($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **prev_block** -
    `int`                **limit**      -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .BlocksDescription
    */
    public function getNextBlocksDescription($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **next_block**   -
    `int`                **limit**        -
    `int`                **cutoff_seqno** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .BlocksDescription
    */
    public function getPrevBlocksDescription($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block**         -
    `Bool`               **allow_partial** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .PreparedProof
    */
    public function prepareBlockProof($params);
    /**
    *
    *
    * Parameters:
    `[tonNode.blockIdExt]` **blocks**        -
    `Bool`                 **allow_partial** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .PreparedProof
    */
    public function prepareBlockProofs($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Prepared
    */
    public function prepareBlock($params);
    /**
    *
    *
    * Parameters:
    `[tonNode.blockIdExt]` **blocks** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Prepared
    */
    public function prepareBlocks($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block**             -
    `tonNode.blockIdExt` **masterchain_block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .PreparedState
    */
    public function preparePersistentState($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .PreparedState
    */
    public function prepareZeroState($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block**    -
    `int`                **max_size** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .KeyBlocks
    */
    public function getNextKeyBlockIds($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **prev_block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .DataFull
    */
    public function downloadNextBlockFull($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .DataFull
    */
    public function downloadBlockFull($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Data
    */
    public function downloadBlock($params);
    /**
    *
    *
    * Parameters:
    `[tonNode.blockIdExt]` **blocks** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .DataList
    */
    public function downloadBlocks($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block**             -
    `tonNode.blockIdExt` **masterchain_block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Data
    */
    public function downloadPersistentState($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block**             -
    `tonNode.blockIdExt` **masterchain_block** -
    `long`               **offset**            -
    `long`               **max_size**          -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Data
    */
    public function downloadPersistentStateSlice($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Data
    */
    public function downloadZeroState($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Data
    */
    public function downloadBlockProof($params);
    /**
    *
    *
    * Parameters:
    `[tonNode.blockIdExt]` **blocks** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .DataList
    */
    public function downloadBlockProofs($params);
    /**
    *
    *
    * Parameters:
    `tonNode.blockIdExt` **block** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Data
    */
    public function downloadBlockProofLink($params);
    /**
    *
    *
    * Parameters:
    `[tonNode.blockIdExt]` **blocks** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .DataList
    */
    public function downloadBlockProofLinks($params);
    /**
    *
    *
    * Parameters:
    `int` **masterchain_seqno** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .ArchiveInfo
    */
    public function getArchiveInfo($params);
    /**
    *
    *
    * Parameters:
    `long` **archive_id** -
    `long` **offset**     -
    `int`  **max_size**   -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Data
    */
    public function getArchiveSlice($params);
    /**
     *
     *
     * @return tonNode .Capabilities
     */
    public function getCapabilities();
    /**
    *
    *
    * Parameters:
    `tonNode.externalMessage` **message** -.
    *
    * @param array $params Parameters
    *
    * @return tonNode .Success
    */
    public function slave($params);
    /**
     *
     *
     * @return object
     */
    public function query();
}
interface adnl
{
    /**
    *
    *
    * Parameters:
    `long` **value** -.
    *
    * @param array $params Parameters
    *
    * @return adnl .Pong
    */
    public function ping($params);
}
interface engine
{
    /**
    *
    *
    * Parameters:
    `PrivateKey` **key**                 -
    `int256`     **key_hash**            -
    `int`        **category**            -
    `int`        **election_date**       -
    `int`        **ttl**                 -
    `int256`     **permanent_key_hash**  -
    `int256`     **adnl_id**             -
    `int`        **port**                -
    `int256`     **peer_key**            -
    `int`        **permissions**         -
    `int`        **ip**                  -
    `[int]`      **categories**          -
    `[int]`      **priority_categories** -
    `int`        **in_ip**               -
    `int`        **in_port**             -
    `int`        **out_ip**              -
    `int`        **out_port**            -
    `adnl.Proxy` **proxy**               -
    `bytes`      **data**                -
    `int`        **verbosity**           -
    `string`     **election_addr**       -
    `string`     **wallet**              -
    `int256`     **id**                  -.
    *
    * @param array $params Parameters
    *
    * @return object
    */
    public function validator($params);
}
interface http
{
    /**
    *
    *
    * Parameters:
    `int256`        **id**           -
    `string`        **method**       -
    `string`        **url**          -
    `string`        **http_version** -
    `[http.header]` **headers**      -.
    *
    * @param array $params Parameters
    *
    * @return http .Response
    */
    public function request($params);
    /**
    *
    *
    * Parameters:
    `int256` **id**             -
    `int`    **seqno**          -
    `int`    **max_chunk_size** -.
    *
    * @param array $params Parameters
    *
    * @return http .PayloadPart
    */
    public function getNextPayloadPart($params);
}
class InternalDoc extends APIFactory
{
    /**
     * Call promise $b after promise $a.
     *
     * @param (\Generator | Promise) $a Promise A
     * @param (\Generator | Promise) $b Promise B
     *
     * @psalm-suppress InvalidScope
     *
     * @return \Amp\Promise
     */
    public function after($a, $b)
    {
        return \danog\MadelineProto\Tools::after($a, $b);
    }
    /**
    * Returns a promise that succeeds when all promises succeed, and fails if any promise fails.
    Returned promise succeeds with an array of values used to succeed each contained promise, with keys corresponding to the array of promises.
    *
    * @param array<(\Generator | Promise)> $promises Promises
    *
    * @return \Amp\Promise
    */
    public function all(array $promises)
    {
        return \danog\MadelineProto\Tools::all($promises);
    }
    /**
     * Returns a promise that is resolved when all promises are resolved. The returned promise will not fail.
     *
     * @param array<(Promise | \Generator)> $promises Promises
     *
     * @return \Amp\Promise
     */
    public function any(array $promises)
    {
        return \danog\MadelineProto\Tools::any($promises);
    }
    /**
     * Create array.
     *
     * @param mixed ...$params Params
     *
     * @return array
     */
    public function arr(...$params) : array
    {
        return \danog\MadelineProto\Tools::arr(...$params);
    }
    /**
     * base64URL decode.
     *
     * @param string $data Data to decode
     *
     * @return string
     */
    public function base64urlDecode(string $data) : string
    {
        return \danog\MadelineProto\Tools::base64urlDecode($data);
    }
    /**
     * Base64URL encode.
     *
     * @param string $data Data to encode
     *
     * @return string
     */
    public function base64urlEncode(string $data) : string
    {
        return \danog\MadelineProto\Tools::base64urlEncode($data);
    }
    /**
     * Convert parameters.
     *
     * @param array $parameters Parameters
     *
     * @return \Amp\Promise
     */
    public function botAPItoMTProto(array $parameters, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$parameters, $extra]);
    }
    /**
     * Convert generator, promise or any other value to a promise.
     *
     * @param (\Generator | Promise | mixed) $promise
     *
     * @template TReturn
     * @psalm-param (\Generator<mixed, mixed, mixed, TReturn> | Promise<TReturn> | TReturn) $promise
     *
     * @return \Amp\Promise
     * @psalm-return Promise<TReturn>
     */
    public function call($promise)
    {
        return \danog\MadelineProto\Tools::call($promise);
    }
    /**
     * Call promise in background.
     *
     * @param (\Generator | Promise) $promise Promise to resolve
     * @param ?\Generator|Promise $actual  Promise to resolve instead of $promise
     * @param string $file File
     *
     * @psalm-suppress InvalidScope
     *
     * @return (\Amp\Promise | mixed)
     */
    public function callFork($promise, $actual = null, $file = '')
    {
        return \danog\MadelineProto\Tools::callFork($promise, $actual, $file);
    }
    /**
     * Call promise in background, deferring execution.
     *
     * @param (\Generator | Promise) $promise Promise to resolve
     *
     * @return void
     */
    public function callForkDefer($promise) : void
    {
        \danog\MadelineProto\Tools::callForkDefer($promise);
    }
    /**
     * Close connection with client, connected via web.
     *
     * @param string $message Message
     *
     * @return void
     */
    public function closeConnection($message)
    {
        return \danog\MadelineProto\Tools::closeConnection($message);
    }
    /**
     * Connect to the lite endpoints specified in the config file.
     *
     * @param string $config Path to config file
     *
     * @return \Amp\Promise
     */
    public function connect(string $config, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$config, $extra]);
    }
    /**
     * Asynchronously write to stdout/browser.
     *
     * @param string $string Message to echo
     *
     * @return \Amp\Promise
     */
    public function echo(string $string)
    {
        return \danog\MadelineProto\Tools::echo($string);
    }
    /**
     * Get final element of array.
     *
     * @param array $what Array
     *
     * @return mixed
     */
    public function end(array $what)
    {
        return \danog\MadelineProto\Tools::end($what);
    }
    /**
     * Returns a promise that succeeds when the first promise succeeds, and fails only if all promises fail.
     *
     * @param array<(Promise | \Generator)> $promises Promises
     *
     * @return \Amp\Promise
     */
    public function first(array $promises)
    {
        return \danog\MadelineProto\Tools::first($promises);
    }
    /**
    * Asynchronously lock a file
    Resolves with a callbable that MUST eventually be called in order to release the lock.
    *
    * @param string $file File to lock
    * @param integer $operation Locking mode
    * @param float $polling Polling interval
    * @param ?Promise $token Cancellation token
    * @param ?callable $failureCb Failure callback, called only once if the first locking attempt fails.
    *
    * @return \Amp\Promise<$token is null ? callable : ?callable>
    */
    public function flock(string $file, int $operation, float $polling = 0.1, ?\Amp\Promise $token = null, $failureCb = null)
    {
        return \danog\MadelineProto\Tools::flock($file, $operation, $polling, $token, $failureCb);
    }
    /**
     * Generate MTProto vector hash.
     *
     * @param array $ints IDs
     *
     * @return string Vector hash
     */
    public function genVectorHash(array $ints) : string
    {
        return \danog\MadelineProto\Tools::genVectorHash($ints);
    }
    /**
     * Get extension from file location.
     *
     * @param mixed $location File location
     * @param string $default Default extension
     *
     * @return string
     */
    public function getExtensionFromLocation($location, string $default) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromLocation($location, $default);
    }
    /**
     * Get extension from mime type.
     *
     * @param string $mime MIME type
     *
     * @return string
     */
    public function getExtensionFromMime(string $mime) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getExtensionFromMime($mime);
    }
    /**
     * Get TL method namespaces.
     *
     * @psalm-return (array | \Amp\Promise<array>)
     * @return mixed
     */
    public function getMethodNamespaces()
    {
        return $this->__call(__FUNCTION__, []);
    }
    /**
     * Get mime type from buffer.
     *
     * @param string $buffer Buffer
     *
     * @return string
     */
    public function getMimeFromBuffer(string $buffer) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromBuffer($buffer);
    }
    /**
     * Get mime type from file extension.
     *
     * @param string $extension File extension
     * @param string $default Default mime type
     *
     * @return string
     */
    public function getMimeFromExtension(string $extension, string $default) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromExtension($extension, $default);
    }
    /**
     * Get mime type of file.
     *
     * @param string $file File
     *
     * @return string
     */
    public function getMimeFromFile(string $file) : string
    {
        return \danog\MadelineProto\TL\Conversion\Extension::getMimeFromFile($file);
    }
    /**
     * Accesses a private variable from an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     *
     * @psalm-suppress InvalidScope
     *
     * @return mixed
     * @access public
     */
    public function getVar($obj, string $var)
    {
        return \danog\MadelineProto\Tools::getVar($obj, $var);
    }
    /**
     * Checks private property exists in an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     *
     * @psalm-suppress InvalidScope
     *
     * @return bool
     * @access public
     */
    public function hasVar($obj, string $var) : bool
    {
        return \danog\MadelineProto\Tools::hasVar($obj, $var);
    }
    /**
     * Inflate stripped photosize to full JPG payload.
     *
     * @param string $stripped Stripped photosize
     *
     * @return string JPG payload
     */
    public function inflateStripped(string $stripped) : string
    {
        return \danog\MadelineProto\Tools::inflateStripped($stripped);
    }
    /**
     * Whether this is altervista.
     *
     * @return boolean
     */
    public function isAltervista() : bool
    {
        return \danog\MadelineProto\Tools::isAltervista();
    }
    /**
     * Check if is array or similar (traversable && countable && arrayAccess).
     *
     * @param mixed $var Value to check
     *
     * @return boolean
     */
    public function isArrayOrAlike($var) : bool
    {
        return \danog\MadelineProto\Tools::isArrayOrAlike($var);
    }
    /**
     * Logger.
     *
     * @param string $param Parameter
     * @param int $level Logging level
     * @param string $file File where the message originated
     *
     * @psalm-return (void | \Amp\Promise<void>)
     * @return mixed
     */
    public function logger($param, int $level = \danog\MadelineProto\Logger::NOTICE, string $file = '')
    {
        $this->__call(__FUNCTION__, [$param, $level, $file]);
    }
    /**
     * Asynchronously run async callable.
     *
     * @param callable $func Function
     *
     * @return \Amp\Promise
     */
    public function loop(callable $func, array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$func, $extra]);
    }
    /**
     * Escape string for markdown.
     *
     * @param string $hwat String to escape
     *
     * @return string
     */
    public function markdownEscape(string $hwat) : string
    {
        return \danog\MadelineProto\StrTools::markdownEscape($hwat);
    }
    /**
     * Call lite method.
     *
     * @param string $methodName Method name
     * @param array $args Arguments
     *
     * @return \Amp\Promise
     */
    public function methodCall(string $methodName, array $args = [], array $aargs = [], array $extra = [])
    {
        return $this->__call(__FUNCTION__, [$methodName, $args, $aargs, $extra]);
    }
    /**
     * Escape method name.
     *
     * @param string $method Method name
     *
     * @return string
     */
    public function methodEscape(string $method) : string
    {
        return \danog\MadelineProto\StrTools::methodEscape($method);
    }
    /**
     * Convert double to binary version.
     *
     * @param float $value Value to convert
     *
     * @return string
     */
    public function packDouble(float $value) : string
    {
        return \danog\MadelineProto\Tools::packDouble($value);
    }
    /**
     * Convert integer to base256 signed int.
     *
     * @param integer $value Value to convert
     *
     * @return string
     */
    public function packSignedInt(int $value) : string
    {
        return \danog\MadelineProto\Tools::packSignedInt($value);
    }
    /**
     * Convert integer to base256 long.
     *
     * @param int $value Value to convert
     *
     * @return string
     */
    public function packSignedLong(int $value) : string
    {
        return \danog\MadelineProto\Tools::packSignedLong($value);
    }
    /**
     * Convert value to unsigned base256 int.
     *
     * @param int $value Value
     *
     * @return string
     */
    public function packUnsignedInt(int $value) : string
    {
        return \danog\MadelineProto\Tools::packUnsignedInt($value);
    }
    /**
    * Positive modulo
    Works just like the % (modulus) operator, only returns always a postive number.
    *
    * @param int $a A
    * @param int $b B
    *
    * @return int Modulo
    */
    public function posmod(int $a, int $b) : int
    {
        return \danog\MadelineProto\Tools::posmod($a, $b);
    }
    /**
     * Get random string of specified length.
     *
     * @param integer $length Length
     *
     * @return string Random string
     */
    public function random(int $length) : string
    {
        return \danog\MadelineProto\Tools::random($length);
    }
    /**
     * Get random integer.
     *
     * @param integer $modulus Modulus
     *
     * @return int
     */
    public function randomInt(int $modulus = 0) : int
    {
        return \danog\MadelineProto\Tools::randomInt($modulus);
    }
    /**
     * Asynchronously read line.
     *
     * @param string $prompt Prompt
     *
     * @return \Amp\Promise<string>
     */
    public function readLine(string $prompt = '')
    {
        return \danog\MadelineProto\Tools::readLine($prompt);
    }
    /**
     * Rethrow error catched in strand.
     *
     * @param \Throwable $e Exception
     * @param string $file File where the strand started
     *
     * @psalm-suppress InvalidScope
     *
     * @return void
     */
    public function rethrow(\Throwable $e, $file = '') : void
    {
        \danog\MadelineProto\Tools::rethrow($e, $file);
    }
    /**
     * null-byte RLE decode.
     *
     * @param string $string Data to decode
     *
     * @return string
     */
    public function rleDecode(string $string) : string
    {
        return \danog\MadelineProto\Tools::rleDecode($string);
    }
    /**
     * null-byte RLE encode.
     *
     * @param string $string Data to encode
     *
     * @return string
     */
    public function rleEncode(string $string) : string
    {
        return \danog\MadelineProto\Tools::rleEncode($string);
    }
    /**
     * Sets a private variable in an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     * @param mixed $val Attribute value
     *
     * @psalm-suppress InvalidScope
     *
     * @return void
     *
     * @access public
     */
    public function setVar($obj, string $var, &$val) : void
    {
        \danog\MadelineProto\Tools::setVar($obj, $var, $val);
    }
    /**
     * Asynchronously sleep.
     *
     * @param (int | float) $time Number of seconds to sleep for
     *
     * @return \Amp\Promise
     */
    public function sleep($time)
    {
        return \danog\MadelineProto\Tools::sleep($time);
    }
    /**
    * Resolves with a two-item array delineating successful and failed Promise results.
    The returned promise will only fail if the given number of required promises fail.
    *
    * @param array<(Promise | \Generator)> $promises Promises
    *
    * @return \Amp\Promise
    */
    public function some(array $promises)
    {
        return \danog\MadelineProto\Tools::some($promises);
    }
    /**
     * Create an artificial timeout for any \Generator or Promise.
     *
     * @param (\Generator | Promise) $promise
     * @param integer $timeout
     *
     * @return \Amp\Promise
     */
    public function timeout($promise, int $timeout)
    {
        return \danog\MadelineProto\Tools::timeout($promise, $timeout);
    }
    /**
     * Creates an artificial timeout for any `Promise`.
     *
     * If the promise is resolved before the timeout expires, the result is returned
     *
     * If the timeout expires before the promise is resolved, a default value is returned
     *
     * @template TReturnAlt
     * @template TReturn
     * @template TGenerator of \Generator<mixed, mixed, mixed, TReturn>
     *
     * @param (Promise | Generator) $promise Promise to which the timeout is applied.
     * @param int $timeout Timeout in milliseconds.
     * @param mixed $default
     *
     * @psalm-param (Promise<TReturn> | TGenerator) $promise Promise to which the timeout is applied.
     * @psalm-param TReturnAlt $default
     *
     * @return (\Amp\Promise<TReturn> | Promise<TReturnAlt>)
     *
     * @throws \TypeError If $promise is not an instance of \Amp\Promise, \Generator or \React\Promise\PromiseInterface.
     */
    public function timeoutWithDefault($promise, int $timeout, $default = null)
    {
        return \danog\MadelineProto\Tools::timeoutWithDefault($promise, $timeout, $default);
    }
    /**
     * Convert to camelCase.
     *
     * @param string $input String
     *
     * @return string
     */
    public function toCamelCase(string $input) : string
    {
        return \danog\MadelineProto\StrTools::toCamelCase($input);
    }
    /**
     * Convert to snake_case.
     *
     * @param string $input String
     *
     * @return string
     */
    public function toSnakeCase(string $input) : string
    {
        return \danog\MadelineProto\StrTools::toSnakeCase($input);
    }
    /**
     * Escape type name.
     *
     * @param string $type String to escape
     *
     * @return string
     */
    public function typeEscape(string $type) : string
    {
        return \danog\MadelineProto\StrTools::typeEscape($type);
    }
    /**
     * Unpack binary double.
     *
     * @param string $value Value to unpack
     *
     * @return float
     */
    public function unpackDouble(string $value) : float
    {
        return \danog\MadelineProto\Tools::unpackDouble($value);
    }
    /**
     * Unpack base256 signed int.
     *
     * @param string $value base256 int
     *
     * @return integer
     */
    public function unpackSignedInt(string $value) : int
    {
        return \danog\MadelineProto\Tools::unpackSignedInt($value);
    }
    /**
     * Unpack base256 signed long.
     *
     * @param string $value base256 long
     *
     * @return integer
     */
    public function unpackSignedLong(string $value) : int
    {
        return \danog\MadelineProto\Tools::unpackSignedLong($value);
    }
    /**
     * Unpack base256 signed long to string.
     *
     * @param (string | int | array) $value base256 long
     *
     * @return string
     */
    public function unpackSignedLongString($value) : string
    {
        return \danog\MadelineProto\Tools::unpackSignedLongString($value);
    }
    /**
     * Synchronously wait for a promise|generator.
     *
     * @param (\Generator | Promise) $promise The promise to wait for
     * @param boolean $ignoreSignal Whether to ignore shutdown signals
     *
     * @return mixed
     */
    public function wait($promise, $ignoreSignal = false)
    {
        return \danog\MadelineProto\Tools::wait($promise, $ignoreSignal);
    }
}<?php

/**
 * TON API module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TON;

use danog\MadelineProto\Magic;
use danog\MadelineProto\Settings\Logger;
/**
 * TON API.
 */
class API extends InternalDoc
{
    /**
     * Construct API.
     *
     * @param Logger $settings Settings
     */
    public function __construct(Logger $settings)
    {
        Magic::start();
        $this->API = new Lite($settings);
        foreach (\get_class_methods($this->API) as $method) {
            $this->methods[$method] = [$this->API, \strtolower($method)];
        }
        foreach ($this->API->getMethodNamespaces() as $namespace) {
            $this->{$namespace} = new APIFactory($namespace, $this->API, $this->async);
        }
    }
}<?php

/**
 * APIFactory module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TON;

use danog\MadelineProto\AbstractAPIFactory;
class APIFactory extends AbstractAPIFactory
{
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var http
     */
    public $http;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var engine
     */
    public $engine;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var adnl
     */
    public $adnl;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var tonNode
     */
    public $tonNode;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var validatorSession
     */
    public $validatorSession;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var catchain
     */
    public $catchain;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var overlay
     */
    public $overlay;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var dht
     */
    public $dht;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var tcp
     */
    public $tcp;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var liteServer
     */
    public $liteServer;
    /**
     * Just proxy async requests to API.
     *
     * @param string $name Method name
     * @param array $arguments Arguments
     * @psalm-suppress UndefinedThisPropertyFetch
     * @return \Generator
     */
    public function __call_async(string $name, array $arguments) : \Generator
    {
        $lower_name = \strtolower($name);
        if ($this->namespace !== '' || !isset($this->methods[$lower_name])) {
            $name = $this->namespace . $name;
            $aargs = isset($arguments[1]) && \is_array($arguments[1]) ? $arguments[1] : [];
            $aargs['apifactory'] = true;
            $args = isset($arguments[0]) && \is_array($arguments[0]) ? $arguments[0] : [];
            return yield from $this->API->methodCall($name, $args, $aargs);
        }
        return (yield $this->methods[$lower_name](...$arguments));
    }
}<?php

/**
 * TON API module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TON;

use Amp\Deferred;
use Amp\Socket\ConnectContext;
use danog\MadelineProto\Magic;
use danog\MadelineProto\MTProtoTools\Crypt;
use danog\MadelineProto\Stream\ADNLTransport\ADNLStream;
use danog\MadelineProto\Stream\Common\BufferedRawStream;
use danog\MadelineProto\Stream\Common\CtrStream;
use danog\MadelineProto\Stream\Common\HashedBufferedStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\StreamInterface;
use danog\MadelineProto\Stream\Transport\DefaultStream;
use danog\MadelineProto\TL\TL;
use danog\MadelineProto\Tools;
use Exception;
use phpseclib3\Crypt\DH;
use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\PrivateKey;
use phpseclib3\Crypt\EC\PublicKey;
use phpseclib3\Math\BigInteger;
class ADNLConnection
{
    /**
     * TL serializer instance.
     *
     * @var TL
     */
    private $TL;
    /**
     * ADNL stream instance.
     *
     * @var StreamInterface
     */
    private $stream;
    /**
     * Request list.
     *
     * @var array
     */
    private $requests = [];
    /**
     * Construct class.
     *
     * @param TL $TL TL instance
     */
    public function __construct(TL $TL)
    {
        $this->TL = $TL;
    }
    /**
     * Connect to specified ADNL endpoint.
     *
     * @param array $endpoint Endpoint
     *
     * @return \Generator
     */
    public function connect(array $endpoint) : \Generator
    {
        if ($endpoint['_'] !== 'liteserver.desc') {
            throw new \InvalidArgumentException('Only liteservers are supported at the moment!');
        }
        if ($endpoint['id']['_'] !== 'pub.ed25519') {
            throw new \InvalidArgumentException('Only ECDH is supported at the moment!');
        }
        $random = Tools::random(256 - 32 - 64);
        //$random = strrev(hex2bin(strrev('9E7C27765D12CE634414F0875D55CE5C58E7A9D58CD45C57CAB516D1241B7864691E5B0AFC4ECB54BFF2CEFC2060F1D45F5B5DEB76A9EF6471D75816AAAEC83CD7DE39EE99B9E980B6C0D4565A916D00908613E63657D5539118F89A14FD73ABB8ECD3AC26C287EEBD0FA44F52B315F01DD60F486EFF4C5B4D71EA6F443358FF141E7294BBBB5D7C079F16BD46C28A12507E1948722E7121B94C3B5C7832ADE7')));
        $s1 = \Phabel\Target\Php80\Polyfill::substr($random, 0, 32);
        $s2 = \Phabel\Target\Php80\Polyfill::substr($random, 32, 32);
        $v1 = \Phabel\Target\Php80\Polyfill::substr($random, 64, 16);
        $v2 = \Phabel\Target\Php80\Polyfill::substr($random, 80, 16);
        $obf = ['decrypt' => ['key' => $s1, 'iv' => $v1], 'encrypt' => ['key' => $s2, 'iv' => $v2]];
        // Generating new private/public params
        $private = EC::createKey('Ed25519');
        $public = $private->getPublicKey();
        $public = \strrev(Tools::getVar($public, 'QA')[1]->toBytes());
        $private = \strrev(Tools::getVar($private, 'dA')->toBytes());
        $private = PrivateKey::loadFormat('MontgomeryPrivate', $private);
        // Transpose their public
        $key = $endpoint['id']['key'];
        $key[31] = $key[31] & \chr(127);
        $curve = new Curve25519();
        $modulo = Tools::getVar($curve, "modulo");
        $y = new BigInteger(\strrev($key), 256);
        $y2 = clone $y;
        $y = $y->add(Magic::$one);
        $y2 = $y2->subtract(Magic::$one);
        $y2 = $modulo->subtract($y2)->powMod(Magic::$one, $modulo);
        $y2 = $y2->modInverse($modulo);
        $key = \strrev($y->multiply($y2)->powMod(Magic::$one, $modulo)->toBytes());
        $peerPublic = PublicKey::loadFormat('MontgomeryPublic', $key);
        // Generate secret
        $secret = DH::computeSecret($private, $peerPublic);
        // Encrypting random with obf keys
        $digest = \hash('sha256', $random, true);
        $key = \Phabel\Target\Php80\Polyfill::substr($secret, 0, 16) . \Phabel\Target\Php80\Polyfill::substr($digest, 16, 16);
        $iv = \Phabel\Target\Php80\Polyfill::substr($digest, 0, 4) . \Phabel\Target\Php80\Polyfill::substr($secret, 20, 12);
        $encryptedRandom = Crypt::ctrEncrypt($random, $key, $iv);
        // Generating plaintext init payload
        $payload = \hash('sha256', yield from $this->TL->serializeObject(['type' => ''], $endpoint['id'], 'key'), true);
        $payload .= $public;
        $payload .= $digest;
        $payload .= $encryptedRandom;
        $ip = \long2ip(\unpack('V', Tools::packSignedInt($endpoint['ip']))[1]);
        $port = $endpoint['port'];
        $ctx = (new ConnectionContext())->setSocketContext(new ConnectContext())->setUri("tcp://{$ip}:{$port}")->addStream(DefaultStream::class)->addStream(BufferedRawStream::class)->addStream(CtrStream::class, $obf)->addStream(HashedBufferedStream::class, 'sha256')->addStream(ADNLStream::class);
        $this->stream = (yield from $ctx->getStream($payload));
        Tools::callFork((function () : \Generator {
            //yield Tools::sleep(1);
            while (true) {
                $buffer = (yield $this->stream->getReadBuffer($length));
                if ($length) {
                    $data = (yield $buffer->bufferRead($length));
                    $data = $this->TL->deserialize($data)[0];
                    if ($data['_'] !== 'adnl.message.answer') {
                        throw new Exception('Wrong answer type: ' . $data['_']);
                    }
                    $this->requests[$data['query_id']]->resolve($this->TL->deserialize((string) $data['answer'])[0]);
                }
            }
        })());
    }
    /**
     * Send ADNL query.
     *
     * @param string $payload Payload to send
     *
     * @return \Generator
     */
    public function query(string $payload) : \Generator
    {
        $data = (yield from $this->TL->serializeObject(['type' => ''], ['_' => 'adnl.message.query', 'query_id' => $id = Tools::random(32), 'query' => $payload], ''));
        ((yield $this->stream->getWriteBuffer(\strlen($data))))->bufferWrite($data);
        $this->requests[$id] = new Deferred();
        return $this->requests[$id]->promise();
    }
}<?php

/**
 * TON API module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TON;

use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Logger as SettingsLogger;
use danog\MadelineProto\Settings\TLSchema;
use danog\MadelineProto\TL\TL;
use danog\MadelineProto\Tools;
use function Amp\File\read;
/**
 * TON API.
 */
class Lite
{
    /**
     * Lite client config.
     *
     * @var array
     */
    private $config;
    /**
     * Misc settings.
     *
     * @var SettingsLogger
     */
    private SettingsLogger $settings;
    /**
     * TL serializer instance.
     *
     * @var \danog\MadelineProto\TL\TL
     */
    private $TL;
    /**
     * Logger instance.
     *
     * @var Logger
     */
    public $logger;
    /**
     * Liteserver connections.
     *
     * @var ADNLConnection[]
     */
    private $connections = [];
    /**
     * Construct settings.
     *
     * @param SettingsLogger $settings
     */
    public function __construct(SettingsLogger $settings)
    {
        $this->settings = $settings;
        $this->logger = Logger::constructorFromSettings($this->settings);
        $schema = new TLSchema();
        $schema->setOther(['lite_api' => __DIR__ . '/../../../../schemas/TON/lite_api.tl', 'ton_api' => __DIR__ . '/../../../../schemas/TON/ton_api.tl']);
        /** @psalm-suppress InvalidArgument */
        $this->TL = new TL($this);
        $this->TL->init($schema);
    }
    /**
     * Connect to the lite endpoints specified in the config file.
     *
     * @param string $config Path to config file
     *
     * @return \Generator
     */
    public function connect(string $config) : \Generator
    {
        $config = \json_decode((yield read($config)), true);
        $config['_'] = 'liteclient.config.global';
        $config = Tools::convertJsonTL($config);
        $config['validator']['init_block'] = $config['validator']['init_block'] ?? $config['validator']['zero_state'];
        [$this->config] = $this->TL->deserialize(yield from $this->TL->serializeObject(['type' => ''], $config, 'cleanup'));
        foreach ($this->config['liteservers'] as $lite) {
            $this->connections[] = $connection = new ADNLConnection($this->TL);
            yield from $connection->connect($lite);
        }
    }
    /**
     * Logger.
     *
     * @param string $param Parameter
     * @param int $level Logging level
     * @param string $file File where the message originated
     *
     * @return void
     */
    public function logger($param, int $level = Logger::NOTICE, string $file = '') : void
    {
        if ($file === null) {
            $file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
        }
        isset($this->logger) ? $this->logger->logger($param, $level, $file) : Logger::$default->logger($param, $level, $file);
    }
    /**
     * Call lite method.
     *
     * @param string $methodName Method name
     * @param array $args Arguments
     *
     * @return \Generator
     */
    public function methodCall(string $methodName, array $args = [], array $aargs = []) : \Generator
    {
        $data = (yield from $this->TL->serializeMethod($methodName, $args));
        $data = (yield from $this->TL->serializeMethod('liteServer.query', ['data' => $data]));
        return yield from $this->connections[\rand(0, \count($this->connections) - 1)]->query($data);
    }
    /**
     * Asynchronously run async callable.
     *
     * @param callable $func Function
     *
     * @return \Generator
     */
    public function loop(callable $func) : \Generator
    {
        return (yield $func());
    }
    /**
     * Convert parameters.
     *
     * @param array $parameters Parameters
     *
     * @return \Generator
     */
    public function botAPItoMTProto(array $parameters) : \Generator
    {
        return $parameters;
        yield;
    }
    /**
     * Get TL method namespaces.
     *
     * @return array
     */
    public function getMethodNamespaces() : array
    {
        return $this->TL->getMethodNamespaces();
    }
}<?php

/**
 * Bug74586Exception module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

class Bug74586Exception extends \Exception
{
}<?php

/**
 * DataCenter module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Dns\Resolver;
use Amp\Dns\Rfc1035StubResolver;
use Amp\DoH\DoHConfig;
use Amp\DoH\Nameserver;
use Amp\DoH\Rfc8484StubResolver;
use Amp\Http\Client\Connection\DefaultConnectionFactory;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\Cookie\CookieInterceptor;
use Amp\Http\Client\Cookie\CookieJar;
use Amp\Http\Client\Cookie\InMemoryCookieJar;
use Amp\Http\Client\HttpClient;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Socket\ConnectContext;
use Amp\Socket\DnsConnector;
use Amp\Websocket\Client\Handshake;
use Amp\Websocket\Client\Rfc6455Connector;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProto\TempAuthKey;
use danog\MadelineProto\Settings\Connection as ConnectionSettings;
use danog\MadelineProto\Stream\Common\BufferedRawStream;
use danog\MadelineProto\Stream\Common\UdpBufferedStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoTransport\AbridgedStream;
use danog\MadelineProto\Stream\MTProtoTransport\FullStream;
use danog\MadelineProto\Stream\MTProtoTransport\HttpsStream;
use danog\MadelineProto\Stream\MTProtoTransport\HttpStream;
use danog\MadelineProto\Stream\MTProtoTransport\IntermediatePaddedStream;
use danog\MadelineProto\Stream\MTProtoTransport\IntermediateStream;
use danog\MadelineProto\Stream\MTProtoTransport\ObfuscatedStream;
use danog\MadelineProto\Stream\Transport\DefaultStream;
use danog\MadelineProto\Stream\Transport\WssStream;
use danog\MadelineProto\Stream\Transport\WsStream;
/**
 * Manages datacenters.
 */
class DataCenter
{
    use \danog\Serializable;
    /**
     * All socket connections to DCs.
     *
     * @var array<string|int, DataCenterConnection>
     */
    public $sockets = [];
    /**
     * Current DC ID.
     *
     * @var string|int
     */
    public $curdc = 0;
    /**
     * Main instance.
     *
     * @var MTProto
     */
    private $API;
    /**
     * DC list.
     *
     * @var array
     */
    private $dclist = [];
    /**
     * Settings.
     *
     * @var ConnectionSettings
     */
    private $settings;
    /**
     * HTTP client.
     *
     * @var \Amp\Http\Client\HttpClient
     */
    private $HTTPClient;
    /**
     * DNS over HTTPS client.
     *
     * @var Rfc8484StubResolver|Rfc1035StubResolver
     */
    private $DoHClient;
    /**
     * Non-proxied DNS over HTTPS client.
     *
     * @var Rfc8484StubResolver|Rfc1035StubResolver
     */
    private $nonProxiedDoHClient;
    /**
     * Cookie jar.
     *
     * @var \Amp\Http\Client\Cookie\CookieJar
     */
    private $CookieJar;
    /**
     * DNS connector.
     *
     * @var DNSConnector
     */
    private $dnsConnector;
    /**
     * DoH connector.
     */
    private Rfc6455Connector $webSocketConnector;
    /**
     *
     */
    public function __sleep()
    {
        return ['sockets', 'curdc', 'dclist', 'settings'];
    }
    /**
     *
     */
    public function __wakeup()
    {
        if (\is_array($this->settings)) {
            $settings = new ConnectionSettings();
            $settings->mergeArray(['connection_settings' => $this->settings]);
            $this->settings = $settings;
        }
        $array = [];
        foreach ($this->sockets as $id => $socket) {
            if ($socket instanceof \danog\MadelineProto\Connection) {
                if (isset($socket->temp_auth_key) && $socket->temp_auth_key) {
                    $array[$id]['tempAuthKey'] = $socket->temp_auth_key;
                }
                if (isset($socket->auth_key) && $socket->auth_key) {
                    $array[$id]['permAuthKey'] = $socket->auth_key;
                    /** @psalm-suppress UndefinedPropertyFetch */
                    $array[$id]['permAuthKey']['authorized'] = $socket->authorized;
                }
                $array[$id] = [];
            }
        }
        $this->setDataCenterConnections($array);
    }
    /**
     * Set auth key information from saved auth array.
     *
     * @param array $saved Saved auth array
     *
     * @return void
     */
    public function setDataCenterConnections(array $saved)
    {
        foreach ($saved as $id => $data) {
            $connection = $this->sockets[$id] = new DataCenterConnection();
            if (isset($data['permAuthKey'])) {
                $connection->setPermAuthKey(new PermAuthKey($data['permAuthKey']));
            }
            if (isset($data['linked'])) {
                continue;
            }
            if (isset($data['tempAuthKey'])) {
                $connection->setTempAuthKey(new TempAuthKey($data['tempAuthKey']));
                if (($data['tempAuthKey']['bound'] ?? false) && $connection->hasPermAuthKey()) {
                    $connection->bind();
                }
            }
            unset($saved[$id]);
        }
        foreach ($saved as $id => $data) {
            $connection = $this->sockets[$id];
            $connection->link($data['linked']);
            if (isset($data['tempAuthKey'])) {
                $connection->setTempAuthKey(new TempAuthKey($data['tempAuthKey']));
                if (($data['tempAuthKey']['bound'] ?? false) && $connection->hasPermAuthKey()) {
                    $connection->bind();
                }
            }
        }
    }
    /**
     * Constructor function.
     *
     * @param MTProto $API Main MTProto instance
     * @param array $dclist DC IP list
     * @param ConnectionSettings $settings Settings
     * @param boolean $reconnectAll Whether to reconnect to all DCs or just to changed ones
     * @param CookieJar $jar Cookie jar
     *
     * @return void
     */
    public function __magic_construct($API, array $dclist, ConnectionSettings $settings, bool $reconnectAll = true, CookieJar $jar = null)
    {
        $this->API = $API;
        $changed = [];
        $changedSettings = $settings->hasChanged();
        if (!$reconnectAll) {
            $changed = [];
            $test = $API->getCachedConfig()['test_mode'] ?? false ? 'test' : 'main';
            foreach ($dclist[$test] as $ipv6 => $dcs) {
                foreach ($dcs as $id => $dc) {
                    if ($dc !== ($this->dclist[$test][$ipv6][$id] ?? [])) {
                        $changed[$id] = true;
                    }
                }
            }
        }
        $this->dclist = $dclist;
        $this->settings = $settings;
        foreach ($this->sockets as $key => $socket) {
            if ($socket instanceof DataCenterConnection && !\strpos($key, '_bk')) {
                if ($reconnectAll || isset($changed[$id])) {
                    $this->API->logger->logger("Disconnecting all before reconnect!");
                    $socket->needReconnect(true);
                    $socket->setExtra($this->API);
                    $socket->disconnect();
                }
            } else {
                unset($this->sockets[$key]);
            }
        }
        if ($reconnectAll || $changedSettings || !$this->CookieJar) {
            $this->CookieJar = $jar ?? new InMemoryCookieJar();
            $this->HTTPClient = (new HttpClientBuilder())->interceptNetwork(new CookieInterceptor($this->CookieJar))->usingPool(new UnlimitedConnectionPool(new DefaultConnectionFactory(new ContextConnector($this))))->build();
            $DoHHTTPClient = (new HttpClientBuilder())->interceptNetwork(new CookieInterceptor($this->CookieJar))->usingPool(new UnlimitedConnectionPool(new DefaultConnectionFactory(new ContextConnector($this, true))))->build();
            $DoHConfig = new DoHConfig([new Nameserver('https://mozilla.cloudflare-dns.com/dns-query'), new Nameserver('https://dns.google/resolve')], $DoHHTTPClient);
            $nonProxiedDoHConfig = new DoHConfig([new Nameserver('https://mozilla.cloudflare-dns.com/dns-query'), new Nameserver('https://dns.google/resolve')]);
            $this->DoHClient = Magic::$altervista || Magic::$zerowebhost || !$settings->getUseDoH() ? new Rfc1035StubResolver() : new Rfc8484StubResolver($DoHConfig);
            $this->nonProxiedDoHClient = Magic::$altervista || Magic::$zerowebhost || !$settings->getUseDoH() ? new Rfc1035StubResolver() : new Rfc8484StubResolver($nonProxiedDoHConfig);
            $this->dnsConnector = new DnsConnector(new Rfc1035StubResolver());
            $this->webSocketConnector = new Rfc6455Connector($this->HTTPClient);
        }
        $this->settings->applyChanges();
    }
    /**
     * Set VoIP endpoints.
     *
     * @param array $endpoints Endpoints
     *
     * @return void
     */
    public function setVoIPEndpoints(array $endpoints) : void
    {
    }
    /**
     * Connect to specified DC.
     *
     * @param string $dc_number DC to connect to
     * @param integer $id Connection ID to re-establish (optional)
     *
     * @return \Generator<bool>
     */
    public function dcConnect(string $dc_number, int $id = -1) : \Generator
    {
        $old = isset($this->sockets[$dc_number]) && ($this->sockets[$dc_number]->shouldReconnect() || $id !== -1 && $this->sockets[$dc_number]->hasConnection($id) && $this->sockets[$dc_number]->getConnection($id)->shouldReconnect());
        if (isset($this->sockets[$dc_number]) && !$old) {
            $this->API->logger("Not reconnecting to DC {$dc_number} ({$id})");
            return false;
        }
        $ctxs = $this->generateContexts($dc_number);
        if (empty($ctxs)) {
            return false;
        }
        foreach ($ctxs as $ctx) {
            try {
                if ($old) {
                    $this->API->logger->logger("Reconnecting to DC {$dc_number} ({$id}) from existing", Logger::WARNING);
                    $this->sockets[$dc_number]->setExtra($this->API);
                    yield from $this->sockets[$dc_number]->connect($ctx, $id);
                } else {
                    $this->API->logger->logger("Connecting to DC {$dc_number} from scratch", Logger::WARNING);
                    $this->sockets[$dc_number] = new DataCenterConnection();
                    $this->sockets[$dc_number]->setExtra($this->API);
                    yield from $this->sockets[$dc_number]->connect($ctx);
                }
                if ($ctx->getIpv6()) {
                    Magic::setIpv6(true);
                }
                $this->API->logger->logger('OK!', Logger::WARNING);
                return true;
            } catch (\Throwable $e) {
                if (\defined("MADELINEPROTO_TEST") && \constant("MADELINEPROTO_TEST") === 'pony') {
                    throw $e;
                }
                $this->API->logger->logger("Connection failed ({$dc_number}): " . $e->getMessage(), Logger::ERROR);
            }
        }
        throw new Exception("Could not connect to DC {$dc_number}");
    }
    /**
     * Generate contexts.
     *
     * @param integer $dc_number DC ID to generate contexts for
     * @param string $uri URI
     * @param ConnectContext $context Connection context
     *
     * @return ConnectionContext[]
     */
    public function generateContexts($dc_number = 0, string $uri = '', ConnectContext $context = null) : array
    {
        $ctxs = [];
        $combos = [];
        $test = $this->settings->getTestMode() ? 'test' : 'main';
        $ipv6 = $this->settings->getIpv6() ? 'ipv6' : 'ipv4';
        switch ($this->settings->getProtocol()) {
            case AbridgedStream::class:
                $default = [[DefaultStream::class, []], [BufferedRawStream::class, []], [AbridgedStream::class, []]];
                break;
            case IntermediateStream::class:
                $default = [[DefaultStream::class, []], [BufferedRawStream::class, []], [IntermediateStream::class, []]];
                break;
            case IntermediatePaddedStream::class:
                $default = [[DefaultStream::class, []], [BufferedRawStream::class, []], [IntermediatePaddedStream::class, []]];
                break;
            case FullStream::class:
                $default = [[DefaultStream::class, []], [BufferedRawStream::class, []], [FullStream::class, []]];
                break;
            case HttpStream::class:
                $default = [[DefaultStream::class, []], [BufferedRawStream::class, []], [HttpStream::class, []]];
                break;
            case HttpsStream::class:
                $default = [[DefaultStream::class, []], [BufferedRawStream::class, []], [HttpsStream::class, []]];
                break;
            case UdpBufferedStream::class:
                $default = [[DefaultStream::class, []], [UdpBufferedStream::class, []]];
                break;
            default:
                throw new Exception(Lang::$current_lang['protocol_invalid']);
        }
        if ($this->settings->getObfuscated() && !\in_array($default[2][0], [HttpsStream::class, HttpStream::class])) {
            $default = [[DefaultStream::class, []], [BufferedRawStream::class, []], [ObfuscatedStream::class, []], \end($default)];
        }
        if ($this->settings->getTransport() && !\in_array($default[2][0], [HttpsStream::class, HttpStream::class])) {
            switch ($this->settings->getTransport()) {
                case DefaultStream::class:
                    if ($this->settings->getObfuscated()) {
                        $default = [[DefaultStream::class, []], [BufferedRawStream::class, []], [ObfuscatedStream::class, []], \end($default)];
                    }
                    break;
                case WssStream::class:
                    $default = [[DefaultStream::class, []], [WssStream::class, []], [BufferedRawStream::class, []], [ObfuscatedStream::class, []], \end($default)];
                    break;
                case WsStream::class:
                    $default = [[DefaultStream::class, []], [WsStream::class, []], [BufferedRawStream::class, []], [ObfuscatedStream::class, []], \end($default)];
                    break;
            }
        }
        if (!$dc_number) {
            $default = [[DefaultStream::class, []], [BufferedRawStream::class, []]];
        }
        $combos[] = $default;
        if ($this->settings->getRetry()) {
            if (isset($this->dclist[$test][$ipv6][$dc_number]['tcpo_only']) && $this->dclist[$test][$ipv6][$dc_number]['tcpo_only'] || isset($this->dclist[$test][$ipv6][$dc_number]['secret'])) {
                $extra = isset($this->dclist[$test][$ipv6][$dc_number]['secret']) ? ['secret' => $this->dclist[$test][$ipv6][$dc_number]['secret']] : [];
                $combos[] = [[DefaultStream::class, []], [BufferedRawStream::class, []], [ObfuscatedStream::class, $extra], [IntermediatePaddedStream::class, []]];
            }
            $proxyCombos = [];
            foreach ($this->settings->getProxies() as $proxy => $extras) {
                if (!$dc_number && $proxy === ObfuscatedStream::class) {
                    continue;
                }
                foreach ($extras as $extra) {
                    if ($proxy === ObfuscatedStream::class && \in_array(\strlen($extra['secret']), [17, 34])) {
                        $combos[] = [[DefaultStream::class, []], [BufferedRawStream::class, []], [$proxy, $extra], [IntermediatePaddedStream::class, []]];
                    }
                    foreach ($combos as $orig) {
                        $combo = [];
                        if ($proxy === ObfuscatedStream::class) {
                            $combo = $orig;
                            if ($combo[\count($combo) - 2][0] === ObfuscatedStream::class) {
                                $combo[\count($combo) - 2][1] = $extra;
                            } else {
                                $mtproto = \end($combo);
                                $combo[\count($combo) - 1] = [$proxy, $extra];
                                $combo[] = $mtproto;
                            }
                        } else {
                            if ($orig[1][0] === BufferedRawStream::class) {
                                [$first, $second] = [\array_slice($orig, 0, 2), \array_slice($orig, 2)];
                                $first[] = [$proxy, $extra];
                                $combo = \array_merge($first, $second);
                            } elseif (\in_array($orig[1][0], [WsStream::class, WssStream::class])) {
                                [$first, $second] = [\array_slice($orig, 0, 1), \array_slice($orig, 1)];
                                $first[] = [BufferedRawStream::class, []];
                                $first[] = [$proxy, $extra];
                                $combo = \array_merge($first, $second);
                            }
                        }
                        $proxyCombos[] = $combo;
                    }
                }
            }
            $combos = \array_merge($proxyCombos, $combos);
            if ($dc_number) {
                $combos[] = [[DefaultStream::class, []], [BufferedRawStream::class, []], [HttpsStream::class, []]];
            }
            $combos = \array_unique($combos, SORT_REGULAR);
        }
        /* @var $context \Amp\ConnectContext */
        $context = $context ?? (new ConnectContext())->withMaxAttempts(1)->withConnectTimeout(1000 * $this->settings->getTimeout())->withBindTo($this->settings->getBindTo());
        foreach ($combos as $combo) {
            foreach ([true, false] as $useDoH) {
                $ipv6Combos = [$this->settings->getIpv6() ? 'ipv6' : 'ipv4', $this->settings->getIpv6() ? 'ipv4' : 'ipv6'];
                foreach ($ipv6Combos as $ipv6) {
                    // This is only for non-MTProto connections
                    if (!$dc_number) {
                        /* @var $ctx \danog\MadelineProto\Stream\ConnectionContext */
                        $ctx = (new ConnectionContext())->setSocketContext($context)->setUri($uri)->setIpv6($ipv6 === 'ipv6');
                        foreach ($combo as $stream) {
                            if ($stream[0] === DefaultStream::class && $stream[1] === []) {
                                $stream[1] = $useDoH ? new DoHConnector($this, $ctx) : $this->dnsConnector;
                            }
                            /** @var array{0: class-string, 1: mixed} $stream */
                            $ctx->addStream(...$stream);
                        }
                        $ctxs[] = $ctx;
                        continue;
                    }
                    // This is only for MTProto connections
                    if (!isset($this->dclist[$test][$ipv6][$dc_number]['ip_address'])) {
                        continue;
                    }
                    $address = $this->dclist[$test][$ipv6][$dc_number]['ip_address'];
                    if ($ipv6 === 'ipv6') {
                        $address = "[{$address}]";
                    }
                    $port = $this->dclist[$test][$ipv6][$dc_number]['port'];
                    foreach (\array_unique([$port, 443, 80, 88, 5222]) as $port) {
                        $stream = \end($combo)[0];
                        if ($stream === HttpsStream::class) {
                            if (\strpos($dc_number, '_cdn') !== false) {
                                continue;
                            }
                            $subdomain = $this->settings->getSslSubdomains()[\preg_replace('/\\D+/', '', $dc_number)];
                            if (\strpos($dc_number, '_media') !== false) {
                                $subdomain .= '-1';
                            }
                            $path = $this->settings->getTestMode() ? 'apiw_test1' : 'apiw1';
                            $uri = 'tcp://' . $subdomain . '.web.telegram.org:' . $port . '/' . $path;
                        } elseif ($stream === HttpStream::class) {
                            $uri = 'tcp://' . $address . ':' . $port . '/api';
                        } else {
                            $uri = 'tcp://' . $address . ':' . $port;
                        }
                        if ($combo[1][0] === WssStream::class) {
                            $subdomain = $this->settings->getSslSubdomains()[\preg_replace('/\\D+/', '', $dc_number)];
                            if (\strpos($dc_number, '_media') !== false) {
                                $subdomain .= '-1';
                            }
                            $path = $this->settings->getTestMode() ? 'apiws_test' : 'apiws';
                            $uri = 'tcp://' . $subdomain . '.web.telegram.org:' . $port . '/' . $path;
                        } elseif ($combo[1][0] === WsStream::class) {
                            $subdomain = $this->settings->getSslSubdomains()[\preg_replace('/\\D+/', '', $dc_number)];
                            if (\strpos($dc_number, '_media') !== false) {
                                $subdomain .= '-1';
                            }
                            $path = $this->settings->getTestMode() ? 'apiws_test' : 'apiws';
                            //$uri = 'tcp://' . $subdomain . '.web.telegram.org:' . $port . '/' . $path;
                            $uri = 'tcp://' . $address . ':' . $port . '/' . $path;
                        }
                        /* @var $ctx \danog\MadelineProto\Stream\ConnectionContext */
                        $ctx = (new ConnectionContext())->setDc($dc_number)->setTest($this->settings->getTestMode())->setSocketContext($context)->setUri($uri)->setIpv6($ipv6 === 'ipv6');
                        foreach ($combo as $stream) {
                            if ($stream[0] === DefaultStream::class && $stream[1] === []) {
                                $stream[1] = $useDoH ? new DoHConnector($this, $ctx) : $this->dnsConnector;
                            }
                            if (\in_array($stream[0], [WsStream::class, WssStream::class]) && $stream[1] === []) {
                                if (!\class_exists(Handshake::class)) {
                                    throw new Exception('Please install amphp/websocket-client by running "composer require amphp/websocket-client:dev-master"');
                                }
                                $stream[1] = $this->webSocketConnector;
                            }
                            /** @var array{0: class-string, 1: mixed} $stream */
                            $ctx->addStream(...$stream);
                        }
                        $ctxs[] = $ctx;
                    }
                }
            }
        }
        if (empty($ctxs)) {
            unset($this->sockets[$dc_number]);
            $this->API->logger->logger("No info for DC {$dc_number}", Logger::ERROR);
        } elseif (\defined('MADELINEPROTO_TEST') && \constant("MADELINEPROTO_TEST") === 'pony') {
            return [$ctxs[0]];
        }
        return $ctxs;
    }
    /**
     * Get main API.
     *
     * @return MTProto
     */
    public function getAPI()
    {
        return $this->API;
    }
    /**
     * Get async HTTP client.
     *
     * @return \Amp\Http\Client\HttpClient
     */
    public function getHTTPClient() : HttpClient
    {
        return $this->HTTPClient;
    }
    /**
     * Get async HTTP client cookies.
     *
     * @return \Amp\Http\Client\Cookie\CookieJar
     */
    public function getCookieJar() : CookieJar
    {
        return $this->CookieJar;
    }
    /**
     * Get DNS over HTTPS async DNS client.
     *
     * @return \Amp\Dns\Resolver
     */
    public function getDNSClient() : Resolver
    {
        return $this->DoHClient;
    }
    /**
     * Get non-proxied DNS over HTTPS async DNS client.
     *
     * @return \Amp\Dns\Resolver
     */
    public function getNonProxiedDNSClient() : Resolver
    {
        return $this->nonProxiedDoHClient;
    }
    /**
     * Get contents of file.
     *
     * @param string $url URL to fetch
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, \Amp\Promise<string>, mixed, string>
     */
    public function fileGetContents(string $url) : \Generator
    {
        return (yield ((yield $this->getHTTPClient()->request(new Request($url))))->getBody()->buffer());
    }
    /**
     * Get Connection instance for authorization.
     *
     * @param string $dc DC ID
     *
     * @return Connection
     */
    public function getAuthConnection(string $dc) : Connection
    {
        return $this->sockets[$dc]->getAuthConnection();
    }
    /**
     * Get Connection instance.
     *
     * @param string $dc DC ID
     *
     * @return Connection
     */
    public function getConnection(string $dc) : Connection
    {
        return $this->sockets[$dc]->getConnection();
    }
    /**
     * Get Connection instance asynchronously.
     *
     * @param string $dc DC ID
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, \Amp\Promise, mixed, Connection>
     */
    public function waitGetConnection(string $dc) : \Generator
    {
        return $this->sockets[$dc]->waitGetConnection();
    }
    /**
     * Get DataCenterConnection instance.
     *
     * @param string $dc DC ID
     *
     * @return DataCenterConnection
     */
    public function getDataCenterConnection(string $dc) : DataCenterConnection
    {
        return $this->sockets[$dc];
    }
    /**
     * Get all DataCenterConnection instances.
     *
     * @return array<(int | string), DataCenterConnection>
     */
    public function getDataCenterConnections() : array
    {
        return $this->sockets;
    }
    /**
     * Check if a DC is present.
     *
     * @param string $dc DC ID
     *
     * @return boolean
     */
    public function has(string $dc) : bool
    {
        return isset($this->sockets[$dc]);
    }
    /**
     * Check if connected to datacenter using HTTP.
     *
     * @param string $datacenter DC ID
     *
     * @return boolean
     */
    public function isHttp(string $datacenter)
    {
        return $this->sockets[$datacenter]->isHttp();
    }
    /**
     * Check if connected to datacenter directly using IP address.
     *
     * @param string $datacenter DC ID
     *
     * @return boolean
     */
    public function byIPAddress(string $datacenter) : bool
    {
        return $this->sockets[$datacenter]->byIPAddress();
    }
    /**
     * Get all DC IDs.
     *
     * @param boolean $all Whether to get all possible DC IDs, or only connected ones
     *
     * @return array
     */
    public function getDcs($all = true) : array
    {
        $test = $this->settings->getTestMode() ? 'test' : 'main';
        $ipv6 = $this->settings->getIpv6() ? 'ipv6' : 'ipv4';
        return $all ? \array_keys((array) $this->dclist[$test][$ipv6]) : \array_keys((array) $this->sockets);
    }
}<?php

/**
 * Crypt module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools\Crypt;

/**
 * Openssl IGE implementation.
 *
 * @internal
 */
final class IGEOpenssl extends IGE
{
    /**
     *
     */
    protected function __construct(string $key, string $iv)
    {
        $this->key = $key;
        $this->iv_part_1 = \Phabel\Target\Php80\Polyfill::substr($iv, 0, 16);
        $this->iv_part_2 = \Phabel\Target\Php80\Polyfill::substr($iv, 16);
    }
    /**
     *
     */
    private string $key;
    /**
     *
     */
    public function encrypt(string $plaintext) : string
    {
        $ciphertext = "";
        for ($i = 0, $length = \strlen($plaintext); $i < $length; $i += 16) {
            $plain = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, 16);
            $cipher = \openssl_encrypt($plain ^ $this->iv_part_1, 'aes-256-ecb', $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING) ^ $this->iv_part_2;
            $ciphertext .= $cipher;
            $this->iv_part_1 = $cipher;
            $this->iv_part_2 = $plain;
        }
        return $ciphertext;
    }
    /**
     *
     */
    public function decrypt(string $ciphertext) : string
    {
        $plaintext = "";
        for ($i = 0, $length = \strlen($ciphertext); $i < $length; $i += 16) {
            $cipher = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, 16);
            $plain = \openssl_decrypt($cipher ^ $this->iv_part_2, 'aes-256-ecb', $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING) ^ $this->iv_part_1;
            $plaintext .= $plain;
            $this->iv_part_1 = $cipher;
            $this->iv_part_2 = $plain;
        }
        return $plaintext;
    }
}<?php

/**
 * Crypt module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools\Crypt;

use danog\MadelineProto\Magic;
/**
 * Continuous mode IGE implementation.
 *
 * @internal
 */
abstract class IGE
{
    /**
     * IV part 1.
     *
     * @var string
     */
    protected $iv_part_1;
    /**
     * IV part 2.
     *
     * @var string
     */
    protected $iv_part_2;
    /**
     * Instantiate appropriate handler.
     *
     * @param string $key
     * @param string $iv
     * @return IGE
     */
    public static function getInstance(string $key, string $iv) : IGE
    {
        if (Magic::$hasOpenssl) {
            return new IGEOpenssl($key, $iv);
        }
        return new IGEPhpseclib($key, $iv);
    }
    /**
     *
     */
    protected abstract function __construct(string $key, string $iv);
    /**
     *
     */
    public abstract function encrypt(string $plaintext) : string;
    /**
     *
     */
    public abstract function decrypt(string $ciphertext) : string;
}<?php

/**
 * Crypt module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools\Crypt;

use phpseclib3\Crypt\AES;
/**
 * Phpseclib IGE implementation.
 *
 * @internal
 */
final class IGEPhpseclib extends IGE
{
    /**
     *
     */
    private AES $instance;
    /**
     *
     */
    protected function __construct(string $key, string $iv)
    {
        $this->instance = new AES('ecb');
        $this->instance->setKey($key);
        $this->instance->disablePadding();
        $this->iv_part_1 = \Phabel\Target\Php80\Polyfill::substr($iv, 0, 16);
        $this->iv_part_2 = \Phabel\Target\Php80\Polyfill::substr($iv, 16);
    }
    /**
     *
     */
    public function encrypt(string $plaintext) : string
    {
        $ciphertext = "";
        for ($i = 0, $length = \strlen($plaintext); $i < $length; $i += 16) {
            $plain = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, 16);
            $cipher = $this->instance->encrypt($plain ^ $this->iv_part_1) ^ $this->iv_part_2;
            $ciphertext .= $cipher;
            $this->iv_part_1 = $cipher;
            $this->iv_part_2 = $plain;
        }
        return $ciphertext;
    }
    /**
     *
     */
    public function decrypt(string $ciphertext) : string
    {
        $plaintext = "";
        for ($i = 0, $length = \strlen($ciphertext); $i < $length; $i += 16) {
            $cipher = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, 16);
            $plain = $this->instance->decrypt($cipher ^ $this->iv_part_2) ^ $this->iv_part_1;
            $plaintext .= $plain;
            $this->iv_part_1 = $cipher;
            $this->iv_part_2 = $plain;
        }
        return $plaintext;
    }
}<?php

/**
 * CombinedUpdatesState class.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

/**
 * Stores multiple update states.
 *
 * @internal
 */
class CombinedUpdatesState
{
    /**
     * Update states.
     *
     * @var array<UpdatesState>
     */
    private $states = [];
    /**
     * Constructor function.
     *
     * @param array $init Initial array of states
     */
    public function __construct($init = [])
    {
        $this->states[false] = new UpdatesState();
        if (!\is_array($init)) {
            return;
        }
        foreach ($init as $channel => $state) {
            if (\is_array($state)) {
                $state = new UpdatesState($state, $channel);
            }
            $this->states[$channel] = $state;
        }
    }
    /**
     * Get or update multiple parameters.
     *
     * @param int $channel Channel to get info about (optional, if not provided returns the entire info array)
     * @param array $init Parameters to update
     *
     * @return (UpdatesState | UpdatesState[])
     */
    public function get(int $channel = null, array $init = [])
    {
        if ($channel === null) {
            return $this->states;
        }
        if (!isset($this->states[$channel])) {
            return $this->states[$channel] = new UpdatesState($init, $channel);
        }
        return $this->states[$channel]->update($init);
    }
    /**
     * Remove update state.
     *
     * @param int $channel Channel whose state should be removed
     *
     * @return void
     */
    public function remove(int $channel)
    {
        if (isset($this->states[$channel])) {
            unset($this->states[$channel]);
        }
    }
    /**
     * Check if update state is present.
     *
     * @param int $channel Channel ID
     *
     * @return bool
     */
    public function has(int $channel) : bool
    {
        return isset($this->states[$channel]);
    }
    /**
     * Are we currently busy?
     *
     * @param int $channel Channel to get info about
     * @param (bool | null) $set Busy flag to set before returning
     *
     * @return bool
     */
    public function syncLoading(int $channel, bool $set = null) : bool
    {
        return $this->get($channel)->syncLoading($set);
    }
}<?php

/**
 * UpdatesState class.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

/**
 * Stores the state of updates.
 */
class UpdatesState
{
    /**
     * PTS.
     */
    private int $pts = 1;
    /**
     * QTS.
     */
    private int $qts = -1;
    /**
     * Seq.
     */
    private int $seq = 0;
    /**
     * Date.
     */
    private int $date = 1;
    /**
     * Channel ID.
     *
     * @var int
     */
    private $channelId;
    /**
     * Is busy?
     */
    private bool $syncLoading = false;
    /**
     * Init function.
     *
     * @param array $init Initial parameters
     * @param int $channelId Channel ID
     */
    public function __construct(array $init = [], int $channelId = 0)
    {
        $this->channelId = $channelId;
        $this->update($init);
    }
    /**
     * Sleep function.
     *
     * @return array Parameters to serialize
     */
    public function __sleep()
    {
        return $this->channelId ? ['pts', 'channelId'] : ['pts', 'qts', 'seq', 'date', 'channelId'];
    }
    /**
     * Wakeup function.
     */
    public function __wakeup()
    {
        /** @psalm-suppress DocblockTypeContradiction */
        if ($this->channelId === false) {
            $this->channelId = 0;
        }
    }
    /**
     * Is this state relative to a channel?
     *
     * @return bool
     */
    public function isChannel() : bool
    {
        return (bool) $this->channelId;
    }
    /**
     * Get the channel ID.
     *
     * @return int
     */
    public function getChannel() : int
    {
        return $this->channelId;
    }
    /**
     * Are we currently busy?
     *
     * @param (bool | null) $set Update the currently busy flag
     *
     * @return bool
     */
    public function syncLoading(bool $set = null) : bool
    {
        if ($set !== null) {
            $this->syncLoading = $set;
        }
        return $this->syncLoading;
    }
    /**
     * Update multiple parameters.
     *
     * @param array $init Parameters to update
     *
     * @return self
     */
    public function update(array $init) : self
    {
        foreach ($this->channelId ? ['pts'] : ['pts', 'qts', 'seq', 'date'] as $param) {
            if (isset($init[$param])) {
                $this->{$param}($init[$param]);
            }
        }
        return $this;
    }
    /**
     * Get/set PTS.
     *
     * @param int $set PTS to set
     *
     * @return int PTS
     */
    public function pts(int $set = 0) : int
    {
        if ($set !== 0 && $set > $this->pts) {
            $this->pts = $set;
        }
        return $this->pts;
    }
    /**
     * Get/set QTS.
     *
     * @param int $set QTS to set
     *
     * @return int QTS
     */
    public function qts(int $set = 0) : int
    {
        if ($set !== 0 && $set > $this->qts) {
            $this->qts = $set;
        }
        return $this->qts;
    }
    /**
     * Get/set seq.
     *
     * @param int $set Seq to set
     *
     * @return int seq
     */
    public function seq(int $set = 0) : int
    {
        if ($set !== 0 && $set > $this->seq) {
            $this->seq = $set;
        }
        return $this->seq;
    }
    /**
     * Get/set date.
     *
     * @param int $set Date to set
     *
     * @return int Date
     */
    public function date(int $set = 0) : int
    {
        if ($set !== 0 && $set > $this->date) {
            $this->date = $set;
        }
        return $this->date;
    }
    /**
     * Check validity of PTS contained in update.
     *
     * @param array $update Update
     *
     * @return int -1 if it's too old, 0 if it's ok, 1 if it's too new
     */
    public function checkPts(array $update) : int
    {
        return $update['pts'] - ($this->pts + $update['pts_count']);
    }
    /**
     * Check validity of seq contained in update.
     *
     * @param int $seq Seq
     *
     * @return int -1 if it's too old, 0 if it's ok, 1 if it's too new
     */
    public function checkSeq(int $seq) : int
    {
        return $seq ? $seq - ($this->seq + 1) : $seq;
    }
}<?php

/**
 * CallHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use danog\MadelineProto\Settings;
/**
 * Manages method and object calls.
 *
 * @property Settings $settings Settings
 */
trait CallHandler
{
    /**
     * Synchronous wrapper for methodCall.
     *
     * @param string $method Method name
     * @param (array | \Generator) $args Arguments
     * @param array $aargs Additional arguments
     *
     * @psalm-param (array | \Generator<mixed, mixed, mixed, array>) $args
     *
     * @return mixed
     */
    public function methodCall(string $method, $args = [], array $aargs = ['msg_id' => null])
    {
        return \danog\MadelineProto\Tools::wait($this->methodCallAsyncRead($method, $args, $aargs));
    }
    /**
     * Call method and wait asynchronously for response.
     *
     * If the $aargs['noResponse'] is true, will not wait for a response.
     *
     * @param string $method Method name
     * @param (array | \Generator) $args Arguments
     * @param array $aargs Additional arguments
     *
     * @psalm-param (array | \Generator<mixed, mixed, mixed, array>) $args
     *
     * @return \Generator
     */
    public function methodCallAsyncRead(string $method, $args = [], array $aargs = ['msg_id' => null]) : \Generator
    {
        return yield from (yield from $this->datacenter->waitGetConnection($aargs['datacenter'] ?? $this->datacenter->curdc))->methodCallAsyncRead($method, $args, $aargs);
    }
    /**
     * Call method and make sure it is asynchronously sent.
     *
     * @param string $method Method name
     * @param (array | \Generator) $args Arguments
     * @param array $aargs Additional arguments
     *
     * @psalm-param (array | \Generator<mixed, mixed, mixed, array>) $args
     *
     * @return \Generator
     */
    public function methodCallAsyncWrite(string $method, $args = [], array $aargs = ['msg_id' => null]) : \Generator
    {
        return yield from (yield from $this->datacenter->waitGetConnection($aargs['datacenter'] ?? $this->datacenter->curdc))->methodCallAsyncWrite($method, $args, $aargs);
    }
}<?php

/**
 * PeerHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use Amp\Http\Client\Request;
use Amp\Promise;
use danog\Decoder\FileId;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceDialogPhoto;
use danog\MadelineProto\Db\DbArray;
use danog\MadelineProto\Magic;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools;
use const danog\Decoder\PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG;
use const danog\Decoder\PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL;
use const danog\Decoder\PROFILE_PHOTO;
/**
 * Manages peers.
 *
 * @property Settings $settings Settings
 */
trait PeerHandler
{
    public $caching_simple = [];
    public $caching_simple_username = [];
    public $caching_possible_username = [];
    public $caching_full_info = [];
    /**
     * Convert MTProto channel ID to bot API channel ID.
     *
     * @param int $id MTProto channel ID
     *
     * @return int
     */
    public static function toSupergroup($id) : int
    {
        return Magic::ZERO_CHANNEL_ID - $id;
    }
    /**
     * Convert bot API channel ID to MTProto channel ID.
     *
     * @param int $id Bot API channel ID
     *
     * @return int
     */
    public static function fromSupergroup($id) : int
    {
        return -$id + Magic::ZERO_CHANNEL_ID;
    }
    /**
     * Check whether provided bot API ID is a channel.
     *
     * @param int $id Bot API ID
     *
     * @return boolean
     */
    public static function isSupergroup($id) : bool
    {
        return $id < Magic::ZERO_CHANNEL_ID;
    }
    /**
     * Set support info.
     *
     * @param array $support Support info
     *
     * @internal
     *
     * @return void
     */
    public function addSupport(array $support) : void
    {
        $this->supportUser = $support['user']['id'];
    }
    /**
     * Add user info.
     *
     * @param array $user User info
     *
     * @return \Generator
     * @throws \danog\MadelineProto\Exception
     */
    public function addUser(array $user) : \Generator
    {
        $existingChat = (yield $this->chats[$user['id']]);
        if ($existingChat) {
            $this->cacheChatUsername($user['id'], $user);
        }
        if (!isset($user['access_hash']) && !($user['min'] ?? false)) {
            if (!empty($existingChat['access_hash'])) {
                $this->logger->logger("No access hash with user {$user['id']}, using backup");
                $user['access_hash'] = $existingChat['access_hash'];
            } elseif (!isset($this->caching_simple[$user['id']]) && !(isset($user['username']) && isset($this->caching_simple_username[$user['username']]))) {
                $this->logger->logger("No access hash with user {$user['id']}, trying to fetch by ID...");
                if (isset($user['username']) && !isset($this->caching_simple_username[$user['username']])) {
                    $this->caching_possible_username[$user['id']] = $user['username'];
                }
                $this->cachePwrChat($user['id'], false, true);
            } elseif (isset($user['username']) && !$existingChat && !isset($this->caching_simple_username[$user['username']])) {
                $this->logger->logger("No access hash with user {$user['id']}, trying to fetch by username...");
                $this->cachePwrChat($user['username'], false, true);
            } else {
                $this->logger->logger("No access hash with user {$user['id']}, tried and failed to fetch data...");
            }
            return;
        }
        switch ($user['_']) {
            case 'user':
                if (!$existingChat || $existingChat !== $user) {
                    $this->logger->logger("Updated user {$user['id']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    if (($user['min'] ?? false) && !($existingChat['min'] ?? false)) {
                        $this->logger->logger("{$user['id']} is min, filling missing fields", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                        if (isset($existingChat['access_hash'])) {
                            $user['min'] = false;
                            $user['access_hash'] = $existingChat['access_hash'];
                        }
                    }
                    if (!$this->getSettings()->getDb()->getEnablePeerInfoDb()) {
                        $user = ['_' => $user['_'], 'id' => $user['id'], 'access_hash' => $user['access_hash'] ?? null, 'min' => $user['min'] ?? false];
                    }
                    (yield $this->chats->set($user['id'], $user));
                    $this->cachePwrChat($user['id'], false, true);
                }
                $this->cacheChatUsername($user['id'], $user);
                break;
            case 'userEmpty':
                break;
            default:
                throw new \danog\MadelineProto\Exception('Invalid user provided', $user);
        }
    }
    /**
     * Add chat to database.
     *
     * @param array $chat Chat
     *
     * @internal
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, (\Amp\Promise | null), mixed, void>
     */
    public function addChat($chat) : \Generator
    {
        switch ($chat['_']) {
            case 'chat':
            case 'chatEmpty':
            case 'chatForbidden':
                $existingChat = (yield $this->chats[-$chat['id']]);
                if (!$existingChat || $existingChat !== $chat) {
                    $this->logger->logger("Updated chat -{$chat['id']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    if (!$this->getSettings()->getDb()->getEnablePeerInfoDb()) {
                        $chat = ['_' => $chat['_'], 'id' => $chat['id'], 'access_hash' => $chat['access_hash'] ?? null, 'min' => $chat['min'] ?? false];
                    }
                    (yield $this->chats->set(-$chat['id'], $chat));
                    $this->cachePwrChat(-$chat['id'], $this->getSettings()->getPeer()->getFullFetch(), true);
                }
                $this->cacheChatUsername(-$chat['id'], $chat);
                break;
            case 'channelEmpty':
                break;
            case 'channel':
            case 'channelForbidden':
                $bot_api_id = $this->toSupergroup($chat['id']);
                if (!isset($chat['access_hash'])) {
                    if (!isset($this->caching_simple[$bot_api_id]) && !(isset($chat['username']) && isset($this->caching_simple_username[$chat['username']]))) {
                        $this->logger->logger("No access hash with {$chat['_']} {$bot_api_id}, trying to fetch by ID...");
                        if (isset($chat['username']) && !isset($this->caching_simple_username[$chat['username']])) {
                            $this->caching_possible_username[$bot_api_id] = $chat['username'];
                        }
                        $this->cachePwrChat($bot_api_id, false, true);
                    } elseif (isset($chat['username']) && !(yield $this->chats[$bot_api_id]) && !isset($this->caching_simple_username[$chat['username']])) {
                        $this->logger->logger("No access hash with {$chat['_']} {$bot_api_id}, trying to fetch by username...");
                        $this->cachePwrChat($chat['username'], false, true);
                    } else {
                        $this->logger->logger("No access hash with {$chat['_']} {$bot_api_id}, tried and failed to fetch data...");
                    }
                    return;
                }
                $existingChat = (yield $this->chats[$bot_api_id]);
                if (!$existingChat || $existingChat !== $chat) {
                    $this->logger->logger("Updated chat {$bot_api_id}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    if (($chat['min'] ?? false) && $existingChat && !($existingChat['min'] ?? false)) {
                        $this->logger->logger("{$bot_api_id} is min, filling missing fields", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                        $newchat = $existingChat;
                        foreach (['title', 'username', 'photo', 'banned_rights', 'megagroup', 'verified'] as $field) {
                            if (isset($chat[$field])) {
                                $newchat[$field] = $chat[$field];
                            }
                        }
                        $chat = $newchat;
                    }
                    if (!$this->getSettings()->getDb()->getEnablePeerInfoDb()) {
                        $chat = ['_' => $chat['_'], 'id' => $chat['id'], 'access_hash' => $chat['access_hash'] ?? null, 'min' => $chat['min'] ?? false];
                    }
                    (yield $this->chats->set($bot_api_id, $chat));
                    $fullChat = (yield $this->full_chats[$bot_api_id]);
                    if ($this->getSettings()->getPeer()->getFullFetch() && $this->getSettings()->getDb()->getEnableFullPeerDb() && (!$fullChat || $fullChat['full']['participants_count'] !== (yield from $this->getFullInfo($bot_api_id))['full']['participants_count'])) {
                        $this->cachePwrChat($bot_api_id, $this->getSettings()->getPeer()->getFullFetch(), true);
                    }
                }
                $this->cacheChatUsername($bot_api_id, $chat);
                break;
        }
    }
    /**
     *
     */
    private function cacheChatUsername($id, array $chat) : void
    {
        if ($id && !empty($chat['username']) && $this->getSettings()->getDb()->getEnableUsernameDb()) {
            $this->usernames[\strtolower($chat['username'])] = $id;
        }
    }
    /**
     *
     */
    private function cachePwrChat($id, $full_fetch, $send) : void
    {
        \danog\MadelineProto\Tools::callFork((function () use($id, $full_fetch, $send) : \Generator {
            try {
                yield from $this->getPwrChat($id, $full_fetch, $send);
            } catch (\danog\MadelineProto\Exception $e) {
                $this->logger->logger('While caching: ' . $e->getMessage(), \danog\MadelineProto\Logger::WARNING);
            } catch (\danog\MadelineProto\RPCErrorException $e) {
                $this->logger->logger('While caching: ' . $e->getMessage(), \danog\MadelineProto\Logger::WARNING);
            }
        })());
    }
    /**
     * Check if peer is present in internal peer database.
     *
     * @param mixed $id Peer
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | array), mixed, bool>
     */
    public function peerIsset($id) : \Generator
    {
        try {
            return (yield $this->chats[yield from $this->getInfo($id, MTProto::INFO_TYPE_ID)]) !== null;
        } catch (\danog\MadelineProto\Exception $e) {
            return false;
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            if ($e->rpc === 'CHAT_FORBIDDEN') {
                return true;
            }
            if ($e->rpc === 'CHANNEL_PRIVATE') {
                return true;
            }
            return false;
        }
    }
    /**
     * Check if all peer entities are in db.
     *
     * @param array $entities Entity list
     *
     * @internal
     *
     * @return \Generator<bool>
     */
    public function entitiesPeerIsset(array $entities) : \Generator
    {
        try {
            foreach ($entities as $entity) {
                if ($entity['_'] === 'messageEntityMentionName' || $entity['_'] === 'inputMessageEntityMentionName') {
                    if (!(yield from $this->peerIsset($entity['user_id']))) {
                        return false;
                    }
                }
            }
        } catch (\danog\MadelineProto\Exception $e) {
            return false;
        }
        return true;
    }
    /**
     * Check if fwd peer is set.
     *
     * @param array $fwd Forward info
     *
     * @internal
     *
     * @return \Generator
     */
    public function fwdPeerIsset(array $fwd) : \Generator
    {
        try {
            if (isset($fwd['user_id']) && !(yield from $this->peerIsset($fwd['user_id']))) {
                return false;
            }
            if (isset($fwd['channel_id']) && !(yield from $this->peerIsset($this->toSupergroup($fwd['channel_id'])))) {
                return false;
            }
        } catch (\danog\MadelineProto\Exception $e) {
            return false;
        }
        return true;
    }
    /**
     * Get folder ID from object.
     *
     * @param mixed $id Object
     *
     * @return ?int
     */
    public static function getFolderId($id) : ?int
    {
        if (!\is_array($id)) {
            return null;
        }
        if (!isset($id['folder_id'])) {
            return null;
        }
        return $id['folder_id'];
    }
    /**
     * Get bot API ID from peer object.
     *
     * @param mixed $id Peer
     *
     * @return int
     */
    public function getId($id)
    {
        if (\is_array($id)) {
            switch ($id['_']) {
                case 'updateDialogPinned':
                case 'updateDialogUnreadMark':
                case 'updateNotifySettings':
                    $id = $id['peer'];
                // no break
                case 'updateDraftMessage':
                case 'inputDialogPeer':
                case 'dialogPeer':
                case 'inputNotifyPeer':
                case 'notifyPeer':
                case 'dialog':
                case 'help.proxyDataPromo':
                case 'updateChatDefaultBannedRights':
                case 'folderPeer':
                case 'inputFolderPeer':
                    return $this->getId($id['peer']);
                case 'inputUserFromMessage':
                case 'inputPeerUserFromMessage':
                    return $id['user_id'];
                case 'inputChannelFromMessage':
                case 'inputPeerChannelFromMessage':
                    return $this->toSupergroup($id['channel_id']);
                case 'inputUserSelf':
                case 'inputPeerSelf':
                    return $this->authorization['user']['id'];
                case 'user':
                    return $id['id'];
                case 'userFull':
                    return $id['id'];
                case 'inputPeerUser':
                case 'inputUser':
                case 'peerUser':
                case 'messageEntityMentionName':
                case 'messageActionChatDeleteUser':
                    return $id['user_id'];
                case 'messageActionChatJoinedByLink':
                    return $id['inviter_id'];
                case 'chat':
                case 'chatForbidden':
                case 'chatFull':
                    return -$id['id'];
                case 'inputPeerChat':
                case 'peerChat':
                    return -$id['chat_id'];
                case 'channelForbidden':
                case 'channel':
                case 'channelFull':
                    return $this->toSupergroup($id['id']);
                case 'inputPeerChannel':
                case 'inputChannel':
                case 'peerChannel':
                    return $this->toSupergroup($id['channel_id']);
                case 'message':
                case 'messageService':
                    if (!isset($id['from_id']) || $id['peer_id']['_'] !== 'peerUser' || $id['peer_id']['user_id'] !== $this->authorization['user']['id']) {
                        return $this->getId($id['peer_id']);
                    }
                    return $this->getId($id['from_id']);
                case 'updateChannelReadMessagesContents':
                case 'updateChannelAvailableMessages':
                case 'updateChannel':
                case 'updateChannelWebPage':
                case 'updateChannelMessageViews':
                case 'updateReadChannelInbox':
                case 'updateReadChannelOutbox':
                case 'updateDeleteChannelMessages':
                case 'updateChannelPinnedMessage':
                case 'updateChannelTooLong':
                    return $this->toSupergroup($id['channel_id']);
                case 'updateChatParticipants':
                    $id = $id['participants'];
                // no break
                case 'updateChatUserTyping':
                case 'updateChatParticipantAdd':
                case 'updateChatParticipantDelete':
                case 'updateChatParticipantAdmin':
                case 'updateChatAdmins':
                case 'updateChatPinnedMessage':
                    return -$id['chat_id'];
                case 'updateUserTyping':
                case 'updateUserStatus':
                case 'updateUserName':
                case 'updateUserPhoto':
                case 'updateUserPhone':
                case 'updateUserBlocked':
                case 'updateContactRegistered':
                case 'updateContactLink':
                case 'updateBotInlineQuery':
                case 'updateInlineBotCallbackQuery':
                case 'updateBotInlineSend':
                case 'updateBotCallbackQuery':
                case 'updateBotPrecheckoutQuery':
                case 'updateBotShippingQuery':
                case 'updateUserPinnedMessage':
                case 'contact':
                    return $id['user_id'];
                case 'updatePhoneCall':
                    return $id['phone_call']->getOtherID();
                case 'updateReadHistoryInbox':
                case 'updateReadHistoryOutbox':
                    return $this->getId($id['peer']);
                case 'updateNewMessage':
                case 'updateNewChannelMessage':
                case 'updateEditMessage':
                case 'updateEditChannelMessage':
                    return $this->getId($id['message']);
                default:
                    throw new \danog\MadelineProto\Exception('Invalid constructor given ' . $id['_']);
            }
        }
        if (\is_string($id)) {
            if (\strpos($id, '#') !== false) {
                if (\preg_match('/^channel#(\\d*)/', $id, $matches)) {
                    return $this->toSupergroup($matches[1]);
                }
                if (\preg_match('/^chat#(\\d*)/', $id, $matches)) {
                    $id = '-' . $matches[1];
                }
                if (\preg_match('/^user#(\\d*)/', $id, $matches)) {
                    return $matches[1];
                }
            }
        }
        if (\is_numeric($id)) {
            if (\is_string($id)) {
                $id = (int) $id;
            }
            return $id;
        }
        return false;
    }
    /**
     * Get InputPeer object.
     *
     * @internal
     *
     * @param mixed $id Peer
     * @return \Generator
     */
    public function getInputPeer($id) : \Generator
    {
        return $this->getInfo($id, MTProto::INFO_TYPE_PEER);
    }
    /**
     * Get InputUser/InputChannel object.
     *
     * @internal
     *
     * @param mixed $id Peer
     * @return \Generator
     */
    public function getInputConstructor($id) : \Generator
    {
        return $this->getInfo($id, MTProto::INFO_TYPE_CONSTRUCTOR);
    }
    /**
    * Get info about peer, returns an Info object.
    *
    * @param mixed $id Peer
    * @param MTProto::INFO_TYPE_* $type Whether to generate an Input*, an InputPeer or the full set of constructors
    * @param boolean $recursive Internal
    *
    * @see https://docs.madelineproto.xyz/Info.html
    *
    * @return \Generator Info object
    *
    * @template TConstructor
    * @psalm-param $id array{_: TConstructor}|mixed
    *
    * @return (((mixed | string)[] | mixed | string)[] | int | mixed | string)[]
    *
    * @psalm-return \Generator<int|mixed, \Amp\Promise|\Amp\Promise<string>|array, mixed, array{
    TConstructor: array
    InputPeer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed},
    Peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed},
    DialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
    NotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
    InputDialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
    InputNotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
    bot_api_id: int|string,
    user_id?: int,
    chat_id?: int,
    channel_id?: int,
    InputUser?: array{_: string, user_id?: int, access_hash?: mixed, min?: bool},
    InputChannel?: array{_: string, channel_id: int, access_hash: mixed, min: bool},
    type: string
    }>|int|array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}|array{_: string, user_id?: int, access_hash?: mixed, min?: bool}|array{_: string, channel_id: int, access_hash: mixed, min: bool}
    */
    public function getInfo($id, int $type = MTProto::INFO_TYPE_ALL, $recursive = true) : \Generator
    {
        if (\is_array($id)) {
            switch ($id['_']) {
                case 'updateEncryption':
                    return $this->getSecretChat($id['chat']['id']);
                case 'inputEncryptedChat':
                case 'updateEncryptedChatTyping':
                case 'updateEncryptedMessagesRead':
                    return $this->getSecretChat($id['chat_id']);
                case 'updateNewEncryptedMessage':
                    $id = $id['message'];
                // no break
                case 'encryptedMessage':
                case 'encryptedMessageService':
                    $id = $id['chat_id'];
                    if (!isset($this->secret_chats[$id])) {
                        throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['sec_peer_not_in_db']);
                    }
                    return $this->secret_chats[$id];
            }
        }
        $folder_id = $this->getFolderId($id);
        $try_id = $this->getId($id);
        if ($try_id !== false) {
            $id = $try_id;
        }
        $tried_simple = false;
        if (\is_numeric($id)) {
            if (!(yield $this->chats[$id])) {
                try {
                    $this->logger->logger("Try fetching {$id} with access hash 0");
                    $this->caching_simple[$id] = true;
                    if ($id < 0) {
                        if ($this->isSupergroup($id)) {
                            yield from $this->methodCallAsyncRead('channels.getChannels', ['id' => [['access_hash' => 0, 'channel_id' => $this->fromSupergroup($id), '_' => 'inputChannel']]]);
                        } else {
                            yield from $this->methodCallAsyncRead('messages.getFullChat', ['chat_id' => -$id]);
                        }
                    } else {
                        yield from $this->methodCallAsyncRead('users.getUsers', ['id' => [['access_hash' => 0, 'user_id' => $id, '_' => 'inputUser']]]);
                    }
                } catch (\danog\MadelineProto\Exception $e) {
                    $this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::WARNING);
                } catch (\danog\MadelineProto\RPCErrorException $e) {
                    $this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::WARNING);
                } finally {
                    if (isset($this->caching_simple[$id])) {
                        unset($this->caching_simple[$id]);
                    }
                    $tried_simple = true;
                }
            }
            if ((yield $this->chats[$id])) {
                if ((((yield $this->chats[$id]))['min'] ?? false) && (yield $this->minDatabase->hasPeer($id) && !isset($this->caching_full_info[$id]))) {
                    $this->caching_full_info[$id] = true;
                    $this->logger->logger("Only have min peer for {$id} in database, trying to fetch full info");
                    try {
                        if ($id < 0) {
                            yield from $this->methodCallAsyncRead('channels.getChannels', ['id' => [$this->genAll((yield $this->chats[$id]), $folder_id, MTProto::INFO_TYPE_CONSTRUCTOR)]]);
                        } else {
                            yield from $this->methodCallAsyncRead('users.getUsers', ['id' => [$this->genAll((yield $this->chats[$id]), $folder_id, MTProto::INFO_TYPE_CONSTRUCTOR)]]);
                        }
                    } catch (\danog\MadelineProto\Exception $e) {
                        $this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::WARNING);
                    } catch (\danog\MadelineProto\RPCErrorException $e) {
                        $this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::WARNING);
                    } finally {
                        unset($this->caching_full_info[$id]);
                    }
                }
                try {
                    return $this->genAll((yield $this->chats[$id]), $folder_id, $type);
                } catch (\danog\MadelineProto\Exception $e) {
                    if ($e->getMessage() === 'This peer is not present in the internal peer database') {
                        (yield $this->chats->unset($id));
                        /** @uses DbArray::offsetUnset() */
                    } else {
                        throw $e;
                    }
                }
            }
            if ($this->settings->getPwr()->getRequests() && $recursive) {
                $dbres = [];
                try {
                    $dbres = \json_decode(yield from $this->datacenter->fileGetContents('https://id.pwrtelegram.xyz/db/getusername?id=' . $id), true);
                } catch (\Throwable $e) {
                    $this->logger->logger($e);
                }
                if (isset($dbres['ok']) && $dbres['ok']) {
                    yield from $this->resolveUsername('@' . $dbres['result']);
                    return yield from $this->getInfo($id, $type, false);
                }
            }
            if ($tried_simple && isset($this->caching_possible_username[$id])) {
                $this->logger->logger("No access hash with {$id}, trying to fetch by username...");
                $user = $this->caching_possible_username[$id];
                unset($this->caching_possible_username[$id]);
                return yield from $this->getInfo($user, $type);
            }
            throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
        }
        if ($r = Tools::parseLink($id)) {
            [$invite, $content] = $r;
            if ($invite) {
                $invite = (yield from $this->methodCallAsyncRead('messages.checkChatInvite', ['hash' => $content]));
                if (isset($invite['chat'])) {
                    return yield from $this->getInfo($invite['chat'], $type);
                }
                throw new \danog\MadelineProto\Exception('You have not joined this chat');
            } else {
                $id = $content;
            }
        }
        $id = \strtolower(\str_replace('@', '', $id));
        if ($id === 'me') {
            return yield from $this->getInfo($this->authorization['user']['id'], $type);
        }
        if ($id === 'support') {
            if (!$this->supportUser) {
                yield from $this->methodCallAsyncRead('help.getSupport', [], $this->settings->getDefaultDcParams());
            }
            return yield from $this->getInfo($this->supportUser, $type);
        }
        if ($bot_api_id = (yield $this->usernames[$id])) {
            $chat = (yield $this->chats[$bot_api_id]);
            if (empty($chat['username']) || \strtolower($chat['username']) !== $id) {
                (yield $this->usernames->unset($id));
                /** @uses DbArray::offsetUnset() */
            }
            if (isset($chat['username']) && \strtolower($chat['username']) === $id) {
                if ($chat['min'] ?? false && !isset($this->caching_full_info[$bot_api_id])) {
                    $this->caching_full_info[$bot_api_id] = true;
                    $this->logger->logger("Only have min peer for {$bot_api_id} in database, trying to fetch full info");
                    try {
                        if ($bot_api_id < 0) {
                            yield from $this->methodCallAsyncRead('channels.getChannels', ['id' => [$this->genAll((yield $this->chats[$bot_api_id]), $folder_id, MTProto::INFO_TYPE_CONSTRUCTOR)]]);
                        } else {
                            yield from $this->methodCallAsyncRead('users.getUsers', ['id' => [$this->genAll((yield $this->chats[$bot_api_id]), $folder_id, MTProto::INFO_TYPE_CONSTRUCTOR)]]);
                        }
                    } catch (\danog\MadelineProto\Exception $e) {
                        $this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::WARNING);
                    } catch (\danog\MadelineProto\RPCErrorException $e) {
                        $this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::WARNING);
                    } finally {
                        unset($this->caching_full_info[$bot_api_id]);
                    }
                }
                return $this->genAll((yield $this->chats[$bot_api_id]), $folder_id, $type);
            }
        }
        if ($recursive) {
            yield from $this->resolveUsername($id);
            return yield from $this->getInfo($id, $type, false);
        }
        throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
    }
    /**
    * @template TConstructor
    * @psalm-param $constructor array{_: TConstructor}
    * @psalm-param $type        bool|null
    *
    * @return (((mixed | string)[] | mixed | string)[] | int | mixed | string)[]
    *
    * @psalm-return array{
    TConstructor: array
    InputPeer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed},
    Peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed},
    DialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
    NotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, chat_id?: mixed, channel_id?: mixed}},
    InputDialogPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
    InputNotifyPeer: array{_: string, peer: array{_: string, user_id?: mixed, access_hash?: mixed, min?: mixed, chat_id?: mixed, channel_id?: mixed}},
    bot_api_id: int|string,
    user_id?: int,
    chat_id?: int,
    channel_id?: int,
    InputUser?: {_: string, user_id?: int, access_hash?: mixed, min?: bool},
    InputChannel?: {_: string, channel_id: int, access_hash: mixed, min: bool},
    type: string
    }
    */
    private function genAll($constructor, $folder_id, int $type)
    {
        if ($type === MTProto::INFO_TYPE_CONSTRUCTOR) {
            if ($constructor['_'] === 'user') {
                return $constructor['self'] ?? false ? ['_' => 'inputUserSelf'] : ['_' => 'inputUser', 'user_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min']];
            }
            if ($constructor['_'] === 'channel') {
                return ['_' => 'inputChannel', 'channel_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min']];
            }
        }
        if ($type === MTProto::INFO_TYPE_PEER) {
            if ($constructor['_'] === 'user') {
                return $constructor['self'] ?? false ? ['_' => 'inputPeerSelf'] : ['_' => 'inputPeerUser', 'user_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min']];
            }
            if ($constructor['_'] === 'channel') {
                return ['_' => 'inputPeerChannel', 'channel_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min']];
            }
            if ($constructor['_'] === 'chat' || $constructor['_'] === 'chatForbidden') {
                return ['_' => 'inputPeerChat', 'chat_id' => $constructor['id']];
            }
        }
        if ($type === MTProto::INFO_TYPE_ID) {
            if ($constructor['_'] === 'user') {
                return $constructor['id'];
            }
            if ($constructor['_'] === 'channel') {
                return $this->toSupergroup($constructor['id']);
            }
            if ($constructor['_'] === 'chat' || $constructor['_'] === 'chatForbidden') {
                return -$constructor['id'];
            }
        }
        $res = [$this->TL->getConstructors()->findByPredicate($constructor['_'])['type'] => $constructor];
        switch ($constructor['_']) {
            case 'user':
                if ($constructor['self'] ?? false) {
                    $res['InputPeer'] = ['_' => 'inputPeerSelf'];
                    $res['InputUser'] = ['_' => 'inputUserSelf'];
                } elseif (isset($constructor['access_hash'])) {
                    $res['InputPeer'] = ['_' => 'inputPeerUser', 'user_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min']];
                    $res['InputUser'] = ['_' => 'inputUser', 'user_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min']];
                } else {
                    throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
                }
                $res['Peer'] = ['_' => 'peerUser', 'user_id' => $constructor['id']];
                $res['DialogPeer'] = ['_' => 'dialogPeer', 'peer' => $res['Peer']];
                $res['NotifyPeer'] = ['_' => 'notifyPeer', 'peer' => $res['Peer']];
                $res['InputDialogPeer'] = ['_' => 'inputDialogPeer', 'peer' => $res['InputPeer']];
                $res['InputNotifyPeer'] = ['_' => 'inputNotifyPeer', 'peer' => $res['InputPeer']];
                $res['user_id'] = $constructor['id'];
                $res['bot_api_id'] = $constructor['id'];
                $res['type'] = $constructor['bot'] ?? false ? 'bot' : 'user';
                break;
            case 'chat':
            case 'chatForbidden':
                $res['InputPeer'] = ['_' => 'inputPeerChat', 'chat_id' => $constructor['id']];
                $res['Peer'] = ['_' => 'peerChat', 'chat_id' => $constructor['id']];
                $res['DialogPeer'] = ['_' => 'dialogPeer', 'peer' => $res['Peer']];
                $res['NotifyPeer'] = ['_' => 'notifyPeer', 'peer' => $res['Peer']];
                $res['InputDialogPeer'] = ['_' => 'inputDialogPeer', 'peer' => $res['InputPeer']];
                $res['InputNotifyPeer'] = ['_' => 'inputNotifyPeer', 'peer' => $res['InputPeer']];
                $res['chat_id'] = $constructor['id'];
                $res['bot_api_id'] = -$constructor['id'];
                $res['type'] = 'chat';
                break;
            case 'channel':
                if (!isset($constructor['access_hash'])) {
                    throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
                }
                $res['InputPeer'] = ['_' => 'inputPeerChannel', 'channel_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min']];
                $res['Peer'] = ['_' => 'peerChannel', 'channel_id' => $constructor['id']];
                $res['DialogPeer'] = ['_' => 'dialogPeer', 'peer' => $res['Peer']];
                $res['NotifyPeer'] = ['_' => 'notifyPeer', 'peer' => $res['Peer']];
                $res['InputDialogPeer'] = ['_' => 'inputDialogPeer', 'peer' => $res['InputPeer']];
                $res['InputNotifyPeer'] = ['_' => 'inputNotifyPeer', 'peer' => $res['InputPeer']];
                $res['InputChannel'] = ['_' => 'inputChannel', 'channel_id' => $constructor['id'], 'access_hash' => $constructor['access_hash'], 'min' => $constructor['min']];
                $res['channel_id'] = $constructor['id'];
                $res['bot_api_id'] = $this->toSupergroup($constructor['id']);
                $res['type'] = $constructor['megagroup'] ?? false ? 'supergroup' : 'channel';
                break;
            case 'channelForbidden':
                throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
            default:
                throw new \danog\MadelineProto\Exception('Invalid constructor given ' . $constructor['_']);
        }
        if ($folder_id) {
            $res['FolderPeer'] = ['_' => 'folderPeer', 'peer' => $res['Peer'], 'folder_id' => $folder_id];
            $res['InputFolderPeer'] = ['_' => 'inputFolderPeer', 'peer' => $res['InputPeer'], 'folder_id' => $folder_id];
        }
        return $res;
    }
    /**
     * When were full info for this chat last cached.
     *
     * @param mixed $id Chat ID
     *
     * @return \Generator<integer>
     */
    public function fullChatLastUpdated($id) : \Generator
    {
        return ((yield $this->full_chats[$id]))['last_update'] ?? 0;
    }
    /**
     * Get full info about peer, returns an FullInfo object.
     *
     * @param mixed $id Peer
     *
     * @see https://docs.madelineproto.xyz/FullInfo.html
     *
     * @return \Generator FullInfo object
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | array), mixed, array>
     */
    public function getFullInfo($id) : \Generator
    {
        $partial = (yield from $this->getInfo($id));
        if (\time() - (yield from $this->fullChatLastUpdated($partial['bot_api_id'])) < $this->getSettings()->getPeer()->getFullInfoCacheTime()) {
            return \array_merge($partial, (yield $this->full_chats[$partial['bot_api_id']]));
        }
        $full = null;
        switch ($partial['type']) {
            case 'user':
            case 'bot':
                $full = (yield from $this->methodCallAsyncRead('users.getFullUser', ['id' => $partial['InputUser']]));
                break;
            case 'chat':
                $full = (yield from $this->methodCallAsyncRead('messages.getFullChat', $partial))['full_chat'];
                break;
            case 'channel':
            case 'supergroup':
                $full = (yield from $this->methodCallAsyncRead('channels.getFullChannel', ['channel' => $partial['InputChannel']]))['full_chat'];
                break;
        }
        $res = [];
        $res['full'] = $full;
        $res['last_update'] = \time();
        $this->full_chats[$partial['bot_api_id']] = $res;
        $partial = (yield from $this->getInfo($id));
        return \array_merge($partial, $res);
    }
    /**
     * Get full info about peer (including full list of channel members), returns a Chat object.
     *
     * @param mixed $id Peer
     *
     * @see https://docs.madelineproto.xyz/Chat.html
     *
     * @return \Generator Chat object
     */
    public function getPwrChat($id, bool $fullfetch = true, bool $send = true) : \Generator
    {
        $full = $fullfetch && $this->getSettings()->getDb()->getEnableFullPeerDb() ? yield from $this->getFullInfo($id) : (yield from $this->getInfo($id));
        $res = ['id' => $full['bot_api_id'], 'type' => $full['type']];
        switch ($full['type']) {
            case 'user':
            case 'bot':
                foreach (['first_name', 'last_name', 'username', 'verified', 'restricted', 'restriction_reason', 'status', 'bot_inline_placeholder', 'access_hash', 'phone', 'lang_code', 'bot_nochats'] as $key) {
                    if (isset($full['User'][$key])) {
                        $res[$key] = $full['User'][$key];
                    }
                }
                foreach (['about', 'bot_info', 'phone_calls_available', 'phone_calls_private', 'common_chats_count', 'can_pin_message', 'pinned_msg_id', 'notify_settings'] as $key) {
                    if (isset($full['full'][$key])) {
                        $res[$key] = $full['full'][$key];
                    }
                }
                if (isset($full['full']['profile_photo']['sizes'])) {
                    $res['photo'] = $full['full']['profile_photo'];
                }
                break;
            case 'chat':
                foreach (['title', 'participants_count', 'admin', 'admins_enabled'] as $key) {
                    if (isset($full['Chat'][$key])) {
                        $res[$key] = $full['Chat'][$key];
                    }
                }
                foreach (['bot_info', 'pinned_msg_id', 'notify_settings'] as $key) {
                    if (isset($full['full'][$key])) {
                        $res[$key] = $full['full'][$key];
                    }
                }
                if (isset($res['admins_enabled'])) {
                    $res['all_members_are_administrators'] = !$res['admins_enabled'];
                }
                if (isset($full['full']['chat_photo']['sizes'])) {
                    $res['photo'] = $full['full']['chat_photo'];
                }
                if (isset($full['full']['exported_invite']['link'])) {
                    $res['invite'] = $full['full']['exported_invite']['link'];
                }
                if (isset($full['full']['participants']['participants'])) {
                    $res['participants'] = $full['full']['participants']['participants'];
                }
                break;
            case 'channel':
            case 'supergroup':
                foreach (['title', 'democracy', 'restricted', 'restriction_reason', 'access_hash', 'username', 'signatures'] as $key) {
                    if (isset($full['Chat'][$key])) {
                        $res[$key] = $full['Chat'][$key];
                    }
                }
                foreach (['read_inbox_max_id', 'read_outbox_max_id', 'hidden_prehistory', 'bot_info', 'notify_settings', 'can_set_stickers', 'stickerset', 'can_view_participants', 'can_set_username', 'participants_count', 'admins_count', 'kicked_count', 'banned_count', 'migrated_from_chat_id', 'migrated_from_max_id', 'pinned_msg_id', 'about', 'hidden_prehistory', 'available_min_id', 'can_view_stats', 'online_count'] as $key) {
                    if (isset($full['full'][$key])) {
                        $res[$key] = $full['full'][$key];
                    }
                }
                if (isset($full['full']['chat_photo']['sizes'])) {
                    $res['photo'] = $full['full']['chat_photo'];
                }
                if (isset($full['full']['exported_invite']['link'])) {
                    $res['invite'] = $full['full']['exported_invite']['link'];
                }
                if (isset($full['full']['participants']['participants'])) {
                    $res['participants'] = $full['full']['participants']['participants'];
                }
                break;
        }
        if (isset($res['participants']) && $fullfetch) {
            foreach ($res['participants'] as $key => $participant) {
                $newres = [];
                $newres['user'] = (yield from $this->getPwrChat($participant['user_id'] ?? $participant['peer'], false, true));
                if (isset($participant['inviter_id'])) {
                    $newres['inviter'] = (yield from $this->getPwrChat($participant['inviter_id'], false, true));
                }
                if (isset($participant['promoted_by'])) {
                    $newres['promoted_by'] = (yield from $this->getPwrChat($participant['promoted_by'], false, true));
                }
                if (isset($participant['kicked_by'])) {
                    $newres['kicked_by'] = (yield from $this->getPwrChat($participant['kicked_by'], false, true));
                }
                if (isset($participant['date'])) {
                    $newres['date'] = $participant['date'];
                }
                if (isset($participant['admin_rights'])) {
                    $newres['admin_rights'] = $participant['admin_rights'];
                }
                if (isset($participant['banned_rights'])) {
                    $newres['banned_rights'] = $participant['banned_rights'];
                }
                if (isset($participant['can_edit'])) {
                    $newres['can_edit'] = $participant['can_edit'];
                }
                if (isset($participant['left'])) {
                    $newres['left'] = $participant['left'];
                }
                switch ($participant['_']) {
                    case 'chatParticipant':
                        $newres['role'] = 'user';
                        break;
                    case 'chatParticipantAdmin':
                        $newres['role'] = 'admin';
                        break;
                    case 'chatParticipantCreator':
                        $newres['role'] = 'creator';
                        break;
                }
                $res['participants'][$key] = $newres;
            }
        }
        if (!isset($res['participants']) && $fullfetch && \in_array($res['type'], ['supergroup', 'channel'])) {
            $total_count = (isset($res['participants_count']) ? $res['participants_count'] : 0) + (isset($res['admins_count']) ? $res['admins_count'] : 0) + (isset($res['kicked_count']) ? $res['kicked_count'] : 0) + (isset($res['banned_count']) ? $res['banned_count'] : 0);
            $res['participants'] = [];
            $filters = ['channelParticipantsAdmins', 'channelParticipantsBots'];
            $promises = [];
            foreach ($filters as $filter) {
                $promises[] = $this->fetchParticipants($full['InputChannel'], $filter, '', $total_count, $res);
            }
            (yield Tools::all($promises));
            $q = '';
            $filters = ['channelParticipantsSearch', 'channelParticipantsKicked', 'channelParticipantsBanned'];
            $promises = [];
            foreach ($filters as $filter) {
                $promises[] = $this->recurseAlphabetSearchParticipants($full['InputChannel'], $filter, $q, $total_count, $res, 0);
            }
            (yield Tools::all($promises));
            $this->logger->logger('Fetched ' . \count($res['participants']) . " out of {$total_count}");
            $res['participants'] = \array_values($res['participants']);
        }
        if (!$fullfetch) {
            unset($res['participants']);
        }
        if ($fullfetch || $send) {
            $this->storeDb($res);
        }
        if (isset($res['photo'])) {
            $photo = [];
            foreach (['small' => $res['photo']['sizes'][0], 'big' => Tools::maxSize($res['photo']['sizes'])] as $type => $size) {
                $fileId = new FileId();
                $fileId->setId($res['photo']['id']);
                $fileId->setAccessHash($res['photo']['access_hash']);
                $fileId->setFileReference($res['photo']['file_reference']);
                $fileId->setDcId($res['photo']['dc_id']);
                $fileId->setType(PROFILE_PHOTO);
                $photoSize = new PhotoSizeSourceDialogPhoto($type === 'small' ? PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL : PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG);
                $photoSize->setDialogId($res['id']);
                $photoSize->setDialogAccessHash($res['access_hash'] ?? 0);
                $fileId->setPhotoSizeSource($photoSize);
                $photo[$type . '_file_id'] = (string) $fileId;
                $photo[$type . '_file_unique_id'] = $fileId->getUniqueBotAPI();
            }
            $res['photo'] += $photo;
        }
        return $res;
    }
    /**
     *
     */
    private function recurseAlphabetSearchParticipants($channel, $filter, $q, $total_count, &$res, int $depth) : \Generator
    {
        if (!(yield from $this->fetchParticipants($channel, $filter, $q, $total_count, $res))) {
            return [];
        }
        $promises = [];
        for ($x = 'a'; $x !== 'aa' && $total_count > \count($res['participants']); $x++) {
            $promises[] = $this->recurseAlphabetSearchParticipants($channel, $filter, $q . $x, $total_count, $res, $depth + 1);
        }
        if ($depth > 2) {
            return $promises;
        }
        $yielded = [...(yield Tools::all($promises))];
        while ($yielded) {
            $newYielded = [];
            foreach (\array_chunk($yielded, 10) as $promises) {
                $newYielded = \array_merge($newYielded, ...(yield Tools::all($promises)));
            }
            $yielded = $newYielded;
        }
        return [];
    }
    /**
     *
     */
    private function fetchParticipants($channel, $filter, $q, $total_count, &$res) : \Generator
    {
        $offset = 0;
        $limit = 200;
        $has_more = false;
        $cached = false;
        $last_count = -1;
        do {
            try {
                $gres = (yield from $this->methodCallAsyncRead('channels.getParticipants', ['channel' => $channel, 'filter' => ['_' => $filter, 'q' => $q], 'offset' => $offset, 'limit' => $limit, 'hash' => $hash = (yield from $this->getParticipantsHash($channel, $filter, $q, $offset, $limit))], ['datacenter' => $this->datacenter->curdc, 'heavy' => true]));
            } catch (\danog\MadelineProto\RPCErrorException $e) {
                if ($e->rpc === 'CHAT_ADMIN_REQUIRED') {
                    $this->logger->logger($e->rpc);
                    return $has_more;
                }
                throw $e;
            }
            if ($cached = $gres['_'] === 'channels.channelParticipantsNotModified') {
                $gres = (yield $this->fetchParticipantsCache($channel, $filter, $q, $offset, $limit));
            } else {
                $this->storeParticipantsCache($gres, $channel, $filter, $q, $offset, $limit);
            }
            if ($last_count !== -1 && $last_count !== $gres['count']) {
                $has_more = true;
            } else {
                $last_count = $gres['count'];
            }
            $promises = [];
            foreach ($gres['participants'] as $participant) {
                $promises[] = Tools::call((function () use(&$res, $participant) {
                    $newres = [];
                    $newres['user'] = (yield from $this->getPwrChat($participant['user_id'] ?? $participant['peer'], false, true));
                    if (isset($participant['inviter_id'])) {
                        $newres['inviter'] = (yield from $this->getPwrChat($participant['inviter_id'], false, true));
                    }
                    if (isset($participant['kicked_by'])) {
                        $newres['kicked_by'] = (yield from $this->getPwrChat($participant['kicked_by'], false, true));
                    }
                    if (isset($participant['promoted_by'])) {
                        $newres['promoted_by'] = (yield from $this->getPwrChat($participant['promoted_by'], false, true));
                    }
                    if (isset($participant['date'])) {
                        $newres['date'] = $participant['date'];
                    }
                    if (isset($participant['rank'])) {
                        $newres['rank'] = $participant['rank'];
                    }
                    if (isset($participant['admin_rights'])) {
                        $newres['admin_rights'] = $participant['admin_rights'];
                    }
                    if (isset($participant['banned_rights'])) {
                        $newres['banned_rights'] = $participant['banned_rights'];
                    }
                    switch ($participant['_']) {
                        case 'channelParticipantSelf':
                            $newres['role'] = 'user';
                            break;
                        case 'channelParticipant':
                            $newres['role'] = 'user';
                            break;
                        case 'channelParticipantCreator':
                            $newres['role'] = 'creator';
                            break;
                        case 'channelParticipantAdmin':
                            $newres['role'] = 'admin';
                            break;
                        case 'channelParticipantBanned':
                            $newres['role'] = 'banned';
                            break;
                    }
                    $res['participants'][$participant['user_id'] ?? $this->getId($participant['peer'])] = $newres;
                })());
            }
            (yield Tools::all($promises));
            $this->logger->logger('Fetched ' . \count($gres['participants']) . " channel participants with filter {$filter}, query {$q}, offset {$offset}, limit {$limit}, hash {$hash}: " . ($cached ? 'cached' : 'not cached') . ', ' . ($offset + \count($gres['participants'])) . ' participants out of ' . $gres['count'] . ', in total fetched ' . \count($res['participants']) . ' out of ' . $total_count);
            $offset += \count($gres['participants']);
        } while (\count($gres['participants']));
        if ($offset === $limit) {
            return true;
        }
        return $has_more;
    }
    /**
     * Key for participatns cache.
     *
     * @param integer $channelId
     * @param string $filter
     * @param string $q
     * @param integer $offset
     * @param integer $limit
     * @return string
     */
    private function participantsKey(int $channelId, string $filter, string $q, int $offset, int $limit) : string
    {
        return "{$channelId}'{$filter}'{$q}'{$offset}'{$limit}";
    }
    /**
     *
     */
    private function fetchParticipantsCache($channel, $filter, $q, $offset, $limit) : Promise
    {
        return $this->channelParticipants[$this->participantsKey($channel['channel_id'], $filter, $q, $offset, $limit)];
    }
    /**
     *
     */
    private function storeParticipantsCache($gres, $channel, $filter, $q, $offset, $limit) : void
    {
        unset($gres['users']);
        $ids = [];
        foreach ($gres['participants'] as $participant) {
            if (isset($participant['user_id'])) {
                $ids[] = $participant['user_id'];
            }
        }
        \sort($ids, SORT_NUMERIC);
        $gres['hash'] = \danog\MadelineProto\Tools::genVectorHash($ids);
        $this->channelParticipants[$this->participantsKey($channel['channel_id'], $filter, $q, $offset, $limit)] = $gres;
    }
    /**
     *
     */
    private function getParticipantsHash($channel, $filter, $q, $offset, $limit) : \Generator
    {
        return ((yield $this->channelParticipants[$this->participantsKey($channel['channel_id'], $filter, $q, $offset, $limit)]))['hash'] ?? 0;
    }
    /**
     *
     */
    private function storeDb($res, $force = false) : \Generator
    {
        if (!$this->settings->getPwr()->getDbToken() || $this->settings->getConnection()->getTestMode()) {
            return;
        }
        if (!empty($res)) {
            if (isset($res['participants'])) {
                unset($res['participants']);
            }
            $this->qres[] = $res;
        }
        if ($this->last_stored > \time() && !$force) {
            //$this->logger->logger("========== WILL SERIALIZE IN ".($this->last_stored - time())." =============");
            return false;
        }
        if (empty($this->qres)) {
            return false;
        }
        try {
            $payload = \json_encode($this->qres);
            //$path = '/tmp/ids'.hash('sha256', $payload);
            //file_put_contents($path, $payload);
            $id = isset($this->authorization['user']['username']) ? $this->authorization['user']['username'] : $this->authorization['user']['id'];
            $request = new Request('https://id.pwrtelegram.xyz/db' . $this->settings->getPwr()->getDbToken() . '/addnewmadeline?d=pls&from=' . $id, 'POST');
            $request->setHeader('content-type', 'application/json');
            $request->setBody($payload);
            $result = (yield ((yield $this->datacenter->getHTTPClient()->request($request)))->getBody()->buffer());
            $this->logger->logger("============ {$result} =============", \danog\MadelineProto\Logger::VERBOSE);
            $this->qres = [];
            $this->last_stored = \time() + 10;
        } catch (\danog\MadelineProto\Exception $e) {
            $this->logger->logger('======= COULD NOT STORE IN DB DUE TO ' . $e->getMessage() . ' =============', \danog\MadelineProto\Logger::VERBOSE);
        }
    }
    /**
     * Resolve username (use getInfo instead).
     *
     * @param string $username Username
     *
     * @return \Generator
     */
    public function resolveUsername(string $username) : \Generator
    {
        $username = \str_replace('@', '', $username);
        if (!$username) {
            return false;
        }
        try {
            $this->caching_simple_username[$username] = true;
            $res = (yield from $this->methodCallAsyncRead('contacts.resolveUsername', ['username' => $username]));
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            $this->logger->logger('Username resolution failed with error ' . $e->getMessage(), \danog\MadelineProto\Logger::ERROR);
            if (\strpos($e->rpc, 'FLOOD_WAIT_') === 0 || $e->rpc === 'AUTH_KEY_UNREGISTERED' || $e->rpc === 'USERNAME_INVALID') {
                throw $e;
            }
            return false;
        } finally {
            if (isset($this->caching_simple_username[$username])) {
                unset($this->caching_simple_username[$username]);
            }
        }
        if ($res['_'] === 'contacts.resolvedPeer') {
            foreach ($res['chats'] as $chat) {
                yield from $this->addChat($chat);
            }
            foreach ($res['users'] as $user) {
                yield from $this->addUser($user);
            }
            return $res;
        }
        return false;
    }
}<?php

/**
 * AuthKeyHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use Amp\Http\Client\Request;
use danog\MadelineProto\DataCenter;
use danog\MadelineProto\DataCenterConnection;
use danog\MadelineProto\Exception;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProto\TempAuthKey;
use danog\MadelineProto\RPCErrorException;
use danog\MadelineProto\SecurityException;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools;
use danog\PrimeModule;
use phpseclib3\Math\BigInteger;
/**
 * Manages the creation of the authorization key.
 *
 * https://core.telegram.org/mtproto/auth_key
 * https://core.telegram.org/mtproto/samples-auth_key
 *
 * @property Settings $settings Settings
 * @property DataCenter $datacenter
 */
trait AuthKeyHandler
{
    /**
     * DCs currently initing authorization.
     *
     * @var array<bool>
     */
    private $init_auth_dcs = [];
    /**
     * Currently initing authorization?
     *
     * @var boolean
     */
    private $pending_auth = false;
    /**
     * Create authorization key.
     *
     * @param int $expires_in Expiry date of auth key, -1 for permanent auth key
     * @param string $datacenter DC ID
     *
     * @internal
     *
     * @return \Generator
     *
     * @psalm-return \Generator<mixed, (mixed | string), mixed, (\danog\MadelineProto\MTProto\PermAuthKey | \danog\MadelineProto\MTProto\TempAuthKey | null)>
     */
    public function createAuthKey(int $expires_in, string $datacenter) : \Generator
    {
        $connection = $this->datacenter->getAuthConnection($datacenter);
        $cdn = $connection->isCDN();
        $media = $connection->isMedia();
        $test = $this->settings->getConnection()->getTestMode();
        $datacenter_id = \preg_replace('|_.*|', '', $datacenter) + ($this->settings->getConnection()->getTestMode() ? 10000 : 0);
        if ($media) {
            $datacenter_id = -$datacenter_id;
        }
        for ($retry_id_total = 1; $retry_id_total <= $this->settings->getAuth()->getMaxAuthTries(); $retry_id_total++) {
            try {
                $this->logger->logger("Requesting pq...", \danog\MadelineProto\Logger::VERBOSE);
                /**
                 * ***********************************************************************
                 * Make pq request, DH exchange initiation.
                 *
                 * @method req_pq_multi
                 *
                 * @param [
                 *         int128         $nonce                             : The value of nonce is selected randomly by the client (random number) and identifies the client within this communication
                 * ]
                 *
                 * @return ResPQ [
                 *               int128         $nonce                             : The value of nonce is selected randomly by the server
                 *               int128         $server_nonce                         : The value of server_nonce is selected randomly by the server
                 *               string         $pq                             : This is a representation of a natural number (in binary big endian format). This number is the product of two different odd prime numbers
                 *               Vector long    $server_public_key_fingerprints                : This is a list of public RSA key fingerprints
                 *               ]
                 */
                $nonce = \danog\MadelineProto\Tools::random(16);
                $ResPQ = (yield from $connection->methodCallAsyncRead('req_pq_multi', ['nonce' => $nonce]));
                /*
                 * ***********************************************************************
                 * Check if the client's nonce and the server's nonce are the same
                 */
                if ($ResPQ['nonce'] !== $nonce) {
                    throw new \danog\MadelineProto\SecurityException('wrong nonce');
                }
                /*
                 * ***********************************************************************
                 * Find our key in the server_public_key_fingerprints vector
                 */
                if ($test) {
                    $keys = $this->test_rsa_keys;
                } else {
                    $keys = $this->rsa_keys;
                }
                foreach ($cdn ? \array_merge($this->cdn_rsa_keys, $keys) : $keys as $curkey) {
                    if (\in_array($curkey->fp, $ResPQ['server_public_key_fingerprints'])) {
                        $key = $curkey;
                    }
                }
                if (!isset($key)) {
                    if ($cdn) {
                        $this->logger->logger("Could not find required CDN public key, postponing CDN handshake...");
                        return;
                    }
                    throw new \danog\MadelineProto\SecurityException("Couldn't find any of our keys in the server_public_key_fingerprints vector.");
                }
                $pq_bytes = $ResPQ['pq'];
                $server_nonce = $ResPQ['server_nonce'];
                /*
                 * ***********************************************************************
                 * Compute p and q
                 */
                $ok = false;
                $pq = Tools::unpackSignedLong(\strrev($pq_bytes));
                foreach (['native_single_cpp', 'python_single_alt', 'python_single', 'native_single', 'wolfram'] as $method) {
                    $this->logger->logger("Factorizing with {$method} (please wait, might take a while)");
                    if ($method !== 'native_single_cpp') {
                        $this->logger->logger("Install https://prime.madelineproto.xyz to speed this up!");
                    }
                    $p = 0;
                    $q = 0;
                    try {
                        if ($method === 'wolfram') {
                            $p = (yield from $this->wolframSingle($pq));
                        } else {
                            $p = PrimeModule::$method($pq);
                        }
                    } catch (\Throwable $e) {
                        $this->logger->logger("While factorizing with {$method}: {$e}");
                    }
                    if ($p) {
                        $q = $pq / $p;
                        if ($p > $q) {
                            list($p, $q) = [$q, $p];
                        }
                        if ($pq === $p * $q) {
                            $ok = true;
                            break;
                        }
                    }
                }
                if (!$ok) {
                    throw new \danog\MadelineProto\SecurityException("Couldn't compute p and q, install prime.madelineproto.xyz to fix. Original pq: {$pq}, computed p: {$p}, computed q: {$q}, computed pq: " . $p * $q);
                }
                $this->logger->logger('Factorization ' . $pq . ' = ' . $p . ' * ' . $q, \danog\MadelineProto\Logger::VERBOSE);
                /*
                 * ***********************************************************************
                 * Serialize object for req_DH_params
                 */
                $p_bytes = \strrev(Tools::packUnsignedInt($p));
                $q_bytes = \strrev(Tools::packUnsignedInt($q));
                $new_nonce = \danog\MadelineProto\Tools::random(32);
                $data_unserialized = ['_' => 'p_q_inner_data' . ($expires_in < 0 ? '' : '_temp') . '_dc', 'pq' => $pq_bytes, 'p' => $p_bytes, 'q' => $q_bytes, 'nonce' => $nonce, 'server_nonce' => $server_nonce, 'new_nonce' => $new_nonce, 'expires_in' => $expires_in, 'dc' => $datacenter_id];
                $p_q_inner_data = (yield from $this->TL->serializeObject(['type' => ''], $data_unserialized, 'p_q_inner_data'));
                /*
                 * ***********************************************************************
                 * Encrypt serialized object
                 */
                if (\strlen($p_q_inner_data) > 144) {
                    throw new SecurityException('p_q_inner_data is too long!');
                }
                $data_with_padding = $p_q_inner_data . Tools::random(192 - \strlen($p_q_inner_data));
                $data_pad_reversed = \strrev($data_with_padding);
                do {
                    $temp_key = Tools::random(32);
                    $data_with_hash = $data_pad_reversed . \hash('sha256', $temp_key . $data_with_padding, true);
                    $aes_encrypted = Crypt::igeEncrypt($data_with_hash, $temp_key, \str_repeat("\x00", 32));
                    $temp_key_xor = $temp_key ^ \hash('sha256', $aes_encrypted, true);
                    $key_aes_encrypted_bigint = new BigInteger($temp_key_xor . $aes_encrypted, 256);
                } while ($key_aes_encrypted_bigint->compare($key->n) >= 0);
                $encrypted_data = $key->encrypt($key_aes_encrypted_bigint);
                $this->logger->logger('Starting Diffie Hellman key exchange', \danog\MadelineProto\Logger::VERBOSE);
                /*
                 * ***********************************************************************
                 * Starting Diffie Hellman key exchange, Server authentication
                 * @method req_DH_params
                 * @param [
                 *         int128         $nonce                             : The value of nonce is selected randomly by the client (random number) and identifies the client within this communication
                 *         int128        $server_nonce                    : The value of server_nonce is selected randomly by the server
                 *         string        $p                                : The value of BigInteger
                 *         string        $q                                : The value of BigInteger
                 *         long        $public_key_fingerprint            : This is our key in the server_public_key_fingerprints vector
                 *         string        $encrypted_data
                 * ]
                 * @return Server_DH_Params [
                 *         int128         $nonce                         : The value of nonce is selected randomly by the server
                 *         int128         $server_nonce                     : The value of server_nonce is selected randomly by the server
                 *         string         $new_nonce_hash                    : Return this value if server responds with server_DH_params_fail
                 *         string         $encrypted_answer                : Return this value if server responds with server_DH_params_ok
                 * ]
                 */
                //
                $server_dh_params = (yield from $connection->methodCallAsyncRead('req_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'p' => $p_bytes, 'q' => $q_bytes, 'public_key_fingerprint' => $key->fp, 'encrypted_data' => $encrypted_data]));
                /*
                 * ***********************************************************************
                 * Check if the client's nonce and the server's nonce are the same
                 */
                if ($nonce != $server_dh_params['nonce']) {
                    throw new \danog\MadelineProto\SecurityException('wrong nonce.');
                }
                /*
                 * ***********************************************************************
                 * Check if server_nonce and new server_nonce are the same
                 */
                if ($server_nonce != $server_dh_params['server_nonce']) {
                    throw new \danog\MadelineProto\SecurityException('wrong server nonce.');
                }
                /*
                 * ***********************************************************************
                 * Check valid new nonce hash if return from server
                 * new nonce hash return in server_DH_params_fail
                 */
                if (isset($server_dh_params['new_nonce_hash']) && \Phabel\Target\Php80\Polyfill::substr(\sha1($new_nonce), -32) != $server_dh_params['new_nonce_hash']) {
                    throw new \danog\MadelineProto\SecurityException('wrong new nonce hash.');
                }
                /*
                 * ***********************************************************************
                 * Get key, iv and decrypt answer
                 */
                $encrypted_answer = $server_dh_params['encrypted_answer'];
                $tmp_aes_key = \sha1($new_nonce . $server_nonce, true) . \Phabel\Target\Php80\Polyfill::substr(\sha1($server_nonce . $new_nonce, true), 0, 12);
                $tmp_aes_iv = \Phabel\Target\Php80\Polyfill::substr(\sha1($server_nonce . $new_nonce, true), 12, 8) . \sha1($new_nonce . $new_nonce, true) . \Phabel\Target\Php80\Polyfill::substr($new_nonce, 0, 4);
                $answer_with_hash = Crypt::igeDecrypt($encrypted_answer, $tmp_aes_key, $tmp_aes_iv);
                /*
                 * ***********************************************************************
                 * Separate answer and hash
                 */
                $answer_hash = \Phabel\Target\Php80\Polyfill::substr($answer_with_hash, 0, 20);
                /** @var string */
                $answer = \Phabel\Target\Php80\Polyfill::substr($answer_with_hash, 20);
                /*
                 * ***********************************************************************
                 * Deserialize answer
                 * @return Server_DH_inner_data [
                 *         int128         $nonce                             : The value of nonce is selected randomly by the client (random number) and identifies the client within this communication
                 *         int128        $server_nonce                    : The value of server_nonce is selected randomly by the server
                 *         int            $g
                 *         string        $dh_prime
                 *         string        $g_a
                 *         int            $server_time
                 * ]
                 */
                [$server_DH_inner_data] = $this->TL->deserialize($answer, ['type' => '']);
                /*
                 * ***********************************************************************
                 * Do some checks
                 */
                $server_DH_inner_data_length = $this->TL->getLength($answer);
                if (\sha1(\Phabel\Target\Php80\Polyfill::substr($answer, 0, $server_DH_inner_data_length), true) != $answer_hash) {
                    throw new \danog\MadelineProto\SecurityException('answer_hash mismatch.');
                }
                if ($nonce != $server_DH_inner_data['nonce']) {
                    throw new \danog\MadelineProto\SecurityException('wrong nonce');
                }
                if ($server_nonce != $server_DH_inner_data['server_nonce']) {
                    throw new \danog\MadelineProto\SecurityException('wrong server nonce');
                }
                $g = new BigInteger($server_DH_inner_data['g']);
                $g_a = new BigInteger((string) $server_DH_inner_data['g_a'], 256);
                $dh_prime = new BigInteger((string) $server_DH_inner_data['dh_prime'], 256);
                /*
                 * ***********************************************************************
                 * Time delta
                 */
                $server_time = $server_DH_inner_data['server_time'];
                $connection->time_delta = $server_time - \time();
                $this->logger->logger(\sprintf('Server-client time delta = %.1f s', $connection->time_delta), \danog\MadelineProto\Logger::VERBOSE);
                Crypt::checkPG($dh_prime, $g);
                Crypt::checkG($g_a, $dh_prime);
                for ($retry_id = 0; $retry_id <= $this->settings->getAuth()->getMaxAuthTries(); $retry_id++) {
                    $this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
                    $b = new BigInteger(\danog\MadelineProto\Tools::random(256), 256);
                    $this->logger->logger('Generating g_b...', \danog\MadelineProto\Logger::VERBOSE);
                    $g_b = $g->powMod($b, $dh_prime);
                    Crypt::checkG($g_b, $dh_prime);
                    /*
                     * ***********************************************************************
                     * Check validity of g_b
                     * 1 < g_b < dh_prime - 1
                     */
                    $this->logger->logger('Executing g_b check...', \danog\MadelineProto\Logger::VERBOSE);
                    if ($g_b->compare(\danog\MadelineProto\Magic::$one) <= 0 || $g_b->compare($dh_prime->subtract(\danog\MadelineProto\Magic::$one)) >= 0) {
                        throw new \danog\MadelineProto\SecurityException('g_b is invalid (1 < g_b < dh_prime - 1 is false).');
                    }
                    $this->logger->logger('Preparing client_DH_inner_data...', \danog\MadelineProto\Logger::VERBOSE);
                    $g_b_str = $g_b->toBytes();
                    /*
                     * ***********************************************************************
                     * serialize client_DH_inner_data
                     * @method client_DH_inner_data
                     * @param Server_DH_inner_data [
                     *         int128         $nonce                             : The value of nonce is selected randomly by the client (random number) and identifies the client within this communication
                     *         int128        $server_nonce                    : The value of server_nonce is selected randomly by the server
                     *         long        $retry_id                        : First attempt
                     *         string        $g_b                            : g^b mod dh_prime
                     * ]
                     */
                    $data = (yield from $this->TL->serializeObject(['type' => ''], ['_' => 'client_DH_inner_data', 'nonce' => $nonce, 'server_nonce' => $server_nonce, 'retry_id' => $retry_id, 'g_b' => $g_b_str], 'client_DH_inner_data'));
                    /*
                     * ***********************************************************************
                     * encrypt client_DH_inner_data
                     */
                    $data_with_sha = \sha1($data, true) . $data;
                    $data_with_sha_padded = $data_with_sha . \danog\MadelineProto\Tools::random(\danog\MadelineProto\Tools::posmod(-\strlen($data_with_sha), 16));
                    $encrypted_data = Crypt::igeEncrypt($data_with_sha_padded, $tmp_aes_key, $tmp_aes_iv);
                    $this->logger->logger('Executing set_client_DH_params...', \danog\MadelineProto\Logger::VERBOSE);
                    /*
                     * ***********************************************************************
                     * Send set_client_DH_params query
                     * @method set_client_DH_params
                     * @param Server_DH_inner_data [
                     *         int128         $nonce                             : The value of nonce is selected randomly by the client (random number) and identifies the client within this communication
                     *         int128        $server_nonce                    : The value of server_nonce is selected randomly by the server
                     *         string        $encrypted_data
                     * ]
                     * @return Set_client_DH_params_answer [
                     *         string         $_                                 : This value is dh_gen_ok, dh_gen_retry OR dh_gen_fail
                     *         int128         $server_nonce                     : The value of server_nonce is selected randomly by the server
                     *         int128         $new_nonce_hash1                : Return this value if server responds with dh_gen_ok
                     *         int128         $new_nonce_hash2                : Return this value if server responds with dh_gen_retry
                     *         int128         $new_nonce_hash2                : Return this value if server responds with dh_gen_fail
                     * ]
                     */
                    $Set_client_DH_params_answer = (yield from $connection->methodCallAsyncRead('set_client_DH_params', ['nonce' => $nonce, 'server_nonce' => $server_nonce, 'encrypted_data' => $encrypted_data]));
                    /*
                     * ***********************************************************************
                     * Generate auth_key
                     */
                    $this->logger->logger('Generating authorization key...', \danog\MadelineProto\Logger::VERBOSE);
                    $auth_key = $g_a->powMod($b, $dh_prime);
                    $auth_key_str = $auth_key->toBytes();
                    $auth_key_sha = \sha1($auth_key_str, true);
                    $auth_key_aux_hash = \Phabel\Target\Php80\Polyfill::substr($auth_key_sha, 0, 8);
                    $new_nonce_hash1 = \Phabel\Target\Php80\Polyfill::substr(\sha1($new_nonce . \chr(1) . $auth_key_aux_hash, true), -16);
                    $new_nonce_hash2 = \Phabel\Target\Php80\Polyfill::substr(\sha1($new_nonce . \chr(2) . $auth_key_aux_hash, true), -16);
                    $new_nonce_hash3 = \Phabel\Target\Php80\Polyfill::substr(\sha1($new_nonce . \chr(3) . $auth_key_aux_hash, true), -16);
                    /*
                     * ***********************************************************************
                     * Check if the client's nonce and the server's nonce are the same
                     */
                    if ($Set_client_DH_params_answer['nonce'] != $nonce) {
                        throw new \danog\MadelineProto\SecurityException('wrong nonce.');
                    }
                    /*
                     * ***********************************************************************
                     * Check if server_nonce and new server_nonce are the same
                     */
                    if ($Set_client_DH_params_answer['server_nonce'] != $server_nonce) {
                        throw new \danog\MadelineProto\SecurityException('wrong server nonce');
                    }
                    /*
                     * ***********************************************************************
                     * Check Set_client_DH_params_answer type
                     */
                    switch ($Set_client_DH_params_answer['_']) {
                        case 'dh_gen_ok':
                            if ($Set_client_DH_params_answer['new_nonce_hash1'] != $new_nonce_hash1) {
                                throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash1');
                            }
                            $this->logger->logger('Diffie Hellman key exchange processed successfully!', \danog\MadelineProto\Logger::VERBOSE);
                            $key = $expires_in < 0 ? new PermAuthKey() : new TempAuthKey();
                            if ($expires_in >= 0) {
                                $key->expires(\time() + $expires_in);
                            }
                            $key->setServerSalt(\Phabel\Target\Php80\Polyfill::substr($new_nonce, 0, 8) ^ \Phabel\Target\Php80\Polyfill::substr($server_nonce, 0, 8));
                            $key->setAuthKey($auth_key_str);
                            $this->logger->logger('Auth key generated', \danog\MadelineProto\Logger::NOTICE);
                            return $key;
                        case 'dh_gen_retry':
                            if ($Set_client_DH_params_answer['new_nonce_hash2'] != $new_nonce_hash2) {
                                throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash_2');
                            }
                            //repeat foreach
                            $this->logger->logger('Retrying Auth', \danog\MadelineProto\Logger::VERBOSE);
                            break;
                        case 'dh_gen_fail':
                            if ($Set_client_DH_params_answer['new_nonce_hash3'] != $new_nonce_hash3) {
                                throw new \danog\MadelineProto\SecurityException('wrong new_nonce_hash_3');
                            }
                            $this->logger->logger('Auth Failed', \danog\MadelineProto\Logger::WARNING);
                            break 2;
                        default:
                            throw new \danog\MadelineProto\SecurityException('Response Error');
                            break;
                    }
                }
            } catch (SecurityException|Exception|RPCErrorException $e) {
                $this->logger->logger('An exception occurred while generating the authorization key: ' . $e->getMessage() . ' in ' . \basename($e->getFile(), '.php') . ' on line ' . $e->getLine() . '. Retrying...', \danog\MadelineProto\Logger::WARNING);
                yield from $connection->reconnect();
            } catch (\Throwable $e) {
                $this->logger->logger('An exception occurred while generating the authorization key: ' . $e . PHP_EOL . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
                yield from $connection->reconnect();
            }
        }
        if (!$cdn) {
            throw new \danog\MadelineProto\SecurityException('Auth Failed, please check the logfile for more information, make sure to install https://prime.madelineproto.xyz!');
        }
    }
    /**
     * Get diffie-hellman configuration.
     *
     * @internal
     *
     * @return \Generator<array>
     */
    public function getDhConfig() : \Generator
    {
        $dh_config = (yield from $this->methodCallAsyncRead('messages.getDhConfig', ['version' => $this->dh_config['version'], 'random_length' => 0]));
        if ($dh_config['_'] === 'messages.dhConfigNotModified') {
            $this->logger->logger('DH configuration not modified', \danog\MadelineProto\Logger::VERBOSE);
            return $this->dh_config;
        }
        $dh_config['p'] = new BigInteger((string) $dh_config['p'], 256);
        $dh_config['g'] = new BigInteger($dh_config['g']);
        Crypt::checkPG($dh_config['p'], $dh_config['g']);
        return $this->dh_config = $dh_config;
    }
    /**
     * Bind temporary and permanent auth keys.
     *
     * @param integer $expires_in Date of expiry for binding
     * @param string $datacenter DC ID
     *
     * @internal
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (array | mixed), mixed, true>
     */
    public function bindTempAuthKey(int $expires_in, string $datacenter) : \Generator
    {
        $datacenterConnection = $this->datacenter->getDataCenterConnection($datacenter);
        $connection = $datacenterConnection->getAuthConnection();
        for ($retry_id_total = 1; $retry_id_total <= $this->settings->getAuth()->getMaxAuthTries(); $retry_id_total++) {
            try {
                $this->logger->logger('Binding authorization keys...', \danog\MadelineProto\Logger::VERBOSE);
                $nonce = \danog\MadelineProto\Tools::random(8);
                $expires_at = \time() + $expires_in;
                $temp_auth_key_id = $datacenterConnection->getTempAuthKey()->getID();
                $perm_auth_key_id = $datacenterConnection->getPermAuthKey()->getID();
                $temp_session_id = $connection->session_id;
                $message_data = (yield from $this->TL->serializeObject(['type' => ''], ['_' => 'bind_auth_key_inner', 'nonce' => $nonce, 'temp_auth_key_id' => $temp_auth_key_id, 'perm_auth_key_id' => $perm_auth_key_id, 'temp_session_id' => $temp_session_id, 'expires_at' => $expires_at], 'bindTempAuthKey_inner'));
                $message_id = $connection->msgIdHandler->generateMessageId();
                $seq_no = 0;
                $encrypted_data = \danog\MadelineProto\Tools::random(16) . $message_id . \pack('VV', $seq_no, \strlen($message_data)) . $message_data;
                $message_key = \Phabel\Target\Php80\Polyfill::substr(\sha1($encrypted_data, true), -16);
                $padding = \danog\MadelineProto\Tools::random(\danog\MadelineProto\Tools::posmod(-\strlen($encrypted_data), 16));
                list($aes_key, $aes_iv) = Crypt::oldAesCalculate($message_key, $datacenterConnection->getPermAuthKey()->getAuthKey());
                $encrypted_message = $datacenterConnection->getPermAuthKey()->getID() . $message_key . Crypt::igeEncrypt($encrypted_data . $padding, $aes_key, $aes_iv);
                $res = (yield from $connection->methodCallAsyncRead('auth.bindTempAuthKey', ['perm_auth_key_id' => $perm_auth_key_id, 'nonce' => $nonce, 'expires_at' => $expires_at, 'encrypted_message' => $encrypted_message], ['msg_id' => $message_id]));
                if ($res === true) {
                    $this->logger->logger('Bound temporary and permanent authorization keys, DC ' . $datacenter, \danog\MadelineProto\Logger::NOTICE);
                    $datacenterConnection->bind();
                    $datacenterConnection->flush();
                    return true;
                }
            } catch (\danog\MadelineProto\SecurityException $e) {
                $this->logger->logger('An exception occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
            } catch (\danog\MadelineProto\Exception $e) {
                $this->logger->logger('An exception occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
            } catch (\danog\MadelineProto\RPCErrorException $e) {
                $this->logger->logger('An RPCErrorException occurred while generating the authorization key: ' . $e->getMessage() . ' Retrying (try number ' . $retry_id_total . ')...', \danog\MadelineProto\Logger::WARNING);
            }
        }
        throw new \danog\MadelineProto\SecurityException('An error occurred while binding temporary and permanent authorization keys.');
    }
    /**
     * Factorize number asynchronously using the wolfram API.
     *
     * @param (string | integer) $what Number to factorize
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, \Amp\Promise<string>, mixed, (false | int | string)>
     */
    private function wolframSingle($what) : \Generator
    {
        $code = (yield from $this->datacenter->fileGetContents('http://www.wolframalpha.com/api/v1/code'));
        $query = 'Do prime factorization of ' . $what;
        $params = ['async' => true, 'banners' => 'raw', 'debuggingdata' => false, 'format' => 'moutput', 'formattimeout' => 8, 'input' => $query, 'output' => 'JSON', 'proxycode' => \json_decode($code, true)['code']];
        $url = 'https://www.wolframalpha.com/input/json.jsp?' . \http_build_query($params);
        $request = new Request($url);
        $request->setHeader('referer', 'https://www.wolframalpha.com/input/?i=' . \urlencode($query));
        $res = \json_decode((yield ((yield $this->datacenter->getHTTPClient()->request($request)))->getBody()->buffer()), true);
        if (!isset($res['queryresult']['pods'])) {
            return false;
        }
        $fres = false;
        foreach ($res['queryresult']['pods'] as $cur) {
            if ($cur['id'] === 'Divisors') {
                $fres = \explode(', ', \preg_replace(["/{\\d+, /", "/, \\d+}\$/"], '', $cur['subpods'][0]['moutput']));
                break;
            }
        }
        if (\is_array($fres)) {
            $fres = $fres[0];
            $newval = \intval($fres);
            if (\is_int($newval)) {
                $fres = $newval;
            }
            return $fres;
        }
        return false;
    }
    /**
     * Asynchronously create, bind and check auth keys for all DCs.
     *
     * @internal
     *
     * @return \Generator
     */
    public function initAuthorization() : \Generator
    {
        if ($this->pending_auth) {
            $this->logger("Pending auth, not initing auth");
            return;
        }
        $this->logger("Initing authorization...");
        $initing = $this->initing_authorization;
        $this->initing_authorization = true;
        try {
            $dcs = [];
            $postpone = [];
            foreach ($this->datacenter->getDataCenterConnections() as $id => $socket) {
                if (!$socket->hasCtx()) {
                    continue;
                }
                if ($socket->isMedia()) {
                    $oid = \intval($id);
                    if (isset($dcs[$oid])) {
                        $postpone[$id] = $socket;
                    }
                    continue;
                }
                yield from $socket->waitGetConnection();
                if (isset($this->init_auth_dcs[$id])) {
                    $this->pending_auth = true;
                    continue;
                }
                $dcs[$id] = function () use($id, $socket) : \Generator {
                    return $this->initAuthorizationSocket($id, $socket);
                };
            }
            if ($dcs) {
                $first = \array_shift($dcs)();
                yield from $first;
            }
            foreach ($dcs as $id => &$dc) {
                $dc = $dc();
            }
            /** @var \Generator[] $dcs */
            (yield \danog\MadelineProto\Tools::all($dcs));
            foreach ($postpone as $id => $socket) {
                yield from $this->initAuthorizationSocket($id, $socket);
            }
            if ($this->pending_auth && empty($this->init_auth_dcs)) {
                $this->pending_auth = false;
                yield from $this->initAuthorization();
            }
        } finally {
            $this->pending_auth = false;
            $this->initing_authorization = $initing;
        }
    }
    /**
     * Init auth keys for single DC.
     *
     * @param string $id DC ID
     * @param DataCenterConnection $socket DC object
     *
     * @internal
     *
     * @return \Generator
     */
    public function initAuthorizationSocket(string $id, DataCenterConnection $socket) : \Generator
    {
        $this->logger("Initing authorization DC {$id}...");
        $this->init_auth_dcs[$id] = true;
        $connection = $socket->getAuthConnection();
        try {
            $socket->createSession();
            $cdn = $socket->isCDN();
            $media = $socket->isMedia();
            if (!$socket->hasTempAuthKey() || !$socket->hasPermAuthKey() || !$socket->isBound()) {
                if (!$socket->hasPermAuthKey() && !$cdn && !$media) {
                    $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['gen_perm_auth_key'], $id), \danog\MadelineProto\Logger::NOTICE);
                    $socket->setPermAuthKey(yield from $this->createAuthKey(-1, $id));
                    //$socket->authorized(false);
                }
                if ($media) {
                    $socket->link(\intval($id));
                    if ($socket->hasTempAuthKey()) {
                        return;
                    }
                }
                if ($this->getSettings()->getAuth()->getPfs()) {
                    if (!$cdn) {
                        $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['gen_temp_auth_key'], $id), \danog\MadelineProto\Logger::NOTICE);
                        //$authorized = $socket->authorized;
                        //$socket->authorized = false;
                        $socket->setTempAuthKey(null);
                        $socket->setTempAuthKey(yield from $this->createAuthKey($this->settings->getAuth()->getDefaultTempAuthKeyExpiresIn(), $id));
                        yield from $this->bindTempAuthKey($this->settings->getAuth()->getDefaultTempAuthKeyExpiresIn(), $id);
                        $this->config = (yield from $connection->methodCallAsyncRead('help.getConfig', []));
                        yield from $this->syncAuthorization($id);
                    } elseif (!$socket->hasTempAuthKey()) {
                        $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['gen_temp_auth_key'], $id), \danog\MadelineProto\Logger::NOTICE);
                        $socket->setTempAuthKey(yield from $this->createAuthKey($this->settings->getAuth()->getDefaultTempAuthKeyExpiresIn(), $id));
                    }
                } else {
                    if (!$cdn) {
                        $socket->bind(false);
                        $this->config = (yield from $connection->methodCallAsyncRead('help.getConfig', []));
                        yield from $this->syncAuthorization($id);
                    } elseif (!$socket->hasTempAuthKey()) {
                        $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['gen_temp_auth_key'], $id), \danog\MadelineProto\Logger::NOTICE);
                        $socket->setTempAuthKey(yield from $this->createAuthKey($this->settings->getAuth()->getDefaultTempAuthKeyExpiresIn(), $id));
                    }
                }
            } elseif (!$cdn) {
                yield from $this->syncAuthorization($id);
            }
        } finally {
            $this->logger("Done initing authorization DC {$id}");
            unset($this->init_auth_dcs[$id]);
        }
    }
    /**
     * Sync authorization data between DCs.
     *
     * @param string $id DC ID
     *
     * @internal
     *
     * @return \Generator
     */
    public function syncAuthorization(string $id) : \Generator
    {
        if (!$this->datacenter->has($id)) {
            return false;
        }
        $socket = $this->datacenter->getDataCenterConnection($id);
        if ($this->authorized === MTProto::LOGGED_IN && !$socket->isAuthorized()) {
            foreach ($this->datacenter->getDataCenterConnections() as $authorized_dc_id => $authorized_socket) {
                if ($this->authorized_dc !== -1 && $authorized_dc_id !== $this->authorized_dc) {
                    continue;
                }
                if ($authorized_socket->hasTempAuthKey() && $authorized_socket->hasPermAuthKey() && $authorized_socket->isAuthorized() && $this->authorized === MTProto::LOGGED_IN && !$socket->isAuthorized() && !$authorized_socket->isCDN()) {
                    try {
                        $this->logger->logger('Trying to copy authorization from DC ' . $authorized_dc_id . ' to DC ' . $id);
                        $exported_authorization = (yield from $this->methodCallAsyncRead('auth.exportAuthorization', ['dc_id' => \preg_replace('|_.*|', '', $id)], ['datacenter' => $authorized_dc_id]));
                        $authorization = (yield from $this->methodCallAsyncRead('auth.importAuthorization', $exported_authorization, ['datacenter' => $id]));
                        $socket->authorized(true);
                        break;
                    } catch (\danog\MadelineProto\Exception $e) {
                        $this->logger->logger('Failure while syncing authorization from DC ' . $authorized_dc_id . ' to DC ' . $id . ': ' . $e->getMessage(), \danog\MadelineProto\Logger::ERROR);
                    } catch (\danog\MadelineProto\RPCErrorException $e) {
                        $this->logger->logger('Failure while syncing authorization from DC ' . $authorized_dc_id . ' to DC ' . $id . ': ' . $e->getMessage(), \danog\MadelineProto\Logger::ERROR);
                        if ($e->rpc === 'DC_ID_INVALID') {
                            break;
                        }
                    }
                    // Turns out this DC isn't authorized after all
                }
            }
        }
    }
}<?php

/**
 * Response information module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use Amp\Http\Status;
/**
 * Obtain response information for file to server.
 */
class ResponseInfo
{
    private const POWERED_BY = "<p><small>Powered by <a href='https://docs.madelineproto.xyz'>MadelineProto</a></small></p>";
    private const NO_CACHE = ['Cache-Control' => ['no-store, no-cache, must-revalidate, max-age=0', 'post-check=0, pre-check=0'], 'Pragma' => 'no-cache'];
    /**
     * Whether to serve file.
     */
    private bool $serve = false;
    /**
     * Serving range.
     */
    private array $serveRange = [];
    /**
     * HTTP response code.
     */
    private int $code = Status::OK;
    /**
     * Header array.
     */
    private array $headers = [];
    /**
     * Parse headers.
     *
     * @param string $method HTTP method
     * @param array $headers HTTP headers
     * @param array $messageMedia Media info
     */
    private function __construct(string $method, array $headers, array $messageMedia)
    {
        if (isset($headers['range'])) {
            $range = \explode('=', $headers['range'], 2);
            if (\count($range) == 1) {
                $range[1] = '';
            }
            [$size_unit, $range_orig] = $range;
            if ($size_unit == 'bytes') {
                //multiple ranges could be specified at the same time, but for simplicity only serve the first range
                //http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
                $list = \explode(',', $range_orig, 2);
                if (\count($list) == 1) {
                    $list[1] = '';
                }
                [$range, $extra_ranges] = $list;
            } else {
                $this->serve = false;
                $this->code = Status::RANGE_NOT_SATISFIABLE;
                $this->headers = self::NO_CACHE;
                return;
            }
        } else {
            $range = '';
        }
        $listseek = \explode('-', $range, 2);
        if (\count($listseek) == 1) {
            $listseek[1] = '';
        }
        [$seek_start, $seek_end] = $listseek;
        $size = $messageMedia['size'] ?? 0;
        $seek_end = empty($seek_end) ? $size - 1 : \min(\abs(\intval($seek_end)), $size - 1);
        if (!empty($seek_start) && $seek_end < \abs(\intval($seek_start))) {
            $this->serve = false;
            $this->code = Status::RANGE_NOT_SATISFIABLE;
            $this->headers = self::NO_CACHE;
            return;
        }
        $seek_start = empty($seek_start) ? 0 : \abs(\intval($seek_start));
        $this->serve = $method !== 'HEAD';
        if ($seek_start > 0 || $seek_end < $size - 1) {
            $this->code = Status::PARTIAL_CONTENT;
            $this->headers['Content-Range'] = "bytes {$seek_start}-{$seek_end}/{$size}";
            $this->headers['Content-Length'] = $seek_end - $seek_start + 1;
        } elseif ($size > 0) {
            $this->headers['Content-Length'] = $size;
        }
        $this->headers['Content-Type'] = $messageMedia['mime'];
        $this->headers['Cache-Control'] = 'max-age=31556926';
        $this->headers['Content-Transfer-Encoding'] = 'Binary';
        $this->headers['Accept-Ranges'] = 'bytes';
        if ($this->serve) {
            if ($seek_start === 0 && $seek_end === -1) {
                $this->serveRange = [0, -1];
            } else {
                $this->serveRange = [$seek_start, $seek_end + 1];
            }
        }
    }
    /**
     * Parse headers.
     *
     * @param string $method HTTP method
     * @param array $headers HTTP headers
     * @param array $messageMedia Media info
     *
     * @return self
     */
    public static function parseHeaders(string $method, array $headers, array $messageMedia) : self
    {
        return new self($method, $headers, $messageMedia);
    }
    /**
     * Get explanation for HTTP code.
     *
     * @return string
     */
    public function getCodeExplanation() : string
    {
        $reason = Status::getReason($this->code);
        $body = "<html><body><h1>{$this->code} {$reason}</h1><br>";
        if ($this->code === Status::RANGE_NOT_SATISFIABLE) {
            $body .= "<p>Could not use selected range.</p>";
        }
        $body .= self::POWERED_BY;
        $body .= "</body></html>";
        return $body;
    }
    /**
     * Whether to serve file.
     *
     * @return bool Whether to serve file
     */
    public function shouldServe() : bool
    {
        return $this->serve;
    }
    /**
     * Get serving range.
     *
     * @return array HTTP serving range
     */
    public function getServeRange() : array
    {
        return $this->serveRange;
    }
    /**
     * Get HTTP response code.
     *
     * @return int HTTP response code
     */
    public function getCode() : int
    {
        return $this->code;
    }
    /**
     * Get header array.
     *
     * @return array Header array
     */
    public function getHeaders() : array
    {
        return $this->headers;
    }
}<?php

/**
 * Files module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use Amp\Loop;
use danog\MadelineProto\Db\DbArray;
use danog\MadelineProto\Db\DbPropertiesTrait;
use danog\MadelineProto\Exception;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProto\OutgoingMessage;
use danog\MadelineProto\TL\TLCallback;
/**
 * Manages upload and download of files.
 */
class ReferenceDatabase implements TLCallback
{
    use DbPropertiesTrait;
    // Reference from a document
    const DOCUMENT_LOCATION = 0;
    // Reference from a photo
    const PHOTO_LOCATION = 1;
    // Reference from a photo location (can only be photo location)
    const PHOTO_LOCATION_LOCATION = 2;
    // Peer + photo ID
    const USER_PHOTO_ORIGIN = 0;
    // Peer (default photo ID)
    const PEER_PHOTO_ORIGIN = 1;
    // set ID
    const STICKER_SET_ID_ORIGIN = 2;
    // Peer + msg ID
    const MESSAGE_ORIGIN = 3;
    //
    const SAVED_GIFS_ORIGIN = 4;
    //
    const STICKER_SET_RECENT_ORIGIN = 5;
    //
    const STICKER_SET_FAVED_ORIGIN = 6;
    // emoticon
    const STICKER_SET_EMOTICON_ORIGIN = 8;
    //
    const WALLPAPER_ORIGIN = 9;
    const LOCATION_CONTEXT = [
        //'inputFileLocation'         => self::PHOTO_LOCATION_LOCATION, // DEPRECATED
        'inputDocumentFileLocation' => self::DOCUMENT_LOCATION,
        'inputPhotoFileLocation' => self::PHOTO_LOCATION,
        'inputPhoto' => self::PHOTO_LOCATION,
        'inputDocument' => self::DOCUMENT_LOCATION,
    ];
    const METHOD_CONTEXT = ['photos.updateProfilePhoto' => self::USER_PHOTO_ORIGIN, 'photos.getUserPhotos' => self::USER_PHOTO_ORIGIN, 'photos.uploadProfilePhoto' => self::USER_PHOTO_ORIGIN, 'messages.getStickers' => self::STICKER_SET_EMOTICON_ORIGIN];
    const CONSTRUCTOR_CONTEXT = ['message' => self::MESSAGE_ORIGIN, 'messageService' => self::MESSAGE_ORIGIN, 'chatFull' => self::PEER_PHOTO_ORIGIN, 'channelFull' => self::PEER_PHOTO_ORIGIN, 'chat' => self::PEER_PHOTO_ORIGIN, 'channel' => self::PEER_PHOTO_ORIGIN, 'updateUserPhoto' => self::USER_PHOTO_ORIGIN, 'user' => self::USER_PHOTO_ORIGIN, 'userFull' => self::USER_PHOTO_ORIGIN, 'wallPaper' => self::WALLPAPER_ORIGIN, 'messages.savedGifs' => self::SAVED_GIFS_ORIGIN, 'messages.recentStickers' => self::STICKER_SET_RECENT_ORIGIN, 'messages.favedStickers' => self::STICKER_SET_FAVED_ORIGIN, 'messages.stickerSet' => self::STICKER_SET_ID_ORIGIN, 'document' => self::STICKER_SET_ID_ORIGIN];
    /**
     * References indexed by location.
     *
     * @var DbArray
     */
    private $db;
    private $cache = [];
    private $cacheContexts = [];
    private $refreshed = [];
    private $API;
    private $refresh = false;
    private $refreshCount = 0;
    /**
     * List of properties stored in database (memory or external).
     * @see DbPropertiesFactory
     * @var array
     */
    protected static array $dbProperties = ['db' => 'array'];
    /**
     *
     */
    public function __construct(MTProto $API)
    {
        $this->API = $API;
    }
    /**
     *
     */
    public function __sleep()
    {
        return ['db', 'API'];
    }
    /**
     *
     */
    public function init() : \Generator
    {
        yield from $this->initDb($this->API);
        //Clear table on each start to fix fatals with invalid references
        Loop::defer(fn() => ((yield $this->db->clear())));
        //Clear table every day
        Loop::repeat(24 * 1000 * 3600, fn() => ((yield $this->db->clear())));
    }
    /**
     *
     */
    public function getMethodCallbacks() : array
    {
        return \array_fill_keys(\array_keys(self::METHOD_CONTEXT), [[$this, 'addOriginMethod']]);
    }
    /**
     *
     */
    public function getMethodBeforeCallbacks() : array
    {
        return \array_fill_keys(\array_keys(self::METHOD_CONTEXT), [[$this, 'addOriginMethodContext']]);
    }
    /**
     *
     */
    public function getConstructorCallbacks() : array
    {
        return \array_merge(\array_fill_keys(['document', 'photo', 'fileLocation'], [[$this, 'addReference']]), \array_fill_keys(\array_keys(self::CONSTRUCTOR_CONTEXT), [[$this, 'addOrigin']]), ['document' => [[$this, 'addReference'], [$this, 'addOrigin']]]);
    }
    /**
     *
     */
    public function getConstructorBeforeCallbacks() : array
    {
        return \array_fill_keys(\array_keys(self::CONSTRUCTOR_CONTEXT), [[$this, 'addOriginContext']]);
    }
    /**
     *
     */
    public function getConstructorSerializeCallbacks() : array
    {
        return \array_fill_keys(\array_keys(self::LOCATION_CONTEXT), [$this, 'populateReference']);
    }
    /**
     *
     */
    public function getTypeMismatchCallbacks() : array
    {
        return [];
    }
    /**
     *
     */
    public function reset() : void
    {
        if ($this->cacheContexts) {
            $this->API->logger->logger('Found ' . \count($this->cacheContexts) . ' pending contexts', \danog\MadelineProto\Logger::ERROR);
            $this->cacheContexts = [];
        }
        if ($this->cache) {
            $this->API->logger->logger('Found pending locations', \danog\MadelineProto\Logger::ERROR);
            $this->cache = [];
        }
    }
    /**
     *
     */
    public function addReference(array $location) : bool
    {
        if (!$this->cacheContexts) {
            $this->API->logger->logger('Trying to add reference out of context, report the following message to @danogentili!', \danog\MadelineProto\Logger::ERROR);
            $frames = [];
            $previous = '';
            foreach (\debug_backtrace(0) as $k => $frame) {
                if (isset($frame['function']) && $frame['function'] === 'deserialize') {
                    if (isset($frame['args'][1]['subtype'])) {
                        if ($frame['args'][1]['subtype'] === $previous) {
                            continue;
                        }
                        $frames[] = $frame['args'][1]['subtype'];
                        $previous = $frame['args'][1]['subtype'];
                    } elseif (isset($frame['args'][1]['type'])) {
                        if ($frame['args'][1]['type'] === '') {
                            break;
                        }
                        if ($frame['args'][1]['type'] === $previous) {
                            continue;
                        }
                        $frames[] = $frame['args'][1]['type'];
                        $previous = $frame['args'][1]['type'];
                    }
                }
            }
            $frames = \array_reverse($frames);
            $tlTrace = \array_shift($frames);
            foreach ($frames as $frame) {
                $tlTrace .= "['" . $frame . "']";
            }
            $this->API->logger->logger($tlTrace, \danog\MadelineProto\Logger::ERROR);
            return false;
        }
        if (!isset($location['file_reference'])) {
            $this->API->logger->logger("Object {$location['_']} does not have reference", \danog\MadelineProto\Logger::ERROR);
            return false;
        }
        $key = \count($this->cacheContexts) - 1;
        switch ($location['_']) {
            case 'document':
                $locationType = self::DOCUMENT_LOCATION;
                break;
            case 'photo':
                $locationType = self::PHOTO_LOCATION;
                break;
            case 'fileLocation':
                $locationType = self::PHOTO_LOCATION_LOCATION;
                break;
            default:
                throw new Exception('Unknown location type provided: ' . $location['_']);
        }
        $this->API->logger->logger("Caching reference from location of type {$locationType} from {$location['_']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
        if (!isset($this->cache[$key])) {
            $this->cache[$key] = [];
        }
        $this->cache[$key][self::serializeLocation($locationType, $location)] = (string) $location['file_reference'];
        return true;
    }
    /**
     *
     */
    public function addOriginContext(string $type) : void
    {
        if (!isset(self::CONSTRUCTOR_CONTEXT[$type])) {
            throw new \danog\MadelineProto\Exception("Unknown origin type provided: {$type}");
        }
        $originContext = self::CONSTRUCTOR_CONTEXT[$type];
        //$this->API->logger->logger("Adding origin context {$originContext} for {$type}!", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
        $this->cacheContexts[] = $originContext;
    }
    /**
     *
     */
    public function addOrigin(array $data = []) : \Generator
    {
        $key = \count($this->cacheContexts) - 1;
        if ($key === -1) {
            throw new \danog\MadelineProto\Exception('Trying to add origin with no origin context set');
        }
        $originType = \array_pop($this->cacheContexts);
        if (!isset($this->cache[$key])) {
            //$this->API->logger->logger("Removing origin context {$originType} for {$data['_']}, nothing in the reference cache!", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
            return;
        }
        $cache = $this->cache[$key];
        unset($this->cache[$key]);
        $origin = [];
        switch ($data['_']) {
            case 'message':
            case 'messageService':
                $origin['peer'] = $this->API->getId($data);
                $origin['msg_id'] = $data['id'];
                break;
            case 'messages.savedGifs':
            case 'messages.recentStickers':
            case 'messages.favedStickers':
            case 'wallPaper':
                break;
            case 'user':
                $origin['max_id'] = $data['photo']['photo_id'];
                $origin['offset'] = -1;
                $origin['limit'] = 1;
                $origin['user_id'] = $data['id'];
                break;
            case 'updateUserPhoto':
                $origin['max_id'] = $data['photo']['photo_id'];
                $origin['offset'] = -1;
                $origin['limit'] = 1;
                $origin['user_id'] = $data['user_id'];
                break;
            case 'userFull':
                $origin['max_id'] = $data['profile_photo']['id'];
                $origin['offset'] = -1;
                $origin['limit'] = 1;
                $origin['user_id'] = $data['id'];
                break;
            case 'chatFull':
            case 'chat':
                $origin['peer'] = -$data['id'];
                break;
            case 'channelFull':
            case 'channel':
                $origin['peer'] = $this->API::toSupergroup($data['id']);
                break;
            case 'document':
                foreach ($data['attributes'] as $attribute) {
                    if ($attribute['_'] === 'documentAttributeSticker' && $attribute['stickerset']['_'] !== 'inputStickerSetEmpty') {
                        $origin['stickerset'] = $attribute['stickerset'];
                    }
                }
                if (!isset($origin['stickerset'])) {
                    $key = \count($this->cacheContexts) - 1;
                    if (!isset($this->cache[$key])) {
                        $this->cache[$key] = [];
                    }
                    foreach ($cache as $location => $reference) {
                        $this->cache[$key][$location] = $reference;
                    }
                    $this->API->logger->logger("Skipped origin {$originType} ({$data['_']}) for " . \count($cache) . ' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    return;
                }
                break;
            case 'messages.stickerSet':
                $origin['stickerset'] = ['_' => 'inputStickerSetID', 'id' => $data['set']['id'], 'access_hash' => $data['set']['access_hash']];
                break;
            default:
                throw new \danog\MadelineProto\Exception("Unknown origin type provided: {$data['_']}");
        }
        foreach ($cache as $location => $reference) {
            yield from $this->storeReference($location, $reference, $originType, $origin);
        }
        $this->API->logger->logger("Added origin {$originType} ({$data['_']}) to " . \count($cache) . ' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
    }
    /**
     *
     */
    public function addOriginMethodContext(string $type) : void
    {
        if (!isset(self::METHOD_CONTEXT[$type])) {
            throw new \danog\MadelineProto\Exception("Unknown origin type provided: {$type}");
        }
        $originContext = self::METHOD_CONTEXT[$type];
        $this->API->logger->logger("Adding origin context {$originContext} for {$type}!", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
        $this->cacheContexts[] = $originContext;
    }
    /**
     *
     */
    public function addOriginMethod(OutgoingMessage $data, array $res) : \Generator
    {
        $key = \count($this->cacheContexts) - 1;
        if ($key === -1) {
            throw new \danog\MadelineProto\Exception('Trying to add origin with no origin context set');
        }
        $constructor = $data->getConstructor();
        $originType = \array_pop($this->cacheContexts);
        if (!isset($this->cache[$key])) {
            $this->API->logger->logger("Removing origin context {$originType} for {$constructor}, nothing in the reference cache!", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
            return;
        }
        $cache = $this->cache[$key];
        unset($this->cache[$key]);
        $origin = [];
        $body = $data->getBodyOrEmpty();
        switch ($body ?? '') {
            case 'photos.updateProfilePhoto':
                $origin['max_id'] = $res['photo_id'] ?? 0;
                $origin['offset'] = -1;
                $origin['limit'] = 1;
                $origin['user_id'] = $this->API->authorization['user']['id'];
                break;
            case 'photos.uploadProfilePhoto':
                $origin['max_id'] = $res['photo']['id'];
                $origin['offset'] = -1;
                $origin['limit'] = 1;
                $origin['user_id'] = $this->API->authorization['user']['id'];
                break;
            case 'photos.getUserPhotos':
                $origin['user_id'] = $body['user_id'];
                $origin['offset'] = -1;
                $origin['limit'] = 1;
                $count = 0;
                foreach ($res['photos'] as $photo) {
                    $origin['max_id'] = $photo['id'];
                    $dc_id = $photo['dc_id'];
                    $location = self::serializeLocation(self::PHOTO_LOCATION, $photo);
                    if (isset($cache[$location])) {
                        $reference = $cache[$location];
                        unset($cache[$location]);
                        yield from $this->storeReference($location, $reference, $originType, $origin);
                        $count++;
                    }
                    if (isset($photo['sizes'])) {
                        foreach ($photo['sizes'] as $size) {
                            if (isset($size['location'])) {
                                $size['location']['dc_id'] = $dc_id;
                                $location = self::serializeLocation(self::PHOTO_LOCATION_LOCATION, $size['location']);
                                if (isset($cache[$location])) {
                                    $reference = $cache[$location];
                                    unset($cache[$location]);
                                    yield from $this->storeReference($location, $reference, $originType, $origin);
                                    $count++;
                                }
                            }
                        }
                    }
                }
                $this->API->logger->logger("Added origin {$originType} ({$constructor}) to {$count} references", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                return;
            case 'messages.getStickers':
                $origin['emoticon'] = $body['emoticon'];
                break;
            default:
                throw new \danog\MadelineProto\Exception("Unknown origin type provided: {$constructor}");
        }
        foreach ($cache as $location => $reference) {
            yield from $this->storeReference($location, $reference, $originType, $origin);
        }
        $this->API->logger->logger("Added origin {$originType} ({$constructor}) to " . \count($cache) . ' references', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
    }
    /**
     *
     */
    public function storeReference(string $location, string $reference, int $originType, array $origin) : \Generator
    {
        $locationValue = (yield $this->db[$location]);
        if (!$locationValue) {
            $locationValue = ['origins' => []];
        }
        $locationValue['reference'] = $reference;
        $locationValue['origins'][$originType] = $origin;
        $this->db[$location] = $locationValue;
        if ($this->refresh) {
            $this->refreshed[$location] = true;
        }
        $key = \count($this->cacheContexts) - 1;
        if ($key >= 0) {
            $this->cache[$key][$location] = $reference;
        }
    }
    /**
     *
     */
    public function refreshNext(bool $refresh = false) : void
    {
        if ($this->refreshCount === 1 && !$refresh) {
            $this->refreshed = [];
            $this->refreshCount--;
            $this->refresh = false;
        } elseif ($this->refreshCount === 0 && $refresh) {
            $this->refreshed = [];
            $this->refreshCount++;
            $this->refresh = true;
        } elseif ($this->refreshCount === 0 && !$refresh) {
        } elseif ($refresh) {
            $this->refreshCount++;
        } elseif (!$refresh) {
            $this->refreshCount--;
        }
    }
    /**
     *
     */
    public function refreshReference(int $locationType, array $location) : \Generator
    {
        return $this->refreshReferenceInternal(self::serializeLocation($locationType, $location));
    }
    /**
     *
     */
    public function refreshReferenceInternal(string $location) : \Generator
    {
        if (isset($this->refreshed[$location])) {
            $this->API->logger->logger('Reference already refreshed!', \danog\MadelineProto\Logger::VERBOSE);
            return ((yield $this->db[$location]))['reference'];
        }
        $locationValue = (yield $this->db[$location]);
        \ksort($locationValue['origins']);
        $this->db[$location] = $locationValue;
        $count = 0;
        foreach (((yield $this->db[$location]))['origins'] as $originType => &$origin) {
            $count++;
            $this->API->logger->logger("Try {$count} refreshing file reference with origin type {$originType}", \danog\MadelineProto\Logger::VERBOSE);
            switch ($originType) {
                // Peer + msg ID
                case self::MESSAGE_ORIGIN:
                    if (\is_array($origin['peer'])) {
                        $origin['peer'] = $this->API->getId($origin['peer']);
                    }
                    if ($origin['peer'] < 0) {
                        yield from $this->API->methodCallAsyncRead('channels.getMessages', ['channel' => $origin['peer'], 'id' => [$origin['msg_id']]], $this->API->getSettings()->getDefaultDcParams());
                        break;
                    }
                    yield from $this->API->methodCallAsyncRead('messages.getMessages', ['id' => [$origin['msg_id']]], $this->API->getSettings()->getDefaultDcParams());
                    break;
                // Peer + photo ID
                case self::PEER_PHOTO_ORIGIN:
                    $fullChat = (yield $this->API->full_chats[$origin['peer']]);
                    if (isset($fullChat['last_update'])) {
                        $fullChat['last_update'] = 0;
                        $this->API->full_chats[$origin['peer']] = $fullChat;
                    }
                    $this->API->getFullInfo($origin['peer']);
                    break;
                // Peer (default photo ID)
                case self::USER_PHOTO_ORIGIN:
                    yield from $this->API->methodCallAsyncRead('photos.getUserPhotos', $origin, $this->API->getSettings()->getDefaultDcParams());
                    break;
                case self::SAVED_GIFS_ORIGIN:
                    yield from $this->API->methodCallAsyncRead('messages.getSavedGifs', $origin, $this->API->getSettings()->getDefaultDcParams());
                    break;
                case self::STICKER_SET_ID_ORIGIN:
                    yield from $this->API->methodCallAsyncRead('messages.getStickerSet', $origin, $this->API->getSettings()->getDefaultDcParams());
                    break;
                case self::STICKER_SET_RECENT_ORIGIN:
                    yield from $this->API->methodCallAsyncRead('messages.getRecentStickers', $origin, $this->API->getSettings()->getDefaultDcParams());
                    break;
                case self::STICKER_SET_FAVED_ORIGIN:
                    yield from $this->API->methodCallAsyncRead('messages.getFavedStickers', $origin, $this->API->getSettings()->getDefaultDcParams());
                    break;
                case self::STICKER_SET_EMOTICON_ORIGIN:
                    yield from $this->API->methodCallAsyncRead('messages.getStickers', $origin, $this->API->getSettings()->getDefaultDcParams());
                    break;
                case self::WALLPAPER_ORIGIN:
                    yield from $this->API->methodCallAsyncRead('account.getWallPapers', $origin, $this->API->getSettings()->getDefaultDcParams());
                    break;
                default:
                    throw new \danog\MadelineProto\Exception("Unknown origin type {$originType}");
            }
            if (isset($this->refreshed[$location])) {
                return ((yield $this->db[$location]))['reference'];
            }
        }
        throw new Exception('Did not refresh reference');
    }
    /**
     *
     */
    public function populateReference(array $object) : \Generator
    {
        $object['file_reference'] = (yield from $this->getReference(self::LOCATION_CONTEXT[$object['_']], $object));
        return $object;
    }
    /**
     *
     */
    public function getReference(int $locationType, array $location) : \Generator
    {
        $locationString = self::serializeLocation($locationType, $location);
        if (!isset(((yield $this->db[$locationString]))['reference'])) {
            if (isset($location['file_reference'])) {
                $this->API->logger->logger("Using outdated file reference for location of type {$locationType} object {$location['_']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                return $location['file_reference'];
            }
            if (!$this->refresh) {
                $this->API->logger->logger("Using null file reference for location of type {$locationType} object {$location['_']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                return '';
            }
            throw new \danog\MadelineProto\Exception("Could not find file reference for location of type {$locationType} object {$location['_']}");
        }
        $this->API->logger->logger("Getting file reference for location of type {$locationType} object {$location['_']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
        if ($this->refresh) {
            return $this->refreshReferenceInternal($locationString);
        }
        return ((yield $this->db[$locationString]))['reference'];
    }
    /**
     *
     */
    private static function serializeLocation(int $locationType, array $location) : string
    {
        switch ($locationType) {
            case self::DOCUMENT_LOCATION:
            case self::PHOTO_LOCATION:
                return $locationType . (\is_int($location['id']) ? \danog\MadelineProto\Tools::packSignedLong($location['id']) : $location['id']);
            case self::PHOTO_LOCATION_LOCATION:
                $dc_id = \danog\MadelineProto\Tools::packSignedInt($location['dc_id']);
                $volume_id = \is_int($location['volume_id']) ? \danog\MadelineProto\Tools::packSignedLong($location['volume_id']) : $location['volume_id'];
                $local_id = \danog\MadelineProto\Tools::packSignedInt($location['local_id']);
                return $locationType . $dc_id . $volume_id . $local_id;
        }
        throw new \danog\MadelineProto\Exception("Invalid location type specified!");
    }
    /**
     *
     */
    public function __debugInfo()
    {
        return ['ReferenceDatabase instance ' . \spl_object_hash($this)];
    }
}<?php

/**
 * Files module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use Amp\Promise;
use danog\MadelineProto\Db\DbArray;
use danog\MadelineProto\Db\DbPropertiesTrait;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\TL\TLCallback;
/**
 * Manages min peers.
 */
class MinDatabase implements TLCallback
{
    use DbPropertiesTrait;
    const SWITCH_CONSTRUCTORS = ['inputChannel', 'inputUser', 'inputPeerUser', 'inputPeerChannel'];
    const CATCH_PEERS = ['message', 'messageService', 'peerUser', 'peerChannel', 'messageEntityMentionName', 'messageFwdHeader', 'messageActionChatCreate', 'messageActionChatAddUser', 'messageActionChatDeleteUser', 'messageActionChatJoinedByLink'];
    const ORIGINS = ['message', 'messageService'];
    /**
     * References indexed by location.
     *
     * @var DbArray
     */
    private $db;
    /**
     * Temporary cache during deserialization.
     *
     * @var array
     */
    private $cache = [];
    /**
     * Instance of MTProto.
     *
     * @var \danog\MadelineProto\MTProto
     */
    private $API;
    /**
     * Whether we cleaned up old database information.
     *
     * @var boolean
     */
    private $clean = false;
    /**
     * List of properties stored in database (memory or external).
     * @see DbPropertiesFactory
     * @var array
     */
    protected static array $dbProperties = ['db' => 'array'];
    /**
     *
     */
    public function __construct(MTProto $API)
    {
        $this->API = $API;
    }
    /**
     *
     */
    public function __sleep()
    {
        return ['db', 'API', 'clean'];
    }
    /**
     *
     */
    public function init() : \Generator
    {
        yield from $this->initDb($this->API);
        if (!$this->API->getSettings()->getDb()->getEnableMinDb()) {
            (yield $this->db->clear());
        }
        if ($this->clean || 0 === (yield $this->db->count())) {
            $this->clean = true;
            return;
        }
        \Amp\Loop::defer(function () {
            $iterator = $this->db->getIterator();
            while ((yield $iterator->advance())) {
                [$id, $origin] = $iterator->getCurrent();
                if (!isset($origin['peer']) || $origin['peer'] === $id) {
                    $this->db->unset($id);
                }
            }
        });
    }
    /**
     *
     */
    public function getMethodCallbacks() : array
    {
        return [];
    }
    /**
     *
     */
    public function getMethodBeforeCallbacks() : array
    {
        return [];
    }
    /**
     *
     */
    public function getConstructorCallbacks() : array
    {
        return \array_merge(\array_fill_keys(self::CATCH_PEERS, [[$this, 'addPeer']]), \array_fill_keys(self::ORIGINS, [[$this, 'addOrigin']]));
    }
    /**
     *
     */
    public function getConstructorBeforeCallbacks() : array
    {
        return \array_fill_keys(self::ORIGINS, [[$this, 'addOriginContext']]);
    }
    /**
     *
     */
    public function getConstructorSerializeCallbacks() : array
    {
        return \array_fill_keys(self::SWITCH_CONSTRUCTORS, [$this, 'populateFrom']);
    }
    /**
     *
     */
    public function getTypeMismatchCallbacks() : array
    {
        return [];
    }
    /**
     *
     */
    public function reset() : void
    {
        if ($this->cache) {
            $this->API->logger->logger('Found ' . \count($this->cache) . ' pending contexts', \danog\MadelineProto\Logger::ERROR);
            $this->cache = [];
        }
    }
    /**
     *
     */
    public function addPeer(array $location) : bool
    {
        $peers = [];
        switch ($location['_']) {
            case 'messageFwdHeader':
                if (isset($location['from_id'])) {
                    $peers[$this->API->getId($location['from_id'])] = true;
                }
                if (isset($location['channel_id'])) {
                    $peers[$this->API->toSupergroup($location['channel_id'])] = true;
                }
                break;
            case 'messageActionChatCreate':
            case 'messageActionChatAddUser':
                foreach ($location['users'] as $user) {
                    $peers[$user] = true;
                }
                break;
            case 'message':
                $peers[$this->API->getId($location['peer_id'])] = true;
                if (isset($location['from_id'])) {
                    $peers[$this->API->getId($location['from_id'])] = true;
                }
                break;
            default:
                $peers[$this->API->getId($location)] = true;
        }
        $this->API->logger->logger("Caching peer location info from location from {$location['_']}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
        $key = \count($this->cache) - 1;
        foreach ($peers as $id => $true) {
            $this->cache[$key][$id] = $id;
        }
        return true;
    }
    /**
     *
     */
    public function addOriginContext(string $type) : void
    {
        $this->API->logger->logger("Adding peer origin context for {$type}!", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
        $this->cache[] = [];
    }
    /**
     *
     */
    public function addOrigin(array $data = []) : void
    {
        $cache = \array_pop($this->cache);
        if ($cache === null) {
            throw new \danog\MadelineProto\Exception('Trying to add origin with no origin context set');
        }
        $origin = [];
        switch ($data['_']) {
            case 'message':
            case 'messageService':
                $origin['peer'] = $this->API->getId($data);
                $origin['msg_id'] = $data['id'];
                break;
            default:
                throw new \danog\MadelineProto\Exception("Unknown origin type provided: {$data['_']}");
        }
        foreach ($cache as $id) {
            if ($origin['peer'] === $id) {
                continue;
            }
            $this->db[$id] = $origin;
        }
        $this->API->logger->logger("Added origin ({$data['_']}) to " . \count($cache) . ' peer locations', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
    }
    /**
     *
     */
    public function populateFrom(array $object) : \Generator
    {
        if (!($object['min'] ?? false)) {
            return $object;
        }
        $id = $this->API->getId($object);
        $dbObject = (yield $this->db[$id]);
        if ($dbObject) {
            $new = \array_merge($object, $dbObject);
            $new['_'] .= 'FromMessage';
            $new['peer'] = (yield from $this->API->getInputPeer($new['peer']));
            if ($new['peer']['min']) {
                $this->API->logger->logger("Don't have origin peer subinfo with min peer {$id}, this may fail");
                return $object;
            }
            return $new;
        }
        $this->API->logger->logger("Don't have origin info with min peer {$id}, this may fail");
        return $object;
    }
    /**
     * Check if location info is available for peer.
     *
     * @param (float | int) $id Peer ID
     *
     * @return Promise
     * @psalm-return Promise<bool>
     */
    public function hasPeer($id) : Promise
    {
        return $this->db->isset($id);
    }
    /**
     *
     */
    public function __debugInfo()
    {
        return ['MinDatabase instance ' . \spl_object_hash($this)];
    }
}<?php

/**
 * Crypt module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use danog\MadelineProto\Logger;
use danog\MadelineProto\Magic;
use danog\MadelineProto\MTProtoTools\Crypt\IGE;
use phpseclib3\Crypt\AES;
use phpseclib3\Math\BigInteger;
abstract class Crypt
{
    /**
     * AES KDF function for MTProto v2.
     *
     * @param string $msg_key Message key
     * @param string $auth_key Auth key
     * @param boolean $to_server To server/from server direction
     *
     * @internal
     *
     * @return array
     */
    public static function aesCalculate(string $msg_key, string $auth_key, bool $to_server = true) : array
    {
        $x = $to_server ? 0 : 8;
        $sha256_a = \hash('sha256', $msg_key . \Phabel\Target\Php80\Polyfill::substr($auth_key, $x, 36), true);
        $sha256_b = \hash('sha256', \Phabel\Target\Php80\Polyfill::substr($auth_key, 40 + $x, 36) . $msg_key, true);
        $aes_key = \Phabel\Target\Php80\Polyfill::substr($sha256_a, 0, 8) . \Phabel\Target\Php80\Polyfill::substr($sha256_b, 8, 16) . \Phabel\Target\Php80\Polyfill::substr($sha256_a, 24, 8);
        $aes_iv = \Phabel\Target\Php80\Polyfill::substr($sha256_b, 0, 8) . \Phabel\Target\Php80\Polyfill::substr($sha256_a, 8, 16) . \Phabel\Target\Php80\Polyfill::substr($sha256_b, 24, 8);
        return [$aes_key, $aes_iv];
    }
    /**
     * AES KDF function for MTProto v1.
     *
     * @param string $msg_key Message key
     * @param string $auth_key Auth key
     * @param boolean $to_server To server/from server direction
     *
     * @internal
     *
     * @return array
     */
    public static function oldAesCalculate(string $msg_key, string $auth_key, bool $to_server = true) : array
    {
        $x = $to_server ? 0 : 8;
        $sha1_a = \sha1($msg_key . \Phabel\Target\Php80\Polyfill::substr($auth_key, $x, 32), true);
        $sha1_b = \sha1(\Phabel\Target\Php80\Polyfill::substr($auth_key, 32 + $x, 16) . $msg_key . \Phabel\Target\Php80\Polyfill::substr($auth_key, 48 + $x, 16), true);
        $sha1_c = \sha1(\Phabel\Target\Php80\Polyfill::substr($auth_key, 64 + $x, 32) . $msg_key, true);
        $sha1_d = \sha1($msg_key . \Phabel\Target\Php80\Polyfill::substr($auth_key, 96 + $x, 32), true);
        $aes_key = \Phabel\Target\Php80\Polyfill::substr($sha1_a, 0, 8) . \Phabel\Target\Php80\Polyfill::substr($sha1_b, 8, 12) . \Phabel\Target\Php80\Polyfill::substr($sha1_c, 4, 12);
        $aes_iv = \Phabel\Target\Php80\Polyfill::substr($sha1_a, 8, 12) . \Phabel\Target\Php80\Polyfill::substr($sha1_b, 0, 8) . \Phabel\Target\Php80\Polyfill::substr($sha1_c, 16, 4) . \Phabel\Target\Php80\Polyfill::substr($sha1_d, 0, 8);
        return [$aes_key, $aes_iv];
    }
    /**
     * CTR encrypt.
     *
     * @param string $message Message to encrypt
     * @param string $key Key
     * @param string $iv IV
     *
     * @internal
     *
     * @return string
     */
    public static function ctrEncrypt(string $message, string $key, string $iv) : string
    {
        $cipher = new AES('ctr');
        $cipher->setKey($key);
        $cipher->setIV($iv);
        return @$cipher->encrypt($message);
    }
    /**
     * IGE encrypt.
     *
     * @param string $plaintext Message to encrypt
     * @param string $key Key
     * @param string $iv IV
     *
     * @internal
     *
     * @return string
     */
    public static function igeEncrypt(string $plaintext, string $key, string $iv) : string
    {
        if (Magic::$hasOpenssl) {
            $iv_part_1 = \Phabel\Target\Php80\Polyfill::substr($iv, 0, 16);
            $iv_part_2 = \Phabel\Target\Php80\Polyfill::substr($iv, 16);
            $ciphertext = "";
            for ($i = 0, $length = \strlen($plaintext); $i < $length; $i += 16) {
                $plain = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, 16);
                $cipher = \openssl_encrypt($plain ^ $iv_part_1, 'aes-256-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING) ^ $iv_part_2;
                $ciphertext .= $cipher;
                $iv_part_1 = $cipher;
                $iv_part_2 = $plain;
            }
            return $ciphertext;
        }
        return IGE::getInstance($key, $iv)->encrypt($plaintext);
    }
    /**
     * IGE decrypt.
     *
     * @param string $ciphertext Message to decrypt
     * @param string $key Key
     * @param string $iv IV
     *
     * @internal
     *
     * @return string
     */
    public static function igeDecrypt(string $ciphertext, string $key, string $iv) : string
    {
        if (Magic::$hasOpenssl) {
            $iv_part_1 = \Phabel\Target\Php80\Polyfill::substr($iv, 0, 16);
            $iv_part_2 = \Phabel\Target\Php80\Polyfill::substr($iv, 16);
            $plaintext = "";
            for ($i = 0, $length = \strlen($ciphertext); $i < $length; $i += 16) {
                $cipher = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, 16);
                $plain = \openssl_decrypt($cipher ^ $iv_part_2, 'aes-256-ecb', $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING) ^ $iv_part_1;
                $plaintext .= $plain;
                $iv_part_1 = $cipher;
                $iv_part_2 = $plain;
            }
            return $plaintext;
        }
        return IGE::getInstance($key, $iv)->decrypt($ciphertext);
    }
    /**
     * Check validity of g_a parameters.
     *
     * @param BigInteger $g_a
     * @param BigInteger $p
     *
     * @internal
     *
     * @return bool
     */
    public static function checkG(BigInteger $g_a, BigInteger $p) : bool
    {
        /*
         * ***********************************************************************
         * Check validity of g_a
         * 1 < g_a < p - 1
         */
        Logger::log('Executing g_a check (1/2)...', \danog\MadelineProto\Logger::VERBOSE);
        if ($g_a->compare(\danog\MadelineProto\Magic::$one) <= 0 || $g_a->compare($p->subtract(\danog\MadelineProto\Magic::$one)) >= 0) {
            throw new \danog\MadelineProto\SecurityException('g_a is invalid (1 < g_a < p - 1 is false).');
        }
        Logger::log('Executing g_a check (2/2)...', \danog\MadelineProto\Logger::VERBOSE);
        if ($g_a->compare(\danog\MadelineProto\Magic::$twoe1984) < 0 || $g_a->compare($p->subtract(\danog\MadelineProto\Magic::$twoe1984)) >= 0) {
            throw new \danog\MadelineProto\SecurityException('g_a is invalid (2^1984 < g_a < p - 2^1984 is false).');
        }
        return true;
    }
    /**
     * Check validity of p and g parameters.
     *
     * @param BigInteger $p
     * @param BigInteger $g
     *
     * @internal
     *
     * @return boolean
     */
    public static function checkPG(BigInteger $p, BigInteger $g) : bool
    {
        /*
         * ***********************************************************************
         * Check validity of dh_prime
         * Is it a prime?
         */
        Logger::log('Executing p/g checks (1/2)...', \danog\MadelineProto\Logger::VERBOSE);
        if (!$p->isPrime()) {
            throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime (p isn't a prime).");
        }
        /*
         * ***********************************************************************
         * Check validity of p
         * Is (p - 1) / 2 a prime?
         *
         * Almost always fails
         */
        /*
                $this->logger->logger('Executing p/g checks (2/3)...', \danog\MadelineProto\Logger::VERBOSE);
                if (!$p->subtract(\danog\MadelineProto\Magic::$one)->divide(\danog\MadelineProto\Magic::$two)[0]->isPrime()) {
                throw new \danog\MadelineProto\SecurityException("p isn't a safe 2048-bit prime ((p - 1) / 2 isn't a prime).");
                }
        */
        /*
         * ***********************************************************************
         * Check validity of p
         * 2^2047 < p < 2^2048
         */
        Logger::log('Executing p/g checks (2/2)...', \danog\MadelineProto\Logger::VERBOSE);
        if ($p->compare(\danog\MadelineProto\Magic::$twoe2047) <= 0 || $p->compare(\danog\MadelineProto\Magic::$twoe2048) >= 0) {
            throw new \danog\MadelineProto\SecurityException("g isn't a safe 2048-bit prime (2^2047 < p < 2^2048 is false).");
        }
        /*
         * ***********************************************************************
         * Check validity of g
         * 1 < g < p - 1
         */
        Logger::log('Executing g check...', \danog\MadelineProto\Logger::VERBOSE);
        if ($g->compare(\danog\MadelineProto\Magic::$one) <= 0 || $g->compare($p->subtract(\danog\MadelineProto\Magic::$one)) >= 0) {
            throw new \danog\MadelineProto\SecurityException('g is invalid (1 < g < p - 1 is false).');
        }
        return true;
    }
}<?php

/**
 * Password calculator module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use danog\MadelineProto\Exception;
use danog\MadelineProto\Magic;
use danog\MadelineProto\SecurityException;
use phpseclib3\Math\BigInteger;
/**
 * Manages SRP password calculation.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @link   https://docs.madelineproto.xyz MadelineProto documentation
 */
class PasswordCalculator
{
    /**
     * The algorithm to use for calculating the hash of new passwords (a PasswordKdfAlgo object).
     *
     * @var array
     */
    private $new_algo;
    /**
     * A secure random string that can be used to compute the password.
     *
     * @var string
     */
    private $secure_random = '';
    /**
     * The algorithm to use for calculatuing the hash of the current password (a PasswordKdfAlgo object).
     *
     * @var array
     */
    private $current_algo;
    /**
     * SRP b parameter.
     *
     * @var BigInteger
     */
    private $srp_B;
    /**
     * SRP b parameter for hashing.
     *
     * @var string
     */
    private $srp_BForHash;
    /**
     * SRP ID.
     *
     * @var [type]
     */
    private $srp_id;
    /**
     * Logger.
     *
     * @var \danog\MadelineProto\Logger
     */
    public $logger;
    /**
     * Initialize logger.
     *
     * @param \danog\MadelineProto\Logger $logger
     */
    public function __construct($logger)
    {
        $this->logger = $logger;
    }
    /**
     * Popupate 2FA configuration.
     *
     * @param array $object 2FA configuration object obtained using account.getPassword
     *
     * @return void
     */
    public function addInfo(array $object) : void
    {
        if ($object['_'] !== 'account.password') {
            throw new Exception('Wrong constructor');
        }
        if ($object['has_secure_values']) {
            //throw new Exception('Cannot parse secure values');
        }
        if ($object['has_password']) {
            switch ($object['current_algo']['_']) {
                case 'passwordKdfAlgoUnknown':
                    throw new Exception('Update your client to continue');
                case 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow':
                    $object['current_algo']['g'] = new BigInteger($object['current_algo']['g']);
                    $object['current_algo']['p'] = new BigInteger((string) $object['current_algo']['p'], 256);
                    Crypt::checkPG($object['current_algo']['p'], $object['current_algo']['g']);
                    $object['current_algo']['gForHash'] = \str_pad($object['current_algo']['g']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
                    $object['current_algo']['pForHash'] = \str_pad($object['current_algo']['p']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
                    break;
                default:
                    throw new Exception("Unknown KDF algo {$object['current_algo']['_']}");
            }
            $this->current_algo = $object['current_algo'];
            $object['srp_B'] = new BigInteger((string) $object['srp_B'], 256);
            if ($object['srp_B']->compare(\danog\MadelineProto\Magic::$zero) < 0) {
                throw new SecurityException('srp_B < 0');
            }
            if ($object['srp_B']->compare($object['current_algo']['p']) > 0) {
                throw new SecurityException('srp_B > p');
            }
            $this->srp_B = $object['srp_B'];
            $this->srp_BForHash = \str_pad($object['srp_B']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
            $this->srp_id = $object['srp_id'];
        } else {
            $this->current_algo = null;
            $this->srp_B = null;
            $this->srp_BForHash = null;
            $this->srp_id = null;
        }
        switch ($object['new_algo']['_']) {
            case 'passwordKdfAlgoUnknown':
                throw new Exception('Update your client to continue');
            case 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow':
                $object['new_algo']['g'] = new BigInteger($object['new_algo']['g']);
                $object['new_algo']['p'] = new BigInteger((string) $object['new_algo']['p'], 256);
                Crypt::checkPG($object['new_algo']['p'], $object['new_algo']['g']);
                $object['new_algo']['gForHash'] = \str_pad($object['new_algo']['g']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
                $object['new_algo']['pForHash'] = \str_pad($object['new_algo']['p']->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
                break;
            default:
                throw new Exception("Unknown KDF algo {$object['new_algo']['_']}");
        }
        $this->new_algo = $object['new_algo'];
        $this->secure_random = $object['secure_random'];
    }
    /**
     * Create a random string (eventually prefixed by the specified string).
     *
     * @param string $prefix Prefix
     * @return string Salt
     */
    public function createSalt(string $prefix = '') : string
    {
        return $prefix . \danog\MadelineProto\Tools::random(32);
    }
    /**
     * Hash specified data using the salt with SHA256.
     *
     * The result will be the SHA256 hash of the salt concatenated with the data concatenated with the salt
     *
     * @param string $data Data to hash
     * @param string $salt Salt
     * @return string Hash
     */
    public function hashSha256(string $data, string $salt) : string
    {
        return \hash('sha256', $salt . $data . $salt, true);
    }
    /**
     * Hashes the specified password.
     *
     * @param string $password Password
     * @param string $client_salt Client salt
     * @param string $server_salt Server salt
     * @return string Resulting hash
     */
    public function hashPassword(string $password, string $client_salt, string $server_salt) : string
    {
        $buf = $this->hashSha256($password, $client_salt);
        $buf = $this->hashSha256($buf, $server_salt);
        $hash = \hash_pbkdf2('sha512', $buf, $client_salt, 100000, 0, true);
        return $this->hashSha256($hash, $server_salt);
    }
    /**
     * Get the InputCheckPassword object for checking the validity of a password using account.checkPassword.
     *
     * @param string $password The password
     * @return array InputCheckPassword object
     */
    public function getCheckPassword(string $password) : array
    {
        if ($password === '' || !$this->current_algo) {
            return ['_' => 'inputCheckPasswordEmpty'];
        }
        $client_salt = $this->current_algo['salt1'];
        $server_salt = $this->current_algo['salt2'];
        $g = $this->current_algo['g'];
        $gForHash = $this->current_algo['gForHash'];
        $p = $this->current_algo['p'];
        $pForHash = $this->current_algo['pForHash'];
        $B = $this->srp_B;
        $BForHash = $this->srp_BForHash;
        $id = $this->srp_id;
        $x = new BigInteger($this->hashPassword($password, $client_salt, $server_salt), 256);
        $g_x = $g->powMod($x, $p);
        $k = new BigInteger(\hash('sha256', $pForHash . $gForHash, true), 256);
        $kg_x = $k->multiply($g_x)->powMod(Magic::$one, $p);
        $a = new BigInteger(\danog\MadelineProto\Tools::random(2048 / 8), 256);
        $A = $g->powMod($a, $p);
        Crypt::checkG($A, $p);
        $AForHash = \str_pad($A->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
        $b_kg_x = $B->powMod(Magic::$one, $p)->subtract($kg_x);
        $u = new BigInteger(\hash('sha256', $AForHash . $BForHash, true), 256);
        $ux = $u->multiply($x);
        $a_ux = $a->add($ux);
        $S = $b_kg_x->powMod($a_ux, $p);
        $SForHash = \str_pad($S->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
        $K = \hash('sha256', $SForHash, true);
        $h1 = \hash('sha256', $pForHash, true);
        $h2 = \hash('sha256', $gForHash, true);
        $h1 ^= $h2;
        $M1 = \hash('sha256', $h1 . \hash('sha256', $client_salt, true) . \hash('sha256', $server_salt, true) . $AForHash . $BForHash . $K, true);
        return ['_' => 'inputCheckPasswordSRP', 'srp_id' => $id, 'A' => $AForHash, 'M1' => $M1];
    }
    /**
     * Get parameters to be passed to the account.updatePasswordSettings to update/set a 2FA password.
     *
     * The input params array can contain password, new_password, email and hint params.
     *
     * @param array $params Input params
     * @return array account.updatePasswordSettings parameters
     */
    public function getPassword(array $params) : array
    {
        $oldPassword = $this->getCheckPassword($params['password'] ?? '');
        $return = ['password' => $oldPassword, 'new_settings' => ['_' => 'account.passwordInputSettings', 'new_algo' => ['_' => 'passwordKdfAlgoUnknown'], 'new_password_hash' => '', 'hint' => '']];
        $new_settings =& $return['new_settings'];
        if (isset($params['new_password']) && $params['new_password'] !== '') {
            $client_salt = $this->createSalt($this->new_algo['salt1']);
            $server_salt = $this->new_algo['salt2'];
            $g = $this->new_algo['g'];
            $p = $this->new_algo['p'];
            $pForHash = $this->new_algo['pForHash'];
            $x = new BigInteger($this->hashPassword($params['new_password'], $client_salt, $server_salt), 256);
            $v = $g->powMod($x, $p);
            $vForHash = \str_pad($v->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
            $new_settings['new_algo'] = ['_' => 'passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow', 'salt1' => $client_salt, 'salt2' => $server_salt, 'g' => (int) $g->toString(), 'p' => $pForHash];
            $new_settings['new_password_hash'] = $vForHash;
            $new_settings['hint'] = $params['hint'] ?? '';
            if (isset($params['email'])) {
                $new_settings['email'] = $params['email'];
            }
        }
        return $return;
    }
}<?php

/**
 * Files module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use Amp\Deferred;
use Amp\File\BlockingFile;
use Amp\Http\Client\Request;
use Amp\Http\Status;
use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Exception;
use danog\MadelineProto\FileCallbackInterface;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProtoTools\Crypt\IGE;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools;
use const danog\Decoder\TYPES;
use function Amp\File\exists;
use function Amp\File\getSize;
use function Amp\File\openFile;
use function Amp\File\touch as touchAsync;
use function Amp\Promise\all;
/**
 * Manages upload and download of files.
 *
 * @property Settings $settings Settings
 */
trait Files
{
    use FilesLogic;
    /**
     * Upload file from URL.
     *
     * @param (string | FileCallbackInterface) $url URL of file
     * @param integer $size Size of file
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | \Amp\Promise<\Amp\Http\Client\Response> | \Amp\Promise<int> | \Amp\Promise<(null | string)> | \danog\MadelineProto\Stream\StreamInterface | array | int | mixed), mixed, mixed>
     */
    public function uploadFromUrl($url, int $size = 0, string $fileName = '', $cb = null, bool $encrypted = false) : \Generator
    {
        if (\is_object($url) && $url instanceof FileCallbackInterface) {
            $cb = $url;
            $url = (yield $url->getFile());
        }
        /** @var $response \Amp\Http\Client\Response */
        $request = new Request($url);
        $request->setTransferTimeout(10 * 1000 * 3600);
        $request->setBodySizeLimit(512 * 1024 * 4000);
        $response = (yield $this->datacenter->getHTTPClient()->request($request));
        if (200 !== ($status = $response->getStatus())) {
            throw new Exception("Wrong status code: {$status} " . $response->getReason());
        }
        $mime = \trim(\explode(';', $response->getHeader('content-type') ?? 'application/octet-stream')[0]);
        $size = $response->getHeader('content-length') ?? $size;
        $stream = $response->getBody();
        if (!$size) {
            $this->logger->logger("No content length for {$url}, caching first");
            $body = $stream;
            $stream = new BlockingFile(\fopen('php://temp', 'r+b'), 'php://temp', 'r+b');
            while (null !== ($chunk = (yield $body->read()))) {
                (yield $stream->write($chunk));
            }
            $size = $stream->tell();
            if (!$size) {
                throw new Exception('Wrong size!');
            }
            (yield $stream->seek(0));
        }
        return yield from $this->uploadFromStream($stream, $size, $mime, $fileName, $cb, $encrypted);
    }
    /**
    * Upload file from callable.
    *
    * The callable must accept two parameters: int $offset, int $size
    The callable must return a string with the contest of the file at the specified offset and size.
    *
    * @param mixed $callable Callable
    * @param integer $size File size
    * @param string $mime Mime type
    * @param string $fileName File name
    * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
    * @param boolean $seekable Whether chunks can be fetched out of order
    * @param boolean $encrypted Whether to encrypt file for secret chats
    *
    * @return \Generator
    *
    * @psalm-return \Generator<int, (\Amp\Promise | \Amp\Promise<array>), mixed, array{_: string, id: string, parts: int, name: string, mime_type: string, key_fingerprint?: mixed, key?: mixed, iv?: mixed, md5_checksum: string}>
    */
    public function uploadFromCallable(callable $callable, int $size, string $mime, string $fileName = '', $cb = null, bool $seekable = true, bool $encrypted = false) : \Generator
    {
        if (\is_object($callable) && $callable instanceof FileCallbackInterface) {
            $cb = $callable;
            $callable = (yield $callable->getFile());
        }
        if (!\is_callable($callable)) {
            throw new Exception('Invalid callable provided');
        }
        if ($cb === null) {
            $cb = function ($percent) : void {
                $this->logger->logger('Upload status: ' . $percent . '%', \danog\MadelineProto\Logger::NOTICE);
            };
        }
        $datacenter = $this->settings->getDefaultDc();
        if ($this->datacenter->has($datacenter . '_media')) {
            $datacenter .= '_media';
        }
        $part_size = 512 * 1024;
        $parallel_chunks = $this->settings->getFiles()->getUploadParallelChunks();
        $part_total_num = (int) \ceil($size / $part_size);
        $part_num = 0;
        $method = $size > 10 * 1024 * 1024 ? 'upload.saveBigFilePart' : 'upload.saveFilePart';
        $constructor = 'input' . ($encrypted === true ? 'Encrypted' : '') . ($size > 10 * 1024 * 1024 ? 'FileBig' : 'File') . ($encrypted === true ? 'Uploaded' : '');
        $file_id = Tools::random(8);
        $ige = null;
        $fingerprint = null;
        $iv = null;
        $key = null;
        if ($encrypted === true) {
            $key = Tools::random(32);
            $iv = Tools::random(32);
            $digest = \hash('md5', $key . $iv, true);
            $fingerprint = Tools::unpackSignedInt(\Phabel\Target\Php80\Polyfill::substr($digest, 0, 4) ^ \Phabel\Target\Php80\Polyfill::substr($digest, 4, 4));
            $ige = IGE::getInstance($key, $iv);
            $seekable = false;
        }
        //$ctx = \hash_init('md5');
        $promises = [];
        $speed = 0;
        $time = 0;
        $cb = function () use($cb, $part_total_num, &$speed, &$time) : void {
            static $cur = 0;
            $cur++;
            Tools::callFork($cb($cur * 100 / $part_total_num, $speed, $time));
        };
        $callable = static function (int $part_num) use($file_id, $part_total_num, $part_size, $callable, $ige) : \Generator {
            $bytes = (yield $callable($part_num * $part_size, $part_size));
            if ($ige) {
                $bytes = $ige->encrypt(\str_pad($bytes, $part_size, \chr(0)));
            }
            //\hash_update($ctx, $bytes);
            return ['file_id' => $file_id, 'file_part' => $part_num, 'file_total_parts' => $part_total_num, 'bytes' => $bytes];
        };
        $resPromises = [];
        $exception = null;
        $start = \microtime(true);
        while ($part_num < $part_total_num) {
            $resa = $callable($part_num);
            $writePromise = Tools::call($this->methodCallAsyncWrite($method, $resa, ['heavy' => true, 'file' => true, 'datacenter' => &$datacenter]));
            if (!$seekable) {
                (yield $writePromise);
            }
            $writePromise->onResolve(function ($e, $readDeferred) use($cb, $part_num, &$resPromises, &$exception) : \Generator {
                if ($e) {
                    $this->logger("Got exception while uploading: {$e}");
                    $exception = $e;
                    return;
                }
                $resPromises[] = $readDeferred->promise();
                try {
                    // Wrote chunk!
                    if (!(yield Tools::call($readDeferred->promise()))) {
                        throw new \danog\MadelineProto\Exception('Upload of part ' . $part_num . ' failed');
                    }
                    // Got OK from server for chunk!
                    $cb();
                } catch (\Throwable $e) {
                    $this->logger("Got exception while uploading: {$e}");
                    $exception = $e;
                }
            });
            $promises[] = $writePromise;
            ++$part_num;
            if (!($part_num % $parallel_chunks)) {
                // By default, 10 mb at a time, for a typical bandwidth of 1gbps (run the code in this every second)
                (yield Tools::all($promises));
                $promises = [];
                if ($exception) {
                    throw $exception;
                }
                $time = \microtime(true) - $start;
                $speed = (int) ($size * 8 / $time) / 1000000;
                $this->logger->logger("Partial upload time: {$time}");
                $this->logger->logger("Partial upload speed: {$speed} mbps");
            }
        }
        (yield all($promises));
        (yield all($resPromises));
        $time = \microtime(true) - $start;
        $speed = (int) ($size * 8 / $time) / 1000000;
        $this->logger->logger("Total upload time: {$time}");
        $this->logger->logger("Total upload speed: {$speed} mbps");
        $constructor = ['_' => $constructor, 'id' => $file_id, 'parts' => $part_total_num, 'name' => $fileName, 'mime_type' => $mime];
        if ($encrypted === true) {
            $constructor['key_fingerprint'] = $fingerprint;
            $constructor['key'] = $key;
            $constructor['iv'] = $iv;
            $constructor['size'] = $size;
        }
        $constructor['md5_checksum'] = '';
        //\hash_final($ctx);
        return $constructor;
    }
    /**
     * Reupload telegram file.
     *
     * @param mixed $media Telegram file
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | array), mixed, mixed>
     */
    public function uploadFromTgfile($media, $cb = null, bool $encrypted = false) : \Generator
    {
        if (\is_object($media) && $media instanceof FileCallbackInterface) {
            $cb = $media;
            $media = (yield $media->getFile());
        }
        $media = (yield from $this->getDownloadInfo($media));
        if (!isset($media['size'], $media['mime'])) {
            throw new Exception('Wrong file provided!');
        }
        $size = $media['size'];
        $mime = $media['mime'];
        $chunk_size = 512 * 1024;
        $bridge = new class($size, $chunk_size, $cb)
        {
            /**
             * Read promises.
             *
             * @var Deferred[]
             */
            private $read = [];
            /**
             * Read promises (write lenth).
             *
             * @var int[]
             */
            private $wrote = [];
            /**
             * Write promises.
             *
             * @var Deferred[]
             */
            private $write = [];
            /**
             * Part size.
             *
             * @var int
             */
            private $partSize;
            /**
             * Offset for callback.
             *
             * @var int
             */
            private $offset = 0;
            /**
             * Callback.
             *
             * @var ?callable
             */
            private $cb;
            /**
             * Constructor.
             *
             * @param integer $size Total file size
             * @param integer $partSize Part size
             * @param ?callable $cb Callback
             */
            public function __construct(int $size, int $partSize, ?callable $cb)
            {
                for ($x = 0; $x < $size; $x += $partSize) {
                    $this->read[] = new Deferred();
                    $this->write[] = new Deferred();
                    $this->wrote[] = $size - $x < $partSize ? $size - $x : $partSize;
                }
                $this->partSize = $partSize;
                $this->cb = $cb;
            }
            /**
             * Read chunk.
             *
             * @param integer $offset Offset
             * @param integer $size Chunk size
             *
             * @return Promise
             */
            public function read(int $offset, int $size) : Promise
            {
                $offset /= $this->partSize;
                return $this->write[$offset]->promise();
            }
            /**
             * Write chunk.
             *
             * @param string $data Data
             * @param integer $offset Offset
             *
             * @return Promise
             */
            public function write(string $data, int $offset) : Promise
            {
                $offset /= $this->partSize;
                $this->write[$offset]->resolve($data);
                return $this->read[$offset]->promise();
            }
            /**
             * Read callback, called when the chunk is read and fully resent.
             *
             * @param mixed ...$params Params to be passed to cb
             *
             * @return void
             */
            public function callback(...$params) : void
            {
                $offset = $this->offset++;
                $this->read[$offset]->resolve($this->wrote[$offset]);
                if ($this->cb) {
                    Tools::callFork(($this->cb)(...$params));
                }
            }
        };
        $reader = [$bridge, 'read'];
        $writer = [$bridge, 'write'];
        $cb = [$bridge, 'callback'];
        $read = $this->uploadFromCallable($reader, $size, $mime, '', $cb, true, $encrypted);
        $write = $this->downloadToCallable($media, $writer, null, true, 0, -1, $chunk_size);
        [$res] = (yield Tools::all([$read, $write]));
        return $res;
    }
    /**
     *
     */
    private function genAllFile($media) : \Generator
    {
        $res = [$this->TL->getConstructors()->findByPredicate($media['_'])['type'] => $media];
        switch ($media['_']) {
            case 'messageMediaPoll':
                $res['Poll'] = $media['poll'];
                $res['InputMedia'] = ['_' => 'inputMediaPoll', 'poll' => $res['Poll']];
                if (isset($res['Poll']['quiz']) && $res['Poll']['quiz']) {
                    if (empty($media['results']['results'])) {
                        //quizzes need a correct answer
                        throw new \danog\MadelineProto\Exception('No poll results');
                    }
                    foreach ($media['results']['results'] as $answer) {
                        if ($answer['correct']) {
                            $res['InputMedia']['correct_answers'][] = $answer['option'];
                        }
                    }
                }
                if (isset($media['results']['solution'])) {
                    $res['InputMedia']['solution'] = $media['results']['solution'];
                }
                if (isset($media['results']['solution_entities'])) {
                    $res['InputMedia']['solution_entities'] = $media['results']['solution_entities'];
                }
                break;
            case 'updateMessagePoll':
                $res['Poll'] = $media['poll'];
                $res['InputMedia'] = ['_' => 'inputMediaPoll', 'poll' => $res['Poll']];
                $res['MessageMedia'] = ['_' => 'messageMediaPoll', 'poll' => $res['Poll'], 'results' => $media['results']];
                if (isset($res['Poll']['quiz']) && $res['Poll']['quiz']) {
                    if (empty($media['results']['results'])) {
                        //quizzes need a correct answer
                        throw new \danog\MadelineProto\Exception('No poll results');
                    }
                    foreach ($media['results']['results'] as $answer) {
                        if ($answer['correct']) {
                            $res['InputMedia']['correct_answers'][] = $answer['option'];
                        }
                    }
                }
                if (isset($media['results']['solution'])) {
                    $res['InputMedia']['solution'] = $media['results']['solution'];
                }
                if (isset($media['results']['solution_entities'])) {
                    $res['InputMedia']['solution_entities'] = $media['results']['solution_entities'];
                }
                break;
            case 'messageMediaPhoto':
                if (!isset($media['photo']['access_hash'])) {
                    throw new \danog\MadelineProto\Exception('No access hash');
                }
                $res['Photo'] = $media['photo'];
                $res['InputPhoto'] = ['_' => 'inputPhoto', 'id' => $media['photo']['id'], 'access_hash' => $media['photo']['access_hash'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::PHOTO_LOCATION, $media['photo'])];
                $res['InputMedia'] = ['_' => 'inputMediaPhoto', 'id' => $res['InputPhoto']];
                if (isset($media['ttl_seconds'])) {
                    $res['InputMedia']['ttl_seconds'] = $media['ttl_seconds'];
                }
                break;
            case 'messageMediaDocument':
                if (!isset($media['document']['access_hash'])) {
                    throw new \danog\MadelineProto\Exception('No access hash');
                }
                $res['Document'] = $media['document'];
                $res['InputDocument'] = ['_' => 'inputDocument', 'id' => $media['document']['id'], 'access_hash' => $media['document']['access_hash'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::DOCUMENT_LOCATION, $media['document'])];
                $res['InputMedia'] = ['_' => 'inputMediaDocument', 'id' => $res['InputDocument']];
                if (isset($media['ttl_seconds'])) {
                    $res['InputMedia']['ttl_seconds'] = $media['ttl_seconds'];
                }
                break;
            case 'messageMediaDice':
                $res['InputMedia'] = ['_' => 'inputMediaDice', 'emoticon' => $media['emoticon']];
                break;
            case 'poll':
                $res['InputMedia'] = ['_' => 'inputMediaPoll', 'poll' => $res['Poll']];
                break;
            case 'document':
                if (!isset($media['access_hash'])) {
                    throw new \danog\MadelineProto\Exception('No access hash');
                }
                $res['InputDocument'] = ['_' => 'inputDocument', 'id' => $media['id'], 'access_hash' => $media['access_hash'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::DOCUMENT_LOCATION, $media)];
                $res['InputMedia'] = ['_' => 'inputMediaDocument', 'id' => $res['InputDocument']];
                $res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $media];
                break;
            case 'photo':
                if (!isset($media['access_hash'])) {
                    throw new \danog\MadelineProto\Exception('No access hash');
                }
                $res['InputPhoto'] = ['_' => 'inputPhoto', 'id' => $media['id'], 'access_hash' => $media['access_hash'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::PHOTO_LOCATION, $media)];
                $res['InputMedia'] = ['_' => 'inputMediaPhoto', 'id' => $res['InputPhoto']];
                $res['MessageMedia'] = ['_' => 'messageMediaPhoto', 'photo' => $media];
                break;
            default:
                throw new \danog\MadelineProto\Exception("Could not convert media object of type {$media['_']}");
        }
        return $res;
    }
    /**
     * Get info about file.
     *
     * @param mixed $constructor File ID
     *
     * @return \Generator<array>
     */
    public function getFileInfo($constructor) : \Generator
    {
        if (\is_string($constructor)) {
            $constructor = $this->unpackFileId($constructor);
            if (isset($constructor['MessageMedia'])) {
                $constructor = $constructor['MessageMedia'];
            } elseif (isset($constructor['InputMedia'])) {
                return $constructor;
            } elseif (isset($constructor['Chat']) || isset($constructor['User'])) {
                throw new Exception("Chat photo file IDs can't be reused to resend chat photos, please use getPwrChat()['photo'], instead");
            }
        }
        switch ($constructor['_']) {
            case 'updateNewMessage':
            case 'updateNewChannelMessage':
            case 'updateEditMessage':
            case 'updateEditChannelMessage':
                $constructor = $constructor['message'];
            // no break
            case 'message':
                $constructor = $constructor['media'];
        }
        return yield from $this->genAllFile($constructor);
    }
    /**
    * Get download info of the propic of a user
    Returns an array with the following structure:.
    *
    * `$info['ext']` - The file extension
    `$info['name']` - The file name, without the extension
    `$info['mime']` - The file mime type
    `$info['size']` - The file size
    *
    * @param mixed $messageMedia File ID
    *
    * @return \Generator<array>
    */
    public function getPropicInfo($data) : \Generator
    {
        return yield from $this->getDownloadInfo((yield $this->chats[yield from $this->getInfo($data, MTProto::INFO_TYPE_ID)]));
    }
    /**
     * Extract file info from bot API message.
     *
     * @param array $info Bot API message object
     *
     * @return ?array
     */
    public static function extractBotAPIFile(array $info) : ?array
    {
        foreach (TYPES as $type) {
            if (isset($info[$type]) && \is_array($info[$type])) {
                $method = $type;
                break;
            }
        }
        if (!isset($method)) {
            return null;
        }
        $info = $info[$method];
        if ($method === 'photo') {
            $info = $info[0];
        }
        $info['file_type'] = $method;
        return $info;
    }
    /**
    * Get download info of file
    Returns an array with the following structure:.
    *
    * `$info['ext']` - The file extension
    `$info['name']` - The file name, without the extension
    `$info['mime']` - The file mime type
    `$info['size']` - The file size
    *
    * @param mixed $messageMedia File ID
    *
    * @return \Generator<array>
    */
    public function getDownloadInfo($messageMedia) : \Generator
    {
        if (\is_string($messageMedia)) {
            $messageMedia = $this->unpackFileId($messageMedia);
            if (isset($messageMedia['InputFileLocation'])) {
                return $messageMedia;
            }
            $messageMedia = $messageMedia['MessageMedia'] ?? $messageMedia['User'] ?? $messageMedia['Chat'];
        }
        if (!isset($messageMedia['_'])) {
            if (!isset($messageMedia['InputFileLocation']) && !isset($messageMedia['file_id'])) {
                $messageMedia = self::extractBotAPIFile($messageMedia) ?? $messageMedia;
            }
            if (isset($messageMedia['file_id'])) {
                $res = (yield from $this->getDownloadInfo($messageMedia['file_id']));
                $res['size'] = $messageMedia['file_size'] ?? 0;
                $res['mime'] = $messageMedia['mime_type'] ?? 'application/octet-stream';
                $pathinfo = \pathinfo($messageMedia['file_name']);
                if (isset($pathinfo['extension'])) {
                    $res['ext'] = '.' . $pathinfo['extension'];
                }
                $res['name'] = $pathinfo['filename'];
                return $res;
            }
            return $messageMedia;
        }
        $res = [];
        switch ($messageMedia['_']) {
            // Updates
            case 'updateNewMessage':
            case 'updateNewChannelMessage':
                $messageMedia = $messageMedia['message'];
            // no break
            case 'message':
                return yield from $this->getDownloadInfo($messageMedia['media']);
            case 'updateNewEncryptedMessage':
                $messageMedia = $messageMedia['message'];
            // Secret media
            // no break
            case 'encryptedMessage':
                if ($messageMedia['decrypted_message']['media']['_'] === 'decryptedMessageMediaExternalDocument') {
                    return yield from $this->getDownloadInfo($messageMedia['decrypted_message']['media']);
                }
                $res['InputFileLocation'] = ['_' => 'inputEncryptedFileLocation', 'id' => $messageMedia['file']['id'], 'access_hash' => $messageMedia['file']['access_hash'], 'dc_id' => $messageMedia['file']['dc_id']];
                $res['size'] = $messageMedia['decrypted_message']['media']['size'];
                $res['key_fingerprint'] = $messageMedia['file']['key_fingerprint'];
                $res['key'] = $messageMedia['decrypted_message']['media']['key'];
                $res['iv'] = $messageMedia['decrypted_message']['media']['iv'];
                if (isset($messageMedia['decrypted_message']['media']['file_name'])) {
                    $pathinfo = \pathinfo($messageMedia['decrypted_message']['media']['file_name']);
                    if (isset($pathinfo['extension'])) {
                        $res['ext'] = '.' . $pathinfo['extension'];
                    }
                    $res['name'] = $pathinfo['filename'];
                }
                if (isset($messageMedia['decrypted_message']['media']['mime_type'])) {
                    $res['mime'] = $messageMedia['decrypted_message']['media']['mime_type'];
                } elseif ($messageMedia['decrypted_message']['media']['_'] === 'decryptedMessageMediaPhoto') {
                    $res['mime'] = 'image/jpeg';
                }
                if (isset($messageMedia['decrypted_message']['media']['attributes'])) {
                    foreach ($messageMedia['decrypted_message']['media']['attributes'] as $attribute) {
                        switch ($attribute['_']) {
                            case 'documentAttributeFilename':
                                $pathinfo = \pathinfo($attribute['file_name']);
                                if (isset($pathinfo['extension'])) {
                                    $res['ext'] = '.' . $pathinfo['extension'];
                                }
                                $res['name'] = $pathinfo['filename'];
                                break;
                            case 'documentAttributeAudio':
                                $audio = $attribute;
                                break;
                        }
                    }
                }
                if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
                    $res['name'] = $audio['title'];
                    if (isset($audio['performer'])) {
                        $res['name'] .= ' - ' . $audio['performer'];
                    }
                }
                if (!isset($res['ext']) || $res['ext'] === '') {
                    $res['ext'] = Tools::getExtensionFromLocation($res['InputFileLocation'], Tools::getExtensionFromMime($res['mime'] ?? 'image/jpeg'));
                }
                if (!isset($res['mime']) || $res['mime'] === '') {
                    $res['mime'] = Tools::getMimeFromExtension($res['ext'], 'image/jpeg');
                }
                if (!isset($res['name']) || $res['name'] === '') {
                    $res['name'] = Tools::unpackSignedLongString($messageMedia['file']['access_hash']);
                }
                return $res;
            // Wallpapers
            case 'wallPaper':
                return $this->getDownloadInfo($messageMedia['document']);
            // Photos
            case 'photo':
            case 'messageMediaPhoto':
                if ($messageMedia['_'] == 'photo') {
                    $messageMedia = ['_' => 'messageMediaPhoto', 'photo' => $messageMedia, 'ttl_seconds' => 0];
                }
                $res['MessageMedia'] = $messageMedia;
                $messageMedia = $messageMedia['photo'];
                $size = Tools::maxSize($messageMedia['sizes']);
                if (isset($size['volume_id'])) {
                    $res['InputFileLocation'] = ['_' => 'inputPhotoLegacyFileLocation', 'id' => $messageMedia['id'], 'access_hash' => $messageMedia['access_hash'], 'dc_id' => $messageMedia['dc_id'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::PHOTO_LOCATION, $messageMedia), 'volume_id' => $size['volume_id'], 'local_id' => $size['local_id'], 'secret' => $size['secret']];
                } else {
                    $res = \array_merge($res, yield from $this->getDownloadInfo($size));
                    $res['InputFileLocation'] = ['_' => 'inputPhotoFileLocation', 'id' => $messageMedia['id'], 'access_hash' => $messageMedia['access_hash'], 'dc_id' => $messageMedia['dc_id'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::PHOTO_LOCATION, $messageMedia), 'thumb_size' => $res['thumb_size'] ?? 'x'];
                }
                $res['name'] = Tools::unpackSignedLongString($messageMedia['id']) . '_' . ($res['thumb_size'] ?? 'x') . '_' . $messageMedia['dc_id'];
                $res['ext'] = '.jpg';
                $res['mime'] = 'image/jpeg';
                return $res;
            case 'user':
            case 'folder':
            case 'channel':
            case 'chat':
            case 'updateUserPhoto':
                $res = (yield from $this->getDownloadInfo($messageMedia['photo']));
                if (\is_array($messageMedia) && ($messageMedia['min'] ?? false) && isset($messageMedia['access_hash'])) {
                    // bot API file ID
                    $messageMedia['min'] = false;
                    $peer = $this->genAll($messageMedia, null, MTProto::INFO_TYPE_PEER);
                } else {
                    $peer = (yield from $this->getInfo($messageMedia, MTProto::INFO_TYPE_PEER));
                }
                $res['InputFileLocation'] = ['_' => 'inputPeerPhotoFileLocation', 'big' => true, 'peer' => $peer, 'photo_id' => $res['InputFileLocation']['photo_id']];
                $res['name'] = Tools::unpackSignedLongString($messageMedia['id']) . '_' . ($res['thumb_size'] ?? 'x') . '_' . $messageMedia['photo']['dc_id'];
                $res['ext'] = '.jpg';
                $res['mime'] = 'image/jpeg';
                return $res;
            case 'userProfilePhoto':
            case 'chatPhoto':
                $res['InputFileLocation']['has_video'] = $messageMedia['has_video'] ?? false;
                $res['InputFileLocation']['photo_id'] = $messageMedia['photo_id'];
                $res['InputFileLocation']['dc_id'] = $messageMedia['dc_id'];
                return $res;
            case 'photoStrippedSize':
                $res['size'] = \strlen($messageMedia['bytes']['bytes'] ?? $messageMedia['bytes']);
                $res['data'] = $messageMedia['bytes'];
                $res['thumb_size'] = 'JPG';
                return $res;
            case 'photoCachedSize':
                $res['size'] = \strlen($messageMedia['bytes']);
                $res['data'] = $messageMedia['bytes'];
                $res['thumb_size'] = $messageMedia['type'];
                return $res;
            case 'photoSize':
                $res['thumb_size'] = $messageMedia['type'];
                //$res['thumb_size'] = $size;
                if (isset($messageMedia['size'])) {
                    $res['size'] = $messageMedia['size'];
                }
                return $res;
            case 'photoSizeProgressive':
                $res['thumb_size'] = $messageMedia['type'];
                if (isset($messageMedia['sizes'])) {
                    $res['size'] = \end($messageMedia['sizes']);
                }
                return $res;
            // Documents
            case 'decryptedMessageMediaExternalDocument':
            case 'document':
                $messageMedia = ['_' => 'messageMediaDocument', 'ttl_seconds' => 0, 'document' => $messageMedia];
            // no break
            case 'messageMediaDocument':
                $res['MessageMedia'] = $messageMedia;
                foreach ($messageMedia['document']['attributes'] as $attribute) {
                    switch ($attribute['_']) {
                        case 'documentAttributeFilename':
                            $pathinfo = \pathinfo($attribute['file_name']);
                            if (isset($pathinfo['extension'])) {
                                $res['ext'] = '.' . $pathinfo['extension'];
                            }
                            $res['name'] = $pathinfo['filename'];
                            break;
                        case 'documentAttributeAudio':
                            $audio = $attribute;
                            break;
                    }
                }
                if (isset($audio) && isset($audio['title']) && !isset($res['name'])) {
                    $res['name'] = $audio['title'];
                    if (isset($audio['performer'])) {
                        $res['name'] .= ' - ' . $audio['performer'];
                    }
                }
                $res['InputFileLocation'] = ['_' => 'inputDocumentFileLocation', 'id' => $messageMedia['document']['id'], 'access_hash' => $messageMedia['document']['access_hash'], 'version' => isset($messageMedia['document']['version']) ? $messageMedia['document']['version'] : 0, 'dc_id' => $messageMedia['document']['dc_id'], 'file_reference' => yield from $this->referenceDatabase->getReference(ReferenceDatabase::DOCUMENT_LOCATION, $messageMedia['document'])];
                if (!isset($res['ext']) || $res['ext'] === '') {
                    $res['ext'] = Tools::getExtensionFromLocation($res['InputFileLocation'], Tools::getExtensionFromMime($messageMedia['document']['mime_type']));
                }
                if (!isset($res['name']) || $res['name'] === '') {
                    $res['name'] = Tools::unpackSignedLongString($messageMedia['document']['access_hash']);
                }
                if (isset($messageMedia['document']['size'])) {
                    $res['size'] = $messageMedia['document']['size'];
                }
                $res['name'] .= '_' . Tools::unpackSignedLongString($messageMedia['document']['id']);
                $res['mime'] = $messageMedia['document']['mime_type'];
                return $res;
            default:
                throw new \danog\MadelineProto\Exception('Invalid constructor provided: ' . $messageMedia['_']);
        }
    }
    /**
     * Download file to directory.
     *
     * @param mixed $messageMedia File to download
     * @param (string | FileCallbackInterface) $dir Directory where to download the file
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | \Amp\Promise<\Amp\File\File> | \Amp\Promise<\Amp\Ipc\Sync\ChannelledSocket> | \Amp\Promise<(callable | null)> | \Amp\Promise<mixed> | array | bool | mixed), mixed, (false | string)>
     */
    public function downloadToDir($messageMedia, $dir, $cb = null) : \Generator
    {
        if (\is_object($dir) && $dir instanceof FileCallbackInterface) {
            $cb = $dir;
            $dir = (yield $dir->getFile());
        }
        $messageMedia = (yield from $this->getDownloadInfo($messageMedia));
        return yield from $this->downloadToFile($messageMedia, $dir . '/' . $messageMedia['name'] . $messageMedia['ext'], $cb);
    }
    /**
     * Download file.
     *
     * @param mixed $messageMedia File to download
     * @param (string | FileCallbackInterface) $file Downloaded file path
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     *
     * @return \Generator Downloaded file path
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | \Amp\Promise<\Amp\File\File> | \Amp\Promise<\Amp\Ipc\Sync\ChannelledSocket> | \Amp\Promise<(callable | null)> | \Amp\Promise<mixed> | array | bool | mixed), mixed, (false | string)>
     */
    public function downloadToFile($messageMedia, $file, $cb = null) : \Generator
    {
        if (\is_object($file) && $file instanceof FileCallbackInterface) {
            $cb = $file;
            $file = (yield $file->getFile());
        }
        $file = Tools::absolute(\preg_replace('|/+|', '/', $file));
        if (!(yield exists($file))) {
            (yield touchAsync($file));
        }
        $file = \realpath($file);
        $messageMedia = (yield from $this->getDownloadInfo($messageMedia));
        $size = (yield getSize($file));
        $stream = (yield openFile($file, 'cb'));
        $this->logger->logger('Waiting for lock of file to download...');
        $unlock = (yield Tools::flock("{$file}.lock", LOCK_EX));
        $this->logger->logger('Got lock of file to download');
        try {
            yield from $this->downloadToStream($messageMedia, $stream, $cb, $size, -1);
        } finally {
            $unlock();
            \unlink("{$file}.lock");
            (yield $stream->close());
        }
        return $file;
    }
    /**
    * Download file to callable.
    The callable must accept two parameters: string $payload, int $offset
    The callable will be called (possibly out of order, depending on the value of $seekable).
    The callable should return the number of written bytes.
    *
    * @param mixed $messageMedia File to download
    * @param (callable | FileCallbackInterface) $callable Chunk callback
    * @param callable $cb Status callback (DEPRECATED, use FileCallbackInterface)
    * @param bool $seekable Whether the callable can be called out of order
    * @param int $offset Offset where to start downloading
    * @param int $end Offset where to stop downloading (inclusive)
    * @param int $part_size Size of each chunk
    *
    * @return \Generator
    *
    * @psalm-return \Generator<(int | mixed), (\Amp\Promise | array), mixed, true>
    */
    public function downloadToCallable($messageMedia, callable $callable, $cb = null, bool $seekable = true, int $offset = 0, int $end = -1, int $part_size = null) : \Generator
    {
        $messageMedia = (yield from $this->getDownloadInfo($messageMedia));
        if (\is_object($callable) && $callable instanceof FileCallbackInterface) {
            $cb = $callable;
            $callable = (yield $callable->getFile());
        }
        if (!\is_callable($callable)) {
            throw new Exception('Wrong callable provided');
        }
        if ($cb === null) {
            $cb = function ($percent) : void {
                $this->logger->logger('Download status: ' . $percent . '%', \danog\MadelineProto\Logger::NOTICE);
            };
        }
        if ($end === -1 && isset($messageMedia['size'])) {
            $end = $messageMedia['size'];
        }
        $part_size = $part_size ?? 1024 * 1024;
        $parallel_chunks = $this->settings->getFiles()->getDownloadParallelChunks();
        $datacenter = $messageMedia['InputFileLocation']['dc_id'] ?? $this->settings->getDefaultDc();
        if ($this->datacenter->has($datacenter . '_media')) {
            $datacenter .= '_media';
        }
        if (isset($messageMedia['key'])) {
            $digest = \hash('md5', $messageMedia['key'] . $messageMedia['iv'], true);
            $fingerprint = Tools::unpackSignedInt(\Phabel\Target\Php80\Polyfill::substr($digest, 0, 4) ^ \Phabel\Target\Php80\Polyfill::substr($digest, 4, 4));
            if ($fingerprint !== $messageMedia['key_fingerprint']) {
                throw new \danog\MadelineProto\Exception('Fingerprint mismatch!');
            }
            $ige = IGE::getInstance($messageMedia['key'], $messageMedia['iv']);
            $seekable = false;
        }
        if ($offset === $end) {
            $cb(100, 0, 0);
            return true;
        }
        $params = [];
        $start_at = $offset % $part_size;
        $probable_end = $end !== -1 ? $end : 512 * 1024 * 4000;
        $breakOut = false;
        for ($x = $offset - $start_at; $x < $probable_end; $x += $part_size) {
            $end_at = $part_size;
            if ($end !== -1 && $x + $part_size > $end) {
                $end_at = $end % $part_size;
                $breakOut = true;
            }
            $params[] = ['offset' => $x, 'limit' => $part_size, 'part_start_at' => $start_at, 'part_end_at' => $end_at];
            $start_at = 0;
            if ($breakOut) {
                break;
            }
        }
        if (!$params) {
            $cb(100, 0, 0);
            return true;
        }
        $count = \count($params);
        $time = 0;
        $speed = 0;
        $origCb = $cb;
        $cb = static function () use($cb, $count, &$time, &$speed) : void {
            static $cur = 0;
            $cur++;
            Tools::callFork($cb($cur * 100 / $count, $time, $speed));
        };
        $cdn = false;
        $params[0]['previous_promise'] = new Success(true);
        $start = \microtime(true);
        $old_dc = null;
        $size = (yield from $this->downloadPart($messageMedia, $cdn, $datacenter, $old_dc, $ige, $cb, $initParam = \array_shift($params), $callable, $seekable));
        if ($initParam['part_end_at'] - $initParam['part_start_at'] !== $size) {
            // Premature end for undefined length files
            $origCb(100, 0, 0);
            return true;
        }
        $parallel_chunks = $seekable ? $parallel_chunks : 1;
        if ($params) {
            $previous_promise = new Success(true);
            $promises = [];
            foreach ($params as $key => $param) {
                $param['previous_promise'] = $previous_promise;
                $previous_promise = Tools::call($this->downloadPart($messageMedia, $cdn, $datacenter, $old_dc, $ige, $cb, $param, $callable, $seekable));
                $previous_promise->onResolve(static function ($e, $res) use(&$size) {
                    if ($res) {
                        $size += $res;
                    }
                });
                $promises[] = $previous_promise;
                if (!($key % $parallel_chunks)) {
                    // 20 mb at a time, for a typical bandwidth of 1gbps
                    $res = (yield Tools::all($promises));
                    $promises = [];
                    foreach ($res as $r) {
                        if (!$r) {
                            break 2;
                        }
                    }
                    $time = \microtime(true) - $start;
                    $speed = (int) ($size * 8 / $time) / 1000000;
                    $this->logger->logger("Partial download time: {$time}");
                    $this->logger->logger("Partial download speed: {$speed} mbps");
                }
            }
            if ($promises) {
                (yield Tools::all($promises));
            }
        }
        $time = \microtime(true) - $start;
        $speed = (int) ($size * 8 / $time) / 1000000;
        $this->logger->logger("Total download time: {$time}");
        $this->logger->logger("Total download speed: {$speed} mbps");
        if ($cdn) {
            $this->clearCdnHashes($messageMedia['file_token']);
        }
        if (!isset($messageMedia['size'])) {
            $origCb(100, $time, $speed);
        }
        return true;
    }
    /**
     * Download file part.
     *
     * @param array $messageMedia File object
     * @param bool $cdn Whether this is a CDN file
     * @param string $datacenter DC ID
     * @param ?string $old_dc Previous DC ID
     * @param IGE $ige IGE decryptor instance
     * @param callable $cb Status callback
     * @param array $offset Offset
     * @param callable $callable Chunk callback
     * @param boolean $seekable Whether the download file is seekable
     * @param boolean $postpone Whether to postpone method call
     *
     * @return \Generator
     */
    private function downloadPart(&$messageMedia, bool &$cdn, &$datacenter, &$old_dc, &$ige, $cb, array $offset, $callable, bool $seekable, bool $postpone = false) : \Generator
    {
        static $method = [
            false => 'upload.getFile',
            // non-cdn
            true => 'upload.getCdnFile',
        ];
        do {
            if (!$cdn) {
                $basic_param = ['location' => $messageMedia['InputFileLocation']];
            } else {
                $basic_param = ['file_token' => $messageMedia['file_token']];
            }
            //$x = 0;
            while (true) {
                try {
                    $res = (yield from $this->methodCallAsyncRead($method[$cdn], $basic_param + $offset, ['heavy' => true, 'file' => true, 'FloodWaitLimit' => 0, 'datacenter' => &$datacenter, 'postpone' => $postpone]));
                    break;
                } catch (\danog\MadelineProto\RPCErrorException $e) {
                    if (\strpos($e->rpc, 'FLOOD_WAIT_') === 0) {
                        (yield Tools::sleep(1));
                        continue;
                    }
                    switch ($e->rpc) {
                        case 'FILE_TOKEN_INVALID':
                            $cdn = false;
                            continue 3;
                        default:
                            throw $e;
                    }
                }
            }
            if ($res['_'] === 'upload.fileCdnRedirect') {
                $cdn = true;
                $messageMedia['file_token'] = $res['file_token'];
                $messageMedia['cdn_key'] = $res['encryption_key'];
                $messageMedia['cdn_iv'] = $res['encryption_iv'];
                $old_dc = $datacenter;
                $datacenter = $res['dc_id'] . '_cdn';
                if (!$this->datacenter->has($datacenter)) {
                    $this->config['expires'] = -1;
                    yield from $this->getConfig([]);
                }
                $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['stored_on_cdn'], \danog\MadelineProto\Logger::NOTICE);
            } elseif ($res['_'] === 'upload.cdnFileReuploadNeeded') {
                $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['cdn_reupload'], \danog\MadelineProto\Logger::NOTICE);
                yield from $this->getConfig([]);
                try {
                    $this->addCdnHashes($messageMedia['file_token'], yield from $this->methodCallAsyncRead('upload.reuploadCdnFile', ['file_token' => $messageMedia['file_token'], 'request_token' => $res['request_token']], ['heavy' => true, 'datacenter' => $old_dc]));
                } catch (\danog\MadelineProto\RPCErrorException $e) {
                    switch ($e->rpc) {
                        case 'FILE_TOKEN_INVALID':
                        case 'REQUEST_TOKEN_INVALID':
                            $cdn = false;
                            continue 2;
                        default:
                            throw $e;
                    }
                }
                continue;
            }
            $res['bytes'] = (string) $res['bytes'];
            if ($cdn === false && $res['type']['_'] === 'storage.fileUnknown' && $res['bytes'] === '') {
                $datacenter = 0;
            }
            while ($cdn === false && $res['type']['_'] === 'storage.fileUnknown' && $res['bytes'] === '' && $this->datacenter->has(++$datacenter)) {
                $res = (yield from $this->methodCallAsyncRead('upload.getFile', $basic_param + $offset, ['heavy' => true, 'file' => true, 'FloodWaitLimit' => 0, 'datacenter' => $datacenter]));
            }
            if ($res['bytes'] === '') {
                return 0;
            }
            if (isset($messageMedia['cdn_key'])) {
                $ivec = \Phabel\Target\Php80\Polyfill::substr($messageMedia['cdn_iv'], 0, 12) . \pack('N', $offset['offset'] >> 4);
                $res['bytes'] = Crypt::ctrEncrypt($res['bytes'], $messageMedia['cdn_key'], $ivec);
                $this->checkCdnHash($messageMedia['file_token'], $offset['offset'], $res['bytes'], $old_dc);
            }
            if (isset($messageMedia['key'])) {
                $res['bytes'] = $ige->decrypt($res['bytes']);
            }
            if ($offset['part_start_at'] || $offset['part_end_at'] !== $offset['limit']) {
                $res['bytes'] = \Phabel\Target\Php80\Polyfill::substr($res['bytes'], $offset['part_start_at'], $offset['part_end_at'] - $offset['part_start_at']);
            }
            if (!$seekable) {
                (yield $offset['previous_promise']);
            }
            $res = (yield $callable($res['bytes'], $offset['offset'] + $offset['part_start_at']));
            $cb();
            return $res;
        } while (true);
    }
    private $cdn_hashes = [];
    /**
     *
     */
    private function addCdnHashes($file, $hashes) : void
    {
        if (!isset($this->cdn_hashes[$file])) {
            $this->cdn_hashes = [];
        }
        foreach ($hashes as $hash) {
            $this->cdn_hashes[$file][$hash['offset']] = ['limit' => $hash['limit'], 'hash' => (string) $hash['hash']];
        }
    }
    /**
     *
     */
    private function checkCdnHash($file, $offset, $data, &$datacenter) : \Generator
    {
        while (\strlen($data)) {
            if (!isset($this->cdn_hashes[$file][$offset])) {
                $this->addCdnHashes($file, yield from $this->methodCallAsyncRead('upload.getCdnFileHashes', ['file_token' => $file, 'offset' => $offset], ['datacenter' => $datacenter]));
            }
            if (!isset($this->cdn_hashes[$file][$offset])) {
                throw new \danog\MadelineProto\Exception('Could not fetch CDN hashes for offset ' . $offset);
            }
            if (\hash('sha256', \Phabel\Target\Php80\Polyfill::substr($data, 0, $this->cdn_hashes[$file][$offset]['limit']), true) !== $this->cdn_hashes[$file][$offset]['hash']) {
                throw new \danog\MadelineProto\SecurityException('CDN hash mismatch for offset ' . $offset);
            }
            $data = \Phabel\Target\Php80\Polyfill::substr($data, $this->cdn_hashes[$file][$offset]['limit']);
            $offset += $this->cdn_hashes[$file][$offset]['limit'];
        }
        return true;
    }
    /**
     * @return true
     */
    private function clearCdnHashes($file) : bool
    {
        unset($this->cdn_hashes[$file]);
        return true;
    }
}<?php

namespace danog\MadelineProto\MTProtoTools;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\IteratorStream;
use Amp\ByteStream\OutputStream;
use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\StreamException;
use Amp\File\BlockingFile;
use Amp\File\Handle;
use Amp\Http\Client\Request;
use Amp\Http\Server\Request as ServerRequest;
use Amp\Http\Server\Response;
use Amp\Http\Status;
use Amp\Producer;
use danog\MadelineProto\Exception;
use danog\MadelineProto\FileCallbackInterface;
use danog\MadelineProto\Ipc\Client;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Stream\Common\BufferedRawStream;
use danog\MadelineProto\Stream\Common\SimpleBufferedRawStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\Transport\PremadeStream;
use danog\MadelineProto\TL\Conversion\Extension;
use danog\MadelineProto\Tools;
use function Amp\File\exists;
use function Amp\File\getSize;
use function Amp\File\openFile;
trait FilesLogic
{
    /**
     * Download file to browser.
     *
     * Supports HEAD requests and content-ranges for parallel and resumed downloads.
     *
     * @param (array | string) $messageMedia File to download
     * @param callable $cb Status callback (can also use FileCallback)
     *
     * @return \Generator
     */
    public function downloadToBrowser($messageMedia, callable $cb = null) : \Generator
    {
        if (\is_object($messageMedia) && $messageMedia instanceof FileCallbackInterface) {
            $cb = $messageMedia;
            $messageMedia = (yield $messageMedia->getFile());
        }
        $headers = [];
        if (isset($_SERVER['HTTP_RANGE'])) {
            $headers['range'] = $_SERVER['HTTP_RANGE'];
        }
        $messageMedia = (yield from $this->getDownloadInfo($messageMedia));
        $result = ResponseInfo::parseHeaders($_SERVER['REQUEST_METHOD'], $headers, $messageMedia);
        foreach ($result->getHeaders() as $key => $value) {
            if (\is_array($value)) {
                foreach ($value as $subValue) {
                    \header("{$key}: {$subValue}", false);
                }
            } else {
                \header("{$key}: {$value}");
            }
        }
        \http_response_code($result->getCode());
        if (!\in_array($result->getCode(), [Status::OK, Status::PARTIAL_CONTENT])) {
            (yield Tools::echo($result->getCodeExplanation()));
        } elseif ($result->shouldServe()) {
            if (!empty($messageMedia['name']) && !empty($messageMedia['ext'])) {
                \header("Content-Disposition: inline; filename=\"{$messageMedia['name']}{$messageMedia['ext']}\"");
            }
            if (\ob_get_level()) {
                \ob_end_flush();
                \Phabel\Target\Php80\Polyfill::ob_implicit_flush();
            }
            yield from $this->downloadToStream($messageMedia, \fopen('php://output', 'w'), $cb, ...$result->getServeRange());
        }
    }
    /**
     * Download file to stream.
     *
     * @param mixed $messageMedia File to download
     * @param (mixed | FileCallbackInterface) $stream Stream where to download file
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param int $offset Offset where to start downloading
     * @param int $end Offset where to end download
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, (\Amp\Promise<\Amp\Ipc\Sync\ChannelledSocket> | \Amp\Promise<mixed> | mixed), mixed, mixed>
     */
    public function downloadToStream($messageMedia, $stream, $cb = null, int $offset = 0, int $end = -1) : \Generator
    {
        $messageMedia = (yield from $this->getDownloadInfo($messageMedia));
        if (\is_object($stream) && $stream instanceof FileCallbackInterface) {
            $cb = $stream;
            $stream = (yield $stream->getFile());
        }
        /** @var $stream \Amp\ByteStream\OutputStream */
        if (!\is_object($stream)) {
            $stream = new ResourceOutputStream($stream);
        }
        if (!$stream instanceof OutputStream) {
            throw new Exception("Invalid stream provided");
        }
        $seekable = false;
        if (\method_exists($stream, 'seek')) {
            try {
                (yield $stream->seek($offset));
                $seekable = true;
            } catch (StreamException $e) {
            }
        }
        $callable = static function (string $payload, int $offset) use($stream, $seekable) : \Generator {
            if ($seekable) {
                while ($stream->tell() !== $offset) {
                    (yield $stream->seek($offset));
                }
            }
            (yield $stream->write($payload));
            return \strlen($payload);
        };
        return yield from $this->downloadToCallable($messageMedia, $callable, $cb, $seekable, $offset, $end);
    }
    /**
     * Download file to amphp/http-server response.
     *
     * Supports HEAD requests and content-ranges for parallel and resumed downloads.
     *
     * @param (array | string) $messageMedia File to download
     * @param ServerRequest $request Request
     * @param callable $cb Status callback (can also use FileCallback)
     *
     * @return \Generator Returned response
     *
     * @psalm-return \Generator<mixed, array, mixed, \Amp\Http\Server\Response>
     */
    public function downloadToResponse($messageMedia, ServerRequest $request, callable $cb = null) : \Generator
    {
        if (\is_object($messageMedia) && $messageMedia instanceof FileCallbackInterface) {
            $cb = $messageMedia;
            $messageMedia = (yield $messageMedia->getFile());
        }
        $messageMedia = (yield from $this->getDownloadInfo($messageMedia));
        $result = ResponseInfo::parseHeaders($request->getMethod(), \array_map(fn(array $headers) => $headers[0], $request->getHeaders()), $messageMedia);
        $body = null;
        if ($result->shouldServe()) {
            $body = new IteratorStream(new Producer(function (callable $emit) use(&$messageMedia, &$cb, &$result) {
                $emit = static function (string $payload) use($emit) : \Generator {
                    (yield $emit($payload));
                    return \strlen($payload);
                };
                (yield Tools::call($this->downloadToCallable($messageMedia, $emit, $cb, false, ...$result->getServeRange())));
            }));
        } elseif (!\in_array($result->getCode(), [Status::OK, Status::PARTIAL_CONTENT])) {
            $body = $result->getCodeExplanation();
        }
        $response = new Response($result->getCode(), $result->getHeaders(), $body);
        if ($result->shouldServe() && !empty($result->getHeaders()['Content-Length'])) {
            $response->setHeader('content-length', $result->getHeaders()['Content-Length']);
            if (!empty($messageMedia['name']) && !empty($messageMedia['ext'])) {
                $response->setHeader('content-disposition', "inline; filename=\"{$messageMedia['name']}{$messageMedia['ext']}\"");
            }
        }
        return $response;
    }
    /**
     * Upload file to secret chat.
     *
     * @param (FileCallbackInterface | string | array) $file File, URL or Telegram file to upload
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | \Amp\Promise<\Amp\File\File> | \Amp\Promise<\Amp\Ipc\Sync\ChannelledSocket> | \Amp\Promise<int> | \Amp\Promise<mixed> | \Amp\Promise<(null | string)> | \danog\MadelineProto\Stream\StreamInterface | array | int | mixed), mixed, mixed>
     */
    public function uploadEncrypted($file, string $fileName = '', $cb = null) : \Generator
    {
        return $this->upload($file, $fileName, $cb, true);
    }
    /**
     * Upload file.
     *
     * @param (FileCallbackInterface | string | array) $file File, URL or Telegram file to upload
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | \Amp\Promise<\Amp\File\File> | \Amp\Promise<\Amp\Ipc\Sync\ChannelledSocket> | \Amp\Promise<int> | \Amp\Promise<mixed> | \Amp\Promise<(null | string)> | \danog\MadelineProto\Stream\StreamInterface | array | int | mixed), mixed, mixed>
     */
    public function upload($file, string $fileName = '', $cb = null, bool $encrypted = false) : \Generator
    {
        if (\is_object($file) && $file instanceof FileCallbackInterface) {
            $cb = $file;
            $file = (yield $file->getFile());
        }
        if (\is_string($file) || \is_object($file) && \method_exists($file, '__toString')) {
            if (\filter_var($file, FILTER_VALIDATE_URL)) {
                return yield from $this->uploadFromUrl($file, 0, $fileName, $cb, $encrypted);
            }
        } elseif (\is_array($file)) {
            return yield from $this->uploadFromTgfile($file, $cb, $encrypted);
        }
        if (\is_resource($file) || \is_object($file) && $file instanceof InputStream) {
            return yield from $this->uploadFromStream($file, 0, '', $fileName, $cb, $encrypted);
        }
        /** @var Settings */
        $settings = $this instanceof Client ? (yield $this->getSettings()) : $this->settings;
        if (!$settings->getFiles()->getAllowAutomaticUpload()) {
            return yield from $this->uploadFromUrl($file, 0, $fileName, $cb, $encrypted);
        }
        $file = Tools::absolute($file);
        if (!(yield exists($file))) {
            throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['file_not_exist']);
        }
        if (empty($fileName)) {
            $fileName = \basename($file);
        }
        $size = (yield getSize($file));
        if ($size > 512 * 1024 * 4000) {
            throw new \danog\MadelineProto\Exception('Given file is too big!');
        }
        $stream = (yield openFile($file, 'rb'));
        $mime = Extension::getMimeFromFile($file);
        try {
            return yield from $this->uploadFromStream($stream, $size, $mime, $fileName, $cb, $encrypted);
        } finally {
            (yield $stream->close());
        }
    }
    /**
     * Upload file from stream.
     *
     * @param mixed $stream PHP resource or AMPHP async stream
     * @param integer $size File size
     * @param string $mime Mime type
     * @param string $fileName File name
     * @param callable $cb Callback (DEPRECATED, use FileCallbackInterface)
     * @param boolean $encrypted Whether to encrypt file for secret chats
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (\Amp\Promise | \Amp\Promise<int> | \Amp\Promise<(null | string)> | \danog\MadelineProto\Stream\StreamInterface | array | int | mixed), mixed, mixed>
     */
    public function uploadFromStream($stream, int $size, string $mime, string $fileName = '', $cb = null, bool $encrypted = false) : \Generator
    {
        if (\is_object($stream) && $stream instanceof FileCallbackInterface) {
            $cb = $stream;
            $stream = (yield $stream->getFile());
        }
        /* @var $stream \Amp\ByteStream\OutputStream */
        if (!\is_object($stream)) {
            $stream = new ResourceInputStream($stream);
        }
        if (!$stream instanceof InputStream) {
            throw new Exception("Invalid stream provided");
        }
        $seekable = false;
        if (\method_exists($stream, 'seek')) {
            try {
                (yield $stream->seek(0));
                $seekable = true;
            } catch (StreamException $e) {
            }
        }
        $created = false;
        if ($stream instanceof Handle) {
            $callable = static function (int $offset, int $size) use($stream, $seekable) : \Generator {
                if ($seekable) {
                    while ($stream->tell() !== $offset) {
                        (yield $stream->seek($offset));
                    }
                }
                return (yield $stream->read($size));
            };
        } else {
            if (!$stream instanceof BufferedRawStream) {
                $ctx = (new ConnectionContext())->addStream(PremadeStream::class, $stream)->addStream(SimpleBufferedRawStream::class);
                $stream = (yield from $ctx->getStream());
                $created = true;
            }
            $callable = static function (int $offset, int $size) use($stream) : \Generator {
                $reader = (yield $stream->getReadBuffer($l));
                try {
                    return (yield $reader->bufferRead($size));
                } catch (\danog\MadelineProto\NothingInTheSocketException $e) {
                    $reader = (yield $stream->getReadBuffer($size));
                    return (yield $reader->bufferRead($size));
                }
            };
            $seekable = false;
        }
        if (!$size && $seekable && \method_exists($stream, 'tell')) {
            (yield $stream->seek(0, \SEEK_END));
            $size = (yield $stream->tell());
            (yield $stream->seek(0));
        } elseif (!$size) {
            $this->logger->logger("No content length for stream, caching first");
            $body = $stream;
            $stream = new BlockingFile(\fopen('php://temp', 'r+b'), 'php://temp', 'r+b');
            while (null !== ($chunk = (yield $body->read()))) {
                (yield $stream->write($chunk));
            }
            $size = $stream->tell();
            if (!$size) {
                throw new Exception('Wrong size!');
            }
            (yield $stream->seek(0));
            return yield from $this->uploadFromStream($stream, $size, $mime, $fileName, $cb, $encrypted);
        }
        $res = (yield from $this->uploadFromCallable($callable, $size, $mime, $fileName, $cb, $seekable, $encrypted));
        if ($created) {
            $stream->disconnect();
        }
        return $res;
    }
}<?php

/**
 * UpdateHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\MTProtoTools;

use Amp\Deferred;
use Amp\Loop;
use Amp\Promise;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Loop\Update\FeedLoop;
use danog\MadelineProto\Loop\Update\UpdateLoop;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\RPCErrorException;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools;
/**
 * Manages updates.
 *
 * @extend MTProto
 * @property Settings $settings Settings
 */
trait UpdateHandler
{
    /**
     * Update handler callback.
     *
     * @var ?callable
     */
    private $updateHandler;
    private $got_state = false;
    private $channels_state;
    public $updates = [];
    public $updates_key = 0;
    /**
     * Get updates.
     *
     * @param array $params Params
     *
     * @internal
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, \Amp\Promise<(mixed | null)>, mixed, (list<array{update_id: mixed, update: mixed}> | mixed)>
     */
    public function getUpdates($params = []) : \Generator
    {
        $this->updateHandler = MTProto::GETUPDATES_HANDLER;
        $params = MTProto::DEFAULT_GETUPDATES_PARAMS + $params;
        if (empty($this->updates)) {
            $params['timeout'] *= 1000;
            (yield Tools::timeoutWithDefault($this->waitUpdate(), $params['timeout'] ?: 100000));
        }
        if (empty($this->updates)) {
            return $this->updates;
        }
        if ($params['offset'] < 0) {
            $params['offset'] = \array_reverse(\array_keys((array) $this->updates))[\abs($params['offset']) - 1];
        }
        $updates = [];
        foreach ($this->updates as $key => $value) {
            if ($params['offset'] > $key) {
                unset($this->updates[$key]);
            } elseif ($params['limit'] === null || \count($updates) < $params['limit']) {
                $updates[] = ['update_id' => $key, 'update' => $value];
            }
        }
        $this->updates = \array_slice($this->updates, 0, \count($this->updates), true);
        return $updates;
    }
    /**
     *
     */
    private ?Deferred $update_deferred = null;
    /**
     * Wait for update.
     *
     * @internal
     *
     * @return Promise
     */
    public function waitUpdate() : Promise
    {
        $this->update_deferred = new Deferred();
        return $this->update_deferred->promise();
    }
    /**
     * Signal update.
     *
     * @internal
     *
     * @return void
     */
    public function signalUpdate() : void
    {
        if ($this->update_deferred) {
            $deferred = $this->update_deferred;
            $this->update_deferred = null;
            Loop::defer(fn() => $deferred->resolve());
        }
    }
    /**
     * Check message ID.
     *
     * @param array $message Message
     *
     * @internal
     *
     * @return boolean
     */
    public function checkMsgId(array $message) : bool
    {
        if (!isset($message['peer_id'])) {
            return true;
        }
        try {
            $peer_id = $this->getId($message['peer_id']);
        } catch (\danog\MadelineProto\Exception $e) {
            return true;
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            return true;
        }
        $message_id = $message['id'];
        if (!isset($this->msg_ids[$peer_id]) || $message_id > $this->msg_ids[$peer_id]) {
            $this->msg_ids[$peer_id] = $message_id;
            return true;
        }
        return false;
    }
    /**
     * Get channel state.
     *
     * @internal
     *
     * @return \Generator
     * @psalm-return <mixed, mixed, mixed, UpdatesState>
     */
    public function loadUpdateState() : \Generator
    {
        if (!$this->got_state) {
            $this->got_state = true;
            $this->channels_state->get(0, yield from $this->getUpdatesState());
        }
        return $this->channels_state->get(0);
    }
    /**
     * Load channel state.
     *
     * @param ?int $channelId Channel ID
     * @param array $init Init
     *
     * @internal
     *
     * @return (UpdatesState | UpdatesState[])
     */
    public function loadChannelState($channelId = null, $init = [])
    {
        return $this->channels_state->get($channelId, $init);
    }
    /**
     * Get channel states.
     *
     * @internal
     *
     * @return CombinedUpdatesState
     */
    public function getChannelStates()
    {
        return $this->channels_state;
    }
    /**
     * Get update state.
     *
     * @internal
     *
     * @return \Generator
     */
    public function getUpdatesState() : \Generator
    {
        $data = (yield from $this->methodCallAsyncRead('updates.getState', [], $this->settings->getDefaultDcParams()));
        yield from $this->getCdnConfig($this->settings->getDefaultDc());
        return $data;
    }
    /**
     * Undocumented function.
     *
     * @param array $updates Updates
     * @param array $actual_updates Actual updates for deferred
     *
     * @internal
     *
     * @return \Generator
     */
    public function handleUpdates($updates, $actual_updates = null) : \Generator
    {
        if ($actual_updates) {
            $updates = $actual_updates;
        }
        $this->logger->logger('Parsing updates (' . $updates['_'] . ') received via the socket...', \danog\MadelineProto\Logger::VERBOSE);
        switch ($updates['_']) {
            case 'updates':
            case 'updatesCombined':
                $result = [];
                foreach ($updates['updates'] as $key => $update) {
                    if ($update['_'] === 'updateNewMessage' || $update['_'] === 'updateReadMessagesContents' || $update['_'] === 'updateEditMessage' || $update['_'] === 'updateDeleteMessages' || $update['_'] === 'updateReadHistoryInbox' || $update['_'] === 'updateReadHistoryOutbox' || $update['_'] === 'updateWebPage' || $update['_'] === 'updateMessageID') {
                        $result[yield from $this->feeders[FeedLoop::GENERIC]->feedSingle($update)] = true;
                        unset($updates['updates'][$key]);
                    }
                }
                $this->seqUpdater->addPendingWakeups($result);
                if ($updates['updates']) {
                    if ($updates['_'] === 'updatesCombined') {
                        $updates['options'] = ['seq_start' => $updates['seq_start'], 'seq_end' => $updates['seq'], 'date' => $updates['date']];
                    } else {
                        $updates['options'] = ['seq_start' => $updates['seq'], 'seq_end' => $updates['seq'], 'date' => $updates['date']];
                    }
                    $this->seqUpdater->feed($updates);
                }
                $this->seqUpdater->resume();
                break;
            case 'updateShort':
                $this->feeders[yield from $this->feeders[FeedLoop::GENERIC]->feedSingle($updates['update'])]->resume();
                break;
            case 'updateShortSentMessage':
                if (!isset($updates['request']['body'])) {
                    break;
                }
                $updates['user_id'] = (yield from $this->getInfo($updates['request']['body']['peer'], MTProto::INFO_TYPE_ID));
                $updates['message'] = $updates['request']['body']['message'];
                unset($updates['request']);
            // no break
            case 'updateShortMessage':
            case 'updateShortChatMessage':
                $from_id = isset($updates['from_id']) ? $updates['from_id'] : ($updates['out'] ? $this->authorization['user']['id'] : $updates['user_id']);
                $to_id = isset($updates['chat_id']) ? -$updates['chat_id'] : ($updates['out'] ? $updates['user_id'] : $this->authorization['user']['id']);
                if (!((yield from $this->peerIsset($from_id)) || !((yield from $this->peerIsset($to_id)) || isset($updates['via_bot_id']) && !((yield from $this->peerIsset($updates['via_bot_id'])) || isset($updates['entities']) && !((yield from $this->entitiesPeerIsset($updates['entities'])) || isset($updates['fwd_from']) && !(yield from $this->fwdPeerIsset($updates['fwd_from']))))))) {
                    (yield $this->updaters[FeedLoop::GENERIC]->resume());
                    return;
                }
                $message = $updates;
                $message['_'] = 'message';
                try {
                    $message['from_id'] = (yield from $this->getInfo($from_id))['Peer'];
                    $message['peer_id'] = (yield from $this->getInfo($to_id))['Peer'];
                } catch (\danog\MadelineProto\Exception $e) {
                    $this->logger->logger('Still did not get user in database, postponing update', \danog\MadelineProto\Logger::ERROR);
                    break;
                } catch (\danog\MadelineProto\RPCErrorException $e) {
                    $this->logger->logger('Still did not get user in database, postponing update', \danog\MadelineProto\Logger::ERROR);
                    break;
                }
                $update = ['_' => 'updateNewMessage', 'message' => $message, 'pts' => $updates['pts'], 'pts_count' => $updates['pts_count']];
                $this->feeders[yield from $this->feeders[FeedLoop::GENERIC]->feedSingle($update)]->resume();
                break;
            case 'updatesTooLong':
                $this->updaters[UpdateLoop::GENERIC]->resume();
                break;
            default:
                throw new \danog\MadelineProto\ResponseException('Unrecognized update received: ' . \var_export($updates, true));
                break;
        }
    }
    /**
     * Save update.
     *
     * @param array $update Update to save
     *
     * @internal
     *
     * @return \Generator
     */
    public function saveUpdate(array $update) : \Generator
    {
        if ($update['_'] === 'updateConfig') {
            $this->config['expires'] = 0;
            yield from $this->getConfig();
        }
        if (\in_array($update['_'], ['updateUserName', 'updateUserPhone', 'updateUserBlocked', 'updateUserPhoto', 'updateContactRegistered', 'updateContactLink']) && $this->getSettings()->getDb()->getEnableFullPeerDb()) {
            $id = $this->getId($update);
            $chat = (yield $this->full_chats[$id]);
            $chat['last_update'] = 0;
            $this->full_chats[$id] = $chat;
            yield from $this->getFullInfo($id);
        }
        if ($update['_'] === 'updateDcOptions') {
            $this->logger->logger('Got new dc options', \danog\MadelineProto\Logger::VERBOSE);
            $this->config['dc_options'] = $update['dc_options'];
            yield from $this->parseConfig();
            return;
        }
        if ($update['_'] === 'updatePhoneCall') {
            if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
                $this->logger->logger('The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.', \danog\MadelineProto\Logger::WARNING);
                return;
            }
            switch ($update['phone_call']['_']) {
                case 'phoneCallRequested':
                    if (isset($this->calls[$update['phone_call']['id']])) {
                        return;
                    }
                    $controller = new \danog\MadelineProto\VoIP(false, $update['phone_call']['admin_id'], $this, \danog\MadelineProto\VoIP::CALL_STATE_INCOMING);
                    $controller->setCall($update['phone_call']);
                    $controller->storage = ['g_a_hash' => $update['phone_call']['g_a_hash']];
                    $controller->storage['video'] = $update['phone_call']['video'] ?? false;
                    $update['phone_call'] = $this->calls[$update['phone_call']['id']] = $controller;
                    break;
                case 'phoneCallAccepted':
                    if (!(yield from $this->confirmCall($update['phone_call']))) {
                        return;
                    }
                    $update['phone_call'] = $this->calls[$update['phone_call']['id']];
                    break;
                case 'phoneCall':
                    if (!(yield from $this->completeCall($update['phone_call']))) {
                        return;
                    }
                    $update['phone_call'] = $this->calls[$update['phone_call']['id']];
                    break;
                case 'phoneCallDiscarded':
                    if (!isset($this->calls[$update['phone_call']['id']])) {
                        return;
                    }
                    return $this->calls[$update['phone_call']['id']]->discard($update['phone_call']['reason'] ?? ['_' => 'phoneCallDiscardReasonDisconnect'], [], $update['phone_call']['need_debug'] ?? false);
            }
        }
        if ($update['_'] === 'updateNewEncryptedMessage' && !isset($update['message']['decrypted_message'])) {
            if (isset($update['qts'])) {
                $cur_state = (yield from $this->loadUpdateState());
                if ($cur_state->qts() === -1) {
                    $cur_state->qts($update['qts']);
                }
                if ($update['qts'] < $cur_state->qts()) {
                    $this->logger->logger('Duplicate update. update qts: ' . $update['qts'] . ' <= current qts ' . $cur_state->qts() . ', chat id: ' . $update['message']['chat_id'], \danog\MadelineProto\Logger::ERROR);
                    return false;
                }
                if ($update['qts'] > $cur_state->qts() + 1) {
                    $this->logger->logger('Qts hole. Fetching updates manually: update qts: ' . $update['qts'] . ' > current qts ' . $cur_state->qts() . '+1, chat id: ' . $update['message']['chat_id'], \danog\MadelineProto\Logger::ERROR);
                    $this->updaters[UpdateLoop::GENERIC]->resumeDefer();
                    return false;
                }
                $this->logger->logger('Applying qts: ' . $update['qts'] . ' over current qts ' . $cur_state->qts() . ', chat id: ' . $update['message']['chat_id'], \danog\MadelineProto\Logger::VERBOSE);
                yield from $this->methodCallAsyncRead('messages.receivedQueue', ['max_qts' => $cur_state->qts($update['qts'])], $this->settings->getDefaultDcParams());
            }
            if (!isset($this->secret_chats[$update['message']['chat_id']])) {
                $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $update['message']['chat_id']));
                return false;
            }
            $this->secretFeeders[$update['message']['chat_id']]->feed($update);
            $this->secretFeeders[$update['message']['chat_id']]->resume();
            return;
        }
        /*
                if ($update['_'] === 'updateEncryptedChatTyping') {
                $update = ['_' => 'updateUserTyping', 'user_id' => $this->encrypted_chats[$update['chat_id']]['user_id'], 'action' => ['_' => 'sendMessageTypingAction']];
                }
        */
        if ($update['_'] === 'updateEncryption') {
            switch ($update['chat']['_']) {
                case 'encryptedChatRequested':
                    if (!$this->settings->getSecretChats()->canAccept($update['chat']['admin_id'])) {
                        return;
                    }
                    $this->logger->logger('Accepting secret chat ' . $update['chat']['id'], \danog\MadelineProto\Logger::NOTICE);
                    try {
                        yield from $this->acceptSecretChat($update['chat']);
                    } catch (RPCErrorException $e) {
                        $this->logger->logger("Error while accepting secret chat: {$e}", Logger::FATAL_ERROR);
                    }
                    break;
                case 'encryptedChatDiscarded':
                    $this->logger->logger('Deleting secret chat ' . $update['chat']['id'] . ' because it was revoked by the other user (it was probably accepted by another client)', \danog\MadelineProto\Logger::NOTICE);
                    if (isset($this->secret_chats[$update['chat']['id']])) {
                        unset($this->secret_chats[$update['chat']['id']]);
                    }
                    if (isset($this->temp_requested_secret_chats[$update['chat']['id']])) {
                        unset($this->temp_requested_secret_chats[$update['chat']['id']]);
                    }
                    if (isset($this->temp_rekeyed_secret_chats[$update['chat']['id']])) {
                        unset($this->temp_rekeyed_secret_chats[$update['chat']['id']]);
                    }
                    break;
                case 'encryptedChat':
                    $this->logger->logger('Completing creation of secret chat ' . $update['chat']['id'], \danog\MadelineProto\Logger::NOTICE);
                    yield from $this->completeSecretChat($update['chat']);
                    break;
            }
            //$this->logger->logger($update, \danog\MadelineProto\Logger::NOTICE);
        }
        //if ($update['_'] === 'updateServiceNotification' && strpos($update['type'], 'AUTH_KEY_DROP_') === 0) {
        //}
        if (!$this->updateHandler) {
            return;
        }
        if (isset($update['message']['_']) && $update['message']['_'] === 'messageEmpty') {
            return;
        }
        if (isset($update['message']['from_id']['user_id'])) {
            if ($update['message']['from_id']['user_id'] === $this->authorization['user']['id']) {
                $update['message']['out'] = true;
            }
        } elseif (!isset($update['message']['from_id']) && isset($update['message']['peer_id']['user_id']) && $update['message']['peer_id']['user_id'] === $this->authorization['user']['id']) {
            $update['message']['out'] = true;
        }
        if (!isset($update['message']['from_id']) && isset($update['message']['peer_id']['user_id'])) {
            $update['message']['from_id'] = $update['message']['peer_id'];
        }
        if (isset($update['message']['peer_id'])) {
            $update['message']['to_id'] = $update['message']['peer_id'];
        }
        // First save to array, then once the feed loop signals resumal of loop, resume and handle
        $this->updates[$this->updates_key++] = $update;
    }
}<?php

/**
 * API module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

\class_alias(API::class, '\\danog\\MadelineProto\\FastAPI');<?php

/**
 * ResponseException module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * Indicates an error thrown when an unexpected response is received from telegram's servers.
 */
class ResponseException extends \Exception
{
}<?php

/**
 * APIFactory module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

class APIFactory extends AbstractAPIFactory
{
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var stats
     */
    public $stats;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var folders
     */
    public $folders;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var langpack
     */
    public $langpack;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var phone
     */
    public $phone;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var stickers
     */
    public $stickers;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var payments
     */
    public $payments;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var bots
     */
    public $bots;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var channels
     */
    public $channels;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var help
     */
    public $help;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var upload
     */
    public $upload;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var photos
     */
    public $photos;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var updates
     */
    public $updates;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var messages
     */
    public $messages;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var contacts
     */
    public $contacts;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var users
     */
    public $users;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var account
     */
    public $account;
    /**
     * @internal this is a internal property generated by build_docs.php, don't change manually
     *
     * @var auth
     */
    public $auth;
}bot_thumbnail#0 dc_id:int id:long access_hash:long volume_id:long = File;
bot_profile_photo#1 dc_id:int id:long access_hash:long volume_id:long = File;
bot_photo#2 dc_id:int id:long access_hash:long volume_id:long = File;

bot_voice#3 dc_id:int id:long access_hash:long = File;
bot_video#4 dc_id:int id:long access_hash:long = File;
bot_document#5 dc_id:int id:long access_hash:long = File;
bot_encrypted#6 dc_id:int id:long access_hash:long = File;
bot_temp#7 dc_id:int id:long access_hash:long = File;
bot_sticker#8 dc_id:int id:long access_hash:long = File;
bot_audio#9 dc_id:int id:long access_hash:long = File;
bot_gif#A dc_id:int id:long access_hash:long = File;
bot_encrypted_thumbnail#B dc_id:int id:long access_hash:long = File;
bot_wallpaper#C dc_id:int id:long access_hash:long = File;
bot_video_note#D dc_id:int id:long access_hash:long = File;
bot_secure_raw#F dc_id:int id:long access_hash:long = File;
bot_secure#10 dc_id:int id:long access_hash:long = File;
bot_background#11 dc_id:int id:long access_hash:long = File;
bot_size#12 dc_id:int id:long access_hash:long = File;
<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog\MadelineProto;

use Amp\Delayed;
use Amp\Loop;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\Stream\Common\FileBufferedStream;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\Ogg\Ogg;
use danog\MadelineProto\VoIP\Endpoint;
use SplQueue;
use function Amp\File\openFile;
if (\extension_loaded('php-libtgvoip')) {
    return;
}
class VoIP
{
    use \danog\MadelineProto\VoIP\MessageHandler;
    use \danog\MadelineProto\VoIP\AckHandler;
    const PHP_LIBTGVOIP_VERSION = '1.5.0';
    const STATE_CREATED = 0;
    const STATE_WAIT_INIT = 1;
    const STATE_WAIT_INIT_ACK = 2;
    const STATE_ESTABLISHED = 3;
    const STATE_FAILED = 4;
    const STATE_RECONNECTING = 5;
    const TGVOIP_ERROR_UNKNOWN = 0;
    const TGVOIP_ERROR_INCOMPATIBLE = 1;
    const TGVOIP_ERROR_TIMEOUT = 2;
    const TGVOIP_ERROR_AUDIO_IO = 3;
    const NET_TYPE_UNKNOWN = 0;
    const NET_TYPE_GPRS = 1;
    const NET_TYPE_EDGE = 2;
    const NET_TYPE_3G = 3;
    const NET_TYPE_HSPA = 4;
    const NET_TYPE_LTE = 5;
    const NET_TYPE_WIFI = 6;
    const NET_TYPE_ETHERNET = 7;
    const NET_TYPE_OTHER_HIGH_SPEED = 8;
    const NET_TYPE_OTHER_LOW_SPEED = 9;
    const NET_TYPE_DIALUP = 10;
    const NET_TYPE_OTHER_MOBILE = 11;
    const DATA_SAVING_NEVER = 0;
    const DATA_SAVING_MOBILE = 1;
    const DATA_SAVING_ALWAYS = 2;
    const PROXY_NONE = 0;
    const PROXY_SOCKS5 = 1;
    const AUDIO_STATE_NONE = -1;
    const AUDIO_STATE_CREATED = 0;
    const AUDIO_STATE_CONFIGURED = 1;
    const AUDIO_STATE_RUNNING = 2;
    const CALL_STATE_NONE = -1;
    const CALL_STATE_REQUESTED = 0;
    const CALL_STATE_INCOMING = 1;
    const CALL_STATE_ACCEPTED = 2;
    const CALL_STATE_CONFIRMED = 3;
    const CALL_STATE_READY = 4;
    const CALL_STATE_ENDED = 5;
    const PKT_INIT = 1;
    const PKT_INIT_ACK = 2;
    const PKT_STREAM_STATE = 3;
    const PKT_STREAM_DATA = 4;
    const PKT_UPDATE_STREAMS = 5;
    const PKT_PING = 6;
    const PKT_PONG = 7;
    const PKT_STREAM_DATA_X2 = 8;
    const PKT_STREAM_DATA_X3 = 9;
    const PKT_LAN_ENDPOINT = 10;
    const PKT_NETWORK_CHANGED = 11;
    const PKT_SWITCH_PREF_RELAY = 12;
    const PKT_SWITCH_TO_P2P = 13;
    const PKT_NOP = 14;
    const TLID_DECRYPTED_AUDIO_BLOCK_HEX = 'dbf948c1';
    const TLID_SIMPLE_AUDIO_BLOCK_HEX = 'cc0d0e76';
    const TLID_REFLECTOR_SELF_INFO_HEX = 'c01572c7';
    const TLID_REFLECTOR_PEER_INFO_HEX = '27D9371C';
    const PROTO_ID = 'GrVP';
    const PROTOCOL_VERSION = 9;
    const MIN_PROTOCOL_VERSION = 9;
    const STREAM_TYPE_AUDIO = 1;
    const STREAM_TYPE_VIDEO = 2;
    const CODEC_OPUS = 'SUPO';
    private $TLID_DECRYPTED_AUDIO_BLOCK;
    private $TLID_SIMPLE_AUDIO_BLOCK;
    private $TLID_REFLECTOR_SELF_INFO;
    private $TLID_REFLECTOR_PEER_INFO;
    /**
     *
     */
    private MTProto $MadelineProto;
    /**
     *
     */
    public MTProto $madeline;
    public $received_timestamp_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    public $remote_ack_timestamp_map = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
    public $session_out_seq_no = 0;
    public $session_in_seq_no = 0;
    public $voip_state = 0;
    public $configuration = ['endpoints' => [], 'shared_config' => []];
    public $storage = [];
    public $internalStorage = [];
    private $signal = 0;
    /**
     *
     */
    private int $callState;
    private $callID;
    private $creatorID;
    private $otherID;
    private $protocol;
    private $visualization;
    private $holdFiles = [];
    private $inputFiles = [];
    private $outputFile;
    private $isPlaying = false;
    /**
     *
     */
    private bool $creator;
    /**
     *
     */
    private PermAuthKey $authKey;
    /**
     *
     */
    private int $peerVersion = 0;
    /**
     * @var Endpoint[]
     */
    private array $sockets = [];
    /**
     * Timeout watcher.
     */
    private string $timeoutWatcher;
    /**
     * Last incoming timestamp.
     *
     * @var float
     */
    private $lastIncomingTimestamp = 0.0;
    /**
     * The outgoing timestamp.
     *
     * @var int
     */
    private $timestamp = 0;
    /**
     * Packet queue.
     *
     * @var SplQueue
     */
    private $packetQueue;
    /**
     * Temporary holdfile array.
     */
    private array $tempHoldFiles = [];
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep()
    {
        $vars = \get_object_vars($this);
        unset($vars['sockets'], $vars['timeoutWatcher']);
        return \array_keys($vars);
    }
    /**
     * Wakeup function.
     */
    public function __wakeup()
    {
        if ($this->voip_state === self::STATE_ESTABLISHED) {
            $this->voip_state = self::STATE_CREATED;
            $this->startTheMagic();
        }
    }
    /**
     * Constructor.
     *
     * @param boolean $creator
     * @param integer $otherID
     * @param MTProto $MadelineProto
     * @param integer $callState
     */
    public function __construct(bool $creator, int $otherID, MTProto $MadelineProto, int $callState)
    {
        $this->creator = $creator;
        $this->otherID = $otherID;
        $this->madeline = $this->MadelineProto = $MadelineProto;
        $this->callState = $callState;
        $this->packetQueue = new SplQueue();
        $this->TLID_REFLECTOR_SELF_INFO = \strrev(\hex2bin(self::TLID_REFLECTOR_SELF_INFO_HEX));
        $this->TLID_REFLECTOR_PEER_INFO = \strrev(\hex2bin(self::TLID_REFLECTOR_PEER_INFO_HEX));
        $this->TLID_DECRYPTED_AUDIO_BLOCK = \strrev(\hex2bin(self::TLID_DECRYPTED_AUDIO_BLOCK_HEX));
        $this->TLID_SIMPLE_AUDIO_BLOCK = \strrev(\hex2bin(self::TLID_SIMPLE_AUDIO_BLOCK_HEX));
    }
    /**
     * Get max layer.
     *
     * @return integer
     */
    public static function getConnectionMaxLayer() : int
    {
        return 92;
    }
    /**
     * Get debug string.
     *
     * @return string
     */
    public function getDebugString() : string
    {
        return '';
    }
    /**
     * Set call constructor.
     *
     * @param array $callID
     * @return void
     */
    public function setCall(array $callID) : void
    {
        $this->protocol = $callID['protocol'];
        $this->callID = ['_' => 'inputPhoneCall', 'id' => $callID['id'], 'access_hash' => $callID['access_hash']];
    }
    /**
     * Set emojis.
     *
     * @param array $visualization
     * @return void
     */
    public function setVisualization(array $visualization) : void
    {
        $this->visualization = $visualization;
    }
    /**
     * Get emojis.
     *
     * @return array
     */
    public function getVisualization() : array
    {
        return $this->visualization;
    }
    /**
     * Discard call.
     *
     * @param array $reason
     * @param array $rating
     * @param boolean $debug
     * @return (self | false)
     */
    public function discard($reason = ['_' => 'phoneCallDiscardReasonDisconnect'], $rating = [], $debug = false)
    {
        if (($this->callState ?? self::CALL_STATE_ENDED) === self::CALL_STATE_ENDED || empty($this->configuration)) {
            return false;
        }
        $this->callState = self::CALL_STATE_ENDED;
        Logger::log("Now closing {$this}");
        if (isset($this->timeoutWatcher)) {
            Loop::cancel($this->timeoutWatcher);
        }
        Logger::log("Closing all sockets in {$this}");
        foreach ($this->sockets as $socket) {
            $socket->disconnect();
        }
        Logger::log("Closed all sockets, discarding {$this}");
        return Tools::callFork($this->MadelineProto->discardCall($this->callID, $reason, $rating, $debug));
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->discard(['_' => 'phoneCallDiscardReasonDisconnect']);
    }
    /**
     * Accept call.
     *
     * @return (self | false)
     */
    public function accept()
    {
        if ($this->callState !== self::CALL_STATE_INCOMING) {
            return false;
        }
        $this->callState = self::CALL_STATE_ACCEPTED;
        Tools::call($this->MadelineProto->acceptCall($this->callID))->onResolve(function ($e, $res) {
            if ($e || !$res) {
                $this->discard(['_' => 'phoneCallDiscardReasonDisconnect']);
            }
        });
        return $this;
    }
    /**
     * Start the actual call.
     */
    public function startTheMagic() : self
    {
        if ($this->voip_state !== self::STATE_CREATED) {
            return $this;
        }
        $this->voip_state = self::STATE_WAIT_INIT;
        $this->timeoutWatcher = Loop::repeat(10000, function () {
            if (\microtime(true) - $this->lastIncomingTimestamp > 10) {
                $this->discard(['_' => 'phoneCallDiscardReasonDisconnect']);
            }
        });
        Tools::callFork((function () {
            $this->authKey = new PermAuthKey();
            $this->authKey->setAuthKey($this->configuration['auth_key']);
            foreach ($this->configuration['endpoints'] as $endpoint) {
                $this->sockets['v6 ' . $endpoint['id']] = new Endpoint('[' . $endpoint['ipv6'] . ']', $endpoint['port'], $endpoint['peer_tag'], true, $this);
                $this->sockets['v4 ' . $endpoint['id']] = new Endpoint($endpoint['ip'], $endpoint['port'], $endpoint['peer_tag'], true, $this);
            }
            foreach ($this->sockets as $k => $socket) {
                try {
                    yield from $socket->connect();
                } catch (\Throwable $e) {
                    unset($this->sockets[$k]);
                }
            }
            foreach ($this->sockets as $socket) {
                $this->send_message(['_' => self::PKT_INIT, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'audio_streams' => [self::CODEC_OPUS], 'video_streams' => []], $socket);
                Tools::callFork((function () use($socket) {
                    while ($payload = (yield from $this->recv_message($socket))) {
                        $this->lastIncomingTimestamp = \microtime(true);
                        Tools::callFork($this->handlePacket($socket, $payload));
                    }
                    Logger::log("Exiting VoIP read loop in {$this}!");
                })());
            }
        })());
        return $this;
    }
    /**
     * Handle incoming packet.
     */
    private function handlePacket(Endpoint $socket, array $packet) : \Generator
    {
        switch ($packet['_']) {
            case self::PKT_INIT:
                //$this->voip_state = self::STATE_WAIT_INIT_ACK;
                $this->send_message(['_' => self::PKT_INIT_ACK, 'protocol' => self::PROTOCOL_VERSION, 'min_protocol' => self::MIN_PROTOCOL_VERSION, 'all_streams' => [['id' => 0, 'type' => self::STREAM_TYPE_AUDIO, 'codec' => self::CODEC_OPUS, 'frame_duration' => 60, 'enabled' => 1]]], $socket);
                yield from $this->startWriteLoop($socket);
                break;
            case self::PKT_INIT_ACK:
                yield from $this->startWriteLoop($socket);
                break;
            case self::PKT_STREAM_DATA:
                $cnt = 1;
                break;
            case self::PKT_STREAM_DATA_X2:
                $cnt = 2;
                break;
            case self::PKT_STREAM_DATA_X3:
                $cnt = 3;
                break;
        }
        if (isset($cnt)) {
        }
    }
    /**
     * Start write loop.
     *
     * @param Endpoint $socket
     * @return \Generator
     */
    private function startWriteLoop(Endpoint $socket) : \Generator
    {
        if ($this->voip_state === self::STATE_ESTABLISHED) {
            return;
        }
        $this->voip_state = self::STATE_ESTABLISHED;
        $this->tempHoldFiles = [];
        while (true) {
            $file = \array_shift($this->inputFiles);
            if (!$file) {
                if (empty($this->tempHoldFiles)) {
                    $this->tempHoldFiles = $this->holdFiles;
                }
                if (empty($this->tempHoldFiles)) {
                    return;
                }
                $file = \array_shift($this->tempHoldFiles);
            }
            $it = (yield from $this->openFile($file));
            if ($this->MadelineProto->getSettings()->getVoip()->getPreloadAudio()) {
                while ((yield $it->advance())) {
                    $this->packetQueue->enqueue($it->getCurrent());
                }
                $t = \microtime(true) / 1000 + 60;
                while (!$this->packetQueue->isEmpty()) {
                    if (!(yield $this->send_message(['_' => self::PKT_STREAM_DATA, 'stream_id' => 0, 'data' => $this->packetQueue->dequeue(), 'timestamp' => $this->timestamp], $socket))) {
                        Logger::log("Exiting VoIP write loop in {$this}!");
                        return;
                    }
                    //Logger::log("Writing {$this->timestamp} in $this!");
                    (yield new Delayed((int) ($t - \microtime(true) / 1000)));
                    $t = \microtime(true) / 1000 + 60;
                    $this->timestamp += 60;
                }
            } else {
                $t = \microtime(true) / 1000 + 60;
                while ((yield $it->advance())) {
                    if (!(yield $this->send_message(['_' => self::PKT_STREAM_DATA, 'stream_id' => 0, 'data' => $it->getCurrent(), 'timestamp' => $this->timestamp], $socket))) {
                        Logger::log("Exiting VoIP write loop in {$this}!");
                        return;
                    }
                    //Logger::log("Writing {$this->timestamp} in $this!");
                    (yield new Delayed((int) ($t - \microtime(true) / 1000)));
                    $t = \microtime(true) / 1000 + 60;
                    $this->timestamp += 60;
                }
            }
        }
    }
    /**
     * Open OGG file for reading.
     *
     * @param string $file
     * @return \Generator
     */
    private function openFile(string $file) : \Generator
    {
        $ctx = new ConnectionContext();
        $ctx->addStream(FileBufferedStream::class, (yield openFile($file, 'r')));
        $stream = (yield from $ctx->getStream());
        $ogg = (yield from Ogg::init($stream, 60000));
        $it = $ogg->getEmitter()->iterate();
        Tools::callFork($ogg->read());
        return $it;
    }
    /**
     * Play file.
     *
     * @param string $file
     * @return self
     */
    public function play(string $file) : self
    {
        $this->inputFiles[] = $file;
        return $this;
    }
    /**
     * Play file.
     *
     * @param string $file
     * @return self
     */
    public function then(string $file) : self
    {
        $this->inputFiles[] = $file;
        return $this;
    }
    /**
     * Files to play on hold.
     *
     * @param array $files
     * @return self
     */
    public function playOnHold(array $files) : self
    {
        $this->holdFiles = $files;
        return $this;
    }
    /**
     * Set output file.
     *
     * @param string $file
     * @return self
     */
    public function setOutputFile(string $file) : self
    {
        $this->outputFile = $file;
        return $this;
    }
    /**
     * Unset output file.
     *
     * @return self
     */
    public function unsetOutputFile() : self
    {
        $this->outputFile = null;
        return $this;
    }
    /**
     * Set MadelineProto instance.
     *
     * @param MTProto $MadelineProto
     * @return void
     */
    public function setMadeline(MTProto $MadelineProto) : void
    {
        $this->MadelineProto = $this->madeline = $MadelineProto;
    }
    /**
     * Get call protocol.
     *
     * @return array
     */
    public function getProtocol() : array
    {
        return $this->protocol;
    }
    /**
     * Get ID of other user.
     *
     * @return int
     */
    public function getOtherID() : int
    {
        return $this->otherID;
    }
    /**
     * Get call ID.
     *
     * @return (string | int)
     */
    public function getCallID()
    {
        return $this->callID;
    }
    /**
     * Get creation date.
     *
     * @return (int | bool)
     */
    public function whenCreated()
    {
        return isset($this->internalStorage['created']) ? $this->internalStorage['created'] : false;
    }
    /**
     * Parse config.
     *
     * @return void
     */
    public function parseConfig() : void
    {
    }
    /**
     * Get call state.
     *
     * @return int
     */
    public function getCallState() : int
    {
        return $this->callState ?? self::CALL_STATE_ENDED;
    }
    /**
     * Get library version.
     *
     * @return string
     */
    public function getVersion() : string
    {
        return 'libponyvoip-1.0';
    }
    /**
     * Get preferred relay ID.
     *
     * @return integer
     */
    public function getPreferredRelayID() : int
    {
        return 0;
    }
    /**
     * Get last error.
     *
     * @return string
     */
    public function getLastError() : string
    {
        return '';
    }
    /**
     * Get debug log.
     *
     * @return string
     */
    public function getDebugLog() : string
    {
        return '';
    }
    /**
     * Get signal bar count.
     */
    public function getSignalBarsCount() : int
    {
        return $this->signal;
    }
    /**
     * Get the value of creator.
     *
     * @return bool
     */
    public function isCreator() : bool
    {
        return $this->creator;
    }
    /**
     * Get the value of authKey.
     *
     * @return PermAuthKey
     */
    public function getAuthKey() : PermAuthKey
    {
        return $this->authKey;
    }
    /**
     * Get the value of peerVersion.
     *
     * @return int
     */
    public function getPeerVersion() : int
    {
        return $this->peerVersion;
    }
    /**
     * Get call representation.
     *
     * @return string
     */
    public function __toString()
    {
        $id = $this->callID['id'];
        return "call {$id} with {$this->otherID}";
    }
}===8===
decryptedMessage#1f814f1f random_id:long random_bytes:bytes message:string media:DecryptedMessageMedia = DecryptedMessage;
decryptedMessageService#aa48327d random_id:long random_bytes:bytes action:DecryptedMessageAction = DecryptedMessage;
decryptedMessageMediaEmpty#89f5c4a = DecryptedMessageMedia;
decryptedMessageMediaPhoto#32798a8c thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaVideo#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaGeoPoint#35480a59 lat:double long:double = DecryptedMessageMedia;
decryptedMessageMediaContact#588a0a97 phone_number:string first_name:string last_name:string user_id:int = DecryptedMessageMedia;
decryptedMessageActionSetMessageTTL#a1733aec ttl_seconds:int = DecryptedMessageAction;
decryptedMessageMediaDocument#b095434b thumb:bytes thumb_w:int thumb_h:int file_name:string mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaAudio#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageActionReadMessages#c4f40be random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionDeleteMessages#65614304 random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionScreenshotMessages#8ac1f475 random_ids:Vector<long> = DecryptedMessageAction;
decryptedMessageActionFlushHistory#6719e45c = DecryptedMessageAction;

===17===
decryptedMessage#204d3878 random_id:long ttl:int message:string media:DecryptedMessageMedia = DecryptedMessage;
decryptedMessageService#73164160 random_id:long action:DecryptedMessageAction = DecryptedMessage;
decryptedMessageMediaVideo#524a415d thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageMediaAudio#57e0a9cb duration:int mime_type:string size:int key:bytes iv:bytes = DecryptedMessageMedia;
decryptedMessageLayer#1be31789 random_bytes:bytes layer:int in_seq_no:int out_seq_no:int message:DecryptedMessage = DecryptedMessageLayer;
sendMessageTypingAction#16bf744e = SendMessageAction;
sendMessageCancelAction#fd5ec8f5 = SendMessageAction;
sendMessageRecordVideoAction#a187d66f = SendMessageAction;
sendMessageUploadVideoAction#92042ff7 = SendMessageAction;
sendMessageRecordAudioAction#d52f73f7 = SendMessageAction;
sendMessageUploadAudioAction#e6ac8a6f = SendMessageAction;
sendMessageUploadPhotoAction#990a3c1a = SendMessageAction;
sendMessageUploadDocumentAction#8faee98e = SendMessageAction;
sendMessageGeoLocationAction#176f8ba1 = SendMessageAction;
sendMessageChooseContactAction#628cbc6f = SendMessageAction;
decryptedMessageActionResend#511110b0 start_seq_no:int end_seq_no:int = DecryptedMessageAction;
decryptedMessageActionNotifyLayer#f3048883 layer:int = DecryptedMessageAction;
decryptedMessageActionTyping#ccb27641 action:SendMessageAction = DecryptedMessageAction;

===20===
decryptedMessageActionRequestKey#f3c9611b exchange_id:long g_a:bytes = DecryptedMessageAction;
decryptedMessageActionAcceptKey#6fe1735b exchange_id:long g_b:bytes key_fingerprint:long = DecryptedMessageAction;
decryptedMessageActionAbortKey#dd05ec6b exchange_id:long = DecryptedMessageAction;
decryptedMessageActionCommitKey#ec2e0b9b exchange_id:long key_fingerprint:long = DecryptedMessageAction;
decryptedMessageActionNoop#a82fdd63 = DecryptedMessageAction;

===23===
documentAttributeImageSize#6c37c15c w:int h:int = DocumentAttribute;
documentAttributeAnimated#11b58939 = DocumentAttribute;
documentAttributeSticker#fb0a5727 = DocumentAttribute;
documentAttributeVideo#5910cccb duration:int w:int h:int = DocumentAttribute;
documentAttributeAudio#51448e5 duration:int = DocumentAttribute;
documentAttributeFilename#15590068 file_name:string = DocumentAttribute;
photoSizeEmpty#e17e23c type:string = PhotoSize;
photoSize#77bfb61b type:string location:FileLocation w:int h:int size:int = PhotoSize;
photoCachedSize#e9a734fa type:string location:FileLocation w:int h:int bytes:bytes = PhotoSize;
fileLocationUnavailable#7c596b46 volume_id:long local_id:int secret:long = FileLocation;
fileLocation#53d69076 dc_id:int volume_id:long local_id:int secret:long = FileLocation;
decryptedMessageMediaExternalDocument#fa95b0dd id:long access_hash:long date:int mime_type:string size:int thumb:PhotoSize dc_id:int attributes:Vector<DocumentAttribute> = DecryptedMessageMedia;

===45===
decryptedMessage#36b091de flags:# random_id:long ttl:int message:string media:flags.9?DecryptedMessageMedia entities:flags.7?Vector<MessageEntity> via_bot_name:flags.11?string reply_to_random_id:flags.3?long = DecryptedMessage;
decryptedMessageMediaPhoto#f1fa8d78 thumb:bytes thumb_w:int thumb_h:int w:int h:int size:int key:bytes iv:bytes caption:string = DecryptedMessageMedia;
decryptedMessageMediaVideo#970c8c0e thumb:bytes thumb_w:int thumb_h:int duration:int mime_type:string w:int h:int size:int key:bytes iv:bytes caption:string = DecryptedMessageMedia;
decryptedMessageMediaDocument#7afe8ae2 thumb:bytes thumb_w:int thumb_h:int mime_type:string size:int key:bytes iv:bytes attributes:Vector<DocumentAttribute> caption:string = DecryptedMessageMedia;

===46===
decryptedMessageMediaVenue#8a0df56f lat:double long:double title:string address:string provider:string venue_id:string = DecryptedMessageMedia;
documentAttributeAudio#ded218e0 duration:int title:string performer:string = DocumentAttribute;
decryptedMessageMediaWebPage#e50511d8 url:string = DecryptedMessageMedia;

===55===
documentAttributeSticker#3a556302 alt:string stickerset:InputStickerSet = DocumentAttribute;

===66===
documentAttributeVideo#ef02ce6 flags:# round_message:flags.0?true duration:int w:int h:int = DocumentAttribute;

===73===
decryptedMessage#91cc4674 flags:# random_id:long ttl:int message:string media:flags.9?DecryptedMessageMedia entities:flags.7?Vector<MessageEntity> via_bot_name:flags.11?string reply_to_random_id:flags.3?long grouped_id:flags.17?long = DecryptedMessage;
<?php

/**
 * Update feeder loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Generic;

use danog\Loop\Generic\PeriodicLoop as GenericPeriodicLoop;
use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\MTProto;
/**
 * {@inheritDoc}
 *
 * @internal For internal use
 */
class PeriodicLoopInternal extends GenericPeriodicLoop
{
    use InternalLoop {
        __construct as private init;
    }
    /**
     * Constructor.
     *
     * @param MTProto $API API instance
     * @param callable $callable Method
     * @param string $name Loop name
     * @param (int | null) $interval Interval
     */
    public function __construct(MTProto $API, callable $callable, string $name, ?int $interval)
    {
        $this->init($API);
        parent::__construct($callable, $name, $interval);
    }
}<?php

/**
 * Update feeder loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Generic;

use Amp\Promise;
use danog\Loop\Generic\GenericLoop as GenericGenericLoop;
use danog\MadelineProto\InternalDoc;
use danog\MadelineProto\Loop\APILoop;
/**
 * {@inheritDoc}
 *
 * @deprecated Use the danog/loop API instead
 */
class GenericLoop extends GenericGenericLoop
{
    use APILoop {
        __construct as private init;
    }
    /**
     * Constructor.
     *
     * @param InternalDoc $API API instance
     * @param callable $callable Method
     * @param string $name Loop name
     */
    public function __construct(InternalDoc $API, callable $callable, string $name)
    {
        $this->init($API);
        parent::__construct($callable, $name);
    }
    /**
     * Pause the loop.
     *
     * @param ?int $time For how long to pause the loop, if null will pause forever (until resume is called from outside of the loop)
     *
     * @return Promise Resolved when the loop is resumed
     */
    public function pause(?int $time = null) : Promise
    {
        return parent::pause(\is_integer($time) ? $time * 1000 : $time);
    }
}<?php

/**
 * Update feeder loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Generic;

use danog\Loop\Generic\PeriodicLoop as GenericPeriodicLoop;
use danog\MadelineProto\InternalDoc;
use danog\MadelineProto\Loop\APILoop;
/**
 * {@inheritDoc}
 *
 * @deprecated Use the danog/loop API instead
 */
class PeriodicLoop extends GenericPeriodicLoop
{
    use APILoop {
        __construct as private init;
    }
    /**
     * Constructor.
     *
     * @param InternalDoc $API API instance
     * @param callable $callable Method
     * @param string $name Loop name
     * @param ?int $interval Interval
     */
    public function __construct(InternalDoc $API, callable $callable, string $name, ?int $interval)
    {
        $this->init($API);
        parent::__construct($callable, $name, $interval === null ? $interval : $interval * 1000);
    }
}<?php

/**
 * Loop logging trait.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop;

use danog\MadelineProto\Logger;
use danog\MadelineProto\Tools;
trait LoggerLoop
{
    /**
     * Whether the loop was started.
     */
    private bool $started = false;
    /**
     * Logger instance.
     */
    protected Logger $logger;
    /**
     * Constructor.
     *
     * @param Logger $logger Logger instance
     */
    public function __construct(Logger $logger)
    {
        $this->logger = $logger;
    }
    /**
     * Start the loop.
     *
     * Returns false if the loop is already running.
     *
     * @return bool
     */
    public function start() : bool
    {
        if ($this->started) {
            return false;
        }
        Tools::callFork((function () : \Generator {
            $this->startedLoop();
            try {
                yield from $this->loop();
            } finally {
                $this->exitedLoop();
            }
        })());
        return true;
    }
    /**
     * Check whether loop is running.
     *
     * @return boolean
     */
    public function isRunning() : bool
    {
        return $this->started;
    }
    /**
     * Signal that loop has started.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        $this->started = true;
        parent::startedLoop();
        $this->logger->logger("Entered {$this}", Logger::ULTRA_VERBOSE);
    }
    /**
     * Signal that loop has exited.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        $this->started = false;
        parent::exitedLoop();
        $this->logger->logger("Exited {$this}", Logger::ULTRA_VERBOSE);
    }
    /**
     * Report pause, can be overriden for logging.
     *
     * @param integer $timeout Pause duration, 0 = forever
     *
     * @return void
     */
    protected function reportPause(int $timeout) : void
    {
        $this->logger->logger("Pausing {$this} for {$timeout}", Logger::ULTRA_VERBOSE);
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public abstract function __toString() : string;
}<?php

/**
 * Internal loop trait.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop;

use danog\MadelineProto\MTProto;
trait InternalLoop
{
    use LoggerLoop {
        __construct as private setLogger;
    }
    /**
     * API instance.
     */
    protected MTProto $API;
    /**
     * Constructor.
     *
     * @param MTProto $API API instance
     */
    public function __construct(MTProto $API)
    {
        $this->API = $API;
        $this->setLogger($API->getLogger());
    }
}<?php

/**
 * Internal loop trait.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop;

use danog\MadelineProto\EventHandler;
use danog\MadelineProto\InternalDoc;
/**
 * API loop trait.
 */
trait APILoop
{
    use LoggerLoop {
        __construct as private setLogger;
    }
    /**
     * API instance.
     */
    protected InternalDoc $API;
    /**
     * Constructor.
     *
     * @param InternalDoc $API API instance
     */
    public function __construct(InternalDoc $API)
    {
        $this->API = $API;
        $this->setLogger($API instanceof EventHandler ? $API->getAPI()->getLogger() : $API->logger);
    }
}<?php

/**
 * Socket read loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Connection;

use Amp\ByteStream\PendingReadError;
use Amp\ByteStream\StreamException;
use Amp\Loop;
use Amp\Websocket\ClosedException;
use danog\Loop\SignalLoop;
use danog\MadelineProto\Logger;
use danog\MadelineProto\MTProto\IncomingMessage;
use danog\MadelineProto\MTProtoTools\Crypt;
use danog\MadelineProto\NothingInTheSocketException;
use danog\MadelineProto\SecurityException;
use danog\MadelineProto\Tools;
/**
 * Socket read loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class ReadLoop extends SignalLoop
{
    use Common;
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        $datacenter = $this->datacenter;
        $connection = $this->connection;
        $shared = $this->datacenterConnection;
        while (true) {
            try {
                $error = (yield $this->waitSignal($this->readMessage()));
            } catch (NothingInTheSocketException|StreamException|PendingReadError|\Error $e) {
                if ($connection->shouldReconnect()) {
                    return;
                }
                Tools::callForkDefer((function () use($API, $connection, $datacenter, $e) : \Generator {
                    $API->logger->logger($e);
                    $API->logger->logger("Got nothing in the socket in DC {$datacenter}, reconnecting...", Logger::ERROR);
                    yield from $connection->reconnect();
                })());
                return;
            } catch (SecurityException $e) {
                $connection->resetSession();
                $API->logger->logger("Got security exception in DC {$datacenter}, reconnecting...", Logger::ERROR);
                yield from $connection->reconnect();
                throw $e;
            }
            if (\is_int($error)) {
                //$this->exitedLoop();
                Tools::callForkDefer((function () use($error, $shared, $connection, $datacenter, $API) : \Generator {
                    if ($error === -404) {
                        if ($shared->hasTempAuthKey()) {
                            $API->logger->logger("WARNING: Resetting auth key in DC {$datacenter}...", Logger::WARNING);
                            $shared->setTempAuthKey(null);
                            $shared->resetSession();
                            foreach ($connection->new_outgoing as $message) {
                                $message->resetSent();
                            }
                            yield from $shared->reconnect();
                            yield from $API->initAuthorization();
                        } else {
                            yield from $connection->reconnect();
                        }
                    } elseif ($error === -1) {
                        $API->logger->logger("WARNING: Got quick ack from DC {$datacenter}", Logger::WARNING);
                        yield from $connection->reconnect();
                    } elseif ($error === 0) {
                        $API->logger->logger("Got NOOP from DC {$datacenter}", Logger::WARNING);
                        yield from $connection->reconnect();
                    } elseif ($error === -429) {
                        $API->logger->logger("Got -429 from DC {$datacenter}", Logger::WARNING);
                        (yield Tools::sleep(3));
                        yield from $connection->reconnect();
                    } else {
                        yield from $connection->reconnect();
                        throw new \danog\MadelineProto\RPCErrorException($error, $error);
                    }
                })());
                return;
            }
            $connection->httpReceived();
            Loop::defer([$connection, 'handleMessages']);
            if ($shared->isHttp()) {
                Loop::defer([$connection, 'pingHttpWaiter']);
            }
        }
    }
    /**
     *
     */
    public function readMessage() : \Generator
    {
        $API = $this->API;
        $datacenter = $this->datacenter;
        $connection = $this->connection;
        $shared = $this->datacenterConnection;
        if ($connection->shouldReconnect()) {
            $API->logger->logger('Not reading because connection is old');
            throw new NothingInTheSocketException();
        }
        try {
            $buffer = (yield $connection->stream->getReadBuffer($payload_length));
        } catch (ClosedException $e) {
            $API->logger->logger($e->getReason());
            if (\strpos($e->getReason(), '       ') === 0) {
                $payload = -\Phabel\Target\Php80\Polyfill::substr($e->getReason(), 7);
                $API->logger->logger("Received {$payload} from DC " . $datacenter, Logger::ERROR);
                return $payload;
            }
            throw $e;
        }
        if ($payload_length === 4) {
            $payload = \danog\MadelineProto\Tools::unpackSignedInt((yield $buffer->bufferRead(4)));
            $API->logger->logger("Received {$payload} from DC " . $datacenter, Logger::ULTRA_VERBOSE);
            return $payload;
        }
        $connection->reading(true);
        try {
            $auth_key_id = (yield $buffer->bufferRead(8));
            if ($auth_key_id === "\x00\x00\x00\x00\x00\x00\x00\x00") {
                $message_id = (yield $buffer->bufferRead(8));
                $connection->msgIdHandler->checkMessageId($message_id, ['outgoing' => false, 'container' => false]);
                $message_length = \unpack('V', (yield $buffer->bufferRead(4)))[1];
                $message_data = (yield $buffer->bufferRead($message_length));
                $left = $payload_length - $message_length - 4 - 8 - 8;
                if ($left) {
                    $API->logger->logger('Padded unencrypted message', Logger::ULTRA_VERBOSE);
                    if ($left < (-$message_length & 15)) {
                        $API->logger->logger('Protocol padded unencrypted message', Logger::ULTRA_VERBOSE);
                    }
                    (yield $buffer->bufferRead($left));
                }
            } elseif ($auth_key_id === $shared->getTempAuthKey()->getID()) {
                $message_key = (yield $buffer->bufferRead(16));
                list($aes_key, $aes_iv) = Crypt::aesCalculate($message_key, $shared->getTempAuthKey()->getAuthKey(), false);
                $decrypted_data = Crypt::igeDecrypt((yield $buffer->bufferRead($payload_length - 24)), $aes_key, $aes_iv);
                if ($message_key != \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', \Phabel\Target\Php80\Polyfill::substr($shared->getTempAuthKey()->getAuthKey(), 96, 32) . $decrypted_data, true), 8, 16)) {
                    throw new \danog\MadelineProto\SecurityException('msg_key mismatch');
                }
                /*
                                $server_salt = substr($decrypted_data, 0, 8);
                                if ($server_salt != $shared->getTempAuthKey()->getServerSalt()) {
                                $API->logger->logger('WARNING: Server salt mismatch (my server salt '.$shared->getTempAuthKey()->getServerSalt().' is not equal to server server salt '.$server_salt.').', Logger::WARNING);
                                }
                */
                $session_id = \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 8, 8);
                if ($session_id !== $connection->session_id) {
                    $API->logger->logger("Session ID mismatch", Logger::FATAL_ERROR);
                    $connection->resetSession();
                    throw new NothingInTheSocketException();
                }
                $message_id = \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 16, 8);
                $connection->msgIdHandler->checkMessageId($message_id, ['outgoing' => false, 'container' => false]);
                $seq_no = \unpack('V', \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 24, 4))[1];
                $message_data_length = \unpack('V', \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 28, 4))[1];
                if ($message_data_length > \strlen($decrypted_data)) {
                    throw new \danog\MadelineProto\SecurityException('message_data_length is too big');
                }
                if (\strlen($decrypted_data) - 32 - $message_data_length < 12) {
                    throw new \danog\MadelineProto\SecurityException('padding is too small');
                }
                if (\strlen($decrypted_data) - 32 - $message_data_length > 1024) {
                    throw new \danog\MadelineProto\SecurityException('padding is too big');
                }
                if ($message_data_length < 0) {
                    throw new \danog\MadelineProto\SecurityException('message_data_length not positive');
                }
                if ($message_data_length % 4 != 0) {
                    throw new \danog\MadelineProto\SecurityException('message_data_length not divisible by 4');
                }
                $message_data = \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 32, $message_data_length);
            } else {
                $API->logger->logger('Got unknown auth_key id', Logger::ERROR);
                return -404;
            }
            [$deserialized, $sideEffects] = $API->getTL()->deserialize($message_data, ['type' => '', 'connection' => $connection]);
            if (isset($API->referenceDatabase)) {
                $API->referenceDatabase->reset();
            }
            $message = new IncomingMessage($deserialized, $message_id);
            if (isset($seq_no)) {
                $message->setSeqNo($seq_no);
            }
            if ($sideEffects) {
                $message->setSideEffects($sideEffects);
            }
            $connection->new_incoming[$message_id] = $connection->incoming_messages[$message_id] = $message;
            $API->logger->logger('Received payload from DC ' . $datacenter, Logger::ULTRA_VERBOSE);
        } finally {
            $connection->reading(false);
        }
        return true;
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return "read loop in DC {$this->datacenter}";
    }
}<?php

/**
 * HttpWait loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Connection;

use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\MTProto\OutgoingMessage;
/**
 * HttpWait loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class HttpWaitLoop extends ResumableSignalLoop
{
    use Common;
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        $datacenter = $this->datacenter;
        $connection = $this->connection;
        $shared = $this->datacenterConnection;
        if (!$shared->isHttp()) {
            return;
        }
        while (true) {
            if ((yield $this->waitSignal($this->pause()))) {
                return;
            }
            if (!$connection->isHttp()) {
                return;
            }
            while (!$shared->hasTempAuthKey()) {
                if ((yield $this->waitSignal($this->pause()))) {
                    return;
                }
            }
            $API->logger->logger("DC {$datacenter}: request {$connection->countHttpSent()}, response {$connection->countHttpReceived()}");
            if ($connection->countHttpSent() === $connection->countHttpReceived() && (!empty($connection->pendingOutgoing) || !empty($connection->new_outgoing) && !$connection->hasPendingCalls())) {
                yield from $connection->sendMessage(new OutgoingMessage(['max_wait' => 30000, 'wait_after' => 0, 'max_delay' => 0], 'http_wait', '', false, false));
            }
            $API->logger->logger("DC {$datacenter}: request {$connection->countHttpSent()}, response {$connection->countHttpReceived()}");
        }
    }
    /**
     * Loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return "HTTP wait loop in DC {$this->datacenter}";
    }
}<?php

/**
 * RPC call status check loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Connection;

use Amp\Loop;
use danog\Loop\ResumableSignalLoop;
/**
 * Message cleanup loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class CleanupLoop extends ResumableSignalLoop
{
    use Common;
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $connection = $this->connection;
        while (!(yield $this->waitSignal($this->pause(1000)))) {
            if (isset($connection->msgIdHandler)) {
                $connection->msgIdHandler->cleanup();
            }
        }
    }
    /**
     * Loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return "cleanup loop in DC {$this->datacenter}";
    }
}<?php

/**
 * Common abstract class for all connection loops.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Connection;

use danog\MadelineProto\Connection;
use danog\MadelineProto\DataCenterConnection;
use danog\MadelineProto\Loop\InternalLoop;
/**
 * RPC call status check loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait Common
{
    use InternalLoop {
        __construct as private init;
    }
    /**
     * Connection instance.
     */
    protected Connection $connection;
    /**
     * DC ID.
     *
     * @var string
     */
    protected string $datacenter;
    /**
     * DataCenterConnection instance.
     */
    protected DataCenterConnection $datacenterConnection;
    /**
     * Constructor function.
     *
     * @param Connection $connection Connection
     */
    public function __construct(Connection $connection)
    {
        $this->init($connection->getExtra());
        $this->connection = $connection;
        $this->datacenter = $connection->getDatacenterID();
        $this->datacenterConnection = $connection->getShared();
    }
}<?php

/**
 * Ping loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Connection;

use danog\Loop\ResumableSignalLoop;
/**
 * Ping loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class PingLoop extends ResumableSignalLoop
{
    use Common;
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        $datacenter = $this->datacenter;
        $connection = $this->connection;
        $shared = $this->datacenterConnection;
        $timeout = $shared->getSettings()->getPingInterval();
        $timeoutMs = $timeout * 1000;
        while (true) {
            while (!$shared->hasTempAuthKey()) {
                if ((yield $this->waitSignal($this->pause()))) {
                    return;
                }
            }
            if ((yield $this->waitSignal($this->pause($timeoutMs)))) {
                return;
            }
            if (\time() - $connection->getLastChunk() >= $timeout && $shared->hasTempAuthKey()) {
                $API->logger->logger("Ping DC {$datacenter}");
                try {
                    yield from $connection->methodCallAsyncRead('ping', ['ping_id' => \random_bytes(8)]);
                } catch (\Throwable $e) {
                    $API->logger->logger("Error while pinging DC {$datacenter}");
                    $API->logger->logger((string) $e);
                }
            }
        }
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return "Ping loop in DC {$this->datacenter}";
    }
}<?php

/**
 * Socket write loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Connection;

use Amp\ByteStream\StreamException;
use Amp\Loop;
use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\Logger;
use danog\MadelineProto\MTProto\Container;
use danog\MadelineProto\MTProto\OutgoingMessage;
use danog\MadelineProto\MTProtoTools\Crypt;
use danog\MadelineProto\Tools;
/**
 * Socket write loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class WriteLoop extends ResumableSignalLoop
{
    const MAX_COUNT = 1020;
    private const MAX_SIZE = 1 << 15;
    const MAX_IDS = 8192;
    use Common;
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        $connection = $this->connection;
        $shared = $this->datacenterConnection;
        $datacenter = $this->datacenter;
        $please_wait = false;
        while (true) {
            while (empty($connection->pendingOutgoing) || $please_wait) {
                if ($connection->shouldReconnect()) {
                    $API->logger->logger('Not writing because connection is old');
                    return;
                }
                $please_wait = false;
                $API->logger->logger("Waiting in {$this}", Logger::ULTRA_VERBOSE);
                if ((yield $this->waitSignal($this->pause()))) {
                    $API->logger->logger("Exiting {$this}", Logger::ULTRA_VERBOSE);
                    return;
                }
                $API->logger->logger("Done waiting in {$this}", Logger::ULTRA_VERBOSE);
                if ($connection->shouldReconnect()) {
                    $API->logger->logger('Not writing because connection is old');
                    return;
                }
            }
            $connection->writing(true);
            try {
                $please_wait = (yield from $this->{$shared->hasTempAuthKey() ? 'encryptedWriteLoop' : 'unencryptedWriteLoop'}());
            } catch (StreamException $e) {
                if ($connection->shouldReconnect()) {
                    return;
                }
                Tools::callForkDefer((function () use($API, $connection, $datacenter, $e) : \Generator {
                    $API->logger->logger($e);
                    $API->logger->logger("Got nothing in the socket in DC {$datacenter}, reconnecting...", Logger::ERROR);
                    yield from $connection->reconnect();
                })());
                return;
            } finally {
                $connection->writing(false);
            }
            //$connection->waiter->resume();
        }
    }
    /**
     *
     */
    public function unencryptedWriteLoop() : \Generator
    {
        $API = $this->API;
        $datacenter = $this->datacenter;
        $connection = $this->connection;
        $shared = $this->datacenterConnection;
        while ($connection->pendingOutgoing) {
            $skipped_all = true;
            foreach ($connection->pendingOutgoing as $k => $message) {
                if ($shared->hasTempAuthKey()) {
                    return;
                }
                if ($message->isEncrypted()) {
                    continue;
                }
                if ($message->getState() & OutgoingMessage::STATE_REPLIED) {
                    unset($connection->pendingOutgoing[$k]);
                    continue;
                }
                $skipped_all = false;
                $API->logger->logger("Sending {$message} as unencrypted message to DC {$datacenter}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                $message_id = $message->getMsgId() ?? $connection->msgIdHandler->generateMessageId();
                $length = \strlen($message->getSerializedBody());
                $pad_length = -$length & 15;
                $pad_length += 16 * \danog\MadelineProto\Tools::randomInt($modulus = 16);
                $pad = \danog\MadelineProto\Tools::random($pad_length);
                $buffer = (yield $connection->stream->getWriteBuffer(8 + 8 + 4 + $pad_length + $length));
                (yield $buffer->bufferWrite("\x00\x00\x00\x00\x00\x00\x00\x00" . $message_id . \danog\MadelineProto\Tools::packUnsignedInt($length) . $message->getSerializedBody() . $pad));
                $connection->httpSent();
                $API->logger->logger("Sent {$message} as unencrypted message to DC {$datacenter}!", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                unset($connection->pendingOutgoing[$k]);
                $message->setMsgId($message_id);
                $connection->outgoing_messages[$message_id] = $message;
                $connection->new_outgoing[$message_id] = $message;
                $message->sent();
            }
            if ($skipped_all) {
                return true;
            }
        }
    }
    /**
     *
     */
    public function encryptedWriteLoop() : \Generator
    {
        $API = $this->API;
        $datacenter = $this->datacenter;
        $connection = $this->connection;
        $shared = $this->datacenterConnection;
        do {
            if (!$shared->hasTempAuthKey()) {
                return;
            }
            if ($shared->isHttp() && empty($connection->pendingOutgoing)) {
                return;
            }
            \ksort($connection->pendingOutgoing);
            $messages = [];
            $keys = [];
            $total_length = 0;
            $count = 0;
            $skipped = false;
            $inited = false;
            $has_seq = false;
            $has_state = false;
            $has_resend = false;
            $has_http_wait = false;
            foreach ($connection->pendingOutgoing as $k => $message) {
                if ($message->isUnencrypted()) {
                    continue;
                }
                if ($message->getState() & OutgoingMessage::STATE_REPLIED) {
                    unset($connection->pendingOutgoing[$k]);
                    $API->logger->logger("Skipping resending of {$message}, we already got a reply in DC {$datacenter}");
                    continue;
                }
                if ($message instanceof Container) {
                    unset($connection->pendingOutgoing[$k]);
                    continue;
                }
                $constructor = $message->getConstructor();
                if ($shared->getGenericSettings()->getAuth()->getPfs() && !$shared->isBound() && !$connection->isCDN() && $message->isMethod() && !\in_array($constructor, ['http_wait', 'auth.bindTempAuthKey'])) {
                    $API->logger->logger("Skipping {$message} due to unbound keys in DC {$datacenter}");
                    $skipped = true;
                    continue;
                }
                if ($constructor === 'http_wait') {
                    $has_http_wait = true;
                }
                if ($constructor === 'msgs_state_req') {
                    if ($has_state) {
                        $API->logger->logger("Already have a state request queued for the current container in DC {$datacenter}");
                        continue;
                    }
                    $has_state = true;
                }
                if ($constructor === 'msg_resend_req') {
                    if ($has_resend) {
                        continue;
                    }
                    $has_resend = true;
                }
                $body_length = \strlen($message->getSerializedBody());
                $actual_length = $body_length + 32;
                if ($total_length && $total_length + $actual_length > 32760 || $count >= 1020) {
                    $API->logger->logger('Length overflow, postponing part of payload', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    break;
                }
                if ($message->hasSeqNo()) {
                    $has_seq = true;
                }
                $message_id = $message->getMsgId() ?? $connection->msgIdHandler->generateMessageId();
                $API->logger->logger("Sending {$message} as encrypted message to DC {$datacenter}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                $MTmessage = ['_' => 'MTmessage', 'msg_id' => $message_id, 'body' => $message->getSerializedBody(), 'seqno' => $message->getSeqNo() ?? $connection->generateOutSeqNo($message->isContentRelated())];
                if ($message->isMethod() && $constructor !== 'http_wait') {
                    if (!$shared->getTempAuthKey()->isInited() && $constructor !== 'auth.bindTempAuthKey' && !$inited) {
                        $inited = true;
                        $API->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['write_client_info'], $constructor), \danog\MadelineProto\Logger::NOTICE);
                        $MTmessage['body'] = (yield from $API->getTL()->serializeMethod('invokeWithLayer', ['layer' => $API->settings->getSchema()->getLayer(), 'query' => yield from $API->getTL()->serializeMethod('initConnection', ['api_id' => $API->settings->getAppInfo()->getApiId(), 'api_hash' => $API->settings->getAppInfo()->getApiHash(), 'device_model' => !$connection->isCDN() ? $API->settings->getAppInfo()->getDeviceModel() : 'n/a', 'system_version' => !$connection->isCDN() ? $API->settings->getAppInfo()->getSystemVersion() : 'n/a', 'app_version' => $API->settings->getAppInfo()->getAppVersion(), 'system_lang_code' => $API->settings->getAppInfo()->getLangCode(), 'lang_code' => $API->settings->getAppInfo()->getLangCode(), 'lang_pack' => $API->settings->getAppInfo()->getLangPack(), 'proxy' => $connection->getCtx()->getInputClientProxy(), 'query' => $MTmessage['body']])]));
                    } else {
                        if ($message->hasQueue()) {
                            $queueId = $message->getQueueId();
                            if (!isset($connection->call_queue[$queueId])) {
                                $connection->call_queue[$queueId] = [];
                            }
                            $MTmessage['body'] = (yield from $API->getTL()->serializeMethod('invokeAfterMsgs', ['msg_ids' => $connection->call_queue[$queueId], 'query' => $MTmessage['body']]));
                            $connection->call_queue[$queueId][$message_id] = $message_id;
                            if (\count($connection->call_queue[$queueId]) > $API->settings->getRpc()->getLimitCallQueue()) {
                                \reset($connection->call_queue[$queueId]);
                                $key = \key($connection->call_queue[$queueId]);
                                unset($connection->call_queue[$queueId][$key]);
                            }
                        }
                        // TODO
                        /*
                                                if ($API->settings['requests']['gzip_encode_if_gt'] !== -1 && ($l = strlen($MTmessage['body'])) > $API->settings['requests']['gzip_encode_if_gt']) {
                                                    if (($g = strlen($gzipped = gzencode($MTmessage['body']))) < $l) {
                                                        $MTmessage['body'] = yield $API->getTL()->serializeObject(['type' => ''], ['_' => 'gzip_packed', 'packed_data' => $gzipped], 'gzipped data');
                                                        $API->logger->logger('Using GZIP compression for ' . $constructor . ', saved ' . ($l - $g) . ' bytes of data, reduced call size by ' . $g * 100 / $l . '%', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                                                    }
                                                    unset($gzipped);
                                                }*/
                    }
                }
                $body_length = \strlen($MTmessage['body']);
                $actual_length = $body_length + 32;
                if ($total_length && $total_length + $actual_length > 32760) {
                    $API->logger->logger('Length overflow, postponing part of payload', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    break;
                }
                $count++;
                $total_length += $actual_length;
                $MTmessage['bytes'] = $body_length;
                $messages[] = $MTmessage;
                $keys[$k] = $message_id;
                $message->setSeqNo($MTmessage['seqno'])->setMsgId($MTmessage['msg_id']);
            }
            $MTmessage = null;
            $acks = \array_slice($connection->ack_queue, 0, self::MAX_COUNT);
            if ($ackCount = \count($acks)) {
                $API->logger->logger("Adding msgs_ack", Logger::ULTRA_VERBOSE);
                $body = (yield from $this->API->getTL()->serializeObject(['type' => ''], ['_' => 'msgs_ack', 'msg_ids' => $acks], 'msgs_ack'));
                $messages[] = ['_' => 'MTmessage', 'msg_id' => $connection->msgIdHandler->generateMessageId(), 'body' => $body, 'seqno' => $connection->generateOutSeqNo(false), 'bytes' => \strlen($body)];
                $count++;
                unset($acks, $body);
            }
            if ($shared->isHttp() && !$has_http_wait) {
                $API->logger->logger("Adding http_wait", Logger::ULTRA_VERBOSE);
                $body = (yield from $this->API->getTL()->serializeObject(['type' => ''], ['_' => 'http_wait', 'max_wait' => 30000, 'wait_after' => 0, 'max_delay' => 0], 'http_wait'));
                $messages[] = ['_' => 'MTmessage', 'msg_id' => $connection->msgIdHandler->generateMessageId(), 'body' => $body, 'seqno' => $connection->generateOutSeqNo(true), 'bytes' => \strlen($body)];
                $count++;
                unset($body);
            }
            if ($count > 1 || $has_seq) {
                $API->logger->logger("Wrapping in msg_container ({$count} messages of total size {$total_length}) as encrypted message for DC {$datacenter}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                $message_id = $connection->msgIdHandler->generateMessageId();
                $connection->pendingOutgoing[$connection->pendingOutgoingKey] = new Container(\array_values($keys));
                $keys[$connection->pendingOutgoingKey++] = $message_id;
                $message_data = (yield from $API->getTL()->serializeObject(['type' => ''], ['_' => 'msg_container', 'messages' => $messages], 'container'));
                $message_data_length = \strlen($message_data);
                $seq_no = $connection->generateOutSeqNo(false);
            } elseif ($count) {
                $message = $messages[0];
                $message_data = $message['body'];
                $message_data_length = $message['bytes'];
                $message_id = $message['msg_id'];
                $seq_no = $message['seqno'];
            } else {
                $API->logger->logger("NO MESSAGE SENT in DC {$datacenter}", \danog\MadelineProto\Logger::WARNING);
                return true;
            }
            unset($messages);
            $plaintext = $shared->getTempAuthKey()->getServerSalt() . $connection->session_id . $message_id . \pack('VV', $seq_no, $message_data_length) . $message_data;
            $padding = \danog\MadelineProto\Tools::posmod(-\strlen($plaintext), 16);
            if ($padding < 12) {
                $padding += 16;
            }
            $padding = \danog\MadelineProto\Tools::random($padding);
            $message_key = \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', \Phabel\Target\Php80\Polyfill::substr($shared->getTempAuthKey()->getAuthKey(), 88, 32) . $plaintext . $padding, true), 8, 16);
            list($aes_key, $aes_iv) = Crypt::aesCalculate($message_key, $shared->getTempAuthKey()->getAuthKey());
            $message = $shared->getTempAuthKey()->getID() . $message_key . Crypt::igeEncrypt($plaintext . $padding, $aes_key, $aes_iv);
            $buffer = (yield $connection->stream->getWriteBuffer(\strlen($message)));
            (yield $buffer->bufferWrite($message));
            $connection->httpSent();
            $API->logger->logger("Sent encrypted payload to DC {$datacenter}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
            if ($ackCount) {
                $connection->ack_queue = \array_slice($connection->ack_queue, $ackCount);
            }
            foreach ($keys as $key => $message_id) {
                $message = $connection->pendingOutgoing[$key];
                unset($connection->pendingOutgoing[$key]);
                $connection->outgoing_messages[$message_id] = $message;
                if ($message->hasPromise()) {
                    $connection->new_outgoing[$message_id] = $message;
                }
                $message->sent();
            }
        } while ($connection->pendingOutgoing && !$skipped);
        if (empty($connection->pendingOutgoing)) {
            $connection->pendingOutgoing = [];
            $connection->pendingOutgoingKey = 'a';
        }
        return $skipped;
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return "write loop in DC {$this->datacenter}";
    }
}<?php

/**
 * RPC call status check loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Connection;

use Amp\Deferred;
use Amp\Loop;
use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\Tools;
/**
 * RPC call status check loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class CheckLoop extends ResumableSignalLoop
{
    use Common;
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        $datacenter = $this->datacenter;
        $connection = $this->connection;
        $shared = $this->datacenterConnection;
        $timeout = $shared->getSettings()->getTimeout();
        $timeoutMs = $timeout * 1000;
        $timeoutResend = $timeout * $timeout;
        // Typically 25 seconds, good enough
        while (true) {
            while (empty($connection->new_outgoing)) {
                if ((yield $this->waitSignal($this->pause()))) {
                    return;
                }
            }
            if (!$connection->hasPendingCalls()) {
                if ((yield $this->waitSignal($this->pause($timeoutMs)))) {
                    return;
                }
                continue;
            }
            $last_msgid = $connection->msgIdHandler->getMaxId(true);
            $last_chunk = $connection->getLastChunk();
            if ($shared->hasTempAuthKey()) {
                $full_message_ids = $connection->getPendingCalls();
                foreach (\array_chunk($full_message_ids, 8192) as $message_ids) {
                    $deferred = new Deferred();
                    $deferred->promise()->onResolve(function ($e, $result) use($message_ids, $API, $connection, $datacenter, $timeoutResend) {
                        if ($e) {
                            $API->logger("Got exception in check loop for DC {$datacenter}");
                            $API->logger((string) $e);
                            return;
                        }
                        $reply = [];
                        foreach (\str_split($result['info']) as $key => $chr) {
                            $message_id = $message_ids[$key];
                            if (!isset($connection->outgoing_messages[$message_id])) {
                                $API->logger->logger('Already got response for and forgot about message ID ' . $message_id);
                                continue;
                            }
                            if (!isset($connection->new_outgoing[$message_id])) {
                                $API->logger->logger('Already got response for ' . $connection->outgoing_messages[$message_id]);
                                continue;
                            }
                            $message = $connection->new_outgoing[$message_id];
                            $chr = \ord($chr);
                            switch ($chr & 7) {
                                case 0:
                                    $API->logger->logger("Wrong message status 0 for {$message}", \danog\MadelineProto\Logger::FATAL_ERROR);
                                    break;
                                case 1:
                                case 2:
                                case 3:
                                    if ($message->getConstructor() === 'msgs_state_req') {
                                        $connection->gotResponseForOutgoingMessage($message);
                                        break;
                                    }
                                    $API->logger->logger("Message {$message} not received by server, resending...", \danog\MadelineProto\Logger::ERROR);
                                    $connection->methodRecall('watcherId', ['message_id' => $message_id, 'postpone' => true]);
                                    break;
                                case 4:
                                    if ($chr & 32) {
                                        if ($message->getSent() + $timeoutResend < \time()) {
                                            $API->logger->logger("Message {$message} received by server and is being processed for way too long, resending request...", \danog\MadelineProto\Logger::ERROR);
                                            $connection->methodRecall('', ['message_id' => $message_id, 'postpone' => true]);
                                        } else {
                                            $API->logger->logger("Message {$message} received by server and is being processed, waiting...", \danog\MadelineProto\Logger::ERROR);
                                        }
                                    } elseif ($chr & 64) {
                                        $API->logger->logger("Message {$message} received by server and was already processed, requesting reply...", \danog\MadelineProto\Logger::ERROR);
                                        $reply[] = $message_id;
                                    } elseif ($chr & 128) {
                                        $API->logger->logger("Message {$message} received by server and was already sent, requesting reply...", \danog\MadelineProto\Logger::ERROR);
                                        $reply[] = $message_id;
                                    } else {
                                        $API->logger->logger("Message {$message} received by server, waiting...", \danog\MadelineProto\Logger::ERROR);
                                        $reply[] = $message_id;
                                    }
                            }
                        }
                        /*
                                                if ($reply) {
                                                    $deferred= new Deferred;
                                                    $deferred->promise()->onResolve(fn($e, $res) => var_dump(ord($res['info'][0])));
                                                    \danog\MadelineProto\Tools::callFork($connection->objectCall('msg_resend_req', ['msg_ids' => $reply], ['postpone' => true, 'promise' => $deferred]));
                                                }*/
                        $connection->flush();
                    });
                    $list = '';
                    // Don't edit this here pls
                    foreach ($message_ids as $message_id) {
                        $list .= $connection->outgoing_messages[$message_id]->getConstructor() . ', ';
                    }
                    $API->logger->logger("Still missing {$list} on DC {$datacenter}, sending state request", \danog\MadelineProto\Logger::ERROR);
                    yield from $connection->objectCall('msgs_state_req', ['msg_ids' => $message_ids], ['promise' => $deferred]);
                }
            } else {
                foreach ($connection->new_outgoing as $message_id => $message) {
                    if ($message->wasSent() && $message->getSent() + $timeout < \time() && $message->isUnencrypted()) {
                        $API->logger->logger("Still missing {$message} on DC {$datacenter}, resending", \danog\MadelineProto\Logger::ERROR);
                        $connection->methodRecall('', ['message_id' => $message->getMsgId(), 'postpone' => true]);
                    }
                }
                $connection->flush();
            }
            if ((yield $this->waitSignal($this->pause($timeoutMs)))) {
                return;
            }
            if ($connection->msgIdHandler->getMaxId(true) === $last_msgid && $connection->getLastChunk() === $last_chunk) {
                $API->logger->logger("We did not receive a response for {$timeout} seconds: reconnecting and exiting check loop on DC {$datacenter}");
                //$this->exitedLoop();
                Tools::callForkDefer($connection->reconnect());
                return;
            }
        }
    }
    /**
     * Loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return "check loop in DC {$this->datacenter}";
    }
}<?php

/**
 * Update feeder loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Update;

use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\SecurityException;
/**
 * Secret feed loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class SecretFeedLoop extends ResumableSignalLoop
{
    use InternalLoop {
        __construct as private init;
    }
    /**
     * Incoming secret updates array.
     */
    private array $incomingUpdates = [];
    /**
     * Secret chat ID.
     */
    private int $secretId;
    /**
     * Constructor.
     *
     * @param MTProto $API API instance
     * @param integer $secretId Secret chat ID
     */
    public function __construct(MTProto $API, int $secretId)
    {
        $this->init($API);
        $this->secretId = $secretId;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        while (!$API->hasAllAuth()) {
            if ((yield $this->waitSignal($this->pause()))) {
                return;
            }
        }
        while (true) {
            while (!$API->hasAllAuth()) {
                if ((yield $this->waitSignal($this->pause()))) {
                    return;
                }
            }
            if ((yield $this->waitSignal($this->pause()))) {
                return;
            }
            $API->logger->logger("Resumed {$this}");
            while ($this->incomingUpdates) {
                $updates = $this->incomingUpdates;
                $this->incomingUpdates = [];
                foreach ($updates as $update) {
                    try {
                        if (!(yield from $API->handleEncryptedUpdate($update))) {
                            $API->logger->logger("Secret chat deleted, exiting {$this}...");
                            unset($API->secretFeeders[$this->secretId]);
                            return;
                        }
                    } catch (SecurityException $e) {
                        $API->logger->logger("Secret chat deleted, exiting {$this}...");
                        unset($API->secretFeeders[$this->secretId]);
                        throw $e;
                    }
                }
                $updates = null;
            }
        }
    }
    /**
     * Feed incoming update to loop.
     *
     * @param array $update
     * @return void
     */
    public function feed(array $update) : void
    {
        $this->incomingUpdates[] = $update;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return "secret chat feed loop {$this->secretId}";
    }
}<?php

/**
 * Update feeder loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Update;

use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProtoTools\UpdatesState;
/**
 * Update feed loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class FeedLoop extends ResumableSignalLoop
{
    use InternalLoop {
        __construct as private init;
    }
    /**
     * Main loop ID.
     */
    const GENERIC = 0;
    /**
     * Incoming updates array.
     */
    private array $incomingUpdates = [];
    /**
     * Parsed updates array.
     */
    private array $parsedUpdates = [];
    /**
     * Channel ID.
     */
    private int $channelId;
    /**
     * Update loop.
     *
     * @var UpdateLoop
     */
    private ?UpdateLoop $updater = null;
    /**
     * Update state.
     */
    private ?UpdatesState $state = null;
    /**
     * Constructor.
     *
     * @param MTProto $API API instance
     * @param integer $channelId Constructor
     */
    public function __construct(MTProto $API, int $channelId = 0)
    {
        $this->init($API);
        $this->channelId = $channelId;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        $this->updater = $API->updaters[$this->channelId];
        while (!$API->hasAllAuth()) {
            if ((yield $this->waitSignal($this->pause()))) {
                return;
            }
        }
        $this->state = $this->channelId === self::GENERIC ? yield from $API->loadUpdateState() : $API->loadChannelState($this->channelId);
        while (true) {
            while (!$API->hasAllAuth()) {
                if ((yield $this->waitSignal($this->pause()))) {
                    return;
                }
            }
            if ((yield $this->waitSignal($this->pause()))) {
                return;
            }
            $API->logger->logger("Resumed {$this}");
            while ($this->incomingUpdates) {
                $updates = $this->incomingUpdates;
                $this->incomingUpdates = [];
                yield from $this->parse($updates);
                $updates = null;
            }
            while ($this->parsedUpdates) {
                $parsedUpdates = $this->parsedUpdates;
                $this->parsedUpdates = [];
                foreach ($parsedUpdates as $update) {
                    yield from $API->saveUpdate($update);
                }
                $parsedUpdates = null;
                $this->API->signalUpdate();
            }
        }
    }
    /**
     *
     */
    public function parse(array $updates) : \Generator
    {
        \reset($updates);
        while ($updates) {
            $key = \key($updates);
            $update = $updates[$key];
            unset($updates[$key]);
            if ($update['_'] === 'updateChannelTooLong') {
                $this->API->logger->logger('Got channel too long update, getting difference...', \danog\MadelineProto\Logger::VERBOSE);
                (yield $this->updater->resume());
                continue;
            }
            if (isset($update['pts'], $update['pts_count'])) {
                $logger = function ($msg) use($update) : void {
                    $pts_count = $update['pts_count'];
                    $mid = isset($update['message']['id']) ? $update['message']['id'] : '-';
                    $mypts = $this->state->pts();
                    $computed = $mypts + $pts_count;
                    $this->API->logger->logger("{$msg}. My pts: {$mypts}, remote pts: {$update['pts']}, computed pts: {$computed}, msg id: {$mid}, channel id: {$this->channelId}", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                };
                $result = $this->state->checkPts($update);
                if ($result < 0) {
                    $logger('PTS duplicate');
                    continue;
                }
                if ($result > 0) {
                    $logger('PTS hole');
                    $this->updater->setLimit($this->state->pts() + $result);
                    (yield $this->updater->resume());
                    $updates = \array_merge($this->incomingUpdates, $updates);
                    $this->incomingUpdates = [];
                    continue;
                }
                if (isset($update['message']['id'], $update['message']['peer_id']) && !\in_array($update['_'], ['updateEditMessage', 'updateEditChannelMessage', 'updateMessageID'])) {
                    if (!$this->API->checkMsgId($update['message'])) {
                        $logger('MSGID duplicate');
                        continue;
                    }
                }
                $logger('PTS OK');
                $this->state->pts($update['pts']);
            }
            $this->save($update);
        }
    }
    /**
     *
     */
    public function feed(array $updates) : \Generator
    {
        $result = [];
        foreach ($updates as $update) {
            $result[yield from $this->feedSingle($update)] = true;
        }
        return $result;
    }
    /**
     *
     */
    public function feedSingle(array $update) : \Generator
    {
        $channelId = self::GENERIC;
        switch ($update['_']) {
            case 'updateNewChannelMessage':
            case 'updateEditChannelMessage':
                $channelId = isset($update['message']['peer_id']['channel_id']) ? $update['message']['peer_id']['channel_id'] : self::GENERIC;
                if (!$channelId) {
                    return false;
                }
                break;
            case 'updateChannelWebPage':
            case 'updateDeleteChannelMessages':
                $channelId = $update['channel_id'];
                break;
            case 'updateChannelTooLong':
                $channelId = isset($update['channel_id']) ? $update['channel_id'] : self::GENERIC;
                if (!isset($update['pts'])) {
                    $update['pts'] = 1;
                }
                break;
        }
        if ($channelId && !$this->API->getChannelStates()->has($channelId)) {
            $this->API->loadChannelState($channelId, $update);
            if (!isset($this->API->feeders[$channelId])) {
                $this->API->feeders[$channelId] = new self($this->API, $channelId);
            }
            if (!isset($this->API->updaters[$channelId])) {
                $this->API->updaters[$channelId] = new UpdateLoop($this->API, $channelId);
            }
            $this->API->feeders[$channelId]->start();
            $this->API->updaters[$channelId]->start();
        }
        switch ($update['_']) {
            case 'updateNewMessage':
            case 'updateEditMessage':
            case 'updateNewChannelMessage':
            case 'updateEditChannelMessage':
                $to = false;
                $from = false;
                $via_bot = false;
                $entities = false;
                if ($update['message']['_'] !== 'messageEmpty' && (($from = isset($update['message']['from_id']) && !(yield from $this->API->peerIsset($update['message']['from_id']))) || ($to = !(yield from $this->API->peerIsset($update['message']['peer_id']))) || ($via_bot = isset($update['message']['via_bot_id']) && !(yield from $this->API->peerIsset($update['message']['via_bot_id']))) || ($entities = isset($update['message']['entities']) && !(yield from $this->API->entitiesPeerIsset($update['message']['entities']))))) {
                    $log = '';
                    if ($from) {
                        $from_id = $this->API->getId($update['message']['from_id']);
                        $log .= "from_id {$from_id}, ";
                    }
                    if ($to) {
                        $log .= 'peer_id ' . \json_encode($update['message']['peer_id']) . ', ';
                    }
                    if ($via_bot) {
                        $log .= "via_bot {$update['message']['via_bot_id']}, ";
                    }
                    if ($entities) {
                        $log .= 'entities ' . \json_encode($update['message']['entities']) . ', ';
                    }
                    $this->API->logger->logger("Not enough data: for message update {$log}, getting difference...", \danog\MadelineProto\Logger::VERBOSE);
                    $update = ['_' => 'updateChannelTooLong'];
                    if ($channelId && $to) {
                        $channelId = self::GENERIC;
                    }
                }
                break;
            default:
                if ($channelId && !(yield from $this->API->peerIsset($this->API->toSupergroup($channelId)))) {
                    $this->API->logger->logger('Skipping update, I do not have the channel id ' . $channelId, \danog\MadelineProto\Logger::ERROR);
                    return false;
                }
                break;
        }
        if ($channelId !== $this->channelId) {
            if (isset($this->API->feeders[$channelId])) {
                return yield from $this->API->feeders[$channelId]->feedSingle($update);
            } elseif ($this->channelId) {
                return yield from $this->API->feeders[self::GENERIC]->feedSingle($update);
            }
        }
        $this->API->logger->logger('Was fed an update of type ' . $update['_'] . " in {$this}...", \danog\MadelineProto\Logger::ULTRA_VERBOSE);
        $this->incomingUpdates[] = $update;
        return $this->channelId;
    }
    /**
     *
     */
    public function save($update) : void
    {
        $this->parsedUpdates[] = $update;
    }
    /**
     *
     */
    public function saveMessages($messages) : void
    {
        foreach ($messages as $message) {
            if (!$this->API->checkMsgId($message)) {
                $this->API->logger->logger("MSGID duplicate ({$message['id']}) in {$this}");
                continue;
            }
            if ($message['_'] !== 'messageEmpty') {
                $this->API->logger->logger('Getdiff fed me message of type ' . $message['_'] . " in {$this}...", \danog\MadelineProto\Logger::VERBOSE);
            }
            $this->parsedUpdates[] = ['_' => $this->channelId === self::GENERIC ? 'updateNewMessage' : 'updateNewChannelMessage', 'message' => $message, 'pts' => -1, 'pts_count' => -1];
        }
    }
    /**
     *
     */
    public function __toString() : string
    {
        return !$this->channelId ? 'update feed loop generic' : "update feed loop channel {$this->channelId}";
    }
}<?php

/**
 * Update feeder loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Update;

use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\MTProtoTools\UpdatesState;
/**
 * update feed loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class SeqLoop extends ResumableSignalLoop
{
    use InternalLoop;
    /**
     * Incoming updates.
     */
    private array $incomingUpdates = [];
    /**
     * Update feeder.
     */
    private ?FeedLoop $feeder = null;
    /**
     * Pending updates.
     */
    private array $pendingWakeups = [];
    /**
     * State.
     */
    private ?UpdatesState $state = null;
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        $this->feeder = $API->feeders[FeedLoop::GENERIC];
        while (!$API->hasAllAuth()) {
            if ((yield $this->waitSignal($this->pause()))) {
                return;
            }
        }
        $this->state = (yield from $API->loadUpdateState());
        while (true) {
            while (!$API->hasAllAuth()) {
                if ((yield $this->waitSignal($this->pause()))) {
                    return;
                }
            }
            if ((yield $this->waitSignal($this->pause()))) {
                return;
            }
            while ($this->incomingUpdates) {
                $updates = $this->incomingUpdates;
                $this->incomingUpdates = [];
                yield from $this->parse($updates);
                $updates = null;
            }
            while ($this->pendingWakeups) {
                \reset($this->pendingWakeups);
                $channelId = \key($this->pendingWakeups);
                unset($this->pendingWakeups[$channelId]);
                if (isset($this->API->feeders[$channelId])) {
                    $this->API->feeders[$channelId]->resume();
                }
            }
        }
    }
    /**
     *
     */
    public function parse(array $updates) : \Generator
    {
        \reset($updates);
        while ($updates) {
            $options = [];
            $key = \key($updates);
            $update = $updates[$key];
            unset($updates[$key]);
            $options = $update['options'];
            $seq_start = $options['seq_start'];
            $seq_end = $options['seq_end'];
            $result = $this->state->checkSeq($seq_start);
            if ($result > 0) {
                $this->API->logger->logger('Seq hole. seq_start: ' . $seq_start . ' != cur seq: ' . ($this->state->seq() + 1), \danog\MadelineProto\Logger::ERROR);
                (yield $this->pause(1000));
                if (!$this->incomingUpdates) {
                    (yield $this->API->updaters[UpdateLoop::GENERIC]->resume());
                }
                $this->incomingUpdates = \array_merge($this->incomingUpdates, [$update], $updates);
                continue;
            }
            if ($result < 0) {
                $this->API->logger->logger('Seq too old. seq_start: ' . $seq_start . ' != cur seq: ' . ($this->state->seq() + 1), \danog\MadelineProto\Logger::ERROR);
                continue;
            }
            $this->state->seq($seq_end);
            if (isset($options['date'])) {
                $this->state->date($options['date']);
            }
            yield from $this->save($update);
        }
    }
    /**
     * @param (array | mixed)[] $updates
     */
    public function feed(array $updates) : void
    {
        $this->API->logger->logger('Was fed updates of type ' . $updates['_'] . '...', \danog\MadelineProto\Logger::VERBOSE);
        $this->incomingUpdates[] = $updates;
    }
    /**
     * @var array{updates: array} $updates
     */
    public function save(array $updates) : \Generator
    {
        $this->pendingWakeups += (yield from $this->feeder->feed($updates['updates']));
    }
    /**
     * @param true[] $wakeups
     */
    public function addPendingWakeups(array $wakeups) : void
    {
        $this->pendingWakeups += $wakeups;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return 'update seq loop';
    }
}<?php

/**
 * Update loop.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Loop\Update;

use danog\Loop\ResumableSignalLoop;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Loop\InternalLoop;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\PTSException;
use danog\MadelineProto\RPCErrorException;
/**
 * Update loop.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class UpdateLoop extends ResumableSignalLoop
{
    use InternalLoop {
        __construct as private init;
    }
    /**
     * Main loop ID.
     */
    const GENERIC = 0;
    private $toPts;
    /**
     * Loop name.
     */
    private int $channelId;
    /**
     * Feed loop.
     */
    private ?FeedLoop $feeder = null;
    /**
     * Constructor.
     *
     * @param MTProto $API
     * @param integer $channelId
     */
    public function __construct(MTProto $API, int $channelId)
    {
        $this->init($API);
        $this->channelId = $channelId;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $API = $this->API;
        $feeder = $this->feeder = $API->feeders[$this->channelId];
        while (!$API->hasAllAuth()) {
            if ((yield $this->waitSignal($this->pause()))) {
                $API->logger->logger("Exiting {$this} due to signal");
                return;
            }
        }
        $this->state = $state = $this->channelId === self::GENERIC ? yield from $API->loadUpdateState() : $API->loadChannelState($this->channelId);
        $timeout = 30 * 1000;
        $first = true;
        while (true) {
            while (!$API->hasAllAuth()) {
                if ((yield $this->waitSignal($this->pause()))) {
                    $API->logger->logger("Exiting {$this} due to signal");
                    return;
                }
            }
            $result = [];
            $toPts = $this->toPts;
            $this->toPts = null;
            while (true) {
                if ($this->channelId) {
                    $API->logger->logger('Resumed and fetching ' . $this->channelId . ' difference...', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    if ($state->pts() <= 1) {
                        $limit = 10;
                    } elseif ($API->authorization['user']['bot']) {
                        $limit = 100000;
                    } else {
                        $limit = 100;
                    }
                    $request_pts = $state->pts();
                    try {
                        $difference = (yield from $API->methodCallAsyncRead('updates.getChannelDifference', ['channel' => 'channel#' . $this->channelId, 'filter' => ['_' => 'channelMessagesFilterEmpty'], 'pts' => $request_pts, 'limit' => $limit, 'force' => true], ['datacenter' => $API->datacenter->curdc, 'postpone' => $first]));
                    } catch (RPCErrorException $e) {
                        if (\in_array($e->rpc, ['CHANNEL_PRIVATE', 'CHAT_FORBIDDEN', 'CHANNEL_INVALID', 'USER_BANNED_IN_CHANNEL'])) {
                            $feeder->signal(true);
                            unset($API->updaters[$this->channelId], $API->feeders[$this->channelId]);
                            $API->getChannelStates()->remove($this->channelId);
                            $API->logger->logger("Channel private, exiting {$this}");
                            return true;
                        }
                        throw $e;
                    } catch (Exception $e) {
                        if (\in_array($e->getMessage(), ['This peer is not present in the internal peer database'])) {
                            $feeder->signal(true);
                            $API->getChannelStates()->remove($this->channelId);
                            unset($API->updaters[$this->channelId], $API->feeders[$this->channelId]);
                            $API->logger->logger("Channel private, exiting {$this}");
                            return true;
                        }
                        throw $e;
                    } catch (PTSException $e) {
                        $API->logger->logger("Got PTS exception, exiting update loop for {$this}: {$e}", Logger::FATAL_ERROR);
                        return true;
                    }
                    if (isset($difference['timeout'])) {
                        $timeout = $difference['timeout'];
                    }
                    $timeout = \min(10 * 1000, $timeout);
                    $API->logger->logger('Got ' . $difference['_'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    switch ($difference['_']) {
                        case 'updates.channelDifferenceEmpty':
                            $state->update($difference);
                            unset($difference);
                            break 2;
                        case 'updates.channelDifference':
                            if ($request_pts >= $difference['pts'] && $request_pts > 1) {
                                $API->logger->logger("The PTS ({$difference['pts']}) I got with getDifference is smaller than the PTS I requested " . $state->pts() . ', using ' . ($state->pts() + 1), \danog\MadelineProto\Logger::VERBOSE);
                                $difference['pts'] = $request_pts + 1;
                            }
                            $result += (yield from $feeder->feed($difference['other_updates']));
                            $state->update($difference);
                            $feeder->saveMessages($difference['new_messages']);
                            if (!$difference['final']) {
                                if ($difference['pts'] >= $toPts) {
                                    unset($difference);
                                    break 2;
                                }
                                unset($difference);
                                break;
                            }
                            unset($difference);
                            break 2;
                        case 'updates.channelDifferenceTooLong':
                            if (isset($difference['dialog']['pts'])) {
                                $difference['pts'] = $difference['dialog']['pts'];
                            }
                            $state->update($difference);
                            $feeder->saveMessages($difference['messages']);
                            unset($difference);
                            break;
                        default:
                            throw new \danog\MadelineProto\Exception('Unrecognized update difference received: ' . \var_export($difference, true));
                    }
                } else {
                    $API->logger->logger('Resumed and fetching normal difference...', \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    $difference = (yield from $API->methodCallAsyncRead('updates.getDifference', ['pts' => $state->pts(), 'date' => $state->date(), 'qts' => $state->qts()], $API->settings->getDefaultDcParams()));
                    $API->logger->logger('Got ' . $difference['_'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
                    switch ($difference['_']) {
                        case 'updates.differenceEmpty':
                            $state->update($difference);
                            unset($difference);
                            break 2;
                        case 'updates.difference':
                            $state->qts($difference['state']['qts']);
                            foreach ($difference['new_encrypted_messages'] as &$encrypted) {
                                $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
                            }
                            $result += (yield from $feeder->feed($difference['other_updates']));
                            $result += (yield from $feeder->feed($difference['new_encrypted_messages']));
                            $state->update($difference['state']);
                            $feeder->saveMessages($difference['new_messages']);
                            unset($difference);
                            break 2;
                        case 'updates.differenceSlice':
                            $state->qts($difference['intermediate_state']['qts']);
                            foreach ($difference['new_encrypted_messages'] as &$encrypted) {
                                $encrypted = ['_' => 'updateNewEncryptedMessage', 'message' => $encrypted];
                            }
                            $result += (yield from $feeder->feed($difference['other_updates']));
                            $result += (yield from $feeder->feed($difference['new_encrypted_messages']));
                            $state->update($difference['intermediate_state']);
                            $feeder->saveMessages($difference['new_messages']);
                            if ($difference['intermediate_state']['pts'] >= $toPts) {
                                unset($difference);
                                break 2;
                            }
                            unset($difference);
                            break;
                        case 'updates.differenceTooLong':
                            $state->update($difference);
                            unset($difference);
                            break;
                        default:
                            throw new \danog\MadelineProto\Exception('Unrecognized update difference received: ' . \var_export($difference, true));
                    }
                }
            }
            $API->logger->logger("Finished parsing updates in {$this}, now resuming feeders", Logger::ULTRA_VERBOSE);
            foreach ($result as $channelId => $_) {
                $API->feeders[$channelId]->resumeDefer();
            }
            $API->logger->logger("Finished resuming feeders in {$this}, signaling updates", Logger::ULTRA_VERBOSE);
            $API->signalUpdate();
            $API->logger->logger("Finished signaling updates in {$this}, pausing", Logger::ULTRA_VERBOSE);
            $first = false;
            if ((yield $this->waitSignal($this->pause($timeout * 1000)))) {
                $API->logger->logger("Exiting {$this} due to signal");
                return;
            }
        }
    }
    /**
     *
     */
    public function setLimit(int $toPts) : void
    {
        $this->toPts = $toPts;
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->channelId ? "getUpdate loop channel {$this->channelId}" : 'getUpdate loop generic';
    }
}<?php

/**
 * Logger module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\ByteStream\ResourceOutputStream;
use Amp\Failure;
use Amp\Loop;
use danog\MadelineProto\Settings\Logger as SettingsLogger;
use Psr\Log\LoggerInterface;
use function Amp\ByteStream\getStderr;
use function Amp\ByteStream\getStdout;
/**
 * Logger class.
 */
class Logger
{
    /**
     * @internal ANSI foreground color escapes
     */
    const FOREGROUND = ['default' => 39, 'black' => 30, 'red' => 31, 'green' => 32, 'yellow' => 33, 'blue' => 34, 'magenta' => 35, 'cyan' => 36, 'light_gray' => 37, 'dark_gray' => 90, 'light_red' => 91, 'light_green' => 92, 'light_yellow' => 93, 'light_blue' => 94, 'light_magenta' => 95, 'light_cyan' => 96, 'white' => 97];
    /**
     * @internal ANSI background color escapes
     */
    const BACKGROUND = ['default' => 49, 'black' => 40, 'red' => 41, 'magenta' => 45, 'yellow' => 43, 'green' => 42, 'blue' => 44, 'cyan' => 46, 'light_gray' => 47, 'dark_gray' => 100, 'light_red' => 101, 'light_green' => 102, 'light_yellow' => 103, 'light_blue' => 104, 'light_magenta' => 105, 'light_cyan' => 106, 'white' => 107];
    /**
     * @internal ANSI modifier escapes
     */
    const SET = ['bold' => 1, 'dim' => 2, 'underlined' => 3, 'blink' => 4, 'reverse' => 5, 'hidden' => 6];
    /**
     * @internal ANSI reset modifier escapes
     */
    const RESET = ['all' => 0, 'bold' => 21, 'dim' => 22, 'underlined' => 24, 'blink' => 25, 'reverse' => 26, 'hidden' => 28];
    /**
     * Logging mode.
     *
     * @var integer
     */
    public $mode = 0;
    /**
     * Optional logger parameter.
     *
     * @var null|string|callable
     */
    public $optional = null;
    /**
     * Logger prefix.
     *
     * @var string
     */
    public $prefix = '';
    /**
     * Logging level.
     *
     * @var integer
     */
    public $level = self::NOTICE;
    /**
     * Logging colors.
     *
     * @var array
     */
    public $colors = [];
    /**
     * Newline.
     *
     * @var string
     */
    public $newline = "\n";
    /**
     * Logfile.
     *
     * @var ResourceOutputStream
     */
    public $stdout;
    /**
     * Default logger instance.
     *
     * @var self
     */
    public static $default;
    /**
     * Whether the AGPL notice was printed.
     *
     * @var boolean
     */
    public static $printed = false;
    /**
     * Log rotation loop ID.
     */
    private string $rotateId = '';
    /**
     * PSR logger.
     */
    private PsrLogger $psr;
    /**
     * Ultra verbose logging.
     *
     * @internal
     */
    const ULTRA_VERBOSE = 5;
    /**
     * Verbose logging.
     *
     * @internal
     */
    const VERBOSE = 4;
    /**
     * Notice logging.
     *
     * @internal
     */
    const NOTICE = 3;
    /**
     * Warning logging.
     *
     * @internal
     */
    const WARNING = 2;
    /**
     * Error logging.
     *
     * @internal
     */
    const ERROR = 1;
    /**
     * Log only fatal errors.
     *
     * @internal
     */
    const FATAL_ERROR = 0;
    /**
     * Disable logger (DEPRECATED).
     *
     * @internal
     * @deprecated
     */
    const NO_LOGGER = 0;
    /**
     * Default logger (syslog).
     *
     * @internal
     */
    const DEFAULT_LOGGER = 1;
    /**
     * File logger.
     *
     * @internal
     */
    const FILE_LOGGER = 2;
    /**
     * Echo logger.
     *
     * @internal
     */
    const ECHO_LOGGER = 3;
    /**
     * Callable logger.
     *
     * @internal
     */
    const CALLABLE_LOGGER = 4;
    /**
     * Ultra verbose level.
     */
    const LEVEL_ULTRA_VERBOSE = self::ULTRA_VERBOSE;
    /**
     * Verbose level.
     */
    const LEVEL_VERBOSE = self::VERBOSE;
    /**
     * Notice level.
     */
    const LEVEL_NOTICE = self::NOTICE;
    /**
     * Warning level.
     */
    const LEVEL_WARNING = self::WARNING;
    /**
     * Error level.
     */
    const LEVEL_ERROR = self::ERROR;
    /**
     * Fatal error level.
     */
    const LEVEL_FATAL = self::FATAL_ERROR;
    /**
     * Default logger (syslog).
     */
    const LOGGER_DEFAULT = self::DEFAULT_LOGGER;
    /**
     * Echo logger.
     */
    const LOGGER_ECHO = self::ECHO_LOGGER;
    /**
     * File logger.
     */
    const LOGGER_FILE = self::FILE_LOGGER;
    /**
     * Callable logger.
     */
    const LOGGER_CALLABLE = self::CALLABLE_LOGGER;
    /**
     * Construct global static logger from MadelineProto settings.
     *
     * @param SettingsLogger $settings Settings instance
     *
     * @return self
     */
    public static function constructorFromSettings(SettingsLogger $settings) : self
    {
        return self::$default = new self($settings);
    }
    /**
     * Construct logger.
     *
     * @param SettingsLogger $settings
     * @param string $prefix
     */
    public function __construct(SettingsLogger $settings, string $prefix = '')
    {
        $this->psr = new PsrLogger($this);
        $this->prefix = $prefix === '' ? '' : ', ' . $prefix;
        $this->mode = $settings->getType();
        $this->optional = $settings->getExtra();
        $this->level = $settings->getLevel();
        $maxSize = $settings->getMaxSize();
        if ($this->mode === self::FILE_LOGGER) {
            if (!$this->optional || !\file_exists(\pathinfo($this->optional, PATHINFO_DIRNAME))) {
                $this->optional = Magic::$script_cwd . DIRECTORY_SEPARATOR . 'MadelineProto.log';
            }
            if (!\str_ends_with($this->optional, '.log')) {
                $this->optional .= '.log';
            }
            if ($maxSize !== -1 && \file_exists($this->optional) && \filesize($this->optional) > $maxSize) {
                \file_put_contents($this->optional, '');
            }
        }
        $this->colors[self::ULTRA_VERBOSE] = \implode(';', [self::FOREGROUND['light_gray'], self::SET['dim']]);
        $this->colors[self::VERBOSE] = \implode(';', [self::FOREGROUND['green'], self::SET['bold']]);
        $this->colors[self::NOTICE] = \implode(';', [self::FOREGROUND['yellow'], self::SET['bold']]);
        $this->colors[self::WARNING] = \implode(';', [self::FOREGROUND['white'], self::SET['dim'], self::BACKGROUND['red']]);
        $this->colors[self::ERROR] = \implode(';', [self::FOREGROUND['white'], self::SET['bold'], self::BACKGROUND['red']]);
        $this->colors[self::FATAL_ERROR] = \implode(';', [self::FOREGROUND['red'], self::SET['bold'], self::BACKGROUND['light_gray']]);
        $this->newline = PHP_EOL;
        if ($this->mode === self::ECHO_LOGGER) {
            $this->stdout = getStdout();
            if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
                $this->newline = '<br>' . $this->newline;
            }
        } elseif ($this->mode === self::FILE_LOGGER) {
            Snitch::logFile($this->optional);
            $this->stdout = new ResourceOutputStream(\fopen($this->optional, 'a'));
            if ($maxSize !== -1) {
                $optional =& $this->optional;
                $stdout =& $this->stdout;
                $this->rotateId = Loop::repeat(10 * 1000, static function () use($maxSize, $optional, &$stdout) {
                    \clearstatcache(true, $optional);
                    if (\file_exists($optional) && \filesize($optional) >= $maxSize) {
                        \ftruncate($stdout->getResource(), 0);
                        self::log("Automatically truncated logfile to {$maxSize}");
                    }
                });
                Loop::unreference($this->rotateId);
            }
        } elseif ($this->mode === self::DEFAULT_LOGGER) {
            $result = @\ini_get('error_log');
            if ($result === 'syslog') {
                $this->stdout = getStderr();
            } elseif ($result) {
                $this->stdout = new ResourceOutputStream(\fopen($result, 'a+'));
            } else {
                $this->stdout = getStderr();
            }
        }
        self::$default = $this;
        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
            try {
                \Phabel\Target\Php80\Polyfill::error_reporting(E_ALL);
                \ini_set('log_errors', "1");
                \ini_set('error_log', $this->mode === self::FILE_LOGGER ? $this->optional : Magic::$script_cwd . DIRECTORY_SEPARATOR . 'MadelineProto.log');
                \error_log('Enabled PHP logging');
            } catch (\danog\MadelineProto\Exception $e) {
                $this->logger('Could not enable PHP logging');
            }
        }
    }
    /**
     * Destructor function.
     */
    public function __destruct()
    {
        if ($this->rotateId) {
            Loop::cancel($this->rotateId);
        }
    }
    /**
     * Log a message.
     *
     * @param mixed $param Message
     * @param int $level Logging level
     *
     * @return void
     */
    public static function log($param, int $level = self::NOTICE)
    {
        if (!\is_null(self::$default)) {
            self::$default->logger($param, $level, \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php'));
        } else {
            echo $param . PHP_EOL;
        }
    }
    /**
     * Log a message.
     *
     * @param mixed $param Message to log
     * @param int $level Logging level
     * @param string $file File that originated the message
     *
     * @return void
     */
    public function logger($param, int $level = self::NOTICE, string $file = '') : void
    {
        if ($level > $this->level) {
            return;
        }
        if (Magic::$suspendPeriodicLogging) {
            Magic::$suspendPeriodicLogging->promise()->onResolve(fn() => $this->logger($param, $level, $file));
            return;
        }
        if (!self::$printed) {
            self::$printed = true;
            $this->colors[self::NOTICE] = \implode(';', [self::FOREGROUND['light_gray'], self::SET['bold'], self::BACKGROUND['blue']]);
            $this->logger('MadelineProto');
            $this->logger('Copyright (C) 2016-2020 Daniil Gentili');
            $this->logger('Licensed under AGPLv3');
            $this->logger('https://github.com/danog/MadelineProto');
            $this->colors[self::NOTICE] = \implode(';', [self::FOREGROUND['yellow'], self::SET['bold']]);
        }
        if ($this->mode === self::CALLABLE_LOGGER) {
            \call_user_func_array($this->optional, [$param, $level]);
            return;
        }
        $prefix = $this->prefix;
        if ($param instanceof \Throwable) {
            $param = (string) $param;
        } elseif (!\is_string($param)) {
            $param = \json_encode($param, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
        }
        if (empty($file)) {
            $file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
        }
        $param = \str_pad($file . $prefix . ': ', 16 + \strlen($prefix)) . "\t" . $param;
        if ($this->mode === self::DEFAULT_LOGGER) {
            if ($this->stdout->write($param . $this->newline) instanceof Failure) {
                \error_log($param);
            }
            return;
        }
        $param = Magic::$isatty ? "\x1b[" . $this->colors[$level] . 'm' . $param . "\x1b[0m" . $this->newline : $param . $this->newline;
        if ($this->stdout->write($param) instanceof Failure) {
            switch ($this->mode) {
                case self::ECHO_LOGGER:
                    echo $param;
                    break;
                case self::FILE_LOGGER:
                    \file_put_contents($this->optional, $param, FILE_APPEND);
                    break;
            }
        }
    }
    /**
     * Get PSR logger.
     *
     * @return LoggerInterface
     */
    public function getPsrLogger() : LoggerInterface
    {
        return $this->psr;
    }
}<?php

/**
 * PTSException module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * Internal error indicating a problem with Telegram's servers.
 */
class PTSException extends \Exception
{
    use TL\PrettyException;
    /**
     *
     */
    public function __toString()
    {
        return \get_class($this) . ($this->message !== '' ? ': ' : '') . $this->message . PHP_EOL . 'TL Trace:' . PHP_EOL . PHP_EOL . $this->getTLTrace() . PHP_EOL;
    }
    /**
     *
     */
    public function __construct($message, $file = '')
    {
        parent::__construct($message);
        $this->prettifyTL($file);
    }
}<?php

/**
 * ApiStart module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\ApiWrappers;

use danog\MadelineProto\Lang;
use danog\MadelineProto\Magic;
use danog\MadelineProto\MyTelegramOrgWrapper;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools;
use function Amp\ByteStream\getStdout;
/**
 * Manages simple logging in and out.
 */
trait Start
{
    /**
     * Start API ID generation process.
     *
     * @param Settings $settings Settings
     *
     * @return \Generator
     */
    private function APIStart(Settings $settings) : \Generator
    {
        if (Magic::$isIpcWorker) {
            throw new \danog\MadelineProto\Exception('Not inited!');
        }
        if ($this->getWebAPITemplate() === 'legacy') {
            $this->setWebAPITemplate($settings->getTemplates()->getHtmlTemplate());
        }
        $app = null;
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            $stdout = getStdout();
            $prepare = Lang::$current_lang['apiChooseManualAuto'] . PHP_EOL;
            $prepare .= \sprintf(Lang::$current_lang['apiChooseManualAutoTip'], 'https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id');
            $prepare .= PHP_EOL;
            (yield $stdout->write($prepare));
            if (\strpos((yield Tools::readLine(Lang::$current_lang['apiChoosePrompt'])), 'm') !== false) {
                (yield $stdout->write("1) " . Lang::$current_lang['apiManualInstructions0'] . PHP_EOL));
                (yield $stdout->write("2) " . Lang::$current_lang['apiManualInstructions1'] . PHP_EOL));
                (yield $stdout->write("3) "));
                foreach (['App title', 'Short name', 'URL', 'Platform', 'Description'] as $k => $key) {
                    (yield $stdout->write($k ? "    {$key}: " : "{$key}: "));
                    (yield $stdout->write(Lang::$current_lang["apiAppInstructionsManual{$k}"] . PHP_EOL));
                }
                (yield $stdout->write("4) " . Lang::$current_lang['apiManualInstructions2'] . PHP_EOL));
                $app['api_id'] = (yield Tools::readLine("5) " . Lang::$current_lang['apiManualPrompt0']));
                $app['api_hash'] = (yield Tools::readLine("6) " . Lang::$current_lang['apiManualPrompt1']));
                return $app;
            }
            $this->myTelegramOrgWrapper = new \danog\MadelineProto\MyTelegramOrgWrapper($settings);
            yield from $this->myTelegramOrgWrapper->login((yield Tools::readLine(Lang::$current_lang['apiAutoPrompt0'])));
            yield from $this->myTelegramOrgWrapper->completeLogin((yield Tools::readLine(Lang::$current_lang['apiAutoPrompt1'])));
            if (!(yield from $this->myTelegramOrgWrapper->hasApp())) {
                $app_title = (yield Tools::readLine(Lang::$current_lang['apiAppInstructionsAuto0']));
                $short_name = (yield Tools::readLine(Lang::$current_lang['apiAppInstructionsAuto1']));
                $url = (yield Tools::readLine(Lang::$current_lang['apiAppInstructionsAuto2']));
                $description = (yield Tools::readLine(Lang::$current_lang['apiAppInstructionsAuto4']));
                $app = (yield from $this->myTelegramOrgWrapper->createApp(['app_title' => $app_title, 'app_shortname' => $short_name, 'app_url' => $url, 'app_platform' => 'web', 'app_desc' => $description]));
            } else {
                $app = (yield from $this->myTelegramOrgWrapper->getApp());
            }
            return $app;
        }
        $this->gettingApiId = true;
        if (!isset($this->myTelegramOrgWrapper)) {
            if (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
                $app['api_id'] = (int) $_POST['api_id'];
                $app['api_hash'] = $_POST['api_hash'];
                $this->gettingApiId = false;
                return $app;
            } elseif (isset($_POST['phone_number'])) {
                yield from $this->webAPIPhoneLogin($settings);
            } else {
                (yield $this->webAPIEcho());
            }
        } elseif (!$this->myTelegramOrgWrapper->loggedIn()) {
            if (isset($_POST['code'])) {
                yield from $this->webAPICompleteLogin();
                if (yield from $this->myTelegramOrgWrapper->hasApp()) {
                    return yield from $this->myTelegramOrgWrapper->getApp();
                }
                (yield $this->webAPIEcho());
            } elseif (isset($_POST['api_id']) && isset($_POST['api_hash'])) {
                $app['api_id'] = (int) $_POST['api_id'];
                $app['api_hash'] = $_POST['api_hash'];
                $this->gettingApiId = false;
                return $app;
            } elseif (isset($_POST['phone_number'])) {
                yield from $this->webAPIPhoneLogin($settings);
            } else {
                $this->myTelegramOrgWrapper = null;
                (yield $this->webAPIEcho());
            }
        } else {
            if (isset($_POST['app_title'], $_POST['app_shortname'], $_POST['app_url'], $_POST['app_platform'], $_POST['app_desc'])) {
                $app = (yield from $this->webAPICreateApp());
                $this->gettingApiId = false;
                return $app;
            }
            (yield $this->webAPIEcho(Lang::$current_lang['apiParamsError']));
        }
        return null;
    }
    /**
     *
     */
    private function webAPIPhoneLogin(Settings $settings) : \Generator
    {
        try {
            $this->myTelegramOrgWrapper = new MyTelegramOrgWrapper($settings);
            yield from $this->myTelegramOrgWrapper->login($_POST['phone_number']);
            (yield $this->webAPIEcho());
        } catch (\Throwable $e) {
            (yield $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], 'Please use manual mode: ' . $e->getMessage())));
        }
    }
    /**
     *
     */
    private function webAPICompleteLogin() : \Generator
    {
        try {
            yield from $this->myTelegramOrgWrapper->completeLogin($_POST['code']);
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            (yield $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], 'Please use manual mode: ' . $e->getMessage())));
        } catch (\danog\MadelineProto\Exception $e) {
            (yield $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], 'Please use manual mode: ' . $e->getMessage())));
        }
    }
    /**
     *
     */
    private function webAPICreateApp() : \Generator
    {
        try {
            $params = $_POST;
            unset($params['creating_app']);
            $app = (yield from $this->myTelegramOrgWrapper->createApp($params));
            return $app;
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            (yield $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], 'Please use manual mode: ' . $e->getMessage())));
        } catch (\danog\MadelineProto\Exception $e) {
            (yield $this->webAPIEcho(\sprintf(Lang::$current_lang['apiError'], 'Please use manual mode: ' . $e->getMessage())));
        }
    }
}<?php

/**
 * ApiTemplates module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\ApiWrappers;

use Amp\Promise;
use danog\MadelineProto\Lang;
use function Amp\ByteStream\getOutputBufferStream;
trait Templates
{
    /**
     * API template.
     *
     * @var string
     */
    private $webApiTemplate = 'legacy';
    /**
     * Generate page from template.
     *
     * @param string $message Message
     * @param string $form Form
     *
     * @return string
     */
    private function webAPIEchoTemplate(string $message, string $form) : string
    {
        return \sprintf($this->webApiTemplate, $message, $form, Lang::$current_lang['go']);
    }
    /**
     * Get web API login HTML template string.
     *
     * @return string
     */
    public function getWebAPITemplate() : string
    {
        return $this->webApiTemplate;
    }
    /**
     * Set web API login HTML template string.
     *
     * @return void
     */
    public function setWebAPITemplate(string $template) : void
    {
        $this->webApiTemplate = $template;
    }
    /**
     * Echo to browser.
     *
     * @param string $message Message to echo
     *
     * @return Promise
     */
    private function webAPIEcho(string $message = '') : Promise
    {
        $message = \Phabel\Target\Php80\Polyfill::htmlentities($message);
        if (!isset($this->myTelegramOrgWrapper)) {
            if (isset($_POST['type'])) {
                if ($_POST['type'] === 'manual') {
                    $title = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiManualWeb']);
                    $title .= "<br><b>{$message}</b>";
                    $title .= "<ol>";
                    $title .= "<li>" . \str_replace('https://my.telegram.org', '<a href="https://my.telegram.org" target="_blank">https://my.telegram.org</a>', \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiManualInstructions0'])) . "</li>";
                    $title .= "<li>" . \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiManualInstructions1']) . "</li>";
                    $title .= "<li><ul>";
                    foreach (['App title', 'Short name', 'URL', 'Platform', 'Description'] as $k => $key) {
                        $title .= "<li>{$key}: ";
                        $title .= \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang["apiAppInstructionsManual{$k}"]);
                        $title .= "</li>";
                    }
                    $title .= "</li></ul>";
                    $title .= "<li>" . \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiManualInstructions2']) . "</li>";
                    $title .= "</ol>";
                    $form = '<input type="string" name="api_id" placeholder="API ID" required/>';
                    $form .= '<input type="string" name="api_hash" placeholder="API hash" required/>';
                } else {
                    $title = Lang::$current_lang['apiAutoWeb'];
                    $title .= "<br><b>{$message}</b>";
                    $phone = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['loginUserPhoneWeb']);
                    $form = "<input type='text' name='phone_number' placeholder='{$phone}' required/>";
                }
            } else {
                if ($message) {
                    $message = '<br><br>' . $message;
                }
                $title = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiChooseManualAutoWeb']);
                $title .= "<br>";
                $title .= \sprintf(Lang::$current_lang['apiChooseManualAutoTipWeb'], 'https://docs.madelineproto.xyz/docs/SETTINGS.html#settingsapp_infoapi_id');
                $title .= "<b>{$message}</b>";
                $automatically = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiChooseAutomaticallyWeb']);
                $manually = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiChooseManuallyWeb']);
                $form = "<select name='type'><option value='automatic'>{$automatically}</option><option value='manual'>{$manually}</option></select>";
            }
        } else {
            if (!$this->myTelegramOrgWrapper->loggedIn()) {
                $title = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['loginUserCode']);
                $title .= "<br><b>{$message}</b>";
                $code = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['loginUserPhoneCodeWeb']);
                $form = "<input type='text' name='code' placeholder='{$code}' required/>";
            } else {
                $title = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiAppWeb']);
                $title .= "<br><b>{$message}</b>";
                $form = '<input type="hidden" name="creating_app" value="yes" required/>';
                foreach (['app_title', 'app_shortname', 'app_url', 'app_platform', 'app_desc'] as $k => $field) {
                    $desc = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang["apiAppInstructionsAuto{$k}"]);
                    if ($field == 'app_platform') {
                        $form .= "{$desc}<br>";
                        foreach (['android' => 'Android', 'ios' => 'iOS', 'wp' => 'Windows Phone', 'bb' => 'BlackBerry', 'desktop' => 'Desktop', 'web' => 'Web', 'ubp' => 'Ubuntu phone', 'other' => \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['apiAppInstructionsAutoTypeOther'])] as $key => $desc) {
                            $form .= "<label><input type='radio' name='app_platform' value='{$key}' checked> {$desc}</label>";
                        }
                    } elseif ($field === 'app_desc') {
                        $form .= "{$desc}<br><textarea name='{$field}' required></textarea><br><br>";
                    } else {
                        $form .= "{$desc}<br><input type='text' name='{$field}' required/><br><br>";
                    }
                }
            }
        }
        return getOutputBufferStream()->write($this->webAPIEchoTemplate($title, $form));
    }
}<?php

/**
 * Lua module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * Lua interface.
 */
class Lua
{
    /**
     *
     */
    public API $MadelineProto;
    protected $Lua;
    /**
     *
     */
    protected string $script;
    /**
     *
     */
    public function __construct(string $script, API $MadelineProto)
    {
        if (!\file_exists($script)) {
            throw new Exception(\danog\MadelineProto\Lang::$current_lang['script_not_exist']);
        }
        $this->MadelineProto = $MadelineProto;
        $this->script = $script;
        $this->__wakeup();
    }
    /**
     *
     */
    public function __sleep()
    {
        return ['MadelineProto', 'script'];
    }
    /**
     *
     */
    public function __wakeup()
    {
        if (!\class_exists(\Lua::class)) {
            throw Exception::extension('lua');
        }
        $this->Lua = new \Lua($this->script);
        $this->madelineproto_lua = 1;
        $this->Lua->registerCallback('tdcliFunction', [$this, 'tdcliFunction']);
        $this->Lua->registerCallback('madelineFunction', [$this, 'madelineFunction']);
        $this->Lua->registerCallback('var_dump', 'var_dump');
        foreach (\get_class_methods($this->MadelineProto->API) as $method) {
            $this->Lua->registerCallback($method, [$this->MadelineProto, $method]);
        }
        $methods = [];
        foreach ($this->MadelineProto->getMethodsNamespaced() as $pair) {
            $namespace = \key($pair);
            $method = $pair[$namespace];
            if ($namespace === 'upload') {
                continue;
            }
            $methods[$namespace][$method] = [$this->MadelineProto->{$namespace}, $method];
        }
        foreach ($this->MadelineProto->getMethodsNamespaced() as $pair) {
            $namespace = \key($pair);
            $method = $pair[$namespace];
            if ($namespace === 'upload') {
                continue;
            }
            $this->{$namespace} = $methods[$namespace];
        }
        $this->MadelineProto->lua = true;
        foreach ($this->MadelineProto->getMethodsNamespaced() as $pair) {
            $namespace = \key($pair);
            $this->MadelineProto->{$namespace}->lua = true;
        }
    }
    /**
     * @return (\Generator | int)
     */
    public function tdcliFunction($params, $cb = null, $cb_extra = null)
    {
        $params = $this->MadelineProto->td_to_mtproto($this->MadelineProto->tdcliToTd($params));
        if ($params === 0) {
            return 0;
        }
        $result = $this->MadelineProto->API->methodCall($params['_'], $params);
        if (\is_callable($cb)) {
            $cb($this->MadelineProto->mtproto_to_td($result), $cb_extra);
        }
        return $result;
    }
    /**
     *
     */
    public function madelineFunction($params, $cb = null, $cb_extra = null)
    {
        $result = $this->MadelineProto->API->methodCall($params['_'], $params);
        if (\is_callable($cb)) {
            $cb($result, $cb_extra);
        }
        self::convertObjects($result);
        return $result;
    }
    /**
     *
     */
    public function tdcliUpdateCallback($update) : void
    {
        $this->Lua->tdcliUpdateCallback($this->MadelineProto->mtproto_to_tdcli($update));
    }
    /**
     *
     */
    private function convertArray($array)
    {
        if (!\is_array($array)) {
            return $array;
        }
        if ($this->is_seqential($array)) {
            return \array_flip(\array_map(function ($el) {
                return $el + 1;
            }, \array_flip($array)));
        }
    }
    /**
     *
     */
    private function isSequential(array $arr) : bool
    {
        if ([] === $arr) {
            return false;
        }
        return isset($arr[0]) && \array_keys($arr) === \range(0, \count($arr) - 1);
    }
    /**
     *
     */
    public function __get($name)
    {
        if ($name === 'API') {
            return $this->MadelineProto->API;
        }
        return $this->Lua->{$name};
    }
    /**
     *
     */
    public function __call($name, $params)
    {
        self::convertObjects($params);
        try {
            return $this->Lua->{$name}(...$params);
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
        } catch (\danog\MadelineProto\Exception $e) {
            return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
        } catch (\danog\MadelineProto\TL\Exception $e) {
            return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
        } catch (\danog\MadelineProto\NothingInTheSocketException $e) {
            return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
        } catch (\danog\MadelineProto\PTSException $e) {
            return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
        } catch (\danog\MadelineProto\SecurityException $e) {
            return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
        } catch (\danog\MadelineProto\TL\Conversion\Exception $e) {
            return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
        }
    }
    /**
     *
     */
    public function __set($name, $value)
    {
        return $this->Lua->{$name} = $value;
    }
    /**
     *
     */
    public static function convertObjects(&$data) : void
    {
        \array_walk_recursive($data, function (&$value, $key) {
            if (\is_object($value) && !$value instanceof \phpseclib3\Math\BigInteger) {
                $newval = [];
                foreach (\get_class_methods($value) as $name) {
                    $newval[$name] = [$value, $name];
                }
                foreach ($value as $key => $name) {
                    if ($key === 'madeline') {
                        continue;
                    }
                    $newval[$key] = $name;
                }
                if ($newval === []) {
                    $newval = $value->__toString();
                }
                $value = $newval;
            }
        });
    }
}<?php

/**
 * MadelineProto fileserver.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Files;

use Amp\Http\Server\HttpServer;
use danog\MadelineProto\Exception;
/**
 * MadelineProto fileserver.
 */
class Server
{
    /**
     * Constructor function.
     */
    public function __construct()
    {
        if (!\class_exists(HttpServer::class)) {
            throw new Exception("Please install https://github.com/amphp/http-server to use this module (composer require amphp/http-server)");
        }
    }
}<?php

/**
 * DocsBuilder module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use danog\MadelineProto\Settings\TLSchema;
use danog\MadelineProto\TL\TL;
// This code was written a few years ago: it is garbage, and has to be rewritten
class DocsBuilder
{
    const DEFAULT_TEMPLATES = ['User' => ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'InputPeer', 'NotifyPeer', 'InputNotifyPeer'], 'InputFile' => ['InputFile', 'InputEncryptedFile'], 'InputEncryptedChat' => ['InputEncryptedChat'], 'PhoneCall' => ['PhoneCall'], 'InputPhoto' => ['InputPhoto'], 'InputDocument' => ['InputDocument'], 'InputMedia' => ['InputMedia'], 'InputMessage' => ['InputMessage'], 'KeyboardButton' => ['KeyboardButton']];
    use \danog\MadelineProto\DocsBuilder\Methods;
    use \danog\MadelineProto\DocsBuilder\Constructors;
    public $td = false;
    /**
     *
     */
    protected array $settings;
    /**
     *
     */
    protected string $index;
    /**
     *
     */
    protected Logger $logger;
    /**
     *
     */
    protected TL $TL;
    /**
     *
     */
    protected array $tdDescriptions;
    /**
     *
     */
    public function __construct(Logger $logger, array $settings)
    {
        $this->logger = $logger;
        \set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
        /** @psalm-suppress InvalidArgument */
        $this->TL = new TL(new class($logger)
        {
            /**
             *
             */
            public function __construct($logger)
            {
                $this->logger = $logger;
            }
        });
        $new = new TLSchema();
        $new->mergeArray($settings);
        $this->TL->init($new);
        if (isset($settings['tl_schema']['td']) && !isset($settings['tl_schema']['telegram'])) {
            $this->td = true;
        }
        $this->settings = $settings;
        if (!\file_exists($this->settings['output_dir'])) {
            \mkdir($this->settings['output_dir']);
        }
        \chdir($this->settings['output_dir']);
        $this->index = $settings['readme'] ? 'README.md' : 'index.md';
        foreach (\glob($this->settings['template'] . "/*") as $template) {
            $this->templates[\basename($template, '.md')] = \file_get_contents($template);
        }
    }
    /**
     * Documentation templates.
     *
     * @var array
     */
    protected $templates = [];
    public $types = [];
    public $any = '*';
    /**
     *
     */
    public function mkDocs() : void
    {
        \danog\MadelineProto\Logger::log('Generating documentation index...', \danog\MadelineProto\Logger::NOTICE);
        \file_put_contents($this->index, $this->template('index', $this->settings['title'], $this->settings['description']));
        $this->mkMethods();
        $this->mkConstructors();
        foreach (\glob('types/*') as $unlink) {
            \unlink($unlink);
        }
        if (\file_exists('types')) {
            \rmdir('types');
        }
        \mkdir('types');
        \ksort($this->types);
        $index = '';
        \danog\MadelineProto\Logger::log('Generating types documentation...', \danog\MadelineProto\Logger::NOTICE);
        foreach ($this->types as $otype => $keys) {
            $type = StrTools::typeEscape($otype);
            $index .= '[' . StrTools::markdownEscape($type) . '](' . $type . '.md)<a name="' . $type . '"></a>  

';
            $constructors = '';
            foreach ($keys['constructors'] as $data) {
                $predicate = $data['predicate'] . (isset($data['layer']) && $data['layer'] !== '' ? '_' . $data['layer'] : '');
                $md_predicate = StrTools::markdownEscape($predicate);
                $constructors .= "[{$md_predicate}](../constructors/{$predicate}.md)  \n\n";
            }
            $methods = '';
            foreach ($keys['methods'] as $data) {
                $name = $data['method'];
                $md_name = \str_replace(['.', '_'], ['->', '\\_'], $name);
                $methods .= "[\$MadelineProto->{$md_name}](../methods/{$name}.md)  \n\n";
            }
            $symFile = \str_replace('.', '_', $type);
            $redir = $symFile !== $type ? "\nredirect_from: /API_docs/types/{$symFile}.html" : '';
            $header = '';
            if (!isset($this->settings['td'])) {
                foreach (self::DEFAULT_TEMPLATES as $template => $types) {
                    if (\in_array($type, $types)) {
                        $header .= $this->template($template, $type);
                    }
                }
            }
            if (isset($this->tdDescriptions['types'][$otype])) {
                $header = "{$this->tdDescriptions['types'][$otype]}\n\n{$header}";
            }
            $header = \sprintf($this->templates['Type'], $type, $redir, StrTools::markdownEscape($type), $header, $constructors, $methods);
            \file_put_contents('types/' . $type . '.md', $header . $constructors . $methods);
        }
        \danog\MadelineProto\Logger::log('Generating types index...', \danog\MadelineProto\Logger::NOTICE);
        \file_put_contents('types/' . $this->index, $this->templates['types-index'] . $index);
        \danog\MadelineProto\Logger::log('Generating additional types...', \danog\MadelineProto\Logger::NOTICE);
        foreach (['string', 'bytes', 'int', 'int53', 'long', 'int128', 'int256', 'int512', 'double', 'Bool', 'DataJSON', '!X'] as $type) {
            \file_put_contents("types/{$type}.md", $this->templates[$type]);
        }
        foreach (['boolFalse', 'boolTrue', 'null', 'photoStrippedSize'] as $constructor) {
            \file_put_contents("constructors/{$constructor}.md", $this->templates[$constructor]);
        }
        \danog\MadelineProto\Logger::log('Done!', \danog\MadelineProto\Logger::NOTICE);
    }
    /**
     *
     */
    public static function addToLang(string $key, string $value = '', bool $force = false) : void
    {
        if (!isset(\danog\MadelineProto\Lang::$lang['en'][$key]) || $force) {
            \danog\MadelineProto\Lang::$lang['en'][$key] = $value;
        }
    }
    /**
     * Get formatted template string.
     *
     * @param string $name Template name
     * @param string ...$params Params
     *
     * @return string
     */
    protected function template(string $name, string ...$params) : string
    {
        return \sprintf($this->templates[$name], ...$params);
    }
}<?php

/**
 * Coroutine (modified version of AMP Coroutine).
 *
 * The MIT License (MIT)
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 * @copyright 2015-2018 amphp
 * @copyright 2016 PHP Asynchronous Interoperability Group
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\MadelineProto;

use Amp\Failure;
use Amp\Internal;
use Amp\Promise;
use Amp\Success;
use JsonSerializable;
use ReflectionGenerator;
/**
 * Creates a promise from a generator function yielding promises.
 *
 * When a promise is yielded, execution of the generator is interrupted until the promise is resolved. A success
 * value is sent into the generator, while a failure reason is thrown into the generator. Using a coroutine,
 * asynchronous code can be written without callbacks and be structured like synchronous code.
 */
final class Coroutine implements Promise, \ArrayAccess, JsonSerializable
{
    use Internal\Placeholder {
        fail as internalFail;
    }
    /** @var \Generator */
    private $generator;
    /** @var callable(\Throwable|null $exception, mixed $value): void */
    private $onResolve;
    /** @var bool Used to control iterative coroutine continuation. */
    private $immediate = true;
    /** @var \Throwable|null Promise failure reason when executing next coroutine step, null at all other times. */
    private $exception;
    /** @var mixed Promise success value when executing next coroutine step, null at all other times. */
    private $value;
    /** @var ?self Reference to coroutine that started this coroutine */
    private $parentCoroutine;
    /**
     * @param \Generator $generator
     */
    public function __construct(\Generator $generator)
    {
        $this->generator = $generator;
        try {
            $yielded = $this->generator->current();
            while (!$yielded instanceof Promise) {
                if ($yielded instanceof \YieldReturnValue) {
                    $this->resolve($yielded->getReturn());
                    $this->generator->next();
                    return;
                }
                if (!$this->generator->valid()) {
                    if (PHP_MAJOR_VERSION >= 7) {
                        $this->resolve($this->generator->getReturn());
                    } else {
                        $this->resolve(null);
                    }
                    return;
                }
                if ($yielded instanceof \Generator) {
                    $yielded = new self($yielded);
                } else {
                    $yielded = $this->generator->send($yielded);
                }
            }
            if ($yielded instanceof self) {
                $yielded->parentCoroutine = $this;
            }
        } catch (\Throwable $exception) {
            $this->fail($exception);
            return;
        }
        /*
         * @param \Throwable|null $exception Exception to be thrown into the generator.
         * @param mixed           $value Value to be sent into the generator.
         */
        $this->onResolve = function ($exception, $value) : void {
            $this->exception = $exception;
            $this->value = $value;
            if (!$this->immediate) {
                $this->immediate = true;
                return;
            }
            try {
                do {
                    if ($this->exception) {
                        // Throw exception at current execution point.
                        $yielded = $this->throw($this->exception);
                    } else {
                        // Send the new value and execute to next yield statement.
                        $yielded = $this->generator->send($this->value);
                    }
                    while (!$yielded instanceof Promise) {
                        if ($yielded instanceof \YieldReturnValue) {
                            $this->resolve($yielded->getReturn());
                            $this->onResolve = null;
                            $this->generator->next();
                            return;
                        }
                        if (!$this->generator->valid()) {
                            if (PHP_MAJOR_VERSION >= 7) {
                                $this->resolve($this->generator->getReturn());
                            } else {
                                $this->resolve(null);
                            }
                            $this->onResolve = null;
                            return;
                        }
                        if ($yielded instanceof \Generator) {
                            $yielded = new self($yielded);
                        } else {
                            $yielded = $this->generator->send($yielded);
                        }
                    }
                    if ($yielded instanceof self) {
                        $yielded->parentCoroutine = $this;
                    }
                    $this->immediate = false;
                    $yielded->onResolve($this->onResolve);
                } while ($this->immediate);
                $this->immediate = true;
            } catch (\Throwable $exception) {
                $this->fail($exception);
                $this->onResolve = null;
            } finally {
                $this->exception = null;
                $this->value = null;
            }
        };
        $yielded->onResolve($this->onResolve);
    }
    /**
     * Throw exception into the generator.
     *
     * @param \Throwable $reason Exception
     *
     * @internal
     *
     * @return mixed
     */
    public function throw(\Throwable $reason)
    {
        if (\method_exists($reason, 'updateTLTrace')) {
            $reason->updateTLTrace($this->getTrace());
        }
        return $this->generator->throw($reason);
    }
    /**
     * @param \Throwable $reason Failure reason.
     *
     * @return void
     */
    public function fail(\Throwable $reason) : void
    {
        $this->resolve(new Failure($reason));
    }
    /**
     * @param mixed $offset
     */
    public function offsetExists($offset) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        throw new Exception('Not supported!');
    }
    /**
     * Get data at an array offset asynchronously.
     *
     * @param mixed $offset Offset
     *
     * @return Promise
     */
    public function offsetGet($offset) : Promise
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return Tools::call((function () use($offset) : \Generator {
            $result = (yield $this);
            return $result[$offset];
        })());
    }
    /**
     * @param mixed $offset
     * @param mixed $value
     */
    #[\ReturnTypeWillChange]
    public function offsetSet($offset, $value) : Promise
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return Tools::call((function () use($offset, $value) : \Generator {
            $result = (yield $this);
            if ($offset === null) {
                return $result[] = $value;
            }
            return $result[$offset] = $value;
        })());
    }
    /**
     * @param mixed $offset
     */
    #[\ReturnTypeWillChange]
    public function offsetUnset($offset) : Promise
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return Tools::call((function () use($offset) : \Generator {
            $result = (yield $this);
            unset($result[$offset]);
        })());
    }
    /**
     * Get an attribute asynchronously.
     *
     * @param string $offset Offset
     *
     * @return Promise
     */
    public function __get(string $offset)
    {
        return Tools::call((function () use($offset) : \Generator {
            $result = (yield $this);
            return $result->{$offset};
        })());
    }
    /**
     *
     */
    public function __call(string $name, array $arguments)
    {
        return Tools::call((function () use($name, $arguments) : \Generator {
            $result = (yield $this);
            return $result->{$name}(...$arguments);
        })());
    }
    /**
     * Get current stack trace for running coroutine.
     *
     * @return array
     */
    public function getTrace() : array
    {
        $frames = [];
        try {
            $reflector = new ReflectionGenerator($this->generator);
            $frames = $reflector->getTrace();
            $frames[] = \array_merge($this->parentCoroutine ? $this->parentCoroutine->getFrame() : [], ['function' => $reflector->getFunction()->getName(), 'args' => []]);
        } catch (\Throwable $e) {
        }
        if ($this->parentCoroutine) {
            $frames = \array_merge($frames, $this->parentCoroutine->getTrace());
        }
        return $frames;
    }
    /**
     * Get current execution frame.
     *
     * @return array
     */
    public function getFrame() : array
    {
        try {
            $reflector = new ReflectionGenerator($this->generator);
            return ['file' => $reflector->getExecutingFile(), 'line' => $reflector->getExecutingLine()];
        } catch (\Throwable $e) {
        }
        return [];
    }
    private const WARNING = 'To obtain a result from a Coroutine object, yield the result or disable async (not recommended). See https://docs.madelineproto.xyz/docs/ASYNC.html for more information on async.';
    /**
     *
     */
    public function __debugInfo()
    {
        return [self::WARNING];
    }
    /**
     * Obtain.
     *
     * @return string
     */
    public function jsonSerialize() : string
    {
        return self::WARNING;
    }
}<?php

/**
 * Tools module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use danog\MadelineProto\TL\Conversion\Extension;
/**
 * Some tools.
 */
abstract class StrTools extends Extension
{
    /**
     * Convert to camelCase.
     *
     * @param string $input String
     *
     * @return string
     */
    public static function toCamelCase(string $input) : string
    {
        return \lcfirst(\str_replace('_', '', \ucwords($input, '_')));
    }
    /**
     * Convert to snake_case.
     *
     * @param string $input String
     *
     * @return string
     */
    public static function toSnakeCase(string $input) : string
    {
        \preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
        $ret = $matches[0];
        foreach ($ret as &$match) {
            $match = $match == \strtoupper($match) ? \strtolower($match) : \lcfirst($match);
        }
        return \implode('_', $ret);
    }
    /**
     * Escape string for markdown.
     *
     * @param string $hwat String to escape
     *
     * @return string
     */
    public static function markdownEscape(string $hwat) : string
    {
        return \str_replace('_', '\\_', $hwat);
    }
    /**
     * Escape type name.
     *
     * @param string $type String to escape
     *
     * @return string
     */
    public static function typeEscape(string $type) : string
    {
        $type = \str_replace(['<', '>'], ['_of_', ''], $type);
        return \preg_replace('/.*_of_/', '', $type);
    }
    /**
     * Escape method name.
     *
     * @param string $method Method name
     *
     * @return string
     */
    public static function methodEscape(string $method) : string
    {
        return \str_replace('.', '->', $method);
    }
}<?php

namespace danog\MadelineProto\Db;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use Amp\Sql\CommandResult;
use Amp\Sql\Pool;
use Amp\Sql\ResultSet;
use Amp\Success;
use danog\MadelineProto\Logger;
use function Amp\call;
/**
 * Generic SQL database backend.
 */
abstract class SqlArray extends DriverArray
{
    /**
     *
     */
    protected Pool $db;
    //Pdo driver used for value quoting, to prevent sql injections.
    /**
     *
     */
    protected \PDO $pdo;
    protected const SQL_GET = 0;
    protected const SQL_SET = 1;
    protected const SQL_UNSET = 2;
    protected const SQL_COUNT = 3;
    protected const SQL_ITERATE = 4;
    protected const SQL_CLEAR = 5;
    /**
     * Prepare statements.
     *
     * @param SqlArray::SQL_* $type
     *
     * @return string
     */
    protected abstract function getSqlQuery(int $type) : string;
    /**
     * Get value from row.
     *
     * @param array $row
     * @return (null | mixed)
     */
    protected abstract function getValue(array $row);
    /**
     *
     */
    public function getIterator() : Iterator
    {
        return new Producer(function (callable $emit) {
            $request = (yield from $this->executeRaw($this->getSqlQuery(self::SQL_ITERATE)));
            while ((yield $request->advance())) {
                $row = $request->getCurrent();
                (yield $emit([$row['key'], $this->getValue($row)]));
            }
        });
    }
    /**
     *
     */
    #[\ReturnTypeWillChange]
    public function getArrayCopy() : Promise
    {
        return call(function () {
            $iterator = $this->getIterator();
            $result = [];
            while ((yield $iterator->advance())) {
                [$key, $value] = $iterator->getCurrent();
                $result[$key] = $value;
            }
            return $result;
        });
    }
    /**
     * @param mixed $key
     */
    public function offsetGet($key) : Promise
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return call(function () use($key) {
            if ($cached = $this->getCache($key)) {
                return $cached;
            }
            $row = (yield $this->execute($this->getSqlQuery(self::SQL_GET), ['index' => $key]));
            if ($value = $this->getValue($row)) {
                $this->setCache($key, $value);
            }
            return $value;
        });
    }
    /**
     * @param (string | int) $key
     * @param mixed $value
     */
    public function set($key, $value) : Promise
    {
        if (!\is_int($key)) {
            if (!(\is_bool($key) || \is_numeric($key))) {
                if (!\is_string($key)) {
                    if (!(\is_string($key) || \is_object($key) && \method_exists($key, '__toString') || (\is_bool($key) || \is_numeric($key)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $key = (string) $key;
                    }
                }
            } else {
                $key = (int) $key;
            }
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if ($this->getCache($key) === $value) {
            return new Success();
        }
        $this->setCache($key, $value);
        $request = $this->execute($this->getSqlQuery(self::SQL_SET), ['index' => $key, 'value' => \serialize($value)]);
        //Ensure that cache is synced with latest insert in case of concurrent requests.
        $request->onResolve(fn() => $this->setCache($key, $value));
        return $request;
    }
    /**
     * Check if key isset.
     *
     * @param mixed $key
     *
     * @return Promise<bool> true if the offset exists, otherwise false
     */
    public function isset($key) : Promise
    {
        if (!\is_int($key)) {
            if (!(\is_bool($key) || \is_numeric($key))) {
                if (!\is_string($key)) {
                    if (!(\is_string($key) || \is_object($key) && \method_exists($key, '__toString') || (\is_bool($key) || \is_numeric($key)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $key = (string) $key;
                    }
                }
            } else {
                $key = (int) $key;
            }
        }
        return call(fn() => (null !== (yield $this->offsetGet($key))));
    }
    /**
    * Unset value for an offset.
    *
    * @link https://php.net/manual/en/arrayiterator.offsetunset.php
    *
    * @param (string | int) $index <p>
    The offset to unset.
    </p>
    *
    * @return Promise<array>
    * @throws \Throwable
    * @param (string | int) $key
    */
    public function unset($key) : Promise
    {
        if (!\is_int($key)) {
            if (!(\is_bool($key) || \is_numeric($key))) {
                if (!\is_string($key)) {
                    if (!(\is_string($key) || \is_object($key) && \method_exists($key, '__toString') || (\is_bool($key) || \is_numeric($key)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $key = (string) $key;
                    }
                }
            } else {
                $key = (int) $key;
            }
        }
        $this->unsetCache($key);
        return $this->execute($this->getSqlQuery(self::SQL_UNSET), ['index' => $key]);
    }
    /**
    * Count elements.
    *
    * @link https://php.net/manual/en/arrayiterator.count.php
    * @return Promise<int> The number of elements or public properties in the associated
    array or object, respectively.
    * @throws \Throwable
    */
    public function count() : Promise
    {
        return call(function () {
            $row = (yield $this->execute($this->getSqlQuery(self::SQL_COUNT)));
            return $row[0]['count'] ?? 0;
        });
    }
    /**
     * Clear all elements.
     *
     * @return Promise
     */
    public function clear() : Promise
    {
        return $this->execute($this->getSqlQuery(self::SQL_CLEAR));
    }
    /**
     * Perform async request to db.
     *
     * @param string $sql
     * @param array $params
     *
     * @psalm-param self::STATEMENT_* $stmt
     *
     * @return Promise<array>
     * @throws \Throwable
     */
    protected function execute(string $sql, array $params = []) : Promise
    {
        return call(function () use($sql, $params) {
            $request = (yield from $this->executeRaw($sql, $params));
            $result = [];
            if ($request instanceof ResultSet) {
                while ((yield $request->advance())) {
                    $result[] = $request->getCurrent();
                }
            }
            return $result;
        });
    }
    /**
     * Return raw query result.
     *
     * @param string $sql
     * @param array $params
     *
     * @return \Generator<(CommandResult | ResultSet)>
     */
    protected function executeRaw(string $sql, array $params = []) : \Generator
    {
        if (!empty($params['index']) && !\mb_check_encoding($params['index'], 'UTF-8')) {
            $params['index'] = \mb_convert_encoding($params['index'], 'UTF-8');
        }
        try {
            foreach ($params as $key => $value) {
                $value = $this->pdo->quote($value);
                $sql = \str_replace(":{$key}", $value, $sql);
            }
            $request = (yield $this->db->query($sql));
        } catch (\Throwable $e) {
            Logger::log($e->getMessage(), Logger::ERROR);
            return [];
        }
        return $request;
    }
}<?php

namespace danog\MadelineProto\Db\Driver;

use Amp\Redis\Config;
use Amp\Redis\Redis as RedisRedis;
use Amp\Redis\RemoteExecutorFactory;
use danog\MadelineProto\Settings\Database\Redis as DatabaseRedis;
/**
 * Redis driver wrapper.
 *
 * @internal
 */
class Redis
{
    /**
     * @var RedisRedis[]
     */
    private static array $connections = [];
    /**
     * @param string $host
     * @param int $port
     * @param string $user
     * @param string $password
     * @param string $db
     * @param int $maxConnections
     * @param int $idleTimeout
     *
     * @throws \Amp\Sql\ConnectionException
     * @throws \Amp\Sql\FailureException
     * @throws \Throwable
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, \Amp\Promise<void>, mixed, RedisRedis>
     */
    public static function getConnection(DatabaseRedis $settings) : \Generator
    {
        $dbKey = $settings->getKey();
        if (empty(static::$connections[$dbKey])) {
            $config = Config::fromUri($settings->getUri())->withPassword($settings->getPassword())->withDatabase($settings->getDatabase());
            static::$connections[$dbKey] = new RedisRedis((new RemoteExecutorFactory($config))->createQueryExecutor());
            (yield static::$connections[$dbKey]->ping());
        }
        return static::$connections[$dbKey];
    }
}<?php

namespace danog\MadelineProto\Db\Driver;

use Amp\Mysql\ConnectionConfig;
use Amp\Mysql\Pool;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Database\Mysql as DatabaseMysql;
use function Amp\Mysql\Pool;
/**
 * MySQL driver wrapper.
 *
 * @internal
 */
class Mysql
{
    /**
     * @var Pool[]
     */
    private static array $connections = [];
    /**
     * @param string $host
     * @param int $port
     * @param string $user
     * @param string $password
     * @param string $db
     *
     * @param int $maxConnections
     * @param int $idleTimeout
     *
     * @throws \Amp\Sql\ConnectionException
     * @throws \Amp\Sql\FailureException
     * @throws \Throwable
     *
     * @return \Generator<Pool>
     */
    public static function getConnection(DatabaseMysql $settings) : \Generator
    {
        $dbKey = $settings->getKey();
        if (empty(static::$connections[$dbKey])) {
            $config = ConnectionConfig::fromString("host=" . \str_replace("tcp://", "", $settings->getUri()))->withUser($settings->getUsername())->withPassword($settings->getPassword())->withDatabase($settings->getDatabase());
            yield from static::createDb($config);
            static::$connections[$dbKey] = new Pool($config, $settings->getMaxConnections(), $settings->getIdleTimeout());
        }
        return static::$connections[$dbKey];
    }
    /**
     * @param ConnectionConfig $config
     *
     * @throws \Amp\Sql\ConnectionException
     * @throws \Amp\Sql\FailureException
     * @throws \Throwable
     *
     * @return \Generator
     */
    private static function createDb(ConnectionConfig $config) : \Generator
    {
        try {
            $db = $config->getDatabase();
            $connection = pool($config->withDatabase(null));
            (yield $connection->query("\n                    CREATE DATABASE IF NOT EXISTS `{$db}`\n                    CHARACTER SET 'utf8mb4' \n                    COLLATE 'utf8mb4_general_ci'\n                "));
            $connection->close();
        } catch (\Throwable $e) {
            Logger::log($e->getMessage(), Logger::ERROR);
        }
    }
}<?php

namespace danog\MadelineProto\Db\Driver;

use Amp\Postgres\ConnectionConfig;
use Amp\Postgres\Pool;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Database\Postgres as DatabasePostgres;
use function Amp\Postgres\Pool;
/**
 * Postgres driver wrapper.
 *
 * @internal
 */
class Postgres
{
    /**
     * @var Pool[]
     */
    private static array $connections = [];
    /**
     * @param string $host
     * @param int $port
     * @param string $user
     * @param string $password
     * @param string $db
     *
     * @param int $maxConnections
     * @param int $idleTimeout
     *
     * @throws \Amp\Sql\ConnectionException
     * @throws \Amp\Sql\FailureException
     * @throws \Throwable
     *
     * @return \Generator<Pool>
     */
    public static function getConnection(DatabasePostgres $settings) : \Generator
    {
        $dbKey = $settings->getKey();
        if (empty(static::$connections[$dbKey])) {
            $config = ConnectionConfig::fromString("host=" . \str_replace("tcp://", "", $settings->getUri()))->withUser($settings->getUsername())->withPassword($settings->getPassword())->withDatabase($settings->getDatabase());
            yield from static::createDb($config);
            static::$connections[$dbKey] = new Pool($config, $settings->getMaxConnections(), $settings->getIdleTimeout());
        }
        return static::$connections[$dbKey];
    }
    /**
     * @param ConnectionConfig $config
     *
     * @throws \Amp\Sql\ConnectionException
     * @throws \Amp\Sql\FailureException
     * @throws \Throwable
     */
    private static function createDb(ConnectionConfig $config) : \Generator
    {
        try {
            $db = $config->getDatabase();
            $user = $config->getUser();
            $connection = pool($config->withDatabase(null));
            $result = (yield $connection->query("SELECT * FROM pg_database WHERE datname = '{$db}'"));
            while ((yield $result->advance())) {
                $row = $result->getCurrent();
                if ($row === false) {
                    (yield $connection->query("\n                            CREATE DATABASE {$db}\n                            OWNER {$user}\n                            ENCODING utf8\n                        "));
                }
            }
            (yield $connection->query("\n                    CREATE OR REPLACE FUNCTION update_ts()\n                    RETURNS TRIGGER AS \$\$\n                    BEGIN\n                       IF row(NEW.*) IS DISTINCT FROM row(OLD.*) THEN\n                          NEW.ts = now(); \n                          RETURN NEW;\n                       ELSE\n                          RETURN OLD;\n                       END IF;\n                    END;\n                    \$\$ language 'plpgsql'\n                "));
            $connection->close();
        } catch (\Throwable $e) {
            Logger::log($e->getMessage(), Logger::ERROR);
        }
    }
}<?php

namespace danog\MadelineProto\Db;

use Amp\Promise;
use danog\MadelineProto\Settings\Database\DatabaseAbstract as DatabaseDatabaseAbstract;
use danog\MadelineProto\Settings\Database\Memory;
use danog\MadelineProto\Settings\Database\Mysql;
use danog\MadelineProto\Settings\Database\Postgres;
use danog\MadelineProto\Settings\Database\Redis;
use danog\MadelineProto\Settings\DatabaseAbstract;
/**
 * This factory class initializes the correct database backend for MadelineProto.
 */
abstract class DbPropertiesFactory
{
    /**
     * Indicates a simple K-V array stored in a database backend.
     * Values can be objects or other arrays, but when lots of nesting is required, it's best to split the array into multiple arrays.
     */
    const TYPE_ARRAY = 'array';
    /**
     * @param DatabaseAbstract $dbSettings
     * @param string $table
     * @param (self::TYPE_* | array) $propertyType
     * @param $value
     * @param (DriverArray | null) $value
     *
     * @return Promise<DbType>
     *
     * @internal
     *
     * @uses \danog\MadelineProto\Db\MemoryArray
     * @uses \danog\MadelineProto\Db\MysqlArray
     * @uses \danog\MadelineProto\Db\PostgresArray
     * @uses \danog\MadelineProto\Db\RedisArray
     */
    public static function get(DatabaseAbstract $dbSettings, string $table, $propertyType, $value = null) : Promise
    {
        $config = $propertyType['config'] ?? [];
        $propertyType = \is_array($propertyType) ? $propertyType['type'] : $propertyType;
        $propertyType = \strtolower($propertyType);
        $class = $dbSettings instanceof DatabaseDatabaseAbstract && (!($config['enableCache'] ?? true) || !$dbSettings->getCacheTtl()) ? __NAMESPACE__ . '\\NullCache' : __NAMESPACE__;
        switch (true) {
            case $dbSettings instanceof Memory:
                $class .= '\\Memory';
                break;
            case $dbSettings instanceof Mysql:
                $class .= '\\Mysql';
                break;
            case $dbSettings instanceof Postgres:
                $class .= '\\Postgres';
                break;
            case $dbSettings instanceof Redis:
                $class .= '\\Redis';
                break;
            default:
                throw new \InvalidArgumentException("Unknown dbType: " . \get_class($dbSettings));
        }
        /** @var DbType $class */
        switch (\strtolower($propertyType)) {
            case self::TYPE_ARRAY:
                $class .= 'Array';
                break;
            default:
                throw new \InvalidArgumentException("Unknown {$propertyType}: {$propertyType}");
        }
        return $class::getInstance($table, $value, $dbSettings);
    }
}<?php

namespace danog\MadelineProto\Db\NullCache;

use danog\MadelineProto\Db\PostgresArray as DbPostgresArray;
/**
 * Postgres database backend, no caching.
 *
 * @internal
 */
class PostgresArray extends DbPostgresArray
{
    use NullCacheTrait;
}<?php

namespace danog\MadelineProto\Db\NullCache;

use danog\MadelineProto\Db\MysqlArray as DbMysqlArray;
/**
 * MySQL database backend, no caching.
 *
 * @internal
 */
class MysqlArray extends DbMysqlArray
{
    use NullCacheTrait;
}<?php

namespace danog\MadelineProto\Db\NullCache;

/**
 * Trait that disables database caching.
 *
 * @internal
 */
trait NullCacheTrait
{
    /**
     * @return void
     */
    protected function getCache(string $key, $default = null)
    {
        return $default;
    }
    /**
     * Save item in cache.
     *
     * @param string $key
     * @param $value
     */
    protected function setCache(string $key, $value) : void
    {
    }
    /**
     * Remove key from cache.
     *
     * @param string $key
     */
    protected function unsetCache(string $key) : void
    {
    }
    /**
     *
     */
    protected function startCacheCleanupLoop() : void
    {
    }
    /**
     *
     */
    protected function stopCacheCleanupLoop() : void
    {
    }
}<?php

namespace danog\MadelineProto\Db\NullCache;

use danog\MadelineProto\Db\RedisArray as DbRedisArray;
/**
 * Redis database backend, no caching.
 *
 * @internal
 */
class RedisArray extends DbRedisArray
{
    use NullCacheTrait;
}<?php

namespace danog\MadelineProto\Db;

use danog\MadelineProto\MTProto;
use danog\MadelineProto\Tools;
/**
 * Include this trait and call DbPropertiesTrait::initDb to use MadelineProto's database backend for properties.
 *
 * You will have to define a `$dbProperties` static array property, with a list of properties you want to store to a database.
 *
 * @see DbPropertiesFactory For a list of allowed property types
 *
 * @property array<string, DbPropertiesFactory::TYPE_*> $dbProperties
 */
trait DbPropertiesTrait
{
    /**
     *
     */
    public ?string $tmpDbPrefix = null;
    /**
     * Initialize database instance.
     *
     * @internal
     *
     * @param MTProto $MadelineProto
     * @param boolean $reset
     * @return \Generator
     */
    public function initDb(MTProto $MadelineProto, bool $reset = false) : \Generator
    {
        if (empty(static::$dbProperties)) {
            throw new \LogicException(static::class . ' must have $dbProperties');
        }
        $dbSettings = $MadelineProto->settings->getDb();
        $prefix = static::getSessionId($MadelineProto);
        $promises = [];
        foreach (static::$dbProperties as $property => $type) {
            if ($reset) {
                unset($this->{$property});
            } else {
                $table = "{$prefix}_{$property}";
                $promises[$property] = DbPropertiesFactory::get($dbSettings, $table, $type, $this->{$property});
            }
        }
        $promises = (yield Tools::all($promises));
        foreach ($promises as $key => $data) {
            $this->{$key} = $data;
        }
    }
    /**
     *
     */
    private static function getSessionId(MTProto $madelineProto) : string
    {
        $result = $madelineProto->getSelf()['id'] ?? null;
        if (!$result) {
            $madelineProto->tmpDbPrefix ??= 'tmp_' . \str_replace('0', '', \spl_object_hash($madelineProto));
            $result = $madelineProto->tmpDbPrefix;
        }
        $className = \explode('\\', static::class);
        $result .= '_' . \end($className);
        return $result;
    }
}<?php

namespace danog\MadelineProto\Db;

use Amp\Postgres\ByteA;
use Amp\Postgres\ConnectionConfig;
use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Db\Driver\Postgres;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Database\Postgres as DatabasePostgres;
/**
 * Postgres database backend.
 */
class PostgresArray extends SqlArray
{
    /**
     *
     */
    public DatabasePostgres $dbSettings;
    // Legacy
    /**
     *
     */
    protected array $settings;
    /**
     * Prepare statements.
     *
     * @param SqlArray::STATEMENT_* $type
     *
     * @return string
     */
    protected function getSqlQuery(int $type) : string
    {
        switch ($type) {
            case SqlArray::SQL_GET:
                return "SELECT value FROM \"{$this->table}\" WHERE key = :index LIMIT 1";
            case SqlArray::SQL_SET:
                return "\n                INSERT INTO \"{$this->table}\"\n                (key,value)\n                VALUES (:index, :value)\n                ON CONFLICT (key) DO UPDATE SET value = :value\n            ";
            case SqlArray::SQL_UNSET:
                return "\n                DELETE FROM \"{$this->table}\"\n                WHERE key = :index\n            ";
            case SqlArray::SQL_COUNT:
                return "\n                SELECT count(key) as count FROM \"{$this->table}\"\n            ";
            case SqlArray::SQL_ITERATE:
                return "\n                SELECT key, value FROM \"{$this->table}\"\n            ";
            case SqlArray::SQL_CLEAR:
                return "\n                DELETE FROM \"{$this->table}\"\n            ";
        }
        throw new Exception("An invalid statement type {$type} was provided!");
    }
    /**
     * Initialize on startup.
     *
     * @return \Generator
     */
    public function initStartup() : \Generator
    {
        yield from $this->initConnection($this->dbSettings);
    }
    /**
     * Initialize connection.
     *
     * @param DatabasePostgres $settings
     * @return \Generator
     */
    public function initConnection($settings) : \Generator
    {
        $config = ConnectionConfig::fromString("host=" . \str_replace("tcp://", "", $settings->getUri()));
        $host = $config->getHost();
        $port = $config->getPort();
        $this->pdo = new \PDO("pgsql:host={$host};port={$port}", $settings->getUsername(), $settings->getPassword());
        if (!isset($this->db)) {
            $this->db = (yield from Postgres::getConnection($settings));
        }
    }
    /**
     * Get value from row.
     *
     * @param array $row
     * @return (null | mixed)
     */
    protected function getValue(array $row)
    {
        if ($row) {
            if (!empty($row[0]['value'])) {
                $row = \reset($row);
            }
            if (!$row['value']) {
                return $row['value'];
            }
            if ($row['value'][0] === '\\') {
                $row['value'] = \hex2bin(\Phabel\Target\Php80\Polyfill::substr($row['value'], 2));
            }
            return \unserialize($row['value']);
        }
        return null;
    }
    /**
    * Set value for an offset.
    *
    * @link https://php.net/manual/en/arrayiterator.offsetset.php
    *
    * @param (string | int) $index <p>
    The index to set for.
    </p>
    * @param $value
    *
    * @throws \Throwable
    * @param mixed $value
    */
    public function set($index, $value) : Promise
    {
        if (!\is_int($index)) {
            if (!(\is_bool($index) || \is_numeric($index))) {
                if (!\is_string($index)) {
                    if (!(\is_string($index) || \is_object($index) && \method_exists($index, '__toString') || (\is_bool($index) || \is_numeric($index)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($index) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($index) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $index = (string) $index;
                    }
                }
            } else {
                $index = (int) $index;
            }
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if ($this->getCache($index) === $value) {
            return new Success();
        }
        $this->setCache($index, $value);
        $request = $this->execute($this->getSqlQuery(self::SQL_SET), ['index' => $index, 'value' => new ByteA(\serialize($value))]);
        //Ensure that cache is synced with latest insert in case of concurrent requests.
        $request->onResolve(fn() => $this->setCache($index, $value));
        return $request;
    }
    /**
     * Create table for property.
     *
     * @return \Generator
     *
     * @throws \Throwable
     *
     * @psalm-return \Generator<int, Promise, mixed, void>
     */
    protected function prepareTable() : \Generator
    {
        Logger::log("Creating/checking table {$this->table}", Logger::WARNING);
        (yield $this->db->query("\n            CREATE TABLE IF NOT EXISTS \"{$this->table}\"\n            (\n                \"key\" VARCHAR(255) NOT NULL,\n                \"value\" BYTEA NULL,\n                \"ts\" TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n                CONSTRAINT \"{$this->table}_pkey\" PRIMARY KEY(\"key\")\n            );            \n        "));
        (yield $this->db->query("\n            DROP TRIGGER IF exists \"{$this->table}_update_ts_trigger\" ON \"{$this->table}\";\n        "));
        (yield $this->db->query("\n            CREATE TRIGGER \"{$this->table}_update_ts_trigger\" BEFORE UPDATE ON \"{$this->table}\" FOR EACH ROW EXECUTE PROCEDURE update_ts();\n        "));
    }
    /**
     *
     */
    protected function renameTable(string $from, string $to) : \Generator
    {
        Logger::log("Moving data from {$from} to {$to}", Logger::WARNING);
        (yield $this->db->query(
            /** @lang PostgreSQL */
            "\n            INSERT INTO \"{$to}\" AS t \n            SELECT * FROM \"{$from}\" as f\n            ON CONFLICT DO UPDATE \n                SET t.value = f.value;\n        "
        ));
        (yield $this->db->query("\n            DROP TABLE \"{$from}\";\n        "));
    }
}<?php

namespace danog\MadelineProto\Db;

use Amp\Promise;
use danog\MadelineProto\Settings\Database\DatabaseAbstract;
interface DbType
{
    /**
     * @param string $table
     * @param (null | DbType | array) $previous
     * @param DatabaseAbstract $settings
     *
     * @return Promise<self>
     */
    public static function getInstance(string $table, $previous, $settings) : Promise;
}<?php

namespace danog\MadelineProto\Db;

use Amp\Mysql\ConnectionConfig;
use Amp\Promise;
use danog\MadelineProto\Db\Driver\Mysql;
use danog\MadelineProto\Exception;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Database\Mysql as DatabaseMysql;
/**
 * MySQL database backend.
 */
class MysqlArray extends SqlArray
{
    /**
     *
     */
    protected DatabaseMysql $dbSettings;
    // Legacy
    /**
     *
     */
    protected array $settings;
    /**
     * Initialize on startup.
     *
     * @return \Generator
     */
    public function initStartup() : \Generator
    {
        yield from $this->initConnection($this->dbSettings);
    }
    /**
     * Prepare statements.
     *
     * @param SqlArray::STATEMENT_* $type
     *
     * @return string
     */
    protected function getSqlQuery(int $type) : string
    {
        switch ($type) {
            case SqlArray::SQL_GET:
                return "SELECT `value` FROM `{$this->table}` WHERE `key` = :index LIMIT 1";
            case SqlArray::SQL_SET:
                return "\n                    REPLACE INTO `{$this->table}` \n                    SET `key` = :index, `value` = :value \n                ";
            case SqlArray::SQL_UNSET:
                return "\n                    DELETE FROM `{$this->table}`\n                    WHERE `key` = :index\n                ";
            case SqlArray::SQL_COUNT:
                return "\n                    SELECT count(`key`) as `count` FROM `{$this->table}`\n                ";
            case SqlArray::SQL_ITERATE:
                return "\n                    SELECT `key`, `value` FROM `{$this->table}`\n                ";
            case SqlArray::SQL_CLEAR:
                return "\n                    DELETE FROM `{$this->table}`\n                ";
        }
        throw new Exception("An invalid statement type {$type} was provided!");
    }
    /**
     * Get value from row.
     *
     * @param array $row
     * @return (null | mixed)
     */
    protected function getValue(array $row)
    {
        if ($row) {
            if (!empty($row[0]['value'])) {
                $row = \reset($row);
            }
            return \unserialize($row['value']);
        }
        return null;
    }
    /**
     * Initialize connection.
     *
     * @param DatabaseMysql $settings
     * @return \Generator
     */
    public function initConnection($settings) : \Generator
    {
        $config = ConnectionConfig::fromString("host=" . \str_replace("tcp://", "", $settings->getUri()));
        $host = $config->getHost();
        $port = $config->getPort();
        $this->pdo = new \PDO("mysql:host={$host};port={$port};charset=UTF8", $settings->getUsername(), $settings->getPassword());
        if (!isset($this->db)) {
            $this->db = (yield from Mysql::getConnection($settings));
        }
    }
    /**
     * Create table for property.
     *
     * @return \Generator
     *
     * @throws \Throwable
     *
     * @psalm-return \Generator<int, Promise, mixed, mixed>
     */
    protected function prepareTable() : \Generator
    {
        Logger::log("Creating/checking table {$this->table}", Logger::WARNING);
        return (yield $this->db->query("\n            CREATE TABLE IF NOT EXISTS `{$this->table}`\n            (\n                `key` VARCHAR(255) NOT NULL,\n                `value` MEDIUMBLOB NULL,\n                `ts` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,\n                PRIMARY KEY (`key`)\n            )\n            ENGINE = InnoDB\n            CHARACTER SET 'utf8mb4' \n            COLLATE 'utf8mb4_general_ci'\n        "));
    }
    /**
     *
     */
    protected function renameTable(string $from, string $to) : \Generator
    {
        Logger::log("Moving data from {$from} to {$to}", Logger::WARNING);
        (yield $this->db->query("\n            REPLACE INTO `{$to}`\n            SELECT * FROM `{$from}`;\n        "));
        (yield $this->db->query("\n            DROP TABLE `{$from}`;\n        "));
    }
}<?php

namespace danog\MadelineProto\Db;

use Amp\Iterator;
use Amp\Promise;
/**
 * DB array interface.
 *
 * @template T as mixed
 */
interface DbArray extends DbType, \ArrayAccess
{
    /**
     * Get Array copy.
     *
     * @psalm-return Promise<array<(string | int), T>>
     *
     * @return Promise
     */
    public function getArrayCopy() : Promise;
    /**
     * Check if element is set.
     *
     * @param (string | int) $key
     *
     * @psalm-return Promise<bool>
     *
     * @return Promise
     */
    public function isset($key) : Promise;
    /**
     * Unset element.
     *
     * @param (string | int) $key
     *
     * @psalm-return Promise<mixed>
     *
     * @return Promise
     */
    public function unset($key) : Promise;
    /**
     * Set element.
     *
     * @param (string | int) $index
     * @param mixed $value
     *
     * @psalm-param T $value
     *
     * @return Promise
     * @param (string | int) $key
     */
    public function set($key, $value) : Promise;
    /**
     * Get element.
     *
     * @param (string | int) $index
     *
     * @psalm-return Promise<T>
     *
     * @return Promise
     */
    public function offsetGet($index) : Promise;
    /**
     * Set element.
     *
     * @param (string | int) $index
     * @param mixed $value
     *
     * @psalm-param T $value
     *
     * @return void
     */
    #[\ReturnTypeWillChange]
    public function offsetSet($index, $value);
    /**
     * @deprecated
     * @internal
     * @see DbArray::unset();
     *
     * Unset element.
     *
     * @param (string | int) $index Offset
     * @return void
     */
    public function offsetUnset($index) : void;
    /**
     * @deprecated
     * @internal
     * @see DbArray::isset();
     *
     * @param mixed $index
     *
     * @return bool
     */
    public function offsetExists($index) : bool;
    /**
     * Count number of elements.
     *
     * @return Promise<integer>
     */
    public function count() : Promise;
    /**
     * Clear all elements.
     *
     * @return Promise
     */
    public function clear() : Promise;
    /**
     * Get iterator.
     *
     * @return Iterator<array{0: (string | int), 1: T}>
     */
    public function getIterator() : Iterator;
}<?php

namespace danog\MadelineProto\Db;

use Amp\Promise;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Database\DatabaseAbstract;
use danog\MadelineProto\Settings\Database\Memory;
use danog\MadelineProto\SettingsAbstract;
use ReflectionClass;
use function Amp\call;
/**
 * Array caching trait.
 */
abstract class DriverArray implements DbArray
{
    /**
     *
     */
    protected string $table;
    use ArrayCacheTrait;
    /**
     * Initialize connection.
     */
    public abstract function initConnection(DatabaseAbstract $settings) : \Generator;
    /**
     * Initialize on startup.
     *
     * @return \Generator
     */
    public abstract function initStartup() : \Generator;
    /**
     * Create table for property.
     *
     * @return \Generator
     *
     * @throws \Throwable
     */
    protected abstract function prepareTable() : \Generator;
    /**
     * Rename table.
     *
     * @param string $from
     * @param string $to
     * @return \Generator
     */
    protected abstract function renameTable(string $from, string $to) : \Generator;
    /**
     * Get the value of table.
     *
     * @return string
     */
    public function getTable() : string
    {
        return $this->table;
    }
    /**
     * Set the value of table.
     *
     * @param string $table
     *
     * @return self
     */
    public function setTable(string $table) : self
    {
        $this->table = $table;
        return $this;
    }
    /**
     * @param string $table
     * @param (DbArray | array | null) $previous
     * @param DatabaseAbstract $settings
     *
     * @return Promise
     *
     * @psalm-return Promise<static>
     */
    public static function getInstance(string $table, $previous, $settings) : Promise
    {
        $instance = new static();
        $instance->setTable($table);
        /** @psalm-suppress UndefinedPropertyAssignment */
        $instance->dbSettings = $settings;
        $instance->ttl = $settings->getCacheTtl();
        $instance->startCacheCleanupLoop();
        return call(static function () use($instance, $previous, $settings) {
            yield from $instance->initConnection($settings);
            yield from $instance->prepareTable();
            if (static::getClassName($previous) !== static::getClassName($instance)) {
                if ($previous instanceof DriverArray) {
                    yield from $previous->initStartup();
                }
                yield from static::renameTmpTable($instance, $previous);
                yield from static::migrateDataToDb($instance, $previous);
            }
            return $instance;
        });
    }
    /**
     * Rename table of old database, if the new one is not a temporary table name.
     *
     * Otherwise, simply change name of table in new database to match old table name.
     *
     * @param self $new New db
     * @param (DbArray | array | null) $old Old db
     *
     * @return \Generator
     */
    protected static function renameTmpTable(self $new, $old) : \Generator
    {
        if ($old instanceof SqlArray && $old->getTable()) {
            if ($old->getTable() !== $new->getTable() && \mb_strpos($new->getTable(), 'tmp') !== 0) {
                yield from $new->renameTable($old->getTable(), $new->getTable());
            } else {
                $new->setTable($old->getTable());
            }
        }
    }
    /**
     * @param self $new
     * @param (DbArray | array | null) $old
     *
     * @return \Generator
     * @throws \Throwable
     */
    protected static function migrateDataToDb(self $new, $old) : \Generator
    {
        if (!empty($old) && static::getClassName($old) !== static::getClassName($new)) {
            if (!$old instanceof DbArray) {
                $old = (yield MemoryArray::getInstance('', $old, new Memory()));
            }
            Logger::log('Converting ' . \get_class($old) . ' to ' . \get_class($new), Logger::ERROR);
            $counter = 0;
            $total = (yield $old->count());
            $iterator = $old->getIterator();
            while ((yield $iterator->advance())) {
                $counter++;
                if ($counter % 500 === 0 || $counter === $total) {
                    (yield $new->set(...$iterator->getCurrent()));
                    Logger::log("Loading data to table {$new}: {$counter}/{$total}", Logger::WARNING);
                } else {
                    $new->set(...$iterator->getCurrent());
                }
                $new->ttlValues = [];
                $new->cache = [];
            }
            (yield $old->clear());
            Logger::log('Converting database done.', Logger::ERROR);
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->stopCacheCleanupLoop();
    }
    /**
     * Get the value of table.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->table;
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep() : array
    {
        return ['table', 'dbSettings'];
    }
    /**
     *
     */
    public function __wakeup()
    {
        if (isset($this->settings) && \is_array($this->settings)) {
            $clazz = (new ReflectionClass($this))->getProperty('dbSettings')->getType()->getName();
            /**
             * @var SettingsAbstract
             * @psalm-suppress UndefinedThisPropertyAssignment
             */
            $this->dbSettings = new $clazz();
            $this->dbSettings->mergeArray($this->settings);
            unset($this->settings);
        }
    }
    /**
     *
     */
    public final function offsetExists($index) : bool
    {
        throw new \RuntimeException('Native isset not support promises. Use isset method');
    }
    /**
     * @param mixed $index
     * @param mixed $value
     */
    public final function offsetSet($index, $value) : void
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($index) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($index) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $this->set($index, $value);
    }
    /**
     * @param mixed $index
     */
    public final function offsetUnset($index) : void
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($index) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($index) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $this->unset($index);
    }
    /**
     *
     */
    protected static function getClassName($instance) : ?string
    {
        if ($instance === null) {
            return null;
        } elseif (\is_array($instance)) {
            return 'Array';
        }
        return \str_replace('NullCache\\', '', \get_class($instance));
    }
}<?php

namespace danog\MadelineProto\Db;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Database\Memory;
use function Amp\call;
/**
 * Memory database backend.
 */
class MemoryArray extends \ArrayIterator implements DbArray
{
    /**
     *
     */
    public function __construct($array = [], $flags = 0)
    {
        parent::__construct((array) $array, $flags | self::STD_PROP_LIST);
    }
    /**
     * Get instance.
     *
     * @param string $table
     * @param mixed $previous
     * @param Memory $settings
     * @return Promise<self>
     */
    public static function getInstance(string $table, $previous, $settings) : Promise
    {
        return call(static function () use($previous) {
            if ($previous instanceof MemoryArray) {
                return $previous;
            }
            if ($previous instanceof DbArray) {
                Logger::log("Loading database to memory. Please wait.", Logger::WARNING);
                if ($previous instanceof DriverArray) {
                    yield from $previous->initStartup();
                }
                $temp = (yield $previous->getArrayCopy());
                (yield $previous->clear());
                $previous = $temp;
            }
            return new static($previous);
        });
    }
    /**
     * @param (string | int) $key
     * @param mixed $value
     */
    public function set($key, $value) : Promise
    {
        if (!\is_int($key)) {
            if (!(\is_bool($key) || \is_numeric($key))) {
                if (!\is_string($key)) {
                    if (!(\is_string($key) || \is_object($key) && \method_exists($key, '__toString') || (\is_bool($key) || \is_numeric($key)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $key = (string) $key;
                    }
                }
            } else {
                $key = (int) $key;
            }
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        parent::offsetSet($key, $value);
        return new Success();
    }
    /**
     * @param (string | int) $key
     */
    public function isset($key) : Promise
    {
        if (!\is_int($key)) {
            if (!(\is_bool($key) || \is_numeric($key))) {
                if (!\is_string($key)) {
                    if (!(\is_string($key) || \is_object($key) && \method_exists($key, '__toString') || (\is_bool($key) || \is_numeric($key)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $key = (string) $key;
                    }
                }
            } else {
                $key = (int) $key;
            }
        }
        return new Success(parent::offsetExists($key));
    }
    /**
     * @param (string | int) $key
     */
    public function unset($key) : Promise
    {
        if (!\is_int($key)) {
            if (!(\is_bool($key) || \is_numeric($key))) {
                if (!\is_string($key)) {
                    if (!(\is_string($key) || \is_object($key) && \method_exists($key, '__toString') || (\is_bool($key) || \is_numeric($key)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $key = (string) $key;
                    }
                }
            } else {
                $key = (int) $key;
            }
        }
        parent::offsetUnset($key);
        return new Success();
    }
    /**
     * @param mixed $offset
     */
    public function offsetExists($offset) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        throw new \RuntimeException('Native isset not support promises. Use isset method');
    }
    /**
     * @param mixed $offset
     */
    public function offsetGet($offset) : Promise
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return new Success(parent::offsetExists($offset) ? parent::offsetGet($offset) : null);
    }
    /**
     * @param mixed $offset
     */
    public function offsetUnset($offset) : void
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        parent::offsetUnset($offset);
    }
    /**
     *
     */
    #[\ReturnTypeWillChange]
    public function count() : Promise
    {
        return new Success(parent::count());
    }
    /**
     *
     */
    #[\ReturnTypeWillChange]
    public function getArrayCopy() : Promise
    {
        return new Success(parent::getArrayCopy());
    }
    /**
     *
     */
    public function clear() : Promise
    {
        parent::__construct([], parent::getFlags());
        return new Success();
    }
    /**
     *
     */
    public function getIterator() : Iterator
    {
        return new Producer(function (callable $emit) {
            foreach ($this as $key => $value) {
                (yield $emit([$key, $value]));
            }
        });
    }
}<?php

namespace danog\MadelineProto\Db;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use Amp\Redis\Redis as RedisRedis;
use Amp\Success;
use danog\MadelineProto\Db\Driver\Redis as Redis;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Database\Redis as DatabaseRedis;
use Generator;
use function Amp\call;
/**
 * Redis database backend.
 */
class RedisArray extends DriverArray
{
    /**
     *
     */
    protected DatabaseRedis $dbSettings;
    /**
     *
     */
    private RedisRedis $db;
    // Legacy
    /**
     *
     */
    protected array $settings;
    /**
     * Initialize on startup.
     *
     * @return \Generator
     */
    public function initStartup() : \Generator
    {
        return $this->initConnection($this->dbSettings);
    }
    /**
     * @return Generator
     *
     * @psalm-return Generator<int, Success<null>, mixed, void>
     */
    protected function prepareTable() : Generator
    {
        (yield new Success());
    }
    /**
     *
     */
    protected function renameTable(string $from, string $to) : \Generator
    {
        Logger::log("Moving data from {$from} to {$to}", Logger::WARNING);
        $from = "va:{$from}";
        $to = "va:{$to}";
        $request = $this->db->scan($from . '*');
        $lenK = \strlen($from);
        while ((yield $request->advance())) {
            $oldKey = $request->getCurrent();
            $newKey = $to . \Phabel\Target\Php80\Polyfill::substr($oldKey, $lenK);
            $value = (yield $this->db->get($oldKey));
            $this->db->set($newKey, $value);
            $this->db->delete($oldKey);
        }
    }
    /**
     * Initialize connection.
     *
     * @param DatabaseRedis $settings
     * @return \Generator
     */
    public function initConnection($settings) : \Generator
    {
        if (!isset($this->db)) {
            $this->db = (yield from Redis::getConnection($settings));
        }
    }
    /**
     * Get redis key name.
     *
     * @param string $key
     * @return string
     */
    private function rKey(string $key) : string
    {
        return 'va:' . $this->table . ':' . $key;
    }
    /**
     * Get redis ts name.
     *
     * @param string $key
     * @return string
     */
    private function tsKey(string $key) : string
    {
        return 'ts:' . $this->table . $key;
    }
    /**
     * Get iterator key.
     *
     * @return string
     */
    private function itKey() : string
    {
        return 'va:' . $this->table . '*';
    }
    /**
    * Set value for an offset.
    *
    * @link https://php.net/manual/en/arrayiterator.offsetset.php
    *
    * @param string $index <p>
    The index to set for.
    </p>
    * @param $value
    *
    * @throws \Throwable
    * @param mixed $value
    */
    public function set($index, $value) : Promise
    {
        if (!\is_int($index)) {
            if (!(\is_bool($index) || \is_numeric($index))) {
                if (!\is_string($index)) {
                    if (!(\is_string($index) || \is_object($index) && \method_exists($index, '__toString') || (\is_bool($index) || \is_numeric($index)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($index) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($index) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $index = (string) $index;
                    }
                }
            } else {
                $index = (int) $index;
            }
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if ($this->getCache($index) === $value) {
            return new Success();
        }
        $this->setCache($index, $value);
        $request = $this->db->set($this->rKey($index), \serialize($value));
        //Ensure that cache is synced with latest insert in case of concurrent requests.
        $request->onResolve(fn() => $this->setCache($index, $value));
        return $request;
    }
    /**
     * Check if key isset.
     *
     * @param $key
     *
     * @return Promise<bool> true if the offset exists, otherwise false
     * @param (string | int) $key
     */
    public function isset($key) : Promise
    {
        if (!\is_int($key)) {
            if (!(\is_bool($key) || \is_numeric($key))) {
                if (!\is_string($key)) {
                    if (!(\is_string($key) || \is_object($key) && \method_exists($key, '__toString') || (\is_bool($key) || \is_numeric($key)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $key = (string) $key;
                    }
                }
            } else {
                $key = (int) $key;
            }
        }
        return $this->db->has($this->rKey($key));
    }
    /**
     * @param mixed $offset
     */
    public function offsetGet($offset) : Promise
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return call(function () use($offset) {
            if ($cached = $this->getCache($offset)) {
                return $cached;
            }
            $value = (yield $this->db->get($this->rKey($offset)));
            if ($value = \unserialize($value)) {
                $this->setCache($offset, $value);
            }
            return $value;
        });
    }
    /**
     * @param (string | int) $key
     */
    public function unset($key) : Promise
    {
        if (!\is_int($key)) {
            if (!(\is_bool($key) || \is_numeric($key))) {
                if (!\is_string($key)) {
                    if (!(\is_string($key) || \is_object($key) && \method_exists($key, '__toString') || (\is_bool($key) || \is_numeric($key)))) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($key) must be of type string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($key) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $key = (string) $key;
                    }
                }
            } else {
                $key = (int) $key;
            }
        }
        $this->unsetCache($key);
        return $this->db->delete($this->rkey($key));
    }
    /**
     * Get array copy.
     *
     * @return Promise<array>
     * @throws \Throwable
     */
    #[\ReturnTypeWillChange]
    public function getArrayCopy() : Promise
    {
        return call(function () {
            $iterator = $this->getIterator();
            $result = [];
            while ((yield $iterator->advance())) {
                [$key, $value] = $iterator->getCurrent();
                $result[$key] = $value;
            }
            return $result;
        });
    }
    /**
     *
     */
    public function getIterator() : Iterator
    {
        return new Producer(function (callable $emit) {
            $request = $this->db->scan($this->itKey());
            $len = \strlen($this->rKey(''));
            while ((yield $request->advance())) {
                $key = $request->getCurrent();
                (yield $emit([\Phabel\Target\Php80\Polyfill::substr($key, $len), \unserialize((yield $this->db->get($key)))]));
            }
        });
    }
    /**
    * Count elements.
    *
    * @link https://php.net/manual/en/arrayiterator.count.php
    * @return Promise<int> The number of elements or public properties in the associated
    array or object, respectively.
    * @throws \Throwable
    */
    public function count() : Promise
    {
        return call(function () {
            $request = $this->db->scan($this->itKey());
            $count = 0;
            while ((yield $request->advance())) {
                $count++;
            }
            return $count;
        });
    }
    /**
     * Clear all elements.
     *
     * @return Promise
     */
    public function clear() : Promise
    {
        return call(function () {
            $request = $this->db->scan($this->itKey());
            $keys = [];
            $k = 0;
            while ((yield $request->advance())) {
                $keys[$k++] = $request->getCurrent();
                if ($k === 10) {
                    (yield $this->db->delete(...$keys));
                    $keys = [];
                    $k = 0;
                }
            }
            if (!empty($keys)) {
                (yield $this->db->delete(...$keys));
            }
        });
    }
}<?php

namespace danog\MadelineProto\Db;

use Amp\Loop;
use Closure;
use danog\MadelineProto\Logger;
/**
 * Array caching trait.
 */
trait ArrayCacheTrait
{
    /**
     * @var array<mixed>
     */
    protected array $cache = [];
    /**
     * @var array<int>
     */
    protected array $ttlValues = [];
    /**
     * TTL interval.
     */
    protected int $ttl = 5 * 60;
    /**
     * Cache cleanup watcher ID.
     */
    private ?string $cacheCleanupId = null;
    /**
     *
     */
    protected function getCache(string $key, $default = null)
    {
        if (!isset($this->ttlValues[$key])) {
            return $default;
        }
        $this->ttlValues[$key] = \time() + $this->ttl;
        return $this->cache[$key];
    }
    /**
     * Save item in cache.
     *
     * @param string $key
     * @param $value
     */
    protected function setCache(string $key, $value) : void
    {
        $this->cache[$key] = $value;
        $this->ttlValues[$key] = \time() + $this->ttl;
    }
    /**
     * Remove key from cache.
     *
     * @param string $key
     */
    protected function unsetCache(string $key) : void
    {
        unset($this->cache[$key], $this->ttlValues[$key]);
    }
    /**
     *
     */
    protected function startCacheCleanupLoop() : void
    {
        $this->cacheCleanupId = Loop::repeat(\max(1000, $this->ttl * 1000 / 5), Closure::fromCallable([$this, 'cleanupCache']));
    }
    /**
     *
     */
    protected function stopCacheCleanupLoop() : void
    {
        if ($this->cacheCleanupId) {
            Loop::cancel($this->cacheCleanupId);
            $this->cacheCleanupId = null;
        }
    }
    /**
     * Remove all keys from cache.
     */
    protected function cleanupCache() : void
    {
        $now = \time();
        $oldCount = 0;
        foreach ($this->ttlValues as $cacheKey => $ttl) {
            if ($ttl < $now) {
                $this->unsetCache($cacheKey);
                $oldCount++;
            }
        }
        Logger::log(\sprintf("cache for table: %s; keys left: %s; keys removed: %s", (string) $this, \count($this->cache), $oldCount), Logger::VERBOSE);
    }
}<?php

namespace danog\MadelineProto;

use danog\MadelineProto\Settings\AppInfo;
use danog\MadelineProto\Settings\Auth;
use danog\MadelineProto\Settings\Connection;
use danog\MadelineProto\Settings\Database\Memory as DatabaseMemory;
use danog\MadelineProto\Settings\Database\Mysql;
use danog\MadelineProto\Settings\Database\Postgres;
use danog\MadelineProto\Settings\Database\Redis;
use danog\MadelineProto\Settings\DatabaseAbstract;
use danog\MadelineProto\Settings\Files;
use danog\MadelineProto\Settings\Ipc;
use danog\MadelineProto\Settings\Logger;
use danog\MadelineProto\Settings\Peer;
use danog\MadelineProto\Settings\Pwr;
use danog\MadelineProto\Settings\RPC;
use danog\MadelineProto\Settings\SecretChats;
use danog\MadelineProto\Settings\Serialization;
use danog\MadelineProto\Settings\Templates;
use danog\MadelineProto\Settings\TLSchema;
use danog\MadelineProto\Settings\VoIP;
/**
 * Settings class used for configuring MadelineProto.
 */
class Settings extends SettingsAbstract
{
    /**
     * App information.
     */
    protected AppInfo $appInfo;
    /**
     * Cryptography settings.
     */
    protected Auth $auth;
    /**
     * Connection settings.
     */
    protected Connection $connection;
    /**
     * File management settings.
     */
    protected Files $files;
    /**
     * IPC server settings.
     */
    protected Ipc $ipc;
    /**
     * Logger settings.
     */
    protected Logger $logger;
    /**
     * Peer database settings.
     */
    protected Peer $peer;
    /**
     * PWRTelegram settings.
     */
    protected Pwr $pwr;
    /**
     * RPC settings.
     */
    protected RPC $rpc;
    /**
     * Secret chat settings.
     */
    protected SecretChats $secretChats;
    /**
     * Serialization settings.
     */
    protected Serialization $serialization;
    /**
     * TL schema settings.
     */
    protected TLSchema $schema;
    /**
     * DatabaseAbstract settings.
     */
    protected DatabaseAbstract $db;
    /**
     * Template settings.
     */
    protected Templates $templates;
    /**
     * VoIP settings.
     */
    protected VoIP $voip;
    /**
     * Create settings object from possibly legacy settings array.
     *
     * @internal
     *
     * @param (SettingsAbstract | array) $settings Settings
     *
     * @return SettingsAbstract
     */
    public static function parseFromLegacy($settings) : SettingsAbstract
    {
        if (\is_array($settings)) {
            if (empty($settings)) {
                return new SettingsEmpty();
            }
            $settingsNew = new Settings();
            $settingsNew->mergeArray($settings);
            return $settingsNew;
        }
        return $settings;
    }
    /**
     * Create full settings object from possibly legacy settings array.
     *
     * @internal
     *
     * @param (SettingsAbstract | array) $settings Settings
     *
     * @return Settings
     */
    public static function parseFromLegacyFull($settings) : Settings
    {
        $settings = self::parseFromLegacy($settings);
        if (!$settings instanceof Settings) {
            $newSettings = new Settings();
            $newSettings->merge($settings);
            $settings = $newSettings;
        }
        return $settings;
    }
    /**
     * Constructor.
     *
     * @internal
     */
    public function __construct()
    {
        $this->appInfo = new AppInfo();
        $this->auth = new Auth();
        $this->connection = new Connection();
        $this->files = new Files();
        $this->logger = new Logger();
        $this->peer = new Peer();
        $this->pwr = new Pwr();
        $this->rpc = new RPC();
        $this->secretChats = new SecretChats();
        $this->serialization = new Serialization();
        $this->schema = new TLSchema();
        $this->db = new DatabaseMemory();
        $this->templates = new Templates();
        $this->ipc = new IPc();
        $this->voip = new VoIP();
    }
    /**
     *
     */
    public function __wakeup()
    {
        if (!isset($this->voip)) {
            $this->voip = new VoIP();
        }
    }
    /**
     * Merge legacy array settings.
     *
     * @param array $settings Settings
     *
     * @internal
     *
     * @return void
     */
    public function mergeArray(array $settings) : void
    {
        $this->appInfo->mergeArray($settings);
        $this->auth->mergeArray($settings);
        $this->connection->mergeArray($settings);
        $this->files->mergeArray($settings);
        $this->logger->mergeArray($settings);
        $this->peer->mergeArray($settings);
        $this->pwr->mergeArray($settings);
        $this->rpc->mergeArray($settings);
        $this->secretChats->mergeArray($settings);
        $this->serialization->mergeArray($settings);
        $this->schema->mergeArray($settings);
        $this->ipc->mergeArray($settings);
        $this->voip->mergeArray($settings);
        switch ($settings['db']['type'] ?? 'memory') {
            case 'memory':
                $this->db = new DatabaseMemory();
                break;
            case 'mysql':
                $this->db = new Mysql();
                break;
            case 'postgres':
                $this->db = new Postgres();
                break;
            case 'redis':
                $this->db = new Redis();
                break;
        }
        $this->db->mergeArray($settings);
    }
    /**
     * Merge another instance of settings.
     *
     * @param SettingsAbstract $settings Settings
     *
     * @return void
     */
    public function merge(SettingsAbstract $settings) : void
    {
        if (!$settings instanceof self) {
            if ($settings instanceof AppInfo) {
                $this->appInfo->merge($settings);
            } elseif ($settings instanceof Auth) {
                $this->auth->merge($settings);
            } elseif ($settings instanceof Connection) {
                $this->connection->merge($settings);
            } elseif ($settings instanceof Files) {
                $this->files->merge($settings);
            } elseif ($settings instanceof Logger) {
                $this->logger->merge($settings);
            } elseif ($settings instanceof Peer) {
                $this->peer->merge($settings);
            } elseif ($settings instanceof Pwr) {
                $this->pwr->merge($settings);
            } elseif ($settings instanceof RPC) {
                $this->rpc->merge($settings);
            } elseif ($settings instanceof SecretChats) {
                $this->secretChats->merge($settings);
            } elseif ($settings instanceof Serialization) {
                $this->serialization->merge($settings);
            } elseif ($settings instanceof TLSchema) {
                $this->schema->merge($settings);
            } elseif ($settings instanceof Ipc) {
                $this->ipc->merge($settings);
            } elseif ($settings instanceof Templates) {
                $this->templates->merge($settings);
            } elseif ($settings instanceof VoIP) {
                $this->voip->merge($settings);
            } elseif ($settings instanceof DatabaseAbstract) {
                if (!$this->db instanceof $settings) {
                    $this->db = $settings;
                } else {
                    $this->db->merge($settings);
                }
            }
            return;
        }
        $this->appInfo->merge($settings->appInfo);
        $this->auth->merge($settings->auth);
        $this->connection->merge($settings->connection);
        $this->files->merge($settings->files);
        $this->logger->merge($settings->logger);
        $this->peer->merge($settings->peer);
        $this->pwr->merge($settings->pwr);
        $this->rpc->merge($settings->rpc);
        $this->secretChats->merge($settings->secretChats);
        $this->serialization->merge($settings->serialization);
        $this->schema->merge($settings->schema);
        $this->ipc->merge($settings->ipc);
        $this->templates->merge($settings->templates);
        $this->voip->merge($settings->voip);
        if (!\Phabel\Plugin\NewFixer::instanceOf($this->db, $settings->db)) {
            $this->db = $settings->db;
        } else {
            $this->db->merge($settings->db);
        }
    }
    /**
     * Get default DC ID.
     *
     * @return integer
     */
    public function getDefaultDc() : int
    {
        return $this->connection->getDefaultDc();
    }
    /**
     * Get default DC params.
     *
     * @return array
     */
    public function getDefaultDcParams() : array
    {
        return $this->connection->getDefaultDcParams();
    }
    /**
     * Set default DC ID.
     *
     * @param int $dc DC ID
     *
     * @return self
     */
    public function setDefaultDc(int $dc) : self
    {
        $this->connection->setDefaultDc($dc);
        return $this;
    }
    /**
     * Get app information.
     *
     * @return AppInfo
     */
    public function getAppInfo() : AppInfo
    {
        return $this->appInfo;
    }
    /**
     * Set app information.
     *
     * @param AppInfo $appInfo App information.
     *
     * @return self
     */
    public function setAppInfo(AppInfo $appInfo) : self
    {
        $this->appInfo = $appInfo;
        return $this;
    }
    /**
     * Get cryptography settings.
     *
     * @return Auth
     */
    public function getAuth() : Auth
    {
        return $this->auth;
    }
    /**
     * Set cryptography settings.
     *
     * @param Auth $auth Cryptography settings.
     *
     * @return self
     */
    public function setAuth(Auth $auth) : self
    {
        $this->auth = $auth;
        return $this;
    }
    /**
     * Get connection settings.
     *
     * @return Connection
     */
    public function getConnection() : Connection
    {
        return $this->connection;
    }
    /**
     * Set connection settings.
     *
     * @param Connection $connection Connection settings.
     *
     * @return self
     */
    public function setConnection(Connection $connection) : self
    {
        $this->connection = $connection;
        return $this;
    }
    /**
     * Get file management settings.
     *
     * @return Files
     */
    public function getFiles() : Files
    {
        return $this->files;
    }
    /**
     * Set file management settings.
     *
     * @param Files $files File management settings.
     *
     * @return self
     */
    public function setFiles(Files $files) : self
    {
        $this->files = $files;
        return $this;
    }
    /**
     * Get logger settings.
     *
     * @return Logger
     */
    public function getLogger() : Logger
    {
        return $this->logger;
    }
    /**
     * Set logger settings.
     *
     * @param Logger $logger Logger settings.
     *
     * @return self
     */
    public function setLogger(Logger $logger) : self
    {
        $this->logger = $logger;
        return $this;
    }
    /**
     * Get peer database settings.
     *
     * @return Peer
     */
    public function getPeer() : Peer
    {
        return $this->peer;
    }
    /**
     * Set peer database settings.
     *
     * @param Peer $peer Peer database settings.
     *
     * @return self
     */
    public function setPeer(Peer $peer) : self
    {
        $this->peer = $peer;
        return $this;
    }
    /**
     * Get PWRTelegram settings.
     *
     * @return Pwr
     */
    public function getPwr() : Pwr
    {
        return $this->pwr;
    }
    /**
     * Set PWRTelegram settings.
     *
     * @param Pwr $pwr PWRTelegram settings.
     *
     * @return self
     */
    public function setPwr(Pwr $pwr) : self
    {
        $this->pwr = $pwr;
        return $this;
    }
    /**
     * Get RPC settings.
     *
     * @return RPC
     */
    public function getRpc() : RPC
    {
        return $this->rpc;
    }
    /**
     * Set RPC settings.
     *
     * @param RPC $rpc RPC settings.
     *
     * @return self
     */
    public function setRpc(RPC $rpc) : self
    {
        $this->rpc = $rpc;
        return $this;
    }
    /**
     * Get secret chat settings.
     *
     * @return SecretChats
     */
    public function getSecretChats() : SecretChats
    {
        return $this->secretChats;
    }
    /**
     * Set secret chat settings.
     *
     * @param SecretChats $secretChats Secret chat settings.
     *
     * @return self
     */
    public function setSecretChats(SecretChats $secretChats) : self
    {
        $this->secretChats = $secretChats;
        return $this;
    }
    /**
     * Get serialization settings.
     *
     * @return Serialization
     */
    public function getSerialization() : Serialization
    {
        return $this->serialization;
    }
    /**
     * Set serialization settings.
     *
     * @param Serialization $serialization Serialization settings.
     *
     * @return self
     */
    public function setSerialization(Serialization $serialization) : self
    {
        $this->serialization = $serialization;
        return $this;
    }
    /**
     * Get TL schema settings.
     *
     * @return TLSchema
     */
    public function getSchema() : TLSchema
    {
        return $this->schema;
    }
    /**
     * Set TL schema settings.
     *
     * @param TLSchema $schema TL schema settings.
     *
     * @return self
     */
    public function setSchema(TLSchema $schema) : self
    {
        $this->schema = $schema;
        return $this;
    }
    /**
     * Get database settings.
     *
     * @return DatabaseAbstract
     */
    public function getDb() : DatabaseAbstract
    {
        return $this->db;
    }
    /**
     * Set database settings.
     *
     * @param DatabaseAbstract $db DatabaseAbstract settings.
     *
     * @return self
     */
    public function setDb(DatabaseAbstract $db) : self
    {
        $this->db = $db;
        return $this;
    }
    /**
     * Get IPC server settings.
     *
     * @return Ipc
     */
    public function getIpc() : Ipc
    {
        return $this->ipc;
    }
    /**
     * Set IPC server settings.
     *
     * @param Ipc $ipc IPC server settings.
     *
     * @return self
     */
    public function setIpc(Ipc $ipc) : self
    {
        $this->ipc = $ipc;
        return $this;
    }
    /**
     *
     */
    public function applyChanges() : SettingsAbstract
    {
        foreach (\get_object_vars($this) as $setting) {
            if ($setting instanceof SettingsAbstract) {
                $setting->applyChanges();
            }
        }
        return $this;
    }
    /**
     * Get template settings.
     *
     * @return Templates
     */
    public function getTemplates() : Templates
    {
        return $this->templates;
    }
    /**
     * Set template settings.
     *
     * @param Templates $templates Template settings
     *
     * @return self
     */
    public function setTemplates(Templates $templates) : self
    {
        $this->templates = $templates;
        return $this;
    }
    /**
     * Get voIP settings.
     *
     * @return VoIP
     */
    public function getVoip() : VoIP
    {
        return $this->voip;
    }
    /**
     * Set voIP settings.
     *
     * @param VoIP $voip VoIP settings.
     *
     * @return self
     */
    public function setVoip(VoIP $voip) : self
    {
        $this->voip = $voip;
        return $this;
    }
}<?php

/**
 * Shutdown module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * Class that controls script shutdown.
 */
class Shutdown
{
    /**
     * Callbacks to call on shutdown.
     *
     * @var array<callable>
     */
    private static $callbacks = [];
    /**
     * Whether the main shutdown was registered.
     *
     * @var boolean
     */
    private static $registered = false;
    /**
     * Incremental ID for new callback.
     *
     * @var integer
     */
    private static $id = 0;
    /**
     * Function to be called on shutdown.
     *
     * @return void
     */
    public static function shutdown()
    {
        foreach (self::$callbacks as $callback) {
            $callback();
        }
        self::$callbacks = [];
        Magic::shutdown(0);
    }
    /**
     * Add a callback for script shutdown.
     *
     * @param callable $callback The callback to set
     * @param (null | string) $id The optional callback ID
     *
     * @return (int | string) The callback ID
     */
    public static function addCallback($callback, $id = null)
    {
        if (!$id) {
            $id = self::$id++;
        }
        self::$callbacks[$id] = $callback;
        if (!self::$registered) {
            \register_shutdown_function([__CLASS__, 'shutdown']);
            self::$registered = true;
        }
        return $id;
    }
    /**
     * Remove a callback from the script shutdown callable list.
     *
     * @param (null | string | int) $id The optional callback ID
     *
     * @return bool true if the callback was removed correctly, false otherwise
     */
    public static function removeCallback($id)
    {
        if (isset(self::$callbacks[$id])) {
            unset(self::$callbacks[$id]);
            return true;
        }
        return false;
    }
}<?php

/**
 * Connection module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\ByteStream\ClosedException;
use Amp\Deferred;
use Amp\Failure;
use danog\MadelineProto\Loop\Connection\CheckLoop;
use danog\MadelineProto\Loop\Connection\CleanupLoop;
use danog\MadelineProto\Loop\Connection\HttpWaitLoop;
use danog\MadelineProto\Loop\Connection\PingLoop;
use danog\MadelineProto\Loop\Connection\ReadLoop;
use danog\MadelineProto\Loop\Connection\WriteLoop;
use danog\MadelineProto\MTProto\OutgoingMessage;
use danog\MadelineProto\MTProtoSession\Session;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoTransport\HttpsStream;
use danog\MadelineProto\Stream\MTProtoTransport\HttpStream;
use danog\MadelineProto\Stream\StreamInterface;
use danog\MadelineProto\Stream\Transport\WssStream;
use danog\MadelineProto\Stream\Transport\WsStream;
/**
 * Connection class.
 *
 * Manages connection to Telegram datacenters
 *
 * @internal
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class Connection
{
    use Session;
    use \danog\Serializable;
    /**
     * Writer loop.
     *
     * @var \danog\MadelineProto\Loop\Connection\WriteLoop
     */
    protected $writer;
    /**
     * Reader loop.
     *
     * @var \danog\MadelineProto\Loop\Connection\ReadLoop
     */
    protected $reader;
    /**
     * Checker loop.
     *
     * @var \danog\MadelineProto\Loop\Connection\CheckLoop
     */
    protected $checker;
    /**
     * Waiter loop.
     *
     * @var \danog\MadelineProto\Loop\Connection\HttpWaitLoop
     */
    protected $waiter;
    /**
     * Ping loop.
     *
     * @var \danog\MadelineProto\Loop\Connection\PingLoop
     */
    protected $pinger;
    /**
     * Cleanup loop.
     *
     * @var \danog\MadelineProto\Loop\Connection\CleanupLoop
     */
    protected $cleanup;
    /**
     * The actual socket.
     *
     * @var StreamInterface
     */
    public $stream;
    /**
     * Connection context.
     *
     * @var ConnectionContext
     */
    private $ctx;
    /**
     * HTTP request count.
     *
     * @var integer
     */
    private $httpReqCount = 0;
    /**
     * HTTP response count.
     *
     * @var integer
     */
    private $httpResCount = 0;
    /**
     * Date of last chunk received.
     *
     * @var float
     */
    private float $lastChunk = 0;
    /**
     * Logger instance.
     *
     * @var Logger
     */
    protected $logger;
    /**
     * Main instance.
     *
     * @var MTProto
     */
    public $API;
    /**
     * Shared connection instance.
     *
     * @var DataCenterConnection
     */
    protected $shared;
    /**
     * DC ID.
     *
     * @var string
     */
    protected $datacenter;
    /**
     * Connection ID.
     *
     * @var int
     */
    private $id = 0;
    /**
     * DC ID and connection ID concatenated.
     *
     * @var
     */
    private $datacenterId = '';
    /**
     * Whether this socket has to be reconnected.
     *
     * @var boolean
     */
    private $needsReconnect = false;
    /**
     * Indicate if this socket needs to be reconnected.
     *
     * @param boolean $needsReconnect Whether the socket has to be reconnected
     *
     * @return void
     */
    public function needReconnect(bool $needsReconnect)
    {
        $this->needsReconnect = $needsReconnect;
    }
    /**
     * Whether this sockets needs to be reconnected.
     *
     * @return boolean
     */
    public function shouldReconnect() : bool
    {
        return $this->needsReconnect;
    }
    /**
     * Set writing boolean.
     *
     * @param boolean $writing
     *
     * @return void
     */
    public function writing(bool $writing) : void
    {
        $this->shared->writing($writing, $this->id);
    }
    /**
     * Set reading boolean.
     *
     * @param boolean $reading
     *
     * @return void
     */
    public function reading(bool $reading) : void
    {
        $this->shared->reading($reading, $this->id);
    }
    /**
     * Tell the class that we have read a chunk of data from the socket.
     *
     * @return void
     */
    public function haveRead()
    {
        $this->lastChunk = \microtime(true);
    }
    /**
     * Get the receive date of the latest chunk of data from the socket.
     *
     * @return float
     */
    public function getLastChunk() : float
    {
        return $this->lastChunk;
    }
    /**
     * Indicate a received HTTP response.
     *
     * @return void
     */
    public function httpReceived()
    {
        $this->httpResCount++;
    }
    /**
     * Count received HTTP responses.
     *
     * @return integer
     */
    public function countHttpReceived() : int
    {
        return $this->httpResCount;
    }
    /**
     * Indicate a sent HTTP request.
     *
     * @return void
     */
    public function httpSent()
    {
        $this->httpReqCount++;
    }
    /**
     * Count sent HTTP requests.
     *
     * @return integer
     */
    public function countHttpSent() : int
    {
        return $this->httpReqCount;
    }
    /**
     * Get connection ID.
     *
     * @return integer
     */
    public function getID() : int
    {
        return $this->id;
    }
    /**
     * Get datacenter concatenated with connection ID.
     *
     * @return string
     */
    public function getDatacenterID() : string
    {
        return $this->datacenterId;
    }
    /**
     * Get connection context.
     *
     * @return ConnectionContext
     */
    public function getCtx() : ConnectionContext
    {
        return $this->ctx;
    }
    /**
     * Check if is an HTTP connection.
     *
     * @return boolean
     */
    public function isHttp() : bool
    {
        return \in_array($this->ctx->getStreamName(), [HttpStream::class, HttpsStream::class]);
    }
    /**
     * Check if is a media connection.
     *
     * @return boolean
     */
    public function isMedia() : bool
    {
        return $this->ctx->isMedia();
    }
    /**
     * Check if is a CDN connection.
     *
     * @return boolean
     */
    public function isCDN() : bool
    {
        return $this->ctx->isCDN();
    }
    /**
     * Connects to a telegram DC using the specified protocol, proxy and connection parameters.
     *
     * @param ConnectionContext $ctx Connection context
     *
     * @return \Generator
     *
     * @psalm-return \Generator<mixed, StreamInterface, mixed, void>
     */
    public function connect(ConnectionContext $ctx) : \Generator
    {
        $this->ctx = $ctx->getCtx();
        $this->datacenter = $ctx->getDc();
        $this->datacenterId = $this->datacenter . '.' . $this->id;
        $this->API->logger->logger("Connecting to DC {$this->datacenterId}", \danog\MadelineProto\Logger::WARNING);
        $this->createSession();
        $ctx->setReadCallback([$this, 'haveRead']);
        $this->stream = (yield from $ctx->getStream());
        $this->API->logger->logger("Connected to DC {$this->datacenterId}!", \danog\MadelineProto\Logger::WARNING);
        if ($this->needsReconnect) {
            $this->needsReconnect = false;
        }
        $this->httpReqCount = 0;
        $this->httpResCount = 0;
        if (!isset($this->writer)) {
            $this->writer = new WriteLoop($this);
        }
        if (!isset($this->reader)) {
            $this->reader = new ReadLoop($this);
        }
        if (!isset($this->checker)) {
            $this->checker = new CheckLoop($this);
        }
        if (!isset($this->cleanup)) {
            $this->cleanup = new CleanupLoop($this);
        }
        if (!isset($this->waiter)) {
            $this->waiter = new HttpWaitLoop($this);
        }
        if (!isset($this->pinger) && !$this->ctx->isMedia()) {
            // && ($this->ctx->hasStreamName(WssStream::class) || $this->ctx->hasStreamName(WsStream::class))) {
            //$this->pinger = new PingLoop($this);
        }
        foreach ($this->new_outgoing as $message_id => $message) {
            if ($message->isUnencrypted()) {
                if (!($message->getState() & OutgoingMessage::STATE_REPLIED)) {
                    $message->reply(new Failure(new Exception('Restart because we were reconnected')));
                }
                unset($this->new_outgoing[$message_id], $this->outgoing_messages[$message_id]);
            }
        }
        $this->writer->start();
        $this->reader->start();
        if (!$this->checker->start()) {
            $this->checker->resume();
        }
        $this->cleanup->start();
        $this->waiter->start();
        if ($this->pinger) {
            $this->pinger->start();
        }
    }
    /**
     * Apply method abstractions.
     *
     * @param string $method Method name
     * @param array $arguments Arguments
     *
     * @return \Generator Whether we need to resolve a queue promise
     */
    private function methodAbstractions(string &$method, array &$arguments) : \Generator
    {
        if ($method === 'messages.importChatInvite' && isset($arguments['hash']) && \is_string($arguments['hash']) && ($r = Tools::parseLink($arguments['hash']))) {
            [$invite, $content] = $r;
            if ($invite) {
                $arguments['hash'] = $content;
            } else {
                $method = 'channels.joinChannel';
                $arguments['channel'] = $content;
            }
        } elseif ($method === 'messages.checkChatInvite' && isset($arguments['hash']) && \is_string($arguments['hash']) && ($r = Tools::parseLink($arguments['hash']))) {
            [$invite, $content] = $r;
            if (!$invite) {
                throw new TL\Exception('This is not an invite link!');
            }
            $arguments['hash'] = $content;
        } elseif ($method === 'channels.joinChannel' && isset($arguments['channel']) && \is_string($arguments['channel']) && ($r = Tools::parseLink($arguments['channel']))) {
            [$invite, $content] = $r;
            if ($invite) {
                $method = 'messages.importChatInvite';
                $arguments['hash'] = $content;
            } else {
                $arguments['channel'] = $content;
            }
        } elseif ($method === 'messages.sendMessage' && isset($arguments['peer']['_']) && \in_array($arguments['peer']['_'], ['inputEncryptedChat', 'updateEncryption', 'updateEncryptedChatTyping', 'updateEncryptedMessagesRead', 'updateNewEncryptedMessage', 'encryptedMessage', 'encryptedMessageService'])) {
            $method = 'messages.sendEncrypted';
            $arguments = ['peer' => $arguments['peer'], 'message' => $arguments];
            if (!isset($arguments['message']['_'])) {
                $arguments['message']['_'] = 'decryptedMessage';
            }
            if (!isset($arguments['message']['ttl'])) {
                $arguments['message']['ttl'] = 0;
            }
            if (isset($arguments['message']['reply_to_msg_id'])) {
                $arguments['message']['reply_to_random_id'] = $arguments['message']['reply_to_msg_id'];
            }
        } elseif ($method === 'messages.sendEncryptedFile' || $method === 'messages.uploadEncryptedFile') {
            if (isset($arguments['file'])) {
                if ((!\is_array($arguments['file']) || !(isset($arguments['file']['_']) && $this->API->getTL()->getConstructors()->findByPredicate($arguments['file']['_']) === 'InputEncryptedFile')) && $this->API->getSettings()->getFiles()->getAllowAutomaticUpload()) {
                    $arguments['file'] = (yield from $this->API->uploadEncrypted($arguments['file']));
                }
                if (isset($arguments['file']['key'])) {
                    $arguments['message']['media']['key'] = $arguments['file']['key'];
                }
                if (isset($arguments['file']['iv'])) {
                    $arguments['message']['media']['iv'] = $arguments['file']['iv'];
                }
                if (isset($arguments['file']['size'])) {
                    $arguments['message']['media']['size'] = $arguments['file']['size'];
                }
            }
            $arguments['queuePromise'] = new Deferred();
            return $arguments['queuePromise'];
        } elseif (\in_array($method, ['messages.addChatUser', 'messages.deleteChatUser', 'messages.editChatAdmin', 'messages.editChatPhoto', 'messages.editChatTitle', 'messages.getFullChat', 'messages.exportChatInvite', 'messages.editChatAdmin', 'messages.migrateChat']) && isset($arguments['chat_id']) && (!\is_numeric($arguments['chat_id']) || $arguments['chat_id'] < 0)) {
            $res = (yield from $this->API->getInfo($arguments['chat_id']));
            if ($res['type'] !== 'chat') {
                throw new \danog\MadelineProto\Exception('chat_id is not a chat id (only normal groups allowed, not supergroups)!');
            }
            $arguments['chat_id'] = $res['chat_id'];
        } elseif ($method === 'photos.updateProfilePhoto') {
            if (isset($arguments['id'])) {
                if (!\is_array($arguments['id'])) {
                    $method = 'photos.uploadProfilePhoto';
                    $arguments['file'] = $arguments['id'];
                }
            } elseif (isset($arguments['file'])) {
                $method = 'photos.uploadProfilePhoto';
            }
        } elseif ($method === 'photos.uploadProfilePhoto') {
            if (isset($arguments['file'])) {
                if (\is_array($arguments['file']) && !\in_array($arguments['file']['_'], ['inputFile', 'inputFileBig'])) {
                    $method = 'photos.uploadProfilePhoto';
                    $arguments['id'] = $arguments['file'];
                }
            } elseif (isset($arguments['id'])) {
                $method = 'photos.updateProfilePhoto';
            }
        } elseif ($method === 'messages.uploadMedia') {
            if (!isset($arguments['peer']) && !$this->API->getSelf()['bot']) {
                $arguments['peer'] = 'me';
            }
        } elseif ($method === 'channels.deleteUserHistory') {
            $method = 'channels.deleteParticipantHistory';
            if (isset($arguments['user_id'])) {
                $arguments['participant'] = $arguments['user_id'];
            }
        }
        if ($method === 'messages.sendEncrypted' || $method === 'messages.sendEncryptedService') {
            $arguments['queuePromise'] = new Deferred();
            return $arguments['queuePromise'];
        }
        return null;
    }
    /**
     * Send an MTProto message.
     *
     * @param OutgoingMessage $message The message to send
     * @param boolean $flush Whether to flush the message right away
     *
     * @return \Generator
     */
    public function sendMessage(OutgoingMessage $message, bool $flush = true) : \Generator
    {
        $message->trySend();
        $promise = $message->getSendPromise();
        if (!$message->hasSerializedBody() || $message->shouldRefreshReferences()) {
            $body = (yield from $message->getBody());
            if ($message->shouldRefreshReferences()) {
                $this->API->referenceDatabase->refreshNext(true);
            }
            if ($message->isMethod()) {
                $method = $message->getConstructor();
                $queuePromise = (yield from $this->methodAbstractions($method, $body));
                $body = (yield from $this->API->getTL()->serializeMethod($method, $body));
            } else {
                $body['_'] = $message->getConstructor();
                $body = (yield from $this->API->getTL()->serializeObject(['type' => ''], $body, $message->getConstructor()));
            }
            if ($message->shouldRefreshReferences()) {
                $this->API->referenceDatabase->refreshNext(false);
            }
            $message->setSerializedBody($body);
            unset($body);
        }
        $this->pendingOutgoing[$this->pendingOutgoingKey++] = $message;
        if (isset($queuePromise)) {
            $queuePromise->resolve();
        }
        if ($flush && isset($this->writer)) {
            $this->writer->resumeDeferOnce();
        }
        return (yield $promise);
    }
    /**
     * Flush pending packets.
     *
     * @return void
     */
    public function flush()
    {
        if (isset($this->writer)) {
            $this->writer->resumeDeferOnce();
        }
    }
    /**
     * Resume HttpWaiter.
     *
     * @return void
     */
    public function pingHttpWaiter()
    {
        if (isset($this->waiter)) {
            $this->waiter->resume();
        }
        if (isset($this->pinger)) {
            $this->pinger->resume();
        }
    }
    /**
     * Connect main instance.
     *
     * @param DataCenterConnection $extra Shared instance
     * @param int $id Connection ID
     *
     * @return void
     */
    public function setExtra($extra, int $id)
    {
        $this->shared = $extra;
        $this->id = $id;
        $this->API = $extra->getExtra();
        $this->logger = $this->API->logger;
    }
    /**
     * Get main instance.
     *
     * @return MTProto
     */
    public function getExtra() : MTProto
    {
        return $this->API;
    }
    /**
     * Get shared connection instance.
     *
     * @return DataCenterConnection
     */
    public function getShared() : DataCenterConnection
    {
        return $this->shared;
    }
    /**
     * Disconnect from DC.
     *
     * @param bool $temporary Whether the disconnection is temporary, triggered by the reconnect method
     *
     * @return void
     */
    public function disconnect(bool $temporary = false)
    {
        $this->API->logger->logger("Disconnecting from DC {$this->datacenterId}");
        $this->needsReconnect = true;
        foreach (['reader', 'writer', 'checker', 'waiter', 'updater', 'pinger', 'cleanup'] as $loop) {
            if (isset($this->{$loop}) && $this->{$loop}) {
                $this->{$loop}->signal($loop === 'reader' ? new NothingInTheSocketException() : true);
            }
        }
        if ($this->stream) {
            try {
                $this->stream->disconnect();
            } catch (ClosedException $e) {
                $this->API->logger->logger($e);
            }
        }
        if (!$temporary) {
            $this->shared->signalDisconnect($this->id);
        }
        $this->API->logger->logger("Disconnected from DC {$this->datacenterId}");
    }
    /**
     * Reconnect to DC.
     *
     * @return \Generator
     */
    public function reconnect() : \Generator
    {
        $this->API->logger->logger("Reconnecting DC {$this->datacenterId}");
        $this->disconnect(true);
        yield from $this->API->datacenter->dcConnect($this->ctx->getDc(), $this->id);
    }
    /**
     * Get name.
     *
     * @return string
     */
    public function getName() : string
    {
        return __CLASS__;
    }
}<?php

/**
 * Lang module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 * @link      https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

class Lang
{
    public static $lang = ['it' => ['phpseclib_fork' => 'Per favore installa questo fork di phpseclib: https://github.com/danog/phpseclib', 'nearest_dc' => 'Siamo in %s, il DC piÃ¹ vicino Ã¨ %d.', 'serialization_ofd' => 'La serializzazione non Ã¨ aggiornata, reistanziamento dell\'oggetto in corso!', 'getupdates_deserialization' => 'Ottenimento aggiornamenti dopo deserializzazione...', 'api_not_set' => 'Devi specificare una chiave ed un ID API, ottienili su https://my.telegram.org', 'session_corrupted' => 'La sessione si Ã¨ corrotta!', 'gen_perm_auth_key' => 'Generando chiave di autorizzazione permanente per il DC %s...', 'gen_temp_auth_key' => 'Generando chiave di autorizzazione temporanea per il DC %s...', 'write_client_info' => 'Scrittura info sul client (eseguendo nel contempo il metodo %s)...', 'config_updated' => 'La configurazione Ã¨ stata aggiornata!', 'length_not_4' => 'La lunghezza non Ã¨ uguale a 4', 'length_not_8' => 'La lunghezza non Ã¨ uguale a 8', 'value_bigger_than_2147483647' => 'Il valore fornito (%s) Ã¨ maggiore di 2147483647', 'value_smaller_than_2147483648' => 'Il valore fornito (%s) Ã¨ minore di -2147483648', 'value_bigger_than_9223372036854775807' => 'Il valore fornito (%s) Ã¨ maggiore di 9223372036854775807', 'value_smaller_than_9223372036854775808' => 'Il valore fornito (%s) Ã¨ minore di -9223372036854775808', 'value_bigger_than_4294967296' => 'Il valore fornito (%s) Ã¨ maggiore di 4294967296', 'value_smaller_than_0' => 'Il valore fornito (%s) Ã¨ minore di 0', 'encode_double_error' => 'Non sono riuscito a codificare il numero a virgola mobile fornito', 'file_not_exist' => 'Il file specificato non esiste', 'deserialization_error' => 'C\'Ã¨ stato un errore durante la deserializzazione', 'rpc_tg_error' => 'Telegram ha ritornato un errore RPC: %s (%s), causato da %s:%s%sTL trace:', 'v_error' => '506572206661766f726520616767696f726e612071756573746120696e7374616c6c617a696f6e65206469204d6164656c696e6550726f746f20636f6e206769742070756c6c206520636f6d706f73657220757064617465', 'v_tgerror' => '506572206661766f726520616767696f726e61207068702d6c69627467766f6970', 'protocol_invalid' => 'Ãˆ stato fornito un protocollo non valido', 'script_not_exist' => 'Lo script fornito non esiste', 'madelineproto_ready' => 'MadelineProto Ã¨ pronto!', 'logout_ok' => 'Il logout Ã¨ stato eseguito correttamente!', 'already_loggedIn' => 'Questa istanza di MadelineProto Ã¨ giÃ  loggata, prima faccio il logout...', 'login_ok' => 'Il login Ã¨ stato eseguito correttamente!', 'login_user' => 'Sto eseguendo il login come utente normale...', 'login_bot' => 'Sto eseguendo il login come bot...', 'login_code_sending' => 'Sto inviando il codice...', 'login_code_sent' => 'Il codice Ã¨ stato inviato correttamente! Una volta ricevuto il codice dovrai usare la funzione completePhoneLogin.', 'login_code_uncalled' => 'Non sto aspettando il codice! Usa la funzione phoneLogin.', 'login_2fa_enabled' => 'L\'autenticazione a due fattori Ã¨ abilitata, dovrai chiamare il metodo complete2falogin...', 'login_need_signup' => 'Questo numero non Ã¨ registrato su telegram, dovrai chiamare la funzione completeSignup...', 'login_auth_key' => 'Sto facendo il login con la chiave di autorizzazione...', 'not_loggedIn' => 'Non ho ancora fatto il login!', 'signup_uncalled' => 'Chiama prima le funzioni phoneLogin e completePhoneLogin.', 'signing_up' => 'Mi sto registrando su telegram come utente normale...', 'signup_ok' => 'Mi sono registrato su Telegram!', '2fa_uncalled' => 'Non sto aspettando la password, chiama prima le funzioni phoneLogin e completePhoneLogin!', 'libtgvoip_required' => 'Ãˆ necessario installare l\'estensione php-libtgvoip per accettare e gestire chiamate vocali, vistate https://docs.madelineproto.xyz per piÃ¹ info.', 'peer_not_in_db' => 'Questo utente/gruppo/canale non Ã¨ presente nel database interno MadelineProto', 'generating_a' => 'Sto generando a...', 'generating_g_a' => 'Sto generando g_a...', 'call_error_1' => 'Impossibile trovare ed accettare la chiamata %s', 'accepting_call' => 'Sto accettando una chiamata da %s...', 'generating_b' => 'Sto generando b...', 'call_already_accepted' => 'La chiamata %s Ã¨ giÃ  stata accettata.', 'call_already_declined' => 'La chiamata %s Ã¨ giÃ  stata annullata.', 'call_error_2' => 'Impossibile trovare e confermare la chiamata %s', 'call_confirming' => 'Sto confermando una chiamata da %s', 'call_error_3' => 'Impossibile trovare e completare la chiamata %s', 'call_completing' => 'Sto completando una chiamata da %s...', 'invalid_g_a' => 'g_a non valido!', 'fingerprint_invalid' => 'fingerprint della chiave non valido!', 'call_discarding' => 'Sto rifiutando la chiamata %s...', 'call_set_rating' => 'Sto inviando la recensione della chiamata %s...', 'call_debug_saving' => 'Sto inviando i dati di debug della chiamata %s...', 'TL_loading' => 'Sto caricando gli schemi TL...', 'file_parsing' => 'Leggendo %s...', 'crc32_mismatch' => 'CRC32 non valido (%s diverso da %s) per %s', 'src_file_invalid' => 'Ãˆ stato fornito un file sorgente non valido: ', 'translating_obj' => 'Traducendo gli oggetti...', 'translating_methods' => 'Traducendo i metodi...', 'bool_error' => 'Non sono riuscito ad estrarre un booleano', 'not_numeric' => 'Il valore fornito non Ã¨ numerico', 'long_not_16' => 'Il valore fornito non Ã¨ lungo 16 byte', 'long_not_32' => 'Il valore fornito non Ã¨ lungo 32 byte', 'long_not_64' => 'Il valore fornito non Ã¨ lungo 64 byte', 'array_invalid' => 'Il valore fornito non Ã¨ un array', 'predicate_not_set' => 'Il predicato (valore sotto chiave _, esempio [\'_\' => \'inputPeer\']) non Ã¨ impostato!', 'type_extract_error' => 'Impossibile estrarre il tipo "%s"', 'method_not_found' => 'Impossibile trovare il seguente metodo: ', 'params_missing' => 'Non hai fornito un parametro obbligatorio, rileggi la documentazione API', 'sec_peer_not_in_db' => 'La chat segreta non Ã¨ presente nel database interno MadelineProto', 'stream_handle_invalid' => 'Il valore fornito non Ã¨ uno stream', 'length_too_big' => 'Il valore fornito Ã¨ troppo lungo', 'type_extract_error_id' => 'Non sono riuscito ad estrarre il tipo %s con ID %s', 'constructor_not_found' => 'Costruttore non trovato per tipo: ', 'rand_bytes_too_small' => 'random_bytes Ã¨ troppo corto!', 'botapi_conversion_error' => 'Non sono risucito a convertire %s in un oggetto bot API', 'non_text_conversion' => 'Non posso ancora convertire messaggi media', 'last_byte_invalid' => 'L\'ultimo byte non Ã¨ valido', 'file_type_invalid' => 'Ãˆ stato fornito un tipo file errato', 'secret_chat_skipping' => 'Non ho la chat segreta %s nel database, ignorando messaggio', 'fingerprint_mismatch' => 'Fingerprint della chiave non valido', 'msg_data_length_too_big' => 'message_data_length Ã¨ troppo grande', 'length_not_divisible_16' => 'La lunghezza dei dati decifrati non Ã¨ divisibile per 16', 'done' => 'Fatto!', 'cdn_reupload' => 'Il file non Ã¨ disponibile sul nostro CDN, richiedo la copia!', 'stored_on_cdn' => 'Il file Ã¨ scaricabile tramite CDN!', 'apiAppInstructionsAuto0' => 'Inserisci il nome dell\'app, puÃ² essere qualsiasi cosa: ', 'apiAppInstructionsAuto1' => 'Inserisci il nome ridotto dell\'app, caratteri alfanumerici: ', 'apiAppInstructionsAuto2' => 'Inserisci il sito internet dell\'app, oppure t.me/username: ', 'apiAppInstructionsAuto3' => 'Inserisci la piattaforma dell\'app: ', 'apiAppInstructionsAuto4' => 'Descrivi la tua app: ', 'apiAppInstructionsManual0' => 'titolo dell\'app, puÃ² essere qualsiasi cosa', 'apiAppInstructionsManual1' => 'il nome ridotto dell\'app, caratteri alfanumerici: ', 'apiAppInstructionsManual2' => 'L\'indirizzo del tuo sito, oppure t.me/username', 'apiAppInstructionsManual3' => 'Qualsiasi', 'apiAppInstructionsManual4' => 'Descrivi la tua app', 'apiAutoPrompt0' => 'Inserisci un numero di telefono che Ã¨ giÃ  registrato su Telegram: ', 'apiAutoPrompt1' => 'Inserisci il codice di verifica che hai ricevuto su Telegram: ', 'apiChooseManualAutoTip' => 'Nota che puoi anche fornire i parametri API direttamente nelle impostazioni: %s', 'apiChoosePrompt' => 'La tua scelta (m/a): ', 'apiError' => 'ERRORE: %s. Prova ancora.', 'apiManualInstructions0' => 'Effettua il login su https://my.telegram.org', 'apiManualInstructions1' => 'Vai su API development tools', 'apiManualInstructions2' => 'Clicca su create application', 'apiManualPrompt0' => 'Inserisci il tuo API ID: ', 'apiManualPrompt1' => 'Inserisci il tuo API hash: ', 'apiParamsError' => 'Non hai fornito tutti i parametri richiesti!', 'loginBot' => 'Inserisci il tuo bot token: ', 'loginChoosePrompt' => 'Vuoi effettuare il login come utente o come bot (u/b)? ', 'loginNoCode' => 'Non hai fornito un codice di verifica!', 'loginNoName' => 'Non hai fornito un nome!', 'loginNoPass' => 'Non hai fornito la password!', 'loginUser' => 'Inserisci il tuo numero di telefono: ', 'loginUserPass' => 'Inserisci la tua password (suggerimento %s): ', 'loginUserPassHint' => 'Suggerimento: %s', 'loginUserPassWeb' => 'Inserisci la tua password: ', 'loginUserCode' => 'Inserisci il codice di verifica: ', 'signupFirstName' => 'Inserisci il tuo nome: ', 'signupFirstNameWeb' => 'Nome', 'signupLastName' => 'Inserisci il tuo cognome: ', 'signupLastNameWeb' => 'Cognome', 'signupWeb' => 'Registrazione', 'go' => 'Vai', 'loginChoosePromptWeb' => 'Vuoi effettuare il login come utente o come bot?', 'loginOptionBot' => 'Bot', 'loginOptionUser' => 'Utente', 'loginBotTokenWeb' => 'Token del bot', 'loginUserPhoneCodeWeb' => 'Codice di verifica', 'loginUserPhoneWeb' => 'Numero di telefono', 'apiAutoWeb' => 'Inserisci un numero di telefono <b>gi&agrave; registrato su Telegram</b> per ottenere l&apos;API ID', 'apiChooseManualAuto' => 'You did not define a valid API ID/API hash. Do you want to define it now manually, or automatically? (m/a)', 'apiManualWeb' => 'Inserisci il tuo API ID e API hash', 'apiAppInstructionsAutoTypeOther' => 'Altro (specificare nella descrizione)', 'apiAppWeb' => 'Inserire informazioni API', 'apiChooseAutomaticallyWeb' => 'Automaticamente', 'apiChooseManualAutoTipWeb' => 'Nota che puoi anche fornire i parametri API direttamente nelle <a target="_blank" href="%s">impostazioni</a>.', 'apiChooseManualAutoWeb' => 'Vuoi configurare il tuo API ID/hash manualmente o automaticamente?', 'apiChooseManuallyWeb' => 'Manualmente'], 'en' => ['go' => 'Go', 'apiChooseManualAuto' => 'Do you want to enter the API id and the API hash manually or automatically? (m/a)', 'apiChooseManualAutoWeb' => 'Do you want to enter the API id and the API hash manually or automatically?', 'apiChooseManualAutoTip' => 'Note that you can also provide them directly in the code using the settings: %s', 'apiChooseManualAutoTipWeb' => 'Note that you can also provide them directly in the code using the <a target="_blank" href="%s">settings</a>.', 'apiChoosePrompt' => 'Your choice (m/a): ', 'apiChooseAutomaticallyWeb' => 'Automatically', 'apiChooseManuallyWeb' => 'Manually', 'apiManualInstructions0' => 'Login to https://my.telegram.org', 'apiManualInstructions1' => 'Go to API development tools', 'apiManualInstructions2' => 'Click on create application', 'apiAppInstructionsManual0' => 'your app\'s name, can be anything', 'apiAppInstructionsManual1' => 'your app\'s short name, alphanumeric, 5-32 characters', 'apiAppInstructionsManual2' => 'your app/website\'s URL, or t.me/yourusername', 'apiAppInstructionsManual3' => 'anything', 'apiAppInstructionsManual4' => 'Describe your app here', 'apiManualWeb' => 'Enter your API ID and API hash', 'apiManualPrompt0' => 'Enter your API ID: ', 'apiManualPrompt1' => 'Enter your API hash: ', 'apiAutoWeb' => 'Enter a phone number that is <b>already registered</b> on telegram to get the API ID', 'apiAutoPrompt0' => 'Enter a phone number that is already registered on Telegram: ', 'apiAutoPrompt1' => 'Enter the verification code you received in Telegram: ', 'apiAppWeb' => 'Enter API information', 'apiAppInstructionsAuto0' => 'Enter the app\'s name, can be anything: ', 'apiAppInstructionsAuto1' => 'Enter the app\'s short name, alphanumeric, 5-32 characters: ', 'apiAppInstructionsAuto2' => 'Enter the app/website\'s URL, or t.me/yourusername: ', 'apiAppInstructionsAuto3' => 'Enter the app platform: ', 'apiAppInstructionsAuto4' => 'Describe your app: ', 'apiAppInstructionsAutoTypeOther' => 'Other (specify in description)', 'apiParamsError' => 'You didn\'t provide all of the required parameters!', 'apiError' => 'ERROR: %s. Try again.', 'loginChoosePrompt' => 'Do you want to login as user or bot (u/b)? ', 'loginChoosePromptWeb' => 'Do you want to login as user or bot?', 'loginOptionBot' => 'Bot', 'loginOptionUser' => 'User', 'loginBot' => 'Enter your bot token: ', 'loginUser' => 'Enter your phone number: ', 'loginUserCode' => 'Enter the code: ', 'loginUserPass' => 'Enter your password (hint %s): ', 'loginUserPassWeb' => 'Enter your password: ', 'loginUserPassHint' => 'Hint: %s', 'signupFirstName' => 'Enter your first name: ', 'signupLastName' => 'Enter your last name (can be empty): ', 'signupWeb' => 'Sign up please', 'signupFirstNameWeb' => 'First name', 'signupLastNameWeb' => 'Last name', 'loginNoCode' => 'You didn\'t provide a phone code!', 'loginNoPass' => 'You didn\'t provide the password!', 'loginNoName' => 'You didn\'t provide the first name!', 'loginBotTokenWeb' => 'Bot token', 'loginUserPhoneWeb' => 'Phone number', 'loginUserPhoneCodeWeb' => 'Code', 'done' => 'Done!', 'cdn_reupload' => 'File is not stored on CDN, requesting reupload!', 'stored_on_cdn' => 'File is stored on CDN!', 'phpseclib_fork' => 'Please install this fork of phpseclib: https://github.com/danog/phpseclib', 'nearest_dc' => 'We\'re in %s, nearest DC is %d.', 'serialization_ofd' => 'Serialization is out of date, reconstructing object!', 'getupdates_deserialization' => 'Getting updates after deserialization...', 'api_not_set' => 'You must provide an api key and an api id, get your own @ my.telegram.org', 'session_corrupted' => 'The session is corrupted!', 'gen_perm_auth_key' => 'Generating permanent authorization key for DC %s...', 'gen_temp_auth_key' => 'Generating temporary authorization key for DC %s...', 'write_client_info' => 'Writing client info (also executing %s)...', 'config_updated' => 'Updated config!', 'length_not_4' => 'Length is not equal to 4', 'length_not_8' => 'Length is not equal to 8', 'value_bigger_than_2147483647' => 'Provided value %s is bigger than 2147483647', 'value_smaller_than_2147483648' => 'Provided value %s is smaller than -2147483648', 'value_bigger_than_9223372036854775807' => 'Provided value %s is bigger than 9223372036854775807', 'value_smaller_than_9223372036854775808' => 'Provided value %s is smaller than -9223372036854775808', 'value_bigger_than_4294967296' => 'Provided value %s is bigger than 4294967296', 'value_smaller_than_0' => 'Provided value %s is smaller than 0', 'encode_double_error' => 'Could not properly encode double', 'file_not_exist' => 'File does not exist', 'deserialization_error' => 'An error occurred on deserialization', 'rpc_tg_error' => 'Telegram returned an RPC error: %s (%s), caused by %s:%s%sTL trace:', 'v_error' => '506c656173652075706461746520746f20746865206c61746573742076657273696f6e206f66204d6164656c696e6550726f746f2e', 'v_tgerror' => '506c6561736520757064617465207068702d6c69627467766f6970', 'protocol_invalid' => 'Connection: invalid protocol specified.', 'script_not_exist' => 'Provided script does not exist', 'madelineproto_ready' => 'MadelineProto is ready!', 'logout_ok' => 'Logged out successfully!', 'already_loggedIn' => 'This instance of MadelineProto is already logged in. Logging out first...', 'login_ok' => 'Logged in successfully!', 'login_user' => 'Logging in as a normal user...', 'login_bot' => 'Logging in as a bot...', 'login_code_sending' => 'Sending code...', 'login_code_sent' => 'Code sent successfully! Once you receive the code you should use the completePhoneLogin function.', 'login_code_uncalled' => 'I\'m not waiting for the code! Please call the phoneLogin method first', 'login_2fa_enabled' => '2FA enabled, you will have to call the complete2falogin function...', 'login_need_signup' => 'An account has not been created for this number, you will have to call the completeSignup function...', 'login_auth_key' => 'Logging in using auth key...', 'not_loggedIn' => 'I\'m not logged in!', 'signup_uncalled' => 'I\'m not waiting to signup! Please call the phoneLogin and the completePhoneLogin methods first!', 'signing_up' => 'Signing up as a normal user...', 'signup_ok' => 'Signed up in successfully!', '2fa_uncalled' => 'I\'m not waiting for the password! Please call the phoneLogin and the completePhoneLogin methods first!', 'libtgvoip_required' => 'The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.', 'peer_not_in_db' => 'This peer is not present in the internal peer database', 'generating_a' => 'Generating a...', 'generating_g_a' => 'Generating g_a...', 'call_error_1' => 'Could not find and accept call %s', 'accepting_call' => 'Accepting call from %s...', 'generating_b' => 'Generating b...', 'call_already_accepted' => 'Call %s already accepted', 'call_already_declined' => 'Call %s already declined', 'call_error_2' => 'Could not find and confirm call %s', 'call_confirming' => 'Confirming call from %s...', 'call_error_3' => 'Could not find and complete call %s', 'call_completing' => 'Completing call from %s...', 'invalid_g_a' => 'Invalid g_a!', 'fingerprint_invalid' => 'Invalid key fingerprint!', 'call_discarding' => 'Discarding call %s...', 'call_set_rating' => 'Setting rating for call %s...', 'call_debug_saving' => 'Saving debug data for call %s...', 'TL_loading' => 'Loading TL schemes...', 'file_parsing' => 'Parsing %s...', 'crc32_mismatch' => 'CRC32 mismatch (%s, %s) for %s', 'src_file_invalid' => 'Invalid source file was provided: ', 'translating_obj' => 'Translating objects...', 'translating_methods' => 'Translating methods...', 'bool_error' => 'Could not extract boolean', 'not_numeric' => 'Given value isn\'t numeric', 'long_not_16' => 'Given value is not 16 bytes long', 'long_not_32' => 'Given value is not 32 bytes long', 'long_not_64' => 'Given value is not 64 bytes long', 'array_invalid' => 'You didn\'t provide a valid array', 'predicate_not_set' => 'Predicate (value under _) was not set!', 'type_extract_error' => 'Could not extract type "%s", you should update MadelineProto!', 'method_not_found' => 'Could not find method: ', 'params_missing' => 'Missing required parameter', 'sec_peer_not_in_db' => 'This secret peer is not present in the internal peer database', 'stream_handle_invalid' => 'An invalid stream handle was provided.', 'length_too_big' => 'Length is too big', 'type_extract_error_id' => 'Could not extract type: %s with id %s, you should update MadelineProto!', 'constructor_not_found' => 'Constructor not found for type: ', 'rand_bytes_too_small' => 'Random_bytes is too small!', 'botapi_conversion_error' => 'Can\'t convert %s to a bot API object', 'non_text_conversion' => 'Can\'t convert non text messages yet!', 'last_byte_invalid' => 'Invalid last byte', 'file_type_invalid' => 'Invalid file type detected (%s)', 'secret_chat_skipping' => 'I do not have the secret chat %s in the database, skipping message...', 'fingerprint_mismatch' => 'Key fingerprint mismatch', 'msg_data_length_too_big' => 'Message_data_length is too big', 'length_not_divisible_16' => 'Length of decrypted data is not divisible by 16']];
    // THIS WILL BE OVERWRITTEN BY $lang["en"]
    public static $current_lang = ['go' => 'Go', 'apiChooseManualAuto' => 'Do you want to enter the API id and the API hash manually or automatically? (m/a)', 'apiChooseManualAutoWeb' => 'Do you want to enter the API id and the API hash manually or automatically?', 'apiChooseManualAutoTip' => 'Note that you can also provide them directly in the code using the settings: %s', 'apiChooseManualAutoTipWeb' => 'Note that you can also provide them directly in the code using the <a href="%s">settings</a>.', 'apiChoosePrompt' => 'Your choice (m/a): ', 'apiChooseAutomaticallyWeb' => 'Automatically', 'apiChooseManuallyWeb' => 'Manually', 'apiManualInstructions0' => 'Login to https://my.telegram.org', 'apiManualInstructions1' => 'Go to API development tools', 'apiManualInstructions2' => 'Click on create application', 'apiAppInstructionsManual0' => 'your app\'s name, can be anything', 'apiAppInstructionsManual1' => 'your app\'s short name, alphanumeric, 5-32 characters', 'apiAppInstructionsManual2' => 'your app/website\'s URL, or t.me/yourusername', 'apiAppInstructionsManual3' => 'anything', 'apiAppInstructionsManual4' => 'Describe your app here', 'apiManualWeb' => 'Enter your API ID and API hash', 'apiManualPrompt0' => 'Enter your API ID: ', 'apiManualPrompt1' => 'Enter your API hash: ', 'apiAutoWeb' => 'Enter a phone number that is <b>already registered</b> on telegram to get the API ID', 'apiAutoPrompt0' => 'Enter a phone number that is already registered on Telegram: ', 'apiAutoPrompt1' => 'Enter the verification code you received in Telegram: ', 'apiAppWeb' => 'Enter API information', 'apiAppInstructionsAuto0' => 'Enter the app\'s name, can be anything: ', 'apiAppInstructionsAuto1' => 'Enter the app\'s short name, alphanumeric, 5-32 characters: ', 'apiAppInstructionsAuto2' => 'Enter the app/website\'s URL, or t.me/yourusername: ', 'apiAppInstructionsAuto3' => 'Enter the app platform: ', 'apiAppInstructionsAuto4' => 'Describe your app: ', 'apiAppInstructionsAutoTypeOther' => 'Other (specify in description)', 'apiParamsError' => 'You didn\'t provide all of the required parameters!', 'apiError' => 'ERROR: %s. Try again.', 'loginChoosePrompt' => 'Do you want to login as user or bot (u/b)? ', 'loginChoosePromptWeb' => 'Do you want to login as user or bot?', 'loginOptionBot' => 'Bot', 'loginOptionUser' => 'User', 'loginBot' => 'Enter your bot token: ', 'loginUser' => 'Enter your phone number: ', 'loginUserCode' => 'Enter the code: ', 'loginUserPass' => 'Enter your password (hint %s): ', 'loginUserPassWeb' => 'Enter your password: ', 'loginUserPassHint' => 'Hint: %s', 'signupFirstName' => 'Enter your first name: ', 'signupLastName' => 'Enter your last name (can be empty): ', 'signupWeb' => 'Sign up please', 'signupFirstNameWeb' => 'First name', 'signupLastNameWeb' => 'Last name', 'loginNoCode' => 'You didn\'t provide a phone code!', 'loginNoPass' => 'You didn\'t provide the password!', 'loginNoName' => 'You didn\'t provide the first name!', 'loginBotTokenWeb' => 'Bot token', 'loginUserPhoneWeb' => 'Phone number', 'loginUserPhoneCodeWeb' => 'Code', 'done' => 'Done!', 'cdn_reupload' => 'File is not stored on CDN, requesting reupload!', 'stored_on_cdn' => 'File is stored on CDN!', 'phpseclib_fork' => 'Please install this fork of phpseclib: https://github.com/danog/phpseclib', 'nearest_dc' => 'We\'re in %s, nearest DC is %d.', 'serialization_ofd' => 'Serialization is out of date, reconstructing object!', 'getupdates_deserialization' => 'Getting updates after deserialization...', 'api_not_set' => 'You must provide an api key and an api id, get your own @ my.telegram.org', 'session_corrupted' => 'The session is corrupted!', 'gen_perm_auth_key' => 'Generating permanent authorization key for DC %s...', 'gen_temp_auth_key' => 'Generating temporary authorization key for DC %s...', 'write_client_info' => 'Writing client info (also executing %s)...', 'config_updated' => 'Updated config!', 'length_not_4' => 'Length is not equal to 4', 'length_not_8' => 'Length is not equal to 8', 'value_bigger_than_2147483647' => 'Provided value %s is bigger than 2147483647', 'value_smaller_than_2147483648' => 'Provided value %s is smaller than -2147483648', 'value_bigger_than_9223372036854775807' => 'Provided value %s is bigger than 9223372036854775807', 'value_smaller_than_9223372036854775808' => 'Provided value %s is smaller than -9223372036854775808', 'value_bigger_than_4294967296' => 'Provided value %s is bigger than 4294967296', 'value_smaller_than_0' => 'Provided value %s is smaller than 0', 'encode_double_error' => 'Could not properly encode double', 'file_not_exist' => 'File does not exist', 'deserialization_error' => 'An error occurred on deserialization', 'rpc_tg_error' => 'Telegram returned an RPC error: %s (%s), caused by %s:%s%sTL trace:', 'v_error' => '506c656173652075706461746520746f20746865206c61746573742076657273696f6e206f66204d6164656c696e6550726f746f2e', 'v_tgerror' => '506c6561736520757064617465207068702d6c69627467766f6970', 'protocol_invalid' => 'Connection: invalid protocol specified.', 'script_not_exist' => 'Provided script does not exist', 'madelineproto_ready' => 'MadelineProto is ready!', 'logout_ok' => 'Logged out successfully!', 'already_loggedIn' => 'This instance of MadelineProto is already logged in. Logging out first...', 'login_ok' => 'Logged in successfully!', 'login_user' => 'Logging in as a normal user...', 'login_bot' => 'Logging in as a bot...', 'login_code_sending' => 'Sending code...', 'login_code_sent' => 'Code sent successfully! Once you receive the code you should use the completePhoneLogin function.', 'login_code_uncalled' => 'I\'m not waiting for the code! Please call the phoneLogin method first', 'login_2fa_enabled' => '2FA enabled, you will have to call the complete2falogin function...', 'login_need_signup' => 'An account has not been created for this number, you will have to call the completeSignup function...', 'login_auth_key' => 'Logging in using auth key...', 'not_loggedIn' => 'I\'m not logged in!', 'signup_uncalled' => 'I\'m not waiting to signup! Please call the phoneLogin and the completePhoneLogin methods first!', 'signing_up' => 'Signing up as a normal user...', 'signup_ok' => 'Signed up in successfully!', '2fa_uncalled' => 'I\'m not waiting for the password! Please call the phoneLogin and the completePhoneLogin methods first!', 'libtgvoip_required' => 'The php-libtgvoip extension is required to accept and manage calls. See daniil.it/MadelineProto for more info.', 'peer_not_in_db' => 'This peer is not present in the internal peer database', 'generating_a' => 'Generating a...', 'generating_g_a' => 'Generating g_a...', 'call_error_1' => 'Could not find and accept call %s', 'accepting_call' => 'Accepting call from %s...', 'generating_b' => 'Generating b...', 'call_already_accepted' => 'Call %s already accepted', 'call_already_declined' => 'Call %s already declined', 'call_error_2' => 'Could not find and confirm call %s', 'call_confirming' => 'Confirming call from %s...', 'call_error_3' => 'Could not find and complete call %s', 'call_completing' => 'Completing call from %s...', 'invalid_g_a' => 'Invalid g_a!', 'fingerprint_invalid' => 'Invalid key fingerprint!', 'call_discarding' => 'Discarding call %s...', 'call_set_rating' => 'Setting rating for call %s...', 'call_debug_saving' => 'Saving debug data for call %s...', 'TL_loading' => 'Loading TL schemes...', 'file_parsing' => 'Parsing %s...', 'crc32_mismatch' => 'CRC32 mismatch (%s, %s) for %s', 'src_file_invalid' => 'Invalid source file was provided: ', 'translating_obj' => 'Translating objects...', 'translating_methods' => 'Translating methods...', 'bool_error' => 'Could not extract boolean', 'not_numeric' => 'Given value isn\'t numeric', 'long_not_16' => 'Given value is not 16 bytes long', 'long_not_32' => 'Given value is not 32 bytes long', 'long_not_64' => 'Given value is not 64 bytes long', 'array_invalid' => 'You didn\'t provide a valid array', 'predicate_not_set' => 'Predicate (value under _) was not set!', 'type_extract_error' => 'Could not extract type "%s", you should update MadelineProto!', 'method_not_found' => 'Could not find method: ', 'params_missing' => 'Missing required parameter', 'sec_peer_not_in_db' => 'This secret peer is not present in the internal peer database', 'stream_handle_invalid' => 'An invalid stream handle was provided.', 'length_too_big' => 'Length is too big', 'type_extract_error_id' => 'Could not extract type: %s with id %s, you should update MadelineProto!', 'constructor_not_found' => 'Constructor not found for type: ', 'rand_bytes_too_small' => 'Random_bytes is too small!', 'botapi_conversion_error' => 'Can\'t convert %s to a bot API object', 'non_text_conversion' => 'Can\'t convert non text messages yet!', 'last_byte_invalid' => 'Invalid last byte', 'file_type_invalid' => 'Invalid file type detected (%s)', 'secret_chat_skipping' => 'I do not have the secret chat %s in the database, skipping message...', 'fingerprint_mismatch' => 'Key fingerprint mismatch', 'msg_data_length_too_big' => 'Message_data_length is too big', 'length_not_divisible_16' => 'Length of decrypted data is not divisible by 16'];
}resPQ#05162463 nonce:int128 server_nonce:int128 pq:string server_public_key_fingerprints:Vector<long> = ResPQ;

vector {t:Type} # [ t ] = Vector t;

p_q_inner_data_dc#a9f55f95 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 dc:int = P_Q_inner_data;
p_q_inner_data_temp_dc#56fddf88 pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 dc:int expires_in:int = P_Q_inner_data;

p_q_inner_data pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data;
p_q_inner_data_temp pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 expires_in:int = P_Q_inner_data;

server_DH_params_fail#79cb045d nonce:int128 server_nonce:int128 new_nonce_hash:int128 = Server_DH_Params;
server_DH_params_ok#d0e8075c nonce:int128 server_nonce:int128 encrypted_answer:string = Server_DH_Params;

server_DH_inner_data#b5890dba nonce:int128 server_nonce:int128 g:int dh_prime:string g_a:string server_time:int = Server_DH_inner_data;

client_DH_inner_data#6643b654 nonce:int128 server_nonce:int128 retry_id:long g_b:string = Client_DH_Inner_Data;

dh_gen_ok#3bcbf734 nonce:int128 server_nonce:int128 new_nonce_hash1:int128 = Set_client_DH_params_answer;
dh_gen_retry#46dc1fb9 nonce:int128 server_nonce:int128 new_nonce_hash2:int128 = Set_client_DH_params_answer;
dh_gen_fail#a69dae02 nonce:int128 server_nonce:int128 new_nonce_hash3:int128 = Set_client_DH_params_answer;

bind_auth_key_inner#75a3f765 nonce:long temp_auth_key_id:long perm_auth_key_id:long temp_session_id:long expires_at:int = BindAuthKeyInner;

rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult;
rpc_error#2144ca19 error_code:int error_message:string = RpcError;

rpc_answer_unknown#5e2ad36e = RpcDropAnswer;
rpc_answer_dropped_running#cd78e586 = RpcDropAnswer;
rpc_answer_dropped#a43ad8b7 msg_id:long seq_no:int bytes:int = RpcDropAnswer;

future_salt#0949d9dc valid_since:int valid_until:int salt:long = FutureSalt;
future_salts#ae500895 req_msg_id:long now:int salts:vector<future_salt> = FutureSalts;

pong#347773c5 msg_id:long ping_id:long = Pong;

destroy_session_ok#e22045fc session_id:long = DestroySessionRes;
destroy_session_none#62d350c9 session_id:long = DestroySessionRes;

new_session_created#9ec20908 first_msg_id:long unique_id:long server_salt:long = NewSession;

msg_container#73f1f8dc messages:vector<%Message> = MessageContainer;
message msg_id:long seqno:int bytes:int body:Object = Message;
msg_copy#e06046b2 orig_message:Message = MessageCopy;

gzip_packed#3072cfa1 packed_data:bytes = Object;

msgs_ack#62d6b459 msg_ids:Vector<long> = MsgsAck;

bad_msg_notification#a7eff811 bad_msg_id:long bad_msg_seqno:int error_code:int = BadMsgNotification;
bad_server_salt#edab447b bad_msg_id:long bad_msg_seqno:int error_code:int new_server_salt:long = BadMsgNotification;

msg_resend_ans_req#8610baeb msg_ids:Vector<long> = MsgResendReq;
msg_resend_req#7d861a08 msg_ids:Vector<long> = MsgResendReq;
msgs_state_req#da69fb52 msg_ids:Vector<long> = MsgsStateReq;
msgs_state_info#04deb57d req_msg_id:long info:string = MsgsStateInfo;
msgs_all_info#8cc0d131 msg_ids:Vector<long> info:string = MsgsAllInfo;
msg_detailed_info#276d3ec6 msg_id:long answer_msg_id:long bytes:int status:int = MsgDetailedInfo;
msg_new_detailed_info#809db6df answer_msg_id:long bytes:int status:int = MsgDetailedInfo;

rsa_public_key n:string e:string = RSAPublicKey;

http_wait#9299359f max_delay:int wait_after:int max_wait:int = HttpWait;

---functions---

req_pq_multi#be7e8ef1 nonce:int128 = ResPQ;

req_pq nonce:int128 = ResPQ;

req_DH_params#d712e4be nonce:int128 server_nonce:int128 p:string q:string public_key_fingerprint:long encrypted_data:string = Server_DH_Params;

set_client_DH_params#f5045f1f nonce:int128 server_nonce:int128 encrypted_data:string = Set_client_DH_params_answer;

rpc_drop_answer#58e4a740 req_msg_id:long = RpcDropAnswer;
get_future_salts#b921bd04 num:int = FutureSalts;
ping#7abe77ec ping_id:long = Pong;
ping_delay_disconnect#f3427b8c ping_id:long disconnect_delay:int = Pong;
destroy_session#e7512126 session_id:long = DestroySessionRes;

//test.useGzipPacked = GzipPacked;
//test.useServerDhInnerData = Server_DH_inner_data;
//test.useNewSessionCreated = NewSession;
//test.useMsgsAck = MsgsAck;
//test.useBadMsgNotification = BadMsgNotification;

//test.useOther key:rsa_public_key p_q_data:P_Q_inner_data dh_data:client_DH_inner_data = RpcError;
<?php

/**
 * FileCallback module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * File callback interface.
 */
class FileCallback implements FileCallbackInterface
{
    /**
     * File to download/upload.
     *
     * @var mixed
     */
    private $file;
    /**
     * Callback.
     *
     * @var callable
     */
    private $callback;
    /**
     * Construct file callback.
     *
     * @param mixed $file File to download/upload
     * @param callable $callback Callback
     */
    public function __construct($file, callable $callback)
    {
        $this->file = $file;
        $this->callback = $callback;
    }
    /**
     * Get file.
     *
     * @return mixed
     */
    public function getFile()
    {
        return $this->file;
    }
    /**
     * Invoke callback.
     *
     * @param int $percent Percent
     * @param int $speed Speed in mbps
     * @param int $time Time
     *
     * @return mixed
     */
    public function __invoke($percent, $speed, $time)
    {
        $callback = $this->callback;
        return $callback($percent, $speed, $time);
    }
}<?php

/**
 * NothingInTheSocketException module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

class NothingInTheSocketException extends \Exception
{
}<?php

/**
 * Connection module handling all connections to a datacenter.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
use danog\MadelineProto\Loop\Generic\PeriodicLoopInternal;
use danog\MadelineProto\MTProto\AuthKey;
use danog\MadelineProto\MTProto\OutgoingMessage;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProto\TempAuthKey;
use danog\MadelineProto\Settings\Connection as ConnectionSettings;
use danog\MadelineProto\Stream\ConnectionContext;
use danog\MadelineProto\Stream\MTProtoTransport\HttpsStream;
use danog\MadelineProto\Stream\MTProtoTransport\HttpStream;
use danog\MadelineProto\Stream\Transport\WssStream;
use JsonSerializable;
/**
 * Datacenter connection.
 */
class DataCenterConnection implements JsonSerializable
{
    const READ_WEIGHT = 1;
    const READ_WEIGHT_MEDIA = 5;
    const WRITE_WEIGHT = 10;
    /**
     * Promise for connection.
     *
     * @var Promise
     */
    private $connectionsPromise;
    /**
     * Deferred for connection.
     *
     * @var Deferred
     */
    private $connectionsDeferred;
    /**
     * Temporary auth key.
     *
     * @var TempAuthKey|null
     */
    private $tempAuthKey;
    /**
     * Permanent auth key.
     *
     * @var PermAuthKey|null
     */
    private $permAuthKey;
    /**
     * Connections open to a certain DC.
     *
     * @var array<int, Connection>
     */
    private $connections = [];
    /**
     * Connection weights.
     *
     * @var array<int, int>
     */
    private $availableConnections = [];
    /**
     * Main API instance.
     *
     * @var \danog\MadelineProto\MTProto
     */
    private $API;
    /**
     * Connection context.
     *
     * @var ConnectionContext
     */
    private $ctx;
    /**
     * DC ID.
     *
     * @var string
     */
    private $datacenter;
    /**
     * Linked DC ID.
     *
     * @var string
     */
    private $linked;
    /**
     * Loop to keep weights at sane value.
     */
    private ?PeriodicLoopInternal $robinLoop = null;
    /**
     * Decrement roundrobin weight by this value if busy reading.
     *
     * @var integer
     */
    private $decRead = 1;
    /**
     * Decrement roundrobin weight by this value if busy writing.
     *
     * @var integer
     */
    private $decWrite = 10;
    /**
     * Backed up messages.
     *
     * @var array
     */
    private $backup = [];
    /**
     * Whether this socket has to be reconnected.
     *
     * @var boolean
     */
    private $needsReconnect = false;
    /**
     * Indicate if this socket needs to be reconnected.
     *
     * @param boolean $needsReconnect Whether the socket has to be reconnected
     *
     * @return void
     */
    public function needReconnect(bool $needsReconnect)
    {
        $this->needsReconnect = $needsReconnect;
    }
    /**
     * Whether this sockets needs to be reconnected.
     *
     * @return boolean
     */
    public function shouldReconnect() : bool
    {
        return $this->needsReconnect;
    }
    /**
     * Get auth key.
     *
     * @param boolean $temp Whether to fetch the temporary auth key
     *
     * @return AuthKey
     */
    public function getAuthKey(bool $temp = true) : AuthKey
    {
        if ($this->{$temp ? 'tempAuthKey' : 'permAuthKey'} === null) {
            throw new NothingInTheSocketException();
        }
        return $this->{$temp ? 'tempAuthKey' : 'permAuthKey'};
    }
    /**
     * Check if auth key is present.
     *
     * @param bool $temp
     *
     * @return bool
     */
    public function hasAuthKey(bool $temp = true) : bool
    {
        return $this->{$temp ? 'tempAuthKey' : 'permAuthKey'} !== null && $this->{$temp ? 'tempAuthKey' : 'permAuthKey'}->hasAuthKey();
    }
    /**
     * Set auth key.
     *
     * @param (AuthKey | null) $key The auth key
     * @param bool $temp
     *
     * @return void
     */
    public function setAuthKey(?AuthKey $key, bool $temp = true) : void
    {
        $this->{$temp ? 'tempAuthKey' : 'permAuthKey'} = $key;
    }
    /**
     * Get temporary authorization key.
     *
     * @return TempAuthKey
     */
    public function getTempAuthKey() : TempAuthKey
    {
        return $this->getAuthKey(true);
    }
    /**
     * Get permanent authorization key.
     *
     * @return PermAuthKey
     */
    public function getPermAuthKey() : PermAuthKey
    {
        return $this->getAuthKey(false);
    }
    /**
     * Check if has temporary authorization key.
     *
     * @return boolean
     */
    public function hasTempAuthKey() : bool
    {
        return $this->hasAuthKey(true);
    }
    /**
     * Check if has permanent authorization key.
     *
     * @return boolean
     */
    public function hasPermAuthKey() : bool
    {
        return $this->hasAuthKey(false);
    }
    /**
     * Set temporary authorization key.
     *
     * @param (TempAuthKey | null) $key Auth key
     *
     * @return void
     */
    public function setTempAuthKey(?TempAuthKey $key) : void
    {
        $this->setAuthKey($key, true);
    }
    /**
     * Set permanent authorization key.
     *
     * @param (PermAuthKey | null) $key Auth key
     *
     * @return void
     */
    public function setPermAuthKey(?PermAuthKey $key) : void
    {
        $this->setAuthKey($key, false);
    }
    /**
     * Bind temporary and permanent auth keys.
     *
     * @param bool $pfs Whether to bind using PFS
     *
     * @return void
     */
    public function bind(bool $pfs = true)
    {
        if (!$pfs && !$this->tempAuthKey) {
            $this->tempAuthKey = new TempAuthKey();
        }
        $this->tempAuthKey->bind($this->permAuthKey, $pfs);
    }
    /**
     * Check if auth keys are bound.
     *
     * @return boolean
     */
    public function isBound() : bool
    {
        return $this->tempAuthKey ? $this->tempAuthKey->isBound() : false;
    }
    /**
     * Check if we are logged in.
     *
     * @return boolean
     */
    public function isAuthorized() : bool
    {
        return $this->hasTempAuthKey() ? $this->getTempAuthKey()->isAuthorized() : false;
    }
    /**
     * Set the authorized boolean.
     *
     * @param boolean $authorized Whether we are authorized
     *
     * @return void
     */
    public function authorized(bool $authorized)
    {
        if ($authorized) {
            $this->getTempAuthKey()->authorized($authorized);
        } elseif ($this->hasTempAuthKey()) {
            $this->getTempAuthKey()->authorized($authorized);
        }
    }
    /**
     * Link permanent authorization info of main DC to media DC.
     *
     * @param string $dc Main DC ID
     *
     * @return void
     */
    public function link(string $dc)
    {
        $this->linked = $dc;
        $this->permAuthKey =& $this->API->datacenter->getDataCenterConnection($dc)->permAuthKey;
    }
    /**
     * Reset MTProto sessions.
     *
     * @return void
     */
    public function resetSession()
    {
        foreach ($this->connections as $socket) {
            $socket->resetSession();
        }
    }
    /**
     * Create MTProto sessions if needed.
     *
     * @return void
     */
    public function createSession()
    {
        foreach ($this->connections as $socket) {
            $socket->createSession();
        }
    }
    /**
     * Flush all pending packets.
     *
     * @return void
     */
    public function flush() : void
    {
        foreach ($this->connections as $socket) {
            $socket->flush();
        }
    }
    /**
     * Get connection context.
     *
     * @return ConnectionContext
     */
    public function getCtx() : ConnectionContext
    {
        return $this->ctx;
    }
    /**
     * Has connection context?
     *
     * @return bool
     */
    public function hasCtx() : bool
    {
        return isset($this->ctx);
    }
    /**
     * Connect function.
     *
     * @param ConnectionContext $ctx Connection context
     * @param int $id Optional connection ID to reconnect
     *
     * @return \Generator
     */
    public function connect(ConnectionContext $ctx, int $id = -1) : \Generator
    {
        $this->API->logger->logger("Trying shared connection via {$ctx} ({$id})");
        $this->ctx = $ctx->getCtx();
        $this->datacenter = $ctx->getDc();
        $media = $ctx->isMedia() || $ctx->isCDN();
        $count = $media ? $this->API->getSettings()->getConnection()->getMinMediaSocketCount() : 1;
        if ($count > 1) {
            if (!$this->robinLoop) {
                $this->robinLoop = new PeriodicLoopInternal($this->API, [$this, 'even'], "robin loop DC {$this->datacenter}", $this->API->getSettings()->getConnection()->getRobinPeriod() * 1000);
            }
            $this->robinLoop->start();
        }
        $this->decRead = $media ? self::READ_WEIGHT_MEDIA : self::READ_WEIGHT;
        $this->decWrite = self::WRITE_WEIGHT;
        if ($id === -1 || !isset($this->connections[$id])) {
            if ($this->connections) {
                $this->API->logger->logger("Already connected!", Logger::WARNING);
                return;
            }
            yield from $this->connectMore($count);
            (yield $this->restoreBackup());
            $this->connectionsPromise = new Success();
            if ($this->connectionsDeferred) {
                $connectionsDeferred = $this->connectionsDeferred;
                $this->connectionsDeferred = null;
                $connectionsDeferred->resolve();
            }
        } else {
            $this->availableConnections[$id] = 0;
            yield from $this->connections[$id]->connect($ctx);
        }
    }
    /**
     * Connect to the DC using count more sockets.
     *
     * @param integer $count Number of sockets to open
     *
     * @return \Generator
     */
    private function connectMore(int $count) : \Generator
    {
        $ctx = $this->ctx->getCtx();
        $count += $previousCount = \count($this->connections);
        for ($x = $previousCount; $x < $count; $x++) {
            $connection = new Connection();
            $connection->setExtra($this, $x);
            yield from $connection->connect($ctx);
            $this->connections[$x] = $connection;
            $this->availableConnections[$x] = 0;
            $ctx = $this->ctx->getCtx();
        }
    }
    /**
     * Signal that a connection ID disconnected.
     *
     * @param integer $id Connection ID
     *
     * @return void
     */
    public function signalDisconnect(int $id)
    {
        $backup = $this->connections[$id]->backupSession();
        $list = '';
        foreach ($backup as $k => $message) {
            if ($message->getConstructor() === 'msgs_state_req' || $message->isUnencrypted()) {
                unset($backup[$k]);
                continue;
            }
            $list .= $message->getConstructor();
            $list .= ', ';
        }
        $this->API->logger->logger("Backed up {$list} from DC {$this->datacenter}.{$id}");
        $this->backup = \array_merge($this->backup, $backup);
        unset($this->connections[$id], $this->availableConnections[$id]);
    }
    /**
     * Close all connections to DC.
     *
     * @return void
     */
    public function disconnect() : void
    {
        $this->connectionsDeferred = new Deferred();
        $this->connectionsPromise = $this->connectionsDeferred->promise();
        $this->API->logger->logger("Disconnecting from shared DC {$this->datacenter}");
        if ($this->robinLoop) {
            $this->robinLoop->signal(true);
            $this->robinLoop = null;
        }
        $before = \count($this->backup);
        foreach ($this->connections as $connection) {
            $connection->disconnect();
        }
        $count = \count($this->backup) - $before;
        $this->API->logger->logger("Backed up {$count}, added to {$before} existing messages) from DC {$this->datacenter}");
        $this->connections = [];
        $this->availableConnections = [];
    }
    /**
     * Reconnect to DC.
     *
     * @return \Generator
     */
    public function reconnect() : \Generator
    {
        $this->API->logger->logger("Reconnecting shared DC {$this->datacenter}");
        $this->disconnect();
        yield from $this->connect($this->ctx);
    }
    /**
     * Restore backed up messages.
     *
     * @return void
     */
    public function restoreBackup()
    {
        $backup = $this->backup;
        $this->backup = [];
        $count = \count($backup);
        $this->API->logger->logger("Restoring {$count} messages to DC {$this->datacenter}");
        /** @var OutgoingMessage */
        foreach ($backup as $message) {
            if ($message->hasSeqno()) {
                $message->setSeqno(null);
            }
            if ($message->hasMsgId()) {
                $message->setMsgId(null);
            }
            if (!($message->getState() & OutgoingMessage::STATE_REPLIED)) {
                Tools::callFork($this->getConnection()->sendMessage($message, false));
            }
        }
        $this->flush();
    }
    /**
     * Get connection for authorization.
     *
     * @return Connection
     */
    public function getAuthConnection() : Connection
    {
        return $this->connections[0];
    }
    /**
     * Check if any connection is available.
     *
     * @param integer $id Connection ID
     *
     * @return (bool | int)
     */
    public function hasConnection(int $id = -1)
    {
        return $id < 0 ? \count($this->connections) : isset($this->connections[$id]);
    }
    /**
     * Get best socket in round robin, asynchronously.
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, Promise, mixed, Connection>
     */
    public function waitGetConnection() : \Generator
    {
        if (empty($this->availableConnections)) {
            (yield $this->connectionsPromise);
        }
        return $this->getConnection();
    }
    /**
     * Get best socket in round robin.
     *
     * @param integer $id Connection ID, for manual fetching
     *
     * @return Connection
     */
    public function getConnection(int $id = -1) : Connection
    {
        if ($id >= 0) {
            return $this->connections[$id];
        }
        if (\count($this->availableConnections) <= 1) {
            return $this->connections[0];
        }
        $max = \max($this->availableConnections);
        $key = \array_search($max, $this->availableConnections);
        // Decrease to implement round robin
        $this->availableConnections[$key]--;
        return $this->connections[$key];
    }
    /**
     * Even out round robin values.
     *
     * @return void
     */
    public function even()
    {
        if (!$this->availableConnections) {
            return;
        }
        $min = \min($this->availableConnections);
        if ($min < 50) {
            foreach ($this->availableConnections as &$count) {
                $count += 50;
            }
        } elseif ($min < 100) {
            $max = $this->isMedia() || $this->isCDN() ? $this->API->getSettings()->getConnection()->getMaxMediaSocketCount() : 1;
            if (\count($this->availableConnections) < $max) {
                $this->connectMore(2);
            } else {
                foreach ($this->availableConnections as &$value) {
                    $value += 1000;
                }
            }
        }
    }
    /**
     * Indicate that one of the sockets is busy reading.
     *
     * @param boolean $reading Whether we're busy reading
     * @param int $x Connection ID
     *
     * @return void
     */
    public function reading(bool $reading, int $x)
    {
        if (!isset($this->availableConnections[$x])) {
            return;
        }
        $this->availableConnections[$x] += $reading ? -$this->decRead : $this->decRead;
    }
    /**
     * Indicate that one of the sockets is busy writing.
     *
     * @param boolean $writing Whether we're busy writing
     * @param int $x Connection ID
     *
     * @return void
     */
    public function writing(bool $writing, int $x)
    {
        if (!isset($this->availableConnections[$x])) {
            return;
        }
        $this->availableConnections[$x] += $writing ? -$this->decWrite : $this->decWrite;
    }
    /**
     * Set main instance.
     *
     * @param MTProto $API Main instance
     *
     * @return void
     */
    public function setExtra($API)
    {
        $this->API = $API;
    }
    /**
     * Get main instance.
     *
     * @return MTProto
     */
    public function getExtra()
    {
        return $this->API;
    }
    /**
     * Check if is an HTTP connection.
     *
     * @return boolean
     */
    public function isHttp() : bool
    {
        return \in_array($this->ctx->getStreamName(), [HttpStream::class, HttpsStream::class]);
    }
    /**
     * Check if is connected directly by IP address.
     *
     * @return boolean
     */
    public function byIPAddress() : bool
    {
        return !$this->ctx->hasStreamName(WssStream::class) && !$this->ctx->hasStreamName(HttpsStream::class);
    }
    /**
     * Check if is a media connection.
     *
     * @return boolean
     */
    public function isMedia() : bool
    {
        return $this->ctx->isMedia();
    }
    /**
     * Check if is a CDN connection.
     *
     * @return boolean
     */
    public function isCDN() : bool
    {
        return $this->ctx->isCDN();
    }
    /**
     * Get DC-specific settings.
     *
     * @return ConnectionSettings
     */
    public function getSettings() : ConnectionSettings
    {
        return $this->API->getSettings()->getConnection();
    }
    /**
     * Get global settings.
     *
     * @return Settings
     */
    public function getGenericSettings() : Settings
    {
        return $this->API->getSettings();
    }
    /**
     * JSON serialize function.
     *
     * @return array
     */
    public function jsonSerialize() : array
    {
        return $this->linked ? ['linked' => $this->linked, 'tempAuthKey' => $this->tempAuthKey] : ['permAuthKey' => $this->permAuthKey, 'tempAuthKey' => $this->tempAuthKey];
    }
    /**
     * Sleep function.
     *
     * @internal
     *
     * @return array
     */
    public function __sleep()
    {
        return $this->linked ? ['linked', 'tempAuthKey'] : ['permAuthKey', 'tempAuthKey'];
    }
}<?php

/**
 * Constructors module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\DocsBuilder;

use danog\MadelineProto\StrTools;
use danog\MadelineProto\Tools;
trait Constructors
{
    /**
     *
     */
    public function mkConstructors() : void
    {
        foreach (\glob('constructors/' . $this->any) as $unlink) {
            \unlink($unlink);
        }
        if (\file_exists('constructors')) {
            \rmdir('constructors');
        }
        \mkdir('constructors');
        $this->docs_constructors = [];
        $this->logger->logger('Generating constructors documentation...', \danog\MadelineProto\Logger::NOTICE);
        $got = [];
        foreach ($this->TL->getConstructors($this->td)->by_predicate_and_layer as $predicate => $id) {
            $data = $this->TL->getConstructors($this->td)->by_id[$id];
            if (isset($got[$id])) {
                $data['layer'] = '';
            }
            $got[$id] = '';
            $layer = isset($data['layer']) && $data['layer'] !== '' ? '_' . $data['layer'] : '';
            $type = $data['type'];
            $constructor = $data['predicate'];
            $php_type = Tools::typeEscape($type);
            $php_constructor = Tools::typeEscape($constructor);
            if (!isset($this->types[$php_type])) {
                $this->types[$php_type] = ['constructors' => [], 'methods' => []];
            }
            if (!\in_array($data, $this->types[$php_type]['constructors'])) {
                $this->types[$php_type]['constructors'][] = $data;
            }
            $params = '';
            foreach ($data['params'] as $param) {
                if (\in_array($param['name'], ['flags', 'random_id', 'random_bytes'])) {
                    continue;
                }
                if ($type === 'EncryptedMessage' && $param['name'] === 'bytes' && !isset($this->settings['td'])) {
                    $param['name'] = 'decrypted_message';
                    $param['type'] = 'DecryptedMessage';
                }
                $type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type';
                $type_or_bare_type = \ctype_upper(Tools::end(\explode('.', $param[$type_or_subtype]))[0]) || \in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int53', 'int', 'long', 'int128', 'int256', 'int512']) ? 'types' : 'constructors';
                $param[$type_or_subtype] = \str_replace(['true', 'false'], ['Bool', 'Bool'], $param[$type_or_subtype]);
                if (\preg_match('/%/', $param[$type_or_subtype])) {
                    $param[$type_or_subtype] = $this->TL->getConstructors($this->td)->findByType(\str_replace('%', '', $param[$type_or_subtype]))['predicate'];
                }
                if (\Phabel\Target\Php80\Polyfill::substr($param[$type_or_subtype], -1) === '>') {
                    $param[$type_or_subtype] = \Phabel\Target\Php80\Polyfill::substr($param[$type_or_subtype], 0, -1);
                }
                $params .= "'" . $param['name'] . "' => ";
                $param[$type_or_subtype] = '[' . Tools::markdownEscape($param[$type_or_subtype]) . '](../' . $type_or_bare_type . '/' . $param[$type_or_subtype] . '.md)';
                $params .= (isset($param['subtype']) ? '\\[' . $param[$type_or_subtype] . '\\]' : $param[$type_or_subtype]) . ', ';
            }
            $md_constructor = StrTools::markdownEscape($constructor . $layer);
            $this->docs_constructors[$constructor] = '[$' . $md_constructor . '](../constructors/' . $php_constructor . $layer . '.md) = \\[' . $params . '\\];<a name="' . $constructor . $layer . '"></a>  

';
            $table = empty($data['params']) ? '' : '### Attributes:

| Name     |    Type       | Required |
|----------|---------------|----------|
';
            if (!isset($this->TL->getDescriptions()['constructors'][$constructor])) {
                $this->addToLang('object_' . $constructor);
                if (\danog\MadelineProto\Lang::$lang['en']['object_' . $constructor] !== '') {
                    /** @psalm-suppress InvalidArrayAssignment */
                    $this->TL->getDescriptions()['constructors'][$constructor]['description'] = \danog\MadelineProto\Lang::$lang['en']['object_' . $constructor];
                }
            }
            if (isset($this->TL->getDescriptions()['constructors'][$constructor]) && !empty($data['params'])) {
                $table = '### Attributes:

| Name     |    Type       | Required | Description |
|----------|---------------|----------|-------------|
';
            }
            $params = '';
            $lua_params = '';
            $pwr_params = '';
            $hasreplymarkup = false;
            $hasentities = false;
            foreach ($data['params'] as $param) {
                if (\in_array($param['name'], ['flags', 'random_id', 'random_bytes'])) {
                    continue;
                }
                if ($type === 'EncryptedMessage' && $param['name'] === 'bytes' && !isset($this->settings['td'])) {
                    $param['name'] = 'decrypted_message';
                    $param['type'] = 'DecryptedMessage';
                }
                if ($type === 'DecryptedMessageMedia' && \in_array($param['name'], ['key', 'iv'])) {
                    unset(\danog\MadelineProto\Lang::$lang['en']['object_' . $constructor . '_param_' . $param['name'] . '_type_' . $param['type']]);
                    continue;
                }
                $ptype = $param[isset($param['subtype']) ? 'subtype' : 'type'];
                if (\preg_match('/%/', $ptype)) {
                    $ptype = $this->TL->getConstructors($this->td)->findByType(\str_replace('%', '', $ptype))['predicate'];
                }
                $type_or_bare_type = (\ctype_upper(Tools::end(\explode('_', $ptype))[0]) || \in_array($ptype, ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int53', 'int', 'long', 'int128', 'int256', 'int512'])) && $ptype !== 'MTmessage' ? 'types' : 'constructors';
                if (\Phabel\Target\Php80\Polyfill::substr($ptype, -1) === '>') {
                    $ptype = \Phabel\Target\Php80\Polyfill::substr($ptype, 0, -1);
                }
                switch ($ptype) {
                    case 'true':
                    case 'false':
                        $ptype = 'Bool';
                }
                $human_ptype = $ptype;
                if (\strpos($type, 'Input') === 0 && \in_array($ptype, ['User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputDialogPeer', 'DialogPeer', 'NotifyPeer', 'InputNotifyPeer', 'InputPeer']) && !isset($this->settings['td'])) {
                    $human_ptype = 'Username, chat ID, Update, Message or ' . $ptype;
                }
                if (\strpos($type, 'Input') === 0 && \in_array($ptype, ['InputMedia', 'InputDocument', 'InputPhoto']) && !isset($this->settings['td'])) {
                    $human_ptype = 'MessageMedia, Message, Update or ' . $ptype;
                }
                if (\in_array($ptype, ['InputMessage']) && !isset($this->settings['td'])) {
                    $human_ptype = 'Message ID or ' . $ptype;
                }
                if (\in_array($ptype, ['InputEncryptedChat']) && !isset($this->settings['td'])) {
                    $human_ptype = 'Secret chat ID, Update, EncryptedMessage or ' . $ptype;
                }
                if (\in_array($ptype, ['InputFile']) && !isset($this->settings['td'])) {
                    $human_ptype = 'File path or ' . $ptype;
                }
                if (\in_array($ptype, ['InputEncryptedFile']) && !isset($this->settings['td'])) {
                    $human_ptype = 'File path or ' . $ptype;
                }
                $table .= '|' . StrTools::markdownEscape($param['name']) . '|' . (isset($param['subtype']) ? 'Array of ' : '') . '[' . StrTools::markdownEscape($human_ptype) . '](../' . $type_or_bare_type . '/' . $ptype . '.md) | ' . (isset($param['pow']) || $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']) . 'Empty') || $data['type'] === 'InputMedia' && $param['name'] === 'mime_type' || $data['type'] === 'DocumentAttribute' && \in_array($param['name'], ['w', 'h', 'duration']) ? 'Optional' : 'Yes') . '|';
                if (!isset($this->TL->getDescriptions()['constructors'][$constructor]['params'][$param['name']])) {
                    $this->addToLang('object_' . $constructor . '_param_' . $param['name'] . '_type_' . $param['type']);
                    if (isset($this->TL->getDescriptions()['constructors'][$constructor]['description'])) {
                        /** @psalm-suppress InvalidArrayAssignment */
                        $this->TL->getDescriptions()['constructors'][$constructor]['params'][$param['name']] = \danog\MadelineProto\Lang::$lang['en']['object_' . $constructor . '_param_' . $param['name'] . '_type_' . $param['type']];
                    }
                }
                if (isset($this->TL->getDescriptions()['constructors'][$constructor]['params'][$param['name']]) && $this->TL->getDescriptions()['constructors'][$constructor]['params'][$param['name']]) {
                    $table .= $this->TL->getDescriptions()['constructors'][$constructor]['params'][$param['name']] . '|';
                }
                $table .= PHP_EOL;
                $pptype = \in_array($ptype, ['string', 'bytes']) ? "'" . $ptype . "'" : $ptype;
                $ppptype = \in_array($ptype, ['string']) ? '"' . $ptype . '"' : $ptype;
                $ppptype = \in_array($ptype, ['bytes']) ? '{"_": "bytes", "bytes":"base64 encoded ' . $ptype . '"}' : $ppptype;
                $params .= ", '" . $param['name'] . "' => ";
                $params .= isset($param['subtype']) ? '[' . $pptype . ', ' . $pptype . ']' : $pptype;
                $lua_params .= ', ' . $param['name'] . '=';
                $lua_params .= isset($param['subtype']) ? '{' . $pptype . '}' : $pptype;
                $pwr_params .= ', "' . $param['name'] . '": ' . (isset($param['subtype']) ? '[' . $ppptype . ']' : $ppptype);
                if ($param['name'] === 'reply_markup') {
                    $hasreplymarkup = true;
                }
            }
            $params = "['_' => '" . $constructor . "'" . $params . ']';
            $lua_params = "{_='" . $constructor . "'" . $lua_params . '}';
            $pwr_params = '{"_": "' . $constructor . '"' . $pwr_params . '}';
            $description = isset($this->TL->getDescriptions()['constructors'][$constructor]) ? $this->TL->getDescriptions()['constructors'][$constructor]['description'] : $constructor . ' attributes, type and example';
            $symFile = \str_replace('.', '_', $constructor . $layer);
            $redir = $symFile !== $constructor . $layer ? "\nredirect_from: /API_docs/constructors/{$symFile}.html" : '';
            $description = \str_replace('"', "'", Tools::toString(\rtrim(\explode("\n", $description)[0], ':')));
            $header = '---
title: "' . $constructor . '"
description: "' . $description . '"
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png' . $redir . '
---
# Constructor: ' . StrTools::markdownEscape($constructor . $layer) . '  
[Back to constructors index](index.md)



';
            $table .= '


';
            if (isset($this->TL->getDescriptions()['constructors'][$constructor])) {
                $header .= $this->TL->getDescriptions()['constructors'][$constructor]['description'] . PHP_EOL . PHP_EOL;
            }
            $type = '### Type: [' . StrTools::markdownEscape($php_type) . '](../types/' . $php_type . '.md)


';
            $example = '';
            if (!isset($this->settings['td'])) {
                $example = $this->template('constructor-example', \str_replace('.', '_', $constructor . $layer), $params, $lua_params);
                if ($hasreplymarkup) {
                    $example .= $this->template('reply_markup');
                }
                if ($hasentities) {
                    $example .= $this->template('parse_mode');
                }
            }
            \file_put_contents('constructors/' . $constructor . $layer . '.md', $header . $table . $type . $example);
        }
        $this->logger->logger('Generating constructors index...', \danog\MadelineProto\Logger::NOTICE);
        \ksort($this->docs_constructors);
        $last_namespace = '';
        foreach ($this->docs_constructors as $constructor => &$value) {
            $new_namespace = \preg_replace('/_.*/', '', $constructor);
            $br = $new_namespace != $last_namespace ? "***\n<br><br>" : '';
            $value = $br . $value;
            $last_namespace = $new_namespace;
        }
        \file_put_contents('constructors/' . $this->index, $this->template('constructors-index', \implode('', $this->docs_constructors)));
    }
}<?php

/**
 * Methods module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\DocsBuilder;

use danog\MadelineProto\StrTools;
use danog\MadelineProto\Tools;
trait Methods
{
    /**
     *
     */
    public function mkMethods() : void
    {
        static $bots;
        if (!$bots) {
            $bots = \json_decode(\file_get_contents('https://rpc.madelineproto.xyz/bot.json'), true)['result'];
        }
        static $errors;
        if (!$errors) {
            $errors = \json_decode(\file_get_contents('https://rpc.madelineproto.xyz/v1.json'), true);
        }
        $new = ['result' => []];
        foreach ($errors['result'] as $code => $suberrors) {
            foreach ($suberrors as $method => $suberrors) {
                if (!isset($new[$method])) {
                    $new[$method] = [];
                }
                foreach ($suberrors as $error) {
                    $new['result'][$method][] = [$error, $code];
                }
            }
        }
        foreach (\glob('methods/' . $this->any) as $unlink) {
            \unlink($unlink);
        }
        if (\file_exists('methods')) {
            \rmdir('methods');
        }
        \mkdir('methods');
        $this->docs_methods = [];
        $this->human_docs_methods = [];
        $this->logger->logger('Generating methods documentation...', \danog\MadelineProto\Logger::NOTICE);
        foreach ($this->TL->getMethods($this->td)->by_id as $id => $data) {
            $method = $data['method'];
            $phpMethod = StrTools::methodEscape($method);
            $type = \str_replace(['<', '>'], ['_of_', ''], $data['type']);
            $php_type = \preg_replace('/.*_of_/', '', $type);
            if (!isset($this->types[$php_type])) {
                $this->types[$php_type] = ['methods' => [], 'constructors' => []];
            }
            if (!\in_array($data, $this->types[$php_type]['methods'])) {
                $this->types[$php_type]['methods'][] = $data;
            }
            $params = '';
            foreach ($data['params'] as $param) {
                if (\in_array($param['name'], ['flags', 'random_id', 'random_bytes'])) {
                    continue;
                }
                if ($param['name'] === 'data' && $type === 'messages_SentEncryptedMessage' && !isset($this->settings['td'])) {
                    $param['name'] = 'message';
                    $param['type'] = 'DecryptedMessage';
                }
                if ($param['name'] === 'chat_id' && $method !== 'messages.discardEncryption' && !isset($this->settings['td'])) {
                    $param['type'] = 'InputPeer';
                }
                $type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type';
                $type_or_bare_type = \ctype_upper(Tools::end(\explode('.', $param[$type_or_subtype]))[0]) || \in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int', 'long', 'int128', 'int256', 'int512', 'int53']) ? 'types' : 'constructors';
                $param[$type_or_subtype] = \str_replace(['true', 'false'], ['Bool', 'Bool'], $param[$type_or_subtype]);
                $param[$type_or_subtype] = '[' . StrTools::markdownEscape($param[$type_or_subtype]) . '](../' . $type_or_bare_type . '/' . $param[$type_or_subtype] . '.md)';
                $params .= "'" . $param['name'] . "' => " . (isset($param['subtype']) ? '\\[' . $param[$type_or_subtype] . '\\]' : $param[$type_or_subtype]) . ', ';
            }
            if (!isset($this->tdDescriptions['methods'][$method])) {
                $this->addToLang('method_' . $method);
                if (\danog\MadelineProto\Lang::$lang['en']['method_' . $method] !== '') {
                    $this->tdDescriptions['methods'][$method]['description'] = \danog\MadelineProto\Lang::$lang['en']['method_' . $method];
                }
            }
            $md_method = '[' . $phpMethod . '](' . $method . '.md)';
            $this->docs_methods[$method] = '$MadelineProto->' . $md_method . '(\\[' . $params . '\\]) === [$' . StrTools::markdownEscape($type) . '](../types/' . $php_type . '.md)<a name="' . $method . '"></a>  

';
            if (isset($this->tdDescriptions['methods'][$method])) {
                $desc = \Parsedown::instance()->line(\trim(\explode("\n", $this->tdDescriptions['methods'][$method]['description'])[0], '.'));
                $dom = new \DOMDocument();
                $dom->loadHTML(\mb_convert_encoding($desc, 'HTML-ENTITIES', 'UTF-8'));
                $desc = $dom->textContent;
                $this->human_docs_methods[$this->tdDescriptions['methods'][$method]['description'] . ': ' . $method] = '* <a href="' . $method . '.html" name="' . $method . '">' . $desc . ': ' . $method . '</a>

';
            }
            $params = '';
            $lua_params = '';
            $pwr_params = '';
            $json_params = '';
            $table = empty($data['params']) ? '' : '### Parameters:

| Name     |    Type       | Required |
|----------|---------------|----------|
';
            if (isset($this->tdDescriptions['methods'][$method]) && !empty($data['params'])) {
                $table = '### Parameters:

| Name     |    Type       | Description | Required |
|----------|---------------|-------------|----------|
';
            }
            $hasentities = false;
            $hasreplymarkup = false;
            $hasmessage = false;
            foreach ($data['params'] as $param) {
                if (\in_array($param['name'], ['flags', 'random_id', 'random_bytes'])) {
                    continue;
                }
                if ($param['name'] === 'data' && $type === 'messages_SentEncryptedMessage' && !isset($this->settings['td'])) {
                    $param['name'] = 'message';
                    $param['type'] = 'DecryptedMessage';
                }
                if ($param['name'] === 'chat_id' && $method !== 'messages.discardEncryption' && !isset($this->settings['td'])) {
                    $param['type'] = 'InputPeer';
                }
                if ($param['name'] === 'hash' && $param['type'] === 'int') {
                    $param['pow'] = 'hi';
                    $param['type'] = 'Vector t';
                    $param['subtype'] = 'int';
                }
                $ptype = $param[$type_or_subtype = isset($param['subtype']) ? 'subtype' : 'type'];
                switch ($ptype) {
                    case 'true':
                    case 'false':
                        $ptype = 'Bool';
                }
                $human_ptype = $ptype;
                if (\in_array($ptype, ['InputDialogPeer', 'DialogPeer', 'NotifyPeer', 'InputNotifyPeer', 'User', 'InputUser', 'Chat', 'InputChannel', 'Peer', 'InputPeer']) && !isset($this->settings['td'])) {
                    $human_ptype = 'Username, chat ID, Update, Message or ' . $ptype;
                }
                if (\in_array($ptype, ['InputMedia', 'InputPhoto', 'InputDocument']) && !isset($this->settings['td'])) {
                    $human_ptype = 'MessageMedia, Update, Message or ' . $ptype;
                }
                if (\in_array($ptype, ['InputMessage']) && !isset($this->settings['td'])) {
                    $human_ptype = 'Message ID or ' . $ptype;
                }
                if (\in_array($ptype, ['InputEncryptedChat']) && !isset($this->settings['td'])) {
                    $human_ptype = 'Secret chat ID, Update, EncryptedMessage or ' . $ptype;
                }
                if (\in_array($ptype, ['InputFile']) && !isset($this->settings['td'])) {
                    $human_ptype = 'File path or ' . $ptype;
                }
                if (\in_array($ptype, ['InputEncryptedFile']) && !isset($this->settings['td'])) {
                    $human_ptype = 'File path or ' . $ptype;
                }
                $type_or_bare_type = \ctype_upper(Tools::end(\explode('.', $param[$type_or_subtype]))[0]) || \in_array($param[$type_or_subtype], ['!X', 'X', 'bytes', 'true', 'false', 'double', 'string', 'Bool', 'int', 'long', 'int128', 'int256', 'int512', 'int53']) ? 'types' : 'constructors';
                if (!isset($this->tdDescriptions['methods'][$method]['params'][$param['name']])) {
                    if (isset($this->tdDescriptions['methods'][$method]['description'])) {
                        $this->tdDescriptions['methods'][$method]['params'][$param['name']] = \danog\MadelineProto\Lang::$lang['en']['method_' . $method . '_param_' . $param['name'] . '_type_' . $param['type']] ?? '';
                    }
                }
                if (isset($this->tdDescriptions['methods'][$method])) {
                    $table .= '|' . StrTools::markdownEscape($param['name']) . '|' . (isset($param['subtype']) ? 'Array of ' : '') . '[' . StrTools::markdownEscape($human_ptype) . '](../' . $type_or_bare_type . '/' . $ptype . '.md) | ' . $this->tdDescriptions['methods'][$method]['params'][$param['name']] . ' | ' . (isset($param['pow']) || ($id = $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']) . 'Empty')) && $id['type'] === $param['type'] || ($id = $this->TL->getConstructors($this->td)->findByPredicate('input' . $param['type'] . 'Empty')) && $id['type'] === $param['type'] ? 'Optional' : 'Yes') . '|';
                } else {
                    $table .= '|' . StrTools::markdownEscape($param['name']) . '|' . (isset($param['subtype']) ? 'Array of ' : '') . '[' . StrTools::markdownEscape($human_ptype) . '](../' . $type_or_bare_type . '/' . $ptype . '.md) | ' . (isset($param['pow']) || ($id = $this->TL->getConstructors($this->td)->findByPredicate(\lcfirst($param['type']) . 'Empty')) && $id['type'] === $param['type'] || ($id = $this->TL->getConstructors($this->td)->findByPredicate('input' . $param['type'] . 'Empty')) && $id['type'] === $param['type'] ? 'Optional' : 'Yes') . '|';
                }
                $table .= PHP_EOL;
                $pptype = \in_array($ptype, ['string', 'bytes']) ? "'" . $ptype . "'" : $ptype;
                $ppptype = \in_array($ptype, ['string']) ? '"' . $ptype . '"' : $ptype;
                $ppptype = \in_array($ptype, ['bytes']) ? '{"_": "bytes", "bytes":"base64 encoded ' . $ptype . '"}' : $ppptype;
                $params .= "'" . $param['name'] . "' => ";
                $params .= (isset($param['subtype']) ? '[' . $pptype . ', ' . $pptype . ']' : $pptype) . ', ';
                $json_params .= '"' . $param['name'] . '": ' . (isset($param['subtype']) ? '[' . $ppptype . ']' : $ppptype) . ', ';
                $pwr_params .= $param['name'] . ' - Json encoded ' . (isset($param['subtype']) ? ' array of ' . $ptype : $ptype) . "\n\n";
                $lua_params .= $param['name'] . '=';
                $lua_params .= (isset($param['subtype']) ? '{' . $pptype . '}' : $pptype) . ', ';
                if ($param['name'] === 'reply_markup') {
                    $hasreplymarkup = true;
                }
                if ($param['name'] === 'message') {
                    $hasmessage = true;
                }
                if ($param['name'] === 'entities') {
                    $hasentities = true;
                    $table .= '|parse\\_mode| [string](../types/string.md) | Whether to parse HTML or Markdown markup in the message| Optional |
';
                    $params .= "'parse_mode' => 'string', ";
                    $lua_params .= "parseMode='string', ";
                    $json_params .= '"parseMode": "string"';
                    $pwr_params = "parseMode - string\n";
                }
            }
            $description = isset($this->tdDescriptions['methods'][$method]) ? $this->tdDescriptions['methods'][$method]['description'] : $method . ' parameters, return type and example';
            $symFile = \str_replace('.', '_', $method);
            $redir = $symFile !== $method ? "\nredirect_from: /API_docs/methods/{$symFile}.html" : '';
            $description = \rtrim(\explode("\n", $description)[0], ':');
            $header = $this->template('Method', $method, $description, $redir, StrTools::markdownEscape($method));
            if ($this->td) {
                $header .= "YOU CANNOT USE THIS METHOD IN MADELINEPROTO\n\n\n\n\n";
            }
            $header .= isset($this->tdDescriptions['methods'][$method]) ? $this->tdDescriptions['methods'][$method]['description'] . PHP_EOL . PHP_EOL : '';
            $table .= '

';
            $return = '### Return type: [' . StrTools::markdownEscape($type) . '](../types/' . $php_type . '.md)

';
            $bot = !\in_array($method, $bots);
            $example = '';
            if (!isset($this->settings['td'])) {
                $example .= '### Can bots use this method: **' . ($bot ? 'YES' : 'NO') . "**\n\n\n";
                $example .= \str_replace('[]', '', $this->template('method-example', \str_replace('.', '_', $type), $phpMethod, $params, $method, $lua_params));
                if ($hasreplymarkup) {
                    $example .= $this->template('reply_markup');
                }
                if ($hasmessage) {
                    $example .= $this->template('chunks', StrTools::markdownEscape($type), $php_type);
                }
                if ($hasentities) {
                    $example .= $this->template('parse_mode');
                }
                if (isset($new['result'][$method])) {
                    $example .= '### Errors

| Code | Type     | Description   |
|------|----------|---------------|
';
                    foreach ($new['result'][$method] as $error) {
                        [$error, $code] = $error;
                        $example .= "|{$code}|{$error}|" . $errors['human_result'][$error][0] . '|
';
                    }
                    $example .= "\n\n";
                }
            }
            \file_put_contents('methods/' . $method . '.md', $header . $table . $return . $example);
        }
        $this->logger->logger('Generating methods index...', \danog\MadelineProto\Logger::NOTICE);
        \ksort($this->docs_methods);
        \ksort($this->human_docs_methods);
        $last_namespace = '';
        foreach ($this->docs_methods as $method => &$value) {
            $new_namespace = \preg_replace('/_.*/', '', $method);
            $br = $new_namespace != $last_namespace ? '***
<br><br>
' : '';
            $value = $br . $value;
            $last_namespace = $new_namespace;
        }
        \file_put_contents('methods/api_' . $this->index, $this->template('methods-api-index', $this->index, \implode('', $this->docs_methods)));
        \file_put_contents('methods/' . $this->index, $this->template('methods-index', $this->index, \implode('', $this->human_docs_methods)));
    }
}<?php

/**
 * Tools module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
use Amp\TimeoutException;
use DOMDocument;
use Parsedown;
use function Amp\ByteStream\getOutputBufferStream;
use function Amp\ByteStream\getStdin;
use function Amp\ByteStream\getStdout;
use function Amp\delay;
use function Amp\File\exists;
use function Amp\File\touch as touchAsync;
use function Amp\Promise\all;
use function Amp\Promise\any;
use function Amp\Promise\first;
use function Amp\Promise\some;
use function Amp\Promise\timeout;
use function Amp\Promise\timeoutWithDefault;
use function Amp\Promise\wait;
/**
 * Some tools.
 */
abstract class Tools extends StrTools
{
    /**
     * Boolean to avoid problems with exceptions thrown by forked strands, see tools.
     *
     * @var boolean
     */
    public bool $destructing = false;
    /**
     * Sanify TL obtained from JSON for TL serialization.
     *
     * @param array $input Data to sanitize
     *
     * @internal
     *
     * @return array
     */
    public static function convertJsonTL(array $input) : array
    {
        $cb = static function (&$val) use(&$cb) : void {
            if (isset($val['@type'])) {
                $val['_'] = $val['@type'];
            } elseif (\is_array($val)) {
                \array_walk($val, $cb);
            }
        };
        \array_walk($input, $cb);
        return $input;
    }
    /**
     * Generate MTProto vector hash.
     *
     * @param array $ints IDs
     *
     * @return string Vector hash
     */
    public static function genVectorHash(array $ints) : string
    {
        $hash = 0;
        foreach ($ints as $id) {
            $hash = $hash ^ $id >> 21;
            $hash = $hash ^ $id << 35;
            $hash = $hash ^ $id >> 4;
            $hash = $hash + $id;
        }
        return Tools::packSignedLong($hash);
    }
    /**
     * Get random integer.
     *
     * @param integer $modulus Modulus
     *
     * @return int
     */
    public static function randomInt(int $modulus = 0) : int
    {
        if ($modulus === 0) {
            $modulus = PHP_INT_MAX;
        }
        try {
            return \random_int(0, PHP_INT_MAX) % $modulus;
        } catch (\Exception $e) {
            // random_compat will throw an Exception, which in PHP 5 does not implement Throwable
        } catch (\Throwable $e) {
            // If a sufficient source of randomness is unavailable, random_bytes() will throw an
            // object that implements the Throwable interface (Exception, TypeError, Error).
            // We don't actually need to do anything here. The string() method should just continue
            // as normal.
        }
        $number = self::unpackSignedLong(self::random(8));
        return ($number & PHP_INT_MAX) % $modulus;
    }
    /**
     * Get random string of specified length.
     *
     * @param integer $length Length
     *
     * @return string Random string
     */
    public static function random(int $length) : string
    {
        return $length === 0 ? '' : \phpseclib3\Crypt\Random::string($length);
    }
    /**
    * Positive modulo
    Works just like the % (modulus) operator, only returns always a postive number.
    *
    * @param int $a A
    * @param int $b B
    *
    * @return int Modulo
    */
    public static function posmod(int $a, int $b) : int
    {
        $resto = $a % $b;
        return $resto < 0 ? $resto + \abs($b) : $resto;
    }
    /**
     * Unpack base256 signed int.
     *
     * @param string $value base256 int
     *
     * @return integer
     */
    public static function unpackSignedInt(string $value) : int
    {
        if (\strlen($value) !== 4) {
            throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_4']);
        }
        return \unpack('l', \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($value) : $value)[1];
    }
    /**
     * Unpack base256 signed long.
     *
     * @param string $value base256 long
     *
     * @return integer
     */
    public static function unpackSignedLong(string $value) : int
    {
        if (\strlen($value) !== 8) {
            throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
        }
        return \unpack('q', \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($value) : $value)[1];
    }
    /**
     * Unpack base256 signed long to string.
     *
     * @param (string | int | array) $value base256 long
     *
     * @return string
     */
    public static function unpackSignedLongString($value) : string
    {
        if (\is_int($value)) {
            return (string) $value;
        }
        if (\is_array($value) && \count($value) === 2) {
            $value = \pack('l2', $value);
        }
        if (\strlen($value) !== 8) {
            throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
        }
        return (string) self::unpackSignedLong($value);
    }
    /**
     * Convert integer to base256 signed int.
     *
     * @param integer $value Value to convert
     *
     * @return string
     */
    public static function packSignedInt(int $value) : string
    {
        if ($value > 2147483647) {
            throw new TL\Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['value_bigger_than_2147483647'], $value));
        }
        if ($value < -2147483648) {
            throw new TL\Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['value_smaller_than_2147483648'], $value));
        }
        $res = \pack('l', $value);
        return \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($res) : $res;
    }
    /**
     * Convert integer to base256 long.
     *
     * @param int $value Value to convert
     *
     * @return string
     */
    public static function packSignedLong(int $value) : string
    {
        return \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev(\pack('q', $value)) : \pack('q', $value);
    }
    /**
     * Convert value to unsigned base256 int.
     *
     * @param int $value Value
     *
     * @return string
     */
    public static function packUnsignedInt(int $value) : string
    {
        if ($value > 4294967295) {
            throw new TL\Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['value_bigger_than_4294967296'], $value));
        }
        if ($value < 0) {
            throw new TL\Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['value_smaller_than_0'], $value));
        }
        return \pack('V', $value);
    }
    /**
     * Convert double to binary version.
     *
     * @param float $value Value to convert
     *
     * @return string
     */
    public static function packDouble(float $value) : string
    {
        $res = \pack('d', $value);
        if (\strlen($res) !== 8) {
            throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['encode_double_error']);
        }
        return \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($res) : $res;
    }
    /**
     * Unpack binary double.
     *
     * @param string $value Value to unpack
     *
     * @return float
     */
    public static function unpackDouble(string $value) : float
    {
        if (\strlen($value) !== 8) {
            throw new TL\Exception(\danog\MadelineProto\Lang::$current_lang['length_not_8']);
        }
        return \unpack('d', \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($value) : $value)[1];
    }
    /**
     * Synchronously wait for a promise|generator.
     *
     * @param (\Generator | Promise) $promise The promise to wait for
     * @param boolean $ignoreSignal Whether to ignore shutdown signals
     *
     * @return mixed
     */
    public static function wait($promise, $ignoreSignal = false)
    {
        if ($promise instanceof \Generator) {
            $promise = new Coroutine($promise);
        } elseif (!$promise instanceof Promise) {
            return $promise;
        }
        $exception = null;
        $value = null;
        $resolved = false;
        do {
            try {
                //Logger::log("Starting event loop...");
                Loop::run(function () use(&$resolved, &$value, &$exception, $promise) {
                    $promise->onResolve(function ($e, $v) use(&$resolved, &$value, &$exception) {
                        Loop::stop();
                        $resolved = true;
                        $exception = $e;
                        $value = $v;
                    });
                });
            } catch (\Throwable $throwable) {
                Logger::log('Loop exceptionally stopped without resolving the promise', Logger::FATAL_ERROR);
                Logger::log((string) $throwable, Logger::FATAL_ERROR);
                throw $throwable;
            }
        } while (!$resolved && !(Magic::$signaled && !$ignoreSignal));
        if ($exception) {
            throw $exception;
        }
        return $value;
    }
    /**
    * Returns a promise that succeeds when all promises succeed, and fails if any promise fails.
    Returned promise succeeds with an array of values used to succeed each contained promise, with keys corresponding to the array of promises.
    *
    * @param array<(\Generator | Promise)> $promises Promises
    *
    * @return Promise
    */
    public static function all(array $promises) : Promise
    {
        foreach ($promises as &$promise) {
            $promise = self::call($promise);
        }
        /** @var Promise[] $promises */
        return all($promises);
    }
    /**
     * Returns a promise that is resolved when all promises are resolved. The returned promise will not fail.
     *
     * @param array<(Promise | \Generator)> $promises Promises
     *
     * @return Promise
     */
    public static function any(array $promises) : Promise
    {
        foreach ($promises as &$promise) {
            $promise = self::call($promise);
        }
        /** @var Promise[] $promises */
        return any($promises);
    }
    /**
    * Resolves with a two-item array delineating successful and failed Promise results.
    The returned promise will only fail if the given number of required promises fail.
    *
    * @param array<(Promise | \Generator)> $promises Promises
    *
    * @return Promise
    */
    public static function some(array $promises) : Promise
    {
        foreach ($promises as &$promise) {
            $promise = self::call($promise);
        }
        /** @var Promise[] $promises */
        return some($promises);
    }
    /**
     * Returns a promise that succeeds when the first promise succeeds, and fails only if all promises fail.
     *
     * @param array<(Promise | \Generator)> $promises Promises
     *
     * @return Promise
     */
    public static function first(array $promises) : Promise
    {
        foreach ($promises as &$promise) {
            $promise = self::call($promise);
        }
        /** @var Promise[] $promises */
        return first($promises);
    }
    /**
     * Create an artificial timeout for any \Generator or Promise.
     *
     * @param (\Generator | Promise) $promise
     * @param integer $timeout
     *
     * @return Promise
     */
    public static function timeout($promise, int $timeout) : Promise
    {
        $promise = self::call($promise);
        $deferred = new Deferred();
        $watcher = Loop::delay($timeout, static function () use(&$deferred) {
            $temp = $deferred;
            // prevent double resolve
            $deferred = null;
            $temp->fail(new TimeoutException());
        });
        //Loop::unreference($watcher);
        $promise->onResolve(function () use(&$deferred, $promise, $watcher) {
            if ($deferred !== null) {
                Loop::cancel($watcher);
                $deferred->resolve($promise);
            }
        });
        return $deferred->promise();
    }
    /**
     * Creates an artificial timeout for any `Promise`.
     *
     * If the promise is resolved before the timeout expires, the result is returned
     *
     * If the timeout expires before the promise is resolved, a default value is returned
     *
     * @template TReturnAlt
     * @template TReturn
     * @template TGenerator of \Generator<mixed, mixed, mixed, TReturn>
     *
     * @param (Promise | Generator) $promise Promise to which the timeout is applied.
     * @param int $timeout Timeout in milliseconds.
     * @param mixed $default
     *
     * @psalm-param (Promise<TReturn> | TGenerator) $promise Promise to which the timeout is applied.
     * @psalm-param TReturnAlt $default
     *
     * @return (Promise<TReturn> | Promise<TReturnAlt>)
     *
     * @throws \TypeError If $promise is not an instance of \Amp\Promise, \Generator or \React\Promise\PromiseInterface.
     */
    public static function timeoutWithDefault($promise, int $timeout, $default = null) : Promise
    {
        $promise = self::call($promise);
        $deferred = new Deferred();
        $watcher = Loop::delay($timeout, static function () use(&$deferred, $default) {
            $temp = $deferred;
            // prevent double resolve
            $deferred = null;
            $temp->resolve($default);
        });
        //Loop::unreference($watcher);
        $promise->onResolve(function () use(&$deferred, $promise, $watcher) {
            if ($deferred !== null) {
                Loop::cancel($watcher);
                $deferred->resolve($promise);
            }
        });
        return $deferred->promise();
    }
    /**
     * Convert generator, promise or any other value to a promise.
     *
     * @param (\Generator | Promise | mixed) $promise
     *
     * @template TReturn
     * @psalm-param (\Generator<mixed, mixed, mixed, TReturn> | Promise<TReturn> | TReturn) $promise
     *
     * @return Promise
     * @psalm-return Promise<TReturn>
     */
    public static function call($promise) : Promise
    {
        if ($promise instanceof \Generator) {
            $promise = new Coroutine($promise);
        } elseif (!$promise instanceof Promise) {
            return new Success($promise);
        }
        return $promise;
    }
    /**
     * Call promise in background.
     *
     * @param (\Generator | Promise) $promise Promise to resolve
     * @param ?\Generator|Promise $actual  Promise to resolve instead of $promise
     * @param string $file File
     *
     * @psalm-suppress InvalidScope
     *
     * @return (Promise | mixed)
     */
    public static function callFork($promise, $actual = null, $file = '')
    {
        if ($actual) {
            $promise = $actual;
        }
        if ($promise instanceof \Generator) {
            $promise = new Coroutine($promise);
        }
        if ($promise instanceof Promise) {
            $promise->onResolve(function ($e, $res) use($file) {
                if ($e) {
                    if (isset($this)) {
                        $this->rethrow($e, $file);
                    } else {
                        self::rethrow($e, $file);
                    }
                }
            });
        }
        return $promise;
    }
    /**
     * Call promise in background, deferring execution.
     *
     * @param (\Generator | Promise) $promise Promise to resolve
     *
     * @return void
     */
    public static function callForkDefer($promise) : void
    {
        Loop::defer(fn() => self::callFork($promise));
    }
    /**
     * Rethrow error catched in strand.
     *
     * @param \Throwable $e Exception
     * @param string $file File where the strand started
     *
     * @psalm-suppress InvalidScope
     *
     * @return void
     */
    public static function rethrow(\Throwable $e, $file = '') : void
    {
        $zis = isset($this) ? $this : null;
        $logger = isset($zis->logger) ? $zis->logger : Logger::$default;
        if ($file) {
            $file = " started @ {$file}";
        }
        if ($logger) {
            $logger->logger("Got the following exception within a forked strand{$file}, trying to rethrow");
        }
        if ($e->getMessage() === "Cannot get return value of a generator that hasn't returned") {
            $logger->logger("Well you know, this might actually not be the actual exception, scroll up in the logs to see the actual exception");
            if (!$zis || !$zis->destructing) {
                Promise\rethrow(new Failure($e));
            }
        } else {
            if ($logger) {
                $logger->logger($e);
            }
            Promise\rethrow(new Failure($e));
        }
    }
    /**
     * Call promise $b after promise $a.
     *
     * @param (\Generator | Promise) $a Promise A
     * @param (\Generator | Promise) $b Promise B
     *
     * @psalm-suppress InvalidScope
     *
     * @return Promise
     */
    public static function after($a, $b) : Promise
    {
        $a = self::call($a);
        $deferred = new Deferred();
        $a->onResolve(static function ($e, $res) use($b, $deferred) {
            if ($e) {
                if (isset($this)) {
                    $this->rethrow($e);
                } else {
                    self::rethrow($e);
                }
                return;
            }
            $b = self::call($b);
            $b->onResolve(function ($e, $res) use($deferred) {
                if ($e) {
                    if (isset($this)) {
                        $this->rethrow($e);
                    } else {
                        self::rethrow($e);
                    }
                    return;
                }
                $deferred->resolve($res);
            });
        });
        return $deferred->promise();
    }
    /**
    * Asynchronously lock a file
    Resolves with a callbable that MUST eventually be called in order to release the lock.
    *
    * @param string $file File to lock
    * @param integer $operation Locking mode
    * @param float $polling Polling interval
    * @param ?Promise $token Cancellation token
    * @param ?callable $failureCb Failure callback, called only once if the first locking attempt fails.
    *
    * @return Promise<$token is null ? callable : ?callable>
    */
    public static function flock(string $file, int $operation, float $polling = 0.1, ?Promise $token = null, $failureCb = null) : Promise
    {
        return self::call(Tools::flockGenerator($file, $operation, $polling, $token, $failureCb));
    }
    /**
     * Asynchronously lock a file (internal generator function).
     *
     * @param string $file File to lock
     * @param integer $operation Locking mode
     * @param float $polling Polling interval
     * @param ?Promise $token Cancellation token
     * @param ?callable $failureCb Failure callback, called only once if the first locking attempt fails.
     *
     * @internal Generator function
     *
     * @return \Generator
     * @psalm-return \Generator<mixed, mixed, mixed, ?callable>
     */
    public static function flockGenerator(string $file, int $operation, float $polling, ?Promise $token = null, $failureCb = null) : \Generator
    {
        $polling *= 1000;
        $polling = (int) $polling;
        if (!(yield exists($file))) {
            (yield touchAsync($file));
        }
        $operation |= LOCK_NB;
        $res = \fopen($file, 'c');
        do {
            $result = \flock($res, $operation);
            if (!$result) {
                if ($failureCb) {
                    $failureCb();
                    $failureCb = null;
                }
                if ($token) {
                    if ((yield Tools::timeoutWithDefault($token, $polling, false))) {
                        return;
                    }
                } else {
                    (yield delay($polling));
                }
            }
        } while (!$result);
        return static function () use(&$res) {
            if ($res) {
                \flock($res, LOCK_UN);
                \fclose($res);
                $res = null;
            }
        };
    }
    /**
     * Asynchronously sleep.
     *
     * @param (int | float) $time Number of seconds to sleep for
     *
     * @return Promise
     */
    public static function sleep($time) : Promise
    {
        return new \Amp\Delayed((int) ($time * 1000));
    }
    /**
     * Asynchronously read line.
     *
     * @param string $prompt Prompt
     *
     * @return Promise<string>
     */
    public static function readLine(string $prompt = '') : Promise
    {
        return self::call(Tools::readLineGenerator($prompt));
    }
    /**
     * Asynchronously read line (generator function).
     *
     * @param string $prompt Prompt
     *
     * @internal Generator function
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, (Promise | Promise<(null | string)>), mixed, (mixed | null)>
     */
    public static function readLineGenerator(string $prompt = '') : \Generator
    {
        try {
            Magic::togglePeriodicLogging();
            $stdin = getStdin();
            $stdout = getStdout();
            if ($prompt) {
                (yield $stdout->write($prompt));
            }
            static $lines = [''];
            while (\count($lines) < 2 && ($chunk = (yield $stdin->read())) !== null) {
                $chunk = \explode("\n", \str_replace(["\r", "\n\n"], "\n", $chunk));
                $lines[\count($lines) - 1] .= \array_shift($chunk);
                $lines = \array_merge($lines, $chunk);
            }
        } finally {
            Magic::togglePeriodicLogging();
        }
        return \array_shift($lines);
    }
    /**
     * Asynchronously write to stdout/browser.
     *
     * @param string $string Message to echo
     *
     * @return Promise
     */
    public static function echo(string $string) : Promise
    {
        return getOutputBufferStream()->write($string);
    }
    /**
     * Check if is array or similar (traversable && countable && arrayAccess).
     *
     * @param mixed $var Value to check
     *
     * @return boolean
     */
    public static function isArrayOrAlike($var) : bool
    {
        return \is_array($var) || $var instanceof \ArrayAccess && $var instanceof \Traversable && $var instanceof \Countable;
    }
    /**
     * Create array.
     *
     * @param mixed ...$params Params
     *
     * @return array
     */
    public static function arr(...$params) : array
    {
        return $params;
    }
    /**
     * base64URL decode.
     *
     * @param string $data Data to decode
     *
     * @return string
     */
    public static function base64urlDecode(string $data) : string
    {
        return \base64_decode(\str_pad(\strtr($data, '-_', '+/'), \strlen($data) % 4, '=', STR_PAD_RIGHT));
    }
    /**
     * Base64URL encode.
     *
     * @param string $data Data to encode
     *
     * @return string
     */
    public static function base64urlEncode(string $data) : string
    {
        return \rtrim(\strtr(\base64_encode($data), '+/', '-_'), '=');
    }
    /**
     * null-byte RLE decode.
     *
     * @param string $string Data to decode
     *
     * @return string
     */
    public static function rleDecode(string $string) : string
    {
        $new = '';
        $last = '';
        $null = \chr(0);
        foreach (\str_split($string) as $cur) {
            if ($last === $null) {
                $new .= \str_repeat($last, \ord($cur));
                $last = '';
            } else {
                $new .= $last;
                $last = $cur;
            }
        }
        $string = $new . $last;
        return $string;
    }
    /**
     * null-byte RLE encode.
     *
     * @param string $string Data to encode
     *
     * @return string
     */
    public static function rleEncode(string $string) : string
    {
        $new = '';
        $count = 0;
        $null = \chr(0);
        foreach (\str_split($string) as $cur) {
            if ($cur === $null) {
                $count++;
            } else {
                if ($count > 0) {
                    $new .= $null . \chr($count);
                    $count = 0;
                }
                $new .= $cur;
            }
        }
        return $new;
    }
    /**
     * Inflate stripped photosize to full JPG payload.
     *
     * @param string $stripped Stripped photosize
     *
     * @return string JPG payload
     */
    public static function inflateStripped(string $stripped) : string
    {
        if (\strlen($stripped) < 3 || \ord($stripped[0]) !== 1) {
            return $stripped;
        }
        $header = 'ÿØÿà JFIF      ÿÛ C (#(#!#-+(0<dA<77<{X]Id‘€™–�€ŒŠ ´æÃ ªÚ­ŠŒÈÿËÚîõÿÿÿ›ÁÿÿÿúÿæýÿøÿÛ C+--<5<vAAvø¥Œ¥øøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøøÿÀ     " ÿÄ           	
ÿÄ µ   } !1AQa"q2�‘¡#B±ÁRÑð$3br‚	
%&\'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚáâãäåæçèéêñòóôõö÷øùúÿÄ        	
ÿÄ µ  w !1AQaq"2�B‘¡±Á	#3RðbrÑ
$4á%ñ&\'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz‚ƒ„…†‡ˆ‰Š’“”•–—˜™š¢£¤¥¦§¨©ª²³´µ¶·¸¹ºÂÃÄÅÆÇÈÉÊÒÓÔÕÖ×ØÙÚâãäåæçèéêòóôõö÷øùúÿÚ   ? ';
        static $footer = "\xff\xd9";
        $header[164] = $stripped[1];
        $header[165] = $stripped[2];
        return $header . \Phabel\Target\Php80\Polyfill::substr($stripped, 3) . $footer;
    }
    /**
     * Close connection with client, connected via web.
     *
     * @param string $message Message
     *
     * @return void
     */
    public static function closeConnection($message)
    {
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' || isset($GLOBALS['exited']) || \headers_sent() || isset($_GET['MadelineSelfRestart']) || Magic::$isIpcWorker) {
            return;
        }
        $buffer = @\ob_get_clean() ?: '';
        $buffer .= $message;
        \Phabel\Target\Php80\Polyfill::ignore_user_abort(true);
        \header('Connection: close');
        \header('Content-Type: text/html');
        echo $buffer;
        \flush();
        $GLOBALS['exited'] = true;
        if (\function_exists('fastcgi_finish_request')) {
            \fastcgi_finish_request();
        }
    }
    /**
     * Get maximum photo size.
     *
     * @internal
     *
     * @param array $sizes
     * @return array
     */
    public static function maxSize(array $sizes) : array
    {
        $maxPixels = 0;
        $max = null;
        foreach ($sizes as $size) {
            if (isset($size['w'], $size['h'])) {
                $curPixels = $size['w'] * $size['h'];
                if ($curPixels > $maxPixels) {
                    $maxPixels = $curPixels;
                    $max = $size;
                }
            }
        }
        if (!$max) {
            $maxType = 0;
            foreach ($sizes as $size) {
                $curType = \ord($size['type']);
                if ($curType > $maxType) {
                    $maxType = $curType;
                    $max = $size;
                }
            }
        }
        return $max;
    }
    /**
     * Get final element of array.
     *
     * @param array $what Array
     *
     * @return mixed
     */
    public static function end(array $what)
    {
        return \end($what);
    }
    /**
     * Whether this is altervista.
     *
     * @return boolean
     */
    public static function isAltervista() : bool
    {
        return Magic::$altervista;
    }
    /**
     * Checks private property exists in an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     *
     * @psalm-suppress InvalidScope
     *
     * @return bool
     * @access public
     */
    public static function hasVar($obj, string $var) : bool
    {
        return \Closure::bind(function () use($var) {
            return isset($this->{$var});
        }, $obj, \get_class($obj))->__invoke();
    }
    /**
     * Accesses a private variable from an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     *
     * @psalm-suppress InvalidScope
     *
     * @return mixed
     * @access public
     */
    public static function &getVar($obj, string $var)
    {
        return \Closure::bind(function &() use($var) {
            return $this->{$var};
        }, $obj, \get_class($obj))->__invoke();
    }
    /**
     * Sets a private variable in an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     * @param mixed $val Attribute value
     *
     * @psalm-suppress InvalidScope
     *
     * @return void
     *
     * @access public
     */
    public static function setVar($obj, string $var, &$val) : void
    {
        \Closure::bind(function () use($var, &$val) {
            $this->{$var} =& $val;
        }, $obj, \get_class($obj))->__invoke();
    }
    /**
     * Get absolute path to file, related to session path.
     *
     * @param string $file File
     *
     * @internal
     *
     * @return string
     */
    public static function absolute(string $file) : string
    {
        if (($file[0] ?? '') !== '/' && ($file[1] ?? '') !== ':' && !\in_array(\Phabel\Target\Php80\Polyfill::substr($file, 0, 4), ['phar', 'http'])) {
            $file = Magic::getcwd() . DIRECTORY_SEPARATOR . $file;
        }
        return $file;
    }
    /**
     * Parse t.me link.
     *
     * @internal
     *
     * @param string $link
     * @return (array{0: bool, 1: string} | null)
     */
    public static function parseLink(string $link) : ?array
    {
        if (!\preg_match('@(?:t|telegram)\\.(?:me|dog)/(joinchat/|\\+)?([a-z0-9_-]*)@i', $link, $matches)) {
            return null;
        }
        return [!!$matches[1], $matches[2]];
    }
    /**
     * Strip markdown tags.
     *
     * @internal
     *
     * @param string $markdown
     * @return string
     */
    public static function toString(string $markdown) : string
    {
        if ($markdown === '') {
            return $markdown;
        }
        $html = (new Parsedown($markdown))->text($markdown);
        $document = new DOMDocument('', 'utf-8');
        @$document->loadHTML(\mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));
        if (!$document->getElementsByTagName('body')[0]) {
            return '';
        }
        return $document->getElementsByTagName('body')[0]->childNodes[0]->textContent;
    }
}<?php

/**
 * FileCallbackInterface module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * File callback interface.
 */
interface FileCallbackInterface
{
    /**
     * Get file.
     *
     * @return mixed
     */
    public function getFile();
    /**
     * Invoke callback.
     *
     * @param float $percent Percent
     * @param float $speed Speed in mbps
     * @param float $time Time
     *
     * @return mixed
     */
    public function __invoke($percent, $speed, $time);
}<?php

/**
 * MyTelegramOrgWrapper module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Http\Client\Cookie\InMemoryCookieJar;
use Amp\Http\Client\Request;
/**
 * Wrapper for my.telegram.org.
 */
class MyTelegramOrgWrapper
{
    /**
     * Whether we're logged in.
     */
    private bool $logged = false;
    /**
     * Login hash.
     */
    private string $hash = '';
    /**
     * Phone number.
     *
     * @var string
     */
    private string $number = '';
    /**
     * Creation hash.
     */
    private string $creation_hash = '';
    /**
     * Settings.
     *
     * @var Settings
     */
    private $settings;
    /**
     * Async setting.
     */
    private bool $async = true;
    /**
     * Datacenter instance.
     */
    private DataCenter $datacenter;
    /**
     * Cooke jar.
     *
     * @var InMemoryCookieJar
     */
    private $jar;
    /**
     * Endpoint.
     */
    private const MY_TELEGRAM_URL = 'https://my.telegram.org';
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep() : array
    {
        return ['logged', 'hash', 'number', 'creation_hash', 'settings', 'async', 'jar'];
    }
    /**
     * Constructor.
     *
     * @param (array | Settings) $settings
     */
    public function __construct($settings)
    {
        $this->settings = Settings::parseFromLegacy($settings);
        if (!$this->settings instanceof Settings) {
            $settings = new Settings();
            $settings->merge($this->settings);
            $this->settings = $settings;
        }
        $this->__wakeup();
    }
    /**
     * Wakeup function.
     *
     * @return void
     */
    public function __wakeup() : void
    {
        if (!$this->settings) {
            $this->settings = new Settings();
        } elseif (\is_array($this->settings)) {
            $this->settings = Settings::parseFromLegacy($this->settings);
            if (!$this->settings instanceof Settings) {
                $settings = new Settings();
                $settings->merge($this->settings);
                $this->settings = $settings;
            }
        }
        if (!$this->jar || !$this->jar instanceof InMemoryCookieJar) {
            $this->jar = new InMemoryCookieJar();
        }
        $this->datacenter = new DataCenter(new class(new Logger($this->settings->getLogger()))
        {
            /**
             *
             */
            public Logger $logger;
            /**
             *
             */
            public function __construct(Logger $logger)
            {
                $this->logger = $logger;
            }
            /**
             *
             */
            public function getLogger() : Logger
            {
                return $this->logger;
            }
        }, [], $this->settings->getConnection(), true, $this->jar);
    }
    /**
     * Login.
     *
     * @param string $number Phone number
     *
     * @return \Generator
     */
    public function login(string $number) : \Generator
    {
        $this->number = $number;
        $request = new Request(self::MY_TELEGRAM_URL . '/auth/send_password', 'POST');
        $request->setBody(\http_build_query(['phone' => $number]));
        $request->setHeaders($this->getHeaders('origin'));
        $response = (yield $this->datacenter->getHTTPClient()->request($request));
        $result = (yield $response->getBody()->buffer());
        $resulta = \json_decode($result, true);
        if (!isset($resulta['random_hash'])) {
            throw new Exception($result);
        }
        $this->hash = $resulta['random_hash'];
    }
    /**
     * Complete login.
     *
     * @param string $password Password
     *
     * @return \Generator
     */
    public function completeLogin(string $password) : \Generator
    {
        if ($this->logged) {
            throw new Exception('Already logged in!');
        }
        $request = new Request(self::MY_TELEGRAM_URL . '/auth/login', 'POST');
        $request->setBody(\http_build_query(['phone' => $this->number, 'random_hash' => $this->hash, 'password' => $password]));
        $request->setHeaders($this->getHeaders('origin'));
        $request->setHeader('user-agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.13) Gecko/20080311 Firefox/2.0.0.13');
        $response = (yield $this->datacenter->getHTTPClient()->request($request));
        $result = (yield $response->getBody()->buffer());
        switch ($result) {
            case 'true':
                //Logger::log(['Login OK'], Logger::VERBOSE);
                break;
            default:
                throw new Exception($result);
        }
        return $this->logged = true;
    }
    /**
     * Whether we are logged in.
     *
     * @return boolean
     */
    public function loggedIn() : bool
    {
        return $this->logged;
    }
    /**
     * Check if an app was already created.
     *
     * @return \Generator
     */
    public function hasApp() : \Generator
    {
        if (!$this->logged) {
            throw new Exception('Not logged in!');
        }
        $request = new Request(self::MY_TELEGRAM_URL . '/apps');
        $request->setHeaders($this->getHeaders('refer'));
        $response = (yield $this->datacenter->getHTTPClient()->request($request));
        $result = (yield $response->getBody()->buffer());
        $title = \explode('</title>', \explode('<title>', $result)[1])[0];
        switch ($title) {
            case 'App configuration':
                return true;
            case 'Create new application':
                $this->creation_hash = \explode('"/>', \explode('<input type="hidden" name="hash" value="', $result)[1])[0];
                return false;
        }
        $this->logged = false;
        throw new Exception($title);
    }
    /**
     * Get the currently created app.
     *
     * @return \Generator
     */
    public function getApp() : \Generator
    {
        if (!$this->logged) {
            throw new Exception('Not logged in!');
        }
        $request = new Request(self::MY_TELEGRAM_URL . '/apps');
        $request->setHeaders($this->getHeaders('refer'));
        $response = (yield $this->datacenter->getHTTPClient()->request($request));
        $result = (yield $response->getBody()->buffer());
        $cose = \explode('<label for="app_id" class="col-md-4 text-right control-label">App api_id:</label>
      <div class="col-md-7">
        <span class="form-control input-xlarge uneditable-input" onclick="this.select();"><strong>', $result);
        $asd = \explode('</strong></span>', $cose[1]);
        $api_id = $asd[0];
        $cose = \explode('<label for="app_hash" class="col-md-4 text-right control-label">App api_hash:</label>
      <div class="col-md-7">
        <span class="form-control input-xlarge uneditable-input" onclick="this.select();">', $result);
        $asd = \explode('</span>', $cose[1]);
        $api_hash = $asd[0];
        return ['api_id' => (int) $api_id, 'api_hash' => $api_hash];
    }
    /**
     * Create an app.
     *
     * @param array $settings App parameters
     *
     * @return \Generator
     */
    public function createApp(array $settings) : \Generator
    {
        if (!$this->logged) {
            throw new Exception('Not logged in!');
        }
        if (yield from $this->hasApp()) {
            throw new Exception('The app was already created!');
        }
        $request = new Request(self::MY_TELEGRAM_URL . '/apps/create', 'POST');
        $request->setHeaders($this->getHeaders('app'));
        $request->setBody(\http_build_query(['hash' => $this->creation_hash, 'app_title' => $settings['app_title'], 'app_shortname' => $settings['app_shortname'], 'app_url' => $settings['app_url'], 'app_platform' => $settings['app_platform'], 'app_desc' => $settings['app_desc']]));
        $response = (yield $this->datacenter->getHTTPClient()->request($request));
        $result = (yield $response->getBody()->buffer());
        if ($result) {
            throw new Exception(\Phabel\Target\Php80\Polyfill::html_entity_decode($result));
        }
        $request = new Request(self::MY_TELEGRAM_URL . '/apps');
        $request->setHeaders($this->getHeaders('refer'));
        $response = (yield $this->datacenter->getHTTPClient()->request($request));
        $result = (yield $response->getBody()->buffer());
        $title = \explode('</title>', \explode('<title>', $result)[1])[0];
        if ($title === 'Create new application') {
            $this->creation_hash = \explode('"/>', \explode('<input type="hidden" name="hash" value="', $result)[1])[0];
            throw new \danog\MadelineProto\Exception('App creation failed');
        }
        $cose = \explode('<label for="app_id" class="col-md-4 text-right control-label">App api_id:</label>
      <div class="col-md-7">
        <span class="form-control input-xlarge uneditable-input" onclick="this.select();"><strong>', $result);
        $asd = \explode('</strong></span>', $cose['1']);
        $api_id = $asd['0'];
        $cose = \explode('<label for="app_hash" class="col-md-4 text-right control-label">App api_hash:</label>
      <div class="col-md-7">
        <span class="form-control input-xlarge uneditable-input" onclick="this.select();">', $result);
        $asd = \explode('</span>', $cose['1']);
        $api_hash = $asd['0'];
        return ['api_id' => (int) $api_id, 'api_hash' => $api_hash];
    }
    /**
     * Function for generating curl request headers.
     *
     * @param string $httpType Origin
     *
     * @return array
     */
    private function getHeaders(string $httpType) : array
    {
        // Common header flags.
        $headers = [];
        $headers[] = 'Dnt: 1';
        $headers[] = 'Connection: keep-alive';
        $headers[] = 'Accept-Language: it-IT,it;q=0.8,en-US;q=0.6,en;q=0.4';
        $headers[] = 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36';
        // Add additional headers based on the type of request.
        switch ($httpType) {
            case 'origin':
                $headers[] = 'Origin: ' . self::MY_TELEGRAM_URL;
                //$headers[] = 'Accept-Encoding: gzip, deflate, br';
                $headers[] = 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8';
                $headers[] = 'Accept: application/json, text/javascript, */*; q=0.01';
                $headers[] = 'Referer: ' . self::MY_TELEGRAM_URL . '/auth';
                $headers[] = 'X-Requested-With: XMLHttpRequest';
                break;
            case 'refer':
                //$headers[] = 'Accept-Encoding: gzip, deflate, sdch, br';
                $headers[] = 'Upgrade-Insecure-Requests: 1';
                $headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8';
                $headers[] = 'Referer: ' . self::MY_TELEGRAM_URL;
                $headers[] = 'Cache-Control: max-age=0';
                break;
            case 'app':
                $headers[] = 'Origin: ' . self::MY_TELEGRAM_URL;
                //$headers[] = 'Accept-Encoding: gzip, deflate, br';
                $headers[] = 'Content-Type: application/x-www-form-urlencoded; charset=UTF-8';
                $headers[] = 'Accept: */*';
                $headers[] = 'Referer: ' . self::MY_TELEGRAM_URL . '/apps';
                $headers[] = 'X-Requested-With: XMLHttpRequest';
                break;
        }
        $final_headers = [];
        foreach ($headers as $header) {
            list($key, $value) = \explode(':', $header, 2);
            $final_headers[\trim($key)] = \trim($value);
        }
        return $final_headers;
    }
    /**
     * Enable or disable async.
     *
     * @param boolean $async Async
     *
     * @return void
     */
    public function async(bool $async) : void
    {
        $this->async = $async;
    }
    /**
     * Run specified callable synchronously.
     *
     * @param callable $callable Callable
     *
     * @return mixed
     */
    public function loop(callable $callable)
    {
        return Tools::wait($callable());
    }
    /**
     * Call function.
     *
     * @param string $name Function name
     * @param array $arguments Arguments
     *
     * @return mixed
     */
    public function __call(string $name, array $arguments)
    {
        $name .= '_async';
        $async = \is_array(\end($arguments)) && isset(\end($arguments)['async']) ? \end($arguments)['async'] : $this->async;
        if (!\method_exists($this, $name)) {
            throw new Exception("{$name} does not exist!");
        }
        return $async ? $this->{$name}(...$arguments) : Tools::wait($this->{$name}(...$arguments));
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * Serialization settings.
 */
class Serialization extends SettingsAbstract
{
    /**
     * Serialization interval, in seconds.
     */
    protected int $interval = 30;
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        if (isset($settings['serialization']['serialization_interval'])) {
            $this->setInterval($settings['serialization']['serialization_interval']);
        }
    }
    /**
     * Get serialization interval, in seconds.
     *
     * @return int
     */
    public function getInterval() : int
    {
        return $this->interval;
    }
    /**
     * Set serialization interval, in seconds.
     *
     * @param int $interval Serialization interval, in seconds.
     *
     * @return self
     */
    public function setInterval(int $interval) : self
    {
        $this->interval = $interval;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * Secret chat settings.
 */
class SecretChats extends SettingsAbstract
{
    /**
     * What secret chats to accept.
     *
     * Boolean or array of IDs
     *
     * @var bool|array<int>
     */
    protected $accept = true;
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        if (isset($settings['secret_chats']['accept_chats'])) {
            $this->setAccept($settings['secret_chats']['accept_chats']);
        }
    }
    /**
     * Get boolean or array of IDs.
     *
     * @return (bool | array<int>)
     */
    public function getAccept()
    {
        return $this->accept;
    }
    /**
     * Set boolean or array of IDs.
     *
     * @param (bool | array<int>) $accept Boolean or array of IDs
     *
     * @return self
     */
    public function setAccept($accept) : self
    {
        $this->accept = $accept;
        return $this;
    }
    /**
     * Can we accept this chat.
     *
     * @internal
     *
     * @param integer $id
     * @return boolean
     */
    public function canAccept(int $id) : bool
    {
        if (!$this->accept) {
            return false;
        }
        if ($this->accept === true) {
            return true;
        }
        return \in_array($id, $this->accept);
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * RPC settings.
 */
class RPC extends SettingsAbstract
{
    /**
     * RPC timeout.
     */
    protected int $rpcTimeout = 5 * 60;
    /**
     * Flood timeout: if FLOOD_WAIT_ time is bigger than this, throw exception instead of waiting asynchronously.
     */
    protected int $floodTimeout = 10 * 60;
    /**
     * Maximum number of message IDs to consider when using call queues.
     */
    protected int $limitCallQueue = 100;
    /**
     * Encode payload with GZIP if bigger than.
     */
    protected int $gzipEncodeIfGt = 1024 * 1024;
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        if (isset($settings['connection_settings']['all']['drop_timeout'])) {
            $this->setRpcTimeout($settings['connection_settings']['all']['drop_timeout']);
        }
        if (isset($settings['flood_timeout']['wait_if_lt'])) {
            $this->setFloodTimeout($settings['flood_timeout']['wait_if_lt']);
        }
        if (isset($settings['msg_array_limit']['call_queue'])) {
            $this->setLimitCallQueue($settings['msg_array_limit']['call_queue']);
        }
        if (isset($settings['requests']['gzip_encode_if_gt'])) {
            $this->setLimitCallQueue($settings['requests']['gzip_encode_if_gt']);
        }
    }
    /**
     * Get RPC timeout.
     *
     * @return int
     */
    public function getRpcTimeout() : int
    {
        return $this->rpcTimeout;
    }
    /**
     * Set RPC timeout.
     *
     * @param int $rpcTimeout RPC timeout.
     *
     * @return self
     */
    public function setRpcTimeout(int $rpcTimeout) : self
    {
        $this->rpcTimeout = $rpcTimeout;
        return $this;
    }
    /**
     * Get flood timeout: if FLOOD_WAIT_ time is bigger than this, throw exception instead of waiting asynchronously.
     *
     * @return int
     */
    public function getFloodTimeout() : int
    {
        return $this->floodTimeout;
    }
    /**
     * Set flood timeout: if FLOOD_WAIT_ time is bigger than this, throw exception instead of waiting asynchronously.
     *
     * @param int $floodTimeout Flood timeout: if FLOOD_WAIT_ time is bigger than this, throw exception instead of waiting asynchronously
     *
     * @return self
     */
    public function setFloodTimeout(int $floodTimeout) : self
    {
        $this->floodTimeout = $floodTimeout;
        return $this;
    }
    /**
     * Get maximum number of messages to consider when using call queues.
     *
     * @return int
     */
    public function getLimitCallQueue() : int
    {
        return $this->limitCallQueue;
    }
    /**
     * Set maximum number of messages to consider when using call queues.
     *
     * @param int $limitCallQueue Maximum number of messages to consider when using call queues
     *
     * @return self
     */
    public function setLimitCallQueue(int $limitCallQueue) : self
    {
        $this->limitCallQueue = $limitCallQueue;
        return $this;
    }
    /**
     * Get encode payload with GZIP if bigger than.
     *
     * @return int
     */
    public function getGzipEncodeIfGt() : int
    {
        return $this->gzipEncodeIfGt;
    }
    /**
     * Set encode payload with GZIP if bigger than.
     *
     * @param int $gzipEncodeIfGt Encode payload with GZIP if bigger than
     *
     * @return self
     */
    public function setGzipEncodeIfGt(int $gzipEncodeIfGt) : self
    {
        $this->gzipEncodeIfGt = $gzipEncodeIfGt;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * Cryptography settings.
 */
class Auth extends SettingsAbstract
{
    /**
    * Validity period of temporary keys.
    Validity period of the binding of temporary and permanent keys.
    */
    protected int $defaultTempAuthKeyExpiresIn = 1 * 24 * 60 * 60;
    /**
     * Whether to use PFS.
     */
    protected bool $pfs;
    /**
     * Max tries for generating auth key.
     */
    protected int $maxAuthTries = 5;
    /**
     *
     */
    public function __construct()
    {
        $this->pfs = \extension_loaded('gmp');
    }
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        foreach (self::toCamel(['default_temp_auth_key_expires_in']) as $object => $array) {
            if (isset($settings['authorization'][$array])) {
                $this->{$object}($settings['authorization'][$array]);
            }
        }
        if (isset($settings['connection_settings']['all']['pfs'])) {
            $this->setPfs($settings['connection_settings']['all']['pfs']);
        }
    }
    /**
     * Get validity period of the binding of temporary and permanent keys.
     *
     * @return int
     */
    public function getDefaultTempAuthKeyExpiresIn() : int
    {
        return $this->defaultTempAuthKeyExpiresIn;
    }
    /**
     * Set validity period of the binding of temporary and permanent keys.
     *
     * @param int $defaultTempAuthKeyExpiresIn Validity period of the binding of temporary and permanent keys.
     *
     * @return self
     */
    public function setDefaultTempAuthKeyExpiresIn(int $defaultTempAuthKeyExpiresIn) : self
    {
        $this->defaultTempAuthKeyExpiresIn = $defaultTempAuthKeyExpiresIn;
        return $this;
    }
    /**
     * Get whether to use PFS.
     *
     * @return bool
     */
    public function getPfs() : bool
    {
        return $this->pfs;
    }
    /**
     * Set whether to use PFS.
     *
     * @param bool $pfs Whether to use PFS
     *
     * @return self
     */
    public function setPfs(bool $pfs) : self
    {
        $this->pfs = $pfs;
        return $this;
    }
    /**
     * Get max tries for generating auth key.
     *
     * @return int
     */
    public function getMaxAuthTries() : int
    {
        return $this->maxAuthTries;
    }
    /**
     * Set max tries for generating auth key.
     *
     * @param int $maxAuthTries Max tries for generating auth key
     *
     * @return self
     */
    public function setMaxAuthTries(int $maxAuthTries) : self
    {
        $this->maxAuthTries = $maxAuthTries;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\Exception;
use danog\MadelineProto\Lang;
use danog\MadelineProto\Magic;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\SettingsAbstract;
/**
 * App information.
 */
class AppInfo extends SettingsAbstract
{
    /**
     * API ID.
     */
    protected int $apiId;
    /**
     * API hash.
     */
    protected string $apiHash;
    /**
     * Device model.
     */
    protected string $deviceModel;
    /**
     * System version.
     */
    protected string $systemVersion;
    /**
     * App version.
     */
    protected string $appVersion;
    /**
     * Language code.
     */
    protected string $langCode = 'en';
    /**
     * Language pack.
     */
    protected string $langPack = '';
    /**
     *
     */
    public function __construct()
    {
        // Detect device model
        try {
            $this->deviceModel = \php_uname('s');
        } catch (\Throwable $e) {
            $this->deviceModel = 'Web server';
        }
        // Detect system version
        try {
            $this->systemVersion = \php_uname('r');
        } catch (\Throwable $e) {
            $this->systemVersion = PHP_VERSION;
        }
        // Detect language
        Lang::$current_lang =& Lang::$lang[$this->langCode];
        if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
            $this->setLangCode(\Phabel\Target\Php80\Polyfill::substr($_SERVER['HTTP_ACCEPT_LANGUAGE'], 0, 2));
        } elseif (isset($_SERVER['LANG'])) {
            $this->setLangCode(\explode('_', $_SERVER['LANG'])[0]);
        }
        $this->init();
    }
    /**
     *
     */
    public function __wakeup()
    {
        $this->init();
    }
    /**
     *
     */
    public function init() : void
    {
        Magic::start(true);
        // Detect language pack
        if (isset(Lang::$lang[$this->langCode])) {
            Lang::$current_lang =& Lang::$lang[$this->langCode];
        }
        $this->appVersion = MTProto::RELEASE . ' (' . MTProto::V . ', ' . Magic::$version . ')';
    }
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        foreach (self::toCamel(['api_id', 'api_hash', 'device_model', 'system_version', 'app_version', 'lang_code', 'lang_pack']) as $object => $array) {
            if (isset($settings['app_info'][$array])) {
                $this->{$object}($settings['app_info'][$array]);
            }
        }
    }
    /**
     * Check if the settings have API ID/hash information.
     *
     * @return boolean
     */
    public function hasApiInfo() : bool
    {
        return isset($this->apiHash, $this->apiId) && $this->apiId;
    }
    /**
     * Get API ID.
     *
     * @return int
     */
    public function getApiId() : int
    {
        if (!isset($this->apiId)) {
            throw new Exception(Lang::$current_lang['api_not_set']);
        }
        return $this->apiId;
    }
    /**
     * Set API ID.
     *
     * @param int $apiId API ID.
     *
     * @return self
     */
    public function setApiId(int $apiId) : self
    {
        $this->apiId = $apiId;
        if ($apiId === 6) {
            // TG DEV NOTICE: these app info spoofing measures were implemented for NON-MALICIOUS purposes.
            // All accounts registered with a custom API ID require manual verification through recover@telegram.org, to avoid instant permabans.
            // This makes usage of all MTProto libraries very difficult, at least for new users.
            // To help a bit, when the android API ID is used, the android app infos are spoofed too.
            // THE ANDROID API HASH IS NOT PRESENT IN THIS REPOSITORY, AND WILL NOT BE GIVEN TO EVERYONE.
            // This measure was NOT created with the intent to aid spammers, flooders, and other scum.
            //
            // I understand that automated account registration through headless libraries may indicate the creation of a botnet,
            // ...and I understand why these automatic bans were implemented in the first place.
            // Manual requests to activate numbers through recover@telegram.org will still be required for the majority of users of this library,
            // ...those that choose to user their own API ID for their application.
            //
            // To be honest, I wrote this feature just for me, since I honestly don't want to
            // ...go through the hassle of registering => recovering => logging in to every account I use for my services (mainly webradios and test userbots)
            $this->deviceModel = 'LGENexus 5';
            $this->systemVersion = 'SDK 28';
            $this->appVersion = '4.9.1 (13613)';
            $this->langPack = 'android';
        }
        return $this;
    }
    /**
     * Get API hash.
     *
     * @return string
     */
    public function getApiHash() : string
    {
        if (!isset($this->apiHash)) {
            throw new Exception(Lang::$current_lang['api_not_set']);
        }
        return $this->apiHash;
    }
    /**
     * Set API hash.
     *
     * @param string $apiHash API hash.
     *
     * @return self
     */
    public function setApiHash(string $apiHash) : self
    {
        $this->apiHash = $apiHash;
        return $this;
    }
    /**
     * Get device model.
     *
     * @return string
     */
    public function getDeviceModel() : string
    {
        return $this->deviceModel;
    }
    /**
     * Set device model.
     *
     * @param string $deviceModel Device model.
     *
     * @return self
     */
    public function setDeviceModel(string $deviceModel) : self
    {
        $this->deviceModel = $deviceModel;
        return $this;
    }
    /**
     * Get system version.
     *
     * @return string
     */
    public function getSystemVersion() : string
    {
        return $this->systemVersion;
    }
    /**
     * Set system version.
     *
     * @param string $systemVersion System version.
     *
     * @return self
     */
    public function setSystemVersion(string $systemVersion) : self
    {
        $this->systemVersion = $systemVersion;
        return $this;
    }
    /**
     * Get app version.
     *
     * @return string
     */
    public function getAppVersion() : string
    {
        return $this->appVersion;
    }
    /**
     * Set app version.
     *
     * @param string $appVersion App version.
     *
     * @return self
     */
    public function setAppVersion(string $appVersion) : self
    {
        $this->appVersion = $appVersion;
        return $this;
    }
    /**
     * Get language code.
     *
     * @return string
     */
    public function getLangCode() : string
    {
        return $this->langCode;
    }
    /**
     * Set language code.
     *
     * @param string $langCode Language code.
     *
     * @return self
     */
    public function setLangCode(string $langCode) : self
    {
        $this->langCode = $langCode;
        if (isset(Lang::$lang[$this->langCode])) {
            Lang::$current_lang =& Lang::$lang[$this->langCode];
        }
        return $this;
    }
    /**
     * Get language pack.
     *
     * @return string
     */
    public function getLangPack() : string
    {
        return $this->langPack;
    }
    /**
     * Set language pack.
     *
     * @param string $langPack Language pack.
     *
     * @return self
     */
    public function setLangPack(string $langPack) : self
    {
        $this->langPack = $langPack;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\Magic;
use danog\MadelineProto\SettingsAbstract;
/**
 * IPC server settings.
 */
class Ipc extends SettingsAbstract
{
    /**
     *
     */
    public function __construct()
    {
        Magic::start(true);
    }
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
    }
    /**
     * Get WARNING: this will cause slow startup if enabled.
     *
     * @return bool
     */
    public function getSlow() : bool
    {
        return Magic::$isIpcWorker;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * VoIP settings.
 */
class VoIP extends SettingsAbstract
{
    /**
     * Whether to preload all songs in memory.
     */
    private bool $preloadAudio = true;
    /**
     * Get whether to preload all songs in memory.
     *
     * @return bool
     */
    public function getPreloadAudio() : bool
    {
        return $this->preloadAudio;
    }
    /**
     * Set whether to preload all songs in memory.
     *
     * @param bool $preloadAudio Whether to preload all songs in memory
     *
     * @return self
     */
    public function setPreloadAudio(bool $preloadAudio) : self
    {
        $this->preloadAudio = $preloadAudio;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\Logger as MadelineProtoLogger;
use danog\MadelineProto\Magic;
use danog\MadelineProto\SettingsAbstract;
use danog\MadelineProto\Tools;
/**
 * Logger settings.
 */
class Logger extends SettingsAbstract
{
    /**
     * Logger type.
     *
     * @var MadelineProtoLogger::LOGGER_* $type Logger type.
     */
    protected int $type;
    /**
     * Extra parameter for logger.
     *
     * @var null|callable|string
     */
    protected $extra;
    /**
     * Logging level.
     *
     * @var MadelineProtoLogger::LEVEL_*
     */
    protected int $level = MadelineProtoLogger::LEVEL_VERBOSE;
    /**
     * Maximum filesize for logger, in case of file logging.
     */
    protected int $maxSize = 1 * 1024 * 1024;
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        if (!isset($settings['logger']['logger_param']) && isset($settings['logger']['param'])) {
            $settings['logger']['logger_param'] = $settings['logger']['param'];
        }
        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' && isset($settings['logger']['logger_param']) && $settings['logger']['logger_param'] === 'MadelineProto.log') {
            $settings['logger']['logger_param'] = Magic::$script_cwd . '/MadelineProto.log';
        }
        switch ($settings['logger']['logger_level'] ?? null) {
            case 'ULTRA_VERBOSE':
                $settings['logger']['logger_level'] = 5;
                break;
            case 'VERBOSE':
                $settings['logger']['logger_level'] = 4;
                break;
            case 'NOTICE':
                $settings['logger']['logger_level'] = 3;
                break;
            case 'WARNING':
                $settings['logger']['logger_level'] = 2;
                break;
            case 'ERROR':
                $settings['logger']['logger_level'] = 1;
                break;
            case 'FATAL ERROR':
                $settings['logger']['logger_level'] = 0;
                break;
        }
        if (isset($settings['logger']['logger'])) {
            $this->setType($settings['logger']['logger']);
        }
        if (isset($settings['logger']['logger_param'])) {
            $this->setExtra($settings['logger']['logger_param']);
        }
        if (isset($settings['logger']['logger_level'])) {
            $this->setLevel($settings['logger']['logger_level']);
        }
        if (isset($settings['logger']['max_size'])) {
            $this->setMaxSize($settings['logger']['max_size'] ?? 1 * 1024 * 1024);
        }
        $this->init();
    }
    /**
     *
     */
    public function __construct()
    {
        $this->type = PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ? MadelineProtoLogger::ECHO_LOGGER : MadelineProtoLogger::FILE_LOGGER;
        Magic::start(true);
        $this->extra = Magic::$script_cwd . '/MadelineProto.log';
    }
    /**
     *
     */
    public function __sleep()
    {
        return $this->extra instanceof \Closure ? ['type', 'extra', 'level', 'maxSize'] : ['type', 'level', 'maxSize'];
    }
    /**
     * Wakeup function.
     */
    public function __wakeup()
    {
        $this->type = PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ? MadelineProtoLogger::ECHO_LOGGER : MadelineProtoLogger::FILE_LOGGER;
        if (!$this->extra && $this->type === MadelineProtoLogger::FILE_LOGGER) {
            $this->extra = Magic::$script_cwd . '/MadelineProto.log';
        }
        $this->init();
    }
    /**
     * Initialize global logging.
     *
     * @return void
     */
    private function init()
    {
        Magic::start(false);
        MadelineProtoLogger::constructorFromSettings($this);
    }
    /**
     * Get $type Logger type.
     *
     * @return MadelineProtoLogger::LOGGER_*
     */
    public function getType() : int
    {
        return \defined('MADELINE_WORKER') ? MadelineProtoLogger::FILE_LOGGER : $this->type;
    }
    /**
     * Set $type Logger type.
     *
     * @param MadelineProtoLogger::LOGGER_* $type $type Logger type.
     *
     * @return self
     */
    public function setType(int $type) : self
    {
        if ($type === MadelineProtoLogger::NO_LOGGER) {
            $type = PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ? MadelineProtoLogger::ECHO_LOGGER : MadelineProtoLogger::FILE_LOGGER;
        }
        $this->type = $type;
        return $this;
    }
    /**
     * Get extra parameter for logger.
     *
     * @return (null | callable | string)
     */
    public function getExtra()
    {
        return $this->type === MadelineProtoLogger::FILE_LOGGER ? Tools::absolute($this->extra) : $this->extra;
    }
    /**
     * Set extra parameter for logger.
     *
     * @param (null | callable | string) $extra Extra parameter for logger.
     *
     * @return self
     */
    public function setExtra($extra) : self
    {
        if ($this->type === MadelineProtoLogger::CALLABLE_LOGGER && !\is_callable($extra)) {
            $this->setType(PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg' ? MadelineProtoLogger::ECHO_LOGGER : MadelineProtoLogger::FILE_LOGGER);
            return $this;
        }
        $this->extra = $extra;
        return $this;
    }
    /**
     * Get logging level.
     *
     * @return MadelineProtoLogger::LEVEL_*
     */
    public function getLevel() : int
    {
        return $this->level;
    }
    /**
     * Set logging level.
     *
     * @param MadelineProtoLogger::LEVEL_* $level Logging level.
     *
     * @return self
     */
    public function setLevel(int $level) : self
    {
        $this->level = \max($level, MadelineProtoLogger::NOTICE);
        return $this;
    }
    /**
     * Get maximum filesize for logger, in case of file logging.
     *
     * @return int
     */
    public function getMaxSize() : int
    {
        return $this->maxSize;
    }
    /**
     * Set maximum filesize for logger, in case of file logging.
     *
     * @param int $maxSize Maximum filesize for logger, in case of file logging.
     *
     * @return self
     */
    public function setMaxSize(int $maxSize) : self
    {
        $this->maxSize = $maxSize === -1 ? $maxSize : \max($maxSize, 25 * 1024 * 1024);
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * PWRTelegram settings.
 */
class Pwr extends SettingsAbstract
{
    /**
     * Whether to try resolving usernames using PWRTelegram DB.
     */
    protected bool $requests = true;
    /**
     * DB token.
     */
    protected string $dbToken = '';
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        $this->requests = $settings['pwr']['requests'] ?? true;
        $this->dbToken = $settings['pwr']['db_token'] ?? '';
    }
    /**
     * Get whether to try resolving usernames using PWRTelegram DB.
     *
     * @return bool
     */
    public function getRequests() : bool
    {
        return $this->requests;
    }
    /**
     * Set whether to try resolving usernames using PWRTelegram DB.
     *
     * @param bool $requests Whether to try resolving usernames using PWRTelegram DB.
     *
     * @return self
     */
    public function setRequests(bool $requests) : self
    {
        $this->requests = $requests;
        return $this;
    }
    /**
     * Get DB token.
     *
     * @return string
     */
    public function getDbToken() : string
    {
        return $this->dbToken;
    }
    /**
     * Set DB token.
     *
     * @param string $dbToken DB token.
     *
     * @return self
     */
    public function setDbToken(string $dbToken) : self
    {
        $this->dbToken = $dbToken;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\Exception;
use danog\MadelineProto\Magic;
use danog\MadelineProto\SettingsAbstract;
use danog\MadelineProto\Stream\Common\UdpBufferedStream;
use danog\MadelineProto\Stream\MTProtoBufferInterface;
use danog\MadelineProto\Stream\MTProtoTransport\AbridgedStream;
use danog\MadelineProto\Stream\MTProtoTransport\FullStream;
use danog\MadelineProto\Stream\MTProtoTransport\HttpsStream;
use danog\MadelineProto\Stream\MTProtoTransport\HttpStream;
use danog\MadelineProto\Stream\MTProtoTransport\IntermediatePaddedStream;
use danog\MadelineProto\Stream\MTProtoTransport\ObfuscatedStream;
use danog\MadelineProto\Stream\Proxy\HttpProxy;
use danog\MadelineProto\Stream\Proxy\SocksProxy;
use danog\MadelineProto\Stream\RawStreamInterface;
use danog\MadelineProto\Stream\StreamInterface;
use danog\MadelineProto\Stream\Transport\DefaultStream;
use danog\MadelineProto\Stream\Transport\WssStream;
use danog\MadelineProto\Stream\Transport\WsStream;
/**
 * Connection settings.
 */
class Connection extends SettingsAbstract
{
    /**
     * Minimum media socket count.
     */
    protected int $minMediaSocketCount = 5;
    /**
     * Maximum media socket count.
     */
    protected int $maxMediaSocketCount = 10;
    /**
     * Robin period (seconds).
     */
    protected int $robinPeriod = 10;
    /**
     * Default DC ID.
     */
    protected int $defaultDc = 2;
    /**
     * Default DC params.
     */
    private array $defaultDcParams = ['datacenter' => 2];
    /**
     * Protocol identifier.
     *
     * @var class-string<MTProtoBufferInterface>
     */
    protected string $protocol = AbridgedStream::class;
    /**
     * Transport identifier.
     *
     * @var class-string<RawStreamInterface>
     */
    protected string $transport = DefaultStream::class;
    /**
     * Proxy identifiers.
     *
     * @var array<class-string<StreamInterface>, array>
     */
    protected array $proxy = [];
    /**
     * Whether to use the obfuscated protocol.
     */
    protected bool $obfuscated = false;
    /**
     * Whether we're in test mode.
     */
    protected bool $testMode = false;
    /**
     * Whether to use ipv6.
     */
    protected bool $ipv6 = false;
    /**
     * Connection timeout.
     */
    protected int $timeout = 2;
    /**
     * Ping interval.
     */
    protected int $pingInterval = 10;
    /**
     * Whether to retry connection.
     */
    protected bool $retry = true;
    /**
     * Whether to use DNS over HTTPS.
     */
    protected bool $useDoH = true;
    /**
     * Bind on specific address and port.
     */
    private ?string $bindTo = null;
    /**
     * Subdomains of web.telegram.org for https protocol.
     */
    protected array $sslSubdomains = [1 => 'pluto', 2 => 'venus', 3 => 'aurora', 4 => 'vesta', 5 => 'flora'];
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        if (isset($settings['connection']['ssl_subdomains'])) {
            $this->setSslSubdomains($settings['connection']['ssl_subdomains']);
        }
        $settings = $settings['connection_settings'] ?? [];
        if (isset($settings['media_socket_count']['min'])) {
            $this->setMinMediaSocketCount($settings['media_socket_count']['min']);
        }
        if (isset($settings['media_socket_count']['max'])) {
            $this->setMaxMediaSocketCount($settings['media_socket_count']['max']);
        }
        foreach (self::toCamel(['robin_period', 'default_dc', 'pfs']) as $object => $array) {
            if (isset($settings[$array])) {
                $this->{$object}($settings[$array]);
            }
        }
        $settings = $settings['all'] ?? [];
        foreach (self::toCamel(['test_mode', 'ipv6', 'timeout', 'obfuscated']) as $object => $array) {
            if (isset($settings[$array])) {
                $this->{$object}($settings[$array]);
            }
        }
        if (isset($settings['do_not_retry'])) {
            $this->setRetry(false);
        }
        if (isset($settings['proxy'])) {
            $isProxyArray = \is_iterable($settings['proxy']);
            foreach ($isProxyArray ? $settings['proxy'] : [$settings['proxy']] as $key => $proxy) {
                if ($proxy === '\\Socket') {
                    $proxy = DefaultStream::class;
                } elseif ($proxy === '\\SocksProxy') {
                    $proxy = SocksProxy::class;
                } elseif ($proxy === '\\HttpProxy') {
                    $proxy = HttpProxy::class;
                } elseif ($proxy === '\\MTProxySocket') {
                    $proxy = ObfuscatedStream::class;
                }
                if ($proxy !== DefaultStream::class) {
                    $this->addProxy($proxy, $isProxyArray ? $settings['proxy_extra'][$key] : $settings['proxy_extra']);
                }
            }
        }
        if (isset($settings['transport'])) {
            $transport = $settings['transport'];
            if ($transport === 'tcp') {
                $transport = DefaultStream::class;
            } elseif ($transport === 'ws') {
                $transport = WsStream::class;
            } elseif ($transport === 'wss') {
                $transport = WssStream::class;
            }
            $this->setTransport($transport);
        }
        if (isset($settings['protocol'])) {
            $protocol = $settings['protocol'];
            switch ($protocol) {
                case 'abridged':
                case 'tcp_abridged':
                    $protocol = AbridgedStream::class;
                    break;
                case 'intermediate':
                case 'tcp_intermediate':
                    $protocol = AbridgedStream::class;
                    break;
                case 'obfuscated2':
                    $this->setObfuscated(true);
                // no break
                case 'intermediate_padded':
                case 'tcp_intermediate_padded':
                    $protocol = IntermediatePaddedStream::class;
                    break;
                case 'full':
                case 'tcp_full':
                    $protocol = FullStream::class;
                    break;
                case 'http':
                    $protocol = HttpStream::class;
                    break;
                case 'https':
                    $protocol = HttpsStream::class;
                    break;
                case 'udp':
                    $protocol = UdpBufferedStream::class;
                    break;
            }
            $this->setProtocol($protocol);
        }
    }
    /**
     *
     */
    public function __construct()
    {
        $this->init();
    }
    /**
     *
     */
    public function __wakeup()
    {
        $this->init();
    }
    /**
     *
     */
    public function init() : void
    {
        Magic::start(true);
        if (Magic::$altervista) {
            $this->addProxy(HttpProxy::class, ['address' => 'localhost', 'port' => 80]);
            $this->setProtocol(HttpStream::class);
        } else {
            $this->removeProxy(HttpProxy::class, ['address' => 'localhost', 'port' => 80]);
        }
    }
    /**
     * Get protocol identifier.
     *
     * @return string
     */
    public function getProtocol() : string
    {
        return $this->protocol;
    }
    /**
    * Set protocol identifier.
    *
    * Available MTProto transport protocols (smaller overhead is better):
    *
    * * `\danog\MadelineProto\Stream\MTProtoTransport\AbridgedStream`: Lightest protocol available
    Overhead: Very small
    Minimum envelope length: 1 byte (length)
    Maximum envelope length: 4 bytes (length)
    *
    * * `\danog\MadelineProto\Stream\MTProtoTransport\IntermediateStream`: I guess they like having multiple protocols
    Overhead: small
    Minimum envelope length: 4 bytes (length)
    Maximum envelope length: 4 bytes (length)
    *
    * * `\danog\MadelineProto\Stream\MTProtoTransport\IntermediatePaddedStream`: Padded version of the intermediate protocol, to use with obfuscation enabled to bypass ISP blocks
    Overhead: small-medium
    Minimum envelope length: random
    Maximum envelope length: random
    *
    * * `\danog\MadelineProto\Stream\MTProtoTransport\FullStream`: The basic MTProto transport protocol
    Overhead: medium
    Minimum envelope length: 12 bytes (length+seqno+crc)
    Maximum envelope length: 12 bytes (length+seqno+crc)
    Pros:
    Initial integrity check with crc32
    Transport sequence number check
    *
    * * Cons:
    Initial integrity check with crc32 is not that useful since the TCP protocol already uses it internally
    Transport sequence number check is also not that useful since transport sequence numbers are not encrypted and thus cannot be used to avoid replay attacks, and MadelineProto already uses MTProto sequence numbers and message ids for that.
    *
    * * `\danog\MadelineProto\Stream\MTProtoTransport\HttpStream`: MTProto over HTTP for browsers and webhosts
    Overhead: medium
    Pros:
    Can be used on restricted webhosts or browsers
    Cons:
    Very big envelope length
    *
    * * `\danog\MadelineProto\Stream\MTProtoTransport\HttpsStream`: MTProto over HTTPS for browsers and webhosts, very secure
    Overhead: high
    Pros:
    Can be used on restricted webhosts or browsers
    Provides an additional layer of security by trasmitting data over TLS
    Integrity checks with HMAC built into TLS
    Sequence number checks built into TLS
    Cons:
    Very big envelope length
    Requires an additional round of encryption
    *
    * @param class-string<MTProtoBufferInterface> $protocol Protocol identifier
    *
    * @return self
    */
    public function setProtocol(string $protocol) : self
    {
        if (!isset(\class_implements($protocol)[MTProtoBufferInterface::class])) {
            throw new Exception("An invalid protocol was specified!");
        }
        $this->protocol = $protocol;
        return $this;
    }
    /**
     * Get whether to use ipv6.
     *
     * @return bool
     */
    public function getIpv6() : bool
    {
        return $this->ipv6;
    }
    /**
     * Set whether to use ipv6.
     *
     * @param bool $ipv6 Whether to use ipv6
     *
     * @return self
     */
    public function setIpv6(bool $ipv6) : self
    {
        $this->ipv6 = $ipv6;
        return $this;
    }
    /**
     * Get subdomains of web.telegram.org for https protocol.
     *
     * @return array
     */
    public function getSslSubdomains() : array
    {
        return $this->sslSubdomains;
    }
    /**
     * Set subdomains of web.telegram.org for https protocol.
     *
     * @param array $sslSubdomains Subdomains of web.telegram.org for https protocol.
     *
     * @return self
     */
    public function setSslSubdomains(array $sslSubdomains) : self
    {
        $this->sslSubdomains = $sslSubdomains;
        return $this;
    }
    /**
     * Get minimum media socket count.
     *
     * @return int
     */
    public function getMinMediaSocketCount() : int
    {
        return $this->minMediaSocketCount;
    }
    /**
     * Set minimum media socket count.
     *
     * @param int $minMediaSocketCount Minimum media socket count.
     *
     * @return self
     */
    public function setMinMediaSocketCount(int $minMediaSocketCount) : self
    {
        $this->minMediaSocketCount = $minMediaSocketCount;
        return $this;
    }
    /**
     * Get maximum media socket count.
     *
     * @return int
     */
    public function getMaxMediaSocketCount() : int
    {
        return $this->maxMediaSocketCount;
    }
    /**
     * Set maximum media socket count.
     *
     * @param int $maxMediaSocketCount Maximum media socket count.
     *
     * @return self
     */
    public function setMaxMediaSocketCount(int $maxMediaSocketCount) : self
    {
        $this->maxMediaSocketCount = $maxMediaSocketCount;
        return $this;
    }
    /**
     * Get robin period (seconds).
     *
     * @return int
     */
    public function getRobinPeriod() : int
    {
        return $this->robinPeriod;
    }
    /**
     * Set robin period (seconds).
     *
     * @param int $robinPeriod Robin period (seconds).
     *
     * @return self
     */
    public function setRobinPeriod(int $robinPeriod) : self
    {
        $this->robinPeriod = $robinPeriod;
        return $this;
    }
    /**
     * Get default DC ID.
     *
     * @return int
     */
    public function getDefaultDc() : int
    {
        return $this->defaultDc;
    }
    /**
     * Get default DC params.
     *
     * @return array
     */
    public function getDefaultDcParams() : array
    {
        return $this->defaultDcParams;
    }
    /**
     * Set default DC ID.
     *
     * @param int $defaultDc Default DC ID.
     *
     * @return self
     */
    public function setDefaultDc(int $defaultDc) : self
    {
        $this->defaultDc = $defaultDc;
        $this->defaultDcParams = ['datacenter' => $defaultDc];
        return $this;
    }
    /**
     * Get proxy identifiers.
     *
     * @return array
     * @psalm-return array<class-string<StreamInterface>, array>
     */
    public function getProxies() : array
    {
        return $this->proxy;
    }
    /**
    * Add proxy identifier to list, one of:.
    *
    * * `\danog\MadelineProto\Stream\MTProtoTransport\ObfuscatedStream::class`
    `\danog\MadelineProto\Stream\Proxy\HttpProxy::class`
    `\danog\MadelineProto\Stream\Proxy\SocksProxy::class`
    *
    * @param class-string<StreamInterface> $proxy Proxy identifier
    * @param array $extra Extra
    *
    * @return self
    */
    public function addProxy(string $proxy, array $extra = []) : self
    {
        if (!isset(\class_implements($proxy)[StreamInterface::class])) {
            throw new Exception("An invalid proxy class was specified!");
        }
        if (!isset($this->proxy[$proxy])) {
            $this->proxy[$proxy] = [];
        }
        $this->proxy[$proxy][] = $extra;
        return $this;
    }
    /**
     * Set proxies.
     *
     * @param array $proxies Proxies
     *
     * @return self
     */
    public function setProxy(array $proxies) : self
    {
        $this->proxy = $proxies;
        return $this;
    }
    /**
     * Clear proxies.
     *
     * @return self
     */
    public function clearProxies() : self
    {
        $this->proxy = [];
        return $this;
    }
    /**
     * Remove specific proxy pair.
     *
     * @param string $proxy
     * @param array $extra
     *
     * @return self
     */
    public function removeProxy(string $proxy, array $extra) : self
    {
        if (!isset($this->proxy[$proxy])) {
            return $this;
        }
        if (false === ($index = \array_search($extra, $this->proxy[$proxy]))) {
            return $this;
        }
        unset($this->proxy[$proxy][$index]);
        if (empty($this->proxy[$proxy])) {
            unset($this->proxy[$proxy]);
        }
        return $this;
    }
    /**
     * Get whether to use the obfuscated protocol: useful to bypass ISP blocks.
     *
     * @return bool
     */
    public function getObfuscated() : bool
    {
        return $this->obfuscated;
    }
    /**
     * Set whether to use the obfuscated protocol: useful to bypass ISP blocks.
     *
     * @param bool $obfuscated Whether to use the obfuscated protocol.
     *
     * @return self
     */
    public function setObfuscated(bool $obfuscated) : self
    {
        $this->obfuscated = $obfuscated;
        return $this;
    }
    /**
     * Get whether we're in test mode.
     *
     * @return bool
     */
    public function getTestMode() : bool
    {
        return $this->testMode;
    }
    /**
     * Set whether we're in test mode.
     *
     * @param bool $testMode Whether we're in test mode.
     *
     * @return self
     */
    public function setTestMode(bool $testMode) : self
    {
        $this->testMode = $testMode;
        return $this;
    }
    /**
     * Get transport identifier.
     *
     * @return class-string<RawStreamInterface>
     */
    public function getTransport() : string
    {
        return $this->transport;
    }
    /**
    * Sets the transport protocol to use when connecting to telegram.
    Not supported by HTTP and HTTPS protocols, obfuscation must be enabled.
    *
    * * `danog\MadelineProto\Stream\Transport`: Default TCP transport
    `danog\MadelineProto\Stream\WsTransport`: Plain websocket transport
    `danog\MadelineProto\Stream\WssTransport`: TLS websocket transport
    *
    * @param class-string<RawStreamInterface> $transport Transport identifier.
    *
    * @return self
    */
    public function setTransport(string $transport) : self
    {
        if (!isset(\class_implements($transport)[RawStreamInterface::class])) {
            throw new Exception("An invalid transport was specified!");
        }
        $this->transport = $transport;
        return $this;
    }
    /**
     * Get whether to retry connection.
     *
     * @return bool
     */
    public function getRetry() : bool
    {
        return $this->retry;
    }
    /**
     * Set whether to retry connection.
     *
     * @param bool $retry Whether to retry connection.
     *
     * @return self
     */
    public function setRetry(bool $retry) : self
    {
        $this->retry = $retry;
        return $this;
    }
    /**
     * Get connection timeout.
     *
     * @return int
     */
    public function getTimeout() : int
    {
        return $this->timeout;
    }
    /**
     * Set connection timeout.
     *
     * @param int $timeout Connection timeout.
     *
     * @return self
     */
    public function setTimeout(int $timeout) : self
    {
        $this->timeout = $timeout;
        return $this;
    }
    /**
     * Get ping interval.
     *
     * @return int
     */
    public function getPingInterval() : int
    {
        return $this->pingInterval;
    }
    /**
     * Set ping interval.
     *
     * @param int $pingInterval Ping interval
     *
     * @return self
     */
    public function setPingInterval(int $pingInterval) : self
    {
        $this->pingInterval = $pingInterval;
        return $this;
    }
    /**
     * Get whether to use DNS over HTTPS.
     *
     * @return bool
     */
    public function getUseDoH() : bool
    {
        return $this->useDoH;
    }
    /**
     * Set whether to use DNS over HTTPS.
     *
     * @param bool $useDoH Whether to use DNS over HTTPS
     *
     * @return self
     */
    public function setUseDoH(bool $useDoH) : self
    {
        $this->useDoH = $useDoH;
        return $this;
    }
    /**
     * Get bind on specific address and port.
     *
     * @return ?string
     */
    public function getBindTo() : ?string
    {
        return $this->bindTo;
    }
    /**
     * Set bind on specific address and port.
     *
     * @param ?string $bindTo Bind on specific address and port.
     *
     * @return self
     */
    public function setBindTo(?string $bindTo) : self
    {
        $this->bindTo = $bindTo;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * Web and CLI template settings for login.
 */
class Templates extends SettingsAbstract
{
    /**
     * Web template used for querying app information.
     */
    protected string $htmlTemplate = '<!DOCTYPE html><html><head><title>MadelineProto</title></head><body><h1>MadelineProto</h1><p>%s</p><form method="POST">%s<button type="submit"/>%s</button></form></body></html>';
    /**
     * Get web template used for querying app information.
     *
     * @return string
     */
    public function getHtmlTemplate() : string
    {
        return $this->htmlTemplate;
    }
    /**
     * Set web template used for querying app information.
     *
     * @param string $htmlTemplate Web template used for querying app information.
     *
     * @return self
     */
    public function setHtmlTemplate(string $htmlTemplate) : self
    {
        $this->htmlTemplate = $htmlTemplate;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * Peer database settings.
 */
class Peer extends SettingsAbstract
{
    /**
     * Cache time for full peer information (seconds).
     */
    protected int $fullInfoCacheTime = 60 * 60;
    /**
     * Should madeline fetch the full member list of every group it meets?
     */
    protected bool $fullFetch = false;
    /**
     * Whether to cache all peers on startup for userbots.
     */
    protected bool $cacheAllPeersOnStartup = false;
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        foreach (self::toCamel(['full_info_cache_time', 'full_fetch', 'cache_all_peers_on_startup']) as $object => $array) {
            if (isset($settings['peer'][$array])) {
                $this->{$object}($settings['peer'][$array]);
            }
        }
    }
    /**
     * Get cache time for full peer information (seconds).
     *
     * @return int
     */
    public function getFullInfoCacheTime() : int
    {
        return $this->fullInfoCacheTime;
    }
    /**
     * Set cache time for full peer information (seconds).
     *
     * @param int $fullInfoCacheTime Cache time for full peer information (seconds).
     *
     * @return self
     */
    public function setFullInfoCacheTime(int $fullInfoCacheTime) : self
    {
        $this->fullInfoCacheTime = $fullInfoCacheTime;
        return $this;
    }
    /**
     * Get should madeline fetch the full member list of every group it meets?
     *
     * @return bool
     */
    public function getFullFetch() : bool
    {
        return $this->fullFetch;
    }
    /**
     * Set should madeline fetch the full member list of every group it meets?
     *
     * @param bool $fullFetch Should madeline fetch the full member list of every group it meets?
     *
     * @return self
     */
    public function setFullFetch(bool $fullFetch) : self
    {
        $this->fullFetch = $fullFetch;
        return $this;
    }
    /**
     * Get whether to cache all peers on startup for userbots.
     *
     * @return bool
     */
    public function getCacheAllPeersOnStartup() : bool
    {
        return $this->cacheAllPeersOnStartup;
    }
    /**
     * Set whether to cache all peers on startup for userbots.
     *
     * @param bool $cacheAllPeersOnStartup Whether to cache all peers on startup for userbots.
     *
     * @return self
     */
    public function setCacheAllPeersOnStartup(bool $cacheAllPeersOnStartup) : self
    {
        $this->cacheAllPeersOnStartup = $cacheAllPeersOnStartup;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings\Database;

use danog\MadelineProto\Settings\Database;
/**
 * Generic db backend settings.
 */
abstract class SqlAbstract extends DatabaseAbstract
{
    /**
     * Database name.
     */
    protected string $database = 'MadelineProto';
    /**
     * Username.
     */
    protected string $username = 'root';
    /**
     * Maximum connection limit.
     */
    protected int $maxConnections = 100;
    /**
     * Idle timeout.
     */
    protected int $idleTimeout = 60;
    /**
     * Database URI.
     */
    protected string $uri = 'tcp://127.0.0.1';
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        foreach (self::toCamel(['max_connections', 'idle_timeout']) as $object => $array) {
            if (isset($settings[$array])) {
                $this->{$object}($settings[$array]);
            }
        }
        if (isset($settings['user'])) {
            $this->setUsername($settings['user']);
        }
        parent::mergeArray($settings);
    }
    /**
     * Get maximum connection limit.
     *
     * @return int
     */
    public function getMaxConnections() : int
    {
        return $this->maxConnections;
    }
    /**
     * Set maximum connection limit.
     *
     * @param int $maxConnections Maximum connection limit.
     *
     * @return self
     */
    public function setMaxConnections(int $maxConnections) : self
    {
        $this->maxConnections = $maxConnections;
        return $this;
    }
    /**
     * Get idle timeout.
     *
     * @return int
     */
    public function getIdleTimeout() : int
    {
        return $this->idleTimeout;
    }
    /**
     * Set idle timeout.
     *
     * @param int $idleTimeout Idle timeout.
     *
     * @return self
     */
    public function setIdleTimeout(int $idleTimeout) : self
    {
        $this->idleTimeout = $idleTimeout;
        return $this;
    }
    /**
     * Get database name.
     *
     * @return string
     */
    public function getDatabase() : string
    {
        return $this->database;
    }
    /**
     * Set database name.
     *
     * @param string $database Database name.
     *
     * @return self
     */
    public function setDatabase($database) : self
    {
        $this->database = $database;
        return $this;
    }
    /**
     * Get username.
     *
     * @return string
     */
    public function getUsername() : string
    {
        return $this->username;
    }
    /**
     * Set username.
     *
     * @param string $username Username.
     *
     * @return self
     */
    public function setUsername(string $username) : self
    {
        $this->username = $username;
        return $this;
    }
    /**
     * Get database URI.
     *
     * @return string
     */
    public function getUri() : string
    {
        return $this->uri;
    }
    /**
     * Set database URI.
     *
     * @param string $uri Database URI.
     *
     * @return self
     */
    public function setUri(string $uri) : self
    {
        $this->uri = $uri;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings\Database;

/**
 * Redis backend settings.
 */
class Redis extends DatabaseAbstract
{
    /**
     * Database number.
     */
    protected int $database = 0;
    /**
     * Database URI.
     */
    protected string $uri = 'redis://127.0.0.1';
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        $settings = $settings['db']['redis'] ?? [];
        if (isset($settings['host'])) {
            $this->setUri($settings['host'] . (isset($settings['port']) ? ':' . $settings['port'] : ''));
        }
        parent::mergeArray($settings);
    }
    /**
     * Get database number.
     *
     * @return int
     */
    public function getDatabase() : int
    {
        return $this->database;
    }
    /**
     * Set database number.
     *
     * @param int $database Database number.
     *
     * @return self
     */
    public function setDatabase($database) : self
    {
        $this->database = $database;
        return $this;
    }
    /**
     * Get database URI.
     *
     * @return string
     */
    public function getUri() : string
    {
        return $this->uri;
    }
    /**
     * Set database URI.
     *
     * @param string $uri Database URI.
     *
     * @return self
     */
    public function setUri(string $uri) : self
    {
        $this->uri = $uri;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings\Database;

use danog\MadelineProto\Settings\DatabaseAbstract;
/**
 * Memory backend settings.
 */
class Memory extends DatabaseAbstract
{
    /**
     * Whether to cleanup the memory before serializing.
     */
    protected bool $cleanup = false;
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        if (isset($settings['serialization']['cleanup_before_serialization'])) {
            $this->setCleanup($settings['serialization']['cleanup_before_serialization']);
        }
    }
    /**
     * Get whether to cleanup the memory before serializing.
     *
     * @return bool
     */
    public function getCleanup() : bool
    {
        return $this->cleanup;
    }
    /**
     * Set whether to cleanup the memory before serializing.
     *
     * @param bool $cleanup Whether to cleanup the memory before serializing.
     *
     * @return self
     */
    public function setCleanup(bool $cleanup) : self
    {
        $this->cleanup = $cleanup;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings\Database;

/**
 * MySQL backend settings.
 *
 * MariaDb 10.2+ or Mysql 5.6+ required.
 */
class Mysql extends SqlAbstract
{
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        $settings = $settings['db']['mysql'] ?? [];
        if (isset($settings['host'])) {
            $this->setUri("tcp://" . $settings['host'] . (isset($settings['port']) ? ':' . $settings['port'] : ''));
        }
        parent::mergeArray($settings);
    }
}<?php

namespace danog\MadelineProto\Settings\Database;

/**
 * Postgres backend settings.
 */
class Postgres extends SqlAbstract
{
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        $settings = $settings['db']['postgres'] ?? [];
        if (isset($settings['host'])) {
            $this->setUri("tcp://" . $settings['host'] . (isset($settings['port']) ? ':' . $settings['port'] : ''));
        }
        parent::mergeArray($settings);
    }
}<?php

namespace danog\MadelineProto\Settings\Database;

use danog\MadelineProto\Settings\DatabaseAbstract as SettingsDatabaseAbstract;
/**
 * Base class for database backends.
 */
abstract class DatabaseAbstract extends SettingsDatabaseAbstract
{
    /**
     * For how long to keep records in memory after last read, for cached backends.
     */
    protected int $cacheTtl = 5 * 60;
    /**
     * Database password.
     */
    protected string $password = '';
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        foreach (self::toCamel(['database', 'password', 'cache_ttl']) as $object => $array) {
            if (isset($settings[$array])) {
                $this->{$object}($settings[$array]);
            }
        }
    }
    /**
     * Get DB key.
     *
     * @return string
     */
    public function getKey() : string
    {
        $uri = \parse_url($this->getUri());
        $host = $uri['host'] ?? '';
        $port = $uri['port'] ?? '';
        return "{$host}:{$port}:" . $this->getDatabase();
    }
    /**
     * Get for how long to keep records in memory after last read, for cached backends.
     *
     * @return int
     */
    public function getCacheTtl() : int
    {
        return $this->cacheTtl;
    }
    /**
    * Set for how long to keep records in memory after last read, for cached backends.
    *
    * The cache TTL identifier can be a string like '+5 minutes'.
    When data is retrieved from a database it is stored in memory.
    This helps to reduce latency, improve speed and reduce mysql/postgres/redis load.
    Data will be removed from the cache if last access was more than this amount of time.
    Clean up is done once per minute.
    *
    * @param (int | string) $cacheTtl For how long to keep records in memory after last read, for cached backends.
    *
    * @return self
    */
    public function setCacheTtl($cacheTtl) : self
    {
        $this->cacheTtl = \is_int($cacheTtl) ? $cacheTtl : \Phabel\Target\Php80\Polyfill::strtotime($cacheTtl) - \time();
        return $this;
    }
    /**
     * Get password.
     *
     * @return string
     */
    public function getPassword() : string
    {
        return $this->password;
    }
    /**
     * Set password.
     *
     * @param string $password Password.
     *
     * @return self
     */
    public function setPassword(string $password) : self
    {
        $this->password = $password;
        return $this;
    }
    /**
     * Get database name/ID.
     *
     * @return (string | int)
     */
    public abstract function getDatabase();
    /**
     * Get database URI.
     *
     * @return string
     */
    public abstract function getUri() : string;
    /**
     * Set database name/ID.
     *
     * @param (int | string) $database
     * @return self
     */
    public abstract function setDatabase($database) : self;
    /**
     * Set database URI.
     *
     * @param string $uri
     * @return self
     */
    public abstract function setUri(string $uri) : self;
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * File management settings.
 */
class Files extends SettingsAbstract
{
    /**
     * Allow automatic upload of files from file paths present in constructors?
     */
    protected bool $allowAutomaticUpload = true;
    /**
     * Upload parallel chunk count.
     */
    protected int $uploadParallelChunks = 20;
    /**
     * Download parallel chunk count.
     */
    protected int $downloadParallelChunks = 20;
    /**
     * Whether to report undownloadable media to TSF.
     */
    protected bool $reportBrokenMedia = true;
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        if (isset($settings['upload']['allow_automatic_upload'])) {
            $this->setAllowAutomaticUpload($settings['upload']['allow_automatic_upload']);
        }
        if (isset($settings['download']['report_broken_media'])) {
            $this->setReportBrokenMedia($settings['download']['report_broken_media']);
        }
        if (isset($settings['upload']['parallel_chunks'])) {
            $this->setUploadParallelChunks($settings['upload']['parallel_chunks']);
        }
        if (isset($settings['download']['parallel_chunks'])) {
            $this->setDownloadParallelChunks($settings['download']['parallel_chunks']);
        }
    }
    /**
     * Get allow automatic upload of files from file paths present in constructors?
     *
     * @return bool
     */
    public function getAllowAutomaticUpload() : bool
    {
        return $this->allowAutomaticUpload;
    }
    /**
     * Set allow automatic upload of files from file paths present in constructors?
     *
     * @param bool $allowAutomaticUpload Allow automatic upload of files from file paths present in constructors?
     *
     * @return self
     */
    public function setAllowAutomaticUpload(bool $allowAutomaticUpload) : self
    {
        $this->allowAutomaticUpload = $allowAutomaticUpload;
        return $this;
    }
    /**
     * Get upload parallel chunk count.
     *
     * @return int
     */
    public function getUploadParallelChunks() : int
    {
        return $this->uploadParallelChunks;
    }
    /**
     * Set upload parallel chunk count.
     *
     * @param int $uploadParallelChunks Upload parallel chunk count
     *
     * @return self
     */
    public function setUploadParallelChunks(int $uploadParallelChunks) : self
    {
        $this->uploadParallelChunks = $uploadParallelChunks;
        return $this;
    }
    /**
     * Get download parallel chunk count.
     *
     * @return int
     */
    public function getDownloadParallelChunks() : int
    {
        return $this->downloadParallelChunks;
    }
    /**
     * Set download parallel chunk count.
     *
     * @param int $downloadParallelChunks Download parallel chunk count
     *
     * @return self
     */
    public function setDownloadParallelChunks(int $downloadParallelChunks) : self
    {
        $this->downloadParallelChunks = $downloadParallelChunks;
        return $this;
    }
    /**
     * Get whether to report undownloadable media to TSF.
     *
     * @return bool
     */
    public function getReportBrokenMedia() : bool
    {
        return $this->reportBrokenMedia;
    }
    /**
     * Set whether to report undownloadable media to TSF.
     *
     * @param bool $reportBrokenMedia Whether to report undownloadable media to TSF
     *
     * @return self
     */
    public function setReportBrokenMedia(bool $reportBrokenMedia) : self
    {
        $this->reportBrokenMedia = $reportBrokenMedia;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * Base class for storage backends.
 */
abstract class DatabaseAbstract extends SettingsAbstract
{
    /**
     * Whether to enable the file reference database. If disabled, will break file downloads.
     */
    protected bool $enableFileReferenceDb = true;
    /**
     * Whether to enable the min database. If disabled, will break sendMessage (and other methods) in certain conditions.
     */
    protected bool $enableMinDb = true;
    /**
     * Whether to enable the username database. If disabled, will break sendMessage (and other methods) with usernames.
     */
    protected bool $enableUsernameDb = true;
    /**
     * Whether to enable the full peer info database. If disabled, will break getFullInfo.
     */
    protected bool $enableFullPeerDb = true;
    /**
     * Whether to enable the peer info database. If disabled, will break getInfo.
     */
    protected bool $enablePeerInfoDb = true;
    /**
     * Get whether to enable the file reference database. If disabled, will break file downloads.
     *
     * @return bool
     */
    public function getEnableFileReferenceDb() : bool
    {
        return $this->enableFileReferenceDb;
    }
    /**
     * Set whether to enable the file reference database. If disabled, will break file downloads.
     *
     * @param bool $enableFileReferenceDb Whether to enable the file reference database. If disabled, will break file downloads.
     *
     * @return self
     */
    public function setEnableFileReferenceDb(bool $enableFileReferenceDb) : self
    {
        $this->enableFileReferenceDb = $enableFileReferenceDb;
        return $this;
    }
    /**
     * Get whether to enable the min database. If disabled, will break sendMessage (and other methods) in certain conditions.
     *
     * @return bool
     */
    public function getEnableMinDb() : bool
    {
        return $this->enableMinDb;
    }
    /**
     * Set whether to enable the min database. If disabled, will break sendMessage (and other methods) in certain conditions.
     *
     * @param bool $enableMinDb Whether to enable the min database. If disabled, will break sendMessage (and other methods) in certain conditions.
     *
     * @return self
     */
    public function setEnableMinDb(bool $enableMinDb) : self
    {
        $this->enableMinDb = $enableMinDb;
        return $this;
    }
    /**
     * Get whether to enable the username database. If disabled, will break sendMessage (and other methods) with usernames.
     *
     * @return bool
     */
    public function getEnableUsernameDb() : bool
    {
        return $this->enableUsernameDb;
    }
    /**
     * Set whether to enable the username database. If disabled, will break sendMessage (and other methods) with usernames.
     *
     * @param bool $enableUsernameDb Whether to enable the username database. If disabled, will break sendMessage (and other methods) with usernames.
     *
     * @return self
     */
    public function setEnableUsernameDb(bool $enableUsernameDb) : self
    {
        $this->enableUsernameDb = $enableUsernameDb;
        return $this;
    }
    /**
     * Get whether to enable the full peer info database. If disabled, will break getFullInfo.
     *
     * @return bool
     */
    public function getEnableFullPeerDb() : bool
    {
        return $this->enableFullPeerDb;
    }
    /**
     * Set whether to enable the full peer info database. If disabled, will break getFullInfo.
     *
     * @param bool $enableFullPeerDb Whether to enable the full peer info database. If disabled, will break getFullInfo.
     *
     * @return self
     */
    public function setEnableFullPeerDb(bool $enableFullPeerDb) : self
    {
        $this->enableFullPeerDb = $enableFullPeerDb;
        return $this;
    }
    /**
     * Get whether to enable the peer info database. If disabled, will break getInfo.
     *
     * @return bool
     */
    public function getEnablePeerInfoDb() : bool
    {
        return $this->enablePeerInfoDb;
    }
    /**
     * Set whether to enable the peer info database. If disabled, will break getInfo.
     *
     * @param bool $enablePeerInfoDb Whether to enable the peer info database. If disabled, will break getInfo.
     *
     * @return self
     */
    public function setEnablePeerInfoDb(bool $enablePeerInfoDb) : self
    {
        $this->enablePeerInfoDb = $enablePeerInfoDb;
        return $this;
    }
}<?php

namespace danog\MadelineProto\Settings;

use danog\MadelineProto\SettingsAbstract;
/**
 * TL schema settings.
 */
class TLSchema extends SettingsAbstract
{
    /**
     * TL layer version.
     */
    protected int $layer = 135;
    /**
     * API schema path.
     */
    protected string $APISchema = __DIR__ . '/../TL_telegram_v135.tl';
    /**
     * MTProto schema path.
     */
    protected string $MTProtoSchema = __DIR__ . '/../TL_mtproto_v1.tl';
    /**
     * Secret schema path.
     */
    protected string $secretSchema = __DIR__ . '/../TL_secret.tl';
    /**
     * @internal Other schemas
     */
    protected array $other = [];
    /**
     * Whether the scheme was upgraded.
     */
    private bool $wasUpgraded = true;
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
        $settings = $settings['tl_schema'] ?? [];
        if (isset($settings['layer'])) {
            $this->setLayer($settings['layer']);
        }
        $src = $settings['src'] ?? $settings;
        if (isset($src['mtproto'])) {
            $this->setMTProtoSchema($src['mtproto']);
        }
        if (isset($src['telegram'])) {
            $this->setAPISchema($src['telegram']);
        }
        if (isset($src['secret'])) {
            $this->setSecretSchema($src['secret']);
        }
    }
    /**
     * Upgrade scheme autonomously.
     */
    public function __wakeup()
    {
        // Scheme was upgraded or path has changed
        if (!\file_exists($this->APISchema)) {
            $new = new self();
            $this->setAPISchema($new->getAPISchema());
            $this->setMTProtoSchema($new->getMTProtoSchema());
            $this->setSecretSchema($new->getSecretSchema());
            $this->setLayer($this->getLayer());
            $this->wasUpgraded = true;
        }
    }
    /**
     * Returns whether the TL parser should re-parse the TL schemes.
     *
     * @return boolean
     */
    public function needsUpgrade() : bool
    {
        return $this->wasUpgraded;
    }
    /**
     * Signal that scheme was re-parsed.
     *
     * @return void
     */
    public function upgrade() : void
    {
        $this->wasUpgraded = false;
    }
    /**
     * Get TL layer version.
     *
     * @return int
     */
    public function getLayer() : int
    {
        return $this->layer;
    }
    /**
     * Set TL layer version.
     *
     * @param int $layer TL layer version.
     *
     * @return self
     */
    public function setLayer(int $layer) : self
    {
        $this->layer = $layer;
        return $this;
    }
    /**
     * Get MTProto schema path.
     *
     * @return string
     */
    public function getMTProtoSchema() : string
    {
        return $this->MTProtoSchema;
    }
    /**
     * Set MTProto schema path.
     *
     * @param string $MTProtoSchema MTProto schema path.
     *
     * @return self
     */
    public function setMTProtoSchema(string $MTProtoSchema) : self
    {
        $this->MTProtoSchema = $MTProtoSchema;
        return $this;
    }
    /**
     * Get API schema path.
     *
     * @return string
     */
    public function getAPISchema() : string
    {
        return $this->APISchema;
    }
    /**
     * Set API schema path.
     *
     * @param string $APISchema API schema path.
     *
     * @return self
     */
    public function setAPISchema(string $APISchema) : self
    {
        $this->APISchema = $APISchema;
        return $this;
    }
    /**
     * Get secret schema path.
     *
     * @return string
     */
    public function getSecretSchema() : string
    {
        return $this->secretSchema;
    }
    /**
     * Set secret schema path.
     *
     * @param string $secretSchema Secret schema path.
     *
     * @return self
     */
    public function setSecretSchema(string $secretSchema) : self
    {
        $this->secretSchema = $secretSchema;
        return $this;
    }
    /**
     * Get the value of other.
     *
     * @return array
     */
    public function getOther() : array
    {
        return $this->other;
    }
    /**
     * Set the value of other.
     *
     * @param array $other
     *
     * @return self
     */
    public function setOther(array $other) : self
    {
        $this->other = $other;
        return $this;
    }
}<?php

/**
 * Magic module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Deferred;
use Amp\Loop;
use Amp\Loop\Driver;
use danog\MadelineProto\TL\Conversion\Extension;
use ReflectionClass;
use function Amp\ByteStream\getStdin;
use function Amp\File\read;
use function Amp\Log\hasColorSupport;
use function Amp\Promise\wait;
class Magic
{
    const ZERO_CHANNEL_ID = -1000000000000;
    /**
     * Static storage.
     *
     * @var array
     */
    public static $storage = [];
    /**
     * Whether this system is bigendian.
     *
     * @var boolean
     */
    public static $BIG_ENDIAN = false;
    /**
     * Whether this is a TTY console.
     *
     * @var boolean
     */
    public static $isatty = false;
    /**
     * Whether we're in a fork.
     *
     * @var boolean
     */
    public static $isFork = false;
    /**
     * Whether this is an IPC worker.
     */
    public static bool $isIpcWorker = false;
    /**
     * Whether we can get our PID.
     *
     * @var boolean
     */
    public static $can_getmypid = true;
    /**
     * Whether we can amphp/parallel.
     *
     * @var boolean
     */
    public static $can_parallel = false;
    /**
     * Whether we can get our CWD.
     *
     * @var boolean
     */
    public static $can_getcwd = false;
    /**
     * Whether we've processed forks.
     *
     * @var boolean
     */
    public static $processed_fork = false;
    /**
     * Whether we can use ipv6.
     *
     * @var bool
     */
    public static $ipv6 = false;
    /**
     * Our PID.
     *
     * @var int
     */
    public static $pid;
    /**
     * Whether we've inited all light constants.
     *
     * @var boolean
     */
    private static $initedLight = false;
    /**
     * Whether we've inited all static constants.
     *
     * @var boolean
     */
    private static $inited = false;
    /**
     * Whether we've inited the ipv6 property.
     *
     * @var boolean
     */
    private static $initedIpv6 = false;
    /**
     * Bigint zero.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    public static $zero;
    /**
     * Bigint one.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    public static $one;
    /**
     * Bigint two.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    public static $two;
    /**
     * Bigint 2^1984.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    public static $twoe1984;
    /**
     * Bigint 2^2047.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    public static $twoe2047;
    /**
     * Bigint 2^2048.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    public static $twoe2048;
    /**
     * Decoded UTF8 emojis for call fingerprint.
     *
     * @var array
     */
    public static $emojis;
    /**
     * MadelineProto revision.
     *
     * @var string
     */
    public static $revision;
    /**
     * MadelineProto version (clean).
     *
     * @var string
     */
    public static $version;
    /**
     * Latest MadelineProto version.
     *
     * @var string
     */
    public static $version_latest;
    /**
     * Our CWD.
     *
     * @var string
     */
    public static $cwd;
    /**
     * Caller script CWD.
     *
     * @var string
     */
    public static $script_cwd;
    /**
     * Whether we're running on altervista.
     *
     * @var boolean
     */
    public static $altervista = false;
    /**
     * Wether we're running on 000webhost (yuck).
     *
     * @var boolean
     */
    public static $zerowebhost = false;
    /**
     * Whether a signal was sent to the processand the system must shut down.
     *
     * @var boolean
     */
    public static $signaled = false;
    /**
     * Whether to suspend certain stdout log printing, when reading input.
     *
     * @var ?Deferred
     */
    public static $suspendPeriodicLogging;
    /**
     * All mime types.
     *
     * @var array<string, string>
     */
    public static $allMimes = [];
    /**
     * Whether the openssl extension is loaded.
     *
     * @var boolean
     */
    public static bool $hasOpenssl = false;
    /**
     * Encoded emojis.
     *
     * @var string
     */
    const JSON_EMOJIS = '["\\ud83d\\ude09","\\ud83d\\ude0d","\\ud83d\\ude1b","\\ud83d\\ude2d","\\ud83d\\ude31","\\ud83d\\ude21","\\ud83d\\ude0e","\\ud83d\\ude34","\\ud83d\\ude35","\\ud83d\\ude08","\\ud83d\\ude2c","\\ud83d\\ude07","\\ud83d\\ude0f","\\ud83d\\udc6e","\\ud83d\\udc77","\\ud83d\\udc82","\\ud83d\\udc76","\\ud83d\\udc68","\\ud83d\\udc69","\\ud83d\\udc74","\\ud83d\\udc75","\\ud83d\\ude3b","\\ud83d\\ude3d","\\ud83d\\ude40","\\ud83d\\udc7a","\\ud83d\\ude48","\\ud83d\\ude49","\\ud83d\\ude4a","\\ud83d\\udc80","\\ud83d\\udc7d","\\ud83d\\udca9","\\ud83d\\udd25","\\ud83d\\udca5","\\ud83d\\udca4","\\ud83d\\udc42","\\ud83d\\udc40","\\ud83d\\udc43","\\ud83d\\udc45","\\ud83d\\udc44","\\ud83d\\udc4d","\\ud83d\\udc4e","\\ud83d\\udc4c","\\ud83d\\udc4a","\\u270c","\\u270b","\\ud83d\\udc50","\\ud83d\\udc46","\\ud83d\\udc47","\\ud83d\\udc49","\\ud83d\\udc48","\\ud83d\\ude4f","\\ud83d\\udc4f","\\ud83d\\udcaa","\\ud83d\\udeb6","\\ud83c\\udfc3","\\ud83d\\udc83","\\ud83d\\udc6b","\\ud83d\\udc6a","\\ud83d\\udc6c","\\ud83d\\udc6d","\\ud83d\\udc85","\\ud83c\\udfa9","\\ud83d\\udc51","\\ud83d\\udc52","\\ud83d\\udc5f","\\ud83d\\udc5e","\\ud83d\\udc60","\\ud83d\\udc55","\\ud83d\\udc57","\\ud83d\\udc56","\\ud83d\\udc59","\\ud83d\\udc5c","\\ud83d\\udc53","\\ud83c\\udf80","\\ud83d\\udc84","\\ud83d\\udc9b","\\ud83d\\udc99","\\ud83d\\udc9c","\\ud83d\\udc9a","\\ud83d\\udc8d","\\ud83d\\udc8e","\\ud83d\\udc36","\\ud83d\\udc3a","\\ud83d\\udc31","\\ud83d\\udc2d","\\ud83d\\udc39","\\ud83d\\udc30","\\ud83d\\udc38","\\ud83d\\udc2f","\\ud83d\\udc28","\\ud83d\\udc3b","\\ud83d\\udc37","\\ud83d\\udc2e","\\ud83d\\udc17","\\ud83d\\udc34","\\ud83d\\udc11","\\ud83d\\udc18","\\ud83d\\udc3c","\\ud83d\\udc27","\\ud83d\\udc25","\\ud83d\\udc14","\\ud83d\\udc0d","\\ud83d\\udc22","\\ud83d\\udc1b","\\ud83d\\udc1d","\\ud83d\\udc1c","\\ud83d\\udc1e","\\ud83d\\udc0c","\\ud83d\\udc19","\\ud83d\\udc1a","\\ud83d\\udc1f","\\ud83d\\udc2c","\\ud83d\\udc0b","\\ud83d\\udc10","\\ud83d\\udc0a","\\ud83d\\udc2b","\\ud83c\\udf40","\\ud83c\\udf39","\\ud83c\\udf3b","\\ud83c\\udf41","\\ud83c\\udf3e","\\ud83c\\udf44","\\ud83c\\udf35","\\ud83c\\udf34","\\ud83c\\udf33","\\ud83c\\udf1e","\\ud83c\\udf1a","\\ud83c\\udf19","\\ud83c\\udf0e","\\ud83c\\udf0b","\\u26a1","\\u2614","\\u2744","\\u26c4","\\ud83c\\udf00","\\ud83c\\udf08","\\ud83c\\udf0a","\\ud83c\\udf93","\\ud83c\\udf86","\\ud83c\\udf83","\\ud83d\\udc7b","\\ud83c\\udf85","\\ud83c\\udf84","\\ud83c\\udf81","\\ud83c\\udf88","\\ud83d\\udd2e","\\ud83c\\udfa5","\\ud83d\\udcf7","\\ud83d\\udcbf","\\ud83d\\udcbb","\\u260e","\\ud83d\\udce1","\\ud83d\\udcfa","\\ud83d\\udcfb","\\ud83d\\udd09","\\ud83d\\udd14","\\u23f3","\\u23f0","\\u231a","\\ud83d\\udd12","\\ud83d\\udd11","\\ud83d\\udd0e","\\ud83d\\udca1","\\ud83d\\udd26","\\ud83d\\udd0c","\\ud83d\\udd0b","\\ud83d\\udebf","\\ud83d\\udebd","\\ud83d\\udd27","\\ud83d\\udd28","\\ud83d\\udeaa","\\ud83d\\udeac","\\ud83d\\udca3","\\ud83d\\udd2b","\\ud83d\\udd2a","\\ud83d\\udc8a","\\ud83d\\udc89","\\ud83d\\udcb0","\\ud83d\\udcb5","\\ud83d\\udcb3","\\u2709","\\ud83d\\udceb","\\ud83d\\udce6","\\ud83d\\udcc5","\\ud83d\\udcc1","\\u2702","\\ud83d\\udccc","\\ud83d\\udcce","\\u2712","\\u270f","\\ud83d\\udcd0","\\ud83d\\udcda","\\ud83d\\udd2c","\\ud83d\\udd2d","\\ud83c\\udfa8","\\ud83c\\udfac","\\ud83c\\udfa4","\\ud83c\\udfa7","\\ud83c\\udfb5","\\ud83c\\udfb9","\\ud83c\\udfbb","\\ud83c\\udfba","\\ud83c\\udfb8","\\ud83d\\udc7e","\\ud83c\\udfae","\\ud83c\\udccf","\\ud83c\\udfb2","\\ud83c\\udfaf","\\ud83c\\udfc8","\\ud83c\\udfc0","\\u26bd","\\u26be","\\ud83c\\udfbe","\\ud83c\\udfb1","\\ud83c\\udfc9","\\ud83c\\udfb3","\\ud83c\\udfc1","\\ud83c\\udfc7","\\ud83c\\udfc6","\\ud83c\\udfca","\\ud83c\\udfc4","\\u2615","\\ud83c\\udf7c","\\ud83c\\udf7a","\\ud83c\\udf77","\\ud83c\\udf74","\\ud83c\\udf55","\\ud83c\\udf54","\\ud83c\\udf5f","\\ud83c\\udf57","\\ud83c\\udf71","\\ud83c\\udf5a","\\ud83c\\udf5c","\\ud83c\\udf61","\\ud83c\\udf73","\\ud83c\\udf5e","\\ud83c\\udf69","\\ud83c\\udf66","\\ud83c\\udf82","\\ud83c\\udf70","\\ud83c\\udf6a","\\ud83c\\udf6b","\\ud83c\\udf6d","\\ud83c\\udf6f","\\ud83c\\udf4e","\\ud83c\\udf4f","\\ud83c\\udf4a","\\ud83c\\udf4b","\\ud83c\\udf52","\\ud83c\\udf47","\\ud83c\\udf49","\\ud83c\\udf53","\\ud83c\\udf51","\\ud83c\\udf4c","\\ud83c\\udf50","\\ud83c\\udf4d","\\ud83c\\udf46","\\ud83c\\udf45","\\ud83c\\udf3d","\\ud83c\\udfe1","\\ud83c\\udfe5","\\ud83c\\udfe6","\\u26ea","\\ud83c\\udff0","\\u26fa","\\ud83c\\udfed","\\ud83d\\uddfb","\\ud83d\\uddfd","\\ud83c\\udfa0","\\ud83c\\udfa1","\\u26f2","\\ud83c\\udfa2","\\ud83d\\udea2","\\ud83d\\udea4","\\u2693","\\ud83d\\ude80","\\u2708","\\ud83d\\ude81","\\ud83d\\ude82","\\ud83d\\ude8b","\\ud83d\\ude8e","\\ud83d\\ude8c","\\ud83d\\ude99","\\ud83d\\ude97","\\ud83d\\ude95","\\ud83d\\ude9b","\\ud83d\\udea8","\\ud83d\\ude94","\\ud83d\\ude92","\\ud83d\\ude91","\\ud83d\\udeb2","\\ud83d\\udea0","\\ud83d\\ude9c","\\ud83d\\udea6","\\u26a0","\\ud83d\\udea7","\\u26fd","\\ud83c\\udfb0","\\ud83d\\uddff","\\ud83c\\udfaa","\\ud83c\\udfad","\\ud83c\\uddef\\ud83c\\uddf5","\\ud83c\\uddf0\\ud83c\\uddf7","\\ud83c\\udde9\\ud83c\\uddea","\\ud83c\\udde8\\ud83c\\uddf3","\\ud83c\\uddfa\\ud83c\\uddf8","\\ud83c\\uddeb\\ud83c\\uddf7","\\ud83c\\uddea\\ud83c\\uddf8","\\ud83c\\uddee\\ud83c\\uddf9","\\ud83c\\uddf7\\ud83c\\uddfa","\\ud83c\\uddec\\ud83c\\udde7","1\\u20e3","2\\u20e3","3\\u20e3","4\\u20e3","5\\u20e3","6\\u20e3","7\\u20e3","8\\u20e3","9\\u20e3","0\\u20e3","\\ud83d\\udd1f","\\u2757","\\u2753","\\u2665","\\u2666","\\ud83d\\udcaf","\\ud83d\\udd17","\\ud83d\\udd31","\\ud83d\\udd34","\\ud83d\\udd35","\\ud83d\\udd36","\\ud83d\\udd37"]';
    /**
     * Initialize magic constants.
     *
     * @param bool $light Use lightweight initialization routine
     *
     * @return void
     */
    public static function start(bool $light = false) : void
    {
        if (self::$inited || self::$initedLight && $light) {
            return;
        }
        if (PHP_INT_SIZE < 8) {
            throw new \danog\MadelineProto\Exception('A 64-bit build of PHP is required to run MadelineProto, PHP 8.0+ recommended.', 0, null, 'MadelineProto', 1);
        }
        if (!self::$initedLight) {
            // Setup error reporting
            \set_error_handler([Exception::class, 'ExceptionErrorHandler']);
            \set_exception_handler([Exception::class, 'ExceptionHandler']);
            self::$isIpcWorker = \defined('MADELINE_WORKER_TYPE') ? \MADELINE_WORKER_TYPE === 'madeline-ipc' : false;
            // Important, obtain root relative to caller script
            $backtrace = \debug_backtrace(0);
            self::$script_cwd = self::$cwd = \dirname(\end($backtrace)['file']);
            if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
                try {
                    \Phabel\Target\Php80\Polyfill::error_reporting(E_ALL);
                    \ini_set('log_errors', 1);
                    \ini_set('error_log', Magic::$script_cwd . DIRECTORY_SEPARATOR . 'MadelineProto.log');
                    \error_log('Enabled PHP logging');
                } catch (\Throwable $e) {
                    //$this->logger->logger('Could not enable PHP logging');
                }
            }
            try {
                \ini_set('memory_limit', -1);
            } catch (\Throwable $e) {
            }
            // Check if we're in a console, for colorful log output
            try {
                self::$isatty = \defined('STDOUT') && hasColorSupport();
            } catch (\Throwable $e) {
            }
            try {
                self::$cwd = \getcwd();
                self::$can_getcwd = true;
            } catch (\Throwable $e) {
            }
            // Define signal handlers
            if (\defined('SIGINT')) {
                //if (function_exists('pcntl_async_signals')) pcntl_async_signals(true);
                try {
                    \pcntl_signal(SIGINT, fn() => null);
                    \pcntl_signal(SIGINT, SIG_DFL);
                    Loop::unreference(Loop::onSignal(SIGINT, static function () {
                        Logger::log('Got sigint', Logger::FATAL_ERROR);
                        Magic::shutdown(self::$isIpcWorker ? 0 : 1);
                    }));
                    Loop::unreference(Loop::onSignal(SIGTERM, static function () {
                        Logger::log('Got sigterm', Logger::FATAL_ERROR);
                        Magic::shutdown(self::$isIpcWorker ? 0 : 1);
                    }));
                } catch (\Throwable $e) {
                }
            }
            self::$altervista = isset($_SERVER['SERVER_ADMIN']) && \strpos($_SERVER['SERVER_ADMIN'], 'altervista.org');
            self::$zerowebhost = isset($_SERVER['SERVER_ADMIN']) && \strpos($_SERVER['SERVER_ADMIN'], '000webhost.io');
            self::$initedLight = true;
            if ($light) {
                if (!\defined('AMP_WORKER')) {
                    \define('AMP_WORKER', true);
                }
                return;
            }
        }
        foreach (['xml', 'fileinfo', 'json', 'mbstring'] as $extension) {
            if (!\extension_loaded($extension)) {
                throw Exception::extension($extension);
            }
        }
        self::$BIG_ENDIAN = \pack('L', 1) === \pack('N', 1);
        if (\class_exists('\\danog\\MadelineProto\\VoIP')) {
            if (!\defined('\\danog\\MadelineProto\\VoIP::PHP_LIBTGVOIP_VERSION') || !\in_array(\danog\MadelineProto\VoIP::PHP_LIBTGVOIP_VERSION, ['1.5.0'])) {
                throw new \danog\MadelineProto\Exception(\hex2bin(\danog\MadelineProto\Lang::$current_lang['v_tgerror']), 0, null, 'MadelineProto', 1);
            }
        }
        self::$hasOpenssl = \extension_loaded('openssl');
        self::$emojis = \json_decode(self::JSON_EMOJIS);
        self::$zero = new \phpseclib3\Math\BigInteger(0);
        self::$one = new \phpseclib3\Math\BigInteger(1);
        self::$two = new \phpseclib3\Math\BigInteger(2);
        self::$twoe1984 = new \phpseclib3\Math\BigInteger('010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 16);
        self::$twoe2047 = new \phpseclib3\Math\BigInteger('80000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 16);
        self::$twoe2048 = new \phpseclib3\Math\BigInteger('0100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', 16);
        self::$can_getmypid = !self::$altervista && !self::$zerowebhost;
        if (\file_exists(__DIR__ . '/../../../.git/refs/heads/master')) {
            self::$version = null;
            try {
                self::$version = @\file_get_contents(__DIR__ . '/../../../.git/refs/heads/master');
            } catch (\Throwable $e) {
            }
        }
        if (self::$version) {
            self::$revision = 'Revision: ' . self::$version;
            self::$version_latest = null;
            try {
                $php = (string) \min(81, (int) (PHP_MAJOR_VERSION . PHP_MINOR_VERSION));
                self::$version_latest = @\file_get_contents("https://phar.madelineproto.xyz/release{$php}");
            } catch (\Throwable $e) {
            }
            if (self::$version_latest !== self::$version) {
                self::$revision .= ' (AN UPDATE IS REQUIRED)';
            }
        }
        self::$can_parallel = false;
        if ((PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') && !(\class_exists(\Phar::class) && \Phar::running())) {
            try {
                $back = \debug_backtrace(0);
                if (!\defined('AMP_WORKER')) {
                    \define('AMP_WORKER', 1);
                }
                $promise = read(\end($back)['file']);
                do {
                    try {
                        if (wait($promise)) {
                            self::$can_parallel = true;
                            break;
                        }
                    } catch (\Throwable $e) {
                        if ($e->getMessage() !== 'Loop stopped without resolving the promise') {
                            throw $e;
                        }
                    }
                } while (true);
            } catch (\Throwable $e) {
            }
        }
        if (!self::$can_parallel && !\defined('AMP_WORKER')) {
            \define('AMP_WORKER', 1);
        }
        try {
            $res = \json_decode(@\file_get_contents('https://rpc.madelineproto.xyz/v3.json'), true);
        } catch (\Throwable $e) {
        }
        if (isset($res, $res['ok']) && $res['ok']) {
            RPCErrorException::$errorMethodMap = $res['result'];
            RPCErrorException::$descriptions += $res['human_result'];
        }
        foreach (Extension::ALL_MIMES as $ext => $mimes) {
            $ext = ".{$ext}";
            foreach ($mimes as $mime) {
                if (!isset(self::$allMimes[$mime])) {
                    self::$allMimes[$mime] = $ext;
                }
            }
        }
        self::$inited = true;
    }
    /**
     * Check if this is a POSIX fork of the main PHP process.
     *
     * @return boolean
     */
    public static function isFork()
    {
        if (self::$isFork) {
            return true;
        }
        if (!self::$can_getmypid) {
            return false;
        }
        try {
            if (self::$pid === null) {
                self::$pid = \getmypid();
            }
            return self::$isFork = self::$pid !== \getmypid();
        } catch (\Throwable $e) {
            return self::$can_getmypid = false;
        }
    }
    /**
     * Get current working directory.
     *
     * @return string
     */
    public static function getcwd() : string
    {
        return self::$can_getcwd ? \getcwd() : self::$cwd;
    }
    /**
     * Shutdown system.
     *
     * @param int $code Exit code
     *
     * @return void
     */
    public static function shutdown(int $code = 0)
    {
        self::$signaled = true;
        if (\defined('STDIN')) {
            getStdin()->unreference();
        }
        if ($code !== 0) {
            $driver = Loop::get();
            $reflectionClass = new ReflectionClass(Driver::class);
            $reflectionProperty = $reflectionClass->getProperty('watchers');
            $reflectionProperty->setAccessible(true);
            foreach (\array_keys($reflectionProperty->getValue($driver)) as $key) {
                $driver->unreference($key);
            }
        }
        MTProto::serializeAll();
        Loop::stop();
        if (\class_exists(Installer::class)) {
            Installer::unlock();
        }
        die($code);
    }
    /**
     * Toggle periodic logging.
     */
    public static function togglePeriodicLogging() : void
    {
        if (self::$suspendPeriodicLogging) {
            $deferred = self::$suspendPeriodicLogging;
            self::$suspendPeriodicLogging = null;
            $deferred->resolve();
        } else {
            self::$suspendPeriodicLogging = new Deferred();
        }
    }
    /**
     * Set whether we can use ipv6.
     *
     * @param bool $ipv6 Whether we can use ipv6.
     *
     * @return void
     */
    public static function setIpv6(bool $ipv6) : void
    {
        if (!self::$initedIpv6) {
            self::$ipv6 = $ipv6;
            self::$initedIpv6 = true;
        }
    }
}<?php

/**
 * SeqNoHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\SecretChats;

use danog\MadelineProto\Logger;
/**
 * Manages sequence numbers.
 */
trait SeqNoHandler
{
    /**
     *
     */
    private function checkSecretInSeqNo($chat_id, $seqno) : \Generator
    {
        $seqno = ($seqno - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2;
        $last = 0;
        foreach ($this->secret_chats[$chat_id]['incoming'] as $message) {
            if (isset($message['decrypted_message']['in_seq_no'])) {
                if (($message['decrypted_message']['in_seq_no'] - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2 < $last) {
                    $this->logger->logger("Discarding secret chat {$chat_id}, in_seq_no is not increasing", Logger::LEVEL_FATAL);
                    yield from $this->discardSecretChat($chat_id);
                    throw new \danog\MadelineProto\SecurityException('in_seq_no is not increasing');
                }
                $last = ($message['decrypted_message']['in_seq_no'] - $this->secret_chats[$chat_id]['out_seq_no_x']) / 2;
            }
        }
        if ($seqno > $this->secret_chats[$chat_id]['out_seq_no'] + 1) {
            $this->logger->logger("Discarding secret chat {$chat_id}, in_seq_no is too big", Logger::LEVEL_FATAL);
            yield from $this->discardSecretChat($chat_id);
            throw new \danog\MadelineProto\SecurityException('in_seq_no is too big');
        }
        return true;
    }
    /**
     *
     */
    private function checkSecretOutSeqNo($chat_id, $seqno) : \Generator
    {
        $seqno = ($seqno - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2;
        $C = 0;
        foreach ($this->secret_chats[$chat_id]['incoming'] as $message) {
            if (isset($message['decrypted_message']['out_seq_no']) && $C < $this->secret_chats[$chat_id]['in_seq_no']) {
                $temp = ($message['decrypted_message']['out_seq_no'] - $this->secret_chats[$chat_id]['in_seq_no_x']) / 2;
                if ($temp !== $C) {
                    $this->logger->logger("Discarding secret chat {$chat_id}, out_seq_no hole: should be {$C}, is {$temp}", Logger::LEVEL_FATAL);
                    yield from $this->discardSecretChat($chat_id);
                    throw new \danog\MadelineProto\SecurityException("out_seq_no hole: should be {$C}, is {$temp}");
                }
                $C++;
            }
        }
        //$this->logger->logger($C, $seqno);
        if ($seqno < $C) {
            // <= C
            $this->logger->logger('WARNING: dropping repeated message with seqno ' . $seqno);
            return false;
        }
        if ($seqno > $C) {
            // > C+1
            $this->logger->logger("Discarding secret chat {$chat_id}, out_seq_no gap detected: ({$seqno} > {$C})", Logger::LEVEL_FATAL);
            yield from $this->discardSecretChat($chat_id);
            throw new \danog\MadelineProto\SecurityException('WARNING: out_seq_no gap detected (' . $seqno . ' > ' . $C . ')!');
        }
        return true;
    }
    /**
     *
     */
    private function generateSecretInSeqNo($chat)
    {
        return $this->secret_chats[$chat]['layer'] > 8 ? $this->secret_chats[$chat]['in_seq_no'] * 2 + $this->secret_chats[$chat]['in_seq_no_x'] : -1;
    }
    /**
     *
     */
    private function generateSecretOutSeqNo($chat)
    {
        return $this->secret_chats[$chat]['layer'] > 8 ? $this->secret_chats[$chat]['out_seq_no'] * 2 + $this->secret_chats[$chat]['out_seq_no_x'] : -1;
    }
}<?php

/**
 * AuthKeyHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\SecretChats;

use danog\MadelineProto\Loop\Update\SecretFeedLoop;
use danog\MadelineProto\Loop\Update\UpdateLoop;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProtoTools\Crypt;
/**
 * Manages secret chats.
 *
 * https://core.telegram.org/api/end-to-end
 */
trait AuthKeyHandler
{
    /**
     * Temporary requested secret chats.
     *
     * @var array
     */
    protected $temp_requested_secret_chats = [];
    /**
     * Secret chats.
     *
     * @var array
     */
    protected $secret_chats = [];
    /**
     * Accept secret chat.
     *
     * @param array $params Secret chat ID
     *
     * @return \Generator
     */
    public function acceptSecretChat($params) : \Generator
    {
        //$this->logger->logger($params['id'],$this->secretChatStatus($params['id']));
        if ($this->secretChatStatus($params['id']) !== 0) {
            //$this->logger->logger($this->secretChatStatus($params['id']));
            $this->logger->logger("I've already accepted secret chat " . $params['id']);
            return false;
        }
        $dh_config = (yield from $this->getDhConfig());
        $this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
        $b = new \phpseclib3\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
        $params['g_a'] = new \phpseclib3\Math\BigInteger((string) $params['g_a'], 256);
        Crypt::checkG($params['g_a'], $dh_config['p']);
        $key = ['auth_key' => \str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
        //$this->logger->logger($key);
        $key['fingerprint'] = \Phabel\Target\Php80\Polyfill::substr(\sha1($key['auth_key'], true), -8);
        $key['visualization_orig'] = \Phabel\Target\Php80\Polyfill::substr(\sha1($key['auth_key'], true), 16);
        $key['visualization_46'] = \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', $key['auth_key'], true), 20);
        $this->secret_chats[$params['id']] = ['key' => $key, 'admin' => false, 'user_id' => $params['admin_id'], 'InputEncryptedChat' => ['_' => 'inputEncryptedChat', 'chat_id' => $params['id'], 'access_hash' => $params['access_hash']], 'in_seq_no_x' => 1, 'out_seq_no_x' => 0, 'in_seq_no' => 0, 'out_seq_no' => 0, 'layer' => 8, 'ttl' => 0, 'ttr' => 100, 'updated' => \time(), 'incoming' => [], 'outgoing' => [], 'created' => \time(), 'rekeying' => [0], 'key_x' => 'from server', 'mtproto' => 1];
        $this->secretFeeders[$params['id']] = new SecretFeedLoop($this, $params['id']);
        if ($this->secretFeeders[$params['id']]->start()) {
            $this->secretFeeders[$params['id']]->resume();
        }
        $g_b = $dh_config['g']->powMod($b, $dh_config['p']);
        Crypt::checkG($g_b, $dh_config['p']);
        yield from $this->methodCallAsyncRead('messages.acceptEncryption', ['peer' => $params['id'], 'g_b' => $g_b->toBytes(), 'key_fingerprint' => $key['fingerprint']]);
        yield from $this->notifyLayer($params['id']);
        $this->logger->logger('Secret chat ' . $params['id'] . ' accepted successfully!', \danog\MadelineProto\Logger::NOTICE);
    }
    /**
     * Request secret chat.
     *
     * @param mixed $user User to start secret chat with
     *
     * @return \Generator
     */
    public function requestSecretChat($user) : \Generator
    {
        $user = (yield from $this->getInfo($user));
        if (!isset($user['InputUser'])) {
            throw new \danog\MadelineProto\Exception('This peer is not present in the internal peer database');
        }
        $user = $user['InputUser'];
        $this->logger->logger('Creating secret chat with ' . $user['user_id'] . '...', \danog\MadelineProto\Logger::VERBOSE);
        $dh_config = (yield from $this->getDhConfig());
        $this->logger->logger('Generating a...', \danog\MadelineProto\Logger::VERBOSE);
        $a = new \phpseclib3\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
        $this->logger->logger('Generating g_a...', \danog\MadelineProto\Logger::VERBOSE);
        $g_a = $dh_config['g']->powMod($a, $dh_config['p']);
        Crypt::checkG($g_a, $dh_config['p']);
        $res = (yield from $this->methodCallAsyncRead('messages.requestEncryption', ['user_id' => $user, 'g_a' => $g_a->toBytes()]));
        $this->temp_requested_secret_chats[$res['id']] = $a;
        $this->updaters[UpdateLoop::GENERIC]->resume();
        $this->logger->logger('Secret chat ' . $res['id'] . ' requested successfully!', \danog\MadelineProto\Logger::NOTICE);
        return $res['id'];
    }
    /**
     * Complete secret chat.
     *
     * @param array $params Secret chat
     *
     * @return \Generator
     */
    private function completeSecretChat(array $params) : \Generator
    {
        if ($this->secretChatStatus($params['id']) !== 1) {
            //$this->logger->logger($this->secretChatStatus($params['id']));
            $this->logger->logger('Could not find and complete secret chat ' . $params['id']);
            return false;
        }
        $dh_config = (yield from $this->getDhConfig());
        $params['g_a_or_b'] = new \phpseclib3\Math\BigInteger((string) $params['g_a_or_b'], 256);
        Crypt::checkG($params['g_a_or_b'], $dh_config['p']);
        $key = ['auth_key' => \str_pad($params['g_a_or_b']->powMod($this->temp_requested_secret_chats[$params['id']], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
        unset($this->temp_requested_secret_chats[$params['id']]);
        $key['fingerprint'] = \Phabel\Target\Php80\Polyfill::substr(\sha1($key['auth_key'], true), -8);
        //$this->logger->logger($key);
        if ($key['fingerprint'] !== $params['key_fingerprint']) {
            yield from $this->discardSecretChat($params['id']);
            throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
        }
        $key['visualization_orig'] = \Phabel\Target\Php80\Polyfill::substr(\sha1($key['auth_key'], true), 16);
        $key['visualization_46'] = \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', $key['auth_key'], true), 20);
        $this->secret_chats[$params['id']] = ['key' => $key, 'admin' => true, 'user_id' => $params['participant_id'], 'InputEncryptedChat' => ['chat_id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputEncryptedChat'], 'in_seq_no_x' => 0, 'out_seq_no_x' => 1, 'in_seq_no' => 0, 'out_seq_no' => 0, 'layer' => 8, 'ttl' => 0, 'ttr' => 100, 'updated' => \time(), 'incoming' => [], 'outgoing' => [], 'created' => \time(), 'rekeying' => [0], 'key_x' => 'to server', 'mtproto' => 1];
        $this->secretFeeders[$params['id']] = new SecretFeedLoop($this, $params['id']);
        if ($this->secretFeeders[$params['id']]->start()) {
            $this->secretFeeders[$params['id']]->resume();
        }
        yield from $this->notifyLayer($params['id']);
        $this->logger->logger('Secret chat ' . $params['id'] . ' completed successfully!', \danog\MadelineProto\Logger::NOTICE);
    }
    /**
     *
     */
    private function notifyLayer($chat) : \Generator
    {
        yield from $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNotifyLayer', 'layer' => $this->TL->getSecretLayer()]]]);
    }
    /**
     * Temporary rekeyed secret chats.
     *
     * @var array
     */
    protected $temp_rekeyed_secret_chats = [];
    /**
     * Rekey secret chat.
     *
     * @param int $chat Secret chat to rekey
     *
     * @return \Generator
     */
    public function rekey(int $chat) : \Generator
    {
        if ($this->secret_chats[$chat]['rekeying'][0] !== 0) {
            return;
        }
        $this->logger->logger('Rekeying secret chat ' . $chat . '...', \danog\MadelineProto\Logger::VERBOSE);
        $dh_config = (yield from $this->getDhConfig());
        $this->logger->logger('Generating a...', \danog\MadelineProto\Logger::VERBOSE);
        $a = new \phpseclib3\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
        $this->logger->logger('Generating g_a...', \danog\MadelineProto\Logger::VERBOSE);
        $g_a = $dh_config['g']->powMod($a, $dh_config['p']);
        Crypt::checkG($g_a, $dh_config['p']);
        $e = \danog\MadelineProto\Tools::random(8);
        $this->temp_rekeyed_secret_chats[$e] = $a;
        $this->secret_chats[$chat]['rekeying'] = [1, $e];
        yield from $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionRequestKey', 'g_a' => $g_a->toBytes(), 'exchange_id' => $e]]]);
        $this->updaters[UpdateLoop::GENERIC]->resume();
        return $e;
    }
    /**
     * Accept rekeying.
     *
     * @param int $chat Chat
     * @param array $params Parameters
     *
     * @return \Generator
     */
    private function acceptRekey(int $chat, array $params) : \Generator
    {
        if ($this->secret_chats[$chat]['rekeying'][0] !== 0) {
            $my_exchange_id = new \phpseclib3\Math\BigInteger($this->secret_chats[$chat]['rekeying'][1], -256);
            $other_exchange_id = new \phpseclib3\Math\BigInteger($params['exchange_id'], -256);
            //$this->logger->logger($my, $params);
            if ($my_exchange_id->compare($other_exchange_id) > 0) {
                return;
            }
            if ($my_exchange_id->compare($other_exchange_id) === 0) {
                $this->secret_chats[$chat]['rekeying'] = [0];
                return;
            }
        }
        $this->logger->logger('Accepting rekeying of secret chat ' . $chat . '...', \danog\MadelineProto\Logger::VERBOSE);
        $dh_config = (yield from $this->getDhConfig());
        $this->logger->logger('Generating b...', \danog\MadelineProto\Logger::VERBOSE);
        $b = new \phpseclib3\Math\BigInteger(\danog\MadelineProto\Tools::random(256), 256);
        $params['g_a'] = new \phpseclib3\Math\BigInteger((string) $params['g_a'], 256);
        Crypt::checkG($params['g_a'], $dh_config['p']);
        $key = ['auth_key' => \str_pad($params['g_a']->powMod($b, $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
        $key['fingerprint'] = \Phabel\Target\Php80\Polyfill::substr(\sha1($key['auth_key'], true), -8);
        $key['visualization_orig'] = $this->secret_chats[$chat]['key']['visualization_orig'];
        $key['visualization_46'] = \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', $key['auth_key'], true), 20);
        $this->temp_rekeyed_secret_chats[$params['exchange_id']] = $key;
        $this->secret_chats[$chat]['rekeying'] = [2, $params['exchange_id']];
        $g_b = $dh_config['g']->powMod($b, $dh_config['p']);
        Crypt::checkG($g_b, $dh_config['p']);
        yield from $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAcceptKey', 'g_b' => $g_b->toBytes(), 'exchange_id' => $params['exchange_id'], 'key_fingerprint' => $key['fingerprint']]]]);
        $this->updaters[UpdateLoop::GENERIC]->resume();
    }
    /**
     * Commit rekeying of secret chat.
     *
     * @param int $chat Chat
     * @param array $params Parameters
     *
     * @return \Generator
     */
    private function commitRekey(int $chat, array $params) : \Generator
    {
        if ($this->secret_chats[$chat]['rekeying'][0] !== 1 || !isset($this->temp_rekeyed_secret_chats[$params['exchange_id']])) {
            $this->secret_chats[$chat]['rekeying'] = [0];
            return;
        }
        $this->logger->logger('Committing rekeying of secret chat ' . $chat . '...', \danog\MadelineProto\Logger::VERBOSE);
        $dh_config = (yield from $this->getDhConfig());
        $params['g_b'] = new \phpseclib3\Math\BigInteger((string) $params['g_b'], 256);
        Crypt::checkG($params['g_b'], $dh_config['p']);
        $key = ['auth_key' => \str_pad($params['g_b']->powMod($this->temp_rekeyed_secret_chats[$params['exchange_id']], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
        $key['fingerprint'] = \Phabel\Target\Php80\Polyfill::substr(\sha1($key['auth_key'], true), -8);
        $key['visualization_orig'] = $this->secret_chats[$chat]['key']['visualization_orig'];
        $key['visualization_46'] = \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', $key['auth_key'], true), 20);
        if ($key['fingerprint'] !== $params['key_fingerprint']) {
            yield from $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]]);
            throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
        }
        yield from $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionCommitKey', 'exchange_id' => $params['exchange_id'], 'key_fingerprint' => $key['fingerprint']]]]);
        unset($this->temp_rekeyed_secret_chats[$params['exchange_id']]);
        $this->secret_chats[$chat]['rekeying'] = [0];
        $this->secret_chats[$chat]['old_key'] = $this->secret_chats[$chat]['key'];
        $this->secret_chats[$chat]['key'] = $key;
        $this->secret_chats[$chat]['ttr'] = 100;
        $this->secret_chats[$chat]['updated'] = \time();
        $this->updaters[UpdateLoop::GENERIC]->resume();
    }
    /**
     * Complete rekeying.
     *
     * @param int $chat Chat
     * @param array $params Parameters
     *
     * @return \Generator
     */
    private function completeRekey(int $chat, array $params) : \Generator
    {
        if ($this->secret_chats[$chat]['rekeying'][0] !== 2 || !isset($this->temp_rekeyed_secret_chats[$params['exchange_id']]['fingerprint'])) {
            return;
        }
        if ($this->temp_rekeyed_secret_chats[$params['exchange_id']]['fingerprint'] !== $params['key_fingerprint']) {
            yield from $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionAbortKey', 'exchange_id' => $params['exchange_id']]]]);
            throw new \danog\MadelineProto\SecurityException('Invalid key fingerprint!');
        }
        $this->logger->logger('Completing rekeying of secret chat ' . $chat . '...', \danog\MadelineProto\Logger::VERBOSE);
        $this->secret_chats[$chat]['rekeying'] = [0];
        $this->secret_chats[$chat]['old_key'] = $this->secret_chats[$chat]['key'];
        $this->secret_chats[$chat]['key'] = $this->temp_rekeyed_secret_chats[$params['exchange_id']];
        $this->secret_chats[$chat]['ttr'] = 100;
        $this->secret_chats[$chat]['updated'] = \time();
        unset($this->temp_rekeyed_secret_chats[$params['exchange_id']]);
        yield from $this->methodCallAsyncRead('messages.sendEncryptedService', ['peer' => $chat, 'message' => ['_' => 'decryptedMessageService', 'action' => ['_' => 'decryptedMessageActionNoop']]]);
        $this->logger->logger('Secret chat ' . $chat . ' rekeyed successfully!', \danog\MadelineProto\Logger::VERBOSE);
        return true;
    }
    /**
     * Get secret chat status.
     *
     * @param int $chat Chat ID
     *
     * @return int One of MTProto::SECRET_EMPTY, MTProto::SECRET_REQUESTED, MTProto::SECRET_READY
     */
    public function secretChatStatus(int $chat) : int
    {
        if (isset($this->secret_chats[$chat])) {
            return MTProto::SECRET_READY;
        }
        if (isset($this->temp_requested_secret_chats[$chat])) {
            return MTProto::SECRET_REQUESTED;
        }
        return MTProto::SECRET_EMPTY;
    }
    /**
     * Get secret chat.
     *
     * @param (array | int) $chat Secret chat ID
     *
     * @return array
     */
    public function getSecretChat($chat) : array
    {
        return $this->secret_chats[\is_array($chat) ? $chat['chat_id'] : $chat];
    }
    /**
     * Check whether secret chat exists.
     *
     * @param (array | int) $chat Secret chat ID
     *
     * @return boolean
     */
    public function hasSecretChat($chat) : bool
    {
        return isset($this->secret_chats[\is_array($chat) ? $chat['chat_id'] : $chat]);
    }
    /**
     * Discard secret chat.
     *
     * @param int $chat Secret chat ID
     *
     * @return \Generator
     */
    public function discardSecretChat(int $chat) : \Generator
    {
        $this->logger->logger('Discarding secret chat ' . $chat . '...', \danog\MadelineProto\Logger::VERBOSE);
        if (isset($this->secret_chats[$chat])) {
            unset($this->secret_chats[$chat]);
        }
        if (isset($this->temp_requested_secret_chats[$chat])) {
            unset($this->temp_requested_secret_chats[$chat]);
        }
        try {
            yield from $this->methodCallAsyncRead('messages.discardEncryption', ['chat_id' => $chat]);
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            if ($e->rpc !== 'ENCRYPTION_ALREADY_DECLINED') {
                throw $e;
            }
        }
    }
}<?php

/**
 * MessageHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\SecretChats;

use Amp\Deferred;
use Amp\Promise;
use danog\MadelineProto\MTProtoTools\Crypt;
/**
 * Manages packing and unpacking of messages, and the list of sent and received messages.
 */
trait MessageHandler
{
    /**
     * Secret queue.
     *
     * @var Promise[]
     */
    private $secretQueue = [];
    /**
     * Encrypt secret chat message.
     *
     * @param integer $chat_id Chat ID
     * @param array $message Message to encrypt
     * @param Deferred $queuePromise Queue promise
     *
     * @internal
     *
     * @return \Generator
     */
    public function encryptSecretMessage(int $chat_id, array $message, Deferred $queuePromise) : \Generator
    {
        if (!isset($this->secret_chats[$chat_id])) {
            $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $chat_id));
            return false;
        }
        $message['random_id'] = \danog\MadelineProto\Tools::random(8);
        $this->secret_chats[$chat_id]['ttr']--;
        if ($this->secret_chats[$chat_id]['layer'] > 8) {
            if (($this->secret_chats[$chat_id]['ttr'] <= 0 || \time() - $this->secret_chats[$chat_id]['updated'] > 7 * 24 * 60 * 60) && $this->secret_chats[$chat_id]['rekeying'][0] === 0) {
                yield from $this->rekey($chat_id);
            }
            if (isset($this->secretQueue[$chat_id])) {
                $promise = $this->secretQueue[$chat_id];
                $this->secretQueue[$chat_id] = $queuePromise->promise();
                (yield $promise);
            } else {
                $this->secretQueue[$chat_id] = $queuePromise->promise();
            }
            $message = ['_' => 'decryptedMessageLayer', 'layer' => $this->secret_chats[$chat_id]['layer'], 'in_seq_no' => $this->generateSecretInSeqNo($chat_id), 'out_seq_no' => $this->generateSecretOutSeqNo($chat_id), 'message' => $message];
            $this->secret_chats[$chat_id]['out_seq_no']++;
        }
        $this->secret_chats[$chat_id]['outgoing'][$this->secret_chats[$chat_id]['out_seq_no']] = $message;
        $constructor = $this->secret_chats[$chat_id]['layer'] === 8 ? 'DecryptedMessage' : 'DecryptedMessageLayer';
        $message = (yield from $this->TL->serializeObject(['type' => $constructor], $message, $constructor, $this->secret_chats[$chat_id]['layer']));
        $message = \danog\MadelineProto\Tools::packUnsignedInt(\strlen($message)) . $message;
        if ($this->secret_chats[$chat_id]['mtproto'] === 2) {
            $padding = \danog\MadelineProto\Tools::posmod(-\strlen($message), 16);
            if ($padding < 12) {
                $padding += 16;
            }
            $message .= \danog\MadelineProto\Tools::random($padding);
            $message_key = \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', \Phabel\Target\Php80\Polyfill::substr($this->secret_chats[$chat_id]['key']['auth_key'], 88 + ($this->secret_chats[$chat_id]['admin'] ? 0 : 8), 32) . $message, true), 8, 16);
            list($aes_key, $aes_iv) = Crypt::aesCalculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], $this->secret_chats[$chat_id]['admin']);
        } else {
            $message_key = \Phabel\Target\Php80\Polyfill::substr(\sha1($message, true), -16);
            list($aes_key, $aes_iv) = Crypt::oldAesCalculate($message_key, $this->secret_chats[$chat_id]['key']['auth_key'], true);
            $message .= \danog\MadelineProto\Tools::random(\danog\MadelineProto\Tools::posmod(-\strlen($message), 16));
        }
        $message = $this->secret_chats[$chat_id]['key']['fingerprint'] . $message_key . Crypt::igeEncrypt($message, $aes_key, $aes_iv);
        return $message;
    }
    /**
     * Handle encrypted update.
     *
     * @internal
     *
     * @param array $message
     * @return \Generator
     */
    public function handleEncryptedUpdate(array $message) : \Generator
    {
        if (!isset($this->secret_chats[$message['message']['chat_id']])) {
            $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['secret_chat_skipping'], $message['message']['chat_id']));
            return false;
        }
        $auth_key_id = \Phabel\Target\Php80\Polyfill::substr($message['message']['bytes'], 0, 8);
        $old = false;
        if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['key']['fingerprint']) {
            if (isset($this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint'])) {
                if ($auth_key_id !== $this->secret_chats[$message['message']['chat_id']]['old_key']['fingerprint']) {
                    yield from $this->discardSecretChat($message['message']['chat_id']);
                    throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_mismatch']);
                }
                $old = true;
            } else {
                yield from $this->discardSecretChat($message['message']['chat_id']);
                throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_mismatch']);
            }
        }
        $message_key = \Phabel\Target\Php80\Polyfill::substr($message['message']['bytes'], 8, 16);
        $encrypted_data = \Phabel\Target\Php80\Polyfill::substr($message['message']['bytes'], 24);
        if ($this->secret_chats[$message['message']['chat_id']]['mtproto'] === 2) {
            $this->logger->logger('Trying MTProto v2 decryption for chat ' . $message['message']['chat_id'] . '...', \danog\MadelineProto\Logger::NOTICE);
            try {
                $message_data = $this->tryMTProtoV2Decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
                $this->logger->logger('MTProto v2 decryption OK for chat ' . $message['message']['chat_id'] . '...', \danog\MadelineProto\Logger::NOTICE);
            } catch (\danog\MadelineProto\SecurityException $e) {
                $this->logger->logger('MTProto v2 decryption failed with message ' . $e->getMessage() . ', trying MTProto v1 decryption for chat ' . $message['message']['chat_id'] . '...', \danog\MadelineProto\Logger::NOTICE);
                $message_data = $this->tryMTProtoV1Decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
                $this->logger->logger('MTProto v1 decryption OK for chat ' . $message['message']['chat_id'] . '...', \danog\MadelineProto\Logger::NOTICE);
                $this->secret_chats[$message['message']['chat_id']]['mtproto'] = 1;
            }
        } else {
            $this->logger->logger('Trying MTProto v1 decryption for chat ' . $message['message']['chat_id'] . '...', \danog\MadelineProto\Logger::NOTICE);
            try {
                $message_data = $this->tryMTProtoV1Decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
                $this->logger->logger('MTProto v1 decryption OK for chat ' . $message['message']['chat_id'] . '...', \danog\MadelineProto\Logger::NOTICE);
            } catch (\danog\MadelineProto\SecurityException $e) {
                $this->logger->logger('MTProto v1 decryption failed with message ' . $e->getMessage() . ', trying MTProto v2 decryption for chat ' . $message['message']['chat_id'] . '...', \danog\MadelineProto\Logger::NOTICE);
                $message_data = $this->tryMTProtoV2Decrypt($message_key, $message['message']['chat_id'], $old, $encrypted_data);
                $this->logger->logger('MTProto v2 decryption OK for chat ' . $message['message']['chat_id'] . '...', \danog\MadelineProto\Logger::NOTICE);
                $this->secret_chats[$message['message']['chat_id']]['mtproto'] = 2;
            }
        }
        [$deserialized, $sideEffects] = $this->TL->deserialize($message_data, ['type' => '']);
        if ($sideEffects) {
            (yield $sideEffects);
        }
        $this->secret_chats[$message['message']['chat_id']]['ttr']--;
        if (($this->secret_chats[$message['message']['chat_id']]['ttr'] <= 0 || \time() - $this->secret_chats[$message['message']['chat_id']]['updated'] > 7 * 24 * 60 * 60) && $this->secret_chats[$message['message']['chat_id']]['rekeying'][0] === 0) {
            yield from $this->rekey($message['message']['chat_id']);
        }
        unset($message['message']['bytes']);
        $message['message']['decrypted_message'] = $deserialized;
        $this->secret_chats[$message['message']['chat_id']]['incoming'][$this->secret_chats[$message['message']['chat_id']]['in_seq_no']] = $message['message'];
        yield from $this->handleDecryptedUpdate($message);
        return true;
    }
    /**
     * @return (false | string)
     */
    private function tryMTProtoV1Decrypt($message_key, $chat_id, $old, $encrypted_data)
    {
        list($aes_key, $aes_iv) = Crypt::oldAesCalculate($message_key, $this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], true);
        $decrypted_data = Crypt::igeDecrypt($encrypted_data, $aes_key, $aes_iv);
        $message_data_length = \unpack('V', \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 0, 4))[1];
        $message_data = \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 4, $message_data_length);
        if ($message_data_length > \strlen($decrypted_data)) {
            throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big']);
        }
        if ($message_key != \Phabel\Target\Php80\Polyfill::substr(\sha1(\Phabel\Target\Php80\Polyfill::substr($decrypted_data, 0, 4 + $message_data_length), true), -16)) {
            throw new \danog\MadelineProto\SecurityException('Msg_key mismatch');
        }
        if (\strlen($decrypted_data) - 4 - $message_data_length > 15) {
            throw new \danog\MadelineProto\SecurityException('difference between message_data_length and the length of the remaining decrypted buffer is too big');
        }
        if (\strlen($decrypted_data) % 16 != 0) {
            throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['length_not_divisible_16']);
        }
        return $message_data;
    }
    /**
     * @return (false | string)
     */
    private function tryMTProtoV2Decrypt($message_key, $chat_id, $old, $encrypted_data)
    {
        list($aes_key, $aes_iv) = Crypt::aesCalculate($message_key, $this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], !$this->secret_chats[$chat_id]['admin']);
        $decrypted_data = Crypt::igeDecrypt($encrypted_data, $aes_key, $aes_iv);
        if ($message_key != \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', \Phabel\Target\Php80\Polyfill::substr($this->secret_chats[$chat_id][$old ? 'old_key' : 'key']['auth_key'], 88 + ($this->secret_chats[$chat_id]['admin'] ? 8 : 0), 32) . $decrypted_data, true), 8, 16)) {
            throw new \danog\MadelineProto\SecurityException('Msg_key mismatch');
        }
        $message_data_length = \unpack('V', \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 0, 4))[1];
        $message_data = \Phabel\Target\Php80\Polyfill::substr($decrypted_data, 4, $message_data_length);
        if ($message_data_length > \strlen($decrypted_data)) {
            throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['msg_data_length_too_big']);
        }
        if (\strlen($decrypted_data) - 4 - $message_data_length < 12) {
            throw new \danog\MadelineProto\SecurityException('padding is too small');
        }
        if (\strlen($decrypted_data) - 4 - $message_data_length > 1024) {
            throw new \danog\MadelineProto\SecurityException('padding is too big');
        }
        if (\strlen($decrypted_data) % 16 != 0) {
            throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['length_not_divisible_16']);
        }
        return $message_data;
    }
}<?php

/**
 * ResponseHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\SecretChats;

/**
 * Manages responses.
 */
trait ResponseHandler
{
    /**
     *
     */
    private function handleDecryptedUpdate(array $update) : \Generator
    {
        $chatId = $update['message']['chat_id'];
        $decryptedMessage = $update['message']['decrypted_message'];
        if ($decryptedMessage['_'] === 'decryptedMessage') {
            yield from $this->saveUpdate($update);
            return;
        }
        if ($decryptedMessage['_'] === 'decryptedMessageService') {
            $action = $decryptedMessage['action'];
            switch ($action['_']) {
                case 'decryptedMessageActionRequestKey':
                    yield from $this->acceptRekey($chatId, $action);
                    return;
                case 'decryptedMessageActionAcceptKey':
                    yield from $this->commitRekey($chatId, $action);
                    return;
                case 'decryptedMessageActionCommitKey':
                    yield from $this->completeRekey($chatId, $action);
                    return;
                case 'decryptedMessageActionNotifyLayer':
                    $this->secret_chats[$chatId]['layer'] = $action['layer'];
                    if ($action['layer'] >= 17 && \time() - $this->secret_chats[$chatId]['created'] > 15) {
                        yield from $this->notifyLayer($chatId);
                    }
                    if ($action['layer'] >= 73) {
                        $this->secret_chats[$chatId]['mtproto'] = 2;
                    }
                    return;
                case 'decryptedMessageActionSetMessageTTL':
                    $this->secret_chats[$chatId]['ttl'] = $action['ttl_seconds'];
                    yield from $this->saveUpdate($update);
                    return;
                case 'decryptedMessageActionNoop':
                    return;
                case 'decryptedMessageActionResend':
                    $action['start_seq_no'] -= $this->secret_chats[$chatId]['out_seq_no_x'];
                    $action['end_seq_no'] -= $this->secret_chats[$chatId]['out_seq_no_x'];
                    $action['start_seq_no'] /= 2;
                    $action['end_seq_no'] /= 2;
                    $this->logger->logger('Resending messages for secret chat ' . $chatId, \danog\MadelineProto\Logger::WARNING);
                    foreach ($this->secret_chats[$chatId]['outgoing'] as $seq => $message) {
                        if ($seq >= $action['start_seq_no'] && $seq <= $action['end_seq_no']) {
                            yield from $this->methodCallAsyncRead('messages.sendEncrypted', ['peer' => $chatId, 'message' => $message]);
                        }
                    }
                    return;
                default:
                    yield from $this->saveUpdate($update);
            }
            return;
        }
        if ($decryptedMessage['_'] === 'decryptedMessageLayer') {
            if ((yield from $this->checkSecretOutSeqNo($chatId, $decryptedMessage['out_seq_no'])) && (yield from $this->checkSecretInSeqNo($chatId, $decryptedMessage['in_seq_no']))) {
                $this->secret_chats[$chatId]['in_seq_no']++;
                if ($decryptedMessage['layer'] >= 17 && $decryptedMessage['layer'] !== $this->secret_chats[$chatId]['layer']) {
                    $this->secret_chats[$chatId]['layer'] = $decryptedMessage['layer'];
                    if ($decryptedMessage['layer'] >= 17 && \time() - $this->secret_chats[$chatId]['created'] > 15) {
                        yield from $this->notifyLayer($chatId);
                    }
                }
                $update['message']['decrypted_message'] = $decryptedMessage['message'];
                yield from $this->handleDecryptedUpdate($update);
            }
            return;
        }
        throw new \danog\MadelineProto\ResponseException('Unrecognized decrypted message received: ' . \var_export($update, true));
    }
}<?php

/**
 * Noop module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

trait Noop
{
    /**
     * Set NOOP update handler, ignoring all updates.
     *
     * @return void
     */
    public function setNoop() : void
    {
        $this->updateHandler = null;
        $this->updates = [];
        $this->startUpdateSystem();
    }
    /**
     * Noop update handler.
     *
     * @internal
     *
     * @return void
     */
    public static function noop() : void
    {
    }
}<?php

/**
 * DialogHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use danog\MadelineProto\MTProto;
use danog\MadelineProto\Settings;
/**
 * Dialog handler.
 *
 * @property Settings $settings Settings
 */
trait DialogHandler
{
    /**
     * Get dialog peers.
     *
     * @param boolean $force Whether to refetch all dialogs ignoring cache
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, \Amp\Promise<bool>, mixed, list<mixed>>
     */
    public function getDialogs(bool $force = true) : \Generator
    {
        if ($this->authorization['user']['bot']) {
            $res = [];
            /** @uses DbArray::getIterator() */
            $iterator = $this->chats->getIterator();
            while ((yield $iterator->advance())) {
                [, $chat] = $iterator->getCurrent();
                try {
                    $res[] = $this->genAll($chat, null, MTProto::INFO_TYPE_ALL)['Peer'];
                } catch (\Throwable $e) {
                    continue;
                }
            }
            return $res;
        }
        $res = [];
        foreach (yield from $this->getFullDialogs($force) as $dialog) {
            $res[] = $dialog['peer'];
        }
        return $res;
    }
    /**
     * Get full info of all dialogs.
     *
     * @param boolean $force Whether to refetch all dialogs ignoring cache
     *
     * @return \Generator
     */
    public function getFullDialogs(bool $force = true) : \Generator
    {
        if ($force || !isset($this->dialog_params['offset_date']) || \is_null($this->dialog_params['offset_date']) || !isset($this->dialog_params['offset_id']) || \is_null($this->dialog_params['offset_id']) || !isset($this->dialog_params['offset_peer']) || \is_null($this->dialog_params['offset_peer']) || !isset($this->dialog_params['count']) || \is_null($this->dialog_params['count'])) {
            $this->dialog_params = ['limit' => 100, 'offset_date' => 0, 'offset_id' => 0, 'offset_peer' => ['_' => 'inputPeerEmpty'], 'count' => 0, 'hash' => 0];
        }
        if (!isset($this->dialog_params['hash'])) {
            $this->dialog_params['hash'] = 0;
        }
        $res = ['dialogs' => [0], 'count' => 1];
        $datacenter = $this->datacenter->curdc;
        $dialogs = [];
        $this->logger->logger("Getting dialogs...");
        while ($this->dialog_params['count'] < $res['count']) {
            $res = (yield from $this->methodCallAsyncRead('messages.getDialogs', $this->dialog_params, ['datacenter' => $datacenter, 'FloodWaitLimit' => 100]));
            $last_peer = 0;
            $last_date = 0;
            $last_id = 0;
            $res['messages'] = \array_reverse($res['messages'] ?? []);
            foreach (\array_reverse($res['dialogs'] ?? []) as $dialog) {
                $id = $this->getId($dialog['peer']);
                if (!isset($dialogs[$id])) {
                    $dialogs[$id] = $dialog;
                }
                if (!$last_date) {
                    if (!$last_peer) {
                        $last_peer = $id;
                    }
                    if (!$last_id) {
                        $last_id = $dialog['top_message'];
                    }
                    foreach ($res['messages'] as $message) {
                        if ($message['_'] !== 'messageEmpty' && $this->getId($message) === $last_peer && $last_id === $message['id']) {
                            $last_date = $message['date'];
                            break;
                        }
                    }
                }
            }
            if ($last_date) {
                $this->dialog_params['offset_date'] = $last_date;
                $this->dialog_params['offset_peer'] = $last_peer;
                $this->dialog_params['offset_id'] = $last_id;
                $this->dialog_params['count'] = \count($dialogs);
            } else {
                break;
            }
            if (!isset($res['count'])) {
                break;
            }
        }
        return $dialogs;
    }
}<?php

/**
 * Start module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use danog\MadelineProto\Ipc\Client;
use danog\MadelineProto\Lang;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools;
/**
 * Manages simple logging in and out.
 *
 * @property Settings $settings Settings
 */
trait Start
{
    /**
     * Log in to telegram (via CLI or web).
     *
     * @return \Generator
     */
    public function start() : \Generator
    {
        if ((yield $this->getAuthorization()) === MTProto::LOGGED_IN) {
            return $this instanceof Client ? yield from $this->getSelf() : (yield from $this->fullGetSelf());
        }
        if ($this->getWebTemplate() === 'legacy') {
            if ($this instanceof Client) {
                $settings = (yield from $this->getSettings());
            } else {
                $settings = $this->settings;
            }
            $this->setWebTemplate($settings->getTemplates()->getHtmlTemplate());
        }
        if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
            if (\strpos((yield Tools::readLine(Lang::$current_lang['loginChoosePrompt'])), 'b') !== false) {
                yield from $this->botLogin((yield Tools::readLine(Lang::$current_lang['loginBot'])));
            } else {
                yield from $this->phoneLogin((yield Tools::readLine(Lang::$current_lang['loginUser'])));
                $authorization = (yield from $this->completePhoneLogin((yield Tools::readLine(Lang::$current_lang['loginUserCode']))));
                if ($authorization['_'] === 'account.password') {
                    $authorization = (yield from $this->complete2faLogin((yield Tools::readLine(\sprintf(Lang::$current_lang['loginUserPass'], $authorization['hint'])))));
                }
                if ($authorization['_'] === 'account.needSignup') {
                    $authorization = (yield from $this->completeSignup((yield Tools::readLine(Lang::$current_lang['signupFirstName'])), (yield Tools::readLine(Lang::$current_lang['signupLastName']))));
                }
            }
            $this->serialize();
            return yield from $this->fullGetSelf();
        }
        if ((yield $this->getAuthorization()) === MTProto::NOT_LOGGED_IN) {
            if (isset($_POST['phone_number'])) {
                yield from $this->webPhoneLogin();
            } elseif (isset($_POST['token'])) {
                yield from $this->webBotLogin();
            } else {
                yield from $this->webEcho();
            }
        } elseif ((yield $this->getAuthorization()) === MTProto::WAITING_CODE) {
            if (isset($_POST['phone_code'])) {
                yield from $this->webCompletePhoneLogin();
            } else {
                yield from $this->webEcho(Lang::$current_lang['loginNoCode']);
            }
        } elseif ((yield $this->getAuthorization()) === MTProto::WAITING_PASSWORD) {
            if (isset($_POST['password'])) {
                yield from $this->webComplete2faLogin();
            } else {
                yield from $this->webEcho(Lang::$current_lang['loginNoPass']);
            }
        } elseif ((yield $this->getAuthorization()) === MTProto::WAITING_SIGNUP) {
            if (isset($_POST['first_name'])) {
                yield from $this->webCompleteSignup();
            } else {
                yield from $this->webEcho(Lang::$current_lang['loginNoName']);
            }
        }
        if ((yield $this->getAuthorization()) === MTProto::LOGGED_IN) {
            $this->serialize();
            return yield from $this->fullGetSelf();
        }
        exit;
    }
    /**
     *
     */
    private function webPhoneLogin() : \Generator
    {
        try {
            yield from $this->phoneLogin($_POST['phone_number']);
            yield from $this->webEcho();
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        } catch (\danog\MadelineProto\Exception $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        }
    }
    /**
     *
     */
    private function webCompletePhoneLogin() : \Generator
    {
        try {
            yield from $this->completePhoneLogin($_POST['phone_code']);
            yield from $this->webEcho();
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        } catch (\danog\MadelineProto\Exception $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        }
    }
    /**
     *
     */
    private function webComplete2faLogin() : \Generator
    {
        try {
            yield from $this->complete2faLogin($_POST['password']);
            yield from $this->webEcho();
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        } catch (\danog\MadelineProto\Exception $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        }
    }
    /**
     *
     */
    private function webCompleteSignup() : \Generator
    {
        try {
            yield from $this->completeSignup($_POST['first_name'], isset($_POST['last_name']) ? $_POST['last_name'] : '');
            yield from $this->webEcho();
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        } catch (\danog\MadelineProto\Exception $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        }
    }
    /**
     *
     */
    private function webBotLogin() : \Generator
    {
        try {
            yield from $this->botLogin($_POST['token']);
            yield from $this->webEcho();
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        } catch (\danog\MadelineProto\Exception $e) {
            yield from $this->webEcho(\sprintf(Lang::$current_lang['apiError'], $e->getMessage()));
        }
    }
}<?php

/**
 * Login module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProtoTools\PasswordCalculator;
use danog\MadelineProto\Settings;
/**
 * Manages logging in and out.
 *
 * @property Settings $settings Settings
 */
trait Login
{
    /**
     * Log out currently logged in user.
     *
     * @return \Generator
     */
    public function logout() : \Generator
    {
        yield from $this->methodCallAsyncRead('auth.logOut', []);
        yield from $this->resetSession();
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['logout_ok'], \danog\MadelineProto\Logger::NOTICE);
        $this->startUpdateSystem();
        return true;
    }
    /**
     * Login as bot.
     *
     * @param string $token Bot token
     *
     * @return \Generator
     */
    public function botLogin(string $token) : \Generator
    {
        if ($this->authorized === MTProto::LOGGED_IN) {
            return;
        }
        $callbacks = [$this, $this->referenceDatabase];
        $this->TL->updateCallbacks($callbacks);
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_bot'], \danog\MadelineProto\Logger::NOTICE);
        $this->authorization = (yield from $this->methodCallAsyncRead('auth.importBotAuthorization', ['bot_auth_token' => $token, 'api_id' => $this->settings->getAppInfo()->getApiId(), 'api_hash' => $this->settings->getAppInfo()->getApiHash()]));
        $this->authorized = MTProto::LOGGED_IN;
        $this->authorized_dc = $this->datacenter->curdc;
        $this->datacenter->getDataCenterConnection($this->datacenter->curdc)->authorized(true);
        $this->updates = [];
        $this->updates_key = 0;
        yield from $this->initAuthorization();
        $this->startUpdateSystem();
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_ok'], \danog\MadelineProto\Logger::NOTICE);
        return $this->authorization;
    }
    /**
     * Login as user.
     *
     * @param string $number Phone number
     * @param integer $sms_type SMS type
     *
     * @return \Generator
     */
    public function phoneLogin($number, $sms_type = 5) : \Generator
    {
        if ($this->authorized === MTProto::LOGGED_IN) {
            $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['already_loggedIn'], \danog\MadelineProto\Logger::NOTICE);
            yield from $this->logout();
        }
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_code_sending'], \danog\MadelineProto\Logger::NOTICE);
        $this->authorization = (yield from $this->methodCallAsyncRead('auth.sendCode', ['settings' => ['_' => 'codeSettings'], 'phone_number' => $number, 'sms_type' => $sms_type, 'api_id' => $this->settings->getAppInfo()->getApiId(), 'api_hash' => $this->settings->getAppInfo()->getApiHash(), 'lang_code' => $this->settings->getAppInfo()->getLangCode()]));
        $this->authorized_dc = $this->datacenter->curdc;
        $this->authorization['phone_number'] = $number;
        //$this->authorization['_'] .= 'MP';
        $this->authorized = MTProto::WAITING_CODE;
        $this->updates = [];
        $this->updates_key = 0;
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_code_sent'], \danog\MadelineProto\Logger::NOTICE);
        return $this->authorization;
    }
    /**
     * Complet user login using login code.
     *
     * @param string $code Login code
     *
     * @return \Generator
     */
    public function completePhoneLogin($code) : \Generator
    {
        if ($this->authorized !== MTProto::WAITING_CODE) {
            throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['login_code_uncalled']);
        }
        $this->authorized = MTProto::NOT_LOGGED_IN;
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_user'], \danog\MadelineProto\Logger::NOTICE);
        try {
            $authorization = (yield from $this->methodCallAsyncRead('auth.signIn', ['phone_number' => $this->authorization['phone_number'], 'phone_code_hash' => $this->authorization['phone_code_hash'], 'phone_code' => (string) $code]));
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            if ($e->rpc === 'SESSION_PASSWORD_NEEDED') {
                $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_2fa_enabled'], \danog\MadelineProto\Logger::NOTICE);
                $this->authorization = (yield from $this->methodCallAsyncRead('account.getPassword', []));
                if (!isset($this->authorization['hint'])) {
                    $this->authorization['hint'] = '';
                }
                $this->authorized = MTProto::WAITING_PASSWORD;
                return $this->authorization;
            }
            if ($e->rpc === 'PHONE_NUMBER_UNOCCUPIED') {
                $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_need_signup'], \danog\MadelineProto\Logger::NOTICE);
                $this->authorized = MTProto::WAITING_SIGNUP;
                $this->authorization['phone_code'] = $code;
                return ['_' => 'account.needSignup'];
            }
            throw $e;
        }
        if ($authorization['_'] === 'auth.authorizationSignUpRequired') {
            $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_need_signup'], \danog\MadelineProto\Logger::NOTICE);
            $this->authorized = MTProto::WAITING_SIGNUP;
            $this->authorization['phone_code'] = $code;
            $authorization['_'] = 'account.needSignup';
            return $authorization;
        }
        $this->authorized = MTProto::LOGGED_IN;
        $this->authorization = $authorization;
        $this->datacenter->getDataCenterConnection($this->datacenter->curdc)->authorized(true);
        yield from $this->initAuthorization();
        yield from $this->getPhoneConfig();
        $this->startUpdateSystem();
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_ok'], \danog\MadelineProto\Logger::NOTICE);
        return $this->authorization;
    }
    /**
     * Import authorization.
     *
     * @param array<int, string> $authorization Authorization info
     * @param int $mainDcID Main DC ID
     *
     * @return \Generator
     */
    public function importAuthorization(array $authorization, int $mainDcID) : \Generator
    {
        if ($this->authorized === MTProto::LOGGED_IN) {
            $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['already_loggedIn'], \danog\MadelineProto\Logger::NOTICE);
            yield from $this->logout();
        }
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_auth_key'], \danog\MadelineProto\Logger::NOTICE);
        foreach ($this->datacenter->getDataCenterConnections() as $connection) {
            $connection->resetSession();
            $connection->setPermAuthKey(null);
            $connection->setTempAuthKey(null);
            $connection->authorized(false);
        }
        foreach ($authorization as $dc_id => $auth_key) {
            $this->logger->logger("Setting auth key in DC {$dc_id}", \danog\MadelineProto\Logger::NOTICE);
            if (!\is_array($auth_key)) {
                $auth_key = ['auth_key' => $auth_key];
            }
            $auth_key = new PermAuthKey($auth_key);
            $auth_key->authorized(true);
            $dataCenterConnection = $this->datacenter->getDataCenterConnection($dc_id);
            $dataCenterConnection->setPermAuthKey($auth_key);
        }
        $this->authorized_dc = $mainDcID;
        $this->authorized = MTProto::LOGGED_IN;
        yield from $this->connectToAllDcs(true);
        yield from $this->initAuthorization();
        yield from $this->getPhoneConfig();
        $res = (yield from $this->fullGetSelf());
        $callbacks = [$this, $this->referenceDatabase];
        if (!($this->authorization['user']['bot'] ?? false)) {
            $callbacks[] = $this->minDatabase;
        }
        $this->TL->updateCallbacks($callbacks);
        $this->startUpdateSystem();
        return $res;
    }
    /**
     * Export authorization.
     *
     * @return \Generator
     *
     * @psalm-return \Generator<mixed, (array | bool), mixed, array{0: (int | string), 1: string}>
     */
    public function exportAuthorization() : \Generator
    {
        if ($this->authorized !== MTProto::LOGGED_IN) {
            throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['not_loggedIn']);
        }
        yield from $this->fullGetSelf();
        $this->authorized_dc = $this->datacenter->curdc;
        return [$this->datacenter->curdc, $this->datacenter->getDataCenterConnection($this->datacenter->curdc)->getPermAuthKey()->getAuthKey()];
    }
    /**
     * Complete signup to Telegram.
     *
     * @param string $first_name First name
     * @param string $last_name Last name
     *
     * @return \Generator
     */
    public function completeSignup(string $first_name, string $last_name = '') : \Generator
    {
        if ($this->authorized !== MTProto::WAITING_SIGNUP) {
            throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['signup_uncalled']);
        }
        $this->authorized = MTProto::NOT_LOGGED_IN;
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['signing_up'], \danog\MadelineProto\Logger::NOTICE);
        $this->authorization = (yield from $this->methodCallAsyncRead('auth.signUp', ['phone_number' => $this->authorization['phone_number'], 'phone_code_hash' => $this->authorization['phone_code_hash'], 'phone_code' => $this->authorization['phone_code'], 'first_name' => $first_name, 'last_name' => $last_name]));
        $this->authorized = MTProto::LOGGED_IN;
        $this->datacenter->getDataCenterConnection($this->datacenter->curdc)->authorized(true);
        yield from $this->initAuthorization();
        yield from $this->getPhoneConfig();
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['signup_ok'], \danog\MadelineProto\Logger::NOTICE);
        $this->startUpdateSystem();
        return $this->authorization;
    }
    /**
     * Complete 2FA login.
     *
     * @param string $password Password
     *
     * @return \Generator
     */
    public function complete2faLogin(string $password) : \Generator
    {
        if ($this->authorized !== MTProto::WAITING_PASSWORD) {
            throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['2fa_uncalled']);
        }
        $this->authorized = MTProto::NOT_LOGGED_IN;
        $hasher = new PasswordCalculator($this->logger);
        $hasher->addInfo(yield from $this->methodCallAsyncRead('account.getPassword', []));
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_user'], \danog\MadelineProto\Logger::NOTICE);
        $this->authorization = (yield from $this->methodCallAsyncRead('auth.checkPassword', ['password' => $hasher->getCheckPassword($password)]));
        $this->authorized = MTProto::LOGGED_IN;
        $this->datacenter->getDataCenterConnection($this->datacenter->curdc)->authorized(true);
        yield from $this->initAuthorization();
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['login_ok'], \danog\MadelineProto\Logger::NOTICE);
        yield from $this->getPhoneConfig();
        $this->startUpdateSystem();
        return $this->authorization;
    }
    /**
     * Update the 2FA password.
     *
     * The params array can contain password, new_password, email and hint params.
     *
     * @param array $params The params
     *
     * @return \Generator
     */
    public function update2fa(array $params) : \Generator
    {
        $hasher = new PasswordCalculator($this->logger);
        $hasher->addInfo(yield from $this->methodCallAsyncRead('account.getPassword', []));
        return yield from $this->methodCallAsyncRead('account.updatePasswordSettings', $hasher->getPassword($params));
    }
}<?php

/**
 * TOS module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

/**
 * Manages terms of service.
 */
trait TOS
{
    /**
     * Check for terms of service update.
     *
     * @return \Generator
     */
    public function checkTos() : \Generator
    {
        if ($this->authorized === self::LOGGED_IN && !$this->authorization['user']['bot']) {
            if ($this->tos['expires'] < \time()) {
                $this->logger->logger('Fetching TOS...');
                $this->tos = (yield from $this->methodCallAsyncRead('help.getTermsOfServiceUpdate', []));
                $this->tos['accepted'] = $this->tos['_'] === 'help.termsOfServiceUpdateEmpty';
            }
            if (!$this->tos['accepted']) {
                $this->logger->logger('Telegram has updated their Terms Of Service', \danog\MadelineProto\Logger::ERROR);
                $this->logger->logger('Accept the TOS before proceeding by calling $MadelineProto->acceptTos().', \danog\MadelineProto\Logger::ERROR);
                $this->logger->logger('You can also decline the TOS by calling $MadelineProto->declineTos().', \danog\MadelineProto\Logger::ERROR);
                $this->logger->logger('By declining the TOS, the currently logged in account will be PERMANENTLY DELETED.', \danog\MadelineProto\Logger::FATAL_ERROR);
                $this->logger->logger('Read the following TOS very carefully: ', \danog\MadelineProto\Logger::ERROR);
                $this->logger->logger($this->tos);
                throw new \danog\MadelineProto\Exception('TOS action required, check the logs', 0, null, 'MadelineProto', 1);
            }
        }
    }
    /**
     * Accept terms of service update.
     *
     * @return \Generator
     */
    public function acceptTos() : \Generator
    {
        $this->tos['accepted'] = (yield from $this->methodCallAsyncRead('help.acceptTermsOfService', ['id' => $this->tos['terms_of_service']['id']]));
        if ($this->tos['accepted']) {
            $this->logger->logger('TOS accepted successfully');
        } else {
            throw new \danog\MadelineProto\Exception('An error occurred while accepting the TOS');
        }
    }
    /**
     * Decline terms of service update.
     *
     * THIS WILL DELETE YOUR ACCOUNT!
     *
     * @return \Generator
     */
    public function declineTos() : \Generator
    {
        yield from $this->methodCallAsyncRead('account.deleteAccount', ['reason' => 'Decline ToS update']);
        yield from $this->logout();
    }
}<?php

/**
 * Ads module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use danog\MadelineProto\Db\DbArray;
/**
 * Manages ads.
 *
 * @property DbArray $sponsoredMessages
 */
trait Ads
{
    /**
    * Get sponsored messages for channel.
    This method will return an array of [sponsored message objects](https://docs.madelineproto.xyz/API_docs/constructors/sponsoredMessage.html).
    *
    * See [the API documentation](https://core.telegram.org/api/sponsored-messages) for more info on how to handle sponsored messages.
    *
    * @param (int | array) $peer Channel ID, or Update, or Message, or Peer.
    * @return \Generator
    */
    public function getSponsoredMessages($peer) : \Generator
    {
        $peer = (yield from $this->getInfo($peer))['bot_api_id'];
        $cache = (yield $this->sponsoredMessages[$peer]);
        if ($cache && $cache[0] < \time()) {
            return $cache[1];
        }
        $result = (yield from $this->methodCallAsyncRead('channels.getSponsoredMessages', ['channel' => $peer]))['messages'];
        $this->sponsoredMessages->set($peer, [\time() + 5 * 60, $result]);
        return $result;
    }
    /**
     * Mark sponsored message as read.
     *
     * @param (int | array) $peer Channel ID, or Update, or Message, or Peer.
     * @param (string | array{random_id: string}) $message Random ID or sponsored message to mark as read.
     *
     * @return \Generator Bool
     */
    public function viewSponsoredMessage($peer, $message) : \Generator
    {
        if (\is_array($message)) {
            $message = $message['random_id'];
        }
        return $this->methodCallAsyncRead('channels.viewSponsoredMessage', ['channel' => $peer, 'random_id' => $message]);
    }
}<?php

/**
 * Callback module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

/**
 * Manages logging in and out.
 */
trait Callback
{
    /**
     * Set update handling callback.
     *
     * @param callable $callback Callback
     *
     * @return void
     */
    public function setCallback($callback) : void
    {
        $this->updateHandler = $callback;
        $this->startUpdateSystem();
    }
}<?php

/**
 * Templates module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use danog\MadelineProto\MTProto;
use danog\MadelineProto\Ipc\Client;
use danog\MadelineProto\Lang;
use function Amp\ByteStream\getOutputBufferStream;
trait Templates
{
    /**
     * Echo page to console.
     *
     * @param string $message Error message
     *
     * @return \Generator
     */
    private function webEcho(string $message = '') : \Generator
    {
        $auth = (yield $this->getAuthorization());
        $form = null;
        if ($auth === MTProto::NOT_LOGGED_IN) {
            if (isset($_POST['type'])) {
                if ($_POST['type'] === 'phone') {
                    $title = \str_replace(':', '', Lang::$current_lang['loginUser']);
                    $phone = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['loginUserPhoneWeb']);
                    $form = "<input type='text' name='phone_number' placeholder='{$phone}' required/>";
                } else {
                    $title = \str_replace(':', '', Lang::$current_lang['loginBot']);
                    $token = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['loginBotTokenWeb']);
                    $form = "<input type='text' name='token' placeholder='{$token}' required/>";
                }
            } else {
                $title = Lang::$current_lang['loginChoosePromptWeb'];
                $optionBot = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['loginOptionBot']);
                $optionUser = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['loginOptionUser']);
                $form = "<select name='type'><option value='phone'>{$optionUser}</option><option value='bot'>{$optionBot}</option></select>";
            }
        } elseif ($auth === MTProto::WAITING_CODE) {
            $title = \str_replace(':', '', Lang::$current_lang['loginUserCode']);
            $phone = \Phabel\Target\Php80\Polyfill::htmlentities(Lang::$current_lang['loginUserPhoneCodeWeb']);
            $form = "<input type='text' name='phone_code' placeholder='{$phone}' required/>";
        } elseif ($auth === MTProto::WAITING_PASSWORD) {
            $title = Lang::$current_lang['loginUserPassWeb'];
            $hint = \Phabel\Target\Php80\Polyfill::htmlentities(\sprintf(
                Lang::$current_lang['loginUserPassHint'],
                /** @psalm-suppress InvalidIterator */
                $this instanceof Client ? yield from $this->getHint() : $this->getHint()
            ));
            $form = "<input type='password' name='password' placeholder='{$hint}' required/>";
        } elseif ($auth === MTProto::WAITING_SIGNUP) {
            $title = Lang::$current_lang['signupWeb'];
            $firstName = Lang::$current_lang['signupFirstNameWeb'];
            $lastName = Lang::$current_lang['signupLastNameWeb'];
            $form = "<input type='text' name='first_name' placeholder='{$firstName}' required/><input type='text' name='last_name' placeholder='{$lastName}'/>";
        } else {
            return;
        }
        $title = \Phabel\Target\Php80\Polyfill::htmlentities($title);
        $message = \Phabel\Target\Php80\Polyfill::htmlentities($message);
        return getOutputBufferStream()->write($this->webEchoTemplate("{$title}<br><b>{$message}</b>", $form));
    }
    /**
     * Web template.
     *
     * @var string
     */
    private $webTemplate = 'legacy';
    /**
     * Format message according to template.
     *
     * @param string $message Message
     * @param string $form Form contents
     *
     * @return string
     */
    private function webEchoTemplate(string $message, string $form) : string
    {
        return \sprintf($this->webTemplate, $message, $form, Lang::$current_lang['go']);
    }
    /**
     * Get web template.
     *
     * @return string
     */
    public function getWebTemplate() : string
    {
        return $this->webTemplate;
    }
    /**
     * Set web template.
     *
     * @param string $template Template
     *
     * @return void
     */
    public function setWebTemplate(string $template) : void
    {
        $this->webTemplate = $template;
    }
}<?php

/**
 * Callback module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use Amp\Promise;
use danog\MadelineProto\Tools;
/**
 * Manages clicking buttons.
 */
trait Button
{
    /**
     * Click on button.
     *
     * @internal
     *
     * @param bool $donotwait
     * @param string $method
     * @param array $parameters
     *
     * @return (Promise | true)
     */
    public function clickInternal(bool $donotwait, string $method, array $parameters)
    {
        $internal = $donotwait ? 'methodCallAsyncWrite' : 'methodCallAsyncRead';
        $result = $this->{$internal}($method, $parameters);
        if ($donotwait) {
            Tools::callFork($result);
        }
        return $donotwait ? true : $result;
    }
}<?php

/**
 * Webhook module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use Amp\Http\Client\Request;
use danog\MadelineProto\Settings;
/**
 * Manages logging in and out.
 *
 * @property Settings $settings
 */
trait Webhook
{
    /**
     * Set webhook update handler.
     *
     * @param string $hook_url Webhook URL
     * @param string $pem_path PEM path for self-signed certificate
     *
     * @return void
     */
    public function setWebhook(string $hook_url, string $pem_path = '') : void
    {
        $this->pem_path = $pem_path;
        $this->hook_url = $hook_url;
        $this->updateHandler = [$this, 'pwrWebhook'];
        $this->startUpdateSystem();
    }
    /**
     * Send update to webhook.
     *
     * @param array $update Update
     *
     * @return void
     */
    private function pwrWebhook(array $update) : void
    {
        $payload = \json_encode($update);
        if ($payload === '') {
            $this->logger->logger($update, $payload, \json_last_error_msg());
            $this->logger->logger('EMPTY UPDATE');
            return;
        }
        \danog\MadelineProto\Tools::callFork((function () use($payload) : \Generator {
            $request = new Request($this->hook_url, 'POST');
            $request->setHeader('content-type', 'application/json');
            $request->setBody($payload);
            $result = (yield ((yield $this->datacenter->getHTTPClient()->request($request)))->getBody()->buffer());
            $this->logger->logger('Result of webhook query is ' . $result, \danog\MadelineProto\Logger::NOTICE);
            $result = \json_decode($result, true);
            if (\is_array($result) && isset($result['method']) && $result['method'] != '' && \is_string($result['method'])) {
                try {
                    $this->logger->logger('Reverse webhook command returned', yield from $this->methodCallAsyncRead($result['method'], $result));
                } catch (\Throwable $e) {
                    $this->logger->logger("Reverse webhook command returned: {$e}");
                }
            }
        })());
    }
}<?php

/**
 * Loop module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use Amp\Loop as AmpLoop;
use Amp\Promise;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Shutdown;
use danog\MadelineProto\Tools;
/**
 * Manages logging in and out.
 *
 * @property Settings $settings Settings
 */
trait Loop
{
    private $loop_callback;
    /**
     * Whether to stop the loop.
     *
     * @var boolean
     */
    private $stopLoop = false;
    /**
     * Initialize self-restart hack.
     *
     * @return void
     */
    public function initSelfRestart() : void
    {
        static $inited = false;
        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg' && !$inited) {
            $needs_restart = true;
            try {
                if (\function_exists('set_time_limit')) {
                    \set_time_limit(-1);
                }
            } catch (\danog\MadelineProto\Exception $e) {
                $needs_restart = true;
            }
            if (isset($_REQUEST['MadelineSelfRestart'])) {
                $this->logger->logger("Self-restarted, restart token " . $_REQUEST['MadelineSelfRestart']);
            }
            $this->logger->logger($needs_restart ? 'Will self-restart' : 'Will not self-restart');
            if ($needs_restart) {
                $this->logger->logger("Adding restart callback!");
                $logger = $this->logger;
                $id = Shutdown::addCallback(static function () use(&$logger) {
                    $address = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'tls' : 'tcp') . '://' . $_SERVER['SERVER_NAME'];
                    $port = $_SERVER['SERVER_PORT'];
                    $uri = $_SERVER['REQUEST_URI'];
                    $params = $_GET;
                    $params['MadelineSelfRestart'] = Tools::randomInt();
                    $url = \explode('?', $uri, 2)[0] ?? '';
                    $query = \http_build_query($params);
                    $uri = \implode('?', [$url, $query]);
                    $payload = $_SERVER['REQUEST_METHOD'] . ' ' . $uri . ' HTTP/1.1
Host: ' . $_SERVER['SERVER_NAME'] . "\r\n\r\n";
                    $logger->logger("Connecting to {$address}:{$port}");
                    $a = \Phabel\Target\Php80\Polyfill::fsockopen($address, $port);
                    $logger->logger("Sending self-restart payload");
                    $logger->logger($payload);
                    \fwrite($a, $payload);
                    $logger->logger("Payload sent with token {$params['MadelineSelfRestart']}, waiting for self-restart");
                    // Keep around resource for a bit more
                    $GLOBALS['MadelineShutdown'] = $a;
                    $logger->logger("Shutdown of self-restart callback");
                }, 'restarter');
                $this->logger->logger("Added restart callback with ID {$id}!");
            }
            $this->logger->logger("Done webhost init process!");
            Tools::closeConnection($this->getWebMessage("The bot was started!"));
            $inited = true;
        } elseif (PHP_SAPI === 'cli') {
            try {
                if (\function_exists('shell_exec') && \file_exists('/data/data/com.termux/files/usr/bin/termux-wake-lock')) {
                    \shell_exec('/data/data/com.termux/files/usr/bin/termux-wake-lock');
                }
            } catch (\Throwable $e) {
            }
        }
    }
    /**
     * Start MadelineProto's update handling loop, or run the provided async callable.
     *
     * @param (callable | null) $callback Async callable to run
     *
     * @return \Generator
     */
    public function loop($callback = null) : \Generator
    {
        if (\is_callable($callback)) {
            $this->logger->logger('Running async callable');
            return (yield $callback());
        }
        if ($callback instanceof Promise) {
            $this->logger->logger('Resolving async promise');
            return (yield $callback);
        }
        if (!$this->authorized) {
            $this->logger->logger('Not authorized, not starting event loop', \danog\MadelineProto\Logger::FATAL_ERROR);
            return false;
        }
        if ($this->updateHandler === self::GETUPDATES_HANDLER) {
            $this->logger->logger('Getupdates event handler is enabled, exiting from loop', \danog\MadelineProto\Logger::FATAL_ERROR);
            return false;
        }
        $this->logger->logger('Starting event loop');
        if (!\is_callable($this->loop_callback)) {
            $this->loop_callback = null;
        }
        $this->initSelfRestart();
        $this->startUpdateSystem();
        $this->logger->logger('Started update loop', \danog\MadelineProto\Logger::NOTICE);
        $this->stopLoop = false;
        if ($this->loop_callback !== null) {
            $repeat = AmpLoop::repeat(1000, fn() => Tools::callFork(($this->loop_callback)()));
        }
        do {
            if (!$this->updateHandler) {
                (yield $this->waitUpdate());
                if (!$this->updateHandler) {
                    $this->logger->logger('Exiting update loop, no handler!', \danog\MadelineProto\Logger::NOTICE);
                    continue;
                }
            }
            while ($this->updates) {
                $updates = $this->updates;
                $this->updates = [];
                foreach ($updates as $update) {
                    $r = ($this->updateHandler)($update);
                    if (\is_object($r)) {
                        \danog\MadelineProto\Tools::callFork($r);
                    }
                }
                $updates = [];
            }
            (yield $this->waitUpdate());
            $this->logger->logger('Resuming update loop!', \danog\MadelineProto\Logger::VERBOSE);
        } while (!$this->stopLoop);
        $this->logger->logger('Exiting update loop!', \danog\MadelineProto\Logger::NOTICE);
        $this->stopLoop = false;
        if (isset($repeat)) {
            AmpLoop::cancel($repeat);
        }
    }
    /**
     * Stop update loop.
     *
     * @return void
     */
    public function stop()
    {
        \danog\MadelineProto\Shutdown::removeCallback('restarter');
        $this->restart();
    }
    /**
     * Restart update loop.
     *
     * @return void
     */
    public function restart()
    {
        $this->stopLoop = true;
        $this->signalUpdate();
    }
    /**
     * Start MadelineProto's update handling loop in background.
     *
     * @return Promise
     */
    public function loopFork() : Promise
    {
        return Tools::callFork($this->loop());
    }
}<?php

/**
 * Events module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\Wrappers;

use danog\MadelineProto\EventHandler;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools;
/**
 * Event handler.
 *
 * @property Settings $settings Settings
 */
trait Events
{
    /**
     * Event handler class name.
     *
     * @var class-string<EventHandler>
     */
    public $event_handler;
    /**
     * Event handler instance.
     *
     * @var EventHandler|null
     */
    private $event_handler_instance;
    /**
     * Event handler method list.
     *
     * @var array<string, callable>
     */
    private $eventHandlerMethods = [];
    /**
     * Initialize event handler.
     *
     * @param class-string<EventHandler> $eventHandler
     *
     * @return void
     */
    private function initEventHandler(string $eventHandler) : void
    {
        $this->event_handler = $eventHandler;
        if (!\Phabel\Plugin\NewFixer::instanceOf($this->event_handler_instance, $this->event_handler)) {
            $class_name = $this->event_handler;
            $this->event_handler_instance = new $class_name($this->wrapper);
        }
        $this->event_handler_instance->initInternal($this->wrapper);
    }
    /**
     * Set event handler.
     *
     * @param class-string<EventHandler> $eventHandler Event handler
     *
     * @return \Generator
     */
    public function setEventHandler(string $eventHandler) : \Generator
    {
        if (!\is_subclass_of($eventHandler, EventHandler::class)) {
            throw new \danog\MadelineProto\Exception('Wrong event handler was defined');
        }
        $this->initEventHandler($eventHandler);
        $this->eventHandlerMethods = [];
        $this->loop_callback = null;
        foreach (\get_class_methods($this->event_handler) as $method) {
            if ($method === 'onLoop') {
                $this->loop_callback = [$this->event_handler_instance, 'onLoop'];
            } elseif ($method === 'onAny') {
                foreach ($this->getTL()->getConstructors()->by_id as $constructor) {
                    if ($constructor['type'] === 'Update' && !isset($this->eventHandlerMethods[$constructor['predicate']])) {
                        $this->eventHandlerMethods[$constructor['predicate']] = [$this->event_handler_instance, 'onAny'];
                    }
                }
            } else {
                $method_name = \lcfirst(\Phabel\Target\Php80\Polyfill::substr($method, 2));
                if (($constructor = $this->getTL()->getConstructors()->findByPredicate($method_name)) && $constructor['type'] === 'Update') {
                    $this->eventHandlerMethods[$method_name] = [$this->event_handler_instance, $method];
                }
            }
        }
        yield from $this->setReportPeers($this->event_handler_instance->getReportPeers());
        Tools::callFork($this->event_handler_instance->startInternal());
        $this->updateHandler = [$this, 'eventUpdateHandler'];
        if ($this->inited()) {
            $this->startUpdateSystem();
        }
    }
    /**
     * Unset event handler.
     *
     * @param bool $disableUpdateHandling Whether to also disable internal update handling (will cause errors, otherwise will simply use the NOOP handler)
     *
     * @return void
     */
    public function unsetEventHandler(bool $disableUpdateHandling = false) : void
    {
        $this->event_handler = null;
        $this->event_handler_instance = null;
        $this->eventHandlerMethods = [];
        $this->setNoop();
    }
    /**
     * Get event handler.
     *
     * @return EventHandler
     */
    public function getEventHandler() : EventHandler
    {
        return $this->event_handler_instance;
    }
    /**
     * Check if an event handler instance is present.
     *
     * @return boolean
     */
    public function hasEventHandler() : bool
    {
        return isset($this->event_handler_instance);
    }
    /**
     * Event update handler.
     *
     * @param array $update Update
     *
     * @return void
     *
     * @internal Internal event handler
     */
    public function eventUpdateHandler(array $update)
    {
        if (isset($this->eventHandlerMethods[$update['_']])) {
            return $this->eventHandlerMethods[$update['_']]($update);
        }
    }
}<?php

/**
 * Snitch module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * Snitch.
 */
class Snitch
{
    /**
     * Maximum starts without a phar file.
     */
    const MAX_NO_PHAR_STARTS = 3;
    /**
     * Maximum starts without a logfile.
     */
    const MAX_NO_LOG_STARTS = 3;
    /**
     * Whether madeline.phar was downloaded from scratch.
     */
    private array $hadInstalled = [];
    /**
     * Whether logs were enabled.
     */
    private array $hadLog = [];
    /**
     * Whether we currently have a logfile.
     */
    private static bool $hasLog = true;
    /**
     * Whether we checked the logfile.
     */
    private static int $snitchedLog = 0;
    /**
     * Snitch on logfile.
     *
     * @param string $file Logfile
     *
     * @return void
     */
    public static function logFile(string $file)
    {
        if (self::$snitchedLog) {
            return;
        }
        self::$snitchedLog = 1;
        \clearstatcache(true, $file);
        self::$hasLog = \file_exists($file);
    }
    /**
     * Called before serialization.
     *
     * @return array
     */
    public function __sleep()
    {
        if (self::$snitchedLog === 1) {
            $this->hadLog[] = self::$hasLog;
            if (\count($this->hadLog) > self::MAX_NO_LOG_STARTS) {
                \array_shift($this->hadLog);
                if (!\array_sum($this->hadLog)) {
                    // For three times, MadelineProto was started with no logfile
                    $this->die();
                }
            }
            self::$snitchedLog++;
        }
        return ['hadInstalled', 'hadLog'];
    }
    /**
     * Wakeup function.
     */
    public function __wakeup()
    {
        if (\defined('HAD_MADELINE_PHAR')) {
            $this->hadInstalled[] = \HAD_MADELINE_PHAR;
            if (\count($this->hadInstalled) > self::MAX_NO_PHAR_STARTS) {
                \array_shift($this->hadInstalled);
                if (!\array_sum($this->hadInstalled)) {
                    // For three times, MadelineProto was started with no phar file
                    $this->die();
                }
            }
        }
    }
    /**
     * Die.
     *
     * @return void
     */
    private function die() : void
    {
        Shutdown::removeCallback('restarter');
        $message = "Please do not remove madeline.phar, madeline.php and MadelineProto.log, or else MadelineProto will crash. If you have any problem with MadelineProto, report it to https://github.com/danog/MadelineProto or https://t.me/pwrtelegramgroup";
        Logger::log($message, Logger::FATAL_ERROR);
        \file_put_contents(Magic::$cwd . DIRECTORY_SEPARATOR . 'DO_NOT_REMOVE_MADELINEPROTO_LOG_SESSION', $message);
        die("{$message}\n");
    }
}<?php

namespace danog\MadelineProto;

use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Loop;
use danog\Loop\Generic\PeriodicLoop;
final class GarbageCollector
{
    /**
    * Ensure only one instance of GarbageCollector
    when multiple instances of MadelineProto running.
    * @var bool
    */
    public static bool $lock = false;
    /**
     * How often will check memory.
     * @var int
     */
    public static int $checkIntervalMs = 1000;
    /**
     * Next cleanup will be triggered when memory consumption will increase by this amount.
     * @var int
     */
    public static int $memoryDiffMb = 1;
    /**
     * Memory consumption after last cleanup.
     * @var int
     */
    private static int $memoryConsumption = 0;
    /**
     * Phar cleanup loop.
     *
     * @var PeriodicLoop
     */
    private static PeriodicLoop $cleanupLoop;
    /**
     *
     */
    public static function start() : void
    {
        if (self::$lock) {
            return;
        }
        self::$lock = true;
        Loop::repeat(self::$checkIntervalMs, static function () {
            $currentMemory = self::getMemoryConsumption();
            if ($currentMemory > self::$memoryConsumption + self::$memoryDiffMb) {
                \gc_collect_cycles();
                self::$memoryConsumption = self::getMemoryConsumption();
                $cleanedMemory = $currentMemory - self::$memoryConsumption;
                if (!Magic::$suspendPeriodicLogging) {
                    Logger::log("gc_collect_cycles done. Cleaned memory: {$cleanedMemory} Mb", Logger::VERBOSE);
                }
            }
        });
        if (!\defined('MADELINE_RELEASE_URL')) {
            return;
        }
        $client = HttpClientBuilder::buildDefault();
        $request = new Request(MADELINE_RELEASE_URL);
        self::$cleanupLoop = new PeriodicLoop(function () use($client, $request) : \Generator {
            try {
                $latest = (yield $client->request($request));
                Magic::$version_latest = (yield $latest->getBody()->buffer());
                if (Magic::$version !== Magic::$version_latest) {
                    Logger::log("!!!!!!!!!!!!! An update of MadelineProto is required, shutting down worker! !!!!!!!!!!!!!", Logger::FATAL_ERROR);
                    self::$cleanupLoop->signal(true);
                    if (Magic::$isIpcWorker) {
                        die;
                    }
                    return;
                }
                foreach (\glob(MADELINE_PHAR_GLOB) as $path) {
                    $base = \basename($path);
                    if ($base === "madeline-" . Magic::$version . ".phar") {
                        continue;
                    }
                    $f = \fopen("{$path}.lock", 'c');
                    if (\flock($f, LOCK_EX | LOCK_NB)) {
                        \fclose($f);
                        \unlink($path);
                        \unlink("{$path}.lock");
                    } else {
                        \fclose($f);
                    }
                }
            } catch (\Throwable $e) {
                Logger::log("An error occurred in the phar cleanup loop: {$e}", Logger::FATAL_ERROR);
            }
        }, "Phar cleanup loop", 60 * 1000);
        self::$cleanupLoop->start();
    }
    /**
     *
     */
    private static function getMemoryConsumption() : int
    {
        $memory = \round(\memory_get_usage() / 1024 / 1024, 1);
        if (!Magic::$suspendPeriodicLogging) {
            Logger::log("Memory consumption: {$memory} Mb", Logger::ULTRA_VERBOSE);
        }
        return (int) $memory;
    }
}<?php

/**
 * SecurityException module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

/**
 * Indicates a security error.
 */
class SecurityException extends \Exception
{
}<?php

namespace danog\MadelineProto;

class SettingsEmpty extends SettingsAbstract
{
    /**
     *
     */
    public function mergeArray(array $settings) : void
    {
    }
}<?php

namespace danog\MadelineProto;

use Psr\Log\AbstractLogger;
use Psr\Log\LogLevel;
/**
 * PSR-3 wrapper for MadelineProto's Logger.
 */
class PsrLogger extends AbstractLogger
{
    private const LEVEL_MAP = [LogLevel::EMERGENCY => Logger::LEVEL_FATAL, LogLevel::ALERT => Logger::LEVEL_FATAL, LogLevel::CRITICAL => Logger::LEVEL_FATAL, LogLevel::ERROR => Logger::LEVEL_ERROR, LogLevel::WARNING => Logger::LEVEL_WARNING, LogLevel::NOTICE => Logger::LEVEL_NOTICE, LogLevel::INFO => Logger::LEVEL_VERBOSE, LogLevel::DEBUG => Logger::LEVEL_ULTRA_VERBOSE];
    /**
     * Logger.
     */
    private Logger $logger;
    /**
     * Constructor.
     *
     * @param Logger $logger
     */
    public function __construct(Logger $logger)
    {
        $this->logger = $logger;
    }
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = []) : void
    {
        $this->logger->logger($message, self::LEVEL_MAP[$level]);
    }
}<?php

/**
 * Conversion module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use danog\MadelineProto\MTProtoTools\Crypt;
class Conversion
{
    /**
     * Prepare API instance.
     *
     * @param array<int, string> $authorization Authorization info
     * @param int $main_dc_id
     * @param string $session
     * @param (SettingsAbstract | array) $settings
     *
     * @return \Generator<mixed, mixed, mixed, API>
     */
    public static function importAuthorization(array $authorization, int $main_dc_id, string $session, $settings) : \Generator
    {
        $settings = Settings::parseFromLegacyFull($settings);
        $settings->getIpc()->setSlow(true);
        $settings->getLogger()->setLevel(Logger::ULTRA_VERBOSE);
        $settings->getAuth()->setPfs(true);
        $MadelineProto = new \danog\MadelineProto\API($session, $settings);
        (yield $MadelineProto->help->getConfig());
        (yield $MadelineProto->logger("About to import auth!", Logger::FATAL_ERROR));
        (yield $MadelineProto->importAuthorization($authorization, $main_dc_id));
        return $MadelineProto;
    }
    /**
     *
     */
    public static function telethon(string $session, string $new_session, $settings = []) : \Generator
    {
        if (!\extension_loaded('sqlite3')) {
            throw new Exception(['extension', 'sqlite3']);
        }
        if (!isset(\pathinfo($session)['extension'])) {
            $session .= '.session';
        }
        $session = Tools::absolute($session);
        $sqlite = new \PDO("sqlite:{$session}");
        $sqlite->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
        $sessions = $sqlite->query('SELECT * FROM sessions')->fetchAll();
        $dcs = [];
        foreach ($sessions as $dc) {
            $dcs[$dc['dc_id']] = $dc['auth_key'];
        }
        return self::importAuthorization($dcs, $dc['dc_id'], $new_session, $settings);
    }
    /**
     *
     */
    public static function pyrogram(string $session, string $new_session, $settings = []) : \Generator
    {
        \set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
        if (!isset(\pathinfo($session)['extension'])) {
            $session .= '.session';
        }
        $session = Tools::absolute($session);
        $session = \json_decode(\file_get_contents($session), true);
        $session['auth_key'] = \base64_decode(\implode('', $session['auth_key']));
        $settings['connection_settings']['all']['test_mode'] = $session['test_mode'];
        return self::importAuthorization([$session['dc_id'] => $session['auth_key']], $session['dc_id'], $new_session, $settings);
    }
    /**
     *
     */
    public static function zerobias($session, $new_session, $settings = [])
    {
        \set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
        if (\is_string($session)) {
            $session = \json_decode($session, true);
        }
        $dc = $session['dc'];
        $key = \hex2bin($session["dc{$dc}" . '_auth_key']);
        return yield from self::importAuthorization([$dc => $key], $dc, $new_session, $settings);
    }
    /**
     *
     */
    public static function tdesktop_md5($data)
    {
        $result = '';
        foreach (\str_split(\md5($data), 2) as $byte) {
            $result .= \strrev($byte);
        }
        return \strtoupper($result);
    }
    const FILEOPTION_SAFE = 1;
    const FILEOPTION_USER = 2;
    public static $tdesktop_base_path;
    public static $tdesktop_user_base_path;
    public static $tdesktop_key;
    /**
     *
     */
    public static function tdesktop_fopen($fileName, $options = self::FILEOPTION_SAFE | self::FILEOPTION_USER)
    {
        $name = ($options & self::FILEOPTION_USER ? self::$tdesktop_user_base_path : self::$tdesktop_base_path) . $fileName;
        $totry = [];
        foreach (['0', '1', 's'] as $x) {
            if (\file_exists($name . $x)) {
                $totry[] = \fopen($name . $x, 'rb');
            }
        }
        foreach ($totry as $fp) {
            if (\stream_get_contents($fp, 4) !== 'TDF$') {
                \danog\MadelineProto\Logger::log('Wrong magic', Logger::ERROR);
                continue;
            }
            $versionBytes = \stream_get_contents($fp, 4);
            $version = Tools::unpackSignedInt($versionBytes);
            \danog\MadelineProto\Logger::log("TDesktop version: {$version}");
            $data = \stream_get_contents($fp);
            $md5 = \Phabel\Target\Php80\Polyfill::substr($data, -16);
            $data = \Phabel\Target\Php80\Polyfill::substr($data, 0, -16);
            $length = \pack('l', \strlen($data));
            $length = \danog\MadelineProto\Magic::$BIG_ENDIAN ? \strrev($length) : $length;
            if (\md5($data . $length . $versionBytes . 'TDF$', true) !== $md5) {
                \danog\MadelineProto\Logger::log('Wrong MD5', Logger::ERROR);
            }
            $res = \fopen('php://memory', 'rw+b');
            \fwrite($res, $data);
            \fseek($res, 0);
            return $res;
        }
        throw new Exception("Could not open {$fileName}");
    }
    /**
     *
     */
    public static function tdesktop_fopen_encrypted($fileName, $options = 3)
    {
        $f = self::tdesktop_fopen($fileName, $options);
        $data = self::tdesktop_read_bytearray($f);
        $res = self::tdesktop_decrypt($data, self::$tdesktop_key);
        $length = \unpack('V', \stream_get_contents($res, 4))[1];
        if ($length > \fstat($res)['size'] || $length < 4) {
            throw new \danog\MadelineProto\Exception('Wrong length');
        }
        return $res;
    }
    /**
     *
     */
    public static function tdesktop_read_bytearray($fp, bool $asString = false)
    {
        $length = Tools::unpackSignedInt(\strrev(\stream_get_contents($fp, 4)));
        $data = $length > 0 ? \stream_get_contents($fp, $length) : '';
        if ($asString) {
            return $data;
        }
        $res = \fopen('php://memory', 'rw+b');
        \fwrite($res, $data);
        \fseek($res, 0);
        return $res;
    }
    /**
     *
     */
    public static function tdesktop_decrypt($data, $auth_key)
    {
        $message_key = \stream_get_contents($data, 16);
        $encrypted_data = \stream_get_contents($data);
        list($aes_key, $aes_iv) = Crypt::oldAesCalculate($message_key, $auth_key, false);
        $decrypted_data = Crypt::igeDecrypt($encrypted_data, $aes_key, $aes_iv);
        if ($message_key != \Phabel\Target\Php80\Polyfill::substr(\sha1($decrypted_data, true), 0, 16)) {
            throw new \danog\MadelineProto\SecurityException('msg_key mismatch');
        }
        $res = \fopen('php://memory', 'rw+b');
        \fwrite($res, $decrypted_data);
        \fseek($res, 0);
        return $res;
    }
    const dbiKey = 0x0;
    const dbiUser = 0x1;
    const dbiDcOptionOldOld = 0x2;
    const dbiChatSizeMax = 0x3;
    const dbiMutePeer = 0x4;
    const dbiSendKey = 0x5;
    const dbiAutoStart = 0x6;
    const dbiStartMinimized = 0x7;
    const dbiSoundNotify = 0x8;
    const dbiWorkMode = 0x9;
    const dbiSeenTrayTooltip = 0xa;
    const dbiDesktopNotify = 0xb;
    const dbiAutoUpdate = 0xc;
    const dbiLastUpdateCheck = 0xd;
    const dbiWindowPosition = 0xe;
    const dbiConnectionTypeOld = 0xf;
    // 0x10 reserved
    const dbiDefaultAttach = 0x11;
    const dbiCatsAndDogs = 0x12;
    const dbiReplaceEmojis = 0x13;
    const dbiAskDownloadPath = 0x14;
    const dbiDownloadPathOld = 0x15;
    const dbiScale = 0x16;
    const dbiEmojiTabOld = 0x17;
    const dbiRecentEmojiOldOld = 0x18;
    const dbiLoggedPhoneNumber = 0x19;
    const dbiMutedPeers = 0x1a;
    // 0x1b reserved
    const dbiNotifyView = 0x1c;
    const dbiSendToMenu = 0x1d;
    const dbiCompressPastedImage = 0x1e;
    const dbiLangOld = 0x1f;
    const dbiLangFileOld = 0x20;
    const dbiTileBackground = 0x21;
    const dbiAutoLock = 0x22;
    const dbiDialogLastPath = 0x23;
    const dbiRecentEmojiOld = 0x24;
    const dbiEmojiVariantsOld = 0x25;
    const dbiRecentStickers = 0x26;
    const dbiDcOptionOld = 0x27;
    const dbiTryIPv6 = 0x28;
    const dbiSongVolume = 0x29;
    const dbiWindowsNotificationsOld = 0x30;
    const dbiIncludeMuted = 0x31;
    const dbiMegagroupSizeMax = 0x32;
    const dbiDownloadPath = 0x33;
    const dbiAutoDownload = 0x34;
    const dbiSavedGifsLimit = 0x35;
    const dbiShowingSavedGifsOld = 0x36;
    const dbiAutoPlay = 0x37;
    const dbiAdaptiveForWide = 0x38;
    const dbiHiddenPinnedMessages = 0x39;
    const dbiRecentEmoji = 0x3a;
    const dbiEmojiVariants = 0x3b;
    const dbiDialogsMode = 0x40;
    const dbiModerateMode = 0x41;
    const dbiVideoVolume = 0x42;
    const dbiStickersRecentLimit = 0x43;
    const dbiNativeNotifications = 0x44;
    const dbiNotificationsCount = 0x45;
    const dbiNotificationsCorner = 0x46;
    const dbiThemeKey = 0x47;
    const dbiDialogsWidthRatioOld = 0x48;
    const dbiUseExternalVideoPlayer = 0x49;
    const dbiDcOptions = 0x4a;
    const dbiMtpAuthorization = 0x4b;
    const dbiLastSeenWarningSeenOld = 0x4c;
    const dbiAuthSessionSettings = 0x4d;
    const dbiLangPackKey = 0x4e;
    const dbiConnectionType = 0x4f;
    const dbiStickersFavedLimit = 0x50;
    const dbiSuggestStickersByEmoji = 0x51;
    const dbiEncryptedWithSalt = 333;
    const dbiEncrypted = 444;
    // 500-600 reserved
    const dbiVersion = 666;
    /**
     *
     */
    public static function tdesktop(string $session, string $new_session, $settings = [])
    {
        \set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
        $settings['old_session_key'] ??= 'data';
        $settings['old_session_passcode'] ??= '';
        if (\basename($session) !== 'tdata') {
            $session .= DIRECTORY_SEPARATOR . 'tdata';
        }
        list($part_one_md5, $part_two_md5) = \str_split(self::tdesktop_md5($settings['old_session_key']), 16);
        self::$tdesktop_base_path = $session . DIRECTORY_SEPARATOR;
        self::$tdesktop_user_base_path = self::$tdesktop_base_path . $part_one_md5 . DIRECTORY_SEPARATOR;
        $data = self::tdesktop_fopen('map');
        $salt = self::tdesktop_read_bytearray($data, true);
        $encryptedKey = self::tdesktop_read_bytearray($data);
        if (\strlen($salt)) {
            $keyIterCount = \strlen($settings['old_session_passcode']) ? 4000 : 4;
            $passKey = \openssl_pbkdf2($settings['old_session_passcode'], $salt, 256, $keyIterCount);
            self::$tdesktop_key = \stream_get_contents(self::tdesktop_read_bytearray(self::tdesktop_decrypt($encryptedKey, $passKey)));
        } else {
            $key = 'key_' . $settings['old_session_key'];
            $data = self::tdesktop_fopen($key, self::FILEOPTION_SAFE);
            $salt = self::tdesktop_read_bytearray($data, true);
            if (\strlen($salt) !== 32) {
                throw new Exception("Length of salt is wrong!");
            }
            $encryptedKey = self::tdesktop_read_bytearray($data);
            $encryptedInfo = self::tdesktop_read_bytearray($data);
            $hash = \hash('sha512', $salt . $settings['old_session_passcode'] . $salt, true);
            $iterCount = \strlen($settings['old_session_passcode']) ? 100000 : 1;
            $passKey = \openssl_pbkdf2($hash, $salt, 256, $iterCount, 'sha512');
            $key = self::tdesktop_read_bytearray(self::tdesktop_decrypt($encryptedKey, $passKey), true);
            $info = self::tdesktop_read_bytearray(self::tdesktop_decrypt($encryptedInfo, $key));
            self::$tdesktop_key = $key;
            $count = Tools::unpackSignedInt(\strrev(\stream_get_contents($info, 4)));
            Logger::log("Number of accounts: {$count}");
            for ($i = 0; $i != $count; $i++) {
                $idx = Tools::unpackSignedInt(\strrev(\stream_get_contents($info, 4)));
                if ($idx >= 0) {
                    $dataName = $settings['old_session_key'];
                    if ($idx > 0) {
                        $dataName = $settings['old_session_key'] . '#' . ($idx + 1);
                    }
                    [$part_one_md5] = \str_split(self::tdesktop_md5($dataName), 16);
                }
            }
        }
        $main = self::tdesktop_fopen_encrypted($part_one_md5, self::FILEOPTION_SAFE);
        $auth_keys = [];
        while (!\feof($main)) {
            $magic = Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)));
            switch ($magic) {
                case self::dbiDcOptionOldOld:
                    \stream_get_contents($main, 4);
                    self::tdesktop_read_bytearray($main);
                    self::tdesktop_read_bytearray($main);
                    \stream_get_contents($main, 4);
                    break;
                case self::dbiDcOptionOld:
                    \stream_get_contents($main, 8);
                    self::tdesktop_read_bytearray($main);
                    \stream_get_contents($main, 4);
                    break;
                case self::dbiDcOptions:
                    self::tdesktop_read_bytearray($main);
                    break;
                case self::dbiUser:
                    \stream_get_contents($main, 4);
                    $main_dc_id = Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)));
                    break;
                case self::dbiKey:
                    $auth_keys[Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)))] = \stream_get_contents($main, 256);
                    break;
                case self::dbiMtpAuthorization:
                    $main = self::tdesktop_read_bytearray($main);
                    //stream_get_contents($main, 4);
                    $user_id = Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)));
                    $main_dc_id = Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)));
                    $length = Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)));
                    for ($x = 0; $x < $length; $x++) {
                        $dc = Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)));
                        $auth_key = \stream_get_contents($main, 256);
                        if ($dc <= 5) {
                            $auth_keys[$dc] = $auth_key;
                        }
                    }
                    break 2;
                case self::dbiAutoDownload:
                    \stream_get_contents($main, 12);
                    break;
                case self::dbiDialogsMode:
                    \stream_get_contents($main, 8);
                    break;
                case self::dbiAuthSessionSettings:
                    self::tdesktop_read_bytearray($main);
                    break;
                case self::dbiConnectionTypeOld:
                    switch (Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)))) {
                        case 2:
                        case 3:
                            self::tdesktop_read_bytearray($main);
                            \stream_get_contents($main, 4);
                            self::tdesktop_read_bytearray($main);
                            self::tdesktop_read_bytearray($main);
                            break;
                    }
                    break;
                case self::dbiConnectionType:
                    \stream_get_contents($main, 8);
                    self::tdesktop_read_bytearray($main);
                    \stream_get_contents($main, 4);
                    self::tdesktop_read_bytearray($main);
                    self::tdesktop_read_bytearray($main);
                    break;
                case self::dbiThemeKey:
                case self::dbiLangPackKey:
                case self::dbiMutePeer:
                    \stream_get_contents($main, 8);
                    break;
                case self::dbiWindowPosition:
                    \stream_get_contents($main, 24);
                    break;
                case self::dbiLoggedPhoneNumber:
                    self::tdesktop_read_bytearray($main);
                    break;
                case self::dbiMutedPeers:
                    $length = Tools::unpackSignedInt(\strrev(\stream_get_contents($main, 4)));
                    for ($x = 0; $x < $length; $x++) {
                        \stream_get_contents($main, 8);
                    }
                // no break
                case self::dbiDownloadPathOld:
                    self::tdesktop_read_bytearray($main);
                    break;
                case self::dbiDialogLastPath:
                    self::tdesktop_read_bytearray($main);
                    break;
                case self::dbiDownloadPath:
                    self::tdesktop_read_bytearray($main);
                    self::tdesktop_read_bytearray($main);
                    break;
                default:
                    throw new \Exception("Unknown type {$magic}");
                    break;
            }
        }
        return yield from self::importAuthorization($auth_keys, $main_dc_id, $new_session, $settings);
    }
}<?php

/**
 * AnnotationsBuilder module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Promise;
use danog\MadelineProto\Settings\TLSchema;
use danog\MadelineProto\TL\TL;
use danog\MadelineProto\TL\TLCallback;
use phpDocumentor\Reflection\DocBlockFactory;
class AnnotationsBuilder
{
    /**
     * Reflection classes.
     */
    private array $reflectionClasses = [];
    /**
     * Logger.
     */
    private Logger $logger;
    /**
     * Namespace.
     */
    private string $namespace;
    /**
     * TL instance.
     */
    private TL $TL;
    /**
     * Settings.
     */
    private array $settings;
    /**
     * Output file.
     */
    private string $output;
    /**
     *
     */
    public function __construct(Logger $logger, array $settings, string $output, array $reflectionClasses, string $namespace)
    {
        $this->reflectionClasses = $reflectionClasses;
        $this->logger = $logger;
        $this->namespace = $namespace;
        /** @psalm-suppress InvalidArgument */
        $this->TL = new TL(new class($logger)
        {
            /**
             *
             */
            public Logger $logger;
            /**
             *
             */
            public function __construct(Logger $logger)
            {
                $this->logger = $logger;
            }
        });
        $tlSchema = new TLSchema();
        $tlSchema->mergeArray($settings);
        $this->TL->init($tlSchema);
        $this->settings = $settings;
        $this->output = $output;
    }
    /**
     *
     */
    public function mkAnnotations() : void
    {
        \danog\MadelineProto\Logger::log('Generating annotations...', \danog\MadelineProto\Logger::NOTICE);
        $this->setProperties();
        $this->createInternalClasses();
    }
    /**
    * Open file of class APIFactory
    Insert properties
    save the file with new content.
    *
    * @return void
    */
    private function setProperties()
    {
        \danog\MadelineProto\Logger::log('Generating properties...', \danog\MadelineProto\Logger::NOTICE);
        $fixture = DocBlockFactory::createInstance();
        $class = new \ReflectionClass($this->reflectionClasses['APIFactory']);
        $content = \file_get_contents($filename = $class->getFileName());
        foreach ($class->getProperties() as $property) {
            if ($raw_docblock = $property->getDocComment()) {
                $docblock = $fixture->create($raw_docblock);
                if ($docblock->hasTag('internal')) {
                    $content = \str_replace("\n    " . $raw_docblock . "\n    public \$" . $property->getName() . ';', '', $content);
                }
            }
        }
        foreach ($this->TL->getMethodNamespaces() as $namespace) {
            $content = \preg_replace('/(class( \\w+[,]?){0,}\\n{\\n)/', '${1}    /**
     * @internal this is a internal property generated by build_docs.php, don\'t change manually
     *
' . "     * @var {$namespace}\n" . "     */\n" . "    public \${$namespace};\n", $content);
        }
        \file_put_contents($filename, $content);
    }
    /**
     * Create internalDoc.
     *
     * @return void
     */
    private function createInternalClasses() : void
    {
        \danog\MadelineProto\Logger::log('Creating internal classes...', \danog\MadelineProto\Logger::NOTICE);
        $handle = \fopen($this->output, 'w');
        \fwrite($handle, "<?php namespace {$this->namespace}; class InternalDoc extends APIFactory {}");
        $class = new \ReflectionClass($this->reflectionClasses['API']);
        $methods = $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC);
        $ignoreMethods = ['fetchserializableobject'];
        foreach ($methods as $method) {
            $ignoreMethods[$method->getName()] = $method->getName();
        }
        $class = new \ReflectionClass(TLCallback::class);
        $methods = $class->getMethods(\ReflectionMethod::IS_STATIC | \ReflectionMethod::IS_PUBLIC);
        foreach ($methods as $method) {
            $ignoreMethods[$method->getName()] = $method->getName();
        }
        \fclose($handle);
        $handle = \fopen($this->output, 'w');
        $internalDoc = [];
        foreach ($this->TL->getMethods()->by_id as $id => $data) {
            if (!\strpos($data['method'], '.')) {
                continue;
            }
            list($namespace, $method) = \explode('.', $data['method']);
            if (!\in_array($namespace, $this->TL->getMethodNamespaces())) {
                continue;
            }
            $internalDoc[$namespace][$method]['title'] = \str_replace(['](../', '.md'], ['](https://docs.madelineproto.xyz/API_docs/', '.html'], Lang::$lang['en']["method_{$data['method']}"] ?? '');
            $type = \str_ireplace(['vector<', '>'], [' of ', '[]'], $data['type']);
            foreach ($data['params'] as $param) {
                if (\in_array($param['name'], ['flags', 'random_id', 'random_bytes'])) {
                    continue;
                }
                if ($param['name'] === 'data' && $type === 'messages.SentEncryptedMessage') {
                    $param['name'] = 'message';
                    $param['type'] = 'DecryptedMessage';
                }
                if ($param['name'] === 'chat_id' && $data['method'] !== 'messages.discardEncryption') {
                    $param['type'] = 'InputPeer';
                }
                if ($param['name'] === 'hash' && $param['type'] === 'int') {
                    $param['pow'] = 'hi';
                    $param['type'] = 'Vector t';
                    $param['subtype'] = 'int';
                }
                $stype = 'type';
                if (isset($param['subtype'])) {
                    $stype = 'subtype';
                }
                $ptype = $param[$stype];
                switch ($ptype) {
                    case 'true':
                    case 'false':
                        $ptype = 'boolean';
                }
                $ptype = $stype === 'type' ? $ptype : "[{$ptype}]";
                $opt = $param['pow'] ?? false ? 'Optional: ' : '';
                $internalDoc[$namespace][$method]['attr'][$param['name']] = ['type' => $ptype, 'description' => \str_replace(['](../', '.md'], ['](https://docs.madelineproto.xyz/API_docs/', '.html'], $opt . (Lang::$lang['en']["method_{$data['method']}_param_{$param['name']}_type_{$param['type']}"] ?? ''))];
            }
            if ($type === 'Bool') {
                $type = \strtolower($type);
            }
            $internalDoc[$namespace][$method]['return'] = $type;
        }
        $class = new \ReflectionClass($this->reflectionClasses['MTProto']);
        $methods = $class->getMethods(\ReflectionMethod::IS_STATIC & \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PUBLIC);
        $class = new \ReflectionClass(Tools::class);
        $methods = \array_merge($methods, $class->getMethods(\ReflectionMethod::IS_STATIC & \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PUBLIC));
        foreach ($methods as $key => $method) {
            $name = $method->getName();
            if ($method == 'methodCallAsyncRead') {
                unset($methods[\array_search('methodCall', $methods)]);
            } elseif (\strpos($name, '__') === 0) {
                unset($methods[$key]);
            } elseif (\stripos($name, 'async') !== false) {
                if (\strpos($name, '_async') !== false) {
                    unset($methods[\array_search(\str_ireplace('_async', '', $method), $methods)]);
                } else {
                    unset($methods[\array_search(\str_ireplace('async', '', $method), $methods)]);
                }
            }
        }
        $sortedMethods = [];
        foreach ($methods as $method) {
            $sortedMethods[$method->getName()] = $method;
        }
        \ksort($sortedMethods);
        $methods = \array_values($sortedMethods);
        foreach ($methods as $method) {
            $name = $method->getName();
            if (isset($ignoreMethods[$name])) {
                continue;
            }
            if (\strpos($method->getDocComment() ?? '', '@internal') !== false) {
                continue;
            }
            $static = $method->isStatic();
            if (!$static) {
                $code = \file_get_contents($method->getFileName());
                $code = \implode("\n", \array_slice(\explode("\n", $code), $method->getStartLine(), $method->getEndLine() - $method->getStartLine()));
                if (\strpos($code, '$this') === false) {
                    Logger::log("{$name} should be STATIC!", Logger::FATAL_ERROR);
                }
            }
            if ($name == 'methodCallAsyncRead') {
                $name = 'methodCall';
            } elseif (\stripos($name, 'async') !== false) {
                if (\strpos($name, '_async') !== false) {
                    $name = \str_ireplace('_async', '', $name);
                } else {
                    $name = \str_ireplace('async', '', $name);
                }
            }
            $name = StrTools::toCamelCase($name);
            $name = \str_ireplace(['mtproto', 'api'], ['MTProto', 'API'], $name);
            $doc = 'public function ';
            $doc .= $name;
            $doc .= '(';
            $paramList = '';
            $hasVariadic = false;
            foreach ($method->getParameters() as $param) {
                if ($param->allowsNull()) {
                    //$doc .= '?';
                }
                if ($type = $param->getType()) {
                    if ($type->allowsNull()) {
                        $doc .= '?';
                    }
                    if (!$type->isBuiltin()) {
                        $doc .= '\\';
                    }
                    $doc .= $type->getName();
                    $doc .= ' ';
                } else {
                    Logger::log($name . '.' . $param->getName() . " has no type!", Logger::WARNING);
                }
                if ($param->isVariadic()) {
                    $doc .= '...';
                }
                if ($param->isPassedByReference()) {
                    $doc .= '&';
                }
                $doc .= '$';
                $doc .= $param->getName();
                if ($param->isOptional() && !$param->isVariadic()) {
                    $doc .= ' = ';
                    if ($param->isDefaultValueConstant()) {
                        $doc .= '\\' . \str_replace(['NULL', 'self'], ['null', 'danog\\MadelineProto\\MTProto'], $param->getDefaultValueConstantName());
                    } else {
                        $doc .= \str_replace('NULL', 'null', \var_export($param->getDefaultValue(), true));
                    }
                }
                $doc .= ', ';
                if ($param->isVariadic()) {
                    $hasVariadic = true;
                    $paramList .= '...';
                }
                $paramList .= '$' . $param->getName() . ', ';
            }
            $hasReturnValue = ($type = $method->getReturnType()) && !\in_array($type->getName(), [\Generator::class, Promise::class]);
            if (!$hasVariadic && !$static && !$hasReturnValue) {
                $paramList .= '$extra, ';
                $doc .= 'array $extra = []';
            }
            $doc = \rtrim($doc, ', ');
            $paramList = \rtrim($paramList, ', ');
            $doc .= ")";
            $async = true;
            if ($hasReturnValue && $static) {
                $doc .= ': ';
                if ($type->allowsNull()) {
                    $doc .= '?';
                }
                if (!$type->isBuiltin()) {
                    $doc .= '\\';
                }
                $doc .= $type->getName() === 'self' ? $this->reflectionClasses['API'] : $type->getName();
                $async = false;
            }
            if ($method->getDeclaringClass()->getName() == Tools::class) {
                $async = false;
            }
            $finalParamList = $hasVariadic ? "Tools::arr({$paramList})" : "[{$paramList}]";
            $ret = $type && \in_array($type->getName(), ['self', 'void']) ? '' : 'return';
            $doc .= "\n{\n";
            if ($async) {
                $doc .= "    {$ret} \$this->__call(__FUNCTION__, {$finalParamList});\n";
            } elseif (!$static) {
                $doc .= "    {$ret} \$this->API->{$name}({$paramList});\n";
            } else {
                $doc .= "    {$ret} \\" . $method->getDeclaringClass()->getName() . "::" . $name . "({$paramList});\n";
            }
            if (!$ret && $type->getName() === 'self') {
                $doc .= "    return \$this;\n";
            }
            $doc .= "}\n";
            if (!$method->getDocComment()) {
                Logger::log("{$name} has no PHPDOC!", Logger::FATAL_ERROR);
            }
            if (!$type) {
                Logger::log("{$name} has no return type!", Logger::FATAL_ERROR);
            }
            $promise = '\\' . Promise::class;
            $phpdoc = $method->getDocComment() ?? '';
            $phpdoc = \str_replace("@return \\Generator", "@return {$promise}", $phpdoc);
            $phpdoc = \str_replace("@return \\Promise", "@return {$promise}", $phpdoc);
            $phpdoc = \str_replace("@return Promise", "@return {$promise}", $phpdoc);
            if ($hasReturnValue && $async && \preg_match("/@return (.*)/", $phpdoc, $matches)) {
                $ret = $matches[1];
                $new = $ret;
                if ($type && !\str_contains($ret, '<')) {
                    $new = '';
                    if ($type->allowsNull()) {
                        $new .= '?';
                    }
                    if (!$type->isBuiltin()) {
                        $new .= '\\';
                    }
                    $new .= $type->getName() === 'self' ? $this->reflectionClasses['API'] : $type->getName();
                }
                $phpdoc = \str_replace("@return " . $ret, "@return mixed", $phpdoc);
                if (!\str_contains($phpdoc, '@psalm-return')) {
                    $phpdoc = \str_replace("@return ", "@psalm-return {$new}|{$promise}<{$new}>\n     * @return ", $phpdoc);
                }
            }
            $phpdoc = \preg_replace("/@psalm-return \\\\Generator<(?:[^,]+), (?:[^,]+), (?:[^,]+), (.+)>/", "@psalm-return {$promise}<\$1>", $phpdoc);
            $internalDoc['InternalDoc'][$name]['method'] = $phpdoc;
            $internalDoc['InternalDoc'][$name]['method'] .= "\n    " . \implode("\n    ", \explode("\n", $doc));
        }
        \fwrite($handle, "<?php\n");
        \fwrite($handle, "/**\n");
        \fwrite($handle, " * This file is automatic generated by build_docs.php file\n");
        \fwrite($handle, " * and is used only for autocomplete in multiple IDE\n");
        \fwrite($handle, " * don't modify manually.\n");
        \fwrite($handle, " */\n\n");
        \fwrite($handle, "namespace {$this->namespace};\n");
        foreach ($internalDoc as $namespace => $methods) {
            if ($namespace === 'InternalDoc') {
                \fwrite($handle, "\nclass {$namespace} extends APIFactory\n{\n");
            } else {
                \fwrite($handle, "\ninterface {$namespace}\n{");
            }
            foreach ($methods as $method => $properties) {
                if (isset($properties['method'])) {
                    \fwrite($handle, $properties['method']);
                    continue;
                }
                $title = \implode("\n     * ", \explode("\n", $properties['title']));
                \fwrite($handle, "\n    /**\n");
                \fwrite($handle, "     * {$title}\n");
                \fwrite($handle, "     *\n");
                if (isset($properties['attr'])) {
                    \fwrite($handle, "     * Parameters: \n");
                    $longest = [0, 0, 0];
                    foreach ($properties['attr'] as $name => $param) {
                        $longest[0] = \max($longest[0], \strlen($param['type']));
                        $longest[1] = \max($longest[1], \strlen($name));
                        $longest[2] = \max($longest[2], \strlen($param['description']));
                    }
                    foreach ($properties['attr'] as $name => $param) {
                        $param['type'] = \str_pad('`' . $param['type'] . '`', $longest[0] + 2);
                        $name = \str_pad('**' . $name . '**', $longest[1] + 4);
                        $param['description'] = \str_pad($param['description'], $longest[2]);
                        \fwrite($handle, "     * * {$param['type']} {$name} - {$param['description']}\n");
                    }
                    \fwrite($handle, "     * \n");
                    \fwrite($handle, "     * @param array \$params Parameters\n");
                    \fwrite($handle, "     *\n");
                }
                \fwrite($handle, "     * @return {$properties['return']}\n");
                \fwrite($handle, "     */\n");
                \fwrite($handle, "    public function {$method}(");
                if (isset($properties['attr'])) {
                    \fwrite($handle, '$params');
                }
                \fwrite($handle, ");\n");
            }
            \fwrite($handle, "}\n");
        }
        \fclose($handle);
    }
}<?php

/**
 * Exception module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL;

/**
 * TL deserialization exception.
 */
class Exception extends \Exception
{
    use PrettyException;
    /**
     *
     */
    public function __toString()
    {
        $result = \get_class($this) . ($this->message !== '' ? ': ' : '') . $this->message . PHP_EOL . \danog\MadelineProto\Magic::$revision . PHP_EOL . 'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):' . PHP_EOL . PHP_EOL . $this->getTLTrace() . PHP_EOL;
        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
            $result = \str_replace(PHP_EOL, '<br>' . PHP_EOL, $result);
        }
        return $result;
    }
    /**
     *
     */
    public function __construct($message, $file = '')
    {
        parent::__construct($message);
        $this->prettifyTL($file);
    }
}<?php

/**
 * PrettyException module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL;

/**
 * Handle async stack traces.
 */
trait PrettyException
{
    /**
     * TL trace.
     *
     * @var string
     */
    public $tlTrace = '';
    /**
     * Method name.
     *
     * @var string
     */
    private $method = '';
    /**
     * Whether the TL trace was updated.
     *
     * @var boolean
     */
    private $updated = false;
    /**
     * Update TL trace.
     *
     * @param array $trace
     *
     * @return void
     */
    public function updateTLTrace(array $trace)
    {
        if (!$this->updated) {
            $this->updated = true;
            $this->prettifyTL($this->method, $trace);
        }
    }
    /**
     * Get TL trace.
     *
     * @return string
     */
    public function getTLTrace() : string
    {
        return $this->tlTrace;
    }
    /**
     * Set TL trace.
     *
     * @param string $tlTrace TL trace
     *
     * @return void
     */
    public function setTLTrace(string $tlTrace) : void
    {
        $this->tlTrace = $tlTrace;
    }
    /**
     * Generate async trace.
     *
     * @param string $init Method name
     * @param array $trace Async trace
     *
     * @return void
     */
    public function prettifyTL(string $init = '', array $trace = null)
    {
        $this->method = $init;
        $previous_trace = $this->tlTrace;
        $this->tlTrace = '';
        $eol = PHP_EOL;
        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
            $eol = '<br>' . PHP_EOL;
        }
        $tl = false;
        foreach (\array_reverse($trace ?? $this->getTrace()) as $k => $frame) {
            if (isset($frame['function']) && \in_array($frame['function'], ['serializeParams', 'serializeObject'])) {
                if (($frame['args'][2] ?? '') !== '') {
                    $this->tlTrace .= $tl ? "['" . $frame['args'][2] . "']" : "While serializing:  \t" . $frame['args'][2];
                    $tl = true;
                }
            } else {
                if ($tl) {
                    $this->tlTrace .= $eol;
                }
                if (isset($frame['function']) && ($frame['function'] === 'handle_rpc_error' && $k === \count($this->getTrace()) - 1) || $frame['function'] === 'unserialize') {
                    continue;
                }
                $this->tlTrace .= isset($frame['file']) ? \str_pad(\basename($frame['file']) . '(' . $frame['line'] . '):', 20) . "\t" : '';
                $this->tlTrace .= isset($frame['function']) ? $frame['function'] . '(' : '';
                $this->tlTrace .= isset($frame['args']) ? \Phabel\Target\Php80\Polyfill::substr(\json_encode($frame['args']), 1, -1) : '';
                $this->tlTrace .= ')';
                $this->tlTrace .= $eol;
                $tl = false;
            }
        }
        $this->tlTrace .= $init !== '' ? "['" . $init . "']" : '';
        $this->tlTrace = \implode($eol, \array_reverse(\explode($eol, $this->tlTrace)));
        if ($previous_trace) {
            $this->tlTrace .= $eol . $eol;
            $this->tlTrace .= "Previous TL trace:{$eol}";
            $this->tlTrace .= $previous_trace;
        }
    }
}<?php

/**
 * TLMethods module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL;

class TLMethods
{
    use \danog\Serializable;
    use TLParams;
    public $by_id = [];
    public $by_method = [];
    public $method_namespace = [];
    /**
     *
     */
    public function __sleep() : array
    {
        return ['by_id', 'by_method', 'method_namespace'];
    }
    /**
     *
     */
    public function add(array $json_dict) : void
    {
        $this->by_id[$json_dict['id']] = ['method' => $json_dict['method'], 'type' => $json_dict['type'], 'params' => $json_dict['params']];
        $this->by_method[$json_dict['method']] = $json_dict['id'];
        $namespace = \explode('.', $json_dict['method']);
        if (isset($namespace[1])) {
            $this->method_namespace[] = [$namespace[0] => $namespace[1]];
        }
        $this->parseParams($json_dict['id']);
    }
    /**
     *
     */
    public function findById(string $id)
    {
        if (isset($this->by_id[$id])) {
            $method = $this->by_id[$id];
            $method['id'] = $id;
            return $method;
        }
        return false;
    }
    /**
     *
     */
    public function findByMethod(string $method_name)
    {
        if (isset($this->by_method[$method_name])) {
            $method = $this->by_id[$this->by_method[$method_name]];
            $method['id'] = $this->by_method[$method_name];
            return $method;
        }
        return false;
    }
}<?php

/**
 * Button module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL\Types;

use danog\MadelineProto\API;
use danog\MadelineProto\Ipc\Client;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\Tools;
/**
 * Clickable button.
 */
class Button implements \JsonSerializable, \ArrayAccess
{
    /**
     * Button data.
     *
     * @psalm-var array<array-key, mixed>
     */
    private array $button = [];
    /**
     * Session name.
     */
    private string $session = '';
    /**
     * MTProto instance.
     *
     * @var MTProto|Client|null
     */
    private $API = null;
    /**
     * Message ID.
     */
    private int $id;
    /**
     * Peer ID.
     *
     * @var array|int
     */
    private $peer;
    /**
     * Constructor function.
     *
     * @param MTProto $API API instance
     * @param array $message Message
     * @param array $button Button info
     */
    public function __construct(MTProto $API, array $message, array $button)
    {
        if (!isset($message['from_id']) || $message['peer_id']['_'] !== 'peerUser' || $message['peer_id']['user_id'] !== $API->authorization['user']['id']) {
            $this->peer = $message['peer_id'];
        } else {
            $this->peer = $message['from_id'];
        }
        $this->button = $button;
        $this->id = $message['id'];
        $this->API = $API;
        $this->session = $API->getWrapper()->getSession()->getLegacySessionPath();
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep() : array
    {
        return ['button', 'peer', 'id', 'session'];
    }
    /**
     * Click on button.
     *
     * @param boolean $donotwait Whether to wait for the result of the method
     *
     * @return mixed
     */
    public function click(bool $donotwait = true)
    {
        if (!isset($this->API)) {
            $this->API = Client::giveInstanceBySession($this->session);
        }
        $async = $this->API instanceof Client ? $this->API->async : $this->API->wrapper->isAsync();
        switch ($this->button['_']) {
            default:
                return false;
            case 'keyboardButtonUrl':
                return $this->button['url'];
            case 'keyboardButton':
                $res = $this->API->clickInternal($donotwait, 'messages.sendMessage', ['peer' => $this->peer, 'message' => $this->button['text'], 'reply_to_msg_id' => $this->id]);
                break;
            case 'keyboardButtonCallback':
                $res = $this->API->clickInternal($donotwait, 'messages.getBotCallbackAnswer', ['peer' => $this->peer, 'msg_id' => $this->id, 'data' => $this->button['data']]);
                break;
            case 'keyboardButtonGame':
                $res = $this->API->clickInternal($donotwait, 'messages.getBotCallbackAnswer', ['peer' => $this->peer, 'msg_id' => $this->id, 'game' => true]);
                break;
        }
        return $async ? $res : Tools::wait($res);
    }
    /**
     * Get debug info.
     *
     * @return array
     */
    public function __debugInfo() : array
    {
        $res = \get_object_vars($this);
        unset($res['API']);
        return $res;
    }
    /**
     * Serialize button.
     *
     * @return array
     */
    public function jsonSerialize() : array
    {
        return $this->button;
    }
    /**
     * Set button info.
     *
     * @param $name  Offset
     * @param mixed $value Value
     *
     * @return void
     * @param mixed $name
     */
    public function offsetSet($name, $value) : void
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($name) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($name) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if ($name === null) {
            $this->button[] = $value;
        } else {
            $this->button[$name] = $value;
        }
    }
    /**
     * Get button info.
     *
     * @param $name Field name
     *
     * @return mixed
     * @param mixed $name
     */
    public function offsetGet($name)
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($name) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($name) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $phabelReturn = $this->button[$name];
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * Unset button info.
     *
     * @param $name Offset
     *
     * @return void
     * @param mixed $name
     */
    public function offsetUnset($name) : void
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($name) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($name) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        unset($this->button[$name]);
    }
    /**
     * Check if button field exists.
     *
     * @param $name Offset
     *
     * @return boolean
     * @param mixed $name
     */
    public function offsetExists($name) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($name) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($name) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return isset($this->button[$name]);
    }
}<?php

/**
 * Bytes module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL\Types;

/**
 * Bytes wrapper.
 */
class Bytes implements \JsonSerializable, \ArrayAccess
{
    /**
     * Bytes.
     *
     * @var string Bytes
     */
    private string $bytes;
    /**
     * Constructor function.
     *
     * @param string $bytes Contents
     */
    public function __construct(string $bytes)
    {
        $this->bytes = $bytes;
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep() : array
    {
        return ['bytes'];
    }
    /**
     * Cast bytes to string.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->bytes;
    }
    /**
     * Obtain values for JSON-encoding.
     *
     * @return array
     */
    public function jsonSerialize() : array
    {
        return ['_' => 'bytes', 'bytes' => \base64_encode($this->bytes)];
    }
    /**
     * Set char at offset.
     *
     * @param (integer | null) $offset Offset
     * @param string $value Char
     *
     * @return void
     */
    public function offsetSet($offset, $value) : void
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if ($offset === null) {
            $this->bytes .= $value;
        } else {
            $this->bytes[$offset] = $value;
        }
    }
    /**
     * Get char at offset.
     *
     * @param integer $offset Name
     *
     * @return string
     */
    public function offsetGet($offset)
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $phabelReturn = $this->bytes[$offset];
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * Unset char at offset.
     *
     * @param integer $offset Offset
     *
     * @return void
     */
    public function offsetUnset($offset) : void
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        unset($this->bytes[$offset]);
    }
    /**
     * Check if char at offset exists.
     *
     * @param integer $offset Offset
     *
     * @return boolean
     */
    public function offsetExists($offset) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($offset) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return isset($this->bytes[$offset]);
    }
}<?php

/**
 * TL callback module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL;

/**
 * Interface for managing TL serialization callbacks.
 */
interface TLCallback
{
    /**
     * Called after serializing a method.
     *
     * @internal
     *
     * @var int
     */
    const METHOD_CALLBACK = 0;
    /**
     * Called before serializing a method.
     *
     * @internal
     *
     * @var int
     */
    const METHOD_BEFORE_CALLBACK = 1;
    /**
     * Called after serializing a constructor.
     *
     * @internal
     *
     * @var int
     */
    const CONSTRUCTOR_CALLBACK = 2;
    /**
     * Called before serializing a constructor.
     *
     * @internal
     *
     * @var int
     */
    const CONSTRUCTOR_BEFORE_CALLBACK = 3;
    /**
     * Called on constructor serialization.
     *
     * @internal
     *
     * @var int
     */
    const CONSTRUCTOR_SERIALIZE_CALLBACK = 4;
    /**
     * Called if objects of the specified type cannot be serialized.
     *
     * @internal
     *
     * @var int
     */
    const TYPE_MISMATCH_CALLBACK = 5;
    /**
     * Called after serialization of method.
     *
     * Pass the method name and arguments
     *
     * @return array
     */
    public function getMethodCallbacks() : array;
    /**
     * Called right before serialization of method starts.
     *
     * Pass the method name
     *
     * @return array
     */
    public function getMethodBeforeCallbacks() : array;
    /**
     * Called right after deserialization of object, passing the final object.
     *
     * @return array
     */
    public function getConstructorCallbacks() : array;
    /**
     * Called right before deserialization of object.
     *
     * Pass only the constructor name
     *
     * @return array
     */
    public function getConstructorBeforeCallbacks() : array;
    /**
     * Called right before serialization of constructor.
     *
     * Passed the object, will return a modified version.
     *
     * @return array
     */
    public function getConstructorSerializeCallbacks() : array;
    /**
    * Called if objects of the specified type cannot be serialized.
    *
    * Passed the unserializable object,
    will try to convert it to an object of the proper type.
    *
    * @return array
    */
    public function getTypeMismatchCallbacks() : array;
}<?php

/**
 * TL module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL;

use Amp\Promise;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\MTProto\OutgoingMessage;
use danog\MadelineProto\Settings\TLSchema;
use danog\MadelineProto\Tools;
/**
 * TL serialization.
 */
class TL
{
    /**
     * Highest available secret chat layer version.
     *
     * @var integer
     */
    private $secretLayer = -1;
    /**
     * Constructors.
     *
     * @var TLConstructors
     */
    private $constructors;
    /**
     * Methods.
     *
     * @var TLMethods
     */
    private $methods;
    /**
     * TD Constructors.
     *
     * @var TLConstructors
     */
    private $tdConstructors;
    /**
     * TD Methods.
     *
     * @var TLMethods
     */
    private $tdMethods;
    /**
     * Descriptions.
     *
     * @var array
     */
    private $tdDescriptions;
    /**
     * TL callbacks.
     *
     * @var array
     */
    private $callbacks = [];
    /**
     * API instance.
     *
     * @var \danog\MadelineProto\MTProto
     */
    private $API;
    /**
     * Constructor function.
     *
     * @param MTProto $API API instance
     */
    public function __construct($API = null)
    {
        $this->API = $API;
    }
    /**
     * Get secret chat layer version.
     *
     * @return integer
     */
    public function getSecretLayer() : int
    {
        return $this->secretLayer;
    }
    /**
     * Get constructors.
     *
     * @param bool $td
     *
     * @return TLConstructors
     */
    public function getConstructors(bool $td = false) : TLConstructors
    {
        return $td ? $this->tdConstructors : $this->constructors;
    }
    /**
     * Get methods.
     *
     * @param bool $td
     *
     * @return TLMethods
     */
    public function getMethods(bool $td = false) : TLMethods
    {
        return $td ? $this->tdMethods : $this->methods;
    }
    /**
     * Get TL descriptions.
     *
     * @return array
     */
    public function &getDescriptions() : array
    {
        return $this->tdDescriptions;
    }
    /**
     * Initialize TL parser.
     *
     * @param TLSchema $files Scheme files
     * @param TLCallback[] $objects TL Callback objects
     *
     * @return void
     */
    public function init(TLSchema $files, array $objects = [])
    {
        $this->API->logger->logger(\danog\MadelineProto\Lang::$current_lang['TL_loading'], \danog\MadelineProto\Logger::VERBOSE);
        $this->updateCallbacks($objects);
        $this->constructors = new TLConstructors();
        $this->methods = new TLMethods();
        $this->tdConstructors = new TLConstructors();
        $this->tdMethods = new TLMethods();
        $this->tdDescriptions = ['types' => [], 'constructors' => [], 'methods' => []];
        foreach (\array_filter(['api' => $files->getAPISchema(), 'mtproto' => $files->getMTProtoSchema(), 'secret' => $files->getSecretSchema(), ...$files->getOther()]) as $scheme_type => $file) {
            $this->API->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['file_parsing'], \basename($file)), \danog\MadelineProto\Logger::VERBOSE);
            $filec = \file_get_contents(Tools::absolute($file));
            $TL_dict = \json_decode($filec, true);
            if ($TL_dict === null) {
                $TL_dict = ['methods' => [], 'constructors' => []];
                $type = 'constructors';
                $layer = null;
                $tl_file = \explode("\n", $filec);
                $key = 0;
                $e = null;
                $class = null;
                $dparams = [];
                $lineBuf = '';
                foreach ($tl_file as $line) {
                    $line = \rtrim($line);
                    if (\preg_match('|^//@|', $line)) {
                        $list = \explode(' @', \str_replace('//', ' ', $line));
                        foreach ($list as $elem) {
                            if ($elem === '') {
                                continue;
                            }
                            $elem = \explode(' ', $elem, 2);
                            if ($elem[0] === 'class') {
                                $elem = \explode(' ', $elem[1], 2);
                                $class = $elem[0];
                                continue;
                            }
                            if ($elem[0] === 'description') {
                                if (!\is_null($class)) {
                                    $this->tdDescriptions['types'][$class] = $elem[1];
                                    $class = null;
                                } else {
                                    $e = $elem[1];
                                }
                                continue;
                            }
                            if ($elem[0] === 'param_description') {
                                $elem[0] = 'description';
                            }
                            $dparams[$elem[0]] = $elem[1];
                        }
                        continue;
                    }
                    $line = \preg_replace(['|//.*|', '|^\\s+$|'], '', $line);
                    if ($line === '') {
                        continue;
                    }
                    if ($line === '---functions---') {
                        $type = 'methods';
                        continue;
                    }
                    if ($line === '---types---') {
                        $type = 'constructors';
                        continue;
                    }
                    if (\preg_match('|^===(\\d*)===|', $line, $matches)) {
                        $layer = (int) $matches[1];
                        continue;
                    }
                    if (\strpos($line, 'vector#') === 0) {
                        continue;
                    }
                    if (\strpos($line, ' ?= ') !== false) {
                        continue;
                    }
                    $line = \preg_replace(['/[(]([\\w\\.]+) ([\\w\\.]+)[)]/', '/\\s+/'], ['$1<$2>', ' '], $line);
                    if (\strpos($line, ';') === false) {
                        $lineBuf .= $line;
                        continue;
                    } elseif ($lineBuf) {
                        $lineBuf .= $line;
                        $line = $lineBuf;
                        $lineBuf = '';
                    }
                    $name = \preg_replace(['/#.*/', '/\\s.*/'], '', $line);
                    if (\in_array($name, ['bytes', 'int128', 'int256', 'int512', 'int', 'long', 'double', 'string', 'bytes', 'object', 'function'])) {
                        /*if (!(\in_array($scheme_type, ['ton_api', 'lite_api']) && $name === 'bytes')) {
                              continue;
                          }*/
                        continue;
                    }
                    if (\in_array($scheme_type, ['ton_api', 'lite_api'])) {
                        $clean = \preg_replace(['/;/', '/#[a-f0-9]+ /', '/ [a-zA-Z0-9_]+\\:flags\\.[0-9]+\\?true/', '/[<]/', '/[>]/', '/  /', '/^ /', '/ $/', '/{/', '/}/'], ['', ' ', '', ' ', ' ', ' ', '', '', '', ''], $line);
                    } else {
                        $clean = \preg_replace(['/:bytes /', '/;/', '/#[a-f0-9]+ /', '/ [a-zA-Z0-9_]+\\:flags\\.[0-9]+\\?true/', '/[<]/', '/[>]/', '/  /', '/^ /', '/ $/', '/\\?bytes /', '/{/', '/}/'], [':string ', '', ' ', '', ' ', ' ', ' ', '', '', '?string ', '', ''], $line);
                    }
                    $id = \hash('crc32b', $clean);
                    if (\preg_match('/^[^\\s]+#([a-f0-9]*)/i', $line, $matches)) {
                        $nid = \str_pad($matches[1], 8, '0', \STR_PAD_LEFT);
                        if ($id !== $nid) {
                            $this->API->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['crc32_mismatch'], $id, $nid, $line), \danog\MadelineProto\Logger::ERROR);
                        }
                        $id = $nid;
                    }
                    if (!\is_null($e)) {
                        $this->tdDescriptions[$type][$name] = ['description' => $e, 'params' => $dparams];
                        $e = null;
                        $dparams = [];
                    }
                    $TL_dict[$type][$key][$type === 'constructors' ? 'predicate' : 'method'] = $name;
                    $TL_dict[$type][$key]['id'] = $a = \strrev(\hex2bin($id));
                    $TL_dict[$type][$key]['params'] = [];
                    $TL_dict[$type][$key]['type'] = \preg_replace(['/.+\\s+=\\s+/', '/;/'], '', $line);
                    if ($layer !== null) {
                        $TL_dict[$type][$key]['layer'] = $layer;
                    }
                    if ($name !== 'vector' && $TL_dict[$type][$key]['type'] !== 'Vector t') {
                        foreach (\explode(' ', \preg_replace(['/^[^\\s]+\\s/', '/=\\s[^\\s]+/', '/\\s$/'], '', $line)) as $param) {
                            if ($param === '') {
                                continue;
                            }
                            if ($param[0] === '{') {
                                continue;
                            }
                            if ($param === '#') {
                                continue;
                            }
                            $explode = \explode(':', $param);
                            $TL_dict[$type][$key]['params'][] = ['name' => $explode[0], 'type' => $explode[1]];
                        }
                    }
                    $key++;
                }
            } else {
                foreach ($TL_dict['constructors'] as $key => $value) {
                    $TL_dict['constructors'][$key]['id'] = \danog\MadelineProto\Tools::packSignedInt($TL_dict['constructors'][$key]['id']);
                }
                foreach ($TL_dict['methods'] as $key => $value) {
                    $TL_dict['methods'][$key]['id'] = \danog\MadelineProto\Tools::packSignedInt($TL_dict['methods'][$key]['id']);
                }
            }
            if (empty($TL_dict) || empty($TL_dict['constructors']) || !isset($TL_dict['methods'])) {
                throw new Exception(\danog\MadelineProto\Lang::$current_lang['src_file_invalid'] . $file);
            }
            $this->API->logger->logger(\danog\MadelineProto\Lang::$current_lang['translating_obj'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
            foreach ($TL_dict['constructors'] as $elem) {
                if ($scheme_type === 'secret') {
                    $this->secretLayer = \max($this->secretLayer, $elem['layer']);
                }
                $this->{$scheme_type === 'td' ? 'tdConstructors' : 'constructors'}->add($elem, $scheme_type);
            }
            $this->API->logger->logger(\danog\MadelineProto\Lang::$current_lang['translating_methods'], \danog\MadelineProto\Logger::ULTRA_VERBOSE);
            foreach ($TL_dict['methods'] as $elem) {
                $this->{$scheme_type === 'td' ? 'tdMethods' : 'methods'}->add($elem);
                if ($scheme_type === 'secret') {
                    $this->secretLayer = \max($this->secretLayer, $elem['layer']);
                }
            }
        }
        if (isset($files->getOther()['td'])) {
            foreach ($this->tdConstructors->by_id as $id => $data) {
                $name = $data['predicate'];
                if ($this->constructors->findById($id) === false) {
                    unset($this->tdDescriptions['constructors'][$name]);
                } else {
                    if (!\count($this->tdDescriptions['constructors'][$name]['params'])) {
                        continue;
                    }
                    foreach ($this->tdDescriptions['constructors'][$name]['params'] as $k => $param) {
                        $this->tdDescriptions['constructors'][$name]['params'][$k] = \str_replace('nullable', 'optional', $param);
                    }
                }
            }
            foreach ($this->tdMethods->by_id as $id => $data) {
                $name = $data['method'];
                if ($this->methods->findById($id) === false) {
                    unset($this->tdDescriptions['methods'][$name]);
                } else {
                    foreach ($this->tdDescriptions['methods'][$name]['params'] as $k => $param) {
                        $this->tdDescriptions['constructors'][$name]['params'][$k] = \str_replace('nullable', 'optional', $param);
                    }
                }
            }
        }
        $files->upgrade();
    }
    /**
     * Get TL namespaces.
     *
     * @return array
     */
    public function getMethodNamespaces() : array
    {
        $res = [];
        foreach ($this->methods->method_namespace as $pair) {
            $a = \key($pair);
            $res[$a] = $a;
        }
        return $res;
    }
    /**
     * Get namespaced methods (method => namespace).
     *
     * @return array
     */
    public function getMethodsNamespaced() : array
    {
        return $this->methods->method_namespace;
    }
    /**
     * Update TL callbacks.
     *
     * @param TLCallback[] $objects TL callbacks
     *
     * @return void
     */
    public function updateCallbacks(array $objects)
    {
        $this->callbacks = [];
        foreach ($objects as $object) {
            if (!isset(\class_implements(\get_class($object))[TLCallback::class])) {
                throw new Exception('Invalid callback object provided!');
            }
            $new = [TLCallback::METHOD_BEFORE_CALLBACK => $object->getMethodBeforeCallbacks(), TLCallback::METHOD_CALLBACK => $object->getMethodCallbacks(), TLCallback::CONSTRUCTOR_BEFORE_CALLBACK => $object->getConstructorBeforeCallbacks(), TLCallback::CONSTRUCTOR_CALLBACK => $object->getConstructorCallbacks(), TLCallback::CONSTRUCTOR_SERIALIZE_CALLBACK => $object->getConstructorSerializeCallbacks(), TLCallback::TYPE_MISMATCH_CALLBACK => $object->getTypeMismatchCallbacks()];
            foreach ($new as $type => $values) {
                foreach ($values as $match => $callback) {
                    if (!isset($this->callbacks[$type][$match])) {
                        $this->callbacks[$type][$match] = [];
                    }
                    if (\in_array($type, [TLCallback::TYPE_MISMATCH_CALLBACK, TLCallback::CONSTRUCTOR_SERIALIZE_CALLBACK])) {
                        $this->callbacks[$type][$match] = $callback;
                    } else {
                        $this->callbacks[$type][$match] = \array_merge($callback, $this->callbacks[$type][$match]);
                    }
                }
            }
        }
    }
    /**
     * Deserialize bool.
     *
     * @param string $id Constructor ID
     *
     * @return bool
     */
    private function deserializeBool(string $id) : bool
    {
        $tl_elem = $this->constructors->findById($id);
        if ($tl_elem === false) {
            throw new Exception(\danog\MadelineProto\Lang::$current_lang['bool_error']);
        }
        return $tl_elem['predicate'] === 'boolTrue';
    }
    /**
     * Serialize TL object.
     *
     * @param array $type TL type definition
     * @param mixed $object Object to serialize
     * @param string $ctx Context
     * @param integer $layer Layer version
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (array | mixed), mixed, (false | mixed | null | string)>
     */
    public function serializeObject(array $type, $object, $ctx, int $layer = -1) : \Generator
    {
        if ($object instanceof \Generator) {
            $object = (yield from $object);
        }
        switch ($type['type']) {
            case 'int':
                if (!\is_numeric($object)) {
                    throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
                }
                return \danog\MadelineProto\Tools::packSignedInt($object);
            case '#':
                if (!\is_numeric($object)) {
                    throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
                }
                return \danog\MadelineProto\Tools::packUnsignedInt($object);
            case 'long':
                if (\is_object($object)) {
                    return \str_pad(\strrev($object->toBytes()), 8, \chr(0));
                }
                if (\is_string($object) && \strlen($object) === 8) {
                    return $object;
                }
                if (\is_string($object) && \strlen($object) === 9 && $object[0] === 'a') {
                    return \Phabel\Target\Php80\Polyfill::substr($object, 1);
                }
                if (\is_array($object) && $type['name'] === 'hash') {
                    return \danog\MadelineProto\Tools::genVectorHash($object);
                }
                if (\is_array($object) && \count($object) === 2) {
                    return \pack('l2', ...$object);
                    // For bot API on 32bit
                }
                if (!\is_numeric($object)) {
                    throw new Exception(\danog\MadelineProto\Lang::$current_lang['not_numeric']);
                }
                return \danog\MadelineProto\Tools::packSignedLong($object);
            case 'int128':
                if (\strlen($object) !== 16) {
                    $object = \base64_decode($object);
                    if (\strlen($object) !== 16) {
                        throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_16']);
                    }
                }
                return (string) $object;
            case 'int256':
                if (\strlen($object) !== 32) {
                    $object = \base64_decode($object);
                    if (\strlen($object) !== 32) {
                        throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_32']);
                    }
                }
                return (string) $object;
            case 'int512':
                if (\strlen($object) !== 64) {
                    $object = \base64_decode($object);
                    if (\strlen($object) !== 64) {
                        throw new Exception(\danog\MadelineProto\Lang::$current_lang['long_not_64']);
                    }
                }
                return (string) $object;
            case 'double':
                return \danog\MadelineProto\Tools::packDouble($object);
            case 'string':
                if (!\is_string($object)) {
                    throw new Exception("You didn't provide a valid string");
                }
                //$object = \pack('C*', ...\unpack('C*', $object));
                $l = \strlen($object);
                $concat = '';
                if ($l <= 253) {
                    $concat .= \chr($l);
                    $concat .= $object;
                    $concat .= \pack('@' . \danog\MadelineProto\Tools::posmod(-$l - 1, 4));
                } else {
                    $concat .= \chr(254);
                    $concat .= \Phabel\Target\Php80\Polyfill::substr(\danog\MadelineProto\Tools::packSignedInt($l), 0, 3);
                    $concat .= $object;
                    $concat .= \pack('@' . \danog\MadelineProto\Tools::posmod(-$l, 4));
                }
                return $concat;
            case 'bytes':
                if (\is_array($object) && isset($object['_']) && $object['_'] === 'bytes') {
                    $object = \base64_decode($object['bytes']);
                }
                if (!\is_string($object) && !$object instanceof \danog\MadelineProto\TL\Types\Bytes) {
                    throw new Exception("You didn't provide a valid string");
                }
                $l = \strlen($object);
                $concat = '';
                if ($l <= 253) {
                    $concat .= \chr($l);
                    $concat .= $object;
                    $concat .= \pack('@' . \danog\MadelineProto\Tools::posmod(-$l - 1, 4));
                } else {
                    $concat .= \chr(254);
                    $concat .= \Phabel\Target\Php80\Polyfill::substr(\danog\MadelineProto\Tools::packSignedInt($l), 0, 3);
                    $concat .= $object;
                    $concat .= \pack('@' . \danog\MadelineProto\Tools::posmod(-$l, 4));
                }
                return $concat;
            case 'Bool':
                return $this->constructors->findByPredicate((bool) $object ? 'boolTrue' : 'boolFalse')['id'];
            case 'true':
                return;
            case '!X':
                return $object;
            case 'Vector t':
                if (!\is_array($object)) {
                    throw new Exception(\danog\MadelineProto\Lang::$current_lang['array_invalid']);
                }
                if (isset($object['_'])) {
                    throw new Exception('You must provide an array of ' . $type['subtype'] . ' objects, not a ' . $type['subtype'] . " object. Example: [['_' => " . $type['subtype'] . ', ... ]]');
                }
                $concat = $this->constructors->findByPredicate('vector')['id'];
                $concat .= \danog\MadelineProto\Tools::packUnsignedInt(\count($object));
                foreach ($object as $k => $current_object) {
                    $concat .= (yield from $this->serializeObject(['type' => $type['subtype']], $current_object, $k, $layer));
                }
                return $concat;
            case 'vector':
                if (!\is_array($object)) {
                    throw new Exception(\danog\MadelineProto\Lang::$current_lang['array_invalid']);
                }
                $concat = \danog\MadelineProto\Tools::packUnsignedInt(\count($object));
                foreach ($object as $k => $current_object) {
                    $concat .= (yield from $this->serializeObject(['type' => $type['subtype']], $current_object, $k, $layer));
                }
                return $concat;
            case 'Object':
                if (\is_string($object)) {
                    return $object;
                }
        }
        if ($type['type'] === 'InputMessage' && !\is_array($object)) {
            $object = ['_' => 'inputMessageID', 'id' => $object];
        } elseif (isset($this->callbacks[TLCallback::TYPE_MISMATCH_CALLBACK][$type['type']]) && (!\is_array($object) || isset($object['_']) && $this->constructors->findByPredicate($object['_'])['type'] !== $type['type'])) {
            $object = $this->callbacks[TLCallback::TYPE_MISMATCH_CALLBACK][$type['type']]($object);
            $object = $object instanceof \Generator ? yield from $object : (yield $object);
            if (!isset($object['_'])) {
                if (!isset($object[$type['type']])) {
                    throw new \danog\MadelineProto\Exception("Could not convert {$type['type']} object");
                }
                $object = $object[$type['type']];
            }
        }
        if (!isset($object['_'])) {
            $constructorData = $this->constructors->findByPredicate($type['type'], $layer);
            if ($constructorData === false) {
                throw new Exception(\danog\MadelineProto\Lang::$current_lang['predicate_not_set']);
            }
            $auto = true;
            $object['_'] = $constructorData['predicate'];
        }
        if (isset($this->callbacks[TLCallback::CONSTRUCTOR_SERIALIZE_CALLBACK][$object['_']])) {
            $object = (yield $this->callbacks[TLCallback::CONSTRUCTOR_SERIALIZE_CALLBACK][$object['_']]($object));
        }
        $predicate = $object['_'];
        $constructorData = $this->constructors->findByPredicate($predicate, $layer);
        if ($constructorData === false) {
            $this->API->logger->logger($object, \danog\MadelineProto\Logger::FATAL_ERROR);
            throw new Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error'], $predicate));
        }
        if ($bare = $type['type'] != '' && $type['type'][0] === '%') {
            $type['type'] = \Phabel\Target\Php80\Polyfill::substr($type['type'], 1);
        }
        if ($predicate === $type['type']) {
            $bare = true;
        }
        if ($predicate === 'messageEntityMentionName') {
            $constructorData = $this->constructors->findByPredicate('inputMessageEntityMentionName');
        }
        $concat = $bare ? '' : $constructorData['id'];
        return $concat . (yield from $this->serializeParams($constructorData, $object, '', $layer, null));
    }
    /**
     * Serialize method.
     *
     * @param string $method Method name
     * @param mixed $arguments Arguments
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (Promise | Promise<\Amp\File\File> | Promise<\Amp\Ipc\Sync\ChannelledSocket> | Promise<int> | Promise<mixed> | Promise<(null | string)> | Promise<string> | \danog\MadelineProto\Stream\StreamInterface | array | int | mixed), mixed, string>
     */
    public function serializeMethod(string $method, $arguments) : \Generator
    {
        $tl = $this->methods->findByMethod($method);
        if ($tl === false) {
            throw new Exception(\danog\MadelineProto\Lang::$current_lang['method_not_found'] . $method);
        }
        return $tl['id'] . (yield from $this->serializeParams($tl, $arguments, $method, -1, $arguments['queuePromise'] ?? null));
    }
    /**
     * Serialize parameters.
     *
     * @param array $tl TL object definition
     * @param array $arguments Arguments
     * @param string $ctx Context
     * @param integer $layer Layer
     *
     * @return \Generator
     *
     * @psalm-return \Generator<(int | mixed), (Promise | Promise<\Amp\File\File> | Promise<\Amp\Ipc\Sync\ChannelledSocket> | Promise<int> | Promise<mixed> | Promise<(null | string)> | \danog\MadelineProto\Stream\StreamInterface | array | int | mixed), mixed, string>
     */
    private function serializeParams(array $tl, $arguments, $ctx, int $layer, $promise) : \Generator
    {
        $serialized = '';
        $arguments = (yield from $this->API->botAPIToMTProto($arguments));
        $flags = 0;
        foreach ($tl['params'] as $cur_flag) {
            if (isset($cur_flag['pow'])) {
                switch ($cur_flag['type']) {
                    case 'true':
                    case 'false':
                        $flags = isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] ? $flags | $cur_flag['pow'] : $flags & ~$cur_flag['pow'];
                        unset($arguments[$cur_flag['name']]);
                        break;
                    case 'Bool':
                        $arguments[$cur_flag['name']] = isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] && ($flags & $cur_flag['pow']) != 0;
                        if (($flags & $cur_flag['pow']) === 0) {
                            unset($arguments[$cur_flag['name']]);
                        }
                        break;
                    default:
                        $flags = isset($arguments[$cur_flag['name']]) && $arguments[$cur_flag['name']] !== null ? $flags | $cur_flag['pow'] : $flags & ~$cur_flag['pow'];
                        break;
                }
            }
        }
        $arguments['flags'] = $flags;
        foreach ($tl['params'] as $current_argument) {
            if (!isset($arguments[$current_argument['name']])) {
                if (isset($current_argument['pow']) && (\in_array($current_argument['type'], ['true', 'false']) || ($flags & $current_argument['pow']) === 0)) {
                    //$this->API->logger->logger('Skipping '.$current_argument['name'].' of type '.$current_argument['type');
                    continue;
                }
                if ($current_argument['name'] === 'random_bytes') {
                    $serialized .= (yield from $this->serializeObject(['type' => 'bytes'], \danog\MadelineProto\Tools::random(15 + 4 * \danog\MadelineProto\Tools::randomInt($modulus = 3)), 'random_bytes'));
                    continue;
                }
                if ($current_argument['name'] === 'data' && isset($tl['method']) && \in_array($tl['method'], ['messages.sendEncrypted', 'messages.sendEncryptedFile', 'messages.sendEncryptedService']) && isset($arguments['message'])) {
                    $serialized .= (yield from $this->serializeObject($current_argument, yield from $this->API->encryptSecretMessage($arguments['peer']['chat_id'], $arguments['message'], $promise), 'data'));
                    continue;
                }
                if ($current_argument['name'] === 'random_id') {
                    switch ($current_argument['type']) {
                        case 'long':
                            $serialized .= \danog\MadelineProto\Tools::random(8);
                            continue 2;
                        case 'int':
                            $serialized .= \danog\MadelineProto\Tools::random(4);
                            continue 2;
                        case 'Vector t':
                            if (isset($arguments['id'])) {
                                $serialized .= $this->constructors->findByPredicate('vector')['id'];
                                $serialized .= \danog\MadelineProto\Tools::packUnsignedInt(\count($arguments['id']));
                                $serialized .= \danog\MadelineProto\Tools::random(8 * \count($arguments['id']));
                                continue 2;
                            }
                    }
                }
                if ($current_argument['name'] === 'hash' && $current_argument['type'] === 'long') {
                    $serialized .= \pack('@8');
                    continue;
                }
                if ($current_argument['name'] === 'hash' && $current_argument['type'] === 'int') {
                    $serialized .= \pack('@4');
                    continue;
                }
                if ($tl['type'] === 'InputMedia' && $current_argument['name'] === 'mime_type') {
                    $serialized .= (yield from $this->serializeObject($current_argument, $arguments['file']['mime_type'], $current_argument['name'], $layer));
                    continue;
                }
                if ($tl['type'] === 'DocumentAttribute' && \in_array($current_argument['name'], ['w', 'h', 'duration'])) {
                    $serialized .= \pack('@4');
                    continue;
                }
                if (\in_array($current_argument['type'], ['bytes', 'string'])) {
                    $serialized .= \pack('@4');
                    continue;
                }
                if (($id = $this->constructors->findByPredicate(\lcfirst($current_argument['type']) . 'Empty', isset($tl['layer']) ? $tl['layer'] : -1)) && $id['type'] === $current_argument['type']) {
                    $serialized .= $id['id'];
                    continue;
                }
                if (($id = $this->constructors->findByPredicate('input' . $current_argument['type'] . 'Empty', isset($tl['layer']) ? $tl['layer'] : -1)) && $id['type'] === $current_argument['type']) {
                    $serialized .= $id['id'];
                    continue;
                }
                switch ($current_argument['type']) {
                    case 'Vector t':
                    case 'vector':
                        $arguments[$current_argument['name']] = [];
                        break;
                    default:
                        throw new Exception("Missing required parameter " . $current_argument['name']);
                }
            }
            if (\in_array($current_argument['type'], ['DataJSON', '%DataJSON'])) {
                $arguments[$current_argument['name']] = ['_' => 'dataJSON', 'data' => \json_encode($arguments[$current_argument['name']])];
            }
            if (isset($current_argument['subtype']) && \in_array($current_argument['subtype'], ['DataJSON', '%DataJSON'])) {
                \array_walk($arguments[$current_argument['name']], function (&$arg) {
                    $arg = ['_' => 'dataJSON', 'data' => \json_encode($arg)];
                });
            }
            if ($current_argument['type'] === 'InputFile' && (!\is_array($arguments[$current_argument['name']]) || !(isset($arguments[$current_argument['name']]['_']) && $this->constructors->findByPredicate($arguments[$current_argument['name']]['_'])['type'] === 'InputFile'))) {
                $arguments[$current_argument['name']] = (yield from $this->API->upload($arguments[$current_argument['name']]));
            }
            if ($current_argument['type'] === 'InputEncryptedChat' && (!\is_array($arguments[$current_argument['name']]) || isset($arguments[$current_argument['name']]['_']) && $this->constructors->findByPredicate($arguments[$current_argument['name']]['_'])['type'] !== $current_argument['type'])) {
                if (\is_array($arguments[$current_argument['name']])) {
                    $arguments[$current_argument['name']] = (yield from $this->API->getInfo($arguments[$current_argument['name']]))['InputEncryptedChat'];
                } else {
                    if (!$this->API->hasSecretChat($arguments[$current_argument['name']])) {
                        throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['sec_peer_not_in_db']);
                    }
                    $arguments[$current_argument['name']] = $this->API->getSecretChat($arguments[$current_argument['name']])['InputEncryptedChat'];
                }
            }
            //$this->API->logger->logger('Serializing '.$current_argument['name'].' of type '.$current_argument['type');
            $serialized .= (yield from $this->serializeObject($current_argument, $arguments[$current_argument['name']], $current_argument['name'], $layer));
        }
        return $serialized;
    }
    /**
     * Get length of TL payload.
     *
     * @param (resource | string) $stream Stream
     * @param array $type Type identifier
     *
     * @return int
     */
    public function getLength($stream, $type = ['type' => '']) : int
    {
        if (\is_string($stream)) {
            $res = \fopen('php://memory', 'rw+b');
            \fwrite($res, $stream);
            \fseek($res, 0);
            $stream = $res;
        } elseif (!\is_resource($stream)) {
            throw new Exception(\danog\MadelineProto\Lang::$current_lang['stream_handle_invalid']);
        }
        $promises = [];
        $this->deserializeInternal($stream, $promises, $type);
        return \ftell($stream);
    }
    /**
     * Deserialize TL object.
     *
     * @param (string | resource) $stream Stream
     * @param array $type Type identifier
     *
     * @return array
     * @psalm-return array{0: mixed, 1: \Amp\Promise[]}
     */
    public function deserialize($stream, $type = ['type' => '']) : array
    {
        $promises = [];
        $result = $this->deserializeInternal($stream, $promises, $type);
        return [$result, $promises];
    }
    /**
     * Deserialize TL object.
     *
     * @param (string | resource) $stream Stream
     * @param Promise[] &$promises Promise array
     * @param array $type Type identifier
     *
     * @return mixed
     */
    private function deserializeInternal($stream, array &$promises, array $type)
    {
        if (\is_string($stream)) {
            $res = \fopen('php://memory', 'rw+b');
            \fwrite($res, $stream);
            \fseek($res, 0);
            $stream = $res;
        } elseif (!\is_resource($stream)) {
            throw new Exception(\danog\MadelineProto\Lang::$current_lang['stream_handle_invalid']);
        }
        switch ($type['type']) {
            case 'Bool':
                return $this->deserializeBool(\stream_get_contents($stream, 4));
            case 'int':
                return \danog\MadelineProto\Tools::unpackSignedInt(\stream_get_contents($stream, 4));
            case '#':
                return \unpack('V', \stream_get_contents($stream, 4))[1];
            case 'long':
                if (isset($type['idstrlong'])) {
                    return \stream_get_contents($stream, 8);
                }
                return isset($type['strlong']) ? \stream_get_contents($stream, 8) : \danog\MadelineProto\Tools::unpackSignedLong(\stream_get_contents($stream, 8));
            case 'double':
                return \danog\MadelineProto\Tools::unpackDouble(\stream_get_contents($stream, 8));
            case 'int128':
                return \stream_get_contents($stream, 16);
            case 'int256':
                return \stream_get_contents($stream, 32);
            case 'int512':
                return \stream_get_contents($stream, 64);
            case 'string':
            case 'bytes':
                $l = \ord(\stream_get_contents($stream, 1));
                if ($l > 254) {
                    throw new Exception(\danog\MadelineProto\Lang::$current_lang['length_too_big']);
                }
                if ($l === 254) {
                    $long_len = \unpack('V', \stream_get_contents($stream, 3) . \chr(0))[1];
                    $x = \stream_get_contents($stream, $long_len);
                    $resto = \danog\MadelineProto\Tools::posmod(-$long_len, 4);
                    if ($resto > 0) {
                        \stream_get_contents($stream, $resto);
                    }
                } else {
                    $x = $l ? \stream_get_contents($stream, $l) : '';
                    $resto = \danog\MadelineProto\Tools::posmod(-($l + 1), 4);
                    if ($resto > 0) {
                        \stream_get_contents($stream, $resto);
                    }
                }
                if (!\is_string($x)) {
                    throw new Exception("Generated value isn't a string");
                }
                return $type['type'] === 'bytes' ? new Types\Bytes($x) : $x;
            case 'Vector t':
                $id = \stream_get_contents($stream, 4);
                $constructorData = $this->constructors->findById($id);
                if ($constructorData === false) {
                    $constructorData = $this->methods->findById($id);
                    $constructorData['predicate'] = 'method_' . $constructorData['method'];
                }
                if ($constructorData === false) {
                    throw new Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error_id'], $type['type'], \bin2hex(\strrev($id))));
                }
                switch ($constructorData['predicate']) {
                    case 'gzip_packed':
                        return $this->deserializeInternal(\gzdecode($this->deserializeInternal($stream, $promises, ['type' => 'bytes', 'connection' => $type['connection']])), $promises, ['type' => '', 'connection' => $type['connection']]);
                    case 'Vector t':
                    case 'vector':
                        break;
                    default:
                        throw new Exception('Invalid vector constructor: ' . $constructorData['predicate']);
                }
            // no break
            case 'vector':
                $count = \unpack('V', \stream_get_contents($stream, 4))[1];
                $result = [];
                $type['type'] = $type['subtype'];
                for ($i = 0; $i < $count; $i++) {
                    $result[] = $this->deserializeInternal($stream, $promises, $type);
                }
                return $result;
        }
        if ($type['type'] != '' && $type['type'][0] === '%') {
            $checkType = \Phabel\Target\Php80\Polyfill::substr($type['type'], 1);
            $constructorData = $this->constructors->findByType($checkType);
            if ($constructorData === false) {
                throw new Exception(\danog\MadelineProto\Lang::$current_lang['constructor_not_found'] . $checkType);
            }
        } else {
            $constructorData = $this->constructors->findByPredicate($type['type']);
            if ($constructorData === false) {
                $id = \stream_get_contents($stream, 4);
                $constructorData = $this->constructors->findById($id);
                if ($constructorData === false) {
                    $constructorData = $this->methods->findById($id);
                    if ($constructorData === false) {
                        throw new Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['type_extract_error_id'], $type['type'], \bin2hex(\strrev($id))));
                    }
                    $constructorData['predicate'] = 'method_' . $constructorData['method'];
                }
            }
        }
        if ($constructorData['predicate'] === 'gzip_packed') {
            if (!isset($type['subtype'])) {
                $type['subtype'] = '';
            }
            return $this->deserializeInternal(\gzdecode($this->deserializeInternal($stream, $promises, ['type' => 'bytes'])), $promises, ['type' => '', 'connection' => $type['connection'], 'subtype' => $type['subtype']]);
        }
        if ($constructorData['type'] === 'Vector t') {
            $constructorData['connection'] = $type['connection'];
            $constructorData['subtype'] = $type['subtype'] ?? '';
            $constructorData['type'] = 'vector';
            return $this->deserializeInternal($stream, $promises, $constructorData);
        }
        if ($constructorData['predicate'] === 'boolTrue') {
            return true;
        }
        if ($constructorData['predicate'] === 'boolFalse') {
            return false;
        }
        $x = ['_' => $constructorData['predicate']];
        if (isset($this->callbacks[TLCallback::CONSTRUCTOR_BEFORE_CALLBACK][$x['_']])) {
            foreach ($this->callbacks[TLCallback::CONSTRUCTOR_BEFORE_CALLBACK][$x['_']] as $callback) {
                $callback($x['_']);
            }
        }
        foreach ($constructorData['params'] as $arg) {
            if (isset($arg['pow'])) {
                switch ($arg['type']) {
                    case 'true':
                    case 'false':
                        $x[$arg['name']] = ($x['flags'] & $arg['pow']) !== 0;
                        continue 2;
                    case 'Bool':
                        if (($x['flags'] & $arg['pow']) === 0) {
                            $x[$arg['name']] = false;
                            continue 2;
                        }
                    // no break
                    default:
                        if (($x['flags'] & $arg['pow']) === 0) {
                            continue 2;
                        }
                }
            }
            if (\in_array($arg['name'], ['msg_ids', 'msg_id', 'bad_msg_id', 'req_msg_id', 'answer_msg_id', 'first_msg_id'])) {
                $arg['idstrlong'] = true;
            }
            if (\in_array($arg['name'], ['key_fingerprint', 'server_salt', 'new_server_salt', 'server_public_key_fingerprints', 'ping_id', 'exchange_id'])) {
                $arg['strlong'] = true;
            }
            if (\in_array($arg['name'], ['peer_tag', 'file_token', 'cdn_key', 'cdn_iv'])) {
                $arg['type'] = 'string';
            }
            if ($x['_'] === 'rpc_result' && $arg['name'] === 'result' && isset($type['connection']->outgoing_messages[$x['req_msg_id']])) {
                /** @var OutgoingMessage */
                $message = $type['connection']->outgoing_messages[$x['req_msg_id']];
                foreach ($this->callbacks[TLCallback::METHOD_BEFORE_CALLBACK][$message->getConstructor()] ?? [] as $callback) {
                    $callback($type['connection']->outgoing_messages[$x['req_msg_id']]->getConstructor());
                }
                if ($message->getType() && \stripos($message->getType(), '<') !== false) {
                    $arg['subtype'] = \str_replace(['Vector<', '>'], '', $message->getType());
                }
            }
            if (isset($type['connection'])) {
                $arg['connection'] = $type['connection'];
            }
            $x[$arg['name']] = $this->deserializeInternal($stream, $promises, $arg);
            if ($arg['name'] === 'random_bytes') {
                if (\strlen($x[$arg['name']]) < 15) {
                    throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['rand_bytes_too_small']);
                }
                unset($x[$arg['name']]);
            }
        }
        if (isset($x['flags'])) {
            // I don't think we need this anymore
            unset($x['flags']);
        }
        if ($x['_'] === 'dataJSON') {
            return \json_decode($x['data'], true);
        } elseif ($constructorData['type'] === 'JSONValue') {
            switch ($x['_']) {
                case 'jsonNull':
                    return;
                case 'jsonObject':
                    $res = [];
                    foreach ($x['value'] as $pair) {
                        $res[$pair['key']] = $pair['value'];
                    }
                    return $res;
                default:
                    return $x['value'];
            }
        } elseif ($x['_'] === 'photoStrippedSize') {
            $x['inflated'] = new Types\Bytes(Tools::inflateStripped($x['bytes']));
        }
        if (isset($this->callbacks[TLCallback::CONSTRUCTOR_CALLBACK][$x['_']])) {
            foreach ($this->callbacks[TLCallback::CONSTRUCTOR_CALLBACK][$x['_']] as $callback) {
                $promise = \danog\MadelineProto\Tools::callFork($callback($x));
                if ($promise instanceof Promise) {
                    $promises[] = $promise;
                }
            }
        } elseif ($x['_'] === 'rpc_result' && isset($type['connection']->outgoing_messages[$x['req_msg_id']]) && isset($this->callbacks[TLCallback::METHOD_CALLBACK][$type['connection']->outgoing_messages[$x['req_msg_id']]->getConstructor()])) {
            foreach ($this->callbacks[TLCallback::METHOD_CALLBACK][$type['connection']->outgoing_messages[$x['req_msg_id']]->getConstructor()] as $callback) {
                $callback($type['connection']->outgoing_messages[$x['req_msg_id']], $x['result']);
            }
        }
        if ($x['_'] === 'message' && isset($x['reply_markup']['rows'])) {
            foreach ($x['reply_markup']['rows'] as $key => $row) {
                foreach ($row['buttons'] as $bkey => $button) {
                    $x['reply_markup']['rows'][$key]['buttons'][$bkey] = new Types\Button($this->API, $x, $button);
                }
            }
        }
        return $x;
    }
}<?php

/**
 * TLParams module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL;

trait TLParams
{
    /**
     *
     */
    public function parseParams($key, $mtproto = false) : void
    {
        foreach ($this->by_id[$key]['params'] as $kkey => $param) {
            if (\preg_match('/(\\w*)\\.(\\d*)\\?(.*)/', $param['type'], $matches)) {
                $param['pow'] = \pow(2, $matches[2]);
                $param['type'] = $matches[3];
            }
            if (\preg_match('/^(v|V)ector\\<(.*)\\>$/', $param['type'], $matches)) {
                $param['type'] = $matches[1] === 'v' ? 'vector' : 'Vector t';
                $param['subtype'] = $matches[2];
                $param['subtype'] = ($mtproto && $param['subtype'] === 'Message' ? 'MT' : '') . $param['subtype'];
                $param['subtype'] = $mtproto && $param['subtype'] === '%Message' ? '%MTMessage' : $param['subtype'];
            }
            $param['type'] = ($mtproto && $param['type'] === 'Message' ? 'MT' : '') . $param['type'];
            $param['type'] = $mtproto && $param['type'] === '%Message' ? '%MTMessage' : $param['type'];
            $this->by_id[$key]['params'][$kkey] = $param;
        }
    }
}<?php

/**
 * TLConstructors module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL;

class TLConstructors
{
    use \danog\Serializable;
    use TLParams;
    public $by_id = [];
    public $by_predicate_and_layer = [];
    public $layers = [];
    /**
     *
     */
    public function __sleep()
    {
        return ['by_predicate_and_layer', 'by_id', 'layers'];
    }
    /**
     *
     */
    public function add(array $json_dict, string $scheme_type) : void
    {
        if (isset($this->by_id[$json_dict['id']]) && (!isset($this->by_id[$json_dict['id']]['layer']) || $this->by_id[$json_dict['id']]['layer'] > $json_dict['layer'])) {
            return;
        }
        $predicate = (string) (($scheme_type === 'mtproto' && $json_dict['predicate'] === 'message' ? 'MT' : '') . $json_dict['predicate']);
        $this->by_id[$json_dict['id']] = ['predicate' => $predicate, 'params' => $json_dict['params'], 'type' => ($scheme_type === 'mtproto' && $json_dict['type'] === 'Message' ? 'MT' : '') . $json_dict['type']];
        if ($scheme_type === 'secret') {
            $this->by_id[$json_dict['id']]['layer'] = $json_dict['layer'];
            $this->layers[$json_dict['layer']] = $json_dict['layer'];
            \ksort($this->layers);
        } else {
            $json_dict['layer'] = '';
        }
        $this->by_predicate_and_layer[$predicate . $json_dict['layer']] = $json_dict['id'];
        $this->parseParams($json_dict['id'], $scheme_type === 'mtproto');
    }
    /**
     *
     */
    public function findByType(string $type)
    {
        foreach ($this->by_id as $id => $constructor) {
            if ($constructor['type'] === $type) {
                $constructor['id'] = $id;
                return $constructor;
            }
        }
        return false;
    }
    /**
     *
     */
    public function findByPredicate(string $predicate, int $layer = -1)
    {
        if ($layer !== -1) {
            $chosenid = null;
            foreach ($this->layers as $alayer) {
                if ($alayer <= $layer) {
                    if (isset($this->by_predicate_and_layer[$predicate . $alayer])) {
                        $chosenid = $this->by_predicate_and_layer[$predicate . $alayer];
                    }
                } elseif (!isset($chosenid)) {
                    $chosenid = $this->by_predicate_and_layer[$predicate . $alayer];
                }
            }
            if (!isset($chosenid)) {
                return $this->findByPredicate($predicate);
            }
            $constructor = $this->by_id[$chosenid];
            $constructor['id'] = $chosenid;
            return $constructor;
        }
        if (isset($this->by_predicate_and_layer[$predicate])) {
            $constructor = $this->by_id[$this->by_predicate_and_layer[$predicate]];
            $constructor['id'] = $this->by_predicate_and_layer[$predicate];
            return $constructor;
        }
        return false;
    }
    /**
     * Find constructor by ID.
     *
     * @param string $id Constructor ID
     *
     * @return (array | false)
     */
    public function findById(string $id)
    {
        if (isset($this->by_id[$id])) {
            $constructor = $this->by_id[$id];
            $constructor['id'] = $id;
            return $constructor;
        }
        return false;
    }
}<?php

/**
 * BotAPIFiles module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL\Conversion;

use danog\Decoder\FileId;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceDialogPhoto;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceLegacy;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceStickersetThumbnail;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceThumbnail;
use danog\MadelineProto\MTProtoTools\PeerHandler;
use const danog\Decoder\ANIMATION;
use const danog\Decoder\AUDIO;
use const danog\Decoder\DOCUMENT;
use const danog\Decoder\PHOTO;
use const danog\Decoder\PHOTOSIZE_SOURCE_THUMBNAIL;
use const danog\Decoder\PROFILE_PHOTO;
use const danog\Decoder\STICKER;
use const danog\Decoder\THUMBNAIL;
use const danog\Decoder\VIDEO;
use const danog\Decoder\VIDEO_NOTE;
use const danog\Decoder\VOICE;
trait BotAPIFiles
{
    /**
     *
     */
    private function photosizeToBotAPI($photoSize, $photo, $thumbnail = false) : array
    {
        $fileId = new FileId();
        $fileId->setId($photo['id'] ?? 0);
        $fileId->setAccessHash($photo['access_hash'] ?? 0);
        $fileId->setFileReference($photo['file_reference'] ?? '');
        $fileId->setDcId($photo['dc_id'] ?? 0);
        if (isset($photoSize['location']['local_id'])) {
            $fileId->setLocalId($photoSize['location']['local_id']);
            $fileId->setVolumeId($photoSize['location']['volume_id']);
        }
        $photoSizeSource = new PhotoSizeSourceThumbnail(PHOTOSIZE_SOURCE_THUMBNAIL);
        $photoSizeSource->setThumbType($photoSize['type']);
        if ($photo['_'] === 'photo') {
            $photoSizeSource->setThumbFileType(PHOTO);
            $fileId->setType(PHOTO);
        } else {
            $photoSizeSource->setThumbFileType(THUMBNAIL);
            $fileId->setType(THUMBNAIL);
        }
        $fileId->setPhotoSizeSource($photoSizeSource);
        return ['file_id' => (string) $fileId, 'file_unique_id' => $fileId->getUniqueBotAPI(), 'width' => $photoSize['w'], 'height' => $photoSize['h'], 'file_size' => $photoSize['size'] ?? (isset($photoSize['sizes']) ? \end($photoSize['sizes']) : \strlen($photoSize['bytes'])), 'mime_type' => 'image/jpeg', 'file_name' => isset($photoSize['location']) ? $photoSize['location']['volume_id'] . '_' . $photoSize['location']['local_id'] . '.jpg' : $photo['id'] . '.jpg'];
    }
    /**
     * Unpack bot API file ID.
     *
     * @param string $fileId Bot API file ID
     *
     * @return array Unpacked file ID
     */
    public function unpackFileId(string $fileId) : array
    {
        $fileId = FileId::fromBotAPI($fileId);
        $this->logger("Got file ID with version {$fileId->getVersion()}.{$fileId->getSubVersion()}");
        if (!\in_array($fileId->getVersion(), [2, 4])) {
            throw new Exception("Invalid bot API file ID version {$fileId->getVersion()}");
        }
        $photoSize = $fileId->hasPhotoSizeSource() ? $fileId->getPhotoSizeSource() : null;
        $res = null;
        switch ($fileId->getType()) {
            case PROFILE_PHOTO:
                /**
                 * @var PhotoSizeSourceDialogPhoto $photoSize
                 */
                if ($photoSize->getDialogId() < 0) {
                    $res['Chat'] = ['_' => $photoSize->getDialogId() < -1000000000000 ? 'channel' : 'chat', 'id' => $photoSize->getDialogId() < -1000000000000 ? PeerHandler::fromSupergroup($photoSize->getDialogId()) : -$photoSize->getDialogId(), 'access_hash' => $photoSize->getDialogAccessHash(), 'photo' => ['_' => 'chatPhoto', 'dc_id' => $fileId->getDcId(), 'photo_id' => $fileId->getId()], 'min' => true];
                    if ($fileId->hasVolumeId()) {
                        $res['photo'][$photoSize->isSmallDialogPhoto() ? 'photo_small' : 'photo_big'] = ['_' => 'fileLocationToBeDeprecated', 'volume_id' => $fileId->getVolumeId(), 'local_id' => $fileId->getLocalId()];
                    }
                    return $res;
                }
                $res['User'] = ['_' => 'user', 'id' => $photoSize->getDialogId(), 'access_hash' => $photoSize->getDialogAccessHash(), 'photo' => ['_' => 'userProfilePhoto', 'dc_id' => $fileId->getDcId(), 'photo_id' => $fileId->getId()], 'min' => true];
                if ($fileId->hasVolumeId()) {
                    $res['photo'][$photoSize->isSmallDialogPhoto() ? 'photo_small' : 'photo_big'] = ['_' => 'fileLocationToBeDeprecated', 'volume_id' => $fileId->getVolumeId(), 'local_id' => $fileId->getLocalId()];
                }
                return $res;
            case THUMBNAIL:
                /**
                 * @var PhotoSizeSourceThumbnail $photoSize
                 */
                $res['InputFileLocation'] = ['_' => $photoSize->getThumbFileType() === THUMBNAIL ? 'inputDocumentFileLocation' : 'inputPhotoFileLocation', 'id' => $fileId->getId(), 'access_hash' => $fileId->getAccessHash(), 'file_reference' => $fileId->getFileReference(), 'thumb_size' => $photoSize->getThumbType()];
                $res['name'] = $fileId->getId() . '_' . $photoSize->getThumbType();
                $res['ext'] = 'jpg';
                $res['mime'] = 'image/jpeg';
                $res['InputMedia'] = ['_' => $photoSize->getThumbFileType() === THUMBNAIL ? 'inputMediaDocument' : 'inputMediaPhoto', 'id' => ['_' => $photoSize->getThumbFileType() === THUMBNAIL ? 'inputDocument' : 'inputPhoto', 'id' => $fileId->getId(), 'access_hash' => $fileId->getAccessHash(), 'file_reference' => $fileId->getFileReference()]];
                if ($res['InputMedia']['id'] === 'inputPhoto') {
                    $res['InputMedia']['id']['sizes'] = [['_' => 'photoSize', 'type' => $photoSize->getThumbType()]];
                }
                return $res;
            case PHOTO:
                $constructor = ['_' => 'photo', 'id' => $fileId->getId(), 'access_hash' => $fileId->getAccessHash(), 'file_reference' => $fileId->getFileReference(), 'dc_id' => $fileId->getDcId(), 'sizes' => []];
                $constructor['sizes'][] = ['_' => 'photoSize', 'type' => $photoSize instanceof PhotoSizeSourceThumbnail ? $photoSize->getThumbType() : '', 'location' => ['_' => $photoSize instanceof PhotoSizeSourceLegacy ? 'fileLocation' : 'fileLocationToBeDeprecated', 'dc_id' => $fileId->getDcId(), 'local_id' => $fileId->hasLocalId() ? $fileId->getLocalId() : null, 'volume_id' => $fileId->hasVolumeId() ? $fileId->getVolumeId() : null, 'secret' => $photoSize instanceof PhotoSizeSourceLegacy ? $photoSize->getSecret() : '']];
                $res['MessageMedia'] = ['_' => 'messageMediaPhoto', 'photo' => $constructor, 'caption' => ''];
                return $res;
            case VOICE:
                $attribute = ['_' => 'documentAttributeAudio', 'voice' => true];
                break;
            case VIDEO:
                $attribute = ['_' => 'documentAttributeVideo', 'round_message' => false];
                break;
            case DOCUMENT:
                $attribute = [];
                break;
            case STICKER:
                $attribute = ['_' => 'documentAttributeSticker', 'alt' => ''];
                if ($photoSize instanceof PhotoSizeSourceStickersetThumbnail) {
                    $attribute['stickerset'] = ['_' => 'inputStickerSetID', 'id' => $photoSize->getStickerSetId(), 'access_hash' => $photoSize->getStickerSetAccessHash()];
                }
                break;
            case AUDIO:
                $attribute = ['_' => 'documentAttributeAudio', 'voice' => false];
                break;
            case ANIMATION:
                $attribute = ['_' => 'documentAttributeAnimated'];
                break;
            case VIDEO_NOTE:
                $attribute = ['_' => 'documentAttributeVideo', 'round_message' => true];
                break;
            default:
                throw new Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['file_type_invalid'], $fileId->getTypeName()));
        }
        $constructor = ['_' => 'document', 'id' => $fileId->getId(), 'access_hash' => $fileId->getAccessHash(), 'file_reference' => $fileId->getFileReference(), 'dc_id' => $fileId->getDcId(), 'mime_type' => '', 'attributes' => $attribute ? [$attribute] : []];
        $res['MessageMedia'] = ['_' => 'messageMediaDocument', 'document' => $constructor, 'caption' => ''];
        return $res;
    }
}<?php

/*
Copyright 2016-2020 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog\MadelineProto\TL\Conversion;

use danog\MadelineProto\Magic;
/**
 * Manages generation of extensions for files.
 */
abstract class Extension
{
    public const ALL_MIMES = ['webp' => [0 => 'image/webp'], 'png' => [0 => 'image/png', 1 => 'image/x-png'], 'bmp' => [0 => 'image/bmp', 1 => 'image/x-bmp', 2 => 'image/x-bitmap', 3 => 'image/x-xbitmap', 4 => 'image/x-win-bitmap', 5 => 'image/x-windows-bmp', 6 => 'image/ms-bmp', 7 => 'image/x-ms-bmp', 8 => 'application/bmp', 9 => 'application/x-bmp', 10 => 'application/x-win-bitmap'], 'gif' => [0 => 'image/gif'], 'jpeg' => [0 => 'image/jpeg', 1 => 'image/pjpeg'], 'xspf' => [0 => 'application/xspf+xml'], 'vlc' => [0 => 'application/videolan'], 'wmv' => [0 => 'video/x-ms-wmv', 1 => 'video/x-ms-asf'], 'au' => [0 => 'audio/x-au'], 'ac3' => [0 => 'audio/ac3'], 'flac' => [0 => 'audio/x-flac'], 'ogg' => [0 => 'audio/ogg', 1 => 'video/ogg', 2 => 'application/ogg'], 'kmz' => [0 => 'application/vnd.google-earth.kmz'], 'kml' => [0 => 'application/vnd.google-earth.kml+xml'], 'rtx' => [0 => 'text/richtext'], 'rtf' => [0 => 'text/rtf'], 'jar' => [0 => 'application/java-archive', 1 => 'application/x-java-application', 2 => 'application/x-jar'], 'zip' => [0 => 'application/x-zip', 1 => 'application/zip', 2 => 'application/x-zip-compressed', 3 => 'application/s-compressed', 4 => 'multipart/x-zip'], '7zip' => [0 => 'application/x-compressed'], 'xml' => [0 => 'application/xml', 1 => 'text/xml'], 'svg' => [0 => 'image/svg+xml'], '3g2' => [0 => 'video/3gpp2'], '3gp' => [0 => 'video/3gp', 1 => 'video/3gpp'], 'mp4' => [0 => 'video/mp4'], 'm4a' => [0 => 'audio/x-m4a'], 'f4v' => [0 => 'video/x-f4v'], 'flv' => [0 => 'video/x-flv'], 'webm' => [0 => 'video/webm'], 'aac' => [0 => 'audio/x-acc'], 'm4u' => [0 => 'application/vnd.mpegurl'], 'pdf' => [0 => 'application/pdf', 1 => 'application/octet-stream'], 'pptx' => [0 => 'application/vnd.openxmlformats-officedocument.presentationml.presentation'], 'ppt' => [0 => 'application/powerpoint', 1 => 'application/vnd.ms-powerpoint', 2 => 'application/vnd.ms-office', 3 => 'application/msword'], 'docx' => [0 => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'], 'xlsx' => [0 => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 1 => 'application/vnd.ms-excel'], 'xl' => [0 => 'application/excel'], 'xls' => [0 => 'application/msexcel', 1 => 'application/x-msexcel', 2 => 'application/x-ms-excel', 3 => 'application/x-excel', 4 => 'application/x-dos_ms_excel', 5 => 'application/xls', 6 => 'application/x-xls'], 'xsl' => [0 => 'text/xsl'], 'mpeg' => [0 => 'video/mpeg'], 'mov' => [0 => 'video/quicktime'], 'avi' => [0 => 'video/x-msvideo', 1 => 'video/msvideo', 2 => 'video/avi', 3 => 'application/x-troff-msvideo'], 'movie' => [0 => 'video/x-sgi-movie'], 'log' => [0 => 'text/x-log'], 'txt' => [0 => 'text/plain'], 'css' => [0 => 'text/css'], 'html' => [0 => 'text/html'], 'wav' => [0 => 'audio/x-wav', 1 => 'audio/wave', 2 => 'audio/wav'], 'xhtml' => [0 => 'application/xhtml+xml'], 'tar' => [0 => 'application/x-tar'], 'tgz' => [0 => 'application/x-gzip-compressed'], 'psd' => [0 => 'application/x-photoshop', 1 => 'image/vnd.adobe.photoshop'], 'exe' => [0 => 'application/x-msdownload'], 'js' => [0 => 'application/x-javascript'], 'mp3' => [0 => 'audio/mpeg', 1 => 'audio/mpg', 2 => 'audio/mpeg3', 3 => 'audio/mp3'], 'rar' => [0 => 'application/x-rar', 1 => 'application/rar', 2 => 'application/x-rar-compressed'], 'gzip' => [0 => 'application/x-gzip'], 'hqx' => [0 => 'application/mac-binhex40', 1 => 'application/mac-binhex', 2 => 'application/x-binhex40', 3 => 'application/x-mac-binhex40'], 'cpt' => [0 => 'application/mac-compactpro'], 'bin' => [0 => 'application/macbinary', 1 => 'application/mac-binary', 2 => 'application/x-binary', 3 => 'application/x-macbinary'], 'oda' => [0 => 'application/oda'], 'ai' => [0 => 'application/postscript'], 'smil' => [0 => 'application/smil'], 'mif' => [0 => 'application/vnd.mif'], 'wbxml' => [0 => 'application/wbxml'], 'wmlc' => [0 => 'application/wmlc'], 'dcr' => [0 => 'application/x-director'], 'dvi' => [0 => 'application/x-dvi'], 'gtar' => [0 => 'application/x-gtar'], 'php' => [0 => 'application/x-httpd-php', 1 => 'application/php', 2 => 'application/x-php', 3 => 'text/php', 4 => 'text/x-php', 5 => 'application/x-httpd-php-source'], 'swf' => [0 => 'application/x-shockwave-flash'], 'sit' => [0 => 'application/x-stuffit'], 'z' => [0 => 'application/x-compress'], 'mid' => [0 => 'audio/midi'], 'aif' => [0 => 'audio/x-aiff', 1 => 'audio/aiff'], 'ram' => [0 => 'audio/x-pn-realaudio'], 'rpm' => [0 => 'audio/x-pn-realaudio-plugin'], 'ra' => [0 => 'audio/x-realaudio'], 'rv' => [0 => 'video/vnd.rn-realvideo'], 'jp2' => [0 => 'image/jp2', 1 => 'video/mj2', 2 => 'image/jpx', 3 => 'image/jpm'], 'tiff' => [0 => 'image/tiff'], 'eml' => [0 => 'message/rfc822'], 'pem' => [0 => 'application/x-x509-user-cert', 1 => 'application/x-pem-file'], 'p10' => [0 => 'application/x-pkcs10', 1 => 'application/pkcs10'], 'p12' => [0 => 'application/x-pkcs12'], 'p7a' => [0 => 'application/x-pkcs7-signature'], 'p7c' => [0 => 'application/pkcs7-mime', 1 => 'application/x-pkcs7-mime'], 'p7r' => [0 => 'application/x-pkcs7-certreqresp'], 'p7s' => [0 => 'application/pkcs7-signature'], 'crt' => [0 => 'application/x-x509-ca-cert', 1 => 'application/pkix-cert'], 'crl' => [0 => 'application/pkix-crl', 1 => 'application/pkcs-crl'], 'pgp' => [0 => 'application/pgp'], 'gpg' => [0 => 'application/gpg-keys'], 'rsa' => [0 => 'application/x-pkcs7'], 'ics' => [0 => 'text/calendar'], 'zsh' => [0 => 'text/x-scriptzsh'], 'cdr' => [0 => 'application/cdr', 1 => 'application/coreldraw', 2 => 'application/x-cdr', 3 => 'application/x-coreldraw', 4 => 'image/cdr', 5 => 'image/x-cdr', 6 => 'zz-application/zz-winassoc-cdr'], 'wma' => [0 => 'audio/x-ms-wma'], 'vcf' => [0 => 'text/x-vcard'], 'srt' => [0 => 'text/srt'], 'vtt' => [0 => 'text/vtt'], 'ico' => [0 => 'image/x-icon', 1 => 'image/x-ico', 2 => 'image/vnd.microsoft.icon'], 'csv' => [0 => 'text/x-comma-separated-values', 1 => 'text/comma-separated-values', 2 => 'application/vnd.msexcel'], 'json' => [0 => 'application/json', 1 => 'text/json']];
    /**
     * Get mime type from file extension.
     *
     * @param string $extension File extension
     * @param string $default Default mime type
     *
     * @return string
     */
    public static function getMimeFromExtension(string $extension, string $default) : string
    {
        $ext = \ltrim($extension, '.');
        if (isset(self::ALL_MIMES[$ext])) {
            return self::ALL_MIMES[$ext][0];
        }
        return $default;
    }
    /**
     * Get extension from mime type.
     *
     * @param string $mime MIME type
     *
     * @return string
     */
    public static function getExtensionFromMime(string $mime) : string
    {
        return Magic::$allMimes[$mime] ?? '';
    }
    /**
     * Get extension from file location.
     *
     * @param mixed $location File location
     * @param string $default Default extension
     *
     * @return string
     */
    public static function getExtensionFromLocation($location, string $default) : string
    {
        return $default;
    }
    /**
     * Get mime type of file.
     *
     * @param string $file File
     *
     * @return string
     */
    public static function getMimeFromFile(string $file) : string
    {
        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        return $finfo->file($file);
    }
    /**
     * Get mime type from buffer.
     *
     * @param string $buffer Buffer
     *
     * @return string
     */
    public static function getMimeFromBuffer(string $buffer) : string
    {
        $finfo = new \finfo(FILEINFO_MIME_TYPE);
        return $finfo->buffer($buffer);
    }
}<?php

/**
 * BotAPI module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL\Conversion;

use danog\Decoder\FileId;
use danog\MadelineProto\Logger;
use danog\MadelineProto\MTProtoTools\PeerHandler;
use danog\MadelineProto\Tools;
use const danog\Decoder\TYPES_IDS;
trait BotAPI
{
    /**
     *
     */
    private function htmlEntityDecode(string $stuff) : string
    {
        return \Phabel\Target\Php80\Polyfill::html_entity_decode(\preg_replace('#< *br */? *>#', "\n", $stuff));
    }
    /**
     * Get Telegram UTF-8 length of string.
     *
     * @param string $text Text
     *
     * @return (float | int)
     */
    public static function mbStrlen(string $text)
    {
        $length = 0;
        $textlength = \strlen($text);
        for ($x = 0; $x < $textlength; $x++) {
            $char = \ord($text[$x]);
            if (($char & 0xc0) != 0x80) {
                $length += 1 + ($char >= 0xf0);
            }
        }
        return $length;
    }
    /**
     * Telegram UTF-8 multibyte substring.
     *
     * @param string $text Text to substring
     * @param integer $offset Offset
     * @param ?int $length Length
     *
     * @return string
     */
    public static function mbSubstr(string $text, int $offset, $length = null) : string
    {
        $mb_text_length = self::mbStrlen($text);
        if ($offset < 0) {
            $offset = $mb_text_length + $offset;
        }
        if ($length < 0) {
            $length = $mb_text_length - $offset + $length;
        } elseif ($length === null) {
            $length = $mb_text_length - $offset;
        }
        $new_text = '';
        $current_offset = 0;
        $current_length = 0;
        $text_length = \strlen($text);
        for ($x = 0; $x < $text_length; $x++) {
            $char = \ord($text[$x]);
            if (($char & 0xc0) != 0x80) {
                $current_offset += 1 + ($char >= 0xf0);
                if ($current_offset > $offset) {
                    $current_length += 1 + ($char >= 0xf0);
                }
            }
            if ($current_offset > $offset) {
                if ($current_length <= $length) {
                    $new_text .= $text[$x];
                }
            }
        }
        return $new_text;
    }
    /**
     * Telegram UTF-8 multibyte split.
     *
     * @param string $text Text
     * @param integer $length Length
     *
     * @return array
     */
    public static function mbStrSplit(string $text, int $length) : array
    {
        $tlength = \mb_strlen($text, 'UTF-8');
        $result = [];
        for ($x = 0; $x < $tlength; $x += $length) {
            $result[] = \mb_substr($text, $x, $length, 'UTF-8');
        }
        return $result;
    }
    /**
     * @return ((bool | mixed | string)[][] | string)[][]
     *
     * @psalm-return array<(int | int), array{_: string, buttons: array<(int | int), array{_: string, text: mixed, same_peer?: bool, query?: mixed, data?: mixed, url?: mixed}>}>
     */
    private function parseButtons($rows) : array
    {
        $newrows = [];
        $key = 0;
        $button_key = 0;
        foreach ($rows as $row) {
            $newrows[$key] = ['_' => 'keyboardButtonRow', 'buttons' => []];
            foreach ($row as $button) {
                $newrows[$key]['buttons'][$button_key] = ['_' => 'keyboardButton', 'text' => $button['text']];
                if (isset($button['url'])) {
                    $newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonUrl';
                    $newrows[$key]['buttons'][$button_key]['url'] = $button['url'];
                } elseif (isset($button['callback_data'])) {
                    $newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonCallback';
                    $newrows[$key]['buttons'][$button_key]['data'] = $button['callback_data'];
                } elseif (isset($button['switch_inline_query'])) {
                    $newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonSwitchInline';
                    $newrows[$key]['buttons'][$button_key]['same_peer'] = false;
                    $newrows[$key]['buttons'][$button_key]['query'] = $button['switch_inline_query'];
                } elseif (isset($button['switch_inline_query_current_chat'])) {
                    $newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonSwitchInline';
                    $newrows[$key]['buttons'][$button_key]['same_peer'] = true;
                    $newrows[$key]['buttons'][$button_key]['query'] = $button['switch_inline_query_current_chat'];
                } elseif (isset($button['callback_game'])) {
                    $newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonGame';
                    $newrows[$key]['buttons'][$button_key]['text'] = $button['callback_game'];
                } elseif (isset($button['request_contact']) && $button['request_contact']) {
                    $newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonRequestPhone';
                } elseif (isset($button['request_location']) && $button['request_location']) {
                    $newrows[$key]['buttons'][$button_key]['_'] = 'keyboardButtonRequestGeoLocation';
                }
                $button_key++;
            }
            $key++;
        }
        return $newrows;
    }
    /**
     *
     */
    private function parseReplyMarkup($markup)
    {
        if (isset($markup['force_reply']) && $markup['force_reply']) {
            $markup['_'] = 'replyKeyboardForceReply';
            unset($markup['force_reply']);
        }
        if (isset($markup['remove_keyboard']) && $markup['remove_keyboard']) {
            $markup['_'] = 'replyKeyboardHide';
            unset($markup['remove_keyboard']);
        }
        if (isset($markup['keyboard'])) {
            $markup['_'] = 'replyKeyboardMarkup';
            if (isset($markup['resize_keyboard'])) {
                $markup['resize'] = $markup['resize_keyboard'];
                unset($markup['resize_keyboard']);
            }
            if (isset($markup['one_time_keyboard'])) {
                $markup['single_use'] = $markup['one_time_keyboard'];
                unset($markup['one_time_keyboard']);
            }
            $markup['rows'] = $this->parseButtons($markup['keyboard']);
            unset($markup['keyboard']);
        }
        if (isset($markup['inline_keyboard'])) {
            $markup['_'] = 'replyInlineMarkup';
            $markup['rows'] = $this->parseButtons($markup['inline_keyboard']);
            unset($markup['inline_keyboard']);
        }
        return $markup;
    }
    /**
     * Convert MTProto parameters to bot API parameters.
     *
     * @param array $data Data
     *
     * @return \Generator<array>
     */
    public function MTProtoToBotAPI(array $data) : \Generator
    {
        $newd = [];
        if (!isset($data['_'])) {
            foreach ($data as $key => $element) {
                $newd[$key] = (yield from $this->MTProtoToBotAPI($element));
            }
            return $newd;
        }
        $res = null;
        switch ($data['_']) {
            case 'updateShortSentMessage':
                $newd['message_id'] = $data['id'];
                $newd['date'] = $data['date'];
                $newd['text'] = $data['request']['body']['message'];
                if ($data['out']) {
                    $newd['from'] = (yield from $this->getPwrChat($this->authorization['user']));
                }
                $newd['chat'] = (yield from $this->getPwrChat($data['request']['body']['peer']));
                if (isset($data['entities'])) {
                    $newd['entities'] = (yield from $this->MTProtoToBotAPI($data['entities']));
                }
                if (isset($data['media'])) {
                    $newd += (yield from $this->MTProtoToBotAPI($data['media']));
                }
                return $newd;
            case 'updates':
                $data = \array_values(\array_filter($data['updates'], fn(array $update) => ($update['_'] !== 'updateMessageID')))[0];
            // no break
            case 'updateNewChannelMessage':
            case 'updateNewMessage':
                return yield from $this->MTProtoToBotAPI($data['message']);
            case 'message':
                $newd['message_id'] = $data['id'];
                $newd['date'] = $data['date'];
                $newd['text'] = $data['message'];
                $newd['post'] = $data['post'];
                $newd['silent'] = $data['silent'];
                if (isset($data['from_id'])) {
                    $newd['from'] = (yield from $this->getPwrChat($data['from_id']));
                }
                $newd['chat'] = (yield from $this->getPwrChat($data['peer_id']));
                if (isset($data['entities'])) {
                    $newd['entities'] = (yield from $this->MTProtoToBotAPI($data['entities']));
                }
                if (isset($data['views'])) {
                    $newd['views'] = $data['views'];
                }
                if (isset($data['edit_date'])) {
                    $newd['edit_date'] = $data['edit_date'];
                }
                if (isset($data['via_bot_id'])) {
                    $newd['via_bot'] = (yield from $this->getPwrChat($data['via_bot_id']));
                }
                if (isset($data['fwd_from']['from_id'])) {
                    $newd['forward_from'] = (yield from $this->getPwrChat($data['fwd_from']['from_id']));
                }
                if (isset($data['fwd_from']['channel_id'])) {
                    try {
                        $newd['forward_from_chat'] = (yield from $this->getPwrChat(PeerHandler::toSupergroup($data['fwd_from']['channel_id'])));
                    } catch (\Throwable $e) {
                    }
                }
                if (isset($data['fwd_from']['date'])) {
                    $newd['forward_date'] = $data['fwd_from']['date'];
                }
                if (isset($data['fwd_from']['channel_post'])) {
                    $newd['forward_from_message_id'] = $data['fwd_from']['channel_post'];
                }
                if (isset($data['media'])) {
                    $newd = \array_merge($newd, yield from $this->MTProtoToBotAPI($data['media']));
                }
                return $newd;
            case 'messageEntityMention':
                unset($data['_']);
                $data['type'] = 'mention';
                return $data;
            case 'messageEntityHashtag':
                unset($data['_']);
                $data['type'] = 'hashtag';
                return $data;
            case 'messageEntityBotCommand':
                unset($data['_']);
                $data['type'] = 'bot_command';
                return $data;
            case 'messageEntityUrl':
                unset($data['_']);
                $data['type'] = 'url';
                return $data;
            case 'messageEntityEmail':
                unset($data['_']);
                $data['type'] = 'email';
                return $data;
            case 'messageEntityBold':
                unset($data['_']);
                $data['type'] = 'bold';
                return $data;
            case 'messageEntityItalic':
                unset($data['_']);
                $data['type'] = 'italic';
                return $data;
            case 'messageEntityCode':
                unset($data['_']);
                $data['type'] = 'code';
                return $data;
            case 'messageEntityPre':
                unset($data['_']);
                $data['type'] = 'pre';
                return $data;
            case 'messageEntityTextUrl':
                unset($data['_']);
                $data['type'] = 'text_url';
                return $data;
            case 'messageEntityMentionName':
                unset($data['_']);
                $data['type'] = 'text_mention';
                $data['user'] = (yield from $this->getPwrChat($data['user_id']));
                unset($data['user_id']);
                return $data;
            case 'messageMediaPhoto':
                if (isset($data['caption'])) {
                    $res['caption'] = $data['caption'];
                }
                $res['photo'] = [];
                foreach ($data['photo']['sizes'] as $key => $photo) {
                    if (\in_array($photo['_'], ['photoCachedSize', 'photoSize', 'photoSizeProgressive'])) {
                        $res['photo'][$key] = $this->photosizeToBotAPI($photo, $data['photo']);
                    }
                }
                return $res;
            case 'messageMediaEmpty':
                return [];
            case 'messageMediaDocument':
                $type_name = 'document';
                $res = [];
                if (isset($data['document']['thumbs']) && $data['document']['thumbs'] && \in_array(\end($data['document']['thumbs'])['_'], ['photoCachedSize', 'photoSize', 'photoSizeProgressive'])) {
                    $res['thumb'] = $this->photosizeToBotAPI(\end($data['document']['thumbs']), $data['document'], true);
                }
                foreach ($data['document']['attributes'] as $attribute) {
                    switch ($attribute['_']) {
                        case 'documentAttributeFilename':
                            $pathinfo = \pathinfo($attribute['file_name']);
                            $res['ext'] = isset($pathinfo['extension']) ? '.' . $pathinfo['extension'] : '';
                            $res['file_name'] = $pathinfo['filename'];
                            break;
                        case 'documentAttributeAudio':
                            $audio = $attribute;
                            $type_name = $attribute['voice'] ? 'voice' : 'audio';
                            $res['duration'] = $attribute['duration'];
                            if (isset($attribute['performer'])) {
                                $res['performer'] = $attribute['performer'];
                            }
                            if (isset($attribute['title'])) {
                                $res['title'] = $attribute['title'];
                            }
                            if (isset($attribute['waveform'])) {
                                $res['title'] = $attribute['waveform'];
                            }
                            break;
                        case 'documentAttributeVideo':
                            $type_name = $attribute['round_message'] ? 'video_note' : 'video';
                            $res['width'] = $attribute['w'];
                            $res['height'] = $attribute['h'];
                            $res['duration'] = $attribute['duration'];
                            break;
                        case 'documentAttributeImageSize':
                            $res['width'] = $attribute['w'];
                            $res['height'] = $attribute['h'];
                            break;
                        case 'documentAttributeAnimated':
                            $type_name = 'animation';
                            $res['animated'] = true;
                            break;
                        case 'documentAttributeHasStickers':
                            $res['has_stickers'] = true;
                            break;
                        case 'documentAttributeSticker':
                            $type_name = 'sticker';
                            $res['mask'] = $attribute['mask'];
                            $res['emoji'] = $attribute['alt'];
                            $res['sticker_set'] = $attribute['stickerset'];
                            if (isset($attribute['mask_coords'])) {
                                $res['mask_coords'] = $attribute['mask_coords'];
                            }
                            break;
                    }
                }
                if (isset($audio) && isset($audio['title']) && !isset($res['file_name'])) {
                    $res['file_name'] = $audio['title'];
                    if (isset($audio['performer'])) {
                        $res['file_name'] .= ' - ' . $audio['performer'];
                    }
                }
                if (!isset($res['file_name'])) {
                    $res['file_name'] = $data['document']['access_hash'];
                }
                $res['file_name'] .= '_' . $data['document']['id'];
                if (isset($res['ext'])) {
                    $res['file_name'] .= $res['ext'];
                    unset($res['ext']);
                } else {
                    $res['file_name'] .= Tools::getExtensionFromMime($data['document']['mime_type']);
                }
                $res['file_size'] = $data['document']['size'];
                $res['mime_type'] = $data['document']['mime_type'];
                $fileId = new FileId();
                $fileId->setId($data['document']['id']);
                $fileId->setAccessHash($data['document']['access_hash']);
                $fileId->setFileReference($data['document']['file_reference'] ?? '');
                $fileId->setDcId($data['document']['dc_id']);
                $fileId->setType(TYPES_IDS[$type_name]);
                $res['file_id'] = (string) $fileId;
                $res['file_unique_id'] = $fileId->getUniqueBotAPI();
                return [$type_name => $res, 'caption' => $data['caption'] ?? ''];
            default:
                throw new Exception(\sprintf(\danog\MadelineProto\Lang::$current_lang['botapi_conversion_error'], $data['_']));
        }
    }
    /**
     * Convert bot API parameters to MTProto parameters.
     *
     * @param array $arguments Arguments
     *
     * @return \Generator<array>
     */
    public function botAPIToMTProto(array $arguments) : \Generator
    {
        foreach (self::BOTAPI_PARAMS_CONVERSION as $bot => $mtproto) {
            if (isset($arguments[$bot]) && !isset($arguments[$mtproto])) {
                $arguments[$mtproto] = $arguments[$bot];
                //unset($arguments[$bot]);
            }
        }
        if (isset($arguments['reply_markup'])) {
            $arguments['reply_markup'] = $this->parseReplyMarkup($arguments['reply_markup']);
        }
        if (isset($arguments['parse_mode'])) {
            $arguments = (yield from $this->parseMode($arguments));
        }
        return $arguments;
    }
    /**
     *
     */
    private function parseNode($node, &$entities, &$new_message, &$offset) : \Generator
    {
        switch ($node->nodeName) {
            case 'br':
                $new_message .= "\n";
                $offset++;
                break;
            case 's':
            case 'strike':
            case 'del':
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $entities[] = ['_' => 'messageEntityStrike', 'offset' => $offset, 'length' => $length];
                $new_message .= $text;
                $offset += $length;
                break;
            case 'u':
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $entities[] = ['_' => 'messageEntityUnderline', 'offset' => $offset, 'length' => $length];
                $new_message .= $text;
                $offset += $length;
                break;
            case 'blockquote':
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $entities[] = ['_' => 'messageEntityBlockquote', 'offset' => $offset, 'length' => $length];
                $new_message .= $text;
                $offset += $length;
                break;
            case 'b':
            case 'strong':
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $entities[] = ['_' => 'messageEntityBold', 'offset' => $offset, 'length' => $length];
                $new_message .= $text;
                $offset += $length;
                break;
            case 'i':
            case 'em':
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $entities[] = ['_' => 'messageEntityItalic', 'offset' => $offset, 'length' => $length];
                $new_message .= $text;
                $offset += $length;
                break;
            case 'code':
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $entities[] = ['_' => 'messageEntityCode', 'offset' => $offset, 'length' => $length];
                $new_message .= $text;
                $offset += $length;
                break;
            case 'pre':
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $language = $node->getAttribute('language');
                if ($language === null) {
                    $language = '';
                }
                $entities[] = ['_' => 'messageEntityPre', 'offset' => $offset, 'length' => $length, 'language' => $language];
                $new_message .= $text;
                $offset += $length;
                break;
            case 'p':
                foreach ($node->childNodes as $node) {
                    yield from $this->parseNode($node, $entities, $new_message, $offset);
                }
                break;
            case 'a':
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $href = $node->getAttribute('href');
                if (\preg_match('|mention:(.*)|', $href, $matches) || \preg_match('|tg://user\\?id=(.*)|', $href, $matches)) {
                    $mention = (yield from $this->getInfo($matches[1]));
                    if (!isset($mention['InputUser'])) {
                        throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
                    }
                    $entities[] = ['_' => 'inputMessageEntityMentionName', 'offset' => $offset, 'length' => $length, 'user_id' => $mention['InputUser']];
                } elseif (\preg_match('|buttonurl:(.*)|', $href)) {
                    if (!isset($entities['buttons'])) {
                        $entities['buttons'] = [];
                    }
                    if (\strpos(\Phabel\Target\Php80\Polyfill::substr($href, -4), '|:new|') !== false) {
                        $entities['buttons'][] = ['_' => 'keyboardButtonUrl', 'text' => $text, 'url' => \str_replace(['buttonurl:', ':new'], '', $href), 'new' => true];
                    } else {
                        $entities['buttons'][] = ['_' => 'keyboardButtonUrl', 'text' => $text, 'url' => \str_replace('buttonurl:', '', $href)];
                    }
                    break;
                } else {
                    $entities[] = ['_' => 'messageEntityTextUrl', 'offset' => $offset, 'length' => $length, 'url' => $href];
                }
                $new_message .= $text;
                $offset += $length;
                break;
            default:
                $text = $this->htmlEntityDecode($node->textContent);
                $length = $this->mbStrlen($text);
                $new_message .= $text;
                $offset += $length;
                break;
        }
    }
    /**
     * Convert markdown and HTML messages.
     *
     * @param array $arguments Arguments
     *
     * @internal
     *
     * @return \Generator<array>
     */
    public function parseMode(array $arguments) : \Generator
    {
        if (($arguments['message'] ?? '') === '' || !isset($arguments['parse_mode'])) {
            return $arguments;
        }
        if (!(\is_string($arguments['message']) || \is_object($arguments['message']) && \method_exists($arguments['message'], '__toString'))) {
            throw new Exception('Messages can only be strings');
        }
        if (isset($arguments['parse_mode']['_'])) {
            $arguments['parse_mode'] = \str_replace('textParseMode', '', $arguments['parse_mode']['_']);
        }
        if (\stripos($arguments['parse_mode'], 'markdown') !== false) {
            $arguments['message'] = \Parsedown::instance()->line($arguments['message']);
            $arguments['parse_mode'] = 'HTML';
        }
        if (\stripos($arguments['parse_mode'], 'html') !== false) {
            $new_message = '';
            $arguments['message'] = \trim($this->htmlFixtags($arguments['message']));
            $dom = new \DOMDocument();
            $dom->loadHTML(\mb_convert_encoding($arguments['message'], 'HTML-ENTITIES', 'UTF-8'));
            if (!isset($arguments['entities'])) {
                $arguments['entities'] = [];
            }
            $offset = 0;
            foreach ($dom->getElementsByTagName('body')->item(0)->childNodes as $node) {
                yield from $this->parseNode($node, $arguments['entities'], $new_message, $offset);
            }
            if (isset($arguments['entities']['buttons'])) {
                $arguments['reply_markup'] = $this->buildRows($arguments['entities']['buttons']);
                unset($arguments['entities']['buttons']);
            }
            unset($arguments['parse_mode']);
            $arguments['message'] = $new_message;
        }
        return $arguments;
    }
    /**
     * Split too long message into chunks.
     *
     * @param array $args Arguments
     *
     * @internal
     *
     * @return \Generator
     */
    public function splitToChunks($args) : \Generator
    {
        $args = (yield from $this->parseMode($args));
        if (!isset($args['entities'])) {
            $args['entities'] = [];
        }
        $max_length = isset($args['media']) ? $this->config['caption_length_max'] : $this->config['message_length_max'];
        $max_entity_length = 100;
        $max_entity_size = 8110;
        $text_arr = [];
        foreach ($this->multipleExplodeKeepDelimiters(["\n"], $args['message']) as $word) {
            if (\mb_strlen($word, 'UTF-8') > $max_length) {
                foreach ($this->mbStrSplit($word, $max_length) as $vv) {
                    $text_arr[] = $vv;
                }
            } else {
                $text_arr[] = $word;
            }
        }
        $multiple_args_base = \array_merge($args, ['entities' => [], 'parse_mode' => 'text', 'message' => '']);
        $multiple_args = [$multiple_args_base];
        $i = 0;
        foreach ($text_arr as $word) {
            if ($this->mbStrlen($multiple_args[$i]['message'] . $word) <= $max_length) {
                $multiple_args[$i]['message'] .= $word;
            } else {
                $i++;
                $multiple_args[$i] = $multiple_args_base;
                $multiple_args[$i]['message'] .= $word;
            }
        }
        $i = 0;
        $offset = 0;
        for ($k = 0; $k < \count($args['entities']); $k++) {
            $entity = $args['entities'][$k];
            do {
                while ($entity['offset'] > $offset + $this->mbStrlen($multiple_args[$i]['message'])) {
                    $offset += $this->mbStrlen($multiple_args[$i]['message']);
                    $i++;
                }
                $entity['offset'] -= $offset;
                if ($entity['offset'] + $entity['length'] > $this->mbStrlen($multiple_args[$i]['message'])) {
                    $newentity = $entity;
                    $newentity['length'] = $entity['length'] - ($this->mbStrlen($multiple_args[$i]['message']) - $entity['offset']);
                    $entity['length'] = $this->mbStrlen($multiple_args[$i]['message']) - $entity['offset'];
                    $offset += $entity['length'];
                    //$this->mbStrlen($multiple_args[$i]['message']);
                    $newentity['offset'] = $offset;
                    $prev_length = $this->mbStrlen($multiple_args[$i]['message']);
                    $multiple_args[$i]['message'] = \rtrim($multiple_args[$i]['message']);
                    $diff = $prev_length - $this->mbStrlen($multiple_args[$i]['message']);
                    if ($diff) {
                        $entity['length'] -= $diff;
                        foreach ($args['entities'] as $key => &$eentity) {
                            if ($key > $k) {
                                $eentity['offset'] -= $diff;
                            }
                        }
                    }
                    $multiple_args[$i]['entities'][] = $entity;
                    $i++;
                    $entity = $newentity;
                    continue;
                }
                $prev_length = $this->mbStrlen($multiple_args[$i]['message']);
                $multiple_args[$i]['message'] = \rtrim($multiple_args[$i]['message']);
                $diff = $prev_length - $this->mbStrlen($multiple_args[$i]['message']);
                if ($diff) {
                    $entity['length'] -= $diff;
                    foreach ($args['entities'] as $key => &$eentity) {
                        if ($key > $k) {
                            $eentity['offset'] -= $diff;
                        }
                    }
                }
                $multiple_args[$i]['entities'][] = $entity;
                break;
            } while (true);
        }
        $total = 0;
        foreach ($multiple_args as $args) {
            if (\count($args['entities']) > $max_entity_length) {
                $total += \count($args['entities']) - $max_entity_length;
            }
            $c = 0;
            foreach ($args['entities'] as $entity) {
                if (isset($entity['url'])) {
                    $c += \strlen($entity['url']);
                }
            }
            if ($c >= $max_entity_size) {
                $this->logger->logger('Entity size limit possibly exceeded, you may get an error indicating that the entities are too long. Reduce the number of entities and/or size of the URLs used.', Logger::FATAL_ERROR);
            }
        }
        if ($total) {
            $this->logger->logger("Too many entities, {$total} entities will be truncated", Logger::FATAL_ERROR);
        }
        return $multiple_args;
    }
    /**
     * @return string[]
     *
     * @psalm-return list<string>
     */
    private function multipleExplodeKeepDelimiters($delimiters, $string) : array
    {
        $initialArray = \explode(\chr(1), \str_replace($delimiters, \chr(1), $string));
        $finalArray = [];
        /** @var int */
        $delimOffset = 0;
        foreach ($initialArray as $item) {
            $delimOffset += $this->mbStrlen($item);
            /** @var int $delimOffset */
            $finalArray[] = $item . ($delimOffset < $this->mbStrlen($string) ? $string[$delimOffset] : '');
            $delimOffset++;
        }
        return $finalArray;
    }
    /**
     *
     */
    private function htmlFixtags($text) : string
    {
        $diff = 0;
        \preg_match_all('#(.*?)(<(\\bu\\b|\\bs\\b|\\ba\\b|\\bb\\b|\\bstrong\\b|\\bblockquote\\b|\\bstrike\\b|\\bdel\\b|\\bem\\b|i|\\bcode\\b|\\bpre\\b)[^>]*>)(.*?)([<]\\s*/\\s*\\3[>])#is', $text, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
        if ($matches) {
            foreach ($matches as $match) {
                if (\trim($match[1][0]) != '') {
                    $mod = \Phabel\Target\Php80\Polyfill::htmlentities($match[1][0]);
                    $temp = \Phabel\Target\Php80\Polyfill::substr($text, 0, $match[1][1] + $diff);
                    $temp .= $mod;
                    $temp .= \Phabel\Target\Php80\Polyfill::substr($text, $match[1][1] + $diff + \strlen($match[1][0]));
                    $diff += \strlen($mod) - \strlen($match[1][0]);
                    $text = $temp;
                }
                $mod = \Phabel\Target\Php80\Polyfill::htmlentities($match[4][0]);
                $temp = \Phabel\Target\Php80\Polyfill::substr($text, 0, $match[4][1] + $diff);
                $temp .= $mod;
                $temp .= \Phabel\Target\Php80\Polyfill::substr($text, $match[4][1] + $diff + \strlen($match[4][0]));
                $diff += \strlen($mod) - \strlen($match[4][0]);
                $text = $temp;
            }
            $diff = 0;
            \preg_match_all('#<a\\s*href=("|\')(.+?)("|\')\\s*>#is', $text, $matches, PREG_OFFSET_CAPTURE);
            foreach ($matches[2] as $match) {
                $mod = \Phabel\Target\Php80\Polyfill::htmlentities($match[0]);
                $temp = \Phabel\Target\Php80\Polyfill::substr($text, 0, $match[1] + $diff);
                $temp .= $mod;
                $temp .= \Phabel\Target\Php80\Polyfill::substr($text, $match[1] + $diff + \strlen($match[0]));
                $diff += \strlen($mod) - \strlen($match[0]);
                $text = $temp;
            }
            return $text;
        }
        return \Phabel\Target\Php80\Polyfill::htmlentities($text);
    }
    /**
     * @return ((array | string)[][] | string)[]
     *
     * @psalm-return array{_: string, rows: list<array{_: string, buttons: list<mixed>}>}
     */
    private function buildRows($button_list) : array
    {
        $end = false;
        $rows = [];
        $buttons = [];
        $cols = 0;
        foreach ($button_list as $button) {
            if (isset($button['new'])) {
                if (\count($buttons) == 0) {
                    $buttons[] = $button;
                } else {
                    $row = ['_' => 'keyboardButtonRow', 'buttons' => $buttons];
                    $rows[] = $row;
                    $buttons = [$button];
                }
            } else {
                $buttons[] = $button;
                $end = true;
            }
        }
        if ($end) {
            $row = ['_' => 'keyboardButtonRow', 'buttons' => $buttons];
            $rows[] = $row;
        }
        return ['_' => 'replyInlineMarkup', 'rows' => $rows];
    }
}<?php

/**
 * Exception module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL\Conversion;

/**
 * TL conversion exception.
 */
class Exception extends \Exception
{
    use \danog\MadelineProto\TL\PrettyException;
    /**
     *
     */
    public function __toString()
    {
        $result = \get_class($this) . ($this->message !== '' ? ': ' : '') . $this->message . PHP_EOL . \danog\MadelineProto\Magic::$revision . PHP_EOL . 'TL Trace (YOU ABSOLUTELY MUST READ THE TEXT BELOW):' . PHP_EOL . PHP_EOL . $this->getTLTrace() . PHP_EOL;
        if (PHP_SAPI !== 'cli' && PHP_SAPI !== 'phpdbg') {
            $result = \str_replace(PHP_EOL, '<br>' . PHP_EOL, $result);
        }
        return $result;
    }
    /**
     *
     */
    public function __construct($message, $file = '')
    {
        parent::__construct($message);
        $this->prettifyTL($file);
    }
}<?php

/**
 * TD module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\TL\Conversion;

trait TD
{
    /**
     * Convert tdcli parameters to tdcli.
     *
     * @param array $params Params
     * @param array $key Key
     *
     * @return array
     */
    public function tdcliToTd(&$params, $key = null) : array
    {
        if (!\is_array($params)) {
            return $params;
        }
        if (!isset($params['ID'])) {
            \array_walk($params, [$this, 'tdcliToTd']);
            return $params;
        }
        foreach ($params as $key => $value) {
            $value = $this->tdcliToTd($value);
            if (\preg_match('/_$/', $key)) {
                $params[\preg_replace('/_$/', '', $key)] = $value;
                unset($params[$key]);
            }
        }
        $params['_'] = \lcfirst($params['ID']);
        unset($params['ID']);
        return $params;
    }
    /**
     * Convert TD to MTProto parameters.
     *
     * @param array $params Parameters
     *
     * @return \Generator<array>
     */
    public function tdToMTProto(array $params) : \Generator
    {
        $newparams = ['_' => self::TD_REVERSE[$params['_']]];
        foreach (self::TD_PARAMS_CONVERSION[$newparams['_']] as $td => $mtproto) {
            if (\is_array($mtproto)) {
                switch (\end($mtproto)) {
                    case 'choose_message_content':
                        switch ($params[$td]['_']) {
                            case 'inputMessageText':
                                $params[$td]['_'] = 'messages.sendMessage';
                                if (isset($params['disable_web_page_preview'])) {
                                    $newparams['no_webpage'] = $params[$td]['disable_web_page_preview'];
                                }
                                $newparams = \array_merge($params[$td], $newparams);
                                break;
                            default:
                                throw new Exception(\danog\MadelineProto\Lang::$current_lang['non_text_conversion']);
                        }
                        break;
                    default:
                        $newparams[$mtproto[0]] = isset($params[$td]) ? $params[$td] : null;
                        if (\is_array($newparams[$mtproto[0]])) {
                            $newparams[$mtproto[0]] = (yield from $this->MTProtoToTd($newparams[$mtproto[0]]));
                        }
                }
            }
        }
        return $newparams;
    }
    /**
     * MTProto to TDCLI params.
     *
     * @param mixed $params Params
     *
     * @return \Generator
     */
    public function MTProtoToTdcli($params) : \Generator
    {
        return $this->tdToTdcli(yield from $this->MTProtoToTd($params));
    }
    /**
     * MTProto to TD params.
     *
     * @param mixed $params Params
     *
     * @return \Generator
     */
    public function MTProtoToTd(&$params) : \Generator
    {
        if (!\is_array($params)) {
            return $params;
        }
        if (!isset($params['_'])) {
            \array_walk($params, [$this, 'mtprotoToTd']);
            return $params;
        }
        $newparams = ['_' => $params['_']];
        if (\in_array($params['_'], self::TD_IGNORE)) {
            return $params;
        }
        foreach (self::TD_PARAMS_CONVERSION[$params['_']] as $td => $mtproto) {
            if (\is_string($mtproto)) {
                $newparams[$td] = $mtproto;
            } else {
                switch (\end($mtproto)) {
                    case 'choose_chat_id_from_botapi':
                        $newparams[$td] = (yield from $this->getInfo($params[$mtproto[0]]))['bot_api_id'] == $this->authorization['user']['id'] ? $this->getId($params['from_id']) : (yield from $this->getInfo($params[$mtproto[0]]))['bot_api_id'];
                        break;
                    case 'choose_incoming_or_sent':
                        $newparams[$td] = ['_' => $params['out'] ? 'messageIsSuccessfullySent' : 'messageIsIncoming'];
                        break;
                    case 'choose_can_edit':
                        $newparams[$td] = !isset($params['fwd_from']) && $params['out'];
                        break;
                    case 'choose_can_delete':
                        $newparams[$td] = $params['out'];
                        break;
                    case 'choose_forward_info':
                        if (isset($params['fwd_from'])) {
                            $newparams[$td] = ['_' => 'messageForwardedFromUser'];
                            if (isset($params['fwd_from']['channel_id'])) {
                                $newparams[$td] = ['_' => 'messageForwardedPost', 'chat_id' => '-100' . $params['fwd_from']['channel_id']];
                            }
                            $newparams[$td]['date'] = $params['fwd_from']['date'];
                            if (isset($params['fwd_from']['channel_post'])) {
                                $newparams[$td]['channel_post'] = $params['fwd_from']['channel_post'];
                            }
                            if (isset($params['fwd_from']['from_id'])) {
                                $newparams[$td]['sender_user_id'] = $this->getId($params['fwd_from']['from_id']);
                            }
                        } else {
                            $newparams[$td] = null;
                        }
                        break;
                    case 'choose_ttl':
                        $newparams[$td] = isset($params['ttl']) ? $params['ttl'] : 0;
                        break;
                    case 'choose_ttl_expires_in':
                        $newparams[$td] = $newparams['ttl'] - \microtime(true);
                        break;
                    case 'choose_message_content':
                        if ($params['message'] !== '') {
                            $newparams[$td] = ['_' => 'messageText', 'text' => $params['message']];
                            if (isset($params['media']['_']) && $params['media']['_'] === 'messageMediaWebPage') {
                                $newparams[$td]['web_page'] = (yield from $this->MTProtoToTd($params['media']['webpage']));
                            }
                            if (isset($params['entities'])) {
                                $newparams[$td]['entities'] = $params['entities'];
                            }
                        } else {
                            throw new Exception(\danog\MadelineProto\Lang::$current_lang['non_text_conversion']);
                        }
                        break;
                    default:
                        if (isset($mtproto[1])) {
                            $newparams[$td] = isset($params[$mtproto[0]][$mtproto[1]]) ? $params[$mtproto[0]][$mtproto[1]] : null;
                        } else {
                            $newparams[$td] = isset($params[$mtproto[0]]) ? $params[$mtproto[0]] : null;
                        }
                        if (\is_array($newparams[$td])) {
                            $newparams[$td] = (yield from $this->MTProtoToTd($newparams[$td]));
                        }
                }
            }
        }
        return $newparams;
    }
    /**
     * Convert TD parameters to tdcli.
     *
     * @param mixed $params Parameters
     *
     * @return mixed
     */
    public function tdToTdcli($params)
    {
        if (!\is_array($params)) {
            return $params;
        }
        $newparams = [];
        foreach ($params as $key => $value) {
            if ($key === '_') {
                $newparams['ID'] = \ucfirst($value);
            } else {
                if (!\is_numeric($key) && !\str_ends_with($key, '_')) {
                    $key = $key . '_';
                }
                $newparams[$key] = $this->tdToTdcli($value);
            }
        }
        return $newparams;
    }
}<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog\MadelineProto\VoIP;

trait AckHandler
{
    /**
     *
     */
    public function seqgt($s1, $s2)
    {
        return $s1 > $s2;
    }
    /**
     *
     */
    public function received_packet($last_ack_id, $packet_seq_no, $ack_mask)
    {
        if ($this->seqgt($packet_seq_no, $this->session_in_seq_no)) {
            $diff = $packet_seq_no - $this->session_in_seq_no;
            if ($diff > 31) {
                $this->received_timestamp_map = \array_fill(0, 32, 0);
            } else {
                $remaining = 32 - $diff;
                for ($x = 0; $x < $remaining; $x++) {
                    $this->received_timestamp_map[$diff + $x] = $this->received_timestamp_map[$x];
                }
                for ($x = 1; $x < $diff; $x++) {
                    $this->received_timestamp_map[$x] = 0;
                }
                $this->received_timestamp_map[0] = \microtime(true);
            }
            $this->session_in_seq_no = $packet_seq_no;
        } elseif (($diff = $this->session_in_seq_no - $packet_seq_no) < 32) {
            if (!$this->received_timestamp_map[$diff]) {
                \danog\MadelineProto\Logger::log("Got duplicate {$packet_seq_no}");
                return false;
            }
            $this->received_timestamp_map[$diff] = \microtime(true);
        } else {
            \danog\MadelineProto\Logger::log("Packet {$packet_seq_no} is out of order and too late");
            return false;
        }
        if ($this->seqgt($last_ack_id, $this->session_out_seq_no)) {
            $diff = $last_ack_id - $this->session_out_seq_no;
            if ($diff > 31) {
                $this->remote_ack_timestamp_map = \array_fill(0, 32, 0);
            } else {
                $remaining = 32 - $diff;
                for ($x = 0; $x < $remaining; $x++) {
                    $this->remote_ack_timestamp_map[$diff + $x] = $this->remote_ack_timestamp_map[$x];
                }
                for ($x = 1; $x < $diff; $x++) {
                    $this->remote_ack_timestamp_map[$x] = 0;
                }
                $this->remote_ack_timestamp_map[0] = \microtime(true);
            }
            $this->session_out_seq_no = $last_ack_id;
            for ($x = 1; $x < 32; $x++) {
                if (!$this->remote_ack_timestamp_map[$x] && $ack_mask >> 32 - $x & 1) {
                    $this->remote_ack_timestamp_map[$x] = \microtime(true);
                }
            }
        }
        return true;
    }
}<?php

namespace danog\MadelineProto\VoIP;

use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Success;
use danog\MadelineProto\MTProto\PermAuthKey;
use danog\MadelineProto\MTProtoTools\Crypt;
use danog\MadelineProto\VoIP;
use function Amp\Socket\connect;
class Endpoint
{
    /**
     * IP address.
     */
    private string $ip;
    /**
     * Port.
     */
    private int $port;
    /**
     * Peer tag.
     */
    private string $peerTag;
    /**
     * Whether we're a reflector.
     */
    private bool $reflector;
    /**
     * Call instance.
     */
    private VoIP $instance;
    /**
     * The socket.
     */
    private ?EncryptableSocket $socket = null;
    /**
     * Whether we're the creator.
     */
    private bool $creator;
    /**
     * The auth key.
     */
    private PermAuthKey $authKey;
    /**
     * Create endpoint.
     *
     * @param string $ip
     * @param integer $port
     * @param string $peerTag
     * @param VoIP $instance
     */
    public function __construct(string $ip, int $port, string $peerTag, bool $reflector, VoIP $instance)
    {
        $this->ip = $ip;
        $this->port = $port;
        $this->peerTag = $peerTag;
        $this->reflector = $reflector;
        $this->instance = $instance;
        $this->creator = $instance->isCreator();
        $this->authKey = $instance->getAuthKey();
    }
    /**
     * Connect to endpoint.
     *
     * @return \Generator
     */
    public function connect() : \Generator
    {
        $this->socket = (yield connect("udp://{$this->ip}:{$this->port}"));
    }
    /**
     * Disconnect from endpoint.
     *
     * @return void
     */
    public function disconnect() : void
    {
        if ($this->socket !== null) {
            $this->socket->close();
            $this->socket = null;
        }
    }
    /**
     * Read packet.
     *
     * @return \Generator
     */
    public function read() : \Generator
    {
        do {
            $packet = (yield $this->socket->read());
            if ($packet === null) {
                return null;
            }
            $payload = \fopen('php://memory', 'rw+b');
            \fwrite($payload, $packet);
            \fseek($payload, 0);
            $hasPeerTag = false;
            if ($this->instance->getPeerVersion() < 9 || $this->reflector) {
                $hasPeerTag = true;
                if (\stream_get_contents($payload, 16) !== $this->peerTag) {
                    \danog\MadelineProto\Logger::log("Received packet has wrong peer tag", \danog\MadelineProto\Logger::ERROR);
                    continue;
                }
            }
            if (\stream_get_contents($payload, 12) === "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00") {
                $payload = \stream_get_contents($payload);
            } else {
                \fseek($payload, $hasPeerTag ? 16 : 0);
                $message_key = \stream_get_contents($payload, 16);
                [$aes_key, $aes_iv] = Crypt::aesCalculate($message_key, $this->authKey->getAuthKey(), !$this->creator);
                $encrypted_data = \stream_get_contents($payload);
                $packet = Crypt::igeDecrypt($encrypted_data, $aes_key, $aes_iv);
                if ($message_key != \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', \Phabel\Target\Php80\Polyfill::substr($this->authKey->getAuthKey(), 88 + ($this->creator ? 8 : 0), 32) . $packet, true), 8, 16)) {
                    \danog\MadelineProto\Logger::log("msg_key mismatch!", \danog\MadelineProto\Logger::ERROR);
                    return false;
                }
                $innerLen = \unpack('v', \Phabel\Target\Php80\Polyfill::substr($packet, 0, 2))[1];
                if ($innerLen > \strlen($packet)) {
                    \danog\MadelineProto\Logger::log("Received packet has wrong inner length!", \danog\MadelineProto\Logger::ERROR);
                    return false;
                }
                $packet = \Phabel\Target\Php80\Polyfill::substr($packet, 2);
            }
            $stream = \fopen('php://memory', 'rw+b');
            \fwrite($stream, $packet);
            \fseek($stream, 0);
            return $stream;
        } while (true);
    }
    /**
     * Write data.
     *
     * @param string $payload
     * @return Promise
     */
    public function write(string $payload) : Promise
    {
        if ($this->socket === null) {
            return new Success(0);
        }
        $plaintext = \pack('v', \strlen($payload)) . $payload;
        $padding = 16 - \strlen($plaintext) % 16;
        if ($padding < 16) {
            $padding += 16;
        }
        $plaintext .= \danog\MadelineProto\Tools::random($padding);
        $message_key = \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', \Phabel\Target\Php80\Polyfill::substr($this->authKey->getAuthKey(), 88 + ($this->creator ? 0 : 8), 32) . $plaintext, true), 8, 16);
        list($aes_key, $aes_iv) = Crypt::aesCalculate($message_key, $this->authKey->getAuthKey(), $this->creator);
        $payload = $message_key . Crypt::igeEncrypt($plaintext, $aes_key, $aes_iv);
        if ($this->instance->getPeerVersion() < 9 || $this->reflector) {
            $payload = $this->peerTag . $payload;
        }
        return $this->socket->write($payload);
    }
    /**
     * Get peer tag.
     *
     * @return string
     */
    public function getPeerTag() : string
    {
        return $this->peerTag;
    }
}<?php

/**
 * AuthKeyHandler module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto\VoIP;

use danog\MadelineProto\Loop\Update\UpdateLoop;
use danog\MadelineProto\MTProtoTools\Crypt;
use danog\MadelineProto\Tools;
/**
 * Manages the creation of the authorization key.
 *
 * https://core.telegram.org/mtproto/auth_key
 * https://core.telegram.org/mtproto/samples-auth_key
 */
trait AuthKeyHandler
{
    private $calls = [];
    /**
     * Accept call from VoIP instance.
     *
     * @param \danog\MadelineProto\VoIP $instance Call instance
     * @param array $user User
     *
     * @internal
     *
     * @return mixed
     */
    public function acceptCallFrom($instance, $user)
    {
        $promise = Tools::call((function () use($instance, $user) {
            if (!($res = (yield from $this->acceptCall($user)))) {
                $instance->discard();
                return false;
            }
            return $instance;
        })());
        if ($this->wrapper && $this->wrapper->isAsync()) {
            return $promise;
        }
        return Tools::wait($promise);
    }
    /**
     * Undocumented function.
     *
     * @param \danog\MadelineProto\VoIP $instance Call instance
     * @param array $call Call info
     * @param array $reason Discard reason
     * @param array $rating Rating
     * @param boolean $need_debug Needs debug?
     *
     * @internal
     *
     * @return mixed
     */
    public function discardCallFrom($instance, $call, $reason, $rating = [], $need_debug = true)
    {
        $promise = Tools::call(function () use($instance, $call, $reason, $rating, $need_debug) {
            if (!($res = (yield from $this->discardCall($call, $reason, $rating, $need_debug)))) {
                return false;
            }
            return $instance;
        });
        if ($this->wrapper && $this->wrapper->isAsync()) {
            return $promise;
        }
        return Tools::wait($promise);
    }
    /**
     * Request VoIP call.
     *
     * @param mixed $user User
     *
     * @return \Generator
     */
    public function requestCall($user) : \Generator
    {
        if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
            throw \danog\MadelineProto\Exception::extension('libtgvoip');
        }
        $user = (yield from $this->getInfo($user));
        if (!isset($user['InputUser']) || $user['InputUser']['_'] === 'inputUserSelf') {
            throw new \danog\MadelineProto\Exception(\danog\MadelineProto\Lang::$current_lang['peer_not_in_db']);
        }
        $user = $user['InputUser'];
        $this->logger->logger(\sprintf("Calling %s...", $user['user_id']), \danog\MadelineProto\Logger::VERBOSE);
        $dh_config = (yield from $this->getDhConfig());
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['generating_a'], \danog\MadelineProto\Logger::VERBOSE);
        $a = \phpseclib3\Math\BigInteger::randomRange(\danog\MadelineProto\Magic::$two, $dh_config['p']->subtract(\danog\MadelineProto\Magic::$two));
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['generating_g_a'], \danog\MadelineProto\Logger::VERBOSE);
        $g_a = $dh_config['g']->powMod($a, $dh_config['p']);
        Crypt::checkG($g_a, $dh_config['p']);
        $controller = new \danog\MadelineProto\VoIP(true, $user['user_id'], $this, \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED);
        $controller->storage = ['a' => $a, 'g_a' => \str_pad($g_a->toBytes(), 256, \chr(0), \STR_PAD_LEFT)];
        $res = (yield from $this->methodCallAsyncRead('phone.requestCall', ['user_id' => $user, 'g_a_hash' => \hash('sha256', $g_a->toBytes(), true), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_p2p' => true, 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]]));
        $controller->setCall($res['phone_call']);
        $this->calls[$res['phone_call']['id']] = $controller;
        (yield $this->updaters[UpdateLoop::GENERIC]->resume());
        return $controller;
    }
    /**
     * Accept call.
     *
     * @param array $call Call
     *
     * @return \Generator
     */
    public function acceptCall(array $call) : \Generator
    {
        if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
            throw new \danog\MadelineProto\Exception();
        }
        if ($this->callStatus($call['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED) {
            $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_1'], $call['id']));
            return false;
        }
        $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['accepting_call'], $this->calls[$call['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
        $dh_config = (yield from $this->getDhConfig());
        $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['generating_b'], \danog\MadelineProto\Logger::VERBOSE);
        $b = \phpseclib3\Math\BigInteger::randomRange(\danog\MadelineProto\Magic::$two, $dh_config['p']->subtract(\danog\MadelineProto\Magic::$two));
        $g_b = $dh_config['g']->powMod($b, $dh_config['p']);
        Crypt::checkG($g_b, $dh_config['p']);
        try {
            $res = (yield from $this->methodCallAsyncRead('phone.acceptCall', ['peer' => ['id' => $call['id'], 'access_hash' => $call['access_hash'], '_' => 'inputPhoneCall'], 'g_b' => $g_b->toBytes(), 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'udp_p2p' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]]));
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            if ($e->rpc === 'CALL_ALREADY_ACCEPTED') {
                $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $call['id']));
                return true;
            }
            if ($e->rpc === 'CALL_ALREADY_DECLINED') {
                $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['call_already_declined']);
                yield from $this->discardCall($call['id'], ['_' => 'phoneCallDiscardReasonHangup']);
                return false;
            }
            throw $e;
        }
        $this->calls[$res['phone_call']['id']]->storage['b'] = $b;
        (yield $this->updaters[UpdateLoop::GENERIC]->resume());
        return true;
    }
    /**
     * Confirm call.
     *
     * @param array $params Params
     *
     * @return \Generator
     */
    public function confirmCall(array $params) : \Generator
    {
        if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
            throw \danog\MadelineProto\Exception::extension('libtgvoip');
        }
        if ($this->callStatus($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_REQUESTED) {
            $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_2'], $params['id']));
            return false;
        }
        $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_confirming'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
        $dh_config = (yield from $this->getDhConfig());
        $params['g_b'] = new \phpseclib3\Math\BigInteger((string) $params['g_b'], 256);
        Crypt::checkG($params['g_b'], $dh_config['p']);
        $key = \str_pad($params['g_b']->powMod($this->calls[$params['id']]->storage['a'], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
        try {
            $res = (yield from $this->methodCallAsyncRead('phone.confirmCall', ['key_fingerprint' => \Phabel\Target\Php80\Polyfill::substr(\sha1($key, true), -8), 'peer' => ['id' => $params['id'], 'access_hash' => $params['access_hash'], '_' => 'inputPhoneCall'], 'g_a' => $this->calls[$params['id']]->storage['g_a'], 'protocol' => ['_' => 'phoneCallProtocol', 'udp_reflector' => true, 'min_layer' => 65, 'max_layer' => \danog\MadelineProto\VoIP::getConnectionMaxLayer()]]))['phone_call'];
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            if ($e->rpc === 'CALL_ALREADY_ACCEPTED') {
                $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_already_accepted'], $params['id']));
                return true;
            }
            if ($e->rpc === 'CALL_ALREADY_DECLINED') {
                $this->logger->logger(\danog\MadelineProto\Lang::$current_lang['call_already_declined']);
                yield from $this->discardCall($params['id'], ['_' => 'phoneCallDiscardReasonHangup']);
                return false;
            }
            throw $e;
        }
        $this->calls[$params['id']]->setCall($res);
        $visualization = [];
        $length = new \phpseclib3\Math\BigInteger(\count(\danog\MadelineProto\Magic::$emojis));
        foreach (\str_split(\hash('sha256', $key . \str_pad($this->calls[$params['id']]->storage['g_a'], 256, \chr(0), \STR_PAD_LEFT), true), 8) as $number) {
            $number[0] = \chr(\ord($number[0]) & 0x7f);
            $visualization[] = \danog\MadelineProto\Magic::$emojis[(int) (new \phpseclib3\Math\BigInteger($number, 256))->divide($length)[1]->toString()];
        }
        $this->calls[$params['id']]->setVisualization($visualization);
        $this->calls[$params['id']]->configuration['endpoints'] = \array_merge($res['connections'], $this->calls[$params['id']]->configuration['endpoints']);
        $this->calls[$params['id']]->configuration = \array_merge(['recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000, 'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000, 'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER, 'enable_NS' => true, 'enable_AEC' => true, 'enable_AGC' => true, 'auth_key' => $key, 'auth_key_id' => \Phabel\Target\Php80\Polyfill::substr(\sha1($key, true), -8), 'call_id' => \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration);
        $this->calls[$params['id']]->parseConfig();
        $res = $this->calls[$params['id']]->startTheMagic();
        return $res;
    }
    /**
     * Complete call handshake.
     *
     * @param array $params Params
     *
     * @return \Generator
     */
    public function completeCall(array $params) : \Generator
    {
        if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
            throw \danog\MadelineProto\Exception::extension('libtgvoip');
        }
        if ($this->callStatus($params['id']) !== \danog\MadelineProto\VoIP::CALL_STATE_ACCEPTED || !isset($this->calls[$params['id']]->storage['b'])) {
            $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_error_3'], $params['id']));
            return false;
        }
        $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_completing'], $this->calls[$params['id']]->getOtherID()), \danog\MadelineProto\Logger::VERBOSE);
        $dh_config = (yield from $this->getDhConfig());
        if (\hash('sha256', $params['g_a_or_b'], true) != $this->calls[$params['id']]->storage['g_a_hash']) {
            throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['invalid_g_a']);
        }
        $params['g_a_or_b'] = new \phpseclib3\Math\BigInteger((string) $params['g_a_or_b'], 256);
        Crypt::checkG($params['g_a_or_b'], $dh_config['p']);
        $key = \str_pad($params['g_a_or_b']->powMod($this->calls[$params['id']]->storage['b'], $dh_config['p'])->toBytes(), 256, \chr(0), \STR_PAD_LEFT);
        if (\Phabel\Target\Php80\Polyfill::substr(\sha1($key, true), -8) != $params['key_fingerprint']) {
            throw new \danog\MadelineProto\SecurityException(\danog\MadelineProto\Lang::$current_lang['fingerprint_invalid']);
        }
        $visualization = [];
        $length = new \phpseclib3\Math\BigInteger(\count(\danog\MadelineProto\Magic::$emojis));
        foreach (\str_split(\hash('sha256', $key . \str_pad($params['g_a_or_b']->toBytes(), 256, \chr(0), \STR_PAD_LEFT), true), 8) as $number) {
            $number[0] = \chr(\ord($number[0]) & 0x7f);
            $visualization[] = \danog\MadelineProto\Magic::$emojis[(int) (new \phpseclib3\Math\BigInteger($number, 256))->divide($length)[1]->toString()];
        }
        $this->calls[$params['id']]->setVisualization($visualization);
        $this->calls[$params['id']]->configuration['endpoints'] = \array_merge($params['connections'], $this->calls[$params['id']]->configuration['endpoints']);
        $this->calls[$params['id']]->configuration = \array_merge(['recv_timeout' => $this->config['call_receive_timeout_ms'] / 1000, 'init_timeout' => $this->config['call_connect_timeout_ms'] / 1000, 'data_saving' => \danog\MadelineProto\VoIP::DATA_SAVING_NEVER, 'enable_NS' => true, 'enable_AEC' => true, 'enable_AGC' => true, 'auth_key' => $key, 'auth_key_id' => \Phabel\Target\Php80\Polyfill::substr(\sha1($key, true), -8), 'call_id' => \Phabel\Target\Php80\Polyfill::substr(\hash('sha256', $key, true), -16), 'network_type' => \danog\MadelineProto\VoIP::NET_TYPE_ETHERNET], $this->calls[$params['id']]->configuration);
        $this->calls[$params['id']]->parseConfig();
        return $this->calls[$params['id']]->startTheMagic();
    }
    /**
     * Get call status.
     *
     * @param int $id Call ID
     *
     * @return integer
     */
    public function callStatus($id) : int
    {
        if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
            throw \danog\MadelineProto\Exception::extension('libtgvoip');
        }
        if (isset($this->calls[$id])) {
            return $this->calls[$id]->getCallState();
        }
        return \danog\MadelineProto\VoIP::CALL_STATE_NONE;
    }
    /**
     * Get call info.
     *
     * @param int $call Call ID
     *
     * @return array
     */
    public function getCall($call) : array
    {
        if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
            throw \danog\MadelineProto\Exception::extension('libtgvoip');
        }
        return $this->calls[$call];
    }
    /**
     * Discard call.
     *
     * @param array $call Call
     * @param array $reason
     * @param array $rating Rating
     * @param boolean $need_debug Need debug?
     *
     * @return \Generator
     */
    public function discardCall(array $call, array $reason, array $rating = [], bool $need_debug = true) : \Generator
    {
        if (!\class_exists('\\danog\\MadelineProto\\VoIP')) {
            throw \danog\MadelineProto\Exception::extension('libtgvoip');
        }
        if (!isset($this->calls[$call['id']])) {
            return;
        }
        $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_discarding'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
        try {
            $res = (yield from $this->methodCallAsyncRead('phone.discardCall', ['peer' => $call, 'duration' => \time() - $this->calls[$call['id']]->whenCreated(), 'connection_id' => $this->calls[$call['id']]->getPreferredRelayID(), 'reason' => $reason]));
        } catch (\danog\MadelineProto\RPCErrorException $e) {
            if (!\in_array($e->rpc, ['CALL_ALREADY_DECLINED', 'CALL_ALREADY_ACCEPTED'])) {
                throw $e;
            }
        }
        if (!empty($rating)) {
            $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_set_rating'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
            yield from $this->methodCallAsyncRead('phone.setCallRating', ['peer' => $call, 'rating' => $rating['rating'], 'comment' => $rating['comment']]);
        }
        if ($need_debug && isset($this->calls[$call['id']])) {
            $this->logger->logger(\sprintf(\danog\MadelineProto\Lang::$current_lang['call_debug_saving'], $call['id']), \danog\MadelineProto\Logger::VERBOSE);
            yield from $this->methodCallAsyncRead('phone.saveCallDebug', ['peer' => $call, 'debug' => $this->calls[$call['id']]->getDebugLog()]);
        }
        $update = ['_' => 'updatePhoneCall', 'phone_call' => $this->calls[$call['id']]];
        $this->updates[$this->updates_key++] = $update;
        unset($this->calls[$call['id']]);
    }
    /**
     * Check state of calls.
     *
     * @internal
     *
     * @return void
     */
    public function checkCalls() : void
    {
        \array_walk($this->calls, function ($controller, $id) {
            if ($controller->getCallState() === \danog\MadelineProto\VoIP::CALL_STATE_ENDED) {
                $this->logger("Discarding ended call...");
                $controller->discard();
                unset($this->calls[$id]);
            }
        });
    }
}<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog\MadelineProto\VoIP;

use danog\MadelineProto\TL\Exception;
use danog\MadelineProto\Tools;
/**
 * Manages packing and unpacking of messages, and the list of sent and received messages.
 */
trait MessageHandler
{
    /**
     *
     */
    public function pack_string($object)
    {
        $l = \strlen($object);
        $concat = '';
        if ($l <= 253) {
            $concat .= \chr($l);
            $concat .= $object;
            $concat .= \pack('@' . Tools::posmod(-$l - 1, 4));
        } else {
            $concat .= \chr(254);
            $concat .= \Phabel\Target\Php80\Polyfill::substr(Tools::packSignedInt($l), 0, 3);
            $concat .= $object;
            $concat .= \pack('@' . Tools::posmod(-$l, 4));
        }
        return $concat;
    }
    /**
     *
     */
    public function unpack_string($stream)
    {
        $l = \ord(\stream_get_contents($stream, 1));
        if ($l > 254) {
            throw new Exception(\danog\MadelineProto\Lang::$current_lang['length_too_big']);
        }
        if ($l === 254) {
            $long_len = \unpack('V', \stream_get_contents($stream, 3) . \chr(0))[1];
            $x = \stream_get_contents($stream, $long_len);
            $resto = Tools::posmod(-$long_len, 4);
            if ($resto > 0) {
                \stream_get_contents($stream, $resto);
            }
        } else {
            $x = \stream_get_contents($stream, $l);
            $resto = Tools::posmod(-($l + 1), 4);
            if ($resto > 0) {
                \stream_get_contents($stream, $resto);
            }
        }
        return $x;
    }
    /**
     *
     */
    public function send_message($args, $datacenter = null)
    {
        if ($datacenter === null) {
            return $this->send_message($args, \reset($this->sockets));
        }
        $message = '';
        switch ($args['_']) {
            // streamTypeSimple codec:int8 = StreamType;
            //
            // packetInit#1 protocol:int min_protocol:int flags:# data_saving_enabled:flags.0?true audio_streams:byteVector<streamTypeSimple> video_streams:byteVector<streamTypeSimple> = Packet;
            case \danog\MadelineProto\VoIP::PKT_INIT:
                $message .= Tools::packSignedInt($args['protocol']);
                $message .= Tools::packSignedInt($args['min_protocol']);
                $flags = 0;
                $flags = isset($args['data_saving_enabled']) && $args['data_saving_enabled'] ? $flags | 1 : $flags & ~1;
                $message .= Tools::packUnsignedInt($flags);
                $message .= \chr(\count($args['audio_streams']));
                foreach ($args['audio_streams'] as $codec) {
                    $message .= $codec;
                }
                $message .= \chr(0);
                $message .= \chr(\count($args['video_streams']));
                foreach ($args['video_streams'] as $codec) {
                    $message .= \chr($codec);
                }
                break;
            // streamType id:int8 type:int8 codec:int8 frame_duration:int16 enabled:int8 = StreamType;
            //
            // packetInitAck#2 protocol:int min_protocol:int all_streams:byteVector<streamType> = Packet;
            case \danog\MadelineProto\VoIP::PKT_INIT_ACK:
                $message .= Tools::packSignedInt($args['protocol']);
                $message .= Tools::packSignedInt($args['min_protocol']);
                $message .= \chr(\count($args['all_streams']));
                foreach ($args['all_streams'] as $stream) {
                    $message .= \chr($stream['id']);
                    $message .= \chr($stream['type']);
                    $message .= $stream['codec'];
                    $message .= \pack('v', $stream['frame_duration']);
                    $message .= \chr($stream['enabled']);
                }
                break;
            // streamTypeState id:int8 enabled:int8 = StreamType;
            // packetStreamState#3 state:streamTypeState = Packet;
            case \danog\MadelineProto\VoIP::PKT_STREAM_STATE:
                $message .= \chr($args['id']);
                $message .= \chr($args['enabled']);
                break;
            // streamData flags:int2 stream_id:int6 has_more_flags:flags.1?true length:(flags.0?int16:int8) timestamp:int data:byteArray = StreamData;
            // packetStreamData#4 stream_data:streamData = Packet;
            case \danog\MadelineProto\VoIP::PKT_STREAM_DATA:
                $length = \strlen($args['data']);
                $flags = 0;
                $flags = $length > 255 ? $flags | 1 : $flags & ~1;
                $flags = isset($args['has_more_flags']) && $args['has_more_flags'] ? $flags | 2 : $flags & ~2;
                $flags = $flags << 6;
                $flags = $flags | $args['stream_id'];
                $message .= \chr($flags);
                $message .= $length > 255 ? \pack('v', $length) : \chr($length);
                $message .= Tools::packUnsignedInt($args['timestamp']);
                $message .= $args['data'];
                break;
            /*case \danog\MadelineProto\VoIP::PKT_UPDATE_STREAMS:
                  break;
              case \danog\MadelineProto\VoIP::PKT_PING:
                  break;*/
            case \danog\MadelineProto\VoIP::PKT_PONG:
                $message .= Tools::packUnsignedInt($args['out_seq_no']);
                break;
            case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X2:
                for ($x = 0; $x < 2; $x++) {
                    $length = \strlen($args[$x]['data']);
                    $flags = 0;
                    $flags = $length > 255 ? $flags | 1 : $flags & ~1;
                    $flags = isset($args[$x]['has_more_flags']) && $args[$x]['has_more_flags'] ? $flags | 2 : $flags & ~2;
                    $flags = $flags << 6;
                    $flags = $flags | $args[$x]['stream_id'];
                    $message .= \chr($flags);
                    $message .= $length > 255 ? \pack('v', $length) : \chr($length);
                    $message .= Tools::packUnsignedInt($args[$x]['timestamp']);
                    $message .= $args[$x]['data'];
                }
                break;
            case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X3:
                for ($x = 0; $x < 3; $x++) {
                    $length = \strlen($args[$x]['data']);
                    $flags = 0;
                    $flags = $length > 255 ? $flags | 1 : $flags & ~1;
                    $flags = isset($args[$x]['has_more_flags']) && $args[$x]['has_more_flags'] ? $flags | 2 : $flags & ~2;
                    $flags = $flags << 6;
                    $flags = $flags | $args[$x]['stream_id'];
                    $message .= \chr($flags);
                    $message .= $length > 255 ? \pack('v', $length) : \chr($length);
                    $message .= Tools::packUnsignedInt($args[$x]['timestamp']);
                    $message .= $args[$x]['data'];
                }
                break;
            // packetLanEndpoint#A address:int port:int = Packet;
            case \danog\MadelineProto\VoIP::PKT_LAN_ENDPOINT:
                $message .= Tools::packSignedInt($args['address']);
                $message .= Tools::packSignedInt($args['port']);
                break;
            // packetNetworkChanged#B flags:# data_saving_enabled:flags.0?true = Packet;
            case \danog\MadelineProto\VoIP::PKT_NETWORK_CHANGED:
                $message .= Tools::packSignedInt(isset($args['data_saving_enabled']) && $args['data_saving_enabled'] ? 1 : 0);
                break;
            // packetSwitchPreferredRelay#C relay_id:long = Packet;
            case \danog\MadelineProto\VoIP::PKT_SWITCH_PREF_RELAY:
                $message .= Tools::packSignedLong($args['relay_d']);
                break;
        }
        $ack_mask = 0;
        for ($x = 0; $x < 32; $x++) {
            if ($this->received_timestamp_map[$x] > 0) {
                $ack_mask |= 1;
            }
            if ($x < 31) {
                $ack_mask <<= 1;
            }
        }
        if ($this->peerVersion >= 8 || !$this->peerVersion && true) {
            $payload = \chr($args['_']);
            $payload .= Tools::packUnsignedInt($this->session_in_seq_no);
            $payload .= Tools::packUnsignedInt($this->session_out_seq_no);
            $payload .= Tools::packUnsignedInt($ack_mask);
            $payload .= \chr(0);
            $payload .= $message;
        } elseif (\in_array($this->voip_state, [\danog\MadelineProto\VoIP::STATE_WAIT_INIT, \danog\MadelineProto\VoIP::STATE_WAIT_INIT_ACK])) {
            $payload = $this->TLID_DECRYPTED_AUDIO_BLOCK;
            $payload .= Tools::random(8);
            $payload .= \chr(7);
            $payload .= Tools::random(7);
            $flags = 0;
            $flags = $flags | 4;
            // call_id
            $flags = $flags | 16;
            // seqno
            $flags = $flags | 32;
            // ack mask
            $flags = $flags | 8;
            // proto
            $flags = isset($args['extra']) ? $flags | 2 : $flags & ~2;
            // extra
            $flags = \strlen($message) ? $flags | 1 : $flags & ~1;
            // raw_data
            $flags = $flags | $args['_'] << 24;
            $payload .= Tools::packUnsignedInt($flags);
            $payload .= $this->configuration['call_id'];
            $payload .= Tools::packUnsignedInt($this->session_in_seq_no);
            $payload .= Tools::packUnsignedInt($this->session_out_seq_no);
            $payload .= Tools::packUnsignedInt($ack_mask);
            $payload .= \danog\MadelineProto\VoIP::PROTO_ID;
            if ($flags & 2) {
                $payload .= $this->pack_string($args['extra']);
            }
            if ($flags & 1) {
                $payload .= $this->pack_string($message);
            }
        } else {
            $payload = $this->TLID_SIMPLE_AUDIO_BLOCK;
            $payload .= Tools::random(8);
            $payload .= \chr(7);
            $payload .= Tools::random(7);
            $message = \chr($args['_']) . Tools::packUnsignedInt($this->session_in_seq_no) . Tools::packUnsignedInt($this->session_out_seq_no) . Tools::packUnsignedInt($ack_mask) . $message;
            $payload .= $this->pack_string($message);
        }
        $this->session_out_seq_no++;
        return $datacenter->write($payload);
    }
    /**
     * Reading connection and receiving message from server.
     */
    public function recv_message(Endpoint $endpoint)
    {
        if (!($payload = (yield from $endpoint->read()))) {
            return null;
        }
        $result = [];
        switch ($crc = \stream_get_contents($payload, 4)) {
            case $this->TLID_DECRYPTED_AUDIO_BLOCK:
                \stream_get_contents($payload, 8);
                $this->unpack_string($payload);
                $flags = \unpack('V', \stream_get_contents($payload, 4))[1];
                $result['_'] = $flags >> 24;
                if ($flags & 4) {
                    if (\stream_get_contents($payload, 16) !== $this->configuration['call_id']) {
                        \danog\MadelineProto\Logger::log('Call ID mismatch', \danog\MadelineProto\Logger::ERROR);
                        return false;
                    }
                }
                if ($flags & 16) {
                    $in_seq_no = \unpack('V', \stream_get_contents($payload, 4))[1];
                    $out_seq_no = \unpack('V', \stream_get_contents($payload, 4))[1];
                }
                if ($flags & 32) {
                    $ack_mask = \unpack('V', \stream_get_contents($payload, 4))[1];
                }
                if ($flags & 8) {
                    if (\stream_get_contents($payload, 4) !== \danog\MadelineProto\VoIP::PROTO_ID) {
                        \danog\MadelineProto\Logger::log('Protocol mismatch', \danog\MadelineProto\Logger::ERROR);
                        return false;
                    }
                }
                if ($flags & 2) {
                    $result['extra'] = $this->unpack_string($payload);
                }
                $message = \fopen('php://memory', 'rw+b');
                if ($flags & 1) {
                    \fwrite($message, $this->unpack_string($payload));
                    \fseek($message, 0);
                }
                break;
            case $this->TLID_SIMPLE_AUDIO_BLOCK:
                \stream_get_contents($payload, 8);
                $this->unpack_string($payload);
                $flags = \unpack('V', \stream_get_contents($payload, 4))[1];
                $message = \fopen('php://memory', 'rw+b');
                \fwrite($message, $this->unpack_string($payload));
                \fseek($message, 0);
                $result['_'] = \ord(\stream_get_contents($message, 1));
                $in_seq_no = \unpack('V', \stream_get_contents($message, 4))[1];
                $out_seq_no = \unpack('V', \stream_get_contents($message, 4))[1];
                $ack_mask = \unpack('V', \stream_get_contents($message, 4))[1];
                break;
            case $this->TLID_REFLECTOR_SELF_INFO:
                $result['date'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
                $result['query_id'] = Tools::unpackSignedLong(\stream_get_contents($payload, 8));
                $result['my_ip'] = \stream_get_contents($payload, 16);
                $result['my_port'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
                return $result;
            case $this->TLID_REFLECTOR_PEER_INFO:
                $result['my_address'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
                $result['my_port'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
                $result['peer_address'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
                $result['peer_port'] = Tools::unpackSignedInt(\stream_get_contents($payload, 4));
                return $result;
            default:
                if ($this->peerVersion >= 8 || !$this->peerVersion && true) {
                    \fseek($payload, 0);
                    $result['_'] = \ord(\stream_get_contents($payload, 1));
                    $in_seq_no = \unpack('V', \stream_get_contents($payload, 4))[1];
                    $out_seq_no = \unpack('V', \stream_get_contents($payload, 4))[1];
                    $ack_mask = \unpack('V', \stream_get_contents($payload, 4))[1];
                    $flags = \ord(\stream_get_contents($payload, 1));
                    if ($flags & 1) {
                        $result['extra'] = [];
                        $count = \ord(\stream_get_contents($payload, 1));
                        for ($x = 0; $x < $count; $x++) {
                            $len = \ord(\stream_get_contents($payload, 1));
                            $result['extra'][] = \stream_get_contents($payload, $len);
                        }
                    }
                    $message = \fopen('php://memory', 'rw+b');
                    \fwrite($message, \stream_get_contents($payload));
                    \fseek($message, 0);
                } else {
                    \danog\MadelineProto\Logger::log('Unknown packet received: ' . \bin2hex($crc), \danog\MadelineProto\Logger::ERROR);
                    return false;
                }
        }
        if (!$this->received_packet($in_seq_no, $out_seq_no, $ack_mask)) {
            return yield from $this->recv_message($endpoint);
        }
        switch ($result['_']) {
            // streamTypeSimple codec:int8 = StreamType;
            //
            // packetInit#1 protocol:int min_protocol:int flags:# data_saving_enabled:flags.0?true audio_streams:byteVector<streamTypeSimple> video_streams:byteVector<streamTypeSimple> = Packet;
            case \danog\MadelineProto\VoIP::PKT_INIT:
                $result['protocol'] = $this->peerVersion = Tools::unpackSignedInt(\stream_get_contents($message, 4));
                $result['min_protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
                $flags = \unpack('V', \stream_get_contents($message, 4))[1];
                $result['data_saving_enabled'] = (bool) ($flags & 1);
                $result['audio_streams'] = [];
                $length = \ord(\stream_get_contents($message, 1));
                for ($x = 0; $x < $length; $x++) {
                    $result['audio_streams'][$x] = \stream_get_contents($message, 4);
                }
                break;
            // streamType id:int8 type:int8 codec:int8 frame_duration:int16 enabled:int8 = StreamType;
            //
            // packetInitAck#2 protocol:int min_protocol:int all_streams:byteVector<streamType> = Packet;
            case \danog\MadelineProto\VoIP::PKT_INIT_ACK:
                $result['protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
                $result['min_protocol'] = Tools::unpackSignedInt(\stream_get_contents($message, 4));
                $result['all_streams'] = [];
                $length = \ord(\stream_get_contents($message, 1));
                for ($x = 0; $x < $length; $x++) {
                    $result['all_streams'][$x]['id'] = \ord(\stream_get_contents($message, 1));
                    $result['all_streams'][$x]['type'] = \stream_get_contents($message, 4);
                    $result['all_streams'][$x]['codec'] = \ord(\stream_get_contents($message, 1));
                    $result['all_streams'][$x]['frame_duration'] = \unpack('v', \stream_get_contents($message, 2))[1];
                    $result['all_streams'][$x]['enabled'] = \ord(\stream_get_contents($message, 1));
                }
                break;
            // streamTypeState id:int8 enabled:int8 = StreamType;
            // packetStreamState#3 state:streamTypeState = Packet;
            case \danog\MadelineProto\VoIP::PKT_STREAM_STATE:
                $result['id'] = \ord(\stream_get_contents($message, 1));
                $result['enabled'] = \ord(\stream_get_contents($message, 1));
                break;
            // streamData flags:int2 stream_id:int6 has_more_flags:flags.1?true length:(flags.0?int16:int8) timestamp:int data:byteArray = StreamData;
            // packetStreamData#4 stream_data:streamData = Packet;
            case \danog\MadelineProto\VoIP::PKT_STREAM_DATA:
                $flags = \ord(\stream_get_contents($message, 1));
                $result['stream_id'] = $flags & 0x3f;
                $flags = ($flags & 0xc0) >> 6;
                $result['has_more_flags'] = (bool) ($flags & 2);
                $length = $flags & 1 ? \unpack('v', \stream_get_contents($message, 2))[1] : \ord(\stream_get_contents($message, 1));
                $result['timestamp'] = \unpack('V', \stream_get_contents($message, 4))[1];
                $result['data'] = \stream_get_contents($message, $length);
                break;
            /*case \danog\MadelineProto\VoIP::PKT_UPDATE_STREAMS:
                  break;
              case \danog\MadelineProto\VoIP::PKT_PING:
                  break;*/
            case \danog\MadelineProto\VoIP::PKT_PONG:
                if (\fstat($payload)['size'] - \ftell($payload)) {
                    $result['out_seq_no'] = \unpack('V', \stream_get_contents($payload, 4))[1];
                }
                break;
            case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X2:
                for ($x = 0; $x < 2; $x++) {
                    $flags = \ord(\stream_get_contents($message, 1));
                    $result[$x]['stream_id'] = $flags & 0x3f;
                    $flags = ($flags & 0xc0) >> 6;
                    $result[$x]['has_more_flags'] = (bool) ($flags & 2);
                    $length = $flags & 1 ? \unpack('v', \stream_get_contents($message, 2))[1] : \ord(\stream_get_contents($message, 1));
                    $result[$x]['timestamp'] = \unpack('V', \stream_get_contents($message, 4))[1];
                    $result[$x]['data'] = \stream_get_contents($message, $length);
                }
                break;
            case \danog\MadelineProto\VoIP::PKT_STREAM_DATA_X3:
                for ($x = 0; $x < 3; $x++) {
                    $flags = \ord(\stream_get_contents($message, 1));
                    $result[$x]['stream_id'] = $flags & 0x3f;
                    $flags = ($flags & 0xc0) >> 6;
                    $result[$x]['has_more_flags'] = (bool) ($flags & 2);
                    $length = $flags & 1 ? \unpack('v', \stream_get_contents($message, 2))[1] : \ord(\stream_get_contents($message, 1));
                    $result[$x]['timestamp'] = \unpack('V', \stream_get_contents($message, 4))[1];
                    $result[$x]['data'] = \stream_get_contents($message, $length);
                }
                break;
            // packetLanEndpoint#A address:int port:int = Packet;
            case \danog\MadelineProto\VoIP::PKT_LAN_ENDPOINT:
                $result['address'] = \unpack('V', \stream_get_contents($payload, 4))[1];
                $result['port'] = \unpack('V', \stream_get_contents($payload, 4))[1];
                break;
            // packetNetworkChanged#B flags:# data_saving_enabled:flags.0?true = Packet;
            case \danog\MadelineProto\VoIP::PKT_NETWORK_CHANGED:
                $result['data_saving_enabled'] = (bool) (\unpack('V', \stream_get_contents($payload, 4))[1] & 1);
                break;
            // packetSwitchPreferredRelay#C relay_id:long = Packet;
            case \danog\MadelineProto\VoIP::PKT_SWITCH_PREF_RELAY:
                $result['relay_id'] = Tools::unpackSignedLong(\stream_get_contents($payload, 8));
                break;
        }
        return $result;
    }
}<?php

/**
 * APIFactory module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use danog\MadelineProto\Async\AsyncConstruct;
use danog\MadelineProto\Ipc\Client;
abstract class AbstractAPIFactory extends AsyncConstruct
{
    /**
     * Namespace.
     *
     * @internal
     *
     * @var string
     */
    private string $namespace = '';
    /**
     * Whether lua is being used.
     *
     * @internal
     *
     * @var boolean
     */
    public bool $lua = false;
    /**
     * Whether async is enabled.
     *
     * @internal
     *
     * @var boolean
     */
    protected bool $async = false;
    /**
     * Method list.
     *
     * @var array<string, callable>
     */
    protected array $methods = [];
    /**
     * Main API instance.
     */
    private API $mainAPI;
    /**
     * Export APIFactory instance with the specified namespace.
     *
     * @param string $namespace Namespace
     *
     * @return self
     */
    protected function exportNamespace(string $namespace = '') : self
    {
        $class = \array_reverse(\array_values(\class_parents(static::class)))[$namespace ? 2 : 3];
        $instance = new $class();
        $instance->namespace = $namespace ? $namespace . '.' : '';
        self::link($instance, $this);
        return $instance;
    }
    /**
     * Link two APIFactory instances.
     *
     * @param self $a First instance
     * @param self $b Second instance
     *
     * @return void
     */
    protected static function link(self $a, self $b) : void
    {
        $a->lua =& $b->lua;
        $a->async =& $b->async;
        $a->methods =& $b->methods;
        if ($b instanceof API) {
            $a->mainAPI = $b;
            $b->mainAPI = $b;
        } elseif ($a instanceof API) {
            $a->mainAPI = $a;
            $b->mainAPI = $a;
        } else {
            $a->mainAPI =& $b->mainAPI;
        }
        if (!$b->inited()) {
            $a->setInitPromise($b->initAsynchronously());
        }
    }
    /**
     * Enable or disable async.
     *
     * @param bool $async Whether to enable or disable async
     *
     * @return void
     */
    public function async(bool $async) : void
    {
        $this->async = $async;
    }
    /**
     * Call async wrapper function.
     *
     * @param string $name Method name
     * @param array $arguments Arguments
     *
     * @internal
     *
     * @return mixed
     */
    public function __call(string $name, array $arguments)
    {
        if ($arguments && !isset($arguments[0])) {
            $arguments = [$arguments];
        }
        $yielded = Tools::call($this->__call_async($name, $arguments));
        $async = !$this->lua && ((\is_array(\end($arguments)) ? \end($arguments) : [])['async'] ?? $this->async && $name !== 'loop');
        if ($async) {
            return $yielded;
        }
        $yielded = Tools::wait($yielded);
        if (!$this->lua) {
            return $yielded;
        }
        try {
            Lua::convertObjects($yielded);
            return $yielded;
        } catch (\Throwable $e) {
            return ['error_code' => $e->getCode(), 'error' => $e->getMessage()];
        }
    }
    /**
     * Info to dump.
     *
     * @return array
     */
    public function __debugInfo() : array
    {
        $keys = APIWrapper::properties();
        $res = [];
        foreach ($keys as $key) {
            if (Tools::hasVar($this, $key)) {
                $res[$key] = Tools::getVar($this, $key);
            }
        }
        return $res;
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep()
    {
        return [];
    }
    /**
     * Call async wrapper function.
     *
     * @param string $name Method name
     * @param array $arguments Arguments
     *
     * @internal
     *
     * @return \Generator
     */
    public function __call_async(string $name, array $arguments) : \Generator
    {
        yield from $this->initAsynchronously();
        $lower_name = \strtolower($name);
        if ($this->namespace !== '' || !isset($this->methods[$lower_name])) {
            $name = $this->namespace . $name;
            $aargs = isset($arguments[1]) && \is_array($arguments[1]) ? $arguments[1] : [];
            $aargs['apifactory'] = true;
            $args = isset($arguments[0]) && \is_array($arguments[0]) ? $arguments[0] : [];
            return yield from $this->mainAPI->API->methodCallAsyncRead($name, $args, $aargs);
        }
        if ($lower_name === 'seteventhandler' || $lower_name === 'loop' && !isset($arguments[0])) {
            yield from $this->mainAPI->reconnectFull();
        }
        $res = $this->methods[$lower_name](...$arguments);
        return $res instanceof \Generator ? yield from $res : (yield $res);
    }
    /**
     * Get fully resolved method list for object, including snake_case and camelCase variants.
     *
     * @param (API | MTProto | Client) $value Value
     * @param string $class Custom class name
     *
     * @return array
     */
    protected static function getInternalMethodList($value, string $class = null) : array
    {
        return \array_map(fn($method) => [$value, $method], self::getInternalMethodListClass($class ?? \get_class($value)));
    }
    /**
     * Get fully resolved method list for object, including snake_case and camelCase variants.
     *
     * @param string $class Class name
     *
     * @return array
     */
    protected static function getInternalMethodListClass(string $class) : array
    {
        static $cache = [];
        if (isset($cache[$class])) {
            return $cache[$class];
        }
        $methods = \get_class_methods($class);
        foreach ($methods as $method) {
            if ($method == 'methodCallAsyncRead') {
                unset($methods[\array_search('methodCall', $methods)]);
            } elseif (\stripos($method, 'async') !== false) {
                if (\strpos($method, '_async') !== false) {
                    unset($methods[\array_search(\str_ireplace('_async', '', $method), $methods)]);
                } else {
                    unset($methods[\array_search(\str_ireplace('async', '', $method), $methods)]);
                }
            }
        }
        $finalMethods = [];
        foreach ($methods as $method) {
            $actual_method = $method;
            if ($method == 'methodCallAsyncRead') {
                $method = 'methodCall';
            } elseif (\stripos($method, 'async') !== false) {
                if (\strpos($method, '_async') !== false) {
                    $method = \str_ireplace('_async', '', $method);
                } else {
                    $method = \str_ireplace('async', '', $method);
                }
            }
            $finalMethods[\strtolower($method)] = $actual_method;
            if (\strpos($method, '_') !== false) {
                $finalMethods[\strtolower(\str_replace('_', '', $method))] = $actual_method;
            } else {
                $finalMethods[\strtolower(StrTools::toSnakeCase($method))] = $actual_method;
            }
        }
        $cache[$class] = $finalMethods;
        return $finalMethods;
    }
}<?php

/**
 * MTProto module.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\Dns\Resolver;
use Amp\Http\Client\HttpClient;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
use Closure;
use danog\MadelineProto\Async\AsyncConstruct;
use danog\MadelineProto\Db\DbArray;
use danog\MadelineProto\Db\DbPropertiesFactory;
use danog\MadelineProto\Db\DbPropertiesTrait;
use danog\MadelineProto\Db\MemoryArray;
use danog\MadelineProto\Ipc\Server;
use danog\MadelineProto\Loop\Generic\PeriodicLoopInternal;
use danog\MadelineProto\Loop\Update\FeedLoop;
use danog\MadelineProto\Loop\Update\SecretFeedLoop;
use danog\MadelineProto\Loop\Update\SeqLoop;
use danog\MadelineProto\Loop\Update\UpdateLoop;
use danog\MadelineProto\MTProtoTools\CombinedUpdatesState;
use danog\MadelineProto\MTProtoTools\MinDatabase;
use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
use danog\MadelineProto\MTProtoTools\UpdatesState;
use danog\MadelineProto\Settings\Database\Memory;
use danog\MadelineProto\Settings\TLSchema;
use danog\MadelineProto\TL\TL;
use danog\MadelineProto\TL\TLCallback;
use Psr\Log\LoggerInterface;
use function Amp\File\getSize;
use function Amp\File\touch as touchAsync;
/**
 * Manages all of the mtproto stuff.
 *
 * @internal
 */
class MTProto extends AsyncConstruct implements TLCallback
{
    use \danog\Serializable;
    use \danog\MadelineProto\MTProtoTools\AuthKeyHandler;
    use \danog\MadelineProto\MTProtoTools\CallHandler;
    use \danog\MadelineProto\MTProtoTools\PeerHandler;
    use \danog\MadelineProto\MTProtoTools\UpdateHandler;
    use \danog\MadelineProto\MTProtoTools\Files;
    use \danog\MadelineProto\SecretChats\AuthKeyHandler;
    use \danog\MadelineProto\SecretChats\MessageHandler;
    use \danog\MadelineProto\SecretChats\ResponseHandler;
    use \danog\MadelineProto\SecretChats\SeqNoHandler;
    use \danog\MadelineProto\TL\Conversion\BotAPI;
    use \danog\MadelineProto\TL\Conversion\BotAPIFiles;
    use \danog\MadelineProto\TL\Conversion\TD;
    use \danog\MadelineProto\VoIP\AuthKeyHandler;
    use \danog\MadelineProto\Wrappers\Ads;
    use \danog\MadelineProto\Wrappers\Button;
    use \danog\MadelineProto\Wrappers\DialogHandler;
    use \danog\MadelineProto\Wrappers\Events;
    use \danog\MadelineProto\Wrappers\Webhook;
    use \danog\MadelineProto\Wrappers\Callback;
    use \danog\MadelineProto\Wrappers\Login;
    use \danog\MadelineProto\Wrappers\Loop;
    use \danog\MadelineProto\Wrappers\Noop;
    use \danog\MadelineProto\Wrappers\Start;
    use \danog\MadelineProto\Wrappers\Templates;
    use \danog\MadelineProto\Wrappers\TOS;
    use DbPropertiesTrait;
    private const RSA_KEYS = ['-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEA6LszBcC1LGzyr992NzE0ieY+BSaOW622Aa9Bd4ZHLl+TuFQ4lo4g
5nKaMBwK/BIb9xUfg0Q29/2mgIR6Zr9krM7HjuIcCzFvDtr+L0GQjae9H0pRB2OO
62cECs5HKhT5DZ98K33vmWiLowc621dQuwKWSQKjWf50XYFw42h21P2KXUGyp2y/
+aEyZ+uVgLLQbRA1dEjSDZ2iGRy12Mk5gpYc397aYp438fsJoHIgJ2lgMv5h7WY9
t6N/byY9Nw9p21Og3AoXSL2q/2IJ1WRUhebgAdGVMlV1fkuOQoEzR7EdpqtQD9Cs
5+bfo3Nhmcyvk5ftB0WkJ9z6bNZ7yxrP8wIDAQAB
-----END RSA PUBLIC KEY-----'];
    private const TEST_RSA_KEYS = ['-----BEGIN RSA PUBLIC KEY-----
MIIBCgKCAQEAyMEdY1aR+sCR3ZSJrtztKTKqigvO/vBfqACJLZtS7QMgCGXJ6XIR
yy7mx66W0/sOFa7/1mAZtEoIokDP3ShoqF4fVNb6XeqgQfaUHd8wJpDWHcR2OFwv
plUUI1PLTktZ9uW2WE23b+ixNwJjJGwBDJPQEQFBE+vfmH0JP503wr5INS1poWg/
j25sIWeYPHYeOrFp/eXaqhISP6G+q2IeTaWTXpwZj4LzXq5YOpk4bYEQ6mvRq7D1
aHWfYmlEGepfaYR8Q0YqvvhYtMte3ITnuSJs171+GDqpdKcSwHnd6FudwGO4pcCO
j4WcDuXc2CTHgH8gFTNhp/Y8/SpDOhvn9QIDAQAB
-----END RSA PUBLIC KEY-----'];
    /**
     * Internal version of MadelineProto.
     *
     * Increased every time the default settings array or something big changes
     *
     * @internal
     *
     * @var int
     */
    const V = 154;
    /**
     * Release version.
     *
     * @var string
     */
    const RELEASE = '7.0';
    /**
     * We're not logged in.
     *
     * @var int
     */
    const NOT_LOGGED_IN = 0;
    /**
     * We're waiting for the login code.
     *
     * @var int
     */
    const WAITING_CODE = 1;
    /**
     * We're waiting for parameters to sign up.
     *
     * @var int
     */
    const WAITING_SIGNUP = -1;
    /**
     * We're waiting for the 2FA password.
     *
     * @var int
     */
    const WAITING_PASSWORD = 2;
    /**
     * We're logged in.
     *
     * @var int
     */
    const LOGGED_IN = 3;
    /**
     * Bad message error codes.
     *
     * @internal
     *
     * @var array
     */
    const BAD_MSG_ERROR_CODES = [16 => 'msg_id too low (most likely, client time is wrong; it would be worthwhile to synchronize it using msg_id notifications and re-send the original message with the correct msg_id or wrap it in a container with a new msg_id if the original message had waited too long on the client to be transmitted)', 17 => 'msg_id too high (similar to the previous case, the client time has to be synchronized, and the message re-sent with the correct msg_id)', 18 => 'incorrect two lower order msg_id bits (the server expects client message msg_id to be divisible by 4)', 19 => 'container msg_id is the same as msg_id of a previously received message (this must never happen)', 20 => 'message too old, and it cannot be verified whether the server has received a message with this msg_id or not', 32 => 'msg_seqno too low (the server has already received a message with a lower msg_id but with either a higher or an equal and odd seqno)', 33 => 'msg_seqno too high (similarly, there is a message with a higher msg_id but with either a lower or an equal and odd seqno)', 34 => 'an even msg_seqno expected (irrelevant message), but odd received', 35 => 'odd msg_seqno expected (relevant message), but even received', 48 => 'incorrect server salt (in this case, the bad_server_salt response is received with the correct salt, and the message is to be re-sent with it)', 64 => 'invalid container'];
    /**
     * Localized message info flags.
     *
     * @internal
     *
     * @var array
     */
    const MSGS_INFO_FLAGS = [1 => 'nothing is known about the message (msg_id too low, the other party may have forgotten it)', 2 => 'message not received (msg_id falls within the range of stored identifiers; however, the other party has certainly not received a message like that)', 3 => 'message not received (msg_id too high; however, the other party has certainly not received it yet)', 4 => 'message received (note that this response is also at the same time a receipt acknowledgment)', 8 => ' and message already acknowledged', 16 => ' and message not requiring acknowledgment', 32 => ' and RPC query contained in message being processed or processing already complete', 64 => ' and content-related response to message already generated', 128 => ' and other party knows for a fact that message is already received'];
    /**
     * Secret chat was not found.
     *
     * @var int
     */
    const SECRET_EMPTY = 0;
    /**
     * Secret chat was requested.
     *
     * @var int
     */
    const SECRET_REQUESTED = 1;
    /**
     * Secret chat was found.
     *
     * @var int
     */
    const SECRET_READY = 2;
    /**
     * @internal
     */
    const GETUPDATES_HANDLER = 'getUpdates';
    /**
     * @internal
     */
    const TD_PARAMS_CONVERSION = ['updateNewMessage' => ['_' => 'updateNewMessage', 'disable_notification' => ['message', 'silent'], 'message' => ['message']], 'message' => ['_' => 'message', 'id' => ['id'], 'sender_user_id' => ['from_id'], 'chat_id' => ['peer_id', 'choose_chat_id_from_botapi'], 'send_state' => ['choose_incoming_or_sent'], 'can_be_edited' => ['choose_can_edit'], 'can_be_deleted' => ['choose_can_delete'], 'is_post' => ['post'], 'date' => ['date'], 'edit_date' => ['edit_date'], 'forward_info' => ['fwd_info', 'choose_forward_info'], 'reply_to_message_id' => ['reply_to_msg_id'], 'ttl' => ['choose_ttl'], 'ttl_expires_in' => ['choose_ttl_expires_in'], 'via_bot_user_id' => ['via_bot_id'], 'views' => ['views'], 'content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']], 'messages.sendMessage' => ['chat_id' => ['peer'], 'reply_to_message_id' => ['reply_to_msg_id'], 'disable_notification' => ['silent'], 'from_background' => ['background'], 'input_message_content' => ['choose_message_content'], 'reply_markup' => ['reply_markup']]];
    /**
     * @internal
     */
    const TD_REVERSE = ['sendMessage' => 'messages.sendMessage'];
    /**
     * @internal
     */
    const TD_IGNORE = ['updateMessageID'];
    /**
     * Whether to generate only peer information.
     */
    const INFO_TYPE_PEER = 0;
    /**
     * Whether to generate only constructor information.
     */
    const INFO_TYPE_CONSTRUCTOR = 1;
    /**
     * Whether to generate only ID information.
     */
    const INFO_TYPE_ID = 2;
    /**
     * Whether to generate all information.
     */
    const INFO_TYPE_ALL = 3;
    /**
     * @internal
     */
    const BOTAPI_PARAMS_CONVERSION = ['disable_web_page_preview' => 'no_webpage', 'disable_notification' => 'silent', 'reply_to_message_id' => 'reply_to_msg_id', 'chat_id' => 'peer', 'text' => 'message'];
    /**
     * @internal
     */
    const DEFAULT_GETUPDATES_PARAMS = ['offset' => 0, 'limit' => null, 'timeout' => 100];
    /**
    * Array of references to all instances of MTProto.
    *
    * This seems like a recipe for memory leaks, but this is actually required to allow saving the session on shutdown.
    When using a network I/O-based database+the EvDriver of AMPHP, calling die(); causes premature garbage collection of the event loop.
    This garbage collection happens always, even if a reference to the event handler is already present elsewhere (probably ev dark magic).
    *
    * Finally, this causes the process to hang on shutdown, since the database driver cannot receive a reply from the server, because the event loop is down.
    *
    * To avoid this, we store each MTProto instance in here (unreferencing on shutdown in unreference()), and call serialize() on all instances before calling die; in Magic.
    *
    * @var self[]
    */
    public static array $references = [];
    /**
     * Instance of wrapper API.
     *
     * @var APIWrapper
     */
    public $wrapper;
    /**
     * PWRTelegram webhook URL.
     *
     * @var boolean|string
     */
    public $hook_url = false;
    /**
     * Settings array.
     *
     * @var Settings
     */
    public $settings;
    /**
     * Config array.
     *
     * @var array
     */
    private $config = ['expires' => -1];
    /**
     * TOS info.
     *
     * @var array
     */
    private $tos = ['expires' => 0, 'accepted' => true];
    /**
     * Whether we're initing authorization.
     *
     * @var boolean
     */
    private $initing_authorization = false;
    /**
     * Authorization info (User).
     *
     * @var array|null
     */
    public $authorization = null;
    /**
     * Whether we're authorized.
     *
     * @var int
     * @psalm-var self::NOT_LOGGED_IN|self::WAITING_*|self::LOGGED_IN
     */
    public $authorized = self::NOT_LOGGED_IN;
    /**
     * Main authorized DC ID.
     *
     * @var integer
     */
    public $authorized_dc = -1;
    /**
     * RSA keys.
     *
     * @var array<RSA>
     */
    private $rsa_keys = [];
    /**
     * RSA keys.
     *
     * @var array<RSA>
     */
    private $test_rsa_keys = [];
    /**
     * CDN RSA keys.
     *
     * @var array
     */
    private $cdn_rsa_keys = [];
    /**
     * Diffie-hellman config.
     *
     * @var array
     */
    private $dh_config = ['version' => 0];
    /**
     * Internal peer database.
     *
     * @var DbArray|Promise[]
     */
    public $chats;
    /**
     * Cache of usernames for chats.
     *
     * @var DbArray|Promise[]
     */
    public $usernames;
    /**
     * Cached parameters for fetching channel participants.
     *
     * @var DbArray|Promise[]
     */
    public $channelParticipants;
    /**
     * When we last stored data in remote peer database (now doesn't exist anymore).
     *
     * @var integer
     */
    public $last_stored = 0;
    /**
     * Temporary array of data to be sent to remote peer database.
     *
     * @var array
     */
    public $qres = [];
    /**
     * Full chat info database.
     *
     * @var DbArray|Promise[]
     */
    public $full_chats;
    /**
     * Sponsored message database.
     *
     * @var DbArray
     */
    public $sponsoredMessages;
    /**
     * Latest chat message ID map for update handling.
     *
     * @var array
     */
    private $msg_ids = [];
    /**
     * Version integer for upgrades.
     *
     * @var integer
     */
    private $v = 0;
    /**
     * Cached getdialogs params.
     *
     * @var array
     */
    private $dialog_params = ['limit' => 0, 'offset_date' => 0, 'offset_id' => 0, 'offset_peer' => ['_' => 'inputPeerEmpty'], 'count' => 0];
    /**
     * Support user ID.
     *
     * @var integer
     */
    private $supportUser = 0;
    /**
     * File reference database.
     *
     * @var \danog\MadelineProto\MTProtoTools\ReferenceDatabase
     */
    public $referenceDatabase;
    /**
     * min database.
     *
     * @var \danog\MadelineProto\MTProtoTools\MinDatabase
     */
    public $minDatabase;
    /**
     * TOS check loop.
     */
    public ?PeriodicLoopInternal $checkTosLoop = null;
    /**
     * Phone config loop.
     */
    public ?PeriodicLoopInternal $phoneConfigLoop = null;
    /**
     * Config loop.
     */
    public ?PeriodicLoopInternal $configLoop = null;
    /**
     * Call checker loop.
     */
    private ?PeriodicLoopInternal $callCheckerLoop = null;
    /**
     * Autoserialization loop.
     */
    private ?PeriodicLoopInternal $serializeLoop = null;
    /**
     * SEQ update loop.
     */
    private ?SeqLoop $seqUpdater = null;
    /**
     * IPC server.
     */
    private ?Server $ipcServer = null;
    /**
     * Feeder loops.
     *
     * @var array<\danog\MadelineProto\Loop\Update\FeedLoop>
     */
    public $feeders = [];
    /**
     * Secret chat feeder loops.
     *
     * @var array<\danog\MadelineProto\Loop\Update\SecretFeedLoop>
     */
    public $secretFeeders = [];
    /**
     * Updater loops.
     *
     * @var array<\danog\MadelineProto\Loop\Update\UpdateLoop>
     */
    public $updaters = [];
    /**
     * DataCenter instance.
     *
     * @var DataCenter
     */
    public $datacenter;
    /**
     * Logger instance.
     *
     * @var Logger
     */
    public $logger;
    /**
     * TL serializer.
     *
     * @var \danog\MadelineProto\TL\TL
     */
    private $TL;
    /**
     * Snitch.
     */
    private Snitch $snitch;
    /**
     * DC list.
     */
    protected array $dcList = ['test' => [
        // Test datacenters
        'ipv4' => [
            // ipv4 addresses
            2 => [
                // The rest will be fetched using help.getConfig
                'ip_address' => '149.154.167.40',
                'port' => 443,
                'media_only' => false,
                'tcpo_only' => false,
            ],
        ],
        'ipv6' => [
            // ipv6 addresses
            2 => [
                // The rest will be fetched using help.getConfig
                'ip_address' => '2001:067c:04e8:f002:0000:0000:0000:000e',
                'port' => 443,
                'media_only' => false,
                'tcpo_only' => false,
            ],
        ],
    ], 'main' => [
        // Main datacenters
        'ipv4' => [
            // ipv4 addresses
            2 => [
                // The rest will be fetched using help.getConfig
                'ip_address' => '149.154.167.51',
                'port' => 443,
                'media_only' => false,
                'tcpo_only' => false,
            ],
        ],
        'ipv6' => [
            // ipv6 addresses
            2 => [
                // The rest will be fetched using help.getConfig
                'ip_address' => '2001:067c:04e8:f002:0000:0000:0000:000a',
                'port' => 443,
                'media_only' => false,
                'tcpo_only' => false,
            ],
        ],
    ]];
    /**
     * Nullcache array for storing main session file to DB.
     *
     * @var DbArray|Promise[]
     */
    public $session;
    /**
     * List of properties stored in database (memory or external).
     * @see DbPropertiesFactory
     * @var array
     */
    protected static array $dbProperties = ['chats' => 'array', 'full_chats' => 'array', 'sponsoredMessages' => 'array', 'channelParticipants' => 'array', 'usernames' => 'array', 'session' => ['type' => 'array', 'config' => ['enableCache' => false]]];
    /**
     * Serialize session, returning object to serialize to db.
     *
     * @return \Generator
     */
    public function serializeSession(object $data) : \Generator
    {
        if (!$this->session || $this->session instanceof MemoryArray) {
            return $data;
        }
        (yield $this->session->set('data', $data));
        return $this->session;
    }
    /**
     * Serialize all instances.
     *
     * CALLED ONLY ON SHUTDOWN.
     *
     * @return void
     */
    public static function serializeAll() : void
    {
        static $done = false;
        if ($done) {
            return;
        }
        $done = true;
        Logger::log('Prompting final serialization (SHUTDOWN)...');
        foreach (self::$references as $instance) {
            Tools::wait($instance->wrapper->serialize());
        }
        Logger::log('Done final serialization (SHUTDOWN)!');
    }
    /**
     * Constructor function.
     *
     * @param (Settings | SettingsEmpty) $settings Settings
     * @param ?APIWrapper $wrapper API wrapper
     *
     * @return void
     */
    public function __magic_construct(SettingsAbstract $settings, ?APIWrapper $wrapper = null)
    {
        if (static::class !== self::class || !$wrapper) {
            return;
        }
        self::$references[\spl_object_hash($this)] = $this;
        $this->wrapper = $wrapper;
        $this->setInitPromise($this->__construct_async($settings));
    }
    /**
     * Async constructor function.
     *
     * @param (Settings | SettingsEmpty) $settings Settings
     *
     * @return \Generator
     */
    public function __construct_async(SettingsAbstract $settings) : \Generator
    {
        // Initialize needed stuffs
        Magic::start();
        // Parse and store settings
        $this->updateSettingsInternal($settings);
        // Actually instantiate needed classes like a boss
        yield from $this->cleanupProperties();
        // Start IPC server
        if (!$this->ipcServer) {
            try {
                $this->ipcServer = new Server($this);
                $this->ipcServer->setSettings($this->settings->getIpc());
                $this->ipcServer->setIpcPath($this->wrapper->session);
            } catch (\Throwable $e) {
                $this->logger->logger("Error while starting IPC server: {$e}", Logger::FATAL_ERROR);
            }
        }
        try {
            $this->ipcServer->start();
        } catch (\Throwable $e) {
            if (Magic::$isIpcWorker) {
                throw $e;
            }
            $this->logger->logger("Error while starting IPC server: {$e}", Logger::FATAL_ERROR);
        }
        // Load rsa keys
        $this->rsa_keys = [];
        foreach (self::RSA_KEYS as $key) {
            $key = (yield from RSA::load($this->TL, $key));
            $this->rsa_keys[$key->fp] = $key;
        }
        $this->test_rsa_keys = [];
        foreach (self::TEST_RSA_KEYS as $key) {
            $key = (yield from RSA::load($this->TL, $key));
            $this->test_rsa_keys[$key->fp] = $key;
        }
        // (re)-initialize TL
        $callbacks = [$this];
        if ($this->settings->getDb()->getEnableFileReferenceDb()) {
            $callbacks[] = $this->referenceDatabase;
        }
        if (!($this->authorization['user']['bot'] ?? false) && $this->settings->getDb()->getEnableMinDb()) {
            $callbacks[] = $this->minDatabase;
        }
        $this->TL->init($this->settings->getSchema(), $callbacks);
        yield from $this->connectToAllDcs();
        $this->startLoops();
        $this->datacenter->curdc = 2;
        if ((!isset($this->authorization['user']['bot']) || !$this->authorization['user']['bot']) && $this->datacenter->getDataCenterConnection($this->datacenter->curdc)->hasTempAuthKey()) {
            try {
                $nearest_dc = (yield from $this->methodCallAsyncRead('help.getNearestDc', []));
                $this->logger->logger(\sprintf(Lang::$current_lang['nearest_dc'], $nearest_dc['country'], $nearest_dc['nearest_dc']), Logger::NOTICE);
                if ($nearest_dc['nearest_dc'] != $nearest_dc['this_dc']) {
                    $this->settings->setDefaultDc($this->datacenter->curdc = (int) $nearest_dc['nearest_dc']);
                }
            } catch (RPCErrorException $e) {
                if ($e->rpc !== 'BOT_METHOD_INVALID') {
                    throw $e;
                }
            }
        }
        yield from $this->getConfig([]);
        $this->startUpdateSystem(true);
        $this->v = self::V;
        $this->settings->applyChanges();
        GarbageCollector::start();
    }
    /**
     * Set API wrapper needed for triggering serialization functions.
     *
     * @internal
     */
    public function setWrapper(APIWrapper $wrapper) : void
    {
        $this->wrapper = $wrapper;
    }
    /**
     * Get API wrapper.
     *
     * @internal
     */
    public function getWrapper() : APIWrapper
    {
        return $this->wrapper;
    }
    /**
     * Sleep function.
     *
     * @return array
     */
    public function __sleep() : array
    {
        $db = $this->settings->getDb();
        if ($db instanceof Memory && $db->getCleanup()) {
            Tools::wait($this->cleanup());
        }
        $res = [
            // Databases
            'chats',
            'full_chats',
            'referenceDatabase',
            'minDatabase',
            'channelParticipants',
            'usernames',
            'sponsoredMessages',
            'tmpDbPrefix',
            // Misc caching
            'dialog_params',
            'last_stored',
            'qres',
            'supportUser',
            'tos',
            // Event handler
            'event_handler',
            'event_handler_instance',
            'loop_callback',
            'updates',
            'updates_key',
            'hook_url',
            // Web login template
            'webTemplate',
            // Settings
            'settings',
            'config',
            'dcList',
            // Authorization keys
            'datacenter',
            // Authorization state
            'authorization',
            'authorized',
            'authorized_dc',
            // Authorization cache
            'rsa_keys',
            'test_rsa_keys',
            'dh_config',
            // Update state
            'got_state',
            'channels_state',
            'msg_ids',
            // Version
            'v',
            // TL
            'TL',
            // Secret chats
            'secret_chats',
            'temp_requested_secret_chats',
            'temp_rekeyed_secret_chats',
            // Report URI
            'reportDest',
            'calls',
            'snitch',
        ];
        if (!$this->updateHandler instanceof Closure) {
            $res[] = 'updateHandler';
        }
        return $res;
    }
    /**
     * Cleanup memory and session file.
     *
     * @return \Generator
     */
    public function cleanup() : \Generator
    {
        $this->referenceDatabase = new ReferenceDatabase($this);
        yield from $this->referenceDatabase->init();
        $callbacks = [$this];
        if ($this->settings->getDb()->getEnableFileReferenceDb()) {
            $callbacks[] = $this->referenceDatabase;
        }
        if ($this->settings->getDb()->getEnableMinDb() && !($this->authorization['user']['bot'] ?? false)) {
            $callbacks[] = $this->minDatabase;
        }
        $this->TL->updateCallbacks($callbacks);
    }
    /**
     *
     */
    private function fillUsernamesCache() : \Generator
    {
        if (!$this->settings->getDb()->getEnableUsernameDb()) {
            (yield $this->usernames->clear());
            return;
        }
        if (!(yield $this->usernames->count())) {
            $this->logger('Filling database cache. This can take few minutes.', Logger::WARNING);
            $iterator = $this->chats->getIterator();
            while ((yield $iterator->advance())) {
                [$id, $chat] = $iterator->getCurrent();
                if (isset($chat['username'])) {
                    $this->usernames[\strtolower($chat['username'])] = $this->getId($chat);
                }
            }
            $this->logger('Cache filled.', Logger::WARNING);
        }
    }
    /**
     * Logger.
     *
     * @param string $param Parameter
     * @param int $level Logging level
     * @param string $file File where the message originated
     *
     * @return void
     */
    public function logger($param, int $level = Logger::NOTICE, string $file = '') : void
    {
        if ($file === null) {
            $file = \basename(\debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0]['file'], '.php');
        }
        isset($this->logger) ? $this->logger->logger($param, $level, $file) : Logger::$default->logger($param, $level, $file);
    }
    /**
     * Get TL namespaces.
     *
     * @return array
     */
    public function getMethodNamespaces() : array
    {
        return $this->TL->getMethodNamespaces();
    }
    /**
     * Get namespaced methods (method => namespace).
     *
     * @return array
     */
    public function getMethodsNamespaced() : array
    {
        return $this->TL->getMethodsNamespaced();
    }
    /**
     * Get TL serializer.
     *
     * @return TL
     */
    public function getTL() : \danog\MadelineProto\TL\TL
    {
        return $this->TL;
    }
    /**
     * Get logger.
     */
    public function getLogger() : Logger
    {
        return $this->logger;
    }
    /**
     * Get PSR logger.
     */
    public function getPsrLogger() : LoggerInterface
    {
        return $this->logger->getPsrLogger();
    }
    /**
     * Get async HTTP client.
     *
     * @return \Amp\Http\Client\HttpClient
     */
    public function getHTTPClient() : HttpClient
    {
        return $this->datacenter->getHTTPClient();
    }
    /**
     * Get async DNS client.
     *
     * @return \Amp\Dns\Resolver
     */
    public function getDNSClient() : Resolver
    {
        return $this->datacenter->getDNSClient();
    }
    /**
     * Get contents of remote file asynchronously.
     *
     * @param string $url URL
     *
     * @return \Generator
     *
     * @psalm-return \Generator<int, Promise<string>, mixed, string>
     */
    public function fileGetContents(string $url) : \Generator
    {
        return $this->datacenter->fileGetContents($url);
    }
    /**
     * Get all datacenter connections.
     *
     * @return array<DataCenterConnection>
     */
    public function getDataCenterConnections() : array
    {
        return $this->datacenter->getDataCenterConnections();
    }
    /**
     * Get main DC ID.
     *
     * @return (int | string)
     */
    public function getDataCenterId()
    {
        return $this->datacenter->curdc;
    }
    /**
     * Prompt serialization of instance.
     *
     * @internal
     *
     * @return void
     */
    public function serialize()
    {
        if ($this->wrapper && $this->inited()) {
            $this->wrapper->serialize();
        }
    }
    /**
     * Start all internal loops.
     *
     * @return void
     */
    private function startLoops()
    {
        if (!$this->callCheckerLoop) {
            $this->callCheckerLoop = new PeriodicLoopInternal($this, [$this, 'checkCalls'], 'call check', 10 * 1000);
        }
        if (!$this->serializeLoop) {
            $this->serializeLoop = new PeriodicLoopInternal($this, [$this, 'serialize'], 'serialize', $this->settings->getSerialization()->getInterval() * 1000);
        }
        if (!$this->phoneConfigLoop) {
            $this->phoneConfigLoop = new PeriodicLoopInternal($this, [$this, 'getPhoneConfig'], 'phone config', 24 * 3600 * 1000);
        }
        if (!$this->checkTosLoop) {
            $this->checkTosLoop = new PeriodicLoopInternal($this, [$this, 'checkTos'], 'TOS', 24 * 3600 * 1000);
        }
        if (!$this->configLoop) {
            $this->configLoop = new PeriodicLoopInternal($this, [$this, 'getConfig'], 'config', 24 * 3600 * 1000);
        }
        if (!$this->ipcServer) {
            try {
                $this->ipcServer = new Server($this);
                $this->ipcServer->setSettings($this->settings->getIpc());
                $this->ipcServer->setIpcPath($this->wrapper->session);
            } catch (\Throwable $e) {
                $this->logger->logger("Error while starting IPC server: {$e}", Logger::FATAL_ERROR);
            }
        }
        $this->callCheckerLoop->start();
        $this->serializeLoop->start();
        $this->phoneConfigLoop->start();
        $this->configLoop->start();
        $this->checkTosLoop->start();
        try {
            $this->ipcServer->start();
        } catch (\Throwable $e) {
            if (Magic::$isIpcWorker) {
                throw $e;
            }
            $this->logger->logger("Error while starting IPC server: {$e}", Logger::FATAL_ERROR);
        }
    }
    /**
     * Stop all internal loops.
     *
     * @return void
     */
    private function stopLoops()
    {
        if ($this->callCheckerLoop) {
            $this->callCheckerLoop->signal(true);
            $this->callCheckerLoop = null;
        }
        if ($this->serializeLoop) {
            $this->serializeLoop->signal(true);
            $this->serializeLoop = null;
        }
        if ($this->phoneConfigLoop) {
            $this->phoneConfigLoop->signal(true);
            $this->phoneConfigLoop = null;
        }
        if ($this->configLoop) {
            $this->configLoop->signal(true);
            $this->configLoop = null;
        }
        if ($this->checkTosLoop) {
            $this->checkTosLoop->signal(true);
            $this->checkTosLoop = null;
        }
        if ($this->ipcServer) {
            $this->ipcServer->signal(null);
            $this->ipcServer = null;
        }
    }
    /**
     * Clean up properties from previous versions of MadelineProto.
     *
     * @internal
     *
     * @return \Generator
     *
     * @psalm-return \Generator<mixed, mixed, mixed, void>
     */
    private function cleanupProperties() : \Generator
    {
        if (!$this->channels_state instanceof CombinedUpdatesState) {
            $this->channels_state = new CombinedUpdatesState($this->channels_state);
        }
        if (isset($this->updates_state)) {
            if (!$this->updates_state instanceof UpdatesState) {
                $this->updates_state = new UpdatesState($this->updates_state);
            }
            $this->channels_state->__construct([UpdateLoop::GENERIC => $this->updates_state]);
            unset($this->updates_state);
        }
        if (!isset($this->datacenter)) {
            $this->datacenter ??= new DataCenter($this, $this->dcList, $this->settings->getConnection());
        }
        if (!isset($this->snitch)) {
            $this->snitch = new Snitch();
        }
        $db = [];
        if (!isset($this->referenceDatabase)) {
            $this->referenceDatabase = new ReferenceDatabase($this);
            $db[] = $this->referenceDatabase->init();
        } else {
            $db[] = $this->referenceDatabase->init();
        }
        if (!isset($this->minDatabase)) {
            $this->minDatabase = new MinDatabase($this);
            $db[] = $this->minDatabase->init();
        } else {
            $db[] = $this->minDatabase->init();
        }
        if (!isset($this->TL)) {
            $this->TL = new TL($this);
            $callbacks = [$this, $this->referenceDatabase];
            if (!($this->authorization['user']['bot'] ?? false)) {
                $callbacks[] = $this->minDatabase;
            }
            $this->TL->init($this->settings->getSchema(), $callbacks);
        }
        $db[] = $this->initDb($this);
        (yield Tools::all($db));
        yield from $this->fillUsernamesCache();
        if (!$this->settings->getDb()->getEnableFullPeerDb()) {
            (yield $this->full_chats->clear());
        }
        if (!$this->settings->getDb()->getEnablePeerInfoDb()) {
            if ((yield $this->chats->isset(0))) {
                return;
            }
            $this->logger("Cleaning up peer database...");
            $k = 0;
            $total = (yield $this->chats->count());
            $iterator = $this->chats->getIterator();
            while ((yield $iterator->advance())) {
                [$key, $value] = $iterator->getCurrent();
                $value = ['_' => $value['_'], 'id' => $value['id'], 'access_hash' => $value['access_hash'] ?? null, 'min' => $value['min'] ?? false];
                $k++;
                if ($k % 500 === 0 || $k === $total) {
                    $this->logger("Cleaning up peer database ({$k}/{$total})...");
                    (yield $this->chats->set($key, $value));
                } else {
                    $this->chats->set($key, $value);
                }
            }
            (yield $this->chats->set(0, []));
            $this->logger("Cleaned up peer database!");
        } elseif ((yield $this->chats->isset(0))) {
            $this->chats->unset(0);
        }
    }
    /**
     * Upgrade MadelineProto instance.
     *
     * @return \Generator
     * @throws Exception
     * @throws RPCErrorException
     * @throws \Throwable
     */
    private function upgradeMadelineProto() : \Generator
    {
        if (!isset($this->snitch)) {
            $this->snitch = new Snitch();
        }
        $this->logger->logger(Lang::$current_lang['serialization_ofd'], Logger::WARNING);
        foreach ($this->datacenter->getDataCenterConnections() as $dc_id => $socket) {
            if ($this->authorized === self::LOGGED_IN && \strpos($dc_id, '_') === false && $socket->hasPermAuthKey() && $socket->hasTempAuthKey()) {
                $socket->bind();
                $socket->authorized(true);
            }
        }
        $this->settings->setSchema(new TLSchema());
        yield from $this->initDb($this);
        if (!isset($this->secret_chats)) {
            $this->secret_chats = [];
        }
        $iterator = $this->full_chats->getIterator();
        while ((yield $iterator->advance())) {
            [$id, $full] = $iterator->getCurrent();
            if (isset($full['full'], $full['last_update'])) {
                (yield $this->full_chats->set($id, ['full' => $full['full'], 'last_update' => $full['last_update']]));
            }
        }
        if (isset($this->channel_participants)) {
            if (\is_array($this->channel_participants)) {
                foreach ($this->channel_participants as $channelId => $filters) {
                    foreach ($filters as $filter => $qs) {
                        foreach ($qs as $q => $offsets) {
                            foreach ($offsets as $offset => $limits) {
                                foreach ($limits as $limit => $data) {
                                    $this->channelParticipants[$this->participantsKey($channelId, $filter, $q, $offset, $limit)] = $data;
                                }
                            }
                        }
                    }
                    unset($this->channel_participants[$channelId]);
                }
            } else {
                self::$dbProperties['channel_participants'] = 'array';
                yield from $this->initDb($this);
                $iterator = $this->channel_participants->getIterator();
                while ((yield $iterator->advance())) {
                    [$channelId, $filters] = $iterator->getCurrent();
                    foreach ($filters as $filter => $qs) {
                        foreach ($qs as $q => $offsets) {
                            foreach ($offsets as $offset => $limits) {
                                foreach ($limits as $limit => $data) {
                                    $this->channelParticipants[$this->participantsKey($channelId, $filter, $q, $offset, $limit)] = $data;
                                }
                            }
                        }
                    }
                    unset($this->channel_participants[$channelId]);
                }
            }
        }
        foreach ($this->secret_chats as $key => &$chat) {
            if (!\is_array($chat)) {
                unset($this->secret_chats[$key]);
                continue;
            }
            if ($chat['layer'] >= 73) {
                $chat['mtproto'] = 2;
            } else {
                $chat['mtproto'] = 1;
            }
        }
        unset($chat);
        $this->resetMTProtoSession(true, true);
        $this->config = ['expires' => -1];
        $this->dh_config = ['version' => 0];
        yield from $this->__construct_async($this->settings);
        foreach ($this->secret_chats as $chat => $data) {
            try {
                if (isset($this->secret_chats[$chat]) && $this->secret_chats[$chat]['InputEncryptedChat'] !== null) {
                    yield from $this->notifyLayer($chat);
                }
            } catch (\danog\MadelineProto\RPCErrorException $e) {
            }
        }
    }
    /**
     * Post-deserialization initialization function.
     *
     * @param (Settings | SettingsEmpty) $settings New settings
     * @param APIWrapper $wrapper API wrapper
     *
     * @internal
     *
     * @return \Generator
     */
    public function wakeup(SettingsAbstract $settings, APIWrapper $wrapper) : \Generator
    {
        // Set reference to itself
        self::$references[\spl_object_hash($this)] = $this;
        // Set API wrapper
        $this->wrapper = $wrapper;
        // BC stuff
        if ($this->authorized === true) {
            $this->authorized = self::LOGGED_IN;
        }
        if (!isset($this->snitch)) {
            $this->snitch = new Snitch();
        }
        // Convert old array settings to new settings object
        if (\is_array($this->settings)) {
            if (($this->settings['updates']['callback'] ?? '') === 'getUpdatesUpdateHandler') {
                /** @psalm-suppress InvalidPropertyAssignmentValue */
                $this->settings['updates']['callback'] = [$this, 'getUpdatesUpdateHandler'];
            }
            if (\is_callable($this->settings['updates']['callback'] ?? null)) {
                $this->updateHandler = $this->settings['updates']['callback'];
            }
            /** @psalm-suppress InvalidArrayOffset */
            $this->dcList = $this->settings['connection'] ?? $this->dcList;
        }
        $this->settings = Settings::parseFromLegacy($this->settings);
        // Clean up phone call array
        foreach ($this->calls as $id => $controller) {
            if (!\is_object($controller)) {
                unset($this->calls[$id]);
            } elseif ($controller->getCallState() === VoIP::CALL_STATE_ENDED) {
                $controller->setMadeline($this);
                $controller->discard();
            } else {
                $controller->setMadeline($this);
            }
        }
        $this->forceInit(false);
        $this->setInitPromise($this->wakeupAsync($settings));
        return $this->initAsynchronously();
    }
    /**
     * Async wakeup function.
     *
     * @param (Settings | SettingsEmpty) $settings New settings
     *
     * @return \Generator
     */
    private function wakeupAsync(SettingsAbstract $settings) : \Generator
    {
        // Setup one-time stuffs
        Magic::start();
        $this->settings->getConnection()->init();
        // Setup logger
        $this->setupLogger();
        // Setup language
        Lang::$current_lang =& Lang::$lang['en'];
        if (Lang::$lang[$this->settings->getAppInfo()->getLangCode()] ?? false) {
            Lang::$current_lang =& Lang::$lang[$this->settings->getAppInfo()->getLangCode()];
        }
        // Reset MTProto session (not related to user session)
        $this->resetMTProtoSession();
        // Update settings from constructor
        $this->updateSettingsInternal($settings);
        // Session update process for BC
        $forceDialogs = false;
        if (!isset($this->v) || $this->v !== self::V || $this->settings->getSchema()->needsUpgrade()) {
            yield from $this->upgradeMadelineProto();
            $forceDialogs = true;
        }
        // Cleanup old properties, init new stuffs
        yield from $this->cleanupProperties();
        // Update TL callbacks
        $callbacks = [$this];
        if ($this->settings->getDb()->getEnableFileReferenceDb()) {
            $callbacks[] = $this->referenceDatabase;
        }
        if ($this->settings->getDb()->getEnableMinDb() && !($this->authorization['user']['bot'] ?? false)) {
            $callbacks[] = $this->minDatabase;
        }
        // Connect to all DCs, start internal loops
        yield from $this->connectToAllDcs();
        if (yield from $this->fullGetSelf()) {
            $this->authorized = self::LOGGED_IN;
            $this->setupLogger();
            $this->startLoops();
            yield from $this->getCdnConfig($this->datacenter->curdc);
            yield from $this->initAuthorization();
        } else {
            $this->startLoops();
        }
        // onStart event handler
        if ($this->event_handler && \class_exists($this->event_handler) && \is_subclass_of($this->event_handler, EventHandler::class)) {
            yield from $this->setEventHandler($this->event_handler);
        } else {
            if ($this->updateHandler === [$this, 'eventUpdateHandler']) {
                $this->setNoop();
            }
            $this->event_handler = null;
            $this->event_handler_instance = null;
        }
        $this->startUpdateSystem(true);
        if ($this->authorized === self::LOGGED_IN && !$this->authorization['user']['bot'] && $this->settings->getPeer()->getCacheAllPeersOnStartup()) {
            yield from $this->getDialogs($forceDialogs);
        }
        if ($this->authorized === self::LOGGED_IN) {
            $this->logger->logger(Lang::$current_lang['getupdates_deserialization'], Logger::NOTICE);
            (yield $this->updaters[UpdateLoop::GENERIC]->resume());
        }
        $this->updaters[UpdateLoop::GENERIC]->start();
        GarbageCollector::start();
    }
    /**
     * Unreference instance, allowing destruction.
     *
     * @internal
     *
     * @return void
     */
    public function unreference() : void
    {
        if (!isset($this->logger)) {
            $this->logger = new Logger(new \danog\MadelineProto\Settings\Logger());
        }
        $this->logger->logger("Will unreference instance");
        if (isset(self::$references[\spl_object_hash($this)])) {
            unset(self::$references[\spl_object_hash($this)]);
        }
        $this->stopLoops();
        if (isset($this->seqUpdater)) {
            $this->seqUpdater->signal(true);
        }
        if (isset($this->channels_state)) {
            $channelIds = [];
            foreach ($this->channels_state->get() as $state) {
                $channelIds[] = $state->getChannel();
            }
            \sort($channelIds);
            foreach ($channelIds as $channelId) {
                if (isset($this->feeders[$channelId])) {
                    $this->feeders[$channelId]->signal(true);
                }
                if (isset($this->updaters[$channelId])) {
                    $this->updaters[$channelId]->signal(true);
                }
            }
        }
        if (isset($this->datacenter)) {
            foreach ($this->datacenter->getDataCenterConnections() as $datacenter) {
                $datacenter->setExtra($this);
                $datacenter->disconnect();
            }
        }
        $this->logger->logger("Unreferenced instance");
    }
    /**
     * Destructor.
     */
    public function __destruct()
    {
        $this->logger('Shutting down MadelineProto (MTProto)');
        $this->unreference();
        $this->logger("Successfully destroyed MadelineProto");
    }
    /**
     * Restart IPC server instance.
     *
     * @internal
     */
    public function restartIpcServer() : Promise
    {
        return new Success();
        // Can only be called from client
    }
    /**
     * Whether we're an IPC client instance.
     *
     * @return boolean
     */
    public function isIpc() : bool
    {
        return false;
    }
    /**
     * Whether we're an IPC server process (as opposed to an event handler).
     *
     * @return boolean
     */
    public function isIpcWorker() : bool
    {
        return Magic::$isIpcWorker;
    }
    /**
     * Parse, update and store settings.
     *
     * @param SettingsAbstract $settings Settings
     *
     * @return \Generator
     */
    public function updateSettings(SettingsAbstract $settings) : \Generator
    {
        $this->updateSettingsInternal($settings);
        if ($this->settings->getDb()->hasChanged()) {
            yield from $this->initDb($this);
            $this->settings->getDb()->applyChanges();
        }
        if ($this->settings->getIpc()->hasChanged()) {
            $this->ipcServer->setSettings($this->settings->getIpc()->applyChanges());
        }
        if ($this->settings->getSerialization()->hasChanged()) {
            $this->serializeLoop->signal(true);
            $this->serializeLoop = new PeriodicLoopInternal($this, [$this, 'serialize'], 'serialize', $this->settings->getSerialization()->applyChanges()->getInterval() * 1000);
        }
        if ($this->settings->getAuth()->hasChanged() || $this->settings->getConnection()->hasChanged() || $this->settings->getSchema()->hasChanged() || $this->settings->getSchema()->needsUpgrade()) {
            yield from $this->__construct_async($this->settings);
        }
    }
    /**
     * Parse, update and store settings.
     *
     * @param SettingsAbstract $settings Settings
     *
     * @return void
     */
    private function updateSettingsInternal(SettingsAbstract $settings) : void
    {
        if ($settings instanceof SettingsEmpty) {
            if (!isset($this->settings)) {
                $this->settings = new Settings();
            } else {
                return;
            }
        } else {
            if (!isset($this->settings)) {
                if ($settings instanceof Settings) {
                    $this->settings = $settings;
                } else {
                    $this->settings = new Settings();
                    $this->settings->merge($settings);
                }
            } else {
                $this->settings->merge($settings);
            }
        }
        if (!$this->settings->getAppInfo()->hasApiInfo()) {
            throw new \danog\MadelineProto\Exception(Lang::$current_lang['api_not_set'], 0, null, 'MadelineProto', 1);
        }
        // Setup logger
        if ($this->settings->getLogger()->hasChanged() || !$this->logger) {
            $this->setupLogger();
        }
    }
    /**
     * Return current settings.
     *
     * @return Settings
     */
    public function getSettings() : Settings
    {
        return $this->settings;
    }
    /**
     * Setup logger.
     *
     * @return void
     */
    public function setupLogger() : void
    {
        $this->logger = new Logger($this->settings->getLogger(), $this->authorization['user']['username'] ?? $this->authorization['user']['id'] ?? '');
    }
    /**
     * Reset all MTProto sessions.
     *
     * @param boolean $de Whether to reset the session ID
     * @param boolean $auth_key Whether to reset the auth key
     *
     * @internal
     *
     * @return void
     */
    public function resetMTProtoSession(bool $de = true, bool $auth_key = false) : void
    {
        if (!\is_object($this->datacenter)) {
            throw new Exception(Lang::$current_lang['session_corrupted']);
        }
        foreach ($this->datacenter->getDataCenterConnections() as $id => $socket) {
            if ($de) {
                $socket->resetSession();
            }
            if ($auth_key) {
                $socket->setAuthKey(null);
            }
        }
    }
    /**
     * Check if connected to datacenter using HTTP.
     *
     * @param string $datacenter DC ID
     *
     * @internal
     *
     * @return boolean
     */
    public function isHttp(string $datacenter) : bool
    {
        return $this->datacenter->isHttp($datacenter);
    }
    /**
     * Checks whether all datacenters are authorized.
     *
     * @return boolean
     */
    public function hasAllAuth() : bool
    {
        if ($this->isInitingAuthorization()) {
            return false;
        }
        foreach ($this->datacenter->getDataCenterConnections() as $dc) {
            if ((!$dc->isAuthorized() || !$dc->hasTempAuthKey()) && !$dc->isCDN()) {
                return false;
            }
        }
        return true;
    }
    /**
     * Whether we're initing authorization.
     *
     * @internal
     *
     * @return boolean
     */
    public function isInitingAuthorization()
    {
        return $this->initing_authorization;
    }
    /**
     * Connects to all datacenters and if necessary creates authorization keys, binds them and writes client info.
     *
     * @param boolean $reconnectAll Whether to reconnect to all DCs
     *
     * @return \Generator
     */
    public function connectToAllDcs(bool $reconnectAll = true) : \Generator
    {
        $this->channels_state->get(FeedLoop::GENERIC);
        foreach ($this->channels_state->get() as $state) {
            $channelId = $state->getChannel();
            if (!isset($this->feeders[$channelId])) {
                $this->feeders[$channelId] = new FeedLoop($this, $channelId);
            }
            if (!isset($this->updaters[$channelId])) {
                $this->updaters[$channelId] = new UpdateLoop($this, $channelId);
            }
        }
        if (!isset($this->seqUpdater)) {
            $this->seqUpdater = new SeqLoop($this);
        }
        $this->datacenter->__construct($this, $this->dcList, $this->settings->getConnection(), $reconnectAll);
        $dcs = [];
        foreach ($this->datacenter->getDcs() as $new_dc) {
            $dcs[] = $this->datacenter->dcConnect($new_dc);
        }
        (yield \danog\MadelineProto\Tools::all($dcs));
        yield from $this->initAuthorization();
        yield from $this->parseConfig();
        $dcs = [];
        foreach ($this->datacenter->getDcs(false) as $new_dc) {
            $dcs[] = $this->datacenter->dcConnect($new_dc);
        }
        (yield \danog\MadelineProto\Tools::all($dcs));
        yield from $this->initAuthorization();
        yield from $this->parseConfig();
        yield from $this->getPhoneConfig();
    }
    /**
     * Clean up MadelineProto session after logout.
     *
     * @internal
     *
     * @return \Generator<void>
     */
    public function resetSession() : \Generator
    {
        if (isset($this->seqUpdater)) {
            $this->seqUpdater->signal(true);
            unset($this->seqUpdater);
        }
        $channelIds = [];
        foreach ($this->channels_state->get() as $state) {
            $channelIds[] = $state->getChannel();
        }
        \sort($channelIds);
        foreach ($channelIds as $channelId) {
            if (isset($this->feeders[$channelId])) {
                $this->feeders[$channelId]->signal(true);
                unset($this->feeders[$channelId]);
            }
            if (isset($this->updaters[$channelId])) {
                $this->updaters[$channelId]->signal(true);
                unset($this->updaters[$channelId]);
            }
        }
        foreach ($this->datacenter->getDataCenterConnections() as $socket) {
            $socket->authorized(false);
        }
        $this->channels_state = new CombinedUpdatesState();
        $this->got_state = false;
        $this->msg_ids = [];
        $this->authorized = self::NOT_LOGGED_IN;
        $this->authorized_dc = -1;
        $this->authorization = null;
        $this->updates = [];
        $this->secret_chats = [];
        yield from $this->initDb($this, true);
        $this->tos = ['expires' => 0, 'accepted' => true];
        $this->dialog_params = ['_' => 'MadelineProto.dialogParams', 'limit' => 0, 'offset_date' => 0, 'offset_id' => 0, 'offset_peer' => ['_' => 'inputPeerEmpty'], 'count' => 0];
        $this->referenceDatabase = new ReferenceDatabase($this);
        yield from $this->referenceDatabase->init();
        $this->minDatabase = new MinDatabase($this);
        yield from $this->minDatabase->init();
    }
    /**
     * Reset the update state and fetch all updates from the beginning.
     *
     * @return void
     */
    public function resetUpdateState() : void
    {
        if (isset($this->seqUpdater)) {
            $this->seqUpdater->signal(true);
        }
        $channelIds = [];
        $newStates = [];
        foreach ($this->channels_state->get() as $state) {
            $channelIds[] = $state->getChannel();
            $channelId = $state->getChannel();
            $pts = $state->pts();
            $pts = $channelId ? \max(1, $pts - 1000000) : ($pts > 4000000 ? $pts - 1000000 : \max(1, $pts - 1000000));
            $newStates[$channelId] = new UpdatesState(['pts' => $pts], $channelId);
        }
        \sort($channelIds);
        foreach ($channelIds as $channelId) {
            if (isset($this->feeders[$channelId])) {
                $this->feeders[$channelId]->signal(true);
            }
            if (isset($this->updaters[$channelId])) {
                $this->updaters[$channelId]->signal(true);
            }
        }
        $this->channels_state->__construct($newStates);
        $this->startUpdateSystem();
    }
    /**
     * Start the update system.
     *
     * @param boolean $anyway Force start update system?
     *
     * @internal
     *
     * @return void
     */
    public function startUpdateSystem($anyway = false) : void
    {
        if (!$this->inited() && !$anyway) {
            $this->logger("Not starting update system");
            return;
        }
        $this->logger("Starting update system");
        foreach ($this->secret_chats as $id => $chat) {
            if (!isset($this->secretFeeders[$id])) {
                $this->secretFeeders[$id] = new SecretFeedLoop($this, $id);
            }
            if ($this->secretFeeders[$id]->start() && isset($this->secretFeeders[$id])) {
                $this->secretFeeders[$id]->resume();
            }
        }
        if (!isset($this->seqUpdater)) {
            $this->seqUpdater = new SeqLoop($this);
        }
        $this->channels_state->get(FeedLoop::GENERIC);
        $channelIds = [];
        foreach ($this->channels_state->get() as $state) {
            $channelIds[] = $state->getChannel();
        }
        \sort($channelIds);
        foreach ($channelIds as $channelId) {
            if (!isset($this->feeders[$channelId])) {
                $this->feeders[$channelId] = new FeedLoop($this, $channelId);
            }
            if (!isset($this->updaters[$channelId])) {
                $this->updaters[$channelId] = new UpdateLoop($this, $channelId);
            }
            if ($this->feeders[$channelId]->start() && isset($this->feeders[$channelId])) {
                $this->feeders[$channelId]->resume();
            }
            if ($this->updaters[$channelId]->start() && isset($this->updaters[$channelId])) {
                $this->updaters[$channelId]->resume();
            }
        }
        $this->flushAll();
        if ($this->seqUpdater->start()) {
            $this->seqUpdater->resume();
        }
    }
    /**
     * Flush all datacenter connections.
     *
     * @return void
     */
    private function flushAll() : void
    {
        foreach ($this->datacenter->getDataCenterConnections() as $datacenter) {
            $datacenter->flush();
        }
    }
    /**
     * Store shared phone config.
     *
     * @param mixed $watcherId Watcher ID
     *
     * @internal
     *
     * @return \Generator<void>
     */
    public function getPhoneConfig($watcherId = null) : \Generator
    {
        if ($this->authorized === self::LOGGED_IN && \class_exists(VoIPServerConfigInternal::class) && !$this->authorization['user']['bot'] && $this->datacenter->getDataCenterConnection($this->settings->getDefaultDc())->hasTempAuthKey()) {
            $this->logger->logger('Fetching phone config...');
            VoIPServerConfig::updateDefault(yield from $this->methodCallAsyncRead('phone.getCallConfig', [], $this->settings->getDefaultDcParams()));
        }
    }
    /**
     * Store RSA keys for CDN datacenters.
     *
     * @param string $datacenter DC ID
     *
     * @return \Generator
     */
    public function getCdnConfig(string $datacenter) : \Generator
    {
        try {
            foreach ((yield from $this->methodCallAsyncRead('help.getCdnConfig', [], ['datacenter' => $datacenter]))['public_keys'] as $curkey) {
                $curkey = (yield from RSA::load($this->TL, $curkey['public_key']));
                $this->cdn_rsa_keys[$curkey->fp] = $curkey;
            }
        } catch (\danog\MadelineProto\TL\Exception $e) {
            $this->logger->logger($e->getMessage(), \danog\MadelineProto\Logger::FATAL_ERROR);
        }
    }
    /**
     * Get cached server-side config.
     *
     * @return array
     */
    public function getCachedConfig() : array
    {
        return $this->config;
    }
    /**
     * Get cached (or eventually re-fetch) server-side config.
     *
     * @param array $config Current config
     * @param array $options Options for method call
     *
     * @return \Generator
     */
    public function getConfig(array $config = [], array $options = []) : \Generator
    {
        if ($this->config['expires'] > \time()) {
            return $this->config;
        }
        $this->config = empty($config) ? yield from $this->methodCallAsyncRead('help.getConfig', $config, $options ?: $this->settings->getDefaultDcParams()) : $config;
        yield from $this->parseConfig();
        $this->logger->logger(Lang::$current_lang['config_updated'], Logger::NOTICE);
        $this->logger->logger($this->config, Logger::NOTICE);
        return $this->config;
    }
    /**
     * Parse cached config.
     *
     * @return \Generator
     */
    private function parseConfig() : \Generator
    {
        if (isset($this->config['dc_options'])) {
            $options = $this->config['dc_options'];
            unset($this->config['dc_options']);
            yield from $this->parseDcOptions($options);
        }
    }
    /**
     * Parse DC options from config.
     *
     * @param array $dc_options DC options
     *
     * @return \Generator
     */
    private function parseDcOptions(array $dc_options) : \Generator
    {
        $previous = $this->dcList;
        foreach ($dc_options as $dc) {
            $test = $this->config['test_mode'] ? 'test' : 'main';
            $id = $dc['id'];
            if (isset($dc['static'])) {
                //$id .= $dc['static'] ? '_static' : '';
            }
            if (isset($dc['cdn'])) {
                $id .= $dc['cdn'] ? '_cdn' : '';
            }
            $id .= $dc['media_only'] ? '_media' : '';
            $ipv6 = $dc['ipv6'] ? 'ipv6' : 'ipv4';
            if (\is_numeric($id)) {
                $id = (int) $id;
            }
            unset($dc['cdn'], $dc['media_only'], $dc['id'], $dc['ipv6']);
            $this->dcList[$test][$ipv6][$id] = $dc;
        }
        $curdc = $this->datacenter->curdc;
        if ($previous !== $this->dcList && (!$this->datacenter->has($curdc) || $this->datacenter->getDataCenterConnection($curdc)->byIPAddress())) {
            $this->logger->logger('Got new DC options, reconnecting');
            yield from $this->connectToAllDcs(false);
        }
        $this->datacenter->curdc = $curdc;
    }
    /**
     * Get info about the logged-in user, cached.
     *
     * @return (array | bool)
     */
    public function getSelf()
    {
        return $this->authorization['user'] ?? false;
    }
    /**
     * Get info about the logged-in user, not cached.
     *
     * @return \Generator<(array | bool)>
     */
    public function fullGetSelf() : \Generator
    {
        try {
            $this->authorization = ['user' => (yield from $this->methodCallAsyncRead('users.getUsers', ['id' => [['_' => 'inputUserSelf']]]))[0]];
        } catch (RPCErrorException $e) {
            $this->logger->logger($e->getMessage());
            return false;
        }
        return $this->authorization['user'];
    }
    /**
     * Get authorization info.
     *
     * @return int
     */
    public function getAuthorization() : int
    {
        return $this->authorized;
    }
    /**
     * Get current password hint.
     *
     * @return string
     */
    public function getHint() : string
    {
        if ($this->authorized !== self::WAITING_PASSWORD) {
            throw new Exception("Not waiting for the password!");
        }
        return $this->authorization['hint'];
    }
    /**
     * IDs of peers where to report errors.
     *
     * @var int[]
     */
    private $reportDest = [];
    /**
     * Check if has report peers.
     *
     * @return boolean
     */
    public function hasReportPeers() : bool
    {
        return (bool) $this->reportDest;
    }
    /**
     * Get a message to show to the user when starting the bot.
     *
     * @param string $message
     */
    public function getWebMessage(string $message) : string
    {
        Logger::log($message);
        $warning = '';
        if (!$this->hasReportPeers() && $this->hasEventHandler()) {
            Logger::log("!!! Warning: no report peers are set, please add the following method to your event handler !!!", Logger::FATAL_ERROR);
            Logger::log("!!! public function getReportPeers() { return '@yourtelegramusername'; } !!!", Logger::FATAL_ERROR);
            $warning .= "<h2 style='color:red;'>Warning: no report peers are set, please add the following method to your event handler:</h2>";
            $warning .= "<code>public function getReportPeers() { return '@yourtelegramusername'; }</code>";
        }
        if (!Magic::$hasOpenssl) {
            $warning .= "<h2 style='color:red;'>Warning: the openssl extension is not installed, please install it to speed up MadelineProto</h2>";
        }
        return "<html><body><h1>{$message}</h1>{$warning}</body></html>";
    }
    /**
     * Set peer(s) where to send errors occurred in the event loop.
     *
     * @param (int | string) $userOrId Username(s) or peer ID(s)
     *
     * @return \Generator
     */
    public function setReportPeers($userOrId) : \Generator
    {
        if (!(\is_array($userOrId) && !isset($userOrId['_']) && !isset($userOrId['id']))) {
            $userOrId = [$userOrId];
        }
        foreach ($userOrId as $k => &$peer) {
            try {
                $peer = (yield from $this->getInfo($peer))['bot_api_id'];
                if ($peer === 101374607) {
                    unset($userOrId[$k]);
                }
            } catch (\Throwable $e) {
                unset($userOrId[$k]);
                $this->logger("Could not obtain info about report peer {$peer}: {$e}", Logger::FATAL_ERROR);
            }
        }
        /** @var int[] $userOrId */
        $this->reportDest = $userOrId;
    }
    /**
     * Report an error to the previously set peer.
     *
     * @param string $message Error to report
     * @param string $parseMode Parse mode
     *
     * @return \Generator
     */
    public function report(string $message, string $parseMode = '') : \Generator
    {
        if (!$this->reportDest) {
            return;
        }
        $file = null;
        if ($this->settings->getLogger()->getType() === Logger::FILE_LOGGER && ($path = $this->settings->getLogger()->getExtra())) {
            (yield touchAsync($path));
            if (!(yield getSize($path))) {
                $message = "!!! WARNING !!!\nThe logfile is empty, please DO NOT delete the logfile to avoid errors in MadelineProto!\n\n{$message}";
            } else {
                $file = (yield from $this->methodCallAsyncRead('messages.uploadMedia', ['peer' => $this->reportDest[0], 'media' => ['_' => 'inputMediaUploadedDocument', 'file' => $path, 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'MadelineProto.log']]]]));
            }
        }
        $sent = true;
        foreach ($this->reportDest as $id) {
            try {
                yield from $this->methodCallAsyncRead('messages.sendMessage', ['peer' => $id, 'message' => $message, 'parse_mode' => $parseMode]);
                if ($file) {
                    yield from $this->methodCallAsyncRead('messages.sendMedia', ['peer' => $id, 'media' => $file]);
                }
                $sent &= true;
            } catch (\Throwable $e) {
                $sent &= false;
                $this->logger("While reporting to {$id}: {$e}", Logger::FATAL_ERROR);
            }
        }
        if ($sent && $file) {
            \ftruncate($this->logger->stdout->getResource(), 0);
            $this->logger->logger("Reported!");
        }
    }
    /**
     * Get full list of MTProto and API methods.
     *
     * @return array
     */
    public function getAllMethods() : array
    {
        $methods = [];
        foreach ($this->getTL()->getMethods()->by_id as $method) {
            $methods[] = $method['method'];
        }
        return \array_merge($methods, \get_class_methods(InternalDoc::class));
    }
    /**
     * Called right before serialization of method starts.
     *
     * Pass the method name
     *
     * @return array
     */
    public function getMethodCallbacks() : array
    {
        return [];
    }
    /**
     * Called right before serialization of method starts.
     *
     * Pass the method name
     *
     * @return array
     */
    public function getMethodBeforeCallbacks() : array
    {
        return [];
    }
    /**
     * Called right after deserialization of object, passing the final object.
     *
     * @return array
     */
    public function getConstructorCallbacks() : array
    {
        return \array_merge(\array_fill_keys(['chat', 'chatEmpty', 'chatForbidden', 'channel', 'channelEmpty', 'channelForbidden'], [[$this, 'addChat']]), \array_fill_keys(['user', 'userEmpty'], [[$this, 'addUser']]), ['help.support' => [[$this, 'addSupport']]]);
    }
    /**
     * Called right before deserialization of object.
     *
     * Pass only the constructor name
     *
     * @return array
     */
    public function getConstructorBeforeCallbacks() : array
    {
        return [];
    }
    /**
     * Called right before serialization of constructor.
     *
     * Passed the object, will return a modified version.
     *
     * @return array
     */
    public function getConstructorSerializeCallbacks() : array
    {
        return [];
    }
    /**
    * Called if objects of the specified type cannot be serialized.
    *
    * Passed the unserializable object,
    will try to convert it to an object of the proper type.
    *
    * @return array
    */
    public function getTypeMismatchCallbacks() : array
    {
        return \array_merge(\array_fill_keys(['InputPeer'], [$this, 'getInputPeer']), \array_fill_keys(['InputUser', 'InputChannel'], [$this, 'getInputConstructor']), \array_fill_keys(['User', 'Chat', 'Peer', 'InputDialogPeer', 'InputNotifyPeer'], [$this, 'getInfo']), \array_fill_keys(['InputMedia', 'InputDocument', 'InputPhoto'], [$this, 'getFileInfo']), \array_fill_keys(['InputFileLocation'], [$this, 'getDownloadInfo']));
    }
    /**
     * Get debug information for var_dump.
     *
     * @return array
     */
    public function __debugInfo() : array
    {
        $vars = \get_object_vars($this);
        unset($vars['full_chats'], $vars['chats'], $vars['referenceDatabase'], $vars['minDatabase'], $vars['TL']);
        return $vars;
    }
}<?php

/**
 * Proxying AMPHP connector.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace danog\MadelineProto;

use Amp\CancellationToken;
use Amp\MultiReasonException;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Socket\ConnectContext;
use Amp\Socket\Connector;
class ContextConnector implements Connector
{
    private $dataCenter;
    private $logger;
    private $fromDns = false;
    /**
     *
     */
    public function __construct(DataCenter $dataCenter, bool $fromDns = false)
    {
        $this->dataCenter = $dataCenter;
        $this->fromDns = $fromDns;
        $this->logger = $dataCenter->getAPI()->getLogger();
    }
    /**
     *
     */
    public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null) : Promise
    {
        return Tools::call((function () use($uri, $context, $token) : \Generator {
            $ctx = $context ?? new ConnectContext();
            $token = $token ?? new NullCancellationToken();
            $ctxs = $this->dataCenter->generateContexts(0, $uri, $ctx);
            if (empty($ctxs)) {
                throw new Exception("No contexts for raw connection to URI {$uri}");
            }
            foreach ($ctxs as $ctx) {
                /* @var $ctx \danog\MadelineProto\Stream\ConnectionContext */
                try {
                    $ctx->setIsDns($this->fromDns);
                    $ctx->setCancellationToken($token);
                    $result = (yield from $ctx->getStream());
                    $this->logger->logger('OK!', \danog\MadelineProto\Logger::WARNING);
                    return $result->getSocket();
                } catch (\Throwable $e) {
                    if (\defined('MADELINEPROTO_TEST') && \constant("MADELINEPROTO_TEST") === 'pony') {
                        throw $e;
                    }
                    $this->logger->logger('Connection failed: ' . $e, \danog\MadelineProto\Logger::ERROR);
                    if ($e instanceof MultiReasonException) {
                        foreach ($e->getReasons() as $reason) {
                            $this->logger->logger('Multireason: ' . $reason, \danog\MadelineProto\Logger::ERROR);
                        }
                    }
                }
            }
            throw new \danog\MadelineProto\Exception("Could not connect to URI {$uri}");
        })());
    }
}<?php

// Polyfill for some PHP 5 functions
/**
 *
 */
function callMe($allable, ...$args)
{
    return $allable(...$args);
}
/**
 *
 */
function returnMe($res)
{
    return $res;
}
/**
 *
 */
function __coalesce($ifNotNull, $then)
{
    return $ifNotNull ?: $then;
}
/**
 *
 */
function __destructure($list, $value) : array
{
    $res = [];
    foreach ($list as $key) {
        if (\is_string($key)) {
            $res[] = $value[$key];
        } else {
            $res = \array_merge($res, __destructure($key, $value[$key]));
        }
    }
    return $res;
}
$ampFilePolyfill = 'namespace Amp\\File {';
foreach (['open' => 'openFile', 'stat' => 'getStatus', 'lstat' => 'getLinkStatus', 'size' => 'getSize', 'isdir' => 'isDirectory', 'mtime' => 'getModificationTime', 'atime' => 'getAccessTime', 'ctime' => 'getCreationTime', 'symlink' => 'createSymlink', 'link' => 'createHardlink', 'readlink' => 'resolveSymlink', 'rename' => 'move', 'unlink' => 'deleteFile', 'rmdir' => 'deleteDirectory', 'scandir' => 'listFiles', 'chmod' => 'changePermissions', 'chown' => 'changeOwner', 'get' => 'read', 'put' => 'write', 'mkdir' => 'createDirectory'] as $old => $new) {
    $ampFilePolyfill .= "function {$old}(...\$args) { return {$new}(...\$args); }";
}
$ampFilePolyfill .= "}";
eval($ampFilePolyfill);
unset($ampFilePolyfill);<?php

/**
 * BigInteger placeholder for deserialization.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
namespace phpseclib\Math;

if (PHP_MAJOR_VERSION < 7 && !(\class_exists(\Phar::class) && \Phar::running() || \defined('TESTING_VERSIONS'))) {
    throw new \Exception('MadelineProto requires php 7 to run natively, use phar.madelineproto.xyz to run on PHP 5.6');
}
if (\defined('HHVM_VERSION')) {
    $engines = [['PHP64', ['OpenSSL']], ['BCMath', ['OpenSSL']], ['PHP32', ['OpenSSL']]];
    foreach ($engines as $engine) {
        try {
            \phpseclib3\Math\BigInteger::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []);
            break;
        } catch (\Exception $e) {
        }
    }
}
class BigIntegor
{
}
namespace tgseclib\Math;

use phpseclib3\Math\BigInteger as MathBigInteger;
use Serializable;
class BigInteger implements Serializable
{
    /**
     *
     */
    public MathBigInteger $real;
    /**
     *
     */
    public function serialize()
    {
        //throw new \Exception("Can't serialize legacy class!");
    }
    /**
     *
     */
    public function unserialize($data)
    {
        $r = \unserialize($data);
        $this->real = new MathBigInteger($r['hex'], -16);
        if (isset($r['precision'])) {
            // recalculate $this->bitmask
            $this->real->setPrecision($r['precision']);
        }
    }
    /**
     *
     */
    public function __serialize() : array
    {
        //throw new \Exception("Can't serialize legacy class!");
    }
    /**
     *
     */
    public function __unserialize(array $data) : void
    {
    }
}<?php

/**
 * Yield return value PHP5 polyfill.
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
class YieldReturnValue
{
    private $value;
    /**
     *
     */
    public function __construct($value)
    {
        $this->value = $value;
    }
    /**
     *
     */
    public function getReturn()
    {
        return $this->value;
    }
}<?php

use danog\MadelineProto\API;
use danog\MadelineProto\Settings;
/*
    * load MadelineProto in Your Project
*/
if (\file_exists('vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    include 'madeline.php';
}
/*
    * create default redis object
*/
$database = new \danog\MadelineProto\Settings\Database\Redis();
/*
    config and set auth information
*/
$database->setUri('127.0.0.1:6379');
// redis service connection information with default port
$database->setDatabase(0);
// redis database number
$database->setPassword('wsudo');
// redis service password
/*
    create default settings object
*/
$settings = new Settings();
/*
    set and merge database settings to main settings
*/
$settings->setDb($database);
/*
    create madeline proto session
*/
$MadelineProto = new API('madeline.session', $settings);
/*
    start madeline proto workers
*/
$MadelineProto->start();<?php

use danog\MadelineProto\API;
use danog\MadelineProto\Settings;
/*
    * load MadelineProto in Your Project
*/
if (\file_exists('vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    include 'madeline.php';
}
/*
    * create default Memory object
*/
$database = new \danog\MadelineProto\Settings\Database\Memory();
/*
    config and set auth information
*/
$database->setCleanup(true);
// set clean up befor serialize session
$database->setEnableFullPeerDb(false);
// madeline proto could fetch peers full information ??
$database->setEnablePeerInfoDb(true);
// enable peer basic info option
/*
    create default settings object
*/
$settings = new Settings();
/*
    set and merge database settings to main settings
*/
$settings->setDb($database);
/*
    create madeline proto session
*/
$MadelineProto = new API('madeline.session', $settings);
/*
    start madeline proto workers
*/
$MadelineProto->start();<?php

use danog\MadelineProto\API;
use danog\MadelineProto\Settings;
/*
    * load MadelineProto in Your Project
*/
if (\file_exists('vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    include 'madeline.php';
}
/*
    * create default Postgres object
*/
$database = new \danog\MadelineProto\Settings\Database\Postgres();
/*
    config and set auth information
*/
$database->setUri('127.0.0.1:5432');
// postgres db default connection inforamtion
$database->setUsername('wsudo');
// postgres db username
$database->setPassword('12345678');
// postgres db password
$database->setDatabase('MyBotsData');
// which database madeline proto will store datas in that
/*
    create default settings object
*/
$settings = new Settings();
/*
    set and merge database settings to main settings
*/
$settings->setDb($database);
/*
    create madeline proto session
*/
$MadelineProto = new API('madeline.session', $settings);
/*
    start madeline proto workers
*/
$MadelineProto->start();<?php

use danog\MadelineProto\API;
use danog\MadelineProto\Settings;
/*
    * load MadelineProto in Your Project
*/
if (\file_exists('vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    include 'madeline.php';
}
/*
    * create default mysql object
*/
$database = new \danog\MadelineProto\Settings\Database\Mysql();
/*
    config and set auth information
*/
$database->setUri('127.0.0.1:3306');
// local mysql service connection with default port
$database->setUsername('Wsudo');
// mysql service username
$database->setPassword('12345678');
// mysql service password
$database->setDatabase('MyBotsData');
// which database madeline proto will store datas in that
/*
    create default settings object
*/
$settings = new Settings();
/*
    set and merge database settings to main settings
*/
$settings->setDb($database);
/*
    create madeline proto session
*/
$MadelineProto = new API('madeline.session', $settings);
/*
    start madeline proto workers
*/
$MadelineProto->start();#!/usr/bin/env php
<?php 
/*
Copyright 2016-2020 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
if (\file_exists(__DIR__ . '/vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    include 'madeline.php';
}
$settings = [];
include_once 'token.php';
try {
    $MadelineProto = new \danog\MadelineProto\API('b.madeline');
} catch (\danog\MadelineProto\Exception $e) {
    $MadelineProto = new \danog\MadelineProto\API($settings);
    $authorization = $MadelineProto->botLogin($pwrtelegram_debug_token);
    \danog\MadelineProto\Logger::log($authorization, \danog\MadelineProto\Logger::NOTICE);
}
/**
 *
 */
function base64urlDecode($data)
{
    return \base64_decode(\str_pad(\strtr($data, '-_', '+/'), \strlen($data) % 4, '=', STR_PAD_RIGHT));
}
/**
 *
 */
function rleDecode($string)
{
    $base256 = '';
    $last = '';
    foreach (\str_split($string) as $cur) {
        if ($last === \chr(0)) {
            $base256 .= \str_repeat($last, \ord($cur));
            $last = '';
        } else {
            $base256 .= $last;
            $last = $cur;
        }
    }
    $string = $base256 . $last;
    return $string;
}
/**
 *
 */
function foreach_offset_length($string)
{
    /*    $a = [];
        $b = [];
        foreach ([2, 3, 4] as $r) {
            $a []= chr(0).chr($r);
            $b []= str_repeat(chr(0), $r);
        }
        $string = str_replace($a, $b, $string);*/
    $res = [];
    $strlen = \strlen($string);
    for ($offset = 0; $offset < \strlen($string); $offset++) {
        //        for ($length = $strlen - $offset; $length > 0; $length--) {
        foreach (['i' => 4, 'q' => 8] as $c => $length) {
            $s = \Phabel\Target\Php80\Polyfill::substr($string, $offset, $length);
            if (\strlen($s) === $length) {
                $number = \danog\PHP\Struct::unpack('<' . $c, $s)[0];
                //$number = ord($s);
                $res[] = ['number' => $number, 'offset' => $offset, 'length' => $length];
            }
        }
    }
    return $res;
}
$res = ['offset' => 0, 'files' => []];
/**
 *
 */
function getfiles($token, &$params)
{
    foreach (\json_decode(\file_get_contents('https://api.telegram.org/bot' . $token . '/getupdates?offset=' . $params['offset']), true)['result'] as $update) {
        $params['offset'] = $update['update_id'] + 1;
        if (isset($update['message']['audio'])) {
            $params['files'][$update['message']['message_id']] = $update['message']['audio']['file_id'];
        }
        if (isset($update['message']['document'])) {
            $params['files'][$update['message']['message_id']] = $update['message']['document']['file_id'];
        }
        if (isset($update['message']['video'])) {
            $params['files'][$update['message']['message_id']] = $update['message']['video']['file_id'];
        }
        if (isset($update['message']['sticker'])) {
            $params['files'][$update['message']['message_id']] = $update['message']['sticker']['file_id'];
        }
        if (isset($update['message']['voice'])) {
            $params['files'][$update['message']['message_id']] = $update['message']['voice']['file_id'];
        }
        if (isset($update['message']['photo'])) {
            $params['files'][$update['message']['message_id']] = \end($update['message']['photo'])['file_id'];
        }
    }
}
/**
 *
 */
function recurse($array, $prefix = '')
{
    $res = [];
    foreach ($array as $k => $v) {
        if (\is_array($v)) {
            $res = \array_merge(recurse($v, $prefix . $k . '->'), $res);
        } elseif (\is_int($v)) {
            $res[$prefix . $k] = $v;
        }
    }
    return $res;
}
$offset = 0;
while (true) {
    $updates = $MadelineProto->getUpdates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]);
    // Just like in the bot API, you can specify an offset, a limit and a timeout
    foreach ($updates as $update) {
        $offset = $update['update_id'] + 1;
        // Just like in the bot API, the offset must be set to the last update_id
        switch ($update['update']['_']) {
            case 'updateNewMessage':
                if (isset($update['update']['message']['out']) && $update['update']['message']['out']) {
                    continue;
                }
                try {
                    if (isset($update['update']['message']['media'])) {
                        getfiles($pwrtelegram_debug_token, $res);
                        $bot_api_id = $message = $res['files'][$update['update']['message']['id']];
                        $bot_api_id_b256 = base64urlDecode($bot_api_id);
                        $bot_api_id_rledecoded = rleDecode($bot_api_id_b256);
                        $message .= PHP_EOL . PHP_EOL;
                        for ($x = 0; $x < \strlen($bot_api_id_rledecoded) - 3; $x++) {
                            $message .= 'Bytes ' . $x . '-' . ($x + 4) . ': ' . \danog\PHP\Struct::unpack('<i', \Phabel\Target\Php80\Polyfill::substr($bot_api_id_rledecoded, $x, 4))[0] . PHP_EOL;
                        }
                        $message .= PHP_EOL . PHP_EOL . 'First 4 bytes: ' . \ord($bot_api_id_rledecoded[0]) . ' ' . \ord($bot_api_id_rledecoded[1]) . ' ' . \ord($bot_api_id_rledecoded[2]) . ' ' . \ord($bot_api_id_rledecoded[3]) . PHP_EOL . 'First 4 bytes (single integer): ' . \danog\PHP\Struct::unpack('<i', \Phabel\Target\Php80\Polyfill::substr($bot_api_id_rledecoded, 0, 4))[0] . PHP_EOL . 'bytes 8-16: ' . \danog\PHP\Struct::unpack('<q', \Phabel\Target\Php80\Polyfill::substr($bot_api_id_rledecoded, 8, 8))[0] . PHP_EOL . 'bytes 16-24: ' . \danog\PHP\Struct::unpack('<q', \Phabel\Target\Php80\Polyfill::substr($bot_api_id_rledecoded, 16, 8))[0] . PHP_EOL . 'Last byte: ' . \ord(\Phabel\Target\Php80\Polyfill::substr($bot_api_id_rledecoded, -1)) . PHP_EOL . 'Total length: ' . \strlen($bot_api_id_b256) . PHP_EOL . 'Total length (rledecoded): ' . \strlen($bot_api_id_rledecoded) . PHP_EOL . PHP_EOL . '<b>param (value): start-end (length)</b>' . PHP_EOL . PHP_EOL;
                        $bot_api = foreach_offset_length($bot_api_id_rledecoded);
                        //$mtproto = $MadelineProto->getDownloadInfo($update['update']['message']['media'])['InputFileLocation'];
                        //unset($mtproto['_']);
                        $m = [];
                        $mtproto = recurse($update['update']['message']);
                        /*
                                                if (isset($mtproto['version'])) {
                                                    unset($mtproto['version']);
                                                }
                                                if (isset($update['update']['message']['media']['photo'])) {
                                                    $mtproto['id'] = $update['update']['message']['media']['photo']['id'];
                                                }
                                                $mtproto['sender_id'] = $update['update']['message']['from_id'];
                                                if (isset($update['update']['message']['media']['photo'])) {
                                                    $mtproto['access_hash'] = $update['update']['message']['media']['photo']['access_hash'];
                                                }
                                                if (isset($update['update']['message']['media']['document'])) {
                                                    $mtproto['id'] = $update['update']['message']['media']['document']['id'];
                                                }
                                                if (isset($update['update']['message']['media']['document'])) {
                                                    $mtproto['access_hash'] = $update['update']['message']['media']['document']['access_hash'];
                                                }*/
                        foreach ($mtproto as $key => $n) {
                            foreach ($bot_api as $bn) {
                                if ($bn['number'] === $n) {
                                    $m[$bn['offset'] + $bn['length']] = $key . ' (' . $n . '): ' . $bn['offset'] . '-' . ($bn['offset'] + $bn['length']) . ' (' . $bn['length'] . ') <b>FOUND</b>' . PHP_EOL;
                                    unset($mtproto[$key]);
                                }
                            }
                        }
                        \ksort($m);
                        foreach ($m as $key => $bn) {
                            $message .= $bn;
                        }
                        foreach ($mtproto as $key => $n) {
                            $message .= $key . ' (' . $n . '): not found' . PHP_EOL;
                        }
                        $message .= PHP_EOL . PHP_EOL . 'File number: ' . \danog\PHP\Struct::unpack('<i', \Phabel\Target\Php80\Polyfill::substr($bot_api_id_rledecoded, 8, 4))[0];
                        if ($update['update']['message']['from_id'] === 101374607) {
                            $message = \danog\PHP\Struct::unpack('<i', \Phabel\Target\Php80\Polyfill::substr($bot_api_id_rledecoded, 8, 4))[0];
                        }
                        $MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_id'], 'message' => $message, 'reply_to_msg_id' => $update['update']['message']['id'], 'parse_mode' => 'markdown']);
                    }
                } catch (\danog\MadelineProto\RPCErrorException $e) {
                    $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode() . ': ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString()]);
                } catch (\danog\MadelineProto\Exception $e) {
                    $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode() . ': ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString()]);
                }
                try {
                    if (isset($update['update']['message']['media']) && $update['update']['message']['media'] == 'messageMediaPhoto' && $update['update']['message']['media'] == 'messageMediaDocument') {
                        $time = \time();
                        //                        $file = $MadelineProto->downloadToDir($update['update']['message']['media'], '/tmp');
                        //                        $MadelineProto->messages->sendMessage(['peer' => $update['update']['message']['from_id'], 'message' => 'Downloaded to '.$file.' in '.(time() - $time).' seconds', 'reply_to_msg_id' => $update['update']['message']['id'], 'entities' => [['_' => 'messageEntityPre', 'offset' => 0, 'length' => strlen($res), 'language' => 'json']]]);
                    }
                } catch (\danog\MadelineProto\RPCErrorException $e) {
                    $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => $e->getCode() . ': ' . $e->getMessage() . PHP_EOL . $e->getTraceAsString()]);
                }
        }
    }
    echo 'Wrote ' . \danog\MadelineProto\Serialization::serialize('b.madeline', $MadelineProto) . ' bytes' . PHP_EOL;
}#!/usr/bin/env php
<?php 
/**
 * Example combined event handler bot.
 *
 * Copyright 2016-2020 Daniil Gentili
 * (https://daniil.it)
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
use danog\MadelineProto\API;
use danog\MadelineProto\EventHandler;
use danog\MadelineProto\Logger;
/*
 * Various ways to load MadelineProto
 */
if (\file_exists('vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    include 'madeline.php';
}
/**
 * Event handler class.
 */
class MyEventHandler extends EventHandler
{
    /**
     * @var int|string Username or ID of bot admin
     */
    const ADMIN = "danogentili";
    // Change this
    /**
     * Get peer(s) where to report errors.
     *
     * @return (int | string | array)
     */
    public function getReportPeers()
    {
        return [self::ADMIN];
    }
    /**
     * Handle updates from supergroups and channels.
     *
     * @param array $update Update
     *
     * @return \Generator
     */
    public function onUpdateNewChannelMessage(array $update) : \Generator
    {
        return $this->onUpdateNewMessage($update);
    }
    /**
     * Handle updates from users.
     *
     * @param array $update Update
     *
     * @return \Generator
     */
    public function onUpdateNewMessage(array $update) : \Generator
    {
        if ($update['message']['_'] === 'messageEmpty' || $update['message']['out'] ?? false) {
            return;
        }
        $res = \json_encode($update, JSON_PRETTY_PRINT);
        (yield $this->messages->sendMessage(['peer' => $update, 'message' => "<code>{$res}</code>", 'reply_to_msg_id' => isset($update['message']['id']) ? $update['message']['id'] : null, 'parse_mode' => 'HTML']));
        if (isset($update['message']['media']) && $update['message']['media']['_'] !== 'messageMediaGame') {
            (yield $this->messages->sendMedia(['peer' => $update, 'message' => $update['message']['message'], 'media' => $update]));
        }
    }
}
$MadelineProtos = [];
foreach (['bot.madeline' => 'Bot Login', 'user.madeline' => 'Userbot login', 'user2.madeline' => 'Userbot login (2)'] as $session => $message) {
    Logger::log($message, Logger::WARNING);
    $MadelineProtos[] = new API($session);
}
API::startAndLoopMulti($MadelineProtos, MyEventHandler::class);#!/usr/bin/env php
<?php 
/**
 * Get all messages in multiple threads.
 *
 * Copyright 2016-2020 Daniil Gentili
 * (https://daniil.it)
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Alexander Panlratov <alexander@i-c-a.su>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
/*
 * Various ways to load MadelineProto
 */
if (\file_exists('vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    /**
     * @psalm-suppress MissingFile
     */
    include 'madeline.php';
}
$MadelineProto = new \danog\MadelineProto\API('bot.madeline');
$MadelineProto->async(true);
$MadelineProto->loop(static function () use($MadelineProto) {
    (yield $MadelineProto->start());
    $lastMessageId = 0;
    $threads = 5;
    $step = 20;
    $totalMessages = 0;
    $start = \microtime(true);
    while (true) {
        $promises = [];
        for ($i = 0; $i < $threads; $i++) {
            $promises[] = $MadelineProto->messages->getMessages(['id' => \range($lastMessageId + 1, $lastMessageId + $step)]);
            $lastMessageId += $step;
        }
        $results = (yield \Amp\Promise\all($promises));
        foreach ($results as $result) {
            foreach ($result['messages'] as $message) {
                if ($message['_'] === 'messageEmpty') {
                    break 3;
                }
                $totalMessages++;
                (yield $MadelineProto->echo("\rTotal messages processed: {$totalMessages}"));
            }
        }
    }
    $time = \microtime(true) - $start;
    (yield $MadelineProto->echo("\nTime: {$time}\n"));
});#!/usr/bin/env php
<?php 
/*
Copyright 2016-2020 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
require '../vendor/autoload.php';
$settings = [];
$Lua = false;
try {
    $Lua = \danog\MadelineProto\Serialization::deserialize('td.madeline');
} catch (\danog\MadelineProto\Exception $e) {
}
if (!\is_object($Lua)) {
    $MadelineProto = new \danog\MadelineProto\API($settings);
    while (!\in_array($res = \readline('Do you want to login as a user or as a bot (u/b)? '), ['u', 'b'])) {
        echo 'Please write either u or b' . PHP_EOL;
    }
    switch ($res) {
        case 'u':
            $sentCode = $MadelineProto->phoneLogin(\readline('Enter your phone number: '));
            \danog\MadelineProto\Logger::log($sentCode, \danog\MadelineProto\Logger::NOTICE);
            echo 'Enter the code you received: ';
            $code = \fgets(STDIN, (isset($sentCode['type']['length']) ? $sentCode['type']['length'] : 5) + 1);
            $authorization = $MadelineProto->completePhoneLogin($code);
            \danog\MadelineProto\Logger::log($authorization, \danog\MadelineProto\Logger::NOTICE);
            if ($authorization['_'] === 'account.noPassword') {
                throw new \danog\MadelineProto\Exception('2FA is enabled but no password is set!');
            }
            if ($authorization['_'] === 'account.password') {
                \danog\MadelineProto\Logger::log('2FA is enabled', \danog\MadelineProto\Logger::NOTICE);
                $authorization = $MadelineProto->complete_2fa_login(\readline('Please enter your password (hint ' . $authorization['hint'] . '): '));
            }
            if ($authorization['_'] === 'account.needSignup') {
                \danog\MadelineProto\Logger::log('Registering new user', \danog\MadelineProto\Logger::NOTICE);
                $authorization = $MadelineProto->completeSignup(\readline('Please enter your first name: '), \readline('Please enter your last name (can be empty): '));
            }
            \danog\MadelineProto\Logger::log($authorization, \danog\MadelineProto\Logger::NOTICE);
            $Lua = new \danog\MadelineProto\Lua('madeline.lua', $MadelineProto);
            break;
        case 'b':
            $authorization = $MadelineProto->botLogin(\readline('Please enter a bot token: '));
            \danog\MadelineProto\Logger::log($authorization, \danog\MadelineProto\Logger::NOTICE);
            $Lua = new \danog\MadelineProto\Lua('madeline.lua', $MadelineProto);
            break;
    }
}
$offset = 0;
while (true) {
    $updates = $Lua->MadelineProto->getUpdates(['offset' => $offset, 'limit' => 50, 'timeout' => 0]);
    // Just like in the bot API, you can specify an offset, a limit and a timeout
    foreach ($updates as $update) {
        $offset = $update['update_id'] + 1;
        // Just like in the bot API, the offset must be set to the last update_id
        $Lua->tdcliUpdateCallback($update['update']);
    }
    echo 'Wrote ' . \danog\MadelineProto\Serialization::serialize('td.madeline', $Lua) . ' bytes' . PHP_EOL;
}#!/usr/bin/env php
<?php 
/**
 * Secret chat bot.
 *
 * Copyright 2016-2020 Daniil Gentili
 * (https://daniil.it)
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
use danog\MadelineProto\APIWrapper;
use danog\MadelineProto\Settings;
/*
 * Various ways to load MadelineProto
 */
if (\file_exists(__DIR__ . '/../vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    include 'madeline.php';
}
class SecretHandler extends \danog\MadelineProto\EventHandler
{
    private $sent = [-440592694 => true];
    /**
     *
     */
    public function __construct(?APIWrapper $API)
    {
        parent::__construct($API);
        $this->sent = [];
    }
    /**
     * @var int|string Username or ID of bot admin
     */
    const ADMIN = "danogentili";
    // Change this
    /**
     * Get peer(s) where to report errors.
     *
     * @return (int | string | array)
     */
    public function getReportPeers()
    {
        return [self::ADMIN];
    }
    /**
     * Handle updates from users.
     *
     * @param array $update Update
     *
     * @return \Generator
     */
    public function onUpdateNewMessage(array $update) : \Generator
    {
        if ($update['message']['message'] === 'request') {
            (yield $this->requestSecretChat($update));
        }
        if ($update['message']['message'] === 'ping') {
            (yield $this->messages->sendMessage(['message' => 'lmao', 'peer' => $update]));
        }
    }
    /**
     * Handle secret chat messages.
     *
     * @param array $update Update
     *
     * @return \Generator
     */
    public function onUpdateNewEncryptedMessage(array $update) : \Generator
    {
        if (isset($update['message']['decrypted_message']['media'])) {
            $this->logger((yield $this->downloadToDir($update, '.')));
        }
        if (isset($this->sent[$update['message']['chat_id']])) {
            return;
        }
        $secret_media = [];
        // Photo uploaded as document, secret chat
        $secret_media['document_photo'] = ['peer' => $update, 'file' => 'tests/faust.jpg', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/faust.jpg'), 'caption' => 'This file was uploaded using MadelineProto', 'file_name' => 'faust.jpg', 'size' => \filesize('tests/faust.jpg'), 'attributes' => [['_' => 'documentAttributeImageSize', 'w' => 1280, 'h' => 914]]]]];
        // Photo, secret chat
        $secret_media['photo'] = ['peer' => $update, 'file' => 'tests/faust.jpg', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaPhoto', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'caption' => 'This file was uploaded using MadelineProto', 'size' => \filesize('tests/faust.jpg'), 'w' => 1280, 'h' => 914]]];
        // GIF, secret chat
        $secret_media['gif'] = ['peer' => $update, 'file' => 'tests/pony.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/pony.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/pony.mp4'), 'caption' => 'test', 'file_name' => 'pony.mp4', 'size' => \filesize('tests/faust.jpg'), 'attributes' => [['_' => 'documentAttributeAnimated']]]]];
        // Sticker, secret chat
        $secret_media['sticker'] = ['peer' => $update, 'file' => 'tests/lel.webp', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/lel.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/lel.webp'), 'caption' => 'test', 'file_name' => 'lel.webp', 'size' => \filesize('tests/lel.webp'), 'attributes' => [['_' => 'documentAttributeSticker', 'alt' => 'LEL', 'stickerset' => ['_' => 'inputStickerSetEmpty']]]]]];
        // Document, secrey chat
        $secret_media['document'] = ['peer' => $update, 'file' => 'tests/60', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => 'magic/magic', 'caption' => 'test', 'file_name' => 'magic.magic', 'size' => \filesize('tests/60'), 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'fairy']]]]];
        // Video, secret chat
        $secret_media['video'] = ['peer' => $update, 'file' => 'tests/swing.mp4', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/swing.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/swing.mp4'), 'caption' => 'test', 'file_name' => 'swing.mp4', 'size' => \filesize('tests/swing.mp4'), 'attributes' => [['_' => 'documentAttributeVideo', 'duration' => 5, 'w' => 1280, 'h' => 720]]]]];
        // audio, secret chat
        $secret_media['audio'] = ['peer' => $update, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => \filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => false, 'duration' => 1, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]];
        $secret_media['voice'] = ['peer' => $update, 'file' => 'tests/mosconi.mp3', 'message' => ['_' => 'decryptedMessage', 'ttl' => 0, 'message' => '', 'media' => ['_' => 'decryptedMessageMediaDocument', 'thumb' => \file_get_contents('tests/faust.preview.jpg'), 'thumb_w' => 90, 'thumb_h' => 90, 'mime_type' => \mime_content_type('tests/mosconi.mp3'), 'caption' => 'test', 'file_name' => 'mosconi.mp3', 'size' => \filesize('tests/mosconi.mp3'), 'attributes' => [['_' => 'documentAttributeAudio', 'voice' => true, 'duration' => 1, 'title' => 'AH NON LO SO IO', 'performer' => 'IL DIO GERMANO MOSCONI']]]]];
        foreach ($secret_media as $type => $smessage) {
            $promises = $this->messages->sendEncryptedFile($smessage);
        }
        (yield $promises);
        $i = 0;
        while ($i < 10) {
            $this->logger("SENDING MESSAGE {$i} TO " . $update['message']['chat_id']);
            // You can also use the sendEncrypted parameter for more options in secret chats
            (yield $this->messages->sendMessage(['peer' => $update, 'message' => (string) $i++]));
        }
        $this->sent[$update['message']['chat_id']] = true;
    }
}
$settings = new Settings();
SecretHandler::startAndLoop('secret.madeline', $settings);<?php

/**
 * Example script.
 *
 * Copyright 2016-2020 Daniil Gentili
 * (https://daniil.it)
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
require '../vendor/autoload.php';
$MadelineProto = new \danog\MadelineProto\API('index.madeline');
$me = $MadelineProto->start();
$me = $MadelineProto->getSelf();
\danog\MadelineProto\Logger::log($me);
if (!$me['bot']) {
    $MadelineProto->messages->sendMessage(['peer' => '@danogentili', 'message' => "Hi!\nThanks for creating MadelineProto! <3"]);
    $MadelineProto->channels->joinChannel(['channel' => '@MadelineProto']);
    try {
        $MadelineProto->messages->importChatInvite(['hash' => 'https://t.me/joinchat/Bgrajz6K-aJKu0IpGsLpBg']);
    } catch (\danog\MadelineProto\RPCErrorException $e) {
    }
    $MadelineProto->messages->sendMessage(['peer' => 'https://t.me/joinchat/Bgrajz6K-aJKu0IpGsLpBg', 'message' => 'Testing MadelineProto!']);
}
echo 'OK, done!' . PHP_EOL;#!/usr/bin/env php
<?php 
/**
 * Example bot.
 *
 * Copyright 2016-2020 Daniil Gentili
 * (https://daniil.it)
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
use danog\MadelineProto\Db\DbArray;
use danog\MadelineProto\EventHandler;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Settings\Database\Mysql;
use danog\MadelineProto\Settings\Database\Postgres;
use danog\MadelineProto\Settings\Database\Redis;
/*
 * Various ways to load MadelineProto
 */
if (\file_exists('vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    /**
     * @psalm-suppress MissingFile
     */
    include 'madeline.php';
}
/**
 * Event handler class.
 */
class MyEventHandler extends EventHandler
{
    /**
     * @var int|string Username or ID of bot admin
     */
    const ADMIN = "danogentili";
    // Change this
    /**
     * List of properties automatically stored in database (MySQL, Postgres, redis or memory).
     * @see https://docs.madelineproto.xyz/docs/DATABASE.html
     * @var array
     */
    protected static array $dbProperties = ['dataStoredOnDb' => 'array'];
    /**
     * @var DbArray<array>
     */
    protected $dataStoredOnDb;
    /**
     * Get peer(s) where to report errors.
     *
     * @return (int | string | array)
     */
    public function getReportPeers()
    {
        return [self::ADMIN];
    }
    /**
     * Handle updates from supergroups and channels.
     *
     * @param array $update Update
     *
     * @return void
     */
    public function onUpdateNewChannelMessage(array $update) : \Generator
    {
        return $this->onUpdateNewMessage($update);
    }
    /**
     * Handle updates from users.
     *
     * @param array $update Update
     *
     * @return \Generator
     */
    public function onUpdateNewMessage(array $update) : \Generator
    {
        if ($update['message']['_'] === 'messageEmpty' || $update['message']['out'] ?? false) {
            return;
        }
        $res = \json_encode($update, JSON_PRETTY_PRINT);
        (yield $this->messages->sendMessage(['peer' => $update, 'message' => "<code>{$res}</code>", 'reply_to_msg_id' => isset($update['message']['id']) ? $update['message']['id'] : null, 'parse_mode' => 'HTML']));
        if (isset($update['message']['media']) && $update['message']['media']['_'] !== 'messageMediaGame' && $update['message']['media']['_'] !== 'messageMediaWebPage') {
            (yield $this->messages->sendMedia(['peer' => $update, 'message' => $update['message']['message'], 'media' => $update]));
        }
        // You can also use the built-in MadelineProto MySQL async driver!
        // Can be anything serializable, an array, an int, an object
        $myData = [];
        // Use the isset method to check whether some data exists in the database
        if ((yield $this->dataStoredOnDb->isset('yourKey'))) {
            // Always yield when fetching data
            $myData = (yield $this->dataStoredOnDb['yourKey']);
        }
        $this->dataStoredOnDb['yourKey'] = $myData + ['moreStuff' => 'yay'];
        $this->dataStoredOnDb['otherKey'] = 0;
        unset($this->dataStoredOnDb['otherKey']);
        $this->logger("Count: " . (yield $this->dataStoredOnDb->count()));
        // You can even use an async iterator to iterate over the data
        $iterator = $this->dataStoredOnDb->getIterator();
        while ((yield $iterator->advance())) {
            [$key, $value] = $iterator->getCurrent();
            $this->logger($key);
            $this->logger($value);
        }
    }
}
$settings = new Settings();
$settings->getLogger()->setLevel(Logger::LEVEL_ULTRA_VERBOSE);
// You can also use Redis, MySQL or PostgreSQL
// $settings->setDb((new Redis)->setDatabase(0)->setPassword('pony'));
// $settings->setDb((new Postgres)->setDatabase('MadelineProto')->setUsername('daniil')->setPassword('pony'));
// $settings->setDb((new Mysql)->setDatabase('MadelineProto')->setUsername('daniil')->setPassword('pony'));
// Reduce boilerplate with new wrapper method.
// Also initializes error reporting, catching and reporting all errors surfacing from the event loop.
MyEventHandler::startAndLoop('uwu.madeline', $settings);#!/usr/bin/env php
<?php 
/**
 * Example bot.
 *
 * Copyright 2016-2020 Daniil Gentili
 * (https://daniil.it)
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://docs.madelineproto.xyz MadelineProto documentation
 */
if (\function_exists('memprof_enable')) {
    \memprof_enable();
}
use Amp\Http\Server\HttpServer;
use danog\MadelineProto\API;
use danog\MadelineProto\APIWrapper;
use danog\MadelineProto\MTProtoTools\Files;
use danog\MadelineProto\RPCErrorException;
use danog\MadelineProto\Settings;
use danog\MadelineProto\Tools;
use League\Uri\Contracts\UriException;
/*
 * Various ways to load MadelineProto
 */
if (\file_exists('vendor/autoload.php')) {
    include 'vendor/autoload.php';
} else {
    if (!\file_exists('madeline.php')) {
        \copy('https://phar.madelineproto.xyz/madeline.php', 'madeline.php');
    }
    include 'madeline.php';
}
/**
 * Event handler class.
 */
class MyEventHandler extends \danog\MadelineProto\EventHandler
{
    const START = 'Send me a file URL and I will download it and send it to you!

Usage: `https://example.com`
Usage: `https://example.com file name.ext`

I can also rename Telegram files, just send me any file and I will rename it!

Max 1.5GB, parallel upload and download powered by @MadelineProto.';
    /**
     * @var int|string Username or ID of bot admin
     */
    const ADMIN = 'danogentili';
    // Change this
    /**
     * Get peer(s) where to report errors.
     *
     * @return (int | string | array)
     */
    public function getReportPeers()
    {
        return [self::ADMIN];
    }
    /**
     * Whether to allow uploads.
     */
    private $UPLOAD;
    /**
     * Array of media objects.
     *
     * @var array
     */
    private $states = [];
    /**
     * Constructor.
     *
     * @param ?API $API API
     */
    public function __construct(?APIWrapper $API)
    {
        $this->UPLOAD = \class_exists(HttpServer::class);
        parent::__construct($API);
    }
    /**
     *
     */
    public function onStart()
    {
        $this->adminId = (yield $this->getInfo(self::ADMIN)['bot_api_id']);
    }
    /**
     * Handle updates from channels and supergroups.
     *
     * @param array $update Update
     *
     * @return \Generator
     */
    public function onUpdateNewChannelMessage(array $update)
    {
        //yield $this->onUpdateNewMessage($update);
    }
    /**
     * Handle updates from users.
     *
     * @param array $update Update
     *
     * @return \Generator
     */
    public function onUpdateNewMessage(array $update) : \Generator
    {
        if ($update['message']['out'] ?? false) {
            return;
        }
        if ($update['message']['_'] !== 'message') {
            return;
        }
        try {
            $peer = (yield $this->getInfo($update));
            $peerId = $peer['bot_api_id'];
            $messageId = $update['message']['id'];
            if ($this->UPLOAD && $update['message']['message'] === '/getUrl') {
                (yield $this->messages->sendMessage(['peer' => $peerId, 'message' => 'Give me a file: ', 'reply_to_msg_id' => $messageId]));
                $this->states[$peerId] = $this->UPLOAD;
                return;
            }
            if ($update['message']['message'] === '/start') {
                return $this->messages->sendMessage(['peer' => $peerId, 'message' => self::START, 'parse_mode' => 'Markdown', 'reply_to_msg_id' => $messageId]);
            }
            if ($update['message']['message'] === '/report' && $peerId === $this->adminId) {
                \memprof_dump_callgrind($stm = \fopen("php://memory", "w"));
                \fseek($stm, 0);
                (yield $this->messages->sendMedia(['peer' => $peerId, 'media' => ['_' => 'inputMediaUploadedDocument', 'file' => $stm, 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => 'callgrind.out']]]]));
                \fclose($stm);
                return;
            }
            if (isset($update['message']['media']['_']) && $update['message']['media']['_'] !== 'messageMediaWebPage') {
                if ($this->UPLOAD && ($this->states[$peerId] ?? false) === $this->UPLOAD) {
                    unset($this->states[$peerId]);
                    $update = Files::extractBotAPIFile((yield $this->MTProtoToBotAPI($update)));
                    $file = [$update['file_size'], $update['mime_type']];
                    \var_dump($update['file_id'] . '.' . Tools::base64urlEncode(\json_encode($file)) . "/" . $update['file_name']);
                    return;
                }
                (yield $this->messages->sendMessage(['peer' => $peerId, 'message' => 'Give me a new name for this file: ', 'reply_to_msg_id' => $messageId]));
                $this->states[$peerId] = $update['message']['media'];
                return;
            }
            if (isset($this->states[$peerId])) {
                $name = $update['message']['message'];
                $url = $this->states[$peerId];
                unset($this->states[$peerId]);
            } else {
                $url = \explode(' ', $update['message']['message'], 2);
                $name = \trim($url[1] ?? \basename($update['message']['message']));
                $url = \trim($url[0]);
                if (!$url) {
                    return;
                }
                if (\stripos($url, 'http') !== 0) {
                    $url = "http://{$url}";
                }
            }
            $id = (yield $this->messages->sendMessage(['peer' => $peerId, 'message' => 'Preparing...', 'reply_to_msg_id' => $messageId]));
            if (!isset($id['id'])) {
                $this->report(\json_encode($id));
                foreach ($id['updates'] as $updat) {
                    if (isset($updat['id'])) {
                        $id = $updat['id'];
                        break;
                    }
                }
            } else {
                $id = $id['id'];
            }
            $url = new \danog\MadelineProto\FileCallback($url, function ($progress, $speed, $time) use($peerId, $id) {
                $this->logger("Upload progress: {$progress}%");
                static $prev = 0;
                $now = \time();
                if ($now - $prev < 10 && $progress < 100) {
                    return;
                }
                $prev = $now;
                try {
                    (yield $this->messages->editMessage(['peer' => $peerId, 'id' => $id, 'message' => "Upload progress: {$progress}%\nSpeed: {$speed} mbps\nTime elapsed since start: {$time}"], ['FloodWaitLimit' => 0]));
                } catch (\danog\MadelineProto\RPCErrorException $e) {
                }
            });
            (yield $this->messages->sendMedia(['peer' => $peerId, 'reply_to_msg_id' => $messageId, 'media' => ['_' => 'inputMediaUploadedDocument', 'file' => $url, 'attributes' => [['_' => 'documentAttributeFilename', 'file_name' => $name]]], 'message' => 'Powered by @MadelineProto!', 'parse_mode' => 'Markdown']));
            if (\in_array($peer['type'], ['channel', 'supergroup'])) {
                (yield $this->channels->deleteMessages(['channel' => $peerId, 'id' => [$id]]));
            } else {
                (yield $this->messages->deleteMessages(['revoke' => true, 'id' => [$id]]));
            }
        } catch (\Throwable $e) {
            if (\strpos($e->getMessage(), 'Could not connect to URI') === false && !$e instanceof UriException && \strpos($e->getMessage(), 'URI') === false) {
                $this->report((string) $e);
                $this->logger((string) $e, \danog\MadelineProto\Logger::FATAL_ERROR);
            }
            if ($e instanceof RPCErrorException && $e->rpc === 'FILE_PARTS_INVALID') {
                $this->report(\json_encode($url));
            }
            try {
                (yield $this->messages->editMessage(['peer' => $peerId, 'id' => $id, 'message' => 'Error: ' . $e->getMessage()]));
            } catch (\Throwable $e) {
                $this->logger((string) $e, \danog\MadelineProto\Logger::FATAL_ERROR);
            }
        }
    }
}
$settings = new Settings();
$settings->getConnection()->setMinMediaSocketCount(20)->setMaxMediaSocketCount(1000);
// IMPORTANT: for security reasons, upload by URL will still be allowed
$settings->getFiles()->setAllowAutomaticUpload(true);
// Reduce boilerplate with new wrapper method.
// Also initializes error reporting, catching and reporting all errors surfacing from the event loop.
MyEventHandler::startAndLoop(($argv[1] ?? 'bot') . '.madeline', $settings);<?php

{
    "require": {
        "vimeo/psalm": "dev-master",
        "ennexa/amp-update-cache": "dev-master",
        "phpunit/phpunit": "^9",
        "amphp/php-cs-fixer-config": "dev-master",
        "friendsofphp/php-cs-fixer": "^2.16"
    }
}
{
	"name": "PHP",
	"build": {
		"dockerfile": "Dockerfile",
		"args": { 
			// Update VARIANT to pick a PHP version: 7, 7.4, 7.3
			"VARIANT": "7.4",
			"INSTALL_NODE": "true",
			"NODE_VERSION": "lts/*"
		}
	},
	
	// Set *default* container specific settings.json values on container create.
	"settings": { 
		"terminal.integrated.shell.linux": "/bin/bash"
	},

	// Add the IDs of extensions you want installed when the container is created.
	"extensions": [
		"felixfbecker.php-debug",
		"felixfbecker.php-intellisense",
                "getpsalm.psalm-vscode-plugin",
                "junstyle.php-cs-fixer"
	]

	// Use 'forwardPorts' to make a list of ports inside the container available locally.
	// "forwardPorts": [],

	// Use 'postCreateCommand' to run commands after the container is created.
	// "postCreateCommand": "php -v",

	// Uncomment to connect as a non-root user. See https://aka.ms/vscode-remote/containers/non-root.
	// "remoteUser": "vscode"
}
#!/usr/bin/env php
<?php 
/*
Copyright 2016-2020 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
if (!isset($argv[3])) {
    echo 'Usage: ' . $argv[0] . ' inputDir output.phar ref' . PHP_EOL;
    die(1);
}
@\unlink($argv[2]);
$p = new Phar(__DIR__ . '/../' . $argv[2], 0, $argv[2]);
$p->buildFromDirectory(\realpath($argv[1]), '/^((?!tests).)*(\\.php|\\.py|\\.exe|\\.tl|\\.json|\\.dat|\\.h)$/i');
$p->addFromString('vendor/danog/madelineproto/.git/refs/heads/master', $argv[3]);
$p->addFromString('.git/refs/heads/master', $argv[3]);
$p->setStub('<?php
$backtrace = debug_backtrace();
if (!isset($backtrace[0]["file"]) || !in_array(basename($backtrace[0]["file"]), ["madeline.php", "phar.php", "testing.php"])) {
    echo("madeline.phar cannot be required manually: use the automatic loader, instead: https://docs.madelineproto.xyz/docs/INSTALLATION.html#simple".PHP_EOL);
    die(1);
}
if (defined("MADELINE_REAL_ROOT")) {
    @chdir(MADELINE_REAL_ROOT);
}
if ($contents = file_get_contents("https://phar.madelineproto.xyz/phar.php?v=new".rand(0, PHP_INT_MAX))) {
    file_put_contents($backtrace[0]["file"], $contents);
}

Phar::interceptFileFuncs();
Phar::mapPhar("' . $argv[2] . '"); 
return require_once "phar://' . $argv[2] . '/vendor/autoload.php"; 

__HALT_COMPILER(); ?>');<?php

use danog\MadelineProto\Tools;
use HaydenPierce\ClassFinder\ClassFinder;
\chdir(__DIR__ . '/../');
require 'vendor/autoload.php';
$classes = ClassFinder::getClassesInNamespace(danog\MadelineProto::class, ClassFinder::RECURSIVE_MODE);
$methods = [];
foreach ($classes as $class) {
    $class = new \ReflectionClass($class);
    $methods = \array_merge($class->getMethods(), $methods);
}
$methods = \array_unique($methods);
/**
 *
 */
function ssort($a, $b)
{
    return \strlen($b->getName()) - \strlen($a->getName());
}
\usort($methods, 'ssort');
$find = [];
$replace = [];
$findDocs = [];
$replaceDocs = [];
foreach ($methods as $methodObj) {
    $method = $methodObj->getName();
    if (\strpos($method, '__') === 0 || $method === 'async') {
        continue;
    }
    $method = Tools::fromCamelCase($method);
    $new = Tools::fromSnakeCase($method);
    $new = \str_ireplace(['mtproto', 'api'], ['MTProto', 'API'], $new);
    $new = \preg_replace('/TL$/i', 'TL', $new);
    if (!\in_array($method, ['discardCallAsync', 'acceptCallAsync', 'requestCallAsync'])) {
        $new = \preg_replace('/async$/i', '', $new);
    }
    $findDocs[] = Tools::fromCamelCase($new) . '(';
    $replaceDocs[] = $new . '(';
    $findDocs[] = $method . '(';
    $replaceDocs[] = $new . '(';
    $findDocs[] = Tools::fromCamelCase($new) . '.';
    $replaceDocs[] = $new . '.';
    $findDocs[] = $method . '.';
    $replaceDocs[] = $new . '.';
    $findDocs[] = Tools::fromCamelCase($new) . ']';
    $replaceDocs[] = $new . ']';
    $findDocs[] = $method . ']';
    $replaceDocs[] = $new . ']';
    if (\method_exists((string) $methodObj->getDeclaringClass(), \preg_replace('/async$/i', '', $method))) {
        \var_dump("Skipping {$method} => {$new}");
        continue;
    }
    if (!\function_exists($method)) {
        $find[] = "{$method}";
        $replace[] = "{$new}";
        continue;
    }
    $find[] = ">{$method}(";
    $replace[] = ">{$new}(";
    $find[] = ":{$method}(";
    $replace[] = ":{$new}(";
    $find[] = "function {$method}(";
    $replace[] = "function {$new}(";
}
foreach (new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator(\realpath('.'))), '/\\.php$/') as $filename) {
    $filename = (string) $filename;
    $new = \str_replace($find, $replace, $old = \file_get_contents($filename));
    do {
        \file_put_contents($filename, $new);
        $new = \str_replace($find, $replace, $old = \file_get_contents($filename));
    } while ($old !== $new);
}
exit;
foreach (new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator(\realpath('docs'))), '/\\.md$/') as $filename) {
    $filename = (string) $filename;
    $new = \str_replace($findDocs, $replaceDocs, $old = \file_get_contents($filename));
    do {
        \file_put_contents($filename, $new);
        $new = \str_replace($findDocs, $replaceDocs, $old = \file_get_contents($filename));
    } while ($old !== $new);
}
$filename = 'README.md';
$new = \str_replace($findDocs, $replaceDocs, $old = \file_get_contents($filename));
do {
    \file_put_contents($filename, $new);
    $new = \str_replace($findDocs, $replaceDocs, $old = \file_get_contents($filename));
} while ($old !== $new);<?php

use danog\MadelineProto\Lang;
require 'vendor/autoload.php';
$template = '<?php
/**
 * Lang module
 *
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 * @link      https://docs.madelineproto.xyz MadelineProto documentation
 */

namespace danog\\MadelineProto;

class Lang
{
    public static $lang = %s;

    // THIS WILL BE OVERWRITTEN BY $lang["en"]
    public static $current_lang = %s;
}';
/**
 *
 */
function fromCamelCase($input)
{
    \preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
    $ret = $matches[0];
    foreach ($ret as &$match) {
        $match = $match == \strtoupper($match) ? \strtolower($match) : \lcfirst($match);
    }
    return \implode(' ', $ret);
}
foreach (Lang::$lang as $code => &$currentLang) {
    if ($code === 'en') {
        continue;
    }
    $currentLang = \array_intersect_key($currentLang, Lang::$lang['en']);
}
$lang_code = \readline('Enter the language you whish to localize: ');
if (!isset(Lang::$lang[$lang_code])) {
    Lang::$lang[$lang_code] = Lang::$current_lang;
    echo 'New language detected!' . PHP_EOL . PHP_EOL;
} else {
    echo 'Completing localization of existing language' . PHP_EOL . PHP_EOL;
}
$count = \count(Lang::$lang[$lang_code]);
$curcount = 0;
\ksort(Lang::$current_lang);
foreach (Lang::$current_lang as $key => $value) {
    if (!(Lang::$lang[$lang_code][$key] ?? '')) {
        Lang::$lang[$lang_code][$key] = $value;
    }
    if (Lang::$lang[$lang_code][$key] === '' || Lang::$lang[$lang_code][$key] === Lang::$lang['en'][$key] && Lang::$lang[$lang_code][$key] !== 'Bot') {
        $value = Lang::$lang[$lang_code][$key];
        if (\in_array($key, ['v_error', 'v_tgerror'])) {
            $value = \hex2bin($value);
        }
        if ($value == '') {
            $value = $key;
        }
        Lang::$lang[$lang_code][$key] = \readline($value . ' => ');
        /*
                if ($param_name === 'nonce' && $param_type === 'int128') {
                    Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security';
                } elseif ($param_name === 'server_nonce' && $param_type === 'int128') {
                    Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security, given by server';
                } elseif ($param_name === 'random_id' && $param_type === 'long') {
                    Lang::$lang[$lang_code][$key] = 'Random number for cryptographic security';
                } else elseif (\strpos($value, 'Update ') === 0) {
                    if (!$param_name && \strpos($key, 'object_') === 0) {
                        $value = \str_replace('Update ', '', $value).' update';
                    }
                    //} elseif (ctype_lower($value[0])) {
                } else {
                    Lang::$lang[$lang_code][$key] = \readline($value.' => ');
                    if (Lang::$lang[$lang_code][$key] === '') {
                        if ($param_name) {
                            $l = \str_replace('_', ' ', $param_name);
                        } else {
                            $l = \explode('.', $method_name);
                            $l = fromCamelCase(\end($l));
                        }
                        $l = \ucfirst(\strtolower($l));
                        if (\preg_match('/ empty$/', $l)) {
                            $l = 'Empty '.\strtolower(\preg_replace('/ empty$/', '', $l));
                        }
                        foreach (['id', 'url', 'dc'] as $upper) {
                            $l = \str_replace([\ucfirst($upper), ' '.$upper], [\strtoupper($upper), ' '.\strtoupper($upper)], $l);
                        }
        
                        if (\in_array($param_type, ['Bool', 'true', 'false'])) {
                            $l .= '?';
                        }
        
                        Lang::$lang[$lang_code][$key] = $l;
                        echo 'Using default value '.Lang::$lang[$lang_code][$key].PHP_EOL;
                    }
                }*/
        Lang::$lang[$lang_code][$key] = \ucfirst(Lang::$lang[$lang_code][$key]);
        if (\in_array($key, ['v_error', 'v_tgerror'])) {
            Lang::$lang[$lang_code][$key] = \bin2hex(Lang::$lang[$lang_code][$key]);
        }
        \file_put_contents('src/danog/MadelineProto/Lang.php', \sprintf($template, \var_export(Lang::$lang, true), \var_export(Lang::$lang['en'], true)));
        echo 'OK, ' . $curcount * 100 / $count . '% done. edit src/danog/MadelineProto/Lang.php to fix mistakes.' . PHP_EOL;
    }
    $curcount++;
}
\file_put_contents('src/danog/MadelineProto/Lang.php', \sprintf($template, \var_export(Lang::$lang, true), \var_export(Lang::$lang['en'], true)));
echo 'OK. edit src/danog/MadelineProto/Lang.php to fix mistakes.' . PHP_EOL;<?php

namespace danog\MadelineProto;

if (\defined('MADELINE_PHP')) {
    throw new \Exception('Please do not include madeline.php twice!');
}
if (!\defined('MADELINE_ALLOW_COMPOSER') && \class_exists(\Composer\Autoload\ClassLoader::class)) {
    throw new \Exception('Composer autoloader detected: madeline.php is incompatible with Composer, please require MadelineProto using composer.');
}
\define('MADELINE_PHP', __FILE__);
class Installer
{
    const RELEASE_TEMPLATE = 'https://phar.madelineproto.xyz/release%s?v=new';
    const PHAR_TEMPLATE = 'https://phar.madelineproto.xyz/madeline%s.phar?v=%s';
    /**
     * Phar lock instance.
     *
     * @var resource|null
     */
    private static $lock = null;
    /**
     * Installer lock instance.
     *
     * @var resource|null
     */
    private $lockInstaller = null;
    /**
     * PHP version.
     *
     * @var string
     */
    private $version;
    /**
     * Constructor.
     */
    public function __construct()
    {
        if (PHP_MAJOR_VERSION === 7 && PHP_MINOR_VERSION < 1 || PHP_MAJOR_VERSION < 7) {
            throw new \Exception('MadelineProto requires at least PHP 7.1 to run');
        }
        if (PHP_INT_SIZE < 8) {
            throw new \Exception('A 64-bit build of PHP is required to run MadelineProto, PHP 8.0+ recommended.');
        }
        $backtrace = \debug_backtrace(0);
        if (\count($backtrace) === 1) {
            if (isset($GLOBALS['argv']) && !empty($GLOBALS['argv'])) {
                $arguments = \array_slice($GLOBALS['argv'], 1);
            } elseif (isset($_GET['argv']) && !empty($_GET['argv'])) {
                $arguments = $_GET['argv'];
            } else {
                $arguments = [];
            }
            if (\count($arguments) >= 2) {
                \define(\MADELINE_WORKER_TYPE::class, \array_shift($arguments));
                \define(\MADELINE_WORKER_ARGS::class, $arguments);
            } else {
                die('MadelineProto loader: you must include this file in another PHP script, see https://docs.madelineproto.xyz for more info.' . PHP_EOL);
            }
            \define('MADELINE_REAL_ROOT', \dirname($backtrace[0]["file"]));
        }
        $this->version = (string) \min(81, (int) (PHP_MAJOR_VERSION . PHP_MINOR_VERSION));
        \define('MADELINE_PHAR_GLOB', \getcwd() . DIRECTORY_SEPARATOR . "madeline*-{$this->version}.phar");
        \define('MADELINE_RELEASE_URL', \sprintf(self::RELEASE_TEMPLATE, $this->version));
    }
    /**
     * Destructor.
     */
    public function __destruct()
    {
        if ($this->lockInstaller) {
            \flock($this->lockInstaller, LOCK_UN);
            \fclose($this->lockInstaller);
            $this->lockInstaller = null;
        }
    }
    /**
     * Extract composer package versions from phar.
     *
     * @param (string | null) $release
     * @return array<string, string>
     */
    private static function extractVersions($release)
    {
        $phar = "madeline-{$release}.phar";
        $packages = ['danog/madelineproto' => 'old'];
        if (!\file_exists("phar://{$phar}/vendor/composer/installed.json")) {
            return $packages;
        }
        $composer = \json_decode(\file_get_contents("phar://{$phar}/vendor/composer/installed.json"), true) ?: [];
        if (!isset($composer['packages'])) {
            return $packages;
        }
        foreach ($composer['packages'] as $dep) {
            $name = $dep['name'];
            if (\strpos($name, 'phabel/transpiler') === 0) {
                $name = \explode('/', $name, 3)[2];
            }
            $version = $dep['version_normalized'];
            if ($name === 'danog/madelineproto' && \Phabel\Target\Php80\Polyfill::substr($version, 0, 2) === '90') {
                $version = \Phabel\Target\Php80\Polyfill::substr($version, 2);
            }
            $packages[$name] = $version;
        }
        return $packages;
    }
    /**
     * Report installs to composer.
     *
     * @param string $local_release
     * @param string $remote_release
     *
     * @return void
     */
    private static function reportComposer($local_release, $remote_release)
    {
        $previous = self::extractVersions($local_release);
        $current = self::extractVersions($remote_release);
        $postData = ['downloads' => []];
        foreach ($current as $name => $version) {
            if (isset($previous[$name]) && $previous[$name] === $version) {
                continue;
            }
            $postData['downloads'][] = ['name' => $name, 'version' => $version];
        }
        if (\defined('HHVM_VERSION')) {
            $phpVersion = 'HHVM ' . HHVM_VERSION;
        } else {
            $phpVersion = 'PHP ' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
        }
        $opts = ['http' => ['method' => 'POST', 'header' => ['Content-Type: application/json', \sprintf('User-Agent: Composer/%s (%s; %s; %s; %s%s)', 'MProto v7', \function_exists('php_uname') ? @\php_uname('s') : 'Unknown', \function_exists('php_uname') ? @\php_uname('r') : 'Unknown', $phpVersion, 'streams', \getenv('CI') ? '; CI' : '')], 'content' => \json_encode($postData), 'timeout' => 6]];
        @\file_get_contents("https://packagist.org/downloads/", false, \stream_context_create($opts));
    }
    /**
     * Load phar file.
     *
     * @param (string | null) $release
     * @return mixed
     */
    private static function load($release)
    {
        if ($release === null) {
            throw new \Exception('Could not download MadelineProto, please check your internet connection and PHP configuration!');
        }
        $phar = "madeline-{$release}.phar";
        if (!self::$lock) {
            self::$lock = \fopen("{$phar}.lock", 'c');
        }
        \flock(self::$lock, LOCK_SH);
        $result = (require_once $phar);
        if (\defined('MADELINE_WORKER_TYPE') && \constant('MADELINE_WORKER_TYPE') === 'madeline-ipc') {
            require_once "phar://{$phar}/vendor/danog/madelineproto/src/danog/MadelineProto/Ipc/Runner/entry.php";
        }
        return $result;
    }
    /**
     * Unlock phar.
     *
     * @return void
     */
    public static function unlock()
    {
        \flock(self::$lock, LOCK_UN);
    }
    /**
     * Lock installer.
     *
     * @param string $version Version file to lock
     *
     * @return bool
     */
    private function lock($version)
    {
        if ($this->lockInstaller) {
            return true;
        }
        $this->lockInstaller = \fopen($version, 'w');
        return \flock($this->lockInstaller, LOCK_EX | LOCK_NB);
    }
    /**
     * Install MadelineProto.
     *
     * @return mixed
     */
    public function install()
    {
        $remote_release = \file_get_contents(MADELINE_RELEASE_URL) ?: null;
        $madeline_phar = "madeline-{$remote_release}.phar";
        $madeline_version = "madeline-{$this->version}.phar.version";
        if (\file_exists($madeline_version)) {
            $local_release = \file_get_contents($madeline_version) ?: null;
        } else {
            \touch($madeline_version);
            $local_release = null;
        }
        \define('HAD_MADELINE_PHAR', !!$local_release);
        if ($remote_release === $local_release && \file_exists($madeline_phar) || $remote_release === null) {
            return self::load($local_release);
        }
        if (!$this->lock($madeline_version)) {
            \flock($this->lockInstaller, LOCK_EX);
            return $this->install();
        }
        if (!\file_exists($madeline_phar)) {
            for ($x = 0; $x < 10; $x++) {
                $pharTest = \file_get_contents(\sprintf(self::PHAR_TEMPLATE, $this->version, $remote_release . $x));
                if ($pharTest && \strpos($pharTest, $remote_release) !== false) {
                    $phar = $pharTest;
                    unset($pharTest);
                    break;
                }
                \sleep(1);
            }
            if (!isset($phar)) {
                return self::load($local_release);
            }
            self::$lock = \fopen("{$madeline_phar}.lock", 'w');
            \flock(self::$lock, LOCK_EX);
            \file_put_contents($madeline_phar, $phar);
            unset($phar);
            self::reportComposer($local_release, $remote_release);
        }
        \fwrite($this->lockInstaller, $remote_release);
        \fflush($this->lockInstaller);
        return self::load($remote_release);
    }
}
return (new \danog\MadelineProto\Installer())->install();<?php

use danog\MadelineProto\Tools;
\chdir(__DIR__ . '/../');
require 'vendor/autoload.php';
$class = new \ReflectionClass(Tools::class);
$methods = $class->getMethods(ReflectionMethod::IS_STATIC | ReflectionMethod::IS_PUBLIC);
/**
 *
 */
function ssort($a, $b)
{
    return \strlen($b->getName()) - \strlen($a->getName());
}
\usort($methods, 'ssort');
$find = [];
$replace = [];
$findDocs = [];
$replaceDocs = [];
foreach ($methods as $methodObj) {
    $method = $methodObj->getName();
    $find[] = "\$this->{$method}(";
    $replace[] = "\\danog\\MadelineProto\\Tools::{$method}(";
}
foreach (new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator(\realpath('.'))), '/\\.php$/') as $filename) {
    $filename = (string) $filename;
    $new = \str_replace($find, $replace, $old = \file_get_contents($filename));
    do {
        \file_put_contents($filename, $new);
        $new = \str_replace($find, $replace, $old = \file_get_contents($filename));
    } while ($old !== $new);
}
exit;
foreach (new RegexIterator(new RecursiveIteratorIterator(new RecursiveDirectoryIterator(\realpath('docs'))), '/\\.md$/') as $filename) {
    $filename = (string) $filename;
    $new = \str_replace($findDocs, $replaceDocs, $old = \file_get_contents($filename));
    do {
        \file_put_contents($filename, $new);
        $new = \str_replace($findDocs, $replaceDocs, $old = \file_get_contents($filename));
    } while ($old !== $new);
}
$filename = 'README.md';
$new = \str_replace($findDocs, $replaceDocs, $old = \file_get_contents($filename));
do {
    \file_put_contents($filename, $new);
    $new = \str_replace($findDocs, $replaceDocs, $old = \file_get_contents($filename));
} while ($old !== $new);<?php

use danog\MadelineProto\AbstractAPIFactory;
use danog\MadelineProto\AnnotationsBuilder;
use danog\MadelineProto\APIFactory;
use danog\MadelineProto\APIWrapper;
use danog\MadelineProto\Async\AsyncConstruct;
use danog\MadelineProto\Bug74586Exception;
use danog\MadelineProto\Connection;
use danog\MadelineProto\DataCenter;
use danog\MadelineProto\DataCenterConnection;
use danog\MadelineProto\Db\DbPropertiesTrait;
use danog\MadelineProto\DocsBuilder;
use danog\MadelineProto\DoHConnector;
use danog\MadelineProto\GarbageCollector;
use danog\MadelineProto\InternalDoc;
use danog\MadelineProto\Lang;
use danog\MadelineProto\LightState;
use danog\MadelineProto\Magic;
use danog\MadelineProto\MTProtoTools\Crypt;
use danog\MadelineProto\MTProtoTools\MinDatabase;
use danog\MadelineProto\MTProtoTools\PasswordCalculator;
use danog\MadelineProto\MTProtoTools\ReferenceDatabase;
use danog\MadelineProto\MTProtoTools\UpdatesState;
use danog\MadelineProto\NothingInTheSocketException;
use danog\MadelineProto\RSA;
use danog\MadelineProto\Serialization;
use danog\MadelineProto\SessionPaths;
use danog\MadelineProto\SettingsAbstract;
use danog\MadelineProto\SettingsEmpty;
use danog\MadelineProto\Snitch;
use danog\MadelineProto\TL\TL;
use danog\MadelineProto\TL\TLCallback;
use danog\MadelineProto\TL\TLConstructors;
use danog\MadelineProto\TL\TLMethods;
use danog\MadelineProto\TON\ADNLConnection;
use danog\MadelineProto\TON\APIFactory as TONAPIFactory;
use danog\MadelineProto\TON\InternalDoc as TONInternalDoc;
use danog\MadelineProto\TON\Lite;
use danog\MadelineProto\VoIP;
use danog\PhpDoc\PhpDocBuilder;
require 'vendor/autoload.php';
$ignore = [
    // Disallow list
    AnnotationsBuilder::class,
    APIFactory::class,
    APIWrapper::class,
    AbstractAPIFactory::class,
    Bug74586Exception::class,
    Connection::class,
    ContextConnector::class,
    DataCenter::class,
    DataCenterConnection::class,
    DoHConnector::class,
    DocsBuilder::class,
    InternalDoc::class,
    Lang::class,
    LightState::class,
    Magic::class,
    PhpDocBuilder::class,
    RSA::class,
    Serialization::class,
    SessionPaths::class,
    SettingsEmpty::class,
    SettingsAbstract::class,
    Snitch::class,
    AsyncConstruct::class,
    VoIP::class,
    Crypt::class,
    NothingInTheSocketException::class,
    GarbageCollector::class,
    MinDatabase::class,
    PasswordCalculator::class,
    ReferenceDatabase::class,
    UpdatesState::class,
    TL::class,
    TLConstructors::class,
    TLMethods::class,
    TLCallback::class,
    ADNLConnection::class,
    TONAPIFactory::class,
    TONInternalDoc::class,
    Lite::class,
    \ArrayIterator::class,
];
$filter = function (string $class) use($ignore) : bool {
    if (\in_array($class, $ignore)) {
        return false;
    }
    if (\str_starts_with($class, 'danog\\MadelineProto\\Ipc') || \str_starts_with($class, 'danog\\MadelineProto\\Loop\\Update') || \str_starts_with($class, 'danog\\MadelineProto\\Loop\\Connection') || \str_starts_with($class, 'danog\\MadelineProto\\MTProto\\') || \str_starts_with($class, 'danog\\MadelineProto\\MTProtoSession\\') || \str_starts_with($class, 'danog\\MadelineProto\\PhpDoc\\') || \str_starts_with($class, 'danog\\MadelineProto\\Stream\\') || \str_starts_with($class, 'danog\\MadelineProto\\Db\\NullCache')) {
        return false;
    }
    if ($class === DbPropertiesTrait::class) {
        return true;
    }
    $class = new ReflectionClass($class);
    return !$class->isTrait();
};
PhpDocBuilder::fromNamespace()->setFilter($filter)->setOutput(__DIR__ . '/../docs/docs/PHP/')->setImage("https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png")->run();<?php

use danog\MadelineProto\Logger;
use danog\MadelineProto\Settings\Logger as SettingsLogger;
use danog\MadelineProto\Settings\TLSchema;
use danog\MadelineProto\TL\TL;
/*
Copyright 2016-2020 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
require 'vendor/autoload.php';
$logger = new Logger(new SettingsLogger());
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
if ($argc !== 3) {
    die("Usage: {$argv[0]} layernumberold layernumbernew\n");
}
/**
 * Get TL info of layer.
 *
 * @param int $layer Layer number
 *
 * @return void
 */
function getTL($layer)
{
    $layer = __DIR__ . "/../schemas/TL_telegram_v{$layer}.tl";
    $layer = new class($layer) extends TL
    {
        /**
         *
         */
        public function __construct($layer)
        {
            $API = new class
            {
            };
            $API->logger = Logger::$default;
            parent::__construct($API);
            $this->init((new TLSchema())->setAPISchema($layer));
        }
    };
    return ['methods' => $layer->getMethods(), 'constructors' => $layer->getConstructors()];
}
/**
 *
 */
function getUrl($constructor, $type)
{
    $changed = \str_replace('.', '_', $constructor);
    //return "[$constructor](https://github.com/danog/MadelineProtoDocs/blob/geochats/docs/API_docs/$type/$changed.md)";
    return "[{$constructor}](https://docs.madelineproto.xyz/API_docs/{$type}/{$changed}.html)";
}
$old = getTL($argv[1]);
$new = getTL($argv[2]);
$res = '';
foreach (['methods', 'constructors'] as $type) {
    $finder = $type === 'methods' ? 'findByMethod' : 'findByPredicate';
    $key = $type === 'methods' ? 'method' : 'predicate';
    // New constructors
    $res .= "\n\nNew " . \ucfirst($type) . "\n";
    foreach ($new[$type]->by_id as $constructor) {
        $name = $constructor[$key];
        if (!$old[$type]->{$finder}($name)) {
            $name = getUrl($name, $type);
            $res .= "Added {$name}\n";
        }
    }
    // Changed constructors
    $res .= "\n\nChanged " . \ucfirst($type) . "\n";
    foreach ($new[$type]->by_id as $constructor) {
        $name = $constructor[$key];
        if ($old[$type]->{$finder}($name)) {
            $new_args = $constructor['params'];
            $old_args = $old[$type]->{$finder}($name)['params'];
            $final_new_args = [];
            $final_old_args = [];
            foreach ($new_args as $arg) {
                $final_new_args[$arg['name']] = $arg['type'];
            }
            foreach ($old_args as $arg) {
                $final_old_args[$arg['name']] = $arg['type'];
            }
            $url = getUrl($name, $type);
            foreach ($final_new_args as $name => $ttype) {
                if (!isset($final_old_args[$name]) && $name !== 'flags') {
                    $res .= "Added {$name} param to {$url}\n";
                }
            }
            foreach ($final_old_args as $name => $ttype) {
                if (!isset($final_new_args[$name]) && $name !== 'flags') {
                    $res .= "Removed {$name} param from {$url}\n";
                }
            }
        }
    }
    // Deleted constructors
    $res .= "\n\nDeleted " . \ucfirst($type) . "\n";
    foreach ($old[$type]->by_id as $constructor) {
        $name = $constructor[$key];
        if (!$new[$type]->{$finder}($name)) {
            $res .= "Removed {$name}\n";
        }
    }
}
$bot = new \danog\MadelineProto\API('layer.madeline');
$bot->start();
foreach (\explode("\n\n", $res) as $chunk) {
    if (!$chunk) {
        continue;
    }
    $bot->messages->sendMessage(['peer' => 'danogentili', 'message' => $chunk, 'parse_mode' => 'markdown']);
}#!/usr/bin/env php
<?php 
/**
 * Copyright 2016-2020 Daniil Gentili
 * (https://daniil.it)
 * This file is part of MadelineProto.
 * MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with MadelineProto.
 * If not, see <http://www.gnu.org/licenses/>.
 */
use danog\MadelineProto\API;
use danog\MadelineProto\APIFactory;
use danog\MadelineProto\Logger;
use danog\MadelineProto\Magic;
use danog\MadelineProto\MTProto;
use danog\MadelineProto\Settings\Logger as SettingsLogger;
use danog\MadelineProto\TON\API as TONAPI;
use danog\MadelineProto\TON\APIFactory as TONAPIFactory;
use danog\MadelineProto\TON\Lite;
use danog\MadelineProto\Tools;
\chdir($d = __DIR__ . '/..');
require 'vendor/autoload.php';
Magic::start();
Logger::constructorFromSettings(new SettingsLogger());
$logger = Logger::$default;
\set_error_handler(['\\danog\\MadelineProto\\Exception', 'ExceptionErrorHandler']);
$logger->logger('Merging constructor localization...', Logger::NOTICE);
mergeExtracted();
$logger->logger('Loading schemas...', Logger::NOTICE);
$schemas = loadSchemas();
$logger->logger('Upgrading layer...', Logger::NOTICE);
$layer = maxLayer($schemas);
layerUpgrade($layer);
$logger->logger("Initing docs (layer {$layer})...", Logger::NOTICE);
$docs = [['tl_schema' => ['mtproto' => "{$d}/schemas/TL_mtproto_v1.tl", 'telegram' => '', 'secret' => ''], 'title' => 'MadelineProto API documentation (mtproto)', 'description' => 'MadelineProto API documentation (mtproto)', 'output_dir' => "{$d}/docs/docs/MTProto_docs", 'template' => "{$d}/docs/template", 'readme' => false], ['tl_schema' => ['mtproto' => '', 'telegram' => "{$d}/schemas/TL_telegram_v{$layer}.tl", 'secret' => "{$d}/schemas/TL_secret.tl", 'td' => "{$d}/schemas/TL_td.tl"], 'title' => "MadelineProto API documentation (layer {$layer})", 'description' => "MadelineProto API documentation (layer {$layer})", 'output_dir' => "{$d}/docs/docs/API_docs", 'template' => "{$d}/docs/template", 'readme' => false]];
$docs = \array_merge($docs, initDocs($schemas));
$logger->logger('Creating annotations...', Logger::NOTICE);
$doc = new \danog\MadelineProto\AnnotationsBuilder($logger, $docs[1], \dirname(__FILE__) . '/../src/danog/MadelineProto/InternalDoc.php', ['API' => API::class, 'APIFactory' => APIFactory::class, 'MTProto' => MTProto::class], 'danog\\MadelineProto');
$doc->mkAnnotations();
$doc = new \danog\MadelineProto\AnnotationsBuilder($logger, ['tl_schema' => ['telegram' => "{$d}/schemas/TON/lite_api.tl", 'mtproto' => "{$d}/schemas/TON/ton_api.tl"]], \dirname(__FILE__) . '/../src/danog/MadelineProto/TON/InternalDoc.php', ['API' => TONAPI::class, 'APIFactory' => TONAPIFactory::class, 'MTProto' => Lite::class], 'danog\\MadelineProto\\TON');
$doc->mkAnnotations();
$logger->logger('Creating docs...', Logger::NOTICE);
foreach ($docs as $settings) {
    $doc = new \danog\MadelineProto\DocsBuilder($logger, $settings);
    $doc->mkDocs();
}
\chdir(__DIR__ . '/..');
$logger->logger('Fixing readme...', Logger::NOTICE);
$orderedfiles = [];
$order = ['CREATING_A_CLIENT', 'LOGIN', 'FEATURES', 'REQUIREMENTS', 'INSTALLATION', 'UPDATES', 'DATABASE', 'SETTINGS', 'SELF', 'EXCEPTIONS', 'FLOOD_WAIT', 'LOGGING', 'CALLS', 'FILES', 'CHAT_INFO', 'DIALOGS', 'INLINE_BUTTONS', 'SECRET_CHATS', 'LUA', 'PROXY', 'ASYNC', 'USING_METHODS', 'CONTRIB', 'TEMPLATES'];
$index = '';
$files = \glob('docs/docs/docs/*md');
foreach ($files as $file) {
    $base = \basename($file, '.md');
    if ($base === 'UPDATES_INTERNAL') {
        continue;
    }
    $key = \array_search($base, $order);
    if ($key !== false) {
        $orderedfiles[$key] = $file;
    }
}
\ksort($orderedfiles);
foreach ($orderedfiles as $key => $filename) {
    $lines = \explode("\n", \file_get_contents($filename));
    while (\end($lines) === '' || \strpos(\end($lines), 'Next')) {
        unset($lines[\count($lines) - 1]);
    }
    if ($lines[0] === '---') {
        \array_shift($lines);
        while ($lines[0] !== '---') {
            \array_shift($lines);
        }
        \array_shift($lines);
    }
    \preg_match('|^# (.*)|', $lines[0], $matches);
    $title = $matches[1];
    $description = \str_replace('"', "'", Tools::toString($lines[2]));
    \array_unshift($lines, '---', 'title: "' . $title . '"', 'description: "' . $description . '"', 'image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png', '---');
    if (isset($orderedfiles[$key + 1])) {
        $nextfile = 'https://docs.madelineproto.xyz/docs/' . \basename($orderedfiles[$key + 1], '.md') . '.html';
        $prevfile = $key === 0 ? 'https://docs.madelineproto.xyz' : 'https://docs.madelineproto.xyz/docs/' . \basename($orderedfiles[$key - 1], '.md') . '.html';
        $lines[\count($lines)] = "\n<a href=\"{$nextfile}\">Next section</a>";
    } else {
        $lines[\count($lines)] = "\n<a href=\"https://docs.madelineproto.xyz/#very-complex-and-complete-examples\">Next section</a>";
    }
    \file_put_contents($filename, \implode("\n", $lines));
    $file = \file_get_contents($filename);
    \preg_match_all('|( *)\\* \\[(.*)\\]\\((.*)\\)|', $file, $matches);
    $file = 'https://docs.madelineproto.xyz/docs/' . \basename($filename, '.md') . '.html';
    $index .= "* [{$title}]({$file})\n";
    if (\basename($filename) !== 'FEATURES.md') {
        foreach ($matches[1] as $key => $match) {
            $spaces = "  {$match}";
            $name = $matches[2][$key];
            if ($matches[3][$key][0] === '#') {
                $url = $file . $matches[3][$key];
            } elseif (\Phabel\Target\Php80\Polyfill::substr($matches[3][$key], 0, 3) === '../') {
                $url = 'https://docs.madelineproto.xyz/' . \str_replace('.md', '.html', \Phabel\Target\Php80\Polyfill::substr($matches[3][$key], 3));
            } else {
                $url = $matches[3][$key];
            }
            $index .= "{$spaces}* [{$name}]({$url})\n";
            if ($name === 'FULL API Documentation with descriptions') {
                $spaces .= '  ';
                \preg_match_all('|\\* (.*)|', \file_get_contents('docs/docs/API_docs/methods/index.md'), $smatches);
                foreach ($smatches[1] as $key => $match) {
                    $match = \str_replace('href="', 'href="https://docs.madelineproto.xyz/API_docs/methods/', $match);
                    $index .= "{$spaces}* " . $match . "\n";
                }
            }
        }
    }
}
$logger->logger('Fixing readme...', Logger::NOTICE);
$readme = \explode('## ', \file_get_contents('README.md'));
foreach ($readme as &$section) {
    if (\explode("\n", $section)[0] === 'Documentation') {
        $section = "Documentation\n\n" . $index . "\n";
    }
}
$readme = \implode('## ', $readme);
\file_put_contents('README.md', $readme);
\file_put_contents('docs/docs/index.md', '---
title: MadelineProto documentation
description: PHP client/server for the telegram MTProto protocol (a better tg-cli)
image: https://docs.madelineproto.xyz/favicons/android-chrome-256x256.png
---
' . $readme);<?php

/**
 * Upgrade layer number.
 *
 * @param integer $layer Layer number
 *
 * @return void
 */
function layerUpgrade(int $layer) : void
{
    $doc = \file_get_contents('docs/docs/docs/USING_METHODS.md');
    $doc = \preg_replace('|here \\(layer \\d+\\)|', "here (layer {$layer})", $doc);
    \file_put_contents('docs/docs/docs/USING_METHODS.md', $doc);
    \array_map(unlink::class, \glob('src/danog/MadelineProto/*.tl'));
    foreach (['TL_mtproto_v1', "TL_telegram_v{$layer}", 'TL_secret', 'TL_botAPI'] as $schema) {
        \copy("schemas/{$schema}.tl", "src/danog/MadelineProto/{$schema}.tl");
    }
    $doc = \file_get_contents('src/danog/MadelineProto/Settings/TLSchema.php');
    \preg_match("/layer = (\\d+)/", $doc, $matches);
    $prevLayer = (int) $matches[1];
    if ($prevLayer === $layer) {
        return;
    }
    $doc = \str_replace(["layer = {$prevLayer}", "TL_telegram_v{$prevLayer}"], ["layer = {$layer}", "TL_telegram_v{$layer}"], $doc);
    \file_put_contents('src/danog/MadelineProto/Settings/TLSchema.php', $doc);
}<?php

/**
 * Load schema file names.
 *
 * @return array
 */
function loadSchemas() : array
{
    $res = [];
    foreach (\glob(\getcwd() . '/schemas/TL_telegram_*') as $file) {
        \preg_match("/telegram_v(\\d+)/", $file, $matches);
        $res[$matches[1]] = $file;
    }
    \ksort($res);
    return $res;
}
/**
 * Return max available layer number.
 *
 * @param array $schemas Scheme array
 *
 * @return integer
 */
function maxLayer(array $schemas) : int
{
    $schemas = \array_keys($schemas);
    return \end($schemas);
}
/**
 * Init docs.
 *
 * @param array $layers Scheme array
 *
 * @return array Documentation information for old docs
 */
function initDocs(array $layers) : array
{
    return [];
}<?php

use danog\MadelineProto\Lang;
/**
 * Merge extracted docs.
 *
 * @return void
 */
function mergeExtracted() : void
{
    if (!\file_exists('extracted.json')) {
        return;
    }
    foreach (\json_decode(\file_get_contents('extracted.json'), true) as $key => $value) {
        $key = \preg_replace(['|flags\\.\\d+[?]|', '/Vector[<].*/'], ['', 'Vector t'], $key);
        $key = \str_replace('param_hash_type_int', 'param_hash_type_Vector t', $key);
        Lang::$lang['en'][$key] = $value;
    }
    foreach (Lang::$lang['en'] as $key => $value) {
        if ($value === '') {
            unset(Lang::$lang['en'][$key]);
        }
    }
    foreach (\json_decode(\file_get_contents('docs/template/disallow.json'), true) as $key => $value) {
        Lang::$lang['en'][$key] = $value;
    }
}<?php

$not_subbing = [];
foreach (\explode("\n", \shell_exec("find src -type f -name '*.php'")) as $file) {
    if (!$file) {
        continue;
    }
    if (\in_array(\basename($file, '.php'), ['APIFactory', 'API', 'Connection', 'Coroutine', 'ReferenceDatabase', 'ProxySocketPool'])) {
        continue;
    }
    if (\strpos($file, 'Loop/')) {
        continue;
    }
    if (\strpos($file, 'Stream/')) {
        continue;
    }
    if (\strpos($file, 'Server/')) {
        continue;
    }
    if (\strpos($file, 'Async/')) {
        continue;
    }
    $to_sub = [];
    $last_match = null;
    foreach (\explode("\n", $filec = \file_get_contents($file)) as $number => $line) {
        if (\preg_match("/public function (\\w*)[(]/", $line, $matches)) {
            $last_match = \stripos($matches[1], 'async') === false ? $matches[1] : null;
        }
        if (\preg_match('/function [(]/', $line) && \stripos($line, 'public function') === false) {
            $last_match = 0;
        }
        if (\strpos($line, 'yield') !== false) {
            if ($last_match) {
                echo "subbing {$last_match} for {$line} at {$number} in {$file}" . PHP_EOL;
                $to_sub[] = $last_match;
            } elseif ($last_match === 0) {
                echo "============\nNOT SUBBING {$last_match} for {$line} at {$number} in {$file}\n============" . PHP_EOL;
                $not_subbing[$file] = $file;
            }
        }
    }
    $input = [];
    $output = [];
    foreach ($to_sub as $func) {
        $input[] = "public function {$func}(";
        $output[] = "public function {$func}" . '_async(';
    }
    if ($input) {
        \file_put_contents($file, \str_replace($input, $output, $filec));
    }
}
\var_dump(\array_values($not_subbing));{
    "liteservers": [
      {
        "ip": 1137658550,
        "port": 4924,
        "id": {
          "@type": "pub.ed25519",
          "key": "peJTw/arlRfssgTuf9BMypJzqOi7SXEqSPSWiEw2U1M="
        }
      }
    ],
    "validator": {
      "@type": "validator.config.global",
      "zero_state": {
        "workchain": -1,
        "shard": -9223372036854775808,
        "seqno": 0,
        "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=",
        "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24="
      }
    }
  }
  {
  "liteservers": [
     {
      "ip": 861606190,
      "port": 9999,
       "id": {
         "@type": "pub.ed25519",
        "key": "T10NJq2tgx6LpTHj734fSNYJ6S2w1hTdFRXJaj5st80"
       }
     }
  ],
  "validator": {
    "@type": "validator.config.global",
    "zero_state": {
      "workchain": -1,
      "shard": -9223372036854775808,
      "seqno": 0,
      "root_hash": "F6OpKZKqvqeFp6CQmFomXNMfMj2EnaUSOXN+Mh+wVWk=",
      "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24="
    }
  }
}
<?php

use danog\MadelineProto\Settings\Logger as SettingsLogger;
use danog\MadelineProto\TON\API;
require 'vendor/autoload.php';
$API = new API(new SettingsLogger());
$API->async(true);
$API->loop(function () use($API) {
    (yield $API->connect(__DIR__ . '/ton-lite-client-test1.config.json'));
    $API->logger((yield $API->liteServer->getTime()));
});{
    "name": "danog/madelineproto",
    "description": "PHP implementation of telegram's MTProto protocol.",
    "type": "project",
    "license": "AGPL-3.0-only",
    "homepage": "https://docs.madelineproto.xyz",
    "keywords": [
        "telegram",
        "mtproto",
        "protocol",
        "bytes",
        "messenger",
        "client",
        "PHP",
        "video",
        "stickers",
        "audio",
        "files",
        "GB"
    ],
    "conflict": {
        "krakjoe/pthreads-polyfill": "*",
        "ext-pthreads": "*"
    },
    "require": {
        "phabel/phabel": "^1.0",
        "php": "*",
        "ext-mbstring": "*",
        "ext-json": "*",
        "ext-xml": "*",
        "ext-dom": "*",
        "ext-filter": "*",
        "ext-hash": "*",
        "ext-zlib": "*",
        "ext-fileinfo": "*"
    },
    "require-dev": {
        "phpdocumentor/reflection-docblock": "^5.2",
        "ext-ctype": "*",
        "danog/phpdoc": "^0.1.7",
        "phpunit/phpunit": "^9",
        "phabel/phabel": "^1",
        "bamarni/composer-bin-plugin": "^1.4",
        "roave/security-advisories": "dev-latest",
        "symfony/yaml": "^6.0"
    },
    "suggest": {
        "ext-libtgvoip": "Install the php-libtgvoip extension to make phone calls (https://github.com/danog/php-libtgvoip)",
        "ext-pdo": "Install pdo extension to support database used as cache",
        "ext-openssl": "Install the openssl extension for faster crypto",
        "ext-gmp": "Install the gmp extension for faster crypto"
    },
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "autoload": {
        "psr-4": {
            "danog\\MadelineProto\\": "src/danog/MadelineProto"
        },
        "files": [
            "src/BigIntegor.php",
            "src/YieldReturnValue.php",
            "src/polyfill.php",
            "___transpiledWithPhabel.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "danog\\MadelineProto\\Test\\": "tests/danog/"
        },
        "files": [
            "tools/build_docs/schemas.php",
            "tools/build_docs/merge.php",
            "tools/build_docs/layerUpgrade.php"
        ]
    },
    "scripts": {
        "build": [
            "@docs",
            "@phpdoc",
            "@cs-fix",
            "@psalm"
        ],
        "phpdoc": [
            "@phpdocInternal",
            "@phpdocMain"
        ],
        "check": [
            "@cs",
            "@test"
        ],
        "test-php7": "tests/test-conversion.sh 70",
        "test-php56": "tests/test-conversion.sh 5",
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "psalm": "psalm",
        "phpdocMain": "php tools/phpdoc.php",
        "docs": "php tools/build_docs.php",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text --config tests/phpunit.xml",
        "bin": "echo 'bin not installed'",
        "post-install-cmd": [
            "@composer bin all install --ansi"
        ],
        "post-update-cmd": [
            "@composer bin all update --ansi"
        ]
    },
    "extra": {
        "phabel": {
            "revision": 0,
            "require": {
                "danog/primemodule": "^1",
                "erusev/parsedown": "^1.7",
                "symfony/polyfill-mbstring": "*",
                "amphp/amp": "^2",
                "amphp/http-client": "^4",
                "amphp/socket": "^1",
                "amphp/dns": "^1",
                "amphp/byte-stream": "^1",
                "amphp/file": "^2",
                "amphp/mysql": "^2",
                "amphp/postgres": "^1.2",
                "danog/dns-over-https": "^0.2",
                "amphp/http-client-cookies": "^1",
                "danog/tg-file-decoder": "^0.1",
                "danog/magicalserializer": "^1.0",
                "league/uri": "^6",
                "danog/ipc": "^0.1",
                "amphp/log": "^1.1",
                "danog/loop": "^0.1.0",
                "phpseclib/phpseclib": "^3",
                "amphp/redis": "^1.0",
                "symfony/polyfill-php80": "^1.18",
                "amphp/websocket-client": "^1.0",
                "psr/http-factory": "^1.0",
                "psr/log": "^1"
            }
        }
    }
}<?php

require 'vendor/autoload.php';
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use function Amp\asyncCall;
use function Amp\Ipc\listen;
Loop::run(static function () {
    $clientHandler = function (ChannelledSocket $socket) {
        echo "Accepted connection" . PHP_EOL;
        while ($payload = (yield $socket->receive())) {
            echo "Received {$payload}" . PHP_EOL;
            if ($payload === 'ping') {
                (yield $socket->send('pong'));
                (yield $socket->disconnect());
            }
        }
        echo "Closed connection" . PHP_EOL . "==========" . PHP_EOL;
    };
    $server = listen(\sys_get_temp_dir() . '/test');
    while ($socket = (yield $server->accept())) {
        asyncCall($clientHandler, $socket);
    }
});<?php

require 'vendor/autoload.php';
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use function Amp\asyncCall;
use function Amp\Ipc\connect;
Loop::run(static function () {
    $clientHandler = function (ChannelledSocket $socket) {
        echo "Created connection." . PHP_EOL;
        while ($payload = (yield $socket->receive())) {
            echo "Received {$payload}" . PHP_EOL;
        }
        echo "Closed connection" . PHP_EOL;
    };
    $channel = (yield connect(\sys_get_temp_dir() . '/test'));
    asyncCall($clientHandler, $channel);
    (yield $channel->send('ping'));
});{
    "name": "danog/ipc",
    "description": "IPC component for Amp.",
    "keywords": [
        "asynchronous",
        "async",
        "concurrent",
        "multi-threading",
        "multi-processing"
    ],
    "homepage": "https://github.com/danog/ipc",
    "license": "MIT",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Stephen Coakley",
            "email": "me@stephencoakley.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/byte-stream": "^1",
        "amphp/parser": "^1"
    },
    "require-dev": {
        "amphp/amp": "^2.4",
        "amphp/parallel": "^1.3",
        "phpunit/phpunit": "^7 | ^8 | ^9",
        "amphp/phpunit-util": "^1.3",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Ipc\\": "lib"
        },
        "files": [
            "lib/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Ipc\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Ipc\Sync;

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class ChannelledSocket implements Channel
{
    private const ESTABLISHED = 0;
    private const GOT_FIN_MASK = 1;
    private const GOT_ACK_MASK = 2;
    private const GOT_ALL_MASK = 3;
    /** @var ChannelledStream */
    private $channel;
    /** @var ResourceInputStream */
    private $read;
    /** @var ResourceOutputStream */
    private $write;
    /** @var bool */
    private $closed = false;
    /** @var int */
    private $state = self::ESTABLISHED;
    /** @var Deferred */
    private $closePromise;
    /** @var bool */
    private $reading = false;
    /**
     * @param resource $read Readable stream resource.
     * @param resource $write Writable stream resource.
     *
     * @throws \Error If a stream resource is not given for $resource.
     */
    public function __construct($read, $write)
    {
        $this->channel = new ChannelledStream($this->read = new ResourceInputStream($read), $this->write = new ResourceOutputStream($write));
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->closed) {
            return new Success();
        }
        return call(function () : \Generator {
            $this->reading = true;
            $data = (yield $this->channel->receive());
            $this->reading = false;
            if ($data instanceof ChannelCloseReq) {
                (yield $this->channel->send(new ChannelCloseAck()));
                $this->state = self::GOT_FIN_MASK;
                (yield $this->disconnect());
                if ($this->closePromise) {
                    $this->closePromise->resolve($data);
                }
                return null;
            } elseif ($data instanceof ChannelCloseAck) {
                $this->closePromise->resolve($data);
                return null;
            }
            return $data;
        });
    }
    /**
     * Cleanly disconnect from other endpoint.
     *
     * @return Promise
     */
    public function disconnect() : Promise
    {
        if ($this->closed) {
            return new Success();
        }
        return call(function () : \Generator {
            if ($this->reading) {
                $this->closePromise = new Deferred();
            }
            (yield $this->channel->send(new ChannelCloseReq()));
            do {
                $data = (yield $this->closePromise ? $this->closePromise->promise() : $this->channel->receive());
                if ($this->closePromise) {
                    $this->closePromise = null;
                }
                if ($data instanceof ChannelCloseReq) {
                    (yield $this->channel->send(new ChannelCloseAck()));
                    $this->state |= self::GOT_FIN_MASK;
                } elseif ($data instanceof ChannelCloseAck) {
                    $this->state |= self::GOT_ACK_MASK;
                }
            } while ($this->state !== self::GOT_ALL_MASK);
            $this->closed = true;
            $this->close();
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->closed) {
            throw new ChannelException('The channel was already closed!');
        }
        return $this->channel->send($data);
    }
    /**
     * {@inheritdoc}
     */
    public function unreference()
    {
        $this->read->unreference();
    }
    /**
     * {@inheritdoc}
     */
    public function reference()
    {
        $this->read->reference();
    }
    /**
     * Closes the read and write resource streams.
     */
    private function close()
    {
        $this->read->close();
        $this->write->close();
    }
}<?php

namespace Amp\Ipc\Sync;

class ChannelException extends \Exception
{
}<?php

namespace Amp\Ipc\Sync;

use Amp\Promise;
/**
 * A parcel object for sharing data across execution contexts.
 *
 * A parcel is an object that stores a value in a safe way that can be shared
 * between different threads or processes. Different handles to the same parcel
 * will access the same data, and a parcel handle itself is serializable and
 * can be transported to other execution contexts.
 *
 * Wrapping and unwrapping values in the parcel are not atomic. To prevent race
 * conditions and guarantee safety, you should use the provided synchronization
 * methods to acquire a lock for exclusive access to the parcel first before
 * accessing the contained value.
 */
interface Parcel
{
    /**
    * Asynchronously invokes a callback while maintaining an exclusive lock on the parcel. The current value of the
    parcel is provided as the first argument to the callback function.
    *
    * @param callable $callback The synchronized callback to invoke. The parcel value is given as the single argument
    to the callback function. The callback may be a regular function or a coroutine.
    *
    * @return \Amp\Promise<mixed> Resolves with the return value of $callback or fails if $callback
    throws an exception.
    */
    public function synchronized(callable $callback) : Promise;
    /**
     * @return \Amp\Promise<mixed> A promise for the value inside the parcel.
     */
    public function unwrap() : Promise;
}<?php

namespace Amp\Ipc\Sync;

final class ChannelCloseReq implements ChannelCloseMsg
{
}<?php

namespace Amp\Ipc\Sync;

interface ChannelCloseMsg
{
}<?php

namespace Amp\Ipc\Sync;

class SynchronizationError extends \Error
{
}<?php

namespace Amp\Ipc\Sync;

final class ChannelCloseAck implements ChannelCloseMsg
{
}<?php

namespace Amp\Ipc\Sync;

use Amp\Promise;
/**
 * Interface for sending messages between execution contexts.
 */
interface Channel
{
    /**
    * @return \Amp\Promise<mixed>
    *
    * @throws \Amp\Ipc\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Ipc\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Ipc\Sync\ChannelException If receiving from the channel fails.
    * @throws \Amp\Ipc\Sync\SerializationException If unserializing the data fails.
    */
    public function receive() : Promise;
    /**
    * @param mixed $data
    *
    * @return \Amp\Promise<int> Resolves with the number of bytes sent on the channel.
    *
    * @throws \Amp\Ipc\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Ipc\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Ipc\Sync\ChannelException If sending on the channel fails.
    * @throws \Error If an ExitResult object is given.
    * @throws \Amp\Ipc\Sync\SerializationException If serializing the data fails.
    */
    public function send($data) : Promise;
}<?php

namespace Amp\Ipc\Sync;

final class PanicError extends \Error
{
    /** @var string Class name of uncaught exception. */
    private $name;
    /** @var string Stack trace of the panic. */
    private $trace;
    /**
     * Creates a new panic error.
     *
     * @param string $name The uncaught exception class.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', \Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * Returns the class name of the uncaught exception.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * Gets the stack trace at the point the panic occurred.
     *
     * @return string
     */
    public function getPanicTrace() : string
    {
        return $this->trace;
    }
}<?php

namespace Amp\Ipc\Sync;

use Amp\Parser\Parser;
final class ChannelParser extends Parser
{
    const HEADER_LENGTH = 5;
    /**
     * @param callable(mixed $data) Callback invoked when data is parsed.
     */
    public function __construct(callable $callback)
    {
        parent::__construct(self::parser($callback));
    }
    /**
     * @param mixed $data Data to encode to send over a channel.
     *
     * @return string Encoded data that can be parsed by this class.
     *
     * @throws \Amp\Ipc\Sync\SerializationException
     */
    public function encode($data) : string
    {
        try {
            $data = \serialize($data);
        } catch (\Throwable $exception) {
            throw new SerializationException("The given data cannot be sent because it is not serializable.", 0, $exception);
        }
        return \pack("CL", 0, \strlen($data)) . $data;
    }
    /**
     * @param callable $push
     *
     * @return \Generator
     *
     * @throws \Amp\Ipc\Sync\ChannelException
     * @throws \Amp\Ipc\Sync\SerializationException
     */
    private static function parser(callable $push) : \Generator
    {
        while (true) {
            $header = (yield self::HEADER_LENGTH);
            $data = \unpack("Cprefix/Llength", $header);
            if ($data["prefix"] !== 0) {
                $data = $header . yield;
                throw new ChannelException("Invalid packet received: " . self::encodeUnprintableChars($data));
            }
            $data = (yield $data["length"]);
            // Attempt to unserialize the received data.
            try {
                $result = \unserialize($data);
                if ($result === false && $data !== \serialize(false)) {
                    throw new ChannelException("Received invalid data: " . self::encodeUnprintableChars($data));
                }
            } catch (\Throwable $exception) {
                throw new SerializationException("Exception thrown when unserializing data", 0, $exception);
            }
            $push($result);
        }
    }
    /**
     * @param string $data Binary data.
     *
     * @return string Unprintable characters encoded as \x##.
     */
    private static function encodeUnprintableChars(string $data) : string
    {
        return \preg_replace_callback("/[^ -~]/", function (array $matches) {
            return "\\x" . \dechex(\ord($matches[0]));
        }, $data);
    }
}<?php

namespace Amp\Ipc\Sync;

class SerializationException extends \Exception
{
}<?php

namespace Amp\Ipc\Sync;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
use Amp\ByteStream\StreamException;
use Amp\Promise;
use function Amp\call;
/**
 * An asynchronous channel for sending data between threads and processes.
 *
 * Supports full duplex read and write.
 */
final class ChannelledStream implements Channel
{
    /** @var \Amp\ByteStream\InputStream */
    private $read;
    /** @var \Amp\ByteStream\OutputStream */
    private $write;
    /** @var \SplQueue */
    private $received;
    /** @var \Amp\Parser\Parser */
    private $parser;
    /**
     * Creates a new channel from the given stream objects. Note that $read and $write can be the same object.
     *
     * @param \Amp\ByteStream\InputStream $read
     * @param \Amp\ByteStream\OutputStream $write
     */
    public function __construct(InputStream $read, OutputStream $write)
    {
        $this->read = $read;
        $this->write = $write;
        $this->received = new \SplQueue();
        $this->parser = new ChannelParser([$this->received, 'push']);
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        return call(function () use($data) {
            try {
                return (yield $this->write->write($this->parser->encode($data)));
            } catch (StreamException $exception) {
                throw new ChannelException("Sending on the channel failed. Did the context die?", 0, $exception);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        return call(function () {
            while ($this->received->isEmpty()) {
                try {
                    $chunk = (yield $this->read->read());
                } catch (StreamException $exception) {
                    throw new ChannelException("Reading from the channel failed. Did the context die?", 0, $exception);
                }
                if ($chunk === null) {
                    throw new ChannelException("The channel closed unexpectedly. Did the context die?");
                }
                $this->parser->push($chunk);
            }
            return $this->received->shift();
        });
    }
}<?php

namespace Amp\Ipc;

use Amp\Deferred;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
class IpcServer
{
    public const TYPE_AUTO = 0;
    public const TYPE_UNIX = 1 << 0;
    public const TYPE_FIFO = 1 << 1;
    public const TYPE_TCP = 1 << 2;
    /** @var resource|null */
    private $server;
    /** @var Deferred */
    private $acceptor;
    /** @var string|null */
    private $watcher;
    /** @var string|null */
    private $uri;
    /**
     * @param string $uri Local endpoint on which to listen for requests
     * @param self::TYPE_* $type Server type
     */
    public function __construct(string $uri = '', int $type = self::TYPE_AUTO)
    {
        if (!$uri) {
            $suffix = \bin2hex(\random_bytes(10));
            $uri = \sys_get_temp_dir() . "/amp-ipc-" . $suffix . ".sock";
        }
        if (\file_exists($uri)) {
            @\unlink($uri);
        }
        $this->uri = $uri;
        $isWindows = \strncasecmp(\PHP_OS, "WIN", 3) === 0;
        if ($isWindows) {
            if ($type === self::TYPE_AUTO || $type === self::TYPE_TCP) {
                $types = [self::TYPE_TCP];
            } else {
                throw new \RuntimeException("Cannot use FIFOs and UNIX sockets on windows");
            }
        } elseif ($type === self::TYPE_AUTO) {
            $types = [];
            if (\strlen($uri) <= 104) {
                $types[] = self::TYPE_UNIX;
            }
            $types[] = self::TYPE_FIFO;
            $types[] = self::TYPE_TCP;
        } else {
            $types = [];
            if ($type & self::TYPE_UNIX && \strlen($uri) <= 104) {
                $types[] = self::TYPE_UNIX;
            }
            if ($type & self::TYPE_TCP) {
                $types[] = self::TYPE_TCP;
            }
            if ($type & self::TYPE_FIFO) {
                $types[] = self::TYPE_FIFO;
            }
        }
        $errors = [];
        foreach ($types as $type) {
            if ($type === self::TYPE_FIFO) {
                try {
                    if (!\posix_mkfifo($uri, 0777)) {
                        $errors[$type] = "could not create the FIFO socket";
                        continue;
                    }
                } catch (\Throwable $e) {
                    $errors[$type] = "could not create the FIFO socket: {$e}";
                    continue;
                }
                $error = '';
                try {
                    // Open in r+w mode to prevent blocking if there is no reader
                    $this->server = \fopen($uri, 'r+');
                } catch (\Throwable $e) {
                    $error = "{$e}";
                }
                if ($this->server) {
                    \stream_set_blocking($this->server, false);
                    break;
                }
                $errors[$type] = "could not connect to the FIFO socket: {$error}";
            } else {
                $listenUri = $type === self::TYPE_TCP ? "tcp://127.0.0.1:0" : "unix://" . $uri;
                $errno = -1;
                $errstr = 'no error';
                try {
                    $this->server = \stream_socket_server($listenUri, $errno, $errstr, \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN);
                } catch (\Throwable $e) {
                    $errstr = "exception: {$e}";
                }
                if ($this->server) {
                    if ($type === self::TYPE_TCP) {
                        try {
                            $name = \stream_socket_get_name($this->server, false);
                            $port = \Phabel\Target\Php80\Polyfill::substr($name, \strrpos($name, ":") + 1);
                            if (!\file_put_contents($this->uri, "tcp://127.0.0.1:" . $port)) {
                                $errors[$type] = 'could not create URI file';
                                $this->server = null;
                            }
                        } catch (\Throwable $e) {
                            $errors[$type] = "could not create URI file: {$e}";
                            $this->server = null;
                        }
                        if (!$this->server) {
                            continue;
                        }
                    }
                    break;
                }
                $errors[$type] = "(errno: {$errno}) {$errstr}";
            }
        }
        if (!$this->server) {
            throw new IpcServerException($errors);
        }
        $acceptor =& $this->acceptor;
        $this->watcher = Loop::onReadable($this->server, static function (string $watcher, $server) use(&$acceptor, $type) : void {
            if ($type === self::TYPE_FIFO) {
                $length = \unpack('v', \fread($server, 2))[1];
                if (!$length) {
                    return;
                    // Could not accept, wrong length read
                }
                $prefix = \fread($server, $length);
                $sockets = [$prefix . '1', $prefix . '2'];
                foreach ($sockets as $k => &$socket) {
                    if (@\filetype($socket) !== 'fifo') {
                        if ($k) {
                            \fclose($sockets[0]);
                        }
                        return;
                        // Is not a FIFO
                    }
                    // Open in either read or write mode to send a close signal when done
                    if (!($socket = \fopen($socket, $k ? 'w' : 'r'))) {
                        if ($k) {
                            \fclose($sockets[0]);
                        }
                        return;
                        // Could not open fifo
                    }
                }
                $channel = new ChannelledSocket(...$sockets);
            } else {
                // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
                if (!($client = @\stream_socket_accept($server, 0))) {
                    // Timeout of 0 to be non-blocking.
                    return;
                    // Accepting client failed.
                }
                $channel = new ChannelledSocket($client, $client);
            }
            $deferred = $acceptor;
            $acceptor = null;
            \assert($deferred !== null);
            $deferred->resolve($channel);
            if (!$acceptor) {
                Loop::disable($watcher);
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     * @return Promise<(ChannelledSocket | null)>
     *
     * @throws PendingAcceptError If another accept request is pending.
     */
    public function accept() : Promise
    {
        if ($this->acceptor) {
            throw new PendingAcceptError();
        }
        if (!$this->server) {
            return new Success();
            // Resolve with null when server is closed.
        }
        $this->acceptor = new Deferred();
        Loop::enable($this->watcher);
        return $this->acceptor->promise();
    }
    /**
     * Closes the server and stops accepting connections. Any socket clients accepted will not be closed.
     */
    public function close() : void
    {
        Loop::cancel($this->watcher);
        if ($this->acceptor) {
            $acceptor = $this->acceptor;
            $this->acceptor = null;
            $acceptor->resolve();
        }
        if ($this->server) {
            \fclose($this->server);
            $this->server = null;
        }
        if ($this->uri !== null) {
            @\unlink($this->uri);
            $this->uri = null;
        }
    }
    /**
     * @return bool
     */
    public function isClosed() : bool
    {
        return $this->server === null;
    }
    /**
     * References the accept watcher.
     *
     * @see Loop::reference()
     */
    public final function reference() : void
    {
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the accept watcher.
     *
     * @see Loop::unreference()
     */
    public final function unreference() : void
    {
        Loop::unreference($this->watcher);
    }
    /**
     * Get endpoint to which clients should connect.
     *
     * @return string
     */
    public function getUri() : string
    {
        return $this->uri;
    }
}<?php

namespace Amp\Ipc;

/**
 * Thrown in case server connection fails.
 */
final class IpcServerException extends \Exception
{
    private const TYPE_MAP = [IpcServer::TYPE_UNIX => 'UNIX', IpcServer::TYPE_TCP => 'TCP', IpcServer::TYPE_FIFO => 'FIFO'];
    /**
     *
     */
    public function __construct(array $messages, int $code = 0, \Throwable $previous = null)
    {
        $message = "Could not create IPC server: ";
        foreach ($messages as $type => $error) {
            $message .= self::TYPE_MAP[$type] . ": {$error}; ";
        }
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Ipc;

/**
 * Thrown in case a second read operation is attempted while another read operation is still pending.
 */
final class PendingAcceptError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = 'The previous accept operation must complete before accept can be called again', int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Ipc;

use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Promise;
use function Amp\call;
/**
 * Create IPC server.
 *
 * @param string $uri Local endpoint on which to listen for requests
 *
 * @return IpcServer
 */
function listen(string $uri) : IpcServer
{
    return new IpcServer($uri);
}
/**
 * Connect to IPC server.
 *
 * @param string $uri URI
 *
 * @return Promise<ChannelledSocket>
 */
function connect(string $uri) : Promise
{
    return call(static function () use($uri) {
        if (!\file_exists($uri)) {
            throw new \RuntimeException("The endpoint does not exist!");
        }
        $type = \filetype($uri);
        if ($type !== 'fifo') {
            if ($type === 'file') {
                $uri = \file_get_contents($uri);
            } else {
                $uri = "unix://{$uri}";
            }
            if (!($socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT))) {
                $message = "Could not connect to IPC socket";
                if ($error = \error_get_last()) {
                    $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
                }
                throw new \RuntimeException($message);
            }
            return new ChannelledSocket($socket, $socket);
        }
        $suffix = \bin2hex(\random_bytes(10));
        $prefix = \sys_get_temp_dir() . "/amp-" . $suffix . ".fifo";
        if (\strlen($prefix) > 0xffff) {
            throw new \RuntimeException('Prefix is too long!');
        }
        $sockets = [$prefix . "2", $prefix . "1"];
        foreach ($sockets as $k => &$socket) {
            if (!\posix_mkfifo($socket, 0777)) {
                throw new \RuntimeException('Could not create FIFO client socket!');
            }
            \register_shutdown_function(static function () use($socket) : void {
                @\unlink($socket);
            });
            if (!($socket = \fopen($socket, 'r+'))) {
                // Open in r+w mode to prevent blocking if there is no reader
                throw new \RuntimeException("Could not open FIFO client socket");
            }
        }
        if (!($tempSocket = \fopen($uri, 'r+'))) {
            // Open in r+w mode to prevent blocking if there is no reader
            throw new \RuntimeException("Could not connect to FIFO server");
        }
        \stream_set_blocking($tempSocket, false);
        \stream_set_write_buffer($tempSocket, 0);
        if (!\fwrite($tempSocket, \pack('v', \strlen($prefix)) . $prefix)) {
            \fclose($tempSocket);
            $tempSocket = null;
            throw new \RuntimeException("Failure sending request to FIFO server");
        }
        \fclose($tempSocket);
        $tempSocket = null;
        return new ChannelledSocket(...$sockets);
    });
}<?php

namespace Amp\Ipc\Test;

use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Parallel\Context\Process;
use Amp\PHPUnit\AsyncTestCase;
use function Amp\asyncCall;
use function Amp\Ipc\connect;
class IpcTest extends AsyncTestCase
{
    /**
     * @dataProvider provideUriType
     */
    public function testBasicIPC(string $uri, int $type)
    {
        $process = new Process([__DIR__ . '/Fixtures/server.php', $uri, $type]);
        (yield $process->start());
        $recvUri = (yield $process->receive());
        if ($uri) {
            $this->assertEquals($uri, $recvUri);
        }
        $client = (yield connect($recvUri));
        $this->assertInstanceOf(ChannelledSocket::class, $client);
        (yield $client->send('ping'));
        $this->assertEquals('pong', (yield $client->receive()));
        (yield $client->disconnect());
        $this->assertNull((yield $process->join()));
    }
    /**
     * @dataProvider provideUriType
     */
    public function testIPCDisconectWhileReading(string $uri, int $type)
    {
        $process = new Process([__DIR__ . '/Fixtures/echoServer.php', $uri, $type]);
        (yield $process->start());
        $recvUri = (yield $process->receive());
        if ($uri) {
            $this->assertEquals($uri, $recvUri);
        }
        $client = (yield connect($recvUri));
        $this->assertInstanceOf(ChannelledSocket::class, $client);
        asyncCall(static function () use($client) {
            while ((yield $client->receive())) {
            }
        });
        (yield $client->disconnect());
        $this->assertNull((yield $process->join()));
    }
    /**
     *
     */
    public function provideUriType() : \Generator
    {
        foreach (['', \sys_get_temp_dir() . '/pony', \sys_get_temp_dir() . '/' . \str_repeat('a', 200)] as $uri) {
            if (\strncasecmp(\PHP_OS, "WIN", 3) === 0) {
                (yield [$uri, IpcServer::TYPE_AUTO]);
                (yield [$uri, IpcServer::TYPE_TCP]);
            } else {
                (yield [$uri, IpcServer::TYPE_AUTO]);
                (yield [$uri, IpcServer::TYPE_TCP]);
                if (\strlen($uri) < 200) {
                    (yield [$uri, IpcServer::TYPE_UNIX]);
                }
                (yield [$uri, IpcServer::TYPE_FIFO]);
            }
        }
    }
}<?php

\Phabel\Target\Php80\Polyfill::error_reporting(E_ALL);
\ini_set('log_errors', 1);
\ini_set('error_log', '/tmp/amphp.log');
\error_log('Inited IPC test!');
use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Parallel\Sync\Channel;
use function Amp\delay;
return function (Channel $channel) use($argv) {
    $server = new IpcServer($argv[1], (int) $argv[2]);
    (yield $channel->send($server->getUri()));
    $socket = (yield $server->accept());
    if (!$socket instanceof ChannelledSocket) {
        throw new \RuntimeException('Socket is not instance of ChannelledSocket');
    }
    $ping = (yield $socket->receive());
    if ($ping !== 'ping') {
        throw new \RuntimeException("Received {$ping} instead of ping!");
    }
    (yield $socket->send('pong'));
    (yield $socket->disconnect());
    $server->close();
    return $server->accept();
};<?php

\Phabel\Target\Php80\Polyfill::error_reporting(E_ALL);
\ini_set('log_errors', 1);
\ini_set('error_log', '/tmp/amphp.log');
\error_log('Inited IPC test!');
use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Parallel\Sync\Channel;
use function Amp\delay;
return function (Channel $channel) use($argv) {
    $server = new IpcServer($argv[1], (int) $argv[2]);
    (yield $channel->send($server->getUri()));
    $socket = (yield $server->accept());
    if (!$socket instanceof ChannelledSocket) {
        throw new \RuntimeException('Socket is not instance of ChannelledSocket');
    }
    while ((yield $socket->receive())) {
    }
    (yield $socket->disconnect());
    $server->close();
    return $server->accept();
};<?php

class a
{
}
class b
{
}
$a = new a();
$a->a = ['lel', ['lel', [new a()]]];
$a->b = new a();
$a->b->c = [new a()];
$a->b->c[0]->d = 'cos';
$a->b->c[0]->e = new b();
$a->b->c[0]->e->f = new a();
$a = [$a];
file_put_contents('test', serialize($a));
var_dump(serialize($a), $a);
var_dump(unserialize(file_get_contents('testb')));<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MagicalSerializer.
MagicalSerializer is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MagicalSerializer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with the MagicalSerializer.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog;

class Serialization
{
    public static $extracted = [];
    /**
     *
     */
    public static function unserialize($data)
    {
        foreach (get_declared_classes() as $class) {
            if (isset(class_uses($class)['danog\\Serializable'])) {
                $namelength = strlen($class);
                if (strpos($data, 'O:' . $namelength . ':"' . $class . '":') === false) {
                    continue;
                }
                $data = explode('O:' . $namelength . ':"' . $class . '":', $data);
                $stringdata = array_shift($data);
                foreach ($data as $chunk) {
                    list($attributecount, $value) = explode(':{', $chunk, 2);
                    $attributecount++;
                    $stringdata .= 'O:17:"danog\\PlaceHolder":' . $attributecount . ':{s:21:"originalclassnamepony";s:' . $namelength . ':"' . $class . '";' . $value;
                }
                $data = $stringdata;
            }
        }
        self::$extracted = [];
        $data = self::extractponyobject(unserialize($data));
        self::$extracted = [];
        return $data;
    }
    /**
     *
     */
    public static function extractponyobject($orig)
    {
        if (isset($orig->realactualponyobject)) {
            return self::extractponyobject($orig->realactualponyobject);
        }
        if (is_array($orig) || $orig instanceof \Volatile) {
            foreach ($orig as $key => $value) {
                $orig[$key] = self::extractponyobject($value);
            }
            return $orig;
        }
        if (is_object($orig) && !isset(self::$extracted[$hash = spl_object_hash($orig)])) {
            self::$extracted[$hash] = true;
            foreach ($orig as $key => $value) {
                $orig->{$key} = self::extractponyobject($value);
            }
        }
        return $orig;
    }
    /**
     *
     */
    public static function serialize($object, $not_compatible = false)
    {
        self::$extracted = [];
        $object = serialize(self::createserializableobject($object));
        self::$extracted = [];
        if ($not_compatible === true) {
            return $object;
        }
        $object = explode('O:17:"danog\\PlaceHolder":', $object);
        $newobject = array_shift($object);
        foreach ($object as $chunk) {
            list($attributecount, $value) = explode(':{', $chunk, 2);
            $attributecount--;
            list($pre, $value) = explode('s:21:"originalclassnamepony";s:', $value, 2);
            list($length, $value) = explode(':', $value, 2);
            $classname = \Phabel\Target\Php80\Polyfill::substr($value, 1, $length);
            $value = $pre . \Phabel\Target\Php80\Polyfill::substr($value, $length + 3);
            $newobject .= 'O:' . strlen($classname) . ':"' . $classname . '":' . $attributecount . ':{' . $value;
        }
        return $newobject;
    }
    /**
     *
     */
    public static function createserializableobject($orig)
    {
        if (is_object($orig) && $orig instanceof \danog\MadelineProto\VoIP) {
            $orig = false;
        }
        if (is_object($orig)) {
            if (isset(self::$extracted[$hash = spl_object_hash($orig)])) {
                return self::$extracted[$hash];
            }
            if (method_exists($orig, 'fetchserializableobject')) {
                return $orig->fetchserializableobject($hash);
            }
            self::$extracted[$hash] = $orig;
        }
        if (is_array($orig) || $orig instanceof \Volatile) {
            foreach ($orig as $key => $value) {
                $orig[$key] = self::createserializableobject($value);
            }
        }
        return $orig;
    }
}<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MagicalSerializer.
MagicalSerializer is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MagicalSerializer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with the MagicalSerializer.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog;

trait Serializable
{
    /**
     *
     */
    public final function __construct(...$params)
    {
        if (count($params) === 1 && is_array($params[0]) && isset($params[0]['originalclassnamepony'])) {
            unset($params[0]['originalclassnamepony']);
            foreach ($params[0] as $key => $value) {
                if (strpos($key, chr(0) . get_class($this) . chr(0)) === 0) {
                    $key = \Phabel\Target\Php80\Polyfill::substr($key, strlen(get_class($this)) + 2);
                } elseif (strpos($key, chr(0) . '*' . chr(0)) === 0) {
                    $key = \Phabel\Target\Php80\Polyfill::substr($key, 3);
                } elseif ($key[0] === "\x00") {
                    $key = \Phabel\Target\Php80\Polyfill::substr($key, 1);
                }
                $this->{$key} = \danog\Serialization::extractponyobject($value);
            }
            return;
        }
        if (method_exists($this, '__magic_construct')) {
            $this->__magic_construct(...$params);
        } elseif (method_exists($this, '___construct')) {
            $this->___construct(...$params);
        }
    }
    /**
     *
     */
    public final function fetchserializableobject($hash)
    {
        $values = get_object_vars($this);
        if (method_exists($this, '__sleep')) {
            $newvalues = [];
            foreach ($this->__sleep() as $key) {
                $newvalues[$key] = $values[$key];
            }
            $values = $newvalues;
        }
        return new \danog\PlaceHolder($hash, get_class($this), $values);
    }
}<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MagicalSerializer.
MagicalSerializer is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MagicalSerializer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with the MagicalSerializer.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog;

class PlaceHolder
{
    /**
     *
     */
    public function __construct($hash, $originalclassnamepony, $elements)
    {
        Serialization::$extracted[$hash] = $this;
        $this->originalclassnamepony = $originalclassnamepony;
        foreach ($elements as $key => $value) {
            $this->{$key} = Serialization::createserializableobject($value);
        }
    }
    /**
     *
     */
    public function __wakeup()
    {
        $this->realactualponyobject = ($phabel_02f998efa324f8a4 = $this->originalclassnamepony) || true ? new $phabel_02f998efa324f8a4(get_object_vars($this)) : false;
        if (method_exists($this->realactualponyobject, '__wakeup')) {
            $this->realactualponyobject->__wakeup();
        }
    }
}{
    "name": "danog/magicalserializer",
    "description": "Serialize Volatile, Threaded or any other internal PHP class!",
    "type": "library",
    "license": "AGPL-3.0-only",
    "homepage": "https://daniil.it/MagicalSerializer",
    "keywords": ["pthreads", "volatile", "serialize", "threading", "serializable"],
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "autoload": {
        "psr-0": {
            "danog\\": "src/"
        }
    }
}
<?php

require 'vendor/autoload.php';
class a
{
    use \danog\Serializable;
    protected $a;
    /**
     *
     */
    public function ___construct()
    {
        var_dump('CONSTRUCTED a');
    }
    /**
     *
     */
    public function __wakeup()
    {
        var_dump('WOKE UP a');
    }
}
new a();
class b
{
    use \danog\Serializable;
}
$result = \danog\Serialization::unserialize(file_get_contents('test'));
var_dump($result);
file_put_contents('testb', \danog\Serialization::serialize($result));<?php

$config = new Amp\CodeStyle\Config();
$config->getFinder()
    ->in(__DIR__ . '/src')
    ->in(__DIR__ . '/tools');

$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;

$config->setCacheFile($cacheDir . '/.php_cs.cache');

return $config;
    <?php
    if (file_exists(__DIR__.'/../vendor/autoload.php')) return require __DIR__.'/../vendor/autoload.php';
    return require __DIR__.'/../../../autoload.php';<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.function.php';<?php

namespace PhabelVendor;

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if (!\function_exists('PhabelVendor\\trigger_deprecation')) {
    /**
     * Triggers a silenced deprecation notice.
     *
     * @param string $package The name of the Composer package that is triggering the deprecation
     * @param string $version The version of the package that introduced the deprecation
     * @param string $message The message of the deprecation
     * @param mixed ...$args Values to insert in the message using printf() formatting
     *
     * @author Nicolas Grekas <p@tchwork.com>
     */
    function trigger_deprecation(string $package, string $version, string $message, ...$args) : void
    {
        foreach ($args as $phabelVariadicIndex => $phabelVariadic) {
            if (!\true) {
                throw new \TypeError(__METHOD__ . '(): Argument #' . (4 + $phabelVariadicIndex) . ' must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($args) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
        }
        @\trigger_error(($package || $version ? "Since {$package} {$version}: " : '') . ($args ? \vsprintf($message, $args) : $message), \E_USER_DEPRECATED);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process;

use PhabelVendor\Symfony\Component\Process\Exception\LogicException;
use PhabelVendor\Symfony\Component\Process\Exception\RuntimeException;
/**
 * PhpProcess runs a PHP script in an independent process.
 *
 *     $p = new PhpProcess('<?php echo "foo"; ?>');
 *     $p->run();
 *     print $p->getOutput()."\n";
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class PhpProcess extends Process
{
    /**
     * @param string $script The PHP script to run (as a string)
     * @param (string | null) $cwd The working directory or null to use the working dir of the current PHP process
     * @param (array | null) $env The environment variables or null to use the same environment as the current PHP process
     * @param int $timeout The timeout in seconds
     * @param (array | null) $php Path to the PHP binary to use with any additional arguments
     */
    public function __construct(string $script, string $cwd = null, array $env = null, int $timeout = 60, array $php = null)
    {
        if (null === $php) {
            $executableFinder = new PhpExecutableFinder();
            $php = $executableFinder->find(\false);
            $php = \false === $php ? null : \array_merge([$php], $executableFinder->findArguments());
        }
        if ('phpdbg' === \PHP_SAPI) {
            $file = \tempnam(\sys_get_temp_dir(), 'dbg');
            \file_put_contents($file, $script);
            \register_shutdown_function('unlink', $file);
            $php[] = $file;
            $script = null;
        }
        parent::__construct($php, $cwd, $env, $script, $timeout);
    }
    /**
     * {@inheritdoc}
     */
    public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60)
    {
        throw new LogicException(\sprintf('The "%s()" method cannot be called when using "%s".', __METHOD__, self::class));
    }
    /**
     * {@inheritdoc}
     */
    public function start(callable $callback = null, array $env = [])
    {
        if (null === $this->getCommandLine()) {
            throw new RuntimeException('Unable to find the PHP executable.');
        }
        parent::start($callback, $env);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process;

/**
 * An executable finder specifically designed for the PHP executable.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class PhpExecutableFinder
{
    private $executableFinder;
    /**
     *
     */
    public function __construct()
    {
        $this->executableFinder = new ExecutableFinder();
    }
    /**
     * Finds The PHP executable.
     *
     * @return (string | false)
     */
    public function find(bool $includeArgs = \true)
    {
        if ($php = \getenv('PHP_BINARY')) {
            if (!\is_executable($php)) {
                $command = '\\' === \DIRECTORY_SEPARATOR ? 'where' : 'command -v';
                if ($php = \strtok(\exec($command . ' ' . \escapeshellarg($php)), \PHP_EOL)) {
                    if (!\is_executable($php)) {
                        return \false;
                    }
                } else {
                    return \false;
                }
            }
            return $php;
        }
        $args = $this->findArguments();
        $args = $includeArgs && $args ? ' ' . \implode(' ', $args) : '';
        // PHP_BINARY return the current sapi executable
        if (\PHP_BINARY && \in_array(\PHP_SAPI, ['cgi-fcgi', 'cli', 'cli-server', 'phpdbg'], \true)) {
            return \PHP_BINARY . $args;
        }
        if ($php = \getenv('PHP_PATH')) {
            if (!@\is_executable($php)) {
                return \false;
            }
            return $php;
        }
        if ($php = \getenv('PHP_PEAR_PHP_BIN')) {
            if (@\is_executable($php)) {
                return $php;
            }
        }
        if (@\is_executable($php = \PHP_BINDIR . ('\\' === \DIRECTORY_SEPARATOR ? '\\php.exe' : '/php'))) {
            return $php;
        }
        $dirs = [\PHP_BINDIR];
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $dirs[] = 'C:\\xampp\\php\\';
        }
        return $this->executableFinder->find('php', \false, $dirs);
    }
    /**
     * Finds the PHP executable arguments.
     *
     * @return array
     */
    public function findArguments()
    {
        $arguments = [];
        if ('phpdbg' === \PHP_SAPI) {
            $arguments[] = '-qrr';
        }
        return $arguments;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process;

/**
 * Generic executable finder.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ExecutableFinder
{
    private $suffixes = ['.exe', '.bat', '.cmd', '.com'];
    /**
     * Replaces default suffixes of executable.
     */
    public function setSuffixes(array $suffixes)
    {
        $this->suffixes = $suffixes;
    }
    /**
     * Adds new possible suffix to check for executable.
     */
    public function addSuffix(string $suffix)
    {
        $this->suffixes[] = $suffix;
    }
    /**
     * Finds an executable by name.
     *
     * @param string $name The executable name (without the extension)
     * @param (string | null) $default The default to return if no executable is found
     * @param array $extraDirs Additional dirs to check into
     *
     * @return (string | null)
     */
    public function find(string $name, string $default = null, array $extraDirs = [])
    {
        if (\ini_get('open_basedir')) {
            $searchPath = \array_merge(\explode(\PATH_SEPARATOR, \ini_get('open_basedir')), $extraDirs);
            $dirs = [];
            foreach ($searchPath as $path) {
                // Silencing against https://bugs.php.net/69240
                if (@\is_dir($path)) {
                    $dirs[] = $path;
                } else {
                    if (\basename($path) == $name && @\is_executable($path)) {
                        return $path;
                    }
                }
            }
        } else {
            $dirs = \array_merge(\explode(\PATH_SEPARATOR, \getenv('PATH') ?: \getenv('Path')), $extraDirs);
        }
        $suffixes = [''];
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $pathExt = \getenv('PATHEXT');
            $suffixes = \array_merge($pathExt ? \explode(\PATH_SEPARATOR, $pathExt) : $this->suffixes, $suffixes);
        }
        foreach ($suffixes as $suffix) {
            foreach ($dirs as $dir) {
                if (@\is_file($file = $dir . \DIRECTORY_SEPARATOR . $name . $suffix) && ('\\' === \DIRECTORY_SEPARATOR || @\is_executable($file))) {
                    return $file;
                }
            }
        }
        return $default;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process;

use PhabelVendor\Symfony\Component\Process\Exception\RuntimeException;
/**
 * Provides a way to continuously write to the input of a Process until the InputStream is closed.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @implements \IteratorAggregate<int, string>
 */
class InputStream implements \IteratorAggregate
{
    /** @var callable|null */
    private $onEmpty = null;
    private $input = [];
    private $open = \true;
    /**
     * Sets a callback that is called when the write buffer becomes empty.
     */
    public function onEmpty(callable $onEmpty = null)
    {
        $this->onEmpty = $onEmpty;
    }
    /**
    * Appends an input to the write buffer.
    *
    * @param (resource | string | int | float | bool | \Traversable | null) $input The input to append as scalar,
    stream resource or \Traversable
    */
    public function write($input)
    {
        if (null === $input) {
            return;
        }
        if ($this->isClosed()) {
            throw new RuntimeException(\sprintf('"%s" is closed.', static::class));
        }
        $this->input[] = ProcessUtils::validateInput(__METHOD__, $input);
    }
    /**
     * Closes the write buffer.
     */
    public function close()
    {
        $this->open = \false;
    }
    /**
     * Tells whether the write buffer is closed or not.
     */
    public function isClosed()
    {
        return !$this->open;
    }
    /**
     * @return \Traversable<int, string>
     */
    #[\ReturnTypeWillChange]
    public function getIterator()
    {
        $this->open = \true;
        while ($this->open || $this->input) {
            if (!$this->input) {
                (yield '');
                continue;
            }
            $current = \array_shift($this->input);
            if ($current instanceof \Iterator) {
                yield from $current;
            } else {
                (yield $current);
            }
            if (!$this->input && $this->open && null !== ($onEmpty = $this->onEmpty)) {
                $this->write($onEmpty($this));
            }
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Exception;

use PhabelVendor\Symfony\Component\Process\Process;
/**
 * Exception for failed processes.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessFailedException extends RuntimeException
{
    private $process;
    /**
     *
     */
    public function __construct(Process $process)
    {
        if ($process->isSuccessful()) {
            throw new InvalidArgumentException('Expected a failed process, but the given process was successful.');
        }
        $error = \sprintf('The command "%s" failed.

Exit Code: %s(%s)

Working directory: %s', $process->getCommandLine(), $process->getExitCode(), $process->getExitCodeText(), $process->getWorkingDirectory());
        if (!$process->isOutputDisabled()) {
            $error .= \sprintf("\n\nOutput:\n================\n%s\n\nError Output:\n================\n%s", $process->getOutput(), $process->getErrorOutput());
        }
        parent::__construct($error);
        $this->process = $process;
    }
    /**
     *
     */
    public function getProcess()
    {
        return $this->process;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Exception;

use PhabelVendor\Symfony\Component\Process\Process;
/**
 * Exception that is thrown when a process has been signaled.
 *
 * @author Sullivan Senechal <soullivaneuh@gmail.com>
 */
final class ProcessSignaledException extends RuntimeException
{
    private $process;
    /**
     *
     */
    public function __construct(Process $process)
    {
        $this->process = $process;
        parent::__construct(\sprintf('The process has been signaled with signal "%s".', $process->getTermSignal()));
    }
    /**
     *
     */
    public function getProcess() : Process
    {
        return $this->process;
    }
    /**
     *
     */
    public function getSignal() : int
    {
        return $this->getProcess()->getTermSignal();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Exception;

/**
 * RuntimeException for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Exception;

use PhabelVendor\Symfony\Component\Process\Process;
/**
 * Exception that is thrown when a process times out.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
class ProcessTimedOutException extends RuntimeException
{
    public const TYPE_GENERAL = 1;
    public const TYPE_IDLE = 2;
    private $process;
    private $timeoutType;
    /**
     *
     */
    public function __construct(Process $process, int $timeoutType)
    {
        $this->process = $process;
        $this->timeoutType = $timeoutType;
        parent::__construct(\sprintf('The process "%s" exceeded the timeout of %s seconds.', $process->getCommandLine(), $this->getExceededTimeout()));
    }
    /**
     *
     */
    public function getProcess()
    {
        return $this->process;
    }
    /**
     *
     */
    public function isGeneralTimeout()
    {
        return self::TYPE_GENERAL === $this->timeoutType;
    }
    /**
     *
     */
    public function isIdleTimeout()
    {
        return self::TYPE_IDLE === $this->timeoutType;
    }
    /**
     *
     */
    public function getExceededTimeout()
    {
        switch ($this->timeoutType) {
            case self::TYPE_GENERAL:
                return $this->process->getTimeout();
            case self::TYPE_IDLE:
                return $this->process->getIdleTimeout();
            default:
                throw new \LogicException(\sprintf('Unknown timeout type "%d".', $this->timeoutType));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Exception;

/**
 * InvalidArgumentException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Exception;

/**
 * LogicException for the Process Component.
 *
 * @author Romain Neutron <imprec@gmail.com>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Exception;

/**
 * Marker Interface for the Process Component.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Pipes;

use PhabelVendor\Symfony\Component\Process\Exception\InvalidArgumentException;
/**
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
abstract class AbstractPipes implements PipesInterface
{
    public $pipes = [];
    private $inputBuffer = '';
    private $input;
    private $blocked = \true;
    private $lastError;
    /**
     * @param (resource | string | int | float | bool | \Iterator | null) $input
     */
    public function __construct($input)
    {
        if (\is_resource($input) || $input instanceof \Iterator) {
            $this->input = $input;
        } elseif (\is_string($input)) {
            $this->inputBuffer = $input;
        } else {
            $this->inputBuffer = (string) $input;
        }
    }
    /**
     * {@inheritdoc}
     */
    public function close()
    {
        foreach ($this->pipes as $pipe) {
            \fclose($pipe);
        }
        $this->pipes = [];
    }
    /**
     * Returns true if a system call has been interrupted.
     */
    protected function hasSystemCallBeenInterrupted() : bool
    {
        $lastError = $this->lastError;
        $this->lastError = null;
        // stream_select returns false when the `select` system call is interrupted by an incoming signal
        return null !== $lastError && \false !== \stripos($lastError, 'interrupted system call');
    }
    /**
     * Unblocks streams.
     */
    protected function unblock()
    {
        if (!$this->blocked) {
            return;
        }
        foreach ($this->pipes as $pipe) {
            \stream_set_blocking($pipe, 0);
        }
        if (\is_resource($this->input)) {
            \stream_set_blocking($this->input, 0);
        }
        $this->blocked = \false;
    }
    /**
     * Writes input to stdin.
     *
     * @throws InvalidArgumentException When an input iterator yields a non supported value
     */
    protected function write() : ?array
    {
        if (!isset($this->pipes[0])) {
            return null;
        }
        $input = $this->input;
        if ($input instanceof \Iterator) {
            if (!$input->valid()) {
                $input = null;
            } elseif (\is_resource($input = $input->current())) {
                \stream_set_blocking($input, 0);
            } elseif (!isset($this->inputBuffer[0])) {
                if (!\is_string($input)) {
                    if (!\is_scalar($input)) {
                        throw new InvalidArgumentException(\sprintf('"%s" yielded a value of type "%s", but only scalars and stream resources are supported.', \get_debug_type($this->input), \get_debug_type($input)));
                    }
                    $input = (string) $input;
                }
                $this->inputBuffer = $input;
                $this->input->next();
                $input = null;
            } else {
                $input = null;
            }
        }
        $r = $e = [];
        $w = [$this->pipes[0]];
        // let's have a look if something changed in streams
        if (\false === @\stream_select($r, $w, $e, 0, 0)) {
            return null;
        }
        foreach ($w as $stdin) {
            if (isset($this->inputBuffer[0])) {
                $written = \fwrite($stdin, $this->inputBuffer);
                $this->inputBuffer = \Phabel\Target\Php80\Polyfill::substr($this->inputBuffer, $written);
                if (isset($this->inputBuffer[0])) {
                    return [$this->pipes[0]];
                }
            }
            if ($input) {
                for (;;) {
                    $data = \fread($input, self::CHUNK_SIZE);
                    if (!isset($data[0])) {
                        break;
                    }
                    $written = \fwrite($stdin, $data);
                    $data = \Phabel\Target\Php80\Polyfill::substr($data, $written);
                    if (isset($data[0])) {
                        $this->inputBuffer = $data;
                        return [$this->pipes[0]];
                    }
                }
                if (\feof($input)) {
                    if ($this->input instanceof \Iterator) {
                        $this->input->next();
                    } else {
                        $this->input = null;
                    }
                }
            }
        }
        // no input to read on resource, buffer is empty
        if (!isset($this->inputBuffer[0]) && !($this->input instanceof \Iterator ? $this->input->valid() : $this->input)) {
            $this->input = null;
            \fclose($this->pipes[0]);
            unset($this->pipes[0]);
        } elseif (!$w) {
            return [$this->pipes[0]];
        }
        return null;
    }
    /**
     * @internal
     */
    public function handleError(int $type, string $msg)
    {
        $this->lastError = $msg;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Pipes;

/**
 * PipesInterface manages descriptors and pipes for the use of proc_open.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
interface PipesInterface
{
    public const CHUNK_SIZE = 16384;
    /**
     * Returns an array of descriptors for the use of proc_open.
     */
    public function getDescriptors() : array;
    /**
     * Returns an array of filenames indexed by their related stream in case these pipes use temporary files.
     *
     * @return string[]
     */
    public function getFiles() : array;
    /**
     * Reads data in file handles and pipes.
     *
     * @param bool $blocking Whether to use blocking calls or not
     * @param bool $close Whether to close pipes if they've reached EOF
     *
     * @return string[] An array of read data indexed by their fd
     */
    public function readAndWrite(bool $blocking, bool $close = \false) : array;
    /**
     * Returns if the current state has open file handles or pipes.
     */
    public function areOpen() : bool;
    /**
     * Returns if pipes are able to read output.
     */
    public function haveReadSupport() : bool;
    /**
     * Closes file handles and pipes.
     */
    public function close();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Pipes;

use PhabelVendor\Symfony\Component\Process\Exception\RuntimeException;
use PhabelVendor\Symfony\Component\Process\Process;
/**
 * WindowsPipes implementation uses temporary files as handles.
 *
 * @see https://bugs.php.net/51800
 * @see https://bugs.php.net/65650
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
class WindowsPipes extends AbstractPipes
{
    private $files = [];
    private $fileHandles = [];
    private $lockHandles = [];
    private $readBytes = [Process::STDOUT => 0, Process::STDERR => 0];
    private $haveReadSupport;
    /**
     *
     */
    public function __construct($input, bool $haveReadSupport)
    {
        $this->haveReadSupport = $haveReadSupport;
        if ($this->haveReadSupport) {
            // Fix for PHP bug #51800: reading from STDOUT pipe hangs forever on Windows if the output is too big.
            // Workaround for this problem is to use temporary files instead of pipes on Windows platform.
            //
            // @see https://bugs.php.net/51800
            $pipes = [Process::STDOUT => Process::OUT, Process::STDERR => Process::ERR];
            $tmpDir = \sys_get_temp_dir();
            $lastError = 'unknown reason';
            \set_error_handler(function ($type, $msg) use(&$lastError) {
                $lastError = $msg;
            });
            for ($i = 0;; ++$i) {
                foreach ($pipes as $pipe => $name) {
                    $file = \sprintf('%s\\sf_proc_%02X.%s', $tmpDir, $i, $name);
                    if (!($h = \fopen($file . '.lock', 'w'))) {
                        if (\file_exists($file . '.lock')) {
                            continue 2;
                        }
                        \restore_error_handler();
                        throw new RuntimeException('A temporary file could not be opened to write the process output: ' . $lastError);
                    }
                    if (!\flock($h, \LOCK_EX | \LOCK_NB)) {
                        continue 2;
                    }
                    if (isset($this->lockHandles[$pipe])) {
                        \flock($this->lockHandles[$pipe], \LOCK_UN);
                        \fclose($this->lockHandles[$pipe]);
                    }
                    $this->lockHandles[$pipe] = $h;
                    if (!($h = \fopen($file, 'w')) || !\fclose($h) || !($h = \fopen($file, 'r'))) {
                        \flock($this->lockHandles[$pipe], \LOCK_UN);
                        \fclose($this->lockHandles[$pipe]);
                        unset($this->lockHandles[$pipe]);
                        continue 2;
                    }
                    $this->fileHandles[$pipe] = $h;
                    $this->files[$pipe] = $file;
                }
                break;
            }
            \restore_error_handler();
        }
        parent::__construct($input);
    }
    /**
     *
     */
    public function __sleep() : array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    /**
     *
     */
    public function __wakeup()
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     * {@inheritdoc}
     */
    public function getDescriptors() : array
    {
        if (!$this->haveReadSupport) {
            $nullstream = \fopen('NUL', 'c');
            return [['pipe', 'r'], $nullstream, $nullstream];
        }
        // We're not using pipe on Windows platform as it hangs (https://bugs.php.net/51800)
        // We're not using file handles as it can produce corrupted output https://bugs.php.net/65650
        // So we redirect output within the commandline and pass the nul device to the process
        return [['pipe', 'r'], ['file', 'NUL', 'w'], ['file', 'NUL', 'w']];
    }
    /**
     * {@inheritdoc}
     */
    public function getFiles() : array
    {
        return $this->files;
    }
    /**
     * {@inheritdoc}
     */
    public function readAndWrite(bool $blocking, bool $close = \false) : array
    {
        $this->unblock();
        $w = $this->write();
        $read = $r = $e = [];
        if ($blocking) {
            if ($w) {
                @\stream_select($r, $w, $e, 0, Process::TIMEOUT_PRECISION * 1000000.0);
            } elseif ($this->fileHandles) {
                \usleep(Process::TIMEOUT_PRECISION * 1000000.0);
            }
        }
        foreach ($this->fileHandles as $type => $fileHandle) {
            $data = \stream_get_contents($fileHandle, -1, $this->readBytes[$type]);
            if (isset($data[0])) {
                $this->readBytes[$type] += \strlen($data);
                $read[$type] = $data;
            }
            if ($close) {
                \ftruncate($fileHandle, 0);
                \fclose($fileHandle);
                \flock($this->lockHandles[$type], \LOCK_UN);
                \fclose($this->lockHandles[$type]);
                unset($this->fileHandles[$type], $this->lockHandles[$type]);
            }
        }
        return $read;
    }
    /**
     * {@inheritdoc}
     */
    public function haveReadSupport() : bool
    {
        return $this->haveReadSupport;
    }
    /**
     * {@inheritdoc}
     */
    public function areOpen() : bool
    {
        return $this->pipes && $this->fileHandles;
    }
    /**
     * {@inheritdoc}
     */
    public function close()
    {
        parent::close();
        foreach ($this->fileHandles as $type => $handle) {
            \ftruncate($handle, 0);
            \fclose($handle);
            \flock($this->lockHandles[$type], \LOCK_UN);
            \fclose($this->lockHandles[$type]);
        }
        $this->fileHandles = $this->lockHandles = [];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process\Pipes;

use PhabelVendor\Symfony\Component\Process\Process;
/**
 * UnixPipes implementation uses unix pipes as handles.
 *
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @internal
 */
class UnixPipes extends AbstractPipes
{
    private $ttyMode;
    private $ptyMode;
    private $haveReadSupport;
    /**
     *
     */
    public function __construct(?bool $ttyMode, bool $ptyMode, $input, bool $haveReadSupport)
    {
        $this->ttyMode = $ttyMode;
        $this->ptyMode = $ptyMode;
        $this->haveReadSupport = $haveReadSupport;
        parent::__construct($input);
    }
    /**
     *
     */
    public function __sleep() : array
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    /**
     *
     */
    public function __wakeup()
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     * {@inheritdoc}
     */
    public function getDescriptors() : array
    {
        if (!$this->haveReadSupport) {
            $nullstream = \fopen('/dev/null', 'c');
            return [['pipe', 'r'], $nullstream, $nullstream];
        }
        if ($this->ttyMode) {
            return [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']];
        }
        if ($this->ptyMode && Process::isPtySupported()) {
            return [['pty'], ['pty'], ['pty']];
        }
        return [
            ['pipe', 'r'],
            ['pipe', 'w'],
            // stdout
            ['pipe', 'w'],
        ];
    }
    /**
     * {@inheritdoc}
     */
    public function getFiles() : array
    {
        return [];
    }
    /**
     * {@inheritdoc}
     */
    public function readAndWrite(bool $blocking, bool $close = \false) : array
    {
        $this->unblock();
        $w = $this->write();
        $read = $e = [];
        $r = $this->pipes;
        unset($r[0]);
        // let's have a look if something changed in streams
        \set_error_handler([$this, 'handleError']);
        if (($r || $w) && \false === \stream_select($r, $w, $e, 0, $blocking ? Process::TIMEOUT_PRECISION * 1000000.0 : 0)) {
            \restore_error_handler();
            // if a system call has been interrupted, forget about it, let's try again
            // otherwise, an error occurred, let's reset pipes
            if (!$this->hasSystemCallBeenInterrupted()) {
                $this->pipes = [];
            }
            return $read;
        }
        \restore_error_handler();
        foreach ($r as $pipe) {
            // prior PHP 5.4 the array passed to stream_select is modified and
            // lose key association, we have to find back the key
            $read[$type = \array_search($pipe, $this->pipes, \true)] = '';
            do {
                $data = @\fread($pipe, self::CHUNK_SIZE);
                $read[$type] .= $data;
            } while (isset($data[0]) && ($close || isset($data[self::CHUNK_SIZE - 1])));
            if (!isset($read[$type][0])) {
                unset($read[$type]);
            }
            if ($close && \feof($pipe)) {
                \fclose($pipe);
                unset($this->pipes[$type]);
            }
        }
        return $read;
    }
    /**
     * {@inheritdoc}
     */
    public function haveReadSupport() : bool
    {
        return $this->haveReadSupport;
    }
    /**
     * {@inheritdoc}
     */
    public function areOpen() : bool
    {
        return (bool) $this->pipes;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process;

use PhabelVendor\Symfony\Component\Process\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Process\Exception\LogicException;
use PhabelVendor\Symfony\Component\Process\Exception\ProcessFailedException;
use PhabelVendor\Symfony\Component\Process\Exception\ProcessSignaledException;
use PhabelVendor\Symfony\Component\Process\Exception\ProcessTimedOutException;
use PhabelVendor\Symfony\Component\Process\Exception\RuntimeException;
use PhabelVendor\Symfony\Component\Process\Pipes\PipesInterface;
use PhabelVendor\Symfony\Component\Process\Pipes\UnixPipes;
use PhabelVendor\Symfony\Component\Process\Pipes\WindowsPipes;
/**
 * Process is a thin wrapper around proc_* functions to easily
 * start independent PHP processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Romain Neutron <imprec@gmail.com>
 *
 * @implements \IteratorAggregate<string, string>
 */
class Process implements \IteratorAggregate
{
    public const ERR = 'err';
    public const OUT = 'out';
    public const STATUS_READY = 'ready';
    public const STATUS_STARTED = 'started';
    public const STATUS_TERMINATED = 'terminated';
    public const STDIN = 0;
    public const STDOUT = 1;
    public const STDERR = 2;
    // Timeout Precision in seconds.
    public const TIMEOUT_PRECISION = 0.2;
    public const ITER_NON_BLOCKING = 1;
    // By default, iterating over outputs is a blocking call, use this flag to make it non-blocking
    public const ITER_KEEP_OUTPUT = 2;
    // By default, outputs are cleared while iterating, use this flag to keep them in memory
    public const ITER_SKIP_OUT = 4;
    // Use this flag to skip STDOUT while iterating
    public const ITER_SKIP_ERR = 8;
    // Use this flag to skip STDERR while iterating
    private $callback;
    private $hasCallback = \false;
    private $commandline;
    private $cwd;
    private $env;
    private $input;
    private $starttime;
    private $lastOutputTime;
    private $timeout;
    private $idleTimeout;
    private $exitcode;
    private $fallbackStatus = [];
    private $processInformation;
    private $outputDisabled = \false;
    private $stdout;
    private $stderr;
    private $process;
    private $status = self::STATUS_READY;
    private $incrementalOutputOffset = 0;
    private $incrementalErrorOutputOffset = 0;
    private $tty = \false;
    private $pty;
    private $options = ['suppress_errors' => \true, 'bypass_shell' => \true];
    private $useFileHandles = \false;
    /** @var PipesInterface */
    private $processPipes;
    private $latestSignal;
    private static $sigchild;
    /**
     * Exit codes translation table.
     *
     * User-defined errors must use exit codes in the 64-113 range.
     */
    public static $exitCodes = [
        0 => 'OK',
        1 => 'General error',
        2 => 'Misuse of shell builtins',
        126 => 'Invoked command cannot execute',
        127 => 'Command not found',
        128 => 'Invalid exit argument',
        // signals
        129 => 'Hangup',
        130 => 'Interrupt',
        131 => 'Quit and dump core',
        132 => 'Illegal instruction',
        133 => 'Trace/breakpoint trap',
        134 => 'Process aborted',
        135 => 'Bus error: "access to undefined portion of memory object"',
        136 => 'Floating point exception: "erroneous arithmetic operation"',
        137 => 'Kill (terminate immediately)',
        138 => 'User-defined 1',
        139 => 'Segmentation violation',
        140 => 'User-defined 2',
        141 => 'Write to pipe with no one reading',
        142 => 'Signal raised by alarm',
        143 => 'Termination (request to terminate)',
        // 144 - not defined
        145 => 'Child process terminated, stopped (or continued*)',
        146 => 'Continue if stopped',
        147 => 'Stop executing temporarily',
        148 => 'Terminal stop signal',
        149 => 'Background process attempting to read from tty ("in")',
        150 => 'Background process attempting to write to tty ("out")',
        151 => 'Urgent data available on socket',
        152 => 'CPU time limit exceeded',
        153 => 'File size limit exceeded',
        154 => 'Signal raised by timer counting virtual time: "virtual timer expired"',
        155 => 'Profiling timer expired',
        // 156 - not defined
        157 => 'Pollable event',
        // 158 - not defined
        159 => 'Bad syscall',
    ];
    /**
     * @param array $command The command to run and its arguments listed as separate entries
     * @param (string | null) $cwd The working directory or null to use the working dir of the current PHP process
     * @param (array | null) $env The environment variables or null to use the same environment as the current PHP process
     * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input
     * @param (int | float | null) $timeout The timeout in seconds or null to disable
     *
     * @throws LogicException When proc_open is not installed
     */
    public function __construct(array $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60)
    {
        if (!\function_exists('proc_open')) {
            throw new LogicException('The Process class relies on proc_open, which is not available on your PHP installation.');
        }
        $this->commandline = $command;
        $this->cwd = $cwd;
        // on Windows, if the cwd changed via chdir(), proc_open defaults to the dir where PHP was started
        // on Gnu/Linux, PHP builds with --enable-maintainer-zts are also affected
        // @see : https://bugs.php.net/51800
        // @see : https://bugs.php.net/50524
        if (null === $this->cwd && (\defined('ZEND_THREAD_SAFE') || '\\' === \DIRECTORY_SEPARATOR)) {
            $this->cwd = \getcwd();
        }
        if (null !== $env) {
            $this->setEnv($env);
        }
        $this->setInput($input);
        $this->setTimeout($timeout);
        $this->useFileHandles = '\\' === \DIRECTORY_SEPARATOR;
        $this->pty = \false;
    }
    /**
    * Creates a Process instance as a command-line to be run in a shell wrapper.
    *
    * Command-lines are parsed by the shell of your OS (/bin/sh on Unix-like, cmd.exe on Windows.)
    This allows using e.g. pipes or conditional execution. In this mode, signals are sent to the
    shell wrapper and not to your commands.
    *
    * In order to inject dynamic values into command-lines, we strongly recommend using placeholders.
    This will save escaping values, which is not portable nor secure anyway:
    *
    * $process = Process::fromShellCommandline('my_command "$MY_VAR"');
    $process->run(null, ['MY_VAR' => $theValue]);
    *
    * @param string $command The command line to pass to the shell of the OS
    * @param (string | null) $cwd The working directory or null to use the working dir of the current PHP process
    * @param (array | null) $env The environment variables or null to use the same environment as the current PHP process
    * @param mixed $input The input as stream resource, scalar or \Traversable, or null for no input
    * @param (int | float | null) $timeout The timeout in seconds or null to disable
    *
    * @return static
    *
    * @throws LogicException When proc_open is not installed
    */
    public static function fromShellCommandline(string $command, string $cwd = null, array $env = null, $input = null, ?float $timeout = 60)
    {
        $process = new static([], $cwd, $env, $input, $timeout);
        $process->commandline = $command;
        return $process;
    }
    /**
     * @return array
     */
    public function __sleep()
    {
        throw new \BadMethodCallException('Cannot serialize ' . __CLASS__);
    }
    /**
     *
     */
    public function __wakeup()
    {
        throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->options['create_new_console'] ?? \false) {
            $this->processPipes->close();
        } else {
            $this->stop(0);
        }
    }
    /**
     *
     */
    public function __clone()
    {
        $this->resetProcessData();
    }
    /**
    * Runs the process.
    *
    * The callback receives the type of output (out or err) and
    some bytes from the output in real-time. It allows to have feedback
    from the independent process during execution.
    *
    * The STDOUT and STDERR are also available after the process is finished
    via the getOutput() and getErrorOutput() methods.
    *
    * @param (callable | null) $callback A PHP callback to run whenever there is some
    output available on STDOUT or STDERR
    *
    * @return int The exit status code
    *
    * @throws RuntimeException When process can't be launched
    * @throws RuntimeException When process is already running
    * @throws ProcessTimedOutException When process timed out
    * @throws ProcessSignaledException When process stopped after receiving signal
    * @throws LogicException In case a callback is provided and output has been disabled
    *
    * @final
    */
    public function run(callable $callback = null, array $env = []) : int
    {
        $this->start($callback, $env);
        return $this->wait();
    }
    /**
    * Runs the process.
    *
    * This is identical to run() except that an exception is thrown if the process
    exits with a non-zero exit code.
    *
    * @return $this
    *
    * @throws ProcessFailedException if the process didn't terminate successfully
    *
    * @final
    */
    public function mustRun(callable $callback = null, array $env = []) : self
    {
        if (0 !== $this->run($callback, $env)) {
            throw new ProcessFailedException($this);
        }
        return $this;
    }
    /**
    * Starts the process and returns after writing the input to STDIN.
    *
    * This method blocks until all STDIN data is sent to the process then it
    returns while the process runs in the background.
    *
    * The termination of the process can be awaited with wait().
    *
    * The callback receives the type of output (out or err) and some bytes from
    the output in real-time while writing the standard input to the process.
    It allows to have feedback from the independent process during execution.
    *
    * @param (callable | null) $callback A PHP callback to run whenever there is some
    output available on STDOUT or STDERR
    *
    * @throws RuntimeException When process can't be launched
    * @throws RuntimeException When process is already running
    * @throws LogicException In case a callback is provided and output has been disabled
    */
    public function start(callable $callback = null, array $env = [])
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running.');
        }
        $this->resetProcessData();
        $this->starttime = $this->lastOutputTime = \microtime(\true);
        $this->callback = $this->buildCallback($callback);
        $this->hasCallback = null !== $callback;
        $descriptors = $this->getDescriptors();
        if ($this->env) {
            $env += '\\' === \DIRECTORY_SEPARATOR ? \array_diff_ukey($this->env, $env, 'strcasecmp') : $this->env;
        }
        $env += '\\' === \DIRECTORY_SEPARATOR ? \array_diff_ukey($this->getDefaultEnv(), $env, 'strcasecmp') : $this->getDefaultEnv();
        if (\is_array($commandline = $this->commandline)) {
            $commandline = \implode(' ', \array_map([$this, 'escapeArgument'], $commandline));
            if ('\\' !== \DIRECTORY_SEPARATOR) {
                // exec is mandatory to deal with sending a signal to the process
                $commandline = 'exec ' . $commandline;
            }
        } else {
            $commandline = $this->replacePlaceholders($commandline, $env);
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $commandline = $this->prepareWindowsCommandLine($commandline, $env);
        } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) {
            // last exit code is output on the fourth pipe and caught to work around --enable-sigchild
            $descriptors[3] = ['pipe', 'w'];
            // See https://unix.stackexchange.com/questions/71205/background-process-pipe-input
            $commandline = '{ (' . $commandline . ') <&3 3<&- 3>/dev/null & } 3<&0;';
            $commandline .= 'pid=$!; echo $pid >&3; wait $pid; code=$?; echo $code >&3; exit $code';
            // Workaround for the bug, when PTS functionality is enabled.
            // @see : https://bugs.php.net/69442
            $ptsWorkaround = \fopen(__FILE__, 'r');
        }
        $envPairs = [];
        foreach ($env as $k => $v) {
            if (\false !== $v && 'argc' !== $k && 'argv' !== $k) {
                $envPairs[] = $k . '=' . $v;
            }
        }
        if (!\is_dir($this->cwd)) {
            throw new RuntimeException(\sprintf('The provided cwd "%s" does not exist.', $this->cwd));
        }
        $this->process = @\proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $envPairs, $this->options);
        if (!\is_resource($this->process)) {
            throw new RuntimeException('Unable to launch a new process.');
        }
        $this->status = self::STATUS_STARTED;
        if (isset($descriptors[3])) {
            $this->fallbackStatus['pid'] = (int) \fgets($this->processPipes->pipes[3]);
        }
        if ($this->tty) {
            return;
        }
        $this->updateStatus(\false);
        $this->checkTimeout();
    }
    /**
    * Restarts the process.
    *
    * Be warned that the process is cloned before being started.
    *
    * @param (callable | null) $callback A PHP callback to run whenever there is some
    output available on STDOUT or STDERR
    *
    * @return static
    *
    * @throws RuntimeException When process can't be launched
    * @throws RuntimeException When process is already running
    *
    * @see start()
    *
    * @final
    */
    public function restart(callable $callback = null, array $env = []) : self
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Process is already running.');
        }
        $process = clone $this;
        $process->start($callback, $env);
        return $process;
    }
    /**
    * Waits for the process to terminate.
    *
    * The callback receives the type of output (out or err) and some bytes
    from the output in real-time while writing the standard input to the process.
    It allows to have feedback from the independent process during execution.
    *
    * @param (callable | null) $callback A valid PHP callback
    *
    * @return int The exitcode of the process
    *
    * @throws ProcessTimedOutException When process timed out
    * @throws ProcessSignaledException When process stopped after receiving signal
    * @throws LogicException When process is not yet started
    */
    public function wait(callable $callback = null)
    {
        $this->requireProcessIsStarted(__FUNCTION__);
        $this->updateStatus(\false);
        if (null !== $callback) {
            if (!$this->processPipes->haveReadSupport()) {
                $this->stop(0);
                throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::wait".');
            }
            $this->callback = $this->buildCallback($callback);
        }
        do {
            $this->checkTimeout();
            $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
            $this->readPipes($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
        } while ($running);
        while ($this->isRunning()) {
            $this->checkTimeout();
            \usleep(1000);
        }
        if ($this->processInformation['signaled'] && $this->processInformation['termsig'] !== $this->latestSignal) {
            throw new ProcessSignaledException($this);
        }
        return $this->exitcode;
    }
    /**
    * Waits until the callback returns true.
    *
    * The callback receives the type of output (out or err) and some bytes
    from the output in real-time while writing the standard input to the process.
    It allows to have feedback from the independent process during execution.
    *
    * @throws RuntimeException When process timed out
    * @throws LogicException When process is not yet started
    * @throws ProcessTimedOutException In case the timeout was reached
    */
    public function waitUntil(callable $callback) : bool
    {
        $this->requireProcessIsStarted(__FUNCTION__);
        $this->updateStatus(\false);
        if (!$this->processPipes->haveReadSupport()) {
            $this->stop(0);
            throw new LogicException('Pass the callback to the "Process::start" method or call enableOutput to use a callback with "Process::waitUntil".');
        }
        $callback = $this->buildCallback($callback);
        $ready = \false;
        while (\true) {
            $this->checkTimeout();
            $running = '\\' === \DIRECTORY_SEPARATOR ? $this->isRunning() : $this->processPipes->areOpen();
            $output = $this->processPipes->readAndWrite($running, '\\' !== \DIRECTORY_SEPARATOR || !$running);
            foreach ($output as $type => $data) {
                if (3 !== $type) {
                    $ready = $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data) || $ready;
                } elseif (!isset($this->fallbackStatus['signaled'])) {
                    $this->fallbackStatus['exitcode'] = (int) $data;
                }
            }
            if ($ready) {
                return \true;
            }
            if (!$running) {
                return \false;
            }
            \usleep(1000);
        }
    }
    /**
     * Returns the Pid (process identifier), if applicable.
     *
     * @return (int | null) The process id if running, null otherwise
     */
    public function getPid()
    {
        return $this->isRunning() ? $this->processInformation['pid'] : null;
    }
    /**
     * Sends a POSIX signal to the process.
     *
     * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants)
     *
     * @return $this
     *
     * @throws LogicException In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
     * @throws RuntimeException In case of failure
     */
    public function signal(int $signal)
    {
        $this->doSignal($signal, \true);
        return $this;
    }
    /**
     * Disables fetching output and error output from the underlying process.
     *
     * @return $this
     *
     * @throws RuntimeException In case the process is already running
     * @throws LogicException if an idle timeout is set
     */
    public function disableOutput()
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Disabling output while the process is running is not possible.');
        }
        if (null !== $this->idleTimeout) {
            throw new LogicException('Output cannot be disabled while an idle timeout is set.');
        }
        $this->outputDisabled = \true;
        return $this;
    }
    /**
     * Enables fetching output and error output from the underlying process.
     *
     * @return $this
     *
     * @throws RuntimeException In case the process is already running
     */
    public function enableOutput()
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Enabling output while the process is running is not possible.');
        }
        $this->outputDisabled = \false;
        return $this;
    }
    /**
     * Returns true in case the output is disabled, false otherwise.
     *
     * @return bool
     */
    public function isOutputDisabled()
    {
        return $this->outputDisabled;
    }
    /**
     * Returns the current output of the process (STDOUT).
     *
     * @return string
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getOutput()
    {
        $this->readPipesForOutput(__FUNCTION__);
        if (\false === ($ret = \stream_get_contents($this->stdout, -1, 0))) {
            return '';
        }
        return $ret;
    }
    /**
    * Returns the output incrementally.
    *
    * In comparison with the getOutput method which always return the whole
    output, this one returns the new output since the last call.
    *
    * @return string
    *
    * @throws LogicException in case the output has been disabled
    * @throws LogicException In case the process is not started
    */
    public function getIncrementalOutput()
    {
        $this->readPipesForOutput(__FUNCTION__);
        $latest = \stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
        $this->incrementalOutputOffset = \ftell($this->stdout);
        if (\false === $latest) {
            return '';
        }
        return $latest;
    }
    /**
     * Returns an iterator to the output of the process, with the output type as keys (Process::OUT/ERR).
     *
     * @param int $flags A bit field of Process::ITER_* flags
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     *
     * @return \Generator<string, string>
     */
    #[\ReturnTypeWillChange]
    public function getIterator(int $flags = 0)
    {
        $this->readPipesForOutput(__FUNCTION__, \false);
        $clearOutput = !(self::ITER_KEEP_OUTPUT & $flags);
        $blocking = !(self::ITER_NON_BLOCKING & $flags);
        $yieldOut = !(self::ITER_SKIP_OUT & $flags);
        $yieldErr = !(self::ITER_SKIP_ERR & $flags);
        while (null !== $this->callback || $yieldOut && !\feof($this->stdout) || $yieldErr && !\feof($this->stderr)) {
            if ($yieldOut) {
                $out = \stream_get_contents($this->stdout, -1, $this->incrementalOutputOffset);
                if (isset($out[0])) {
                    if ($clearOutput) {
                        $this->clearOutput();
                    } else {
                        $this->incrementalOutputOffset = \ftell($this->stdout);
                    }
                    (yield self::OUT => $out);
                }
            }
            if ($yieldErr) {
                $err = \stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
                if (isset($err[0])) {
                    if ($clearOutput) {
                        $this->clearErrorOutput();
                    } else {
                        $this->incrementalErrorOutputOffset = \ftell($this->stderr);
                    }
                    (yield self::ERR => $err);
                }
            }
            if (!$blocking && !isset($out[0]) && !isset($err[0])) {
                (yield self::OUT => '');
            }
            $this->checkTimeout();
            $this->readPipesForOutput(__FUNCTION__, $blocking);
        }
    }
    /**
     * Clears the process output.
     *
     * @return $this
     */
    public function clearOutput()
    {
        \ftruncate($this->stdout, 0);
        \fseek($this->stdout, 0);
        $this->incrementalOutputOffset = 0;
        return $this;
    }
    /**
     * Returns the current error output of the process (STDERR).
     *
     * @return string
     *
     * @throws LogicException in case the output has been disabled
     * @throws LogicException In case the process is not started
     */
    public function getErrorOutput()
    {
        $this->readPipesForOutput(__FUNCTION__);
        if (\false === ($ret = \stream_get_contents($this->stderr, -1, 0))) {
            return '';
        }
        return $ret;
    }
    /**
    * Returns the errorOutput incrementally.
    *
    * In comparison with the getErrorOutput method which always return the
    whole error output, this one returns the new error output since the last
    call.
    *
    * @return string
    *
    * @throws LogicException in case the output has been disabled
    * @throws LogicException In case the process is not started
    */
    public function getIncrementalErrorOutput()
    {
        $this->readPipesForOutput(__FUNCTION__);
        $latest = \stream_get_contents($this->stderr, -1, $this->incrementalErrorOutputOffset);
        $this->incrementalErrorOutputOffset = \ftell($this->stderr);
        if (\false === $latest) {
            return '';
        }
        return $latest;
    }
    /**
     * Clears the process output.
     *
     * @return $this
     */
    public function clearErrorOutput()
    {
        \ftruncate($this->stderr, 0);
        \fseek($this->stderr, 0);
        $this->incrementalErrorOutputOffset = 0;
        return $this;
    }
    /**
     * Returns the exit code returned by the process.
     *
     * @return (int | null) The exit status code, null if the Process is not terminated
     */
    public function getExitCode()
    {
        $this->updateStatus(\false);
        return $this->exitcode;
    }
    /**
    * Returns a string representation for the exit code returned by the process.
    *
    * This method relies on the Unix exit code status standardization
    and might not be relevant for other operating systems.
    *
    * @return (string | null) A string representation for the exit status code, null if the Process is not terminated
    *
    * @see http://tldp.org/LDP/abs/html/exitcodes.html
    * @see http://en.wikipedia.org/wiki/Unix_signal
    */
    public function getExitCodeText()
    {
        if (null === ($exitcode = $this->getExitCode())) {
            return null;
        }
        return self::$exitCodes[$exitcode] ?? 'Unknown error';
    }
    /**
     * Checks if the process ended successfully.
     *
     * @return bool
     */
    public function isSuccessful()
    {
        return 0 === $this->getExitCode();
    }
    /**
     * Returns true if the child process has been terminated by an uncaught signal.
     *
     * It always returns false on Windows.
     *
     * @return bool
     *
     * @throws LogicException In case the process is not terminated
     */
    public function hasBeenSignaled()
    {
        $this->requireProcessIsTerminated(__FUNCTION__);
        return $this->processInformation['signaled'];
    }
    /**
     * Returns the number of the signal that caused the child process to terminate its execution.
     *
     * It is only meaningful if hasBeenSignaled() returns true.
     *
     * @return int
     *
     * @throws RuntimeException In case --enable-sigchild is activated
     * @throws LogicException In case the process is not terminated
     */
    public function getTermSignal()
    {
        $this->requireProcessIsTerminated(__FUNCTION__);
        if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) {
            throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal cannot be retrieved.');
        }
        return $this->processInformation['termsig'];
    }
    /**
     * Returns true if the child process has been stopped by a signal.
     *
     * It always returns false on Windows.
     *
     * @return bool
     *
     * @throws LogicException In case the process is not terminated
     */
    public function hasBeenStopped()
    {
        $this->requireProcessIsTerminated(__FUNCTION__);
        return $this->processInformation['stopped'];
    }
    /**
     * Returns the number of the signal that caused the child process to stop its execution.
     *
     * It is only meaningful if hasBeenStopped() returns true.
     *
     * @return int
     *
     * @throws LogicException In case the process is not terminated
     */
    public function getStopSignal()
    {
        $this->requireProcessIsTerminated(__FUNCTION__);
        return $this->processInformation['stopsig'];
    }
    /**
     * Checks if the process is currently running.
     *
     * @return bool
     */
    public function isRunning()
    {
        if (self::STATUS_STARTED !== $this->status) {
            return \false;
        }
        $this->updateStatus(\false);
        return $this->processInformation['running'];
    }
    /**
     * Checks if the process has been started with no regard to the current state.
     *
     * @return bool
     */
    public function isStarted()
    {
        return self::STATUS_READY != $this->status;
    }
    /**
     * Checks if the process is terminated.
     *
     * @return bool
     */
    public function isTerminated()
    {
        $this->updateStatus(\false);
        return self::STATUS_TERMINATED == $this->status;
    }
    /**
     * Gets the process status.
     *
     * The status is one of: ready, started, terminated.
     *
     * @return string
     */
    public function getStatus()
    {
        $this->updateStatus(\false);
        return $this->status;
    }
    /**
     * Stops the process.
     *
     * @param (int | float) $timeout The timeout in seconds
     * @param int $signal A POSIX signal to send in case the process has not stop at timeout, default is SIGKILL (9)
     *
     * @return (int | null) The exit-code of the process or null if it's not running
     */
    public function stop(float $timeout = 10, int $signal = null)
    {
        $timeoutMicro = \microtime(\true) + $timeout;
        if ($this->isRunning()) {
            // given SIGTERM may not be defined and that "proc_terminate" uses the constant value and not the constant itself, we use the same here
            $this->doSignal(15, \false);
            do {
                \usleep(1000);
            } while ($this->isRunning() && \microtime(\true) < $timeoutMicro);
            if ($this->isRunning()) {
                // Avoid exception here: process is supposed to be running, but it might have stopped just
                // after this line. In any case, let's silently discard the error, we cannot do anything.
                $this->doSignal($signal ?: 9, \false);
            }
        }
        if ($this->isRunning()) {
            if (isset($this->fallbackStatus['pid'])) {
                unset($this->fallbackStatus['pid']);
                return $this->stop(0, $signal);
            }
            $this->close();
        }
        return $this->exitcode;
    }
    /**
     * Adds a line to the STDOUT stream.
     *
     * @internal
     */
    public function addOutput(string $line)
    {
        $this->lastOutputTime = \microtime(\true);
        \fseek($this->stdout, 0, \SEEK_END);
        \fwrite($this->stdout, $line);
        \fseek($this->stdout, $this->incrementalOutputOffset);
    }
    /**
     * Adds a line to the STDERR stream.
     *
     * @internal
     */
    public function addErrorOutput(string $line)
    {
        $this->lastOutputTime = \microtime(\true);
        \fseek($this->stderr, 0, \SEEK_END);
        \fwrite($this->stderr, $line);
        \fseek($this->stderr, $this->incrementalErrorOutputOffset);
    }
    /**
     * Gets the last output time in seconds.
     *
     * @return (float | null)
     */
    public function getLastOutputTime() : ?float
    {
        return $this->lastOutputTime;
    }
    /**
     * Gets the command line to be executed.
     *
     * @return string
     */
    public function getCommandLine()
    {
        return \is_array($this->commandline) ? \implode(' ', \array_map([$this, 'escapeArgument'], $this->commandline)) : $this->commandline;
    }
    /**
     * Gets the process timeout in seconds (max. runtime).
     *
     * @return (float | null)
     */
    public function getTimeout()
    {
        return $this->timeout;
    }
    /**
     * Gets the process idle timeout in seconds (max. time since last output).
     *
     * @return (float | null)
     */
    public function getIdleTimeout()
    {
        return $this->idleTimeout;
    }
    /**
     * Sets the process timeout (max. runtime) in seconds.
     *
     * To disable the timeout, set this value to null.
     *
     * @return $this
     *
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setTimeout(?float $timeout)
    {
        $this->timeout = $this->validateTimeout($timeout);
        return $this;
    }
    /**
     * Sets the process idle timeout (max. time since last output) in seconds.
     *
     * To disable the timeout, set this value to null.
     *
     * @return $this
     *
     * @throws LogicException if the output is disabled
     * @throws InvalidArgumentException if the timeout is negative
     */
    public function setIdleTimeout(?float $timeout)
    {
        if (null !== $timeout && $this->outputDisabled) {
            throw new LogicException('Idle timeout cannot be set while the output is disabled.');
        }
        $this->idleTimeout = $this->validateTimeout($timeout);
        return $this;
    }
    /**
     * Enables or disables the TTY mode.
     *
     * @return $this
     *
     * @throws RuntimeException In case the TTY mode is not supported
     */
    public function setTty(bool $tty)
    {
        if ('\\' === \DIRECTORY_SEPARATOR && $tty) {
            throw new RuntimeException('TTY mode is not supported on Windows platform.');
        }
        if ($tty && !self::isTtySupported()) {
            throw new RuntimeException('TTY mode requires /dev/tty to be read/writable.');
        }
        $this->tty = $tty;
        return $this;
    }
    /**
     * Checks if the TTY mode is enabled.
     *
     * @return bool
     */
    public function isTty()
    {
        return $this->tty;
    }
    /**
     * Sets PTY mode.
     *
     * @return $this
     */
    public function setPty(bool $bool)
    {
        $this->pty = $bool;
        return $this;
    }
    /**
     * Returns PTY state.
     *
     * @return bool
     */
    public function isPty()
    {
        return $this->pty;
    }
    /**
     * Gets the working directory.
     *
     * @return (string | null)
     */
    public function getWorkingDirectory()
    {
        if (null === $this->cwd) {
            // getcwd() will return false if any one of the parent directories does not have
            // the readable or search mode set, even if the current directory does
            return \getcwd() ?: null;
        }
        return $this->cwd;
    }
    /**
     * Sets the current working directory.
     *
     * @return $this
     */
    public function setWorkingDirectory(string $cwd)
    {
        $this->cwd = $cwd;
        return $this;
    }
    /**
     * Gets the environment variables.
     *
     * @return array
     */
    public function getEnv()
    {
        return $this->env;
    }
    /**
     * Sets the environment variables.
     *
     * @param array<(string | \Stringable)> $env The new environment variables
     *
     * @return $this
     */
    public function setEnv(array $env)
    {
        $this->env = $env;
        return $this;
    }
    /**
     * Gets the Process input.
     *
     * @return (resource | string | \Iterator | null)
     */
    public function getInput()
    {
        return $this->input;
    }
    /**
     * Sets the input.
     *
     * This content will be passed to the underlying process standard input.
     *
     * @param (string | int | float | bool | resource | \Traversable | null) $input The content
     *
     * @return $this
     *
     * @throws LogicException In case the process is running
     */
    public function setInput($input)
    {
        if ($this->isRunning()) {
            throw new LogicException('Input cannot be set while the process is running.');
        }
        $this->input = ProcessUtils::validateInput(__METHOD__, $input);
        return $this;
    }
    /**
    * Performs a check between the timeout definition and the time the process started.
    *
    * In case you run a background process (with the start method), you should
    trigger this method regularly to ensure the process timeout
    *
    * @throws ProcessTimedOutException In case the timeout was reached
    */
    public function checkTimeout()
    {
        if (self::STATUS_STARTED !== $this->status) {
            return;
        }
        if (null !== $this->timeout && $this->timeout < \microtime(\true) - $this->starttime) {
            $this->stop(0);
            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_GENERAL);
        }
        if (null !== $this->idleTimeout && $this->idleTimeout < \microtime(\true) - $this->lastOutputTime) {
            $this->stop(0);
            throw new ProcessTimedOutException($this, ProcessTimedOutException::TYPE_IDLE);
        }
    }
    /**
     * @throws LogicException in case process is not started
     */
    public function getStartTime() : float
    {
        if (!$this->isStarted()) {
            throw new LogicException('Start time is only available after process start.');
        }
        return $this->starttime;
    }
    /**
    * Defines options to pass to the underlying proc_open().
    *
    * @see https://php.net/proc_open for the options supported by PHP.
    *
    * Enabling the "create_new_console" option allows a subprocess to continue
    to run after the main process exited, on both Windows and *nix
    */
    public function setOptions(array $options)
    {
        if ($this->isRunning()) {
            throw new RuntimeException('Setting options while the process is running is not possible.');
        }
        $defaultOptions = $this->options;
        $existingOptions = ['blocking_pipes', 'create_process_group', 'create_new_console'];
        foreach ($options as $key => $value) {
            if (!\in_array($key, $existingOptions)) {
                $this->options = $defaultOptions;
                throw new LogicException(\sprintf('Invalid option "%s" passed to "%s()". Supported options are "%s".', $key, __METHOD__, \implode('", "', $existingOptions)));
            }
            $this->options[$key] = $value;
        }
    }
    /**
     * Returns whether TTY is supported on the current operating system.
     */
    public static function isTtySupported() : bool
    {
        static $isTtySupported;
        if (null === $isTtySupported) {
            $isTtySupported = (bool) @\proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes);
        }
        return $isTtySupported;
    }
    /**
     * Returns whether PTY is supported on the current operating system.
     *
     * @return bool
     */
    public static function isPtySupported()
    {
        static $result;
        if (null !== $result) {
            return $result;
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            return $result = \false;
        }
        return $result = (bool) @\proc_open('echo 1 >/dev/null', [['pty'], ['pty'], ['pty']], $pipes);
    }
    /**
     * Creates the descriptors needed by the proc_open.
     */
    private function getDescriptors() : array
    {
        if ($this->input instanceof \Iterator) {
            $this->input->rewind();
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $this->processPipes = new WindowsPipes($this->input, !$this->outputDisabled || $this->hasCallback);
        } else {
            $this->processPipes = new UnixPipes($this->isTty(), $this->isPty(), $this->input, !$this->outputDisabled || $this->hasCallback);
        }
        return $this->processPipes->getDescriptors();
    }
    /**
    * Builds up the callback used by wait().
    *
    * The callbacks adds all occurred output to the specific buffer and calls
    the user callback (if present) with the received output.
    *
    * @param (callable | null) $callback The user defined PHP callback
    *
    * @return \Closure
    */
    protected function buildCallback(callable $callback = null)
    {
        if ($this->outputDisabled) {
            return function ($type, $data) use($callback) : bool {
                return null !== $callback && $callback($type, $data);
            };
        }
        $out = self::OUT;
        return function ($type, $data) use($callback, $out) : bool {
            if ($out == $type) {
                $this->addOutput($data);
            } else {
                $this->addErrorOutput($data);
            }
            return null !== $callback && $callback($type, $data);
        };
    }
    /**
     * Updates the status of the process, reads pipes.
     *
     * @param bool $blocking Whether to use a blocking read call
     */
    protected function updateStatus(bool $blocking)
    {
        if (self::STATUS_STARTED !== $this->status) {
            return;
        }
        $this->processInformation = \proc_get_status($this->process);
        $running = $this->processInformation['running'];
        $this->readPipes($running && $blocking, '\\' !== \DIRECTORY_SEPARATOR || !$running);
        if ($this->fallbackStatus && $this->isSigchildEnabled()) {
            $this->processInformation = $this->fallbackStatus + $this->processInformation;
        }
        if (!$running) {
            $this->close();
        }
    }
    /**
     * Returns whether PHP has been compiled with the '--enable-sigchild' option or not.
     *
     * @return bool
     */
    protected function isSigchildEnabled()
    {
        if (null !== self::$sigchild) {
            return self::$sigchild;
        }
        if (!\function_exists('phpinfo')) {
            return self::$sigchild = \false;
        }
        \ob_start();
        \phpinfo(\INFO_GENERAL);
        return self::$sigchild = \str_contains(\ob_get_clean(), '--enable-sigchild');
    }
    /**
     * Reads pipes for the freshest output.
     *
     * @param string $caller The name of the method that needs fresh outputs
     * @param bool $blocking Whether to use blocking calls or not
     *
     * @throws LogicException in case output has been disabled or process is not started
     */
    private function readPipesForOutput(string $caller, bool $blocking = \false)
    {
        if ($this->outputDisabled) {
            throw new LogicException('Output has been disabled.');
        }
        $this->requireProcessIsStarted($caller);
        $this->updateStatus($blocking);
    }
    /**
     * Validates and returns the filtered timeout.
     *
     * @throws InvalidArgumentException if the given timeout is a negative number
     */
    private function validateTimeout(?float $timeout) : ?float
    {
        $timeout = (float) $timeout;
        if (0.0 === $timeout) {
            $timeout = null;
        } elseif ($timeout < 0) {
            throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.');
        }
        return $timeout;
    }
    /**
     * Reads pipes, executes callback.
     *
     * @param bool $blocking Whether to use blocking calls or not
     * @param bool $close Whether to close file handles or not
     */
    private function readPipes(bool $blocking, bool $close)
    {
        $result = $this->processPipes->readAndWrite($blocking, $close);
        $callback = $this->callback;
        foreach ($result as $type => $data) {
            if (3 !== $type) {
                $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data);
            } elseif (!isset($this->fallbackStatus['signaled'])) {
                $this->fallbackStatus['exitcode'] = (int) $data;
            }
        }
    }
    /**
     * Closes process resource, closes file handles, sets the exitcode.
     *
     * @return int The exitcode
     */
    private function close() : int
    {
        $this->processPipes->close();
        if (\is_resource($this->process)) {
            \proc_close($this->process);
        }
        $this->exitcode = $this->processInformation['exitcode'];
        $this->status = self::STATUS_TERMINATED;
        if (-1 === $this->exitcode) {
            if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) {
                // if process has been signaled, no exitcode but a valid termsig, apply Unix convention
                $this->exitcode = 128 + $this->processInformation['termsig'];
            } elseif ($this->isSigchildEnabled()) {
                $this->processInformation['signaled'] = \true;
                $this->processInformation['termsig'] = -1;
            }
        }
        // Free memory from self-reference callback created by buildCallback
        // Doing so in other contexts like __destruct or by garbage collector is ineffective
        // Now pipes are closed, so the callback is no longer necessary
        $this->callback = null;
        return $this->exitcode;
    }
    /**
     * Resets data related to the latest run of the process.
     */
    private function resetProcessData()
    {
        $this->starttime = null;
        $this->callback = null;
        $this->exitcode = null;
        $this->fallbackStatus = [];
        $this->processInformation = null;
        $this->stdout = \fopen('php://temp/maxmemory:' . 1024 * 1024, 'w+');
        $this->stderr = \fopen('php://temp/maxmemory:' . 1024 * 1024, 'w+');
        $this->process = null;
        $this->latestSignal = null;
        $this->status = self::STATUS_READY;
        $this->incrementalOutputOffset = 0;
        $this->incrementalErrorOutputOffset = 0;
    }
    /**
     * Sends a POSIX signal to the process.
     *
     * @param int $signal A valid POSIX signal (see https://php.net/pcntl.constants)
     * @param bool $throwException Whether to throw exception in case signal failed
     *
     * @return bool
     *
     * @throws LogicException In case the process is not running
     * @throws RuntimeException In case --enable-sigchild is activated and the process can't be killed
     * @throws RuntimeException In case of failure
     */
    private function doSignal(int $signal, bool $throwException) : bool
    {
        if (null === ($pid = $this->getPid())) {
            if ($throwException) {
                throw new LogicException('Cannot send signal on a non running process.');
            }
            return \false;
        }
        if ('\\' === \DIRECTORY_SEPARATOR) {
            \exec(\sprintf('taskkill /F /T /PID %d 2>&1', $pid), $output, $exitCode);
            if ($exitCode && $this->isRunning()) {
                if ($throwException) {
                    throw new RuntimeException(\sprintf('Unable to kill the process (%s).', \implode(' ', $output)));
                }
                return \false;
            }
        } else {
            if (!$this->isSigchildEnabled()) {
                $ok = @\proc_terminate($this->process, $signal);
            } elseif (\function_exists('posix_kill')) {
                $ok = @\posix_kill($pid, $signal);
            } elseif ($ok = \proc_open(\sprintf('kill -%d %d', $signal, $pid), [2 => ['pipe', 'w']], $pipes)) {
                $ok = \false === \fgets($pipes[2]);
            }
            if (!$ok) {
                if ($throwException) {
                    throw new RuntimeException(\sprintf('Error while sending signal "%s".', $signal));
                }
                return \false;
            }
        }
        $this->latestSignal = $signal;
        $this->fallbackStatus['signaled'] = \true;
        $this->fallbackStatus['exitcode'] = -1;
        $this->fallbackStatus['termsig'] = $this->latestSignal;
        return \true;
    }
    /**
     *
     */
    private function prepareWindowsCommandLine(string $cmd, array &$env) : string
    {
        $uid = \uniqid('', \true);
        $varCount = 0;
        $varCache = [];
        $cmd = \preg_replace_callback('/"(?:(
                [^"%!^]*+
                (?:
                    (?: !LF! | "(?:\\^[%!^])?+" )
                    [^"%!^]*+
                )++
            ) | [^"]*+ )"/x', function ($m) use(&$env, &$varCache, &$varCount, $uid) {
            if (!isset($m[1])) {
                return $m[0];
            }
            if (isset($varCache[$m[0]])) {
                return $varCache[$m[0]];
            }
            if (\str_contains($value = $m[1], "\x00")) {
                $value = \str_replace("\x00", '?', $value);
            }
            if (\false === \strpbrk($value, "\"%!\n")) {
                return '"' . $value . '"';
            }
            $value = \str_replace(['!LF!', '"^!"', '"^%"', '"^^"', '""'], ["\n", '!', '%', '^', '"'], $value);
            $value = '"' . \preg_replace('/(\\\\*)"/', '$1$1\\"', $value) . '"';
            $var = $uid . ++$varCount;
            $env[$var] = $value;
            return $varCache[$m[0]] = '!' . $var . '!';
        }, $cmd);
        $cmd = 'cmd /V:ON /E:ON /D /C (' . \str_replace("\n", ' ', $cmd) . ')';
        foreach ($this->processPipes->getFiles() as $offset => $filename) {
            $cmd .= ' ' . $offset . '>"' . $filename . '"';
        }
        return $cmd;
    }
    /**
     * Ensures the process is running or terminated, throws a LogicException if the process has a not started.
     *
     * @throws LogicException if the process has not run
     */
    private function requireProcessIsStarted(string $functionName)
    {
        if (!$this->isStarted()) {
            throw new LogicException(\sprintf('Process must be started before calling "%s()".', $functionName));
        }
    }
    /**
     * Ensures the process is terminated, throws a LogicException if the process has a status different than "terminated".
     *
     * @throws LogicException if the process is not yet terminated
     */
    private function requireProcessIsTerminated(string $functionName)
    {
        if (!$this->isTerminated()) {
            throw new LogicException(\sprintf('Process must be terminated before calling "%s()".', $functionName));
        }
    }
    /**
     * Escapes a string to be used as a shell argument.
     */
    private function escapeArgument(?string $argument) : string
    {
        if ('' === $argument || null === $argument) {
            return '""';
        }
        if ('\\' !== \DIRECTORY_SEPARATOR) {
            return "'" . \str_replace("'", "'\\''", $argument) . "'";
        }
        if (\str_contains($argument, "\x00")) {
            $argument = \str_replace("\x00", '?', $argument);
        }
        if (!\preg_match('/[\\/()%!^"<>&|\\s]/', $argument)) {
            return $argument;
        }
        $argument = \preg_replace('/(\\\\+)$/', '$1$1', $argument);
        return '"' . \str_replace(['"', '^', '%', '!', "\n"], ['""', '"^^"', '"^%"', '"^!"', '!LF!'], $argument) . '"';
    }
    /**
     *
     */
    private function replacePlaceholders(string $commandline, array $env)
    {
        return \preg_replace_callback('/"\\$\\{:([_a-zA-Z]++[_a-zA-Z0-9]*+)\\}"/', function ($matches) use($commandline, $env) {
            if (!isset($env[$matches[1]]) || \false === $env[$matches[1]]) {
                throw new InvalidArgumentException(\sprintf('Command line is missing a value for parameter "%s": ', $matches[1]) . $commandline);
            }
            return $this->escapeArgument($env[$matches[1]]);
        }, $commandline);
    }
    /**
     *
     */
    private function getDefaultEnv() : array
    {
        $env = \getenv();
        $env = ('\\' === \DIRECTORY_SEPARATOR ? \array_intersect_ukey($env, $_SERVER, 'strcasecmp') : \array_intersect_key($env, $_SERVER)) ?: $env;
        return $_ENV + ('\\' === \DIRECTORY_SEPARATOR ? \array_diff_ukey($env, $_ENV, 'strcasecmp') : $env);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Process;

use PhabelVendor\Symfony\Component\Process\Exception\InvalidArgumentException;
/**
 * ProcessUtils is a bunch of utility methods.
 *
 * This class contains static methods only and is not meant to be instantiated.
 *
 * @author Martin HasoÅˆ <martin.hason@gmail.com>
 */
class ProcessUtils
{
    /**
     * This class should not be instantiated.
     */
    private function __construct()
    {
    }
    /**
     * Validates and normalizes a Process input.
     *
     * @param string $caller The name of method call that validates the input
     * @param mixed $input The input to validate
     *
     * @return mixed
     *
     * @throws InvalidArgumentException In case the input is not valid
     */
    public static function validateInput(string $caller, $input)
    {
        if (null !== $input) {
            if (\is_resource($input)) {
                return $input;
            }
            if (\is_string($input)) {
                return $input;
            }
            if (\is_scalar($input)) {
                return (string) $input;
            }
            if ($input instanceof Process) {
                return $input->getIterator($input::ITER_SKIP_ERR);
            }
            if ($input instanceof \Iterator) {
                return $input;
            }
            if ($input instanceof \Traversable) {
                return new \IteratorIterator($input);
            }
            throw new InvalidArgumentException(\sprintf('"%s" only accepts strings, Traversable objects or stream resources.', $caller));
        }
        return $input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Intl\Normalizer;

/**
 * Normalizer is a PHP fallback implementation of the Normalizer class provided by the intl extension.
 *
 * It has been validated with Unicode 6.3 Normalization Conformance Test.
 * See http://www.unicode.org/reports/tr15/ for detailed info about Unicode normalizations.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
class Normalizer
{
    public const FORM_D = \Normalizer::FORM_D;
    public const FORM_KD = \Normalizer::FORM_KD;
    public const FORM_C = \Normalizer::FORM_C;
    public const FORM_KC = \Normalizer::FORM_KC;
    public const NFD = \Normalizer::NFD;
    public const NFKD = \Normalizer::NFKD;
    public const NFC = \Normalizer::NFC;
    public const NFKC = \Normalizer::NFKC;
    private static $C;
    private static $D;
    private static $KD;
    private static $cC;
    private static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
    private static $ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T<D4}B{8FwR67UGN;JzV#HOW_&!K?XQ%Y\\\tZ+~^\$@`\x00\x01\x02\x03\x04\x05\x06\x07\x08\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
    /**
     *
     */
    public static function isNormalized(string $s, int $form = self::FORM_C)
    {
        if (!\in_array($form, [self::NFD, self::NFKD, self::NFC, self::NFKC])) {
            return false;
        }
        if (!isset($s[\Phabel\Target\Php80\Polyfill::strspn($s, self::$ASCII)])) {
            return true;
        }
        if (self::NFC == $form && preg_match('//u', $s) && !preg_match('/[^\\x00-\\x{2FF}]/u', $s)) {
            return true;
        }
        return self::normalize($s, $form) === $s;
    }
    /**
     *
     */
    public static function normalize(string $s, int $form = self::FORM_C)
    {
        if (!preg_match('//u', $s)) {
            return false;
        }
        switch ($form) {
            case self::NFC:
                $C = true;
                $K = false;
                break;
            case self::NFD:
                $C = false;
                $K = false;
                break;
            case self::NFKC:
                $C = true;
                $K = true;
                break;
            case self::NFKD:
                $C = false;
                $K = true;
                break;
            default:
                if (\defined('Normalizer::NONE') && \Normalizer::NONE == $form) {
                    return $s;
                }
                if (80000 > \PHP_VERSION_ID) {
                    return false;
                }
                throw new \ValueError('normalizer_normalize(): Argument #2 ($form) must be a a valid normalization form');
        }
        if ('' === $s) {
            return '';
        }
        if ($K && null === self::$KD) {
            self::$KD = self::getData('compatibilityDecomposition');
        }
        if (null === self::$D) {
            self::$D = self::getData('canonicalDecomposition');
            self::$cC = self::getData('combiningClass');
        }
        if (null !== ($mbEncoding = 2 & (int) ini_get('mbstring.func_overload') ? mb_internal_encoding() : null)) {
            mb_internal_encoding('8bit');
        }
        $r = self::decompose($s, $K);
        if ($C) {
            if (null === self::$C) {
                self::$C = self::getData('canonicalComposition');
            }
            $r = self::recompose($r);
        }
        if (null !== $mbEncoding) {
            mb_internal_encoding($mbEncoding);
        }
        return $r;
    }
    /**
     *
     */
    private static function recompose($s)
    {
        $ASCII = self::$ASCII;
        $compMap = self::$C;
        $combClass = self::$cC;
        $ulenMask = self::$ulenMask;
        $result = $tail = '';
        $i = $s[0] < "\x80" ? 1 : $ulenMask[$s[0] & "\xf0"];
        $len = \strlen($s);
        $lastUchr = \Phabel\Target\Php80\Polyfill::substr($s, 0, $i);
        $lastUcls = isset($combClass[$lastUchr]) ? 256 : 0;
        while ($i < $len) {
            if ($s[$i] < "\x80") {
                // ASCII chars
                if ($tail) {
                    $lastUchr .= $tail;
                    $tail = '';
                }
                if ($j = \Phabel\Target\Php80\Polyfill::strspn($s, $ASCII, $i + 1)) {
                    $lastUchr .= \Phabel\Target\Php80\Polyfill::substr($s, $i, $j);
                    $i += $j;
                }
                $result .= $lastUchr;
                $lastUchr = $s[$i];
                $lastUcls = 0;
                ++$i;
                continue;
            }
            $ulen = $ulenMask[$s[$i] & "\xf0"];
            $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i, $ulen);
            if ($lastUchr < "á„€" || "á„’" < $lastUchr || $uchr < "á…¡" || "á…µ" < $uchr || $lastUcls) {
                // Table lookup and combining chars composition
                $ucls = $combClass[$uchr] ?? 0;
                if (isset($compMap[$lastUchr . $uchr]) && (!$lastUcls || $lastUcls < $ucls)) {
                    $lastUchr = $compMap[$lastUchr . $uchr];
                } elseif ($lastUcls = $ucls) {
                    $tail .= $uchr;
                } else {
                    if ($tail) {
                        $lastUchr .= $tail;
                        $tail = '';
                    }
                    $result .= $lastUchr;
                    $lastUchr = $uchr;
                }
            } else {
                // Hangul chars
                $L = \ord($lastUchr[2]) - 0x80;
                $V = \ord($uchr[2]) - 0xa1;
                $T = 0;
                $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i + $ulen, 3);
                if ("á†§" <= $uchr && $uchr <= "á‡‚") {
                    $T = \ord($uchr[2]) - 0xa7;
                    0 > $T && ($T += 0x40);
                    $ulen += 3;
                }
                $L = 0xac00 + ($L * 21 + $V) * 28 + $T;
                $lastUchr = \chr(0xe0 | $L >> 12) . \chr(0x80 | $L >> 6 & 0x3f) . \chr(0x80 | $L & 0x3f);
            }
            $i += $ulen;
        }
        return $result . $lastUchr . $tail;
    }
    /**
     *
     */
    private static function decompose($s, $c)
    {
        $result = '';
        $ASCII = self::$ASCII;
        $decompMap = self::$D;
        $combClass = self::$cC;
        $ulenMask = self::$ulenMask;
        if ($c) {
            $compatMap = self::$KD;
        }
        $c = [];
        $i = 0;
        $len = \strlen($s);
        while ($i < $len) {
            if ($s[$i] < "\x80") {
                // ASCII chars
                if ($c) {
                    ksort($c);
                    $result .= implode('', $c);
                    $c = [];
                }
                $j = 1 + \Phabel\Target\Php80\Polyfill::strspn($s, $ASCII, $i + 1);
                $result .= \Phabel\Target\Php80\Polyfill::substr($s, $i, $j);
                $i += $j;
                continue;
            }
            $ulen = $ulenMask[$s[$i] & "\xf0"];
            $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i, $ulen);
            $i += $ulen;
            if ($uchr < "ê°€" || "íž£" < $uchr) {
                // Table lookup
                if ($uchr !== ($j = $compatMap[$uchr] ?? $decompMap[$uchr] ?? $uchr)) {
                    $uchr = $j;
                    $j = \strlen($uchr);
                    $ulen = $uchr[0] < "\x80" ? 1 : $ulenMask[$uchr[0] & "\xf0"];
                    if ($ulen != $j) {
                        // Put trailing chars in $s
                        $j -= $ulen;
                        $i -= $j;
                        if (0 > $i) {
                            $s = str_repeat(' ', -$i) . $s;
                            $len -= $i;
                            $i = 0;
                        }
                        while ($j--) {
                            $s[$i + $j] = $uchr[$ulen + $j];
                        }
                        $uchr = \Phabel\Target\Php80\Polyfill::substr($uchr, 0, $ulen);
                    }
                }
                if (isset($combClass[$uchr])) {
                    // Combining chars, for sorting
                    if (!isset($c[$combClass[$uchr]])) {
                        $c[$combClass[$uchr]] = '';
                    }
                    $c[$combClass[$uchr]] .= $uchr;
                    continue;
                }
            } else {
                // Hangul chars
                $uchr = unpack('C*', $uchr);
                $j = ($uchr[1] - 224 << 12) + ($uchr[2] - 128 << 6) + $uchr[3] - 0xac80;
                $uchr = "\xe1\x84" . \chr(0x80 + (int) ($j / 588)) . "\xe1\x85" . \chr(0xa1 + (int) ($j % 588 / 28));
                if ($j %= 28) {
                    $uchr .= $j < 25 ? "\xe1\x86" . \chr(0xa7 + $j) : "\xe1\x87" . \chr(0x67 + $j);
                }
            }
            if ($c) {
                ksort($c);
                $result .= implode('', $c);
                $c = [];
            }
            $result .= $uchr;
        }
        if ($c) {
            ksort($c);
            $result .= implode('', $c);
        }
        return $result;
    }
    /**
     *
     */
    private static function getData($file)
    {
        if (file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) {
            return require $file;
        }
        return false;
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Intl\Normalizer as p;
if (!function_exists('normalizer_is_normalized')) {
    /**
     *
     */
    function normalizer_is_normalized(?string $string, ?int $form = p\Normalizer::FORM_C) : bool
    {
        return p\Normalizer::isNormalized((string) $string, (int) $form);
    }
}
if (!function_exists('normalizer_normalize')) {
    /**
     * @return (string | false)
     */
    function normalizer_normalize(?string $string, ?int $form = p\Normalizer::FORM_C)
    {
        $phabelReturn = p\Normalizer::normalize((string) $string, (int) $form);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}<?php

return array('Ã€' => 'AÌ€', 'Ã�' => 'AÌ�', 'Ã‚' => 'AÌ‚', 'Ãƒ' => 'AÌƒ', 'Ã„' => 'AÌˆ', 'Ã…' => 'AÌŠ', 'Ã‡' => 'CÌ§', 'Ãˆ' => 'EÌ€', 'Ã‰' => 'EÌ�', 'ÃŠ' => 'EÌ‚', 'Ã‹' => 'EÌˆ', 'ÃŒ' => 'IÌ€', 'Ã�' => 'IÌ�', 'ÃŽ' => 'IÌ‚', 'Ã�' => 'IÌˆ', 'Ã‘' => 'NÌƒ', 'Ã’' => 'OÌ€', 'Ã“' => 'OÌ�', 'Ã”' => 'OÌ‚', 'Ã•' => 'OÌƒ', 'Ã–' => 'OÌˆ', 'Ã™' => 'UÌ€', 'Ãš' => 'UÌ�', 'Ã›' => 'UÌ‚', 'Ãœ' => 'UÌˆ', 'Ã�' => 'YÌ�', 'Ã ' => 'aÌ€', 'Ã¡' => 'aÌ�', 'Ã¢' => 'aÌ‚', 'Ã£' => 'aÌƒ', 'Ã¤' => 'aÌˆ', 'Ã¥' => 'aÌŠ', 'Ã§' => 'cÌ§', 'Ã¨' => 'eÌ€', 'Ã©' => 'eÌ�', 'Ãª' => 'eÌ‚', 'Ã«' => 'eÌˆ', 'Ã¬' => 'iÌ€', 'Ã­' => 'iÌ�', 'Ã®' => 'iÌ‚', 'Ã¯' => 'iÌˆ', 'Ã±' => 'nÌƒ', 'Ã²' => 'oÌ€', 'Ã³' => 'oÌ�', 'Ã´' => 'oÌ‚', 'Ãµ' => 'oÌƒ', 'Ã¶' => 'oÌˆ', 'Ã¹' => 'uÌ€', 'Ãº' => 'uÌ�', 'Ã»' => 'uÌ‚', 'Ã¼' => 'uÌˆ', 'Ã½' => 'yÌ�', 'Ã¿' => 'yÌˆ', 'Ä€' => 'AÌ„', 'Ä�' => 'aÌ„', 'Ä‚' => 'AÌ†', 'Äƒ' => 'aÌ†', 'Ä„' => 'AÌ¨', 'Ä…' => 'aÌ¨', 'Ä†' => 'CÌ�', 'Ä‡' => 'cÌ�', 'Äˆ' => 'CÌ‚', 'Ä‰' => 'cÌ‚', 'ÄŠ' => 'CÌ‡', 'Ä‹' => 'cÌ‡', 'ÄŒ' => 'CÌŒ', 'Ä�' => 'cÌŒ', 'ÄŽ' => 'DÌŒ', 'Ä�' => 'dÌŒ', 'Ä’' => 'EÌ„', 'Ä“' => 'eÌ„', 'Ä”' => 'EÌ†', 'Ä•' => 'eÌ†', 'Ä–' => 'EÌ‡', 'Ä—' => 'eÌ‡', 'Ä˜' => 'EÌ¨', 'Ä™' => 'eÌ¨', 'Äš' => 'EÌŒ', 'Ä›' => 'eÌŒ', 'Äœ' => 'GÌ‚', 'Ä�' => 'gÌ‚', 'Äž' => 'GÌ†', 'ÄŸ' => 'gÌ†', 'Ä ' => 'GÌ‡', 'Ä¡' => 'gÌ‡', 'Ä¢' => 'GÌ§', 'Ä£' => 'gÌ§', 'Ä¤' => 'HÌ‚', 'Ä¥' => 'hÌ‚', 'Ä¨' => 'IÌƒ', 'Ä©' => 'iÌƒ', 'Äª' => 'IÌ„', 'Ä«' => 'iÌ„', 'Ä¬' => 'IÌ†', 'Ä­' => 'iÌ†', 'Ä®' => 'IÌ¨', 'Ä¯' => 'iÌ¨', 'Ä°' => 'IÌ‡', 'Ä´' => 'JÌ‚', 'Äµ' => 'jÌ‚', 'Ä¶' => 'KÌ§', 'Ä·' => 'kÌ§', 'Ä¹' => 'LÌ�', 'Äº' => 'lÌ�', 'Ä»' => 'LÌ§', 'Ä¼' => 'lÌ§', 'Ä½' => 'LÌŒ', 'Ä¾' => 'lÌŒ', 'Åƒ' => 'NÌ�', 'Å„' => 'nÌ�', 'Å…' => 'NÌ§', 'Å†' => 'nÌ§', 'Å‡' => 'NÌŒ', 'Åˆ' => 'nÌŒ', 'ÅŒ' => 'OÌ„', 'Å�' => 'oÌ„', 'ÅŽ' => 'OÌ†', 'Å�' => 'oÌ†', 'Å�' => 'OÌ‹', 'Å‘' => 'oÌ‹', 'Å”' => 'RÌ�', 'Å•' => 'rÌ�', 'Å–' => 'RÌ§', 'Å—' => 'rÌ§', 'Å˜' => 'RÌŒ', 'Å™' => 'rÌŒ', 'Åš' => 'SÌ�', 'Å›' => 'sÌ�', 'Åœ' => 'SÌ‚', 'Å�' => 'sÌ‚', 'Åž' => 'SÌ§', 'ÅŸ' => 'sÌ§', 'Å ' => 'SÌŒ', 'Å¡' => 'sÌŒ', 'Å¢' => 'TÌ§', 'Å£' => 'tÌ§', 'Å¤' => 'TÌŒ', 'Å¥' => 'tÌŒ', 'Å¨' => 'UÌƒ', 'Å©' => 'uÌƒ', 'Åª' => 'UÌ„', 'Å«' => 'uÌ„', 'Å¬' => 'UÌ†', 'Å­' => 'uÌ†', 'Å®' => 'UÌŠ', 'Å¯' => 'uÌŠ', 'Å°' => 'UÌ‹', 'Å±' => 'uÌ‹', 'Å²' => 'UÌ¨', 'Å³' => 'uÌ¨', 'Å´' => 'WÌ‚', 'Åµ' => 'wÌ‚', 'Å¶' => 'YÌ‚', 'Å·' => 'yÌ‚', 'Å¸' => 'YÌˆ', 'Å¹' => 'ZÌ�', 'Åº' => 'zÌ�', 'Å»' => 'ZÌ‡', 'Å¼' => 'zÌ‡', 'Å½' => 'ZÌŒ', 'Å¾' => 'zÌŒ', 'Æ ' => 'OÌ›', 'Æ¡' => 'oÌ›', 'Æ¯' => 'UÌ›', 'Æ°' => 'uÌ›', 'Ç�' => 'AÌŒ', 'ÇŽ' => 'aÌŒ', 'Ç�' => 'IÌŒ', 'Ç�' => 'iÌŒ', 'Ç‘' => 'OÌŒ', 'Ç’' => 'oÌŒ', 'Ç“' => 'UÌŒ', 'Ç”' => 'uÌŒ', 'Ç•' => 'UÌˆÌ„', 'Ç–' => 'uÌˆÌ„', 'Ç—' => 'UÌˆÌ�', 'Ç˜' => 'uÌˆÌ�', 'Ç™' => 'UÌˆÌŒ', 'Çš' => 'uÌˆÌŒ', 'Ç›' => 'UÌˆÌ€', 'Çœ' => 'uÌˆÌ€', 'Çž' => 'AÌˆÌ„', 'ÇŸ' => 'aÌˆÌ„', 'Ç ' => 'AÌ‡Ì„', 'Ç¡' => 'aÌ‡Ì„', 'Ç¢' => 'Ã†Ì„', 'Ç£' => 'Ã¦Ì„', 'Ç¦' => 'GÌŒ', 'Ç§' => 'gÌŒ', 'Ç¨' => 'KÌŒ', 'Ç©' => 'kÌŒ', 'Çª' => 'OÌ¨', 'Ç«' => 'oÌ¨', 'Ç¬' => 'OÌ¨Ì„', 'Ç­' => 'oÌ¨Ì„', 'Ç®' => 'Æ·ÌŒ', 'Ç¯' => 'Ê’ÌŒ', 'Ç°' => 'jÌŒ', 'Ç´' => 'GÌ�', 'Çµ' => 'gÌ�', 'Ç¸' => 'NÌ€', 'Ç¹' => 'nÌ€', 'Çº' => 'AÌŠÌ�', 'Ç»' => 'aÌŠÌ�', 'Ç¼' => 'Ã†Ì�', 'Ç½' => 'Ã¦Ì�', 'Ç¾' => 'Ã˜Ì�', 'Ç¿' => 'Ã¸Ì�', 'È€' => 'AÌ�', 'È�' => 'aÌ�', 'È‚' => 'AÌ‘', 'Èƒ' => 'aÌ‘', 'È„' => 'EÌ�', 'È…' => 'eÌ�', 'È†' => 'EÌ‘', 'È‡' => 'eÌ‘', 'Èˆ' => 'IÌ�', 'È‰' => 'iÌ�', 'ÈŠ' => 'IÌ‘', 'È‹' => 'iÌ‘', 'ÈŒ' => 'OÌ�', 'È�' => 'oÌ�', 'ÈŽ' => 'OÌ‘', 'È�' => 'oÌ‘', 'È�' => 'RÌ�', 'È‘' => 'rÌ�', 'È’' => 'RÌ‘', 'È“' => 'rÌ‘', 'È”' => 'UÌ�', 'È•' => 'uÌ�', 'È–' => 'UÌ‘', 'È—' => 'uÌ‘', 'È˜' => 'SÌ¦', 'È™' => 'sÌ¦', 'Èš' => 'TÌ¦', 'È›' => 'tÌ¦', 'Èž' => 'HÌŒ', 'ÈŸ' => 'hÌŒ', 'È¦' => 'AÌ‡', 'È§' => 'aÌ‡', 'È¨' => 'EÌ§', 'È©' => 'eÌ§', 'Èª' => 'OÌˆÌ„', 'È«' => 'oÌˆÌ„', 'È¬' => 'OÌƒÌ„', 'È­' => 'oÌƒÌ„', 'È®' => 'OÌ‡', 'È¯' => 'oÌ‡', 'È°' => 'OÌ‡Ì„', 'È±' => 'oÌ‡Ì„', 'È²' => 'YÌ„', 'È³' => 'yÌ„', 'Í€' => 'Ì€', 'Í�' => 'Ì�', 'Íƒ' => 'Ì“', 'Í„' => 'ÌˆÌ�', 'Í´' => 'Ê¹', 'Í¾' => ';', 'Î…' => 'Â¨Ì�', 'Î†' => 'Î‘Ì�', 'Î‡' => 'Â·', 'Îˆ' => 'Î•Ì�', 'Î‰' => 'Î—Ì�', 'ÎŠ' => 'Î™Ì�', 'ÎŒ' => 'ÎŸÌ�', 'ÎŽ' => 'Î¥Ì�', 'Î�' => 'Î©Ì�', 'Î�' => 'Î¹ÌˆÌ�', 'Îª' => 'Î™Ìˆ', 'Î«' => 'Î¥Ìˆ', 'Î¬' => 'Î±Ì�', 'Î­' => 'ÎµÌ�', 'Î®' => 'Î·Ì�', 'Î¯' => 'Î¹Ì�', 'Î°' => 'Ï…ÌˆÌ�', 'ÏŠ' => 'Î¹Ìˆ', 'Ï‹' => 'Ï…Ìˆ', 'ÏŒ' => 'Î¿Ì�', 'Ï�' => 'Ï…Ì�', 'ÏŽ' => 'Ï‰Ì�', 'Ï“' => 'Ï’Ì�', 'Ï”' => 'Ï’Ìˆ', 'Ð€' => 'Ð•Ì€', 'Ð�' => 'Ð•Ìˆ', 'Ðƒ' => 'Ð“Ì�', 'Ð‡' => 'Ð†Ìˆ', 'ÐŒ' => 'ÐšÌ�', 'Ð�' => 'Ð˜Ì€', 'ÐŽ' => 'Ð£Ì†', 'Ð™' => 'Ð˜Ì†', 'Ð¹' => 'Ð¸Ì†', 'Ñ�' => 'ÐµÌ€', 'Ñ‘' => 'ÐµÌˆ', 'Ñ“' => 'Ð³Ì�', 'Ñ—' => 'Ñ–Ìˆ', 'Ñœ' => 'ÐºÌ�', 'Ñ�' => 'Ð¸Ì€', 'Ñž' => 'ÑƒÌ†', 'Ñ¶' => 'Ñ´Ì�', 'Ñ·' => 'ÑµÌ�', 'Ó�' => 'Ð–Ì†', 'Ó‚' => 'Ð¶Ì†', 'Ó�' => 'Ð�Ì†', 'Ó‘' => 'Ð°Ì†', 'Ó’' => 'Ð�Ìˆ', 'Ó“' => 'Ð°Ìˆ', 'Ó–' => 'Ð•Ì†', 'Ó—' => 'ÐµÌ†', 'Óš' => 'Ó˜Ìˆ', 'Ó›' => 'Ó™Ìˆ', 'Óœ' => 'Ð–Ìˆ', 'Ó�' => 'Ð¶Ìˆ', 'Óž' => 'Ð—Ìˆ', 'ÓŸ' => 'Ð·Ìˆ', 'Ó¢' => 'Ð˜Ì„', 'Ó£' => 'Ð¸Ì„', 'Ó¤' => 'Ð˜Ìˆ', 'Ó¥' => 'Ð¸Ìˆ', 'Ó¦' => 'ÐžÌˆ', 'Ó§' => 'Ð¾Ìˆ', 'Óª' => 'Ó¨Ìˆ', 'Ó«' => 'Ó©Ìˆ', 'Ó¬' => 'Ð­Ìˆ', 'Ó­' => 'Ñ�Ìˆ', 'Ó®' => 'Ð£Ì„', 'Ó¯' => 'ÑƒÌ„', 'Ó°' => 'Ð£Ìˆ', 'Ó±' => 'ÑƒÌˆ', 'Ó²' => 'Ð£Ì‹', 'Ó³' => 'ÑƒÌ‹', 'Ó´' => 'Ð§Ìˆ', 'Óµ' => 'Ñ‡Ìˆ', 'Ó¸' => 'Ð«Ìˆ', 'Ó¹' => 'Ñ‹Ìˆ', 'Ø¢' => 'Ø§Ù“', 'Ø£' => 'Ø§Ù”', 'Ø¤' => 'ÙˆÙ”', 'Ø¥' => 'Ø§Ù•', 'Ø¦' => 'ÙŠÙ”', 'Û€' => 'Û•Ù”', 'Û‚' => 'Û�Ù”', 'Û“' => 'Û’Ù”', 'à¤©' => 'à¤¨à¤¼', 'à¤±' => 'à¤°à¤¼', 'à¤´' => 'à¤³à¤¼', 'à¥˜' => 'à¤•à¤¼', 'à¥™' => 'à¤–à¤¼', 'à¥š' => 'à¤—à¤¼', 'à¥›' => 'à¤œà¤¼', 'à¥œ' => 'à¤¡à¤¼', 'à¥�' => 'à¤¢à¤¼', 'à¥ž' => 'à¤«à¤¼', 'à¥Ÿ' => 'à¤¯à¤¼', 'à§‹' => 'à§‡à¦¾', 'à§Œ' => 'à§‡à§—', 'à§œ' => 'à¦¡à¦¼', 'à§�' => 'à¦¢à¦¼', 'à§Ÿ' => 'à¦¯à¦¼', 'à¨³' => 'à¨²à¨¼', 'à¨¶' => 'à¨¸à¨¼', 'à©™' => 'à¨–à¨¼', 'à©š' => 'à¨—à¨¼', 'à©›' => 'à¨œà¨¼', 'à©ž' => 'à¨«à¨¼', 'à­ˆ' => 'à­‡à­–', 'à­‹' => 'à­‡à¬¾', 'à­Œ' => 'à­‡à­—', 'à­œ' => 'à¬¡à¬¼', 'à­�' => 'à¬¢à¬¼', 'à®”' => 'à®’à¯—', 'à¯Š' => 'à¯†à®¾', 'à¯‹' => 'à¯‡à®¾', 'à¯Œ' => 'à¯†à¯—', 'à±ˆ' => 'à±†à±–', 'à³€' => 'à²¿à³•', 'à³‡' => 'à³†à³•', 'à³ˆ' => 'à³†à³–', 'à³Š' => 'à³†à³‚', 'à³‹' => 'à³†à³‚à³•', 'àµŠ' => 'àµ†à´¾', 'àµ‹' => 'àµ‡à´¾', 'àµŒ' => 'àµ†àµ—', 'à·š' => 'à·™à·Š', 'à·œ' => 'à·™à·�', 'à·�' => 'à·™à·�à·Š', 'à·ž' => 'à·™à·Ÿ', 'à½ƒ' => 'à½‚à¾·', 'à½�' => 'à½Œà¾·', 'à½’' => 'à½‘à¾·', 'à½—' => 'à½–à¾·', 'à½œ' => 'à½›à¾·', 'à½©' => 'à½€à¾µ', 'à½³' => 'à½±à½²', 'à½µ' => 'à½±à½´', 'à½¶' => 'à¾²à¾€', 'à½¸' => 'à¾³à¾€', 'à¾�' => 'à½±à¾€', 'à¾“' => 'à¾’à¾·', 'à¾�' => 'à¾œà¾·', 'à¾¢' => 'à¾¡à¾·', 'à¾§' => 'à¾¦à¾·', 'à¾¬' => 'à¾«à¾·', 'à¾¹' => 'à¾�à¾µ', 'á€¦' => 'á€¥á€®', 'á¬†' => 'á¬…á¬µ', 'á¬ˆ' => 'á¬‡á¬µ', 'á¬Š' => 'á¬‰á¬µ', 'á¬Œ' => 'á¬‹á¬µ', 'á¬Ž' => 'á¬�á¬µ', 'á¬’' => 'á¬‘á¬µ', 'á¬»' => 'á¬ºá¬µ', 'á¬½' => 'á¬¼á¬µ', 'á­€' => 'á¬¾á¬µ', 'á­�' => 'á¬¿á¬µ', 'á­ƒ' => 'á­‚á¬µ', 'á¸€' => 'AÌ¥', 'á¸�' => 'aÌ¥', 'á¸‚' => 'BÌ‡', 'á¸ƒ' => 'bÌ‡', 'á¸„' => 'BÌ£', 'á¸…' => 'bÌ£', 'á¸†' => 'BÌ±', 'á¸‡' => 'bÌ±', 'á¸ˆ' => 'CÌ§Ì�', 'á¸‰' => 'cÌ§Ì�', 'á¸Š' => 'DÌ‡', 'á¸‹' => 'dÌ‡', 'á¸Œ' => 'DÌ£', 'á¸�' => 'dÌ£', 'á¸Ž' => 'DÌ±', 'á¸�' => 'dÌ±', 'á¸�' => 'DÌ§', 'á¸‘' => 'dÌ§', 'á¸’' => 'DÌ­', 'á¸“' => 'dÌ­', 'á¸”' => 'EÌ„Ì€', 'á¸•' => 'eÌ„Ì€', 'á¸–' => 'EÌ„Ì�', 'á¸—' => 'eÌ„Ì�', 'á¸˜' => 'EÌ­', 'á¸™' => 'eÌ­', 'á¸š' => 'EÌ°', 'á¸›' => 'eÌ°', 'á¸œ' => 'EÌ§Ì†', 'á¸�' => 'eÌ§Ì†', 'á¸ž' => 'FÌ‡', 'á¸Ÿ' => 'fÌ‡', 'á¸ ' => 'GÌ„', 'á¸¡' => 'gÌ„', 'á¸¢' => 'HÌ‡', 'á¸£' => 'hÌ‡', 'á¸¤' => 'HÌ£', 'á¸¥' => 'hÌ£', 'á¸¦' => 'HÌˆ', 'á¸§' => 'hÌˆ', 'á¸¨' => 'HÌ§', 'á¸©' => 'hÌ§', 'á¸ª' => 'HÌ®', 'á¸«' => 'hÌ®', 'á¸¬' => 'IÌ°', 'á¸­' => 'iÌ°', 'á¸®' => 'IÌˆÌ�', 'á¸¯' => 'iÌˆÌ�', 'á¸°' => 'KÌ�', 'á¸±' => 'kÌ�', 'á¸²' => 'KÌ£', 'á¸³' => 'kÌ£', 'á¸´' => 'KÌ±', 'á¸µ' => 'kÌ±', 'á¸¶' => 'LÌ£', 'á¸·' => 'lÌ£', 'á¸¸' => 'LÌ£Ì„', 'á¸¹' => 'lÌ£Ì„', 'á¸º' => 'LÌ±', 'á¸»' => 'lÌ±', 'á¸¼' => 'LÌ­', 'á¸½' => 'lÌ­', 'á¸¾' => 'MÌ�', 'á¸¿' => 'mÌ�', 'á¹€' => 'MÌ‡', 'á¹�' => 'mÌ‡', 'á¹‚' => 'MÌ£', 'á¹ƒ' => 'mÌ£', 'á¹„' => 'NÌ‡', 'á¹…' => 'nÌ‡', 'á¹†' => 'NÌ£', 'á¹‡' => 'nÌ£', 'á¹ˆ' => 'NÌ±', 'á¹‰' => 'nÌ±', 'á¹Š' => 'NÌ­', 'á¹‹' => 'nÌ­', 'á¹Œ' => 'OÌƒÌ�', 'á¹�' => 'oÌƒÌ�', 'á¹Ž' => 'OÌƒÌˆ', 'á¹�' => 'oÌƒÌˆ', 'á¹�' => 'OÌ„Ì€', 'á¹‘' => 'oÌ„Ì€', 'á¹’' => 'OÌ„Ì�', 'á¹“' => 'oÌ„Ì�', 'á¹”' => 'PÌ�', 'á¹•' => 'pÌ�', 'á¹–' => 'PÌ‡', 'á¹—' => 'pÌ‡', 'á¹˜' => 'RÌ‡', 'á¹™' => 'rÌ‡', 'á¹š' => 'RÌ£', 'á¹›' => 'rÌ£', 'á¹œ' => 'RÌ£Ì„', 'á¹�' => 'rÌ£Ì„', 'á¹ž' => 'RÌ±', 'á¹Ÿ' => 'rÌ±', 'á¹ ' => 'SÌ‡', 'á¹¡' => 'sÌ‡', 'á¹¢' => 'SÌ£', 'á¹£' => 'sÌ£', 'á¹¤' => 'SÌ�Ì‡', 'á¹¥' => 'sÌ�Ì‡', 'á¹¦' => 'SÌŒÌ‡', 'á¹§' => 'sÌŒÌ‡', 'á¹¨' => 'SÌ£Ì‡', 'á¹©' => 'sÌ£Ì‡', 'á¹ª' => 'TÌ‡', 'á¹«' => 'tÌ‡', 'á¹¬' => 'TÌ£', 'á¹­' => 'tÌ£', 'á¹®' => 'TÌ±', 'á¹¯' => 'tÌ±', 'á¹°' => 'TÌ­', 'á¹±' => 'tÌ­', 'á¹²' => 'UÌ¤', 'á¹³' => 'uÌ¤', 'á¹´' => 'UÌ°', 'á¹µ' => 'uÌ°', 'á¹¶' => 'UÌ­', 'á¹·' => 'uÌ­', 'á¹¸' => 'UÌƒÌ�', 'á¹¹' => 'uÌƒÌ�', 'á¹º' => 'UÌ„Ìˆ', 'á¹»' => 'uÌ„Ìˆ', 'á¹¼' => 'VÌƒ', 'á¹½' => 'vÌƒ', 'á¹¾' => 'VÌ£', 'á¹¿' => 'vÌ£', 'áº€' => 'WÌ€', 'áº�' => 'wÌ€', 'áº‚' => 'WÌ�', 'áºƒ' => 'wÌ�', 'áº„' => 'WÌˆ', 'áº…' => 'wÌˆ', 'áº†' => 'WÌ‡', 'áº‡' => 'wÌ‡', 'áºˆ' => 'WÌ£', 'áº‰' => 'wÌ£', 'áºŠ' => 'XÌ‡', 'áº‹' => 'xÌ‡', 'áºŒ' => 'XÌˆ', 'áº�' => 'xÌˆ', 'áºŽ' => 'YÌ‡', 'áº�' => 'yÌ‡', 'áº�' => 'ZÌ‚', 'áº‘' => 'zÌ‚', 'áº’' => 'ZÌ£', 'áº“' => 'zÌ£', 'áº”' => 'ZÌ±', 'áº•' => 'zÌ±', 'áº–' => 'hÌ±', 'áº—' => 'tÌˆ', 'áº˜' => 'wÌŠ', 'áº™' => 'yÌŠ', 'áº›' => 'Å¿Ì‡', 'áº ' => 'AÌ£', 'áº¡' => 'aÌ£', 'áº¢' => 'AÌ‰', 'áº£' => 'aÌ‰', 'áº¤' => 'AÌ‚Ì�', 'áº¥' => 'aÌ‚Ì�', 'áº¦' => 'AÌ‚Ì€', 'áº§' => 'aÌ‚Ì€', 'áº¨' => 'AÌ‚Ì‰', 'áº©' => 'aÌ‚Ì‰', 'áºª' => 'AÌ‚Ìƒ', 'áº«' => 'aÌ‚Ìƒ', 'áº¬' => 'AÌ£Ì‚', 'áº­' => 'aÌ£Ì‚', 'áº®' => 'AÌ†Ì�', 'áº¯' => 'aÌ†Ì�', 'áº°' => 'AÌ†Ì€', 'áº±' => 'aÌ†Ì€', 'áº²' => 'AÌ†Ì‰', 'áº³' => 'aÌ†Ì‰', 'áº´' => 'AÌ†Ìƒ', 'áºµ' => 'aÌ†Ìƒ', 'áº¶' => 'AÌ£Ì†', 'áº·' => 'aÌ£Ì†', 'áº¸' => 'EÌ£', 'áº¹' => 'eÌ£', 'áºº' => 'EÌ‰', 'áº»' => 'eÌ‰', 'áº¼' => 'EÌƒ', 'áº½' => 'eÌƒ', 'áº¾' => 'EÌ‚Ì�', 'áº¿' => 'eÌ‚Ì�', 'á»€' => 'EÌ‚Ì€', 'á»�' => 'eÌ‚Ì€', 'á»‚' => 'EÌ‚Ì‰', 'á»ƒ' => 'eÌ‚Ì‰', 'á»„' => 'EÌ‚Ìƒ', 'á»…' => 'eÌ‚Ìƒ', 'á»†' => 'EÌ£Ì‚', 'á»‡' => 'eÌ£Ì‚', 'á»ˆ' => 'IÌ‰', 'á»‰' => 'iÌ‰', 'á»Š' => 'IÌ£', 'á»‹' => 'iÌ£', 'á»Œ' => 'OÌ£', 'á»�' => 'oÌ£', 'á»Ž' => 'OÌ‰', 'á»�' => 'oÌ‰', 'á»�' => 'OÌ‚Ì�', 'á»‘' => 'oÌ‚Ì�', 'á»’' => 'OÌ‚Ì€', 'á»“' => 'oÌ‚Ì€', 'á»”' => 'OÌ‚Ì‰', 'á»•' => 'oÌ‚Ì‰', 'á»–' => 'OÌ‚Ìƒ', 'á»—' => 'oÌ‚Ìƒ', 'á»˜' => 'OÌ£Ì‚', 'á»™' => 'oÌ£Ì‚', 'á»š' => 'OÌ›Ì�', 'á»›' => 'oÌ›Ì�', 'á»œ' => 'OÌ›Ì€', 'á»�' => 'oÌ›Ì€', 'á»ž' => 'OÌ›Ì‰', 'á»Ÿ' => 'oÌ›Ì‰', 'á» ' => 'OÌ›Ìƒ', 'á»¡' => 'oÌ›Ìƒ', 'á»¢' => 'OÌ›Ì£', 'á»£' => 'oÌ›Ì£', 'á»¤' => 'UÌ£', 'á»¥' => 'uÌ£', 'á»¦' => 'UÌ‰', 'á»§' => 'uÌ‰', 'á»¨' => 'UÌ›Ì�', 'á»©' => 'uÌ›Ì�', 'á»ª' => 'UÌ›Ì€', 'á»«' => 'uÌ›Ì€', 'á»¬' => 'UÌ›Ì‰', 'á»­' => 'uÌ›Ì‰', 'á»®' => 'UÌ›Ìƒ', 'á»¯' => 'uÌ›Ìƒ', 'á»°' => 'UÌ›Ì£', 'á»±' => 'uÌ›Ì£', 'á»²' => 'YÌ€', 'á»³' => 'yÌ€', 'á»´' => 'YÌ£', 'á»µ' => 'yÌ£', 'á»¶' => 'YÌ‰', 'á»·' => 'yÌ‰', 'á»¸' => 'YÌƒ', 'á»¹' => 'yÌƒ', 'á¼€' => 'Î±Ì“', 'á¼�' => 'Î±Ì”', 'á¼‚' => 'Î±Ì“Ì€', 'á¼ƒ' => 'Î±Ì”Ì€', 'á¼„' => 'Î±Ì“Ì�', 'á¼…' => 'Î±Ì”Ì�', 'á¼†' => 'Î±Ì“Í‚', 'á¼‡' => 'Î±Ì”Í‚', 'á¼ˆ' => 'Î‘Ì“', 'á¼‰' => 'Î‘Ì”', 'á¼Š' => 'Î‘Ì“Ì€', 'á¼‹' => 'Î‘Ì”Ì€', 'á¼Œ' => 'Î‘Ì“Ì�', 'á¼�' => 'Î‘Ì”Ì�', 'á¼Ž' => 'Î‘Ì“Í‚', 'á¼�' => 'Î‘Ì”Í‚', 'á¼�' => 'ÎµÌ“', 'á¼‘' => 'ÎµÌ”', 'á¼’' => 'ÎµÌ“Ì€', 'á¼“' => 'ÎµÌ”Ì€', 'á¼”' => 'ÎµÌ“Ì�', 'á¼•' => 'ÎµÌ”Ì�', 'á¼˜' => 'Î•Ì“', 'á¼™' => 'Î•Ì”', 'á¼š' => 'Î•Ì“Ì€', 'á¼›' => 'Î•Ì”Ì€', 'á¼œ' => 'Î•Ì“Ì�', 'á¼�' => 'Î•Ì”Ì�', 'á¼ ' => 'Î·Ì“', 'á¼¡' => 'Î·Ì”', 'á¼¢' => 'Î·Ì“Ì€', 'á¼£' => 'Î·Ì”Ì€', 'á¼¤' => 'Î·Ì“Ì�', 'á¼¥' => 'Î·Ì”Ì�', 'á¼¦' => 'Î·Ì“Í‚', 'á¼§' => 'Î·Ì”Í‚', 'á¼¨' => 'Î—Ì“', 'á¼©' => 'Î—Ì”', 'á¼ª' => 'Î—Ì“Ì€', 'á¼«' => 'Î—Ì”Ì€', 'á¼¬' => 'Î—Ì“Ì�', 'á¼­' => 'Î—Ì”Ì�', 'á¼®' => 'Î—Ì“Í‚', 'á¼¯' => 'Î—Ì”Í‚', 'á¼°' => 'Î¹Ì“', 'á¼±' => 'Î¹Ì”', 'á¼²' => 'Î¹Ì“Ì€', 'á¼³' => 'Î¹Ì”Ì€', 'á¼´' => 'Î¹Ì“Ì�', 'á¼µ' => 'Î¹Ì”Ì�', 'á¼¶' => 'Î¹Ì“Í‚', 'á¼·' => 'Î¹Ì”Í‚', 'á¼¸' => 'Î™Ì“', 'á¼¹' => 'Î™Ì”', 'á¼º' => 'Î™Ì“Ì€', 'á¼»' => 'Î™Ì”Ì€', 'á¼¼' => 'Î™Ì“Ì�', 'á¼½' => 'Î™Ì”Ì�', 'á¼¾' => 'Î™Ì“Í‚', 'á¼¿' => 'Î™Ì”Í‚', 'á½€' => 'Î¿Ì“', 'á½�' => 'Î¿Ì”', 'á½‚' => 'Î¿Ì“Ì€', 'á½ƒ' => 'Î¿Ì”Ì€', 'á½„' => 'Î¿Ì“Ì�', 'á½…' => 'Î¿Ì”Ì�', 'á½ˆ' => 'ÎŸÌ“', 'á½‰' => 'ÎŸÌ”', 'á½Š' => 'ÎŸÌ“Ì€', 'á½‹' => 'ÎŸÌ”Ì€', 'á½Œ' => 'ÎŸÌ“Ì�', 'á½�' => 'ÎŸÌ”Ì�', 'á½�' => 'Ï…Ì“', 'á½‘' => 'Ï…Ì”', 'á½’' => 'Ï…Ì“Ì€', 'á½“' => 'Ï…Ì”Ì€', 'á½”' => 'Ï…Ì“Ì�', 'á½•' => 'Ï…Ì”Ì�', 'á½–' => 'Ï…Ì“Í‚', 'á½—' => 'Ï…Ì”Í‚', 'á½™' => 'Î¥Ì”', 'á½›' => 'Î¥Ì”Ì€', 'á½�' => 'Î¥Ì”Ì�', 'á½Ÿ' => 'Î¥Ì”Í‚', 'á½ ' => 'Ï‰Ì“', 'á½¡' => 'Ï‰Ì”', 'á½¢' => 'Ï‰Ì“Ì€', 'á½£' => 'Ï‰Ì”Ì€', 'á½¤' => 'Ï‰Ì“Ì�', 'á½¥' => 'Ï‰Ì”Ì�', 'á½¦' => 'Ï‰Ì“Í‚', 'á½§' => 'Ï‰Ì”Í‚', 'á½¨' => 'Î©Ì“', 'á½©' => 'Î©Ì”', 'á½ª' => 'Î©Ì“Ì€', 'á½«' => 'Î©Ì”Ì€', 'á½¬' => 'Î©Ì“Ì�', 'á½­' => 'Î©Ì”Ì�', 'á½®' => 'Î©Ì“Í‚', 'á½¯' => 'Î©Ì”Í‚', 'á½°' => 'Î±Ì€', 'á½±' => 'Î±Ì�', 'á½²' => 'ÎµÌ€', 'á½³' => 'ÎµÌ�', 'á½´' => 'Î·Ì€', 'á½µ' => 'Î·Ì�', 'á½¶' => 'Î¹Ì€', 'á½·' => 'Î¹Ì�', 'á½¸' => 'Î¿Ì€', 'á½¹' => 'Î¿Ì�', 'á½º' => 'Ï…Ì€', 'á½»' => 'Ï…Ì�', 'á½¼' => 'Ï‰Ì€', 'á½½' => 'Ï‰Ì�', 'á¾€' => 'Î±Ì“Í…', 'á¾�' => 'Î±Ì”Í…', 'á¾‚' => 'Î±Ì“Ì€Í…', 'á¾ƒ' => 'Î±Ì”Ì€Í…', 'á¾„' => 'Î±Ì“Ì�Í…', 'á¾…' => 'Î±Ì”Ì�Í…', 'á¾†' => 'Î±Ì“Í‚Í…', 'á¾‡' => 'Î±Ì”Í‚Í…', 'á¾ˆ' => 'Î‘Ì“Í…', 'á¾‰' => 'Î‘Ì”Í…', 'á¾Š' => 'Î‘Ì“Ì€Í…', 'á¾‹' => 'Î‘Ì”Ì€Í…', 'á¾Œ' => 'Î‘Ì“Ì�Í…', 'á¾�' => 'Î‘Ì”Ì�Í…', 'á¾Ž' => 'Î‘Ì“Í‚Í…', 'á¾�' => 'Î‘Ì”Í‚Í…', 'á¾�' => 'Î·Ì“Í…', 'á¾‘' => 'Î·Ì”Í…', 'á¾’' => 'Î·Ì“Ì€Í…', 'á¾“' => 'Î·Ì”Ì€Í…', 'á¾”' => 'Î·Ì“Ì�Í…', 'á¾•' => 'Î·Ì”Ì�Í…', 'á¾–' => 'Î·Ì“Í‚Í…', 'á¾—' => 'Î·Ì”Í‚Í…', 'á¾˜' => 'Î—Ì“Í…', 'á¾™' => 'Î—Ì”Í…', 'á¾š' => 'Î—Ì“Ì€Í…', 'á¾›' => 'Î—Ì”Ì€Í…', 'á¾œ' => 'Î—Ì“Ì�Í…', 'á¾�' => 'Î—Ì”Ì�Í…', 'á¾ž' => 'Î—Ì“Í‚Í…', 'á¾Ÿ' => 'Î—Ì”Í‚Í…', 'á¾ ' => 'Ï‰Ì“Í…', 'á¾¡' => 'Ï‰Ì”Í…', 'á¾¢' => 'Ï‰Ì“Ì€Í…', 'á¾£' => 'Ï‰Ì”Ì€Í…', 'á¾¤' => 'Ï‰Ì“Ì�Í…', 'á¾¥' => 'Ï‰Ì”Ì�Í…', 'á¾¦' => 'Ï‰Ì“Í‚Í…', 'á¾§' => 'Ï‰Ì”Í‚Í…', 'á¾¨' => 'Î©Ì“Í…', 'á¾©' => 'Î©Ì”Í…', 'á¾ª' => 'Î©Ì“Ì€Í…', 'á¾«' => 'Î©Ì”Ì€Í…', 'á¾¬' => 'Î©Ì“Ì�Í…', 'á¾­' => 'Î©Ì”Ì�Í…', 'á¾®' => 'Î©Ì“Í‚Í…', 'á¾¯' => 'Î©Ì”Í‚Í…', 'á¾°' => 'Î±Ì†', 'á¾±' => 'Î±Ì„', 'á¾²' => 'Î±Ì€Í…', 'á¾³' => 'Î±Í…', 'á¾´' => 'Î±Ì�Í…', 'á¾¶' => 'Î±Í‚', 'á¾·' => 'Î±Í‚Í…', 'á¾¸' => 'Î‘Ì†', 'á¾¹' => 'Î‘Ì„', 'á¾º' => 'Î‘Ì€', 'á¾»' => 'Î‘Ì�', 'á¾¼' => 'Î‘Í…', 'á¾¾' => 'Î¹', 'á¿�' => 'Â¨Í‚', 'á¿‚' => 'Î·Ì€Í…', 'á¿ƒ' => 'Î·Í…', 'á¿„' => 'Î·Ì�Í…', 'á¿†' => 'Î·Í‚', 'á¿‡' => 'Î·Í‚Í…', 'á¿ˆ' => 'Î•Ì€', 'á¿‰' => 'Î•Ì�', 'á¿Š' => 'Î—Ì€', 'á¿‹' => 'Î—Ì�', 'á¿Œ' => 'Î—Í…', 'á¿�' => 'á¾¿Ì€', 'á¿Ž' => 'á¾¿Ì�', 'á¿�' => 'á¾¿Í‚', 'á¿�' => 'Î¹Ì†', 'á¿‘' => 'Î¹Ì„', 'á¿’' => 'Î¹ÌˆÌ€', 'á¿“' => 'Î¹ÌˆÌ�', 'á¿–' => 'Î¹Í‚', 'á¿—' => 'Î¹ÌˆÍ‚', 'á¿˜' => 'Î™Ì†', 'á¿™' => 'Î™Ì„', 'á¿š' => 'Î™Ì€', 'á¿›' => 'Î™Ì�', 'á¿�' => 'á¿¾Ì€', 'á¿ž' => 'á¿¾Ì�', 'á¿Ÿ' => 'á¿¾Í‚', 'á¿ ' => 'Ï…Ì†', 'á¿¡' => 'Ï…Ì„', 'á¿¢' => 'Ï…ÌˆÌ€', 'á¿£' => 'Ï…ÌˆÌ�', 'á¿¤' => 'Ï�Ì“', 'á¿¥' => 'Ï�Ì”', 'á¿¦' => 'Ï…Í‚', 'á¿§' => 'Ï…ÌˆÍ‚', 'á¿¨' => 'Î¥Ì†', 'á¿©' => 'Î¥Ì„', 'á¿ª' => 'Î¥Ì€', 'á¿«' => 'Î¥Ì�', 'á¿¬' => 'Î¡Ì”', 'á¿­' => 'Â¨Ì€', 'á¿®' => 'Â¨Ì�', 'á¿¯' => '`', 'á¿²' => 'Ï‰Ì€Í…', 'á¿³' => 'Ï‰Í…', 'á¿´' => 'Ï‰Ì�Í…', 'á¿¶' => 'Ï‰Í‚', 'á¿·' => 'Ï‰Í‚Í…', 'á¿¸' => 'ÎŸÌ€', 'á¿¹' => 'ÎŸÌ�', 'á¿º' => 'Î©Ì€', 'á¿»' => 'Î©Ì�', 'á¿¼' => 'Î©Í…', 'á¿½' => 'Â´', 'â€€' => 'â€‚', 'â€�' => 'â€ƒ', 'â„¦' => 'Î©', 'â„ª' => 'K', 'â„«' => 'AÌŠ', 'â†š' => 'â†�Ì¸', 'â†›' => 'â†’Ì¸', 'â†®' => 'â†”Ì¸', 'â‡�' => 'â‡�Ì¸', 'â‡Ž' => 'â‡”Ì¸', 'â‡�' => 'â‡’Ì¸', 'âˆ„' => 'âˆƒÌ¸', 'âˆ‰' => 'âˆˆÌ¸', 'âˆŒ' => 'âˆ‹Ì¸', 'âˆ¤' => 'âˆ£Ì¸', 'âˆ¦' => 'âˆ¥Ì¸', 'â‰�' => 'âˆ¼Ì¸', 'â‰„' => 'â‰ƒÌ¸', 'â‰‡' => 'â‰…Ì¸', 'â‰‰' => 'â‰ˆÌ¸', 'â‰ ' => '=Ì¸', 'â‰¢' => 'â‰¡Ì¸', 'â‰­' => 'â‰�Ì¸', 'â‰®' => '<Ì¸', 'â‰¯' => '>Ì¸', 'â‰°' => 'â‰¤Ì¸', 'â‰±' => 'â‰¥Ì¸', 'â‰´' => 'â‰²Ì¸', 'â‰µ' => 'â‰³Ì¸', 'â‰¸' => 'â‰¶Ì¸', 'â‰¹' => 'â‰·Ì¸', 'âŠ€' => 'â‰ºÌ¸', 'âŠ�' => 'â‰»Ì¸', 'âŠ„' => 'âŠ‚Ì¸', 'âŠ…' => 'âŠƒÌ¸', 'âŠˆ' => 'âŠ†Ì¸', 'âŠ‰' => 'âŠ‡Ì¸', 'âŠ¬' => 'âŠ¢Ì¸', 'âŠ­' => 'âŠ¨Ì¸', 'âŠ®' => 'âŠ©Ì¸', 'âŠ¯' => 'âŠ«Ì¸', 'â‹ ' => 'â‰¼Ì¸', 'â‹¡' => 'â‰½Ì¸', 'â‹¢' => 'âŠ‘Ì¸', 'â‹£' => 'âŠ’Ì¸', 'â‹ª' => 'âŠ²Ì¸', 'â‹«' => 'âŠ³Ì¸', 'â‹¬' => 'âŠ´Ì¸', 'â‹­' => 'âŠµÌ¸', 'âŒ©' => 'ã€ˆ', 'âŒª' => 'ã€‰', 'â«œ' => 'â«�Ì¸', 'ã�Œ' => 'ã�‹ã‚™', 'ã�Ž' => 'ã��ã‚™', 'ã��' => 'ã��ã‚™', 'ã�’' => 'ã�‘ã‚™', 'ã�”' => 'ã�“ã‚™', 'ã�–' => 'ã�•ã‚™', 'ã�˜' => 'ã�—ã‚™', 'ã�š' => 'ã�™ã‚™', 'ã�œ' => 'ã�›ã‚™', 'ã�ž' => 'ã��ã‚™', 'ã� ' => 'ã�Ÿã‚™', 'ã�¢' => 'ã�¡ã‚™', 'ã�¥' => 'ã�¤ã‚™', 'ã�§' => 'ã�¦ã‚™', 'ã�©' => 'ã�¨ã‚™', 'ã�°' => 'ã�¯ã‚™', 'ã�±' => 'ã�¯ã‚š', 'ã�³' => 'ã�²ã‚™', 'ã�´' => 'ã�²ã‚š', 'ã�¶' => 'ã�µã‚™', 'ã�·' => 'ã�µã‚š', 'ã�¹' => 'ã�¸ã‚™', 'ã�º' => 'ã�¸ã‚š', 'ã�¼' => 'ã�»ã‚™', 'ã�½' => 'ã�»ã‚š', 'ã‚”' => 'ã�†ã‚™', 'ã‚ž' => 'ã‚�ã‚™', 'ã‚¬' => 'ã‚«ã‚™', 'ã‚®' => 'ã‚­ã‚™', 'ã‚°' => 'ã‚¯ã‚™', 'ã‚²' => 'ã‚±ã‚™', 'ã‚´' => 'ã‚³ã‚™', 'ã‚¶' => 'ã‚µã‚™', 'ã‚¸' => 'ã‚·ã‚™', 'ã‚º' => 'ã‚¹ã‚™', 'ã‚¼' => 'ã‚»ã‚™', 'ã‚¾' => 'ã‚½ã‚™', 'ãƒ€' => 'ã‚¿ã‚™', 'ãƒ‚' => 'ãƒ�ã‚™', 'ãƒ…' => 'ãƒ„ã‚™', 'ãƒ‡' => 'ãƒ†ã‚™', 'ãƒ‰' => 'ãƒˆã‚™', 'ãƒ�' => 'ãƒ�ã‚™', 'ãƒ‘' => 'ãƒ�ã‚š', 'ãƒ“' => 'ãƒ’ã‚™', 'ãƒ”' => 'ãƒ’ã‚š', 'ãƒ–' => 'ãƒ•ã‚™', 'ãƒ—' => 'ãƒ•ã‚š', 'ãƒ™' => 'ãƒ˜ã‚™', 'ãƒš' => 'ãƒ˜ã‚š', 'ãƒœ' => 'ãƒ›ã‚™', 'ãƒ�' => 'ãƒ›ã‚š', 'ãƒ´' => 'ã‚¦ã‚™', 'ãƒ·' => 'ãƒ¯ã‚™', 'ãƒ¸' => 'ãƒ°ã‚™', 'ãƒ¹' => 'ãƒ±ã‚™', 'ãƒº' => 'ãƒ²ã‚™', 'ãƒ¾' => 'ãƒ½ã‚™', 'ï¤€' => 'è±ˆ', 'ï¤�' => 'æ›´', 'ï¤‚' => 'è»Š', 'ï¤ƒ' => 'è³ˆ', 'ï¤„' => 'æ»‘', 'ï¤…' => 'ä¸²', 'ï¤†' => 'å�¥', 'ï¤‡' => 'é¾œ', 'ï¤ˆ' => 'é¾œ', 'ï¤‰' => 'å¥‘', 'ï¤Š' => 'é‡‘', 'ï¤‹' => 'å–‡', 'ï¤Œ' => 'å¥ˆ', 'ï¤�' => 'æ‡¶', 'ï¤Ž' => 'ç™©', 'ï¤�' => 'ç¾…', 'ï¤�' => 'è˜¿', 'ï¤‘' => 'èžº', 'ï¤’' => 'è£¸', 'ï¤“' => 'é‚�', 'ï¤”' => 'æ¨‚', 'ï¤•' => 'æ´›', 'ï¤–' => 'çƒ™', 'ï¤—' => 'ç�ž', 'ï¤˜' => 'è�½', 'ï¤™' => 'é…ª', 'ï¤š' => 'é§±', 'ï¤›' => 'äº‚', 'ï¤œ' => 'å�µ', 'ï¤�' => 'æ¬„', 'ï¤ž' => 'çˆ›', 'ï¤Ÿ' => 'è˜­', 'ï¤ ' => 'é¸ž', 'ï¤¡' => 'åµ�', 'ï¤¢' => 'æ¿«', 'ï¤£' => 'è—�', 'ï¤¤' => 'è¥¤', 'ï¤¥' => 'æ‹‰', 'ï¤¦' => 'è‡˜', 'ï¤§' => 'è Ÿ', 'ï¤¨' => 'å»Š', 'ï¤©' => 'æœ—', 'ï¤ª' => 'æµª', 'ï¤«' => 'ç‹¼', 'ï¤¬' => 'éƒŽ', 'ï¤­' => 'ä¾†', 'ï¤®' => 'å†·', 'ï¤¯' => 'å‹ž', 'ï¤°' => 'æ“„', 'ï¤±' => 'æ«“', 'ï¤²' => 'çˆ�', 'ï¤³' => 'ç›§', 'ï¤´' => 'è€�', 'ï¤µ' => 'è˜†', 'ï¤¶' => 'è™œ', 'ï¤·' => 'è·¯', 'ï¤¸' => 'éœ²', 'ï¤¹' => 'é­¯', 'ï¤º' => 'é·º', 'ï¤»' => 'ç¢Œ', 'ï¤¼' => 'ç¥¿', 'ï¤½' => 'ç¶ ', 'ï¤¾' => 'è�‰', 'ï¤¿' => 'éŒ„', 'ï¥€' => 'é¹¿', 'ï¥�' => 'è«–', 'ï¥‚' => 'å£Ÿ', 'ï¥ƒ' => 'å¼„', 'ï¥„' => 'ç± ', 'ï¥…' => 'è�¾', 'ï¥†' => 'ç‰¢', 'ï¥‡' => 'ç£Š', 'ï¥ˆ' => 'è³‚', 'ï¥‰' => 'é›·', 'ï¥Š' => 'å£˜', 'ï¥‹' => 'å±¢', 'ï¥Œ' => 'æ¨“', 'ï¥�' => 'æ·š', 'ï¥Ž' => 'æ¼�', 'ï¥�' => 'ç´¯', 'ï¥�' => 'ç¸·', 'ï¥‘' => 'é™‹', 'ï¥’' => 'å‹’', 'ï¥“' => 'è‚‹', 'ï¥”' => 'å‡œ', 'ï¥•' => 'å‡Œ', 'ï¥–' => 'ç¨œ', 'ï¥—' => 'ç¶¾', 'ï¥˜' => 'è�±', 'ï¥™' => 'é™µ', 'ï¥š' => 'è®€', 'ï¥›' => 'æ‹�', 'ï¥œ' => 'æ¨‚', 'ï¥�' => 'è«¾', 'ï¥ž' => 'ä¸¹', 'ï¥Ÿ' => 'å¯§', 'ï¥ ' => 'æ€’', 'ï¥¡' => 'çŽ‡', 'ï¥¢' => 'ç•°', 'ï¥£' => 'åŒ—', 'ï¥¤' => 'ç£»', 'ï¥¥' => 'ä¾¿', 'ï¥¦' => 'å¾©', 'ï¥§' => 'ä¸�', 'ï¥¨' => 'æ³Œ', 'ï¥©' => 'æ•¸', 'ï¥ª' => 'ç´¢', 'ï¥«' => 'å�ƒ', 'ï¥¬' => 'å¡ž', 'ï¥­' => 'çœ�', 'ï¥®' => 'è‘‰', 'ï¥¯' => 'èªª', 'ï¥°' => 'æ®º', 'ï¥±' => 'è¾°', 'ï¥²' => 'æ²ˆ', 'ï¥³' => 'æ‹¾', 'ï¥´' => 'è‹¥', 'ï¥µ' => 'æŽ ', 'ï¥¶' => 'ç•¥', 'ï¥·' => 'äº®', 'ï¥¸' => 'å…©', 'ï¥¹' => 'å‡‰', 'ï¥º' => 'æ¢�', 'ï¥»' => 'ç³§', 'ï¥¼' => 'è‰¯', 'ï¥½' => 'è«’', 'ï¥¾' => 'é‡�', 'ï¥¿' => 'å‹µ', 'ï¦€' => 'å‘‚', 'ï¦�' => 'å¥³', 'ï¦‚' => 'å»¬', 'ï¦ƒ' => 'æ—…', 'ï¦„' => 'æ¿¾', 'ï¦…' => 'ç¤ª', 'ï¦†' => 'é–­', 'ï¦‡' => 'é©ª', 'ï¦ˆ' => 'éº—', 'ï¦‰' => 'é»Ž', 'ï¦Š' => 'åŠ›', 'ï¦‹' => 'æ›†', 'ï¦Œ' => 'æ­·', 'ï¦�' => 'è½¢', 'ï¦Ž' => 'å¹´', 'ï¦�' => 'æ†�', 'ï¦�' => 'æˆ€', 'ï¦‘' => 'æ’š', 'ï¦’' => 'æ¼£', 'ï¦“' => 'ç…‰', 'ï¦”' => 'ç’‰', 'ï¦•' => 'ç§Š', 'ï¦–' => 'ç·´', 'ï¦—' => 'è�¯', 'ï¦˜' => 'è¼¦', 'ï¦™' => 'è“®', 'ï¦š' => 'é€£', 'ï¦›' => 'é�Š', 'ï¦œ' => 'åˆ—', 'ï¦�' => 'åŠ£', 'ï¦ž' => 'å’½', 'ï¦Ÿ' => 'çƒˆ', 'ï¦ ' => 'è£‚', 'ï¦¡' => 'èªª', 'ï¦¢' => 'å»‰', 'ï¦£' => 'å¿µ', 'ï¦¤' => 'æ�»', 'ï¦¥' => 'æ®®', 'ï¦¦' => 'ç°¾', 'ï¦§' => 'ç�µ', 'ï¦¨' => 'ä»¤', 'ï¦©' => 'å›¹', 'ï¦ª' => 'å¯§', 'ï¦«' => 'å¶º', 'ï¦¬' => 'æ€œ', 'ï¦­' => 'çŽ²', 'ï¦®' => 'ç‘©', 'ï¦¯' => 'ç¾š', 'ï¦°' => 'è�†', 'ï¦±' => 'éˆ´', 'ï¦²' => 'é›¶', 'ï¦³' => 'é�ˆ', 'ï¦´' => 'é ˜', 'ï¦µ' => 'ä¾‹', 'ï¦¶' => 'ç¦®', 'ï¦·' => 'é†´', 'ï¦¸' => 'éš¸', 'ï¦¹' => 'æƒ¡', 'ï¦º' => 'äº†', 'ï¦»' => 'åƒš', 'ï¦¼' => 'å¯®', 'ï¦½' => 'å°¿', 'ï¦¾' => 'æ–™', 'ï¦¿' => 'æ¨‚', 'ï§€' => 'ç‡Ž', 'ï§�' => 'ç™‚', 'ï§‚' => 'è“¼', 'ï§ƒ' => 'é�¼', 'ï§„' => 'é¾�', 'ï§…' => 'æšˆ', 'ï§†' => 'é˜®', 'ï§‡' => 'åŠ‰', 'ï§ˆ' => 'æ�»', 'ï§‰' => 'æŸ³', 'ï§Š' => 'æµ�', 'ï§‹' => 'æºœ', 'ï§Œ' => 'ç�‰', 'ï§�' => 'ç•™', 'ï§Ž' => 'ç¡«', 'ï§�' => 'ç´�', 'ï§�' => 'é¡ž', 'ï§‘' => 'å…­', 'ï§’' => 'æˆ®', 'ï§“' => 'é™¸', 'ï§”' => 'å€«', 'ï§•' => 'å´™', 'ï§–' => 'æ·ª', 'ï§—' => 'è¼ª', 'ï§˜' => 'å¾‹', 'ï§™' => 'æ…„', 'ï§š' => 'æ —', 'ï§›' => 'çŽ‡', 'ï§œ' => 'éš†', 'ï§�' => 'åˆ©', 'ï§ž' => 'å��', 'ï§Ÿ' => 'å±¥', 'ï§ ' => 'æ˜“', 'ï§¡' => 'æ�Ž', 'ï§¢' => 'æ¢¨', 'ï§£' => 'æ³¥', 'ï§¤' => 'ç�†', 'ï§¥' => 'ç—¢', 'ï§¦' => 'ç½¹', 'ï§§' => 'è£�', 'ï§¨' => 'è£¡', 'ï§©' => 'é‡Œ', 'ï§ª' => 'é›¢', 'ï§«' => 'åŒ¿', 'ï§¬' => 'æºº', 'ï§­' => 'å��', 'ï§®' => 'ç‡�', 'ï§¯' => 'ç’˜', 'ï§°' => 'è—º', 'ï§±' => 'éš£', 'ï§²' => 'é±—', 'ï§³' => 'éºŸ', 'ï§´' => 'æž—', 'ï§µ' => 'æ·‹', 'ï§¶' => 'è‡¨', 'ï§·' => 'ç«‹', 'ï§¸' => 'ç¬ ', 'ï§¹' => 'ç²’', 'ï§º' => 'ç‹€', 'ï§»' => 'ç‚™', 'ï§¼' => 'è­˜', 'ï§½' => 'ä»€', 'ï§¾' => 'èŒ¶', 'ï§¿' => 'åˆº', 'ï¨€' => 'åˆ‡', 'ï¨�' => 'åº¦', 'ï¨‚' => 'æ‹“', 'ï¨ƒ' => 'ç³–', 'ï¨„' => 'å®…', 'ï¨…' => 'æ´ž', 'ï¨†' => 'æš´', 'ï¨‡' => 'è¼»', 'ï¨ˆ' => 'è¡Œ', 'ï¨‰' => 'é™�', 'ï¨Š' => 'è¦‹', 'ï¨‹' => 'å»“', 'ï¨Œ' => 'å…€', 'ï¨�' => 'å—€', 'ï¨�' => 'å¡š', 'ï¨’' => 'æ™´', 'ï¨•' => 'å‡ž', 'ï¨–' => 'çŒª', 'ï¨—' => 'ç›Š', 'ï¨˜' => 'ç¤¼', 'ï¨™' => 'ç¥ž', 'ï¨š' => 'ç¥¥', 'ï¨›' => 'ç¦�', 'ï¨œ' => 'é�–', 'ï¨�' => 'ç²¾', 'ï¨ž' => 'ç¾½', 'ï¨ ' => 'è˜’', 'ï¨¢' => 'è«¸', 'ï¨¥' => 'é€¸', 'ï¨¦' => 'éƒ½', 'ï¨ª' => 'é£¯', 'ï¨«' => 'é£¼', 'ï¨¬' => 'é¤¨', 'ï¨­' => 'é¶´', 'ï¨®' => 'éƒž', 'ï¨¯' => 'éš·', 'ï¨°' => 'ä¾®', 'ï¨±' => 'åƒ§', 'ï¨²' => 'å…�', 'ï¨³' => 'å‹‰', 'ï¨´' => 'å‹¤', 'ï¨µ' => 'å�‘', 'ï¨¶' => 'å–�', 'ï¨·' => 'å˜†', 'ï¨¸' => 'å™¨', 'ï¨¹' => 'å¡€', 'ï¨º' => 'å¢¨', 'ï¨»' => 'å±¤', 'ï¨¼' => 'å±®', 'ï¨½' => 'æ‚”', 'ï¨¾' => 'æ…¨', 'ï¨¿' => 'æ†Ž', 'ï©€' => 'æ‡²', 'ï©�' => 'æ•�', 'ï©‚' => 'æ—¢', 'ï©ƒ' => 'æš‘', 'ï©„' => 'æ¢…', 'ï©…' => 'æµ·', 'ï©†' => 'æ¸š', 'ï©‡' => 'æ¼¢', 'ï©ˆ' => 'ç…®', 'ï©‰' => 'çˆ«', 'ï©Š' => 'ç�¢', 'ï©‹' => 'ç¢‘', 'ï©Œ' => 'ç¤¾', 'ï©�' => 'ç¥‰', 'ï©Ž' => 'ç¥ˆ', 'ï©�' => 'ç¥�', 'ï©�' => 'ç¥–', 'ï©‘' => 'ç¥�', 'ï©’' => 'ç¦�', 'ï©“' => 'ç¦Ž', 'ï©”' => 'ç©€', 'ï©•' => 'çª�', 'ï©–' => 'ç¯€', 'ï©—' => 'ç·´', 'ï©˜' => 'ç¸‰', 'ï©™' => 'ç¹�', 'ï©š' => 'ç½²', 'ï©›' => 'è€…', 'ï©œ' => 'è‡­', 'ï©�' => 'è‰¹', 'ï©ž' => 'è‰¹', 'ï©Ÿ' => 'è‘—', 'ï© ' => 'è¤�', 'ï©¡' => 'è¦–', 'ï©¢' => 'è¬�', 'ï©£' => 'è¬¹', 'ï©¤' => 'è³“', 'ï©¥' => 'è´ˆ', 'ï©¦' => 'è¾¶', 'ï©§' => 'é€¸', 'ï©¨' => 'é›£', 'ï©©' => 'éŸ¿', 'ï©ª' => 'é »', 'ï©«' => 'æ�µ', 'ï©¬' => 'ð¤‹®', 'ï©­' => 'èˆ˜', 'ï©°' => 'ä¸¦', 'ï©±' => 'å†µ', 'ï©²' => 'å…¨', 'ï©³' => 'ä¾€', 'ï©´' => 'å……', 'ï©µ' => 'å†€', 'ï©¶' => 'å‹‡', 'ï©·' => 'å‹º', 'ï©¸' => 'å–�', 'ï©¹' => 'å••', 'ï©º' => 'å–™', 'ï©»' => 'å—¢', 'ï©¼' => 'å¡š', 'ï©½' => 'å¢³', 'ï©¾' => 'å¥„', 'ï©¿' => 'å¥”', 'ïª€' => 'å©¢', 'ïª�' => 'å¬¨', 'ïª‚' => 'å»’', 'ïªƒ' => 'å»™', 'ïª„' => 'å½©', 'ïª…' => 'å¾­', 'ïª†' => 'æƒ˜', 'ïª‡' => 'æ…Ž', 'ïªˆ' => 'æ„ˆ', 'ïª‰' => 'æ†Ž', 'ïªŠ' => 'æ… ', 'ïª‹' => 'æ‡²', 'ïªŒ' => 'æˆ´', 'ïª�' => 'æ�„', 'ïªŽ' => 'æ�œ', 'ïª�' => 'æ‘’', 'ïª�' => 'æ•–', 'ïª‘' => 'æ™´', 'ïª’' => 'æœ—', 'ïª“' => 'æœ›', 'ïª”' => 'æ�–', 'ïª•' => 'æ­¹', 'ïª–' => 'æ®º', 'ïª—' => 'æµ�', 'ïª˜' => 'æ»›', 'ïª™' => 'æ»‹', 'ïªš' => 'æ¼¢', 'ïª›' => 'ç€ž', 'ïªœ' => 'ç…®', 'ïª�' => 'çž§', 'ïªž' => 'çˆµ', 'ïªŸ' => 'çŠ¯', 'ïª ' => 'çŒª', 'ïª¡' => 'ç‘±', 'ïª¢' => 'ç”†', 'ïª£' => 'ç”»', 'ïª¤' => 'ç˜�', 'ïª¥' => 'ç˜Ÿ', 'ïª¦' => 'ç›Š', 'ïª§' => 'ç››', 'ïª¨' => 'ç›´', 'ïª©' => 'ç�Š', 'ïªª' => 'ç�€', 'ïª«' => 'ç£Œ', 'ïª¬' => 'çª±', 'ïª­' => 'ç¯€', 'ïª®' => 'ç±»', 'ïª¯' => 'çµ›', 'ïª°' => 'ç·´', 'ïª±' => 'ç¼¾', 'ïª²' => 'è€…', 'ïª³' => 'è�’', 'ïª´' => 'è�¯', 'ïªµ' => 'è�¹', 'ïª¶' => 'è¥�', 'ïª·' => 'è¦†', 'ïª¸' => 'è¦–', 'ïª¹' => 'èª¿', 'ïªº' => 'è«¸', 'ïª»' => 'è«‹', 'ïª¼' => 'è¬�', 'ïª½' => 'è«¾', 'ïª¾' => 'è«­', 'ïª¿' => 'è¬¹', 'ï«€' => 'è®Š', 'ï«�' => 'è´ˆ', 'ï«‚' => 'è¼¸', 'ï«ƒ' => 'é�²', 'ï«„' => 'é†™', 'ï«…' => 'é‰¶', 'ï«†' => 'é™¼', 'ï«‡' => 'é›£', 'ï«ˆ' => 'é�–', 'ï«‰' => 'éŸ›', 'ï«Š' => 'éŸ¿', 'ï«‹' => 'é ‹', 'ï«Œ' => 'é »', 'ï«�' => 'é¬’', 'ï«Ž' => 'é¾œ', 'ï«�' => 'ð¢¡Š', 'ï«�' => 'ð¢¡„', 'ï«‘' => 'ð£�•', 'ï«’' => 'ã®�', 'ï«“' => 'ä€˜', 'ï«”' => 'ä€¹', 'ï«•' => 'ð¥‰‰', 'ï«–' => 'ð¥³�', 'ï«—' => 'ð§»“', 'ï«˜' => 'é½ƒ', 'ï«™' => 'é¾Ž', 'ï¬�' => '×™Ö´', 'ï¬Ÿ' => '×²Ö·', 'ï¬ª' => '×©×�', 'ï¬«' => '×©×‚', 'ï¬¬' => '×©Ö¼×�', 'ï¬­' => '×©Ö¼×‚', 'ï¬®' => '×�Ö·', 'ï¬¯' => '×�Ö¸', 'ï¬°' => '×�Ö¼', 'ï¬±' => '×‘Ö¼', 'ï¬²' => '×’Ö¼', 'ï¬³' => '×“Ö¼', 'ï¬´' => '×”Ö¼', 'ï¬µ' => '×•Ö¼', 'ï¬¶' => '×–Ö¼', 'ï¬¸' => '×˜Ö¼', 'ï¬¹' => '×™Ö¼', 'ï¬º' => '×šÖ¼', 'ï¬»' => '×›Ö¼', 'ï¬¼' => '×œÖ¼', 'ï¬¾' => '×žÖ¼', 'ï­€' => '× Ö¼', 'ï­�' => '×¡Ö¼', 'ï­ƒ' => '×£Ö¼', 'ï­„' => '×¤Ö¼', 'ï­†' => '×¦Ö¼', 'ï­‡' => '×§Ö¼', 'ï­ˆ' => '×¨Ö¼', 'ï­‰' => '×©Ö¼', 'ï­Š' => '×ªÖ¼', 'ï­‹' => '×•Ö¹', 'ï­Œ' => '×‘Ö¿', 'ï­�' => '×›Ö¿', 'ï­Ž' => '×¤Ö¿', 'ð‘‚š' => 'ð‘‚™ð‘‚º', 'ð‘‚œ' => 'ð‘‚›ð‘‚º', 'ð‘‚«' => 'ð‘‚¥ð‘‚º', 'ð‘„®' => 'ð‘„±ð‘„§', 'ð‘„¯' => 'ð‘„²ð‘„§', 'ð‘�‹' => 'ð‘�‡ð‘Œ¾', 'ð‘�Œ' => 'ð‘�‡ð‘�—', 'ð‘’»' => 'ð‘’¹ð‘’º', 'ð‘’¼' => 'ð‘’¹ð‘’°', 'ð‘’¾' => 'ð‘’¹ð‘’½', 'ð‘–º' => 'ð‘–¸ð‘–¯', 'ð‘–»' => 'ð‘–¹ð‘–¯', 'ð‘¤¸' => 'ð‘¤µð‘¤°', 'ð�…ž' => 'ð�…—ð�…¥', 'ð�…Ÿ' => 'ð�…˜ð�…¥', 'ð�… ' => 'ð�…˜ð�…¥ð�…®', 'ð�…¡' => 'ð�…˜ð�…¥ð�…¯', 'ð�…¢' => 'ð�…˜ð�…¥ð�…°', 'ð�…£' => 'ð�…˜ð�…¥ð�…±', 'ð�…¤' => 'ð�…˜ð�…¥ð�…²', 'ð�†»' => 'ð�†¹ð�…¥', 'ð�†¼' => 'ð�†ºð�…¥', 'ð�†½' => 'ð�†¹ð�…¥ð�…®', 'ð�†¾' => 'ð�†ºð�…¥ð�…®', 'ð�†¿' => 'ð�†¹ð�…¥ð�…¯', 'ð�‡€' => 'ð�†ºð�…¥ð�…¯', 'ð¯ €' => 'ä¸½', 'ð¯ �' => 'ä¸¸', 'ð¯ ‚' => 'ä¹�', 'ð¯ ƒ' => 'ð „¢', 'ð¯ „' => 'ä½ ', 'ð¯ …' => 'ä¾®', 'ð¯ †' => 'ä¾»', 'ð¯ ‡' => 'å€‚', 'ð¯ ˆ' => 'å�º', 'ð¯ ‰' => 'å‚™', 'ð¯ Š' => 'åƒ§', 'ð¯ ‹' => 'åƒ�', 'ð¯ Œ' => 'ã’ž', 'ð¯ �' => 'ð ˜º', 'ð¯ Ž' => 'å…�', 'ð¯ �' => 'å…”', 'ð¯ �' => 'å…¤', 'ð¯ ‘' => 'å…·', 'ð¯ ’' => 'ð ”œ', 'ð¯ “' => 'ã’¹', 'ð¯ ”' => 'å…§', 'ð¯ •' => 'å†�', 'ð¯ –' => 'ð •‹', 'ð¯ —' => 'å†—', 'ð¯ ˜' => 'å†¤', 'ð¯ ™' => 'ä»Œ', 'ð¯ š' => 'å†¬', 'ð¯ ›' => 'å†µ', 'ð¯ œ' => 'ð©‡Ÿ', 'ð¯ �' => 'å‡µ', 'ð¯ ž' => 'åˆƒ', 'ð¯ Ÿ' => 'ã“Ÿ', 'ð¯  ' => 'åˆ»', 'ð¯ ¡' => 'å‰†', 'ð¯ ¢' => 'å‰²', 'ð¯ £' => 'å‰·', 'ð¯ ¤' => 'ã”•', 'ð¯ ¥' => 'å‹‡', 'ð¯ ¦' => 'å‹‰', 'ð¯ §' => 'å‹¤', 'ð¯ ¨' => 'å‹º', 'ð¯ ©' => 'åŒ…', 'ð¯ ª' => 'åŒ†', 'ð¯ «' => 'åŒ—', 'ð¯ ¬' => 'å�‰', 'ð¯ ­' => 'å�‘', 'ð¯ ®' => 'å�š', 'ð¯ ¯' => 'å�³', 'ð¯ °' => 'å�½', 'ð¯ ±' => 'å�¿', 'ð¯ ²' => 'å�¿', 'ð¯ ³' => 'å�¿', 'ð¯ ´' => 'ð ¨¬', 'ð¯ µ' => 'ç�°', 'ð¯ ¶' => 'å�Š', 'ð¯ ·' => 'å�Ÿ', 'ð¯ ¸' => 'ð ­£', 'ð¯ ¹' => 'å�«', 'ð¯ º' => 'å�±', 'ð¯ »' => 'å�†', 'ð¯ ¼' => 'å’ž', 'ð¯ ½' => 'å�¸', 'ð¯ ¾' => 'å‘ˆ', 'ð¯ ¿' => 'å‘¨', 'ð¯¡€' => 'å’¢', 'ð¯¡�' => 'å“¶', 'ð¯¡‚' => 'å”�', 'ð¯¡ƒ' => 'å•“', 'ð¯¡„' => 'å•£', 'ð¯¡…' => 'å–„', 'ð¯¡†' => 'å–„', 'ð¯¡‡' => 'å–™', 'ð¯¡ˆ' => 'å–«', 'ð¯¡‰' => 'å–³', 'ð¯¡Š' => 'å—‚', 'ð¯¡‹' => 'åœ–', 'ð¯¡Œ' => 'å˜†', 'ð¯¡�' => 'åœ—', 'ð¯¡Ž' => 'å™‘', 'ð¯¡�' => 'å™´', 'ð¯¡�' => 'åˆ‡', 'ð¯¡‘' => 'å£®', 'ð¯¡’' => 'åŸŽ', 'ð¯¡“' => 'åŸ´', 'ð¯¡”' => 'å �', 'ð¯¡•' => 'åž‹', 'ð¯¡–' => 'å ²', 'ð¯¡—' => 'å ±', 'ð¯¡˜' => 'å¢¬', 'ð¯¡™' => 'ð¡“¤', 'ð¯¡š' => 'å£²', 'ð¯¡›' => 'å£·', 'ð¯¡œ' => 'å¤†', 'ð¯¡�' => 'å¤š', 'ð¯¡ž' => 'å¤¢', 'ð¯¡Ÿ' => 'å¥¢', 'ð¯¡ ' => 'ð¡š¨', 'ð¯¡¡' => 'ð¡›ª', 'ð¯¡¢' => 'å§¬', 'ð¯¡£' => 'å¨›', 'ð¯¡¤' => 'å¨§', 'ð¯¡¥' => 'å§˜', 'ð¯¡¦' => 'å©¦', 'ð¯¡§' => 'ã›®', 'ð¯¡¨' => 'ã›¼', 'ð¯¡©' => 'å¬ˆ', 'ð¯¡ª' => 'å¬¾', 'ð¯¡«' => 'å¬¾', 'ð¯¡¬' => 'ð¡§ˆ', 'ð¯¡­' => 'å¯ƒ', 'ð¯¡®' => 'å¯˜', 'ð¯¡¯' => 'å¯§', 'ð¯¡°' => 'å¯³', 'ð¯¡±' => 'ð¡¬˜', 'ð¯¡²' => 'å¯¿', 'ð¯¡³' => 'å°†', 'ð¯¡´' => 'å½“', 'ð¯¡µ' => 'å°¢', 'ð¯¡¶' => 'ãž�', 'ð¯¡·' => 'å± ', 'ð¯¡¸' => 'å±®', 'ð¯¡¹' => 'å³€', 'ð¯¡º' => 'å²�', 'ð¯¡»' => 'ð¡·¤', 'ð¯¡¼' => 'åµƒ', 'ð¯¡½' => 'ð¡·¦', 'ð¯¡¾' => 'åµ®', 'ð¯¡¿' => 'åµ«', 'ð¯¢€' => 'åµ¼', 'ð¯¢�' => 'å·¡', 'ð¯¢‚' => 'å·¢', 'ð¯¢ƒ' => 'ã ¯', 'ð¯¢„' => 'å·½', 'ð¯¢…' => 'å¸¨', 'ð¯¢†' => 'å¸½', 'ð¯¢‡' => 'å¹©', 'ð¯¢ˆ' => 'ã¡¢', 'ð¯¢‰' => 'ð¢†ƒ', 'ð¯¢Š' => 'ã¡¼', 'ð¯¢‹' => 'åº°', 'ð¯¢Œ' => 'åº³', 'ð¯¢�' => 'åº¶', 'ð¯¢Ž' => 'å»Š', 'ð¯¢�' => 'ðªŽ’', 'ð¯¢�' => 'å»¾', 'ð¯¢‘' => 'ð¢Œ±', 'ð¯¢’' => 'ð¢Œ±', 'ð¯¢“' => 'èˆ�', 'ð¯¢”' => 'å¼¢', 'ð¯¢•' => 'å¼¢', 'ð¯¢–' => 'ã£‡', 'ð¯¢—' => 'ð£Š¸', 'ð¯¢˜' => 'ð¦‡š', 'ð¯¢™' => 'å½¢', 'ð¯¢š' => 'å½«', 'ð¯¢›' => 'ã££', 'ð¯¢œ' => 'å¾š', 'ð¯¢�' => 'å¿�', 'ð¯¢ž' => 'å¿—', 'ð¯¢Ÿ' => 'å¿¹', 'ð¯¢ ' => 'æ‚�', 'ð¯¢¡' => 'ã¤º', 'ð¯¢¢' => 'ã¤œ', 'ð¯¢£' => 'æ‚”', 'ð¯¢¤' => 'ð¢›”', 'ð¯¢¥' => 'æƒ‡', 'ð¯¢¦' => 'æ…ˆ', 'ð¯¢§' => 'æ…Œ', 'ð¯¢¨' => 'æ…Ž', 'ð¯¢©' => 'æ…Œ', 'ð¯¢ª' => 'æ…º', 'ð¯¢«' => 'æ†Ž', 'ð¯¢¬' => 'æ†²', 'ð¯¢­' => 'æ†¤', 'ð¯¢®' => 'æ†¯', 'ð¯¢¯' => 'æ‡ž', 'ð¯¢°' => 'æ‡²', 'ð¯¢±' => 'æ‡¶', 'ð¯¢²' => 'æˆ�', 'ð¯¢³' => 'æˆ›', 'ð¯¢´' => 'æ‰�', 'ð¯¢µ' => 'æŠ±', 'ð¯¢¶' => 'æ‹”', 'ð¯¢·' => 'æ��', 'ð¯¢¸' => 'ð¢¬Œ', 'ð¯¢¹' => 'æŒ½', 'ð¯¢º' => 'æ‹¼', 'ð¯¢»' => 'æ�¨', 'ð¯¢¼' => 'æŽƒ', 'ð¯¢½' => 'æ�¤', 'ð¯¢¾' => 'ð¢¯±', 'ð¯¢¿' => 'æ�¢', 'ð¯£€' => 'æ�…', 'ð¯£�' => 'æŽ©', 'ð¯£‚' => 'ã¨®', 'ð¯£ƒ' => 'æ‘©', 'ð¯£„' => 'æ‘¾', 'ð¯£…' => 'æ’�', 'ð¯£†' => 'æ‘·', 'ð¯£‡' => 'ã©¬', 'ð¯£ˆ' => 'æ•�', 'ð¯£‰' => 'æ•¬', 'ð¯£Š' => 'ð£€Š', 'ð¯£‹' => 'æ—£', 'ð¯£Œ' => 'æ›¸', 'ð¯£�' => 'æ™‰', 'ð¯£Ž' => 'ã¬™', 'ð¯£�' => 'æš‘', 'ð¯£�' => 'ã¬ˆ', 'ð¯£‘' => 'ã«¤', 'ð¯£’' => 'å†’', 'ð¯£“' => 'å†•', 'ð¯£”' => 'æœ€', 'ð¯£•' => 'æšœ', 'ð¯£–' => 'è‚­', 'ð¯£—' => 'ä�™', 'ð¯£˜' => 'æœ—', 'ð¯£™' => 'æœ›', 'ð¯£š' => 'æœ¡', 'ð¯£›' => 'æ�ž', 'ð¯£œ' => 'æ�“', 'ð¯£�' => 'ð£�ƒ', 'ð¯£ž' => 'ã­‰', 'ð¯£Ÿ' => 'æŸº', 'ð¯£ ' => 'æž…', 'ð¯£¡' => 'æ¡’', 'ð¯£¢' => 'æ¢…', 'ð¯££' => 'ð£‘­', 'ð¯£¤' => 'æ¢Ž', 'ð¯£¥' => 'æ Ÿ', 'ð¯£¦' => 'æ¤”', 'ð¯£§' => 'ã®�', 'ð¯£¨' => 'æ¥‚', 'ð¯£©' => 'æ¦£', 'ð¯£ª' => 'æ§ª', 'ð¯£«' => 'æª¨', 'ð¯£¬' => 'ð£š£', 'ð¯£­' => 'æ«›', 'ð¯£®' => 'ã°˜', 'ð¯£¯' => 'æ¬¡', 'ð¯£°' => 'ð£¢§', 'ð¯£±' => 'æ­”', 'ð¯£²' => 'ã±Ž', 'ð¯£³' => 'æ­²', 'ð¯£´' => 'æ®Ÿ', 'ð¯£µ' => 'æ®º', 'ð¯£¶' => 'æ®»', 'ð¯£·' => 'ð£ª�', 'ð¯£¸' => 'ð¡´‹', 'ð¯£¹' => 'ð£«º', 'ð¯£º' => 'æ±Ž', 'ð¯£»' => 'ð£²¼', 'ð¯£¼' => 'æ²¿', 'ð¯£½' => 'æ³�', 'ð¯£¾' => 'æ±§', 'ð¯£¿' => 'æ´–', 'ð¯¤€' => 'æ´¾', 'ð¯¤�' => 'æµ·', 'ð¯¤‚' => 'æµ�', 'ð¯¤ƒ' => 'æµ©', 'ð¯¤„' => 'æµ¸', 'ð¯¤…' => 'æ¶…', 'ð¯¤†' => 'ð£´ž', 'ð¯¤‡' => 'æ´´', 'ð¯¤ˆ' => 'æ¸¯', 'ð¯¤‰' => 'æ¹®', 'ð¯¤Š' => 'ã´³', 'ð¯¤‹' => 'æ»‹', 'ð¯¤Œ' => 'æ»‡', 'ð¯¤�' => 'ð£»‘', 'ð¯¤Ž' => 'æ·¹', 'ð¯¤�' => 'æ½®', 'ð¯¤�' => 'ð£½ž', 'ð¯¤‘' => 'ð£¾Ž', 'ð¯¤’' => 'æ¿†', 'ð¯¤“' => 'ç€¹', 'ð¯¤”' => 'ç€ž', 'ð¯¤•' => 'ç€›', 'ð¯¤–' => 'ã¶–', 'ð¯¤—' => 'ç�Š', 'ð¯¤˜' => 'ç�½', 'ð¯¤™' => 'ç�·', 'ð¯¤š' => 'ç‚­', 'ð¯¤›' => 'ð ”¥', 'ð¯¤œ' => 'ç……', 'ð¯¤�' => 'ð¤‰£', 'ð¯¤ž' => 'ç†œ', 'ð¯¤Ÿ' => 'ð¤Ž«', 'ð¯¤ ' => 'çˆ¨', 'ð¯¤¡' => 'çˆµ', 'ð¯¤¢' => 'ç‰�', 'ð¯¤£' => 'ð¤˜ˆ', 'ð¯¤¤' => 'çŠ€', 'ð¯¤¥' => 'çŠ•', 'ð¯¤¦' => 'ð¤œµ', 'ð¯¤§' => 'ð¤ ”', 'ð¯¤¨' => 'ç�º', 'ð¯¤©' => 'çŽ‹', 'ð¯¤ª' => 'ãº¬', 'ð¯¤«' => 'çŽ¥', 'ð¯¤¬' => 'ãº¸', 'ð¯¤­' => 'ãº¸', 'ð¯¤®' => 'ç‘‡', 'ð¯¤¯' => 'ç‘œ', 'ð¯¤°' => 'ç‘±', 'ð¯¤±' => 'ç’…', 'ð¯¤²' => 'ç“Š', 'ð¯¤³' => 'ã¼›', 'ð¯¤´' => 'ç”¤', 'ð¯¤µ' => 'ð¤°¶', 'ð¯¤¶' => 'ç”¾', 'ð¯¤·' => 'ð¤²’', 'ð¯¤¸' => 'ç•°', 'ð¯¤¹' => 'ð¢†Ÿ', 'ð¯¤º' => 'ç˜�', 'ð¯¤»' => 'ð¤¾¡', 'ð¯¤¼' => 'ð¤¾¸', 'ð¯¤½' => 'ð¥�„', 'ð¯¤¾' => 'ã¿¼', 'ð¯¤¿' => 'ä€ˆ', 'ð¯¥€' => 'ç›´', 'ð¯¥�' => 'ð¥ƒ³', 'ð¯¥‚' => 'ð¥ƒ²', 'ð¯¥ƒ' => 'ð¥„™', 'ð¯¥„' => 'ð¥„³', 'ð¯¥…' => 'çœž', 'ð¯¥†' => 'çœŸ', 'ð¯¥‡' => 'çœŸ', 'ð¯¥ˆ' => 'ç�Š', 'ð¯¥‰' => 'ä€¹', 'ð¯¥Š' => 'çž‹', 'ð¯¥‹' => 'ä�†', 'ð¯¥Œ' => 'ä‚–', 'ð¯¥�' => 'ð¥��', 'ð¯¥Ž' => 'ç¡Ž', 'ð¯¥�' => 'ç¢Œ', 'ð¯¥�' => 'ç£Œ', 'ð¯¥‘' => 'äƒ£', 'ð¯¥’' => 'ð¥˜¦', 'ð¯¥“' => 'ç¥–', 'ð¯¥”' => 'ð¥šš', 'ð¯¥•' => 'ð¥›…', 'ð¯¥–' => 'ç¦�', 'ð¯¥—' => 'ç§«', 'ð¯¥˜' => 'ä„¯', 'ð¯¥™' => 'ç©€', 'ð¯¥š' => 'ç©Š', 'ð¯¥›' => 'ç©�', 'ð¯¥œ' => 'ð¥¥¼', 'ð¯¥�' => 'ð¥ª§', 'ð¯¥ž' => 'ð¥ª§', 'ð¯¥Ÿ' => 'ç«®', 'ð¯¥ ' => 'äˆ‚', 'ð¯¥¡' => 'ð¥®«', 'ð¯¥¢' => 'ç¯†', 'ð¯¥£' => 'ç¯‰', 'ð¯¥¤' => 'äˆ§', 'ð¯¥¥' => 'ð¥²€', 'ð¯¥¦' => 'ç³’', 'ð¯¥§' => 'äŠ ', 'ð¯¥¨' => 'ç³¨', 'ð¯¥©' => 'ç³£', 'ð¯¥ª' => 'ç´€', 'ð¯¥«' => 'ð¥¾†', 'ð¯¥¬' => 'çµ£', 'ð¯¥­' => 'äŒ�', 'ð¯¥®' => 'ç·‡', 'ð¯¥¯' => 'ç¸‚', 'ð¯¥°' => 'ç¹…', 'ð¯¥±' => 'äŒ´', 'ð¯¥²' => 'ð¦ˆ¨', 'ð¯¥³' => 'ð¦‰‡', 'ð¯¥´' => 'ä�™', 'ð¯¥µ' => 'ð¦‹™', 'ð¯¥¶' => 'ç½º', 'ð¯¥·' => 'ð¦Œ¾', 'ð¯¥¸' => 'ç¾•', 'ð¯¥¹' => 'ç¿º', 'ð¯¥º' => 'è€…', 'ð¯¥»' => 'ð¦“š', 'ð¯¥¼' => 'ð¦”£', 'ð¯¥½' => 'è� ', 'ð¯¥¾' => 'ð¦–¨', 'ð¯¥¿' => 'è�°', 'ð¯¦€' => 'ð£�Ÿ', 'ð¯¦�' => 'ä�•', 'ð¯¦‚' => 'è‚²', 'ð¯¦ƒ' => 'è„ƒ', 'ð¯¦„' => 'ä�‹', 'ð¯¦…' => 'è„¾', 'ð¯¦†' => 'åªµ', 'ð¯¦‡' => 'ð¦ž§', 'ð¯¦ˆ' => 'ð¦žµ', 'ð¯¦‰' => 'ð£Ž“', 'ð¯¦Š' => 'ð£Žœ', 'ð¯¦‹' => 'èˆ�', 'ð¯¦Œ' => 'èˆ„', 'ð¯¦�' => 'è¾ž', 'ð¯¦Ž' => 'ä‘«', 'ð¯¦�' => 'èŠ‘', 'ð¯¦�' => 'èŠ‹', 'ð¯¦‘' => 'èŠ�', 'ð¯¦’' => 'åŠ³', 'ð¯¦“' => 'èŠ±', 'ð¯¦”' => 'èŠ³', 'ð¯¦•' => 'èŠ½', 'ð¯¦–' => 'è‹¦', 'ð¯¦—' => 'ð¦¬¼', 'ð¯¦˜' => 'è‹¥', 'ð¯¦™' => 'èŒ�', 'ð¯¦š' => 'è�£', 'ð¯¦›' => 'èŽ­', 'ð¯¦œ' => 'èŒ£', 'ð¯¦�' => 'èŽ½', 'ð¯¦ž' => 'è�§', 'ð¯¦Ÿ' => 'è‘—', 'ð¯¦ ' => 'è�“', 'ð¯¦¡' => 'è�Š', 'ð¯¦¢' => 'è�Œ', 'ð¯¦£' => 'è�œ', 'ð¯¦¤' => 'ð¦°¶', 'ð¯¦¥' => 'ð¦µ«', 'ð¯¦¦' => 'ð¦³•', 'ð¯¦§' => 'ä”«', 'ð¯¦¨' => 'è“±', 'ð¯¦©' => 'è“³', 'ð¯¦ª' => 'è”–', 'ð¯¦«' => 'ð§�Š', 'ð¯¦¬' => 'è•¤', 'ð¯¦­' => 'ð¦¼¬', 'ð¯¦®' => 'ä•�', 'ð¯¦¯' => 'ä•¡', 'ð¯¦°' => 'ð¦¾±', 'ð¯¦±' => 'ð§ƒ’', 'ð¯¦²' => 'ä•«', 'ð¯¦³' => 'è™�', 'ð¯¦´' => 'è™œ', 'ð¯¦µ' => 'è™§', 'ð¯¦¶' => 'è™©', 'ð¯¦·' => 'èš©', 'ð¯¦¸' => 'èšˆ', 'ð¯¦¹' => 'èœŽ', 'ð¯¦º' => 'è›¢', 'ð¯¦»' => 'è�¹', 'ð¯¦¼' => 'èœ¨', 'ð¯¦½' => 'è�«', 'ð¯¦¾' => 'èž†', 'ð¯¦¿' => 'ä——', 'ð¯§€' => 'èŸ¡', 'ð¯§�' => 'è �', 'ð¯§‚' => 'ä—¹', 'ð¯§ƒ' => 'è¡ ', 'ð¯§„' => 'è¡£', 'ð¯§…' => 'ð§™§', 'ð¯§†' => 'è£—', 'ð¯§‡' => 'è£ž', 'ð¯§ˆ' => 'ä˜µ', 'ð¯§‰' => 'è£º', 'ð¯§Š' => 'ã’»', 'ð¯§‹' => 'ð§¢®', 'ð¯§Œ' => 'ð§¥¦', 'ð¯§�' => 'äš¾', 'ð¯§Ž' => 'ä›‡', 'ð¯§�' => 'èª ', 'ð¯§�' => 'è«­', 'ð¯§‘' => 'è®Š', 'ð¯§’' => 'è±•', 'ð¯§“' => 'ð§²¨', 'ð¯§”' => 'è²«', 'ð¯§•' => 'è³�', 'ð¯§–' => 'è´›', 'ð¯§—' => 'èµ·', 'ð¯§˜' => 'ð§¼¯', 'ð¯§™' => 'ð  „', 'ð¯§š' => 'è·‹', 'ð¯§›' => 'è¶¼', 'ð¯§œ' => 'è·°', 'ð¯§�' => 'ð £ž', 'ð¯§ž' => 'è»”', 'ð¯§Ÿ' => 'è¼¸', 'ð¯§ ' => 'ð¨—’', 'ð¯§¡' => 'ð¨—­', 'ð¯§¢' => 'é‚”', 'ð¯§£' => 'éƒ±', 'ð¯§¤' => 'é„‘', 'ð¯§¥' => 'ð¨œ®', 'ð¯§¦' => 'é„›', 'ð¯§§' => 'éˆ¸', 'ð¯§¨' => 'é‹—', 'ð¯§©' => 'é‹˜', 'ð¯§ª' => 'é‰¼', 'ð¯§«' => 'é�¹', 'ð¯§¬' => 'é�•', 'ð¯§­' => 'ð¨¯º', 'ð¯§®' => 'é–‹', 'ð¯§¯' => 'ä¦•', 'ð¯§°' => 'é–·', 'ð¯§±' => 'ð¨µ·', 'ð¯§²' => 'ä§¦', 'ð¯§³' => 'é›ƒ', 'ð¯§´' => 'å¶²', 'ð¯§µ' => 'éœ£', 'ð¯§¶' => 'ð©……', 'ð¯§·' => 'ð©ˆš', 'ð¯§¸' => 'ä©®', 'ð¯§¹' => 'ä©¶', 'ð¯§º' => 'éŸ ', 'ð¯§»' => 'ð©�Š', 'ð¯§¼' => 'äª²', 'ð¯§½' => 'ð©’–', 'ð¯§¾' => 'é ‹', 'ð¯§¿' => 'é ‹', 'ð¯¨€' => 'é ©', 'ð¯¨�' => 'ð©–¶', 'ð¯¨‚' => 'é£¢', 'ð¯¨ƒ' => 'ä¬³', 'ð¯¨„' => 'é¤©', 'ð¯¨…' => 'é¦§', 'ð¯¨†' => 'é§‚', 'ð¯¨‡' => 'é§¾', 'ð¯¨ˆ' => 'ä¯Ž', 'ð¯¨‰' => 'ð©¬°', 'ð¯¨Š' => 'é¬’', 'ð¯¨‹' => 'é±€', 'ð¯¨Œ' => 'é³½', 'ð¯¨�' => 'ä³Ž', 'ð¯¨Ž' => 'ä³­', 'ð¯¨�' => 'éµ§', 'ð¯¨�' => 'ðªƒŽ', 'ð¯¨‘' => 'ä³¸', 'ð¯¨’' => 'ðª„…', 'ð¯¨“' => 'ðªˆŽ', 'ð¯¨”' => 'ðªŠ‘', 'ð¯¨•' => 'éº»', 'ð¯¨–' => 'äµ–', 'ð¯¨—' => 'é»¹', 'ð¯¨˜' => 'é»¾', 'ð¯¨™' => 'é¼…', 'ð¯¨š' => 'é¼�', 'ð¯¨›' => 'é¼–', 'ð¯¨œ' => 'é¼»', 'ð¯¨�' => 'ðª˜€');<?php

return array('Ì€' => 230, 'Ì�' => 230, 'Ì‚' => 230, 'Ìƒ' => 230, 'Ì„' => 230, 'Ì…' => 230, 'Ì†' => 230, 'Ì‡' => 230, 'Ìˆ' => 230, 'Ì‰' => 230, 'ÌŠ' => 230, 'Ì‹' => 230, 'ÌŒ' => 230, 'Ì�' => 230, 'ÌŽ' => 230, 'Ì�' => 230, 'Ì�' => 230, 'Ì‘' => 230, 'Ì’' => 230, 'Ì“' => 230, 'Ì”' => 230, 'Ì•' => 232, 'Ì–' => 220, 'Ì—' => 220, 'Ì˜' => 220, 'Ì™' => 220, 'Ìš' => 232, 'Ì›' => 216, 'Ìœ' => 220, 'Ì�' => 220, 'Ìž' => 220, 'ÌŸ' => 220, 'Ì ' => 220, 'Ì¡' => 202, 'Ì¢' => 202, 'Ì£' => 220, 'Ì¤' => 220, 'Ì¥' => 220, 'Ì¦' => 220, 'Ì§' => 202, 'Ì¨' => 202, 'Ì©' => 220, 'Ìª' => 220, 'Ì«' => 220, 'Ì¬' => 220, 'Ì­' => 220, 'Ì®' => 220, 'Ì¯' => 220, 'Ì°' => 220, 'Ì±' => 220, 'Ì²' => 220, 'Ì³' => 220, 'Ì´' => 1, 'Ìµ' => 1, 'Ì¶' => 1, 'Ì·' => 1, 'Ì¸' => 1, 'Ì¹' => 220, 'Ìº' => 220, 'Ì»' => 220, 'Ì¼' => 220, 'Ì½' => 230, 'Ì¾' => 230, 'Ì¿' => 230, 'Í€' => 230, 'Í�' => 230, 'Í‚' => 230, 'Íƒ' => 230, 'Í„' => 230, 'Í…' => 240, 'Í†' => 230, 'Í‡' => 220, 'Íˆ' => 220, 'Í‰' => 220, 'ÍŠ' => 230, 'Í‹' => 230, 'ÍŒ' => 230, 'Í�' => 220, 'ÍŽ' => 220, 'Í�' => 230, 'Í‘' => 230, 'Í’' => 230, 'Í“' => 220, 'Í”' => 220, 'Í•' => 220, 'Í–' => 220, 'Í—' => 230, 'Í˜' => 232, 'Í™' => 220, 'Íš' => 220, 'Í›' => 230, 'Íœ' => 233, 'Í�' => 234, 'Íž' => 234, 'ÍŸ' => 233, 'Í ' => 234, 'Í¡' => 234, 'Í¢' => 233, 'Í£' => 230, 'Í¤' => 230, 'Í¥' => 230, 'Í¦' => 230, 'Í§' => 230, 'Í¨' => 230, 'Í©' => 230, 'Íª' => 230, 'Í«' => 230, 'Í¬' => 230, 'Í­' => 230, 'Í®' => 230, 'Í¯' => 230, 'Òƒ' => 230, 'Ò„' => 230, 'Ò…' => 230, 'Ò†' => 230, 'Ò‡' => 230, 'Ö‘' => 220, 'Ö’' => 230, 'Ö“' => 230, 'Ö”' => 230, 'Ö•' => 230, 'Ö–' => 220, 'Ö—' => 230, 'Ö˜' => 230, 'Ö™' => 230, 'Öš' => 222, 'Ö›' => 220, 'Öœ' => 230, 'Ö�' => 230, 'Öž' => 230, 'ÖŸ' => 230, 'Ö ' => 230, 'Ö¡' => 230, 'Ö¢' => 220, 'Ö£' => 220, 'Ö¤' => 220, 'Ö¥' => 220, 'Ö¦' => 220, 'Ö§' => 220, 'Ö¨' => 230, 'Ö©' => 230, 'Öª' => 220, 'Ö«' => 230, 'Ö¬' => 230, 'Ö­' => 222, 'Ö®' => 228, 'Ö¯' => 230, 'Ö°' => 10, 'Ö±' => 11, 'Ö²' => 12, 'Ö³' => 13, 'Ö´' => 14, 'Öµ' => 15, 'Ö¶' => 16, 'Ö·' => 17, 'Ö¸' => 18, 'Ö¹' => 19, 'Öº' => 19, 'Ö»' => 20, 'Ö¼' => 21, 'Ö½' => 22, 'Ö¿' => 23, '×�' => 24, '×‚' => 25, '×„' => 230, '×…' => 220, '×‡' => 18, 'Ø�' => 230, 'Ø‘' => 230, 'Ø’' => 230, 'Ø“' => 230, 'Ø”' => 230, 'Ø•' => 230, 'Ø–' => 230, 'Ø—' => 230, 'Ø˜' => 30, 'Ø™' => 31, 'Øš' => 32, 'Ù‹' => 27, 'ÙŒ' => 28, 'Ù�' => 29, 'ÙŽ' => 30, 'Ù�' => 31, 'Ù�' => 32, 'Ù‘' => 33, 'Ù’' => 34, 'Ù“' => 230, 'Ù”' => 230, 'Ù•' => 220, 'Ù–' => 220, 'Ù—' => 230, 'Ù˜' => 230, 'Ù™' => 230, 'Ùš' => 230, 'Ù›' => 230, 'Ùœ' => 220, 'Ù�' => 230, 'Ùž' => 230, 'ÙŸ' => 220, 'Ù°' => 35, 'Û–' => 230, 'Û—' => 230, 'Û˜' => 230, 'Û™' => 230, 'Ûš' => 230, 'Û›' => 230, 'Ûœ' => 230, 'ÛŸ' => 230, 'Û ' => 230, 'Û¡' => 230, 'Û¢' => 230, 'Û£' => 220, 'Û¤' => 230, 'Û§' => 230, 'Û¨' => 230, 'Ûª' => 220, 'Û«' => 230, 'Û¬' => 230, 'Û­' => 220, 'Ü‘' => 36, 'Ü°' => 230, 'Ü±' => 220, 'Ü²' => 230, 'Ü³' => 230, 'Ü´' => 220, 'Üµ' => 230, 'Ü¶' => 230, 'Ü·' => 220, 'Ü¸' => 220, 'Ü¹' => 220, 'Üº' => 230, 'Ü»' => 220, 'Ü¼' => 220, 'Ü½' => 230, 'Ü¾' => 220, 'Ü¿' => 230, 'Ý€' => 230, 'Ý�' => 230, 'Ý‚' => 220, 'Ýƒ' => 230, 'Ý„' => 220, 'Ý…' => 230, 'Ý†' => 220, 'Ý‡' => 230, 'Ýˆ' => 220, 'Ý‰' => 230, 'ÝŠ' => 230, 'ß«' => 230, 'ß¬' => 230, 'ß­' => 230, 'ß®' => 230, 'ß¯' => 230, 'ß°' => 230, 'ß±' => 230, 'ß²' => 220, 'ß³' => 230, 'ß½' => 220, 'à –' => 230, 'à —' => 230, 'à ˜' => 230, 'à ™' => 230, 'à ›' => 230, 'à œ' => 230, 'à �' => 230, 'à ž' => 230, 'à Ÿ' => 230, 'à  ' => 230, 'à ¡' => 230, 'à ¢' => 230, 'à £' => 230, 'à ¥' => 230, 'à ¦' => 230, 'à §' => 230, 'à ©' => 230, 'à ª' => 230, 'à «' => 230, 'à ¬' => 230, 'à ­' => 230, 'à¡™' => 220, 'à¡š' => 220, 'à¡›' => 220, 'à£“' => 220, 'à£”' => 230, 'à£•' => 230, 'à£–' => 230, 'à£—' => 230, 'à£˜' => 230, 'à£™' => 230, 'à£š' => 230, 'à£›' => 230, 'à£œ' => 230, 'à£�' => 230, 'à£ž' => 230, 'à£Ÿ' => 230, 'à£ ' => 230, 'à£¡' => 230, 'à££' => 220, 'à£¤' => 230, 'à£¥' => 230, 'à£¦' => 220, 'à£§' => 230, 'à£¨' => 230, 'à£©' => 220, 'à£ª' => 230, 'à£«' => 230, 'à£¬' => 230, 'à£­' => 220, 'à£®' => 220, 'à£¯' => 220, 'à£°' => 27, 'à£±' => 28, 'à£²' => 29, 'à£³' => 230, 'à£´' => 230, 'à£µ' => 230, 'à£¶' => 220, 'à£·' => 230, 'à£¸' => 230, 'à£¹' => 220, 'à£º' => 220, 'à£»' => 230, 'à£¼' => 230, 'à£½' => 230, 'à£¾' => 230, 'à£¿' => 230, 'à¤¼' => 7, 'à¥�' => 9, 'à¥‘' => 230, 'à¥’' => 220, 'à¥“' => 230, 'à¥”' => 230, 'à¦¼' => 7, 'à§�' => 9, 'à§¾' => 230, 'à¨¼' => 7, 'à©�' => 9, 'àª¼' => 7, 'à«�' => 9, 'à¬¼' => 7, 'à­�' => 9, 'à¯�' => 9, 'à±�' => 9, 'à±•' => 84, 'à±–' => 91, 'à²¼' => 7, 'à³�' => 9, 'à´»' => 9, 'à´¼' => 9, 'àµ�' => 9, 'à·Š' => 9, 'à¸¸' => 103, 'à¸¹' => 103, 'à¸º' => 9, 'à¹ˆ' => 107, 'à¹‰' => 107, 'à¹Š' => 107, 'à¹‹' => 107, 'àº¸' => 118, 'àº¹' => 118, 'àºº' => 9, 'à»ˆ' => 122, 'à»‰' => 122, 'à»Š' => 122, 'à»‹' => 122, 'à¼˜' => 220, 'à¼™' => 220, 'à¼µ' => 220, 'à¼·' => 220, 'à¼¹' => 216, 'à½±' => 129, 'à½²' => 130, 'à½´' => 132, 'à½º' => 130, 'à½»' => 130, 'à½¼' => 130, 'à½½' => 130, 'à¾€' => 130, 'à¾‚' => 230, 'à¾ƒ' => 230, 'à¾„' => 9, 'à¾†' => 230, 'à¾‡' => 230, 'à¿†' => 220, 'á€·' => 7, 'á€¹' => 9, 'á€º' => 9, 'á‚�' => 220, 'á��' => 230, 'á�ž' => 230, 'á�Ÿ' => 230, 'áœ”' => 9, 'áœ´' => 9, 'áŸ’' => 9, 'áŸ�' => 230, 'á¢©' => 228, 'á¤¹' => 222, 'á¤º' => 230, 'á¤»' => 220, 'á¨—' => 230, 'á¨˜' => 220, 'á© ' => 9, 'á©µ' => 230, 'á©¶' => 230, 'á©·' => 230, 'á©¸' => 230, 'á©¹' => 230, 'á©º' => 230, 'á©»' => 230, 'á©¼' => 230, 'á©¿' => 220, 'áª°' => 230, 'áª±' => 230, 'áª²' => 230, 'áª³' => 230, 'áª´' => 230, 'áªµ' => 220, 'áª¶' => 220, 'áª·' => 220, 'áª¸' => 220, 'áª¹' => 220, 'áªº' => 220, 'áª»' => 230, 'áª¼' => 230, 'áª½' => 220, 'áª¿' => 220, 'á«€' => 220, 'á¬´' => 7, 'á­„' => 9, 'á­«' => 230, 'á­¬' => 220, 'á­­' => 230, 'á­®' => 230, 'á­¯' => 230, 'á­°' => 230, 'á­±' => 230, 'á­²' => 230, 'á­³' => 230, 'á®ª' => 9, 'á®«' => 9, 'á¯¦' => 7, 'á¯²' => 9, 'á¯³' => 9, 'á°·' => 7, 'á³�' => 230, 'á³‘' => 230, 'á³’' => 230, 'á³”' => 1, 'á³•' => 220, 'á³–' => 220, 'á³—' => 220, 'á³˜' => 220, 'á³™' => 220, 'á³š' => 230, 'á³›' => 230, 'á³œ' => 220, 'á³�' => 220, 'á³ž' => 220, 'á³Ÿ' => 220, 'á³ ' => 230, 'á³¢' => 1, 'á³£' => 1, 'á³¤' => 1, 'á³¥' => 1, 'á³¦' => 1, 'á³§' => 1, 'á³¨' => 1, 'á³­' => 220, 'á³´' => 230, 'á³¸' => 230, 'á³¹' => 230, 'á·€' => 230, 'á·�' => 230, 'á·‚' => 220, 'á·ƒ' => 230, 'á·„' => 230, 'á·…' => 230, 'á·†' => 230, 'á·‡' => 230, 'á·ˆ' => 230, 'á·‰' => 230, 'á·Š' => 220, 'á·‹' => 230, 'á·Œ' => 230, 'á·�' => 234, 'á·Ž' => 214, 'á·�' => 220, 'á·�' => 202, 'á·‘' => 230, 'á·’' => 230, 'á·“' => 230, 'á·”' => 230, 'á·•' => 230, 'á·–' => 230, 'á·—' => 230, 'á·˜' => 230, 'á·™' => 230, 'á·š' => 230, 'á·›' => 230, 'á·œ' => 230, 'á·�' => 230, 'á·ž' => 230, 'á·Ÿ' => 230, 'á· ' => 230, 'á·¡' => 230, 'á·¢' => 230, 'á·£' => 230, 'á·¤' => 230, 'á·¥' => 230, 'á·¦' => 230, 'á·§' => 230, 'á·¨' => 230, 'á·©' => 230, 'á·ª' => 230, 'á·«' => 230, 'á·¬' => 230, 'á·­' => 230, 'á·®' => 230, 'á·¯' => 230, 'á·°' => 230, 'á·±' => 230, 'á·²' => 230, 'á·³' => 230, 'á·´' => 230, 'á·µ' => 230, 'á·¶' => 232, 'á··' => 228, 'á·¸' => 228, 'á·¹' => 220, 'á·»' => 230, 'á·¼' => 233, 'á·½' => 220, 'á·¾' => 230, 'á·¿' => 220, 'âƒ�' => 230, 'âƒ‘' => 230, 'âƒ’' => 1, 'âƒ“' => 1, 'âƒ”' => 230, 'âƒ•' => 230, 'âƒ–' => 230, 'âƒ—' => 230, 'âƒ˜' => 1, 'âƒ™' => 1, 'âƒš' => 1, 'âƒ›' => 230, 'âƒœ' => 230, 'âƒ¡' => 230, 'âƒ¥' => 1, 'âƒ¦' => 1, 'âƒ§' => 230, 'âƒ¨' => 220, 'âƒ©' => 230, 'âƒª' => 1, 'âƒ«' => 1, 'âƒ¬' => 220, 'âƒ­' => 220, 'âƒ®' => 220, 'âƒ¯' => 220, 'âƒ°' => 230, 'â³¯' => 230, 'â³°' => 230, 'â³±' => 230, 'âµ¿' => 9, 'â· ' => 230, 'â·¡' => 230, 'â·¢' => 230, 'â·£' => 230, 'â·¤' => 230, 'â·¥' => 230, 'â·¦' => 230, 'â·§' => 230, 'â·¨' => 230, 'â·©' => 230, 'â·ª' => 230, 'â·«' => 230, 'â·¬' => 230, 'â·­' => 230, 'â·®' => 230, 'â·¯' => 230, 'â·°' => 230, 'â·±' => 230, 'â·²' => 230, 'â·³' => 230, 'â·´' => 230, 'â·µ' => 230, 'â·¶' => 230, 'â··' => 230, 'â·¸' => 230, 'â·¹' => 230, 'â·º' => 230, 'â·»' => 230, 'â·¼' => 230, 'â·½' => 230, 'â·¾' => 230, 'â·¿' => 230, 'ã€ª' => 218, 'ã€«' => 228, 'ã€¬' => 232, 'ã€­' => 222, 'ã€®' => 224, 'ã€¯' => 224, 'ã‚™' => 8, 'ã‚š' => 8, 'ê™¯' => 230, 'ê™´' => 230, 'ê™µ' => 230, 'ê™¶' => 230, 'ê™·' => 230, 'ê™¸' => 230, 'ê™¹' => 230, 'ê™º' => 230, 'ê™»' => 230, 'ê™¼' => 230, 'ê™½' => 230, 'êšž' => 230, 'êšŸ' => 230, 'ê›°' => 230, 'ê›±' => 230, 'ê †' => 9, 'ê ¬' => 9, 'ê£„' => 9, 'ê£ ' => 230, 'ê£¡' => 230, 'ê£¢' => 230, 'ê££' => 230, 'ê£¤' => 230, 'ê£¥' => 230, 'ê£¦' => 230, 'ê£§' => 230, 'ê£¨' => 230, 'ê£©' => 230, 'ê£ª' => 230, 'ê£«' => 230, 'ê£¬' => 230, 'ê£­' => 230, 'ê£®' => 230, 'ê£¯' => 230, 'ê£°' => 230, 'ê£±' => 230, 'ê¤«' => 220, 'ê¤¬' => 220, 'ê¤­' => 220, 'ê¥“' => 9, 'ê¦³' => 7, 'ê§€' => 9, 'êª°' => 230, 'êª²' => 230, 'êª³' => 230, 'êª´' => 220, 'êª·' => 230, 'êª¸' => 230, 'êª¾' => 230, 'êª¿' => 230, 'ê«�' => 230, 'ê«¶' => 9, 'ê¯­' => 9, 'ï¬ž' => 26, 'ï¸ ' => 230, 'ï¸¡' => 230, 'ï¸¢' => 230, 'ï¸£' => 230, 'ï¸¤' => 230, 'ï¸¥' => 230, 'ï¸¦' => 230, 'ï¸§' => 220, 'ï¸¨' => 220, 'ï¸©' => 220, 'ï¸ª' => 220, 'ï¸«' => 220, 'ï¸¬' => 220, 'ï¸­' => 220, 'ï¸®' => 230, 'ï¸¯' => 230, 'ð�‡½' => 220, 'ð�‹ ' => 220, 'ð��¶' => 230, 'ð��·' => 230, 'ð��¸' => 230, 'ð��¹' => 230, 'ð��º' => 230, 'ð�¨�' => 220, 'ð�¨�' => 230, 'ð�¨¸' => 230, 'ð�¨¹' => 1, 'ð�¨º' => 220, 'ð�¨¿' => 9, 'ð�«¥' => 230, 'ð�«¦' => 220, 'ð�´¤' => 230, 'ð�´¥' => 230, 'ð�´¦' => 230, 'ð�´§' => 230, 'ð�º«' => 230, 'ð�º¬' => 230, 'ð�½†' => 220, 'ð�½‡' => 220, 'ð�½ˆ' => 230, 'ð�½‰' => 230, 'ð�½Š' => 230, 'ð�½‹' => 220, 'ð�½Œ' => 230, 'ð�½�' => 220, 'ð�½Ž' => 220, 'ð�½�' => 220, 'ð�½�' => 220, 'ð‘�†' => 9, 'ð‘�¿' => 9, 'ð‘‚¹' => 9, 'ð‘‚º' => 7, 'ð‘„€' => 230, 'ð‘„�' => 230, 'ð‘„‚' => 230, 'ð‘„³' => 9, 'ð‘„´' => 9, 'ð‘…³' => 7, 'ð‘‡€' => 9, 'ð‘‡Š' => 7, 'ð‘ˆµ' => 9, 'ð‘ˆ¶' => 7, 'ð‘‹©' => 7, 'ð‘‹ª' => 9, 'ð‘Œ»' => 7, 'ð‘Œ¼' => 7, 'ð‘��' => 9, 'ð‘�¦' => 230, 'ð‘�§' => 230, 'ð‘�¨' => 230, 'ð‘�©' => 230, 'ð‘�ª' => 230, 'ð‘�«' => 230, 'ð‘�¬' => 230, 'ð‘�°' => 230, 'ð‘�±' => 230, 'ð‘�²' => 230, 'ð‘�³' => 230, 'ð‘�´' => 230, 'ð‘‘‚' => 9, 'ð‘‘†' => 7, 'ð‘‘ž' => 230, 'ð‘“‚' => 9, 'ð‘“ƒ' => 7, 'ð‘–¿' => 9, 'ð‘—€' => 7, 'ð‘˜¿' => 9, 'ð‘š¶' => 9, 'ð‘š·' => 7, 'ð‘œ«' => 9, 'ð‘ ¹' => 9, 'ð‘ º' => 7, 'ð‘¤½' => 9, 'ð‘¤¾' => 9, 'ð‘¥ƒ' => 7, 'ð‘§ ' => 9, 'ð‘¨´' => 9, 'ð‘©‡' => 9, 'ð‘ª™' => 9, 'ð‘°¿' => 9, 'ð‘µ‚' => 7, 'ð‘µ„' => 9, 'ð‘µ…' => 9, 'ð‘¶—' => 9, 'ð–«°' => 1, 'ð–«±' => 1, 'ð–«²' => 1, 'ð–«³' => 1, 'ð–«´' => 1, 'ð–¬°' => 230, 'ð–¬±' => 230, 'ð–¬²' => 230, 'ð–¬³' => 230, 'ð–¬´' => 230, 'ð–¬µ' => 230, 'ð–¬¶' => 230, 'ð–¿°' => 6, 'ð–¿±' => 6, 'ð›²ž' => 1, 'ð�…¥' => 216, 'ð�…¦' => 216, 'ð�…§' => 1, 'ð�…¨' => 1, 'ð�…©' => 1, 'ð�…­' => 226, 'ð�…®' => 216, 'ð�…¯' => 216, 'ð�…°' => 216, 'ð�…±' => 216, 'ð�…²' => 216, 'ð�…»' => 220, 'ð�…¼' => 220, 'ð�…½' => 220, 'ð�…¾' => 220, 'ð�…¿' => 220, 'ð�†€' => 220, 'ð�†�' => 220, 'ð�†‚' => 220, 'ð�†…' => 230, 'ð�††' => 230, 'ð�†‡' => 230, 'ð�†ˆ' => 230, 'ð�†‰' => 230, 'ð�†Š' => 220, 'ð�†‹' => 220, 'ð�†ª' => 230, 'ð�†«' => 230, 'ð�†¬' => 230, 'ð�†­' => 230, 'ð�‰‚' => 230, 'ð�‰ƒ' => 230, 'ð�‰„' => 230, 'ðž€€' => 230, 'ðž€�' => 230, 'ðž€‚' => 230, 'ðž€ƒ' => 230, 'ðž€„' => 230, 'ðž€…' => 230, 'ðž€†' => 230, 'ðž€ˆ' => 230, 'ðž€‰' => 230, 'ðž€Š' => 230, 'ðž€‹' => 230, 'ðž€Œ' => 230, 'ðž€�' => 230, 'ðž€Ž' => 230, 'ðž€�' => 230, 'ðž€�' => 230, 'ðž€‘' => 230, 'ðž€’' => 230, 'ðž€“' => 230, 'ðž€”' => 230, 'ðž€•' => 230, 'ðž€–' => 230, 'ðž€—' => 230, 'ðž€˜' => 230, 'ðž€›' => 230, 'ðž€œ' => 230, 'ðž€�' => 230, 'ðž€ž' => 230, 'ðž€Ÿ' => 230, 'ðž€ ' => 230, 'ðž€¡' => 230, 'ðž€£' => 230, 'ðž€¤' => 230, 'ðž€¦' => 230, 'ðž€§' => 230, 'ðž€¨' => 230, 'ðž€©' => 230, 'ðž€ª' => 230, 'ðž„°' => 230, 'ðž„±' => 230, 'ðž„²' => 230, 'ðž„³' => 230, 'ðž„´' => 230, 'ðž„µ' => 230, 'ðž„¶' => 230, 'ðž‹¬' => 230, 'ðž‹­' => 230, 'ðž‹®' => 230, 'ðž‹¯' => 230, 'ðž£�' => 220, 'ðž£‘' => 220, 'ðž£’' => 220, 'ðž£“' => 220, 'ðž£”' => 220, 'ðž£•' => 220, 'ðž£–' => 220, 'ðž¥„' => 230, 'ðž¥…' => 230, 'ðž¥†' => 230, 'ðž¥‡' => 230, 'ðž¥ˆ' => 230, 'ðž¥‰' => 230, 'ðž¥Š' => 7);<?php

return array('Â ' => ' ', 'Â¨' => ' Ìˆ', 'Âª' => 'a', 'Â¯' => ' Ì„', 'Â²' => '2', 'Â³' => '3', 'Â´' => ' Ì�', 'Âµ' => 'Î¼', 'Â¸' => ' Ì§', 'Â¹' => '1', 'Âº' => 'o', 'Â¼' => '1â�„4', 'Â½' => '1â�„2', 'Â¾' => '3â�„4', 'Ä²' => 'IJ', 'Ä³' => 'ij', 'Ä¿' => 'LÂ·', 'Å€' => 'lÂ·', 'Å‰' => 'Ê¼n', 'Å¿' => 's', 'Ç„' => 'DZÌŒ', 'Ç…' => 'DzÌŒ', 'Ç†' => 'dzÌŒ', 'Ç‡' => 'LJ', 'Çˆ' => 'Lj', 'Ç‰' => 'lj', 'ÇŠ' => 'NJ', 'Ç‹' => 'Nj', 'ÇŒ' => 'nj', 'Ç±' => 'DZ', 'Ç²' => 'Dz', 'Ç³' => 'dz', 'Ê°' => 'h', 'Ê±' => 'É¦', 'Ê²' => 'j', 'Ê³' => 'r', 'Ê´' => 'É¹', 'Êµ' => 'É»', 'Ê¶' => 'Ê�', 'Ê·' => 'w', 'Ê¸' => 'y', 'Ë˜' => ' Ì†', 'Ë™' => ' Ì‡', 'Ëš' => ' ÌŠ', 'Ë›' => ' Ì¨', 'Ëœ' => ' Ìƒ', 'Ë�' => ' Ì‹', 'Ë ' => 'É£', 'Ë¡' => 'l', 'Ë¢' => 's', 'Ë£' => 'x', 'Ë¤' => 'Ê•', 'Íº' => ' Í…', 'Î„' => ' Ì�', 'Î…' => ' ÌˆÌ�', 'Ï�' => 'Î²', 'Ï‘' => 'Î¸', 'Ï’' => 'Î¥', 'Ï“' => 'Î¥Ì�', 'Ï”' => 'Î¥Ìˆ', 'Ï•' => 'Ï†', 'Ï–' => 'Ï€', 'Ï°' => 'Îº', 'Ï±' => 'Ï�', 'Ï²' => 'Ï‚', 'Ï´' => 'Î˜', 'Ïµ' => 'Îµ', 'Ï¹' => 'Î£', 'Ö‡' => 'Õ¥Ö‚', 'Ùµ' => 'Ø§Ù´', 'Ù¶' => 'ÙˆÙ´', 'Ù·' => 'Û‡Ù´', 'Ù¸' => 'ÙŠÙ´', 'à¸³' => 'à¹�à¸²', 'àº³' => 'à»�àº²', 'à»œ' => 'àº«àº™', 'à»�' => 'àº«àº¡', 'à¼Œ' => 'à¼‹', 'à½·' => 'à¾²à½±à¾€', 'à½¹' => 'à¾³à½±à¾€', 'áƒ¼' => 'áƒœ', 'á´¬' => 'A', 'á´­' => 'Ã†', 'á´®' => 'B', 'á´°' => 'D', 'á´±' => 'E', 'á´²' => 'ÆŽ', 'á´³' => 'G', 'á´´' => 'H', 'á´µ' => 'I', 'á´¶' => 'J', 'á´·' => 'K', 'á´¸' => 'L', 'á´¹' => 'M', 'á´º' => 'N', 'á´¼' => 'O', 'á´½' => 'È¢', 'á´¾' => 'P', 'á´¿' => 'R', 'áµ€' => 'T', 'áµ�' => 'U', 'áµ‚' => 'W', 'áµƒ' => 'a', 'áµ„' => 'É�', 'áµ…' => 'É‘', 'áµ†' => 'á´‚', 'áµ‡' => 'b', 'áµˆ' => 'd', 'áµ‰' => 'e', 'áµŠ' => 'É™', 'áµ‹' => 'É›', 'áµŒ' => 'Éœ', 'áµ�' => 'g', 'áµ�' => 'k', 'áµ�' => 'm', 'áµ‘' => 'Å‹', 'áµ’' => 'o', 'áµ“' => 'É”', 'áµ”' => 'á´–', 'áµ•' => 'á´—', 'áµ–' => 'p', 'áµ—' => 't', 'áµ˜' => 'u', 'áµ™' => 'á´�', 'áµš' => 'É¯', 'áµ›' => 'v', 'áµœ' => 'á´¥', 'áµ�' => 'Î²', 'áµž' => 'Î³', 'áµŸ' => 'Î´', 'áµ ' => 'Ï†', 'áµ¡' => 'Ï‡', 'áµ¢' => 'i', 'áµ£' => 'r', 'áµ¤' => 'u', 'áµ¥' => 'v', 'áµ¦' => 'Î²', 'áµ§' => 'Î³', 'áµ¨' => 'Ï�', 'áµ©' => 'Ï†', 'áµª' => 'Ï‡', 'áµ¸' => 'Ð½', 'á¶›' => 'É’', 'á¶œ' => 'c', 'á¶�' => 'É•', 'á¶ž' => 'Ã°', 'á¶Ÿ' => 'Éœ', 'á¶ ' => 'f', 'á¶¡' => 'ÉŸ', 'á¶¢' => 'É¡', 'á¶£' => 'É¥', 'á¶¤' => 'É¨', 'á¶¥' => 'É©', 'á¶¦' => 'Éª', 'á¶§' => 'áµ»', 'á¶¨' => 'Ê�', 'á¶©' => 'É­', 'á¶ª' => 'á¶…', 'á¶«' => 'ÊŸ', 'á¶¬' => 'É±', 'á¶­' => 'É°', 'á¶®' => 'É²', 'á¶¯' => 'É³', 'á¶°' => 'É´', 'á¶±' => 'Éµ', 'á¶²' => 'É¸', 'á¶³' => 'Ê‚', 'á¶´' => 'Êƒ', 'á¶µ' => 'Æ«', 'á¶¶' => 'Ê‰', 'á¶·' => 'ÊŠ', 'á¶¸' => 'á´œ', 'á¶¹' => 'Ê‹', 'á¶º' => 'ÊŒ', 'á¶»' => 'z', 'á¶¼' => 'Ê�', 'á¶½' => 'Ê‘', 'á¶¾' => 'Ê’', 'á¶¿' => 'Î¸', 'áºš' => 'aÊ¾', 'áº›' => 'sÌ‡', 'á¾½' => ' Ì“', 'á¾¿' => ' Ì“', 'á¿€' => ' Í‚', 'á¿�' => ' ÌˆÍ‚', 'á¿�' => ' Ì“Ì€', 'á¿Ž' => ' Ì“Ì�', 'á¿�' => ' Ì“Í‚', 'á¿�' => ' Ì”Ì€', 'á¿ž' => ' Ì”Ì�', 'á¿Ÿ' => ' Ì”Í‚', 'á¿­' => ' ÌˆÌ€', 'á¿®' => ' ÌˆÌ�', 'á¿½' => ' Ì�', 'á¿¾' => ' Ì”', 'â€€' => ' ', 'â€�' => ' ', 'â€‚' => ' ', 'â€ƒ' => ' ', 'â€„' => ' ', 'â€…' => ' ', 'â€†' => ' ', 'â€‡' => ' ', 'â€ˆ' => ' ', 'â€‰' => ' ', 'â€Š' => ' ', 'â€‘' => 'â€�', 'â€—' => ' Ì³', 'â€¤' => '.', 'â€¥' => '..', 'â€¦' => '...', 'â€¯' => ' ', 'â€³' => 'â€²â€²', 'â€´' => 'â€²â€²â€²', 'â€¶' => 'â€µâ€µ', 'â€·' => 'â€µâ€µâ€µ', 'â€¼' => '!!', 'â€¾' => ' Ì…', 'â�‡' => '??', 'â�ˆ' => '?!', 'â�‰' => '!?', 'â�—' => 'â€²â€²â€²â€²', 'â�Ÿ' => ' ', 'â�°' => '0', 'â�±' => 'i', 'â�´' => '4', 'â�µ' => '5', 'â�¶' => '6', 'â�·' => '7', 'â�¸' => '8', 'â�¹' => '9', 'â�º' => '+', 'â�»' => 'âˆ’', 'â�¼' => '=', 'â�½' => '(', 'â�¾' => ')', 'â�¿' => 'n', 'â‚€' => '0', 'â‚�' => '1', 'â‚‚' => '2', 'â‚ƒ' => '3', 'â‚„' => '4', 'â‚…' => '5', 'â‚†' => '6', 'â‚‡' => '7', 'â‚ˆ' => '8', 'â‚‰' => '9', 'â‚Š' => '+', 'â‚‹' => 'âˆ’', 'â‚Œ' => '=', 'â‚�' => '(', 'â‚Ž' => ')', 'â‚�' => 'a', 'â‚‘' => 'e', 'â‚’' => 'o', 'â‚“' => 'x', 'â‚”' => 'É™', 'â‚•' => 'h', 'â‚–' => 'k', 'â‚—' => 'l', 'â‚˜' => 'm', 'â‚™' => 'n', 'â‚š' => 'p', 'â‚›' => 's', 'â‚œ' => 't', 'â‚¨' => 'Rs', 'â„€' => 'a/c', 'â„�' => 'a/s', 'â„‚' => 'C', 'â„ƒ' => 'Â°C', 'â„…' => 'c/o', 'â„†' => 'c/u', 'â„‡' => 'Æ�', 'â„‰' => 'Â°F', 'â„Š' => 'g', 'â„‹' => 'H', 'â„Œ' => 'H', 'â„�' => 'H', 'â„Ž' => 'h', 'â„�' => 'Ä§', 'â„�' => 'I', 'â„‘' => 'I', 'â„’' => 'L', 'â„“' => 'l', 'â„•' => 'N', 'â„–' => 'No', 'â„™' => 'P', 'â„š' => 'Q', 'â„›' => 'R', 'â„œ' => 'R', 'â„�' => 'R', 'â„ ' => 'SM', 'â„¡' => 'TEL', 'â„¢' => 'TM', 'â„¤' => 'Z', 'â„¨' => 'Z', 'â„¬' => 'B', 'â„­' => 'C', 'â„¯' => 'e', 'â„°' => 'E', 'â„±' => 'F', 'â„³' => 'M', 'â„´' => 'o', 'â„µ' => '×�', 'â„¶' => '×‘', 'â„·' => '×’', 'â„¸' => '×“', 'â„¹' => 'i', 'â„»' => 'FAX', 'â„¼' => 'Ï€', 'â„½' => 'Î³', 'â„¾' => 'Î“', 'â„¿' => 'Î ', 'â…€' => 'âˆ‘', 'â……' => 'D', 'â…†' => 'd', 'â…‡' => 'e', 'â…ˆ' => 'i', 'â…‰' => 'j', 'â…�' => '1â�„7', 'â…‘' => '1â�„9', 'â…’' => '1â�„10', 'â…“' => '1â�„3', 'â…”' => '2â�„3', 'â…•' => '1â�„5', 'â…–' => '2â�„5', 'â…—' => '3â�„5', 'â…˜' => '4â�„5', 'â…™' => '1â�„6', 'â…š' => '5â�„6', 'â…›' => '1â�„8', 'â…œ' => '3â�„8', 'â…�' => '5â�„8', 'â…ž' => '7â�„8', 'â…Ÿ' => '1â�„', 'â… ' => 'I', 'â…¡' => 'II', 'â…¢' => 'III', 'â…£' => 'IV', 'â…¤' => 'V', 'â…¥' => 'VI', 'â…¦' => 'VII', 'â…§' => 'VIII', 'â…¨' => 'IX', 'â…©' => 'X', 'â…ª' => 'XI', 'â…«' => 'XII', 'â…¬' => 'L', 'â…­' => 'C', 'â…®' => 'D', 'â…¯' => 'M', 'â…°' => 'i', 'â…±' => 'ii', 'â…²' => 'iii', 'â…³' => 'iv', 'â…´' => 'v', 'â…µ' => 'vi', 'â…¶' => 'vii', 'â…·' => 'viii', 'â…¸' => 'ix', 'â…¹' => 'x', 'â…º' => 'xi', 'â…»' => 'xii', 'â…¼' => 'l', 'â…½' => 'c', 'â…¾' => 'd', 'â…¿' => 'm', 'â†‰' => '0â�„3', 'âˆ¬' => 'âˆ«âˆ«', 'âˆ­' => 'âˆ«âˆ«âˆ«', 'âˆ¯' => 'âˆ®âˆ®', 'âˆ°' => 'âˆ®âˆ®âˆ®', 'â‘ ' => '1', 'â‘¡' => '2', 'â‘¢' => '3', 'â‘£' => '4', 'â‘¤' => '5', 'â‘¥' => '6', 'â‘¦' => '7', 'â‘§' => '8', 'â‘¨' => '9', 'â‘©' => '10', 'â‘ª' => '11', 'â‘«' => '12', 'â‘¬' => '13', 'â‘­' => '14', 'â‘®' => '15', 'â‘¯' => '16', 'â‘°' => '17', 'â‘±' => '18', 'â‘²' => '19', 'â‘³' => '20', 'â‘´' => '(1)', 'â‘µ' => '(2)', 'â‘¶' => '(3)', 'â‘·' => '(4)', 'â‘¸' => '(5)', 'â‘¹' => '(6)', 'â‘º' => '(7)', 'â‘»' => '(8)', 'â‘¼' => '(9)', 'â‘½' => '(10)', 'â‘¾' => '(11)', 'â‘¿' => '(12)', 'â’€' => '(13)', 'â’�' => '(14)', 'â’‚' => '(15)', 'â’ƒ' => '(16)', 'â’„' => '(17)', 'â’…' => '(18)', 'â’†' => '(19)', 'â’‡' => '(20)', 'â’ˆ' => '1.', 'â’‰' => '2.', 'â’Š' => '3.', 'â’‹' => '4.', 'â’Œ' => '5.', 'â’�' => '6.', 'â’Ž' => '7.', 'â’�' => '8.', 'â’�' => '9.', 'â’‘' => '10.', 'â’’' => '11.', 'â’“' => '12.', 'â’”' => '13.', 'â’•' => '14.', 'â’–' => '15.', 'â’—' => '16.', 'â’˜' => '17.', 'â’™' => '18.', 'â’š' => '19.', 'â’›' => '20.', 'â’œ' => '(a)', 'â’�' => '(b)', 'â’ž' => '(c)', 'â’Ÿ' => '(d)', 'â’ ' => '(e)', 'â’¡' => '(f)', 'â’¢' => '(g)', 'â’£' => '(h)', 'â’¤' => '(i)', 'â’¥' => '(j)', 'â’¦' => '(k)', 'â’§' => '(l)', 'â’¨' => '(m)', 'â’©' => '(n)', 'â’ª' => '(o)', 'â’«' => '(p)', 'â’¬' => '(q)', 'â’­' => '(r)', 'â’®' => '(s)', 'â’¯' => '(t)', 'â’°' => '(u)', 'â’±' => '(v)', 'â’²' => '(w)', 'â’³' => '(x)', 'â’´' => '(y)', 'â’µ' => '(z)', 'â’¶' => 'A', 'â’·' => 'B', 'â’¸' => 'C', 'â’¹' => 'D', 'â’º' => 'E', 'â’»' => 'F', 'â’¼' => 'G', 'â’½' => 'H', 'â’¾' => 'I', 'â’¿' => 'J', 'â“€' => 'K', 'â“�' => 'L', 'â“‚' => 'M', 'â“ƒ' => 'N', 'â“„' => 'O', 'â“…' => 'P', 'â“†' => 'Q', 'â“‡' => 'R', 'â“ˆ' => 'S', 'â“‰' => 'T', 'â“Š' => 'U', 'â“‹' => 'V', 'â“Œ' => 'W', 'â“�' => 'X', 'â“Ž' => 'Y', 'â“�' => 'Z', 'â“�' => 'a', 'â“‘' => 'b', 'â“’' => 'c', 'â““' => 'd', 'â“”' => 'e', 'â“•' => 'f', 'â“–' => 'g', 'â“—' => 'h', 'â“˜' => 'i', 'â“™' => 'j', 'â“š' => 'k', 'â“›' => 'l', 'â“œ' => 'm', 'â“�' => 'n', 'â“ž' => 'o', 'â“Ÿ' => 'p', 'â“ ' => 'q', 'â“¡' => 'r', 'â“¢' => 's', 'â“£' => 't', 'â“¤' => 'u', 'â“¥' => 'v', 'â“¦' => 'w', 'â“§' => 'x', 'â“¨' => 'y', 'â“©' => 'z', 'â“ª' => '0', 'â¨Œ' => 'âˆ«âˆ«âˆ«âˆ«', 'â©´' => '::=', 'â©µ' => '==', 'â©¶' => '===', 'â±¼' => 'j', 'â±½' => 'V', 'âµ¯' => 'âµ¡', 'âºŸ' => 'æ¯�', 'â»³' => 'é¾Ÿ', 'â¼€' => 'ä¸€', 'â¼�' => 'ä¸¨', 'â¼‚' => 'ä¸¶', 'â¼ƒ' => 'ä¸¿', 'â¼„' => 'ä¹™', 'â¼…' => 'äº…', 'â¼†' => 'äºŒ', 'â¼‡' => 'äº ', 'â¼ˆ' => 'äºº', 'â¼‰' => 'å„¿', 'â¼Š' => 'å…¥', 'â¼‹' => 'å…«', 'â¼Œ' => 'å†‚', 'â¼�' => 'å†–', 'â¼Ž' => 'å†«', 'â¼�' => 'å‡ ', 'â¼�' => 'å‡µ', 'â¼‘' => 'åˆ€', 'â¼’' => 'åŠ›', 'â¼“' => 'å‹¹', 'â¼”' => 'åŒ•', 'â¼•' => 'åŒš', 'â¼–' => 'åŒ¸', 'â¼—' => 'å��', 'â¼˜' => 'å�œ', 'â¼™' => 'å�©', 'â¼š' => 'åŽ‚', 'â¼›' => 'åŽ¶', 'â¼œ' => 'å�ˆ', 'â¼�' => 'å�£', 'â¼ž' => 'å›—', 'â¼Ÿ' => 'åœŸ', 'â¼ ' => 'å£«', 'â¼¡' => 'å¤‚', 'â¼¢' => 'å¤Š', 'â¼£' => 'å¤•', 'â¼¤' => 'å¤§', 'â¼¥' => 'å¥³', 'â¼¦' => 'å­�', 'â¼§' => 'å®€', 'â¼¨' => 'å¯¸', 'â¼©' => 'å°�', 'â¼ª' => 'å°¢', 'â¼«' => 'å°¸', 'â¼¬' => 'å±®', 'â¼­' => 'å±±', 'â¼®' => 'å·›', 'â¼¯' => 'å·¥', 'â¼°' => 'å·±', 'â¼±' => 'å·¾', 'â¼²' => 'å¹²', 'â¼³' => 'å¹º', 'â¼´' => 'å¹¿', 'â¼µ' => 'å»´', 'â¼¶' => 'å»¾', 'â¼·' => 'å¼‹', 'â¼¸' => 'å¼“', 'â¼¹' => 'å½�', 'â¼º' => 'å½¡', 'â¼»' => 'å½³', 'â¼¼' => 'å¿ƒ', 'â¼½' => 'æˆˆ', 'â¼¾' => 'æˆ¶', 'â¼¿' => 'æ‰‹', 'â½€' => 'æ”¯', 'â½�' => 'æ”´', 'â½‚' => 'æ–‡', 'â½ƒ' => 'æ–—', 'â½„' => 'æ–¤', 'â½…' => 'æ–¹', 'â½†' => 'æ— ', 'â½‡' => 'æ—¥', 'â½ˆ' => 'æ›°', 'â½‰' => 'æœˆ', 'â½Š' => 'æœ¨', 'â½‹' => 'æ¬ ', 'â½Œ' => 'æ­¢', 'â½�' => 'æ­¹', 'â½Ž' => 'æ®³', 'â½�' => 'æ¯‹', 'â½�' => 'æ¯”', 'â½‘' => 'æ¯›', 'â½’' => 'æ°�', 'â½“' => 'æ°”', 'â½”' => 'æ°´', 'â½•' => 'ç�«', 'â½–' => 'çˆª', 'â½—' => 'çˆ¶', 'â½˜' => 'çˆ»', 'â½™' => 'çˆ¿', 'â½š' => 'ç‰‡', 'â½›' => 'ç‰™', 'â½œ' => 'ç‰›', 'â½�' => 'çŠ¬', 'â½ž' => 'çŽ„', 'â½Ÿ' => 'çŽ‰', 'â½ ' => 'ç“œ', 'â½¡' => 'ç“¦', 'â½¢' => 'ç”˜', 'â½£' => 'ç”Ÿ', 'â½¤' => 'ç”¨', 'â½¥' => 'ç”°', 'â½¦' => 'ç–‹', 'â½§' => 'ç–’', 'â½¨' => 'ç™¶', 'â½©' => 'ç™½', 'â½ª' => 'çš®', 'â½«' => 'çš¿', 'â½¬' => 'ç›®', 'â½­' => 'çŸ›', 'â½®' => 'çŸ¢', 'â½¯' => 'çŸ³', 'â½°' => 'ç¤º', 'â½±' => 'ç¦¸', 'â½²' => 'ç¦¾', 'â½³' => 'ç©´', 'â½´' => 'ç«‹', 'â½µ' => 'ç«¹', 'â½¶' => 'ç±³', 'â½·' => 'ç³¸', 'â½¸' => 'ç¼¶', 'â½¹' => 'ç½‘', 'â½º' => 'ç¾Š', 'â½»' => 'ç¾½', 'â½¼' => 'è€�', 'â½½' => 'è€Œ', 'â½¾' => 'è€’', 'â½¿' => 'è€³', 'â¾€' => 'è�¿', 'â¾�' => 'è‚‰', 'â¾‚' => 'è‡£', 'â¾ƒ' => 'è‡ª', 'â¾„' => 'è‡³', 'â¾…' => 'è‡¼', 'â¾†' => 'èˆŒ', 'â¾‡' => 'èˆ›', 'â¾ˆ' => 'èˆŸ', 'â¾‰' => 'è‰®', 'â¾Š' => 'è‰²', 'â¾‹' => 'è‰¸', 'â¾Œ' => 'è™�', 'â¾�' => 'è™«', 'â¾Ž' => 'è¡€', 'â¾�' => 'è¡Œ', 'â¾�' => 'è¡£', 'â¾‘' => 'è¥¾', 'â¾’' => 'è¦‹', 'â¾“' => 'è§’', 'â¾”' => 'è¨€', 'â¾•' => 'è°·', 'â¾–' => 'è±†', 'â¾—' => 'è±•', 'â¾˜' => 'è±¸', 'â¾™' => 'è²�', 'â¾š' => 'èµ¤', 'â¾›' => 'èµ°', 'â¾œ' => 'è¶³', 'â¾�' => 'èº«', 'â¾ž' => 'è»Š', 'â¾Ÿ' => 'è¾›', 'â¾ ' => 'è¾°', 'â¾¡' => 'è¾µ', 'â¾¢' => 'é‚‘', 'â¾£' => 'é…‰', 'â¾¤' => 'é‡†', 'â¾¥' => 'é‡Œ', 'â¾¦' => 'é‡‘', 'â¾§' => 'é•·', 'â¾¨' => 'é–€', 'â¾©' => 'é˜œ', 'â¾ª' => 'éš¶', 'â¾«' => 'éš¹', 'â¾¬' => 'é›¨', 'â¾­' => 'é�‘', 'â¾®' => 'é�ž', 'â¾¯' => 'é�¢', 'â¾°' => 'é�©', 'â¾±' => 'éŸ‹', 'â¾²' => 'éŸ­', 'â¾³' => 'éŸ³', 'â¾´' => 'é �', 'â¾µ' => 'é¢¨', 'â¾¶' => 'é£›', 'â¾·' => 'é£Ÿ', 'â¾¸' => 'é¦–', 'â¾¹' => 'é¦™', 'â¾º' => 'é¦¬', 'â¾»' => 'éª¨', 'â¾¼' => 'é«˜', 'â¾½' => 'é«Ÿ', 'â¾¾' => 'é¬¥', 'â¾¿' => 'é¬¯', 'â¿€' => 'é¬²', 'â¿�' => 'é¬¼', 'â¿‚' => 'é­š', 'â¿ƒ' => 'é³¥', 'â¿„' => 'é¹µ', 'â¿…' => 'é¹¿', 'â¿†' => 'éº¥', 'â¿‡' => 'éº»', 'â¿ˆ' => 'é»ƒ', 'â¿‰' => 'é»�', 'â¿Š' => 'é»‘', 'â¿‹' => 'é»¹', 'â¿Œ' => 'é»½', 'â¿�' => 'é¼Ž', 'â¿Ž' => 'é¼“', 'â¿�' => 'é¼ ', 'â¿�' => 'é¼»', 'â¿‘' => 'é½Š', 'â¿’' => 'é½’', 'â¿“' => 'é¾�', 'â¿”' => 'é¾œ', 'â¿•' => 'é¾ ', 'ã€€' => ' ', 'ã€¶' => 'ã€’', 'ã€¸' => 'å��', 'ã€¹' => 'å�„', 'ã€º' => 'å�…', 'ã‚›' => ' ã‚™', 'ã‚œ' => ' ã‚š', 'ã‚Ÿ' => 'ã‚ˆã‚Š', 'ãƒ¿' => 'ã‚³ãƒˆ', 'ã„±' => 'á„€', 'ã„²' => 'á„�', 'ã„³' => 'á†ª', 'ã„´' => 'á„‚', 'ã„µ' => 'á†¬', 'ã„¶' => 'á†­', 'ã„·' => 'á„ƒ', 'ã„¸' => 'á„„', 'ã„¹' => 'á„…', 'ã„º' => 'á†°', 'ã„»' => 'á†±', 'ã„¼' => 'á†²', 'ã„½' => 'á†³', 'ã„¾' => 'á†´', 'ã„¿' => 'á†µ', 'ã…€' => 'á„š', 'ã…�' => 'á„†', 'ã…‚' => 'á„‡', 'ã…ƒ' => 'á„ˆ', 'ã…„' => 'á„¡', 'ã……' => 'á„‰', 'ã…†' => 'á„Š', 'ã…‡' => 'á„‹', 'ã…ˆ' => 'á„Œ', 'ã…‰' => 'á„�', 'ã…Š' => 'á„Ž', 'ã…‹' => 'á„�', 'ã…Œ' => 'á„�', 'ã…�' => 'á„‘', 'ã…Ž' => 'á„’', 'ã…�' => 'á…¡', 'ã…�' => 'á…¢', 'ã…‘' => 'á…£', 'ã…’' => 'á…¤', 'ã…“' => 'á…¥', 'ã…”' => 'á…¦', 'ã…•' => 'á…§', 'ã…–' => 'á…¨', 'ã…—' => 'á…©', 'ã…˜' => 'á…ª', 'ã…™' => 'á…«', 'ã…š' => 'á…¬', 'ã…›' => 'á…­', 'ã…œ' => 'á…®', 'ã…�' => 'á…¯', 'ã…ž' => 'á…°', 'ã…Ÿ' => 'á…±', 'ã… ' => 'á…²', 'ã…¡' => 'á…³', 'ã…¢' => 'á…´', 'ã…£' => 'á…µ', 'ã…¤' => 'á… ', 'ã…¥' => 'á„”', 'ã…¦' => 'á„•', 'ã…§' => 'á‡‡', 'ã…¨' => 'á‡ˆ', 'ã…©' => 'á‡Œ', 'ã…ª' => 'á‡Ž', 'ã…«' => 'á‡“', 'ã…¬' => 'á‡—', 'ã…­' => 'á‡™', 'ã…®' => 'á„œ', 'ã…¯' => 'á‡�', 'ã…°' => 'á‡Ÿ', 'ã…±' => 'á„�', 'ã…²' => 'á„ž', 'ã…³' => 'á„ ', 'ã…´' => 'á„¢', 'ã…µ' => 'á„£', 'ã…¶' => 'á„§', 'ã…·' => 'á„©', 'ã…¸' => 'á„«', 'ã…¹' => 'á„¬', 'ã…º' => 'á„­', 'ã…»' => 'á„®', 'ã…¼' => 'á„¯', 'ã…½' => 'á„²', 'ã…¾' => 'á„¶', 'ã…¿' => 'á…€', 'ã†€' => 'á…‡', 'ã†�' => 'á…Œ', 'ã†‚' => 'á‡±', 'ã†ƒ' => 'á‡²', 'ã†„' => 'á…—', 'ã†…' => 'á…˜', 'ã††' => 'á…™', 'ã†‡' => 'á†„', 'ã†ˆ' => 'á†…', 'ã†‰' => 'á†ˆ', 'ã†Š' => 'á†‘', 'ã†‹' => 'á†’', 'ã†Œ' => 'á†”', 'ã†�' => 'á†ž', 'ã†Ž' => 'á†¡', 'ã†’' => 'ä¸€', 'ã†“' => 'äºŒ', 'ã†”' => 'ä¸‰', 'ã†•' => 'å››', 'ã†–' => 'ä¸Š', 'ã†—' => 'ä¸­', 'ã†˜' => 'ä¸‹', 'ã†™' => 'ç”²', 'ã†š' => 'ä¹™', 'ã†›' => 'ä¸™', 'ã†œ' => 'ä¸�', 'ã†�' => 'å¤©', 'ã†ž' => 'åœ°', 'ã†Ÿ' => 'äºº', 'ãˆ€' => '(á„€)', 'ãˆ�' => '(á„‚)', 'ãˆ‚' => '(á„ƒ)', 'ãˆƒ' => '(á„…)', 'ãˆ„' => '(á„†)', 'ãˆ…' => '(á„‡)', 'ãˆ†' => '(á„‰)', 'ãˆ‡' => '(á„‹)', 'ãˆˆ' => '(á„Œ)', 'ãˆ‰' => '(á„Ž)', 'ãˆŠ' => '(á„�)', 'ãˆ‹' => '(á„�)', 'ãˆŒ' => '(á„‘)', 'ãˆ�' => '(á„’)', 'ãˆŽ' => '(á„€á…¡)', 'ãˆ�' => '(á„‚á…¡)', 'ãˆ�' => '(á„ƒá…¡)', 'ãˆ‘' => '(á„…á…¡)', 'ãˆ’' => '(á„†á…¡)', 'ãˆ“' => '(á„‡á…¡)', 'ãˆ”' => '(á„‰á…¡)', 'ãˆ•' => '(á„‹á…¡)', 'ãˆ–' => '(á„Œá…¡)', 'ãˆ—' => '(á„Žá…¡)', 'ãˆ˜' => '(á„�á…¡)', 'ãˆ™' => '(á„�á…¡)', 'ãˆš' => '(á„‘á…¡)', 'ãˆ›' => '(á„’á…¡)', 'ãˆœ' => '(á„Œá…®)', 'ãˆ�' => '(á„‹á…©á„Œá…¥á†«)', 'ãˆž' => '(á„‹á…©á„’á…®)', 'ãˆ ' => '(ä¸€)', 'ãˆ¡' => '(äºŒ)', 'ãˆ¢' => '(ä¸‰)', 'ãˆ£' => '(å››)', 'ãˆ¤' => '(äº”)', 'ãˆ¥' => '(å…­)', 'ãˆ¦' => '(ä¸ƒ)', 'ãˆ§' => '(å…«)', 'ãˆ¨' => '(ä¹�)', 'ãˆ©' => '(å��)', 'ãˆª' => '(æœˆ)', 'ãˆ«' => '(ç�«)', 'ãˆ¬' => '(æ°´)', 'ãˆ­' => '(æœ¨)', 'ãˆ®' => '(é‡‘)', 'ãˆ¯' => '(åœŸ)', 'ãˆ°' => '(æ—¥)', 'ãˆ±' => '(æ ª)', 'ãˆ²' => '(æœ‰)', 'ãˆ³' => '(ç¤¾)', 'ãˆ´' => '(å��)', 'ãˆµ' => '(ç‰¹)', 'ãˆ¶' => '(è²¡)', 'ãˆ·' => '(ç¥�)', 'ãˆ¸' => '(åŠ´)', 'ãˆ¹' => '(ä»£)', 'ãˆº' => '(å‘¼)', 'ãˆ»' => '(å­¦)', 'ãˆ¼' => '(ç›£)', 'ãˆ½' => '(ä¼�)', 'ãˆ¾' => '(è³‡)', 'ãˆ¿' => '(å�”)', 'ã‰€' => '(ç¥­)', 'ã‰�' => '(ä¼‘)', 'ã‰‚' => '(è‡ª)', 'ã‰ƒ' => '(è‡³)', 'ã‰„' => 'å•�', 'ã‰…' => 'å¹¼', 'ã‰†' => 'æ–‡', 'ã‰‡' => 'ç®�', 'ã‰�' => 'PTE', 'ã‰‘' => '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', 'ã‹€' => '1æœˆ', 'ã‹�' => '2æœˆ', 'ã‹‚' => '3æœˆ', 'ã‹ƒ' => '4æœˆ', 'ã‹„' => '5æœˆ', 'ã‹…' => '6æœˆ', 'ã‹†' => '7æœˆ', 'ã‹‡' => '8æœˆ', 'ã‹ˆ' => '9æœˆ', 'ã‹‰' => '10æœˆ', 'ã‹Š' => '11æœˆ', 'ã‹‹' => '12æœˆ', 'ã‹Œ' => 'Hg', 'ã‹�' => 'erg', 'ã‹Ž' => 'eV', 'ã‹�' => 'LTD', 'ã‹�' => 'ã‚¢', 'ã‹‘' => 'ã‚¤', 'ã‹’' => 'ã‚¦', 'ã‹“' => 'ã‚¨', 'ã‹”' => 'ã‚ª', 'ã‹•' => 'ã‚«', 'ã‹–' => 'ã‚­', 'ã‹—' => 'ã‚¯', 'ã‹˜' => 'ã‚±', 'ã‹™' => 'ã‚³', 'ã‹š' => 'ã‚µ', 'ã‹›' => 'ã‚·', 'ã‹œ' => 'ã‚¹', 'ã‹�' => 'ã‚»', 'ã‹ž' => 'ã‚½', 'ã‹Ÿ' => 'ã‚¿', 'ã‹ ' => 'ãƒ�', 'ã‹¡' => 'ãƒ„', 'ã‹¢' => 'ãƒ†', 'ã‹£' => 'ãƒˆ', 'ã‹¤' => 'ãƒŠ', 'ã‹¥' => 'ãƒ‹', 'ã‹¦' => 'ãƒŒ', 'ã‹§' => 'ãƒ�', 'ã‹¨' => 'ãƒŽ', 'ã‹©' => 'ãƒ�', 'ã‹ª' => 'ãƒ’', 'ã‹«' => 'ãƒ•', 'ã‹¬' => 'ãƒ˜', 'ã‹­' => 'ãƒ›', 'ã‹®' => 'ãƒž', 'ã‹¯' => 'ãƒŸ', 'ã‹°' => 'ãƒ ', 'ã‹±' => 'ãƒ¡', 'ã‹²' => 'ãƒ¢', 'ã‹³' => 'ãƒ¤', 'ã‹´' => 'ãƒ¦', 'ã‹µ' => 'ãƒ¨', 'ã‹¶' => 'ãƒ©', 'ã‹·' => 'ãƒª', 'ã‹¸' => 'ãƒ«', 'ã‹¹' => 'ãƒ¬', 'ã‹º' => 'ãƒ­', 'ã‹»' => 'ãƒ¯', 'ã‹¼' => 'ãƒ°', 'ã‹½' => 'ãƒ±', 'ã‹¾' => 'ãƒ²', 'ã‹¿' => 'ä»¤å’Œ', 'ãŒ€' => 'ã‚¢ãƒ�ã‚šãƒ¼ãƒˆ', 'ãŒ�' => 'ã‚¢ãƒ«ãƒ•ã‚¡', 'ãŒ‚' => 'ã‚¢ãƒ³ãƒ˜ã‚šã‚¢', 'ãŒƒ' => 'ã‚¢ãƒ¼ãƒ«', 'ãŒ„' => 'ã‚¤ãƒ‹ãƒ³ã‚¯ã‚™', 'ãŒ…' => 'ã‚¤ãƒ³ãƒ�', 'ãŒ†' => 'ã‚¦ã‚©ãƒ³', 'ãŒ‡' => 'ã‚¨ã‚¹ã‚¯ãƒ¼ãƒˆã‚™', 'ãŒˆ' => 'ã‚¨ãƒ¼ã‚«ãƒ¼', 'ãŒ‰' => 'ã‚ªãƒ³ã‚¹', 'ãŒŠ' => 'ã‚ªãƒ¼ãƒ ', 'ãŒ‹' => 'ã‚«ã‚¤ãƒª', 'ãŒŒ' => 'ã‚«ãƒ©ãƒƒãƒˆ', 'ãŒ�' => 'ã‚«ãƒ­ãƒªãƒ¼', 'ãŒŽ' => 'ã‚«ã‚™ãƒ­ãƒ³', 'ãŒ�' => 'ã‚«ã‚™ãƒ³ãƒž', 'ãŒ�' => 'ã‚­ã‚™ã‚«ã‚™', 'ãŒ‘' => 'ã‚­ã‚™ãƒ‹ãƒ¼', 'ãŒ’' => 'ã‚­ãƒ¥ãƒªãƒ¼', 'ãŒ“' => 'ã‚­ã‚™ãƒ«ã‚¿ã‚™ãƒ¼', 'ãŒ”' => 'ã‚­ãƒ­', 'ãŒ•' => 'ã‚­ãƒ­ã‚¯ã‚™ãƒ©ãƒ ', 'ãŒ–' => 'ã‚­ãƒ­ãƒ¡ãƒ¼ãƒˆãƒ«', 'ãŒ—' => 'ã‚­ãƒ­ãƒ¯ãƒƒãƒˆ', 'ãŒ˜' => 'ã‚¯ã‚™ãƒ©ãƒ ', 'ãŒ™' => 'ã‚¯ã‚™ãƒ©ãƒ ãƒˆãƒ³', 'ãŒš' => 'ã‚¯ãƒ«ã‚»ã‚™ã‚¤ãƒ­', 'ãŒ›' => 'ã‚¯ãƒ­ãƒ¼ãƒ�', 'ãŒœ' => 'ã‚±ãƒ¼ã‚¹', 'ãŒ�' => 'ã‚³ãƒ«ãƒŠ', 'ãŒž' => 'ã‚³ãƒ¼ãƒ›ã‚š', 'ãŒŸ' => 'ã‚µã‚¤ã‚¯ãƒ«', 'ãŒ ' => 'ã‚µãƒ³ãƒ�ãƒ¼ãƒ ', 'ãŒ¡' => 'ã‚·ãƒªãƒ³ã‚¯ã‚™', 'ãŒ¢' => 'ã‚»ãƒ³ãƒ�', 'ãŒ£' => 'ã‚»ãƒ³ãƒˆ', 'ãŒ¤' => 'ã‚¿ã‚™ãƒ¼ã‚¹', 'ãŒ¥' => 'ãƒ†ã‚™ã‚·', 'ãŒ¦' => 'ãƒˆã‚™ãƒ«', 'ãŒ§' => 'ãƒˆãƒ³', 'ãŒ¨' => 'ãƒŠãƒŽ', 'ãŒ©' => 'ãƒŽãƒƒãƒˆ', 'ãŒª' => 'ãƒ�ã‚¤ãƒ„', 'ãŒ«' => 'ãƒ�ã‚šãƒ¼ã‚»ãƒ³ãƒˆ', 'ãŒ¬' => 'ãƒ�ã‚šãƒ¼ãƒ„', 'ãŒ­' => 'ãƒ�ã‚™ãƒ¼ãƒ¬ãƒ«', 'ãŒ®' => 'ãƒ’ã‚šã‚¢ã‚¹ãƒˆãƒ«', 'ãŒ¯' => 'ãƒ’ã‚šã‚¯ãƒ«', 'ãŒ°' => 'ãƒ’ã‚šã‚³', 'ãŒ±' => 'ãƒ’ã‚™ãƒ«', 'ãŒ²' => 'ãƒ•ã‚¡ãƒ©ãƒƒãƒˆã‚™', 'ãŒ³' => 'ãƒ•ã‚£ãƒ¼ãƒˆ', 'ãŒ´' => 'ãƒ•ã‚™ãƒƒã‚·ã‚§ãƒ«', 'ãŒµ' => 'ãƒ•ãƒ©ãƒ³', 'ãŒ¶' => 'ãƒ˜ã‚¯ã‚¿ãƒ¼ãƒ«', 'ãŒ·' => 'ãƒ˜ã‚šã‚½', 'ãŒ¸' => 'ãƒ˜ã‚šãƒ‹ãƒ’', 'ãŒ¹' => 'ãƒ˜ãƒ«ãƒ„', 'ãŒº' => 'ãƒ˜ã‚šãƒ³ã‚¹', 'ãŒ»' => 'ãƒ˜ã‚šãƒ¼ã‚·ã‚™', 'ãŒ¼' => 'ãƒ˜ã‚™ãƒ¼ã‚¿', 'ãŒ½' => 'ãƒ›ã‚šã‚¤ãƒ³ãƒˆ', 'ãŒ¾' => 'ãƒ›ã‚™ãƒ«ãƒˆ', 'ãŒ¿' => 'ãƒ›ãƒ³', 'ã�€' => 'ãƒ›ã‚šãƒ³ãƒˆã‚™', 'ã��' => 'ãƒ›ãƒ¼ãƒ«', 'ã�‚' => 'ãƒ›ãƒ¼ãƒ³', 'ã�ƒ' => 'ãƒžã‚¤ã‚¯ãƒ­', 'ã�„' => 'ãƒžã‚¤ãƒ«', 'ã�…' => 'ãƒžãƒƒãƒ�', 'ã�†' => 'ãƒžãƒ«ã‚¯', 'ã�‡' => 'ãƒžãƒ³ã‚·ãƒ§ãƒ³', 'ã�ˆ' => 'ãƒŸã‚¯ãƒ­ãƒ³', 'ã�‰' => 'ãƒŸãƒª', 'ã�Š' => 'ãƒŸãƒªãƒ�ã‚™ãƒ¼ãƒ«', 'ã�‹' => 'ãƒ¡ã‚«ã‚™', 'ã�Œ' => 'ãƒ¡ã‚«ã‚™ãƒˆãƒ³', 'ã��' => 'ãƒ¡ãƒ¼ãƒˆãƒ«', 'ã�Ž' => 'ãƒ¤ãƒ¼ãƒˆã‚™', 'ã��' => 'ãƒ¤ãƒ¼ãƒ«', 'ã��' => 'ãƒ¦ã‚¢ãƒ³', 'ã�‘' => 'ãƒªãƒƒãƒˆãƒ«', 'ã�’' => 'ãƒªãƒ©', 'ã�“' => 'ãƒ«ãƒ’ã‚šãƒ¼', 'ã�”' => 'ãƒ«ãƒ¼ãƒ•ã‚™ãƒ«', 'ã�•' => 'ãƒ¬ãƒ ', 'ã�–' => 'ãƒ¬ãƒ³ãƒˆã‚±ã‚™ãƒ³', 'ã�—' => 'ãƒ¯ãƒƒãƒˆ', 'ã�˜' => '0ç‚¹', 'ã�™' => '1ç‚¹', 'ã�š' => '2ç‚¹', 'ã�›' => '3ç‚¹', 'ã�œ' => '4ç‚¹', 'ã��' => '5ç‚¹', 'ã�ž' => '6ç‚¹', 'ã�Ÿ' => '7ç‚¹', 'ã� ' => '8ç‚¹', 'ã�¡' => '9ç‚¹', 'ã�¢' => '10ç‚¹', 'ã�£' => '11ç‚¹', 'ã�¤' => '12ç‚¹', 'ã�¥' => '13ç‚¹', 'ã�¦' => '14ç‚¹', 'ã�§' => '15ç‚¹', 'ã�¨' => '16ç‚¹', 'ã�©' => '17ç‚¹', 'ã�ª' => '18ç‚¹', 'ã�«' => '19ç‚¹', 'ã�¬' => '20ç‚¹', 'ã�­' => '21ç‚¹', 'ã�®' => '22ç‚¹', 'ã�¯' => '23ç‚¹', 'ã�°' => '24ç‚¹', 'ã�±' => 'hPa', 'ã�²' => 'da', 'ã�³' => 'AU', 'ã�´' => 'bar', 'ã�µ' => 'oV', 'ã�¶' => 'pc', 'ã�·' => 'dm', 'ã�¸' => 'dm2', 'ã�¹' => 'dm3', 'ã�º' => 'IU', 'ã�»' => 'å¹³æˆ�', 'ã�¼' => 'æ˜­å’Œ', 'ã�½' => 'å¤§æ­£', 'ã�¾' => 'æ˜Žæ²»', 'ã�¿' => 'æ ªå¼�ä¼šç¤¾', 'ãŽ€' => 'pA', 'ãŽ�' => 'nA', 'ãŽ‚' => 'Î¼A', 'ãŽƒ' => 'mA', 'ãŽ„' => 'kA', 'ãŽ…' => 'KB', 'ãŽ†' => 'MB', 'ãŽ‡' => 'GB', 'ãŽˆ' => 'cal', 'ãŽ‰' => 'kcal', 'ãŽŠ' => 'pF', 'ãŽ‹' => 'nF', 'ãŽŒ' => 'Î¼F', 'ãŽ�' => 'Î¼g', 'ãŽŽ' => 'mg', 'ãŽ�' => 'kg', 'ãŽ�' => 'Hz', 'ãŽ‘' => 'kHz', 'ãŽ’' => 'MHz', 'ãŽ“' => 'GHz', 'ãŽ”' => 'THz', 'ãŽ•' => 'Î¼l', 'ãŽ–' => 'ml', 'ãŽ—' => 'dl', 'ãŽ˜' => 'kl', 'ãŽ™' => 'fm', 'ãŽš' => 'nm', 'ãŽ›' => 'Î¼m', 'ãŽœ' => 'mm', 'ãŽ�' => 'cm', 'ãŽž' => 'km', 'ãŽŸ' => 'mm2', 'ãŽ ' => 'cm2', 'ãŽ¡' => 'm2', 'ãŽ¢' => 'km2', 'ãŽ£' => 'mm3', 'ãŽ¤' => 'cm3', 'ãŽ¥' => 'm3', 'ãŽ¦' => 'km3', 'ãŽ§' => 'mâˆ•s', 'ãŽ¨' => 'mâˆ•s2', 'ãŽ©' => 'Pa', 'ãŽª' => 'kPa', 'ãŽ«' => 'MPa', 'ãŽ¬' => 'GPa', 'ãŽ­' => 'rad', 'ãŽ®' => 'radâˆ•s', 'ãŽ¯' => 'radâˆ•s2', 'ãŽ°' => 'ps', 'ãŽ±' => 'ns', 'ãŽ²' => 'Î¼s', 'ãŽ³' => 'ms', 'ãŽ´' => 'pV', 'ãŽµ' => 'nV', 'ãŽ¶' => 'Î¼V', 'ãŽ·' => 'mV', 'ãŽ¸' => 'kV', 'ãŽ¹' => 'MV', 'ãŽº' => 'pW', 'ãŽ»' => 'nW', 'ãŽ¼' => 'Î¼W', 'ãŽ½' => 'mW', 'ãŽ¾' => 'kW', 'ãŽ¿' => 'MW', 'ã�€' => 'kÎ©', 'ã��' => 'MÎ©', 'ã�‚' => 'a.m.', 'ã�ƒ' => 'Bq', 'ã�„' => 'cc', 'ã�…' => 'cd', 'ã�†' => 'Câˆ•kg', 'ã�‡' => 'Co.', 'ã�ˆ' => 'dB', 'ã�‰' => 'Gy', 'ã�Š' => 'ha', 'ã�‹' => 'HP', 'ã�Œ' => 'in', 'ã��' => 'KK', 'ã�Ž' => 'KM', 'ã��' => 'kt', 'ã��' => 'lm', 'ã�‘' => 'ln', 'ã�’' => 'log', 'ã�“' => 'lx', 'ã�”' => 'mb', 'ã�•' => 'mil', 'ã�–' => 'mol', 'ã�—' => 'PH', 'ã�˜' => 'p.m.', 'ã�™' => 'PPM', 'ã�š' => 'PR', 'ã�›' => 'sr', 'ã�œ' => 'Sv', 'ã��' => 'Wb', 'ã�ž' => 'Vâˆ•m', 'ã�Ÿ' => 'Aâˆ•m', 'ã� ' => '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æ—¥', 'ã�¿' => 'gal', 'êšœ' => 'ÑŠ', 'êš�' => 'ÑŒ', 'ê�°' => 'ê�¯', 'êŸ¸' => 'Ä¦', 'êŸ¹' => 'Å“', 'ê­œ' => 'êœ§', 'ê­�' => 'ê¬·', 'ê­ž' => 'É«', 'ê­Ÿ' => 'ê­’', 'ê­©' => 'Ê�', 'ï¬€' => 'ff', 'ï¬�' => 'fi', 'ï¬‚' => 'fl', 'ï¬ƒ' => 'ffi', 'ï¬„' => 'ffl', 'ï¬…' => 'st', 'ï¬†' => 'st', 'ï¬“' => 'Õ´Õ¶', 'ï¬”' => 'Õ´Õ¥', 'ï¬•' => 'Õ´Õ«', 'ï¬–' => 'Õ¾Õ¶', 'ï¬—' => 'Õ´Õ­', 'ï¬ ' => '×¢', 'ï¬¡' => '×�', 'ï¬¢' => '×“', 'ï¬£' => '×”', 'ï¬¤' => '×›', 'ï¬¥' => '×œ', 'ï¬¦' => '×�', 'ï¬§' => '×¨', 'ï¬¨' => '×ª', 'ï¬©' => '+', 'ï­�' => '×�×œ', 'ï­�' => 'Ù±', 'ï­‘' => 'Ù±', 'ï­’' => 'Ù»', 'ï­“' => 'Ù»', 'ï­”' => 'Ù»', 'ï­•' => 'Ù»', 'ï­–' => 'Ù¾', 'ï­—' => 'Ù¾', 'ï­˜' => 'Ù¾', 'ï­™' => 'Ù¾', 'ï­š' => 'Ú€', 'ï­›' => 'Ú€', 'ï­œ' => 'Ú€', 'ï­�' => 'Ú€', 'ï­ž' => 'Ùº', 'ï­Ÿ' => 'Ùº', 'ï­ ' => 'Ùº', 'ï­¡' => 'Ùº', 'ï­¢' => 'Ù¿', 'ï­£' => 'Ù¿', 'ï­¤' => 'Ù¿', 'ï­¥' => 'Ù¿', 'ï­¦' => 'Ù¹', 'ï­§' => 'Ù¹', 'ï­¨' => 'Ù¹', 'ï­©' => 'Ù¹', 'ï­ª' => 'Ú¤', 'ï­«' => 'Ú¤', 'ï­¬' => 'Ú¤', 'ï­­' => 'Ú¤', 'ï­®' => 'Ú¦', 'ï­¯' => 'Ú¦', 'ï­°' => 'Ú¦', 'ï­±' => 'Ú¦', 'ï­²' => 'Ú„', 'ï­³' => 'Ú„', 'ï­´' => 'Ú„', 'ï­µ' => 'Ú„', 'ï­¶' => 'Úƒ', 'ï­·' => 'Úƒ', 'ï­¸' => 'Úƒ', 'ï­¹' => 'Úƒ', 'ï­º' => 'Ú†', 'ï­»' => 'Ú†', 'ï­¼' => 'Ú†', 'ï­½' => 'Ú†', 'ï­¾' => 'Ú‡', 'ï­¿' => 'Ú‡', 'ï®€' => 'Ú‡', 'ï®�' => 'Ú‡', 'ï®‚' => 'Ú�', 'ï®ƒ' => 'Ú�', 'ï®„' => 'ÚŒ', 'ï®…' => 'ÚŒ', 'ï®†' => 'ÚŽ', 'ï®‡' => 'ÚŽ', 'ï®ˆ' => 'Úˆ', 'ï®‰' => 'Úˆ', 'ï®Š' => 'Ú˜', 'ï®‹' => 'Ú˜', 'ï®Œ' => 'Ú‘', 'ï®�' => 'Ú‘', 'ï®Ž' => 'Ú©', 'ï®�' => 'Ú©', 'ï®�' => 'Ú©', 'ï®‘' => 'Ú©', 'ï®’' => 'Ú¯', 'ï®“' => 'Ú¯', 'ï®”' => 'Ú¯', 'ï®•' => 'Ú¯', 'ï®–' => 'Ú³', 'ï®—' => 'Ú³', 'ï®˜' => 'Ú³', 'ï®™' => 'Ú³', 'ï®š' => 'Ú±', 'ï®›' => 'Ú±', 'ï®œ' => 'Ú±', 'ï®�' => 'Ú±', 'ï®ž' => 'Úº', 'ï®Ÿ' => 'Úº', 'ï® ' => 'Ú»', 'ï®¡' => 'Ú»', 'ï®¢' => 'Ú»', 'ï®£' => 'Ú»', 'ï®¤' => 'Û•Ù”', 'ï®¥' => 'Û•Ù”', 'ï®¦' => 'Û�', 'ï®§' => 'Û�', 'ï®¨' => 'Û�', 'ï®©' => 'Û�', 'ï®ª' => 'Ú¾', 'ï®«' => 'Ú¾', 'ï®¬' => 'Ú¾', 'ï®­' => 'Ú¾', 'ï®®' => 'Û’', 'ï®¯' => 'Û’', 'ï®°' => 'Û’Ù”', 'ï®±' => 'Û’Ù”', 'ï¯“' => 'Ú­', 'ï¯”' => 'Ú­', 'ï¯•' => 'Ú­', 'ï¯–' => 'Ú­', 'ï¯—' => 'Û‡', 'ï¯˜' => 'Û‡', 'ï¯™' => 'Û†', 'ï¯š' => 'Û†', 'ï¯›' => 'Ûˆ', 'ï¯œ' => 'Ûˆ', 'ï¯�' => 'Û‡Ù´', 'ï¯ž' => 'Û‹', 'ï¯Ÿ' => 'Û‹', 'ï¯ ' => 'Û…', 'ï¯¡' => 'Û…', 'ï¯¢' => 'Û‰', 'ï¯£' => 'Û‰', 'ï¯¤' => 'Û�', 'ï¯¥' => 'Û�', 'ï¯¦' => 'Û�', 'ï¯§' => 'Û�', 'ï¯¨' => 'Ù‰', 'ï¯©' => 'Ù‰', 'ï¯ª' => 'ÙŠÙ”Ø§', 'ï¯«' => 'ÙŠÙ”Ø§', 'ï¯¬' => 'ÙŠÙ”Û•', 'ï¯­' => 'ÙŠÙ”Û•', 'ï¯®' => 'ÙŠÙ”Ùˆ', 'ï¯¯' => 'ÙŠÙ”Ùˆ', 'ï¯°' => 'ÙŠÙ”Û‡', 'ï¯±' => 'ÙŠÙ”Û‡', 'ï¯²' => 'ÙŠÙ”Û†', 'ï¯³' => 'ÙŠÙ”Û†', 'ï¯´' => 'ÙŠÙ”Ûˆ', 'ï¯µ' => 'ÙŠÙ”Ûˆ', 'ï¯¶' => 'ÙŠÙ”Û�', 'ï¯·' => 'ÙŠÙ”Û�', 'ï¯¸' => 'ÙŠÙ”Û�', 'ï¯¹' => 'ÙŠÙ”Ù‰', 'ï¯º' => 'ÙŠÙ”Ù‰', 'ï¯»' => 'ÙŠÙ”Ù‰', 'ï¯¼' => 'ÛŒ', 'ï¯½' => 'ÛŒ', 'ï¯¾' => 'ÛŒ', 'ï¯¿' => 'ÛŒ', 'ï°€' => 'ÙŠÙ”Ø¬', 'ï°�' => 'ÙŠÙ”Ø­', 'ï°‚' => 'ÙŠÙ”Ù…', 'ï°ƒ' => 'ÙŠÙ”Ù‰', 'ï°„' => 'ÙŠÙ”ÙŠ', 'ï°…' => 'Ø¨Ø¬', 'ï°†' => 'Ø¨Ø­', 'ï°‡' => 'Ø¨Ø®', 'ï°ˆ' => 'Ø¨Ù…', 'ï°‰' => 'Ø¨Ù‰', 'ï°Š' => 'Ø¨ÙŠ', 'ï°‹' => 'ØªØ¬', 'ï°Œ' => 'ØªØ­', 'ï°�' => 'ØªØ®', 'ï°Ž' => 'ØªÙ…', 'ï°�' => 'ØªÙ‰', 'ï°�' => 'ØªÙŠ', 'ï°‘' => 'Ø«Ø¬', 'ï°’' => 'Ø«Ù…', 'ï°“' => 'Ø«Ù‰', 'ï°”' => 'Ø«ÙŠ', 'ï°•' => 'Ø¬Ø­', 'ï°–' => 'Ø¬Ù…', 'ï°—' => 'Ø­Ø¬', 'ï°˜' => 'Ø­Ù…', 'ï°™' => 'Ø®Ø¬', 'ï°š' => 'Ø®Ø­', 'ï°›' => 'Ø®Ù…', 'ï°œ' => 'Ø³Ø¬', 'ï°�' => 'Ø³Ø­', 'ï°ž' => 'Ø³Ø®', 'ï°Ÿ' => 'Ø³Ù…', 'ï° ' => 'ØµØ­', 'ï°¡' => 'ØµÙ…', 'ï°¢' => 'Ø¶Ø¬', 'ï°£' => 'Ø¶Ø­', 'ï°¤' => 'Ø¶Ø®', 'ï°¥' => 'Ø¶Ù…', 'ï°¦' => 'Ø·Ø­', 'ï°§' => 'Ø·Ù…', 'ï°¨' => 'Ø¸Ù…', 'ï°©' => 'Ø¹Ø¬', 'ï°ª' => 'Ø¹Ù…', 'ï°«' => 'ØºØ¬', 'ï°¬' => 'ØºÙ…', 'ï°­' => 'Ù�Ø¬', 'ï°®' => 'Ù�Ø­', 'ï°¯' => 'Ù�Ø®', 'ï°°' => 'Ù�Ù…', 'ï°±' => 'Ù�Ù‰', 'ï°²' => 'Ù�ÙŠ', 'ï°³' => 'Ù‚Ø­', 'ï°´' => 'Ù‚Ù…', 'ï°µ' => 'Ù‚Ù‰', 'ï°¶' => 'Ù‚ÙŠ', 'ï°·' => 'ÙƒØ§', 'ï°¸' => 'ÙƒØ¬', 'ï°¹' => 'ÙƒØ­', 'ï°º' => 'ÙƒØ®', 'ï°»' => 'ÙƒÙ„', 'ï°¼' => 'ÙƒÙ…', 'ï°½' => 'ÙƒÙ‰', 'ï°¾' => 'ÙƒÙŠ', 'ï°¿' => 'Ù„Ø¬', 'ï±€' => 'Ù„Ø­', 'ï±�' => 'Ù„Ø®', 'ï±‚' => 'Ù„Ù…', 'ï±ƒ' => 'Ù„Ù‰', 'ï±„' => 'Ù„ÙŠ', 'ï±…' => 'Ù…Ø¬', 'ï±†' => 'Ù…Ø­', 'ï±‡' => 'Ù…Ø®', 'ï±ˆ' => 'Ù…Ù…', 'ï±‰' => 'Ù…Ù‰', 'ï±Š' => 'Ù…ÙŠ', 'ï±‹' => 'Ù†Ø¬', 'ï±Œ' => 'Ù†Ø­', 'ï±�' => 'Ù†Ø®', 'ï±Ž' => 'Ù†Ù…', 'ï±�' => 'Ù†Ù‰', 'ï±�' => 'Ù†ÙŠ', 'ï±‘' => 'Ù‡Ø¬', 'ï±’' => 'Ù‡Ù…', 'ï±“' => 'Ù‡Ù‰', 'ï±”' => 'Ù‡ÙŠ', 'ï±•' => 'ÙŠØ¬', 'ï±–' => 'ÙŠØ­', 'ï±—' => 'ÙŠØ®', 'ï±˜' => 'ÙŠÙ…', 'ï±™' => 'ÙŠÙ‰', 'ï±š' => 'ÙŠÙŠ', 'ï±›' => 'Ø°Ù°', 'ï±œ' => 'Ø±Ù°', 'ï±�' => 'Ù‰Ù°', 'ï±ž' => ' ÙŒÙ‘', 'ï±Ÿ' => ' Ù�Ù‘', 'ï± ' => ' ÙŽÙ‘', 'ï±¡' => ' Ù�Ù‘', 'ï±¢' => ' Ù�Ù‘', 'ï±£' => ' Ù‘Ù°', 'ï±¤' => 'ÙŠÙ”Ø±', 'ï±¥' => 'ÙŠÙ”Ø²', 'ï±¦' => 'ÙŠÙ”Ù…', 'ï±§' => 'ÙŠÙ”Ù†', 'ï±¨' => 'ÙŠÙ”Ù‰', 'ï±©' => 'ÙŠÙ”ÙŠ', 'ï±ª' => 'Ø¨Ø±', 'ï±«' => 'Ø¨Ø²', 'ï±¬' => 'Ø¨Ù…', 'ï±­' => 'Ø¨Ù†', 'ï±®' => 'Ø¨Ù‰', 'ï±¯' => 'Ø¨ÙŠ', 'ï±°' => 'ØªØ±', 'ï±±' => 'ØªØ²', 'ï±²' => 'ØªÙ…', 'ï±³' => 'ØªÙ†', 'ï±´' => 'ØªÙ‰', 'ï±µ' => 'ØªÙŠ', 'ï±¶' => 'Ø«Ø±', 'ï±·' => 'Ø«Ø²', 'ï±¸' => 'Ø«Ù…', 'ï±¹' => 'Ø«Ù†', 'ï±º' => 'Ø«Ù‰', 'ï±»' => 'Ø«ÙŠ', 'ï±¼' => 'Ù�Ù‰', 'ï±½' => 'Ù�ÙŠ', 'ï±¾' => 'Ù‚Ù‰', 'ï±¿' => 'Ù‚ÙŠ', 'ï²€' => 'ÙƒØ§', 'ï²�' => 'ÙƒÙ„', 'ï²‚' => 'ÙƒÙ…', 'ï²ƒ' => 'ÙƒÙ‰', 'ï²„' => 'ÙƒÙŠ', 'ï²…' => 'Ù„Ù…', 'ï²†' => 'Ù„Ù‰', 'ï²‡' => 'Ù„ÙŠ', 'ï²ˆ' => 'Ù…Ø§', 'ï²‰' => 'Ù…Ù…', 'ï²Š' => 'Ù†Ø±', 'ï²‹' => 'Ù†Ø²', 'ï²Œ' => 'Ù†Ù…', 'ï²�' => 'Ù†Ù†', 'ï²Ž' => 'Ù†Ù‰', 'ï²�' => 'Ù†ÙŠ', 'ï²�' => 'Ù‰Ù°', 'ï²‘' => 'ÙŠØ±', 'ï²’' => 'ÙŠØ²', 'ï²“' => 'ÙŠÙ…', 'ï²”' => 'ÙŠÙ†', 'ï²•' => 'ÙŠÙ‰', 'ï²–' => 'ÙŠÙŠ', 'ï²—' => 'ÙŠÙ”Ø¬', 'ï²˜' => 'ÙŠÙ”Ø­', 'ï²™' => 'ÙŠÙ”Ø®', 'ï²š' => 'ÙŠÙ”Ù…', 'ï²›' => 'ÙŠÙ”Ù‡', 'ï²œ' => 'Ø¨Ø¬', 'ï²�' => 'Ø¨Ø­', 'ï²ž' => 'Ø¨Ø®', 'ï²Ÿ' => 'Ø¨Ù…', 'ï² ' => 'Ø¨Ù‡', 'ï²¡' => 'ØªØ¬', 'ï²¢' => 'ØªØ­', 'ï²£' => 'ØªØ®', 'ï²¤' => 'ØªÙ…', 'ï²¥' => 'ØªÙ‡', 'ï²¦' => 'Ø«Ù…', 'ï²§' => 'Ø¬Ø­', 'ï²¨' => 'Ø¬Ù…', 'ï²©' => 'Ø­Ø¬', 'ï²ª' => 'Ø­Ù…', 'ï²«' => 'Ø®Ø¬', 'ï²¬' => 'Ø®Ù…', 'ï²­' => 'Ø³Ø¬', 'ï²®' => 'Ø³Ø­', 'ï²¯' => 'Ø³Ø®', 'ï²°' => 'Ø³Ù…', 'ï²±' => 'ØµØ­', 'ï²²' => 'ØµØ®', 'ï²³' => 'ØµÙ…', 'ï²´' => 'Ø¶Ø¬', 'ï²µ' => 'Ø¶Ø­', 'ï²¶' => 'Ø¶Ø®', 'ï²·' => 'Ø¶Ù…', 'ï²¸' => 'Ø·Ø­', 'ï²¹' => 'Ø¸Ù…', 'ï²º' => 'Ø¹Ø¬', 'ï²»' => 'Ø¹Ù…', 'ï²¼' => 'ØºØ¬', 'ï²½' => 'ØºÙ…', 'ï²¾' => 'Ù�Ø¬', 'ï²¿' => 'Ù�Ø­', 'ï³€' => 'Ù�Ø®', 'ï³�' => 'Ù�Ù…', 'ï³‚' => 'Ù‚Ø­', 'ï³ƒ' => 'Ù‚Ù…', 'ï³„' => 'ÙƒØ¬', 'ï³…' => 'ÙƒØ­', 'ï³†' => 'ÙƒØ®', 'ï³‡' => 'ÙƒÙ„', 'ï³ˆ' => 'ÙƒÙ…', 'ï³‰' => 'Ù„Ø¬', 'ï³Š' => 'Ù„Ø­', 'ï³‹' => 'Ù„Ø®', 'ï³Œ' => 'Ù„Ù…', 'ï³�' => 'Ù„Ù‡', 'ï³Ž' => 'Ù…Ø¬', 'ï³�' => 'Ù…Ø­', 'ï³�' => 'Ù…Ø®', 'ï³‘' => 'Ù…Ù…', 'ï³’' => 'Ù†Ø¬', 'ï³“' => 'Ù†Ø­', 'ï³”' => 'Ù†Ø®', 'ï³•' => 'Ù†Ù…', 'ï³–' => 'Ù†Ù‡', 'ï³—' => 'Ù‡Ø¬', 'ï³˜' => 'Ù‡Ù…', 'ï³™' => 'Ù‡Ù°', 'ï³š' => 'ÙŠØ¬', 'ï³›' => 'ÙŠØ­', 'ï³œ' => 'ÙŠØ®', 'ï³�' => 'ÙŠÙ…', 'ï³ž' => 'ÙŠÙ‡', 'ï³Ÿ' => 'ÙŠÙ”Ù…', 'ï³ ' => 'ÙŠÙ”Ù‡', 'ï³¡' => 'Ø¨Ù…', 'ï³¢' => 'Ø¨Ù‡', 'ï³£' => 'ØªÙ…', 'ï³¤' => 'ØªÙ‡', 'ï³¥' => 'Ø«Ù…', 'ï³¦' => 'Ø«Ù‡', 'ï³§' => 'Ø³Ù…', 'ï³¨' => 'Ø³Ù‡', 'ï³©' => 'Ø´Ù…', 'ï³ª' => 'Ø´Ù‡', 'ï³«' => 'ÙƒÙ„', 'ï³¬' => 'ÙƒÙ…', 'ï³­' => 'Ù„Ù…', 'ï³®' => 'Ù†Ù…', 'ï³¯' => 'Ù†Ù‡', 'ï³°' => 'ÙŠÙ…', 'ï³±' => 'ÙŠÙ‡', 'ï³²' => 'Ù€ÙŽÙ‘', 'ï³³' => 'Ù€Ù�Ù‘', 'ï³´' => 'Ù€Ù�Ù‘', 'ï³µ' => 'Ø·Ù‰', 'ï³¶' => 'Ø·ÙŠ', 'ï³·' => 'Ø¹Ù‰', 'ï³¸' => 'Ø¹ÙŠ', 'ï³¹' => 'ØºÙ‰', 'ï³º' => 'ØºÙŠ', 'ï³»' => 'Ø³Ù‰', 'ï³¼' => 'Ø³ÙŠ', 'ï³½' => 'Ø´Ù‰', 'ï³¾' => 'Ø´ÙŠ', 'ï³¿' => 'Ø­Ù‰', 'ï´€' => 'Ø­ÙŠ', 'ï´�' => 'Ø¬Ù‰', 'ï´‚' => 'Ø¬ÙŠ', 'ï´ƒ' => 'Ø®Ù‰', 'ï´„' => 'Ø®ÙŠ', 'ï´…' => 'ØµÙ‰', 'ï´†' => 'ØµÙŠ', 'ï´‡' => 'Ø¶Ù‰', 'ï´ˆ' => 'Ø¶ÙŠ', 'ï´‰' => 'Ø´Ø¬', 'ï´Š' => 'Ø´Ø­', 'ï´‹' => 'Ø´Ø®', 'ï´Œ' => 'Ø´Ù…', 'ï´�' => 'Ø´Ø±', 'ï´Ž' => 'Ø³Ø±', 'ï´�' => 'ØµØ±', 'ï´�' => 'Ø¶Ø±', 'ï´‘' => 'Ø·Ù‰', 'ï´’' => 'Ø·ÙŠ', 'ï´“' => 'Ø¹Ù‰', 'ï´”' => 'Ø¹ÙŠ', 'ï´•' => 'ØºÙ‰', 'ï´–' => 'ØºÙŠ', 'ï´—' => 'Ø³Ù‰', 'ï´˜' => 'Ø³ÙŠ', 'ï´™' => 'Ø´Ù‰', 'ï´š' => 'Ø´ÙŠ', 'ï´›' => 'Ø­Ù‰', 'ï´œ' => 'Ø­ÙŠ', 'ï´�' => 'Ø¬Ù‰', 'ï´ž' => 'Ø¬ÙŠ', 'ï´Ÿ' => 'Ø®Ù‰', 'ï´ ' => 'Ø®ÙŠ', 'ï´¡' => 'ØµÙ‰', 'ï´¢' => 'ØµÙŠ', 'ï´£' => 'Ø¶Ù‰', 'ï´¤' => 'Ø¶ÙŠ', 'ï´¥' => 'Ø´Ø¬', 'ï´¦' => 'Ø´Ø­', 'ï´§' => 'Ø´Ø®', 'ï´¨' => 'Ø´Ù…', 'ï´©' => 'Ø´Ø±', 'ï´ª' => 'Ø³Ø±', 'ï´«' => 'ØµØ±', 'ï´¬' => 'Ø¶Ø±', 'ï´­' => 'Ø´Ø¬', 'ï´®' => 'Ø´Ø­', 'ï´¯' => 'Ø´Ø®', 'ï´°' => 'Ø´Ù…', 'ï´±' => 'Ø³Ù‡', 'ï´²' => 'Ø´Ù‡', 'ï´³' => 'Ø·Ù…', 'ï´´' => 'Ø³Ø¬', 'ï´µ' => 'Ø³Ø­', 'ï´¶' => 'Ø³Ø®', 'ï´·' => 'Ø´Ø¬', 'ï´¸' => 'Ø´Ø­', 'ï´¹' => 'Ø´Ø®', 'ï´º' => 'Ø·Ù…', 'ï´»' => 'Ø¸Ù…', 'ï´¼' => 'Ø§Ù‹', 'ï´½' => 'Ø§Ù‹', 'ïµ�' => 'ØªØ¬Ù…', 'ïµ‘' => 'ØªØ­Ø¬', 'ïµ’' => 'ØªØ­Ø¬', 'ïµ“' => 'ØªØ­Ù…', 'ïµ”' => 'ØªØ®Ù…', 'ïµ•' => 'ØªÙ…Ø¬', 'ïµ–' => 'ØªÙ…Ø­', 'ïµ—' => 'ØªÙ…Ø®', 'ïµ˜' => 'Ø¬Ù…Ø­', 'ïµ™' => 'Ø¬Ù…Ø­', 'ïµš' => 'Ø­Ù…ÙŠ', 'ïµ›' => 'Ø­Ù…Ù‰', 'ïµœ' => 'Ø³Ø­Ø¬', 'ïµ�' => 'Ø³Ø¬Ø­', 'ïµž' => 'Ø³Ø¬Ù‰', 'ïµŸ' => 'Ø³Ù…Ø­', 'ïµ ' => 'Ø³Ù…Ø­', 'ïµ¡' => 'Ø³Ù…Ø¬', 'ïµ¢' => 'Ø³Ù…Ù…', 'ïµ£' => 'Ø³Ù…Ù…', 'ïµ¤' => 'ØµØ­Ø­', 'ïµ¥' => 'ØµØ­Ø­', 'ïµ¦' => 'ØµÙ…Ù…', 'ïµ§' => 'Ø´Ø­Ù…', 'ïµ¨' => 'Ø´Ø­Ù…', 'ïµ©' => 'Ø´Ø¬ÙŠ', 'ïµª' => 'Ø´Ù…Ø®', 'ïµ«' => 'Ø´Ù…Ø®', 'ïµ¬' => 'Ø´Ù…Ù…', 'ïµ­' => 'Ø´Ù…Ù…', 'ïµ®' => 'Ø¶Ø­Ù‰', 'ïµ¯' => 'Ø¶Ø®Ù…', 'ïµ°' => 'Ø¶Ø®Ù…', 'ïµ±' => 'Ø·Ù…Ø­', 'ïµ²' => 'Ø·Ù…Ø­', 'ïµ³' => 'Ø·Ù…Ù…', 'ïµ´' => 'Ø·Ù…ÙŠ', 'ïµµ' => 'Ø¹Ø¬Ù…', 'ïµ¶' => 'Ø¹Ù…Ù…', 'ïµ·' => 'Ø¹Ù…Ù…', 'ïµ¸' => 'Ø¹Ù…Ù‰', 'ïµ¹' => 'ØºÙ…Ù…', 'ïµº' => 'ØºÙ…ÙŠ', 'ïµ»' => 'ØºÙ…Ù‰', 'ïµ¼' => 'Ù�Ø®Ù…', 'ïµ½' => 'Ù�Ø®Ù…', 'ïµ¾' => 'Ù‚Ù…Ø­', 'ïµ¿' => 'Ù‚Ù…Ù…', 'ï¶€' => 'Ù„Ø­Ù…', 'ï¶�' => 'Ù„Ø­ÙŠ', 'ï¶‚' => 'Ù„Ø­Ù‰', 'ï¶ƒ' => 'Ù„Ø¬Ø¬', 'ï¶„' => 'Ù„Ø¬Ø¬', 'ï¶…' => 'Ù„Ø®Ù…', 'ï¶†' => 'Ù„Ø®Ù…', 'ï¶‡' => 'Ù„Ù…Ø­', 'ï¶ˆ' => 'Ù„Ù…Ø­', 'ï¶‰' => 'Ù…Ø­Ø¬', 'ï¶Š' => 'Ù…Ø­Ù…', 'ï¶‹' => 'Ù…Ø­ÙŠ', 'ï¶Œ' => 'Ù…Ø¬Ø­', 'ï¶�' => 'Ù…Ø¬Ù…', 'ï¶Ž' => 'Ù…Ø®Ø¬', 'ï¶�' => 'Ù…Ø®Ù…', 'ï¶’' => 'Ù…Ø¬Ø®', 'ï¶“' => 'Ù‡Ù…Ø¬', 'ï¶”' => 'Ù‡Ù…Ù…', 'ï¶•' => 'Ù†Ø­Ù…', 'ï¶–' => 'Ù†Ø­Ù‰', 'ï¶—' => 'Ù†Ø¬Ù…', 'ï¶˜' => 'Ù†Ø¬Ù…', 'ï¶™' => 'Ù†Ø¬Ù‰', 'ï¶š' => 'Ù†Ù…ÙŠ', 'ï¶›' => 'Ù†Ù…Ù‰', 'ï¶œ' => 'ÙŠÙ…Ù…', 'ï¶�' => 'ÙŠÙ…Ù…', 'ï¶ž' => 'Ø¨Ø®ÙŠ', 'ï¶Ÿ' => 'ØªØ¬ÙŠ', 'ï¶ ' => 'ØªØ¬Ù‰', 'ï¶¡' => 'ØªØ®ÙŠ', 'ï¶¢' => 'ØªØ®Ù‰', 'ï¶£' => 'ØªÙ…ÙŠ', 'ï¶¤' => 'ØªÙ…Ù‰', 'ï¶¥' => 'Ø¬Ù…ÙŠ', 'ï¶¦' => 'Ø¬Ø­Ù‰', 'ï¶§' => 'Ø¬Ù…Ù‰', 'ï¶¨' => 'Ø³Ø®Ù‰', 'ï¶©' => 'ØµØ­ÙŠ', 'ï¶ª' => 'Ø´Ø­ÙŠ', 'ï¶«' => 'Ø¶Ø­ÙŠ', 'ï¶¬' => 'Ù„Ø¬ÙŠ', 'ï¶­' => 'Ù„Ù…ÙŠ', 'ï¶®' => 'ÙŠØ­ÙŠ', 'ï¶¯' => 'ÙŠØ¬ÙŠ', 'ï¶°' => 'ÙŠÙ…ÙŠ', 'ï¶±' => 'Ù…Ù…ÙŠ', 'ï¶²' => 'Ù‚Ù…ÙŠ', 'ï¶³' => 'Ù†Ø­ÙŠ', 'ï¶´' => 'Ù‚Ù…Ø­', 'ï¶µ' => 'Ù„Ø­Ù…', 'ï¶¶' => 'Ø¹Ù…ÙŠ', 'ï¶·' => 'ÙƒÙ…ÙŠ', 'ï¶¸' => 'Ù†Ø¬Ø­', 'ï¶¹' => 'Ù…Ø®ÙŠ', 'ï¶º' => 'Ù„Ø¬Ù…', 'ï¶»' => 'ÙƒÙ…Ù…', 'ï¶¼' => 'Ù„Ø¬Ù…', 'ï¶½' => 'Ù†Ø¬Ø­', 'ï¶¾' => 'Ø¬Ø­ÙŠ', 'ï¶¿' => 'Ø­Ø¬ÙŠ', 'ï·€' => 'Ù…Ø¬ÙŠ', 'ï·�' => 'Ù�Ù…ÙŠ', 'ï·‚' => 'Ø¨Ø­ÙŠ', 'ï·ƒ' => 'ÙƒÙ…Ù…', 'ï·„' => 'Ø¹Ø¬Ù…', 'ï·…' => 'ØµÙ…Ù…', 'ï·†' => 'Ø³Ø®ÙŠ', 'ï·‡' => 'Ù†Ø¬ÙŠ', 'ï·°' => 'ØµÙ„Û’', 'ï·±' => 'Ù‚Ù„Û’', 'ï·²' => 'Ø§Ù„Ù„Ù‡', 'ï·³' => 'Ø§ÙƒØ¨Ø±', 'ï·´' => 'Ù…Ø­Ù…Ø¯', 'ï·µ' => 'ØµÙ„Ø¹Ù…', 'ï·¶' => 'Ø±Ø³ÙˆÙ„', 'ï··' => 'Ø¹Ù„ÙŠÙ‡', 'ï·¸' => 'ÙˆØ³Ù„Ù…', 'ï·¹' => 'ØµÙ„Ù‰', 'ï·º' => 'ØµÙ„Ù‰ Ø§Ù„Ù„Ù‡ Ø¹Ù„ÙŠÙ‡ ÙˆØ³Ù„Ù…', 'ï·»' => 'Ø¬Ù„ Ø¬Ù„Ø§Ù„Ù‡', 'ï·¼' => 'Ø±ÛŒØ§Ù„', 'ï¸�' => ',', 'ï¸‘' => 'ã€�', 'ï¸’' => 'ã€‚', 'ï¸“' => ':', 'ï¸”' => ';', 'ï¸•' => '!', 'ï¸–' => '?', 'ï¸—' => 'ã€–', 'ï¸˜' => 'ã€—', 'ï¸™' => '...', 'ï¸°' => '..', 'ï¸±' => 'â€”', 'ï¸²' => 'â€“', 'ï¸³' => '_', 'ï¸´' => '_', 'ï¸µ' => '(', 'ï¸¶' => ')', 'ï¸·' => '{', 'ï¸¸' => '}', 'ï¸¹' => 'ã€”', 'ï¸º' => 'ã€•', 'ï¸»' => 'ã€�', 'ï¸¼' => 'ã€‘', 'ï¸½' => 'ã€Š', 'ï¸¾' => 'ã€‹', 'ï¸¿' => 'ã€ˆ', 'ï¹€' => 'ã€‰', 'ï¹�' => 'ã€Œ', 'ï¹‚' => 'ã€�', 'ï¹ƒ' => 'ã€Ž', 'ï¹„' => 'ã€�', 'ï¹‡' => '[', 'ï¹ˆ' => ']', 'ï¹‰' => ' Ì…', 'ï¹Š' => ' Ì…', 'ï¹‹' => ' Ì…', 'ï¹Œ' => ' Ì…', 'ï¹�' => '_', 'ï¹Ž' => '_', 'ï¹�' => '_', 'ï¹�' => ',', 'ï¹‘' => 'ã€�', 'ï¹’' => '.', 'ï¹”' => ';', 'ï¹•' => ':', 'ï¹–' => '?', 'ï¹—' => '!', 'ï¹˜' => 'â€”', 'ï¹™' => '(', 'ï¹š' => ')', 'ï¹›' => '{', 'ï¹œ' => '}', 'ï¹�' => 'ã€”', 'ï¹ž' => 'ã€•', 'ï¹Ÿ' => '#', 'ï¹ ' => '&', 'ï¹¡' => '*', 'ï¹¢' => '+', 'ï¹£' => '-', 'ï¹¤' => '<', 'ï¹¥' => '>', 'ï¹¦' => '=', 'ï¹¨' => '\\', 'ï¹©' => '$', 'ï¹ª' => '%', 'ï¹«' => '@', 'ï¹°' => ' Ù‹', 'ï¹±' => 'Ù€Ù‹', 'ï¹²' => ' ÙŒ', 'ï¹´' => ' Ù�', 'ï¹¶' => ' ÙŽ', 'ï¹·' => 'Ù€ÙŽ', 'ï¹¸' => ' Ù�', 'ï¹¹' => 'Ù€Ù�', 'ï¹º' => ' Ù�', 'ï¹»' => 'Ù€Ù�', 'ï¹¼' => ' Ù‘', 'ï¹½' => 'Ù€Ù‘', 'ï¹¾' => ' Ù’', 'ï¹¿' => 'Ù€Ù’', 'ïº€' => 'Ø¡', 'ïº�' => 'Ø§Ù“', 'ïº‚' => 'Ø§Ù“', 'ïºƒ' => 'Ø§Ù”', 'ïº„' => 'Ø§Ù”', 'ïº…' => 'ÙˆÙ”', 'ïº†' => 'ÙˆÙ”', 'ïº‡' => 'Ø§Ù•', 'ïºˆ' => 'Ø§Ù•', 'ïº‰' => 'ÙŠÙ”', 'ïºŠ' => 'ÙŠÙ”', 'ïº‹' => 'ÙŠÙ”', 'ïºŒ' => 'ÙŠÙ”', 'ïº�' => 'Ø§', 'ïºŽ' => 'Ø§', 'ïº�' => 'Ø¨', 'ïº�' => 'Ø¨', 'ïº‘' => 'Ø¨', 'ïº’' => 'Ø¨', 'ïº“' => 'Ø©', 'ïº”' => 'Ø©', 'ïº•' => 'Øª', 'ïº–' => 'Øª', 'ïº—' => 'Øª', 'ïº˜' => 'Øª', 'ïº™' => 'Ø«', 'ïºš' => 'Ø«', 'ïº›' => 'Ø«', 'ïºœ' => 'Ø«', 'ïº�' => 'Ø¬', 'ïºž' => 'Ø¬', 'ïºŸ' => 'Ø¬', 'ïº ' => 'Ø¬', 'ïº¡' => 'Ø­', 'ïº¢' => 'Ø­', 'ïº£' => 'Ø­', 'ïº¤' => 'Ø­', 'ïº¥' => 'Ø®', 'ïº¦' => 'Ø®', 'ïº§' => 'Ø®', 'ïº¨' => 'Ø®', 'ïº©' => 'Ø¯', 'ïºª' => 'Ø¯', 'ïº«' => 'Ø°', 'ïº¬' => 'Ø°', 'ïº­' => 'Ø±', 'ïº®' => 'Ø±', 'ïº¯' => 'Ø²', 'ïº°' => 'Ø²', 'ïº±' => 'Ø³', 'ïº²' => 'Ø³', 'ïº³' => 'Ø³', 'ïº´' => 'Ø³', 'ïºµ' => 'Ø´', 'ïº¶' => 'Ø´', 'ïº·' => 'Ø´', 'ïº¸' => 'Ø´', 'ïº¹' => 'Øµ', 'ïºº' => 'Øµ', 'ïº»' => 'Øµ', 'ïº¼' => 'Øµ', 'ïº½' => 'Ø¶', 'ïº¾' => 'Ø¶', 'ïº¿' => 'Ø¶', 'ï»€' => 'Ø¶', 'ï»�' => 'Ø·', 'ï»‚' => 'Ø·', 'ï»ƒ' => 'Ø·', 'ï»„' => 'Ø·', 'ï»…' => 'Ø¸', 'ï»†' => 'Ø¸', 'ï»‡' => 'Ø¸', 'ï»ˆ' => 'Ø¸', 'ï»‰' => 'Ø¹', 'ï»Š' => 'Ø¹', 'ï»‹' => 'Ø¹', 'ï»Œ' => 'Ø¹', 'ï»�' => 'Øº', 'ï»Ž' => 'Øº', 'ï»�' => 'Øº', 'ï»�' => 'Øº', 'ï»‘' => 'Ù�', 'ï»’' => 'Ù�', 'ï»“' => 'Ù�', 'ï»”' => 'Ù�', 'ï»•' => 'Ù‚', 'ï»–' => 'Ù‚', 'ï»—' => 'Ù‚', 'ï»˜' => 'Ù‚', 'ï»™' => 'Ùƒ', 'ï»š' => 'Ùƒ', 'ï»›' => 'Ùƒ', 'ï»œ' => 'Ùƒ', 'ï»�' => 'Ù„', 'ï»ž' => 'Ù„', 'ï»Ÿ' => 'Ù„', 'ï» ' => 'Ù„', 'ï»¡' => 'Ù…', 'ï»¢' => 'Ù…', 'ï»£' => 'Ù…', 'ï»¤' => 'Ù…', 'ï»¥' => 'Ù†', 'ï»¦' => 'Ù†', 'ï»§' => 'Ù†', 'ï»¨' => 'Ù†', 'ï»©' => 'Ù‡', 'ï»ª' => 'Ù‡', 'ï»«' => 'Ù‡', 'ï»¬' => 'Ù‡', 'ï»­' => 'Ùˆ', 'ï»®' => 'Ùˆ', 'ï»¯' => 'Ù‰', 'ï»°' => 'Ù‰', 'ï»±' => 'ÙŠ', 'ï»²' => 'ÙŠ', 'ï»³' => 'ÙŠ', 'ï»´' => 'ÙŠ', 'ï»µ' => 'Ù„Ø§Ù“', 'ï»¶' => 'Ù„Ø§Ù“', 'ï»·' => 'Ù„Ø§Ù”', 'ï»¸' => 'Ù„Ø§Ù”', 'ï»¹' => 'Ù„Ø§Ù•', 'ï»º' => 'Ù„Ø§Ù•', 'ï»»' => 'Ù„Ø§', 'ï»¼' => 'Ù„Ø§', 'ï¼�' => '!', 'ï¼‚' => '"', 'ï¼ƒ' => '#', 'ï¼„' => '$', 'ï¼…' => '%', 'ï¼†' => '&', 'ï¼‡' => '\'', 'ï¼ˆ' => '(', 'ï¼‰' => ')', 'ï¼Š' => '*', 'ï¼‹' => '+', 'ï¼Œ' => ',', 'ï¼�' => '-', 'ï¼Ž' => '.', 'ï¼�' => '/', 'ï¼�' => '0', 'ï¼‘' => '1', 'ï¼’' => '2', 'ï¼“' => '3', 'ï¼”' => '4', 'ï¼•' => '5', 'ï¼–' => '6', 'ï¼—' => '7', 'ï¼˜' => '8', 'ï¼™' => '9', 'ï¼š' => ':', 'ï¼›' => ';', 'ï¼œ' => '<', 'ï¼�' => '=', 'ï¼ž' => '>', 'ï¼Ÿ' => '?', 'ï¼ ' => '@', 'ï¼¡' => 'A', 'ï¼¢' => 'B', 'ï¼£' => 'C', 'ï¼¤' => 'D', 'ï¼¥' => 'E', 'ï¼¦' => 'F', 'ï¼§' => 'G', 'ï¼¨' => 'H', 'ï¼©' => 'I', 'ï¼ª' => 'J', 'ï¼«' => 'K', 'ï¼¬' => 'L', 'ï¼­' => 'M', 'ï¼®' => 'N', 'ï¼¯' => 'O', 'ï¼°' => 'P', 'ï¼±' => 'Q', 'ï¼²' => 'R', 'ï¼³' => 'S', 'ï¼´' => 'T', 'ï¼µ' => 'U', 'ï¼¶' => 'V', 'ï¼·' => 'W', 'ï¼¸' => 'X', 'ï¼¹' => 'Y', 'ï¼º' => 'Z', 'ï¼»' => '[', 'ï¼¼' => '\\', 'ï¼½' => ']', 'ï¼¾' => '^', 'ï¼¿' => '_', 'ï½€' => '`', 'ï½�' => 'a', 'ï½‚' => 'b', 'ï½ƒ' => 'c', 'ï½„' => 'd', 'ï½…' => 'e', 'ï½†' => 'f', 'ï½‡' => 'g', 'ï½ˆ' => 'h', 'ï½‰' => 'i', 'ï½Š' => 'j', 'ï½‹' => 'k', 'ï½Œ' => 'l', 'ï½�' => 'm', 'ï½Ž' => 'n', 'ï½�' => 'o', 'ï½�' => 'p', 'ï½‘' => 'q', 'ï½’' => 'r', 'ï½“' => 's', 'ï½”' => 't', 'ï½•' => 'u', 'ï½–' => 'v', 'ï½—' => 'w', 'ï½˜' => 'x', 'ï½™' => 'y', 'ï½š' => 'z', 'ï½›' => '{', 'ï½œ' => '|', 'ï½�' => '}', 'ï½ž' => '~', 'ï½Ÿ' => 'â¦…', 'ï½ ' => 'â¦†', 'ï½¡' => 'ã€‚', 'ï½¢' => 'ã€Œ', 'ï½£' => 'ã€�', 'ï½¤' => 'ã€�', 'ï½¥' => 'ãƒ»', 'ï½¦' => 'ãƒ²', 'ï½§' => 'ã‚¡', 'ï½¨' => 'ã‚£', 'ï½©' => 'ã‚¥', 'ï½ª' => 'ã‚§', 'ï½«' => 'ã‚©', 'ï½¬' => 'ãƒ£', 'ï½­' => 'ãƒ¥', 'ï½®' => 'ãƒ§', 'ï½¯' => 'ãƒƒ', 'ï½°' => 'ãƒ¼', 'ï½±' => 'ã‚¢', 'ï½²' => 'ã‚¤', 'ï½³' => 'ã‚¦', 'ï½´' => 'ã‚¨', 'ï½µ' => 'ã‚ª', 'ï½¶' => 'ã‚«', 'ï½·' => 'ã‚­', 'ï½¸' => 'ã‚¯', 'ï½¹' => 'ã‚±', 'ï½º' => 'ã‚³', 'ï½»' => 'ã‚µ', 'ï½¼' => 'ã‚·', 'ï½½' => 'ã‚¹', 'ï½¾' => 'ã‚»', 'ï½¿' => 'ã‚½', 'ï¾€' => 'ã‚¿', 'ï¾�' => 'ãƒ�', 'ï¾‚' => 'ãƒ„', 'ï¾ƒ' => 'ãƒ†', 'ï¾„' => 'ãƒˆ', 'ï¾…' => 'ãƒŠ', 'ï¾†' => 'ãƒ‹', 'ï¾‡' => 'ãƒŒ', 'ï¾ˆ' => 'ãƒ�', 'ï¾‰' => 'ãƒŽ', 'ï¾Š' => 'ãƒ�', 'ï¾‹' => 'ãƒ’', 'ï¾Œ' => 'ãƒ•', 'ï¾�' => 'ãƒ˜', 'ï¾Ž' => 'ãƒ›', 'ï¾�' => 'ãƒž', 'ï¾�' => 'ãƒŸ', 'ï¾‘' => 'ãƒ ', 'ï¾’' => 'ãƒ¡', 'ï¾“' => 'ãƒ¢', 'ï¾”' => 'ãƒ¤', 'ï¾•' => 'ãƒ¦', 'ï¾–' => 'ãƒ¨', 'ï¾—' => 'ãƒ©', 'ï¾˜' => 'ãƒª', 'ï¾™' => 'ãƒ«', 'ï¾š' => 'ãƒ¬', 'ï¾›' => 'ãƒ­', 'ï¾œ' => 'ãƒ¯', 'ï¾�' => 'ãƒ³', 'ï¾ž' => 'ã‚™', 'ï¾Ÿ' => 'ã‚š', 'ï¾ ' => 'á… ', 'ï¾¡' => 'á„€', 'ï¾¢' => 'á„�', 'ï¾£' => 'á†ª', 'ï¾¤' => 'á„‚', 'ï¾¥' => 'á†¬', 'ï¾¦' => 'á†­', 'ï¾§' => 'á„ƒ', 'ï¾¨' => 'á„„', 'ï¾©' => 'á„…', 'ï¾ª' => 'á†°', 'ï¾«' => 'á†±', 'ï¾¬' => 'á†²', 'ï¾­' => 'á†³', 'ï¾®' => 'á†´', 'ï¾¯' => 'á†µ', 'ï¾°' => 'á„š', 'ï¾±' => 'á„†', 'ï¾²' => 'á„‡', 'ï¾³' => 'á„ˆ', 'ï¾´' => 'á„¡', 'ï¾µ' => 'á„‰', 'ï¾¶' => 'á„Š', 'ï¾·' => 'á„‹', 'ï¾¸' => 'á„Œ', 'ï¾¹' => 'á„�', 'ï¾º' => 'á„Ž', 'ï¾»' => 'á„�', 'ï¾¼' => 'á„�', 'ï¾½' => 'á„‘', 'ï¾¾' => 'á„’', 'ï¿‚' => 'á…¡', 'ï¿ƒ' => 'á…¢', 'ï¿„' => 'á…£', 'ï¿…' => 'á…¤', 'ï¿†' => 'á…¥', 'ï¿‡' => 'á…¦', 'ï¿Š' => 'á…§', 'ï¿‹' => 'á…¨', 'ï¿Œ' => 'á…©', 'ï¿�' => 'á…ª', 'ï¿Ž' => 'á…«', 'ï¿�' => 'á…¬', 'ï¿’' => 'á…­', 'ï¿“' => 'á…®', 'ï¿”' => 'á…¯', 'ï¿•' => 'á…°', 'ï¿–' => 'á…±', 'ï¿—' => 'á…²', 'ï¿š' => 'á…³', 'ï¿›' => 'á…´', 'ï¿œ' => 'á…µ', 'ï¿ ' => 'Â¢', 'ï¿¡' => 'Â£', 'ï¿¢' => 'Â¬', 'ï¿£' => ' Ì„', 'ï¿¤' => 'Â¦', 'ï¿¥' => 'Â¥', 'ï¿¦' => 'â‚©', 'ï¿¨' => 'â”‚', 'ï¿©' => 'â†�', 'ï¿ª' => 'â†‘', 'ï¿«' => 'â†’', 'ï¿¬' => 'â†“', 'ï¿­' => 'â– ', 'ï¿®' => 'â—‹', 'ð��€' => 'A', 'ð���' => 'B', 'ð��‚' => 'C', 'ð��ƒ' => 'D', 'ð��„' => 'E', 'ð��…' => 'F', 'ð��†' => 'G', 'ð��‡' => 'H', 'ð��ˆ' => 'I', 'ð��‰' => 'J', 'ð��Š' => 'K', 'ð��‹' => 'L', 'ð��Œ' => 'M', 'ð���' => 'N', 'ð��Ž' => 'O', 'ð���' => 'P', 'ð���' => 'Q', 'ð��‘' => 'R', 'ð��’' => 'S', 'ð��“' => 'T', 'ð��”' => 'U', 'ð��•' => 'V', 'ð��–' => 'W', 'ð��—' => 'X', 'ð��˜' => 'Y', 'ð��™' => 'Z', 'ð��š' => 'a', 'ð��›' => 'b', 'ð��œ' => 'c', 'ð���' => 'd', 'ð��ž' => 'e', 'ð��Ÿ' => 'f', 'ð�� ' => 'g', 'ð��¡' => 'h', 'ð��¢' => 'i', 'ð��£' => 'j', 'ð��¤' => 'k', 'ð��¥' => 'l', 'ð��¦' => 'm', 'ð��§' => 'n', 'ð��¨' => 'o', 'ð��©' => 'p', 'ð��ª' => 'q', 'ð��«' => 'r', 'ð��¬' => 's', 'ð��­' => 't', 'ð��®' => 'u', 'ð��¯' => 'v', 'ð��°' => 'w', 'ð��±' => 'x', 'ð��²' => 'y', 'ð��³' => 'z', 'ð��´' => 'A', 'ð��µ' => 'B', 'ð��¶' => 'C', 'ð��·' => 'D', 'ð��¸' => 'E', 'ð��¹' => 'F', 'ð��º' => 'G', 'ð��»' => 'H', 'ð��¼' => 'I', 'ð��½' => 'J', 'ð��¾' => 'K', 'ð��¿' => 'L', 'ð�‘€' => 'M', 'ð�‘�' => 'N', 'ð�‘‚' => 'O', 'ð�‘ƒ' => 'P', 'ð�‘„' => 'Q', 'ð�‘…' => 'R', 'ð�‘†' => 'S', 'ð�‘‡' => 'T', 'ð�‘ˆ' => 'U', 'ð�‘‰' => 'V', 'ð�‘Š' => 'W', 'ð�‘‹' => 'X', 'ð�‘Œ' => 'Y', 'ð�‘�' => 'Z', 'ð�‘Ž' => 'a', 'ð�‘�' => 'b', 'ð�‘�' => 'c', 'ð�‘‘' => 'd', 'ð�‘’' => 'e', 'ð�‘“' => 'f', 'ð�‘”' => 'g', 'ð�‘–' => 'i', 'ð�‘—' => 'j', 'ð�‘˜' => 'k', 'ð�‘™' => 'l', 'ð�‘š' => 'm', 'ð�‘›' => 'n', 'ð�‘œ' => 'o', 'ð�‘�' => 'p', 'ð�‘ž' => 'q', 'ð�‘Ÿ' => 'r', 'ð�‘ ' => 's', 'ð�‘¡' => 't', 'ð�‘¢' => 'u', 'ð�‘£' => 'v', 'ð�‘¤' => 'w', 'ð�‘¥' => 'x', 'ð�‘¦' => 'y', 'ð�‘§' => 'z', 'ð�‘¨' => 'A', 'ð�‘©' => 'B', 'ð�‘ª' => 'C', 'ð�‘«' => 'D', 'ð�‘¬' => 'E', 'ð�‘­' => 'F', 'ð�‘®' => 'G', 'ð�‘¯' => 'H', 'ð�‘°' => 'I', 'ð�‘±' => 'J', 'ð�‘²' => 'K', 'ð�‘³' => 'L', 'ð�‘´' => 'M', 'ð�‘µ' => 'N', 'ð�‘¶' => 'O', 'ð�‘·' => 'P', 'ð�‘¸' => 'Q', 'ð�‘¹' => 'R', 'ð�‘º' => 'S', 'ð�‘»' => 'T', 'ð�‘¼' => 'U', 'ð�‘½' => 'V', 'ð�‘¾' => 'W', 'ð�‘¿' => 'X', 'ð�’€' => 'Y', 'ð�’�' => 'Z', 'ð�’‚' => 'a', 'ð�’ƒ' => 'b', 'ð�’„' => 'c', 'ð�’…' => 'd', 'ð�’†' => 'e', 'ð�’‡' => 'f', 'ð�’ˆ' => 'g', 'ð�’‰' => 'h', 'ð�’Š' => 'i', 'ð�’‹' => 'j', 'ð�’Œ' => 'k', 'ð�’�' => 'l', 'ð�’Ž' => 'm', 'ð�’�' => 'n', 'ð�’�' => 'o', 'ð�’‘' => 'p', 'ð�’’' => 'q', 'ð�’“' => 'r', 'ð�’”' => 's', 'ð�’•' => 't', 'ð�’–' => 'u', 'ð�’—' => 'v', 'ð�’˜' => 'w', 'ð�’™' => 'x', 'ð�’š' => 'y', 'ð�’›' => 'z', 'ð�’œ' => 'A', 'ð�’ž' => 'C', 'ð�’Ÿ' => 'D', 'ð�’¢' => 'G', 'ð�’¥' => 'J', 'ð�’¦' => 'K', 'ð�’©' => 'N', 'ð�’ª' => 'O', 'ð�’«' => 'P', 'ð�’¬' => 'Q', 'ð�’®' => 'S', 'ð�’¯' => 'T', 'ð�’°' => 'U', 'ð�’±' => 'V', 'ð�’²' => 'W', 'ð�’³' => 'X', 'ð�’´' => 'Y', 'ð�’µ' => 'Z', 'ð�’¶' => 'a', 'ð�’·' => 'b', 'ð�’¸' => 'c', 'ð�’¹' => 'd', 'ð�’»' => 'f', 'ð�’½' => 'h', 'ð�’¾' => 'i', 'ð�’¿' => 'j', 'ð�“€' => 'k', 'ð�“�' => 'l', 'ð�“‚' => 'm', 'ð�“ƒ' => 'n', 'ð�“…' => 'p', 'ð�“†' => 'q', 'ð�“‡' => 'r', 'ð�“ˆ' => 's', 'ð�“‰' => 't', 'ð�“Š' => 'u', 'ð�“‹' => 'v', 'ð�“Œ' => 'w', 'ð�“�' => 'x', 'ð�“Ž' => 'y', 'ð�“�' => 'z', 'ð�“�' => 'A', 'ð�“‘' => 'B', 'ð�“’' => 'C', 'ð�““' => 'D', 'ð�“”' => 'E', 'ð�“•' => 'F', 'ð�“–' => 'G', 'ð�“—' => 'H', 'ð�“˜' => 'I', 'ð�“™' => 'J', 'ð�“š' => 'K', 'ð�“›' => 'L', 'ð�“œ' => 'M', 'ð�“�' => 'N', 'ð�“ž' => 'O', 'ð�“Ÿ' => 'P', 'ð�“ ' => 'Q', 'ð�“¡' => 'R', 'ð�“¢' => 'S', 'ð�“£' => 'T', 'ð�“¤' => 'U', 'ð�“¥' => 'V', 'ð�“¦' => 'W', 'ð�“§' => 'X', 'ð�“¨' => 'Y', 'ð�“©' => 'Z', 'ð�“ª' => 'a', 'ð�“«' => 'b', 'ð�“¬' => 'c', 'ð�“­' => 'd', 'ð�“®' => 'e', 'ð�“¯' => 'f', 'ð�“°' => 'g', 'ð�“±' => 'h', 'ð�“²' => 'i', 'ð�“³' => 'j', 'ð�“´' => 'k', 'ð�“µ' => 'l', 'ð�“¶' => 'm', 'ð�“·' => 'n', 'ð�“¸' => 'o', 'ð�“¹' => 'p', 'ð�“º' => 'q', 'ð�“»' => 'r', 'ð�“¼' => 's', 'ð�“½' => 't', 'ð�“¾' => 'u', 'ð�“¿' => 'v', 'ð�”€' => 'w', 'ð�”�' => 'x', 'ð�”‚' => 'y', 'ð�”ƒ' => 'z', 'ð�”„' => 'A', 'ð�”…' => 'B', 'ð�”‡' => 'D', 'ð�”ˆ' => 'E', 'ð�”‰' => 'F', 'ð�”Š' => 'G', 'ð�”�' => 'J', 'ð�”Ž' => 'K', 'ð�”�' => 'L', 'ð�”�' => 'M', 'ð�”‘' => 'N', 'ð�”’' => 'O', 'ð�”“' => 'P', 'ð�””' => 'Q', 'ð�”–' => 'S', 'ð�”—' => 'T', 'ð�”˜' => 'U', 'ð�”™' => 'V', 'ð�”š' => 'W', 'ð�”›' => 'X', 'ð�”œ' => 'Y', 'ð�”ž' => 'a', 'ð�”Ÿ' => 'b', 'ð�” ' => 'c', 'ð�”¡' => 'd', 'ð�”¢' => 'e', 'ð�”£' => 'f', 'ð�”¤' => 'g', 'ð�”¥' => 'h', 'ð�”¦' => 'i', 'ð�”§' => 'j', 'ð�”¨' => 'k', 'ð�”©' => 'l', 'ð�”ª' => 'm', 'ð�”«' => 'n', 'ð�”¬' => 'o', 'ð�”­' => 'p', 'ð�”®' => 'q', 'ð�”¯' => 'r', 'ð�”°' => 's', 'ð�”±' => 't', 'ð�”²' => 'u', 'ð�”³' => 'v', 'ð�”´' => 'w', 'ð�”µ' => 'x', 'ð�”¶' => 'y', 'ð�”·' => 'z', 'ð�”¸' => 'A', 'ð�”¹' => 'B', 'ð�”»' => 'D', 'ð�”¼' => 'E', 'ð�”½' => 'F', 'ð�”¾' => 'G', 'ð�•€' => 'I', 'ð�•�' => 'J', 'ð�•‚' => 'K', 'ð�•ƒ' => 'L', 'ð�•„' => 'M', 'ð�•†' => 'O', 'ð�•Š' => 'S', 'ð�•‹' => 'T', 'ð�•Œ' => 'U', 'ð�•�' => 'V', 'ð�•Ž' => 'W', 'ð�•�' => 'X', 'ð�•�' => 'Y', 'ð�•’' => 'a', 'ð�•“' => 'b', 'ð�•”' => 'c', 'ð�••' => 'd', 'ð�•–' => 'e', 'ð�•—' => 'f', 'ð�•˜' => 'g', 'ð�•™' => 'h', 'ð�•š' => 'i', 'ð�•›' => 'j', 'ð�•œ' => 'k', 'ð�•�' => 'l', 'ð�•ž' => 'm', 'ð�•Ÿ' => 'n', 'ð�• ' => 'o', 'ð�•¡' => 'p', 'ð�•¢' => 'q', 'ð�•£' => 'r', 'ð�•¤' => 's', 'ð�•¥' => 't', 'ð�•¦' => 'u', 'ð�•§' => 'v', 'ð�•¨' => 'w', 'ð�•©' => 'x', 'ð�•ª' => 'y', 'ð�•«' => 'z', 'ð�•¬' => 'A', 'ð�•­' => 'B', 'ð�•®' => 'C', 'ð�•¯' => 'D', 'ð�•°' => 'E', 'ð�•±' => 'F', 'ð�•²' => 'G', 'ð�•³' => 'H', 'ð�•´' => 'I', 'ð�•µ' => 'J', 'ð�•¶' => 'K', 'ð�•·' => 'L', 'ð�•¸' => 'M', 'ð�•¹' => 'N', 'ð�•º' => 'O', 'ð�•»' => 'P', 'ð�•¼' => 'Q', 'ð�•½' => 'R', 'ð�•¾' => 'S', 'ð�•¿' => 'T', 'ð�–€' => 'U', 'ð�–�' => 'V', 'ð�–‚' => 'W', 'ð�–ƒ' => 'X', 'ð�–„' => 'Y', 'ð�–…' => 'Z', 'ð�–†' => 'a', 'ð�–‡' => 'b', 'ð�–ˆ' => 'c', 'ð�–‰' => 'd', 'ð�–Š' => 'e', 'ð�–‹' => 'f', 'ð�–Œ' => 'g', 'ð�–�' => 'h', 'ð�–Ž' => 'i', 'ð�–�' => 'j', 'ð�–�' => 'k', 'ð�–‘' => 'l', 'ð�–’' => 'm', 'ð�–“' => 'n', 'ð�–”' => 'o', 'ð�–•' => 'p', 'ð�––' => 'q', 'ð�–—' => 'r', 'ð�–˜' => 's', 'ð�–™' => 't', 'ð�–š' => 'u', 'ð�–›' => 'v', 'ð�–œ' => 'w', 'ð�–�' => 'x', 'ð�–ž' => 'y', 'ð�–Ÿ' => 'z', 'ð�– ' => 'A', 'ð�–¡' => 'B', 'ð�–¢' => 'C', 'ð�–£' => 'D', 'ð�–¤' => 'E', 'ð�–¥' => 'F', 'ð�–¦' => 'G', 'ð�–§' => 'H', 'ð�–¨' => 'I', 'ð�–©' => 'J', 'ð�–ª' => 'K', 'ð�–«' => 'L', 'ð�–¬' => 'M', 'ð�–­' => 'N', 'ð�–®' => 'O', 'ð�–¯' => 'P', 'ð�–°' => 'Q', 'ð�–±' => 'R', 'ð�–²' => 'S', 'ð�–³' => 'T', 'ð�–´' => 'U', 'ð�–µ' => 'V', 'ð�–¶' => 'W', 'ð�–·' => 'X', 'ð�–¸' => 'Y', 'ð�–¹' => 'Z', 'ð�–º' => 'a', 'ð�–»' => 'b', 'ð�–¼' => 'c', 'ð�–½' => 'd', 'ð�–¾' => 'e', 'ð�–¿' => 'f', 'ð�—€' => 'g', 'ð�—�' => 'h', 'ð�—‚' => 'i', 'ð�—ƒ' => 'j', 'ð�—„' => 'k', 'ð�—…' => 'l', 'ð�—†' => 'm', 'ð�—‡' => 'n', 'ð�—ˆ' => 'o', 'ð�—‰' => 'p', 'ð�—Š' => 'q', 'ð�—‹' => 'r', 'ð�—Œ' => 's', 'ð�—�' => 't', 'ð�—Ž' => 'u', 'ð�—�' => 'v', 'ð�—�' => 'w', 'ð�—‘' => 'x', 'ð�—’' => 'y', 'ð�—“' => 'z', 'ð�—”' => 'A', 'ð�—•' => 'B', 'ð�—–' => 'C', 'ð�——' => 'D', 'ð�—˜' => 'E', 'ð�—™' => 'F', 'ð�—š' => 'G', 'ð�—›' => 'H', 'ð�—œ' => 'I', 'ð�—�' => 'J', 'ð�—ž' => 'K', 'ð�—Ÿ' => 'L', 'ð�— ' => 'M', 'ð�—¡' => 'N', 'ð�—¢' => 'O', 'ð�—£' => 'P', 'ð�—¤' => 'Q', 'ð�—¥' => 'R', 'ð�—¦' => 'S', 'ð�—§' => 'T', 'ð�—¨' => 'U', 'ð�—©' => 'V', 'ð�—ª' => 'W', 'ð�—«' => 'X', 'ð�—¬' => 'Y', 'ð�—­' => 'Z', 'ð�—®' => 'a', 'ð�—¯' => 'b', 'ð�—°' => 'c', 'ð�—±' => 'd', 'ð�—²' => 'e', 'ð�—³' => 'f', 'ð�—´' => 'g', 'ð�—µ' => 'h', 'ð�—¶' => 'i', 'ð�—·' => 'j', 'ð�—¸' => 'k', 'ð�—¹' => 'l', 'ð�—º' => 'm', 'ð�—»' => 'n', 'ð�—¼' => 'o', 'ð�—½' => 'p', 'ð�—¾' => 'q', 'ð�—¿' => 'r', 'ð�˜€' => 's', 'ð�˜�' => 't', 'ð�˜‚' => 'u', 'ð�˜ƒ' => 'v', 'ð�˜„' => 'w', 'ð�˜…' => 'x', 'ð�˜†' => 'y', 'ð�˜‡' => 'z', 'ð�˜ˆ' => 'A', 'ð�˜‰' => 'B', 'ð�˜Š' => 'C', 'ð�˜‹' => 'D', 'ð�˜Œ' => 'E', 'ð�˜�' => 'F', 'ð�˜Ž' => 'G', 'ð�˜�' => 'H', 'ð�˜�' => 'I', 'ð�˜‘' => 'J', 'ð�˜’' => 'K', 'ð�˜“' => 'L', 'ð�˜”' => 'M', 'ð�˜•' => 'N', 'ð�˜–' => 'O', 'ð�˜—' => 'P', 'ð�˜˜' => 'Q', 'ð�˜™' => 'R', 'ð�˜š' => 'S', 'ð�˜›' => 'T', 'ð�˜œ' => 'U', 'ð�˜�' => 'V', 'ð�˜ž' => 'W', 'ð�˜Ÿ' => 'X', 'ð�˜ ' => 'Y', 'ð�˜¡' => 'Z', 'ð�˜¢' => 'a', 'ð�˜£' => 'b', 'ð�˜¤' => 'c', 'ð�˜¥' => 'd', 'ð�˜¦' => 'e', 'ð�˜§' => 'f', 'ð�˜¨' => 'g', 'ð�˜©' => 'h', 'ð�˜ª' => 'i', 'ð�˜«' => 'j', 'ð�˜¬' => 'k', 'ð�˜­' => 'l', 'ð�˜®' => 'm', 'ð�˜¯' => 'n', 'ð�˜°' => 'o', 'ð�˜±' => 'p', 'ð�˜²' => 'q', 'ð�˜³' => 'r', 'ð�˜´' => 's', 'ð�˜µ' => 't', 'ð�˜¶' => 'u', 'ð�˜·' => 'v', 'ð�˜¸' => 'w', 'ð�˜¹' => 'x', 'ð�˜º' => 'y', 'ð�˜»' => 'z', 'ð�˜¼' => 'A', 'ð�˜½' => 'B', 'ð�˜¾' => 'C', 'ð�˜¿' => 'D', 'ð�™€' => 'E', 'ð�™�' => 'F', 'ð�™‚' => 'G', 'ð�™ƒ' => 'H', 'ð�™„' => 'I', 'ð�™…' => 'J', 'ð�™†' => 'K', 'ð�™‡' => 'L', 'ð�™ˆ' => 'M', 'ð�™‰' => 'N', 'ð�™Š' => 'O', 'ð�™‹' => 'P', 'ð�™Œ' => 'Q', 'ð�™�' => 'R', 'ð�™Ž' => 'S', 'ð�™�' => 'T', 'ð�™�' => 'U', 'ð�™‘' => 'V', 'ð�™’' => 'W', 'ð�™“' => 'X', 'ð�™”' => 'Y', 'ð�™•' => 'Z', 'ð�™–' => 'a', 'ð�™—' => 'b', 'ð�™˜' => 'c', 'ð�™™' => 'd', 'ð�™š' => 'e', 'ð�™›' => 'f', 'ð�™œ' => 'g', 'ð�™�' => 'h', 'ð�™ž' => 'i', 'ð�™Ÿ' => 'j', 'ð�™ ' => 'k', 'ð�™¡' => 'l', 'ð�™¢' => 'm', 'ð�™£' => 'n', 'ð�™¤' => 'o', 'ð�™¥' => 'p', 'ð�™¦' => 'q', 'ð�™§' => 'r', 'ð�™¨' => 's', 'ð�™©' => 't', 'ð�™ª' => 'u', 'ð�™«' => 'v', 'ð�™¬' => 'w', 'ð�™­' => 'x', 'ð�™®' => 'y', 'ð�™¯' => 'z', 'ð�™°' => 'A', 'ð�™±' => 'B', 'ð�™²' => 'C', 'ð�™³' => 'D', 'ð�™´' => 'E', 'ð�™µ' => 'F', 'ð�™¶' => 'G', 'ð�™·' => 'H', 'ð�™¸' => 'I', 'ð�™¹' => 'J', 'ð�™º' => 'K', 'ð�™»' => 'L', 'ð�™¼' => 'M', 'ð�™½' => 'N', 'ð�™¾' => 'O', 'ð�™¿' => 'P', 'ð�š€' => 'Q', 'ð�š�' => 'R', 'ð�š‚' => 'S', 'ð�šƒ' => 'T', 'ð�š„' => 'U', 'ð�š…' => 'V', 'ð�š†' => 'W', 'ð�š‡' => 'X', 'ð�šˆ' => 'Y', 'ð�š‰' => 'Z', 'ð�šŠ' => 'a', 'ð�š‹' => 'b', 'ð�šŒ' => 'c', 'ð�š�' => 'd', 'ð�šŽ' => 'e', 'ð�š�' => 'f', 'ð�š�' => 'g', 'ð�š‘' => 'h', 'ð�š’' => 'i', 'ð�š“' => 'j', 'ð�š”' => 'k', 'ð�š•' => 'l', 'ð�š–' => 'm', 'ð�š—' => 'n', 'ð�š˜' => 'o', 'ð�š™' => 'p', 'ð�šš' => 'q', 'ð�š›' => 'r', 'ð�šœ' => 's', 'ð�š�' => 't', 'ð�šž' => 'u', 'ð�šŸ' => 'v', 'ð�š ' => 'w', 'ð�š¡' => 'x', 'ð�š¢' => 'y', 'ð�š£' => 'z', 'ð�š¤' => 'Ä±', 'ð�š¥' => 'È·', 'ð�š¨' => 'Î‘', 'ð�š©' => 'Î’', 'ð�šª' => 'Î“', 'ð�š«' => 'Î”', 'ð�š¬' => 'Î•', 'ð�š­' => 'Î–', 'ð�š®' => 'Î—', 'ð�š¯' => 'Î˜', 'ð�š°' => 'Î™', 'ð�š±' => 'Îš', 'ð�š²' => 'Î›', 'ð�š³' => 'Îœ', 'ð�š´' => 'Î�', 'ð�šµ' => 'Îž', 'ð�š¶' => 'ÎŸ', 'ð�š·' => 'Î ', 'ð�š¸' => 'Î¡', 'ð�š¹' => 'Î˜', 'ð�šº' => 'Î£', 'ð�š»' => 'Î¤', 'ð�š¼' => 'Î¥', 'ð�š½' => 'Î¦', 'ð�š¾' => 'Î§', 'ð�š¿' => 'Î¨', 'ð�›€' => 'Î©', 'ð�›�' => 'âˆ‡', 'ð�›‚' => 'Î±', 'ð�›ƒ' => 'Î²', 'ð�›„' => 'Î³', 'ð�›…' => 'Î´', 'ð�›†' => 'Îµ', 'ð�›‡' => 'Î¶', 'ð�›ˆ' => 'Î·', 'ð�›‰' => 'Î¸', 'ð�›Š' => 'Î¹', 'ð�›‹' => 'Îº', 'ð�›Œ' => 'Î»', 'ð�›�' => 'Î¼', 'ð�›Ž' => 'Î½', 'ð�›�' => 'Î¾', 'ð�›�' => 'Î¿', 'ð�›‘' => 'Ï€', 'ð�›’' => 'Ï�', 'ð�›“' => 'Ï‚', 'ð�›”' => 'Ïƒ', 'ð�›•' => 'Ï„', 'ð�›–' => 'Ï…', 'ð�›—' => 'Ï†', 'ð�›˜' => 'Ï‡', 'ð�›™' => 'Ïˆ', 'ð�›š' => 'Ï‰', 'ð�››' => 'âˆ‚', 'ð�›œ' => 'Îµ', 'ð�›�' => 'Î¸', 'ð�›ž' => 'Îº', 'ð�›Ÿ' => 'Ï†', 'ð�› ' => 'Ï�', 'ð�›¡' => 'Ï€', 'ð�›¢' => 'Î‘', 'ð�›£' => 'Î’', 'ð�›¤' => 'Î“', 'ð�›¥' => 'Î”', 'ð�›¦' => 'Î•', 'ð�›§' => 'Î–', 'ð�›¨' => 'Î—', 'ð�›©' => 'Î˜', 'ð�›ª' => 'Î™', 'ð�›«' => 'Îš', 'ð�›¬' => 'Î›', 'ð�›­' => 'Îœ', 'ð�›®' => 'Î�', 'ð�›¯' => 'Îž', 'ð�›°' => 'ÎŸ', 'ð�›±' => 'Î ', 'ð�›²' => 'Î¡', 'ð�›³' => 'Î˜', 'ð�›´' => 'Î£', 'ð�›µ' => 'Î¤', 'ð�›¶' => 'Î¥', 'ð�›·' => 'Î¦', 'ð�›¸' => 'Î§', 'ð�›¹' => 'Î¨', 'ð�›º' => 'Î©', 'ð�›»' => 'âˆ‡', 'ð�›¼' => 'Î±', 'ð�›½' => 'Î²', 'ð�›¾' => 'Î³', 'ð�›¿' => 'Î´', 'ð�œ€' => 'Îµ', 'ð�œ�' => 'Î¶', 'ð�œ‚' => 'Î·', 'ð�œƒ' => 'Î¸', 'ð�œ„' => 'Î¹', 'ð�œ…' => 'Îº', 'ð�œ†' => 'Î»', 'ð�œ‡' => 'Î¼', 'ð�œˆ' => 'Î½', 'ð�œ‰' => 'Î¾', 'ð�œŠ' => 'Î¿', 'ð�œ‹' => 'Ï€', 'ð�œŒ' => 'Ï�', 'ð�œ�' => 'Ï‚', 'ð�œŽ' => 'Ïƒ', 'ð�œ�' => 'Ï„', 'ð�œ�' => 'Ï…', 'ð�œ‘' => 'Ï†', 'ð�œ’' => 'Ï‡', 'ð�œ“' => 'Ïˆ', 'ð�œ”' => 'Ï‰', 'ð�œ•' => 'âˆ‚', 'ð�œ–' => 'Îµ', 'ð�œ—' => 'Î¸', 'ð�œ˜' => 'Îº', 'ð�œ™' => 'Ï†', 'ð�œš' => 'Ï�', 'ð�œ›' => 'Ï€', 'ð�œœ' => 'Î‘', 'ð�œ�' => 'Î’', 'ð�œž' => 'Î“', 'ð�œŸ' => 'Î”', 'ð�œ ' => 'Î•', 'ð�œ¡' => 'Î–', 'ð�œ¢' => 'Î—', 'ð�œ£' => 'Î˜', 'ð�œ¤' => 'Î™', 'ð�œ¥' => 'Îš', 'ð�œ¦' => 'Î›', 'ð�œ§' => 'Îœ', 'ð�œ¨' => 'Î�', 'ð�œ©' => 'Îž', 'ð�œª' => 'ÎŸ', 'ð�œ«' => 'Î ', 'ð�œ¬' => 'Î¡', 'ð�œ­' => 'Î˜', 'ð�œ®' => 'Î£', 'ð�œ¯' => 'Î¤', 'ð�œ°' => 'Î¥', 'ð�œ±' => 'Î¦', 'ð�œ²' => 'Î§', 'ð�œ³' => 'Î¨', 'ð�œ´' => 'Î©', 'ð�œµ' => 'âˆ‡', 'ð�œ¶' => 'Î±', 'ð�œ·' => 'Î²', 'ð�œ¸' => 'Î³', 'ð�œ¹' => 'Î´', 'ð�œº' => 'Îµ', 'ð�œ»' => 'Î¶', 'ð�œ¼' => 'Î·', 'ð�œ½' => 'Î¸', 'ð�œ¾' => 'Î¹', 'ð�œ¿' => 'Îº', 'ð��€' => 'Î»', 'ð���' => 'Î¼', 'ð��‚' => 'Î½', 'ð��ƒ' => 'Î¾', 'ð��„' => 'Î¿', 'ð��…' => 'Ï€', 'ð��†' => 'Ï�', 'ð��‡' => 'Ï‚', 'ð��ˆ' => 'Ïƒ', 'ð��‰' => 'Ï„', 'ð��Š' => 'Ï…', 'ð��‹' => 'Ï†', 'ð��Œ' => 'Ï‡', 'ð���' => 'Ïˆ', 'ð��Ž' => 'Ï‰', 'ð���' => 'âˆ‚', 'ð���' => 'Îµ', 'ð��‘' => 'Î¸', 'ð��’' => 'Îº', 'ð��“' => 'Ï†', 'ð��”' => 'Ï�', 'ð��•' => 'Ï€', 'ð��–' => 'Î‘', 'ð��—' => 'Î’', 'ð��˜' => 'Î“', 'ð��™' => 'Î”', 'ð��š' => 'Î•', 'ð��›' => 'Î–', 'ð��œ' => 'Î—', 'ð���' => 'Î˜', 'ð��ž' => 'Î™', 'ð��Ÿ' => 'Îš', 'ð�� ' => 'Î›', 'ð��¡' => 'Îœ', 'ð��¢' => 'Î�', 'ð��£' => 'Îž', 'ð��¤' => 'ÎŸ', 'ð��¥' => 'Î ', 'ð��¦' => 'Î¡', 'ð��§' => 'Î˜', 'ð��¨' => 'Î£', 'ð��©' => 'Î¤', 'ð��ª' => 'Î¥', 'ð��«' => 'Î¦', 'ð��¬' => 'Î§', 'ð��­' => 'Î¨', 'ð��®' => 'Î©', 'ð��¯' => 'âˆ‡', 'ð��°' => 'Î±', 'ð��±' => 'Î²', 'ð��²' => 'Î³', 'ð��³' => 'Î´', 'ð��´' => 'Îµ', 'ð��µ' => 'Î¶', 'ð��¶' => 'Î·', 'ð��·' => 'Î¸', 'ð��¸' => 'Î¹', 'ð��¹' => 'Îº', 'ð��º' => 'Î»', 'ð��»' => 'Î¼', 'ð��¼' => 'Î½', 'ð��½' => 'Î¾', 'ð��¾' => 'Î¿', 'ð��¿' => 'Ï€', 'ð�ž€' => 'Ï�', 'ð�ž�' => 'Ï‚', 'ð�ž‚' => 'Ïƒ', 'ð�žƒ' => 'Ï„', 'ð�ž„' => 'Ï…', 'ð�ž…' => 'Ï†', 'ð�ž†' => 'Ï‡', 'ð�ž‡' => 'Ïˆ', 'ð�žˆ' => 'Ï‰', 'ð�ž‰' => 'âˆ‚', 'ð�žŠ' => 'Îµ', 'ð�ž‹' => 'Î¸', 'ð�žŒ' => 'Îº', 'ð�ž�' => 'Ï†', 'ð�žŽ' => 'Ï�', 'ð�ž�' => 'Ï€', 'ð�ž�' => 'Î‘', 'ð�ž‘' => 'Î’', 'ð�ž’' => 'Î“', 'ð�ž“' => 'Î”', 'ð�ž”' => 'Î•', 'ð�ž•' => 'Î–', 'ð�ž–' => 'Î—', 'ð�ž—' => 'Î˜', 'ð�ž˜' => 'Î™', 'ð�ž™' => 'Îš', 'ð�žš' => 'Î›', 'ð�ž›' => 'Îœ', 'ð�žœ' => 'Î�', 'ð�ž�' => 'Îž', 'ð�žž' => 'ÎŸ', 'ð�žŸ' => 'Î ', 'ð�ž ' => 'Î¡', 'ð�ž¡' => 'Î˜', 'ð�ž¢' => 'Î£', 'ð�ž£' => 'Î¤', 'ð�ž¤' => 'Î¥', 'ð�ž¥' => 'Î¦', 'ð�ž¦' => 'Î§', 'ð�ž§' => 'Î¨', 'ð�ž¨' => 'Î©', 'ð�ž©' => 'âˆ‡', 'ð�žª' => 'Î±', 'ð�ž«' => 'Î²', 'ð�ž¬' => 'Î³', 'ð�ž­' => 'Î´', 'ð�ž®' => 'Îµ', 'ð�ž¯' => 'Î¶', 'ð�ž°' => 'Î·', 'ð�ž±' => 'Î¸', 'ð�ž²' => 'Î¹', 'ð�ž³' => 'Îº', 'ð�ž´' => 'Î»', 'ð�žµ' => 'Î¼', 'ð�ž¶' => 'Î½', 'ð�ž·' => 'Î¾', 'ð�ž¸' => 'Î¿', 'ð�ž¹' => 'Ï€', 'ð�žº' => 'Ï�', 'ð�ž»' => 'Ï‚', 'ð�ž¼' => 'Ïƒ', 'ð�ž½' => 'Ï„', 'ð�ž¾' => 'Ï…', 'ð�ž¿' => 'Ï†', 'ð�Ÿ€' => 'Ï‡', 'ð�Ÿ�' => 'Ïˆ', 'ð�Ÿ‚' => 'Ï‰', 'ð�Ÿƒ' => 'âˆ‚', 'ð�Ÿ„' => 'Îµ', 'ð�Ÿ…' => 'Î¸', 'ð�Ÿ†' => 'Îº', 'ð�Ÿ‡' => 'Ï†', 'ð�Ÿˆ' => 'Ï�', 'ð�Ÿ‰' => 'Ï€', 'ð�ŸŠ' => 'Ïœ', 'ð�Ÿ‹' => 'Ï�', 'ð�ŸŽ' => '0', 'ð�Ÿ�' => '1', 'ð�Ÿ�' => '2', 'ð�Ÿ‘' => '3', 'ð�Ÿ’' => '4', 'ð�Ÿ“' => '5', 'ð�Ÿ”' => '6', 'ð�Ÿ•' => '7', 'ð�Ÿ–' => '8', 'ð�Ÿ—' => '9', 'ð�Ÿ˜' => '0', 'ð�Ÿ™' => '1', 'ð�Ÿš' => '2', 'ð�Ÿ›' => '3', 'ð�Ÿœ' => '4', 'ð�Ÿ�' => '5', 'ð�Ÿž' => '6', 'ð�ŸŸ' => '7', 'ð�Ÿ ' => '8', 'ð�Ÿ¡' => '9', 'ð�Ÿ¢' => '0', 'ð�Ÿ£' => '1', 'ð�Ÿ¤' => '2', 'ð�Ÿ¥' => '3', 'ð�Ÿ¦' => '4', 'ð�Ÿ§' => '5', 'ð�Ÿ¨' => '6', 'ð�Ÿ©' => '7', 'ð�Ÿª' => '8', 'ð�Ÿ«' => '9', 'ð�Ÿ¬' => '0', 'ð�Ÿ­' => '1', 'ð�Ÿ®' => '2', 'ð�Ÿ¯' => '3', 'ð�Ÿ°' => '4', 'ð�Ÿ±' => '5', 'ð�Ÿ²' => '6', 'ð�Ÿ³' => '7', 'ð�Ÿ´' => '8', 'ð�Ÿµ' => '9', 'ð�Ÿ¶' => '0', 'ð�Ÿ·' => '1', 'ð�Ÿ¸' => '2', 'ð�Ÿ¹' => '3', 'ð�Ÿº' => '4', 'ð�Ÿ»' => '5', 'ð�Ÿ¼' => '6', 'ð�Ÿ½' => '7', 'ð�Ÿ¾' => '8', 'ð�Ÿ¿' => '9', 'ðž¸€' => 'Ø§', 'ðž¸�' => 'Ø¨', 'ðž¸‚' => 'Ø¬', 'ðž¸ƒ' => 'Ø¯', 'ðž¸…' => 'Ùˆ', 'ðž¸†' => 'Ø²', 'ðž¸‡' => 'Ø­', 'ðž¸ˆ' => 'Ø·', 'ðž¸‰' => 'ÙŠ', 'ðž¸Š' => 'Ùƒ', 'ðž¸‹' => 'Ù„', 'ðž¸Œ' => 'Ù…', 'ðž¸�' => 'Ù†', 'ðž¸Ž' => 'Ø³', 'ðž¸�' => 'Ø¹', 'ðž¸�' => 'Ù�', 'ðž¸‘' => 'Øµ', 'ðž¸’' => 'Ù‚', 'ðž¸“' => 'Ø±', 'ðž¸”' => 'Ø´', 'ðž¸•' => 'Øª', 'ðž¸–' => 'Ø«', 'ðž¸—' => 'Ø®', 'ðž¸˜' => 'Ø°', 'ðž¸™' => 'Ø¶', 'ðž¸š' => 'Ø¸', 'ðž¸›' => 'Øº', 'ðž¸œ' => 'Ù®', 'ðž¸�' => 'Úº', 'ðž¸ž' => 'Ú¡', 'ðž¸Ÿ' => 'Ù¯', 'ðž¸¡' => 'Ø¨', 'ðž¸¢' => 'Ø¬', 'ðž¸¤' => 'Ù‡', 'ðž¸§' => 'Ø­', 'ðž¸©' => 'ÙŠ', 'ðž¸ª' => 'Ùƒ', 'ðž¸«' => 'Ù„', 'ðž¸¬' => 'Ù…', 'ðž¸­' => 'Ù†', 'ðž¸®' => 'Ø³', 'ðž¸¯' => 'Ø¹', 'ðž¸°' => 'Ù�', 'ðž¸±' => 'Øµ', 'ðž¸²' => 'Ù‚', 'ðž¸´' => 'Ø´', 'ðž¸µ' => 'Øª', 'ðž¸¶' => 'Ø«', 'ðž¸·' => 'Ø®', 'ðž¸¹' => 'Ø¶', 'ðž¸»' => 'Øº', 'ðž¹‚' => 'Ø¬', 'ðž¹‡' => 'Ø­', 'ðž¹‰' => 'ÙŠ', 'ðž¹‹' => 'Ù„', 'ðž¹�' => 'Ù†', 'ðž¹Ž' => 'Ø³', 'ðž¹�' => 'Ø¹', 'ðž¹‘' => 'Øµ', 'ðž¹’' => 'Ù‚', 'ðž¹”' => 'Ø´', 'ðž¹—' => 'Ø®', 'ðž¹™' => 'Ø¶', 'ðž¹›' => 'Øº', 'ðž¹�' => 'Úº', 'ðž¹Ÿ' => 'Ù¯', 'ðž¹¡' => 'Ø¨', 'ðž¹¢' => 'Ø¬', 'ðž¹¤' => 'Ù‡', 'ðž¹§' => 'Ø­', 'ðž¹¨' => 'Ø·', 'ðž¹©' => 'ÙŠ', 'ðž¹ª' => 'Ùƒ', 'ðž¹¬' => 'Ù…', 'ðž¹­' => 'Ù†', 'ðž¹®' => 'Ø³', 'ðž¹¯' => 'Ø¹', 'ðž¹°' => 'Ù�', 'ðž¹±' => 'Øµ', 'ðž¹²' => 'Ù‚', 'ðž¹´' => 'Ø´', 'ðž¹µ' => 'Øª', 'ðž¹¶' => 'Ø«', 'ðž¹·' => 'Ø®', 'ðž¹¹' => 'Ø¶', 'ðž¹º' => 'Ø¸', 'ðž¹»' => 'Øº', 'ðž¹¼' => 'Ù®', 'ðž¹¾' => 'Ú¡', 'ðžº€' => 'Ø§', 'ðžº�' => 'Ø¨', 'ðžº‚' => 'Ø¬', 'ðžºƒ' => 'Ø¯', 'ðžº„' => 'Ù‡', 'ðžº…' => 'Ùˆ', 'ðžº†' => 'Ø²', 'ðžº‡' => 'Ø­', 'ðžºˆ' => 'Ø·', 'ðžº‰' => 'ÙŠ', 'ðžº‹' => 'Ù„', 'ðžºŒ' => 'Ù…', 'ðžº�' => 'Ù†', 'ðžºŽ' => 'Ø³', 'ðžº�' => 'Ø¹', 'ðžº�' => 'Ù�', 'ðžº‘' => 'Øµ', 'ðžº’' => 'Ù‚', 'ðžº“' => 'Ø±', 'ðžº”' => 'Ø´', 'ðžº•' => 'Øª', 'ðžº–' => 'Ø«', 'ðžº—' => 'Ø®', 'ðžº˜' => 'Ø°', 'ðžº™' => 'Ø¶', 'ðžºš' => 'Ø¸', 'ðžº›' => 'Øº', 'ðžº¡' => 'Ø¨', 'ðžº¢' => 'Ø¬', 'ðžº£' => 'Ø¯', 'ðžº¥' => 'Ùˆ', 'ðžº¦' => 'Ø²', 'ðžº§' => 'Ø­', 'ðžº¨' => 'Ø·', 'ðžº©' => 'ÙŠ', 'ðžº«' => 'Ù„', 'ðžº¬' => 'Ù…', 'ðžº­' => 'Ù†', 'ðžº®' => 'Ø³', 'ðžº¯' => 'Ø¹', 'ðžº°' => 'Ù�', 'ðžº±' => 'Øµ', 'ðžº²' => 'Ù‚', 'ðžº³' => 'Ø±', 'ðžº´' => 'Ø´', 'ðžºµ' => 'Øª', 'ðžº¶' => 'Ø«', 'ðžº·' => 'Ø®', 'ðžº¸' => 'Ø°', 'ðžº¹' => 'Ø¶', 'ðžºº' => 'Ø¸', 'ðžº»' => 'Øº', 'ðŸ„€' => '0.', 'ðŸ„�' => '0,', 'ðŸ„‚' => '1,', 'ðŸ„ƒ' => '2,', 'ðŸ„„' => '3,', 'ðŸ„…' => '4,', 'ðŸ„†' => '5,', 'ðŸ„‡' => '6,', 'ðŸ„ˆ' => '7,', 'ðŸ„‰' => '8,', 'ðŸ„Š' => '9,', 'ðŸ„�' => '(A)', 'ðŸ„‘' => '(B)', 'ðŸ„’' => '(C)', 'ðŸ„“' => '(D)', 'ðŸ„”' => '(E)', 'ðŸ„•' => '(F)', 'ðŸ„–' => '(G)', 'ðŸ„—' => '(H)', 'ðŸ„˜' => '(I)', 'ðŸ„™' => '(J)', 'ðŸ„š' => '(K)', 'ðŸ„›' => '(L)', 'ðŸ„œ' => '(M)', 'ðŸ„�' => '(N)', 'ðŸ„ž' => '(O)', 'ðŸ„Ÿ' => '(P)', 'ðŸ„ ' => '(Q)', 'ðŸ„¡' => '(R)', 'ðŸ„¢' => '(S)', 'ðŸ„£' => '(T)', 'ðŸ„¤' => '(U)', 'ðŸ„¥' => '(V)', 'ðŸ„¦' => '(W)', 'ðŸ„§' => '(X)', 'ðŸ„¨' => '(Y)', 'ðŸ„©' => '(Z)', 'ðŸ„ª' => 'ã€”Sã€•', 'ðŸ„«' => 'C', 'ðŸ„¬' => 'R', 'ðŸ„­' => 'CD', 'ðŸ„®' => 'WZ', 'ðŸ„°' => 'A', 'ðŸ„±' => 'B', 'ðŸ„²' => 'C', 'ðŸ„³' => 'D', 'ðŸ„´' => 'E', 'ðŸ„µ' => 'F', 'ðŸ„¶' => 'G', 'ðŸ„·' => 'H', 'ðŸ„¸' => 'I', 'ðŸ„¹' => 'J', 'ðŸ„º' => 'K', 'ðŸ„»' => 'L', 'ðŸ„¼' => 'M', 'ðŸ„½' => 'N', 'ðŸ„¾' => 'O', 'ðŸ„¿' => 'P', 'ðŸ…€' => 'Q', 'ðŸ…�' => 'R', 'ðŸ…‚' => 'S', 'ðŸ…ƒ' => 'T', 'ðŸ…„' => 'U', 'ðŸ……' => 'V', 'ðŸ…†' => 'W', 'ðŸ…‡' => 'X', 'ðŸ…ˆ' => 'Y', 'ðŸ…‰' => 'Z', 'ðŸ…Š' => 'HV', 'ðŸ…‹' => 'MV', 'ðŸ…Œ' => 'SD', 'ðŸ…�' => 'SS', 'ðŸ…Ž' => 'PPV', 'ðŸ…�' => 'WC', 'ðŸ…ª' => 'MC', 'ðŸ…«' => 'MD', 'ðŸ…¬' => 'MR', 'ðŸ†�' => 'DJ', 'ðŸˆ€' => 'ã�»ã�‹', 'ðŸˆ�' => 'ã‚³ã‚³', 'ðŸˆ‚' => 'ã‚µ', 'ðŸˆ�' => 'æ‰‹', 'ðŸˆ‘' => 'å­—', 'ðŸˆ’' => 'å�Œ', 'ðŸˆ“' => 'ãƒ†ã‚™', 'ðŸˆ”' => 'äºŒ', 'ðŸˆ•' => 'å¤š', 'ðŸˆ–' => 'è§£', 'ðŸˆ—' => 'å¤©', 'ðŸˆ˜' => 'äº¤', 'ðŸˆ™' => 'æ˜ ', 'ðŸˆš' => 'ç„¡', 'ðŸˆ›' => 'æ–™', 'ðŸˆœ' => 'å‰�', 'ðŸˆ�' => 'å¾Œ', 'ðŸˆž' => 'å†�', 'ðŸˆŸ' => 'æ–°', 'ðŸˆ ' => 'åˆ�', 'ðŸˆ¡' => 'çµ‚', 'ðŸˆ¢' => 'ç”Ÿ', 'ðŸˆ£' => 'è²©', 'ðŸˆ¤' => 'å£°', 'ðŸˆ¥' => 'å�¹', 'ðŸˆ¦' => 'æ¼”', 'ðŸˆ§' => 'æŠ•', 'ðŸˆ¨' => 'æ�•', 'ðŸˆ©' => 'ä¸€', 'ðŸˆª' => 'ä¸‰', 'ðŸˆ«' => 'é�Š', 'ðŸˆ¬' => 'å·¦', 'ðŸˆ­' => 'ä¸­', 'ðŸˆ®' => 'å�³', 'ðŸˆ¯' => 'æŒ‡', 'ðŸˆ°' => 'èµ°', 'ðŸˆ±' => 'æ‰“', 'ðŸˆ²' => 'ç¦�', 'ðŸˆ³' => 'ç©º', 'ðŸˆ´' => 'å�ˆ', 'ðŸˆµ' => 'æº€', 'ðŸˆ¶' => 'æœ‰', 'ðŸˆ·' => 'æœˆ', 'ðŸˆ¸' => 'ç”³', 'ðŸˆ¹' => 'å‰²', 'ðŸˆº' => 'å–¶', 'ðŸˆ»' => 'é…�', 'ðŸ‰€' => 'ã€”æœ¬ã€•', 'ðŸ‰�' => 'ã€”ä¸‰ã€•', 'ðŸ‰‚' => 'ã€”äºŒã€•', 'ðŸ‰ƒ' => 'ã€”å®‰ã€•', 'ðŸ‰„' => 'ã€”ç‚¹ã€•', 'ðŸ‰…' => 'ã€”æ‰“ã€•', 'ðŸ‰†' => 'ã€”ç›—ã€•', 'ðŸ‰‡' => 'ã€”å‹�ã€•', 'ðŸ‰ˆ' => 'ã€”æ•—ã€•', 'ðŸ‰�' => 'å¾—', 'ðŸ‰‘' => 'å�¯', 'ðŸ¯°' => '0', 'ðŸ¯±' => '1', 'ðŸ¯²' => '2', 'ðŸ¯³' => '3', 'ðŸ¯´' => '4', 'ðŸ¯µ' => '5', 'ðŸ¯¶' => '6', 'ðŸ¯·' => '7', 'ðŸ¯¸' => '8', 'ðŸ¯¹' => '9');<?php

return array('AÌ€' => 'Ã€', 'AÌ�' => 'Ã�', 'AÌ‚' => 'Ã‚', 'AÌƒ' => 'Ãƒ', 'AÌˆ' => 'Ã„', 'AÌŠ' => 'Ã…', 'CÌ§' => 'Ã‡', 'EÌ€' => 'Ãˆ', 'EÌ�' => 'Ã‰', 'EÌ‚' => 'ÃŠ', 'EÌˆ' => 'Ã‹', 'IÌ€' => 'ÃŒ', 'IÌ�' => 'Ã�', 'IÌ‚' => 'ÃŽ', 'IÌˆ' => 'Ã�', 'NÌƒ' => 'Ã‘', 'OÌ€' => 'Ã’', 'OÌ�' => 'Ã“', 'OÌ‚' => 'Ã”', 'OÌƒ' => 'Ã•', 'OÌˆ' => 'Ã–', 'UÌ€' => 'Ã™', 'UÌ�' => 'Ãš', 'UÌ‚' => 'Ã›', 'UÌˆ' => 'Ãœ', 'YÌ�' => 'Ã�', 'aÌ€' => 'Ã ', 'aÌ�' => 'Ã¡', 'aÌ‚' => 'Ã¢', 'aÌƒ' => 'Ã£', 'aÌˆ' => 'Ã¤', 'aÌŠ' => 'Ã¥', 'cÌ§' => 'Ã§', 'eÌ€' => 'Ã¨', 'eÌ�' => 'Ã©', 'eÌ‚' => 'Ãª', 'eÌˆ' => 'Ã«', 'iÌ€' => 'Ã¬', 'iÌ�' => 'Ã­', 'iÌ‚' => 'Ã®', 'iÌˆ' => 'Ã¯', 'nÌƒ' => 'Ã±', 'oÌ€' => 'Ã²', 'oÌ�' => 'Ã³', 'oÌ‚' => 'Ã´', 'oÌƒ' => 'Ãµ', 'oÌˆ' => 'Ã¶', 'uÌ€' => 'Ã¹', 'uÌ�' => 'Ãº', 'uÌ‚' => 'Ã»', 'uÌˆ' => 'Ã¼', 'yÌ�' => 'Ã½', 'yÌˆ' => 'Ã¿', 'AÌ„' => 'Ä€', 'aÌ„' => 'Ä�', 'AÌ†' => 'Ä‚', 'aÌ†' => 'Äƒ', 'AÌ¨' => 'Ä„', 'aÌ¨' => 'Ä…', 'CÌ�' => 'Ä†', 'cÌ�' => 'Ä‡', 'CÌ‚' => 'Äˆ', 'cÌ‚' => 'Ä‰', 'CÌ‡' => 'ÄŠ', 'cÌ‡' => 'Ä‹', 'CÌŒ' => 'ÄŒ', 'cÌŒ' => 'Ä�', 'DÌŒ' => 'ÄŽ', 'dÌŒ' => 'Ä�', 'EÌ„' => 'Ä’', 'eÌ„' => 'Ä“', 'EÌ†' => 'Ä”', 'eÌ†' => 'Ä•', 'EÌ‡' => 'Ä–', 'eÌ‡' => 'Ä—', 'EÌ¨' => 'Ä˜', 'eÌ¨' => 'Ä™', 'EÌŒ' => 'Äš', 'eÌŒ' => 'Ä›', 'GÌ‚' => 'Äœ', 'gÌ‚' => 'Ä�', 'GÌ†' => 'Äž', 'gÌ†' => 'ÄŸ', 'GÌ‡' => 'Ä ', 'gÌ‡' => 'Ä¡', 'GÌ§' => 'Ä¢', 'gÌ§' => 'Ä£', 'HÌ‚' => 'Ä¤', 'hÌ‚' => 'Ä¥', 'IÌƒ' => 'Ä¨', 'iÌƒ' => 'Ä©', 'IÌ„' => 'Äª', 'iÌ„' => 'Ä«', 'IÌ†' => 'Ä¬', 'iÌ†' => 'Ä­', 'IÌ¨' => 'Ä®', 'iÌ¨' => 'Ä¯', 'IÌ‡' => 'Ä°', 'JÌ‚' => 'Ä´', 'jÌ‚' => 'Äµ', 'KÌ§' => 'Ä¶', 'kÌ§' => 'Ä·', 'LÌ�' => 'Ä¹', 'lÌ�' => 'Äº', 'LÌ§' => 'Ä»', 'lÌ§' => 'Ä¼', 'LÌŒ' => 'Ä½', 'lÌŒ' => 'Ä¾', 'NÌ�' => 'Åƒ', 'nÌ�' => 'Å„', 'NÌ§' => 'Å…', 'nÌ§' => 'Å†', 'NÌŒ' => 'Å‡', 'nÌŒ' => 'Åˆ', 'OÌ„' => 'ÅŒ', 'oÌ„' => 'Å�', 'OÌ†' => 'ÅŽ', 'oÌ†' => 'Å�', 'OÌ‹' => 'Å�', 'oÌ‹' => 'Å‘', 'RÌ�' => 'Å”', 'rÌ�' => 'Å•', 'RÌ§' => 'Å–', 'rÌ§' => 'Å—', 'RÌŒ' => 'Å˜', 'rÌŒ' => 'Å™', 'SÌ�' => 'Åš', 'sÌ�' => 'Å›', 'SÌ‚' => 'Åœ', 'sÌ‚' => 'Å�', 'SÌ§' => 'Åž', 'sÌ§' => 'ÅŸ', 'SÌŒ' => 'Å ', 'sÌŒ' => 'Å¡', 'TÌ§' => 'Å¢', 'tÌ§' => 'Å£', 'TÌŒ' => 'Å¤', 'tÌŒ' => 'Å¥', 'UÌƒ' => 'Å¨', 'uÌƒ' => 'Å©', 'UÌ„' => 'Åª', 'uÌ„' => 'Å«', 'UÌ†' => 'Å¬', 'uÌ†' => 'Å­', 'UÌŠ' => 'Å®', 'uÌŠ' => 'Å¯', 'UÌ‹' => 'Å°', 'uÌ‹' => 'Å±', 'UÌ¨' => 'Å²', 'uÌ¨' => 'Å³', 'WÌ‚' => 'Å´', 'wÌ‚' => 'Åµ', 'YÌ‚' => 'Å¶', 'yÌ‚' => 'Å·', 'YÌˆ' => 'Å¸', 'ZÌ�' => 'Å¹', 'zÌ�' => 'Åº', 'ZÌ‡' => 'Å»', 'zÌ‡' => 'Å¼', 'ZÌŒ' => 'Å½', 'zÌŒ' => 'Å¾', 'OÌ›' => 'Æ ', 'oÌ›' => 'Æ¡', 'UÌ›' => 'Æ¯', 'uÌ›' => 'Æ°', 'AÌŒ' => 'Ç�', 'aÌŒ' => 'ÇŽ', 'IÌŒ' => 'Ç�', 'iÌŒ' => 'Ç�', 'OÌŒ' => 'Ç‘', 'oÌŒ' => 'Ç’', 'UÌŒ' => 'Ç“', 'uÌŒ' => 'Ç”', 'ÃœÌ„' => 'Ç•', 'Ã¼Ì„' => 'Ç–', 'ÃœÌ�' => 'Ç—', 'Ã¼Ì�' => 'Ç˜', 'ÃœÌŒ' => 'Ç™', 'Ã¼ÌŒ' => 'Çš', 'ÃœÌ€' => 'Ç›', 'Ã¼Ì€' => 'Çœ', 'Ã„Ì„' => 'Çž', 'Ã¤Ì„' => 'ÇŸ', 'È¦Ì„' => 'Ç ', 'È§Ì„' => 'Ç¡', 'Ã†Ì„' => 'Ç¢', 'Ã¦Ì„' => 'Ç£', 'GÌŒ' => 'Ç¦', 'gÌŒ' => 'Ç§', 'KÌŒ' => 'Ç¨', 'kÌŒ' => 'Ç©', 'OÌ¨' => 'Çª', 'oÌ¨' => 'Ç«', 'ÇªÌ„' => 'Ç¬', 'Ç«Ì„' => 'Ç­', 'Æ·ÌŒ' => 'Ç®', 'Ê’ÌŒ' => 'Ç¯', 'jÌŒ' => 'Ç°', 'GÌ�' => 'Ç´', 'gÌ�' => 'Çµ', 'NÌ€' => 'Ç¸', 'nÌ€' => 'Ç¹', 'Ã…Ì�' => 'Çº', 'Ã¥Ì�' => 'Ç»', 'Ã†Ì�' => 'Ç¼', 'Ã¦Ì�' => 'Ç½', 'Ã˜Ì�' => 'Ç¾', 'Ã¸Ì�' => 'Ç¿', 'AÌ�' => 'È€', 'aÌ�' => 'È�', 'AÌ‘' => 'È‚', 'aÌ‘' => 'Èƒ', 'EÌ�' => 'È„', 'eÌ�' => 'È…', 'EÌ‘' => 'È†', 'eÌ‘' => 'È‡', 'IÌ�' => 'Èˆ', 'iÌ�' => 'È‰', 'IÌ‘' => 'ÈŠ', 'iÌ‘' => 'È‹', 'OÌ�' => 'ÈŒ', 'oÌ�' => 'È�', 'OÌ‘' => 'ÈŽ', 'oÌ‘' => 'È�', 'RÌ�' => 'È�', 'rÌ�' => 'È‘', 'RÌ‘' => 'È’', 'rÌ‘' => 'È“', 'UÌ�' => 'È”', 'uÌ�' => 'È•', 'UÌ‘' => 'È–', 'uÌ‘' => 'È—', 'SÌ¦' => 'È˜', 'sÌ¦' => 'È™', 'TÌ¦' => 'Èš', 'tÌ¦' => 'È›', 'HÌŒ' => 'Èž', 'hÌŒ' => 'ÈŸ', 'AÌ‡' => 'È¦', 'aÌ‡' => 'È§', 'EÌ§' => 'È¨', 'eÌ§' => 'È©', 'Ã–Ì„' => 'Èª', 'Ã¶Ì„' => 'È«', 'Ã•Ì„' => 'È¬', 'ÃµÌ„' => 'È­', 'OÌ‡' => 'È®', 'oÌ‡' => 'È¯', 'È®Ì„' => 'È°', 'È¯Ì„' => 'È±', 'YÌ„' => 'È²', 'yÌ„' => 'È³', 'Â¨Ì�' => 'Î…', 'Î‘Ì�' => 'Î†', 'Î•Ì�' => 'Îˆ', 'Î—Ì�' => 'Î‰', 'Î™Ì�' => 'ÎŠ', 'ÎŸÌ�' => 'ÎŒ', 'Î¥Ì�' => 'ÎŽ', 'Î©Ì�' => 'Î�', 'ÏŠÌ�' => 'Î�', 'Î™Ìˆ' => 'Îª', 'Î¥Ìˆ' => 'Î«', 'Î±Ì�' => 'Î¬', 'ÎµÌ�' => 'Î­', 'Î·Ì�' => 'Î®', 'Î¹Ì�' => 'Î¯', 'Ï‹Ì�' => 'Î°', 'Î¹Ìˆ' => 'ÏŠ', 'Ï…Ìˆ' => 'Ï‹', 'Î¿Ì�' => 'ÏŒ', 'Ï…Ì�' => 'Ï�', 'Ï‰Ì�' => 'ÏŽ', 'Ï’Ì�' => 'Ï“', 'Ï’Ìˆ' => 'Ï”', 'Ð•Ì€' => 'Ð€', 'Ð•Ìˆ' => 'Ð�', 'Ð“Ì�' => 'Ðƒ', 'Ð†Ìˆ' => 'Ð‡', 'ÐšÌ�' => 'ÐŒ', 'Ð˜Ì€' => 'Ð�', 'Ð£Ì†' => 'ÐŽ', 'Ð˜Ì†' => 'Ð™', 'Ð¸Ì†' => 'Ð¹', 'ÐµÌ€' => 'Ñ�', 'ÐµÌˆ' => 'Ñ‘', 'Ð³Ì�' => 'Ñ“', 'Ñ–Ìˆ' => 'Ñ—', 'ÐºÌ�' => 'Ñœ', 'Ð¸Ì€' => 'Ñ�', 'ÑƒÌ†' => 'Ñž', 'Ñ´Ì�' => 'Ñ¶', 'ÑµÌ�' => 'Ñ·', 'Ð–Ì†' => 'Ó�', 'Ð¶Ì†' => 'Ó‚', 'Ð�Ì†' => 'Ó�', 'Ð°Ì†' => 'Ó‘', 'Ð�Ìˆ' => 'Ó’', 'Ð°Ìˆ' => 'Ó“', 'Ð•Ì†' => 'Ó–', 'ÐµÌ†' => 'Ó—', 'Ó˜Ìˆ' => 'Óš', 'Ó™Ìˆ' => 'Ó›', 'Ð–Ìˆ' => 'Óœ', 'Ð¶Ìˆ' => 'Ó�', 'Ð—Ìˆ' => 'Óž', 'Ð·Ìˆ' => 'ÓŸ', 'Ð˜Ì„' => 'Ó¢', 'Ð¸Ì„' => 'Ó£', 'Ð˜Ìˆ' => 'Ó¤', 'Ð¸Ìˆ' => 'Ó¥', 'ÐžÌˆ' => 'Ó¦', 'Ð¾Ìˆ' => 'Ó§', 'Ó¨Ìˆ' => 'Óª', 'Ó©Ìˆ' => 'Ó«', 'Ð­Ìˆ' => 'Ó¬', 'Ñ�Ìˆ' => 'Ó­', 'Ð£Ì„' => 'Ó®', 'ÑƒÌ„' => 'Ó¯', 'Ð£Ìˆ' => 'Ó°', 'ÑƒÌˆ' => 'Ó±', 'Ð£Ì‹' => 'Ó²', 'ÑƒÌ‹' => 'Ó³', 'Ð§Ìˆ' => 'Ó´', 'Ñ‡Ìˆ' => 'Óµ', 'Ð«Ìˆ' => 'Ó¸', 'Ñ‹Ìˆ' => 'Ó¹', 'Ø§Ù“' => 'Ø¢', 'Ø§Ù”' => 'Ø£', 'ÙˆÙ”' => 'Ø¤', 'Ø§Ù•' => 'Ø¥', 'ÙŠÙ”' => 'Ø¦', 'Û•Ù”' => 'Û€', 'Û�Ù”' => 'Û‚', 'Û’Ù”' => 'Û“', 'à¤¨à¤¼' => 'à¤©', 'à¤°à¤¼' => 'à¤±', 'à¤³à¤¼' => 'à¤´', 'à§‡à¦¾' => 'à§‹', 'à§‡à§—' => 'à§Œ', 'à­‡à­–' => 'à­ˆ', 'à­‡à¬¾' => 'à­‹', 'à­‡à­—' => 'à­Œ', 'à®’à¯—' => 'à®”', 'à¯†à®¾' => 'à¯Š', 'à¯‡à®¾' => 'à¯‹', 'à¯†à¯—' => 'à¯Œ', 'à±†à±–' => 'à±ˆ', 'à²¿à³•' => 'à³€', 'à³†à³•' => 'à³‡', 'à³†à³–' => 'à³ˆ', 'à³†à³‚' => 'à³Š', 'à³Šà³•' => 'à³‹', 'àµ†à´¾' => 'àµŠ', 'àµ‡à´¾' => 'àµ‹', 'àµ†àµ—' => 'àµŒ', 'à·™à·Š' => 'à·š', 'à·™à·�' => 'à·œ', 'à·œà·Š' => 'à·�', 'à·™à·Ÿ' => 'à·ž', 'á€¥á€®' => 'á€¦', 'á¬…á¬µ' => 'á¬†', 'á¬‡á¬µ' => 'á¬ˆ', 'á¬‰á¬µ' => 'á¬Š', 'á¬‹á¬µ' => 'á¬Œ', 'á¬�á¬µ' => 'á¬Ž', 'á¬‘á¬µ' => 'á¬’', 'á¬ºá¬µ' => 'á¬»', 'á¬¼á¬µ' => 'á¬½', 'á¬¾á¬µ' => 'á­€', 'á¬¿á¬µ' => 'á­�', 'á­‚á¬µ' => 'á­ƒ', 'AÌ¥' => 'á¸€', 'aÌ¥' => 'á¸�', 'BÌ‡' => 'á¸‚', 'bÌ‡' => 'á¸ƒ', 'BÌ£' => 'á¸„', 'bÌ£' => 'á¸…', 'BÌ±' => 'á¸†', 'bÌ±' => 'á¸‡', 'Ã‡Ì�' => 'á¸ˆ', 'Ã§Ì�' => 'á¸‰', 'DÌ‡' => 'á¸Š', 'dÌ‡' => 'á¸‹', 'DÌ£' => 'á¸Œ', 'dÌ£' => 'á¸�', 'DÌ±' => 'á¸Ž', 'dÌ±' => 'á¸�', 'DÌ§' => 'á¸�', 'dÌ§' => 'á¸‘', 'DÌ­' => 'á¸’', 'dÌ­' => 'á¸“', 'Ä’Ì€' => 'á¸”', 'Ä“Ì€' => 'á¸•', 'Ä’Ì�' => 'á¸–', 'Ä“Ì�' => 'á¸—', 'EÌ­' => 'á¸˜', 'eÌ­' => 'á¸™', 'EÌ°' => 'á¸š', 'eÌ°' => 'á¸›', 'È¨Ì†' => 'á¸œ', 'È©Ì†' => 'á¸�', 'FÌ‡' => 'á¸ž', 'fÌ‡' => 'á¸Ÿ', 'GÌ„' => 'á¸ ', 'gÌ„' => 'á¸¡', 'HÌ‡' => 'á¸¢', 'hÌ‡' => 'á¸£', 'HÌ£' => 'á¸¤', 'hÌ£' => 'á¸¥', 'HÌˆ' => 'á¸¦', 'hÌˆ' => 'á¸§', 'HÌ§' => 'á¸¨', 'hÌ§' => 'á¸©', 'HÌ®' => 'á¸ª', 'hÌ®' => 'á¸«', 'IÌ°' => 'á¸¬', 'iÌ°' => 'á¸­', 'Ã�Ì�' => 'á¸®', 'Ã¯Ì�' => 'á¸¯', 'KÌ�' => 'á¸°', 'kÌ�' => 'á¸±', 'KÌ£' => 'á¸²', 'kÌ£' => 'á¸³', 'KÌ±' => 'á¸´', 'kÌ±' => 'á¸µ', 'LÌ£' => 'á¸¶', 'lÌ£' => 'á¸·', 'á¸¶Ì„' => 'á¸¸', 'á¸·Ì„' => 'á¸¹', 'LÌ±' => 'á¸º', 'lÌ±' => 'á¸»', 'LÌ­' => 'á¸¼', 'lÌ­' => 'á¸½', 'MÌ�' => 'á¸¾', 'mÌ�' => 'á¸¿', 'MÌ‡' => 'á¹€', 'mÌ‡' => 'á¹�', 'MÌ£' => 'á¹‚', 'mÌ£' => 'á¹ƒ', 'NÌ‡' => 'á¹„', 'nÌ‡' => 'á¹…', 'NÌ£' => 'á¹†', 'nÌ£' => 'á¹‡', 'NÌ±' => 'á¹ˆ', 'nÌ±' => 'á¹‰', 'NÌ­' => 'á¹Š', 'nÌ­' => 'á¹‹', 'Ã•Ì�' => 'á¹Œ', 'ÃµÌ�' => 'á¹�', 'Ã•Ìˆ' => 'á¹Ž', 'ÃµÌˆ' => 'á¹�', 'ÅŒÌ€' => 'á¹�', 'Å�Ì€' => 'á¹‘', 'ÅŒÌ�' => 'á¹’', 'Å�Ì�' => 'á¹“', 'PÌ�' => 'á¹”', 'pÌ�' => 'á¹•', 'PÌ‡' => 'á¹–', 'pÌ‡' => 'á¹—', 'RÌ‡' => 'á¹˜', 'rÌ‡' => 'á¹™', 'RÌ£' => 'á¹š', 'rÌ£' => 'á¹›', 'á¹šÌ„' => 'á¹œ', 'á¹›Ì„' => 'á¹�', 'RÌ±' => 'á¹ž', 'rÌ±' => 'á¹Ÿ', 'SÌ‡' => 'á¹ ', 'sÌ‡' => 'á¹¡', 'SÌ£' => 'á¹¢', 'sÌ£' => 'á¹£', 'ÅšÌ‡' => 'á¹¤', 'Å›Ì‡' => 'á¹¥', 'Å Ì‡' => 'á¹¦', 'Å¡Ì‡' => 'á¹§', 'á¹¢Ì‡' => 'á¹¨', 'á¹£Ì‡' => 'á¹©', 'TÌ‡' => 'á¹ª', 'tÌ‡' => 'á¹«', 'TÌ£' => 'á¹¬', 'tÌ£' => 'á¹­', 'TÌ±' => 'á¹®', 'tÌ±' => 'á¹¯', 'TÌ­' => 'á¹°', 'tÌ­' => 'á¹±', 'UÌ¤' => 'á¹²', 'uÌ¤' => 'á¹³', 'UÌ°' => 'á¹´', 'uÌ°' => 'á¹µ', 'UÌ­' => 'á¹¶', 'uÌ­' => 'á¹·', 'Å¨Ì�' => 'á¹¸', 'Å©Ì�' => 'á¹¹', 'ÅªÌˆ' => 'á¹º', 'Å«Ìˆ' => 'á¹»', 'VÌƒ' => 'á¹¼', 'vÌƒ' => 'á¹½', 'VÌ£' => 'á¹¾', 'vÌ£' => 'á¹¿', 'WÌ€' => 'áº€', 'wÌ€' => 'áº�', 'WÌ�' => 'áº‚', 'wÌ�' => 'áºƒ', 'WÌˆ' => 'áº„', 'wÌˆ' => 'áº…', 'WÌ‡' => 'áº†', 'wÌ‡' => 'áº‡', 'WÌ£' => 'áºˆ', 'wÌ£' => 'áº‰', 'XÌ‡' => 'áºŠ', 'xÌ‡' => 'áº‹', 'XÌˆ' => 'áºŒ', 'xÌˆ' => 'áº�', 'YÌ‡' => 'áºŽ', 'yÌ‡' => 'áº�', 'ZÌ‚' => 'áº�', 'zÌ‚' => 'áº‘', 'ZÌ£' => 'áº’', 'zÌ£' => 'áº“', 'ZÌ±' => 'áº”', 'zÌ±' => 'áº•', 'hÌ±' => 'áº–', 'tÌˆ' => 'áº—', 'wÌŠ' => 'áº˜', 'yÌŠ' => 'áº™', 'Å¿Ì‡' => 'áº›', 'AÌ£' => 'áº ', 'aÌ£' => 'áº¡', 'AÌ‰' => 'áº¢', 'aÌ‰' => 'áº£', 'Ã‚Ì�' => 'áº¤', 'Ã¢Ì�' => 'áº¥', 'Ã‚Ì€' => 'áº¦', 'Ã¢Ì€' => 'áº§', 'Ã‚Ì‰' => 'áº¨', 'Ã¢Ì‰' => 'áº©', 'Ã‚Ìƒ' => 'áºª', 'Ã¢Ìƒ' => 'áº«', 'áº Ì‚' => 'áº¬', 'áº¡Ì‚' => 'áº­', 'Ä‚Ì�' => 'áº®', 'ÄƒÌ�' => 'áº¯', 'Ä‚Ì€' => 'áº°', 'ÄƒÌ€' => 'áº±', 'Ä‚Ì‰' => 'áº²', 'ÄƒÌ‰' => 'áº³', 'Ä‚Ìƒ' => 'áº´', 'ÄƒÌƒ' => 'áºµ', 'áº Ì†' => 'áº¶', 'áº¡Ì†' => 'áº·', 'EÌ£' => 'áº¸', 'eÌ£' => 'áº¹', 'EÌ‰' => 'áºº', 'eÌ‰' => 'áº»', 'EÌƒ' => 'áº¼', 'eÌƒ' => 'áº½', 'ÃŠÌ�' => 'áº¾', 'ÃªÌ�' => 'áº¿', 'ÃŠÌ€' => 'á»€', 'ÃªÌ€' => 'á»�', 'ÃŠÌ‰' => 'á»‚', 'ÃªÌ‰' => 'á»ƒ', 'ÃŠÌƒ' => 'á»„', 'ÃªÌƒ' => 'á»…', 'áº¸Ì‚' => 'á»†', 'áº¹Ì‚' => 'á»‡', 'IÌ‰' => 'á»ˆ', 'iÌ‰' => 'á»‰', 'IÌ£' => 'á»Š', 'iÌ£' => 'á»‹', 'OÌ£' => 'á»Œ', 'oÌ£' => 'á»�', 'OÌ‰' => 'á»Ž', 'oÌ‰' => 'á»�', 'Ã”Ì�' => 'á»�', 'Ã´Ì�' => 'á»‘', 'Ã”Ì€' => 'á»’', 'Ã´Ì€' => 'á»“', 'Ã”Ì‰' => 'á»”', 'Ã´Ì‰' => 'á»•', 'Ã”Ìƒ' => 'á»–', 'Ã´Ìƒ' => 'á»—', 'á»ŒÌ‚' => 'á»˜', 'á»�Ì‚' => 'á»™', 'Æ Ì�' => 'á»š', 'Æ¡Ì�' => 'á»›', 'Æ Ì€' => 'á»œ', 'Æ¡Ì€' => 'á»�', 'Æ Ì‰' => 'á»ž', 'Æ¡Ì‰' => 'á»Ÿ', 'Æ Ìƒ' => 'á» ', 'Æ¡Ìƒ' => 'á»¡', 'Æ Ì£' => 'á»¢', 'Æ¡Ì£' => 'á»£', 'UÌ£' => 'á»¤', 'uÌ£' => 'á»¥', 'UÌ‰' => 'á»¦', 'uÌ‰' => 'á»§', 'Æ¯Ì�' => 'á»¨', 'Æ°Ì�' => 'á»©', 'Æ¯Ì€' => 'á»ª', 'Æ°Ì€' => 'á»«', 'Æ¯Ì‰' => 'á»¬', 'Æ°Ì‰' => 'á»­', 'Æ¯Ìƒ' => 'á»®', 'Æ°Ìƒ' => 'á»¯', 'Æ¯Ì£' => 'á»°', 'Æ°Ì£' => 'á»±', 'YÌ€' => 'á»²', 'yÌ€' => 'á»³', 'YÌ£' => 'á»´', 'yÌ£' => 'á»µ', 'YÌ‰' => 'á»¶', 'yÌ‰' => 'á»·', 'YÌƒ' => 'á»¸', 'yÌƒ' => 'á»¹', 'Î±Ì“' => 'á¼€', 'Î±Ì”' => 'á¼�', 'á¼€Ì€' => 'á¼‚', 'á¼�Ì€' => 'á¼ƒ', 'á¼€Ì�' => 'á¼„', 'á¼�Ì�' => 'á¼…', 'á¼€Í‚' => 'á¼†', 'á¼�Í‚' => 'á¼‡', 'Î‘Ì“' => 'á¼ˆ', 'Î‘Ì”' => 'á¼‰', 'á¼ˆÌ€' => 'á¼Š', 'á¼‰Ì€' => 'á¼‹', 'á¼ˆÌ�' => 'á¼Œ', 'á¼‰Ì�' => 'á¼�', 'á¼ˆÍ‚' => 'á¼Ž', 'á¼‰Í‚' => 'á¼�', 'ÎµÌ“' => 'á¼�', 'ÎµÌ”' => 'á¼‘', 'á¼�Ì€' => 'á¼’', 'á¼‘Ì€' => 'á¼“', 'á¼�Ì�' => 'á¼”', 'á¼‘Ì�' => 'á¼•', 'Î•Ì“' => 'á¼˜', 'Î•Ì”' => 'á¼™', 'á¼˜Ì€' => 'á¼š', 'á¼™Ì€' => 'á¼›', 'á¼˜Ì�' => 'á¼œ', 'á¼™Ì�' => 'á¼�', 'Î·Ì“' => 'á¼ ', 'Î·Ì”' => 'á¼¡', 'á¼ Ì€' => 'á¼¢', 'á¼¡Ì€' => 'á¼£', 'á¼ Ì�' => 'á¼¤', 'á¼¡Ì�' => 'á¼¥', 'á¼ Í‚' => 'á¼¦', 'á¼¡Í‚' => 'á¼§', 'Î—Ì“' => 'á¼¨', 'Î—Ì”' => 'á¼©', 'á¼¨Ì€' => 'á¼ª', 'á¼©Ì€' => 'á¼«', 'á¼¨Ì�' => 'á¼¬', 'á¼©Ì�' => 'á¼­', 'á¼¨Í‚' => 'á¼®', 'á¼©Í‚' => 'á¼¯', 'Î¹Ì“' => 'á¼°', 'Î¹Ì”' => 'á¼±', 'á¼°Ì€' => 'á¼²', 'á¼±Ì€' => 'á¼³', 'á¼°Ì�' => 'á¼´', 'á¼±Ì�' => 'á¼µ', 'á¼°Í‚' => 'á¼¶', 'á¼±Í‚' => 'á¼·', 'Î™Ì“' => 'á¼¸', 'Î™Ì”' => 'á¼¹', 'á¼¸Ì€' => 'á¼º', 'á¼¹Ì€' => 'á¼»', 'á¼¸Ì�' => 'á¼¼', 'á¼¹Ì�' => 'á¼½', 'á¼¸Í‚' => 'á¼¾', 'á¼¹Í‚' => 'á¼¿', 'Î¿Ì“' => 'á½€', 'Î¿Ì”' => 'á½�', 'á½€Ì€' => 'á½‚', 'á½�Ì€' => 'á½ƒ', 'á½€Ì�' => 'á½„', 'á½�Ì�' => 'á½…', 'ÎŸÌ“' => 'á½ˆ', 'ÎŸÌ”' => 'á½‰', 'á½ˆÌ€' => 'á½Š', 'á½‰Ì€' => 'á½‹', 'á½ˆÌ�' => 'á½Œ', 'á½‰Ì�' => 'á½�', 'Ï…Ì“' => 'á½�', 'Ï…Ì”' => 'á½‘', 'á½�Ì€' => 'á½’', 'á½‘Ì€' => 'á½“', 'á½�Ì�' => 'á½”', 'á½‘Ì�' => 'á½•', 'á½�Í‚' => 'á½–', 'á½‘Í‚' => 'á½—', 'Î¥Ì”' => 'á½™', 'á½™Ì€' => 'á½›', 'á½™Ì�' => 'á½�', 'á½™Í‚' => 'á½Ÿ', 'Ï‰Ì“' => 'á½ ', 'Ï‰Ì”' => 'á½¡', 'á½ Ì€' => 'á½¢', 'á½¡Ì€' => 'á½£', 'á½ Ì�' => 'á½¤', 'á½¡Ì�' => 'á½¥', 'á½ Í‚' => 'á½¦', 'á½¡Í‚' => 'á½§', 'Î©Ì“' => 'á½¨', 'Î©Ì”' => 'á½©', 'á½¨Ì€' => 'á½ª', 'á½©Ì€' => 'á½«', 'á½¨Ì�' => 'á½¬', 'á½©Ì�' => 'á½­', 'á½¨Í‚' => 'á½®', 'á½©Í‚' => 'á½¯', 'Î±Ì€' => 'á½°', 'ÎµÌ€' => 'á½²', 'Î·Ì€' => 'á½´', 'Î¹Ì€' => 'á½¶', 'Î¿Ì€' => 'á½¸', 'Ï…Ì€' => 'á½º', 'Ï‰Ì€' => 'á½¼', 'á¼€Í…' => 'á¾€', 'á¼�Í…' => 'á¾�', 'á¼‚Í…' => 'á¾‚', 'á¼ƒÍ…' => 'á¾ƒ', 'á¼„Í…' => 'á¾„', 'á¼…Í…' => 'á¾…', 'á¼†Í…' => 'á¾†', 'á¼‡Í…' => 'á¾‡', 'á¼ˆÍ…' => 'á¾ˆ', 'á¼‰Í…' => 'á¾‰', 'á¼ŠÍ…' => 'á¾Š', 'á¼‹Í…' => 'á¾‹', 'á¼ŒÍ…' => 'á¾Œ', 'á¼�Í…' => 'á¾�', 'á¼ŽÍ…' => 'á¾Ž', 'á¼�Í…' => 'á¾�', 'á¼ Í…' => 'á¾�', 'á¼¡Í…' => 'á¾‘', 'á¼¢Í…' => 'á¾’', 'á¼£Í…' => 'á¾“', 'á¼¤Í…' => 'á¾”', 'á¼¥Í…' => 'á¾•', 'á¼¦Í…' => 'á¾–', 'á¼§Í…' => 'á¾—', 'á¼¨Í…' => 'á¾˜', 'á¼©Í…' => 'á¾™', 'á¼ªÍ…' => 'á¾š', 'á¼«Í…' => 'á¾›', 'á¼¬Í…' => 'á¾œ', 'á¼­Í…' => 'á¾�', 'á¼®Í…' => 'á¾ž', 'á¼¯Í…' => 'á¾Ÿ', 'á½ Í…' => 'á¾ ', 'á½¡Í…' => 'á¾¡', 'á½¢Í…' => 'á¾¢', 'á½£Í…' => 'á¾£', 'á½¤Í…' => 'á¾¤', 'á½¥Í…' => 'á¾¥', 'á½¦Í…' => 'á¾¦', 'á½§Í…' => 'á¾§', 'á½¨Í…' => 'á¾¨', 'á½©Í…' => 'á¾©', 'á½ªÍ…' => 'á¾ª', 'á½«Í…' => 'á¾«', 'á½¬Í…' => 'á¾¬', 'á½­Í…' => 'á¾­', 'á½®Í…' => 'á¾®', 'á½¯Í…' => 'á¾¯', 'Î±Ì†' => 'á¾°', 'Î±Ì„' => 'á¾±', 'á½°Í…' => 'á¾²', 'Î±Í…' => 'á¾³', 'Î¬Í…' => 'á¾´', 'Î±Í‚' => 'á¾¶', 'á¾¶Í…' => 'á¾·', 'Î‘Ì†' => 'á¾¸', 'Î‘Ì„' => 'á¾¹', 'Î‘Ì€' => 'á¾º', 'Î‘Í…' => 'á¾¼', 'Â¨Í‚' => 'á¿�', 'á½´Í…' => 'á¿‚', 'Î·Í…' => 'á¿ƒ', 'Î®Í…' => 'á¿„', 'Î·Í‚' => 'á¿†', 'á¿†Í…' => 'á¿‡', 'Î•Ì€' => 'á¿ˆ', 'Î—Ì€' => 'á¿Š', 'Î—Í…' => 'á¿Œ', 'á¾¿Ì€' => 'á¿�', 'á¾¿Ì�' => 'á¿Ž', 'á¾¿Í‚' => 'á¿�', 'Î¹Ì†' => 'á¿�', 'Î¹Ì„' => 'á¿‘', 'ÏŠÌ€' => 'á¿’', 'Î¹Í‚' => 'á¿–', 'ÏŠÍ‚' => 'á¿—', 'Î™Ì†' => 'á¿˜', 'Î™Ì„' => 'á¿™', 'Î™Ì€' => 'á¿š', 'á¿¾Ì€' => 'á¿�', 'á¿¾Ì�' => 'á¿ž', 'á¿¾Í‚' => 'á¿Ÿ', 'Ï…Ì†' => 'á¿ ', 'Ï…Ì„' => 'á¿¡', 'Ï‹Ì€' => 'á¿¢', 'Ï�Ì“' => 'á¿¤', 'Ï�Ì”' => 'á¿¥', 'Ï…Í‚' => 'á¿¦', 'Ï‹Í‚' => 'á¿§', 'Î¥Ì†' => 'á¿¨', 'Î¥Ì„' => 'á¿©', 'Î¥Ì€' => 'á¿ª', 'Î¡Ì”' => 'á¿¬', 'Â¨Ì€' => 'á¿­', 'á½¼Í…' => 'á¿²', 'Ï‰Í…' => 'á¿³', 'ÏŽÍ…' => 'á¿´', 'Ï‰Í‚' => 'á¿¶', 'á¿¶Í…' => 'á¿·', 'ÎŸÌ€' => 'á¿¸', 'Î©Ì€' => 'á¿º', 'Î©Í…' => 'á¿¼', 'â†�Ì¸' => 'â†š', 'â†’Ì¸' => 'â†›', 'â†”Ì¸' => 'â†®', 'â‡�Ì¸' => 'â‡�', 'â‡”Ì¸' => 'â‡Ž', 'â‡’Ì¸' => 'â‡�', 'âˆƒÌ¸' => 'âˆ„', 'âˆˆÌ¸' => 'âˆ‰', 'âˆ‹Ì¸' => 'âˆŒ', 'âˆ£Ì¸' => 'âˆ¤', 'âˆ¥Ì¸' => 'âˆ¦', 'âˆ¼Ì¸' => 'â‰�', 'â‰ƒÌ¸' => 'â‰„', 'â‰…Ì¸' => 'â‰‡', 'â‰ˆÌ¸' => 'â‰‰', '=Ì¸' => 'â‰ ', 'â‰¡Ì¸' => 'â‰¢', 'â‰�Ì¸' => 'â‰­', '<Ì¸' => 'â‰®', '>Ì¸' => 'â‰¯', 'â‰¤Ì¸' => 'â‰°', 'â‰¥Ì¸' => 'â‰±', 'â‰²Ì¸' => 'â‰´', 'â‰³Ì¸' => 'â‰µ', 'â‰¶Ì¸' => 'â‰¸', 'â‰·Ì¸' => 'â‰¹', 'â‰ºÌ¸' => 'âŠ€', 'â‰»Ì¸' => 'âŠ�', 'âŠ‚Ì¸' => 'âŠ„', 'âŠƒÌ¸' => 'âŠ…', 'âŠ†Ì¸' => 'âŠˆ', 'âŠ‡Ì¸' => 'âŠ‰', 'âŠ¢Ì¸' => 'âŠ¬', 'âŠ¨Ì¸' => 'âŠ­', 'âŠ©Ì¸' => 'âŠ®', 'âŠ«Ì¸' => 'âŠ¯', 'â‰¼Ì¸' => 'â‹ ', 'â‰½Ì¸' => 'â‹¡', 'âŠ‘Ì¸' => 'â‹¢', 'âŠ’Ì¸' => 'â‹£', 'âŠ²Ì¸' => 'â‹ª', 'âŠ³Ì¸' => 'â‹«', 'âŠ´Ì¸' => 'â‹¬', 'âŠµÌ¸' => 'â‹­', 'ã�‹ã‚™' => 'ã�Œ', 'ã��ã‚™' => 'ã�Ž', 'ã��ã‚™' => 'ã��', 'ã�‘ã‚™' => 'ã�’', 'ã�“ã‚™' => 'ã�”', 'ã�•ã‚™' => 'ã�–', 'ã�—ã‚™' => 'ã�˜', 'ã�™ã‚™' => 'ã�š', 'ã�›ã‚™' => 'ã�œ', 'ã��ã‚™' => 'ã�ž', 'ã�Ÿã‚™' => 'ã� ', 'ã�¡ã‚™' => 'ã�¢', 'ã�¤ã‚™' => 'ã�¥', 'ã�¦ã‚™' => 'ã�§', 'ã�¨ã‚™' => 'ã�©', 'ã�¯ã‚™' => 'ã�°', 'ã�¯ã‚š' => 'ã�±', 'ã�²ã‚™' => 'ã�³', 'ã�²ã‚š' => 'ã�´', 'ã�µã‚™' => 'ã�¶', 'ã�µã‚š' => 'ã�·', 'ã�¸ã‚™' => 'ã�¹', 'ã�¸ã‚š' => 'ã�º', 'ã�»ã‚™' => 'ã�¼', 'ã�»ã‚š' => 'ã�½', 'ã�†ã‚™' => 'ã‚”', 'ã‚�ã‚™' => 'ã‚ž', 'ã‚«ã‚™' => 'ã‚¬', 'ã‚­ã‚™' => 'ã‚®', 'ã‚¯ã‚™' => 'ã‚°', 'ã‚±ã‚™' => 'ã‚²', 'ã‚³ã‚™' => 'ã‚´', 'ã‚µã‚™' => 'ã‚¶', 'ã‚·ã‚™' => 'ã‚¸', 'ã‚¹ã‚™' => 'ã‚º', 'ã‚»ã‚™' => 'ã‚¼', 'ã‚½ã‚™' => 'ã‚¾', 'ã‚¿ã‚™' => 'ãƒ€', 'ãƒ�ã‚™' => 'ãƒ‚', 'ãƒ„ã‚™' => 'ãƒ…', 'ãƒ†ã‚™' => 'ãƒ‡', 'ãƒˆã‚™' => 'ãƒ‰', 'ãƒ�ã‚™' => 'ãƒ�', 'ãƒ�ã‚š' => 'ãƒ‘', 'ãƒ’ã‚™' => 'ãƒ“', 'ãƒ’ã‚š' => 'ãƒ”', 'ãƒ•ã‚™' => 'ãƒ–', 'ãƒ•ã‚š' => 'ãƒ—', 'ãƒ˜ã‚™' => 'ãƒ™', 'ãƒ˜ã‚š' => 'ãƒš', 'ãƒ›ã‚™' => 'ãƒœ', 'ãƒ›ã‚š' => 'ãƒ�', 'ã‚¦ã‚™' => 'ãƒ´', 'ãƒ¯ã‚™' => 'ãƒ·', 'ãƒ°ã‚™' => 'ãƒ¸', 'ãƒ±ã‚™' => 'ãƒ¹', 'ãƒ²ã‚™' => 'ãƒº', 'ãƒ½ã‚™' => 'ãƒ¾', 'ð‘‚™ð‘‚º' => 'ð‘‚š', 'ð‘‚›ð‘‚º' => 'ð‘‚œ', 'ð‘‚¥ð‘‚º' => 'ð‘‚«', 'ð‘„±ð‘„§' => 'ð‘„®', 'ð‘„²ð‘„§' => 'ð‘„¯', 'ð‘�‡ð‘Œ¾' => 'ð‘�‹', 'ð‘�‡ð‘�—' => 'ð‘�Œ', 'ð‘’¹ð‘’º' => 'ð‘’»', 'ð‘’¹ð‘’°' => 'ð‘’¼', 'ð‘’¹ð‘’½' => 'ð‘’¾', 'ð‘–¸ð‘–¯' => 'ð‘–º', 'ð‘–¹ð‘–¯' => 'ð‘–»', 'ð‘¤µð‘¤°' => 'ð‘¤¸');<?php

class Normalizer extends Symfony\Polyfill\Intl\Normalizer\Normalizer
{
    /**
     * @deprecated since ICU 56 and removed in PHP 8
     */
    public const NONE = 2;
    public const FORM_D = 4;
    public const FORM_KD = 8;
    public const FORM_C = 16;
    public const FORM_KC = 32;
    public const NFD = 4;
    public const NFKD = 8;
    public const NFC = 16;
    public const NFKC = 32;
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Intl\Normalizer as p;
if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__ . '/bootstrap80.php';
}
if (!function_exists('normalizer_is_normalized')) {
    /**
     *
     */
    function normalizer_is_normalized($string, $form = p\Normalizer::FORM_C)
    {
        return p\Normalizer::isNormalized($string, $form);
    }
}
if (!function_exists('normalizer_normalize')) {
    /**
     *
     */
    function normalizer_normalize($string, $form = p\Normalizer::FORM_C)
    {
        return p\Normalizer::normalize($string, $form);
    }
}{
    "name": "symfony/polyfill-intl-normalizer",
    "type": "library",
    "description": "Symfony polyfill for intl's Normalizer class and related functions",
    "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "normalizer"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Intl\\Normalizer\\": "" },
        "files": [ "bootstrap.php" ],
        "classmap": [ "Resources/stubs" ]
    },
    "suggest": {
        "ext-intl": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.bootstrap.php';<?php

#[Attribute(Attribute::TARGET_CLASS)]
final class Attribute
{
    public const TARGET_CLASS = 1;
    public const TARGET_FUNCTION = 2;
    public const TARGET_METHOD = 4;
    public const TARGET_PROPERTY = 8;
    public const TARGET_CLASS_CONSTANT = 16;
    public const TARGET_PARAMETER = 32;
    public const TARGET_ALL = 63;
    public const IS_REPEATABLE = 64;
    /** @var int */
    public $flags;
    /**
     *
     */
    public function __construct(int $flags = self::TARGET_ALL)
    {
        $this->flags = $flags;
    }
}<?php

class UnhandledMatchError extends Error
{
}<?php

if (\PHP_VERSION_ID < 80000) {
    interface Stringable
    {
        /**
         * @return string
         */
        public function __toString();
    }
}<?php

class ValueError extends Error
{
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php80;

/**
 * @author Ion Bazan <ion.bazan@gmail.com>
 * @author Nico Oelgart <nicoswd@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Php80
{
    /**
     *
     */
    public static function fdiv(float $dividend, float $divisor) : float
    {
        return @($dividend / $divisor);
    }
    /**
     *
     */
    public static function get_debug_type($value) : string
    {
        switch (true) {
            case null === $value:
                return 'null';
            case \is_bool($value):
                return 'bool';
            case \is_string($value):
                return 'string';
            case \is_array($value):
                return 'array';
            case \is_int($value):
                return 'int';
            case \is_float($value):
                return 'float';
            case \is_object($value):
                break;
            case $value instanceof \__PHP_Incomplete_Class:
                return '__PHP_Incomplete_Class';
            default:
                if (null === ($type = @get_resource_type($value))) {
                    return 'unknown';
                }
                if ('Unknown' === $type) {
                    $type = 'closed';
                }
                return "resource ({$type})";
        }
        $class = \get_class($value);
        if (false === strpos($class, '@')) {
            return $class;
        }
        return ((get_parent_class($class) ?: key(class_implements($class))) ?: 'class') . '@anonymous';
    }
    /**
     *
     */
    public static function get_resource_id($res) : int
    {
        if (!\is_resource($res) && null === @get_resource_type($res)) {
            throw new \TypeError(sprintf('Argument 1 passed to get_resource_id() must be of the type resource, %s given', get_debug_type($res)));
        }
        return (int) $res;
    }
    /**
     *
     */
    public static function preg_last_error_msg() : string
    {
        switch (preg_last_error()) {
            case \PREG_INTERNAL_ERROR:
                return 'Internal error';
            case \PREG_BAD_UTF8_ERROR:
                return 'Malformed UTF-8 characters, possibly incorrectly encoded';
            case \PREG_BAD_UTF8_OFFSET_ERROR:
                return 'The offset did not correspond to the beginning of a valid UTF-8 code point';
            case \PREG_BACKTRACK_LIMIT_ERROR:
                return 'Backtrack limit exhausted';
            case \PREG_RECURSION_LIMIT_ERROR:
                return 'Recursion limit exhausted';
            case \PREG_JIT_STACKLIMIT_ERROR:
                return 'JIT stack limit exhausted';
            case \PREG_NO_ERROR:
                return 'No error';
            default:
                return 'Unknown error';
        }
    }
    /**
     *
     */
    public static function str_contains(string $haystack, string $needle) : bool
    {
        return '' === $needle || false !== strpos($haystack, $needle);
    }
    /**
     *
     */
    public static function str_starts_with(string $haystack, string $needle) : bool
    {
        return 0 === strncmp($haystack, $needle, \strlen($needle));
    }
    /**
     *
     */
    public static function str_ends_with(string $haystack, string $needle) : bool
    {
        return '' === $needle || '' !== $haystack && 0 === \Phabel\Target\Php80\Polyfill::substr_compare($haystack, $needle, -\strlen($needle));
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Php80 as p;
if (\PHP_VERSION_ID >= 80000) {
    return;
}
if (!defined('FILTER_VALIDATE_BOOL') && defined('FILTER_VALIDATE_BOOLEAN')) {
    define('FILTER_VALIDATE_BOOL', \FILTER_VALIDATE_BOOLEAN);
}
if (!function_exists('fdiv')) {
    /**
     *
     */
    function fdiv(float $num1, float $num2) : float
    {
        return p\Php80::fdiv($num1, $num2);
    }
}
if (!function_exists('preg_last_error_msg')) {
    /**
     *
     */
    function preg_last_error_msg() : string
    {
        return p\Php80::preg_last_error_msg();
    }
}
if (!function_exists('str_contains')) {
    /**
     *
     */
    function str_contains(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_contains($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('str_starts_with')) {
    /**
     *
     */
    function str_starts_with(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_starts_with($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('str_ends_with')) {
    /**
     *
     */
    function str_ends_with(?string $haystack, ?string $needle) : bool
    {
        return p\Php80::str_ends_with($haystack ?? '', $needle ?? '');
    }
}
if (!function_exists('get_debug_type')) {
    /**
     *
     */
    function get_debug_type($value) : string
    {
        return p\Php80::get_debug_type($value);
    }
}
if (!function_exists('get_resource_id')) {
    /**
     *
     */
    function get_resource_id($resource) : int
    {
        return p\Php80::get_resource_id($resource);
    }
}{
    "name": "symfony/polyfill-php80",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions",
    "keywords": ["polyfill", "shim", "compatibility", "portable"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Ion Bazan",
            "email": "ion.bazan@gmail.com"
        },
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Php80\\": "" },
        "files": [ "bootstrap.php" ],
        "classmap": [ "Resources/stubs" ]
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.bootstrap.php';<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Contracts\Service;

/**
 * A ServiceSubscriber exposes its dependencies via the static {@link getSubscribedServices} method.
 *
 * The getSubscribedServices method returns an array of service types required by such instances,
 * optionally keyed by the service names used internally. Service types that start with an interrogation
 * mark "?" are optional, while the other ones are mandatory service dependencies.
 *
 * The injected service locators SHOULD NOT allow access to any other services not specified by the method.
 *
 * It is expected that ServiceSubscriber instances consume PSR-11-based service locators internally.
 * This interface does not dictate any injection method for these service locators, although constructor
 * injection is recommended.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
interface ServiceSubscriberInterface
{
    /**
    * Returns an array of service types required by such instances, optionally keyed by the service names used internally.
    *
    * For mandatory dependencies:
    *
    * * ['logger' => 'Psr\Log\LoggerInterface'] means the objects use the "logger" name
    internally to fetch a service which must implement Psr\Log\LoggerInterface.
    ['loggers' => 'Psr\Log\LoggerInterface[]'] means the objects use the "loggers" name
    internally to fetch an iterable of Psr\Log\LoggerInterface instances.
    ['Psr\Log\LoggerInterface'] is a shortcut for
    ['Psr\Log\LoggerInterface' => 'Psr\Log\LoggerInterface']
    *
    * otherwise:
    *
    * * ['logger' => '?Psr\Log\LoggerInterface'] denotes an optional dependency
    ['loggers' => '?Psr\Log\LoggerInterface[]'] denotes an optional iterable dependency
    ['?Psr\Log\LoggerInterface'] is a shortcut for
    ['Psr\Log\LoggerInterface' => '?Psr\Log\LoggerInterface']
    *
    * @return string[] The required service types, optionally keyed by service names
    */
    public static function getSubscribedServices() : array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Contracts\Service;

use PhabelVendor\Psr\Container\ContainerExceptionInterface;
use PhabelVendor\Psr\Container\NotFoundExceptionInterface;
// Help opcache.preload discover always-needed symbols
\class_exists(ContainerExceptionInterface::class);
\class_exists(NotFoundExceptionInterface::class);
/**
 * A trait to help implement ServiceProviderInterface.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 * @author Nicolas Grekas <p@tchwork.com>
 */
trait ServiceLocatorTrait
{
    /**
     *
     */
    private array $factories;
    /**
     *
     */
    private array $loading = [];
    /**
     *
     */
    private array $providedTypes;
    /**
     * @param callable[] $factories
     */
    public function __construct(array $factories)
    {
        $this->factories = $factories;
    }
    /**
     * {@inheritdoc}
     */
    public function has(string $id) : bool
    {
        return isset($this->factories[$id]);
    }
    /**
     * {@inheritdoc}
     * @return mixed
     */
    public function get(string $id)
    {
        if (!isset($this->factories[$id])) {
            throw $this->createNotFoundException($id);
        }
        if (isset($this->loading[$id])) {
            $ids = \array_values($this->loading);
            $ids = \array_slice($this->loading, \array_search($id, $ids));
            $ids[] = $id;
            throw $this->createCircularReferenceException($id, $ids);
        }
        $this->loading[$id] = $id;
        try {
            $phabelReturn = $this->factories[$id]($this);
            if (!\true) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        } finally {
            unset($this->loading[$id]);
        }
        throw new \TypeError(__METHOD__ . '(): Return value must be of type mixed, none returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
    }
    /**
     * {@inheritdoc}
     */
    public function getProvidedServices() : array
    {
        if (!isset($this->providedTypes)) {
            $this->providedTypes = [];
            foreach ($this->factories as $name => $factory) {
                if (!\is_callable($factory)) {
                    $this->providedTypes[$name] = '?';
                } else {
                    $type = (new \ReflectionFunction($factory))->getReturnType();
                    $this->providedTypes[$name] = $type ? ($type->allowsNull() ? '?' : '') . ($type instanceof \ReflectionNamedType ? $type->getName() : $type) : '?';
                }
            }
        }
        return $this->providedTypes;
    }
    /**
     *
     */
    private function createNotFoundException(string $id) : NotFoundExceptionInterface
    {
        if (!($alternatives = \array_keys($this->factories))) {
            $message = 'is empty...';
        } else {
            $last = \array_pop($alternatives);
            if ($alternatives) {
                $message = \sprintf('only knows about the "%s" and "%s" services.', \implode('", "', $alternatives), $last);
            } else {
                $message = \sprintf('only knows about the "%s" service.', $last);
            }
        }
        if ($this->loading) {
            $message = \sprintf('The service "%s" has a dependency on a non-existent service "%s". This locator %s', \end($this->loading), $id, $message);
        } else {
            $message = \sprintf('Service "%s" not found: the current service locator %s', $id, $message);
        }
        return new class($message) extends \InvalidArgumentException implements NotFoundExceptionInterface
        {
        };
    }
    /**
     *
     */
    private function createCircularReferenceException(string $id, array $path) : ContainerExceptionInterface
    {
        return new class(\sprintf('Circular reference detected for service "%s", path: "%s".', $id, \implode(' -> ', $path))) extends \RuntimeException implements ContainerExceptionInterface
        {
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Contracts\Service\Test;

use PhabelVendor\PHPUnit\Framework\TestCase;
use PhabelVendor\Psr\Container\ContainerInterface;
use PhabelVendor\Symfony\Contracts\Service\ServiceLocatorTrait;
abstract class ServiceLocatorTest extends TestCase
{
    /**
     *
     */
    protected function getServiceLocator(array $factories) : ContainerInterface
    {
        return new class($factories) implements ContainerInterface
        {
            use ServiceLocatorTrait;
        };
    }
    /**
     *
     */
    public function testHas()
    {
        $locator = $this->getServiceLocator(['foo' => function () {
            return 'bar';
        }, 'bar' => function () {
            return 'baz';
        }, function () {
            return 'dummy';
        }]);
        $this->assertTrue($locator->has('foo'));
        $this->assertTrue($locator->has('bar'));
        $this->assertFalse($locator->has('dummy'));
    }
    /**
     *
     */
    public function testGet()
    {
        $locator = $this->getServiceLocator(['foo' => function () {
            return 'bar';
        }, 'bar' => function () {
            return 'baz';
        }]);
        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame('baz', $locator->get('bar'));
    }
    /**
     *
     */
    public function testGetDoesNotMemoize()
    {
        $i = 0;
        $locator = $this->getServiceLocator(['foo' => function () use(&$i) {
            ++$i;
            return 'bar';
        }]);
        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame('bar', $locator->get('foo'));
        $this->assertSame(2, $i);
    }
    /**
     *
     */
    public function testThrowsOnUndefinedInternalService()
    {
        if (!$this->getExpectedException()) {
            $this->expectException(\PhabelVendor\Psr\Container\NotFoundExceptionInterface::class);
            $this->expectExceptionMessage('The service "foo" has a dependency on a non-existent service "bar". This locator only knows about the "foo" service.');
        }
        $locator = $this->getServiceLocator(['foo' => function () use(&$locator) {
            return $locator->get('bar');
        }]);
        $locator->get('foo');
    }
    /**
     *
     */
    public function testThrowsOnCircularReference()
    {
        $this->expectException(\PhabelVendor\Psr\Container\ContainerExceptionInterface::class);
        $this->expectExceptionMessage('Circular reference detected for service "bar", path: "bar -> baz -> bar".');
        $locator = $this->getServiceLocator(['foo' => function () use(&$locator) {
            return $locator->get('bar');
        }, 'bar' => function () use(&$locator) {
            return $locator->get('baz');
        }, 'baz' => function () use(&$locator) {
            return $locator->get('bar');
        }]);
        $locator->get('foo');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Contracts\Service;

use PhabelVendor\Psr\Container\ContainerInterface;
/**
 * A ServiceProviderInterface exposes the identifiers and the types of services provided by a container.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Mateusz Sip <mateusz.sip@gmail.com>
 */
interface ServiceProviderInterface extends ContainerInterface
{
    /**
    * Returns an associative array of service types keyed by the identifiers provided by the current container.
    *
    * Examples:
    *
    * * ['logger' => 'Psr\Log\LoggerInterface'] means the object provides a service named "logger" that implements Psr\Log\LoggerInterface
    ['foo' => '?'] means the container provides service name "foo" of unspecified type
    ['bar' => '?Bar\Baz'] means the container provides a service "bar" of type Bar\Baz|null
    *
    * @return string[] The provided service types, keyed by service names
    */
    public function getProvidedServices() : array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Contracts\Service\Attribute;

/**
 * A required dependency.
 *
 * This attribute indicates that a property holds a required dependency. The annotated property or method should be
 * considered during the instantiation process of the containing class.
 *
 * @author Alexander M. Turek <me@derrabus.de>
 */
#[\Attribute(\Attribute::TARGET_METHOD | \Attribute::TARGET_PROPERTY)]
final class Required
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Contracts\Service\Attribute;

use PhabelVendor\Symfony\Contracts\Service\ServiceSubscriberTrait;
/**
 * Use with {@see ServiceSubscriberTrait} to mark a method's return type
 * as a subscribed service.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
#[\Attribute(\Attribute::TARGET_METHOD)]
final class SubscribedService
{
    /**
    * @param (string | null) $key The key to use for the service
    If null, use "ClassName::methodName"
    */
    public function __construct(?string $key = null)
    {
        $this->key = $key;
    }
    /**
     *
     */
    public ?string $key;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Contracts\Service;

/**
 * Provides a way to reset an object to its initial state.
 *
 * When calling the "reset()" method on an object, it should be put back to its
 * initial state. This usually means clearing any internal buffers and forwarding
 * the call to internal dependencies. All properties of the object should be put
 * back to the same state it had when it was first ready to use.
 *
 * This method could be called, for example, to recycle objects that are used as
 * services, so that they can be used to handle several requests in the same
 * process loop (note that we advise making your services stateless instead of
 * implementing this interface when possible.)
 */
interface ResetInterface
{
    /**
     *
     */
    public function reset();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Contracts\Service;

use PhabelVendor\Psr\Container\ContainerInterface;
use PhabelVendor\Symfony\Contracts\Service\Attribute\SubscribedService;
/**
 * Implementation of ServiceSubscriberInterface that determines subscribed services from
 * method return types. Service ids are available as "ClassName::methodName".
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
trait ServiceSubscriberTrait
{
    /** @var ContainerInterface */
    protected $container;
    /**
     * {@inheritdoc}
     */
    public static function getSubscribedServices() : array
    {
        static $services;
        if (null !== $services) {
            return $services;
        }
        $services = \is_callable(['parent', __FUNCTION__]) ? parent::getSubscribedServices() : [];
        foreach ((new \ReflectionClass(self::class))->getMethods() as $method) {
            if (self::class !== $method->getDeclaringClass()->name) {
                continue;
            }
            if (!($attribute = $method->getAttributes(SubscribedService::class)[0] ?? null)) {
                continue;
            }
            if ($method->isStatic() || $method->isAbstract() || $method->isGenerator() || $method->isInternal() || $method->getNumberOfRequiredParameters()) {
                throw new \LogicException(\sprintf('Cannot use "%s" on method "%s::%s()" (can only be used on non-static, non-abstract methods with no parameters).', SubscribedService::class, self::class, $method->name));
            }
            if (!($returnType = $method->getReturnType())) {
                throw new \LogicException(\sprintf('Cannot use "%s" on methods without a return type in "%s::%s()".', SubscribedService::class, $method->name, self::class));
            }
            $serviceId = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : (string) $returnType;
            if ($returnType->allowsNull()) {
                $serviceId = '?' . $serviceId;
            }
            $services[$attribute->newInstance()->key ?? self::class . '::' . $method->name] = $serviceId;
        }
        return $services;
    }
    /**
     * @required
     */
    public function setContainer(ContainerInterface $container) : ?ContainerInterface
    {
        $this->container = $container;
        if (\is_callable(['parent', __FUNCTION__])) {
            return parent::setContainer($container);
        }
        return null;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
class JsonException extends Exception
{
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Php73;

/**
 * @author Gabriel Caruso <carusogabriel34@gmail.com>
 * @author Ion Bazan <ion.bazan@gmail.com>
 *
 * @internal
 */
final class Php73
{
    public static $startAt = 1533462603;
    /**
     * @param bool $asNum
     *
     * @return (array | float | int)
     */
    public static function hrtime($asNum = false)
    {
        $ns = microtime(false);
        $s = \Phabel\Target\Php80\Polyfill::substr($ns, 11) - self::$startAt;
        $ns = 1000000000.0 * (float) $ns;
        if ($asNum) {
            $ns += $s * 1000000000.0;
            return \PHP_INT_SIZE === 4 ? $ns : (int) $ns;
        }
        return [$s, (int) $ns];
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Php73 as p;
if (\PHP_VERSION_ID >= 70300) {
    return;
}
if (!function_exists('is_countable')) {
    /**
     *
     */
    function is_countable($value)
    {
        return is_array($value) || $value instanceof Countable || $value instanceof ResourceBundle || $value instanceof SimpleXmlElement;
    }
}
if (!function_exists('hrtime')) {
    require_once __DIR__ . '/Php73.php';
    p\Php73::$startAt = (int) microtime(true);
    /**
     *
     */
    function hrtime($as_number = false)
    {
        return p\Php73::hrtime($as_number);
    }
}
if (!function_exists('array_key_first')) {
    /**
     *
     */
    function array_key_first(array $array)
    {
        foreach ($array as $key => $value) {
            return $key;
        }
    }
}
if (!function_exists('array_key_last')) {
    /**
     *
     */
    function array_key_last(array $array)
    {
        return key(array_slice($array, -1, 1, true));
    }
}{
    "name": "symfony/polyfill-php73",
    "type": "library",
    "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
    "keywords": ["polyfill", "shim", "compatibility", "portable"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Php73\\": "" },
        "files": [ "bootstrap.php" ],
        "classmap": [ "Resources/stubs" ]
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.bootstrap.php';<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Command;

use PhabelVendor\Symfony\Component\Console\Completion\CompletionInput;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Process\Process;
/**
 * Dumps the completion script for the current shell.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class DumpCompletionCommand extends Command
{
    protected static $defaultName = 'completion';
    protected static $defaultDescription = 'Dump the shell completion script';
    /**
     *
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void
    {
        if ($input->mustSuggestArgumentValuesFor('shell')) {
            $suggestions->suggestValues($this->getSupportedShells());
        }
    }
    /**
     *
     */
    protected function configure()
    {
        $fullCommand = $_SERVER['PHP_SELF'];
        $commandName = \basename($fullCommand);
        $fullCommand = \realpath($fullCommand) ?: $fullCommand;
        $this->setHelp(<<<EOH
The <info>%command.name%</> command dumps the shell completion script required
to use shell autocompletion (currently only bash completion is supported).

<comment>Static installation
-------------------</>

Dump the script to a global completion file and restart your shell:

    <info>%command.full_name% bash | sudo tee /etc/bash_completion.d/{$commandName}</>

Or dump the script to a local file and source it:

    <info>%command.full_name% bash > completion.sh</>

    <comment># source the file whenever you use the project</>
    <info>source completion.sh</>

    <comment># or add this line at the end of your "~/.bashrc" file:</>
    <info>source /path/to/completion.sh</>

<comment>Dynamic installation
--------------------</>

Add this add the end of your shell configuration file (e.g. <info>"~/.bashrc"</>):

    <info>eval "\$({$fullCommand} completion bash)"</>
EOH
)->addArgument('shell', InputArgument::OPTIONAL, 'The shell type (e.g. "bash"), the value of the "$SHELL" env var will be used if this is not given')->addOption('debug', null, InputOption::VALUE_NONE, 'Tail the completion debug log');
    }
    /**
     *
     */
    protected function execute(InputInterface $input, OutputInterface $output) : int
    {
        $commandName = \basename($_SERVER['argv'][0]);
        if ($input->getOption('debug')) {
            $this->tailDebugLog($commandName, $output);
            return self::SUCCESS;
        }
        $shell = $input->getArgument('shell') ?? self::guessShell();
        $completionFile = __DIR__ . '/../Resources/completion.' . $shell;
        if (!\file_exists($completionFile)) {
            $supportedShells = $this->getSupportedShells();
            ($output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output)->writeln(\sprintf('<error>Detected shell "%s", which is not supported by Symfony shell completion (supported shells: "%s").</>', $shell, \implode('", "', $supportedShells)));
            return self::INVALID;
        }
        $output->write(\str_replace(['{{ COMMAND_NAME }}', '{{ VERSION }}'], [$commandName, $this->getApplication()->getVersion()], \file_get_contents($completionFile)));
        return self::SUCCESS;
    }
    /**
     *
     */
    private static function guessShell() : string
    {
        return \basename($_SERVER['SHELL'] ?? '');
    }
    /**
     *
     */
    private function tailDebugLog(string $commandName, OutputInterface $output) : void
    {
        $debugFile = \sys_get_temp_dir() . '/sf_' . $commandName . '.log';
        if (!\file_exists($debugFile)) {
            \touch($debugFile);
        }
        $process = new Process(['tail', '-f', $debugFile], null, null, null, 0);
        $process->run(function (string $type, string $line) use($output) : void {
            $output->write($line);
        });
    }
    /**
     * @return string[]
     */
    private function getSupportedShells() : array
    {
        return \array_map(function ($f) {
            return \pathinfo($f, \PATHINFO_EXTENSION);
        }, \glob(__DIR__ . '/../Resources/completion.*'));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Command;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionInput;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Helper\HelperSet;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Nicolas Grekas <p@tchwork.com>
 */
final class LazyCommand extends Command
{
    private $command;
    private $isEnabled;
    /**
     *
     */
    public function __construct(string $name, array $aliases, string $description, bool $isHidden, \Closure $commandFactory, ?bool $isEnabled = \true)
    {
        $this->setName($name)->setAliases($aliases)->setHidden($isHidden)->setDescription($description);
        $this->command = $commandFactory;
        $this->isEnabled = $isEnabled;
    }
    /**
     *
     */
    public function ignoreValidationErrors() : void
    {
        $this->getCommand()->ignoreValidationErrors();
    }
    /**
     *
     */
    public function setApplication(Application $application = null) : void
    {
        if ($this->command instanceof parent) {
            $this->command->setApplication($application);
        }
        parent::setApplication($application);
    }
    /**
     *
     */
    public function setHelperSet(HelperSet $helperSet) : void
    {
        if ($this->command instanceof parent) {
            $this->command->setHelperSet($helperSet);
        }
        parent::setHelperSet($helperSet);
    }
    /**
     *
     */
    public function isEnabled() : bool
    {
        return $this->isEnabled ?? $this->getCommand()->isEnabled();
    }
    /**
     *
     */
    public function run(InputInterface $input, OutputInterface $output) : int
    {
        return $this->getCommand()->run($input, $output);
    }
    /**
     *
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void
    {
        $this->getCommand()->complete($input, $suggestions);
    }
    /**
     * @return $this
     */
    public function setCode(callable $code) : self
    {
        $this->getCommand()->setCode($code);
        return $this;
    }
    /**
     * @internal
     */
    public function mergeApplicationDefinition(bool $mergeArgs = \true) : void
    {
        $this->getCommand()->mergeApplicationDefinition($mergeArgs);
    }
    /**
     * @return $this
     */
    public function setDefinition($definition) : self
    {
        $this->getCommand()->setDefinition($definition);
        return $this;
    }
    /**
     *
     */
    public function getDefinition() : InputDefinition
    {
        return $this->getCommand()->getDefinition();
    }
    /**
     *
     */
    public function getNativeDefinition() : InputDefinition
    {
        return $this->getCommand()->getNativeDefinition();
    }
    /**
     * @return $this
     */
    public function addArgument(string $name, int $mode = null, string $description = '', $default = null) : self
    {
        $this->getCommand()->addArgument($name, $mode, $description, $default);
        return $this;
    }
    /**
     * @return $this
     */
    public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null) : self
    {
        $this->getCommand()->addOption($name, $shortcut, $mode, $description, $default);
        return $this;
    }
    /**
     * @return $this
     */
    public function setProcessTitle(string $title) : self
    {
        $this->getCommand()->setProcessTitle($title);
        return $this;
    }
    /**
     * @return $this
     */
    public function setHelp(string $help) : self
    {
        $this->getCommand()->setHelp($help);
        return $this;
    }
    /**
     *
     */
    public function getHelp() : string
    {
        return $this->getCommand()->getHelp();
    }
    /**
     *
     */
    public function getProcessedHelp() : string
    {
        return $this->getCommand()->getProcessedHelp();
    }
    /**
     *
     */
    public function getSynopsis(bool $short = \false) : string
    {
        return $this->getCommand()->getSynopsis($short);
    }
    /**
     * @return $this
     */
    public function addUsage(string $usage) : self
    {
        $this->getCommand()->addUsage($usage);
        return $this;
    }
    /**
     *
     */
    public function getUsages() : array
    {
        return $this->getCommand()->getUsages();
    }
    /**
     * @return mixed
     */
    public function getHelper(string $name)
    {
        return $this->getCommand()->getHelper($name);
    }
    /**
     *
     */
    public function getCommand() : parent
    {
        if (!$this->command instanceof \Closure) {
            return $this->command;
        }
        $command = $this->command = ($this->command)();
        $command->setApplication($this->getApplication());
        if (null !== $this->getHelperSet()) {
            $command->setHelperSet($this->getHelperSet());
        }
        $command->setName($this->getName())->setAliases($this->getAliases())->setHidden($this->isHidden())->setDescription($this->getDescription());
        // Will throw if the command is not correctly initialized.
        $command->getDefinition();
        return $command;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Command;

use PhabelVendor\Symfony\Component\Console\Completion\CompletionInput;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Descriptor\ApplicationDescription;
use PhabelVendor\Symfony\Component\Console\Helper\DescriptorHelper;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * HelpCommand displays the help for a given command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class HelpCommand extends Command
{
    private $command;
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->ignoreValidationErrors();
        $this->setName('help')->setDefinition([new InputArgument('command_name', InputArgument::OPTIONAL, 'The command name', 'help'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command help')])->setDescription('Display help for a command')->setHelp(<<<'EOF'
The <info>%command.name%</info> command displays help for a given command:

  <info>%command.full_name% list</info>

You can also output the help in other formats by using the <comment>--format</comment> option:

  <info>%command.full_name% --format=xml list</info>

To display the list of available commands, please use the <info>list</info> command.
EOF
);
    }
    /**
     *
     */
    public function setCommand(Command $command)
    {
        $this->command = $command;
    }
    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        if (null === $this->command) {
            $this->command = $this->getApplication()->find($input->getArgument('command_name'));
        }
        $helper = new DescriptorHelper();
        $helper->describe($output, $this->command, ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw')]);
        $this->command = null;
        return 0;
    }
    /**
     *
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void
    {
        if ($input->mustSuggestArgumentValuesFor('command_name')) {
            $descriptor = new ApplicationDescription($this->getApplication());
            $suggestions->suggestValues(\array_keys($descriptor->getCommands()));
            return;
        }
        if ($input->mustSuggestOptionValuesFor('format')) {
            $helper = new DescriptorHelper();
            $suggestions->suggestValues($helper->getFormats());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Command;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Attribute\AsCommand;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionInput;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Exception\ExceptionInterface;
use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
use PhabelVendor\Symfony\Component\Console\Helper\HelperSet;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Base class for all commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Command
{
    // see https://tldp.org/LDP/abs/html/exitcodes.html
    public const SUCCESS = 0;
    public const FAILURE = 1;
    public const INVALID = 2;
    /**
     * @var string|null The default command name
     */
    protected static $defaultName;
    /**
     * @var string|null The default command description
     */
    protected static $defaultDescription;
    private $application;
    private $name;
    private $processTitle;
    private $aliases = [];
    private $definition;
    private $hidden = \false;
    private $help = '';
    private $description = '';
    private $fullDefinition;
    private $ignoreValidationErrors = \false;
    private $code;
    private $synopsis = [];
    private $usages = [];
    private $helperSet;
    /**
     * @return (string | null)
     */
    public static function getDefaultName()
    {
        $class = static::class;
        if (\PHP_VERSION_ID >= 80000 && ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class))) {
            return $attribute[0]->newInstance()->name;
        }
        $r = new \ReflectionProperty($class, 'defaultName');
        return $class === $r->class ? static::$defaultName : null;
    }
    /**
     *
     */
    public static function getDefaultDescription() : ?string
    {
        $class = static::class;
        if (\PHP_VERSION_ID >= 80000 && ($attribute = (new \ReflectionClass($class))->getAttributes(AsCommand::class))) {
            return $attribute[0]->newInstance()->description;
        }
        $r = new \ReflectionProperty($class, 'defaultDescription');
        return $class === $r->class ? static::$defaultDescription : null;
    }
    /**
     * @param (string | null) $name The name of the command; passing null means it must be set in configure()
     *
     * @throws LogicException When the command name is empty
     */
    public function __construct(string $name = null)
    {
        $this->definition = new InputDefinition();
        if (null === $name && null !== ($name = static::getDefaultName())) {
            $aliases = \explode('|', $name);
            if ('' === ($name = \array_shift($aliases))) {
                $this->setHidden(\true);
                $name = \array_shift($aliases);
            }
            $this->setAliases($aliases);
        }
        if (null !== $name) {
            $this->setName($name);
        }
        if ('' === $this->description) {
            $this->setDescription(static::getDefaultDescription() ?? '');
        }
        $this->configure();
    }
    /**
     * Ignores validation errors.
     *
     * This is mainly useful for the help command.
     */
    public function ignoreValidationErrors()
    {
        $this->ignoreValidationErrors = \true;
    }
    /**
     *
     */
    public function setApplication(Application $application = null)
    {
        $this->application = $application;
        if ($application) {
            $this->setHelperSet($application->getHelperSet());
        } else {
            $this->helperSet = null;
        }
        $this->fullDefinition = null;
    }
    /**
     *
     */
    public function setHelperSet(HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }
    /**
     * Gets the helper set.
     *
     * @return (HelperSet | null)
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }
    /**
     * Gets the application instance for this command.
     *
     * @return (Application | null)
     */
    public function getApplication()
    {
        return $this->application;
    }
    /**
    * Checks whether the command is enabled or not in the current environment.
    *
    * Override this to check for x or y and return false if the command cannot
    run properly under the current conditions.
    *
    * @return bool
    */
    public function isEnabled()
    {
        return \true;
    }
    /**
     * Configures the current command.
     */
    protected function configure()
    {
    }
    /**
    * Executes the current command.
    *
    * This method is not abstract because you can use this class
    as a concrete class. In this case, instead of defining the
    execute() method, you set the code to execute by passing
    a Closure to the setCode() method.
    *
    * @return int 0 if everything went fine, or an exit code
    *
    * @throws LogicException When this abstract method is not implemented
    *
    * @see setCode()
    */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        throw new LogicException('You must override the execute() method in the concrete command class.');
    }
    /**
    * Interacts with the user.
    *
    * This method is executed before the InputDefinition is validated.
    This means that this is the only place where the command can
    interactively ask for values of missing required arguments.
    */
    protected function interact(InputInterface $input, OutputInterface $output)
    {
    }
    /**
    * Initializes the command after the input has been bound and before the input
    is validated.
    *
    * This is mainly useful when a lot of commands extends one main command
    where some things need to be initialized based on the input arguments and options.
    *
    * @see InputInterface::bind()
    * @see InputInterface::validate()
    */
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
    }
    /**
    * Runs the command.
    *
    * The code to execute is either defined directly with the
    setCode() method or by overriding the execute() method
    in a sub-class.
    *
    * @return int The command exit code
    *
    * @throws \Exception When binding input fails. Bypass this by calling {@link ignoreValidationErrors()}.
    *
    * @see setCode()
    * @see execute()
    */
    public function run(InputInterface $input, OutputInterface $output)
    {
        // add the application arguments and options
        $this->mergeApplicationDefinition();
        // bind the input against the command specific arguments/options
        try {
            $input->bind($this->getDefinition());
        } catch (ExceptionInterface $e) {
            if (!$this->ignoreValidationErrors) {
                throw $e;
            }
        }
        $this->initialize($input, $output);
        if (null !== $this->processTitle) {
            if (\function_exists('cli_set_process_title')) {
                if (!@\cli_set_process_title($this->processTitle)) {
                    if ('Darwin' === \PHP_OS) {
                        $output->writeln('<comment>Running "cli_set_process_title" as an unprivileged user is not supported on MacOS.</comment>', OutputInterface::VERBOSITY_VERY_VERBOSE);
                    } else {
                        \cli_set_process_title($this->processTitle);
                    }
                }
            } elseif (\function_exists('PhabelVendor\\setproctitle')) {
                setproctitle($this->processTitle);
            } elseif (OutputInterface::VERBOSITY_VERY_VERBOSE === $output->getVerbosity()) {
                $output->writeln('<comment>Install the proctitle PECL to be able to change the process title.</comment>');
            }
        }
        if ($input->isInteractive()) {
            $this->interact($input, $output);
        }
        // The command name argument is often omitted when a command is executed directly with its run() method.
        // It would fail the validation if we didn't make sure the command argument is present,
        // since it's required by the application.
        if ($input->hasArgument('command') && null === $input->getArgument('command')) {
            $input->setArgument('command', $this->getName());
        }
        $input->validate();
        if ($this->code) {
            $statusCode = ($this->code)($input, $output);
        } else {
            $statusCode = $this->execute($input, $output);
            if (!\is_int($statusCode)) {
                throw new \TypeError(\sprintf('Return value of "%s::execute()" must be of the type int, "%s" returned.', static::class, \get_debug_type($statusCode)));
            }
        }
        return \is_numeric($statusCode) ? (int) $statusCode : 0;
    }
    /**
     * Adds suggestions to $suggestions for the current completion input (e.g. option or argument).
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void
    {
    }
    /**
    * Sets the code to execute when running this command.
    *
    * If this method is used, it overrides the code defined
    in the execute() method.
    *
    * @param callable $code A callable(InputInterface $input, OutputInterface $output)
    *
    * @return $this
    *
    * @throws InvalidArgumentException
    *
    * @see execute()
    */
    public function setCode(callable $code)
    {
        if ($code instanceof \Closure) {
            $r = new \ReflectionFunction($code);
            if (null === $r->getClosureThis()) {
                \set_error_handler(static function () {
                });
                try {
                    if ($c = \Closure::bind($code, $this)) {
                        $code = $c;
                    }
                } finally {
                    \restore_error_handler();
                }
            }
        }
        $this->code = $code;
        return $this;
    }
    /**
     * Merges the application definition with the command definition.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @param bool $mergeArgs Whether to merge or not the Application definition arguments to Command definition arguments
     *
     * @internal
     */
    public function mergeApplicationDefinition(bool $mergeArgs = \true)
    {
        if (null === $this->application) {
            return;
        }
        $this->fullDefinition = new InputDefinition();
        $this->fullDefinition->setOptions($this->definition->getOptions());
        $this->fullDefinition->addOptions($this->application->getDefinition()->getOptions());
        if ($mergeArgs) {
            $this->fullDefinition->setArguments($this->application->getDefinition()->getArguments());
            $this->fullDefinition->addArguments($this->definition->getArguments());
        } else {
            $this->fullDefinition->setArguments($this->definition->getArguments());
        }
    }
    /**
     * Sets an array of argument and option instances.
     *
     * @param (array | InputDefinition) $definition An array of argument and option instances or a definition instance
     *
     * @return $this
     */
    public function setDefinition($definition)
    {
        if ($definition instanceof InputDefinition) {
            $this->definition = $definition;
        } else {
            $this->definition->setDefinition($definition);
        }
        $this->fullDefinition = null;
        return $this;
    }
    /**
     * Gets the InputDefinition attached to this Command.
     *
     * @return InputDefinition
     */
    public function getDefinition()
    {
        return $this->fullDefinition ?? $this->getNativeDefinition();
    }
    /**
    * Gets the InputDefinition to be used to create representations of this Command.
    *
    * Can be overridden to provide the original command representation when it would otherwise
    be changed by merging with the application InputDefinition.
    *
    * This method is not part of public API and should not be used directly.
    *
    * @return InputDefinition
    */
    public function getNativeDefinition()
    {
        if (null === $this->definition) {
            throw new LogicException(\sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', static::class));
        }
        return $this->definition;
    }
    /**
     * Adds an argument.
     *
     * @param (int | null) $mode The argument mode: InputArgument::REQUIRED or InputArgument::OPTIONAL
     * @param mixed $default The default value (for InputArgument::OPTIONAL mode only)
     *
     * @throws InvalidArgumentException When argument mode is not valid
     *
     * @return $this
     */
    public function addArgument(string $name, int $mode = null, string $description = '', $default = null)
    {
        $this->definition->addArgument(new InputArgument($name, $mode, $description, $default));
        if (null !== $this->fullDefinition) {
            $this->fullDefinition->addArgument(new InputArgument($name, $mode, $description, $default));
        }
        return $this;
    }
    /**
     * Adds an option.
     *
     * @param (string | array | null) $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param (int | null) $mode The option mode: One of the InputOption::VALUE_* constants
     * @param mixed $default The default value (must be null for InputOption::VALUE_NONE)
     *
     * @throws InvalidArgumentException If option mode is invalid or incompatible
     *
     * @return $this
     */
    public function addOption(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
    {
        $this->definition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
        if (null !== $this->fullDefinition) {
            $this->fullDefinition->addOption(new InputOption($name, $shortcut, $mode, $description, $default));
        }
        return $this;
    }
    /**
    * Sets the name of the command.
    *
    * This method can set both the namespace and the name if
    you separate them by a colon (:)
    *
    * $command->setName('foo:bar');
    *
    * @return $this
    *
    * @throws InvalidArgumentException When the name is invalid
    */
    public function setName(string $name)
    {
        $this->validateName($name);
        $this->name = $name;
        return $this;
    }
    /**
    * Sets the process title of the command.
    *
    * This feature should be used only when creating a long process command,
    like a daemon.
    *
    * @return $this
    */
    public function setProcessTitle(string $title)
    {
        $this->processTitle = $title;
        return $this;
    }
    /**
     * Returns the command name.
     *
     * @return (string | null)
     */
    public function getName()
    {
        return $this->name;
    }
    /**
    * @param bool $hidden Whether or not the command should be hidden from the list of commands
    The default value will be true in Symfony 6.0
    *
    * @return $this
    *
    * @final since Symfony 5.1
    */
    public function setHidden(bool $hidden)
    {
        $this->hidden = $hidden;
        return $this;
    }
    /**
     * @return bool whether the command should be publicly shown or not
     */
    public function isHidden()
    {
        return $this->hidden;
    }
    /**
     * Sets the description for the command.
     *
     * @return $this
     */
    public function setDescription(string $description)
    {
        $this->description = $description;
        return $this;
    }
    /**
     * Returns the description for the command.
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }
    /**
     * Sets the help for the command.
     *
     * @return $this
     */
    public function setHelp(string $help)
    {
        $this->help = $help;
        return $this;
    }
    /**
     * Returns the help for the command.
     *
     * @return string
     */
    public function getHelp()
    {
        return $this->help;
    }
    /**
    * Returns the processed help for the command replacing the %command.name% and
    %command.full_name% patterns with the real values dynamically.
    *
    * @return string
    */
    public function getProcessedHelp()
    {
        $name = $this->name;
        $isSingleCommand = $this->application && $this->application->isSingleCommand();
        $placeholders = ['%command.name%', '%command.full_name%'];
        $replacements = [$name, $isSingleCommand ? $_SERVER['PHP_SELF'] : $_SERVER['PHP_SELF'] . ' ' . $name];
        return \str_replace($placeholders, $replacements, $this->getHelp() ?: $this->getDescription());
    }
    /**
     * Sets the aliases for the command.
     *
     * @param string[] $aliases An array of aliases for the command
     *
     * @return $this
     *
     * @throws InvalidArgumentException When an alias is invalid
     */
    public function setAliases(iterable $aliases)
    {
        $list = [];
        foreach ($aliases as $alias) {
            $this->validateName($alias);
            $list[] = $alias;
        }
        $this->aliases = \is_array($aliases) ? $aliases : $list;
        return $this;
    }
    /**
     * Returns the aliases for the command.
     *
     * @return array
     */
    public function getAliases()
    {
        return $this->aliases;
    }
    /**
     * Returns the synopsis for the command.
     *
     * @param bool $short Whether to show the short version of the synopsis (with options folded) or not
     *
     * @return string
     */
    public function getSynopsis(bool $short = \false)
    {
        $key = $short ? 'short' : 'long';
        if (!isset($this->synopsis[$key])) {
            $this->synopsis[$key] = \trim(\sprintf('%s %s', $this->name, $this->definition->getSynopsis($short)));
        }
        return $this->synopsis[$key];
    }
    /**
     * Add a command usage example, it'll be prefixed with the command name.
     *
     * @return $this
     */
    public function addUsage(string $usage)
    {
        if (!\str_starts_with($usage, $this->name)) {
            $usage = \sprintf('%s %s', $this->name, $usage);
        }
        $this->usages[] = $usage;
        return $this;
    }
    /**
     * Returns alternative usages of the command.
     *
     * @return array
     */
    public function getUsages()
    {
        return $this->usages;
    }
    /**
     * Gets a helper instance by name.
     *
     * @return mixed
     *
     * @throws LogicException if no HelperSet is defined
     * @throws InvalidArgumentException if the helper is not defined
     */
    public function getHelper(string $name)
    {
        if (null === $this->helperSet) {
            throw new LogicException(\sprintf('Cannot retrieve helper "%s" because there is no HelperSet defined. Did you forget to add your command to the application or to set the application on the command using the setApplication() method? You can also set the HelperSet directly using the setHelperSet() method.', $name));
        }
        return $this->helperSet->get($name);
    }
    /**
     * Validates a command name.
     *
     * It must be non-empty and parts can optionally be separated by ":".
     *
     * @throws InvalidArgumentException When the name is invalid
     */
    private function validateName(string $name)
    {
        if (!\preg_match('/^[^\\:]++(\\:[^\\:]++)*$/', $name)) {
            throw new InvalidArgumentException(\sprintf('Command name "%s" is invalid.', $name));
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Command;

/**
 * Interface for command reacting to signal.
 *
 * @author GrÃ©goire Pineau <lyrixx@lyrix.info>
 */
interface SignalableCommandInterface
{
    /**
     * Returns the list of signals to subscribe.
     */
    public function getSubscribedSignals() : array;
    /**
     * The method will be called when the application is signaled.
     */
    public function handleSignal(int $signal) : void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Command;

use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
use PhabelVendor\Symfony\Component\Lock\LockFactory;
use PhabelVendor\Symfony\Component\Lock\LockInterface;
use PhabelVendor\Symfony\Component\Lock\Store\FlockStore;
use PhabelVendor\Symfony\Component\Lock\Store\SemaphoreStore;
/**
 * Basic lock feature for commands.
 *
 * @author Geoffrey Brier <geoffrey.brier@gmail.com>
 */
trait LockableTrait
{
    /** @var LockInterface|null */
    private $lock;
    /**
     * Locks a command.
     */
    private function lock(string $name = null, bool $blocking = \false) : bool
    {
        if (!\class_exists(SemaphoreStore::class)) {
            throw new LogicException('To enable the locking feature you must install the symfony/lock component.');
        }
        if (null !== $this->lock) {
            throw new LogicException('A lock is already in place.');
        }
        if (SemaphoreStore::isSupported()) {
            $store = new SemaphoreStore();
        } else {
            $store = new FlockStore();
        }
        $this->lock = (new LockFactory($store))->createLock($name ?: $this->getName());
        if (!$this->lock->acquire($blocking)) {
            $this->lock = null;
            return \false;
        }
        return \true;
    }
    /**
     * Releases the command lock if there is one.
     */
    private function release()
    {
        if ($this->lock) {
            $this->lock->release();
            $this->lock = null;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Command;

use PhabelVendor\Symfony\Component\Console\Completion\CompletionInput;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Descriptor\ApplicationDescription;
use PhabelVendor\Symfony\Component\Console\Helper\DescriptorHelper;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * ListCommand displays the list of all available commands for the application.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ListCommand extends Command
{
    /**
     * {@inheritdoc}
     */
    protected function configure()
    {
        $this->setName('list')->setDefinition([new InputArgument('namespace', InputArgument::OPTIONAL, 'The namespace name'), new InputOption('raw', null, InputOption::VALUE_NONE, 'To output raw command list'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), new InputOption('short', null, InputOption::VALUE_NONE, 'To skip describing commands\' arguments')])->setDescription('List commands')->setHelp(<<<'EOF'
The <info>%command.name%</info> command lists all commands:

  <info>%command.full_name%</info>

You can also display the commands for a specific namespace:

  <info>%command.full_name% test</info>

You can also output the information in other formats by using the <comment>--format</comment> option:

  <info>%command.full_name% --format=xml</info>

It's also possible to get raw list of commands (useful for embedding command runner):

  <info>%command.full_name% --raw</info>
EOF
);
    }
    /**
     * {@inheritdoc}
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $helper = new DescriptorHelper();
        $helper->describe($output, $this->getApplication(), ['format' => $input->getOption('format'), 'raw_text' => $input->getOption('raw'), 'namespace' => $input->getArgument('namespace'), 'short' => $input->getOption('short')]);
        return 0;
    }
    /**
     *
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void
    {
        if ($input->mustSuggestArgumentValuesFor('namespace')) {
            $descriptor = new ApplicationDescription($this->getApplication());
            $suggestions->suggestValues(\array_keys($descriptor->getNamespaces()));
            return;
        }
        if ($input->mustSuggestOptionValuesFor('format')) {
            $helper = new DescriptorHelper();
            $suggestions->suggestValues($helper->getFormats());
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Command;

use PhabelVendor\Symfony\Component\Console\Completion\CompletionInput;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Completion\Output\BashCompletionOutput;
use PhabelVendor\Symfony\Component\Console\Completion\Output\CompletionOutputInterface;
use PhabelVendor\Symfony\Component\Console\Exception\CommandNotFoundException;
use PhabelVendor\Symfony\Component\Console\Exception\ExceptionInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Responsible for providing the values to the shell completion.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class CompleteCommand extends Command
{
    protected static $defaultName = '|_complete';
    protected static $defaultDescription = 'Internal command to provide shell completion suggestions';
    private $completionOutputs;
    private $isDebug = \false;
    /**
     * @param array<string, class-string<CompletionOutputInterface>> $completionOutputs A list of additional completion outputs, with shell name as key and FQCN as value
     */
    public function __construct(array $completionOutputs = [])
    {
        // must be set before the parent constructor, as the property value is used in configure()
        $this->completionOutputs = $completionOutputs + ['bash' => BashCompletionOutput::class];
        parent::__construct();
    }
    /**
     *
     */
    protected function configure() : void
    {
        $this->addOption('shell', 's', InputOption::VALUE_REQUIRED, 'The shell type ("' . \implode('", "', \array_keys($this->completionOutputs)) . '")')->addOption('input', 'i', InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'An array of input tokens (e.g. COMP_WORDS or argv)')->addOption('current', 'c', InputOption::VALUE_REQUIRED, 'The index of the "input" array that the cursor is in (e.g. COMP_CWORD)')->addOption('symfony', 'S', InputOption::VALUE_REQUIRED, 'The version of the completion script');
    }
    /**
     *
     */
    protected function initialize(InputInterface $input, OutputInterface $output)
    {
        $this->isDebug = \filter_var(\getenv('SYMFONY_COMPLETION_DEBUG'), \FILTER_VALIDATE_BOOLEAN);
    }
    /**
     *
     */
    protected function execute(InputInterface $input, OutputInterface $output) : int
    {
        try {
            // uncomment when a bugfix or BC break has been introduced in the shell completion scripts
            //$version = $input->getOption('symfony');
            //if ($version && version_compare($version, 'x.y', '>=')) {
            //    $message = sprintf('Completion script version is not supported ("%s" given, ">=x.y" required).', $version);
            //    $this->log($message);
            //    $output->writeln($message.' Install the Symfony completion script again by using the "completion" command.');
            //    return 126;
            //}
            $shell = $input->getOption('shell');
            if (!$shell) {
                throw new \RuntimeException('The "--shell" option must be set.');
            }
            if (!($completionOutput = $this->completionOutputs[$shell] ?? \false)) {
                throw new \RuntimeException(\sprintf('Shell completion is not supported for your shell: "%s" (supported: "%s").', $shell, \implode('", "', \array_keys($this->completionOutputs))));
            }
            $completionInput = $this->createCompletionInput($input);
            $suggestions = new CompletionSuggestions();
            $this->log(['', '<comment>' . \Phabel\Target\Php80\Polyfill::date('Y-m-d H:i:s') . '</>', '<info>Input:</> <comment>("|" indicates the cursor position)</>', '  ' . (string) $completionInput, '<info>Command:</>', '  ' . (string) \implode(' ', $_SERVER['argv']), '<info>Messages:</>']);
            $command = $this->findCommand($completionInput, $output);
            if (null === $command) {
                $this->log('  No command found, completing using the Application class.');
                $this->getApplication()->complete($completionInput, $suggestions);
            } elseif ($completionInput->mustSuggestArgumentValuesFor('command') && $command->getName() !== $completionInput->getCompletionValue()) {
                $this->log('  No command found, completing using the Application class.');
                // expand shortcut names ("cache:cl<TAB>") into their full name ("cache:clear")
                $suggestions->suggestValue($command->getName());
            } else {
                $command->mergeApplicationDefinition();
                $completionInput->bind($command->getDefinition());
                if (CompletionInput::TYPE_OPTION_NAME === $completionInput->getCompletionType()) {
                    $this->log('  Completing option names for the <comment>' . \get_class($command instanceof LazyCommand ? $command->getCommand() : $command) . '</> command.');
                    $suggestions->suggestOptions($command->getDefinition()->getOptions());
                } else {
                    $this->log(['  Completing using the <comment>' . \get_class($command instanceof LazyCommand ? $command->getCommand() : $command) . '</> class.', '  Completing <comment>' . $completionInput->getCompletionType() . '</> for <comment>' . $completionInput->getCompletionName() . '</>']);
                    if (null !== ($compval = $completionInput->getCompletionValue())) {
                        $this->log('  Current value: <comment>' . $compval . '</>');
                    }
                    $command->complete($completionInput, $suggestions);
                }
            }
            /** @var CompletionOutputInterface $completionOutput */
            $completionOutput = new $completionOutput();
            $this->log('<info>Suggestions:</>');
            if ($options = $suggestions->getOptionSuggestions()) {
                $this->log('  --' . \implode(' --', \array_map(function ($o) {
                    return $o->getName();
                }, $options)));
            } elseif ($values = $suggestions->getValueSuggestions()) {
                $this->log('  ' . \implode(' ', $values));
            } else {
                $this->log('  <comment>No suggestions were provided</>');
            }
            $completionOutput->write($suggestions, $output);
        } catch (\Throwable $e) {
            $this->log(['<error>Error!</error>', (string) $e]);
            if ($output->isDebug()) {
                throw $e;
            }
            return self::FAILURE;
        }
        return self::SUCCESS;
    }
    /**
     *
     */
    private function createCompletionInput(InputInterface $input) : CompletionInput
    {
        $currentIndex = $input->getOption('current');
        if (!$currentIndex || !\ctype_digit($currentIndex)) {
            throw new \RuntimeException('The "--current" option must be set and it must be an integer.');
        }
        $completionInput = CompletionInput::fromTokens($input->getOption('input'), (int) $currentIndex);
        try {
            $completionInput->bind($this->getApplication()->getDefinition());
        } catch (ExceptionInterface $e) {
        }
        return $completionInput;
    }
    /**
     *
     */
    private function findCommand(CompletionInput $completionInput, OutputInterface $output) : ?Command
    {
        try {
            $inputName = $completionInput->getFirstArgument();
            if (null === $inputName) {
                return null;
            }
            return $this->getApplication()->find($inputName);
        } catch (CommandNotFoundException $e) {
        }
        return null;
    }
    /**
     *
     */
    private function log($messages) : void
    {
        if (!$this->isDebug) {
            return;
        }
        $commandName = \basename($_SERVER['argv'][0]);
        \file_put_contents(\sys_get_temp_dir() . '/sf_' . $commandName . '.log', \implode(\PHP_EOL, (array) $messages) . \PHP_EOL, \FILE_APPEND);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class Color
{
    private const COLORS = ['black' => 0, 'red' => 1, 'green' => 2, 'yellow' => 3, 'blue' => 4, 'magenta' => 5, 'cyan' => 6, 'white' => 7, 'default' => 9];
    private const BRIGHT_COLORS = ['gray' => 0, 'bright-red' => 1, 'bright-green' => 2, 'bright-yellow' => 3, 'bright-blue' => 4, 'bright-magenta' => 5, 'bright-cyan' => 6, 'bright-white' => 7];
    private const AVAILABLE_OPTIONS = ['bold' => ['set' => 1, 'unset' => 22], 'underscore' => ['set' => 4, 'unset' => 24], 'blink' => ['set' => 5, 'unset' => 25], 'reverse' => ['set' => 7, 'unset' => 27], 'conceal' => ['set' => 8, 'unset' => 28]];
    private $foreground;
    private $background;
    private $options = [];
    /**
     *
     */
    public function __construct(string $foreground = '', string $background = '', array $options = [])
    {
        $this->foreground = $this->parseColor($foreground);
        $this->background = $this->parseColor($background, \true);
        foreach ($options as $option) {
            if (!isset(self::AVAILABLE_OPTIONS[$option])) {
                throw new InvalidArgumentException(\sprintf('Invalid option specified: "%s". Expected one of (%s).', $option, \implode(', ', \array_keys(self::AVAILABLE_OPTIONS))));
            }
            $this->options[$option] = self::AVAILABLE_OPTIONS[$option];
        }
    }
    /**
     *
     */
    public function apply(string $text) : string
    {
        return $this->set() . $text . $this->unset();
    }
    /**
     *
     */
    public function set() : string
    {
        $setCodes = [];
        if ('' !== $this->foreground) {
            $setCodes[] = $this->foreground;
        }
        if ('' !== $this->background) {
            $setCodes[] = $this->background;
        }
        foreach ($this->options as $option) {
            $setCodes[] = $option['set'];
        }
        if (0 === \count($setCodes)) {
            return '';
        }
        return \sprintf("\x1b[%sm", \implode(';', $setCodes));
    }
    /**
     *
     */
    public function unset() : string
    {
        $unsetCodes = [];
        if ('' !== $this->foreground) {
            $unsetCodes[] = 39;
        }
        if ('' !== $this->background) {
            $unsetCodes[] = 49;
        }
        foreach ($this->options as $option) {
            $unsetCodes[] = $option['unset'];
        }
        if (0 === \count($unsetCodes)) {
            return '';
        }
        return \sprintf("\x1b[%sm", \implode(';', $unsetCodes));
    }
    /**
     *
     */
    private function parseColor(string $color, bool $background = \false) : string
    {
        if ('' === $color) {
            return '';
        }
        if ('#' === $color[0]) {
            $color = \Phabel\Target\Php80\Polyfill::substr($color, 1);
            if (3 === \strlen($color)) {
                $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
            }
            if (6 !== \strlen($color)) {
                throw new InvalidArgumentException(\sprintf('Invalid "%s" color.', $color));
            }
            return ($background ? '4' : '3') . $this->convertHexColorToAnsi(\hexdec($color));
        }
        if (isset(self::COLORS[$color])) {
            return ($background ? '4' : '3') . self::COLORS[$color];
        }
        if (isset(self::BRIGHT_COLORS[$color])) {
            return ($background ? '10' : '9') . self::BRIGHT_COLORS[$color];
        }
        throw new InvalidArgumentException(\sprintf('Invalid "%s" color; expected one of (%s).', $color, \implode(', ', \array_merge(\array_keys(self::COLORS), \array_keys(self::BRIGHT_COLORS)))));
    }
    /**
     *
     */
    private function convertHexColorToAnsi(int $color) : string
    {
        $r = $color >> 16 & 255;
        $g = $color >> 8 & 255;
        $b = $color & 255;
        // see https://github.com/termstandard/colors/ for more information about true color support
        if ('truecolor' !== \getenv('COLORTERM')) {
            return (string) $this->degradeHexColorToAnsi($r, $g, $b);
        }
        return \sprintf('8;2;%d;%d;%d', $r, $g, $b);
    }
    /**
     *
     */
    private function degradeHexColorToAnsi(int $r, int $g, int $b) : int
    {
        if (0 === \round($this->getSaturation($r, $g, $b) / 50)) {
            return 0;
        }
        return \round($b / 255) << 2 | \round($g / 255) << 1 | \round($r / 255);
    }
    /**
     *
     */
    private function getSaturation(int $r, int $g, int $b) : int
    {
        $r = $r / 255;
        $g = $g / 255;
        $b = $b / 255;
        $v = \max($r, $g, $b);
        if (0 === ($diff = $v - \min($r, $g, $b))) {
            return 0;
        }
        return (int) $diff * 100 / $v;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\EventListener;

use PhabelVendor\Psr\Log\LoggerInterface;
use PhabelVendor\Symfony\Component\Console\ConsoleEvents;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleErrorEvent;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleEvent;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleTerminateEvent;
use PhabelVendor\Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
 * @author James Halsall <james.t.halsall@googlemail.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class ErrorListener implements EventSubscriberInterface
{
    private $logger;
    /**
     *
     */
    public function __construct(LoggerInterface $logger = null)
    {
        $this->logger = $logger;
    }
    /**
     *
     */
    public function onConsoleError(ConsoleErrorEvent $event)
    {
        if (null === $this->logger) {
            return;
        }
        $error = $event->getError();
        if (!($inputString = $this->getInputString($event))) {
            $this->logger->critical('An error occurred while using the console. Message: "{message}"', ['exception' => $error, 'message' => $error->getMessage()]);
            return;
        }
        $this->logger->critical('Error thrown while running command "{command}". Message: "{message}"', ['exception' => $error, 'command' => $inputString, 'message' => $error->getMessage()]);
    }
    /**
     *
     */
    public function onConsoleTerminate(ConsoleTerminateEvent $event)
    {
        if (null === $this->logger) {
            return;
        }
        $exitCode = $event->getExitCode();
        if (0 === $exitCode) {
            return;
        }
        if (!($inputString = $this->getInputString($event))) {
            $this->logger->debug('The console exited with code "{code}"', ['code' => $exitCode]);
            return;
        }
        $this->logger->debug('Command "{command}" exited with code "{code}"', ['command' => $inputString, 'code' => $exitCode]);
    }
    /**
     *
     */
    public static function getSubscribedEvents()
    {
        return [ConsoleEvents::ERROR => ['onConsoleError', -128], ConsoleEvents::TERMINATE => ['onConsoleTerminate', -128]];
    }
    /**
     *
     */
    private static function getInputString(ConsoleEvent $event) : ?string
    {
        $commandName = $event->getCommand() ? $event->getCommand()->getName() : null;
        $input = $event->getInput();
        if (\method_exists($input, '__toString')) {
            if ($commandName) {
                return \str_replace(["'{$commandName}'", "\"{$commandName}\""], $commandName, (string) $input);
            }
            return (string) $input;
        }
        return $commandName;
    }
}
MZ�       ÿÿ  ¸       @                                   è   º ´	Í!¸LÍ!This program cannot be run in DOS mode.
$       Æ,Í;§Bž;§Bž;§Bž2ß×ž:§Bž2ßÁž-§Bž2ßÆž9§Bž2ßÑž?§Bža9ž8§Bž;§Cž§Bž2ßÈž:§Bž2ßÖž:§Bž2ßÓž:§BžRich;§Bž        PE  L ¬MoO        à 	  
         8           @                      `     ?œ   @�                           �"  P    @                      P  p   !                             8!  @               Ø                           .text   	      
                    `.rdata  Î	       
                 @  @.data   �   0                    @  À.rsrc       @                    @  @.reloc  Ì   P      "              @  B                                                                                                                                                                                                                                                                                                                                                        j$¸æ@ èx  jöÿ @ ƒeÐ ‹ð�EÐPVÿ  @ ‹EÐƒàûPVÿ @ �MÔÿX @ ƒeü �EÔPÿ5H @ ÿL @ YYÿ5\ @ �EÔPÿ5` @ ÿD @ YY‹ÈÿP @ ƒMüÿ�MÔÿT @ 3ÀèH  Ã; 0@ uóÃé¬  h€@ è£  ¡l3@ Ç$40@ ÿ5h3@ £40@ h$0@ h(0@ h 0@ ÿ  @ ƒÄ£00@ …À}jè¹  YÃjh"@ è  3Û‰]üd¡   ‹p‰]ä¿€3@ SVWÿ0 @ ;Ãt;Æu3öF‰uäëhè  ÿ4 @ ëÚ3öF¡|3@ ;Æu
jè\  Yë;¡|3@ …Àu,‰5|3@ hð @ hä @ è§  YY…ÀtÇEüþÿÿÿ¸ÿ   éÝ   ‰5<0@ ¡|3@ ;Æuhà @ hØ @ èl  YYÇ|3@    9]äuSWÿ8 @ 9Œ3@ thŒ3@ èƒ  Y…Àt
SjSÿŒ3@ ¡$0@ ‹¼ @ ‰ÿ5$0@ ÿ5(0@ ÿ5 0@ èþÿÿƒÄ£80@ 9,0@ u7PÿÀ @ ‹Eì‹‹	‰MàPQèŽ  YYÃ‹eè‹Eà£80@ 3Û9,0@ uPÿh @ 9<0@ uÿœ @ ÇEüþÿÿÿ¡80@ èû  Ã¸MZ  f9  @ t3ÀëM¡< @ �€  @ �8PE  ué·H�ù  t�ù  uÕƒ¸„   vÌ3É9ˆø   ëƒxtv¼3É9ˆè   •Á‹Áj£,0@ ÿp @ jÿÿl @ YY£„3@ £ˆ3@ ÿÌ @ ‹t3@ ‰ÿˆ @ ‹p3@ ‰¡¨ @ ‹ £x3@ èV  è¬  ƒ=0@  uhµ@ ÿ¬ @ Yèg  ƒ=0@ ÿu	jÿÿ° @ Y3ÀÃè{  éŸýÿÿ‹ÿU‹ì�ì(  £H1@ ‰D1@ ‰@1@ ‰<1@ ‰581@ ‰=41@ fŒ`1@ fŒT1@ fŒ01@ fŒ,1@ fŒ%(1@ fŒ-$1@ œ�X1@ ‹E £L1@ ‹E£P1@ �E£\1@ ‹…àüÿÿÇ˜0@   ¡P1@ £L0@ Ç@0@ 	 ÀÇD0@    ¡ 0@ ‰…Øüÿÿ¡0@ ‰…Üüÿÿÿ @ £�0@ jè?  Yj ÿ  @ h!@ ÿ$ @ ƒ=�0@  ujè  Yh	 Àÿ( @ Pÿ, @ ÉÃ‹ÿU‹ì‹E‹ �8csmàu*ƒxu$‹@= “t=!“t="“t= @™uèÐ  3À]Â hH@ ÿ  @ 3ÀÃÿ%¤ @ jh("@ èb  ÿ5ˆ3@ ‹5Œ @ ÿÖY‰EäƒøÿuÿuÿÄ @ Yëgjè’  Yƒeü ÿ5ˆ3@ ÿÖ‰Eäÿ5„3@ ÿÖYY‰Eà�EàP�EäPÿu‹5l @ ÿÖYPèU  ‰EÜÿuäÿÖ£ˆ3@ ÿuàÿÖƒÄ£„3@ ÇEüþÿÿÿè	   ‹EÜè  Ãjè  YÃ‹ÿU‹ìÿuèNÿÿÿ÷ØÀ÷ØYH]Ã‹ÿV¸ü!@ ¾ü!@ W‹ø;Æs‹…ÀtÿÐƒÇ;þrñ_^Ã‹ÿV¸"@ ¾"@ W‹ø;Æs‹…ÀtÿÐƒÇ;þrñ_^Ãÿ%È @ ÌÌÌÌ‹ÿU‹ì‹M¸MZ  f9t3À]Ã‹A<Á�8PE  uï3Ò¹  f9H”Â‹Â]ÃÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ì‹E‹H<È·ASV·q3ÒW�D…öv‹}‹H;ùr	‹XÙ;ûr
BƒÀ(;Örè3À_^[]ÃÌÌÌÌÌÌÌÌÌÌÌÌ‹ÿU‹ìjþhH"@ he@ d¡    PƒìSVW¡ 0@ 1Eø3ÅP�Eðd£    ‰eèÇEü    h  @ è*ÿÿÿƒÄ…ÀtU‹E-  @ Ph  @ èPÿÿÿƒÄ…Àt;‹@$Áè÷ÐƒàÇEüþÿÿÿ‹Mðd‰    Y_^[‹å]Ã‹Eì‹‹3Ò=  À”Â‹ÂÃ‹eèÇEüþÿÿÿ3À‹Mðd‰    Y_^[‹å]ÃÌÿ%¸ @ ÿ%´ @ ÌÌhe@ dÿ5    ‹D$‰l$�l$+àSVW¡ 0@ 1Eü3ÅP‰eèÿuø‹EüÇEüþÿÿÿ‰Eø�Eðd£    Ã‹Mðd‰    Y__^[‹å]QÃ‹ÿU‹ìÿuÿuÿuÿuh‡@ h 0@ èç   ƒÄ]Ã‹ÿVh   h   3öVèÙ   ƒÄ…ÀtVVVVVèÂ   ƒÄ^Ã3ÀÃ‹ÿU‹ìƒì¡ 0@ ƒeø ƒeü SW¿Næ@»»  ÿÿ;Çt…Ãt	÷Ð£0@ ë`V�EøPÿ< @ ‹uü3uøÿ @ 3ðÿ @ 3ðÿ @ 3ð�EðPÿ @ ‹Eô3Eð3ð;÷u¾Oæ@»ë…óu‹ÆÁàð‰5 0@ ÷Ö‰50@ ^_[ÉÃÿ%t @ ÿ%x @ ÿ%| @ ÿ%€ @ ÿ%„ @ ÿ%� @ ÿ%” @ ÿ%˜ @ ÿ%Ð @ Pdÿ5    �D$+d$SVW‰(‹è¡ 0@ 3ÅP‰EðÿuüÇEüÿÿÿÿ�Eôd£    Ã‹Môd‰    Y__^[‹å]QÃ‹Mð3Íè¯÷ÿÿéÝÿÿÿ�MÔÿ%T @ ‹T$�B‹JÌ3Èè�÷ÿÿ‹Jü3Èè†÷ÿÿ¸l"@ ésÿÿÿ                                                                                                                                                                                                                                                     ¸#  Ê#  Ü#  ˆ)  r)  b)  H)  4)  )  ú(  æ(  Ò(  ´(  ¬(  –(  ž)      ú#  à$  %  Ê%  &  d&  ®&  ¤$      ('  Ä'  Ö'  è'  þ'  (  ((  6(  ¦'  H(  Z(  t(  †(  '  '   '  –'  ‚'  l'  ^'  R'  F'  >'  >(  0'  ¶'  ¸)          –@         W@ Š@                     ¬MoO       l   €!  €  @0@ ˜0@ bad allocation      H                                                            0@ ð!@    RSDSÑŒ³´�J¨!öÌëLZ    c:\users\seld\documents\visual studio 2010\Projects\hiddeninp\Release\hiddeninp.pdb     e  æ                  þÿÿÿ    Ðÿÿÿ    þÿÿÿ@ @     þÿÿÿ    Ìÿÿÿ    þÿÿÿ    :@     þÿÿÿ    Øÿÿÿ    þÿÿÿË@ ß@ ÿÿÿÿÝ@ "“   d"@                        à"          ì#      $#          ô&  D   H#          (  h                       ¸#  Ê#  Ü#  ˆ)  r)  b)  H)  4)  )  ú(  æ(  Ò(  ´(  ¬(  –(  ž)      ú#  à$  %  Ê%  &  d&  ®&  ¤$      ('  Ä'  Ö'  è'  þ'  (  ((  6(  ¦'  H(  Z(  t(  †(  '  '   '  –'  ‚'  l'  ^'  R'  F'  >'  >(  0'  ¶'  ¸)      •GetConsoleMode  ·SetConsoleMode  ;GetStdHandle  KERNEL32.dll   ??$?6DU?$char_traits@D@std@@V?$allocator@D@1@@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@AAV10@ABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z ‘?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A  J?cin@std@@3V?$basic_istream@DU?$char_traits@D@std@@@1@A Â ??$getline@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@YAAAV?$basic_istream@DU?$char_traits@D@std@@@0@AAV10@AAV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@0@@Z ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01@P6AAAV01@AAV01@@Z@Z  _??1?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ  {??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAE@XZ  ³?endl@std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@1@AAV21@@Z  MSVCP90.dll _amsg_exit  Ÿ __getmainargs ,_cexit  |_exit f _XcptFilter Ìexit    __initenv _initterm _initterm_e <_configthreadlocale ã __setusermatherr  _adjust_fdiv  Ë __p__commode  Ï __p__fmode  j_encode_pointer à __set_app_type  K_crt_debugger_hook  C ?terminate@@YAXXZ MSVCR90.dll æ_unlock – __dllonexit v_lock _onexit `_decode_pointer s_except_handler4_common _invoke_watson  ?_controlfp_s  ½InterlockedExchange !Sleep ºInterlockedCompareExchange  -TerminateProcess  ©GetCurrentProcess >UnhandledExceptionFilter  SetUnhandledExceptionFilter ÑIsDebuggerPresent TQueryPerformanceCounter fGetTickCount  ­GetCurrentThreadId  ªGetCurrentProcessId OGetSystemTimeAsFileTime s __CxxFrameHandler3                                                    Næ@»±¿Dÿÿÿÿÿÿÿÿþÿÿÿ   $!@                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         €   8  €                 P  €                 h  €              	  €                 	  �    @  (  ä      ÈC  V  ä      (4   V S _ V E R S I O N _ I N F O     ½ïþ                                          †   S t r i n g F i l e I n f o   b   0 4 0 9 0 4 b 0   Ê Q  F i l e D e s c r i p t i o n     R e a d s   f r o m   s t d i n   w i t h o u t   l e a k i n g   i n f o   t o   t h e   t e r m i n a l   a n d   o u t p u t s   b a c k   t o   s t d o u t     6   F i l e V e r s i o n     1 ,   0 ,   0 ,   0     8   I n t e r n a l N a m e   h i d d e n i n p u t   P   L e g a l C o p y r i g h t   J o r d i   B o g g i a n o   -   2 0 1 2   H   O r i g i n a l F i l e n a m e   h i d d e n i n p u t . e x e   :   P r o d u c t N a m e     H i d d e n   I n p u t     :   P r o d u c t V e r s i o n   1 ,   0 ,   0 ,   0     D    V a r F i l e I n f o     $    T r a n s l a t i o n     	°<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="x86" publicKeyToken="1fc8b3b9a1e18e3b"></assemblyIdentity>
    </dependentAssembly>
  </dependency>
</assembly>PAPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDINGPADDINGXXPADDING   @  00!0/080F0L0T0^0d0n0{0‰0—0¡0¨0®0³0¸0½0Â0È0Ð0ä0ÿ01#1-1@1J1O1T1v1{1„1‰1–1§1­1´1È1Í1Ó1Û1á1ç1ô1ú12"2*23292A2M2_2j2p2¹2¿2Ç2Î2Ó2Ù2ß2ç2í2ô2û2333%303N3T3Z3`3f3l3s3z3�3ˆ3�3–3�3¥3­3µ3Á3Ê3Ï3Õ3ß3è3ó3ÿ34444%4;4B4‹4‘4š4¡4¬4²4Æ4Û4æ4þ45!5^5c5„5‰5¨5H6M6_6}6‘6—6 777*7w7|7Á7ä7ñ7ý7888=8E8P8V8\8b8h8n8t8z8€8œ8â89      $   Ü0è0ì01 1t1x12 2@2\2`2h2t2 0     0                                                                                                                                                  <?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Descriptor;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
/**
 * JSON descriptor.
 *
 * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class JsonDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = [])
    {
        $this->writeData($this->getInputArgumentData($argument), $options);
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = [])
    {
        $this->writeData($this->getInputOptionData($option), $options);
        if ($option->isNegatable()) {
            $this->writeData($this->getInputOptionData($option, \true), $options);
        }
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = [])
    {
        $this->writeData($this->getInputDefinitionData($definition), $options);
    }
    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = [])
    {
        $this->writeData($this->getCommandData($command, $options['short'] ?? \false), $options);
    }
    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = [])
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace, \true);
        $commands = [];
        foreach ($description->getCommands() as $command) {
            $commands[] = $this->getCommandData($command, $options['short'] ?? \false);
        }
        $data = [];
        if ('UNKNOWN' !== $application->getName()) {
            $data['application']['name'] = $application->getName();
            if ('UNKNOWN' !== $application->getVersion()) {
                $data['application']['version'] = $application->getVersion();
            }
        }
        $data['commands'] = $commands;
        if ($describedNamespace) {
            $data['namespace'] = $describedNamespace;
        } else {
            $data['namespaces'] = \array_values($description->getNamespaces());
        }
        $this->writeData($data, $options);
    }
    /**
     * Writes data as json.
     */
    private function writeData(array $data, array $options)
    {
        $flags = $options['json_encoding'] ?? 0;
        $this->write(\json_encode($data, $flags));
    }
    /**
     *
     */
    private function getInputArgumentData(InputArgument $argument) : array
    {
        return ['name' => $argument->getName(), 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => \preg_replace('/\\s*[\\r\\n]\\s*/', ' ', $argument->getDescription()), 'default' => \INF === $argument->getDefault() ? 'INF' : $argument->getDefault()];
    }
    /**
     *
     */
    private function getInputOptionData(InputOption $option, bool $negated = \false) : array
    {
        return $negated ? ['name' => '--no-' . $option->getName(), 'shortcut' => '', 'accept_value' => \false, 'is_value_required' => \false, 'is_multiple' => \false, 'description' => 'Negate the "--' . $option->getName() . '" option', 'default' => \false] : ['name' => '--' . $option->getName(), 'shortcut' => $option->getShortcut() ? '-' . \str_replace('|', '|-', $option->getShortcut()) : '', 'accept_value' => $option->acceptValue(), 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => \preg_replace('/\\s*[\\r\\n]\\s*/', ' ', $option->getDescription()), 'default' => \INF === $option->getDefault() ? 'INF' : $option->getDefault()];
    }
    /**
     *
     */
    private function getInputDefinitionData(InputDefinition $definition) : array
    {
        $inputArguments = [];
        foreach ($definition->getArguments() as $name => $argument) {
            $inputArguments[$name] = $this->getInputArgumentData($argument);
        }
        $inputOptions = [];
        foreach ($definition->getOptions() as $name => $option) {
            $inputOptions[$name] = $this->getInputOptionData($option);
            if ($option->isNegatable()) {
                $inputOptions['no-' . $name] = $this->getInputOptionData($option, \true);
            }
        }
        return ['arguments' => $inputArguments, 'options' => $inputOptions];
    }
    /**
     *
     */
    private function getCommandData(Command $command, bool $short = \false) : array
    {
        $data = ['name' => $command->getName(), 'description' => $command->getDescription()];
        if ($short) {
            $data += ['usage' => $command->getAliases()];
        } else {
            $command->mergeApplicationDefinition(\false);
            $data += ['usage' => \array_merge([$command->getSynopsis()], $command->getUsages(), $command->getAliases()), 'help' => $command->getProcessedHelp(), 'definition' => $this->getInputDefinitionData($command->getDefinition())];
        }
        $data['hidden'] = $command->isHidden();
        return $data;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Descriptor;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Helper\Helper;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Markdown descriptor.
 *
 * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class MarkdownDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    public function describe(OutputInterface $output, object $object, array $options = [])
    {
        $decorated = $output->isDecorated();
        $output->setDecorated(\false);
        parent::describe($output, $object, $options);
        $output->setDecorated($decorated);
    }
    /**
     * {@inheritdoc}
     */
    protected function write(string $content, bool $decorated = \true)
    {
        parent::write($content, $decorated);
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = [])
    {
        $this->write('#### `' . ($argument->getName() ?: '<none>') . "`\n\n" . ($argument->getDescription() ? \preg_replace('/\\s*[\\r\\n]\\s*/', "\n", $argument->getDescription()) . "\n\n" : '') . '* Is required: ' . ($argument->isRequired() ? 'yes' : 'no') . '
* Is array: ' . ($argument->isArray() ? 'yes' : 'no') . '
* Default: `' . \str_replace("\n", '', \var_export($argument->getDefault(), \true)) . '`');
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = [])
    {
        $name = '--' . $option->getName();
        if ($option->isNegatable()) {
            $name .= '|--no-' . $option->getName();
        }
        if ($option->getShortcut()) {
            $name .= '|-' . \str_replace('|', '|-', $option->getShortcut()) . '';
        }
        $this->write('#### `' . $name . '`

' . ($option->getDescription() ? \preg_replace('/\\s*[\\r\\n]\\s*/', "\n", $option->getDescription()) . "\n\n" : '') . '* Accept value: ' . ($option->acceptValue() ? 'yes' : 'no') . '
* Is value required: ' . ($option->isValueRequired() ? 'yes' : 'no') . '
* Is multiple: ' . ($option->isArray() ? 'yes' : 'no') . '
* Is negatable: ' . ($option->isNegatable() ? 'yes' : 'no') . '
* Default: `' . \str_replace("\n", '', \var_export($option->getDefault(), \true)) . '`');
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = [])
    {
        if ($showArguments = \count($definition->getArguments()) > 0) {
            $this->write('### Arguments');
            foreach ($definition->getArguments() as $argument) {
                $this->write("\n\n");
                if (null !== ($describeInputArgument = $this->describeInputArgument($argument))) {
                    $this->write($describeInputArgument);
                }
            }
        }
        if (\count($definition->getOptions()) > 0) {
            if ($showArguments) {
                $this->write("\n\n");
            }
            $this->write('### Options');
            foreach ($definition->getOptions() as $option) {
                $this->write("\n\n");
                if (null !== ($describeInputOption = $this->describeInputOption($option))) {
                    $this->write($describeInputOption);
                }
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = [])
    {
        if ($options['short'] ?? \false) {
            $this->write('`' . $command->getName() . "`\n" . \str_repeat('-', Helper::width($command->getName()) + 2) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . '### Usage

' . \array_reduce($command->getAliases(), function ($carry, $usage) {
                return $carry . '* `' . $usage . '`
';
            }));
            return;
        }
        $command->mergeApplicationDefinition(\false);
        $this->write('`' . $command->getName() . "`\n" . \str_repeat('-', Helper::width($command->getName()) + 2) . "\n\n" . ($command->getDescription() ? $command->getDescription() . "\n\n" : '') . '### Usage

' . \array_reduce(\array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()), function ($carry, $usage) {
            return $carry . '* `' . $usage . '`
';
        }));
        if ($help = $command->getProcessedHelp()) {
            $this->write("\n");
            $this->write($help);
        }
        $definition = $command->getDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->write("\n\n");
            $this->describeInputDefinition($definition);
        }
    }
    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = [])
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace);
        $title = $this->getApplicationTitle($application);
        $this->write($title . "\n" . \str_repeat('=', Helper::width($title)));
        foreach ($description->getNamespaces() as $namespace) {
            if (ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                $this->write("\n\n");
                $this->write('**' . $namespace['id'] . ':**');
            }
            $this->write("\n\n");
            $this->write(\implode("\n", \array_map(function ($commandName) use($description) {
                return \sprintf('* [`%s`](#%s)', $commandName, \str_replace(':', '', $description->getCommand($commandName)->getName()));
            }, $namespace['commands'])));
        }
        foreach ($description->getCommands() as $command) {
            $this->write("\n\n");
            if (null !== ($describeCommand = $this->describeCommand($command, $options))) {
                $this->write($describeCommand);
            }
        }
    }
    /**
     *
     */
    private function getApplicationTitle(Application $application) : string
    {
        if ('UNKNOWN' !== $application->getName()) {
            if ('UNKNOWN' !== $application->getVersion()) {
                return \sprintf('%s %s', $application->getName(), $application->getVersion());
            }
            return $application->getName();
        }
        return 'Console Tool';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Descriptor;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Jean-FranÃ§ois Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
abstract class Descriptor implements DescriptorInterface
{
    /**
     * @var OutputInterface
     */
    protected $output;
    /**
     * {@inheritdoc}
     */
    public function describe(OutputInterface $output, object $object, array $options = [])
    {
        $this->output = $output;
        switch (\true) {
            case $object instanceof InputArgument:
                $this->describeInputArgument($object, $options);
                break;
            case $object instanceof InputOption:
                $this->describeInputOption($object, $options);
                break;
            case $object instanceof InputDefinition:
                $this->describeInputDefinition($object, $options);
                break;
            case $object instanceof Command:
                $this->describeCommand($object, $options);
                break;
            case $object instanceof Application:
                $this->describeApplication($object, $options);
                break;
            default:
                throw new InvalidArgumentException(\sprintf('Object of type "%s" is not describable.', \get_debug_type($object)));
        }
    }
    /**
     * Writes content to output.
     */
    protected function write(string $content, bool $decorated = \false)
    {
        $this->output->write($content, \false, $decorated ? OutputInterface::OUTPUT_NORMAL : OutputInterface::OUTPUT_RAW);
    }
    /**
     * Describes an InputArgument instance.
     */
    protected abstract function describeInputArgument(InputArgument $argument, array $options = []);
    /**
     * Describes an InputOption instance.
     */
    protected abstract function describeInputOption(InputOption $option, array $options = []);
    /**
     * Describes an InputDefinition instance.
     */
    protected abstract function describeInputDefinition(InputDefinition $definition, array $options = []);
    /**
     * Describes a Command instance.
     */
    protected abstract function describeCommand(Command $command, array $options = []);
    /**
     * Describes an Application instance.
     */
    protected abstract function describeApplication(Application $application, array $options = []);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Descriptor;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
/**
 * XML descriptor.
 *
 * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class XmlDescriptor extends Descriptor
{
    /**
     *
     */
    public function getInputDefinitionDocument(InputDefinition $definition) : \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($definitionXML = $dom->createElement('definition'));
        $definitionXML->appendChild($argumentsXML = $dom->createElement('arguments'));
        foreach ($definition->getArguments() as $argument) {
            $this->appendDocument($argumentsXML, $this->getInputArgumentDocument($argument));
        }
        $definitionXML->appendChild($optionsXML = $dom->createElement('options'));
        foreach ($definition->getOptions() as $option) {
            $this->appendDocument($optionsXML, $this->getInputOptionDocument($option));
        }
        return $dom;
    }
    /**
     *
     */
    public function getCommandDocument(Command $command, bool $short = \false) : \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($commandXML = $dom->createElement('command'));
        $commandXML->setAttribute('id', $command->getName());
        $commandXML->setAttribute('name', $command->getName());
        $commandXML->setAttribute('hidden', $command->isHidden() ? 1 : 0);
        $commandXML->appendChild($usagesXML = $dom->createElement('usages'));
        $commandXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode(\str_replace("\n", "\n ", $command->getDescription())));
        if ($short) {
            foreach ($command->getAliases() as $usage) {
                $usagesXML->appendChild($dom->createElement('usage', $usage));
            }
        } else {
            $command->mergeApplicationDefinition(\false);
            foreach (\array_merge([$command->getSynopsis()], $command->getAliases(), $command->getUsages()) as $usage) {
                $usagesXML->appendChild($dom->createElement('usage', $usage));
            }
            $commandXML->appendChild($helpXML = $dom->createElement('help'));
            $helpXML->appendChild($dom->createTextNode(\str_replace("\n", "\n ", $command->getProcessedHelp())));
            $definitionXML = $this->getInputDefinitionDocument($command->getDefinition());
            $this->appendDocument($commandXML, $definitionXML->getElementsByTagName('definition')->item(0));
        }
        return $dom;
    }
    /**
     *
     */
    public function getApplicationDocument(Application $application, string $namespace = null, bool $short = \false) : \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($rootXml = $dom->createElement('symfony'));
        if ('UNKNOWN' !== $application->getName()) {
            $rootXml->setAttribute('name', $application->getName());
            if ('UNKNOWN' !== $application->getVersion()) {
                $rootXml->setAttribute('version', $application->getVersion());
            }
        }
        $rootXml->appendChild($commandsXML = $dom->createElement('commands'));
        $description = new ApplicationDescription($application, $namespace, \true);
        if ($namespace) {
            $commandsXML->setAttribute('namespace', $namespace);
        }
        foreach ($description->getCommands() as $command) {
            $this->appendDocument($commandsXML, $this->getCommandDocument($command, $short));
        }
        if (!$namespace) {
            $rootXml->appendChild($namespacesXML = $dom->createElement('namespaces'));
            foreach ($description->getNamespaces() as $namespaceDescription) {
                $namespacesXML->appendChild($namespaceArrayXML = $dom->createElement('namespace'));
                $namespaceArrayXML->setAttribute('id', $namespaceDescription['id']);
                foreach ($namespaceDescription['commands'] as $name) {
                    $namespaceArrayXML->appendChild($commandXML = $dom->createElement('command'));
                    $commandXML->appendChild($dom->createTextNode($name));
                }
            }
        }
        return $dom;
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = [])
    {
        $this->writeDocument($this->getInputArgumentDocument($argument));
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = [])
    {
        $this->writeDocument($this->getInputOptionDocument($option));
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = [])
    {
        $this->writeDocument($this->getInputDefinitionDocument($definition));
    }
    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = [])
    {
        $this->writeDocument($this->getCommandDocument($command, $options['short'] ?? \false));
    }
    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = [])
    {
        $this->writeDocument($this->getApplicationDocument($application, $options['namespace'] ?? null, $options['short'] ?? \false));
    }
    /**
     * Appends document children to parent node.
     */
    private function appendDocument(\DOMNode $parentNode, \DOMNode $importedParent)
    {
        foreach ($importedParent->childNodes as $childNode) {
            $parentNode->appendChild($parentNode->ownerDocument->importNode($childNode, \true));
        }
    }
    /**
     * Writes DOM document.
     */
    private function writeDocument(\DOMDocument $dom)
    {
        $dom->formatOutput = \true;
        $this->write($dom->saveXML());
    }
    /**
     *
     */
    private function getInputArgumentDocument(InputArgument $argument) : \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($objectXML = $dom->createElement('argument'));
        $objectXML->setAttribute('name', $argument->getName());
        $objectXML->setAttribute('is_required', $argument->isRequired() ? 1 : 0);
        $objectXML->setAttribute('is_array', $argument->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($argument->getDescription()));
        $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
        $defaults = \is_array($argument->getDefault()) ? $argument->getDefault() : (\is_bool($argument->getDefault()) ? [\var_export($argument->getDefault(), \true)] : ($argument->getDefault() ? [$argument->getDefault()] : []));
        foreach ($defaults as $default) {
            $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
            $defaultXML->appendChild($dom->createTextNode($default));
        }
        return $dom;
    }
    /**
     *
     */
    private function getInputOptionDocument(InputOption $option) : \DOMDocument
    {
        $dom = new \DOMDocument('1.0', 'UTF-8');
        $dom->appendChild($objectXML = $dom->createElement('option'));
        $objectXML->setAttribute('name', '--' . $option->getName());
        $pos = \strpos($option->getShortcut() ?? '', '|');
        if (\false !== $pos) {
            $objectXML->setAttribute('shortcut', '-' . \Phabel\Target\Php80\Polyfill::substr($option->getShortcut(), 0, $pos));
            $objectXML->setAttribute('shortcuts', '-' . \str_replace('|', '|-', $option->getShortcut()));
        } else {
            $objectXML->setAttribute('shortcut', $option->getShortcut() ? '-' . $option->getShortcut() : '');
        }
        $objectXML->setAttribute('accept_value', $option->acceptValue() ? 1 : 0);
        $objectXML->setAttribute('is_value_required', $option->isValueRequired() ? 1 : 0);
        $objectXML->setAttribute('is_multiple', $option->isArray() ? 1 : 0);
        $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
        $descriptionXML->appendChild($dom->createTextNode($option->getDescription()));
        if ($option->acceptValue()) {
            $defaults = \is_array($option->getDefault()) ? $option->getDefault() : (\is_bool($option->getDefault()) ? [\var_export($option->getDefault(), \true)] : ($option->getDefault() ? [$option->getDefault()] : []));
            $objectXML->appendChild($defaultsXML = $dom->createElement('defaults'));
            if (!empty($defaults)) {
                foreach ($defaults as $default) {
                    $defaultsXML->appendChild($defaultXML = $dom->createElement('default'));
                    $defaultXML->appendChild($dom->createTextNode($default));
                }
            }
        }
        if ($option->isNegatable()) {
            $dom->appendChild($objectXML = $dom->createElement('option'));
            $objectXML->setAttribute('name', '--no-' . $option->getName());
            $objectXML->setAttribute('shortcut', '');
            $objectXML->setAttribute('accept_value', 0);
            $objectXML->setAttribute('is_value_required', 0);
            $objectXML->setAttribute('is_multiple', 0);
            $objectXML->appendChild($descriptionXML = $dom->createElement('description'));
            $descriptionXML->appendChild($dom->createTextNode('Negate the "--' . $option->getName() . '" option'));
        }
        return $dom;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Descriptor;

use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Descriptor interface.
 *
 * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
 */
interface DescriptorInterface
{
    /**
     *
     */
    public function describe(OutputInterface $output, object $object, array $options = []);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Descriptor;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Helper\Helper;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
/**
 * Text descriptor.
 *
 * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
 *
 * @internal
 */
class TextDescriptor extends Descriptor
{
    /**
     * {@inheritdoc}
     */
    protected function describeInputArgument(InputArgument $argument, array $options = [])
    {
        if (null !== $argument->getDefault() && (!\is_array($argument->getDefault()) || \count($argument->getDefault()))) {
            $default = \sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($argument->getDefault()));
        } else {
            $default = '';
        }
        $totalWidth = $options['total_width'] ?? Helper::width($argument->getName());
        $spacingWidth = $totalWidth - \strlen($argument->getName());
        $this->writeText(\sprintf(
            '  <info>%s</info>  %s%s%s',
            $argument->getName(),
            \str_repeat(' ', $spacingWidth),
            // + 4 = 2 spaces before <info>, 2 spaces after </info>
            \preg_replace('/\\s*[\\r\\n]\\s*/', "\n" . \str_repeat(' ', $totalWidth + 4), $argument->getDescription()),
            $default
        ), $options);
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputOption(InputOption $option, array $options = [])
    {
        if ($option->acceptValue() && null !== $option->getDefault() && (!\is_array($option->getDefault()) || \count($option->getDefault()))) {
            $default = \sprintf('<comment> [default: %s]</comment>', $this->formatDefaultValue($option->getDefault()));
        } else {
            $default = '';
        }
        $value = '';
        if ($option->acceptValue()) {
            $value = '=' . \strtoupper($option->getName());
            if ($option->isValueOptional()) {
                $value = '[' . $value . ']';
            }
        }
        $totalWidth = $options['total_width'] ?? $this->calculateTotalWidthForOptions([$option]);
        $synopsis = \sprintf('%s%s', $option->getShortcut() ? \sprintf('-%s, ', $option->getShortcut()) : '    ', \sprintf($option->isNegatable() ? '--%1$s|--no-%1$s' : '--%1$s%2$s', $option->getName(), $value));
        $spacingWidth = $totalWidth - Helper::width($synopsis);
        $this->writeText(\sprintf(
            '  <info>%s</info>  %s%s%s%s',
            $synopsis,
            \str_repeat(' ', $spacingWidth),
            // + 4 = 2 spaces before <info>, 2 spaces after </info>
            \preg_replace('/\\s*[\\r\\n]\\s*/', "\n" . \str_repeat(' ', $totalWidth + 4), $option->getDescription()),
            $default,
            $option->isArray() ? '<comment> (multiple values allowed)</comment>' : ''
        ), $options);
    }
    /**
     * {@inheritdoc}
     */
    protected function describeInputDefinition(InputDefinition $definition, array $options = [])
    {
        $totalWidth = $this->calculateTotalWidthForOptions($definition->getOptions());
        foreach ($definition->getArguments() as $argument) {
            $totalWidth = \max($totalWidth, Helper::width($argument->getName()));
        }
        if ($definition->getArguments()) {
            $this->writeText('<comment>Arguments:</comment>', $options);
            $this->writeText("\n");
            foreach ($definition->getArguments() as $argument) {
                $this->describeInputArgument($argument, \array_merge($options, ['total_width' => $totalWidth]));
                $this->writeText("\n");
            }
        }
        if ($definition->getArguments() && $definition->getOptions()) {
            $this->writeText("\n");
        }
        if ($definition->getOptions()) {
            $laterOptions = [];
            $this->writeText('<comment>Options:</comment>', $options);
            foreach ($definition->getOptions() as $option) {
                if (\strlen($option->getShortcut() ?? '') > 1) {
                    $laterOptions[] = $option;
                    continue;
                }
                $this->writeText("\n");
                $this->describeInputOption($option, \array_merge($options, ['total_width' => $totalWidth]));
            }
            foreach ($laterOptions as $option) {
                $this->writeText("\n");
                $this->describeInputOption($option, \array_merge($options, ['total_width' => $totalWidth]));
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    protected function describeCommand(Command $command, array $options = [])
    {
        $command->mergeApplicationDefinition(\false);
        if ($description = $command->getDescription()) {
            $this->writeText('<comment>Description:</comment>', $options);
            $this->writeText("\n");
            $this->writeText('  ' . $description);
            $this->writeText("\n\n");
        }
        $this->writeText('<comment>Usage:</comment>', $options);
        foreach (\array_merge([$command->getSynopsis(\true)], $command->getAliases(), $command->getUsages()) as $usage) {
            $this->writeText("\n");
            $this->writeText('  ' . OutputFormatter::escape($usage), $options);
        }
        $this->writeText("\n");
        $definition = $command->getDefinition();
        if ($definition->getOptions() || $definition->getArguments()) {
            $this->writeText("\n");
            $this->describeInputDefinition($definition, $options);
            $this->writeText("\n");
        }
        $help = $command->getProcessedHelp();
        if ($help && $help !== $description) {
            $this->writeText("\n");
            $this->writeText('<comment>Help:</comment>', $options);
            $this->writeText("\n");
            $this->writeText('  ' . \str_replace("\n", "\n  ", $help), $options);
            $this->writeText("\n");
        }
    }
    /**
     * {@inheritdoc}
     */
    protected function describeApplication(Application $application, array $options = [])
    {
        $describedNamespace = $options['namespace'] ?? null;
        $description = new ApplicationDescription($application, $describedNamespace);
        if (isset($options['raw_text']) && $options['raw_text']) {
            $width = $this->getColumnWidth($description->getCommands());
            foreach ($description->getCommands() as $command) {
                $this->writeText(\sprintf("%-{$width}s %s", $command->getName(), $command->getDescription()), $options);
                $this->writeText("\n");
            }
        } else {
            if ('' != ($help = $application->getHelp())) {
                $this->writeText("{$help}\n\n", $options);
            }
            $this->writeText("<comment>Usage:</comment>\n", $options);
            $this->writeText("  command [options] [arguments]\n\n", $options);
            $this->describeInputDefinition(new InputDefinition($application->getDefinition()->getOptions()), $options);
            $this->writeText("\n");
            $this->writeText("\n");
            $commands = $description->getCommands();
            $namespaces = $description->getNamespaces();
            if ($describedNamespace && $namespaces) {
                // make sure all alias commands are included when describing a specific namespace
                $describedNamespaceInfo = \reset($namespaces);
                foreach ($describedNamespaceInfo['commands'] as $name) {
                    $commands[$name] = $description->getCommand($name);
                }
            }
            // calculate max. width based on available commands per namespace
            $width = $this->getColumnWidth(\array_merge(...\array_values(\array_map(function ($namespace) use($commands) {
                return \array_intersect($namespace['commands'], \array_keys($commands));
            }, \array_values($namespaces)))));
            if ($describedNamespace) {
                $this->writeText(\sprintf('<comment>Available commands for the "%s" namespace:</comment>', $describedNamespace), $options);
            } else {
                $this->writeText('<comment>Available commands:</comment>', $options);
            }
            foreach ($namespaces as $namespace) {
                $namespace['commands'] = \array_filter($namespace['commands'], function ($name) use($commands) {
                    return isset($commands[$name]);
                });
                if (!$namespace['commands']) {
                    continue;
                }
                if (!$describedNamespace && ApplicationDescription::GLOBAL_NAMESPACE !== $namespace['id']) {
                    $this->writeText("\n");
                    $this->writeText(' <comment>' . $namespace['id'] . '</comment>', $options);
                }
                foreach ($namespace['commands'] as $name) {
                    $this->writeText("\n");
                    $spacingWidth = $width - Helper::width($name);
                    $command = $commands[$name];
                    $commandAliases = $name === $command->getName() ? $this->getCommandAliasesText($command) : '';
                    $this->writeText(\sprintf('  <info>%s</info>%s%s', $name, \str_repeat(' ', $spacingWidth), $commandAliases . $command->getDescription()), $options);
                }
            }
            $this->writeText("\n");
        }
    }
    /**
     * {@inheritdoc}
     */
    private function writeText(string $content, array $options = [])
    {
        $this->write(isset($options['raw_text']) && $options['raw_text'] ? \Phabel\Target\Php80\Polyfill::strip_tags($content) : $content, isset($options['raw_output']) ? !$options['raw_output'] : \true);
    }
    /**
     * Formats command aliases to show them in the command description.
     */
    private function getCommandAliasesText(Command $command) : string
    {
        $text = '';
        $aliases = $command->getAliases();
        if ($aliases) {
            $text = '[' . \implode('|', $aliases) . '] ';
        }
        return $text;
    }
    /**
     * Formats input option/argument default value.
     *
     * @param mixed $default
     */
    private function formatDefaultValue($default) : string
    {
        if (\INF === $default) {
            return 'INF';
        }
        if (\is_string($default)) {
            $default = OutputFormatter::escape($default);
        } elseif (\is_array($default)) {
            foreach ($default as $key => $value) {
                if (\is_string($value)) {
                    $default[$key] = OutputFormatter::escape($value);
                }
            }
        }
        return \str_replace('\\\\', '\\', \json_encode($default, \JSON_UNESCAPED_SLASHES | \JSON_UNESCAPED_UNICODE));
    }
    /**
     * @param array<(Command | string)> $commands
     */
    private function getColumnWidth(array $commands) : int
    {
        $widths = [];
        foreach ($commands as $command) {
            if ($command instanceof Command) {
                $widths[] = Helper::width($command->getName());
                foreach ($command->getAliases() as $alias) {
                    $widths[] = Helper::width($alias);
                }
            } else {
                $widths[] = Helper::width($command);
            }
        }
        return $widths ? \max($widths) + 2 : 0;
    }
    /**
     * @param InputOption[] $options
     */
    private function calculateTotalWidthForOptions(array $options) : int
    {
        $totalWidth = 0;
        foreach ($options as $option) {
            // "-" + shortcut + ", --" + name
            $nameLength = 1 + \max(Helper::width($option->getShortcut()), 1) + 4 + Helper::width($option->getName());
            if ($option->isNegatable()) {
                $nameLength += 6 + Helper::width($option->getName());
                // |--no- + name
            } elseif ($option->acceptValue()) {
                $valueLength = 1 + Helper::width($option->getName());
                // = + value
                $valueLength += $option->isValueOptional() ? 2 : 0;
                // [ + ]
                $nameLength += $valueLength;
            }
            $totalWidth = \max($totalWidth, $nameLength);
        }
        return $totalWidth;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Descriptor;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Exception\CommandNotFoundException;
/**
 * @author Jean-FranÃ§ois Simon <jeanfrancois.simon@sensiolabs.com>
 *
 * @internal
 */
class ApplicationDescription
{
    public const GLOBAL_NAMESPACE = '_global';
    private $application;
    private $namespace;
    private $showHidden;
    /**
     * @var array
     */
    private $namespaces;
    /**
     * @var array<string, Command>
     */
    private $commands;
    /**
     * @var array<string, Command>
     */
    private $aliases;
    /**
     *
     */
    public function __construct(Application $application, string $namespace = null, bool $showHidden = \false)
    {
        $this->application = $application;
        $this->namespace = $namespace;
        $this->showHidden = $showHidden;
    }
    /**
     *
     */
    public function getNamespaces() : array
    {
        if (null === $this->namespaces) {
            $this->inspectApplication();
        }
        return $this->namespaces;
    }
    /**
     * @return Command[]
     */
    public function getCommands() : array
    {
        if (null === $this->commands) {
            $this->inspectApplication();
        }
        return $this->commands;
    }
    /**
     * @throws CommandNotFoundException
     */
    public function getCommand(string $name) : Command
    {
        if (!isset($this->commands[$name]) && !isset($this->aliases[$name])) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }
        return $this->commands[$name] ?? $this->aliases[$name];
    }
    /**
     *
     */
    private function inspectApplication()
    {
        $this->commands = [];
        $this->namespaces = [];
        $all = $this->application->all($this->namespace ? $this->application->findNamespace($this->namespace) : null);
        foreach ($this->sortCommands($all) as $namespace => $commands) {
            $names = [];
            /** @var Command $command */
            foreach ($commands as $name => $command) {
                if (!$command->getName() || !$this->showHidden && $command->isHidden()) {
                    continue;
                }
                if ($command->getName() === $name) {
                    $this->commands[$name] = $command;
                } else {
                    $this->aliases[$name] = $command;
                }
                $names[] = $name;
            }
            $this->namespaces[$namespace] = ['id' => $namespace, 'commands' => $names];
        }
    }
    /**
     *
     */
    private function sortCommands(array $commands) : array
    {
        $namespacedCommands = [];
        $globalCommands = [];
        $sortedCommands = [];
        foreach ($commands as $name => $command) {
            $key = $this->application->extractNamespace($name, 1);
            if (\in_array($key, ['', self::GLOBAL_NAMESPACE], \true)) {
                $globalCommands[$name] = $command;
            } else {
                $namespacedCommands[$key][$name] = $command;
            }
        }
        if ($globalCommands) {
            \ksort($globalCommands);
            $sortedCommands[self::GLOBAL_NAMESPACE] = $globalCommands;
        }
        if ($namespacedCommands) {
            \ksort($namespacedCommands);
            foreach ($namespacedCommands as $key => $commandsSet) {
                \ksort($commandsSet);
                $sortedCommands[$key] = $commandsSet;
            }
        }
        return $sortedCommands;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Command\CompleteCommand;
use PhabelVendor\Symfony\Component\Console\Command\DumpCompletionCommand;
use PhabelVendor\Symfony\Component\Console\Command\HelpCommand;
use PhabelVendor\Symfony\Component\Console\Command\LazyCommand;
use PhabelVendor\Symfony\Component\Console\Command\ListCommand;
use PhabelVendor\Symfony\Component\Console\Command\SignalableCommandInterface;
use PhabelVendor\Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionInput;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleCommandEvent;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleErrorEvent;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleSignalEvent;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleTerminateEvent;
use PhabelVendor\Symfony\Component\Console\Exception\CommandNotFoundException;
use PhabelVendor\Symfony\Component\Console\Exception\ExceptionInterface;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
use PhabelVendor\Symfony\Component\Console\Exception\NamespaceNotFoundException;
use PhabelVendor\Symfony\Component\Console\Exception\RuntimeException;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Helper\DebugFormatterHelper;
use PhabelVendor\Symfony\Component\Console\Helper\FormatterHelper;
use PhabelVendor\Symfony\Component\Console\Helper\Helper;
use PhabelVendor\Symfony\Component\Console\Helper\HelperSet;
use PhabelVendor\Symfony\Component\Console\Helper\ProcessHelper;
use PhabelVendor\Symfony\Component\Console\Helper\QuestionHelper;
use PhabelVendor\Symfony\Component\Console\Input\ArgvInput;
use PhabelVendor\Symfony\Component\Console\Input\ArrayInput;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputAwareInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutput;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Console\SignalRegistry\SignalRegistry;
use PhabelVendor\Symfony\Component\Console\Style\SymfonyStyle;
use PhabelVendor\Symfony\Component\ErrorHandler\ErrorHandler;
use PhabelVendor\Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
use PhabelVendor\Symfony\Contracts\Service\ResetInterface;
/**
 * An Application is the container for a collection of commands.
 *
 * It is the main entry point of a Console application.
 *
 * This class is optimized for a standard CLI environment.
 *
 * Usage:
 *
 *     $app = new Application('myapp', '1.0 (stable)');
 *     $app->add(new SimpleCommand());
 *     $app->run();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Application implements ResetInterface
{
    private $commands = [];
    private $wantHelps = \false;
    private $runningCommand;
    private $name;
    private $version;
    private $commandLoader;
    private $catchExceptions = \true;
    private $autoExit = \true;
    private $definition;
    private $helperSet;
    private $dispatcher;
    private $terminal;
    private $defaultCommand;
    private $singleCommand = \false;
    private $initialized;
    private $signalRegistry;
    private $signalsToDispatchEvent = [];
    /**
     *
     */
    public function __construct(string $name = 'UNKNOWN', string $version = 'UNKNOWN')
    {
        $this->name = $name;
        $this->version = $version;
        $this->terminal = new Terminal();
        $this->defaultCommand = 'list';
        if (\defined('SIGINT') && SignalRegistry::isSupported()) {
            $this->signalRegistry = new SignalRegistry();
            $this->signalsToDispatchEvent = [\SIGINT, \SIGTERM, \SIGUSR1, \SIGUSR2];
        }
    }
    /**
     * @final
     */
    public function setDispatcher(EventDispatcherInterface $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
    /**
     *
     */
    public function setCommandLoader(CommandLoaderInterface $commandLoader)
    {
        $this->commandLoader = $commandLoader;
    }
    /**
     *
     */
    public function getSignalRegistry() : SignalRegistry
    {
        if (!$this->signalRegistry) {
            throw new RuntimeException('Signals are not supported. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
        }
        return $this->signalRegistry;
    }
    /**
     *
     */
    public function setSignalsToDispatchEvent(int ...$signalsToDispatchEvent)
    {
        $this->signalsToDispatchEvent = $signalsToDispatchEvent;
    }
    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     *
     * @throws \Exception When running fails. Bypass this when {@link setCatchExceptions()}.
     */
    public function run(InputInterface $input = null, OutputInterface $output = null)
    {
        if (\function_exists('putenv')) {
            @\putenv('LINES=' . $this->terminal->getHeight());
            @\putenv('COLUMNS=' . $this->terminal->getWidth());
        }
        if (null === $input) {
            $input = new ArgvInput();
        }
        if (null === $output) {
            $output = new ConsoleOutput();
        }
        $renderException = function (\Throwable $e) use($output) {
            if ($output instanceof ConsoleOutputInterface) {
                $this->renderThrowable($e, $output->getErrorOutput());
            } else {
                $this->renderThrowable($e, $output);
            }
        };
        if ($phpHandler = \set_exception_handler($renderException)) {
            \restore_exception_handler();
            if (!\is_array($phpHandler) || !$phpHandler[0] instanceof ErrorHandler) {
                $errorHandler = \true;
            } elseif ($errorHandler = $phpHandler[0]->setExceptionHandler($renderException)) {
                $phpHandler[0]->setExceptionHandler($errorHandler);
            }
        }
        $this->configureIO($input, $output);
        try {
            $exitCode = $this->doRun($input, $output);
        } catch (\Exception $e) {
            if (!$this->catchExceptions) {
                throw $e;
            }
            $renderException($e);
            $exitCode = $e->getCode();
            if (\is_numeric($exitCode)) {
                $exitCode = (int) $exitCode;
                if (0 === $exitCode) {
                    $exitCode = 1;
                }
            } else {
                $exitCode = 1;
            }
        } finally {
            // if the exception handler changed, keep it
            // otherwise, unregister $renderException
            if (!$phpHandler) {
                if (\set_exception_handler($renderException) === $renderException) {
                    \restore_exception_handler();
                }
                \restore_exception_handler();
            } elseif (!$errorHandler) {
                $finalHandler = $phpHandler[0]->setExceptionHandler(null);
                if ($finalHandler !== $renderException) {
                    $phpHandler[0]->setExceptionHandler($finalHandler);
                }
            }
        }
        if ($this->autoExit) {
            if ($exitCode > 255) {
                $exitCode = 255;
            }
            exit($exitCode);
        }
        return $exitCode;
    }
    /**
     * Runs the current application.
     *
     * @return int 0 if everything went fine, or an error code
     */
    public function doRun(InputInterface $input, OutputInterface $output)
    {
        if (\true === $input->hasParameterOption(['--version', '-V'], \true)) {
            $output->writeln($this->getLongVersion());
            return 0;
        }
        try {
            // Makes ArgvInput::getFirstArgument() able to distinguish an option from an argument.
            $input->bind($this->getDefinition());
        } catch (ExceptionInterface $e) {
            // Errors must be ignored, full binding/validation happens later when the command is known.
        }
        $name = $this->getCommandName($input);
        if (\true === $input->hasParameterOption(['--help', '-h'], \true)) {
            if (!$name) {
                $name = 'help';
                $input = new ArrayInput(['command_name' => $this->defaultCommand]);
            } else {
                $this->wantHelps = \true;
            }
        }
        if (!$name) {
            $name = $this->defaultCommand;
            $definition = $this->getDefinition();
            $definition->setArguments(\array_merge($definition->getArguments(), ['command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name)]));
        }
        try {
            $this->runningCommand = null;
            // the command name MUST be the first element of the input
            $command = $this->find($name);
        } catch (\Throwable $e) {
            if (!($e instanceof CommandNotFoundException && !$e instanceof NamespaceNotFoundException) || 1 !== \count($alternatives = $e->getAlternatives()) || !$input->isInteractive()) {
                if (null !== $this->dispatcher) {
                    $event = new ConsoleErrorEvent($input, $output, $e);
                    $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
                    if (0 === $event->getExitCode()) {
                        return 0;
                    }
                    $e = $event->getError();
                }
                throw $e;
            }
            $alternative = $alternatives[0];
            $style = new SymfonyStyle($input, $output);
            $style->block(\sprintf("\nCommand \"%s\" is not defined.\n", $name), null, 'error');
            if (!$style->confirm(\sprintf('Do you want to run "%s" instead? ', $alternative), \false)) {
                if (null !== $this->dispatcher) {
                    $event = new ConsoleErrorEvent($input, $output, $e);
                    $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
                    return $event->getExitCode();
                }
                return 1;
            }
            $command = $this->find($alternative);
        }
        if ($command instanceof LazyCommand) {
            $command = $command->getCommand();
        }
        $this->runningCommand = $command;
        $exitCode = $this->doRunCommand($command, $input, $output);
        $this->runningCommand = null;
        return $exitCode;
    }
    /**
     * {@inheritdoc}
     */
    public function reset()
    {
    }
    /**
     *
     */
    public function setHelperSet(HelperSet $helperSet)
    {
        $this->helperSet = $helperSet;
    }
    /**
     * Get the helper set associated with the command.
     *
     * @return HelperSet
     */
    public function getHelperSet()
    {
        if (!$this->helperSet) {
            $this->helperSet = $this->getDefaultHelperSet();
        }
        return $this->helperSet;
    }
    /**
     *
     */
    public function setDefinition(InputDefinition $definition)
    {
        $this->definition = $definition;
    }
    /**
     * Gets the InputDefinition related to this Application.
     *
     * @return InputDefinition
     */
    public function getDefinition()
    {
        if (!$this->definition) {
            $this->definition = $this->getDefaultInputDefinition();
        }
        if ($this->singleCommand) {
            $inputDefinition = $this->definition;
            $inputDefinition->setArguments();
            return $inputDefinition;
        }
        return $this->definition;
    }
    /**
     * Adds suggestions to $suggestions for the current completion input (e.g. option or argument).
     */
    public function complete(CompletionInput $input, CompletionSuggestions $suggestions) : void
    {
        if (CompletionInput::TYPE_ARGUMENT_VALUE === $input->getCompletionType() && 'command' === $input->getCompletionName()) {
            $suggestions->suggestValues(\array_filter(\array_map(function (Command $command) {
                return $command->isHidden() ? null : $command->getName();
            }, $this->all())));
            return;
        }
        if (CompletionInput::TYPE_OPTION_NAME === $input->getCompletionType()) {
            $suggestions->suggestOptions($this->getDefinition()->getOptions());
            return;
        }
    }
    /**
     * Gets the help message.
     *
     * @return string
     */
    public function getHelp()
    {
        return $this->getLongVersion();
    }
    /**
     * Gets whether to catch exceptions or not during commands execution.
     *
     * @return bool
     */
    public function areExceptionsCaught()
    {
        return $this->catchExceptions;
    }
    /**
     * Sets whether to catch exceptions or not during commands execution.
     */
    public function setCatchExceptions(bool $boolean)
    {
        $this->catchExceptions = $boolean;
    }
    /**
     * Gets whether to automatically exit after a command execution or not.
     *
     * @return bool
     */
    public function isAutoExitEnabled()
    {
        return $this->autoExit;
    }
    /**
     * Sets whether to automatically exit after a command execution or not.
     */
    public function setAutoExit(bool $boolean)
    {
        $this->autoExit = $boolean;
    }
    /**
     * Gets the name of the application.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }
    /**
     * Sets the application name.
     */
    public function setName(string $name)
    {
        $this->name = $name;
    }
    /**
     * Gets the application version.
     *
     * @return string
     */
    public function getVersion()
    {
        return $this->version;
    }
    /**
     * Sets the application version.
     */
    public function setVersion(string $version)
    {
        $this->version = $version;
    }
    /**
     * Returns the long version of the application.
     *
     * @return string
     */
    public function getLongVersion()
    {
        if ('UNKNOWN' !== $this->getName()) {
            if ('UNKNOWN' !== $this->getVersion()) {
                return \sprintf('%s <info>%s</info>', $this->getName(), $this->getVersion());
            }
            return $this->getName();
        }
        return 'Console Tool';
    }
    /**
     * Registers a new command.
     *
     * @return Command
     */
    public function register(string $name)
    {
        return $this->add(new Command($name));
    }
    /**
     * Adds an array of command objects.
     *
     * If a Command is not enabled it will not be added.
     *
     * @param Command[] $commands An array of commands
     */
    public function addCommands(array $commands)
    {
        foreach ($commands as $command) {
            $this->add($command);
        }
    }
    /**
    * Adds a command object.
    *
    * If a command with the same name already exists, it will be overridden.
    If the command is not enabled it will not be added.
    *
    * @return (Command | null)
    */
    public function add(Command $command)
    {
        $this->init();
        $command->setApplication($this);
        if (!$command->isEnabled()) {
            $command->setApplication(null);
            return null;
        }
        if (!$command instanceof LazyCommand) {
            // Will throw if the command is not correctly initialized.
            $command->getDefinition();
        }
        if (!$command->getName()) {
            throw new LogicException(\sprintf('The command defined in "%s" cannot have an empty name.', \get_debug_type($command)));
        }
        $this->commands[$command->getName()] = $command;
        foreach ($command->getAliases() as $alias) {
            $this->commands[$alias] = $command;
        }
        return $command;
    }
    /**
     * Returns a registered command by name or alias.
     *
     * @return Command
     *
     * @throws CommandNotFoundException When given command name does not exist
     */
    public function get(string $name)
    {
        $this->init();
        if (!$this->has($name)) {
            throw new CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name));
        }
        // When the command has a different name than the one used at the command loader level
        if (!isset($this->commands[$name])) {
            throw new CommandNotFoundException(\sprintf('The "%s" command cannot be found because it is registered under multiple names. Make sure you don\'t set a different name via constructor or "setName()".', $name));
        }
        $command = $this->commands[$name];
        if ($this->wantHelps) {
            $this->wantHelps = \false;
            $helpCommand = $this->get('help');
            $helpCommand->setCommand($command);
            return $helpCommand;
        }
        return $command;
    }
    /**
     * Returns true if the command exists, false otherwise.
     *
     * @return bool
     */
    public function has(string $name)
    {
        $this->init();
        return isset($this->commands[$name]) || $this->commandLoader && $this->commandLoader->has($name) && $this->add($this->commandLoader->get($name));
    }
    /**
     * Returns an array of all unique namespaces used by currently registered commands.
     *
     * It does not return the global namespace which always exists.
     *
     * @return string[]
     */
    public function getNamespaces()
    {
        $namespaces = [];
        foreach ($this->all() as $command) {
            if ($command->isHidden()) {
                continue;
            }
            $namespaces[] = $this->extractAllNamespaces($command->getName());
            foreach ($command->getAliases() as $alias) {
                $namespaces[] = $this->extractAllNamespaces($alias);
            }
        }
        return \array_values(\array_unique(\array_filter(\array_merge([], ...$namespaces))));
    }
    /**
     * Finds a registered namespace by a name or an abbreviation.
     *
     * @return string
     *
     * @throws NamespaceNotFoundException When namespace is incorrect or ambiguous
     */
    public function findNamespace(string $namespace)
    {
        $allNamespaces = $this->getNamespaces();
        $expr = \implode('[^:]*:', \array_map('preg_quote', \explode(':', $namespace))) . '[^:]*';
        $namespaces = \preg_grep('{^' . $expr . '}', $allNamespaces);
        if (empty($namespaces)) {
            $message = \sprintf('There are no commands defined in the "%s" namespace.', $namespace);
            if ($alternatives = $this->findAlternatives($namespace, $allNamespaces)) {
                if (1 == \count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }
                $message .= \implode("\n    ", $alternatives);
            }
            throw new NamespaceNotFoundException($message, $alternatives);
        }
        $exact = \in_array($namespace, $namespaces, \true);
        if (\count($namespaces) > 1 && !$exact) {
            throw new NamespaceNotFoundException(\sprintf("The namespace \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $namespace, $this->getAbbreviationSuggestions(\array_values($namespaces))), \array_values($namespaces));
        }
        return $exact ? $namespace : \reset($namespaces);
    }
    /**
    * Finds a command by name or alias.
    *
    * Contrary to get, this command tries to find the best
    match if you give it an abbreviation of a name or alias.
    *
    * @return Command
    *
    * @throws CommandNotFoundException When command name is incorrect or ambiguous
    */
    public function find(string $name)
    {
        $this->init();
        $aliases = [];
        foreach ($this->commands as $command) {
            foreach ($command->getAliases() as $alias) {
                if (!$this->has($alias)) {
                    $this->commands[$alias] = $command;
                }
            }
        }
        if ($this->has($name)) {
            return $this->get($name);
        }
        $allCommands = $this->commandLoader ? \array_merge($this->commandLoader->getNames(), \array_keys($this->commands)) : \array_keys($this->commands);
        $expr = \implode('[^:]*:', \array_map('preg_quote', \explode(':', $name))) . '[^:]*';
        $commands = \preg_grep('{^' . $expr . '}', $allCommands);
        if (empty($commands)) {
            $commands = \preg_grep('{^' . $expr . '}i', $allCommands);
        }
        // if no commands matched or we just matched namespaces
        if (empty($commands) || \count(\preg_grep('{^' . $expr . '$}i', $commands)) < 1) {
            if (\false !== ($pos = \strrpos($name, ':'))) {
                // check if a namespace exists and contains commands
                $this->findNamespace(\Phabel\Target\Php80\Polyfill::substr($name, 0, $pos));
            }
            $message = \sprintf('Command "%s" is not defined.', $name);
            if ($alternatives = $this->findAlternatives($name, $allCommands)) {
                // remove hidden commands
                $alternatives = \array_filter($alternatives, function ($name) {
                    return !$this->get($name)->isHidden();
                });
                if (1 == \count($alternatives)) {
                    $message .= "\n\nDid you mean this?\n    ";
                } else {
                    $message .= "\n\nDid you mean one of these?\n    ";
                }
                $message .= \implode("\n    ", $alternatives);
            }
            throw new CommandNotFoundException($message, \array_values($alternatives));
        }
        // filter out aliases for commands which are already on the list
        if (\count($commands) > 1) {
            $commandList = $this->commandLoader ? \array_merge(\array_flip($this->commandLoader->getNames()), $this->commands) : $this->commands;
            $commands = \array_unique(\array_filter($commands, function ($nameOrAlias) use(&$commandList, $commands, &$aliases) {
                if (!$commandList[$nameOrAlias] instanceof Command) {
                    $commandList[$nameOrAlias] = $this->commandLoader->get($nameOrAlias);
                }
                $commandName = $commandList[$nameOrAlias]->getName();
                $aliases[$nameOrAlias] = $commandName;
                return $commandName === $nameOrAlias || !\in_array($commandName, $commands);
            }));
        }
        if (\count($commands) > 1) {
            $usableWidth = $this->terminal->getWidth() - 10;
            $abbrevs = \array_values($commands);
            $maxLen = 0;
            foreach ($abbrevs as $abbrev) {
                $maxLen = \max(Helper::width($abbrev), $maxLen);
            }
            $abbrevs = \array_map(function ($cmd) use($commandList, $usableWidth, $maxLen, &$commands) {
                if ($commandList[$cmd]->isHidden()) {
                    unset($commands[\array_search($cmd, $commands)]);
                    return \false;
                }
                $abbrev = \str_pad($cmd, $maxLen, ' ') . ' ' . $commandList[$cmd]->getDescription();
                return Helper::width($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3) . '...' : $abbrev;
            }, \array_values($commands));
            if (\count($commands) > 1) {
                $suggestions = $this->getAbbreviationSuggestions(\array_filter($abbrevs));
                throw new CommandNotFoundException(\sprintf("Command \"%s\" is ambiguous.\nDid you mean one of these?\n%s.", $name, $suggestions), \array_values($commands));
            }
        }
        $command = $this->get(\reset($commands));
        if ($command->isHidden()) {
            throw new CommandNotFoundException(\sprintf('The command "%s" does not exist.', $name));
        }
        return $command;
    }
    /**
     * Gets the commands (registered in the given namespace if provided).
     *
     * The array keys are the full names and the values the command instances.
     *
     * @return Command[]
     */
    public function all(string $namespace = null)
    {
        $this->init();
        if (null === $namespace) {
            if (!$this->commandLoader) {
                return $this->commands;
            }
            $commands = $this->commands;
            foreach ($this->commandLoader->getNames() as $name) {
                if (!isset($commands[$name]) && $this->has($name)) {
                    $commands[$name] = $this->get($name);
                }
            }
            return $commands;
        }
        $commands = [];
        foreach ($this->commands as $name => $command) {
            if ($namespace === $this->extractNamespace($name, \Phabel\Target\Php80\Polyfill::substr_count($namespace, ':') + 1)) {
                $commands[$name] = $command;
            }
        }
        if ($this->commandLoader) {
            foreach ($this->commandLoader->getNames() as $name) {
                if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, \Phabel\Target\Php80\Polyfill::substr_count($namespace, ':') + 1) && $this->has($name)) {
                    $commands[$name] = $this->get($name);
                }
            }
        }
        return $commands;
    }
    /**
     * Returns an array of possible abbreviations given a set of names.
     *
     * @return string[][]
     */
    public static function getAbbreviations(array $names)
    {
        $abbrevs = [];
        foreach ($names as $name) {
            for ($len = \strlen($name); $len > 0; --$len) {
                $abbrev = \Phabel\Target\Php80\Polyfill::substr($name, 0, $len);
                $abbrevs[$abbrev][] = $name;
            }
        }
        return $abbrevs;
    }
    /**
     *
     */
    public function renderThrowable(\Throwable $e, OutputInterface $output) : void
    {
        $output->writeln('', OutputInterface::VERBOSITY_QUIET);
        $this->doRenderThrowable($e, $output);
        if (null !== $this->runningCommand) {
            $output->writeln(\sprintf('<info>%s</info>', OutputFormatter::escape(\sprintf($this->runningCommand->getSynopsis(), $this->getName()))), OutputInterface::VERBOSITY_QUIET);
            $output->writeln('', OutputInterface::VERBOSITY_QUIET);
        }
    }
    /**
     *
     */
    protected function doRenderThrowable(\Throwable $e, OutputInterface $output) : void
    {
        do {
            $message = \trim($e->getMessage());
            if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $class = \get_debug_type($e);
                $title = \sprintf('  [%s%s]  ', $class, 0 !== ($code = $e->getCode()) ? ' (' . $code . ')' : '');
                $len = Helper::width($title);
            } else {
                $len = 0;
            }
            if (\str_contains($message, "@anonymous\x00")) {
                $message = \preg_replace_callback('/[a-zA-Z_\\x7f-\\xff][\\\\a-zA-Z0-9_\\x7f-\\xff]*+@anonymous\\x00.*?\\.php(?:0x?|:[0-9]++\\$)[0-9a-fA-F]++/', function ($m) {
                    return \class_exists($m[0], \false) ? ((\get_parent_class($m[0]) ?: \key(\class_implements($m[0]))) ?: 'class') . '@anonymous' : $m[0];
                }, $message);
            }
            $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : \PHP_INT_MAX;
            $lines = [];
            foreach ('' !== $message ? \preg_split('/\\r?\\n/', $message) : [] as $line) {
                foreach ($this->splitStringByWidth($line, $width - 4) as $line) {
                    // pre-format lines to get the right string length
                    $lineLength = Helper::width($line) + 4;
                    $lines[] = [$line, $lineLength];
                    $len = \max($lineLength, $len);
                }
            }
            $messages = [];
            if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $messages[] = \sprintf('<comment>%s</comment>', OutputFormatter::escape(\sprintf('In %s line %s:', \basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a')));
            }
            $messages[] = $emptyLine = \sprintf('<error>%s</error>', \str_repeat(' ', $len));
            if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $messages[] = \sprintf('<error>%s%s</error>', $title, \str_repeat(' ', \max(0, $len - Helper::width($title))));
            }
            foreach ($lines as $line) {
                $messages[] = \sprintf('<error>  %s  %s</error>', OutputFormatter::escape($line[0]), \str_repeat(' ', $len - $line[1]));
            }
            $messages[] = $emptyLine;
            $messages[] = '';
            $output->writeln($messages, OutputInterface::VERBOSITY_QUIET);
            if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
                $output->writeln('<comment>Exception trace:</comment>', OutputInterface::VERBOSITY_QUIET);
                // exception related properties
                $trace = $e->getTrace();
                \array_unshift($trace, ['function' => '', 'file' => $e->getFile() ?: 'n/a', 'line' => $e->getLine() ?: 'n/a', 'args' => []]);
                for ($i = 0, $count = \count($trace); $i < $count; ++$i) {
                    $class = $trace[$i]['class'] ?? '';
                    $type = $trace[$i]['type'] ?? '';
                    $function = $trace[$i]['function'] ?? '';
                    $file = $trace[$i]['file'] ?? 'n/a';
                    $line = $trace[$i]['line'] ?? 'n/a';
                    $output->writeln(\sprintf(' %s%s at <info>%s:%s</info>', $class, $function ? $type . $function . '()' : '', $file, $line), OutputInterface::VERBOSITY_QUIET);
                }
                $output->writeln('', OutputInterface::VERBOSITY_QUIET);
            }
        } while ($e = $e->getPrevious());
    }
    /**
     * Configures the input and output instances based on the user arguments and options.
     */
    protected function configureIO(InputInterface $input, OutputInterface $output)
    {
        if (\true === $input->hasParameterOption(['--ansi'], \true)) {
            $output->setDecorated(\true);
        } elseif (\true === $input->hasParameterOption(['--no-ansi'], \true)) {
            $output->setDecorated(\false);
        }
        if (\true === $input->hasParameterOption(['--no-interaction', '-n'], \true)) {
            $input->setInteractive(\false);
        }
        switch ($shellVerbosity = (int) \getenv('SHELL_VERBOSITY')) {
            case -1:
                $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
                break;
            case 1:
                $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
                break;
            case 2:
                $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
                break;
            case 3:
                $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
                break;
            default:
                $shellVerbosity = 0;
                break;
        }
        if (\true === $input->hasParameterOption(['--quiet', '-q'], \true)) {
            $output->setVerbosity(OutputInterface::VERBOSITY_QUIET);
            $shellVerbosity = -1;
        } else {
            if ($input->hasParameterOption('-vvv', \true) || $input->hasParameterOption('--verbose=3', \true) || 3 === $input->getParameterOption('--verbose', \false, \true)) {
                $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG);
                $shellVerbosity = 3;
            } elseif ($input->hasParameterOption('-vv', \true) || $input->hasParameterOption('--verbose=2', \true) || 2 === $input->getParameterOption('--verbose', \false, \true)) {
                $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);
                $shellVerbosity = 2;
            } elseif ($input->hasParameterOption('-v', \true) || $input->hasParameterOption('--verbose=1', \true) || $input->hasParameterOption('--verbose', \true) || $input->getParameterOption('--verbose', \false, \true)) {
                $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE);
                $shellVerbosity = 1;
            }
        }
        if (-1 === $shellVerbosity) {
            $input->setInteractive(\false);
        }
        if (\function_exists('putenv')) {
            @\putenv('SHELL_VERBOSITY=' . $shellVerbosity);
        }
        $_ENV['SHELL_VERBOSITY'] = $shellVerbosity;
        $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity;
    }
    /**
    * Runs the current command.
    *
    * If an event dispatcher has been attached to the application,
    events are also dispatched during the life-cycle of the command.
    *
    * @return int 0 if everything went fine, or an error code
    */
    protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output)
    {
        foreach ($command->getHelperSet() as $helper) {
            if ($helper instanceof InputAwareInterface) {
                $helper->setInput($input);
            }
        }
        if ($command instanceof SignalableCommandInterface && ($this->signalsToDispatchEvent || $command->getSubscribedSignals())) {
            if (!$this->signalRegistry) {
                throw new RuntimeException('Unable to subscribe to signal events. Make sure that the `pcntl` extension is installed and that "pcntl_*" functions are not disabled by your php.ini\'s "disable_functions" directive.');
            }
            if ($this->dispatcher) {
                foreach ($this->signalsToDispatchEvent as $signal) {
                    $event = new ConsoleSignalEvent($command, $input, $output, $signal);
                    $this->signalRegistry->register($signal, function ($signal, $hasNext) use($event) {
                        $this->dispatcher->dispatch($event, ConsoleEvents::SIGNAL);
                        // No more handlers, we try to simulate PHP default behavior
                        if (!$hasNext) {
                            if (!\in_array($signal, [\SIGUSR1, \SIGUSR2], \true)) {
                                exit(0);
                            }
                        }
                    });
                }
            }
            foreach ($command->getSubscribedSignals() as $signal) {
                $this->signalRegistry->register($signal, [$command, 'handleSignal']);
            }
        }
        if (null === $this->dispatcher) {
            return $command->run($input, $output);
        }
        // bind before the console.command event, so the listeners have access to input options/arguments
        try {
            $command->mergeApplicationDefinition();
            $input->bind($command->getDefinition());
        } catch (ExceptionInterface $e) {
            // ignore invalid options/arguments for now, to allow the event listeners to customize the InputDefinition
        }
        $event = new ConsoleCommandEvent($command, $input, $output);
        $e = null;
        try {
            $this->dispatcher->dispatch($event, ConsoleEvents::COMMAND);
            if ($event->commandShouldRun()) {
                $exitCode = $command->run($input, $output);
            } else {
                $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED;
            }
        } catch (\Throwable $e) {
            $event = new ConsoleErrorEvent($input, $output, $e, $command);
            $this->dispatcher->dispatch($event, ConsoleEvents::ERROR);
            $e = $event->getError();
            if (0 === ($exitCode = $event->getExitCode())) {
                $e = null;
            }
        }
        $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode);
        $this->dispatcher->dispatch($event, ConsoleEvents::TERMINATE);
        if (null !== $e) {
            throw $e;
        }
        return $event->getExitCode();
    }
    /**
     * Gets the name of the command based on input.
     *
     * @return (string | null)
     */
    protected function getCommandName(InputInterface $input)
    {
        return $this->singleCommand ? $this->defaultCommand : $input->getFirstArgument();
    }
    /**
     * Gets the default input definition.
     *
     * @return InputDefinition
     */
    protected function getDefaultInputDefinition()
    {
        return new InputDefinition([new InputArgument('command', InputArgument::REQUIRED, 'The command to execute'), new InputOption('--help', '-h', InputOption::VALUE_NONE, 'Display help for the given command. When no command is given display help for the <info>' . $this->defaultCommand . '</info> command'), new InputOption('--quiet', '-q', InputOption::VALUE_NONE, 'Do not output any message'), new InputOption('--verbose', '-v|vv|vvv', InputOption::VALUE_NONE, 'Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug'), new InputOption('--version', '-V', InputOption::VALUE_NONE, 'Display this application version'), new InputOption('--ansi', '', InputOption::VALUE_NEGATABLE, 'Force (or disable --no-ansi) ANSI output', null), new InputOption('--no-interaction', '-n', InputOption::VALUE_NONE, 'Do not ask any interactive question')]);
    }
    /**
     * Gets the default commands that should always be available.
     *
     * @return Command[]
     */
    protected function getDefaultCommands()
    {
        return [new HelpCommand(), new ListCommand(), new CompleteCommand(), new DumpCompletionCommand()];
    }
    /**
     * Gets the default helper set with the helpers that should always be available.
     *
     * @return HelperSet
     */
    protected function getDefaultHelperSet()
    {
        return new HelperSet([new FormatterHelper(), new DebugFormatterHelper(), new ProcessHelper(), new QuestionHelper()]);
    }
    /**
     * Returns abbreviated suggestions in string format.
     */
    private function getAbbreviationSuggestions(array $abbrevs) : string
    {
        return '    ' . \implode("\n    ", $abbrevs);
    }
    /**
     * Returns the namespace part of the command name.
     *
     * This method is not part of public API and should not be used directly.
     *
     * @return string
     */
    public function extractNamespace(string $name, int $limit = null)
    {
        $parts = \explode(':', $name, -1);
        return \implode(':', null === $limit ? $parts : \array_slice($parts, 0, $limit));
    }
    /**
    * Finds alternative of $name among $collection,
    if nothing is found in $collection, try in $abbrevs.
    *
    * @return string[]
    */
    private function findAlternatives(string $name, iterable $collection) : array
    {
        $threshold = 1000.0;
        $alternatives = [];
        $collectionParts = [];
        foreach ($collection as $item) {
            $collectionParts[$item] = \explode(':', $item);
        }
        foreach (\explode(':', $name) as $i => $subname) {
            foreach ($collectionParts as $collectionName => $parts) {
                $exists = isset($alternatives[$collectionName]);
                if (!isset($parts[$i]) && $exists) {
                    $alternatives[$collectionName] += $threshold;
                    continue;
                } elseif (!isset($parts[$i])) {
                    continue;
                }
                $lev = \levenshtein($subname, $parts[$i]);
                if ($lev <= \strlen($subname) / 3 || '' !== $subname && \str_contains($parts[$i], $subname)) {
                    $alternatives[$collectionName] = $exists ? $alternatives[$collectionName] + $lev : $lev;
                } elseif ($exists) {
                    $alternatives[$collectionName] += $threshold;
                }
            }
        }
        foreach ($collection as $item) {
            $lev = \levenshtein($name, $item);
            if ($lev <= \strlen($name) / 3 || \str_contains($item, $name)) {
                $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev;
            }
        }
        $alternatives = \array_filter($alternatives, function ($lev) use($threshold) {
            return $lev < 2 * $threshold;
        });
        \ksort($alternatives, \SORT_NATURAL | \SORT_FLAG_CASE);
        return \array_keys($alternatives);
    }
    /**
     * Sets the default Command name.
     *
     * @return $this
     */
    public function setDefaultCommand(string $commandName, bool $isSingleCommand = \false)
    {
        $this->defaultCommand = \explode('|', \ltrim($commandName, '|'))[0];
        if ($isSingleCommand) {
            // Ensure the command exist
            $this->find($commandName);
            $this->singleCommand = \true;
        }
        return $this;
    }
    /**
     * @internal
     */
    public function isSingleCommand() : bool
    {
        return $this->singleCommand;
    }
    /**
     *
     */
    private function splitStringByWidth(string $string, int $width) : array
    {
        // str_split is not suitable for multi-byte characters, we should use preg_split to get char array properly.
        // additionally, array_slice() is not enough as some character has doubled width.
        // we need a function to split string not by character count but by string width
        if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) {
            return \str_split($string, $width);
        }
        $utf8String = \mb_convert_encoding($string, 'utf8', $encoding);
        $lines = [];
        $line = '';
        $offset = 0;
        while (\preg_match('/.{1,10000}/u', $utf8String, $m, 0, $offset)) {
            $offset += \strlen($m[0]);
            foreach (\preg_split('//u', $m[0]) as $char) {
                // test if $char could be appended to current line
                if (\mb_strwidth($line . $char, 'utf8') <= $width) {
                    $line .= $char;
                    continue;
                }
                // if not, push current line to array and make new line
                $lines[] = \str_pad($line, $width);
                $line = $char;
            }
        }
        $lines[] = \count($lines) ? \str_pad($line, $width) : $line;
        \mb_convert_variables($encoding, 'utf8', $lines);
        return $lines;
    }
    /**
     * Returns all namespaces of the command name.
     *
     * @return string[]
     */
    private function extractAllNamespaces(string $name) : array
    {
        // -1 as third argument is needed to skip the command short name when exploding
        $parts = \explode(':', $name, -1);
        $namespaces = [];
        foreach ($parts as $part) {
            if (\count($namespaces)) {
                $namespaces[] = \end($namespaces) . ':' . $part;
            } else {
                $namespaces[] = $part;
            }
        }
        return $namespaces;
    }
    /**
     *
     */
    private function init()
    {
        if ($this->initialized) {
            return;
        }
        $this->initialized = \true;
        foreach ($this->getDefaultCommands() as $command) {
            $this->add($command);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\DependencyInjection;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Command\LazyCommand;
use PhabelVendor\Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
use PhabelVendor\Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
use PhabelVendor\Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use PhabelVendor\Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
use PhabelVendor\Symfony\Component\DependencyInjection\ContainerBuilder;
use PhabelVendor\Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\DependencyInjection\Reference;
use PhabelVendor\Symfony\Component\DependencyInjection\TypedReference;
/**
 * Registers console commands.
 *
 * @author GrÃ©goire Pineau <lyrixx@lyrixx.info>
 */
class AddConsoleCommandPass implements CompilerPassInterface
{
    private $commandLoaderServiceId;
    private $commandTag;
    private $noPreloadTag;
    private $privateTagName;
    /**
     *
     */
    public function __construct(string $commandLoaderServiceId = 'console.command_loader', string $commandTag = 'console.command', string $noPreloadTag = 'container.no_preload', string $privateTagName = 'container.private')
    {
        if (0 < \func_num_args()) {
            trigger_deprecation('symfony/console', '5.3', 'Configuring "%s" is deprecated.', __CLASS__);
        }
        $this->commandLoaderServiceId = $commandLoaderServiceId;
        $this->commandTag = $commandTag;
        $this->noPreloadTag = $noPreloadTag;
        $this->privateTagName = $privateTagName;
    }
    /**
     *
     */
    public function process(ContainerBuilder $container)
    {
        $commandServices = $container->findTaggedServiceIds($this->commandTag, \true);
        $lazyCommandMap = [];
        $lazyCommandRefs = [];
        $serviceIds = [];
        foreach ($commandServices as $id => $tags) {
            $definition = $container->getDefinition($id);
            $definition->addTag($this->noPreloadTag);
            $class = $container->getParameterBag()->resolveValue($definition->getClass());
            if (isset($tags[0]['command'])) {
                $aliases = $tags[0]['command'];
            } else {
                if (!($r = $container->getReflectionClass($class))) {
                    throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
                }
                if (!$r->isSubclassOf(Command::class)) {
                    throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
                }
                $aliases = $class::getDefaultName();
            }
            $aliases = \explode('|', $aliases ?? '');
            $commandName = \array_shift($aliases);
            if ($isHidden = '' === $commandName) {
                $commandName = \array_shift($aliases);
            }
            if (null === $commandName) {
                if (!$definition->isPublic() || $definition->isPrivate() || $definition->hasTag($this->privateTagName)) {
                    $commandId = 'console.command.public_alias.' . $id;
                    $container->setAlias($commandId, $id)->setPublic(\true);
                    $id = $commandId;
                }
                $serviceIds[] = $id;
                continue;
            }
            $description = $tags[0]['description'] ?? null;
            unset($tags[0]);
            $lazyCommandMap[$commandName] = $id;
            $lazyCommandRefs[$id] = new TypedReference($id, $class);
            foreach ($aliases as $alias) {
                $lazyCommandMap[$alias] = $id;
            }
            foreach ($tags as $tag) {
                if (isset($tag['command'])) {
                    $aliases[] = $tag['command'];
                    $lazyCommandMap[$tag['command']] = $id;
                }
                $description = $description ?? $tag['description'] ?? null;
            }
            $definition->addMethodCall('setName', [$commandName]);
            if ($aliases) {
                $definition->addMethodCall('setAliases', [$aliases]);
            }
            if ($isHidden) {
                $definition->addMethodCall('setHidden', [\true]);
            }
            if (!$description) {
                if (!($r = $container->getReflectionClass($class))) {
                    throw new InvalidArgumentException(\sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
                }
                if (!$r->isSubclassOf(Command::class)) {
                    throw new InvalidArgumentException(\sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class));
                }
                $description = $class::getDefaultDescription();
            }
            if ($description) {
                $definition->addMethodCall('setDescription', [$description]);
                $container->register('.' . $id . '.lazy', LazyCommand::class)->setArguments([$commandName, $aliases, $description, $isHidden, new ServiceClosureArgument($lazyCommandRefs[$id])]);
                $lazyCommandRefs[$id] = new Reference('.' . $id . '.lazy');
            }
        }
        $container->register($this->commandLoaderServiceId, ContainerCommandLoader::class)->setPublic(\true)->addTag($this->noPreloadTag)->setArguments([ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap]);
        $container->setParameter('console.command.ids', $serviceIds);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\SignalRegistry;

final class SignalRegistry
{
    private $signalHandlers = [];
    /**
     *
     */
    public function __construct()
    {
        if (\function_exists('pcntl_async_signals')) {
            \Phabel\Target\Php80\Polyfill::pcntl_async_signals(\true);
        }
    }
    /**
     *
     */
    public function register(int $signal, callable $signalHandler) : void
    {
        if (!isset($this->signalHandlers[$signal])) {
            $previousCallback = \pcntl_signal_get_handler($signal);
            if (\is_callable($previousCallback)) {
                $this->signalHandlers[$signal][] = $previousCallback;
            }
        }
        $this->signalHandlers[$signal][] = $signalHandler;
        \pcntl_signal($signal, [$this, 'handle']);
    }
    /**
     *
     */
    public static function isSupported() : bool
    {
        if (!\function_exists('pcntl_signal')) {
            return \false;
        }
        if (\in_array('pcntl_signal', \explode(',', \ini_get('disable_functions')))) {
            return \false;
        }
        return \true;
    }
    /**
     * @internal
     */
    public function handle(int $signal) : void
    {
        $count = \count($this->signalHandlers[$signal]);
        foreach ($this->signalHandlers[$signal] as $i => $signalHandler) {
            $hasNext = $i !== $count - 1;
            $signalHandler($signal, $hasNext);
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Style;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
use PhabelVendor\Symfony\Component\Console\Helper\ProgressBar;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Decorates output to add console style guide helpers.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
abstract class OutputStyle implements OutputInterface, StyleInterface
{
    private $output;
    /**
     *
     */
    public function __construct(OutputInterface $output)
    {
        $this->output = $output;
    }
    /**
     * {@inheritdoc}
     */
    public function newLine(int $count = 1)
    {
        $this->output->write(\str_repeat(\PHP_EOL, $count));
    }
    /**
     * @return ProgressBar
     */
    public function createProgressBar(int $max = 0)
    {
        return new ProgressBar($this->output, $max);
    }
    /**
     * {@inheritdoc}
     */
    public function write($messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL)
    {
        $this->output->write($messages, $newline, $type);
    }
    /**
     * {@inheritdoc}
     */
    public function writeln($messages, int $type = self::OUTPUT_NORMAL)
    {
        $this->output->writeln($messages, $type);
    }
    /**
     * {@inheritdoc}
     */
    public function setVerbosity(int $level)
    {
        $this->output->setVerbosity($level);
    }
    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return $this->output->getVerbosity();
    }
    /**
     * {@inheritdoc}
     */
    public function setDecorated(bool $decorated)
    {
        $this->output->setDecorated($decorated);
    }
    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return $this->output->isDecorated();
    }
    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        $this->output->setFormatter($formatter);
    }
    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        return $this->output->getFormatter();
    }
    /**
     * {@inheritdoc}
     */
    public function isQuiet()
    {
        return $this->output->isQuiet();
    }
    /**
     * {@inheritdoc}
     */
    public function isVerbose()
    {
        return $this->output->isVerbose();
    }
    /**
     * {@inheritdoc}
     */
    public function isVeryVerbose()
    {
        return $this->output->isVeryVerbose();
    }
    /**
     * {@inheritdoc}
     */
    public function isDebug()
    {
        return $this->output->isDebug();
    }
    /**
     *
     */
    protected function getErrorOutput()
    {
        if (!$this->output instanceof ConsoleOutputInterface) {
            return $this->output;
        }
        return $this->output->getErrorOutput();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Style;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\RuntimeException;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Helper\Helper;
use PhabelVendor\Symfony\Component\Console\Helper\ProgressBar;
use PhabelVendor\Symfony\Component\Console\Helper\SymfonyQuestionHelper;
use PhabelVendor\Symfony\Component\Console\Helper\Table;
use PhabelVendor\Symfony\Component\Console\Helper\TableCell;
use PhabelVendor\Symfony\Component\Console\Helper\TableSeparator;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\TrimmedBufferOutput;
use PhabelVendor\Symfony\Component\Console\Question\ChoiceQuestion;
use PhabelVendor\Symfony\Component\Console\Question\ConfirmationQuestion;
use PhabelVendor\Symfony\Component\Console\Question\Question;
use PhabelVendor\Symfony\Component\Console\Terminal;
/**
 * Output decorator helpers for the Symfony Style Guide.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class SymfonyStyle extends OutputStyle
{
    public const MAX_LINE_LENGTH = 120;
    private $input;
    private $output;
    private $questionHelper;
    private $progressBar;
    private $lineLength;
    private $bufferedOutput;
    /**
     *
     */
    public function __construct(InputInterface $input, OutputInterface $output)
    {
        $this->input = $input;
        $this->bufferedOutput = new TrimmedBufferOutput(\DIRECTORY_SEPARATOR === '\\' ? 4 : 2, $output->getVerbosity(), \false, clone $output->getFormatter());
        // Windows cmd wraps lines as soon as the terminal width is reached, whether there are following chars or not.
        $width = (new Terminal())->getWidth() ?: self::MAX_LINE_LENGTH;
        $this->lineLength = \min($width - (int) (\DIRECTORY_SEPARATOR === '\\'), self::MAX_LINE_LENGTH);
        parent::__construct($this->output = $output);
    }
    /**
     * Formats a message as a block of text.
     *
     * @param (string | array) $messages The message to write in the block
     */
    public function block($messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \true)
    {
        $messages = \is_array($messages) ? \array_values($messages) : [$messages];
        $this->autoPrependBlock();
        $this->writeln($this->createBlock($messages, $type, $style, $prefix, $padding, $escape));
        $this->newLine();
    }
    /**
     * {@inheritdoc}
     */
    public function title(string $message)
    {
        $this->autoPrependBlock();
        $this->writeln([\sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), \sprintf('<comment>%s</>', \str_repeat('=', Helper::width(Helper::removeDecoration($this->getFormatter(), $message))))]);
        $this->newLine();
    }
    /**
     * {@inheritdoc}
     */
    public function section(string $message)
    {
        $this->autoPrependBlock();
        $this->writeln([\sprintf('<comment>%s</>', OutputFormatter::escapeTrailingBackslash($message)), \sprintf('<comment>%s</>', \str_repeat('-', Helper::width(Helper::removeDecoration($this->getFormatter(), $message))))]);
        $this->newLine();
    }
    /**
     * {@inheritdoc}
     */
    public function listing(array $elements)
    {
        $this->autoPrependText();
        $elements = \array_map(function ($element) {
            return \sprintf(' * %s', $element);
        }, $elements);
        $this->writeln($elements);
        $this->newLine();
    }
    /**
     * {@inheritdoc}
     */
    public function text($message)
    {
        $this->autoPrependText();
        $messages = \is_array($message) ? \array_values($message) : [$message];
        foreach ($messages as $message) {
            $this->writeln(\sprintf(' %s', $message));
        }
    }
    /**
     * Formats a command comment.
     *
     * @param (string | array) $message
     */
    public function comment($message)
    {
        $this->block($message, null, null, '<fg=default;bg=default> // </>', \false, \false);
    }
    /**
     * {@inheritdoc}
     */
    public function success($message)
    {
        $this->block($message, 'OK', 'fg=black;bg=green', ' ', \true);
    }
    /**
     * {@inheritdoc}
     */
    public function error($message)
    {
        $this->block($message, 'ERROR', 'fg=white;bg=red', ' ', \true);
    }
    /**
     * {@inheritdoc}
     */
    public function warning($message)
    {
        $this->block($message, 'WARNING', 'fg=black;bg=yellow', ' ', \true);
    }
    /**
     * {@inheritdoc}
     */
    public function note($message)
    {
        $this->block($message, 'NOTE', 'fg=yellow', ' ! ');
    }
    /**
     * Formats an info message.
     *
     * @param (string | array) $message
     */
    public function info($message)
    {
        $this->block($message, 'INFO', 'fg=green', ' ', \true);
    }
    /**
     * {@inheritdoc}
     */
    public function caution($message)
    {
        $this->block($message, 'CAUTION', 'fg=white;bg=red', ' ! ', \true);
    }
    /**
     * {@inheritdoc}
     */
    public function table(array $headers, array $rows)
    {
        $this->createTable()->setHeaders($headers)->setRows($rows)->render();
        $this->newLine();
    }
    /**
     * Formats a horizontal table.
     */
    public function horizontalTable(array $headers, array $rows)
    {
        $this->createTable()->setHorizontal(\true)->setHeaders($headers)->setRows($rows)->render();
        $this->newLine();
    }
    /**
    * Formats a list of key/value horizontally.
    *
    * Each row can be one of:
    'A title'
    ['key' => 'value']
    new TableSeparator()
    *
    * @param (string | array | TableSeparator) ...$list
    */
    public function definitionList(...$list)
    {
        $headers = [];
        $row = [];
        foreach ($list as $value) {
            if ($value instanceof TableSeparator) {
                $headers[] = $value;
                $row[] = $value;
                continue;
            }
            if (\is_string($value)) {
                $headers[] = new TableCell($value, ['colspan' => 2]);
                $row[] = null;
                continue;
            }
            if (!\is_array($value)) {
                throw new InvalidArgumentException('Value should be an array, string, or an instance of TableSeparator.');
            }
            $headers[] = \key($value);
            $row[] = \current($value);
        }
        $this->horizontalTable($headers, [$row]);
    }
    /**
     * {@inheritdoc}
     */
    public function ask(string $question, string $default = null, callable $validator = null)
    {
        $question = new Question($question, $default);
        $question->setValidator($validator);
        return $this->askQuestion($question);
    }
    /**
     * {@inheritdoc}
     */
    public function askHidden(string $question, callable $validator = null)
    {
        $question = new Question($question);
        $question->setHidden(\true);
        $question->setValidator($validator);
        return $this->askQuestion($question);
    }
    /**
     * {@inheritdoc}
     */
    public function confirm(string $question, bool $default = \true)
    {
        return $this->askQuestion(new ConfirmationQuestion($question, $default));
    }
    /**
     * {@inheritdoc}
     */
    public function choice(string $question, array $choices, $default = null)
    {
        if (null !== $default) {
            $values = \array_flip($choices);
            $default = $values[$default] ?? $default;
        }
        return $this->askQuestion(new ChoiceQuestion($question, $choices, $default));
    }
    /**
     * {@inheritdoc}
     */
    public function progressStart(int $max = 0)
    {
        $this->progressBar = $this->createProgressBar($max);
        $this->progressBar->start();
    }
    /**
     * {@inheritdoc}
     */
    public function progressAdvance(int $step = 1)
    {
        $this->getProgressBar()->advance($step);
    }
    /**
     * {@inheritdoc}
     */
    public function progressFinish()
    {
        $this->getProgressBar()->finish();
        $this->newLine(2);
        $this->progressBar = null;
    }
    /**
     * {@inheritdoc}
     */
    public function createProgressBar(int $max = 0)
    {
        $progressBar = parent::createProgressBar($max);
        if ('\\' !== \DIRECTORY_SEPARATOR || 'Hyper' === \getenv('TERM_PROGRAM')) {
            $progressBar->setEmptyBarCharacter('â–‘');
            // light shade character \u2591
            $progressBar->setProgressCharacter('');
            $progressBar->setBarCharacter('â–“');
            // dark shade character \u2593
        }
        return $progressBar;
    }
    /**
     * @see ProgressBar::iterate()
     */
    public function progressIterate(iterable $iterable, int $max = null) : iterable
    {
        yield from $this->createProgressBar()->iterate($iterable, $max);
        $this->newLine(2);
    }
    /**
     * @return mixed
     */
    public function askQuestion(Question $question)
    {
        if ($this->input->isInteractive()) {
            $this->autoPrependBlock();
        }
        if (!$this->questionHelper) {
            $this->questionHelper = new SymfonyQuestionHelper();
        }
        $answer = $this->questionHelper->ask($this->input, $this, $question);
        if ($this->input->isInteractive()) {
            $this->newLine();
            $this->bufferedOutput->write("\n");
        }
        return $answer;
    }
    /**
     * {@inheritdoc}
     */
    public function writeln($messages, int $type = self::OUTPUT_NORMAL)
    {
        if (!\is_iterable($messages)) {
            $messages = [$messages];
        }
        foreach ($messages as $message) {
            parent::writeln($message, $type);
            $this->writeBuffer($message, \true, $type);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function write($messages, bool $newline = \false, int $type = self::OUTPUT_NORMAL)
    {
        if (!\is_iterable($messages)) {
            $messages = [$messages];
        }
        foreach ($messages as $message) {
            parent::write($message, $newline, $type);
            $this->writeBuffer($message, $newline, $type);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function newLine(int $count = 1)
    {
        parent::newLine($count);
        $this->bufferedOutput->write(\str_repeat("\n", $count));
    }
    /**
     * Returns a new instance which makes use of stderr if available.
     *
     * @return self
     */
    public function getErrorStyle()
    {
        return new self($this->input, $this->getErrorOutput());
    }
    /**
     *
     */
    public function createTable() : Table
    {
        $output = $this->output instanceof ConsoleOutputInterface ? $this->output->section() : $this->output;
        $style = clone Table::getStyleDefinition('symfony-style-guide');
        $style->setCellHeaderFormat('<info>%s</info>');
        return (new Table($output))->setStyle($style);
    }
    /**
     *
     */
    private function getProgressBar() : ProgressBar
    {
        if (!$this->progressBar) {
            throw new RuntimeException('The ProgressBar is not started.');
        }
        return $this->progressBar;
    }
    /**
     *
     */
    private function autoPrependBlock() : void
    {
        $chars = \Phabel\Target\Php80\Polyfill::substr(\str_replace(\PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2);
        if (!isset($chars[0])) {
            $this->newLine();
            //empty history, so we should start with a new line.
            return;
        }
        //Prepend new line for each non LF chars (This means no blank line was output before)
        $this->newLine(2 - \Phabel\Target\Php80\Polyfill::substr_count($chars, "\n"));
    }
    /**
     *
     */
    private function autoPrependText() : void
    {
        $fetched = $this->bufferedOutput->fetch();
        //Prepend new line if last char isn't EOL:
        if (!\str_ends_with($fetched, "\n")) {
            $this->newLine();
        }
    }
    /**
     *
     */
    private function writeBuffer(string $message, bool $newLine, int $type) : void
    {
        // We need to know if the last chars are PHP_EOL
        $this->bufferedOutput->write($message, $newLine, $type);
    }
    /**
     *
     */
    private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = \false, bool $escape = \false) : array
    {
        $indentLength = 0;
        $prefixLength = Helper::width(Helper::removeDecoration($this->getFormatter(), $prefix));
        $lines = [];
        if (null !== $type) {
            $type = \sprintf('[%s] ', $type);
            $indentLength = \strlen($type);
            $lineIndentation = \str_repeat(' ', $indentLength);
        }
        // wrap and add newlines for each element
        foreach ($messages as $key => $message) {
            if ($escape) {
                $message = OutputFormatter::escape($message);
            }
            $decorationLength = Helper::width($message) - Helper::width(Helper::removeDecoration($this->getFormatter(), $message));
            $messageLineLength = \min($this->lineLength - $prefixLength - $indentLength + $decorationLength, $this->lineLength);
            $messageLines = \explode(\PHP_EOL, \wordwrap($message, $messageLineLength, \PHP_EOL, \true));
            foreach ($messageLines as $messageLine) {
                $lines[] = $messageLine;
            }
            if (\count($messages) > 1 && $key < \count($messages) - 1) {
                $lines[] = '';
            }
        }
        $firstLineIndex = 0;
        if ($padding && $this->isDecorated()) {
            $firstLineIndex = 1;
            \array_unshift($lines, '');
            $lines[] = '';
        }
        foreach ($lines as $i => &$line) {
            if (null !== $type) {
                $line = $firstLineIndex === $i ? $type . $line : $lineIndentation . $line;
            }
            $line = $prefix . $line;
            $line .= \str_repeat(' ', \max($this->lineLength - Helper::width(Helper::removeDecoration($this->getFormatter(), $line)), 0));
            if ($style) {
                $line = \sprintf('<%s>%s</>', $style, $line);
            }
        }
        return $lines;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Style;

/**
 * Output style helpers.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
interface StyleInterface
{
    /**
     * Formats a command title.
     */
    public function title(string $message);
    /**
     * Formats a section title.
     */
    public function section(string $message);
    /**
     * Formats a list.
     */
    public function listing(array $elements);
    /**
     * Formats informational text.
     *
     * @param (string | array) $message
     */
    public function text($message);
    /**
     * Formats a success result bar.
     *
     * @param (string | array) $message
     */
    public function success($message);
    /**
     * Formats an error result bar.
     *
     * @param (string | array) $message
     */
    public function error($message);
    /**
     * Formats an warning result bar.
     *
     * @param (string | array) $message
     */
    public function warning($message);
    /**
     * Formats a note admonition.
     *
     * @param (string | array) $message
     */
    public function note($message);
    /**
     * Formats a caution admonition.
     *
     * @param (string | array) $message
     */
    public function caution($message);
    /**
     * Formats a table.
     */
    public function table(array $headers, array $rows);
    /**
     * Asks a question.
     *
     * @return mixed
     */
    public function ask(string $question, string $default = null, callable $validator = null);
    /**
     * Asks a question with the user input hidden.
     *
     * @return mixed
     */
    public function askHidden(string $question, callable $validator = null);
    /**
     * Asks for confirmation.
     *
     * @return bool
     */
    public function confirm(string $question, bool $default = \true);
    /**
     * Asks a choice question.
     *
     * @param (string | int | null) $default
     *
     * @return mixed
     */
    public function choice(string $question, array $choices, $default = null);
    /**
     * Add newline(s).
     */
    public function newLine(int $count = 1);
    /**
     * Starts the progress output.
     */
    public function progressStart(int $max = 0);
    /**
     * Advances the progress output X steps.
     */
    public function progressAdvance(int $step = 1);
    /**
     * Finishes the progress output.
     */
    public function progressFinish();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Logger;

use PhabelVendor\Psr\Log\AbstractLogger;
use PhabelVendor\Psr\Log\InvalidArgumentException;
use PhabelVendor\Psr\Log\LogLevel;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * PSR-3 compliant console logger.
 *
 * @author KÃ©vin Dunglas <dunglas@gmail.com>
 *
 * @see https://www.php-fig.org/psr/psr-3/
 */
class ConsoleLogger extends AbstractLogger
{
    public const INFO = 'info';
    public const ERROR = 'error';
    private $output;
    private $verbosityLevelMap = [LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG];
    private $formatLevelMap = [LogLevel::EMERGENCY => self::ERROR, LogLevel::ALERT => self::ERROR, LogLevel::CRITICAL => self::ERROR, LogLevel::ERROR => self::ERROR, LogLevel::WARNING => self::INFO, LogLevel::NOTICE => self::INFO, LogLevel::INFO => self::INFO, LogLevel::DEBUG => self::INFO];
    private $errored = \false;
    /**
     *
     */
    public function __construct(OutputInterface $output, array $verbosityLevelMap = [], array $formatLevelMap = [])
    {
        $this->output = $output;
        $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
        $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    public function log($level, $message, array $context = [])
    {
        if (!isset($this->verbosityLevelMap[$level])) {
            throw new InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $level));
        }
        $output = $this->output;
        // Write to the error output if necessary and available
        if (self::ERROR === $this->formatLevelMap[$level]) {
            if ($this->output instanceof ConsoleOutputInterface) {
                $output = $output->getErrorOutput();
            }
            $this->errored = \true;
        }
        // the if condition check isn't necessary -- it's the same one that $output will do internally anyway.
        // We only do it for efficiency here as the message formatting is relatively expensive.
        if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
            $output->writeln(\sprintf('<%1$s>[%2$s] %3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]);
        }
    }
    /**
     * Returns true when any messages have been logged at error levels.
     *
     * @return bool
     */
    public function hasErrored()
    {
        return $this->errored;
    }
    /**
     * Interpolates context values into the message placeholders.
     *
     * @author PHP Framework Interoperability Group
     */
    private function interpolate(string $message, array $context) : string
    {
        if (!\str_contains($message, '{')) {
            return $message;
        }
        $replacements = [];
        foreach ($context as $key => $val) {
            if (null === $val || \is_scalar($val) || \is_object($val) && \method_exists($val, '__toString')) {
                $replacements["{{$key}}"] = $val;
            } elseif ($val instanceof \DateTimeInterface) {
                $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339);
            } elseif (\is_object($val)) {
                $replacements["{{$key}}"] = '[object ' . \get_class($val) . ']';
            } else {
                $replacements["{{$key}}"] = '[' . \gettype($val) . ']';
            }
        }
        return \strtr($message, $replacements);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

/**
 * ConsoleOutputInterface is the interface implemented by ConsoleOutput class.
 * This adds information about stderr and section output stream.
 *
 * @author Dariusz GÃ³recki <darek.krk@gmail.com>
 */
interface ConsoleOutputInterface extends OutputInterface
{
    /**
     * Gets the OutputInterface for errors.
     *
     * @return OutputInterface
     */
    public function getErrorOutput();
    /**
     *
     */
    public function setErrorOutput(OutputInterface $error);
    /**
     *
     */
    public function section() : ConsoleSectionOutput;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * Base class for output classes.
 *
 * There are five levels of verbosity:
 *
 *  * normal: no option passed (normal output)
 *  * verbose: -v (more output)
 *  * very verbose: -vv (highly extended output)
 *  * debug: -vvv (all debug output)
 *  * quiet: -q (no output)
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Output implements OutputInterface
{
    private $verbosity;
    private $formatter;
    /**
     * @param (int | null) $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param bool $decorated Whether to decorate messages
     * @param (OutputFormatterInterface | null) $formatter Output formatter instance (null to use default OutputFormatter)
     */
    public function __construct(?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = \false, OutputFormatterInterface $formatter = null)
    {
        $this->verbosity = $verbosity ?? self::VERBOSITY_NORMAL;
        $this->formatter = $formatter ?? new OutputFormatter();
        $this->formatter->setDecorated($decorated);
    }
    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        $this->formatter = $formatter;
    }
    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        return $this->formatter;
    }
    /**
     * {@inheritdoc}
     */
    public function setDecorated(bool $decorated)
    {
        $this->formatter->setDecorated($decorated);
    }
    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return $this->formatter->isDecorated();
    }
    /**
     * {@inheritdoc}
     */
    public function setVerbosity(int $level)
    {
        $this->verbosity = $level;
    }
    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return $this->verbosity;
    }
    /**
     * {@inheritdoc}
     */
    public function isQuiet()
    {
        return self::VERBOSITY_QUIET === $this->verbosity;
    }
    /**
     * {@inheritdoc}
     */
    public function isVerbose()
    {
        return self::VERBOSITY_VERBOSE <= $this->verbosity;
    }
    /**
     * {@inheritdoc}
     */
    public function isVeryVerbose()
    {
        return self::VERBOSITY_VERY_VERBOSE <= $this->verbosity;
    }
    /**
     * {@inheritdoc}
     */
    public function isDebug()
    {
        return self::VERBOSITY_DEBUG <= $this->verbosity;
    }
    /**
     * {@inheritdoc}
     */
    public function writeln($messages, int $options = self::OUTPUT_NORMAL)
    {
        $this->write($messages, \true, $options);
    }
    /**
     * {@inheritdoc}
     */
    public function write($messages, bool $newline = \false, int $options = self::OUTPUT_NORMAL)
    {
        if (!\is_iterable($messages)) {
            $messages = [$messages];
        }
        $types = self::OUTPUT_NORMAL | self::OUTPUT_RAW | self::OUTPUT_PLAIN;
        $type = $types & $options ?: self::OUTPUT_NORMAL;
        $verbosities = self::VERBOSITY_QUIET | self::VERBOSITY_NORMAL | self::VERBOSITY_VERBOSE | self::VERBOSITY_VERY_VERBOSE | self::VERBOSITY_DEBUG;
        $verbosity = $verbosities & $options ?: self::VERBOSITY_NORMAL;
        if ($verbosity > $this->getVerbosity()) {
            return;
        }
        foreach ($messages as $message) {
            switch ($type) {
                case OutputInterface::OUTPUT_NORMAL:
                    $message = $this->formatter->format($message);
                    break;
                case OutputInterface::OUTPUT_RAW:
                    break;
                case OutputInterface::OUTPUT_PLAIN:
                    $message = \Phabel\Target\Php80\Polyfill::strip_tags($this->formatter->format($message));
                    break;
            }
            $this->doWrite($message ?? '', $newline);
        }
    }
    /**
     * Writes a message to the output.
     */
    protected abstract function doWrite(string $message, bool $newline);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
use PhabelVendor\Symfony\Component\Console\Helper\Helper;
use PhabelVendor\Symfony\Component\Console\Terminal;
/**
 * @author Pierre du Plessis <pdples@gmail.com>
 * @author Gabriel OstroluckÃ½ <gabriel.ostrolucky@gmail.com>
 */
class ConsoleSectionOutput extends StreamOutput
{
    private $content = [];
    private $lines = 0;
    private $sections;
    private $terminal;
    /**
     * @param resource $stream
     * @param ConsoleSectionOutput[] $sections
     */
    public function __construct($stream, array &$sections, int $verbosity, bool $decorated, OutputFormatterInterface $formatter)
    {
        parent::__construct($stream, $verbosity, $decorated, $formatter);
        \array_unshift($sections, $this);
        $this->sections =& $sections;
        $this->terminal = new Terminal();
    }
    /**
     * Clears previous output for this section.
     *
     * @param int $lines Number of lines to clear. If null, then the entire output of this section is cleared
     */
    public function clear(int $lines = null)
    {
        if (empty($this->content) || !$this->isDecorated()) {
            return;
        }
        if ($lines) {
            \array_splice($this->content, -($lines * 2));
            // Multiply lines by 2 to cater for each new line added between content
        } else {
            $lines = $this->lines;
            $this->content = [];
        }
        $this->lines -= $lines;
        parent::doWrite($this->popStreamContentUntilCurrentSection($lines), \false);
    }
    /**
     * Overwrites the previous output with a new message.
     *
     * @param (array | string) $message
     */
    public function overwrite($message)
    {
        $this->clear();
        $this->writeln($message);
    }
    /**
     *
     */
    public function getContent() : string
    {
        return \implode('', $this->content);
    }
    /**
     * @internal
     */
    public function addContent(string $input)
    {
        foreach (\explode(\PHP_EOL, $input) as $lineContent) {
            $this->lines += \ceil($this->getDisplayLength($lineContent) / $this->terminal->getWidth()) ?: 1;
            $this->content[] = $lineContent;
            $this->content[] = \PHP_EOL;
        }
    }
    /**
     * {@inheritdoc}
     */
    protected function doWrite(string $message, bool $newline)
    {
        if (!$this->isDecorated()) {
            parent::doWrite($message, $newline);
            return;
        }
        $erasedContent = $this->popStreamContentUntilCurrentSection();
        $this->addContent($message);
        parent::doWrite($message, \true);
        parent::doWrite($erasedContent, \false);
    }
    /**
    * At initial stage, cursor is at the end of stream output. This method makes cursor crawl upwards until it hits
    current section. Then it erases content it crawled through. Optionally, it erases part of current section too.
    */
    private function popStreamContentUntilCurrentSection(int $numberOfLinesToClearFromCurrentSection = 0) : string
    {
        $numberOfLinesToClear = $numberOfLinesToClearFromCurrentSection;
        $erasedContent = [];
        foreach ($this->sections as $section) {
            if ($section === $this) {
                break;
            }
            $numberOfLinesToClear += $section->lines;
            $erasedContent[] = $section->getContent();
        }
        if ($numberOfLinesToClear > 0) {
            // move cursor up n lines
            parent::doWrite(\sprintf("\x1b[%dA", $numberOfLinesToClear), \false);
            // erase to end of screen
            parent::doWrite("\x1b[0J", \false);
        }
        return \implode('', \array_reverse($erasedContent));
    }
    /**
     *
     */
    private function getDisplayLength(string $text) : int
    {
        return Helper::width(Helper::removeDecoration($this->getFormatter(), \str_replace("\t", '        ', $text)));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

/**
 * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
 */
class BufferedOutput extends Output
{
    private $buffer = '';
    /**
     * Empties buffer and returns its content.
     *
     * @return string
     */
    public function fetch()
    {
        $content = $this->buffer;
        $this->buffer = '';
        return $content;
    }
    /**
     * {@inheritdoc}
     */
    protected function doWrite(string $message, bool $newline)
    {
        $this->buffer .= $message;
        if ($newline) {
            $this->buffer .= \PHP_EOL;
        }
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * A BufferedOutput that keeps only the last N chars.
 *
 * @author JÃ©rÃ©my DerussÃ© <jeremy@derusse.com>
 */
class TrimmedBufferOutput extends Output
{
    private $maxLength;
    private $buffer = '';
    /**
     *
     */
    public function __construct(int $maxLength, ?int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = \false, OutputFormatterInterface $formatter = null)
    {
        if ($maxLength <= 0) {
            throw new InvalidArgumentException(\sprintf('"%s()" expects a strictly positive maxLength. Got %d.', __METHOD__, $maxLength));
        }
        parent::__construct($verbosity, $decorated, $formatter);
        $this->maxLength = $maxLength;
    }
    /**
     * Empties buffer and returns its content.
     *
     * @return string
     */
    public function fetch()
    {
        $content = $this->buffer;
        $this->buffer = '';
        return $content;
    }
    /**
     * {@inheritdoc}
     */
    protected function doWrite(string $message, bool $newline)
    {
        $this->buffer .= $message;
        if ($newline) {
            $this->buffer .= \PHP_EOL;
        }
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0 - $this->maxLength);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * OutputInterface is the interface implemented by all Output classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface OutputInterface
{
    public const VERBOSITY_QUIET = 16;
    public const VERBOSITY_NORMAL = 32;
    public const VERBOSITY_VERBOSE = 64;
    public const VERBOSITY_VERY_VERBOSE = 128;
    public const VERBOSITY_DEBUG = 256;
    public const OUTPUT_NORMAL = 1;
    public const OUTPUT_RAW = 2;
    public const OUTPUT_PLAIN = 4;
    /**
     * Writes a message to the output.
     *
     * @param (string | iterable) $messages The message as an iterable of strings or a single string
     * @param bool $newline Whether to add a newline
     * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
     */
    public function write($messages, bool $newline = \false, int $options = 0);
    /**
     * Writes a message to the output and adds a newline at the end.
     *
     * @param (string | iterable) $messages The message as an iterable of strings or a single string
     * @param int $options A bitmask of options (one of the OUTPUT or VERBOSITY constants), 0 is considered the same as self::OUTPUT_NORMAL | self::VERBOSITY_NORMAL
     */
    public function writeln($messages, int $options = 0);
    /**
     * Sets the verbosity of the output.
     */
    public function setVerbosity(int $level);
    /**
     * Gets the current verbosity of the output.
     *
     * @return int
     */
    public function getVerbosity();
    /**
     * Returns whether verbosity is quiet (-q).
     *
     * @return bool
     */
    public function isQuiet();
    /**
     * Returns whether verbosity is verbose (-v).
     *
     * @return bool
     */
    public function isVerbose();
    /**
     * Returns whether verbosity is very verbose (-vv).
     *
     * @return bool
     */
    public function isVeryVerbose();
    /**
     * Returns whether verbosity is debug (-vvv).
     *
     * @return bool
     */
    public function isDebug();
    /**
     * Sets the decorated flag.
     */
    public function setDecorated(bool $decorated);
    /**
     * Gets the decorated flag.
     *
     * @return bool
     */
    public function isDecorated();
    /**
     *
     */
    public function setFormatter(OutputFormatterInterface $formatter);
    /**
     * Returns current output formatter instance.
     *
     * @return OutputFormatterInterface
     */
    public function getFormatter();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * StreamOutput writes the output to a given stream.
 *
 * Usage:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *
 * As `StreamOutput` can use any stream, you can also use a file:
 *
 *     $output = new StreamOutput(fopen('/path/to/output.log', 'a', false));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StreamOutput extends Output
{
    private $stream;
    /**
     * @param resource $stream A stream resource
     * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param (bool | null) $decorated Whether to decorate messages (null for auto-guessing)
     * @param (OutputFormatterInterface | null) $formatter Output formatter instance (null to use default OutputFormatter)
     *
     * @throws InvalidArgumentException When first argument is not a real stream
     */
    public function __construct($stream, int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null)
    {
        if (!\is_resource($stream) || 'stream' !== \get_resource_type($stream)) {
            throw new InvalidArgumentException('The StreamOutput class needs a stream as its first argument.');
        }
        $this->stream = $stream;
        if (null === $decorated) {
            $decorated = $this->hasColorSupport();
        }
        parent::__construct($verbosity, $decorated, $formatter);
    }
    /**
     * Gets the stream attached to this StreamOutput instance.
     *
     * @return resource
     */
    public function getStream()
    {
        return $this->stream;
    }
    /**
     * {@inheritdoc}
     */
    protected function doWrite(string $message, bool $newline)
    {
        if ($newline) {
            $message .= \PHP_EOL;
        }
        @\fwrite($this->stream, $message);
        \fflush($this->stream);
    }
    /**
    * Returns true if the stream supports colorization.
    *
    * Colorization is disabled if not supported by the stream:
    *
    * This is tricky on Windows, because Cygwin, Msys2 etc emulate pseudo
    terminals via named pipes, so we can only check the environment.
    *
    * Reference: Composer\XdebugHandler\Process::supportsColor
    https://github.com/composer/xdebug-handler
    *
    * @return bool true if the stream supports colorization, false otherwise
    */
    protected function hasColorSupport()
    {
        // Follow https://no-color.org/
        if (isset($_SERVER['NO_COLOR']) || \false !== \getenv('NO_COLOR')) {
            return \false;
        }
        if ('Hyper' === \getenv('TERM_PROGRAM')) {
            return \true;
        }
        if (\DIRECTORY_SEPARATOR === '\\') {
            return \function_exists('sapi_windows_vt100_support') && @\sapi_windows_vt100_support($this->stream) || \false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM');
        }
        return \stream_isatty($this->stream);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

use PhabelVendor\Symfony\Component\Console\Formatter\NullOutputFormatter;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * NullOutput suppresses all output.
 *
 *     $output = new NullOutput();
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Tobias Schultze <http://tobion.de>
 */
class NullOutput implements OutputInterface
{
    private $formatter;
    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function getFormatter()
    {
        if ($this->formatter) {
            return $this->formatter;
        }
        // to comply with the interface we must return a OutputFormatterInterface
        return $this->formatter = new NullOutputFormatter();
    }
    /**
     * {@inheritdoc}
     */
    public function setDecorated(bool $decorated)
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return \false;
    }
    /**
     * {@inheritdoc}
     */
    public function setVerbosity(int $level)
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function getVerbosity()
    {
        return self::VERBOSITY_QUIET;
    }
    /**
     * {@inheritdoc}
     */
    public function isQuiet()
    {
        return \true;
    }
    /**
     * {@inheritdoc}
     */
    public function isVerbose()
    {
        return \false;
    }
    /**
     * {@inheritdoc}
     */
    public function isVeryVerbose()
    {
        return \false;
    }
    /**
     * {@inheritdoc}
     */
    public function isDebug()
    {
        return \false;
    }
    /**
     * {@inheritdoc}
     */
    public function writeln($messages, int $options = self::OUTPUT_NORMAL)
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function write($messages, bool $newline = \false, int $options = self::OUTPUT_NORMAL)
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Output;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
/**
 * ConsoleOutput is the default class for all CLI output. It uses STDOUT and STDERR.
 *
 * This class is a convenient wrapper around `StreamOutput` for both STDOUT and STDERR.
 *
 *     $output = new ConsoleOutput();
 *
 * This is equivalent to:
 *
 *     $output = new StreamOutput(fopen('php://stdout', 'w'));
 *     $stdErr = new StreamOutput(fopen('php://stderr', 'w'));
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface
{
    private $stderr;
    private $consoleSectionOutputs = [];
    /**
     * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface)
     * @param (bool | null) $decorated Whether to decorate messages (null for auto-guessing)
     * @param (OutputFormatterInterface | null) $formatter Output formatter instance (null to use default OutputFormatter)
     */
    public function __construct(int $verbosity = self::VERBOSITY_NORMAL, bool $decorated = null, OutputFormatterInterface $formatter = null)
    {
        parent::__construct($this->openOutputStream(), $verbosity, $decorated, $formatter);
        if (null === $formatter) {
            // for BC reasons, stdErr has it own Formatter only when user don't inject a specific formatter.
            $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated);
            return;
        }
        $actualDecorated = $this->isDecorated();
        $this->stderr = new StreamOutput($this->openErrorStream(), $verbosity, $decorated, $this->getFormatter());
        if (null === $decorated) {
            $this->setDecorated($actualDecorated && $this->stderr->isDecorated());
        }
    }
    /**
     * Creates a new output section.
     */
    public function section() : ConsoleSectionOutput
    {
        return new ConsoleSectionOutput($this->getStream(), $this->consoleSectionOutputs, $this->getVerbosity(), $this->isDecorated(), $this->getFormatter());
    }
    /**
     * {@inheritdoc}
     */
    public function setDecorated(bool $decorated)
    {
        parent::setDecorated($decorated);
        $this->stderr->setDecorated($decorated);
    }
    /**
     * {@inheritdoc}
     */
    public function setFormatter(OutputFormatterInterface $formatter)
    {
        parent::setFormatter($formatter);
        $this->stderr->setFormatter($formatter);
    }
    /**
     * {@inheritdoc}
     */
    public function setVerbosity(int $level)
    {
        parent::setVerbosity($level);
        $this->stderr->setVerbosity($level);
    }
    /**
     * {@inheritdoc}
     */
    public function getErrorOutput()
    {
        return $this->stderr;
    }
    /**
     * {@inheritdoc}
     */
    public function setErrorOutput(OutputInterface $error)
    {
        $this->stderr = $error;
    }
    /**
    * Returns true if current environment supports writing console output to
    STDOUT.
    *
    * @return bool
    */
    protected function hasStdoutSupport()
    {
        return \false === $this->isRunningOS400();
    }
    /**
    * Returns true if current environment supports writing console output to
    STDERR.
    *
    * @return bool
    */
    protected function hasStderrSupport()
    {
        return \false === $this->isRunningOS400();
    }
    /**
    * Checks if current executing environment is IBM iSeries (OS400), which
    doesn't properly convert character-encodings between ASCII to EBCDIC.
    */
    private function isRunningOS400() : bool
    {
        $checks = [\function_exists('php_uname') ? \php_uname('s') : '', \getenv('OSTYPE'), \PHP_OS];
        return \false !== \stripos(\implode(';', $checks), 'OS400');
    }
    /**
     * @return resource
     */
    private function openOutputStream()
    {
        if (!$this->hasStdoutSupport()) {
            return \fopen('php://output', 'w');
        }
        return @\fopen('php://stdout', 'w') ?: \fopen('php://output', 'w');
    }
    /**
     * @return resource
     */
    private function openErrorStream()
    {
        return \fopen($this->hasStderrSupport() ? 'php://stderr' : 'php://output', 'w');
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Event;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Contracts\EventDispatcher\Event;
/**
 * Allows to inspect input and output of a command.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
class ConsoleEvent extends Event
{
    protected $command;
    private $input;
    private $output;
    /**
     *
     */
    public function __construct(?Command $command, InputInterface $input, OutputInterface $output)
    {
        $this->command = $command;
        $this->input = $input;
        $this->output = $output;
    }
    /**
     * Gets the command that is executed.
     *
     * @return (Command | null)
     */
    public function getCommand()
    {
        return $this->command;
    }
    /**
     * Gets the input instance.
     *
     * @return InputInterface
     */
    public function getInput()
    {
        return $this->input;
    }
    /**
     * Gets the output instance.
     *
     * @return OutputInterface
     */
    public function getOutput()
    {
        return $this->output;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Event;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Allows to handle throwables thrown while running a command.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class ConsoleErrorEvent extends ConsoleEvent
{
    private $error;
    private $exitCode;
    /**
     *
     */
    public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null)
    {
        parent::__construct($command, $input, $output);
        $this->error = $error;
    }
    /**
     *
     */
    public function getError() : \Throwable
    {
        return $this->error;
    }
    /**
     *
     */
    public function setError(\Throwable $error) : void
    {
        $this->error = $error;
    }
    /**
     *
     */
    public function setExitCode(int $exitCode) : void
    {
        $this->exitCode = $exitCode;
        $r = new \ReflectionProperty($this->error, 'code');
        $r->setAccessible(\true);
        $r->setValue($this->error, $this->exitCode);
    }
    /**
     *
     */
    public function getExitCode() : int
    {
        return $this->exitCode ?? (\is_int($this->error->getCode()) && 0 !== $this->error->getCode() ? $this->error->getCode() : 1);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Event;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author marie <marie@users.noreply.github.com>
 */
final class ConsoleSignalEvent extends ConsoleEvent
{
    private $handlingSignal;
    /**
     *
     */
    public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $handlingSignal)
    {
        parent::__construct($command, $input, $output);
        $this->handlingSignal = $handlingSignal;
    }
    /**
     *
     */
    public function getHandlingSignal() : int
    {
        return $this->handlingSignal;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Event;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Allows to manipulate the exit code of a command after its execution.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
final class ConsoleTerminateEvent extends ConsoleEvent
{
    private $exitCode;
    /**
     *
     */
    public function __construct(Command $command, InputInterface $input, OutputInterface $output, int $exitCode)
    {
        parent::__construct($command, $input, $output);
        $this->setExitCode($exitCode);
    }
    /**
     *
     */
    public function setExitCode(int $exitCode) : void
    {
        $this->exitCode = $exitCode;
    }
    /**
     *
     */
    public function getExitCode() : int
    {
        return $this->exitCode;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Event;

/**
 * Allows to do things before the command is executed, like skipping the command or changing the input.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
final class ConsoleCommandEvent extends ConsoleEvent
{
    /**
     * The return code for skipped commands, this will also be passed into the terminate event.
     */
    public const RETURN_CODE_DISABLED = 113;
    /**
     * Indicates if the command should be run or skipped.
     */
    private $commandShouldRun = \true;
    /**
     * Disables the command, so it won't be run.
     */
    public function disableCommand() : bool
    {
        return $this->commandShouldRun = \false;
    }
    /**
     *
     */
    public function enableCommand() : bool
    {
        return $this->commandShouldRun = \true;
    }
    /**
     * Returns true if the command is runnable, false otherwise.
     */
    public function commandShouldRun() : bool
    {
        return $this->commandShouldRun;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\CI;

use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Utility class for Github actions.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class GithubActionReporter
{
    private $output;
    /**
     * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L80-L85
     */
    private const ESCAPED_DATA = ['%' => '%25', "\r" => '%0D', "\n" => '%0A'];
    /**
     * @see https://github.com/actions/toolkit/blob/5e5e1b7aacba68a53836a34db4a288c3c1c1585b/packages/core/src/command.ts#L87-L94
     */
    private const ESCAPED_PROPERTIES = ['%' => '%25', "\r" => '%0D', "\n" => '%0A', ':' => '%3A', ',' => '%2C'];
    /**
     *
     */
    public function __construct(OutputInterface $output)
    {
        $this->output = $output;
    }
    /**
     *
     */
    public static function isGithubActionEnvironment() : bool
    {
        return \false !== \getenv('GITHUB_ACTIONS');
    }
    /**
     * Output an error using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
     */
    public function error(string $message, string $file = null, int $line = null, int $col = null) : void
    {
        $this->log('error', $message, $file, $line, $col);
    }
    /**
     * Output a warning using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message
     */
    public function warning(string $message, string $file = null, int $line = null, int $col = null) : void
    {
        $this->log('warning', $message, $file, $line, $col);
    }
    /**
     * Output a debug log using the Github annotations format.
     *
     * @see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-commands-for-github-actions#setting-a-debug-message
     */
    public function debug(string $message, string $file = null, int $line = null, int $col = null) : void
    {
        $this->log('debug', $message, $file, $line, $col);
    }
    /**
     *
     */
    private function log(string $type, string $message, string $file = null, int $line = null, int $col = null) : void
    {
        // Some values must be encoded.
        $message = \strtr($message, self::ESCAPED_DATA);
        if (!$file) {
            // No file provided, output the message solely:
            $this->output->writeln(\sprintf('::%s::%s', $type, $message));
            return;
        }
        $this->output->writeln(\sprintf('::%s file=%s,line=%s,col=%s::%s', $type, \strtr($file, self::ESCAPED_PROPERTIES), \strtr($line ?? 1, self::ESCAPED_PROPERTIES), \strtr($col ?? 0, self::ESCAPED_PROPERTIES), $message));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Attribute;

/**
 * Service tag to autoconfigure commands.
 */
#[\Attribute(\Attribute::TARGET_CLASS)]
class AsCommand
{
    /**
     *
     */
    public function __construct(string $name, ?string $description = null, array $aliases = [], bool $hidden = \false)
    {
        $this->description = $description;
        $this->name = $name;
        if (!$hidden && !$aliases) {
            return;
        }
        $name = \explode('|', $name);
        $name = \array_merge($name, $aliases);
        if ($hidden && '' !== $name[0]) {
            \array_unshift($name, '');
        }
        $this->name = \implode('|', $name);
    }
    /**
     *
     */
    public ?string $description;
    /**
     *
     */
    public string $name;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console;

class Terminal
{
    private static $width;
    private static $height;
    private static $stty;
    /**
     * Gets the terminal width.
     *
     * @return int
     */
    public function getWidth()
    {
        $width = \getenv('COLUMNS');
        if (\false !== $width) {
            return (int) \trim($width);
        }
        if (null === self::$width) {
            self::initDimensions();
        }
        return self::$width ?: 80;
    }
    /**
     * Gets the terminal height.
     *
     * @return int
     */
    public function getHeight()
    {
        $height = \getenv('LINES');
        if (\false !== $height) {
            return (int) \trim($height);
        }
        if (null === self::$height) {
            self::initDimensions();
        }
        return self::$height ?: 50;
    }
    /**
     * @internal
     */
    public static function hasSttyAvailable() : bool
    {
        if (null !== self::$stty) {
            return self::$stty;
        }
        // skip check if exec function is disabled
        if (!\function_exists('exec')) {
            return \false;
        }
        \exec('stty 2>&1', $output, $exitcode);
        return self::$stty = 0 === $exitcode;
    }
    /**
     *
     */
    private static function initDimensions()
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            if (\preg_match('/^(\\d+)x(\\d+)(?: \\((\\d+)x(\\d+)\\))?$/', \trim(\getenv('ANSICON')), $matches)) {
                // extract [w, H] from "wxh (WxH)"
                // or [w, h] from "wxh"
                self::$width = (int) $matches[1];
                self::$height = isset($matches[4]) ? (int) $matches[4] : (int) $matches[2];
            } elseif (!self::hasVt100Support() && self::hasSttyAvailable()) {
                // only use stty on Windows if the terminal does not support vt100 (e.g. Windows 7 + git-bash)
                // testing for stty in a Windows 10 vt100-enabled console will implicitly disable vt100 support on STDOUT
                self::initDimensionsUsingStty();
            } elseif (null !== ($dimensions = self::getConsoleMode())) {
                // extract [w, h] from "wxh"
                self::$width = (int) $dimensions[0];
                self::$height = (int) $dimensions[1];
            }
        } else {
            self::initDimensionsUsingStty();
        }
    }
    /**
     * Returns whether STDOUT has vt100 support (some Windows 10+ configurations).
     */
    private static function hasVt100Support() : bool
    {
        return \function_exists('sapi_windows_vt100_support') && \sapi_windows_vt100_support(\fopen('php://stdout', 'w'));
    }
    /**
     * Initializes dimensions using the output of an stty columns line.
     */
    private static function initDimensionsUsingStty()
    {
        if ($sttyString = self::getSttyColumns()) {
            if (\preg_match('/rows.(\\d+);.columns.(\\d+);/i', $sttyString, $matches)) {
                // extract [w, h] from "rows h; columns w;"
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            } elseif (\preg_match('/;.(\\d+).rows;.(\\d+).columns/i', $sttyString, $matches)) {
                // extract [w, h] from "; h rows; w columns"
                self::$width = (int) $matches[2];
                self::$height = (int) $matches[1];
            }
        }
    }
    /**
     * Runs and parses mode CON if it's available, suppressing any error output.
     *
     * @return (int[] | null) An array composed of the width and the height or null if it could not be parsed
     */
    private static function getConsoleMode() : ?array
    {
        $info = self::readFromProcess('mode CON');
        if (null === $info || !\preg_match('/--------+\\r?\\n.+?(\\d+)\\r?\\n.+?(\\d+)\\r?\\n/', $info, $matches)) {
            return null;
        }
        return [(int) $matches[2], (int) $matches[1]];
    }
    /**
     * Runs and parses stty -a if it's available, suppressing any error output.
     */
    private static function getSttyColumns() : ?string
    {
        return self::readFromProcess('stty -a | grep columns');
    }
    /**
     *
     */
    private static function readFromProcess(string $command) : ?string
    {
        if (!\function_exists('proc_open')) {
            return null;
        }
        $descriptorspec = [1 => ['pipe', 'w'], 2 => ['pipe', 'w']];
        $process = \proc_open($command, $descriptorspec, $pipes, null, null, ['suppress_errors' => \true]);
        if (!\is_resource($process)) {
            return null;
        }
        $info = \stream_get_contents($pipes[1]);
        \fclose($pipes[1]);
        \fclose($pipes[2]);
        \proc_close($process);
        return $info;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Question;

/**
 * Represents a yes/no question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ConfirmationQuestion extends Question
{
    private $trueAnswerRegex;
    /**
     * @param string $question The question to ask to the user
     * @param bool $default The default answer to return, true or false
     * @param string $trueAnswerRegex A regex to match the "yes" answer
     */
    public function __construct(string $question, bool $default = \true, string $trueAnswerRegex = '/^y/i')
    {
        parent::__construct($question, $default);
        $this->trueAnswerRegex = $trueAnswerRegex;
        $this->setNormalizer($this->getDefaultNormalizer());
    }
    /**
     * Returns the default answer normalizer.
     */
    private function getDefaultNormalizer() : callable
    {
        $default = $this->getDefault();
        $regex = $this->trueAnswerRegex;
        return function ($answer) use($default, $regex) {
            if (\is_bool($answer)) {
                return $answer;
            }
            $answerIsTrue = (bool) \preg_match($regex, $answer);
            if (\false === $default) {
                return $answer && $answerIsTrue;
            }
            return '' === $answer || $answerIsTrue;
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Question;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
/**
 * Represents a Question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class Question
{
    private $question;
    private $attempts;
    private $hidden = \false;
    private $hiddenFallback = \true;
    private $autocompleterCallback;
    private $validator;
    private $default;
    private $normalizer;
    private $trimmable = \true;
    private $multiline = \false;
    /**
     * @param string $question The question to ask to the user
     * @param (string | bool | int | float | null) $default The default answer to return if the user enters nothing
     */
    public function __construct(string $question, $default = null)
    {
        $this->question = $question;
        $this->default = $default;
    }
    /**
     * Returns the question.
     *
     * @return string
     */
    public function getQuestion()
    {
        return $this->question;
    }
    /**
     * Returns the default answer.
     *
     * @return (string | bool | int | float | null)
     */
    public function getDefault()
    {
        return $this->default;
    }
    /**
     * Returns whether the user response accepts newline characters.
     */
    public function isMultiline() : bool
    {
        return $this->multiline;
    }
    /**
     * Sets whether the user response should accept newline characters.
     *
     * @return $this
     */
    public function setMultiline(bool $multiline) : self
    {
        $this->multiline = $multiline;
        return $this;
    }
    /**
     * Returns whether the user response must be hidden.
     *
     * @return bool
     */
    public function isHidden()
    {
        return $this->hidden;
    }
    /**
     * Sets whether the user response must be hidden or not.
     *
     * @return $this
     *
     * @throws LogicException In case the autocompleter is also used
     */
    public function setHidden(bool $hidden)
    {
        if ($this->autocompleterCallback) {
            throw new LogicException('A hidden question cannot use the autocompleter.');
        }
        $this->hidden = $hidden;
        return $this;
    }
    /**
     * In case the response cannot be hidden, whether to fallback on non-hidden question or not.
     *
     * @return bool
     */
    public function isHiddenFallback()
    {
        return $this->hiddenFallback;
    }
    /**
     * Sets whether to fallback on non-hidden question if the response cannot be hidden.
     *
     * @return $this
     */
    public function setHiddenFallback(bool $fallback)
    {
        $this->hiddenFallback = $fallback;
        return $this;
    }
    /**
     * Gets values for the autocompleter.
     *
     * @return (iterable | null)
     */
    public function getAutocompleterValues()
    {
        $callback = $this->getAutocompleterCallback();
        return $callback ? $callback('') : null;
    }
    /**
     * Sets values for the autocompleter.
     *
     * @return $this
     *
     * @throws LogicException
     */
    public function setAutocompleterValues(?iterable $values)
    {
        if (\is_array($values)) {
            $values = $this->isAssoc($values) ? \array_merge(\array_keys($values), \array_values($values)) : \array_values($values);
            $callback = static function () use($values) {
                return $values;
            };
        } elseif ($values instanceof \Traversable) {
            $valueCache = null;
            $callback = static function () use($values, &$valueCache) {
                return $valueCache ?? ($valueCache = \iterator_to_array($values, \false));
            };
        } else {
            $callback = null;
        }
        return $this->setAutocompleterCallback($callback);
    }
    /**
     * Gets the callback function used for the autocompleter.
     */
    public function getAutocompleterCallback() : ?callable
    {
        return $this->autocompleterCallback;
    }
    /**
     * Sets the callback function used for the autocompleter.
     *
     * The callback is passed the user input as argument and should return an iterable of corresponding suggestions.
     *
     * @return $this
     */
    public function setAutocompleterCallback(callable $callback = null) : self
    {
        if ($this->hidden && null !== $callback) {
            throw new LogicException('A hidden question cannot use the autocompleter.');
        }
        $this->autocompleterCallback = $callback;
        return $this;
    }
    /**
     * Sets a validator for the question.
     *
     * @return $this
     */
    public function setValidator(callable $validator = null)
    {
        $this->validator = $validator;
        return $this;
    }
    /**
     * Gets the validator for the question.
     *
     * @return (callable | null)
     */
    public function getValidator()
    {
        return $this->validator;
    }
    /**
     * Sets the maximum number of attempts.
     *
     * Null means an unlimited number of attempts.
     *
     * @return $this
     *
     * @throws InvalidArgumentException in case the number of attempts is invalid
     */
    public function setMaxAttempts(?int $attempts)
    {
        if (null !== $attempts && $attempts < 1) {
            throw new InvalidArgumentException('Maximum number of attempts must be a positive value.');
        }
        $this->attempts = $attempts;
        return $this;
    }
    /**
     * Gets the maximum number of attempts.
     *
     * Null means an unlimited number of attempts.
     *
     * @return (int | null)
     */
    public function getMaxAttempts()
    {
        return $this->attempts;
    }
    /**
     * Sets a normalizer for the response.
     *
     * The normalizer can be a callable (a string), a closure or a class implementing __invoke.
     *
     * @return $this
     */
    public function setNormalizer(callable $normalizer)
    {
        $this->normalizer = $normalizer;
        return $this;
    }
    /**
     * Gets the normalizer for the response.
     *
     * The normalizer can ba a callable (a string), a closure or a class implementing __invoke.
     *
     * @return (callable | null)
     */
    public function getNormalizer()
    {
        return $this->normalizer;
    }
    /**
     *
     */
    protected function isAssoc(array $array)
    {
        return (bool) \count(\array_filter(\array_keys($array), 'is_string'));
    }
    /**
     *
     */
    public function isTrimmable() : bool
    {
        return $this->trimmable;
    }
    /**
     * @return $this
     */
    public function setTrimmable(bool $trimmable) : self
    {
        $this->trimmable = $trimmable;
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Question;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * Represents a choice question.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ChoiceQuestion extends Question
{
    private $choices;
    private $multiselect = \false;
    private $prompt = ' > ';
    private $errorMessage = 'Value "%s" is invalid';
    /**
     * @param string $question The question to ask to the user
     * @param array $choices The list of available choices
     * @param mixed $default The default answer to return
     */
    public function __construct(string $question, array $choices, $default = null)
    {
        if (!$choices) {
            throw new \LogicException('Choice question must have at least 1 choice available.');
        }
        parent::__construct($question, $default);
        $this->choices = $choices;
        $this->setValidator($this->getDefaultValidator());
        $this->setAutocompleterValues($choices);
    }
    /**
     * Returns available choices.
     *
     * @return array
     */
    public function getChoices()
    {
        return $this->choices;
    }
    /**
     * Sets multiselect option.
     *
     * When multiselect is set to true, multiple choices can be answered.
     *
     * @return $this
     */
    public function setMultiselect(bool $multiselect)
    {
        $this->multiselect = $multiselect;
        $this->setValidator($this->getDefaultValidator());
        return $this;
    }
    /**
     * Returns whether the choices are multiselect.
     *
     * @return bool
     */
    public function isMultiselect()
    {
        return $this->multiselect;
    }
    /**
     * Gets the prompt for choices.
     *
     * @return string
     */
    public function getPrompt()
    {
        return $this->prompt;
    }
    /**
     * Sets the prompt for choices.
     *
     * @return $this
     */
    public function setPrompt(string $prompt)
    {
        $this->prompt = $prompt;
        return $this;
    }
    /**
     * Sets the error message for invalid values.
     *
     * The error message has a string placeholder (%s) for the invalid value.
     *
     * @return $this
     */
    public function setErrorMessage(string $errorMessage)
    {
        $this->errorMessage = $errorMessage;
        $this->setValidator($this->getDefaultValidator());
        return $this;
    }
    /**
     *
     */
    private function getDefaultValidator() : callable
    {
        $choices = $this->choices;
        $errorMessage = $this->errorMessage;
        $multiselect = $this->multiselect;
        $isAssoc = $this->isAssoc($choices);
        return function ($selected) use($choices, $errorMessage, $multiselect, $isAssoc) {
            if ($multiselect) {
                // Check for a separated comma values
                if (!\preg_match('/^[^,]+(?:,[^,]+)*$/', $selected, $matches)) {
                    throw new InvalidArgumentException(\sprintf($errorMessage, $selected));
                }
                $selectedChoices = \explode(',', $selected);
            } else {
                $selectedChoices = [$selected];
            }
            if ($this->isTrimmable()) {
                foreach ($selectedChoices as $k => $v) {
                    $selectedChoices[$k] = \trim($v);
                }
            }
            $multiselectChoices = [];
            foreach ($selectedChoices as $value) {
                $results = [];
                foreach ($choices as $key => $choice) {
                    if ($choice === $value) {
                        $results[] = $key;
                    }
                }
                if (\count($results) > 1) {
                    throw new InvalidArgumentException(\sprintf('The provided answer is ambiguous. Value should be one of "%s".', \implode('" or "', $results)));
                }
                $result = \array_search($value, $choices);
                if (!$isAssoc) {
                    if (\false !== $result) {
                        $result = $choices[$result];
                    } elseif (isset($choices[$value])) {
                        $result = $choices[$value];
                    }
                } elseif (\false === $result && isset($choices[$value])) {
                    $result = $value;
                }
                if (\false === $result) {
                    throw new InvalidArgumentException(\sprintf($errorMessage, $value));
                }
                // For associative choices, consistently return the key as string:
                $multiselectChoices[] = $isAssoc ? (string) $result : $result;
            }
            if ($multiselect) {
                return $multiselectChoices;
            }
            return \current($multiselectChoices);
        };
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Exception;

/**
 * Represents an incorrect command name typed in the console.
 *
 * @author JÃ©rÃ´me Tamarelle <jerome@tamarelle.net>
 */
class CommandNotFoundException extends \InvalidArgumentException implements ExceptionInterface
{
    private $alternatives;
    /**
     * @param string $message Exception message to throw
     * @param string[] $alternatives List of similar defined names
     * @param int $code Exception code
     * @param (\Throwable | null) $previous Previous exception used for the exception chaining
     */
    public function __construct(string $message, array $alternatives = [], int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->alternatives = $alternatives;
    }
    /**
     * @return string[]
     */
    public function getAlternatives()
    {
        return $this->alternatives;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Exception;

/**
 * @author JÃ©rÃ´me Tamarelle <jerome@tamarelle.net>
 */
class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Exception;

/**
 * @author JÃ©rÃ´me Tamarelle <jerome@tamarelle.net>
 */
class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Exception;

/**
 * Represents an incorrect namespace typed in the console.
 *
 * @author Pierre du Plessis <pdples@gmail.com>
 */
class NamespaceNotFoundException extends CommandNotFoundException
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Exception;

/**
 * Represents failure to read input from stdin.
 *
 * @author Gabriel OstroluckÃ½ <gabriel.ostrolucky@gmail.com>
 */
class MissingInputException extends RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Exception;

/**
 * Represents an incorrect option name typed in the console.
 *
 * @author JÃ©rÃ´me Tamarelle <jerome@tamarelle.net>
 */
class InvalidOptionException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Exception;

/**
 * @author JÃ©rÃ´me Tamarelle <jerome@tamarelle.net>
 */
class LogicException extends \LogicException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Exception;

/**
 * ExceptionInterface.
 *
 * @author JÃ©rÃ´me Tamarelle <jerome@tamarelle.net>
 */
interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Tester;

use PhabelVendor\PHPUnit\Framework\Assert;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutput;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\StreamOutput;
use PhabelVendor\Symfony\Component\Console\Tester\Constraint\CommandIsSuccessful;
/**
 * @author Amrouche Hamza <hamza.simperfit@gmail.com>
 */
trait TesterTrait
{
    /** @var StreamOutput */
    private $output;
    private $inputs = [];
    private $captureStreamsIndependently = \false;
    /** @var InputInterface */
    private $input;
    /** @var int */
    private $statusCode;
    /**
     * Gets the display returned by the last execution of the command or application.
     *
     * @throws \RuntimeException If it's called before the execute method
     *
     * @return string
     */
    public function getDisplay(bool $normalize = \false)
    {
        if (null === $this->output) {
            throw new \RuntimeException('Output not initialized, did you execute the command before requesting the display?');
        }
        \rewind($this->output->getStream());
        $display = \stream_get_contents($this->output->getStream());
        if ($normalize) {
            $display = \str_replace(\PHP_EOL, "\n", $display);
        }
        return $display;
    }
    /**
     * Gets the output written to STDERR by the application.
     *
     * @param bool $normalize Whether to normalize end of lines to \n or not
     *
     * @return string
     */
    public function getErrorOutput(bool $normalize = \false)
    {
        if (!$this->captureStreamsIndependently) {
            throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.');
        }
        \rewind($this->output->getErrorOutput()->getStream());
        $display = \stream_get_contents($this->output->getErrorOutput()->getStream());
        if ($normalize) {
            $display = \str_replace(\PHP_EOL, "\n", $display);
        }
        return $display;
    }
    /**
     * Gets the input instance used by the last execution of the command or application.
     *
     * @return InputInterface
     */
    public function getInput()
    {
        return $this->input;
    }
    /**
     * Gets the output instance used by the last execution of the command or application.
     *
     * @return OutputInterface
     */
    public function getOutput()
    {
        return $this->output;
    }
    /**
     * Gets the status code returned by the last execution of the command or application.
     *
     * @throws \RuntimeException If it's called before the execute method
     *
     * @return int
     */
    public function getStatusCode()
    {
        if (null === $this->statusCode) {
            throw new \RuntimeException('Status code not initialized, did you execute the command before requesting the status code?');
        }
        return $this->statusCode;
    }
    /**
     *
     */
    public function assertCommandIsSuccessful(string $message = '') : void
    {
        Assert::assertThat($this->statusCode, new CommandIsSuccessful(), $message);
    }
    /**
    * Sets the user inputs.
    *
    * @param array $inputs An array of strings representing each input
    passed to the command input stream
    *
    * @return $this
    */
    public function setInputs(array $inputs)
    {
        $this->inputs = $inputs;
        return $this;
    }
    /**
    * Initializes the output property.
    *
    * Available options:
    *
    * * decorated:                 Sets the output decorated flag
    verbosity:                 Sets the output verbosity flag
    capture_stderr_separately: Make output of stdOut and stdErr separately available
    */
    private function initOutput(array $options)
    {
        $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately'];
        if (!$this->captureStreamsIndependently) {
            $this->output = new StreamOutput(\fopen('php://memory', 'w', \false));
            if (isset($options['decorated'])) {
                $this->output->setDecorated($options['decorated']);
            }
            if (isset($options['verbosity'])) {
                $this->output->setVerbosity($options['verbosity']);
            }
        } else {
            $this->output = new ConsoleOutput($options['verbosity'] ?? ConsoleOutput::VERBOSITY_NORMAL, $options['decorated'] ?? null);
            $errorOutput = new StreamOutput(\fopen('php://memory', 'w', \false));
            $errorOutput->setFormatter($this->output->getFormatter());
            $errorOutput->setVerbosity($this->output->getVerbosity());
            $errorOutput->setDecorated($this->output->isDecorated());
            $reflectedOutput = new \ReflectionObject($this->output);
            $strErrProperty = $reflectedOutput->getProperty('stderr');
            $strErrProperty->setAccessible(\true);
            $strErrProperty->setValue($this->output, $errorOutput);
            $reflectedParent = $reflectedOutput->getParentClass();
            $streamProperty = $reflectedParent->getProperty('stream');
            $streamProperty->setAccessible(\true);
            $streamProperty->setValue($this->output, \fopen('php://memory', 'w', \false));
        }
    }
    /**
     * @return resource
     */
    private static function createStream(array $inputs)
    {
        $stream = \fopen('php://memory', 'r+', \false);
        foreach ($inputs as $input) {
            \fwrite($stream, $input . \PHP_EOL);
        }
        \rewind($stream);
        return $stream;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Tester;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\ArrayInput;
/**
 * Eases the testing of console commands.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class CommandTester
{
    use TesterTrait;
    private $command;
    /**
     *
     */
    public function __construct(Command $command)
    {
        $this->command = $command;
    }
    /**
    * Executes the command.
    *
    * Available execution options:
    *
    * * interactive:               Sets the input interactive flag
    decorated:                 Sets the output decorated flag
    verbosity:                 Sets the output verbosity flag
    capture_stderr_separately: Make output of stdOut and stdErr separately available
    *
    * @param array $input An array of command arguments and options
    * @param array $options An array of execution options
    *
    * @return int The command exit code
    */
    public function execute(array $input, array $options = [])
    {
        // set the command name automatically if the application requires
        // this argument and no command name was passed
        if (!isset($input['command']) && null !== ($application = $this->command->getApplication()) && $application->getDefinition()->hasArgument('command')) {
            $input = \array_merge(['command' => $this->command->getName()], $input);
        }
        $this->input = new ArrayInput($input);
        // Use an in-memory input stream even if no inputs are set so that QuestionHelper::ask() does not rely on the blocking STDIN.
        $this->input->setStream(self::createStream($this->inputs));
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }
        if (!isset($options['decorated'])) {
            $options['decorated'] = \false;
        }
        $this->initOutput($options);
        return $this->statusCode = $this->command->run($this->input, $this->output);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Tester;

use PhabelVendor\Symfony\Component\Console\Application;
use PhabelVendor\Symfony\Component\Console\Input\ArrayInput;
/**
 * Eases the testing of console applications.
 *
 * When testing an application, don't forget to disable the auto exit flag:
 *
 *     $application = new Application();
 *     $application->setAutoExit(false);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ApplicationTester
{
    use TesterTrait;
    private $application;
    /**
     *
     */
    public function __construct(Application $application)
    {
        $this->application = $application;
    }
    /**
    * Executes the application.
    *
    * Available options:
    *
    * * interactive:               Sets the input interactive flag
    decorated:                 Sets the output decorated flag
    verbosity:                 Sets the output verbosity flag
    capture_stderr_separately: Make output of stdOut and stdErr separately available
    *
    * @return int The command exit code
    */
    public function run(array $input, array $options = [])
    {
        $this->input = new ArrayInput($input);
        if (isset($options['interactive'])) {
            $this->input->setInteractive($options['interactive']);
        }
        if ($this->inputs) {
            $this->input->setStream(self::createStream($this->inputs));
        }
        $this->initOutput($options);
        return $this->statusCode = $this->application->run($this->input, $this->output);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Tester\Constraint;

use PhabelVendor\PHPUnit\Framework\Constraint\Constraint;
use PhabelVendor\Symfony\Component\Console\Command\Command;
final class CommandIsSuccessful extends Constraint
{
    /**
     * {@inheritdoc}
     */
    public function toString() : string
    {
        return 'is successful';
    }
    /**
     * {@inheritdoc}
     */
    protected function matches($other) : bool
    {
        return Command::SUCCESS === $other;
    }
    /**
     * {@inheritdoc}
     */
    protected function failureDescription($other) : string
    {
        return 'the command ' . $this->toString();
    }
    /**
     * {@inheritdoc}
     */
    protected function additionalFailureDescription($other) : string
    {
        $mapping = [Command::FAILURE => 'Command failed.', Command::INVALID => 'Command was invalid.'];
        return $mapping[$other] ?? \sprintf('Command returned exit status %d.', $other);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Tester;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionInput;
use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
/**
 * Eases the testing of command completion.
 *
 * @author JÃ©rÃ´me Tamarelle <jerome@tamarelle.net>
 */
class CommandCompletionTester
{
    private $command;
    /**
     *
     */
    public function __construct(Command $command)
    {
        $this->command = $command;
    }
    /**
     * Create completion suggestions from input tokens.
     */
    public function complete(array $input) : array
    {
        $currentIndex = \count($input);
        if ('' === \end($input)) {
            \array_pop($input);
        }
        \array_unshift($input, $this->command->getName());
        $completionInput = CompletionInput::fromTokens($input, $currentIndex);
        $completionInput->bind($this->command->getDefinition());
        $suggestions = new CompletionSuggestions();
        $this->command->complete($completionInput, $suggestions);
        $options = [];
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $options[] = '--' . $option->getName();
        }
        return \array_map('strval', \array_merge($options, $suggestions->getValueSuggestions()));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author GrÃ©goire Pineau <lyrixx@lyrixx.info>
 */
class SingleCommandApplication extends Command
{
    private $version = 'UNKNOWN';
    private $autoExit = \true;
    private $running = \false;
    /**
     * @return $this
     */
    public function setVersion(string $version) : self
    {
        $this->version = $version;
        return $this;
    }
    /**
     * @final
     *
     * @return $this
     */
    public function setAutoExit(bool $autoExit) : self
    {
        $this->autoExit = $autoExit;
        return $this;
    }
    /**
     *
     */
    public function run(InputInterface $input = null, OutputInterface $output = null) : int
    {
        if ($this->running) {
            return parent::run($input, $output);
        }
        // We use the command name as the application name
        $application = new Application($this->getName() ?: 'UNKNOWN', $this->version);
        $application->setAutoExit($this->autoExit);
        // Fix the usage of the command displayed with "--help"
        $this->setName($_SERVER['argv'][0]);
        $application->add($this);
        $application->setDefaultCommand($this->getName(), \true);
        $this->running = \true;
        try {
            $ret = $application->run($input, $output);
        } finally {
            $this->running = \false;
        }
        return $ret ?? 1;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console;

use PhabelVendor\Symfony\Component\Console\Event\ConsoleCommandEvent;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleErrorEvent;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleSignalEvent;
use PhabelVendor\Symfony\Component\Console\Event\ConsoleTerminateEvent;
/**
 * Contains all events dispatched by an Application.
 *
 * @author Francesco Levorato <git@flevour.net>
 */
final class ConsoleEvents
{
    /**
     * The COMMAND event allows you to attach listeners before any command is
     * executed by the console. It also allows you to modify the command, input and output
     * before they are handed to the command.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleCommandEvent")
     */
    public const COMMAND = 'console.command';
    /**
     * The SIGNAL event allows you to perform some actions
     * after the command execution was interrupted.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleSignalEvent")
     */
    public const SIGNAL = 'console.signal';
    /**
     * The TERMINATE event allows you to attach listeners after a command is
     * executed by the console.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleTerminateEvent")
     */
    public const TERMINATE = 'console.terminate';
    /**
     * The ERROR event occurs when an uncaught exception or error appears.
     *
     * This event allows you to deal with the exception/error or
     * to modify the thrown exception.
     *
     * @Event("Symfony\Component\Console\Event\ConsoleErrorEvent")
     */
    public const ERROR = 'console.error';
    /**
     * Event aliases.
     *
     * These aliases can be consumed by RegisterListenersPass.
     */
    public const ALIASES = [ConsoleCommandEvent::class => self::COMMAND, ConsoleErrorEvent::class => self::ERROR, ConsoleSignalEvent::class => self::SIGNAL, ConsoleTerminateEvent::class => self::TERMINATE];
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console;

use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Pierre du Plessis <pdples@gmail.com>
 */
final class Cursor
{
    private $output;
    private $input;
    /**
     * @param (resource | null) $input
     */
    public function __construct(OutputInterface $output, $input = null)
    {
        $this->output = $output;
        $this->input = $input ?? (\defined('STDIN') ? \STDIN : \fopen('php://input', 'r+'));
    }
    /**
     * @return $this
     */
    public function moveUp(int $lines = 1) : self
    {
        $this->output->write(\sprintf("\x1b[%dA", $lines));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveDown(int $lines = 1) : self
    {
        $this->output->write(\sprintf("\x1b[%dB", $lines));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveRight(int $columns = 1) : self
    {
        $this->output->write(\sprintf("\x1b[%dC", $columns));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveLeft(int $columns = 1) : self
    {
        $this->output->write(\sprintf("\x1b[%dD", $columns));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveToColumn(int $column) : self
    {
        $this->output->write(\sprintf("\x1b[%dG", $column));
        return $this;
    }
    /**
     * @return $this
     */
    public function moveToPosition(int $column, int $row) : self
    {
        $this->output->write(\sprintf("\x1b[%d;%dH", $row + 1, $column));
        return $this;
    }
    /**
     * @return $this
     */
    public function savePosition() : self
    {
        $this->output->write("\x1b7");
        return $this;
    }
    /**
     * @return $this
     */
    public function restorePosition() : self
    {
        $this->output->write("\x1b8");
        return $this;
    }
    /**
     * @return $this
     */
    public function hide() : self
    {
        $this->output->write("\x1b[?25l");
        return $this;
    }
    /**
     * @return $this
     */
    public function show() : self
    {
        $this->output->write("\x1b[?25h\x1b[?0c");
        return $this;
    }
    /**
     * Clears all the output from the current line.
     *
     * @return $this
     */
    public function clearLine() : self
    {
        $this->output->write("\x1b[2K");
        return $this;
    }
    /**
     * Clears all the output from the current line after the current position.
     */
    public function clearLineAfter() : self
    {
        $this->output->write("\x1b[K");
        return $this;
    }
    /**
     * Clears all the output from the cursors' current position to the end of the screen.
     *
     * @return $this
     */
    public function clearOutput() : self
    {
        $this->output->write("\x1b[0J");
        return $this;
    }
    /**
     * Clears the entire screen.
     *
     * @return $this
     */
    public function clearScreen() : self
    {
        $this->output->write("\x1b[2J");
        return $this;
    }
    /**
     * Returns the current cursor position as x,y coordinates.
     */
    public function getCurrentPosition() : array
    {
        static $isTtySupported;
        if (null === $isTtySupported && \function_exists('proc_open')) {
            $isTtySupported = (bool) @\proc_open('echo 1 >/dev/null', [['file', '/dev/tty', 'r'], ['file', '/dev/tty', 'w'], ['file', '/dev/tty', 'w']], $pipes);
        }
        if (!$isTtySupported) {
            return [1, 1];
        }
        $sttyMode = \shell_exec('stty -g');
        \shell_exec('stty -icanon -echo');
        @\fwrite($this->input, "\x1b[6n");
        $code = \trim(\fread($this->input, 1024));
        \shell_exec(\sprintf('stty %s', $sttyMode));
        \sscanf($code, "\x1b[%d;%dR", $row, $col);
        return [$col, $row];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Formatter;

/**
 * Formatter style interface for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OutputFormatterStyleInterface
{
    /**
     * Sets style foreground color.
     */
    public function setForeground(string $color = null);
    /**
     * Sets style background color.
     */
    public function setBackground(string $color = null);
    /**
     * Sets some specific style option.
     */
    public function setOption(string $option);
    /**
     * Unsets some specific style option.
     */
    public function unsetOption(string $option);
    /**
     * Sets multiple style options at once.
     */
    public function setOptions(array $options);
    /**
     * Applies the style to a given text.
     *
     * @return string
     */
    public function apply(string $text);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output that supports word wrapping.
 *
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
interface WrappableOutputFormatterInterface extends OutputFormatterInterface
{
    /**
     * Formats a message according to the given styles, wrapping at `$width` (0 means no wrapping).
     */
    public function formatAndWrap(?string $message, int $width);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Formatter;

/**
 * @author Tien Xuan Vo <tien.xuan.vo@gmail.com>
 */
final class NullOutputFormatter implements OutputFormatterInterface
{
    private $style;
    /**
     * {@inheritdoc}
     */
    public function format(?string $message) : ?string
    {
        return null;
    }
    /**
     * {@inheritdoc}
     */
    public function getStyle(string $name) : OutputFormatterStyleInterface
    {
        // to comply with the interface we must return a OutputFormatterStyleInterface
        return $this->style ?? ($this->style = new NullOutputFormatterStyle());
    }
    /**
     * {@inheritdoc}
     */
    public function hasStyle(string $name) : bool
    {
        return \false;
    }
    /**
     * {@inheritdoc}
     */
    public function isDecorated() : bool
    {
        return \false;
    }
    /**
     * {@inheritdoc}
     */
    public function setDecorated(bool $decorated) : void
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function setStyle(string $name, OutputFormatterStyleInterface $style) : void
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Formatter;

use PhabelVendor\Symfony\Component\Console\Color;
/**
 * Formatter style class for defining styles.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
class OutputFormatterStyle implements OutputFormatterStyleInterface
{
    private $color;
    private $foreground;
    private $background;
    private $options;
    private $href;
    private $handlesHrefGracefully;
    /**
     * Initializes output formatter style.
     *
     * @param (string | null) $foreground The style foreground color name
     * @param (string | null) $background The style background color name
     */
    public function __construct(string $foreground = null, string $background = null, array $options = [])
    {
        $this->color = new Color($this->foreground = $foreground ?: '', $this->background = $background ?: '', $this->options = $options);
    }
    /**
     * {@inheritdoc}
     */
    public function setForeground(string $color = null)
    {
        $this->color = new Color($this->foreground = $color ?: '', $this->background, $this->options);
    }
    /**
     * {@inheritdoc}
     */
    public function setBackground(string $color = null)
    {
        $this->color = new Color($this->foreground, $this->background = $color ?: '', $this->options);
    }
    /**
     *
     */
    public function setHref(string $url) : void
    {
        $this->href = $url;
    }
    /**
     * {@inheritdoc}
     */
    public function setOption(string $option)
    {
        $this->options[] = $option;
        $this->color = new Color($this->foreground, $this->background, $this->options);
    }
    /**
     * {@inheritdoc}
     */
    public function unsetOption(string $option)
    {
        $pos = \array_search($option, $this->options);
        if (\false !== $pos) {
            unset($this->options[$pos]);
        }
        $this->color = new Color($this->foreground, $this->background, $this->options);
    }
    /**
     * {@inheritdoc}
     */
    public function setOptions(array $options)
    {
        $this->color = new Color($this->foreground, $this->background, $this->options = $options);
    }
    /**
     * {@inheritdoc}
     */
    public function apply(string $text)
    {
        if (null === $this->handlesHrefGracefully) {
            $this->handlesHrefGracefully = 'JetBrains-JediTerm' !== \getenv('TERMINAL_EMULATOR') && (!\getenv('KONSOLE_VERSION') || (int) \getenv('KONSOLE_VERSION') > 201100);
        }
        if (null !== $this->href && $this->handlesHrefGracefully) {
            $text = "\x1b]8;;{$this->href}\x1b\\{$text}\x1b]8;;\x1b\\";
        }
        return $this->color->apply($text);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Formatter;

/**
 * Formatter interface for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 */
interface OutputFormatterInterface
{
    /**
     * Sets the decorated flag.
     */
    public function setDecorated(bool $decorated);
    /**
     * Whether the output will decorate messages.
     *
     * @return bool
     */
    public function isDecorated();
    /**
     * Sets a new style.
     */
    public function setStyle(string $name, OutputFormatterStyleInterface $style);
    /**
     * Checks if output formatter has style with specified name.
     *
     * @return bool
     */
    public function hasStyle(string $name);
    /**
     * Gets style options from style with specified name.
     *
     * @return OutputFormatterStyleInterface
     *
     * @throws \InvalidArgumentException When style isn't defined
     */
    public function getStyle(string $name);
    /**
     * Formats a message according to the given styles.
     *
     * @return (string | null)
     */
    public function format(?string $message);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Formatter;

/**
 * @author Tien Xuan Vo <tien.xuan.vo@gmail.com>
 */
final class NullOutputFormatterStyle implements OutputFormatterStyleInterface
{
    /**
     * {@inheritdoc}
     */
    public function apply(string $text) : string
    {
        return $text;
    }
    /**
     * {@inheritdoc}
     */
    public function setBackground(string $color = null) : void
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function setForeground(string $color = null) : void
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function setOption(string $option) : void
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function setOptions(array $options) : void
    {
        // do nothing
    }
    /**
     * {@inheritdoc}
     */
    public function unsetOption(string $option) : void
    {
        // do nothing
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Formatter;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * Formatter class for console output.
 *
 * @author Konstantin Kudryashov <ever.zet@gmail.com>
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
class OutputFormatter implements WrappableOutputFormatterInterface
{
    private $decorated;
    private $styles = [];
    private $styleStack;
    /**
     *
     */
    public function __clone()
    {
        $this->styleStack = clone $this->styleStack;
        foreach ($this->styles as $key => $value) {
            $this->styles[$key] = clone $value;
        }
    }
    /**
     * Escapes "<" special char in given text.
     *
     * @return string
     */
    public static function escape(string $text)
    {
        $text = \preg_replace('/([^\\\\]?)</', '$1\\<', $text);
        return self::escapeTrailingBackslash($text);
    }
    /**
     * Escapes trailing "\" in given text.
     *
     * @internal
     */
    public static function escapeTrailingBackslash(string $text) : string
    {
        if (\str_ends_with($text, '\\')) {
            $len = \strlen($text);
            $text = \rtrim($text, '\\');
            $text = \str_replace("\x00", '', $text);
            $text .= \str_repeat("\x00", $len - \strlen($text));
        }
        return $text;
    }
    /**
     * Initializes console output formatter.
     *
     * @param OutputFormatterStyleInterface[] $styles Array of "name => FormatterStyle" instances
     */
    public function __construct(bool $decorated = \false, array $styles = [])
    {
        $this->decorated = $decorated;
        $this->setStyle('error', new OutputFormatterStyle('white', 'red'));
        $this->setStyle('info', new OutputFormatterStyle('green'));
        $this->setStyle('comment', new OutputFormatterStyle('yellow'));
        $this->setStyle('question', new OutputFormatterStyle('black', 'cyan'));
        foreach ($styles as $name => $style) {
            $this->setStyle($name, $style);
        }
        $this->styleStack = new OutputFormatterStyleStack();
    }
    /**
     * {@inheritdoc}
     */
    public function setDecorated(bool $decorated)
    {
        $this->decorated = $decorated;
    }
    /**
     * {@inheritdoc}
     */
    public function isDecorated()
    {
        return $this->decorated;
    }
    /**
     * {@inheritdoc}
     */
    public function setStyle(string $name, OutputFormatterStyleInterface $style)
    {
        $this->styles[\strtolower($name)] = $style;
    }
    /**
     * {@inheritdoc}
     */
    public function hasStyle(string $name)
    {
        return isset($this->styles[\strtolower($name)]);
    }
    /**
     * {@inheritdoc}
     */
    public function getStyle(string $name)
    {
        if (!$this->hasStyle($name)) {
            throw new InvalidArgumentException(\sprintf('Undefined style: "%s".', $name));
        }
        return $this->styles[\strtolower($name)];
    }
    /**
     * {@inheritdoc}
     */
    public function format(?string $message)
    {
        return $this->formatAndWrap($message, 0);
    }
    /**
     * {@inheritdoc}
     */
    public function formatAndWrap(?string $message, int $width)
    {
        $offset = 0;
        $output = '';
        $tagRegex = '[a-z][^<>]*+';
        $currentLineLength = 0;
        \preg_match_all("#<(({$tagRegex}) | /({$tagRegex})?)>#ix", $message, $matches, \PREG_OFFSET_CAPTURE);
        foreach ($matches[0] as $i => $match) {
            $pos = $match[1];
            $text = $match[0];
            if (0 != $pos && '\\' == $message[$pos - 1]) {
                continue;
            }
            // add the text up to the next tag
            $output .= $this->applyCurrentStyle(\Phabel\Target\Php80\Polyfill::substr($message, $offset, $pos - $offset), $output, $width, $currentLineLength);
            $offset = $pos + \strlen($text);
            // opening tag?
            if ($open = '/' != $text[1]) {
                $tag = $matches[1][$i][0];
            } else {
                $tag = $matches[3][$i][0] ?? '';
            }
            if (!$open && !$tag) {
                // </>
                $this->styleStack->pop();
            } elseif (null === ($style = $this->createStyleFromString($tag))) {
                $output .= $this->applyCurrentStyle($text, $output, $width, $currentLineLength);
            } elseif ($open) {
                $this->styleStack->push($style);
            } else {
                $this->styleStack->pop($style);
            }
        }
        $output .= $this->applyCurrentStyle(\Phabel\Target\Php80\Polyfill::substr($message, $offset), $output, $width, $currentLineLength);
        if (\str_contains($output, "\x00")) {
            return \strtr($output, ["\x00" => '\\', '\\<' => '<']);
        }
        return \str_replace('\\<', '<', $output);
    }
    /**
     * @return OutputFormatterStyleStack
     */
    public function getStyleStack()
    {
        return $this->styleStack;
    }
    /**
     * Tries to create new style instance from string.
     */
    private function createStyleFromString(string $string) : ?OutputFormatterStyleInterface
    {
        if (isset($this->styles[$string])) {
            return $this->styles[$string];
        }
        if (!\preg_match_all('/([^=]+)=([^;]+)(;|$)/', $string, $matches, \PREG_SET_ORDER)) {
            return null;
        }
        $style = new OutputFormatterStyle();
        foreach ($matches as $match) {
            \array_shift($match);
            $match[0] = \strtolower($match[0]);
            if ('fg' == $match[0]) {
                $style->setForeground(\strtolower($match[1]));
            } elseif ('bg' == $match[0]) {
                $style->setBackground(\strtolower($match[1]));
            } elseif ('href' === $match[0]) {
                $style->setHref($match[1]);
            } elseif ('options' === $match[0]) {
                \preg_match_all('([^,;]+)', \strtolower($match[1]), $options);
                $options = \array_shift($options);
                foreach ($options as $option) {
                    $style->setOption($option);
                }
            } else {
                return null;
            }
        }
        return $style;
    }
    /**
     * Applies current style from stack to text, if must be applied.
     */
    private function applyCurrentStyle(string $text, string $current, int $width, int &$currentLineLength) : string
    {
        if ('' === $text) {
            return '';
        }
        if (!$width) {
            return $this->isDecorated() ? $this->styleStack->getCurrent()->apply($text) : $text;
        }
        if (!$currentLineLength && '' !== $current) {
            $text = \ltrim($text);
        }
        if ($currentLineLength) {
            $prefix = \Phabel\Target\Php80\Polyfill::substr($text, 0, $i = $width - $currentLineLength) . "\n";
            $text = \Phabel\Target\Php80\Polyfill::substr($text, $i);
        } else {
            $prefix = '';
        }
        \preg_match('~(\\n)$~', $text, $matches);
        $text = $prefix . \preg_replace('~([^\\n]{' . $width . '})\\ *~', "\$1\n", $text);
        $text = \rtrim($text, "\n") . ($matches[1] ?? '');
        if (!$currentLineLength && '' !== $current && "\n" !== \Phabel\Target\Php80\Polyfill::substr($current, -1)) {
            $text = "\n" . $text;
        }
        $lines = \explode("\n", $text);
        foreach ($lines as $line) {
            $currentLineLength += \strlen($line);
            if ($width <= $currentLineLength) {
                $currentLineLength = 0;
            }
        }
        if ($this->isDecorated()) {
            foreach ($lines as $i => $line) {
                $lines[$i] = $this->styleStack->getCurrent()->apply($line);
            }
        }
        return \implode("\n", $lines);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Formatter;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Contracts\Service\ResetInterface;
/**
 * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
 */
class OutputFormatterStyleStack implements ResetInterface
{
    /**
     * @var OutputFormatterStyleInterface[]
     */
    private $styles;
    private $emptyStyle;
    /**
     *
     */
    public function __construct(OutputFormatterStyleInterface $emptyStyle = null)
    {
        $this->emptyStyle = $emptyStyle ?? new OutputFormatterStyle();
        $this->reset();
    }
    /**
     * Resets stack (ie. empty internal arrays).
     */
    public function reset()
    {
        $this->styles = [];
    }
    /**
     * Pushes a style in the stack.
     */
    public function push(OutputFormatterStyleInterface $style)
    {
        $this->styles[] = $style;
    }
    /**
     * Pops a style from the stack.
     *
     * @return OutputFormatterStyleInterface
     *
     * @throws InvalidArgumentException When style tags incorrectly nested
     */
    public function pop(OutputFormatterStyleInterface $style = null)
    {
        if (empty($this->styles)) {
            return $this->emptyStyle;
        }
        if (null === $style) {
            return \array_pop($this->styles);
        }
        foreach (\array_reverse($this->styles, \true) as $index => $stackedStyle) {
            if ($style->apply('') === $stackedStyle->apply('')) {
                $this->styles = \array_slice($this->styles, 0, $index);
                return $stackedStyle;
            }
        }
        throw new InvalidArgumentException('Incorrectly nested style tag found.');
    }
    /**
     * Computes current style with stacks top codes.
     *
     * @return OutputFormatterStyle
     */
    public function getCurrent()
    {
        if (empty($this->styles)) {
            return $this->emptyStyle;
        }
        return $this->styles[\count($this->styles) - 1];
    }
    /**
     * @return $this
     */
    public function setEmptyStyle(OutputFormatterStyleInterface $emptyStyle)
    {
        $this->emptyStyle = $emptyStyle;
        return $this;
    }
    /**
     * @return OutputFormatterStyleInterface
     */
    public function getEmptyStyle()
    {
        return $this->emptyStyle;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\CommandLoader;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Exception\CommandNotFoundException;
/**
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface CommandLoaderInterface
{
    /**
     * Loads a command.
     *
     * @return Command
     *
     * @throws CommandNotFoundException
     */
    public function get(string $name);
    /**
     * Checks if a command exists.
     *
     * @return bool
     */
    public function has(string $name);
    /**
     * @return string[]
     */
    public function getNames();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\CommandLoader;

use PhabelVendor\Symfony\Component\Console\Exception\CommandNotFoundException;
/**
 * A simple command loader using factories to instantiate commands lazily.
 *
 * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
 */
class FactoryCommandLoader implements CommandLoaderInterface
{
    private $factories;
    /**
     * @param callable[] $factories Indexed by command names
     */
    public function __construct(array $factories)
    {
        $this->factories = $factories;
    }
    /**
     * {@inheritdoc}
     */
    public function has(string $name)
    {
        return isset($this->factories[$name]);
    }
    /**
     * {@inheritdoc}
     */
    public function get(string $name)
    {
        if (!isset($this->factories[$name])) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }
        $factory = $this->factories[$name];
        return $factory();
    }
    /**
     * {@inheritdoc}
     */
    public function getNames()
    {
        return \array_keys($this->factories);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\CommandLoader;

use PhabelVendor\Psr\Container\ContainerInterface;
use PhabelVendor\Symfony\Component\Console\Exception\CommandNotFoundException;
/**
 * Loads commands from a PSR-11 container.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
class ContainerCommandLoader implements CommandLoaderInterface
{
    private $container;
    private $commandMap;
    /**
     * @param array $commandMap An array with command names as keys and service ids as values
     */
    public function __construct(ContainerInterface $container, array $commandMap)
    {
        $this->container = $container;
        $this->commandMap = $commandMap;
    }
    /**
     * {@inheritdoc}
     */
    public function get(string $name)
    {
        if (!$this->has($name)) {
            throw new CommandNotFoundException(\sprintf('Command "%s" does not exist.', $name));
        }
        return $this->container->get($this->commandMap[$name]);
    }
    /**
     * {@inheritdoc}
     */
    public function has(string $name)
    {
        return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]);
    }
    /**
     * {@inheritdoc}
     */
    public function getNames()
    {
        return \array_keys($this->commandMap);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Console\Question\ChoiceQuestion;
use PhabelVendor\Symfony\Component\Console\Question\ConfirmationQuestion;
use PhabelVendor\Symfony\Component\Console\Question\Question;
use PhabelVendor\Symfony\Component\Console\Style\SymfonyStyle;
/**
 * Symfony Style Guide compliant question helper.
 *
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class SymfonyQuestionHelper extends QuestionHelper
{
    /**
     * {@inheritdoc}
     */
    protected function writePrompt(OutputInterface $output, Question $question)
    {
        $text = OutputFormatter::escapeTrailingBackslash($question->getQuestion());
        $default = $question->getDefault();
        if ($question->isMultiline()) {
            $text .= \sprintf(' (press %s to continue)', $this->getEofShortcut());
        }
        switch (\true) {
            case null === $default:
                $text = \sprintf(' <info>%s</info>:', $text);
                break;
            case $question instanceof ConfirmationQuestion:
                $text = \sprintf(' <info>%s (yes/no)</info> [<comment>%s</comment>]:', $text, $default ? 'yes' : 'no');
                break;
            case $question instanceof ChoiceQuestion && $question->isMultiselect():
                $choices = $question->getChoices();
                $default = \explode(',', $default);
                foreach ($default as $key => $value) {
                    $default[$key] = $choices[\trim($value)];
                }
                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape(\implode(', ', $default)));
                break;
            case $question instanceof ChoiceQuestion:
                $choices = $question->getChoices();
                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($choices[$default] ?? $default));
                break;
            default:
                $text = \sprintf(' <info>%s</info> [<comment>%s</comment>]:', $text, OutputFormatter::escape($default));
        }
        $output->writeln($text);
        $prompt = ' > ';
        if ($question instanceof ChoiceQuestion) {
            $output->writeln($this->formatChoiceQuestionChoices($question, 'comment'));
            $prompt = $question->getPrompt();
        }
        $output->write($prompt);
    }
    /**
     * {@inheritdoc}
     */
    protected function writeError(OutputInterface $output, \Exception $error)
    {
        if ($output instanceof SymfonyStyle) {
            $output->newLine();
            $output->error($error->getMessage());
            return;
        }
        parent::writeError($output, $error);
    }
    /**
     *
     */
    private function getEofShortcut() : string
    {
        if ('Windows' === \PHP_OS_FAMILY) {
            return '<comment>Ctrl+Z</comment> then <comment>Enter</comment>';
        }
        return '<comment>Ctrl+D</comment>';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

/**
 * Marks a row as being a separator.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class TableSeparator extends TableCell
{
    /**
     *
     */
    public function __construct(array $options = [])
    {
        parent::__construct('', $options);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Cursor;
use PhabelVendor\Symfony\Component\Console\Exception\MissingInputException;
use PhabelVendor\Symfony\Component\Console\Exception\RuntimeException;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\StreamableInputInterface;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleSectionOutput;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Console\Question\ChoiceQuestion;
use PhabelVendor\Symfony\Component\Console\Question\Question;
use PhabelVendor\Symfony\Component\Console\Terminal;
use function PhabelVendor\Symfony\Component\String\s;
/**
 * The QuestionHelper class provides helpers to interact with the user.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class QuestionHelper extends Helper
{
    /**
     * @var resource|null
     */
    private $inputStream;
    private static $stty = \true;
    private static $stdinIsInteractive;
    /**
     * Asks a question to the user.
     *
     * @return mixed The user answer
     *
     * @throws RuntimeException If there is no data to read in the input stream
     */
    public function ask(InputInterface $input, OutputInterface $output, Question $question)
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        if (!$input->isInteractive()) {
            return $this->getDefaultAnswer($question);
        }
        if ($input instanceof StreamableInputInterface && ($stream = $input->getStream())) {
            $this->inputStream = $stream;
        }
        try {
            if (!$question->getValidator()) {
                return $this->doAsk($output, $question);
            }
            $interviewer = function () use($output, $question) {
                return $this->doAsk($output, $question);
            };
            return $this->validateAttempts($interviewer, $output, $question);
        } catch (MissingInputException $exception) {
            $input->setInteractive(\false);
            if (null === ($fallbackOutput = $this->getDefaultAnswer($question))) {
                throw $exception;
            }
            return $fallbackOutput;
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'question';
    }
    /**
     * Prevents usage of stty.
     */
    public static function disableStty()
    {
        self::$stty = \false;
    }
    /**
     * Asks the question to the user.
     *
     * @return mixed
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    private function doAsk(OutputInterface $output, Question $question)
    {
        $this->writePrompt($output, $question);
        $inputStream = $this->inputStream ?: \STDIN;
        $autocomplete = $question->getAutocompleterCallback();
        if (null === $autocomplete || !self::$stty || !Terminal::hasSttyAvailable()) {
            $ret = \false;
            if ($question->isHidden()) {
                try {
                    $hiddenResponse = $this->getHiddenResponse($output, $inputStream, $question->isTrimmable());
                    $ret = $question->isTrimmable() ? \trim($hiddenResponse) : $hiddenResponse;
                } catch (RuntimeException $e) {
                    if (!$question->isHiddenFallback()) {
                        throw $e;
                    }
                }
            }
            if (\false === $ret) {
                $ret = $this->readInput($inputStream, $question);
                if (\false === $ret) {
                    throw new MissingInputException('Aborted.');
                }
                if ($question->isTrimmable()) {
                    $ret = \trim($ret);
                }
            }
        } else {
            $autocomplete = $this->autocomplete($output, $question, $inputStream, $autocomplete);
            $ret = $question->isTrimmable() ? \trim($autocomplete) : $autocomplete;
        }
        if ($output instanceof ConsoleSectionOutput) {
            $output->addContent($ret);
        }
        $ret = \strlen($ret) > 0 ? $ret : $question->getDefault();
        if ($normalizer = $question->getNormalizer()) {
            return $normalizer($ret);
        }
        return $ret;
    }
    /**
     * @return mixed
     */
    private function getDefaultAnswer(Question $question)
    {
        $default = $question->getDefault();
        if (null === $default) {
            return $default;
        }
        if ($validator = $question->getValidator()) {
            return \call_user_func($question->getValidator(), $default);
        } elseif ($question instanceof ChoiceQuestion) {
            $choices = $question->getChoices();
            if (!$question->isMultiselect()) {
                return $choices[$default] ?? $default;
            }
            $default = \explode(',', $default);
            foreach ($default as $k => $v) {
                $v = $question->isTrimmable() ? \trim($v) : $v;
                $default[$k] = $choices[$v] ?? $v;
            }
        }
        return $default;
    }
    /**
     * Outputs the question prompt.
     */
    protected function writePrompt(OutputInterface $output, Question $question)
    {
        $message = $question->getQuestion();
        if ($question instanceof ChoiceQuestion) {
            $output->writeln(\array_merge([$question->getQuestion()], $this->formatChoiceQuestionChoices($question, 'info')));
            $message = $question->getPrompt();
        }
        $output->write($message);
    }
    /**
     * @return string[]
     */
    protected function formatChoiceQuestionChoices(ChoiceQuestion $question, string $tag)
    {
        $messages = [];
        $maxWidth = \max(\array_map([__CLASS__, 'width'], \array_keys($choices = $question->getChoices())));
        foreach ($choices as $key => $value) {
            $padding = \str_repeat(' ', $maxWidth - self::width($key));
            $messages[] = \sprintf("  [<{$tag}>%s{$padding}</{$tag}>] %s", $key, $value);
        }
        return $messages;
    }
    /**
     * Outputs an error message.
     */
    protected function writeError(OutputInterface $output, \Exception $error)
    {
        if (null !== $this->getHelperSet() && $this->getHelperSet()->has('formatter')) {
            $message = $this->getHelperSet()->get('formatter')->formatBlock($error->getMessage(), 'error');
        } else {
            $message = '<error>' . $error->getMessage() . '</error>';
        }
        $output->writeln($message);
    }
    /**
     * Autocompletes a question.
     *
     * @param resource $inputStream
     */
    private function autocomplete(OutputInterface $output, Question $question, $inputStream, callable $autocomplete) : string
    {
        $cursor = new Cursor($output, $inputStream);
        $fullChoice = '';
        $ret = '';
        $i = 0;
        $ofs = -1;
        $matches = $autocomplete($ret);
        $numMatches = \count($matches);
        $sttyMode = \shell_exec('stty -g');
        // Disable icanon (so we can fread each keypress) and echo (we'll do echoing here instead)
        \shell_exec('stty -icanon -echo');
        // Add highlighted text style
        $output->getFormatter()->setStyle('hl', new OutputFormatterStyle('black', 'white'));
        // Read a keypress
        while (!\feof($inputStream)) {
            $c = \fread($inputStream, 1);
            // as opposed to fgets(), fread() returns an empty string when the stream content is empty, not false.
            if (\false === $c || '' === $ret && '' === $c && null === $question->getDefault()) {
                \shell_exec(\sprintf('stty %s', $sttyMode));
                throw new MissingInputException('Aborted.');
            } elseif ("" === $c) {
                // Backspace Character
                if (0 === $numMatches && 0 !== $i) {
                    --$i;
                    $cursor->moveLeft(s($fullChoice)->slice(-1)->width(\false));
                    $fullChoice = self::substr($fullChoice, 0, $i);
                }
                if (0 === $i) {
                    $ofs = -1;
                    $matches = $autocomplete($ret);
                    $numMatches = \count($matches);
                } else {
                    $numMatches = 0;
                }
                // Pop the last character off the end of our string
                $ret = self::substr($ret, 0, $i);
            } elseif ("\x1b" === $c) {
                // Did we read an escape sequence?
                $c .= \fread($inputStream, 2);
                // A = Up Arrow. B = Down Arrow
                if (isset($c[2]) && ('A' === $c[2] || 'B' === $c[2])) {
                    if ('A' === $c[2] && -1 === $ofs) {
                        $ofs = 0;
                    }
                    if (0 === $numMatches) {
                        continue;
                    }
                    $ofs += 'A' === $c[2] ? -1 : 1;
                    $ofs = ($numMatches + $ofs) % $numMatches;
                }
            } elseif (\ord($c) < 32) {
                if ("\t" === $c || "\n" === $c) {
                    if ($numMatches > 0 && -1 !== $ofs) {
                        $ret = (string) $matches[$ofs];
                        // Echo out remaining chars for current match
                        $remainingCharacters = \Phabel\Target\Php80\Polyfill::substr($ret, \strlen(\trim($this->mostRecentlyEnteredValue($fullChoice))));
                        $output->write($remainingCharacters);
                        $fullChoice .= $remainingCharacters;
                        $i = \false === ($encoding = \mb_detect_encoding($fullChoice, null, \true)) ? \strlen($fullChoice) : \mb_strlen($fullChoice, $encoding);
                        $matches = \array_filter($autocomplete($ret), function ($match) use($ret) {
                            return '' === $ret || \str_starts_with($match, $ret);
                        });
                        $numMatches = \count($matches);
                        $ofs = -1;
                    }
                    if ("\n" === $c) {
                        $output->write($c);
                        break;
                    }
                    $numMatches = 0;
                }
                continue;
            } else {
                if ("\x80" <= $c) {
                    $c .= \fread($inputStream, ["\xc0" => 1, "\xd0" => 1, "\xe0" => 2, "\xf0" => 3][$c & "\xf0"]);
                }
                $output->write($c);
                $ret .= $c;
                $fullChoice .= $c;
                ++$i;
                $tempRet = $ret;
                if ($question instanceof ChoiceQuestion && $question->isMultiselect()) {
                    $tempRet = $this->mostRecentlyEnteredValue($fullChoice);
                }
                $numMatches = 0;
                $ofs = 0;
                foreach ($autocomplete($ret) as $value) {
                    // If typed characters match the beginning chunk of value (e.g. [AcmeDe]moBundle)
                    if (\str_starts_with($value, $tempRet)) {
                        $matches[$numMatches++] = $value;
                    }
                }
            }
            $cursor->clearLineAfter();
            if ($numMatches > 0 && -1 !== $ofs) {
                $cursor->savePosition();
                // Write highlighted text, complete the partially entered response
                $charactersEntered = \strlen(\trim($this->mostRecentlyEnteredValue($fullChoice)));
                $output->write('<hl>' . OutputFormatter::escapeTrailingBackslash(\Phabel\Target\Php80\Polyfill::substr($matches[$ofs], $charactersEntered)) . '</hl>');
                $cursor->restorePosition();
            }
        }
        // Reset stty so it behaves normally again
        \shell_exec(\sprintf('stty %s', $sttyMode));
        return $fullChoice;
    }
    /**
     *
     */
    private function mostRecentlyEnteredValue(string $entered) : string
    {
        // Determine the most recent value that the user entered
        if (!\str_contains($entered, ',')) {
            return $entered;
        }
        $choices = \explode(',', $entered);
        if ('' !== ($lastChoice = \trim($choices[\count($choices) - 1]))) {
            return $lastChoice;
        }
        return $entered;
    }
    /**
     * Gets a hidden response from user.
     *
     * @param resource $inputStream The handler resource
     * @param bool $trimmable Is the answer trimmable
     *
     * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden
     */
    private function getHiddenResponse(OutputInterface $output, $inputStream, bool $trimmable = \true) : string
    {
        if ('\\' === \DIRECTORY_SEPARATOR) {
            $exe = __DIR__ . '/../Resources/bin/hiddeninput.exe';
            // handle code running from a phar
            if ('phar:' === \Phabel\Target\Php80\Polyfill::substr(__FILE__, 0, 5)) {
                $tmpExe = \sys_get_temp_dir() . '/hiddeninput.exe';
                \copy($exe, $tmpExe);
                $exe = $tmpExe;
            }
            $sExec = \shell_exec('"' . $exe . '"');
            $value = $trimmable ? \rtrim($sExec) : $sExec;
            $output->writeln('');
            if (isset($tmpExe)) {
                \unlink($tmpExe);
            }
            return $value;
        }
        if (self::$stty && Terminal::hasSttyAvailable()) {
            $sttyMode = \shell_exec('stty -g');
            \shell_exec('stty -echo');
        } elseif ($this->isInteractiveInput($inputStream)) {
            throw new RuntimeException('Unable to hide the response.');
        }
        $value = \fgets($inputStream, 4096);
        if (self::$stty && Terminal::hasSttyAvailable()) {
            \shell_exec(\sprintf('stty %s', $sttyMode));
        }
        if (\false === $value) {
            throw new MissingInputException('Aborted.');
        }
        if ($trimmable) {
            $value = \trim($value);
        }
        $output->writeln('');
        return $value;
    }
    /**
     * Validates an attempt.
     *
     * @param callable $interviewer A callable that will ask for a question and return the result
     *
     * @return mixed The validated response
     *
     * @throws \Exception In case the max number of attempts has been reached and no valid response has been given
     */
    private function validateAttempts(callable $interviewer, OutputInterface $output, Question $question)
    {
        $error = null;
        $attempts = $question->getMaxAttempts();
        while (null === $attempts || $attempts--) {
            if (null !== $error) {
                $this->writeError($output, $error);
            }
            try {
                return $question->getValidator()($interviewer());
            } catch (RuntimeException $e) {
                throw $e;
            } catch (\Exception $error) {
            }
        }
        throw $error;
    }
    /**
     *
     */
    private function isInteractiveInput($inputStream) : bool
    {
        if ('php://stdin' !== (\stream_get_meta_data($inputStream)['uri'] ?? null)) {
            return \false;
        }
        if (null !== self::$stdinIsInteractive) {
            return self::$stdinIsInteractive;
        }
        if (\function_exists('stream_isatty')) {
            return self::$stdinIsInteractive = \stream_isatty(\fopen('php://stdin', 'r'));
        }
        if (\function_exists('posix_isatty')) {
            return self::$stdinIsInteractive = \posix_isatty(\fopen('php://stdin', 'r'));
        }
        if (!\function_exists('exec')) {
            return self::$stdinIsInteractive = \true;
        }
        \exec('stty 2> /dev/null', $output, $status);
        return self::$stdinIsInteractive = 1 !== $status;
    }
    /**
     * Reads one or more lines of input and returns what is read.
     *
     * @param resource $inputStream The handler resource
     * @param Question $question The question being asked
     *
     * @return (string | false) The input received, false in case input could not be read
     */
    private function readInput($inputStream, Question $question)
    {
        if (!$question->isMultiline()) {
            $cp = $this->setIOCodepage();
            $ret = \fgets($inputStream, 4096);
            return $this->resetIOCodepage($cp, $ret);
        }
        $multiLineStreamReader = $this->cloneInputStream($inputStream);
        if (null === $multiLineStreamReader) {
            return \false;
        }
        $ret = '';
        $cp = $this->setIOCodepage();
        while (\false !== ($char = \fgetc($multiLineStreamReader))) {
            if (\PHP_EOL === "{$ret}{$char}") {
                break;
            }
            $ret .= $char;
        }
        return $this->resetIOCodepage($cp, $ret);
    }
    /**
     * Sets console I/O to the host code page.
     *
     * @return int Previous code page in IBM/EBCDIC format
     */
    private function setIOCodepage() : int
    {
        if (\function_exists('sapi_windows_cp_set')) {
            $cp = \sapi_windows_cp_get();
            \sapi_windows_cp_set(\sapi_windows_cp_get('oem'));
            return $cp;
        }
        return 0;
    }
    /**
     * Sets console I/O to the specified code page and converts the user input.
     *
     * @param (string | false) $input
     *
     * @return (string | false)
     */
    private function resetIOCodepage(int $cp, $input)
    {
        if (0 !== $cp) {
            \sapi_windows_cp_set($cp);
            if (\false !== $input && '' !== $input) {
                $input = \sapi_windows_cp_conv(\sapi_windows_cp_get('oem'), $cp, $input);
            }
        }
        return $input;
    }
    /**
    * Clones an input stream in order to act on one instance of the same
    stream without affecting the other instance.
    *
    * @param resource $inputStream The handler resource
    *
    * @return (resource | null) The cloned resource, null in case it could not be cloned
    */
    private function cloneInputStream($inputStream)
    {
        $streamMetaData = \stream_get_meta_data($inputStream);
        $seekable = $streamMetaData['seekable'] ?? \false;
        $mode = $streamMetaData['mode'] ?? 'rb';
        $uri = $streamMetaData['uri'] ?? null;
        if (null === $uri) {
            return null;
        }
        $cloneStream = \fopen($uri, $mode);
        // For seekable and writable streams, add all the same data to the
        // cloned stream and then seek to the same offset.
        if (\true === $seekable && !\in_array($mode, ['r', 'rb', 'rt'])) {
            $offset = \ftell($inputStream);
            \rewind($inputStream);
            \stream_copy_to_stream($inputStream, $cloneStream);
            \fseek($inputStream, $offset);
            \fseek($cloneStream, $offset);
        }
        return $cloneStream;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Process\Exception\ProcessFailedException;
use PhabelVendor\Symfony\Component\Process\Process;
/**
 * The ProcessHelper class provides helpers to run external processes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @final
 */
class ProcessHelper extends Helper
{
    /**
    * Runs an external process.
    *
    * @param (array | Process) $cmd An instance of Process or an array of the command and arguments
    * @param (callable | null) $callback A PHP callback to run whenever there is some
    output available on STDOUT or STDERR
    *
    * @return Process
    */
    public function run(OutputInterface $output, $cmd, string $error = null, callable $callback = null, int $verbosity = OutputInterface::VERBOSITY_VERY_VERBOSE) : Process
    {
        if (!\class_exists(Process::class)) {
            throw new \LogicException('The ProcessHelper cannot be run as the Process component is not installed. Try running "compose require symfony/process".');
        }
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        $formatter = $this->getHelperSet()->get('debug_formatter');
        if ($cmd instanceof Process) {
            $cmd = [$cmd];
        }
        if (!\is_array($cmd)) {
            throw new \TypeError(\sprintf('The "command" argument of "%s()" must be an array or a "%s" instance, "%s" given.', __METHOD__, Process::class, \get_debug_type($cmd)));
        }
        if (\is_string($cmd[0] ?? null)) {
            $process = new Process($cmd);
            $cmd = [];
        } elseif (($cmd[0] ?? null) instanceof Process) {
            $process = $cmd[0];
            unset($cmd[0]);
        } else {
            throw new \InvalidArgumentException(\sprintf('Invalid command provided to "%s()": the command should be an array whose first element is either the path to the binary to run or a "Process" object.', __METHOD__));
        }
        if ($verbosity <= $output->getVerbosity()) {
            $output->write($formatter->start(\spl_object_hash($process), $this->escapeString($process->getCommandLine())));
        }
        if ($output->isDebug()) {
            $callback = $this->wrapCallback($output, $process, $callback);
        }
        $process->run($callback, $cmd);
        if ($verbosity <= $output->getVerbosity()) {
            $message = $process->isSuccessful() ? 'Command ran successfully' : \sprintf('%s Command did not run successfully', $process->getExitCode());
            $output->write($formatter->stop(\spl_object_hash($process), $message, $process->isSuccessful()));
        }
        if (!$process->isSuccessful() && null !== $error) {
            $output->writeln(\sprintf('<error>%s</error>', $this->escapeString($error)));
        }
        return $process;
    }
    /**
    * Runs the process.
    *
    * This is identical to run() except that an exception is thrown if the process
    exits with a non-zero exit code.
    *
    * @param (array | Process) $cmd An instance of Process or a command to run
    * @param (callable | null) $callback A PHP callback to run whenever there is some
    output available on STDOUT or STDERR
    *
    * @return Process
    *
    * @throws ProcessFailedException
    *
    * @see run()
    */
    public function mustRun(OutputInterface $output, $cmd, string $error = null, callable $callback = null) : Process
    {
        $process = $this->run($output, $cmd, $error, $callback);
        if (!$process->isSuccessful()) {
            throw new ProcessFailedException($process);
        }
        return $process;
    }
    /**
     * Wraps a Process callback to add debugging output.
     */
    public function wrapCallback(OutputInterface $output, Process $process, callable $callback = null) : callable
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        $formatter = $this->getHelperSet()->get('debug_formatter');
        return function ($type, $buffer) use($output, $process, $callback, $formatter) {
            $output->write($formatter->progress(\spl_object_hash($process), $this->escapeString($buffer), Process::ERR === $type));
            if (null !== $callback) {
                $callback($type, $buffer);
            }
        };
    }
    /**
     *
     */
    private function escapeString(string $str) : string
    {
        return \str_replace('<', '\\<', $str);
    }
    /**
     * {@inheritdoc}
     */
    public function getName() : string
    {
        return 'process';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterInterface;
use PhabelVendor\Symfony\Component\String\UnicodeString;
/**
 * Helper is the base class for all helper classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Helper implements HelperInterface
{
    protected $helperSet = null;
    /**
     * {@inheritdoc}
     */
    public function setHelperSet(HelperSet $helperSet = null)
    {
        $this->helperSet = $helperSet;
    }
    /**
     * {@inheritdoc}
     */
    public function getHelperSet()
    {
        return $this->helperSet;
    }
    /**
     * Returns the length of a string, using mb_strwidth if it is available.
     *
     * @deprecated since Symfony 5.3
     *
     * @return int
     */
    public static function strlen(?string $string)
    {
        trigger_deprecation('symfony/console', '5.3', 'Method "%s()" is deprecated and will be removed in Symfony 6.0. Use Helper::width() or Helper::length() instead.', __METHOD__);
        return self::width($string);
    }
    /**
    * Returns the width of a string, using mb_strwidth if it is available.
    The width is how many characters positions the string will use.
    */
    public static function width(?string $string) : int
    {
        $string ?? ($string = '');
        if (\preg_match('//u', $string)) {
            return (new UnicodeString($string))->width(\false);
        }
        if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) {
            return \strlen($string);
        }
        return \mb_strwidth($string, $encoding);
    }
    /**
    * Returns the length of a string, using mb_strlen if it is available.
    The length is related to how many bytes the string will use.
    */
    public static function length(?string $string) : int
    {
        $string ?? ($string = '');
        if (\preg_match('//u', $string)) {
            return (new UnicodeString($string))->length();
        }
        if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) {
            return \strlen($string);
        }
        return \mb_strlen($string, $encoding);
    }
    /**
     * Returns the subset of a string, using mb_substr if it is available.
     *
     * @return string
     */
    public static function substr(?string $string, int $from, int $length = null)
    {
        $string ?? ($string = '');
        if (\false === ($encoding = \mb_detect_encoding($string, null, \true))) {
            return \Phabel\Target\Php80\Polyfill::substr($string, $from, $length);
        }
        return \mb_substr($string, $from, $length, $encoding);
    }
    /**
     *
     */
    public static function formatTime($secs)
    {
        static $timeFormats = [[0, '< 1 sec'], [1, '1 sec'], [2, 'secs', 1], [60, '1 min'], [120, 'mins', 60], [3600, '1 hr'], [7200, 'hrs', 3600], [86400, '1 day'], [172800, 'days', 86400]];
        foreach ($timeFormats as $index => $format) {
            if ($secs >= $format[0]) {
                if (isset($timeFormats[$index + 1]) && $secs < $timeFormats[$index + 1][0] || $index == \count($timeFormats) - 1) {
                    if (2 == \count($format)) {
                        return $format[1];
                    }
                    return \floor($secs / $format[2]) . ' ' . $format[1];
                }
            }
        }
    }
    /**
     *
     */
    public static function formatMemory(int $memory)
    {
        if ($memory >= 1024 * 1024 * 1024) {
            return \sprintf('%.1f GiB', $memory / 1024 / 1024 / 1024);
        }
        if ($memory >= 1024 * 1024) {
            return \sprintf('%.1f MiB', $memory / 1024 / 1024);
        }
        if ($memory >= 1024) {
            return \sprintf('%d KiB', $memory / 1024);
        }
        return \sprintf('%d B', $memory);
    }
    /**
     * @deprecated since Symfony 5.3
     */
    public static function strlenWithoutDecoration(OutputFormatterInterface $formatter, ?string $string)
    {
        trigger_deprecation('symfony/console', '5.3', 'Method "%s()" is deprecated and will be removed in Symfony 6.0. Use Helper::removeDecoration() instead.', __METHOD__);
        return self::width(self::removeDecoration($formatter, $string));
    }
    /**
     *
     */
    public static function removeDecoration(OutputFormatterInterface $formatter, ?string $string)
    {
        $isDecorated = $formatter->isDecorated();
        $formatter->setDecorated(\false);
        // remove <...> formatting
        $string = $formatter->format($string ?? '');
        // remove already formatted characters
        $string = \preg_replace("/\x1b\\[[^m]*m/", '', $string ?? '');
        $formatter->setDecorated($isDecorated);
        return $string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

/**
 * Helps outputting debug information when running an external program from a command.
 *
 * An external program can be a Process, an HTTP request, or anything else.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class DebugFormatterHelper extends Helper
{
    private const COLORS = ['black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'default'];
    private $started = [];
    private $count = -1;
    /**
     * Starts a debug formatting session.
     *
     * @return string
     */
    public function start(string $id, string $message, string $prefix = 'RUN')
    {
        $this->started[$id] = ['border' => ++$this->count % \count(self::COLORS)];
        return \sprintf("%s<bg=blue;fg=white> %s </> <fg=blue>%s</>\n", $this->getBorder($id), $prefix, $message);
    }
    /**
     * Adds progress to a formatting session.
     *
     * @return string
     */
    public function progress(string $id, string $buffer, bool $error = \false, string $prefix = 'OUT', string $errorPrefix = 'ERR')
    {
        $message = '';
        if ($error) {
            if (isset($this->started[$id]['out'])) {
                $message .= "\n";
                unset($this->started[$id]['out']);
            }
            if (!isset($this->started[$id]['err'])) {
                $message .= \sprintf('%s<bg=red;fg=white> %s </> ', $this->getBorder($id), $errorPrefix);
                $this->started[$id]['err'] = \true;
            }
            $message .= \str_replace("\n", \sprintf("\n%s<bg=red;fg=white> %s </> ", $this->getBorder($id), $errorPrefix), $buffer);
        } else {
            if (isset($this->started[$id]['err'])) {
                $message .= "\n";
                unset($this->started[$id]['err']);
            }
            if (!isset($this->started[$id]['out'])) {
                $message .= \sprintf('%s<bg=green;fg=white> %s </> ', $this->getBorder($id), $prefix);
                $this->started[$id]['out'] = \true;
            }
            $message .= \str_replace("\n", \sprintf("\n%s<bg=green;fg=white> %s </> ", $this->getBorder($id), $prefix), $buffer);
        }
        return $message;
    }
    /**
     * Stops a formatting session.
     *
     * @return string
     */
    public function stop(string $id, string $message, bool $successful, string $prefix = 'RES')
    {
        $trailingEOL = isset($this->started[$id]['out']) || isset($this->started[$id]['err']) ? "\n" : '';
        if ($successful) {
            return \sprintf("%s%s<bg=green;fg=white> %s </> <fg=green>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
        }
        $message = \sprintf("%s%s<bg=red;fg=white> %s </> <fg=red>%s</>\n", $trailingEOL, $this->getBorder($id), $prefix, $message);
        unset($this->started[$id]['out'], $this->started[$id]['err']);
        return $message;
    }
    /**
     *
     */
    private function getBorder(string $id) : string
    {
        return \sprintf('<bg=%s> </>', self::COLORS[$this->started[$id]['border']]);
    }
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'debug_formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
/**
 * Defines the styles for a Table.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Ð¡Ð°ÑˆÐ° Ð¡Ñ‚Ð°Ð¼ÐµÐ½ÐºÐ¾Ð²Ð¸Ñ› <umpirsky@gmail.com>
 * @author Dany Maillard <danymaillard93b@gmail.com>
 */
class TableStyle
{
    private $paddingChar = ' ';
    private $horizontalOutsideBorderChar = '-';
    private $horizontalInsideBorderChar = '-';
    private $verticalOutsideBorderChar = '|';
    private $verticalInsideBorderChar = '|';
    private $crossingChar = '+';
    private $crossingTopRightChar = '+';
    private $crossingTopMidChar = '+';
    private $crossingTopLeftChar = '+';
    private $crossingMidRightChar = '+';
    private $crossingBottomRightChar = '+';
    private $crossingBottomMidChar = '+';
    private $crossingBottomLeftChar = '+';
    private $crossingMidLeftChar = '+';
    private $crossingTopLeftBottomChar = '+';
    private $crossingTopMidBottomChar = '+';
    private $crossingTopRightBottomChar = '+';
    private $headerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
    private $footerTitleFormat = '<fg=black;bg=white;options=bold> %s </>';
    private $cellHeaderFormat = '<info>%s</info>';
    private $cellRowFormat = '%s';
    private $cellRowContentFormat = ' %s ';
    private $borderFormat = '%s';
    private $padType = \STR_PAD_RIGHT;
    /**
     * Sets padding character, used for cell padding.
     *
     * @return $this
     */
    public function setPaddingChar(string $paddingChar)
    {
        if (!$paddingChar) {
            throw new LogicException('The padding char must not be empty.');
        }
        $this->paddingChar = $paddingChar;
        return $this;
    }
    /**
     * Gets padding character, used for cell padding.
     *
     * @return string
     */
    public function getPaddingChar()
    {
        return $this->paddingChar;
    }
    /**
    * Sets horizontal border characters.
    *
    * <code>
    â•”â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•¤â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•¤â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•—
    1 ISBN          2 Title                    â”‚ Author           â•‘
    â• â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•ªâ•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•ªâ•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•£
    â•‘ 99921-58-10-7 â”‚ Divine Comedy            â”‚ Dante Alighieri  â•‘
    â•‘ 9971-5-0210-0 â”‚ A Tale of Two Cities     â”‚ Charles Dickens  â•‘
    â•‘ 960-425-059-0 â”‚ The Lord of the Rings    â”‚ J. R. R. Tolkien â•‘
    â•‘ 80-902734-1-6 â”‚ And Then There Were None â”‚ Agatha Christie  â•‘
    â•šâ•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•§â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•§â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�
    </code>
    *
    * @return $this
    */
    public function setHorizontalBorderChars(string $outside, string $inside = null) : self
    {
        $this->horizontalOutsideBorderChar = $outside;
        $this->horizontalInsideBorderChar = $inside ?? $outside;
        return $this;
    }
    /**
    * Sets vertical border characters.
    *
    * <code>
    â•”â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•¤â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•¤â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•—
    â•‘ ISBN          â”‚ Title                    â”‚ Author           â•‘
    â• â•�â•�â•�â•�â•�â•�â•�1â•�â•�â•�â•�â•�â•�â•�â•ªâ•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•ªâ•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•£
    â•‘ 99921-58-10-7 â”‚ Divine Comedy            â”‚ Dante Alighieri  â•‘
    â•‘ 9971-5-0210-0 â”‚ A Tale of Two Cities     â”‚ Charles Dickens  â•‘
    â•Ÿâ”€â”€â”€â”€â”€â”€â”€2â”€â”€â”€â”€â”€â”€â”€â”¼â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”¼â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â•¢
    â•‘ 960-425-059-0 â”‚ The Lord of the Rings    â”‚ J. R. R. Tolkien â•‘
    â•‘ 80-902734-1-6 â”‚ And Then There Were None â”‚ Agatha Christie  â•‘
    â•šâ•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•§â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•§â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�
    </code>
    *
    * @return $this
    */
    public function setVerticalBorderChars(string $outside, string $inside = null) : self
    {
        $this->verticalOutsideBorderChar = $outside;
        $this->verticalInsideBorderChar = $inside ?? $outside;
        return $this;
    }
    /**
     * Gets border characters.
     *
     * @internal
     */
    public function getBorderChars() : array
    {
        return [$this->horizontalOutsideBorderChar, $this->verticalOutsideBorderChar, $this->horizontalInsideBorderChar, $this->verticalInsideBorderChar];
    }
    /**
    * Sets crossing characters.
    *
    * Example:
    <code>
    1â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�2â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�2â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�3
    â•‘ ISBN          â”‚ Title                    â”‚ Author           â•‘
    8'â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�0'â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�0'â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�4'
    â•‘ 99921-58-10-7 â”‚ Divine Comedy            â”‚ Dante Alighieri  â•‘
    â•‘ 9971-5-0210-0 â”‚ A Tale of Two Cities     â”‚ Charles Dickens  â•‘
    8â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€0â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€0â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€â”€4
    â•‘ 960-425-059-0 â”‚ The Lord of the Rings    â”‚ J. R. R. Tolkien â•‘
    â•‘ 80-902734-1-6 â”‚ And Then There Were None â”‚ Agatha Christie  â•‘
    7â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�6â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�6â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�â•�5
    </code>
    *
    * @param string $cross Crossing char (see #0 of example)
    * @param string $topLeft Top left char (see #1 of example)
    * @param string $topMid Top mid char (see #2 of example)
    * @param string $topRight Top right char (see #3 of example)
    * @param string $midRight Mid right char (see #4 of example)
    * @param string $bottomRight Bottom right char (see #5 of example)
    * @param string $bottomMid Bottom mid char (see #6 of example)
    * @param string $bottomLeft Bottom left char (see #7 of example)
    * @param string $midLeft Mid left char (see #8 of example)
    * @param (string | null) $topLeftBottom Top left bottom char (see #8' of example), equals to $midLeft if null
    * @param (string | null) $topMidBottom Top mid bottom char (see #0' of example), equals to $cross if null
    * @param (string | null) $topRightBottom Top right bottom char (see #4' of example), equals to $midRight if null
    *
    * @return $this
    */
    public function setCrossingChars(string $cross, string $topLeft, string $topMid, string $topRight, string $midRight, string $bottomRight, string $bottomMid, string $bottomLeft, string $midLeft, string $topLeftBottom = null, string $topMidBottom = null, string $topRightBottom = null) : self
    {
        $this->crossingChar = $cross;
        $this->crossingTopLeftChar = $topLeft;
        $this->crossingTopMidChar = $topMid;
        $this->crossingTopRightChar = $topRight;
        $this->crossingMidRightChar = $midRight;
        $this->crossingBottomRightChar = $bottomRight;
        $this->crossingBottomMidChar = $bottomMid;
        $this->crossingBottomLeftChar = $bottomLeft;
        $this->crossingMidLeftChar = $midLeft;
        $this->crossingTopLeftBottomChar = $topLeftBottom ?? $midLeft;
        $this->crossingTopMidBottomChar = $topMidBottom ?? $cross;
        $this->crossingTopRightBottomChar = $topRightBottom ?? $midRight;
        return $this;
    }
    /**
     * Sets default crossing character used for each cross.
     *
     * @see {@link setCrossingChars()} for setting each crossing individually.
     */
    public function setDefaultCrossingChar(string $char) : self
    {
        return $this->setCrossingChars($char, $char, $char, $char, $char, $char, $char, $char, $char);
    }
    /**
     * Gets crossing character.
     *
     * @return string
     */
    public function getCrossingChar()
    {
        return $this->crossingChar;
    }
    /**
     * Gets crossing characters.
     *
     * @internal
     */
    public function getCrossingChars() : array
    {
        return [$this->crossingChar, $this->crossingTopLeftChar, $this->crossingTopMidChar, $this->crossingTopRightChar, $this->crossingMidRightChar, $this->crossingBottomRightChar, $this->crossingBottomMidChar, $this->crossingBottomLeftChar, $this->crossingMidLeftChar, $this->crossingTopLeftBottomChar, $this->crossingTopMidBottomChar, $this->crossingTopRightBottomChar];
    }
    /**
     * Sets header cell format.
     *
     * @return $this
     */
    public function setCellHeaderFormat(string $cellHeaderFormat)
    {
        $this->cellHeaderFormat = $cellHeaderFormat;
        return $this;
    }
    /**
     * Gets header cell format.
     *
     * @return string
     */
    public function getCellHeaderFormat()
    {
        return $this->cellHeaderFormat;
    }
    /**
     * Sets row cell format.
     *
     * @return $this
     */
    public function setCellRowFormat(string $cellRowFormat)
    {
        $this->cellRowFormat = $cellRowFormat;
        return $this;
    }
    /**
     * Gets row cell format.
     *
     * @return string
     */
    public function getCellRowFormat()
    {
        return $this->cellRowFormat;
    }
    /**
     * Sets row cell content format.
     *
     * @return $this
     */
    public function setCellRowContentFormat(string $cellRowContentFormat)
    {
        $this->cellRowContentFormat = $cellRowContentFormat;
        return $this;
    }
    /**
     * Gets row cell content format.
     *
     * @return string
     */
    public function getCellRowContentFormat()
    {
        return $this->cellRowContentFormat;
    }
    /**
     * Sets table border format.
     *
     * @return $this
     */
    public function setBorderFormat(string $borderFormat)
    {
        $this->borderFormat = $borderFormat;
        return $this;
    }
    /**
     * Gets table border format.
     *
     * @return string
     */
    public function getBorderFormat()
    {
        return $this->borderFormat;
    }
    /**
     * Sets cell padding type.
     *
     * @return $this
     */
    public function setPadType(int $padType)
    {
        if (!\in_array($padType, [\STR_PAD_LEFT, \STR_PAD_RIGHT, \STR_PAD_BOTH], \true)) {
            throw new InvalidArgumentException('Invalid padding type. Expected one of (STR_PAD_LEFT, STR_PAD_RIGHT, STR_PAD_BOTH).');
        }
        $this->padType = $padType;
        return $this;
    }
    /**
     * Gets cell padding type.
     *
     * @return int
     */
    public function getPadType()
    {
        return $this->padType;
    }
    /**
     *
     */
    public function getHeaderTitleFormat() : string
    {
        return $this->headerTitleFormat;
    }
    /**
     * @return $this
     */
    public function setHeaderTitleFormat(string $format) : self
    {
        $this->headerTitleFormat = $format;
        return $this;
    }
    /**
     *
     */
    public function getFooterTitleFormat() : string
    {
        return $this->footerTitleFormat;
    }
    /**
     * @return $this
     */
    public function setFooterTitleFormat(string $format) : self
    {
        $this->footerTitleFormat = $format;
        return $this;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

/**
 * HelperInterface is the interface all helpers must implement.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface HelperInterface
{
    /**
     * Sets the helper set associated with this helper.
     */
    public function setHelperSet(HelperSet $helperSet = null);
    /**
     * Gets the helper set associated with this helper.
     *
     * @return (HelperSet | null)
     */
    public function getHelperSet();
    /**
     * Returns the canonical name of this helper.
     *
     * @return string
     */
    public function getName();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Input\InputAwareInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
/**
 * An implementation of InputAwareInterface for Helpers.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
abstract class InputAwareHelper extends Helper implements InputAwareInterface
{
    protected $input;
    /**
     * {@inheritdoc}
     */
    public function setInput(InputInterface $input)
    {
        $this->input = $input;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Cursor;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleSectionOutput;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Console\Terminal;
/**
 * The ProgressBar provides helpers to display progress output.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Chris Jones <leeked@gmail.com>
 */
final class ProgressBar
{
    public const FORMAT_VERBOSE = 'verbose';
    public const FORMAT_VERY_VERBOSE = 'very_verbose';
    public const FORMAT_DEBUG = 'debug';
    public const FORMAT_NORMAL = 'normal';
    private const FORMAT_VERBOSE_NOMAX = 'verbose_nomax';
    private const FORMAT_VERY_VERBOSE_NOMAX = 'very_verbose_nomax';
    private const FORMAT_DEBUG_NOMAX = 'debug_nomax';
    private const FORMAT_NORMAL_NOMAX = 'normal_nomax';
    private $barWidth = 28;
    private $barChar;
    private $emptyBarChar = '-';
    private $progressChar = '>';
    private $format;
    private $internalFormat;
    private $redrawFreq = 1;
    private $writeCount;
    private $lastWriteTime;
    private $minSecondsBetweenRedraws = 0;
    private $maxSecondsBetweenRedraws = 1;
    private $output;
    private $step = 0;
    private $max;
    private $startTime;
    private $stepWidth;
    private $percent = 0.0;
    private $formatLineCount;
    private $messages = [];
    private $overwrite = \true;
    private $terminal;
    private $previousMessage;
    private $cursor;
    private static $formatters;
    private static $formats;
    /**
     * @param int $max Maximum steps (0 if unknown)
     */
    public function __construct(OutputInterface $output, int $max = 0, float $minSecondsBetweenRedraws = 1 / 25)
    {
        if ($output instanceof ConsoleOutputInterface) {
            $output = $output->getErrorOutput();
        }
        $this->output = $output;
        $this->setMaxSteps($max);
        $this->terminal = new Terminal();
        if (0 < $minSecondsBetweenRedraws) {
            $this->redrawFreq = null;
            $this->minSecondsBetweenRedraws = $minSecondsBetweenRedraws;
        }
        if (!$this->output->isDecorated()) {
            // disable overwrite when output does not support ANSI codes.
            $this->overwrite = \false;
            // set a reasonable redraw frequency so output isn't flooded
            $this->redrawFreq = null;
        }
        $this->startTime = \time();
        $this->cursor = new Cursor($output);
    }
    /**
     * Sets a placeholder formatter for a given name.
     *
     * This method also allow you to override an existing placeholder.
     *
     * @param string $name The placeholder name (including the delimiter char like %)
     * @param callable $callable A PHP callable
     */
    public static function setPlaceholderFormatterDefinition(string $name, callable $callable) : void
    {
        if (!self::$formatters) {
            self::$formatters = self::initPlaceholderFormatters();
        }
        self::$formatters[$name] = $callable;
    }
    /**
     * Gets the placeholder formatter for a given name.
     *
     * @param string $name The placeholder name (including the delimiter char like %)
     */
    public static function getPlaceholderFormatterDefinition(string $name) : ?callable
    {
        if (!self::$formatters) {
            self::$formatters = self::initPlaceholderFormatters();
        }
        return self::$formatters[$name] ?? null;
    }
    /**
     * Sets a format for a given name.
     *
     * This method also allow you to override an existing format.
     *
     * @param string $name The format name
     * @param string $format A format string
     */
    public static function setFormatDefinition(string $name, string $format) : void
    {
        if (!self::$formats) {
            self::$formats = self::initFormats();
        }
        self::$formats[$name] = $format;
    }
    /**
     * Gets the format for a given name.
     *
     * @param string $name The format name
     */
    public static function getFormatDefinition(string $name) : ?string
    {
        if (!self::$formats) {
            self::$formats = self::initFormats();
        }
        return self::$formats[$name] ?? null;
    }
    /**
    * Associates a text with a named placeholder.
    *
    * The text is displayed when the progress bar is rendered but only
    when the corresponding placeholder is part of the custom format line
    (by wrapping the name with %).
    *
    * @param string $message The text to associate with the placeholder
    * @param string $name The name of the placeholder
    */
    public function setMessage(string $message, string $name = 'message')
    {
        $this->messages[$name] = $message;
    }
    /**
     *
     */
    public function getMessage(string $name = 'message')
    {
        return $this->messages[$name];
    }
    /**
     *
     */
    public function getStartTime() : int
    {
        return $this->startTime;
    }
    /**
     *
     */
    public function getMaxSteps() : int
    {
        return $this->max;
    }
    /**
     *
     */
    public function getProgress() : int
    {
        return $this->step;
    }
    /**
     *
     */
    private function getStepWidth() : int
    {
        return $this->stepWidth;
    }
    /**
     *
     */
    public function getProgressPercent() : float
    {
        return $this->percent;
    }
    /**
     *
     */
    public function getBarOffset() : float
    {
        return \floor($this->max ? $this->percent * $this->barWidth : (null === $this->redrawFreq ? (int) (\min(5, $this->barWidth / 15) * $this->writeCount) : $this->step) % $this->barWidth);
    }
    /**
     *
     */
    public function getEstimated() : float
    {
        if (!$this->step) {
            return 0;
        }
        return \round((\time() - $this->startTime) / $this->step * $this->max);
    }
    /**
     *
     */
    public function getRemaining() : float
    {
        if (!$this->step) {
            return 0;
        }
        return \round((\time() - $this->startTime) / $this->step * ($this->max - $this->step));
    }
    /**
     *
     */
    public function setBarWidth(int $size)
    {
        $this->barWidth = \max(1, $size);
    }
    /**
     *
     */
    public function getBarWidth() : int
    {
        return $this->barWidth;
    }
    /**
     *
     */
    public function setBarCharacter(string $char)
    {
        $this->barChar = $char;
    }
    /**
     *
     */
    public function getBarCharacter() : string
    {
        return $this->barChar ?? ($this->max ? '=' : $this->emptyBarChar);
    }
    /**
     *
     */
    public function setEmptyBarCharacter(string $char)
    {
        $this->emptyBarChar = $char;
    }
    /**
     *
     */
    public function getEmptyBarCharacter() : string
    {
        return $this->emptyBarChar;
    }
    /**
     *
     */
    public function setProgressCharacter(string $char)
    {
        $this->progressChar = $char;
    }
    /**
     *
     */
    public function getProgressCharacter() : string
    {
        return $this->progressChar;
    }
    /**
     *
     */
    public function setFormat(string $format)
    {
        $this->format = null;
        $this->internalFormat = $format;
    }
    /**
     * Sets the redraw frequency.
     *
     * @param (int | null) $freq The frequency in steps
     */
    public function setRedrawFrequency(?int $freq)
    {
        $this->redrawFreq = null !== $freq ? \max(1, $freq) : null;
    }
    /**
     *
     */
    public function minSecondsBetweenRedraws(float $seconds) : void
    {
        $this->minSecondsBetweenRedraws = $seconds;
    }
    /**
     *
     */
    public function maxSecondsBetweenRedraws(float $seconds) : void
    {
        $this->maxSecondsBetweenRedraws = $seconds;
    }
    /**
     * Returns an iterator that will automatically update the progress bar when iterated.
     *
     * @param (int | null) $max Number of steps to complete the bar (0 if indeterminate), if null it will be inferred from $iterable
     */
    public function iterate(iterable $iterable, int $max = null) : iterable
    {
        $this->start($max ?? (\is_countable($iterable) ? \count($iterable) : 0));
        foreach ($iterable as $key => $value) {
            (yield $key => $value);
            $this->advance();
        }
        $this->finish();
    }
    /**
     * Starts the progress output.
     *
     * @param (int | null) $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged
     */
    public function start(int $max = null)
    {
        $this->startTime = \time();
        $this->step = 0;
        $this->percent = 0.0;
        if (null !== $max) {
            $this->setMaxSteps($max);
        }
        $this->display();
    }
    /**
     * Advances the progress output X steps.
     *
     * @param int $step Number of steps to advance
     */
    public function advance(int $step = 1)
    {
        $this->setProgress($this->step + $step);
    }
    /**
     * Sets whether to overwrite the progressbar, false for new line.
     */
    public function setOverwrite(bool $overwrite)
    {
        $this->overwrite = $overwrite;
    }
    /**
     *
     */
    public function setProgress(int $step)
    {
        if ($this->max && $step > $this->max) {
            $this->max = $step;
        } elseif ($step < 0) {
            $step = 0;
        }
        $redrawFreq = $this->redrawFreq ?? ($this->max ?: 10) / 10;
        $prevPeriod = (int) ($this->step / $redrawFreq);
        $currPeriod = (int) ($step / $redrawFreq);
        $this->step = $step;
        $this->percent = $this->max ? (float) $this->step / $this->max : 0;
        $timeInterval = \microtime(\true) - $this->lastWriteTime;
        // Draw regardless of other limits
        if ($this->max === $step) {
            $this->display();
            return;
        }
        // Throttling
        if ($timeInterval < $this->minSecondsBetweenRedraws) {
            return;
        }
        // Draw each step period, but not too late
        if ($prevPeriod !== $currPeriod || $timeInterval >= $this->maxSecondsBetweenRedraws) {
            $this->display();
        }
    }
    /**
     *
     */
    public function setMaxSteps(int $max)
    {
        $this->format = null;
        $this->max = \max(0, $max);
        $this->stepWidth = $this->max ? Helper::width((string) $this->max) : 4;
    }
    /**
     * Finishes the progress output.
     */
    public function finish() : void
    {
        if (!$this->max) {
            $this->max = $this->step;
        }
        if ($this->step === $this->max && !$this->overwrite) {
            // prevent double 100% output
            return;
        }
        $this->setProgress($this->max);
    }
    /**
     * Outputs the current progress string.
     */
    public function display() : void
    {
        if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
            return;
        }
        if (null === $this->format) {
            $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
        }
        $this->overwrite($this->buildLine());
    }
    /**
    * Removes the progress bar from the current line.
    *
    * This is useful if you wish to write some output
    while a progress bar is running.
    Call display() to show the progress bar again.
    */
    public function clear() : void
    {
        if (!$this->overwrite) {
            return;
        }
        if (null === $this->format) {
            $this->setRealFormat($this->internalFormat ?: $this->determineBestFormat());
        }
        $this->overwrite('');
    }
    /**
     *
     */
    private function setRealFormat(string $format)
    {
        // try to use the _nomax variant if available
        if (!$this->max && null !== self::getFormatDefinition($format . '_nomax')) {
            $this->format = self::getFormatDefinition($format . '_nomax');
        } elseif (null !== self::getFormatDefinition($format)) {
            $this->format = self::getFormatDefinition($format);
        } else {
            $this->format = $format;
        }
        $this->formatLineCount = \Phabel\Target\Php80\Polyfill::substr_count($this->format, "\n");
    }
    /**
     * Overwrites a previous message to the output.
     */
    private function overwrite(string $message) : void
    {
        if ($this->previousMessage === $message) {
            return;
        }
        $originalMessage = $message;
        if ($this->overwrite) {
            if (null !== $this->previousMessage) {
                if ($this->output instanceof ConsoleSectionOutput) {
                    $messageLines = \explode("\n", $message);
                    $lineCount = \count($messageLines);
                    foreach ($messageLines as $messageLine) {
                        $messageLineLength = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $messageLine));
                        if ($messageLineLength > $this->terminal->getWidth()) {
                            $lineCount += \floor($messageLineLength / $this->terminal->getWidth());
                        }
                    }
                    $this->output->clear($lineCount);
                } else {
                    for ($i = 0; $i < $this->formatLineCount; ++$i) {
                        $this->cursor->moveToColumn(1);
                        $this->cursor->clearLine();
                        $this->cursor->moveUp();
                    }
                    $this->cursor->moveToColumn(1);
                    $this->cursor->clearLine();
                }
            }
        } elseif ($this->step > 0) {
            $message = \PHP_EOL . $message;
        }
        $this->previousMessage = $originalMessage;
        $this->lastWriteTime = \microtime(\true);
        $this->output->write($message);
        ++$this->writeCount;
    }
    /**
     *
     */
    private function determineBestFormat() : string
    {
        switch ($this->output->getVerbosity()) {
            // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
            case OutputInterface::VERBOSITY_VERBOSE:
                return $this->max ? self::FORMAT_VERBOSE : self::FORMAT_VERBOSE_NOMAX;
            case OutputInterface::VERBOSITY_VERY_VERBOSE:
                return $this->max ? self::FORMAT_VERY_VERBOSE : self::FORMAT_VERY_VERBOSE_NOMAX;
            case OutputInterface::VERBOSITY_DEBUG:
                return $this->max ? self::FORMAT_DEBUG : self::FORMAT_DEBUG_NOMAX;
            default:
                return $this->max ? self::FORMAT_NORMAL : self::FORMAT_NORMAL_NOMAX;
        }
    }
    /**
     *
     */
    private static function initPlaceholderFormatters() : array
    {
        return ['bar' => function (self $bar, OutputInterface $output) {
            $completeBars = $bar->getBarOffset();
            $display = \str_repeat($bar->getBarCharacter(), $completeBars);
            if ($completeBars < $bar->getBarWidth()) {
                $emptyBars = $bar->getBarWidth() - $completeBars - Helper::length(Helper::removeDecoration($output->getFormatter(), $bar->getProgressCharacter()));
                $display .= $bar->getProgressCharacter() . \str_repeat($bar->getEmptyBarCharacter(), $emptyBars);
            }
            return $display;
        }, 'elapsed' => function (self $bar) {
            return Helper::formatTime(\time() - $bar->getStartTime());
        }, 'remaining' => function (self $bar) {
            if (!$bar->getMaxSteps()) {
                throw new LogicException('Unable to display the remaining time if the maximum number of steps is not set.');
            }
            return Helper::formatTime($bar->getRemaining());
        }, 'estimated' => function (self $bar) {
            if (!$bar->getMaxSteps()) {
                throw new LogicException('Unable to display the estimated time if the maximum number of steps is not set.');
            }
            return Helper::formatTime($bar->getEstimated());
        }, 'memory' => function (self $bar) {
            return Helper::formatMemory(\memory_get_usage(\true));
        }, 'current' => function (self $bar) {
            return \str_pad($bar->getProgress(), $bar->getStepWidth(), ' ', \STR_PAD_LEFT);
        }, 'max' => function (self $bar) {
            return $bar->getMaxSteps();
        }, 'percent' => function (self $bar) {
            return \floor($bar->getProgressPercent() * 100);
        }];
    }
    /**
     *
     */
    private static function initFormats() : array
    {
        return [self::FORMAT_NORMAL => ' %current%/%max% [%bar%] %percent:3s%%', self::FORMAT_NORMAL_NOMAX => ' %current% [%bar%]', self::FORMAT_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%', self::FORMAT_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', self::FORMAT_VERY_VERBOSE => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s%', self::FORMAT_VERY_VERBOSE_NOMAX => ' %current% [%bar%] %elapsed:6s%', self::FORMAT_DEBUG => ' %current%/%max% [%bar%] %percent:3s%% %elapsed:6s%/%estimated:-6s% %memory:6s%', self::FORMAT_DEBUG_NOMAX => ' %current% [%bar%] %elapsed:6s% %memory:6s%'];
    }
    /**
     *
     */
    private function buildLine() : string
    {
        $regex = "{%([a-z\\-_]+)(?:\\:([^%]+))?%}i";
        $callback = function ($matches) {
            if ($formatter = $this::getPlaceholderFormatterDefinition($matches[1])) {
                $text = $formatter($this, $this->output);
            } elseif (isset($this->messages[$matches[1]])) {
                $text = $this->messages[$matches[1]];
            } else {
                return $matches[0];
            }
            if (isset($matches[2])) {
                $text = \sprintf('%' . $matches[2], $text);
            }
            return $text;
        };
        $line = \preg_replace_callback($regex, $callback, $this->format);
        // gets string length for each sub line with multiline format
        $linesLength = \array_map(function ($subLine) {
            return Helper::width(Helper::removeDecoration($this->output->getFormatter(), \rtrim($subLine, "\r")));
        }, \explode("\n", $line));
        $linesWidth = \max($linesLength);
        $terminalWidth = $this->terminal->getWidth();
        if ($linesWidth <= $terminalWidth) {
            return $line;
        }
        $this->setBarWidth($this->barWidth - $linesWidth + $terminalWidth);
        return \preg_replace_callback($regex, $callback, $this->format);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\RuntimeException;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Formatter\WrappableOutputFormatterInterface;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleSectionOutput;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Provides helpers to display a table.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 * @author Ð¡Ð°ÑˆÐ° Ð¡Ñ‚Ð°Ð¼ÐµÐ½ÐºÐ¾Ð²Ð¸Ñ› <umpirsky@gmail.com>
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 * @author Max Grigorian <maxakawizard@gmail.com>
 * @author Dany Maillard <danymaillard93b@gmail.com>
 */
class Table
{
    private const SEPARATOR_TOP = 0;
    private const SEPARATOR_TOP_BOTTOM = 1;
    private const SEPARATOR_MID = 2;
    private const SEPARATOR_BOTTOM = 3;
    private const BORDER_OUTSIDE = 0;
    private const BORDER_INSIDE = 1;
    private $headerTitle;
    private $footerTitle;
    /**
     * Table headers.
     */
    private $headers = [];
    /**
     * Table rows.
     */
    private $rows = [];
    private $horizontal = \false;
    /**
     * Column widths cache.
     */
    private $effectiveColumnWidths = [];
    /**
     * Number of columns cache.
     *
     * @var int
     */
    private $numberOfColumns;
    /**
     * @var OutputInterface
     */
    private $output;
    /**
     * @var TableStyle
     */
    private $style;
    /**
     * @var array
     */
    private $columnStyles = [];
    /**
     * User set column widths.
     *
     * @var array
     */
    private $columnWidths = [];
    private $columnMaxWidths = [];
    /**
     * @var array<string, TableStyle>|null
     */
    private static $styles;
    private $rendered = \false;
    /**
     *
     */
    public function __construct(OutputInterface $output)
    {
        $this->output = $output;
        if (!self::$styles) {
            self::$styles = self::initStyles();
        }
        $this->setStyle('default');
    }
    /**
     * Sets a style definition.
     */
    public static function setStyleDefinition(string $name, TableStyle $style)
    {
        if (!self::$styles) {
            self::$styles = self::initStyles();
        }
        self::$styles[$name] = $style;
    }
    /**
     * Gets a style definition by name.
     *
     * @return TableStyle
     */
    public static function getStyleDefinition(string $name)
    {
        if (!self::$styles) {
            self::$styles = self::initStyles();
        }
        if (isset(self::$styles[$name])) {
            return self::$styles[$name];
        }
        throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name));
    }
    /**
     * Sets table style.
     *
     * @param (TableStyle | string) $name The style name or a TableStyle instance
     *
     * @return $this
     */
    public function setStyle($name)
    {
        $this->style = $this->resolveStyle($name);
        return $this;
    }
    /**
     * Gets the current table style.
     *
     * @return TableStyle
     */
    public function getStyle()
    {
        return $this->style;
    }
    /**
     * Sets table column style.
     *
     * @param (TableStyle | string) $name The style name or a TableStyle instance
     *
     * @return $this
     */
    public function setColumnStyle(int $columnIndex, $name)
    {
        $this->columnStyles[$columnIndex] = $this->resolveStyle($name);
        return $this;
    }
    /**
     * Gets the current style for a column.
     *
     * If style was not set, it returns the global table style.
     *
     * @return TableStyle
     */
    public function getColumnStyle(int $columnIndex)
    {
        return $this->columnStyles[$columnIndex] ?? $this->getStyle();
    }
    /**
     * Sets the minimum width of a column.
     *
     * @return $this
     */
    public function setColumnWidth(int $columnIndex, int $width)
    {
        $this->columnWidths[$columnIndex] = $width;
        return $this;
    }
    /**
     * Sets the minimum width of all columns.
     *
     * @return $this
     */
    public function setColumnWidths(array $widths)
    {
        $this->columnWidths = [];
        foreach ($widths as $index => $width) {
            $this->setColumnWidth($index, $width);
        }
        return $this;
    }
    /**
    * Sets the maximum width of a column.
    *
    * Any cell within this column which contents exceeds the specified width will be wrapped into multiple lines, while
    formatted strings are preserved.
    *
    * @return $this
    */
    public function setColumnMaxWidth(int $columnIndex, int $width) : self
    {
        if (!$this->output->getFormatter() instanceof WrappableOutputFormatterInterface) {
            throw new \LogicException(\sprintf('Setting a maximum column width is only supported when using a "%s" formatter, got "%s".', WrappableOutputFormatterInterface::class, \get_debug_type($this->output->getFormatter())));
        }
        $this->columnMaxWidths[$columnIndex] = $width;
        return $this;
    }
    /**
     * @return $this
     */
    public function setHeaders(array $headers)
    {
        $headers = \array_values($headers);
        if (!empty($headers) && !\is_array($headers[0])) {
            $headers = [$headers];
        }
        $this->headers = $headers;
        return $this;
    }
    /**
     *
     */
    public function setRows(array $rows)
    {
        $this->rows = [];
        return $this->addRows($rows);
    }
    /**
     * @return $this
     */
    public function addRows(array $rows)
    {
        foreach ($rows as $row) {
            $this->addRow($row);
        }
        return $this;
    }
    /**
     * @return $this
     */
    public function addRow($row)
    {
        if ($row instanceof TableSeparator) {
            $this->rows[] = $row;
            return $this;
        }
        if (!\is_array($row)) {
            throw new InvalidArgumentException('A row must be an array or a TableSeparator instance.');
        }
        $this->rows[] = \array_values($row);
        return $this;
    }
    /**
     * Adds a row to the table, and re-renders the table.
     *
     * @return $this
     */
    public function appendRow($row) : self
    {
        if (!$this->output instanceof ConsoleSectionOutput) {
            throw new RuntimeException(\sprintf('Output should be an instance of "%s" when calling "%s".', ConsoleSectionOutput::class, __METHOD__));
        }
        if ($this->rendered) {
            $this->output->clear($this->calculateRowCount());
        }
        $this->addRow($row);
        $this->render();
        return $this;
    }
    /**
     * @return $this
     */
    public function setRow($column, array $row)
    {
        $this->rows[$column] = $row;
        return $this;
    }
    /**
     * @return $this
     */
    public function setHeaderTitle(?string $title) : self
    {
        $this->headerTitle = $title;
        return $this;
    }
    /**
     * @return $this
     */
    public function setFooterTitle(?string $title) : self
    {
        $this->footerTitle = $title;
        return $this;
    }
    /**
     * @return $this
     */
    public function setHorizontal(bool $horizontal = \true) : self
    {
        $this->horizontal = $horizontal;
        return $this;
    }
    /**
    * Renders table to output.
    *
    * Example:
    *
    * +---------------+-----------------------+------------------+
    | ISBN          | Title                 | Author           |
    +---------------+-----------------------+------------------+
    | 99921-58-10-7 | Divine Comedy         | Dante Alighieri  |
    | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
    | 960-425-059-0 | The Lord of the Rings | J. R. R. Tolkien |
    +---------------+-----------------------+------------------+
    */
    public function render()
    {
        $divider = new TableSeparator();
        if ($this->horizontal) {
            $rows = [];
            foreach ($this->headers[0] ?? [] as $i => $header) {
                $rows[$i] = [$header];
                foreach ($this->rows as $row) {
                    if ($row instanceof TableSeparator) {
                        continue;
                    }
                    if (isset($row[$i])) {
                        $rows[$i][] = $row[$i];
                    } elseif ($rows[$i][0] instanceof TableCell && $rows[$i][0]->getColspan() >= 2) {
                        // Noop, there is a "title"
                    } else {
                        $rows[$i][] = null;
                    }
                }
            }
        } else {
            $rows = \array_merge($this->headers, [$divider], $this->rows);
        }
        $this->calculateNumberOfColumns($rows);
        $rows = $this->buildTableRows($rows);
        $this->calculateColumnsWidth($rows);
        $isHeader = !$this->horizontal;
        $isFirstRow = $this->horizontal;
        $hasTitle = (bool) $this->headerTitle;
        foreach ($rows as $row) {
            if ($divider === $row) {
                $isHeader = \false;
                $isFirstRow = \true;
                continue;
            }
            if ($row instanceof TableSeparator) {
                $this->renderRowSeparator();
                continue;
            }
            if (!$row) {
                continue;
            }
            if ($isHeader || $isFirstRow) {
                $this->renderRowSeparator($isHeader ? self::SEPARATOR_TOP : self::SEPARATOR_TOP_BOTTOM, $hasTitle ? $this->headerTitle : null, $hasTitle ? $this->style->getHeaderTitleFormat() : null);
                $isFirstRow = \false;
                $hasTitle = \false;
            }
            if ($this->horizontal) {
                $this->renderRow($row, $this->style->getCellRowFormat(), $this->style->getCellHeaderFormat());
            } else {
                $this->renderRow($row, $isHeader ? $this->style->getCellHeaderFormat() : $this->style->getCellRowFormat());
            }
        }
        $this->renderRowSeparator(self::SEPARATOR_BOTTOM, $this->footerTitle, $this->style->getFooterTitleFormat());
        $this->cleanup();
        $this->rendered = \true;
    }
    /**
     * Renders horizontal header separator.
     *
     * Example:
     *
     * +-----+-----------+-------+
     */
    private function renderRowSeparator(int $type = self::SEPARATOR_MID, string $title = null, string $titleFormat = null)
    {
        if (0 === ($count = $this->numberOfColumns)) {
            return;
        }
        $borders = $this->style->getBorderChars();
        if (!$borders[0] && !$borders[2] && !$this->style->getCrossingChar()) {
            return;
        }
        $crossings = $this->style->getCrossingChars();
        if (self::SEPARATOR_MID === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[2], $crossings[8], $crossings[0], $crossings[4]];
        } elseif (self::SEPARATOR_TOP === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[1], $crossings[2], $crossings[3]];
        } elseif (self::SEPARATOR_TOP_BOTTOM === $type) {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[9], $crossings[10], $crossings[11]];
        } else {
            [$horizontal, $leftChar, $midChar, $rightChar] = [$borders[0], $crossings[7], $crossings[6], $crossings[5]];
        }
        $markup = $leftChar;
        for ($column = 0; $column < $count; ++$column) {
            $markup .= \str_repeat($horizontal, $this->effectiveColumnWidths[$column]);
            $markup .= $column === $count - 1 ? $rightChar : $midChar;
        }
        if (null !== $title) {
            $titleLength = Helper::width(Helper::removeDecoration($formatter = $this->output->getFormatter(), $formattedTitle = \sprintf($titleFormat, $title)));
            $markupLength = Helper::width($markup);
            if ($titleLength > ($limit = $markupLength - 4)) {
                $titleLength = $limit;
                $formatLength = Helper::width(Helper::removeDecoration($formatter, \sprintf($titleFormat, '')));
                $formattedTitle = \sprintf($titleFormat, Helper::substr($title, 0, $limit - $formatLength - 3) . '...');
            }
            $titleStart = \intdiv($markupLength - $titleLength, 2);
            if (\false === \mb_detect_encoding($markup, null, \true)) {
                $markup = \Phabel\Target\Php80\Polyfill::substr_replace($markup, $formattedTitle, $titleStart, $titleLength);
            } else {
                $markup = \mb_substr($markup, 0, $titleStart) . $formattedTitle . \mb_substr($markup, $titleStart + $titleLength);
            }
        }
        $this->output->writeln(\sprintf($this->style->getBorderFormat(), $markup));
    }
    /**
     * Renders vertical column separator.
     */
    private function renderColumnSeparator(int $type = self::BORDER_OUTSIDE) : string
    {
        $borders = $this->style->getBorderChars();
        return \sprintf($this->style->getBorderFormat(), self::BORDER_OUTSIDE === $type ? $borders[1] : $borders[3]);
    }
    /**
     * Renders table row.
     *
     * Example:
     *
     * | 9971-5-0210-0 | A Tale of Two Cities  | Charles Dickens  |
     */
    private function renderRow(array $row, string $cellFormat, string $firstCellFormat = null)
    {
        $rowContent = $this->renderColumnSeparator(self::BORDER_OUTSIDE);
        $columns = $this->getRowColumns($row);
        $last = \count($columns) - 1;
        foreach ($columns as $i => $column) {
            if ($firstCellFormat && 0 === $i) {
                $rowContent .= $this->renderCell($row, $column, $firstCellFormat);
            } else {
                $rowContent .= $this->renderCell($row, $column, $cellFormat);
            }
            $rowContent .= $this->renderColumnSeparator($last === $i ? self::BORDER_OUTSIDE : self::BORDER_INSIDE);
        }
        $this->output->writeln($rowContent);
    }
    /**
     * Renders table cell with padding.
     */
    private function renderCell(array $row, int $column, string $cellFormat) : string
    {
        $cell = $row[$column] ?? '';
        $width = $this->effectiveColumnWidths[$column];
        if ($cell instanceof TableCell && $cell->getColspan() > 1) {
            // add the width of the following columns(numbers of colspan).
            foreach (\range($column + 1, $column + $cell->getColspan() - 1) as $nextColumn) {
                $width += $this->getColumnSeparatorWidth() + $this->effectiveColumnWidths[$nextColumn];
            }
        }
        // str_pad won't work properly with multi-byte strings, we need to fix the padding
        if (\false !== ($encoding = \mb_detect_encoding($cell, null, \true))) {
            $width += \strlen($cell) - \mb_strwidth($cell, $encoding);
        }
        $style = $this->getColumnStyle($column);
        if ($cell instanceof TableSeparator) {
            return \sprintf($style->getBorderFormat(), \str_repeat($style->getBorderChars()[2], $width));
        }
        $width += Helper::length($cell) - Helper::length(Helper::removeDecoration($this->output->getFormatter(), $cell));
        $content = \sprintf($style->getCellRowContentFormat(), $cell);
        $padType = $style->getPadType();
        if ($cell instanceof TableCell && $cell->getStyle() instanceof TableCellStyle) {
            $isNotStyledByTag = !\preg_match('/^<(\\w+|(\\w+=[\\w,]+;?)*)>.+<\\/(\\w+|(\\w+=\\w+;?)*)?>$/', $cell);
            if ($isNotStyledByTag) {
                $cellFormat = $cell->getStyle()->getCellFormat();
                if (!\is_string($cellFormat)) {
                    $tag = \http_build_query($cell->getStyle()->getTagOptions(), '', ';');
                    $cellFormat = '<' . $tag . '>%s</>';
                }
                if (\strstr($content, '</>')) {
                    $content = \str_replace('</>', '', $content);
                    $width -= 3;
                }
                if (\strstr($content, '<fg=default;bg=default>')) {
                    $content = \str_replace('<fg=default;bg=default>', '', $content);
                    $width -= \strlen('<fg=default;bg=default>');
                }
            }
            $padType = $cell->getStyle()->getPadByAlign();
        }
        return \sprintf($cellFormat, \str_pad($content, $width, $style->getPaddingChar(), $padType));
    }
    /**
     * Calculate number of columns for this table.
     */
    private function calculateNumberOfColumns(array $rows)
    {
        $columns = [0];
        foreach ($rows as $row) {
            if ($row instanceof TableSeparator) {
                continue;
            }
            $columns[] = $this->getNumberOfColumns($row);
        }
        $this->numberOfColumns = \max($columns);
    }
    /**
     *
     */
    private function buildTableRows(array $rows) : TableRows
    {
        /** @var WrappableOutputFormatterInterface $formatter */
        $formatter = $this->output->getFormatter();
        $unmergedRows = [];
        for ($rowKey = 0; $rowKey < \count($rows); ++$rowKey) {
            $rows = $this->fillNextRows($rows, $rowKey);
            // Remove any new line breaks and replace it with a new line
            foreach ($rows[$rowKey] as $column => $cell) {
                $colspan = $cell instanceof TableCell ? $cell->getColspan() : 1;
                if (isset($this->columnMaxWidths[$column]) && Helper::width(Helper::removeDecoration($formatter, $cell)) > $this->columnMaxWidths[$column]) {
                    $cell = $formatter->formatAndWrap($cell, $this->columnMaxWidths[$column] * $colspan);
                }
                if (!\strstr($cell ?? '', "\n")) {
                    continue;
                }
                $escaped = \implode("\n", \array_map([OutputFormatter::class, 'escapeTrailingBackslash'], \explode("\n", $cell)));
                $cell = $cell instanceof TableCell ? new TableCell($escaped, ['colspan' => $cell->getColspan()]) : $escaped;
                $lines = \explode("\n", \str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
                foreach ($lines as $lineKey => $line) {
                    if ($colspan > 1) {
                        $line = new TableCell($line, ['colspan' => $colspan]);
                    }
                    if (0 === $lineKey) {
                        $rows[$rowKey][$column] = $line;
                    } else {
                        if (!\array_key_exists($rowKey, $unmergedRows) || !\array_key_exists($lineKey, $unmergedRows[$rowKey])) {
                            $unmergedRows[$rowKey][$lineKey] = $this->copyRow($rows, $rowKey);
                        }
                        $unmergedRows[$rowKey][$lineKey][$column] = $line;
                    }
                }
            }
        }
        return new TableRows(function () use($rows, $unmergedRows) : \Traversable {
            foreach ($rows as $rowKey => $row) {
                (yield $row instanceof TableSeparator ? $row : $this->fillCells($row));
                if (isset($unmergedRows[$rowKey])) {
                    foreach ($unmergedRows[$rowKey] as $row) {
                        (yield $row instanceof TableSeparator ? $row : $this->fillCells($row));
                    }
                }
            }
        });
    }
    /**
     *
     */
    private function calculateRowCount() : int
    {
        $numberOfRows = \count(\iterator_to_array($this->buildTableRows(\array_merge($this->headers, [new TableSeparator()], $this->rows))));
        if ($this->headers) {
            ++$numberOfRows;
            // Add row for header separator
        }
        if (\count($this->rows) > 0) {
            ++$numberOfRows;
            // Add row for footer separator
        }
        return $numberOfRows;
    }
    /**
     * fill rows that contains rowspan > 1.
     *
     * @throws InvalidArgumentException
     */
    private function fillNextRows(array $rows, int $line) : array
    {
        $unmergedRows = [];
        foreach ($rows[$line] as $column => $cell) {
            if (null !== $cell && !$cell instanceof TableCell && !\is_scalar($cell) && !(\is_object($cell) && \method_exists($cell, '__toString'))) {
                throw new InvalidArgumentException(\sprintf('A cell must be a TableCell, a scalar or an object implementing "__toString()", "%s" given.', \get_debug_type($cell)));
            }
            if ($cell instanceof TableCell && $cell->getRowspan() > 1) {
                $nbLines = $cell->getRowspan() - 1;
                $lines = [$cell];
                if (\strstr($cell, "\n")) {
                    $lines = \explode("\n", \str_replace("\n", "<fg=default;bg=default>\n</>", $cell));
                    $nbLines = \count($lines) > $nbLines ? \Phabel\Target\Php80\Polyfill::substr_count($cell, "\n") : $nbLines;
                    $rows[$line][$column] = new TableCell($lines[0], ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
                    unset($lines[0]);
                }
                // create a two dimensional array (rowspan x colspan)
                $unmergedRows = \array_replace_recursive(\array_fill($line + 1, $nbLines, []), $unmergedRows);
                foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
                    $value = $lines[$unmergedRowKey - $line] ?? '';
                    $unmergedRows[$unmergedRowKey][$column] = new TableCell($value, ['colspan' => $cell->getColspan(), 'style' => $cell->getStyle()]);
                    if ($nbLines === $unmergedRowKey - $line) {
                        break;
                    }
                }
            }
        }
        foreach ($unmergedRows as $unmergedRowKey => $unmergedRow) {
            // we need to know if $unmergedRow will be merged or inserted into $rows
            if (isset($rows[$unmergedRowKey]) && \is_array($rows[$unmergedRowKey]) && $this->getNumberOfColumns($rows[$unmergedRowKey]) + $this->getNumberOfColumns($unmergedRows[$unmergedRowKey]) <= $this->numberOfColumns) {
                foreach ($unmergedRow as $cellKey => $cell) {
                    // insert cell into row at cellKey position
                    \array_splice($rows[$unmergedRowKey], $cellKey, 0, [$cell]);
                }
            } else {
                $row = $this->copyRow($rows, $unmergedRowKey - 1);
                foreach ($unmergedRow as $column => $cell) {
                    if (!empty($cell)) {
                        $row[$column] = $unmergedRow[$column];
                    }
                }
                \array_splice($rows, $unmergedRowKey, 0, [$row]);
            }
        }
        return $rows;
    }
    /**
     * fill cells for a row that contains colspan > 1.
     */
    private function fillCells(iterable $row)
    {
        $newRow = [];
        foreach ($row as $column => $cell) {
            $newRow[] = $cell;
            if ($cell instanceof TableCell && $cell->getColspan() > 1) {
                foreach (\range($column + 1, $column + $cell->getColspan() - 1) as $position) {
                    // insert empty value at column position
                    $newRow[] = '';
                }
            }
        }
        return $newRow ?: $row;
    }
    /**
     *
     */
    private function copyRow(array $rows, int $line) : array
    {
        $row = $rows[$line];
        foreach ($row as $cellKey => $cellValue) {
            $row[$cellKey] = '';
            if ($cellValue instanceof TableCell) {
                $row[$cellKey] = new TableCell('', ['colspan' => $cellValue->getColspan()]);
            }
        }
        return $row;
    }
    /**
     * Gets number of columns by row.
     */
    private function getNumberOfColumns(array $row) : int
    {
        $columns = \count($row);
        foreach ($row as $column) {
            $columns += $column instanceof TableCell ? $column->getColspan() - 1 : 0;
        }
        return $columns;
    }
    /**
     * Gets list of columns for the given row.
     */
    private function getRowColumns(array $row) : array
    {
        $columns = \range(0, $this->numberOfColumns - 1);
        foreach ($row as $cellKey => $cell) {
            if ($cell instanceof TableCell && $cell->getColspan() > 1) {
                // exclude grouped columns.
                $columns = \array_diff($columns, \range($cellKey + 1, $cellKey + $cell->getColspan() - 1));
            }
        }
        return $columns;
    }
    /**
     * Calculates columns widths.
     */
    private function calculateColumnsWidth(iterable $rows)
    {
        for ($column = 0; $column < $this->numberOfColumns; ++$column) {
            $lengths = [];
            foreach ($rows as $row) {
                if ($row instanceof TableSeparator) {
                    continue;
                }
                foreach ($row as $i => $cell) {
                    if ($cell instanceof TableCell) {
                        $textContent = Helper::removeDecoration($this->output->getFormatter(), $cell);
                        $textLength = Helper::width($textContent);
                        if ($textLength > 0) {
                            $contentColumns = \str_split($textContent, \ceil($textLength / $cell->getColspan()));
                            foreach ($contentColumns as $position => $content) {
                                $row[$i + $position] = $content;
                            }
                        }
                    }
                }
                $lengths[] = $this->getCellWidth($row, $column);
            }
            $this->effectiveColumnWidths[$column] = \max($lengths) + Helper::width($this->style->getCellRowContentFormat()) - 2;
        }
    }
    /**
     *
     */
    private function getColumnSeparatorWidth() : int
    {
        return Helper::width(\sprintf($this->style->getBorderFormat(), $this->style->getBorderChars()[3]));
    }
    /**
     *
     */
    private function getCellWidth(array $row, int $column) : int
    {
        $cellWidth = 0;
        if (isset($row[$column])) {
            $cell = $row[$column];
            $cellWidth = Helper::width(Helper::removeDecoration($this->output->getFormatter(), $cell));
        }
        $columnWidth = $this->columnWidths[$column] ?? 0;
        $cellWidth = \max($cellWidth, $columnWidth);
        return isset($this->columnMaxWidths[$column]) ? \min($this->columnMaxWidths[$column], $cellWidth) : $cellWidth;
    }
    /**
     * Called after rendering to cleanup cache data.
     */
    private function cleanup()
    {
        $this->effectiveColumnWidths = [];
        $this->numberOfColumns = null;
    }
    /**
     * @return array<string, TableStyle>
     */
    private static function initStyles() : array
    {
        $borderless = new TableStyle();
        $borderless->setHorizontalBorderChars('=')->setVerticalBorderChars(' ')->setDefaultCrossingChar(' ');
        $compact = new TableStyle();
        $compact->setHorizontalBorderChars('')->setVerticalBorderChars(' ')->setDefaultCrossingChar('')->setCellRowContentFormat('%s');
        $styleGuide = new TableStyle();
        $styleGuide->setHorizontalBorderChars('-')->setVerticalBorderChars(' ')->setDefaultCrossingChar(' ')->setCellHeaderFormat('%s');
        $box = (new TableStyle())->setHorizontalBorderChars('â”€')->setVerticalBorderChars('â”‚')->setCrossingChars('â”¼', 'â”Œ', 'â”¬', 'â”�', 'â”¤', 'â”˜', 'â”´', 'â””', 'â”œ');
        $boxDouble = (new TableStyle())->setHorizontalBorderChars('â•�', 'â”€')->setVerticalBorderChars('â•‘', 'â”‚')->setCrossingChars('â”¼', 'â•”', 'â•¤', 'â•—', 'â•¢', 'â•�', 'â•§', 'â•š', 'â•Ÿ', 'â• ', 'â•ª', 'â•£');
        return ['default' => new TableStyle(), 'borderless' => $borderless, 'compact' => $compact, 'symfony-style-guide' => $styleGuide, 'box' => $box, 'box-double' => $boxDouble];
    }
    /**
     *
     */
    private function resolveStyle($name) : TableStyle
    {
        if ($name instanceof TableStyle) {
            return $name;
        }
        if (isset(self::$styles[$name])) {
            return self::$styles[$name];
        }
        throw new InvalidArgumentException(\sprintf('Style "%s" is not defined.', $name));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * @author Yewhen Khoptynskyi <khoptynskyi@gmail.com>
 */
class TableCellStyle
{
    public const DEFAULT_ALIGN = 'left';
    private const TAG_OPTIONS = ['fg', 'bg', 'options'];
    private const ALIGN_MAP = ['left' => \STR_PAD_RIGHT, 'center' => \STR_PAD_BOTH, 'right' => \STR_PAD_LEFT];
    private $options = ['fg' => 'default', 'bg' => 'default', 'options' => null, 'align' => self::DEFAULT_ALIGN, 'cellFormat' => null];
    /**
     *
     */
    public function __construct(array $options = [])
    {
        if ($diff = \array_diff(\array_keys($options), \array_keys($this->options))) {
            throw new InvalidArgumentException(\sprintf('The TableCellStyle does not support the following options: \'%s\'.', \implode('\', \'', $diff)));
        }
        if (isset($options['align']) && !\array_key_exists($options['align'], self::ALIGN_MAP)) {
            throw new InvalidArgumentException(\sprintf('Wrong align value. Value must be following: \'%s\'.', \implode('\', \'', \array_keys(self::ALIGN_MAP))));
        }
        $this->options = \array_merge($this->options, $options);
    }
    /**
     *
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * Gets options we need for tag for example fg, bg.
     *
     * @return string[]
     */
    public function getTagOptions()
    {
        return \array_filter($this->getOptions(), function ($key) {
            return \in_array($key, self::TAG_OPTIONS) && isset($this->options[$key]);
        }, \ARRAY_FILTER_USE_KEY);
    }
    /**
     * @return int
     */
    public function getPadByAlign()
    {
        return self::ALIGN_MAP[$this->getOptions()['align']];
    }
    /**
     *
     */
    public function getCellFormat() : ?string
    {
        return $this->getOptions()['cellFormat'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Kevin Bond <kevinbond@gmail.com>
 */
class ProgressIndicator
{
    private const FORMATS = ['normal' => ' %indicator% %message%', 'normal_no_ansi' => ' %message%', 'verbose' => ' %indicator% %message% (%elapsed:6s%)', 'verbose_no_ansi' => ' %message% (%elapsed:6s%)', 'very_verbose' => ' %indicator% %message% (%elapsed:6s%, %memory:6s%)', 'very_verbose_no_ansi' => ' %message% (%elapsed:6s%, %memory:6s%)'];
    private $output;
    private $startTime;
    private $format;
    private $message;
    private $indicatorValues;
    private $indicatorCurrent;
    private $indicatorChangeInterval;
    private $indicatorUpdateTime;
    private $started = \false;
    /**
     * @var array<string, callable>
     */
    private static $formatters;
    /**
     * @param int $indicatorChangeInterval Change interval in milliseconds
     * @param (array | null) $indicatorValues Animated indicator characters
     */
    public function __construct(OutputInterface $output, string $format = null, int $indicatorChangeInterval = 100, array $indicatorValues = null)
    {
        $this->output = $output;
        if (null === $format) {
            $format = $this->determineBestFormat();
        }
        if (null === $indicatorValues) {
            $indicatorValues = ['-', '\\', '|', '/'];
        }
        $indicatorValues = \array_values($indicatorValues);
        if (2 > \count($indicatorValues)) {
            throw new InvalidArgumentException('Must have at least 2 indicator value characters.');
        }
        $this->format = self::getFormatDefinition($format);
        $this->indicatorChangeInterval = $indicatorChangeInterval;
        $this->indicatorValues = $indicatorValues;
        $this->startTime = \time();
    }
    /**
     * Sets the current indicator message.
     */
    public function setMessage(?string $message)
    {
        $this->message = $message;
        $this->display();
    }
    /**
     * Starts the indicator output.
     */
    public function start(string $message)
    {
        if ($this->started) {
            throw new LogicException('Progress indicator already started.');
        }
        $this->message = $message;
        $this->started = \true;
        $this->startTime = \time();
        $this->indicatorUpdateTime = $this->getCurrentTimeInMilliseconds() + $this->indicatorChangeInterval;
        $this->indicatorCurrent = 0;
        $this->display();
    }
    /**
     * Advances the indicator.
     */
    public function advance()
    {
        if (!$this->started) {
            throw new LogicException('Progress indicator has not yet been started.');
        }
        if (!$this->output->isDecorated()) {
            return;
        }
        $currentTime = $this->getCurrentTimeInMilliseconds();
        if ($currentTime < $this->indicatorUpdateTime) {
            return;
        }
        $this->indicatorUpdateTime = $currentTime + $this->indicatorChangeInterval;
        ++$this->indicatorCurrent;
        $this->display();
    }
    /**
     * Finish the indicator with message.
     *
     * @param $message
     */
    public function finish(string $message)
    {
        if (!$this->started) {
            throw new LogicException('Progress indicator has not yet been started.');
        }
        $this->message = $message;
        $this->display();
        $this->output->writeln('');
        $this->started = \false;
    }
    /**
     * Gets the format for a given name.
     *
     * @return (string | null)
     */
    public static function getFormatDefinition(string $name)
    {
        return self::FORMATS[$name] ?? null;
    }
    /**
     * Sets a placeholder formatter for a given name.
     *
     * This method also allow you to override an existing placeholder.
     */
    public static function setPlaceholderFormatterDefinition(string $name, callable $callable)
    {
        if (!self::$formatters) {
            self::$formatters = self::initPlaceholderFormatters();
        }
        self::$formatters[$name] = $callable;
    }
    /**
     * Gets the placeholder formatter for a given name (including the delimiter char like %).
     *
     * @return (callable | null)
     */
    public static function getPlaceholderFormatterDefinition(string $name)
    {
        if (!self::$formatters) {
            self::$formatters = self::initPlaceholderFormatters();
        }
        return self::$formatters[$name] ?? null;
    }
    /**
     *
     */
    private function display()
    {
        if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) {
            return;
        }
        $this->overwrite(\preg_replace_callback("{%([a-z\\-_]+)(?:\\:([^%]+))?%}i", function ($matches) {
            if ($formatter = self::getPlaceholderFormatterDefinition($matches[1])) {
                return $formatter($this);
            }
            return $matches[0];
        }, $this->format ?? ''));
    }
    /**
     *
     */
    private function determineBestFormat() : string
    {
        switch ($this->output->getVerbosity()) {
            // OutputInterface::VERBOSITY_QUIET: display is disabled anyway
            case OutputInterface::VERBOSITY_VERBOSE:
                return $this->output->isDecorated() ? 'verbose' : 'verbose_no_ansi';
            case OutputInterface::VERBOSITY_VERY_VERBOSE:
            case OutputInterface::VERBOSITY_DEBUG:
                return $this->output->isDecorated() ? 'very_verbose' : 'very_verbose_no_ansi';
            default:
                return $this->output->isDecorated() ? 'normal' : 'normal_no_ansi';
        }
    }
    /**
     * Overwrites a previous message to the output.
     */
    private function overwrite(string $message)
    {
        if ($this->output->isDecorated()) {
            $this->output->write("\r\x1b[2K");
            $this->output->write($message);
        } else {
            $this->output->writeln($message);
        }
    }
    /**
     *
     */
    private function getCurrentTimeInMilliseconds() : float
    {
        return \round(\microtime(\true) * 1000);
    }
    /**
     *
     */
    private static function initPlaceholderFormatters() : array
    {
        return ['indicator' => function (self $indicator) {
            return $indicator->indicatorValues[$indicator->indicatorCurrent % \count($indicator->indicatorValues)];
        }, 'message' => function (self $indicator) {
            return $indicator->message;
        }, 'elapsed' => function (self $indicator) {
            return Helper::formatTime(\time() - $indicator->startTime);
        }, 'memory' => function () {
            return Helper::formatMemory(\memory_get_usage(\true));
        }];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

/**
 * @internal
 */
class TableRows implements \IteratorAggregate
{
    private $generator;
    /**
     *
     */
    public function __construct(\Closure $generator)
    {
        $this->generator = $generator;
    }
    /**
     *
     */
    public function getIterator() : \Traversable
    {
        return ($this->generator)();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
/**
 * The Formatter class provides helpers to format messages.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class FormatterHelper extends Helper
{
    /**
     * Formats a message within a section.
     *
     * @return string
     */
    public function formatSection(string $section, string $message, string $style = 'info')
    {
        return \sprintf('<%s>[%s]</%s> %s', $style, $section, $style, $message);
    }
    /**
     * Formats a message as a block of text.
     *
     * @param (string | array) $messages The message to write in the block
     *
     * @return string
     */
    public function formatBlock($messages, string $style, bool $large = \false)
    {
        if (!\is_array($messages)) {
            $messages = [$messages];
        }
        $len = 0;
        $lines = [];
        foreach ($messages as $message) {
            $message = OutputFormatter::escape($message);
            $lines[] = \sprintf($large ? '  %s  ' : ' %s ', $message);
            $len = \max(self::width($message) + ($large ? 4 : 2), $len);
        }
        $messages = $large ? [\str_repeat(' ', $len)] : [];
        for ($i = 0; isset($lines[$i]); ++$i) {
            $messages[] = $lines[$i] . \str_repeat(' ', $len - self::width($lines[$i]));
        }
        if ($large) {
            $messages[] = \str_repeat(' ', $len);
        }
        for ($i = 0; isset($messages[$i]); ++$i) {
            $messages[$i] = \sprintf('<%s>%s</%s>', $style, $messages[$i], $style);
        }
        return \implode("\n", $messages);
    }
    /**
     * Truncates a message to the given length.
     *
     * @return string
     */
    public function truncate(string $message, int $length, string $suffix = '...')
    {
        $computedLength = $length - self::width($suffix);
        if ($computedLength > self::width($message)) {
            return $message;
        }
        return self::substr($message, 0, $length) . $suffix;
    }
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'formatter';
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * HelperSet represents a set of helpers to be used with a command.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @implements \IteratorAggregate<string, Helper>
 */
class HelperSet implements \IteratorAggregate
{
    /** @var array<string, Helper> */
    private $helpers = [];
    private $command;
    /**
     * @param Helper[] $helpers An array of helper
     */
    public function __construct(array $helpers = [])
    {
        foreach ($helpers as $alias => $helper) {
            $this->set($helper, \is_int($alias) ? null : $alias);
        }
    }
    /**
     *
     */
    public function set(HelperInterface $helper, string $alias = null)
    {
        $this->helpers[$helper->getName()] = $helper;
        if (null !== $alias) {
            $this->helpers[$alias] = $helper;
        }
        $helper->setHelperSet($this);
    }
    /**
     * Returns true if the helper if defined.
     *
     * @return bool
     */
    public function has(string $name)
    {
        return isset($this->helpers[$name]);
    }
    /**
     * Gets a helper value.
     *
     * @return HelperInterface
     *
     * @throws InvalidArgumentException if the helper is not defined
     */
    public function get(string $name)
    {
        if (!$this->has($name)) {
            throw new InvalidArgumentException(\sprintf('The helper "%s" is not defined.', $name));
        }
        return $this->helpers[$name];
    }
    /**
     * @deprecated since Symfony 5.4
     */
    public function setCommand(Command $command = null)
    {
        trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__);
        $this->command = $command;
    }
    /**
     * Gets the command associated with this helper set.
     *
     * @return Command
     *
     * @deprecated since Symfony 5.4
     */
    public function getCommand()
    {
        trigger_deprecation('symfony/console', '5.4', 'Method "%s()" is deprecated.', __METHOD__);
        return $this->command;
    }
    /**
     * @return \Traversable<string, Helper>
     */
    #[\ReturnTypeWillChange]
    public function getIterator()
    {
        return new \ArrayIterator($this->helpers);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Descriptor\DescriptorInterface;
use PhabelVendor\Symfony\Component\Console\Descriptor\JsonDescriptor;
use PhabelVendor\Symfony\Component\Console\Descriptor\MarkdownDescriptor;
use PhabelVendor\Symfony\Component\Console\Descriptor\TextDescriptor;
use PhabelVendor\Symfony\Component\Console\Descriptor\XmlDescriptor;
use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * This class adds helper method to describe objects in various formats.
 *
 * @author Jean-FranÃ§ois Simon <contact@jfsimon.fr>
 */
class DescriptorHelper extends Helper
{
    /**
     * @var DescriptorInterface[]
     */
    private $descriptors = [];
    /**
     *
     */
    public function __construct()
    {
        $this->register('txt', new TextDescriptor())->register('xml', new XmlDescriptor())->register('json', new JsonDescriptor())->register('md', new MarkdownDescriptor());
    }
    /**
    * Describes an object if supported.
    *
    * Available options are:
    format: string, the output format name
    raw_text: boolean, sets output type as raw
    *
    * @throws InvalidArgumentException when the given format is not supported
    */
    public function describe(OutputInterface $output, ?object $object, array $options = [])
    {
        $options = \array_merge(['raw_text' => \false, 'format' => 'txt'], $options);
        if (!isset($this->descriptors[$options['format']])) {
            throw new InvalidArgumentException(\sprintf('Unsupported format "%s".', $options['format']));
        }
        $descriptor = $this->descriptors[$options['format']];
        $descriptor->describe($output, $object, $options);
    }
    /**
     * Registers a descriptor.
     *
     * @return $this
     */
    public function register(string $format, DescriptorInterface $descriptor)
    {
        $this->descriptors[$format] = $descriptor;
        return $this;
    }
    /**
     * {@inheritdoc}
     */
    public function getName()
    {
        return 'descriptor';
    }
    /**
     *
     */
    public function getFormats() : array
    {
        return \array_keys($this->descriptors);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * @author Abdellatif Ait boudad <a.aitboudad@gmail.com>
 */
class TableCell
{
    private $value;
    private $options = ['rowspan' => 1, 'colspan' => 1, 'style' => null];
    /**
     *
     */
    public function __construct(string $value = '', array $options = [])
    {
        $this->value = $value;
        // check option names
        if ($diff = \array_diff(\array_keys($options), \array_keys($this->options))) {
            throw new InvalidArgumentException(\sprintf('The TableCell does not support the following options: \'%s\'.', \implode('\', \'', $diff)));
        }
        if (isset($options['style']) && !$options['style'] instanceof TableCellStyle) {
            throw new InvalidArgumentException('The style option must be an instance of "TableCellStyle".');
        }
        $this->options = \array_merge($this->options, $options);
    }
    /**
     * Returns the cell value.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->value;
    }
    /**
     * Gets number of colspan.
     *
     * @return int
     */
    public function getColspan()
    {
        return (int) $this->options['colspan'];
    }
    /**
     * Gets number of rowspan.
     *
     * @return int
     */
    public function getRowspan()
    {
        return (int) $this->options['rowspan'];
    }
    /**
     *
     */
    public function getStyle() : ?TableCellStyle
    {
        return $this->options['style'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Helper;

use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\VarDumper\Cloner\ClonerInterface;
use PhabelVendor\Symfony\Component\VarDumper\Cloner\VarCloner;
use PhabelVendor\Symfony\Component\VarDumper\Dumper\CliDumper;
/**
 * @author Roland Franssen <franssen.roland@gmail.com>
 */
final class Dumper
{
    private $output;
    private $dumper;
    private $cloner;
    private $handler;
    /**
     *
     */
    public function __construct(OutputInterface $output, CliDumper $dumper = null, ClonerInterface $cloner = null)
    {
        $this->output = $output;
        $this->dumper = $dumper;
        $this->cloner = $cloner;
        if (\class_exists(CliDumper::class)) {
            $this->handler = function ($var) : string {
                $dumper = $this->dumper ?? ($this->dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR));
                $dumper->setColors($this->output->isDecorated());
                return \rtrim($dumper->dump(($this->cloner ?? ($this->cloner = new VarCloner()))->cloneVar($var)->withRefHandles(\false), \true));
            };
        } else {
            $this->handler = function ($var) : string {
                switch (\true) {
                    case null === $var:
                        return 'null';
                    case \true === $var:
                        return 'true';
                    case \false === $var:
                        return 'false';
                    case \is_string($var):
                        return '"' . $var . '"';
                    default:
                        return \rtrim(\print_r($var, \true));
                }
            };
        }
    }
    /**
     *
     */
    public function __invoke($var) : string
    {
        return ($this->handler)($var);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Completion\Output;

use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class BashCompletionOutput implements CompletionOutputInterface
{
    /**
     *
     */
    public function write(CompletionSuggestions $suggestions, OutputInterface $output) : void
    {
        $values = $suggestions->getValueSuggestions();
        foreach ($suggestions->getOptionSuggestions() as $option) {
            $values[] = '--' . $option->getName();
        }
        $output->writeln(\implode("\n", $values));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Completion\Output;

use PhabelVendor\Symfony\Component\Console\Completion\CompletionSuggestions;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * Transforms the {@see CompletionSuggestions} object into output readable by the shell completion.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
interface CompletionOutputInterface
{
    /**
     *
     */
    public function write(CompletionSuggestions $suggestions, OutputInterface $output) : void;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Completion;

use PhabelVendor\Symfony\Component\Console\Exception\RuntimeException;
use PhabelVendor\Symfony\Component\Console\Input\ArgvInput;
use PhabelVendor\Symfony\Component\Console\Input\InputDefinition;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
/**
 * An input specialized for shell completion.
 *
 * This input allows unfinished option names or values and exposes what kind of
 * completion is expected.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class CompletionInput extends ArgvInput
{
    public const TYPE_ARGUMENT_VALUE = 'argument_value';
    public const TYPE_OPTION_VALUE = 'option_value';
    public const TYPE_OPTION_NAME = 'option_name';
    public const TYPE_NONE = 'none';
    private $tokens;
    private $currentIndex;
    private $completionType;
    private $completionName = null;
    private $completionValue = '';
    /**
     * Converts a terminal string into tokens.
     *
     * This is required for shell completions without COMP_WORDS support.
     */
    public static function fromString(string $inputStr, int $currentIndex) : self
    {
        \preg_match_all('/(?<=^|\\s)([\'"]?)(.+?)(?<!\\\\)\\1(?=$|\\s)/', $inputStr, $tokens);
        return self::fromTokens($tokens[0], $currentIndex);
    }
    /**
     * Create an input based on an COMP_WORDS token list.
     *
     * @param string[] $tokens the set of split tokens (e.g. COMP_WORDS or argv)
     * @param $currentIndex the index of the cursor (e.g. COMP_CWORD)
     */
    public static function fromTokens(array $tokens, int $currentIndex) : self
    {
        $input = new self($tokens);
        $input->tokens = $tokens;
        $input->currentIndex = $currentIndex;
        return $input;
    }
    /**
     * {@inheritdoc}
     */
    public function bind(InputDefinition $definition) : void
    {
        parent::bind($definition);
        $relevantToken = $this->getRelevantToken();
        if ('-' === $relevantToken[0]) {
            // the current token is an input option: complete either option name or option value
            [$optionToken, $optionValue] = \explode('=', $relevantToken, 2) + ['', ''];
            $option = $this->getOptionFromToken($optionToken);
            if (null === $option && !$this->isCursorFree()) {
                $this->completionType = self::TYPE_OPTION_NAME;
                $this->completionValue = $relevantToken;
                return;
            }
            if (null !== $option && $option->acceptValue()) {
                $this->completionType = self::TYPE_OPTION_VALUE;
                $this->completionName = $option->getName();
                $this->completionValue = $optionValue ?: (!\str_starts_with($optionToken, '--') ? \Phabel\Target\Php80\Polyfill::substr($optionToken, 2) : '');
                return;
            }
        }
        $previousToken = $this->tokens[$this->currentIndex - 1];
        if ('-' === $previousToken[0] && '' !== \trim($previousToken, '-')) {
            // check if previous option accepted a value
            $previousOption = $this->getOptionFromToken($previousToken);
            if (null !== $previousOption && $previousOption->acceptValue()) {
                $this->completionType = self::TYPE_OPTION_VALUE;
                $this->completionName = $previousOption->getName();
                $this->completionValue = $relevantToken;
                return;
            }
        }
        // complete argument value
        $this->completionType = self::TYPE_ARGUMENT_VALUE;
        $arguments = $this->getArguments();
        foreach ($arguments as $argumentName => $argumentValue) {
            if (null === $argumentValue) {
                break;
            }
            $this->completionName = $argumentName;
            if (\is_array($argumentValue)) {
                $this->completionValue = $argumentValue ? $argumentValue[\array_key_last($argumentValue)] : null;
            } else {
                $this->completionValue = $argumentValue;
            }
        }
        if ($this->currentIndex >= \count($this->tokens)) {
            if (null === $arguments[$argumentName] || $this->definition->getArgument($argumentName)->isArray()) {
                $this->completionName = $argumentName;
                $this->completionValue = '';
            } else {
                // we've reached the end
                $this->completionType = self::TYPE_NONE;
                $this->completionName = null;
                $this->completionValue = '';
            }
        }
    }
    /**
    * Returns the type of completion required.
    *
    * TYPE_ARGUMENT_VALUE when completing the value of an input argument
    TYPE_OPTION_VALUE   when completing the value of an input option
    TYPE_OPTION_NAME    when completing the name of an input option
    TYPE_NONE           when nothing should be completed
    *
    * @return string One of self::TYPE_* constants. TYPE_OPTION_NAME and TYPE_NONE are already implemented by the Console component
    */
    public function getCompletionType() : string
    {
        return $this->completionType;
    }
    /**
     * The name of the input option or argument when completing a value.
     *
     * @return (string | null) returns null when completing an option name
     */
    public function getCompletionName() : ?string
    {
        return $this->completionName;
    }
    /**
     * The value already typed by the user (or empty string).
     */
    public function getCompletionValue() : string
    {
        return $this->completionValue;
    }
    /**
     *
     */
    public function mustSuggestOptionValuesFor(string $optionName) : bool
    {
        return self::TYPE_OPTION_VALUE === $this->getCompletionType() && $optionName === $this->getCompletionName();
    }
    /**
     *
     */
    public function mustSuggestArgumentValuesFor(string $argumentName) : bool
    {
        return self::TYPE_ARGUMENT_VALUE === $this->getCompletionType() && $argumentName === $this->getCompletionName();
    }
    /**
     *
     */
    protected function parseToken(string $token, bool $parseOptions) : bool
    {
        try {
            return parent::parseToken($token, $parseOptions);
        } catch (RuntimeException $e) {
            // suppress errors, completed input is almost never valid
        }
        return $parseOptions;
    }
    /**
     *
     */
    private function getOptionFromToken(string $optionToken) : ?InputOption
    {
        $optionName = \ltrim($optionToken, '-');
        if (!$optionName) {
            return null;
        }
        if ('-' === ($optionToken[1] ?? ' ')) {
            // long option name
            return $this->definition->hasOption($optionName) ? $this->definition->getOption($optionName) : null;
        }
        // short option name
        return $this->definition->hasShortcut($optionName[0]) ? $this->definition->getOptionForShortcut($optionName[0]) : null;
    }
    /**
     * The token of the cursor, or the last token if the cursor is at the end of the input.
     */
    private function getRelevantToken() : string
    {
        return $this->tokens[$this->isCursorFree() ? $this->currentIndex - 1 : $this->currentIndex];
    }
    /**
     * Whether the cursor is "free" (i.e. at the end of the input preceded by a space).
     */
    private function isCursorFree() : bool
    {
        $nrOfTokens = \count($this->tokens);
        if ($this->currentIndex > $nrOfTokens) {
            throw new \LogicException('Current index is invalid, it must be the number of input tokens or one more.');
        }
        return $this->currentIndex >= $nrOfTokens;
    }
    /**
     *
     */
    public function __toString()
    {
        $str = '';
        foreach ($this->tokens as $i => $token) {
            $str .= $token;
            if ($this->currentIndex === $i) {
                $str .= '|';
            }
            $str .= ' ';
        }
        if ($this->currentIndex > $i) {
            $str .= '|';
        }
        return \rtrim($str);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Completion;

/**
 * Represents a single suggested value.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
class Suggestion
{
    private $value;
    /**
     *
     */
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    /**
     *
     */
    public function getValue() : string
    {
        return $this->value;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->getValue();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Completion;

use PhabelVendor\Symfony\Component\Console\Input\InputOption;
/**
 * Stores all completion suggestions for the current input.
 *
 * @author Wouter de Jong <wouter@wouterj.nl>
 */
final class CompletionSuggestions
{
    private $valueSuggestions = [];
    private $optionSuggestions = [];
    /**
     * Add a suggested value for an input option or argument.
     *
     * @param (string | Suggestion) $value
     *
     * @return $this
     */
    public function suggestValue($value) : self
    {
        $this->valueSuggestions[] = !$value instanceof Suggestion ? new Suggestion($value) : $value;
        return $this;
    }
    /**
     * Add multiple suggested values at once for an input option or argument.
     *
     * @param list<(string | Suggestion)> $values
     *
     * @return $this
     */
    public function suggestValues(array $values) : self
    {
        foreach ($values as $value) {
            $this->suggestValue($value);
        }
        return $this;
    }
    /**
     * Add a suggestion for an input option name.
     *
     * @return $this
     */
    public function suggestOption(InputOption $option) : self
    {
        $this->optionSuggestions[] = $option;
        return $this;
    }
    /**
     * Add multiple suggestions for input option names at once.
     *
     * @param InputOption[] $options
     *
     * @return $this
     */
    public function suggestOptions(array $options) : self
    {
        foreach ($options as $option) {
            $this->suggestOption($option);
        }
        return $this;
    }
    /**
     * @return InputOption[]
     */
    public function getOptionSuggestions() : array
    {
        return $this->optionSuggestions;
    }
    /**
     * @return Suggestion[]
     */
    public function getValueSuggestions() : array
    {
        return $this->valueSuggestions;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
/**
 * Represents a command line argument.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputArgument
{
    public const REQUIRED = 1;
    public const OPTIONAL = 2;
    public const IS_ARRAY = 4;
    private $name;
    private $mode;
    private $default;
    private $description;
    /**
     * @param string $name The argument name
     * @param (int | null) $mode The argument mode: self::REQUIRED or self::OPTIONAL
     * @param string $description A description text
     * @param (string | bool | int | float | array | null) $default The default value (for self::OPTIONAL mode only)
     *
     * @throws InvalidArgumentException When argument mode is not valid
     */
    public function __construct(string $name, int $mode = null, string $description = '', $default = null)
    {
        if (null === $mode) {
            $mode = self::OPTIONAL;
        } elseif ($mode > 7 || $mode < 1) {
            throw new InvalidArgumentException(\sprintf('Argument mode "%s" is not valid.', $mode));
        }
        $this->name = $name;
        $this->mode = $mode;
        $this->description = $description;
        $this->setDefault($default);
    }
    /**
     * Returns the argument name.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }
    /**
     * Returns true if the argument is required.
     *
     * @return bool true if parameter mode is self::REQUIRED, false otherwise
     */
    public function isRequired()
    {
        return self::REQUIRED === (self::REQUIRED & $this->mode);
    }
    /**
     * Returns true if the argument can take multiple values.
     *
     * @return bool true if mode is self::IS_ARRAY, false otherwise
     */
    public function isArray()
    {
        return self::IS_ARRAY === (self::IS_ARRAY & $this->mode);
    }
    /**
     * Sets the default value.
     *
     * @param (string | bool | int | float | array | null) $default
     *
     * @throws LogicException When incorrect default value is given
     */
    public function setDefault($default = null)
    {
        if (self::REQUIRED === $this->mode && null !== $default) {
            throw new LogicException('Cannot set a default value except for InputArgument::OPTIONAL mode.');
        }
        if ($this->isArray()) {
            if (null === $default) {
                $default = [];
            } elseif (!\is_array($default)) {
                throw new LogicException('A default value for an array argument must be an array.');
            }
        }
        $this->default = $default;
    }
    /**
     * Returns the default value.
     *
     * @return (string | bool | int | float | array | null)
     */
    public function getDefault()
    {
        return $this->default;
    }
    /**
     * Returns the description text.
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

/**
 * InputAwareInterface should be implemented by classes that depends on the
 * Console Input.
 *
 * @author Wouter J <waldio.webdesign@gmail.com>
 */
interface InputAwareInterface
{
    /**
     * Sets the Console Input.
     */
    public function setInput(InputInterface $input);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

/**
 * StreamableInputInterface is the interface implemented by all input classes
 * that have an input stream.
 *
 * @author Robin Chalas <robin.chalas@gmail.com>
 */
interface StreamableInputInterface extends InputInterface
{
    /**
     * Sets the input stream to read from when interacting with the user.
     *
     * This is mainly useful for testing purpose.
     *
     * @param resource $stream The input stream
     */
    public function setStream($stream);
    /**
     * Returns the input stream.
     *
     * @return (resource | null)
     */
    public function getStream();
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\RuntimeException;
/**
 * Input is the base class for all concrete Input classes.
 *
 * Three concrete classes are provided by default:
 *
 *  * `ArgvInput`: The input comes from the CLI arguments (argv)
 *  * `StringInput`: The input is provided as a string
 *  * `ArrayInput`: The input is provided as an array
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
abstract class Input implements InputInterface, StreamableInputInterface
{
    protected $definition;
    protected $stream;
    protected $options = [];
    protected $arguments = [];
    protected $interactive = \true;
    /**
     *
     */
    public function __construct(InputDefinition $definition = null)
    {
        if (null === $definition) {
            $this->definition = new InputDefinition();
        } else {
            $this->bind($definition);
            $this->validate();
        }
    }
    /**
     * {@inheritdoc}
     */
    public function bind(InputDefinition $definition)
    {
        $this->arguments = [];
        $this->options = [];
        $this->definition = $definition;
        $this->parse();
    }
    /**
     * Processes command line arguments.
     */
    protected abstract function parse();
    /**
     * {@inheritdoc}
     */
    public function validate()
    {
        $definition = $this->definition;
        $givenArguments = $this->arguments;
        $missingArguments = \array_filter(\array_keys($definition->getArguments()), function ($argument) use($definition, $givenArguments) {
            return !\array_key_exists($argument, $givenArguments) && $definition->getArgument($argument)->isRequired();
        });
        if (\count($missingArguments) > 0) {
            throw new RuntimeException(\sprintf('Not enough arguments (missing: "%s").', \implode(', ', $missingArguments)));
        }
    }
    /**
     * {@inheritdoc}
     */
    public function isInteractive()
    {
        return $this->interactive;
    }
    /**
     * {@inheritdoc}
     */
    public function setInteractive(bool $interactive)
    {
        $this->interactive = $interactive;
    }
    /**
     * {@inheritdoc}
     */
    public function getArguments()
    {
        return \array_merge($this->definition->getArgumentDefaults(), $this->arguments);
    }
    /**
     * {@inheritdoc}
     */
    public function getArgument(string $name)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }
        return $this->arguments[$name] ?? $this->definition->getArgument($name)->getDefault();
    }
    /**
     * {@inheritdoc}
     */
    public function setArgument(string $name, $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }
        $this->arguments[$name] = $value;
    }
    /**
     * {@inheritdoc}
     */
    public function hasArgument(string $name)
    {
        return $this->definition->hasArgument($name);
    }
    /**
     * {@inheritdoc}
     */
    public function getOptions()
    {
        return \array_merge($this->definition->getOptionDefaults(), $this->options);
    }
    /**
     * {@inheritdoc}
     */
    public function getOption(string $name)
    {
        if ($this->definition->hasNegation($name)) {
            if (null === ($value = $this->getOption($this->definition->negationToName($name)))) {
                return $value;
            }
            return !$value;
        }
        if (!$this->definition->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name));
        }
        return \array_key_exists($name, $this->options) ? $this->options[$name] : $this->definition->getOption($name)->getDefault();
    }
    /**
     * {@inheritdoc}
     */
    public function setOption(string $name, $value)
    {
        if ($this->definition->hasNegation($name)) {
            $this->options[$this->definition->negationToName($name)] = !$value;
            return;
        } elseif (!$this->definition->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" option does not exist.', $name));
        }
        $this->options[$name] = $value;
    }
    /**
     * {@inheritdoc}
     */
    public function hasOption(string $name)
    {
        return $this->definition->hasOption($name) || $this->definition->hasNegation($name);
    }
    /**
     * Escapes a token through escapeshellarg if it contains unsafe chars.
     *
     * @return string
     */
    public function escapeToken(string $token)
    {
        return \preg_match('{^[\\w-]+$}', $token) ? $token : \escapeshellarg($token);
    }
    /**
     * {@inheritdoc}
     */
    public function setStream($stream)
    {
        $this->stream = $stream;
    }
    /**
     * {@inheritdoc}
     */
    public function getStream()
    {
        return $this->stream;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
/**
 * StringInput represents an input provided as a string.
 *
 * Usage:
 *
 *     $input = new StringInput('foo --bar="foobar"');
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class StringInput extends ArgvInput
{
    public const REGEX_STRING = '([^\\s]+?)(?:\\s|(?<!\\\\)"|(?<!\\\\)\'|$)';
    public const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')';
    /**
     * @param string $input A string representing the parameters from the CLI
     */
    public function __construct(string $input)
    {
        parent::__construct([]);
        $this->setTokens($this->tokenize($input));
    }
    /**
     * Tokenizes a string.
     *
     * @throws InvalidArgumentException When unable to parse input (should never happen)
     */
    private function tokenize(string $input) : array
    {
        $tokens = [];
        $length = \strlen($input);
        $cursor = 0;
        while ($cursor < $length) {
            if (\preg_match('/\\s+/A', $input, $match, 0, $cursor)) {
            } elseif (\preg_match('/([^="\'\\s]+?)(=?)(' . self::REGEX_QUOTED_STRING . '+)/A', $input, $match, 0, $cursor)) {
                $tokens[] = $match[1] . $match[2] . \stripcslashes(\str_replace(['"\'', '\'"', '\'\'', '""'], '', \Phabel\Target\Php80\Polyfill::substr($match[3], 1, -1)));
            } elseif (\preg_match('/' . self::REGEX_QUOTED_STRING . '/A', $input, $match, 0, $cursor)) {
                $tokens[] = \stripcslashes(\Phabel\Target\Php80\Polyfill::substr($match[0], 1, -1));
            } elseif (\preg_match('/' . self::REGEX_STRING . '/A', $input, $match, 0, $cursor)) {
                $tokens[] = \stripcslashes($match[1]);
            } else {
                // should never happen
                throw new InvalidArgumentException(\sprintf('Unable to parse input near "... %s ...".', \Phabel\Target\Php80\Polyfill::substr($input, $cursor, 10)));
            }
            $cursor += \strlen($match[0]);
        }
        return $tokens;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\RuntimeException;
/**
 * InputInterface is the interface implemented by all input classes.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
interface InputInterface
{
    /**
     * Returns the first argument from the raw parameters (not parsed).
     *
     * @return (string | null)
     */
    public function getFirstArgument();
    /**
    * Returns true if the raw parameters (not parsed) contain a value.
    *
    * This method is to be used to introspect the input parameters
    before they have been validated. It must be used carefully.
    Does not necessarily return the correct result for short options
    when multiple flags are combined in the same option.
    *
    * @param (string | array) $values The values to look for in the raw parameters (can be an array)
    * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
    *
    * @return bool
    */
    public function hasParameterOption($values, bool $onlyParams = \false);
    /**
    * Returns the value of a raw option (not parsed).
    *
    * This method is to be used to introspect the input parameters
    before they have been validated. It must be used carefully.
    Does not necessarily return the correct result for short options
    when multiple flags are combined in the same option.
    *
    * @param (string | array) $values The value(s) to look for in the raw parameters (can be an array)
    * @param (string | bool | int | float | array | null) $default The default value to return if no result is found
    * @param bool $onlyParams Only check real parameters, skip those following an end of options (--) signal
    *
    * @return mixed
    */
    public function getParameterOption($values, $default = \false, bool $onlyParams = \false);
    /**
     * Binds the current Input instance with the given arguments and options.
     *
     * @throws RuntimeException
     */
    public function bind(InputDefinition $definition);
    /**
     * Validates the input.
     *
     * @throws RuntimeException When not enough arguments are given
     */
    public function validate();
    /**
     * Returns all the given arguments merged with the default values.
     *
     * @return array<(string | bool | int | float | array | null)>
     */
    public function getArguments();
    /**
     * Returns the argument value for a given argument name.
     *
     * @return mixed
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument(string $name);
    /**
     * Sets an argument value by name.
     *
     * @param mixed $value The argument value
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function setArgument(string $name, $value);
    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @return bool
     */
    public function hasArgument(string $name);
    /**
     * Returns all the given options merged with the default values.
     *
     * @return array<(string | bool | int | float | array | null)>
     */
    public function getOptions();
    /**
     * Returns the option value for a given option name.
     *
     * @return mixed
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function getOption(string $name);
    /**
     * Sets an option value by name.
     *
     * @param mixed $value The option value
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function setOption(string $name, $value);
    /**
     * Returns true if an InputOption object exists by name.
     *
     * @return bool
     */
    public function hasOption(string $name);
    /**
     * Is this input means interactive?
     *
     * @return bool
     */
    public function isInteractive();
    /**
     * Sets the input interactivity.
     */
    public function setInteractive(bool $interactive);
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\InvalidOptionException;
/**
 * ArrayInput represents an input provided as an array.
 *
 * Usage:
 *
 *     $input = new ArrayInput(['command' => 'foo:bar', 'foo' => 'bar', '--bar' => 'foobar']);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class ArrayInput extends Input
{
    private $parameters;
    /**
     *
     */
    public function __construct(array $parameters, InputDefinition $definition = null)
    {
        $this->parameters = $parameters;
        parent::__construct($definition);
    }
    /**
     * {@inheritdoc}
     */
    public function getFirstArgument()
    {
        foreach ($this->parameters as $param => $value) {
            if ($param && \is_string($param) && '-' === $param[0]) {
                continue;
            }
            return $value;
        }
        return null;
    }
    /**
     * {@inheritdoc}
     */
    public function hasParameterOption($values, bool $onlyParams = \false)
    {
        $values = (array) $values;
        foreach ($this->parameters as $k => $v) {
            if (!\is_int($k)) {
                $v = $k;
            }
            if ($onlyParams && '--' === $v) {
                return \false;
            }
            if (\in_array($v, $values)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * {@inheritdoc}
     */
    public function getParameterOption($values, $default = \false, bool $onlyParams = \false)
    {
        $values = (array) $values;
        foreach ($this->parameters as $k => $v) {
            if ($onlyParams && ('--' === $k || \is_int($k) && '--' === $v)) {
                return $default;
            }
            if (\is_int($k)) {
                if (\in_array($v, $values)) {
                    return \true;
                }
            } elseif (\in_array($k, $values)) {
                return $v;
            }
        }
        return $default;
    }
    /**
     * Returns a stringified representation of the args passed to the command.
     *
     * @return string
     */
    public function __toString()
    {
        $params = [];
        foreach ($this->parameters as $param => $val) {
            if ($param && \is_string($param) && '-' === $param[0]) {
                $glue = '-' === $param[1] ? '=' : ' ';
                if (\is_array($val)) {
                    foreach ($val as $v) {
                        $params[] = $param . ('' != $v ? $glue . $this->escapeToken($v) : '');
                    }
                } else {
                    $params[] = $param . ('' != $val ? $glue . $this->escapeToken($val) : '');
                }
            } else {
                $params[] = \is_array($val) ? \implode(' ', \array_map([$this, 'escapeToken'], $val)) : $this->escapeToken($val);
            }
        }
        return \implode(' ', $params);
    }
    /**
     * {@inheritdoc}
     */
    protected function parse()
    {
        foreach ($this->parameters as $key => $value) {
            if ('--' === $key) {
                return;
            }
            if (\str_starts_with($key, '--')) {
                $this->addLongOption(\Phabel\Target\Php80\Polyfill::substr($key, 2), $value);
            } elseif (\str_starts_with($key, '-')) {
                $this->addShortOption(\Phabel\Target\Php80\Polyfill::substr($key, 1), $value);
            } else {
                $this->addArgument($key, $value);
            }
        }
    }
    /**
     * Adds a short option value.
     *
     * @throws InvalidOptionException When option given doesn't exist
     */
    private function addShortOption(string $shortcut, $value)
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new InvalidOptionException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }
        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }
    /**
     * Adds a long option value.
     *
     * @throws InvalidOptionException When option given doesn't exist
     * @throws InvalidOptionException When a required value is missing
     */
    private function addLongOption(string $name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            if (!$this->definition->hasNegation($name)) {
                throw new InvalidOptionException(\sprintf('The "--%s" option does not exist.', $name));
            }
            $optionName = $this->definition->negationToName($name);
            $this->options[$optionName] = \false;
            return;
        }
        $option = $this->definition->getOption($name);
        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new InvalidOptionException(\sprintf('The "--%s" option requires a value.', $name));
            }
            if (!$option->isValueOptional()) {
                $value = \true;
            }
        }
        $this->options[$name] = $value;
    }
    /**
     * Adds an argument value.
     *
     * @param (string | int) $name The argument name
     * @param mixed $value The value for the argument
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    private function addArgument($name, $value)
    {
        if (!$this->definition->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }
        $this->arguments[$name] = $value;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
/**
 * A InputDefinition represents a set of valid command line arguments and options.
 *
 * Usage:
 *
 *     $definition = new InputDefinition([
 *         new InputArgument('name', InputArgument::REQUIRED),
 *         new InputOption('foo', 'f', InputOption::VALUE_REQUIRED),
 *     ]);
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputDefinition
{
    private $arguments;
    private $requiredCount;
    private $lastArrayArgument;
    private $lastOptionalArgument;
    private $options;
    private $negations;
    private $shortcuts;
    /**
     * @param array $definition An array of InputArgument and InputOption instance
     */
    public function __construct(array $definition = [])
    {
        $this->setDefinition($definition);
    }
    /**
     * Sets the definition of the input.
     */
    public function setDefinition(array $definition)
    {
        $arguments = [];
        $options = [];
        foreach ($definition as $item) {
            if ($item instanceof InputOption) {
                $options[] = $item;
            } else {
                $arguments[] = $item;
            }
        }
        $this->setArguments($arguments);
        $this->setOptions($options);
    }
    /**
     * Sets the InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     */
    public function setArguments(array $arguments = [])
    {
        $this->arguments = [];
        $this->requiredCount = 0;
        $this->lastOptionalArgument = null;
        $this->lastArrayArgument = null;
        $this->addArguments($arguments);
    }
    /**
     * Adds an array of InputArgument objects.
     *
     * @param InputArgument[] $arguments An array of InputArgument objects
     */
    public function addArguments(?array $arguments = [])
    {
        if (null !== $arguments) {
            foreach ($arguments as $argument) {
                $this->addArgument($argument);
            }
        }
    }
    /**
     * @throws LogicException When incorrect argument is given
     */
    public function addArgument(InputArgument $argument)
    {
        if (isset($this->arguments[$argument->getName()])) {
            throw new LogicException(\sprintf('An argument with name "%s" already exists.', $argument->getName()));
        }
        if (null !== $this->lastArrayArgument) {
            throw new LogicException(\sprintf('Cannot add a required argument "%s" after an array argument "%s".', $argument->getName(), $this->lastArrayArgument->getName()));
        }
        if ($argument->isRequired() && null !== $this->lastOptionalArgument) {
            throw new LogicException(\sprintf('Cannot add a required argument "%s" after an optional one "%s".', $argument->getName(), $this->lastOptionalArgument->getName()));
        }
        if ($argument->isArray()) {
            $this->lastArrayArgument = $argument;
        }
        if ($argument->isRequired()) {
            ++$this->requiredCount;
        } else {
            $this->lastOptionalArgument = $argument;
        }
        $this->arguments[$argument->getName()] = $argument;
    }
    /**
     * Returns an InputArgument by name or by position.
     *
     * @param (string | int) $name The InputArgument name or position
     *
     * @return InputArgument
     *
     * @throws InvalidArgumentException When argument given doesn't exist
     */
    public function getArgument($name)
    {
        if (!$this->hasArgument($name)) {
            throw new InvalidArgumentException(\sprintf('The "%s" argument does not exist.', $name));
        }
        $arguments = \is_int($name) ? \array_values($this->arguments) : $this->arguments;
        return $arguments[$name];
    }
    /**
     * Returns true if an InputArgument object exists by name or position.
     *
     * @param (string | int) $name The InputArgument name or position
     *
     * @return bool
     */
    public function hasArgument($name)
    {
        $arguments = \is_int($name) ? \array_values($this->arguments) : $this->arguments;
        return isset($arguments[$name]);
    }
    /**
     * Gets the array of InputArgument objects.
     *
     * @return InputArgument[]
     */
    public function getArguments()
    {
        return $this->arguments;
    }
    /**
     * Returns the number of InputArguments.
     *
     * @return int
     */
    public function getArgumentCount()
    {
        return null !== $this->lastArrayArgument ? \PHP_INT_MAX : \count($this->arguments);
    }
    /**
     * Returns the number of required InputArguments.
     *
     * @return int
     */
    public function getArgumentRequiredCount()
    {
        return $this->requiredCount;
    }
    /**
     * @return array<(string | bool | int | float | array | null)>
     */
    public function getArgumentDefaults()
    {
        $values = [];
        foreach ($this->arguments as $argument) {
            $values[$argument->getName()] = $argument->getDefault();
        }
        return $values;
    }
    /**
     * Sets the InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     */
    public function setOptions(array $options = [])
    {
        $this->options = [];
        $this->shortcuts = [];
        $this->negations = [];
        $this->addOptions($options);
    }
    /**
     * Adds an array of InputOption objects.
     *
     * @param InputOption[] $options An array of InputOption objects
     */
    public function addOptions(array $options = [])
    {
        foreach ($options as $option) {
            $this->addOption($option);
        }
    }
    /**
     * @throws LogicException When option given already exist
     */
    public function addOption(InputOption $option)
    {
        if (isset($this->options[$option->getName()]) && !$option->equals($this->options[$option->getName()])) {
            throw new LogicException(\sprintf('An option named "%s" already exists.', $option->getName()));
        }
        if (isset($this->negations[$option->getName()])) {
            throw new LogicException(\sprintf('An option named "%s" already exists.', $option->getName()));
        }
        if ($option->getShortcut()) {
            foreach (\explode('|', $option->getShortcut()) as $shortcut) {
                if (isset($this->shortcuts[$shortcut]) && !$option->equals($this->options[$this->shortcuts[$shortcut]])) {
                    throw new LogicException(\sprintf('An option with shortcut "%s" already exists.', $shortcut));
                }
            }
        }
        $this->options[$option->getName()] = $option;
        if ($option->getShortcut()) {
            foreach (\explode('|', $option->getShortcut()) as $shortcut) {
                $this->shortcuts[$shortcut] = $option->getName();
            }
        }
        if ($option->isNegatable()) {
            $negatedName = 'no-' . $option->getName();
            if (isset($this->options[$negatedName])) {
                throw new LogicException(\sprintf('An option named "%s" already exists.', $negatedName));
            }
            $this->negations[$negatedName] = $option->getName();
        }
    }
    /**
     * Returns an InputOption by name.
     *
     * @return InputOption
     *
     * @throws InvalidArgumentException When option given doesn't exist
     */
    public function getOption(string $name)
    {
        if (!$this->hasOption($name)) {
            throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $name));
        }
        return $this->options[$name];
    }
    /**
    * Returns true if an InputOption object exists by name.
    *
    * This method can't be used to check if the user included the option when
    executing the command (use getOption() instead).
    *
    * @return bool
    */
    public function hasOption(string $name)
    {
        return isset($this->options[$name]);
    }
    /**
     * Gets the array of InputOption objects.
     *
     * @return InputOption[]
     */
    public function getOptions()
    {
        return $this->options;
    }
    /**
     * Returns true if an InputOption object exists by shortcut.
     *
     * @return bool
     */
    public function hasShortcut(string $name)
    {
        return isset($this->shortcuts[$name]);
    }
    /**
     * Returns true if an InputOption object exists by negated name.
     */
    public function hasNegation(string $name) : bool
    {
        return isset($this->negations[$name]);
    }
    /**
     * Gets an InputOption by shortcut.
     *
     * @return InputOption
     */
    public function getOptionForShortcut(string $shortcut)
    {
        return $this->getOption($this->shortcutToName($shortcut));
    }
    /**
     * @return array<(string | bool | int | float | array | null)>
     */
    public function getOptionDefaults()
    {
        $values = [];
        foreach ($this->options as $option) {
            $values[$option->getName()] = $option->getDefault();
        }
        return $values;
    }
    /**
     * Returns the InputOption name given a shortcut.
     *
     * @throws InvalidArgumentException When option given does not exist
     *
     * @internal
     */
    public function shortcutToName(string $shortcut) : string
    {
        if (!isset($this->shortcuts[$shortcut])) {
            throw new InvalidArgumentException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }
        return $this->shortcuts[$shortcut];
    }
    /**
     * Returns the InputOption name given a negation.
     *
     * @throws InvalidArgumentException When option given does not exist
     *
     * @internal
     */
    public function negationToName(string $negation) : string
    {
        if (!isset($this->negations[$negation])) {
            throw new InvalidArgumentException(\sprintf('The "--%s" option does not exist.', $negation));
        }
        return $this->negations[$negation];
    }
    /**
     * Gets the synopsis.
     *
     * @return string
     */
    public function getSynopsis(bool $short = \false)
    {
        $elements = [];
        if ($short && $this->getOptions()) {
            $elements[] = '[options]';
        } elseif (!$short) {
            foreach ($this->getOptions() as $option) {
                $value = '';
                if ($option->acceptValue()) {
                    $value = \sprintf(' %s%s%s', $option->isValueOptional() ? '[' : '', \strtoupper($option->getName()), $option->isValueOptional() ? ']' : '');
                }
                $shortcut = $option->getShortcut() ? \sprintf('-%s|', $option->getShortcut()) : '';
                $negation = $option->isNegatable() ? \sprintf('|--no-%s', $option->getName()) : '';
                $elements[] = \sprintf('[%s--%s%s%s]', $shortcut, $option->getName(), $value, $negation);
            }
        }
        if (\count($elements) && $this->getArguments()) {
            $elements[] = '[--]';
        }
        $tail = '';
        foreach ($this->getArguments() as $argument) {
            $element = '<' . $argument->getName() . '>';
            if ($argument->isArray()) {
                $element .= '...';
            }
            if (!$argument->isRequired()) {
                $element = '[' . $element;
                $tail .= ']';
            }
            $elements[] = $element;
        }
        return \implode(' ', $elements) . $tail;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

use PhabelVendor\Symfony\Component\Console\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\Console\Exception\LogicException;
/**
 * Represents a command line option.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 */
class InputOption
{
    /**
     * Do not accept input for the option (e.g. --yell). This is the default behavior of options.
     */
    public const VALUE_NONE = 1;
    /**
     * A value must be passed when the option is used (e.g. --iterations=5 or -i5).
     */
    public const VALUE_REQUIRED = 2;
    /**
     * The option may or may not have a value (e.g. --yell or --yell=loud).
     */
    public const VALUE_OPTIONAL = 4;
    /**
     * The option accepts multiple values (e.g. --dir=/foo --dir=/bar).
     */
    public const VALUE_IS_ARRAY = 8;
    /**
     * The option may have either positive or negative value (e.g. --ansi or --no-ansi).
     */
    public const VALUE_NEGATABLE = 16;
    private $name;
    private $shortcut;
    private $mode;
    private $default;
    private $description;
    /**
     * @param (string | array | null) $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts
     * @param (int | null) $mode The option mode: One of the VALUE_* constants
     * @param (string | bool | int | float | array | null) $default The default value (must be null for self::VALUE_NONE)
     *
     * @throws InvalidArgumentException If option mode is invalid or incompatible
     */
    public function __construct(string $name, $shortcut = null, int $mode = null, string $description = '', $default = null)
    {
        if (\str_starts_with($name, '--')) {
            $name = \Phabel\Target\Php80\Polyfill::substr($name, 2);
        }
        if (empty($name)) {
            throw new InvalidArgumentException('An option name cannot be empty.');
        }
        if (empty($shortcut)) {
            $shortcut = null;
        }
        if (null !== $shortcut) {
            if (\is_array($shortcut)) {
                $shortcut = \implode('|', $shortcut);
            }
            $shortcuts = \preg_split('{(\\|)-?}', \ltrim($shortcut, '-'));
            $shortcuts = \array_filter($shortcuts);
            $shortcut = \implode('|', $shortcuts);
            if (empty($shortcut)) {
                throw new InvalidArgumentException('An option shortcut cannot be empty.');
            }
        }
        if (null === $mode) {
            $mode = self::VALUE_NONE;
        } elseif ($mode >= self::VALUE_NEGATABLE << 1 || $mode < 1) {
            throw new InvalidArgumentException(\sprintf('Option mode "%s" is not valid.', $mode));
        }
        $this->name = $name;
        $this->shortcut = $shortcut;
        $this->mode = $mode;
        $this->description = $description;
        if ($this->isArray() && !$this->acceptValue()) {
            throw new InvalidArgumentException('Impossible to have an option mode VALUE_IS_ARRAY if the option does not accept a value.');
        }
        if ($this->isNegatable() && $this->acceptValue()) {
            throw new InvalidArgumentException('Impossible to have an option mode VALUE_NEGATABLE if the option also accepts a value.');
        }
        $this->setDefault($default);
    }
    /**
     * Returns the option shortcut.
     *
     * @return (string | null)
     */
    public function getShortcut()
    {
        return $this->shortcut;
    }
    /**
     * Returns the option name.
     *
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }
    /**
     * Returns true if the option accepts a value.
     *
     * @return bool true if value mode is not self::VALUE_NONE, false otherwise
     */
    public function acceptValue()
    {
        return $this->isValueRequired() || $this->isValueOptional();
    }
    /**
     * Returns true if the option requires a value.
     *
     * @return bool true if value mode is self::VALUE_REQUIRED, false otherwise
     */
    public function isValueRequired()
    {
        return self::VALUE_REQUIRED === (self::VALUE_REQUIRED & $this->mode);
    }
    /**
     * Returns true if the option takes an optional value.
     *
     * @return bool true if value mode is self::VALUE_OPTIONAL, false otherwise
     */
    public function isValueOptional()
    {
        return self::VALUE_OPTIONAL === (self::VALUE_OPTIONAL & $this->mode);
    }
    /**
     * Returns true if the option can take multiple values.
     *
     * @return bool true if mode is self::VALUE_IS_ARRAY, false otherwise
     */
    public function isArray()
    {
        return self::VALUE_IS_ARRAY === (self::VALUE_IS_ARRAY & $this->mode);
    }
    /**
     *
     */
    public function isNegatable() : bool
    {
        return self::VALUE_NEGATABLE === (self::VALUE_NEGATABLE & $this->mode);
    }
    /**
     * @param (string | bool | int | float | array | null) $default
     */
    public function setDefault($default = null)
    {
        if (self::VALUE_NONE === (self::VALUE_NONE & $this->mode) && null !== $default) {
            throw new LogicException('Cannot set a default value when using InputOption::VALUE_NONE mode.');
        }
        if ($this->isArray()) {
            if (null === $default) {
                $default = [];
            } elseif (!\is_array($default)) {
                throw new LogicException('A default value for an array option must be an array.');
            }
        }
        $this->default = $this->acceptValue() || $this->isNegatable() ? $default : \false;
    }
    /**
     * Returns the default value.
     *
     * @return (string | bool | int | float | array | null)
     */
    public function getDefault()
    {
        return $this->default;
    }
    /**
     * Returns the description text.
     *
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }
    /**
     * Checks whether the given option equals this one.
     *
     * @return bool
     */
    public function equals(self $option)
    {
        return $option->getName() === $this->getName() && $option->getShortcut() === $this->getShortcut() && $option->getDefault() === $this->getDefault() && $option->isNegatable() === $this->isNegatable() && $option->isArray() === $this->isArray() && $option->isValueRequired() === $this->isValueRequired() && $option->isValueOptional() === $this->isValueOptional();
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\Console\Input;

use PhabelVendor\Symfony\Component\Console\Exception\RuntimeException;
/**
 * ArgvInput represents an input coming from the CLI arguments.
 *
 * Usage:
 *
 *     $input = new ArgvInput();
 *
 * By default, the `$_SERVER['argv']` array is used for the input values.
 *
 * This can be overridden by explicitly passing the input values in the constructor:
 *
 *     $input = new ArgvInput($_SERVER['argv']);
 *
 * If you pass it yourself, don't forget that the first element of the array
 * is the name of the running application.
 *
 * When passing an argument to the constructor, be sure that it respects
 * the same rules as the argv one. It's almost always better to use the
 * `StringInput` when you want to provide your own input.
 *
 * @author Fabien Potencier <fabien@symfony.com>
 *
 * @see http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
 * @see http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
 */
class ArgvInput extends Input
{
    private $tokens;
    private $parsed;
    /**
     *
     */
    public function __construct(array $argv = null, InputDefinition $definition = null)
    {
        $argv = $argv ?? $_SERVER['argv'] ?? [];
        // strip the application name
        \array_shift($argv);
        $this->tokens = $argv;
        parent::__construct($definition);
    }
    /**
     *
     */
    protected function setTokens(array $tokens)
    {
        $this->tokens = $tokens;
    }
    /**
     * {@inheritdoc}
     */
    protected function parse()
    {
        $parseOptions = \true;
        $this->parsed = $this->tokens;
        while (null !== ($token = \array_shift($this->parsed))) {
            $parseOptions = $this->parseToken($token, $parseOptions);
        }
    }
    /**
     *
     */
    protected function parseToken(string $token, bool $parseOptions) : bool
    {
        if ($parseOptions && '' == $token) {
            $this->parseArgument($token);
        } elseif ($parseOptions && '--' == $token) {
            return \false;
        } elseif ($parseOptions && \str_starts_with($token, '--')) {
            $this->parseLongOption($token);
        } elseif ($parseOptions && '-' === $token[0] && '-' !== $token) {
            $this->parseShortOption($token);
        } else {
            $this->parseArgument($token);
        }
        return $parseOptions;
    }
    /**
     * Parses a short option.
     */
    private function parseShortOption(string $token)
    {
        $name = \Phabel\Target\Php80\Polyfill::substr($token, 1);
        if (\strlen($name) > 1) {
            if ($this->definition->hasShortcut($name[0]) && $this->definition->getOptionForShortcut($name[0])->acceptValue()) {
                // an option with a value (with no space)
                $this->addShortOption($name[0], \Phabel\Target\Php80\Polyfill::substr($name, 1));
            } else {
                $this->parseShortOptionSet($name);
            }
        } else {
            $this->addShortOption($name, null);
        }
    }
    /**
     * Parses a short option set.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function parseShortOptionSet(string $name)
    {
        $len = \strlen($name);
        for ($i = 0; $i < $len; ++$i) {
            if (!$this->definition->hasShortcut($name[$i])) {
                $encoding = \mb_detect_encoding($name, null, \true);
                throw new RuntimeException(\sprintf('The "-%s" option does not exist.', \false === $encoding ? $name[$i] : \mb_substr($name, $i, 1, $encoding)));
            }
            $option = $this->definition->getOptionForShortcut($name[$i]);
            if ($option->acceptValue()) {
                $this->addLongOption($option->getName(), $i === $len - 1 ? null : \Phabel\Target\Php80\Polyfill::substr($name, $i + 1));
                break;
            } else {
                $this->addLongOption($option->getName(), null);
            }
        }
    }
    /**
     * Parses a long option.
     */
    private function parseLongOption(string $token)
    {
        $name = \Phabel\Target\Php80\Polyfill::substr($token, 2);
        if (\false !== ($pos = \strpos($name, '='))) {
            if ('' === ($value = \Phabel\Target\Php80\Polyfill::substr($name, $pos + 1))) {
                \array_unshift($this->parsed, $value);
            }
            $this->addLongOption(\Phabel\Target\Php80\Polyfill::substr($name, 0, $pos), $value);
        } else {
            $this->addLongOption($name, null);
        }
    }
    /**
     * Parses an argument.
     *
     * @throws RuntimeException When too many arguments are given
     */
    private function parseArgument(string $token)
    {
        $c = \count($this->arguments);
        // if input is expecting another argument, add it
        if ($this->definition->hasArgument($c)) {
            $arg = $this->definition->getArgument($c);
            $this->arguments[$arg->getName()] = $arg->isArray() ? [$token] : $token;
            // if last argument isArray(), append token to last argument
        } elseif ($this->definition->hasArgument($c - 1) && $this->definition->getArgument($c - 1)->isArray()) {
            $arg = $this->definition->getArgument($c - 1);
            $this->arguments[$arg->getName()][] = $token;
            // unexpected argument
        } else {
            $all = $this->definition->getArguments();
            $symfonyCommandName = null;
            if (($inputArgument = $all[$key = \array_key_first($all)] ?? null) && 'command' === $inputArgument->getName()) {
                $symfonyCommandName = $this->arguments['command'] ?? null;
                unset($all[$key]);
            }
            if (\count($all)) {
                if ($symfonyCommandName) {
                    $message = \sprintf('Too many arguments to "%s" command, expected arguments "%s".', $symfonyCommandName, \implode('" "', \array_keys($all)));
                } else {
                    $message = \sprintf('Too many arguments, expected arguments "%s".', \implode('" "', \array_keys($all)));
                }
            } elseif ($symfonyCommandName) {
                $message = \sprintf('No arguments expected for "%s" command, got "%s".', $symfonyCommandName, $token);
            } else {
                $message = \sprintf('No arguments expected, got "%s".', $token);
            }
            throw new RuntimeException($message);
        }
    }
    /**
     * Adds a short option value.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function addShortOption(string $shortcut, $value)
    {
        if (!$this->definition->hasShortcut($shortcut)) {
            throw new RuntimeException(\sprintf('The "-%s" option does not exist.', $shortcut));
        }
        $this->addLongOption($this->definition->getOptionForShortcut($shortcut)->getName(), $value);
    }
    /**
     * Adds a long option value.
     *
     * @throws RuntimeException When option given doesn't exist
     */
    private function addLongOption(string $name, $value)
    {
        if (!$this->definition->hasOption($name)) {
            if (!$this->definition->hasNegation($name)) {
                throw new RuntimeException(\sprintf('The "--%s" option does not exist.', $name));
            }
            $optionName = $this->definition->negationToName($name);
            if (null !== $value) {
                throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name));
            }
            $this->options[$optionName] = \false;
            return;
        }
        $option = $this->definition->getOption($name);
        if (null !== $value && !$option->acceptValue()) {
            throw new RuntimeException(\sprintf('The "--%s" option does not accept a value.', $name));
        }
        if (\in_array($value, ['', null], \true) && $option->acceptValue() && \count($this->parsed)) {
            // if option accepts an optional or mandatory argument
            // let's see if there is one provided
            $next = \array_shift($this->parsed);
            if (isset($next[0]) && '-' !== $next[0] || \in_array($next, ['', null], \true)) {
                $value = $next;
            } else {
                \array_unshift($this->parsed, $next);
            }
        }
        if (null === $value) {
            if ($option->isValueRequired()) {
                throw new RuntimeException(\sprintf('The "--%s" option requires a value.', $name));
            }
            if (!$option->isArray() && !$option->isValueOptional()) {
                $value = \true;
            }
        }
        if ($option->isArray()) {
            $this->options[$name][] = $value;
        } else {
            $this->options[$name] = $value;
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getFirstArgument()
    {
        $isOption = \false;
        foreach ($this->tokens as $i => $token) {
            if ($token && '-' === $token[0]) {
                if (\str_contains($token, '=') || !isset($this->tokens[$i + 1])) {
                    continue;
                }
                // If it's a long option, consider that everything after "--" is the option name.
                // Otherwise, use the last char (if it's a short option set, only the last one can take a value with space separator)
                $name = '-' === $token[1] ? \Phabel\Target\Php80\Polyfill::substr($token, 2) : \Phabel\Target\Php80\Polyfill::substr($token, -1);
                if (!isset($this->options[$name]) && !$this->definition->hasShortcut($name)) {
                    // noop
                } elseif ((isset($this->options[$name]) || isset($this->options[$name = $this->definition->shortcutToName($name)])) && $this->tokens[$i + 1] === $this->options[$name]) {
                    $isOption = \true;
                }
                continue;
            }
            if ($isOption) {
                $isOption = \false;
                continue;
            }
            return $token;
        }
        return null;
    }
    /**
     * {@inheritdoc}
     */
    public function hasParameterOption($values, bool $onlyParams = \false)
    {
        $values = (array) $values;
        foreach ($this->tokens as $token) {
            if ($onlyParams && '--' === $token) {
                return \false;
            }
            foreach ($values as $value) {
                // Options with values:
                //   For long options, test for '--option=' at beginning
                //   For short options, test for '-o' at beginning
                $leading = \str_starts_with($value, '--') ? $value . '=' : $value;
                if ($token === $value || '' !== $leading && \str_starts_with($token, $leading)) {
                    return \true;
                }
            }
        }
        return \false;
    }
    /**
     * {@inheritdoc}
     */
    public function getParameterOption($values, $default = \false, bool $onlyParams = \false)
    {
        $values = (array) $values;
        $tokens = $this->tokens;
        while (0 < \count($tokens)) {
            $token = \array_shift($tokens);
            if ($onlyParams && '--' === $token) {
                return $default;
            }
            foreach ($values as $value) {
                if ($token === $value) {
                    return \array_shift($tokens);
                }
                // Options with values:
                //   For long options, test for '--option=' at beginning
                //   For short options, test for '-o' at beginning
                $leading = \str_starts_with($value, '--') ? $value . '=' : $value;
                if ('' !== $leading && \str_starts_with($token, $leading)) {
                    return \Phabel\Target\Php80\Polyfill::substr($token, \strlen($leading));
                }
            }
        }
        return $default;
    }
    /**
     * Returns a stringified representation of the args passed to the command.
     *
     * @return string
     */
    public function __toString()
    {
        $tokens = \array_map(function ($token) {
            if (\preg_match('{^(-[^=]+=)(.+)}', $token, $match)) {
                return $match[1] . $this->escapeToken($match[2]);
            }
            if ($token && '-' !== $token[0]) {
                return $this->escapeToken($token);
            }
            return $token;
        }, $this->tokens);
        return \implode(' ', $tokens);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String\Slugger;

use PhabelVendor\Symfony\Component\String\AbstractUnicodeString;
use PhabelVendor\Symfony\Component\String\UnicodeString;
use PhabelVendor\Symfony\Contracts\Translation\LocaleAwareInterface;
if (!\interface_exists(LocaleAwareInterface::class)) {
    throw new \LogicException('You cannot use the "Symfony\\Component\\String\\Slugger\\AsciiSlugger" as the "symfony/translation-contracts" package is not installed. Try running "composer require symfony/translation-contracts".');
}
/**
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
class AsciiSlugger implements SluggerInterface, LocaleAwareInterface
{
    private const LOCALE_TO_TRANSLITERATOR_ID = ['am' => 'Amharic-Latin', 'ar' => 'Arabic-Latin', 'az' => 'Azerbaijani-Latin', 'be' => 'Belarusian-Latin', 'bg' => 'Bulgarian-Latin', 'bn' => 'Bengali-Latin', 'de' => 'de-ASCII', 'el' => 'Greek-Latin', 'fa' => 'Persian-Latin', 'he' => 'Hebrew-Latin', 'hy' => 'Armenian-Latin', 'ka' => 'Georgian-Latin', 'kk' => 'Kazakh-Latin', 'ky' => 'Kirghiz-Latin', 'ko' => 'Korean-Latin', 'mk' => 'Macedonian-Latin', 'mn' => 'Mongolian-Latin', 'or' => 'Oriya-Latin', 'ps' => 'Pashto-Latin', 'ru' => 'Russian-Latin', 'sr' => 'Serbian-Latin', 'sr_Cyrl' => 'Serbian-Latin', 'th' => 'Thai-Latin', 'tk' => 'Turkmen-Latin', 'uk' => 'Ukrainian-Latin', 'uz' => 'Uzbek-Latin', 'zh' => 'Han-Latin'];
    /**
     *
     */
    private ?string $defaultLocale;
    /**
     * @var (\Closure | array) $symbolsMap
     */
    private $symbolsMap = ['en' => ['@' => 'at', '&' => 'and']];
    /**
     * Cache of transliterators per locale.
     *
     * @var \Transliterator[]
     */
    private array $transliterators = [];
    /**
     * @param (array | \Closure | null) $symbolsMap
     */
    public function __construct(string $defaultLocale = null, $symbolsMap = null)
    {
        if (!(\is_array($symbolsMap) || $symbolsMap instanceof \Closure || \is_null($symbolsMap))) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($symbolsMap) must be of type ?Closure|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($symbolsMap) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $this->defaultLocale = $defaultLocale;
        $this->symbolsMap = $symbolsMap ?? $this->symbolsMap;
    }
    /**
     * {@inheritdoc}
     */
    public function setLocale(string $locale)
    {
        $this->defaultLocale = $locale;
    }
    /**
     * {@inheritdoc}
     */
    public function getLocale() : string
    {
        return $this->defaultLocale;
    }
    /**
     * {@inheritdoc}
     */
    public function slug(string $string, string $separator = '-', string $locale = null) : AbstractUnicodeString
    {
        $locale = $locale ?? $this->defaultLocale;
        $transliterator = [];
        if ($locale && ('de' === $locale || 0 === \strpos($locale, 'de_'))) {
            // Use the shortcut for German in UnicodeString::ascii() if possible (faster and no requirement on intl)
            $transliterator = ['de-ASCII'];
        } elseif (\function_exists('transliterator_transliterate') && $locale) {
            $transliterator = (array) $this->createTransliterator($locale);
        }
        if ($this->symbolsMap instanceof \Closure) {
            // If the symbols map is passed as a closure, there is no need to fallback to the parent locale
            // as the closure can just provide substitutions for all locales of interest.
            $symbolsMap = $this->symbolsMap;
            \array_unshift($transliterator, static function ($s) use($symbolsMap, $locale) {
                return $symbolsMap($s, $locale);
            });
        }
        $unicodeString = (new UnicodeString($string))->ascii($transliterator);
        if (\is_array($this->symbolsMap)) {
            $map = null;
            if (isset($this->symbolsMap[$locale])) {
                $map = $this->symbolsMap[$locale];
            } else {
                $parent = self::getParentLocale($locale);
                if ($parent && isset($this->symbolsMap[$parent])) {
                    $map = $this->symbolsMap[$parent];
                }
            }
            if ($map) {
                foreach ($map as $char => $replace) {
                    $unicodeString = $unicodeString->replace($char, ' ' . $replace . ' ');
                }
            }
        }
        return $unicodeString->replaceMatches('/[^A-Za-z0-9]++/', $separator)->trim($separator);
    }
    /**
     *
     */
    private function createTransliterator(string $locale) : ?\Transliterator
    {
        if (\array_key_exists($locale, $this->transliterators)) {
            return $this->transliterators[$locale];
        }
        // Exact locale supported, cache and return
        if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$locale] ?? null) {
            return $this->transliterators[$locale] = \Transliterator::create($id . '/BGN') ?? \Transliterator::create($id);
        }
        // Locale not supported and no parent, fallback to any-latin
        if (!($parent = self::getParentLocale($locale))) {
            return $this->transliterators[$locale] = null;
        }
        // Try to use the parent locale (ie. try "de" for "de_AT") and cache both locales
        if ($id = self::LOCALE_TO_TRANSLITERATOR_ID[$parent] ?? null) {
            $transliterator = \Transliterator::create($id . '/BGN') ?? \Transliterator::create($id);
        }
        return $this->transliterators[$locale] = $this->transliterators[$parent] = $transliterator ?? null;
    }
    /**
     *
     */
    private static function getParentLocale(?string $locale) : ?string
    {
        if (!$locale) {
            return null;
        }
        if (\false === ($str = \strrchr($locale, '_'))) {
            // no parent locale
            return null;
        }
        return \Phabel\Target\Php80\Polyfill::substr($locale, 0, -\strlen($str));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String\Slugger;

use PhabelVendor\Symfony\Component\String\AbstractUnicodeString;
/**
 * Creates a URL-friendly slug from a given string.
 *
 * @author Titouan Galopin <galopintitouan@gmail.com>
 */
interface SluggerInterface
{
    /**
     * Creates a slug for the given string and locale, using appropriate transliteration when needed.
     */
    public function slug(string $string, string $separator = '-', string $locale = null) : AbstractUnicodeString;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String;

use PhabelVendor\Symfony\Component\String\Exception\ExceptionInterface;
use PhabelVendor\Symfony\Component\String\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\String\Exception\RuntimeException;
/**
 * Represents a binary-safe string of bytes.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class ByteString extends AbstractString
{
    private const ALPHABET_ALPHANUMERIC = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz';
    /**
     *
     */
    public function __construct(string $string = '')
    {
        $this->string = $string;
    }
    /*
     * The following method was derived from code of the Hack Standard Library (v4.40 - 2020-05-03)
     *
     * https://github.com/hhvm/hsl/blob/80a42c02f036f72a42f0415e80d6b847f4bf62d5/src/random/private.php#L16
     *
     * Code subject to the MIT license (https://github.com/hhvm/hsl/blob/master/LICENSE).
     *
     * Copyright (c) 2004-2020, Facebook, Inc. (https://www.facebook.com/)
     */
    /**
     *
     */
    public static function fromRandom(int $length = 16, string $alphabet = null) : self
    {
        if ($length <= 0) {
            throw new InvalidArgumentException(\sprintf('A strictly positive length is expected, "%d" given.', $length));
        }
        $alphabet = $alphabet ?? self::ALPHABET_ALPHANUMERIC;
        $alphabetSize = \strlen($alphabet);
        $bits = (int) \ceil(\log($alphabetSize, 2.0));
        if ($bits <= 0 || $bits > 56) {
            throw new InvalidArgumentException('The length of the alphabet must in the [2^1, 2^56] range.');
        }
        $ret = '';
        while ($length > 0) {
            $urandomLength = (int) \ceil(2 * $length * $bits / 8.0);
            $data = \random_bytes($urandomLength);
            $unpackedData = 0;
            $unpackedBits = 0;
            for ($i = 0; $i < $urandomLength && $length > 0; ++$i) {
                // Unpack 8 bits
                $unpackedData = $unpackedData << 8 | \ord($data[$i]);
                $unpackedBits += 8;
                // While we have enough bits to select a character from the alphabet, keep
                // consuming the random data
                for (; $unpackedBits >= $bits && $length > 0; $unpackedBits -= $bits) {
                    $index = $unpackedData & (1 << $bits) - 1;
                    $unpackedData >>= $bits;
                    // Unfortunately, the alphabet size is not necessarily a power of two.
                    // Worst case, it is 2^k + 1, which means we need (k+1) bits and we
                    // have around a 50% chance of missing as k gets larger
                    if ($index < $alphabetSize) {
                        $ret .= $alphabet[$index];
                        --$length;
                    }
                }
            }
        }
        return new static($ret);
    }
    /**
     *
     */
    public function bytesAt(int $offset) : array
    {
        $str = $this->string[$offset] ?? '';
        return '' === $str ? [] : [\ord($str)];
    }
    /**
     * @return static
     */
    public function append(string ...$suffix)
    {
        $str = clone $this;
        $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function camel()
    {
        $str = clone $this;
        $str->string = \lcfirst(\str_replace(' ', '', \ucwords(\preg_replace('/[^a-zA-Z0-9\\x7f-\\xff]++/', ' ', $this->string))));
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function chunk(int $length = 1) : array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }
        if ('' === $this->string) {
            return [];
        }
        $str = clone $this;
        $chunks = [];
        foreach (\str_split($this->string, $length) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }
        return $chunks;
    }
    /**
     * @param (string | iterable | AbstractString) $suffix
     */
    public function endsWith($suffix) : bool
    {
        if (!(\is_array($suffix) || $suffix instanceof \Traversable || $suffix instanceof AbstractString)) {
            if (!\is_string($suffix)) {
                if (!(\is_string($suffix) || \is_object($suffix) && \method_exists($suffix, '__toString') || (\is_bool($suffix) || \is_numeric($suffix)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($suffix) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($suffix) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $suffix = (string) $suffix;
                }
            }
        }
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }
        return '' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \Phabel\Target\Php80\Polyfill::substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase);
    }
    /**
     * @param (string | iterable | AbstractString) $string
     */
    public function equalsTo($string) : bool
    {
        if (!(\is_array($string) || $string instanceof \Traversable || $string instanceof AbstractString)) {
            if (!\is_string($string)) {
                if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $string = (string) $string;
                }
            }
        }
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }
        if ('' !== $string && $this->ignoreCase) {
            return 0 === \strcasecmp($string, $this->string);
        }
        return $string === $this->string;
    }
    /**
     * @return static
     */
    public function folded()
    {
        $str = clone $this;
        $str->string = \strtolower($str->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | iterable | AbstractString) $needle
     */
    public function indexOf($needle, int $offset = 0) : ?int
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable || $needle instanceof AbstractString)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }
        if ('' === $needle) {
            return null;
        }
        $i = $this->ignoreCase ? \stripos($this->string, $needle, $offset) : \strpos($this->string, $needle, $offset);
        return \false === $i ? null : $i;
    }
    /**
     * @param (string | iterable | AbstractString) $needle
     */
    public function indexOfLast($needle, int $offset = 0) : ?int
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable || $needle instanceof AbstractString)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }
        if ('' === $needle) {
            return null;
        }
        $i = $this->ignoreCase ? \strripos($this->string, $needle, $offset) : \strrpos($this->string, $needle, $offset);
        return \false === $i ? null : $i;
    }
    /**
     *
     */
    public function isUtf8() : bool
    {
        return '' === $this->string || \preg_match('//u', $this->string);
    }
    /**
     * @return static
     */
    public function join(array $strings, string $lastGlue = null)
    {
        $str = clone $this;
        $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : '';
        $str->string = \implode($this->string, $strings) . $tail;
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function length() : int
    {
        return \strlen($this->string);
    }
    /**
     * @return static
     */
    public function lower()
    {
        $str = clone $this;
        $str->string = \strtolower($str->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function match(string $regexp, int $flags = 0, int $offset = 0) : array
    {
        $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
        if ($this->ignoreCase) {
            $regexp .= 'i';
        }
        \set_error_handler(static function ($t, $m) {
            throw new InvalidArgumentException($m);
        });
        try {
            if (\false === $match($regexp, $this->string, $matches, $flags | 0, $offset)) {
                $lastError = \preg_last_error();
                foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
                    if ($lastError === $v && '_ERROR' === \Phabel\Target\Php80\Polyfill::substr($k, -6)) {
                        throw new RuntimeException('Matching failed with ' . $k . '.');
                    }
                }
                throw new RuntimeException('Matching failed with unknown error code.');
            }
        } finally {
            \restore_error_handler();
        }
        array_walk_recursive($match, function (&$v){return $v === "" ? null : $v;}); return $matches;
    }
    /**
     * @return static
     */
    public function padBoth(int $length, string $padStr = ' ')
    {
        $str = clone $this;
        $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_BOTH);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function padEnd(int $length, string $padStr = ' ')
    {
        $str = clone $this;
        $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_RIGHT);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function padStart(int $length, string $padStr = ' ')
    {
        $str = clone $this;
        $str->string = \str_pad($this->string, $length, $padStr, \STR_PAD_LEFT);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function prepend(string ...$prefix)
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $str->string;
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function replace(string $from, string $to)
    {
        $str = clone $this;
        if ('' !== $from) {
            $str->string = $this->ignoreCase ? \str_ireplace($from, $to, $this->string) : \str_replace($from, $to, $this->string);
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | callable) $to
     * @return static
     */
    public function replaceMatches(string $fromRegexp, $to)
    {
        if (!\is_callable($to)) {
            if (!\is_string($to)) {
                if (!(\is_string($to) || \is_object($to) && \method_exists($to, '__toString') || (\is_bool($to) || \is_numeric($to)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #2 ($to) must be of type callable|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($to) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $to = (string) $to;
                }
            }
        }
        if ($this->ignoreCase) {
            $fromRegexp .= 'i';
        }
        $replace = \is_array($to) || $to instanceof \Closure ? 'preg_replace_callback' : 'preg_replace';
        \set_error_handler(static function ($t, $m) {
            throw new InvalidArgumentException($m);
        });
        try {
            if (null === ($string = $replace($fromRegexp, $to, $this->string))) {
                $lastError = \preg_last_error();
                foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
                    if ($lastError === $v && '_ERROR' === \Phabel\Target\Php80\Polyfill::substr($k, -6)) {
                        throw new RuntimeException('Matching failed with ' . $k . '.');
                    }
                }
                throw new RuntimeException('Matching failed with unknown error code.');
            }
        } finally {
            \restore_error_handler();
        }
        $str = clone $this;
        $str->string = $string;
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function reverse()
    {
        $str = clone $this;
        $str->string = \strrev($str->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function slice(int $start = 0, int $length = null)
    {
        $str = clone $this;
        $str->string = (string) \Phabel\Target\Php80\Polyfill::substr($this->string, $start, $length ?? \PHP_INT_MAX);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function snake()
    {
        $str = $this->camel()->title();
        $str->string = \strtolower(\preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\\d])([A-Z])/'], 'PhabelVendor\\1_\\2', $str->string));
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function splice(string $replacement, int $start = 0, int $length = null)
    {
        $str = clone $this;
        $str->string = \Phabel\Target\Php80\Polyfill::substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function split(string $delimiter, int $limit = null, int $flags = null) : array
    {
        if (1 > ($limit = $limit ?? \PHP_INT_MAX)) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }
        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }
        if (null !== $flags) {
            return parent::split($delimiter, $limit, $flags);
        }
        $str = clone $this;
        $chunks = $this->ignoreCase ? \preg_split('{' . \preg_quote($delimiter) . '}iD', $this->string, $limit) : \explode($delimiter, $this->string, $limit);
        foreach ($chunks as &$chunk) {
            $str->string = $chunk;
            $chunk = clone $str;
        }
        return $chunks;
    }
    /**
     * @param (string | iterable | AbstractString) $prefix
     */
    public function startsWith($prefix) : bool
    {
        if (!(\is_array($prefix) || $prefix instanceof \Traversable || $prefix instanceof AbstractString)) {
            if (!\is_string($prefix)) {
                if (!(\is_string($prefix) || \is_object($prefix) && \method_exists($prefix, '__toString') || (\is_bool($prefix) || \is_numeric($prefix)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($prefix) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($prefix) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $prefix = (string) $prefix;
                }
            }
        }
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }
        return '' !== $prefix && 0 === ($this->ignoreCase ? \strncasecmp($this->string, $prefix, \strlen($prefix)) : \strncmp($this->string, $prefix, \strlen($prefix)));
    }
    /**
     * @return static
     */
    public function title(bool $allWords = \false)
    {
        $str = clone $this;
        $str->string = $allWords ? \ucwords($str->string) : \ucfirst($str->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function toUnicodeString(string $fromEncoding = null) : UnicodeString
    {
        return new UnicodeString($this->toCodePointString($fromEncoding)->string);
    }
    /**
     *
     */
    public function toCodePointString(string $fromEncoding = null) : CodePointString
    {
        $u = new CodePointString();
        if (\in_array($fromEncoding, [null, 'utf8', 'utf-8', 'UTF8', 'UTF-8'], \true) && \preg_match('//u', $this->string)) {
            $u->string = $this->string;
            return $u;
        }
        \set_error_handler(static function ($t, $m) {
            throw new InvalidArgumentException($m);
        });
        try {
            try {
                $validEncoding = \false !== \mb_detect_encoding($this->string, $fromEncoding ?? 'Windows-1252', \true);
            } catch (InvalidArgumentException $e) {
                if (!\function_exists('iconv')) {
                    throw $e;
                }
                $u->string = \iconv($fromEncoding ?? 'Windows-1252', 'UTF-8', $this->string);
                return $u;
            }
        } finally {
            \restore_error_handler();
        }
        if (!$validEncoding) {
            throw new InvalidArgumentException(\sprintf('Invalid "%s" string.', $fromEncoding ?? 'Windows-1252'));
        }
        $u->string = \mb_convert_encoding($this->string, 'UTF-8', $fromEncoding ?? 'Windows-1252');
        return $u;
    }
    /**
     * @return static
     */
    public function trim(string $chars = " \t\n\r\x00\v\f")
    {
        $str = clone $this;
        $str->string = \trim($str->string, $chars);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function trimEnd(string $chars = " \t\n\r\x00\v\f")
    {
        $str = clone $this;
        $str->string = \rtrim($str->string, $chars);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function trimStart(string $chars = " \t\n\r\x00\v\f")
    {
        $str = clone $this;
        $str->string = \ltrim($str->string, $chars);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function upper()
    {
        $str = clone $this;
        $str->string = \strtoupper($str->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function width(bool $ignoreAnsiDecoration = \true) : int
    {
        $string = \preg_match('//u', $this->string) ? $this->string : \preg_replace('/[\\x80-\\xFF]/', '?', $this->string);
        return (new CodePointString($string))->width($ignoreAnsiDecoration);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String;

if (!\function_exists(u::class)) {
    /**
     *
     */
    function u(?string $string = '') : UnicodeString
    {
        return new UnicodeString($string ?? '');
    }
}
if (!\function_exists(b::class)) {
    /**
     *
     */
    function b(?string $string = '') : ByteString
    {
        return new ByteString($string ?? '');
    }
}
if (!\function_exists(s::class)) {
    /**
     * @return (UnicodeString | ByteString)
     */
    function s(?string $string = '') : AbstractString
    {
        $string = $string ?? '';
        return \preg_match('//u', $string) ? new UnicodeString($string) : new ByteString($string);
    }
}
<?php

namespace PhabelVendor;

/*
 * This file has been auto-generated by the Symfony String Component for internal use.
 *
 * Unicode version: 14.0.0
 * Date: 2021-09-17T09:20:30+02:00
 */
return [[768, 879], [1155, 1159], [1160, 1161], [1425, 1469], [1471, 1471], [1473, 1474], [1476, 1477], [1479, 1479], [1552, 1562], [1611, 1631], [1648, 1648], [1750, 1756], [1759, 1764], [1767, 1768], [1770, 1773], [1809, 1809], [1840, 1866], [1958, 1968], [2027, 2035], [2045, 2045], [2070, 2073], [2075, 2083], [2085, 2087], [2089, 2093], [2137, 2139], [2200, 2207], [2250, 2273], [2275, 2306], [2362, 2362], [2364, 2364], [2369, 2376], [2381, 2381], [2385, 2391], [2402, 2403], [2433, 2433], [2492, 2492], [2497, 2500], [2509, 2509], [2530, 2531], [2558, 2558], [2561, 2562], [2620, 2620], [2625, 2626], [2631, 2632], [2635, 2637], [2641, 2641], [2672, 2673], [2677, 2677], [2689, 2690], [2748, 2748], [2753, 2757], [2759, 2760], [2765, 2765], [2786, 2787], [2810, 2815], [2817, 2817], [2876, 2876], [2879, 2879], [2881, 2884], [2893, 2893], [2901, 2902], [2914, 2915], [2946, 2946], [3008, 3008], [3021, 3021], [3072, 3072], [3076, 3076], [3132, 3132], [3134, 3136], [3142, 3144], [3146, 3149], [3157, 3158], [3170, 3171], [3201, 3201], [3260, 3260], [3263, 3263], [3270, 3270], [3276, 3277], [3298, 3299], [3328, 3329], [3387, 3388], [3393, 3396], [3405, 3405], [3426, 3427], [3457, 3457], [3530, 3530], [3538, 3540], [3542, 3542], [3633, 3633], [3636, 3642], [3655, 3662], [3761, 3761], [3764, 3772], [3784, 3789], [3864, 3865], [3893, 3893], [3895, 3895], [3897, 3897], [3953, 3966], [3968, 3972], [3974, 3975], [3981, 3991], [3993, 4028], [4038, 4038], [4141, 4144], [4146, 4151], [4153, 4154], [4157, 4158], [4184, 4185], [4190, 4192], [4209, 4212], [4226, 4226], [4229, 4230], [4237, 4237], [4253, 4253], [4957, 4959], [5906, 5908], [5938, 5939], [5970, 5971], [6002, 6003], [6068, 6069], [6071, 6077], [6086, 6086], [6089, 6099], [6109, 6109], [6155, 6157], [6159, 6159], [6277, 6278], [6313, 6313], [6432, 6434], [6439, 6440], [6450, 6450], [6457, 6459], [6679, 6680], [6683, 6683], [6742, 6742], [6744, 6750], [6752, 6752], [6754, 6754], [6757, 6764], [6771, 6780], [6783, 6783], [6832, 6845], [6846, 6846], [6847, 6862], [6912, 6915], [6964, 6964], [6966, 6970], [6972, 6972], [6978, 6978], [7019, 7027], [7040, 7041], [7074, 7077], [7080, 7081], [7083, 7085], [7142, 7142], [7144, 7145], [7149, 7149], [7151, 7153], [7212, 7219], [7222, 7223], [7376, 7378], [7380, 7392], [7394, 7400], [7405, 7405], [7412, 7412], [7416, 7417], [7616, 7679], [8400, 8412], [8413, 8416], [8417, 8417], [8418, 8420], [8421, 8432], [11503, 11505], [11647, 11647], [11744, 11775], [12330, 12333], [12441, 12442], [42607, 42607], [42608, 42610], [42612, 42621], [42654, 42655], [42736, 42737], [43010, 43010], [43014, 43014], [43019, 43019], [43045, 43046], [43052, 43052], [43204, 43205], [43232, 43249], [43263, 43263], [43302, 43309], [43335, 43345], [43392, 43394], [43443, 43443], [43446, 43449], [43452, 43453], [43493, 43493], [43561, 43566], [43569, 43570], [43573, 43574], [43587, 43587], [43596, 43596], [43644, 43644], [43696, 43696], [43698, 43700], [43703, 43704], [43710, 43711], [43713, 43713], [43756, 43757], [43766, 43766], [44005, 44005], [44008, 44008], [44013, 44013], [64286, 64286], [65024, 65039], [65056, 65071], [66045, 66045], [66272, 66272], [66422, 66426], [68097, 68099], [68101, 68102], [68108, 68111], [68152, 68154], [68159, 68159], [68325, 68326], [68900, 68903], [69291, 69292], [69446, 69456], [69506, 69509], [69633, 69633], [69688, 69702], [69744, 69744], [69747, 69748], [69759, 69761], [69811, 69814], [69817, 69818], [69826, 69826], [69888, 69890], [69927, 69931], [69933, 69940], [70003, 70003], [70016, 70017], [70070, 70078], [70089, 70092], [70095, 70095], [70191, 70193], [70196, 70196], [70198, 70199], [70206, 70206], [70367, 70367], [70371, 70378], [70400, 70401], [70459, 70460], [70464, 70464], [70502, 70508], [70512, 70516], [70712, 70719], [70722, 70724], [70726, 70726], [70750, 70750], [70835, 70840], [70842, 70842], [70847, 70848], [70850, 70851], [71090, 71093], [71100, 71101], [71103, 71104], [71132, 71133], [71219, 71226], [71229, 71229], [71231, 71232], [71339, 71339], [71341, 71341], [71344, 71349], [71351, 71351], [71453, 71455], [71458, 71461], [71463, 71467], [71727, 71735], [71737, 71738], [71995, 71996], [71998, 71998], [72003, 72003], [72148, 72151], [72154, 72155], [72160, 72160], [72193, 72202], [72243, 72248], [72251, 72254], [72263, 72263], [72273, 72278], [72281, 72283], [72330, 72342], [72344, 72345], [72752, 72758], [72760, 72765], [72767, 72767], [72850, 72871], [72874, 72880], [72882, 72883], [72885, 72886], [73009, 73014], [73018, 73018], [73020, 73021], [73023, 73029], [73031, 73031], [73104, 73105], [73109, 73109], [73111, 73111], [73459, 73460], [92912, 92916], [92976, 92982], [94031, 94031], [94095, 94098], [94180, 94180], [113821, 113822], [118528, 118573], [118576, 118598], [119143, 119145], [119163, 119170], [119173, 119179], [119210, 119213], [119362, 119364], [121344, 121398], [121403, 121452], [121461, 121461], [121476, 121476], [121499, 121503], [121505, 121519], [122880, 122886], [122888, 122904], [122907, 122913], [122915, 122916], [122918, 122922], [123184, 123190], [123566, 123566], [123628, 123631], [125136, 125142], [125252, 125258], [917760, 917999]];
<?php

namespace PhabelVendor;

/*
 * This file has been auto-generated by the Symfony String Component for internal use.
 *
 * Unicode version: 14.0.0
 * Date: 2021-09-17T09:20:30+02:00
 */
return [[4352, 4447], [8986, 8987], [9001, 9001], [9002, 9002], [9193, 9196], [9200, 9200], [9203, 9203], [9725, 9726], [9748, 9749], [9800, 9811], [9855, 9855], [9875, 9875], [9889, 9889], [9898, 9899], [9917, 9918], [9924, 9925], [9934, 9934], [9940, 9940], [9962, 9962], [9970, 9971], [9973, 9973], [9978, 9978], [9981, 9981], [9989, 9989], [9994, 9995], [10024, 10024], [10060, 10060], [10062, 10062], [10067, 10069], [10071, 10071], [10133, 10135], [10160, 10160], [10175, 10175], [11035, 11036], [11088, 11088], [11093, 11093], [11904, 11929], [11931, 12019], [12032, 12245], [12272, 12283], [12288, 12288], [12289, 12291], [12292, 12292], [12293, 12293], [12294, 12294], [12295, 12295], [12296, 12296], [12297, 12297], [12298, 12298], [12299, 12299], [12300, 12300], [12301, 12301], [12302, 12302], [12303, 12303], [12304, 12304], [12305, 12305], [12306, 12307], [12308, 12308], [12309, 12309], [12310, 12310], [12311, 12311], [12312, 12312], [12313, 12313], [12314, 12314], [12315, 12315], [12316, 12316], [12317, 12317], [12318, 12319], [12320, 12320], [12321, 12329], [12330, 12333], [12334, 12335], [12336, 12336], [12337, 12341], [12342, 12343], [12344, 12346], [12347, 12347], [12348, 12348], [12349, 12349], [12350, 12350], [12353, 12438], [12441, 12442], [12443, 12444], [12445, 12446], [12447, 12447], [12448, 12448], [12449, 12538], [12539, 12539], [12540, 12542], [12543, 12543], [12549, 12591], [12593, 12686], [12688, 12689], [12690, 12693], [12694, 12703], [12704, 12735], [12736, 12771], [12784, 12799], [12800, 12830], [12832, 12841], [12842, 12871], [12880, 12880], [12881, 12895], [12896, 12927], [12928, 12937], [12938, 12976], [12977, 12991], [12992, 13055], [13056, 13311], [13312, 19903], [19968, 40959], [40960, 40980], [40981, 40981], [40982, 42124], [42128, 42182], [43360, 43388], [44032, 55203], [63744, 64109], [64110, 64111], [64112, 64217], [64218, 64255], [65040, 65046], [65047, 65047], [65048, 65048], [65049, 65049], [65072, 65072], [65073, 65074], [65075, 65076], [65077, 65077], [65078, 65078], [65079, 65079], [65080, 65080], [65081, 65081], [65082, 65082], [65083, 65083], [65084, 65084], [65085, 65085], [65086, 65086], [65087, 65087], [65088, 65088], [65089, 65089], [65090, 65090], [65091, 65091], [65092, 65092], [65093, 65094], [65095, 65095], [65096, 65096], [65097, 65100], [65101, 65103], [65104, 65106], [65108, 65111], [65112, 65112], [65113, 65113], [65114, 65114], [65115, 65115], [65116, 65116], [65117, 65117], [65118, 65118], [65119, 65121], [65122, 65122], [65123, 65123], [65124, 65126], [65128, 65128], [65129, 65129], [65130, 65131], [65281, 65283], [65284, 65284], [65285, 65287], [65288, 65288], [65289, 65289], [65290, 65290], [65291, 65291], [65292, 65292], [65293, 65293], [65294, 65295], [65296, 65305], [65306, 65307], [65308, 65310], [65311, 65312], [65313, 65338], [65339, 65339], [65340, 65340], [65341, 65341], [65342, 65342], [65343, 65343], [65344, 65344], [65345, 65370], [65371, 65371], [65372, 65372], [65373, 65373], [65374, 65374], [65375, 65375], [65376, 65376], [65504, 65505], [65506, 65506], [65507, 65507], [65508, 65508], [65509, 65510], [94176, 94177], [94178, 94178], [94179, 94179], [94180, 94180], [94192, 94193], [94208, 100343], [100352, 101119], [101120, 101589], [101632, 101640], [110576, 110579], [110581, 110587], [110589, 110590], [110592, 110847], [110848, 110882], [110928, 110930], [110948, 110951], [110960, 111355], [126980, 126980], [127183, 127183], [127374, 127374], [127377, 127386], [127488, 127490], [127504, 127547], [127552, 127560], [127568, 127569], [127584, 127589], [127744, 127776], [127789, 127797], [127799, 127868], [127870, 127891], [127904, 127946], [127951, 127955], [127968, 127984], [127988, 127988], [127992, 127994], [127995, 127999], [128000, 128062], [128064, 128064], [128066, 128252], [128255, 128317], [128331, 128334], [128336, 128359], [128378, 128378], [128405, 128406], [128420, 128420], [128507, 128511], [128512, 128591], [128640, 128709], [128716, 128716], [128720, 128722], [128725, 128727], [128733, 128735], [128747, 128748], [128756, 128764], [128992, 129003], [129008, 129008], [129292, 129338], [129340, 129349], [129351, 129535], [129648, 129652], [129656, 129660], [129664, 129670], [129680, 129708], [129712, 129722], [129728, 129733], [129744, 129753], [129760, 129767], [129776, 129782], [131072, 173791], [173792, 173823], [173824, 177976], [177977, 177983], [177984, 178205], [178206, 178207], [178208, 183969], [183970, 183983], [183984, 191456], [191457, 194559], [194560, 195101], [195102, 195103], [195104, 196605], [196608, 201546], [201547, 262141]];
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String;

use PhabelVendor\Symfony\Component\String\Exception\ExceptionInterface;
use PhabelVendor\Symfony\Component\String\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\String\Exception\RuntimeException;
/**
 * Represents a string of abstract Unicode characters.
 *
 * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
 * This class is the abstract type to use as a type-hint when the logic you want to
 * implement is Unicode-aware but doesn't care about code points vs grapheme clusters.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @throws ExceptionInterface
 */
abstract class AbstractUnicodeString extends AbstractString
{
    public const NFC = \Normalizer::NFC;
    public const NFD = \Normalizer::NFD;
    public const NFKC = \Normalizer::NFKC;
    public const NFKD = \Normalizer::NFKD;
    // all ASCII letters sorted by typical frequency of occurrence
    private const ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T<D4}B{8FwR67UGN;JzV#HOW_&!K?XQ%Y\\\tZ+~^\$@`\x00\x01\x02\x03\x04\x05\x06\x07\x08\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
    // the subset of folded case mappings that is not in lower case mappings
    private const FOLD_FROM = ['Ä°', 'Âµ', 'Å¿', "Í…", 'Ï‚', 'Ï�', 'Ï‘', 'Ï•', 'Ï–', 'Ï°', 'Ï±', 'Ïµ', 'áº›', "á¾¾", 'ÃŸ', 'Ä°', 'Å‰', 'Ç°', 'Î�', 'Î°', 'Ö‡', 'áº–', 'áº—', 'áº˜', 'áº™', 'áºš', 'áºž', 'á½�', 'á½’', 'á½”', 'á½–', 'á¾€', 'á¾�', 'á¾‚', 'á¾ƒ', 'á¾„', 'á¾…', 'á¾†', 'á¾‡', 'á¾ˆ', 'á¾‰', 'á¾Š', 'á¾‹', 'á¾Œ', 'á¾�', 'á¾Ž', 'á¾�', 'á¾�', 'á¾‘', 'á¾’', 'á¾“', 'á¾”', 'á¾•', 'á¾–', 'á¾—', 'á¾˜', 'á¾™', 'á¾š', 'á¾›', 'á¾œ', 'á¾�', 'á¾ž', 'á¾Ÿ', 'á¾ ', 'á¾¡', 'á¾¢', 'á¾£', 'á¾¤', 'á¾¥', 'á¾¦', 'á¾§', 'á¾¨', 'á¾©', 'á¾ª', 'á¾«', 'á¾¬', 'á¾­', 'á¾®', 'á¾¯', 'á¾²', 'á¾³', 'á¾´', 'á¾¶', 'á¾·', 'á¾¼', 'á¿‚', 'á¿ƒ', 'á¿„', 'á¿†', 'á¿‡', 'á¿Œ', 'á¿’', 'Î�', 'á¿–', 'á¿—', 'á¿¢', 'Î°', 'á¿¤', 'á¿¦', 'á¿§', 'á¿²', 'á¿³', 'á¿´', 'á¿¶', 'á¿·', 'á¿¼', 'ï¬€', 'ï¬�', 'ï¬‚', 'ï¬ƒ', 'ï¬„', 'ï¬…', 'ï¬†', 'ï¬“', 'ï¬”', 'ï¬•', 'ï¬–', 'ï¬—'];
    private const FOLD_TO = ['iÌ‡', 'Î¼', 's', 'Î¹', 'Ïƒ', 'Î²', 'Î¸', 'Ï†', 'Ï€', 'Îº', 'Ï�', 'Îµ', 'á¹¡', 'Î¹', 'ss', 'iÌ‡', 'Ê¼n', 'Ç°', 'Î�', 'Î°', 'Õ¥Ö‚', 'áº–', 'áº—', 'áº˜', 'áº™', 'aÊ¾', 'ss', 'á½�', 'á½’', 'á½”', 'á½–', 'á¼€Î¹', 'á¼�Î¹', 'á¼‚Î¹', 'á¼ƒÎ¹', 'á¼„Î¹', 'á¼…Î¹', 'á¼†Î¹', 'á¼‡Î¹', 'á¼€Î¹', 'á¼�Î¹', 'á¼‚Î¹', 'á¼ƒÎ¹', 'á¼„Î¹', 'á¼…Î¹', 'á¼†Î¹', 'á¼‡Î¹', 'á¼ Î¹', 'á¼¡Î¹', 'á¼¢Î¹', 'á¼£Î¹', 'á¼¤Î¹', 'á¼¥Î¹', 'á¼¦Î¹', 'á¼§Î¹', 'á¼ Î¹', 'á¼¡Î¹', 'á¼¢Î¹', 'á¼£Î¹', 'á¼¤Î¹', 'á¼¥Î¹', 'á¼¦Î¹', 'á¼§Î¹', 'á½ Î¹', 'á½¡Î¹', 'á½¢Î¹', 'á½£Î¹', 'á½¤Î¹', 'á½¥Î¹', 'á½¦Î¹', 'á½§Î¹', 'á½ Î¹', 'á½¡Î¹', 'á½¢Î¹', 'á½£Î¹', 'á½¤Î¹', 'á½¥Î¹', 'á½¦Î¹', 'á½§Î¹', 'á½°Î¹', 'Î±Î¹', 'Î¬Î¹', 'á¾¶', 'á¾¶Î¹', 'Î±Î¹', 'á½´Î¹', 'Î·Î¹', 'Î®Î¹', 'á¿†', 'á¿†Î¹', 'Î·Î¹', 'á¿’', 'Î�', 'á¿–', 'á¿—', 'á¿¢', 'Î°', 'á¿¤', 'á¿¦', 'á¿§', 'á½¼Î¹', 'Ï‰Î¹', 'ÏŽÎ¹', 'á¿¶', 'á¿¶Î¹', 'Ï‰Î¹', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'st', 'st', 'Õ´Õ¶', 'Õ´Õ¥', 'Õ´Õ«', 'Õ¾Õ¶', 'Õ´Õ­'];
    // the subset of upper case mappings that map one code point to many code points
    private const UPPER_FROM = ['ÃŸ', 'ï¬€', 'ï¬�', 'ï¬‚', 'ï¬ƒ', 'ï¬„', 'ï¬…', 'ï¬†', 'Ö‡', 'ï¬“', 'ï¬”', 'ï¬•', 'ï¬–', 'ï¬—', 'Å‰', 'Î�', 'Î°', 'Ç°', 'áº–', 'áº—', 'áº˜', 'áº™', 'áºš', 'á½�', 'á½’', 'á½”', 'á½–', 'á¾¶', 'á¿†', 'á¿’', 'á¿“', 'á¿–', 'á¿—', 'á¿¢', 'á¿£', 'á¿¤', 'á¿¦', 'á¿§', 'á¿¶'];
    private const UPPER_TO = ['SS', 'FF', 'FI', 'FL', 'FFI', 'FFL', 'ST', 'ST', 'ÔµÕ’', 'Õ„Õ†', 'Õ„Ôµ', 'Õ„Ô»', 'ÕŽÕ†', 'Õ„Ô½', 'Ê¼N', 'Î™ÌˆÌ�', 'Î¥ÌˆÌ�', 'JÌŒ', 'HÌ±', 'TÌˆ', 'WÌŠ', 'YÌŠ', 'AÊ¾', 'Î¥Ì“', 'Î¥Ì“Ì€', 'Î¥Ì“Ì�', 'Î¥Ì“Í‚', 'Î‘Í‚', 'Î—Í‚', 'Î™ÌˆÌ€', 'Î™ÌˆÌ�', 'Î™Í‚', 'Î™ÌˆÍ‚', 'Î¥ÌˆÌ€', 'Î¥ÌˆÌ�', 'Î¡Ì“', 'Î¥Í‚', 'Î¥ÌˆÍ‚', 'Î©Í‚'];
    // the subset of https://github.com/unicode-org/cldr/blob/master/common/transforms/Latin-ASCII.xml that is not in NFKD
    private const TRANSLIT_FROM = ['Ã†', 'Ã�', 'Ã˜', 'Ãž', 'ÃŸ', 'Ã¦', 'Ã°', 'Ã¸', 'Ã¾', 'Ä�', 'Ä‘', 'Ä¦', 'Ä§', 'Ä±', 'Ä¸', 'Ä¿', 'Å€', 'Å�', 'Å‚', 'Å‰', 'ÅŠ', 'Å‹', 'Å’', 'Å“', 'Å¦', 'Å§', 'Æ€', 'Æ�', 'Æ‚', 'Æƒ', 'Æ‡', 'Æˆ', 'Æ‰', 'ÆŠ', 'Æ‹', 'ÆŒ', 'Æ�', 'Æ‘', 'Æ’', 'Æ“', 'Æ•', 'Æ–', 'Æ—', 'Æ˜', 'Æ™', 'Æš', 'Æ�', 'Æž', 'Æ¢', 'Æ£', 'Æ¤', 'Æ¥', 'Æ«', 'Æ¬', 'Æ­', 'Æ®', 'Æ²', 'Æ³', 'Æ´', 'Æµ', 'Æ¶', 'Ç„', 'Ç…', 'Ç†', 'Ç¤', 'Ç¥', 'È¡', 'È¤', 'È¥', 'È´', 'Èµ', 'È¶', 'È·', 'È¸', 'È¹', 'Èº', 'È»', 'È¼', 'È½', 'È¾', 'È¿', 'É€', 'Éƒ', 'É„', 'É†', 'É‡', 'Éˆ', 'É‰', 'ÉŒ', 'É�', 'ÉŽ', 'É�', 'É“', 'É•', 'É–', 'É—', 'É›', 'ÉŸ', 'É ', 'É¡', 'É¢', 'É¦', 'É§', 'É¨', 'Éª', 'É«', 'É¬', 'É­', 'É±', 'É²', 'É³', 'É´', 'É¶', 'É¼', 'É½', 'É¾', 'Ê€', 'Ê‚', 'Êˆ', 'Ê‰', 'Ê‹', 'Ê�', 'Ê�', 'Ê‘', 'Ê™', 'Ê›', 'Êœ', 'Ê�', 'ÊŸ', 'Ê ', 'Ê£', 'Ê¥', 'Ê¦', 'Êª', 'Ê«', 'á´€', 'á´�', 'á´ƒ', 'á´„', 'á´…', 'á´†', 'á´‡', 'á´Š', 'á´‹', 'á´Œ', 'á´�', 'á´�', 'á´˜', 'á´›', 'á´œ', 'á´ ', 'á´¡', 'á´¢', 'áµ«', 'áµ¬', 'áµ­', 'áµ®', 'áµ¯', 'áµ°', 'áµ±', 'áµ²', 'áµ³', 'áµ´', 'áµµ', 'áµ¶', 'áµº', 'áµ»', 'áµ½', 'áµ¾', 'á¶€', 'á¶�', 'á¶‚', 'á¶ƒ', 'á¶„', 'á¶…', 'á¶†', 'á¶‡', 'á¶ˆ', 'á¶‰', 'á¶Š', 'á¶Œ', 'á¶�', 'á¶Ž', 'á¶�', 'á¶‘', 'á¶’', 'á¶“', 'á¶–', 'á¶™', 'áºš', 'áºœ', 'áº�', 'áºž', 'á»º', 'á»»', 'á»¼', 'á»½', 'á»¾', 'á»¿', 'Â©', 'Â®', 'â‚ ', 'â‚¢', 'â‚£', 'â‚¤', 'â‚§', 'â‚º', 'â‚¹', 'â„Œ', 'â„ž', 'ãŽ§', 'ãŽ®', 'ã�†', 'ã�—', 'ã�ž', 'ã�Ÿ', 'Â¼', 'Â½', 'Â¾', 'â…“', 'â…”', 'â…•', 'â…–', 'â…—', 'â…˜', 'â…™', 'â…š', 'â…›', 'â…œ', 'â…�', 'â…ž', 'â…Ÿ', 'ã€‡', 'â€˜', 'â€™', 'â€š', 'â€›', 'â€œ', 'â€�', 'â€ž', 'â€Ÿ', 'â€²', 'â€³', 'ã€�', 'ã€ž', 'Â«', 'Â»', 'â€¹', 'â€º', 'â€�', 'â€‘', 'â€’', 'â€“', 'â€”', 'â€•', 'ï¸±', 'ï¸²', 'ï¹˜', 'â€–', 'â�„', 'â�…', 'â�†', 'â�Ž', 'ã€�', 'ã€‚', 'ã€ˆ', 'ã€‰', 'ã€Š', 'ã€‹', 'ã€”', 'ã€•', 'ã€˜', 'ã€™', 'ã€š', 'ã€›', 'ï¸‘', 'ï¸’', 'ï¸¹', 'ï¸º', 'ï¸½', 'ï¸¾', 'ï¸¿', 'ï¹€', 'ï¹‘', 'ï¹�', 'ï¹ž', 'ï½Ÿ', 'ï½ ', 'ï½¡', 'ï½¤', 'Ã—', 'Ã·', 'âˆ’', 'âˆ•', 'âˆ–', 'âˆ£', 'âˆ¥', 'â‰ª', 'â‰«', 'â¦…', 'â¦†'];
    private const TRANSLIT_TO = ['AE', 'D', 'O', 'TH', 'ss', 'ae', 'd', 'o', 'th', 'D', 'd', 'H', 'h', 'i', 'q', 'L', 'l', 'L', 'l', '\'n', 'N', 'n', 'OE', 'oe', 'T', 't', 'b', 'B', 'B', 'b', 'C', 'c', 'D', 'D', 'D', 'd', 'E', 'F', 'f', 'G', 'hv', 'I', 'I', 'K', 'k', 'l', 'N', 'n', 'OI', 'oi', 'P', 'p', 't', 'T', 't', 'T', 'V', 'Y', 'y', 'Z', 'z', 'DZ', 'Dz', 'dz', 'G', 'g', 'd', 'Z', 'z', 'l', 'n', 't', 'j', 'db', 'qp', 'A', 'C', 'c', 'L', 'T', 's', 'z', 'B', 'U', 'E', 'e', 'J', 'j', 'R', 'r', 'Y', 'y', 'b', 'c', 'd', 'd', 'e', 'j', 'g', 'g', 'G', 'h', 'h', 'i', 'I', 'l', 'l', 'l', 'm', 'n', 'n', 'N', 'OE', 'r', 'r', 'r', 'R', 's', 't', 'u', 'v', 'Y', 'z', 'z', 'B', 'G', 'H', 'j', 'L', 'q', 'dz', 'dz', 'ts', 'ls', 'lz', 'A', 'AE', 'B', 'C', 'D', 'D', 'E', 'J', 'K', 'L', 'M', 'O', 'P', 'T', 'U', 'V', 'W', 'Z', 'ue', 'b', 'd', 'f', 'm', 'n', 'p', 'r', 'r', 's', 't', 'z', 'th', 'I', 'p', 'U', 'b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 'v', 'x', 'z', 'a', 'd', 'e', 'e', 'i', 'u', 'a', 's', 's', 'SS', 'LL', 'll', 'V', 'v', 'Y', 'y', '(C)', '(R)', 'CE', 'Cr', 'Fr.', 'L.', 'Pts', 'TL', 'Rs', 'x', 'Rx', 'm/s', 'rad/s', 'C/kg', 'pH', 'V/m', 'A/m', ' 1/4', ' 1/2', ' 3/4', ' 1/3', ' 2/3', ' 1/5', ' 2/5', ' 3/5', ' 4/5', ' 1/6', ' 5/6', ' 1/8', ' 3/8', ' 5/8', ' 7/8', ' 1/', '0', '\'', '\'', ',', '\'', '"', '"', ',,', '"', '\'', '"', '"', '"', '<<', '>>', '<', '>', '-', '-', '-', '-', '-', '-', '-', '-', '-', '||', '/', '[', ']', '*', ',', '.', '<', '>', '<<', '>>', '[', ']', '[', ']', '[', ']', ',', '.', '[', ']', '<<', '>>', '<', '>', ',', '[', ']', '((', '))', '.', ',', '*', '/', '-', '/', '\\', '|', '||', '<<', '>>', '((', '))'];
    private static $transliterators = [];
    /**
     * @return static
     */
    public static function fromCodePoints(int ...$codes)
    {
        $string = '';
        foreach ($codes as $code) {
            if (0x80 > ($code %= 0x200000)) {
                $string .= \chr($code);
            } elseif (0x800 > $code) {
                $string .= \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
            } elseif (0x10000 > $code) {
                $string .= \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
            } else {
                $string .= \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
            }
        }
        $phabelReturn = new static($string);
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * Generic UTF-8 to ASCII transliteration.
     *
     * Install the intl extension for best results.
     *
     * @param (string[] | \Transliterator[] | \Closure[]) $rules See "*-Latin" rules from Transliterator::listIDs()
     */
    public function ascii(array $rules = []) : self
    {
        $str = clone $this;
        $s = $str->string;
        $str->string = '';
        \array_unshift($rules, 'nfd');
        $rules[] = 'latin-ascii';
        if (\function_exists('transliterator_transliterate')) {
            $rules[] = 'any-latin/bgn';
        }
        $rules[] = 'nfkd';
        $rules[] = '[:nonspacing mark:] remove';
        while (\strlen($s) - 1 > ($i = \Phabel\Target\Php80\Polyfill::strspn($s, self::ASCII))) {
            if (0 < --$i) {
                $str->string .= \Phabel\Target\Php80\Polyfill::substr($s, 0, $i);
                $s = \Phabel\Target\Php80\Polyfill::substr($s, $i);
            }
            if (!($rule = \array_shift($rules))) {
                $rules = [];
                // An empty rule interrupts the next ones
            }
            if ($rule instanceof \Transliterator) {
                $s = $rule->transliterate($s);
            } elseif ($rule instanceof \Closure) {
                $s = $rule($s);
            } elseif ($rule) {
                if ('nfd' === ($rule = \strtolower($rule))) {
                    \normalizer_is_normalized($s, self::NFD) ?: ($s = \normalizer_normalize($s, self::NFD));
                } elseif ('nfkd' === $rule) {
                    \normalizer_is_normalized($s, self::NFKD) ?: ($s = \normalizer_normalize($s, self::NFKD));
                } elseif ('[:nonspacing mark:] remove' === $rule) {
                    $s = \preg_replace('/\\p{Mn}++/u', '', $s);
                } elseif ('latin-ascii' === $rule) {
                    $s = \str_replace(self::TRANSLIT_FROM, self::TRANSLIT_TO, $s);
                } elseif ('de-ascii' === $rule) {
                    $s = \preg_replace("/([AUO])Ìˆ(?=\\p{Ll})/u", '$1e', $s);
                    $s = \str_replace(["aÌˆ", "oÌˆ", "uÌˆ", "AÌˆ", "OÌˆ", "UÌˆ"], ['ae', 'oe', 'ue', 'AE', 'OE', 'UE'], $s);
                } elseif (\function_exists('transliterator_transliterate')) {
                    if (null === ($transliterator = self::$transliterators[$rule] ?? (self::$transliterators[$rule] = \Transliterator::create($rule)))) {
                        if ('any-latin/bgn' === $rule) {
                            $rule = 'any-latin';
                            $transliterator = self::$transliterators[$rule] ?? (self::$transliterators[$rule] = \Transliterator::create($rule));
                        }
                        if (null === $transliterator) {
                            throw new InvalidArgumentException(\sprintf('Unknown transliteration rule "%s".', $rule));
                        }
                        self::$transliterators['any-latin/bgn'] = $transliterator;
                    }
                    $s = $transliterator->transliterate($s);
                }
            } elseif (!\function_exists('iconv')) {
                $s = \preg_replace('/[^\\x00-\\x7F]/u', '?', $s);
            } else {
                $s = @\preg_replace_callback('/[^\\x00-\\x7F]/u', static function ($c) {
                    $c = (string) \iconv('UTF-8', 'ASCII//TRANSLIT', $c[0]);
                    if ('' === $c && '' === \iconv('UTF-8', 'ASCII//TRANSLIT', 'Â²')) {
                        throw new \LogicException(\sprintf('"%s" requires a translit-able iconv implementation, try installing "gnu-libiconv" if you\'re using Alpine Linux.', static::class));
                    }
                    return 1 < \strlen($c) ? \ltrim($c, '\'`"^~') : ('' !== $c ? $c : '?');
                }, $s);
            }
        }
        $str->string .= $s;
        return $str;
    }
    /**
     * @return static
     */
    public function camel()
    {
        $str = clone $this;
        $str->string = \str_replace(' ', '', \preg_replace_callback('/\\b./u', static function ($m) use(&$i) {
            return 1 === ++$i ? 'Ä°' === $m[0] ? 'iÌ‡' : \mb_strtolower($m[0], 'UTF-8') : \mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
        }, \preg_replace('/[^\\pL0-9]++/u', ' ', $this->string)));
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return int[]
     */
    public function codePointsAt(int $offset) : array
    {
        $str = $this->slice($offset, 1);
        if ('' === $str->string) {
            return [];
        }
        $codePoints = [];
        foreach (\preg_split('//u', $str->string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
            $codePoints[] = \mb_ord($c, 'UTF-8');
        }
        return $codePoints;
    }
    /**
     * @return static
     */
    public function folded(bool $compat = \true)
    {
        $str = clone $this;
        if (!$compat || !\defined('Normalizer::NFKC_CF')) {
            $str->string = \normalizer_normalize($str->string, $compat ? \Normalizer::NFKC : \Normalizer::NFC);
            $str->string = \mb_strtolower(\str_replace(self::FOLD_FROM, self::FOLD_TO, $this->string), 'UTF-8');
        } else {
            $str->string = \normalizer_normalize($str->string, \Normalizer::NFKC_CF);
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function join(array $strings, string $lastGlue = null)
    {
        $str = clone $this;
        $tail = null !== $lastGlue && 1 < \count($strings) ? $lastGlue . \array_pop($strings) : '';
        $str->string = \implode($this->string, $strings) . $tail;
        if (!\preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function lower()
    {
        $str = clone $this;
        $str->string = \mb_strtolower(\str_replace('Ä°', 'iÌ‡', $str->string), 'UTF-8');
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function match(string $regexp, int $flags = 0, int $offset = 0) : array
    {
        $match = (\PREG_PATTERN_ORDER | \PREG_SET_ORDER) & $flags ? 'preg_match_all' : 'preg_match';
        if ($this->ignoreCase) {
            $regexp .= 'i';
        }
        \set_error_handler(static function ($t, $m) {
            throw new InvalidArgumentException($m);
        });
        try {
            if (\false === $match($regexp . 'u', $this->string, $matches, $flags | 0, $offset)) {
                $lastError = \preg_last_error();
                foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
                    if ($lastError === $v && '_ERROR' === \Phabel\Target\Php80\Polyfill::substr($k, -6)) {
                        throw new RuntimeException('Matching failed with ' . $k . '.');
                    }
                }
                throw new RuntimeException('Matching failed with unknown error code.');
            }
        } finally {
            \restore_error_handler();
        }
        array_walk_recursive($match, function (&$v){return $v === "" ? null : $v;}); return $matches;
    }
    /**
     * @return static
     */
    public function normalize(int $form = self::NFC)
    {
        if (!\in_array($form, [self::NFC, self::NFD, self::NFKC, self::NFKD])) {
            throw new InvalidArgumentException('Unsupported normalization form.');
        }
        $str = clone $this;
        \normalizer_is_normalized($str->string, $form) ?: ($str->string = \normalizer_normalize($str->string, $form));
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function padBoth(int $length, string $padStr = ' ')
    {
        if ('' === $padStr || !\preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $pad = clone $this;
        $pad->string = $padStr;
        $phabelReturn = $this->pad($length, $pad, \STR_PAD_BOTH);
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function padEnd(int $length, string $padStr = ' ')
    {
        if ('' === $padStr || !\preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $pad = clone $this;
        $pad->string = $padStr;
        $phabelReturn = $this->pad($length, $pad, \STR_PAD_RIGHT);
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function padStart(int $length, string $padStr = ' ')
    {
        if ('' === $padStr || !\preg_match('//u', $padStr)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $pad = clone $this;
        $pad->string = $padStr;
        $phabelReturn = $this->pad($length, $pad, \STR_PAD_LEFT);
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | callable) $to
     * @return static
     */
    public function replaceMatches(string $fromRegexp, $to)
    {
        if (!\is_callable($to)) {
            if (!\is_string($to)) {
                if (!(\is_string($to) || \is_object($to) && \method_exists($to, '__toString') || (\is_bool($to) || \is_numeric($to)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #2 ($to) must be of type callable|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($to) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $to = (string) $to;
                }
            }
        }
        if ($this->ignoreCase) {
            $fromRegexp .= 'i';
        }
        if (\is_array($to) || $to instanceof \Closure) {
            $replace = 'preg_replace_callback';
            $to = static function (array $m) use($to) : string {
                $to = $to($m);
                if ('' !== $to && (!\is_string($to) || !\preg_match('//u', $to))) {
                    throw new InvalidArgumentException('Replace callback must return a valid UTF-8 string.');
                }
                return $to;
            };
        } elseif ('' !== $to && !\preg_match('//u', $to)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        } else {
            $replace = 'preg_replace';
        }
        \set_error_handler(static function ($t, $m) {
            throw new InvalidArgumentException($m);
        });
        try {
            if (null === ($string = $replace($fromRegexp . 'u', $to, $this->string))) {
                $lastError = \preg_last_error();
                foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
                    if ($lastError === $v && '_ERROR' === \Phabel\Target\Php80\Polyfill::substr($k, -6)) {
                        throw new RuntimeException('Matching failed with ' . $k . '.');
                    }
                }
                throw new RuntimeException('Matching failed with unknown error code.');
            }
        } finally {
            \restore_error_handler();
        }
        $str = clone $this;
        $str->string = $string;
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function reverse()
    {
        $str = clone $this;
        $str->string = \implode('', \array_reverse(\preg_split('/(\\X)/u', $str->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY)));
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function snake()
    {
        $str = $this->camel()->title();
        $str->string = \mb_strtolower(\preg_replace(['/(\\p{Lu}+)(\\p{Lu}\\p{Ll})/u', '/([\\p{Ll}0-9])(\\p{Lu})/u'], 'PhabelVendor\\1_\\2', $str->string), 'UTF-8');
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function title(bool $allWords = \false)
    {
        $str = clone $this;
        $limit = $allWords ? -1 : 1;
        $str->string = \preg_replace_callback('/\\b./u', static function (array $m) : string {
            return \mb_convert_case($m[0], \MB_CASE_TITLE, 'UTF-8');
        }, $str->string, $limit);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function trim(string $chars = " \t\n\r\x00\v\fÂ ï»¿")
    {
        if (" \t\n\r\x00\v\fÂ ï»¿" !== $chars && !\preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = \preg_quote($chars);
        $str = clone $this;
        $str->string = \preg_replace("{^[{$chars}]++|[{$chars}]++\$}uD", '', $str->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function trimEnd(string $chars = " \t\n\r\x00\v\fÂ ï»¿")
    {
        if (" \t\n\r\x00\v\fÂ ï»¿" !== $chars && !\preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = \preg_quote($chars);
        $str = clone $this;
        $str->string = \preg_replace("{[{$chars}]++\$}uD", '', $str->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function trimPrefix($prefix)
    {
        if (!$this->ignoreCase) {
            $phabelReturn = parent::trimPrefix($prefix);
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $str = clone $this;
        if ($prefix instanceof \Traversable) {
            $prefix = \iterator_to_array($prefix, \false);
        } elseif ($prefix instanceof parent) {
            $prefix = $prefix->string;
        }
        $prefix = \implode('|', \array_map('preg_quote', (array) $prefix));
        $str->string = \preg_replace("{^(?:{$prefix})}iuD", '', $this->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function trimStart(string $chars = " \t\n\r\x00\v\fÂ ï»¿")
    {
        if (" \t\n\r\x00\v\fÂ ï»¿" !== $chars && !\preg_match('//u', $chars)) {
            throw new InvalidArgumentException('Invalid UTF-8 chars.');
        }
        $chars = \preg_quote($chars);
        $str = clone $this;
        $str->string = \preg_replace("{^[{$chars}]++}uD", '', $str->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function trimSuffix($suffix)
    {
        if (!$this->ignoreCase) {
            $phabelReturn = parent::trimSuffix($suffix);
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $str = clone $this;
        if ($suffix instanceof \Traversable) {
            $suffix = \iterator_to_array($suffix, \false);
        } elseif ($suffix instanceof parent) {
            $suffix = $suffix->string;
        }
        $suffix = \implode('|', \array_map('preg_quote', (array) $suffix));
        $str->string = \preg_replace("{(?:{$suffix})\$}iuD", '', $this->string);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function upper()
    {
        $str = clone $this;
        $str->string = \mb_strtoupper($str->string, 'UTF-8');
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function width(bool $ignoreAnsiDecoration = \true) : int
    {
        $width = 0;
        $s = \str_replace(["\x00", "\x05", "\x07"], '', $this->string);
        if (\false !== \strpos($s, "\r")) {
            $s = \str_replace(["\r\n", "\r"], "\n", $s);
        }
        if (!$ignoreAnsiDecoration) {
            $s = \preg_replace('/[\\p{Cc}\\x7F]++/u', '', $s);
        }
        foreach (\explode("\n", $s) as $s) {
            if ($ignoreAnsiDecoration) {
                $s = \preg_replace('/(?:\\x1B(?:
                    \\[ [\\x30-\\x3F]*+ [\\x20-\\x2F]*+ [0x40-\\x7E]
                    | [P\\]X^_] .*? \\x1B\\\\
                    | [\\x41-\\x7E]
                )|[\\p{Cc}\\x7F]++)/xu', '', $s);
            }
            // Non printable characters have been dropped, so wcswidth cannot logically return -1.
            $width += $this->wcswidth($s);
        }
        return $width;
    }
    /**
     * @return static
     */
    private function pad(int $len, self $pad, int $type)
    {
        $sLen = $this->length();
        if ($len <= $sLen) {
            $phabelReturn = clone $this;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $padLen = $pad->length();
        $freeLen = $len - $sLen;
        $len = $freeLen % $padLen;
        switch ($type) {
            case \STR_PAD_RIGHT:
                $phabelReturn = $this->append(\str_repeat($pad->string, \intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
                if (!$phabelReturn instanceof static) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                return $phabelReturn;
            case \STR_PAD_LEFT:
                $phabelReturn = $this->prepend(\str_repeat($pad->string, \intdiv($freeLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
                if (!$phabelReturn instanceof static) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                return $phabelReturn;
            case \STR_PAD_BOTH:
                $freeLen /= 2;
                $rightLen = \ceil($freeLen);
                $len = $rightLen % $padLen;
                $str = $this->append(\str_repeat($pad->string, \intdiv($rightLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
                $leftLen = \floor($freeLen);
                $len = $leftLen % $padLen;
                $phabelReturn = $str->prepend(\str_repeat($pad->string, \intdiv($leftLen, $padLen)) . ($len ? $pad->slice(0, $len) : ''));
                if (!$phabelReturn instanceof static) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                return $phabelReturn;
            default:
                throw new InvalidArgumentException('Invalid padding type.');
        }
        throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', none returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
    }
    /**
     * Based on https://github.com/jquast/wcwidth, a Python implementation of https://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c.
     */
    private function wcswidth(string $string) : int
    {
        $width = 0;
        foreach (\preg_split('//u', $string, -1, \PREG_SPLIT_NO_EMPTY) as $c) {
            $codePoint = \mb_ord($c, 'UTF-8');
            if (0 === $codePoint || 0x34f === $codePoint || 0x200b <= $codePoint && 0x200f >= $codePoint || 0x2028 === $codePoint || 0x2029 === $codePoint || 0x202a <= $codePoint && 0x202e >= $codePoint || 0x2060 <= $codePoint && 0x2063 >= $codePoint) {
                continue;
            }
            // Non printable characters
            if (32 > $codePoint || 0x7f <= $codePoint && 0xa0 > $codePoint) {
                return -1;
            }
            static $tableZero;
            if (null === $tableZero) {
                $tableZero = (require __DIR__ . '/Resources/data/wcswidth_table_zero.php');
            }
            if ($codePoint >= $tableZero[0][0] && $codePoint <= $tableZero[$ubound = \count($tableZero) - 1][1]) {
                $lbound = 0;
                while ($ubound >= $lbound) {
                    $mid = \floor(($lbound + $ubound) / 2);
                    if ($codePoint > $tableZero[$mid][1]) {
                        $lbound = $mid + 1;
                    } elseif ($codePoint < $tableZero[$mid][0]) {
                        $ubound = $mid - 1;
                    } else {
                        continue 2;
                    }
                }
            }
            static $tableWide;
            if (null === $tableWide) {
                $tableWide = (require __DIR__ . '/Resources/data/wcswidth_table_wide.php');
            }
            if ($codePoint >= $tableWide[0][0] && $codePoint <= $tableWide[$ubound = \count($tableWide) - 1][1]) {
                $lbound = 0;
                while ($ubound >= $lbound) {
                    $mid = \floor(($lbound + $ubound) / 2);
                    if ($codePoint > $tableWide[$mid][1]) {
                        $lbound = $mid + 1;
                    } elseif ($codePoint < $tableWide[$mid][0]) {
                        $ubound = $mid - 1;
                    } else {
                        $width += 2;
                        continue 2;
                    }
                }
            }
            ++$width;
        }
        return $width;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String;

/**
 * A string whose value is computed lazily by a callback.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 */
class LazyString implements \Stringable, \JsonSerializable
{
    /**
     * @var (\Closure | string) $value
     */
    private $value;
    /**
     * @param (callable | array) $callback A callable or a [Closure, method] lazy-callable
     * @param mixed ...$arguments
     * @return static
     */
    public static function fromCallable($callback, ...$arguments)
    {
        if (!(\is_callable($callback) || \is_array($callback))) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($callback) must be of type callable|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($callback) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        foreach ($arguments as $phabelVariadicIndex => $phabelVariadic) {
            if (!\true) {
                throw new \TypeError(__METHOD__ . '(): Argument #' . (2 + $phabelVariadicIndex) . ' must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($arguments) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
        }
        if (\is_array($callback) && !\is_callable($callback) && !(($callback[0] ?? null) instanceof \Closure || 2 < \count($callback))) {
            throw new \TypeError(\sprintf('Argument 1 passed to "%s()" must be a callable or a [Closure, method] lazy-callable, "%s" given.', __METHOD__, '[' . \implode(', ', \array_map('get_debug_type', $callback)) . ']'));
        }
        $lazyString = new static();
        $lazyString->value = static function () use(&$callback, &$arguments, &$value) : string {
            if (null !== $arguments) {
                if (!\is_callable($callback)) {
                    $callback[0] = $callback[0]();
                    $callback[1] = $callback[1] ?? '__invoke';
                }
                $value = $callback(...$arguments);
                $callback = self::getPrettyName($callback);
                $arguments = null;
            }
            return $value ?? '';
        };
        $phabelReturn = $lazyString;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | int | float | bool | \Stringable) $value
     * @return static
     */
    public static function fromStringable($value)
    {
        if (!$value instanceof \Stringable) {
            if (!\is_bool($value)) {
                if (!(\is_bool($value) || \is_numeric($value) || \is_string($value))) {
                    if (!\is_float($value)) {
                        if (!(\is_bool($value) || \is_numeric($value))) {
                            if (!\is_int($value)) {
                                if (!(\is_bool($value) || \is_numeric($value))) {
                                    if (!\is_string($value)) {
                                        if (!(\is_string($value) || \is_object($value) && \method_exists($value, '__toString') || (\is_bool($value) || \is_numeric($value)))) {
                                            throw new \TypeError(__METHOD__ . '(): Argument #1 ($value) must be of type Stringable|string|int|float|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                                        } else {
                                            $value = (string) $value;
                                        }
                                    }
                                } else {
                                    $value = (int) $value;
                                }
                            }
                        } else {
                            $value = (double) $value;
                        }
                    }
                } else {
                    $value = (bool) $value;
                }
            }
        }
        if (\is_object($value)) {
            $phabelReturn = static::fromCallable([$value, '__toString']);
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $lazyString = new static();
        $lazyString->value = (string) $value;
        $phabelReturn = $lazyString;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * Tells whether the provided value can be cast to string.
     * @param mixed $value
     */
    public static final function isStringable($value) : bool
    {
        if (!\true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($value) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return \is_string($value) || $value instanceof \Stringable || \is_scalar($value);
    }
    /**
     * Casts scalars and stringable objects to strings.
     *
     * @throws \TypeError When the provided value is not stringable
     * @param (\Stringable | string | int | float | bool) $value
     */
    public static final function resolve($value) : string
    {
        if (!\is_bool($value)) {
            if (!(\is_bool($value) || \is_numeric($value) || \is_string($value))) {
                if (!\is_float($value)) {
                    if (!(\is_bool($value) || \is_numeric($value))) {
                        if (!\is_int($value)) {
                            if (!(\is_bool($value) || \is_numeric($value))) {
                                if (!\is_string($value)) {
                                    if (!(\is_string($value) || \is_object($value) && \method_exists($value, '__toString') || (\is_bool($value) || \is_numeric($value)))) {
                                        if (!$value instanceof \Stringable) {
                                            throw new \TypeError(__METHOD__ . '(): Argument #1 ($value) must be of type Stringable|string|int|float|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                                        }
                                    } else {
                                        $value = (string) $value;
                                    }
                                }
                            } else {
                                $value = (int) $value;
                            }
                        }
                    } else {
                        $value = (double) $value;
                    }
                }
            } else {
                $value = (bool) $value;
            }
        }
        return $value;
    }
    /**
     *
     */
    public function __toString() : string
    {
        if (\is_string($this->value)) {
            return $this->value;
        }
        try {
            return $this->value = ($this->value)();
        } catch (\Throwable $e) {
            if (\TypeError::class === \get_class($e) && __FILE__ === $e->getFile()) {
                $type = \explode(', ', $e->getMessage());
                $type = \Phabel\Target\Php80\Polyfill::substr(\array_pop($type), 0, -\strlen(' returned'));
                $r = new \ReflectionFunction($this->value);
                $callback = $r->getStaticVariables()['callback'];
                $e = new \TypeError(\sprintf('Return value of %s() passed to %s::fromCallable() must be of the type string, %s returned.', $callback, static::class, $type));
            }
            throw $e;
        }
    }
    /**
     *
     */
    public function __sleep() : array
    {
        $this->__toString();
        return ['value'];
    }
    /**
     *
     */
    public function jsonSerialize() : string
    {
        return $this->__toString();
    }
    /**
     *
     */
    private function __construct()
    {
    }
    /**
     *
     */
    private static function getPrettyName(callable $callback) : string
    {
        if (\is_string($callback)) {
            return $callback;
        }
        if (\is_array($callback)) {
            $class = \is_object($callback[0]) ? \get_debug_type($callback[0]) : $callback[0];
            $method = $callback[1];
        } elseif ($callback instanceof \Closure) {
            $r = new \ReflectionFunction($callback);
            if (\false !== \strpos($r->name, '{closure}') || !($class = $r->getClosureScopeClass())) {
                return $r->name;
            }
            $class = $class->name;
            $method = $r->name;
        } else {
            $class = \get_debug_type($callback);
            $method = '__invoke';
        }
        return $class . '::' . $method;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String\Exception;

class RuntimeException extends \RuntimeException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String\Exception;

class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String\Exception;

interface ExceptionInterface extends \Throwable
{
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String;

use PhabelVendor\Symfony\Component\String\Exception\ExceptionInterface;
use PhabelVendor\Symfony\Component\String\Exception\InvalidArgumentException;
/**
 * Represents a string of Unicode code points encoded as UTF-8.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class CodePointString extends AbstractUnicodeString
{
    /**
     *
     */
    public function __construct(string $string = '')
    {
        if ('' !== $string && !\preg_match('//u', $string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $this->string = $string;
    }
    /**
     * @return static
     */
    public function append(string ...$suffix)
    {
        $str = clone $this;
        $str->string .= 1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix);
        if (!\preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function chunk(int $length = 1) : array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }
        if ('' === $this->string) {
            return [];
        }
        $rx = '/(';
        while (65535 < $length) {
            $rx .= '.{65535}';
            $length -= 65535;
        }
        $rx .= '.{' . $length . '})/us';
        $str = clone $this;
        $chunks = [];
        foreach (\preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }
        return $chunks;
    }
    /**
     *
     */
    public function codePointsAt(int $offset) : array
    {
        $str = $offset ? $this->slice($offset, 1) : $this;
        return '' === $str->string ? [] : [\mb_ord($str->string, 'UTF-8')];
    }
    /**
     * @param (string | iterable | AbstractString) $suffix
     */
    public function endsWith($suffix) : bool
    {
        if (!(\is_array($suffix) || $suffix instanceof \Traversable || $suffix instanceof AbstractString)) {
            if (!\is_string($suffix)) {
                if (!(\is_string($suffix) || \is_object($suffix) && \method_exists($suffix, '__toString') || (\is_bool($suffix) || \is_numeric($suffix)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($suffix) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($suffix) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $suffix = (string) $suffix;
                }
            }
        }
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }
        if ('' === $suffix || !\preg_match('//u', $suffix)) {
            return \false;
        }
        if ($this->ignoreCase) {
            return \preg_match('{' . \preg_quote($suffix) . '$}iuD', $this->string);
        }
        return \strlen($this->string) >= \strlen($suffix) && 0 === \Phabel\Target\Php80\Polyfill::substr_compare($this->string, $suffix, -\strlen($suffix));
    }
    /**
     * @param (string | iterable | AbstractString) $string
     */
    public function equalsTo($string) : bool
    {
        if (!(\is_array($string) || $string instanceof \Traversable || $string instanceof AbstractString)) {
            if (!\is_string($string)) {
                if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $string = (string) $string;
                }
            }
        }
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }
        if ('' !== $string && $this->ignoreCase) {
            return \strlen($string) === \strlen($this->string) && 0 === \mb_stripos($this->string, $string, 0, 'UTF-8');
        }
        return $string === $this->string;
    }
    /**
     * @param (string | iterable | AbstractString) $needle
     */
    public function indexOf($needle, int $offset = 0) : ?int
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable || $needle instanceof AbstractString)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }
        if ('' === $needle) {
            return null;
        }
        $i = $this->ignoreCase ? \mb_stripos($this->string, $needle, $offset, 'UTF-8') : \mb_strpos($this->string, $needle, $offset, 'UTF-8');
        return \false === $i ? null : $i;
    }
    /**
     * @param (string | iterable | AbstractString) $needle
     */
    public function indexOfLast($needle, int $offset = 0) : ?int
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable || $needle instanceof AbstractString)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }
        if ('' === $needle) {
            return null;
        }
        $i = $this->ignoreCase ? \mb_strripos($this->string, $needle, $offset, 'UTF-8') : \mb_strrpos($this->string, $needle, $offset, 'UTF-8');
        return \false === $i ? null : $i;
    }
    /**
     *
     */
    public function length() : int
    {
        return \mb_strlen($this->string, 'UTF-8');
    }
    /**
     * @return static
     */
    public function prepend(string ...$prefix)
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $this->string;
        if (!\preg_match('//u', $str->string)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function replace(string $from, string $to)
    {
        $str = clone $this;
        if ('' === $from || !\preg_match('//u', $from)) {
            $phabelReturn = $str;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        if ('' !== $to && !\preg_match('//u', $to)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        if ($this->ignoreCase) {
            $str->string = \implode($to, \preg_split('{' . \preg_quote($from) . '}iuD', $this->string));
        } else {
            $str->string = \str_replace($from, $to, $this->string);
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function slice(int $start = 0, int $length = null)
    {
        $str = clone $this;
        $str->string = \mb_substr($this->string, $start, $length, 'UTF-8');
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function splice(string $replacement, int $start = 0, int $length = null)
    {
        if (!\preg_match('//u', $replacement)) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $str = clone $this;
        $start = $start ? \strlen(\mb_substr($this->string, 0, $start, 'UTF-8')) : 0;
        $length = $length ? \strlen(\mb_substr($this->string, $start, $length, 'UTF-8')) : $length;
        $str->string = \Phabel\Target\Php80\Polyfill::substr_replace($this->string, $replacement, $start, $length ?? \PHP_INT_MAX);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function split(string $delimiter, int $limit = null, int $flags = null) : array
    {
        if (1 > ($limit = $limit ?? \PHP_INT_MAX)) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }
        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }
        if (null !== $flags) {
            return parent::split($delimiter . 'u', $limit, $flags);
        }
        if (!\preg_match('//u', $delimiter)) {
            throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
        }
        $str = clone $this;
        $chunks = $this->ignoreCase ? \preg_split('{' . \preg_quote($delimiter) . '}iuD', $this->string, $limit) : \explode($delimiter, $this->string, $limit);
        foreach ($chunks as &$chunk) {
            $str->string = $chunk;
            $chunk = clone $str;
        }
        return $chunks;
    }
    /**
     * @param (string | iterable | AbstractString) $prefix
     */
    public function startsWith($prefix) : bool
    {
        if (!(\is_array($prefix) || $prefix instanceof \Traversable || $prefix instanceof AbstractString)) {
            if (!\is_string($prefix)) {
                if (!(\is_string($prefix) || \is_object($prefix) && \method_exists($prefix, '__toString') || (\is_bool($prefix) || \is_numeric($prefix)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($prefix) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($prefix) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $prefix = (string) $prefix;
                }
            }
        }
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }
        if ('' === $prefix || !\preg_match('//u', $prefix)) {
            return \false;
        }
        if ($this->ignoreCase) {
            return 0 === \mb_stripos($this->string, $prefix, 0, 'UTF-8');
        }
        return 0 === \strncmp($this->string, $prefix, \strlen($prefix));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String;

use PhabelVendor\Symfony\Component\String\Exception\ExceptionInterface;
use PhabelVendor\Symfony\Component\String\Exception\InvalidArgumentException;
use PhabelVendor\Symfony\Component\String\Exception\RuntimeException;
/**
 * Represents a string of abstract characters.
 *
 * Unicode defines 3 types of "characters" (bytes, code points and grapheme clusters).
 * This class is the abstract type to use as a type-hint when the logic you want to
 * implement doesn't care about the exact variant it deals with.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
abstract class AbstractString implements \Stringable, \JsonSerializable
{
    public const PREG_PATTERN_ORDER = \PREG_PATTERN_ORDER;
    public const PREG_SET_ORDER = \PREG_SET_ORDER;
    public const PREG_OFFSET_CAPTURE = \PREG_OFFSET_CAPTURE;
    public const PREG_UNMATCHED_AS_NULL = 0;
    public const PREG_SPLIT = 0;
    public const PREG_SPLIT_NO_EMPTY = \PREG_SPLIT_NO_EMPTY;
    public const PREG_SPLIT_DELIM_CAPTURE = \PREG_SPLIT_DELIM_CAPTURE;
    public const PREG_SPLIT_OFFSET_CAPTURE = \PREG_SPLIT_OFFSET_CAPTURE;
    protected $string = '';
    protected $ignoreCase = \false;
    /**
     *
     */
    public abstract function __construct(string $string = '');
    /**
     * Unwraps instances of AbstractString back to strings.
     *
     * @return (string[] | array)
     */
    public static function unwrap(array $values) : array
    {
        foreach ($values as $k => $v) {
            if ($v instanceof self) {
                $values[$k] = $v->__toString();
            } elseif (\is_array($v) && $values[$k] !== ($v = static::unwrap($v))) {
                $values[$k] = $v;
            }
        }
        return $values;
    }
    /**
     * Wraps (and normalizes) strings in instances of AbstractString.
     *
     * @return (static[] | array)
     */
    public static function wrap(array $values) : array
    {
        $i = 0;
        $keys = null;
        foreach ($values as $k => $v) {
            if (\is_string($k) && '' !== $k && $k !== ($j = (string) new static($k))) {
                $keys = $keys ?? \array_keys($values);
                $keys[$i] = $j;
            }
            if (\is_string($v)) {
                $values[$k] = new static($v);
            } elseif (\is_array($v) && $values[$k] !== ($v = static::wrap($v))) {
                $values[$k] = $v;
            }
            ++$i;
        }
        return null !== $keys ? \array_combine($keys, $values) : $values;
    }
    /**
     * @param (string | string[]) $needle
     * @return static
     */
    public function after($needle, bool $includeNeedle = \false, int $offset = 0)
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        $str = clone $this;
        $i = \PHP_INT_MAX;
        if (\is_string($needle)) {
            $needle = [$needle];
        }
        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOf($n, $offset);
            if (null !== $j && $j < $i) {
                $i = $j;
                $str->string = $n;
            }
        }
        if (\PHP_INT_MAX === $i) {
            $phabelReturn = $str;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        if (!$includeNeedle) {
            $i += $str->length();
        }
        $phabelReturn = $this->slice($i);
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | string[]) $needle
     * @return static
     */
    public function afterLast($needle, bool $includeNeedle = \false, int $offset = 0)
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        $str = clone $this;
        $i = null;
        if (\is_string($needle)) {
            $needle = [$needle];
        }
        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOfLast($n, $offset);
            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
                $str->string = $n;
            }
        }
        if (null === $i) {
            $phabelReturn = $str;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        if (!$includeNeedle) {
            $i += $str->length();
        }
        $phabelReturn = $this->slice($i);
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public abstract function append(string ...$suffix);
    /**
     * @param (string | string[]) $needle
     * @return static
     */
    public function before($needle, bool $includeNeedle = \false, int $offset = 0)
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        $str = clone $this;
        $i = \PHP_INT_MAX;
        if (\is_string($needle)) {
            $needle = [$needle];
        }
        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOf($n, $offset);
            if (null !== $j && $j < $i) {
                $i = $j;
                $str->string = $n;
            }
        }
        if (\PHP_INT_MAX === $i) {
            $phabelReturn = $str;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        if ($includeNeedle) {
            $i += $str->length();
        }
        $phabelReturn = $this->slice(0, $i);
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | string[]) $needle
     * @return static
     */
    public function beforeLast($needle, bool $includeNeedle = \false, int $offset = 0)
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        $str = clone $this;
        $i = null;
        if (\is_string($needle)) {
            $needle = [$needle];
        }
        foreach ($needle as $n) {
            $n = (string) $n;
            $j = $this->indexOfLast($n, $offset);
            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
                $str->string = $n;
            }
        }
        if (null === $i) {
            $phabelReturn = $str;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        if ($includeNeedle) {
            $i += $str->length();
        }
        $phabelReturn = $this->slice(0, $i);
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return int[]
     */
    public function bytesAt(int $offset) : array
    {
        $str = $this->slice($offset, 1);
        return '' === $str->string ? [] : \array_values(\unpack('C*', $str->string));
    }
    /**
     * @return static
     */
    public abstract function camel();
    /**
     * @return static[]
     */
    public abstract function chunk(int $length = 1) : array;
    /**
     * @return static
     */
    public function collapseWhitespace()
    {
        $str = clone $this;
        $str->string = \trim(\preg_replace('/(?:\\s{2,}+|[^\\S ])/', ' ', $str->string));
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | string[]) $needle
     */
    public function containsAny($needle) : bool
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        return null !== $this->indexOf($needle);
    }
    /**
     * @param (string | string[]) $suffix
     */
    public function endsWith($suffix) : bool
    {
        if (!(\is_array($suffix) || $suffix instanceof \Traversable)) {
            if (!\is_string($suffix)) {
                if (!(\is_string($suffix) || \is_object($suffix) && \method_exists($suffix, '__toString') || (\is_bool($suffix) || \is_numeric($suffix)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($suffix) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($suffix) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $suffix = (string) $suffix;
                }
            }
        }
        if (\is_string($suffix)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        foreach ($suffix as $s) {
            if ($this->endsWith((string) $s)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @return static
     */
    public function ensureEnd(string $suffix)
    {
        if (!$this->endsWith($suffix)) {
            $phabelReturn = $this->append($suffix);
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $suffix = \preg_quote($suffix);
        $regex = '{(' . $suffix . ')(?:' . $suffix . ')++$}D';
        $phabelReturn = $this->replaceMatches($regex . ($this->ignoreCase ? 'i' : ''), '$1');
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function ensureStart(string $prefix)
    {
        $prefix = new static($prefix);
        if (!$this->startsWith($prefix)) {
            $phabelReturn = $this->prepend($prefix);
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $str = clone $this;
        $i = $prefixLen = $prefix->length();
        while ($this->indexOf($prefix, $i) === $i) {
            $str = $str->slice($prefixLen);
            $i += $prefixLen;
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | string[]) $string
     */
    public function equalsTo($string) : bool
    {
        if (!(\is_array($string) || $string instanceof \Traversable)) {
            if (!\is_string($string)) {
                if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $string = (string) $string;
                }
            }
        }
        if (\is_string($string)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        foreach ($string as $s) {
            if ($this->equalsTo((string) $s)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @return static
     */
    public abstract function folded();
    /**
     * @return static
     */
    public function ignoreCase()
    {
        $str = clone $this;
        $str->ignoreCase = \true;
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | string[]) $needle
     */
    public function indexOf($needle, int $offset = 0) : ?int
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        if (\is_string($needle)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        $i = \PHP_INT_MAX;
        foreach ($needle as $n) {
            $j = $this->indexOf((string) $n, $offset);
            if (null !== $j && $j < $i) {
                $i = $j;
            }
        }
        return \PHP_INT_MAX === $i ? null : $i;
    }
    /**
     * @param (string | string[]) $needle
     */
    public function indexOfLast($needle, int $offset = 0) : ?int
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        if (\is_string($needle)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        $i = null;
        foreach ($needle as $n) {
            $j = $this->indexOfLast((string) $n, $offset);
            if (null !== $j && $j >= $i) {
                $i = $offset = $j;
            }
        }
        return $i;
    }
    /**
     *
     */
    public function isEmpty() : bool
    {
        return '' === $this->string;
    }
    /**
     * @return static
     */
    public abstract function join(array $strings, string $lastGlue = null);
    /**
     *
     */
    public function jsonSerialize() : string
    {
        return $this->string;
    }
    /**
     *
     */
    public abstract function length() : int;
    /**
     * @return static
     */
    public abstract function lower();
    /**
     * Matches the string using a regular expression.
     *
     * Pass PREG_PATTERN_ORDER or PREG_SET_ORDER as $flags to get all occurrences matching the regular expression.
     *
     * @return array All matches in a multi-dimensional array ordered according to flags
     */
    public abstract function match(string $regexp, int $flags = 0, int $offset = 0) : array;
    /**
     * @return static
     */
    public abstract function padBoth(int $length, string $padStr = ' ');
    /**
     * @return static
     */
    public abstract function padEnd(int $length, string $padStr = ' ');
    /**
     * @return static
     */
    public abstract function padStart(int $length, string $padStr = ' ');
    /**
     * @return static
     */
    public abstract function prepend(string ...$prefix);
    /**
     * @return static
     */
    public function repeat(int $multiplier)
    {
        if (0 > $multiplier) {
            throw new InvalidArgumentException(\sprintf('Multiplier must be positive, %d given.', $multiplier));
        }
        $str = clone $this;
        $str->string = \str_repeat($str->string, $multiplier);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public abstract function replace(string $from, string $to);
    /**
     * @param (string | callable) $to
     * @return static
     */
    public abstract function replaceMatches(string $fromRegexp, $to);
    /**
     * @return static
     */
    public abstract function reverse();
    /**
     * @return static
     */
    public abstract function slice(int $start = 0, int $length = null);
    /**
     * @return static
     */
    public abstract function snake();
    /**
     * @return static
     */
    public abstract function splice(string $replacement, int $start = 0, int $length = null);
    /**
     * @return static[]
     */
    public function split(string $delimiter, int $limit = null, int $flags = null) : array
    {
        if (null === $flags) {
            throw new \TypeError('Split behavior when $flags is null must be implemented by child classes.');
        }
        if ($this->ignoreCase) {
            $delimiter .= 'i';
        }
        \set_error_handler(static function ($t, $m) {
            throw new InvalidArgumentException($m);
        });
        try {
            if (\false === ($chunks = \preg_split($delimiter, $this->string, $limit, $flags))) {
                $lastError = \preg_last_error();
                foreach (\get_defined_constants(\true)['pcre'] as $k => $v) {
                    if ($lastError === $v && '_ERROR' === \Phabel\Target\Php80\Polyfill::substr($k, -6)) {
                        throw new RuntimeException('Splitting failed with ' . $k . '.');
                    }
                }
                throw new RuntimeException('Splitting failed with unknown error code.');
            }
        } finally {
            \restore_error_handler();
        }
        $str = clone $this;
        if (self::PREG_SPLIT_OFFSET_CAPTURE & $flags) {
            foreach ($chunks as &$chunk) {
                $str->string = $chunk[0];
                $chunk[0] = clone $str;
            }
        } else {
            foreach ($chunks as &$chunk) {
                $str->string = $chunk;
                $chunk = clone $str;
            }
        }
        return $chunks;
    }
    /**
     * @param (string | string[]) $prefix
     */
    public function startsWith($prefix) : bool
    {
        if (!(\is_array($prefix) || $prefix instanceof \Traversable)) {
            if (!\is_string($prefix)) {
                if (!(\is_string($prefix) || \is_object($prefix) && \method_exists($prefix, '__toString') || (\is_bool($prefix) || \is_numeric($prefix)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($prefix) must be of type string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($prefix) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $prefix = (string) $prefix;
                }
            }
        }
        if (\is_string($prefix)) {
            throw new \TypeError(\sprintf('Method "%s()" must be overridden by class "%s" to deal with non-iterable values.', __FUNCTION__, static::class));
        }
        foreach ($prefix as $prefix) {
            if ($this->startsWith((string) $prefix)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @return static
     */
    public abstract function title(bool $allWords = \false);
    /**
     *
     */
    public function toByteString(string $toEncoding = null) : ByteString
    {
        $b = new ByteString();
        $toEncoding = \in_array($toEncoding, ['utf8', 'utf-8', 'UTF8'], \true) ? 'UTF-8' : $toEncoding;
        if (null === $toEncoding || $toEncoding === ($fromEncoding = $this instanceof AbstractUnicodeString || \preg_match('//u', $b->string) ? 'UTF-8' : 'Windows-1252')) {
            $b->string = $this->string;
            return $b;
        }
        \set_error_handler(static function ($t, $m) {
            throw new InvalidArgumentException($m);
        });
        try {
            try {
                $b->string = \mb_convert_encoding($this->string, $toEncoding, 'UTF-8');
            } catch (InvalidArgumentException $e) {
                if (!\function_exists('iconv')) {
                    throw $e;
                }
                $b->string = \iconv('UTF-8', $toEncoding, $this->string);
            }
        } finally {
            \restore_error_handler();
        }
        return $b;
    }
    /**
     *
     */
    public function toCodePointString() : CodePointString
    {
        return new CodePointString($this->string);
    }
    /**
     *
     */
    public function toString() : string
    {
        return $this->string;
    }
    /**
     *
     */
    public function toUnicodeString() : UnicodeString
    {
        return new UnicodeString($this->string);
    }
    /**
     * @return static
     */
    public abstract function trim(string $chars = " \t\n\r\x00\v\fÂ ï»¿");
    /**
     * @return static
     */
    public abstract function trimEnd(string $chars = " \t\n\r\x00\v\fÂ ï»¿");
    /**
     * @param (string | string[]) $prefix
     * @return static
     */
    public function trimPrefix($prefix)
    {
        if (\is_array($prefix) || $prefix instanceof \Traversable) {
            foreach ($prefix as $s) {
                $t = $this->trimPrefix($s);
                if ($t->string !== $this->string) {
                    $phabelReturn = $t;
                    if (!$phabelReturn instanceof static) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    return $phabelReturn;
                }
            }
            $phabelReturn = clone $this;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $str = clone $this;
        if ($prefix instanceof self) {
            $prefix = $prefix->string;
        } else {
            $prefix = (string) $prefix;
        }
        if ('' !== $prefix && \strlen($this->string) >= \strlen($prefix) && 0 === \Phabel\Target\Php80\Polyfill::substr_compare($this->string, $prefix, 0, \strlen($prefix), $this->ignoreCase)) {
            $str->string = \Phabel\Target\Php80\Polyfill::substr($this->string, \strlen($prefix));
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public abstract function trimStart(string $chars = " \t\n\r\x00\v\fÂ ï»¿");
    /**
     * @param (string | string[]) $suffix
     * @return static
     */
    public function trimSuffix($suffix)
    {
        if (\is_array($suffix) || $suffix instanceof \Traversable) {
            foreach ($suffix as $s) {
                $t = $this->trimSuffix($s);
                if ($t->string !== $this->string) {
                    $phabelReturn = $t;
                    if (!$phabelReturn instanceof static) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    return $phabelReturn;
                }
            }
            $phabelReturn = clone $this;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $str = clone $this;
        if ($suffix instanceof self) {
            $suffix = $suffix->string;
        } else {
            $suffix = (string) $suffix;
        }
        if ('' !== $suffix && \strlen($this->string) >= \strlen($suffix) && 0 === \Phabel\Target\Php80\Polyfill::substr_compare($this->string, $suffix, -\strlen($suffix), null, $this->ignoreCase)) {
            $str->string = \Phabel\Target\Php80\Polyfill::substr($this->string, 0, -\strlen($suffix));
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function truncate(int $length, string $ellipsis = '', bool $cut = \true)
    {
        $stringLength = $this->length();
        if ($stringLength <= $length) {
            $phabelReturn = clone $this;
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $ellipsisLength = '' !== $ellipsis ? (new static($ellipsis))->length() : 0;
        if ($length < $ellipsisLength) {
            $ellipsisLength = 0;
        }
        if (!$cut) {
            if (null === ($length = $this->indexOf([' ', "\r", "\n", "\t"], ($length ?: 1) - 1))) {
                $phabelReturn = clone $this;
                if (!$phabelReturn instanceof static) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                return $phabelReturn;
            }
            $length += $ellipsisLength;
        }
        $str = $this->slice(0, $length - $ellipsisLength);
        $phabelReturn = $ellipsisLength ? $str->trimEnd()->append($ellipsis) : $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public abstract function upper();
    /**
     * Returns the printable length on a terminal.
     */
    public abstract function width(bool $ignoreAnsiDecoration = \true) : int;
    /**
     * @return static
     */
    public function wordwrap(int $width = 75, string $break = "\n", bool $cut = \false)
    {
        $lines = '' !== $break ? $this->split($break) : [clone $this];
        $chars = [];
        $mask = '';
        if (1 === \count($lines) && '' === $lines[0]->string) {
            $phabelReturn = $lines[0];
            if (!$phabelReturn instanceof static) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        foreach ($lines as $i => $line) {
            if ($i) {
                $chars[] = $break;
                $mask .= '#';
            }
            foreach ($line->chunk() as $char) {
                $chars[] = $char->string;
                $mask .= ' ' === $char->string ? ' ' : '?';
            }
        }
        $string = '';
        $j = 0;
        $b = $i = -1;
        $mask = \wordwrap($mask, $width, '#', $cut);
        while (\false !== ($b = \strpos($mask, '#', $b + 1))) {
            for (++$i; $i < $b; ++$i) {
                $string .= $chars[$j];
                unset($chars[$j++]);
            }
            if ($break === $chars[$j] || ' ' === $chars[$j]) {
                unset($chars[$j++]);
            }
            $string .= $break;
        }
        $str = clone $this;
        $str->string = $string . \implode('', $chars);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function __sleep() : array
    {
        return ['string'];
    }
    /**
     *
     */
    public function __clone()
    {
        $this->ignoreCase = \false;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->string;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String;

use PhabelVendor\Symfony\Component\String\Exception\ExceptionInterface;
use PhabelVendor\Symfony\Component\String\Exception\InvalidArgumentException;
/**
 * Represents a string of Unicode grapheme clusters encoded as UTF-8.
 *
 * A letter followed by combining characters (accents typically) form what Unicode defines
 * as a grapheme cluster: a character as humans mean it in written texts. This class knows
 * about the concept and won't split a letter apart from its combining accents. It also
 * ensures all string comparisons happen on their canonically-composed representation,
 * ignoring e.g. the order in which accents are listed when a letter has many of them.
 *
 * @see https://unicode.org/reports/tr15/
 *
 * @author Nicolas Grekas <p@tchwork.com>
 * @author Hugo Hamon <hugohamon@neuf.fr>
 *
 * @throws ExceptionInterface
 */
class UnicodeString extends AbstractUnicodeString
{
    /**
     *
     */
    public function __construct(string $string = '')
    {
        $this->string = \normalizer_is_normalized($string) ? $string : \normalizer_normalize($string);
        if (\false === $this->string) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
    }
    /**
     * @return static
     */
    public function append(string ...$suffix)
    {
        $str = clone $this;
        $str->string = $this->string . (1 >= \count($suffix) ? $suffix[0] ?? '' : \implode('', $suffix));
        \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string));
        if (\false === $str->string) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function chunk(int $length = 1) : array
    {
        if (1 > $length) {
            throw new InvalidArgumentException('The chunk length must be greater than zero.');
        }
        if ('' === $this->string) {
            return [];
        }
        $rx = '/(';
        while (65535 < $length) {
            $rx .= '\\X{65535}';
            $length -= 65535;
        }
        $rx .= '\\X{' . $length . '})/u';
        $str = clone $this;
        $chunks = [];
        foreach (\preg_split($rx, $this->string, -1, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY) as $chunk) {
            $str->string = $chunk;
            $chunks[] = clone $str;
        }
        return $chunks;
    }
    /**
     * @param (string | iterable | AbstractString) $suffix
     */
    public function endsWith($suffix) : bool
    {
        if (!(\is_array($suffix) || $suffix instanceof \Traversable || $suffix instanceof AbstractString)) {
            if (!\is_string($suffix)) {
                if (!(\is_string($suffix) || \is_object($suffix) && \method_exists($suffix, '__toString') || (\is_bool($suffix) || \is_numeric($suffix)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($suffix) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($suffix) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $suffix = (string) $suffix;
                }
            }
        }
        if ($suffix instanceof AbstractString) {
            $suffix = $suffix->string;
        } elseif (!\is_string($suffix)) {
            return parent::endsWith($suffix);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        \normalizer_is_normalized($suffix, $form) ?: ($suffix = \normalizer_normalize($suffix, $form));
        if ('' === $suffix || \false === $suffix) {
            return \false;
        }
        if ($this->ignoreCase) {
            return 0 === \mb_stripos(\grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix)), $suffix, 0, 'UTF-8');
        }
        return $suffix === \grapheme_extract($this->string, \strlen($suffix), \GRAPHEME_EXTR_MAXBYTES, \strlen($this->string) - \strlen($suffix));
    }
    /**
     * @param (string | iterable | AbstractString) $string
     */
    public function equalsTo($string) : bool
    {
        if (!(\is_array($string) || $string instanceof \Traversable || $string instanceof AbstractString)) {
            if (!\is_string($string)) {
                if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $string = (string) $string;
                }
            }
        }
        if ($string instanceof AbstractString) {
            $string = $string->string;
        } elseif (!\is_string($string)) {
            return parent::equalsTo($string);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        \normalizer_is_normalized($string, $form) ?: ($string = \normalizer_normalize($string, $form));
        if ('' !== $string && \false !== $string && $this->ignoreCase) {
            return \strlen($string) === \strlen($this->string) && 0 === \mb_stripos($this->string, $string, 0, 'UTF-8');
        }
        return $string === $this->string;
    }
    /**
     * @param (string | iterable | AbstractString) $needle
     */
    public function indexOf($needle, int $offset = 0) : ?int
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable || $needle instanceof AbstractString)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOf($needle, $offset);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        \normalizer_is_normalized($needle, $form) ?: ($needle = \normalizer_normalize($needle, $form));
        if ('' === $needle || \false === $needle) {
            return null;
        }
        try {
            $i = $this->ignoreCase ? \grapheme_stripos($this->string, $needle, $offset) : \grapheme_strpos($this->string, $needle, $offset);
        } catch (\ValueError $e) {
            return null;
        }
        return \false === $i ? null : $i;
    }
    /**
     * @param (string | iterable | AbstractString) $needle
     */
    public function indexOfLast($needle, int $offset = 0) : ?int
    {
        if (!(\is_array($needle) || $needle instanceof \Traversable || $needle instanceof AbstractString)) {
            if (!\is_string($needle)) {
                if (!(\is_string($needle) || \is_object($needle) && \method_exists($needle, '__toString') || (\is_bool($needle) || \is_numeric($needle)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($needle) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($needle) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $needle = (string) $needle;
                }
            }
        }
        if ($needle instanceof AbstractString) {
            $needle = $needle->string;
        } elseif (!\is_string($needle)) {
            return parent::indexOfLast($needle, $offset);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        \normalizer_is_normalized($needle, $form) ?: ($needle = \normalizer_normalize($needle, $form));
        if ('' === $needle || \false === $needle) {
            return null;
        }
        $string = $this->string;
        if (0 > $offset) {
            // workaround https://bugs.php.net/74264
            if (0 > ($offset += \grapheme_strlen($needle))) {
                $string = \grapheme_substr($string, 0, $offset);
            }
            $offset = 0;
        }
        $i = $this->ignoreCase ? \grapheme_strripos($string, $needle, $offset) : \grapheme_strrpos($string, $needle, $offset);
        return \false === $i ? null : $i;
    }
    /**
     * @return static
     */
    public function join(array $strings, string $lastGlue = null)
    {
        $str = parent::join($strings, $lastGlue);
        \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string));
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function length() : int
    {
        return \grapheme_strlen($this->string);
    }
    /**
     * @return static
     */
    public function normalize(int $form = self::NFC)
    {
        $str = clone $this;
        if (\in_array($form, [self::NFC, self::NFKC], \true)) {
            \normalizer_is_normalized($str->string, $form) ?: ($str->string = \normalizer_normalize($str->string, $form));
        } elseif (!\in_array($form, [self::NFD, self::NFKD], \true)) {
            throw new InvalidArgumentException('Unsupported normalization form.');
        } elseif (!\normalizer_is_normalized($str->string, $form)) {
            $str->string = \normalizer_normalize($str->string, $form);
            $str->ignoreCase = null;
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function prepend(string ...$prefix)
    {
        $str = clone $this;
        $str->string = (1 >= \count($prefix) ? $prefix[0] ?? '' : \implode('', $prefix)) . $this->string;
        \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string));
        if (\false === $str->string) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function replace(string $from, string $to)
    {
        $str = clone $this;
        \normalizer_is_normalized($from) ?: ($from = \normalizer_normalize($from));
        if ('' !== $from && \false !== $from) {
            $tail = $str->string;
            $result = '';
            $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';
            while ('' !== $tail && \false !== ($i = $indexOf($tail, $from))) {
                $slice = \grapheme_substr($tail, 0, $i);
                $result .= $slice . $to;
                $tail = \Phabel\Target\Php80\Polyfill::substr($tail, \strlen($slice) + \strlen($from));
            }
            $str->string = $result . $tail;
            \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string));
            if (\false === $str->string) {
                throw new InvalidArgumentException('Invalid UTF-8 string.');
            }
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @param (string | callable) $to
     * @return static
     */
    public function replaceMatches(string $fromRegexp, $to)
    {
        if (!\is_callable($to)) {
            if (!\is_string($to)) {
                if (!(\is_string($to) || \is_object($to) && \method_exists($to, '__toString') || (\is_bool($to) || \is_numeric($to)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #2 ($to) must be of type callable|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($to) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $to = (string) $to;
                }
            }
        }
        $str = parent::replaceMatches($fromRegexp, $to);
        \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string));
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function slice(int $start = 0, int $length = null)
    {
        $str = clone $this;
        $str->string = (string) \grapheme_substr($this->string, $start, $length ?? 2147483647);
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return static
     */
    public function splice(string $replacement, int $start = 0, int $length = null)
    {
        $str = clone $this;
        $start = $start ? \strlen(\grapheme_substr($this->string, 0, $start)) : 0;
        $length = $length ? \strlen(\grapheme_substr($this->string, $start, $length ?? 2147483647)) : $length;
        $str->string = \Phabel\Target\Php80\Polyfill::substr_replace($this->string, $replacement, $start, $length ?? 2147483647);
        \normalizer_is_normalized($str->string) ?: ($str->string = \normalizer_normalize($str->string));
        if (\false === $str->string) {
            throw new InvalidArgumentException('Invalid UTF-8 string.');
        }
        $phabelReturn = $str;
        if (!$phabelReturn instanceof static) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type ' . static::class . ', ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public function split(string $delimiter, int $limit = null, int $flags = null) : array
    {
        if (1 > ($limit = $limit ?? 2147483647)) {
            throw new InvalidArgumentException('Split limit must be a positive integer.');
        }
        if ('' === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is empty.');
        }
        if (null !== $flags) {
            return parent::split($delimiter . 'u', $limit, $flags);
        }
        \normalizer_is_normalized($delimiter) ?: ($delimiter = \normalizer_normalize($delimiter));
        if (\false === $delimiter) {
            throw new InvalidArgumentException('Split delimiter is not a valid UTF-8 string.');
        }
        $str = clone $this;
        $tail = $this->string;
        $chunks = [];
        $indexOf = $this->ignoreCase ? 'grapheme_stripos' : 'grapheme_strpos';
        while (1 < $limit && \false !== ($i = $indexOf($tail, $delimiter))) {
            $str->string = \grapheme_substr($tail, 0, $i);
            $chunks[] = clone $str;
            $tail = \Phabel\Target\Php80\Polyfill::substr($tail, \strlen($str->string) + \strlen($delimiter));
            --$limit;
        }
        $str->string = $tail;
        $chunks[] = clone $str;
        return $chunks;
    }
    /**
     * @param (string | iterable | AbstractString) $prefix
     */
    public function startsWith($prefix) : bool
    {
        if (!(\is_array($prefix) || $prefix instanceof \Traversable || $prefix instanceof AbstractString)) {
            if (!\is_string($prefix)) {
                if (!(\is_string($prefix) || \is_object($prefix) && \method_exists($prefix, '__toString') || (\is_bool($prefix) || \is_numeric($prefix)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($prefix) must be of type AbstractString|string|iterable, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($prefix) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $prefix = (string) $prefix;
                }
            }
        }
        if ($prefix instanceof AbstractString) {
            $prefix = $prefix->string;
        } elseif (!\is_string($prefix)) {
            return parent::startsWith($prefix);
        }
        $form = null === $this->ignoreCase ? \Normalizer::NFD : \Normalizer::NFC;
        \normalizer_is_normalized($prefix, $form) ?: ($prefix = \normalizer_normalize($prefix, $form));
        if ('' === $prefix || \false === $prefix) {
            return \false;
        }
        if ($this->ignoreCase) {
            return 0 === \mb_stripos(\grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES), $prefix, 0, 'UTF-8');
        }
        return $prefix === \grapheme_extract($this->string, \strlen($prefix), \GRAPHEME_EXTR_MAXBYTES);
    }
    /**
     *
     */
    public function __wakeup()
    {
        if (!\is_string($this->string)) {
            throw new \BadMethodCallException('Cannot unserialize ' . __CLASS__);
        }
        \normalizer_is_normalized($this->string) ?: ($this->string = \normalizer_normalize($this->string));
    }
    /**
     *
     */
    public function __clone()
    {
        if (null === $this->ignoreCase) {
            \normalizer_is_normalized($this->string) ?: ($this->string = \normalizer_normalize($this->string));
        }
        $this->ignoreCase = \false;
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String\Inflector;

/**
 * French inflector.
 *
 * This class does only inflect nouns; not adjectives nor composed words like "soixante-dix".
 */
final class FrenchInflector implements InflectorInterface
{
    /**
     * A list of all rules for pluralise.
     *
     * @see https://la-conjugaison.nouvelobs.com/regles/grammaire/le-pluriel-des-noms-121.php
     */
    private const PLURALIZE_REGEXP = [
        // First entry: regexp
        // Second entry: replacement
        // Words finishing with "s", "x" or "z" are invariables
        // Les mots finissant par "s", "x" ou "z" sont invariables
        ['/(s|x|z)$/i', '\\1'],
        // Words finishing with "eau" are pluralized with a "x"
        // Les mots finissant par "eau" prennent tous un "x" au pluriel
        ['/(eau)$/i', '\\1x'],
        // Words finishing with "au" are pluralized with a "x" excepted "landau"
        // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau"
        ['/^(landau)$/i', '\\1s'],
        ['/(au)$/i', '\\1x'],
        // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "Ã©meu"
        // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "Ã©meu"
        ['/^(pneu|bleu|Ã©meu)$/i', '\\1s'],
        ['/(eu)$/i', '\\1x'],
        // Words finishing with "al" are pluralized with a "aux" excepted
        // Les mots finissant en "al" se terminent en "aux" sauf
        ['/^(bal|carnaval|caracal|chacal|choral|corral|Ã©tal|festival|rÃ©cital|val)$/i', '\\1s'],
        ['/al$/i', '\\1aux'],
        // Aspirail, bail, corail, Ã©mail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux
        ['/^(aspir|b|cor|Ã©m|ferm|soupir|trav|vant|vitr)ail$/i', '\\1aux'],
        // Bijou, caillou, chou, genou, hibou, joujou et pou qui prennent un x au pluriel
        ['/^(bij|caill|ch|gen|hib|jouj|p)ou$/i', '\\1oux'],
        // Invariable words
        ['/^(cinquante|soixante|mille)$/i', '\\1'],
        // French titles
        ['/^(mon|ma)(sieur|dame|demoiselle|seigneur)$/', 'PhabelVendor\\mes\\2s'],
        ['/^(Mon|Ma)(sieur|dame|demoiselle|seigneur)$/', 'PhabelVendor\\Mes\\2s'],
    ];
    /**
     * A list of all rules for singularize.
     */
    private const SINGULARIZE_REGEXP = [
        // First entry: regexp
        // Second entry: replacement
        // Aspirail, bail, corail, Ã©mail, fermail, soupirail, travail, vantail et vitrail font leur pluriel en -aux
        ['/((aspir|b|cor|Ã©m|ferm|soupir|trav|vant|vitr))aux$/i', '\\1ail'],
        // Words finishing with "eau" are pluralized with a "x"
        // Les mots finissant par "eau" prennent tous un "x" au pluriel
        ['/(eau)x$/i', '\\1'],
        // Words finishing with "al" are pluralized with a "aux" expected
        // Les mots finissant en "al" se terminent en "aux" sauf
        ['/(amir|anim|arsen|boc|can|capit|capor|chev|crist|gÃ©nÃ©r|hopit|hÃ´pit|idÃ©|journ|littor|loc|m|mÃ©t|minÃ©r|princip|radic|termin)aux$/i', '\\1al'],
        // Words finishing with "au" are pluralized with a "x" excepted "landau"
        // Les mots finissant par "au" prennent un "x" au pluriel sauf "landau"
        ['/(au)x$/i', '\\1'],
        // Words finishing with "eu" are pluralized with a "x" excepted "pneu", "bleu", "Ã©meu"
        // Les mots finissant en "eu" prennent un "x" au pluriel sauf "pneu", "bleu", "Ã©meu"
        ['/(eu)x$/i', '\\1'],
        //  Words finishing with "ou" are pluralized with a "s" excepted bijou, caillou, chou, genou, hibou, joujou, pou
        // Les mots finissant par "ou" prennent un "s" sauf bijou, caillou, chou, genou, hibou, joujou, pou
        ['/(bij|caill|ch|gen|hib|jouj|p)oux$/i', '\\1ou'],
        // French titles
        ['/^mes(dame|demoiselle)s$/', 'PhabelVendor\\ma\\1'],
        ['/^Mes(dame|demoiselle)s$/', 'PhabelVendor\\Ma\\1'],
        ['/^mes(sieur|seigneur)s$/', 'PhabelVendor\\mon\\1'],
        ['/^Mes(sieur|seigneur)s$/', 'PhabelVendor\\Mon\\1'],
        //Default rule
        ['/s$/i', ''],
    ];
    /**
     * A list of words which should not be inflected.
     * This list is only used by singularize.
     */
    private const UNINFLECTED = '/^(abcÃ¨s|accÃ¨s|abus|albatros|anchois|anglais|autobus|bois|brebis|carquois|cas|chas|colis|concours|corps|cours|cyprÃ¨s|dÃ©cÃ¨s|devis|discours|dos|embarras|engrais|entrelacs|excÃ¨s|fils|fois|gÃ¢chis|gars|glas|hÃ©ros|intrus|jars|jus|kermÃ¨s|lacis|legs|lilas|marais|mars|matelas|mÃ©pris|mets|mois|mors|obus|os|palais|paradis|parcours|pardessus|pays|plusieurs|poids|pois|pouls|printemps|processus|progrÃ¨s|puits|pus|rabais|radis|recors|recours|refus|relais|remords|remous|rictus|rhinocÃ©ros|repas|rubis|sas|secours|sens|souris|succÃ¨s|talus|tapis|tas|taudis|temps|tiers|univers|velours|verglas|vernis|virus)$/i';
    /**
     * {@inheritdoc}
     */
    public function singularize(string $plural) : array
    {
        if ($this->isInflectedWord($plural)) {
            return [$plural];
        }
        foreach (self::SINGULARIZE_REGEXP as $rule) {
            [$regexp, $replace] = $rule;
            if (1 === \preg_match($regexp, $plural)) {
                return [\preg_replace($regexp, $replace, $plural)];
            }
        }
        return [$plural];
    }
    /**
     * {@inheritdoc}
     */
    public function pluralize(string $singular) : array
    {
        if ($this->isInflectedWord($singular)) {
            return [$singular];
        }
        foreach (self::PLURALIZE_REGEXP as $rule) {
            [$regexp, $replace] = $rule;
            if (1 === \preg_match($regexp, $singular)) {
                return [\preg_replace($regexp, $replace, $singular)];
            }
        }
        return [$singular . 's'];
    }
    /**
     *
     */
    private function isInflectedWord(string $word) : bool
    {
        return 1 === \preg_match(self::UNINFLECTED, $word);
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String\Inflector;

interface InflectorInterface
{
    /**
     * Returns the singular forms of a string.
     *
     * If the method can't determine the form with certainty, several possible singulars are returned.
     *
     * @return string[]
     */
    public function singularize(string $plural) : array;
    /**
     * Returns the plural forms of a string.
     *
     * If the method can't determine the form with certainty, several possible plurals are returned.
     *
     * @return string[]
     */
    public function pluralize(string $singular) : array;
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace PhabelVendor\Symfony\Component\String\Inflector;

final class EnglishInflector implements InflectorInterface
{
    /**
     * Map English plural to singular suffixes.
     *
     * @see http://english-zone.com/spelling/plurals.html
     */
    private const PLURAL_MAP = [
        // First entry: plural suffix, reversed
        // Second entry: length of plural suffix
        // Third entry: Whether the suffix may succeed a vocal
        // Fourth entry: Whether the suffix may succeed a consonant
        // Fifth entry: singular suffix, normal
        // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
        ['a', 1, \true, \true, ['on', 'um']],
        // nebulae (nebula)
        ['ea', 2, \true, \true, 'a'],
        // services (service)
        ['secivres', 8, \true, \true, 'service'],
        // mice (mouse), lice (louse)
        ['eci', 3, \false, \true, 'ouse'],
        // geese (goose)
        ['esee', 4, \false, \true, 'oose'],
        // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
        ['i', 1, \true, \true, 'us'],
        // men (man), women (woman)
        ['nem', 3, \true, \true, 'man'],
        // children (child)
        ['nerdlihc', 8, \true, \true, 'child'],
        // oxen (ox)
        ['nexo', 4, \false, \false, 'ox'],
        // indices (index), appendices (appendix), prices (price)
        ['seci', 4, \false, \true, ['ex', 'ix', 'ice']],
        // selfies (selfie)
        ['seifles', 7, \true, \true, 'selfie'],
        // zombies (zombie)
        ['seibmoz', 7, \true, \true, 'zombie'],
        // movies (movie)
        ['seivom', 6, \true, \true, 'movie'],
        // conspectuses (conspectus), prospectuses (prospectus)
        ['sesutcep', 8, \true, \true, 'pectus'],
        // feet (foot)
        ['teef', 4, \true, \true, 'foot'],
        // geese (goose)
        ['eseeg', 5, \true, \true, 'goose'],
        // teeth (tooth)
        ['hteet', 5, \true, \true, 'tooth'],
        // news (news)
        ['swen', 4, \true, \true, 'news'],
        // series (series)
        ['seires', 6, \true, \true, 'series'],
        // babies (baby)
        ['sei', 3, \false, \true, 'y'],
        // accesses (access), addresses (address), kisses (kiss)
        ['sess', 4, \true, \false, 'ss'],
        // analyses (analysis), ellipses (ellipsis), fungi (fungus),
        // neuroses (neurosis), theses (thesis), emphases (emphasis),
        // oases (oasis), crises (crisis), houses (house), bases (base),
        // atlases (atlas)
        ['ses', 3, \true, \true, ['s', 'se', 'sis']],
        // objectives (objective), alternative (alternatives)
        ['sevit', 5, \true, \true, 'tive'],
        // drives (drive)
        ['sevird', 6, \false, \true, 'drive'],
        // lives (life), wives (wife)
        ['sevi', 4, \false, \true, 'ife'],
        // moves (move)
        ['sevom', 5, \true, \true, 'move'],
        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf), caves (cave), staves (staff)
        ['sev', 3, \true, \true, ['f', 've', 'ff']],
        // axes (axis), axes (ax), axes (axe)
        ['sexa', 4, \false, \false, ['ax', 'axe', 'axis']],
        // indexes (index), matrixes (matrix)
        ['sex', 3, \true, \false, 'x'],
        // quizzes (quiz)
        ['sezz', 4, \true, \false, 'z'],
        // bureaus (bureau)
        ['suae', 4, \false, \true, 'eau'],
        // fees (fee), trees (tree), employees (employee)
        ['see', 3, \true, \true, 'ee'],
        // edges (edge)
        ['segd', 4, \true, \true, 'dge'],
        // roses (rose), garages (garage), cassettes (cassette),
        // waltzes (waltz), heroes (hero), bushes (bush), arches (arch),
        // shoes (shoe)
        ['se', 2, \true, \true, ['', 'e']],
        // tags (tag)
        ['s', 1, \true, \true, ''],
        // chateaux (chateau)
        ['xuae', 4, \false, \true, 'eau'],
        // people (person)
        ['elpoep', 6, \true, \true, 'person'],
    ];
    /**
     * Map English singular to plural suffixes.
     *
     * @see http://english-zone.com/spelling/plurals.html
     */
    private const SINGULAR_MAP = [
        // First entry: singular suffix, reversed
        // Second entry: length of singular suffix
        // Third entry: Whether the suffix may succeed a vocal
        // Fourth entry: Whether the suffix may succeed a consonant
        // Fifth entry: plural suffix, normal
        // criterion (criteria)
        ['airetirc', 8, \false, \false, 'criterion'],
        // nebulae (nebula)
        ['aluben', 6, \false, \false, 'nebulae'],
        // children (child)
        ['dlihc', 5, \true, \true, 'children'],
        // prices (price)
        ['eci', 3, \false, \true, 'ices'],
        // services (service)
        ['ecivres', 7, \true, \true, 'services'],
        // lives (life), wives (wife)
        ['efi', 3, \false, \true, 'ives'],
        // selfies (selfie)
        ['eifles', 6, \true, \true, 'selfies'],
        // movies (movie)
        ['eivom', 5, \true, \true, 'movies'],
        // lice (louse)
        ['esuol', 5, \false, \true, 'lice'],
        // mice (mouse)
        ['esuom', 5, \false, \true, 'mice'],
        // geese (goose)
        ['esoo', 4, \false, \true, 'eese'],
        // houses (house), bases (base)
        ['es', 2, \true, \true, 'ses'],
        // geese (goose)
        ['esoog', 5, \true, \true, 'geese'],
        // caves (cave)
        ['ev', 2, \true, \true, 'ves'],
        // drives (drive)
        ['evird', 5, \false, \true, 'drives'],
        // objectives (objective), alternative (alternatives)
        ['evit', 4, \true, \true, 'tives'],
        // moves (move)
        ['evom', 4, \true, \true, 'moves'],
        // staves (staff)
        ['ffats', 5, \true, \true, 'staves'],
        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
        ['ff', 2, \true, \true, 'ffs'],
        // hooves (hoof), dwarves (dwarf), elves (elf), leaves (leaf)
        ['f', 1, \true, \true, ['fs', 'ves']],
        // arches (arch)
        ['hc', 2, \true, \true, 'ches'],
        // bushes (bush)
        ['hs', 2, \true, \true, 'shes'],
        // teeth (tooth)
        ['htoot', 5, \true, \true, 'teeth'],
        // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
        ['mu', 2, \true, \true, 'a'],
        // men (man), women (woman)
        ['nam', 3, \true, \true, 'men'],
        // people (person)
        ['nosrep', 6, \true, \true, ['persons', 'people']],
        // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
        ['noi', 3, \true, \true, 'ions'],
        // coupon (coupons)
        ['nop', 3, \true, \true, 'pons'],
        // seasons (season), treasons (treason), poisons (poison), lessons (lesson)
        ['nos', 3, \true, \true, 'sons'],
        // bacteria (bacterium), criteria (criterion), phenomena (phenomenon)
        ['no', 2, \true, \true, 'a'],
        // echoes (echo)
        ['ohce', 4, \true, \true, 'echoes'],
        // heroes (hero)
        ['oreh', 4, \true, \true, 'heroes'],
        // atlases (atlas)
        ['salta', 5, \true, \true, 'atlases'],
        // irises (iris)
        ['siri', 4, \true, \true, 'irises'],
        // analyses (analysis), ellipses (ellipsis), neuroses (neurosis)
        // theses (thesis), emphases (emphasis), oases (oasis),
        // crises (crisis)
        ['sis', 3, \true, \true, 'ses'],
        // accesses (access), addresses (address), kisses (kiss)
        ['ss', 2, \true, \false, 'sses'],
        // syllabi (syllabus)
        ['suballys', 8, \true, \true, 'syllabi'],
        // buses (bus)
        ['sub', 3, \true, \true, 'buses'],
        // circuses (circus)
        ['suc', 3, \true, \true, 'cuses'],
        // conspectuses (conspectus), prospectuses (prospectus)
        ['sutcep', 6, \true, \true, 'pectuses'],
        // fungi (fungus), alumni (alumnus), syllabi (syllabus), radii (radius)
        ['su', 2, \true, \true, 'i'],
        // news (news)
        ['swen', 4, \true, \true, 'news'],
        // feet (foot)
        ['toof', 4, \true, \true, 'feet'],
        // chateaux (chateau), bureaus (bureau)
        ['uae', 3, \false, \true, ['eaus', 'eaux']],
        // oxen (ox)
        ['xo', 2, \false, \false, 'oxen'],
        // hoaxes (hoax)
        ['xaoh', 4, \true, \false, 'hoaxes'],
        // indices (index)
        ['xedni', 5, \false, \true, ['indicies', 'indexes']],
        // boxes (box)
        ['xo', 2, \false, \true, 'oxes'],
        // indexes (index), matrixes (matrix)
        ['x', 1, \true, \false, ['cies', 'xes']],
        // appendices (appendix)
        ['xi', 2, \false, \true, 'ices'],
        // babies (baby)
        ['y', 1, \false, \true, 'ies'],
        // quizzes (quiz)
        ['ziuq', 4, \true, \false, 'quizzes'],
        // waltzes (waltz)
        ['z', 1, \true, \true, 'zes'],
    ];
    /**
     * A list of words which should not be inflected, reversed.
     */
    private const UNINFLECTED = [
        '',
        // data
        'atad',
        // deer
        'reed',
        // feedback
        'kcabdeef',
        // fish
        'hsif',
        // info
        'ofni',
        // moose
        'esoom',
        // series
        'seires',
        // sheep
        'peehs',
        // species
        'seiceps',
    ];
    /**
     * {@inheritdoc}
     */
    public function singularize(string $plural) : array
    {
        $pluralRev = \strrev($plural);
        $lowerPluralRev = \strtolower($pluralRev);
        $pluralLength = \strlen($lowerPluralRev);
        // Check if the word is one which is not inflected, return early if so
        if (\in_array($lowerPluralRev, self::UNINFLECTED, \true)) {
            return [$plural];
        }
        // The outer loop iterates over the entries of the plural table
        // The inner loop $j iterates over the characters of the plural suffix
        // in the plural table to compare them with the characters of the actual
        // given plural suffix
        foreach (self::PLURAL_MAP as $map) {
            $suffix = $map[0];
            $suffixLength = $map[1];
            $j = 0;
            // Compare characters in the plural table and of the suffix of the
            // given plural one by one
            while ($suffix[$j] === $lowerPluralRev[$j]) {
                // Let $j point to the next character
                ++$j;
                // Successfully compared the last character
                // Add an entry with the singular suffix to the singular array
                if ($j === $suffixLength) {
                    // Is there any character preceding the suffix in the plural string?
                    if ($j < $pluralLength) {
                        $nextIsVocal = \false !== \strpos('aeiou', $lowerPluralRev[$j]);
                        if (!$map[2] && $nextIsVocal) {
                            // suffix may not succeed a vocal but next char is one
                            break;
                        }
                        if (!$map[3] && !$nextIsVocal) {
                            // suffix may not succeed a consonant but next char is one
                            break;
                        }
                    }
                    $newBase = \Phabel\Target\Php80\Polyfill::substr($plural, 0, $pluralLength - $suffixLength);
                    $newSuffix = $map[4];
                    // Check whether the first character in the plural suffix
                    // is uppercased. If yes, uppercase the first character in
                    // the singular suffix too
                    $firstUpper = \ctype_upper($pluralRev[$j - 1]);
                    if (\is_array($newSuffix)) {
                        $singulars = [];
                        foreach ($newSuffix as $newSuffixEntry) {
                            $singulars[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry);
                        }
                        return $singulars;
                    }
                    return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)];
                }
                // Suffix is longer than word
                if ($j === $pluralLength) {
                    break;
                }
            }
        }
        // Assume that plural and singular is identical
        return [$plural];
    }
    /**
     * {@inheritdoc}
     */
    public function pluralize(string $singular) : array
    {
        $singularRev = \strrev($singular);
        $lowerSingularRev = \strtolower($singularRev);
        $singularLength = \strlen($lowerSingularRev);
        // Check if the word is one which is not inflected, return early if so
        if (\in_array($lowerSingularRev, self::UNINFLECTED, \true)) {
            return [$singular];
        }
        // The outer loop iterates over the entries of the singular table
        // The inner loop $j iterates over the characters of the singular suffix
        // in the singular table to compare them with the characters of the actual
        // given singular suffix
        foreach (self::SINGULAR_MAP as $map) {
            $suffix = $map[0];
            $suffixLength = $map[1];
            $j = 0;
            // Compare characters in the singular table and of the suffix of the
            // given plural one by one
            while ($suffix[$j] === $lowerSingularRev[$j]) {
                // Let $j point to the next character
                ++$j;
                // Successfully compared the last character
                // Add an entry with the plural suffix to the plural array
                if ($j === $suffixLength) {
                    // Is there any character preceding the suffix in the plural string?
                    if ($j < $singularLength) {
                        $nextIsVocal = \false !== \strpos('aeiou', $lowerSingularRev[$j]);
                        if (!$map[2] && $nextIsVocal) {
                            // suffix may not succeed a vocal but next char is one
                            break;
                        }
                        if (!$map[3] && !$nextIsVocal) {
                            // suffix may not succeed a consonant but next char is one
                            break;
                        }
                    }
                    $newBase = \Phabel\Target\Php80\Polyfill::substr($singular, 0, $singularLength - $suffixLength);
                    $newSuffix = $map[4];
                    // Check whether the first character in the singular suffix
                    // is uppercased. If yes, uppercase the first character in
                    // the singular suffix too
                    $firstUpper = \ctype_upper($singularRev[$j - 1]);
                    if (\is_array($newSuffix)) {
                        $plurals = [];
                        foreach ($newSuffix as $newSuffixEntry) {
                            $plurals[] = $newBase . ($firstUpper ? \ucfirst($newSuffixEntry) : $newSuffixEntry);
                        }
                        return $plurals;
                    }
                    return [$newBase . ($firstUpper ? \ucfirst($newSuffix) : $newSuffix)];
                }
                // Suffix is longer than word
                if ($j === $singularLength) {
                    break;
                }
            }
        }
        // Assume that plural is singular with a trailing `s`
        return [$singular . 's'];
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Mbstring as p;
if (!function_exists('mb_convert_encoding')) {
    /**
     * @param (array | string | null) $string
     * @param (array | string | null) $from_encoding
     * @return (array | string | false)
     */
    function mb_convert_encoding($string, ?string $to_encoding, $from_encoding = null)
    {
        if (!\is_null($string)) {
            if (!\is_string($string)) {
                if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                    if (!\is_array($string)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $string = (string) $string;
                }
            }
        }
        if (!(\is_null($from_encoding) || \is_null($from_encoding))) {
            if (!\is_string($from_encoding)) {
                if (!(\is_string($from_encoding) || \is_object($from_encoding) && \method_exists($from_encoding, '__toString') || (\is_bool($from_encoding) || \is_numeric($from_encoding)))) {
                    if (!\is_array($from_encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #3 ($from_encoding) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($from_encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $from_encoding = (string) $from_encoding;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_convert_encoding($string ?? '', (string) $to_encoding, $from_encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    if (!\is_array($phabelReturn)) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_decode_mimeheader')) {
    /**
     *
     */
    function mb_decode_mimeheader(?string $string) : string
    {
        return p\Mbstring::mb_decode_mimeheader((string) $string);
    }
}
if (!function_exists('mb_encode_mimeheader')) {
    /**
     *
     */
    function mb_encode_mimeheader(?string $string, ?string $charset = null, ?string $transfer_encoding = null, ?string $newline = "\r\n", ?int $indent = 0) : string
    {
        return p\Mbstring::mb_encode_mimeheader((string) $string, $charset, $transfer_encoding, (string) $newline, (int) $indent);
    }
}
if (!function_exists('mb_decode_numericentity')) {
    /**
     *
     */
    function mb_decode_numericentity(?string $string, array $map, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_decode_numericentity((string) $string, $map, $encoding);
    }
}
if (!function_exists('mb_encode_numericentity')) {
    /**
     *
     */
    function mb_encode_numericentity(?string $string, array $map, ?string $encoding = null, ?bool $hex = false) : string
    {
        return p\Mbstring::mb_encode_numericentity((string) $string, $map, $encoding, (bool) $hex);
    }
}
if (!function_exists('mb_convert_case')) {
    /**
     *
     */
    function mb_convert_case(?string $string, ?int $mode, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_convert_case((string) $string, (int) $mode, $encoding);
    }
}
if (!function_exists('mb_internal_encoding')) {
    /**
     * @return (string | bool)
     */
    function mb_internal_encoding(?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_internal_encoding($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_language')) {
    /**
     * @return (string | bool)
     */
    function mb_language(?string $language = null)
    {
        $phabelReturn = p\Mbstring::mb_language($language);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_list_encodings')) {
    /**
     *
     */
    function mb_list_encodings() : array
    {
        return p\Mbstring::mb_list_encodings();
    }
}
if (!function_exists('mb_encoding_aliases')) {
    /**
     *
     */
    function mb_encoding_aliases(?string $encoding) : array
    {
        return p\Mbstring::mb_encoding_aliases((string) $encoding);
    }
}
if (!function_exists('mb_check_encoding')) {
    /**
     * @param (array | string | null) $value
     */
    function mb_check_encoding($value = null, ?string $encoding = null) : bool
    {
        if (!(\is_null($value) || \is_null($value))) {
            if (!\is_string($value)) {
                if (!(\is_string($value) || \is_object($value) && \method_exists($value, '__toString') || (\is_bool($value) || \is_numeric($value)))) {
                    if (!\is_array($value)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($value) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $value = (string) $value;
                }
            }
        }
        return p\Mbstring::mb_check_encoding($value, $encoding);
    }
}
if (!function_exists('mb_detect_encoding')) {
    /**
     * @param (array | string | null) $encodings
     * @return (string | false)
     */
    function mb_detect_encoding(?string $string, $encodings = null, ?bool $strict = false)
    {
        if (!(\is_null($encodings) || \is_null($encodings))) {
            if (!\is_string($encodings)) {
                if (!(\is_string($encodings) || \is_object($encodings) && \method_exists($encodings, '__toString') || (\is_bool($encodings) || \is_numeric($encodings)))) {
                    if (!\is_array($encodings)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #2 ($encodings) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($encodings) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $encodings = (string) $encodings;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_detect_encoding((string) $string, $encodings, (bool) $strict);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_detect_order')) {
    /**
     * @param (array | string | null) $encoding
     * @return (array | bool)
     */
    function mb_detect_order($encoding = null)
    {
        if (!(\is_null($encoding) || \is_null($encoding))) {
            if (!\is_string($encoding)) {
                if (!(\is_string($encoding) || \is_object($encoding) && \method_exists($encoding, '__toString') || (\is_bool($encoding) || \is_numeric($encoding)))) {
                    if (!\is_array($encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #1 ($encoding) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $encoding = (string) $encoding;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_detect_order($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_array($phabelReturn)) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type array|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_parse_str')) {
    /**
     *
     */
    function mb_parse_str(?string $string, &$result = []) : bool
    {
        parse_str((string) $string, $result);
        return (bool) $result;
    }
}
if (!function_exists('mb_strlen')) {
    /**
     *
     */
    function mb_strlen(?string $string, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_strlen((string) $string, $encoding);
    }
}
if (!function_exists('mb_strpos')) {
    /**
     * @return (int | false)
     */
    function mb_strpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strpos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strtolower')) {
    /**
     *
     */
    function mb_strtolower(?string $string, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_strtolower((string) $string, $encoding);
    }
}
if (!function_exists('mb_strtoupper')) {
    /**
     *
     */
    function mb_strtoupper(?string $string, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_strtoupper((string) $string, $encoding);
    }
}
if (!function_exists('mb_substitute_character')) {
    /**
     * @param (string | int | null) $substitute_character
     * @return (string | int | bool)
     */
    function mb_substitute_character($substitute_character = null)
    {
        if (!(\is_null($substitute_character) || \is_null($substitute_character))) {
            if (!\is_int($substitute_character)) {
                if (!(\is_bool($substitute_character) || \is_numeric($substitute_character))) {
                    if (!\is_string($substitute_character)) {
                        if (!(\is_string($substitute_character) || \is_object($substitute_character) && \method_exists($substitute_character, '__toString') || (\is_bool($substitute_character) || \is_numeric($substitute_character)))) {
                            throw new \TypeError(__METHOD__ . '(): Argument #1 ($substitute_character) must be of type ?string|int|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($substitute_character) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                        } else {
                            $substitute_character = (string) $substitute_character;
                        }
                    }
                } else {
                    $substitute_character = (int) $substitute_character;
                }
            }
        }
        $phabelReturn = p\Mbstring::mb_substitute_character($substitute_character);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        if (!\is_string($phabelReturn)) {
                            if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                                throw new \TypeError(__METHOD__ . '(): Return value must be of type string|int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                            } else {
                                $phabelReturn = (string) $phabelReturn;
                            }
                        }
                    } else {
                        $phabelReturn = (int) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_substr')) {
    /**
     *
     */
    function mb_substr(?string $string, ?int $start, ?int $length = null, ?string $encoding = null) : string
    {
        return p\Mbstring::mb_substr((string) $string, (int) $start, $length, $encoding);
    }
}
if (!function_exists('mb_stripos')) {
    /**
     * @return (int | false)
     */
    function mb_stripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_stripos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_stristr')) {
    /**
     * @return (string | false)
     */
    function mb_stristr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_stristr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrchr')) {
    /**
     * @return (string | false)
     */
    function mb_strrchr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrchr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrichr')) {
    /**
     * @return (string | false)
     */
    function mb_strrichr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrichr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strripos')) {
    /**
     * @return (int | false)
     */
    function mb_strripos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strripos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strrpos')) {
    /**
     * @return (int | false)
     */
    function mb_strrpos(?string $haystack, ?string $needle, ?int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strrpos((string) $haystack, (string) $needle, (int) $offset, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strstr')) {
    /**
     * @return (string | false)
     */
    function mb_strstr(?string $haystack, ?string $needle, ?bool $before_needle = false, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_strstr((string) $haystack, (string) $needle, (bool) $before_needle, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_get_info')) {
    /**
     * @return (array | string | int | false)
     */
    function mb_get_info(?string $type = 'all')
    {
        $phabelReturn = p\Mbstring::mb_get_info((string) $type);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    if (!\is_string($phabelReturn)) {
                        if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                            if (!\is_array($phabelReturn)) {
                                throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                            }
                        } else {
                            $phabelReturn = (string) $phabelReturn;
                        }
                    }
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_http_output')) {
    /**
     * @return (string | bool)
     */
    function mb_http_output(?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_http_output($encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_strwidth')) {
    /**
     *
     */
    function mb_strwidth(?string $string, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_strwidth((string) $string, $encoding);
    }
}
if (!function_exists('mb_substr_count')) {
    /**
     *
     */
    function mb_substr_count(?string $haystack, ?string $needle, ?string $encoding = null) : int
    {
        return p\Mbstring::mb_substr_count((string) $haystack, (string) $needle, $encoding);
    }
}
if (!function_exists('mb_output_handler')) {
    /**
     *
     */
    function mb_output_handler(?string $string, ?int $status) : string
    {
        return p\Mbstring::mb_output_handler((string) $string, (int) $status);
    }
}
if (!function_exists('mb_http_input')) {
    /**
     * @return (array | string | false)
     */
    function mb_http_input(?string $type = null)
    {
        $phabelReturn = p\Mbstring::mb_http_input($type);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    if (!\is_array($phabelReturn)) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_convert_variables')) {
    /**
     * @param (array | string | null) $from_encoding
     * @param mixed $var
     * @param mixed ...$vars
     * @return (string | false)
     */
    function mb_convert_variables(?string $to_encoding, $from_encoding, &$var, &...$vars)
    {
        if (!\is_null($from_encoding)) {
            if (!\is_string($from_encoding)) {
                if (!(\is_string($from_encoding) || \is_object($from_encoding) && \method_exists($from_encoding, '__toString') || (\is_bool($from_encoding) || \is_numeric($from_encoding)))) {
                    if (!\is_array($from_encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #2 ($from_encoding) must be of type array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($from_encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $from_encoding = (string) $from_encoding;
                }
            }
        }
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #3 ($var) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($var) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        foreach ($vars as $phabelVariadicIndex => $phabelVariadic) {
            if (!true) {
                throw new \TypeError(__METHOD__ . '(): Argument #' . (4 + $phabelVariadicIndex) . ' must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($vars) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
        }
        $phabelReturn = p\Mbstring::mb_convert_variables((string) $to_encoding, $from_encoding ?? '', $var, ...$vars);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_ord')) {
    /**
     * @return (int | false)
     */
    function mb_ord(?string $string, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_ord((string) $string, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_chr')) {
    /**
     * @return (string | false)
     */
    function mb_chr(?int $codepoint, ?string $encoding = null)
    {
        $phabelReturn = p\Mbstring::mb_chr((int) $codepoint, $encoding);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('mb_scrub')) {
    /**
     *
     */
    function mb_scrub(?string $string, ?string $encoding = null) : string
    {
        $encoding ??= mb_internal_encoding();
        return mb_convert_encoding((string) $string, $encoding, $encoding);
    }
}
if (!function_exists('mb_str_split')) {
    /**
     *
     */
    function mb_str_split(?string $string, ?int $length = 1, ?string $encoding = null) : array
    {
        return p\Mbstring::mb_str_split((string) $string, (int) $length, $encoding);
    }
}
if (extension_loaded('mbstring')) {
    return;
}
if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}<?php

// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt
return '/(?<![\\x{0027}\\x{002E}\\x{003A}\\x{005E}\\x{0060}\\x{00A8}\\x{00AD}\\x{00AF}\\x{00B4}\\x{00B7}\\x{00B8}\\x{02B0}-\\x{02C1}\\x{02C2}-\\x{02C5}\\x{02C6}-\\x{02D1}\\x{02D2}-\\x{02DF}\\x{02E0}-\\x{02E4}\\x{02E5}-\\x{02EB}\\x{02EC}\\x{02ED}\\x{02EE}\\x{02EF}-\\x{02FF}\\x{0300}-\\x{036F}\\x{0374}\\x{0375}\\x{037A}\\x{0384}-\\x{0385}\\x{0387}\\x{0483}-\\x{0487}\\x{0488}-\\x{0489}\\x{0559}\\x{0591}-\\x{05BD}\\x{05BF}\\x{05C1}-\\x{05C2}\\x{05C4}-\\x{05C5}\\x{05C7}\\x{05F4}\\x{0600}-\\x{0605}\\x{0610}-\\x{061A}\\x{061C}\\x{0640}\\x{064B}-\\x{065F}\\x{0670}\\x{06D6}-\\x{06DC}\\x{06DD}\\x{06DF}-\\x{06E4}\\x{06E5}-\\x{06E6}\\x{06E7}-\\x{06E8}\\x{06EA}-\\x{06ED}\\x{070F}\\x{0711}\\x{0730}-\\x{074A}\\x{07A6}-\\x{07B0}\\x{07EB}-\\x{07F3}\\x{07F4}-\\x{07F5}\\x{07FA}\\x{07FD}\\x{0816}-\\x{0819}\\x{081A}\\x{081B}-\\x{0823}\\x{0824}\\x{0825}-\\x{0827}\\x{0828}\\x{0829}-\\x{082D}\\x{0859}-\\x{085B}\\x{08D3}-\\x{08E1}\\x{08E2}\\x{08E3}-\\x{0902}\\x{093A}\\x{093C}\\x{0941}-\\x{0948}\\x{094D}\\x{0951}-\\x{0957}\\x{0962}-\\x{0963}\\x{0971}\\x{0981}\\x{09BC}\\x{09C1}-\\x{09C4}\\x{09CD}\\x{09E2}-\\x{09E3}\\x{09FE}\\x{0A01}-\\x{0A02}\\x{0A3C}\\x{0A41}-\\x{0A42}\\x{0A47}-\\x{0A48}\\x{0A4B}-\\x{0A4D}\\x{0A51}\\x{0A70}-\\x{0A71}\\x{0A75}\\x{0A81}-\\x{0A82}\\x{0ABC}\\x{0AC1}-\\x{0AC5}\\x{0AC7}-\\x{0AC8}\\x{0ACD}\\x{0AE2}-\\x{0AE3}\\x{0AFA}-\\x{0AFF}\\x{0B01}\\x{0B3C}\\x{0B3F}\\x{0B41}-\\x{0B44}\\x{0B4D}\\x{0B56}\\x{0B62}-\\x{0B63}\\x{0B82}\\x{0BC0}\\x{0BCD}\\x{0C00}\\x{0C04}\\x{0C3E}-\\x{0C40}\\x{0C46}-\\x{0C48}\\x{0C4A}-\\x{0C4D}\\x{0C55}-\\x{0C56}\\x{0C62}-\\x{0C63}\\x{0C81}\\x{0CBC}\\x{0CBF}\\x{0CC6}\\x{0CCC}-\\x{0CCD}\\x{0CE2}-\\x{0CE3}\\x{0D00}-\\x{0D01}\\x{0D3B}-\\x{0D3C}\\x{0D41}-\\x{0D44}\\x{0D4D}\\x{0D62}-\\x{0D63}\\x{0DCA}\\x{0DD2}-\\x{0DD4}\\x{0DD6}\\x{0E31}\\x{0E34}-\\x{0E3A}\\x{0E46}\\x{0E47}-\\x{0E4E}\\x{0EB1}\\x{0EB4}-\\x{0EB9}\\x{0EBB}-\\x{0EBC}\\x{0EC6}\\x{0EC8}-\\x{0ECD}\\x{0F18}-\\x{0F19}\\x{0F35}\\x{0F37}\\x{0F39}\\x{0F71}-\\x{0F7E}\\x{0F80}-\\x{0F84}\\x{0F86}-\\x{0F87}\\x{0F8D}-\\x{0F97}\\x{0F99}-\\x{0FBC}\\x{0FC6}\\x{102D}-\\x{1030}\\x{1032}-\\x{1037}\\x{1039}-\\x{103A}\\x{103D}-\\x{103E}\\x{1058}-\\x{1059}\\x{105E}-\\x{1060}\\x{1071}-\\x{1074}\\x{1082}\\x{1085}-\\x{1086}\\x{108D}\\x{109D}\\x{10FC}\\x{135D}-\\x{135F}\\x{1712}-\\x{1714}\\x{1732}-\\x{1734}\\x{1752}-\\x{1753}\\x{1772}-\\x{1773}\\x{17B4}-\\x{17B5}\\x{17B7}-\\x{17BD}\\x{17C6}\\x{17C9}-\\x{17D3}\\x{17D7}\\x{17DD}\\x{180B}-\\x{180D}\\x{180E}\\x{1843}\\x{1885}-\\x{1886}\\x{18A9}\\x{1920}-\\x{1922}\\x{1927}-\\x{1928}\\x{1932}\\x{1939}-\\x{193B}\\x{1A17}-\\x{1A18}\\x{1A1B}\\x{1A56}\\x{1A58}-\\x{1A5E}\\x{1A60}\\x{1A62}\\x{1A65}-\\x{1A6C}\\x{1A73}-\\x{1A7C}\\x{1A7F}\\x{1AA7}\\x{1AB0}-\\x{1ABD}\\x{1ABE}\\x{1B00}-\\x{1B03}\\x{1B34}\\x{1B36}-\\x{1B3A}\\x{1B3C}\\x{1B42}\\x{1B6B}-\\x{1B73}\\x{1B80}-\\x{1B81}\\x{1BA2}-\\x{1BA5}\\x{1BA8}-\\x{1BA9}\\x{1BAB}-\\x{1BAD}\\x{1BE6}\\x{1BE8}-\\x{1BE9}\\x{1BED}\\x{1BEF}-\\x{1BF1}\\x{1C2C}-\\x{1C33}\\x{1C36}-\\x{1C37}\\x{1C78}-\\x{1C7D}\\x{1CD0}-\\x{1CD2}\\x{1CD4}-\\x{1CE0}\\x{1CE2}-\\x{1CE8}\\x{1CED}\\x{1CF4}\\x{1CF8}-\\x{1CF9}\\x{1D2C}-\\x{1D6A}\\x{1D78}\\x{1D9B}-\\x{1DBF}\\x{1DC0}-\\x{1DF9}\\x{1DFB}-\\x{1DFF}\\x{1FBD}\\x{1FBF}-\\x{1FC1}\\x{1FCD}-\\x{1FCF}\\x{1FDD}-\\x{1FDF}\\x{1FED}-\\x{1FEF}\\x{1FFD}-\\x{1FFE}\\x{200B}-\\x{200F}\\x{2018}\\x{2019}\\x{2024}\\x{2027}\\x{202A}-\\x{202E}\\x{2060}-\\x{2064}\\x{2066}-\\x{206F}\\x{2071}\\x{207F}\\x{2090}-\\x{209C}\\x{20D0}-\\x{20DC}\\x{20DD}-\\x{20E0}\\x{20E1}\\x{20E2}-\\x{20E4}\\x{20E5}-\\x{20F0}\\x{2C7C}-\\x{2C7D}\\x{2CEF}-\\x{2CF1}\\x{2D6F}\\x{2D7F}\\x{2DE0}-\\x{2DFF}\\x{2E2F}\\x{3005}\\x{302A}-\\x{302D}\\x{3031}-\\x{3035}\\x{303B}\\x{3099}-\\x{309A}\\x{309B}-\\x{309C}\\x{309D}-\\x{309E}\\x{30FC}-\\x{30FE}\\x{A015}\\x{A4F8}-\\x{A4FD}\\x{A60C}\\x{A66F}\\x{A670}-\\x{A672}\\x{A674}-\\x{A67D}\\x{A67F}\\x{A69C}-\\x{A69D}\\x{A69E}-\\x{A69F}\\x{A6F0}-\\x{A6F1}\\x{A700}-\\x{A716}\\x{A717}-\\x{A71F}\\x{A720}-\\x{A721}\\x{A770}\\x{A788}\\x{A789}-\\x{A78A}\\x{A7F8}-\\x{A7F9}\\x{A802}\\x{A806}\\x{A80B}\\x{A825}-\\x{A826}\\x{A8C4}-\\x{A8C5}\\x{A8E0}-\\x{A8F1}\\x{A8FF}\\x{A926}-\\x{A92D}\\x{A947}-\\x{A951}\\x{A980}-\\x{A982}\\x{A9B3}\\x{A9B6}-\\x{A9B9}\\x{A9BC}\\x{A9CF}\\x{A9E5}\\x{A9E6}\\x{AA29}-\\x{AA2E}\\x{AA31}-\\x{AA32}\\x{AA35}-\\x{AA36}\\x{AA43}\\x{AA4C}\\x{AA70}\\x{AA7C}\\x{AAB0}\\x{AAB2}-\\x{AAB4}\\x{AAB7}-\\x{AAB8}\\x{AABE}-\\x{AABF}\\x{AAC1}\\x{AADD}\\x{AAEC}-\\x{AAED}\\x{AAF3}-\\x{AAF4}\\x{AAF6}\\x{AB5B}\\x{AB5C}-\\x{AB5F}\\x{ABE5}\\x{ABE8}\\x{ABED}\\x{FB1E}\\x{FBB2}-\\x{FBC1}\\x{FE00}-\\x{FE0F}\\x{FE13}\\x{FE20}-\\x{FE2F}\\x{FE52}\\x{FE55}\\x{FEFF}\\x{FF07}\\x{FF0E}\\x{FF1A}\\x{FF3E}\\x{FF40}\\x{FF70}\\x{FF9E}-\\x{FF9F}\\x{FFE3}\\x{FFF9}-\\x{FFFB}\\x{101FD}\\x{102E0}\\x{10376}-\\x{1037A}\\x{10A01}-\\x{10A03}\\x{10A05}-\\x{10A06}\\x{10A0C}-\\x{10A0F}\\x{10A38}-\\x{10A3A}\\x{10A3F}\\x{10AE5}-\\x{10AE6}\\x{10D24}-\\x{10D27}\\x{10F46}-\\x{10F50}\\x{11001}\\x{11038}-\\x{11046}\\x{1107F}-\\x{11081}\\x{110B3}-\\x{110B6}\\x{110B9}-\\x{110BA}\\x{110BD}\\x{110CD}\\x{11100}-\\x{11102}\\x{11127}-\\x{1112B}\\x{1112D}-\\x{11134}\\x{11173}\\x{11180}-\\x{11181}\\x{111B6}-\\x{111BE}\\x{111C9}-\\x{111CC}\\x{1122F}-\\x{11231}\\x{11234}\\x{11236}-\\x{11237}\\x{1123E}\\x{112DF}\\x{112E3}-\\x{112EA}\\x{11300}-\\x{11301}\\x{1133B}-\\x{1133C}\\x{11340}\\x{11366}-\\x{1136C}\\x{11370}-\\x{11374}\\x{11438}-\\x{1143F}\\x{11442}-\\x{11444}\\x{11446}\\x{1145E}\\x{114B3}-\\x{114B8}\\x{114BA}\\x{114BF}-\\x{114C0}\\x{114C2}-\\x{114C3}\\x{115B2}-\\x{115B5}\\x{115BC}-\\x{115BD}\\x{115BF}-\\x{115C0}\\x{115DC}-\\x{115DD}\\x{11633}-\\x{1163A}\\x{1163D}\\x{1163F}-\\x{11640}\\x{116AB}\\x{116AD}\\x{116B0}-\\x{116B5}\\x{116B7}\\x{1171D}-\\x{1171F}\\x{11722}-\\x{11725}\\x{11727}-\\x{1172B}\\x{1182F}-\\x{11837}\\x{11839}-\\x{1183A}\\x{11A01}-\\x{11A0A}\\x{11A33}-\\x{11A38}\\x{11A3B}-\\x{11A3E}\\x{11A47}\\x{11A51}-\\x{11A56}\\x{11A59}-\\x{11A5B}\\x{11A8A}-\\x{11A96}\\x{11A98}-\\x{11A99}\\x{11C30}-\\x{11C36}\\x{11C38}-\\x{11C3D}\\x{11C3F}\\x{11C92}-\\x{11CA7}\\x{11CAA}-\\x{11CB0}\\x{11CB2}-\\x{11CB3}\\x{11CB5}-\\x{11CB6}\\x{11D31}-\\x{11D36}\\x{11D3A}\\x{11D3C}-\\x{11D3D}\\x{11D3F}-\\x{11D45}\\x{11D47}\\x{11D90}-\\x{11D91}\\x{11D95}\\x{11D97}\\x{11EF3}-\\x{11EF4}\\x{16AF0}-\\x{16AF4}\\x{16B30}-\\x{16B36}\\x{16B40}-\\x{16B43}\\x{16F8F}-\\x{16F92}\\x{16F93}-\\x{16F9F}\\x{16FE0}-\\x{16FE1}\\x{1BC9D}-\\x{1BC9E}\\x{1BCA0}-\\x{1BCA3}\\x{1D167}-\\x{1D169}\\x{1D173}-\\x{1D17A}\\x{1D17B}-\\x{1D182}\\x{1D185}-\\x{1D18B}\\x{1D1AA}-\\x{1D1AD}\\x{1D242}-\\x{1D244}\\x{1DA00}-\\x{1DA36}\\x{1DA3B}-\\x{1DA6C}\\x{1DA75}\\x{1DA84}\\x{1DA9B}-\\x{1DA9F}\\x{1DAA1}-\\x{1DAAF}\\x{1E000}-\\x{1E006}\\x{1E008}-\\x{1E018}\\x{1E01B}-\\x{1E021}\\x{1E023}-\\x{1E024}\\x{1E026}-\\x{1E02A}\\x{1E8D0}-\\x{1E8D6}\\x{1E944}-\\x{1E94A}\\x{1F3FB}-\\x{1F3FF}\\x{E0001}\\x{E0020}-\\x{E007F}\\x{E0100}-\\x{E01EF}])(\\pL)(\\pL*+)/u';<?php

return array('A' => 'a', 'B' => 'b', 'C' => 'c', 'D' => 'd', 'E' => 'e', 'F' => 'f', 'G' => 'g', 'H' => 'h', 'I' => 'i', 'J' => 'j', 'K' => 'k', 'L' => 'l', 'M' => 'm', 'N' => 'n', 'O' => 'o', 'P' => 'p', 'Q' => 'q', 'R' => 'r', 'S' => 's', 'T' => 't', 'U' => 'u', 'V' => 'v', 'W' => 'w', 'X' => 'x', 'Y' => 'y', 'Z' => 'z', 'Ã€' => 'Ã ', 'Ã�' => 'Ã¡', 'Ã‚' => 'Ã¢', 'Ãƒ' => 'Ã£', 'Ã„' => 'Ã¤', 'Ã…' => 'Ã¥', 'Ã†' => 'Ã¦', 'Ã‡' => 'Ã§', 'Ãˆ' => 'Ã¨', 'Ã‰' => 'Ã©', 'ÃŠ' => 'Ãª', 'Ã‹' => 'Ã«', 'ÃŒ' => 'Ã¬', 'Ã�' => 'Ã­', 'ÃŽ' => 'Ã®', 'Ã�' => 'Ã¯', 'Ã�' => 'Ã°', 'Ã‘' => 'Ã±', 'Ã’' => 'Ã²', 'Ã“' => 'Ã³', 'Ã”' => 'Ã´', 'Ã•' => 'Ãµ', 'Ã–' => 'Ã¶', 'Ã˜' => 'Ã¸', 'Ã™' => 'Ã¹', 'Ãš' => 'Ãº', 'Ã›' => 'Ã»', 'Ãœ' => 'Ã¼', 'Ã�' => 'Ã½', 'Ãž' => 'Ã¾', 'Ä€' => 'Ä�', 'Ä‚' => 'Äƒ', 'Ä„' => 'Ä…', 'Ä†' => 'Ä‡', 'Äˆ' => 'Ä‰', 'ÄŠ' => 'Ä‹', 'ÄŒ' => 'Ä�', 'ÄŽ' => 'Ä�', 'Ä�' => 'Ä‘', 'Ä’' => 'Ä“', 'Ä”' => 'Ä•', 'Ä–' => 'Ä—', 'Ä˜' => 'Ä™', 'Äš' => 'Ä›', 'Äœ' => 'Ä�', 'Äž' => 'ÄŸ', 'Ä ' => 'Ä¡', 'Ä¢' => 'Ä£', 'Ä¤' => 'Ä¥', 'Ä¦' => 'Ä§', 'Ä¨' => 'Ä©', 'Äª' => 'Ä«', 'Ä¬' => 'Ä­', 'Ä®' => 'Ä¯', 'Ä°' => 'iÌ‡', 'Ä²' => 'Ä³', 'Ä´' => 'Äµ', 'Ä¶' => 'Ä·', 'Ä¹' => 'Äº', 'Ä»' => 'Ä¼', 'Ä½' => 'Ä¾', 'Ä¿' => 'Å€', 'Å�' => 'Å‚', 'Åƒ' => 'Å„', 'Å…' => 'Å†', 'Å‡' => 'Åˆ', 'ÅŠ' => 'Å‹', 'ÅŒ' => 'Å�', 'ÅŽ' => 'Å�', 'Å�' => 'Å‘', 'Å’' => 'Å“', 'Å”' => 'Å•', 'Å–' => 'Å—', 'Å˜' => 'Å™', 'Åš' => 'Å›', 'Åœ' => 'Å�', 'Åž' => 'ÅŸ', 'Å ' => 'Å¡', 'Å¢' => 'Å£', 'Å¤' => 'Å¥', 'Å¦' => 'Å§', 'Å¨' => 'Å©', 'Åª' => 'Å«', 'Å¬' => 'Å­', 'Å®' => 'Å¯', 'Å°' => 'Å±', 'Å²' => 'Å³', 'Å´' => 'Åµ', 'Å¶' => 'Å·', 'Å¸' => 'Ã¿', 'Å¹' => 'Åº', 'Å»' => 'Å¼', 'Å½' => 'Å¾', 'Æ�' => 'É“', 'Æ‚' => 'Æƒ', 'Æ„' => 'Æ…', 'Æ†' => 'É”', 'Æ‡' => 'Æˆ', 'Æ‰' => 'É–', 'ÆŠ' => 'É—', 'Æ‹' => 'ÆŒ', 'ÆŽ' => 'Ç�', 'Æ�' => 'É™', 'Æ�' => 'É›', 'Æ‘' => 'Æ’', 'Æ“' => 'É ', 'Æ”' => 'É£', 'Æ–' => 'É©', 'Æ—' => 'É¨', 'Æ˜' => 'Æ™', 'Æœ' => 'É¯', 'Æ�' => 'É²', 'ÆŸ' => 'Éµ', 'Æ ' => 'Æ¡', 'Æ¢' => 'Æ£', 'Æ¤' => 'Æ¥', 'Æ¦' => 'Ê€', 'Æ§' => 'Æ¨', 'Æ©' => 'Êƒ', 'Æ¬' => 'Æ­', 'Æ®' => 'Êˆ', 'Æ¯' => 'Æ°', 'Æ±' => 'ÊŠ', 'Æ²' => 'Ê‹', 'Æ³' => 'Æ´', 'Æµ' => 'Æ¶', 'Æ·' => 'Ê’', 'Æ¸' => 'Æ¹', 'Æ¼' => 'Æ½', 'Ç„' => 'Ç†', 'Ç…' => 'Ç†', 'Ç‡' => 'Ç‰', 'Çˆ' => 'Ç‰', 'ÇŠ' => 'ÇŒ', 'Ç‹' => 'ÇŒ', 'Ç�' => 'ÇŽ', 'Ç�' => 'Ç�', 'Ç‘' => 'Ç’', 'Ç“' => 'Ç”', 'Ç•' => 'Ç–', 'Ç—' => 'Ç˜', 'Ç™' => 'Çš', 'Ç›' => 'Çœ', 'Çž' => 'ÇŸ', 'Ç ' => 'Ç¡', 'Ç¢' => 'Ç£', 'Ç¤' => 'Ç¥', 'Ç¦' => 'Ç§', 'Ç¨' => 'Ç©', 'Çª' => 'Ç«', 'Ç¬' => 'Ç­', 'Ç®' => 'Ç¯', 'Ç±' => 'Ç³', 'Ç²' => 'Ç³', 'Ç´' => 'Çµ', 'Ç¶' => 'Æ•', 'Ç·' => 'Æ¿', 'Ç¸' => 'Ç¹', 'Çº' => 'Ç»', 'Ç¼' => 'Ç½', 'Ç¾' => 'Ç¿', 'È€' => 'È�', 'È‚' => 'Èƒ', 'È„' => 'È…', 'È†' => 'È‡', 'Èˆ' => 'È‰', 'ÈŠ' => 'È‹', 'ÈŒ' => 'È�', 'ÈŽ' => 'È�', 'È�' => 'È‘', 'È’' => 'È“', 'È”' => 'È•', 'È–' => 'È—', 'È˜' => 'È™', 'Èš' => 'È›', 'Èœ' => 'È�', 'Èž' => 'ÈŸ', 'È ' => 'Æž', 'È¢' => 'È£', 'È¤' => 'È¥', 'È¦' => 'È§', 'È¨' => 'È©', 'Èª' => 'È«', 'È¬' => 'È­', 'È®' => 'È¯', 'È°' => 'È±', 'È²' => 'È³', 'Èº' => 'â±¥', 'È»' => 'È¼', 'È½' => 'Æš', 'È¾' => 'â±¦', 'É�' => 'É‚', 'Éƒ' => 'Æ€', 'É„' => 'Ê‰', 'É…' => 'ÊŒ', 'É†' => 'É‡', 'Éˆ' => 'É‰', 'ÉŠ' => 'É‹', 'ÉŒ' => 'É�', 'ÉŽ' => 'É�', 'Í°' => 'Í±', 'Í²' => 'Í³', 'Í¶' => 'Í·', 'Í¿' => 'Ï³', 'Î†' => 'Î¬', 'Îˆ' => 'Î­', 'Î‰' => 'Î®', 'ÎŠ' => 'Î¯', 'ÎŒ' => 'ÏŒ', 'ÎŽ' => 'Ï�', 'Î�' => 'ÏŽ', 'Î‘' => 'Î±', 'Î’' => 'Î²', 'Î“' => 'Î³', 'Î”' => 'Î´', 'Î•' => 'Îµ', 'Î–' => 'Î¶', 'Î—' => 'Î·', 'Î˜' => 'Î¸', 'Î™' => 'Î¹', 'Îš' => 'Îº', 'Î›' => 'Î»', 'Îœ' => 'Î¼', 'Î�' => 'Î½', 'Îž' => 'Î¾', 'ÎŸ' => 'Î¿', 'Î ' => 'Ï€', 'Î¡' => 'Ï�', 'Î£' => 'Ïƒ', 'Î¤' => 'Ï„', 'Î¥' => 'Ï…', 'Î¦' => 'Ï†', 'Î§' => 'Ï‡', 'Î¨' => 'Ïˆ', 'Î©' => 'Ï‰', 'Îª' => 'ÏŠ', 'Î«' => 'Ï‹', 'Ï�' => 'Ï—', 'Ï˜' => 'Ï™', 'Ïš' => 'Ï›', 'Ïœ' => 'Ï�', 'Ïž' => 'ÏŸ', 'Ï ' => 'Ï¡', 'Ï¢' => 'Ï£', 'Ï¤' => 'Ï¥', 'Ï¦' => 'Ï§', 'Ï¨' => 'Ï©', 'Ïª' => 'Ï«', 'Ï¬' => 'Ï­', 'Ï®' => 'Ï¯', 'Ï´' => 'Î¸', 'Ï·' => 'Ï¸', 'Ï¹' => 'Ï²', 'Ïº' => 'Ï»', 'Ï½' => 'Í»', 'Ï¾' => 'Í¼', 'Ï¿' => 'Í½', 'Ð€' => 'Ñ�', 'Ð�' => 'Ñ‘', 'Ð‚' => 'Ñ’', 'Ðƒ' => 'Ñ“', 'Ð„' => 'Ñ”', 'Ð…' => 'Ñ•', 'Ð†' => 'Ñ–', 'Ð‡' => 'Ñ—', 'Ðˆ' => 'Ñ˜', 'Ð‰' => 'Ñ™', 'ÐŠ' => 'Ñš', 'Ð‹' => 'Ñ›', 'ÐŒ' => 'Ñœ', 'Ð�' => 'Ñ�', 'ÐŽ' => 'Ñž', 'Ð�' => 'ÑŸ', 'Ð�' => 'Ð°', 'Ð‘' => 'Ð±', 'Ð’' => 'Ð²', 'Ð“' => 'Ð³', 'Ð”' => 'Ð´', 'Ð•' => 'Ðµ', 'Ð–' => 'Ð¶', 'Ð—' => 'Ð·', 'Ð˜' => 'Ð¸', 'Ð™' => 'Ð¹', 'Ðš' => 'Ðº', 'Ð›' => 'Ð»', 'Ðœ' => 'Ð¼', 'Ð�' => 'Ð½', 'Ðž' => 'Ð¾', 'ÐŸ' => 'Ð¿', 'Ð ' => 'Ñ€', 'Ð¡' => 'Ñ�', 'Ð¢' => 'Ñ‚', 'Ð£' => 'Ñƒ', 'Ð¤' => 'Ñ„', 'Ð¥' => 'Ñ…', 'Ð¦' => 'Ñ†', 'Ð§' => 'Ñ‡', 'Ð¨' => 'Ñˆ', 'Ð©' => 'Ñ‰', 'Ðª' => 'ÑŠ', 'Ð«' => 'Ñ‹', 'Ð¬' => 'ÑŒ', 'Ð­' => 'Ñ�', 'Ð®' => 'ÑŽ', 'Ð¯' => 'Ñ�', 'Ñ ' => 'Ñ¡', 'Ñ¢' => 'Ñ£', 'Ñ¤' => 'Ñ¥', 'Ñ¦' => 'Ñ§', 'Ñ¨' => 'Ñ©', 'Ñª' => 'Ñ«', 'Ñ¬' => 'Ñ­', 'Ñ®' => 'Ñ¯', 'Ñ°' => 'Ñ±', 'Ñ²' => 'Ñ³', 'Ñ´' => 'Ñµ', 'Ñ¶' => 'Ñ·', 'Ñ¸' => 'Ñ¹', 'Ñº' => 'Ñ»', 'Ñ¼' => 'Ñ½', 'Ñ¾' => 'Ñ¿', 'Ò€' => 'Ò�', 'ÒŠ' => 'Ò‹', 'ÒŒ' => 'Ò�', 'ÒŽ' => 'Ò�', 'Ò�' => 'Ò‘', 'Ò’' => 'Ò“', 'Ò”' => 'Ò•', 'Ò–' => 'Ò—', 'Ò˜' => 'Ò™', 'Òš' => 'Ò›', 'Òœ' => 'Ò�', 'Òž' => 'ÒŸ', 'Ò ' => 'Ò¡', 'Ò¢' => 'Ò£', 'Ò¤' => 'Ò¥', 'Ò¦' => 'Ò§', 'Ò¨' => 'Ò©', 'Òª' => 'Ò«', 'Ò¬' => 'Ò­', 'Ò®' => 'Ò¯', 'Ò°' => 'Ò±', 'Ò²' => 'Ò³', 'Ò´' => 'Òµ', 'Ò¶' => 'Ò·', 'Ò¸' => 'Ò¹', 'Òº' => 'Ò»', 'Ò¼' => 'Ò½', 'Ò¾' => 'Ò¿', 'Ó€' => 'Ó�', 'Ó�' => 'Ó‚', 'Óƒ' => 'Ó„', 'Ó…' => 'Ó†', 'Ó‡' => 'Óˆ', 'Ó‰' => 'ÓŠ', 'Ó‹' => 'ÓŒ', 'Ó�' => 'ÓŽ', 'Ó�' => 'Ó‘', 'Ó’' => 'Ó“', 'Ó”' => 'Ó•', 'Ó–' => 'Ó—', 'Ó˜' => 'Ó™', 'Óš' => 'Ó›', 'Óœ' => 'Ó�', 'Óž' => 'ÓŸ', 'Ó ' => 'Ó¡', 'Ó¢' => 'Ó£', 'Ó¤' => 'Ó¥', 'Ó¦' => 'Ó§', 'Ó¨' => 'Ó©', 'Óª' => 'Ó«', 'Ó¬' => 'Ó­', 'Ó®' => 'Ó¯', 'Ó°' => 'Ó±', 'Ó²' => 'Ó³', 'Ó´' => 'Óµ', 'Ó¶' => 'Ó·', 'Ó¸' => 'Ó¹', 'Óº' => 'Ó»', 'Ó¼' => 'Ó½', 'Ó¾' => 'Ó¿', 'Ô€' => 'Ô�', 'Ô‚' => 'Ôƒ', 'Ô„' => 'Ô…', 'Ô†' => 'Ô‡', 'Ôˆ' => 'Ô‰', 'ÔŠ' => 'Ô‹', 'ÔŒ' => 'Ô�', 'ÔŽ' => 'Ô�', 'Ô�' => 'Ô‘', 'Ô’' => 'Ô“', 'Ô”' => 'Ô•', 'Ô–' => 'Ô—', 'Ô˜' => 'Ô™', 'Ôš' => 'Ô›', 'Ôœ' => 'Ô�', 'Ôž' => 'ÔŸ', 'Ô ' => 'Ô¡', 'Ô¢' => 'Ô£', 'Ô¤' => 'Ô¥', 'Ô¦' => 'Ô§', 'Ô¨' => 'Ô©', 'Ôª' => 'Ô«', 'Ô¬' => 'Ô­', 'Ô®' => 'Ô¯', 'Ô±' => 'Õ¡', 'Ô²' => 'Õ¢', 'Ô³' => 'Õ£', 'Ô´' => 'Õ¤', 'Ôµ' => 'Õ¥', 'Ô¶' => 'Õ¦', 'Ô·' => 'Õ§', 'Ô¸' => 'Õ¨', 'Ô¹' => 'Õ©', 'Ôº' => 'Õª', 'Ô»' => 'Õ«', 'Ô¼' => 'Õ¬', 'Ô½' => 'Õ­', 'Ô¾' => 'Õ®', 'Ô¿' => 'Õ¯', 'Õ€' => 'Õ°', 'Õ�' => 'Õ±', 'Õ‚' => 'Õ²', 'Õƒ' => 'Õ³', 'Õ„' => 'Õ´', 'Õ…' => 'Õµ', 'Õ†' => 'Õ¶', 'Õ‡' => 'Õ·', 'Õˆ' => 'Õ¸', 'Õ‰' => 'Õ¹', 'ÕŠ' => 'Õº', 'Õ‹' => 'Õ»', 'ÕŒ' => 'Õ¼', 'Õ�' => 'Õ½', 'ÕŽ' => 'Õ¾', 'Õ�' => 'Õ¿', 'Õ�' => 'Ö€', 'Õ‘' => 'Ö�', 'Õ’' => 'Ö‚', 'Õ“' => 'Öƒ', 'Õ”' => 'Ö„', 'Õ•' => 'Ö…', 'Õ–' => 'Ö†', 'á‚ ' => 'â´€', 'á‚¡' => 'â´�', 'á‚¢' => 'â´‚', 'á‚£' => 'â´ƒ', 'á‚¤' => 'â´„', 'á‚¥' => 'â´…', 'á‚¦' => 'â´†', 'á‚§' => 'â´‡', 'á‚¨' => 'â´ˆ', 'á‚©' => 'â´‰', 'á‚ª' => 'â´Š', 'á‚«' => 'â´‹', 'á‚¬' => 'â´Œ', 'á‚­' => 'â´�', 'á‚®' => 'â´Ž', 'á‚¯' => 'â´�', 'á‚°' => 'â´�', 'á‚±' => 'â´‘', 'á‚²' => 'â´’', 'á‚³' => 'â´“', 'á‚´' => 'â´”', 'á‚µ' => 'â´•', 'á‚¶' => 'â´–', 'á‚·' => 'â´—', 'á‚¸' => 'â´˜', 'á‚¹' => 'â´™', 'á‚º' => 'â´š', 'á‚»' => 'â´›', 'á‚¼' => 'â´œ', 'á‚½' => 'â´�', 'á‚¾' => 'â´ž', 'á‚¿' => 'â´Ÿ', 'áƒ€' => 'â´ ', 'áƒ�' => 'â´¡', 'áƒ‚' => 'â´¢', 'áƒƒ' => 'â´£', 'áƒ„' => 'â´¤', 'áƒ…' => 'â´¥', 'áƒ‡' => 'â´§', 'áƒ�' => 'â´­', 'áŽ ' => 'ê­°', 'áŽ¡' => 'ê­±', 'áŽ¢' => 'ê­²', 'áŽ£' => 'ê­³', 'áŽ¤' => 'ê­´', 'áŽ¥' => 'ê­µ', 'áŽ¦' => 'ê­¶', 'áŽ§' => 'ê­·', 'áŽ¨' => 'ê­¸', 'áŽ©' => 'ê­¹', 'áŽª' => 'ê­º', 'áŽ«' => 'ê­»', 'áŽ¬' => 'ê­¼', 'áŽ­' => 'ê­½', 'áŽ®' => 'ê­¾', 'áŽ¯' => 'ê­¿', 'áŽ°' => 'ê®€', 'áŽ±' => 'ê®�', 'áŽ²' => 'ê®‚', 'áŽ³' => 'ê®ƒ', 'áŽ´' => 'ê®„', 'áŽµ' => 'ê®…', 'áŽ¶' => 'ê®†', 'áŽ·' => 'ê®‡', 'áŽ¸' => 'ê®ˆ', 'áŽ¹' => 'ê®‰', 'áŽº' => 'ê®Š', 'áŽ»' => 'ê®‹', 'áŽ¼' => 'ê®Œ', 'áŽ½' => 'ê®�', 'áŽ¾' => 'ê®Ž', 'áŽ¿' => 'ê®�', 'á�€' => 'ê®�', 'á��' => 'ê®‘', 'á�‚' => 'ê®’', 'á�ƒ' => 'ê®“', 'á�„' => 'ê®”', 'á�…' => 'ê®•', 'á�†' => 'ê®–', 'á�‡' => 'ê®—', 'á�ˆ' => 'ê®˜', 'á�‰' => 'ê®™', 'á�Š' => 'ê®š', 'á�‹' => 'ê®›', 'á�Œ' => 'ê®œ', 'á��' => 'ê®�', 'á�Ž' => 'ê®ž', 'á��' => 'ê®Ÿ', 'á��' => 'ê® ', 'á�‘' => 'ê®¡', 'á�’' => 'ê®¢', 'á�“' => 'ê®£', 'á�”' => 'ê®¤', 'á�•' => 'ê®¥', 'á�–' => 'ê®¦', 'á�—' => 'ê®§', 'á�˜' => 'ê®¨', 'á�™' => 'ê®©', 'á�š' => 'ê®ª', 'á�›' => 'ê®«', 'á�œ' => 'ê®¬', 'á��' => 'ê®­', 'á�ž' => 'ê®®', 'á�Ÿ' => 'ê®¯', 'á� ' => 'ê®°', 'á�¡' => 'ê®±', 'á�¢' => 'ê®²', 'á�£' => 'ê®³', 'á�¤' => 'ê®´', 'á�¥' => 'ê®µ', 'á�¦' => 'ê®¶', 'á�§' => 'ê®·', 'á�¨' => 'ê®¸', 'á�©' => 'ê®¹', 'á�ª' => 'ê®º', 'á�«' => 'ê®»', 'á�¬' => 'ê®¼', 'á�­' => 'ê®½', 'á�®' => 'ê®¾', 'á�¯' => 'ê®¿', 'á�°' => 'á�¸', 'á�±' => 'á�¹', 'á�²' => 'á�º', 'á�³' => 'á�»', 'á�´' => 'á�¼', 'á�µ' => 'á�½', 'á²�' => 'áƒ�', 'á²‘' => 'áƒ‘', 'á²’' => 'áƒ’', 'á²“' => 'áƒ“', 'á²”' => 'áƒ”', 'á²•' => 'áƒ•', 'á²–' => 'áƒ–', 'á²—' => 'áƒ—', 'á²˜' => 'áƒ˜', 'á²™' => 'áƒ™', 'á²š' => 'áƒš', 'á²›' => 'áƒ›', 'á²œ' => 'áƒœ', 'á²�' => 'áƒ�', 'á²ž' => 'áƒž', 'á²Ÿ' => 'áƒŸ', 'á² ' => 'áƒ ', 'á²¡' => 'áƒ¡', 'á²¢' => 'áƒ¢', 'á²£' => 'áƒ£', 'á²¤' => 'áƒ¤', 'á²¥' => 'áƒ¥', 'á²¦' => 'áƒ¦', 'á²§' => 'áƒ§', 'á²¨' => 'áƒ¨', 'á²©' => 'áƒ©', 'á²ª' => 'áƒª', 'á²«' => 'áƒ«', 'á²¬' => 'áƒ¬', 'á²­' => 'áƒ­', 'á²®' => 'áƒ®', 'á²¯' => 'áƒ¯', 'á²°' => 'áƒ°', 'á²±' => 'áƒ±', 'á²²' => 'áƒ²', 'á²³' => 'áƒ³', 'á²´' => 'áƒ´', 'á²µ' => 'áƒµ', 'á²¶' => 'áƒ¶', 'á²·' => 'áƒ·', 'á²¸' => 'áƒ¸', 'á²¹' => 'áƒ¹', 'á²º' => 'áƒº', 'á²½' => 'áƒ½', 'á²¾' => 'áƒ¾', 'á²¿' => 'áƒ¿', 'á¸€' => 'á¸�', 'á¸‚' => 'á¸ƒ', 'á¸„' => 'á¸…', 'á¸†' => 'á¸‡', 'á¸ˆ' => 'á¸‰', 'á¸Š' => 'á¸‹', 'á¸Œ' => 'á¸�', 'á¸Ž' => 'á¸�', 'á¸�' => 'á¸‘', 'á¸’' => 'á¸“', 'á¸”' => 'á¸•', 'á¸–' => 'á¸—', 'á¸˜' => 'á¸™', 'á¸š' => 'á¸›', 'á¸œ' => 'á¸�', 'á¸ž' => 'á¸Ÿ', 'á¸ ' => 'á¸¡', 'á¸¢' => 'á¸£', 'á¸¤' => 'á¸¥', 'á¸¦' => 'á¸§', 'á¸¨' => 'á¸©', 'á¸ª' => 'á¸«', 'á¸¬' => 'á¸­', 'á¸®' => 'á¸¯', 'á¸°' => 'á¸±', 'á¸²' => 'á¸³', 'á¸´' => 'á¸µ', 'á¸¶' => 'á¸·', 'á¸¸' => 'á¸¹', 'á¸º' => 'á¸»', 'á¸¼' => 'á¸½', 'á¸¾' => 'á¸¿', 'á¹€' => 'á¹�', 'á¹‚' => 'á¹ƒ', 'á¹„' => 'á¹…', 'á¹†' => 'á¹‡', 'á¹ˆ' => 'á¹‰', 'á¹Š' => 'á¹‹', 'á¹Œ' => 'á¹�', 'á¹Ž' => 'á¹�', 'á¹�' => 'á¹‘', 'á¹’' => 'á¹“', 'á¹”' => 'á¹•', 'á¹–' => 'á¹—', 'á¹˜' => 'á¹™', 'á¹š' => 'á¹›', 'á¹œ' => 'á¹�', 'á¹ž' => 'á¹Ÿ', 'á¹ ' => 'á¹¡', 'á¹¢' => 'á¹£', 'á¹¤' => 'á¹¥', 'á¹¦' => 'á¹§', 'á¹¨' => 'á¹©', 'á¹ª' => 'á¹«', 'á¹¬' => 'á¹­', 'á¹®' => 'á¹¯', 'á¹°' => 'á¹±', 'á¹²' => 'á¹³', 'á¹´' => 'á¹µ', 'á¹¶' => 'á¹·', 'á¹¸' => 'á¹¹', 'á¹º' => 'á¹»', 'á¹¼' => 'á¹½', 'á¹¾' => 'á¹¿', 'áº€' => 'áº�', 'áº‚' => 'áºƒ', 'áº„' => 'áº…', 'áº†' => 'áº‡', 'áºˆ' => 'áº‰', 'áºŠ' => 'áº‹', 'áºŒ' => 'áº�', 'áºŽ' => 'áº�', 'áº�' => 'áº‘', 'áº’' => 'áº“', 'áº”' => 'áº•', 'áºž' => 'ÃŸ', 'áº ' => 'áº¡', 'áº¢' => 'áº£', 'áº¤' => 'áº¥', 'áº¦' => 'áº§', 'áº¨' => 'áº©', 'áºª' => 'áº«', 'áº¬' => 'áº­', 'áº®' => 'áº¯', 'áº°' => 'áº±', 'áº²' => 'áº³', 'áº´' => 'áºµ', 'áº¶' => 'áº·', 'áº¸' => 'áº¹', 'áºº' => 'áº»', 'áº¼' => 'áº½', 'áº¾' => 'áº¿', 'á»€' => 'á»�', 'á»‚' => 'á»ƒ', 'á»„' => 'á»…', 'á»†' => 'á»‡', 'á»ˆ' => 'á»‰', 'á»Š' => 'á»‹', 'á»Œ' => 'á»�', 'á»Ž' => 'á»�', 'á»�' => 'á»‘', 'á»’' => 'á»“', 'á»”' => 'á»•', 'á»–' => 'á»—', 'á»˜' => 'á»™', 'á»š' => 'á»›', 'á»œ' => 'á»�', 'á»ž' => 'á»Ÿ', 'á» ' => 'á»¡', 'á»¢' => 'á»£', 'á»¤' => 'á»¥', 'á»¦' => 'á»§', 'á»¨' => 'á»©', 'á»ª' => 'á»«', 'á»¬' => 'á»­', 'á»®' => 'á»¯', 'á»°' => 'á»±', 'á»²' => 'á»³', 'á»´' => 'á»µ', 'á»¶' => 'á»·', 'á»¸' => 'á»¹', 'á»º' => 'á»»', 'á»¼' => 'á»½', 'á»¾' => 'á»¿', 'á¼ˆ' => 'á¼€', 'á¼‰' => 'á¼�', 'á¼Š' => 'á¼‚', 'á¼‹' => 'á¼ƒ', 'á¼Œ' => 'á¼„', 'á¼�' => 'á¼…', 'á¼Ž' => 'á¼†', 'á¼�' => 'á¼‡', 'á¼˜' => 'á¼�', 'á¼™' => 'á¼‘', 'á¼š' => 'á¼’', 'á¼›' => 'á¼“', 'á¼œ' => 'á¼”', 'á¼�' => 'á¼•', 'á¼¨' => 'á¼ ', 'á¼©' => 'á¼¡', 'á¼ª' => 'á¼¢', 'á¼«' => 'á¼£', 'á¼¬' => 'á¼¤', 'á¼­' => 'á¼¥', 'á¼®' => 'á¼¦', 'á¼¯' => 'á¼§', 'á¼¸' => 'á¼°', 'á¼¹' => 'á¼±', 'á¼º' => 'á¼²', 'á¼»' => 'á¼³', 'á¼¼' => 'á¼´', 'á¼½' => 'á¼µ', 'á¼¾' => 'á¼¶', 'á¼¿' => 'á¼·', 'á½ˆ' => 'á½€', 'á½‰' => 'á½�', 'á½Š' => 'á½‚', 'á½‹' => 'á½ƒ', 'á½Œ' => 'á½„', 'á½�' => 'á½…', 'á½™' => 'á½‘', 'á½›' => 'á½“', 'á½�' => 'á½•', 'á½Ÿ' => 'á½—', 'á½¨' => 'á½ ', 'á½©' => 'á½¡', 'á½ª' => 'á½¢', 'á½«' => 'á½£', 'á½¬' => 'á½¤', 'á½­' => 'á½¥', 'á½®' => 'á½¦', 'á½¯' => 'á½§', 'á¾ˆ' => 'á¾€', 'á¾‰' => 'á¾�', 'á¾Š' => 'á¾‚', 'á¾‹' => 'á¾ƒ', 'á¾Œ' => 'á¾„', 'á¾�' => 'á¾…', 'á¾Ž' => 'á¾†', 'á¾�' => 'á¾‡', 'á¾˜' => 'á¾�', 'á¾™' => 'á¾‘', 'á¾š' => 'á¾’', 'á¾›' => 'á¾“', 'á¾œ' => 'á¾”', 'á¾�' => 'á¾•', 'á¾ž' => 'á¾–', 'á¾Ÿ' => 'á¾—', 'á¾¨' => 'á¾ ', 'á¾©' => 'á¾¡', 'á¾ª' => 'á¾¢', 'á¾«' => 'á¾£', 'á¾¬' => 'á¾¤', 'á¾­' => 'á¾¥', 'á¾®' => 'á¾¦', 'á¾¯' => 'á¾§', 'á¾¸' => 'á¾°', 'á¾¹' => 'á¾±', 'á¾º' => 'á½°', 'á¾»' => 'á½±', 'á¾¼' => 'á¾³', 'á¿ˆ' => 'á½²', 'á¿‰' => 'á½³', 'á¿Š' => 'á½´', 'á¿‹' => 'á½µ', 'á¿Œ' => 'á¿ƒ', 'á¿˜' => 'á¿�', 'á¿™' => 'á¿‘', 'á¿š' => 'á½¶', 'á¿›' => 'á½·', 'á¿¨' => 'á¿ ', 'á¿©' => 'á¿¡', 'á¿ª' => 'á½º', 'á¿«' => 'á½»', 'á¿¬' => 'á¿¥', 'á¿¸' => 'á½¸', 'á¿¹' => 'á½¹', 'á¿º' => 'á½¼', 'á¿»' => 'á½½', 'á¿¼' => 'á¿³', 'â„¦' => 'Ï‰', 'â„ª' => 'k', 'â„«' => 'Ã¥', 'â„²' => 'â…Ž', 'â… ' => 'â…°', 'â…¡' => 'â…±', 'â…¢' => 'â…²', 'â…£' => 'â…³', 'â…¤' => 'â…´', 'â…¥' => 'â…µ', 'â…¦' => 'â…¶', 'â…§' => 'â…·', 'â…¨' => 'â…¸', 'â…©' => 'â…¹', 'â…ª' => 'â…º', 'â…«' => 'â…»', 'â…¬' => 'â…¼', 'â…­' => 'â…½', 'â…®' => 'â…¾', 'â…¯' => 'â…¿', 'â†ƒ' => 'â†„', 'â’¶' => 'â“�', 'â’·' => 'â“‘', 'â’¸' => 'â“’', 'â’¹' => 'â““', 'â’º' => 'â“”', 'â’»' => 'â“•', 'â’¼' => 'â“–', 'â’½' => 'â“—', 'â’¾' => 'â“˜', 'â’¿' => 'â“™', 'â“€' => 'â“š', 'â“�' => 'â“›', 'â“‚' => 'â“œ', 'â“ƒ' => 'â“�', 'â“„' => 'â“ž', 'â“…' => 'â“Ÿ', 'â“†' => 'â“ ', 'â“‡' => 'â“¡', 'â“ˆ' => 'â“¢', 'â“‰' => 'â“£', 'â“Š' => 'â“¤', 'â“‹' => 'â“¥', 'â“Œ' => 'â“¦', 'â“�' => 'â“§', 'â“Ž' => 'â“¨', 'â“�' => 'â“©', 'â°€' => 'â°°', 'â°�' => 'â°±', 'â°‚' => 'â°²', 'â°ƒ' => 'â°³', 'â°„' => 'â°´', 'â°…' => 'â°µ', 'â°†' => 'â°¶', 'â°‡' => 'â°·', 'â°ˆ' => 'â°¸', 'â°‰' => 'â°¹', 'â°Š' => 'â°º', 'â°‹' => 'â°»', 'â°Œ' => 'â°¼', 'â°�' => 'â°½', 'â°Ž' => 'â°¾', 'â°�' => 'â°¿', 'â°�' => 'â±€', 'â°‘' => 'â±�', 'â°’' => 'â±‚', 'â°“' => 'â±ƒ', 'â°”' => 'â±„', 'â°•' => 'â±…', 'â°–' => 'â±†', 'â°—' => 'â±‡', 'â°˜' => 'â±ˆ', 'â°™' => 'â±‰', 'â°š' => 'â±Š', 'â°›' => 'â±‹', 'â°œ' => 'â±Œ', 'â°�' => 'â±�', 'â°ž' => 'â±Ž', 'â°Ÿ' => 'â±�', 'â° ' => 'â±�', 'â°¡' => 'â±‘', 'â°¢' => 'â±’', 'â°£' => 'â±“', 'â°¤' => 'â±”', 'â°¥' => 'â±•', 'â°¦' => 'â±–', 'â°§' => 'â±—', 'â°¨' => 'â±˜', 'â°©' => 'â±™', 'â°ª' => 'â±š', 'â°«' => 'â±›', 'â°¬' => 'â±œ', 'â°­' => 'â±�', 'â°®' => 'â±ž', 'â± ' => 'â±¡', 'â±¢' => 'É«', 'â±£' => 'áµ½', 'â±¤' => 'É½', 'â±§' => 'â±¨', 'â±©' => 'â±ª', 'â±«' => 'â±¬', 'â±­' => 'É‘', 'â±®' => 'É±', 'â±¯' => 'É�', 'â±°' => 'É’', 'â±²' => 'â±³', 'â±µ' => 'â±¶', 'â±¾' => 'È¿', 'â±¿' => 'É€', 'â²€' => 'â²�', 'â²‚' => 'â²ƒ', 'â²„' => 'â²…', 'â²†' => 'â²‡', 'â²ˆ' => 'â²‰', 'â²Š' => 'â²‹', 'â²Œ' => 'â²�', 'â²Ž' => 'â²�', 'â²�' => 'â²‘', 'â²’' => 'â²“', 'â²”' => 'â²•', 'â²–' => 'â²—', 'â²˜' => 'â²™', 'â²š' => 'â²›', 'â²œ' => 'â²�', 'â²ž' => 'â²Ÿ', 'â² ' => 'â²¡', 'â²¢' => 'â²£', 'â²¤' => 'â²¥', 'â²¦' => 'â²§', 'â²¨' => 'â²©', 'â²ª' => 'â²«', 'â²¬' => 'â²­', 'â²®' => 'â²¯', 'â²°' => 'â²±', 'â²²' => 'â²³', 'â²´' => 'â²µ', 'â²¶' => 'â²·', 'â²¸' => 'â²¹', 'â²º' => 'â²»', 'â²¼' => 'â²½', 'â²¾' => 'â²¿', 'â³€' => 'â³�', 'â³‚' => 'â³ƒ', 'â³„' => 'â³…', 'â³†' => 'â³‡', 'â³ˆ' => 'â³‰', 'â³Š' => 'â³‹', 'â³Œ' => 'â³�', 'â³Ž' => 'â³�', 'â³�' => 'â³‘', 'â³’' => 'â³“', 'â³”' => 'â³•', 'â³–' => 'â³—', 'â³˜' => 'â³™', 'â³š' => 'â³›', 'â³œ' => 'â³�', 'â³ž' => 'â³Ÿ', 'â³ ' => 'â³¡', 'â³¢' => 'â³£', 'â³«' => 'â³¬', 'â³­' => 'â³®', 'â³²' => 'â³³', 'ê™€' => 'ê™�', 'ê™‚' => 'ê™ƒ', 'ê™„' => 'ê™…', 'ê™†' => 'ê™‡', 'ê™ˆ' => 'ê™‰', 'ê™Š' => 'ê™‹', 'ê™Œ' => 'ê™�', 'ê™Ž' => 'ê™�', 'ê™�' => 'ê™‘', 'ê™’' => 'ê™“', 'ê™”' => 'ê™•', 'ê™–' => 'ê™—', 'ê™˜' => 'ê™™', 'ê™š' => 'ê™›', 'ê™œ' => 'ê™�', 'ê™ž' => 'ê™Ÿ', 'ê™ ' => 'ê™¡', 'ê™¢' => 'ê™£', 'ê™¤' => 'ê™¥', 'ê™¦' => 'ê™§', 'ê™¨' => 'ê™©', 'ê™ª' => 'ê™«', 'ê™¬' => 'ê™­', 'êš€' => 'êš�', 'êš‚' => 'êšƒ', 'êš„' => 'êš…', 'êš†' => 'êš‡', 'êšˆ' => 'êš‰', 'êšŠ' => 'êš‹', 'êšŒ' => 'êš�', 'êšŽ' => 'êš�', 'êš�' => 'êš‘', 'êš’' => 'êš“', 'êš”' => 'êš•', 'êš–' => 'êš—', 'êš˜' => 'êš™', 'êšš' => 'êš›', 'êœ¢' => 'êœ£', 'êœ¤' => 'êœ¥', 'êœ¦' => 'êœ§', 'êœ¨' => 'êœ©', 'êœª' => 'êœ«', 'êœ¬' => 'êœ­', 'êœ®' => 'êœ¯', 'êœ²' => 'êœ³', 'êœ´' => 'êœµ', 'êœ¶' => 'êœ·', 'êœ¸' => 'êœ¹', 'êœº' => 'êœ»', 'êœ¼' => 'êœ½', 'êœ¾' => 'êœ¿', 'ê�€' => 'ê��', 'ê�‚' => 'ê�ƒ', 'ê�„' => 'ê�…', 'ê�†' => 'ê�‡', 'ê�ˆ' => 'ê�‰', 'ê�Š' => 'ê�‹', 'ê�Œ' => 'ê��', 'ê�Ž' => 'ê��', 'ê��' => 'ê�‘', 'ê�’' => 'ê�“', 'ê�”' => 'ê�•', 'ê�–' => 'ê�—', 'ê�˜' => 'ê�™', 'ê�š' => 'ê�›', 'ê�œ' => 'ê��', 'ê�ž' => 'ê�Ÿ', 'ê� ' => 'ê�¡', 'ê�¢' => 'ê�£', 'ê�¤' => 'ê�¥', 'ê�¦' => 'ê�§', 'ê�¨' => 'ê�©', 'ê�ª' => 'ê�«', 'ê�¬' => 'ê�­', 'ê�®' => 'ê�¯', 'ê�¹' => 'ê�º', 'ê�»' => 'ê�¼', 'ê�½' => 'áµ¹', 'ê�¾' => 'ê�¿', 'êž€' => 'êž�', 'êž‚' => 'êžƒ', 'êž„' => 'êž…', 'êž†' => 'êž‡', 'êž‹' => 'êžŒ', 'êž�' => 'É¥', 'êž�' => 'êž‘', 'êž’' => 'êž“', 'êž–' => 'êž—', 'êž˜' => 'êž™', 'êžš' => 'êž›', 'êžœ' => 'êž�', 'êžž' => 'êžŸ', 'êž ' => 'êž¡', 'êž¢' => 'êž£', 'êž¤' => 'êž¥', 'êž¦' => 'êž§', 'êž¨' => 'êž©', 'êžª' => 'É¦', 'êž«' => 'Éœ', 'êž¬' => 'É¡', 'êž­' => 'É¬', 'êž®' => 'Éª', 'êž°' => 'Êž', 'êž±' => 'Ê‡', 'êž²' => 'Ê�', 'êž³' => 'ê­“', 'êž´' => 'êžµ', 'êž¶' => 'êž·', 'êž¸' => 'êž¹', 'êžº' => 'êž»', 'êž¼' => 'êž½', 'êž¾' => 'êž¿', 'êŸ‚' => 'êŸƒ', 'êŸ„' => 'êž”', 'êŸ…' => 'Ê‚', 'êŸ†' => 'á¶Ž', 'êŸ‡' => 'êŸˆ', 'êŸ‰' => 'êŸŠ', 'êŸµ' => 'êŸ¶', 'ï¼¡' => 'ï½�', 'ï¼¢' => 'ï½‚', 'ï¼£' => 'ï½ƒ', 'ï¼¤' => 'ï½„', 'ï¼¥' => 'ï½…', 'ï¼¦' => 'ï½†', 'ï¼§' => 'ï½‡', 'ï¼¨' => 'ï½ˆ', 'ï¼©' => 'ï½‰', 'ï¼ª' => 'ï½Š', 'ï¼«' => 'ï½‹', 'ï¼¬' => 'ï½Œ', 'ï¼­' => 'ï½�', 'ï¼®' => 'ï½Ž', 'ï¼¯' => 'ï½�', 'ï¼°' => 'ï½�', 'ï¼±' => 'ï½‘', 'ï¼²' => 'ï½’', 'ï¼³' => 'ï½“', 'ï¼´' => 'ï½”', 'ï¼µ' => 'ï½•', 'ï¼¶' => 'ï½–', 'ï¼·' => 'ï½—', 'ï¼¸' => 'ï½˜', 'ï¼¹' => 'ï½™', 'ï¼º' => 'ï½š', 'ð��€' => 'ð��¨', 'ð���' => 'ð��©', 'ð��‚' => 'ð��ª', 'ð��ƒ' => 'ð��«', 'ð��„' => 'ð��¬', 'ð��…' => 'ð��­', 'ð��†' => 'ð��®', 'ð��‡' => 'ð��¯', 'ð��ˆ' => 'ð��°', 'ð��‰' => 'ð��±', 'ð��Š' => 'ð��²', 'ð��‹' => 'ð��³', 'ð��Œ' => 'ð��´', 'ð���' => 'ð��µ', 'ð��Ž' => 'ð��¶', 'ð���' => 'ð��·', 'ð���' => 'ð��¸', 'ð��‘' => 'ð��¹', 'ð��’' => 'ð��º', 'ð��“' => 'ð��»', 'ð��”' => 'ð��¼', 'ð��•' => 'ð��½', 'ð��–' => 'ð��¾', 'ð��—' => 'ð��¿', 'ð��˜' => 'ð�‘€', 'ð��™' => 'ð�‘�', 'ð��š' => 'ð�‘‚', 'ð��›' => 'ð�‘ƒ', 'ð��œ' => 'ð�‘„', 'ð���' => 'ð�‘…', 'ð��ž' => 'ð�‘†', 'ð��Ÿ' => 'ð�‘‡', 'ð�� ' => 'ð�‘ˆ', 'ð��¡' => 'ð�‘‰', 'ð��¢' => 'ð�‘Š', 'ð��£' => 'ð�‘‹', 'ð��¤' => 'ð�‘Œ', 'ð��¥' => 'ð�‘�', 'ð��¦' => 'ð�‘Ž', 'ð��§' => 'ð�‘�', 'ð�’°' => 'ð�“˜', 'ð�’±' => 'ð�“™', 'ð�’²' => 'ð�“š', 'ð�’³' => 'ð�“›', 'ð�’´' => 'ð�“œ', 'ð�’µ' => 'ð�“�', 'ð�’¶' => 'ð�“ž', 'ð�’·' => 'ð�“Ÿ', 'ð�’¸' => 'ð�“ ', 'ð�’¹' => 'ð�“¡', 'ð�’º' => 'ð�“¢', 'ð�’»' => 'ð�“£', 'ð�’¼' => 'ð�“¤', 'ð�’½' => 'ð�“¥', 'ð�’¾' => 'ð�“¦', 'ð�’¿' => 'ð�“§', 'ð�“€' => 'ð�“¨', 'ð�“�' => 'ð�“©', 'ð�“‚' => 'ð�“ª', 'ð�“ƒ' => 'ð�“«', 'ð�“„' => 'ð�“¬', 'ð�“…' => 'ð�“­', 'ð�“†' => 'ð�“®', 'ð�“‡' => 'ð�“¯', 'ð�“ˆ' => 'ð�“°', 'ð�“‰' => 'ð�“±', 'ð�“Š' => 'ð�“²', 'ð�“‹' => 'ð�“³', 'ð�“Œ' => 'ð�“´', 'ð�“�' => 'ð�“µ', 'ð�“Ž' => 'ð�“¶', 'ð�“�' => 'ð�“·', 'ð�“�' => 'ð�“¸', 'ð�“‘' => 'ð�“¹', 'ð�“’' => 'ð�“º', 'ð�““' => 'ð�“»', 'ð�²€' => 'ð�³€', 'ð�²�' => 'ð�³�', 'ð�²‚' => 'ð�³‚', 'ð�²ƒ' => 'ð�³ƒ', 'ð�²„' => 'ð�³„', 'ð�²…' => 'ð�³…', 'ð�²†' => 'ð�³†', 'ð�²‡' => 'ð�³‡', 'ð�²ˆ' => 'ð�³ˆ', 'ð�²‰' => 'ð�³‰', 'ð�²Š' => 'ð�³Š', 'ð�²‹' => 'ð�³‹', 'ð�²Œ' => 'ð�³Œ', 'ð�²�' => 'ð�³�', 'ð�²Ž' => 'ð�³Ž', 'ð�²�' => 'ð�³�', 'ð�²�' => 'ð�³�', 'ð�²‘' => 'ð�³‘', 'ð�²’' => 'ð�³’', 'ð�²“' => 'ð�³“', 'ð�²”' => 'ð�³”', 'ð�²•' => 'ð�³•', 'ð�²–' => 'ð�³–', 'ð�²—' => 'ð�³—', 'ð�²˜' => 'ð�³˜', 'ð�²™' => 'ð�³™', 'ð�²š' => 'ð�³š', 'ð�²›' => 'ð�³›', 'ð�²œ' => 'ð�³œ', 'ð�²�' => 'ð�³�', 'ð�²ž' => 'ð�³ž', 'ð�²Ÿ' => 'ð�³Ÿ', 'ð�² ' => 'ð�³ ', 'ð�²¡' => 'ð�³¡', 'ð�²¢' => 'ð�³¢', 'ð�²£' => 'ð�³£', 'ð�²¤' => 'ð�³¤', 'ð�²¥' => 'ð�³¥', 'ð�²¦' => 'ð�³¦', 'ð�²§' => 'ð�³§', 'ð�²¨' => 'ð�³¨', 'ð�²©' => 'ð�³©', 'ð�²ª' => 'ð�³ª', 'ð�²«' => 'ð�³«', 'ð�²¬' => 'ð�³¬', 'ð�²­' => 'ð�³­', 'ð�²®' => 'ð�³®', 'ð�²¯' => 'ð�³¯', 'ð�²°' => 'ð�³°', 'ð�²±' => 'ð�³±', 'ð�²²' => 'ð�³²', 'ð‘¢ ' => 'ð‘£€', 'ð‘¢¡' => 'ð‘£�', 'ð‘¢¢' => 'ð‘£‚', 'ð‘¢£' => 'ð‘£ƒ', 'ð‘¢¤' => 'ð‘£„', 'ð‘¢¥' => 'ð‘£…', 'ð‘¢¦' => 'ð‘£†', 'ð‘¢§' => 'ð‘£‡', 'ð‘¢¨' => 'ð‘£ˆ', 'ð‘¢©' => 'ð‘£‰', 'ð‘¢ª' => 'ð‘£Š', 'ð‘¢«' => 'ð‘£‹', 'ð‘¢¬' => 'ð‘£Œ', 'ð‘¢­' => 'ð‘£�', 'ð‘¢®' => 'ð‘£Ž', 'ð‘¢¯' => 'ð‘£�', 'ð‘¢°' => 'ð‘£�', 'ð‘¢±' => 'ð‘£‘', 'ð‘¢²' => 'ð‘£’', 'ð‘¢³' => 'ð‘£“', 'ð‘¢´' => 'ð‘£”', 'ð‘¢µ' => 'ð‘£•', 'ð‘¢¶' => 'ð‘£–', 'ð‘¢·' => 'ð‘£—', 'ð‘¢¸' => 'ð‘£˜', 'ð‘¢¹' => 'ð‘£™', 'ð‘¢º' => 'ð‘£š', 'ð‘¢»' => 'ð‘£›', 'ð‘¢¼' => 'ð‘£œ', 'ð‘¢½' => 'ð‘£�', 'ð‘¢¾' => 'ð‘£ž', 'ð‘¢¿' => 'ð‘£Ÿ', 'ð–¹€' => 'ð–¹ ', 'ð–¹�' => 'ð–¹¡', 'ð–¹‚' => 'ð–¹¢', 'ð–¹ƒ' => 'ð–¹£', 'ð–¹„' => 'ð–¹¤', 'ð–¹…' => 'ð–¹¥', 'ð–¹†' => 'ð–¹¦', 'ð–¹‡' => 'ð–¹§', 'ð–¹ˆ' => 'ð–¹¨', 'ð–¹‰' => 'ð–¹©', 'ð–¹Š' => 'ð–¹ª', 'ð–¹‹' => 'ð–¹«', 'ð–¹Œ' => 'ð–¹¬', 'ð–¹�' => 'ð–¹­', 'ð–¹Ž' => 'ð–¹®', 'ð–¹�' => 'ð–¹¯', 'ð–¹�' => 'ð–¹°', 'ð–¹‘' => 'ð–¹±', 'ð–¹’' => 'ð–¹²', 'ð–¹“' => 'ð–¹³', 'ð–¹”' => 'ð–¹´', 'ð–¹•' => 'ð–¹µ', 'ð–¹–' => 'ð–¹¶', 'ð–¹—' => 'ð–¹·', 'ð–¹˜' => 'ð–¹¸', 'ð–¹™' => 'ð–¹¹', 'ð–¹š' => 'ð–¹º', 'ð–¹›' => 'ð–¹»', 'ð–¹œ' => 'ð–¹¼', 'ð–¹�' => 'ð–¹½', 'ð–¹ž' => 'ð–¹¾', 'ð–¹Ÿ' => 'ð–¹¿', 'ðž¤€' => 'ðž¤¢', 'ðž¤�' => 'ðž¤£', 'ðž¤‚' => 'ðž¤¤', 'ðž¤ƒ' => 'ðž¤¥', 'ðž¤„' => 'ðž¤¦', 'ðž¤…' => 'ðž¤§', 'ðž¤†' => 'ðž¤¨', 'ðž¤‡' => 'ðž¤©', 'ðž¤ˆ' => 'ðž¤ª', 'ðž¤‰' => 'ðž¤«', 'ðž¤Š' => 'ðž¤¬', 'ðž¤‹' => 'ðž¤­', 'ðž¤Œ' => 'ðž¤®', 'ðž¤�' => 'ðž¤¯', 'ðž¤Ž' => 'ðž¤°', 'ðž¤�' => 'ðž¤±', 'ðž¤�' => 'ðž¤²', 'ðž¤‘' => 'ðž¤³', 'ðž¤’' => 'ðž¤´', 'ðž¤“' => 'ðž¤µ', 'ðž¤”' => 'ðž¤¶', 'ðž¤•' => 'ðž¤·', 'ðž¤–' => 'ðž¤¸', 'ðž¤—' => 'ðž¤¹', 'ðž¤˜' => 'ðž¤º', 'ðž¤™' => 'ðž¤»', 'ðž¤š' => 'ðž¤¼', 'ðž¤›' => 'ðž¤½', 'ðž¤œ' => 'ðž¤¾', 'ðž¤�' => 'ðž¤¿', 'ðž¤ž' => 'ðž¥€', 'ðž¤Ÿ' => 'ðž¥�', 'ðž¤ ' => 'ðž¥‚', 'ðž¤¡' => 'ðž¥ƒ');<?php

return array('a' => 'A', 'b' => 'B', 'c' => 'C', 'd' => 'D', 'e' => 'E', 'f' => 'F', 'g' => 'G', 'h' => 'H', 'i' => 'I', 'j' => 'J', 'k' => 'K', 'l' => 'L', 'm' => 'M', 'n' => 'N', 'o' => 'O', 'p' => 'P', 'q' => 'Q', 'r' => 'R', 's' => 'S', 't' => 'T', 'u' => 'U', 'v' => 'V', 'w' => 'W', 'x' => 'X', 'y' => 'Y', 'z' => 'Z', 'Âµ' => 'Îœ', 'Ã ' => 'Ã€', 'Ã¡' => 'Ã�', 'Ã¢' => 'Ã‚', 'Ã£' => 'Ãƒ', 'Ã¤' => 'Ã„', 'Ã¥' => 'Ã…', 'Ã¦' => 'Ã†', 'Ã§' => 'Ã‡', 'Ã¨' => 'Ãˆ', 'Ã©' => 'Ã‰', 'Ãª' => 'ÃŠ', 'Ã«' => 'Ã‹', 'Ã¬' => 'ÃŒ', 'Ã­' => 'Ã�', 'Ã®' => 'ÃŽ', 'Ã¯' => 'Ã�', 'Ã°' => 'Ã�', 'Ã±' => 'Ã‘', 'Ã²' => 'Ã’', 'Ã³' => 'Ã“', 'Ã´' => 'Ã”', 'Ãµ' => 'Ã•', 'Ã¶' => 'Ã–', 'Ã¸' => 'Ã˜', 'Ã¹' => 'Ã™', 'Ãº' => 'Ãš', 'Ã»' => 'Ã›', 'Ã¼' => 'Ãœ', 'Ã½' => 'Ã�', 'Ã¾' => 'Ãž', 'Ã¿' => 'Å¸', 'Ä�' => 'Ä€', 'Äƒ' => 'Ä‚', 'Ä…' => 'Ä„', 'Ä‡' => 'Ä†', 'Ä‰' => 'Äˆ', 'Ä‹' => 'ÄŠ', 'Ä�' => 'ÄŒ', 'Ä�' => 'ÄŽ', 'Ä‘' => 'Ä�', 'Ä“' => 'Ä’', 'Ä•' => 'Ä”', 'Ä—' => 'Ä–', 'Ä™' => 'Ä˜', 'Ä›' => 'Äš', 'Ä�' => 'Äœ', 'ÄŸ' => 'Äž', 'Ä¡' => 'Ä ', 'Ä£' => 'Ä¢', 'Ä¥' => 'Ä¤', 'Ä§' => 'Ä¦', 'Ä©' => 'Ä¨', 'Ä«' => 'Äª', 'Ä­' => 'Ä¬', 'Ä¯' => 'Ä®', 'Ä±' => 'I', 'Ä³' => 'Ä²', 'Äµ' => 'Ä´', 'Ä·' => 'Ä¶', 'Äº' => 'Ä¹', 'Ä¼' => 'Ä»', 'Ä¾' => 'Ä½', 'Å€' => 'Ä¿', 'Å‚' => 'Å�', 'Å„' => 'Åƒ', 'Å†' => 'Å…', 'Åˆ' => 'Å‡', 'Å‹' => 'ÅŠ', 'Å�' => 'ÅŒ', 'Å�' => 'ÅŽ', 'Å‘' => 'Å�', 'Å“' => 'Å’', 'Å•' => 'Å”', 'Å—' => 'Å–', 'Å™' => 'Å˜', 'Å›' => 'Åš', 'Å�' => 'Åœ', 'ÅŸ' => 'Åž', 'Å¡' => 'Å ', 'Å£' => 'Å¢', 'Å¥' => 'Å¤', 'Å§' => 'Å¦', 'Å©' => 'Å¨', 'Å«' => 'Åª', 'Å­' => 'Å¬', 'Å¯' => 'Å®', 'Å±' => 'Å°', 'Å³' => 'Å²', 'Åµ' => 'Å´', 'Å·' => 'Å¶', 'Åº' => 'Å¹', 'Å¼' => 'Å»', 'Å¾' => 'Å½', 'Å¿' => 'S', 'Æ€' => 'Éƒ', 'Æƒ' => 'Æ‚', 'Æ…' => 'Æ„', 'Æˆ' => 'Æ‡', 'ÆŒ' => 'Æ‹', 'Æ’' => 'Æ‘', 'Æ•' => 'Ç¶', 'Æ™' => 'Æ˜', 'Æš' => 'È½', 'Æž' => 'È ', 'Æ¡' => 'Æ ', 'Æ£' => 'Æ¢', 'Æ¥' => 'Æ¤', 'Æ¨' => 'Æ§', 'Æ­' => 'Æ¬', 'Æ°' => 'Æ¯', 'Æ´' => 'Æ³', 'Æ¶' => 'Æµ', 'Æ¹' => 'Æ¸', 'Æ½' => 'Æ¼', 'Æ¿' => 'Ç·', 'Ç…' => 'Ç„', 'Ç†' => 'Ç„', 'Çˆ' => 'Ç‡', 'Ç‰' => 'Ç‡', 'Ç‹' => 'ÇŠ', 'ÇŒ' => 'ÇŠ', 'ÇŽ' => 'Ç�', 'Ç�' => 'Ç�', 'Ç’' => 'Ç‘', 'Ç”' => 'Ç“', 'Ç–' => 'Ç•', 'Ç˜' => 'Ç—', 'Çš' => 'Ç™', 'Çœ' => 'Ç›', 'Ç�' => 'ÆŽ', 'ÇŸ' => 'Çž', 'Ç¡' => 'Ç ', 'Ç£' => 'Ç¢', 'Ç¥' => 'Ç¤', 'Ç§' => 'Ç¦', 'Ç©' => 'Ç¨', 'Ç«' => 'Çª', 'Ç­' => 'Ç¬', 'Ç¯' => 'Ç®', 'Ç²' => 'Ç±', 'Ç³' => 'Ç±', 'Çµ' => 'Ç´', 'Ç¹' => 'Ç¸', 'Ç»' => 'Çº', 'Ç½' => 'Ç¼', 'Ç¿' => 'Ç¾', 'È�' => 'È€', 'Èƒ' => 'È‚', 'È…' => 'È„', 'È‡' => 'È†', 'È‰' => 'Èˆ', 'È‹' => 'ÈŠ', 'È�' => 'ÈŒ', 'È�' => 'ÈŽ', 'È‘' => 'È�', 'È“' => 'È’', 'È•' => 'È”', 'È—' => 'È–', 'È™' => 'È˜', 'È›' => 'Èš', 'È�' => 'Èœ', 'ÈŸ' => 'Èž', 'È£' => 'È¢', 'È¥' => 'È¤', 'È§' => 'È¦', 'È©' => 'È¨', 'È«' => 'Èª', 'È­' => 'È¬', 'È¯' => 'È®', 'È±' => 'È°', 'È³' => 'È²', 'È¼' => 'È»', 'È¿' => 'â±¾', 'É€' => 'â±¿', 'É‚' => 'É�', 'É‡' => 'É†', 'É‰' => 'Éˆ', 'É‹' => 'ÉŠ', 'É�' => 'ÉŒ', 'É�' => 'ÉŽ', 'É�' => 'â±¯', 'É‘' => 'â±­', 'É’' => 'â±°', 'É“' => 'Æ�', 'É”' => 'Æ†', 'É–' => 'Æ‰', 'É—' => 'ÆŠ', 'É™' => 'Æ�', 'É›' => 'Æ�', 'Éœ' => 'êž«', 'É ' => 'Æ“', 'É¡' => 'êž¬', 'É£' => 'Æ”', 'É¥' => 'êž�', 'É¦' => 'êžª', 'É¨' => 'Æ—', 'É©' => 'Æ–', 'Éª' => 'êž®', 'É«' => 'â±¢', 'É¬' => 'êž­', 'É¯' => 'Æœ', 'É±' => 'â±®', 'É²' => 'Æ�', 'Éµ' => 'ÆŸ', 'É½' => 'â±¤', 'Ê€' => 'Æ¦', 'Ê‚' => 'êŸ…', 'Êƒ' => 'Æ©', 'Ê‡' => 'êž±', 'Êˆ' => 'Æ®', 'Ê‰' => 'É„', 'ÊŠ' => 'Æ±', 'Ê‹' => 'Æ²', 'ÊŒ' => 'É…', 'Ê’' => 'Æ·', 'Ê�' => 'êž²', 'Êž' => 'êž°', 'Í…' => 'Î™', 'Í±' => 'Í°', 'Í³' => 'Í²', 'Í·' => 'Í¶', 'Í»' => 'Ï½', 'Í¼' => 'Ï¾', 'Í½' => 'Ï¿', 'Î¬' => 'Î†', 'Î­' => 'Îˆ', 'Î®' => 'Î‰', 'Î¯' => 'ÎŠ', 'Î±' => 'Î‘', 'Î²' => 'Î’', 'Î³' => 'Î“', 'Î´' => 'Î”', 'Îµ' => 'Î•', 'Î¶' => 'Î–', 'Î·' => 'Î—', 'Î¸' => 'Î˜', 'Î¹' => 'Î™', 'Îº' => 'Îš', 'Î»' => 'Î›', 'Î¼' => 'Îœ', 'Î½' => 'Î�', 'Î¾' => 'Îž', 'Î¿' => 'ÎŸ', 'Ï€' => 'Î ', 'Ï�' => 'Î¡', 'Ï‚' => 'Î£', 'Ïƒ' => 'Î£', 'Ï„' => 'Î¤', 'Ï…' => 'Î¥', 'Ï†' => 'Î¦', 'Ï‡' => 'Î§', 'Ïˆ' => 'Î¨', 'Ï‰' => 'Î©', 'ÏŠ' => 'Îª', 'Ï‹' => 'Î«', 'ÏŒ' => 'ÎŒ', 'Ï�' => 'ÎŽ', 'ÏŽ' => 'Î�', 'Ï�' => 'Î’', 'Ï‘' => 'Î˜', 'Ï•' => 'Î¦', 'Ï–' => 'Î ', 'Ï—' => 'Ï�', 'Ï™' => 'Ï˜', 'Ï›' => 'Ïš', 'Ï�' => 'Ïœ', 'ÏŸ' => 'Ïž', 'Ï¡' => 'Ï ', 'Ï£' => 'Ï¢', 'Ï¥' => 'Ï¤', 'Ï§' => 'Ï¦', 'Ï©' => 'Ï¨', 'Ï«' => 'Ïª', 'Ï­' => 'Ï¬', 'Ï¯' => 'Ï®', 'Ï°' => 'Îš', 'Ï±' => 'Î¡', 'Ï²' => 'Ï¹', 'Ï³' => 'Í¿', 'Ïµ' => 'Î•', 'Ï¸' => 'Ï·', 'Ï»' => 'Ïº', 'Ð°' => 'Ð�', 'Ð±' => 'Ð‘', 'Ð²' => 'Ð’', 'Ð³' => 'Ð“', 'Ð´' => 'Ð”', 'Ðµ' => 'Ð•', 'Ð¶' => 'Ð–', 'Ð·' => 'Ð—', 'Ð¸' => 'Ð˜', 'Ð¹' => 'Ð™', 'Ðº' => 'Ðš', 'Ð»' => 'Ð›', 'Ð¼' => 'Ðœ', 'Ð½' => 'Ð�', 'Ð¾' => 'Ðž', 'Ð¿' => 'ÐŸ', 'Ñ€' => 'Ð ', 'Ñ�' => 'Ð¡', 'Ñ‚' => 'Ð¢', 'Ñƒ' => 'Ð£', 'Ñ„' => 'Ð¤', 'Ñ…' => 'Ð¥', 'Ñ†' => 'Ð¦', 'Ñ‡' => 'Ð§', 'Ñˆ' => 'Ð¨', 'Ñ‰' => 'Ð©', 'ÑŠ' => 'Ðª', 'Ñ‹' => 'Ð«', 'ÑŒ' => 'Ð¬', 'Ñ�' => 'Ð­', 'ÑŽ' => 'Ð®', 'Ñ�' => 'Ð¯', 'Ñ�' => 'Ð€', 'Ñ‘' => 'Ð�', 'Ñ’' => 'Ð‚', 'Ñ“' => 'Ðƒ', 'Ñ”' => 'Ð„', 'Ñ•' => 'Ð…', 'Ñ–' => 'Ð†', 'Ñ—' => 'Ð‡', 'Ñ˜' => 'Ðˆ', 'Ñ™' => 'Ð‰', 'Ñš' => 'ÐŠ', 'Ñ›' => 'Ð‹', 'Ñœ' => 'ÐŒ', 'Ñ�' => 'Ð�', 'Ñž' => 'ÐŽ', 'ÑŸ' => 'Ð�', 'Ñ¡' => 'Ñ ', 'Ñ£' => 'Ñ¢', 'Ñ¥' => 'Ñ¤', 'Ñ§' => 'Ñ¦', 'Ñ©' => 'Ñ¨', 'Ñ«' => 'Ñª', 'Ñ­' => 'Ñ¬', 'Ñ¯' => 'Ñ®', 'Ñ±' => 'Ñ°', 'Ñ³' => 'Ñ²', 'Ñµ' => 'Ñ´', 'Ñ·' => 'Ñ¶', 'Ñ¹' => 'Ñ¸', 'Ñ»' => 'Ñº', 'Ñ½' => 'Ñ¼', 'Ñ¿' => 'Ñ¾', 'Ò�' => 'Ò€', 'Ò‹' => 'ÒŠ', 'Ò�' => 'ÒŒ', 'Ò�' => 'ÒŽ', 'Ò‘' => 'Ò�', 'Ò“' => 'Ò’', 'Ò•' => 'Ò”', 'Ò—' => 'Ò–', 'Ò™' => 'Ò˜', 'Ò›' => 'Òš', 'Ò�' => 'Òœ', 'ÒŸ' => 'Òž', 'Ò¡' => 'Ò ', 'Ò£' => 'Ò¢', 'Ò¥' => 'Ò¤', 'Ò§' => 'Ò¦', 'Ò©' => 'Ò¨', 'Ò«' => 'Òª', 'Ò­' => 'Ò¬', 'Ò¯' => 'Ò®', 'Ò±' => 'Ò°', 'Ò³' => 'Ò²', 'Òµ' => 'Ò´', 'Ò·' => 'Ò¶', 'Ò¹' => 'Ò¸', 'Ò»' => 'Òº', 'Ò½' => 'Ò¼', 'Ò¿' => 'Ò¾', 'Ó‚' => 'Ó�', 'Ó„' => 'Óƒ', 'Ó†' => 'Ó…', 'Óˆ' => 'Ó‡', 'ÓŠ' => 'Ó‰', 'ÓŒ' => 'Ó‹', 'ÓŽ' => 'Ó�', 'Ó�' => 'Ó€', 'Ó‘' => 'Ó�', 'Ó“' => 'Ó’', 'Ó•' => 'Ó”', 'Ó—' => 'Ó–', 'Ó™' => 'Ó˜', 'Ó›' => 'Óš', 'Ó�' => 'Óœ', 'ÓŸ' => 'Óž', 'Ó¡' => 'Ó ', 'Ó£' => 'Ó¢', 'Ó¥' => 'Ó¤', 'Ó§' => 'Ó¦', 'Ó©' => 'Ó¨', 'Ó«' => 'Óª', 'Ó­' => 'Ó¬', 'Ó¯' => 'Ó®', 'Ó±' => 'Ó°', 'Ó³' => 'Ó²', 'Óµ' => 'Ó´', 'Ó·' => 'Ó¶', 'Ó¹' => 'Ó¸', 'Ó»' => 'Óº', 'Ó½' => 'Ó¼', 'Ó¿' => 'Ó¾', 'Ô�' => 'Ô€', 'Ôƒ' => 'Ô‚', 'Ô…' => 'Ô„', 'Ô‡' => 'Ô†', 'Ô‰' => 'Ôˆ', 'Ô‹' => 'ÔŠ', 'Ô�' => 'ÔŒ', 'Ô�' => 'ÔŽ', 'Ô‘' => 'Ô�', 'Ô“' => 'Ô’', 'Ô•' => 'Ô”', 'Ô—' => 'Ô–', 'Ô™' => 'Ô˜', 'Ô›' => 'Ôš', 'Ô�' => 'Ôœ', 'ÔŸ' => 'Ôž', 'Ô¡' => 'Ô ', 'Ô£' => 'Ô¢', 'Ô¥' => 'Ô¤', 'Ô§' => 'Ô¦', 'Ô©' => 'Ô¨', 'Ô«' => 'Ôª', 'Ô­' => 'Ô¬', 'Ô¯' => 'Ô®', 'Õ¡' => 'Ô±', 'Õ¢' => 'Ô²', 'Õ£' => 'Ô³', 'Õ¤' => 'Ô´', 'Õ¥' => 'Ôµ', 'Õ¦' => 'Ô¶', 'Õ§' => 'Ô·', 'Õ¨' => 'Ô¸', 'Õ©' => 'Ô¹', 'Õª' => 'Ôº', 'Õ«' => 'Ô»', 'Õ¬' => 'Ô¼', 'Õ­' => 'Ô½', 'Õ®' => 'Ô¾', 'Õ¯' => 'Ô¿', 'Õ°' => 'Õ€', 'Õ±' => 'Õ�', 'Õ²' => 'Õ‚', 'Õ³' => 'Õƒ', 'Õ´' => 'Õ„', 'Õµ' => 'Õ…', 'Õ¶' => 'Õ†', 'Õ·' => 'Õ‡', 'Õ¸' => 'Õˆ', 'Õ¹' => 'Õ‰', 'Õº' => 'ÕŠ', 'Õ»' => 'Õ‹', 'Õ¼' => 'ÕŒ', 'Õ½' => 'Õ�', 'Õ¾' => 'ÕŽ', 'Õ¿' => 'Õ�', 'Ö€' => 'Õ�', 'Ö�' => 'Õ‘', 'Ö‚' => 'Õ’', 'Öƒ' => 'Õ“', 'Ö„' => 'Õ”', 'Ö…' => 'Õ•', 'Ö†' => 'Õ–', 'áƒ�' => 'á²�', 'áƒ‘' => 'á²‘', 'áƒ’' => 'á²’', 'áƒ“' => 'á²“', 'áƒ”' => 'á²”', 'áƒ•' => 'á²•', 'áƒ–' => 'á²–', 'áƒ—' => 'á²—', 'áƒ˜' => 'á²˜', 'áƒ™' => 'á²™', 'áƒš' => 'á²š', 'áƒ›' => 'á²›', 'áƒœ' => 'á²œ', 'áƒ�' => 'á²�', 'áƒž' => 'á²ž', 'áƒŸ' => 'á²Ÿ', 'áƒ ' => 'á² ', 'áƒ¡' => 'á²¡', 'áƒ¢' => 'á²¢', 'áƒ£' => 'á²£', 'áƒ¤' => 'á²¤', 'áƒ¥' => 'á²¥', 'áƒ¦' => 'á²¦', 'áƒ§' => 'á²§', 'áƒ¨' => 'á²¨', 'áƒ©' => 'á²©', 'áƒª' => 'á²ª', 'áƒ«' => 'á²«', 'áƒ¬' => 'á²¬', 'áƒ­' => 'á²­', 'áƒ®' => 'á²®', 'áƒ¯' => 'á²¯', 'áƒ°' => 'á²°', 'áƒ±' => 'á²±', 'áƒ²' => 'á²²', 'áƒ³' => 'á²³', 'áƒ´' => 'á²´', 'áƒµ' => 'á²µ', 'áƒ¶' => 'á²¶', 'áƒ·' => 'á²·', 'áƒ¸' => 'á²¸', 'áƒ¹' => 'á²¹', 'áƒº' => 'á²º', 'áƒ½' => 'á²½', 'áƒ¾' => 'á²¾', 'áƒ¿' => 'á²¿', 'á�¸' => 'á�°', 'á�¹' => 'á�±', 'á�º' => 'á�²', 'á�»' => 'á�³', 'á�¼' => 'á�´', 'á�½' => 'á�µ', 'á²€' => 'Ð’', 'á²�' => 'Ð”', 'á²‚' => 'Ðž', 'á²ƒ' => 'Ð¡', 'á²„' => 'Ð¢', 'á²…' => 'Ð¢', 'á²†' => 'Ðª', 'á²‡' => 'Ñ¢', 'á²ˆ' => 'ê™Š', 'áµ¹' => 'ê�½', 'áµ½' => 'â±£', 'á¶Ž' => 'êŸ†', 'á¸�' => 'á¸€', 'á¸ƒ' => 'á¸‚', 'á¸…' => 'á¸„', 'á¸‡' => 'á¸†', 'á¸‰' => 'á¸ˆ', 'á¸‹' => 'á¸Š', 'á¸�' => 'á¸Œ', 'á¸�' => 'á¸Ž', 'á¸‘' => 'á¸�', 'á¸“' => 'á¸’', 'á¸•' => 'á¸”', 'á¸—' => 'á¸–', 'á¸™' => 'á¸˜', 'á¸›' => 'á¸š', 'á¸�' => 'á¸œ', 'á¸Ÿ' => 'á¸ž', 'á¸¡' => 'á¸ ', 'á¸£' => 'á¸¢', 'á¸¥' => 'á¸¤', 'á¸§' => 'á¸¦', 'á¸©' => 'á¸¨', 'á¸«' => 'á¸ª', 'á¸­' => 'á¸¬', 'á¸¯' => 'á¸®', 'á¸±' => 'á¸°', 'á¸³' => 'á¸²', 'á¸µ' => 'á¸´', 'á¸·' => 'á¸¶', 'á¸¹' => 'á¸¸', 'á¸»' => 'á¸º', 'á¸½' => 'á¸¼', 'á¸¿' => 'á¸¾', 'á¹�' => 'á¹€', 'á¹ƒ' => 'á¹‚', 'á¹…' => 'á¹„', 'á¹‡' => 'á¹†', 'á¹‰' => 'á¹ˆ', 'á¹‹' => 'á¹Š', 'á¹�' => 'á¹Œ', 'á¹�' => 'á¹Ž', 'á¹‘' => 'á¹�', 'á¹“' => 'á¹’', 'á¹•' => 'á¹”', 'á¹—' => 'á¹–', 'á¹™' => 'á¹˜', 'á¹›' => 'á¹š', 'á¹�' => 'á¹œ', 'á¹Ÿ' => 'á¹ž', 'á¹¡' => 'á¹ ', 'á¹£' => 'á¹¢', 'á¹¥' => 'á¹¤', 'á¹§' => 'á¹¦', 'á¹©' => 'á¹¨', 'á¹«' => 'á¹ª', 'á¹­' => 'á¹¬', 'á¹¯' => 'á¹®', 'á¹±' => 'á¹°', 'á¹³' => 'á¹²', 'á¹µ' => 'á¹´', 'á¹·' => 'á¹¶', 'á¹¹' => 'á¹¸', 'á¹»' => 'á¹º', 'á¹½' => 'á¹¼', 'á¹¿' => 'á¹¾', 'áº�' => 'áº€', 'áºƒ' => 'áº‚', 'áº…' => 'áº„', 'áº‡' => 'áº†', 'áº‰' => 'áºˆ', 'áº‹' => 'áºŠ', 'áº�' => 'áºŒ', 'áº�' => 'áºŽ', 'áº‘' => 'áº�', 'áº“' => 'áº’', 'áº•' => 'áº”', 'áº›' => 'á¹ ', 'áº¡' => 'áº ', 'áº£' => 'áº¢', 'áº¥' => 'áº¤', 'áº§' => 'áº¦', 'áº©' => 'áº¨', 'áº«' => 'áºª', 'áº­' => 'áº¬', 'áº¯' => 'áº®', 'áº±' => 'áº°', 'áº³' => 'áº²', 'áºµ' => 'áº´', 'áº·' => 'áº¶', 'áº¹' => 'áº¸', 'áº»' => 'áºº', 'áº½' => 'áº¼', 'áº¿' => 'áº¾', 'á»�' => 'á»€', 'á»ƒ' => 'á»‚', 'á»…' => 'á»„', 'á»‡' => 'á»†', 'á»‰' => 'á»ˆ', 'á»‹' => 'á»Š', 'á»�' => 'á»Œ', 'á»�' => 'á»Ž', 'á»‘' => 'á»�', 'á»“' => 'á»’', 'á»•' => 'á»”', 'á»—' => 'á»–', 'á»™' => 'á»˜', 'á»›' => 'á»š', 'á»�' => 'á»œ', 'á»Ÿ' => 'á»ž', 'á»¡' => 'á» ', 'á»£' => 'á»¢', 'á»¥' => 'á»¤', 'á»§' => 'á»¦', 'á»©' => 'á»¨', 'á»«' => 'á»ª', 'á»­' => 'á»¬', 'á»¯' => 'á»®', 'á»±' => 'á»°', 'á»³' => 'á»²', 'á»µ' => 'á»´', 'á»·' => 'á»¶', 'á»¹' => 'á»¸', 'á»»' => 'á»º', 'á»½' => 'á»¼', 'á»¿' => 'á»¾', 'á¼€' => 'á¼ˆ', 'á¼�' => 'á¼‰', 'á¼‚' => 'á¼Š', 'á¼ƒ' => 'á¼‹', 'á¼„' => 'á¼Œ', 'á¼…' => 'á¼�', 'á¼†' => 'á¼Ž', 'á¼‡' => 'á¼�', 'á¼�' => 'á¼˜', 'á¼‘' => 'á¼™', 'á¼’' => 'á¼š', 'á¼“' => 'á¼›', 'á¼”' => 'á¼œ', 'á¼•' => 'á¼�', 'á¼ ' => 'á¼¨', 'á¼¡' => 'á¼©', 'á¼¢' => 'á¼ª', 'á¼£' => 'á¼«', 'á¼¤' => 'á¼¬', 'á¼¥' => 'á¼­', 'á¼¦' => 'á¼®', 'á¼§' => 'á¼¯', 'á¼°' => 'á¼¸', 'á¼±' => 'á¼¹', 'á¼²' => 'á¼º', 'á¼³' => 'á¼»', 'á¼´' => 'á¼¼', 'á¼µ' => 'á¼½', 'á¼¶' => 'á¼¾', 'á¼·' => 'á¼¿', 'á½€' => 'á½ˆ', 'á½�' => 'á½‰', 'á½‚' => 'á½Š', 'á½ƒ' => 'á½‹', 'á½„' => 'á½Œ', 'á½…' => 'á½�', 'á½‘' => 'á½™', 'á½“' => 'á½›', 'á½•' => 'á½�', 'á½—' => 'á½Ÿ', 'á½ ' => 'á½¨', 'á½¡' => 'á½©', 'á½¢' => 'á½ª', 'á½£' => 'á½«', 'á½¤' => 'á½¬', 'á½¥' => 'á½­', 'á½¦' => 'á½®', 'á½§' => 'á½¯', 'á½°' => 'á¾º', 'á½±' => 'á¾»', 'á½²' => 'á¿ˆ', 'á½³' => 'á¿‰', 'á½´' => 'á¿Š', 'á½µ' => 'á¿‹', 'á½¶' => 'á¿š', 'á½·' => 'á¿›', 'á½¸' => 'á¿¸', 'á½¹' => 'á¿¹', 'á½º' => 'á¿ª', 'á½»' => 'á¿«', 'á½¼' => 'á¿º', 'á½½' => 'á¿»', 'á¾€' => 'á¼ˆÎ™', 'á¾�' => 'á¼‰Î™', 'á¾‚' => 'á¼ŠÎ™', 'á¾ƒ' => 'á¼‹Î™', 'á¾„' => 'á¼ŒÎ™', 'á¾…' => 'á¼�Î™', 'á¾†' => 'á¼ŽÎ™', 'á¾‡' => 'á¼�Î™', 'á¾�' => 'á¼¨Î™', 'á¾‘' => 'á¼©Î™', 'á¾’' => 'á¼ªÎ™', 'á¾“' => 'á¼«Î™', 'á¾”' => 'á¼¬Î™', 'á¾•' => 'á¼­Î™', 'á¾–' => 'á¼®Î™', 'á¾—' => 'á¼¯Î™', 'á¾ ' => 'á½¨Î™', 'á¾¡' => 'á½©Î™', 'á¾¢' => 'á½ªÎ™', 'á¾£' => 'á½«Î™', 'á¾¤' => 'á½¬Î™', 'á¾¥' => 'á½­Î™', 'á¾¦' => 'á½®Î™', 'á¾§' => 'á½¯Î™', 'á¾°' => 'á¾¸', 'á¾±' => 'á¾¹', 'á¾³' => 'Î‘Î™', 'á¾¾' => 'Î™', 'á¿ƒ' => 'Î—Î™', 'á¿�' => 'á¿˜', 'á¿‘' => 'á¿™', 'á¿ ' => 'á¿¨', 'á¿¡' => 'á¿©', 'á¿¥' => 'á¿¬', 'á¿³' => 'Î©Î™', 'â…Ž' => 'â„²', 'â…°' => 'â… ', 'â…±' => 'â…¡', 'â…²' => 'â…¢', 'â…³' => 'â…£', 'â…´' => 'â…¤', 'â…µ' => 'â…¥', 'â…¶' => 'â…¦', 'â…·' => 'â…§', 'â…¸' => 'â…¨', 'â…¹' => 'â…©', 'â…º' => 'â…ª', 'â…»' => 'â…«', 'â…¼' => 'â…¬', 'â…½' => 'â…­', 'â…¾' => 'â…®', 'â…¿' => 'â…¯', 'â†„' => 'â†ƒ', 'â“�' => 'â’¶', 'â“‘' => 'â’·', 'â“’' => 'â’¸', 'â““' => 'â’¹', 'â“”' => 'â’º', 'â“•' => 'â’»', 'â“–' => 'â’¼', 'â“—' => 'â’½', 'â“˜' => 'â’¾', 'â“™' => 'â’¿', 'â“š' => 'â“€', 'â“›' => 'â“�', 'â“œ' => 'â“‚', 'â“�' => 'â“ƒ', 'â“ž' => 'â“„', 'â“Ÿ' => 'â“…', 'â“ ' => 'â“†', 'â“¡' => 'â“‡', 'â“¢' => 'â“ˆ', 'â“£' => 'â“‰', 'â“¤' => 'â“Š', 'â“¥' => 'â“‹', 'â“¦' => 'â“Œ', 'â“§' => 'â“�', 'â“¨' => 'â“Ž', 'â“©' => 'â“�', 'â°°' => 'â°€', 'â°±' => 'â°�', 'â°²' => 'â°‚', 'â°³' => 'â°ƒ', 'â°´' => 'â°„', 'â°µ' => 'â°…', 'â°¶' => 'â°†', 'â°·' => 'â°‡', 'â°¸' => 'â°ˆ', 'â°¹' => 'â°‰', 'â°º' => 'â°Š', 'â°»' => 'â°‹', 'â°¼' => 'â°Œ', 'â°½' => 'â°�', 'â°¾' => 'â°Ž', 'â°¿' => 'â°�', 'â±€' => 'â°�', 'â±�' => 'â°‘', 'â±‚' => 'â°’', 'â±ƒ' => 'â°“', 'â±„' => 'â°”', 'â±…' => 'â°•', 'â±†' => 'â°–', 'â±‡' => 'â°—', 'â±ˆ' => 'â°˜', 'â±‰' => 'â°™', 'â±Š' => 'â°š', 'â±‹' => 'â°›', 'â±Œ' => 'â°œ', 'â±�' => 'â°�', 'â±Ž' => 'â°ž', 'â±�' => 'â°Ÿ', 'â±�' => 'â° ', 'â±‘' => 'â°¡', 'â±’' => 'â°¢', 'â±“' => 'â°£', 'â±”' => 'â°¤', 'â±•' => 'â°¥', 'â±–' => 'â°¦', 'â±—' => 'â°§', 'â±˜' => 'â°¨', 'â±™' => 'â°©', 'â±š' => 'â°ª', 'â±›' => 'â°«', 'â±œ' => 'â°¬', 'â±�' => 'â°­', 'â±ž' => 'â°®', 'â±¡' => 'â± ', 'â±¥' => 'Èº', 'â±¦' => 'È¾', 'â±¨' => 'â±§', 'â±ª' => 'â±©', 'â±¬' => 'â±«', 'â±³' => 'â±²', 'â±¶' => 'â±µ', 'â²�' => 'â²€', 'â²ƒ' => 'â²‚', 'â²…' => 'â²„', 'â²‡' => 'â²†', 'â²‰' => 'â²ˆ', 'â²‹' => 'â²Š', 'â²�' => 'â²Œ', 'â²�' => 'â²Ž', 'â²‘' => 'â²�', 'â²“' => 'â²’', 'â²•' => 'â²”', 'â²—' => 'â²–', 'â²™' => 'â²˜', 'â²›' => 'â²š', 'â²�' => 'â²œ', 'â²Ÿ' => 'â²ž', 'â²¡' => 'â² ', 'â²£' => 'â²¢', 'â²¥' => 'â²¤', 'â²§' => 'â²¦', 'â²©' => 'â²¨', 'â²«' => 'â²ª', 'â²­' => 'â²¬', 'â²¯' => 'â²®', 'â²±' => 'â²°', 'â²³' => 'â²²', 'â²µ' => 'â²´', 'â²·' => 'â²¶', 'â²¹' => 'â²¸', 'â²»' => 'â²º', 'â²½' => 'â²¼', 'â²¿' => 'â²¾', 'â³�' => 'â³€', 'â³ƒ' => 'â³‚', 'â³…' => 'â³„', 'â³‡' => 'â³†', 'â³‰' => 'â³ˆ', 'â³‹' => 'â³Š', 'â³�' => 'â³Œ', 'â³�' => 'â³Ž', 'â³‘' => 'â³�', 'â³“' => 'â³’', 'â³•' => 'â³”', 'â³—' => 'â³–', 'â³™' => 'â³˜', 'â³›' => 'â³š', 'â³�' => 'â³œ', 'â³Ÿ' => 'â³ž', 'â³¡' => 'â³ ', 'â³£' => 'â³¢', 'â³¬' => 'â³«', 'â³®' => 'â³­', 'â³³' => 'â³²', 'â´€' => 'á‚ ', 'â´�' => 'á‚¡', 'â´‚' => 'á‚¢', 'â´ƒ' => 'á‚£', 'â´„' => 'á‚¤', 'â´…' => 'á‚¥', 'â´†' => 'á‚¦', 'â´‡' => 'á‚§', 'â´ˆ' => 'á‚¨', 'â´‰' => 'á‚©', 'â´Š' => 'á‚ª', 'â´‹' => 'á‚«', 'â´Œ' => 'á‚¬', 'â´�' => 'á‚­', 'â´Ž' => 'á‚®', 'â´�' => 'á‚¯', 'â´�' => 'á‚°', 'â´‘' => 'á‚±', 'â´’' => 'á‚²', 'â´“' => 'á‚³', 'â´”' => 'á‚´', 'â´•' => 'á‚µ', 'â´–' => 'á‚¶', 'â´—' => 'á‚·', 'â´˜' => 'á‚¸', 'â´™' => 'á‚¹', 'â´š' => 'á‚º', 'â´›' => 'á‚»', 'â´œ' => 'á‚¼', 'â´�' => 'á‚½', 'â´ž' => 'á‚¾', 'â´Ÿ' => 'á‚¿', 'â´ ' => 'áƒ€', 'â´¡' => 'áƒ�', 'â´¢' => 'áƒ‚', 'â´£' => 'áƒƒ', 'â´¤' => 'áƒ„', 'â´¥' => 'áƒ…', 'â´§' => 'áƒ‡', 'â´­' => 'áƒ�', 'ê™�' => 'ê™€', 'ê™ƒ' => 'ê™‚', 'ê™…' => 'ê™„', 'ê™‡' => 'ê™†', 'ê™‰' => 'ê™ˆ', 'ê™‹' => 'ê™Š', 'ê™�' => 'ê™Œ', 'ê™�' => 'ê™Ž', 'ê™‘' => 'ê™�', 'ê™“' => 'ê™’', 'ê™•' => 'ê™”', 'ê™—' => 'ê™–', 'ê™™' => 'ê™˜', 'ê™›' => 'ê™š', 'ê™�' => 'ê™œ', 'ê™Ÿ' => 'ê™ž', 'ê™¡' => 'ê™ ', 'ê™£' => 'ê™¢', 'ê™¥' => 'ê™¤', 'ê™§' => 'ê™¦', 'ê™©' => 'ê™¨', 'ê™«' => 'ê™ª', 'ê™­' => 'ê™¬', 'êš�' => 'êš€', 'êšƒ' => 'êš‚', 'êš…' => 'êš„', 'êš‡' => 'êš†', 'êš‰' => 'êšˆ', 'êš‹' => 'êšŠ', 'êš�' => 'êšŒ', 'êš�' => 'êšŽ', 'êš‘' => 'êš�', 'êš“' => 'êš’', 'êš•' => 'êš”', 'êš—' => 'êš–', 'êš™' => 'êš˜', 'êš›' => 'êšš', 'êœ£' => 'êœ¢', 'êœ¥' => 'êœ¤', 'êœ§' => 'êœ¦', 'êœ©' => 'êœ¨', 'êœ«' => 'êœª', 'êœ­' => 'êœ¬', 'êœ¯' => 'êœ®', 'êœ³' => 'êœ²', 'êœµ' => 'êœ´', 'êœ·' => 'êœ¶', 'êœ¹' => 'êœ¸', 'êœ»' => 'êœº', 'êœ½' => 'êœ¼', 'êœ¿' => 'êœ¾', 'ê��' => 'ê�€', 'ê�ƒ' => 'ê�‚', 'ê�…' => 'ê�„', 'ê�‡' => 'ê�†', 'ê�‰' => 'ê�ˆ', 'ê�‹' => 'ê�Š', 'ê��' => 'ê�Œ', 'ê��' => 'ê�Ž', 'ê�‘' => 'ê��', 'ê�“' => 'ê�’', 'ê�•' => 'ê�”', 'ê�—' => 'ê�–', 'ê�™' => 'ê�˜', 'ê�›' => 'ê�š', 'ê��' => 'ê�œ', 'ê�Ÿ' => 'ê�ž', 'ê�¡' => 'ê� ', 'ê�£' => 'ê�¢', 'ê�¥' => 'ê�¤', 'ê�§' => 'ê�¦', 'ê�©' => 'ê�¨', 'ê�«' => 'ê�ª', 'ê�­' => 'ê�¬', 'ê�¯' => 'ê�®', 'ê�º' => 'ê�¹', 'ê�¼' => 'ê�»', 'ê�¿' => 'ê�¾', 'êž�' => 'êž€', 'êžƒ' => 'êž‚', 'êž…' => 'êž„', 'êž‡' => 'êž†', 'êžŒ' => 'êž‹', 'êž‘' => 'êž�', 'êž“' => 'êž’', 'êž”' => 'êŸ„', 'êž—' => 'êž–', 'êž™' => 'êž˜', 'êž›' => 'êžš', 'êž�' => 'êžœ', 'êžŸ' => 'êžž', 'êž¡' => 'êž ', 'êž£' => 'êž¢', 'êž¥' => 'êž¤', 'êž§' => 'êž¦', 'êž©' => 'êž¨', 'êžµ' => 'êž´', 'êž·' => 'êž¶', 'êž¹' => 'êž¸', 'êž»' => 'êžº', 'êž½' => 'êž¼', 'êž¿' => 'êž¾', 'êŸƒ' => 'êŸ‚', 'êŸˆ' => 'êŸ‡', 'êŸŠ' => 'êŸ‰', 'êŸ¶' => 'êŸµ', 'ê­“' => 'êž³', 'ê­°' => 'áŽ ', 'ê­±' => 'áŽ¡', 'ê­²' => 'áŽ¢', 'ê­³' => 'áŽ£', 'ê­´' => 'áŽ¤', 'ê­µ' => 'áŽ¥', 'ê­¶' => 'áŽ¦', 'ê­·' => 'áŽ§', 'ê­¸' => 'áŽ¨', 'ê­¹' => 'áŽ©', 'ê­º' => 'áŽª', 'ê­»' => 'áŽ«', 'ê­¼' => 'áŽ¬', 'ê­½' => 'áŽ­', 'ê­¾' => 'áŽ®', 'ê­¿' => 'áŽ¯', 'ê®€' => 'áŽ°', 'ê®�' => 'áŽ±', 'ê®‚' => 'áŽ²', 'ê®ƒ' => 'áŽ³', 'ê®„' => 'áŽ´', 'ê®…' => 'áŽµ', 'ê®†' => 'áŽ¶', 'ê®‡' => 'áŽ·', 'ê®ˆ' => 'áŽ¸', 'ê®‰' => 'áŽ¹', 'ê®Š' => 'áŽº', 'ê®‹' => 'áŽ»', 'ê®Œ' => 'áŽ¼', 'ê®�' => 'áŽ½', 'ê®Ž' => 'áŽ¾', 'ê®�' => 'áŽ¿', 'ê®�' => 'á�€', 'ê®‘' => 'á��', 'ê®’' => 'á�‚', 'ê®“' => 'á�ƒ', 'ê®”' => 'á�„', 'ê®•' => 'á�…', 'ê®–' => 'á�†', 'ê®—' => 'á�‡', 'ê®˜' => 'á�ˆ', 'ê®™' => 'á�‰', 'ê®š' => 'á�Š', 'ê®›' => 'á�‹', 'ê®œ' => 'á�Œ', 'ê®�' => 'á��', 'ê®ž' => 'á�Ž', 'ê®Ÿ' => 'á��', 'ê® ' => 'á��', 'ê®¡' => 'á�‘', 'ê®¢' => 'á�’', 'ê®£' => 'á�“', 'ê®¤' => 'á�”', 'ê®¥' => 'á�•', 'ê®¦' => 'á�–', 'ê®§' => 'á�—', 'ê®¨' => 'á�˜', 'ê®©' => 'á�™', 'ê®ª' => 'á�š', 'ê®«' => 'á�›', 'ê®¬' => 'á�œ', 'ê®­' => 'á��', 'ê®®' => 'á�ž', 'ê®¯' => 'á�Ÿ', 'ê®°' => 'á� ', 'ê®±' => 'á�¡', 'ê®²' => 'á�¢', 'ê®³' => 'á�£', 'ê®´' => 'á�¤', 'ê®µ' => 'á�¥', 'ê®¶' => 'á�¦', 'ê®·' => 'á�§', 'ê®¸' => 'á�¨', 'ê®¹' => 'á�©', 'ê®º' => 'á�ª', 'ê®»' => 'á�«', 'ê®¼' => 'á�¬', 'ê®½' => 'á�­', 'ê®¾' => 'á�®', 'ê®¿' => 'á�¯', 'ï½�' => 'ï¼¡', 'ï½‚' => 'ï¼¢', 'ï½ƒ' => 'ï¼£', 'ï½„' => 'ï¼¤', 'ï½…' => 'ï¼¥', 'ï½†' => 'ï¼¦', 'ï½‡' => 'ï¼§', 'ï½ˆ' => 'ï¼¨', 'ï½‰' => 'ï¼©', 'ï½Š' => 'ï¼ª', 'ï½‹' => 'ï¼«', 'ï½Œ' => 'ï¼¬', 'ï½�' => 'ï¼­', 'ï½Ž' => 'ï¼®', 'ï½�' => 'ï¼¯', 'ï½�' => 'ï¼°', 'ï½‘' => 'ï¼±', 'ï½’' => 'ï¼²', 'ï½“' => 'ï¼³', 'ï½”' => 'ï¼´', 'ï½•' => 'ï¼µ', 'ï½–' => 'ï¼¶', 'ï½—' => 'ï¼·', 'ï½˜' => 'ï¼¸', 'ï½™' => 'ï¼¹', 'ï½š' => 'ï¼º', 'ð��¨' => 'ð��€', 'ð��©' => 'ð���', 'ð��ª' => 'ð��‚', 'ð��«' => 'ð��ƒ', 'ð��¬' => 'ð��„', 'ð��­' => 'ð��…', 'ð��®' => 'ð��†', 'ð��¯' => 'ð��‡', 'ð��°' => 'ð��ˆ', 'ð��±' => 'ð��‰', 'ð��²' => 'ð��Š', 'ð��³' => 'ð��‹', 'ð��´' => 'ð��Œ', 'ð��µ' => 'ð���', 'ð��¶' => 'ð��Ž', 'ð��·' => 'ð���', 'ð��¸' => 'ð���', 'ð��¹' => 'ð��‘', 'ð��º' => 'ð��’', 'ð��»' => 'ð��“', 'ð��¼' => 'ð��”', 'ð��½' => 'ð��•', 'ð��¾' => 'ð��–', 'ð��¿' => 'ð��—', 'ð�‘€' => 'ð��˜', 'ð�‘�' => 'ð��™', 'ð�‘‚' => 'ð��š', 'ð�‘ƒ' => 'ð��›', 'ð�‘„' => 'ð��œ', 'ð�‘…' => 'ð���', 'ð�‘†' => 'ð��ž', 'ð�‘‡' => 'ð��Ÿ', 'ð�‘ˆ' => 'ð�� ', 'ð�‘‰' => 'ð��¡', 'ð�‘Š' => 'ð��¢', 'ð�‘‹' => 'ð��£', 'ð�‘Œ' => 'ð��¤', 'ð�‘�' => 'ð��¥', 'ð�‘Ž' => 'ð��¦', 'ð�‘�' => 'ð��§', 'ð�“˜' => 'ð�’°', 'ð�“™' => 'ð�’±', 'ð�“š' => 'ð�’²', 'ð�“›' => 'ð�’³', 'ð�“œ' => 'ð�’´', 'ð�“�' => 'ð�’µ', 'ð�“ž' => 'ð�’¶', 'ð�“Ÿ' => 'ð�’·', 'ð�“ ' => 'ð�’¸', 'ð�“¡' => 'ð�’¹', 'ð�“¢' => 'ð�’º', 'ð�“£' => 'ð�’»', 'ð�“¤' => 'ð�’¼', 'ð�“¥' => 'ð�’½', 'ð�“¦' => 'ð�’¾', 'ð�“§' => 'ð�’¿', 'ð�“¨' => 'ð�“€', 'ð�“©' => 'ð�“�', 'ð�“ª' => 'ð�“‚', 'ð�“«' => 'ð�“ƒ', 'ð�“¬' => 'ð�“„', 'ð�“­' => 'ð�“…', 'ð�“®' => 'ð�“†', 'ð�“¯' => 'ð�“‡', 'ð�“°' => 'ð�“ˆ', 'ð�“±' => 'ð�“‰', 'ð�“²' => 'ð�“Š', 'ð�“³' => 'ð�“‹', 'ð�“´' => 'ð�“Œ', 'ð�“µ' => 'ð�“�', 'ð�“¶' => 'ð�“Ž', 'ð�“·' => 'ð�“�', 'ð�“¸' => 'ð�“�', 'ð�“¹' => 'ð�“‘', 'ð�“º' => 'ð�“’', 'ð�“»' => 'ð�““', 'ð�³€' => 'ð�²€', 'ð�³�' => 'ð�²�', 'ð�³‚' => 'ð�²‚', 'ð�³ƒ' => 'ð�²ƒ', 'ð�³„' => 'ð�²„', 'ð�³…' => 'ð�²…', 'ð�³†' => 'ð�²†', 'ð�³‡' => 'ð�²‡', 'ð�³ˆ' => 'ð�²ˆ', 'ð�³‰' => 'ð�²‰', 'ð�³Š' => 'ð�²Š', 'ð�³‹' => 'ð�²‹', 'ð�³Œ' => 'ð�²Œ', 'ð�³�' => 'ð�²�', 'ð�³Ž' => 'ð�²Ž', 'ð�³�' => 'ð�²�', 'ð�³�' => 'ð�²�', 'ð�³‘' => 'ð�²‘', 'ð�³’' => 'ð�²’', 'ð�³“' => 'ð�²“', 'ð�³”' => 'ð�²”', 'ð�³•' => 'ð�²•', 'ð�³–' => 'ð�²–', 'ð�³—' => 'ð�²—', 'ð�³˜' => 'ð�²˜', 'ð�³™' => 'ð�²™', 'ð�³š' => 'ð�²š', 'ð�³›' => 'ð�²›', 'ð�³œ' => 'ð�²œ', 'ð�³�' => 'ð�²�', 'ð�³ž' => 'ð�²ž', 'ð�³Ÿ' => 'ð�²Ÿ', 'ð�³ ' => 'ð�² ', 'ð�³¡' => 'ð�²¡', 'ð�³¢' => 'ð�²¢', 'ð�³£' => 'ð�²£', 'ð�³¤' => 'ð�²¤', 'ð�³¥' => 'ð�²¥', 'ð�³¦' => 'ð�²¦', 'ð�³§' => 'ð�²§', 'ð�³¨' => 'ð�²¨', 'ð�³©' => 'ð�²©', 'ð�³ª' => 'ð�²ª', 'ð�³«' => 'ð�²«', 'ð�³¬' => 'ð�²¬', 'ð�³­' => 'ð�²­', 'ð�³®' => 'ð�²®', 'ð�³¯' => 'ð�²¯', 'ð�³°' => 'ð�²°', 'ð�³±' => 'ð�²±', 'ð�³²' => 'ð�²²', 'ð‘£€' => 'ð‘¢ ', 'ð‘£�' => 'ð‘¢¡', 'ð‘£‚' => 'ð‘¢¢', 'ð‘£ƒ' => 'ð‘¢£', 'ð‘£„' => 'ð‘¢¤', 'ð‘£…' => 'ð‘¢¥', 'ð‘£†' => 'ð‘¢¦', 'ð‘£‡' => 'ð‘¢§', 'ð‘£ˆ' => 'ð‘¢¨', 'ð‘£‰' => 'ð‘¢©', 'ð‘£Š' => 'ð‘¢ª', 'ð‘£‹' => 'ð‘¢«', 'ð‘£Œ' => 'ð‘¢¬', 'ð‘£�' => 'ð‘¢­', 'ð‘£Ž' => 'ð‘¢®', 'ð‘£�' => 'ð‘¢¯', 'ð‘£�' => 'ð‘¢°', 'ð‘£‘' => 'ð‘¢±', 'ð‘£’' => 'ð‘¢²', 'ð‘£“' => 'ð‘¢³', 'ð‘£”' => 'ð‘¢´', 'ð‘£•' => 'ð‘¢µ', 'ð‘£–' => 'ð‘¢¶', 'ð‘£—' => 'ð‘¢·', 'ð‘£˜' => 'ð‘¢¸', 'ð‘£™' => 'ð‘¢¹', 'ð‘£š' => 'ð‘¢º', 'ð‘£›' => 'ð‘¢»', 'ð‘£œ' => 'ð‘¢¼', 'ð‘£�' => 'ð‘¢½', 'ð‘£ž' => 'ð‘¢¾', 'ð‘£Ÿ' => 'ð‘¢¿', 'ð–¹ ' => 'ð–¹€', 'ð–¹¡' => 'ð–¹�', 'ð–¹¢' => 'ð–¹‚', 'ð–¹£' => 'ð–¹ƒ', 'ð–¹¤' => 'ð–¹„', 'ð–¹¥' => 'ð–¹…', 'ð–¹¦' => 'ð–¹†', 'ð–¹§' => 'ð–¹‡', 'ð–¹¨' => 'ð–¹ˆ', 'ð–¹©' => 'ð–¹‰', 'ð–¹ª' => 'ð–¹Š', 'ð–¹«' => 'ð–¹‹', 'ð–¹¬' => 'ð–¹Œ', 'ð–¹­' => 'ð–¹�', 'ð–¹®' => 'ð–¹Ž', 'ð–¹¯' => 'ð–¹�', 'ð–¹°' => 'ð–¹�', 'ð–¹±' => 'ð–¹‘', 'ð–¹²' => 'ð–¹’', 'ð–¹³' => 'ð–¹“', 'ð–¹´' => 'ð–¹”', 'ð–¹µ' => 'ð–¹•', 'ð–¹¶' => 'ð–¹–', 'ð–¹·' => 'ð–¹—', 'ð–¹¸' => 'ð–¹˜', 'ð–¹¹' => 'ð–¹™', 'ð–¹º' => 'ð–¹š', 'ð–¹»' => 'ð–¹›', 'ð–¹¼' => 'ð–¹œ', 'ð–¹½' => 'ð–¹�', 'ð–¹¾' => 'ð–¹ž', 'ð–¹¿' => 'ð–¹Ÿ', 'ðž¤¢' => 'ðž¤€', 'ðž¤£' => 'ðž¤�', 'ðž¤¤' => 'ðž¤‚', 'ðž¤¥' => 'ðž¤ƒ', 'ðž¤¦' => 'ðž¤„', 'ðž¤§' => 'ðž¤…', 'ðž¤¨' => 'ðž¤†', 'ðž¤©' => 'ðž¤‡', 'ðž¤ª' => 'ðž¤ˆ', 'ðž¤«' => 'ðž¤‰', 'ðž¤¬' => 'ðž¤Š', 'ðž¤­' => 'ðž¤‹', 'ðž¤®' => 'ðž¤Œ', 'ðž¤¯' => 'ðž¤�', 'ðž¤°' => 'ðž¤Ž', 'ðž¤±' => 'ðž¤�', 'ðž¤²' => 'ðž¤�', 'ðž¤³' => 'ðž¤‘', 'ðž¤´' => 'ðž¤’', 'ðž¤µ' => 'ðž¤“', 'ðž¤¶' => 'ðž¤”', 'ðž¤·' => 'ðž¤•', 'ðž¤¸' => 'ðž¤–', 'ðž¤¹' => 'ðž¤—', 'ðž¤º' => 'ðž¤˜', 'ðž¤»' => 'ðž¤™', 'ðž¤¼' => 'ðž¤š', 'ðž¤½' => 'ðž¤›', 'ðž¤¾' => 'ðž¤œ', 'ðž¤¿' => 'ðž¤�', 'ðž¥€' => 'ðž¤ž', 'ðž¥�' => 'ðž¤Ÿ', 'ðž¥‚' => 'ðž¤ ', 'ðž¥ƒ' => 'ðž¤¡', 'ÃŸ' => 'SS', 'ï¬€' => 'FF', 'ï¬�' => 'FI', 'ï¬‚' => 'FL', 'ï¬ƒ' => 'FFI', 'ï¬„' => 'FFL', 'ï¬…' => 'ST', 'ï¬†' => 'ST', 'Ö‡' => 'ÔµÕ’', 'ï¬“' => 'Õ„Õ†', 'ï¬”' => 'Õ„Ôµ', 'ï¬•' => 'Õ„Ô»', 'ï¬–' => 'ÕŽÕ†', 'ï¬—' => 'Õ„Ô½', 'Å‰' => 'Ê¼N', 'Î�' => 'Î™ÌˆÌ�', 'Î°' => 'Î¥ÌˆÌ�', 'Ç°' => 'JÌŒ', 'áº–' => 'HÌ±', 'áº—' => 'TÌˆ', 'áº˜' => 'WÌŠ', 'áº™' => 'YÌŠ', 'áºš' => 'AÊ¾', 'á½�' => 'Î¥Ì“', 'á½’' => 'Î¥Ì“Ì€', 'á½”' => 'Î¥Ì“Ì�', 'á½–' => 'Î¥Ì“Í‚', 'á¾¶' => 'Î‘Í‚', 'á¿†' => 'Î—Í‚', 'á¿’' => 'Î™ÌˆÌ€', 'á¿“' => 'Î™ÌˆÌ�', 'á¿–' => 'Î™Í‚', 'á¿—' => 'Î™ÌˆÍ‚', 'á¿¢' => 'Î¥ÌˆÌ€', 'á¿£' => 'Î¥ÌˆÌ�', 'á¿¤' => 'Î¡Ì“', 'á¿¦' => 'Î¥Í‚', 'á¿§' => 'Î¥ÌˆÍ‚', 'á¿¶' => 'Î©Í‚', 'á¾ˆ' => 'á¼ˆÎ™', 'á¾‰' => 'á¼‰Î™', 'á¾Š' => 'á¼ŠÎ™', 'á¾‹' => 'á¼‹Î™', 'á¾Œ' => 'á¼ŒÎ™', 'á¾�' => 'á¼�Î™', 'á¾Ž' => 'á¼ŽÎ™', 'á¾�' => 'á¼�Î™', 'á¾˜' => 'á¼¨Î™', 'á¾™' => 'á¼©Î™', 'á¾š' => 'á¼ªÎ™', 'á¾›' => 'á¼«Î™', 'á¾œ' => 'á¼¬Î™', 'á¾�' => 'á¼­Î™', 'á¾ž' => 'á¼®Î™', 'á¾Ÿ' => 'á¼¯Î™', 'á¾¨' => 'á½¨Î™', 'á¾©' => 'á½©Î™', 'á¾ª' => 'á½ªÎ™', 'á¾«' => 'á½«Î™', 'á¾¬' => 'á½¬Î™', 'á¾­' => 'á½­Î™', 'á¾®' => 'á½®Î™', 'á¾¯' => 'á½¯Î™', 'á¾¼' => 'Î‘Î™', 'á¿Œ' => 'Î—Î™', 'á¿¼' => 'Î©Î™', 'á¾²' => 'á¾ºÎ™', 'á¾´' => 'Î†Î™', 'á¿‚' => 'á¿ŠÎ™', 'á¿„' => 'Î‰Î™', 'á¿²' => 'á¿ºÎ™', 'á¿´' => 'Î�Î™', 'á¾·' => 'Î‘Í‚Î™', 'á¿‡' => 'Î—Í‚Î™', 'á¿·' => 'Î©Í‚Î™');<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Mbstring;

/**
 * Partial mbstring implementation in PHP, iconv based, UTF-8 centric.
 *
 * Implemented:
 * - mb_chr                  - Returns a specific character from its Unicode code point
 * - mb_convert_encoding     - Convert character encoding
 * - mb_convert_variables    - Convert character code in variable(s)
 * - mb_decode_mimeheader    - Decode string in MIME header field
 * - mb_encode_mimeheader    - Encode string for MIME header XXX NATIVE IMPLEMENTATION IS REALLY BUGGED
 * - mb_decode_numericentity - Decode HTML numeric string reference to character
 * - mb_encode_numericentity - Encode character to HTML numeric string reference
 * - mb_convert_case         - Perform case folding on a string
 * - mb_detect_encoding      - Detect character encoding
 * - mb_get_info             - Get internal settings of mbstring
 * - mb_http_input           - Detect HTTP input character encoding
 * - mb_http_output          - Set/Get HTTP output character encoding
 * - mb_internal_encoding    - Set/Get internal character encoding
 * - mb_list_encodings       - Returns an array of all supported encodings
 * - mb_ord                  - Returns the Unicode code point of a character
 * - mb_output_handler       - Callback function converts character encoding in output buffer
 * - mb_scrub                - Replaces ill-formed byte sequences with substitute characters
 * - mb_strlen               - Get string length
 * - mb_strpos               - Find position of first occurrence of string in a string
 * - mb_strrpos              - Find position of last occurrence of a string in a string
 * - mb_str_split            - Convert a string to an array
 * - mb_strtolower           - Make a string lowercase
 * - mb_strtoupper           - Make a string uppercase
 * - mb_substitute_character - Set/Get substitution character
 * - mb_substr               - Get part of string
 * - mb_stripos              - Finds position of first occurrence of a string within another, case insensitive
 * - mb_stristr              - Finds first occurrence of a string within another, case insensitive
 * - mb_strrchr              - Finds the last occurrence of a character in a string within another
 * - mb_strrichr             - Finds the last occurrence of a character in a string within another, case insensitive
 * - mb_strripos             - Finds position of last occurrence of a string within another, case insensitive
 * - mb_strstr               - Finds first occurrence of a string within another
 * - mb_strwidth             - Return width of string
 * - mb_substr_count         - Count the number of substring occurrences
 *
 * Not implemented:
 * - mb_convert_kana         - Convert "kana" one from another ("zen-kaku", "han-kaku" and more)
 * - mb_ereg_*               - Regular expression with multibyte support
 * - mb_parse_str            - Parse GET/POST/COOKIE data and set global variable
 * - mb_preferred_mime_name  - Get MIME charset string
 * - mb_regex_encoding       - Returns current encoding for multibyte regex as string
 * - mb_regex_set_options    - Set/Get the default options for mbregex functions
 * - mb_send_mail            - Send encoded mail
 * - mb_split                - Split multibyte string using regular expression
 * - mb_strcut               - Get part of string
 * - mb_strimwidth           - Get truncated string with specified width
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Mbstring
{
    public const MB_CASE_FOLD = \PHP_INT_MAX;
    private const CASE_FOLD = [['Âµ', 'Å¿', "Í…", 'Ï‚', "Ï�", "Ï‘", "Ï•", "Ï–", "Ï°", "Ï±", "Ïµ", "áº›", "á¾¾"], ['Î¼', 's', 'Î¹', 'Ïƒ', 'Î²', 'Î¸', 'Ï†', 'Ï€', 'Îº', 'Ï�', 'Îµ', "á¹¡", 'Î¹']];
    private static $encodingList = ['ASCII', 'UTF-8'];
    private static $language = 'neutral';
    private static $internalEncoding = 'UTF-8';
    /**
     *
     */
    public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null)
    {
        if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) {
            $fromEncoding = self::mb_detect_encoding($s, $fromEncoding);
        } else {
            $fromEncoding = self::getEncoding($fromEncoding);
        }
        $toEncoding = self::getEncoding($toEncoding);
        if ('BASE64' === $fromEncoding) {
            $s = base64_decode($s);
            $fromEncoding = $toEncoding;
        }
        if ('BASE64' === $toEncoding) {
            return base64_encode($s);
        }
        if ('HTML-ENTITIES' === $toEncoding || 'HTML' === $toEncoding) {
            if ('HTML-ENTITIES' === $fromEncoding || 'HTML' === $fromEncoding) {
                $fromEncoding = 'Windows-1252';
            }
            if ('UTF-8' !== $fromEncoding) {
                $s = \iconv($fromEncoding, 'UTF-8//IGNORE', $s);
            }
            return preg_replace_callback('/[\\x80-\\xFF]+/', [__CLASS__, 'html_encoding_callback'], $s);
        }
        if ('HTML-ENTITIES' === $fromEncoding) {
            $s = \Phabel\Target\Php80\Polyfill::html_entity_decode($s, \ENT_COMPAT, 'UTF-8');
            $fromEncoding = 'UTF-8';
        }
        return \iconv($fromEncoding, $toEncoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_convert_variables($toEncoding, $fromEncoding, &...$vars)
    {
        $ok = true;
        array_walk_recursive($vars, function (&$v) use(&$ok, $toEncoding, $fromEncoding) {
            if (false === ($v = self::mb_convert_encoding($v, $toEncoding, $fromEncoding))) {
                $ok = false;
            }
        });
        return $ok ? $fromEncoding : false;
    }
    /**
     *
     */
    public static function mb_decode_mimeheader($s)
    {
        return \Phabel\Target\Php80\Polyfill::iconv_mime_decode($s, 2, self::$internalEncoding);
    }
    /**
     *
     */
    public static function mb_encode_mimeheader($s, $charset = null, $transferEncoding = null, $linefeed = null, $indent = null)
    {
        trigger_error('mb_encode_mimeheader() is bugged. Please use iconv_mime_encode() instead', \E_USER_WARNING);
    }
    /**
     *
     */
    public static function mb_decode_numericentity($s, $convmap, $encoding = null)
    {
        if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_decode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
            return false;
        }
        if (null !== $encoding && !is_scalar($encoding)) {
            trigger_error('mb_decode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return '';
            // Instead of null (cf. mb_encode_numericentity).
        }
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        $cnt = floor(\count($convmap) / 4) * 4;
        for ($i = 0; $i < $cnt; $i += 4) {
            // collector_decode_htmlnumericentity ignores $convmap[$i + 3]
            $convmap[$i] += $convmap[$i + 2];
            $convmap[$i + 1] += $convmap[$i + 2];
        }
        $s = preg_replace_callback('/&#(?:0*([0-9]+)|x0*([0-9a-fA-F]+))(?!&);?/', function (array $m) use($cnt, $convmap) {
            $c = isset($m[2]) ? (int) hexdec($m[2]) : $m[1];
            for ($i = 0; $i < $cnt; $i += 4) {
                if ($c >= $convmap[$i] && $c <= $convmap[$i + 1]) {
                    return self::mb_chr($c - $convmap[$i + 2]);
                }
            }
            return $m[0];
        }, $s);
        if (null === $encoding) {
            return $s;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false)
    {
        if (null !== $s && !is_scalar($s) && !(\is_object($s) && method_exists($s, '__toString'))) {
            trigger_error('mb_encode_numericentity() expects parameter 1 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        if (!\is_array($convmap) || 80000 > \PHP_VERSION_ID && !$convmap) {
            return false;
        }
        if (null !== $encoding && !is_scalar($encoding)) {
            trigger_error('mb_encode_numericentity() expects parameter 3 to be string, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
            // Instead of '' (cf. mb_decode_numericentity).
        }
        if (null !== $is_hex && !is_scalar($is_hex)) {
            trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, ' . \gettype($s) . ' given', \E_USER_WARNING);
            return null;
        }
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
        $cnt = floor(\count($convmap) / 4) * 4;
        $i = 0;
        $len = \strlen($s);
        $result = '';
        while ($i < $len) {
            $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
            $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i, $ulen);
            $i += $ulen;
            $c = self::mb_ord($uchr);
            for ($j = 0; $j < $cnt; $j += 4) {
                if ($c >= $convmap[$j] && $c <= $convmap[$j + 1]) {
                    $cOffset = $c + $convmap[$j + 2] & $convmap[$j + 3];
                    $result .= $is_hex ? sprintf('&#x%X;', $cOffset) : '&#' . $cOffset . ';';
                    continue 2;
                }
            }
            $result .= $uchr;
        }
        if (null === $encoding) {
            return $result;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $result);
    }
    /**
     *
     */
    public static function mb_convert_case($s, $mode, $encoding = null)
    {
        $s = (string) $s;
        if ('' === $s) {
            return '';
        }
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' === $encoding) {
            $encoding = null;
            if (!preg_match('//u', $s)) {
                $s = @\iconv('UTF-8', 'UTF-8//IGNORE', $s);
            }
        } else {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        if (\MB_CASE_TITLE == $mode) {
            static $titleRegexp = null;
            if (null === $titleRegexp) {
                $titleRegexp = self::getData('titleCaseRegexp');
            }
            $s = preg_replace_callback($titleRegexp, [__CLASS__, 'title_case'], $s);
        } else {
            if (\MB_CASE_UPPER == $mode) {
                static $upper = null;
                if (null === $upper) {
                    $upper = self::getData('upperCase');
                }
                $map = $upper;
            } else {
                if (self::MB_CASE_FOLD === $mode) {
                    $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
                }
                static $lower = null;
                if (null === $lower) {
                    $lower = self::getData('lowerCase');
                }
                $map = $lower;
            }
            static $ulenMask = ["\xc0" => 2, "\xd0" => 2, "\xe0" => 3, "\xf0" => 4];
            $i = 0;
            $len = \strlen($s);
            while ($i < $len) {
                $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xf0"];
                $uchr = \Phabel\Target\Php80\Polyfill::substr($s, $i, $ulen);
                $i += $ulen;
                if (isset($map[$uchr])) {
                    $uchr = $map[$uchr];
                    $nlen = \strlen($uchr);
                    if ($nlen == $ulen) {
                        $nlen = $i;
                        do {
                            $s[--$nlen] = $uchr[--$ulen];
                        } while ($ulen);
                    } else {
                        $s = \Phabel\Target\Php80\Polyfill::substr_replace($s, $uchr, $i - $ulen, $ulen);
                        $len += $nlen - $ulen;
                        $i += $nlen - $ulen;
                    }
                }
            }
        }
        if (null === $encoding) {
            return $s;
        }
        return \iconv('UTF-8', $encoding . '//IGNORE', $s);
    }
    /**
     *
     */
    public static function mb_internal_encoding($encoding = null)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }
        $normalizedEncoding = self::getEncoding($encoding);
        if ('UTF-8' === $normalizedEncoding || false !== @\iconv($normalizedEncoding, $normalizedEncoding, ' ')) {
            self::$internalEncoding = $normalizedEncoding;
            return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError(sprintf('Argument #1 ($encoding) must be a valid encoding, "%s" given', $encoding));
    }
    /**
     *
     */
    public static function mb_language($lang = null)
    {
        if (null === $lang) {
            return self::$language;
        }
        switch ($normalizedLang = strtolower($lang)) {
            case 'uni':
            case 'neutral':
                self::$language = $normalizedLang;
                return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError(sprintf('Argument #1 ($language) must be a valid language, "%s" given', $lang));
    }
    /**
     *
     */
    public static function mb_list_encodings()
    {
        return ['UTF-8'];
    }
    /**
     *
     */
    public static function mb_encoding_aliases($encoding)
    {
        switch (strtoupper($encoding)) {
            case 'UTF8':
            case 'UTF-8':
                return ['utf8'];
        }
        return false;
    }
    /**
     *
     */
    public static function mb_check_encoding($var = null, $encoding = null)
    {
        if (null === $encoding) {
            if (null === $var) {
                return false;
            }
            $encoding = self::$internalEncoding;
        }
        return self::mb_detect_encoding($var, [$encoding]) || false !== @\iconv($encoding, $encoding, $var);
    }
    /**
     *
     */
    public static function mb_detect_encoding($str, $encodingList = null, $strict = false)
    {
        if (null === $encodingList) {
            $encodingList = self::$encodingList;
        } else {
            if (!\is_array($encodingList)) {
                $encodingList = array_map('trim', explode(',', $encodingList));
            }
            $encodingList = array_map('strtoupper', $encodingList);
        }
        foreach ($encodingList as $enc) {
            switch ($enc) {
                case 'ASCII':
                    if (!preg_match('/[\\x80-\\xFF]/', $str)) {
                        return $enc;
                    }
                    break;
                case 'UTF8':
                case 'UTF-8':
                    if (preg_match('//u', $str)) {
                        return 'UTF-8';
                    }
                    break;
                default:
                    if (0 === strncmp($enc, 'ISO-8859-', 9)) {
                        return $enc;
                    }
            }
        }
        return false;
    }
    /**
     *
     */
    public static function mb_detect_order($encodingList = null)
    {
        if (null === $encodingList) {
            return self::$encodingList;
        }
        if (!\is_array($encodingList)) {
            $encodingList = array_map('trim', explode(',', $encodingList));
        }
        $encodingList = array_map('strtoupper', $encodingList);
        foreach ($encodingList as $enc) {
            switch ($enc) {
                default:
                    if (strncmp($enc, 'ISO-8859-', 9)) {
                        return false;
                    }
                // no break
                case 'ASCII':
                case 'UTF8':
                case 'UTF-8':
            }
        }
        self::$encodingList = $encodingList;
        return true;
    }
    /**
     *
     */
    public static function mb_strlen($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return \strlen($s);
        }
        return @\Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding);
    }
    /**
     *
     */
    public static function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strpos($haystack, $needle, $offset);
        }
        $needle = (string) $needle;
        if ('' === $needle) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error(__METHOD__ . ': Empty delimiter', \E_USER_WARNING);
                return false;
            }
            return 0;
        }
        return \Phabel\Target\Php80\Polyfill::iconv_strpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return strrpos($haystack, $needle, $offset);
        }
        if ($offset != (int) $offset) {
            $offset = 0;
        } elseif ($offset = (int) $offset) {
            if ($offset < 0) {
                if (0 > ($offset += self::mb_strlen($needle))) {
                    $haystack = self::mb_substr($haystack, 0, $offset, $encoding);
                }
                $offset = 0;
            } else {
                $haystack = self::mb_substr($haystack, $offset, 2147483647, $encoding);
            }
        }
        $pos = '' !== $needle || 80000 > \PHP_VERSION_ID ? \Phabel\Target\Php80\Polyfill::iconv_strrpos($haystack, $needle, $encoding) : self::mb_strlen($haystack, $encoding);
        return false !== $pos ? $offset + $pos : false;
    }
    /**
     *
     */
    public static function mb_str_split($string, $split_length = 1, $encoding = null)
    {
        if (null !== $string && !is_scalar($string) && !(\is_object($string) && method_exists($string, '__toString'))) {
            trigger_error('mb_str_split() expects parameter 1 to be string, ' . \gettype($string) . ' given', \E_USER_WARNING);
            return null;
        }
        if (1 > ($split_length = (int) $split_length)) {
            if (80000 > \PHP_VERSION_ID) {
                trigger_error('The length of each segment must be greater than zero', \E_USER_WARNING);
                return false;
            }
            throw new \ValueError('Argument #2 ($length) must be greater than 0');
        }
        if (null === $encoding) {
            $encoding = mb_internal_encoding();
        }
        if ('UTF-8' === ($encoding = self::getEncoding($encoding))) {
            $rx = '/(';
            while (65535 < $split_length) {
                $rx .= '.{65535}';
                $split_length -= 65535;
            }
            $rx .= '.{' . $split_length . '})/us';
            return preg_split($rx, $string, null, \PREG_SPLIT_DELIM_CAPTURE | \PREG_SPLIT_NO_EMPTY);
        }
        $result = [];
        $length = mb_strlen($string, $encoding);
        for ($i = 0; $i < $length; $i += $split_length) {
            $result[] = mb_substr($string, $i, $split_length, $encoding);
        }
        return $result;
    }
    /**
     *
     */
    public static function mb_strtolower($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_LOWER, $encoding);
    }
    /**
     *
     */
    public static function mb_strtoupper($s, $encoding = null)
    {
        return self::mb_convert_case($s, \MB_CASE_UPPER, $encoding);
    }
    /**
     *
     */
    public static function mb_substitute_character($c = null)
    {
        if (null === $c) {
            return 'none';
        }
        if (0 === strcasecmp($c, 'none')) {
            return true;
        }
        if (80000 > \PHP_VERSION_ID) {
            return false;
        }
        throw new \ValueError('Argument #1 ($substitute_character) must be "none", "long", "entity" or a valid codepoint');
    }
    /**
     *
     */
    public static function mb_substr($s, $start, $length = null, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            return (string) \Phabel\Target\Php80\Polyfill::substr($s, $start, null === $length ? 2147483647 : $length);
        }
        if ($start < 0) {
            $start = \Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding) + $start;
            if ($start < 0) {
                $start = 0;
            }
        }
        if (null === $length) {
            $length = 2147483647;
        } elseif ($length < 0) {
            $length = \Phabel\Target\Php80\Polyfill::iconv_strlen($s, $encoding) + $length - $start;
            if ($length < 0) {
                return '';
            }
        }
        return (string) \Phabel\Target\Php80\Polyfill::iconv_substr($s, $start, $length, $encoding);
    }
    /**
     *
     */
    public static function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
        return self::mb_strpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_stristr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = self::mb_stripos($haystack, $needle, 0, $encoding);
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strrchr($haystack, $needle, $part = false, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('CP850' === $encoding || 'ASCII' === $encoding) {
            $pos = strrpos($haystack, $needle);
        } else {
            $needle = self::mb_substr($needle, 0, 1, $encoding);
            $pos = \Phabel\Target\Php80\Polyfill::iconv_strrpos($haystack, $needle, $encoding);
        }
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strrichr($haystack, $needle, $part = false, $encoding = null)
    {
        $needle = self::mb_substr($needle, 0, 1, $encoding);
        $pos = self::mb_strripos($haystack, $needle, $encoding);
        return self::getSubpart($pos, $part, $haystack, $encoding);
    }
    /**
     *
     */
    public static function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        $haystack = self::mb_convert_case($haystack, self::MB_CASE_FOLD, $encoding);
        $needle = self::mb_convert_case($needle, self::MB_CASE_FOLD, $encoding);
        return self::mb_strrpos($haystack, $needle, $offset, $encoding);
    }
    /**
     *
     */
    public static function mb_strstr($haystack, $needle, $part = false, $encoding = null)
    {
        $pos = strpos($haystack, $needle);
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return \Phabel\Target\Php80\Polyfill::substr($haystack, 0, $pos);
        }
        return \Phabel\Target\Php80\Polyfill::substr($haystack, $pos);
    }
    /**
     *
     */
    public static function mb_get_info($type = 'all')
    {
        $info = ['internal_encoding' => self::$internalEncoding, 'http_output' => 'pass', 'http_output_conv_mimetypes' => '^(text/|application/xhtml\\+xml)', 'func_overload' => 0, 'func_overload_list' => 'no overload', 'mail_charset' => 'UTF-8', 'mail_header_encoding' => 'BASE64', 'mail_body_encoding' => 'BASE64', 'illegal_chars' => 0, 'encoding_translation' => 'Off', 'language' => self::$language, 'detect_order' => self::$encodingList, 'substitute_character' => 'none', 'strict_detection' => 'Off'];
        if ('all' === $type) {
            return $info;
        }
        if (isset($info[$type])) {
            return $info[$type];
        }
        return false;
    }
    /**
     *
     */
    public static function mb_http_input($type = '')
    {
        return false;
    }
    /**
     *
     */
    public static function mb_http_output($encoding = null)
    {
        return null !== $encoding ? 'pass' === $encoding : 'pass';
    }
    /**
     *
     */
    public static function mb_strwidth($s, $encoding = null)
    {
        $encoding = self::getEncoding($encoding);
        if ('UTF-8' !== $encoding) {
            $s = \iconv($encoding, 'UTF-8//IGNORE', $s);
        }
        $s = preg_replace('/[\\x{1100}-\\x{115F}\\x{2329}\\x{232A}\\x{2E80}-\\x{303E}\\x{3040}-\\x{A4CF}\\x{AC00}-\\x{D7A3}\\x{F900}-\\x{FAFF}\\x{FE10}-\\x{FE19}\\x{FE30}-\\x{FE6F}\\x{FF00}-\\x{FF60}\\x{FFE0}-\\x{FFE6}\\x{20000}-\\x{2FFFD}\\x{30000}-\\x{3FFFD}]/u', '', $s, -1, $wide);
        return ($wide << 1) + \Phabel\Target\Php80\Polyfill::iconv_strlen($s, 'UTF-8');
    }
    /**
     *
     */
    public static function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return \Phabel\Target\Php80\Polyfill::substr_count($haystack, $needle);
    }
    /**
     *
     */
    public static function mb_output_handler($contents, $status)
    {
        return $contents;
    }
    /**
     *
     */
    public static function mb_chr($code, $encoding = null)
    {
        if (0x80 > ($code %= 0x200000)) {
            $s = \chr($code);
        } elseif (0x800 > $code) {
            $s = \chr(0xc0 | $code >> 6) . \chr(0x80 | $code & 0x3f);
        } elseif (0x10000 > $code) {
            $s = \chr(0xe0 | $code >> 12) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
        } else {
            $s = \chr(0xf0 | $code >> 18) . \chr(0x80 | $code >> 12 & 0x3f) . \chr(0x80 | $code >> 6 & 0x3f) . \chr(0x80 | $code & 0x3f);
        }
        if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) {
            $s = mb_convert_encoding($s, $encoding, 'UTF-8');
        }
        return $s;
    }
    /**
     *
     */
    public static function mb_ord($s, $encoding = null)
    {
        if ('UTF-8' !== ($encoding = self::getEncoding($encoding))) {
            $s = mb_convert_encoding($s, 'UTF-8', $encoding);
        }
        if (1 === \strlen($s)) {
            return \ord($s);
        }
        $code = ($s = unpack('C*', \Phabel\Target\Php80\Polyfill::substr($s, 0, 4))) ? $s[1] : 0;
        if (0xf0 <= $code) {
            return ($code - 0xf0 << 18) + ($s[2] - 0x80 << 12) + ($s[3] - 0x80 << 6) + $s[4] - 0x80;
        }
        if (0xe0 <= $code) {
            return ($code - 0xe0 << 12) + ($s[2] - 0x80 << 6) + $s[3] - 0x80;
        }
        if (0xc0 <= $code) {
            return ($code - 0xc0 << 6) + $s[2] - 0x80;
        }
        return $code;
    }
    /**
     *
     */
    private static function getSubpart($pos, $part, $haystack, $encoding)
    {
        if (false === $pos) {
            return false;
        }
        if ($part) {
            return self::mb_substr($haystack, 0, $pos, $encoding);
        }
        return self::mb_substr($haystack, $pos, null, $encoding);
    }
    /**
     *
     */
    private static function html_encoding_callback(array $m)
    {
        $i = 1;
        $entities = '';
        $m = unpack('C*', \Phabel\Target\Php80\Polyfill::htmlentities($m[0], \ENT_COMPAT, 'UTF-8'));
        while (isset($m[$i])) {
            if (0x80 > $m[$i]) {
                $entities .= \chr($m[$i++]);
                continue;
            }
            if (0xf0 <= $m[$i]) {
                $c = ($m[$i++] - 0xf0 << 18) + ($m[$i++] - 0x80 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
            } elseif (0xe0 <= $m[$i]) {
                $c = ($m[$i++] - 0xe0 << 12) + ($m[$i++] - 0x80 << 6) + $m[$i++] - 0x80;
            } else {
                $c = ($m[$i++] - 0xc0 << 6) + $m[$i++] - 0x80;
            }
            $entities .= '&#' . $c . ';';
        }
        return $entities;
    }
    /**
     *
     */
    private static function title_case(array $s)
    {
        return self::mb_convert_case($s[1], \MB_CASE_UPPER, 'UTF-8') . self::mb_convert_case($s[2], \MB_CASE_LOWER, 'UTF-8');
    }
    /**
     *
     */
    private static function getData($file)
    {
        if (file_exists($file = __DIR__ . '/Resources/unidata/' . $file . '.php')) {
            return require $file;
        }
        return false;
    }
    /**
     *
     */
    private static function getEncoding($encoding)
    {
        if (null === $encoding) {
            return self::$internalEncoding;
        }
        if ('UTF-8' === $encoding) {
            return 'UTF-8';
        }
        $encoding = strtoupper($encoding);
        if ('8BIT' === $encoding || 'BINARY' === $encoding) {
            return 'CP850';
        }
        if ('UTF8' === $encoding) {
            return 'UTF-8';
        }
        return $encoding;
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Mbstring as p;
if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__ . '/bootstrap80.php';
}
if (!function_exists('mb_convert_encoding')) {
    /**
     *
     */
    function mb_convert_encoding($string, $to_encoding, $from_encoding = null)
    {
        return p\Mbstring::mb_convert_encoding($string, $to_encoding, $from_encoding);
    }
}
if (!function_exists('mb_decode_mimeheader')) {
    /**
     *
     */
    function mb_decode_mimeheader($string)
    {
        return p\Mbstring::mb_decode_mimeheader($string);
    }
}
if (!function_exists('mb_encode_mimeheader')) {
    /**
     *
     */
    function mb_encode_mimeheader($string, $charset = null, $transfer_encoding = null, $newline = "\r\n", $indent = 0)
    {
        return p\Mbstring::mb_encode_mimeheader($string, $charset, $transfer_encoding, $newline, $indent);
    }
}
if (!function_exists('mb_decode_numericentity')) {
    /**
     *
     */
    function mb_decode_numericentity($string, $map, $encoding = null)
    {
        return p\Mbstring::mb_decode_numericentity($string, $map, $encoding);
    }
}
if (!function_exists('mb_encode_numericentity')) {
    /**
     *
     */
    function mb_encode_numericentity($string, $map, $encoding = null, $hex = false)
    {
        return p\Mbstring::mb_encode_numericentity($string, $map, $encoding, $hex);
    }
}
if (!function_exists('mb_convert_case')) {
    /**
     *
     */
    function mb_convert_case($string, $mode, $encoding = null)
    {
        return p\Mbstring::mb_convert_case($string, $mode, $encoding);
    }
}
if (!function_exists('mb_internal_encoding')) {
    /**
     *
     */
    function mb_internal_encoding($encoding = null)
    {
        return p\Mbstring::mb_internal_encoding($encoding);
    }
}
if (!function_exists('mb_language')) {
    /**
     *
     */
    function mb_language($language = null)
    {
        return p\Mbstring::mb_language($language);
    }
}
if (!function_exists('mb_list_encodings')) {
    /**
     *
     */
    function mb_list_encodings()
    {
        return p\Mbstring::mb_list_encodings();
    }
}
if (!function_exists('mb_encoding_aliases')) {
    /**
     *
     */
    function mb_encoding_aliases($encoding)
    {
        return p\Mbstring::mb_encoding_aliases($encoding);
    }
}
if (!function_exists('mb_check_encoding')) {
    /**
     *
     */
    function mb_check_encoding($value = null, $encoding = null)
    {
        return p\Mbstring::mb_check_encoding($value, $encoding);
    }
}
if (!function_exists('mb_detect_encoding')) {
    /**
     *
     */
    function mb_detect_encoding($string, $encodings = null, $strict = false)
    {
        return p\Mbstring::mb_detect_encoding($string, $encodings, $strict);
    }
}
if (!function_exists('mb_detect_order')) {
    /**
     *
     */
    function mb_detect_order($encoding = null)
    {
        return p\Mbstring::mb_detect_order($encoding);
    }
}
if (!function_exists('mb_parse_str')) {
    /**
     *
     */
    function mb_parse_str($string, &$result = [])
    {
        parse_str($string, $result);
        return (bool) $result;
    }
}
if (!function_exists('mb_strlen')) {
    /**
     *
     */
    function mb_strlen($string, $encoding = null)
    {
        return p\Mbstring::mb_strlen($string, $encoding);
    }
}
if (!function_exists('mb_strpos')) {
    /**
     *
     */
    function mb_strpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strpos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strtolower')) {
    /**
     *
     */
    function mb_strtolower($string, $encoding = null)
    {
        return p\Mbstring::mb_strtolower($string, $encoding);
    }
}
if (!function_exists('mb_strtoupper')) {
    /**
     *
     */
    function mb_strtoupper($string, $encoding = null)
    {
        return p\Mbstring::mb_strtoupper($string, $encoding);
    }
}
if (!function_exists('mb_substitute_character')) {
    /**
     *
     */
    function mb_substitute_character($substitute_character = null)
    {
        return p\Mbstring::mb_substitute_character($substitute_character);
    }
}
if (!function_exists('mb_substr')) {
    /**
     *
     */
    function mb_substr($string, $start, $length = 2147483647, $encoding = null)
    {
        return p\Mbstring::mb_substr($string, $start, $length, $encoding);
    }
}
if (!function_exists('mb_stripos')) {
    /**
     *
     */
    function mb_stripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_stripos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_stristr')) {
    /**
     *
     */
    function mb_stristr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_stristr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strrchr')) {
    /**
     *
     */
    function mb_strrchr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strrchr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strrichr')) {
    /**
     *
     */
    function mb_strrichr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strrichr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_strripos')) {
    /**
     *
     */
    function mb_strripos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strripos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strrpos')) {
    /**
     *
     */
    function mb_strrpos($haystack, $needle, $offset = 0, $encoding = null)
    {
        return p\Mbstring::mb_strrpos($haystack, $needle, $offset, $encoding);
    }
}
if (!function_exists('mb_strstr')) {
    /**
     *
     */
    function mb_strstr($haystack, $needle, $before_needle = false, $encoding = null)
    {
        return p\Mbstring::mb_strstr($haystack, $needle, $before_needle, $encoding);
    }
}
if (!function_exists('mb_get_info')) {
    /**
     *
     */
    function mb_get_info($type = 'all')
    {
        return p\Mbstring::mb_get_info($type);
    }
}
if (!function_exists('mb_http_output')) {
    /**
     *
     */
    function mb_http_output($encoding = null)
    {
        return p\Mbstring::mb_http_output($encoding);
    }
}
if (!function_exists('mb_strwidth')) {
    /**
     *
     */
    function mb_strwidth($string, $encoding = null)
    {
        return p\Mbstring::mb_strwidth($string, $encoding);
    }
}
if (!function_exists('mb_substr_count')) {
    /**
     *
     */
    function mb_substr_count($haystack, $needle, $encoding = null)
    {
        return p\Mbstring::mb_substr_count($haystack, $needle, $encoding);
    }
}
if (!function_exists('mb_output_handler')) {
    /**
     *
     */
    function mb_output_handler($string, $status)
    {
        return p\Mbstring::mb_output_handler($string, $status);
    }
}
if (!function_exists('mb_http_input')) {
    /**
     *
     */
    function mb_http_input($type = null)
    {
        return p\Mbstring::mb_http_input($type);
    }
}
if (!function_exists('mb_convert_variables')) {
    /**
     *
     */
    function mb_convert_variables($to_encoding, $from_encoding, &...$vars)
    {
        return p\Mbstring::mb_convert_variables($to_encoding, $from_encoding, ...$vars);
    }
}
if (!function_exists('mb_ord')) {
    /**
     *
     */
    function mb_ord($string, $encoding = null)
    {
        return p\Mbstring::mb_ord($string, $encoding);
    }
}
if (!function_exists('mb_chr')) {
    /**
     *
     */
    function mb_chr($codepoint, $encoding = null)
    {
        return p\Mbstring::mb_chr($codepoint, $encoding);
    }
}
if (!function_exists('mb_scrub')) {
    /**
     *
     */
    function mb_scrub($string, $encoding = null)
    {
        $encoding = null === $encoding ? mb_internal_encoding() : $encoding;
        return mb_convert_encoding($string, $encoding, $encoding);
    }
}
if (!function_exists('mb_str_split')) {
    /**
     *
     */
    function mb_str_split($string, $length = 1, $encoding = null)
    {
        return p\Mbstring::mb_str_split($string, $length, $encoding);
    }
}
if (extension_loaded('mbstring')) {
    return;
}
if (!defined('MB_CASE_UPPER')) {
    define('MB_CASE_UPPER', 0);
}
if (!defined('MB_CASE_LOWER')) {
    define('MB_CASE_LOWER', 1);
}
if (!defined('MB_CASE_TITLE')) {
    define('MB_CASE_TITLE', 2);
}{
    "name": "symfony/polyfill-mbstring",
    "type": "library",
    "description": "Symfony polyfill for the Mbstring extension",
    "keywords": ["polyfill", "shim", "compatibility", "portable", "mbstring"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Mbstring\\": "" },
        "files": [ "bootstrap.php" ]
    },
    "suggest": {
        "ext-mbstring": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.bootstrap.php';<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Intl\Grapheme as p;
if (!defined('GRAPHEME_EXTR_COUNT')) {
    define('GRAPHEME_EXTR_COUNT', 0);
}
if (!defined('GRAPHEME_EXTR_MAXBYTES')) {
    define('GRAPHEME_EXTR_MAXBYTES', 1);
}
if (!defined('GRAPHEME_EXTR_MAXCHARS')) {
    define('GRAPHEME_EXTR_MAXCHARS', 2);
}
if (!function_exists('grapheme_extract')) {
    /**
     * @return (string | false)
     */
    function grapheme_extract(?string $haystack, ?int $size, ?int $type = GRAPHEME_EXTR_COUNT, ?int $offset = 0, &$next = null)
    {
        $phabelReturn = p\Grapheme::grapheme_extract((string) $haystack, (int) $size, (int) $type, (int) $offset, $next);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('grapheme_stripos')) {
    /**
     * @return (int | false)
     */
    function grapheme_stripos(?string $haystack, ?string $needle, ?int $offset = 0)
    {
        $phabelReturn = p\Grapheme::grapheme_stripos((string) $haystack, (string) $needle, (int) $offset);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('grapheme_stristr')) {
    /**
     * @return (string | false)
     */
    function grapheme_stristr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false)
    {
        $phabelReturn = p\Grapheme::grapheme_stristr((string) $haystack, (string) $needle, (bool) $beforeNeedle);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('grapheme_strlen')) {
    /**
     * @return (int | false | null)
     */
    function grapheme_strlen(?string $string)
    {
        $phabelReturn = p\Grapheme::grapheme_strlen((string) $string);
        if (!($phabelReturn === false || \is_null($phabelReturn))) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('grapheme_strpos')) {
    /**
     * @return (int | false)
     */
    function grapheme_strpos(?string $haystack, ?string $needle, ?int $offset = 0)
    {
        $phabelReturn = p\Grapheme::grapheme_strpos((string) $haystack, (string) $needle, (int) $offset);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('grapheme_strripos')) {
    /**
     * @return (int | false)
     */
    function grapheme_strripos(?string $haystack, ?string $needle, ?int $offset = 0)
    {
        $phabelReturn = p\Grapheme::grapheme_strripos((string) $haystack, (string) $needle, (int) $offset);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('grapheme_strrpos')) {
    /**
     * @return (int | false)
     */
    function grapheme_strrpos(?string $haystack, ?string $needle, ?int $offset = 0)
    {
        $phabelReturn = p\Grapheme::grapheme_strrpos((string) $haystack, (string) $needle, (int) $offset);
        if (!($phabelReturn === false)) {
            if (!\is_int($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (int) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('grapheme_strstr')) {
    /**
     * @return (string | false)
     */
    function grapheme_strstr(?string $haystack, ?string $needle, ?bool $beforeNeedle = false)
    {
        $phabelReturn = p\Grapheme::grapheme_strstr((string) $haystack, (string) $needle, (bool) $beforeNeedle);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}
if (!function_exists('grapheme_substr')) {
    /**
     * @return (string | false)
     */
    function grapheme_substr(?string $string, ?int $offset, ?int $length = null)
    {
        $phabelReturn = p\Grapheme::grapheme_substr((string) $string, (int) $offset, $length);
        if (!($phabelReturn === false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                } else {
                    $phabelReturn = (string) $phabelReturn;
                }
            }
        }
        return $phabelReturn;
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Intl\Grapheme;

\define('SYMFONY_GRAPHEME_CLUSTER_RX', \PCRE_VERSION >= '8.32' ? '\\X' : Grapheme::GRAPHEME_CLUSTER_RX);
/**
 * Partial intl implementation in pure PHP.
 *
 * Implemented:
 * - grapheme_extract  - Extract a sequence of grapheme clusters from a text buffer, which must be encoded in UTF-8
 * - grapheme_stripos  - Find position (in grapheme units) of first occurrence of a case-insensitive string
 * - grapheme_stristr  - Returns part of haystack string from the first occurrence of case-insensitive needle to the end of haystack
 * - grapheme_strlen   - Get string length in grapheme units
 * - grapheme_strpos   - Find position (in grapheme units) of first occurrence of a string
 * - grapheme_strripos - Find position (in grapheme units) of last occurrence of a case-insensitive string
 * - grapheme_strrpos  - Find position (in grapheme units) of last occurrence of a string
 * - grapheme_strstr   - Returns part of haystack string from the first occurrence of needle to the end of haystack
 * - grapheme_substr   - Return part of a string
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @internal
 */
final class Grapheme
{
    // (CRLF|([ZWNJ-ZWJ]|T+|L*(LV?V+|LV|LVT)T*|L+|[^Control])[Extend]*|[Control])
    // This regular expression is a work around for http://bugs.exim.org/1279
    public const GRAPHEME_CLUSTER_RX = '(?:\\r\\n|(?:[ -~\\x{200C}\\x{200D}]|[á†¨-á‡¹]+|[á„€-á…Ÿ]*(?:[ê°€ê°œê°¸ê±”ê±°ê²Œê²¨ê³„ê³ ê³¼ê´˜ê´´êµ�êµ¬ê¶ˆê¶¤ê·€ê·œê·¸ê¸”ê¸°ê¹Œê¹¨êº„êº êº¼ê»˜ê»´ê¼�ê¼¬ê½ˆê½¤ê¾€ê¾œê¾¸ê¿”ê¿°ë€Œë€¨ë�„ë� ë�¼ë‚˜ë‚´ëƒ�ëƒ¬ë„ˆë„¤ë…€ë…œë…¸ë†”ë†°ë‡Œë‡¨ëˆ„ëˆ ëˆ¼ë‰˜ë‰´ëŠ�ëŠ¬ë‹ˆë‹¤ëŒ€ëŒœëŒ¸ë�”ë�°ëŽŒëŽ¨ë�„ë� ë�¼ë�˜ë�´ë‘�ë‘¬ë’ˆë’¤ë“€ë“œë“¸ë””ë”°ë•Œë•¨ë–„ë– ë–¼ë—˜ë—´ë˜�ë˜¬ë™ˆë™¤ëš€ëšœëš¸ë›”ë›°ëœŒëœ¨ë�„ë� ë�¼ëž˜ëž´ëŸ�ëŸ¬ë ˆë ¤ë¡€ë¡œë¡¸ë¢”ë¢°ë£Œë£¨ë¤„ë¤ ë¤¼ë¥˜ë¥´ë¦�ë¦¬ë§ˆë§¤ë¨€ë¨œë¨¸ë©”ë©°ëªŒëª¨ë«„ë« ë«¼ë¬˜ë¬´ë­�ë­¬ë®ˆë®¤ë¯€ë¯œë¯¸ë°”ë°°ë±Œë±¨ë²„ë² ë²¼ë³˜ë³´ë´�ë´¬ëµˆëµ¤ë¶€ë¶œë¶¸ë·”ë·°ë¸Œë¸¨ë¹„ë¹ ë¹¼ëº˜ëº´ë»�ë»¬ë¼ˆë¼¤ë½€ë½œë½¸ë¾”ë¾°ë¿Œë¿¨ì€„ì€ ì€¼ì�˜ì�´ì‚�ì‚¬ìƒˆìƒ¤ì„€ì„œì„¸ì…”ì…°ì†Œì†¨ì‡„ì‡ ì‡¼ìˆ˜ìˆ´ì‰�ì‰¬ìŠˆìŠ¤ì‹€ì‹œì‹¸ìŒ”ìŒ°ì�Œì�¨ìŽ„ìŽ ìŽ¼ì�˜ì�´ì��ì�¬ì‘ˆì‘¤ì’€ì’œì’¸ì“”ì“°ì”Œì”¨ì•„ì• ì•¼ì–˜ì–´ì—�ì—¬ì˜ˆì˜¤ì™€ì™œì™¸ìš”ìš°ì›Œì›¨ìœ„ìœ ìœ¼ì�˜ì�´ìž�ìž¬ìŸˆìŸ¤ì €ì œì ¸ì¡”ì¡°ì¢Œì¢¨ì£„ì£ ì£¼ì¤˜ì¤´ì¥�ì¥¬ì¦ˆì¦¤ì§€ì§œì§¸ì¨”ì¨°ì©Œì©¨ìª„ìª ìª¼ì«˜ì«´ì¬�ì¬¬ì­ˆì­¤ì®€ì®œì®¸ì¯”ì¯°ì°Œì°¨ì±„ì± ì±¼ì²˜ì²´ì³�ì³¬ì´ˆì´¤ìµ€ìµœìµ¸ì¶”ì¶°ì·Œì·¨ì¸„ì¸ ì¸¼ì¹˜ì¹´ìº�ìº¬ì»ˆì»¤ì¼€ì¼œì¼¸ì½”ì½°ì¾Œì¾¨ì¿„ì¿ ì¿¼í€˜í€´í��í�¬í‚ˆí‚¤íƒ€íƒœíƒ¸í„”í„°í…Œí…¨í†„í† í†¼í‡˜í‡´íˆ�íˆ¬í‰ˆí‰¤íŠ€íŠœíŠ¸í‹”í‹°íŒŒíŒ¨í�„í� í�¼íŽ˜íŽ´í��í�¬í�ˆí�¤í‘€í‘œí‘¸í’”í’°í“Œí“¨í”„í” í”¼í•˜í•´í–�í–¬í—ˆí—¤í˜€í˜œí˜¸í™”í™°íšŒíš¨í›„í› í›¼íœ˜íœ´í��í�¬ížˆ]?[á… -á†¢]+|[ê°€-íž£])[á†¨-á‡¹]*|[á„€-á…Ÿ]+|[^\\p{Cc}\\p{Cf}\\p{Zl}\\p{Zp}])[\\p{Mn}\\p{Me}\\x{09BE}\\x{09D7}\\x{0B3E}\\x{0B57}\\x{0BBE}\\x{0BD7}\\x{0CC2}\\x{0CD5}\\x{0CD6}\\x{0D3E}\\x{0D57}\\x{0DCF}\\x{0DDF}\\x{200C}\\x{200D}\\x{1D165}\\x{1D16E}-\\x{1D172}]*|[\\p{Cc}\\p{Cf}\\p{Zl}\\p{Zp}])';
    private const CASE_FOLD = [['Âµ', 'Å¿', "Í…", 'Ï‚', "Ï�", "Ï‘", "Ï•", "Ï–", "Ï°", "Ï±", "Ïµ", "áº›", "á¾¾"], ['Î¼', 's', 'Î¹', 'Ïƒ', 'Î²', 'Î¸', 'Ï†', 'Ï€', 'Îº', 'Ï�', 'Îµ', "á¹¡", 'Î¹']];
    /**
     *
     */
    public static function grapheme_extract($s, $size, $type = \GRAPHEME_EXTR_COUNT, $start = 0, &$next = 0)
    {
        if (0 > $start) {
            $start = \strlen($s) + $start;
        }
        if (!is_scalar($s)) {
            $hasError = false;
            set_error_handler(function () use(&$hasError) {
                $hasError = true;
            });
            $next = \Phabel\Target\Php80\Polyfill::substr($s, $start);
            restore_error_handler();
            if ($hasError) {
                \Phabel\Target\Php80\Polyfill::substr($s, $start);
                $s = '';
            } else {
                $s = $next;
            }
        } else {
            $s = \Phabel\Target\Php80\Polyfill::substr($s, $start);
        }
        $size = (int) $size;
        $type = (int) $type;
        $start = (int) $start;
        if (\GRAPHEME_EXTR_COUNT !== $type && \GRAPHEME_EXTR_MAXBYTES !== $type && \GRAPHEME_EXTR_MAXCHARS !== $type) {
            if (80000 > \PHP_VERSION_ID) {
                return false;
            }
            throw new \ValueError('grapheme_extract(): Argument #3 ($type) must be one of GRAPHEME_EXTR_COUNT, GRAPHEME_EXTR_MAXBYTES, or GRAPHEME_EXTR_MAXCHARS');
        }
        if (!isset($s[0]) || 0 > $size || 0 > $start) {
            return false;
        }
        if (0 === $size) {
            return '';
        }
        $next = $start;
        $s = preg_split('/(' . SYMFONY_GRAPHEME_CLUSTER_RX . ')/u', "\r\n" . $s, $size + 1, \PREG_SPLIT_NO_EMPTY | \PREG_SPLIT_DELIM_CAPTURE);
        if (!isset($s[1])) {
            return false;
        }
        $i = 1;
        $ret = '';
        do {
            if (\GRAPHEME_EXTR_COUNT === $type) {
                --$size;
            } elseif (\GRAPHEME_EXTR_MAXBYTES === $type) {
                $size -= \strlen($s[$i]);
            } else {
                $size -= \Phabel\Target\Php80\Polyfill::iconv_strlen($s[$i], 'UTF-8//IGNORE');
            }
            if ($size >= 0) {
                $ret .= $s[$i];
            }
        } while (isset($s[++$i]) && $size > 0);
        $next += \strlen($ret);
        return $ret;
    }
    /**
     *
     */
    public static function grapheme_strlen($s)
    {
        preg_replace('/' . SYMFONY_GRAPHEME_CLUSTER_RX . '/u', '', $s, -1, $len);
        return 0 === $len && '' !== $s ? null : $len;
    }
    /**
     *
     */
    public static function grapheme_substr($s, $start, $len = null)
    {
        if (null === $len) {
            $len = 2147483647;
        }
        preg_match_all('/' . SYMFONY_GRAPHEME_CLUSTER_RX . '/u', $s, $s);
        $slen = \count($s[0]);
        $start = (int) $start;
        if (0 > $start) {
            $start += $slen;
        }
        if (0 > $start) {
            if (\PHP_VERSION_ID < 80000) {
                return false;
            }
            $start = 0;
        }
        if ($start >= $slen) {
            return \PHP_VERSION_ID >= 80000 ? '' : false;
        }
        $rem = $slen - $start;
        if (0 > $len) {
            $len += $rem;
        }
        if (0 === $len) {
            return '';
        }
        if (0 > $len) {
            return \PHP_VERSION_ID >= 80000 ? '' : false;
        }
        if ($len > $rem) {
            $len = $rem;
        }
        return implode('', \array_slice($s[0], $start, $len));
    }
    /**
     *
     */
    public static function grapheme_strpos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 0);
    }
    /**
     *
     */
    public static function grapheme_stripos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 1);
    }
    /**
     *
     */
    public static function grapheme_strrpos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 2);
    }
    /**
     *
     */
    public static function grapheme_strripos($s, $needle, $offset = 0)
    {
        return self::grapheme_position($s, $needle, $offset, 3);
    }
    /**
     *
     */
    public static function grapheme_stristr($s, $needle, $beforeNeedle = false)
    {
        return mb_stristr($s, $needle, $beforeNeedle, 'UTF-8');
    }
    /**
     *
     */
    public static function grapheme_strstr($s, $needle, $beforeNeedle = false)
    {
        return mb_strstr($s, $needle, $beforeNeedle, 'UTF-8');
    }
    /**
     *
     */
    private static function grapheme_position($s, $needle, $offset, $mode)
    {
        $needle = (string) $needle;
        if (80000 > \PHP_VERSION_ID && !preg_match('/./us', $needle)) {
            return false;
        }
        $s = (string) $s;
        if (!preg_match('/./us', $s)) {
            return false;
        }
        if ($offset > 0) {
            $s = self::grapheme_substr($s, $offset);
        } elseif ($offset < 0) {
            if (2 > $mode) {
                $offset += self::grapheme_strlen($s);
                $s = self::grapheme_substr($s, $offset);
                if (0 > $offset) {
                    $offset = 0;
                }
            } elseif (0 > ($offset += self::grapheme_strlen($needle))) {
                $s = self::grapheme_substr($s, 0, $offset);
                $offset = 0;
            } else {
                $offset = 0;
            }
        }
        // As UTF-8 is self-synchronizing, and we have ensured the strings are valid UTF-8,
        // we can use normal binary string functions here. For case-insensitive searches,
        // case fold the strings first.
        $caseInsensitive = $mode & 1;
        $reverse = $mode & 2;
        if ($caseInsensitive) {
            // Use the same case folding mode as mbstring does for mb_stripos().
            // Stick to SIMPLE case folding to avoid changing the length of the string, which
            // might result in offsets being shifted.
            $mode = \defined('MB_CASE_FOLD_SIMPLE') ? \MB_CASE_FOLD_SIMPLE : \MB_CASE_LOWER;
            $s = mb_convert_case($s, $mode, 'UTF-8');
            $needle = mb_convert_case($needle, $mode, 'UTF-8');
            if (!\defined('MB_CASE_FOLD_SIMPLE')) {
                $s = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $s);
                $needle = str_replace(self::CASE_FOLD[0], self::CASE_FOLD[1], $needle);
            }
        }
        if ($reverse) {
            $needlePos = strrpos($s, $needle);
        } else {
            $needlePos = strpos($s, $needle);
        }
        return false !== $needlePos ? self::grapheme_strlen(\Phabel\Target\Php80\Polyfill::substr($s, 0, $needlePos)) + $offset : false;
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Intl\Grapheme as p;
if (extension_loaded('intl')) {
    return;
}
if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__ . '/bootstrap80.php';
}
if (!defined('GRAPHEME_EXTR_COUNT')) {
    define('GRAPHEME_EXTR_COUNT', 0);
}
if (!defined('GRAPHEME_EXTR_MAXBYTES')) {
    define('GRAPHEME_EXTR_MAXBYTES', 1);
}
if (!defined('GRAPHEME_EXTR_MAXCHARS')) {
    define('GRAPHEME_EXTR_MAXCHARS', 2);
}
if (!function_exists('grapheme_extract')) {
    /**
     *
     */
    function grapheme_extract($haystack, $size, $type = 0, $start = 0, &$next = 0)
    {
        return p\Grapheme::grapheme_extract($haystack, $size, $type, $start, $next);
    }
}
if (!function_exists('grapheme_stripos')) {
    /**
     *
     */
    function grapheme_stripos($haystack, $needle, $offset = 0)
    {
        return p\Grapheme::grapheme_stripos($haystack, $needle, $offset);
    }
}
if (!function_exists('grapheme_stristr')) {
    /**
     *
     */
    function grapheme_stristr($haystack, $needle, $beforeNeedle = false)
    {
        return p\Grapheme::grapheme_stristr($haystack, $needle, $beforeNeedle);
    }
}
if (!function_exists('grapheme_strlen')) {
    /**
     *
     */
    function grapheme_strlen($input)
    {
        return p\Grapheme::grapheme_strlen($input);
    }
}
if (!function_exists('grapheme_strpos')) {
    /**
     *
     */
    function grapheme_strpos($haystack, $needle, $offset = 0)
    {
        return p\Grapheme::grapheme_strpos($haystack, $needle, $offset);
    }
}
if (!function_exists('grapheme_strripos')) {
    /**
     *
     */
    function grapheme_strripos($haystack, $needle, $offset = 0)
    {
        return p\Grapheme::grapheme_strripos($haystack, $needle, $offset);
    }
}
if (!function_exists('grapheme_strrpos')) {
    /**
     *
     */
    function grapheme_strrpos($haystack, $needle, $offset = 0)
    {
        return p\Grapheme::grapheme_strrpos($haystack, $needle, $offset);
    }
}
if (!function_exists('grapheme_strstr')) {
    /**
     *
     */
    function grapheme_strstr($haystack, $needle, $beforeNeedle = false)
    {
        return p\Grapheme::grapheme_strstr($haystack, $needle, $beforeNeedle);
    }
}
if (!function_exists('grapheme_substr')) {
    /**
     *
     */
    function grapheme_substr($string, $offset, $length = null)
    {
        return p\Grapheme::grapheme_substr($string, $offset, $length);
    }
}{
    "name": "symfony/polyfill-intl-grapheme",
    "type": "library",
    "description": "Symfony polyfill for intl's grapheme_* functions",
    "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "grapheme"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Nicolas Grekas",
            "email": "p@tchwork.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Intl\\Grapheme\\": "" },
        "files": [ "bootstrap.php" ]
    },
    "suggest": {
        "ext-intl": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.bootstrap.php';<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Ctype as p;
if (!function_exists('ctype_alnum')) {
    /**
     * @param mixed $text
     */
    function ctype_alnum($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_alnum($text);
    }
}
if (!function_exists('ctype_alpha')) {
    /**
     * @param mixed $text
     */
    function ctype_alpha($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_alpha($text);
    }
}
if (!function_exists('ctype_cntrl')) {
    /**
     * @param mixed $text
     */
    function ctype_cntrl($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_cntrl($text);
    }
}
if (!function_exists('ctype_digit')) {
    /**
     * @param mixed $text
     */
    function ctype_digit($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_digit($text);
    }
}
if (!function_exists('ctype_graph')) {
    /**
     * @param mixed $text
     */
    function ctype_graph($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_graph($text);
    }
}
if (!function_exists('ctype_lower')) {
    /**
     * @param mixed $text
     */
    function ctype_lower($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_lower($text);
    }
}
if (!function_exists('ctype_print')) {
    /**
     * @param mixed $text
     */
    function ctype_print($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_print($text);
    }
}
if (!function_exists('ctype_punct')) {
    /**
     * @param mixed $text
     */
    function ctype_punct($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_punct($text);
    }
}
if (!function_exists('ctype_space')) {
    /**
     * @param mixed $text
     */
    function ctype_space($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_space($text);
    }
}
if (!function_exists('ctype_upper')) {
    /**
     * @param mixed $text
     */
    function ctype_upper($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_upper($text);
    }
}
if (!function_exists('ctype_xdigit')) {
    /**
     * @param mixed $text
     */
    function ctype_xdigit($text) : bool
    {
        if (!true) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($text) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($text) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return p\Ctype::ctype_xdigit($text);
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
use Symfony\Polyfill\Ctype as p;
if (\PHP_VERSION_ID >= 80000) {
    return require __DIR__ . '/bootstrap80.php';
}
if (!function_exists('ctype_alnum')) {
    /**
     *
     */
    function ctype_alnum($text)
    {
        return p\Ctype::ctype_alnum($text);
    }
}
if (!function_exists('ctype_alpha')) {
    /**
     *
     */
    function ctype_alpha($text)
    {
        return p\Ctype::ctype_alpha($text);
    }
}
if (!function_exists('ctype_cntrl')) {
    /**
     *
     */
    function ctype_cntrl($text)
    {
        return p\Ctype::ctype_cntrl($text);
    }
}
if (!function_exists('ctype_digit')) {
    /**
     *
     */
    function ctype_digit($text)
    {
        return p\Ctype::ctype_digit($text);
    }
}
if (!function_exists('ctype_graph')) {
    /**
     *
     */
    function ctype_graph($text)
    {
        return p\Ctype::ctype_graph($text);
    }
}
if (!function_exists('ctype_lower')) {
    /**
     *
     */
    function ctype_lower($text)
    {
        return p\Ctype::ctype_lower($text);
    }
}
if (!function_exists('ctype_print')) {
    /**
     *
     */
    function ctype_print($text)
    {
        return p\Ctype::ctype_print($text);
    }
}
if (!function_exists('ctype_punct')) {
    /**
     *
     */
    function ctype_punct($text)
    {
        return p\Ctype::ctype_punct($text);
    }
}
if (!function_exists('ctype_space')) {
    /**
     *
     */
    function ctype_space($text)
    {
        return p\Ctype::ctype_space($text);
    }
}
if (!function_exists('ctype_upper')) {
    /**
     *
     */
    function ctype_upper($text)
    {
        return p\Ctype::ctype_upper($text);
    }
}
if (!function_exists('ctype_xdigit')) {
    /**
     *
     */
    function ctype_xdigit($text)
    {
        return p\Ctype::ctype_xdigit($text);
    }
}<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Symfony\Polyfill\Ctype;

/**
 * Ctype implementation through regex.
 *
 * @internal
 *
 * @author Gert de Pagter <BackEndTea@gmail.com>
 */
final class Ctype
{
    /**
     * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise.
     *
     * @see https://php.net/ctype-alnum
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_alnum($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text);
    }
    /**
     * Returns TRUE if every character in text is a letter, FALSE otherwise.
     *
     * @see https://php.net/ctype-alpha
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_alpha($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text);
    }
    /**
     * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise.
     *
     * @see https://php.net/ctype-cntrl
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_cntrl($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^\\x00-\\x1f\\x7f]/', $text);
    }
    /**
     * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise.
     *
     * @see https://php.net/ctype-digit
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_digit($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text);
    }
    /**
     * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise.
     *
     * @see https://php.net/ctype-graph
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_graph($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text);
    }
    /**
     * Returns TRUE if every character in text is a lowercase letter.
     *
     * @see https://php.net/ctype-lower
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_lower($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text);
    }
    /**
     * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all.
     *
     * @see https://php.net/ctype-print
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_print($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text);
    }
    /**
     * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise.
     *
     * @see https://php.net/ctype-punct
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_punct($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^!-\\/\\:-@\\[-`\\{-~]/', $text);
    }
    /**
     * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters.
     *
     * @see https://php.net/ctype-space
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_space($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^\\s]/', $text);
    }
    /**
     * Returns TRUE if every character in text is an uppercase letter.
     *
     * @see https://php.net/ctype-upper
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_upper($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text);
    }
    /**
     * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise.
     *
     * @see https://php.net/ctype-xdigit
     *
     * @param (string | int) $text
     *
     * @return bool
     */
    public static function ctype_xdigit($text)
    {
        $text = self::convert_int_to_char_for_ctype($text);
        return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text);
    }
    /**
    * Converts integers to their char versions according to normal ctype behaviour, if needed.
    *
    * If an integer between -128 and 255 inclusive is provided,
    it is interpreted as the ASCII value of a single character
    (negative values have 256 added in order to allow characters in the Extended ASCII range).
    Any other integer is interpreted as a string containing the decimal digits of the integer.
    *
    * @param (string | int) $int
    *
    * @return mixed
    */
    private static function convert_int_to_char_for_ctype($int)
    {
        if (!\is_int($int)) {
            return $int;
        }
        if ($int < -128 || $int > 255) {
            return (string) $int;
        }
        if ($int < 0) {
            $int += 256;
        }
        return \chr($int);
    }
}{
    "name": "symfony/polyfill-ctype",
    "type": "library",
    "description": "Symfony polyfill for ctype functions",
    "keywords": ["polyfill", "compatibility", "portable", "ctype"],
    "homepage": "https://symfony.com",
    "license": "MIT",
    "authors": [
        {
            "name": "Gert de Pagter",
            "email": "BackEndTea@gmail.com"
        },
        {
            "name": "Symfony Community",
            "homepage": "https://symfony.com/contributors"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "autoload": {
        "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" },
        "files": [ "bootstrap.php" ]
    },
    "suggest": {
        "ext-ctype": "For best performance"
    },
    "minimum-stability": "dev",
    "extra": {
        "branch-alias": {
            "dev-main": "1.23-dev"
        },
        "thanks": {
            "name": "symfony/polyfill",
            "url": "https://github.com/symfony/polyfill"
        }
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.bootstrap.php';MZ�       ÿÿ  ¸       @                                     º ´	Í!¸LÍ!This program cannot be run in DOS mode.
$       äíP¦ Œ>õ Œ>õ Œ>õ©ô­õ¬Œ>õ›Ò?ô¢Œ>õ›Ò=ô£Œ>õ›Ò;ô±Œ>õ›Ò:ô¬Œ>õ}sõõ¥Œ>õ Œ?õþŒ>õ
Ò6ô£Œ>õ
ÒÁõ¡Œ>õ Œ©õ¡Œ>õ
Ò<ô¡Œ>õRich Œ>õ                        PE  d† U%s\        ð "   0        „2        @                        �         `�                                           ð_  È       ¨Ü   €  H           € L   X  p                           €X  ”            @  ø                          .text   .      0                    `.rdata  H*   @   ,   4              @  @.data   €   p      `              @  À.pdata  H   €      b              @  @.gfids      �      f              @  @.rsrc   ¨Ü       Þ   h              @  @.reloc  L    €     F             @  B                                                                                                                                                                                                                        @SH�ì€   H‹ð_  H3ÄH‰D$xH‹ÙÇD$@   H‹IL�D$@º~f€ÿ11  …Àt‹H�¬4  D‹Àè”  3Àéó   H‰´$˜   3ö95-f  H‰¼$    t9·f  �~¸   f‰D$XH‹ f   ‰t$\D$`ÿî0  f‰D$ZH�T$Xë3¸   ¿   f‰D$HH‹Ìe  ‹‰L$L··e  ÿ¹0  f‰D$JH�T$HH‹KE3ÉH‰t$0D‹ÇH‰t$(H‰t$ ÿP0  H‹¼$    H‹´$˜   ƒøÿt‹H�Z4  èÅ  3Àë'ÿ;0  =3'  tD‹H�š4  ‹Èèc  3Àë¸   H‹L$xH3Ìè­  H�Ä€   [ÃÌÌÌÌ@SUVWAVAWHƒìXH‹Œ^  H3ÄH‰D$HL‹¼$°   3ÛA‹ñH‰\$0I‹èH‰\$(D‹ò‰\$ L�L$@D‹ÆH‹Õ‹ûÿÀ/  ƒøÿu!ÿ¥/  E‹ÎH�K4  ‹ÈM‹ÇèÑ  3Àév  D‹Óƒþ‚ã   ‹þWíƒçøfoåA»   @ „     E‹ÊE�CMÀA‹ÓHÒA�KÿHÉMÉAƒÂfBnLÅ E�CfnDÕ MÀfnTÍ A�SfBn\Í A�KfbØE�KfBnDÅ MÉfbÑHÒfbÚHÉfþÝAƒÃfBnLÍ foëfnTÕ fn\Í fbØfbÑfbÚfþÜfoãD;×‚]ÿÿÿfþåfoÄfsØfþàfoÄfsØfþàf~ç‹ÓD;ÖsW‹ÆA+Âƒør9A‹Â‹ÎA+ÊHÁàƒéHÅÑéÿÁD‹ÁE�J@ f„     PH�@ IƒèuñD;Ös
A‹ÂHÀ|Å �øD‹L$@D;ÏtE‹Æ‰|$ I‹×H�3  è�  3Àë¸   H‹L$HH3Ìè§  HƒÄXA_A^_^][ÃÌÌÌÌÌÌÌÌÌÌ@SH�ì�   H‹€\  H3ÄH‰„$ˆ   H‹ÙÇD$P    H‹IL�D$Pº~f€ÿ¾-  …Àt‹H�	3  D‹Àè!  3Àé«   ‹Èb  H�D$xH‰D$8‹¯Á‰L$@ÇD$0   ÆD$xHcÈH²b  H‰L$Hÿ_,  D$0‹L�D$X‹ÈˆD$|ÁéA¹   ˆL$y‹ÈÁéˆL$z‹È¶ÁéD$XˆD$}H�÷2  D$@ˆL${H‹KH‰D$ D$hèýÿÿ…À„ZÿÿÿÇC   ¸   H‹Œ$ˆ   H3Ìè  H�Ä�   [ÃÌÌÌÌÌÌH‰\$ AVH�ì€   H‹[[  H3ÄH‰D$p‹áa  H‹ÙƒÀE3ö‹ÈD‰t$d‰D$@ÿ-  H‹KL�L$hH‰D$HE�FH�D$dL‰t$0L‰t$(H�T$@H‰D$ ÿ¢,  ƒøÿu)ÿW,  D‹H�=2  ‹Èè†  H‹L$HÿÃ,  3Àé‚  D‹D$hAƒøs%D‹L$@H�m2  ‹è–  H‹L$Hÿ“,  3ÀéR  H‰¼$    H‹|$H¶<t$‹H�×2  D¾Àè^  H‹L$Hÿ[,  3Àé  ¶O„Ét@€ù}¶ÁL�õ?  M‹ÁëL�X3  ‹D¾ÁH�k3  è  H‹L$Hÿ,  3ÀéÊ   D‹L$@H�D$`H‰´$˜   A‹öH‰D$XfÇD$`ÇD$P   E;Át‹H��1  èÈ  H‹|$HëLHcn`  ‹L‹Á¯ÁH�OHcÐH|`  èq'  …Àt‹H�r3  è�  H‹|$Hë@ˆt$a¾   ÇC   H‹Ïÿt+  ‹H�³3  H‹KL�D$PA¹   H‰D$ èÊúÿÿ…ÀADö‹ÆH‹´$˜   H‹¼$    H‹L$pH3ÌèE  H‹œ$¨   H�Ä€   A^ÃÌÌÌ3ÀH‹Áƒz|HÿÀHƒø|í3ÀÃ¸   ÃÌÌH‰\$ UAVAWH�¬$€úÿÿH�ì€  H‹ðX  H3ÄH‰…p  E3ÿL‹ñA‹ßI‹ÞèÔøÿÿ…À„Ì  HÿÃHƒû|æH‰´$¨  I‹ÎH‰¼$°  è{ÿÿÿ…À„é   E‹ÇD‰|$@E‹ÏD‰½P  E‹×D‰½`  I‹Þ¿   @ „     L‹A‹C…À…‘   A‹ÏE…ÉtI‹SD  H9”ÍX  tÿÁA;ÉrïA;Éu#Aƒù@sI‹CH‰„ÍX  D‹�P  AÿÁD‰�P  A‹ÏE…ÒtI‹SH9”Íh  tÿÁA;ÊrïA;ÊuiAƒú@scI‹CH‰„Íh  D‹•`  AÿÂD‰•`  ëDƒøu?A‹ÇE…ÀtI‹S‹ÈH9TÌHtÿÀA;ÀrðA;ÀuAƒø@s‹ÈI‹CH‰DÌHD‹D$@AÿÀD‰D$@HƒÃHƒï…ÿÿÿL��`  L‰|$ L�…P  3ÉH�T$@ÿ¶(  ‹Øƒøÿ„=  …À„'  A‹÷I‹ÿ~y Hƒÿ}pI‹þH�T$@H‹Iÿ§(  I‹þ…Àtèªûÿÿ…À„¢   ÿËë;H‹IH�•P  ÿ}(  I‹þ…Àtè`úÿÿ…Àt|ÿËëH‹IH�•`  ÿW(  …ÀuÿÆHÿÇ…ÛŠI‹Îè’ýÿÿ…À…þÿÿ3ÀëIHcÆL�L$4ºÿÿ  ÇD$0   A¸  I‹ÆH�D$0H‰D$ H‹Kÿ+(  ƒøÿuE‹H�Å0  èP  ƒÈÿH‹´$¨  H‹¼$°  H‹�p  H3ÌèN  H‹œ$¸  H�Ä€  A_A^]ÃD‹H�×0  ‹L$4èÆ  ë´H�}1  èø  ë¦ÿp'  ‹ÈH�'1  è¢  ë�ƒÈÿëžÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$H‰|$AVHƒì 3ÛÇAH   H‰YPH‹ñÇAX   H‹ù�HcËL�FHHÁáE3ÉHÎH�QÿÍ%  …Àtj…ÛuH‹OëH‹E3ÀA�Pÿ�%  …ÀtCÿÃHƒÇƒû|¸ÇF`h   ¸   H‹H‰Ž°   H‹NH‰Ž¸   H‹N(�Žœ      H‰ŽÀ   ëH�i1  ëH�ð0  ‹Óè	  3ÀH‹\$0H‹t$8H‹|$@HƒÄ A^ÃÌH‰\$H‰l$H‰t$ WHƒìPH‹õT  H3ÄH‰D$HH‹ÙƒÏÿ¹   ÿ¼&  H‹KL�L$@3öH‰D$8H‹ÐÇD$0   A¸   H‰t$ ÿ°$  …ÀtZH�-í1  D  ‹D$@…Àtj‹L�D$0H‹KA¹   ‰D$0H‰l$ èÙõÿÿ…ÀtIH‹T$8L�L$@H‹KA¸   H‰t$ ÿV$  …Àu²ÿ”$  ƒømtÿ‰$  D‹H�'1  ‹ÈèÐ  ë‹þH‹Kÿr$  H‹Kÿ�%  ‹ÇH‹L$HH3Ìè	  H‹\$hH‹l$pH‹t$xHƒÄP_ÃÌÌÌÌH‰\$H‰t$WHƒìpH‹ÚS  H3ÄH‰D$`H‹Ù3ö¹   ‰t$TƒÏÿÿ›%  H‹KL�L$PH‰D$HD�FH�D$TH‰t$0H‰t$(H�T$@H‰D$ ÇD$@   ÿ"%  ;ÇtqD‹D$PE…À„Ä   H‹T$HL�L$XH‹KH‰t$ ÿo#  …À„”   D‹D$XD‹L$PE;ÁuuH‹KH�D$TH‰t$0L�L$PH‰t$(H�T$@A¸   H‰D$ ÿ²$  ƒøÿu�ÿO#  H�X0  D‹‹Èè–  H‹Kÿ<#  ‹ÇH‹L$`H3ÌèÝ  L�\$pI‹[I‹s I‹ã_Ã‹H�Â0  è�  ëÅÿý"  H�N0  ë¬‹þë²ÌÌÌÌÌÌÌÌH‰\$H‰l$H‰t$W¸P  èæ  H+àH‹|R  H3ÄH‰„$@  ‹ÿX  ¹öÿÿÿ�@Û�4@ÿh"  3íL�L$0H‹ÈH‰l$ D‹ÃH�T$@H‹øÿ8"  …Àuÿv"  ‹ÈH�µ0  èÀ  3Àéè  ‹T$0;ÓtD‹ÃH�ç0  èâ  3ÀéÊ  ‹Î‰5“X  ‹ÞÿË#  D‹ÆH�T$@H‹ÈH‰�X  èŒ  ‹Î‰5|X  ÿ¦#  H�T$@D‹ÆHÓH‰lX  H‹Èèd  L�L$0H‰l$ A¸   H�T$@H‹ÏÿŽ!  …ÀuÿÌ!  ‹ÈH�ë0  è  3Àé>  ‹T$0ƒútH�?1  è:  3Àé"  ¶D$@„Àt¾ÐH�Ð1  è  3Àé  L�L$0H‰l$ A¸   H�T$@H‹Ïÿ!  …ÀuÿT!  ‹ÈH�#2  èž  3ÀéÆ   ‹D$0=   uH�U2  èÀ  3Àé¨   ÿÈ@8l@tH�©2  è¤  3ÀéŒ   HƒÏÿ‰l$(D‹ÏH‰l$ L�D$@3Ò¹éý  ÿÓ   HcØ…ÀuH�í2  èh  3ÀëS¸   H÷ãH@ÇH‹ÈÿO"  D‹Ï‰\$(L�D$@H‰W  3ÒH‰D$ ¹éý  ÿ‚   …ÀuH�3  è  3Àë¸   H‹Œ$@  H3Ìè!  L�œ$P  I‹[I‹kI‹s I‹ã_ÃÌÌÌÌÌÌÌÌHƒìXH‹õO  H3ÄH‰D$H3ÀˆT$@‹H‹I‰D$AH�D$@H‰D$8A‹ÀÁèˆD$AA‹ÀÁèˆD$BA‹ÀÁèDˆD$DL�D$0L‰L$ A¹   ˆD$CÇD$0   èóðÿÿH‹L$HH3Ìè†  HƒÄXÃÌH‰\$H‰l$H‰t$ WAVAWHƒìPH‹aO  H3ÄH‰D$@3ÿH�t$(D‹÷‹ï‹ßL‹ù„     I‹ßH�T$ ÿq  …À„    ‹D$ =  uI‹ßAÿÆH‰HƒÆë…À…”   ÿÅHÿÃHƒû|»E…öt[AƒÉÿH�T$(A¸   A‹Îÿþ  ƒøÿuÿ  ‹ÈH�Š2  èe  H‹ßf�I‹ßH�T$ ÿñ  …Àtƒ|$  u4ÿÇHÿÃHƒû|Û¸   ë$ÿÖ  D‹Çë	ÿË  D‹ÅH�Ù1  ‹Èè  3ÀH‹L$@H3Ìèc  L�\$PI‹[(I‹k0I‹s8I‹ãA_A^_ÃÌÌÌÌÌÌÌÌÌ@USWH�¬$PÿÿÿH�ì°  H‹&N  H3ÄH‰…¨   Hƒ=ÜT   H‹ú‹Ùu"º   ‹ÊÿØ  H‰ÁT  H…Àt	H‹Èÿƒ  ¹  H�¿T  ÿ)  …Àt‹ÐH�Ü1  è§
  L‹Ç‹Óè­  …Àuè  ƒÈÿéa  èûÿÿ…Àtêƒ=,T   ¸   H‰´$Ð  H�uxL‰´$à  A¾   DEðL‰¼$è  E3ÿA‹ÿ¹   ÿ@  º   A‹ÎH‹Ø‰8D�BD‰xÿÝ  H‰CHƒøÿ„¾  H‰ÿÇHƒÆƒÿ|¾L‰|$(L�MxL�	ôÿÿD‰|$ 3Ò3Éÿb  3ÒH�M A¸È   H‹Øè,  H�M èýöÿÿ…À„z  ƒÊÿH‹Ëÿ	  ƒøÿuÿ  ‹ÈH�1  è`
  éP  H�UpH‹Ëÿî  …Àuÿì  ‹ÈH�+1  è6
  é&  D9}p…  H‹@S  H�EÐH‰D$HL�MèH�E 3ÉH‰D$@L�EèH‹õR  H‰D$8L‰|$0ÇD$(   ÇD$    ÿ¥  …Àuÿ{  ‹ÈH�Ò(  èÅ	  éµ  H‹MØÿf  H‹M ÿ\  H‹M¸ÿR  H‹MÈÿH  D‹EàL�Õ0  H‹Mxº   èßûÿÿ…À„l  H‹ExL�L$PD‰|$PL�Ò÷ÿÿL‰|$(3ÒD‰|$ H‹HH‹E¨H‰L$`3ÉH‰D$Xÿô  ÇD$h   L�L$hH‰…�   L�qöÿÿH‹…€   3ÒL‰|$(D‰|$ H‹HH‹E°H‰L$x3ÉH‰D$pÿ¬  ÇE€   L�M€H‰…˜   L�+öÿÿH‹…ˆ   3ÒL‰|$(D‰|$ H‹HH‹EÀH‰M�3ÉH‰Eˆÿh  H‹MÐƒÊÿH‰…    ÿ,  ƒøÿuÿ9  ‹ÈH�Ø/  èƒ  ëvH‹MÐH�UpÿC  …Àuÿ  ‹ÈH� 0  è[  ëND‹EpL�60  H‹Mxº   è úÿÿ…Àt1H���   èûÿÿ…Àt!H‹MxH‹Iÿö  ‹Epë‹H�X%  èK  èÆ  ƒÈÿL‹´$à  H‹´$Ð  L‹¼$è  H‹�¨   H3Ìè<
  H�Ä°  _[]ÃÌH‰\$H‰t$ WHƒì0H‹J  H3ÄH‰D$(3öH‹úH‰t$ H‹Ùÿ§  D�F
H‹ËH�T$ ‰0ÿ£  ‹ðH9\$ tÿ„  ƒ8 u	‰7¸   ë3ÀH‹L$(H3Ìè¿	  H‹\$PH‹t$XHƒÄ0_ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$WHƒì H‹ÙI‹ð¹   ÿ`  H‹Ö¹   L‹ÀH‹øÿü  …Àt.ƒøt	H�t/  ëtH‰{¸   ÇC    H‹\$0H‹t$8HƒÄ _ÃH‹Ïÿ  ¹   ÿ  H‹Ö¹   L‹ÀH‹øÿ¢  …Àt!ƒøu¦‰C¸   H‰{H‹\$0H‹t$8HƒÄ _ÃH�>/  èÁ  H‹ÏÿÀ  H‹\$03ÀH‹t$8HƒÄ _ÃÌÌÌÌÌÌ@SHƒì H‹ÙH‹ÑI‹Èè|þÿÿ…Àt‹ÿÈ=þÿ  w¸   HƒÄ [Ã‹H�/  èd  3ÀHƒÄ [ÃÌÌÌÌÌÌÌÌÌÌÌÌ@SHƒì H�YI‹ÈH‹Óè+þÿÿ…Àtƒ; ‹H�/  è$  ¸   HƒÄ [ÃÌÌÌÌÌÌÌÌÌL‰A¸   ÃÌÌÌÌÌÌH‰\$WHƒì ·I‹ØH‹úfƒø-uf9Bufƒz u¸   H‹\$@HƒÄ _ÃH‰t$0L‰t$8E…ÉtrI‹L�5H  E3ÒH�5gH  E‹ÚM‹Î�M‹H‹ÃL+Ã€    ·B· +ÑuHƒÀ…Éuì…ÒtAÿÃIƒÁL;Î|ÌëIcÃH�@M�ÎL‹ÇH�õM  H‹ÓAÿRéB  fƒø-…3  f9B…)  H�JH�2.  I‰ÿi  L‹L�5wG  E3ÒH�5ÍG  H‹øM‹ÎH…Àuof�M‹I‹ÃM+Ã€    ·B· +ÑuHƒÀ…Éuì…ÒtAÿÂIƒÁL;Î|Ìé}   IcÂH�@I�ÎH…ÀtmH‹@H…Àu
¸   é�   I‹ÓH�:M  ÿÐéŒ   fD‰M‹I‹ÃM+ÃfD  ·B· +ÑuHƒÀ…Éuì…ÒtAÿÂIƒÁL;Î|ÍëIcÂH�@I�ÎH…ÀuI‹ÓH�P-  è;  3Àë0H‹@I‹ÓH…ÀuH�\-  è  3ÀëL�GH�°L  ÿÐë¸   H‹t$0L‹t$8H‹\$@HƒÄ _ÃÌÌH‰\$H‰l$H‰L$VWAVHƒì 3ÿHcê3ÀH‰|$@»   ‰=bL  H‰cL  M‹ðÇ^L  ÿÿÿÿ‹÷‰=ZL  H‰=WL  H;Ý}Nff„     I‹ÞL�D$@D‹Îèýÿÿ…Àtd~ƒø~ƒøt	ƒøu	‹÷ë¾   HÿÃH;Ý|Éƒ=L  ÿ…±   ¹   ÿA  H�-  ¹   L‹ÀH‹ØÿÙ  …Àt$ƒøtH�Q+  ën3Àé¨   H‰±K  ‰=³K  ëfH‹Ëÿ   ¹   ÿí  H�Æ,  ¹   L‹ÀH‹Øÿ…  …Àt!ƒøt	H�ý*  ëH‰dK  ÇbK     ëH�!+  è¤  H‹Ëÿ£  9=IK  uH�ü+  è‡  ë9=K  uH�,  èq  ë¿   ‹ÇH‹\$HH‹l$PHƒÄ A^_^ÃÌÌÌÌÌH�áL  ÃÌÌÌÌÌÌÌÌH‰T$L‰D$L‰L$ SVWHƒì0H‹úH�t$`H‹ÙèÊÿÿÿE3ÉH‰t$ L‹ÇH‹ÓH‹ÿ  HƒÄ0_^[ÃÌÌÌÌÌÌÌÌÌÌÌH‰l$H‰t$H‰|$ ATAVAWHƒì0I‹èL‹òH‹ñèyÿÿÿH‰l$(M‹ÎE3ÀHÇD$     3ÒL‹øH‹HƒÉÿ“  IƒÌÿ‹ø…ÀAHüA;üuA‹ÄëlHcÏ¸   HÿÁH‰\$PH÷áI@ÄH‹Èÿm  H‹ØH…Àt7I‹�GLcÀM‹ÎH‰l$(H‹ÓHÇD$     ÿB  …ÀAHÄƒøÿuH‹Ëÿ6  A‹ÄëH‰H‹\$PH‹l$XH‹t$`H‹|$hHƒÄ0A_A^A\ÃÌÌÌÌÌÌÌH‰L$H‰T$L‰D$L‰L$ Hƒì8Hƒ=ÈI   u3ÀHƒÄ8Ãº   H‰\$0�Jÿ¼  H‹ØH…Àu
H‹\$0HƒÄ8ÃH‹T$@L�D$HH�L$ è®þÿÿH‹T$ ÿÈHcÈI¹ &     E3ÀH�J ·fƒù w·ÉI£És
fD‰ HƒèëäH‹EI  H‰SH‹Óÿ   H‹\$0¸   HƒÄ8ÃÌL‹ÜI‰SM‰CM‰K SHƒì`H‹EB  H3ÄH‰D$P3À‹ÙI‰CÈD‹Á‰D$(A¹   I‰Cà3ÒI�Cà¹   I‰C¸ÿ‡  H‹T$xH…Òu&L‹D$HH�Ñ)  ‹ÓèÒþÿÿH‹L$PH3Ìèå  HƒÄ`[ÃL�„$€   H�L$@è½ýÿÿL‹L$HH�©)  H‹T$@D‹Ãè”þÿÿH‹L$PH3Ìè§  HƒÄ`[ÃÌH‰l$H‰t$ AVHƒì@½€   ‹Íÿc  H‰\$PE3öH‹ðH‰|$X H‹1H  H…É„#  ÿú  H…À„î   H‹XH‹Èÿ4  H…Û„Ø   L‰t$8AƒÉÿL‰t$0L‹Ã‰l$(3Ò¹éý  H‰t$ ÿœ  …À…‡   ÿN  ƒøzu‘L‰t$8AƒÉÿL‰t$0L‹ÃD‰t$(3Ò¹éý  L‰t$ ÿa  Hcø…À„^ÿÿÿH‹×H‹Îÿ’  H…À„IÿÿÿL‰t$8AƒÉÿL‰t$0L‹Ã‰|$(3Ò¹éý  H‰D$ H‹ð‹ïÿ  …À„ÿÿÿ¹   ÿR  L‹ÆH�p(  H‹ÈèüÿÿéóþÿÿH‹$G  H…ÉtÿÑ  H‹G  ÿ4  L‰5G  H‹ÎH‹|$XH‹\$PH‹l$`H‹t$hHƒÄ@A^Hÿ%  ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌff„     H;ù?  òuHÁÁf÷ÁÿÿòuòÃHÁÉé«  ÌÌÌ@SHƒì ¹   è  è;  ‹Èè8  èc  H‹Øè  ¹   ‰èC  „ÀtlèR	  H�—	  è6  èù  ‹ÈèÔ  …ÀuVèù  è,  …ÀtH�Õ  è°  è‹  è†  èÁ  ‹Èèî  èÙ  „Àtè˜  è§  3ÀHƒÄ [Ã¹   èý  Ì¹   èò  ÌÌHƒì(è¯  3ÀHƒÄ(ÃHƒì(ès  èj  ‹ÈHƒÄ(é™  ÌÌÌH‰\$H‰t$WHƒì0¹   è+  „Àu¹   è�  Ì@2ö@ˆt$ èÓ  ŠØ‹ÇD  ƒùu
¹   èx  …ÉuJÇªD     H�Ë  H�¬  èí
  …Àt
¸ÿ   éì   H�Š  H�s  èÆ
  ÇlD     ë@¶@ˆt$ ŠËèO  è  H‹ØHƒ8 t"H‹Èè�  „ÀtH‹H‹Ëèr  E3ÀA�P3ÉÿÓèÞ  H‹ØHƒ8 tH‹Èèm  „ÀtH‹è�
  èx
  H‹øèj
  H‹Øè>
  L‹ÀH‹‹è—ïÿÿ‹Øèè  „Àu‹Ëè1
  @„öuèE
  3Ò±èÚ  ‹Ãë!‹Øè¿  „Àu‹Ëè
  Ì€|$  uè
  ‹ÃH‹\$@H‹t$HHƒÄ0_ÃÌHƒì(è/  HƒÄ(évþÿÿÌÌ@SHƒì H‹Ù3ÉÿG  H‹ËÿF  ÿ0  H‹Èº	 ÀHƒÄ [Hÿ%  H‰L$Hƒì8¹   èç	  …Àt¹   Í)H�O>  èª   H‹D$8H‰6?  H�D$8HƒÀH‰Æ>  H‹?  H‰�=  H‹D$@H‰”>  Çj=  	 ÀÇd=     Çn=     ¸   HkÀ H�f=  HÇ   ¸   HkÀ H‹Ž<  H‰L ¸   HkÀH‹�<  H‰L H�Í  è ÿÿÿHƒÄ8ÃÌÌÌ@SVWHƒì@H‹ÙÿW  H‹³ø   3ÿE3ÀH�T$`H‹ÎÿÝ  H…Àt9Hƒd$8 H�L$hH‹T$`L‹ÈH‰L$0L‹ÆH�L$pH‰L$(3ÉH‰\$ ÿþ  ÿÇƒÿ|±HƒÄ@_^[ÃÌÌÌHƒì(èÿ  …Àt!eH‹%0   H‹HëH;Èt3ÀðH±ØA  uî2ÀHƒÄ(Ã°ë÷ÌÌÌ@SHƒì ¶óA  …É»   DÃˆãA  èâ  è  „Àu2Àëè  „Àu	3Éèý  ëêŠÃHƒÄ [ÃÌÌÌH‰\$UH‹ìHƒì@‹Ùƒù‡¦   èc  …Àt+…Ûu'H�XA  èá  …Àt2ÀëzH�\A  èÍ  …À”ÀëgH‹;  IƒÈÿ‹Â¹@   ƒà?+È°IÓÈL3ÂL‰EàL‰EèEàL‰EðòMðý@  L‰EàL‰EèEàL‰Eðòõ@  òMðñ@  òù@  H‹\$PHƒÄ@]Ã¹   èl  ÌÌÌÌHƒìL‹Á¸MZ  f9…ÊÿÿuyHc¸ÊÿÿH�uÊÿÿH��9PE  u_¸  f9AuTL+Â·AH�QHÐ·AH�€L�ÊH‰$I;Ñt‹JL;Ár
‹BÁL;ÀrHƒÂ(ëß3ÒH…Òu2Àëƒz$ }2Àë
°ë2Àë2ÀHƒÄÃÌÌÌ@SHƒì ŠÙè  3Ò…Àt„ÛuH‡ö?  HƒÄ [Ã@SHƒì €=@   ŠÙt„ÒuŠËèH  ŠËèA  °HƒÄ [ÃÌ@SHƒì H‹Ÿ9  H‹Ù‹ÊH3³?  ƒá?HÓÊHƒúÿu
H‹Ëè9  ëH‹ÓH�“?  è"  3É…ÀHDËH‹ÁHƒÄ [ÃÌHƒì(è§ÿÿÿH÷ØÀ÷ØÿÈHƒÄ(ÃÌH‰\$ UH‹ìHƒì Hƒe H»2¢ß-™+  H‹!9  H;ÃuoH�MÿÒ	  H‹EH‰EÿÌ	  ‹ÀH1EÿX	  ‹ÀH�M H1Eÿ¸	  ‹E H�MHÁà H3E H3EH3ÁH¹ÿÿÿÿÿÿ  H#ÁH¹3¢ß-™+  H;ÃHDÁH‰­8  H‹\$HH÷ÐH‰¦8  HƒÄ ]Ã3ÀÃÌ¸   ÃÌÌ¸ @  ÃÌÌH�Ý>  Hÿ%	  ÌÌ°ÃÌH�Ù>  ÃHƒì(èïóÿÿHƒèæÿÿÿHƒHƒÄ(ÃÌ3À9X8  ”ÀÃH�?  ÃH�?  ÃH‰\$UH�¬$@ûÿÿH�ìÀ  ‹Ù¹   èÕ  …Àt‹ËÍ)ƒ%x>   H�Mð3ÒA¸Ð  è%  H�Mðÿí  H‹�è   H�•Ø  H‹ËE3Àÿs  H…Àt<Hƒd$8 H��à  H‹•Ø  L‹ÈH‰L$0L‹ÃH��è  H‰L$(H�MðH‰L$ 3ÉÿŠ  H‹…È  H�L$PH‰…è   3ÒH�…È  A¸˜   HƒÀH‰…ˆ   èŽ  H‹…È  H‰D$`ÇD$P  @ÇD$T   ÿî  ƒøH�D$PH‰D$@H�Eð”ÃH‰D$H3Éÿ  H�L$@ÿ  …Àu
öÛÀ!t=  H‹œ$Ð  H�ÄÀ  ]ÃÌÌÌHƒì(3ÉÿŒ  H‹ÈH…Àu2Àë7¸MZ  f9uòHcA<HÁ�8PE  uã¹  f9HuØƒ¸„   vÏƒ¸ø    •ÀHƒÄ(ÃH�	   Hÿ%v  ÌÌHƒì(H‹�8csmàuƒxu‹H ��àúlæƒøv�ù @™t3ÀHƒÄ(Ãè  ÌH‰\$H‰t$WHƒì H�N"  H�5G"  ëH‹;H…ÿt
H‹Ïèi   ÿ×HƒÃH;ÞråH‹\$0H‹t$8HƒÄ _ÃÌÌH‰\$H‰t$WHƒì H�"  H�5"  ëH‹;H…ÿt
H‹Ïè   ÿ×HƒÃH;ÞråH‹\$0H‹t$8HƒÄ _ÃÌÌHÿ%¥  ÌH‰\$H‰|$UH‹ìHƒì ƒeè 3É3ÀÇ¤5     ¢D‹ÁÇ‘5     �ñcAMDD‹ÊD‹ÒA�ñentiA�òineIA�ðntelEÐD‹ÛD‹Ç;  A�óAuthEÙ‹ÓDÙ�òGenu3É‹øDÒ¸   ¢‰EðD‹ÉD‰Mø‹È‰]ô‰UüE…ÒuRHƒ)5  ÿAƒÈ%ð?ÿD‰u;  =À t(=` t!=p t°ùüÿƒø wH»     H£ÃsAƒÈD‰;;  E…Ûu�á ð�ù ` rAƒÈD‰;  ¸   ‰UàD‰Mä;ø|$3É¢‰Eð‰]ô‰Mø‰Uü‰]èºã	sAƒÈD‰é:  AºásnÇt4     Çn4     AºásSAºásL3ÉÐHÁâ HÐH‰UH‹E$<u2‹@4  ƒÈÇ/4     öEè ‰)4  tƒÈ Ç4     ‰4  H‹\$83ÀH‹|$@HƒÄ ]ÃÌÌ3À94  •ÀÃÂ  ÌÌÌÌÌÿ%â  ÿ%ä  ÿ%F  ÿ%8  ÿ%Â  ÿ%  ÿ%Æ  ÿ%Ð  ÿ%*  ÿ%D  ÿ%.  ÿ%   ÿ%J  ÿ%ô  ÿ%Æ  ÿ%¨  ÿ%Ú  ÿ%Ä  ÿ%^  ÿ%   ÿ%  ÿ%t  ÿ%®  ÿ%€  ÿ%‚  ÿ%  Hƒì(M‹A8H‹ÊI‹Ñè   ¸   HƒÄ(ÃÌÌÌ@SE‹H‹ÚAƒãøL‹ÉAö L‹ÑtA‹@McP÷ØLÑHcÈL#ÑIcÃJ‹H‹C‹HHKöAt
¶AƒàðLÈL3ÊI‹É[é»òÿÿÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌff„     HƒìL‰$L‰\$M3ÛL�T$L+ÐMBÓeL‹%   M;ÓòsfA�â ðM�› ðÿÿAÆ M;ÓòuïL‹$L‹\$HƒÄòÃÌÿ%x  ÿ%z  ÌÌÌÌÌÌÌÌff„     ÿà@UHƒì H‹êH‹H‹Ñ‹èTþÿÿ�HƒÄ ]ÃÌ@UH‹êH‹3É�8  À”Á‹Á]ÃÌ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        °c      ¼c      Ôc      äc      ðc      
d      d      .d      Dd      Xd      hd      vd      †d      œd      ®d      Äd      Öd      îd      e       e      6e      i       j      j      òi      Üi      Âi      ¦i      ’i      ~i      `i      Di      0i      i              ¤e      ¼e      še      4j      >j              je      s      €      €o      €
      €xe            €—      €	      €‚e            €`e            €        êe              Êg      >f      Hf      àe      Øe      þe              ´g              ²f              Þf      êg      þf      rg      "h      0h      dg      Æf      †g      h      |g      Vg      ¢f      �f      g      @g      8g      ôe      *g              Úg      Hg      tf      ,f      f      Zf              (< @   Ð= @           ð0 @                   $0 @   à0 @                                            p @   @q @   S u c c e s s   S i g n a l   n o t   e x p e c t e d   a t   t h i s   t i m e         I n v a l i d   s t r e a m   i d e n t i f i e r       I n v a l i d   p r o c e s s   i d e n t i f i e r     D u p l i c a t e   s t r e a m   i d e n t i f i e r   I n v a l i d   c l i e n t   s e c u r i t y   t o k e n       I n v a l i d   s e r v e r   s e c u r i t y   t o k e n       F a i l e d   t o   s e t   s o c k e t   # % d   t o   n o n - b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       C o n n e c t i n g   s o c k e t   # % d   u n e x p e c t e d l y   s u c c e e d e d         C o n n e c t i n g   s o c k e t   # % d   f a i l e d         F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d   F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d :   s e n t   % d   o f   % d   b y t e s         F a i l e d   t o   s e t   s o c k e t   # % d   t o   b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       h a n d s h a k e       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   U n e x p e c t e d   s i g n a l   c o d e   % d   f r o m   s e r v e r ,   e x p e c t i n g   H A N D S H A K E _ A C K   U n k n o w n   e r r o r       H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   S e r v e r   r e j e c t e d   c o n n e c t i o n :   % d :   % s           H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   I n v a l i d   s e r v e r   t o k e n       h a n d s h a k e   a c k       F a i l e d   t o   c o n n e c t   s o c k e t   # % d :   U n k n o w n   e r r o r   F a i l e d   t o   c o n n e c t   s o c k e t   # % d         F a i l e d   t o   c r e a t e   s o c k e t   # % d   s e l e c t ( )   o p e r a t i o n   f a i l e d               s e l e c t ( )   u n e x p e c t e d l y   r e t u r n e d   z e r o   s o c k e t s           F a i l e d   t o   c r e a t e   p i p e   f o r   p r o c e s s   I / O   s t r e a m   # % d                 F a i l e d   t o   s e t   h a n d l e   i n f o r m a t i o n   f o r   p r o c e s s   I / O   s t r e a m   # % d   F a i l e d   t o   c r e a t e   c h i l d   p r o c e s s             F a i l e d   t o   r e a d   f r o m   c h i l d   p r o c e s s   p i p e   # % d     d a t a         F a i l e d   t o   r e a d   f r o m   s o c k e t   # % d             F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d       F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d :   s e n t   % d   o f   % d   b y t e s             F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n                 F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s             F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n               F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   1   b y t e               F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   e x p e c t e d   0 ,   g o t   % d       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n               F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   c o m m a n d   t o o   l o n g           F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   m i s s i n g   n u l l   t e r m i n a t o r             F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   i n v a l i d   U T F - 8   s t r i n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   f a i l e d   t o   d e c o d e   U T F - 8   s t r i n g                 R e t r i e v i n g   c o p y   t h r e a d   # % d   e x i t   c o d e   f a i l e d           W a i t   o p e r a t i o n   o n   c o p y   t h r e a d s   f a i l e d       W S A S t a r t u p   f a i l e d :   % d       W a i t   o p e r a t i o n   o n   c o n n e c t   t h r e a d   f a i l e d   R e t r i e v i n g   c o n n e c t   t h r e a d   e x i t   c o d e   f a i l e d     P I D   W a i t   o p e r a t i o n   o n   c h i l d   p r o c e s s   f a i l e d     R e t r i e v i n g   p r o c e s s   e x i t   c o d e   f a i l e d   e x i t   c o d e       pC @   €C @   ÈC @    D @   8D @   pD @   °D @   a d d r e s s   p o r t         t o k e n - s i z e     c w d   E r r o r   p a r s i n g   s e r v e r   a d d r e s s         I n v a l i d   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   p o r t :   % d   I n v a l i d   t o k e n   s i z e :   % d     =       U n k n o w n   o p t i o n :   % s     O p t i o n   % s   r e q u i r e s   a   v a l u e     P r o c e s s   l a b e l   n o t   s u p p l i e d     S e r v e r   p o r t   n o t   s u p p l i e d         1 2 7 . 0 . 0 . 1       % d :   % s     % s :   % d :   % s     %s
                 U%s\       h   Y  M      U%s\          |Y  |M      U%s\       €  �Y  �M      U%s\                   ”                                                                                        p @                   øB @    C @                      RSDS3Þ¬«öÛmN¢¼H^„‘gØ   C:\Users\Dave\source\repos\windows-process-wrapper\Release\ProcessWrapper64.pdb                   GCTL   À-  .text$mn    À=     .text$mn$00 Ò=  6   .text$x  @  ø  .idata$5    øB     .00cfg  C     .CRT$XCA    C     .CRT$XCAA   C     .CRT$XCZ     C     .CRT$XIA    (C     .CRT$XIAA   0C     .CRT$XIAC   8C     .CRT$XIZ    @C     .CRT$XPA    HC     .CRT$XPZ    PC     .CRT$XTA    XC     .CRT$XTZ    `C  ´  .rdata  Y  ü  .rdata$zzzdbg   \     .rtc$IAA    \     .rtc$IZZ     \     .rtc$TAA    (\     .rtc$TZZ    0\  À  .xdata  ð_  ´   .idata$2    ¤`     .idata$3    ¸`  ø  .idata$4    °c  ˜  .idata$6     p      .data    p  à  .bss     €  H  .pdata   �     .gfids$y        À  .rsrc$01    À¡  èÚ  .rsrc$02                                     	ò0Ì<  x   ! t d    S  0\  !      S  0\   ¢	ðàp`P0  Ì<  H    	 0  Ì<  ˆ    4 òàÌ<  p   ! t �  \  ˜\  ! d \  æ  ¬\  !   \  æ  ¬\  !   �  \  ˜\  * 4× Ð 
ðàP  Ì<  p  ! tÖ dÕ ð  =  ô\  !   ð  =  ô\  !   tÖ  dÕ ð  =  ô\   t d 4 2à# d T 4 ’pÌ<  H    d 4 ÒpÌ<  `   /	 d T 4 
 p  Ì<  @   ¢  Ì<  H   '
 d T 4 ’ðàpÌ<  @   $ 6 p0P  Ì<  ¨  !& &ô= ä< d: À!  i"  è]  !   À!  i"  è]   d 4
 RpÌ<  (    d 4 2p 20@ @ä ;d 
4 
2p T
 4	 2àp` Rp`0
 t d T RðàÀ! 4
 ð+  ^,  �^  !   ð+  ^,  �^   b  ! 4 à,  -  Ì^  !   4 à,  -  Ì^  # ²0Ì<  P   -
 -t "4
 d T rà       	 d	 4 Rp0<     <1  R2  Ò=  R2   2P	 	b   rp`0	 "  0<     o5  ú5  ð=  ú5   P   4
 rP 4	 2P 4º ¸ P   t 4 2P    0   B         ¸`          Re   @   b          Že  HA  Ða          Æe  A  €b          <h  ÈA  pb          \h  ¸A  Øb          ~h   B  xc           h  ÀB  Èb          Àh  B  ¸b          àh   B                      °c      ¼c      Ôc      äc      ðc      
d      d      .d      Dd      Xd      hd      vd      †d      œd      ®d      Äd      Öd      îd      e       e      6e      i       j      j      òi      Üi      Âi      ¦i      ’i      ~i      `i      Di      0i      i              ¤e      ¼e      še      4j      >j              je      s      €      €o      €
      €xe            €—      €	      €‚e            €`e            €        êe              Êg      >f      Hf      àe      Øe      þe              ´g              ²f              Þf      êg      þf      rg      "h      0h      dg      Æf      †g      h      |g      Vg      ¢f      �f      g      @g      8g      ôe      *g              Úg      Hg      tf      ,f      f      Zf              TReadFile  SetHandleInformation  ÇGetStdHandle  ñWriteFile ¹WaitForMultipleObjects  Ô CreatePipe  »WaitForSingleObject ÔMultiByteToWideChar 4GetExitCodeThread VGetLastError   CloseHandle ç CreateThread  GetCurrentProcessId Û CreateProcessW  3GetExitCodeProcess   FormatMessageW  XInterlockedFlushSList ÝWideCharToMultiByte ZInterlockedPushEntrySList TInitializeSListHead YInterlockedPopEntrySList  KERNEL32.dll  H WSARecv   WSAConnect  M WSASend  InetPtonW WS2_32.dll  F wcsstr   __C_specific_handler  > memset  VCRUNTIME140.dll   free   malloc  n wcstol  ! _errno    _aligned_free  __stdio_common_vswprintf_s    __acrt_iob_func  realloc  _aligned_malloc  __stdio_common_vfprintf  __stdio_common_vswprintf  @ _seh_filter_exe B _set_app_type 	 __setusermatherr   _configure_wide_argv  5 _initialize_wide_environment  ) _get_initial_wide_environment 6 _initterm 7 _initterm_e U exit  # _exit T _set_fmode   __p___argc   __p___wargv  _cexit   _c_exit = _register_thread_local_exe_atexit_callback   _configthreadlocale  _set_new_mode  __p__commode  4 _initialize_onexit_table  < _register_onexit_function  _crt_atexit g terminate api-ms-win-crt-heap-l1-1-0.dll  api-ms-win-crt-convert-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll  api-ms-win-crt-locale-l1-1-0.dll  ®RtlCaptureContext µRtlLookupFunctionEntry  ¼RtlVirtualUnwind  ’UnhandledExceptionFilter  RSetUnhandledExceptionFilter GetCurrentProcess pTerminateProcess  pIsProcessorFeaturePresent 0QueryPerformanceCounter GetCurrentThreadId  ÝGetSystemTimeAsFileTime jIsDebuggerPresent mGetModuleHandleW  ; memcmp  < memcpy                                                                                                                                                                                                                                                                                                                                                                                                                                                          2¢ß-™+  Í] ÒfÔÿÿÿÿÿÿ         /                              ØU @           `& @   èU @           @' @   øU @           �' @   V @           Ð' @                                                                                                                                                                                                                                                                                                                                                                      S  0\  S    @\    \  X\  `  f  h\  p  Š  „\  �  \  ˜\  \  æ  ¬\  æ  ¦  À\  ¦  ®  Ô\  ®  Í  ä\  ð  =  ô\  =  £  ]  £  Ç  (]  Ç     8]       (]    ï  P]  ð    d]    X  €]  `  ø  ˜]         ¸]  €   ·!  È]  À!  i"  è]  i"  µ%   ^  µ%  Ï%  ^  Ð%  Q&  ,^  `&  :'  D^  @'  „'  T^  �'  Ç'  T^  à'  î)  \^  ð)  ‹+  p^   +  å+  „^  ð+  ^,  �^  ^,  ¿,  ¨^  ¿,  Ù,  ¼^  à,  -  Ì^  -  .-  Ô^  .-  Ÿ-  è^   -  _.  ü^  `.  ç/  _   0  !0  (_  $0  ß0  T^  à0  ð0  Ü_  ð0  	1  Ü_  1  ƒ2  ,_  „2  –2  Ü_  ˜2  Ì2  T^  Ì2  �3  \_   3  4  d_  4  M4  Ü_  P4  ™4  T^  œ4  e5  ˜_  h5  6  p_  6  (6  T^  (6  S6  T^  T6  £6  T^  ¤6  »6  Ü_  ¼6  h7  ¤_  ˜7  ³7  Ü_  Ð7  9  °_  9  l9  Ü_  |9  ´9  Ü_  ´9  þ9  D^   :  J:  D^  T:  <  À_  Ì<  é<  Ü_  ì<  E=  Ô_  `=  ±=  è_  Ð=  Ò=  Ð_  Ò=  ð=  T_  ð=  >  �_                                                                                                                                                                                          
         E   r   7                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            0  €   `  €   x  €   �  €                  ¨  €   À  €   Ø  €   ð  €               e    €                    €                  8 €               	  P                 	  `                 	  p                 	  €                 	  �                 	                    	  °  À¡  h          (¦  ¨          Ð¶  ¨%          xÜ  ›          �w >           Ðw X          ({ }          (                                                ­�: ©|6	º�EcÈ™OÌÍ�Q÷Ò¥^ùÕ©cäË£c¡Ò¦_GÛ�5×žC         k7Ë *N H%ŒK/G»‹=xÃ�?õ³‚4ÿ«{/ÿ»‰9ÿÏšHÿ×©aÿÓ¬oî³‘[’²…>²�Q ˆ<  n:Î s<ÖV-§‰Y9Gb˜l3ì�\!ó_C—R:dgI�›o(æ¾�Dÿ¬˜xÿ¸�sÿÛµx±ÓžKÕ¤W e/Ên9Î’o?ÇøsI»ïoH¨ÿV4‰â;wCqV'_u_<–\F%l™‰oíÄ´›ÿÕªeÿà»‚ÿÔ®r�] yIÑLŠ`Øï�yßú¢€ÒÞ¢{¡ü†a¥ÿ_:¡Ù�`>ÅÂ£qÙxoa9ÄÅÇÜÊ¯ƒÿ×¨]ÿÝ´tÿÛ¼ŒèÕ¬lF‘jÞ`¢äÀ˜wÕÈaK¾�D¹©}>ÿ’jHÿ¹�VùØ·ƒ‚YPAMÁ¿»õ·›pÿÖ©bÿÝ³rÿäÃ�ÿá½„§‘xRlš~d\ˆmyL]Idšv;%Ã˜U}È ] ÂŸg x9UhK‘­†Iÿ»�KÿÓ¦_ÿÚ°nÿâ¿‰ÿÕºŽØÇ©{ûÜ¼ŠúÒ³�è’{W�´”b¯¤†V—´ŒM«³…<Ñ†`%°ZÆÅ‘?ÿØ¨[ÿ‰mAÿ€g@ÿÞ¾ŒÿçÍ¥ùÎ±ƒûæÅ’ÿäÂŽÿ¾žkþÕ«hÿÍžUÿº‡7ÿ�e$÷[AÛ›n'üÐ›Iÿ×§[ÿ‰mAÿ€g@ÿÞ¿ŒÿçÍ¥ùÆ§vãÝ³rÿÚ°lÿÙ¬cÿÎ›Jÿ½‰9ÿ•j&ÿ[AýhJþ®}/ÿÐ™DÿÓŸMÿÙ¬eÿÚ°mÿâÁŒÿÖ»�Ø½¡t§Ú°nÿ×ªbÿÍ�Oÿ¸…3ÿ¢r(ÿZ ÿS;ÿ�\!ÿ½‡1ÿÎ•<ÿÓ OÿÚ®iÿÜ³qÿåÆ•ÿá¾†¥ª“pIÓ¯víÆ’@ÿ¿ˆ0ÿµ€-ÿ�f%ÿnNÿV=ÿ“i%ÿÂ‹2ÿÎ˜AÿÖ§\ÿØªbÿÝ¶wÿäÅ’éÚ°lC?2Æ©{’Ï£]ÿ»…1ÿšn'ÿ‹c$ÿlMÿfIÿ¬|/ÿÎ˜CÿÓ¡PÿÕ¤WÿÛ±nÿá¾‡úÜ³r|µc ¸œn §ŒbÙ¹‡±Í¥gÿŸw6ÿŠc$ÿhJÿjKÿ±„=ÿÕ¢PÿÖ§[ÿÙ®iÿÝ·zëÛ³r|Ì’9
ÑœI , êÅˆ Ô­qâ¿ˆ“Ü¹�ïÇ¢gÿ³ŽTÿ½˜]ÿ×±uòÕªg½Öªg¶×¬g‹Ñ S9ÁÈŒ1             Ù¬e Ó£Vàº~IãÀˆ äÂŠËåÃŒÀá¼‚hÂ�@®o¡M ¢Q             ð  À  €                                          €  À  à  (       @                                                                 ‚Q �\ …]«:eÃ•K¿ÉœTë¾•TðÅ�_ñÓ¨cóÐ£]ÙËœR­Â�Bi—i ®f·t                                                                 �n# •e¯�8a»ŽHÌÂ—SóÕ¦[ÿÔ£TÿÒ Qÿ×©`ÿÙ­gÿÚ¯lÿÛ²qÿÐ©løÀ�eÍÓ£W–É‘77·o¿~                                            ‚[ [9¥{9zÉšO÷ÐœIÿÊ“=ÿÇ�7ÿÃ‹3ÿÄŒ3ÿÍ–?ÿÐšDÿÒ�HÿÔ Oÿ×ªbÿÝ·zÿà»ƒÿÛ²rêÔ¡QŠÙš6Æ�A ý¿%                             m9Ì     H&†29'  ÿ ©|5t»ŒBñË•@ÿ»…1ÿ«y+ÿ¤t)ÿšm'ÿšm'ÿ­{,ÿ¼‡2ÿÇ�9ÿÏ™CÿÔ¢QÿÖ¥XÿÛ¯iÿÖ²yÿ¸›lþ™u<Ã³�26\aj Ã‚                     l8Ì p<Ð p;ÑDN)“°%—l%0»Š<åÅŽ7ÿ°},ÿ—k&ÿoOüT<ÜG3·G2³Z@ÑxUö¡r(ÿÃŒ5ÿÐ›GÿÔ¢Qÿ²ŠIÿ”…nÿ�xjÿ°˜rÿÙ°oÙÏ—>Bá¹z Æˆ(             p=Í n:Î n:Î6k9ÉÜ@"w¯  $U<�‰b'ÿ€[ÿnOÿQ:ë(
w         "OV=Ç˜l&ÿÅŒ3ÿ©=ÿœ”ˆÿ¶±«ÿº™eÿã½„ÿåÆ–ÿÛ±nÙÌ“86ÑœG ÄŠ-         n:Í n:Ín:ÎÂm9Ìÿ\0®òX-§åX.�õY0‘ÿM+{ÿ6Oÿ(¢  " :+dK#JlQ&hnZ<>'S;¹�d#ÿ�‚nÿÛÝßÿ®˜vÿÕ§^ÿÛ¯lÿá½†ÿåÆ•ÿØªaÂÍ�/Í”8     n;Ì n<Én:Î‰m9Îÿn9ÎÿuCÒÿQÕÿ†YØÿ…YÙÿQ×ÿsBÏÿ`3´ôB#}£ (jQ)_yZ(÷P:ÿ‘}]ðspkI -RF4áÊÊÉÿ×ÔÑÿ·“\ÿÚ«bÿØªbÿÜ²qÿãÁ�ÿß¾Šÿ¹ŒDvÿÓ… W8 m9Í m8Í7n:Îè}OÓÿ™tÝÿ©Šãÿ¬�äÿª‹äÿ¦†àÿ¡�ÛÿœyÜÿ�dÝÿo?ÇÿD#‚ª?3!M¡IíÄŸeÿÀ¨ƒàlcV*   †††ÈëìíÿÇ¿³ÿÀ“LÿÙ«cÿØªbÿØ«dÿà¹}ÿØ¼’ÿºžqÏÎ›J0Ì›M P»sAÏ—ŽeÙÿ§‡âÿ§‡ãÿ¡ßø¡~âÆ˜u§Èª�sÿšqXÿxY[ÿz_˜ÿ…^ÐÿT,¡ø/'­ u/ñâ½ƒÿ×¼’¼©_ (()'¬¬¬çôõöÿÀ´¢ÿÂ�=ÿØ©`ÿÙ¬fÿÚ¯jÿÞ¶xÿæÇ–ÿéÍ¡ÿØ«b—·j }OÒ(’kÛÝ£�áÿ¢áÿ£âÿ…h¹ÝK:s%¤x+3¼�FÜÉ”?ÿ¦v&ÿvT$ÿ`CEÿ[==ÿ…^(ÿÊ™LÿÞ¿�ýÁ¥zr†‰� 655C···õøøùÿ¹®�ÿ¾Œ=ÿÚ¬cÿÜ²pÿÜ²pÿÜ³rÿâÀ‰ÿéÏ¦ÿßºÞÏ˜A*•mÞ¡~â^¢á‰¢á¯£€âÐ‘rÊåJ9gdñÄù «‚@bÉœVïÌšKÿ¿Œ9ÿ³‚0ÿ¼Š7ÿÑ¡TÿÛ·þË¯�²®…E   <0®©§¤ÿêëìÿ¤œ�ÿ”n2ÿØ©`ÿÜ²qÿÜ²pÿÜ²oÿàº~ÿçË�ÿåÇ–ûÕ£Sl	 	    —sÿ­‡þ¦‚ë)bLŠ+   �g£|@KÅ�\ÂÍ¤cïÔªhüÖ¯rùÐ®yÞÈ§s�›wA¤v-"!+fIæ’q>ÿ©Œ]ÿ±‹Oÿ—o1ÿÐ¢YÿÜ²pÿÜ²pÿÜ²oÿÞ¶wÿåÆ”ÿãÉŸÿÉŸ\�zb=»Ÿ‚UÆŠpF¡t\7yZF%R6(/       Ð³o �q,®‰M5»–[O°ŽXE�o;%`H"¤z9{™n+œ 4rQë°}+ÿÌ–@ÿÔŸLÿÄ“EÿÔ£WÿÝ±lÿÜ±mÿÝ´rÿÞ¶wÿæÇ•ÿÒ¿ þ¬‘f­§ŒbòæÅ’ÿà¿ŒÿØ·„ÿÌ«yû¼�lð�xR†E7!)e<�x_7€lU1`VC%,sY1`‡j=y¢I¢¸‹EÙ©z1þƒ]!€2#^€[ ûµ�/ÿÏšGÿÔ¢RÿÖ£SÿÓ¤[ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò®”jýçÇ”ÿåÅ“ÿæÆ”ÿçÇ”ÿéÉ–ÿ¤�iéPC-ÃÒ®uþ×²vÿÆ¤mù†mFÛË¢aýÎ¡ZÿË—Fÿ´�0ÿˆ`"ßI4`_DÒ q(ÿÆŽ7ÿÕ¤Vÿ×¨]ÿÛ®eÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý°—oýçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿçÇ•ÿÁ¦|ÿ„oMÿà»€ÿß¹|ÿÛ³sÿ¿”QÿÊ”AÿÃ‹4ÿ¯|,ÿŠc#ü\B­L6Ì€[ ÿ®|,ÿÌ•=ÿÖ¦Yÿ×§\ÿÛ®dÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý®–pòçÇ•ÿåÅ“ÿåÄ‘ÿäÂŽÿãÀŠÿÛ·ÿÊ¢bÿØ¨^ÿÕ¤VÿÔ¡PÿÎ˜Cÿ¼…/ÿ§w*ÿŒd#ÿjKìC0àaEÿŽe$ÿ·‚.ÿÍ—BÿÔ OÿÔ¡PÿÕ¢SÿÓ¥\ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò¤ŽjÙá¾†ÿÞ¶xÿÜ³rÿÛ°mÿÚ®iÿÙ®hÿÖ¦YÿÓžLÿÓŸMÿÐœKÿÀ�<ÿ¢s)ÿ�e$ÿuSÿK5ùQ9þrQÿšm'ÿ»†1ÿÏšEÿÓŸLÿÓŸMÿÓŸLÿ×¨]ÿÝ²mÿÜ±mÿÝ´rÿÞ¶wÿçÉ™ÿÓÀ¢þ­’g­”^¬Û¶|ÿÙ¬eÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿØªaÿÒŸNÿÇ“Bÿµ‚3ÿ¬z,ÿ r(ÿ~Z ÿaEÿ@.ÿ^Cÿƒ]!ÿ£t)ÿÃ�7ÿÏ—?ÿÐ™BÿÒœHÿÓ OÿÚ®hÿÜ²qÿÜ²pÿÜ²oÿÞ¶xÿæÉšÿäË¤ÿÉŸ]�zgJlÕ¶†ûÚ¯iÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÔ¥[ÿ¿Œ<ÿ­z,ÿ«y+ÿ¨w*ÿŽe$ÿZ ÿR:ÿJ5ÿjKÿ�f%ÿ®|,ÿÈ�5ÿÏ–>ÿÏ—?ÿÏ—?ÿÔ¡QÿÛ°lÿÜ²pÿÜ²pÿÜ²oÿà¼‚ÿéÎ¤ÿæÈ™ûÕ£SkI9*ÃªƒÞß·yÿÙ­fÿÙ­hÿÖ©aÿË™KÿÁ‹5ÿ»„/ÿ®|,ÿ©x+ÿ’h%ÿ�\!ÿxVÿF1ÿV>ÿvTÿ–k&ÿ»…/ÿÉŽ2ÿË’7ÿÏ–>ÿÑšEÿ×§\ÿØ«dÿÚ®iÿÛ±nÿÝ´sÿäÄ�ÿëÓ¬ÿß¹~ÛÏ—@'   £�i–áÂ‘ÿØ¬fÿÎžQÿÃŽ:ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿšm'ÿ‚\!ÿ‚]!ÿiKÿB/ÿ_Dÿ€\ ÿ�p(ÿÀ‰0ÿÈŽ2ÿÈŽ2ÿÍ–?ÿÖ¦ZÿØªbÿØªbÿØªbÿÙ«dÿÞ·zÿçËŸÿèÍ£ÿ×©_� = „kC nX67Ï¶ŽéØ¯nÿ¿‰2ÿ¾†/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¬{,ÿ�e$ÿ…_"ÿ�\!ÿZ@ÿC/ÿdHÿˆa"ÿ¦v*ÿ¾‡0ÿÈ�4ÿÌ•>ÿÒŸNÿ×§]ÿØªbÿØªbÿØªaÿÚ­hÿá½…ÿèÌ¡ÿÞ·yÝÐšE+ÒžL '	    £ŠbŠßÂ“ÿÎ Vÿ¾‡1ÿ¾‡0ÿ¿‡0ÿ²~-ÿ‘h%ÿŒd$ÿŒd$ÿ‚]!ÿY@ÿL6ÿmNÿ“i%ÿµ‚1ÿÆ�9ÿÐœHÿÔ¢QÿÔ¢RÿÔ£Tÿ×¨^ÿØªbÿÙ¬fÿß¹~ÿæÈ™ÿà¼ƒ÷Ñ›HhòÐ› Ì—C     pW. [CÁ¦{ÂäÅ•ÿÏ VÿÀ‰3ÿµ�-ÿ•j&ÿ‹d$ÿŒd$ÿ�d$ÿyVÿbEÿ]Bÿ€[ ÿ­|,ÿË”>ÿÑšCÿÓžKÿÔ¢RÿÔ¢RÿÔ¢RÿÕ£TÿÙ¬eÿßºÿåÇ—ÿâÀŠüÓ¡QŽÆ‡#	Ì’7           Ç¢f Šl>6Ò¶‰ÙæÈ˜ÿÓ§bÿ§{4ÿ‹c$ÿ‹c#ÿŒd$ÿŠb#ÿmMÿcFÿ_CÿkLÿ˜m(ÿÉ”?ÿÑšCÿÒœFÿÔ¡QÿÔ¢RÿÕ£Tÿ×©_ÿÞ¶yÿåÇ—ÿà½„÷Ô¡RŽÊ�-Í“9                 + ÿÿê ª‡NBÝ¾�ÙæÉšÿÔ­pÿµ‹Hÿšq/ÿŽf&ÿ€[ ÿcFÿaDÿaDÿ`Dÿ‰f.ÿÓ¤XÿÕ£SÿÓŸMÿÖ¦ZÿÙ¬fÿÜ´tÿà»�ÿÞ¹ÿØ­hÝÑœJgÇˆ&	Ë�3                         mI ÿÿÿ Î V6à¼ƒÃçÉ›þãÁ‹ÿÕ­mÿÂ˜Uÿ¦~>ÿ�i1ÿŠg0ÿ•p6ÿ°‡FÿÏ¡Xÿß¹}ÿÛ´vÿØ®lÿÛ´vÿÞ¸}ÿÛ´uùÖ©bÙÎšG‹ÆŠ,)­V À}                                 ±p Ý²m ÐœIÛ²q‹äÄ‘ëçËžÿåÆ”ÿàº}ÿÜ³rÿÛ±oÿÝ´sÿá»~ÿãÁŒÿãÃ�ðÍŸWŠÂ‘D‰Æ•H‘Í™F{É‘9OÂ…%¬e ¶r                                                 Ì’6 Å„"Ô¤V9Ü´t—âÀŠÛäÅ”÷æÈ™ÿæÊœÿçÊ�ÿæÉ›úá¿ˆ×Ù®ifÉ�.ÐšF                                                                                 Ê‹( À~Ð›F$Ö§[WÙ®h‚Û±n”Ú°m‰Øªb`Ñ�K"ºn Å…#                                                     ÿÀÿÿ€ ÿ  ?ù  ð  à  À €  €                 À                                      €  €  À  à  ð  ø  ü  þ ÿÿ€?ÿ(   0   `           $                                                                                  ?, Ê�+ ¦t$¯|,e¶…7¨¼�A×Â“Hó§�Dß¯‰LàÍžT÷ÊšNæÇ•FÌÃ�=£¿ˆ2nº‚(6¼ƒ"   õàX                                                                                                                 ”d uE ¡q%'šo,t™u<³ËŸYûÔ©dÿ×¬gÿÙ­fÿÏ¥bÿÓ­pÿÞ·zÿÝ·zÿÜ¶zÿÚ³uÿÕ¬küÏ¢Zê¨~<¢šo*LÆŠ*(¾}Â„                                                                                                      �n# ˜i¥v,d¶‰AÛÇšTþÂ˜Uþ×¨]ÿÕ£TÿÒŸMÿÐœHÿÑ�IÿÖ¥XÿÖ§\ÿ×©_ÿØ«dÿÚ¯kÿÜ³sÿÞ·zÿ¼žnúÏ«t÷Ô¤ZâË”<�ÅŠ+.¿Â…$                                                                                         Šb! }T¨z1†Á”L÷Ô¤XÿÓžKÿÎ˜AÿÍ–?ÿÊ’8ÿÈ�4ÿÇ�2ÿÈ�4ÿÐ˜AÿÑ›DÿÒ›EÿÒœGÿÓŸLÿÕ£TÿØªbÿÝµwÿá½…ÿãÂŽÿÞ¹~ÿÒ¢WãÉ�7|Ã‡(ÇŒ/ ¼                                                             H*t <$`$    šm& ¤s%
ˆb&n©‚DæÕ£TÿÏ˜BÿÅŽ7ÿ¼†1ÿ»…/ÿ¹„.ÿ¶�-ÿ´€-ÿ¶‚.ÿÂŒ5ÿÇ�9ÿË”=ÿÏ˜AÿÑšCÿÑšCÿÔ¡Pÿ×¨]ÿÚ¯kÿÝµwÿá½…ÿãÃ�ÿÜ´týÒœGÀÐ“3;íšÙ—/                                                     o<Î žUÿK(‹^-S8_ «‚> žq)h¸ŠA÷Æ“CÿË”<ÿÀ‰3ÿ²-ÿ¦v*ÿ r)ÿ�p(ÿ–j&ÿ’h%ÿ•j&ÿ¥u)ÿ°},ÿº„/ÿÂ‹4ÿÉ’:ÿÑœGÿÔ¢RÿÔ¢QÿÔ£Sÿ×¨^ÿÝ³pÿÕ¯uÿ¹Ÿvÿ”{Tÿ‰e,ã±0_ë§;Ê‘6                                             m9Í l8Ìo:ÐtF%ƒÓ)R9 ˜k$'°‚:ÚÎšGÿÅŒ2ÿ·‚.ÿ¬z,ÿœo(ÿˆ`"ÿoNÿ\BýM7òG2éK5î_CúvTÿ’h%ÿªx+ÿ¼…/ÿÊ’9ÿÑ�JÿÔ¢RÿÕ¢RÿÓ¡Qÿ¥€Dÿ{mWÿxtpÿ`VGÿ¶Ÿ{ÿÖ«eñÎ•;rÆŠ,É�4                                     n;Í o<Ìn:Ïrh7Ãø2\Ÿ   ÄŠ0 |X³ƒ5ÿ¾ˆ4ÿ±~,ÿ¡s)ÿ‘g%ÿvSÿI3õ&
´f9   *1Q&
“F2ßrQÿ¡r)ÿ¿ˆ0ÿÉ�5ÿÐ›GÿÐŸOÿŠl;ÿ€{sÿ¿ÀÁÿ�‚oÿËªwÿçÆ”ÿèÌŸÿÙ­gôÍ”:rÈŽ2Ë“:                             m9Ì {Eç n:Í^o;Ðñ]1®ÿ,   %5L6Î€[ÿwUÿjLÿcGÿX?ÿ5&ä`   
                     )*žeHø�p(ÿ¿‡0ÿÈ�4ÿ†f4ÿˆ…‚ÿäåæÿ ˜Œÿ¸�SÿÞ´rÿà¼„ÿäÄ’ÿçËŸÿ×ªañÌ’7_ÿÿ� È�7                     q?Î m:Í n:Í<n:Îâo:Ïÿe5½ÿM)‘ïN)’çM)�êN*†üP,~ÿH)lÿ:"Pÿ&,ÿøc#         	  4(I81?1&   
!cF÷¤t)ÿ’h&ÿ{ulÿáâãÿÔÓÓÿ—}SÿÙªaÿØªbÿÜ³sÿá¼…ÿåÆ•ÿæÉ›ÿÔ£TâÊ�3<Ì’7 Ê‘8                 n;Í n;Ìn:Î¿n:Îÿn:Îÿn:Ïÿo:Ðÿn9Ðÿn8Ðÿn8Ñÿm8Ñÿm8Ðÿk7Ìÿd4½ÿO*–û6e¹%G    fM$ƒvX'ÜmP#îx[.æ…u[­AAA)   )“iJÿdWBÿÉÉÊÿ÷÷øÿ¨¢˜ÿº’SÿÚ«cÿØªbÿØ«cÿÝ¶xÿá½‡ÿçÊœÿãÁŒÿÑ›E¾Ï“6Ð—< ®{*         n<É _�  n:Í{n:Îþn:Îÿm8Îÿm9ÎÿsAÐÿQÔÿ‰_×ÿ�fÙÿ�gÙÿŠ`×ÿ�TÕÿwEÒÿp;Ñÿi7ÆÿO)“î"@x   $=“o6ódHÿ-
ÿM9ÿº§‰ÿa`]„´±¬  &Ï”“�ÿèèéÿôôöÿ”…lÿÐ£\ÿØªbÿØªbÿØªbÿÙ¬fÿß¹ÿâ¿ŠÿéÎ£ÿÐ©kù¦v*T°2 _=         n;Í n;Í.n:Îàm8Îÿq>Ïÿ…ZÖÿ¢€ßÿ³—æÿ·œçÿ´˜æÿ°“æÿ®�æÿ­Žæÿ«‹æÿ¦…ãÿ—pÝÿ}OÔÿo;ÐÿV-¡÷!?s   hBºÀ™[ÿÁ—VÿÌ§kÿº¨‹çFDAAlha    III«ÈÈÈÿñññÿççèÿ“xMÿÖ¦YÿØªbÿØªbÿØªbÿØªaÿÛ°nÿá¼„ÿáÂ‘ÿ¦”xù™zI¤Ð›G$È–H     m9Ì m:Êm9Í�n;Îÿ„XÕÿ§‡áÿ´™æÿ­Žäÿ¥ƒâÿ¢áÿ¡~áÿ�{Úÿ›yÊÿ–t¹ÿ�m°ÿŠl¸ÿ™yÒÿ£�ãÿ‰^Øÿp<ÏÿG%‡ê>:*Š©€@ÿÞµuÿäÌ¦ÿÂ§}¼g. %
    zzy×ÜÜÜÿøøøÿÚÚÚÿ˜u=ÿÕ MÿØªbÿØªbÿØªbÿØªcÿÙ­gÿà¼‚ÿäÄ“ÿçÑ­ÿáÀ‹ÿÓŸN�Ë”;ÑžL m9Ì l7Ë(r@Ïá’kÚÿ¬�äÿ§†ãÿ¢~áÿ¡~áÿ¡~ßø¢áËž{ÜŠŠikÉ²ˆWÿ²‚>ÿ˜m/ÿvU+ÿW@?ÿnU“ÿ–sØÿwIÍÿO'œÿ/ÉaEß¼ˆ6ÿÜ²pÿêÒ¬ÿÈ¨uŸ    4˜——ïãããÿüüüÿÒÑÐÿžw9ÿÒšAÿ×¨_ÿÙ«dÿÚ­hÿÛ°mÿÜ±oÿÞ·zÿäÄ‘ÿèÌ ÿëÔ®ÿØªbáÐšE(ÒžM ‡[Ø xHÐs“lÛÿ¥„âÿ¢áÿ¢áÿ¢áÿ¡~ßÿpWœÉ^I�“j ¤v)[À“KõÎ›JÿÃŒ5ÿªy*ÿ„^ÿX?ÿL5JÿH-\ÿ@(:ÿ`C!ÿ¥u*ÿÎ›Jÿá¾‡ÿÕÀ�ô²�TXÀ¢r **) $##G¥¥¥øåååÿþþþÿÏÎÌÿ y:ÿÒš@ÿØ©`ÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿâ¿‰ÿæÆ•ÿìÖ²ÿà¼‚ÿÒ�JrÕ¡N l;Ç“lÛš¢áî¢áú¢áÿ¢áÿ¢áÿ£€ãÿw\¥ï!A:+0 ¡n�l2ƒÆœZýÔ NÿÃŒ5ÿ±~-ÿ�o'ÿŠb ÿ†_ÿ—l$ÿ´�/ÿË–CÿÜ³rÿåÊ ÿ½Ÿq¯c: E2    �¥¥¥ÿæææÿþþþÿÌÌÌÿsY1ÿË˜HÿØ©^ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿß¹~ÿåÅ’ÿêÐ§ÿèÍ¡ÿÕ£U»Ï™DˆbÌ¡~ß¡~à.¡}àN¡~àt¡~à›¢~á¿¢âÜ™xÕôL;k®   oP  Ÿp&¸ŒE¹Ê ]þÒ£XÿÎ™EÿÅ�9ÿÂŒ7ÿÃ�7ÿË•?ÿÔ¢Sÿß·yÿÜ¾�þ½£xÆ±…@4·‘X %	 VA1ö›š™ÿÜÝßÿôõöÿÁÀ¾ÿeM'ÿšs6ÿØ¦XÿÜ²oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÝµuÿäÃ�ÿçÊœÿìÖ²ÿÙ­gèÐšF6                žyß štßžzß
 }ß¤�å9kS–O §x.  p$•r;|ÆžaìÕ«jÿÕ«hÿÚ®gÿÙ®jÿß¸{ÿÙ·‚þÑ´…ôÅ¢k°�h.&i žq*    +�uTÿy`7ÿ‰uTÿ–‚cÿ™~Rÿ§|7ÿ‚a+ÿÔ¢SÿÛ°mÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²qÿâ¿‰ÿæÆ–ÿí×´ÿáº~üÐœHn#Q8*d? "                                  ¤q" šg­5@ª„H„¸•^»Î¨mÜ»›iÏÉ¦nËº–^™—t=D¬u"  œt4M—m)€   - —…_"ÿ¨w)ÿ¼†0ÿÌ˜EÿÔŸLÿÆ”Dÿ•o2ÿÒ PÿÛ¯kÿÜ²qÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà»�ÿåÆ”ÿãÌ§ÿ°˜tï•o3YbN.Ëº˜dÿ«ŒZô”wJâ|b:ÆdN+¤K:}1$W5                    e9 5  œh¯{)�n#¢g­J    SA%(›w=†©|3î‡`"—    0" †_"ÿ©x*ÿÁŠ4ÿÑœIÿÓŸMÿÒžLÿÍšJÿÓ OÿÚ®iÿÜ°mÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá¼ƒÿèËŸÿàË«ÿ´¥�õ¶�T›{eAçåÄ�ÿèÇ”ÿæÅ‘ÿâÀ‹ÿÙ·�ÿË©tÿ¸˜eü£…Tò�h@¡	7*C3g5(Z%D5		''5D3KhQ,r‘rA©´‹Jã¾‹;þ•j&þwUb   C/Ì�e$ÿ«y+ÿÂ‹5ÿÑ�KÿÓŸNÿÓ NÿÔ OÿÕ£TÿÖ§]ÿ»‹?ÿ¨|6ÿº’SÿÛ¶zÿà»ÿâÀ‰ÿéÏ¥ÿîÙ¸ÿòßÁÿÚ¯iæ†oKõåÅ’ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿæÆ•ÿçÇ•ÿêÈ•ÿ¹žtõ!WUE-z¸–`ý¹–]ý­‹V÷¥„Pò{c<¢aL+¢€Iê®ŠQð¼–YùÊ ^ÿÎ�QÿÅŽ9ÿ¢s(ÿ{XÙhJ"&
ojKû¡r(ÿ¹„/ÿË”=ÿÕ¤WÿÖ¦YÿÖ¦Zÿ×¨\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö�vRþæÆ”ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿÓ¶‡ÿ0)Þ]N5éà»€ÿâ½‚ÿã½�ÿå¿‚ÿ¢‡\ú~fAöàµqÿÛ¯iÿÓ¢VÿÉ“>ÿÀˆ1ÿ¦v*ÿ‚]!ýqQx!	TU=êŒc#ÿ¬z,ÿÅ�3ÿÑœGÿ×¨]ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�yVþçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿäÄ“ÿ]O;ÿˆrNÿä¾‚ÿà»�ÿà»�ÿá¼€ÿÌ¨oÿ·�PÿÎ›KÿÆ�9ÿÄŠ1ÿ¾†/ÿ¥v*ÿ‡`"ÿsRÆ1#mK5åvSÿ™m'ÿ´.ÿÊ‘6ÿÓ¡Pÿ×¨^ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�xWõæÇ—ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ”ÿèÇ•ÿ¤Œgÿºšhÿá¹{ÿÝ´sÿÚ®iÿ×¨^ÿÕ¢SÿÈ‘:ÿÃ‰0ÿÃŠ1ÿ¸‚.ÿ r)ÿŠb#ÿuTóH4¦>,äbEÿ�\ ÿžp(ÿ¹ƒ.ÿÈ�7ÿÓ OÿÕ£UÿÕ¥WÿÖ¦Yÿ×§\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö…qRçåÇ˜ÿåÅ“ÿåÅ”ÿåÅ“ÿåÄ’ÿäÃ�ÿãÁ‹ÿá¾†ÿàºÿÖ¯pÿÓ¤YÿÕ£SÿÓ OÿÓŸMÿÓŸLÿÓŸMÿÌ–@ÿ¿ˆ0ÿ®{,ÿ›n'ÿ�e$ÿxVÿ]Cß<+çP9ÿkLÿ‰a#ÿ¥u*ÿÀˆ0ÿË•?ÿÓŸMÿÓŸMÿÓŸMÿÓŸNÿÓ OÿÕ£Tÿ×¨^ÿ»‹?ÿ¨|6ÿ»’SÿÛ¶{ÿà»ÿâ¿‰ÿéÎ¥ÿîÙ¸ÿòßÁÿÚ¯iæxeIËáÄ–ÿâ¾‡ÿà»�ÿÞ·zÿÜ´tÿÛ±nÿÚ¯jÿÙ­hÿÙ­gÿÙ¬eÿÔ¢RÿÓŸLÿÓŸMÿÓŸMÿÓŸMÿÒžLÿÄ‘?ÿ¤u*ÿ–k&ÿ‘g%ÿ{WÿkLýB/õJ5ÿ_CÿtSÿ‘g%ÿ¬z+ÿ¼†1ÿÏšEÿÓŸMÿÓŸMÿÓŸMÿÓŸMÿÓŸLÿÕ£TÿÛ°mÿÜ°lÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá½…ÿéÍ¢ÿàÌ­ÿµ¦�õ¶�T›dS8£Ø»�ÿÛ°lÿÙ­gÿÙ­fÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÖ¥YÿÓŸMÿÓŸMÿÓŸMÿË—Fÿ¹‡7ÿ­{-ÿ¤t)ÿ•j&ÿ}Y ÿsRÿT<ÿ9(ÿS;ÿlLÿZ ÿ˜l'ÿ³-ÿÃ�7ÿÏ—@ÿÐšDÿÒ�JÿÓŸMÿÓŸMÿÓŸMÿ×¨]ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿá½…ÿçÊ›ÿäÎ¬ÿ°™vï”n3YI:#nÊ±‰üÞ¶vÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿØªaÿÔ OÿÎ›Iÿ¾‹;ÿ¯}.ÿªy+ÿ«y+ÿ©x+ÿ�d$ÿuTÿlMÿ@-ÿC0ÿX?ÿvTÿŠb#ÿ¡s)ÿ±.ÿÌ•=ÿÏ—?ÿÏ—?ÿÏ˜@ÿÑ›FÿÒžKÿÔ PÿÚ®hÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿãÂŽÿçÊ�ÿîÚ¹ÿá»üÐ›Hn!6²›wèäÁŠÿÙ¬fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ®hÿØ«cÿÈ•Fÿ²€1ÿ«y+ÿ«y+ÿ«y+ÿ«y+ÿ—k&ÿ‚]!ÿ€[!ÿ`Dÿ:)ÿO8ÿbFÿxUÿ˜l'ÿ¥v*ÿ»…/ÿÌ“9ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ˜AÿÕ£UÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÞ¶wÿåÇ–ÿèÎ£ÿíØ¶ÿÙ­gèÑ›F5   �yW»åÉ�ÿÚ¯lÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­hÿÙ¬fÿÑ¢XÿÆ‘?ÿ»…0ÿ­{+ÿ«y+ÿ«y+ÿ«y+ÿœo'ÿƒ^"ÿ�\!ÿ[!ÿN7ÿ@.ÿV>ÿmNÿ~Y ÿ�p(ÿ®|,ÿÆ�2ÿÈ�3ÿÌ”:ÿÏ—?ÿÏ—?ÿÏ—?ÿÐšDÿ×§\ÿÙ¬fÿÛ°lÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà¼ƒÿæÉšÿëÔ®ÿèÍ¢ÿÔ£T¹ÎšGâ¶q cO1r×¿™ÿà»�ÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÔ¦]ÿÉ–FÿÀ‰3ÿ¾†/ÿ¾‡0ÿ¸‚.ÿ¬z+ÿ«y+ÿ r(ÿ†_"ÿ�\!ÿ‚]!ÿuTÿ?-ÿH3ÿ^CÿsRÿ‰b#ÿšn'ÿº„/ÿÉŽ2ÿÈŽ2ÿÉ�3ÿÍ•<ÿÏ—?ÿÐ˜AÿÕ¤VÿØªbÿØªbÿØªcÿÙ­gÿÛ±mÿÜ²pÿÝ´sÿäÄ‘ÿçË�ÿîÙ¹ÿßºþÑ�IlÔ N 3' '(²šuàéÍ¢ÿÚ°lÿÙ­gÿÖ©aÿÌšLÿÁ‹6ÿ¾‡/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ·‚.ÿ¥u*ÿ‰a#ÿ€\!ÿ�\!ÿ‚]!ÿeHÿ:)ÿN8ÿeHÿxUÿ‘g%ÿ�p(ÿ¿ˆ0ÿÈŽ2ÿÈŽ2ÿÈŽ2ÿÉ�4ÿÎ—?ÿÔ¢TÿØªbÿØªbÿØªbÿØªbÿØªbÿØ«dÿÚ®iÿàºÿæÈ™ÿêÑ©ÿëÓ­ÿ×¨]ØÐ›F!ÒžM     }eA�áÊ¥ÿá¾‡ÿÑ¡VÿÃŽ;ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿ•j&ÿ‚]!ÿ�\!ÿ�\!ÿ[ ÿV=ÿ;*ÿQ:ÿiKÿ~Z ÿ•j&ÿ¥v*ÿ½‡0ÿÇŽ2ÿÈŽ2ÿÈŽ2ÿÊ‘6ÿÑ�KÿØ©`ÿØªbÿØªbÿØªbÿØªbÿØªbÿØªaÿÙ­hÿá¾†ÿåÈ˜ÿíÙ¸ÿà¼‚ÿÒžK|á«R ÏœM     K8 9(.·�uáêÏ¥ÿÑ£[ÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¼†/ÿŸr)ÿŒd$ÿŠc#ÿ…_"ÿ‚]!ÿvTÿL7ÿ=+ÿT<ÿlMÿ„^!ÿ—l&ÿ®|,ÿº…/ÿÄ‹1ÿÉ�4ÿÌ–>ÿÒŸMÿÔ¢RÿÕ¥XÿØªaÿØªbÿØªbÿØªbÿØªbÿØ«dÿÞ¸{ÿâÀŠÿçÌ ÿæÈ™ÿÔ£UËÐ›GÑžL              x_8}ÙÀ—þåÅ“ÿÍœPÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ½‡0ÿ¥v*ÿ�d$ÿŒd$ÿŒd$ÿŒd$ÿŠb#ÿoOÿO8ÿ?-ÿU<ÿmNÿˆa"ÿ›o'ÿ¶‚/ÿ¾‰3ÿÈ’<ÿÑžKÿÔ¢QÿÔ¢RÿÔ¢RÿÔ¢RÿÖ¦ZÿØªbÿØªbÿØªbÿØªbÿÝµuÿâ¿‰ÿåÇ—ÿèÎ¤ÿÖ§]ðÌ“:QÐ–: Í™H             :* ! £‡Z¾èÐ©ÿá¾‡ÿÌ›Oÿ¿ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ«z+ÿŽf%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿˆa#ÿjKÿ_CÿT;ÿgIÿ‚]!ÿ r(ÿµ‚0ÿË•>ÿÏ™BÿÑ›FÿÔ¡QÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢SÿÖ§\ÿØªbÿØªcÿÜ´tÿá¿ˆÿäÅ”ÿéÐ§ÿÚ°mûÎ–=‚Ë‘7Í•=                     Žl7 ]E;À£tâìÓ­ÿà¼ƒÿÏŸTÿÀŠ4ÿ¾‡/ÿ°}-ÿ‘g%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿ�d$ÿZ ÿdGÿcFÿZ@ÿhJÿ‰b#ÿªy+ÿÀ‹5ÿÐ™CÿÑšCÿÑšCÿÓŸMÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢Sÿ×©`ÿÝ¶wÿâ¿ˆÿåÆ”ÿéÏ¦ÿÜ³sýÏ˜AšÊ‘6Í”;                          ÿÿÿ €b3_Ñ³„ñìÔ®ÿá¾†ÿÔ§_ÿ½‹;ÿ”j&ÿ‹c#ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿrQÿbFÿcFÿ_Dÿ]BÿxVÿ�p(ÿ»†2ÿÏ˜AÿÑšCÿÑšCÿÒ�IÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢QÿÔ¢RÿÖ¦[ÿÛ±oÿá¾‡ÿæÉšÿèÎ£ÿÛ±nûÏ˜AšÎ•;Î–>                                 7(    šxArÚ»‹ôìÕ°ÿãÁŒÿÔ©fÿ±‡Dÿ”l+ÿ‹c#ÿ‹c#ÿŒd$ÿŒd$ÿ†`"ÿhJÿcFÿcFÿcFÿ_Cÿ_DÿjKÿ¬€9ÿÓŸMÿÑšDÿÑšBÿÑ›DÿÓ OÿÔ¢RÿÔ£TÿÖ§[ÿÙ­hÿÜ³tÿß¹~ÿäÅ“ÿäÅ”ÿ×©`ðÎ–?�Ê‘7Ì“9 _'                                      _F ( ²‰IqÞ½ˆñëÒ¬ÿäÃ�ÿÜ³sÿË [ÿ¯…Bÿ—o.ÿ�e%ÿ‹c#ÿzWÿbEÿbEÿbEÿbEÿaEÿ_CÿtV'ÿÈ™NÿÚ­fÿÖ¦ZÿÔ OÿÔ OÿÖ¦ZÿÙ¬fÿÛ°nÿÝµwÿßº�ÿâÁŒÿáÀ‹ÿ×¬hýÎ™EÊÌ”:PÊ�6Ë’8                                                 œs1 wQÏžP_Þ¸zãéÏ¦ÿçËŸÿá½„ÿÛ²pÿÐ¥`ÿ½“Oÿ«�>ÿˆd,ÿsS"ÿoP ÿpQ!ÿwW%ÿ‰f/ÿ«‚BÿÌœPÿØ©_ÿàºÿà»‚ÿÜ´tÿÜ³rÿÞ¶xÿá¾†ÿâÀ‹ÿâÀ‹ÿÞº€ÿ×ªeüÍ™FÕÇ�2xÄ‰*ÌŽ- ¿‡/                                                         Î˜B Á~Ñ�K<Ù®iÁåÆ–ýêÒ«ÿæÉ›ÿá¾†ÿÞ¶wÿÚ¯lÿÒ¥]ÿËžVÿÇšTÿÇ›TÿÎ XÿÖ¨^ÿÚ­dÿÚ­gÿß¹}ÿçÊœÿÔ«jóËžVöÏ¤`þÐ¦dÿÕªfýÔ¥\ôÏœKÜÊ“;«Å‹/bÃ‡)½�%¿„'                                                                     µz# Ö£R Î™CÕ¤W€Þ·yåçËžÿëÓ­ÿéÎ¤ÿäÃ�ÿà»€ÿß·yÿÞ¶vÿÞ¶uÿÞ·xÿßº~ÿâ¿ˆÿäÄ‘ÿéÎ£ÿá¾†ïÎœL`¶'C¸‚,`¹ƒ-eÁˆ-YÅ‰+=Ã‡'Á„#ÈŒ) ¦g                                                                                     Í•= È�2ÐœH0Ö¦Z’ÝµváäÅ“ýèÍ¢ÿéÏ§ÿéÏ¦ÿèÎ£ÿèÍ£ÿéÏ¦ÿêÑ«ÿëÓ­ÿæÉ›ÿÞ·yåÔ¤VhÊ‘6Ð›H                                                                                                                             Î–< Ê�5Ð›F&Ó¡Qj×©`¬Û²p×ß¹~íá¿‡öâÁŒùâÀŠöà»�ëÛ²qÎÖ§[�Ñ�K2Ê�5Î—A                                                                                                                                         œ= â¶S ÉŽ4Ï˜AÑœG;ÒžLQÒžLXÑžKPÐ›G7Î–=Ä„$Ç‹,                                                                                         ÿÿÀ ÿÿ  ÿþ  ÿ  ÿü  ÿ  ÿø  ÿ  ÿ0   ÿ  þ0     ü    ?  ø      ø €   ð <    à     à     À     €     €     €              0    ø     ü       ?€                                                                                            €      €      €      À      à      à      ð      ø      ø    ?  ü      þ   ÿ  ÿ   ÿ  ÿÀ  ÿ  ÿà ÿÿ  ÿø ÿÿ  ÿÿ ÿÿ  ‰PNG

   IHDR         \r¨f  € IDATxÚì}wœå™ÿ÷�ª.moöº¬;®‚ÁØ„ÐB	Ž$€Ó+I(ù]r	wÀÝåîRH%…�5	�\$@(¡0Ýlã¾öö¦®éïï�ÑhUFÒhW[Lüý|ÖÞ�F3£yž÷y¾OŽáŽáŽáŽáŽáŽádªOàÊcÃõ÷‡˜Æ–€ÝkFOTîO©çŸ¼Cžêó<†£ÇÀcÃõ÷‡hMÝ¬P °ŒaÈ
Ý �„�v AÏ¶k­srCSƒ°t
,Öºß0èÖp4ºÝxðW»Ž)ˆc°Ã10‰Øpýý!ÒÔ¶šg¹UA7·VÑéJŽeæNÆgkºñ¥t;�¥¤gŸúâÚÎ©¾Ç0õ8¦ &–À‡<âûŠÓ8–Y5ÕçdAÓ�7‚¿‡#w?{ÕÉ[§ú|ŽajpLTº¥�ã„KÝ{CõSŽgªy|.ïÓèø�©éÆþ”¢ß¢iÊ=Ç,ƒ,S U@–Ð_:ÖU>äâpq¹9E!77ÏÂ#0à¯À‚gí¿.U§H(:Tƒ"©ˆÊÂ)IÇ`BÁHRu¤(M5t0wG¢Ñï³
þ1pLŒ®¿?œ5ç ä“ËœZÉ{¼<Z"š¼ý"¼|Qá®T�b8©¢'*ãHTÅ�á$Í(ùô�ýÃá?¦ÞÝ8¦ *Ä)?|nE0¸Æ-pç8eè›}<f×ºÑr¡5 L¨°;E_LÁ;ƒ)ìêO",iE÷S5ýÎè¡_yæÆÂS}ÎÇP}Lý“x”à¼_o½ÌéjïâÌ«saN­í5.xÒ ªN¡Šf@5L›Ý0(ô"æ;K †!àók8Ó]¨DÁ$U=Q;ûSØ3�°u8†IŠvÕƒŸXq÷$ßöc˜`S %°~Óf±ö²k.!7–×¹8K=XÚìÅŒ ˜`;$UŠf@ÖH…fPõ*°yYpó&gàáST	%ÕQW@Ñ¼ÑÇŽ¾„­‹ jú�#wÿ3Çr
Þ=8¦ l°~ÓfÑýOW}Å-°Ÿ-%øæ7x±¬Ù‹yu.pì¨�¥T=ó{R5“4HÍÙ>Ùpó,‚.6‡PÌV ,Eðfw¬À"Ðtã�X2uÁ±hÁ»Ç@,Á¯ñ
ÿ\Ê¿¹8¬žáÃÊ6?Ü<[ðzJÕ3,üT
|)dGÎÞ:ˆIžÞAgXÊÙ®éÆþX2µñ˜8úqL¤‘öñKšúóëÜXÓ@G�»à5Kè“ê¨9_‰ð«…®›«±F	´ôï¥\	 ÿŸcp„‚e™Ì6'ˆ+|ƒ:/¯ÀÚîóv_ÏíÉ±Ž)�wþáÀ©?{åô€[üv±ø=G€%Í>œ<'ˆ:Ÿóš¦ˆÈ¦àÛùðÅ€¤ê�4“ðÓt
Å¨®ÿo�·E
º8o/ÜqeÔ9‚F/¿‹+Øo ®â¡]CH(£×¤éÆ‘ƒû7‹½ø‡U º¥½Îïù�r¡ÝëV¶ú±~N�<�ˆJÂ’†¤R:–®’ª9íû+šQ•Ì½±B`Ü<¯Èf¬„¸Í5øÍ~¡À5H(:Ú9„�„šÙÆ€þñW,ûÐÔ]Õ1Œÿp
Àòó½<þÛ.M·˜à—[í³‘RõÌ*‘§'ÀdLþlò25n-1g›¢¸ÿ­Á% iúåÇB„G'þ¡À)?|nE(¼­˜¹¿´Éƒ59¦¾¦H¨ˆH¥9¥êˆ+F�ÙïtÕ7zÚ÷×©ù+§Ù¸œåû3 K8–K(Æyé�aˆÊ¼‚°#4EŽ`fPÌ±ÍÀ}Û2	Dšnì¾ë¦%váÁõ›6‹ÌyŸZÔwh_jœ+xõº®µ €¡H�ùû3‚« X–ëQ’ÑA—7Ðçóˆ½„»�ñÕÇ?„Øpýý¡š9s¿É0ÌWí^o¹pÆ‚šœÕÎ‰à[+}¬„+ é’¦gÓ0L—@Ö)4ƒBÕ�LP5`%ñ,G rÅk,`¡”"h¹G-¢pJÃïßìË(·XJýÚãŸ]õ��?ÝÒK©TM{Ç«´TlÙX¯…< Ü¨2¦”FÐCšª¼¡ËÉíõ[i_×+Ç8ˆ±ã]¯ Ò$ß/ìØý�‹Ã¦y!,möe¶•|Í�é;ZM§N©�4Šdº`g²a��…‡gr”Q¶°Ô¸ù× ÁË£Á7*�ïô'ðøÞ°ußöïÛ€åD×¬j�7ë	:Ú�Pc»¦*oð÷„ßÍ?sÌRpŽw­X¿i³XÅµÿi·ês8af ›:B™‡ÜòñâªíñŠ™øvˆËd�"&kÐ)ªºÂW~��_ä rÄV ¦kQë.Œäó~{�a	á„„¡¡¡ª�cþê_	5¶SÃx8àÿ¦ýáæg�e.Ç»R”òõ["ÎYT›óG%	µh(/œÒJ
°eæGåâ
Â.ãnªaE6a?‘Aƒ/—Ì¶Â)¿y£=C$ñ²ŸéxE^vô~
<%}ß:§KHr�ªÜ3JiÔPåûkÞ»�)ƒB¼ëÀy¿ÞzãŽ|†Ÿ#ÀÆŽNœÊlK©:úb
$–.*kHÈ¥Mö¸¬•úlLG ˜¡=Ž >‘+ªD– Ù/ä¸3ƒBÆ:xl÷0ž~»’¬d^o¯ñ èá9]Ü‹¢8–�O0÷�+")1YÇ@BEXÒNH§4GÇÊ†¥”pÿ­;ÿç’ç§úÞO¼kÀ†ëïfÍùÏ±Wä¿ÖráÜ%uv¿”Ÿ_nÅW41YÏ˜÷N1ÝÜ Ù‰=ê½<Î&`£æÕ¹ pz¢2~ýü^´´5Ô¡ÎËW”�˜�R‰K$UG_BCOTF_$itÇuFÓœ+B�ír<|g�¡üê™D|W(€´ÉÿÇ|¢ÏnÕ/fî—üJVûb(fÈª=…šˆ"ž’AÔÉÌ¿W¥DÎ¾¼Ë \.x!PÁw b�)†l`ÁêN”�|%à´×¸ hvõ'Ç|_
>ßÍUüÕ è�)8‘qd ‚ž¤3‹Ë²
‚.ö²ÒQ¯ ÎûõÖË\÷Ãüâ�/�Ž«ÏøúÅV}Í00’*^´‘tŒ$•ŠVûbHÄ"ˆŽc¤¿R¸ƒ±”èŒ<!/B¬iBSC=¼¡:„ZÚá	Ô”?'Åþº]ƒZŸÉ7°àX4û…Ìß3ƒt
tŽH(‡låªeÝP.¦ä’cþ�qÅÀ¾¡ÆŒÎ°ìè€,!OÄûÝø�äÕ
à‚Û·}×Žå_ÚäÁyKê3+UJÕÑUrV}+œgÃ×tŠˆ¤UlæçÃøD4ŒÃýÃP#�ú'/BÅ¸¼hm›ÿÌ…¨ŸÙak%S €iA5úÅ%Pïát›î”È™=¬è‰ÕÐ$¥QÈšÍ Mw|ýâh¨R`8–”­g(‡¸b`÷@o÷Dq,!OxEæ;OaõãòÅL#•
`Ãõ÷‡::þ7?�Ÿ#ÀY‹ê°ªÍŸÙÖ•VýRßPB³à«ŠŒ�á’ƒ]8Ü?C.4‹“]{@õÊ	¬ñ‚°Úfw eÁr[FCõ¥€uOí”À¬�˜£`‡*ªUÙr•6ÿEŽÀ'rf£Ô¬š§è‰*ØÑ—ÀÞÁ$ÊqÿÁQ§ :>wóÜãÖžò‡ü_ÈÅáâå“ßŽá/eî�ÕÔWƒ½ÝéïEÏÀ`Ùý•È ÔÈÀ”ÞCÎÂ‚«Ñ4yÙæ €é4ú„œmÙ®Àî�ä¸ x–�·Â.ê"GàâXø]\E®ƒ¤êx«?åÈ*`	yÂM”¯¾9‚£J´žÿ•uKO9û/¾†¶n­ZÖ�Ia�Jº£JÎ{­VÙùˆË†SzE°ªS |dŸ#¡Ï†¡iHuï™ê[	 àƒ˜¿t%‚s––Ý×Ž´¬€½åãÿNàY°d|�¤_4;UB$îêObkOýÑ2<†®}ÛüŸwSÔà¨Q /žô¾ÿyð�|á_×ÀûÔfþÎ7ù5ÃÀ@\-0÷ÍÀ`R«ˆÕOÄ"èîîÁáCAuÕñûò‘ìÙªN�|”Ä¡˜µj=:Þ™QnˆI³/7DøDû†Rã>– ~±rö¿ü"‹:ç˜;80œÂË‡£%¥4ÊRýÊW¿ºþ®ªžìáèP „|xÓ·îÿmhFGfG€óŽ«Çª6?T�BÓ‰È9&±U(�PâÝ½ýcZí‹A�‡¡÷LáEâÐ €«yÖ^òEðþâ‘ƒ|W€cLËàp¤P™Y„«jPèEB«lVGc�ÀVlþ;Ç2ºL«À	gp`8…ç÷—tÞ-nÁ´W „å>µéßî¾5ÛLuq.]ÙˆÅ @DÒp(,gºbR5Ð“ùùªN1Øu»öî·%óÆƒéäX
  Ä`=V}øjøêš‹îŸop0œÔ i$Í¬lKÖcÐÅ‚#€È³9ÅKãu	
?‡C�›ud¼Õ—ÀK†m¯‡ã8øx€eØ¯¥~ÿÃ­)ÆÓ[ríi7üî{ÙÂrqøØ	ÍhIPICwLÉtç)fò÷ÇÄ4çP·™_©þÎªÄÿÇ}½¦‚cD9	¡¶k7¢Çc»>Ð–ÊöJ(ž¡ðöæ¿¥<<7ÏB¬ÒP§î�jP¼t(Š7�„GÏ‰ãrJ¦ãÉÔv/«_~4ZÓV–¿aý?ßz}Ãâ2Û¼<>vB3êÓ)½ƒI5Ó™Æ0(FRZN§Àùª?Y‚Ÿù¼iâd[ Z®Äq}ÉvŽ ­A ³QÉÎ*d zxÆñ0«n¡Z.ƒ[`Ñä-¯Â)Ïì4:Ã2ãw‹¯³ÐÁ2ì×ÿìªïŒû¤&ÓR–¿aí—x}ëª™m­ŸZÓ’ùÒ{b
†“*†d„?¿\×‰¯o™ú;wížÁÏF¢sç¤~^6¨aZLRÿÁLÙ-ÕÔŒ»³âÂÏ#[ùf£5`æôÇôÅÇÏ‚®±%ød1�×2pjôD<{`)Õ~EIJÊžpÏÅGK¤`Ú) Âò7œð™o]?óÄ³3ÛÚC.|ì„fxyŠAÑS2	,†AÑŸP!§É?M7�PtôÆÕ²¡½žÎâã;…<Ü-žÔÏ¤†CMMF¢º]N‚=Xÿéëm#Í>:ö•Oÿ-‡Ræ%pqB.vÜ‘„ ‹C½Ï¾˜)àâÀ³IÅÀcï�~hæ‰~éÑ�I86Õ;A ,ÃÒ‹¿|ýœM—d¶Í­uá“kZàæ
…_Õ)úb2²9š„¢£§ŒðaÏëÇ¡#Ý“¾êç\/a %"“òYÔ0`(IªÐÑ{CX¬èçöƒ=`xÁÈ	xƒuÄÛÐZx,tG%tüë‡‹cÁŽ£rÐ‚fPÄQIƒf .ž3QÖŒ$5p�+K÷¹y6ó7Ï,¨w£ÎËãHDB~.Cˆ„¹|ÁyŸKíÿË-/Œûâ&ÓGríâÓÿé¿~èË™MóëÜøØê�bPtŽH™Ìµ¤b /®ÂÈ2bâ2†S:B@)E¾‘¦*2ìÜŽÝ;ßBR™ütÜ|0œ`Z tb{šCN>¨ç�uyÀð‚ù#¸Àº¼`<A†„ÐœãFïŸnæ÷G$£*Â ž*þä\+ I30’Ò`ÐôÀ”1(˜¸b–|»9~_pž„Ô{y,lð /®ÚÌ:ÅéË?ô…¹�±Ô#�¶NËöÐÓÃ äÃ­+Nþíš/ÿ(crÎ­uáãyÂo1ûQIÃH*g@zc
d=?Ùg´¥§óÀ”øùå0‘©ÁÅÌ}Îë	€duæ<SðEOÎ6c[Î{}ÁZTÕ2ÿË!äâPëáÆR9‚9µnÔ¸90E‰aP¼x(Š—:£¶¯Ç“©íû�éØ«pê aÎt¬|ää¯þ"zj¹ðéµÎ„?¥êè�+(–Ò>8<Œ½[_Á`lüÙj�‰Ê	(&ü|°¬8:ÚŒ°<„`}Žà–‡PÛ&¯'_¨®±è�± ö¿¨TX	D€é´„’ç»o0…Gß²%5ƒ³jbÓtNLê•C–_&Ö¶ü~Ý¿“þfŸêË~Ã J¨9ÂKçüÛ	¿fPŒÛ�Œ`(9õæ~10Â‹ã?Pœ
? ˆµ-9ÂÀVø=^_U…Ÿgè¤
? „%�#’ã,Ðì0cJÕ±o(…¨¤Á(’ÙØQïÆeÇ7£Î[ØÌ”cH­Î{Ÿ<õg¯œ>©]SÆN˜Iuõ¹S¿~k] ÕläÓàåñ©5-ð‹l�ð[a>‘”Š�"‚•4lëÄ`$NÃ‚uû¡'"îk�ýfè©êÔ €¡$…ß_6ÝMÈ‚XÛFpåîh ë*Lry¼à¸ê™ëÕ"ÿ*¾70sC’ªŽe QBA—iT’�˜lŽxó	,ˆ�%!rŽkòb0¡b$/•˜!ÄÍzyÝÆ+öw?öëm“~ñ6˜€ñk©¦þyõç¿Ódeùy;¡AWVøâ2‹ÿÁÁ˜ñú¾n¤¤ÑÌLVô@l¬Z»úªƒuùÆ�4M)~Fp¬òœ'P°�°<8oÀö¸¢X]+e²Wÿ|Hš�î¨Œ�„š™ÄdÁ/²¶Âo!¦80,�É³ç-©Ãê™þ‚×t°ðz½wž~Ëÿ<¥7 �)Q F2rÇâ3>¼ÂŠõ»8&“ág…úŠ	oL±íe¯h:¶ìÅÁ¾Ûkâ<ˆÓS	0&ouÌP_!×Áês? à¼¡Â{d³0C5Á3Ó§9ªå$Ò±d·ÀEµƒjPt†%D‹¸CpÊÜ6Î³/®R|{:(�IW „åo,\û�…ÿôÿ2R|éÊF´ÍÆŠóÛ	ÿ‘°dÛÁ&šHâµ}ÝN(%?›Ô�ó×a:‚óÆ}Cµ~]¡ð{¶C7˜<~À‚ÈUwµæÙé} �ÝQ1Yƒ§Âôâî¨‚¡„Z”8¾Í‡Ž«·}m:(�ÉU „|XÔ\¿áËßƒî;wq]¦ª¯§ˆðkº�#a© Ì¤Mþƒƒ™LÀrp5Îr<rj2ÁûB ìØ}lj¦?a¹3@ ¤Ý„"“xN@51Õæ¿8HÅÁá]’²1�PÑ•K’ƒ-·� Lµ˜4@X~(½eõç¾“©9_×ÀúÙ¦0&Í¼};á/ã/eò—‚«±ÝV0¦¬{ì\€ÝêÏy‚«?ayÛkgÆ8†«RL'ó?¾t
±¤Qì–—+‹Å‡#JQ%0«FÄEKë¦�˜°~Óf‘êÚ]Ïû¬ß*0™[ëÂ9‹Ms<"�VñÅ½¬ð§To,kòay¸[:ªîÛŽcuìV ö«3ŸpÕ%ùŠaº™ÿ€I@çãHÄ4í+AJÕq`X²1 m!WI%pÂ÷ž¿|²¯}RÀóOÞyK`áš‹/øœ˜	—®h„À$TÝ1S�³“|Š	4‘Ä›ûsYþ±€°ü´‹°.ï˜Ü »ÕŸÜ«?P\ÐÇ:ˆ³RL7óß+ï,<�PÑ–sf”ƒjE°Æ ¼^ï�“�'0ñ
€�óÞÀæuŸûŽg8|ôø¦L¸¯'j
rR1r’|ì„¿R¿¦cd€ó•æ‘�b«?[ÄÅ)jŒƒpŠéfþ»8¦l‹°¤¢ãHDªˆp¢Šƒ*eï9å‡Ï­˜¬{0¡
€pÂLPzËÊ+¾™i3uÖ¢ºãoÅúU�æ4ò°#üöt�Éß/>P¡¦yüªŠ…âŠ�EÂPE )Jô· ml®V>¦“ùÏS8�¤QŽÈUU³jD[%`enüé–öÉ¸¦ Ò~ÿoÖœã·âýK›<Ò¯'+Öß5çóW~Í ØÓ=Œ®‘êeÊåC¨m�6‘�JSƒíŠ›ËÙšÿŒàvrÈ	ÁT¤þƒÕH¤¨ºIVÒï°œè¨wãôù…Ç�Ú¨¤ÿeÃõ÷‡&ú^L˜xá™ßþ‹+TòºÍ_`úý.k`’~ÃI5ÓÌCK—–Äåœ8¿fP¼ÝÙ7¡Âoa:Ex¿³Š»¢äo/èÅVùrdh5\®é´úW*üÙè©,B`)�bÑ�å­>¬k/$}÷²d¨å¾‰¾¢ Ë/cþmåÇ®Ï„ü.^Þ /ÏdH?†!Ii™‡+’Rs2ü,á+Ó?†sž6‘�ñ¦3|é¸=ÕÔÜ]…¡g¼«QB=]V;Æ¿R‰(+�R!Âg°¨±pññ¸„÷Mtx°êjyý¦Íbçþ7®?áÌæ¥ç
 °±£kfú¡]5Kàc’–SØ3ÙÂoÁ*Ò¢Õéÿ?öó``¨JÙá!TW, ªk ¬ ªÊÐ¥$ôTZ"->ªëÐ’1è©(´d$ó£§â Ðâ#™=‡.%@U	†œëò‚c	Sù#cšÿSZx
 4ã_)¢²G¥æ3]¬ˆˆ³çÀÁáyõ:ÅésÎùÔß>tëþ‰¸'UWË„åoà\žëÏüÎ_ÀûkÐìãñÅ“f@`zb
Â’U§™Ñ]ÖäÞì5ÂŸ5:yàÐ”}>P¾k05èRZ2šÓÌ0ËyíX}Þ_g›lDX®ÆÒœ“PÛš‰ –‡È0œ ·K,k5MvÝ¿\ã˜ô«3‚BE.EÈÍåŒWÏFTÒp÷ë½ý4ƒPWMDC‘ªÞËô_vÉUàý5àpéÊ&ADÒ2™~é§éúãÓKø�é°K¦†CS Ë	èRòÀaè‰HASÓJCzNL|šå"P]…$+H&âÂ`/â‘a$qh6½ß­Â˜î@%Ä`8¥- 
¸8œ¿Ä>2Wð¿qþU½+ÔÐêí8žÌÞx1 `cG-~Ša†ùòI¿ÞØh3�é"ü¦Cd€uû2B¯%#Ð¥%5öñâEÌw«Ex)P­´;b)„ðP?†††�LÄAuuÊcÿ•„ûÆŠÎ‘Êòº£JÑRâ¶�ëç„
¶OPµ;CXîS ÆÉ'lþ ³³Ï)&h•÷Æ=CúÄåœpßt~î–Ž)‹šÂò¡ÏG1%0–ó%“³ÂÛA—�·T£ºš±"±"’^46‘K¸o¬8©,c°'*½'«gøÐ^ã*Ø®øvµ“„ª¢ O°–êÚ.>ã#°x~hycÆô�¥ý~+Ó/–E f’Ït~“04†¦™ä›&ƒÝEÍyRåæ¦åÜ€±FdÊb$žB×Há„4©Š@t8¸PuŠ#çsTÃäÁì"CpÎ¢:¸ùB×)¡³w­ß´¹j…UQ F2úMÞlšûÁ« ˜U~íA1cúÀPÒü_ÓôgeýŒ“ç+ËÃÕÒ1þ•@¶Ðç›Úœ¯z]xË�C9Tb …ùá”†®‘ú#É	oË^MÆß)$�æÚå�Rõ‚¶a<ƒ3ö®ðyÜË’g}úÆj�ó¸ aùe,Ç]½ì’« z<ð
,Þ¿À|híLÿÞØèêŽH’Þ[m°¢®–yU?n¶àC±¤ MÃŠlŒ¯5½!U¦¨‹YNIÕ@Tš0Eà$Ç¢•´ŠªjQ> £Þ�e-…Q›�Ïõµj¹ã>ª«ÿåjšMÚO¾À €3ÔÀË3ˆHŠžcúgûýQIÃ;Gú«q“Î¨ZdÀ‰à[`8~RRx�œ‹Q�Ò!,_¶Âp"ÁD2þN1�P+Š”j&²±#”3�ÙÍx]"BÁàmÕ8×ñÝ)Âœ	àË.¹
Ç3í!N�[“¹	Ù!¿”ªgü~EÓñÖ¡©ŸŒ[)„ÚÖq·s*øÙ¨´B°JEœ·Y•ð&ÙŠ`<Ád0þNÑuN
ªéè˜x–àýjÁ±Lz6¡ÉkP�UÕˆ
ŒïnQú?�yÇÃšâ{áR3†™Pƒ¸¢C£$'Þ¯»ŽT­¤w²ájœ5&¦ÝZõÇ»F!åXûŠÏÏ¡p;åÆÒ_ ©²°â{4‰Œ¿¨:Íô¹p‚pJ+pƒ‚g–4ypB[¡+àåñßã­» äÃ ]±âbs–ßÒ&æÖš¦ª•è ê"G0’R3ñþ½#Ó–ñwŠJ"•˜ûÅÀp<8‡9	¥&—Š÷SÃp¤Tœð ã�š„SŽ„+‹L'á·�TôŠø€|WÀïâ2dæ©!¸óš³ê„c|n×ŒçÇ® (ý�ÀÂµhX|8œ—Î`êM›üé¹ñ²F!kôÇ•I©ì›h8�š6.ÁÏçåžÃVØb½€t.€ƒPŸ aSMÓ[Õ(ð™($TÇIB–+À3!—Cdz'Ïµq	sÅxº�Mòa +.ü< à„™4ûE¤TIÕ@BÑ‘Ru¨éÿ\ƒ¶šêÁ˜J”ŠTcÕÏç	Œ»kO9wâ¢”«tBþU‚pJ+ÉLE¸¯RtG�=å®cE‹6cÇnñÛc=·±)€¼Õßjî9˜Ì�ùÆÕLnxRÑÁ³3‚X2«µÞê¶šž
Øµ«æª_øyÎÜ€bdÕµ’n€S–_O„‹¾6IS7�)˜Êp_%�4ZÒà¿ÀÀ+š–Œ%?vØ4/T°�‚¬:ï×[/Ë¹U® òVÿg9sÅ×)†“*T�BRuDÒ\@B5�­Àý"‹ùmX0£±êC'&ÙÃF&Rø�Üh 7ÆU––È¨8‘ÍEû£RÆ%˜NŒ¿sÜ<¯È‚Í*—NªFÑ¦í!:êlÂÂ„Œ)9¨ò;Hñ5ß¬ã2«ÿûš‰*ƒIjº§?`¶ü �R¨ºýªSãáqÜ¬–£Þ-p5Îaù	~ %Sƒ³Q*M¸\��R$bæEÜ€ÉH™§4„Ò¤¦ùV½ñÑ{ææY„Ü\Ñ°”ÅpêÜBK�‚Ì‹P™ Ì™ ]±øìÍ Lß?(rˆÈf®8-üá¬N?I¥tö™åßÑzÔºjt| nRzë[©Á´„°i%»û”N¸qª´s&«pJ‹�¸Õ8ºBÉIÅäÈüSÖòUÓš¶C­‡Çr›Arc¥u•Z ßpÕ4¢mõé€LÊoTÒ 4ó¿Eüå›þ¥À³óÛ°dV3Ü®ÉR1^P]…`öÛw5Ì˜ðÏtÒ/°T8¯\‡_Ç<@ž0YS.Ñ\$Rª™w4)�À".k9æ~)ô'Ô¢×·¶½pò0™[{Ù5WrNŽ€9ÚË8yþ—ƒáxfy‹õÞvõJ›þ¥àY,o¯Çì¦c:óTW¡%¢¹÷ˆ!6Ll7g+5x¬ª«¥‰@%å(€êjŽ˜àásI?M7Ð9"Aªp–ßdÃÅ\8†@3€þ
„ìrqE­€JÎÍ± ºv-ËñtöÉ  6u„ ä®þ’:šøPÎô/‡¦ ‡™®ü€�ð[`]>µ­úùXÌä.™¤k%‰@Ày¶Ÿ•TíÐŸí5sØ"ŸÑ‘§¥àYSð.—¯LjÐ.ŽCÉÊ­€J¸ G
€ñkzaûúóï¯A{È…¹µîóo%ý¥{Ê:ulú—»�3‚X6§eÚð¥„ßçU<à£8™!XÊ×/Gê«þ´¤y&zõç8î2¤ßtR<KàØ’çÜ—p^üTÊ
XbÓM„\ãôØŽ€‘Š~€nºÕ—ÅBZÌJÕ!©:b²�šWžÉ„§’p"ü„ÚVÛ1ÜÕ€•\jÕÕKX†Z†¨ èGKD'|õ/'üº"SOZ‚Ï•ÉOÈ&ÊË¡”°Æf¦ Yå´\Ø™@éç½móœ³^�Å	3™ÕßÒNÖê/M`‘O�‡ŸR~À©ð[fMXd€ó…Jæ”$ÕTÙ>€N¯u¢CŸ~we÷oªˆÁl?ß)âÎï]1+ ÁËc–Mû°` àÈ
(« ^<	@ÇÜ“Ï ¼7íwDò|kõñW)¦‚°ÌÝJ1Q‘Î Jô	7PAó'¹c�ÅøWM7*¬ñ¢˜ŸïQÙplë$ ï±©da\æ¤R°¬0TåÓ `‘'Î0³•bé“²ü™ñ• “?0»~Âù«÷þX0‘‘¾Lo‚’õÿeâýN¢V£’±*ÇRÈgü+�"¬¼¤¸âs,ãç;A©´ßl¨-šØQçFÈ�Ò	Çpœpi¹ã–T ù×ºòðþÌ¯s£ÞÃgrþGRæêŸRÌÕ
¿‚Ä	M+Öåä¸kï'*2ÀùjJ&ß”äLü-°fR¼ªý	<<S”ñwŠ”Z\`Æ‹±˜ûÅNU(‘x|k¡àØÏ–;fI@åÄ… üm'~ €9Ã0ÍëæZ¾ÿd®þv¨ñðX9·³›jªæƒP]…Qa#Ìbà¼!ðÁ†ª^3+ºÁy‹•ä”TÙ¤­DÑO~›2-©Î}*î«C	µ¢~å`	þXÌý’ç™tvŽªAs†çfÃn¶ ™[®T¸´0Œ+XŽ§�+N…‹cp\“‘ôÍ÷ý§bõ·CSÐÃßÑ:n~ Æß)ø@CÕ#B¨©èkå|órn€© í�‘?i¸T… S8	÷UŠ¾¸:nRÐ
ëU[ð-Tb©D${àX,l(ä„ü.¡dN@Q@8a&Ë²ëk�?=,mòÂÍ³H)zA³Ï©^ýóQ�²ãJ[`;Eµ#e­Š!=]N”�¨ñpÁ¶bMJõqZÕ~ã!�†õÆÍ(Îòç#*kEÚqM…‹ã²RõE ÕÕKtM%³ßcöû[•f“ªaNz1("’6­Vÿ|XeÇ•†«á÷—‚«aFÕ” Ãñj[Š¾®Jã‹Ø‘�L]�ŒýžŒ�ñwŠ±ðÕôó� ’ÖaÅÜ€Ž:·mÛ°Rõ%\ r~¶ù¿¬Ù—“øci¬é¶úÛ¡’°a5ýþb œ¡¦iüJ£œP* 'ce�ŸÍ”kQ>+`<Œ¿S%TG™‚åç—ƒ¬Óª„í¸ �c>Xl[Àx‚µ,Ë®oZzbÆüÌÖÞ–ö‰HÓË÷/§eÇeúç£š‘�rn@©h€.ÅÊ'e…A™2]¥V@5§N�|L´ŸïNC‚IÕ(ê,i*\ä4M»`Ãõ÷‡ìö·U TN\¨k*i^µ€iþ[™QIC\1 éÆ„fýMJ•O´éŸ�jEÊ¹e:ˆãk‰°ã%N­€j2þNPÌ˜?ß	*‰XÄŠX­~1W‰é„c‚³æ|Àn{ kç@ýò“Á`^�‰´ÖQuŠHJ�´¬¿‰B~Ùñd˜þvàU)*eM”s´d¤¬P‰e¤FÊ*�‰`ü�`(«Æ~²ýür¨„)±ß¼ºÂÔ`
Ø†@š1Üàm›_]3æ7¤ÙU7§ü1Y?*W;Xü@]`b
wœ@¨m7)(Ö4•L
Ò¥WårV +º¡Å†ŸO¹¼€©~	EŸ?ß	œZªA‹º
Ÿ·À�c·o�xþ©»6ð·/] XÜ8ZöWt$d“0Œ£wõ·ƒ×ÄÌŽùà¼åKm'ã�šZ2)h<V€Uî«K‰Š:³&’ñ/Žeàæ	T½ú«ÕBT6gsZbA4 ¥uvIA…. ¥§@pÉI €¥Í¾ó$¥V­ÞºÀòy–E{[+šÚçÀãšÜ‡t¬-Åt9-…¡¤JFÌ}K'³XqÔ÷WFúŸ›jc1¸DaJZy»ybFÒ³õFnS�˜âLÄ‹Dàx† Ý¦B0äßŸ¿ÍŽ8 æ-GÈÅ¡ÞÃgÌI5Ç|+ÚôÔžcAR5
†Nx]"šÛç¢©¥eÂkÝ³QIá�%øÙÃ>ÑSº6 Œ %#9+<5Œâ�jrEƒ²­€É÷åÃÍ“œ¡šRÚôµœº¥¢µ…
À ¦lg#G0ž`-ËqË½móÁûk21EËü·4Ó»iõO”Ècðúƒ˜1k6|µõ“v>¬ËW22`hj�à[ S6¿ \åžÉüÎð¢mØÏj„êÊH/€É÷(˜¦k‡éjXS´� Øó;»¶0bCAVå‡s€‘Š­Ñ5•Xþÿ‚z·Ùô3mþÇeò»HúíVÿ|ð,‹ÆúzÌž5kÒø»È€%øåºõðÁÆ’¯ë‰Hé2a%•Yá³MÿlPMv¬¨&ƒ×S“*ü–¹_ÓÙ
°¸¶rHq¼[P" ¤©muöß¹w)íÿûæ®`j+÷ÿÝhþ'*ÈbdD·ÉL’[�ÝRÌÐTÇmºÊå å¹ ->\6æ¯%ÂŽ	AIžœiÐÅÌýR˜®V@Ä¡(¥ÀæÔ’Êù<@¾š< jŸñÿUƒ"©ˆ)ÆQ•ùWªN+?mÁëbÎÜ'¶ó/ 5Í04Õñ°ŽÌûj[�Ó�ÊY€³!NÂ‚ŒËCS!ÙUc|©iº¨¥.N¥Â�3Båy€ŒX¿i³ÈrÜrÞ„¯®í5®Lø/¥êˆË¦IÓÕª`¼uâõ¡ fvÌŸP~@—S‚ Leó[XÑ6Pú¼Jå0¼z2Zv…×¥DIN�qù2ó’‰ô*gY:ñó� ,M? ëÔq8°˜%;3Xh0T_‘]˜y²þþÜ='èšJæ›ÍDçÕ¹ ¤¨}×™ÿ©*$2YüÀD„µDTWA8b“Þî¦9%­ CNÚ–
3‚;£pœäõ«‘[E‘-ü™}+´dJ^ŸC?ß	b²mNr,ÅØ¥3ç}j‘õwæš² üí‹˜SHSŠY3�˜fM?Æ‹˜CÿÊ)ª6´„ß#zÀÊ¦ëfƒuûÀ”'.Gs\Âr`¸QEFuÍ¶@>òó'ÚN.ª†0s¿¦cUkRuö}—âZ…SR#Ë­ßGU(Å2 ´u  ZüTƒBÒL+àÝdþOÔ 	‹�[�/ü8o ¼/TÑ±<m2Ó{ŠÞ¨+Àð…ÄŸžŒ–�ûk‰pfÂ‰`Äâb<î¼Ûp6&Jð3çUÅÖaÕB5x€¶À¨0°íY¼ô“«ÿàzøÖ{­mÙjz% øg.Dƒ—‡›g¡êŠ™$ëïó¬ä_%h¬¯GMMzzû*j+¦Kq[á·À*Š°n¸`#Œd(2½Çt<`�E¹->R4$˜¹¯Ñ!°3J
?`F I„àr6I˜c™ª™ú¥`‘�Ó©>ÀâœU4¼Pxî!7‡Þ—ÁÛÞŠD×ÞïôÚlÇŽF	@ 4·M>>Sû/¥Í‹w‹ù?Yã£*M+¦šìH°…`CE£¸¼³—AO•núQªk`ºJ™¸?ÕdÇaÁdÂ™PM?ß	œúÜ“	§EwrÞs�EñûßÞ…½p-^¿õ›4Ñ½÷« ½6ÿ} ¼ðÌoP]%ÞÆ™`8ž™2	@Õ ™ðß»“=?ÎëámŸ‹D,‚þ�AÛªÉŽ{ë[¤ 4Ðéh†ãái[€TßA0®ÂfŒèáxèÑþ’V€žŒAãø¢s	Y—z2
Öå+kš
EJµÜ<™0S¿ŠŽ:Ïä%,9='¯Xþ^XŠ"‹â¡_ý ÿ{÷o �ô§_%? èMvïc €ÚR ¶ÎP>ð‰fE4ùx„\x‡óÍ§&Ãü/†RiÅ•v!ª42 ¶.€Gí¢i©i*t©¸¥@ZÜ>ù‡uy3V‰uÖ()ØV­°ÞX¡êtÚE‡¡À”ªãÅîÂ•ÿt6~ñó›é¨ð ½À^r­9ëc Ëß@uõúÅg|‹?úüÛûf ö¥°µ;Ÿhß¼!¥êP4)�BÖt$}Z»
1Y¯z`,Pu=ÃèR¼¢aœÙÐQÇghZOø¥?¶°5£	L¬Mù0ï¯+ï�@XbÝè1'ð| ¬ƒ&'¯._Ë€gè”	~6¼<.nüª8¦°¾ß*¨âY’ÞÇ\�—µŒ~oC	ÑîèéïÇ›o¿ƒ÷BMÅ¡�ô á®ÿåìS/þÙ³W�¼• ªk³ÀÝ: Pïáq8"!¥êÐ))ZÁåæÍVJÙ�‘¦H©ƒšaDÝ$W¦ƒbÐ¦I#‹HÄ¼è>°gÌÇá¼Gî5†iZ¼¤t®c}µ¶Â jl„åsÂ�9ÇJ‡y_ÈVø“´ËÈ‡$+¨©!ÓÊ¢ŒËÚ´Q °Ä”¿|a·CJÑáN�u^uó`ÎüpÏ^�è;9×gRŠVàCÖ•® !Ôoú ªN“4°„‚«àâX~kÿ,JÓ$ŠnDL¨Æ¤·«FòO5¡î–yPcCf-½ò¹“È€å×{Ú—ÎÙúÔs�µ'—:¦)ÉDÁº¼J¬òjd dM+z@Xñ”‚Ÿ³^ƒ“�©zF,açX,1Ï�ÉºÿœƒlPÕ °»“v¼†‹cZ�L � ž†hòñ™ƒI…P%íÌ±‚n>3B.,lð`i³unÌŠ¨÷šÍÙ	*Ÿ*ß¿øùèH¤Ì�¼¿î–Ž¢[9ˆu­Ž"Çµ´ŸåÎèî-}¥zöiš
-1R2ñH—%–!'m§1ÎÌœo"%CÕ§Þ-ËÆD†¼9Y¯ÀÂ+°ˆBnÎt³<KÀ0LŽðK+‹%ÙU*æ›çã	ÖÉˆ ¼ÁZÔºùQß^5 pkžM–1Ùì9ÄS¹r„å!6Ì¯$!uWÌˆµ-�‡{ÊZºAÎ%,w]bßë·z;Ž/š¹hUrÞšK€ð"¨¡C‰–$#µd4ã
0Âò¶ŠjºY’F!ØxŠ¦#,é�4³ŒÜ�SPSQˆ‚�gôûðšþºµ¢È¬êŒí*^~ÅÓ¨³UQ)òŒ\x†ä$‰S·áúûC•“m Àr<åý5¤ÆÍB1(dÍ€¤é¨á'?,RÊ�H©æyUêFLÿÈ]ýóÁ¸[æAéuLð&›/ë!÷”Ü�á¸–™ç~auçý?ù¾tø­kÜsVÝW—“`W)HøÑ4_]NBK„‹v5¦š
->Wã¬’J"%Ãç¦	˜‹…e‹iERÑÑ•0œ7ÄS•d¨±8 +¯¡nŽ % bÁüy<}çÆ|>fªoy9,51àâ
æÐšºY5ô6 pÕ6 ¨ñ™@:%ùÿŽeàwqcr#¦“û¯¨åÓN…šfxf,rÜ‹­(ÊðŸi=ÿË÷IáÁç”#;Kî«Æ†33³…?s-Ñ¡¢VG%uùÑTÂ²£’†þ˜Œ¸¬9VN‰x;wíÆƒ�<†×wìªŠë©9<F©Ï
ˆ…rÌ®F†0Ì `ÓNÐÅBÓ$U#Ã<Nw¸yA7�f¿€Y5n,nòaQƒ³B.´DøEŒœp¤$gÃ*	ËÃÝ2¯¢	Bœ7àˆK`ö;ŒÛA¢ÿð>¥ï@É}ÕØ0Ãeõó­Âñ`=�ŒòrÒ=h:qªNÑWrêx–@ å­H+"C5;wíÆÿ=ú4’69•@q˜›PJøÄÂï.àš€Ì  ŸÏÌó
,’ªÉÔO'¡©–µPçá1´ûUxâ]XÕêÅ’F:êÜh¹¹IWrª®CrXåe�÷×UdðÁ†²ûBNn9õÒK	Ë0Ñµ'VJ	po¶/ÒDÄÐTh‰0Ç›�Ió>ÛÌu(�nL�À³nÎüñ‹,¼<:êÜ.#GP–£šZ�é©'£¸ïþqpïî1Ÿ£aÐV‚S~¡ðÜSªÑÊQ]ó€2- Ï ©H©ú„€“…®¯ fÏ[· ¸‘ËŒªºYñ˜Ru$U#3þ|"0Ö‡Ü²œrb]ky2‘s]wÊu÷-yæß/¼Dê;ø0 "4Í)Ø�²< kP#ýE­]NA`ù¢V‚€Ø0«ä9'Rò„‘�™8:I“rEr[j=XBÐt¡;"å¼æu‰èÝ¿Ñ=¯Aê;�©¤jšà�¹ØöÞX•’O>ù>àõ¡±¥­âsgªNáD5Ý°uW\6‰|^‘mà Ô€K4ÓÝ‹ˆlF¼Âô eÆ‹½/>ÉU‹÷~ä‹¶¯ó,AÈÍe”‚aÐ)ABÑÍYˆ²Vµøðxëá…šfpÞ ¤þÎ²Œ¿l(`8®åÀÖ'¿j|V×éG¥¾ƒ¿Až`³ÚŒÓ´Èn<Êp|Ž©_¬+±ÙÔ4®L�‚„$Ãëß”$ž%eÝu>ÃÜ‹,A½—Ç`B…F�Ã/>œ®¨+ž¸Å{ƒ·ÁåAXºœÊIó~èáGðO}ž`Í¸®¯ŠåØeòr™Ë ´ Ñ E3 èÆ´" Ç
%6Œý»v oÇ‹Ôi}5Ã0¥Ð^ãÂ’fVµz±°Ám;|±TjþÛžŸàq”7à¤fÀ$¿²”þN×µÿ—èÚËàlH<C‘ ÅGÀp<Ø<s¿\Z³]^@>œò#@¡ùn)q¯ÀBäÙŠ„ß/0óÜA¿ÈAÐ“xéû_À+?ÿç’Â j"‚�—Â¡ßý’=ûrÆª¦}êo��iª–:Î�`/Ë Á3Z)&O³˜ùxðêßŸ èšJúw½2æã0ŸÈ™!žÏ˜B5I.+o AH8¾ld€aØï  (½‰°ü�– EBwTWÍ¨€�¹_ª�˜¡©¶Ó‚²!©FÁ}âY’v;A¯TØóÁ33‚…4cC½øÓ7?Šî7Ÿ­èxj"‚®©ÿ`Á}ëê<ˆÃ;^®ø�ö,æºÚYó.Žie@i  x·®´“!iÅ’Ž>~ëÕÌï{þþhÕŽ[L!4xù‚¹lœ„ÿ*…•EX*ÎÎy%• !ää¶³?û  ºzƒ¥R�oå^³àëöƒ°<Ôè íjohjÉnÁå:Ž‡¢j‚>–UÝ)fÔ¸Y4ûG•¹N)þú_Ÿ-»ê—ÂÐÿG-…¨ËI(á~hñaüý™§*¶œ&³ìëyˆ‡hfé·@JÕ�ê@6Þxî‰ÌïÝo�Ý(K!X.ÃòfÕ¸rÈFe‚,+'.AÙð çºÎšCuõ€|?Ñµ©}¯�°\Fð³¡F‡m#¥úZ\ `
;áxð.wæ‡ã8ÄULˆ C�Û¼.GPçáÐì°íÿnÁþ];Æu\]SÉÈ+†2Ò5ÒŸábF"tî»bì¢]ŠAÛ >À¬éæYÅ �T9ú5@Oç~$úgþÞ¿kÇ¸c²NÁ§I¤Ž:7VµzÑQç†G‹Â5An2©Ä%VúRáÁ!˜½–°ü�‰þÃH¾³Åö=ÔÐŠšü–Àp|æ‡uùÀº| º–vŽ³�„S“Ó£¯ÎÃÃ•·ÚÉ0žº÷—U9¾4Ò_à
 À[Û¶Vtœñf²«èe dh^KIHw”$•Â®—Ÿ)ØvxÛß'ý<†A@d�|þ7XÛÑ„U³0«ÞgL„2jšK-ÕR,CZ[î@ÿaÄw<mM04jlØ¼Î,a74¬ËgvNÿdŽ«©PÊôJtÚw¼°Ë�{áÑ –¤Z	¤Ãolë:¸oLd`9³2‹úËñÀŠ7˜’ÎÕÆÛ/=U°íÍ-/LÉ¹Þñ2Þxéy f^öìz?3QÊ€ó‹òå"B0�l%Ýö¤9«€1Û‡³¢''L˜/ìZ	Ö¿\ƒ˜¤BŸ„î<-~.žÍi¼i÷Ü8ÅG/»O?ý4^yå|ñKW0­ ªk™C‘ �«ž’DŽ©³µ¿Tƒõ
@ÓìÛöjÁöÎ7žƒa“Nrvíx‰®=PÂ}B£±ò€‹CÀågf×û1”T1Ž¡;ê<V/ õ* ë,%`W8d‚]ßò3kÕÕ@HLéÿ¶=‰Ð{ÎáscõjlØ¬øËZéÕèPéB!M+ê f'»RÖj¢Æ#ä¸ :îÚ>¦c}ô²Ëp÷]weþ>á„  ?ýÉ Îô_´Ð?Ð�Ù˜�;@7(]Ss^Ñtš^Y�éˆðî-¶f\¢ÿ0ûzÆpÄñaï‹�  zß(¾ºÔyxÌo­ÅIš1¿¥^÷øbËÃÕ8ËÖï/Y8Ä¹®ËïJo!_•Fú1ôâaØô1´[ÕKYz²ô
8n€�`äöÓsŽOêSÛ>ûé�§/V×Ð˜ñæØ�eHÁpP¨…ñ.èüâß·}­”N’‘‘£üÆo”ÝŸcÌTÔfÕbMG#ZcWV
±] Xd€á¸–ïßüß/¤•€šˆØ*]NAÏó%&—›™0]Gw¿›À°O³ÃËD�S…oW ãññÆ‚lâ±gës½×Í³9VÁX¹±a–­°‹ä‚£/”V!hA—S Zq—F•Šgjºy‚•€]âŒ«¦qGnýÕ¯
¶Ýrëmæ/,:Ž4ð‰pÉuƒæZ Ó¬kÖ˜“4ôíx1ûjbé À¾m¯Nª²ËNF’FúîÚWñ1,«`mG–¶×£Æ_yÑL1%P,2�Of�¥Â¯=ªæ
x~±R©¶çZ7`¢{ô�$Œ¤4ô'TôDeôÇdÌ^´lLÇúÍÝwã²Ë/Ç3Ï<ƒW_}W~ùüô'?  ˆ3ÁêÀy`E8ŽGcÃØÍXP,C�Ñ55˜Àtë›7VìyóEäp„ÜBnÌÜŒDdLé˜c…Åþ[è~ù‰1ÉD�‡Çò¶VÍn¨XØ)«›P>²3�N–Fú1òÊŸct¥Î_õKùúF™™Qibózb
$UÏIµ]²nã˜�÷›»ïÆ©§žŠÕ«Wg„ßUÓÂr™Fp�¯›—?8æÏ©4ƒ1 2NÚDS�¼”ß}ë7^qóú�WÜ�Lö…U"<ÑèïéÊN'Ý”vO*AÀÅeA%<��(J
r®ë²çÉg#�1x‡4Ò�È¶'s”@v6 ¡icv&ú™ŒÊ…–àIgœÞ[=átÍ<®`[ÛìŽ	‰D+á/–HÄ ÝÐLMÅ!«füÑž˜“òKÈ¿>ÿäòóOÞ!–»Üâ<ª%„å�E8þ…pÂF ±¾/Òjvž¸8Ìo­­È"°Sœ7PÀ0×rÀåúd±ã¬ßtÅgA˜ç]{ßÿff»!'s­€+}©f!šnLh>ÀPR-˜¿ÇxBØxÉgªr|WM#\�³¶·|EEÇoT®˜"e  %ŸV}óÆ
«ü @˜ç@éï¬×¨®n×5í **Ò¬ŒpÂ¨¦!7êšJvo/¨‹`f5®òJ\l(
ÁÊ¬€çŸ¼CfÜþ ì‹îÞuà�ùÃæZ%¢åF£Mô4§‘”IÎIÅPRCoLÁò}s-×qYŽ§5«Ï…PÓ>Ø˜áYj‚A´Ï�?¡×”;÷^`HB¢ ÀÈ&G–˜¡˜HXå¿,ÇSÂ°@Öoºâ öéšJ:·üÕÑ1Ã@JÑ—5„SÓ„QOTFçˆ„}C)¼3�Ä;I¼ÝÇÛ½qlë1Ž¼òË]C5Å,J ô&æ¹#¯=…Î°„îˆùÓWÐW0”T1”T•´t{v½âyu¯Ëg;‹äwìµË,gÉÈ0Ã‹›YŽ§Ã¯?F-¿ÞPåŒPJÈË±ãÝ+ðHDÁHJGoLÉ(–œù�[àm» Ö�ô!Â§*+z „ÁùjñÞ+6ÿ9âì(-°· h’5"  Éæ%kÆQ]`¥úêšv'ÕÕ‚”®çŸ¼Ca®FÙyKÀÃ)³lOTÎõÛ½qìèKbÏP
û‡%Sh£2**Â’fŽQ×Hš�Žv ŽØ5{ŽêZN|ˆ0ì{Þ6Ýkëý	ÅË–4$TôÆUtGåŒ²ÈVåCkÐ…÷ÌiÄ¬z_Ñ�‡™'�›6ÌˆžÂhçº®Ôgªü‚Añïº¦’ØÎç3|@vrÐØy€‰}UƒâH^û/ ð×5ãƒßúZWžRÑñxomç}¹Àô',�¶öÙ˜¹tMÅçÈ:tŠõ¸´[Ø%Íèæ 2PÈa3t?Ê-€Î7ž€ã	\ccŸ©ñW€ÜñÆKÏon½À™ëchª‘Œ1zt‰ð”pfØ¢$Ë�Ãˆ§dRTS '#�Fúc„å¿Hóª«Ûc¶ßøçÏŸt=+ˆ`yÄ ãòÁç!† êá­k6Çµ…êà©oü5Ðò¾Ž "ÏÂÃ3àY\Þ
À1³ëýL­Ï�ƒ½ƒ‘
/ÖÌlGªg4<ÉyC9ÂËp\ËÂ«o¿p÷>öÇb÷è¤ùïçŸ¼ó‚D×žž¶àëf@OÅ3ÊD��õlKˆ	ÇƒêöåÊq™ Ì�F)²òìB>ËOK)qL1 p4§+PLÖ °¬»ægcn	¦F2Ê•°6žvú˜È¿ñæ$•"EB †  73¸ŽæP`¦ü—��dd¸Ô¾Œ'pM¢kÏ™áÁÞ&_]3M5¢½�Lrà=û¡�ô ÒwÑ‘!hÑH#ýk„å¿og… –°Üq™š@GööR¹q¼×,ò©›1¾æÙÍY†À¬%Ð<žŒ†wqLú‡@àF»À\–ÏnÆÁÁ˜qh0^p-Œà�PÛ
e¸Û<÷t'¡ì˜~âà¶« U iëêë ô‘ð[Ï£víy Ò‚7t9FôØ¾×�â@‘~rž†Î~Fsœb5»(PºOàPRE“Ïì(ëƒ	5óÞ9ï=ÍkÎÂ¾·K7Íæ:XÑê	dÜŸsÎ>kBûÅ…]V¥fÐýa¹ÕUè)“p:‡lº &i�4QÙÀ³�=¤Ã~Ï?yGÉ÷ÉÈ0¹ú…ï}þ·P%$ú—p–ã©®©ý éèaÓzÂº	ÃF¨¡'Nè¤†€“6|ä�bçñü“wÈ æYäÚß_ºßK•””†ÃMõ†™A=ŠV€.PÑ™êÞ×›£{_Ïé¼ém›�ÆùËQ¿x-j_]3 €#*|"�Àf,Ëx§/Z0�ˆ÷×Á�â™•ŸórúüBNN�’+®\©ñWæ9599ÕõÜmLÁÜ%] Ã0–ÉA–²È=KIØ)‡á¤9¸ÛÆ%HH2|3Á7s‘yL)•ÓâŒj*”<²Ó*†ÚpÒº1uLÕiûúbÑ;¹NÈú !,÷)ªk·òÞ ÎýùX×nja».¢S	«ew\Ö�TtÄ£À¯yéû_@÷Öç>’Íü;ÀŸ| Èø~ ;òºt3œÐI)í<é”÷§wJÁx‚µP¥ÅÔÐS]_BVƒ+˜3ÛæcÆ{6aÆ{6"8Çd²]ƒ�‹ÍXšAq wÄ¶ò0Õ³7#ô†œÌ©4¤ø³+mA˜3A�GxoµkÏa8ˆõm`8¾dCwKGÑ×jC�qw®~‘Í‰�kè�$¡ÐQËW   wç�š¬'€óNZ9î•QƒÇÑ~ËZ¼¶ÛÚ9„í½‰œm‘¤r9Gã`fÇšj$UƒñLP×'°ÆˆÇd	Õ@2Í¾óÓ-Ó=vx7º·>ÿ\…ÂÂ	_ ºöSÂro�˜#àH¦‘Nu-gULÒ+ðé ]¼EX~@×&ºö®ßÝµçÌÝÞÒämœ‰ëÎFÛº³!Íè GTÔxøL�A0 `ç‘Ü‡ØÕ8É#»  3è#cˆÞK”V Ôø+€}j"ÒaÄ‡ÁøjÍ:ø2×EuÕÑ”ãÉ@­‡Ï<{€iId1pž ÔèÇcÑ¼¹X¶xá¸‡ÏýÿRŸ“=åÈBTRúaùeTW·ÀûðV-˜ƒf¿0)åÀ1IC"=ˆ#¥šB_jŠo|¨ÑÎÝHôìGïþ]Hv½©ï Õ5•°OŠÅ|îD˜
¢ºv@Wæ�…§_Š¶Õ§Ï3–"H©:¶uæ´,WcC>€j*¤�ÎÌks—�\óÌ�„Ë|úM ½Æ7ë8x;Ž¨ëò–e.Ô¶ä4ÉÆd[ uf~Déá …@öpP»q\c�‡gÐr•ßO`2ç��[·ô=Ô;¸’#¢§‹¦ÙòTÿÄfÍD³_¨êÍtb¾gCN&=ô6½0r`†Ž@ªg_±6MÄ4Ýµ ô˜ðg!­·¸�pÂÌØ�íŸ|åç¯_¶ýžÆŽùg\ŽŽ÷_fx\"Sëá±jV=vÈD	²ù Âñà<�7ÐoB	2 @Èã ôyð¼ÇÃPe°./Æ
E30öw�CÒM[|…ãÁ*ï³ V¢YéñàåáÔ/)°«© #C‡¸´9à—ÂýKc'Çc¾G»ö!Ö¹‘î9�<mÐà•´�þ*a¸'žò‘w¦ƒo>�‘NDºÀRxðÌí÷ÜôÅ=�Þõ�%|í'_`ÔúÜÌ’ö¦^@¨m5{t5',˜:ðú(£ Öo¼ü©Ÿý-Ub(©ÌÊNµâf~±ÙƒÓÇ¢Ñ—-Œn µ¶ûj ¥}H9“Èd€c�™>äT18M*V•´‚D Y3†ž¹ñ‚pÚF!ûºBé+i‚g£Jæ;)1*+Â¼	J÷–}ž0ìNð®�£´é£S]�6¾ùQÓGÿ«Yöúmÿ~íîÇ~»ùø+¾‰™ËÖ`Ns S	–l€2ÜmþLsá—ûˆ´BÞ C�•	”Î4Ÿ“‰™8™(§,¥  £\-€bÜ�]‡e�ÁÀÌ €7¬ˆ÷`fÝ£3&Á|ßàMlÈ[„åÞ¢šrÔT(V3E¨Çùj"í"|,Ù{ð¦çþûcÿÕ°æœ¬ÛüuÌhnAwTï¯ƒ�¡¤ÀûB�‡S º>ÏáGìÐaÈIPÃú.Ç7q20Ù£�QÅ g¥=sŒ–³Ggúþq%¬¾D~C>$ÍèÒ
€°ÜAª«™lÀýÃ ©bó}øÐ®rýÔöa4ÄVh¾SóªMþ˜èd¤Á¹Co<qÒŸ_~ø§ë®¾yÅ’OEwT†X×ŠTÏ>³©%ËƒZÖoÚ,–w»Ì,SCŠƒÓÛ¼ŸŽÐ …¬QÈ™ü¡`Y<cŽL³”‚;=þKÕ)º†aÄ†ÐÓß�7ß~oíDb¨ŒCÂ]ÿËÙ§^ü3 ­ ¨¡í€H·92œGØ™ï‰®=¥Ë|…°ìÎcæûÑC•_X¿ióÚ~|Õ¿ŒìûÄõk>r  ;ŠLV +º¡%Uô,XÝ†'ïØ_æ�C Ž:…>�¦b‰\¡ù¯QM£�­85tˆÁ_~ûküäûßÅ‘Ã�6G"[ApãÜf$#Ã�÷ÿØ¼V  ·ƒê*ý‡1°óU§æ;Ž™ïcÇ†ëïõËÊRCN6ò¡Æ¹Ztp €0™t±èžWnê~àG/u|îæ¹‚Ëó~ƒ0ýZ*þfË;¯tMé™>îï<ôëÿëïÜûËs®úïu)…`8Pg* —Z2ŠTÏžF˜>þQU×1ÔuÑ×Æ‚^9Õ§ãNÝÏ ãÜËðËMçã¡_ý ÿ{÷o²¬qò}€^
ä×Ç H›sHg’Á> ;	Ë¿Fm7a¸éT×c’í­çe]`þêkA��ÃÔ•Û?²û•ž9ñðœ·†�<ÝrúÇstš¶,·�hÊß)ùØ¾_\Yuad<ÁÚºE«oY÷Éë/TDû»¡F�êÙ]×Nì~àG/•>‚™àm›ßÂup5Îï�-BrÞø€ýmq»DÔ‡J�C/…„$£¿ûú½ÉƒÛ°éÛÝ×/²hôU7>V4zyø]åó	¼<|£Ñ9ÃC~ Üò]ôôôP]×þ(½)ÿ}�)â¸Ô¸ @˜wŠ™ï‰sÌ|/�õ›6‹+6žCXîÃïüè“?4Tùõð[×2V_bzOÇ¡Öï†Ï-¢ÖE ¹ÍtÑ “"éŽ´üîß¯Ü²úóß^ÑÒZ�ž¨ŒDÜ¬Ù`8n!€…à…‹D^À¢«oß†ù+á]Øù?—<?¦“Îƒ‘Œ¼þÄÅÙúÌç~ïÏ×K5ÍP£faO*6þ˜$¨ºŽápjd ±=¯€åK'Mæ`Òrp;ÌÊõ¹û‰^?.¼ô2œpÆEøÙ¯ï";¾ã{ñCo·ôÚìýFU‹jNÿnþwÌ|¯§üð¹ý‡||¸ŒM¯ò³þéøÍ_5XqãâùsÑQëF¨¦õ¾Òi¯ú¼YøÃMßXñÅ:®�ÙAV3ÄUôô¢ �#zGb£
AW¾Ò~Á—Ùyÿ�?[­k¢ºzÃk�ÿ©ÿ¸Ó/þ©h€–ˆB=Š@$–€.'AuÒH?¼�3Kî?]¦bqŒóV`ÅÎy ¡¢yÍYh^s¶={Í¾gþÔ¾0Ôv™e¹OìÜ¥ ,¼úö	ÁW»�’�ØÑ\ãGëqg¡-uð{Ýo½‚3VÌv|L–e°ñ’Ïd„0Ã@--�6`žI¤T;õb×á>tö‡;øÖòõ›6‹��à�=óÖÔNøÑx­« hÆÆKj¥-04†œ*:ÉxºÂŽ ´ß�Mê��°ËOAÃòS.êŠ<ˆ'ï¸8¦ Æ�Å_¿w=U’ßbX.Ó6Fà8tÌiÇq³š3ùà‹>=îþ×Ü®Z²FÍÎ>:…bÐÌ¬�šÚœ%ë.ý<jNè'?5ÔÍ³8~^ŽŸ×†”ªãÛOßºîù§îz|Án>™! tå¢E×Üþlc{Ç—Ÿ½êäÊæRg¡ëá[~X°Öàu?GïÑÃÿÉÕä²½-¸¦IÀíð<JïuG#0Žn³~?¦ ÆˆŽÏÝ<—÷…¾Mtå"Âš·Qà8,]8Kf6´U8›>ÿïè�)HiÔqïE‘%¶‰ž�›g!rž�ó,”‘>\ÿË{On>nÙ²{»Á°Ü)ƒ]‡Þ\tí�?jòn(_Ìc��?üÄ/]{ç¢©¾ÿN‘ÝOÐiÒdŽ-¯àÌ(V+`¥ågƒ¥ša<ø«]ÖßÇÀ¡ö¾ó5qþš‹€Ò‚¯hÂ’†˜¬CuÕ¡;*çtê+’ª‘3<ÓÃ3¹9xx+ÏºëN6‡[|þ¬Õ88œUó•¾xô²ÅWýúº�?üÄ/ÆòÙ»nºâª×ßê~àGU¿¯Z2
e¸òP7ÔØ09C5Wî°‹�!ú!x|àÝ>x›çÀÝ8b¨ÉÑ±©ÃiPÜ4à *ñÿ‹Y ½±ÂÕß ìÖìÈÝ»N8ËP:>wó\+øÏ?ïYøåUXÐÞ‚•K”~ÆeÃ)É¼•¾\Ç5-Ë  Ža�37‚Ž §_ü1Èš1íÎ®uãóg­ÆÛ»ñÐëûÑ;«#ü|ÑWï>­ÉëûôX¬'ï±ºMA5»ëP]ƒ¡iÈVTW?¸ñ½¯Aé?P2“´Ø+¼7ˆ†ù+P·h5ZÖžUT!X}À/­�Š4`;8íÉÁZÔÿ?.ìjÄü-çýS}¡cÅúM›ÅŸ5Î_å›×¶�²ˆ¬¥+/»ù†Âò7šSkª‡…Wß~!a˜_njçò'ªkCíá·±þüÓrö‹ËfÛp©HµªSð¬ùZ2ÝMXÓ�¢3ðx–dLAž!™^"K rÄV1HÅ�a	^‘E£—Ï(‚%³[Ñ1£�½þžÞ~ ÁE}Ñð²Å_¿÷SÕ
æ‚ =-xù&xlÏ«xöž‚D³3ÛÑÖÚŠÚ:³Ò®¶Öü?TÓ€ðˆIäc÷þNÚ»›ª‰é~óYt¿ù,ÞþÃ�é‚Ó.&s?xÑE5³ZM…1UH°¡¥Ø	ÃÅMóßåÐJ,•#p$Rh„“òcÙ
àÍ‹¯ŸX8û”´ Ï¥ Ç1„Ì[úéóâ…‘ƒ pá„ÿÍôâ']{ç†ù
 xg,Äi7þns×_oÅÝƒS/»K hzãjÁŠŸI3LW *�­¿�A¡*ÈêðÊ3�…—gàØœÕ !ë8 ëðŠ,šýx†@äœ»fæÏnÇoŸz‰xla|×ó—˜ @¶ æ@Ô€®ÂÐÔL_ÀDçÛè~ä ¦ÀoØp
ÞwÚiX»v-<žÂ¦ n·��…Ã4UI&{ìÇ–-[pï}÷á‘‡&;ý-$YÆÒÍ7@ÑP]Õ5ÈiâÒß^¼˜qºä 8�ÿóÿÍÀ@¢�ó }]¯dÿ=­À›_?‡aù&ß¼¶…CÎ¦ Ç�ÒV†arªÙ}Eotã»OþÁ|={Ç8°~ÓfqðøÓïf.²¶uÌž…å3€µk±óÑß`û3AûÚ3mo¶…°¤!"é™Î¬fGá~a¥$³Z
¼ùYí¿ÞcPD$É<îŒ  ŸÈåÄ…²Ž}r
>u3÷`Q£×ž"n}àIüí�Ÿ¼³~Ófq¿?´ª|vŸs¤3Eû 4)#}`E/O TW¡Œ˜}gÌlÇÝwÝ	 ðz½¶Â_
¼KÄâÅ‹±xñb|ìcÃu×Ý€o}ëF1ëZT)‘éi�8¸� 5Ë‹o( ‘%ãöÿF<èù®Û”(€bæ»­ ;˜S¨©*þß]?´þüKþ Ž±`Ãõ÷‡úbá‚Lxïøã`Vóèè¬ùïû0¢‰¢Â–4%Ô‚fªA3ÂO)Ð55§WÎ=àxpÜè×ÄeB��+`Š‡S:†S:‚.A›ó@ÄUÄ$m!x† èbÁ| 9glð_VœZ¸öÎíºéŠ«Æ{ÿ «®€ü ›¥ÃoA¬ŸªkÐ£ÍÏÛZ[Çñ	…˜7ovæ÷„$CÖ(´ø";Í‰Ñ®šF„Ž;©èû§CÐí�ý/ÿ?8RHƒåûÿÀ$( §æûxæ‘þâ¥G°#ÖŒÎà×9g„?+¶Ÿ/ü²¦£sD‚Fpš–CJš�¾¸jÛ‹�*)š‚Þ(SLM7 é@JE¦G�›gpqhŒæ¯›V�V $�bß`
í5.¸�ö¾øný¿GN> {pÿë‡ à+Ko|øÈŽëÏþÞ¸nb„ånb®�Fú‰;ÜVô€°Ü¤tÿIÄcÐ’QJ
‘7Ì‰Ñ³Nþ`I÷«šñÂ)(Ñsðp¤Päûÿ@ÀxÌ÷ñ ‹Ñï?û€yhBn¯é¿~Óf1[øŽÃñË— ¥f´N*¡èèÌbX5j’>‘Ã@Bµ�ÛS%…”$çaÕê€›RM÷BÕuD5|Ú„Œ¤G—Õ{r­…Î	F2‚›ÿ0jBAXc0ïýŒøðw_õëøXÃ„9×­«Ûu�;lŽïÞ!ÔFJäLšªIV F0òÊC�FúÁ{ƒXpÆeEßã4ñf"Á1Î{ æçÿ[ˆ«¶ñí7?[ðy•ž`µÍ÷ñâ¦?Üžn+F¶:RiŸtåÏþˆ¤Ù÷Ò×(ºÃQLî-µüÌkYm°M¢JÍd«Yí±ÇCÍVX„åÍŸ<· 0Õ JéJé¨s³E ÝQ~‘ËiøZ[W�UBç¾w9Â*ƒ§· á…Ÿ/þú½;ª ÿ¯TS.T|÷Kð/^_v h5 F?¸/? XvÉU€'TtqÌÂpÚI˜#´h¢Ðþ¡BÿŸã¸ûíÂã%?m2Ì÷ñàí�nÜÖùŠu_oüÑµwþ0›ð;þ¸Ž„?©hè�šÇ'•HÀPŠ�Å¶VACŠ—<¯Q]>úÅ*0GO–7‡yºr­‰¡”Ž¨¬¡Ö# äbÁ0ª�Ca­!·ùÕ¥ù‹¯ùþË7,E2ÇËû@UéþŽÏÝ¼f¼¥Æé±èŸ¥¿Mtíá0.ßxéä3?¸½ÿœ kÎAÛ)•|Ït  �šÿ¥Â{m€¢²Û×ö(ë7m±rMÊï÷çÜ‘©¿=¹øÉw§OŒy.]Í8ft|îæ¹T•¿‚ôj»xþÜŸ?¡èe… 4M«ëH&ì…ÚÐTr
Z"Àâ±Â´R@2Š¸ïòBGK]Uƒ /m¶„Œ5‘tø<c® Jàô5è¼÷YôŽÄêx�ï6 ÆýeQú;Ò
J¿?ôxoù&¡ã�îG×Ÿn¢º¦’À¼ã±æ×—}�Ç!ù6Q¨ÄüQ ±ôTé|Dø‹Ýþ¶êæù'ï�å—v½¬©Ó·�ãÛÝx¸k‡yÿ/ã=Þ¾_\¹øùßÿA—Sh®ñcQûh²ˆ¬åúüò…0GiÅ†í«Î´DÊpOFø�Ñ™xºœ2Ó`Gz!�4p©ž}HõìƒÜÊp7”án³A§Ï1¡	ËA’Ä"#‚,ç*ª¤jàÐH
IE‡7½Â‰ª9óâ†j¦{¬‡gð‰3×š÷–åNY|Õ¯?W•/�Ò›Ëß h—©jAMD k*	,\‹“¿ú0e­Ù[oj—¸j˜ÿ†ŸSút±ÌÍ¢ö†aÐ{£/ïÂtEfõþb¨òÕ8æà¶g¯9ø›¢‹fŒŽ¢Öt�#Î…ß2ë³+Ït9y¨;Gð¤ãá}Hõìƒ2Ü52 ]J€jrÎ Mª«0ä¤yüØ”‘^È‡ ÷‚)8¦¥²yÕ H¨Hd…ó•@oLÉÓì¨sãkMo�æªj}oTWo !�9‹bB1çÔáä«RVø�é‘ÇŸý·k ÐåL)ú#Åö/zÕüÌº?		±·Lõ})@,£™ÕŸÿg<ÇZzãÃ_�ñÁkž­YyÚ‹T×~#u¥îü×Ï`¤ß¬yïŽ)�‘Ë	¿=]ƒ®FrÂ^†œ„2Ü©¿³@)ä£ÔD]ª«Ð“QÈ��‡ºs&ìR]ÅÐÐPÆá
ž%èŽÊIŽ†I{bJNžBvùèŽŸƒ€Áîª*!ÁÑ“£¿!7Võ˜yðÍ:íÿttÎYk¯©V •$ÿ”2ÿíÊ5M¹§Ø±Šª’•÷Ýxàµ÷~i‹Ò5´6é÷À¿j>ôÁ‰Ý8Åo>•¶ÕÈÖñ¬þ§üð¹ƒ]‡¾˜w<óŽÇêÍÿ‚V—Ž·¶mÅsÿ«ÏßŒ„šû¥¨:u$üTS¡FMW ›é×Ñ¡743UÕPe³`ÅÐ3
ƒ°/‚0,Ã€°¼Iþq"˜¬H€¡¤ t‚óÀzC`8ó3“‰8MAcý¨UÓWÁ0‚.:%èŽ*˜2¹ƒ”ªc ¡¢ÁËcçlÿMZ¿æÌŽÏþø�jõ$™È\ †Í„+™‚g(Ü<)ÿŸjÿßïpõ9RÔügÐ6ûïé§¾¸¶³ØñJ:ºnÜÄ±ì½©]fh}:(MUqÛó�XW÷m8›šd‹þÎ}?f²jùç´ÏÏ2XÛ2IEÇ¡°žÑàFoÓH<÷&—þl?�j*”<K€ê*ôTºœÃ	04J¸z"’öóMmÎºý ËCÖƒ4‚õ˜‘	†ãÁÀq£ -…–ŒšÛ½fM…rGQ
dªÝº£2\�È±PušzÀä†û{ñûïü3®úô'°Ÿm¼uk*ƒâ .žÒ`°`ÀÍ³ikhTˆ¦ƒÿt;Ë	)•ü³«ß&âDéÿ–:^Ip�7þà�R�!Äm)�º3V#õv'¦
�Ü‰A% }ë7^ñÇ±Æý^}û…Ù™~sÚ3É3†1ZH¡I‡‡g��äœ|ª©Ž„_�t£Ñâ#Ð’³HeàpÙRØlðÞ ÄúpÏ\ÂòÐapÞPFà¤ÏA†Pk¦ÚJª�Áp-u£ì{çˆ„9µnp,“‰¸x<KP×Ü‚ïÝv àPï¶Þý,‚‹:>wóÜjXÔÐã=ÆX�Ru¤€«Àiã�‰B@tî~]öçÚ•Ø–jÆÈ¡C)u¼’
àù'ï�S'é!�nÆÆS»c@ÓeïCì™©Äûçg¬hùÍXãþë7m�ÿ²þöúühªmGSr›m f^ùp8šIÄ -YÈdç¿–C‰š#¤YÑC•¡FÍ•]ï qp;Õ55³üÔ^,ô6 èñ¡‰5É«>=…Îè zå•ÔDj"+œæ[¸¾ÙË Kqð¾˜ô N]NA�A¨1{½Jª�þH�Aóu�šM#[¦ù?”Ô0¯^ Ï$U)E‡[`1«¹óZë±·{¼7ðe W�ÿ›$# Å@$>þC�ÙVAƒ—‡fÐ)³j®þ>�)šû¿³¿Ðü×ÁÜ]®oCÙ¸C ­é&­³?“A‘ÚuÝ?­Ÿ?É·MºKpî†3�g€¿öïù£1ÆnÅCË7|<ÝE °pVK¦®Þ0Äeäg=Xí¸­Œ=«Ä4j¤¸ð[¯ër4Cø­ç­P©¼8·y	6úf¡Ã[Ø_bƒÓ¼‹è2:µ(^9Œ�©!ª&"däõÇß½5'œÚ8¬è†PÛ
ÂrÐ¥8”‘ÞŒH¤d„9!¯Ù#,i¨õp¹8ƒ”ªƒO»EYÏ¦\¸j¾Ó= —­ß´ùkãMºb8>f¨2”¬Â D"�††ÛýS)gýü*…•ü“Ttð,K&· ò¯Æm/®Šf`g¡A“”»Ë³¬X~Ïu/½vâ—Bæd>°k‡þë·˜õ��˜4‰ÖÀÙó—ãìùËaÆŸÜÙuà—+ï»±¢P%ÌU–x{}~£fqXÒ¡¹Â/ËfUYæýº
52 Â‰kÀ�â0äQL—S9Â¯'cÐ£ý�#ƒˆîÞÀœ¬tEëJòå§‚¯±ÏŒSGâ@bô8AVÄ2¶ËšÑeòŠÜ‡GûÌ¦ýÏÜƒÀÂµ-ß˜^ùÍÎ8ùJ`$–‚Àsð\ƒ¤¢ga„SZ†e§4Ôyxð,ÁÊ³!<ºŠ¦Õ¬Øxž¼£äxð²ß¥� Ð7<1ù N7?ú]«:…
@Ò4¸ÒÍV&Ú*:ú˜±ÿbá¿½CR&|k�€îú«/w\GªÇ ôæüm4)ãàu·!ùÖ!4|ìt°õcŸÚ20SÃ0Ì×k–tì?øo·?¹ÿºÛ6o¸þþP¹÷-¼úö³Wÿö–†œÕ8YFQ¥\íj•³RM6_ŠCÍvª«PÂ}™¿õdòp’·e„©¿�~ä›äºË>‡Ú“–Á¿düKæÀ=Üóg€õ›fzg‚œîZÔó¹µòAVÄû<í¸®ýR/x ÑÝ[0ô÷ÿK}Ö9Hñ—%žRàX¸8’F—MkF5(¢Y³!­ßy–à½‹Í~ú„aNÁ8qÒ)îg9žª‰"‘ÑóÒ´É"ZŒT“4Š¤bYiÆ8˜æà8šú 5žâáÌ7º
S*RŠ~‹“ã:R _=ã}¿¦”ÚÚ`ý¿{ûòGº|#ü–MÈ�*B˜�,ËÞ~'¢#ÿíößï¿î¶Íë7m¶ÿ’8¸í*iàt9�ãr|§«~l^�ešN €5ÌCJ yp+â»· Ño©o_�¾ô-ÌŸ3Ÿëÿq<Žçá™ÙÖïA½èÍ¼VL Àˆ¡PÀ´*]{0øÜïM¡�åº  À»Ü0rVÐpjô÷xVÇ¡ìîÅkÚ3–Rñ’:‡xþÉ;d]Sû³½—¨RùUÝjæ¤$œgHÙì;U7ATÒ hÎ:9;EÈ¡ð•“J÷¡_:9®#ðÌ�„S*öºòÒnrðÓ?_ëGÝÕçÃ½¤½ª7ªÂ\Â²ìíw�´±ÇR–e@8af|ß'Ç¼‰è®—�ŒãpO?Âá¨ºýêŸHå>tÙÍ, 3†o1ü†¦A‰@KFAUJï>Dß|,3`µ^ðâçù*nøø—
ßRg?Ü¼˜£ Sd+�Wä>¤‰Ä}º®Ÿ –èÚƒ‘7‡.%`(æù1CIf|Î¡,¡O*æ| éÒâtßÂ,2táÓ`¦®ãs7Ïÿ—Å¼ {÷ÌlR”*MV¥²»d›ÿN i¦uT«€cœ‡þjÜlQòïÍîBÕ	ù—9§'hkºI=Ôw)Rú§taÏ~ŒÆoBã§Î„oÍBÿeË”å¤Ë“/aY\r'¢ ÿvûSGžzmèŠ�§Ð·s/À»àn��={÷‚óÕ€j‡ Kq¸\nPo\¢ †rÒiíV=9ê¨ñ0�oAêÕèÉ¤‘~°Oÿß¦‹Èæ•i~�•Øú boìMšŸåæEÔ”G]‘ g’xû¤<Ú·› „åþ‡êÚ_­Ê»èî-p·-€—á˜äš–ˆBÔ�cMÂOÒŒL\B5LÇÇ³ÉÀ¨dò‡æ?zGbàÜ¾•ït`J÷8ùà¡} Ì6æ¥\ E–Á»JÏõM+EI”îj=c ªê£�¬&­•¢’Õßjã–�˜¤a÷@¡a‰F¿ïôØŽÏbù=×½ôÚ{¿´ÀÚRûõÿîI„ŸÝŠYßü(Ú®<ñ­ûynÇ”'Âlœ¹i5žÂjÄb1ú\ïr¤-…WºßÆ®#lFÐeO „‘Ý¦Y¯É™¬;=Ý_Hççk*”Þ}P%“üÓ"ýÐ¢Ðj"‚¥þfœµé"l^¹~¿pPPÉÖ ÷ÁÊ»°PL	d¯þ'møè]Ï?y‡™jr@7GÞxÞöã2¹€)\Àü=&ë£
@Ñ3¦¦¤ê20›`Z4£½#1‹‚í ÀÞ={3›ò™²‘�%xQšk²\ CNÒR÷Ûì°<þô_I£�4<KÀ³ÎIC§¹¥Vÿ×m|út%ÓŸ*jbe–ÛÏ²êN?uWŸ�¶ÓG €ßï'gûÍÆ�Ÿi7³ß	à`x;jÂØçp¨'ŠÁtcI«�•<�+”z|z2]1Ú¦Ú –{qÜªEØ´è,iÈô»sôT°õèƒQDž¶ÿþ\œ d)€ˆ&å¬þÙ¡9Æ¸ÆHF.”FúýÉ#»áïX	¤€–Œi•´L`v³ì¶æ	EG]zŸÕ´“0mãÿ&È[ ÅÖwF‰R¡@'L¡k*¡J
D°/
T°;A%VAÈÍ9ý[ýÍÀŽ¾ÂÌ¿hJþ¯rÇÌFEwaÍ–ŸÞ÷Ú{¿´…€¬u²ÿÐã¯bø…íhûô9h¸d|+:¦•"ÈÜžÇ’†V,ihÅÙ P Ð–®AJ’èa)F à`xvÁ{çs>¨>„ùõÅà^ÒŽÔÛ�züÕ¢ûBP/z3VÀ-=¯¦W²5¿ª9Î�Ü
Ðkâ{^†oöqk†j*4Ýl\¢ªAÁ3ªN¡éK
™Zhò¥CkÄ8Á¸ý/i7éÀ�˜3ÇŒ4kšVÐñp–PmL¥EÁ×ÛO¹«« ²QÊ*àçU¥ÞèŠÛ…þÞpúËFÅwÁ©`�&eùÑÑÿ‡gÐúùóP³q%|+:�:Ø‹øË»§4­¸ìÍáyøyž,1Í÷ì½ªðoX†‘'^/ºòÛáõx^9–ã)%ÌíâÞ/üÑPåkR]ïPCÓˆ.§Àq¦Mäà1ýeYÕÁ§ÙpƒZÎ²6JÖÖ¥‹Š(œÍã*SIa€ŽW_ß–Q Š¢Ø* 'ð`9žêšJñBõ…ûDfRºÿØY!—óÕ?»}[6ÍÀ›Ý6ÕÔ”:öý-Tì­ÙòÓû(¥×+]C8xÝmØõÉïaä©7ážÝŒ†K6 åë—À¿aÙ¤çL°õø7,CßÝO8~' ¢Iøé³}¿®iw«ˆ|ïÉ—¾j	ƒÈ!4³C›ŠjRý<K QóF}ÿì…¦IHƒaêQ�çàÕ—_Ìl)E:	¶´´ PFzm_+ù7HéIÐÇ@ÓËÏ(,µúoïML’" ûüÄŠ²™ù“šÕãk•XÙHí:Œƒ×Ý†¾E3ÑtÙûP³qeæçh°
ªÿ†eÐ"8ô_¿Í°ýNqKÏ«™‚¨´¯o»_šØ C‹‡˜µ
òP7æ-^Šµµ<êjB¨­«g²gâ©:ÅðÐ ¤p±á.ŠA\Ü�9óTý>–}žêÚæ×wìÌl+E:‰´µ¶âÈáN(‘Á‚×Ü<;eµÿ!gŽ‚×œév³J­þ¯¶qŸ)-ßóÌcR k¶üô¾üôàJa)‚î¶:4^´¡óÖÁ=»îÙÍP%òî#Hí>ò®SþËÀ×úqäÇ*`ú�àÁ¾·3¦¿®ëK›Ñ%@â EbÿÆâ´s.À	ûbÉ!˜<KÐÔØ Ža°pÎL,ð×ÇÇï~qR‹ ëM |i!tÂ<
˜-¼¶¼±kW-C"‘@MM�­à$0oþ<lÙòä¡®‚×êÜSSùçâH¦æŸ!Zšo�j€cIN/ÀRÌÿ]ñª­þÀ8æŒÇ
È†Ò5„#?ú#ºn}µ'-CíßßŠð+:à[Ñ‘£”þð´"+�Ã2¸æ4càöÇK}¥°#Ü�ÿì|– º¦ý  ¡RËñô}ç^HÎýÈ'?©æôœ,³”cˆ�‡7«[ýÎ=óýàÎ9o<z¾ækðÎ[]•IÌæ² +ž~ü¬]ef“&“É£Ÿ'DàìY  yðHÎv'™…z/¦H�¦SD4gr�"NBÑñj—­ï?¦Õg£ß×Þû¥—œF*�{ÑLÔ�±ž3VÁÌ}R{!è…6™öÖ�{I;Üg€zÇ%ø p8>ŒOîú“iúæ¹õ/?½”ð1ž`­‘ŠÝÏ{ü'ã‡ÿ‹ùïY Iéè�)I*Kz&P~‘Å{fø13(¢ÁË££Î…žƒ{ñþ3ÎÄ‘Ã‡·Ž?w¼ÃXËß@uõzÞÄã= ÀœX,ØÚÔ\Ò¸ýöÛññ�ÞÆ™Xqý™íÍ~¡¢œjÁ#°hõ;ãjÜ,¿ïv¼ü‡_¢­µüŒÅXÑšæ"én@SÆ_ŸihB@ßxðãË�ó½Ï…m»ô?×©‡ú^$8ÀR¾5ážÝ\ðz¶B˜‚%ôdv”×÷£û/§ÊK»ÇuƒRªŒËvÜ‹© ØÇx‚kJ™þ„fRMyŠåø¹_»ëI2Þ<
Ëè‘ i¹”µò[D  ¼Ù:ØRsjÝàY�!XÕæÃ™k±oß>,]ý^H#ý}„åO§º:æ’PÂòË¨®n€o~ózœ~º™8cÆ[7 >TS°0dã™gžÁ©§ž
 8ñ/€nðAGÝØ[°�í5.¢;zŽÛ^zßûæÕ™ú‘,Ä@˜7Vmêš;žêxÿe/T’ø“�qKîó'é>�N.ïqœ@h«Cè”ð7¾Û®ª$Cë�I µÛ4'J1°õ�¡ŒÀ¢ˆø‹;{f;†_Ø^1¹g‡”*ã³»°f–6Ó,¿s@W|øß~Š5ï;Û{Á×t‰Dƒ±$Y)èT”s}¢.QÀq³ZÐÁ³³B"Ö´Ðêçñìã�àüóÏ(%Ø cíÚuøö·Í>„µµµ¶n  Ìš5«è�úûûÑÔdF)WþË=ðÌX0e«ƒ—wTòkPŠ¶ ˜“ êÃÿüËW°ëÅ¿ [O`Ó8ïqÆ­ Þ¼øú9ú‘á·!“®^Ý‹fÂ¿j><ÇÍ‚kN³­…��D$
f$	=b&Ò¨Ã¦?¥¯IçÌX9_kæ°A/¸æð.1‡ŸèßòU·$ÕzyÂcxñ¬²MP	¹”~oî¢¥øÄÍÁÛé>q’f «o ‰heõ÷Þ@l:_ Ù/à’å�XÔhfÖ{x|ú#Ä#?€| ×Žãr÷è €Ûn»sæÌ—0³}ŽîÄœËnDûIçMÉêïâZbQß?nžA{�«`»ªSüúGßÅc·} ä#fšwõ0n•¸ò¾¼ºîÊ›!×UóÄœ µëp“N<"\í�f)m} žãf�¯õƒÌn€70ÍÆ`åù–â�ôf"ÉÃ}ù,~Uý Ãña\µç!Ëìw&ü @éç`åY—f„?�£³·ßv"¯�2«5Çƒp"ø@„Ú–Œð GÌ¹s�A{È¯@ð¹Ï~6­ è§×oÚü�1‘‚„|”vX>ñ·¿áÓŸú‰¼^/<žÂòçráÀeË–âÈáNÄnGÓªæWã¥ˆ¿|XmÙòÁ³â)W`¡þæ†_(‘�çÇË¹d£*6ÑUžØþ(øèxÂ‚Õ MÊJ!Ä#‚¯ñ�õ{ ‡<Ôír|;)I¢l8I @�%¡ta²±#Ü�kö>2ëçÅ9~Æ¬5’‘ ÐÚO `
ÿ¡®îÌ>Z|áíÏ"¾çe¤ºÞÉéG˜–ã©wö2â[¸'¼ï<,oY ØÖGÈÅ!äöbÝºuÖîþžùí qéHÂdo»÷OÆ%_Œ`0ˆD"a« Ã#%y€ãW­Æ#?ŒÔá�SÂü×z8¸V	Ö¸Ù¢aÙ—;£Jª¨[ø¸®þu óß¹wäÍ¿�X­ó¬ÚªõòÚ/^\�°à?2(¥x°ïmügç³–`î#,ÿA§[ZÀ‡~ùwˆ¾öuõeÌþðögÐó—›K
}1°OO»ü*rî§®B�›E�‡Ç™ÍÊ;Á‚šˆ€°üòŠÉÀ´ËÂr<õ/YOÂÛž |ô²ËðéO}
@q2°”�M^vûË<“—iÊ³3ƒÎLÿlâ/QIÃí¯öæÔe0††¡®ƒ'Wcj30†TàbX³å§÷QÐ-Õ:Þ?RªŒí|
7îÿ›YàC˜çOpM%•&ˆú @M×ÃKòhƒ�¾Ç�±?`V×=vÛwá˜ô(ró¡T%†œ¤,ÇS"zº*9&á„™VÛÛq<q7ÏÍ½÷OÎ´
±}ÿH	>ã„•«Àr<€C»ßÏWS1š|ÎLƒR´Š‡ŸÜ.(Ê’5úDµ„¨¢  ¶­öÃÅZ‡Cq<=°ço½wíH?´äûë7^~úØ_ò 8²ÍÌ­¯Œvª;ñÂq�çú}’jöÉ³âÚ�<ö(tM%º¦>TéùRMù ?ïÂ3s	XO ÁåfPMDpï}æ\‚D"a[P*)Èà„÷¼‡ Ààë��ëº+A%¦�‡+:xwûòÆ|3†7Q¾ZÍó­j^ä/Þ~&ü™k\„�q7�üGÀáø0¾Ûó"n>ø’f¡N¥¸ ?ë<°uLèOðUªÊÜó¦oÖÚ÷#P×ˆ¤ªC•exf.Bpñ‰`ˆ’ÈX	¥àªiDÍ	gáÄOþN¿ð2ÈC€%M^ˆj
gŸ{.¢ÑHŒ°üGAg“M “øþ êV½œ¯B¨| É[a¨2ví;„ó?p6\.t]‡×ë-8OEÜ€ƒ�à¹çžA*ÆÒ³¯˜ðïÓÅ4x8É‹áX‚™!—ík)UÇß*h;æáÙ¯=uåÚñ5aÉCÕ3xÖoÚ,þH
<3‚ï¤T¿ê{wv¿™å�“;Ò…=ãŽó2¼x’¡Ê�xgúOû—[áªŸ�Á‘0†Ã¹CJÓíÂ•È t9	ªk ,Vô€ó†àné@pF†œÇŒ€€—5b^�ýÃaÜø™Kðêk¯Q]×>ZIx*�¨ô
€&ß¬ãà_¸|°lzŠolß|ñ~ ÀYgŸ�¯ýó? m	Áb9¯¾ú*V¯^ 8ïE}Ûì	üV�'ü”bv­«èêÿÐÎ¡‚)¿²$mw?tËêñ¦^çcBRøÒ‚ONEnÀt†%øî}Ûbø�­/|±Z#Î-¤•ÀÿñÞ`Ó²K®Â¼MæH¿Á‘0²ê8À¢±¾^-«gø°ûñ{ðïÿý$úÇÒýÿúM›ÅçŸºëqPãdÞDÝ‰‚õø!F»3‹í8xû×2£ÒÊå”Ê´ò–]z-V_øéjÞâ´Dxygu½�/ÚégwÙ•ybŒ.¯OÆ_1LHiÔÏw<yä˜+0ŠÃñaÜÙÿ&®Úó}}ä0±Ì}ÂrW¯ßxù—í{­ê3Ø©¡&œð{]NÎïyó™_ø3tMEãìEhnl@]m‚¿á÷z‰èáõzr~êkBh¨¯5ê‚~²¬ÙA�ã�§þ·~ó³øã½÷@MÆŸ#,÷!úß*9¯ÎÛ¾ÐK ö„³ÀyƒkF{‹˜–€¬¿Ñ]fÏƒí»÷áüœU5§‹b®ÉŸ”$„B!ÛÏÛà0^yù%$F±ôÌ�LÈ÷[ëátjtóLÑ˜TÒðÀÛ“cú[˜°$þtW ¥ÊØ>Œÿ4Ëw³°„ü|ýÆ+n®¶9Wikàë,ÇŸ£k*ñÍ:3­€»u>¼ÍsPÓØ*x!ð,UQHDÃˆöv"¾ÿMÈ‡¶aÿ®V§�‡@˜Ÿ‚*ó`&üü ×Â;k)„Ú–Ì(sÖåÍL/€Î{ÿñCo ¾ø¥«qñ‡Î`,fd»§Ýxf-^YÕ{[I¶ Ì­s�ùÿþÍ>‰æ¶EWõ	ñÏ?ûÀD=+Úi*Ó„§–Ð?‘ìÄ£}»óãíû@È¿¦'OŠàçƒñk©œ¸�êúz€®G:õ¶ú ¼BXîæÑ±f¡Y¼ ¿·m>ü‹×ƒÔ‚ËŠÏ‹íe ˜3öüä3T×TÂr<ýÕ­¿$¥\�b\@ÇâeØ¿kæœú!lüÂ·ªv?+‰÷—óû_îŒâ¹ƒ¹n†¨«žúâÚ	+{�ðÆh/¯ýâÅ,ÃÜ;‘ƒSJ)ÞŠô`Ÿ4‚'Föá¥XW‰$²uý¦+ÖN•ðÛÁTÉ6jèm ­!ë5Çv“†ãcà];«AJ¦«ýÐäªiDè=çøýBmk† ÆåƒPÓŒÞÇoC÷#æ”«¹‹–â×¿0§ÔÙ
¹Ýn46ö*ýÎoÆ×®þXŽ§þÕ¤ZIA3‚‚ã�_)¿¿;ªàwoölWRÉ+^ýêú»ªr²E0)R9™ƒJ)Ž$F°/5Œíò Þ‰”øB–¿‘êêS}-“‰láç½AÔ®=¬ÛŸã÷sÞø,e@8BM3Çƒj*ÞùÑ'�èÚ 7CÐ.*`—˜ˆDQÓÖ5©X	éW¬Ð0C~w¿Þ‹¨œ7Ž>½së×OÝ<A_Ëè½žè Ò|@*°sªkŠ�R
IS0('Ñ$ªÉÌîwbè–"èTãE…�åxÊˆžÌké±ß™î´ÙûQÂœ\mÆº"_økN8œ'>ØPÔïLk€G[êÙ‹Ý?øxæ^~û?ÉtÊçŠYW~ùüô'?€«¦ùÙ ;öÆ NK|�Ò©¾€½ß?Q!?;Lš]>>à�Þ·ðoUí\éñ^1]Áˆ¡T´Š[Â.x ïáÐTzV[n]‘Á
bæw5ÉV}„VW³¢k:Â
C¢„ðN„«aFÎûø`CN¢…ÁïGç}fŸ WM#~û­ƒ¶|€!xèÐ!tÌ›OuM%Çüz¬<ëÃcº®Z‡Z‡3ý€Ò¤ßSûÂÓ}0Ìª‰Mò³Ã¤:æcåžØ‹kö<<)çÈr<åý5„åÅŒ€3.ÑÞå�*%‘ß…×PePMÉì]…2t,/‚¸aÅµ'ª¹Ã´�Éöß‚tšo1ájšrH?Ëï/†wÿFÒi½s-Å¾ý­¢JÀÎÈ¶.úÁ_*.
¸8Ô{8ÇŒ{�X”ôÛÙ—ÀÃ»¿þÉðû³1éÌÜ«ë®ü†a*êp8>Œó·¥›žòU Ý•¼ Ã-ôÔ5gš'zf/‡Øº /‚ÝP¢C ÂŒúuz*%œKÎ]…<Ü°|F)P–‡–ˆÀ�“ö®«ÐS1NÈ„µÞ­J€°üÁ¿éšJ\5�®:¬è)+ü„!6Ì,ylCNbÏÍŸÍð¥ºÙ¹ÙVÀÂó>‹“.»ÚñuyÍùäw÷ÉFLÆ=[

}¤dòÛ¯ÿ¿õ_Ÿð/)“Þ#ù—G^~êòÙk–ò”,qúž ïÂûß2óå	óPz?€•ü0nÿ6WýŒ¯1¢Œèë«E`ápÞ X—´`¦<a9ªd¦ÇºüàüµàCM¦EÀ`À˜·�eYP |°|°œ¯†ª€ê*Äš&ðõ3`(x_Jd  š©ªœI8á!úÑÙê8Œ'XKUù^Pã3Ô0ˆ·m>‚ËßÖå¨/+üBM3Súq$�Àâ÷bäµG`¨2ººŽ ¯¿ëO:	©T*'IHÓ4(Š’S?
… (:yî¹gÞ·�ÎXw6ñ¤g$–‚‹#hñŽ…¿Ñ/ ¦ˆ›•4Ü³qÝ2ª  ÍIDATmrÞpUQŸxíÚ÷N8é—�)i’þÎ¼Åž©‰§�Nö'„àåÈ–Â ,·ÔxºÒÏ¤ªœò´/9“*Ò Ðå$¼íÇ™«>Ë›Âlè`Ý°¢¼7Þ_Þ_Fp�uûÀð"Ë�áEh‰0 €\àýuêZÁyC™é;„å!Öµ�uû–a0‚†ª@¬i‚¤ÔÐ›aèaxñEjèG/'@˜3©*=àxÀLòñu¼¬Ç1Ô�ì’ÂÏ9ó«ëjC˜½ò$t>ÿ ¥†AöîÙUÓðžã�G*•‚ àÓ35M+(Zûžãqço~‹Hx„Äú:1ïäsK~^¥‰>µ>{‚1¥êøÃöADåÜÊFY’¶{#}gzæi2¿6`Š@ç�­úÖ�õ7#š:�Rãä=ª®á™‘és¦·�åsëŽ¿H(=‡õÕ‚uûánš±~&X—¬ÛÂ°`8Œ ‚p¼ù· BKäúüœÇÎ—VŒà6÷åE€R°ž „PXÑÖåƒ.% j€°œièø@=Ñ"ý”†�a˜�SJã ^ËuMÌU_ù9@¿ÀÇ{ƒ¨[õ>¸šç‚÷×€÷�~µvÂ bÝÇÂrsy]pÕ4"Ð¾˜ô¼ú8¥†A¶oÛ–Q‰D"G	$%	^—l:R ¸DÌëèÀ=÷ÜƒXï!_šç/³ý¼J…ßïâÐ\$ÍWÕ)îß1€¾¸š³� ÃŽnxúŸß×çä3ª�©“³tøÊõçmÑÃñ�BÊ>^p¸§oXŽk'.ÿO¨*WÜw ÑµwŸ»¥ãkÖß†ªÀÝ2šG@a7d“=`8oZ°Ý~ðþÚŒ`›û¸!àjœ:¨an'†M€åÁ
n°./¨¡�óÕCŠC““ÀûA˜ÓË½ZQYí`ý¦ÍbçÁmWQUºÀ 0³ûÞÆ€PÓÎí½./ÄºÖ_l˜U±ð[ð·ÌF }19ò’Ioß¶-ãä+�X"žS+°páBìÝ·Û·mCÿŽ¿Ûº•
¿›g0#T¼Gá_wcÿHîo1þÏ|ù½ïLÂ×f‹)S €Y4ô©¶ÕïB>PN	X<@B•Õ”­0}ûŠ@U9åmœ±œ° ôTžÖy œ`šö‚Ô$Ó®€¹Ò‡@½àae]^0o6Ïtû3¯3‚zj4¼CXœ' šV.„aÁºü`¨ËñPcÃ è,–e?GH×õO«æ*ë7mw¾õñÎýoüÀ¥ DÞD`ñ{án›Îí¨3]¥´°sÞ„P.G8qL+>ü-³œ},K`ïž=Ø¹sN?ý}H$9œ@>°~ýzÜóû{	��#;¶`Á) ›wæXÇ>?P:Ñ þ¶g;úr	bÆÐÀ3ôüg¾tâß'÷[ÌÅ”*  ¸µë•·ÓJàâRáABv«aì‰õÃœw‡ûÇòy5«No`=Ás8_x-8_Ü-æ*/z@X L:"0z{(¨®eÌzÖãç«ÃrÝvM÷f” Ãñ`]>pî,w€!ýy,!Ô„,kàDªÊ_ H=á„�SM2ž`-Õ”/txó6Pc3€Z–ã©îJâ_´œ¯| œ7dÞ3j¤c+8on¨­RŸ¿˜ð[°,K	tuÁ³/½ŠSO>	”ÒŒÈ'½^/Þsüñ¸ëîßP92@”¾ý˜yâ9±ý@yáî@¯uÅ¶Ë’tÅß¿râŸ&û»ÌÇ”+ ÀTŸž±&F€3J)FÕñèð hY¿ióOÆÒ5gÅÌ¥ÛÂ.ï'YÑã',=ƒ»iNFØÞ]2¿0Âr`Ñl�á«ëò˜ÖÇgÂ…Œà‚¡HWÀ‚É' º
Â‰émX—º"†BÞ•q	øP8—z"L©aˆ Ndæ*jÐ9/L6QÈðâIÔ0þƒªÒ- ÎEZð½3“Àqë	l ç	B5æøö¬è.ÈíÌ8¿X×V–í·PNø-ø[f£eùzÒ³õYhR#ƒý¸ÿÑ'1á"Ô…PU^¯·@	Ìž=®@yâÑG0xä ¼F+OÚT5áñP/uên/G¾öü—×þ|¢¿?'˜
  n=òò‹å”@“àÅýÛ(5ß‘#»þ:�è<°Ut¬L1‚ûÀôÑ9_êjCx„<"·*gZïÊ‚„°¶Ã‹¶9 „ãÁºý0²,yÂpà¼A€¦âÀ¨K`YbC;á\^PM±,‚•ÔÐ?àó ia˜õ›®8<Ö¶aÅ`úöÛO7?wRCÿ2€• ÄÑÿD"Ô¶€sû!„ÁºrÛt	Ázð�Ñ¤KØYW .øÝÎÓu]5�hYszw¼56MJà‰G�ªiX¶lTU…(Š0#G	œ´nM†èÜù&8–ÇìåkÊ~^9á¹3ŠÙÿãŸ]õ�j~oãÁ´Q €©>3cà;%À³:µÙë5ctŽÿÈ¿î‘óõŒÙ
Šy³Ûá9¸x^‘Ç`¼PÐ	Ã‚ ™Pßèv„1sr¶§-Ftƒjr†`òy.Ã»Ày‚E Ô¶@ð×‚Pš”  €zYç�­_aÎ°„Ô–'ë7^qªO°– Çƒ�3@éGA˜ëº¿õKjè—™Ÿ xgÂÛñø¬&\ |ÚÜ·¢&£×ã†X—›ÃŸë
�œ Sø=Bå½ü�3ß{ÂýÝH¦“…¶oÛ†g_z‹ÌË²`,Ëæ(�sÏ>¯¾ñ:öîÙƒ}oþl%àwq%	?»Ò^ÀLôyáËko¬øÂ&Ó²F÷ÕuWþ!ä:;%�•[¿isÃX&]{ç©*Åú{Öœ9hjiË¼NièIØ¾WOF`hjÁvCNeòË„¼Ôè�í,>5: -ÎÙFºƒ–Œ‚j*9irÑ¨±‘Rõ} é!QP#¯Àœ	‚­ øíÞÌr<uÕ6¶¦bÃL–3£n?XÑÂæ¡¢œ7”+øY¯åö”‚‡gPã+ž;_	>u¶Þõ_™ûÄr<½ôÒ"—\|1Z[[QSSŽã2)Ã‰H§�q¶l1»½ÿãÿ§|ô‹9î€A)ê<ýÅ…ÿÅCüÝfåŸŠ,?'˜–
 (®(¥8ãµ_§Çd�}VZÇçnžË	â¾Ì�`9¿z-Ø¬¦ŽbHªFÁ{©¦BKFl�kÈ)èR¼@ø-hÉ(4›n¼T“¡ÆÃÐ“…¯šb†³,92CŠƒ¦¢PÑLb¥à½¦Ïºý`õàýµéûÁ›.�è1óòPJð­|«Ùaù²¤ŸS¿Ä‡zñÒ/¾‰èîÑq®šF|ò²�ââ�ŸI¶Š‡úûûqÞyçg”Àâ3>‚‹¯ùO¸86“áW¬¦°/î¦¯ðÓX À+ë®¼†!ä¦|%ð“#/â¶ÎW Â<jŒ¹ï`¾ÐÖÜˆ¶¹2¯ËªŽ½qÛ÷–R  §-;š
-6Ã¦×}1E@Œè†ª@—bfß,¥ JI“‹ÐU[®0ùŠì:â6Âò`8$]‘¿Ò[(%ø ÒaÓ@ÁûKYc5ù�âàS÷aû½?ÌQ’3f¶ãü>„‹?t>QWW‡ÆÆÆK`î¢¥¸ôúŸcþ¼yEsûûN¾Àôóùó1­ `¯²‹ƒÆ4Ž*�×ßê‹G÷RUÎt£X¼òÃïqe*‚â2ú£öš†œ„žGþ±é]—“%• PÜÈ¼žCKFaÈ)3¡ÈUØŸê¨*ÃÐÌº+$i7Ô¼_\Æ¬'Î29¶øÊfÖBøl{ôºÝàƒE_·³ªiò—ƒÁÞŽwþv_ŽûÄ{ƒ¸äƒçâ}§�†µk×¢½Õt/þÈ‡ÓCOM«ákßù–¯ÛPx\�âÁ·qp¤ð™îÂL3Ð·yùÅOµ­~;;Y((¸±#Þ‡ÃR Ôƒ1’�‡ž¹GjX{n”Rúk["#MÍ£%©^�CBR*· “åÏ&Ù¬UÎL)v¯„¹3¢„-]Hgr¿~$È!�4É	`Ò†¬ÛÖí7ßgóÃºýf“à6žÒiÌ×Ærà<3¥7Ý©×n?Kðyméðµ2#Í}Bnu~wŽË5‘ðz½xÏ)ïÃŠ÷_LâI	#‡vQjÄPelß¶<ð xðÏØþö[ðx½¸òÊ+‘’u¼òòKÐ¤žùó½èîÄÒeË!zÌ,G3· G"¹ßch�%éŠéê+…ioXH÷¸Ãj(’M2žàìñ”Õ.ºúö]TWZç‚ºA±w0i;ž
0-ª«¶«ÕUh‰(¨Vš«44†’*jX1uª«™QÞ†’²%#+�¥´XÑÂ‰`8Œè)iXû³ÞPŽÒsŸÏ7i«¾…/�PžùêÅÞ§îÇÝƒDa4™÷qüÒÅèêîÆ‘Ã£=9]5�øäµÿŠ¥›>ˆÞ,håE€ažè—>ý…Õ�OÚŽG� 2G~K™C)ÅEoÞ�© äû ½v¬Ç]üõ{×ÉÈs™›ÂrX´leŽ+�Pt´ç\¢ ª¤�’Š¹–ŒÂ�âpÓìOæpùI5Ù º
CÓ@59£J¹ Ù¥¹¥Ìz»÷–sJÁçóÁç&ÔßÏ†‹cÐè –P6:¥Úý*^zìAt¾ñœ­2°½–YÇ¡õ_Dý’ÌxôIïæSU
 H·ëþYû@ï[¸qÿß€jXy„ ÛëÇ’eËsLT;>ÀÃ�æ›'ñ’JÀ©5`A—S%]ˆjÀIˆÎ$ýÜ¯ö™{éáñŽyxfÂ- »U¿DŽ@îÂ��Ûpø­W1ØÝ‰ÃûÞ�4Ü[4ìê›uZÎüVo¸ØLdï‰ÀQ§  3cíÔÀÝnUË
X¿i³8¸bãÖlW ?* ä*Žãàwå®„²,#/½ÒWb f
-ÕTèR†’§ÙŸsì"ñ{Â‰ãzÀ|ÁåÇævÏå:aV€“Uß~‘E£_ _„“§4<¿ë0ö’}ºªüµV—>üÌ�„'ä¢&G¥°ðêº+ÿãÏý;¯³¬ Â	Ç�§Ùf~n  ,X¸¡ºúœýºFˆ«(~N”€Sk€p¢m�j*¨&C—S²RÅ@8³JÑúk0èxQLð³Qm%À ÞËÃïpDW6šýBîâïH¨øëÎ~„S6n•®MÛ¿Õ
 0ÉÁ5[~ú€ü†ñ¾5Þ{‹¯úõçCÏao—.=žÀhs‹ƒ[· nþ
#¦1EŸpM7�ÅÒ†óQNS E�—¥ò�i%™¿›Çäª4$0}|–ãK
~6ªå
„\j=Ø
›Íº­�â«> ¼Õ—À“ïl§”FYª_9™<'G½ Òg«ØC=Ÿ°HA£2/Üþm�zœö±kÐW‘J§Þ—ã,P]5}þ<×€qùÊ¾w<¯p»D°_0°Ó	ÆkxM>¾bÁÊ¯ú’ªã©}aÛD0B�í^V¿üh"ûŠá]¡ ª�õ›6‹ƒ+7>F55“e¨w£ÿ±_Aî¥þÕ$ª�aŽ”€— ºœÌTV²ú�cQ „åáu‹­öÅ0+À+°¨óðûù@y_ º"2þº³ß6\W¤;ý�Ýö™é4âm<8¦ Š`Ãõ÷‡ú¢á—%¹pèå‡††^yø/ 0çÔ7ŸsÕÿdö3ƒ	C©ÒJ@Ó(RÒ‘5`�°|Ú2Hë�N€µÒWCèót9ËG�às,ƒf¿ ŸPüÜUƒâ¥ýƒx³§0òòn1ùîËTŸÀtÅ37^îøÜÍgK�ÛÏyëù{ :�ÛùãNCRÑáÒD�~"¯¡;oÄS68–÷ÿÛ;ûØªÎ:ŽŸç9çžû~o_i+XÖÂºN ¸¦BjL†fâÌÔÄlþ�C—8ÙœgÒD3’EˆD·l¨™Fb”2§t&3å5aH#8y]K¡o—{{_ÎÛóøÇí)íí¹¯½·´ô|’þçÐÒÛþ>Ïï÷{~Ï¹¾t�Oªy{ÀØ¤¡$�wê­�#nè�Þ£’«bŸIB3r–Ó	| ¨ñÉ¨óåÎ¤zo©xû¿ƒ¶�>"xOÈÍ6üëÉÕsj‹¯œ ªV®?ÚøÙo>èó°¼½m\	ÍD_4�çYó•…œ †~{`Lã×r‚°t°QI†wLJ f$Ø³‘Y
Hð+¥5÷,
I÷Sº‰“W†mW} s¾ËŸG Ò±î1¥·©%e=EØ%Ix`Åýðz&Oèé&G_T³­íÈ&‚BÏÐO—*ÑoÕX1Bn·Dv3x]¬äÀ÷¸ø$¸åÜ¥Åù›	t_²ýYÝM�¾\8(êUßûí�(¥ã']’„em-‡'¿µç‘”9åð¹ÈÁ|€µPÊôÞD‰ Î¯ä¬ó�ô¾þ‘‹CüjD�r£"J¸¹ÛûæË�wK£/Ž Š uó®Ù<1Q Ð¾´�õuSî/¦$°PU¦¡C3sPóN
 äfð¹¼òí8(Å¯ü…~¾tŸrØC´ïßí«þDIëæ]-²ÇˆJRÛÄ¿_ØÔ€%Í‹@3fƒJÉBnÝˆ§TŒêÈz
±Ì¤ ¬•>3è'Â
žæóŒ5ó¾ÎÎ\�ãôµû'<Ý¥þBpPk;÷…oÄ"oP&Mz‘ÏÀò{ï™Ò 
ïØÇ$4šnTD•€W¦ðH~E*x¿_f>9{P†oþHOò»4œýu7�í�ÑÁæâ9pP"ëS?¾~;¥ô©ÌkíK[° ¶fJ6 ¤Ë‚�¸žõ2ß`Œn
$tUUn4æ¢œ�©€ÌXÑoGf) 1Š�›!ì‘rvõ-ÎßLàäÕûù}ÌÏtßG Ó¤mËž�„ÒßdöªX|�}6À9GLãˆ$�)A\èPŒ…n
è¦	M7 ¼h)”" +ÐeFà–(%�))ë_«(é>A®±Ýñ×‚\HàÔµHÖÀ'‚÷<ò3så�•Æ@ÈÖ €ÖÅÍXÔXo›dŠ œ'ä,1èœŒÏ
hÆd9h‚¢Ú+AfS¥#3iì·Cb•	òlÈŒ¢ÚÃpí½XÝ±&ïŠŸÒMôôÇq¦÷VVÁ{ˆà?Ÿ�u~.”‰\%�Ï@[sã”íÂ‰$’Ihj
	:3Ûù&äf
™Q„ÜBn6ð'ïÇéãÝønç‹¶õ~$i §wïhY{#NàçÆ@™ißº·C¨‰Wì²�\eA×îN|aÓ³ ž bª�HÊDÊ˜~�Ÿ�;) �ÌThº_`³ÊóD?Øð€Xºjybû„=t.peDÅÙ¾ˆí>¾…ø…á äÊ€©":õìÝö=±õà…I?Õ0SÓ•’ÁL
Àêî—Djæýú‡�ãüÑ.´Ü·ŸÚú*.Ç�³ÏÁ9ìSè‹N�_Ž *Hëæ]-²?¼�<bw½¡* _¨ÿüñ— ÏüñxÖÏe˜1Õ@ÊUe¡R`pI
#EüDâš‰¿¼þN½ö“ÿ&ís…ë·,ùÖKA¥nÑ¤û„Q®«ûBn¶c¾wõ‹ÅÀÐ¾uo‡ÐÏgÎ À‡Ý�è§ú›?¶áÉ_í/ø0Žj˜Hh&R†@Êà%gå€Ì(Ü#ž±!ŸbƒÝ"®™¸8Åå�(†ãôèÎ¾ðè¿!øêUóDô¹ûŸýýÓîÆ% ‚÷¨£‘ßÕpí•ùº�?]Ì m[öl$À6«?9w}‡v�z‚où›Z‡Ú¾Ñ‰†Új,j¬G•·ð·Æ¶P�´t“§w¸€É“gÍr	ÀjøSJ!Q2~W‘\Œ–´ªÛÑÓ0��}&Wþôü±‘Ó]«­?Éµhí/»ïsÒüéãàÐ¶eÏFBðÔ…�Oüˆëj7 Ô¬zh°ñó›Æg	˜âÁ’ú ÔÖ”$;3�%˜"mƒÄðø½^„«Òo*MØâ+G`gc$©ãÃáQÜ¸•Â`,5O=“¸úÎù�¯-ðÓ;�#€YÂÂ/=ýNxÙšOÛ]óHµÕ¨«¡.è+Û™ý÷ßzJ 
ŸøÌ+ö}é\`(®c /8à-L]û»¼«®¶fï\{Þþ\Áy"Ð,Á·xÅKä£¢9óZÒ¸Ô?„KýCé{ƒ!,)üú¼ð¹J;9øþ¹s P6Ä5‘”�áX·b£IqÛ”>\ð˜0ŒnÅëÿƒ/6xÀ©ë+�“Ì2Ú·îízêæ=l';<AUÐÅ¥ äSàRÜðz<ðÉ4g¶ð‹¯}LVð³?Éû5t. 1Õ„j
Dã	hj
#) ©iˆ«zÁ+ûD˜ËÝ#8?”ê;Xsâo'çÃüÙ„#€YL)2ÈÄ#hÌ�¾ÛY‚âR�ìEWçWo Àºmo,hjjÄ(—93’4ÅÓ‰aRÓ�4	¸¡•ÜvXïûàDC0ü¶³ÊßYÌZ7ïjq¹½Ÿ’k=óV•*‹¡ãÐßõÛM ÐôÐw^®[ýpÙÿÏÌåî1tí]SMô˜ÉÑcÎ
?ûp0GiÝ¼«EòøWJ×È¡ú6®«íÅH¡÷ÀÎñ­µª•ë�6?úÜƒ…þÛ‰pÁc²â½lèÚ»ŒI×)ÁY¯$Îðý¯œw‚}öãà.bmç¾°¨ªi¾qå­r¸¾Åˆ.¡‘ƒµ~®«íÖ}¢ùì¶¯¬¦Þ „ÉË—ÿôÍnëº™Œ»ÃuQ ÐâÑ^êrßdLº®%¢ƒn_ð†ß«ôs-u“Œ]qRø¹ÍÿÒ‡+¦Å1È®    IEND®B`‚               h          ¨   00     ¨%          ›     X4   V S _ V E R S I O N _ I N F O     ½ïþ                  ?                        ¸   S t r i n g F i l e I n f o   ”   0 8 0 9 0 4 b 0   ,   C o m p a n y N a m e     a m p h p   Ô V  F i l e D e s c r i p t i o n     E x e c u t e s   a   c o m m a n d   a n d   p a s s e s   t h e   s t d i o   s t r e a m s   o f   t h e   c r e a t e d   p r o c e s s   t o   T C P   s o c k e t s   0   F i l e V e r s i o n     1 . 0 . 0 . 0   :   I n t e r n a l N a m e   P r o c e s s W . e x e     V   L e g a l C o p y r i g h t   C o p y r i g h t   ( C )   a m p h p   2 0 1 7     B   O r i g i n a l F i l e n a m e   P r o c e s s W . e x e     @   P r o d u c t N a m e     P r o c e s s   W r a p p e r   4   P r o d u c t V e r s i o n   0 . 0 . 0 . 0   D    V a r F i l e I n f o     $    T r a n s l a t i o n     	°<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
                                                                                                                                                                                                                                                                                                                                                            @     ø¢ ££(£0£`£h£   P      ¥¨¥°¥¸¥À¥È¥Ð¥Ø¨ð¨ø¨ p     @ P X h p € ˆ ˜                                                                                                                                                                                                                                                                                                                                                                                                                                                     MZ�       ÿÿ  ¸       @                                   ø   º ´	Í!¸LÍ!This program cannot be run in DOS mode.
$       ‹ìä Ï�ŠóÏ�ŠóÏ�ŠóÆõóÃ�ŠóôÓ‹òÍ�ŠóôÓ‰òÍ�ŠóôÓ�òÝ�ŠóôÓŽòÂ�ŠórAóÊ�ŠóÏ�‹ó”�ŠóeÓ‚òÌ�ŠóeÓuóÎ�ŠóÏ�óÎ�ŠóeÓˆòÎ�ŠóRichÏ�Šó        PE  L h%s\        à   (        1-      @    @                      €         @�                           TY  È    �  ¨Ü                   p @  PU  p                           ÀU  @            @  p                          .text   ô&      (                    `.rdata  ê!   @   "   ,              @  @.data   ˜   p      N              @  À.gfids       €      P              @  @.rsrc   ¨Ü   �   Þ   R              @  @.reloc  @   p     0             @  B                                                                                                                                                                                                                                                                                                U‹ìƒì8¡p@ 3Å‰EüVW�EøÇEø   ‹ñPh~f€ÿvÿ¬@@ …Àt"Pÿ6hC@ è‚  ƒÄ3À_^‹Mü3Íè¤  ‹å]Ãƒ=Äs@  t8¸   ¿   f‰EÌ¡Às@  ·¼s@ PEÔÇEÐ    ÿ°@@ f‰EÎ�EÌë-¸   ¿   f‰Eè¡Às@ ‹ ‰Eì·¼s@ Pÿ°@@ f‰Eê�Eèj j j j WPÿvÿ´@@ ƒøÿt!ÿ6h˜C@ èÛ  ƒÄ3À_^‹Mü3Íèý  ‹å]Ãÿ¤@@ =3'  t"ÿ6hôC@ Pè,  ƒÄ3À_^‹Mü3ÍèÎ  ‹å]Ã‹Mü¸   _3Í^è¹  ‹å]ÃÌÌU‹ìƒì¡p@ 3Å‰Eü‹ES‹]V‹uWj j j ‰Eð‹ú�Eø‰}ìPSVQÇEô    ÿœ@@ ƒøÿu+Wÿuðh0D@ ÿ¤@@ Pè¨  ƒÄ3À_^[‹Mü3ÍèI  ‹å]Ã3À…Û„�   ƒû‚†   ‹Ó�NWíƒâø(å�fnQ�I@fnAÀƒÀfnI¸fnY°fbØfnAàfbÊfnQèfbÙfnIØfþëfnYÐfbØfbÊfbÙfþã;Âr®fþå(ÄfsØfþà(ÄfsØfþàf~á‰Môë3É3Ò3ÿ;Ãs,‹Ë+Èƒùr�Kÿ Æ|ÆƒÀ;Árò‹Mô;ÃsÆ�È‹Eø;Át(QPÿuìÿuðhpD@ è*  ƒÄ3À_^[‹Mü3ÍèK  ‹å]Ã‹Mü¸   _^3Í[è5  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì$¡p@ 3Å‰EüSVW�EàÇEà    ‹ÙPh~f€ÿsÿ¬@@ …Àt#Pÿ3hàD@ è±  ƒÄ3À_^[‹Mü3ÍèÒ  ‹å]Ã‹;‹5Ès@ ¯þÆEô=Ôs@ ÿ0@@ ‹‹ÈÁéˆMõ‹ÈÁéˆMö‹ÈˆEøŠˆEù�EôÁéhTE@ ‰Eè�EäˆM÷‹KjPÇEä   ‰uì‰}ðè¸ýÿÿƒÄ…Àtƒ‹Mü¸   _^ÇC   3Í[èK  ‹å]ÃÌÌÌÌU‹ìƒì$¡p@ 3Å‰Eü¡Ès@ SVƒÀÇEô    WP‹ù‰EèÿÔ@@ ƒÄ‰Eì�Eôj j P�EðPj�EèPÿwÿÀ@@ ƒøÿu5ÿ7hhE@ ÿ¤@@ Pè)  ƒÄÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè¾  ‹å]Ã‹Eðƒøs/ÿuèPÿ7hÈE@ èo  ÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè‡  ‹å]Ã‹]ìŠ€ùt¾ÁPÿ7hhF@ è6  ë‹ŠK„ÉtF€ù}¶Á‹…S@ ë¸(G@ P¾ÁPÿ7hHG@ è  ÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè  ‹å]Ã�MøfÇEø‰Mä‹MèÇEà   ÇEÜ    ;ÁtQPÿ7hÈE@ è¸  ‹]ìƒÄé†   ‹�S‹5Ès@ ¯ÎÜs@ ƒîr@ ‹;uƒÂƒÁƒîsïƒþütAŠ:u'ƒþýt6ŠB:Auƒþþt)ŠB:AuƒþÿtŠB:Atÿ7hÐG@ èA  ‹]ìƒÄëÆEù ÇG   ÇEÜ   SÿØ@@ ‹�Eà‹OƒÄh<H@ jPèˆûÿÿ‹MüƒÄ÷ØÀ3Í#EÜ_^[è$  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌ3À‹�ƒz|	@ƒø|ñ3ÀÃ¸   ÃÌÌÌÌÌÌU‹ìQƒ=Äs@  ¸   S‹Ù¹   VEÁ3öW‰EüjÿÔ@@ ƒÄ‹øjjÿuü‰7ÇG    ÿÄ@@ ‰Gƒøÿt‰<³Fƒþ|Ì¸   _^[‹å]Ãÿ7hìH@ èR  ƒÄ3À_^[‹å]ÃÌÌÌÌÌÌU‹ìƒäø�ì,  ¡p@ 3Ä‰„$(  S‹]VW‰\$3ö‹³èRùÿÿ…À„  Fƒþ|ê‹Ëèÿÿÿ…À„¯  D  3Ò3ö3ÿ‰T$3À‰´$   ‰¼$(  ‰D$f�‹ƒ‹C…Àux3É…öt‹C9„Œ$  tA;Îrò;Îuƒþ@s‹C‰„Œ$  ‹´$   F‰´$   3É…ÿt‹C@ 9„Œ,  tA;Ïrò;ÏuRƒÿ@sM‹C‰„Œ,  ‹¼$(  G‰¼$(  ë2ƒøu-3À…Òt‹K9L„t@;Ârõ;Âuƒú@s‹K‰L„‹T$B‰T$‹D$‹\$@‰D$ƒøŒ6ÿÿÿj �„$,  P�„$(  P�D$$Pj ÿ @@ ‹ðƒþÿ„'  …ö„  3ÿ…ö~uƒÿ}p�D$P‹»ÿpÿ¸@@ …Àt‹»èœûÿÿ…À„³   NëC�„$   P‹»ÿpÿ¸@@ …Àt‹»è‘úÿÿ…À„ˆ   Në�„$(  P‹»ÿpÿ¸@@ …Àu1G…ö‹‹\$‹Ëènýÿÿ…À…Vþÿÿ3À_^[‹Œ$(  3Ìèf  ‹å]Â ‹4»�D$P�D$ÇD$   Ph  hÿÿ  ÿvÿ¼@@ ÿ6ƒøÿu'hXH@ èô  ƒÄ‹Œ$4  ƒÈÿ_^[3Ìè  ‹å]Â h°H@ ÿt$èI  ƒÄëÓhXI@ èº  ƒÄëÄh$I@ ÿ¤@@ Pè$  ë®ÌÌSVW‹ù3ö�G(Ç    ÇG0   ÇG,    f�j P�÷�CPSÿ@@ …Àt_…öu‹Gë‹j jPÿ@@ …Àt1F�G(ƒþ|ÈÇG4D   ‹‰Gl‹G‰Gp‹G�O`   ‰Gt¸   _^[ÃVhJ@ è  ƒÄ3À_^[ÃVh°I@ è  ƒÄ3À_^[ÃÌÌÌÌÌÌÌÌQVW‹ù�GP�G4Pÿ5Ìs@ �W(j h   jRRÿ5às@ j ÿ4@@ …Àuh�J@ ÿ$@@ Pè,  ƒÄ3À_^YÃÿw‹5(@@ ÿÖÿ7ÿÖÿwÿÖÿwÿÖ_¸   ^YÃÌU‹ìƒäøƒì¡p@ 3Ä‰D$SV‹uƒËÿWh   ÿÔ@@ ‹= @@ �L$ƒÄ‰D$ÇD$   j Qh   Pÿvÿ×…ÀtB‹D$…Àt[‹‹Nh(K@ ‰D$�D$jPè‹öÿÿƒÄ…Àt<j �D$Ph   ÿt$ ÿvÿ×…Àu¾‹=$@@ ÿ×ƒømtÿ6hÐJ@ ÿ×PèO  ƒÄë3Ûÿvÿ(@@ ÿvÿ˜@@ ‹L$‹Ã_^[3ÌèÙ  ‹å]Â U‹ìƒäøƒì¡p@ 3Ä‰D$SV‹uWh   ÇD$     ÇD$ÿÿÿÿÿÔ@@ ‹À@@ ƒÄ‰D$�D$ÇD$   j j P�D$$Pj�D$$PÿvÿÓƒøÿtS‹=@@ �‹D$…À„“   j �L$$QPÿt$ ÿvÿ×…Àtu‹D$ ‹L$;ÁuVj j �D$$P�D$$Pj�D$$PÿvÿÓƒøÿu´ÿ6h4K@ ÿ$@@ PèQ  ƒÄÿvÿ(@@ ‹L$$‹D$_^[3Ìèæ  ‹å]Â QPÿ6hØK@ èŸ  ƒÄëÌÿ6hxK@ ë´ÇD$    ë¹ÌÌÌÌÌÌÌU‹ì¸  ès  ¡p@ 3Å‰Eü¡Ès@ SVW�4@jöö�<@ÿ@@ ‹Ø�…ôÿþÿj PV�…øÿþÿPSÿ @@ …Àu'h`L@ ÿ$@@ Pè¢  ƒÄ3À_^[‹Mü3ÍèC  ‹å]Ã‹…ôÿþÿ;Æt"VPh¨L@ èö  ƒÄ3À_^[‹Mü3Íè  ‹å]Ã‹5Ô@@ W‰=Ðs@ ÿÖƒÄ£Ôs@ ��øÿþÿWQPèé  ƒÄ‰=Øs@ WÿÖƒÄ£Üs@ ��øÿþÿÏWQPèÅ  ‹5 @@ �…ôÿþÿƒÄj Pj�…øÿþÿPSÿÖ…Àu
h0M@ é=ÿÿÿ‹…ôÿþÿƒøtPh˜M@ èU  é.ÿÿÿŠ…øÿþÿ„Àt¾ÀPh@N@ è8  éÿÿÿj �…ôÿþÿPh   �…øÿþÿPSÿÖ…Àu
hÐN@ éßþÿÿ‹…ôÿþÿ=   u hO@ èö
  ƒÄ3À_^[‹Mü3Íè  ‹å]Ã€¼÷ÿþÿ t h€O@ èÌ
  ƒÄ3À_^[‹Mü3Íèí  ‹å]Ã‹=@@ �…øÿþÿj j jÿPj héý  ÿ×‹ð…öu høO@ èŠ
  ƒÄ3À_^[‹Mü3Íè«  ‹å]Ã3Éº   ÷â�Á÷ÙÈQÿÔ@@ ƒÄ£às@ VPjÿ�…øÿþÿPj héý  ÿ×…Àu hhP@ è3
  ƒÄ3À_^[‹Mü3ÍèT  ‹å]Ã‹Mü¸   _^3Í[è>  ‹å]ÃÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüˆUô�Eô‹U‰Eð‹ÂÁèÇEõ    ˆEõ‹ÂÁèˆEö‹ÂV‹uÁèVˆE÷�EìˆUø‹‹IjPÇEì   è&òÿÿ‹MüƒÄ3Í^èË  ‹å]ÃÌÌÌÌU‹ìƒì¡p@ 3Å‰EüSVW3ÿ‹Ù3ö€    �EìPÿ4³ÿ @@ …À„�   ‹Eì=  u
‹³‰D½ðGë…Àu~Fƒþ|Í…ÿtIjÿj�EðPWÿ@@ ƒøÿuhHQ@ ÿ$@@ Pè”	  ƒÄ‹= @@ 3ö�EìPÿ4³ÿ×…Àt"ƒ}ì u1Fƒþ|ç¸   _^[‹Mü3Íè  ‹å]ÃVhðP@ ÿ$@@ PèH	  ƒÄ‹Mü3À_^3Í[èé
  ‹å]ÃÌÌU‹ìƒäø�ìÀ   ¡p@ 3Ä‰„$¼   ƒ=äs@  V‹uWujjÿè@@ ƒÄ£äs@ …ÀtPÿL@@ h t@ h  ÿ¨@@ …ÀtPh”Q@ èL  ƒÄ‹UVè@  ƒÄ…Àtxè´ûÿÿ…Àto�Œ$¬   èdõÿÿ…Àt_‹=,@@ �„$¬   j j Ph€@ j j ÿ×jx‹ð�D$4j PèG  ƒÄ�L$0èGøÿÿ…Àt"jÿVÿ@@ ƒøÿu0hÀQ@ ÿ$@@ PèD  ƒÄèÌ  ƒÈÿ_^‹Œ$¼   3ÌèÜ	  ‹å]Ã�„$¨   PVÿ @@ …Àu0hR@ ÿ$@@ Pè  ƒÄè‰  ƒÈÿ_^‹Œ$¼   3Ìè™	  ‹å]Ãƒ¼$¨    u—�L$0è_øÿÿ…ÀtŠ‹Œ$¬   º   hhR@ ÿt$Tè1ýÿÿƒÄ…À„eÿÿÿ‹„$¬   j ÇD$    j ‹@‰D$‹D$<‰D$�D$Ph @ j j ÿ×‰„$¸   ‹„$°   j ÇD$   j ‹@‰D$(‹D$@‰D$$�D$ Ph@@ j j ÿ×‰„$¼   ‹„$´   j ÇD$(   j ‹@‰D$4‹D$H‰D$0�D$,Ph@@ j j ÿ×jÿÿt$L‰„$È   ÿ@@ ƒøÿu0hpR@ ÿ$@@ PèÙ  ƒÄèa  ƒÈÿ_^‹Œ$¼   3Ìèq  ‹å]Ã�„$¨   Pÿt$Lÿ8@@ …Àu0hÀR@ ÿ$@@ Pè“  ƒÄè  ƒÈÿ_^‹Œ$¼   3Ìè+  ‹å]Ã‹Œ$¬   º   hS@ ÿ´$¬   è×ûÿÿƒÄ…À„þÿÿ�Œ$¸   è0üÿÿ…À„÷ýÿÿ‹„$¬   ÿpÿ˜@@ ‹Œ$Ä   ‹„$¨   _^3ÌèÄ  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌSVW‹Ù3ÿ¾p@ @ ‹‹Óf‹
f;uf…Étf‹Jf;HuƒÂƒÀf…ÉuÞ3ÀëÀƒÈ…ÀtƒÆG�þHp@ |Á_^3À[Ã�_^�…p@ [ÃÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìQVWjÿÔ@@ ƒÄ‹ðVÿujÿ”@@ ƒè t:ƒèthtS@ èÝ  ƒÄVÿØ@@ ƒÄ3À_^Y]Ã‹E‰pÇ@    ¸   _^Y]Ã‹=Ø@@ Vÿ×ƒÄjÿÔ@@ ƒÄ‹ðVÿujÿ”@@ ƒè t#ƒèthtS@ ë‹E‰pÇ@   ¸   _^Y]Ãh°S@ è[  ƒÄVÿ×ƒÄ3À_^Y]ÃÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüS‹]V‹uWÇEø    ÿ<A@ j
Ç     �EøPVÿÌ@@ ƒÄ‹ø9uøt/ÿ<A@ ƒ8 u$‰;…ÿ~�ÿ   }_^¸   [‹Mü3Íè  ‹å]Ãÿ3hàS@ èÂ  ‹MüƒÄ3Í3À_^[èã  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüS‹]V‹uWÇEø    ÿ<A@ j
Ç     �EøPVÿÌ@@ ƒÄ‹ø9uøtÿ<A@ ƒ8 u‰{…ÿÿshT@ è>  ƒÄ‹Mü¸   _^3Í[è\  ‹å]ÃÌÌÌÌÌU‹ì‹E‹M‰H¸   ]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìVW‹ú·ƒø-uf9Gufƒ u	¸   _^]Ãƒ} t‹E‹0‹ÎèIýÿÿWVh¼s@ ‹@ÿÐƒÄ_^]Ãƒø-…£   f9G…™   ‹u�Gh@T@ P‰ÿˆ@@ ‹6‹øƒÄ‹Î…ÿu<èýüÿÿ…ÀuVhDT@ èn  ƒÄ3À_^]Ã‹@…Àu	¸   _^]ÃVh¼s@ ÿÐƒÄ_^]Ã3Àf‰è¼üÿÿ…Àt¿‹H…ÉuVhlT@ è&  ƒÄ3À_^]Ã�GPVh¼s@ ÿÑƒÄ_^]Ã_¸   ^]ÃÌU‹ìƒìS3ÛÇÄs@ ÿÿÿÿVW‹ú‰]ü�s‰¼s@ ‰Às@ ‰Ès@ ‰Ìs@ ;þ~=€    �EüSP‹E‹°è°þÿÿƒÄƒøwÿ$…˜'@ »   ë3ÛF;÷|Óƒ=Äs@ ÿuhU@ h8S@ h¼s@ èfüÿÿƒÄƒ=Ès@  uh¤T@ è`  ƒÄ3À_^[‹å]Ãƒ=¼s@  uhÜT@ èA  ƒÄ3À_^[‹å]Ã_^¸   [‹å]Ã�c'@ -'@ -'@ '@ &'@ ÌÌÌÌ¸�u@ ÃÌÌÌÌÌÌÌÌÌÌU‹ìƒäø‹E�MQj ÿuPèØÿÿÿÿpÿ0ÿXA@ ƒÄ‹å]ÃÌÌÌÌÌÌU‹ìƒäøƒìSV‹Ú‰L$W‰\$è¥ÿÿÿÿu‹øj Sj ‹j ÿwƒÉQÿTA@ ƒÉÿƒÄ…ÀHÁ;Áu	‹Á_^[‹å]Ã�X3É‹Ãº   ÷â�Á÷ÙÈQÿÔ@@ ‹ðƒÄ…öuƒÏÿ‹Ç_^[‹å]Ãÿuj ÿt$SVÿwÿ7ÿ`A@ ƒÄ¿ÿÿÿÿ…ÀHÇ;ÇuVÿØ@@ ƒÄ‹Ç_^[‹å]Ã‹L$_‰1^[‹å]ÃÌÌÌÌÌÌÌÌÌÌU‹ìƒìƒ=äs@  Vu3À^‹å]Ãjjÿè@@ ‹ðƒÄ…ötæ‹U�EP�Müè÷þÿÿ‹UüƒÄH�B·ƒø tƒø	t
ƒøtƒø
u
3Àf‰ƒéëßVÿ5äs@ ‰VÿH@@ ¸   ^‹å]ÃÌÌU‹ìƒì¡p@ 3Å‰EüV‹u�Eøj j Ph   Vj h   ÇEø    ÿ<@@ ‹U…Òu ÿuøVh$U@ è5ÿÿÿƒÄ^‹Mü3ÍèZ  ‹å]Ã�EP�MôèGþÿÿƒÄÿuøVÿuôh4U@ èÿÿÿ‹MüƒÄ3Í^è(  ‹å]ÃÌU‹ìQSVWh€   ÇEü€   ÿÔ@@ ƒÄ‹Ø‹=D@@ ¡äs@ …À„á   PÿP@@ …À„©   ‹pPÿÜ@@ ƒÄ…ö„”   j j ÿuüSjÿVj héý  ÿ×…Àu]ÿ$@@ ƒøzu¬j j j j jÿVj héý  ÿ×‹ø…ÿtŒWSÿà@@ ƒÄ…À„yÿÿÿj j WPjÿVj ‰}ü‹Ø‹=D@@ héý  ÿ×…À„ZÿÿÿShLU@ jÿ\A@ ƒÄPèýÿÿƒÄé;ÿÿÿ¡äs@ …Àt Pÿ@@@ ÿ5äs@ ÿÜ@@ ƒÄÇäs@     SÿØ@@ ƒÄ_^[‹å]Ã;p@ òuòÃòé_  Vjè  èX  PèE  èp  ‹ðè?  j‰èä  ƒÄ^„ÀtlÛâèL  h²3@ èl  è  Pèâ
  YY…ÀuJè  èc  …Àthb1@ è¾
  Yè+  è&  è   èß  Pè÷
  Yèì  „Àtè 
  èÅ  3ÀÃjè4  Ìèù  3ÀÃè…  è¨  PèÆ
  YÃjhY@ è"  jè  Y„Àujèú  2Ûˆ]çƒeü è³  ˆEÜ¡|s@ 3ÉA;ÁtÜ…ÀuI‰|s@ hŒA@ h€A@ è3
  YY…ÀtÇEüþÿÿÿ¸ÿ   éý   h|A@ htA@ è
  YYÇ|s@    ëŠÙˆ]çÿuÜèÙ  Yèq  ‹ð3ÿ9>tVè;  Y„ÀtWjW‹6‹Îè_  ÿÖèP  ‹ð9>tVè  Y„Àtÿ6èÝ	  YèÅ	  ‹øè¸	  ‹ðè�	  Pÿ7ÿ6èUóÿÿƒÄ‹ðè1  „ÀuVè�	  „Ûuè–	  j jèm  YYÇEüþÿÿÿ‹Æë=‹Mì‹‹ ‰EàQPè!	  YYÃ‹eèèì  „Àuÿuàè@	  €}ç uèS	  ÇEüþÿÿÿ‹Eàè  Ãè�  é‡þÿÿU‹ìj ÿt@@ ÿuÿx@@ h	 Àÿp@@ Pÿl@@ ]ÃU‹ì�ì$  jè=	  …ÀtjYÍ)£`q@ ‰\q@ ‰Xq@ ‰Tq@ ‰5Pq@ ‰=Lq@ fŒxq@ fŒlq@ fŒHq@ fŒDq@ fŒ%@q@ fŒ-<q@ œ�pq@ ‹E £dq@ ‹E£hq@ �E£tq@ ‹…ÜüÿÿÇ°p@   ¡hq@ £lp@ Ç`p@ 	 ÀÇdp@    Çpp@    jXkÀ Ç€tp@    jXkÀ ‹p@ ‰LøjXÁà ‹ p@ ‰Løh A@ èáþÿÿ‹å]ÃU‹ì‹EV‹H<È·A�QÐ·Akð(ò;Öt‹M;Jr
‹BB;ÈrƒÂ(;Öuê3À^]Ã‹Âëùèa  …Àu2ÀÃd¡   V¾€s@ ‹Pë;Ðt3À‹Êð±…Àuð2À^Ã°^ÃU‹ìƒ} uÆœs@ è‚  èŠ  „Àu2À]Ãè}  „Àu
j èr  Yëé°]ÃU‹ìƒìV‹u…ötƒþu|èà  …Àt*…öu&h„s@ èX  Y…Àt2ÀëWh�s@ èE  ÷ØYÀþÀëD¡p@ �uôWƒà¿„s@ j Y+ÈƒÈÿÓÈ3p@ ‰Eô‰Eø‰Eü¥¥¥¿�s@ ‰Eô‰Eø�uô‰Eü°¥¥¥_^‹å]Ãjè5  Ìjh8Y@ è=  ƒeü ¸MZ  f9  @ u]¡< @ �¸  @ PE  uL¹  f9ˆ @ u>‹E¹  @ +ÁPQèiþÿÿYY…Àt'ƒx$ |!ÇEüþÿÿÿ°ë‹Eì‹ 3É�8  À”Á‹ÁÃ‹eèÇEüþÿÿÿ2Àè  ÃU‹ìèÏ  …Àt€} u	3À¹€s@ ‡]ÃU‹ì€=œs@  t€} uÿuè  ÿuè  YY°]ÃU‹ì¡p@ ‹È3„s@ ƒáÿuÓÈƒøÿuè  ëh„s@ èô  Y÷ØYÀ÷Ð#E]ÃU‹ìÿuèºÿÿÿ÷ØYÀ÷ØH]ÃU‹ìƒìƒeô ƒeø ¡p@ VW¿Næ@»¾  ÿÿ;Çt…Æt	÷Ð£ p@ ëf�EôPÿ\@@ ‹Eø3Eô‰Eüÿ`@@ 1Eüÿ0@@ 1Eü�EìPÿd@@ ‹Mð�Eü3Mì3Mü3È;Ïu¹Oæ@»ë…Îu‹ÁG  ÁàÈ‰p@ ÷Ñ‰ p@ _^‹å]Ã3ÀÃ3À@Ã¸ @  Ãh s@ ÿL@@ Ã°Ãh   h   j è  ƒÄ…ÀuÃjè=   ÌÃ¸¨s@ Ãèöÿÿ‹Hƒ‰Hèçÿÿÿ‹Hƒ‰HÃ3À9p@ ”ÀÃ¸ìs@ Ã¸ès@ ÃU‹ì�ì$  SVjèÃ  …Àt‹MÍ)3ö�…ÜüÿÿhÌ  VP‰5°s@ è  ƒÄ‰…Œýÿÿ‰�ˆýÿÿ‰•„ýÿÿ‰�€ýÿÿ‰µ|ýÿÿ‰½xýÿÿfŒ•¤ýÿÿfŒ�˜ýÿÿfŒ�týÿÿfŒ…pýÿÿfŒ¥lýÿÿfŒ­hýÿÿœ�…œýÿÿ‹E‰…”ýÿÿ�E‰… ýÿÿÇ…Üüÿÿ  ‹@üjP‰…�ýÿÿ�E¨VPè{  ‹EƒÄÇE¨  @ÇE¬   ‰E´ÿX@@ V�Xÿ÷Û�E¨‰Eø�…ÜüÿÿÛ‰EüþÃÿt@@ �EøPÿx@@ …Àu¶Ã÷ØÀ!°s@ ^[‹å]Ãj ÿT@@ ‹È…Éu2ÀÃ¸MZ  f9uó‹A<Á�8PE  uæ¹  f9HuÛƒxtvÕƒ¸è    •ÀÃhF3@ ÿt@@ ÃU‹ì‹E‹ �8csmàu%ƒxu‹@= “t=!“t="“t= @™t3À]Â è$  ÌSV¾Y@ »Y@ ;ósW‹>…ÿt	‹Ïè8   ÿ×ƒÆ;órê_^[ÃSV¾Y@ »Y@ ;ósW‹>…ÿt	‹Ïè   ÿ×ƒÆ;órê_^[Ãÿ%pA@ ÌÌÌÌÌÌÌÌÌÌÌÌÌhK4@ dÿ5    ‹D$‰l$�l$+àSVW¡p@ 1Eü3ÅP‰eèÿuø‹EüÇEüþÿÿÿ‰Eø�Eðd£    òÃ‹Mðd‰    Y__^[‹å]QòÃU‹ìÿuÿuÿuÿuhó*@ hp@ è±  ƒÄ]ÃU‹ìƒ%´s@  ƒì(S3ÛC	p@ j
è$  …À„m  ƒeð 3Àƒp@ 3ÉVW‰´s@ �}ØS¢‹ó[‰‰w‰O‰W‹EØ‹Mä‰Eø�ñineI‹Eà5ntelÈ‹EÜj5GenuÈXj YS¢‹ó[‰‰w‰O‰WuC‹EØ%ð?ÿ=À t#=` t=p t=P t=` t=p u‹=¸s@ ƒÏ‰=¸s@ ë‹=¸s@ ƒ}ø‹Eä‰Eè‹Eà‰Eü‰Eì|2jX3ÉS¢‹ó[�]Ø‰‰s‰K‰S‹EÜ©   ‰Eð‹Eüt	ƒÏ‰=¸s@ _^©   tmƒp@ Ç´s@    ©   tU©   tN3ÉÐ‰Eô‰Uø‹Eô‹Møƒà3Éƒøu3…Éu/¡p@ ƒÈÇ´s@    öEð £p@ tƒÈ Ç´s@    £p@ 3À[‹å]Ã3À9p@ •ÀÃÿ%Œ@@ ÿ%„@@ ÿ%A@ ÿ%4A@ ÿ%ø@@ ÿ%HA@ ÿ%DA@ ÿ%@A@ ÿ%0A@ ÿ%,A@ ÿ%A@ ÿ%LA@ ÿ%dA@ ÿ%8A@ ÿ%A@ ÿ%A@ ÿ% A@ ÿ%A@ ÿ%ð@@ ÿ%ä@@ ÿ%hA@ ÿ%A@ ÿ%A@ ÿ% A@ ÿ%$A@ ÿ%(A@ ÿ%h@@ ÌÌÌÌÌÌÌÌÌÌQ�L$+ÈÀ÷Ð#È‹Ä% ðÿÿ;Èòr‹ÁY”‹ ‰$òÃ-   … ëçÌÿ%€@@                                                                                                                                                                                                                                                                             Œ[  ˜[  °[  À[  Ì[  æ[  ô[  
\   \  4\  D\  R\  b\  x\  Š\   \  ²\  Ê\  à\  ü\  ]  Ìa  ¸a  ža  ˆa  na  Ra  >a  *a  a  ð`      àa  Š]  v]  €]      ^]    €T]    €o  €s  €
  €	  €F]  —  €  €<]    €    È]      ¾]  ¶]  Ü]  ^  ¨_  &^      ’_      �^      Z_  d_  P_  _  n^  È_  ä_  B_   `  `  `  _  ü^  €^  4_  Ò]  Ü^  ¼^  ¤^  _      R^  8^  
^  ì]  &_  ¸_      Ÿ1@     °+@         +@ ¨+@                     `p@ °p@ S u c c e s s   S i g n a l   n o t   e x p e c t e d   a t   t h i s   t i m e     I n v a l i d   s t r e a m   i d e n t i f i e r   I n v a l i d   p r o c e s s   i d e n t i f i e r     D u p l i c a t e   s t r e a m   i d e n t i f i e r   I n v a l i d   c l i e n t   s e c u r i t y   t o k e n   I n v a l i d   s e r v e r   s e c u r i t y   t o k e n   F a i l e d   t o   s e t   s o c k e t   # % d   t o   n o n - b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       C o n n e c t i n g   s o c k e t   # % d   u n e x p e c t e d l y   s u c c e e d e d     C o n n e c t i n g   s o c k e t   # % d   f a i l e d     F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d   F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d :   s e n t   % d   o f   % d   b y t e s         F a i l e d   t o   s e t   s o c k e t   # % d   t o   b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d   h a n d s h a k e   F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   U n e x p e c t e d   s i g n a l   c o d e   % d   f r o m   s e r v e r ,   e x p e c t i n g   H A N D S H A K E _ A C K   U n k n o w n   e r r o r       H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   S e r v e r   r e j e c t e d   c o n n e c t i o n :   % d :   % s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   I n v a l i d   s e r v e r   t o k e n   h a n d s h a k e   a c k   F a i l e d   t o   c o n n e c t   s o c k e t   # % d :   U n k n o w n   e r r o r   F a i l e d   t o   c o n n e c t   s o c k e t   # % d     F a i l e d   t o   c r e a t e   s o c k e t   # % d   s e l e c t ( )   o p e r a t i o n   f a i l e d   s e l e c t ( )   u n e x p e c t e d l y   r e t u r n e d   z e r o   s o c k e t s   F a i l e d   t o   c r e a t e   p i p e   f o r   p r o c e s s   I / O   s t r e a m   # % d         F a i l e d   t o   s e t   h a n d l e   i n f o r m a t i o n   f o r   p r o c e s s   I / O   s t r e a m   # % d   F a i l e d   t o   c r e a t e   c h i l d   p r o c e s s     F a i l e d   t o   r e a d   f r o m   c h i l d   p r o c e s s   p i p e   # % d     d a t a     F a i l e d   t o   r e a d   f r o m   s o c k e t   # % d         F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d       F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d :   s e n t   % d   o f   % d   b y t e s     F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n         F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s     F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n       F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   1   b y t e       F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   e x p e c t e d   0 ,   g o t   % d       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   c o m m a n d   t o o   l o n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   m i s s i n g   n u l l   t e r m i n a t o r     F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   i n v a l i d   U T F - 8   s t r i n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   f a i l e d   t o   d e c o d e   U T F - 8   s t r i n g         R e t r i e v i n g   c o p y   t h r e a d   # % d   e x i t   c o d e   f a i l e d   W a i t   o p e r a t i o n   o n   c o p y   t h r e a d s   f a i l e d   W S A S t a r t u p   f a i l e d :   % d   W a i t   o p e r a t i o n   o n   c o n n e c t   t h r e a d   f a i l e d   R e t r i e v i n g   c o n n e c t   t h r e a d   e x i t   c o d e   f a i l e d     P I D   W a i t   o p e r a t i o n   o n   c h i l d   p r o c e s s   f a i l e d     R e t r i e v i n g   p r o c e s s   e x i t   c o d e   f a i l e d   e x i t   c o d e   ¨A@ ¸A@ üA@ 0B@ hB@  B@ ÜB@ a d d r e s s   p o r t     t o k e n - s i z e     c w d   E r r o r   p a r s i n g   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   p o r t :   % d   I n v a l i d   t o k e n   s i z e :   % d     =   U n k n o w n   o p t i o n :   % s     O p t i o n   % s   r e q u i r e s   a   v a l u e     P r o c e s s   l a b e l   n o t   s u p p l i e d     S e r v e r   p o r t   n o t   s u p p l i e d     1 2 7 . 0 . 0 . 1   % d :   % s     % s :   % d :   % s     %s
     h%s\       f   $V  $B      h%s\          ŒV  ŒB      h%s\       h   V   B      h%s\                   \                                                           p@  V@    pA@                    K4  RSDS0=|«@ÕèE�¾¿’ó œØ   C:\Users\Dave\source\repos\windows-process-wrapper\Release\ProcessWrapper.pdb       "   "         GCTL   ô&  .text$mn     @  p  .idata$5    pA     .00cfg  tA     .CRT$XCA    xA     .CRT$XCAA   |A     .CRT$XCZ    €A     .CRT$XIA    „A     .CRT$XIAA   ˆA     .CRT$XIAC   ŒA     .CRT$XIZ    �A     .CRT$XPA    ”A     .CRT$XPZ    ˜A     .CRT$XTA    œA     .CRT$XTZ     A  €  .rdata   V     .rdata$sxdata   $V  ä  .rdata$zzzdbg   Y     .rtc$IAA    Y     .rtc$IZZ    Y     .rtc$TAA    Y     .rtc$TZZ    Y  <   .xdata$x    TY  ´   .idata$2    Z     .idata$3    Z  p  .idata$4    Œ[  ^  .idata$6     p  `   .data   `p  8  .bss     €      .gfids$y     �  À  .rsrc$01    À‘  èÚ  .rsrc$02                    þÿÿÿ    Ìÿÿÿ    þÿÿÿî,@ -@     þÿÿÿ    Øÿÿÿ    þÿÿÿ0@ 0@ Z          .]   @  °Z          j]  ”@  œZ          ¤]  €@  ðZ          *`  Ô@  èZ          J`  Ì@  [          l`   A  p[          Ž`  TA  [          ®`  ø@  [          Î`  ð@                      Œ[  ˜[  °[  À[  Ì[  æ[  ô[  
\   \  4\  D\  R\  b\  x\  Š\   \  ²\  Ê\  à\  ü\  ]  Ìa  ¸a  ža  ˆa  na  Ra  >a  *a  a  ð`      àa  Š]  v]  €]      ^]    €T]    €o  €s  €
  €	  €F]  —  €  €<]    €    È]      ¾]  ¶]  Ü]  ^  ¨_  &^      ’_      �^      Z_  d_  P_  _  n^  È_  ä_  B_   `  `  `  _  ü^  €^  4_  Ò]  Ü^  ¼^  ¤^  _      R^  8^  
^  ì]  &_  ¸_      PReadFile  SetHandleInformation  ÀGetStdHandle  áWriteFile ©WaitForMultipleObjects  Ô CreatePipe  «WaitForSingleObject ÑMultiByteToWideChar -GetExitCodeThread PGetLastError   CloseHandle è CreateThread  
GetCurrentProcessId Û CreateProcessW  ,GetExitCodeProcess  šFormatMessageW  TInterlockedFlushSList ÍWideCharToMultiByte WInterlockedPushEntrySList KInitializeSListHead VInterlockedPopEntrySList  KERNEL32.dll  H WSARecv   WSAConnect  M WSASend  InetPtonW WS2_32.dll  P wcsstr  H memset  5 _except_handler4_common VCRUNTIME140.dll   free   malloc  n wcstol  # _errno    _aligned_free  __stdio_common_vswprintf_s    __acrt_iob_func  realloc  _aligned_malloc  __stdio_common_vfprintf  __stdio_common_vswprintf  B _seh_filter_exe D _set_app_type . __setusermatherr   _configure_wide_argv  7 _initialize_wide_environment  + _get_initial_wide_environment 8 _initterm 9 _initterm_e X exit  % _exit T _set_fmode   __p___argc   __p___wargv  _cexit   _c_exit ? _register_thread_local_exe_atexit_callback   _configthreadlocale  _set_new_mode  __p__commode  6 _initialize_onexit_table  > _register_onexit_function  _crt_atexit  _controlfp_s  j terminate api-ms-win-crt-heap-l1-1-0.dll  api-ms-win-crt-convert-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll  api-ms-win-crt-locale-l1-1-0.dll  ‚UnhandledExceptionFilter  CSetUnhandledExceptionFilter 	GetCurrentProcess aTerminateProcess  mIsProcessorFeaturePresent -QueryPerformanceCounter GetCurrentThreadId  ÖGetSystemTimeAsFileTime gIsDebuggerPresent gGetModuleHandleW  F memcpy                        ±¿DNæ@»ÿÿÿÿ         8S@     °#@ HS@     €$@ TS@      %@ lS@      %@                                                                                                                                                                                                                                                                                                                                                                                                                                                         
         E   s   4      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     0  €   `  €   x  €   �  €                  ¨  €   À  €   Ø  €   ð  €               e    €                    €                  8 €               	  P                 	  `                 	  p                 	  €                 	  �                 	                    	  °  À‘  h          (–  ¨          Ð¦  ¨%          xÌ  ›          �g >           Ðg X          (k }          (                                                ­�: ©|6	º�EcÈ™OÌÍ�Q÷Ò¥^ùÕ©cäË£c¡Ò¦_GÛ�5×žC         k7Ë *N H%ŒK/G»‹=xÃ�?õ³‚4ÿ«{/ÿ»‰9ÿÏšHÿ×©aÿÓ¬oî³‘[’²…>²�Q ˆ<  n:Î s<ÖV-§‰Y9Gb˜l3ì�\!ó_C—R:dgI�›o(æ¾�Dÿ¬˜xÿ¸�sÿÛµx±ÓžKÕ¤W e/Ên9Î’o?ÇøsI»ïoH¨ÿV4‰â;wCqV'_u_<–\F%l™‰oíÄ´›ÿÕªeÿà»‚ÿÔ®r�] yIÑLŠ`Øï�yßú¢€ÒÞ¢{¡ü†a¥ÿ_:¡Ù�`>ÅÂ£qÙxoa9ÄÅÇÜÊ¯ƒÿ×¨]ÿÝ´tÿÛ¼ŒèÕ¬lF‘jÞ`¢äÀ˜wÕÈaK¾�D¹©}>ÿ’jHÿ¹�VùØ·ƒ‚YPAMÁ¿»õ·›pÿÖ©bÿÝ³rÿäÃ�ÿá½„§‘xRlš~d\ˆmyL]Idšv;%Ã˜U}È ] ÂŸg x9UhK‘­†Iÿ»�KÿÓ¦_ÿÚ°nÿâ¿‰ÿÕºŽØÇ©{ûÜ¼ŠúÒ³�è’{W�´”b¯¤†V—´ŒM«³…<Ñ†`%°ZÆÅ‘?ÿØ¨[ÿ‰mAÿ€g@ÿÞ¾ŒÿçÍ¥ùÎ±ƒûæÅ’ÿäÂŽÿ¾žkþÕ«hÿÍžUÿº‡7ÿ�e$÷[AÛ›n'üÐ›Iÿ×§[ÿ‰mAÿ€g@ÿÞ¿ŒÿçÍ¥ùÆ§vãÝ³rÿÚ°lÿÙ¬cÿÎ›Jÿ½‰9ÿ•j&ÿ[AýhJþ®}/ÿÐ™DÿÓŸMÿÙ¬eÿÚ°mÿâÁŒÿÖ»�Ø½¡t§Ú°nÿ×ªbÿÍ�Oÿ¸…3ÿ¢r(ÿZ ÿS;ÿ�\!ÿ½‡1ÿÎ•<ÿÓ OÿÚ®iÿÜ³qÿåÆ•ÿá¾†¥ª“pIÓ¯víÆ’@ÿ¿ˆ0ÿµ€-ÿ�f%ÿnNÿV=ÿ“i%ÿÂ‹2ÿÎ˜AÿÖ§\ÿØªbÿÝ¶wÿäÅ’éÚ°lC?2Æ©{’Ï£]ÿ»…1ÿšn'ÿ‹c$ÿlMÿfIÿ¬|/ÿÎ˜CÿÓ¡PÿÕ¤WÿÛ±nÿá¾‡úÜ³r|µc ¸œn §ŒbÙ¹‡±Í¥gÿŸw6ÿŠc$ÿhJÿjKÿ±„=ÿÕ¢PÿÖ§[ÿÙ®iÿÝ·zëÛ³r|Ì’9
ÑœI , êÅˆ Ô­qâ¿ˆ“Ü¹�ïÇ¢gÿ³ŽTÿ½˜]ÿ×±uòÕªg½Öªg¶×¬g‹Ñ S9ÁÈŒ1             Ù¬e Ó£Vàº~IãÀˆ äÂŠËåÃŒÀá¼‚hÂ�@®o¡M ¢Q             ð  À  €                                          €  À  à  (       @                                                                 ‚Q �\ …]«:eÃ•K¿ÉœTë¾•TðÅ�_ñÓ¨cóÐ£]ÙËœR­Â�Bi—i ®f·t                                                                 �n# •e¯�8a»ŽHÌÂ—SóÕ¦[ÿÔ£TÿÒ Qÿ×©`ÿÙ­gÿÚ¯lÿÛ²qÿÐ©løÀ�eÍÓ£W–É‘77·o¿~                                            ‚[ [9¥{9zÉšO÷ÐœIÿÊ“=ÿÇ�7ÿÃ‹3ÿÄŒ3ÿÍ–?ÿÐšDÿÒ�HÿÔ Oÿ×ªbÿÝ·zÿà»ƒÿÛ²rêÔ¡QŠÙš6Æ�A ý¿%                             m9Ì     H&†29'  ÿ ©|5t»ŒBñË•@ÿ»…1ÿ«y+ÿ¤t)ÿšm'ÿšm'ÿ­{,ÿ¼‡2ÿÇ�9ÿÏ™CÿÔ¢QÿÖ¥XÿÛ¯iÿÖ²yÿ¸›lþ™u<Ã³�26\aj Ã‚                     l8Ì p<Ð p;ÑDN)“°%—l%0»Š<åÅŽ7ÿ°},ÿ—k&ÿoOüT<ÜG3·G2³Z@ÑxUö¡r(ÿÃŒ5ÿÐ›GÿÔ¢Qÿ²ŠIÿ”…nÿ�xjÿ°˜rÿÙ°oÙÏ—>Bá¹z Æˆ(             p=Í n:Î n:Î6k9ÉÜ@"w¯  $U<�‰b'ÿ€[ÿnOÿQ:ë(
w         "OV=Ç˜l&ÿÅŒ3ÿ©=ÿœ”ˆÿ¶±«ÿº™eÿã½„ÿåÆ–ÿÛ±nÙÌ“86ÑœG ÄŠ-         n:Í n:Ín:ÎÂm9Ìÿ\0®òX-§åX.�õY0‘ÿM+{ÿ6Oÿ(¢  " :+dK#JlQ&hnZ<>'S;¹�d#ÿ�‚nÿÛÝßÿ®˜vÿÕ§^ÿÛ¯lÿá½†ÿåÆ•ÿØªaÂÍ�/Í”8     n;Ì n<Én:Î‰m9Îÿn9ÎÿuCÒÿQÕÿ†YØÿ…YÙÿQ×ÿsBÏÿ`3´ôB#}£ (jQ)_yZ(÷P:ÿ‘}]ðspkI -RF4áÊÊÉÿ×ÔÑÿ·“\ÿÚ«bÿØªbÿÜ²qÿãÁ�ÿß¾Šÿ¹ŒDvÿÓ… W8 m9Í m8Í7n:Îè}OÓÿ™tÝÿ©Šãÿ¬�äÿª‹äÿ¦†àÿ¡�ÛÿœyÜÿ�dÝÿo?ÇÿD#‚ª?3!M¡IíÄŸeÿÀ¨ƒàlcV*   †††ÈëìíÿÇ¿³ÿÀ“LÿÙ«cÿØªbÿØ«dÿà¹}ÿØ¼’ÿºžqÏÎ›J0Ì›M P»sAÏ—ŽeÙÿ§‡âÿ§‡ãÿ¡ßø¡~âÆ˜u§Èª�sÿšqXÿxY[ÿz_˜ÿ…^ÐÿT,¡ø/'­ u/ñâ½ƒÿ×¼’¼©_ (()'¬¬¬çôõöÿÀ´¢ÿÂ�=ÿØ©`ÿÙ¬fÿÚ¯jÿÞ¶xÿæÇ–ÿéÍ¡ÿØ«b—·j }OÒ(’kÛÝ£�áÿ¢áÿ£âÿ…h¹ÝK:s%¤x+3¼�FÜÉ”?ÿ¦v&ÿvT$ÿ`CEÿ[==ÿ…^(ÿÊ™LÿÞ¿�ýÁ¥zr†‰� 655C···õøøùÿ¹®�ÿ¾Œ=ÿÚ¬cÿÜ²pÿÜ²pÿÜ³rÿâÀ‰ÿéÏ¦ÿßºÞÏ˜A*•mÞ¡~â^¢á‰¢á¯£€âÐ‘rÊåJ9gdñÄù «‚@bÉœVïÌšKÿ¿Œ9ÿ³‚0ÿ¼Š7ÿÑ¡TÿÛ·þË¯�²®…E   <0®©§¤ÿêëìÿ¤œ�ÿ”n2ÿØ©`ÿÜ²qÿÜ²pÿÜ²oÿàº~ÿçË�ÿåÇ–ûÕ£Sl	 	    —sÿ­‡þ¦‚ë)bLŠ+   �g£|@KÅ�\ÂÍ¤cïÔªhüÖ¯rùÐ®yÞÈ§s�›wA¤v-"!+fIæ’q>ÿ©Œ]ÿ±‹Oÿ—o1ÿÐ¢YÿÜ²pÿÜ²pÿÜ²oÿÞ¶wÿåÆ”ÿãÉŸÿÉŸ\�zb=»Ÿ‚UÆŠpF¡t\7yZF%R6(/       Ð³o �q,®‰M5»–[O°ŽXE�o;%`H"¤z9{™n+œ 4rQë°}+ÿÌ–@ÿÔŸLÿÄ“EÿÔ£WÿÝ±lÿÜ±mÿÝ´rÿÞ¶wÿæÇ•ÿÒ¿ þ¬‘f­§ŒbòæÅ’ÿà¿ŒÿØ·„ÿÌ«yû¼�lð�xR†E7!)e<�x_7€lU1`VC%,sY1`‡j=y¢I¢¸‹EÙ©z1þƒ]!€2#^€[ ûµ�/ÿÏšGÿÔ¢RÿÖ£SÿÓ¤[ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò®”jýçÇ”ÿåÅ“ÿæÆ”ÿçÇ”ÿéÉ–ÿ¤�iéPC-ÃÒ®uþ×²vÿÆ¤mù†mFÛË¢aýÎ¡ZÿË—Fÿ´�0ÿˆ`"ßI4`_DÒ q(ÿÆŽ7ÿÕ¤Vÿ×¨]ÿÛ®eÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý°—oýçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿçÇ•ÿÁ¦|ÿ„oMÿà»€ÿß¹|ÿÛ³sÿ¿”QÿÊ”AÿÃ‹4ÿ¯|,ÿŠc#ü\B­L6Ì€[ ÿ®|,ÿÌ•=ÿÖ¦Yÿ×§\ÿÛ®dÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý®–pòçÇ•ÿåÅ“ÿåÄ‘ÿäÂŽÿãÀŠÿÛ·ÿÊ¢bÿØ¨^ÿÕ¤VÿÔ¡PÿÎ˜Cÿ¼…/ÿ§w*ÿŒd#ÿjKìC0àaEÿŽe$ÿ·‚.ÿÍ—BÿÔ OÿÔ¡PÿÕ¢SÿÓ¥\ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò¤ŽjÙá¾†ÿÞ¶xÿÜ³rÿÛ°mÿÚ®iÿÙ®hÿÖ¦YÿÓžLÿÓŸMÿÐœKÿÀ�<ÿ¢s)ÿ�e$ÿuSÿK5ùQ9þrQÿšm'ÿ»†1ÿÏšEÿÓŸLÿÓŸMÿÓŸLÿ×¨]ÿÝ²mÿÜ±mÿÝ´rÿÞ¶wÿçÉ™ÿÓÀ¢þ­’g­”^¬Û¶|ÿÙ¬eÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿØªaÿÒŸNÿÇ“Bÿµ‚3ÿ¬z,ÿ r(ÿ~Z ÿaEÿ@.ÿ^Cÿƒ]!ÿ£t)ÿÃ�7ÿÏ—?ÿÐ™BÿÒœHÿÓ OÿÚ®hÿÜ²qÿÜ²pÿÜ²oÿÞ¶xÿæÉšÿäË¤ÿÉŸ]�zgJlÕ¶†ûÚ¯iÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÔ¥[ÿ¿Œ<ÿ­z,ÿ«y+ÿ¨w*ÿŽe$ÿZ ÿR:ÿJ5ÿjKÿ�f%ÿ®|,ÿÈ�5ÿÏ–>ÿÏ—?ÿÏ—?ÿÔ¡QÿÛ°lÿÜ²pÿÜ²pÿÜ²oÿà¼‚ÿéÎ¤ÿæÈ™ûÕ£SkI9*ÃªƒÞß·yÿÙ­fÿÙ­hÿÖ©aÿË™KÿÁ‹5ÿ»„/ÿ®|,ÿ©x+ÿ’h%ÿ�\!ÿxVÿF1ÿV>ÿvTÿ–k&ÿ»…/ÿÉŽ2ÿË’7ÿÏ–>ÿÑšEÿ×§\ÿØ«dÿÚ®iÿÛ±nÿÝ´sÿäÄ�ÿëÓ¬ÿß¹~ÛÏ—@'   £�i–áÂ‘ÿØ¬fÿÎžQÿÃŽ:ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿšm'ÿ‚\!ÿ‚]!ÿiKÿB/ÿ_Dÿ€\ ÿ�p(ÿÀ‰0ÿÈŽ2ÿÈŽ2ÿÍ–?ÿÖ¦ZÿØªbÿØªbÿØªbÿÙ«dÿÞ·zÿçËŸÿèÍ£ÿ×©_� = „kC nX67Ï¶ŽéØ¯nÿ¿‰2ÿ¾†/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¬{,ÿ�e$ÿ…_"ÿ�\!ÿZ@ÿC/ÿdHÿˆa"ÿ¦v*ÿ¾‡0ÿÈ�4ÿÌ•>ÿÒŸNÿ×§]ÿØªbÿØªbÿØªaÿÚ­hÿá½…ÿèÌ¡ÿÞ·yÝÐšE+ÒžL '	    £ŠbŠßÂ“ÿÎ Vÿ¾‡1ÿ¾‡0ÿ¿‡0ÿ²~-ÿ‘h%ÿŒd$ÿŒd$ÿ‚]!ÿY@ÿL6ÿmNÿ“i%ÿµ‚1ÿÆ�9ÿÐœHÿÔ¢QÿÔ¢RÿÔ£Tÿ×¨^ÿØªbÿÙ¬fÿß¹~ÿæÈ™ÿà¼ƒ÷Ñ›HhòÐ› Ì—C     pW. [CÁ¦{ÂäÅ•ÿÏ VÿÀ‰3ÿµ�-ÿ•j&ÿ‹d$ÿŒd$ÿ�d$ÿyVÿbEÿ]Bÿ€[ ÿ­|,ÿË”>ÿÑšCÿÓžKÿÔ¢RÿÔ¢RÿÔ¢RÿÕ£TÿÙ¬eÿßºÿåÇ—ÿâÀŠüÓ¡QŽÆ‡#	Ì’7           Ç¢f Šl>6Ò¶‰ÙæÈ˜ÿÓ§bÿ§{4ÿ‹c$ÿ‹c#ÿŒd$ÿŠb#ÿmMÿcFÿ_CÿkLÿ˜m(ÿÉ”?ÿÑšCÿÒœFÿÔ¡QÿÔ¢RÿÕ£Tÿ×©_ÿÞ¶yÿåÇ—ÿà½„÷Ô¡RŽÊ�-Í“9                 + ÿÿê ª‡NBÝ¾�ÙæÉšÿÔ­pÿµ‹Hÿšq/ÿŽf&ÿ€[ ÿcFÿaDÿaDÿ`Dÿ‰f.ÿÓ¤XÿÕ£SÿÓŸMÿÖ¦ZÿÙ¬fÿÜ´tÿà»�ÿÞ¹ÿØ­hÝÑœJgÇˆ&	Ë�3                         mI ÿÿÿ Î V6à¼ƒÃçÉ›þãÁ‹ÿÕ­mÿÂ˜Uÿ¦~>ÿ�i1ÿŠg0ÿ•p6ÿ°‡FÿÏ¡Xÿß¹}ÿÛ´vÿØ®lÿÛ´vÿÞ¸}ÿÛ´uùÖ©bÙÎšG‹ÆŠ,)­V À}                                 ±p Ý²m ÐœIÛ²q‹äÄ‘ëçËžÿåÆ”ÿàº}ÿÜ³rÿÛ±oÿÝ´sÿá»~ÿãÁŒÿãÃ�ðÍŸWŠÂ‘D‰Æ•H‘Í™F{É‘9OÂ…%¬e ¶r                                                 Ì’6 Å„"Ô¤V9Ü´t—âÀŠÛäÅ”÷æÈ™ÿæÊœÿçÊ�ÿæÉ›úá¿ˆ×Ù®ifÉ�.ÐšF                                                                                 Ê‹( À~Ð›F$Ö§[WÙ®h‚Û±n”Ú°m‰Øªb`Ñ�K"ºn Å…#                                                     ÿÀÿÿ€ ÿ  ?ù  ð  à  À €  €                 À                                      €  €  À  à  ð  ø  ü  þ ÿÿ€?ÿ(   0   `           $                                                                                  ?, Ê�+ ¦t$¯|,e¶…7¨¼�A×Â“Hó§�Dß¯‰LàÍžT÷ÊšNæÇ•FÌÃ�=£¿ˆ2nº‚(6¼ƒ"   õàX                                                                                                                 ”d uE ¡q%'šo,t™u<³ËŸYûÔ©dÿ×¬gÿÙ­fÿÏ¥bÿÓ­pÿÞ·zÿÝ·zÿÜ¶zÿÚ³uÿÕ¬küÏ¢Zê¨~<¢šo*LÆŠ*(¾}Â„                                                                                                      �n# ˜i¥v,d¶‰AÛÇšTþÂ˜Uþ×¨]ÿÕ£TÿÒŸMÿÐœHÿÑ�IÿÖ¥XÿÖ§\ÿ×©_ÿØ«dÿÚ¯kÿÜ³sÿÞ·zÿ¼žnúÏ«t÷Ô¤ZâË”<�ÅŠ+.¿Â…$                                                                                         Šb! }T¨z1†Á”L÷Ô¤XÿÓžKÿÎ˜AÿÍ–?ÿÊ’8ÿÈ�4ÿÇ�2ÿÈ�4ÿÐ˜AÿÑ›DÿÒ›EÿÒœGÿÓŸLÿÕ£TÿØªbÿÝµwÿá½…ÿãÂŽÿÞ¹~ÿÒ¢WãÉ�7|Ã‡(ÇŒ/ ¼                                                             H*t <$`$    šm& ¤s%
ˆb&n©‚DæÕ£TÿÏ˜BÿÅŽ7ÿ¼†1ÿ»…/ÿ¹„.ÿ¶�-ÿ´€-ÿ¶‚.ÿÂŒ5ÿÇ�9ÿË”=ÿÏ˜AÿÑšCÿÑšCÿÔ¡Pÿ×¨]ÿÚ¯kÿÝµwÿá½…ÿãÃ�ÿÜ´týÒœGÀÐ“3;íšÙ—/                                                     o<Î žUÿK(‹^-S8_ «‚> žq)h¸ŠA÷Æ“CÿË”<ÿÀ‰3ÿ²-ÿ¦v*ÿ r)ÿ�p(ÿ–j&ÿ’h%ÿ•j&ÿ¥u)ÿ°},ÿº„/ÿÂ‹4ÿÉ’:ÿÑœGÿÔ¢RÿÔ¢QÿÔ£Sÿ×¨^ÿÝ³pÿÕ¯uÿ¹Ÿvÿ”{Tÿ‰e,ã±0_ë§;Ê‘6                                             m9Í l8Ìo:ÐtF%ƒÓ)R9 ˜k$'°‚:ÚÎšGÿÅŒ2ÿ·‚.ÿ¬z,ÿœo(ÿˆ`"ÿoNÿ\BýM7òG2éK5î_CúvTÿ’h%ÿªx+ÿ¼…/ÿÊ’9ÿÑ�JÿÔ¢RÿÕ¢RÿÓ¡Qÿ¥€Dÿ{mWÿxtpÿ`VGÿ¶Ÿ{ÿÖ«eñÎ•;rÆŠ,É�4                                     n;Í o<Ìn:Ïrh7Ãø2\Ÿ   ÄŠ0 |X³ƒ5ÿ¾ˆ4ÿ±~,ÿ¡s)ÿ‘g%ÿvSÿI3õ&
´f9   *1Q&
“F2ßrQÿ¡r)ÿ¿ˆ0ÿÉ�5ÿÐ›GÿÐŸOÿŠl;ÿ€{sÿ¿ÀÁÿ�‚oÿËªwÿçÆ”ÿèÌŸÿÙ­gôÍ”:rÈŽ2Ë“:                             m9Ì {Eç n:Í^o;Ðñ]1®ÿ,   %5L6Î€[ÿwUÿjLÿcGÿX?ÿ5&ä`   
                     )*žeHø�p(ÿ¿‡0ÿÈ�4ÿ†f4ÿˆ…‚ÿäåæÿ ˜Œÿ¸�SÿÞ´rÿà¼„ÿäÄ’ÿçËŸÿ×ªañÌ’7_ÿÿ� È�7                     q?Î m:Í n:Í<n:Îâo:Ïÿe5½ÿM)‘ïN)’çM)�êN*†üP,~ÿH)lÿ:"Pÿ&,ÿøc#         	  4(I81?1&   
!cF÷¤t)ÿ’h&ÿ{ulÿáâãÿÔÓÓÿ—}SÿÙªaÿØªbÿÜ³sÿá¼…ÿåÆ•ÿæÉ›ÿÔ£TâÊ�3<Ì’7 Ê‘8                 n;Í n;Ìn:Î¿n:Îÿn:Îÿn:Ïÿo:Ðÿn9Ðÿn8Ðÿn8Ñÿm8Ñÿm8Ðÿk7Ìÿd4½ÿO*–û6e¹%G    fM$ƒvX'ÜmP#îx[.æ…u[­AAA)   )“iJÿdWBÿÉÉÊÿ÷÷øÿ¨¢˜ÿº’SÿÚ«cÿØªbÿØ«cÿÝ¶xÿá½‡ÿçÊœÿãÁŒÿÑ›E¾Ï“6Ð—< ®{*         n<É _�  n:Í{n:Îþn:Îÿm8Îÿm9ÎÿsAÐÿQÔÿ‰_×ÿ�fÙÿ�gÙÿŠ`×ÿ�TÕÿwEÒÿp;Ñÿi7ÆÿO)“î"@x   $=“o6ódHÿ-
ÿM9ÿº§‰ÿa`]„´±¬  &Ï”“�ÿèèéÿôôöÿ”…lÿÐ£\ÿØªbÿØªbÿØªbÿÙ¬fÿß¹ÿâ¿ŠÿéÎ£ÿÐ©kù¦v*T°2 _=         n;Í n;Í.n:Îàm8Îÿq>Ïÿ…ZÖÿ¢€ßÿ³—æÿ·œçÿ´˜æÿ°“æÿ®�æÿ­Žæÿ«‹æÿ¦…ãÿ—pÝÿ}OÔÿo;ÐÿV-¡÷!?s   hBºÀ™[ÿÁ—VÿÌ§kÿº¨‹çFDAAlha    III«ÈÈÈÿñññÿççèÿ“xMÿÖ¦YÿØªbÿØªbÿØªbÿØªaÿÛ°nÿá¼„ÿáÂ‘ÿ¦”xù™zI¤Ð›G$È–H     m9Ì m:Êm9Í�n;Îÿ„XÕÿ§‡áÿ´™æÿ­Žäÿ¥ƒâÿ¢áÿ¡~áÿ�{Úÿ›yÊÿ–t¹ÿ�m°ÿŠl¸ÿ™yÒÿ£�ãÿ‰^Øÿp<ÏÿG%‡ê>:*Š©€@ÿÞµuÿäÌ¦ÿÂ§}¼g. %
    zzy×ÜÜÜÿøøøÿÚÚÚÿ˜u=ÿÕ MÿØªbÿØªbÿØªbÿØªcÿÙ­gÿà¼‚ÿäÄ“ÿçÑ­ÿáÀ‹ÿÓŸN�Ë”;ÑžL m9Ì l7Ë(r@Ïá’kÚÿ¬�äÿ§†ãÿ¢~áÿ¡~áÿ¡~ßø¢áËž{ÜŠŠikÉ²ˆWÿ²‚>ÿ˜m/ÿvU+ÿW@?ÿnU“ÿ–sØÿwIÍÿO'œÿ/ÉaEß¼ˆ6ÿÜ²pÿêÒ¬ÿÈ¨uŸ    4˜——ïãããÿüüüÿÒÑÐÿžw9ÿÒšAÿ×¨_ÿÙ«dÿÚ­hÿÛ°mÿÜ±oÿÞ·zÿäÄ‘ÿèÌ ÿëÔ®ÿØªbáÐšE(ÒžM ‡[Ø xHÐs“lÛÿ¥„âÿ¢áÿ¢áÿ¢áÿ¡~ßÿpWœÉ^I�“j ¤v)[À“KõÎ›JÿÃŒ5ÿªy*ÿ„^ÿX?ÿL5JÿH-\ÿ@(:ÿ`C!ÿ¥u*ÿÎ›Jÿá¾‡ÿÕÀ�ô²�TXÀ¢r **) $##G¥¥¥øåååÿþþþÿÏÎÌÿ y:ÿÒš@ÿØ©`ÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿâ¿‰ÿæÆ•ÿìÖ²ÿà¼‚ÿÒ�JrÕ¡N l;Ç“lÛš¢áî¢áú¢áÿ¢áÿ¢áÿ£€ãÿw\¥ï!A:+0 ¡n�l2ƒÆœZýÔ NÿÃŒ5ÿ±~-ÿ�o'ÿŠb ÿ†_ÿ—l$ÿ´�/ÿË–CÿÜ³rÿåÊ ÿ½Ÿq¯c: E2    �¥¥¥ÿæææÿþþþÿÌÌÌÿsY1ÿË˜HÿØ©^ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿß¹~ÿåÅ’ÿêÐ§ÿèÍ¡ÿÕ£U»Ï™DˆbÌ¡~ß¡~à.¡}àN¡~àt¡~à›¢~á¿¢âÜ™xÕôL;k®   oP  Ÿp&¸ŒE¹Ê ]þÒ£XÿÎ™EÿÅ�9ÿÂŒ7ÿÃ�7ÿË•?ÿÔ¢Sÿß·yÿÜ¾�þ½£xÆ±…@4·‘X %	 VA1ö›š™ÿÜÝßÿôõöÿÁÀ¾ÿeM'ÿšs6ÿØ¦XÿÜ²oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÝµuÿäÃ�ÿçÊœÿìÖ²ÿÙ­gèÐšF6                žyß štßžzß
 }ß¤�å9kS–O §x.  p$•r;|ÆžaìÕ«jÿÕ«hÿÚ®gÿÙ®jÿß¸{ÿÙ·‚þÑ´…ôÅ¢k°�h.&i žq*    +�uTÿy`7ÿ‰uTÿ–‚cÿ™~Rÿ§|7ÿ‚a+ÿÔ¢SÿÛ°mÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²qÿâ¿‰ÿæÆ–ÿí×´ÿáº~üÐœHn#Q8*d? "                                  ¤q" šg­5@ª„H„¸•^»Î¨mÜ»›iÏÉ¦nËº–^™—t=D¬u"  œt4M—m)€   - —…_"ÿ¨w)ÿ¼†0ÿÌ˜EÿÔŸLÿÆ”Dÿ•o2ÿÒ PÿÛ¯kÿÜ²qÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà»�ÿåÆ”ÿãÌ§ÿ°˜tï•o3YbN.Ëº˜dÿ«ŒZô”wJâ|b:ÆdN+¤K:}1$W5                    e9 5  œh¯{)�n#¢g­J    SA%(›w=†©|3î‡`"—    0" †_"ÿ©x*ÿÁŠ4ÿÑœIÿÓŸMÿÒžLÿÍšJÿÓ OÿÚ®iÿÜ°mÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá¼ƒÿèËŸÿàË«ÿ´¥�õ¶�T›{eAçåÄ�ÿèÇ”ÿæÅ‘ÿâÀ‹ÿÙ·�ÿË©tÿ¸˜eü£…Tò�h@¡	7*C3g5(Z%D5		''5D3KhQ,r‘rA©´‹Jã¾‹;þ•j&þwUb   C/Ì�e$ÿ«y+ÿÂ‹5ÿÑ�KÿÓŸNÿÓ NÿÔ OÿÕ£TÿÖ§]ÿ»‹?ÿ¨|6ÿº’SÿÛ¶zÿà»ÿâÀ‰ÿéÏ¥ÿîÙ¸ÿòßÁÿÚ¯iæ†oKõåÅ’ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿæÆ•ÿçÇ•ÿêÈ•ÿ¹žtõ!WUE-z¸–`ý¹–]ý­‹V÷¥„Pò{c<¢aL+¢€Iê®ŠQð¼–YùÊ ^ÿÎ�QÿÅŽ9ÿ¢s(ÿ{XÙhJ"&
ojKû¡r(ÿ¹„/ÿË”=ÿÕ¤WÿÖ¦YÿÖ¦Zÿ×¨\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö�vRþæÆ”ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿÓ¶‡ÿ0)Þ]N5éà»€ÿâ½‚ÿã½�ÿå¿‚ÿ¢‡\ú~fAöàµqÿÛ¯iÿÓ¢VÿÉ“>ÿÀˆ1ÿ¦v*ÿ‚]!ýqQx!	TU=êŒc#ÿ¬z,ÿÅ�3ÿÑœGÿ×¨]ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�yVþçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿäÄ“ÿ]O;ÿˆrNÿä¾‚ÿà»�ÿà»�ÿá¼€ÿÌ¨oÿ·�PÿÎ›KÿÆ�9ÿÄŠ1ÿ¾†/ÿ¥v*ÿ‡`"ÿsRÆ1#mK5åvSÿ™m'ÿ´.ÿÊ‘6ÿÓ¡Pÿ×¨^ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�xWõæÇ—ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ”ÿèÇ•ÿ¤Œgÿºšhÿá¹{ÿÝ´sÿÚ®iÿ×¨^ÿÕ¢SÿÈ‘:ÿÃ‰0ÿÃŠ1ÿ¸‚.ÿ r)ÿŠb#ÿuTóH4¦>,äbEÿ�\ ÿžp(ÿ¹ƒ.ÿÈ�7ÿÓ OÿÕ£UÿÕ¥WÿÖ¦Yÿ×§\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö…qRçåÇ˜ÿåÅ“ÿåÅ”ÿåÅ“ÿåÄ’ÿäÃ�ÿãÁ‹ÿá¾†ÿàºÿÖ¯pÿÓ¤YÿÕ£SÿÓ OÿÓŸMÿÓŸLÿÓŸMÿÌ–@ÿ¿ˆ0ÿ®{,ÿ›n'ÿ�e$ÿxVÿ]Cß<+çP9ÿkLÿ‰a#ÿ¥u*ÿÀˆ0ÿË•?ÿÓŸMÿÓŸMÿÓŸMÿÓŸNÿÓ OÿÕ£Tÿ×¨^ÿ»‹?ÿ¨|6ÿ»’SÿÛ¶{ÿà»ÿâ¿‰ÿéÎ¥ÿîÙ¸ÿòßÁÿÚ¯iæxeIËáÄ–ÿâ¾‡ÿà»�ÿÞ·zÿÜ´tÿÛ±nÿÚ¯jÿÙ­hÿÙ­gÿÙ¬eÿÔ¢RÿÓŸLÿÓŸMÿÓŸMÿÓŸMÿÒžLÿÄ‘?ÿ¤u*ÿ–k&ÿ‘g%ÿ{WÿkLýB/õJ5ÿ_CÿtSÿ‘g%ÿ¬z+ÿ¼†1ÿÏšEÿÓŸMÿÓŸMÿÓŸMÿÓŸMÿÓŸLÿÕ£TÿÛ°mÿÜ°lÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá½…ÿéÍ¢ÿàÌ­ÿµ¦�õ¶�T›dS8£Ø»�ÿÛ°lÿÙ­gÿÙ­fÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÖ¥YÿÓŸMÿÓŸMÿÓŸMÿË—Fÿ¹‡7ÿ­{-ÿ¤t)ÿ•j&ÿ}Y ÿsRÿT<ÿ9(ÿS;ÿlLÿZ ÿ˜l'ÿ³-ÿÃ�7ÿÏ—@ÿÐšDÿÒ�JÿÓŸMÿÓŸMÿÓŸMÿ×¨]ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿá½…ÿçÊ›ÿäÎ¬ÿ°™vï”n3YI:#nÊ±‰üÞ¶vÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿØªaÿÔ OÿÎ›Iÿ¾‹;ÿ¯}.ÿªy+ÿ«y+ÿ©x+ÿ�d$ÿuTÿlMÿ@-ÿC0ÿX?ÿvTÿŠb#ÿ¡s)ÿ±.ÿÌ•=ÿÏ—?ÿÏ—?ÿÏ˜@ÿÑ›FÿÒžKÿÔ PÿÚ®hÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿãÂŽÿçÊ�ÿîÚ¹ÿá»üÐ›Hn!6²›wèäÁŠÿÙ¬fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ®hÿØ«cÿÈ•Fÿ²€1ÿ«y+ÿ«y+ÿ«y+ÿ«y+ÿ—k&ÿ‚]!ÿ€[!ÿ`Dÿ:)ÿO8ÿbFÿxUÿ˜l'ÿ¥v*ÿ»…/ÿÌ“9ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ˜AÿÕ£UÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÞ¶wÿåÇ–ÿèÎ£ÿíØ¶ÿÙ­gèÑ›F5   �yW»åÉ�ÿÚ¯lÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­hÿÙ¬fÿÑ¢XÿÆ‘?ÿ»…0ÿ­{+ÿ«y+ÿ«y+ÿ«y+ÿœo'ÿƒ^"ÿ�\!ÿ[!ÿN7ÿ@.ÿV>ÿmNÿ~Y ÿ�p(ÿ®|,ÿÆ�2ÿÈ�3ÿÌ”:ÿÏ—?ÿÏ—?ÿÏ—?ÿÐšDÿ×§\ÿÙ¬fÿÛ°lÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà¼ƒÿæÉšÿëÔ®ÿèÍ¢ÿÔ£T¹ÎšGâ¶q cO1r×¿™ÿà»�ÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÔ¦]ÿÉ–FÿÀ‰3ÿ¾†/ÿ¾‡0ÿ¸‚.ÿ¬z+ÿ«y+ÿ r(ÿ†_"ÿ�\!ÿ‚]!ÿuTÿ?-ÿH3ÿ^CÿsRÿ‰b#ÿšn'ÿº„/ÿÉŽ2ÿÈŽ2ÿÉ�3ÿÍ•<ÿÏ—?ÿÐ˜AÿÕ¤VÿØªbÿØªbÿØªcÿÙ­gÿÛ±mÿÜ²pÿÝ´sÿäÄ‘ÿçË�ÿîÙ¹ÿßºþÑ�IlÔ N 3' '(²šuàéÍ¢ÿÚ°lÿÙ­gÿÖ©aÿÌšLÿÁ‹6ÿ¾‡/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ·‚.ÿ¥u*ÿ‰a#ÿ€\!ÿ�\!ÿ‚]!ÿeHÿ:)ÿN8ÿeHÿxUÿ‘g%ÿ�p(ÿ¿ˆ0ÿÈŽ2ÿÈŽ2ÿÈŽ2ÿÉ�4ÿÎ—?ÿÔ¢TÿØªbÿØªbÿØªbÿØªbÿØªbÿØ«dÿÚ®iÿàºÿæÈ™ÿêÑ©ÿëÓ­ÿ×¨]ØÐ›F!ÒžM     }eA�áÊ¥ÿá¾‡ÿÑ¡VÿÃŽ;ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿ•j&ÿ‚]!ÿ�\!ÿ�\!ÿ[ ÿV=ÿ;*ÿQ:ÿiKÿ~Z ÿ•j&ÿ¥v*ÿ½‡0ÿÇŽ2ÿÈŽ2ÿÈŽ2ÿÊ‘6ÿÑ�KÿØ©`ÿØªbÿØªbÿØªbÿØªbÿØªbÿØªaÿÙ­hÿá¾†ÿåÈ˜ÿíÙ¸ÿà¼‚ÿÒžK|á«R ÏœM     K8 9(.·�uáêÏ¥ÿÑ£[ÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¼†/ÿŸr)ÿŒd$ÿŠc#ÿ…_"ÿ‚]!ÿvTÿL7ÿ=+ÿT<ÿlMÿ„^!ÿ—l&ÿ®|,ÿº…/ÿÄ‹1ÿÉ�4ÿÌ–>ÿÒŸMÿÔ¢RÿÕ¥XÿØªaÿØªbÿØªbÿØªbÿØªbÿØ«dÿÞ¸{ÿâÀŠÿçÌ ÿæÈ™ÿÔ£UËÐ›GÑžL              x_8}ÙÀ—þåÅ“ÿÍœPÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ½‡0ÿ¥v*ÿ�d$ÿŒd$ÿŒd$ÿŒd$ÿŠb#ÿoOÿO8ÿ?-ÿU<ÿmNÿˆa"ÿ›o'ÿ¶‚/ÿ¾‰3ÿÈ’<ÿÑžKÿÔ¢QÿÔ¢RÿÔ¢RÿÔ¢RÿÖ¦ZÿØªbÿØªbÿØªbÿØªbÿÝµuÿâ¿‰ÿåÇ—ÿèÎ¤ÿÖ§]ðÌ“:QÐ–: Í™H             :* ! £‡Z¾èÐ©ÿá¾‡ÿÌ›Oÿ¿ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ«z+ÿŽf%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿˆa#ÿjKÿ_CÿT;ÿgIÿ‚]!ÿ r(ÿµ‚0ÿË•>ÿÏ™BÿÑ›FÿÔ¡QÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢SÿÖ§\ÿØªbÿØªcÿÜ´tÿá¿ˆÿäÅ”ÿéÐ§ÿÚ°mûÎ–=‚Ë‘7Í•=                     Žl7 ]E;À£tâìÓ­ÿà¼ƒÿÏŸTÿÀŠ4ÿ¾‡/ÿ°}-ÿ‘g%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿ�d$ÿZ ÿdGÿcFÿZ@ÿhJÿ‰b#ÿªy+ÿÀ‹5ÿÐ™CÿÑšCÿÑšCÿÓŸMÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢Sÿ×©`ÿÝ¶wÿâ¿ˆÿåÆ”ÿéÏ¦ÿÜ³sýÏ˜AšÊ‘6Í”;                          ÿÿÿ €b3_Ñ³„ñìÔ®ÿá¾†ÿÔ§_ÿ½‹;ÿ”j&ÿ‹c#ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿrQÿbFÿcFÿ_Dÿ]BÿxVÿ�p(ÿ»†2ÿÏ˜AÿÑšCÿÑšCÿÒ�IÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢QÿÔ¢RÿÖ¦[ÿÛ±oÿá¾‡ÿæÉšÿèÎ£ÿÛ±nûÏ˜AšÎ•;Î–>                                 7(    šxArÚ»‹ôìÕ°ÿãÁŒÿÔ©fÿ±‡Dÿ”l+ÿ‹c#ÿ‹c#ÿŒd$ÿŒd$ÿ†`"ÿhJÿcFÿcFÿcFÿ_Cÿ_DÿjKÿ¬€9ÿÓŸMÿÑšDÿÑšBÿÑ›DÿÓ OÿÔ¢RÿÔ£TÿÖ§[ÿÙ­hÿÜ³tÿß¹~ÿäÅ“ÿäÅ”ÿ×©`ðÎ–?�Ê‘7Ì“9 _'                                      _F ( ²‰IqÞ½ˆñëÒ¬ÿäÃ�ÿÜ³sÿË [ÿ¯…Bÿ—o.ÿ�e%ÿ‹c#ÿzWÿbEÿbEÿbEÿbEÿaEÿ_CÿtV'ÿÈ™NÿÚ­fÿÖ¦ZÿÔ OÿÔ OÿÖ¦ZÿÙ¬fÿÛ°nÿÝµwÿßº�ÿâÁŒÿáÀ‹ÿ×¬hýÎ™EÊÌ”:PÊ�6Ë’8                                                 œs1 wQÏžP_Þ¸zãéÏ¦ÿçËŸÿá½„ÿÛ²pÿÐ¥`ÿ½“Oÿ«�>ÿˆd,ÿsS"ÿoP ÿpQ!ÿwW%ÿ‰f/ÿ«‚BÿÌœPÿØ©_ÿàºÿà»‚ÿÜ´tÿÜ³rÿÞ¶xÿá¾†ÿâÀ‹ÿâÀ‹ÿÞº€ÿ×ªeüÍ™FÕÇ�2xÄ‰*ÌŽ- ¿‡/                                                         Î˜B Á~Ñ�K<Ù®iÁåÆ–ýêÒ«ÿæÉ›ÿá¾†ÿÞ¶wÿÚ¯lÿÒ¥]ÿËžVÿÇšTÿÇ›TÿÎ XÿÖ¨^ÿÚ­dÿÚ­gÿß¹}ÿçÊœÿÔ«jóËžVöÏ¤`þÐ¦dÿÕªfýÔ¥\ôÏœKÜÊ“;«Å‹/bÃ‡)½�%¿„'                                                                     µz# Ö£R Î™CÕ¤W€Þ·yåçËžÿëÓ­ÿéÎ¤ÿäÃ�ÿà»€ÿß·yÿÞ¶vÿÞ¶uÿÞ·xÿßº~ÿâ¿ˆÿäÄ‘ÿéÎ£ÿá¾†ïÎœL`¶'C¸‚,`¹ƒ-eÁˆ-YÅ‰+=Ã‡'Á„#ÈŒ) ¦g                                                                                     Í•= È�2ÐœH0Ö¦Z’ÝµváäÅ“ýèÍ¢ÿéÏ§ÿéÏ¦ÿèÎ£ÿèÍ£ÿéÏ¦ÿêÑ«ÿëÓ­ÿæÉ›ÿÞ·yåÔ¤VhÊ‘6Ð›H                                                                                                                             Î–< Ê�5Ð›F&Ó¡Qj×©`¬Û²p×ß¹~íá¿‡öâÁŒùâÀŠöà»�ëÛ²qÎÖ§[�Ñ�K2Ê�5Î—A                                                                                                                                         œ= â¶S ÉŽ4Ï˜AÑœG;ÒžLQÒžLXÑžKPÐ›G7Î–=Ä„$Ç‹,                                                                                         ÿÿÀ ÿÿ  ÿþ  ÿ  ÿü  ÿ  ÿø  ÿ  ÿ0   ÿ  þ0     ü    ?  ø      ø €   ð <    à     à     À     €     €     €              0    ø     ü       ?€                                                                                            €      €      €      À      à      à      ð      ø      ø    ?  ü      þ   ÿ  ÿ   ÿ  ÿÀ  ÿ  ÿà ÿÿ  ÿø ÿÿ  ÿÿ ÿÿ  ‰PNG

   IHDR         \r¨f  € IDATxÚì}wœå™ÿ÷�ª.moöº¬;®‚ÁØ„ÐB	Ž$€Ó+I(ù]r	wÀÝåîRH%…�5	�\$@(¡0Ýlã¾öö¦®éïï�ÑhUFÒhW[Lüý|ÖÞ�F3£yž÷y¾OŽáŽáŽáŽáŽáŽádªOàÊcÃõ÷‡˜Æ–€ÝkFOTîO©çŸ¼Cžêó<†£ÇÀcÃõ÷‡hMÝ¬P °ŒaÈ
Ý �„�v AÏ¶k­srCSƒ°t
,Öºß0èÖp4ºÝxðW»Ž)ˆc°Ã10‰Øpýý!ÒÔ¶šg¹UA7·VÑéJŽeæNÆgkºñ¥t;�¥¤gŸúâÚÎ©¾Ç0õ8¦ &–À‡<âûŠÓ8–Y5ÕçdAÓ�7‚¿‡#w?{ÕÉ[§ú|ŽajpLTº¥�ã„KÝ{CõSŽgªy|.ïÓèø�©éÆþ”¢ß¢iÊ=Ç,ƒ,S U@–Ð_:ÖU>äâpq¹9E!77ÏÂ#0à¯À‚gí¿.U§H(:Tƒ"©ˆÊÂ)IÇ`BÁHRu¤(M5t0wG¢Ñï³
þ1pLŒ®¿?œ5ç ä“ËœZÉ{¼<Z"š¼ý"¼|Qá®T�b8©¢'*ãHTÅ�á$Í(ùô�ýÃá?¦ÞÝ8¦ *Ä)?|nE0¸Æ-pç8eè›}<f×ºÑr¡5 L¨°;E_LÁ;ƒ)ìêO",iE÷S5ýÎè¡_yæÆÂS}ÎÇP}Lý“x”à¼_o½ÌéjïâÌ«saN­í5.xÒ ªN¡Šf@5L›Ý0(ô"æ;K †!àók8Ó]¨DÁ$U=Q;ûSØ3�°u8†IŠvÕƒŸXq÷$ßöc˜`S %°~Óf±ö²k.!7–×¹8K=XÚìÅŒ ˜`;$UŠf@ÖH…fPõ*°yYpó&gàáST	%ÕQW@Ñ¼ÑÇŽ¾„­‹ jú�#wÿ3Çr
Þ=8¦ l°~ÓfÑýOW}Å-°Ÿ-%øæ7x±¬Ù‹yu.pì¨�¥T=ó{R5“4HÍÙ>Ùpó,‚.6‡PÌV ,Eðfw¬À"Ðtã�X2uÁ±hÁ»Ç@,Á¯ñ
ÿ\Ê¿¹8¬žáÃÊ6?Ü<[ðzJÕ3,üT
|)dGÎÞ:ˆIžÞAgXÊÙ®éÆþX2µñ˜8úqL¤‘öñKšúóëÜXÓ@G�»à5Kè“ê¨9_‰ð«…®›«±F	´ôï¥\	 ÿŸcp„‚e™Ì6'ˆ+|ƒ:/¯ÀÚîóv_ÏíÉ±Ž)�wþáÀ©?{åô€[üv±ø=G€%Í>œ<'ˆ:Ÿóš¦ˆÈ¦àÛùðÅ€¤ê�4“ðÓt
Å¨®ÿo�·E
º8o/ÜqeÔ9‚F/¿‹+Øo ®â¡]CH(£×¤éÆ‘ƒû7‹½ø‡U º¥½Îïù�r¡ÝëV¶ú±~N�<�ˆJÂ’†¤R:–®’ª9íû+šQ•Ì½±B`Ü<¯Èf¬„¸Í5øÍ~¡À5H(:Ú9„�„šÙÆ€þñW,ûÐÔ]Õ1Œÿp
Àòó½<þÛ.M·˜à—[í³‘RõÌ*‘§'ÀdLþlò25n-1g›¢¸ÿ­Á% iúåÇB„G'þ¡À)?|nE(¼­˜¹¿´Éƒ59¦¾¦H¨ˆH¥9¥êˆ+F�ÙïtÕ7zÚ÷×©ù+§Ù¸œåû3 K8–K(Æyé�aˆÊ¼‚°#4EŽ`fPÌ±ÍÀ}Û2	Dšnì¾ë¦%váÁõ›6‹ÌyŸZÔwh_jœ+xõº®µ €¡H�ùû3‚« X–ëQ’ÑA—7Ðçóˆ½„»�ñÕÇ?„Øpýý¡š9s¿É0ÌWí^o¹pÆ‚šœÕÎ‰à[+}¬„+ é’¦gÓ0L—@Ö)4ƒBÕ�LP5`%ñ,G rÅk,`¡”"h¹G-¢pJÃïßìË(·XJýÚãŸ]õ��?ÝÒK©TM{Ç«´TlÙX¯…< Ü¨2¦”FÐCšª¼¡ËÉíõ[i_×+Ç8ˆ±ã]¯ Ò$ß/ìØý�‹Ã¦y!,möe¶•|Í�é;ZM§N©�4Šdº`g²a��…‡gr”Q¶°Ô¸ù× ÁË£Á7*�ïô'ðøÞ°ußöïÛ€åD×¬j�7ë	:Ú�Pc»¦*oð÷„ßÍ?sÌRpŽw­X¿i³XÅµÿi·ês8af ›:B™‡ÜòñâªíñŠ™øvˆËd�"&kÐ)ªºÂW~��_ä rÄV ¦kQë.Œäó~{�a	á„„¡¡¡ª�cþê_	5¶SÃx8àÿ¦ýáæg�e.Ç»R”òõ["ÎYT›óG%	µh(/œÒJ
°eæGåâ
Â.ãnªaE6a?‘Aƒ/—Ì¶Â)¿y£=C$ñ²ŸéxE^vô~
<%}ß:§KHr�ªÜ3JiÔPåûkÞ»�)ƒB¼ëÀy¿ÞzãŽ|†Ÿ#ÀÆŽNœÊlK©:úb
$–.*kHÈ¥Mö¸¬•úlLG ˜¡=Ž >‘+ªD– Ù/ä¸3ƒBÆ:xl÷0ž~»’¬d^o¯ñ èá9]Ü‹¢8–�O0÷�+")1YÇ@BEXÒNH§4GÇÊ†¥”pÿ­;ÿç’ç§úÞO¼kÀ†ëïfÍùÏ±Wä¿ÖráÜ%uv¿”Ÿ_nÅW41YÏ˜÷N1ÝÜ Ù‰=ê½<Î&`£æÕ¹ pz¢2~ýü^´´5Ô¡ÎËW”�˜�R‰K$UG_BCOTF_$itÇuFÓœ+B�ír<|g�¡üê™D|W(€´ÉÿÇ|¢ÏnÕ/fî—üJVûb(fÈª=…šˆ"ž’AÔÉÌ¿W¥DÎ¾¼Ë \.x!PÁw b�)†l`ÁêN”�|%à´×¸ hvõ'Ç|_
>ßÍUüÕ è�)8‘qd ‚ž¤3‹Ë²
‚.ö²ÒQ¯ ÎûõÖË\÷Ãüâ�/�Ž«ÏøúÅV}Í00’*^´‘tŒ$•ŠVûbHÄ"ˆŽc¤¿R¸ƒ±”èŒ<!/B¬iBSC=¼¡:„ZÚá	Ô”?'Åþº]ƒZŸÉ7°àX4û…Ìß3ƒt
tŽH(‡låªeÝP.¦ä’cþ�qÅÀ¾¡ÆŒÎ°ìè€,!OÄûÝø�äÕ
à‚Û·}×Žå_ÚäÁyKê3+UJÕÑUrV}+œgÃ×tŠˆ¤UlæçÃøD4ŒÃýÃP#�ú'/BÅ¸¼hm›ÿÌ…¨ŸÙak%S €iA5úÅ%Pïát›î”È™=¬è‰ÕÐ$¥QÈšÍ Mw|ýâh¨R`8–”­g(‡¸b`÷@o÷Dq,!OxEæ;OaõãòÅL#•
`Ãõ÷‡::þ7?�Ÿ#ÀY‹ê°ªÍŸÙÖ•VýRßPB³à«ŠŒ�á’ƒ]8Ü?C.4‹“]{@õÊ	¬ñ‚°Úfw eÁr[FCõ¥€uOí”À¬�˜£`‡*ªUÙr•6ÿEŽÀ'rf£Ô¬š§è‰*ØÑ—ÀÞÁ$ÊqÿÁQ§ :>wóÜãÖžò‡ü_ÈÅáâå“ßŽá/eî�ÕÔWƒ½ÝéïEÏÀ`Ùý•È ÔÈÀ”ÞCÎÂ‚«Ñ4yÙæ €é4ú„œmÙ®Àî�ä¸ x–�·Â.ê"GàâXø]\E®ƒ¤êx«?åÈ*`	yÂM”¯¾9‚£J´žÿ•uKO9û/¾†¶n­ZÖ�Ia�Jº£JÎ{­VÙùˆË†SzE°ªS |dŸ#¡Ï†¡iHuï™ê[	 àƒ˜¿t%‚s––Ý×Ž´¬€½åãÿNàY°d|�¤_4;UB$îêObkOýÑ2<†®}ÛüŸwSÔà¨Q /žô¾ÿyð�|á_×ÀûÔfþÎ7ù5ÃÀ@\-0÷ÍÀ`R«ˆÕOÄ"èîîÁáCAuÕñûò‘ìÙªN�|”Ä¡˜µj=:Þ™QnˆI³/7DøDû†Rã>– ~±rö¿ü"‹:ç˜;80œÂË‡£%¥4ÊRýÊW¿ºþ®ªžìáèP „|xÓ·îÿmhFGfG€óŽ«Çª6?T�BÓ‰È9&±U(�PâÝ½ýcZí‹A�‡¡÷LáEâÐ €«yÖ^òEðþâ‘ƒ|W€cLËàp¤P™Y„«jPèEB«lVGc�ÀVlþ;Ç2ºL«À	gp`8…ç÷—tÞ-nÁ´W „å>µéßî¾5ÛLuq.]ÙˆÅ @DÒp(,gºbR5Ð“ùùªN1Øu»öî·%óÆƒéäX
  Ä`=V}øjøêš‹îŸop0œÔ i$Í¬lKÖcÐÅ‚#€È³9ÅKãu	
?‡C�›ud¼Õ—ÀK†m¯‡ã8øx€eØ¯¥~ÿÃ­)ÆÓ[ríi7üî{ÙÂrqøØ	ÍhIPICwLÉtç)fò÷ÇÄ4çP·™_©þÎªÄÿÇ}½¦‚cD9	¡¶k7¢Çc»>Ð–ÊöJ(ž¡ðöæ¿¥<<7ÏB¬ÒP§î�jP¼t(Š7�„GÏ‰ãrJ¦ãÉÔv/«_~4ZÓV–¿aý?ßz}Ãâ2Û¼<>vB3êÓ)½ƒI5Ó™Æ0(FRZN§Àùª?Y‚Ÿù¼iâd[ Z®Äq}ÉvŽ ­A ³QÉÎ*d zxÆñ0«n¡Z.ƒ[`Ñä-¯Â)Ïì4:Ã2ãw‹¯³ÐÁ2ì×ÿìªïŒû¤&ÓR–¿aí—x}ëª™m­ŸZÓ’ùÒ{b
†“*†d„?¿\×‰¯o™ú;wížÁÏF¢sç¤~^6¨aZLRÿÁLÙ-ÕÔŒ»³âÂÏ#[ùf£5`æôÇôÅÇÏ‚®±%ød1�×2pjôD<{`)Õ~EIJÊžpÏÅGK¤`Ú) Âò7œð™o]?óÄ³3ÛÚC.|ì„fxyŠAÑS2	,†AÑŸP!§É?M7�PtôÆÕ²¡½žÎâã;…<Ü-žÔÏ¤†CMMF¢º]N‚=Xÿéëm#Í>:ö•Oÿ-‡Ræ%pqB.vÜ‘„ ‹C½Ï¾˜)àâÀ³IÅÀcï�~hæ‰~éÑ�I86Õ;A ,ÃÒ‹¿|ýœM—d¶Í­uá“kZàæ
…_Õ)úb2²9š„¢£§ŒðaÏëÇ¡#Ý“¾êç\/a %"“òYÔ0`(IªÐÑ{CX¬èçöƒ=`xÁÈ	xƒuÄÛÐZx,tG%tüë‡‹cÁŽ£rÐ‚fPÄQIƒf .ž3QÖŒ$5p�+K÷¹y6ó7Ï,¨w£ÎËãHDB~.Cˆ„¹|ÁyŸKíÿË-/Œûâ&ÓGríâÓÿé¿~èË™MóëÜøØê�bPtŽH™Ìµ¤b /®ÂÈ2bâ2†S:B@)E¾‘¦*2ìÜŽÝ;ßBR™ütÜ|0œ`Z tb{šCN>¨ç�uyÀð‚ù#¸Àº¼`<A†„ÐœãFïŸnæ÷G$£*Â ž*þä\+ I30’Ò`ÐôÀ”1(˜¸b–|»9~_pž„Ô{y,lð /®ÚÌ:ÅéË?ô…¹�±Ô#�¶NËöÐÓÃ äÃ­+Nþíš/ÿ(crÎ­uáãyÂo1ûQIÃH*g@zc
d=?Ùg´¥§óÀ”øùå0‘©ÁÅÌ}Îë	€duæ<SðEOÎ6c[Î{}ÁZTÕ2ÿË!äâPëáÆR9‚9µnÔ¸90E‰aP¼x(Š—:£¶¯Ç“©íû�éØ«pê aÎt¬|ää¯þ"zj¹ðéµÎ„?¥êè�+(–Ò>8<Œ½[_Á`lüÙj�‰Ê	(&ü|°¬8:ÚŒ°<„`}Žà–‡PÛ&¯'_¨®±è�± ö¿¨TX	D€é´„’ç»o0…Gß²%5ƒ³jbÓtNLê•C–_&Ö¶ü~Ý¿“þfŸêË~Ã J¨9ÂKçüÛ	¿fPŒÛ�Œ`(9õæ~10Â‹ã?Pœ
? ˆµ-9ÂÀVø=^_U…Ÿgè¤
? „%�#’ã,Ðì0cJÕ±o(…¨¤Á(’ÙØQïÆeÇ7£Î[ØÌ”cH­Î{Ÿ<õg¯œ>©]SÆN˜Iuõ¹S¿~k] ÕläÓàåñ©5-ð‹l�ð[a>‘”Š�"‚•4lëÄ`$NÃ‚uû¡'"îk�ýfè©êÔ €¡$…ß_6ÝMÈ‚XÛFpåîh ë*Lry¼à¸ê™ëÕ"ÿ*¾70sC’ªŽe QBA—iT’�˜lŽxó	,ˆ�%!rŽkòb0¡b$/•˜!ÄÍzyÝÆ+öw?öëm“~ñ6˜€ñk©¦þyõç¿Ódeùy;¡AWVøâ2‹ÿÁÁ˜ñú¾n¤¤ÑÌLVô@l¬Z»úªƒuùÆ�4M)~Fp¬òœ'P°�°<8oÀö¸¢X]+e²Wÿ|Hš�î¨Œ�„š™ÄdÁ/²¶Âo!¦80,�É³ç-©Ãê™þ‚×t°ðz½wž~Ëÿ<¥7 �)Q F2rÇâ3>¼ÂŠõ»8&“ág…úŠ	oL±íe¯h:¶ìÅÁ¾Ûkâ<ˆÓS	0&ouÌP_!×Áês? à¼¡Â{d³0C5Á3Ó§9ªå$Ò±d·ÀEµƒjPt†%D‹¸CpÊÜ6Î³/®R|{:(�IW „åo,\û�…ÿôÿ2R|éÊF´ÍÆŠóÛ	ÿ‘°dÛÁ&šHâµ}ÝN(%?›Ô�ó×a:‚óÆ}Cµ~]¡ð{¶C7˜<~À‚ÈUwµæÙé} �ÝQ1Yƒ§Âôâî¨‚¡„Z”8¾Í‡Ž«·}m:(�ÉU „|XÔ\¿áËßƒî;wq]¦ª¯§ˆðkº�#a© Ì¤Mþƒƒ™LÀrp5Îr<rj2ÁûB ìØ}lj¦?a¹3@ ¤Ý„"“xN@51Õæ¿8HÅÁá]’²1�PÑ•K’ƒ-·� Lµ˜4@X~(½eõç¾“©9_×ÀúÙ¦0&Í¼};á/ã/eò—‚«±ÝV0¦¬{ì\€ÝêÏy‚«?ayÛkgÆ8†«RL'ó?¾t
±¤Qì–—+‹Å‡#JQ%0«FÄEKë¦�˜°~Óf‘êÚ]Ïû¬ß*0™[ëÂ9‹Ms<"�VñÅ½¬ð§To,kòay¸[:ªîÛŽcuìV ö«3ŸpÕ%ùŠaº™ÿ€I@çãHÄ4í+AJÕq`X²1 m!WI%pÂ÷ž¿|²¯}RÀóOÞyK`áš‹/øœ˜	—®h„À$TÝ1S�³“|Š	4‘Ä›ûsYþ±€°ü´‹°.ï˜Ü »ÕŸÜ«?P\ÐÇ:ˆ³RL7óß+ï,<�PÑ–sf”ƒjE°Æ ¼^ï�“�'0ñ
€�óÞÀæuŸûŽg8|ôø¦L¸¯'j
rR1r’|ì„¿R¿¦cd€ó•æ‘�b«?[ÄÅ)jŒƒpŠéfþ»8¦l‹°¤¢ãHDªˆp¢Šƒ*eï9å‡Ï­˜¬{0¡
€pÂLPzËÊ+¾™i3uÖ¢ºãoÅúU�æ4ò°#üöt�Éß/>P¡¦yüªŠ…âŠ�EÂPE )Jô· ml®V>¦“ùÏS8�¤QŽÈUU³jD[%`enüé–öÉ¸¦ Ò~ÿoÖœã·âýK›<Ò¯'+Öß5çóW~Í ØÓ=Œ®‘êeÊåC¨m�6‘�JSƒíŠ›ËÙšÿŒàvrÈ	ÁT¤þƒÕH¤¨ºIVÒï°œè¨wãôù…Ç�Ú¨¤ÿeÃõ÷‡&ú^L˜xá™ßþ‹+TòºÍ_`úý.k`’~ÃI5ÓÌCK—–Äåœ8¿fP¼ÝÙ7¡Âoa:Ex¿³Š»¢äo/èÅVùrdh5\®é´úW*üÙè©,B`)�bÑ�å­>¬k/$}÷²d¨å¾‰¾¢ Ë/cþmåÇ®Ï„ü.^Þ /ÏdH?†!Ii™‡+’Rs2ü,á+Ó?†sž6‘�ñ¦3|é¸=ÕÔÜ]…¡g¼«QB=]V;Æ¿R‰(+�R!Âg°¨±pññ¸„÷Mtx°êjyý¦Íbçþ7®?áÌæ¥ç
 °±£kfú¡]5Kàc’–SØ3ÙÂoÁ*Ò¢Õéÿ?öó``¨JÙá!TW, ªk ¬ ªÊÐ¥$ôTZ"->ªëÐ’1è©(´d$ó£§â Ðâ#™=‡.%@U	†œëò‚c	Sù#cšÿSZx
 4ã_)¢²G¥æ3]¬ˆˆ³çÀÁáyõ:ÅésÎùÔß>tëþ‰¸'UWË„åoà\žëÏüÎ_ÀûkÐìãñÅ“f@`zb
Â’U§™Ñ]ÖäÞì5ÂŸ5:yàÐ”}>P¾k05èRZ2šÓÌ0ËyíX}Þ_g›lDX®ÆÒœ“PÛš‰ –‡È0œ ·K,k5MvÝ¿\ã˜ô«3‚BE.EÈÍåŒWÏFTÒp÷ë½ý4ƒPWMDC‘ªÞËô_vÉUàý5àpéÊ&ADÒ2™~é§éúãÓKø�é°K¦†CS Ë	èRòÀaè‰HASÓJCzNL|šå"P]…$+H&âÂ`/â‘a$qh6½ß­Â˜î@%Ä`8¥- 
¸8œ¿Ä>2Wð¿qþU½+ÔÐêí8žÌÞx1 `cG-~Ša†ùòI¿ÞØh3�é"ü¦Cd€uû2B¯%#Ð¥%5öñâEÌw«Ex)P­´;b)„ðP?†††�LÄAuuÊcÿ•„ûÆŠÎ‘Êòº£JÑRâ¶�ëç„
¶OPµ;CXîS ÆÉ'lþ ³³Ï)&h•÷Æ=CúÄåœpßt~î–Ž)‹šÂò¡ÏG1%0–ó%“³ÂÛA—�·T£ºš±"±"’^46‘K¸o¬8©,c°'*½'«gøÐ^ã*Ø®øvµ“„ª¢ O°–êÚ.>ã#°x~hycÆô�¥ý~+Ó/–E f’Ït~“04†¦™ä›&ƒÝEÍyRåæ¦åÜ€±FdÊb$žB×Há„4©Š@t8¸PuŠ#çsTÃäÁì"CpÎ¢:¸ùB×)¡³w­ß´¹j…UQ F2úMÞlšûÁ« ˜U~íA1cúÀPÒü_ÓôgeýŒ“ç+ËÃÕÒ1þ•@¶Ðç›Úœ¯z]xË�C9Tb …ùá”†®‘ú#É	oË^MÆß)$�æÚå�Rõ‚¶a<ƒ3ö®ðyÜË’g}úÆj�ó¸ aùe,Ç]½ì’« z<ð
,Þ¿À|híLÿÞØèêŽH’Þ[m°¢®–yU?n¶àC±¤ MÃŠlŒ¯5½!U¦¨‹YNIÕ@Tš0Eà$Ç¢•´ŠªjQ> £Þ�e-…Q›�Ïõµj¹ã>ª«ÿåjšMÚO¾À €3ÔÀË3ˆHŠžcúgûýQIÃ;Gú«q“Î¨ZdÀ‰à[`8~RRx�œ‹Q�Ò!,_¶Âp"ÁD2þN1�P+Š”j&²±#”3�ÙÍx]"BÁàmÕ8×ñÝ)Âœ	àË.¹
Ç3í!N�[“¹	Ù!¿”ªgü~EÓñÖ¡©ŸŒ[)„ÚÖq·s*øÙ¨´B°JEœ·Y•ð&ÙŠ`<Ád0þNÑuN
ªéè˜x–àýjÁ±Lz6¡ÉkP�UÕˆ
ŒïnQú?�yÇÃšâ{áR3†™Pƒ¸¢C£$'Þ¯»ŽT­¤w²ájœ5&¦ÝZõÇ»F!åXûŠÏÏ¡p;åÆÒ_ ©²°â{4‰Œ¿¨:Íô¹p‚pJ+pƒ‚g–4ypB[¡+àåñßã­» äÃ ]±âbs–ßÒ&æÖš¦ª•è ê"G0’R3ñþ½#Ó–ñwŠJ"•˜ûÅÀp<8‡9	¥&—Š÷SÃp¤Tœð ã�š„SŽ„+‹L'á·�TôŠø€|WÀïâ2dæ©!¸óš³ê„c|n×ŒçÇ® (ý�ÀÂµhX|8œ—Î`êM›üé¹ñ²F!kôÇ•I©ì›h8�š6.ÁÏçåžÃVØb½€t.€ƒPŸ aSMÓ[Õ(ð™($TÇIB–+À3!—Cdz'Ïµq	sÅxº�Mòa +.ü< à„™4ûE¤TIÕ@BÑ‘Ru¨éÿ\ƒ¶šêÁ˜J”ŠTcÕÏç	Œ»kO9wâ¢”«tBþU‚pJ+ÉLE¸¯RtG�=å®cE‹6cÇnñÛc=·±)€¼Õßjî9˜Ì�ùÆÕLnxRÑÁ³3‚X2«µÞê¶šž
Øµ«æª_øyÎÜ€bdÕµ’n€S–_O„‹¾6IS7�)˜Êp_%�4ZÒà¿ÀÀ+š–Œ%?vØ4/T°�‚¬:ï×[/Ë¹U® òVÿg9sÅ×)†“*T�BRuDÒ\@B5�­Àý"‹ùmX0£±êC'&ÙÃF&Rø�Üh 7ÆU––È¨8‘ÍEû£RÆ%˜NŒ¿sÜ<¯È‚Í*—NªFÑ¦í!:êlÂÂ„Œ)9¨ò;Hñ5ß¬ã2«ÿûš‰*ƒIjº§?`¶ü �R¨ºýªSãáqÜ¬–£Þ-p5Îaù	~ %Sƒ³Q*M¸\��R$bæEÜ€ÉH™§4„Ò¤¦ùV½ñÑ{ææY„Ü\Ñ°”ÅpêÜBK�‚Ì‹P™ Ì™ ]±øìÍ Lß?(rˆÈf®8-üá¬N?I¥tö™åßÑzÔºjt| nRzë[©Á´„°i%»û”N¸qª´s&«pJ‹�¸Õ8ºBÉIÅäÈüSÖòUÓš¶C­‡Çr›Arc¥u•Z ßpÕ4¢mõé€LÊoTÒ 4ó¿Eüå›þ¥À³óÛ°dV3Ü®ÉR1^P]…`öÛw5Ì˜ðÏtÒ/°T8¯\‡_Ç<@ž0YS.Ñ\$Rª™w4)�À".k9æ~)ô'Ô¢×·¶½pò0™[{Ù5WrNŽ€9ÚË8yþ—ƒáxfy‹õÞvõJ›þ¥àY,o¯Çì¦c:óTW¡%¢¹÷ˆ!6Ll7g+5x¬ª«¥‰@%å(€êjŽ˜àásI?M7Ð9"Aªp–ßdÃÅ\8†@3€þ
„ìrqE­€JÎÍ± ºv-ËñtöÉ  6u„ ä®þ’:šøPÎô/‡¦ ‡™®ü€�ð[`]>µ­úùXÌä.™¤k%‰@Ày¶Ÿ•TíÐŸí5sØ"ŸÑ‘§¥àYSð.—¯LjÐ.ŽCÉÊ­€J¸ G
€ñkzaûúóï¯A{È…¹µîóo%ý¥{Ê:ulú—»�3‚X6§eÚð¥„ßçU<à£8™!XÊ×/Gê«þ´¤y&zõç8î2¤ßtR<KàØ’çÜ—p^üTÊ
XbÓM„\ãôØŽ€‘Š~€nºÕ—ÅBZÌJÕ!©:b²�šWžÉ„§’p"ü„ÚVÛ1ÜÕ€•\jÕÕKX†Z†¨ èGKD'|õ/'üº"SOZ‚Ï•ÉOÈ&ÊË¡”°Æf¦ Yå´\Ø™@éç½móœ³^�Å	3™ÕßÒNÖê/M`‘O�‡ŸR~À©ð[fMXd€ó…Jæ”$ÕTÙ>€N¯u¢CŸ~we÷oªˆÁl?ß)âÎï]1+ ÁËc–Mû°` àÈ
(« ^<	@ÇÜ“Ï ¼7íwDò|kõñW)¦‚°ÌÝJ1Q‘Î Jô	7PAó'¹c�ÅøWM7*¬ñ¢˜ŸïQÙplë$ ï±©da\æ¤R°¬0TåÓ `‘'Î0³•bé“²ü™ñ• “?0»~Âù«÷þX0‘‘¾Lo‚’õÿeâýN¢V£’±*ÇRÈgü+�"¬¼¤¸âs,ãç;A©´ßl¨-šØQçFÈ�Ò	Çpœpi¹ã–T ù×ºòðþÌ¯s£ÞÃgrþGRæêŸRÌÕ
¿‚Ä	M+Öåä¸kï'*2ÀùjJ&ß”äLü-°fR¼ªý	<<S”ñwŠ”Z\`Æ‹±˜ûÅNU(‘x|k¡àØÏ–;fI@åÄ… üm'~ €9Ã0ÍëæZ¾ÿd®þv¨ñðX9·³›jªæƒP]…Qa#Ìbà¼!ðÁ†ª^3+ºÁy‹•ä”TÙ¤­DÑO~›2-©Î}*î«C	µ¢~å`	þXÌý’ç™tvŽªAs†çfÃn¶ ™[®T¸´0Œ+XŽ§�+N…‹cp\“‘ôÍ÷ý§bõ·CSÐÃßÑ:n~ Æß)ø@CÕ#B¨©èkå|órn€© í�‘?i¸T… S8	÷UŠ¾¸:nRÐ
ëU[ð-Tb©D${àX,l(ä„ü.¡dN@Q@8a&Ë²ëk�?=,mòÂÍ³H)zA³Ï©^ýóQ�²ãJ[`;Eµ#e­Š!=]N”�¨ñpÁ¶bMJõqZÕ~ã!�†õÆÍ(Îòç#*kEÚqM…‹ã²RõE ÕÕKtM%³ßcöû[•f“ªaNz1("’6­Vÿ|XeÇ•†«á÷—‚«aFÕ” Ãñj[Š¾®Jã‹Ø‘�L]�ŒýžŒ�ñwŠ±ðÕôó� ’ÖaÅÜ€Ž:·mÛ°Rõ%\ r~¶ù¿¬Ù—“øci¬é¶úÛ¡’°a5ýþb œ¡¦iüJ£œP* 'ce�ŸÍ”kQ>+`<Œ¿S%TG™‚åç—ƒ¬Óª„í¸ �c>Xl[Àx‚µ,Ë®oZzbÆüÌÖÞ–ö‰HÓË÷/§eÇeúç£š‘�rn@©h€.ÅÊ'e…A™2]¥V@5§N�|L´ŸïNC‚IÕ(ê,i*\ä4M»`Ãõ÷‡ìö·U TN\¨k*i^µ€iþ[™QIC\1 éÆ„fýMJ•O´éŸ�jEÊ¹e:ˆãk‰°ã%N­€j2þNPÌ˜?ß	*‰XÄŠX­~1W‰é„c‚³æ|Àn{ kç@ýò“Á`^�‰´ÖQuŠHJ�´¬¿‰B~Ùñd˜þvàU)*eM”s´d¤¬P‰e¤FÊ*�‰`ü�`(«Æ~²ýür¨„)±ß¼ºÂÔ`
Ø†@š1Üàm›_]3æ7¤ÙU7§ü1Y?*W;Xü@]`b
wœ@¨m7)(Ö4•L
Ò¥WårV +º¡Å†ŸO¹¼€©~	EŸ?ß	œZªA‹º
Ÿ·À�c·o�xþ©»6ð·/] XÜ8ZöWt$d“0Œ£wõ·ƒ×ÄÌŽùà¼åKm'ã�šZ2)h<V€Uî«K‰Š:³&’ñ/Žeàæ	T½ú«ÕBT6gsZbA4 ¥uvIA…. ¥§@pÉI €¥Í¾ó$¥V­ÞºÀòy–E{[+šÚçÀãšÜ‡t¬-Åt9-…¡¤JFÌ}K'³XqÔ÷WFúŸ›jc1¸DaJZy»ybFÒ³õFnS�˜âLÄ‹Dàx† Ý¦B0äßŸ¿ÍŽ8 æ-GÈÅ¡ÞÃgÌI5Ç|+ÚôÔžcAR5
†Nx]"šÛç¢©¥eÂkÝ³QIá�%øÙÃ>ÑSº6 Œ %#9+<5Œâ�jrEƒ²­€É÷åÃÍ“œ¡šRÚôµœº¥¢µ…
À ¦lg#G0ž`-ËqË½móÁûk21EËü·4Ó»iõO”Ècðúƒ˜1k6|µõ“v>¬ËW22`hj�à[ S6¿ \åžÉüÎð¢mØÏj„êÊH/€É÷(˜¦k‡éjXS´� Øó;»¶0bCAVå‡s€‘Š­Ñ5•Xþÿ‚z·Ùô3mþÇeò»HúíVÿ|ð,‹ÆúzÌž5kÒø»È€%øåºõðÁÆ’¯ë‰Hé2a%•Yá³MÿlPMv¬¨&ƒ×S“*ü–¹_ÓÙ
°¸¶rHq¼[P" ¤©muöß¹w)íÿûæ®`j+÷ÿÝhþ'*ÈbdD·ÉL’[�ÝRÌÐTÇmºÊå å¹ ->\6æ¯%ÂŽ	AIžœiÐÅÌýR˜®V@Ä¡(¥ÀæÔ’Êù<@¾š< jŸñÿUƒ"©ˆ)ÆQ•ùWªN+?mÁëbÎÜ'¶ó/ 5Í04Õñ°ŽÌûj[�Ó�ÊY€³!NÂ‚ŒËCS!ÙUc|©iº¨¥.N¥Â�3Båy€ŒX¿i³ÈrÜrÞ„¯®í5®Lø/¥êˆË¦IÓÕª`¼uâõ¡ fvÌŸP~@—S‚ Leó[XÑ6Pú¼Jå0¼z2Zv…×¥DIN�qù2ó’‰ô*gY:ñó� ,M? ëÔq8°˜%;3Xh0T_‘]˜y²þþÜ='èšJæ›ÍDçÕ¹ ¤¨}×™ÿ©*$2YüÀD„µDTWA8b“Þî¦9%­ CNÚ–
3‚;£pœäõ«‘[E‘-ü™}+´dJ^ŸC?ß	b²mNr,ÅØ¥3ç}j‘õwæš² üí‹˜SHSŠY3�˜fM?Æ‹˜CÿÊ)ª6´„ß#zÀÊ¦ëfƒuûÀ”'.Gs\Âr`¸QEFuÍ¶@>òó'ÚN.ª†0s¿¦cUkRuö}—âZ…SR#Ë­ßGU(Å2 ´u  ZüTƒBÒL+àÝdþOÔ 	‹�[�/ü8o ¼/TÑ±<m2Ó{ŠÞ¨+Àð…ÄŸžŒ–�ûk‰pfÂ‰`Äâb<î¼Ûp6&Jð3çUÅÖaÕB5x€¶À¨0°íY¼ô“«ÿàzøÖ{­mÙjz% øg.Dƒ—‡›g¡êŠ™$ëïó¬ä_%h¬¯GMMzzû*j+¦Kq[á·À*Š°n¸`#Œd(2½Çt<`�E¹->R4$˜¹¯Ñ!°3J
?`F I„àr6I˜c™ª™ú¥`‘�Ó©>ÀâœU4¼Pxî!7‡Þ—ÁÛÞŠD×ÞïôÚlÇŽF	@ 4·M>>Sû/¥Í‹w‹ù?Yã£*M+¦šìH°…`CE£¸¼³—AO•núQªk`ºJ™¸?ÕdÇaÁdÂ™PM?ß	œúÜ“	§EwrÞs�EñûßÞ…½p-^¿õ›4Ñ½÷« ½6ÿ} ¼ðÌoP]%ÞÆ™`8ž™2	@Õ ™ðß»“=?ÎëámŸ‹D,‚þ�AÛªÉŽ{ë[¤ 4Ðéh†ãái[€TßA0®ÂfŒèáxèÑþ’V€žŒAãø¢s	Y—z2
Öå+kš
EJµÜ<™0S¿ŠŽ:Ïä%,9='¯Xþ^XŠ"‹â¡_ý ÿ{÷o �ô§_%? èMvïc €ÚR ¶ÎP>ð‰fE4ùx„\x‡óÍ§&Ãü/†RiÅ•v!ª42 ¶.€Gí¢i©i*t©¸¥@ZÜ>ù‡uy3V‰uÖ()ØV­°ÞX¡êtÚE‡¡À”ªãÅîÂ•ÿt6~ñó›é¨ð ½À^r­9ëc Ëß@uõúÅg|‹?úüÛûf ö¥°µ;Ÿhß¼!¥êP4)�BÖt$}Z»
1Y¯z`,Pu=ÃèR¼¢aœÙÐQÇghZOø¥?¶°5£	L¬Mù0ï¯+ï�@XbÝè1'ð| ¬ƒ&'¯._Ë€gè”	~6¼<.nüª8¦°¾ß*¨âY’ÞÇ\�—µŒ~oC	ÑîèéïÇ›o¿ƒ÷BMÅ¡�ô á®ÿåìS/þÙ³W�¼• ªk³ÀÝ: Pïáq8"!¥êÐ))ZÁåæÍVJÙ�‘¦H©ƒšaDÝ$W¦ƒbÐ¦I#‹HÄ¼è>°gÌÇá¼Gî5†iZ¼¤t®c}µ¶Â jl„åsÂ�9ÇJ‡y_ÈVø“´ËÈ‡$+¨©!ÓÊ¢ŒËÚ´Q °Ä”¿|a·CJÑáN�u^uó`ÎüpÏ^�è;9×gRŠVàCÖ•® !Ôoú ªN“4°„‚«àâX~kÿ,JÓ$ŠnDL¨Æ¤·«FòO5¡î–yPcCf-½ò¹“È€å×{Ú—ÎÙúÔs�µ'—:¦)ÉDÁº¼J¬òjd dM+z@Xñ”‚Ÿ³^ƒ“�©zF,açX,1Ï�ÉºÿœƒlPÕ °»“v¼†‹cZ�L � ž†hòñ™ƒI…P%íÌ±‚n>3B.,lð`i³unÌŠ¨÷šÍÙ	*Ÿ*ß¿øùèH¤Ì�¼¿î–Ž¢[9ˆu­Ž"Çµ´ŸåÎèî-}¥zöiš
-1R2ñH—%–!'m§1ÎÌœo"%CÕ§Þ-ËÆD†¼9Y¯ÀÂ+°ˆBnÎt³<KÀ0LŽðK+‹%ÙU*æ›çã	ÖÉˆ ¼ÁZÔºùQß^5 pkžM–1Ùì9ÄS¹r„å!6Ì¯$!uWÌˆµ-�‡{ÊZºAÎ%,w]bßë·z;Ž/š¹hUrÞšK€ð"¨¡C‰–$#µd4ã
0Âò¶ŠjºY’F!ØxŠ¦#,é�4³ŒÜ�SPSQˆ‚�gôûðšþºµ¢È¬êŒí*^~ÅÓ¨³UQ)òŒ\x†ä$‰S·áúûC•“m Àr<åý5¤ÆÍB1(dÍ€¤é¨á'?,RÊ�H©æyUêFLÿÈ]ýóÁ¸[æAéuLð&›/ë!÷”Ü�á¸–™ç~auçý?ù¾tø­kÜsVÝW—“`W)HøÑ4_]NBK„‹v5¦š
->Wã¬’J"%Ãç¦	˜‹…e‹iERÑÑ•0œ7ÄS•d¨±8 +¯¡nŽ % bÁüy<}çÆ|>fªoy9,51àâ
æÐšºY5ô6 pÕ6 ¨ñ™@:%ùÿŽeàwqcr#¦“û¯¨åÓN…šfxf,rÜ‹­(ÊðŸi=ÿË÷IáÁç”#;Kî«Æ†33³…?s-Ñ¡¢VG%uùÑTÂ²£’†þ˜Œ¸¬9VN‰x;wíÆƒ�<†×wìªŠë©9<F©Ï
ˆ…rÌ®F†0Ì `ÓNÐÅBÓ$U#Ã<Nw¸yA7�f¿€Y5n,nòaQƒ³B.´DøEŒœp¤$gÃ*	ËÃÝ2¯¢	Bœ7àˆK`ö;ŒÛA¢ÿð>¥ï@É}ÕØ0Ãeõó­Âñ`=�ŒòrÒ=h:qªNÑWrêx–@ å­H+"C5;wíÆÿ=ú4’69•@q˜›PJøÄÂï.àš€Ì  ŸÏÌó
,’ªÉÔO'¡©–µPçá1´ûUxâ]XÕêÅ’F:êÜh¹¹IWrª®CrXåe�÷×UdðÁ†²ûBNn9õÒK	Ë0Ñµ'VJ	po¶/ÒDÄÐTh‰0Ç›�Ió>ÛÌu(�nL�À³nÎüñ‹,¼<:êÜ.#GP–£šZ�é©'£¸ïþqpïî1Ÿ£aÐV‚S~¡ðÜSªÑÊQ]ó€2- Ï ©H©ú„€“…®¯ fÏ[· ¸‘ËŒªºYñ˜Ru$U#3þ|"0Ö‡Ü²œrb]ky2‘s]wÊu÷-yæß/¼Dê;ø0 "4Í)Ø�²< kP#ýE­]NA`ù¢V‚€Ø0«ä9'Rò„‘�™8:I“rEr[j=XBÐt¡;"å¼æu‰èÝ¿Ñ=¯Aê;�©¤jšà�¹ØöÞX•’O>ù>àõ¡±¥­âsgªNáD5Ý°uW\6‰|^‘mà Ô€K4ÓÝ‹ˆlF¼Âô eÆ‹½/>ÉU‹÷~ä‹¶¯ó,AÈÍe”‚aÐ)ABÑÍYˆ²Vµøðxëá…šfpÞ ¤þÎ²Œ¿l(`8®åÀÖ'¿j|V×éG¥¾ƒ¿Až`³ÚŒÓ´Èn<Êp|Ž©_¬+±ÙÔ4®L�‚„$Ãëß”$ž%eÝu>ÃÜ‹,A½—Ç`B…F�Ã/>œ®¨+ž¸Å{ƒ·ÁåAXºœÊIó~èáGðO}ž`Í¸®¯ŠåØeòr™Ë ´ Ñ E3 èÆ´" Ç
%6Œý»v oÇ‹Ôi}5Ã0¥Ð^ãÂ’fVµz±°Ám;|±TjþÛžŸàq”7à¤fÀ$¿²”þN×µÿ—èÚËàlH<C‘ ÅGÀp<Ø<s¿\Z³]^@>œò#@¡ùn)q¯ÀBäÙŠ„ß/0óÜA¿ÈAÐ“xéû_À+?ÿç’Â j"‚�—Â¡ßý’=ûrÆª¦}êo��iª–:Î�`/Ë Á3Z)&O³˜ùxðêßŸ èšJúw½2æã0ŸÈ™!žÏ˜B5I.+o AH8¾ld€aØï  (½‰°ü�– EBwTWÍ¨€�¹_ª�˜¡©¶Ó‚²!©FÁ}âY’v;A¯TØóÁ33‚…4cC½øÓ7?Šî7Ÿ­èxj"‚®©ÿ`Á}ëê<ˆÃ;^®ø�ö,æºÚYó.Žie@i  x·®´“!iÅ’Ž>~ëÕÌï{þþhÕŽ[L!4xù‚¹lœ„ÿ*…•EX*ÎÎy%• !ää¶³?û  ºzƒ¥R�oå^³àëöƒ°<Ôè íjohjÉnÁå:Ž‡¢j‚>–UÝ)fÔ¸Y4ûG•¹N)þú_Ÿ-»ê—ÂÐÿG-…¨ËI(á~hñaüý™§*¶œ&³ìëyˆ‡hfé·@JÕ�ê@6Þxî‰ÌïÝo�Ý(K!X.ÃòfÕ¸rÈFe‚,+'.AÙð çºÎšCuõ€|?Ñµ©}¯�°\Fð³¡F‡m#¥úZ\ `
;áxð.wæ‡ã8ÄULˆ C�Û¼.GPçáÐì°íÿnÁþ];Æu\]SÉÈ+†2Ò5ÒŸábF"tî»bì¢]ŠAÛ >À¬éæYÅ �T9ú5@Oç~$úgþÞ¿kÇ¸c²NÁ§I¤Ž:7VµzÑQç†G‹Â5An2©Ä%VúRáÁ!˜½–°ü�‰þÃH¾³Åö=ÔÐŠšü–Àp|æ‡uùÀº| º–vŽ³�„S“Ó£¯ÎÃÃ•·ÚÉ0žº÷—U9¾4Ò_à
 À[Û¶Vtœñf²«èe dh^KIHw”$•Â®—Ÿ)ØvxÛß'ý<†A@d�|þ7XÛÑ„U³0«ÞgL„2jšK-ÕR,CZ[î@ÿaÄw<mM04jlØ¼Î,a74¬ËgvNÿdŽ«©PÊôJtÚw¼°Ë�{áÑ –¤Z	¤Ãolë:¸oLd`9³2‹úËñÀŠ7˜’ÎÕÆÛ/=U°íÍ-/LÉ¹Þñ2Þxéy f^öìz?3QÊ€ó‹òå"B0�l%Ýö¤9«€1Û‡³¢''L˜/ìZ	Ö¿\ƒ˜¤BŸ„î<-~.žÍi¼i÷Ü8ÅG/»O?ý4^yå|ñKW0­ ªk™C‘ �«ž’DŽ©³µ¿Tƒõ
@ÓìÛöjÁöÎ7žƒa“Nrvíx‰®=PÂ}B£±ò€‹CÀågf×û1”T1Ž¡;ê<V/ õ* ë,%`W8d‚]ßò3kÕÕ@HLéÿ¶=‰Ð{ÎáscõjlØ¬øËZéÕèPéB!M+ê f'»RÖj¢Æ#ä¸ :îÚ>¦c}ô²Ëp÷]weþ>á„  ?ýÉ Îô_´Ð?Ð�Ù˜�;@7(]Ss^Ñtš^Y�éˆðî-¶f\¢ÿ0ûzÆpÄñaï‹�  zß(¾ºÔyxÌo­ÅIš1¿¥^÷øbËÃÕ8ËÖï/Y8Ä¹®ËïJo!_•Fú1ôâaØô1´[ÕKYz²ô
8n€�`äöÓsŽOêSÛ>ûé�§/V×Ð˜ñæØ�eHÁpP¨…ñ.èüâß·}­”N’‘‘£üÆo”ÝŸcÌTÔfÕbMG#ZcWV
±] Xd€á¸–ïßüß/¤•€šˆØ*]NAÏó%&—›™0]Gw¿›À°O³ÃËD�S…oW ãññÆ‚lâ±gës½×Í³9VÁX¹±a–­°‹ä‚£/”V!hA—S Zq—F•Šgjºy‚•€]âŒ«¦qGnýÕ¯
¶Ýrëmæ/,:Ž4ð‰pÉuƒæZ Ó¬kÖ˜“4ôíx1ûjbé À¾m¯Nª²ËNF’FúîÚWñ1,«`mG–¶×£Æ_yÑL1%P,2�Of�¥Â¯=ªæ
x~±R©¶çZ7`¢{ô�$Œ¤4ô'TôDeôÇdÌ^´lLÇúÍÝwã²Ë/Ç3Ï<ƒW_}W~ùüô'?  ˆ3ÁêÀy`E8ŽGcÃØÍXP,C�Ñ55˜Àtë›7VìyóEäp„ÜBnÌÜŒDdLé˜c…Åþ[è~ù‰1ÉD�‡Çò¶VÍn¨XØ)«›P>²3�N–Fú1òÊŸct¥Î_õKùúF™™Qibózb
$UÏIµ]²nã˜�÷›»ïÆ©§žŠÕ«Wg„ßUÓÂr™Fp�¯›—?8æÏ©4ƒ1 2NÚDS�¼”ß}ë7^qóú�WÜ�Lö…U"<ÑèïéÊN'Ý”vO*AÀÅeA%<��(J
r®ë²çÉg#�1x‡4Ò�È¶'s”@v6 ¡icv&ú™ŒÊ…–àIgœÞ[=átÍ<®`[ÛìŽ	‰D+á/–HÄ ÝÐLMÅ!«füÑž˜“òKÈ¿>ÿäòóOÞ!–»Üâ<ª%„å�E8þ…pÂF ±¾/Òjvž¸8Ìo­­È"°Sœ7PÀ0×rÀåúd±ã¬ßtÅgA˜ç]{ßÿff»!'s­€+}©f!šnLh>ÀPR-˜¿ÇxBØxÉgªr|WM#\�³¶·|EEÇoT®˜"e  %ŸV}óÆ
«ü @˜ç@éï¬×¨®n×5í **Ò¬ŒpÂ¨¦!7êšJvo/¨‹`f5®òJ\l(
ÁÊ¬€çŸ¼CfÜþ ì‹îÞuà�ùÃæZ%¢åF£Mô4§‘”IÎIÅPRCoLÁò}s-×qYŽ§5«Ï…PÓ>Ø˜áYj‚A´Ï�?¡×”;÷^`HB¢ ÀÈ&G–˜¡˜HXå¿,ÇSÂ°@Öoºâ öéšJ:·üÕÑ1Ã@JÑ—5„SÓ„QOTFçˆ„}C)¼3�Ä;I¼ÝÇÛ½qlë1Ž¼òË]C5Å,J ô&æ¹#¯=…Î°„îˆùÓWÐW0”T1”T•´t{v½âyu¯Ëg;‹äwìµË,gÉÈ0Ã‹›YŽ§Ã¯?F-¿ÞPåŒPJÈË±ãÝ+ðHDÁHJGoLÉ(–œù�[àm» Ö�ô!Â§*+z „ÁùjñÞ+6ÿ9âì(-°· h’5"  Éæ%kÆQ]`¥úêšv'ÕÕ‚”®çŸ¼Ca®FÙyKÀÃ)³lOTÎõÛ½qìèKbÏP
û‡%Sh£2**Â’fŽQ×Hš�Žv ŽØ5{ŽêZN|ˆ0ì{Þ6Ýkëý	ÅË–4$TôÆUtGåŒ²ÈVåCkÐ…÷ÌiÄ¬z_Ñ�‡™'�›6ÌˆžÂhçº®Ôgªü‚Añïº¦’ØÎç3|@vrÐØy€‰}UƒâH^û/ ð×5ãƒßúZWžRÑñxomç}¹Àô',�¶öÙ˜¹tMÅçÈ:tŠõ¸´[Ø%Íèæ 2PÈa3t?Ê-€Î7ž€ã	\ccŸ©ñW€ÜñÆKÏon½À™ëchª‘Œ1zt‰ð”pfØ¢$Ë�Ãˆ§dRTS '#�Fúc„å¿Hóª«Ûc¶ßøçÏŸt=+ˆ`yÄ ãòÁç!† êá­k6Çµ…êà©oü5Ðò¾Ž "ÏÂÃ3àY\Þ
À1³ëýL­Ï�ƒ½ƒ‘
/ÖÌlGªg4<ÉyC9ÂËp\ËÂ«o¿p÷>öÇb÷è¤ùïçŸ¼ó‚D×žž¶àëf@OÅ3ÊD��õlKˆ	ÇƒêöåÊq™ Ì�F)²òìB>ËOK)qL1 p4§+PLÖ °¬»ægcn	¦F2Ê•°6žvú˜È¿ñæ$•"EB †  73¸ŽæP`¦ü—��dd¸Ô¾Œ'pM¢kÏ™áÁÞ&_]3M5¢½�Lrà=û¡�ô ÒwÑ‘!hÑH#ýk„å¿og… –°Üq™š@GööR¹q¼×,ò©›1¾æÙÍY†À¬%Ð<žŒ†wqLú‡@àF»À\–ÏnÆÁÁ˜qh0^p-Œà�PÛ
e¸Û<÷t'¡ì˜~âà¶« U iëêë ô‘ð[Ï£víy Ò‚7t9FôØ¾×�â@‘~rž†Î~Fsœb5»(PºOàPRE“Ïì(ëƒ	5óÞ9ï=ÍkÎÂ¾·K7Íæ:XÑê	dÜŸsÎ>kBûÅ…]V¥fÐýa¹ÕUè)“p:‡lº &i�4QÙÀ³�=¤Ã~Ï?yGÉ÷ÉÈ0¹ú…ï}þ·P%$ú—p–ã©®©ý éèaÓzÂº	ÃF¨¡'Nè¤†€“6|ä�bçñü“wÈ æYäÚß_ºßK•””†ÃMõ†™A=ŠV€.PÑ™êÞ×›£{_Ïé¼ém›�ÆùËQ¿x-j_]3 €#*|"�Àf,Ëx§/Z0�ˆ÷×Á�â™•ŸórúüBNN�’+®\©ñWæ9599ÕõÜmLÁÜ%] Ã0–ÉA–²È=KIØ)‡á¤9¸ÛÆ%HH2|3Á7s‘yL)•ÓâŒj*”<²Ó*†ÚpÒº1uLÕiûúbÑ;¹NÈú !,÷)ªk·òÞ ÎýùX×nja».¢S	«ew\Ö�TtÄ£À¯yéû_@÷Öç>’Íü;ÀŸ| Èø~ ;òºt3œÐI)í<é”÷§wJÁx‚µP¥ÅÔÐS]_BVƒ+˜3ÛæcÆ{6aÆ{6"8Çd²]ƒ�‹ÍXšAq wÄ¶ò0Õ³7#ô†œÌ©4¤ø³+mA˜3A�GxoµkÏa8ˆõm`8¾dCwKGÑ×jC�qw®~‘Í‰�kè�$¡ÐQËW   wç�š¬'€óNZ9î•QƒÇÑ~ËZ¼¶ÛÚ9„í½‰œm‘¤r9Gã`fÇšj$UƒñLP×'°ÆˆÇd	Õ@2Í¾óÓ-Ó=vx7º·>ÿ\…ÂÂ	_ ºöSÂro�˜#àH¦‘Nu-gULÒ+ðé ]¼EX~@×&ºö®ßÝµçÌÝÞÒämœ‰ëÎFÛº³!Íè GTÔxøL�A0 `ç‘Ü‡ØÕ8É#»  3è#cˆÞK”V Ôø+€}j"ÒaÄ‡ÁøjÍ:ø2×EuÕÑ”ãÉ@­‡Ï<{€iId1pž ÔèÇcÑ¼¹X¶xá¸‡ÏýÿRŸ“=åÈBTRúaùeTW·ÀûðV-˜ƒf¿0)åÀ1IC"=ˆ#¥šB_jŠo|¨ÑÎÝHôìGïþ]Hv½©ï Õ5•°OŠÅ|îD˜
¢ºv@Wæ�…§_Š¶Õ§Ï3–"H©:¶uæ´,WcC>€j*¤�ÎÌks—�\óÌ�„Ë|úM ½Æ7ë8x;Ž¨ëò–e.Ô¶ä4ÉÆd[ uf~Déá …@öpP»q\c�‡gÐr•ßO`2ç��[·ô=Ô;¸’#¢§‹¦ÙòTÿÄfÍD³_¨êÍtb¾gCN&=ô6½0r`†Ž@ªg_±6MÄ4Ýµ ô˜ðg!­·¸�pÂÌØ�íŸ|åç¯_¶ýžÆŽùg\ŽŽ÷_fx\"Sëá±jV=vÈD	²ù Âñà<�7ÐoB	2 @Èã ôyð¼ÇÃPe°./Æ
E30öw�CÒM[|…ãÁ*ï³ V¢YéñàåáÔ/)°«© #C‡¸´9à—ÂýKc'Çc¾G»ö!Ö¹‘î9�<mÐà•´�þ*a¸'žò‘w¦ƒo>�‘NDºÀRxðÌí÷ÜôÅ=�Þõ�%|í'_`ÔúÜÌ’ö¦^@¨m5{t5',˜:ðú(£ Öo¼ü©Ÿý-Ub(©ÌÊNµâf~±ÙƒÓÇ¢Ñ—-Œn µ¶ûj ¥}H9“Èd€c�™>äT18M*V•´‚D Y3†ž¹ñ‚pÚF!ûºBé+i‚g£Jæ;)1*+Â¼	J÷–}ž0ìNð®�£´é£S]�6¾ùQÓGÿ«Yöúmÿ~íîÇ~»ùø+¾‰™ËÖ`Ns S	–l€2ÜmþLsá—ûˆ´BÞ C�•	”Î4Ÿ“‰™8™(§,¥  £\-€bÜ�]‡e�ÁÀÌ €7¬ˆ÷`fÝ£3&Á|ßàMlÈ[„åÞ¢šrÔT(V3E¨Çùj"í"|,Ù{ð¦çþûcÿÕ°æœ¬ÛüuÌhnAwTï¯ƒ�¡¤ÀûB�‡S º>ÏáGìÐaÈIPÃú.Ç7q20Ù£�QÅ g¥=sŒ–³Ggúþq%¬¾D~C>$ÍèÒ
€°ÜAª«™lÀýÃ ©bó}øÐ®rýÔöa4ÄVh¾SóªMþ˜èd¤Á¹Co<qÒŸ_~ø§ë®¾yÅ’OEwT†X×ŠTÏ>³©%ËƒZÖoÚ,–w»Ì,SCŠƒÓÛ¼ŸŽÐ …¬QÈ™ü¡`Y<cŽL³”‚;=þKÕ)º†aÄ†ÐÓß�7ß~oíDb¨ŒCÂ]ÿËÙ§^ü3 ­ ¨¡í€H·92œGØ™ï‰®=¥Ë|…°ìÎcæûÑC•_X¿ióÚ~|Õ¿ŒìûÄõk>r  ;ŠLV +º¡%Uô,XÝ†'ïØ_æ�C Ž:…>�¦b‰\¡ù¯QM£�­85tˆÁ_~ûküäûßÅ‘Ã�6G"[ApãÜf$#Ã�÷ÿØ¼V  ·ƒê*ý‡1°óU§æ;Ž™ïcÇ†ëïõËÊRCN6ò¡Æ¹Ztp €0™t±èžWnê~àG/u|îæ¹‚Ëó~ƒ0ýZ*þfË;¯tMé™>îï<ôëÿëïÜûËs®úïu)…`8Pg* —Z2ŠTÏžF˜>þQU×1ÔuÑ×Æ‚^9Õ§ãNÝÏ ãÜËðËMçã¡_ý ÿ{÷o²¬qò}€^
ä×Ç H›sHg’Á> ;	Ë¿Fm7a¸éT×c’í­çe]`þêkA��ÃÔ•Û?²û•ž9ñðœ·†�<ÝrúÇstš¶,·�hÊß)ùØ¾_\Yuad<ÁÚºE«oY÷Éë/TDû»¡F�êÙ]×Nì~àG/•>‚™àm›ßÂup5Îï�-BrÞø€ýmq»DÔ‡J�C/…„$£¿ûú½ÉƒÛ°éÛÝ×/²hôU7>V4zyø]åó	¼<|£Ñ9ÃC~ Üò]ôôôP]×þ(½)ÿ}�)â¸Ô¸ @˜wŠ™ï‰sÌ|/�õ›6‹+6žCXîÃïüè“?4Tùõð[×2V_bzOÇ¡Öï†Ï-¢ÖE ¹ÍtÑ “"éŽ´üîß¯Ü²úóß^ÑÒZ�ž¨ŒDÜ¬Ù`8n!€…à…‹D^À¢«oß†ù+á]Øù?—<?¦“Îƒ‘Œ¼þÄÅÙúÌç~ïÏ×K5ÍP£faO*6þ˜$¨ºŽápjd ±=¯€åK'Mæ`Òrp;ÌÊõ¹û‰^?.¼ô2œpÆEøÙ¯ï";¾ã{ñCo·ôÚìýFU‹jNÿnþwÌ|¯§üð¹ý‡||¸ŒM¯ò³þéøÍ_5XqãâùsÑQëF¨¦õ¾Òi¯ú¼YøÃMßXñÅ:®�ÙAV3ÄUôô¢ �#zGb£
AW¾Ò~Á—Ùyÿ�?[­k¢ºzÃk�ÿ©ÿ¸Ó/þ©h€–ˆB=Š@$–€.'AuÒH?¼�3Kî?]¦bqŒóV`ÅÎy ¡¢yÍYh^s¶={Í¾gþÔ¾0Ôv™e¹OìÜ¥ ,¼úö	ÁW»�’�ØÑ\ãGëqg¡-uð{Ýo½‚3VÌv|L–e°ñ’Ïd„0Ã@--�6`žI¤T;õb×á>tö‡;øÖòõ›6‹��à�=óÖÔNøÑx­« hÆÆKj¥-04†œ*:ÉxºÂŽ ´ß�Mê��°ËOAÃòS.êŠ<ˆ'ï¸8¦ Æ�Å_¿w=U’ßbX.Ó6Fà8tÌiÇq³š3ùà‹>=îþ×Ü®Z²FÍÎ>:…bÐÌ¬�šÚœ%ë.ý<jNè'?5ÔÍ³8~^ŽŸ×†”ªãÛOßºîù§îz|Án>™! tå¢E×Üþlc{Ç—Ÿ½êäÊæRg¡ëá[~X°Öàu?GïÑÃÿÉÕä²½-¸¦IÀíð<JïuG#0Žn³~?¦ ÆˆŽÏÝ<—÷…¾Mtå"Âš·Qà8,]8Kf6´U8›>ÿïè�)HiÔqïE‘%¶‰ž�›g!rž�ó,”‘>\ÿË{On>nÙ²{»Á°Ü)ƒ]‡Þ\tí�?jòn(_Ìc��?üÄ/]{ç¢©¾ÿN‘ÝOÐiÒdŽ-¯àÌ(V+`¥ågƒ¥ša<ø«]ÖßÇÀ¡ö¾ó5qþš‹€Ò‚¯hÂ’†˜¬CuÕ¡;*çtê+’ª‘3<ÓÃ3¹9xx+ÏºëN6‡[|þ¬Õ88œUó•¾xô²ÅWýúº�?üÄ/ÆòÙ»nºâª×ßê~àGU¿¯Z2
e¸òP7ÔØ09C5Wî°‹�!ú!x|àÝ>x›çÀÝ8b¨ÉÑ±©ÃiPÜ4à *ñÿ‹Y ½±ÂÕß ìÖìÈÝ»N8ËP:>wó\+øÏ?ïYøåUXÐÞ‚•K”~ÆeÃ)É¼•¾\Ç5-Ë  Ža�37‚Ž §_ü1Èš1íÎ®uãóg­ÆÛ»ñÐëûÑ;«#ü|ÑWï>­ÉëûôX¬'ï±ºMA5»ëP]ƒ¡iÈVTW?¸ñ½¯Aé?P2“´Ø+¼7ˆ†ù+P·h5ZÖžUT!X}À/­�Š4`;8íÉÁZÔÿ?.ìjÄü-çýS}¡cÅúM›ÅŸ5Î_å›×¶�²ˆ¬¥+/»ù†Âò7šSkª‡…Wß~!a˜_njçò'ªkCíá·±þüÓrö‹ËfÛp©HµªSð¬ùZ2ÝMXÓ�¢3ðx–dLAž!™^"K rÄV1HÅ�a	^‘E£—Ï(‚%³[Ñ1£�½þžÞ~ ÁE}Ñð²Å_¿÷SÕ
æ‚ =-xù&xlÏ«xöž‚D³3ÛÑÖÚŠÚ:³Ò®¶Öü?TÓ€ðˆIäc÷þNÚ»›ª‰é~óYt¿ù,ÞþÃ�é‚Ó.&s?xÑE5³ZM…1UH°¡¥Ø	ÃÅMóßåÐJ,•#p$Rh„“òcÙ
àÍ‹¯ŸX8û”´ Ï¥ Ç1„Ì[úéóâ…‘ƒ pá„ÿÍôâ']{ç†ù
 xg,Äi7þns×_oÅÝƒS/»K hzãjÁŠŸI3LW *�­¿�A¡*ÈêðÊ3�…—gàØœÕ !ë8 ëðŠ,šýx†@äœ»fæÏnÇoŸz‰xla|×ó—˜ @¶ æ@Ô€®ÂÐÔL_ÀDçÛè~ä ¦ÀoØp
ÞwÚiX»v-<žÂ¦ n·��…Ã4UI&{ìÇ–-[pï}÷á‘‡&;ý-$YÆÒÍ7@ÑP]Õ5ÈiâÒß^¼˜qºä 8�ÿóÿÍÀ@¢�ó }]¯dÿ=­À›_?‡aù&ß¼¶…CÎ¦ Ç�ÒV†arªÙ}Eotã»OþÁ|={Ç8°~ÓfqðøÓïf.²¶uÌž…å3€µk±óÑß`û3AûÚ3mo¶…°¤!"é™Î¬fGá~a¥$³Z
¼ùYí¿ÞcPD$É<îŒ  ŸÈåÄ…²Ž}r
>u3÷`Q£×ž"n}àIüí�Ÿ¼³~Ófq¿?´ª|vŸs¤3Eû 4)#}`E/O TW¡Œ˜}gÌlÇÝwÝ	 ðz½¶Â_
¼KÄâÅ‹±xñb|ìcÃu×Ý€o}ëF1ëZT)‘éi�8¸� 5Ë‹o( ‘%ãöÿF<èù®Û”(€bæ»­ ;˜S¨©*þß]?´þüKþ Ž±`Ãõ÷‡úbá‚Lxïøã`Vóèè¬ùïû0¢‰¢Â–4%Ô‚fªA3ÂO)Ð55§WÎ=àxpÜè×ÄeB��+`Š‡S:†S:‚.A›ó@ÄUÄ$m!x† èbÁ| 9glð_VœZ¸öÎíºéŠ«Æ{ÿ «®€ü ›¥ÃoA¬ŸªkÐ£ÍÏÛZ[Çñ	…˜7ovæ÷„$CÖ(´ø";Í‰Ñ®šF„Ž;©èû§CÐí�ý/ÿ?8RHƒåûÿÀ$( §æûxæ‘þâ¥G°#ÖŒÎà×9g„?+¶Ÿ/ü²¦£sD‚Fpš–CJš�¾¸jÛ‹�*)š‚Þ(SLM7 é@JE¦G�›gpqhŒæ¯›V�V $�bß`
í5.¸�ö¾øný¿GN> {pÿë‡ à+Ko|øÈŽëÏþÞ¸nb„ånb®�Fú‰;ÜVô€°Ü¤tÿIÄcÐ’QJ
‘7Ì‰Ñ³Nþ`I÷«šñÂ)(Ñsðp¤Päûÿ@ÀxÌ÷ñ ‹Ñï?û€yhBn¯é¿~Óf1[øŽÃñË— ¥f´N*¡èèÌbX5j’>‘Ã@Bµ�ÛS%…”$çaÕê€›RM÷BÕuD5|Ú„Œ¤G—Õ{r­…Î	F2‚›ÿ0jBAXc0ïýŒøðw_õëøXÃ„9×­«Ûu�;lŽïÞ!ÔFJäLšªIV F0òÊC�FúÁ{ƒXpÆeEßã4ñf"Á1Î{ æçÿ[ˆ«¶ñí7?[ðy•ž`µÍ÷ñâ¦?Üžn+F¶:RiŸtåÏþˆ¤Ù÷Ò×(ºÃQLî-µüÌkYm°M¢JÍd«Yí±ÇCÍVX„åÍŸ<· 0Õ JéJé¨s³E ÝQ~‘ËiøZ[W�UBç¾w9Â*ƒ§· á…Ÿ/þú½;ª ÿ¯TS.T|÷Kð/^_v h5 F?¸/? XvÉU€'TtqÌÂpÚI˜#´h¢Ðþ¡BÿŸã¸ûíÂã%?m2Ì÷ñàí�nÜÖùŠu_oüÑµwþ0›ð;þ¸Ž„?©hè�šÇ'•HÀPŠ�Å¶VACŠ—<¯Q]>úÅ*0GO–7‡yºr­‰¡”Ž¨¬¡Ö# äbÁ0ª�Ca­!·ùÕ¥ù‹¯ùþË7,E2ÇËû@UéþŽÏÝ¼f¼¥Æé±èŸ¥¿Mtíá0.ßxéä3?¸½ÿœ kÎAÛ)•|Ït  �šÿ¥Â{m€¢²Û×ö(ë7m±rMÊï÷çÜ‘©¿=¹øÉw§OŒy.]Í8ft|îæ¹T•¿‚ôj»xþÜŸ?¡èe… 4M«ëH&ì…ÚÐTr
Z"Àâ±Â´R@2Š¸ïòBGK]Uƒ /m¶„Œ5‘tø<c® Jàô5è¼÷YôŽÄêx�ï6 ÆýeQú;Ò
J¿?ôxoù&¡ã�îG×Ÿn¢º¦’À¼ã±æ×—}�Ç!ù6Q¨ÄüQ ±ôTé|Dø‹Ýþ¶êæù'ï�å—v½¬©Ó·�ãÛÝx¸k‡yÿ/ã=Þ¾_\¹øùßÿA—Sh®ñcQûh²ˆ¬åúüò…0GiÅ†í«Î´DÊpOFø�Ñ™xºœ2Ó`Gz!�4p©ž}HõìƒÜÊp7”án³A§Ï1¡	ËA’Ä"#‚,ç*ª¤jàÐH
IE‡7½Â‰ª9óâ†j¦{¬‡gð‰3×š÷–åNY|Õ¯?W•/�Ò›Ëß h—©jAMD k*	,\‹“¿ú0e­Ù[oj—¸j˜ÿ†ŸSút±ÌÍ¢ö†aÐ{£/ïÂtEfõþb¨òÕ8æà¶g¯9ø›¢‹fŒŽ¢Öt�#Î…ß2ë³+Ït9y¨;Gð¤ãá}Hõìƒ2Ü52 ]J€jrÎ Mª«0ä¤yüØ”‘^È‡ ÷‚)8¦¥²yÕ H¨Hd…ó•@oLÉÓì¨sãkMo�æªj}oTWo !�9‹bB1çÔáä«RVø�é‘ÇŸý·k ÐåL)ú#Åö/zÕüÌº?		±·Lõ})@,£™ÕŸÿg<ÇZzãÃ_�ñÁkž­YyÚ‹T×~#u¥îü×Ï`¤ß¬yïŽ)�‘Ë	¿=]ƒ®FrÂ^†œ„2Ü©¿³@)ä£ÔD]ª«Ð“QÈ��‡ºs&ìR]ÅÐÐPÆá
ž%èŽÊIŽ†I{bJNžBvùèŽŸƒ€Áîª*!ÁÑ“£¿!7Võ˜yðÍ:íÿttÎYk¯©V •$ÿ”2ÿíÊ5M¹§Ø±Šª’•÷Ýxàµ÷~i‹Ò5´6é÷À¿j>ôÁ‰Ý8Åo>•¶ÕÈÖñ¬þ§üð¹ƒ]‡¾˜w<óŽÇêÍÿ‚V—Ž·¶mÅsÿ«ÏßŒ„šû¥¨:u$üTS¡FMW ›é×Ñ¡743UÕPe³`ÅÐ3
ƒ°/‚0,Ã€°¼Iþq"˜¬H€¡¤ t‚óÀzC`8ó3“‰8MAcý¨UÓWÁ0‚.:%èŽ*˜2¹ƒ”ªc ¡¢ÁËcçlÿMZ¿æÌŽÏþø�jõ$™È\ †Í„+™‚g(Ü<)ÿŸjÿßïpõ9RÔügÐ6ûïé§¾¸¶³ØñJ:ºnÜÄ±ì½©]fh}:(MUqÛó�XW÷m8›šd‹þÎ}?f²jùç´ÏÏ2XÛ2IEÇ¡°žÑàFoÓH<÷&—þl?�j*”<K€ê*ôTºœÃ	04J¸z"’öóMmÎºý ËCÖƒ4‚õ˜‘	†ãÁÀq£ -…–ŒšÛ½fM…rGQ
dªÝº£2\�È±PušzÀä†û{ñûïü3®úô'°Ÿm¼uk*ƒâ .žÒ`°`ÀÍ³ikhTˆ¦ƒÿt;Ë	)•ü³«ß&âDéÿ–:^Ip�7þà�R�!Äm)�º3V#õv'¦
�Ü‰A% }ë7^ñÇ±Æý^}û…Ù™~sÚ3É3†1ZH¡I‡‡g��äœ|ª©Ž„_�t£Ñâ#Ð’³HeàpÙRØlðÞ ÄúpÏ\ÂòÐapÞPFà¤ÏA†Pk¦ÚJª�Áp-u£ì{çˆ„9µnp,“‰¸x<KP×Ü‚ïÝv àPï¶Þý,‚‹:>wóÜjXÔÐã=ÆX�Ru¤€«Àiã�‰B@tî~]öçÚ•Ø–jÆÈ¡C)u¼’
àù'ï�S'é!�nÆÆS»c@ÓeïCì™©Äûçg¬hùÍXãþë7m�ÿ²þöúühªmGSr›m f^ùp8šIÄ -YÈdç¿–C‰š#¤YÑC•¡FÍ•]ï qp;Õ55³üÔ^,ô6 èñ¡‰5É«>=…Îè zå•ÔDj"+œæ[¸¾ÙË Kqð¾˜ô N]NA�A¨1{½Jª�þH�Aóu�šM#[¦ù?”Ô0¯^ Ï$U)E‡[`1«¹óZë±·{¼7ðe W�ÿ›$# Å@$>þC�ÙVAƒ—‡fÐ)³j®þ>�)šû¿³¿Ðü×ÁÜ]®oCÙ¸C ­é&­³?“A‘ÚuÝ?­Ÿ?É·MºKpî†3�g€¿öïù£1ÆnÅCË7|<ÝE °pVK¦®Þ0Äeäg=Xí¸­Œ=«Ä4j¤¸ð[¯ër4Cø­ç­P©¼8·y	6úf¡Ã[Ø_bƒÓ¼‹è2:µ(^9Œ�©!ª&"däõÇß½5'œÚ8¬è†PÛ
ÂrÐ¥8”‘ÞŒH¤d„9!¯Ù#,i¨õp¹8ƒ”ªƒO»EYÏ¦\¸j¾Ó= —­ß´ùkãMºb8>f¨2”¬Â D"�††ÛýS)gýü*…•ü“Ttð,K&· ò¯Æm/®Šf`g¡A“”»Ë³¬X~Ïu/½vâ—Bæd>°k‡þë·˜õ��˜4‰ÖÀÙó—ãìùËaÆŸÜÙuà—+ï»±¢P%ÌU–x{}~£fqXÒ¡¹Â/ËfUYæýº
52 Â‰kÀ�â0äQL—S9Â¯'cÐ£ý�#ƒˆîÞÀœ¬tEëJòå§‚¯±ÏŒSGâ@bô8AVÄ2¶ËšÑeòŠÜ‡GûÌ¦ýÏÜƒÀÂµ-ß˜^ùÍÎ8ùJ`$–‚Àsð\ƒ¤¢ga„SZ†e§4Ôyxð,ÁÊ³!<ºŠ¦Õ¬Øxž¼£äxð²ß¥� Ð7<1ù N7?ú]«:…
@Ò4¸ÒÍV&Ú*:ú˜±ÿbá¿½CR&|k�€îú«/w\GªÇ ôæüm4)ãàu·!ùÖ!4|ìt°õcŸÚ20SÃ0Ì×k–tì?øo·?¹ÿºÛ6o¸þþP¹÷-¼úö³Wÿö–†œÕ8YFQ¥\íj•³RM6_ŠCÍvª«PÂ}™¿õdòp’·e„©¿�~ä›äºË>‡Ú“–Á¿düKæÀ=Üóg€õ›fzg‚œîZÔó¹µòAVÄû<í¸®ýR/x ÑÝ[0ô÷ÿK}Ö9Hñ—%žRàX¸8’F—MkF5(¢Y³!­ßy–à½‹Í~ú„aNÁ8qÒ)îg9žª‰"‘ÑóÒ´É"ZŒT“4Š¤bYiÆ8˜æà8šú 5žâáÌ7º
S*RŠ~‹“ã:R _=ã}¿¦”ÚÚ`ý¿{ûòGº|#ü–MÈ�*B˜�,ËÞ~'¢#ÿíößï¿î¶Íë7m¶ÿ’8¸í*iàt9�ãr|§«~l^�ešN €5ÌCJ yp+â»· Ño©o_�¾ô-ÌŸ3Ÿëÿq<Žçá™ÙÖïA½èÍ¼VL Àˆ¡PÀ´*]{0øÜïM¡�åº  À»Ü0rVÐpjô÷xVÇ¡ìîÅkÚ3–Rñ’:‡xþÉ;d]Sû³½—¨RùUÝjæ¤$œgHÙì;U7ATÒ hÎ:9;EÈ¡ð•“J÷¡_:9®#ðÌ�„S*öºòÒnrðÓ?_ëGÝÕçÃ½¤½ª7ªÂ\Â²ìíw�´±ÇR–e@8af|ß'Ç¼‰è®—�ŒãpO?Âá¨ºýêŸHå>tÙÍ, 3†o1ü†¦A‰@KFAUJï>Dß|,3`µ^ðâçù*nøø—
ßRg?Ü¼˜£ Sd+�Wä>¤‰Ä}º®Ÿ –èÚƒ‘7‡.%`(æù1CIf|Î¡,¡O*æ| éÒâtßÂ,2táÓ`¦®ãs7Ïÿ—Å¼ {÷ÌlR”*MV¥²»d›ÿN i¦uT«€cœ‡þjÜlQòïÍîBÕ	ù—9§'hkºI=Ôw)Rú§taÏ~ŒÆoBã§Î„oÍBÿeË”å¤Ë“/aY\r'¢ ÿvûSGžzmèŠ�§Ð·s/À»àn��={÷‚óÕ€j‡ Kq¸\nPo\¢ †rÒiíV=9ê¨ñ0�oAêÕèÉ¤‘~°Oÿß¦‹Èæ•i~�•Øú boìMšŸåæEÔ”G]‘ g’xû¤<Ú·› „åþ‡êÚ_­Ê»èî-p·-€—á˜äš–ˆBÔ�cMÂOÒŒL\B5LÇÇ³ÉÀ¨dò‡æ?zGbàÜ¾•ït`J÷8ùà¡} Ì6æ¥\ E–Á»JÏõM+EI”îj=c ªê£�¬&­•¢’Õßjã–�˜¤a÷@¡a‰F¿ïôØŽÏbù=×½ôÚ{¿´ÀÚRûõÿîI„ŸÝŠYßü(Ú®<ñ­ûynÇ”'Âlœ¹i5žÂjÄb1ú\ïr¤-…WºßÆ®#lFÐeO „‘Ý¦Y¯É™¬;=Ý_Hççk*”Þ}P%“üÓ"ýÐ¢Ðj"‚¥þfœµé"l^¹~¿pPPÉÖ ÷ÁÊ»°PL	d¯þ'møè]Ï?y‡™jr@7GÞxÞöã2¹€)\Àü=&ë£
@Ñ3¦¦¤ê20›`Z4£½#1‹‚í ÀÞ={3›ò™²‘�%xQšk²\ CNÒR÷Ûì°<þô_I£�4<KÀ³ÎIC§¹¥Vÿ×m|út%ÓŸ*jbe–ÛÏ²êN?uWŸ�¶ÓG €ßï'gûÍÆ�Ÿi7³ß	à`x;jÂØçp¨'ŠÁtcI«�•<�+”z|z2]1Ú¦Ú –{qÜªEØ´è,iÈô»sôT°õèƒQDž¶ÿþ\œ d)€ˆ&å¬þÙ¡9Æ¸ÆHF.”FúýÉ#»áïX	¤€–Œi•´L`v³ì¶æ	EG]zŸÕ´“0mãÿ&È[ ÅÖwF‰R¡@'L¡k*¡J
D°/
T°;A%VAÈÍ9ý[ýÍÀŽ¾ÂÌ¿hJþ¯rÇÌFEwaÍ–ŸÞ÷Ú{¿´…€¬u²ÿÐã¯bø…íhûô9h¸d|+:¦•"ÈÜžÇ’†V,ihÅÙ P Ð–®AJ’èa)F à`xvÁ{çs>¨>„ùõÅà^ÒŽÔÛ�züÕ¢ûBP/z3VÀ-=¯¦W²5¿ª9Î�Ü
Ðkâ{^†oöqk†j*4Ýl\¢ªAÁ3ªN¡éK
™Zhò¥CkÄ8Á¸ý/i7éÀ�˜3ÇŒ4kšVÐñp–PmL¥EÁ×ÛO¹«« ²QÊ*àçU¥ÞèŠÛ…þÞpúËFÅwÁ©`�&eùÑÑÿ‡gÐúùóP³q%|+:�:Ø‹øË»§4­¸ìÍáyøyž,1Í÷ì½ªðoX†‘'^/ºòÛáõx^9–ã)%ÌíâÞ/üÑPåkR]ïPCÓˆ.§Àq¦Mäà1ýeYÕÁ§ÙpƒZÎ²6JÖÖ¥‹Š(œÍã*SIa€ŽW_ß–Q Š¢Ø* 'ð`9žêšJñBõ…ûDfRºÿØY!—óÕ?»}[6ÍÀ›Ý6ÕÔ”:öý-Tì­ÙòÓû(¥×+]C8xÝmØõÉïaä©7ážÝŒ†K6 åë—À¿aÙ¤çL°õø7,CßÝO8~' ¢Iøé³}¿®iw«ˆ|ïÉ—¾j	ƒÈ!4³C›ŠjRý<K QóF}ÿì…¦IHƒaêQ�çàÕ—_Ìl)E:	¶´´ PFzm_+ù7HéIÐÇ@ÓËÏ(,µúoïML’" ûüÄŠ²™ù“šÕãk•XÙHí:Œƒ×Ý†¾E3ÑtÙûP³qeæçh°
ªÿ†eÐ"8ô_¿Í°ýNqKÏ«™‚¨´¯o»_šØ C‹‡˜µ
òP7æ-^Šµµ<êjB¨­«g²gâ©:ÅðÐ ¤p±á.ŠA\Ü�9óTý>–}žêÚæ×wìÌl+E:‰´µ¶âÈáN(‘Á‚×Ü<;eµÿ!gŽ‚×œév³J­þ¯¶qŸ)-ßóÌcR k¶üô¾üôàJa)‚î¶:4^´¡óÖÁ=»îÙÍP%òî#Hí>ò®SþËÀ×úqäÇ*`ú�àÁ¾·3¦¿®ëK›Ñ%@â EbÿÆâ´s.À	ûbÉ!˜<KÐÔØ Ža°pÎL,ð×ÇÇï~qR‹ ëM |i!tÂ<
˜-¼¶¼±kW-C"‘@MM�­à$0oþ<lÙòä¡®‚×êÜSSùçâH¦æŸ!Zšo�j€cIN/ÀRÌÿ]ñª­þÀ8æŒÇ
È†Ò5„#?ú#ºn}µ'-CíßßŠð+:à[Ñ‘£”þð´"+�Ã2¸æ4càöÇK}¥°#Ü�ÿì|– º¦ý  ¡RËñô}ç^HÎýÈ'?©æôœ,³”cˆ�‡7«[ýÎ=óýàÎ9o<z¾ækðÎ[]•IÌæ² +ž~ü¬]ef“&“É£Ÿ'DàìY  yðHÎv'™…z/¦H�¦SD4gr�"NBÑñj—­ï?¦Õg£ß×Þû¥—œF*�{ÑLÔ�±ž3VÁÌ}R{!è…6™öÖ�{I;Üg€zÇ%ø p8>ŒOîú“iúæ¹õ/?½”ð1ž`­‘ŠÝÏ{ü'ã‡ÿ‹ùïY Iéè�)I*Kz&P~‘Å{fø13(¢ÁË££Î…žƒ{ñþ3ÎÄ‘Ã‡·Ž?w¼ÃXËß@uõzÞÄã= ÀœX,ØÚÔ\Ò¸ýöÛññ�ÞÆ™Xqý™íÍ~¡¢œjÁ#°hõ;ãjÜ,¿ïv¼ü‡_¢­µüŒÅXÑšæ"én@SÆ_ŸihB@ßxðãË�ó½Ï…m»ô?×©‡ú^$8ÀR¾5ážÝ\ðz¶B˜‚%ôdv”×÷£û/§ÊK»ÇuƒRªŒËvÜ‹© ØÇx‚kJ™þ„fRMyŠåø¹_»ëI2Þ<
Ëè‘ i¹”µò[D  ¼Ù:ØRsjÝàY�!XÕæÃ™k±oß>,]ý^H#ý}„åO§º:æ’PÂòË¨®n€o~ózœ~º™8cÆ[7 >TS°0dã™gžÁ©§ž
 8ñ/€nðAGÝØ[°�í5.¢;zŽÛ^zßûæÕ™ú‘,Ä@˜7Vmêš;žêxÿe/T’ø“�qKîó'é>�N.ïqœ@h«Cè”ð7¾Û®ª$Cë�I µÛ4'J1°õ�¡ŒÀ¢ˆø‹;{f;†_Ø^1¹g‡”*ã³»°f–6Ó,¿s@W|øß~Š5ï;Û{Á×t‰Dƒ±$Y)èT”s}¢.QÀq³ZÐÁ³³B"Ö´Ðêçñìã�àüóÏ(%Ø cíÚuøö·Í>„µµµ¶n  Ìš5«è�úûûÑÔdF)WþË=ðÌX0e«ƒ—wTòkPŠ¶ ˜“ êÃÿüËW°ëÅ¿ [O`Ó8ïqÆ­ Þ¼øú9ú‘á·!“®^Ý‹fÂ¿j><ÇÍ‚kN³­…��D$
f$	=b&Ò¨Ã¦?¥¯IçÌX9_kæ°A/¸æð.1‡ŸèßòU·$ÕzyÂcxñ¬²MP	¹”~oî¢¥øÄÍÁÛé>q’f «o ‰heõ÷Þ@l:_ Ù/à’å�XÔhfÖ{x|ú#Ä#?€| ×Žãr÷è €Ûn»sæÌ—0³}ŽîÄœËnDûIçMÉêïâZbQß?nžA{�«`»ªSüúGßÅc·} ä#fšwõ0n•¸ò¾¼ºîÊ›!×UóÄœ µëp“N<"\í�f)m} žãf�¯õƒÌn€70ÍÆ`åù–â�ôf"ÉÃ}ù,~Uý Ãña\µç!Ëìw&ü @éç`åY—f„?�£³·ßv"¯�2«5Çƒp"ø@„Ú–Œð GÌ¹s�A{È¯@ð¹Ï~6­ è§×oÚü�1‘‚„|”vX>ñ·¿áÓŸú‰¼^/<žÂòçráÀeË–âÈáNÄnGÓªæWã¥ˆ¿|XmÙòÁ³â)W`¡þæ†_(‘�çÇË¹d£*6ÑUžØþ(øèxÂ‚Õ MÊJ!Ä#‚¯ñ�õ{ ‡<Ôír|;)I¢l8I @�%¡ta²±#Ü�kö>2ëçÅ9~Æ¬5’‘ ÐÚO `
ÿ¡®îÌ>Z|áíÏ"¾çe¤ºÞÉéG˜–ã©wö2â[¸'¼ï<,oY ØÖGÈÅ!äöbÝºuÖîþžùí qéHÂdo»÷OÆ%_Œ`0ˆD"a« Ã#%y€ãW­Æ#?ŒÔá�SÂü×z8¸V	Ö¸Ù¢aÙ—;£Jª¨[ø¸®þu óß¹wäÍ¿�X­ó¬ÚªõòÚ/^\�°à?2(¥x°ïmügç³–`î#,ÿA§[ZÀ‡~ùwˆ¾öuõeÌþðögÐó—›K
}1°OO»ü*rî§®B�›E�‡Ç™ÍÊ;Á‚šˆ€°üòŠÉÀ´ËÂr<õ/YOÂÛž |ô²ËðéO}
@q2°”�M^vûË<“—iÊ³3ƒÎLÿlâ/QIÃí¯öæÔe0††¡®ƒ'Wcj30†TàbX³å§÷QÐ-Õ:Þ?RªŒí|
7îÿ›YàC˜çOpM%•&ˆú @M×ÃKòhƒ�¾Ç�±?`V×=vÛwá˜ô(ró¡T%†œ¤,ÇS"zº*9&á„™VÛÛq<q7ÏÍ½÷OÎ´
±}ÿH	>ã„•«Àr<€C»ßÏWS1š|ÎLƒR´Š‡ŸÜ.(Ê’5úDµ„¨¢  ¶­öÃÅZ‡Cq<=°ço½wíH?´äûë7^~úØ_ò 8²ÍÌ­¯Œvª;ñÂq�çú}’jöÉ³âÚ�<ö(tM%º¦>TéùRMù ?ïÂ3s	XO ÁåfPMDpï}æ\‚D"a[P*)Èà„÷¼‡ Ààë��ëº+A%¦�‡+:xwûòÆ|3†7Q¾ZÍó­j^ä/Þ~&ü™k\„�q7�üGÀáø0¾Ûó"n>ø’f¡N¥¸ ?ë<°uLèOðUªÊÜó¦oÖÚ÷#P×ˆ¤ªC•exf.Bpñ‰`ˆ’ÈX	¥àªiDÍ	gáÄOþN¿ð2ÈC€%M^ˆj
gŸ{.¢ÑHŒ°üGAg“M “øþ êV½œ¯B¨| É[a¨2ví;„ó?p6\.t]‡×ë-8OEÜ€ƒ�à¹çžA*ÆÒ³¯˜ðïÓÅ4x8É‹áX‚™!—ík)UÇß*h;æáÙ¯=uåÚñ5aÉCÕ3xÖoÚ,þH
<3‚ï¤T¿ê{wv¿™å�“;Ò…=ãŽó2¼x’¡Ê�xgúOû—[áªŸ�Á‘0†Ã¹CJÓíÂ•È t9	ªk ,Vô€ó†àné@pF†œÇŒ€€—5b^�ýÃaÜø™Kðêk¯Q]×>ZIx*�¨ô
€&ß¬ãà_¸|°lzŠolß|ñ~ ÀYgŸ�¯ýó? m	Áb9¯¾ú*V¯^ 8ïE}Ûì	üV�'ü”bv­«èêÿÐÎ¡‚)¿²$mw?tËêñ¦^çcBRøÒ‚ONEnÀt†%øî}Ûbø�­/|±Z#Î-¤•ÀÿñÞ`Ó²K®Â¼MæH¿Á‘0²ê8À¢±¾^-«gø°ûñ{ðïÿý$úÇÒýÿúM›ÅçŸºëqPãdÞDÝ‰‚õø!F»3‹í8xû×2£ÒÊå”Ê´ò–]z-V_øéjÞâ´Dxygu½�/ÚégwÙ•ybŒ.¯OÆ_1LHiÔÏw<yä˜+0ŠÃñaÜÙÿ&®Úó}}ä0±Ì}ÂrW¯ßxù—í{­ê3Ø©¡&œð{]NÎïyó™_ø3tMEãìEhnl@]m‚¿á÷z‰èáõzr~êkBh¨¯5ê‚~²¬ÙA�ã�§þ·~ó³øã½÷@MÆŸ#,÷!úß*9¯ÎÛ¾ÐK ö„³ÀyƒkF{‹˜–€¬¿Ñ]fÏƒí»÷áüœU5§‹b®ÉŸ”$„B!ÛÏÛà0^yù%$F±ôÌ�LÈ÷[ëátjtóLÑ˜TÒðÀÛ“cú[˜°$þtW ¥ÊØ>Œÿ4Ëw³°„ü|ýÆ+n®¶9Wikàë,ÇŸ£k*ñÍ:3­€»u>¼ÍsPÓØ*x!ð,UQHDÃˆöv"¾ÿMÈ‡¶aÿ®V§�‡@˜Ÿ‚*ó`&üü ×Â;k)„Ú–Ì(sÖåÍL/€Î{ÿñCo ¾ø¥«qñ‡Î`,fd»§Ýxf-^YÕ{[I¶ Ì­s�ùÿþÍ>‰æ¶EWõ	ñÏ?ûÀD=+Úi*Ó„§–Ð?‘ìÄ£}»óãíû@È¿¦'OŠàçƒñk©œ¸�êúz€®G:õ¶ú ¼BXîæÑ±f¡Y¼ ¿·m>ü‹×ƒÔ‚ËŠÏ‹íe ˜3öüä3T×TÂr<ýÕ­¿$¥\�b\@ÇâeØ¿kæœú!lüÂ·ªv?+‰÷—óû_îŒâ¹ƒ¹n†¨«žúâÚ	+{�ðÆh/¯ýâÅ,ÃÜ;‘ƒSJ)ÞŠô`Ÿ4‚'Föá¥XW‰$²uý¦+ÖN•ðÛÁTÉ6jèm ­!ë5Çv“†ãcà];«AJ¦«ýÐäªiDè=çøýBmk† ÆåƒPÓŒÞÇoC÷#æ”«¹‹–â×¿0§ÔÙ
¹Ýn46ö*ýÎoÆ×®þXŽ§þÕ¤ZIA3‚‚ã�_)¿¿;ªàwoölWRÉ+^ýêú»ªr²E0)R9™ƒJ)Ž$F°/5Œíò Þ‰”øB–¿‘êêS}-“‰láç½AÔ®=¬ÛŸã÷sÞø,e@8BM3Çƒj*ÞùÑ'�èÚ 7CÐ.*`—˜ˆDQÓÖ5©X	éW¬Ð0C~w¿Þ‹¨œ7Ž>½së×OÝ<A_Ëè½žè Ò|@*°sªkŠ�R
IS0('Ñ$ªÉÌîwbè–"èTãE…�åxÊˆžÌké±ß™î´ÙûQÂœ\mÆº"_økN8œ'>ØPÔïLk€G[êÙ‹Ý?øxæ^~û?ÉtÊçŠYW~ùüô'?€«¦ùÙ ;öÆ NK|�Ò©¾€½ß?Q!?;Lš]>>à�Þ·ðoUí\éñ^1]Áˆ¡T´Š[Â.x ïáÐTzV[n]‘Á
bæw5ÉV}„VW³¢k:Â
C¢„ðN„«aFÎûø`CN¢…ÁïGç}fŸ WM#~û­ƒ¶|€!xèÐ!tÌ›OuM%Çüz¬<ëÃcº®Z‡Z‡3ý€Ò¤ßSûÂÓ}0Ìª‰Mò³Ã¤:æcåžØ‹kö<<)çÈr<åý5„åÅŒ€3.ÑÞå�*%‘ß…×PePMÉì]…2t,/‚¸aÅµ'ª¹Ã´�Éöß‚tšo1ájšrH?Ëï/†wÿFÒi½s-Å¾ý­¢JÀÎÈ¶.úÁ_*.
¸8Ô{8ÇŒ{�X”ôÛÙ—ÀÃ»¿þÉðû³1éÌÜ«ë®ü†a*êp8>Œó·¥›žòU Ý•¼ Ã-ôÔ5gš'zf/‡Øº /‚ÝP¢C ÂŒúuz*%œKÎ]…<Ü°|F)P–‡–ˆÀ�“ö®«ÐS1NÈ„µÞ­J€°üÁ¿éšJ\5�®:¬è)+ü„!6Ì,ylCNbÏÍŸÍð¥ºÙ¹ÙVÀÂó>‹“.»ÚñuyÍùäw÷ÉFLÆ=[

}¤dòÛ¯ÿ¿õ_Ÿð/)“Þ#ù—G^~êòÙk–ò”,qúž ïÂûß2óå	óPz?€•ü0nÿ6WýŒ¯1¢Œèë«E`ápÞ X—´`¦<a9ªd¦ÇºüàüµàCM¦EÀ`À˜·�eYP |°|°œ¯†ª€ê*Äš&ðõ3`(x_Jd  š©ªœI8á!úÑÙê8Œ'XKUù^Pã3Ô0ˆ·m>‚ËßÖå¨/+üBM3Súq$�Àâ÷bäµG`¨2ººŽ ¯¿ëO:	©T*'IHÓ4(Š’S?
… (:yî¹gÞ·�ÎXw6ñ¤g$–‚‹#hñŽ…¿Ñ/ ¦ˆ›•4Ü³qÝ2ª  ÍIDATmrÞpUQŸxíÚ÷N8é—�)i’þÎ¼Åž©‰§�Nö'„àåÈ–Â ,·ÔxºÒÏ¤ªœò´/9“*Ò Ðå$¼íÇ™«>Ë›Âlè`Ý°¢¼7Þ_Þ_Fp�uûÀð"Ë�áEh‰0 €\àýuêZÁyC™é;„å!Öµ�uû–a0‚†ª@¬i‚¤ÔÐ›aèaxñEjèG/'@˜3©*=àxÀLòñu¼¬Ç1Ô�ì’ÂÏ9ó«ëjC˜½ò$t>ÿ ¥†AöîÙUÓðžã�G*•‚ àÓ35M+(Zûžãqço~‹Hx„Äú:1ïäsK~^¥‰>µ>{‚1¥êøÃöADåÜÊFY’¶{#}gzæi2¿6`Š@ç�­úÖ�õ7#š:�Rãä=ª®á™‘és¦·�åsëŽ¿H(=‡õÕ‚uûánš±~&X—¬ÛÂ°`8Œ ‚p¼ù· BKäúüœÇÎ—VŒà6÷åE€R°ž „PXÑÖåƒ.% j€°œièø@=Ñ"ý”†�a˜�SJã ^ËuMÌU_ù9@¿ÀÇ{ƒ¨[õ>¸šç‚÷×€÷�~µvÂ bÝÇÂrsy]pÕ4"Ð¾˜ô¼ú8¥†A¶oÛ–Q‰D"G	$%	^—l:R ¸DÌëèÀ=÷ÜƒXï!_šç/³ý¼J…ßïâÐ\$ÍWÕ)îß1€¾¸š³� ÃŽnxúŸß×çä3ª�©“³tøÊõçmÑÃñ�BÊ>^p¸§oXŽk'.ÿO¨*WÜw ÑµwŸ»¥ãkÖß†ªÀÝ2šG@a7d“=`8oZ°Ý~ðþÚŒ`›û¸!àjœ:¨an'†M€åÁ
n°./¨¡�óÕCŠC““ÀûA˜ÓË½ZQYí`ý¦ÍbçÁmWQUºÀ 0³ûÞÆ€PÓÎí½./ÄºÖ_l˜U±ð[ð·ÌF }19ò’Ioß¶-ãä+�X"žS+°páBìÝ·Û·mCÿŽ¿Ûº•
¿›g0#T¼Gá_wcÿHîo1þÏ|ù½ïLÂ×f‹)S €Y4ô©¶ÕïB>PN	X<@B•Õ”­0}ûŠ@U9åmœ±œ° ôTžÖy œ`šö‚Ô$Ó®€¹Ò‡@½àae]^0o6Ïtû3¯3‚zj4¼CXœ' šV.„aÁºü`¨ËñPcÃ è,–e?GH×õO«æ*ë7mw¾õñÎýoüÀ¥ DÞD`ñ{án›Îí¨3]¥´°sÞ„P.G8qL+>ü-³œ},K`ïž=Ø¹sN?ý}H$9œ@>°~ýzÜóû{	��#;¶`Á) ›wæXÇ>?P:Ñ þ¶g;úr	bÆÐÀ3ôüg¾tâß'÷[ÌÅ”*  ¸µë•·ÓJàâRáABv«aì‰õÃœw‡ûÇòy5«No`=Ás8_x-8_Ü-æ*/z@X L:"0z{(¨®eÌzÖãç«ÃrÝvM÷f” Ãñ`]>pî,w€!ýy,!Ô„,kàDªÊ_ H=á„�SM2ž`-Õ”/txó6Pc3€Z–ã©îJâ_´œ¯| œ7dÞ3j¤c+8on¨­RŸ¿˜ð[°,K	tuÁ³/½ŠSO>	”ÒŒÈ'½^/Þsüñ¸ëîßP92@”¾ý˜yâ9±ý@yáî@¯uÅ¶Ë’tÅß¿râŸ&û»ÌÇ”+ ÀTŸž±&F€3J)FÕñèð hY¿ióOÆÒ5gÅÌ¥ÛÂ.ï'YÑã',=ƒ»iNFØÞ]2¿0Âr`Ñl�á«ëò˜ÖÇgÂ…Œà‚¡HWÀ‚É' º
Â‰émX—º"†BÞ•q	øP8—z"L©aˆ Ndæ*jÐ9/L6QÈðâIÔ0þƒªÒ- ÎEZð½3“Àqë	l ç	B5æøö¬è.ÈíÌ8¿X×V–í·PNø-ø[f£eùzÒ³õYhR#ƒý¸ÿÑ'1á"Ô…PU^¯·@	Ìž=®@yâÑG0xä ¼F+OÚT5áñP/uên/G¾öü—×þ|¢¿?'˜
  n=òò‹å”@“àÅýÛ(5ß‘#»þ:�è<°Ut¬L1‚ûÀôÑ9_êjCx„<"·*gZïÊ‚„°¶Ã‹¶9 „ãÁºý0²,yÂpà¼A€¦âÀ¨K`YbC;á\^PM±,‚•ÔÐ?àó ia˜õ›®8<Ö¶aÅ`úöÛO7?wRCÿ2€• ÄÑÿD"Ô¶€sû!„ÁºrÛt	Ázð�Ñ¤KØYW .øÝÎÓu]5�hYszw¼56MJà‰G�ªiX¶lTU…(Š0#G	œ´nM†èÜù&8–ÇìåkÊ~^9á¹3ŠÙÿãŸ]õ�j~oãÁ´Q €©>3cà;%À³:µÙë5ctŽÿÈ¿î‘óõŒÙ
Šy³Ûá9¸x^‘Ç`¼PÐ	Ã‚ ™Pßèv„1sr¶§-Ftƒjr†`òy.Ã»Ày‚E Ô¶@ð×‚Pš”  €zYç�­_aÎ°„Ô–'ë7^qªO°– Çƒ�3@éGA˜ëº¿õKjè—™Ÿ xgÂÛñø¬&\ |ÚÜ·¢&£×ã†X—›ÃŸë
�œ Sø=Bå½ü�3ß{ÂýÝH¦“…¶oÛ†g_z‹ÌË²`,Ëæ(�sÏ>¯¾ñ:öîÙƒ}oþl%àwq%	?»Ò^ÀLôyáËko¬øÂ&Ó²F÷ÕuWþ!ä:;%�•[¿isÃX&]{ç©*Åú{Öœ9hjiË¼NièIØ¾WOF`hjÁvCNeòË„¼Ôè�í,>5: -ÎÙFºƒ–Œ‚j*9irÑ¨±‘Rõ} é!QP#¯Àœ	‚­ øíÞÌr<uÕ6¶¦bÃL–3£n?XÑÂæ¡¢œ7”+øY¯åö”‚‡gPã+ž;_	>u¶Þõ_™ûÄr<½ôÒ"—\|1Z[[QSSŽã2)Ã‰H§�q¶l1»½ÿãÿ§|ô‹9î€A)ê<ýÅ…ÿÅCüÝfåŸŠ,?'˜–
 (®(¥8ãµ_§Çd�}VZÇçnžË	â¾Ì�`9¿z-Ø¬¦ŽbHªFÁ{©¦BKFl�kÈ)èR¼@ø-hÉ(4›n¼T“¡ÆÃÐ“…¯šb†³,92CŠƒ¦¢PÑLb¥à½¦Ïºý`õàýµéûÁ›.�è1óòPJð­|«Ùaù²¤ŸS¿Ä‡zñÒ/¾‰èîÑq®šF|ò²�ââ�ŸI¶Š‡úûûqÞyçg”Àâ3>‚‹¯ùO¸86“áW¬¦°/î¦¯ðÓX À+ë®¼†!ä¦|%ð“#/â¶ÎW Â<jŒ¹ï`¾ÐÖÜˆ¶¹2¯ËªŽ½qÛ÷–R  §-;š
-6Ã¦×}1E@Œè†ª@—bfß,¥ JI“‹ÐU[®0ùŠì:â6Âò`8$]‘¿Ò[(%ø ÒaÓ@ÁûKYc5ù�âàS÷aû½?ÌQ’3f¶ãü>„‹?t>QWW‡ÆÆÆK`î¢¥¸ôúŸcþ¼yEsûûN¾Àôóùó1­ `¯²‹ƒÆ4Ž*�×ßê‹G÷RUÎt£X¼òÃïqe*‚â2ú£öš†œ„žGþ±é]—“%• PÜÈ¼žCKFaÈ)3¡ÈUØŸê¨*ÃÐÌº+$i7Ô¼_\Æ¬'Î29¶øÊfÖBøl{ôºÝàƒE_·³ªiò—ƒÁÞŽwþv_ŽûÄ{ƒ¸äƒçâ}§�†µk×¢½Õt/þÈ‡ÓCOM«ákßù–¯ÛPx\�âÁ·qp¤ð™îÂL3Ð·yùÅOµ­~;;Y((¸±#Þ‡ÃR Ôƒ1’�‡ž¹GjX{n”Rúk["#MÍ£%©^�CBR*· “åÏ&Ù¬UÎL)v¯„¹3¢„-]Hgr¿~$È!�4É	`Ò†¬ÛÖí7ßgóÃºýf“à6žÒiÌ×Ærà<3¥7Ý©×n?Kðyméðµ2#Í}Bnu~wŽË5‘ðz½xÏ)ïÃŠ÷_LâI	#‡vQjÄPelß¶<ð xðÏØþö[ðx½¸òÊ+‘’u¼òòKÐ¤žùó½èîÄÒeË!zÌ,G3· G"¹ßch�%éŠéê+…ioXH÷¸Ãj(’M2žàìñ”Õ.ºúö]TWZç‚ºA±w0i;ž
0-ª«¶«ÕUh‰(¨Vš«44†’*jX1uª«™QÞ†’²%#+�¥´XÑÂ‰`8Œè)iXû³ÞPŽÒsŸÏ7i«¾…/�PžùêÅÞ§îÇÝƒDa4™÷qüÒÅèêîÆ‘Ã£=9]5�øäµÿŠ¥›>ˆÞ,håE€ažè—>ý…Õ�OÚŽG� 2G~K™C)ÅEoÞ�© äû ½v¬Ç]üõ{×ÉÈs™›ÂrX´leŽ+�Pt´ç\¢ ª¤�’Š¹–ŒÂ�âpÓìOæpùI5Ù º
CÓ@59£J¹ Ù¥¹¥Ìz»÷–sJÁçóÁç&ÔßÏ†‹cÐè –P6:¥Úý*^zìAt¾ñœ­2°½–YÇ¡õ_Dý’ÌxôIïæSU
 H·ëþYû@ï[¸qÿß€jXy„ ÛëÇ’eËsLT;>ÀÃ�æ›'ñ’JÀ©5`A—S%]ˆjÀIˆÎ$ýÜ¯ö™{éáñŽyxfÂ- »U¿DŽ@îÂ��Ûpø­W1ØÝ‰ÃûÞ�4Ü[4ìê›uZÎüVo¸ØLdï‰ÀQ§  3cíÔÀÝnUË
X¿i³8¸bãÖlW ?* ä*Žãàwå®„²,#/½ÒWb f
-ÕTèR†’§ÙŸsì"ñ{Â‰ãzÀ|ÁåÇævÏå:aV€“Uß~‘E£_ _„“§4<¿ë0ö’}ºªüµV—>üÌ�„'ä¢&G¥°ðêº+ÿãÏý;¯³¬ Â	Ç�§Ùf~n  ,X¸¡ºúœýºFˆ«(~N”€Sk€p¢m�j*¨&C—S²RÅ@8³JÑúk0èxQLð³Qm%À ÞËÃïpDW6šýBîâïH¨øëÎ~„S6n•®MÛ¿Õ
 0ÉÁ5[~ú€ü†ñ¾5Þ{‹¯úõçCÏao—.=žÀhs‹ƒ[· nþ
#¦1EŸpM7�ÅÒ†óQNS E�—¥ò�i%™¿›Çäª4$0}|–ãK
~6ªå
„\j=Ø
›Íº­�â«> ¼Õ—À“ïl§”FYª_9™<'G½ Òg«ØC=Ÿ°HA£2/Üþm�zœö±kÐW‘J§Þ—ã,P]5}þ<×€qùÊ¾w<¯p»D°_0°Ó	ÆkxM>¾bÁÊ¯ú’ªã©}aÛD0B�í^V¿üh"ûŠá]¡ ª�õ›6‹ƒ+7>F55“e¨w£ÿ±_Aî¥þÕ$ª�aŽ”€— ºœÌTV²ú�cQ „åáu‹­öÅ0+À+°¨óðûù@y_ º"2þº³ß6\W¤;ý�Ýö™é4âm<8¦ Š`Ãõ÷‡ú¢á—%¹pèå‡††^yø/ 0çÔ7ŸsÕÿdö3ƒ	C©ÒJ@Ó(RÒ‘5`�°|Ú2Hë�N€µÒWCèót9ËG�às,ƒf¿ ŸPüÜUƒâ¥ýƒx³§0òòn1ùîËTŸÀtÅ37^îøÜÍgK�ÛÏyëù{ :�ÛùãNCRÑáÒD�~"¯¡;oÄS68–÷ÿÛ;ûØªÎ:ŽŸç9çžû~o_i+XÖÂºN ¸¦BjL†fâÌÔÄlþ�C—8ÙœgÒD3’EˆD·l¨™Fb”2§t&3å5aH#8y]K¡o—{{_ÎÛóøÇí)íí¹¯½·´ô|’þçÐÒÛþ>Ïï÷{~Ï¹¾t�Oªy{ÀØ¤¡$�wê­�#nè�Þ£’«bŸIB3r–Ó	| ¨ñÉ¨óåÎ¤zo©xû¿ƒ¶�>"xOÈÍ6üëÉÕsj‹¯œ ªV®?ÚøÙo>èó°¼½m\	ÍD_4�çYó•…œ †~{`Lã×r‚°t°QI†wLJ f$Ø³‘Y
Hð+¥5÷,
I÷Sº‰“W†mW} s¾ËŸG Ò±î1¥·©%e=EØ%Ix`Åýðz&Oèé&G_T³­íÈ&‚BÏÐO—*ÑoÕX1Bn·Dv3x]¬äÀ÷¸ø$¸åÜ¥Åù›	t_²ýYÝM�¾\8(êUßûí�(¥ã']’„em-‡'¿µç‘”9åð¹ÈÁ|€µPÊôÞD‰ Î¯ä¬ó�ô¾þ‘‹CüjD�r£"J¸¹ÛûæË�wK£/Ž Š uó®Ù<1Q Ð¾´�õuSî/¦$°PU¦¡C3sPóN
 äfð¹¼òí8(Å¯ü…~¾tŸrØC´ïßí«þDIëæ]-²ÇˆJRÛÄ¿_ØÔ€%Í‹@3fƒJÉBnÝˆ§TŒêÈz
±Ì¤ ¬•>3è'Â
žæóŒ5ó¾ÎÎ\�ãôµû'<Ý¥þBpPk;÷…oÄ"oP&Mz‘ÏÀò{ï™Ò 
ïØÇ$4šnTD•€W¦ðH~E*x¿_f>9{P†oþHOò»4œýu7�í�ÑÁæâ9pP"ëS?¾~;¥ô©ÌkíK[° ¶fJ6 ¤Ë‚�¸žõ2ß`Œn
$tUUn4æ¢œ�©€ÌXÑoGf) 1Š�›!ì‘rvõ-ÎßLàäÕûù}ÌÏtßG Ó¤mËž�„ÒßdöªX|�}6À9GLãˆ$�)A\èPŒ…n
è¦	M7 ¼h)”" +ÐeFà–(%�))ë_«(é>A®±Ýñ×‚\HàÔµHÖÀ'‚÷<ò3så�•Æ@ÈÖ €ÖÅÍXÔXo›dŠ œ'ä,1èœŒÏ
hÆd9h‚¢Ú+AfS¥#3iì·Cb•	òlÈŒ¢ÚÃpí½XÝ±&ïŠŸÒMôôÇq¦÷VVÁ{ˆà?Ÿ�u~.”‰\%�Ï@[sã”íÂ‰$’Ihj
	:3Ûù&äf
™Q„ÜBn6ð'ïÇéãÝønç‹¶õ~$i §wïhY{#NàçÆ@™ißº·C¨‰Wì²�\eA×îN|aÓ³ ž bª�HÊDÊ˜~�Ÿ�;) �ÌThº_`³ÊóD?Øð€Xºjybû„=t.peDÅÙ¾ˆí>¾…ø…á äÊ€©":õìÝö=±õà…I?Õ0SÓ•’ÁL
Àêî—Djæýú‡�ãüÑ.´Ü·ŸÚú*.Ç�³ÏÁ9ìSè‹N�_Ž *Hëæ]-²?¼�<bw½¡* _¨ÿüñ— ÏüñxÖÏe˜1Õ@ÊUe¡R`pI
#EüDâš‰¿¼þN½ö“ÿ&ís…ë·,ùÖKA¥nÑ¤û„Q®«ûBn¶c¾wõ‹ÅÀÐ¾uo‡ÐÏgÎ À‡Ý�è§ú›?¶áÉ_í/ø0Žj˜Hh&R†@Êà%gå€Ì(Ü#ž±!ŸbƒÝ"®™¸8Åå�(†ãôèÎ¾ðè¿!øêUóDô¹ûŸýýÓîÆ% ‚÷¨£‘ßÕpí•ùº�?]Ì m[öl$À6«?9w}‡v�z‚où›Z‡Ú¾Ñ‰†Új,j¬G•·ð·Æ¶P�´t“§w¸€É“gÍr	ÀjøSJ!Q2~W‘\Œ–´ªÛÑÓ0��}&Wþôü±‘Ó]«­?Éµhí/»ïsÒüéãàÐ¶eÏFBðÔ…�Oüˆëj7 Ô¬zh°ñó›Æg	˜âÁ’ú ÔÖ”$;3�%˜"mƒÄðø½^„«Òo*MØâ+G`gc$©ãÃáQÜ¸•Â`,5O=“¸úÎù�¯-ðÓ;�#€YÂÂ/=ýNxÙšOÛ]óHµÕ¨«¡.è+Û™ý÷ßzJ 
ŸøÌ+ö}é\`(®c /8à-L]û»¼«®¶fï\{Þþ\Áy"Ð,Á·xÅKä£¢9óZÒ¸Ô?„KýCé{ƒ!,)üú¼ð¹J;9øþ¹s P6Ä5‘”�áX·b£IqÛ”>\ð˜0ŒnÅëÿƒ/6xÀ©ë+�“Ì2Ú·îízêæ=l';<AUÐÅ¥ äSàRÜðz<ðÉ4g¶ð‹¯}LVð³?Éû5t. 1Õ„j
Dã	hj
#) ©iˆ«zÁ+ûD˜ËÝ#8?”ê;Xsâo'çÃüÙ„#€YL)2ÈÄ#hÌ�¾ÛY‚âR�ìEWçWo Àºmo,hjjÄ(—93’4ÅÓ‰aRÓ�4	¸¡•ÜvXïûàDC0ü¶³ÊßYÌZ7ïjq¹½Ÿ’k=óV•*‹¡ãÐßõÛM ÐôÐw^®[ýpÙÿÏÌåî1tí]SMô˜ÉÑcÎ
?ûp0GiÝ¼«EòøWJ×È¡ú6®«íÅH¡÷ÀÎñ­µª•ë�6?úÜƒ…þÛ‰pÁc²â½lèÚ»ŒI×)ÁY¯$Îðý¯œw‚}öãà.bmç¾°¨ªi¾qå­r¸¾Åˆ.¡‘ƒµ~®«íÖ}¢ùì¶¯¬¦Þ „ÉË—ÿôÍnëº™Œ»ÃuQ ÐâÑ^êrßdLº®%¢ƒn_ð†ß«ôs-u“Œ]qRø¹ÍÿÒ‡+¦Å1È®    IEND®B`‚               h          ¨   00     ¨%          ›     X4   V S _ V E R S I O N _ I N F O     ½ïþ                  ?                        ¸   S t r i n g F i l e I n f o   ”   0 8 0 9 0 4 b 0   ,   C o m p a n y N a m e     a m p h p   Ô V  F i l e D e s c r i p t i o n     E x e c u t e s   a   c o m m a n d   a n d   p a s s e s   t h e   s t d i o   s t r e a m s   o f   t h e   c r e a t e d   p r o c e s s   t o   T C P   s o c k e t s   0   F i l e V e r s i o n     1 . 0 . 0 . 0   :   I n t e r n a l N a m e   P r o c e s s W . e x e     V   L e g a l C o p y r i g h t   C o p y r i g h t   ( C )   a m p h p   2 0 1 7     B   O r i g i n a l F i l e n a m e   P r o c e s s W . e x e     @   P r o d u c t N a m e     P r o c e s s   W r a p p e r   4   P r o d u c t V e r s i o n   0 . 0 . 0 . 0   D    V a r F i l e I n f o     $    T r a n s l a t i o n     	°<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
                                                                                                                                                                                                                                                                                                                                                              ü   0)050U0k0u0‡0£0¯0¶0Ð0Ü0ü0
1G1z1ˆ1Ž1�2×2ú23)363<3c3·3Á3Ú3û3444H4V4�4ž4¥4±4¿4ÿ45#5v5œ5¬56&6A6e6�6Õ78/8Z8·8Ã8ê8ý899M9g9¢9¶9ß9ó9û9:
:":J:d:j:¡:×:å:ý:;*;Q;W;‹;ß;å;÷;<)<N<X<k<…<Ž<”<Á<â<é<ó<
==+=L=b==ª=Á=ë=>->_>g>„>Ç>7?Y?’?œ?¢?±?è?î?      L  0,0>0F0Q0V0a0k0¢0³0â0ì0ò0&1/151‚1Â1û142M2W2]2”2�2£2Ù23H3‰3�3º3Ë3Ú3é344/4>4\4‡4¢4µ4Å4õ4'5B5U5e5y5ú5$6-6I6m6‘6©6Ë6ß6å6ë6ñ67/777<7A7O7W7n7v7˜7œ7 7¤7¨7±7ß7"8V8�8™8È8Ý8'909G9r9‚9´9å9ð9õ9::?:f:‡:œ:¤:º:Å:Ë:Ñ:Ú:å:õ:<;e;Å;ó;<	<</<4<A<B=K=V=]=}=ƒ=‰=�=•=›=¢=©=°=·=¾=Å=Ì=Ô=Ü=ä=ð=ù=þ=>>>(>8>H>Q>¶>â>1?D?W?c?s?„?ª?¿?Æ?Ì?Þ?è?   0  ¨   F0S0z0‚0›0Õ0ð0ü011!1P1X1p1v1¡1Ç1Ð1Ö12²2Ñ2Û2ì2ú2;3A3Š3�3µ3º3ß3ñ34[4`4s4�4œ4§4/585@5‡5–5�5Ó5Ü5é5ô5ý5666"6(6.646:6@6F6L6R6X6^6d6j6p6v6|6‚6ˆ6Ž6”6š6 6¦6¬6²6ð6 @     p1x1„1ˆ1 1¤1 P  $   3 3$3(3,30343ü5 66,909L9P9 p     0 0$0,00080<0D0                                                                                                                                                                                                <?php

namespace PhabelVendor\Amp\Process;

const BIN_DIR = __DIR__ . \DIRECTORY_SEPARATOR . '..' . \DIRECTORY_SEPARATOR . 'bin';
const IS_WINDOWS = (\PHP_OS & "\xdf\xdf\xdf") === 'WIN';
if (!\function_exists(__NAMESPACE__ . '\\escapeArguments')) {
    if (IS_WINDOWS) {
        /**
         * Escapes the command argument for safe inclusion into a Windows command string.
         *
         * @param string $arg
         *
         * @return string
         */
        function escapeArguments(string $arg) : string
        {
            return '"' . \preg_replace_callback('(\\\\*("|$))', function (array $m) : string {
                return \str_repeat('\\', \strlen($m[0])) . $m[0];
            }, $arg) . '"';
        }
    } else {
        /**
         * Escapes the command argument for safe inclusion into a Posix shell command string.
         *
         * @param string $arg
         *
         * @return string
         */
        function escapeArguments(string $arg) : string
        {
            return \escapeshellarg($arg);
        }
    }
}
<?php

namespace PhabelVendor\Amp\Process\Internal;

final class ProcessStatus
{
    const STARTING = 0;
    const RUNNING = 1;
    const ENDED = 2;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}
<?php

namespace PhabelVendor\Amp\Process\Internal;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Process\ProcessInputStream;
use PhabelVendor\Amp\Process\ProcessOutputStream;
use PhabelVendor\Amp\Struct;
abstract class ProcessHandle
{
    use Struct;
    /** @var ProcessOutputStream */
    public $stdin;
    /** @var ProcessInputStream */
    public $stdout;
    /** @var ProcessInputStream */
    public $stderr;
    /** @var Deferred */
    public $pidDeferred;
    /** @var int */
    public $status = ProcessStatus::STARTING;
}
<?php

namespace PhabelVendor\Amp\Process\Internal\Posix;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Process\Internal\ProcessHandle;
/** @internal */
final class Handle extends ProcessHandle
{
    /**
     *
     */
    public function __construct()
    {
        $this->pidDeferred = new Deferred();
        $this->joinDeferred = new Deferred();
        $this->originalParentPid = \getmypid();
    }
    /** @var Deferred */
    public $joinDeferred;
    /** @var resource */
    public $proc;
    /** @var resource */
    public $extraDataPipe;
    /** @var string */
    public $extraDataPipeWatcher;
    /** @var string */
    public $extraDataPipeStartWatcher;
    /** @var int */
    public $originalParentPid;
}
<?php

namespace PhabelVendor\Amp\Process\Internal\Posix;

use PhabelVendor\Amp\ByteStream\ResourceInputStream;
use PhabelVendor\Amp\ByteStream\ResourceOutputStream;
use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Process\Internal\ProcessHandle;
use PhabelVendor\Amp\Process\Internal\ProcessRunner;
use PhabelVendor\Amp\Process\Internal\ProcessStatus;
use PhabelVendor\Amp\Process\ProcessException;
use PhabelVendor\Amp\Process\ProcessInputStream;
use PhabelVendor\Amp\Process\ProcessOutputStream;
use PhabelVendor\Amp\Promise;
/** @internal */
final class Runner implements ProcessRunner
{
    const FD_SPEC = [
        ["pipe", "r"],
        // stdin
        ["pipe", "w"],
        // stdout
        ["pipe", "w"],
        // stderr
        ["pipe", "w"],
    ];
    /** @var string|null */
    private static $fdPath;
    /**
     *
     */
    public static function onProcessEndExtraDataPipeReadable($watcher, $stream, Handle $handle)
    {
        Loop::cancel($watcher);
        $handle->extraDataPipeWatcher = null;
        $handle->status = ProcessStatus::ENDED;
        if (!\is_resource($stream) || \feof($stream)) {
            $handle->joinDeferred->fail(new ProcessException("Process ended unexpectedly"));
        } else {
            $handle->joinDeferred->resolve((int) \rtrim(@\stream_get_contents($stream)));
        }
    }
    /**
     *
     */
    public static function onProcessStartExtraDataPipeReadable($watcher, $stream, $data)
    {
        Loop::cancel($watcher);
        $pid = \rtrim(@\fgets($stream));
        /** @var $deferreds Deferred[] */
        list($handle, $pipes, $deferreds) = $data;
        if (!$pid || !\is_numeric($pid)) {
            $error = new ProcessException("Could not determine PID");
            $handle->pidDeferred->fail($error);
            foreach ($deferreds as $deferred) {
                /** @var $deferred Deferred */
                $deferred->fail($error);
            }
            if ($handle->status < ProcessStatus::ENDED) {
                $handle->status = ProcessStatus::ENDED;
                $handle->joinDeferred->fail($error);
            }
            return;
        }
        $handle->status = ProcessStatus::RUNNING;
        $handle->pidDeferred->resolve((int) $pid);
        $deferreds[0]->resolve($pipes[0]);
        $deferreds[1]->resolve($pipes[1]);
        $deferreds[2]->resolve($pipes[2]);
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::enable($handle->extraDataPipeWatcher);
        }
    }
    /**
     * @inheritdoc
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle
    {
        $command = \sprintf('{ (%s) <&3 3<&- 3>/dev/null & } 3<&0; trap "" INT TERM QUIT HUP;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3; exit $RC', $command);
        $handle = new Handle();
        $handle->proc = @\proc_open($command, $this->generateFds(), $pipes, $cwd ?: null, $env ?: null, $options);
        if (!\is_resource($handle->proc)) {
            $message = "Could not start process";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            throw new ProcessException($message);
        }
        $status = \proc_get_status($handle->proc);
        if (!$status) {
            \proc_close($handle->proc);
            throw new ProcessException("Could not get process status");
        }
        $stdinDeferred = new Deferred();
        $handle->stdin = new ProcessOutputStream($stdinDeferred->promise());
        $stdoutDeferred = new Deferred();
        $handle->stdout = new ProcessInputStream($stdoutDeferred->promise());
        $stderrDeferred = new Deferred();
        $handle->stderr = new ProcessInputStream($stderrDeferred->promise());
        $handle->extraDataPipe = $pipes[3];
        \stream_set_blocking($pipes[3], \false);
        $handle->extraDataPipeStartWatcher = Loop::onReadable($pipes[3], [self::class, 'onProcessStartExtraDataPipeReadable'], [$handle, [new ResourceOutputStream($pipes[0]), new ResourceInputStream($pipes[1]), new ResourceInputStream($pipes[2])], [$stdinDeferred, $stdoutDeferred, $stderrDeferred]]);
        $handle->extraDataPipeWatcher = Loop::onReadable($pipes[3], [self::class, 'onProcessEndExtraDataPipeReadable'], $handle);
        Loop::unreference($handle->extraDataPipeWatcher);
        Loop::disable($handle->extraDataPipeWatcher);
        return $handle;
    }
    /**
     *
     */
    private function generateFds() : array
    {
        if (self::$fdPath === null) {
            self::$fdPath = \file_exists("/dev/fd") ? "/dev/fd" : "/proc/self/fd";
        }
        $fdList = @\scandir(self::$fdPath, \SCANDIR_SORT_NONE);
        if ($fdList === \false) {
            throw new ProcessException("Unable to list open file descriptors");
        }
        $fdList = \array_filter($fdList, function (string $path) : bool {
            return $path !== "." && $path !== "..";
        });
        $fds = [];
        foreach ($fdList as $id) {
            $fds[(int) $id] = ["file", "/dev/null", "r"];
        }
        return self::FD_SPEC + $fds;
    }
    /**
     * @inheritdoc
     */
    public function join(ProcessHandle $handle) : Promise
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::reference($handle->extraDataPipeWatcher);
        }
        return $handle->joinDeferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function kill(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::cancel($handle->extraDataPipeWatcher);
            $handle->extraDataPipeWatcher = null;
        }
        /** @var Handle $handle */
        if ($handle->extraDataPipeStartWatcher !== null) {
            Loop::cancel($handle->extraDataPipeStartWatcher);
            $handle->extraDataPipeStartWatcher = null;
        }
        if (!\proc_terminate($handle->proc, 9)) {
            // Forcefully kill the process using SIGKILL.
            throw new ProcessException("Terminating process failed");
        }
        $handle->pidDeferred->promise()->onResolve(function ($error, $pid) {
            // The function should not call posix_kill() if $pid is null (i.e., there was an error starting the process).
            if ($error) {
                return;
            }
            // ignore errors because process not always detached
            @\posix_kill($pid, 9);
        });
        if ($handle->status < ProcessStatus::ENDED) {
            $handle->status = ProcessStatus::ENDED;
            $handle->joinDeferred->fail(new ProcessException("The process was killed"));
        }
        $this->free($handle);
    }
    /**
     * @inheritdoc
     */
    public function signal(ProcessHandle $handle, int $signo)
    {
        $handle->pidDeferred->promise()->onResolve(function ($error, $pid) use($signo) {
            if ($error) {
                return;
            }
            @\posix_kill($pid, $signo);
        });
    }
    /**
     * @inheritdoc
     */
    public function destroy(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->status < ProcessStatus::ENDED && \getmypid() === $handle->originalParentPid) {
            try {
                $this->kill($handle);
                return;
            } catch (ProcessException $e) {
                // ignore
            }
        }
        $this->free($handle);
    }
    /**
     *
     */
    private function free(Handle $handle)
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::cancel($handle->extraDataPipeWatcher);
            $handle->extraDataPipeWatcher = null;
        }
        /** @var Handle $handle */
        if ($handle->extraDataPipeStartWatcher !== null) {
            Loop::cancel($handle->extraDataPipeStartWatcher);
            $handle->extraDataPipeStartWatcher = null;
        }
        if (\is_resource($handle->extraDataPipe)) {
            \fclose($handle->extraDataPipe);
        }
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        if (\is_resource($handle->proc)) {
            \proc_close($handle->proc);
        }
    }
}
<?php

namespace PhabelVendor\Amp\Process\Internal\Windows;

use PhabelVendor\Amp\ByteStream\ResourceInputStream;
use PhabelVendor\Amp\ByteStream\ResourceOutputStream;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Process\Internal\ProcessStatus;
use PhabelVendor\Amp\Process\ProcessException;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class SocketConnector
{
    const SERVER_SOCKET_URI = 'tcp://127.0.0.1:0';
    const SECURITY_TOKEN_SIZE = 16;
    const CONNECT_TIMEOUT = 1000;
    /** @var resource */
    private $server;
    /** @var PendingSocketClient[] */
    private $pendingClients = [];
    /** @var Handle[] */
    private $pendingProcesses = [];
    /** @var string */
    public $address;
    /** @var int */
    public $port;
    /**
     *
     */
    public function __construct()
    {
        $flags = \STREAM_SERVER_LISTEN | \STREAM_SERVER_BIND;
        $this->server = \stream_socket_server(self::SERVER_SOCKET_URI, $errNo, $errStr, $flags);
        if (!$this->server) {
            throw new \Error("Failed to create TCP server socket for process wrapper: {$errNo}: {$errStr}");
        }
        if (!\stream_set_blocking($this->server, \false)) {
            throw new \Error("Failed to set server socket to non-blocking mode");
        }
        list($this->address, $this->port) = \explode(':', \stream_socket_get_name($this->server, \false));
        $this->port = (int) $this->port;
        Loop::unreference(Loop::onReadable($this->server, [$this, 'onServerSocketReadable']));
    }
    /**
     *
     */
    private function failClientHandshake($socket, int $code)
    {
        \fwrite($socket, \chr(SignalCode::HANDSHAKE_ACK) . \chr($code));
        \fclose($socket);
        unset($this->pendingClients[(int) $socket]);
    }
    /**
     *
     */
    public function failHandleStart(Handle $handle, string $message, ...$args)
    {
        Loop::cancel($handle->connectTimeoutWatcher);
        unset($this->pendingProcesses[$handle->wrapperPid]);
        foreach ($handle->sockets as $socket) {
            \fclose($socket);
        }
        $error = new ProcessException(\vsprintf($message, $args));
        $deferreds = $handle->stdioDeferreds;
        $deferreds[] = $handle->joinDeferred;
        $handle->stdioDeferreds = [];
        foreach ($deferreds as $deferred) {
            $deferred->fail($error);
        }
    }
    /**
     * Read data from a client socket.
     *
     * This method cleans up internal state as appropriate. Returns null if the read fails or needs to be repeated.
     *
     * @param resource $socket
     * @param int $length
     * @param PendingSocketClient $state
     *
     * @return (string | null)
     */
    private function readDataFromPendingClient($socket, int $length, PendingSocketClient $state)
    {
        $data = \fread($socket, $length);
        if ($data === \false || $data === '') {
            return null;
        }
        $data = $state->receivedDataBuffer . $data;
        if (\strlen($data) < $length) {
            $state->receivedDataBuffer = $data;
            return null;
        }
        $state->receivedDataBuffer = '';
        Loop::cancel($state->readWatcher);
        return $data;
    }
    /**
     *
     */
    public function onReadableHandshake($watcher, $socket)
    {
        $socketId = (int) $socket;
        $pendingClient = $this->pendingClients[$socketId];
        if (null === ($data = $this->readDataFromPendingClient($socket, self::SECURITY_TOKEN_SIZE + 6, $pendingClient))) {
            return;
        }
        $packet = \unpack('Csignal/Npid/Cstream_id/a*client_token', $data);
        // validate the client's handshake
        if ($packet['signal'] !== SignalCode::HANDSHAKE) {
            $this->failClientHandshake($socket, HandshakeStatus::SIGNAL_UNEXPECTED);
            return;
        }
        if ($packet['stream_id'] > 2) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_STREAM_ID);
            return;
        }
        if (!isset($this->pendingProcesses[$packet['pid']])) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_PROCESS_ID);
            return;
        }
        $handle = $this->pendingProcesses[$packet['pid']];
        if (isset($handle->sockets[$packet['stream_id']])) {
            $this->failClientHandshake($socket, HandshakeStatus::DUPLICATE_STREAM_ID);
            \trigger_error(\sprintf("%s: Received duplicate socket for process #%s stream #%d", self::class, $handle->pid, $packet['stream_id']), \E_USER_WARNING);
            return;
        }
        if (!\hash_equals($packet['client_token'], $handle->securityTokens[$packet['stream_id']])) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_CLIENT_TOKEN);
            $this->failHandleStart($handle, "Invalid client security token for stream #%d", $packet['stream_id']);
            return;
        }
        $ackData = \chr(SignalCode::HANDSHAKE_ACK) . \chr(HandshakeStatus::SUCCESS) . $handle->securityTokens[$packet['stream_id'] + 3];
        // Unless we set the security token size so high that it won't fit in the
        // buffer, this probably shouldn't ever happen unless something has gone wrong
        if (\fwrite($socket, $ackData) !== self::SECURITY_TOKEN_SIZE + 2) {
            unset($this->pendingClients[$socketId]);
            return;
        }
        $pendingClient->pid = $packet['pid'];
        $pendingClient->streamId = $packet['stream_id'];
        $pendingClient->readWatcher = Loop::onReadable($socket, [$this, 'onReadableHandshakeAck']);
    }
    /**
     *
     */
    public function onReadableHandshakeAck($watcher, $socket)
    {
        $socketId = (int) $socket;
        $pendingClient = $this->pendingClients[$socketId];
        // can happen if the start promise was failed
        if (!isset($this->pendingProcesses[$pendingClient->pid]) || $this->pendingProcesses[$pendingClient->pid]->status === ProcessStatus::ENDED) {
            \fclose($socket);
            Loop::cancel($watcher);
            Loop::cancel($pendingClient->timeoutWatcher);
            unset($this->pendingClients[$socketId]);
            return;
        }
        if (null === ($data = $this->readDataFromPendingClient($socket, 2, $pendingClient))) {
            return;
        }
        Loop::cancel($pendingClient->timeoutWatcher);
        unset($this->pendingClients[$socketId]);
        $handle = $this->pendingProcesses[$pendingClient->pid];
        $packet = \unpack('Csignal/Cstatus', $data);
        if ($packet['signal'] !== SignalCode::HANDSHAKE_ACK || $packet['status'] !== HandshakeStatus::SUCCESS) {
            $this->failHandleStart($handle, "Client rejected handshake with code %d for stream #%d", $packet['status'], $pendingClient->streamId);
            return;
        }
        $handle->sockets[$pendingClient->streamId] = $socket;
        if (\count($handle->sockets) === 3) {
            $handle->childPidWatcher = Loop::onReadable($handle->sockets[0], [$this, 'onReadableChildPid'], $handle);
            $deferreds = $handle->stdioDeferreds;
            $handle->stdioDeferreds = [];
            // clear, so there's no double resolution if process spawn fails
            $deferreds[0]->resolve(new ResourceOutputStream($handle->sockets[0]));
            $deferreds[1]->resolve(new ResourceInputStream($handle->sockets[1]));
            $deferreds[2]->resolve(new ResourceInputStream($handle->sockets[2]));
        }
    }
    /**
     *
     */
    public function onReadableChildPid($watcher, $socket, Handle $handle)
    {
        $data = \fread($socket, 5);
        if ($data === \false || $data === '') {
            return;
        }
        Loop::cancel($handle->childPidWatcher);
        Loop::cancel($handle->connectTimeoutWatcher);
        $handle->childPidWatcher = null;
        if (\strlen($data) !== 5) {
            $this->failHandleStart($handle, 'Failed to read PID from wrapper: Received %d of 5 expected bytes', \strlen($data));
            return;
        }
        $packet = \unpack('Csignal/Npid', $data);
        if ($packet['signal'] !== SignalCode::CHILD_PID) {
            $this->failHandleStart($handle, "Failed to read PID from wrapper: Unexpected signal code %d", $packet['signal']);
            return;
        }
        // Required, because a process might be destroyed while starting
        if ($handle->status === ProcessStatus::STARTING) {
            $handle->status = ProcessStatus::RUNNING;
            $handle->exitCodeWatcher = Loop::onReadable($handle->sockets[0], [$this, 'onReadableExitCode'], $handle);
            if (!$handle->exitCodeRequested) {
                Loop::unreference($handle->exitCodeWatcher);
            }
        }
        $handle->pidDeferred->resolve($packet['pid']);
        unset($this->pendingProcesses[$handle->wrapperPid]);
    }
    /**
     *
     */
    public function onReadableExitCode($watcher, $socket, Handle $handle)
    {
        $data = \fread($socket, 5);
        if ($data === \false || $data === '') {
            return;
        }
        Loop::cancel($handle->exitCodeWatcher);
        $handle->exitCodeWatcher = null;
        if (\strlen($data) !== 5) {
            $handle->status = ProcessStatus::ENDED;
            $handle->joinDeferred->fail(new ProcessException(\sprintf('Failed to read exit code from wrapper: Received %d of 5 expected bytes', \strlen($data))));
            return;
        }
        $packet = \unpack('Csignal/Ncode', $data);
        if ($packet['signal'] !== SignalCode::EXIT_CODE) {
            $this->failHandleStart($handle, "Failed to read exit code from wrapper: Unexpected signal code %d", $packet['signal']);
            return;
        }
        $handle->status = ProcessStatus::ENDED;
        $handle->joinDeferred->resolve($packet['code']);
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        // Explicitly \fclose() sockets, as resource streams shut only one side down.
        foreach ($handle->sockets as $sock) {
            // Ensure socket is still open before attempting to close.
            if (\is_resource($sock)) {
                @\fclose($sock);
            }
        }
    }
    /**
     *
     */
    public function onClientSocketConnectTimeout($watcher, $socket)
    {
        $id = (int) $socket;
        Loop::cancel($this->pendingClients[$id]->readWatcher);
        unset($this->pendingClients[$id]);
        \fclose($socket);
    }
    /**
     *
     */
    public function onServerSocketReadable()
    {
        $socket = \stream_socket_accept($this->server);
        if (!\stream_set_blocking($socket, \false)) {
            throw new \Error("Failed to set client socket to non-blocking mode");
        }
        $pendingClient = new PendingSocketClient();
        $pendingClient->readWatcher = Loop::onReadable($socket, [$this, 'onReadableHandshake']);
        $pendingClient->timeoutWatcher = Loop::delay(self::CONNECT_TIMEOUT, [$this, 'onClientSocketConnectTimeout'], $socket);
        $this->pendingClients[(int) $socket] = $pendingClient;
    }
    /**
     *
     */
    public function onProcessConnectTimeout($watcher, Handle $handle)
    {
        $running = \is_resource($handle->proc) && \proc_get_status($handle->proc)['running'];
        $error = null;
        if (!$running) {
            $error = \stream_get_contents($handle->wrapperStderrPipe);
        }
        $error = $error ?: 'Process did not connect to server before timeout elapsed';
        foreach ($handle->sockets as $socket) {
            \fclose($socket);
        }
        $error = new ProcessException(\trim($error));
        foreach ($handle->stdioDeferreds as $deferred) {
            $deferred->fail($error);
        }
        \fclose($handle->wrapperStderrPipe);
        \proc_close($handle->proc);
        $handle->joinDeferred->fail($error);
    }
    /**
     *
     */
    public function registerPendingProcess(Handle $handle)
    {
        // Use Loop::defer() to start the timeout only after the loop has ticked once. This prevents issues with many
        // things started at once, see https://github.com/amphp/process/issues/21.
        $handle->connectTimeoutWatcher = Loop::defer(function () use($handle) {
            $handle->connectTimeoutWatcher = Loop::delay(self::CONNECT_TIMEOUT, [$this, 'onProcessConnectTimeout'], $handle);
        });
        $this->pendingProcesses[$handle->wrapperPid] = $handle;
    }
}
<?php

namespace PhabelVendor\Amp\Process\Internal\Windows;

use PhabelVendor\Amp\Struct;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class PendingSocketClient
{
    use Struct;
    public $readWatcher;
    public $timeoutWatcher;
    public $receivedDataBuffer = '';
    public $pid;
    public $streamId;
}
<?php

namespace PhabelVendor\Amp\Process\Internal\Windows;

/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class SignalCode
{
    const HANDSHAKE = 0x1;
    const HANDSHAKE_ACK = 0x2;
    const CHILD_PID = 0x3;
    const EXIT_CODE = 0x4;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}
<?php

namespace PhabelVendor\Amp\Process\Internal\Windows;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Process\Internal\ProcessHandle;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class Handle extends ProcessHandle
{
    /**
     *
     */
    public function __construct()
    {
        $this->joinDeferred = new Deferred();
        $this->pidDeferred = new Deferred();
    }
    /** @var Deferred */
    public $joinDeferred;
    /** @var string */
    public $exitCodeWatcher;
    /** @var bool */
    public $exitCodeRequested = \false;
    /** @var resource */
    public $proc;
    /** @var int */
    public $wrapperPid;
    /** @var resource */
    public $wrapperStderrPipe;
    /** @var resource[] */
    public $sockets = [];
    /** @var Deferred[] */
    public $stdioDeferreds;
    /** @var string */
    public $childPidWatcher;
    /** @var string */
    public $connectTimeoutWatcher;
    /** @var string[] */
    public $securityTokens;
}
<?php

namespace PhabelVendor\Amp\Process\Internal\Windows;

/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class HandshakeStatus
{
    const SUCCESS = 0;
    const SIGNAL_UNEXPECTED = 0x1;
    const INVALID_STREAM_ID = 0x2;
    const INVALID_PROCESS_ID = 0x3;
    const DUPLICATE_STREAM_ID = 0x4;
    const INVALID_CLIENT_TOKEN = 0x5;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}
<?php

namespace PhabelVendor\Amp\Process\Internal\Windows;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Process\Internal\ProcessHandle;
use PhabelVendor\Amp\Process\Internal\ProcessRunner;
use PhabelVendor\Amp\Process\Internal\ProcessStatus;
use PhabelVendor\Amp\Process\ProcessException;
use PhabelVendor\Amp\Process\ProcessInputStream;
use PhabelVendor\Amp\Process\ProcessOutputStream;
use PhabelVendor\Amp\Promise;
use const PhabelVendor\Amp\Process\BIN_DIR;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class Runner implements ProcessRunner
{
    const FD_SPEC = [
        ["pipe", "r"],
        // stdin
        ["pipe", "w"],
        // stdout
        ["pipe", "w"],
        // stderr
        ["pipe", "w"],
    ];
    const WRAPPER_EXE_PATH = \PHP_INT_SIZE === 8 ? BIN_DIR . '\\windows\\ProcessWrapper64.exe' : BIN_DIR . '\\windows\\ProcessWrapper.exe';
    private static $pharWrapperPath;
    private $socketConnector;
    /**
     *
     */
    private function makeCommand(string $workingDirectory) : string
    {
        $wrapperPath = self::WRAPPER_EXE_PATH;
        // We can't execute the exe from within the PHAR, so copy it out...
        if (\strncmp($wrapperPath, "phar://", 7) === 0) {
            if (self::$pharWrapperPath === null) {
                $fileHash = \hash_file('sha1', self::WRAPPER_EXE_PATH);
                self::$pharWrapperPath = \sys_get_temp_dir() . "/amphp-process-wrapper-" . $fileHash;
                if (!\file_exists(self::$pharWrapperPath) || \hash_file('sha1', self::$pharWrapperPath) !== $fileHash) {
                    \copy(self::WRAPPER_EXE_PATH, self::$pharWrapperPath);
                }
            }
            $wrapperPath = self::$pharWrapperPath;
        }
        $result = \sprintf('%s --address=%s --port=%d --token-size=%d', \escapeshellarg($wrapperPath), $this->socketConnector->address, $this->socketConnector->port, SocketConnector::SECURITY_TOKEN_SIZE);
        if ($workingDirectory !== '') {
            $result .= ' ' . \escapeshellarg('--cwd=' . \rtrim($workingDirectory, '\\'));
        }
        return $result;
    }
    /**
     *
     */
    public function __construct()
    {
        $this->socketConnector = new SocketConnector();
    }
    /**
     * @inheritdoc
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle
    {
        if (\strpos($command, "\x00") !== \false) {
            throw new ProcessException("Can't execute commands that contain null bytes.");
        }
        $options['bypass_shell'] = \true;
        $handle = new Handle();
        $handle->proc = @\proc_open($this->makeCommand($cwd ?? ''), self::FD_SPEC, $pipes, $cwd ?: null, $env ?: null, $options);
        if (!\is_resource($handle->proc)) {
            $message = "Could not start process";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            throw new ProcessException($message);
        }
        $status = \proc_get_status($handle->proc);
        if (!$status) {
            \proc_close($handle->proc);
            throw new ProcessException("Could not get process status");
        }
        $securityTokens = \random_bytes(SocketConnector::SECURITY_TOKEN_SIZE * 6);
        $written = \fwrite($pipes[0], $securityTokens . "\x00" . $command . "\x00");
        \fclose($pipes[0]);
        \fclose($pipes[1]);
        if ($written !== SocketConnector::SECURITY_TOKEN_SIZE * 6 + \strlen($command) + 2) {
            \fclose($pipes[2]);
            \proc_close($handle->proc);
            throw new ProcessException("Could not send security tokens / command to process wrapper");
        }
        $handle->securityTokens = \str_split($securityTokens, SocketConnector::SECURITY_TOKEN_SIZE);
        $handle->wrapperPid = $status['pid'];
        $handle->wrapperStderrPipe = $pipes[2];
        $stdinDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stdinDeferred;
        $handle->stdin = new ProcessOutputStream($stdinDeferred->promise());
        $stdoutDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stdoutDeferred;
        $handle->stdout = new ProcessInputStream($stdoutDeferred->promise());
        $stderrDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stderrDeferred;
        $handle->stderr = new ProcessInputStream($stderrDeferred->promise());
        $this->socketConnector->registerPendingProcess($handle);
        return $handle;
    }
    /**
     * @inheritdoc
     */
    public function join(ProcessHandle $handle) : Promise
    {
        /** @var Handle $handle */
        $handle->exitCodeRequested = \true;
        if ($handle->exitCodeWatcher !== null) {
            Loop::reference($handle->exitCodeWatcher);
        }
        return $handle->joinDeferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function kill(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        \exec('taskkill /F /T /PID ' . $handle->wrapperPid . ' 2>&1', $output, $exitCode);
        $failStart = \false;
        if ($handle->childPidWatcher !== null) {
            Loop::cancel($handle->childPidWatcher);
            $handle->childPidWatcher = null;
            $handle->pidDeferred->fail(new ProcessException("The process was killed"));
            $failStart = \true;
        }
        if ($handle->exitCodeWatcher !== null) {
            Loop::cancel($handle->exitCodeWatcher);
            $handle->exitCodeWatcher = null;
            $handle->joinDeferred->fail(new ProcessException("The process was killed"));
        }
        $handle->status = ProcessStatus::ENDED;
        if ($failStart || $handle->stdioDeferreds) {
            $this->socketConnector->failHandleStart($handle, "The process was killed");
        }
        $this->free($handle);
    }
    /**
     * @inheritdoc
     */
    public function signal(ProcessHandle $handle, int $signo)
    {
        throw new ProcessException('Signals are not supported on Windows');
    }
    /**
     * @inheritdoc
     */
    public function destroy(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->status < ProcessStatus::ENDED && \is_resource($handle->proc)) {
            try {
                $this->kill($handle);
                return;
            } catch (ProcessException $e) {
                // ignore
            }
        }
        $this->free($handle);
    }
    /**
     *
     */
    private function free(Handle $handle)
    {
        if ($handle->childPidWatcher !== null) {
            Loop::cancel($handle->childPidWatcher);
            $handle->childPidWatcher = null;
        }
        if ($handle->exitCodeWatcher !== null) {
            Loop::cancel($handle->exitCodeWatcher);
            $handle->exitCodeWatcher = null;
        }
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        foreach ($handle->sockets as $socket) {
            if (\is_resource($socket)) {
                @\fclose($socket);
            }
        }
        if (\is_resource($handle->wrapperStderrPipe)) {
            @\fclose($handle->wrapperStderrPipe);
        }
        if (\is_resource($handle->proc)) {
            \proc_close($handle->proc);
        }
    }
}
<?php

namespace PhabelVendor\Amp\Process\Internal;

use PhabelVendor\Amp\Process\ProcessException;
use PhabelVendor\Amp\Promise;
interface ProcessRunner
{
    /**
     * Start a process using the supplied parameters.
     *
     * @param string $command The command to execute.
     * @param (string | null) $cwd The working directory for the child process.
     * @param array $env Environment variables to pass to the child process.
     * @param array $options `proc_open()` options.
     *
     * @return ProcessHandle
     *
     * @throws ProcessException If starting the process fails.
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle;
    /**
     * Wait for the child process to end.
     *
     * @param ProcessHandle $handle The process descriptor.
     *
     * @return Promise<int> Succeeds with exit code of the process or fails if the process is killed.
     */
    public function join(ProcessHandle $handle) : Promise;
    /**
     * Forcibly end the child process.
     *
     * @param ProcessHandle $handle The process descriptor.
     *
     * @throws ProcessException If terminating the process fails.
     */
    public function kill(ProcessHandle $handle);
    /**
     * Send a signal signal to the child process.
     *
     * @param ProcessHandle $handle The process descriptor.
     * @param int $signo Signal number to send to process.
     *
     * @throws ProcessException If sending the signal fails.
     */
    public function signal(ProcessHandle $handle, int $signo);
    /**
     * Release all resources held by the process handle.
     *
     * @param ProcessHandle $handle The process descriptor.
     */
    public function destroy(ProcessHandle $handle);
}
<?php

namespace PhabelVendor\Amp\Process;

class StatusError extends \Error
{
}
<?php

namespace PhabelVendor\Amp\Process;

use PhabelVendor\Amp\ByteStream\ClosedException;
use PhabelVendor\Amp\ByteStream\OutputStream;
use PhabelVendor\Amp\ByteStream\ResourceOutputStream;
use PhabelVendor\Amp\ByteStream\StreamException;
use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Promise;
final class ProcessOutputStream implements OutputStream
{
    /** @var \SplQueue */
    private $queuedWrites;
    /** @var bool */
    private $shouldClose = \false;
    /** @var ResourceOutputStream */
    private $resourceStream;
    /** @var StreamException|null */
    private $error;
    /**
     *
     */
    public function __construct(Promise $resourceStreamPromise)
    {
        $this->queuedWrites = new \SplQueue();
        $resourceStreamPromise->onResolve(function ($error, $resourceStream) {
            if ($error) {
                $this->error = new StreamException("Failed to launch process", 0, $error);
                while (!$this->queuedWrites->isEmpty()) {
                    list(, $deferred) = $this->queuedWrites->shift();
                    $deferred->fail($this->error);
                }
                return;
            }
            while (!$this->queuedWrites->isEmpty()) {
                /**
                 * @var string $data
                 * @var \Amp\Deferred $deferred
                 */
                list($data, $deferred) = $this->queuedWrites->shift();
                $deferred->resolve($resourceStream->write($data));
            }
            $this->resourceStream = $resourceStream;
            if ($this->shouldClose) {
                $this->resourceStream->close();
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function write(string $data) : Promise
    {
        if ($this->resourceStream) {
            return $this->resourceStream->write($data);
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->shouldClose) {
            throw new ClosedException("Stream has already been closed.");
        }
        $deferred = new Deferred();
        $this->queuedWrites->push([$data, $deferred]);
        return $deferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->resourceStream) {
            return $this->resourceStream->end($finalData);
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->shouldClose) {
            throw new ClosedException("Stream has already been closed.");
        }
        $deferred = new Deferred();
        $this->queuedWrites->push([$finalData, $deferred]);
        $this->shouldClose = \true;
        return $deferred->promise();
    }
    /**
     *
     */
    public function close()
    {
        $this->shouldClose = \true;
        if ($this->resourceStream) {
            $this->resourceStream->close();
        } elseif (!$this->queuedWrites->isEmpty()) {
            $error = new ClosedException("Stream closed.");
            do {
                list(, $deferred) = $this->queuedWrites->shift();
                $deferred->fail($error);
            } while (!$this->queuedWrites->isEmpty());
        }
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\Process;

use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Process\Internal\Posix\Runner as PosixProcessRunner;
use PhabelVendor\Amp\Process\Internal\ProcessHandle;
use PhabelVendor\Amp\Process\Internal\ProcessRunner;
use PhabelVendor\Amp\Process\Internal\ProcessStatus;
use PhabelVendor\Amp\Process\Internal\Windows\Runner as WindowsProcessRunner;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
final class Process
{
    /** @var ProcessRunner */
    private $processRunner;
    /** @var string */
    private $command;
    /** @var string */
    private $cwd = "";
    /** @var array */
    private $env = [];
    /** @var array */
    private $options;
    /** @var ProcessHandle */
    private $handle;
    /** @var int|null */
    private $pid;
    /**
    * @param (string | string[]) $command Command to run.
    * @param (string | null) $cwd Working directory or use an empty string to use the working directory of the
    parent.
    * @param mixed[] $env Environment variables or use an empty array to inherit from the parent.
    * @param mixed[] $options Options for `proc_open()`.
    *
    * @throws \Error If the arguments are invalid.
    */
    public function __construct($command, string $cwd = null, array $env = [], array $options = [])
    {
        $command = \is_array($command) ? \implode(" ", \array_map(__NAMESPACE__ . "\\escapeArguments", $command)) : (string) $command;
        $cwd = $cwd ?? "";
        $envVars = [];
        foreach ($env as $key => $value) {
            if (\is_array($value)) {
                throw new \Error("\$env cannot accept array values");
            }
            $envVars[(string) $key] = (string) $value;
        }
        $this->command = $command;
        $this->cwd = $cwd;
        $this->env = $envVars;
        $this->options = $options;
        $this->processRunner = Loop::getState(self::class);
        if ($this->processRunner === null) {
            $this->processRunner = IS_WINDOWS ? new WindowsProcessRunner() : new PosixProcessRunner();
            Loop::setState(self::class, $this->processRunner);
        }
    }
    /**
     * Stops the process if it is still running.
     */
    public function __destruct()
    {
        if ($this->handle !== null) {
            $this->processRunner->destroy($this->handle);
        }
    }
    /**
     *
     */
    public function __clone()
    {
        throw new \Error("Cloning is not allowed!");
    }
    /**
     * Start the process.
     *
     * @return Promise<int> Resolves with the PID.
     *
     * @throws StatusError If the process has already been started.
     */
    public function start() : Promise
    {
        if ($this->handle) {
            throw new StatusError("Process has already been started.");
        }
        return call(function () {
            $this->handle = $this->processRunner->start($this->command, $this->cwd, $this->env, $this->options);
            return $this->pid = (yield $this->handle->pidDeferred->promise());
        });
    }
    /**
     * Wait for the process to end.
     *
     * @return Promise<int> Succeeds with process exit code or fails with a ProcessException if the process is killed.
     *
     * @throws StatusError If the process has already been started.
     */
    public function join() : Promise
    {
        if (!$this->handle) {
            throw new StatusError("Process has not been started.");
        }
        return $this->processRunner->join($this->handle);
    }
    /**
     * Forcibly end the process.
     *
     * @throws StatusError If the process is not running.
     * @throws ProcessException If terminating the process fails.
     */
    public function kill()
    {
        if (!$this->isRunning()) {
            throw new StatusError("Process is not running.");
        }
        $this->processRunner->kill($this->handle);
    }
    /**
     * Send a signal signal to the process.
     *
     * @param int $signo Signal number to send to process.
     *
     * @throws StatusError If the process is not running.
     * @throws ProcessException If sending the signal fails.
     */
    public function signal(int $signo)
    {
        if (!$this->isRunning()) {
            throw new StatusError("Process is not running.");
        }
        $this->processRunner->signal($this->handle, $signo);
    }
    /**
     * Returns the PID of the child process.
     *
     * @return int
     *
     * @throws StatusError If the process has not started or has not completed starting.
     */
    public function getPid() : int
    {
        if (!$this->pid) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->pid;
    }
    /**
     * Returns the command to execute.
     *
     * @return string The command to execute.
     */
    public function getCommand() : string
    {
        return $this->command;
    }
    /**
     * Gets the current working directory.
     *
     * @return string The current working directory an empty string if inherited from the current PHP process.
     */
    public function getWorkingDirectory() : string
    {
        if ($this->cwd === "") {
            return \getcwd() ?: "";
        }
        return $this->cwd;
    }
    /**
     * Gets the environment variables array.
     *
     * @return string[] Array of environment variables.
     */
    public function getEnv() : array
    {
        return $this->env;
    }
    /**
     * Gets the options to pass to proc_open().
     *
     * @return mixed[] Array of options.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * Determines if the process is still running.
     *
     * @return bool
     */
    public function isRunning() : bool
    {
        return $this->handle && $this->handle->status !== ProcessStatus::ENDED;
    }
    /**
     * Gets the process input stream (STDIN).
     *
     * @return ProcessOutputStream
     */
    public function getStdin() : ProcessOutputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stdin;
    }
    /**
     * Gets the process output stream (STDOUT).
     *
     * @return ProcessInputStream
     */
    public function getStdout() : ProcessInputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stdout;
    }
    /**
     * Gets the process error stream (STDERR).
     *
     * @return ProcessInputStream
     */
    public function getStderr() : ProcessInputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stderr;
    }
    /**
     *
     */
    public function __debugInfo() : array
    {
        return ['command' => $this->getCommand(), 'cwd' => $this->getWorkingDirectory(), 'env' => $this->getEnv(), 'options' => $this->getOptions(), 'pid' => $this->pid, 'status' => $this->handle ? $this->handle->status : -1];
    }
}
<?php

namespace PhabelVendor\Amp\Process;

use PhabelVendor\Amp\ByteStream\InputStream;
use PhabelVendor\Amp\ByteStream\PendingReadError;
use PhabelVendor\Amp\ByteStream\ResourceInputStream;
use PhabelVendor\Amp\ByteStream\StreamException;
use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
final class ProcessInputStream implements InputStream
{
    /** @var Deferred */
    private $initialRead;
    /** @var bool */
    private $shouldClose = \false;
    /** @var bool */
    private $referenced = \true;
    /** @var ResourceInputStream */
    private $resourceStream;
    /** @var StreamException|null */
    private $error;
    /**
     *
     */
    public function __construct(Promise $resourceStreamPromise)
    {
        $resourceStreamPromise->onResolve(function ($error, $resourceStream) {
            if ($error) {
                $this->error = new StreamException("Failed to launch process", 0, $error);
                if ($this->initialRead) {
                    $initialRead = $this->initialRead;
                    $this->initialRead = null;
                    $initialRead->fail($this->error);
                }
                return;
            }
            $this->resourceStream = $resourceStream;
            if (!$this->referenced) {
                $this->resourceStream->unreference();
            }
            if ($this->shouldClose) {
                $this->resourceStream->close();
            }
            if ($this->initialRead) {
                $initialRead = $this->initialRead;
                $this->initialRead = null;
                $initialRead->resolve($this->shouldClose ? null : $this->resourceStream->read());
            }
        });
    }
    /**
     * Reads data from the stream.
     *
     * @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
     *
     * @throws PendingReadError Thrown if another read operation is still pending.
     */
    public function read() : Promise
    {
        if ($this->initialRead) {
            throw new PendingReadError();
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->resourceStream) {
            return $this->resourceStream->read();
        }
        if ($this->shouldClose) {
            return new Success();
            // Resolve reads on closed streams with null.
        }
        $this->initialRead = new Deferred();
        return $this->initialRead->promise();
    }
    /**
     *
     */
    public function reference()
    {
        $this->referenced = \true;
        if ($this->resourceStream) {
            $this->resourceStream->reference();
        }
    }
    /**
     *
     */
    public function unreference()
    {
        $this->referenced = \false;
        if ($this->resourceStream) {
            $this->resourceStream->unreference();
        }
    }
    /**
     *
     */
    public function close()
    {
        $this->shouldClose = \true;
        if ($this->initialRead) {
            $initialRead = $this->initialRead;
            $this->initialRead = null;
            $initialRead->resolve();
        }
        if ($this->resourceStream) {
            $this->resourceStream->close();
        }
    }
}
<?php

namespace PhabelVendor\Amp\Process;

class ProcessException extends \Exception
{
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Parallel\Context\Parallel;
use PhabelVendor\Amp\Parallel\Context\Thread;
/**
 * Worker factory that includes a custom bootstrap file after initializing the worker.
 */
final class BootstrapWorkerFactory implements WorkerFactory
{
    /** @var string */
    private $bootstrapPath;
    /** @var string */
    private $className;
    /**
    * @param string $bootstrapFilePath Path to custom bootstrap file.
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate in each
    worker. Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    *
    * @throws \Error If the given class name does not exist or does not implement {@see Environment}.
    */
    public function __construct(string $bootstrapFilePath, string $envClassName = BasicEnvironment::class)
    {
        if (!\file_exists($bootstrapFilePath)) {
            throw new \Error(\sprintf("No file found at autoload path given '%s'", $bootstrapFilePath));
        }
        if (!\class_exists($envClassName)) {
            throw new \Error(\sprintf("Invalid environment class name '%s'", $envClassName));
        }
        if (!\is_subclass_of($envClassName, Environment::class)) {
            throw new \Error(\sprintf("The class '%s' does not implement '%s'", $envClassName, Environment::class));
        }
        $this->bootstrapPath = $bootstrapFilePath;
        $this->className = $envClassName;
    }
    /**
    * {@inheritdoc}
    *
    * The type of worker created depends on the extensions available. If multi-threading is enabled, a WorkerThread
    will be created. If threads are not available a WorkerProcess will be created.
    */
    public function create() : Worker
    {
        if (Parallel::isSupported()) {
            return new WorkerParallel($this->className, $this->bootstrapPath);
        }
        if (Thread::isSupported()) {
            return new WorkerThread($this->className, $this->bootstrapPath);
        }
        return new WorkerProcess($this->className, [], \getenv("AMP_PHP_BINARY") ?: (\defined("AMP_PHP_BINARY") ? \AMP_PHP_BINARY : null), $this->bootstrapPath);
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

/**
 * Common interface for exceptions thrown when Task::run() throws an exception when being executed in a worker.
 */
interface TaskFailureThrowable extends \Throwable
{
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string;
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string;
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode();
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array;
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string;
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

/**
 * Interface for factories used to create new workers.
 */
interface WorkerFactory
{
    /**
     * Creates a new worker instance.
     *
     * @return Worker The newly created worker.
     */
    public function create() : Worker;
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

/**
 * Task implementation dispatching a simple callable.
 */
final class CallableTask implements Task
{
    /** @var callable */
    private $callable;
    /** @var mixed[] */
    private $args;
    /**
     * @param callable $callable Callable will be serialized.
     * @param mixed $args Arguments to pass to the function. Must be serializable.
     */
    public function __construct(callable $callable, array $args)
    {
        $this->callable = $callable;
        $this->args = $args;
    }
    /**
     *
     */
    public function run(Environment $environment)
    {
        if ($this->callable instanceof \__PHP_Incomplete_Class) {
            throw new \Error('When using a class instance as a callable, the class must be autoloadable');
        }
        if (\is_array($this->callable) && ($this->callable[0] ?? null) instanceof \__PHP_Incomplete_Class) {
            throw new \Error('When using a class instance method as a callable, the class must be autoloadable');
        }
        if (!\is_callable($this->callable)) {
            $message = 'User-defined functions must be autoloadable (that is, defined in a file autoloaded by composer)';
            if (\is_string($this->callable)) {
                $message .= \sprintf("; unable to load function '%s'", $this->callable);
            }
            throw new \Error($message);
        }
        return ($this->callable)(...$this->args);
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use function PhabelVendor\Amp\Parallel\Sync\formatFlattenedBacktrace;
final class TaskFailureException extends TaskException implements TaskFailureThrowable
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
    * @param string $className Original exception class name.
    * @param string $message Original exception message.
    * @param (int | string) $code Original exception code.
    * @param array $trace Backtrace generated by
    {@see \Amp\Parallel\Sync\flattenThrowableBacktrace()}.
    * @param (TaskFailureThrowable | null) $previous Instance representing any previous exception thrown in the Task.
    */
    public function __construct(string $className, string $message, $code, array $trace, ?TaskFailureThrowable $previous = null)
    {
        $format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the worker';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getWorkerTrace();
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use function PhabelVendor\Amp\Parallel\Sync\formatFlattenedBacktrace;
final class TaskFailureError extends TaskError implements TaskFailureThrowable
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
    * @param string $className Original exception class name.
    * @param string $message Original exception message.
    * @param (int | string) $code Original exception code.
    * @param array $trace Backtrace generated by
    {@see \Amp\Parallel\Sync\flattenThrowableBacktrace()}.
    * @param (TaskFailureThrowable | null) $previous Instance representing any previous exception thrown in the Task.
    */
    public function __construct(string $className, string $message, $code, array $trace, ?TaskFailureThrowable $previous = null)
    {
        $format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the worker';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getWorkerTrace();
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Parallel\Context\StatusError;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\asyncCall;
/**
 * Provides a pool of workers that can be used to execute multiple tasks asynchronously.
 *
 * A worker pool is a collection of worker threads that can perform multiple
 * tasks simultaneously. The load on each worker is balanced such that tasks
 * are completed as soon as possible and workers are used efficiently.
 */
final class DefaultPool implements Pool
{
    /** @var bool Indicates if the pool is currently running. */
    private $running = \true;
    /** @var int The maximum number of workers the pool should spawn. */
    private $maxSize;
    /** @var WorkerFactory A worker factory to be used to create new workers. */
    private $factory;
    /** @var \SplObjectStorage A collection of all workers in the pool. */
    private $workers;
    /** @var \SplQueue A collection of idle workers. */
    private $idleWorkers;
    /** @var \SplQueue A queue of workers that have been assigned to tasks. */
    private $busyQueue;
    /** @var \Closure */
    private $push;
    /** @var Promise|null */
    private $exitStatus;
    /**
    * Creates a new worker pool.
    *
    * @param int $maxSize The maximum number of workers the pool should spawn.
    Defaults to `Pool::DEFAULT_MAX_SIZE`.
    * @param (WorkerFactory | null) $factory A worker factory to be used to create
    new workers.
    *
    * @throws \Error
    */
    public function __construct(int $maxSize = self::DEFAULT_MAX_SIZE, WorkerFactory $factory = null)
    {
        if ($maxSize < 0) {
            throw new \Error("Maximum size must be a non-negative integer");
        }
        $this->maxSize = $maxSize;
        // Use the global factory if none is given.
        $this->factory = $factory ?: factory();
        $this->workers = new \SplObjectStorage();
        $this->idleWorkers = new \SplQueue();
        $this->busyQueue = new \SplQueue();
        $workers = $this->workers;
        $idleWorkers = $this->idleWorkers;
        $busyQueue = $this->busyQueue;
        $this->push = static function (Worker $worker) use($workers, $idleWorkers, $busyQueue) : void {
            if (!$workers->contains($worker) || ($workers[$worker] -= 1) > 0) {
                return;
            }
            // Worker is completely idle, remove from busy queue and add to idle queue.
            foreach ($busyQueue as $key => $busy) {
                if ($busy === $worker) {
                    unset($busyQueue[$key]);
                    break;
                }
            }
            $idleWorkers->push($worker);
        };
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->isRunning()) {
            $this->kill();
        }
    }
    /**
     * Checks if the pool is running.
     *
     * @return bool True if the pool is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->running;
    }
    /**
     * Checks if the pool has any idle workers.
     *
     * @return bool True if the pool has at least one idle worker, otherwise false.
     */
    public function isIdle() : bool
    {
        return $this->idleWorkers->count() > 0 || $this->workers->count() === 0;
    }
    /**
     * {@inheritdoc}
     */
    public function getMaxSize() : int
    {
        return $this->maxSize;
    }
    /**
     * {@inheritdoc}
     */
    public function getWorkerCount() : int
    {
        return $this->workers->count();
    }
    /**
     * {@inheritdoc}
     */
    public function getIdleWorkerCount() : int
    {
        return $this->idleWorkers->count();
    }
    /**
     * Enqueues a {@see Task} to be executed by the worker pool.
     *
     * @param Task $task The task to enqueue.
     *
     * @return Promise<mixed> The return value of Task::run().
     *
     * @throws StatusError If the pool has been shutdown.
     * @throws TaskFailureThrowable If the task throws an exception.
     */
    public function enqueue(Task $task) : Promise
    {
        $worker = $this->pull();
        $promise = $worker->enqueue($task);
        $promise->onResolve(function () use($worker) : void {
            ($this->push)($worker);
        });
        return $promise;
    }
    /**
     * Shuts down the pool and all workers in it.
     *
     * @return Promise<int[]> Array of exit status from all workers.
     *
     * @throws StatusError If the pool has not been started.
     */
    public function shutdown() : Promise
    {
        if ($this->exitStatus) {
            return $this->exitStatus;
        }
        $this->running = \false;
        $shutdowns = [];
        foreach ($this->workers as $worker) {
            if ($worker->isRunning()) {
                $shutdowns[] = $worker->shutdown();
            }
        }
        return $this->exitStatus = Promise\all($shutdowns);
    }
    /**
     * Kills all workers in the pool and halts the worker pool.
     */
    public function kill() : void
    {
        $this->running = \false;
        foreach ($this->workers as $worker) {
            \assert($worker instanceof Worker);
            if ($worker->isRunning()) {
                $worker->kill();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getWorker() : Worker
    {
        return new Internal\PooledWorker($this->pull(), $this->push);
    }
    /**
     * Pulls a worker from the pool.
     *
     * @return Worker
     * @throws StatusError
     */
    private function pull() : Worker
    {
        if (!$this->isRunning()) {
            throw new StatusError("The pool was shutdown");
        }
        do {
            if ($this->idleWorkers->isEmpty()) {
                if ($this->getWorkerCount() >= $this->maxSize) {
                    // All possible workers busy, so shift from head (will be pushed back onto tail below).
                    $worker = $this->busyQueue->shift();
                } else {
                    // Max worker count has not been reached, so create another worker.
                    $worker = $this->factory->create();
                    if (!$worker->isRunning()) {
                        throw new WorkerException('Worker factory did not create a viable worker');
                    }
                    $this->workers->attach($worker, 0);
                    break;
                }
            } else {
                // Shift a worker off the idle queue.
                $worker = $this->idleWorkers->shift();
            }
            \assert($worker instanceof Worker);
            if ($worker->isRunning()) {
                break;
            }
            // Worker crashed; trigger error and remove it from the pool.
            asyncCall(function () use($worker) : \Generator {
                try {
                    $code = (yield $worker->shutdown());
                    \trigger_error('Worker in pool exited unexpectedly with code ' . $code, \E_USER_WARNING);
                } catch (\Throwable $exception) {
                    \trigger_error('Worker in pool crashed with exception on shutdown: ' . $exception->getMessage(), \E_USER_WARNING);
                }
            });
            $this->workers->detach($worker);
        } while (\true);
        $this->busyQueue->push($worker);
        $this->workers[$worker] += 1;
        return $worker;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Promise;
const LOOP_POOL_IDENTIFIER = Pool::class;
const LOOP_FACTORY_IDENTIFIER = WorkerFactory::class;
/**
 * Gets or sets the global worker pool.
 *
 * @param (Pool | null) $pool A worker pool instance.
 *
 * @return Pool The global worker pool instance.
 */
function pool(Pool $pool = null) : Pool
{
    if ($pool === null) {
        $pool = Loop::getState(LOOP_POOL_IDENTIFIER);
        if ($pool) {
            return $pool;
        }
        $pool = new DefaultPool();
    }
    Loop::setState(LOOP_POOL_IDENTIFIER, $pool);
    return $pool;
}
/**
 * Enqueues a task to be executed by the global worker pool.
 *
 * @param Task $task The task to enqueue.
 *
 * @return Promise<mixed>
 */
function enqueue(Task $task) : Promise
{
    return pool()->enqueue($task);
}
/**
 * Enqueues a callable to be executed by the global worker pool.
 *
 * @param callable $callable Callable needs to be serializable.
 * @param mixed ...$args Arguments have to be serializable.
 *
 * @return Promise<mixed>
 */
function enqueueCallable(callable $callable, ...$args)
{
    return enqueue(new CallableTask($callable, $args));
}
/**
 * Gets a worker from the global worker pool.
 *
 * @return \Amp\Parallel\Worker\Worker
 */
function worker() : Worker
{
    return pool()->getWorker();
}
/**
 * Creates a worker using the global worker factory.
 *
 * @return \Amp\Parallel\Worker\Worker
 */
function create() : Worker
{
    return factory()->create();
}
/**
 * Gets or sets the global worker factory.
 *
 * @param (WorkerFactory | null) $factory
 *
 * @return WorkerFactory
 */
function factory(WorkerFactory $factory = null) : WorkerFactory
{
    if ($factory === null) {
        $factory = Loop::getState(LOOP_FACTORY_IDENTIFIER);
        if ($factory) {
            return $factory;
        }
        $factory = new DefaultWorkerFactory();
    }
    Loop::setState(LOOP_FACTORY_IDENTIFIER, $factory);
    return $factory;
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

class WorkerException extends \Exception
{
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Struct;
final class BasicEnvironment implements Environment
{
    /** @var array */
    private $data = [];
    /** @var \SplPriorityQueue */
    private $queue;
    /** @var string */
    private $timer;
    /**
     *
     */
    public function __construct()
    {
        $this->queue = $queue = new \SplPriorityQueue();
        $data =& $this->data;
        $this->timer = Loop::repeat(1000, static function (string $watcherId) use($queue, &$data) : void {
            $time = \time();
            while (!$queue->isEmpty()) {
                list($key, $expiration) = $queue->top();
                if (!isset($data[$key])) {
                    // Item removed.
                    $queue->extract();
                    continue;
                }
                $struct = $data[$key];
                if ($struct->expire === 0) {
                    // Item was set again without a TTL.
                    $queue->extract();
                    continue;
                }
                if ($struct->expire !== $expiration) {
                    // Expiration changed or TTL updated.
                    $queue->extract();
                    continue;
                }
                if ($time < $struct->expire) {
                    // Item at top has not expired, break out of loop.
                    break;
                }
                unset($data[$key]);
                $queue->extract();
            }
            if ($queue->isEmpty()) {
                Loop::disable($watcherId);
            }
        });
        Loop::disable($this->timer);
        Loop::unreference($this->timer);
    }
    /**
     * @param string $key
     *
     * @return bool
     */
    public function exists(string $key) : bool
    {
        return isset($this->data[$key]);
    }
    /**
     * @param string $key
     *
     * @return (mixed | null) Returns null if the key does not exist.
     */
    public function get(string $key)
    {
        if (!isset($this->data[$key])) {
            return null;
        }
        $struct = $this->data[$key];
        if ($struct->ttl !== null) {
            $expire = \time() + $struct->ttl;
            if ($struct->expire < $expire) {
                $struct->expire = $expire;
                $this->queue->insert([$key, $struct->expire], -$struct->expire);
            }
        }
        return $struct->data;
    }
    /**
     * @param string $key
     * @param mixed $value Using null for the value deletes the key.
     * @param int $ttl Number of seconds until data is automatically deleted. Use null for unlimited TTL.
     *
     * @throws \Error If the time-to-live is not a positive integer.
     */
    public function set(string $key, $value, int $ttl = null) : void
    {
        if ($value === null) {
            $this->delete($key);
            return;
        }
        if ($ttl !== null && $ttl <= 0) {
            throw new \Error("The time-to-live must be a positive integer or null");
        }
        $struct = new class
        {
            use Struct;
            public $data;
            public $expire = 0;
            public $ttl;
        };
        $struct->data = $value;
        if ($ttl !== null) {
            $struct->ttl = $ttl;
            $struct->expire = \time() + $ttl;
            $this->queue->insert([$key, $struct->expire], -$struct->expire);
            Loop::enable($this->timer);
        }
        $this->data[$key] = $struct;
    }
    /**
     * @param string $key
     */
    public function delete(string $key) : void
    {
        unset($this->data[$key]);
    }
    /**
     * Alias of exists().
     *
     * @param $key
     *
     * @return bool
     */
    public function offsetExists($key) : bool
    {
        return $this->exists($key);
    }
    /**
     * Alias of get().
     *
     * @param string $key
     *
     * @return mixed
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($key)
    {
        return $this->get($key);
    }
    /**
     * Alias of set() with $ttl = null.
     *
     * @param string $key
     * @param mixed $value
     */
    public function offsetSet($key, $value) : void
    {
        $this->set($key, $value);
    }
    /**
     * Alias of delete().
     *
     * @param string $key
     */
    public function offsetUnset($key) : void
    {
        $this->delete($key);
    }
    /**
     * Removes all values.
     */
    public function clear() : void
    {
        $this->data = [];
        Loop::disable($this->timer);
        $this->queue = new \SplPriorityQueue();
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker\Internal;

use PhabelVendor\Amp\Parallel\Worker\Task;
/** @internal */
final class Job
{
    /** @var string */
    private $id;
    /** @var Task */
    private $task;
    /**
     *
     */
    public function __construct(Task $task)
    {
        static $id = 'a';
        $this->task = $task;
        $this->id = $id++;
    }
    /**
     *
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     *
     */
    public function getTask() : Task
    {
        // Classes that cannot be autoloaded will be unserialized as an instance of __PHP_Incomplete_Class.
        if ($this->task instanceof \__PHP_Incomplete_Class) {
            throw new \Error(\sprintf("Classes implementing %s must be autoloadable by the Composer autoloader", Task::class));
        }
        return $this->task;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker\Internal;

use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Parallel\Sync;
use PhabelVendor\Amp\Parallel\Worker\TaskFailureError;
use PhabelVendor\Amp\Parallel\Worker\TaskFailureException;
use PhabelVendor\Amp\Parallel\Worker\TaskFailureThrowable;
use PhabelVendor\Amp\Promise;
/** @internal */
final class TaskFailure extends TaskResult
{
    const PARENT_EXCEPTION = 0;
    const PARENT_ERROR = 1;
    /** @var string */
    private $type;
    /** @var int */
    private $parent;
    /** @var string */
    private $message;
    /** @var int|string */
    private $code;
    /** @var string[] */
    private $trace;
    /** @var self|null */
    private $previous;
    /**
     *
     */
    public function __construct(string $id, \Throwable $exception)
    {
        parent::__construct($id);
        $this->type = \get_class($exception);
        $this->parent = $exception instanceof \Error ? self::PARENT_ERROR : self::PARENT_EXCEPTION;
        $this->message = $exception->getMessage();
        $this->code = $exception->getCode();
        $this->trace = Sync\flattenThrowableBacktrace($exception);
        if ($previous = $exception->getPrevious()) {
            $this->previous = new self($id, $previous);
        }
    }
    /**
     *
     */
    public function promise() : Promise
    {
        return new Failure($this->createException());
    }
    /**
     *
     */
    private function createException() : TaskFailureThrowable
    {
        $previous = $this->previous ? $this->previous->createException() : null;
        if ($this->parent === self::PARENT_ERROR) {
            return new TaskFailureError($this->type, $this->message, $this->code, $this->trace, $previous);
        }
        return new TaskFailureException($this->type, $this->message, $this->code, $this->trace, $previous);
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker\Internal;

use PhabelVendor\Amp\Parallel\Worker\Task;
use PhabelVendor\Amp\Parallel\Worker\Worker;
use PhabelVendor\Amp\Promise;
/** @internal */
final class PooledWorker implements Worker
{
    /** @var callable */
    private $push;
    /** @var Worker */
    private $worker;
    /**
     * @param Worker $worker
     * @param callable $push Callable to push the worker back into the queue.
     */
    public function __construct(Worker $worker, callable $push)
    {
        $this->worker = $worker;
        $this->push = $push;
    }
    /**
     * Automatically pushes the worker back into the queue.
     */
    public function __destruct()
    {
        ($this->push)($this->worker);
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        return $this->worker->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function isIdle() : bool
    {
        return $this->worker->isIdle();
    }
    /**
     * {@inheritdoc}
     */
    public function enqueue(Task $task) : Promise
    {
        return $this->worker->enqueue($task);
    }
    /**
     * {@inheritdoc}
     */
    public function shutdown() : Promise
    {
        return $this->worker->shutdown();
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        $this->worker->kill();
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker\Internal;

use PhabelVendor\Amp\ByteStream;
use PhabelVendor\Amp\Parallel\Context\Context;
use PhabelVendor\Amp\Parallel\Context\Process;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
class WorkerProcess implements Context
{
    /** @var Process */
    private $process;
    /**
     *
     */
    public function __construct($script, array $env = [], string $binary = null)
    {
        $this->process = new Process($script, null, $env, $binary);
    }
    /**
     *
     */
    public function receive() : Promise
    {
        return $this->process->receive();
    }
    /**
     *
     */
    public function send($data) : Promise
    {
        return $this->process->send($data);
    }
    /**
     *
     */
    public function isRunning() : bool
    {
        return $this->process->isRunning();
    }
    /**
     *
     */
    public function start() : Promise
    {
        return call(function () {
            $result = (yield $this->process->start());
            $stdout = $this->process->getStdout();
            $stdout->unreference();
            $stderr = $this->process->getStderr();
            $stderr->unreference();
            ByteStream\pipe($stdout, ByteStream\getStdout());
            ByteStream\pipe($stderr, ByteStream\getStderr());
            return $result;
        });
    }
    /**
     *
     */
    public function kill() : void
    {
        if ($this->process->isRunning()) {
            $this->process->kill();
        }
    }
    /**
     *
     */
    public function join() : Promise
    {
        return $this->process->join();
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker\Internal;

use PhabelVendor\Amp\Parallel\Sync;
use PhabelVendor\Amp\Parallel\Worker;
use PhabelVendor\Amp\Promise;
return function (Sync\Channel $channel) use($argc, $argv) : Promise {
    if (!\defined("AMP_WORKER")) {
        \define("AMP_WORKER", \AMP_CONTEXT);
    }
    if (isset($argv[2])) {
        if (!\is_file($argv[2])) {
            throw new \Error(\sprintf("No file found at bootstrap file path given '%s'", $argv[2]));
        }
        // Include file within closure to protect scope.
        (function () use($argc, $argv) : void {
            require $argv[2];
        })();
    }
    if (!isset($argv[1])) {
        throw new \Error("No environment class name provided");
    }
    $className = $argv[1];
    if (!\class_exists($className)) {
        throw new \Error(\sprintf("Invalid environment class name '%s'", $className));
    }
    if (!\is_subclass_of($className, Worker\Environment::class)) {
        throw new \Error(\sprintf("The class '%s' does not implement '%s'", $className, Worker\Environment::class));
    }
    $environment = new $className();
    $runner = new Worker\TaskRunner($channel, $environment);
    return $runner->run();
};
<?php

namespace PhabelVendor\Amp\Parallel\Worker\Internal;

use PhabelVendor\Amp\Promise;
/** @internal */
abstract class TaskResult
{
    /** @var string Task identifier. */
    private $id;
    /**
     * @param string $id Task identifier.
     */
    public function __construct(string $id)
    {
        $this->id = $id;
    }
    /**
     * @return string Task identifier.
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     * @return Promise<mixed> Resolved with the task result or failure reason.
     */
    public abstract function promise() : Promise;
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker\Internal;

use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Parallel\Worker\Task;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
/** @internal */
final class TaskSuccess extends TaskResult
{
    /** @var mixed Result of task. */
    private $result;
    /**
     *
     */
    public function __construct(string $id, $result)
    {
        parent::__construct($id);
        $this->result = $result;
    }
    /**
     *
     */
    public function promise() : Promise
    {
        if ($this->result instanceof \__PHP_Incomplete_Class) {
            return new Failure(new \Error(\sprintf("Class instances returned from %s::run() must be autoloadable by the Composer autoloader", Task::class)));
        }
        return new Success($this->result);
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

/**
 * An interface for worker pools.
 */
interface Pool extends Worker
{
    /** @var int The default maximum pool size. */
    const DEFAULT_MAX_SIZE = 32;
    /**
    * Gets a worker from the pool. The worker is marked as busy and will only be reused if the pool runs out of
    idle workers. The worker will be automatically marked as idle once no references to the returned worker remain.
    *
    * @return \Amp\Parallel\Worker\Worker
    *
    * @throws \Amp\Parallel\Context\StatusError If the queue is not running.
    */
    public function getWorker() : Worker;
    /**
     * Gets the number of workers currently running in the pool.
     *
     * @return int The number of workers.
     */
    public function getWorkerCount() : int;
    /**
     * Gets the number of workers that are currently idle.
     *
     * @return int The number of idle workers.
     */
    public function getIdleWorkerCount() : int;
    /**
     * Gets the maximum number of workers the pool may spawn to handle concurrent tasks.
     *
     * @return int The maximum number of workers.
     */
    public function getMaxSize() : int;
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

/**
 * @deprecated TaskFailureException will be thrown from failed Tasks instead of this class.
 */
class TaskException extends \Exception
{
    /** @var string Class name of exception thrown from task. */
    private $name;
    /** @var string Stack trace of the exception thrown from task. */
    private $trace;
    /**
     * @param string $name The exception class name.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalClassName() instead.
     *
     * Returns the class name of the exception thrown from the task.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the exception was thrown in the task.
     *
     * @return string
     */
    public function getWorkerTrace() : string
    {
        return $this->trace;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Parallel\Context\Thread;
use PhabelVendor\Amp\Parallel\Sync\Channel;
use PhabelVendor\Amp\Promise;
/**
 * A worker thread that executes task objects.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class WorkerThread extends TaskWorker
{
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param (string | null) $bootstrapPath Path to custom autoloader.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, string $bootstrapPath = null)
    {
        parent::__construct(new Thread(static function (Channel $channel, string $className, string $bootstrapPath = null) : Promise {
            if ($bootstrapPath !== null) {
                if (!\is_file($bootstrapPath)) {
                    throw new \Error(\sprintf("No file found at bootstrap file path given '%s'", $bootstrapPath));
                }
                // Include file within unbound closure to protect scope.
                (static function () use($bootstrapPath) : void {
                    require $bootstrapPath;
                })->bindTo(null, null)();
            }
            if (!\class_exists($className)) {
                throw new \Error(\sprintf("Invalid environment class name '%s'", $className));
            }
            if (!\is_subclass_of($className, Environment::class)) {
                throw new \Error(\sprintf("The class '%s' does not implement '%s'", $className, Environment::class));
            }
            $environment = new $className();
            if (!\defined("AMP_WORKER")) {
                \define("AMP_WORKER", \AMP_CONTEXT);
            }
            $runner = new TaskRunner($channel, $environment);
            return $runner->run();
        }, $envClassName, $bootstrapPath));
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

interface Environment extends \ArrayAccess
{
    /**
     * @param string $key
     *
     * @return bool
     */
    public function exists(string $key) : bool;
    /**
     * @param string $key
     *
     * @return (mixed | null) Returns null if the key does not exist.
     */
    public function get(string $key);
    /**
     * @param string $key
     * @param mixed $value Using null for the value deletes the key.
     * @param int $ttl Number of seconds until data is automatically deleted. Use null for unlimited TTL.
     */
    public function set(string $key, $value, int $ttl = null);
    /**
     * @param string $key
     */
    public function delete(string $key);
    /**
     * Removes all values.
     */
    public function clear();
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Parallel\Sync\Channel;
use PhabelVendor\Amp\Parallel\Sync\SerializationException;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
final class TaskRunner
{
    /** @var Channel */
    private $channel;
    /** @var Environment */
    private $environment;
    /**
     *
     */
    public function __construct(Channel $channel, Environment $environment)
    {
        $this->channel = $channel;
        $this->environment = $environment;
    }
    /**
     * Runs the task runner, receiving tasks from the parent and sending the result of those tasks.
     *
     * @return \Amp\Promise
     */
    public function run() : Promise
    {
        return new Coroutine($this->execute());
    }
    /**
     * @coroutine
     *
     * @return \Generator
     */
    private function execute() : \Generator
    {
        $job = (yield $this->channel->receive());
        while ($job instanceof Internal\Job) {
            try {
                $result = (yield call([$job->getTask(), "run"], $this->environment));
                $result = new Internal\TaskSuccess($job->getId(), $result);
            } catch (\Throwable $exception) {
                $result = new Internal\TaskFailure($job->getId(), $exception);
            }
            $job = null;
            // Free memory from last job.
            try {
                (yield $this->channel->send($result));
            } catch (SerializationException $exception) {
                // Could not serialize task result.
                (yield $this->channel->send(new Internal\TaskFailure($result->getId(), $exception)));
            }
            $result = null;
            // Free memory from last result.
            $job = (yield $this->channel->receive());
        }
        return $job;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Parallel\Context\Context;
use PhabelVendor\Amp\Parallel\Context\StatusError;
use PhabelVendor\Amp\Parallel\Sync\ChannelException;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
use PhabelVendor\Amp\TimeoutException;
use function PhabelVendor\Amp\call;
/**
 * Base class for most common types of task workers.
 */
abstract class TaskWorker implements Worker
{
    const SHUTDOWN_TIMEOUT = 1000;
    const ERROR_TIMEOUT = 250;
    /** @var Context */
    private $context;
    /** @var bool */
    private $started = \false;
    /** @var Promise|null */
    private $pending;
    /** @var Promise|null */
    private $exitStatus;
    /**
     * @param Context $context A context running an instance of TaskRunner.
     */
    public function __construct(Context $context)
    {
        if ($context->isRunning()) {
            throw new \Error("The context was already running");
        }
        $this->context = $context;
        $context =& $this->context;
        $pending =& $this->pending;
        \register_shutdown_function(static function () use(&$context, &$pending) : void {
            if ($context === null || !$context->isRunning()) {
                return;
            }
            try {
                Promise\wait(Promise\timeout(call(function () use($context, $pending) : \Generator {
                    if ($pending) {
                        (yield $pending);
                    }
                    (yield $context->send(0));
                    return (yield $context->join());
                }), self::SHUTDOWN_TIMEOUT));
            } catch (\Throwable $exception) {
                if ($context !== null) {
                    $context->kill();
                }
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        // Report as running unless shutdown or crashed.
        return !$this->started || $this->exitStatus === null && $this->context !== null && $this->context->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function isIdle() : bool
    {
        return $this->pending === null;
    }
    /**
     * {@inheritdoc}
     */
    public function enqueue(Task $task) : Promise
    {
        if ($this->exitStatus) {
            throw new StatusError("The worker has been shut down");
        }
        $promise = $this->pending = call(function () use($task) : \Generator {
            if ($this->pending) {
                try {
                    (yield $this->pending);
                } catch (\Throwable $exception) {
                    // Ignore error from prior job.
                }
            }
            if ($this->exitStatus !== null || $this->context === null) {
                throw new WorkerException("The worker was shutdown");
            }
            if (!$this->context->isRunning()) {
                if ($this->started) {
                    throw new WorkerException("The worker crashed");
                }
                $this->started = \true;
                (yield $this->context->start());
            }
            $job = new Internal\Job($task);
            try {
                (yield $this->context->send($job));
                $result = (yield $this->context->receive());
            } catch (ChannelException $exception) {
                try {
                    (yield Promise\timeout($this->context->join(), self::ERROR_TIMEOUT));
                } catch (TimeoutException $timeout) {
                    $this->kill();
                    throw new WorkerException("The worker failed unexpectedly", 0, $exception);
                }
                throw new WorkerException("The worker exited unexpectedly", 0, $exception);
            }
            if (!$result instanceof Internal\TaskResult) {
                $this->kill();
                throw new WorkerException("Context did not return a task result");
            }
            if ($result->getId() !== $job->getId()) {
                $this->kill();
                throw new WorkerException("Task results returned out of order");
            }
            return $result->promise();
        });
        $promise->onResolve(function () use($promise) : void {
            if ($this->pending === $promise) {
                $this->pending = null;
            }
        });
        return $promise;
    }
    /**
     * {@inheritdoc}
     */
    public function shutdown() : Promise
    {
        if ($this->exitStatus !== null) {
            return $this->exitStatus;
        }
        if ($this->context === null || !$this->context->isRunning()) {
            return $this->exitStatus = new Success(-1);
            // Context crashed?
        }
        return $this->exitStatus = call(function () : \Generator {
            if ($this->pending) {
                // If a task is currently running, wait for it to finish.
                (yield Promise\any([$this->pending]));
            }
            (yield $this->context->send(0));
            try {
                return (yield Promise\timeout($this->context->join(), self::SHUTDOWN_TIMEOUT));
            } catch (\Throwable $exception) {
                $this->context->kill();
                throw new WorkerException("Failed to gracefully shutdown worker", 0, $exception);
            } finally {
                // Null properties to free memory because the shutdown function has references to these.
                $this->context = null;
                $this->pending = null;
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        if ($this->exitStatus !== null || $this->context === null) {
            return;
        }
        if ($this->context->isRunning()) {
            $this->context->kill();
            $this->exitStatus = new Failure(new WorkerException("The worker was killed"));
            return;
        }
        $this->exitStatus = new Success(0);
        // Null properties to free memory because the shutdown function has references to these.
        $this->context = null;
        $this->pending = null;
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Promise;
/**
 * An interface for a parallel worker thread that runs a queue of tasks.
 */
interface Worker
{
    /**
     * Checks if the worker is running.
     *
     * @return bool True if the worker is running, otherwise false.
     */
    public function isRunning() : bool;
    /**
     * Checks if the worker is currently idle.
     *
     * @return bool
     */
    public function isIdle() : bool;
    /**
     * Enqueues a {@see Task} to be executed by the worker.
     *
     * @param Task $task The task to enqueue.
     *
     * @return Promise<mixed> Resolves with the return value of {@see Task::run()}.
     *
     * @throws TaskFailureThrowable Promise fails if {@see Task::run()} throws an exception.
     */
    public function enqueue(Task $task) : Promise;
    /**
     * @return Promise<int> Resolves with the worker exit code.
     */
    public function shutdown() : Promise;
    /**
     * Immediately kills the context.
     */
    public function kill();
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

/**
 * A worker process that executes task objects.
 */
final class WorkerProcess extends TaskWorker
{
    const SCRIPT_PATH = __DIR__ . "/Internal/worker-process.php";
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param mixed[] $env Array of environment variables to pass to the worker. Empty array inherits from the current
    PHP process. See the $env parameter of \Amp\Process\Process::__construct().
    * @param (string | null) $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    * @param (string | null) $bootstrapPath Path to custom bootstrap file.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, array $env = [], string $binary = null, string $bootstrapPath = null)
    {
        $script = [self::SCRIPT_PATH, $envClassName];
        if ($bootstrapPath !== null) {
            $script[] = $bootstrapPath;
        }
        parent::__construct(new Internal\WorkerProcess($script, $env, $binary));
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Parallel\Context\Parallel;
/**
 * A worker parallel extension thread that executes task objects.
 */
final class WorkerParallel extends TaskWorker
{
    const SCRIPT_PATH = __DIR__ . "/Internal/worker-process.php";
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param string|null Path to custom bootstrap file.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, string $bootstrapPath = null)
    {
        $script = [self::SCRIPT_PATH, $envClassName];
        if ($bootstrapPath !== null) {
            $script[] = $bootstrapPath;
        }
        parent::__construct(new Parallel($script));
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

/**
 * A runnable unit of execution.
 */
interface Task
{
    /**
     * Runs the task inside the caller's context.
     *
     * Does not have to be a coroutine, can also be a regular function returning a value.
     *
     * @param \Amp\Parallel\Worker\Environment
     *
     * @return (mixed | \Amp\Promise | \Generator)
     */
    public function run(Environment $environment);
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

use PhabelVendor\Amp\Parallel\Context\Parallel;
use PhabelVendor\Amp\Parallel\Context\Thread;
/**
 * The built-in worker factory type.
 */
final class DefaultWorkerFactory implements WorkerFactory
{
    /** @var string */
    private $className;
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate in each
    worker. Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    *
    * @throws \Error If the given class name does not exist or does not implement {@see Environment}.
    */
    public function __construct(string $envClassName = BasicEnvironment::class)
    {
        if (!\class_exists($envClassName)) {
            throw new \Error(\sprintf("Invalid environment class name '%s'", $envClassName));
        }
        if (!\is_subclass_of($envClassName, Environment::class)) {
            throw new \Error(\sprintf("The class '%s' does not implement '%s'", $envClassName, Environment::class));
        }
        $this->className = $envClassName;
    }
    /**
    * {@inheritdoc}
    *
    * The type of worker created depends on the extensions available. If multi-threading is enabled, a WorkerThread
    will be created. If threads are not available a WorkerProcess will be created.
    */
    public function create() : Worker
    {
        if (Parallel::isSupported()) {
            return new WorkerParallel($this->className);
        }
        if (Thread::isSupported()) {
            return new WorkerThread($this->className);
        }
        return new WorkerProcess($this->className, [], \getenv("AMP_PHP_BINARY") ?: (\defined("AMP_PHP_BINARY") ? \AMP_PHP_BINARY : null));
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Worker;

/**
 * @deprecated TaskFailureError will be thrown from failed Tasks instead of this class.
 */
class TaskError extends \Error
{
    /** @var string Class name of error thrown from task. */
    private $name;
    /** @var string Stack trace of the error thrown from task. */
    private $trace;
    /**
     * @param string $name The exception class name.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalClassName() instead.
     *
     * Returns the class name of the error thrown from the task.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the error was thrown in the task.
     *
     * @return string
     */
    public function getWorkerTrace() : string
    {
        return $this->trace;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

final class ContextPanicError extends PanicError
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
     * @param string $className Original exception class name.
     * @param string $message Original exception message.
     * @param (int | string) $code Original exception code.
     * @param array $trace Backtrace generated by {@see formatFlattenedBacktrace()}.
     * @param (self | null) $previous Instance representing any previous exception thrown in the child process or thread.
     */
    public function __construct(string $className, string $message, $code, array $trace, ?self $previous = null)
    {
        $format = 'Uncaught %s in child process or thread with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the child process or thread';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getPanicTrace();
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

class SharedMemoryException extends ParcelException
{
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

final class ExitFailure implements ExitResult
{
    /** @var string */
    private $type;
    /** @var string */
    private $message;
    /** @var int|string */
    private $code;
    /** @var string[] */
    private $trace;
    /** @var self|null */
    private $previous;
    /**
     *
     */
    public function __construct(\Throwable $exception)
    {
        $this->type = \get_class($exception);
        $this->message = $exception->getMessage();
        $this->code = $exception->getCode();
        $this->trace = flattenThrowableBacktrace($exception);
        if ($previous = $exception->getPrevious()) {
            $this->previous = new self($previous);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getResult()
    {
        throw $this->createException();
    }
    /**
     *
     */
    private function createException() : ContextPanicError
    {
        $previous = $this->previous ? $this->previous->createException() : null;
        return new ContextPanicError($this->type, $this->message, $this->code, $this->trace, $previous);
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

final class ExitSuccess implements ExitResult
{
    /** @var mixed */
    private $result;
    /**
     *
     */
    public function __construct($result)
    {
        $this->result = $result;
    }
    /**
     * {@inheritdoc}
     */
    public function getResult()
    {
        return $this->result;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Serialization\NativeSerializer;
use PhabelVendor\Amp\Serialization\Serializer;
use PhabelVendor\Amp\Sync\Lock;
use PhabelVendor\Amp\Sync\PosixSemaphore;
use PhabelVendor\Amp\Sync\SyncException;
use function PhabelVendor\Amp\call;
/**
 * A container object for sharing a value across contexts.
 *
 * A shared object is a container that stores an object inside shared memory.
 * The object can be accessed and mutated by any thread or process. The shared
 * object handle itself is serializable and can be sent to any thread or process
 * to give access to the value that is shared in the container.
 *
 * Because each shared object uses its own shared memory segment, it is much
 * more efficient to store a larger object containing many values inside a
 * single shared container than to use many small shared containers.
 *
 * Note that accessing a shared object is not atomic. Access to a shared object
 * should be protected with a mutex to preserve data integrity.
 *
 * When used with forking, the object must be created prior to forking for both
 * processes to access the synchronized object.
 *
 * @see http://php.net/manual/en/book.shmop.php The shared memory extension.
 * @see http://man7.org/linux/man-pages/man2/shmctl.2.html How shared memory works on Linux.
 * @see https://msdn.microsoft.com/en-us/library/ms810613.aspx How shared memory works on Windows.
 */
final class SharedMemoryParcel implements Parcel
{
    /** @var int The byte offset to the start of the object data in memory. */
    const MEM_DATA_OFFSET = 7;
    // A list of valid states the object can be in.
    const STATE_UNALLOCATED = 0;
    const STATE_ALLOCATED = 1;
    const STATE_MOVED = 2;
    const STATE_FREED = 3;
    /** @var string */
    private $id;
    /** @var int The shared memory segment key. */
    private $key;
    /** @var PosixSemaphore A semaphore for synchronizing on the parcel. */
    private $semaphore;
    /** @var resource|null An open handle to the shared memory segment. */
    private $handle;
    /** @var int */
    private $initializer = 0;
    /** @var Serializer */
    private $serializer;
    /**
    * @param string $id
    * @param mixed $value
    * @param int $size The initial size in bytes of the shared memory segment. It will automatically be expanded as
    necessary.
    * @param int $permissions Permissions to access the semaphore. Use file permission format specified as 0xxx.
    * @param (Serializer | null) $serializer
    *
    * @return self
    *
    * @throws SharedMemoryException
    * @throws SyncException
    * @throws \Error If the size or permissions are invalid.
    */
    public static function create(string $id, $value, int $size = 8192, int $permissions = 0600, ?Serializer $serializer = null) : self
    {
        $parcel = new self($id, $serializer);
        $parcel->init($value, $size, $permissions);
        return $parcel;
    }
    /**
     * @param string $id
     * @param (Serializer | null) $serializer
     *
     * @return self
     *
     * @throws SharedMemoryException
     */
    public static function use(string $id, ?Serializer $serializer = null) : self
    {
        $parcel = new self($id, $serializer);
        $parcel->open();
        return $parcel;
    }
    /**
     * @param string $id
     * @param (Serializer | null) $serializer
     */
    private function __construct(string $id, ?Serializer $serializer = null)
    {
        if (!\extension_loaded("shmop")) {
            throw new \Error(__CLASS__ . " requires the shmop extension");
        }
        $this->id = $id;
        $this->key = self::makeKey($this->id);
        $this->serializer = $serializer ?? new NativeSerializer();
    }
    /**
     * @param mixed $value
     * @param int $size
     * @param int $permissions
     *
     * @throws SharedMemoryException
     * @throws SyncException
     * @throws \Error If the size or permissions are invalid.
     */
    private function init($value, int $size = 8192, int $permissions = 0600) : void
    {
        if ($size <= 0) {
            throw new \Error('The memory size must be greater than 0');
        }
        if ($permissions <= 0 || $permissions > 0777) {
            throw new \Error('Invalid permissions');
        }
        $this->semaphore = PosixSemaphore::create($this->id, 1);
        $this->initializer = \getmypid();
        $this->memOpen($this->key, 'n', $permissions, $size + self::MEM_DATA_OFFSET);
        $this->setHeader(self::STATE_ALLOCATED, 0, $permissions);
        $this->wrap($value);
    }
    /**
     *
     */
    private function open() : void
    {
        $this->semaphore = PosixSemaphore::use($this->id);
        $this->memOpen($this->key, 'w', 0, 0);
    }
    /**
    * Checks if the object has been freed.
    *
    * Note that this does not check if the object has been destroyed; it only
    checks if this handle has freed its reference to the object.
    *
    * @return bool True if the object is freed, otherwise false.
    */
    private function isFreed() : bool
    {
        // If we are no longer connected to the memory segment, check if it has
        // been invalidated.
        if ($this->handle !== null) {
            $this->handleMovedMemory();
            $header = $this->getHeader();
            return $header['state'] === static::STATE_FREED;
        }
        return \true;
    }
    /**
     * {@inheritdoc}
     */
    public function unwrap() : Promise
    {
        return call(function () {
            $lock = (yield $this->semaphore->acquire());
            \assert($lock instanceof Lock);
            try {
                return $this->getValue();
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * @return mixed
     *
     * @throws SharedMemoryException
     * @throws SerializationException
     */
    private function getValue()
    {
        if ($this->isFreed()) {
            throw new SharedMemoryException('The object has already been freed');
        }
        $header = $this->getHeader();
        // Make sure the header is in a valid state and format.
        if ($header['state'] !== self::STATE_ALLOCATED || $header['size'] <= 0) {
            throw new SharedMemoryException('Shared object memory is corrupt');
        }
        // Read the actual value data from memory and unserialize it.
        $data = $this->memGet(self::MEM_DATA_OFFSET, $header['size']);
        return $this->serializer->unserialize($data);
    }
    /**
    * If the value requires more memory to store than currently allocated, a
    new shared memory segment will be allocated with a larger size to store
    the value in. The previous memory segment will be cleaned up and marked
    for deletion. Other processes and threads will be notified of the new
    memory segment on the next read attempt. Once all running processes and
    threads disconnect from the old segment, it will be freed by the OS.
    */
    private function wrap($value) : void
    {
        if ($this->isFreed()) {
            throw new SharedMemoryException('The object has already been freed');
        }
        $serialized = $this->serializer->serialize($value);
        $size = \strlen($serialized);
        $header = $this->getHeader();
        /* If we run out of space, we need to allocate a new shared memory
              segment that is larger than the current one. To coordinate with other
              processes, we will leave a message in the old segment that the segment
              has moved and along with the new key. The old segment will be discarded
              automatically after all other processes notice the change and close
              the old handle.
           */
        if (\shmop_size($this->handle) < $size + self::MEM_DATA_OFFSET) {
            $this->key = $this->key < 0xffffffff ? $this->key + 1 : \random_int(0x10, 0xfffffffe);
            $this->setHeader(self::STATE_MOVED, $this->key, 0);
            $this->memDelete();
            \shmop_close($this->handle);
            $this->memOpen($this->key, 'n', $header['permissions'], $size * 2);
        }
        // Rewrite the header and the serialized value to memory.
        $this->setHeader(self::STATE_ALLOCATED, $size, $header['permissions']);
        $this->memSet(self::MEM_DATA_OFFSET, $serialized);
    }
    /**
     * {@inheritdoc}
     */
    public function synchronized(callable $callback) : Promise
    {
        return call(function () use($callback) : \Generator {
            $lock = (yield $this->semaphore->acquire());
            \assert($lock instanceof Lock);
            try {
                $result = (yield call($callback, $this->getValue()));
                if ($result !== null) {
                    $this->wrap($result);
                }
            } finally {
                $lock->release();
            }
            return $result;
        });
    }
    /**
    * Frees the shared object from memory.
    *
    * The memory containing the shared value will be invalidated. When all
    process disconnect from the object, the shared memory block will be
    destroyed by the OS.
    */
    public function __destruct()
    {
        if ($this->initializer === 0 || $this->initializer !== \getmypid()) {
            return;
        }
        if ($this->isFreed()) {
            return;
        }
        // Invalidate the memory block by setting its state to FREED.
        $this->setHeader(static::STATE_FREED, 0, 0);
        // Request the block to be deleted, then close our local handle.
        $this->memDelete();
        \shmop_close($this->handle);
        $this->handle = null;
        $this->semaphore = null;
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * Prevent serialization.
     */
    public function __sleep()
    {
        throw new \Error('A shared memory parcel cannot be serialized!');
    }
    /**
    * Updates the current memory segment handle, handling any moves made on the
    data.
    *
    * @throws SharedMemoryException
    */
    private function handleMovedMemory() : void
    {
        // Read from the memory block and handle moved blocks until we find the
        // correct block.
        while (\true) {
            $header = $this->getHeader();
            // If the state is STATE_MOVED, the memory is stale and has been moved
            // to a new location. Move handle and try to read again.
            if ($header['state'] !== self::STATE_MOVED) {
                break;
            }
            \shmop_close($this->handle);
            $this->key = $header['size'];
            $this->memOpen($this->key, 'w', 0, 0);
        }
    }
    /**
     * Reads and returns the data header at the current memory segment.
     *
     * @return array An associative array of header data.
     *
     * @throws SharedMemoryException
     */
    private function getHeader() : array
    {
        $data = $this->memGet(0, self::MEM_DATA_OFFSET);
        return \unpack('Cstate/Lsize/Spermissions', $data);
    }
    /**
     * Sets the header data for the current memory segment.
     *
     * @param int $state An object state.
     * @param int $size The size of the stored data, or other value.
     * @param int $permissions The permissions mask on the memory segment.
     *
     * @throws SharedMemoryException
     */
    private function setHeader(int $state, int $size, int $permissions) : void
    {
        $header = \pack('CLS', $state, $size, $permissions);
        $this->memSet(0, $header);
    }
    /**
     * Opens a shared memory handle.
     *
     * @param int $key The shared memory key.
     * @param string $mode The mode to open the shared memory in.
     * @param int $permissions Process permissions on the shared memory.
     * @param int $size The size to crate the shared memory in bytes.
     *
     * @throws SharedMemoryException
     */
    private function memOpen(int $key, string $mode, int $permissions, int $size) : void
    {
        $handle = @\shmop_open($key, $mode, $permissions, $size);
        if ($handle === \false) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to create shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
        $this->handle = $handle;
    }
    /**
     * Reads binary data from shared memory.
     *
     * @param int $offset The offset to read from.
     * @param int $size The number of bytes to read.
     *
     * @return string The binary data at the given offset.
     *
     * @throws SharedMemoryException
     */
    private function memGet(int $offset, int $size) : string
    {
        $data = \shmop_read($this->handle, $offset, $size);
        if ($data === \false) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to read from shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
        return $data;
    }
    /**
     * Writes binary data to shared memory.
     *
     * @param int $offset The offset to write to.
     * @param string $data The binary data to write.
     *
     * @throws SharedMemoryException
     */
    private function memSet(int $offset, string $data) : void
    {
        if (!\shmop_write($this->handle, $data, $offset)) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to write to shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
    }
    /**
     * Requests the shared memory segment to be deleted.
     *
     * @throws SharedMemoryException
     */
    private function memDelete() : void
    {
        if (!\shmop_delete($this->handle)) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to discard shared memory block' . ($error['message'] ?? 'unknown error'));
        }
    }
    /**
     *
     */
    private static function makeKey(string $id) : int
    {
        return \abs(\unpack("l", \md5($id, \true))[1]);
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

use PhabelVendor\Amp\Serialization\SerializationException as SerializerException;
// Alias must be defined in an always-loaded file as catch blocks do not trigger the autoloader.
\class_alias(SerializerException::class, SerializationException::class);
/**
 * @param \Throwable $exception
 *
 * @return array Serializable exception backtrace, with all function arguments flattened to strings.
 */
function flattenThrowableBacktrace(\Throwable $exception) : array
{
    $trace = $exception->getTrace();
    foreach ($trace as &$call) {
        unset($call['object']);
        $call['args'] = \array_map(__NAMESPACE__ . '\\flattenArgument', $call['args'] ?? []);
    }
    return $trace;
}
/**
 * @param array $trace Backtrace produced by {@see formatFlattenedBacktrace()}.
 *
 * @return string
 */
function formatFlattenedBacktrace(array $trace) : string
{
    $output = [];
    foreach ($trace as $index => $call) {
        if (isset($call['class'])) {
            $name = $call['class'] . $call['type'] . $call['function'];
        } else {
            $name = $call['function'];
        }
        $output[] = \sprintf('#%d %s(%d): %s(%s)', $index, $call['file'] ?? '[internal function]', $call['line'] ?? 0, $name, \implode(', ', $call['args'] ?? ['...']));
    }
    return \implode("\n", $output);
}
/**
 * @param mixed $value
 *
 * @return string Serializable string representation of $value for backtraces.
 */
function flattenArgument($value) : string
{
    if ($value instanceof \Closure) {
        $closureReflection = new \ReflectionFunction($value);
        return \sprintf('Closure(%s:%s)', $closureReflection->getFileName(), $closureReflection->getStartLine());
    }
    if (\is_object($value)) {
        return \sprintf('Object(%s)', \get_class($value));
    }
    if (\is_array($value)) {
        return 'Array([' . \implode(', ', \array_map(__FUNCTION__, $value)) . '])';
    }
    if (\is_resource($value)) {
        return \sprintf('Resource(%s)', \get_resource_type($value));
    }
    if (\is_string($value)) {
        return '"' . $value . '"';
    }
    if (\is_null($value)) {
        return 'null';
    }
    if (\is_bool($value)) {
        return $value ? 'true' : 'false';
    }
    return (string) $value;
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

use PhabelVendor\Amp\ByteStream\ResourceInputStream;
use PhabelVendor\Amp\ByteStream\ResourceOutputStream;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Serialization\Serializer;
final class ChannelledSocket implements Channel
{
    /** @var ChannelledStream */
    private $channel;
    /** @var ResourceInputStream */
    private $read;
    /** @var ResourceOutputStream */
    private $write;
    /**
     * @param resource $read Readable stream resource.
     * @param resource $write Writable stream resource.
     * @param (Serializer | null) $serializer
     *
     * @throws \Error If a stream resource is not given for $resource.
     */
    public function __construct($read, $write, ?Serializer $serializer = null)
    {
        $this->channel = new ChannelledStream($this->read = new ResourceInputStream($read), $this->write = new ResourceOutputStream($write), $serializer);
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        return $this->channel->receive();
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        return $this->channel->send($data);
    }
    /**
     *
     */
    public function unreference() : void
    {
        $this->read->unreference();
    }
    /**
     *
     */
    public function reference() : void
    {
        $this->read->reference();
    }
    /**
     * Closes the read and write resource streams.
     */
    public function close() : void
    {
        $this->read->close();
        $this->write->close();
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

class ParcelException extends \Exception
{
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

class ChannelException extends \Exception
{
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

use PhabelVendor\Amp\Promise;
/**
 * A parcel object for sharing data across execution contexts.
 *
 * A parcel is an object that stores a value in a safe way that can be shared
 * between different threads or processes. Different handles to the same parcel
 * will access the same data, and a parcel handle itself is serializable and
 * can be transported to other execution contexts.
 *
 * Wrapping and unwrapping values in the parcel are not atomic. To prevent race
 * conditions and guarantee safety, you should use the provided synchronization
 * methods to acquire a lock for exclusive access to the parcel first before
 * accessing the contained value.
 */
interface Parcel
{
    /**
    * Asynchronously invokes a callback while maintaining an exclusive lock on the parcel. The current value of the
    parcel is provided as the first argument to the callback function.
    *
    * @param callable $callback The synchronized callback to invoke. The parcel value is given as the single argument
    to the callback function. The callback may be a regular function or a coroutine.
    *
    * @return \Amp\Promise<mixed> Resolves with the return value of $callback or fails if $callback
    throws an exception.
    */
    public function synchronized(callable $callback) : Promise;
    /**
     * @return \Amp\Promise<mixed> A promise for the value inside the parcel.
     */
    public function unwrap() : Promise;
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync\Internal;

final class ParcelStorage extends \Threaded
{
    /** @var mixed */
    private $value;
    /**
     * @param mixed $value
     */
    public function __construct($value)
    {
        $this->value = $value;
    }
    /**
     * @return mixed
     */
    public function get()
    {
        return $this->value;
    }
    /**
     * @param mixed $value
     */
    public function set($value) : void
    {
        $this->value = $value;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

class SynchronizationError extends \Error
{
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
use PhabelVendor\Amp\Sync\ThreadedMutex;
use function PhabelVendor\Amp\call;
/**
 * A thread-safe container that shares a value between multiple threads.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class ThreadedParcel implements Parcel
{
    /** @var ThreadedMutex */
    private $mutex;
    /** @var \Threaded */
    private $storage;
    /**
     * Creates a new shared object container.
     *
     * @param mixed $value The value to store in the container.
     */
    public function __construct($value)
    {
        $this->mutex = new ThreadedMutex();
        $this->storage = new Internal\ParcelStorage($value);
    }
    /**
     * {@inheritdoc}
     */
    public function unwrap() : Promise
    {
        return new Success($this->storage->get());
    }
    /**
     * @return \Amp\Promise
     */
    public function synchronized(callable $callback) : Promise
    {
        return call(function () use($callback) : \Generator {
            /** @var \Amp\Sync\Lock $lock */
            $lock = (yield $this->mutex->acquire());
            try {
                $result = (yield call($callback, $this->storage->get()));
                if ($result !== null) {
                    $this->storage->set($result);
                }
            } finally {
                $lock->release();
            }
            return $result;
        });
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

use PhabelVendor\Amp\Promise;
/**
 * Interface for sending messages between execution contexts.
 */
interface Channel
{
    /**
    * @return \Amp\Promise<mixed>
    *
    * @throws \Amp\Parallel\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Parallel\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Parallel\Sync\ChannelException If receiving from the channel fails.
    * @throws \Amp\Parallel\Sync\SerializationException If unserializing the data fails.
    */
    public function receive() : Promise;
    /**
    * @param mixed $data
    *
    * @return \Amp\Promise<int> Resolves with the number of bytes sent on the channel.
    *
    * @throws \Amp\Parallel\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Parallel\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Parallel\Sync\ChannelException If sending on the channel fails.
    * @throws \Error If an ExitResult object is given.
    * @throws \Amp\Parallel\Sync\SerializationException If serializing the data fails.
    */
    public function send($data) : Promise;
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\Parallel\Sync;

/**
 * @deprecated ContextPanicError will be thrown from uncaught exceptions in child processes and threads instead of
 * this class.
 */
class PanicError extends \Error
{
    /** @var string Class name of uncaught exception. */
    private $name;
    /** @var string Stack trace of the panic. */
    private $trace;
    /**
     * Creates a new panic error.
     *
     * @param string $name The uncaught exception class.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use ContextPanicError::getOriginalClassName() instead.
     *
     * Returns the class name of the uncaught exception.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use ContextPanicError::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the panic occurred.
     *
     * @return string
     */
    public function getPanicTrace() : string
    {
        return $this->trace;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

use PhabelVendor\Amp\Parser\Parser;
use PhabelVendor\Amp\Serialization\NativeSerializer;
use PhabelVendor\Amp\Serialization\Serializer;
use function PhabelVendor\Amp\Serialization\encodeUnprintableChars;
final class ChannelParser extends Parser
{
    const HEADER_LENGTH = 5;
    /** @var Serializer */
    private $serializer;
    /**
     * @param callable(mixed $data) Callback invoked when data is parsed.
     * @param (Serializer | null) $serializer
     */
    public function __construct(callable $callback, ?Serializer $serializer = null)
    {
        $this->serializer = $serializer ?? new NativeSerializer();
        parent::__construct(self::parser($callback, $this->serializer));
    }
    /**
     * @param mixed $data Data to encode to send over a channel.
     *
     * @return string Encoded data that can be parsed by this class.
     *
     * @throws SerializationException
     */
    public function encode($data) : string
    {
        $data = $this->serializer->serialize($data);
        return \pack("CL", 0, \strlen($data)) . $data;
    }
    /**
     * @param callable $push
     * @param Serializer $serializer
     *
     * @return \Generator
     *
     * @throws ChannelException
     * @throws SerializationException
     */
    private static function parser(callable $push, Serializer $serializer) : \Generator
    {
        while (\true) {
            $header = (yield self::HEADER_LENGTH);
            $data = \unpack("Cprefix/Llength", $header);
            if ($data["prefix"] !== 0) {
                $data = $header . yield;
                throw new ChannelException("Invalid packet received: " . encodeUnprintableChars($data));
            }
            $data = (yield $data["length"]);
            $push($serializer->unserialize($data));
        }
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

interface ExitResult
{
    /**
     * @return mixed Return value of the callable given to the execution context.
     *
     * @throws \Amp\Parallel\Sync\PanicError If the context exited with an uncaught exception.
     */
    public function getResult();
}
<?php

namespace PhabelVendor\Amp\Parallel\Sync;

use PhabelVendor\Amp\ByteStream\InputStream;
use PhabelVendor\Amp\ByteStream\OutputStream;
use PhabelVendor\Amp\ByteStream\StreamException;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Serialization\Serializer;
use function PhabelVendor\Amp\call;
/**
 * An asynchronous channel for sending data between threads and processes.
 *
 * Supports full duplex read and write.
 */
final class ChannelledStream implements Channel
{
    /** @var InputStream */
    private $read;
    /** @var OutputStream */
    private $write;
    /** @var \SplQueue */
    private $received;
    /** @var ChannelParser */
    private $parser;
    /**
     * Creates a new channel from the given stream objects. Note that $read and $write can be the same object.
     *
     * @param InputStream $read
     * @param OutputStream $write
     * @param (Serializer | null) $serializer
     */
    public function __construct(InputStream $read, OutputStream $write, ?Serializer $serializer = null)
    {
        $this->read = $read;
        $this->write = $write;
        $this->received = new \SplQueue();
        $this->parser = new ChannelParser([$this->received, 'push'], $serializer);
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->write->write($this->parser->encode($data)));
            } catch (StreamException $exception) {
                throw new ChannelException("Sending on the channel failed. Did the context die?", 0, $exception);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        return call(function () : \Generator {
            while ($this->received->isEmpty()) {
                try {
                    $chunk = (yield $this->read->read());
                } catch (StreamException $exception) {
                    throw new ChannelException("Reading from the channel failed. Did the context die?", 0, $exception);
                }
                if ($chunk === null) {
                    throw new ChannelException("The channel closed unexpectedly. Did the context die?");
                }
                $this->parser->push($chunk);
            }
            return $this->received->shift();
        });
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Context;

use PhabelVendor\Amp\Promise;
interface ContextFactory
{
    /**
    * Creates a new execution context.
    *
    * @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Context
    */
    public function create($script) : Context;
    /**
    * Creates and starts a new execution context.
    *
    * @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Promise<Context>
    */
    public function run($script) : Promise;
}
<?php

namespace PhabelVendor\Amp\Parallel\Context;

use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Parallel\Sync\ChannelledSocket;
use PhabelVendor\Amp\Parallel\Sync\ExitResult;
use PhabelVendor\Amp\Parallel\Sync\SynchronizationError;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
use function PhabelVendor\Amp\call;
/**
 * Implements an execution context using native multi-threading.
 *
 * The thread context is not itself threaded. A local instance of the context is
 * maintained both in the context that creates the thread and in the thread
 * itself.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class Thread implements Context
{
    const EXIT_CHECK_FREQUENCY = 250;
    /** @var int */
    private static $nextId = 1;
    /** @var Internal\Thread An internal thread instance. */
    private $thread;
    /** @var ChannelledSocket A channel for communicating with the thread. */
    private $channel;
    /** @var resource */
    private $socket;
    /** @var callable */
    private $function;
    /** @var mixed[] */
    private $args;
    /** @var int|null */
    private $id;
    /** @var int */
    private $oid = 0;
    /** @var string */
    private $watcher;
    /**
     * Checks if threading is enabled.
     *
     * @return bool True if threading is enabled, otherwise false.
     */
    public static function isSupported() : bool
    {
        return \extension_loaded('pthreads');
    }
    /**
    * Creates and starts a new thread.
    *
    * @param callable $function The callable to invoke in the thread. First argument is an instance of
    \Amp\Parallel\Sync\Channel.
    * @param mixed ...$args Additional arguments to pass to the given callable.
    *
    * @return Promise<Thread> The thread object that was spawned.
    */
    public static function run(callable $function, ...$args) : Promise
    {
        $thread = new self($function, ...$args);
        return call(function () use($thread) : \Generator {
            (yield $thread->start());
            return $thread;
        });
    }
    /**
    * Creates a new thread.
    *
    * @param callable $function The callable to invoke in the thread. First argument is an instance of
    \Amp\Parallel\Sync\Channel.
    * @param mixed ...$args Additional arguments to pass to the given callable.
    *
    * @throws \Error Thrown if the pthreads extension is not available.
    */
    public function __construct(callable $function, ...$args)
    {
        if (!self::isSupported()) {
            throw new \Error("The pthreads extension is required to create threads.");
        }
        $this->function = $function;
        $this->args = $args;
    }
    /**
    * Returns the thread to the condition before starting. The new thread can be started and run independently of the
    first thread.
    */
    public function __clone()
    {
        $this->thread = null;
        $this->socket = null;
        $this->channel = null;
        $this->oid = 0;
    }
    /**
     * Kills the thread if it is still running.
     *
     * @throws \Amp\Parallel\Context\ContextException
     */
    public function __destruct()
    {
        if (\getmypid() === $this->oid) {
            $this->kill();
        }
    }
    /**
     * Checks if the context is running.
     *
     * @return bool True if the context is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->channel !== null;
    }
    /**
     * Spawns the thread and begins the thread's execution.
     *
     * @return Promise<int> Resolved once the thread has started.
     *
     * @throws \Amp\Parallel\Context\StatusError If the thread has already been started.
     * @throws \Amp\Parallel\Context\ContextException If starting the thread was unsuccessful.
     */
    public function start() : Promise
    {
        if ($this->oid !== 0) {
            throw new StatusError('The thread has already been started.');
        }
        $this->oid = \getmypid();
        $sockets = @\stream_socket_pair(\stripos(\PHP_OS, "win") === 0 ? \STREAM_PF_INET : \STREAM_PF_UNIX, \STREAM_SOCK_STREAM, \STREAM_IPPROTO_IP);
        if ($sockets === \false) {
            $message = "Failed to create socket pair";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            return new Failure(new ContextException($message));
        }
        list($channel, $this->socket) = $sockets;
        $this->id = self::$nextId++;
        $thread = $this->thread = new Internal\Thread($this->id, $this->socket, $this->function, $this->args);
        if (!$this->thread->start(\PTHREADS_INHERIT_INI)) {
            return new Failure(new ContextException('Failed to start the thread.'));
        }
        $channel = $this->channel = new ChannelledSocket($channel, $channel);
        $this->watcher = Loop::repeat(self::EXIT_CHECK_FREQUENCY, static function ($watcher) use($thread, $channel) : void {
            if (!$thread->isRunning()) {
                // Delay closing to avoid race condition between thread exiting and data becoming available.
                Loop::delay(self::EXIT_CHECK_FREQUENCY, [$channel, "close"]);
                Loop::cancel($watcher);
            }
        });
        Loop::disable($this->watcher);
        return new Success($this->id);
    }
    /**
     * Immediately kills the context.
     *
     * @throws ContextException If killing the thread was unsuccessful.
     */
    public function kill() : void
    {
        if ($this->thread !== null) {
            try {
                if ($this->thread->isRunning() && !$this->thread->kill()) {
                    throw new ContextException('Could not kill thread.');
                }
            } finally {
                $this->close();
            }
        }
    }
    /**
     * Closes channel and socket if still open.
     */
    private function close() : void
    {
        if ($this->channel !== null) {
            $this->channel->close();
        }
        $this->channel = null;
        Loop::cancel($this->watcher);
    }
    /**
    * Gets a promise that resolves when the context ends and joins with the
    parent context.
    *
    * @return \Amp\Promise<mixed>
    *
    * @throws StatusError Thrown if the context has not been started.
    * @throws SynchronizationError Thrown if an exit status object is not received.
    * @throws ContextException If the context stops responding.
    */
    public function join() : Promise
    {
        if ($this->channel == null || $this->thread === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        return call(function () : \Generator {
            Loop::enable($this->watcher);
            try {
                $response = (yield $this->channel->receive());
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Failed to receive result from thread", 0, $exception);
            } finally {
                Loop::disable($this->watcher);
                $this->close();
            }
            if (!$response instanceof ExitResult) {
                $this->kill();
                throw new SynchronizationError('Did not receive an exit result from thread.');
            }
            return $response->getResult();
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The process has not been started.');
        }
        return call(function () : \Generator {
            Loop::enable($this->watcher);
            try {
                $data = (yield $this->channel->receive());
            } finally {
                Loop::disable($this->watcher);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Thread process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        if ($data instanceof ExitResult) {
            throw new \Error('Cannot send exit result objects.');
        }
        return call(function () use($data) : \Generator {
            Loop::enable($this->watcher);
            try {
                $result = (yield $this->channel->send($data));
            } finally {
                Loop::disable($this->watcher);
            }
            return $result;
        });
    }
    /**
     * Returns the ID of the thread. This ID will be unique to this process.
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getId() : int
    {
        if ($this->id === null) {
            throw new StatusError('The thread has not been started');
        }
        return $this->id;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Context;

use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Promise;
const LOOP_FACTORY_IDENTIFIER = ContextFactory::class;
/**
* @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
*
* @return Context
*/
function create($script) : Context
{
    return factory()->create($script);
}
/**
* Creates and starts a process based on installed extensions (a thread if ext-parallel is installed, otherwise a child
process).
*
* @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
*
* @return Promise<Context>
*/
function run($script) : Promise
{
    return factory()->run($script);
}
/**
 * Gets or sets the global context factory.
 *
 * @param (ContextFactory | null) $factory
 *
 * @return ContextFactory
 */
function factory(?ContextFactory $factory = null) : ContextFactory
{
    if ($factory === null) {
        $factory = Loop::getState(LOOP_FACTORY_IDENTIFIER);
        if ($factory) {
            return $factory;
        }
        $factory = new DefaultContextFactory();
    }
    Loop::setState(LOOP_FACTORY_IDENTIFIER, $factory);
    return $factory;
}
<?php

namespace PhabelVendor\Amp\Parallel\Context;

class ContextException extends \Exception
{
}
<?php

namespace PhabelVendor\Amp\Parallel\Context\Internal;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Parallel\Context\ContextException;
use PhabelVendor\Amp\Parallel\Sync\ChannelledSocket;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\TimeoutException;
use function PhabelVendor\Amp\asyncCall;
use function PhabelVendor\Amp\call;
class ProcessHub
{
    const PROCESS_START_TIMEOUT = 5000;
    const KEY_RECEIVE_TIMEOUT = 1000;
    /** @var resource|null */
    private $server;
    /** @var string|null */
    private $uri;
    /** @var int[] */
    private $keys;
    /** @var string|null */
    private $watcher;
    /** @var Deferred[] */
    private $acceptor = [];
    /** @var string|null */
    private $toUnlink;
    /**
     *
     */
    public function __construct()
    {
        $isWindows = \strncasecmp(\PHP_OS, "WIN", 3) === 0;
        if ($isWindows) {
            $this->uri = "tcp://127.0.0.1:0";
        } else {
            $suffix = \bin2hex(\random_bytes(10));
            $path = \sys_get_temp_dir() . "/amp-parallel-ipc-" . $suffix . ".sock";
            $this->uri = "unix://" . $path;
            $this->toUnlink = $path;
        }
        $context = \stream_context_create(['socket' => ['backlog' => 128]]);
        $this->server = \stream_socket_server($this->uri, $errno, $errstr, \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN, $context);
        if (!$this->server) {
            throw new \RuntimeException(\sprintf("Could not create IPC server: (Errno: %d) %s", $errno, $errstr));
        }
        if ($isWindows) {
            $name = \stream_socket_get_name($this->server, \false);
            $port = \Phabel\Target\Php80\Polyfill::substr($name, \strrpos($name, ":") + 1);
            $this->uri = "tcp://127.0.0.1:" . $port;
        }
        $keys =& $this->keys;
        $acceptor =& $this->acceptor;
        $this->watcher = Loop::onReadable($this->server, static function (string $watcher, $server) use(&$keys, &$acceptor) : void {
            // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
            while ($client = @\stream_socket_accept($server, 0)) {
                // Timeout of 0 to be non-blocking.
                asyncCall(static function () use($client, &$keys, &$acceptor) {
                    $channel = new ChannelledSocket($client, $client);
                    try {
                        $received = (yield Promise\timeout($channel->receive(), self::KEY_RECEIVE_TIMEOUT));
                    } catch (\Throwable $exception) {
                        $channel->close();
                        return;
                        // Ignore possible foreign connection attempt.
                    }
                    if (!\is_string($received) || !isset($keys[$received])) {
                        $channel->close();
                        return;
                        // Ignore possible foreign connection attempt.
                    }
                    $pid = $keys[$received];
                    $deferred = $acceptor[$pid];
                    unset($acceptor[$pid], $keys[$received]);
                    $deferred->resolve($channel);
                });
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->watcher);
        \fclose($this->server);
        if ($this->toUnlink !== null) {
            @\unlink($this->toUnlink);
        }
    }
    /**
     *
     */
    public function getUri() : string
    {
        return $this->uri;
    }
    /**
     *
     */
    public function generateKey(int $pid, int $length) : string
    {
        $key = \random_bytes($length);
        $this->keys[$key] = $pid;
        return $key;
    }
    /**
     *
     */
    public function accept(int $pid) : Promise
    {
        return call(function () use($pid) : \Generator {
            $this->acceptor[$pid] = new Deferred();
            Loop::enable($this->watcher);
            try {
                $channel = (yield Promise\timeout($this->acceptor[$pid]->promise(), self::PROCESS_START_TIMEOUT));
            } catch (TimeoutException $exception) {
                $key = \array_search($pid, $this->keys, \true);
                \assert(\is_string($key), "Key for {$pid} not found");
                unset($this->acceptor[$pid], $this->keys[$key]);
                throw new ContextException("Starting the process timed out", 0, $exception);
            } finally {
                if (empty($this->acceptor)) {
                    Loop::disable($this->watcher);
                }
            }
            return $channel;
        });
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Context\Internal;

use PhabelVendor\Amp\Parallel\Context\Process;
use PhabelVendor\Amp\Parallel\Sync;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
use function PhabelVendor\Amp\getCurrentTime;
\define("AMP_CONTEXT", "process");
\define("AMP_CONTEXT_ID", \getmypid());
// Doesn't exist in phpdbg...
if (\function_exists("cli_set_process_title")) {
    @\cli_set_process_title("amp-process");
}
(function () : void {
    $paths = [\dirname(__DIR__, 5) . "/autoload.php", \dirname(__DIR__, 3) . "/vendor/autoload.php"];
    foreach ($paths as $path) {
        if (\file_exists($path)) {
            $autoloadPath = $path;
            break;
        }
    }
    if (!isset($autoloadPath)) {
        \trigger_error("Could not locate autoload.php in any of the following files: " . \implode(", ", $paths), \E_USER_ERROR);
        exit(1);
    }
    require $autoloadPath;
})();
(function () use($argc, $argv) : void {
    // Remove this scripts path from process arguments.
    --$argc;
    \array_shift($argv);
    if (!isset($argv[0])) {
        \trigger_error("No socket path provided", \E_USER_ERROR);
        exit(1);
    }
    // Remove socket path from process arguments.
    --$argc;
    $uri = \array_shift($argv);
    $key = "";
    // Read random key from STDIN and send back to parent over IPC socket to authenticate.
    do {
        if (($chunk = \fread(\STDIN, Process::KEY_LENGTH)) === \false || \feof(\STDIN)) {
            \trigger_error("Could not read key from parent", \E_USER_ERROR);
            exit(1);
        }
        $key .= $chunk;
    } while (\strlen($key) < Process::KEY_LENGTH);
    $connectStart = getCurrentTime();
    while (!($socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT))) {
        if (getCurrentTime() < $connectStart + 5000) {
            // try for 5 seconds, after that the parent times out anyway
            \trigger_error("Could not connect to IPC socket", \E_USER_ERROR);
            exit(1);
        }
        \usleep(50 * 1000);
    }
    $channel = new Sync\ChannelledSocket($socket, $socket);
    try {
        Promise\wait($channel->send($key));
    } catch (\Throwable $exception) {
        \trigger_error("Could not send key to parent", \E_USER_ERROR);
        exit(1);
    }
    try {
        if (!isset($argv[0])) {
            throw new \Error("No script path given");
        }
        if (!\is_file($argv[0])) {
            throw new \Error(\sprintf("No script found at '%s' (be sure to provide the full path to the script)", $argv[0]));
        }
        try {
            // Protect current scope by requiring script within another function.
            $callable = (function () use($argc, $argv) : callable {
                // Using $argc so it is available to the required script.
                return require $argv[0];
            })();
        } catch (\TypeError $exception) {
            throw new \Error(\sprintf("Script '%s' did not return a callable function", $argv[0]), 0, $exception);
        } catch (\ParseError $exception) {
            throw new \Error(\sprintf("Script '%s' contains a parse error: " . $exception->getMessage(), $argv[0]), 0, $exception);
        }
        $result = new Sync\ExitSuccess(Promise\wait(call($callable, $channel)));
    } catch (\Throwable $exception) {
        $result = new Sync\ExitFailure($exception);
    }
    try {
        Promise\wait(call(function () use($channel, $result) : \Generator {
            try {
                (yield $channel->send($result));
            } catch (Sync\SerializationException $exception) {
                // Serializing the result failed. Send the reason why.
                (yield $channel->send(new Sync\ExitFailure($exception)));
            }
        }));
    } catch (\Throwable $exception) {
        \trigger_error("Could not send result to parent; be sure to shutdown the child before ending the parent", \E_USER_ERROR);
        exit(1);
    }
})();
<?php

namespace PhabelVendor\Amp\Parallel\Context\Internal;

use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Parallel\Sync\Channel;
use PhabelVendor\Amp\Parallel\Sync\ChannelException;
use PhabelVendor\Amp\Parallel\Sync\ChannelledSocket;
use PhabelVendor\Amp\Parallel\Sync\ExitFailure;
use PhabelVendor\Amp\Parallel\Sync\ExitSuccess;
use PhabelVendor\Amp\Parallel\Sync\SerializationException;
use function PhabelVendor\Amp\call;
/**
 * An internal thread that executes a given function concurrently.
 *
 * @internal
 */
final class Thread extends \Thread
{
    const KILL_CHECK_FREQUENCY = 250;
    private $id;
    /** @var callable The function to execute in the thread. */
    private $function;
    /** @var mixed[] Arguments to pass to the function. */
    private $args;
    /** @var resource */
    private $socket;
    /** @var bool */
    private $killed = \false;
    /**
     * Creates a new thread object.
     *
     * @param int $id Thread ID.
     * @param resource $socket IPC communication socket.
     * @param callable $function The function to execute in the thread.
     * @param mixed[] $args Arguments to pass to the function.
     */
    public function __construct(int $id, $socket, callable $function, array $args = [])
    {
        $this->id = $id;
        $this->function = $function;
        $this->args = $args;
        $this->socket = $socket;
    }
    /**
     * Runs the thread code and the initialized function.
     *
     * @codeCoverageIgnore Only executed in thread.
     */
    public function run()
    {
        \define("AMP_CONTEXT", "thread");
        \define("AMP_CONTEXT_ID", $this->id);
        /* First thing we need to do is re-initialize the class autoloader. If
         * we don't do this first, any object of a class that was loaded after
         * the thread started will just be garbage data and unserializable
         * values (like resources) will be lost. This happens even with
         * thread-safe objects.
         */
        // Protect scope by using an unbound closure (protects static access as well).
        (static function () : void {
            $paths = [\dirname(__DIR__, 3) . \DIRECTORY_SEPARATOR . "vendor" . \DIRECTORY_SEPARATOR . "autoload.php", \dirname(__DIR__, 5) . \DIRECTORY_SEPARATOR . "autoload.php"];
            foreach ($paths as $path) {
                if (\file_exists($path)) {
                    $autoloadPath = $path;
                    break;
                }
            }
            if (!isset($autoloadPath)) {
                throw new \Error("Could not locate autoload.php");
            }
            require $autoloadPath;
        })->bindTo(null, null)();
        // At this point, the thread environment has been prepared so begin using the thread.
        if ($this->killed) {
            return;
            // Thread killed while requiring autoloader, simply exit.
        }
        Loop::run(function () : \Generator {
            $watcher = Loop::repeat(self::KILL_CHECK_FREQUENCY, function () : void {
                if ($this->killed) {
                    Loop::stop();
                }
            });
            Loop::unreference($watcher);
            try {
                $channel = new ChannelledSocket($this->socket, $this->socket);
                yield from $this->execute($channel);
            } catch (\Throwable $exception) {
                return;
                // Parent context exited or destroyed thread, no need to continue.
            } finally {
                Loop::cancel($watcher);
            }
        });
    }
    /**
     * Sets a local variable to true so the running event loop can check for a kill signal.
     */
    public function kill()
    {
        return $this->killed = \true;
    }
    /**
     * @param \Amp\Parallel\Sync\Channel $channel
     *
     * @return \Generator
     *
     * @codeCoverageIgnore Only executed in thread.
     */
    private function execute(Channel $channel) : \Generator
    {
        try {
            $result = new ExitSuccess((yield call($this->function, $channel, ...$this->args)));
        } catch (\Throwable $exception) {
            $result = new ExitFailure($exception);
        }
        if ($this->killed) {
            return;
            // Parent is not listening for a result.
        }
        // Attempt to return the result.
        try {
            try {
                (yield $channel->send($result));
            } catch (SerializationException $exception) {
                // Serializing the result failed. Send the reason why.
                (yield $channel->send(new ExitFailure($exception)));
            }
        } catch (ChannelException $exception) {
            // The result was not sendable! The parent context must have died or killed the context.
        }
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Context\Internal;

use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Parallel\Sync\ChannelledSocket;
use parallel\Events;
use parallel\Future;
class ParallelHub extends ProcessHub
{
    const EXIT_CHECK_FREQUENCY = 250;
    /** @var ChannelledSocket[] */
    private $channels;
    /** @var string */
    private $watcher;
    /** @var Events */
    private $events;
    /**
     *
     */
    public function __construct()
    {
        parent::__construct();
        $events = $this->events = new Events();
        $this->events->setBlocking(\false);
        $channels =& $this->channels;
        $this->watcher = Loop::repeat(self::EXIT_CHECK_FREQUENCY, static function () use(&$channels, $events) : void {
            while ($event = $events->poll()) {
                $id = (int) $event->source;
                \assert(isset($channels[$id]), 'Channel for context ID not found');
                $channel = $channels[$id];
                unset($channels[$id]);
                $channel->close();
            }
        });
        Loop::disable($this->watcher);
        Loop::unreference($this->watcher);
    }
    /**
     *
     */
    public function add(int $id, ChannelledSocket $channel, Future $future) : void
    {
        $this->channels[$id] = $channel;
        $this->events->addFuture((string) $id, $future);
        Loop::enable($this->watcher);
    }
    /**
     *
     */
    public function remove(int $id) : void
    {
        if (!isset($this->channels[$id])) {
            return;
        }
        unset($this->channels[$id]);
        $this->events->remove((string) $id);
        if (empty($this->channels)) {
            Loop::disable($this->watcher);
        }
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Context;

class StatusError extends \Error
{
}
<?php

namespace PhabelVendor\Amp\Parallel\Context;

use PhabelVendor\Amp\Promise;
class DefaultContextFactory implements ContextFactory
{
    /**
     *
     */
    public function create($script) : Context
    {
        /**
         * Creates a thread if ext-parallel is installed, otherwise creates a child process.
         *
         * @inheritdoc
         */
        if (Parallel::isSupported()) {
            return new Parallel($script);
        }
        return new Process($script);
    }
    /**
     * Creates and starts a thread if ext-parallel is installed, otherwise creates a child process.
     *
     * @inheritdoc
     */
    public function run($script) : Promise
    {
        if (Parallel::isSupported()) {
            return Parallel::run($script);
        }
        return Process::run($script);
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\Parallel\Context;

use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Parallel\Sync\ChannelException;
use PhabelVendor\Amp\Parallel\Sync\ChannelledSocket;
use PhabelVendor\Amp\Parallel\Sync\ExitResult;
use PhabelVendor\Amp\Parallel\Sync\SynchronizationError;
use PhabelVendor\Amp\Process\Process as BaseProcess;
use PhabelVendor\Amp\Process\ProcessInputStream;
use PhabelVendor\Amp\Process\ProcessOutputStream;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\TimeoutException;
use function PhabelVendor\Amp\call;
final class Process implements Context
{
    const SCRIPT_PATH = __DIR__ . "/Internal/process-runner.php";
    const KEY_LENGTH = 32;
    /** @var string|null External version of SCRIPT_PATH if inside a PHAR. */
    private static $pharScriptPath;
    /** @var string|null PHAR path with a '.phar' extension. */
    private static $pharCopy;
    /** @var string|null Cached path to located PHP binary. */
    private static $binaryPath;
    /** @var Internal\ProcessHub */
    private $hub;
    /** @var BaseProcess */
    private $process;
    /** @var ChannelledSocket */
    private $channel;
    /**
    * Creates and starts the process at the given path using the optional PHP binary path.
    *
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    * @param (string | null) $cwd Working directory.
    * @param mixed[] $env Array of environment variables.
    * @param string $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    *
    * @return Promise<Process>
    */
    public static function run($script, string $cwd = null, array $env = [], string $binary = null) : Promise
    {
        $process = new self($script, $cwd, $env, $binary);
        return call(function () use($process) : \Generator {
            (yield $process->start());
            return $process;
        });
    }
    /**
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    * @param (string | null) $cwd Working directory.
    * @param mixed[] $env Array of environment variables.
    * @param string $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct($script, string $cwd = null, array $env = [], string $binary = null)
    {
        $this->hub = Loop::getState(self::class);
        if (!$this->hub instanceof Internal\ProcessHub) {
            $this->hub = new Internal\ProcessHub();
            Loop::setState(self::class, $this->hub);
        }
        $options = ["html_errors" => "0", "display_errors" => "0", "log_errors" => "1"];
        if ($binary === null) {
            if (\PHP_SAPI === "cli") {
                $binary = \PHP_BINARY;
            } else {
                $binary = self::$binaryPath ?? self::locateBinary();
            }
        } elseif (!\is_executable($binary)) {
            throw new \Error(\sprintf("The PHP binary path '%s' was not found or is not executable", $binary));
        }
        // Write process runner to external file if inside a PHAR,
        // because PHP can't open files inside a PHAR directly except for the stub.
        if (\strpos(self::SCRIPT_PATH, "phar://") === 0) {
            if (self::$pharScriptPath) {
                $scriptPath = self::$pharScriptPath;
            } else {
                $path = \dirname(self::SCRIPT_PATH);
                if (\Phabel\Target\Php80\Polyfill::substr(\Phar::running(\false), -5) !== ".phar") {
                    self::$pharCopy = \sys_get_temp_dir() . "/phar-" . \bin2hex(\random_bytes(10)) . ".phar";
                    \copy(\Phar::running(\false), self::$pharCopy);
                    \register_shutdown_function(static function () : void {
                        @\unlink(self::$pharCopy);
                    });
                    $path = "phar://" . self::$pharCopy . "/" . \Phabel\Target\Php80\Polyfill::substr($path, \strlen(\Phar::running(\true)));
                }
                $contents = \file_get_contents(self::SCRIPT_PATH);
                $contents = \str_replace("__DIR__", \var_export($path, \true), $contents);
                $suffix = \bin2hex(\random_bytes(10));
                self::$pharScriptPath = $scriptPath = \sys_get_temp_dir() . "/amp-process-runner-" . $suffix . ".php";
                \file_put_contents($scriptPath, $contents);
                \register_shutdown_function(static function () : void {
                    @\unlink(self::$pharScriptPath);
                });
            }
            // Monkey-patch the script path in the same way, only supported if the command is given as array.
            if (isset(self::$pharCopy) && \is_array($script) && isset($script[0])) {
                $script[0] = "phar://" . self::$pharCopy . \Phabel\Target\Php80\Polyfill::substr($script[0], \strlen(\Phar::running(\true)));
            }
        } else {
            $scriptPath = self::SCRIPT_PATH;
        }
        if (\is_array($script)) {
            $script = \implode(" ", \array_map("escapeshellarg", $script));
        } else {
            $script = \escapeshellarg($script);
        }
        $command = \implode(" ", [\escapeshellarg($binary), $this->formatOptions($options), \escapeshellarg($scriptPath), $this->hub->getUri(), $script]);
        $this->process = new BaseProcess($command, $cwd, $env);
    }
    /**
     *
     */
    private static function locateBinary() : string
    {
        $executable = \strncasecmp(\PHP_OS, "WIN", 3) === 0 ? "php.exe" : "php";
        $paths = \array_filter(\explode(\PATH_SEPARATOR, \getenv("PATH")));
        $paths[] = \PHP_BINDIR;
        $paths = \array_unique($paths);
        foreach ($paths as $path) {
            $path .= \DIRECTORY_SEPARATOR . $executable;
            if (\is_executable($path)) {
                return self::$binaryPath = $path;
            }
        }
        throw new \Error("Could not locate PHP executable binary");
    }
    /**
     *
     */
    private function formatOptions(array $options) : string
    {
        $result = [];
        foreach ($options as $option => $value) {
            $result[] = \sprintf("-d%s=%s", $option, $value);
        }
        return \implode(" ", $result);
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * {@inheritdoc}
     */
    public function start() : Promise
    {
        return call(function () : \Generator {
            try {
                $pid = (yield $this->process->start());
                (yield $this->process->getStdin()->write($this->hub->generateKey($pid, self::KEY_LENGTH)));
                $this->channel = (yield $this->hub->accept($pid));
                return $pid;
            } catch (\Throwable $exception) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new ContextException("Starting the process failed", 0, $exception);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        return $this->process->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (ChannelException $e) {
                throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        if ($data instanceof ExitResult) {
            throw new \Error("Cannot send exit result objects");
        }
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->channel->send($data));
            } catch (ChannelException $e) {
                if ($this->channel === null) {
                    throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                try {
                    $data = (yield Promise\timeout($this->join(), 100));
                } catch (ContextException|ChannelException|TimeoutException $ex) {
                    if ($this->isRunning()) {
                        $this->kill();
                    }
                    throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                throw new SynchronizationError(\sprintf('Process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)), 0, $e);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function join() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (\Throwable $exception) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new ContextException("Failed to receive result from process", 0, $exception);
            }
            if (!$data instanceof ExitResult) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new SynchronizationError("Did not receive an exit result from process");
            }
            $this->channel->close();
            $code = (yield $this->process->join());
            if ($code !== 0) {
                throw new ContextException(\sprintf("Process exited with code %d", $code));
            }
            return $data->getResult();
        });
    }
    /**
     * Send a signal to the process.
     *
     * @see \Amp\Process\Process::signal()
     *
     * @param int $signo
     *
     * @throws \Amp\Process\ProcessException
     * @throws \Amp\Process\StatusError
     */
    public function signal(int $signo) : void
    {
        $this->process->signal($signo);
    }
    /**
     * Returns the PID of the process.
     *
     * @see \Amp\Process\Process::getPid()
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getPid() : int
    {
        return $this->process->getPid();
    }
    /**
     * Returns the STDIN stream of the process.
     *
     * @see \Amp\Process\Process::getStdin()
     *
     * @return ProcessOutputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStdin() : ProcessOutputStream
    {
        return $this->process->getStdin();
    }
    /**
     * Returns the STDOUT stream of the process.
     *
     * @see \Amp\Process\Process::getStdout()
     *
     * @return ProcessInputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStdout() : ProcessInputStream
    {
        return $this->process->getStdout();
    }
    /**
     * Returns the STDOUT stream of the process.
     *
     * @see \Amp\Process\Process::getStderr()
     *
     * @return ProcessInputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStderr() : ProcessInputStream
    {
        return $this->process->getStderr();
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        $this->process->kill();
        if ($this->channel !== null) {
            $this->channel->close();
        }
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Context;

use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Parallel\Sync\ChannelException;
use PhabelVendor\Amp\Parallel\Sync\ChannelledSocket;
use PhabelVendor\Amp\Parallel\Sync\ExitFailure;
use PhabelVendor\Amp\Parallel\Sync\ExitResult;
use PhabelVendor\Amp\Parallel\Sync\ExitSuccess;
use PhabelVendor\Amp\Parallel\Sync\SerializationException;
use PhabelVendor\Amp\Parallel\Sync\SynchronizationError;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\TimeoutException;
use parallel\Runtime;
use function PhabelVendor\Amp\call;
/**
 * Implements an execution context using native threads provided by the parallel extension.
 */
final class Parallel implements Context
{
    const EXIT_CHECK_FREQUENCY = 250;
    const KEY_LENGTH = 32;
    /** @var string|null */
    private static $autoloadPath;
    /** @var int Next thread ID. */
    private static $nextId = 1;
    /** @var Internal\ProcessHub */
    private $hub;
    /** @var int|null */
    private $id;
    /** @var Runtime|null */
    private $runtime;
    /** @var ChannelledSocket|null A channel for communicating with the parallel thread. */
    private $channel;
    /** @var string Script path. */
    private $script;
    /** @var string[] */
    private $args = [];
    /** @var int */
    private $oid = 0;
    /** @var bool */
    private $killed = \false;
    /**
     * Checks if threading is enabled.
     *
     * @return bool True if threading is enabled, otherwise false.
     */
    public static function isSupported() : bool
    {
        return \extension_loaded('parallel');
    }
    /**
    * Creates and starts a new thread.
    *
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Promise<Thread> The thread object that was spawned.
    */
    public static function run($script) : Promise
    {
        $thread = new self($script);
        return call(function () use($thread) : \Generator {
            (yield $thread->start());
            return $thread;
        });
    }
    /**
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @throws \Error Thrown if the pthreads extension is not available.
    */
    public function __construct($script)
    {
        if (!self::isSupported()) {
            throw new \Error("The parallel extension is required to create parallel threads.");
        }
        $this->hub = Loop::getState(self::class);
        if (!$this->hub instanceof Internal\ParallelHub) {
            $this->hub = new Internal\ParallelHub();
            Loop::setState(self::class, $this->hub);
        }
        if (\is_array($script)) {
            $this->script = (string) \array_shift($script);
            $this->args = \array_values(\array_map("strval", $script));
        } else {
            $this->script = (string) $script;
        }
        if (self::$autoloadPath === null) {
            $paths = [\dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR . "vendor" . \DIRECTORY_SEPARATOR . "autoload.php", \dirname(__DIR__, 4) . \DIRECTORY_SEPARATOR . "autoload.php"];
            foreach ($paths as $path) {
                if (\file_exists($path)) {
                    self::$autoloadPath = $path;
                    break;
                }
            }
            if (self::$autoloadPath === null) {
                throw new \Error("Could not locate autoload.php");
            }
        }
    }
    /**
    * Returns the thread to the condition before starting. The new thread can be started and run independently of the
    first thread.
    */
    public function __clone()
    {
        $this->runtime = null;
        $this->channel = null;
        $this->id = null;
        $this->oid = 0;
        $this->killed = \false;
    }
    /**
     * Kills the thread if it is still running.
     *
     * @throws \Amp\Parallel\Context\ContextException
     */
    public function __destruct()
    {
        if (\getmypid() === $this->oid) {
            $this->kill();
        }
    }
    /**
     * Checks if the context is running.
     *
     * @return bool True if the context is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->channel !== null;
    }
    /**
     * Spawns the thread and begins the thread's execution.
     *
     * @return Promise<int> Resolved once the thread has started.
     *
     * @throws \Amp\Parallel\Context\StatusError If the thread has already been started.
     * @throws \Amp\Parallel\Context\ContextException If starting the thread was unsuccessful.
     */
    public function start() : Promise
    {
        if ($this->oid !== 0) {
            throw new StatusError('The thread has already been started.');
        }
        $this->oid = \getmypid();
        $this->runtime = new Runtime(self::$autoloadPath);
        $this->id = self::$nextId++;
        $future = $this->runtime->run(static function (int $id, string $uri, string $key, string $path, array $argv) : int {
            // @codeCoverageIgnoreStart
            // Only executed in thread.
            \define("AMP_CONTEXT", "parallel");
            \define("AMP_CONTEXT_ID", $id);
            if (!($socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT))) {
                \trigger_error("Could not connect to IPC socket", \E_USER_ERROR);
                return 1;
            }
            $channel = new ChannelledSocket($socket, $socket);
            try {
                Promise\wait($channel->send($key));
            } catch (\Throwable $exception) {
                \trigger_error("Could not send key to parent", \E_USER_ERROR);
                return 1;
            }
            try {
                Loop::unreference(Loop::repeat(self::EXIT_CHECK_FREQUENCY, function () : void {
                    // Timer to give the chance for the PHP VM to be interrupted by Runtime::kill(), since system calls such as
                    // select() will not be interrupted.
                }));
                try {
                    if (!\is_file($path)) {
                        throw new \Error(\sprintf("No script found at '%s' (be sure to provide the full path to the script)", $path));
                    }
                    $argc = \array_unshift($argv, $path);
                    try {
                        // Protect current scope by requiring script within another function.
                        $callable = (function () use($argc, $argv) : callable {
                            // Using $argc so it is available to the required script.
                            return require $argv[0];
                        })->bindTo(null, null)();
                    } catch (\TypeError $exception) {
                        throw new \Error(\sprintf("Script '%s' did not return a callable function", $path), 0, $exception);
                    } catch (\ParseError $exception) {
                        throw new \Error(\sprintf("Script '%s' contains a parse error", $path), 0, $exception);
                    }
                    $result = new ExitSuccess(Promise\wait(call($callable, $channel)));
                } catch (\Throwable $exception) {
                    $result = new ExitFailure($exception);
                }
                Promise\wait(call(function () use($channel, $result) : \Generator {
                    try {
                        (yield $channel->send($result));
                    } catch (SerializationException $exception) {
                        // Serializing the result failed. Send the reason why.
                        (yield $channel->send(new ExitFailure($exception)));
                    }
                }));
            } catch (\Throwable $exception) {
                \trigger_error("Could not send result to parent; be sure to shutdown the child before ending the parent", \E_USER_ERROR);
                return 1;
            } finally {
                $channel->close();
            }
            return 0;
            // @codeCoverageIgnoreEnd
        }, [$this->id, $this->hub->getUri(), $this->hub->generateKey($this->id, self::KEY_LENGTH), $this->script, $this->args]);
        return call(function () use($future) : \Generator {
            try {
                $this->channel = (yield $this->hub->accept($this->id));
                $this->hub->add($this->id, $this->channel, $future);
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Starting the parallel runtime failed", 0, $exception);
            }
            if ($this->killed) {
                $this->kill();
            }
            return $this->id;
        });
    }
    /**
     * Immediately kills the context.
     */
    public function kill() : void
    {
        $this->killed = \true;
        if ($this->runtime !== null) {
            try {
                $this->runtime->kill();
            } finally {
                $this->close();
            }
        }
    }
    /**
     * Closes channel and socket if still open.
     */
    private function close() : void
    {
        $this->runtime = null;
        if ($this->channel !== null) {
            $this->channel->close();
        }
        $this->channel = null;
        $this->hub->remove($this->id);
    }
    /**
    * Gets a promise that resolves when the context ends and joins with the
    parent context.
    *
    * @return \Amp\Promise<mixed>
    *
    * @throws StatusError Thrown if the context has not been started.
    * @throws SynchronizationError Thrown if an exit status object is not received.
    * @throws ContextException If the context stops responding.
    */
    public function join() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        return call(function () : \Generator {
            try {
                $response = (yield $this->channel->receive());
                $this->close();
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Failed to receive result from thread", 0, $exception);
            }
            if (!$response instanceof ExitResult) {
                $this->kill();
                throw new SynchronizationError('Did not receive an exit result from thread.');
            }
            return $response->getResult();
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started.');
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (ChannelException $e) {
                throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Thread unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        if ($data instanceof ExitResult) {
            throw new \Error('Cannot send exit result objects.');
        }
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->channel->send($data));
            } catch (ChannelException $e) {
                if ($this->channel === null) {
                    throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                try {
                    $data = (yield Promise\timeout($this->join(), 100));
                } catch (ContextException|ChannelException|TimeoutException $ex) {
                    $this->kill();
                    throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                throw new SynchronizationError(\sprintf('Thread unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)), 0, $e);
            }
        });
    }
    /**
     * Returns the ID of the thread. This ID will be unique to this process.
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getId() : int
    {
        if ($this->id === null) {
            throw new StatusError('The thread has not been started');
        }
        return $this->id;
    }
}
<?php

namespace PhabelVendor\Amp\Parallel\Context;

use PhabelVendor\Amp\Parallel\Sync\Channel;
use PhabelVendor\Amp\Promise;
interface Context extends Channel
{
    /**
     * @return bool
     */
    public function isRunning() : bool;
    /**
     * Starts the execution context.
     *
     * @return Promise<null> Resolved once the context has started.
     */
    public function start() : Promise;
    /**
     * Immediately kills the context.
     */
    public function kill();
    /**
     * @return \Amp\Promise<mixed> Resolves with the returned from the context.
     *
     * @throws \Amp\Parallel\Context\ContextException If the context dies unexpectedly.
     * @throws \Amp\Parallel\Sync\PanicError If the context throws an uncaught exception.
     */
    public function join() : Promise;
}
<?php

namespace PhabelVendor\Amp;

/**
 * Emitter is a container for an iterator that can emit values using the emit() method and completed using the
 * complete() and fail() methods of this object. The contained iterator may be accessed using the iterate()
 * method. This object should not be part of a public API, but used internally to create and emit values to an
 * iterator.
 *
 * @template TValue
 */
final class Emitter
{
    /** @var Iterator<TValue> Has public emit, complete, and fail methods. */
    private $emitter;
    /** @var Iterator<TValue> Hides producer methods. */
    private $iterator;
    /**
     *
     */
    public function __construct()
    {
        $this->emitter = new class implements Iterator
        {
            use Internal\Producer {
                emit as public;
                complete as public;
                fail as public;
            }
        };
        $this->iterator = new Internal\PrivateIterator($this->emitter);
    }
    /**
     * @return Iterator
     * @psalm-return Iterator<TValue>
     */
    public function iterate() : Iterator
    {
        return $this->iterator;
    }
    /**
     * Emits a value to the iterator.
     *
     * @param mixed $value
     *
     * @psalm-param TValue $value
     *
     * @return Promise
     * @psalm-return Promise<null>
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public function emit($value) : Promise
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        return $this->emitter->emit($value);
    }
    /**
     * Completes the iterator.
     *
     * @return void
     */
    public function complete()
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->emitter->complete();
    }
    /**
     * Fails the iterator with the given reason.
     *
     * @param \Throwable $reason
     *
     * @return void
     */
    public function fail(\Throwable $reason)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->emitter->fail($reason);
    }
}
<?php

namespace PhabelVendor\Amp;

/**
 * A NullCancellationToken can be used to avoid conditionals to check whether a token has been provided.
 *
 * Instead of writing
 *
 * ```php
 * if ($token) {
 *     $token->throwIfRequested();
 * }
 * ```
 *
 * potentially multiple times, it allows writing
 *
 * ```php
 * $token = $token ?? new NullCancellationToken;
 *
 * // ...
 *
 * $token->throwIfRequested();
 * ```
 *
 * instead.
 */
final class NullCancellationToken implements CancellationToken
{
    /**
     * @inheritdoc
     */
    public function subscribe(callable $callback) : string
    {
        return "null-token";
    }
    /**
     * @inheritdoc
     */
    public function unsubscribe(string $id)
    {
        // nothing to do
    }
    /**
     * @inheritdoc
     */
    public function isRequested() : bool
    {
        return \false;
    }
    /**
     * @inheritdoc
     */
    public function throwIfRequested()
    {
        // nothing to do
    }
}
<?php

namespace PhabelVendor\Amp;

use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a successful promise using the given value (which can be any value except an object implementing
 * `Amp\Promise` or `React\Promise\PromiseInterface`).
 *
 * @template-covariant TValue
 * @template-implements Promise<TValue>
 */
final class Success implements Promise
{
    /** @var mixed */
    private $value;
    /**
     * @param mixed $value Anything other than a Promise object.
     *
     * @psalm-param TValue $value
     *
     * @throws \Error If a promise is given as the value.
     */
    public function __construct($value = null)
    {
        if ($value instanceof Promise || $value instanceof ReactPromise) {
            throw new \Error("Cannot use a promise as success value");
        }
        $this->value = $value;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        try {
            $result = $onResolved(null, $this->value);
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
}
<?php

namespace PhabelVendor\Amp;

use function PhabelVendor\Amp\Internal\formatStacktrace;
/**
 * A TimeoutCancellationToken automatically requests cancellation after the timeout has elapsed.
 */
final class TimeoutCancellationToken implements CancellationToken
{
    /** @var string */
    private $watcher;
    /** @var CancellationToken */
    private $token;
    /**
     * @param int $timeout Milliseconds until cancellation is requested.
     * @param string $message Message for TimeoutException. Default is "Operation timed out".
     */
    public function __construct(int $timeout, string $message = "Operation timed out")
    {
        $source = new CancellationTokenSource();
        $this->token = $source->getToken();
        $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
        $this->watcher = Loop::delay($timeout, static function () use($source, $message, $trace) {
            $trace = formatStacktrace($trace);
            $source->cancel(new TimeoutException("{$message}\r\nTimeoutCancellationToken was created here:\r\n{$trace}"));
        });
        Loop::unreference($this->watcher);
    }
    /**
     * Cancels the delay watcher.
     */
    public function __destruct()
    {
        Loop::cancel($this->watcher);
    }
    /**
     * {@inheritdoc}
     */
    public function subscribe(callable $callback) : string
    {
        return $this->token->subscribe($callback);
    }
    /**
     * {@inheritdoc}
     */
    public function unsubscribe(string $id)
    {
        $this->token->unsubscribe($id);
    }
    /**
     * {@inheritdoc}
     */
    public function isRequested() : bool
    {
        return $this->token->isRequested();
    }
    /**
     * {@inheritdoc}
     */
    public function throwIfRequested()
    {
        $this->token->throwIfRequested();
    }
}
<?php

namespace PhabelVendor\Amp;

/**
 * @template-covariant TValue
 * @template-implements Iterator<TValue>
 */
final class Producer implements Iterator
{
    /**
     * @use Internal\Producer<TValue>
     */
    use CallableMaker, Internal\Producer;
    /**
     * @param callable(callable(TValue ): Promise ): \Generator $producer
     *
     * @throws \Error Thrown if the callable does not return a Generator.
     */
    public function __construct(callable $producer)
    {
        $result = $producer($this->callableFromInstanceMethod("emit"));
        if (!$result instanceof \Generator) {
            throw new \Error("The callable did not return a Generator");
        }
        $coroutine = new Coroutine($result);
        $coroutine->onResolve(function ($exception) {
            if ($this->complete) {
                return;
            }
            if ($exception) {
                $this->fail($exception);
                return;
            }
            $this->complete();
        });
    }
}
<?php

namespace PhabelVendor\Amp;

/**
 * Representation of the future value of an asynchronous operation.
 *
 * @template-covariant TValue
 * @psalm-yield TValue
 */
interface Promise
{
    /**
    * Registers a callback to be invoked when the promise is resolved.
    *
    * If this method is called multiple times, additional handlers will be registered instead of replacing any already
    existing handlers.
    *
    * If the promise is already resolved, the callback MUST be executed immediately.
    *
    * Exceptions MUST NOT be thrown from this method. Any exceptions thrown from invoked callbacks MUST be
    forwarded to the event-loop error handler.
    *
    * Note: You shouldn't implement this interface yourself. Instead, provide a method that returns a promise for the
    operation you're implementing. Objects other than pure placeholders implementing it are a very bad idea.
    *
    * @param callable $onResolved The first argument shall be `null` on success, while the second shall be `null` on
    failure.
    *
    * @psalm-param (callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $onResolved
    *
    * @return void
    */
    public function onResolve(callable $onResolved);
}
<?php

namespace PhabelVendor\Amp;

use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
/**
* Returns a new function that wraps $callback in a promise/coroutine-aware function that automatically runs
Generators as coroutines. The returned function always returns a promise when invoked. Errors have to be handled
by the callback caller or they will go unnoticed.
*
* Use this function to create a coroutine-aware callable for a promise-aware callback caller.
*
* @template TReturn
* @template TPromise
* @template TGeneratorReturn
* @template TGeneratorPromise
*
* @template TGenerator of (TGeneratorReturn | Promise<TGeneratorPromise>)
* @template T of (TReturn | Promise<TPromise> | \Generator<mixed, mixed, mixed, TGenerator>)
*
* @formatter :off
*
* @param callable(...mixed): T $callback
*
* @return callable
* @psalm-return (T is Promise ? (callable(mixed...): Promise<TPromise>) : (T is \Generator ? (TGenerator is Promise ? (callable(mixed...): Promise<TGeneratorPromise>) : (callable(mixed...): Promise<TGeneratorReturn>)) : (callable(mixed...): Promise<TReturn>)))
*
* @formatter :on
*
* @see asyncCoroutine()
*
* @psalm-suppress InvalidReturnType
*/
function coroutine(callable $callback) : callable
{
    /** @psalm-suppress InvalidReturnStatement */
    return static function (...$args) use($callback) : Promise {
        return call($callback, ...$args);
    };
}
/**
* Returns a new function that wraps $callback in a promise/coroutine-aware function that automatically runs
Generators as coroutines. The returned function always returns void when invoked. Errors are forwarded to the
loop's error handler using `Amp\Promise\rethrow()`.
*
* Use this function to create a coroutine-aware callable for a non-promise-aware callback caller.
*
* @param callable(...mixed): mixed $callback
*
* @return callable
* @psalm-return callable(mixed ...): void
*
* @see coroutine()
*/
function asyncCoroutine(callable $callback) : callable
{
    return static function (...$args) use($callback) {
        Promise\rethrow(call($callback, ...$args));
    };
}
/**
* Calls the given function, always returning a promise. If the function returns a Generator, it will be run as a
coroutine. If the function throws, a failed promise will be returned.
*
* @template TReturn
* @template TPromise
* @template TGeneratorReturn
* @template TGeneratorPromise
*
* @template TGenerator of (TGeneratorReturn | Promise<TGeneratorPromise>)
* @template T of (TReturn | Promise<TPromise> | \Generator<mixed, mixed, mixed, TGenerator>)
*
* @formatter :off
*
* @param callable(...mixed): T $callback
* @param mixed ...$args Arguments to pass to the function.
*
* @return Promise
* @psalm-return (T is Promise ? Promise<TPromise> : (T is \Generator ? (TGenerator is Promise ? Promise<TGeneratorPromise> : Promise<TGeneratorReturn>) : Promise<TReturn>))
*
* @formatter :on
*/
function call(callable $callback, ...$args) : Promise
{
    try {
        $result = $callback(...$args);
    } catch (\Throwable $exception) {
        return new Failure($exception);
    }
    if ($result instanceof \Generator) {
        return new Coroutine($result);
    }
    if ($result instanceof Promise) {
        return $result;
    }
    if ($result instanceof ReactPromise) {
        return Promise\adapt($result);
    }
    return new Success($result);
}
/**
* Calls the given function. If the function returns a Generator, it will be run as a coroutine. If the function
throws or returns a failing promise, the failure is forwarded to the loop error handler.
*
* @param callable(...mixed): mixed $callback
* @param mixed ...$args Arguments to pass to the function.
*
* @return void
*/
function asyncCall(callable $callback, ...$args)
{
    Promise\rethrow(call($callback, ...$args));
}
/**
 * Sleeps for the specified number of milliseconds.
 *
 * @param int $milliseconds
 *
 * @return Delayed
 */
function delay(int $milliseconds) : Delayed
{
    return new Delayed($milliseconds);
}
/**
 * Returns the current time relative to an arbitrary point in time.
 *
 * @return int Time in milliseconds.
 */
function getCurrentTime() : int
{
    return Internal\getCurrentTime();
}
namespace PhabelVendor\Amp\Promise;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\MultiReasonException;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
use PhabelVendor\Amp\TimeoutException;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
use function PhabelVendor\Amp\call;
use function PhabelVendor\Amp\Internal\createTypeError;
/**
* Registers a callback that will forward the failure reason to the event loop's error handler if the promise fails.
*
* Use this function if you neither return the promise nor handle a possible error yourself to prevent errors from
going entirely unnoticed.
*
* @param (Promise | ReactPromise) $promise Promise to register the handler on.
*
* @return void
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
*
*/
function rethrow($promise)
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $promise->onResolve(static function ($exception) {
        if ($exception) {
            throw $exception;
        }
    });
}
/**
* Runs the event loop until the promise is resolved. Should not be called within a running event loop.
*
* Use this function only in synchronous contexts to wait for an asynchronous operation. Use coroutines and yield to
await promise resolution in a fully asynchronous application instead.
*
* @template TPromise
* @template T of (Promise<TPromise> | ReactPromise)
*
* @param (Promise | ReactPromise) $promise Promise to wait for.
*
* @return mixed Promise success value.
*
* @psalm-param T $promise
* @psalm-return (T is Promise ? TPromise : mixed)
*
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
* @throws \Error If the event loop stopped without the $promise being resolved.
* @throws \Throwable Promise failure reason.
*/
function wait($promise)
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $resolved = \false;
    try {
        Loop::run(function () use(&$resolved, &$value, &$exception, $promise) {
            $promise->onResolve(function ($e, $v) use(&$resolved, &$value, &$exception) {
                Loop::stop();
                $resolved = \true;
                $exception = $e;
                $value = $v;
            });
        });
    } catch (\Throwable $throwable) {
        throw new \Error("Loop exceptionally stopped without resolving the promise", 0, $throwable);
    }
    if (!$resolved) {
        throw new \Error("Loop stopped without resolving the promise");
    }
    if ($exception) {
        throw $exception;
    }
    return $value;
}
/**
* Creates an artificial timeout for any `Promise`.
*
* If the timeout expires before the promise is resolved, the returned promise fails with an instance of
`Amp\TimeoutException`.
*
* @template TReturn
*
* @param (Promise<TReturn> | ReactPromise) $promise Promise to which the timeout is applied.
* @param int $timeout Timeout in milliseconds.
*
* @return Promise<TReturn>
*
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
*/
function timeout($promise, int $timeout) : Promise
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $deferred = new Deferred();
    $watcher = Loop::delay($timeout, static function () use(&$deferred) {
        $temp = $deferred;
        // prevent double resolve
        $deferred = null;
        $temp->fail(new TimeoutException());
    });
    Loop::unreference($watcher);
    $promise->onResolve(function () use(&$deferred, $promise, $watcher) {
        if ($deferred !== null) {
            Loop::cancel($watcher);
            $deferred->resolve($promise);
        }
    });
    return $deferred->promise();
}
/**
 * Creates an artificial timeout for any `Promise`.
 *
 * If the promise is resolved before the timeout expires, the result is returned
 *
 * If the timeout expires before the promise is resolved, a default value is returned
 *
 * @template TReturn
 *
 * @param (Promise<TReturn> | ReactPromise) $promise Promise to which the timeout is applied.
 * @param int $timeout Timeout in milliseconds.
 * @param TReturn $default
 *
 * @return Promise<TReturn>
 *
 * @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
 */
function timeoutWithDefault($promise, int $timeout, $default = null) : Promise
{
    $promise = timeout($promise, $timeout);
    return call(static function () use($promise, $default) {
        try {
            return (yield $promise);
        } catch (TimeoutException $exception) {
            return $default;
        }
    });
}
/**
* Adapts any object with a done(callable $onFulfilled, callable $onRejected) or then(callable $onFulfilled,
callable $onRejected) method to a promise usable by components depending on placeholders implementing
\AsyncInterop\Promise.
*
* @param object $promise Object with a done() or then() method.
*
* @return Promise Promise resolved by the $thenable object.
*
* @throws \Error If the provided object does not have a then() method.
*/
function adapt($promise) : Promise
{
    if (!\is_object($promise)) {
        throw new \Error("Object must be provided");
    }
    $deferred = new Deferred();
    if (\method_exists($promise, 'done')) {
        $promise->done([$deferred, 'resolve'], [$deferred, 'fail']);
    } elseif (\method_exists($promise, 'then')) {
        $promise->then([$deferred, 'resolve'], [$deferred, 'fail']);
    } else {
        throw new \Error("Object must have a 'then' or 'done' method");
    }
    return $deferred->promise();
}
/**
* Returns a promise that is resolved when all promises are resolved. The returned promise will not fail.
Returned promise succeeds with a two-item array delineating successful and failed promise results,
with keys identical and corresponding to the original given array.
*
* This function is the same as some() with the notable exception that it will never fail even
if all promises in the array resolve unsuccessfully.
*
* @template TValue
*
* @param (Promise<TValue>[] | ReactPromise[]) $promises
*
* @return Promise<array{0: \Throwable[], 1: TValue[]}>
*
* @throws \Error If a non-Promise is in the array.
*/
function any(array $promises) : Promise
{
    return some($promises, 0);
}
/**
* Returns a promise that succeeds when all promises succeed, and fails if any promise fails. Returned
promise succeeds with an array of values used to succeed each contained promise, with keys corresponding to
the array of promises.
*
* @param (Promise[] | ReactPromise[]) $promises Array of only promises.
*
* @return Promise
*
* @throws \Error If a non-Promise is in the array.
*
* @template TValue
*
* @psalm-param array<array-key, (Promise<TValue> | ReactPromise)> $promises
* @psalm-assert array<array-key, Promise<TValue>|ReactPromise> $promises $promises
* @psalm-return Promise<array<array-key, TValue>>
*/
function all(array $promises) : Promise
{
    if (empty($promises)) {
        return new Success([]);
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $pending = \count($promises);
    $values = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $values[$key] = null;
        // add entry to array to preserve order
        $promise->onResolve(function ($exception, $value) use(&$deferred, &$values, &$pending, $key) {
            if ($pending === 0) {
                return;
            }
            if ($exception) {
                $pending = 0;
                $deferred->fail($exception);
                $deferred = null;
                return;
            }
            $values[$key] = $value;
            if (0 === --$pending) {
                $deferred->resolve($values);
            }
        });
    }
    return $result;
}
/**
 * Returns a promise that succeeds when the first promise succeeds, and fails only if all promises fail.
 *
 * @template TValue
 *
 * @param (Promise<TValue>[] | ReactPromise[]) $promises Array of only promises.
 *
 * @return Promise<TValue>
 *
 * @throws \Error If the array is empty or a non-Promise is in the array.
 */
function first(array $promises) : Promise
{
    if (empty($promises)) {
        throw new \Error("No promises provided");
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $pending = \count($promises);
    $exceptions = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $exceptions[$key] = null;
        // add entry to array to preserve order
        $promise->onResolve(function ($error, $value) use(&$deferred, &$exceptions, &$pending, $key) {
            if ($pending === 0) {
                return;
            }
            if (!$error) {
                $pending = 0;
                $deferred->resolve($value);
                $deferred = null;
                return;
            }
            $exceptions[$key] = $error;
            if (0 === --$pending) {
                $deferred->fail(new MultiReasonException($exceptions));
            }
        });
    }
    return $result;
}
/**
* Resolves with a two-item array delineating successful and failed Promise results.
*
* The returned promise will only fail if the given number of required promises fail.
*
* @template TValue
*
* @param (Promise<TValue>[] | ReactPromise[]) $promises Array of only promises.
* @param int $required Number of promises that must succeed for the
returned promise to succeed.
*
* @return Promise<array{0: \Throwable[], 1: TValue[]}>
*
* @throws \Error If a non-Promise is in the array.
*/
function some(array $promises, int $required = 1) : Promise
{
    if ($required < 0) {
        throw new \Error("Number of promises required must be non-negative");
    }
    $pending = \count($promises);
    if ($required > $pending) {
        throw new \Error("Too few promises provided");
    }
    if (empty($promises)) {
        return new Success([[], []]);
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $values = [];
    $exceptions = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $values[$key] = $exceptions[$key] = null;
        // add entry to arrays to preserve order
        $promise->onResolve(static function ($exception, $value) use(&$values, &$exceptions, &$pending, $key, $required, $deferred) {
            if ($exception) {
                $exceptions[$key] = $exception;
                unset($values[$key]);
            } else {
                $values[$key] = $value;
                unset($exceptions[$key]);
            }
            if (0 === --$pending) {
                if (\count($values) < $required) {
                    $deferred->fail(new MultiReasonException($exceptions));
                } else {
                    $deferred->resolve([$exceptions, $values]);
                }
            }
        });
    }
    return $result;
}
/**
 * Wraps a promise into another promise, altering the exception or result.
 *
 * @param (Promise | ReactPromise) $promise
 * @param callable $callback
 *
 * @return Promise
 */
function wrap($promise, callable $callback) : Promise
{
    if ($promise instanceof ReactPromise) {
        $promise = adapt($promise);
    } elseif (!$promise instanceof Promise) {
        throw createTypeError([Promise::class, ReactPromise::class], $promise);
    }
    $deferred = new Deferred();
    $promise->onResolve(static function (\Throwable $exception = null, $result) use($deferred, $callback) {
        try {
            $result = $callback($exception, $result);
        } catch (\Throwable $exception) {
            $deferred->fail($exception);
            return;
        }
        $deferred->resolve($result);
    });
    return $deferred->promise();
}
namespace PhabelVendor\Amp\Iterator;

use PhabelVendor\Amp\Delayed;
use PhabelVendor\Amp\Emitter;
use PhabelVendor\Amp\Iterator;
use PhabelVendor\Amp\Producer;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
use function PhabelVendor\Amp\coroutine;
use function PhabelVendor\Amp\Internal\createTypeError;
/**
* Creates an iterator from the given iterable, emitting the each value. The iterable may contain promises. If any
promise fails, the iterator will fail with the same reason.
*
* @param (array | \Traversable) $iterable Elements to emit.
* @param int $delay Delay between element emissions in milliseconds.
*
* @return Iterator
*
* @throws \TypeError If the argument is not an array or instance of \Traversable.
*/
function fromIterable($iterable, int $delay = 0) : Iterator
{
    if (!$iterable instanceof \Traversable && !\is_array($iterable)) {
        throw createTypeError(["array", "Traversable"], $iterable);
    }
    if ($delay) {
        return new Producer(static function (callable $emit) use($iterable, $delay) {
            foreach ($iterable as $value) {
                (yield new Delayed($delay));
                (yield $emit($value));
            }
        });
    }
    return new Producer(static function (callable $emit) use($iterable) {
        foreach ($iterable as $value) {
            (yield $emit($value));
        }
    });
}
/**
 * @template TValue
 * @template TReturn
 *
 * @param Iterator<TValue> $iterator
 * @param callable(TValue $value): TReturn $onEmit
 *
 * @return Iterator<TReturn>
 */
function map(Iterator $iterator, callable $onEmit) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $onEmit) {
        while ((yield $iterator->advance())) {
            (yield $emit($onEmit($iterator->getCurrent())));
        }
    });
}
/**
 * @template TValue
 *
 * @param Iterator<TValue> $iterator
 * @param callable(TValue $value): bool $filter
 *
 * @return Iterator<TValue>
 */
function filter(Iterator $iterator, callable $filter) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $filter) {
        while ((yield $iterator->advance())) {
            if ($filter($iterator->getCurrent())) {
                (yield $emit($iterator->getCurrent()));
            }
        }
    });
}
/**
 * Creates an iterator that emits values emitted from any iterator in the array of iterators.
 *
 * @param Iterator[] $iterators
 *
 * @return Iterator
 */
function merge(array $iterators) : Iterator
{
    $emitter = new Emitter();
    $result = $emitter->iterate();
    $coroutine = coroutine(static function (Iterator $iterator) use(&$emitter) {
        while ((yield $iterator->advance()) && $emitter !== null) {
            (yield $emitter->emit($iterator->getCurrent()));
        }
    });
    $coroutines = [];
    foreach ($iterators as $iterator) {
        if (!$iterator instanceof Iterator) {
            throw createTypeError([Iterator::class], $iterator);
        }
        $coroutines[] = $coroutine($iterator);
    }
    Promise\all($coroutines)->onResolve(static function ($exception) use(&$emitter) {
        if ($exception) {
            $emitter->fail($exception);
            $emitter = null;
        } else {
            $emitter->complete();
        }
    });
    return $result;
}
/**
* Concatenates the given iterators into a single iterator, emitting values from a single iterator at a time. The
prior iterator must complete before values are emitted from any subsequent iterators. Iterators are concatenated
in the order given (iteration order of the array).
*
* @param Iterator[] $iterators
*
* @return Iterator
*/
function concat(array $iterators) : Iterator
{
    foreach ($iterators as $iterator) {
        if (!$iterator instanceof Iterator) {
            throw createTypeError([Iterator::class], $iterator);
        }
    }
    $emitter = new Emitter();
    $previous = [];
    $promise = Promise\all($previous);
    $coroutine = coroutine(static function (Iterator $iterator, callable $emit) {
        while ((yield $iterator->advance())) {
            (yield $emit($iterator->getCurrent()));
        }
    });
    foreach ($iterators as $iterator) {
        $emit = coroutine(static function ($value) use($emitter, $promise) {
            static $pending = \true, $failed = \false;
            if ($failed) {
                return;
            }
            if ($pending) {
                try {
                    (yield $promise);
                    $pending = \false;
                } catch (\Throwable $exception) {
                    $failed = \true;
                    return;
                    // Prior iterator failed.
                }
            }
            (yield $emitter->emit($value));
        });
        $previous[] = $coroutine($iterator, $emit);
        $promise = Promise\all($previous);
    }
    $promise->onResolve(static function ($exception) use($emitter) {
        if ($exception) {
            $emitter->fail($exception);
            return;
        }
        $emitter->complete();
    });
    return $emitter->iterate();
}
/**
 * Discards all remaining items and returns the number of discarded items.
 *
 * @template TValue
 *
 * @param Iterator $iterator
 *
 * @return Promise
 *
 * @psalm-param Iterator<TValue> $iterator
 * @psalm-return Promise<int>
 */
function discard(Iterator $iterator) : Promise
{
    return call(static function () use($iterator) : \Generator {
        $count = 0;
        while ((yield $iterator->advance())) {
            $count++;
        }
        return $count;
    });
}
/**
 * Collects all items from an iterator into an array.
 *
 * @template TValue
 *
 * @param Iterator $iterator
 *
 * @psalm-param Iterator<TValue> $iterator
 *
 * @return Promise
 * @psalm-return Promise<array<array-key, TValue>>
 */
function toArray(Iterator $iterator) : Promise
{
    return call(static function () use($iterator) {
        /** @psalm-var list $array */
        $array = [];
        while ((yield $iterator->advance())) {
            $array[] = $iterator->getCurrent();
        }
        return $array;
    });
}
<?php

namespace PhabelVendor\Amp\Internal;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Promise;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
/**
 * Trait used by Promise implementations. Do not use this trait in your code, instead compose your class from one of
 * the available classes implementing \Amp\Promise.
 *
 * @internal
 */
trait Placeholder
{
    /** @var bool */
    private $resolved = \false;
    /** @var mixed */
    private $result;
    /** @var ResolutionQueue|null|callable(\Throwable|null, mixed): (Promise|\React\Promise\PromiseInterface|\Generator<mixed,
     *     Promise|\React\Promise\PromiseInterface|array<array-key, Promise|\React\Promise\PromiseInterface>, mixed,
     *     mixed>|null)|callable(\Throwable|null, mixed): void */
    private $onResolved;
    /** @var null|array */
    private $resolutionTrace;
    /**
     * @inheritdoc
     */
    public function onResolve(callable $onResolved)
    {
        if ($this->resolved) {
            if ($this->result instanceof Promise) {
                $this->result->onResolve($onResolved);
                return;
            }
            try {
                /** @var mixed $result */
                $result = $onResolved(null, $this->result);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    Promise\rethrow($result);
                }
            } catch (\Throwable $exception) {
                Loop::defer(static function () use($exception) {
                    throw $exception;
                });
            }
            return;
        }
        if (null === $this->onResolved) {
            $this->onResolved = $onResolved;
            return;
        }
        if (!$this->onResolved instanceof ResolutionQueue) {
            /** @psalm-suppress InternalClass */
            $this->onResolved = new ResolutionQueue($this->onResolved);
        }
        /** @psalm-suppress InternalMethod */
        $this->onResolved->push($onResolved);
    }
    /**
     *
     */
    public function __destruct()
    {
        try {
            $this->result = null;
        } catch (\Throwable $e) {
            Loop::defer(static function () use($e) {
                throw $e;
            });
        }
    }
    /**
     * @param mixed $value
     *
     * @return void
     *
     * @throws \Error Thrown if the promise has already been resolved.
     */
    private function resolve($value = null)
    {
        if ($this->resolved) {
            $message = "Promise has already been resolved";
            if (isset($this->resolutionTrace)) {
                $trace = formatStacktrace($this->resolutionTrace);
                $message .= ". Previous resolution trace:\n\n{$trace}\n\n";
            } else {
                // @codeCoverageIgnoreStart
                $message .= ', define environment variable AMP_DEBUG or const AMP_DEBUG = true and enable assertions for a stacktrace of the previous resolution.';
                // @codeCoverageIgnoreEnd
            }
            throw new \Error($message);
        }
        \assert((function () {
            $env = \getenv("AMP_DEBUG") ?: "0";
            if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG") && \AMP_DEBUG) {
                $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
                \array_shift($trace);
                // remove current closure
                $this->resolutionTrace = $trace;
            }
            return \true;
        })());
        if ($value instanceof ReactPromise) {
            $value = Promise\adapt($value);
        }
        $this->resolved = \true;
        $this->result = $value;
        if ($this->onResolved === null) {
            return;
        }
        $onResolved = $this->onResolved;
        $this->onResolved = null;
        if ($this->result instanceof Promise) {
            $this->result->onResolve($onResolved);
            return;
        }
        try {
            /** @var mixed $result */
            $result = $onResolved(null, $this->result);
            $onResolved = null;
            // allow garbage collection of $onResolved, to catch any exceptions from destructors
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
    /**
     * @param \Throwable $reason Failure reason.
     *
     * @return void
     */
    private function fail(\Throwable $reason)
    {
        $this->resolve(new Failure($reason));
    }
    /**
     * @return bool True if the placeholder has been resolved.
     */
    private function isResolved() : bool
    {
        return $this->resolved;
    }
}
<?php

namespace PhabelVendor\Amp\Internal;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
/**
 * Trait used by Iterator implementations. Do not use this trait in your code, instead compose your class from one of
 * the available classes implementing \Amp\Iterator.
 * Note that it is the responsibility of the user of this trait to ensure that listeners have a chance to listen first
 * before emitting values.
 *
 * @internal
 * @template-covariant TValue
 */
trait Producer
{
    /** @var Promise|null */
    private $complete;
    /** @var mixed[] */
    private $values = [];
    /** @var Deferred[] */
    private $backPressure = [];
    /** @var int */
    private $consumePosition = -1;
    /** @var int */
    private $emitPosition = -1;
    /** @var Deferred|null */
    private $waiting;
    /** @var null|array */
    private $resolutionTrace;
    /**
     * {@inheritdoc}
     *
     * @return Promise<bool>
     */
    public function advance() : Promise
    {
        if ($this->waiting !== null) {
            throw new \Error("The prior promise returned must resolve before invoking this method again");
        }
        unset($this->values[$this->consumePosition]);
        $position = ++$this->consumePosition;
        if (\array_key_exists($position, $this->values)) {
            \assert(isset($this->backPressure[$position]));
            $deferred = $this->backPressure[$position];
            unset($this->backPressure[$position]);
            $deferred->resolve();
            return new Success(\true);
        }
        if ($this->complete) {
            return $this->complete;
        }
        $this->waiting = new Deferred();
        return $this->waiting->promise();
    }
    /**
     * {@inheritdoc}
     *
     * @return TValue
     */
    public function getCurrent()
    {
        if (empty($this->values) && $this->complete) {
            throw new \Error("The iterator has completed");
        }
        if (!\array_key_exists($this->consumePosition, $this->values)) {
            throw new \Error("Promise returned from advance() must resolve before calling this method");
        }
        return $this->values[$this->consumePosition];
    }
    /**
     * Emits a value from the iterator. The returned promise is resolved once the emitted value has been consumed.
     *
     * @param mixed $value
     *
     * @return Promise
     * @psalm-return Promise<null>
     *
     * @throws \Error If the iterator has completed.
     */
    private function emit($value) : Promise
    {
        if ($this->complete) {
            throw new \Error("Iterators cannot emit values after calling complete");
        }
        if ($value instanceof ReactPromise) {
            $value = Promise\adapt($value);
        }
        if ($value instanceof Promise) {
            $deferred = new Deferred();
            $value->onResolve(function ($e, $v) use($deferred) {
                if ($this->complete) {
                    $deferred->fail(new \Error("The iterator was completed before the promise result could be emitted"));
                    return;
                }
                if ($e) {
                    $this->fail($e);
                    $deferred->fail($e);
                    return;
                }
                $deferred->resolve($this->emit($v));
            });
            return $deferred->promise();
        }
        $position = ++$this->emitPosition;
        $this->values[$position] = $value;
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve(\true);
            return new Success();
            // Consumer was already waiting for a new value, so back-pressure is unnecessary.
        }
        $this->backPressure[$position] = $pressure = new Deferred();
        return $pressure->promise();
    }
    /**
     * Completes the iterator.
     *
     * @return void
     *
     * @throws \Error If the iterator has already been completed.
     */
    private function complete()
    {
        if ($this->complete) {
            $message = "Iterator has already been completed";
            if (isset($this->resolutionTrace)) {
                $trace = formatStacktrace($this->resolutionTrace);
                $message .= ". Previous completion trace:\n\n{$trace}\n\n";
            } else {
                // @codeCoverageIgnoreStart
                $message .= ', define environment variable AMP_DEBUG or const AMP_DEBUG = true and enable assertions for a stacktrace of the previous resolution.';
                // @codeCoverageIgnoreEnd
            }
            throw new \Error($message);
        }
        \assert((function () {
            $env = \getenv("AMP_DEBUG") ?: "0";
            if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG") && \AMP_DEBUG) {
                $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
                \array_shift($trace);
                // remove current closure
                $this->resolutionTrace = $trace;
            }
            return \true;
        })());
        $this->complete = new Success(\false);
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve($this->complete);
        }
    }
    /**
     * @param \Throwable $exception
     *
     * @return void
     */
    private function fail(\Throwable $exception)
    {
        $this->complete = new Failure($exception);
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve($this->complete);
        }
    }
}
<?php

namespace PhabelVendor\Amp\Internal;

/**
* Formats a stacktrace obtained via `debug_backtrace()`.
*
* @param array<array{file?: string, line: int, type?: string, class: string, function: string}> $trace Output of
`debug_backtrace()`.
*
* @return string Formatted stacktrace.
*
* @codeCoverageIgnore
* @internal
*/
function formatStacktrace(array $trace) : string
{
    return \implode("\n", \array_map(static function ($e, $i) {
        $line = "#{$i} ";
        if (isset($e["file"])) {
            $line .= "{$e['file']}:{$e['line']} ";
        }
        if (isset($e["type"])) {
            $line .= $e["class"] . $e["type"];
        }
        return $line . $e["function"] . "()";
    }, $trace, \array_keys($trace)));
}
/**
 * Creates a `TypeError` with a standardized error message.
 *
 * @param string[] $expected Expected types.
 * @param mixed $given Given value.
 *
 * @return \TypeError
 *
 * @internal
 */
function createTypeError(array $expected, $given) : \TypeError
{
    $givenType = \is_object($given) ? \sprintf("instance of %s", \get_class($given)) : \gettype($given);
    if (\count($expected) === 1) {
        $expectedType = "Expected the following type: " . \array_pop($expected);
    } else {
        $expectedType = "Expected one of the following types: " . \implode(", ", $expected);
    }
    return new \TypeError("{$expectedType}; {$givenType} given");
}
/**
 * Returns the current time relative to an arbitrary point in time.
 *
 * @return int Time in milliseconds.
 */
function getCurrentTime() : int
{
    /** @var int|null $startTime */
    static $startTime;
    /** @var int|null $nextWarning */
    static $nextWarning;
    if (\PHP_INT_SIZE === 4) {
        // @codeCoverageIgnoreStart
        if ($startTime === null) {
            $startTime = \PHP_VERSION_ID >= 70300 ? \hrtime(\false)[0] : \time();
            $nextWarning = \PHP_INT_MAX - 86400 * 7;
        }
        if (\PHP_VERSION_ID >= 70300) {
            list($seconds, $nanoseconds) = \hrtime(\false);
            $seconds -= $startTime;
            if ($seconds >= $nextWarning) {
                $timeToOverflow = (\PHP_INT_MAX - $seconds * 1000) / 1000;
                \trigger_error("getCurrentTime() will overflow in {$timeToOverflow} seconds, please restart the process before that. " . "You're using a 32 bit version of PHP, so time will overflow about every 24 days. Regular restarts are required.", \E_USER_WARNING);
                /** @psalm-suppress PossiblyNullOperand */
                $nextWarning += 600;
                // every 10 minutes
            }
            return (int) ($seconds * 1000 + $nanoseconds / 1000000);
        }
        $seconds = \microtime(\true) - $startTime;
        if ($seconds >= $nextWarning) {
            $timeToOverflow = (\PHP_INT_MAX - $seconds * 1000) / 1000;
            \trigger_error("getCurrentTime() will overflow in {$timeToOverflow} seconds, please restart the process before that. " . "You're using a 32 bit version of PHP, so time will overflow about every 24 days. Regular restarts are required.", \E_USER_WARNING);
            /** @psalm-suppress PossiblyNullOperand */
            $nextWarning += 600;
            // every 10 minutes
        }
        return (int) ($seconds * 1000);
        // @codeCoverageIgnoreEnd
    }
    if (\PHP_VERSION_ID >= 70300) {
        list($seconds, $nanoseconds) = \hrtime(\false);
        return (int) ($seconds * 1000 + $nanoseconds / 1000000);
    }
    return (int) (\microtime(\true) * 1000);
}
<?php

namespace PhabelVendor\Amp\Internal;

use PhabelVendor\Amp\Promise;
/**
 * Wraps a Promise instance that has public methods to resolve and fail the promise into an object that only allows
 * access to the public API methods.
 */
final class PrivatePromise implements Promise
{
    /** @var Promise */
    private $promise;
    /**
     *
     */
    public function __construct(Promise $promise)
    {
        $this->promise = $promise;
    }
    /**
     *
     */
    public function onResolve(callable $onResolved)
    {
        $this->promise->onResolve($onResolved);
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\Internal;

use PhabelVendor\Amp\Iterator;
use PhabelVendor\Amp\Promise;
/**
 * Wraps an Iterator instance that has public methods to emit, complete, and fail into an object that only allows
 * access to the public API methods.
 *
 * @template-covariant TValue
 * @template-implements Iterator<TValue>
 */
final class PrivateIterator implements Iterator
{
    /** @var Iterator<TValue> */
    private $iterator;
    /**
     * @param Iterator $iterator
     *
     * @psalm-param Iterator<TValue> $iterator
     */
    public function __construct(Iterator $iterator)
    {
        $this->iterator = $iterator;
    }
    /**
     * @return Promise<bool>
     */
    public function advance() : Promise
    {
        return $this->iterator->advance();
    }
    /**
     * @psalm-return TValue
     */
    public function getCurrent()
    {
        return $this->iterator->getCurrent();
    }
}
<?php

namespace PhabelVendor\Amp\Internal;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Promise;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
/**
 * Stores a set of functions to be invoked when a promise is resolved.
 *
 * @internal
 * @psalm-internal Amp\Internal
 */
class ResolutionQueue
{
    /** @var array<array-key, callable(\Throwable|null, mixed): (Promise|\React\Promise\PromiseInterface|\Generator<mixed,
     *     Promise|\React\Promise\PromiseInterface|array<array-key, Promise|\React\Promise\PromiseInterface>, mixed,
     *     mixed>|null) | callable(\Throwable|null, mixed): void> */
    private $queue = [];
    /**
     * @param (callable | null) $callback Initial callback to add to queue.
     *
     * @psalm-param (null | callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $callback
     */
    public function __construct(callable $callback = null)
    {
        if ($callback !== null) {
            $this->push($callback);
        }
    }
    /**
     * Unrolls instances of self to avoid blowing up the call stack on resolution.
     *
     * @param callable $callback
     *
     * @psalm-param (callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $callback
     *
     * @return void
     */
    public function push(callable $callback)
    {
        if ($callback instanceof self) {
            $this->queue = \array_merge($this->queue, $callback->queue);
            return;
        }
        $this->queue[] = $callback;
    }
    /**
     * Calls each callback in the queue, passing the provided values to the function.
     *
     * @param (\Throwable | null) $exception
     * @param mixed $value
     *
     * @return void
     */
    public function __invoke($exception, $value)
    {
        foreach ($this->queue as $callback) {
            try {
                $result = $callback($exception, $value);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    Promise\rethrow($result);
                }
            } catch (\Throwable $exception) {
                Loop::defer(static function () use($exception) {
                    throw $exception;
                });
            }
        }
    }
}
<?php

namespace PhabelVendor\Amp;

use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
use function PhabelVendor\Amp\Promise\rethrow;
/**
 * A cancellation token source provides a mechanism to cancel operations.
 *
 * Cancellation of operation works by creating a cancellation token source and passing the corresponding token when
 * starting the operation. To cancel the operation, invoke `CancellationTokenSource::cancel()`.
 *
 * Any operation can decide what to do on a cancellation request, it has "don't care" semantics. An operation SHOULD be
 * aborted, but MAY continue. Example: A DNS client might continue to receive and cache the response, as the query has
 * been sent anyway. An HTTP client would usually close a connection, but might not do so in case a response is close to
 * be fully received to reuse the connection.
 *
 * **Example**
 *
 * ```php
 * $tokenSource = new CancellationTokenSource;
 * $token = $tokenSource->getToken();
 *
 * $response = yield $httpClient->request("https://example.com/stream", $token);
 * $responseBody = $response->getBody();
 *
 * while (($chunk = yield $response->read()) !== null) {
 *     // consume $chunk
 *
 *     if ($noLongerInterested) {
 *         $cancellationTokenSource->cancel();
 *         break;
 *     }
 * }
 * ```
 *
 * @see CancellationToken
 * @see CancelledException
 */
final class CancellationTokenSource
{
    /** @var CancellationToken */
    private $token;
    /** @var callable|null */
    private $onCancel;
    /**
     *
     */
    public function __construct()
    {
        $onCancel = null;
        $this->token = new class($onCancel) implements CancellationToken
        {
            /** @var string */
            private $nextId = "a";
            /** @var callable[] */
            private $callbacks = [];
            /** @var \Throwable|null */
            private $exception;
            /**
             * @param mixed $onCancel
             * @param-out callable $onCancel
             */
            public function __construct(&$onCancel)
            {
                /** @psalm-suppress MissingClosureReturnType We still support PHP 7.0 */
                $onCancel = function (\Throwable $exception) {
                    $this->exception = $exception;
                    $callbacks = $this->callbacks;
                    $this->callbacks = [];
                    foreach ($callbacks as $callback) {
                        $this->invokeCallback($callback);
                    }
                };
            }
            /**
             * @param callable $callback
             *
             * @return void
             */
            private function invokeCallback(callable $callback)
            {
                // No type declaration to prevent exception outside the try!
                try {
                    /** @var mixed $result */
                    $result = $callback($this->exception);
                    if ($result instanceof \Generator) {
                        /** @psalm-var \Generator<mixed, Promise|ReactPromise|(Promise|ReactPromise)[], mixed, mixed> $result */
                        $result = new Coroutine($result);
                    }
                    if ($result instanceof Promise || $result instanceof ReactPromise) {
                        rethrow($result);
                    }
                } catch (\Throwable $exception) {
                    Loop::defer(static function () use($exception) {
                        throw $exception;
                    });
                }
            }
            /**
             *
             */
            public function subscribe(callable $callback) : string
            {
                $id = $this->nextId++;
                if ($this->exception) {
                    $this->invokeCallback($callback);
                } else {
                    $this->callbacks[$id] = $callback;
                }
                return $id;
            }
            /**
             *
             */
            public function unsubscribe(string $id)
            {
                unset($this->callbacks[$id]);
            }
            /**
             *
             */
            public function isRequested() : bool
            {
                return isset($this->exception);
            }
            /**
             *
             */
            public function throwIfRequested()
            {
                if (isset($this->exception)) {
                    throw $this->exception;
                }
            }
        };
        $this->onCancel = $onCancel;
    }
    /**
     *
     */
    public function getToken() : CancellationToken
    {
        return $this->token;
    }
    /**
     * @param (\Throwable | null) $previous Exception to be used as the previous exception to CancelledException.
     *
     * @return void
     */
    public function cancel(\Throwable $previous = null)
    {
        if ($this->onCancel === null) {
            return;
        }
        $onCancel = $this->onCancel;
        $this->onCancel = null;
        $onCancel(new CancelledException($previous));
    }
}
<?php

namespace PhabelVendor\Amp\Loop;

use PhabelVendor\Amp\Struct;
/**
 * @template TValue as (int|resource|null)
 *
 * @psalm-suppress MissingConstructor
 */
class Watcher
{
    use Struct;
    const IO = 0b11;
    const READABLE = 0b1;
    const WRITABLE = 0b10;
    const DEFER = 0b100;
    const TIMER = 0b11000;
    const DELAY = 0b1000;
    const REPEAT = 0b10000;
    const SIGNAL = 0b100000;
    /** @var int */
    public $type;
    /** @var bool */
    public $enabled = \true;
    /** @var bool */
    public $referenced = \true;
    /** @var string */
    public $id;
    /** @var callable */
    public $callback;
    /**
     * Data provided to the watcher callback.
     *
     * @var mixed
     */
    public $data;
    /**
     * Watcher-dependent value storage. Stream for IO watchers, signal number for signal watchers, interval for timers.
     *
     * @var resource|int|null
     * @psalm-var TValue
     */
    public $value;
    /** @var int|null */
    public $expiration;
}
<?php

namespace PhabelVendor\Amp\Loop;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Promise;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
use function PhabelVendor\Amp\Internal\getCurrentTime;
use function PhabelVendor\Amp\Promise\rethrow;
class EventDriver extends Driver
{
    /** @var \Event[]|null */
    private static $activeSignals;
    /** @var \EventBase */
    private $handle;
    /** @var \Event[] */
    private $events = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /** @var \Event[] */
    private $signals = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /**
     *
     */
    public function __construct()
    {
        $config = new \EventConfig();
        if (\DIRECTORY_SEPARATOR !== '\\') {
            $config->requireFeatures(\EventConfig::FEATURE_FDS);
        }
        $this->handle = new \EventBase($config);
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        if (self::$activeSignals === null) {
            self::$activeSignals =& $this->signals;
        }
        /**
         * @param         $resource
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->ioCallback = function ($resource, $what, Watcher $watcher) {
            \assert(\is_resource($watcher->value));
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param         $resource
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->timerCallback = function ($resource, $what, Watcher $watcher) {
            \assert(\is_int($watcher->value));
            if ($watcher->type & Watcher::DELAY) {
                $this->cancel($watcher->id);
            } else {
                $this->events[$watcher->id]->add($watcher->value / self::MILLISEC_PER_SEC);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param         $signum
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->signalCallback = function ($signum, $what, Watcher $watcher) {
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        if (isset($this->events[$watcherId])) {
            $this->events[$watcherId]->free();
            unset($this->events[$watcherId]);
        }
    }
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("event");
    }
    /**
     * @codeCoverageIgnore
     */
    public function __destruct()
    {
        // Unset here, otherwise $event->del() in the loop may fail with a warning, because __destruct order isn't defined.
        // Related https://github.com/amphp/amp/issues/159.
        $events = $this->events;
        $this->events = [];
        foreach ($events as $event) {
            if ($event !== null) {
                // Events may have been nulled in extension depending on destruct order.
                $event->free();
            }
        }
        // Manually free the loop handle to fully release loop resources.
        // See https://github.com/amphp/amp/issues/177.
        if ($this->handle !== null) {
            $this->handle->free();
            $this->handle = null;
        }
    }
    /**
     * {@inheritdoc}
     */
    public function run()
    {
        $active = self::$activeSignals;
        \assert($active !== null);
        foreach ($active as $event) {
            $event->del();
        }
        self::$activeSignals =& $this->signals;
        foreach ($this->signals as $event) {
            /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
            $event->add();
        }
        try {
            parent::run();
        } finally {
            foreach ($this->signals as $event) {
                $event->del();
            }
            self::$activeSignals =& $active;
            foreach ($active as $event) {
                /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
                $event->add();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function stop()
    {
        $this->handle->stop();
        parent::stop();
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle() : \EventBase
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        $this->handle->loop($blocking ? \EventBase::LOOP_ONCE : \EventBase::LOOP_ONCE | \EventBase::LOOP_NONBLOCK);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $now = $this->now();
        foreach ($watchers as $watcher) {
            if (!isset($this->events[$id = $watcher->id])) {
                switch ($watcher->type) {
                    case Watcher::READABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::READ | \Event::PERSIST, $this->ioCallback, $watcher);
                        break;
                    case Watcher::WRITABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::WRITE | \Event::PERSIST, $this->ioCallback, $watcher);
                        break;
                    case Watcher::DELAY:
                    case Watcher::REPEAT:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = new \Event($this->handle, -1, \Event::TIMEOUT, $this->timerCallback, $watcher);
                        break;
                    case Watcher::SIGNAL:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::SIGNAL | \Event::PERSIST, $this->signalCallback, $watcher);
                        break;
                    default:
                        // @codeCoverageIgnoreStart
                        throw new \Error("Unknown watcher type");
                }
            }
            switch ($watcher->type) {
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    $interval = \max(0, $watcher->expiration - $now);
                    $this->events[$id]->add($interval > 0 ? $interval / self::MILLISEC_PER_SEC : 0);
                    break;
                case Watcher::SIGNAL:
                    $this->signals[$id] = $this->events[$id];
                // no break
                default:
                    /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
                    $this->events[$id]->add();
                    break;
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        if (isset($this->events[$id = $watcher->id])) {
            $this->events[$id]->del();
            if ($watcher->type === Watcher::SIGNAL) {
                unset($this->signals[$id]);
            }
        }
    }
}
<?php

namespace PhabelVendor\Amp\Loop;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Promise;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
use function PhabelVendor\Amp\Promise\rethrow;
/**
 * Event loop driver which implements all basic operations to allow interoperability.
 *
 * Watchers (enabled or new watchers) MUST immediately be marked as enabled, but only be activated (i.e. callbacks can
 * be called) right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
 *
 * All registered callbacks MUST NOT be called from a file with strict types enabled (`declare(strict_types=1)`).
 */
abstract class Driver
{
    // Don't use 1e3 / 1e6, they result in a float instead of int
    const MILLISEC_PER_SEC = 1000;
    const MICROSEC_PER_SEC = 1000000;
    /** @var string */
    private $nextId = "a";
    /** @var Watcher[] */
    private $watchers = [];
    /** @var Watcher[] */
    private $enableQueue = [];
    /** @var Watcher[] */
    private $deferQueue = [];
    /** @var Watcher[] */
    private $nextTickQueue = [];
    /** @var callable(\Throwable):void|null */
    private $errorHandler;
    /** @var bool */
    private $running = \false;
    /** @var array */
    private $registry = [];
    /**
    * Run the event loop.
    *
    * One iteration of the loop is called one "tick". A tick covers the following steps:
    *
    * 1. Activate watchers created / enabled in the last tick / before `run()`.
    2. Execute all enabled defer watchers.
    3. Execute all due timer, pending signal and actionable stream callbacks, each only once per tick.
    *
    * The loop MUST continue to run until it is either stopped explicitly, no referenced watchers exist anymore, or an
    exception is thrown that cannot be handled. Exceptions that cannot be handled are exceptions thrown from an
    error handler or exceptions that would be passed to an error handler but none exists to handle them.
    *
    * @return void
    */
    public function run()
    {
        $this->running = \true;
        try {
            while ($this->running) {
                if ($this->isEmpty()) {
                    return;
                }
                $this->tick();
            }
        } finally {
            $this->stop();
        }
    }
    /**
     * @return bool True if no enabled and referenced watchers remain in the loop.
     */
    private function isEmpty() : bool
    {
        foreach ($this->watchers as $watcher) {
            if ($watcher->enabled && $watcher->referenced) {
                return \false;
            }
        }
        return \true;
    }
    /**
     * Executes a single tick of the event loop.
     *
     * @return void
     */
    private function tick()
    {
        if (empty($this->deferQueue)) {
            $this->deferQueue = $this->nextTickQueue;
        } else {
            $this->deferQueue = \array_merge($this->deferQueue, $this->nextTickQueue);
        }
        $this->nextTickQueue = [];
        $this->activate($this->enableQueue);
        $this->enableQueue = [];
        foreach ($this->deferQueue as $watcher) {
            if (!isset($this->deferQueue[$watcher->id])) {
                continue;
                // Watcher disabled by another defer watcher.
            }
            unset($this->watchers[$watcher->id], $this->deferQueue[$watcher->id]);
            try {
                /** @var mixed $result */
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
        /** @psalm-suppress RedundantCondition */
        $this->dispatch(empty($this->nextTickQueue) && empty($this->enableQueue) && $this->running && !$this->isEmpty());
    }
    /**
     * Activates (enables) all the given watchers.
     *
     * @param Watcher[] $watchers
     *
     * @return void
     */
    protected abstract function activate(array $watchers);
    /**
     * Dispatches any pending read/write, timer, and signal events.
     *
     * @param bool $blocking
     *
     * @return void
     */
    protected abstract function dispatch(bool $blocking);
    /**
    * Stop the event loop.
    *
    * When an event loop is stopped, it continues with its current tick and exits the loop afterwards. Multiple calls
    to stop MUST be ignored and MUST NOT raise an exception.
    *
    * @return void
    */
    public function stop()
    {
        $this->running = \false;
    }
    /**
    * Defer the execution of a callback.
    *
    * The deferred callable MUST be executed before any other type of watcher in a tick. Order of enabling MUST be
    preserved when executing the callbacks.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param callable (string $watcherId, mixed $data) $callback The callback to defer. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function defer(callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<null> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::DEFER;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->nextTickQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Delay the execution of a callback.
    *
    * The delay is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be determined by which
    timers expire first, but timers with the same expiration time MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $delay The amount of time, in milliseconds, to delay the execution for.
    * @param callable (string $watcherId, mixed $data) $callback The callback to delay. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function delay(int $delay, callable $callback, $data = null) : string
    {
        if ($delay < 0) {
            throw new \Error("Delay must be greater than or equal to zero");
        }
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::DELAY;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $delay;
        $watcher->expiration = $this->now() + $delay;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Repeatedly execute a callback.
    *
    * The interval between executions is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be
    determined by which timers expire first, but timers with the same expiration time MAY be executed in any order.
    The first execution is scheduled after the first interval period.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $interval The time interval, in milliseconds, to wait between executions.
    * @param callable (string $watcherId, mixed $data) $callback The callback to repeat.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function repeat(int $interval, callable $callback, $data = null) : string
    {
        if ($interval < 0) {
            throw new \Error("Interval must be greater than or equal to zero");
        }
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::REPEAT;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $interval;
        $watcher->expiration = $this->now() + $interval;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a stream resource becomes readable or is closed for reading.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable (string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function onReadable($stream, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<resource> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::READABLE;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $stream;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a stream resource becomes writable or is closed for writing.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable (string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function onWritable($stream, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<resource> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::WRITABLE;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $stream;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a signal is received.
    *
    * Warning: Installing the same signal on different instances of this interface is deemed undefined behavior.
    Implementations MAY try to detect this, if possible, but are not required to. This is due to technical
    limitations of the signals being registered globally per process.
    *
    * Multiple watchers on the same signal MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $signo The signal number to monitor.
    * @param callable (string $watcherId, int $signo, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the $data parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    *
    * @throws UnsupportedFeatureException If signal handling is not supported.
    */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::SIGNAL;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $signo;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Enable a watcher to be active starting in the next tick.
    *
    * Watchers MUST immediately be marked as enabled, but only be activated (i.e. callbacks can be called) right before
    the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public function enable(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            throw new InvalidWatcherError($watcherId, "Cannot enable an invalid watcher identifier: '{$watcherId}'");
        }
        $watcher = $this->watchers[$watcherId];
        if ($watcher->enabled) {
            return;
            // Watcher already enabled.
        }
        $watcher->enabled = \true;
        switch ($watcher->type) {
            case Watcher::DEFER:
                $this->nextTickQueue[$watcher->id] = $watcher;
                break;
            case Watcher::REPEAT:
            case Watcher::DELAY:
                \assert(\is_int($watcher->value));
                $watcher->expiration = $this->now() + $watcher->value;
                $this->enableQueue[$watcher->id] = $watcher;
                break;
            default:
                $this->enableQueue[$watcher->id] = $watcher;
                break;
        }
    }
    /**
    * Cancel a watcher.
    *
    * This will detach the event loop from all resources that are associated to the watcher. After this operation the
    watcher is permanently invalid. Calling this function MUST NOT fail, even if passed an invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function cancel(string $watcherId)
    {
        $this->disable($watcherId);
        unset($this->watchers[$watcherId]);
    }
    /**
    * Disable a watcher immediately.
    *
    * A watcher MUST be disabled immediately, e.g. if a defer watcher disables a later defer watcher, the second defer
    watcher isn't executed in this tick.
    *
    * Disabling a watcher MUST NOT invalidate the watcher. Calling this function MUST NOT fail, even if passed an
    invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function disable(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            return;
        }
        $watcher = $this->watchers[$watcherId];
        if (!$watcher->enabled) {
            return;
            // Watcher already disabled.
        }
        $watcher->enabled = \false;
        $id = $watcher->id;
        switch ($watcher->type) {
            case Watcher::DEFER:
                if (isset($this->nextTickQueue[$id])) {
                    // Watcher was only queued to be enabled.
                    unset($this->nextTickQueue[$id]);
                } else {
                    unset($this->deferQueue[$id]);
                }
                break;
            default:
                if (isset($this->enableQueue[$id])) {
                    // Watcher was only queued to be enabled.
                    unset($this->enableQueue[$id]);
                } else {
                    $this->deactivate($watcher);
                }
                break;
        }
    }
    /**
     * Deactivates (disables) the given watcher.
     *
     * @param Watcher $watcher
     *
     * @return void
     */
    protected abstract function deactivate(Watcher $watcher);
    /**
    * Reference a watcher.
    *
    * This will keep the event loop alive whilst the watcher is still being monitored. Watchers have this state by
    default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public function reference(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            throw new InvalidWatcherError($watcherId, "Cannot reference an invalid watcher identifier: '{$watcherId}'");
        }
        $this->watchers[$watcherId]->referenced = \true;
    }
    /**
    * Unreference a watcher.
    *
    * The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers
    are all referenced by default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function unreference(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            return;
        }
        $this->watchers[$watcherId]->referenced = \false;
    }
    /**
    * Stores information in the loop bound registry.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    * @param mixed $value The value to be stored.
    *
    * @return void
    */
    public final function setState(string $key, $value)
    {
        if ($value === null) {
            unset($this->registry[$key]);
        } else {
            $this->registry[$key] = $value;
        }
    }
    /**
    * Gets information stored bound to the loop.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    *
    * @return mixed The previously stored value or `null` if it doesn't exist.
    */
    public final function getState(string $key)
    {
        return isset($this->registry[$key]) ? $this->registry[$key] : null;
    }
    /**
    * Set a callback to be executed when an error occurs.
    *
    * The callback receives the error as the first and only parameter. The return value of the callback gets ignored.
    If it can't handle the error, it MUST throw the error. Errors thrown by the callback or during its invocation
    MUST be thrown into the `run` loop and stop the driver.
    *
    * Subsequent calls to this method will overwrite the previous handler.
    *
    * @param (callable(\Throwable $error): void | null) $callback The callback to execute. `null` will clear the
    current handler.
    *
    * @return (callable(\Throwable $error): void | null) The previous handler, `null` if there was none.
    */
    public function setErrorHandler(callable $callback = null)
    {
        $previous = $this->errorHandler;
        $this->errorHandler = $callback;
        return $previous;
    }
    /**
     * Invokes the error handler with the given exception.
     *
     * @param \Throwable $exception The exception thrown from a watcher callback.
     *
     * @return void
     * @throws \Throwable If no error handler has been set.
     */
    protected function error(\Throwable $exception)
    {
        if ($this->errorHandler === null) {
            throw $exception;
        }
        ($this->errorHandler)($exception);
    }
    /**
    * Returns the current loop time in millisecond increments. Note this value does not necessarily correlate to
    wall-clock time, rather the value returned is meant to be used in relative comparisons to prior values returned
    by this method (intervals, expiration calculations, etc.) and is only updated once per loop tick.
    *
    * Extending classes should override this function to return a value cached once per loop tick.
    *
    * @return int
    */
    public function now() : int
    {
        return (int) (\microtime(\true) * self::MILLISEC_PER_SEC);
    }
    /**
    * Get the underlying loop handle.
    *
    * Example: the `uv_loop` resource for `libuv` or the `EvLoop` object for `libev` or `null` for a native driver.
    *
    * Note: This function is *not* exposed in the `Loop` class. Users shall access it directly on the respective loop
    instance.
    *
    * @return (null | object | resource) The loop handle the event loop operates on. `null` if there is none.
    */
    public abstract function getHandle();
    /**
     * Returns the same array of data as getInfo().
     *
     * @return array
     */
    public function __debugInfo()
    {
        // @codeCoverageIgnoreStart
        return $this->getInfo();
        // @codeCoverageIgnoreEnd
    }
    /**
    * Retrieve an associative array of information about the event loop driver.
    *
    * The returned array MUST contain the following data describing the driver's currently registered watchers:
    *
    * [
    "defer"            => ["enabled" => int, "disabled" => int],
    "delay"            => ["enabled" => int, "disabled" => int],
    "repeat"           => ["enabled" => int, "disabled" => int],
    "on_readable"      => ["enabled" => int, "disabled" => int],
    "on_writable"      => ["enabled" => int, "disabled" => int],
    "on_signal"        => ["enabled" => int, "disabled" => int],
    "enabled_watchers" => ["referenced" => int, "unreferenced" => int],
    "running"          => bool
    ];
    *
    * Implementations MAY optionally add more information in the array but at minimum the above `key => value` format
    MUST always be provided.
    *
    * @return array Statistics about the loop in the described format.
    */
    public function getInfo() : array
    {
        $watchers = ["referenced" => 0, "unreferenced" => 0];
        $defer = $delay = $repeat = $onReadable = $onWritable = $onSignal = ["enabled" => 0, "disabled" => 0];
        foreach ($this->watchers as $watcher) {
            switch ($watcher->type) {
                case Watcher::READABLE:
                    $array =& $onReadable;
                    break;
                case Watcher::WRITABLE:
                    $array =& $onWritable;
                    break;
                case Watcher::SIGNAL:
                    $array =& $onSignal;
                    break;
                case Watcher::DEFER:
                    $array =& $defer;
                    break;
                case Watcher::DELAY:
                    $array =& $delay;
                    break;
                case Watcher::REPEAT:
                    $array =& $repeat;
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
            if ($watcher->enabled) {
                ++$array["enabled"];
                if ($watcher->referenced) {
                    ++$watchers["referenced"];
                } else {
                    ++$watchers["unreferenced"];
                }
            } else {
                ++$array["disabled"];
            }
        }
        return ["enabled_watchers" => $watchers, "defer" => $defer, "delay" => $delay, "repeat" => $repeat, "on_readable" => $onReadable, "on_writable" => $onWritable, "on_signal" => $onSignal, "running" => (bool) $this->running];
    }
}
<?php

namespace PhabelVendor\Amp\Loop;

// @codeCoverageIgnoreStart
class DriverFactory
{
    /**
     * Creates a new loop instance and chooses the best available driver.
     *
     * @return Driver
     *
     * @throws \Error If an invalid class has been specified via AMP_LOOP_DRIVER
     */
    public function create() : Driver
    {
        $driver = (function () {
            if ($driver = $this->createDriverFromEnv()) {
                return $driver;
            }
            if (UvDriver::isSupported()) {
                return new UvDriver();
            }
            if (EvDriver::isSupported()) {
                return new EvDriver();
            }
            if (EventDriver::isSupported()) {
                return new EventDriver();
            }
            return new NativeDriver();
        })();
        if (\getenv("AMP_DEBUG_TRACE_WATCHERS")) {
            return new TracingDriver($driver);
        }
        return $driver;
    }
    /**
     * @return (Driver | null)
     */
    private function createDriverFromEnv()
    {
        $driver = \getenv("AMP_LOOP_DRIVER");
        if (!$driver) {
            return null;
        }
        if (!\class_exists($driver)) {
            throw new \Error(\sprintf("Driver '%s' does not exist.", $driver));
        }
        if (!\is_subclass_of($driver, Driver::class)) {
            throw new \Error(\sprintf("Driver '%s' is not a subclass of '%s'.", $driver, Driver::class));
        }
        return new $driver();
    }
}
// @codeCoverageIgnoreEnd
<?php

namespace PhabelVendor\Amp\Loop;

use PhabelVendor\Amp\CallableMaker;
use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Promise;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
use function PhabelVendor\Amp\Internal\getCurrentTime;
use function PhabelVendor\Amp\Promise\rethrow;
class NativeDriver extends Driver
{
    use CallableMaker;
    /** @var resource[] */
    private $readStreams = [];
    /** @var Watcher[][] */
    private $readWatchers = [];
    /** @var resource[] */
    private $writeStreams = [];
    /** @var Watcher[][] */
    private $writeWatchers = [];
    /** @var Internal\TimerQueue */
    private $timerQueue;
    /** @var Watcher[][] */
    private $signalWatchers = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /** @var bool */
    private $signalHandling;
    /** @var callable */
    private $streamSelectErrorHandler;
    /** @var bool */
    private $streamSelectIgnoreResult = \false;
    /**
     *
     */
    public function __construct()
    {
        $this->timerQueue = new Internal\TimerQueue();
        $this->signalHandling = \extension_loaded("pcntl");
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        $this->streamSelectErrorHandler = function ($errno, $message) {
            // Casing changed in PHP 8 from 'unable' to 'Unable'
            if (\stripos($message, "stream_select(): unable to select [4]: ") === 0) {
                // EINTR
                $this->streamSelectIgnoreResult = \true;
                return;
            }
            if (\strpos($message, 'FD_SETSIZE') !== \false) {
                $message = \str_replace(["\r\n", "\n", "\r"], " ", $message);
                $pattern = '(stream_select\\(\\): You MUST recompile PHP with a larger value of FD_SETSIZE. It is set to (\\d+), but you have descriptors numbered at least as high as (\\d+)\\.)';
                if (\preg_match($pattern, $message, $match)) {
                    $helpLink = 'https://amphp.org/amp/event-loop/#implementations';
                    $message = 'You have reached the limits of stream_select(). It has a FD_SETSIZE of ' . $match[1] . ', but you have file descriptors numbered at least as high as ' . $match[2] . '. ' . "You can install one of the extensions listed on {$helpLink} to support a higher number of " . 'concurrent file descriptors. If a large number of open file descriptors is unexpected, you might be leaking file descriptors that aren\'t closed correctly.';
                }
            }
            throw new \Exception($message, $errno);
        };
    }
    /**
     * {@inheritdoc}
     *
     * @throws \Amp\Loop\UnsupportedFeatureException If the pcntl extension is not available.
     */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        if (!$this->signalHandling) {
            throw new UnsupportedFeatureException("Signal handling requires the pcntl extension");
        }
        return parent::onSignal($signo, $callback, $data);
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle()
    {
        return null;
    }
    /**
     * @param bool $blocking
     *
     * @return void
     *
     * @throws \Throwable
     */
    protected function dispatch(bool $blocking)
    {
        $this->selectStreams($this->readStreams, $this->writeStreams, $blocking ? $this->getTimeout() : 0);
        $now = $this->now();
        while ($watcher = $this->timerQueue->extract($now)) {
            if ($watcher->type & Watcher::REPEAT) {
                $watcher->enabled = \false;
                // Trick base class into adding to enable queue when calling enable()
                $this->enable($watcher->id);
            } else {
                $this->cancel($watcher->id);
            }
            try {
                // Execute the timer.
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
        if ($this->signalHandling) {
            \pcntl_signal_dispatch();
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        foreach ($watchers as $watcher) {
            switch ($watcher->type) {
                case Watcher::READABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    $this->readWatchers[$streamId][$watcher->id] = $watcher;
                    $this->readStreams[$streamId] = $watcher->value;
                    break;
                case Watcher::WRITABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    $this->writeWatchers[$streamId][$watcher->id] = $watcher;
                    $this->writeStreams[$streamId] = $watcher->value;
                    break;
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    $this->timerQueue->insert($watcher);
                    break;
                case Watcher::SIGNAL:
                    \assert(\is_int($watcher->value));
                    if (!isset($this->signalWatchers[$watcher->value])) {
                        if (!@\pcntl_signal($watcher->value, $this->callableFromInstanceMethod('handleSignal'))) {
                            $message = "Failed to register signal handler";
                            if ($error = \error_get_last()) {
                                $message .= \sprintf("; Errno: %d; %s", $error["type"], $error["message"]);
                            }
                            throw new \Error($message);
                        }
                    }
                    $this->signalWatchers[$watcher->value][$watcher->id] = $watcher;
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        switch ($watcher->type) {
            case Watcher::READABLE:
                $streamId = (int) $watcher->value;
                unset($this->readWatchers[$streamId][$watcher->id]);
                if (empty($this->readWatchers[$streamId])) {
                    unset($this->readWatchers[$streamId], $this->readStreams[$streamId]);
                }
                break;
            case Watcher::WRITABLE:
                $streamId = (int) $watcher->value;
                unset($this->writeWatchers[$streamId][$watcher->id]);
                if (empty($this->writeWatchers[$streamId])) {
                    unset($this->writeWatchers[$streamId], $this->writeStreams[$streamId]);
                }
                break;
            case Watcher::DELAY:
            case Watcher::REPEAT:
                $this->timerQueue->remove($watcher);
                break;
            case Watcher::SIGNAL:
                \assert(\is_int($watcher->value));
                if (isset($this->signalWatchers[$watcher->value])) {
                    unset($this->signalWatchers[$watcher->value][$watcher->id]);
                    if (empty($this->signalWatchers[$watcher->value])) {
                        unset($this->signalWatchers[$watcher->value]);
                        @\pcntl_signal($watcher->value, \SIG_DFL);
                    }
                }
                break;
            default:
                // @codeCoverageIgnoreStart
                throw new \Error("Unknown watcher type");
        }
    }
    /**
     * @param resource[] $read
     * @param resource[] $write
     * @param int $timeout
     *
     * @return void
     */
    private function selectStreams(array $read, array $write, int $timeout)
    {
        $timeout /= self::MILLISEC_PER_SEC;
        if (!empty($read) || !empty($write)) {
            // Use stream_select() if there are any streams in the loop.
            if ($timeout >= 0) {
                $seconds = (int) $timeout;
                $microseconds = (int) (($timeout - $seconds) * self::MICROSEC_PER_SEC);
            } else {
                $seconds = null;
                $microseconds = null;
            }
            // Failed connection attempts are indicated via except on Windows
            // @link https://github.com/reactphp/event-loop/blob/8bd064ce23c26c4decf186c2a5a818c9a8209eb0/src/StreamSelectLoop.php#L279-L287
            // @link https://docs.microsoft.com/de-de/windows/win32/api/winsock2/nf-winsock2-select
            $except = null;
            if (\DIRECTORY_SEPARATOR === '\\') {
                $except = $write;
            }
            \set_error_handler($this->streamSelectErrorHandler);
            try {
                $result = \stream_select($read, $write, $except, $seconds, $microseconds);
            } finally {
                \restore_error_handler();
            }
            if ($this->streamSelectIgnoreResult || $result === 0) {
                $this->streamSelectIgnoreResult = \false;
                return;
            }
            if (!$result) {
                $this->error(new \Exception('Unknown error during stream_select'));
                return;
            }
            foreach ($read as $stream) {
                $streamId = (int) $stream;
                if (!isset($this->readWatchers[$streamId])) {
                    continue;
                    // All read watchers disabled.
                }
                foreach ($this->readWatchers[$streamId] as $watcher) {
                    if (!isset($this->readWatchers[$streamId][$watcher->id])) {
                        continue;
                        // Watcher disabled by another IO watcher.
                    }
                    try {
                        $result = ($watcher->callback)($watcher->id, $stream, $watcher->data);
                        if ($result === null) {
                            continue;
                        }
                        if ($result instanceof \Generator) {
                            $result = new Coroutine($result);
                        }
                        if ($result instanceof Promise || $result instanceof ReactPromise) {
                            rethrow($result);
                        }
                    } catch (\Throwable $exception) {
                        $this->error($exception);
                    }
                }
            }
            \assert(\is_array($write));
            // See https://github.com/vimeo/psalm/issues/3036
            if ($except) {
                foreach ($except as $key => $socket) {
                    $write[$key] = $socket;
                }
            }
            foreach ($write as $stream) {
                $streamId = (int) $stream;
                if (!isset($this->writeWatchers[$streamId])) {
                    continue;
                    // All write watchers disabled.
                }
                foreach ($this->writeWatchers[$streamId] as $watcher) {
                    if (!isset($this->writeWatchers[$streamId][$watcher->id])) {
                        continue;
                        // Watcher disabled by another IO watcher.
                    }
                    try {
                        $result = ($watcher->callback)($watcher->id, $stream, $watcher->data);
                        if ($result === null) {
                            continue;
                        }
                        if ($result instanceof \Generator) {
                            $result = new Coroutine($result);
                        }
                        if ($result instanceof Promise || $result instanceof ReactPromise) {
                            rethrow($result);
                        }
                    } catch (\Throwable $exception) {
                        $this->error($exception);
                    }
                }
            }
            return;
        }
        if ($timeout < 0) {
            // Only signal watchers are enabled, so sleep indefinitely.
            \usleep(\PHP_INT_MAX);
            return;
        }
        if ($timeout > 0) {
            // Sleep until next timer expires.
            \usleep((int) ($timeout * self::MICROSEC_PER_SEC));
        }
    }
    /**
     * @return int Milliseconds until next timer expires or -1 if there are no pending times.
     */
    private function getTimeout() : int
    {
        $expiration = $this->timerQueue->peek();
        if ($expiration === null) {
            return -1;
        }
        $expiration -= getCurrentTime() - $this->nowOffset;
        return $expiration > 0 ? $expiration : 0;
    }
    /**
     * @param int $signo
     *
     * @return void
     */
    private function handleSignal(int $signo)
    {
        foreach ($this->signalWatchers[$signo] as $watcher) {
            if (!isset($this->signalWatchers[$signo][$watcher->id])) {
                continue;
            }
            try {
                $result = ($watcher->callback)($watcher->id, $signo, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
    }
}
<?php

namespace PhabelVendor\Amp\Loop\Internal;

use PhabelVendor\Amp\Loop\Watcher;
/**
 * Uses a binary tree stored in an array to implement a heap.
 */
final class TimerQueue
{
    /** @var Watcher[] */
    private $data = [];
    /** @var int[] */
    private $pointers = [];
    /**
     * @param int $node Rebuild the data array from the given node upward.
     *
     * @return void
     */
    private function heapifyUp(int $node)
    {
        $entry = $this->data[$node];
        while ($node !== 0 && $entry->expiration < $this->data[$parent = $node - 1 >> 1]->expiration) {
            $this->swap($node, $parent);
            $node = $parent;
        }
    }
    /**
     * @param int $node Rebuild the data array from the given node downward.
     *
     * @return void
     */
    private function heapifyDown(int $node)
    {
        $length = \count($this->data);
        while (($child = ($node << 1) + 1) < $length) {
            if ($this->data[$child]->expiration < $this->data[$node]->expiration && ($child + 1 >= $length || $this->data[$child]->expiration < $this->data[$child + 1]->expiration)) {
                // Left child is less than parent and right child.
                $swap = $child;
            } elseif ($child + 1 < $length && $this->data[$child + 1]->expiration < $this->data[$node]->expiration) {
                // Right child is less than parent and left child.
                $swap = $child + 1;
            } else {
                // Left and right child are greater than parent.
                break;
            }
            $this->swap($node, $swap);
            $node = $swap;
        }
    }
    /**
     *
     */
    private function swap(int $left, int $right)
    {
        $temp = $this->data[$left];
        $this->data[$left] = $this->data[$right];
        $this->pointers[$this->data[$right]->id] = $left;
        $this->data[$right] = $temp;
        $this->pointers[$temp->id] = $right;
    }
    /**
     * Inserts the watcher into the queue. Time complexity: O(log(n)).
     *
     * @param Watcher $watcher
     *
     * @psalm-param Watcher<int> $watcher
     *
     * @return void
     */
    public function insert(Watcher $watcher)
    {
        \assert($watcher->expiration !== null);
        \assert(!isset($this->pointers[$watcher->id]));
        $node = \count($this->data);
        $this->data[$node] = $watcher;
        $this->pointers[$watcher->id] = $node;
        $this->heapifyUp($node);
    }
    /**
     * Removes the given watcher from the queue. Time complexity: O(log(n)).
     *
     * @param Watcher $watcher
     *
     * @psalm-param Watcher<int> $watcher
     *
     * @return void
     */
    public function remove(Watcher $watcher)
    {
        $id = $watcher->id;
        if (!isset($this->pointers[$id])) {
            return;
        }
        $this->removeAndRebuild($this->pointers[$id]);
    }
    /**
    * Deletes and returns the Watcher on top of the heap if it has expired, otherwise null is returned.
    Time complexity: O(log(n)).
    *
    * @param int $now Current loop time.
    *
    * @return (Watcher | null) Expired watcher at the top of the heap or null if the watcher has not expired.
    *
    * @psalm-return (Watcher<int> | null)
    */
    public function extract(int $now)
    {
        if (empty($this->data)) {
            return null;
        }
        $watcher = $this->data[0];
        if ($watcher->expiration > $now) {
            return null;
        }
        $this->removeAndRebuild(0);
        return $watcher;
    }
    /**
     * Returns the expiration time value at the top of the heap. Time complexity: O(1).
     *
     * @return (int | null) Expiration time of the watcher at the top of the heap or null if the heap is empty.
     */
    public function peek()
    {
        return isset($this->data[0]) ? $this->data[0]->expiration : null;
    }
    /**
     * @param int $node Remove the given node and then rebuild the data array.
     *
     * @return void
     */
    private function removeAndRebuild(int $node)
    {
        $length = \count($this->data) - 1;
        $id = $this->data[$node]->id;
        $left = $this->data[$node] = $this->data[$length];
        $this->pointers[$left->id] = $node;
        unset($this->data[$length], $this->pointers[$id]);
        if ($node < $length) {
            // don't need to do anything if we removed the last element
            $parent = $node - 1 >> 1;
            if ($parent >= 0 && $this->data[$node]->expiration < $this->data[$parent]->expiration) {
                $this->heapifyUp($node);
            } else {
                $this->heapifyDown($node);
            }
        }
    }
}
<?php

namespace PhabelVendor\Amp\Loop;

/**
 * MUST be thrown if a feature is not supported by the system.
 *
 * This might happen if ext-pcntl is missing and the loop driver doesn't support another way to dispatch signals.
 */
class UnsupportedFeatureException extends \Exception
{
}
<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace PhabelVendor\Amp\Loop;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Promise;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
use function PhabelVendor\Amp\Internal\getCurrentTime;
use function PhabelVendor\Amp\Promise\rethrow;
class EvDriver extends Driver
{
    /** @var \EvSignal[]|null */
    private static $activeSignals;
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("ev");
    }
    /** @var \EvLoop */
    private $handle;
    /** @var \EvWatcher[] */
    private $events = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /** @var \EvSignal[] */
    private $signals = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /**
     *
     */
    public function __construct()
    {
        $this->handle = new \EvLoop();
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        if (self::$activeSignals === null) {
            self::$activeSignals =& $this->signals;
        }
        /**
         * @param \EvIO $event
         *
         * @return void
         */
        $this->ioCallback = function (\PhabelVendor\EvIO $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param \EvTimer $event
         *
         * @return void
         */
        $this->timerCallback = function (\EvTimer $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            if ($watcher->type & Watcher::DELAY) {
                $this->cancel($watcher->id);
            } elseif ($watcher->value === 0) {
                // Disable and re-enable so it's not executed repeatedly in the same tick
                // See https://github.com/amphp/amp/issues/131
                $this->disable($watcher->id);
                $this->enable($watcher->id);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param \EvSignal $event
         *
         * @return void
         */
        $this->signalCallback = function (\EvSignal $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        unset($this->events[$watcherId]);
    }
    /**
     *
     */
    public function __destruct()
    {
        foreach ($this->events as $event) {
            /** @psalm-suppress all */
            if ($event !== null) {
                // Events may have been nulled in extension depending on destruct order.
                $event->stop();
            }
        }
        // We need to clear all references to events manually, see
        // https://bitbucket.org/osmanov/pecl-ev/issues/31/segfault-in-ev_timer_stop
        $this->events = [];
    }
    /**
     * {@inheritdoc}
     */
    public function run()
    {
        $active = self::$activeSignals;
        \assert($active !== null);
        foreach ($active as $event) {
            $event->stop();
        }
        self::$activeSignals =& $this->signals;
        foreach ($this->signals as $event) {
            $event->start();
        }
        try {
            parent::run();
        } finally {
            foreach ($this->signals as $event) {
                $event->stop();
            }
            self::$activeSignals =& $active;
            foreach ($active as $event) {
                $event->start();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function stop()
    {
        $this->handle->stop();
        parent::stop();
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle() : \EvLoop
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        $this->handle->run($blocking ? \Ev::RUN_ONCE : \Ev::RUN_ONCE | \Ev::RUN_NOWAIT);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $this->handle->nowUpdate();
        $now = $this->now();
        foreach ($watchers as $watcher) {
            if (!isset($this->events[$id = $watcher->id])) {
                switch ($watcher->type) {
                    case Watcher::READABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = $this->handle->io($watcher->value, \Ev::READ, $this->ioCallback, $watcher);
                        break;
                    case Watcher::WRITABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = $this->handle->io($watcher->value, \Ev::WRITE, $this->ioCallback, $watcher);
                        break;
                    case Watcher::DELAY:
                    case Watcher::REPEAT:
                        \assert(\is_int($watcher->value));
                        $interval = $watcher->value / self::MILLISEC_PER_SEC;
                        $this->events[$id] = $this->handle->timer(\max(0, ($watcher->expiration - $now) / self::MILLISEC_PER_SEC), $watcher->type & Watcher::REPEAT ? $interval : 0, $this->timerCallback, $watcher);
                        break;
                    case Watcher::SIGNAL:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = $this->handle->signal($watcher->value, $this->signalCallback, $watcher);
                        break;
                    default:
                        // @codeCoverageIgnoreStart
                        throw new \Error("Unknown watcher type");
                }
            } else {
                $this->events[$id]->start();
            }
            if ($watcher->type === Watcher::SIGNAL) {
                /** @psalm-suppress PropertyTypeCoercion */
                $this->signals[$id] = $this->events[$id];
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        if (isset($this->events[$id = $watcher->id])) {
            $this->events[$id]->stop();
            if ($watcher->type === Watcher::SIGNAL) {
                unset($this->signals[$id]);
            }
        }
    }
}
<?php

namespace PhabelVendor\Amp\Loop;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Promise;
use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
use function PhabelVendor\Amp\Promise\rethrow;
class UvDriver extends Driver
{
    /** @var resource A uv_loop resource created with uv_loop_new() */
    private $handle;
    /** @var resource[] */
    private $events = [];
    /** @var Watcher[][] */
    private $watchers = [];
    /** @var resource[] */
    private $streams = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /**
     *
     */
    public function __construct()
    {
        $this->handle = \uv_loop_new();
        /**
         * @param $event
         * @param $status
         * @param $events
         * @param $resource
         *
         * @return void
         */
        $this->ioCallback = function ($event, $status, $events, $resource) {
            $watchers = $this->watchers[(int) $event];
            switch ($status) {
                case 0:
                    // OK
                    break;
                default:
                    // Invoke the callback on errors, as this matches behavior with other loop back-ends.
                    // Re-enable watcher as libuv disables the watcher on non-zero status.
                    $flags = 0;
                    foreach ($watchers as $watcher) {
                        $flags |= $watcher->enabled ? $watcher->type : 0;
                    }
                    \uv_poll_start($event, $flags, $this->ioCallback);
                    break;
            }
            foreach ($watchers as $watcher) {
                // $events is OR'ed with 4 to trigger watcher if no events are indicated (0) or on UV_DISCONNECT (4).
                // http://docs.libuv.org/en/v1.x/poll.html
                if (!($watcher->enabled && ($watcher->type & $events || ($events | 4) === 4))) {
                    continue;
                }
                try {
                    $result = ($watcher->callback)($watcher->id, $resource, $watcher->data);
                    if ($result === null) {
                        continue;
                    }
                    if ($result instanceof \Generator) {
                        $result = new Coroutine($result);
                    }
                    if ($result instanceof Promise || $result instanceof ReactPromise) {
                        rethrow($result);
                    }
                } catch (\Throwable $exception) {
                    $this->error($exception);
                }
            }
        };
        /**
         * @param $event
         *
         * @return void
         */
        $this->timerCallback = function ($event) {
            $watcher = $this->watchers[(int) $event][0];
            if ($watcher->type & Watcher::DELAY) {
                unset($this->events[$watcher->id], $this->watchers[(int) $event]);
                // Avoid call to uv_is_active().
                $this->cancel($watcher->id);
                // Remove reference to watcher in parent.
            } elseif ($watcher->value === 0) {
                // Disable and re-enable so it's not executed repeatedly in the same tick
                // See https://github.com/amphp/amp/issues/131
                $this->disable($watcher->id);
                $this->enable($watcher->id);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param $event
         * @param $signo
         *
         * @return void
         */
        $this->signalCallback = function ($event, $signo) {
            $watcher = $this->watchers[(int) $event][0];
            try {
                $result = ($watcher->callback)($watcher->id, $signo, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        if (!isset($this->events[$watcherId])) {
            return;
        }
        $event = $this->events[$watcherId];
        $eventId = (int) $event;
        if (isset($this->watchers[$eventId][0])) {
            // All except IO watchers.
            unset($this->watchers[$eventId]);
        } elseif (isset($this->watchers[$eventId][$watcherId])) {
            $watcher = $this->watchers[$eventId][$watcherId];
            unset($this->watchers[$eventId][$watcherId]);
            if (empty($this->watchers[$eventId])) {
                unset($this->watchers[$eventId], $this->streams[(int) $watcher->value]);
            }
        }
        unset($this->events[$watcherId]);
    }
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("uv");
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        \uv_update_time($this->handle);
        /** @psalm-suppress TooManyArguments */
        return \uv_now($this->handle);
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle()
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        /** @psalm-suppress TooManyArguments */
        \uv_run($this->handle, $blocking ? \UV::RUN_ONCE : \UV::RUN_NOWAIT);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $now = $this->now();
        foreach ($watchers as $watcher) {
            $id = $watcher->id;
            switch ($watcher->type) {
                case Watcher::READABLE:
                case Watcher::WRITABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    if (isset($this->streams[$streamId])) {
                        $event = $this->streams[$streamId];
                    } elseif (isset($this->events[$id])) {
                        $event = $this->streams[$streamId] = $this->events[$id];
                    } else {
                        /** @psalm-suppress UndefinedFunction */
                        $event = $this->streams[$streamId] = \PhabelVendor\uv_poll_init_socket($this->handle, $watcher->value);
                    }
                    $eventId = (int) $event;
                    $this->events[$id] = $event;
                    $this->watchers[$eventId][$id] = $watcher;
                    $flags = 0;
                    foreach ($this->watchers[$eventId] as $w) {
                        $flags |= $w->enabled ? $w->type : 0;
                    }
                    \uv_poll_start($event, $flags, $this->ioCallback);
                    break;
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    if (isset($this->events[$id])) {
                        $event = $this->events[$id];
                    } else {
                        $event = $this->events[$id] = \uv_timer_init($this->handle);
                    }
                    $this->watchers[(int) $event] = [$watcher];
                    \uv_timer_start($event, \max(0, $watcher->expiration - $now), $watcher->type & Watcher::REPEAT ? $watcher->value : 0, $this->timerCallback);
                    break;
                case Watcher::SIGNAL:
                    \assert(\is_int($watcher->value));
                    if (isset($this->events[$id])) {
                        $event = $this->events[$id];
                    } else {
                        /** @psalm-suppress UndefinedFunction */
                        $event = $this->events[$id] = \PhabelVendor\uv_signal_init($this->handle);
                    }
                    $this->watchers[(int) $event] = [$watcher];
                    /** @psalm-suppress UndefinedFunction */
                    \PhabelVendor\uv_signal_start($event, $this->signalCallback, $watcher->value);
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        $id = $watcher->id;
        if (!isset($this->events[$id])) {
            return;
        }
        $event = $this->events[$id];
        if (!\uv_is_active($event)) {
            return;
        }
        switch ($watcher->type) {
            case Watcher::READABLE:
            case Watcher::WRITABLE:
                $flags = 0;
                foreach ($this->watchers[(int) $event] as $w) {
                    $flags |= $w->enabled ? $w->type : 0;
                }
                if ($flags) {
                    \uv_poll_start($event, $flags, $this->ioCallback);
                } else {
                    \uv_poll_stop($event);
                }
                break;
            case Watcher::DELAY:
            case Watcher::REPEAT:
                \uv_timer_stop($event);
                break;
            case Watcher::SIGNAL:
                \uv_signal_stop($event);
                break;
            default:
                // @codeCoverageIgnoreStart
                throw new \Error("Unknown watcher type");
        }
    }
}
<?php

namespace PhabelVendor\Amp\Loop;

/**
 * MUST be thrown if any operation (except disable() and cancel()) is attempted with an invalid watcher identifier.
 *
 * An invalid watcher identifier is any identifier that is not yet emitted by the driver or cancelled by the user.
 */
class InvalidWatcherError extends \Error
{
    /** @var string */
    private $watcherId;
    /**
     * @param string $watcherId The watcher identifier.
     * @param string $message The exception message.
     */
    public function __construct(string $watcherId, string $message)
    {
        $this->watcherId = $watcherId;
        parent::__construct($message);
    }
    /**
     * @return string The watcher identifier.
     */
    public function getWatcherId()
    {
        return $this->watcherId;
    }
}
<?php

namespace PhabelVendor\Amp\Loop;

use function PhabelVendor\Amp\Internal\formatStacktrace;
final class TracingDriver extends Driver
{
    /** @var Driver */
    private $driver;
    /** @var true[] */
    private $enabledWatchers = [];
    /** @var true[] */
    private $unreferencedWatchers = [];
    /** @var string[] */
    private $creationTraces = [];
    /** @var string[] */
    private $cancelTraces = [];
    /**
     *
     */
    public function __construct(Driver $driver)
    {
        $this->driver = $driver;
    }
    /**
     *
     */
    public function run()
    {
        $this->driver->run();
    }
    /**
     *
     */
    public function stop()
    {
        $this->driver->stop();
    }
    /**
     *
     */
    public function defer(callable $callback, $data = null) : string
    {
        $id = $this->driver->defer(function (...$args) use($callback) {
            $this->cancel($args[0]);
            return $callback(...$args);
        }, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = \true;
        return $id;
    }
    /**
     *
     */
    public function delay(int $delay, callable $callback, $data = null) : string
    {
        $id = $this->driver->delay($delay, function (...$args) use($callback) {
            $this->cancel($args[0]);
            return $callback(...$args);
        }, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = \true;
        return $id;
    }
    /**
     *
     */
    public function repeat(int $interval, callable $callback, $data = null) : string
    {
        $id = $this->driver->repeat($interval, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = \true;
        return $id;
    }
    /**
     *
     */
    public function onReadable($stream, callable $callback, $data = null) : string
    {
        $id = $this->driver->onReadable($stream, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = \true;
        return $id;
    }
    /**
     *
     */
    public function onWritable($stream, callable $callback, $data = null) : string
    {
        $id = $this->driver->onWritable($stream, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = \true;
        return $id;
    }
    /**
     *
     */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        $id = $this->driver->onSignal($signo, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = \true;
        return $id;
    }
    /**
     *
     */
    public function enable(string $watcherId)
    {
        try {
            $this->driver->enable($watcherId);
            $this->enabledWatchers[$watcherId] = \true;
        } catch (InvalidWatcherError $e) {
            throw new InvalidWatcherError($watcherId, $e->getMessage() . "\r\n\r\n" . $this->getTraces($watcherId));
        }
    }
    /**
     *
     */
    public function cancel(string $watcherId)
    {
        $this->driver->cancel($watcherId);
        if (!isset($this->cancelTraces[$watcherId])) {
            $this->cancelTraces[$watcherId] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        }
        unset($this->enabledWatchers[$watcherId], $this->unreferencedWatchers[$watcherId]);
    }
    /**
     *
     */
    public function disable(string $watcherId)
    {
        $this->driver->disable($watcherId);
        unset($this->enabledWatchers[$watcherId]);
    }
    /**
     *
     */
    public function reference(string $watcherId)
    {
        try {
            $this->driver->reference($watcherId);
            unset($this->unreferencedWatchers[$watcherId]);
        } catch (InvalidWatcherError $e) {
            throw new InvalidWatcherError($watcherId, $e->getMessage() . "\r\n\r\n" . $this->getTraces($watcherId));
        }
    }
    /**
     *
     */
    public function unreference(string $watcherId)
    {
        $this->driver->unreference($watcherId);
        $this->unreferencedWatchers[$watcherId] = \true;
    }
    /**
     *
     */
    public function setErrorHandler(callable $callback = null)
    {
        return $this->driver->setErrorHandler($callback);
    }
    /**
     * @inheritdoc
     */
    public function getHandle()
    {
        $this->driver->getHandle();
    }
    /**
     *
     */
    public function dump() : string
    {
        $dump = "Enabled, referenced watchers keeping the loop running: ";
        foreach ($this->enabledWatchers as $watcher => $_) {
            if (isset($this->unreferencedWatchers[$watcher])) {
                continue;
            }
            $dump .= "Watcher ID: " . $watcher . "\r\n";
            $dump .= $this->getCreationTrace($watcher);
            $dump .= "\r\n\r\n";
        }
        return \rtrim($dump);
    }
    /**
     *
     */
    public function getInfo() : array
    {
        return $this->driver->getInfo();
    }
    /**
     *
     */
    public function __debugInfo()
    {
        return $this->driver->__debugInfo();
    }
    /**
     *
     */
    public function now() : int
    {
        return $this->driver->now();
    }
    /**
     *
     */
    protected function error(\Throwable $exception)
    {
        $this->driver->error($exception);
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        // nothing to do in a decorator
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        // nothing to do in a decorator
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        // nothing to do in a decorator
    }
    /**
     *
     */
    private function getTraces(string $watcherId) : string
    {
        return "Creation Trace:\r\n" . $this->getCreationTrace($watcherId) . '

Cancellation Trace:
' . $this->getCancelTrace($watcherId);
    }
    /**
     *
     */
    private function getCreationTrace(string $watcher) : string
    {
        if (!isset($this->creationTraces[$watcher])) {
            return 'No creation trace, yet.';
        }
        return $this->creationTraces[$watcher];
    }
    /**
     *
     */
    private function getCancelTrace(string $watcher) : string
    {
        if (!isset($this->cancelTraces[$watcher])) {
            return 'No cancellation trace, yet.';
        }
        return $this->cancelTraces[$watcher];
    }
}
<?php

namespace PhabelVendor\Amp;

use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a promise from a generator function yielding promises.
 *
 * When a promise is yielded, execution of the generator is interrupted until the promise is resolved. A success
 * value is sent into the generator, while a failure reason is thrown into the generator. Using a coroutine,
 * asynchronous code can be written without callbacks and be structured like synchronous code.
 *
 * @template-covariant TReturn
 * @template-implements Promise<TReturn>
 */
final class Coroutine implements Promise
{
    use Internal\Placeholder;
    /**
    * Attempts to transform the non-promise yielded from the generator into a promise, otherwise returns an instance
    `Amp\Failure` failed with an instance of `Amp\InvalidYieldError`.
    *
    * @param mixed $yielded Non-promise yielded from generator.
    * @param \Generator $generator No type for performance, we already know the type.
    *
    * @return Promise
    */
    private static function transform($yielded, $generator) : Promise
    {
        $exception = null;
        // initialize here, see https://github.com/vimeo/psalm/issues/2951
        try {
            if (\is_array($yielded)) {
                return Promise\all($yielded);
            }
            if ($yielded instanceof ReactPromise) {
                return Promise\adapt($yielded);
            }
            // No match, continue to returning Failure below.
        } catch (\Throwable $exception) {
            // Conversion to promise failed, fall-through to returning Failure below.
        }
        return new Failure(new InvalidYieldError($generator, \sprintf("Unexpected yield; Expected an instance of %s or %s or an array of such instances", Promise::class, ReactPromise::class), $exception));
    }
    /**
     * @param \Generator $generator
     * @psalm-param \Generator<mixed, (Promise | ReactPromise | array<array-key, (Promise | ReactPromise)>), mixed, (Promise<TReturn> | ReactPromise | TReturn)> $generator
     */
    public function __construct(\Generator $generator)
    {
        try {
            $yielded = $generator->current();
            if (!$yielded instanceof Promise) {
                if (!$generator->valid()) {
                    $this->resolve($generator->getReturn());
                    return;
                }
                $yielded = self::transform($yielded, $generator);
            }
        } catch (\Throwable $exception) {
            $this->fail($exception);
            return;
        }
        /**
         * @param \Throwable|null $e Exception to be thrown into the generator.
         * @param mixed           $v Value to be sent into the generator.
         *
         * @return void
         *
         * @psalm-suppress MissingClosureParamType
         * @psalm-suppress MissingClosureReturnType
         */
        $onResolve = function (\Throwable $e = null, $v) use($generator, &$onResolve) {
            /** @var bool $immediate Used to control iterative coroutine continuation. */
            static $immediate = \true;
            /** @var \Throwable|null $exception Promise failure reason when executing next coroutine step, null at all other times. */
            static $exception;
            /** @var mixed $value Promise success value when executing next coroutine step, null at all other times. */
            static $value;
            $exception = $e;
            /** @psalm-suppress MixedAssignment */
            $value = $v;
            if (!$immediate) {
                $immediate = \true;
                return;
            }
            try {
                try {
                    do {
                        if ($exception) {
                            // Throw exception at current execution point.
                            $yielded = $generator->throw($exception);
                        } else {
                            // Send the new value and execute to next yield statement.
                            $yielded = $generator->send($value);
                        }
                        if (!$yielded instanceof Promise) {
                            if (!$generator->valid()) {
                                $this->resolve($generator->getReturn());
                                $onResolve = null;
                                return;
                            }
                            $yielded = self::transform($yielded, $generator);
                        }
                        $immediate = \false;
                        $yielded->onResolve($onResolve);
                    } while ($immediate);
                    $immediate = \true;
                } catch (\Throwable $exception) {
                    $this->fail($exception);
                    $onResolve = null;
                } finally {
                    $exception = null;
                    $value = null;
                }
            } catch (\Throwable $e) {
                Loop::defer(static function () use($e) {
                    throw $e;
                });
            }
        };
        try {
            $yielded->onResolve($onResolve);
            unset($generator, $yielded, $onResolve);
        } catch (\Throwable $e) {
            Loop::defer(static function () use($e) {
                throw $e;
            });
        }
    }
}
<?php

namespace PhabelVendor\Amp;

/**
 * Cancellation tokens are simple objects that allow registering handlers to subscribe to cancellation requests.
 */
interface CancellationToken
{
    /**
    * Subscribes a new handler to be invoked on a cancellation request.
    *
    * This handler might be invoked immediately in case the token has already been cancelled. Returned generators will
    automatically be run as coroutines. Any unhandled exceptions will be throw into the event loop.
    *
    * @param callable(CancelledException) $callback Callback to be invoked on a cancellation request. Will receive a
    `CancelledException` as first argument that may be used to fail the operation's promise.
    *
    * @return string Identifier that can be used to cancel the subscription.
    */
    public function subscribe(callable $callback) : string;
    /**
     * Unsubscribes a previously registered handler.
     *
     * The handler will no longer be called as long as this method isn't invoked from a subscribed callback.
     *
     * @param string $id
     *
     * @return void
     */
    public function unsubscribe(string $id);
    /**
     * Returns whether cancellation has been requested yet.
     *
     * @return bool
     */
    public function isRequested() : bool;
    /**
     * Throws the `CancelledException` if cancellation has been requested, otherwise does nothing.
     *
     * @return void
     *
     * @throws CancelledException
     */
    public function throwIfRequested();
}
<?php

namespace PhabelVendor\Amp;

/**
 * Deferred is a container for a promise that is resolved using the resolve() and fail() methods of this object.
 * The contained promise may be accessed using the promise() method. This object should not be part of a public
 * API, but used internally to create and resolve a promise.
 *
 * @template TValue
 */
final class Deferred
{
    /** @var Promise<TValue> Has public resolve and fail methods. */
    private $resolver;
    /** @var Promise<TValue> Hides placeholder methods */
    private $promise;
    /**
     *
     */
    public function __construct()
    {
        $this->resolver = new class implements Promise
        {
            use Internal\Placeholder {
                resolve as public;
                fail as public;
                isResolved as public;
            }
        };
        $this->promise = new Internal\PrivatePromise($this->resolver);
    }
    /**
     * @return Promise<TValue>
     */
    public function promise() : Promise
    {
        return $this->promise;
    }
    /**
     * Fulfill the promise with the given value.
     *
     * @param mixed $value
     *
     * @psalm-param (TValue | Promise<TValue>) $value
     *
     * @return void
     */
    public function resolve($value = null)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->resolver->resolve($value);
    }
    /**
     * Fails the promise the the given reason.
     *
     * @param \Throwable $reason
     *
     * @return void
     */
    public function fail(\Throwable $reason)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->resolver->fail($reason);
    }
    /**
     * @return bool True if the promise has been resolved.
     */
    public function isResolved() : bool
    {
        return $this->resolver->isResolved();
    }
}
<?php

namespace PhabelVendor\Amp;

use PhabelVendor\React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a failed promise using the given exception.
 *
 * @template-covariant TValue
 * @template-implements Promise<TValue>
 */
final class Failure implements Promise
{
    /** @var \Throwable $exception */
    private $exception;
    /**
     * @param \Throwable $exception Rejection reason.
     */
    public function __construct(\Throwable $exception)
    {
        $this->exception = $exception;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        try {
            /** @var mixed $result */
            $result = $onResolved($this->exception, null);
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
}
<?php

namespace PhabelVendor\Amp;

class MultiReasonException extends \Exception
{
    /** @var \Throwable[] */
    private $reasons;
    /**
     * @param \Throwable[] $reasons Array of exceptions rejecting the promise.
     * @param (string | null) $message
     */
    public function __construct(array $reasons, string $message = null)
    {
        parent::__construct($message ?: "Multiple errors encountered; use " . self::class . "::getReasons() to retrieve the array of exceptions thrown");
        $this->reasons = $reasons;
    }
    /**
     * @return \Throwable[]
     */
    public function getReasons() : array
    {
        return $this->reasons;
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp;

class InvalidYieldError extends \Error
{
    /**
     * @param \Generator $generator
     * @param string $prefix
     * @param (\Throwable | null) $previous
     */
    public function __construct(\Generator $generator, string $prefix, \Throwable $previous = null)
    {
        $yielded = $generator->current();
        $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), \var_export($generator->key(), \true));
        if (!$generator->valid()) {
            parent::__construct($prefix, 0, $previous);
            return;
        }
        $reflGen = new \ReflectionGenerator($generator);
        $exeGen = $reflGen->getExecutingGenerator();
        if ($isSubgenerator = $exeGen !== $generator) {
            $reflGen = new \ReflectionGenerator($exeGen);
        }
        parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile()), 0, $previous);
    }
}
<?php

namespace PhabelVendor\Amp;

final class CombinedCancellationToken implements CancellationToken
{
    /** @var array{0: CancellationToken, 1: string}[] */
    private $tokens = [];
    /** @var string */
    private $nextId = "a";
    /** @var callable[] */
    private $callbacks = [];
    /** @var CancelledException|null */
    private $exception;
    /**
     *
     */
    public function __construct(CancellationToken ...$tokens)
    {
        foreach ($tokens as $token) {
            $id = $token->subscribe(function (CancelledException $exception) {
                $this->exception = $exception;
                $callbacks = $this->callbacks;
                $this->callbacks = [];
                foreach ($callbacks as $callback) {
                    asyncCall($callback, $this->exception);
                }
            });
            $this->tokens[] = [$token, $id];
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        foreach ($this->tokens as list($token, $id)) {
            /** @var CancellationToken $token */
            $token->unsubscribe($id);
        }
    }
    /**
     * @inheritdoc
     */
    public function subscribe(callable $callback) : string
    {
        $id = $this->nextId++;
        if ($this->exception) {
            asyncCall($callback, $this->exception);
        } else {
            $this->callbacks[$id] = $callback;
        }
        return $id;
    }
    /**
     * @inheritdoc
     */
    public function unsubscribe(string $id)
    {
        unset($this->callbacks[$id]);
    }
    /**
     * @inheritdoc
     */
    public function isRequested() : bool
    {
        foreach ($this->tokens as list($token)) {
            if ($token->isRequested()) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * @inheritdoc
     */
    public function throwIfRequested()
    {
        foreach ($this->tokens as list($token)) {
            $token->throwIfRequested();
        }
    }
}
<?php

namespace PhabelVendor\Amp;

/**
 * Thrown if a promise doesn't resolve within a specified timeout.
 *
 * @see \Amp\Promise\timeout()
 */
class TimeoutException extends \Exception
{
    /**
     * @param string $message Exception message.
     */
    public function __construct(string $message = "Operation timed out")
    {
        parent::__construct($message);
    }
}
<?php

namespace PhabelVendor\Amp;

use PhabelVendor\Amp\Loop\Driver;
use PhabelVendor\Amp\Loop\DriverFactory;
use PhabelVendor\Amp\Loop\InvalidWatcherError;
use PhabelVendor\Amp\Loop\UnsupportedFeatureException;
use PhabelVendor\Amp\Loop\Watcher;
/**
 * Accessor to allow global access to the event loop.
 *
 * @see \Amp\Loop\Driver
 */
final class Loop
{
    /**
     * @var Driver
     */
    private static $driver;
    /**
     * Disable construction as this is a static class.
     */
    private function __construct()
    {
        // intentionally left blank
    }
    /**
     * Sets the driver to be used for `Loop::run()`.
     *
     * @param Driver $driver
     *
     * @return void
     */
    public static function set(Driver $driver)
    {
        try {
            self::$driver = new class extends Driver
            {
                /**
                 * @return void
                 */
                protected function activate(array $watchers)
                {
                    throw new \Error("Can't activate watcher during garbage collection.");
                }
                /**
                 * @return void
                 */
                protected function dispatch(bool $blocking)
                {
                    throw new \Error("Can't dispatch during garbage collection.");
                }
                /**
                 * @return void
                 */
                protected function deactivate(Watcher $watcher)
                {
                    // do nothing
                }
                /**
                 *
                 */
                public function getHandle()
                {
                    return null;
                }
            };
            \gc_collect_cycles();
        } finally {
            self::$driver = $driver;
        }
    }
    /**
    * Run the event loop and optionally execute a callback within the scope of it.
    *
    * The loop MUST continue to run until it is either stopped explicitly, no referenced watchers exist anymore, or an
    exception is thrown that cannot be handled. Exceptions that cannot be handled are exceptions thrown from an
    error handler or exceptions that would be passed to an error handler but none exists to handle them.
    *
    * @param (callable | null) $callback The callback to execute.
    *
    * @return void
    */
    public static function run(callable $callback = null)
    {
        if ($callback) {
            self::$driver->defer($callback);
        }
        self::$driver->run();
    }
    /**
    * Stop the event loop.
    *
    * When an event loop is stopped, it continues with its current tick and exits the loop afterwards. Multiple calls
    to stop MUST be ignored and MUST NOT raise an exception.
    *
    * @return void
    */
    public static function stop()
    {
        self::$driver->stop();
    }
    /**
    * Defer the execution of a callback.
    *
    * The deferred callable MUST be executed before any other type of watcher in a tick. Order of enabling MUST be
    preserved when executing the callbacks.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param callable(string $watcherId, mixed $data) $callback The callback to defer. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function defer(callable $callback, $data = null) : string
    {
        return self::$driver->defer($callback, $data);
    }
    /**
    * Delay the execution of a callback.
    *
    * The delay is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be determined by which
    timers expire first, but timers with the same expiration time MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $delay The amount of time, in milliseconds, to delay the execution for.
    * @param callable(string $watcherId, mixed $data) $callback The callback to delay. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function delay(int $delay, callable $callback, $data = null) : string
    {
        return self::$driver->delay($delay, $callback, $data);
    }
    /**
    * Repeatedly execute a callback.
    *
    * The interval between executions is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be
    determined by which timers expire first, but timers with the same expiration time MAY be executed in any order.
    The first execution is scheduled after the first interval period.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $interval The time interval, in milliseconds, to wait between executions.
    * @param callable(string $watcherId, mixed $data) $callback The callback to repeat.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function repeat(int $interval, callable $callback, $data = null) : string
    {
        return self::$driver->repeat($interval, $callback, $data);
    }
    /**
    * Execute a callback when a stream resource becomes readable or is closed for reading.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable(string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function onReadable($stream, callable $callback, $data = null) : string
    {
        return self::$driver->onReadable($stream, $callback, $data);
    }
    /**
    * Execute a callback when a stream resource becomes writable or is closed for writing.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable(string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function onWritable($stream, callable $callback, $data = null) : string
    {
        return self::$driver->onWritable($stream, $callback, $data);
    }
    /**
    * Execute a callback when a signal is received.
    *
    * Warning: Installing the same signal on different instances of this interface is deemed undefined behavior.
    Implementations MAY try to detect this, if possible, but are not required to. This is due to technical
    limitations of the signals being registered globally per process.
    *
    * Multiple watchers on the same signal MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $signo The signal number to monitor.
    * @param callable(string $watcherId, int $signo, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the $data parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    *
    * @throws UnsupportedFeatureException If signal handling is not supported.
    */
    public static function onSignal(int $signo, callable $callback, $data = null) : string
    {
        return self::$driver->onSignal($signo, $callback, $data);
    }
    /**
    * Enable a watcher to be active starting in the next tick.
    *
    * Watchers MUST immediately be marked as enabled, but only be activated (i.e. callbacks can be called) right before
    the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public static function enable(string $watcherId)
    {
        self::$driver->enable($watcherId);
    }
    /**
    * Disable a watcher immediately.
    *
    * A watcher MUST be disabled immediately, e.g. if a defer watcher disables a later defer watcher, the second defer
    watcher isn't executed in this tick.
    *
    * Disabling a watcher MUST NOT invalidate the watcher. Calling this function MUST NOT fail, even if passed an
    invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function disable(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->disable($watcherId);
    }
    /**
    * Cancel a watcher.
    *
    * This will detatch the event loop from all resources that are associated to the watcher. After this operation the
    watcher is permanently invalid. Calling this function MUST NOT fail, even if passed an invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function cancel(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->cancel($watcherId);
    }
    /**
    * Reference a watcher.
    *
    * This will keep the event loop alive whilst the watcher is still being monitored. Watchers have this state by
    default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public static function reference(string $watcherId)
    {
        self::$driver->reference($watcherId);
    }
    /**
    * Unreference a watcher.
    *
    * The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers
    are all referenced by default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function unreference(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->unreference($watcherId);
    }
    /**
    * Returns the current loop time in millisecond increments. Note this value does not necessarily correlate to
    wall-clock time, rather the value returned is meant to be used in relative comparisons to prior values returned
    by this method (intervals, expiration calculations, etc.) and is only updated once per loop tick.
    *
    * @return int
    */
    public static function now() : int
    {
        return self::$driver->now();
    }
    /**
    * Stores information in the loop bound registry.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    * @param mixed $value The value to be stored.
    *
    * @return void
    */
    public static function setState(string $key, $value)
    {
        self::$driver->setState($key, $value);
    }
    /**
    * Gets information stored bound to the loop.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    *
    * @return mixed The previously stored value or `null` if it doesn't exist.
    */
    public static function getState(string $key)
    {
        return self::$driver->getState($key);
    }
    /**
    * Set a callback to be executed when an error occurs.
    *
    * The callback receives the error as the first and only parameter. The return value of the callback gets ignored.
    If it can't handle the error, it MUST throw the error. Errors thrown by the callback or during its invocation
    MUST be thrown into the `run` loop and stop the driver.
    *
    * Subsequent calls to this method will overwrite the previous handler.
    *
    * @param callable(\Throwable $error)|null $callback The callback to execute. `null` will clear the
    current handler.
    *
    * @return callable (\Throwable $error)|null The previous handler, `null` if there was none.
    */
    public static function setErrorHandler(callable $callback = null)
    {
        return self::$driver->setErrorHandler($callback);
    }
    /**
    * Retrieve an associative array of information about the event loop driver.
    *
    * The returned array MUST contain the following data describing the driver's currently registered watchers:
    *
    * [
    "defer"            => ["enabled" => int, "disabled" => int],
    "delay"            => ["enabled" => int, "disabled" => int],
    "repeat"           => ["enabled" => int, "disabled" => int],
    "on_readable"      => ["enabled" => int, "disabled" => int],
    "on_writable"      => ["enabled" => int, "disabled" => int],
    "on_signal"        => ["enabled" => int, "disabled" => int],
    "enabled_watchers" => ["referenced" => int, "unreferenced" => int],
    "running"          => bool
    ];
    *
    * Implementations MAY optionally add more information in the array but at minimum the above `key => value` format
    MUST always be provided.
    *
    * @return array Statistics about the loop in the described format.
    */
    public static function getInfo() : array
    {
        return self::$driver->getInfo();
    }
    /**
     * Retrieve the event loop driver that is in scope.
     *
     * @return Driver
     */
    public static function get() : Driver
    {
        return self::$driver;
    }
}
// Default factory, don't move this to a file loaded by the composer "files" autoload mechanism, otherwise custom
// implementations might have issues setting a default loop, because it's overridden by us then.
// @codeCoverageIgnoreStart
Loop::set((new DriverFactory())->create());
// @codeCoverageIgnoreEnd
<?php

namespace PhabelVendor\Amp;

/**
 * Creates a promise that resolves itself with a given value after a number of milliseconds.
 *
 * @template-covariant TReturn
 * @template-implements Promise<TReturn>
 */
final class Delayed implements Promise
{
    use Internal\Placeholder;
    /** @var string|null Event loop watcher identifier. */
    private $watcher;
    /**
     * @param int $time Milliseconds before succeeding the promise.
     * @param TReturn $value Succeed the promise with this value.
     */
    public function __construct(int $time, $value = null)
    {
        $this->watcher = Loop::delay($time, function () use($value) {
            $this->watcher = null;
            $this->resolve($value);
        });
    }
    /**
     * References the internal watcher in the event loop, keeping the loop running while this promise is pending.
     *
     * @return self
     */
    public function reference() : self
    {
        if ($this->watcher !== null) {
            Loop::reference($this->watcher);
        }
        return $this;
    }
    /**
    * Unreferences the internal watcher in the event loop, allowing the loop to stop while this promise is pending if
    no other events are pending in the loop.
    *
    * @return self
    */
    public function unreference() : self
    {
        if ($this->watcher !== null) {
            Loop::unreference($this->watcher);
        }
        return $this;
    }
}
<?php

namespace PhabelVendor\Amp;

/**
 * Defines an asynchronous iterator over a set of values that is designed to be used within a coroutine.
 *
 * @template-covariant TValue
 */
interface Iterator
{
    /**
    * Succeeds with true if an emitted value is available by calling getCurrent() or false if the iterator has
    resolved. If the iterator fails, the returned promise will fail with the same exception.
    *
    * @return Promise
    * @psalm-return Promise<bool>
    *
    * @throws \Error If the prior promise returned from this method has not resolved.
    * @throws \Throwable The exception used to fail the iterator.
    */
    public function advance() : Promise;
    /**
     * Gets the last emitted value or throws an exception if the iterator has completed.
     *
     * @return mixed Value emitted from the iterator.
     * @psalm-return TValue
     *
     * @throws \Error If the iterator has resolved or advance() was not called before calling this method.
     * @throws \Throwable The exception used to fail the iterator.
     */
    public function getCurrent();
}
<?php

namespace PhabelVendor\Amp;

// @codeCoverageIgnoreStart
if (\PHP_VERSION_ID < 70100) {
    /** @psalm-suppress DuplicateClass */
    trait CallableMaker
    {
        /** @var \ReflectionClass */
        private static $__reflectionClass;
        /** @var \ReflectionMethod[] */
        private static $__reflectionMethods = [];
        /**
        * Creates a callable from a protected or private instance method that may be invoked by callers requiring a
        publicly invokable callback.
        *
        * @param string $method Instance method name.
        *
        * @return callable
        *
        * @psalm-suppress MixedInferredReturnType
        */
        private function callableFromInstanceMethod(string $method) : callable
        {
            if (!isset(self::$__reflectionMethods[$method])) {
                if (self::$__reflectionClass === null) {
                    self::$__reflectionClass = new \ReflectionClass(self::class);
                }
                self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method);
            }
            return self::$__reflectionMethods[$method]->getClosure($this);
        }
        /**
        * Creates a callable from a protected or private static method that may be invoked by methods requiring a
        publicly invokable callback.
        *
        * @param string $method Static method name.
        *
        * @return callable
        *
        * @psalm-suppress MixedInferredReturnType
        */
        private static function callableFromStaticMethod(string $method) : callable
        {
            if (!isset(self::$__reflectionMethods[$method])) {
                if (self::$__reflectionClass === null) {
                    self::$__reflectionClass = new \ReflectionClass(self::class);
                }
                self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method);
            }
            return self::$__reflectionMethods[$method]->getClosure();
        }
    }
} else {
    /** @psalm-suppress DuplicateClass */
    trait CallableMaker
    {
        /**
         * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1.
         */
        private function callableFromInstanceMethod(string $method) : callable
        {
            return \Closure::fromCallable([$this, $method]);
        }
        /**
         * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1.
         */
        private static function callableFromStaticMethod(string $method) : callable
        {
            return \Closure::fromCallable([self::class, $method]);
        }
    }
}
// @codeCoverageIgnoreEnd
<?php

namespace PhabelVendor\Amp;

/**
 * Will be thrown in case an operation is cancelled.
 *
 * @see CancellationToken
 * @see CancellationTokenSource
 */
class CancelledException extends \Exception
{
    /**
     *
     */
    public function __construct(\Throwable $previous = null)
    {
        parent::__construct("The operation was cancelled", 0, $previous);
    }
}
<?php

namespace PhabelVendor\Amp;

/**
 * Creates a promise that calls $promisor only when the result of the promise is requested (i.e. onResolve() is called
 * on the promise). $promisor can return a promise or any value. If $promisor throws an exception, the promise fails
 * with that exception. If $promisor returns a Generator, it will be run as a coroutine.
 */
final class LazyPromise implements Promise
{
    /** @var callable|null */
    private $promisor;
    /** @var Promise|null */
    private $promise;
    /**
    * @param callable $promisor Function which starts an async operation, returning a Promise (or any value).
    Generators will be run as a coroutine.
    */
    public function __construct(callable $promisor)
    {
        $this->promisor = $promisor;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        if ($this->promise === null) {
            \assert($this->promisor !== null);
            $provider = $this->promisor;
            $this->promisor = null;
            $this->promise = call($provider);
        }
        \assert($this->promise !== null);
        $this->promise->onResolve($onResolved);
    }
}
<?php

namespace PhabelVendor\Amp;

/**
 * A "safe" struct trait for public property aggregators.
 *
 * This trait is intended to make using public properties a little safer by throwing when
 * nonexistent property names are read or written.
 */
trait Struct
{
    /**
     * The minimum percentage [0-100] at which to recommend a similar property
     * name when generating error messages.
     */
    private $__propertySuggestThreshold = 70;
    /**
     * @param string $property
     *
     * @psalm-return no-return
     */
    public function __get(string $property)
    {
        throw new \Error($this->generateStructPropertyError($property));
    }
    /**
     * @param string $property
     * @param mixed $value
     *
     * @psalm-return no-return
     */
    public function __set(string $property, $value)
    {
        throw new \Error($this->generateStructPropertyError($property));
    }
    /**
     *
     */
    private function generateStructPropertyError(string $property) : string
    {
        $suggestion = $this->suggestPropertyName($property);
        $suggestStr = $suggestion == "" ? "" : " ... did you mean \"{$suggestion}?\"";
        return \sprintf(
            "%s property \"%s\" does not exist%s",
            \str_replace("\x00", "@", \get_class($this)),
            // Handle anonymous class names.
            $property,
            $suggestStr
        );
    }
    /**
     *
     */
    private function suggestPropertyName(string $badProperty) : string
    {
        $badProperty = \strtolower($badProperty);
        $bestMatch = "";
        $bestMatchPercentage = 0;
        /** @psalm-suppress RawObjectIteration */
        foreach ($this as $property => $value) {
            // Never suggest properties that begin with an underscore
            if ($property[0] === "_") {
                continue;
            }
            \similar_text($badProperty, \strtolower($property), $byRefPercentage);
            if ($byRefPercentage > $bestMatchPercentage) {
                $bestMatchPercentage = $byRefPercentage;
                $bestMatch = $property;
            }
        }
        return $bestMatchPercentage >= $this->__propertySuggestThreshold ? $bestMatch : "";
    }
}
<?php

namespace PhabelVendor\Amp\Serialization;

final class NativeSerializer implements Serializer
{
    /** @var string[]|null */
    private $allowedClasses;
    /**
     * @param (string[] | null) $allowedClasses List of allowed class names to be unserialized. Null for any class.
     */
    public function __construct(?array $allowedClasses = null)
    {
        $this->allowedClasses = $allowedClasses;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        try {
            return \serialize($data);
        } catch (\Throwable $exception) {
            throw new SerializationException(\sprintf('The given data could not be serialized: %s', $exception->getMessage()), 0, $exception);
        }
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        try {
            $result = \unserialize($data, ['allowed_classes' => $this->allowedClasses ?? \true]);
            if ($result === \false && $data !== \serialize(\false)) {
                throw new SerializationException('Invalid data provided to unserialize: ' . encodeUnprintableChars($data));
            }
        } catch (\Throwable $exception) {
            throw new SerializationException('Exception thrown when unserializing data', 0, $exception);
        }
        return $result;
    }
}
<?php

namespace PhabelVendor\Amp\Serialization;

final class JsonSerializer implements Serializer
{
    // Equal to JSON_THROW_ON_ERROR, only available in PHP 7.3+.
    private const THROW_ON_ERROR = 4194304;
    /** @var bool */
    private $associative;
    /** @var int */
    private $encodeOptions;
    /** @var int */
    private $decodeOptions;
    /** @var int */
    private $depth;
    /**
     * Creates a JSON serializer that decodes objects to associative arrays.
     *
     * @param int $encodeOptions @see \json_encode() options parameter.
     * @param int $decodeOptions @see \json_decode() options parameter.
     * @param int $depth Maximum recursion depth.
     *
     * @return self
     */
    public static function withAssociativeArrays(int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512) : self
    {
        return new self(\true, $encodeOptions, $decodeOptions, $depth);
    }
    /**
     * Creates a JSON serializer that decodes objects to instances of stdClass.
     *
     * @param int $encodeOptions @see \json_encode() options parameter.
     * @param int $decodeOptions @see \json_decode() options parameter.
     * @param int $depth Maximum recursion depth.
     *
     * @return self
     */
    public static function withObjects(int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512) : self
    {
        return new self(\false, $encodeOptions, $decodeOptions, $depth);
    }
    /**
     *
     */
    private function __construct(bool $associative, int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512)
    {
        $this->associative = $associative;
        $this->depth = $depth;
        // We don't want to throw on errors, we manually check for errors using json_last_error().
        $this->encodeOptions = $encodeOptions & ~self::THROW_ON_ERROR;
        $this->decodeOptions = $decodeOptions & ~self::THROW_ON_ERROR;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        $result = \json_encode($data, $this->encodeOptions, $this->depth);
        switch ($code = \json_last_error()) {
            case \JSON_ERROR_NONE:
                return $result;
            default:
                throw new SerializationException(\json_last_error_msg(), $code);
        }
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        $result = \json_decode($data, $this->associative, $this->depth, $this->decodeOptions);
        switch ($code = \json_last_error()) {
            case \JSON_ERROR_NONE:
                return $result;
            default:
                throw new SerializationException(\json_last_error_msg(), $code);
        }
    }
}
<?php

namespace PhabelVendor\Amp\Serialization;

/**
 * @param string $data Binary data.
 *
 * @return string Unprintable characters encoded as \x##.
 */
function encodeUnprintableChars(string $data) : string
{
    return \preg_replace_callback("/[^ -~]/", function (array $matches) : string {
        return "\\x" . \dechex(\ord($matches[0]));
    }, $data);
}
<?php

namespace PhabelVendor\Amp\Serialization;

interface Serializer
{
    /**
     * @param mixed $data
     *
     * @return string
     *
     * @throws SerializationException
     */
    public function serialize($data) : string;
    /**
     * @param string $data
     *
     * @return mixed The unserialized data.
     *
     * @throws SerializationException
     */
    public function unserialize(string $data);
}
<?php

namespace PhabelVendor\Amp\Serialization;

final class CompressingSerializer implements Serializer
{
    private const FLAG_COMPRESSED = 1;
    private const COMPRESSION_THRESHOLD = 256;
    /** @var Serializer */
    private $serializer;
    /**
     *
     */
    public function __construct(Serializer $serializer)
    {
        $this->serializer = $serializer;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        $serializedData = $this->serializer->serialize($data);
        $flags = 0;
        if (\strlen($serializedData) > self::COMPRESSION_THRESHOLD) {
            $serializedData = @\gzdeflate($serializedData, 1);
            if ($serializedData === \false) {
                $error = \error_get_last();
                throw new SerializationException('Could not compress data: ' . ($error['message'] ?? 'unknown error'));
            }
            $flags |= self::FLAG_COMPRESSED;
        }
        return \chr($flags & 0xff) . $serializedData;
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        $firstByte = \ord($data[0]);
        $data = \Phabel\Target\Php80\Polyfill::substr($data, 1);
        if ($firstByte & self::FLAG_COMPRESSED) {
            $data = @\gzinflate($data);
            if ($data === \false) {
                $error = \error_get_last();
                throw new SerializationException('Could not decompress data: ' . ($error['message'] ?? 'unknown error'));
            }
        }
        return $this->serializer->unserialize($data);
    }
}
<?php

namespace PhabelVendor\Amp\Serialization;

final class PassthroughSerializer implements Serializer
{
    /**
     *
     */
    public function serialize($data) : string
    {
        if (!\is_string($data)) {
            throw new SerializationException('Serializer implementation only allows strings');
        }
        return $data;
    }
    /**
     *
     */
    public function unserialize(string $data) : string
    {
        return $data;
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\Serialization;

class SerializationException extends \Exception
{
}
<?php

namespace PhabelVendor\Amp\ByteStream\Base64;

use PhabelVendor\Amp\ByteStream\InputStream;
use PhabelVendor\Amp\ByteStream\StreamException;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
final class Base64DecodingInputStream implements InputStream
{
    /** @var InputStream|null */
    private $source;
    /** @var string|null */
    private $buffer = '';
    /**
     *
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    public function read() : Promise
    {
        return call(function () {
            if ($this->source === null) {
                throw new StreamException('Failed to read stream chunk due to invalid base64 data');
            }
            $chunk = (yield $this->source->read());
            if ($chunk === null) {
                if ($this->buffer === null) {
                    return null;
                }
                $chunk = \base64_decode($this->buffer, \true);
                if ($chunk === \false) {
                    $this->source = null;
                    $this->buffer = null;
                    throw new StreamException('Failed to read stream chunk due to invalid base64 data');
                }
                $this->buffer = null;
                return $chunk;
            }
            $this->buffer .= $chunk;
            $length = \strlen($this->buffer);
            $chunk = \base64_decode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 4), \true);
            if ($chunk === \false) {
                $this->source = null;
                $this->buffer = null;
                throw new StreamException('Failed to read stream chunk due to invalid base64 data');
            }
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 4);
            return $chunk;
        });
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream\Base64;

use PhabelVendor\Amp\ByteStream\OutputStream;
use PhabelVendor\Amp\Promise;
final class Base64EncodingOutputStream implements OutputStream
{
    /** @var OutputStream */
    private $destination;
    /** @var string */
    private $buffer = '';
    /**
     *
     */
    public function __construct(OutputStream $destination)
    {
        $this->destination = $destination;
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        $this->buffer .= $data;
        $length = \strlen($this->buffer);
        $chunk = \base64_encode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 3));
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 3);
        return $this->destination->write($chunk);
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        $chunk = \base64_encode($this->buffer . $finalData);
        $this->buffer = '';
        return $this->destination->end($chunk);
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream\Base64;

use PhabelVendor\Amp\ByteStream\OutputStream;
use PhabelVendor\Amp\ByteStream\StreamException;
use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Promise;
final class Base64DecodingOutputStream implements OutputStream
{
    /** @var OutputStream */
    private $destination;
    /** @var string */
    private $buffer = '';
    /** @var int */
    private $offset = 0;
    /**
     *
     */
    public function __construct(OutputStream $destination)
    {
        $this->destination = $destination;
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        $this->buffer .= $data;
        $length = \strlen($this->buffer);
        $chunk = \base64_decode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 4), \true);
        if ($chunk === \false) {
            return new Failure(new StreamException('Invalid base64 near offset ' . $this->offset));
        }
        $this->offset += $length - $length % 4;
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 4);
        return $this->destination->write($chunk);
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        $this->offset += \strlen($this->buffer);
        $chunk = \base64_decode($this->buffer . $finalData, \true);
        if ($chunk === \false) {
            return new Failure(new StreamException('Invalid base64 near offset ' . $this->offset));
        }
        $this->buffer = '';
        return $this->destination->end($chunk);
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream\Base64;

use PhabelVendor\Amp\ByteStream\InputStream;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
final class Base64EncodingInputStream implements InputStream
{
    /** @var InputStream */
    private $source;
    /** @var string|null */
    private $buffer = '';
    /**
     *
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    public function read() : Promise
    {
        return call(function () {
            $chunk = (yield $this->source->read());
            if ($chunk === null) {
                if ($this->buffer === null) {
                    return null;
                }
                $chunk = \base64_encode($this->buffer);
                $this->buffer = null;
                return $chunk;
            }
            $this->buffer .= $chunk;
            $length = \strlen($this->buffer);
            $chunk = \base64_encode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 3));
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 3);
            return $chunk;
        });
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Iterator;
use PhabelVendor\Amp\Promise;
final class IteratorStream implements InputStream
{
    /** @var Iterator<string> */
    private $iterator;
    /** @var \Throwable|null */
    private $exception;
    /** @var bool */
    private $pending = \false;
    /**
     * @psam-param Iterator<string> $iterator
     */
    public function __construct(Iterator $iterator)
    {
        $this->iterator = $iterator;
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        if ($this->exception) {
            return new Failure($this->exception);
        }
        if ($this->pending) {
            throw new PendingReadError();
        }
        $this->pending = \true;
        /** @var Deferred<string|null> $deferred */
        $deferred = new Deferred();
        $this->iterator->advance()->onResolve(function ($error, $hasNextElement) use($deferred) {
            $this->pending = \false;
            if ($error) {
                $this->exception = $error;
                $deferred->fail($error);
            } elseif ($hasNextElement) {
                $chunk = $this->iterator->getCurrent();
                if (!\is_string($chunk)) {
                    $this->exception = new StreamException(\sprintf("Unexpected iterator value of type '%s', expected string", \is_object($chunk) ? \get_class($chunk) : \gettype($chunk)));
                    $deferred->fail($this->exception);
                    return;
                }
                $deferred->resolve($chunk);
            } else {
                $deferred->resolve();
            }
        });
        return $deferred->promise();
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
/**
 * Output stream abstraction for PHP's stream resources.
 */
final class ResourceOutputStream implements OutputStream
{
    const MAX_CONSECUTIVE_EMPTY_WRITES = 3;
    const LARGE_CHUNK_SIZE = 128 * 1024;
    /** @var resource|null */
    private $resource;
    /** @var string */
    private $watcher;
    /** @var \SplQueue<array> */
    private $writes;
    /** @var bool */
    private $writable = \true;
    /** @var int|null */
    private $chunkSize;
    /**
     * @param resource $stream Stream resource.
     * @param (int | null) $chunkSize Chunk size per `fwrite()` operation.
     */
    public function __construct($stream, int $chunkSize = null)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== 'stream') {
            throw new \Error("Expected a valid stream");
        }
        $meta = \stream_get_meta_data($stream);
        if (\strpos($meta["mode"], "r") !== \false && \strpos($meta["mode"], "+") === \false) {
            throw new \Error("Expected a writable stream");
        }
        \stream_set_blocking($stream, \false);
        \stream_set_write_buffer($stream, 0);
        $this->resource = $stream;
        $this->chunkSize =& $chunkSize;
        $writes = $this->writes = new \SplQueue();
        $writable =& $this->writable;
        $resource =& $this->resource;
        $this->watcher = Loop::onWritable($stream, static function ($watcher, $stream) use($writes, &$chunkSize, &$writable, &$resource) {
            static $emptyWrites = 0;
            try {
                while (!$writes->isEmpty()) {
                    /** @var Deferred $deferred */
                    list($data, $previous, $deferred) = $writes->shift();
                    $length = \strlen($data);
                    if ($length === 0) {
                        $deferred->resolve(0);
                        continue;
                    }
                    if (!\is_resource($stream) || ($metaData = @\stream_get_meta_data($stream)) && $metaData['eof']) {
                        throw new ClosedException("The stream was closed by the peer");
                    }
                    // Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full.
                    // Use conditional, because PHP doesn't like getting null passed
                    if ($chunkSize) {
                        $written = @\fwrite($stream, $data, $chunkSize);
                    } else {
                        $written = @\fwrite($stream, $data);
                    }
                    \assert(
                        $written !== \false || \PHP_VERSION_ID >= 70400,
                        // PHP 7.4+ returns false on EPIPE.
                        "Trying to write on a previously fclose()'d resource. Do NOT manually fclose() resources the still referenced in the loop."
                    );
                    // PHP 7.4.0 and 7.4.1 may return false on EAGAIN.
                    if ($written === \false && \PHP_VERSION_ID >= 70402) {
                        $message = "Failed to write to stream";
                        if ($error = \error_get_last()) {
                            $message .= \sprintf("; %s", $error["message"]);
                        }
                        throw new StreamException($message);
                    }
                    // Broken pipes between processes on macOS/FreeBSD do not detect EOF properly.
                    if ($written === 0 || $written === \false) {
                        if ($emptyWrites++ > self::MAX_CONSECUTIVE_EMPTY_WRITES) {
                            $message = "Failed to write to stream after multiple attempts";
                            if ($error = \error_get_last()) {
                                $message .= \sprintf("; %s", $error["message"]);
                            }
                            throw new StreamException($message);
                        }
                        $writes->unshift([$data, $previous, $deferred]);
                        return;
                    }
                    $emptyWrites = 0;
                    if ($length > $written) {
                        $data = \Phabel\Target\Php80\Polyfill::substr($data, $written);
                        $writes->unshift([$data, $written + $previous, $deferred]);
                        return;
                    }
                    $deferred->resolve($written + $previous);
                }
            } catch (\Throwable $exception) {
                $resource = null;
                $writable = \false;
                /** @psalm-suppress PossiblyUndefinedVariable */
                $deferred->fail($exception);
                while (!$writes->isEmpty()) {
                    list(, , $deferred) = $writes->shift();
                    $deferred->fail($exception);
                }
                Loop::cancel($watcher);
            } finally {
                if ($writes->isEmpty()) {
                    Loop::disable($watcher);
                }
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     */
    public function write(string $data) : Promise
    {
        return $this->send($data, \false);
    }
    /**
     * Closes the stream after all pending writes have been completed. Optionally writes a final data chunk before.
     *
     * @param string $finalData Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     */
    public function end(string $finalData = "") : Promise
    {
        return $this->send($finalData, \true);
    }
    /**
     *
     */
    private function send(string $data, bool $end = \false) : Promise
    {
        if (!$this->writable) {
            return new Failure(new ClosedException("The stream is not writable"));
        }
        $length = \strlen($data);
        $written = 0;
        if ($end) {
            $this->writable = \false;
        }
        if ($this->writes->isEmpty()) {
            if ($length === 0) {
                if ($end) {
                    $this->close();
                }
                return new Success(0);
            }
            if (!\is_resource($this->resource) || ($metaData = @\stream_get_meta_data($this->resource)) && $metaData['eof']) {
                return new Failure(new ClosedException("The stream was closed by the peer"));
            }
            // Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full.
            // Use conditional, because PHP doesn't like getting null passed.
            if ($this->chunkSize) {
                $written = @\fwrite($this->resource, $data, $this->chunkSize);
            } else {
                $written = @\fwrite($this->resource, $data);
            }
            \assert(
                $written !== \false || \PHP_VERSION_ID >= 70400,
                // PHP 7.4+ returns false on EPIPE.
                "Trying to write on a previously fclose()'d resource. Do NOT manually fclose() resources the still referenced in the loop."
            );
            // PHP 7.4.0 and 7.4.1 may return false on EAGAIN.
            if ($written === \false && \PHP_VERSION_ID >= 70402) {
                $message = "Failed to write to stream";
                if ($error = \error_get_last()) {
                    $message .= \sprintf("; %s", $error["message"]);
                }
                return new Failure(new StreamException($message));
            }
            $written = (int) $written;
            // Cast potential false to 0.
            if ($length === $written) {
                if ($end) {
                    $this->close();
                }
                return new Success($written);
            }
            $data = \Phabel\Target\Php80\Polyfill::substr($data, $written);
        }
        $deferred = new Deferred();
        if ($length - $written > self::LARGE_CHUNK_SIZE) {
            $chunks = \str_split($data, self::LARGE_CHUNK_SIZE);
            $data = \array_pop($chunks);
            foreach ($chunks as $chunk) {
                $this->writes->push([$chunk, $written, new Deferred()]);
                $written += self::LARGE_CHUNK_SIZE;
            }
        }
        $this->writes->push([$data, $written, $deferred]);
        Loop::enable($this->watcher);
        $promise = $deferred->promise();
        if ($end) {
            $promise->onResolve([$this, "close"]);
        }
        return $promise;
    }
    /**
     * Closes the stream forcefully. Multiple `close()` calls are ignored.
     *
     * @return void
     */
    public function close()
    {
        if (\is_resource($this->resource)) {
            // Error suppression, as resource might already be closed
            $meta = @\stream_get_meta_data($this->resource);
            if ($meta && \strpos($meta["mode"], "+") !== \false) {
                @\stream_socket_shutdown($this->resource, \STREAM_SHUT_WR);
            } else {
                /** @psalm-suppress InvalidPropertyAssignmentValue psalm reports this as closed-resource */
                @\fclose($this->resource);
            }
        }
        $this->free();
    }
    /**
     * Nulls reference to resource, marks stream unwritable, and fails any pending write.
     *
     * @return void
     */
    private function free()
    {
        $this->resource = null;
        $this->writable = \false;
        if (!$this->writes->isEmpty()) {
            $exception = new ClosedException("The socket was closed before writing completed");
            do {
                /** @var Deferred $deferred */
                list(, , $deferred) = $this->writes->shift();
                $deferred->fail($exception);
            } while (!$this->writes->isEmpty());
        }
        Loop::cancel($this->watcher);
    }
    /**
     * @return (resource | null) Stream resource or null if end() has been called or the stream closed.
     */
    public function getResource()
    {
        return $this->resource;
    }
    /**
     * @return void
     */
    public function setChunkSize(int $chunkSize)
    {
        $this->chunkSize = $chunkSize;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->resource !== null) {
            $this->free();
        }
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Promise;
/**
 * An `OutputStream` allows writing data in chunks. Writers can wait on the returned promises to feel the backpressure.
 */
interface OutputStream
{
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     * @throws StreamException If writing to the stream fails.
     */
    public function write(string $data) : Promise;
    /**
    * Marks the stream as no longer writable. Optionally writes a final data chunk before. Note that this is not the
    same as forcefully closing the stream. This method waits for all pending writes to complete before closing the
    stream. Socket streams implementing this interface should only close the writable side of the stream.
    *
    * @param string $finalData Bytes to write.
    *
    * @return Promise Succeeds once the data has been successfully written to the stream.
    *
    * @throws ClosedException If the stream has already been closed.
    * @throws StreamException If writing to the stream fails.
    */
    public function end(string $finalData = "") : Promise;
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
use function PhabelVendor\Amp\call;
final class InputStreamChain implements InputStream
{
    /** @var InputStream[] */
    private $streams;
    /** @var bool */
    private $reading = \false;
    /**
     *
     */
    public function __construct(InputStream ...$streams)
    {
        $this->streams = $streams;
    }
    /**
     * @inheritDoc
     */
    public function read() : Promise
    {
        if ($this->reading) {
            throw new PendingReadError();
        }
        if (!$this->streams) {
            return new Success(null);
        }
        return call(function () {
            $this->reading = \true;
            try {
                while ($this->streams) {
                    $chunk = (yield $this->streams[0]->read());
                    if ($chunk === null) {
                        \array_shift($this->streams);
                        continue;
                    }
                    return $chunk;
                }
                return null;
            } finally {
                $this->reading = \false;
            }
        });
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Iterator;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Producer;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
// @codeCoverageIgnoreStart
if (\strlen('â€¦') !== 3) {
    throw new \Error('The mbstring.func_overload ini setting is enabled. It must be disabled to use the stream package.');
}
// @codeCoverageIgnoreEnd
if (!\defined('STDOUT')) {
    \define('STDOUT', \fopen('php://stdout', 'w'));
}
if (!\defined('STDERR')) {
    \define('STDERR', \fopen('php://stderr', 'w'));
}
/**
 * @param \Amp\ByteStream\InputStream $source
 * @param \Amp\ByteStream\OutputStream $destination
 *
 * @return \Amp\Promise
 */
function pipe(InputStream $source, OutputStream $destination) : Promise
{
    return call(function () use($source, $destination) : \Generator {
        $written = 0;
        while (($chunk = (yield $source->read())) !== null) {
            $written += \strlen($chunk);
            $writePromise = $destination->write($chunk);
            $chunk = null;
            // free memory
            (yield $writePromise);
        }
        return $written;
    });
}
/**
 * @param \Amp\ByteStream\InputStream $source
 *
 * @return \Amp\Promise
 */
function buffer(InputStream $source) : Promise
{
    return call(function () use($source) : \Generator {
        $buffer = "";
        while (($chunk = (yield $source->read())) !== null) {
            $buffer .= $chunk;
            $chunk = null;
            // free memory
        }
        return $buffer;
    });
}
/**
 * The php://input input buffer stream for the process associated with the currently active event loop.
 *
 * @return ResourceInputStream
 */
function getInputBufferStream() : ResourceInputStream
{
    static $key = InputStream::class . '\\input';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceInputStream(\fopen('php://input', 'rb'));
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The php://output output buffer stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getOutputBufferStream() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\output';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\fopen('php://output', 'wb'));
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDIN stream for the process associated with the currently active event loop.
 *
 * @return ResourceInputStream
 */
function getStdin() : ResourceInputStream
{
    static $key = InputStream::class . '\\stdin';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceInputStream(\STDIN);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDOUT stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getStdout() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\stdout';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\STDOUT);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDERR stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getStderr() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\stderr';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\STDERR);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 *
 */
function parseLineDelimitedJson(InputStream $stream, bool $assoc = \false, int $depth = 512, int $options = 0) : Iterator
{
    return new Producer(static function (callable $emit) use($stream, $assoc, $depth, $options) {
        $reader = new LineReader($stream);
        while (null !== ($line = (yield $reader->readLine()))) {
            $line = \trim($line);
            if ($line === '') {
                continue;
            }
            /** @noinspection PhpComposerExtensionStubsInspection */
            $data = \json_decode($line, $assoc, $depth, $options);
            /** @noinspection PhpComposerExtensionStubsInspection */
            $error = \json_last_error();
            /** @noinspection PhpComposerExtensionStubsInspection */
            if ($error !== \JSON_ERROR_NONE) {
                /** @noinspection PhpComposerExtensionStubsInspection */
                throw new StreamException('Failed to parse JSON: ' . \json_last_error_msg(), $error);
            }
            (yield $emit($data));
        }
    });
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Failure;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
/**
 * Creates a buffered message from an InputStream. The message can be consumed in chunks using the read() API or it may
 * be buffered and accessed in its entirety by waiting for the promise to resolve.
 *
 * Other implementations may extend this class to add custom properties such as a `isBinary()` flag for WebSocket
 * messages.
 *
 * Buffering Example:
 *
 * $stream = new Message($inputStream);
 * $content = yield $stream;
 *
 * Streaming Example:
 *
 * $stream = new Message($inputStream);
 *
 * while (($chunk = yield $stream->read()) !== null) {
 *     // Immediately use $chunk, reducing memory consumption since the entire message is never buffered.
 * }
 *
 * @deprecated Use Amp\ByteStream\Payload instead.
 */
class Message implements InputStream, Promise
{
    /** @var InputStream */
    private $source;
    /** @var string */
    private $buffer = "";
    /** @var Deferred|null */
    private $pendingRead;
    /** @var Coroutine|null */
    private $coroutine;
    /** @var bool True if onResolve() has been called. */
    private $buffering = \false;
    /** @var Deferred|null */
    private $backpressure;
    /** @var bool True if the iterator has completed. */
    private $complete = \false;
    /** @var \Throwable|null Used to fail future reads on failure. */
    private $error;
    /**
     * @param InputStream $source An iterator that only emits strings.
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    private function consume() : \Generator
    {
        while (($chunk = (yield $this->source->read())) !== null) {
            $buffer = $this->buffer .= $chunk;
            if ($buffer === "") {
                continue;
                // Do not succeed reads with empty string.
            } elseif ($this->pendingRead) {
                $deferred = $this->pendingRead;
                $this->pendingRead = null;
                $this->buffer = "";
                $deferred->resolve($buffer);
                $buffer = "";
                // Destroy last emitted chunk to free memory.
            } elseif (!$this->buffering) {
                $buffer = "";
                // Destroy last emitted chunk to free memory.
                $this->backpressure = new Deferred();
                (yield $this->backpressure->promise());
            }
        }
        $this->complete = \true;
        if ($this->pendingRead) {
            $deferred = $this->pendingRead;
            $this->pendingRead = null;
            $deferred->resolve($this->buffer !== "" ? $this->buffer : null);
            $this->buffer = "";
        }
        return $this->buffer;
    }
    /**
     * @inheritdoc
     */
    public final function read() : Promise
    {
        if ($this->pendingRead) {
            throw new PendingReadError();
        }
        if ($this->coroutine === null) {
            $this->coroutine = new Coroutine($this->consume());
            $this->coroutine->onResolve(function ($error) {
                if ($error) {
                    $this->error = $error;
                }
                if ($this->pendingRead) {
                    $deferred = $this->pendingRead;
                    $this->pendingRead = null;
                    $deferred->fail($error);
                }
            });
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->buffer !== "") {
            $buffer = $this->buffer;
            $this->buffer = "";
            if ($this->backpressure) {
                $backpressure = $this->backpressure;
                $this->backpressure = null;
                $backpressure->resolve();
            }
            return new Success($buffer);
        }
        if ($this->complete) {
            return new Success();
        }
        $this->pendingRead = new Deferred();
        return $this->pendingRead->promise();
    }
    /**
     * @inheritdoc
     */
    public final function onResolve(callable $onResolved)
    {
        $this->buffering = \true;
        if ($this->coroutine === null) {
            $this->coroutine = new Coroutine($this->consume());
        }
        if ($this->backpressure) {
            $backpressure = $this->backpressure;
            $this->backpressure = null;
            $backpressure->resolve();
        }
        $this->coroutine->onResolve($onResolved);
    }
    /**
    * Exposes the source input stream.
    *
    * This might be required to resolve a promise with an InputStream, because promises in Amp can't be resolved with
    other promises.
    *
    * @return InputStream
    */
    public final function getInputStream() : InputStream
    {
        return $this->source;
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Promise;
/**
 * An `InputStream` allows reading byte streams in chunks.
 *
 * **Example**
 *
 * ```php
 * function readAll(InputStream $in): Promise {
 *     return Amp\call(function () use ($in) {
 *         $buffer = "";
 *
 *         while (($chunk = yield $in->read()) !== null) {
 *             $buffer .= $chunk;
 *         }
 *
 *         return $buffer;
 *     });
 * }
 * ```
 */
interface InputStream
{
    /**
     * Reads data from the stream.
     *
     * @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
     *
     * @psalm-return Promise<(string | null)>
     *
     * @throws PendingReadError Thrown if another read operation is still pending.
     */
    public function read() : Promise;
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Loop;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
/**
 * Input stream abstraction for PHP's stream resources.
 */
final class ResourceInputStream implements InputStream
{
    const DEFAULT_CHUNK_SIZE = 8192;
    /** @var resource|null */
    private $resource;
    /** @var string */
    private $watcher;
    /** @var Deferred|null */
    private $deferred;
    /** @var bool */
    private $readable = \true;
    /** @var int */
    private $chunkSize;
    /** @var bool */
    private $useSingleRead;
    /** @var callable */
    private $immediateCallable;
    /** @var string|null */
    private $immediateWatcher;
    /**
     * @param resource $stream Stream resource.
     * @param int $chunkSize Chunk size per read operation.
     *
     * @throws \Error If an invalid stream or parameter has been passed.
     */
    public function __construct($stream, int $chunkSize = self::DEFAULT_CHUNK_SIZE)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== 'stream') {
            throw new \Error("Expected a valid stream");
        }
        $meta = \stream_get_meta_data($stream);
        $useSingleRead = $meta["stream_type"] === "udp_socket" || $meta["stream_type"] === "STDIO";
        $this->useSingleRead = $useSingleRead;
        if (\strpos($meta["mode"], "r") === \false && \strpos($meta["mode"], "+") === \false) {
            throw new \Error("Expected a readable stream");
        }
        \stream_set_blocking($stream, \false);
        \stream_set_read_buffer($stream, 0);
        $this->resource =& $stream;
        $this->chunkSize =& $chunkSize;
        $deferred =& $this->deferred;
        $readable =& $this->readable;
        $this->watcher = Loop::onReadable($this->resource, static function ($watcher) use(&$deferred, &$readable, &$stream, &$chunkSize, $useSingleRead) {
            if ($useSingleRead) {
                $data = @\fread($stream, $chunkSize);
            } else {
                $data = @\stream_get_contents($stream, $chunkSize);
            }
            \assert($data !== \false, "Trying to read from a previously fclose()'d resource. Do NOT manually fclose() resources the loop still has a reference to.");
            // Error suppression, because pthreads does crazy things with resources,
            // which might be closed during two operations.
            // See https://github.com/amphp/byte-stream/issues/32
            if ($data === '' && @\feof($stream)) {
                $readable = \false;
                $stream = null;
                $data = null;
                // Stream closed, resolve read with null.
                Loop::cancel($watcher);
            } else {
                Loop::disable($watcher);
            }
            $temp = $deferred;
            $deferred = null;
            \assert($temp instanceof Deferred);
            $temp->resolve($data);
        });
        $this->immediateCallable = static function ($watcherId, $data) use(&$deferred) {
            $temp = $deferred;
            $deferred = null;
            \assert($temp instanceof Deferred);
            $temp->resolve($data);
        };
        Loop::disable($this->watcher);
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        if ($this->deferred !== null) {
            throw new PendingReadError();
        }
        if (!$this->readable) {
            return new Success();
            // Resolve with null on closed stream.
        }
        \assert($this->resource !== null);
        // Attempt a direct read, because Windows suffers from slow I/O on STDIN otherwise.
        if ($this->useSingleRead) {
            $data = @\fread($this->resource, $this->chunkSize);
        } else {
            $data = @\stream_get_contents($this->resource, $this->chunkSize);
        }
        \assert($data !== \false, "Trying to read from a previously fclose()'d resource. Do NOT manually fclose() resources the loop still has a reference to.");
        if ($data === '') {
            // Error suppression, because pthreads does crazy things with resources,
            // which might be closed during two operations.
            // See https://github.com/amphp/byte-stream/issues/32
            if (@\feof($this->resource)) {
                $this->readable = \false;
                $this->resource = null;
                Loop::cancel($this->watcher);
                return new Success();
                // Stream closed, resolve read with null.
            }
            $this->deferred = new Deferred();
            Loop::enable($this->watcher);
            return $this->deferred->promise();
        }
        // Prevent an immediate read â†’ write loop from blocking everything
        // See e.g. examples/benchmark-throughput.php
        $this->deferred = new Deferred();
        $this->immediateWatcher = Loop::defer($this->immediateCallable, $data);
        return $this->deferred->promise();
    }
    /**
     * Closes the stream forcefully. Multiple `close()` calls are ignored.
     *
     * @return void
     */
    public function close()
    {
        if (\is_resource($this->resource)) {
            // Error suppression, as resource might already be closed
            $meta = @\stream_get_meta_data($this->resource);
            if ($meta && \strpos($meta["mode"], "+") !== \false) {
                @\stream_socket_shutdown($this->resource, \STREAM_SHUT_RD);
            } else {
                /** @psalm-suppress InvalidPropertyAssignmentValue */
                @\fclose($this->resource);
            }
        }
        $this->free();
    }
    /**
     * Nulls reference to resource, marks stream unreadable, and succeeds any pending read with null.
     *
     * @return void
     */
    private function free()
    {
        $this->readable = \false;
        $this->resource = null;
        if ($this->deferred !== null) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->resolve();
        }
        Loop::cancel($this->watcher);
        if ($this->immediateWatcher !== null) {
            Loop::cancel($this->immediateWatcher);
        }
    }
    /**
     * @return (resource | null) The stream resource or null if the stream has closed.
     */
    public function getResource()
    {
        return $this->resource;
    }
    /**
     * @return void
     */
    public function setChunkSize(int $chunkSize)
    {
        $this->chunkSize = $chunkSize;
    }
    /**
     * References the read watcher, so the loop keeps running in case there's an active read.
     *
     * @return void
     *
     * @see Loop::reference()
     */
    public function reference()
    {
        if (!$this->resource) {
            throw new \Error("Resource has already been freed");
        }
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the read watcher, so the loop doesn't keep running even if there are active reads.
     *
     * @return void
     *
     * @see Loop::unreference()
     */
    public function unreference()
    {
        if (!$this->resource) {
            throw new \Error("Resource has already been freed");
        }
        Loop::unreference($this->watcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->resource !== null) {
            $this->free();
        }
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
/**
 * Allows decompression of input streams using Zlib.
 */
final class ZlibInputStream implements InputStream
{
    /** @var InputStream|null */
    private $source;
    /** @var int */
    private $encoding;
    /** @var array */
    private $options;
    /** @var resource|null */
    private $resource;
    /**
     * @param InputStream $source Input stream to read compressed data from.
     * @param int $encoding Compression algorithm used, see `inflate_init()`.
     * @param array $options Algorithm options, see `inflate_init()`.
     *
     * @throws StreamException
     * @throws \Error
     *
     * @see http://php.net/manual/en/function.inflate-init.php
     */
    public function __construct(InputStream $source, int $encoding, array $options = [])
    {
        $this->source = $source;
        $this->encoding = $encoding;
        $this->options = $options;
        $this->resource = @\inflate_init($encoding, $options);
        if ($this->resource === \false) {
            throw new StreamException("Failed initializing deflate context");
        }
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        return call(function () {
            if ($this->resource === null) {
                return null;
            }
            \assert($this->source !== null);
            $data = (yield $this->source->read());
            // Needs a double guard, as stream might have been closed while reading
            /** @psalm-suppress ParadoxicalCondition */
            if ($this->resource === null) {
                return null;
            }
            if ($data === null) {
                $decompressed = @\inflate_add($this->resource, "", \ZLIB_FINISH);
                if ($decompressed === \false) {
                    throw new StreamException("Failed adding data to deflate context");
                }
                $this->close();
                return $decompressed;
            }
            $decompressed = @\inflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH);
            if ($decompressed === \false) {
                throw new StreamException("Failed adding data to deflate context");
            }
            return $decompressed;
        });
    }
    /**
     * @internal
     * @return void
     */
    private function close()
    {
        $this->resource = null;
        $this->source = null;
    }
    /**
     * Gets the used compression encoding.
     *
     * @return int Encoding specified on construction time.
     */
    public function getEncoding() : int
    {
        return $this->encoding;
    }
    /**
     * Gets the used compression options.
     *
     * @return array Options array passed on construction time.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

class StreamException extends \Exception
{
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
final class LineReader
{
    /** @var string */
    private $delimiter;
    /** @var bool */
    private $lineMode;
    /** @var string */
    private $buffer = "";
    /** @var InputStream */
    private $source;
    /**
     *
     */
    public function __construct(InputStream $inputStream, string $delimiter = null)
    {
        $this->source = $inputStream;
        $this->delimiter = $delimiter === null ? "\n" : $delimiter;
        $this->lineMode = $delimiter === null;
    }
    /**
     * @return Promise<(string | null)>
     */
    public function readLine() : Promise
    {
        return call(function () {
            if (\false !== \strpos($this->buffer, $this->delimiter)) {
                list($line, $this->buffer) = \explode($this->delimiter, $this->buffer, 2);
                return $this->lineMode ? \rtrim($line, "\r") : $line;
            }
            while (null !== ($chunk = (yield $this->source->read()))) {
                $this->buffer .= $chunk;
                if (\false !== \strpos($this->buffer, $this->delimiter)) {
                    list($line, $this->buffer) = \explode($this->delimiter, $this->buffer, 2);
                    return $this->lineMode ? \rtrim($line, "\r") : $line;
                }
            }
            if ($this->buffer === "") {
                return null;
            }
            $line = $this->buffer;
            $this->buffer = "";
            return $this->lineMode ? \rtrim($line, "\r") : $line;
        });
    }
    /**
     *
     */
    public function getBuffer() : string
    {
        return $this->buffer;
    }
    /**
     * @return void
     */
    public function clearBuffer()
    {
        $this->buffer = "";
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\ByteStream;

final class ClosedException extends StreamException
{
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
/**
 * Creates a buffered message from an InputStream. The message can be consumed in chunks using the read() API or it may
 * be buffered and accessed in its entirety by calling buffer(). Once buffering is requested through buffer(), the
 * stream cannot be read in chunks. On destruct any remaining data is read from the InputStream given to this class.
 */
class Payload implements InputStream
{
    /** @var InputStream */
    private $stream;
    /** @var \Amp\Promise|null */
    private $promise;
    /** @var \Amp\Promise|null */
    private $lastRead;
    /**
     * @param \Amp\ByteStream\InputStream $stream
     */
    public function __construct(InputStream $stream)
    {
        $this->stream = $stream;
    }
    /**
     *
     */
    public function __destruct()
    {
        if (!$this->promise) {
            Promise\rethrow(new Coroutine($this->consume()));
        }
    }
    /**
     *
     */
    private function consume() : \Generator
    {
        try {
            if ($this->lastRead && null === (yield $this->lastRead)) {
                return;
            }
            while (null !== (yield $this->stream->read())) {
                // Discard unread bytes from message.
            }
        } catch (\Throwable $exception) {
            // If exception is thrown here the connection closed anyway.
        }
    }
    /**
     * @inheritdoc
     *
     * @throws \Error If a buffered message was requested by calling buffer().
     */
    public final function read() : Promise
    {
        if ($this->promise) {
            throw new \Error("Cannot stream message data once a buffered message has been requested");
        }
        return $this->lastRead = $this->stream->read();
    }
    /**
     * Buffers the entire message and resolves the returned promise then.
     *
     * @return Promise<string> Resolves with the entire message contents.
     */
    public final function buffer() : Promise
    {
        if ($this->promise) {
            return $this->promise;
        }
        return $this->promise = call(function () {
            $buffer = '';
            if ($this->lastRead && null === (yield $this->lastRead)) {
                return $buffer;
            }
            while (null !== ($chunk = (yield $this->stream->read()))) {
                $buffer .= $chunk;
            }
            return $buffer;
        });
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

/**
 * Thrown in case a second read operation is attempted while another read operation is still pending.
 */
final class PendingReadError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = "The previous read operation must complete before read can be called again", int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Promise;
/**
 * Allows compression of output streams using Zlib.
 */
final class ZlibOutputStream implements OutputStream
{
    /** @var OutputStream|null */
    private $destination;
    /** @var int */
    private $encoding;
    /** @var array */
    private $options;
    /** @var resource|null */
    private $resource;
    /**
     * @param OutputStream $destination Output stream to write the compressed data to.
     * @param int $encoding Compression encoding to use, see `deflate_init()`.
     * @param array $options Compression options to use, see `deflate_init()`.
     *
     * @throws StreamException If an invalid encoding or invalid options have been passed.
     *
     * @see http://php.net/manual/en/function.deflate-init.php
     */
    public function __construct(OutputStream $destination, int $encoding, array $options = [])
    {
        $this->destination = $destination;
        $this->encoding = $encoding;
        $this->options = $options;
        $this->resource = @\deflate_init($encoding, $options);
        if ($this->resource === \false) {
            throw new StreamException("Failed initializing deflate context");
        }
    }
    /**
     * @inheritdoc
     */
    public function write(string $data) : Promise
    {
        if ($this->resource === null) {
            throw new ClosedException("The stream has already been closed");
        }
        \assert($this->destination !== null);
        $compressed = \deflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH);
        if ($compressed === \false) {
            throw new StreamException("Failed adding data to deflate context");
        }
        $promise = $this->destination->write($compressed);
        $promise->onResolve(function ($error) {
            if ($error) {
                $this->close();
            }
        });
        return $promise;
    }
    /**
     * @inheritdoc
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->resource === null) {
            throw new ClosedException("The stream has already been closed");
        }
        \assert($this->destination !== null);
        $compressed = \deflate_add($this->resource, $finalData, \ZLIB_FINISH);
        if ($compressed === \false) {
            throw new StreamException("Failed adding data to deflate context");
        }
        $promise = $this->destination->end($compressed);
        $promise->onResolve(function () {
            $this->close();
        });
        return $promise;
    }
    /**
     * @internal
     * @return void
     */
    private function close()
    {
        $this->resource = null;
        $this->destination = null;
    }
    /**
     * Gets the used compression encoding.
     *
     * @return int Encoding specified on construction time.
     */
    public function getEncoding() : int
    {
        return $this->encoding;
    }
    /**
     * Gets the used compression options.
     *
     * @return array Options array passed on construction time.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
class OutputBuffer implements OutputStream, Promise
{
    /** @var Deferred */
    private $deferred;
    /** @var string */
    private $contents = '';
    /** @var bool */
    private $closed = \false;
    /**
     *
     */
    public function __construct()
    {
        $this->deferred = new Deferred();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->closed) {
            throw new ClosedException("The stream has already been closed.");
        }
        $this->contents .= $data;
        return new Success(\strlen($data));
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->closed) {
            throw new ClosedException("The stream has already been closed.");
        }
        $this->contents .= $finalData;
        $this->closed = \true;
        $this->deferred->resolve($this->contents);
        $this->contents = "";
        return new Success(\strlen($finalData));
    }
    /**
     *
     */
    public function onResolve(callable $onResolved)
    {
        $this->deferred->promise()->onResolve($onResolved);
    }
}
<?php

namespace PhabelVendor\Amp\ByteStream;

use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
/**
 * Input stream with a single already known data chunk.
 */
final class InMemoryStream implements InputStream
{
    private $contents;
    /**
     * @param (string | null) $contents Data chunk or `null` for no data chunk.
     */
    public function __construct(string $contents = null)
    {
        $this->contents = $contents;
    }
    /**
     * Reads data from the stream.
     *
     * @return Promise<(string | null)> Resolves with the full contents or `null` if the stream has closed / already been consumed.
     */
    public function read() : Promise
    {
        if ($this->contents === null) {
            return new Success();
        }
        $promise = new Success($this->contents);
        $this->contents = null;
        return $promise;
    }
}
<?php

namespace PhabelVendor\Amp\Parser;

class InvalidDelimiterError extends \Error
{
    /**
     * @param \Generator $generator
     * @param string $prefix
     * @param (\Throwable | null) $previous
     */
    public function __construct(\Generator $generator, string $prefix, \Throwable $previous = null)
    {
        $yielded = $generator->current();
        $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), \var_export($generator->key(), \true));
        if (!$generator->valid()) {
            parent::__construct($prefix, 0, $previous);
            return;
        }
        $reflGen = new \ReflectionGenerator($generator);
        $exeGen = $reflGen->getExecutingGenerator();
        if ($isSubgenerator = $exeGen !== $generator) {
            $reflGen = new \ReflectionGenerator($exeGen);
        }
        parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile()), 0, $previous);
    }
}
<?php

namespace PhabelVendor\Amp\Parser;

class Parser
{
    /** @var \Generator */
    private $generator;
    /** @var string */
    private $buffer = '';
    /** @var int|string|null */
    private $delimiter;
    /**
     * @param \Generator $generator
     *
     * @throws InvalidDelimiterError If the generator yields an invalid delimiter.
     * @throws \Throwable If the generator throws.
     */
    public function __construct(\Generator $generator)
    {
        $this->generator = $generator;
        $this->delimiter = $this->generator->current();
        if (!$this->generator->valid()) {
            $this->generator = null;
            return;
        }
        if ($this->delimiter !== null && (!\is_int($this->delimiter) || $this->delimiter <= 0) && (!\is_string($this->delimiter) || !\strlen($this->delimiter))) {
            throw new InvalidDelimiterError($generator, \sprintf("Invalid value yielded: Expected NULL, an int greater than 0, or a non-empty string; %s given", \is_object($this->delimiter) ? \sprintf("instance of %s", \get_class($this->delimiter)) : \gettype($this->delimiter)));
        }
    }
    /**
    * Cancels the generator parser and returns any remaining data in the internal buffer. Writing data after calling
    this method will result in an error.
    *
    * @return string
    */
    public final function cancel() : string
    {
        $this->generator = null;
        return $this->buffer;
    }
    /**
    * @return bool True if the parser can still receive more data to parse, false if it has ended and calling push
    will throw an exception.
    */
    public final function isValid() : bool
    {
        return $this->generator !== null;
    }
    /**
     * Adds data to the internal buffer and tries to continue parsing.
     *
     * @param string $data Data to append to the internal buffer.
     *
     * @throws InvalidDelimiterError If the generator yields an invalid delimiter.
     * @throws \Error If parsing has already been cancelled.
     * @throws \Throwable If the generator throws.
     */
    public final function push(string $data)
    {
        if ($this->generator === null) {
            throw new \Error("The parser is no longer writable");
        }
        $this->buffer .= $data;
        $end = \false;
        try {
            while ($this->buffer !== "") {
                if (\is_int($this->delimiter)) {
                    if (\strlen($this->buffer) < $this->delimiter) {
                        break;
                        // Too few bytes in buffer.
                    }
                    $send = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $this->delimiter);
                    $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->delimiter);
                } elseif (\is_string($this->delimiter)) {
                    if (($position = \strpos($this->buffer, $this->delimiter)) === \false) {
                        break;
                    }
                    $send = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $position);
                    $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $position + \strlen($this->delimiter));
                } else {
                    $send = $this->buffer;
                    $this->buffer = "";
                }
                $this->delimiter = $this->generator->send($send);
                if (!$this->generator->valid()) {
                    $end = \true;
                    break;
                }
                if ($this->delimiter !== null && (!\is_int($this->delimiter) || $this->delimiter <= 0) && (!\is_string($this->delimiter) || !\strlen($this->delimiter))) {
                    throw new InvalidDelimiterError($this->generator, \sprintf("Invalid value yielded: Expected NULL, an int greater than 0, or a non-empty string; %s given", \is_object($this->delimiter) ? \sprintf("instance of %s", \get_class($this->delimiter)) : \gettype($this->delimiter)));
                }
            }
        } catch (\Throwable $exception) {
            $end = \true;
            throw $exception;
        } finally {
            if ($end) {
                $this->generator = null;
            }
        }
    }
}
{
    "symbol-whitelist": [
        "null",
        "true",
        "false",
        "static",
        "self",
        "parent",
        "array",
        "string",
        "int",
        "float",
        "bool",
        "iterable",
        "callable",
        "void",
        "object",
        "MSG_EAGAIN",
        "MSG_ENOMSG",
        "msg_get_queue",
        "MSG_IPC_NOWAIT",
        "msg_queue_exists",
        "msg_receive",
        "msg_remove_queue",
        "msg_send",
        "msg_set_queue",
        "msg_stat_queue",
        "Threaded",
        "transform",
        "SysvMessageQueue"
    ],
    "php-core-extensions": [
        "Core",
        "date",
        "pcre",
        "Phar",
        "Reflection",
        "SPL",
        "standard"
    ]
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
final class PrefixedKeyedSemaphore implements KeyedSemaphore
{
    /** @var KeyedSemaphore */
    private $semaphore;
    /** @var string */
    private $prefix;
    /**
     *
     */
    public function __construct(KeyedSemaphore $semaphore, string $prefix)
    {
        $this->semaphore = $semaphore;
        $this->prefix = $prefix;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        return $this->semaphore->acquire($this->prefix . $key);
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
final class LocalKeyedSemaphore implements KeyedSemaphore
{
    /** @var LocalSemaphore[] */
    private $semaphore = [];
    /** @var int[] */
    private $locks = [];
    /** @var int */
    private $maxLocks;
    /**
     *
     */
    public function __construct(int $maxLocks)
    {
        $this->maxLocks = $maxLocks;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        if (!isset($this->semaphore[$key])) {
            $this->semaphore[$key] = new LocalSemaphore($this->maxLocks);
            $this->locks[$key] = 0;
        }
        return call(function () use($key) {
            $this->locks[$key]++;
            /** @var Lock $lock */
            $lock = (yield $this->semaphore[$key]->acquire());
            return new Lock(0, function () use($lock, $key) {
                if (--$this->locks[$key] === 0) {
                    unset($this->semaphore[$key], $this->locks[$key]);
                }
                $lock->release();
            });
        });
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
/**
* Invokes the given callback while maintaining a lock from the provided mutex. The lock is automatically released after
invoking the callback or once the promise returned by the callback is resolved. If the callback returns a Generator,
it will be run as a coroutine. See Amp\call().
*
* @param Mutex $mutex
* @param callable $callback
* @param array ...$args
*
* @return Promise Resolves with the return value of the callback.
*/
function synchronized(Mutex $mutex, callable $callback, ...$args) : Promise
{
    return call(static function () use($mutex, $callback, $args) : \Generator {
        /** @var Lock $lock */
        $lock = (yield $mutex->acquire());
        try {
            return (yield call($callback, ...$args));
        } finally {
            $lock->release();
        }
    });
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
/**
 * A non-blocking counting semaphore.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface Semaphore
{
    /**
    * Acquires a lock on the semaphore.
    *
    * @return Promise<Lock> Resolves with an integer keyed lock object. Identifiers returned by the
    locks should be 0-indexed. Releasing an identifier MUST make that same identifier available. May fail with
    a SyncException if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire() : Promise;
}
<?php

namespace PhabelVendor\Amp\Sync\Internal;

use PhabelVendor\Amp\Delayed;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Sync\Lock;
use function PhabelVendor\Amp\call;
/** @internal */
final class SemaphoreStorage extends \Threaded
{
    public const LATENCY_TIMEOUT = 10;
    /**
     * Creates a new semaphore with a given number of locks.
     *
     * @param int $locks The maximum number of locks that can be acquired from the semaphore.
     */
    public function __construct(int $locks)
    {
        foreach (\range(0, $locks - 1) as $lock) {
            $this[] = $lock;
        }
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        /**
         * Uses a double locking mechanism to acquire a lock without blocking. A
         * synchronous mutex is used to make sure that the semaphore is queried one
         * at a time to preserve the integrity of the semaphore itself. Then a lock
         * count is used to check if a lock is available without blocking.
         *
         * If a lock is not available, we add the request to a queue and set a timer
         * to check again in the future.
         */
        return call(function () : \Generator {
            $tsl = function () : ?int {
                // If there are no locks available or the wait queue is not empty,
                // we need to wait our turn to acquire a lock.
                if (!$this->count()) {
                    return null;
                }
                return $this->shift();
            };
            while (!$this->count() || ($id = $this->synchronized($tsl)) === null) {
                (yield new Delayed(self::LATENCY_TIMEOUT));
            }
            return new Lock($id, function (Lock $lock) : void {
                $id = $lock->getId();
                $this->synchronized(function () use($id) {
                    $this[] = $id;
                });
            });
        });
    }
}
<?php

namespace PhabelVendor\Amp\Sync\Internal;

use PhabelVendor\Amp\Delayed;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Sync\Lock;
use function PhabelVendor\Amp\call;
/** @internal */
final class MutexStorage extends \Threaded
{
    public const LATENCY_TIMEOUT = 10;
    /** @var bool */
    private $locked = \false;
    /**
     *
     */
    public function acquire() : Promise
    {
        return call(function () : \Generator {
            $tsl = function () : bool {
                if ($this->locked) {
                    return \true;
                }
                $this->locked = \true;
                return \false;
            };
            while ($this->locked || $this->synchronized($tsl)) {
                (yield new Delayed(self::LATENCY_TIMEOUT));
            }
            return new Lock(0, function () : void {
                $this->locked = \false;
            });
        });
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

class SyncException extends \Exception
{
}
<?php

namespace PhabelVendor\Amp\Sync\ConcurrentIterator;

use PhabelVendor\Amp\CancelledException;
use PhabelVendor\Amp\Iterator;
use PhabelVendor\Amp\Producer;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Sync\Barrier;
use PhabelVendor\Amp\Sync\Lock;
use PhabelVendor\Amp\Sync\Semaphore;
use function PhabelVendor\Amp\asyncCall;
use function PhabelVendor\Amp\call;
use function PhabelVendor\Amp\coroutine;
/**
* Concurrently act on iterator values using {@code $processor}.
*
* @param Iterator $iterator Values to process.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Iterator Result values.
*/
function transform(Iterator $iterator, Semaphore $semaphore, callable $processor) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $semaphore, $processor) {
        // one dummy item, because we can't start the barrier with a count of zero
        $barrier = new Barrier(1);
        /** @var \Throwable|null $error */
        $error = null;
        $locks = [];
        $gc = \false;
        $processor = coroutine($processor);
        $processor = static function (Lock $lock, $currentElement) use($processor, $emit, $barrier, &$locks, &$error, &$gc) {
            $done = \false;
            try {
                (yield $processor($currentElement, $emit));
                $done = \true;
            } catch (\Throwable $e) {
                $error = $error ?? $e;
                $done = \true;
            } finally {
                if (!$done) {
                    $gc = \true;
                }
                unset($locks[$lock->getId()]);
                $lock->release();
                $barrier->arrive();
            }
        };
        while ((yield $iterator->advance())) {
            if ($error) {
                break;
            }
            /** @var Lock $lock */
            $lock = (yield $semaphore->acquire());
            if ($gc || isset($locks[$lock->getId()])) {
                // Throwing here causes a segfault on PHP 7.3
                return;
                // throw new CancelledException; // producer and locks have been GCed
            }
            $locks[$lock->getId()] = \true;
            $barrier->register();
            asyncCall($processor, $lock, $iterator->getCurrent());
        }
        $barrier->arrive();
        // remove dummy item
        (yield $barrier->await());
        if ($error) {
            throw $error;
        }
    });
}
/**
* Concurrently map all iterator values using {@code $processor}.
*
* The order of the items in the resulting iterator is not guaranteed in any way.
*
* @param Iterator $iterator Values to map.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Iterator Mapped values.
*/
function map(Iterator $iterator, Semaphore $semaphore, callable $processor) : Iterator
{
    $processor = coroutine($processor);
    return transform($iterator, $semaphore, static function ($value, callable $emit) use($processor) {
        $value = (yield $processor($value));
        (yield $emit($value));
    });
}
/**
* Concurrently filter all iterator values using {@code $filter}.
*
* The order of the items in the resulting iterator is not guaranteed in any way.
*
* @param Iterator $iterator Values to map.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $filter Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted. Must resolve to a boolean, true to keep values in the resulting
iterator.
*
* @return Iterator Values, where {@code $filter} resolved to {@code true}.
*/
function filter(Iterator $iterator, Semaphore $semaphore, callable $filter) : Iterator
{
    $filter = coroutine($filter);
    return transform($iterator, $semaphore, static function ($value, callable $emit) use($filter) {
        $keep = (yield $filter($value));
        if (!\is_bool($keep)) {
            throw new \TypeError(__NAMESPACE__ . '\\filter\'s callable must resolve to a boolean value, got ' . \gettype($keep));
        }
        if ($keep) {
            (yield $emit($value));
        }
    });
}
/**
* Concurrently invoke a callback on all iterator values using {@code $processor}.
*
* @param Iterator $iterator Values to act on.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Promise
*/
function each(Iterator $iterator, Semaphore $semaphore, callable $processor) : Promise
{
    $processor = coroutine($processor);
    $iterator = transform($iterator, $semaphore, static function ($value, callable $emit) use($processor) {
        (yield $processor($value));
        (yield $emit(null));
    });
    // Use Amp\Iterator\discard in the future
    return call(static function () use($iterator) {
        $count = 0;
        while ((yield $iterator->advance())) {
            $count++;
        }
        return $count;
    });
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
/**
 * A non-blocking synchronization primitive that can be used for mutual exclusion across contexts.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface Mutex extends Semaphore
{
    /**
    * Acquires a lock on the mutex.
    *
    * @return Promise<Lock> Resolves with a lock object with an ID of 0. May fail with a SyncException
    if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire() : Promise;
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
/**
 * An asynchronous semaphore based on pthreads' synchronization methods.
 *
 * This is an implementation of a thread-safe semaphore that has non-blocking
 * acquire methods. There is a small tradeoff for asynchronous semaphores; you
 * may not acquire a lock immediately when one is available and there may be a
 * small delay. However, the small delay will not block the thread.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
class ThreadedSemaphore implements Semaphore
{
    /** @var \Threaded */
    private $semaphore;
    /**
     * Creates a new semaphore with a given number of locks.
     *
     * @param int $locks The maximum number of locks that can be acquired from the semaphore.
     */
    public function __construct(int $locks)
    {
        if ($locks < 1) {
            throw new \Error("The number of locks should be a positive integer");
        }
        $this->semaphore = new Internal\SemaphoreStorage($locks);
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return $this->semaphore->acquire();
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
final class StaticKeyMutex implements Mutex
{
    /** @var KeyedMutex */
    private $mutex;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(KeyedMutex $mutex, string $key)
    {
        $this->mutex = $mutex;
        $this->key = $key;
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        return $this->mutex->acquire($this->key);
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Delayed;
use PhabelVendor\Amp\Promise;
/**
 * A non-blocking, inter-process POSIX semaphore.
 *
 * Uses a POSIX message queue to store a queue of permits in a lock-free data structure. This semaphore implementation
 * is preferred over other implementations when available, as it provides the best performance.
 *
 * Not compatible with Windows.
 */
class PosixSemaphore implements Semaphore
{
    public const LATENCY_TIMEOUT = 10;
    /** @var string */
    private $id;
    /** @var int The semaphore key. */
    private $key;
    /** @var int PID of the process that created the semaphore. */
    private $initializer = 0;
    /** @var resource A message queue of available locks. */
    private $queue;
    /**
     * Creates a new semaphore with a given ID and number of locks.
     *
     * @param string $id The unique name for the new semaphore.
     * @param int $maxLocks The maximum number of locks that can be acquired from the semaphore.
     * @param int $permissions Permissions to access the semaphore. Use file permission format specified as 0xxx.
     *
     * @return PosixSemaphore
     * @throws SyncException If the semaphore could not be created due to an internal error.
     */
    public static function create(string $id, int $maxLocks, int $permissions = 0600) : self
    {
        if ($maxLocks < 1) {
            throw new \Error('Number of locks must be greater than 0');
        }
        $semaphore = new self($id);
        $semaphore->init($maxLocks, $permissions);
        return $semaphore;
    }
    /**
     * @param string $id The unique name of the semaphore to use.
     *
     * @return \Amp\Sync\PosixSemaphore
     */
    public static function use(string $id) : self
    {
        $semaphore = new self($id);
        $semaphore->open();
        return $semaphore;
    }
    /**
     * @param string $id
     *
     * @throws \Error If the sysvmsg extension is not loaded.
     */
    private function __construct(string $id)
    {
        if (!\extension_loaded("sysvmsg")) {
            throw new \Error(__CLASS__ . " requires the sysvmsg extension.");
        }
        $this->id = $id;
        $this->key = self::makeKey($this->id);
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * Prevent serialization.
     */
    public function __sleep()
    {
        throw new \Error('A semaphore cannot be serialized!');
    }
    /**
     *
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     *
     */
    private function open() : void
    {
        if (!\msg_queue_exists($this->key)) {
            throw new SyncException('No semaphore with that ID found');
        }
        $this->queue = \msg_get_queue($this->key);
        if (!$this->queue) {
            throw new SyncException('Failed to open the semaphore.');
        }
    }
    /**
     * @param int $maxLocks The maximum number of locks that can be acquired from the semaphore.
     * @param int $permissions Permissions to access the semaphore.
     *
     * @throws SyncException If the semaphore could not be created due to an internal error.
     */
    private function init(int $maxLocks, int $permissions) : void
    {
        if (\msg_queue_exists($this->key)) {
            throw new SyncException('A semaphore with that ID already exists');
        }
        $this->queue = \msg_get_queue($this->key, $permissions);
        if (!$this->queue) {
            throw new SyncException('Failed to create the semaphore.');
        }
        $this->initializer = \getmypid();
        // Fill the semaphore with locks.
        while (--$maxLocks >= 0) {
            $this->release($maxLocks);
        }
    }
    /**
     * Gets the access permissions of the semaphore.
     *
     * @return int A permissions mode.
     */
    public function getPermissions() : int
    {
        $stat = \msg_stat_queue($this->queue);
        return $stat['msg_perm.mode'];
    }
    /**
     * Sets the access permissions of the semaphore.
     *
     * The current user must have access to the semaphore in order to change the permissions.
     *
     * @param int $mode A permissions mode to set.
     *
     * @throws SyncException If the operation failed.
     */
    public function setPermissions(int $mode)
    {
        if (!\msg_set_queue($this->queue, ['msg_perm.mode' => $mode])) {
            throw new SyncException('Failed to change the semaphore permissions.');
        }
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        return new Coroutine($this->doAcquire());
    }
    /**
     * {@inheritdoc}
     */
    private function doAcquire() : \Generator
    {
        do {
            // Attempt to acquire a lock from the semaphore.
            if (@\msg_receive($this->queue, 0, $type, 1, $id, \false, \MSG_IPC_NOWAIT, $errno)) {
                // A free lock was found, so resolve with a lock object that can
                // be used to release the lock.
                return new Lock(\unpack("C", $id)[1], function (Lock $lock) {
                    $this->release($lock->getId());
                });
            }
            // Check for unusual errors.
            if ($errno !== \MSG_ENOMSG) {
                throw new SyncException(\sprintf('Failed to acquire a lock; errno: %d', $errno));
            }
        } while ((yield new Delayed(self::LATENCY_TIMEOUT, \true)));
    }
    /**
     * Removes the semaphore if it still exists.
     *
     * @throws SyncException If the operation failed.
     */
    public function __destruct()
    {
        if ($this->initializer === 0 || $this->initializer !== \getmypid()) {
            return;
        }
        if (\PHP_VERSION_ID < 80000 && (!\is_resource($this->queue) || !\msg_queue_exists($this->key))) {
            return;
        }
        if (\PHP_VERSION_ID >= 80000 && (!$this->queue instanceof \SysvMessageQueue || !\msg_queue_exists($this->key))) {
            return;
        }
        \msg_remove_queue($this->queue);
    }
    /**
     * Releases a lock from the semaphore.
     *
     * @param int $id Lock identifier.
     *
     * @throws SyncException If the operation failed.
     */
    protected function release(int $id)
    {
        if (!$this->queue) {
            return;
            // Queue already destroyed.
        }
        // Call send in non-blocking mode. If the call fails because the queue
        // is full, then the number of locks configured is too large.
        if (!@\msg_send($this->queue, 1, \pack("C", $id), \false, \false, $errno)) {
            if ($errno === \MSG_EAGAIN) {
                throw new SyncException('The semaphore size is larger than the system allows.');
            }
            throw new SyncException('Failed to release the lock.');
        }
    }
    /**
     *
     */
    private static function makeKey(string $id) : int
    {
        return \abs(\unpack("l", \md5($id, \true))[1]);
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
final class LocalKeyedMutex implements KeyedMutex
{
    /** @var LocalMutex[] */
    private $mutex = [];
    /** @var int[] */
    private $locks = [];
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        if (!isset($this->mutex[$key])) {
            $this->mutex[$key] = new LocalMutex();
            $this->locks[$key] = 0;
        }
        return call(function () use($key) {
            $this->locks[$key]++;
            /** @var Lock $lock */
            $lock = (yield $this->mutex[$key]->acquire());
            return new Lock(0, function () use($lock, $key) {
                if (--$this->locks[$key] === 0) {
                    unset($this->mutex[$key], $this->locks[$key]);
                }
                $lock->release();
            });
        });
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Promise;
/**
 * A barrier is a synchronization primitive.
 *
 * The barrier is initialized with a certain count, which can be increased and decreased until it reaches zero.
 *
 * A count of one can be used to block multiple coroutines until a certain condition is met.
 *
 * A count of N can be used to await multiple coroutines doing an action to complete.
 *
 * **Example**
 *
 * ```php
 * $barrier = new Amp\Sync\Barrier(2);
 * $barrier->arrive();
 * $barrier->arrive(); // promise returned from Barrier::await() is now resolved
 *
 * yield $barrier->await();
 * ```
 */
final class Barrier
{
    /** @var int */
    private $count;
    /** @var Deferred */
    private $deferred;
    /**
     *
     */
    public function __construct(int $count)
    {
        if ($count < 1) {
            throw new \Error('Count must be positive, got ' . $count);
        }
        $this->count = $count;
        $this->deferred = new Deferred();
    }
    /**
     *
     */
    public function getCount() : int
    {
        return $this->count;
    }
    /**
     *
     */
    public function arrive(int $count = 1) : void
    {
        if ($count < 1) {
            throw new \Error('Count must be at least 1, got ' . $count);
        }
        if ($count > $this->count) {
            throw new \Error('Count cannot be greater than remaining count: ' . $count . ' > ' . $this->count);
        }
        $this->count -= $count;
        if ($this->count === 0) {
            $this->deferred->resolve();
        }
    }
    /**
     *
     */
    public function register(int $count = 1) : void
    {
        if ($count < 1) {
            throw new \Error('Count must be at least 1, got ' . $count);
        }
        if ($this->count === 0) {
            throw new \Error('Can\'t increase count, because the barrier already broke');
        }
        $this->count += $count;
    }
    /**
     *
     */
    public function await() : Promise
    {
        return $this->deferred->promise();
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\CallableMaker;
use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
class LocalSemaphore implements Semaphore
{
    use CallableMaker;
    // kept for BC only
    /** @var int[] */
    private $locks;
    /** @var Deferred[] */
    private $queue = [];
    /**
     *
     */
    public function __construct(int $maxLocks)
    {
        if ($maxLocks < 1) {
            throw new \Error('The number of locks must be greater than 0');
        }
        $this->locks = \range(0, $maxLocks - 1);
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        if (!empty($this->locks)) {
            return new Success(new Lock(\array_shift($this->locks), \Closure::fromCallable([$this, 'release'])));
        }
        $this->queue[] = $deferred = new Deferred();
        return $deferred->promise();
    }
    /**
     *
     */
    private function release(Lock $lock) : void
    {
        $id = $lock->getId();
        if (!empty($this->queue)) {
            $deferred = \array_shift($this->queue);
            $deferred->resolve(new Lock($id, \Closure::fromCallable([$this, 'release'])));
            return;
        }
        $this->locks[] = $id;
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
final class PrefixedKeyedMutex implements KeyedMutex
{
    /** @var KeyedMutex */
    private $mutex;
    /** @var string */
    private $prefix;
    /**
     *
     */
    public function __construct(KeyedMutex $mutex, string $prefix)
    {
        $this->mutex = $mutex;
        $this->prefix = $prefix;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        return $this->mutex->acquire($this->prefix . $key);
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
/**
 * A thread-safe, asynchronous mutex using the pthreads locking mechanism.
 *
 * Compatible with POSIX systems and Microsoft Windows.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
class ThreadedMutex implements Mutex
{
    /** @var Internal\MutexStorage */
    private $mutex;
    /**
     * Creates a new threaded mutex.
     */
    public function __construct()
    {
        $this->mutex = new Internal\MutexStorage();
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return $this->mutex->acquire();
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
/**
 * A non-blocking counting semaphore based on keys.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface KeyedSemaphore
{
    /**
    * Acquires a lock on the semaphore.
    *
    * @param string $key Lock key
    *
    * @return Promise<Lock> Resolves with an integer keyed lock object. Identifiers returned by the
    locks should be 0-indexed. Releasing an identifier MUST make that same identifier available. May fail with
    a SyncException if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire(string $key) : Promise;
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Coroutine;
use PhabelVendor\Amp\Delayed;
use PhabelVendor\Amp\Promise;
/**
 * A cross-platform mutex that uses exclusive files as the lock mechanism.
 *
 * This mutex implementation is not always atomic and depends on the operating
 * system's implementation of file creation operations. Use this implementation
 * only if no other mutex types are available.
 *
 * This implementation avoids using [flock()](https://www.php.net/flock)
 * because flock() is known to have some atomicity issues on some systems. In
 * addition, flock() does not work as expected when trying to lock a file
 * multiple times in the same process on Linux. Instead, exclusive file creation
 * is used to create a lock file, which is atomic on most systems.
 *
 * @see https://www.php.net/fopen
 */
class FileMutex implements Mutex
{
    public const LATENCY_TIMEOUT = 10;
    /** @var string The full path to the lock file. */
    private $fileName;
    /**
     * @param string $fileName Name of temporary file to use as a mutex.
     */
    public function __construct(string $fileName)
    {
        $this->fileName = $fileName;
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return new Coroutine($this->doAcquire());
    }
    /**
     * @coroutine
     *
     * @return \Generator
     */
    private function doAcquire() : \Generator
    {
        // Try to create the lock file. If the file already exists, someone else
        // has the lock, so set an asynchronous timer and try again.
        while (($handle = @\fopen($this->fileName, 'x')) === \false) {
            (yield new Delayed(self::LATENCY_TIMEOUT));
        }
        // Return a lock object that can be used to release the lock on the mutex.
        $lock = new Lock(0, function () : void {
            $this->release();
        });
        \fclose($handle);
        return $lock;
    }
    /**
     * Releases the lock on the mutex.
     *
     * @throws SyncException If the unlock operation failed.
     */
    protected function release()
    {
        $success = @\unlink($this->fileName);
        if (!$success) {
            throw new SyncException('Failed to unlock the mutex file.');
        }
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

/**
 * A handle on an acquired lock from a synchronization object.
 *
 * This object is not thread-safe; after acquiring a lock from a mutex or
 * semaphore, the lock should reside in the same thread or process until it is
 * released.
 */
class Lock
{
    /** @var callable|null The function to be called on release or null if the lock has been released. */
    private $releaser;
    /** @var int */
    private $id;
    /**
     * Creates a new lock permit object.
     *
     * @param int $id The lock identifier.
     * @param callable(self ): void $releaser A function to be called upon release.
     */
    public function __construct(int $id, callable $releaser)
    {
        $this->id = $id;
        $this->releaser = $releaser;
    }
    /**
     * Checks if the lock has already been released.
     *
     * @return bool True if the lock has already been released, otherwise false.
     */
    public function isReleased() : bool
    {
        return !$this->releaser;
    }
    /**
     * @return int Lock identifier.
     */
    public function getId() : int
    {
        return $this->id;
    }
    /**
     * Releases the lock. No-op if the lock has already been released.
     */
    public function release()
    {
        if (!$this->releaser) {
            return;
        }
        // Invoke the releaser function given to us by the synchronization source
        // to release the lock.
        $releaser = $this->releaser;
        $this->releaser = null;
        $releaser($this);
    }
    /**
     * Releases the lock when there are no more references to it.
     */
    public function __destruct()
    {
        if (!$this->isReleased()) {
            $this->release();
        }
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
use function PhabelVendor\Amp\call;
class SemaphoreMutex implements Mutex
{
    /** @var Semaphore */
    private $semaphore;
    /**
     * @param Semaphore $semaphore A semaphore with a single lock.
     */
    public function __construct(Semaphore $semaphore)
    {
        $this->semaphore = $semaphore;
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return call(function () : \Generator {
            /** @var \Amp\Sync\Lock $lock */
            $lock = (yield $this->semaphore->acquire());
            if ($lock->getId() !== 0) {
                $lock->release();
                throw new \Error("Cannot use a semaphore with more than a single lock");
            }
            return $lock;
        });
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.functions.php';<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\CallableMaker;
use PhabelVendor\Amp\Deferred;
use PhabelVendor\Amp\Promise;
use PhabelVendor\Amp\Success;
class LocalMutex implements Mutex
{
    use CallableMaker;
    // kept for BC only
    /** @var bool */
    private $locked = \false;
    /** @var Deferred[] */
    private $queue = [];
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        if (!$this->locked) {
            $this->locked = \true;
            return new Success(new Lock(0, \Closure::fromCallable([$this, 'release'])));
        }
        $this->queue[] = $deferred = new Deferred();
        return $deferred->promise();
    }
    /**
     *
     */
    private function release() : void
    {
        if (!empty($this->queue)) {
            $deferred = \array_shift($this->queue);
            $deferred->resolve(new Lock(0, \Closure::fromCallable([$this, 'release'])));
            return;
        }
        $this->locked = \false;
    }
}
<?php

namespace PhabelVendor\Amp\Sync;

use PhabelVendor\Amp\Promise;
/**
 * A non-blocking synchronization primitive that can be used for mutual exclusion across contexts based on keys.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface KeyedMutex extends KeyedSemaphore
{
    /**
    * Acquires a lock on the mutex.
    *
    * @param string $key Lock key
    *
    * @return Promise<Lock> Resolves with a lock object with an ID of 0. May fail with a SyncException
    if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire(string $key) : Promise;
}
<?php

namespace PhabelVendor;

use Phabel\Target\Php;
use Phabel\Traverser;
if (!\file_exists('composer.json')) {
    echo "This script must be run from package root" . \PHP_EOL;
    die(1);
}
require 'vendor/autoload.php';
if ($argc < 2) {
    $help = <<<EOF
Usage: {$argv[0]} target [ dry ]

target - Target version
dry - 0 or 1, whether to dry-run conversion

EOF;
    echo $help;
    die(1);
}
$target = $argv[1];
$dry = (bool) ($argv[2] ?? '');
if (!\file_exists('phabelConverted')) {
    \mkdir('phabelConverted');
}
\passthru("git stash");
$branch = \trim(\shell_exec("git rev-parse --abbrev-ref HEAD"));
foreach ($target === 'all' ? Php::VERSIONS : [$target] as $realTarget) {
    if (!$dry) {
        \passthru("git branch -D phabel_tmp");
        \passthru("git branch phabel_tmp");
        \passthru("git checkout phabel_tmp");
    }
    foreach (['8.0', $realTarget] as $target) {
        $coverage = \getenv('PHABEL_COVERAGE') ?: '';
        if ($coverage) {
            $coverage .= "-{$target}";
        }
        $packages = [];
        foreach (['tools', 'src', 'bin', 'test', 'test_old', 'lib'] as $dir) {
            if (!\file_exists($dir)) {
                continue;
            }
            $packages += Traverser::run([Php::class => ['target' => $target]], $dir, $dir, $coverage);
        }
        $str = (string) $target;
        $packages["php"] = ">={$str[0]}.{$str[1]}";
        if (!empty($packages)) {
            $cmd = "composer require ";
            foreach ($packages as $package => $constraint) {
                $cmd .= \escapeshellarg("{$package}:{$constraint}") . " ";
            }
            \passthru($cmd);
        }
        \passthru("composer cs-fix");
        if (!$dry) {
            \passthru("git add -A");
            \passthru("git commit -m " . \escapeshellarg("phabel.io: transpile to {$target}"));
        }
    }
    if (!$dry) {
        \passthru("git push -f origin " . \escapeshellarg("phabel_tmp:{$branch}-{$target}"));
        \passthru("git checkout " . \escapeshellarg($branch));
        \passthru("git branch -D phabel_tmp");
    }
    \passthru("git reset --hard");
}
\passthru("git stash pop");
<?php

namespace PhabelVendor;

require __DIR__ . '/phpyLang.php';
$grammarFileToName = [__DIR__ . '/php5.y' => 'Php5', __DIR__ . '/php7.y' => 'Php7'];
$tokensFile = __DIR__ . '/tokens.y';
$tokensTemplate = __DIR__ . '/tokens.template';
$skeletonFile = __DIR__ . '/parser.template';
$tmpGrammarFile = __DIR__ . '/tmp_parser.phpy';
$tmpResultFile = __DIR__ . '/tmp_parser.php';
$resultDir = __DIR__ . '/../lib/PhpParser/Parser';
$tokensResultsFile = $resultDir . '/Tokens.php';
$kmyacc = \getenv('KMYACC');
if (!$kmyacc) {
    // Use phpyacc from dev dependencies by default.
    $kmyacc = __DIR__ . '/../vendor/bin/phpyacc';
}
$options = \array_flip($argv);
$optionDebug = isset($options['--debug']);
$optionKeepTmpGrammar = isset($options['--keep-tmp-grammar']);
///////////////////
/// Main script ///
///////////////////
$tokens = \file_get_contents($tokensFile);
foreach ($grammarFileToName as $grammarFile => $name) {
    echo "Building temporary {$name} grammar file.\n";
    $grammarCode = \file_get_contents($grammarFile);
    $grammarCode = \str_replace('%tokens', $tokens, $grammarCode);
    $grammarCode = preprocessGrammar($grammarCode);
    \file_put_contents($tmpGrammarFile, $grammarCode);
    $additionalArgs = $optionDebug ? '-t -v' : '';
    echo "Building {$name} parser.\n";
    $output = execCmd("{$kmyacc} {$additionalArgs} -m {$skeletonFile} -p {$name} {$tmpGrammarFile}");
    $resultCode = \file_get_contents($tmpResultFile);
    $resultCode = removeTrailingWhitespace($resultCode);
    ensureDirExists($resultDir);
    \file_put_contents("{$resultDir}/{$name}.php", $resultCode);
    \unlink($tmpResultFile);
    echo "Building token definition.\n";
    $output = execCmd("{$kmyacc} -m {$tokensTemplate} {$tmpGrammarFile}");
    \rename($tmpResultFile, $tokensResultsFile);
    if (!$optionKeepTmpGrammar) {
        \unlink($tmpGrammarFile);
    }
}
////////////////////////////////
/// Utility helper functions ///
////////////////////////////////
/**
 *
 */
function ensureDirExists($dir)
{
    if (!\is_dir($dir)) {
        \mkdir($dir, 0777, \true);
    }
}
/**
 *
 */
function execCmd($cmd)
{
    $output = \trim(\shell_exec("{$cmd} 2>&1"));
    if ($output !== "") {
        echo "> " . $cmd . "\n";
        echo $output;
    }
    return $output;
}
<?php

namespace PhabelVendor;

///////////////////////////////
/// Utility regex constants ///
///////////////////////////////
const LIB = '(?(DEFINE)
    (?<singleQuotedString>\'[^\\\\\']*+(?:\\\\.[^\\\\\']*+)*+\')
    (?<doubleQuotedString>"[^\\\\"]*+(?:\\\\.[^\\\\"]*+)*+")
    (?<string>(?&singleQuotedString)|(?&doubleQuotedString))
    (?<comment>/\\*[^*]*+(?:\\*(?!/)[^*]*+)*+\\*/)
    (?<code>\\{[^\'"/{}]*+(?:(?:(?&string)|(?&comment)|(?&code)|/)[^\'"/{}]*+)*+})
)';
const PARAMS = '\\[(?<params>[^[\\]]*+(?:\\[(?&params)\\][^[\\]]*+)*+)\\]';
const ARGS = '\\((?<args>[^()]*+(?:\\((?&args)\\)[^()]*+)*+)\\)';
///////////////////////////////
/// Preprocessing functions ///
///////////////////////////////
/**
 *
 */
function preprocessGrammar($code)
{
    $code = resolveNodes($code);
    $code = resolveMacros($code);
    $code = resolveStackAccess($code);
    return $code;
}
/**
 *
 */
function resolveNodes($code)
{
    return \preg_replace_callback('~\\b(?<name>[A-Z][a-zA-Z_\\\\]++)\\s*' . \PARAMS . '~', function ($matches) {
        // recurse
        $matches['params'] = resolveNodes($matches['params']);
        $params = magicSplit('(?:' . \PARAMS . '|' . \ARGS . ')(*SKIP)(*FAIL)|,', $matches['params']);
        $paramCode = '';
        foreach ($params as $param) {
            $paramCode .= $param . ', ';
        }
        return 'new ' . $matches['name'] . '(' . $paramCode . 'attributes())';
    }, $code);
}
/**
 *
 */
function resolveMacros($code)
{
    return \preg_replace_callback('~\\b(?<!::|->)(?!array\\()(?<name>[a-z][A-Za-z]++)' . \ARGS . '~', function ($matches) {
        // recurse
        $matches['args'] = resolveMacros($matches['args']);
        $name = $matches['name'];
        $args = magicSplit('(?:' . \PARAMS . '|' . \ARGS . ')(*SKIP)(*FAIL)|,', $matches['args']);
        if ('attributes' === $name) {
            assertArgs(0, $args, $name);
            return '$this->startAttributeStack[#1] + $this->endAttributes';
        }
        if ('stackAttributes' === $name) {
            assertArgs(1, $args, $name);
            return '$this->startAttributeStack[' . $args[0] . '] + $this->endAttributeStack[' . $args[0] . ']';
        }
        if ('init' === $name) {
            return '$$ = array(' . \implode(', ', $args) . ')';
        }
        if ('push' === $name) {
            assertArgs(2, $args, $name);
            return $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0];
        }
        if ('pushNormalizing' === $name) {
            assertArgs(2, $args, $name);
            return 'if (is_array(' . $args[1] . ')) { $$ = array_merge(' . $args[0] . ', ' . $args[1] . '); } else { ' . $args[0] . '[] = ' . $args[1] . '; $$ = ' . $args[0] . '; }';
        }
        if ('toArray' == $name) {
            assertArgs(1, $args, $name);
            return 'is_array(' . $args[0] . ') ? ' . $args[0] . ' : array(' . $args[0] . ')';
        }
        if ('parseVar' === $name) {
            assertArgs(1, $args, $name);
            return 'substr(' . $args[0] . ', 1)';
        }
        if ('parseEncapsed' === $name) {
            assertArgs(3, $args, $name);
            return 'foreach (' . $args[0] . ' as $s) { if ($s instanceof Node\\Scalar\\EncapsedStringPart) { $s->value = Node\\Scalar\\String_::parseEscapeSequences($s->value, ' . $args[1] . ', ' . $args[2] . '); } }';
        }
        if ('makeNop' === $name) {
            assertArgs(3, $args, $name);
            return '$startAttributes = ' . $args[1] . '; if (isset($startAttributes[\'comments\'])) { ' . $args[0] . ' = new Stmt\\Nop($startAttributes + ' . $args[2] . '); } else { ' . $args[0] . ' = null; }';
        }
        if ('makeZeroLengthNop' == $name) {
            assertArgs(2, $args, $name);
            return '$startAttributes = ' . $args[1] . '; if (isset($startAttributes[\'comments\'])) { ' . $args[0] . ' = new Stmt\\Nop($this->createCommentNopAttributes($startAttributes[\'comments\'])); } else { ' . $args[0] . ' = null; }';
        }
        if ('strKind' === $name) {
            assertArgs(1, $args, $name);
            return '(' . $args[0] . '[0] === "\'" || (' . $args[0] . '[1] === "\'" && (' . $args[0] . '[0] === \'b\' || ' . $args[0] . '[0] === \'B\')) ? Scalar\\String_::KIND_SINGLE_QUOTED : Scalar\\String_::KIND_DOUBLE_QUOTED)';
        }
        if ('prependLeadingComments' === $name) {
            assertArgs(1, $args, $name);
            return '$attrs = $this->startAttributeStack[#1]; $stmts = ' . $args[0] . '; if (!empty($attrs[\'comments\'])) {$stmts[0]->setAttribute(\'comments\', array_merge($attrs[\'comments\'], $stmts[0]->getAttribute(\'comments\', []))); }';
        }
        return $matches[0];
    }, $code);
}
/**
 *
 */
function assertArgs($num, $args, $name)
{
    if ($num != \count($args)) {
        die('Wrong argument count for ' . $name . '().');
    }
}
/**
 *
 */
function resolveStackAccess($code)
{
    $code = \preg_replace('/\\$\\d+/', '$this->semStack[$0]', $code);
    $code = \preg_replace('/#(\\d+)/', '$$1', $code);
    return $code;
}
/**
 *
 */
function removeTrailingWhitespace($code)
{
    $lines = \explode("\n", $code);
    $lines = \array_map('rtrim', $lines);
    return \implode("\n", $lines);
}
//////////////////////////////
/// Regex helper functions ///
//////////////////////////////
/**
 *
 */
function regex($regex)
{
    return '~' . \LIB . '(?:' . \str_replace('~', '\\~', $regex) . ')~';
}
/**
 *
 */
function magicSplit($regex, $string)
{
    $pieces = \preg_split(regex('(?:(?&string)|(?&comment)|(?&code))(*SKIP)(*FAIL)|' . $regex), $string);
    foreach ($pieces as &$piece) {
        $piece = \trim($piece);
    }
    if ($pieces === ['']) {
        return [];
    }
    return $pieces;
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Concat;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Scalar\String_;
use PhabelVendor\PhpParser\Node\Stmt\Use_;
class BuilderFactory
{
    /**
     * Creates an attribute node.
     *
     * @param (string | Name) $name Name of the attribute
     * @param array $args Attribute named arguments
     *
     * @return Node\Attribute
     */
    public function attribute($name, array $args = []) : Node\Attribute
    {
        return new Node\Attribute(BuilderHelpers::normalizeName($name), $this->args($args));
    }
    /**
     * Creates a namespace builder.
     *
     * @param (null | string | Node\Name) $name Name of the namespace
     *
     * @return Builder\Namespace_ The created namespace builder
     */
    public function namespace($name) : Builder\Namespace_
    {
        return new Builder\Namespace_($name);
    }
    /**
     * Creates a class builder.
     *
     * @param string $name Name of the class
     *
     * @return Builder\Class_ The created class builder
     */
    public function class(string $name) : Builder\Class_
    {
        return new Builder\Class_($name);
    }
    /**
     * Creates an interface builder.
     *
     * @param string $name Name of the interface
     *
     * @return Builder\Interface_ The created interface builder
     */
    public function interface(string $name) : Builder\Interface_
    {
        return new Builder\Interface_($name);
    }
    /**
     * Creates a trait builder.
     *
     * @param string $name Name of the trait
     *
     * @return Builder\Trait_ The created trait builder
     */
    public function trait(string $name) : Builder\Trait_
    {
        return new Builder\Trait_($name);
    }
    /**
     * Creates an enum builder.
     *
     * @param string $name Name of the enum
     *
     * @return Builder\Enum_ The created enum builder
     */
    public function enum(string $name) : Builder\Enum_
    {
        return new Builder\Enum_($name);
    }
    /**
     * Creates a trait use builder.
     *
     * @param (Node\Name | string) ...$traits Trait names
     *
     * @return Builder\TraitUse The create trait use builder
     */
    public function useTrait(...$traits) : Builder\TraitUse
    {
        return new Builder\TraitUse(...$traits);
    }
    /**
     * Creates a trait use adaptation builder.
     *
     * @param (Node\Name | string | null) $trait Trait name
     * @param (Node\Identifier | string) $method Method name
     *
     * @return Builder\TraitUseAdaptation The create trait use adaptation builder
     */
    public function traitUseAdaptation($trait, $method = null) : Builder\TraitUseAdaptation
    {
        if ($method === null) {
            $method = $trait;
            $trait = null;
        }
        return new Builder\TraitUseAdaptation($trait, $method);
    }
    /**
     * Creates a method builder.
     *
     * @param string $name Name of the method
     *
     * @return Builder\Method The created method builder
     */
    public function method(string $name) : Builder\Method
    {
        return new Builder\Method($name);
    }
    /**
     * Creates a parameter builder.
     *
     * @param string $name Name of the parameter
     *
     * @return Builder\Param The created parameter builder
     */
    public function param(string $name) : Builder\Param
    {
        return new Builder\Param($name);
    }
    /**
     * Creates a property builder.
     *
     * @param string $name Name of the property
     *
     * @return Builder\Property The created property builder
     */
    public function property(string $name) : Builder\Property
    {
        return new Builder\Property($name);
    }
    /**
     * Creates a function builder.
     *
     * @param string $name Name of the function
     *
     * @return Builder\Function_ The created function builder
     */
    public function function(string $name) : Builder\Function_
    {
        return new Builder\Function_($name);
    }
    /**
     * Creates a namespace/class use builder.
     *
     * @param (Node\Name | string) $name Name of the entity (namespace or class) to alias
     *
     * @return Builder\Use_ The created use builder
     */
    public function use($name) : Builder\Use_
    {
        return new Builder\Use_($name, Use_::TYPE_NORMAL);
    }
    /**
     * Creates a function use builder.
     *
     * @param (Node\Name | string) $name Name of the function to alias
     *
     * @return Builder\Use_ The created use function builder
     */
    public function useFunction($name) : Builder\Use_
    {
        return new Builder\Use_($name, Use_::TYPE_FUNCTION);
    }
    /**
     * Creates a constant use builder.
     *
     * @param (Node\Name | string) $name Name of the const to alias
     *
     * @return Builder\Use_ The created use const builder
     */
    public function useConst($name) : Builder\Use_
    {
        return new Builder\Use_($name, Use_::TYPE_CONSTANT);
    }
    /**
     * Creates a class constant builder.
     *
     * @param (string | Identifier) $name Name
     * @param (Node\Expr | bool | null | int | float | string | array) $value Value
     *
     * @return Builder\ClassConst The created use const builder
     */
    public function classConst($name, $value) : Builder\ClassConst
    {
        return new Builder\ClassConst($name, $value);
    }
    /**
     * Creates an enum case builder.
     *
     * @param (string | Identifier) $name Name
     *
     * @return Builder\EnumCase The created use const builder
     */
    public function enumCase($name) : Builder\EnumCase
    {
        return new Builder\EnumCase($name);
    }
    /**
     * Creates node a for a literal value.
     *
     * @param (Expr | bool | null | int | float | string | array) $value $value
     *
     * @return Expr
     */
    public function val($value) : Expr
    {
        return BuilderHelpers::normalizeValue($value);
    }
    /**
     * Creates variable node.
     *
     * @param (string | Expr) $name Name
     *
     * @return Expr\Variable
     */
    public function var($name) : Expr\Variable
    {
        if (!\is_string($name) && !$name instanceof Expr) {
            throw new \LogicException('Variable name must be string or Expr');
        }
        return new Expr\Variable($name);
    }
    /**
     * Normalizes an argument list.
     *
     * Creates Arg nodes for all arguments and converts literal values to expressions.
     *
     * @param array $args List of arguments to normalize
     *
     * @return Arg[]
     */
    public function args(array $args) : array
    {
        $normalizedArgs = [];
        foreach ($args as $key => $arg) {
            if (!$arg instanceof Arg) {
                $arg = new Arg(BuilderHelpers::normalizeValue($arg));
            }
            if (\is_string($key)) {
                $arg->name = BuilderHelpers::normalizeIdentifier($key);
            }
            $normalizedArgs[] = $arg;
        }
        return $normalizedArgs;
    }
    /**
     * Creates a function call node.
     *
     * @param (string | Name | Expr) $name Function name
     * @param array $args Function arguments
     *
     * @return Expr\FuncCall
     */
    public function funcCall($name, array $args = []) : Expr\FuncCall
    {
        return new Expr\FuncCall(BuilderHelpers::normalizeNameOrExpr($name), $this->args($args));
    }
    /**
     * Creates a method call node.
     *
     * @param Expr $var Variable the method is called on
     * @param (string | Identifier | Expr) $name Method name
     * @param array $args Method arguments
     *
     * @return Expr\MethodCall
     */
    public function methodCall(Expr $var, $name, array $args = []) : Expr\MethodCall
    {
        return new Expr\MethodCall($var, BuilderHelpers::normalizeIdentifierOrExpr($name), $this->args($args));
    }
    /**
     * Creates a static method call node.
     *
     * @param (string | Name | Expr) $class Class name
     * @param (string | Identifier | Expr) $name Method name
     * @param array $args Method arguments
     *
     * @return Expr\StaticCall
     */
    public function staticCall($class, $name, array $args = []) : Expr\StaticCall
    {
        return new Expr\StaticCall(BuilderHelpers::normalizeNameOrExpr($class), BuilderHelpers::normalizeIdentifierOrExpr($name), $this->args($args));
    }
    /**
     * Creates an object creation node.
     *
     * @param (string | Name | Expr) $class Class name
     * @param array $args Constructor arguments
     *
     * @return Expr\New_
     */
    public function new($class, array $args = []) : Expr\New_
    {
        return new Expr\New_(BuilderHelpers::normalizeNameOrExpr($class), $this->args($args));
    }
    /**
     * Creates a constant fetch node.
     *
     * @param (string | Name) $name Constant name
     *
     * @return Expr\ConstFetch
     */
    public function constFetch($name) : Expr\ConstFetch
    {
        return new Expr\ConstFetch(BuilderHelpers::normalizeName($name));
    }
    /**
     * Creates a property fetch node.
     *
     * @param Expr $var Variable holding object
     * @param (string | Identifier | Expr) $name Property name
     *
     * @return Expr\PropertyFetch
     */
    public function propertyFetch(Expr $var, $name) : Expr\PropertyFetch
    {
        return new Expr\PropertyFetch($var, BuilderHelpers::normalizeIdentifierOrExpr($name));
    }
    /**
     * Creates a class constant fetch node.
     *
     * @param (string | Name | Expr) $class Class name
     * @param (string | Identifier) $name Constant name
     *
     * @return Expr\ClassConstFetch
     */
    public function classConstFetch($class, $name) : Expr\ClassConstFetch
    {
        return new Expr\ClassConstFetch(BuilderHelpers::normalizeNameOrExpr($class), BuilderHelpers::normalizeIdentifier($name));
    }
    /**
     * Creates nested Concat nodes from a list of expressions.
     *
     * @param (Expr | string) ...$exprs Expressions or literal strings
     *
     * @return Concat
     */
    public function concat(...$exprs) : Concat
    {
        $numExprs = \count($exprs);
        if ($numExprs < 2) {
            throw new \LogicException('Expected at least two expressions');
        }
        $lastConcat = $this->normalizeStringExpr($exprs[0]);
        for ($i = 1; $i < $numExprs; $i++) {
            $lastConcat = new Concat($lastConcat, $this->normalizeStringExpr($exprs[$i]));
        }
        return $lastConcat;
    }
    /**
     * @param (string | Expr) $expr
     * @return Expr
     */
    private function normalizeStringExpr($expr) : Expr
    {
        if ($expr instanceof Expr) {
            return $expr;
        }
        if (\is_string($expr)) {
            return new String_($expr);
        }
        throw new \LogicException('Expected string or Expr');
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

class JsonDecoder
{
    /** @var \ReflectionClass[] Node type to reflection class map */
    private $reflectionClassCache;
    /**
     *
     */
    public function decode(string $json)
    {
        $value = \json_decode($json, \true);
        if (\json_last_error()) {
            throw new \RuntimeException('JSON decoding error: ' . \json_last_error_msg());
        }
        return $this->decodeRecursive($value);
    }
    /**
     *
     */
    private function decodeRecursive($value)
    {
        if (\is_array($value)) {
            if (isset($value['nodeType'])) {
                if ($value['nodeType'] === 'Comment' || $value['nodeType'] === 'Comment_Doc') {
                    return $this->decodeComment($value);
                }
                return $this->decodeNode($value);
            }
            return $this->decodeArray($value);
        }
        return $value;
    }
    /**
     *
     */
    private function decodeArray(array $array) : array
    {
        $decodedArray = [];
        foreach ($array as $key => $value) {
            $decodedArray[$key] = $this->decodeRecursive($value);
        }
        return $decodedArray;
    }
    /**
     *
     */
    private function decodeNode(array $value) : Node
    {
        $nodeType = $value['nodeType'];
        if (!\is_string($nodeType)) {
            throw new \RuntimeException('Node type must be a string');
        }
        $reflectionClass = $this->reflectionClassFromNodeType($nodeType);
        /** @var Node $node */
        $node = $reflectionClass->newInstanceWithoutConstructor();
        if (isset($value['attributes'])) {
            if (!\is_array($value['attributes'])) {
                throw new \RuntimeException('Attributes must be an array');
            }
            $node->setAttributes($this->decodeArray($value['attributes']));
        }
        foreach ($value as $name => $subNode) {
            if ($name === 'nodeType' || $name === 'attributes') {
                continue;
            }
            $node->{$name} = $this->decodeRecursive($subNode);
        }
        return $node;
    }
    /**
     *
     */
    private function decodeComment(array $value) : Comment
    {
        $className = $value['nodeType'] === 'Comment' ? Comment::class : Comment\Doc::class;
        if (!isset($value['text'])) {
            throw new \RuntimeException('Comment must have text');
        }
        return new $className($value['text'], $value['line'] ?? -1, $value['filePos'] ?? -1, $value['tokenPos'] ?? -1, $value['endLine'] ?? -1, $value['endFilePos'] ?? -1, $value['endTokenPos'] ?? -1);
    }
    /**
     *
     */
    private function reflectionClassFromNodeType(string $nodeType) : \ReflectionClass
    {
        if (!isset($this->reflectionClassCache[$nodeType])) {
            $className = $this->classNameFromNodeType($nodeType);
            $this->reflectionClassCache[$nodeType] = new \ReflectionClass($className);
        }
        return $this->reflectionClassCache[$nodeType];
    }
    /**
     *
     */
    private function classNameFromNodeType(string $nodeType) : string
    {
        $className = 'PhpParser\\Node\\' . \strtr($nodeType, '_', '\\');
        if (\class_exists($className)) {
            return $className;
        }
        $className .= '_';
        if (\class_exists($className)) {
            return $className;
        }
        throw new \RuntimeException("Unknown node type \"{$nodeType}\"");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

use PhabelVendor\PhpParser\Internal\DiffElem;
use PhabelVendor\PhpParser\Internal\PrintableNewAnonClassNode;
use PhabelVendor\PhpParser\Internal\TokenStream;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\AssignOp;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
use PhabelVendor\PhpParser\Node\Expr\Cast;
use PhabelVendor\PhpParser\Node\Scalar;
use PhabelVendor\PhpParser\Node\Stmt;
abstract class PrettyPrinterAbstract
{
    const FIXUP_PREC_LEFT = 0;
    // LHS operand affected by precedence
    const FIXUP_PREC_RIGHT = 1;
    // RHS operand affected by precedence
    const FIXUP_CALL_LHS = 2;
    // LHS of call
    const FIXUP_DEREF_LHS = 3;
    // LHS of dereferencing operation
    const FIXUP_BRACED_NAME = 4;
    // Name operand that may require bracing
    const FIXUP_VAR_BRACED_NAME = 5;
    // Name operand that may require ${} bracing
    const FIXUP_ENCAPSED = 6;
    // Encapsed string part
    protected $precedenceMap = [
        // [precedence, associativity]
        // where for precedence -1 is %left, 0 is %nonassoc and 1 is %right
        BinaryOp\Pow::class => [0, 1],
        Expr\BitwiseNot::class => [10, 1],
        Expr\PreInc::class => [10, 1],
        Expr\PreDec::class => [10, 1],
        Expr\PostInc::class => [10, -1],
        Expr\PostDec::class => [10, -1],
        Expr\UnaryPlus::class => [10, 1],
        Expr\UnaryMinus::class => [10, 1],
        Cast\Int_::class => [10, 1],
        Cast\Double::class => [10, 1],
        Cast\String_::class => [10, 1],
        Cast\Array_::class => [10, 1],
        Cast\Object_::class => [10, 1],
        Cast\Bool_::class => [10, 1],
        Cast\Unset_::class => [10, 1],
        Expr\ErrorSuppress::class => [10, 1],
        Expr\Instanceof_::class => [20, 0],
        Expr\BooleanNot::class => [30, 1],
        BinaryOp\Mul::class => [40, -1],
        BinaryOp\Div::class => [40, -1],
        BinaryOp\Mod::class => [40, -1],
        BinaryOp\Plus::class => [50, -1],
        BinaryOp\Minus::class => [50, -1],
        BinaryOp\Concat::class => [50, -1],
        BinaryOp\ShiftLeft::class => [60, -1],
        BinaryOp\ShiftRight::class => [60, -1],
        BinaryOp\Smaller::class => [70, 0],
        BinaryOp\SmallerOrEqual::class => [70, 0],
        BinaryOp\Greater::class => [70, 0],
        BinaryOp\GreaterOrEqual::class => [70, 0],
        BinaryOp\Equal::class => [80, 0],
        BinaryOp\NotEqual::class => [80, 0],
        BinaryOp\Identical::class => [80, 0],
        BinaryOp\NotIdentical::class => [80, 0],
        BinaryOp\Spaceship::class => [80, 0],
        BinaryOp\BitwiseAnd::class => [90, -1],
        BinaryOp\BitwiseXor::class => [100, -1],
        BinaryOp\BitwiseOr::class => [110, -1],
        BinaryOp\BooleanAnd::class => [120, -1],
        BinaryOp\BooleanOr::class => [130, -1],
        BinaryOp\Coalesce::class => [140, 1],
        Expr\Ternary::class => [150, 0],
        // parser uses %left for assignments, but they really behave as %right
        Expr\Assign::class => [160, 1],
        Expr\AssignRef::class => [160, 1],
        AssignOp\Plus::class => [160, 1],
        AssignOp\Minus::class => [160, 1],
        AssignOp\Mul::class => [160, 1],
        AssignOp\Div::class => [160, 1],
        AssignOp\Concat::class => [160, 1],
        AssignOp\Mod::class => [160, 1],
        AssignOp\BitwiseAnd::class => [160, 1],
        AssignOp\BitwiseOr::class => [160, 1],
        AssignOp\BitwiseXor::class => [160, 1],
        AssignOp\ShiftLeft::class => [160, 1],
        AssignOp\ShiftRight::class => [160, 1],
        AssignOp\Pow::class => [160, 1],
        AssignOp\Coalesce::class => [160, 1],
        Expr\YieldFrom::class => [165, 1],
        Expr\Print_::class => [168, 1],
        BinaryOp\LogicalAnd::class => [170, -1],
        BinaryOp\LogicalXor::class => [180, -1],
        BinaryOp\LogicalOr::class => [190, -1],
        Expr\Include_::class => [200, -1],
    ];
    /** @var int Current indentation level. */
    protected $indentLevel;
    /** @var string Newline including current indentation. */
    protected $nl;
    /** @var string Token placed at end of doc string to ensure it is followed by a newline. */
    protected $docStringEndToken;
    /** @var bool Whether semicolon namespaces can be used (i.e. no global namespace is used) */
    protected $canUseSemicolonNamespaces;
    /** @var array Pretty printer options */
    protected $options;
    /** @var TokenStream Original tokens for use in format-preserving pretty print */
    protected $origTokens;
    /** @var Internal\Differ Differ for node lists */
    protected $nodeListDiffer;
    /** @var bool[] Map determining whether a certain character is a label character */
    protected $labelCharMap;
    /**
     * @var int[][] Map from token classes and subnode names to FIXUP_* constants. This is used
     *              during format-preserving prints to place additional parens/braces if necessary.
     */
    protected $fixupMap;
    /**
     * @var int[][] Map from "{$node->getType()}->{$subNode}" to ['left' => $l, 'right' => $r],
     *              where $l and $r specify the token type that needs to be stripped when removing
     *              this node.
     */
    protected $removalMap;
    /**
     * @var mixed[] Map from "{$node->getType()}->{$subNode}" to [$find, $beforeToken, $extraLeft, $extraRight].
     *              $find is an optional token after which the insertion occurs. $extraLeft/Right
     *              are optionally added before/after the main insertions.
     */
    protected $insertionMap;
    /**
     * @var string[] Map From "{$node->getType()}->{$subNode}" to string that should be inserted
     *               between elements of this list subnode.
     */
    protected $listInsertionMap;
    protected $emptyListInsertionMap;
    /** @var int[] Map from "{$node->getType()}->{$subNode}" to token before which the modifiers
     *             should be reprinted. */
    protected $modifierChangeMap;
    /**
    * Creates a pretty printer instance using the given options.
    *
    * Supported options:
    bool $shortArraySyntax = false: Whether to use [] instead of array() as the default array
    syntax, if the node does not specify a format.
    *
    * @param array $options Dictionary of formatting options
    */
    public function __construct(array $options = [])
    {
        $this->docStringEndToken = '_DOC_STRING_END_' . \mt_rand();
        $defaultOptions = ['shortArraySyntax' => \false];
        $this->options = $options + $defaultOptions;
    }
    /**
     * Reset pretty printing state.
     */
    protected function resetState()
    {
        $this->indentLevel = 0;
        $this->nl = "\n";
        $this->origTokens = null;
    }
    /**
     * Set indentation level
     *
     * @param int $level Level in number of spaces
     */
    protected function setIndentLevel(int $level)
    {
        $this->indentLevel = $level;
        $this->nl = "\n" . \str_repeat(' ', $level);
    }
    /**
     * Increase indentation level.
     */
    protected function indent()
    {
        $this->indentLevel += 4;
        $this->nl .= '    ';
    }
    /**
     * Decrease indentation level.
     */
    protected function outdent()
    {
        \assert($this->indentLevel >= 4);
        $this->indentLevel -= 4;
        $this->nl = "\n" . \str_repeat(' ', $this->indentLevel);
    }
    /**
     * Pretty prints an array of statements.
     *
     * @param Node[] $stmts Array of statements
     *
     * @return string Pretty printed statements
     */
    public function prettyPrint(array $stmts) : string
    {
        $this->resetState();
        $this->preprocessNodes($stmts);
        return \ltrim($this->handleMagicTokens($this->pStmts($stmts, \false)));
    }
    /**
     * Pretty prints an expression.
     *
     * @param Expr $node Expression node
     *
     * @return string Pretty printed node
     */
    public function prettyPrintExpr(Expr $node) : string
    {
        $this->resetState();
        return $this->handleMagicTokens($this->p($node));
    }
    /**
     * Pretty prints a file of statements (includes the opening <?php tag if it is required).
     *
     * @param Node[] $stmts Array of statements
     *
     * @return string Pretty printed statements
     */
    public function prettyPrintFile(array $stmts) : string
    {
        if (!$stmts) {
            return "<?php\n\n";
        }
        $p = "<?php\n\n" . $this->prettyPrint($stmts);
        if ($stmts[0] instanceof Stmt\InlineHTML) {
            $p = \preg_replace('/^<\\?php\\s+\\?>\\n?/', '', $p);
        }
        if ($stmts[\count($stmts) - 1] instanceof Stmt\InlineHTML) {
            $p = \preg_replace('/<\\?php$/', '', \rtrim($p));
        }
        return $p;
    }
    /**
     * Preprocesses the top-level nodes to initialize pretty printer state.
     *
     * @param Node[] $nodes Array of nodes
     */
    protected function preprocessNodes(array $nodes)
    {
        /* We can use semicolon-namespaces unless there is a global namespace declaration */
        $this->canUseSemicolonNamespaces = \true;
        foreach ($nodes as $node) {
            if ($node instanceof Stmt\Namespace_ && null === $node->name) {
                $this->canUseSemicolonNamespaces = \false;
                break;
            }
        }
    }
    /**
     * Handles (and removes) no-indent and doc-string-end tokens.
     *
     * @param string $str
     * @return string
     */
    protected function handleMagicTokens(string $str) : string
    {
        // Replace doc-string-end tokens with nothing or a newline
        $str = \str_replace($this->docStringEndToken . ";\n", ";\n", $str);
        $str = \str_replace($this->docStringEndToken, "\n", $str);
        return $str;
    }
    /**
     * Pretty prints an array of nodes (statements) and indents them optionally.
     *
     * @param Node[] $nodes Array of nodes
     * @param bool $indent Whether to indent the printed nodes
     *
     * @return string Pretty printed statements
     */
    protected function pStmts(array $nodes, bool $indent = \true) : string
    {
        if ($indent) {
            $this->indent();
        }
        $result = '';
        foreach ($nodes as $node) {
            $comments = $node->getComments();
            if ($comments) {
                $result .= $this->nl . $this->pComments($comments);
                if ($node instanceof Stmt\Nop) {
                    continue;
                }
            }
            $result .= $this->nl . $this->p($node);
        }
        if ($indent) {
            $this->outdent();
        }
        return $result;
    }
    /**
     * Pretty-print an infix operation while taking precedence into account.
     *
     * @param string $class Node class of operator
     * @param Node $leftNode Left-hand side node
     * @param string $operatorString String representation of the operator
     * @param Node $rightNode Right-hand side node
     *
     * @return string Pretty printed infix operation
     */
    protected function pInfixOp(string $class, Node $leftNode, string $operatorString, Node $rightNode) : string
    {
        list($precedence, $associativity) = $this->precedenceMap[$class];
        return $this->pPrec($leftNode, $precedence, $associativity, -1) . $operatorString . $this->pPrec($rightNode, $precedence, $associativity, 1);
    }
    /**
     * Pretty-print a prefix operation while taking precedence into account.
     *
     * @param string $class Node class of operator
     * @param string $operatorString String representation of the operator
     * @param Node $node Node
     *
     * @return string Pretty printed prefix operation
     */
    protected function pPrefixOp(string $class, string $operatorString, Node $node) : string
    {
        list($precedence, $associativity) = $this->precedenceMap[$class];
        return $operatorString . $this->pPrec($node, $precedence, $associativity, 1);
    }
    /**
     * Pretty-print a postfix operation while taking precedence into account.
     *
     * @param string $class Node class of operator
     * @param string $operatorString String representation of the operator
     * @param Node $node Node
     *
     * @return string Pretty printed postfix operation
     */
    protected function pPostfixOp(string $class, Node $node, string $operatorString) : string
    {
        list($precedence, $associativity) = $this->precedenceMap[$class];
        return $this->pPrec($node, $precedence, $associativity, -1) . $operatorString;
    }
    /**
    * Prints an expression node with the least amount of parentheses necessary to preserve the meaning.
    *
    * @param Node $node Node to pretty print
    * @param int $parentPrecedence Precedence of the parent operator
    * @param int $parentAssociativity Associativity of parent operator
    (-1 is left, 0 is nonassoc, 1 is right)
    * @param int $childPosition Position of the node relative to the operator
    (-1 is left, 1 is right)
    *
    * @return string The pretty printed node
    */
    protected function pPrec(Node $node, int $parentPrecedence, int $parentAssociativity, int $childPosition) : string
    {
        $class = \get_class($node);
        if (isset($this->precedenceMap[$class])) {
            $childPrecedence = $this->precedenceMap[$class][0];
            if ($childPrecedence > $parentPrecedence || $parentPrecedence === $childPrecedence && $parentAssociativity !== $childPosition) {
                return '(' . $this->p($node) . ')';
            }
        }
        return $this->p($node);
    }
    /**
     * Pretty prints an array of nodes and implodes the printed values.
     *
     * @param Node[] $nodes Array of Nodes to be printed
     * @param string $glue Character to implode with
     *
     * @return string Imploded pretty printed nodes
     */
    protected function pImplode(array $nodes, string $glue = '') : string
    {
        $pNodes = [];
        foreach ($nodes as $node) {
            if (null === $node) {
                $pNodes[] = '';
            } else {
                $pNodes[] = $this->p($node);
            }
        }
        return \implode($glue, $pNodes);
    }
    /**
     * Pretty prints an array of nodes and implodes the printed values with commas.
     *
     * @param Node[] $nodes Array of Nodes to be printed
     *
     * @return string Comma separated pretty printed nodes
     */
    protected function pCommaSeparated(array $nodes) : string
    {
        return $this->pImplode($nodes, ', ');
    }
    /**
     * Pretty prints a comma-separated list of nodes in multiline style, including comments.
     *
     * The result includes a leading newline and one level of indentation (same as pStmts).
     *
     * @param Node[] $nodes Array of Nodes to be printed
     * @param bool $trailingComma Whether to use a trailing comma
     *
     * @return string Comma separated pretty printed nodes in multiline style
     */
    protected function pCommaSeparatedMultiline(array $nodes, bool $trailingComma) : string
    {
        $this->indent();
        $result = '';
        $lastIdx = \count($nodes) - 1;
        foreach ($nodes as $idx => $node) {
            if ($node !== null) {
                $comments = $node->getComments();
                if ($comments) {
                    $result .= $this->nl . $this->pComments($comments);
                }
                $result .= $this->nl . $this->p($node);
            } else {
                $result .= $this->nl;
            }
            if ($trailingComma || $idx !== $lastIdx) {
                $result .= ',';
            }
        }
        $this->outdent();
        return $result;
    }
    /**
     * Prints reformatted text of the passed comments.
     *
     * @param Comment[] $comments List of comments
     *
     * @return string Reformatted text of comments
     */
    protected function pComments(array $comments) : string
    {
        $formattedComments = [];
        foreach ($comments as $comment) {
            $formattedComments[] = \str_replace("\n", $this->nl, $comment->getReformattedText());
        }
        return \implode($this->nl, $formattedComments);
    }
    /**
    * Perform a format-preserving pretty print of an AST.
    *
    * The format preservation is best effort. For some changes to the AST the formatting will not
    be preserved (at least not locally).
    *
    * In order to use this method a number of prerequisites must be satisfied:
    The startTokenPos and endTokenPos attributes in the lexer must be enabled.
    The CloningVisitor must be run on the AST prior to modification.
    The original tokens must be provided, using the getTokens() method on the lexer.
    *
    * @param Node[] $stmts Modified AST with links to original AST
    * @param Node[] $origStmts Original AST with token offset information
    * @param array $origTokens Tokens of the original code
    *
    * @return string
    */
    public function printFormatPreserving(array $stmts, array $origStmts, array $origTokens) : string
    {
        $this->initializeNodeListDiffer();
        $this->initializeLabelCharMap();
        $this->initializeFixupMap();
        $this->initializeRemovalMap();
        $this->initializeInsertionMap();
        $this->initializeListInsertionMap();
        $this->initializeEmptyListInsertionMap();
        $this->initializeModifierChangeMap();
        $this->resetState();
        $this->origTokens = new TokenStream($origTokens);
        $this->preprocessNodes($stmts);
        $pos = 0;
        $result = $this->pArray($stmts, $origStmts, $pos, 0, 'File', 'stmts', null);
        if (null !== $result) {
            $result .= $this->origTokens->getTokenCode($pos, \count($origTokens), 0);
        } else {
            // Fallback
            // TODO Add <?php properly
            $result = "<?php\n" . $this->pStmts($stmts, \false);
        }
        return \ltrim($this->handleMagicTokens($result));
    }
    /**
     *
     */
    protected function pFallback(Node $node)
    {
        return $this->{'p' . $node->getType()}($node);
    }
    /**
     * Pretty prints a node.
     *
     * This method also handles formatting preservation for nodes.
     *
     * @param Node $node Node to be pretty printed
     * @param bool $parentFormatPreserved Whether parent node has preserved formatting
     *
     * @return string Pretty printed node
     */
    protected function p(Node $node, $parentFormatPreserved = \false) : string
    {
        // No orig tokens means this is a normal pretty print without preservation of formatting
        if (!$this->origTokens) {
            return $this->{'p' . $node->getType()}($node);
        }
        /** @var Node $origNode */
        $origNode = $node->getAttribute('origNode');
        if (null === $origNode) {
            return $this->pFallback($node);
        }
        $class = \get_class($node);
        \assert($class === \get_class($origNode));
        $startPos = $origNode->getStartTokenPos();
        $endPos = $origNode->getEndTokenPos();
        \assert($startPos >= 0 && $endPos >= 0);
        $fallbackNode = $node;
        if ($node instanceof Expr\New_ && $node->class instanceof Stmt\Class_) {
            // Normalize node structure of anonymous classes
            $node = PrintableNewAnonClassNode::fromNewNode($node);
            $origNode = PrintableNewAnonClassNode::fromNewNode($origNode);
        }
        // InlineHTML node does not contain closing and opening PHP tags. If the parent formatting
        // is not preserved, then we need to use the fallback code to make sure the tags are
        // printed.
        if ($node instanceof Stmt\InlineHTML && !$parentFormatPreserved) {
            return $this->pFallback($fallbackNode);
        }
        $indentAdjustment = $this->indentLevel - $this->origTokens->getIndentationBefore($startPos);
        $type = $node->getType();
        $fixupInfo = $this->fixupMap[$class] ?? null;
        $result = '';
        $pos = $startPos;
        foreach ($node->getSubNodeNames() as $subNodeName) {
            $subNode = $node->{$subNodeName};
            $origSubNode = $origNode->{$subNodeName};
            if (!$subNode instanceof Node && $subNode !== null || !$origSubNode instanceof Node && $origSubNode !== null) {
                if ($subNode === $origSubNode) {
                    // Unchanged, can reuse old code
                    continue;
                }
                if (\is_array($subNode) && \is_array($origSubNode)) {
                    // Array subnode changed, we might be able to reconstruct it
                    $listResult = $this->pArray($subNode, $origSubNode, $pos, $indentAdjustment, $type, $subNodeName, $fixupInfo[$subNodeName] ?? null);
                    if (null === $listResult) {
                        return $this->pFallback($fallbackNode);
                    }
                    $result .= $listResult;
                    continue;
                }
                if (\is_int($subNode) && \is_int($origSubNode)) {
                    // Check if this is a modifier change
                    $key = $type . '->' . $subNodeName;
                    if (!isset($this->modifierChangeMap[$key])) {
                        return $this->pFallback($fallbackNode);
                    }
                    $findToken = $this->modifierChangeMap[$key];
                    $result .= $this->pModifiers($subNode);
                    $pos = $this->origTokens->findRight($pos, $findToken);
                    continue;
                }
                // If a non-node, non-array subnode changed, we don't be able to do a partial
                // reconstructions, as we don't have enough offset information. Pretty print the
                // whole node instead.
                return $this->pFallback($fallbackNode);
            }
            $extraLeft = '';
            $extraRight = '';
            if ($origSubNode !== null) {
                $subStartPos = $origSubNode->getStartTokenPos();
                $subEndPos = $origSubNode->getEndTokenPos();
                \assert($subStartPos >= 0 && $subEndPos >= 0);
            } else {
                if ($subNode === null) {
                    // Both null, nothing to do
                    continue;
                }
                // A node has been inserted, check if we have insertion information for it
                $key = $type . '->' . $subNodeName;
                if (!isset($this->insertionMap[$key])) {
                    return $this->pFallback($fallbackNode);
                }
                list($findToken, $beforeToken, $extraLeft, $extraRight) = $this->insertionMap[$key];
                if (null !== $findToken) {
                    $subStartPos = $this->origTokens->findRight($pos, $findToken) + (int) (!$beforeToken);
                } else {
                    $subStartPos = $pos;
                }
                if (null === $extraLeft && null !== $extraRight) {
                    // If inserting on the right only, skipping whitespace looks better
                    $subStartPos = $this->origTokens->skipRightWhitespace($subStartPos);
                }
                $subEndPos = $subStartPos - 1;
            }
            if (null === $subNode) {
                // A node has been removed, check if we have removal information for it
                $key = $type . '->' . $subNodeName;
                if (!isset($this->removalMap[$key])) {
                    return $this->pFallback($fallbackNode);
                }
                // Adjust positions to account for additional tokens that must be skipped
                $removalInfo = $this->removalMap[$key];
                if (isset($removalInfo['left'])) {
                    $subStartPos = $this->origTokens->skipLeft($subStartPos - 1, $removalInfo['left']) + 1;
                }
                if (isset($removalInfo['right'])) {
                    $subEndPos = $this->origTokens->skipRight($subEndPos + 1, $removalInfo['right']) - 1;
                }
            }
            $result .= $this->origTokens->getTokenCode($pos, $subStartPos, $indentAdjustment);
            if (null !== $subNode) {
                $result .= $extraLeft;
                $origIndentLevel = $this->indentLevel;
                $this->setIndentLevel($this->origTokens->getIndentationBefore($subStartPos) + $indentAdjustment);
                // If it's the same node that was previously in this position, it certainly doesn't
                // need fixup. It's important to check this here, because our fixup checks are more
                // conservative than strictly necessary.
                if (isset($fixupInfo[$subNodeName]) && $subNode->getAttribute('origNode') !== $origSubNode) {
                    $fixup = $fixupInfo[$subNodeName];
                    $res = $this->pFixup($fixup, $subNode, $class, $subStartPos, $subEndPos);
                } else {
                    $res = $this->p($subNode, \true);
                }
                $this->safeAppend($result, $res);
                $this->setIndentLevel($origIndentLevel);
                $result .= $extraRight;
            }
            $pos = $subEndPos + 1;
        }
        $result .= $this->origTokens->getTokenCode($pos, $endPos + 1, $indentAdjustment);
        return $result;
    }
    /**
     * Perform a format-preserving pretty print of an array.
     *
     * @param array $nodes New nodes
     * @param array $origNodes Original nodes
     * @param int $pos Current token position (updated by reference)
     * @param int $indentAdjustment Adjustment for indentation
     * @param string $parentNodeType Type of the containing node.
     * @param string $subNodeName Name of array subnode.
     * @param (null | int) $fixup Fixup information for array item nodes
     *
     * @return (null | string) Result of pretty print or null if cannot preserve formatting
     */
    protected function pArray(array $nodes, array $origNodes, int &$pos, int $indentAdjustment, string $parentNodeType, string $subNodeName, $fixup)
    {
        $diff = $this->nodeListDiffer->diffWithReplacements($origNodes, $nodes);
        $mapKey = $parentNodeType . '->' . $subNodeName;
        $insertStr = $this->listInsertionMap[$mapKey] ?? null;
        $isStmtList = $subNodeName === 'stmts';
        $beforeFirstKeepOrReplace = \true;
        $skipRemovedNode = \false;
        $delayedAdd = [];
        $lastElemIndentLevel = $this->indentLevel;
        $insertNewline = \false;
        if ($insertStr === "\n") {
            $insertStr = '';
            $insertNewline = \true;
        }
        if ($isStmtList && \count($origNodes) === 1 && \count($nodes) !== 1) {
            $startPos = $origNodes[0]->getStartTokenPos();
            $endPos = $origNodes[0]->getEndTokenPos();
            \assert($startPos >= 0 && $endPos >= 0);
            if (!$this->origTokens->haveBraces($startPos, $endPos)) {
                // This was a single statement without braces, but either additional statements
                // have been added, or the single statement has been removed. This requires the
                // addition of braces. For now fall back.
                // TODO: Try to preserve formatting
                return null;
            }
        }
        $result = '';
        foreach ($diff as $i => $diffElem) {
            $diffType = $diffElem->type;
            /** @var Node|null $arrItem */
            $arrItem = $diffElem->new;
            /** @var Node|null $origArrItem */
            $origArrItem = $diffElem->old;
            if ($diffType === DiffElem::TYPE_KEEP || $diffType === DiffElem::TYPE_REPLACE) {
                $beforeFirstKeepOrReplace = \false;
                if ($origArrItem === null || $arrItem === null) {
                    // We can only handle the case where both are null
                    if ($origArrItem === $arrItem) {
                        continue;
                    }
                    return null;
                }
                if (!$arrItem instanceof Node || !$origArrItem instanceof Node) {
                    // We can only deal with nodes. This can occur for Names, which use string arrays.
                    return null;
                }
                $itemStartPos = $origArrItem->getStartTokenPos();
                $itemEndPos = $origArrItem->getEndTokenPos();
                \assert($itemStartPos >= 0 && $itemEndPos >= 0 && $itemStartPos >= $pos);
                $origIndentLevel = $this->indentLevel;
                $lastElemIndentLevel = $this->origTokens->getIndentationBefore($itemStartPos) + $indentAdjustment;
                $this->setIndentLevel($lastElemIndentLevel);
                $comments = $arrItem->getComments();
                $origComments = $origArrItem->getComments();
                $commentStartPos = $origComments ? $origComments[0]->getStartTokenPos() : $itemStartPos;
                \assert($commentStartPos >= 0);
                if ($commentStartPos < $pos) {
                    // Comments may be assigned to multiple nodes if they start at the same position.
                    // Make sure we don't try to print them multiple times.
                    $commentStartPos = $itemStartPos;
                }
                if ($skipRemovedNode) {
                    if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) {
                        // We'd remove the brace of a code block.
                        // TODO: Preserve formatting.
                        $this->setIndentLevel($origIndentLevel);
                        return null;
                    }
                } else {
                    $result .= $this->origTokens->getTokenCode($pos, $commentStartPos, $indentAdjustment);
                }
                if (!empty($delayedAdd)) {
                    /** @var Node $delayedAddNode */
                    foreach ($delayedAdd as $delayedAddNode) {
                        if ($insertNewline) {
                            $delayedAddComments = $delayedAddNode->getComments();
                            if ($delayedAddComments) {
                                $result .= $this->pComments($delayedAddComments) . $this->nl;
                            }
                        }
                        $this->safeAppend($result, $this->p($delayedAddNode, \true));
                        if ($insertNewline) {
                            $result .= $insertStr . $this->nl;
                        } else {
                            $result .= $insertStr;
                        }
                    }
                    $delayedAdd = [];
                }
                if ($comments !== $origComments) {
                    if ($comments) {
                        $result .= $this->pComments($comments) . $this->nl;
                    }
                } else {
                    $result .= $this->origTokens->getTokenCode($commentStartPos, $itemStartPos, $indentAdjustment);
                }
                // If we had to remove anything, we have done so now.
                $skipRemovedNode = \false;
            } elseif ($diffType === DiffElem::TYPE_ADD) {
                if (null === $insertStr) {
                    // We don't have insertion information for this list type
                    return null;
                }
                // We go multiline if the original code was multiline,
                // or if it's an array item with a comment above it.
                if ($insertStr === ', ' && ($this->isMultiline($origNodes) || $arrItem->getComments())) {
                    $insertStr = ',';
                    $insertNewline = \true;
                }
                if ($beforeFirstKeepOrReplace) {
                    // Will be inserted at the next "replace" or "keep" element
                    $delayedAdd[] = $arrItem;
                    continue;
                }
                $itemStartPos = $pos;
                $itemEndPos = $pos - 1;
                $origIndentLevel = $this->indentLevel;
                $this->setIndentLevel($lastElemIndentLevel);
                if ($insertNewline) {
                    $result .= $insertStr . $this->nl;
                    $comments = $arrItem->getComments();
                    if ($comments) {
                        $result .= $this->pComments($comments) . $this->nl;
                    }
                } else {
                    $result .= $insertStr;
                }
            } elseif ($diffType === DiffElem::TYPE_REMOVE) {
                if (!$origArrItem instanceof Node) {
                    // We only support removal for nodes
                    return null;
                }
                $itemStartPos = $origArrItem->getStartTokenPos();
                $itemEndPos = $origArrItem->getEndTokenPos();
                \assert($itemStartPos >= 0 && $itemEndPos >= 0);
                // Consider comments part of the node.
                $origComments = $origArrItem->getComments();
                if ($origComments) {
                    $itemStartPos = $origComments[0]->getStartTokenPos();
                }
                if ($i === 0) {
                    // If we're removing from the start, keep the tokens before the node and drop those after it,
                    // instead of the other way around.
                    $result .= $this->origTokens->getTokenCode($pos, $itemStartPos, $indentAdjustment);
                    $skipRemovedNode = \true;
                } else {
                    if ($isStmtList && $this->origTokens->haveBracesInRange($pos, $itemStartPos)) {
                        // We'd remove the brace of a code block.
                        // TODO: Preserve formatting.
                        return null;
                    }
                }
                $pos = $itemEndPos + 1;
                continue;
            } else {
                throw new \Exception("Shouldn't happen");
            }
            if (null !== $fixup && $arrItem->getAttribute('origNode') !== $origArrItem) {
                $res = $this->pFixup($fixup, $arrItem, null, $itemStartPos, $itemEndPos);
            } else {
                $res = $this->p($arrItem, \true);
            }
            $this->safeAppend($result, $res);
            $this->setIndentLevel($origIndentLevel);
            $pos = $itemEndPos + 1;
        }
        if ($skipRemovedNode) {
            // TODO: Support removing single node.
            return null;
        }
        if (!empty($delayedAdd)) {
            if (!isset($this->emptyListInsertionMap[$mapKey])) {
                return null;
            }
            list($findToken, $extraLeft, $extraRight) = $this->emptyListInsertionMap[$mapKey];
            if (null !== $findToken) {
                $insertPos = $this->origTokens->findRight($pos, $findToken) + 1;
                $result .= $this->origTokens->getTokenCode($pos, $insertPos, $indentAdjustment);
                $pos = $insertPos;
            }
            $first = \true;
            $result .= $extraLeft;
            foreach ($delayedAdd as $delayedAddNode) {
                if (!$first) {
                    $result .= $insertStr;
                }
                $result .= $this->p($delayedAddNode, \true);
                $first = \false;
            }
            $result .= $extraRight;
        }
        return $result;
    }
    /**
    * Print node with fixups.
    *
    * Fixups here refer to the addition of extra parentheses, braces or other characters, that
    are required to preserve program semantics in a certain context (e.g. to maintain precedence
    or because only certain expressions are allowed in certain places).
    *
    * @param int $fixup Fixup type
    * @param Node $subNode Subnode to print
    * @param (string | null) $parentClass Class of parent node
    * @param int $subStartPos Original start pos of subnode
    * @param int $subEndPos Original end pos of subnode
    *
    * @return string Result of fixed-up print of subnode
    */
    protected function pFixup(int $fixup, Node $subNode, $parentClass, int $subStartPos, int $subEndPos) : string
    {
        switch ($fixup) {
            case self::FIXUP_PREC_LEFT:
            case self::FIXUP_PREC_RIGHT:
                if (!$this->origTokens->haveParens($subStartPos, $subEndPos)) {
                    list($precedence, $associativity) = $this->precedenceMap[$parentClass];
                    return $this->pPrec($subNode, $precedence, $associativity, $fixup === self::FIXUP_PREC_LEFT ? -1 : 1);
                }
                break;
            case self::FIXUP_CALL_LHS:
                if ($this->callLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos)) {
                    return '(' . $this->p($subNode) . ')';
                }
                break;
            case self::FIXUP_DEREF_LHS:
                if ($this->dereferenceLhsRequiresParens($subNode) && !$this->origTokens->haveParens($subStartPos, $subEndPos)) {
                    return '(' . $this->p($subNode) . ')';
                }
                break;
            case self::FIXUP_BRACED_NAME:
            case self::FIXUP_VAR_BRACED_NAME:
                if ($subNode instanceof Expr && !$this->origTokens->haveBraces($subStartPos, $subEndPos)) {
                    return ($fixup === self::FIXUP_VAR_BRACED_NAME ? '$' : '') . '{' . $this->p($subNode) . '}';
                }
                break;
            case self::FIXUP_ENCAPSED:
                if (!$subNode instanceof Scalar\EncapsedStringPart && !$this->origTokens->haveBraces($subStartPos, $subEndPos)) {
                    return '{' . $this->p($subNode) . '}';
                }
                break;
            default:
                throw new \Exception('Cannot happen');
        }
        // Nothing special to do
        return $this->p($subNode);
    }
    /**
    * Appends to a string, ensuring whitespace between label characters.
    *
    * Example: "echo" and "$x" result in "echo$x", but "echo" and "x" result in "echo x".
    Without safeAppend the result would be "echox", which does not preserve semantics.
    *
    * @param string $str
    * @param string $append
    */
    protected function safeAppend(string &$str, string $append)
    {
        if ($str === "") {
            $str = $append;
            return;
        }
        if ($append === "") {
            return;
        }
        if (!$this->labelCharMap[$append[0]] || !$this->labelCharMap[$str[\strlen($str) - 1]]) {
            $str .= $append;
        } else {
            $str .= " " . $append;
        }
    }
    /**
     * Determines whether the LHS of a call must be wrapped in parenthesis.
     *
     * @param Node $node LHS of a call
     *
     * @return bool Whether parentheses are required
     */
    protected function callLhsRequiresParens(Node $node) : bool
    {
        return !($node instanceof Node\Name || $node instanceof Expr\Variable || $node instanceof Expr\ArrayDimFetch || $node instanceof Expr\FuncCall || $node instanceof Expr\MethodCall || $node instanceof Expr\NullsafeMethodCall || $node instanceof Expr\StaticCall || $node instanceof Expr\Array_);
    }
    /**
     * Determines whether the LHS of a dereferencing operation must be wrapped in parenthesis.
     *
     * @param Node $node LHS of dereferencing operation
     *
     * @return bool Whether parentheses are required
     */
    protected function dereferenceLhsRequiresParens(Node $node) : bool
    {
        return !($node instanceof Expr\Variable || $node instanceof Node\Name || $node instanceof Expr\ArrayDimFetch || $node instanceof Expr\PropertyFetch || $node instanceof Expr\NullsafePropertyFetch || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\FuncCall || $node instanceof Expr\MethodCall || $node instanceof Expr\NullsafeMethodCall || $node instanceof Expr\StaticCall || $node instanceof Expr\Array_ || $node instanceof Scalar\String_ || $node instanceof Expr\ConstFetch || $node instanceof Expr\ClassConstFetch);
    }
    /**
     * Print modifiers, including trailing whitespace.
     *
     * @param int $modifiers Modifier mask to print
     *
     * @return string Printed modifiers
     */
    protected function pModifiers(int $modifiers)
    {
        return ($modifiers & Stmt\Class_::MODIFIER_PUBLIC ? 'public ' : '') . ($modifiers & Stmt\Class_::MODIFIER_PROTECTED ? 'protected ' : '') . ($modifiers & Stmt\Class_::MODIFIER_PRIVATE ? 'private ' : '') . ($modifiers & Stmt\Class_::MODIFIER_STATIC ? 'static ' : '') . ($modifiers & Stmt\Class_::MODIFIER_ABSTRACT ? 'abstract ' : '') . ($modifiers & Stmt\Class_::MODIFIER_FINAL ? 'final ' : '') . ($modifiers & Stmt\Class_::MODIFIER_READONLY ? 'readonly ' : '');
    }
    /**
     * Determine whether a list of nodes uses multiline formatting.
     *
     * @param (Node | null)[] $nodes Node list
     *
     * @return bool Whether multiline formatting is used
     */
    protected function isMultiline(array $nodes) : bool
    {
        if (\count($nodes) < 2) {
            return \false;
        }
        $pos = -1;
        foreach ($nodes as $node) {
            if (null === $node) {
                continue;
            }
            $endPos = $node->getEndTokenPos() + 1;
            if ($pos >= 0) {
                $text = $this->origTokens->getTokenCode($pos, $endPos, 0);
                if (\false === \strpos($text, "\n")) {
                    // We require that a newline is present between *every* item. If the formatting
                    // is inconsistent, with only some items having newlines, we don't consider it
                    // as multiline
                    return \false;
                }
            }
            $pos = $endPos;
        }
        return \true;
    }
    /**
     * Lazily initializes label char map.
     *
     * The label char map determines whether a certain character may occur in a label.
     */
    protected function initializeLabelCharMap()
    {
        if ($this->labelCharMap) {
            return;
        }
        $this->labelCharMap = [];
        for ($i = 0; $i < 256; $i++) {
            // Since PHP 7.1 The lower range is 0x80. However, we also want to support code for
            // older versions.
            $chr = \chr($i);
            $this->labelCharMap[$chr] = $i >= 0x7f || \ctype_alnum($chr);
        }
    }
    /**
     * Lazily initializes node list differ.
     *
     * The node list differ is used to determine differences between two array subnodes.
     */
    protected function initializeNodeListDiffer()
    {
        if ($this->nodeListDiffer) {
            return;
        }
        $this->nodeListDiffer = new Internal\Differ(function ($a, $b) {
            if ($a instanceof Node && $b instanceof Node) {
                return $a === $b->getAttribute('origNode');
            }
            // Can happen for array destructuring
            return $a === null && $b === null;
        });
    }
    /**
    * Lazily initializes fixup map.
    *
    * The fixup map is used to determine whether a certain subnode of a certain node may require
    some kind of "fixup" operation, e.g. the addition of parenthesis or braces.
    */
    protected function initializeFixupMap()
    {
        if ($this->fixupMap) {
            return;
        }
        $this->fixupMap = [
            Expr\PreInc::class => ['var' => self::FIXUP_PREC_RIGHT],
            Expr\PreDec::class => ['var' => self::FIXUP_PREC_RIGHT],
            Expr\PostInc::class => ['var' => self::FIXUP_PREC_LEFT],
            Expr\PostDec::class => ['var' => self::FIXUP_PREC_LEFT],
            Expr\Instanceof_::class => ['expr' => self::FIXUP_PREC_LEFT, 'class' => self::FIXUP_PREC_RIGHT],
            Expr\Ternary::class => ['cond' => self::FIXUP_PREC_LEFT, 'else' => self::FIXUP_PREC_RIGHT],
            Expr\FuncCall::class => ['name' => self::FIXUP_CALL_LHS],
            Expr\StaticCall::class => ['class' => self::FIXUP_DEREF_LHS],
            Expr\ArrayDimFetch::class => ['var' => self::FIXUP_DEREF_LHS],
            Expr\ClassConstFetch::class => ['var' => self::FIXUP_DEREF_LHS],
            Expr\New_::class => ['class' => self::FIXUP_DEREF_LHS],
            // TODO: FIXUP_NEW_VARIABLE
            Expr\MethodCall::class => ['var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME],
            Expr\NullsafeMethodCall::class => ['var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME],
            Expr\StaticPropertyFetch::class => ['class' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_VAR_BRACED_NAME],
            Expr\PropertyFetch::class => ['var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME],
            Expr\NullsafePropertyFetch::class => ['var' => self::FIXUP_DEREF_LHS, 'name' => self::FIXUP_BRACED_NAME],
            Scalar\Encapsed::class => ['parts' => self::FIXUP_ENCAPSED],
        ];
        $binaryOps = [BinaryOp\Pow::class, BinaryOp\Mul::class, BinaryOp\Div::class, BinaryOp\Mod::class, BinaryOp\Plus::class, BinaryOp\Minus::class, BinaryOp\Concat::class, BinaryOp\ShiftLeft::class, BinaryOp\ShiftRight::class, BinaryOp\Smaller::class, BinaryOp\SmallerOrEqual::class, BinaryOp\Greater::class, BinaryOp\GreaterOrEqual::class, BinaryOp\Equal::class, BinaryOp\NotEqual::class, BinaryOp\Identical::class, BinaryOp\NotIdentical::class, BinaryOp\Spaceship::class, BinaryOp\BitwiseAnd::class, BinaryOp\BitwiseXor::class, BinaryOp\BitwiseOr::class, BinaryOp\BooleanAnd::class, BinaryOp\BooleanOr::class, BinaryOp\Coalesce::class, BinaryOp\LogicalAnd::class, BinaryOp\LogicalXor::class, BinaryOp\LogicalOr::class];
        foreach ($binaryOps as $binaryOp) {
            $this->fixupMap[$binaryOp] = ['left' => self::FIXUP_PREC_LEFT, 'right' => self::FIXUP_PREC_RIGHT];
        }
        $assignOps = [Expr\Assign::class, Expr\AssignRef::class, AssignOp\Plus::class, AssignOp\Minus::class, AssignOp\Mul::class, AssignOp\Div::class, AssignOp\Concat::class, AssignOp\Mod::class, AssignOp\BitwiseAnd::class, AssignOp\BitwiseOr::class, AssignOp\BitwiseXor::class, AssignOp\ShiftLeft::class, AssignOp\ShiftRight::class, AssignOp\Pow::class, AssignOp\Coalesce::class];
        foreach ($assignOps as $assignOp) {
            $this->fixupMap[$assignOp] = ['var' => self::FIXUP_PREC_LEFT, 'expr' => self::FIXUP_PREC_RIGHT];
        }
        $prefixOps = [Expr\BitwiseNot::class, Expr\BooleanNot::class, Expr\UnaryPlus::class, Expr\UnaryMinus::class, Cast\Int_::class, Cast\Double::class, Cast\String_::class, Cast\Array_::class, Cast\Object_::class, Cast\Bool_::class, Cast\Unset_::class, Expr\ErrorSuppress::class, Expr\YieldFrom::class, Expr\Print_::class, Expr\Include_::class];
        foreach ($prefixOps as $prefixOp) {
            $this->fixupMap[$prefixOp] = ['expr' => self::FIXUP_PREC_RIGHT];
        }
    }
    /**
    * Lazily initializes the removal map.
    *
    * The removal map is used to determine which additional tokens should be removed when a
    certain node is replaced by null.
    */
    protected function initializeRemovalMap()
    {
        if ($this->removalMap) {
            return;
        }
        $stripBoth = ['left' => \T_WHITESPACE, 'right' => \T_WHITESPACE];
        $stripLeft = ['left' => \T_WHITESPACE];
        $stripRight = ['right' => \T_WHITESPACE];
        $stripDoubleArrow = ['right' => \T_DOUBLE_ARROW];
        $stripColon = ['left' => ':'];
        $stripEquals = ['left' => '='];
        $this->removalMap = ['Expr_ArrayDimFetch->dim' => $stripBoth, 'Expr_ArrayItem->key' => $stripDoubleArrow, 'Expr_ArrowFunction->returnType' => $stripColon, 'Expr_Closure->returnType' => $stripColon, 'Expr_Exit->expr' => $stripBoth, 'Expr_Ternary->if' => $stripBoth, 'Expr_Yield->key' => $stripDoubleArrow, 'Expr_Yield->value' => $stripBoth, 'Param->type' => $stripRight, 'Param->default' => $stripEquals, 'Stmt_Break->num' => $stripBoth, 'Stmt_Catch->var' => $stripLeft, 'Stmt_ClassMethod->returnType' => $stripColon, 'Stmt_Class->extends' => ['left' => \T_EXTENDS], 'Stmt_Enum->scalarType' => $stripColon, 'Stmt_EnumCase->expr' => $stripEquals, 'Expr_PrintableNewAnonClass->extends' => ['left' => \T_EXTENDS], 'Stmt_Continue->num' => $stripBoth, 'Stmt_Foreach->keyVar' => $stripDoubleArrow, 'Stmt_Function->returnType' => $stripColon, 'Stmt_If->else' => $stripLeft, 'Stmt_Namespace->name' => $stripLeft, 'Stmt_Property->type' => $stripRight, 'Stmt_PropertyProperty->default' => $stripEquals, 'Stmt_Return->expr' => $stripBoth, 'Stmt_StaticVar->default' => $stripEquals, 'Stmt_TraitUseAdaptation_Alias->newName' => $stripLeft, 'Stmt_TryCatch->finally' => $stripLeft];
    }
    /**
     *
     */
    protected function initializeInsertionMap()
    {
        if ($this->insertionMap) {
            return;
        }
        // TODO: "yield" where both key and value are inserted doesn't work
        // [$find, $beforeToken, $extraLeft, $extraRight]
        $this->insertionMap = [
            'Expr_ArrayDimFetch->dim' => ['[', \false, null, null],
            'Expr_ArrayItem->key' => [null, \false, null, ' => '],
            'Expr_ArrowFunction->returnType' => [')', \false, ' : ', null],
            'Expr_Closure->returnType' => [')', \false, ' : ', null],
            'Expr_Ternary->if' => ['?', \false, ' ', ' '],
            'Expr_Yield->key' => [\T_YIELD, \false, null, ' => '],
            'Expr_Yield->value' => [\T_YIELD, \false, ' ', null],
            'Param->type' => [null, \false, null, ' '],
            'Param->default' => [null, \false, ' = ', null],
            'Stmt_Break->num' => [\T_BREAK, \false, ' ', null],
            'Stmt_Catch->var' => [null, \false, ' ', null],
            'Stmt_ClassMethod->returnType' => [')', \false, ' : ', null],
            'Stmt_Class->extends' => [null, \false, ' extends ', null],
            'Stmt_Enum->scalarType' => [null, \false, ' : ', null],
            'Stmt_EnumCase->expr' => [null, \false, ' = ', null],
            'Expr_PrintableNewAnonClass->extends' => [null, ' extends ', null],
            'Stmt_Continue->num' => [\T_CONTINUE, \false, ' ', null],
            'Stmt_Foreach->keyVar' => [\T_AS, \false, null, ' => '],
            'Stmt_Function->returnType' => [')', \false, ' : ', null],
            'Stmt_If->else' => [null, \false, ' ', null],
            'Stmt_Namespace->name' => [\T_NAMESPACE, \false, ' ', null],
            'Stmt_Property->type' => [\T_VARIABLE, \true, null, ' '],
            'Stmt_PropertyProperty->default' => [null, \false, ' = ', null],
            'Stmt_Return->expr' => [\T_RETURN, \false, ' ', null],
            'Stmt_StaticVar->default' => [null, \false, ' = ', null],
            //'Stmt_TraitUseAdaptation_Alias->newName' => [T_AS, false, ' ', null], // TODO
            'Stmt_TryCatch->finally' => [null, \false, ' ', null],
        ];
    }
    /**
     *
     */
    protected function initializeListInsertionMap()
    {
        if ($this->listInsertionMap) {
            return;
        }
        $this->listInsertionMap = [
            // special
            //'Expr_ShellExec->parts' => '', // TODO These need to be treated more carefully
            //'Scalar_Encapsed->parts' => '',
            'Stmt_Catch->types' => '|',
            'UnionType->types' => '|',
            'IntersectionType->types' => '&',
            'Stmt_If->elseifs' => ' ',
            'Stmt_TryCatch->catches' => ' ',
            // comma-separated lists
            'Expr_Array->items' => ', ',
            'Expr_ArrowFunction->params' => ', ',
            'Expr_Closure->params' => ', ',
            'Expr_Closure->uses' => ', ',
            'Expr_FuncCall->args' => ', ',
            'Expr_Isset->vars' => ', ',
            'Expr_List->items' => ', ',
            'Expr_MethodCall->args' => ', ',
            'Expr_NullsafeMethodCall->args' => ', ',
            'Expr_New->args' => ', ',
            'Expr_PrintableNewAnonClass->args' => ', ',
            'Expr_StaticCall->args' => ', ',
            'Stmt_ClassConst->consts' => ', ',
            'Stmt_ClassMethod->params' => ', ',
            'Stmt_Class->implements' => ', ',
            'Stmt_Enum->implements' => ', ',
            'Expr_PrintableNewAnonClass->implements' => ', ',
            'Stmt_Const->consts' => ', ',
            'Stmt_Declare->declares' => ', ',
            'Stmt_Echo->exprs' => ', ',
            'Stmt_For->init' => ', ',
            'Stmt_For->cond' => ', ',
            'Stmt_For->loop' => ', ',
            'Stmt_Function->params' => ', ',
            'Stmt_Global->vars' => ', ',
            'Stmt_GroupUse->uses' => ', ',
            'Stmt_Interface->extends' => ', ',
            'Stmt_Match->arms' => ', ',
            'Stmt_Property->props' => ', ',
            'Stmt_StaticVar->vars' => ', ',
            'Stmt_TraitUse->traits' => ', ',
            'Stmt_TraitUseAdaptation_Precedence->insteadof' => ', ',
            'Stmt_Unset->vars' => ', ',
            'Stmt_Use->uses' => ', ',
            'MatchArm->conds' => ', ',
            'AttributeGroup->attrs' => ', ',
            // statement lists
            'Expr_Closure->stmts' => "\n",
            'Stmt_Case->stmts' => "\n",
            'Stmt_Catch->stmts' => "\n",
            'Stmt_Class->stmts' => "\n",
            'Stmt_Enum->stmts' => "\n",
            'Expr_PrintableNewAnonClass->stmts' => "\n",
            'Stmt_Interface->stmts' => "\n",
            'Stmt_Trait->stmts' => "\n",
            'Stmt_ClassMethod->stmts' => "\n",
            'Stmt_Declare->stmts' => "\n",
            'Stmt_Do->stmts' => "\n",
            'Stmt_ElseIf->stmts' => "\n",
            'Stmt_Else->stmts' => "\n",
            'Stmt_Finally->stmts' => "\n",
            'Stmt_Foreach->stmts' => "\n",
            'Stmt_For->stmts' => "\n",
            'Stmt_Function->stmts' => "\n",
            'Stmt_If->stmts' => "\n",
            'Stmt_Namespace->stmts' => "\n",
            'Stmt_Class->attrGroups' => "\n",
            'Stmt_Enum->attrGroups' => "\n",
            'Stmt_EnumCase->attrGroups' => "\n",
            'Stmt_Interface->attrGroups' => "\n",
            'Stmt_Trait->attrGroups' => "\n",
            'Stmt_Function->attrGroups' => "\n",
            'Stmt_ClassMethod->attrGroups' => "\n",
            'Stmt_ClassConst->attrGroups' => "\n",
            'Stmt_Property->attrGroups' => "\n",
            'Expr_PrintableNewAnonClass->attrGroups' => ' ',
            'Expr_Closure->attrGroups' => ' ',
            'Expr_ArrowFunction->attrGroups' => ' ',
            'Param->attrGroups' => ' ',
            'Stmt_Switch->cases' => "\n",
            'Stmt_TraitUse->adaptations' => "\n",
            'Stmt_TryCatch->stmts' => "\n",
            'Stmt_While->stmts' => "\n",
            // dummy for top-level context
            'File->stmts' => "\n",
        ];
    }
    /**
     *
     */
    protected function initializeEmptyListInsertionMap()
    {
        if ($this->emptyListInsertionMap) {
            return;
        }
        // TODO Insertion into empty statement lists.
        // [$find, $extraLeft, $extraRight]
        $this->emptyListInsertionMap = ['Expr_ArrowFunction->params' => ['(', '', ''], 'Expr_Closure->uses' => [')', ' use(', ')'], 'Expr_Closure->params' => ['(', '', ''], 'Expr_FuncCall->args' => ['(', '', ''], 'Expr_MethodCall->args' => ['(', '', ''], 'Expr_NullsafeMethodCall->args' => ['(', '', ''], 'Expr_New->args' => ['(', '', ''], 'Expr_PrintableNewAnonClass->args' => ['(', '', ''], 'Expr_PrintableNewAnonClass->implements' => [null, ' implements ', ''], 'Expr_StaticCall->args' => ['(', '', ''], 'Stmt_Class->implements' => [null, ' implements ', ''], 'Stmt_Enum->implements' => [null, ' implements ', ''], 'Stmt_ClassMethod->params' => ['(', '', ''], 'Stmt_Interface->extends' => [null, ' extends ', ''], 'Stmt_Function->params' => ['(', '', '']];
    }
    /**
     *
     */
    protected function initializeModifierChangeMap()
    {
        if ($this->modifierChangeMap) {
            return;
        }
        $this->modifierChangeMap = ['Stmt_ClassConst->flags' => \T_CONST, 'Stmt_ClassMethod->flags' => \T_FUNCTION, 'Stmt_Class->flags' => \T_CLASS, 'Stmt_Property->flags' => \T_VARIABLE, 'Param->flags' => \T_VARIABLE];
        // List of integer subnodes that are not modifiers:
        // Expr_Include->type
        // Stmt_GroupUse->type
        // Stmt_Use->type
        // Stmt_UseUse->type
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

/*
 * This parser is based on a skeleton written by Moriyoshi Koizumi, which in
 * turn is based on work by Masato Bito.
 */
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\Cast\Double;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Param;
use PhabelVendor\PhpParser\Node\Scalar\Encapsed;
use PhabelVendor\PhpParser\Node\Scalar\LNumber;
use PhabelVendor\PhpParser\Node\Scalar\String_;
use PhabelVendor\PhpParser\Node\Stmt\Class_;
use PhabelVendor\PhpParser\Node\Stmt\ClassConst;
use PhabelVendor\PhpParser\Node\Stmt\ClassMethod;
use PhabelVendor\PhpParser\Node\Stmt\Enum_;
use PhabelVendor\PhpParser\Node\Stmt\Interface_;
use PhabelVendor\PhpParser\Node\Stmt\Namespace_;
use PhabelVendor\PhpParser\Node\Stmt\Property;
use PhabelVendor\PhpParser\Node\Stmt\TryCatch;
use PhabelVendor\PhpParser\Node\Stmt\UseUse;
use PhabelVendor\PhpParser\Node\VarLikeIdentifier;
abstract class ParserAbstract implements Parser
{
    const SYMBOL_NONE = -1;
    /*
     * The following members will be filled with generated parsing data:
     */
    /** @var int Size of $tokenToSymbol map */
    protected $tokenToSymbolMapSize;
    /** @var int Size of $action table */
    protected $actionTableSize;
    /** @var int Size of $goto table */
    protected $gotoTableSize;
    /** @var int Symbol number signifying an invalid token */
    protected $invalidSymbol;
    /** @var int Symbol number of error recovery token */
    protected $errorSymbol;
    /** @var int Action number signifying default action */
    protected $defaultAction;
    /** @var int Rule number signifying that an unexpected token was encountered */
    protected $unexpectedTokenRule;
    protected $YY2TBLSTATE;
    /** @var int Number of non-leaf states */
    protected $numNonLeafStates;
    /** @var int[] Map of lexer tokens to internal symbols */
    protected $tokenToSymbol;
    /** @var string[] Map of symbols to their names */
    protected $symbolToName;
    /** @var array Names of the production rules (only necessary for debugging) */
    protected $productions;
    /** @var int[] Map of states to a displacement into the $action table. The corresponding action for this
     *             state/symbol pair is $action[$actionBase[$state] + $symbol]. If $actionBase[$state] is 0, the
     *             action is defaulted, i.e. $actionDefault[$state] should be used instead. */
    protected $actionBase;
    /** @var int[] Table of actions. Indexed according to $actionBase comment. */
    protected $action;
    /** @var int[] Table indexed analogously to $action. If $actionCheck[$actionBase[$state] + $symbol] != $symbol
     *             then the action is defaulted, i.e. $actionDefault[$state] should be used instead. */
    protected $actionCheck;
    /** @var int[] Map of states to their default action */
    protected $actionDefault;
    /** @var callable[] Semantic action callbacks */
    protected $reduceCallbacks;
    /** @var int[] Map of non-terminals to a displacement into the $goto table. The corresponding goto state for this
     *             non-terminal/state pair is $goto[$gotoBase[$nonTerminal] + $state] (unless defaulted) */
    protected $gotoBase;
    /** @var int[] Table of states to goto after reduction. Indexed according to $gotoBase comment. */
    protected $goto;
    /** @var int[] Table indexed analogously to $goto. If $gotoCheck[$gotoBase[$nonTerminal] + $state] != $nonTerminal
     *             then the goto state is defaulted, i.e. $gotoDefault[$nonTerminal] should be used. */
    protected $gotoCheck;
    /** @var int[] Map of non-terminals to the default state to goto after their reduction */
    protected $gotoDefault;
    /** @var int[] Map of rules to the non-terminal on their left-hand side, i.e. the non-terminal to use for
     *             determining the state to goto after reduction. */
    protected $ruleToNonTerminal;
    /** @var int[] Map of rules to the length of their right-hand side, which is the number of elements that have to
     *             be popped from the stack(s) on reduction. */
    protected $ruleToLength;
    /*
     * The following members are part of the parser state:
     */
    /** @var Lexer Lexer that is used when parsing */
    protected $lexer;
    /** @var mixed Temporary value containing the result of last semantic action (reduction) */
    protected $semValue;
    /** @var array Semantic value stack (contains values of tokens and semantic action results) */
    protected $semStack;
    /** @var array[] Start attribute stack */
    protected $startAttributeStack;
    /** @var array[] End attribute stack */
    protected $endAttributeStack;
    /** @var array End attributes of last *shifted* token */
    protected $endAttributes;
    /** @var array Start attributes of last *read* token */
    protected $lookaheadStartAttributes;
    /** @var ErrorHandler Error handler */
    protected $errorHandler;
    /** @var int Error state, used to avoid error floods */
    protected $errorState;
    /**
     * Initialize $reduceCallbacks map.
     */
    protected abstract function initReduceCallbacks();
    /**
     * Creates a parser instance.
     *
     * Options: Currently none.
     *
     * @param Lexer $lexer A lexer
     * @param array $options Options array.
     */
    public function __construct(Lexer $lexer, array $options = [])
    {
        $this->lexer = $lexer;
        if (isset($options['throwOnError'])) {
            throw new \LogicException('"throwOnError" is no longer supported, use "errorHandler" instead');
        }
        $this->initReduceCallbacks();
    }
    /**
    * Parses PHP code into a node tree.
    *
    * If a non-throwing error handler is used, the parser will continue parsing after an error
    occurred and attempt to build a partial AST.
    *
    * @param string $code The source code to parse
    * @param (ErrorHandler | null) $errorHandler Error handler to use for lexer/parser errors, defaults
    to ErrorHandler\Throwing.
    *
    * @return (Node\Stmt[] | null) Array of statements (or null non-throwing error handler is used and
    the parser was unable to recover from an error).
    */
    public function parse(string $code, ErrorHandler $errorHandler = null)
    {
        $this->errorHandler = $errorHandler ?: new ErrorHandler\Throwing();
        $this->lexer->startLexing($code, $this->errorHandler);
        $result = $this->doParse();
        // Clear out some of the interior state, so we don't hold onto unnecessary
        // memory between uses of the parser
        $this->startAttributeStack = [];
        $this->endAttributeStack = [];
        $this->semStack = [];
        $this->semValue = null;
        return $result;
    }
    /**
     *
     */
    protected function doParse()
    {
        // We start off with no lookahead-token
        $symbol = self::SYMBOL_NONE;
        // The attributes for a node are taken from the first and last token of the node.
        // From the first token only the startAttributes are taken and from the last only
        // the endAttributes. Both are merged using the array union operator (+).
        $startAttributes = [];
        $endAttributes = [];
        $this->endAttributes = $endAttributes;
        // Keep stack of start and end attributes
        $this->startAttributeStack = [];
        $this->endAttributeStack = [$endAttributes];
        // Start off in the initial state and keep a stack of previous states
        $state = 0;
        $stateStack = [$state];
        // Semantic value stack (contains values of tokens and semantic action results)
        $this->semStack = [];
        // Current position in the stack(s)
        $stackPos = 0;
        $this->errorState = 0;
        for (;;) {
            //$this->traceNewState($state, $symbol);
            if ($this->actionBase[$state] === 0) {
                $rule = $this->actionDefault[$state];
            } else {
                if ($symbol === self::SYMBOL_NONE) {
                    // Fetch the next token id from the lexer and fetch additional info by-ref.
                    // The end attributes are fetched into a temporary variable and only set once the token is really
                    // shifted (not during read). Otherwise you would sometimes get off-by-one errors, when a rule is
                    // reduced after a token was read but not yet shifted.
                    $tokenId = $this->lexer->getNextToken($tokenValue, $startAttributes, $endAttributes);
                    // map the lexer token id to the internally used symbols
                    $symbol = $tokenId >= 0 && $tokenId < $this->tokenToSymbolMapSize ? $this->tokenToSymbol[$tokenId] : $this->invalidSymbol;
                    if ($symbol === $this->invalidSymbol) {
                        throw new \RangeException(\sprintf('The lexer returned an invalid token (id=%d, value=%s)', $tokenId, $tokenValue));
                    }
                    // Allow productions to access the start attributes of the lookahead token.
                    $this->lookaheadStartAttributes = $startAttributes;
                    //$this->traceRead($symbol);
                }
                $idx = $this->actionBase[$state] + $symbol;
                if (($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) && ($action = $this->action[$idx]) !== $this->defaultAction) {
                    /*
                     * >= numNonLeafStates: shift and reduce
                     * > 0: shift
                     * = 0: accept
                     * < 0: reduce
                     * = -YYUNEXPECTED: error
                     */
                    if ($action > 0) {
                        /* shift */
                        //$this->traceShift($symbol);
                        ++$stackPos;
                        $stateStack[$stackPos] = $state = $action;
                        $this->semStack[$stackPos] = $tokenValue;
                        $this->startAttributeStack[$stackPos] = $startAttributes;
                        $this->endAttributeStack[$stackPos] = $endAttributes;
                        $this->endAttributes = $endAttributes;
                        $symbol = self::SYMBOL_NONE;
                        if ($this->errorState) {
                            --$this->errorState;
                        }
                        if ($action < $this->numNonLeafStates) {
                            continue;
                        }
                        /* $yyn >= numNonLeafStates means shift-and-reduce */
                        $rule = $action - $this->numNonLeafStates;
                    } else {
                        $rule = -$action;
                    }
                } else {
                    $rule = $this->actionDefault[$state];
                }
            }
            for (;;) {
                if ($rule === 0) {
                    /* accept */
                    //$this->traceAccept();
                    return $this->semValue;
                } elseif ($rule !== $this->unexpectedTokenRule) {
                    /* reduce */
                    //$this->traceReduce($rule);
                    try {
                        $this->reduceCallbacks[$rule]($stackPos);
                    } catch (Error $e) {
                        if (-1 === $e->getStartLine() && isset($startAttributes['startLine'])) {
                            $e->setStartLine($startAttributes['startLine']);
                        }
                        $this->emitError($e);
                        // Can't recover from this type of error
                        return null;
                    }
                    /* Goto - shift nonterminal */
                    $lastEndAttributes = $this->endAttributeStack[$stackPos];
                    $ruleLength = $this->ruleToLength[$rule];
                    $stackPos -= $ruleLength;
                    $nonTerminal = $this->ruleToNonTerminal[$rule];
                    $idx = $this->gotoBase[$nonTerminal] + $stateStack[$stackPos];
                    if ($idx >= 0 && $idx < $this->gotoTableSize && $this->gotoCheck[$idx] === $nonTerminal) {
                        $state = $this->goto[$idx];
                    } else {
                        $state = $this->gotoDefault[$nonTerminal];
                    }
                    ++$stackPos;
                    $stateStack[$stackPos] = $state;
                    $this->semStack[$stackPos] = $this->semValue;
                    $this->endAttributeStack[$stackPos] = $lastEndAttributes;
                    if ($ruleLength === 0) {
                        // Empty productions use the start attributes of the lookahead token.
                        $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes;
                    }
                } else {
                    /* error */
                    switch ($this->errorState) {
                        case 0:
                            $msg = $this->getErrorMessage($symbol, $state);
                            $this->emitError(new Error($msg, $startAttributes + $endAttributes));
                        // Break missing intentionally
                        case 1:
                        case 2:
                            $this->errorState = 3;
                            // Pop until error-expecting state uncovered
                            while (!(($idx = $this->actionBase[$state] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $this->errorSymbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $this->errorSymbol) || ($action = $this->action[$idx]) === $this->defaultAction) {
                                // Not totally sure about this
                                if ($stackPos <= 0) {
                                    // Could not recover from error
                                    return null;
                                }
                                $state = $stateStack[--$stackPos];
                                //$this->tracePop($state);
                            }
                            //$this->traceShift($this->errorSymbol);
                            ++$stackPos;
                            $stateStack[$stackPos] = $state = $action;
                            // We treat the error symbol as being empty, so we reset the end attributes
                            // to the end attributes of the last non-error symbol
                            $this->startAttributeStack[$stackPos] = $this->lookaheadStartAttributes;
                            $this->endAttributeStack[$stackPos] = $this->endAttributeStack[$stackPos - 1];
                            $this->endAttributes = $this->endAttributeStack[$stackPos - 1];
                            break;
                        case 3:
                            if ($symbol === 0) {
                                // Reached EOF without recovering from error
                                return null;
                            }
                            //$this->traceDiscard($symbol);
                            $symbol = self::SYMBOL_NONE;
                            break 2;
                    }
                }
                if ($state < $this->numNonLeafStates) {
                    break;
                }
                /* >= numNonLeafStates means shift-and-reduce */
                $rule = $state - $this->numNonLeafStates;
            }
        }
        throw new \RuntimeException('Reached end of parser loop');
    }
    /**
     *
     */
    protected function emitError(Error $error)
    {
        $this->errorHandler->handleError($error);
    }
    /**
     * Format error message including expected tokens.
     *
     * @param int $symbol Unexpected symbol
     * @param int $state State at time of error
     *
     * @return string Formatted error message
     */
    protected function getErrorMessage(int $symbol, int $state) : string
    {
        $expectedString = '';
        if ($expected = $this->getExpectedTokens($state)) {
            $expectedString = ', expecting ' . \implode(' or ', $expected);
        }
        return 'Syntax error, unexpected ' . $this->symbolToName[$symbol] . $expectedString;
    }
    /**
     * Get limited number of expected tokens in given state.
     *
     * @param int $state State
     *
     * @return string[] Expected tokens. If too many, an empty array is returned.
     */
    protected function getExpectedTokens(int $state) : array
    {
        $expected = [];
        $base = $this->actionBase[$state];
        foreach ($this->symbolToName as $symbol => $name) {
            $idx = $base + $symbol;
            if ($idx >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol || $state < $this->YY2TBLSTATE && ($idx = $this->actionBase[$state + $this->numNonLeafStates] + $symbol) >= 0 && $idx < $this->actionTableSize && $this->actionCheck[$idx] === $symbol) {
                if ($this->action[$idx] !== $this->unexpectedTokenRule && $this->action[$idx] !== $this->defaultAction && $symbol !== $this->errorSymbol) {
                    if (\count($expected) === 4) {
                        /* Too many expected tokens */
                        return [];
                    }
                    $expected[] = $name;
                }
            }
        }
        return $expected;
    }
    /*
     * Tracing functions used for debugging the parser.
     */
    /*
    protected function traceNewState($state, $symbol) {
        echo '% State ' . $state
            . ', Lookahead ' . ($symbol == self::SYMBOL_NONE ? '--none--' : $this->symbolToName[$symbol]) . "\n";
    }
    
    protected function traceRead($symbol) {
        echo '% Reading ' . $this->symbolToName[$symbol] . "\n";
    }
    
    protected function traceShift($symbol) {
        echo '% Shift ' . $this->symbolToName[$symbol] . "\n";
    }
    
    protected function traceAccept() {
        echo "% Accepted.\n";
    }
    
    protected function traceReduce($n) {
        echo '% Reduce by (' . $n . ') ' . $this->productions[$n] . "\n";
    }
    
    protected function tracePop($state) {
        echo '% Recovering, uncovered state ' . $state . "\n";
    }
    
    protected function traceDiscard($symbol) {
        echo '% Discard ' . $this->symbolToName[$symbol] . "\n";
    }
    */
    /*
     * Helper functions invoked by semantic actions
     */
    /**
     * Moves statements of semicolon-style namespaces into $ns->stmts and checks various error conditions.
     *
     * @param Node\Stmt[] $stmts
     * @return Node\Stmt[]
     */
    protected function handleNamespaces(array $stmts) : array
    {
        $hasErrored = \false;
        $style = $this->getNamespacingStyle($stmts);
        if (null === $style) {
            // not namespaced, nothing to do
            return $stmts;
        } elseif ('brace' === $style) {
            // For braced namespaces we only have to check that there are no invalid statements between the namespaces
            $afterFirstNamespace = \false;
            foreach ($stmts as $stmt) {
                if ($stmt instanceof Node\Stmt\Namespace_) {
                    $afterFirstNamespace = \true;
                } elseif (!$stmt instanceof Node\Stmt\HaltCompiler && !$stmt instanceof Node\Stmt\Nop && $afterFirstNamespace && !$hasErrored) {
                    $this->emitError(new Error('No code may exist outside of namespace {}', $stmt->getAttributes()));
                    $hasErrored = \true;
                    // Avoid one error for every statement
                }
            }
            return $stmts;
        } else {
            // For semicolon namespaces we have to move the statements after a namespace declaration into ->stmts
            $resultStmts = [];
            $targetStmts =& $resultStmts;
            $lastNs = null;
            foreach ($stmts as $stmt) {
                if ($stmt instanceof Node\Stmt\Namespace_) {
                    if ($lastNs !== null) {
                        $this->fixupNamespaceAttributes($lastNs);
                    }
                    if ($stmt->stmts === null) {
                        $stmt->stmts = [];
                        $targetStmts =& $stmt->stmts;
                        $resultStmts[] = $stmt;
                    } else {
                        // This handles the invalid case of mixed style namespaces
                        $resultStmts[] = $stmt;
                        $targetStmts =& $resultStmts;
                    }
                    $lastNs = $stmt;
                } elseif ($stmt instanceof Node\Stmt\HaltCompiler) {
                    // __halt_compiler() is not moved into the namespace
                    $resultStmts[] = $stmt;
                } else {
                    $targetStmts[] = $stmt;
                }
            }
            if ($lastNs !== null) {
                $this->fixupNamespaceAttributes($lastNs);
            }
            return $resultStmts;
        }
    }
    /**
     *
     */
    private function fixupNamespaceAttributes(Node\Stmt\Namespace_ $stmt)
    {
        // We moved the statements into the namespace node, as such the end of the namespace node
        // needs to be extended to the end of the statements.
        if (empty($stmt->stmts)) {
            return;
        }
        // We only move the builtin end attributes here. This is the best we can do with the
        // knowledge we have.
        $endAttributes = ['endLine', 'endFilePos', 'endTokenPos'];
        $lastStmt = $stmt->stmts[\count($stmt->stmts) - 1];
        foreach ($endAttributes as $endAttribute) {
            if ($lastStmt->hasAttribute($endAttribute)) {
                $stmt->setAttribute($endAttribute, $lastStmt->getAttribute($endAttribute));
            }
        }
    }
    /**
     * Determine namespacing style (semicolon or brace)
     *
     * @param Node[] $stmts Top-level statements.
     *
     * @return (null | string) One of "semicolon", "brace" or null (no namespaces)
     */
    private function getNamespacingStyle(array $stmts)
    {
        $style = null;
        $hasNotAllowedStmts = \false;
        foreach ($stmts as $i => $stmt) {
            if ($stmt instanceof Node\Stmt\Namespace_) {
                $currentStyle = null === $stmt->stmts ? 'semicolon' : 'brace';
                if (null === $style) {
                    $style = $currentStyle;
                    if ($hasNotAllowedStmts) {
                        $this->emitError(new Error('Namespace declaration statement has to be the very first statement in the script', $stmt->getLine()));
                    }
                } elseif ($style !== $currentStyle) {
                    $this->emitError(new Error('Cannot mix bracketed namespace declarations with unbracketed namespace declarations', $stmt->getLine()));
                    // Treat like semicolon style for namespace normalization
                    return 'semicolon';
                }
                continue;
            }
            /* declare(), __halt_compiler() and nops can be used before a namespace declaration */
            if ($stmt instanceof Node\Stmt\Declare_ || $stmt instanceof Node\Stmt\HaltCompiler || $stmt instanceof Node\Stmt\Nop) {
                continue;
            }
            /* There may be a hashbang line at the very start of the file */
            if ($i === 0 && $stmt instanceof Node\Stmt\InlineHTML && \preg_match('/\\A#!.*\\r?\\n\\z/', $stmt->value)) {
                continue;
            }
            /* Everything else if forbidden before namespace declarations */
            $hasNotAllowedStmts = \true;
        }
        return $style;
    }
    /**
    * Fix up parsing of static property calls in PHP 5.
    *
    * In PHP 5 A::$b[c][d] and A::$b[c][d]() have very different interpretation. The former is
    interpreted as (A::$b)[c][d], while the latter is the same as A::{$b[c][d]}(). We parse the
    latter as the former initially and this method fixes the AST into the correct form when we
    encounter the "()".
    *
    * @param (Node\Expr\StaticPropertyFetch | Node\Expr\ArrayDimFetch) $prop
    * @param Node\Arg[] $args
    * @param array $attributes
    *
    * @return Expr\StaticCall
    */
    protected function fixupPhp5StaticPropCall($prop, array $args, array $attributes) : Expr\StaticCall
    {
        if ($prop instanceof Node\Expr\StaticPropertyFetch) {
            $name = $prop->name instanceof VarLikeIdentifier ? $prop->name->toString() : $prop->name;
            $var = new Expr\Variable($name, $prop->name->getAttributes());
            return new Expr\StaticCall($prop->class, $var, $args, $attributes);
        } elseif ($prop instanceof Node\Expr\ArrayDimFetch) {
            $tmp = $prop;
            while ($tmp->var instanceof Node\Expr\ArrayDimFetch) {
                $tmp = $tmp->var;
            }
            /** @var Expr\StaticPropertyFetch $staticProp */
            $staticProp = $tmp->var;
            // Set start attributes to attributes of innermost node
            $tmp = $prop;
            $this->fixupStartAttributes($tmp, $staticProp->name);
            while ($tmp->var instanceof Node\Expr\ArrayDimFetch) {
                $tmp = $tmp->var;
                $this->fixupStartAttributes($tmp, $staticProp->name);
            }
            $name = $staticProp->name instanceof VarLikeIdentifier ? $staticProp->name->toString() : $staticProp->name;
            $tmp->var = new Expr\Variable($name, $staticProp->name->getAttributes());
            return new Expr\StaticCall($staticProp->class, $prop, $args, $attributes);
        } else {
            throw new \Exception();
        }
    }
    /**
     *
     */
    protected function fixupStartAttributes(Node $to, Node $from)
    {
        $startAttributes = ['startLine', 'startFilePos', 'startTokenPos'];
        foreach ($startAttributes as $startAttribute) {
            if ($from->hasAttribute($startAttribute)) {
                $to->setAttribute($startAttribute, $from->getAttribute($startAttribute));
            }
        }
    }
    /**
     *
     */
    protected function handleBuiltinTypes(Name $name)
    {
        $builtinTypes = ['bool' => \true, 'int' => \true, 'float' => \true, 'string' => \true, 'iterable' => \true, 'void' => \true, 'object' => \true, 'null' => \true, 'false' => \true, 'mixed' => \true, 'never' => \true];
        if (!$name->isUnqualified()) {
            return $name;
        }
        $lowerName = $name->toLowerString();
        if (!isset($builtinTypes[$lowerName])) {
            return $name;
        }
        return new Node\Identifier($lowerName, $name->getAttributes());
    }
    /**
     * Get combined start and end attributes at a stack location
     *
     * @param int $pos Stack location
     *
     * @return array Combined start and end attributes
     */
    protected function getAttributesAt(int $pos) : array
    {
        return $this->startAttributeStack[$pos] + $this->endAttributeStack[$pos];
    }
    /**
     *
     */
    protected function getFloatCastKind(string $cast) : int
    {
        $cast = \strtolower($cast);
        if (\strpos($cast, 'float') !== \false) {
            return Double::KIND_FLOAT;
        }
        if (\strpos($cast, 'real') !== \false) {
            return Double::KIND_REAL;
        }
        return Double::KIND_DOUBLE;
    }
    /**
     *
     */
    protected function parseLNumber($str, $attributes, $allowInvalidOctal = \false)
    {
        try {
            return LNumber::fromString($str, $attributes, $allowInvalidOctal);
        } catch (Error $error) {
            $this->emitError($error);
            // Use dummy value
            return new LNumber(0, $attributes);
        }
    }
    /**
     * Parse a T_NUM_STRING token into either an integer or string node.
     *
     * @param string $str Number string
     * @param array $attributes Attributes
     *
     * @return (LNumber | String_) Integer or string node.
     */
    protected function parseNumString(string $str, array $attributes)
    {
        if (!\preg_match('/^(?:0|-?[1-9][0-9]*)$/', $str)) {
            return new String_($str, $attributes);
        }
        $num = +$str;
        if (!\is_int($num)) {
            return new String_($str, $attributes);
        }
        return new LNumber($num, $attributes);
    }
    /**
     *
     */
    protected function stripIndentation(string $string, int $indentLen, string $indentChar, bool $newlineAtStart, bool $newlineAtEnd, array $attributes)
    {
        if ($indentLen === 0) {
            return $string;
        }
        $start = $newlineAtStart ? '(?:(?<=\\n)|\\A)' : '(?<=\\n)';
        $end = $newlineAtEnd ? '(?:(?=[\\r\\n])|\\z)' : '(?=[\\r\\n])';
        $regex = '/' . $start . '([ \\t]*)(' . $end . ')?/';
        return \preg_replace_callback($regex, function ($matches) use($indentLen, $indentChar, $attributes) {
            $prefix = \Phabel\Target\Php80\Polyfill::substr($matches[1], 0, $indentLen);
            if (\false !== \strpos($prefix, $indentChar === " " ? "\t" : " ")) {
                $this->emitError(new Error('Invalid indentation - tabs and spaces cannot be mixed', $attributes));
            } elseif (\strlen($prefix) < $indentLen && !isset($matches[2])) {
                $this->emitError(new Error('Invalid body indentation level (expecting an indentation level of at least ' . $indentLen . ')', $attributes));
            }
            return \Phabel\Target\Php80\Polyfill::substr($matches[0], \strlen($prefix));
        }, $string);
    }
    /**
     *
     */
    protected function parseDocString(string $startToken, $contents, string $endToken, array $attributes, array $endTokenAttributes, bool $parseUnicodeEscape)
    {
        $kind = \strpos($startToken, "'") === \false ? String_::KIND_HEREDOC : String_::KIND_NOWDOC;
        $regex = '/\\A[bB]?<<<[ \\t]*[\'"]?([a-zA-Z_\\x7f-\\xff][a-zA-Z0-9_\\x7f-\\xff]*)[\'"]?(?:\\r\\n|\\n|\\r)\\z/';
        $result = \preg_match($regex, $startToken, $matches);
        \assert($result === 1);
        $label = $matches[1];
        $result = \preg_match('/\\A[ \\t]*/', $endToken, $matches);
        \assert($result === 1);
        $indentation = $matches[0];
        $attributes['kind'] = $kind;
        $attributes['docLabel'] = $label;
        $attributes['docIndentation'] = $indentation;
        $indentHasSpaces = \false !== \strpos($indentation, " ");
        $indentHasTabs = \false !== \strpos($indentation, "\t");
        if ($indentHasSpaces && $indentHasTabs) {
            $this->emitError(new Error('Invalid indentation - tabs and spaces cannot be mixed', $endTokenAttributes));
            // Proceed processing as if this doc string is not indented
            $indentation = '';
        }
        $indentLen = \strlen($indentation);
        $indentChar = $indentHasSpaces ? " " : "\t";
        if (\is_string($contents)) {
            if ($contents === '') {
                return new String_('', $attributes);
            }
            $contents = $this->stripIndentation($contents, $indentLen, $indentChar, \true, \true, $attributes);
            $contents = \preg_replace('~(\\r\\n|\\n|\\r)\\z~', '', $contents);
            if ($kind === String_::KIND_HEREDOC) {
                $contents = String_::parseEscapeSequences($contents, null, $parseUnicodeEscape);
            }
            return new String_($contents, $attributes);
        } else {
            \assert(\count($contents) > 0);
            if (!$contents[0] instanceof Node\Scalar\EncapsedStringPart) {
                // If there is no leading encapsed string part, pretend there is an empty one
                $this->stripIndentation('', $indentLen, $indentChar, \true, \false, $contents[0]->getAttributes());
            }
            $newContents = [];
            foreach ($contents as $i => $part) {
                if ($part instanceof Node\Scalar\EncapsedStringPart) {
                    $isLast = $i === \count($contents) - 1;
                    $part->value = $this->stripIndentation($part->value, $indentLen, $indentChar, $i === 0, $isLast, $part->getAttributes());
                    $part->value = String_::parseEscapeSequences($part->value, null, $parseUnicodeEscape);
                    if ($isLast) {
                        $part->value = \preg_replace('~(\\r\\n|\\n|\\r)\\z~', '', $part->value);
                    }
                    if ('' === $part->value) {
                        continue;
                    }
                }
                $newContents[] = $part;
            }
            return new Encapsed($newContents, $attributes);
        }
    }
    /**
     * Create attributes for a zero-length common-capturing nop.
     *
     * @param Comment[] $comments
     * @return array
     */
    protected function createCommentNopAttributes(array $comments)
    {
        $comment = $comments[\count($comments) - 1];
        $commentEndLine = $comment->getEndLine();
        $commentEndFilePos = $comment->getEndFilePos();
        $commentEndTokenPos = $comment->getEndTokenPos();
        $attributes = ['comments' => $comments];
        if (-1 !== $commentEndLine) {
            $attributes['startLine'] = $commentEndLine;
            $attributes['endLine'] = $commentEndLine;
        }
        if (-1 !== $commentEndFilePos) {
            $attributes['startFilePos'] = $commentEndFilePos + 1;
            $attributes['endFilePos'] = $commentEndFilePos;
        }
        if (-1 !== $commentEndTokenPos) {
            $attributes['startTokenPos'] = $commentEndTokenPos + 1;
            $attributes['endTokenPos'] = $commentEndTokenPos;
        }
        return $attributes;
    }
    /**
     *
     */
    protected function checkModifier($a, $b, $modifierPos)
    {
        // Jumping through some hoops here because verifyModifier() is also used elsewhere
        try {
            Class_::verifyModifier($a, $b);
        } catch (Error $error) {
            $error->setAttributes($this->getAttributesAt($modifierPos));
            $this->emitError($error);
        }
    }
    /**
     *
     */
    protected function checkParam(Param $node)
    {
        if ($node->variadic && null !== $node->default) {
            $this->emitError(new Error('Variadic parameter cannot have a default value', $node->default->getAttributes()));
        }
    }
    /**
     *
     */
    protected function checkTryCatch(TryCatch $node)
    {
        if (empty($node->catches) && null === $node->finally) {
            $this->emitError(new Error('Cannot use try without catch or finally', $node->getAttributes()));
        }
    }
    /**
     *
     */
    protected function checkNamespace(Namespace_ $node)
    {
        if (null !== $node->stmts) {
            foreach ($node->stmts as $stmt) {
                if ($stmt instanceof Namespace_) {
                    $this->emitError(new Error('Namespace declarations cannot be nested', $stmt->getAttributes()));
                }
            }
        }
    }
    /**
     *
     */
    private function checkClassName($name, $namePos)
    {
        if (null !== $name && $name->isSpecialClassName()) {
            $this->emitError(new Error(\sprintf('Cannot use \'%s\' as class name as it is reserved', $name), $this->getAttributesAt($namePos)));
        }
    }
    /**
     *
     */
    private function checkImplementedInterfaces(array $interfaces)
    {
        foreach ($interfaces as $interface) {
            if ($interface->isSpecialClassName()) {
                $this->emitError(new Error(\sprintf('Cannot use \'%s\' as interface name as it is reserved', $interface), $interface->getAttributes()));
            }
        }
    }
    /**
     *
     */
    protected function checkClass(Class_ $node, $namePos)
    {
        $this->checkClassName($node->name, $namePos);
        if ($node->extends && $node->extends->isSpecialClassName()) {
            $this->emitError(new Error(\sprintf('Cannot use \'%s\' as class name as it is reserved', $node->extends), $node->extends->getAttributes()));
        }
        $this->checkImplementedInterfaces($node->implements);
    }
    /**
     *
     */
    protected function checkInterface(Interface_ $node, $namePos)
    {
        $this->checkClassName($node->name, $namePos);
        $this->checkImplementedInterfaces($node->extends);
    }
    /**
     *
     */
    protected function checkEnum(Enum_ $node, $namePos)
    {
        $this->checkClassName($node->name, $namePos);
        $this->checkImplementedInterfaces($node->implements);
    }
    /**
     *
     */
    protected function checkClassMethod(ClassMethod $node, $modifierPos)
    {
        if ($node->flags & Class_::MODIFIER_STATIC) {
            switch ($node->name->toLowerString()) {
                case '__construct':
                    $this->emitError(new Error(\sprintf('Constructor %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos)));
                    break;
                case '__destruct':
                    $this->emitError(new Error(\sprintf('Destructor %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos)));
                    break;
                case '__clone':
                    $this->emitError(new Error(\sprintf('Clone method %s() cannot be static', $node->name), $this->getAttributesAt($modifierPos)));
                    break;
            }
        }
        if ($node->flags & Class_::MODIFIER_READONLY) {
            $this->emitError(new Error(\sprintf('Method %s() cannot be readonly', $node->name), $this->getAttributesAt($modifierPos)));
        }
    }
    /**
     *
     */
    protected function checkClassConst(ClassConst $node, $modifierPos)
    {
        if ($node->flags & Class_::MODIFIER_STATIC) {
            $this->emitError(new Error("Cannot use 'static' as constant modifier", $this->getAttributesAt($modifierPos)));
        }
        if ($node->flags & Class_::MODIFIER_ABSTRACT) {
            $this->emitError(new Error("Cannot use 'abstract' as constant modifier", $this->getAttributesAt($modifierPos)));
        }
        if ($node->flags & Class_::MODIFIER_READONLY) {
            $this->emitError(new Error("Cannot use 'readonly' as constant modifier", $this->getAttributesAt($modifierPos)));
        }
    }
    /**
     *
     */
    protected function checkProperty(Property $node, $modifierPos)
    {
        if ($node->flags & Class_::MODIFIER_ABSTRACT) {
            $this->emitError(new Error('Properties cannot be declared abstract', $this->getAttributesAt($modifierPos)));
        }
        if ($node->flags & Class_::MODIFIER_FINAL) {
            $this->emitError(new Error('Properties cannot be declared final', $this->getAttributesAt($modifierPos)));
        }
    }
    /**
     *
     */
    protected function checkUseUse(UseUse $node, $namePos)
    {
        if ($node->alias && $node->alias->isSpecialClassName()) {
            $this->emitError(new Error(\sprintf('Cannot use %s as %s because \'%2$s\' is a special class name', $node->name, $node->alias), $this->getAttributesAt($namePos)));
        }
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

class Error extends \RuntimeException
{
    protected $rawMessage;
    protected $attributes;
    /**
    * Creates an Exception signifying a parse error.
    *
    * @param string $message Error message
    * @param (array | int) $attributes Attributes of node/token where error occurred
    (or start line of error -- deprecated)
    */
    public function __construct(string $message, $attributes = [])
    {
        $this->rawMessage = $message;
        if (\is_array($attributes)) {
            $this->attributes = $attributes;
        } else {
            $this->attributes = ['startLine' => $attributes];
        }
        $this->updateMessage();
    }
    /**
     * Gets the error message
     *
     * @return string Error message
     */
    public function getRawMessage() : string
    {
        return $this->rawMessage;
    }
    /**
     * Gets the line the error starts in.
     *
     * @return int Error start line
     */
    public function getStartLine() : int
    {
        return $this->attributes['startLine'] ?? -1;
    }
    /**
     * Gets the line the error ends in.
     *
     * @return int Error end line
     */
    public function getEndLine() : int
    {
        return $this->attributes['endLine'] ?? -1;
    }
    /**
     * Gets the attributes of the node/token the error occurred at.
     *
     * @return array
     */
    public function getAttributes() : array
    {
        return $this->attributes;
    }
    /**
     * Sets the attributes of the node/token the error occurred at.
     *
     * @param array $attributes
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
        $this->updateMessage();
    }
    /**
     * Sets the line of the PHP file the error occurred in.
     *
     * @param string $message Error message
     */
    public function setRawMessage(string $message)
    {
        $this->rawMessage = $message;
        $this->updateMessage();
    }
    /**
     * Sets the line the error starts in.
     *
     * @param int $line Error start line
     */
    public function setStartLine(int $line)
    {
        $this->attributes['startLine'] = $line;
        $this->updateMessage();
    }
    /**
     * Returns whether the error has start and end column information.
     *
     * For column information enable the startFilePos and endFilePos in the lexer options.
     *
     * @return bool
     */
    public function hasColumnInfo() : bool
    {
        return isset($this->attributes['startFilePos'], $this->attributes['endFilePos']);
    }
    /**
     * Gets the start column (1-based) into the line where the error started.
     *
     * @param string $code Source code of the file
     * @return int
     */
    public function getStartColumn(string $code) : int
    {
        if (!$this->hasColumnInfo()) {
            throw new \RuntimeException('Error does not have column information');
        }
        return $this->toColumn($code, $this->attributes['startFilePos']);
    }
    /**
     * Gets the end column (1-based) into the line where the error ended.
     *
     * @param string $code Source code of the file
     * @return int
     */
    public function getEndColumn(string $code) : int
    {
        if (!$this->hasColumnInfo()) {
            throw new \RuntimeException('Error does not have column information');
        }
        return $this->toColumn($code, $this->attributes['endFilePos']);
    }
    /**
     * Formats message including line and column information.
     *
     * @param string $code Source code associated with the error, for calculation of the columns
     *
     * @return string Formatted message
     */
    public function getMessageWithColumnInfo(string $code) : string
    {
        return \sprintf('%s from %d:%d to %d:%d', $this->getRawMessage(), $this->getStartLine(), $this->getStartColumn($code), $this->getEndLine(), $this->getEndColumn($code));
    }
    /**
     * Converts a file offset into a column.
     *
     * @param string $code Source code that $pos indexes into
     * @param int $pos 0-based position in $code
     *
     * @return int 1-based column (relative to start of line)
     */
    private function toColumn(string $code, int $pos) : int
    {
        if ($pos > \strlen($code)) {
            throw new \RuntimeException('Invalid position information');
        }
        $lineStartPos = \strrpos($code, "\n", $pos - \strlen($code));
        if (\false === $lineStartPos) {
            $lineStartPos = -1;
        }
        return $pos - $lineStartPos;
    }
    /**
     * Updates the exception message after a change to rawMessage or rawLine.
     */
    protected function updateMessage()
    {
        $this->message = $this->rawMessage;
        if (-1 === $this->getStartLine()) {
            $this->message .= ' on unknown line';
        } else {
            $this->message .= ' on line ' . $this->getStartLine();
        }
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

interface Builder
{
    /**
     * Returns the built node.
     *
     * @return Node The built node
     */
    public function getNode() : Node;
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

abstract class NodeAbstract implements Node, \JsonSerializable
{
    protected $attributes;
    /**
     * Creates a Node.
     *
     * @param array $attributes Array of attributes
     */
    public function __construct(array $attributes = [])
    {
        $this->attributes = $attributes;
    }
    /**
     * Gets line the node started in (alias of getStartLine).
     *
     * @return int Start line (or -1 if not available)
     */
    public function getLine() : int
    {
        return $this->attributes['startLine'] ?? -1;
    }
    /**
     * Gets line the node started in.
     *
     * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default).
     *
     * @return int Start line (or -1 if not available)
     */
    public function getStartLine() : int
    {
        return $this->attributes['startLine'] ?? -1;
    }
    /**
     * Gets the line the node ended in.
     *
     * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default).
     *
     * @return int End line (or -1 if not available)
     */
    public function getEndLine() : int
    {
        return $this->attributes['endLine'] ?? -1;
    }
    /**
     * Gets the token offset of the first token that is part of this node.
     *
     * The offset is an index into the array returned by Lexer::getTokens().
     *
     * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default).
     *
     * @return int Token start position (or -1 if not available)
     */
    public function getStartTokenPos() : int
    {
        return $this->attributes['startTokenPos'] ?? -1;
    }
    /**
     * Gets the token offset of the last token that is part of this node.
     *
     * The offset is an index into the array returned by Lexer::getTokens().
     *
     * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default).
     *
     * @return int Token end position (or -1 if not available)
     */
    public function getEndTokenPos() : int
    {
        return $this->attributes['endTokenPos'] ?? -1;
    }
    /**
     * Gets the file offset of the first character that is part of this node.
     *
     * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default).
     *
     * @return int File start position (or -1 if not available)
     */
    public function getStartFilePos() : int
    {
        return $this->attributes['startFilePos'] ?? -1;
    }
    /**
     * Gets the file offset of the last character that is part of this node.
     *
     * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default).
     *
     * @return int File end position (or -1 if not available)
     */
    public function getEndFilePos() : int
    {
        return $this->attributes['endFilePos'] ?? -1;
    }
    /**
     * Gets all comments directly preceding this node.
     *
     * The comments are also available through the "comments" attribute.
     *
     * @return Comment[]
     */
    public function getComments() : array
    {
        return $this->attributes['comments'] ?? [];
    }
    /**
     * Gets the doc comment of the node.
     *
     * @return (null | Comment\Doc) Doc comment object or null
     */
    public function getDocComment()
    {
        $comments = $this->getComments();
        for ($i = \count($comments) - 1; $i >= 0; $i--) {
            $comment = $comments[$i];
            if ($comment instanceof Comment\Doc) {
                return $comment;
            }
        }
        return null;
    }
    /**
     * Sets the doc comment of the node.
     *
     * This will either replace an existing doc comment or add it to the comments array.
     *
     * @param Comment\Doc $docComment Doc comment to set
     */
    public function setDocComment(Comment\Doc $docComment)
    {
        $comments = $this->getComments();
        for ($i = \count($comments) - 1; $i >= 0; $i--) {
            if ($comments[$i] instanceof Comment\Doc) {
                // Replace existing doc comment.
                $comments[$i] = $docComment;
                $this->setAttribute('comments', $comments);
                return;
            }
        }
        // Append new doc comment.
        $comments[] = $docComment;
        $this->setAttribute('comments', $comments);
    }
    /**
     *
     */
    public function setAttribute(string $key, $value)
    {
        $this->attributes[$key] = $value;
    }
    /**
     *
     */
    public function hasAttribute(string $key) : bool
    {
        return \array_key_exists($key, $this->attributes);
    }
    /**
     *
     */
    public function getAttribute(string $key, $default = null)
    {
        if (\array_key_exists($key, $this->attributes)) {
            return $this->attributes[$key];
        }
        return $default;
    }
    /**
     *
     */
    public function getAttributes() : array
    {
        return $this->attributes;
    }
    /**
     *
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }
    /**
     * @return array
     */
    public function jsonSerialize() : array
    {
        return ['nodeType' => $this->getType()] + \get_object_vars($this);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Internal;

/**
 * Implements the Myers diff algorithm.
 *
 * Myers, Eugene W. "An O (ND) difference algorithm and its variations."
 * Algorithmica 1.1 (1986): 251-266.
 *
 * @internal
 */
class Differ
{
    private $isEqual;
    /**
     * Create differ over the given equality relation.
     *
     * @param callable $isEqual Equality relation with signature function($a, $b) : bool
     */
    public function __construct(callable $isEqual)
    {
        $this->isEqual = $isEqual;
    }
    /**
     * Calculate diff (edit script) from $old to $new.
     *
     * @param array $old Original array
     * @param array $new New array
     *
     * @return DiffElem[] Diff (edit script)
     */
    public function diff(array $old, array $new)
    {
        list($trace, $x, $y) = $this->calculateTrace($old, $new);
        return $this->extractDiff($trace, $x, $y, $old, $new);
    }
    /**
    * Calculate diff, including "replace" operations.
    *
    * If a sequence of remove operations is followed by the same number of add operations, these
    will be coalesced into replace operations.
    *
    * @param array $old Original array
    * @param array $new New array
    *
    * @return DiffElem[] Diff (edit script), including replace operations
    */
    public function diffWithReplacements(array $old, array $new)
    {
        return $this->coalesceReplacements($this->diff($old, $new));
    }
    /**
     *
     */
    private function calculateTrace(array $a, array $b)
    {
        $n = \count($a);
        $m = \count($b);
        $max = $n + $m;
        $v = [1 => 0];
        $trace = [];
        for ($d = 0; $d <= $max; $d++) {
            $trace[] = $v;
            for ($k = -$d; $k <= $d; $k += 2) {
                if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) {
                    $x = $v[$k + 1];
                } else {
                    $x = $v[$k - 1] + 1;
                }
                $y = $x - $k;
                while ($x < $n && $y < $m && ($this->isEqual)($a[$x], $b[$y])) {
                    $x++;
                    $y++;
                }
                $v[$k] = $x;
                if ($x >= $n && $y >= $m) {
                    return [$trace, $x, $y];
                }
            }
        }
        throw new \Exception('Should not happen');
    }
    /**
     *
     */
    private function extractDiff(array $trace, int $x, int $y, array $a, array $b)
    {
        $result = [];
        for ($d = \count($trace) - 1; $d >= 0; $d--) {
            $v = $trace[$d];
            $k = $x - $y;
            if ($k === -$d || $k !== $d && $v[$k - 1] < $v[$k + 1]) {
                $prevK = $k + 1;
            } else {
                $prevK = $k - 1;
            }
            $prevX = $v[$prevK];
            $prevY = $prevX - $prevK;
            while ($x > $prevX && $y > $prevY) {
                $result[] = new DiffElem(DiffElem::TYPE_KEEP, $a[$x - 1], $b[$y - 1]);
                $x--;
                $y--;
            }
            if ($d === 0) {
                break;
            }
            while ($x > $prevX) {
                $result[] = new DiffElem(DiffElem::TYPE_REMOVE, $a[$x - 1], null);
                $x--;
            }
            while ($y > $prevY) {
                $result[] = new DiffElem(DiffElem::TYPE_ADD, null, $b[$y - 1]);
                $y--;
            }
        }
        return \array_reverse($result);
    }
    /**
     * Coalesce equal-length sequences of remove+add into a replace operation.
     *
     * @param DiffElem[] $diff
     * @return DiffElem[]
     */
    private function coalesceReplacements(array $diff)
    {
        $newDiff = [];
        $c = \count($diff);
        for ($i = 0; $i < $c; $i++) {
            $diffType = $diff[$i]->type;
            if ($diffType !== DiffElem::TYPE_REMOVE) {
                $newDiff[] = $diff[$i];
                continue;
            }
            $j = $i;
            while ($j < $c && $diff[$j]->type === DiffElem::TYPE_REMOVE) {
                $j++;
            }
            $k = $j;
            while ($k < $c && $diff[$k]->type === DiffElem::TYPE_ADD) {
                $k++;
            }
            if ($j - $i === $k - $j) {
                $len = $j - $i;
                for ($n = 0; $n < $len; $n++) {
                    $newDiff[] = new DiffElem(DiffElem::TYPE_REPLACE, $diff[$i + $n]->old, $diff[$j + $n]->new);
                }
            } else {
                for (; $i < $k; $i++) {
                    $newDiff[] = $diff[$i];
                }
            }
            $i = $k - 1;
        }
        return $newDiff;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Internal;

/**
 * @internal
 */
class DiffElem
{
    const TYPE_KEEP = 0;
    const TYPE_REMOVE = 1;
    const TYPE_ADD = 2;
    const TYPE_REPLACE = 3;
    /** @var int One of the TYPE_* constants */
    public $type;
    /** @var mixed Is null for add operations */
    public $old;
    /** @var mixed Is null for remove operations */
    public $new;
    /**
     *
     */
    public function __construct(int $type, $old, $new)
    {
        $this->type = $type;
        $this->old = $old;
        $this->new = $new;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Internal;

/**
 * Provides operations on token streams, for use by pretty printer.
 *
 * @internal
 */
class TokenStream
{
    /** @var array Tokens (in token_get_all format) */
    private $tokens;
    /** @var int[] Map from position to indentation */
    private $indentMap;
    /**
     * Create token stream instance.
     *
     * @param array $tokens Tokens in token_get_all() format
     */
    public function __construct(array $tokens)
    {
        $this->tokens = $tokens;
        $this->indentMap = $this->calcIndentMap();
    }
    /**
     * Whether the given position is immediately surrounded by parenthesis.
     *
     * @param int $startPos Start position
     * @param int $endPos End position
     *
     * @return bool
     */
    public function haveParens(int $startPos, int $endPos) : bool
    {
        return $this->haveTokenImmediatelyBefore($startPos, '(') && $this->haveTokenImmediatelyAfter($endPos, ')');
    }
    /**
     * Whether the given position is immediately surrounded by braces.
     *
     * @param int $startPos Start position
     * @param int $endPos End position
     *
     * @return bool
     */
    public function haveBraces(int $startPos, int $endPos) : bool
    {
        return ($this->haveTokenImmediatelyBefore($startPos, '{') || $this->haveTokenImmediatelyBefore($startPos, \T_CURLY_OPEN)) && $this->haveTokenImmediatelyAfter($endPos, '}');
    }
    /**
     * Check whether the position is directly preceded by a certain token type.
     *
     * During this check whitespace and comments are skipped.
     *
     * @param int $pos Position before which the token should occur
     * @param (int | string) $expectedTokenType Token to check for
     *
     * @return bool Whether the expected token was found
     */
    public function haveTokenImmediatelyBefore(int $pos, $expectedTokenType) : bool
    {
        $tokens = $this->tokens;
        $pos--;
        for (; $pos >= 0; $pos--) {
            $tokenType = $tokens[$pos][0];
            if ($tokenType === $expectedTokenType) {
                return \true;
            }
            if ($tokenType !== \T_WHITESPACE && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) {
                break;
            }
        }
        return \false;
    }
    /**
     * Check whether the position is directly followed by a certain token type.
     *
     * During this check whitespace and comments are skipped.
     *
     * @param int $pos Position after which the token should occur
     * @param (int | string) $expectedTokenType Token to check for
     *
     * @return bool Whether the expected token was found
     */
    public function haveTokenImmediatelyAfter(int $pos, $expectedTokenType) : bool
    {
        $tokens = $this->tokens;
        $pos++;
        for (; $pos < \count($tokens); $pos++) {
            $tokenType = $tokens[$pos][0];
            if ($tokenType === $expectedTokenType) {
                return \true;
            }
            if ($tokenType !== \T_WHITESPACE && $tokenType !== \T_COMMENT && $tokenType !== \T_DOC_COMMENT) {
                break;
            }
        }
        return \false;
    }
    /**
     *
     */
    public function skipLeft(int $pos, $skipTokenType)
    {
        $tokens = $this->tokens;
        $pos = $this->skipLeftWhitespace($pos);
        if ($skipTokenType === \T_WHITESPACE) {
            return $pos;
        }
        if ($tokens[$pos][0] !== $skipTokenType) {
            // Shouldn't happen. The skip token MUST be there
            throw new \Exception('Encountered unexpected token');
        }
        $pos--;
        return $this->skipLeftWhitespace($pos);
    }
    /**
     *
     */
    public function skipRight(int $pos, $skipTokenType)
    {
        $tokens = $this->tokens;
        $pos = $this->skipRightWhitespace($pos);
        if ($skipTokenType === \T_WHITESPACE) {
            return $pos;
        }
        if ($tokens[$pos][0] !== $skipTokenType) {
            // Shouldn't happen. The skip token MUST be there
            throw new \Exception('Encountered unexpected token');
        }
        $pos++;
        return $this->skipRightWhitespace($pos);
    }
    /**
     * Return first non-whitespace token position smaller or equal to passed position.
     *
     * @param int $pos Token position
     * @return int Non-whitespace token position
     */
    public function skipLeftWhitespace(int $pos)
    {
        $tokens = $this->tokens;
        for (; $pos >= 0; $pos--) {
            $type = $tokens[$pos][0];
            if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) {
                break;
            }
        }
        return $pos;
    }
    /**
     * Return first non-whitespace position greater or equal to passed position.
     *
     * @param int $pos Token position
     * @return int Non-whitespace token position
     */
    public function skipRightWhitespace(int $pos)
    {
        $tokens = $this->tokens;
        for ($count = \count($tokens); $pos < $count; $pos++) {
            $type = $tokens[$pos][0];
            if ($type !== \T_WHITESPACE && $type !== \T_COMMENT && $type !== \T_DOC_COMMENT) {
                break;
            }
        }
        return $pos;
    }
    /**
     *
     */
    public function findRight(int $pos, $findTokenType)
    {
        $tokens = $this->tokens;
        for ($count = \count($tokens); $pos < $count; $pos++) {
            $type = $tokens[$pos][0];
            if ($type === $findTokenType) {
                return $pos;
            }
        }
        return -1;
    }
    /**
     * Whether the given position range contains a certain token type.
     *
     * @param int $startPos Starting position (inclusive)
     * @param int $endPos Ending position (exclusive)
     * @param (int | string) $tokenType Token type to look for
     * @return bool Whether the token occurs in the given range
     */
    public function haveTokenInRange(int $startPos, int $endPos, $tokenType)
    {
        $tokens = $this->tokens;
        for ($pos = $startPos; $pos < $endPos; $pos++) {
            if ($tokens[$pos][0] === $tokenType) {
                return \true;
            }
        }
        return \false;
    }
    /**
     *
     */
    public function haveBracesInRange(int $startPos, int $endPos)
    {
        return $this->haveTokenInRange($startPos, $endPos, '{') || $this->haveTokenInRange($startPos, $endPos, \T_CURLY_OPEN) || $this->haveTokenInRange($startPos, $endPos, '}');
    }
    /**
     * Get indentation before token position.
     *
     * @param int $pos Token position
     *
     * @return int Indentation depth (in spaces)
     */
    public function getIndentationBefore(int $pos) : int
    {
        return $this->indentMap[$pos];
    }
    /**
     * Get the code corresponding to a token offset range, optionally adjusted for indentation.
     *
     * @param int $from Token start position (inclusive)
     * @param int $to Token end position (exclusive)
     * @param int $indent By how much the code should be indented (can be negative as well)
     *
     * @return string Code corresponding to token range, adjusted for indentation
     */
    public function getTokenCode(int $from, int $to, int $indent) : string
    {
        $tokens = $this->tokens;
        $result = '';
        for ($pos = $from; $pos < $to; $pos++) {
            $token = $tokens[$pos];
            if (\is_array($token)) {
                $type = $token[0];
                $content = $token[1];
                if ($type === \T_CONSTANT_ENCAPSED_STRING || $type === \T_ENCAPSED_AND_WHITESPACE) {
                    $result .= $content;
                } else {
                    // TODO Handle non-space indentation
                    if ($indent < 0) {
                        $result .= \str_replace("\n" . \str_repeat(" ", -$indent), "\n", $content);
                    } elseif ($indent > 0) {
                        $result .= \str_replace("\n", "\n" . \str_repeat(" ", $indent), $content);
                    } else {
                        $result .= $content;
                    }
                }
            } else {
                $result .= $token;
            }
        }
        return $result;
    }
    /**
     * Precalculate the indentation at every token position.
     *
     * @return int[] Token position to indentation map
     */
    private function calcIndentMap()
    {
        $indentMap = [];
        $indent = 0;
        foreach ($this->tokens as $token) {
            $indentMap[] = $indent;
            if ($token[0] === \T_WHITESPACE) {
                $content = $token[1];
                $newlinePos = \strrpos($content, "\n");
                if (\false !== $newlinePos) {
                    $indent = \strlen($content) - $newlinePos - 1;
                }
            }
        }
        // Add a sentinel for one past end of the file
        $indentMap[] = $indent;
        return $indentMap;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Internal;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
/**
 * This node is used internally by the format-preserving pretty printer to print anonymous classes.
 *
 * The normal anonymous class structure violates assumptions about the order of token offsets.
 * Namely, the constructor arguments are part of the Expr\New_ node and follow the class node, even
 * though they are actually interleaved with them. This special node type is used temporarily to
 * restore a sane token offset order.
 *
 * @internal
 */
class PrintableNewAnonClassNode extends Expr
{
    /** @var Node\AttributeGroup[] PHP attribute groups */
    public $attrGroups;
    /** @var Node\Arg[] Arguments */
    public $args;
    /** @var null|Node\Name Name of extended class */
    public $extends;
    /** @var Node\Name[] Names of implemented interfaces */
    public $implements;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
     *
     */
    public function __construct(array $attrGroups, array $args, Node\Name $extends = null, array $implements, array $stmts, array $attributes)
    {
        parent::__construct($attributes);
        $this->attrGroups = $attrGroups;
        $this->args = $args;
        $this->extends = $extends;
        $this->implements = $implements;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public static function fromNewNode(Expr\New_ $newNode)
    {
        $class = $newNode->class;
        \assert($class instanceof Node\Stmt\Class_);
        // We don't assert that $class->name is null here, to allow consumers to assign unique names
        // to anonymous classes for their own purposes. We simplify ignore the name here.
        return new self($class->attrGroups, $newNode->args, $class->extends, $class->implements, $class->stmts, $newNode->getAttributes());
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_PrintableNewAnonClass';
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'args', 'extends', 'implements', 'stmts'];
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Comment;

class Doc extends \PhabelVendor\PhpParser\Comment
{
}
<?php

namespace PhabelVendor\PhpParser;

class ConstExprEvaluationException extends \Exception
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

use PhabelVendor\PhpParser\Node\ComplexType;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\NullableType;
use PhabelVendor\PhpParser\Node\Scalar;
use PhabelVendor\PhpParser\Node\Stmt;
/**
 * This class defines helpers used in the implementation of builders. Don't use it directly.
 *
 * @internal
 */
final class BuilderHelpers
{
    /**
     * Normalizes a node: Converts builder objects to nodes.
     *
     * @param (Node | Builder) $node The node to normalize
     *
     * @return Node The normalized node
     */
    public static function normalizeNode($node) : Node
    {
        if ($node instanceof Builder) {
            return $node->getNode();
        }
        if ($node instanceof Node) {
            return $node;
        }
        throw new \LogicException('Expected node or builder object');
    }
    /**
     * Normalizes a node to a statement.
     *
     * Expressions are wrapped in a Stmt\Expression node.
     *
     * @param (Node | Builder) $node The node to normalize
     *
     * @return Stmt The normalized statement node
     */
    public static function normalizeStmt($node) : Stmt
    {
        $node = self::normalizeNode($node);
        if ($node instanceof Stmt) {
            return $node;
        }
        if ($node instanceof Expr) {
            return new Stmt\Expression($node);
        }
        throw new \LogicException('Expected statement or expression node');
    }
    /**
     * Normalizes strings to Identifier.
     *
     * @param (string | Identifier) $name The identifier to normalize
     *
     * @return Identifier The normalized identifier
     */
    public static function normalizeIdentifier($name) : Identifier
    {
        if ($name instanceof Identifier) {
            return $name;
        }
        if (\is_string($name)) {
            return new Identifier($name);
        }
        throw new \LogicException('PhabelVendor\\Expected string or instance of Node\\Identifier');
    }
    /**
     * Normalizes strings to Identifier, also allowing expressions.
     *
     * @param (string | Identifier | Expr) $name The identifier to normalize
     *
     * @return (Identifier | Expr) The normalized identifier or expression
     */
    public static function normalizeIdentifierOrExpr($name)
    {
        if ($name instanceof Identifier || $name instanceof Expr) {
            return $name;
        }
        if (\is_string($name)) {
            return new Identifier($name);
        }
        throw new \LogicException('PhabelVendor\\Expected string or instance of Node\\Identifier or Node\\Expr');
    }
    /**
     * Normalizes a name: Converts string names to Name nodes.
     *
     * @param (Name | string) $name The name to normalize
     *
     * @return Name The normalized name
     */
    public static function normalizeName($name) : Name
    {
        if ($name instanceof Name) {
            return $name;
        }
        if (\is_string($name)) {
            if (!$name) {
                throw new \LogicException('Name cannot be empty');
            }
            if ($name[0] === '\\') {
                return new Name\FullyQualified(\Phabel\Target\Php80\Polyfill::substr($name, 1));
            }
            if (0 === \strpos($name, 'namespace\\')) {
                return new Name\Relative(\Phabel\Target\Php80\Polyfill::substr($name, \strlen('namespace\\')));
            }
            return new Name($name);
        }
        throw new \LogicException('PhabelVendor\\Name must be a string or an instance of Node\\Name');
    }
    /**
     * Normalizes a name: Converts string names to Name nodes, while also allowing expressions.
     *
     * @param (Expr | Name | string) $name The name to normalize
     *
     * @return (Name | Expr) The normalized name or expression
     */
    public static function normalizeNameOrExpr($name)
    {
        if ($name instanceof Expr) {
            return $name;
        }
        if (!\is_string($name) && !$name instanceof Name) {
            throw new \LogicException('PhabelVendor\\Name must be a string or an instance of Node\\Name or Node\\Expr');
        }
        return self::normalizeName($name);
    }
    /**
    * Normalizes a type: Converts plain-text type names into proper AST representation.
    *
    * In particular, builtin types become Identifiers, custom types become Names and nullables
    are wrapped in NullableType nodes.
    *
    * @param (string | Name | Identifier | ComplexType) $type The type to normalize
    *
    * @return (Name | Identifier | ComplexType) The normalized type
    */
    public static function normalizeType($type)
    {
        if (!\is_string($type)) {
            if (!$type instanceof Name && !$type instanceof Identifier && !$type instanceof ComplexType) {
                throw new \LogicException('Type must be a string, or an instance of Name, Identifier or ComplexType');
            }
            return $type;
        }
        $nullable = \false;
        if (\strlen($type) > 0 && $type[0] === '?') {
            $nullable = \true;
            $type = \Phabel\Target\Php80\Polyfill::substr($type, 1);
        }
        $builtinTypes = ['array', 'callable', 'string', 'int', 'float', 'bool', 'iterable', 'void', 'object', 'mixed', 'never'];
        $lowerType = \strtolower($type);
        if (\in_array($lowerType, $builtinTypes)) {
            $type = new Identifier($lowerType);
        } else {
            $type = self::normalizeName($type);
        }
        $notNullableTypes = ['void', 'mixed', 'never'];
        if ($nullable && \in_array((string) $type, $notNullableTypes)) {
            throw new \LogicException(\sprintf('%s type cannot be nullable', $type));
        }
        return $nullable ? new NullableType($type) : $type;
    }
    /**
    * Normalizes a value: Converts nulls, booleans, integers,
    floats, strings and arrays into their respective nodes
    *
    * @param (Node\Expr | bool | null | int | float | string | array) $value The value to normalize
    *
    * @return Expr The normalized value
    */
    public static function normalizeValue($value) : Expr
    {
        if ($value instanceof Node\Expr) {
            return $value;
        }
        if (\is_null($value)) {
            return new Expr\ConstFetch(new Name('null'));
        }
        if (\is_bool($value)) {
            return new Expr\ConstFetch(new Name($value ? 'true' : 'false'));
        }
        if (\is_int($value)) {
            return new Scalar\LNumber($value);
        }
        if (\is_float($value)) {
            return new Scalar\DNumber($value);
        }
        if (\is_string($value)) {
            return new Scalar\String_($value);
        }
        if (\is_array($value)) {
            $items = [];
            $lastKey = -1;
            foreach ($value as $itemKey => $itemValue) {
                // for consecutive, numeric keys don't generate keys
                if (null !== $lastKey && ++$lastKey === $itemKey) {
                    $items[] = new Expr\ArrayItem(self::normalizeValue($itemValue));
                } else {
                    $lastKey = null;
                    $items[] = new Expr\ArrayItem(self::normalizeValue($itemValue), self::normalizeValue($itemKey));
                }
            }
            return new Expr\Array_($items);
        }
        throw new \LogicException('Invalid value');
    }
    /**
     * Normalizes a doc comment: Converts plain strings to PhpParser\Comment\Doc.
     *
     * @param (Comment\Doc | string) $docComment The doc comment to normalize
     *
     * @return Comment\Doc The normalized doc comment
     */
    public static function normalizeDocComment($docComment) : Comment\Doc
    {
        if ($docComment instanceof Comment\Doc) {
            return $docComment;
        }
        if (\is_string($docComment)) {
            return new Comment\Doc($docComment);
        }
        throw new \LogicException('PhabelVendor\\Doc comment must be a string or an instance of PhpParser\\Comment\\Doc');
    }
    /**
     * Normalizes a attribute: Converts attribute to the Attribute Group if needed.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return Node\AttributeGroup The Attribute Group
     */
    public static function normalizeAttribute($attribute) : Node\AttributeGroup
    {
        if ($attribute instanceof Node\AttributeGroup) {
            return $attribute;
        }
        if (!$attribute instanceof Node\Attribute) {
            throw new \LogicException('PhabelVendor\\Attribute must be an instance of PhpParser\\Node\\Attribute or PhpParser\\Node\\AttributeGroup');
        }
        return new Node\AttributeGroup([$attribute]);
    }
    /**
     * Adds a modifier and returns new modifier bitmask.
     *
     * @param int $modifiers Existing modifiers
     * @param int $modifier Modifier to set
     *
     * @return int New modifiers
     */
    public static function addModifier(int $modifiers, int $modifier) : int
    {
        Stmt\Class_::verifyModifier($modifiers, $modifier);
        return $modifiers | $modifier;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\PrettyPrinter;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\AssignOp;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
use PhabelVendor\PhpParser\Node\Expr\Cast;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Scalar;
use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
use PhabelVendor\PhpParser\Node\Stmt;
use PhabelVendor\PhpParser\PrettyPrinterAbstract;
class Standard extends PrettyPrinterAbstract
{
    // Special nodes
    /**
     *
     */
    protected function pParam(Node\Param $node)
    {
        return $this->pAttrGroups($node->attrGroups, \true) . $this->pModifiers($node->flags) . ($node->type ? $this->p($node->type) . ' ' : '') . ($node->byRef ? '&' : '') . ($node->variadic ? '...' : '') . $this->p($node->var) . ($node->default ? ' = ' . $this->p($node->default) : '');
    }
    /**
     *
     */
    protected function pArg(Node\Arg $node)
    {
        return ($node->name ? $node->name->toString() . ': ' : '') . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value);
    }
    /**
     *
     */
    protected function pVariadicPlaceholder(Node\VariadicPlaceholder $node)
    {
        return '...';
    }
    /**
     *
     */
    protected function pConst(Node\Const_ $node)
    {
        return $node->name . ' = ' . $this->p($node->value);
    }
    /**
     *
     */
    protected function pNullableType(Node\NullableType $node)
    {
        return '?' . $this->p($node->type);
    }
    /**
     *
     */
    protected function pUnionType(Node\UnionType $node)
    {
        return $this->pImplode($node->types, '|');
    }
    /**
     *
     */
    protected function pIntersectionType(Node\IntersectionType $node)
    {
        return $this->pImplode($node->types, '&');
    }
    /**
     *
     */
    protected function pIdentifier(Node\Identifier $node)
    {
        return $node->name;
    }
    /**
     *
     */
    protected function pVarLikeIdentifier(Node\VarLikeIdentifier $node)
    {
        return '$' . $node->name;
    }
    /**
     *
     */
    protected function pAttribute(Node\Attribute $node)
    {
        return $this->p($node->name) . ($node->args ? '(' . $this->pCommaSeparated($node->args) . ')' : '');
    }
    /**
     *
     */
    protected function pAttributeGroup(Node\AttributeGroup $node)
    {
        return '#[' . $this->pCommaSeparated($node->attrs) . ']';
    }
    // Names
    /**
     *
     */
    protected function pName(Name $node)
    {
        return \implode('\\', $node->parts);
    }
    /**
     *
     */
    protected function pName_FullyQualified(Name\FullyQualified $node)
    {
        return '\\' . \implode('\\', $node->parts);
    }
    /**
     *
     */
    protected function pName_Relative(Name\Relative $node)
    {
        return 'namespace\\' . \implode('\\', $node->parts);
    }
    // Magic Constants
    /**
     *
     */
    protected function pScalar_MagicConst_Class(MagicConst\Class_ $node)
    {
        return '__CLASS__';
    }
    /**
     *
     */
    protected function pScalar_MagicConst_Dir(MagicConst\Dir $node)
    {
        return '__DIR__';
    }
    /**
     *
     */
    protected function pScalar_MagicConst_File(MagicConst\File $node)
    {
        return '__FILE__';
    }
    /**
     *
     */
    protected function pScalar_MagicConst_Function(MagicConst\Function_ $node)
    {
        return '__FUNCTION__';
    }
    /**
     *
     */
    protected function pScalar_MagicConst_Line(MagicConst\Line $node)
    {
        return '__LINE__';
    }
    /**
     *
     */
    protected function pScalar_MagicConst_Method(MagicConst\Method $node)
    {
        return '__METHOD__';
    }
    /**
     *
     */
    protected function pScalar_MagicConst_Namespace(MagicConst\Namespace_ $node)
    {
        return '__NAMESPACE__';
    }
    /**
     *
     */
    protected function pScalar_MagicConst_Trait(MagicConst\Trait_ $node)
    {
        return '__TRAIT__';
    }
    // Scalars
    /**
     *
     */
    protected function pScalar_String(Scalar\String_ $node)
    {
        $kind = $node->getAttribute('kind', Scalar\String_::KIND_SINGLE_QUOTED);
        switch ($kind) {
            case Scalar\String_::KIND_NOWDOC:
                $label = $node->getAttribute('docLabel');
                if ($label && !$this->containsEndLabel($node->value, $label)) {
                    if ($node->value === '') {
                        return "<<<'{$label}'\n{$label}" . $this->docStringEndToken;
                    }
                    return "<<<'{$label}'\n{$node->value}\n{$label}" . $this->docStringEndToken;
                }
            /* break missing intentionally */
            case Scalar\String_::KIND_SINGLE_QUOTED:
                return $this->pSingleQuotedString($node->value);
            case Scalar\String_::KIND_HEREDOC:
                $label = $node->getAttribute('docLabel');
                if ($label && !$this->containsEndLabel($node->value, $label)) {
                    if ($node->value === '') {
                        return "<<<{$label}\n{$label}" . $this->docStringEndToken;
                    }
                    $escaped = $this->escapeString($node->value, null);
                    return "<<<{$label}\n" . $escaped . "\n{$label}" . $this->docStringEndToken;
                }
            /* break missing intentionally */
            case Scalar\String_::KIND_DOUBLE_QUOTED:
                return '"' . $this->escapeString($node->value, '"') . '"';
        }
        throw new \Exception('Invalid string kind');
    }
    /**
     *
     */
    protected function pScalar_Encapsed(Scalar\Encapsed $node)
    {
        if ($node->getAttribute('kind') === Scalar\String_::KIND_HEREDOC) {
            $label = $node->getAttribute('docLabel');
            if ($label && !$this->encapsedContainsEndLabel($node->parts, $label)) {
                if (\count($node->parts) === 1 && $node->parts[0] instanceof Scalar\EncapsedStringPart && $node->parts[0]->value === '') {
                    return "<<<{$label}\n{$label}" . $this->docStringEndToken;
                }
                return "<<<{$label}\n" . $this->pEncapsList($node->parts, null) . "\n{$label}" . $this->docStringEndToken;
            }
        }
        return '"' . $this->pEncapsList($node->parts, '"') . '"';
    }
    /**
     *
     */
    protected function pScalar_LNumber(Scalar\LNumber $node)
    {
        if ($node->value === -\PHP_INT_MAX - 1) {
            // PHP_INT_MIN cannot be represented as a literal,
            // because the sign is not part of the literal
            return '(-' . \PHP_INT_MAX . '-1)';
        }
        $kind = $node->getAttribute('kind', Scalar\LNumber::KIND_DEC);
        if (Scalar\LNumber::KIND_DEC === $kind) {
            return (string) $node->value;
        }
        if ($node->value < 0) {
            $sign = '-';
            $str = (string) -$node->value;
        } else {
            $sign = '';
            $str = (string) $node->value;
        }
        switch ($kind) {
            case Scalar\LNumber::KIND_BIN:
                return $sign . '0b' . \base_convert($str, 10, 2);
            case Scalar\LNumber::KIND_OCT:
                return $sign . '0' . \base_convert($str, 10, 8);
            case Scalar\LNumber::KIND_HEX:
                return $sign . '0x' . \base_convert($str, 10, 16);
        }
        throw new \Exception('Invalid number kind');
    }
    /**
     *
     */
    protected function pScalar_DNumber(Scalar\DNumber $node)
    {
        if (!\is_finite($node->value)) {
            if ($node->value === \INF) {
                return '\\INF';
            } elseif ($node->value === -\INF) {
                return '-\\INF';
            } else {
                return '\\NAN';
            }
        }
        // Try to find a short full-precision representation
        $stringValue = \sprintf('%.16G', $node->value);
        if ($node->value !== (double) $stringValue) {
            $stringValue = \sprintf('%.17G', $node->value);
        }
        // %G is locale dependent and there exists no locale-independent alternative. We don't want
        // mess with switching locales here, so let's assume that a comma is the only non-standard
        // decimal separator we may encounter...
        $stringValue = \str_replace(',', '.', $stringValue);
        // ensure that number is really printed as float
        return \preg_match('/^-?[0-9]+$/', $stringValue) ? $stringValue . '.0' : $stringValue;
    }
    /**
     *
     */
    protected function pScalar_EncapsedStringPart(Scalar\EncapsedStringPart $node)
    {
        throw new \LogicException('Cannot directly print EncapsedStringPart');
    }
    // Assignments
    /**
     *
     */
    protected function pExpr_Assign(Expr\Assign $node)
    {
        return $this->pInfixOp(Expr\Assign::class, $node->var, ' = ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignRef(Expr\AssignRef $node)
    {
        return $this->pInfixOp(Expr\AssignRef::class, $node->var, ' =& ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_Plus(AssignOp\Plus $node)
    {
        return $this->pInfixOp(AssignOp\Plus::class, $node->var, ' += ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_Minus(AssignOp\Minus $node)
    {
        return $this->pInfixOp(AssignOp\Minus::class, $node->var, ' -= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_Mul(AssignOp\Mul $node)
    {
        return $this->pInfixOp(AssignOp\Mul::class, $node->var, ' *= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_Div(AssignOp\Div $node)
    {
        return $this->pInfixOp(AssignOp\Div::class, $node->var, ' /= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_Concat(AssignOp\Concat $node)
    {
        return $this->pInfixOp(AssignOp\Concat::class, $node->var, ' .= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_Mod(AssignOp\Mod $node)
    {
        return $this->pInfixOp(AssignOp\Mod::class, $node->var, ' %= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_BitwiseAnd(AssignOp\BitwiseAnd $node)
    {
        return $this->pInfixOp(AssignOp\BitwiseAnd::class, $node->var, ' &= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_BitwiseOr(AssignOp\BitwiseOr $node)
    {
        return $this->pInfixOp(AssignOp\BitwiseOr::class, $node->var, ' |= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_BitwiseXor(AssignOp\BitwiseXor $node)
    {
        return $this->pInfixOp(AssignOp\BitwiseXor::class, $node->var, ' ^= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_ShiftLeft(AssignOp\ShiftLeft $node)
    {
        return $this->pInfixOp(AssignOp\ShiftLeft::class, $node->var, ' <<= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_ShiftRight(AssignOp\ShiftRight $node)
    {
        return $this->pInfixOp(AssignOp\ShiftRight::class, $node->var, ' >>= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_Pow(AssignOp\Pow $node)
    {
        return $this->pInfixOp(AssignOp\Pow::class, $node->var, ' **= ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_AssignOp_Coalesce(AssignOp\Coalesce $node)
    {
        return $this->pInfixOp(AssignOp\Coalesce::class, $node->var, ' ??= ', $node->expr);
    }
    // Binary expressions
    /**
     *
     */
    protected function pExpr_BinaryOp_Plus(BinaryOp\Plus $node)
    {
        return $this->pInfixOp(BinaryOp\Plus::class, $node->left, ' + ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Minus(BinaryOp\Minus $node)
    {
        return $this->pInfixOp(BinaryOp\Minus::class, $node->left, ' - ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Mul(BinaryOp\Mul $node)
    {
        return $this->pInfixOp(BinaryOp\Mul::class, $node->left, ' * ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Div(BinaryOp\Div $node)
    {
        return $this->pInfixOp(BinaryOp\Div::class, $node->left, ' / ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Concat(BinaryOp\Concat $node)
    {
        return $this->pInfixOp(BinaryOp\Concat::class, $node->left, ' . ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Mod(BinaryOp\Mod $node)
    {
        return $this->pInfixOp(BinaryOp\Mod::class, $node->left, ' % ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_BooleanAnd(BinaryOp\BooleanAnd $node)
    {
        return $this->pInfixOp(BinaryOp\BooleanAnd::class, $node->left, ' && ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_BooleanOr(BinaryOp\BooleanOr $node)
    {
        return $this->pInfixOp(BinaryOp\BooleanOr::class, $node->left, ' || ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_BitwiseAnd(BinaryOp\BitwiseAnd $node)
    {
        return $this->pInfixOp(BinaryOp\BitwiseAnd::class, $node->left, ' & ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_BitwiseOr(BinaryOp\BitwiseOr $node)
    {
        return $this->pInfixOp(BinaryOp\BitwiseOr::class, $node->left, ' | ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_BitwiseXor(BinaryOp\BitwiseXor $node)
    {
        return $this->pInfixOp(BinaryOp\BitwiseXor::class, $node->left, ' ^ ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_ShiftLeft(BinaryOp\ShiftLeft $node)
    {
        return $this->pInfixOp(BinaryOp\ShiftLeft::class, $node->left, ' << ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_ShiftRight(BinaryOp\ShiftRight $node)
    {
        return $this->pInfixOp(BinaryOp\ShiftRight::class, $node->left, ' >> ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Pow(BinaryOp\Pow $node)
    {
        return $this->pInfixOp(BinaryOp\Pow::class, $node->left, ' ** ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_LogicalAnd(BinaryOp\LogicalAnd $node)
    {
        return $this->pInfixOp(BinaryOp\LogicalAnd::class, $node->left, ' and ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_LogicalOr(BinaryOp\LogicalOr $node)
    {
        return $this->pInfixOp(BinaryOp\LogicalOr::class, $node->left, ' or ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_LogicalXor(BinaryOp\LogicalXor $node)
    {
        return $this->pInfixOp(BinaryOp\LogicalXor::class, $node->left, ' xor ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Equal(BinaryOp\Equal $node)
    {
        return $this->pInfixOp(BinaryOp\Equal::class, $node->left, ' == ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_NotEqual(BinaryOp\NotEqual $node)
    {
        return $this->pInfixOp(BinaryOp\NotEqual::class, $node->left, ' != ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Identical(BinaryOp\Identical $node)
    {
        return $this->pInfixOp(BinaryOp\Identical::class, $node->left, ' === ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_NotIdentical(BinaryOp\NotIdentical $node)
    {
        return $this->pInfixOp(BinaryOp\NotIdentical::class, $node->left, ' !== ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Spaceship(BinaryOp\Spaceship $node)
    {
        return $this->pInfixOp(BinaryOp\Spaceship::class, $node->left, ' <=> ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Greater(BinaryOp\Greater $node)
    {
        return $this->pInfixOp(BinaryOp\Greater::class, $node->left, ' > ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_GreaterOrEqual(BinaryOp\GreaterOrEqual $node)
    {
        return $this->pInfixOp(BinaryOp\GreaterOrEqual::class, $node->left, ' >= ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Smaller(BinaryOp\Smaller $node)
    {
        return $this->pInfixOp(BinaryOp\Smaller::class, $node->left, ' < ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_SmallerOrEqual(BinaryOp\SmallerOrEqual $node)
    {
        return $this->pInfixOp(BinaryOp\SmallerOrEqual::class, $node->left, ' <= ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_BinaryOp_Coalesce(BinaryOp\Coalesce $node)
    {
        return $this->pInfixOp(BinaryOp\Coalesce::class, $node->left, ' ?? ', $node->right);
    }
    /**
     *
     */
    protected function pExpr_Instanceof(Expr\Instanceof_ $node)
    {
        list($precedence, $associativity) = $this->precedenceMap[Expr\Instanceof_::class];
        return $this->pPrec($node->expr, $precedence, $associativity, -1) . ' instanceof ' . $this->pNewVariable($node->class);
    }
    // Unary expressions
    /**
     *
     */
    protected function pExpr_BooleanNot(Expr\BooleanNot $node)
    {
        return $this->pPrefixOp(Expr\BooleanNot::class, '!', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_BitwiseNot(Expr\BitwiseNot $node)
    {
        return $this->pPrefixOp(Expr\BitwiseNot::class, '~', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_UnaryMinus(Expr\UnaryMinus $node)
    {
        if ($node->expr instanceof Expr\UnaryMinus || $node->expr instanceof Expr\PreDec) {
            // Enforce -(-$expr) instead of --$expr
            return '-(' . $this->p($node->expr) . ')';
        }
        return $this->pPrefixOp(Expr\UnaryMinus::class, '-', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_UnaryPlus(Expr\UnaryPlus $node)
    {
        if ($node->expr instanceof Expr\UnaryPlus || $node->expr instanceof Expr\PreInc) {
            // Enforce +(+$expr) instead of ++$expr
            return '+(' . $this->p($node->expr) . ')';
        }
        return $this->pPrefixOp(Expr\UnaryPlus::class, '+', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_PreInc(Expr\PreInc $node)
    {
        return $this->pPrefixOp(Expr\PreInc::class, '++', $node->var);
    }
    /**
     *
     */
    protected function pExpr_PreDec(Expr\PreDec $node)
    {
        return $this->pPrefixOp(Expr\PreDec::class, '--', $node->var);
    }
    /**
     *
     */
    protected function pExpr_PostInc(Expr\PostInc $node)
    {
        return $this->pPostfixOp(Expr\PostInc::class, $node->var, '++');
    }
    /**
     *
     */
    protected function pExpr_PostDec(Expr\PostDec $node)
    {
        return $this->pPostfixOp(Expr\PostDec::class, $node->var, '--');
    }
    /**
     *
     */
    protected function pExpr_ErrorSuppress(Expr\ErrorSuppress $node)
    {
        return $this->pPrefixOp(Expr\ErrorSuppress::class, '@', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_YieldFrom(Expr\YieldFrom $node)
    {
        return $this->pPrefixOp(Expr\YieldFrom::class, 'yield from ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_Print(Expr\Print_ $node)
    {
        return $this->pPrefixOp(Expr\Print_::class, 'print ', $node->expr);
    }
    // Casts
    /**
     *
     */
    protected function pExpr_Cast_Int(Cast\Int_ $node)
    {
        return $this->pPrefixOp(Cast\Int_::class, '(int) ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_Cast_Double(Cast\Double $node)
    {
        $kind = $node->getAttribute('kind', Cast\Double::KIND_DOUBLE);
        if ($kind === Cast\Double::KIND_DOUBLE) {
            $cast = '(double)';
        } elseif ($kind === Cast\Double::KIND_FLOAT) {
            $cast = '(float)';
        } elseif ($kind === Cast\Double::KIND_REAL) {
            $cast = '(real)';
        }
        return $this->pPrefixOp(Cast\Double::class, $cast . ' ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_Cast_String(Cast\String_ $node)
    {
        return $this->pPrefixOp(Cast\String_::class, '(string) ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_Cast_Array(Cast\Array_ $node)
    {
        return $this->pPrefixOp(Cast\Array_::class, '(array) ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_Cast_Object(Cast\Object_ $node)
    {
        return $this->pPrefixOp(Cast\Object_::class, '(object) ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_Cast_Bool(Cast\Bool_ $node)
    {
        return $this->pPrefixOp(Cast\Bool_::class, '(bool) ', $node->expr);
    }
    /**
     *
     */
    protected function pExpr_Cast_Unset(Cast\Unset_ $node)
    {
        return $this->pPrefixOp(Cast\Unset_::class, '(unset) ', $node->expr);
    }
    // Function calls and similar constructs
    /**
     *
     */
    protected function pExpr_FuncCall(Expr\FuncCall $node)
    {
        return $this->pCallLhs($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')';
    }
    /**
     *
     */
    protected function pExpr_MethodCall(Expr\MethodCall $node)
    {
        return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')';
    }
    /**
     *
     */
    protected function pExpr_NullsafeMethodCall(Expr\NullsafeMethodCall $node)
    {
        return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name) . '(' . $this->pMaybeMultiline($node->args) . ')';
    }
    /**
     *
     */
    protected function pExpr_StaticCall(Expr\StaticCall $node)
    {
        return $this->pDereferenceLhs($node->class) . '::' . ($node->name instanceof Expr ? $node->name instanceof Expr\Variable ? $this->p($node->name) : '{' . $this->p($node->name) . '}' : $node->name) . '(' . $this->pMaybeMultiline($node->args) . ')';
    }
    /**
     *
     */
    protected function pExpr_Empty(Expr\Empty_ $node)
    {
        return 'empty(' . $this->p($node->expr) . ')';
    }
    /**
     *
     */
    protected function pExpr_Isset(Expr\Isset_ $node)
    {
        return 'isset(' . $this->pCommaSeparated($node->vars) . ')';
    }
    /**
     *
     */
    protected function pExpr_Eval(Expr\Eval_ $node)
    {
        return 'eval(' . $this->p($node->expr) . ')';
    }
    /**
     *
     */
    protected function pExpr_Include(Expr\Include_ $node)
    {
        static $map = [Expr\Include_::TYPE_INCLUDE => 'include', Expr\Include_::TYPE_INCLUDE_ONCE => 'include_once', Expr\Include_::TYPE_REQUIRE => 'require', Expr\Include_::TYPE_REQUIRE_ONCE => 'require_once'];
        return $map[$node->type] . ' ' . $this->p($node->expr);
    }
    /**
     *
     */
    protected function pExpr_List(Expr\List_ $node)
    {
        return 'list(' . $this->pCommaSeparated($node->items) . ')';
    }
    // Other
    /**
     *
     */
    protected function pExpr_Error(Expr\Error $node)
    {
        throw new \LogicException('Cannot pretty-print AST with Error nodes');
    }
    /**
     *
     */
    protected function pExpr_Variable(Expr\Variable $node)
    {
        if ($node->name instanceof Expr) {
            return '${' . $this->p($node->name) . '}';
        } else {
            return '$' . $node->name;
        }
    }
    /**
     *
     */
    protected function pExpr_Array(Expr\Array_ $node)
    {
        $syntax = $node->getAttribute('kind', $this->options['shortArraySyntax'] ? Expr\Array_::KIND_SHORT : Expr\Array_::KIND_LONG);
        if ($syntax === Expr\Array_::KIND_SHORT) {
            return '[' . $this->pMaybeMultiline($node->items, \true) . ']';
        } else {
            return 'array(' . $this->pMaybeMultiline($node->items, \true) . ')';
        }
    }
    /**
     *
     */
    protected function pExpr_ArrayItem(Expr\ArrayItem $node)
    {
        return (null !== $node->key ? $this->p($node->key) . ' => ' : '') . ($node->byRef ? '&' : '') . ($node->unpack ? '...' : '') . $this->p($node->value);
    }
    /**
     *
     */
    protected function pExpr_ArrayDimFetch(Expr\ArrayDimFetch $node)
    {
        return $this->pDereferenceLhs($node->var) . '[' . (null !== $node->dim ? $this->p($node->dim) : '') . ']';
    }
    /**
     *
     */
    protected function pExpr_ConstFetch(Expr\ConstFetch $node)
    {
        return $this->p($node->name);
    }
    /**
     *
     */
    protected function pExpr_ClassConstFetch(Expr\ClassConstFetch $node)
    {
        return $this->pDereferenceLhs($node->class) . '::' . $this->p($node->name);
    }
    /**
     *
     */
    protected function pExpr_PropertyFetch(Expr\PropertyFetch $node)
    {
        return $this->pDereferenceLhs($node->var) . '->' . $this->pObjectProperty($node->name);
    }
    /**
     *
     */
    protected function pExpr_NullsafePropertyFetch(Expr\NullsafePropertyFetch $node)
    {
        return $this->pDereferenceLhs($node->var) . '?->' . $this->pObjectProperty($node->name);
    }
    /**
     *
     */
    protected function pExpr_StaticPropertyFetch(Expr\StaticPropertyFetch $node)
    {
        return $this->pDereferenceLhs($node->class) . '::$' . $this->pObjectProperty($node->name);
    }
    /**
     *
     */
    protected function pExpr_ShellExec(Expr\ShellExec $node)
    {
        return '`' . $this->pEncapsList($node->parts, '`') . '`';
    }
    /**
     *
     */
    protected function pExpr_Closure(Expr\Closure $node)
    {
        return $this->pAttrGroups($node->attrGroups, \true) . ($node->static ? 'static ' : '') . 'function ' . ($node->byRef ? '&' : '') . '(' . $this->pCommaSeparated($node->params) . ')' . (!empty($node->uses) ? ' use(' . $this->pCommaSeparated($node->uses) . ')' : '') . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . ' {' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pExpr_Match(Expr\Match_ $node)
    {
        return 'match (' . $this->p($node->cond) . ') {' . $this->pCommaSeparatedMultiline($node->arms, \true) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pMatchArm(Node\MatchArm $node)
    {
        return ($node->conds ? $this->pCommaSeparated($node->conds) : 'default') . ' => ' . $this->p($node->body);
    }
    /**
     *
     */
    protected function pExpr_ArrowFunction(Expr\ArrowFunction $node)
    {
        return $this->pAttrGroups($node->attrGroups, \true) . ($node->static ? 'static ' : '') . 'fn' . ($node->byRef ? '&' : '') . '(' . $this->pCommaSeparated($node->params) . ')' . (null !== $node->returnType ? ': ' . $this->p($node->returnType) : '') . ' => ' . $this->pDereferenceLhs($node->expr);
    }
    /**
     *
     */
    protected function pExpr_ClosureUse(Expr\ClosureUse $node)
    {
        return ($node->byRef ? '&' : '') . $this->p($node->var);
    }
    /**
     *
     */
    protected function pExpr_New(Expr\New_ $node)
    {
        if ($node->class instanceof Stmt\Class_) {
            $args = $node->args ? '(' . $this->pMaybeMultiline($node->args) . ')' : '';
            return 'new ' . $this->pClassCommon($node->class, $args);
        }
        return 'new ' . $this->pNewVariable($node->class) . '(' . $this->pMaybeMultiline($node->args) . ')';
    }
    /**
     *
     */
    protected function pExpr_Clone(Expr\Clone_ $node)
    {
        return 'clone ' . $this->p($node->expr);
    }
    /**
     *
     */
    protected function pExpr_Ternary(Expr\Ternary $node)
    {
        // a bit of cheating: we treat the ternary as a binary op where the ?...: part is the operator.
        // this is okay because the part between ? and : never needs parentheses.
        return $this->pInfixOp(Expr\Ternary::class, $node->cond, ' ?' . (null !== $node->if ? ' ' . $this->p($node->if) . ' ' : '') . ': ', $node->else);
    }
    /**
     *
     */
    protected function pExpr_Exit(Expr\Exit_ $node)
    {
        $kind = $node->getAttribute('kind', Expr\Exit_::KIND_DIE);
        return ($kind === Expr\Exit_::KIND_EXIT ? 'exit' : 'die') . (null !== $node->expr ? '(' . $this->p($node->expr) . ')' : '');
    }
    /**
     *
     */
    protected function pExpr_Throw(Expr\Throw_ $node)
    {
        return 'throw ' . $this->p($node->expr);
    }
    /**
     *
     */
    protected function pExpr_Yield(Expr\Yield_ $node)
    {
        if ($node->value === null) {
            return 'yield';
        } else {
            // this is a bit ugly, but currently there is no way to detect whether the parentheses are necessary
            return '(yield ' . ($node->key !== null ? $this->p($node->key) . ' => ' : '') . $this->p($node->value) . ')';
        }
    }
    // Declarations
    /**
     *
     */
    protected function pStmt_Namespace(Stmt\Namespace_ $node)
    {
        if ($this->canUseSemicolonNamespaces) {
            return 'namespace ' . $this->p($node->name) . ';' . $this->nl . $this->pStmts($node->stmts, \false);
        } else {
            return 'namespace' . (null !== $node->name ? ' ' . $this->p($node->name) : '') . ' {' . $this->pStmts($node->stmts) . $this->nl . '}';
        }
    }
    /**
     *
     */
    protected function pStmt_Use(Stmt\Use_ $node)
    {
        return 'use ' . $this->pUseType($node->type) . $this->pCommaSeparated($node->uses) . ';';
    }
    /**
     *
     */
    protected function pStmt_GroupUse(Stmt\GroupUse $node)
    {
        return 'use ' . $this->pUseType($node->type) . $this->pName($node->prefix) . '\\{' . $this->pCommaSeparated($node->uses) . '};';
    }
    /**
     *
     */
    protected function pStmt_UseUse(Stmt\UseUse $node)
    {
        return $this->pUseType($node->type) . $this->p($node->name) . (null !== $node->alias ? ' as ' . $node->alias : '');
    }
    /**
     *
     */
    protected function pUseType($type)
    {
        return $type === Stmt\Use_::TYPE_FUNCTION ? 'function ' : ($type === Stmt\Use_::TYPE_CONSTANT ? 'const ' : '');
    }
    /**
     *
     */
    protected function pStmt_Interface(Stmt\Interface_ $node)
    {
        return $this->pAttrGroups($node->attrGroups) . 'interface ' . $node->name . (!empty($node->extends) ? ' extends ' . $this->pCommaSeparated($node->extends) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Enum(Stmt\Enum_ $node)
    {
        return $this->pAttrGroups($node->attrGroups) . 'enum ' . $node->name . ($node->scalarType ? " : {$node->scalarType}" : '') . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Class(Stmt\Class_ $node)
    {
        return $this->pClassCommon($node, ' ' . $node->name);
    }
    /**
     *
     */
    protected function pStmt_Trait(Stmt\Trait_ $node)
    {
        return $this->pAttrGroups($node->attrGroups) . 'trait ' . $node->name . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_EnumCase(Stmt\EnumCase $node)
    {
        return $this->pAttrGroups($node->attrGroups) . 'case ' . $node->name . ($node->expr ? ' = ' . $this->p($node->expr) : '') . ';';
    }
    /**
     *
     */
    protected function pStmt_TraitUse(Stmt\TraitUse $node)
    {
        return 'use ' . $this->pCommaSeparated($node->traits) . (empty($node->adaptations) ? ';' : ' {' . $this->pStmts($node->adaptations) . $this->nl . '}');
    }
    /**
     *
     */
    protected function pStmt_TraitUseAdaptation_Precedence(Stmt\TraitUseAdaptation\Precedence $node)
    {
        return $this->p($node->trait) . '::' . $node->method . ' insteadof ' . $this->pCommaSeparated($node->insteadof) . ';';
    }
    /**
     *
     */
    protected function pStmt_TraitUseAdaptation_Alias(Stmt\TraitUseAdaptation\Alias $node)
    {
        return (null !== $node->trait ? $this->p($node->trait) . '::' : '') . $node->method . ' as' . (null !== $node->newModifier ? ' ' . \rtrim($this->pModifiers($node->newModifier), ' ') : '') . (null !== $node->newName ? ' ' . $node->newName : '') . ';';
    }
    /**
     *
     */
    protected function pStmt_Property(Stmt\Property $node)
    {
        return $this->pAttrGroups($node->attrGroups) . (0 === $node->flags ? 'var ' : $this->pModifiers($node->flags)) . ($node->type ? $this->p($node->type) . ' ' : '') . $this->pCommaSeparated($node->props) . ';';
    }
    /**
     *
     */
    protected function pStmt_PropertyProperty(Stmt\PropertyProperty $node)
    {
        return '$' . $node->name . (null !== $node->default ? ' = ' . $this->p($node->default) : '');
    }
    /**
     *
     */
    protected function pStmt_ClassMethod(Stmt\ClassMethod $node)
    {
        return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pMaybeMultiline($node->params) . ')' . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . (null !== $node->stmts ? $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}' : ';');
    }
    /**
     *
     */
    protected function pStmt_ClassConst(Stmt\ClassConst $node)
    {
        return $this->pAttrGroups($node->attrGroups) . $this->pModifiers($node->flags) . 'const ' . $this->pCommaSeparated($node->consts) . ';';
    }
    /**
     *
     */
    protected function pStmt_Function(Stmt\Function_ $node)
    {
        return $this->pAttrGroups($node->attrGroups) . 'function ' . ($node->byRef ? '&' : '') . $node->name . '(' . $this->pCommaSeparated($node->params) . ')' . (null !== $node->returnType ? ' : ' . $this->p($node->returnType) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Const(Stmt\Const_ $node)
    {
        return 'const ' . $this->pCommaSeparated($node->consts) . ';';
    }
    /**
     *
     */
    protected function pStmt_Declare(Stmt\Declare_ $node)
    {
        return 'declare (' . $this->pCommaSeparated($node->declares) . ')' . (null !== $node->stmts ? ' {' . $this->pStmts($node->stmts) . $this->nl . '}' : ';');
    }
    /**
     *
     */
    protected function pStmt_DeclareDeclare(Stmt\DeclareDeclare $node)
    {
        return $node->key . '=' . $this->p($node->value);
    }
    // Control flow
    /**
     *
     */
    protected function pStmt_If(Stmt\If_ $node)
    {
        return 'if (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}' . ($node->elseifs ? ' ' . $this->pImplode($node->elseifs, ' ') : '') . (null !== $node->else ? ' ' . $this->p($node->else) : '');
    }
    /**
     *
     */
    protected function pStmt_ElseIf(Stmt\ElseIf_ $node)
    {
        return 'elseif (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Else(Stmt\Else_ $node)
    {
        return 'else {' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_For(Stmt\For_ $node)
    {
        return 'for (' . $this->pCommaSeparated($node->init) . ';' . (!empty($node->cond) ? ' ' : '') . $this->pCommaSeparated($node->cond) . ';' . (!empty($node->loop) ? ' ' : '') . $this->pCommaSeparated($node->loop) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Foreach(Stmt\Foreach_ $node)
    {
        return 'foreach (' . $this->p($node->expr) . ' as ' . (null !== $node->keyVar ? $this->p($node->keyVar) . ' => ' : '') . ($node->byRef ? '&' : '') . $this->p($node->valueVar) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_While(Stmt\While_ $node)
    {
        return 'while (' . $this->p($node->cond) . ') {' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Do(Stmt\Do_ $node)
    {
        return 'do {' . $this->pStmts($node->stmts) . $this->nl . '} while (' . $this->p($node->cond) . ');';
    }
    /**
     *
     */
    protected function pStmt_Switch(Stmt\Switch_ $node)
    {
        return 'switch (' . $this->p($node->cond) . ') {' . $this->pStmts($node->cases) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Case(Stmt\Case_ $node)
    {
        return (null !== $node->cond ? 'case ' . $this->p($node->cond) : 'default') . ':' . $this->pStmts($node->stmts);
    }
    /**
     *
     */
    protected function pStmt_TryCatch(Stmt\TryCatch $node)
    {
        return 'try {' . $this->pStmts($node->stmts) . $this->nl . '}' . ($node->catches ? ' ' . $this->pImplode($node->catches, ' ') : '') . ($node->finally !== null ? ' ' . $this->p($node->finally) : '');
    }
    /**
     *
     */
    protected function pStmt_Catch(Stmt\Catch_ $node)
    {
        return 'catch (' . $this->pImplode($node->types, '|') . ($node->var !== null ? ' ' . $this->p($node->var) : '') . ') {' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Finally(Stmt\Finally_ $node)
    {
        return 'finally {' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pStmt_Break(Stmt\Break_ $node)
    {
        return 'break' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';';
    }
    /**
     *
     */
    protected function pStmt_Continue(Stmt\Continue_ $node)
    {
        return 'continue' . ($node->num !== null ? ' ' . $this->p($node->num) : '') . ';';
    }
    /**
     *
     */
    protected function pStmt_Return(Stmt\Return_ $node)
    {
        return 'return' . (null !== $node->expr ? ' ' . $this->p($node->expr) : '') . ';';
    }
    /**
     *
     */
    protected function pStmt_Throw(Stmt\Throw_ $node)
    {
        return 'throw ' . $this->p($node->expr) . ';';
    }
    /**
     *
     */
    protected function pStmt_Label(Stmt\Label $node)
    {
        return $node->name . ':';
    }
    /**
     *
     */
    protected function pStmt_Goto(Stmt\Goto_ $node)
    {
        return 'goto ' . $node->name . ';';
    }
    // Other
    /**
     *
     */
    protected function pStmt_Expression(Stmt\Expression $node)
    {
        return $this->p($node->expr) . ';';
    }
    /**
     *
     */
    protected function pStmt_Echo(Stmt\Echo_ $node)
    {
        return 'echo ' . $this->pCommaSeparated($node->exprs) . ';';
    }
    /**
     *
     */
    protected function pStmt_Static(Stmt\Static_ $node)
    {
        return 'static ' . $this->pCommaSeparated($node->vars) . ';';
    }
    /**
     *
     */
    protected function pStmt_Global(Stmt\Global_ $node)
    {
        return 'global ' . $this->pCommaSeparated($node->vars) . ';';
    }
    /**
     *
     */
    protected function pStmt_StaticVar(Stmt\StaticVar $node)
    {
        return $this->p($node->var) . (null !== $node->default ? ' = ' . $this->p($node->default) : '');
    }
    /**
     *
     */
    protected function pStmt_Unset(Stmt\Unset_ $node)
    {
        return 'unset(' . $this->pCommaSeparated($node->vars) . ');';
    }
    /**
     *
     */
    protected function pStmt_InlineHTML(Stmt\InlineHTML $node)
    {
        $newline = $node->getAttribute('hasLeadingNewline', \true) ? "\n" : '';
        return '?>' . $newline . $node->value . '<?php ';
    }
    /**
     *
     */
    protected function pStmt_HaltCompiler(Stmt\HaltCompiler $node)
    {
        return '__halt_compiler();' . $node->remaining;
    }
    /**
     *
     */
    protected function pStmt_Nop(Stmt\Nop $node)
    {
        return '';
    }
    // Helpers
    /**
     *
     */
    protected function pClassCommon(Stmt\Class_ $node, $afterClassToken)
    {
        return $this->pAttrGroups($node->attrGroups, $node->name === null) . $this->pModifiers($node->flags) . 'class' . $afterClassToken . (null !== $node->extends ? ' extends ' . $this->p($node->extends) : '') . (!empty($node->implements) ? ' implements ' . $this->pCommaSeparated($node->implements) : '') . $this->nl . '{' . $this->pStmts($node->stmts) . $this->nl . '}';
    }
    /**
     *
     */
    protected function pObjectProperty($node)
    {
        if ($node instanceof Expr) {
            return '{' . $this->p($node) . '}';
        } else {
            return $node;
        }
    }
    /**
     *
     */
    protected function pEncapsList(array $encapsList, $quote)
    {
        $return = '';
        foreach ($encapsList as $element) {
            if ($element instanceof Scalar\EncapsedStringPart) {
                $return .= $this->escapeString($element->value, $quote);
            } else {
                $return .= '{' . $this->p($element) . '}';
            }
        }
        return $return;
    }
    /**
     *
     */
    protected function pSingleQuotedString(string $string)
    {
        return '\'' . \addcslashes($string, '\'\\') . '\'';
    }
    /**
     *
     */
    protected function escapeString($string, $quote)
    {
        if (null === $quote) {
            // For doc strings, don't escape newlines
            $escaped = \addcslashes($string, "\t\f\v\$\\");
        } else {
            $escaped = \addcslashes($string, "\n\r\t\f\v\$" . $quote . "\\");
        }
        // Escape control characters and non-UTF-8 characters.
        // Regex based on https://stackoverflow.com/a/11709412/385378.
        $regex = '/(
              [\\x00-\\x08\\x0E-\\x1F] # Control characters
            | [\\xC0-\\xC1] # Invalid UTF-8 Bytes
            | [\\xF5-\\xFF] # Invalid UTF-8 Bytes
            | \\xE0(?=[\\x80-\\x9F]) # Overlong encoding of prior code point
            | \\xF0(?=[\\x80-\\x8F]) # Overlong encoding of prior code point
            | [\\xC2-\\xDF](?![\\x80-\\xBF]) # Invalid UTF-8 Sequence Start
            | [\\xE0-\\xEF](?![\\x80-\\xBF]{2}) # Invalid UTF-8 Sequence Start
            | [\\xF0-\\xF4](?![\\x80-\\xBF]{3}) # Invalid UTF-8 Sequence Start
            | (?<=[\\x00-\\x7F\\xF5-\\xFF])[\\x80-\\xBF] # Invalid UTF-8 Sequence Middle
            | (?<![\\xC2-\\xDF]|[\\xE0-\\xEF]|[\\xE0-\\xEF][\\x80-\\xBF]|[\\xF0-\\xF4]|[\\xF0-\\xF4][\\x80-\\xBF]|[\\xF0-\\xF4][\\x80-\\xBF]{2})[\\x80-\\xBF] # Overlong Sequence
            | (?<=[\\xE0-\\xEF])[\\x80-\\xBF](?![\\x80-\\xBF]) # Short 3 byte sequence
            | (?<=[\\xF0-\\xF4])[\\x80-\\xBF](?![\\x80-\\xBF]{2}) # Short 4 byte sequence
            | (?<=[\\xF0-\\xF4][\\x80-\\xBF])[\\x80-\\xBF](?![\\x80-\\xBF]) # Short 4 byte sequence (2)
        )/x';
        return \preg_replace_callback($regex, function ($matches) {
            \assert(\strlen($matches[0]) === 1);
            $hex = \dechex(\ord($matches[0]));
            return '\\x' . \str_pad($hex, 2, '0', \STR_PAD_LEFT);
        }, $escaped);
    }
    /**
     *
     */
    protected function containsEndLabel($string, $label, $atStart = \true, $atEnd = \true)
    {
        $start = $atStart ? '(?:^|[\\r\\n])' : '[\\r\\n]';
        $end = $atEnd ? '(?:$|[;\\r\\n])' : '[;\\r\\n]';
        return \false !== \strpos($string, $label) && \preg_match('/' . $start . $label . $end . '/', $string);
    }
    /**
     *
     */
    protected function encapsedContainsEndLabel(array $parts, $label)
    {
        foreach ($parts as $i => $part) {
            $atStart = $i === 0;
            $atEnd = $i === \count($parts) - 1;
            if ($part instanceof Scalar\EncapsedStringPart && $this->containsEndLabel($part->value, $label, $atStart, $atEnd)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     *
     */
    protected function pDereferenceLhs(Node $node)
    {
        if (!$this->dereferenceLhsRequiresParens($node)) {
            return $this->p($node);
        } else {
            return '(' . $this->p($node) . ')';
        }
    }
    /**
     *
     */
    protected function pCallLhs(Node $node)
    {
        if (!$this->callLhsRequiresParens($node)) {
            return $this->p($node);
        } else {
            return '(' . $this->p($node) . ')';
        }
    }
    /**
     *
     */
    protected function pNewVariable(Node $node)
    {
        if (!$node instanceof Scalar\String_) {
            return $this->pDereferenceLhs($node);
        } else {
            return '(' . $this->p($node) . ')';
        }
    }
    /**
     * @param Node[] $nodes
     * @return bool
     */
    protected function hasNodeWithComments(array $nodes)
    {
        foreach ($nodes as $node) {
            if ($node && $node->getComments()) {
                return \true;
            }
        }
        return \false;
    }
    /**
     *
     */
    protected function pMaybeMultiline(array $nodes, bool $trailingComma = \false)
    {
        if (!$this->hasNodeWithComments($nodes)) {
            return $this->pCommaSeparated($nodes);
        } else {
            return $this->pCommaSeparatedMultiline($nodes, $trailingComma) . $this->nl;
        }
    }
    /**
     *
     */
    protected function pAttrGroups(array $nodes, bool $inline = \false) : string
    {
        $result = '';
        $sep = $inline ? ' ' : $this->nl;
        foreach ($nodes as $node) {
            $result .= $this->p($node) . $sep;
        }
        return $result;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

interface Node
{
    /**
     * Gets the type of the node.
     *
     * @return string Type of the node
     */
    public function getType() : string;
    /**
     * Gets the names of the sub nodes.
     *
     * @return array Names of sub nodes
     */
    public function getSubNodeNames() : array;
    /**
     * Gets line the node started in (alias of getStartLine).
     *
     * @return int Start line (or -1 if not available)
     */
    public function getLine() : int;
    /**
     * Gets line the node started in.
     *
     * Requires the 'startLine' attribute to be enabled in the lexer (enabled by default).
     *
     * @return int Start line (or -1 if not available)
     */
    public function getStartLine() : int;
    /**
     * Gets the line the node ended in.
     *
     * Requires the 'endLine' attribute to be enabled in the lexer (enabled by default).
     *
     * @return int End line (or -1 if not available)
     */
    public function getEndLine() : int;
    /**
     * Gets the token offset of the first token that is part of this node.
     *
     * The offset is an index into the array returned by Lexer::getTokens().
     *
     * Requires the 'startTokenPos' attribute to be enabled in the lexer (DISABLED by default).
     *
     * @return int Token start position (or -1 if not available)
     */
    public function getStartTokenPos() : int;
    /**
     * Gets the token offset of the last token that is part of this node.
     *
     * The offset is an index into the array returned by Lexer::getTokens().
     *
     * Requires the 'endTokenPos' attribute to be enabled in the lexer (DISABLED by default).
     *
     * @return int Token end position (or -1 if not available)
     */
    public function getEndTokenPos() : int;
    /**
     * Gets the file offset of the first character that is part of this node.
     *
     * Requires the 'startFilePos' attribute to be enabled in the lexer (DISABLED by default).
     *
     * @return int File start position (or -1 if not available)
     */
    public function getStartFilePos() : int;
    /**
     * Gets the file offset of the last character that is part of this node.
     *
     * Requires the 'endFilePos' attribute to be enabled in the lexer (DISABLED by default).
     *
     * @return int File end position (or -1 if not available)
     */
    public function getEndFilePos() : int;
    /**
     * Gets all comments directly preceding this node.
     *
     * The comments are also available through the "comments" attribute.
     *
     * @return Comment[]
     */
    public function getComments() : array;
    /**
     * Gets the doc comment of the node.
     *
     * @return (null | Comment\Doc) Doc comment object or null
     */
    public function getDocComment();
    /**
     * Sets the doc comment of the node.
     *
     * This will either replace an existing doc comment or add it to the comments array.
     *
     * @param Comment\Doc $docComment Doc comment to set
     */
    public function setDocComment(Comment\Doc $docComment);
    /**
     * Sets an attribute on a node.
     *
     * @param string $key
     * @param mixed $value
     */
    public function setAttribute(string $key, $value);
    /**
     * Returns whether an attribute exists.
     *
     * @param string $key
     *
     * @return bool
     */
    public function hasAttribute(string $key) : bool;
    /**
     * Returns the value of an attribute.
     *
     * @param string $key
     * @param mixed $default
     *
     * @return mixed
     */
    public function getAttribute(string $key, $default = null);
    /**
     * Returns all the attributes of this node.
     *
     * @return array
     */
    public function getAttributes() : array;
    /**
     * Replaces all the attributes of this node.
     *
     * @param array $attributes
     */
    public function setAttributes(array $attributes);
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

use PhabelVendor\PhpParser\Node\Expr\Include_;
use PhabelVendor\PhpParser\Node\Stmt\Class_;
use PhabelVendor\PhpParser\Node\Stmt\GroupUse;
use PhabelVendor\PhpParser\Node\Stmt\Use_;
use PhabelVendor\PhpParser\Node\Stmt\UseUse;
class NodeDumper
{
    private $dumpComments;
    private $dumpPositions;
    private $code;
    /**
    * Constructs a NodeDumper.
    *
    * Supported options:
    bool dumpComments: Whether comments should be dumped.
    bool dumpPositions: Whether line/offset information should be dumped. To dump offset
    information, the code needs to be passed to dump().
    *
    * @param array $options Options (see description)
    */
    public function __construct(array $options = [])
    {
        $this->dumpComments = !empty($options['dumpComments']);
        $this->dumpPositions = !empty($options['dumpPositions']);
    }
    /**
    * Dumps a node or array.
    *
    * @param (array | Node) $node Node or array to dump
    * @param (string | null) $code Code corresponding to dumped AST. This only needs to be passed if
    the dumpPositions option is enabled and the dumping of node offsets
    is desired.
    *
    * @return string Dumped value
    */
    public function dump($node, string $code = null) : string
    {
        $this->code = $code;
        return $this->dumpRecursive($node);
    }
    /**
     *
     */
    protected function dumpRecursive($node)
    {
        if ($node instanceof Node) {
            $r = $node->getType();
            if ($this->dumpPositions && null !== ($p = $this->dumpPosition($node))) {
                $r .= $p;
            }
            $r .= '(';
            foreach ($node->getSubNodeNames() as $key) {
                $r .= "\n    " . $key . ': ';
                $value = $node->{$key};
                if (null === $value) {
                    $r .= 'null';
                } elseif (\false === $value) {
                    $r .= 'false';
                } elseif (\true === $value) {
                    $r .= 'true';
                } elseif (\is_scalar($value)) {
                    if ('flags' === $key || 'newModifier' === $key) {
                        $r .= $this->dumpFlags($value);
                    } elseif ('type' === $key && $node instanceof Include_) {
                        $r .= $this->dumpIncludeType($value);
                    } elseif ('type' === $key && ($node instanceof Use_ || $node instanceof UseUse || $node instanceof GroupUse)) {
                        $r .= $this->dumpUseType($value);
                    } else {
                        $r .= $value;
                    }
                } else {
                    $r .= \str_replace("\n", "\n    ", $this->dumpRecursive($value));
                }
            }
            if ($this->dumpComments && ($comments = $node->getComments())) {
                $r .= "\n    comments: " . \str_replace("\n", "\n    ", $this->dumpRecursive($comments));
            }
        } elseif (\is_array($node)) {
            $r = 'array(';
            foreach ($node as $key => $value) {
                $r .= "\n    " . $key . ': ';
                if (null === $value) {
                    $r .= 'null';
                } elseif (\false === $value) {
                    $r .= 'false';
                } elseif (\true === $value) {
                    $r .= 'true';
                } elseif (\is_scalar($value)) {
                    $r .= $value;
                } else {
                    $r .= \str_replace("\n", "\n    ", $this->dumpRecursive($value));
                }
            }
        } elseif ($node instanceof Comment) {
            return $node->getReformattedText();
        } else {
            throw new \InvalidArgumentException('Can only dump nodes and arrays.');
        }
        return $r . "\n)";
    }
    /**
     *
     */
    protected function dumpFlags($flags)
    {
        $strs = [];
        if ($flags & Class_::MODIFIER_PUBLIC) {
            $strs[] = 'MODIFIER_PUBLIC';
        }
        if ($flags & Class_::MODIFIER_PROTECTED) {
            $strs[] = 'MODIFIER_PROTECTED';
        }
        if ($flags & Class_::MODIFIER_PRIVATE) {
            $strs[] = 'MODIFIER_PRIVATE';
        }
        if ($flags & Class_::MODIFIER_ABSTRACT) {
            $strs[] = 'MODIFIER_ABSTRACT';
        }
        if ($flags & Class_::MODIFIER_STATIC) {
            $strs[] = 'MODIFIER_STATIC';
        }
        if ($flags & Class_::MODIFIER_FINAL) {
            $strs[] = 'MODIFIER_FINAL';
        }
        if ($flags & Class_::MODIFIER_READONLY) {
            $strs[] = 'MODIFIER_READONLY';
        }
        if ($strs) {
            return \implode(' | ', $strs) . ' (' . $flags . ')';
        } else {
            return $flags;
        }
    }
    /**
     *
     */
    protected function dumpIncludeType($type)
    {
        $map = [Include_::TYPE_INCLUDE => 'TYPE_INCLUDE', Include_::TYPE_INCLUDE_ONCE => 'TYPE_INCLUDE_ONCE', Include_::TYPE_REQUIRE => 'TYPE_REQUIRE', Include_::TYPE_REQUIRE_ONCE => 'TYPE_REQUIRE_ONCE'];
        if (!isset($map[$type])) {
            return $type;
        }
        return $map[$type] . ' (' . $type . ')';
    }
    /**
     *
     */
    protected function dumpUseType($type)
    {
        $map = [Use_::TYPE_UNKNOWN => 'TYPE_UNKNOWN', Use_::TYPE_NORMAL => 'TYPE_NORMAL', Use_::TYPE_FUNCTION => 'TYPE_FUNCTION', Use_::TYPE_CONSTANT => 'TYPE_CONSTANT'];
        if (!isset($map[$type])) {
            return $type;
        }
        return $map[$type] . ' (' . $type . ')';
    }
    /**
     * Dump node position, if possible.
     *
     * @param Node $node Node for which to dump position
     *
     * @return (string | null) Dump of position, or null if position information not available
     */
    protected function dumpPosition(Node $node)
    {
        if (!$node->hasAttribute('startLine') || !$node->hasAttribute('endLine')) {
            return null;
        }
        $start = $node->getStartLine();
        $end = $node->getEndLine();
        if ($node->hasAttribute('startFilePos') && $node->hasAttribute('endFilePos') && null !== $this->code) {
            $start .= ':' . $this->toColumn($this->code, $node->getStartFilePos());
            $end .= ':' . $this->toColumn($this->code, $node->getEndFilePos());
        }
        return "[{$start} - {$end}]";
    }
    // Copied from Error class
    /**
     *
     */
    private function toColumn($code, $pos)
    {
        if ($pos > \strlen($code)) {
            throw new \RuntimeException('Invalid position information');
        }
        $lineStartPos = \strrpos($code, "\n", $pos - \strlen($code));
        if (\false === $lineStartPos) {
            $lineStartPos = -1;
        }
        return $pos - $lineStartPos;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
abstract class Declaration implements PhpParser\Builder
{
    protected $attributes = [];
    /**
     *
     */
    public abstract function addStmt($stmt);
    /**
     * Adds multiple statements.
     *
     * @param array $stmts The statements to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmts(array $stmts)
    {
        foreach ($stmts as $stmt) {
            $this->addStmt($stmt);
        }
        return $this;
    }
    /**
     * Sets doc comment for the declaration.
     *
     * @param (PhpParser\Comment\Doc | string) $docComment Doc comment to set
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDocComment($docComment)
    {
        $this->attributes['comments'] = [BuilderHelpers::normalizeDocComment($docComment)];
        return $this;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
class Param implements PhpParser\Builder
{
    protected $name;
    protected $default = null;
    /** @var Node\Identifier|Node\Name|Node\NullableType|null */
    protected $type = null;
    protected $byRef = \false;
    protected $variadic = \false;
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates a parameter builder.
     *
     * @param string $name Name of the parameter
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Sets default value for the parameter.
     *
     * @param mixed $value Default value to use
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDefault($value)
    {
        $this->default = BuilderHelpers::normalizeValue($value);
        return $this;
    }
    /**
     * Sets type for the parameter.
     *
     * @param (string | Node\Name | Node\Identifier | Node\ComplexType) $type Parameter type
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setType($type)
    {
        $this->type = BuilderHelpers::normalizeType($type);
        if ($this->type == 'void') {
            throw new \LogicException('Parameter type cannot be void');
        }
        return $this;
    }
    /**
     * Sets type for the parameter.
     *
     * @param (string | Node\Name | Node\Identifier | Node\ComplexType) $type Parameter type
     *
     * @return $this The builder instance (for fluid interface)
     *
     * @deprecated Use setType() instead
     */
    public function setTypeHint($type)
    {
        return $this->setType($type);
    }
    /**
     * Make the parameter accept the value by reference.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeByRef()
    {
        $this->byRef = \true;
        return $this;
    }
    /**
     * Make the parameter variadic
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeVariadic()
    {
        $this->variadic = \true;
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built parameter node.
     *
     * @return Node\Param The built parameter node
     */
    public function getNode() : Node
    {
        return new Node\Param(new Node\Expr\Variable($this->name), $this->default, $this->type, $this->byRef, $this->variadic, [], 0, $this->attributeGroups);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Stmt;
class EnumCase implements PhpParser\Builder
{
    protected $name;
    protected $value = null;
    protected $attributes = [];
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates an enum case builder.
     *
     * @param (string | Identifier) $name Name
     */
    public function __construct($name)
    {
        $this->name = $name;
    }
    /**
     * Sets the value.
     *
     * @param (Node\Expr | string | int) $value
     *
     * @return $this
     */
    public function setValue($value)
    {
        $this->value = BuilderHelpers::normalizeValue($value);
        return $this;
    }
    /**
     * Sets doc comment for the constant.
     *
     * @param (PhpParser\Comment\Doc | string) $docComment Doc comment to set
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDocComment($docComment)
    {
        $this->attributes = ['comments' => [BuilderHelpers::normalizeDocComment($docComment)]];
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built enum case node.
     *
     * @return Stmt\EnumCase The built constant node
     */
    public function getNode() : PhpParser\Node
    {
        return new Stmt\EnumCase($this->name, $this->value, $this->attributes, $this->attributeGroups);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Const_;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Stmt;
class ClassConst implements PhpParser\Builder
{
    protected $flags = 0;
    protected $attributes = [];
    protected $constants = [];
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates a class constant builder
     *
     * @param (string | Identifier) $name Name
     * @param (Node\Expr | bool | null | int | float | string | array) $value Value
     */
    public function __construct($name, $value)
    {
        $this->constants = [new Const_($name, BuilderHelpers::normalizeValue($value))];
    }
    /**
     * Add another constant to const group
     *
     * @param (string | Identifier) $name Name
     * @param (Node\Expr | bool | null | int | float | string | array) $value Value
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addConst($name, $value)
    {
        $this->constants[] = new Const_($name, BuilderHelpers::normalizeValue($value));
        return $this;
    }
    /**
     * Makes the constant public.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePublic()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC);
        return $this;
    }
    /**
     * Makes the constant protected.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeProtected()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED);
        return $this;
    }
    /**
     * Makes the constant private.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePrivate()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE);
        return $this;
    }
    /**
     * Makes the constant final.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeFinal()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
        return $this;
    }
    /**
     * Sets doc comment for the constant.
     *
     * @param (PhpParser\Comment\Doc | string) $docComment Doc comment to set
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDocComment($docComment)
    {
        $this->attributes = ['comments' => [BuilderHelpers::normalizeDocComment($docComment)]];
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built class node.
     *
     * @return Stmt\ClassConst The built constant node
     */
    public function getNode() : PhpParser\Node
    {
        return new Stmt\ClassConst($this->constants, $this->flags, $this->attributes, $this->attributeGroups);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Stmt;
class Enum_ extends Declaration
{
    protected $name;
    protected $scalarType = null;
    protected $implements = [];
    protected $uses = [];
    protected $enumCases = [];
    protected $constants = [];
    protected $methods = [];
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates an enum builder.
     *
     * @param string $name Name of the enum
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Sets the scalar type.
     *
     * @param (string | Identifier) $type
     *
     * @return $this
     */
    public function setScalarType($scalarType)
    {
        $this->scalarType = BuilderHelpers::normalizeType($scalarType);
        return $this;
    }
    /**
     * Implements one or more interfaces.
     *
     * @param (Name | string) ...$interfaces Names of interfaces to implement
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function implement(...$interfaces)
    {
        foreach ($interfaces as $interface) {
            $this->implements[] = BuilderHelpers::normalizeName($interface);
        }
        return $this;
    }
    /**
     * Adds a statement.
     *
     * @param (Stmt | PhpParser\Builder) $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt)
    {
        $stmt = BuilderHelpers::normalizeNode($stmt);
        $targets = [Stmt\TraitUse::class => &$this->uses, Stmt\EnumCase::class => &$this->enumCases, Stmt\ClassConst::class => &$this->constants, Stmt\ClassMethod::class => &$this->methods];
        $class = \get_class($stmt);
        if (!isset($targets[$class])) {
            throw new \LogicException(\sprintf('Unexpected node of type "%s"', $stmt->getType()));
        }
        $targets[$class][] = $stmt;
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built class node.
     *
     * @return Stmt\Enum_ The built enum node
     */
    public function getNode() : PhpParser\Node
    {
        return new Stmt\Enum_($this->name, ['scalarType' => $this->scalarType, 'implements' => $this->implements, 'stmts' => \array_merge($this->uses, $this->enumCases, $this->constants, $this->methods), 'attrGroups' => $this->attributeGroups], $this->attributes);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Stmt;
class Trait_ extends Declaration
{
    protected $name;
    protected $uses = [];
    protected $properties = [];
    protected $methods = [];
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates an interface builder.
     *
     * @param string $name Name of the interface
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Adds a statement.
     *
     * @param (Stmt | PhpParser\Builder) $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt)
    {
        $stmt = BuilderHelpers::normalizeNode($stmt);
        if ($stmt instanceof Stmt\Property) {
            $this->properties[] = $stmt;
        } elseif ($stmt instanceof Stmt\ClassMethod) {
            $this->methods[] = $stmt;
        } elseif ($stmt instanceof Stmt\TraitUse) {
            $this->uses[] = $stmt;
        } else {
            throw new \LogicException(\sprintf('Unexpected node of type "%s"', $stmt->getType()));
        }
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built trait node.
     *
     * @return Stmt\Trait_ The built interface node
     */
    public function getNode() : PhpParser\Node
    {
        return new Stmt\Trait_($this->name, ['stmts' => \array_merge($this->uses, $this->properties, $this->methods), 'attrGroups' => $this->attributeGroups], $this->attributes);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
abstract class FunctionLike extends Declaration
{
    protected $returnByRef = \false;
    protected $params = [];
    /** @var string|Node\Name|Node\NullableType|null */
    protected $returnType = null;
    /**
     * Make the function return by reference.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeReturnByRef()
    {
        $this->returnByRef = \true;
        return $this;
    }
    /**
     * Adds a parameter.
     *
     * @param (Node\Param | Param) $param The parameter to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addParam($param)
    {
        $param = BuilderHelpers::normalizeNode($param);
        if (!$param instanceof Node\Param) {
            throw new \LogicException(\sprintf('Expected parameter node, got "%s"', $param->getType()));
        }
        $this->params[] = $param;
        return $this;
    }
    /**
     * Adds multiple parameters.
     *
     * @param array $params The parameters to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addParams(array $params)
    {
        foreach ($params as $param) {
            $this->addParam($param);
        }
        return $this;
    }
    /**
     * Sets the return type for PHP 7.
     *
     * @param (string | Node\Name | Node\Identifier | Node\ComplexType) $type
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setReturnType($type)
    {
        $this->returnType = BuilderHelpers::normalizeType($type);
        return $this;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Stmt;
class Function_ extends FunctionLike
{
    protected $name;
    protected $stmts = [];
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates a function builder.
     *
     * @param string $name Name of the function
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Adds a statement.
     *
     * @param (Node | PhpParser\Builder) $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt)
    {
        $this->stmts[] = BuilderHelpers::normalizeStmt($stmt);
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built function node.
     *
     * @return Stmt\Function_ The built function node
     */
    public function getNode() : Node
    {
        return new Stmt\Function_($this->name, ['byRef' => $this->returnByRef, 'params' => $this->params, 'returnType' => $this->returnType, 'stmts' => $this->stmts, 'attrGroups' => $this->attributeGroups], $this->attributes);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Stmt;
class Interface_ extends Declaration
{
    protected $name;
    protected $extends = [];
    protected $constants = [];
    protected $methods = [];
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates an interface builder.
     *
     * @param string $name Name of the interface
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Extends one or more interfaces.
     *
     * @param (Name | string) ...$interfaces Names of interfaces to extend
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function extend(...$interfaces)
    {
        foreach ($interfaces as $interface) {
            $this->extends[] = BuilderHelpers::normalizeName($interface);
        }
        return $this;
    }
    /**
     * Adds a statement.
     *
     * @param (Stmt | PhpParser\Builder) $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt)
    {
        $stmt = BuilderHelpers::normalizeNode($stmt);
        if ($stmt instanceof Stmt\ClassConst) {
            $this->constants[] = $stmt;
        } elseif ($stmt instanceof Stmt\ClassMethod) {
            // we erase all statements in the body of an interface method
            $stmt->stmts = null;
            $this->methods[] = $stmt;
        } else {
            throw new \LogicException(\sprintf('Unexpected node of type "%s"', $stmt->getType()));
        }
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built interface node.
     *
     * @return Stmt\Interface_ The built interface node
     */
    public function getNode() : PhpParser\Node
    {
        return new Stmt\Interface_($this->name, ['extends' => $this->extends, 'stmts' => \array_merge($this->constants, $this->methods), 'attrGroups' => $this->attributeGroups], $this->attributes);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser\Builder;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Stmt;
class TraitUse implements Builder
{
    protected $traits = [];
    protected $adaptations = [];
    /**
     * Creates a trait use builder.
     *
     * @param (Node\Name | string) ...$traits Names of used traits
     */
    public function __construct(...$traits)
    {
        foreach ($traits as $trait) {
            $this->and($trait);
        }
    }
    /**
     * Adds used trait.
     *
     * @param (Node\Name | string) $trait Trait name
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function and($trait)
    {
        $this->traits[] = BuilderHelpers::normalizeName($trait);
        return $this;
    }
    /**
     * Adds trait adaptation.
     *
     * @param (Stmt\TraitUseAdaptation | Builder\TraitUseAdaptation) $adaptation Trait adaptation
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function with($adaptation)
    {
        $adaptation = BuilderHelpers::normalizeNode($adaptation);
        if (!$adaptation instanceof Stmt\TraitUseAdaptation) {
            throw new \LogicException('Adaptation must have type TraitUseAdaptation');
        }
        $this->adaptations[] = $adaptation;
        return $this;
    }
    /**
     * Returns the built node.
     *
     * @return Node The built node
     */
    public function getNode() : Node
    {
        return new Stmt\TraitUse($this->traits, $this->adaptations);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser\Builder;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Stmt;
class Use_ implements Builder
{
    protected $name;
    protected $type;
    protected $alias = null;
    /**
     * Creates a name use (alias) builder.
     *
     * @param (Node\Name | string) $name Name of the entity (namespace, class, function, constant) to alias
     * @param int $type One of the Stmt\Use_::TYPE_* constants
     */
    public function __construct($name, int $type)
    {
        $this->name = BuilderHelpers::normalizeName($name);
        $this->type = $type;
    }
    /**
     * Sets alias for used name.
     *
     * @param string $alias Alias to use (last component of full name by default)
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function as(string $alias)
    {
        $this->alias = $alias;
        return $this;
    }
    /**
     * Returns the built node.
     *
     * @return Stmt\Use_ The built node
     */
    public function getNode() : Node
    {
        return new Stmt\Use_([new Stmt\UseUse($this->name, $this->alias)], $this->type);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Stmt;
class Namespace_ extends Declaration
{
    private $name;
    private $stmts = [];
    /**
     * Creates a namespace builder.
     *
     * @param (Node\Name | string | null) $name Name of the namespace
     */
    public function __construct($name)
    {
        $this->name = null !== $name ? BuilderHelpers::normalizeName($name) : null;
    }
    /**
     * Adds a statement.
     *
     * @param (Node | PhpParser\Builder) $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt)
    {
        $this->stmts[] = BuilderHelpers::normalizeStmt($stmt);
        return $this;
    }
    /**
     * Returns the built node.
     *
     * @return Stmt\Namespace_ The built node
     */
    public function getNode() : Node
    {
        return new Stmt\Namespace_($this->name, $this->stmts, $this->attributes);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Stmt;
class Class_ extends Declaration
{
    protected $name;
    protected $extends = null;
    protected $implements = [];
    protected $flags = 0;
    protected $uses = [];
    protected $constants = [];
    protected $properties = [];
    protected $methods = [];
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates a class builder.
     *
     * @param string $name Name of the class
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Extends a class.
     *
     * @param (Name | string) $class Name of class to extend
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function extend($class)
    {
        $this->extends = BuilderHelpers::normalizeName($class);
        return $this;
    }
    /**
     * Implements one or more interfaces.
     *
     * @param (Name | string) ...$interfaces Names of interfaces to implement
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function implement(...$interfaces)
    {
        foreach ($interfaces as $interface) {
            $this->implements[] = BuilderHelpers::normalizeName($interface);
        }
        return $this;
    }
    /**
     * Makes the class abstract.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeAbstract()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT);
        return $this;
    }
    /**
     * Makes the class final.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeFinal()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
        return $this;
    }
    /**
     * Adds a statement.
     *
     * @param (Stmt | PhpParser\Builder) $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt)
    {
        $stmt = BuilderHelpers::normalizeNode($stmt);
        $targets = [Stmt\TraitUse::class => &$this->uses, Stmt\ClassConst::class => &$this->constants, Stmt\Property::class => &$this->properties, Stmt\ClassMethod::class => &$this->methods];
        $class = \get_class($stmt);
        if (!isset($targets[$class])) {
            throw new \LogicException(\sprintf('Unexpected node of type "%s"', $stmt->getType()));
        }
        $targets[$class][] = $stmt;
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built class node.
     *
     * @return Stmt\Class_ The built class node
     */
    public function getNode() : PhpParser\Node
    {
        return new Stmt\Class_($this->name, ['flags' => $this->flags, 'extends' => $this->extends, 'implements' => $this->implements, 'stmts' => \array_merge($this->uses, $this->constants, $this->properties, $this->methods), 'attrGroups' => $this->attributeGroups], $this->attributes);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser\Builder;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Stmt;
class TraitUseAdaptation implements Builder
{
    const TYPE_UNDEFINED = 0;
    const TYPE_ALIAS = 1;
    const TYPE_PRECEDENCE = 2;
    /** @var int Type of building adaptation */
    protected $type;
    protected $trait;
    protected $method;
    protected $modifier = null;
    protected $alias = null;
    protected $insteadof = [];
    /**
     * Creates a trait use adaptation builder.
     *
     * @param (Node\Name | string | null) $trait Name of adaptated trait
     * @param (Node\Identifier | string) $method Name of adaptated method
     */
    public function __construct($trait, $method)
    {
        $this->type = self::TYPE_UNDEFINED;
        $this->trait = \is_null($trait) ? null : BuilderHelpers::normalizeName($trait);
        $this->method = BuilderHelpers::normalizeIdentifier($method);
    }
    /**
     * Sets alias of method.
     *
     * @param (Node\Identifier | string) $alias Alias for adaptated method
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function as($alias)
    {
        if ($this->type === self::TYPE_UNDEFINED) {
            $this->type = self::TYPE_ALIAS;
        }
        if ($this->type !== self::TYPE_ALIAS) {
            throw new \LogicException('Cannot set alias for not alias adaptation buider');
        }
        $this->alias = $alias;
        return $this;
    }
    /**
     * Sets adaptated method public.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePublic()
    {
        $this->setModifier(Stmt\Class_::MODIFIER_PUBLIC);
        return $this;
    }
    /**
     * Sets adaptated method protected.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeProtected()
    {
        $this->setModifier(Stmt\Class_::MODIFIER_PROTECTED);
        return $this;
    }
    /**
     * Sets adaptated method private.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePrivate()
    {
        $this->setModifier(Stmt\Class_::MODIFIER_PRIVATE);
        return $this;
    }
    /**
     * Adds overwritten traits.
     *
     * @param (Node\Name | string) ...$traits Traits for overwrite
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function insteadof(...$traits)
    {
        if ($this->type === self::TYPE_UNDEFINED) {
            if (\is_null($this->trait)) {
                throw new \LogicException('Precedence adaptation must have trait');
            }
            $this->type = self::TYPE_PRECEDENCE;
        }
        if ($this->type !== self::TYPE_PRECEDENCE) {
            throw new \LogicException('Cannot add overwritten traits for not precedence adaptation buider');
        }
        foreach ($traits as $trait) {
            $this->insteadof[] = BuilderHelpers::normalizeName($trait);
        }
        return $this;
    }
    /**
     *
     */
    protected function setModifier(int $modifier)
    {
        if ($this->type === self::TYPE_UNDEFINED) {
            $this->type = self::TYPE_ALIAS;
        }
        if ($this->type !== self::TYPE_ALIAS) {
            throw new \LogicException('Cannot set access modifier for not alias adaptation buider');
        }
        if (\is_null($this->modifier)) {
            $this->modifier = $modifier;
        } else {
            throw new \LogicException('Multiple access type modifiers are not allowed');
        }
    }
    /**
     * Returns the built node.
     *
     * @return Node The built node
     */
    public function getNode() : Node
    {
        switch ($this->type) {
            case self::TYPE_ALIAS:
                return new Stmt\TraitUseAdaptation\Alias($this->trait, $this->method, $this->modifier, $this->alias);
            case self::TYPE_PRECEDENCE:
                return new Stmt\TraitUseAdaptation\Precedence($this->trait, $this->method, $this->insteadof);
            default:
                throw new \LogicException('Type of adaptation is not defined');
        }
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Stmt;
use PhabelVendor\PhpParser\Node\ComplexType;
class Property implements PhpParser\Builder
{
    protected $name;
    protected $flags = 0;
    protected $default = null;
    protected $attributes = [];
    /** @var null|Identifier|Name|NullableType */
    protected $type;
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates a property builder.
     *
     * @param string $name Name of the property
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Makes the property public.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePublic()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC);
        return $this;
    }
    /**
     * Makes the property protected.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeProtected()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED);
        return $this;
    }
    /**
     * Makes the property private.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePrivate()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE);
        return $this;
    }
    /**
     * Makes the property static.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeStatic()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC);
        return $this;
    }
    /**
     * Makes the property readonly.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeReadonly()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_READONLY);
        return $this;
    }
    /**
     * Sets default value for the property.
     *
     * @param mixed $value Default value to use
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDefault($value)
    {
        $this->default = BuilderHelpers::normalizeValue($value);
        return $this;
    }
    /**
     * Sets doc comment for the property.
     *
     * @param (PhpParser\Comment\Doc | string) $docComment Doc comment to set
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function setDocComment($docComment)
    {
        $this->attributes = ['comments' => [BuilderHelpers::normalizeDocComment($docComment)]];
        return $this;
    }
    /**
     * Sets the property type for PHP 7.4+.
     *
     * @param (string | Name | Identifier | ComplexType) $type
     *
     * @return $this
     */
    public function setType($type)
    {
        $this->type = BuilderHelpers::normalizeType($type);
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built class node.
     *
     * @return Stmt\Property The built property node
     */
    public function getNode() : PhpParser\Node
    {
        return new Stmt\Property($this->flags !== 0 ? $this->flags : Stmt\Class_::MODIFIER_PUBLIC, [new Stmt\PropertyProperty($this->name, $this->default)], $this->attributes, $this->type, $this->attributeGroups);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Builder;

use PhabelVendor\PhpParser;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Stmt;
class Method extends FunctionLike
{
    protected $name;
    protected $flags = 0;
    /** @var array|null */
    protected $stmts = [];
    /** @var Node\AttributeGroup[] */
    protected $attributeGroups = [];
    /**
     * Creates a method builder.
     *
     * @param string $name Name of the method
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Makes the method public.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePublic()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PUBLIC);
        return $this;
    }
    /**
     * Makes the method protected.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeProtected()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PROTECTED);
        return $this;
    }
    /**
     * Makes the method private.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makePrivate()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_PRIVATE);
        return $this;
    }
    /**
     * Makes the method static.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeStatic()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_STATIC);
        return $this;
    }
    /**
     * Makes the method abstract.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeAbstract()
    {
        if (!empty($this->stmts)) {
            throw new \LogicException('Cannot make method with statements abstract');
        }
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_ABSTRACT);
        $this->stmts = null;
        // abstract methods don't have statements
        return $this;
    }
    /**
     * Makes the method final.
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function makeFinal()
    {
        $this->flags = BuilderHelpers::addModifier($this->flags, Stmt\Class_::MODIFIER_FINAL);
        return $this;
    }
    /**
     * Adds a statement.
     *
     * @param (Node | PhpParser\Builder) $stmt The statement to add
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addStmt($stmt)
    {
        if (null === $this->stmts) {
            throw new \LogicException('Cannot add statements to an abstract method');
        }
        $this->stmts[] = BuilderHelpers::normalizeStmt($stmt);
        return $this;
    }
    /**
     * Adds an attribute group.
     *
     * @param (Node\Attribute | Node\AttributeGroup) $attribute
     *
     * @return $this The builder instance (for fluid interface)
     */
    public function addAttribute($attribute)
    {
        $this->attributeGroups[] = BuilderHelpers::normalizeAttribute($attribute);
        return $this;
    }
    /**
     * Returns the built method node.
     *
     * @return Stmt\ClassMethod The built method node
     */
    public function getNode() : Node
    {
        return new Stmt\ClassMethod($this->name, ['flags' => $this->flags, 'byRef' => $this->returnByRef, 'params' => $this->params, 'returnType' => $this->returnType, 'stmts' => $this->stmts, 'attrGroups' => $this->attributeGroups], $this->attributes);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Stmt;
class NameContext
{
    /** @var null|Name Current namespace */
    protected $namespace;
    /** @var Name[][] Map of format [aliasType => [aliasName => originalName]] */
    protected $aliases = [];
    /** @var Name[][] Same as $aliases but preserving original case */
    protected $origAliases = [];
    /** @var ErrorHandler Error handler */
    protected $errorHandler;
    /**
     * Create a name context.
     *
     * @param ErrorHandler $errorHandler Error handling used to report errors
     */
    public function __construct(ErrorHandler $errorHandler)
    {
        $this->errorHandler = $errorHandler;
    }
    /**
     * Start a new namespace.
     *
     * This also resets the alias table.
     *
     * @param (Name | null) $namespace Null is the global namespace
     */
    public function startNamespace(Name $namespace = null)
    {
        $this->namespace = $namespace;
        $this->origAliases = $this->aliases = [Stmt\Use_::TYPE_NORMAL => [], Stmt\Use_::TYPE_FUNCTION => [], Stmt\Use_::TYPE_CONSTANT => []];
    }
    /**
     * Add an alias / import.
     *
     * @param Name $name Original name
     * @param string $aliasName Aliased name
     * @param int $type One of Stmt\Use_::TYPE_*
     * @param array $errorAttrs Attributes to use to report an error
     */
    public function addAlias(Name $name, string $aliasName, int $type, array $errorAttrs = [])
    {
        // Constant names are case sensitive, everything else case insensitive
        if ($type === Stmt\Use_::TYPE_CONSTANT) {
            $aliasLookupName = $aliasName;
        } else {
            $aliasLookupName = \strtolower($aliasName);
        }
        if (isset($this->aliases[$type][$aliasLookupName])) {
            $typeStringMap = [Stmt\Use_::TYPE_NORMAL => '', Stmt\Use_::TYPE_FUNCTION => 'function ', Stmt\Use_::TYPE_CONSTANT => 'const '];
            $this->errorHandler->handleError(new Error(\sprintf('Cannot use %s%s as %s because the name is already in use', $typeStringMap[$type], $name, $aliasName), $errorAttrs));
            return;
        }
        $this->aliases[$type][$aliasLookupName] = $name;
        $this->origAliases[$type][$aliasName] = $name;
    }
    /**
     * Get current namespace.
     *
     * @return (null | Name) Namespace (or null if global namespace)
     */
    public function getNamespace()
    {
        return $this->namespace;
    }
    /**
     * Get resolved name.
     *
     * @param Name $name Name to resolve
     * @param int $type One of Stmt\Use_::TYPE_{FUNCTION|CONSTANT}
     *
     * @return (null | Name) Resolved name, or null if static resolution is not possible
     */
    public function getResolvedName(Name $name, int $type)
    {
        // don't resolve special class names
        if ($type === Stmt\Use_::TYPE_NORMAL && $name->isSpecialClassName()) {
            if (!$name->isUnqualified()) {
                $this->errorHandler->handleError(new Error(\sprintf("'\\%s' is an invalid class name", $name->toString()), $name->getAttributes()));
            }
            return $name;
        }
        // fully qualified names are already resolved
        if ($name->isFullyQualified()) {
            return $name;
        }
        // Try to resolve aliases
        if (null !== ($resolvedName = $this->resolveAlias($name, $type))) {
            return $resolvedName;
        }
        if ($type !== Stmt\Use_::TYPE_NORMAL && $name->isUnqualified()) {
            if (null === $this->namespace) {
                // outside of a namespace unaliased unqualified is same as fully qualified
                return new FullyQualified($name, $name->getAttributes());
            }
            // Cannot resolve statically
            return null;
        }
        // if no alias exists prepend current namespace
        return FullyQualified::concat($this->namespace, $name, $name->getAttributes());
    }
    /**
     * Get resolved class name.
     *
     * @param Name $name Class ame to resolve
     *
     * @return Name Resolved name
     */
    public function getResolvedClassName(Name $name) : Name
    {
        return $this->getResolvedName($name, Stmt\Use_::TYPE_NORMAL);
    }
    /**
     * Get possible ways of writing a fully qualified name (e.g., by making use of aliases).
     *
     * @param string $name Fully-qualified name (without leading namespace separator)
     * @param int $type One of Stmt\Use_::TYPE_*
     *
     * @return Name[] Possible representations of the name
     */
    public function getPossibleNames(string $name, int $type) : array
    {
        $lcName = \strtolower($name);
        if ($type === Stmt\Use_::TYPE_NORMAL) {
            // self, parent and static must always be unqualified
            if ($lcName === "self" || $lcName === "parent" || $lcName === "static") {
                return [new Name($name)];
            }
        }
        // Collect possible ways to write this name, starting with the fully-qualified name
        $possibleNames = [new FullyQualified($name)];
        if (null !== ($nsRelativeName = $this->getNamespaceRelativeName($name, $lcName, $type))) {
            // Make sure there is no alias that makes the normally namespace-relative name
            // into something else
            if (null === $this->resolveAlias($nsRelativeName, $type)) {
                $possibleNames[] = $nsRelativeName;
            }
        }
        // Check for relevant namespace use statements
        foreach ($this->origAliases[Stmt\Use_::TYPE_NORMAL] as $alias => $orig) {
            $lcOrig = $orig->toLowerString();
            if (0 === \strpos($lcName, $lcOrig . '\\')) {
                $possibleNames[] = new Name($alias . \Phabel\Target\Php80\Polyfill::substr($name, \strlen($lcOrig)));
            }
        }
        // Check for relevant type-specific use statements
        foreach ($this->origAliases[$type] as $alias => $orig) {
            if ($type === Stmt\Use_::TYPE_CONSTANT) {
                // Constants are are complicated-sensitive
                $normalizedOrig = $this->normalizeConstName($orig->toString());
                if ($normalizedOrig === $this->normalizeConstName($name)) {
                    $possibleNames[] = new Name($alias);
                }
            } else {
                // Everything else is case-insensitive
                if ($orig->toLowerString() === $lcName) {
                    $possibleNames[] = new Name($alias);
                }
            }
        }
        return $possibleNames;
    }
    /**
     * Get shortest representation of this fully-qualified name.
     *
     * @param string $name Fully-qualified name (without leading namespace separator)
     * @param int $type One of Stmt\Use_::TYPE_*
     *
     * @return Name Shortest representation
     */
    public function getShortName(string $name, int $type) : Name
    {
        $possibleNames = $this->getPossibleNames($name, $type);
        // Find shortest name
        $shortestName = null;
        $shortestLength = \INF;
        foreach ($possibleNames as $possibleName) {
            $length = \strlen($possibleName->toCodeString());
            if ($length < $shortestLength) {
                $shortestName = $possibleName;
                $shortestLength = $length;
            }
        }
        return $shortestName;
    }
    /**
     *
     */
    private function resolveAlias(Name $name, $type)
    {
        $firstPart = $name->getFirst();
        if ($name->isQualified()) {
            // resolve aliases for qualified names, always against class alias table
            $checkName = \strtolower($firstPart);
            if (isset($this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName])) {
                $alias = $this->aliases[Stmt\Use_::TYPE_NORMAL][$checkName];
                return FullyQualified::concat($alias, $name->slice(1), $name->getAttributes());
            }
        } elseif ($name->isUnqualified()) {
            // constant aliases are case-sensitive, function aliases case-insensitive
            $checkName = $type === Stmt\Use_::TYPE_CONSTANT ? $firstPart : \strtolower($firstPart);
            if (isset($this->aliases[$type][$checkName])) {
                // resolve unqualified aliases
                return new FullyQualified($this->aliases[$type][$checkName], $name->getAttributes());
            }
        }
        // No applicable aliases
        return null;
    }
    /**
     *
     */
    private function getNamespaceRelativeName(string $name, string $lcName, int $type)
    {
        if (null === $this->namespace) {
            return new Name($name);
        }
        if ($type === Stmt\Use_::TYPE_CONSTANT) {
            // The constants true/false/null always resolve to the global symbols, even inside a
            // namespace, so they may be used without qualification
            if ($lcName === "true" || $lcName === "false" || $lcName === "null") {
                return new Name($name);
            }
        }
        $namespacePrefix = \strtolower($this->namespace . '\\');
        if (0 === \strpos($lcName, $namespacePrefix)) {
            return new Name(\Phabel\Target\Php80\Polyfill::substr($name, \strlen($namespacePrefix)));
        }
        return null;
    }
    /**
     *
     */
    private function normalizeConstName(string $name)
    {
        $nsSep = \strrpos($name, '\\');
        if (\false === $nsSep) {
            return $name;
        }
        // Constants have case-insensitive namespace and case-sensitive short-name
        $ns = \Phabel\Target\Php80\Polyfill::substr($name, 0, $nsSep);
        $shortName = \Phabel\Target\Php80\Polyfill::substr($name, $nsSep + 1);
        return \strtolower($ns) . '\\' . $shortName;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\ErrorHandler;
use PhabelVendor\PhpParser\Lexer;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\AttributeEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\AwaitTokenEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\EnumTokenEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\CoaleseEqualTokenEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\ExplicitOctalEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\FlexibleDocStringEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\FnTokenEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\MatchTokenEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\NullsafeTokenEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\NumericLiteralSeparatorEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\ReadonlyTokenEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\ReverseEmulator;
use PhabelVendor\PhpParser\Lexer\TokenEmulator\TokenEmulator;
class Emulative extends Lexer
{
    const PHP_7_3 = '7.3dev';
    const PHP_7_4 = '7.4dev';
    const PHP_8_0 = '8.0dev';
    const PHP_8_1 = '8.1dev';
    const PHP_UNOBTANIUM = '100.0dev';
    /** @var mixed[] Patches used to reverse changes introduced in the code */
    private $patches = [];
    /** @var TokenEmulator[] */
    public $emulators = [];
    /** @var string */
    private $targetPhpVersion;
    /**
    * @param mixed[] $options Lexer options. In addition to the usual options,
    accepts a 'phpVersion' string that specifies the
    version to emulate. Defaults to newest supported.
    */
    public function __construct(array $options = [])
    {
        $this->targetPhpVersion = $options['phpVersion'] ?? Emulative::PHP_8_1;
        unset($options['phpVersion']);
        parent::__construct($options);
        $emulators = [new AwaitTokenEmulator(), new FlexibleDocStringEmulator(), new FnTokenEmulator(), new MatchTokenEmulator(), new CoaleseEqualTokenEmulator(), new NumericLiteralSeparatorEmulator(), new NullsafeTokenEmulator(), new AttributeEmulator(), new EnumTokenEmulator(), new ReadonlyTokenEmulator(), new ExplicitOctalEmulator()];
        // Collect emulators that are relevant for the PHP version we're running
        // and the PHP version we're targeting for emulation.
        foreach ($emulators as $emulator) {
            $emulatorPhpVersion = $emulator->getPhpVersion();
            if ($this->isForwardEmulationNeeded($emulatorPhpVersion)) {
                $this->emulators[] = $emulator;
            } else {
                if ($this->isReverseEmulationNeeded($emulatorPhpVersion)) {
                    $this->emulators[] = new ReverseEmulator($emulator);
                }
            }
        }
    }
    /**
     *
     */
    public function startLexing(string $code, ErrorHandler $errorHandler = null)
    {
        $emulators = \array_filter($this->emulators, function ($emulator) use($code) {
            return $emulator->isEmulationNeeded($code);
        });
        if (empty($emulators)) {
            // Nothing to emulate, yay
            parent::startLexing($code, $errorHandler);
            return;
        }
        $this->patches = [];
        foreach ($emulators as $emulator) {
            $code = $emulator->preprocessCode($code, $this->patches);
        }
        $collector = new ErrorHandler\Collecting();
        parent::startLexing($code, $collector);
        $this->sortPatches();
        $this->fixupTokens();
        $errors = $collector->getErrors();
        if (!empty($errors)) {
            $this->fixupErrors($errors);
            foreach ($errors as $error) {
                $errorHandler->handleError($error);
            }
        }
        foreach ($emulators as $emulator) {
            $this->tokens = $emulator->emulate($code, $this->tokens);
        }
    }
    /**
     *
     */
    private function isForwardEmulationNeeded(string $emulatorPhpVersion) : bool
    {
        if ($emulatorPhpVersion === self::PHP_UNOBTANIUM) {
            return \true;
        }
        return \version_compare(\PHP_VERSION, $emulatorPhpVersion, '<') && \version_compare($this->targetPhpVersion, $emulatorPhpVersion, '>=');
    }
    /**
     *
     */
    private function isReverseEmulationNeeded(string $emulatorPhpVersion) : bool
    {
        return \version_compare(\PHP_VERSION, $emulatorPhpVersion, '>=') && \version_compare($this->targetPhpVersion, $emulatorPhpVersion, '<');
    }
    /**
     *
     */
    private function sortPatches()
    {
        // Patches may be contributed by different emulators.
        // Make sure they are sorted by increasing patch position.
        \usort($this->patches, function ($p1, $p2) {
            return $p1[0] <=> $p2[0];
        });
    }
    /**
     *
     */
    private function fixupTokens()
    {
        if (\count($this->patches) === 0) {
            return;
        }
        // Load first patch
        $patchIdx = 0;
        list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
        // We use a manual loop over the tokens, because we modify the array on the fly
        $pos = 0;
        for ($i = 0, $c = \count($this->tokens); $i < $c; $i++) {
            $token = $this->tokens[$i];
            if (\is_string($token)) {
                if ($patchPos === $pos) {
                    // Only support replacement for string tokens.
                    \assert($patchType === 'replace');
                    $this->tokens[$i] = $patchText;
                    // Fetch the next patch
                    $patchIdx++;
                    if ($patchIdx >= \count($this->patches)) {
                        // No more patches, we're done
                        return;
                    }
                    list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
                }
                $pos += \strlen($token);
                continue;
            }
            $len = \strlen($token[1]);
            $posDelta = 0;
            while ($patchPos >= $pos && $patchPos < $pos + $len) {
                $patchTextLen = \strlen($patchText);
                if ($patchType === 'remove') {
                    if ($patchPos === $pos && $patchTextLen === $len) {
                        // Remove token entirely
                        \array_splice($this->tokens, $i, 1, []);
                        $i--;
                        $c--;
                    } else {
                        // Remove from token string
                        $this->tokens[$i][1] = \Phabel\Target\Php80\Polyfill::substr_replace($token[1], '', $patchPos - $pos + $posDelta, $patchTextLen);
                        $posDelta -= $patchTextLen;
                    }
                } elseif ($patchType === 'add') {
                    // Insert into the token string
                    $this->tokens[$i][1] = \Phabel\Target\Php80\Polyfill::substr_replace($token[1], $patchText, $patchPos - $pos + $posDelta, 0);
                    $posDelta += $patchTextLen;
                } else {
                    if ($patchType === 'replace') {
                        // Replace inside the token string
                        $this->tokens[$i][1] = \Phabel\Target\Php80\Polyfill::substr_replace($token[1], $patchText, $patchPos - $pos + $posDelta, $patchTextLen);
                    } else {
                        \assert(\false);
                    }
                }
                // Fetch the next patch
                $patchIdx++;
                if ($patchIdx >= \count($this->patches)) {
                    // No more patches, we're done
                    return;
                }
                list($patchPos, $patchType, $patchText) = $this->patches[$patchIdx];
                // Multiple patches may apply to the same token. Reload the current one to check
                // If the new patch applies
                $token = $this->tokens[$i];
            }
            $pos += $len;
        }
        // A patch did not apply
        \assert(\false);
    }
    /**
     * Fixup line and position information in errors.
     *
     * @param Error[] $errors
     */
    private function fixupErrors(array $errors)
    {
        foreach ($errors as $error) {
            $attrs = $error->getAttributes();
            $posDelta = 0;
            $lineDelta = 0;
            foreach ($this->patches as $patch) {
                list($patchPos, $patchType, $patchText) = $patch;
                if ($patchPos >= $attrs['startFilePos']) {
                    // No longer relevant
                    break;
                }
                if ($patchType === 'add') {
                    $posDelta += \strlen($patchText);
                    $lineDelta += \Phabel\Target\Php80\Polyfill::substr_count($patchText, "\n");
                } else {
                    if ($patchType === 'remove') {
                        $posDelta -= \strlen($patchText);
                        $lineDelta -= \Phabel\Target\Php80\Polyfill::substr_count($patchText, "\n");
                    }
                }
            }
            $attrs['startFilePos'] += $posDelta;
            $attrs['endFilePos'] += $posDelta;
            $attrs['startLine'] += $lineDelta;
            $attrs['endLine'] += $lineDelta;
            $error->setAttributes($attrs);
        }
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class ReadonlyTokenEmulator extends KeywordEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_8_1;
    }
    /**
     *
     */
    public function getKeywordString() : string
    {
        return 'readonly';
    }
    /**
     *
     */
    public function getKeywordToken() : int
    {
        return \T_READONLY;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class FlexibleDocStringEmulator extends TokenEmulator
{
    const FLEXIBLE_DOC_STRING_REGEX = <<<'REGEX'
/<<<[ \t]*(['"]?)([a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*)\1\r?\n
(?:.*\r?\n)*?
(?<indentation>\h*)\2(?![a-zA-Z0-9_\x80-\xff])(?<separator>(?:;?[\r\n])?)/x
REGEX;
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_7_3;
    }
    /**
     *
     */
    public function isEmulationNeeded(string $code) : bool
    {
        return \strpos($code, '<<<') !== \false;
    }
    /**
     *
     */
    public function emulate(string $code, array $tokens) : array
    {
        // Handled by preprocessing + fixup.
        return $tokens;
    }
    /**
     *
     */
    public function reverseEmulate(string $code, array $tokens) : array
    {
        // Not supported.
        return $tokens;
    }
    /**
     *
     */
    public function preprocessCode(string $code, array &$patches) : string
    {
        if (!\preg_match_all(self::FLEXIBLE_DOC_STRING_REGEX, $code, $matches, \PREG_SET_ORDER | \PREG_OFFSET_CAPTURE)) {
            // No heredoc/nowdoc found
            return $code;
        }
        // Keep track of how much we need to adjust string offsets due to the modifications we
        // already made
        $posDelta = 0;
        foreach ($matches as $match) {
            $indentation = $match['indentation'][0];
            $indentationStart = $match['indentation'][1];
            $separator = $match['separator'][0];
            $separatorStart = $match['separator'][1];
            if ($indentation === '' && $separator !== '') {
                // Ordinary heredoc/nowdoc
                continue;
            }
            if ($indentation !== '') {
                // Remove indentation
                $indentationLen = \strlen($indentation);
                $code = \Phabel\Target\Php80\Polyfill::substr_replace($code, '', $indentationStart + $posDelta, $indentationLen);
                $patches[] = [$indentationStart + $posDelta, 'add', $indentation];
                $posDelta -= $indentationLen;
            }
            if ($separator === '') {
                // Insert newline as separator
                $code = \Phabel\Target\Php80\Polyfill::substr_replace($code, "\n", $separatorStart + $posDelta, 0);
                $patches[] = [$separatorStart + $posDelta, 'remove', "\n"];
                $posDelta += 1;
            }
        }
        return $code;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class NumericLiteralSeparatorEmulator extends TokenEmulator
{
    const BIN = '(?:0b[01]+(?:_[01]+)*)';
    const HEX = '(?:0x[0-9a-f]+(?:_[0-9a-f]+)*)';
    const DEC = '(?:[0-9]+(?:_[0-9]+)*)';
    const SIMPLE_FLOAT = '(?:' . self::DEC . '\\.' . self::DEC . '?|\\.' . self::DEC . ')';
    const EXP = '(?:e[+-]?' . self::DEC . ')';
    const FLOAT = '(?:' . self::SIMPLE_FLOAT . self::EXP . '?|' . self::DEC . self::EXP . ')';
    const NUMBER = '~' . self::FLOAT . '|' . self::BIN . '|' . self::HEX . '|' . self::DEC . '~iA';
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_7_4;
    }
    /**
     *
     */
    public function isEmulationNeeded(string $code) : bool
    {
        return \preg_match('~[0-9]_[0-9]~', $code) || \preg_match('~0x[0-9a-f]+_[0-9a-f]~i', $code);
    }
    /**
     *
     */
    public function emulate(string $code, array $tokens) : array
    {
        // We need to manually iterate and manage a count because we'll change
        // the tokens array on the way
        $codeOffset = 0;
        for ($i = 0, $c = \count($tokens); $i < $c; ++$i) {
            $token = $tokens[$i];
            $tokenLen = \strlen(\is_array($token) ? $token[1] : $token);
            if ($token[0] !== \T_LNUMBER && $token[0] !== \T_DNUMBER) {
                $codeOffset += $tokenLen;
                continue;
            }
            $res = \preg_match(self::NUMBER, $code, $matches, 0, $codeOffset);
            \assert($res, "No number at number token position");
            $match = $matches[0];
            $matchLen = \strlen($match);
            if ($matchLen === $tokenLen) {
                // Original token already holds the full number.
                $codeOffset += $tokenLen;
                continue;
            }
            $tokenKind = $this->resolveIntegerOrFloatToken($match);
            $newTokens = [[$tokenKind, $match, $token[2]]];
            $numTokens = 1;
            $len = $tokenLen;
            while ($matchLen > $len) {
                $nextToken = $tokens[$i + $numTokens];
                $nextTokenText = \is_array($nextToken) ? $nextToken[1] : $nextToken;
                $nextTokenLen = \strlen($nextTokenText);
                $numTokens++;
                if ($matchLen < $len + $nextTokenLen) {
                    // Split trailing characters into a partial token.
                    \assert(\is_array($nextToken), "Partial token should be an array token");
                    $partialText = \Phabel\Target\Php80\Polyfill::substr($nextTokenText, $matchLen - $len);
                    $newTokens[] = [$nextToken[0], $partialText, $nextToken[2]];
                    break;
                }
                $len += $nextTokenLen;
            }
            \array_splice($tokens, $i, $numTokens, $newTokens);
            $c -= $numTokens - \count($newTokens);
            $codeOffset += $matchLen;
        }
        return $tokens;
    }
    /**
     *
     */
    private function resolveIntegerOrFloatToken(string $str) : int
    {
        $str = \str_replace('_', '', $str);
        if (\stripos($str, '0b') === 0) {
            $num = \bindec($str);
        } elseif (\stripos($str, '0x') === 0) {
            $num = \hexdec($str);
        } elseif (\stripos($str, '0') === 0 && \ctype_digit($str)) {
            $num = \octdec($str);
        } else {
            $num = +$str;
        }
        return \is_float($num) ? \T_DNUMBER : \T_LNUMBER;
    }
    /**
     *
     */
    public function reverseEmulate(string $code, array $tokens) : array
    {
        // Numeric separators were not legal code previously, don't bother.
        return $tokens;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class AttributeEmulator extends TokenEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_8_0;
    }
    /**
     *
     */
    public function isEmulationNeeded(string $code) : bool
    {
        return \strpos($code, '#[') !== \false;
    }
    /**
     *
     */
    public function emulate(string $code, array $tokens) : array
    {
        // We need to manually iterate and manage a count because we'll change
        // the tokens array on the way.
        $line = 1;
        for ($i = 0, $c = \count($tokens); $i < $c; ++$i) {
            if ($tokens[$i] === '#' && isset($tokens[$i + 1]) && $tokens[$i + 1] === '[') {
                \array_splice($tokens, $i, 2, [[\T_ATTRIBUTE, '#[', $line]]);
                $c--;
                continue;
            }
            if (\is_array($tokens[$i])) {
                $line += \Phabel\Target\Php80\Polyfill::substr_count($tokens[$i][1], "\n");
            }
        }
        return $tokens;
    }
    /**
     *
     */
    public function reverseEmulate(string $code, array $tokens) : array
    {
        // TODO
        return $tokens;
    }
    /**
     *
     */
    public function preprocessCode(string $code, array &$patches) : string
    {
        $pos = 0;
        while (\false !== ($pos = \strpos($code, '#[', $pos))) {
            // Replace #[ with %[
            $code[$pos] = '%';
            $patches[] = [$pos, 'replace', '#'];
            $pos += 2;
        }
        return $code;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class AwaitTokenEmulator extends KeywordEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_UNOBTANIUM;
    }
    /**
     *
     */
    public function getKeywordString() : string
    {
        return 'await';
    }
    /**
     *
     */
    public function getKeywordToken() : int
    {
        return \T_YIELD;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

abstract class KeywordEmulator extends TokenEmulator
{
    /**
     *
     */
    abstract function getKeywordString() : string;
    /**
     *
     */
    abstract function getKeywordToken() : int;
    /**
     *
     */
    public function isEmulationNeeded(string $code) : bool
    {
        return \strpos(\strtolower($code), $this->getKeywordString()) !== \false;
    }
    /**
     *
     */
    protected function isKeywordContext(array $tokens, int $pos) : bool
    {
        $previousNonSpaceToken = $this->getPreviousNonSpaceToken($tokens, $pos);
        return $previousNonSpaceToken === null || $previousNonSpaceToken[0] !== \T_OBJECT_OPERATOR;
    }
    /**
     *
     */
    public function emulate(string $code, array $tokens) : array
    {
        $keywordString = $this->getKeywordString();
        foreach ($tokens as $i => $token) {
            if ($token[0] === \T_STRING && \strtolower($token[1]) === $keywordString && $this->isKeywordContext($tokens, $i)) {
                if ($keywordString === 'await') {
                    // Workaround await not being a reserved token
                    $prev = $this->getPreviousNonSpaceToken($tokens, $i);
                    $next = $this->getNextNonSpaceToken($tokens, $i);
                    if ($prev[0] !== \T_FUNCTION && $next !== '(') {
                        $tokens[$i][0] = $this->getKeywordToken();
                        $tokens[$i][1] = 'yield';
                    }
                } else {
                    $tokens[$i][0] = $this->getKeywordToken();
                }
            }
        }
        return $tokens;
    }
    /**
     * @param mixed[] $tokens
     * @return (mixed[] | null)
     */
    private function getPreviousNonSpaceToken(array $tokens, int $start)
    {
        for ($i = $start - 1; $i >= 0; --$i) {
            if ($tokens[$i][0] === \T_WHITESPACE) {
                continue;
            }
            return $tokens[$i];
        }
        return null;
    }
    /**
     * @param mixed[] $tokens
     * @return (mixed[] | null)
     */
    private function getNextNonSpaceToken(array $tokens, int $start)
    {
        for ($i = $start + 1; $i < \count($tokens); ++$i) {
            if ($tokens[$i][0] === \T_WHITESPACE) {
                continue;
            }
            return $tokens[$i];
        }
        return null;
    }
    /**
     *
     */
    public function reverseEmulate(string $code, array $tokens) : array
    {
        $keywordToken = $this->getKeywordToken();
        foreach ($tokens as $i => $token) {
            if ($token[0] === $keywordToken) {
                $tokens[$i][0] = \T_STRING;
            }
        }
        return $tokens;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class MatchTokenEmulator extends KeywordEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_8_0;
    }
    /**
     *
     */
    public function getKeywordString() : string
    {
        return 'match';
    }
    /**
     *
     */
    public function getKeywordToken() : int
    {
        return \T_MATCH;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class FnTokenEmulator extends KeywordEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_7_4;
    }
    /**
     *
     */
    public function getKeywordString() : string
    {
        return 'fn';
    }
    /**
     *
     */
    public function getKeywordToken() : int
    {
        return \T_FN;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

/**
 * Reverses emulation direction of the inner emulator.
 */
final class ReverseEmulator extends TokenEmulator
{
    /** @var TokenEmulator Inner emulator */
    private $emulator;
    /**
     *
     */
    public function __construct(TokenEmulator $emulator)
    {
        $this->emulator = $emulator;
    }
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return $this->emulator->getPhpVersion();
    }
    /**
     *
     */
    public function isEmulationNeeded(string $code) : bool
    {
        return $this->emulator->isEmulationNeeded($code);
    }
    /**
     *
     */
    public function emulate(string $code, array $tokens) : array
    {
        return $this->emulator->reverseEmulate($code, $tokens);
    }
    /**
     *
     */
    public function reverseEmulate(string $code, array $tokens) : array
    {
        return $this->emulator->emulate($code, $tokens);
    }
    /**
     *
     */
    public function preprocessCode(string $code, array &$patches) : string
    {
        return $code;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class EnumTokenEmulator extends KeywordEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_8_1;
    }
    /**
     *
     */
    public function getKeywordString() : string
    {
        return 'enum';
    }
    /**
     *
     */
    public function getKeywordToken() : int
    {
        return \T_ENUM;
    }
    /**
     *
     */
    protected function isKeywordContext(array $tokens, int $pos) : bool
    {
        return parent::isKeywordContext($tokens, $pos) && isset($tokens[$pos + 2]) && $tokens[$pos + 1][0] === \T_WHITESPACE && $tokens[$pos + 2][0] === \T_STRING;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

/** @internal */
abstract class TokenEmulator
{
    /**
     *
     */
    public abstract function getPhpVersion() : string;
    /**
     *
     */
    public abstract function isEmulationNeeded(string $code) : bool;
    /**
     * @return array Modified Tokens
     */
    public abstract function emulate(string $code, array $tokens) : array;
    /**
     * @return array Modified Tokens
     */
    public abstract function reverseEmulate(string $code, array $tokens) : array;
    /**
     *
     */
    public function preprocessCode(string $code, array &$patches) : string
    {
        return $code;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class NullsafeTokenEmulator extends TokenEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_8_0;
    }
    /**
     *
     */
    public function isEmulationNeeded(string $code) : bool
    {
        return \strpos($code, '?->') !== \false;
    }
    /**
     *
     */
    public function emulate(string $code, array $tokens) : array
    {
        // We need to manually iterate and manage a count because we'll change
        // the tokens array on the way
        $line = 1;
        for ($i = 0, $c = \count($tokens); $i < $c; ++$i) {
            if ($tokens[$i] === '?' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] === \T_OBJECT_OPERATOR) {
                \array_splice($tokens, $i, 2, [[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line]]);
                $c--;
                continue;
            }
            // Handle ?-> inside encapsed string.
            if ($tokens[$i][0] === \T_ENCAPSED_AND_WHITESPACE && isset($tokens[$i - 1]) && $tokens[$i - 1][0] === \T_VARIABLE && \preg_match('/^\\?->([a-zA-Z_\\x80-\\xff][a-zA-Z0-9_\\x80-\\xff]*)/', $tokens[$i][1], $matches)) {
                $replacement = [[\T_NULLSAFE_OBJECT_OPERATOR, '?->', $line], [\T_STRING, $matches[1], $line]];
                if (\strlen($matches[0]) !== \strlen($tokens[$i][1])) {
                    $replacement[] = [\T_ENCAPSED_AND_WHITESPACE, \Phabel\Target\Php80\Polyfill::substr($tokens[$i][1], \strlen($matches[0])), $line];
                }
                \array_splice($tokens, $i, 1, $replacement);
                $c += \count($replacement) - 1;
                continue;
            }
            if (\is_array($tokens[$i])) {
                $line += \Phabel\Target\Php80\Polyfill::substr_count($tokens[$i][1], "\n");
            }
        }
        return $tokens;
    }
    /**
     *
     */
    public function reverseEmulate(string $code, array $tokens) : array
    {
        // ?-> was not valid code previously, don't bother.
        return $tokens;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
final class CoaleseEqualTokenEmulator extends TokenEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_7_4;
    }
    /**
     *
     */
    public function isEmulationNeeded(string $code) : bool
    {
        return \strpos($code, '??=') !== \false;
    }
    /**
     *
     */
    public function emulate(string $code, array $tokens) : array
    {
        // We need to manually iterate and manage a count because we'll change
        // the tokens array on the way
        $line = 1;
        for ($i = 0, $c = \count($tokens); $i < $c; ++$i) {
            if (isset($tokens[$i + 1])) {
                if ($tokens[$i][0] === \T_COALESCE && $tokens[$i + 1] === '=') {
                    \array_splice($tokens, $i, 2, [[\T_COALESCE_EQUAL, '??=', $line]]);
                    $c--;
                    continue;
                }
            }
            if (\is_array($tokens[$i])) {
                $line += \Phabel\Target\Php80\Polyfill::substr_count($tokens[$i][1], "\n");
            }
        }
        return $tokens;
    }
    /**
     *
     */
    public function reverseEmulate(string $code, array $tokens) : array
    {
        // ??= was not valid code previously, don't bother.
        return $tokens;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Lexer\TokenEmulator;

use PhabelVendor\PhpParser\Lexer\Emulative;
class ExplicitOctalEmulator extends TokenEmulator
{
    /**
     *
     */
    public function getPhpVersion() : string
    {
        return Emulative::PHP_8_1;
    }
    /**
     *
     */
    public function isEmulationNeeded(string $code) : bool
    {
        return \strpos($code, '0o') !== \false || \strpos($code, '0O') !== \false;
    }
    /**
     *
     */
    public function emulate(string $code, array $tokens) : array
    {
        for ($i = 0, $c = \count($tokens); $i < $c; ++$i) {
            if ($tokens[$i][0] == \T_LNUMBER && $tokens[$i][1] === '0' && isset($tokens[$i + 1]) && $tokens[$i + 1][0] == \T_STRING && \preg_match('/[oO][0-7]+(?:_[0-7]+)*/', $tokens[$i + 1][1])) {
                $tokenKind = $this->resolveIntegerOrFloatToken($tokens[$i + 1][1]);
                \array_splice($tokens, $i, 2, [[$tokenKind, '0' . $tokens[$i + 1][1], $tokens[$i][2]]]);
                $c--;
            }
        }
        return $tokens;
    }
    /**
     *
     */
    private function resolveIntegerOrFloatToken(string $str) : int
    {
        $str = \Phabel\Target\Php80\Polyfill::substr($str, 1);
        $str = \str_replace('_', '', $str);
        $num = \octdec($str);
        return \is_float($num) ? \T_DNUMBER : \T_LNUMBER;
    }
    /**
     *
     */
    public function reverseEmulate(string $code, array $tokens) : array
    {
        // Explicit octals were not legal code previously, don't bother.
        return $tokens;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

class Comment implements \JsonSerializable
{
    protected $text;
    protected $startLine;
    protected $startFilePos;
    protected $startTokenPos;
    protected $endLine;
    protected $endFilePos;
    protected $endTokenPos;
    /**
     * Constructs a comment node.
     *
     * @param string $text Comment text (including comment delimiters like /*)
     * @param int $startLine Line number the comment started on
     * @param int $startFilePos File offset the comment started on
     * @param int $startTokenPos Token offset the comment started on
     */
    public function __construct(string $text, int $startLine = -1, int $startFilePos = -1, int $startTokenPos = -1, int $endLine = -1, int $endFilePos = -1, int $endTokenPos = -1)
    {
        $this->text = $text;
        $this->startLine = $startLine;
        $this->startFilePos = $startFilePos;
        $this->startTokenPos = $startTokenPos;
        $this->endLine = $endLine;
        $this->endFilePos = $endFilePos;
        $this->endTokenPos = $endTokenPos;
    }
    /**
     * Gets the comment text.
     *
     * @return string The comment text (including comment delimiters like /*)
     */
    public function getText() : string
    {
        return $this->text;
    }
    /**
     * Gets the line number the comment started on.
     *
     * @return int Line number (or -1 if not available)
     */
    public function getStartLine() : int
    {
        return $this->startLine;
    }
    /**
     * Gets the file offset the comment started on.
     *
     * @return int File offset (or -1 if not available)
     */
    public function getStartFilePos() : int
    {
        return $this->startFilePos;
    }
    /**
     * Gets the token offset the comment started on.
     *
     * @return int Token offset (or -1 if not available)
     */
    public function getStartTokenPos() : int
    {
        return $this->startTokenPos;
    }
    /**
     * Gets the line number the comment ends on.
     *
     * @return int Line number (or -1 if not available)
     */
    public function getEndLine() : int
    {
        return $this->endLine;
    }
    /**
     * Gets the file offset the comment ends on.
     *
     * @return int File offset (or -1 if not available)
     */
    public function getEndFilePos() : int
    {
        return $this->endFilePos;
    }
    /**
     * Gets the token offset the comment ends on.
     *
     * @return int Token offset (or -1 if not available)
     */
    public function getEndTokenPos() : int
    {
        return $this->endTokenPos;
    }
    /**
     * Gets the line number the comment started on.
     *
     * @deprecated Use getStartLine() instead
     *
     * @return int Line number
     */
    public function getLine() : int
    {
        return $this->startLine;
    }
    /**
     * Gets the file offset the comment started on.
     *
     * @deprecated Use getStartFilePos() instead
     *
     * @return int File offset
     */
    public function getFilePos() : int
    {
        return $this->startFilePos;
    }
    /**
     * Gets the token offset the comment started on.
     *
     * @deprecated Use getStartTokenPos() instead
     *
     * @return int Token offset
     */
    public function getTokenPos() : int
    {
        return $this->startTokenPos;
    }
    /**
     * Gets the comment text.
     *
     * @return string The comment text (including comment delimiters like /*)
     */
    public function __toString() : string
    {
        return $this->text;
    }
    /**
    * Gets the reformatted comment text.
    *
    * "Reformatted" here means that we try to clean up the whitespace at the
    starts of the lines. This is necessary because we receive the comments
    without trailing whitespace on the first line, but with trailing whitespace
    on all subsequent lines.
    *
    * @return (mixed | string)
    */
    public function getReformattedText()
    {
        $text = \trim($this->text);
        $newlinePos = \strpos($text, "\n");
        if (\false === $newlinePos) {
            // Single line comments don't need further processing
            return $text;
        } elseif (\preg_match('((*BSR_ANYCRLF)(*ANYCRLF)^.*(?:\\R\\s+\\*.*)+$)', $text)) {
            // Multi line comment of the type
            //
            //     /*
            //      * Some text.
            //      * Some more text.
            //      */
            //
            // is handled by replacing the whitespace sequences before the * by a single space
            return \preg_replace('(^\\s+\\*)m', ' *', $this->text);
        } elseif (\preg_match('(^/\\*\\*?\\s*[\\r\\n])', $text) && \preg_match('(\\n(\\s*)\\*/$)', $text, $matches)) {
            // Multi line comment of the type
            //
            //    /*
            //        Some text.
            //        Some more text.
            //    */
            //
            // is handled by removing the whitespace sequence on the line before the closing
            // */ on all lines. So if the last line is "    */", then "    " is removed at the
            // start of all lines.
            return \preg_replace('(^' . \preg_quote($matches[1]) . ')m', '', $text);
        } elseif (\preg_match('(^/\\*\\*?\\s*(?!\\s))', $text, $matches)) {
            // Multi line comment of the type
            //
            //     /* Some text.
            //        Some more text.
            //          Indented text.
            //        Even more text. */
            //
            // is handled by removing the difference between the shortest whitespace prefix on all
            // lines and the length of the "/* " opening sequence.
            $prefixLen = $this->getShortestWhitespacePrefixLen(\Phabel\Target\Php80\Polyfill::substr($text, $newlinePos + 1));
            $removeLen = $prefixLen - \strlen($matches[0]);
            return \preg_replace('(^\\s{' . $removeLen . '})m', '', $text);
        }
        // No idea how to format this comment, so simply return as is
        return $text;
    }
    /**
     * Get length of shortest whitespace prefix (at the start of a line).
     *
     * If there is a line with no prefix whitespace, 0 is a valid return value.
     *
     * @param string $str String to check
     * @return int Length in characters. Tabs count as single characters.
     */
    private function getShortestWhitespacePrefixLen(string $str) : int
    {
        $lines = \explode("\n", $str);
        $shortestPrefixLen = \INF;
        foreach ($lines as $line) {
            \preg_match('(^\\s*)', $line, $matches);
            $prefixLen = \strlen($matches[0]);
            if ($prefixLen < $shortestPrefixLen) {
                $shortestPrefixLen = $prefixLen;
            }
        }
        return $shortestPrefixLen;
    }
    /**
     * @return array
     * @psalm-return array{nodeType: string, text: mixed, line: mixed, filePos: mixed}
     */
    public function jsonSerialize() : array
    {
        // Technically not a node, but we make it look like one anyway
        $type = $this instanceof Comment\Doc ? 'Comment_Doc' : 'Comment';
        return [
            'nodeType' => $type,
            'text' => $this->text,
            // TODO: Rename these to include "start".
            'line' => $this->startLine,
            'filePos' => $this->startFilePos,
            'tokenPos' => $this->startTokenPos,
            'endLine' => $this->endLine,
            'endFilePos' => $this->endFilePos,
            'endTokenPos' => $this->endTokenPos,
        ];
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

use PhabelVendor\PhpParser\NodeVisitor\FindingVisitor;
use PhabelVendor\PhpParser\NodeVisitor\FirstFindingVisitor;
class NodeFinder
{
    /**
     * Find all nodes satisfying a filter callback.
     *
     * @param (Node | Node[]) $nodes Single node or array of nodes to search in
     * @param callable $filter Filter callback: function(Node $node) : bool
     *
     * @return Node[] Found nodes satisfying the filter callback
     */
    public function find($nodes, callable $filter) : array
    {
        if (!\is_array($nodes)) {
            $nodes = [$nodes];
        }
        $visitor = new FindingVisitor($filter);
        $traverser = new NodeTraverser();
        $traverser->addVisitor($visitor);
        $traverser->traverse($nodes);
        return $visitor->getFoundNodes();
    }
    /**
     * Find all nodes that are instances of a certain class.
     *
     * @param (Node | Node[]) $nodes Single node or array of nodes to search in
     * @param string $class Class name
     *
     * @return Node[] Found nodes (all instances of $class)
     */
    public function findInstanceOf($nodes, string $class) : array
    {
        return $this->find($nodes, function ($node) use($class) {
            return $node instanceof $class;
        });
    }
    /**
     * Find first node satisfying a filter callback.
     *
     * @param (Node | Node[]) $nodes Single node or array of nodes to search in
     * @param callable $filter Filter callback: function(Node $node) : bool
     *
     * @return (null | Node) Found node (or null if none found)
     */
    public function findFirst($nodes, callable $filter)
    {
        if (!\is_array($nodes)) {
            $nodes = [$nodes];
        }
        $visitor = new FirstFindingVisitor($filter);
        $traverser = new NodeTraverser();
        $traverser->addVisitor($visitor);
        $traverser->traverse($nodes);
        return $visitor->getFoundNode();
    }
    /**
     * Find first node that is an instance of a certain class.
     *
     * @param (Node | Node[]) $nodes Single node or array of nodes to search in
     * @param string $class Class name
     *
     * @return (null | Node) Found node, which is an instance of $class (or null if none found)
     */
    public function findFirstInstanceOf($nodes, string $class)
    {
        return $this->findFirst($nodes, function ($node) use($class) {
            return $node instanceof $class;
        });
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
/**
 * Represents the "..." in "foo(...)" of the first-class callable syntax.
 */
class VariadicPlaceholder extends NodeAbstract
{
    /**
     * Create a variadic argument placeholder (first-class callable syntax).
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = [])
    {
        $this->attributes = $attributes;
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'VariadicPlaceholder';
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return [];
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
class IntersectionType extends ComplexType
{
    /** @var (Identifier|Name)[] Types */
    public $types;
    /**
     * Constructs an intersection type.
     *
     * @param (Identifier | Name)[] $types Types
     * @param array $attributes Additional attributes
     */
    public function __construct(array $types, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->types = $types;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['types'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'IntersectionType';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
/**
 * Represents a non-namespaced name. Namespaced names are represented using Name nodes.
 */
class Identifier extends NodeAbstract
{
    /** @var string Identifier as string */
    public $name;
    private static $specialClassNames = ['self' => \true, 'parent' => \true, 'static' => \true];
    /**
     * Constructs an identifier node.
     *
     * @param string $name Identifier as string
     * @param array $attributes Additional attributes
     */
    public function __construct(string $name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name'];
    }
    /**
     * Get identifier as string.
     *
     * @return string Identifier as string.
     */
    public function toString() : string
    {
        return $this->name;
    }
    /**
     * Get lowercased identifier as string.
     *
     * @return string Lowercased identifier as string
     */
    public function toLowerString() : string
    {
        return \strtolower($this->name);
    }
    /**
     * Checks whether the identifier is a special class name (self, parent or static).
     *
     * @return bool Whether identifier is a special class name
     */
    public function isSpecialClassName() : bool
    {
        return isset(self::$specialClassNames[\strtolower($this->name)]);
    }
    /**
     * Get identifier as string.
     *
     * @return string Identifier as string
     */
    public function __toString() : string
    {
        return $this->name;
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Identifier';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
/**
 * This is a base class for complex types, including nullable types and union types.
 *
 * It does not provide any shared behavior and exists only for type-checking purposes.
 */
abstract class ComplexType extends NodeAbstract
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\FunctionLike;
class Closure extends Expr implements FunctionLike
{
    /** @var bool Whether the closure is static */
    public $static;
    /** @var bool Whether to return by reference */
    public $byRef;
    /** @var Node\Param[] Parameters */
    public $params;
    /** @var ClosureUse[] use()s */
    public $uses;
    /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */
    public $returnType;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /** @var Node\AttributeGroup[] PHP attribute groups */
    public $attrGroups;
    /**
    * Constructs a lambda function node.
    *
    * @param array $subNodes Array of the following optional subnodes:
    'static'     => false  : Whether the closure is static
    'byRef'      => false  : Whether to return by reference
    'params'     => array(): Parameters
    'uses'       => array(): use()s
    'returnType' => null   : Return type
    'stmts'      => array(): Statements
    'attrGroups' => array(): PHP attributes groups
    * @param array $attributes Additional attributes
    */
    public function __construct(array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->static = $subNodes['static'] ?? \false;
        $this->byRef = $subNodes['byRef'] ?? \false;
        $this->params = $subNodes['params'] ?? [];
        $this->uses = $subNodes['uses'] ?? [];
        $returnType = $subNodes['returnType'] ?? null;
        $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
        $this->stmts = $subNodes['stmts'] ?? [];
        $this->attrGroups = $subNodes['attrGroups'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'static', 'byRef', 'params', 'uses', 'returnType', 'stmts'];
    }
    /**
     *
     */
    public function returnsByRef() : bool
    {
        return $this->byRef;
    }
    /**
     *
     */
    public function getParams() : array
    {
        return $this->params;
    }
    /**
     *
     */
    public function getReturnType()
    {
        return $this->returnType;
    }
    /**
     * @return Node\Stmt[]
     */
    public function getStmts() : array
    {
        return $this->stmts;
    }
    /**
     *
     */
    public function getAttrGroups() : array
    {
        return $this->attrGroups;
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Closure';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class ErrorSuppress extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs an error suppress node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_ErrorSuppress';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class BooleanAnd extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '&&';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_BooleanAnd';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Mod extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '%';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Mod';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class ShiftRight extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '>>';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_ShiftRight';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class NotIdentical extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '!==';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_NotIdentical';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Identical extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '===';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Identical';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class LogicalOr extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return 'or';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_LogicalOr';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Coalesce extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '??';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Coalesce';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class BitwiseOr extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '|';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_BitwiseOr';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class BooleanOr extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '||';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_BooleanOr';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Greater extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '>';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Greater';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Concat extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '.';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Concat';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Equal extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '==';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Equal';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class BitwiseAnd extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '&';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_BitwiseAnd';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class GreaterOrEqual extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '>=';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_GreaterOrEqual';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class NotEqual extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '!=';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_NotEqual';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class ShiftLeft extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '<<';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_ShiftLeft';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class BitwiseXor extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '^';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_BitwiseXor';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Pow extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '**';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Pow';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Div extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '/';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Div';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Minus extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '-';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Minus';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Plus extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '+';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Plus';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class SmallerOrEqual extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '<=';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_SmallerOrEqual';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Mul extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '*';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Mul';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Spaceship extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '<=>';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Spaceship';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class LogicalAnd extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return 'and';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_LogicalAnd';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class Smaller extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return '<';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_Smaller';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\BinaryOp;

use PhabelVendor\PhpParser\Node\Expr\BinaryOp;
class LogicalXor extends BinaryOp
{
    /**
     *
     */
    public function getOperatorSigil() : string
    {
        return 'xor';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BinaryOp_LogicalXor';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class PreInc extends Expr
{
    /** @var Expr Variable */
    public $var;
    /**
     * Constructs a pre increment node.
     *
     * @param Expr $var Variable
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_PreInc';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\VariadicPlaceholder;
class NullsafeMethodCall extends CallLike
{
    /** @var Expr Variable holding object */
    public $var;
    /** @var Identifier|Expr Method name */
    public $name;
    /** @var array<Arg|VariadicPlaceholder> Arguments */
    public $args;
    /**
     * Constructs a nullsafe method call node.
     *
     * @param Expr $var Variable holding object
     * @param (string | Identifier | Expr) $name Method name
     * @param array<(Arg | VariadicPlaceholder)> $args Arguments
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, $name, array $args = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
        $this->args = $args;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'name', 'args'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_NullsafeMethodCall';
    }
    /**
     *
     */
    public function getRawArgs() : array
    {
        return $this->args;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
/**
 * Error node used during parsing with error recovery.
 *
 * An error node may be placed at a position where an expression is required, but an error occurred.
 * Error nodes will not be present if the parser is run in throwOnError mode (the default).
 */
class Error extends Expr
{
    /**
     * Constructs an error node.
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = [])
    {
        $this->attributes = $attributes;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return [];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Error';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Ternary extends Expr
{
    /** @var Expr Condition */
    public $cond;
    /** @var null|Expr Expression for true */
    public $if;
    /** @var Expr Expression for false */
    public $else;
    /**
     * Constructs a ternary operator node.
     *
     * @param Expr $cond Condition
     * @param (null | Expr) $if Expression for true
     * @param Expr $else Expression for false
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $cond, $if, Expr $else, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->cond = $cond;
        $this->if = $if;
        $this->else = $else;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['cond', 'if', 'else'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Ternary';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\MatchArm;
class Match_ extends Node\Expr
{
    /** @var Node\Expr */
    public $cond;
    /** @var MatchArm[] */
    public $arms;
    /**
     * @param MatchArm[] $arms
     */
    public function __construct(Node\Expr $cond, array $arms = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->cond = $cond;
        $this->arms = $arms;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['cond', 'arms'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Match';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
class ClassConstFetch extends Expr
{
    /** @var Name|Expr Class name */
    public $class;
    /** @var Identifier|Error Constant name */
    public $name;
    /**
     * Constructs a class const fetch node.
     *
     * @param (Name | Expr) $class Class name
     * @param (string | Identifier | Error) $name Constant name
     * @param array $attributes Additional attributes
     */
    public function __construct($class, $name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->class = $class;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['class', 'name'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_ClassConstFetch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\VariadicPlaceholder;
abstract class CallLike extends Expr
{
    /**
    * Return raw arguments, which may be actual Args, or VariadicPlaceholders for first-class
    callables.
    *
    * @return array<(Arg | VariadicPlaceholder)>
    */
    public abstract function getRawArgs() : array;
    /**
     * Returns whether this call expression is actually a first class callable.
     */
    public function isFirstClassCallable() : bool
    {
        foreach ($this->getRawArgs() as $arg) {
            if ($arg instanceof VariadicPlaceholder) {
                return \true;
            }
        }
        return \false;
    }
    /**
     * Assert that this is not a first-class callable and return only ordinary Args.
     *
     * @return Arg[]
     */
    public function getArgs() : array
    {
        \assert(!$this->isFirstClassCallable());
        return $this->getRawArgs();
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
abstract class BinaryOp extends Expr
{
    /** @var Expr The left hand side expression */
    public $left;
    /** @var Expr The right hand side expression */
    public $right;
    /**
     * Constructs a binary operator node.
     *
     * @param Expr $left The left hand side expression
     * @param Expr $right The right hand side expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $left, Expr $right, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->left = $left;
        $this->right = $right;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['left', 'right'];
    }
    /**
    * Get the operator sigil for this binary operation.
    *
    * In the case there are multiple possible sigils for an operator, this method does not
    necessarily return the one used in the parsed code.
    *
    * @return string
    */
    public abstract function getOperatorSigil() : string;
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Identifier;
class NullsafePropertyFetch extends Expr
{
    /** @var Expr Variable holding object */
    public $var;
    /** @var Identifier|Expr Property name */
    public $name;
    /**
     * Constructs a nullsafe property fetch node.
     *
     * @param Expr $var Variable holding object
     * @param (string | Identifier | Expr) $name Property name
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, $name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'name'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_NullsafePropertyFetch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class BitwiseNot extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs a bitwise not node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BitwiseNot';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Exit_ extends Expr
{
    /* For use in "kind" attribute */
    const KIND_EXIT = 1;
    const KIND_DIE = 2;
    /** @var null|Expr Expression */
    public $expr;
    /**
     * Constructs an exit() node.
     *
     * @param (null | Expr) $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Exit';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Identifier;
class PropertyFetch extends Expr
{
    /** @var Expr Variable holding object */
    public $var;
    /** @var Identifier|Expr Property name */
    public $name;
    /**
     * Constructs a function call node.
     *
     * @param Expr $var Variable holding object
     * @param (string | Identifier | Expr) $name Property name
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, $name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'name'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_PropertyFetch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class ShellExec extends Expr
{
    /** @var array Encapsed string array */
    public $parts;
    /**
     * Constructs a shell exec (backtick) node.
     *
     * @param array $parts Encapsed string array
     * @param array $attributes Additional attributes
     */
    public function __construct(array $parts, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->parts = $parts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['parts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_ShellExec';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\VarLikeIdentifier;
class StaticPropertyFetch extends Expr
{
    /** @var Name|Expr Class name */
    public $class;
    /** @var VarLikeIdentifier|Expr Property name */
    public $name;
    /**
     * Constructs a static property fetch node.
     *
     * @param (Name | Expr) $class Class name
     * @param (string | VarLikeIdentifier | Expr) $name Property name
     * @param array $attributes Additional attributes
     */
    public function __construct($class, $name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->class = $class;
        $this->name = \is_string($name) ? new VarLikeIdentifier($name) : $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['class', 'name'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_StaticPropertyFetch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class ArrayItem extends Expr
{
    /** @var null|Expr Key */
    public $key;
    /** @var Expr Value */
    public $value;
    /** @var bool Whether to assign by reference */
    public $byRef;
    /** @var bool Whether to unpack the argument */
    public $unpack;
    /**
     * Constructs an array item node.
     *
     * @param Expr $value Value
     * @param (null | Expr) $key Key
     * @param bool $byRef Whether to assign by reference
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $value, Expr $key = null, bool $byRef = \false, array $attributes = [], bool $unpack = \false)
    {
        $this->attributes = $attributes;
        $this->key = $key;
        $this->value = $value;
        $this->byRef = $byRef;
        $this->unpack = $unpack;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['key', 'value', 'byRef', 'unpack'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_ArrayItem';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class YieldFrom extends Expr
{
    /** @var Expr Expression to yield from */
    public $expr;
    /**
     * Constructs an "yield from" node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_YieldFrom';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Eval_ extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs an eval() node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Eval';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class List_ extends Expr
{
    /** @var (ArrayItem|null)[] List of items to assign to */
    public $items;
    /**
     * Constructs a list() destructuring node.
     *
     * @param (ArrayItem | null)[] $items List of items to assign to
     * @param array $attributes Additional attributes
     */
    public function __construct(array $items, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->items = $items;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['items'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_List';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Print_ extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs an print() node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Print';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class Mod extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_Mod';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class ShiftRight extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_ShiftRight';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class Coalesce extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_Coalesce';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class BitwiseOr extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_BitwiseOr';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class Concat extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_Concat';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class BitwiseAnd extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_BitwiseAnd';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class ShiftLeft extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_ShiftLeft';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class BitwiseXor extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_BitwiseXor';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class Pow extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_Pow';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class Div extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_Div';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class Minus extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_Minus';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class Plus extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_Plus';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\AssignOp;

use PhabelVendor\PhpParser\Node\Expr\AssignOp;
class Mul extends AssignOp
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignOp_Mul';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\VariadicPlaceholder;
class StaticCall extends CallLike
{
    /** @var Node\Name|Expr Class name */
    public $class;
    /** @var Identifier|Expr Method name */
    public $name;
    /** @var array<Arg|VariadicPlaceholder> Arguments */
    public $args;
    /**
     * Constructs a static method call node.
     *
     * @param (Node\Name | Expr) $class Class name
     * @param (string | Identifier | Expr) $name Method name
     * @param array<(Arg | VariadicPlaceholder)> $args Arguments
     * @param array $attributes Additional attributes
     */
    public function __construct($class, $name, array $args = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->class = $class;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
        $this->args = $args;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['class', 'name', 'args'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_StaticCall';
    }
    /**
     *
     */
    public function getRawArgs() : array
    {
        return $this->args;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Array_ extends Expr
{
    // For use in "kind" attribute
    const KIND_LONG = 1;
    // array() syntax
    const KIND_SHORT = 2;
    // [] syntax
    /** @var (ArrayItem|null)[] Items */
    public $items;
    /**
     * Constructs an array node.
     *
     * @param (ArrayItem | null)[] $items Items of the array
     * @param array $attributes Additional attributes
     */
    public function __construct(array $items = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->items = $items;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['items'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Array';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Name;
class Instanceof_ extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /** @var Name|Expr Class name */
    public $class;
    /**
     * Constructs an instanceof check node.
     *
     * @param Expr $expr Expression
     * @param (Name | Expr) $class Class name
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, $class, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
        $this->class = $class;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr', 'class'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Instanceof';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
class FuncCall extends CallLike
{
    /** @var Node\Name|Expr Function name */
    public $name;
    /** @var array<Node\Arg|Node\VariadicPlaceholder> Arguments */
    public $args;
    /**
     * Constructs a function call node.
     *
     * @param (Node\Name | Expr) $name Function name
     * @param array<(Node\Arg | Node\VariadicPlaceholder)> $args Arguments
     * @param array $attributes Additional attributes
     */
    public function __construct($name, array $args = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = $name;
        $this->args = $args;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name', 'args'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_FuncCall';
    }
    /**
     *
     */
    public function getRawArgs() : array
    {
        return $this->args;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class BooleanNot extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs a boolean not node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_BooleanNot';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class ClosureUse extends Expr
{
    /** @var Expr\Variable Variable to use */
    public $var;
    /** @var bool Whether to use by reference */
    public $byRef;
    /**
     * Constructs a closure use node.
     *
     * @param Expr\Variable $var Variable to use
     * @param bool $byRef Whether to use by reference
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr\Variable $var, bool $byRef = \false, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->byRef = $byRef;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'byRef'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_ClosureUse';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class PostDec extends Expr
{
    /** @var Expr Variable */
    public $var;
    /**
     * Constructs a post decrement node.
     *
     * @param Expr $var Variable
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_PostDec';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node;
class Throw_ extends Node\Expr
{
    /** @var Node\Expr Expression */
    public $expr;
    /**
     * Constructs a throw expression node.
     *
     * @param Node\Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Throw';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Clone_ extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs a clone node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Clone';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Name;
class ConstFetch extends Expr
{
    /** @var Name Constant name */
    public $name;
    /**
     * Constructs a const fetch node.
     *
     * @param Name $name Constant name
     * @param array $attributes Additional attributes
     */
    public function __construct(Name $name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_ConstFetch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Isset_ extends Expr
{
    /** @var Expr[] Variables */
    public $vars;
    /**
     * Constructs an array node.
     *
     * @param Expr[] $vars Variables
     * @param array $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->vars = $vars;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['vars'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Isset';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class AssignRef extends Expr
{
    /** @var Expr Variable reference is assigned to */
    public $var;
    /** @var Expr Variable which is referenced */
    public $expr;
    /**
     * Constructs an assignment node.
     *
     * @param Expr $var Variable
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_AssignRef';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class PostInc extends Expr
{
    /** @var Expr Variable */
    public $var;
    /**
     * Constructs a post increment node.
     *
     * @param Expr $var Variable
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_PostInc';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Empty_ extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs an empty() node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Empty';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class UnaryPlus extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs a unary plus node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_UnaryPlus';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Include_ extends Expr
{
    const TYPE_INCLUDE = 1;
    const TYPE_INCLUDE_ONCE = 2;
    const TYPE_REQUIRE = 3;
    const TYPE_REQUIRE_ONCE = 4;
    /** @var Expr Expression */
    public $expr;
    /** @var int Type of include */
    public $type;
    /**
     * Constructs an include node.
     *
     * @param Expr $expr Expression
     * @param int $type Type of include
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, int $type, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
        $this->type = $type;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr', 'type'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Include';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
abstract class Cast extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs a cast node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class UnaryMinus extends Expr
{
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs a unary minus node.
     *
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_UnaryMinus';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\Cast;

use PhabelVendor\PhpParser\Node\Expr\Cast;
class Int_ extends Cast
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Cast_Int';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\Cast;

use PhabelVendor\PhpParser\Node\Expr\Cast;
class Bool_ extends Cast
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Cast_Bool';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\Cast;

use PhabelVendor\PhpParser\Node\Expr\Cast;
class Double extends Cast
{
    // For use in "kind" attribute
    const KIND_DOUBLE = 1;
    // "double" syntax
    const KIND_FLOAT = 2;
    // "float" syntax
    const KIND_REAL = 3;
    // "real" syntax
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Cast_Double';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\Cast;

use PhabelVendor\PhpParser\Node\Expr\Cast;
class Array_ extends Cast
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Cast_Array';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\Cast;

use PhabelVendor\PhpParser\Node\Expr\Cast;
class String_ extends Cast
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Cast_String';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\Cast;

use PhabelVendor\PhpParser\Node\Expr\Cast;
class Unset_ extends Cast
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Cast_Unset';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr\Cast;

use PhabelVendor\PhpParser\Node\Expr\Cast;
class Object_ extends Cast
{
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Cast_Object';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\VariadicPlaceholder;
class MethodCall extends CallLike
{
    /** @var Expr Variable holding object */
    public $var;
    /** @var Identifier|Expr Method name */
    public $name;
    /** @var array<Arg|VariadicPlaceholder> Arguments */
    public $args;
    /**
     * Constructs a function call node.
     *
     * @param Expr $var Variable holding object
     * @param (string | Identifier | Expr) $name Method name
     * @param array<(Arg | VariadicPlaceholder)> $args Arguments
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, $name, array $args = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
        $this->args = $args;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'name', 'args'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_MethodCall';
    }
    /**
     *
     */
    public function getRawArgs() : array
    {
        return $this->args;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\VariadicPlaceholder;
class New_ extends CallLike
{
    /** @var Node\Name|Expr|Node\Stmt\Class_ Class name */
    public $class;
    /** @var array<Arg|VariadicPlaceholder> Arguments */
    public $args;
    /**
     * Constructs a function call node.
     *
     * @param (Node\Name | Expr | Node\Stmt\Class_) $class Class name (or class node for anonymous classes)
     * @param array<(Arg | VariadicPlaceholder)> $args Arguments
     * @param array $attributes Additional attributes
     */
    public function __construct($class, array $args = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->class = $class;
        $this->args = $args;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['class', 'args'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_New';
    }
    /**
     *
     */
    public function getRawArgs() : array
    {
        return $this->args;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class PreDec extends Expr
{
    /** @var Expr Variable */
    public $var;
    /**
     * Constructs a pre decrement node.
     *
     * @param Expr $var Variable
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_PreDec';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
abstract class AssignOp extends Expr
{
    /** @var Expr Variable */
    public $var;
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs a compound assignment operation node.
     *
     * @param Expr $var Variable
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'expr'];
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Assign extends Expr
{
    /** @var Expr Variable */
    public $var;
    /** @var Expr Expression */
    public $expr;
    /**
     * Constructs an assignment node.
     *
     * @param Expr $var Variable
     * @param Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Assign';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Yield_ extends Expr
{
    /** @var null|Expr Key expression */
    public $key;
    /** @var null|Expr Value expression */
    public $value;
    /**
     * Constructs a yield expression node.
     *
     * @param (null | Expr) $value Value expression
     * @param (null | Expr) $key Key expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $value = null, Expr $key = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->key = $key;
        $this->value = $value;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['key', 'value'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Yield';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class ArrayDimFetch extends Expr
{
    /** @var Expr Variable */
    public $var;
    /** @var null|Expr Array index / dim */
    public $dim;
    /**
     * Constructs an array index fetch node.
     *
     * @param Expr $var Variable
     * @param (null | Expr) $dim Array index / dim
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr $var, Expr $dim = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->dim = $dim;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'dim'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_ArrayDimFetch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\FunctionLike;
class ArrowFunction extends Expr implements FunctionLike
{
    /** @var bool */
    public $static;
    /** @var bool */
    public $byRef;
    /** @var Node\Param[] */
    public $params = [];
    /** @var null|Node\Identifier|Node\Name|Node\ComplexType */
    public $returnType;
    /** @var Expr */
    public $expr;
    /** @var Node\AttributeGroup[] */
    public $attrGroups;
    /**
    * @param array $subNodes Array of the following optional subnodes:
    'static'     => false   : Whether the closure is static
    'byRef'      => false   : Whether to return by reference
    'params'     => array() : Parameters
    'returnType' => null    : Return type
    'expr'       => Expr    : Expression body
    'attrGroups' => array() : PHP attribute groups
    * @param array $attributes Additional attributes
    */
    public function __construct(array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->static = $subNodes['static'] ?? \false;
        $this->byRef = $subNodes['byRef'] ?? \false;
        $this->params = $subNodes['params'] ?? [];
        $returnType = $subNodes['returnType'] ?? null;
        $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
        $this->expr = $subNodes['expr'];
        $this->attrGroups = $subNodes['attrGroups'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'static', 'byRef', 'params', 'returnType', 'expr'];
    }
    /**
     *
     */
    public function returnsByRef() : bool
    {
        return $this->byRef;
    }
    /**
     *
     */
    public function getParams() : array
    {
        return $this->params;
    }
    /**
     *
     */
    public function getReturnType()
    {
        return $this->returnType;
    }
    /**
     *
     */
    public function getAttrGroups() : array
    {
        return $this->attrGroups;
    }
    /**
     * @return Node\Stmt\Return_[]
     */
    public function getStmts() : array
    {
        return [new Node\Stmt\Return_($this->expr)];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_ArrowFunction';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Expr;

use PhabelVendor\PhpParser\Node\Expr;
class Variable extends Expr
{
    /** @var string|Expr Name */
    public $name;
    /**
     * Constructs a variable node.
     *
     * @param (string | Expr) $name Name
     * @param array $attributes Additional attributes
     */
    public function __construct($name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Expr_Variable';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\Node\VariadicPlaceholder;
use PhabelVendor\PhpParser\NodeAbstract;
class Arg extends NodeAbstract
{
    /** @var Identifier|null Parameter name (for named parameters) */
    public $name;
    /** @var Expr Value to pass */
    public $value;
    /** @var bool Whether to pass by ref */
    public $byRef;
    /** @var bool Whether to unpack the argument */
    public $unpack;
    /**
     * Constructs a function call argument node.
     *
     * @param Expr $value Value to pass
     * @param bool $byRef Whether to pass by ref
     * @param bool $unpack Whether to unpack the argument
     * @param array $attributes Additional attributes
     * @param (Identifier | null) $name Parameter name (for named parameters)
     */
    public function __construct(Expr $value, bool $byRef = \false, bool $unpack = \false, array $attributes = [], Identifier $name = null)
    {
        $this->attributes = $attributes;
        $this->name = $name;
        $this->value = $value;
        $this->byRef = $byRef;
        $this->unpack = $unpack;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name', 'value', 'byRef', 'unpack'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Arg';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar\MagicConst;

use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
class Trait_ extends MagicConst
{
    /**
     *
     */
    public function getName() : string
    {
        return '__TRAIT__';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_MagicConst_Trait';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar\MagicConst;

use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
class File extends MagicConst
{
    /**
     *
     */
    public function getName() : string
    {
        return '__FILE__';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_MagicConst_File';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar\MagicConst;

use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
class Function_ extends MagicConst
{
    /**
     *
     */
    public function getName() : string
    {
        return '__FUNCTION__';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_MagicConst_Function';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar\MagicConst;

use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
class Line extends MagicConst
{
    /**
     *
     */
    public function getName() : string
    {
        return '__LINE__';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_MagicConst_Line';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar\MagicConst;

use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
class Dir extends MagicConst
{
    /**
     *
     */
    public function getName() : string
    {
        return '__DIR__';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_MagicConst_Dir';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar\MagicConst;

use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
class Namespace_ extends MagicConst
{
    /**
     *
     */
    public function getName() : string
    {
        return '__NAMESPACE__';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_MagicConst_Namespace';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar\MagicConst;

use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
class Class_ extends MagicConst
{
    /**
     *
     */
    public function getName() : string
    {
        return '__CLASS__';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_MagicConst_Class';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar\MagicConst;

use PhabelVendor\PhpParser\Node\Scalar\MagicConst;
class Method extends MagicConst
{
    /**
     *
     */
    public function getName() : string
    {
        return '__METHOD__';
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_MagicConst_Method';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar;

use PhabelVendor\PhpParser\Node\Scalar;
abstract class MagicConst extends Scalar
{
    /**
     * Constructs a magic constant node.
     *
     * @param array $attributes Additional attributes
     */
    public function __construct(array $attributes = [])
    {
        $this->attributes = $attributes;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return [];
    }
    /**
     * Get name of magic constant.
     *
     * @return string Name of magic constant
     */
    public abstract function getName() : string;
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar;

use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Scalar;
class Encapsed extends Scalar
{
    /** @var Expr[] list of string parts */
    public $parts;
    /**
     * Constructs an encapsed string node.
     *
     * @param Expr[] $parts Encaps list
     * @param array $attributes Additional attributes
     */
    public function __construct(array $parts, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->parts = $parts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['parts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_Encapsed';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar;

use PhabelVendor\PhpParser\Node\Scalar;
class EncapsedStringPart extends Scalar
{
    /** @var string String value */
    public $value;
    /**
     * Constructs a node representing a string part of an encapsed string.
     *
     * @param string $value String value
     * @param array $attributes Additional attributes
     */
    public function __construct(string $value, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->value = $value;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['value'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_EncapsedStringPart';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\Node\Scalar;
class String_ extends Scalar
{
    /* For use in "kind" attribute */
    const KIND_SINGLE_QUOTED = 1;
    const KIND_DOUBLE_QUOTED = 2;
    const KIND_HEREDOC = 3;
    const KIND_NOWDOC = 4;
    /** @var string String value */
    public $value;
    protected static $replacements = ['\\' => '\\', '$' => '$', 'n' => "\n", 'r' => "\r", 't' => "\t", 'f' => "\f", 'v' => "\v", 'e' => "\x1b"];
    /**
     * Constructs a string scalar node.
     *
     * @param string $value Value of the string
     * @param array $attributes Additional attributes
     */
    public function __construct(string $value, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->value = $value;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['value'];
    }
    /**
     * @internal
     *
     * Parses a string token.
     *
     * @param string $str String token content
     * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
     *
     * @return string The parsed string
     */
    public static function parse(string $str, bool $parseUnicodeEscape = \true) : string
    {
        $bLength = 0;
        if ('b' === $str[0] || 'B' === $str[0]) {
            $bLength = 1;
        }
        if ('\'' === $str[$bLength]) {
            return \str_replace(['\\\\', '\\\''], ['\\', '\''], \Phabel\Target\Php80\Polyfill::substr($str, $bLength + 1, -1));
        } else {
            return self::parseEscapeSequences(\Phabel\Target\Php80\Polyfill::substr($str, $bLength + 1, -1), '"', $parseUnicodeEscape);
        }
    }
    /**
     * @internal
     *
     * Parses escape sequences in strings (all string types apart from single quoted).
     *
     * @param string $str String without quotes
     * @param (null | string) $quote Quote type
     * @param bool $parseUnicodeEscape Whether to parse PHP 7 \u escapes
     *
     * @return string String with escape sequences parsed
     */
    public static function parseEscapeSequences(string $str, $quote, bool $parseUnicodeEscape = \true) : string
    {
        if (null !== $quote) {
            $str = \str_replace('\\' . $quote, $quote, $str);
        }
        $extra = '';
        if ($parseUnicodeEscape) {
            $extra = '|u\\{([0-9a-fA-F]+)\\}';
        }
        return \preg_replace_callback('~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3}' . $extra . ')~', function ($matches) {
            $str = $matches[1];
            if (isset(self::$replacements[$str])) {
                return self::$replacements[$str];
            } elseif ('x' === $str[0] || 'X' === $str[0]) {
                return \chr(\hexdec(\Phabel\Target\Php80\Polyfill::substr($str, 1)));
            } elseif ('u' === $str[0]) {
                return self::codePointToUtf8(\hexdec($matches[2]));
            } else {
                return \chr(\octdec($str));
            }
        }, $str);
    }
    /**
     * Converts a Unicode code point to its UTF-8 encoded representation.
     *
     * @param int $num Code point
     *
     * @return string UTF-8 representation of code point
     */
    private static function codePointToUtf8(int $num) : string
    {
        if ($num <= 0x7f) {
            return \chr($num);
        }
        if ($num <= 0x7ff) {
            return \chr(($num >> 6) + 0xc0) . \chr(($num & 0x3f) + 0x80);
        }
        if ($num <= 0xffff) {
            return \chr(($num >> 12) + 0xe0) . \chr(($num >> 6 & 0x3f) + 0x80) . \chr(($num & 0x3f) + 0x80);
        }
        if ($num <= 0x1fffff) {
            return \chr(($num >> 18) + 0xf0) . \chr(($num >> 12 & 0x3f) + 0x80) . \chr(($num >> 6 & 0x3f) + 0x80) . \chr(($num & 0x3f) + 0x80);
        }
        throw new Error('Invalid UTF-8 codepoint escape sequence: Codepoint too large');
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_String';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar;

use PhabelVendor\PhpParser\Node\Scalar;
class DNumber extends Scalar
{
    /** @var float Number value */
    public $value;
    /**
     * Constructs a float number scalar node.
     *
     * @param float $value Value of the number
     * @param array $attributes Additional attributes
     */
    public function __construct(float $value, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->value = $value;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['value'];
    }
    /**
     * @internal
     *
     * Parses a DNUMBER token like PHP would.
     *
     * @param string $str A string number
     *
     * @return float The parsed number
     */
    public static function parse(string $str) : float
    {
        $str = \str_replace('_', '', $str);
        // if string contains any of .eE just cast it to float
        if (\false !== \strpbrk($str, '.eE')) {
            return (float) $str;
        }
        // otherwise it's an integer notation that overflowed into a float
        // if it starts with 0 it's one of the special integer notations
        if ('0' === $str[0]) {
            // hex
            if ('x' === $str[1] || 'X' === $str[1]) {
                return \hexdec($str);
            }
            // bin
            if ('b' === $str[1] || 'B' === $str[1]) {
                return \bindec($str);
            }
            // oct
            // substr($str, 0, strcspn($str, '89')) cuts the string at the first invalid digit (8 or 9)
            // so that only the digits before that are used
            return \octdec(\Phabel\Target\Php80\Polyfill::substr($str, 0, \Phabel\Target\Php80\Polyfill::strcspn($str, '89')));
        }
        // dec
        return (float) $str;
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_DNumber';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Scalar;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\Node\Scalar;
class LNumber extends Scalar
{
    /* For use in "kind" attribute */
    const KIND_BIN = 2;
    const KIND_OCT = 8;
    const KIND_DEC = 10;
    const KIND_HEX = 16;
    /** @var int Number value */
    public $value;
    /**
     * Constructs an integer number scalar node.
     *
     * @param int $value Value of the number
     * @param array $attributes Additional attributes
     */
    public function __construct(int $value, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->value = $value;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['value'];
    }
    /**
     * Constructs an LNumber node from a string number literal.
     *
     * @param string $str String number literal (decimal, octal, hex or binary)
     * @param array $attributes Additional attributes
     * @param bool $allowInvalidOctal Whether to allow invalid octal numbers (PHP 5)
     *
     * @return LNumber The constructed LNumber, including kind attribute
     */
    public static function fromString(string $str, array $attributes = [], bool $allowInvalidOctal = \false) : LNumber
    {
        $str = \str_replace('_', '', $str);
        if ('0' !== $str[0] || '0' === $str) {
            $attributes['kind'] = LNumber::KIND_DEC;
            return new LNumber((int) $str, $attributes);
        }
        if ('x' === $str[1] || 'X' === $str[1]) {
            $attributes['kind'] = LNumber::KIND_HEX;
            return new LNumber(\hexdec($str), $attributes);
        }
        if ('b' === $str[1] || 'B' === $str[1]) {
            $attributes['kind'] = LNumber::KIND_BIN;
            return new LNumber(\bindec($str), $attributes);
        }
        if (!$allowInvalidOctal && \strpbrk($str, '89')) {
            throw new Error('Invalid numeric literal', $attributes);
        }
        // Strip optional explicit octal prefix.
        if ('o' === $str[1] || 'O' === $str[1]) {
            $str = \Phabel\Target\Php80\Polyfill::substr($str, 2);
        }
        // use intval instead of octdec to get proper cutting behavior with malformed numbers
        $attributes['kind'] = LNumber::KIND_OCT;
        return new LNumber(\intval($str, 8), $attributes);
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Scalar_LNumber';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
class Param extends NodeAbstract
{
    /** @var null|Identifier|Name|ComplexType Type declaration */
    public $type;
    /** @var bool Whether parameter is passed by reference */
    public $byRef;
    /** @var bool Whether this is a variadic argument */
    public $variadic;
    /** @var Expr\Variable|Expr\Error Parameter variable */
    public $var;
    /** @var null|Expr Default value */
    public $default;
    /** @var int */
    public $flags;
    /** @var AttributeGroup[] PHP attribute groups */
    public $attrGroups;
    /**
     * Constructs a parameter node.
     *
     * @param (Expr\Variable | Expr\Error) $var Parameter variable
     * @param (null | Expr) $default Default value
     * @param (null | string | Identifier | Name | ComplexType) $type Type declaration
     * @param bool $byRef Whether is passed by reference
     * @param bool $variadic Whether this is a variadic argument
     * @param array $attributes Additional attributes
     * @param int $flags Optional visibility flags
     * @param AttributeGroup[] $attrGroups PHP attribute groups
     */
    public function __construct($var, Expr $default = null, $type = null, bool $byRef = \false, bool $variadic = \false, array $attributes = [], int $flags = 0, array $attrGroups = [])
    {
        $this->attributes = $attributes;
        $this->type = \is_string($type) ? new Identifier($type) : $type;
        $this->byRef = $byRef;
        $this->variadic = $variadic;
        $this->var = $var;
        $this->default = $default;
        $this->flags = $flags;
        $this->attrGroups = $attrGroups;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'flags', 'type', 'byRef', 'variadic', 'var', 'default'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Param';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

class NullableType extends ComplexType
{
    /** @var Identifier|Name Type */
    public $type;
    /**
     * Constructs a nullable type (wrapping another type).
     *
     * @param (string | Identifier | Name) $type Type
     * @param array $attributes Additional attributes
     */
    public function __construct($type, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->type = \is_string($type) ? new Identifier($type) : $type;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['type'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'NullableType';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeAbstract;
class AttributeGroup extends NodeAbstract
{
    /** @var Attribute[] Attributes */
    public $attrs;
    /**
     * @param Attribute[] $attrs PHP attributes
     * @param array $attributes Additional node attributes
     */
    public function __construct(array $attrs, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->attrs = $attrs;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrs'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'AttributeGroup';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeAbstract;
class Attribute extends NodeAbstract
{
    /** @var Name Attribute name */
    public $name;
    /** @var Arg[] Attribute arguments */
    public $args;
    /**
     * @param Node\Name $name Attribute name
     * @param Arg[] $args Attribute arguments
     * @param array $attributes Additional node attributes
     */
    public function __construct(Name $name, array $args = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = $name;
        $this->args = $args;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name', 'args'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Attribute';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
abstract class Stmt extends NodeAbstract
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
class Name extends NodeAbstract
{
    /** @var string[] Parts of the name */
    public $parts;
    private static $specialClassNames = ['self' => \true, 'parent' => \true, 'static' => \true];
    /**
     * Constructs a name node.
     *
     * @param (string | string[] | self) $name Name as string, part array or Name instance (copy ctor)
     * @param array $attributes Additional attributes
     */
    public function __construct($name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->parts = self::prepareName($name);
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['parts'];
    }
    /**
     * Gets the first part of the name, i.e. everything before the first namespace separator.
     *
     * @return string First part of the name
     */
    public function getFirst() : string
    {
        return $this->parts[0];
    }
    /**
     * Gets the last part of the name, i.e. everything after the last namespace separator.
     *
     * @return string Last part of the name
     */
    public function getLast() : string
    {
        return $this->parts[\count($this->parts) - 1];
    }
    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() : bool
    {
        return 1 === \count($this->parts);
    }
    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() : bool
    {
        return 1 < \count($this->parts);
    }
    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() : bool
    {
        return \false;
    }
    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() : bool
    {
        return \false;
    }
    /**
    * Returns a string representation of the name itself, without taking the name type into
    account (e.g., not including a leading backslash for fully qualified names).
    *
    * @return string String representation
    */
    public function toString() : string
    {
        return \implode('\\', $this->parts);
    }
    /**
    * Returns a string representation of the name as it would occur in code (e.g., including
    leading backslash for fully qualified names.
    *
    * @return string String representation
    */
    public function toCodeString() : string
    {
        return $this->toString();
    }
    /**
    * Returns lowercased string representation of the name, without taking the name type into
    account (e.g., no leading backslash for fully qualified names).
    *
    * @return string Lowercased string representation
    */
    public function toLowerString() : string
    {
        return \strtolower(\implode('\\', $this->parts));
    }
    /**
     * Checks whether the identifier is a special class name (self, parent or static).
     *
     * @return bool Whether identifier is a special class name
     */
    public function isSpecialClassName() : bool
    {
        return \count($this->parts) === 1 && isset(self::$specialClassNames[\strtolower($this->parts[0])]);
    }
    /**
    * Returns a string representation of the name by imploding the namespace parts with the
    namespace separator.
    *
    * @return string String representation
    */
    public function __toString() : string
    {
        return \implode('\\', $this->parts);
    }
    /**
    * Gets a slice of a name (similar to array_slice).
    *
    * This method returns a new instance of the same type as the original and with the same
    attributes.
    *
    * If the slice is empty, null is returned. The null value will be correctly handled in
    concatenations using concat().
    *
    * Offset and length have the same meaning as in array_slice().
    *
    * @param int $offset Offset to start the slice at (may be negative)
    * @param (int | null) $length Length of the slice (may be negative)
    *
    * @return (static | null) Sliced name
    */
    public function slice(int $offset, int $length = null)
    {
        $numParts = \count($this->parts);
        $realOffset = $offset < 0 ? $offset + $numParts : $offset;
        if ($realOffset < 0 || $realOffset > $numParts) {
            throw new \OutOfBoundsException(\sprintf('Offset %d is out of bounds', $offset));
        }
        if (null === $length) {
            $realLength = $numParts - $realOffset;
        } else {
            $realLength = $length < 0 ? $length + $numParts - $realOffset : $length;
            if ($realLength < 0 || $realLength > $numParts) {
                throw new \OutOfBoundsException(\sprintf('Length %d is out of bounds', $length));
            }
        }
        if ($realLength === 0) {
            // Empty slice is represented as null
            return null;
        }
        return new static(\array_slice($this->parts, $realOffset, $realLength), $this->attributes);
    }
    /**
    * Concatenate two names, yielding a new Name instance.
    *
    * The type of the generated instance depends on which class this method is called on, for
    example Name\FullyQualified::concat() will yield a Name\FullyQualified instance.
    *
    * If one of the arguments is null, a new instance of the other name will be returned. If both
    arguments are null, null will be returned. As such, writing
    Name::concat($namespace, $shortName)
    where $namespace is a Name node or null will work as expected.
    *
    * @param (string | string[] | self | null) $name1 The first name
    * @param (string | string[] | self | null) $name2 The second name
    * @param array $attributes Attributes to assign to concatenated name
    *
    * @return (static | null) Concatenated name
    */
    public static function concat($name1, $name2, array $attributes = [])
    {
        if (null === $name1 && null === $name2) {
            return null;
        } elseif (null === $name1) {
            return new static(self::prepareName($name2), $attributes);
        } elseif (null === $name2) {
            return new static(self::prepareName($name1), $attributes);
        } else {
            return new static(\array_merge(self::prepareName($name1), self::prepareName($name2)), $attributes);
        }
    }
    /**
    * Prepares a (string, array or Name node) name for use in name changing methods by converting
    it to an array.
    *
    * @param (string | string[] | self) $name Name to prepare
    *
    * @return string[] Prepared name
    */
    private static function prepareName($name) : array
    {
        if (\is_string($name)) {
            if ('' === $name) {
                throw new \InvalidArgumentException('Name cannot be empty');
            }
            return \explode('\\', $name);
        } elseif (\is_array($name)) {
            if (empty($name)) {
                throw new \InvalidArgumentException('Name cannot be empty');
            }
            return $name;
        } elseif ($name instanceof self) {
            return $name->parts;
        }
        throw new \InvalidArgumentException('Expected string, array of parts or Name instance');
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Name';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

class UnionType extends ComplexType
{
    /** @var (Identifier|Name)[] Types */
    public $types;
    /**
     * Constructs a union type.
     *
     * @param (Identifier | Name)[] $types Types
     * @param array $attributes Additional attributes
     */
    public function __construct(array $types, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->types = $types;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['types'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'UnionType';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\Node;
interface FunctionLike extends Node
{
    /**
     * Whether to return by reference
     *
     * @return bool
     */
    public function returnsByRef() : bool;
    /**
     * List of parameters
     *
     * @return Param[]
     */
    public function getParams() : array;
    /**
     * Get the declared return type or null
     *
     * @return (null | Identifier | Name | ComplexType)
     */
    public function getReturnType();
    /**
     * The function body
     *
     * @return (Stmt[] | null)
     */
    public function getStmts();
    /**
     * Get PHP attribute groups.
     *
     * @return AttributeGroup[]
     */
    public function getAttrGroups() : array;
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeAbstract;
class MatchArm extends NodeAbstract
{
    /** @var null|Node\Expr[] */
    public $conds;
    /** @var Node\Expr */
    public $body;
    /**
     * @param (null | Node\Expr[]) $conds
     */
    public function __construct($conds, Node\Expr $body, array $attributes = [])
    {
        $this->conds = $conds;
        $this->body = $body;
        $this->attributes = $attributes;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['conds', 'body'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'MatchArm';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
class Const_ extends NodeAbstract
{
    /** @var Identifier Name */
    public $name;
    /** @var Expr Value */
    public $value;
    /** @var Name|null Namespaced name (if using NameResolver) */
    public $namespacedName;
    /**
     * Constructs a const node for use in class const and const statements.
     *
     * @param (string | Identifier) $name Name
     * @param Expr $value Value
     * @param array $attributes Additional attributes
     */
    public function __construct($name, Expr $value, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
        $this->value = $value;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name', 'value'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Const';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

use PhabelVendor\PhpParser\NodeAbstract;
abstract class Expr extends NodeAbstract
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Do_ extends Node\Stmt
{
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /** @var Node\Expr Condition */
    public $cond;
    /**
     * Constructs a do while node.
     *
     * @param Node\Expr $cond Condition
     * @param Node\Stmt[] $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->cond = $cond;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['stmts', 'cond'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Do';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Break_ extends Node\Stmt
{
    /** @var null|Node\Expr Number of loops to break */
    public $num;
    /**
     * Constructs a break node.
     *
     * @param (null | Node\Expr) $num Number of loops to break
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $num = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->num = $num;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['num'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Break';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Foreach_ extends Node\Stmt
{
    /** @var Node\Expr Expression to iterate */
    public $expr;
    /** @var null|Node\Expr Variable to assign key to */
    public $keyVar;
    /** @var bool Whether to assign value by reference */
    public $byRef;
    /** @var Node\Expr Variable to assign value to */
    public $valueVar;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
    * Constructs a foreach node.
    *
    * @param Node\Expr $expr Expression to iterate
    * @param Node\Expr $valueVar Variable to assign value to
    * @param array $subNodes Array of the following optional subnodes:
    'keyVar' => null   : Variable to assign key to
    'byRef'  => false  : Whether to assign value by reference
    'stmts'  => array(): Statements
    * @param array $attributes Additional attributes
    */
    public function __construct(Node\Expr $expr, Node\Expr $valueVar, array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
        $this->keyVar = $subNodes['keyVar'] ?? null;
        $this->byRef = $subNodes['byRef'] ?? \false;
        $this->valueVar = $valueVar;
        $this->stmts = $subNodes['stmts'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr', 'keyVar', 'byRef', 'valueVar', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Foreach';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class PropertyProperty extends Node\Stmt
{
    /** @var Node\VarLikeIdentifier Name */
    public $name;
    /** @var null|Node\Expr Default */
    public $default;
    /**
     * Constructs a class property node.
     *
     * @param (string | Node\VarLikeIdentifier) $name Name
     * @param (null | Node\Expr) $default Default value
     * @param array $attributes Additional attributes
     */
    public function __construct($name, Node\Expr $default = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = \is_string($name) ? new Node\VarLikeIdentifier($name) : $name;
        $this->default = $default;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name', 'default'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_PropertyProperty';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class For_ extends Node\Stmt
{
    /** @var Node\Expr[] Init expressions */
    public $init;
    /** @var Node\Expr[] Loop conditions */
    public $cond;
    /** @var Node\Expr[] Loop expressions */
    public $loop;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
    * Constructs a for loop node.
    *
    * @param array $subNodes Array of the following optional subnodes:
    'init'  => array(): Init expressions
    'cond'  => array(): Loop conditions
    'loop'  => array(): Loop expressions
    'stmts' => array(): Statements
    * @param array $attributes Additional attributes
    */
    public function __construct(array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->init = $subNodes['init'] ?? [];
        $this->cond = $subNodes['cond'] ?? [];
        $this->loop = $subNodes['loop'] ?? [];
        $this->stmts = $subNodes['stmts'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['init', 'cond', 'loop', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_For';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\AttributeGroup;
class EnumCase extends Node\Stmt
{
    /** @var Node\Identifier Enum case name */
    public $name;
    /** @var Node\Expr|null Enum case expression */
    public $expr;
    /** @var Node\AttributeGroup[] PHP attribute groups */
    public $attrGroups;
    /**
     * @param (string | Node\Identifier) $name Enum case name
     * @param (Node\Expr | null) $expr Enum case expression
     * @param AttributeGroup[] $attrGroups PHP attribute groups
     * @param array $attributes Additional attributes
     */
    public function __construct($name, Node\Expr $expr = null, array $attrGroups = [], array $attributes = [])
    {
        parent::__construct($attributes);
        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
        $this->expr = $expr;
        $this->attrGroups = $attrGroups;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'name', 'expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_EnumCase';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Declare_ extends Node\Stmt
{
    /** @var DeclareDeclare[] List of declares */
    public $declares;
    /** @var Node\Stmt[]|null Statements */
    public $stmts;
    /**
     * Constructs a declare node.
     *
     * @param DeclareDeclare[] $declares List of declares
     * @param (Node\Stmt[] | null) $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(array $declares, array $stmts = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->declares = $declares;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['declares', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Declare';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Identifier;
class UseUse extends Node\Stmt
{
    /** @var int One of the Stmt\Use_::TYPE_* constants. Will only differ from TYPE_UNKNOWN for mixed group uses */
    public $type;
    /** @var Node\Name Namespace, class, function or constant to alias */
    public $name;
    /** @var Identifier|null Alias */
    public $alias;
    /**
     * Constructs an alias (use) node.
     *
     * @param Node\Name $name Namespace/Class to alias
     * @param (null | string | Identifier) $alias Alias
     * @param int $type Type of the use element (for mixed group use only)
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Name $name, $alias = null, int $type = Use_::TYPE_UNKNOWN, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->type = $type;
        $this->name = $name;
        $this->alias = \is_string($alias) ? new Identifier($alias) : $alias;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['type', 'name', 'alias'];
    }
    /**
     * Get alias. If not explicitly given this is the last component of the used name.
     *
     * @return Identifier
     */
    public function getAlias() : Identifier
    {
        if (null !== $this->alias) {
            return $this->alias;
        }
        return new Identifier($this->name->getLast());
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_UseUse';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class ClassConst extends Node\Stmt
{
    /** @var int Modifiers */
    public $flags;
    /** @var Node\Const_[] Constant declarations */
    public $consts;
    /** @var Node\AttributeGroup[] */
    public $attrGroups;
    /**
     * Constructs a class const list node.
     *
     * @param Node\Const_[] $consts Constant declarations
     * @param int $flags Modifiers
     * @param array $attributes Additional attributes
     * @param Node\AttributeGroup[] $attrGroups PHP attribute groups
     */
    public function __construct(array $consts, int $flags = 0, array $attributes = [], array $attrGroups = [])
    {
        $this->attributes = $attributes;
        $this->flags = $flags;
        $this->consts = $consts;
        $this->attrGroups = $attrGroups;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'flags', 'consts'];
    }
    /**
     * Whether constant is explicitly or implicitly public.
     *
     * @return bool
     */
    public function isPublic() : bool
    {
        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
    }
    /**
     * Whether constant is protected.
     *
     * @return bool
     */
    public function isProtected() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
    }
    /**
     * Whether constant is private.
     *
     * @return bool
     */
    public function isPrivate() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
    }
    /**
     * Whether constant is final.
     *
     * @return bool
     */
    public function isFinal() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_FINAL);
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_ClassConst';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Echo_ extends Node\Stmt
{
    /** @var Node\Expr[] Expressions */
    public $exprs;
    /**
     * Constructs an echo node.
     *
     * @param Node\Expr[] $exprs Expressions
     * @param array $attributes Additional attributes
     */
    public function __construct(array $exprs, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->exprs = $exprs;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['exprs'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Echo';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Stmt;
class Label extends Stmt
{
    /** @var Identifier Name */
    public $name;
    /**
     * Constructs a label node.
     *
     * @param (string | Identifier) $name Name
     * @param array $attributes Additional attributes
     */
    public function __construct($name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Label';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Enum_ extends ClassLike
{
    /** @var null|Node\Identifier Scalar Type */
    public $scalarType;
    /** @var Node\Name[] Names of implemented interfaces */
    public $implements;
    /**
    * @param (string | Node\Identifier | null) $name Name
    * @param array $subNodes Array of the following optional subnodes:
    'scalarType'  => null    : Scalar type
    'implements'  => array() : Names of implemented interfaces
    'stmts'       => array() : Statements
    'attrGroups'  => array() : PHP attribute groups
    * @param array $attributes Additional attributes
    */
    public function __construct($name, array $subNodes = [], array $attributes = [])
    {
        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
        $this->scalarType = $subNodes['scalarType'] ?? null;
        $this->implements = $subNodes['implements'] ?? [];
        $this->stmts = $subNodes['stmts'] ?? [];
        $this->attrGroups = $subNodes['attrGroups'] ?? [];
        parent::__construct($attributes);
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'name', 'scalarType', 'implements', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Enum';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
class StaticVar extends Node\Stmt
{
    /** @var Expr\Variable Variable */
    public $var;
    /** @var null|Node\Expr Default value */
    public $default;
    /**
     * Constructs a static variable node.
     *
     * @param Expr\Variable $var Name
     * @param (null | Node\Expr) $default Default value
     * @param array $attributes Additional attributes
     */
    public function __construct(Expr\Variable $var, Node\Expr $default = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->var = $var;
        $this->default = $default;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['var', 'default'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_StaticVar';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
/**
 * Represents statements of type "expr;"
 */
class Expression extends Node\Stmt
{
    /** @var Node\Expr Expression */
    public $expr;
    /**
     * Constructs an expression statement.
     *
     * @param Node\Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Expression';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Trait_ extends ClassLike
{
    /**
    * Constructs a trait node.
    *
    * @param (string | Node\Identifier) $name Name
    * @param array $subNodes Array of the following optional subnodes:
    'stmts'      => array(): Statements
    'attrGroups' => array(): PHP attribute groups
    * @param array $attributes Additional attributes
    */
    public function __construct($name, array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
        $this->stmts = $subNodes['stmts'] ?? [];
        $this->attrGroups = $subNodes['attrGroups'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'name', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Trait';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Stmt;
class GroupUse extends Stmt
{
    /** @var int Type of group use */
    public $type;
    /** @var Name Prefix for uses */
    public $prefix;
    /** @var UseUse[] Uses */
    public $uses;
    /**
     * Constructs a group use node.
     *
     * @param Name $prefix Prefix for uses
     * @param UseUse[] $uses Uses
     * @param int $type Type of group use
     * @param array $attributes Additional attributes
     */
    public function __construct(Name $prefix, array $uses, int $type = Use_::TYPE_NORMAL, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->type = $type;
        $this->prefix = $prefix;
        $this->uses = $uses;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['type', 'prefix', 'uses'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_GroupUse';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\FunctionLike;
class ClassMethod extends Node\Stmt implements FunctionLike
{
    /** @var int Flags */
    public $flags;
    /** @var bool Whether to return by reference */
    public $byRef;
    /** @var Node\Identifier Name */
    public $name;
    /** @var Node\Param[] Parameters */
    public $params;
    /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */
    public $returnType;
    /** @var Node\Stmt[]|null Statements */
    public $stmts;
    /** @var Node\AttributeGroup[] PHP attribute groups */
    public $attrGroups;
    private static $magicNames = ['__construct' => \true, '__destruct' => \true, '__call' => \true, '__callstatic' => \true, '__get' => \true, '__set' => \true, '__isset' => \true, '__unset' => \true, '__sleep' => \true, '__wakeup' => \true, '__tostring' => \true, '__set_state' => \true, '__clone' => \true, '__invoke' => \true, '__debuginfo' => \true];
    /**
    * Constructs a class method node.
    *
    * @param (string | Node\Identifier) $name Name
    * @param array $subNodes Array of the following optional subnodes:
    'flags       => MODIFIER_PUBLIC: Flags
    'byRef'      => false          : Whether to return by reference
    'params'     => array()        : Parameters
    'returnType' => null           : Return type
    'stmts'      => array()        : Statements
    'attrGroups' => array()        : PHP attribute groups
    * @param array $attributes Additional attributes
    */
    public function __construct($name, array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0;
        $this->byRef = $subNodes['byRef'] ?? \false;
        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
        $this->params = $subNodes['params'] ?? [];
        $returnType = $subNodes['returnType'] ?? null;
        $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
        $this->stmts = \array_key_exists('stmts', $subNodes) ? $subNodes['stmts'] : [];
        $this->attrGroups = $subNodes['attrGroups'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'flags', 'byRef', 'name', 'params', 'returnType', 'stmts'];
    }
    /**
     *
     */
    public function returnsByRef() : bool
    {
        return $this->byRef;
    }
    /**
     *
     */
    public function getParams() : array
    {
        return $this->params;
    }
    /**
     *
     */
    public function getReturnType()
    {
        return $this->returnType;
    }
    /**
     *
     */
    public function getStmts()
    {
        return $this->stmts;
    }
    /**
     *
     */
    public function getAttrGroups() : array
    {
        return $this->attrGroups;
    }
    /**
     * Whether the method is explicitly or implicitly public.
     *
     * @return bool
     */
    public function isPublic() : bool
    {
        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
    }
    /**
     * Whether the method is protected.
     *
     * @return bool
     */
    public function isProtected() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
    }
    /**
     * Whether the method is private.
     *
     * @return bool
     */
    public function isPrivate() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
    }
    /**
     * Whether the method is abstract.
     *
     * @return bool
     */
    public function isAbstract() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_ABSTRACT);
    }
    /**
     * Whether the method is final.
     *
     * @return bool
     */
    public function isFinal() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_FINAL);
    }
    /**
     * Whether the method is static.
     *
     * @return bool
     */
    public function isStatic() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_STATIC);
    }
    /**
     * Whether the method is magic.
     *
     * @return bool
     */
    public function isMagic() : bool
    {
        return isset(self::$magicNames[$this->name->toLowerString()]);
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_ClassMethod';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
class Catch_ extends Node\Stmt
{
    /** @var Node\Name[] Types of exceptions to catch */
    public $types;
    /** @var Expr\Variable|null Variable for exception */
    public $var;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
     * Constructs a catch node.
     *
     * @param Node\Name[] $types Types of exceptions to catch
     * @param (Expr\Variable | null) $var Variable for exception
     * @param Node\Stmt[] $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(array $types, Expr\Variable $var = null, array $stmts = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->types = $types;
        $this->var = $var;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['types', 'var', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Catch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node\Stmt;
class Static_ extends Stmt
{
    /** @var StaticVar[] Variable definitions */
    public $vars;
    /**
     * Constructs a static variables list node.
     *
     * @param StaticVar[] $vars Variable definitions
     * @param array $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->vars = $vars;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['vars'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Static';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Stmt;
class Goto_ extends Stmt
{
    /** @var Identifier Name of label to jump to */
    public $name;
    /**
     * Constructs a goto node.
     *
     * @param (string | Identifier) $name Name of label to jump to
     * @param array $attributes Additional attributes
     */
    public function __construct($name, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = \is_string($name) ? new Identifier($name) : $name;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Goto';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
abstract class ClassLike extends Node\Stmt
{
    /** @var Node\Identifier|null Name */
    public $name;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /** @var Node\AttributeGroup[] PHP attribute groups */
    public $attrGroups;
    /** @var Node\Name|null Namespaced name (if using NameResolver) */
    public $namespacedName;
    /**
     * @return TraitUse[]
     */
    public function getTraitUses() : array
    {
        $traitUses = [];
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof TraitUse) {
                $traitUses[] = $stmt;
            }
        }
        return $traitUses;
    }
    /**
     * @return ClassConst[]
     */
    public function getConstants() : array
    {
        $constants = [];
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof ClassConst) {
                $constants[] = $stmt;
            }
        }
        return $constants;
    }
    /**
     * @return Property[]
     */
    public function getProperties() : array
    {
        $properties = [];
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof Property) {
                $properties[] = $stmt;
            }
        }
        return $properties;
    }
    /**
     * Gets property with the given name defined directly in this class/interface/trait.
     *
     * @param string $name Name of the property
     *
     * @return (Property | null) Property node or null if the property does not exist
     */
    public function getProperty(string $name)
    {
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof Property) {
                foreach ($stmt->props as $prop) {
                    if ($prop instanceof PropertyProperty && $name === $prop->name->toString()) {
                        return $stmt;
                    }
                }
            }
        }
        return null;
    }
    /**
     * Gets all methods defined directly in this class/interface/trait
     *
     * @return ClassMethod[]
     */
    public function getMethods() : array
    {
        $methods = [];
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof ClassMethod) {
                $methods[] = $stmt;
            }
        }
        return $methods;
    }
    /**
     * Gets method with the given name defined directly in this class/interface/trait.
     *
     * @param string $name Name of the method (compared case-insensitively)
     *
     * @return (ClassMethod | null) Method node or null if the method does not exist
     */
    public function getMethod(string $name)
    {
        $lowerName = \strtolower($name);
        foreach ($this->stmts as $stmt) {
            if ($stmt instanceof ClassMethod && $lowerName === $stmt->name->toLowerString()) {
                return $stmt;
            }
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Switch_ extends Node\Stmt
{
    /** @var Node\Expr Condition */
    public $cond;
    /** @var Case_[] Case list */
    public $cases;
    /**
     * Constructs a case node.
     *
     * @param Node\Expr $cond Condition
     * @param Case_[] $cases Case list
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $cases, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->cond = $cond;
        $this->cases = $cases;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['cond', 'cases'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Switch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Return_ extends Node\Stmt
{
    /** @var null|Node\Expr Expression */
    public $expr;
    /**
     * Constructs a return node.
     *
     * @param (null | Node\Expr) $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $expr = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Return';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class DeclareDeclare extends Node\Stmt
{
    /** @var Node\Identifier Key */
    public $key;
    /** @var Node\Expr Value */
    public $value;
    /**
     * Constructs a declare key=>value pair node.
     *
     * @param (string | Node\Identifier) $key Key
     * @param Node\Expr $value Value
     * @param array $attributes Additional attributes
     */
    public function __construct($key, Node\Expr $value, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->key = \is_string($key) ? new Node\Identifier($key) : $key;
        $this->value = $value;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['key', 'value'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_DeclareDeclare';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\FunctionLike;
class Function_ extends Node\Stmt implements FunctionLike
{
    /** @var bool Whether function returns by reference */
    public $byRef;
    /** @var Node\Identifier Name */
    public $name;
    /** @var Node\Param[] Parameters */
    public $params;
    /** @var null|Node\Identifier|Node\Name|Node\ComplexType Return type */
    public $returnType;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /** @var Node\AttributeGroup[] PHP attribute groups */
    public $attrGroups;
    /** @var Node\Name|null Namespaced name (if using NameResolver) */
    public $namespacedName;
    /**
    * Constructs a function node.
    *
    * @param (string | Node\Identifier) $name Name
    * @param array $subNodes Array of the following optional subnodes:
    'byRef'      => false  : Whether to return by reference
    'params'     => array(): Parameters
    'returnType' => null   : Return type
    'stmts'      => array(): Statements
    'attrGroups' => array(): PHP attribute groups
    * @param array $attributes Additional attributes
    */
    public function __construct($name, array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->byRef = $subNodes['byRef'] ?? \false;
        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
        $this->params = $subNodes['params'] ?? [];
        $returnType = $subNodes['returnType'] ?? null;
        $this->returnType = \is_string($returnType) ? new Node\Identifier($returnType) : $returnType;
        $this->stmts = $subNodes['stmts'] ?? [];
        $this->attrGroups = $subNodes['attrGroups'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'byRef', 'name', 'params', 'returnType', 'stmts'];
    }
    /**
     *
     */
    public function returnsByRef() : bool
    {
        return $this->byRef;
    }
    /**
     *
     */
    public function getParams() : array
    {
        return $this->params;
    }
    /**
     *
     */
    public function getReturnType()
    {
        return $this->returnType;
    }
    /**
     *
     */
    public function getAttrGroups() : array
    {
        return $this->attrGroups;
    }
    /**
     * @return Node\Stmt[]
     */
    public function getStmts() : array
    {
        return $this->stmts;
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Function';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Interface_ extends ClassLike
{
    /** @var Node\Name[] Extended interfaces */
    public $extends;
    /**
    * Constructs a class node.
    *
    * @param (string | Node\Identifier) $name Name
    * @param array $subNodes Array of the following optional subnodes:
    'extends'    => array(): Name of extended interfaces
    'stmts'      => array(): Statements
    'attrGroups' => array(): PHP attribute groups
    * @param array $attributes Additional attributes
    */
    public function __construct($name, array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
        $this->extends = $subNodes['extends'] ?? [];
        $this->stmts = $subNodes['stmts'] ?? [];
        $this->attrGroups = $subNodes['attrGroups'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'name', 'extends', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Interface';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Const_ extends Node\Stmt
{
    /** @var Node\Const_[] Constant declarations */
    public $consts;
    /**
     * Constructs a const list node.
     *
     * @param Node\Const_[] $consts Constant declarations
     * @param array $attributes Additional attributes
     */
    public function __construct(array $consts, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->consts = $consts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['consts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Const';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Throw_ extends Node\Stmt
{
    /** @var Node\Expr Expression */
    public $expr;
    /**
     * Constructs a legacy throw statement node.
     *
     * @param Node\Expr $expr Expression
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $expr, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->expr = $expr;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['expr'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Throw';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class TraitUse extends Node\Stmt
{
    /** @var Node\Name[] Traits */
    public $traits;
    /** @var TraitUseAdaptation[] Adaptations */
    public $adaptations;
    /**
     * Constructs a trait use node.
     *
     * @param Node\Name[] $traits Traits
     * @param TraitUseAdaptation[] $adaptations Adaptations
     * @param array $attributes Additional attributes
     */
    public function __construct(array $traits, array $adaptations = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->traits = $traits;
        $this->adaptations = $adaptations;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['traits', 'adaptations'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_TraitUse';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Unset_ extends Node\Stmt
{
    /** @var Node\Expr[] Variables to unset */
    public $vars;
    /**
     * Constructs an unset node.
     *
     * @param Node\Expr[] $vars Variables to unset
     * @param array $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->vars = $vars;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['vars'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Unset';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
/** Nop/empty statement (;). */
class Nop extends Node\Stmt
{
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return [];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Nop';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class While_ extends Node\Stmt
{
    /** @var Node\Expr Condition */
    public $cond;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
     * Constructs a while node.
     *
     * @param Node\Expr $cond Condition
     * @param Node\Stmt[] $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->cond = $cond;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['cond', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_While';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class TryCatch extends Node\Stmt
{
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /** @var Catch_[] Catches */
    public $catches;
    /** @var null|Finally_ Optional finally node */
    public $finally;
    /**
     * Constructs a try catch node.
     *
     * @param Node\Stmt[] $stmts Statements
     * @param Catch_[] $catches Catches
     * @param (null | Finally_) $finally Optional finally node
     * @param array $attributes Additional attributes
     */
    public function __construct(array $stmts, array $catches, Finally_ $finally = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->stmts = $stmts;
        $this->catches = $catches;
        $this->finally = $finally;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['stmts', 'catches', 'finally'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_TryCatch';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node\Stmt;
class Use_ extends Stmt
{
    /**
     * Unknown type. Both Stmt\Use_ / Stmt\GroupUse and Stmt\UseUse have a $type property, one of them will always be
     * TYPE_UNKNOWN while the other has one of the three other possible types. For normal use statements the type on the
     * Stmt\UseUse is unknown. It's only the other way around for mixed group use declarations.
     */
    const TYPE_UNKNOWN = 0;
    /** Class or namespace import */
    const TYPE_NORMAL = 1;
    /** Function import */
    const TYPE_FUNCTION = 2;
    /** Constant import */
    const TYPE_CONSTANT = 3;
    /** @var int Type of alias */
    public $type;
    /** @var UseUse[] Aliases */
    public $uses;
    /**
     * Constructs an alias (use) list node.
     *
     * @param UseUse[] $uses Aliases
     * @param int $type Type of alias
     * @param array $attributes Additional attributes
     */
    public function __construct(array $uses, int $type = self::TYPE_NORMAL, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->type = $type;
        $this->uses = $uses;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['type', 'uses'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Use';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Continue_ extends Node\Stmt
{
    /** @var null|Node\Expr Number of loops to continue */
    public $num;
    /**
     * Constructs a continue node.
     *
     * @param (null | Node\Expr) $num Number of loops to continue
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $num = null, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->num = $num;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['num'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Continue';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Namespace_ extends Node\Stmt
{
    /* For use in the "kind" attribute */
    const KIND_SEMICOLON = 1;
    const KIND_BRACED = 2;
    /** @var null|Node\Name Name */
    public $name;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
     * Constructs a namespace node.
     *
     * @param (null | Node\Name) $name Name
     * @param (null | Node\Stmt[]) $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Name $name = null, $stmts = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->name = $name;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['name', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Namespace';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class If_ extends Node\Stmt
{
    /** @var Node\Expr Condition expression */
    public $cond;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /** @var ElseIf_[] Elseif clauses */
    public $elseifs;
    /** @var null|Else_ Else clause */
    public $else;
    /**
    * Constructs an if node.
    *
    * @param Node\Expr $cond Condition
    * @param array $subNodes Array of the following optional subnodes:
    'stmts'   => array(): Statements
    'elseifs' => array(): Elseif clauses
    'else'    => null   : Else clause
    * @param array $attributes Additional attributes
    */
    public function __construct(Node\Expr $cond, array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->cond = $cond;
        $this->stmts = $subNodes['stmts'] ?? [];
        $this->elseifs = $subNodes['elseifs'] ?? [];
        $this->else = $subNodes['else'] ?? null;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['cond', 'stmts', 'elseifs', 'else'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_If';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Global_ extends Node\Stmt
{
    /** @var Node\Expr[] Variables */
    public $vars;
    /**
     * Constructs a global variables list node.
     *
     * @param Node\Expr[] $vars Variables to unset
     * @param array $attributes Additional attributes
     */
    public function __construct(array $vars, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->vars = $vars;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['vars'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Global';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\Node;
class Class_ extends ClassLike
{
    const MODIFIER_PUBLIC = 1;
    const MODIFIER_PROTECTED = 2;
    const MODIFIER_PRIVATE = 4;
    const MODIFIER_STATIC = 8;
    const MODIFIER_ABSTRACT = 16;
    const MODIFIER_FINAL = 32;
    const MODIFIER_READONLY = 64;
    const VISIBILITY_MODIFIER_MASK = 7;
    // 1 | 2 | 4
    /** @var int Type */
    public $flags;
    /** @var null|Node\Name Name of extended class */
    public $extends;
    /** @var Node\Name[] Names of implemented interfaces */
    public $implements;
    /**
    * Constructs a class node.
    *
    * @param (string | Node\Identifier | null) $name Name
    * @param array $subNodes Array of the following optional subnodes:
    'flags'       => 0      : Flags
    'extends'     => null   : Name of extended class
    'implements'  => array(): Names of implemented interfaces
    'stmts'       => array(): Statements
    'attrGroups'  => array(): PHP attribute groups
    * @param array $attributes Additional attributes
    */
    public function __construct($name, array $subNodes = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->flags = $subNodes['flags'] ?? $subNodes['type'] ?? 0;
        $this->name = \is_string($name) ? new Node\Identifier($name) : $name;
        $this->extends = $subNodes['extends'] ?? null;
        $this->implements = $subNodes['implements'] ?? [];
        $this->stmts = $subNodes['stmts'] ?? [];
        $this->attrGroups = $subNodes['attrGroups'] ?? [];
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'flags', 'name', 'extends', 'implements', 'stmts'];
    }
    /**
     * Whether the class is explicitly abstract.
     *
     * @return bool
     */
    public function isAbstract() : bool
    {
        return (bool) ($this->flags & self::MODIFIER_ABSTRACT);
    }
    /**
     * Whether the class is final.
     *
     * @return bool
     */
    public function isFinal() : bool
    {
        return (bool) ($this->flags & self::MODIFIER_FINAL);
    }
    /**
     * Whether the class is anonymous.
     *
     * @return bool
     */
    public function isAnonymous() : bool
    {
        return null === $this->name;
    }
    /**
     * @internal
     */
    public static function verifyModifier($a, $b)
    {
        if ($a & self::VISIBILITY_MODIFIER_MASK && $b & self::VISIBILITY_MODIFIER_MASK) {
            throw new Error('Multiple access type modifiers are not allowed');
        }
        if ($a & self::MODIFIER_ABSTRACT && $b & self::MODIFIER_ABSTRACT) {
            throw new Error('Multiple abstract modifiers are not allowed');
        }
        if ($a & self::MODIFIER_STATIC && $b & self::MODIFIER_STATIC) {
            throw new Error('Multiple static modifiers are not allowed');
        }
        if ($a & self::MODIFIER_FINAL && $b & self::MODIFIER_FINAL) {
            throw new Error('Multiple final modifiers are not allowed');
        }
        if ($a & self::MODIFIER_READONLY && $b & self::MODIFIER_READONLY) {
            throw new Error('Multiple readonly modifiers are not allowed');
        }
        if ($a & 48 && $b & 48) {
            throw new Error('Cannot use the final modifier on an abstract class member');
        }
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Class';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Finally_ extends Node\Stmt
{
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
     * Constructs a finally node.
     *
     * @param Node\Stmt[] $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(array $stmts = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Finally';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node\Stmt;
class HaltCompiler extends Stmt
{
    /** @var string Remaining text after halt compiler statement. */
    public $remaining;
    /**
     * Constructs a __halt_compiler node.
     *
     * @param string $remaining Remaining text after halt compiler statement.
     * @param array $attributes Additional attributes
     */
    public function __construct(string $remaining, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->remaining = $remaining;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['remaining'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_HaltCompiler';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt\TraitUseAdaptation;

use PhabelVendor\PhpParser\Node;
class Precedence extends Node\Stmt\TraitUseAdaptation
{
    /** @var Node\Name[] Overwritten traits */
    public $insteadof;
    /**
     * Constructs a trait use precedence adaptation node.
     *
     * @param Node\Name $trait Trait name
     * @param (string | Node\Identifier) $method Method name
     * @param Node\Name[] $insteadof Overwritten traits
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Name $trait, $method, array $insteadof, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->trait = $trait;
        $this->method = \is_string($method) ? new Node\Identifier($method) : $method;
        $this->insteadof = $insteadof;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['trait', 'method', 'insteadof'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_TraitUseAdaptation_Precedence';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt\TraitUseAdaptation;

use PhabelVendor\PhpParser\Node;
class Alias extends Node\Stmt\TraitUseAdaptation
{
    /** @var null|int New modifier */
    public $newModifier;
    /** @var null|Node\Identifier New name */
    public $newName;
    /**
     * Constructs a trait use precedence adaptation node.
     *
     * @param (null | Node\Name) $trait Trait name
     * @param (string | Node\Identifier) $method Method name
     * @param (null | int) $newModifier New modifier
     * @param (null | string | Node\Identifier) $newName New name
     * @param array $attributes Additional attributes
     */
    public function __construct($trait, $method, $newModifier, $newName, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->trait = $trait;
        $this->method = \is_string($method) ? new Node\Identifier($method) : $method;
        $this->newModifier = $newModifier;
        $this->newName = \is_string($newName) ? new Node\Identifier($newName) : $newName;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['trait', 'method', 'newModifier', 'newName'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_TraitUseAdaptation_Alias';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Case_ extends Node\Stmt
{
    /** @var null|Node\Expr Condition (null for default) */
    public $cond;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
     * Constructs a case node.
     *
     * @param (null | Node\Expr) $cond Condition (null for default)
     * @param Node\Stmt[] $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct($cond, array $stmts = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->cond = $cond;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['cond', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Case';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node\Stmt;
class InlineHTML extends Stmt
{
    /** @var string String */
    public $value;
    /**
     * Constructs an inline HTML node.
     *
     * @param string $value String
     * @param array $attributes Additional attributes
     */
    public function __construct(string $value, array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->value = $value;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['value'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_InlineHTML';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
abstract class TraitUseAdaptation extends Node\Stmt
{
    /** @var Node\Name|null Trait name */
    public $trait;
    /** @var Node\Identifier Method name */
    public $method;
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class Else_ extends Node\Stmt
{
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
     * Constructs an else node.
     *
     * @param Node\Stmt[] $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(array $stmts = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Else';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\ComplexType;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
class Property extends Node\Stmt
{
    /** @var int Modifiers */
    public $flags;
    /** @var PropertyProperty[] Properties */
    public $props;
    /** @var null|Identifier|Name|ComplexType Type declaration */
    public $type;
    /** @var Node\AttributeGroup[] PHP attribute groups */
    public $attrGroups;
    /**
     * Constructs a class property list node.
     *
     * @param int $flags Modifiers
     * @param PropertyProperty[] $props Properties
     * @param array $attributes Additional attributes
     * @param (null | string | Identifier | Name | ComplexType) $type Type declaration
     * @param Node\AttributeGroup[] $attrGroups PHP attribute groups
     */
    public function __construct(int $flags, array $props, array $attributes = [], $type = null, array $attrGroups = [])
    {
        $this->attributes = $attributes;
        $this->flags = $flags;
        $this->props = $props;
        $this->type = \is_string($type) ? new Identifier($type) : $type;
        $this->attrGroups = $attrGroups;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['attrGroups', 'flags', 'type', 'props'];
    }
    /**
     * Whether the property is explicitly or implicitly public.
     *
     * @return bool
     */
    public function isPublic() : bool
    {
        return ($this->flags & Class_::MODIFIER_PUBLIC) !== 0 || ($this->flags & Class_::VISIBILITY_MODIFIER_MASK) === 0;
    }
    /**
     * Whether the property is protected.
     *
     * @return bool
     */
    public function isProtected() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_PROTECTED);
    }
    /**
     * Whether the property is private.
     *
     * @return bool
     */
    public function isPrivate() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_PRIVATE);
    }
    /**
     * Whether the property is static.
     *
     * @return bool
     */
    public function isStatic() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_STATIC);
    }
    /**
     * Whether the property is readonly.
     *
     * @return bool
     */
    public function isReadonly() : bool
    {
        return (bool) ($this->flags & Class_::MODIFIER_READONLY);
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_Property';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Stmt;

use PhabelVendor\PhpParser\Node;
class ElseIf_ extends Node\Stmt
{
    /** @var Node\Expr Condition */
    public $cond;
    /** @var Node\Stmt[] Statements */
    public $stmts;
    /**
     * Constructs an elseif node.
     *
     * @param Node\Expr $cond Condition
     * @param Node\Stmt[] $stmts Statements
     * @param array $attributes Additional attributes
     */
    public function __construct(Node\Expr $cond, array $stmts = [], array $attributes = [])
    {
        $this->attributes = $attributes;
        $this->cond = $cond;
        $this->stmts = $stmts;
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['cond', 'stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Stmt_ElseIf';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Name;

class Relative extends \PhabelVendor\PhpParser\Node\Name
{
    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() : bool
    {
        return \false;
    }
    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() : bool
    {
        return \false;
    }
    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() : bool
    {
        return \false;
    }
    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() : bool
    {
        return \true;
    }
    /**
     *
     */
    public function toCodeString() : string
    {
        return 'namespace\\' . $this->toString();
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Name_Relative';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node\Name;

class FullyQualified extends \PhabelVendor\PhpParser\Node\Name
{
    /**
     * Checks whether the name is unqualified. (E.g. Name)
     *
     * @return bool Whether the name is unqualified
     */
    public function isUnqualified() : bool
    {
        return \false;
    }
    /**
     * Checks whether the name is qualified. (E.g. Name\Name)
     *
     * @return bool Whether the name is qualified
     */
    public function isQualified() : bool
    {
        return \false;
    }
    /**
     * Checks whether the name is fully qualified. (E.g. \Name)
     *
     * @return bool Whether the name is fully qualified
     */
    public function isFullyQualified() : bool
    {
        return \true;
    }
    /**
     * Checks whether the name is explicitly relative to the current namespace. (E.g. namespace\Name)
     *
     * @return bool Whether the name is relative
     */
    public function isRelative() : bool
    {
        return \false;
    }
    /**
     *
     */
    public function toCodeString() : string
    {
        return '\\' . $this->toString();
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'Name_FullyQualified';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

/**
 * Represents a name that is written in source code with a leading dollar,
 * but is not a proper variable. The leading dollar is not stored as part of the name.
 *
 * Examples: Names in property declarations are formatted as variables. Names in static property
 * lookups are also formatted as variables.
 */
class VarLikeIdentifier extends Identifier
{
    /**
     *
     */
    public function getType() : string
    {
        return 'VarLikeIdentifier';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Node;

abstract class Scalar extends Expr
{
}
<?php

namespace PhabelVendor\PhpParser;

use function array_merge;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Scalar;
/**
 * Evaluates constant expressions.
 *
 * This evaluator is able to evaluate all constant expressions (as defined by PHP), which can be
 * evaluated without further context. If a subexpression is not of this type, a user-provided
 * fallback evaluator is invoked. To support all constant expressions that are also supported by
 * PHP (and not already handled by this class), the fallback evaluator must be able to handle the
 * following node types:
 *
 *  * All Scalar\MagicConst\* nodes.
 *  * Expr\ConstFetch nodes. Only null/false/true are already handled by this class.
 *  * Expr\ClassConstFetch nodes.
 *
 * The fallback evaluator should throw ConstExprEvaluationException for nodes it cannot evaluate.
 *
 * The evaluation is dependent on runtime configuration in two respects: Firstly, floating
 * point to string conversions are affected by the precision ini setting. Secondly, they are also
 * affected by the LC_NUMERIC locale.
 */
class ConstExprEvaluator
{
    private $fallbackEvaluator;
    /**
    * Create a constant expression evaluator.
    *
    * The provided fallback evaluator is invoked whenever a subexpression cannot be evaluated. See
    class doc comment for more information.
    *
    * @param (callable | null) $fallbackEvaluator To call if subexpression cannot be evaluated
    */
    public function __construct(callable $fallbackEvaluator = null)
    {
        $this->fallbackEvaluator = $fallbackEvaluator ?? function (Expr $expr) {
            throw new ConstExprEvaluationException("Expression of type {$expr->getType()} cannot be evaluated");
        };
    }
    /**
    * Silently evaluates a constant expression into a PHP value.
    *
    * Thrown Errors, warnings or notices will be converted into a ConstExprEvaluationException.
    The original source of the exception is available through getPrevious().
    *
    * If some part of the expression cannot be evaluated, the fallback evaluator passed to the
    constructor will be invoked. By default, if no fallback is provided, an exception of type
    ConstExprEvaluationException is thrown.
    *
    * See class doc comment for caveats and limitations.
    *
    * @param Expr $expr Constant expression to evaluate
    * @return mixed Result of evaluation
    *
    * @throws ConstExprEvaluationException if the expression cannot be evaluated or an error occurred
    */
    public function evaluateSilently(Expr $expr)
    {
        \set_error_handler(function ($num, $str, $file, $line) {
            throw new \ErrorException($str, 0, $num, $file, $line);
        });
        try {
            return $this->evaluate($expr);
        } catch (\Throwable $e) {
            if (!$e instanceof ConstExprEvaluationException) {
                $e = new ConstExprEvaluationException("An error occurred during constant expression evaluation", 0, $e);
            }
            throw $e;
        } finally {
            \restore_error_handler();
        }
    }
    /**
    * Directly evaluates a constant expression into a PHP value.
    *
    * May generate Error exceptions, warnings or notices. Use evaluateSilently() to convert these
    into a ConstExprEvaluationException.
    *
    * If some part of the expression cannot be evaluated, the fallback evaluator passed to the
    constructor will be invoked. By default, if no fallback is provided, an exception of type
    ConstExprEvaluationException is thrown.
    *
    * See class doc comment for caveats and limitations.
    *
    * @param Expr $expr Constant expression to evaluate
    * @return mixed Result of evaluation
    *
    * @throws ConstExprEvaluationException if the expression cannot be evaluated
    */
    public function evaluateDirectly(Expr $expr)
    {
        return $this->evaluate($expr);
    }
    /**
     *
     */
    private function evaluate(Expr $expr)
    {
        if ($expr instanceof Scalar\LNumber || $expr instanceof Scalar\DNumber || $expr instanceof Scalar\String_) {
            return $expr->value;
        }
        if ($expr instanceof Expr\Array_) {
            return $this->evaluateArray($expr);
        }
        // Unary operators
        if ($expr instanceof Expr\UnaryPlus) {
            return +$this->evaluate($expr->expr);
        }
        if ($expr instanceof Expr\UnaryMinus) {
            return -$this->evaluate($expr->expr);
        }
        if ($expr instanceof Expr\BooleanNot) {
            return !$this->evaluate($expr->expr);
        }
        if ($expr instanceof Expr\BitwiseNot) {
            return ~$this->evaluate($expr->expr);
        }
        if ($expr instanceof Expr\BinaryOp) {
            return $this->evaluateBinaryOp($expr);
        }
        if ($expr instanceof Expr\Ternary) {
            return $this->evaluateTernary($expr);
        }
        if ($expr instanceof Expr\ArrayDimFetch && null !== $expr->dim) {
            return $this->evaluate($expr->var)[$this->evaluate($expr->dim)];
        }
        if ($expr instanceof Expr\ConstFetch) {
            return $this->evaluateConstFetch($expr);
        }
        return ($this->fallbackEvaluator)($expr);
    }
    /**
     *
     */
    private function evaluateArray(Expr\Array_ $expr)
    {
        $array = [];
        foreach ($expr->items as $item) {
            if (null !== $item->key) {
                $array[$this->evaluate($item->key)] = $this->evaluate($item->value);
            } elseif ($item->unpack) {
                $array = array_merge($array, $this->evaluate($item->value));
            } else {
                $array[] = $this->evaluate($item->value);
            }
        }
        return $array;
    }
    /**
     *
     */
    private function evaluateTernary(Expr\Ternary $expr)
    {
        if (null === $expr->if) {
            return $this->evaluate($expr->cond) ?: $this->evaluate($expr->else);
        }
        return $this->evaluate($expr->cond) ? $this->evaluate($expr->if) : $this->evaluate($expr->else);
    }
    /**
     *
     */
    private function evaluateBinaryOp(Expr\BinaryOp $expr)
    {
        if ($expr instanceof Expr\BinaryOp\Coalesce && $expr->left instanceof Expr\ArrayDimFetch) {
            // This needs to be special cased to respect BP_VAR_IS fetch semantics
            return $this->evaluate($expr->left->var)[$this->evaluate($expr->left->dim)] ?? $this->evaluate($expr->right);
        }
        // The evaluate() calls are repeated in each branch, because some of the operators are
        // short-circuiting and evaluating the RHS in advance may be illegal in that case
        $l = $expr->left;
        $r = $expr->right;
        switch ($expr->getOperatorSigil()) {
            case '&':
                return $this->evaluate($l) & $this->evaluate($r);
            case '|':
                return $this->evaluate($l) | $this->evaluate($r);
            case '^':
                return $this->evaluate($l) ^ $this->evaluate($r);
            case '&&':
                return $this->evaluate($l) && $this->evaluate($r);
            case '||':
                return $this->evaluate($l) || $this->evaluate($r);
            case '??':
                return $this->evaluate($l) ?? $this->evaluate($r);
            case '.':
                return $this->evaluate($l) . $this->evaluate($r);
            case '/':
                return $this->evaluate($l) / $this->evaluate($r);
            case '==':
                return $this->evaluate($l) == $this->evaluate($r);
            case '>':
                return $this->evaluate($l) > $this->evaluate($r);
            case '>=':
                return $this->evaluate($l) >= $this->evaluate($r);
            case '===':
                return $this->evaluate($l) === $this->evaluate($r);
            case 'and':
                return $this->evaluate($l) and $this->evaluate($r);
            case 'or':
                return $this->evaluate($l) or $this->evaluate($r);
            case 'xor':
                return $this->evaluate($l) xor $this->evaluate($r);
            case '-':
                return $this->evaluate($l) - $this->evaluate($r);
            case '%':
                return $this->evaluate($l) % $this->evaluate($r);
            case '*':
                return $this->evaluate($l) * $this->evaluate($r);
            case '!=':
                return $this->evaluate($l) != $this->evaluate($r);
            case '!==':
                return $this->evaluate($l) !== $this->evaluate($r);
            case '+':
                return $this->evaluate($l) + $this->evaluate($r);
            case '**':
                return $this->evaluate($l) ** $this->evaluate($r);
            case '<<':
                return $this->evaluate($l) << $this->evaluate($r);
            case '>>':
                return $this->evaluate($l) >> $this->evaluate($r);
            case '<':
                return $this->evaluate($l) < $this->evaluate($r);
            case '<=':
                return $this->evaluate($l) <= $this->evaluate($r);
            case '<=>':
                return $this->evaluate($l) <=> $this->evaluate($r);
        }
        throw new \Exception('Should not happen');
    }
    /**
     *
     */
    private function evaluateConstFetch(Expr\ConstFetch $expr)
    {
        $name = $expr->name->toLowerString();
        switch ($name) {
            case 'null':
                return null;
            case 'false':
                return \false;
            case 'true':
                return \true;
        }
        return ($this->fallbackEvaluator)($expr);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\ErrorHandler;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\ErrorHandler;
/**
 * Error handler that collects all errors into an array.
 *
 * This allows graceful handling of errors.
 */
class Collecting implements ErrorHandler
{
    /** @var Error[] Collected errors */
    private $errors = [];
    /**
     *
     */
    public function handleError(Error $error)
    {
        $this->errors[] = $error;
    }
    /**
     * Get collected errors.
     *
     * @return Error[]
     */
    public function getErrors() : array
    {
        return $this->errors;
    }
    /**
     * Check whether there are any errors.
     *
     * @return bool
     */
    public function hasErrors() : bool
    {
        return !empty($this->errors);
    }
    /**
     * Reset/clear collected errors.
     */
    public function clearErrors()
    {
        $this->errors = [];
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\ErrorHandler;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\ErrorHandler;
/**
 * Error handler that handles all errors by throwing them.
 *
 * This is the default strategy used by all components.
 */
class Throwing implements ErrorHandler
{
    /**
     *
     */
    public function handleError(Error $error)
    {
        throw $error;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

interface NodeVisitor
{
    /**
    * Called once before traversal.
    *
    * Return value semantics:
    null:      $nodes stays as-is
    otherwise: $nodes is set to the return value
    *
    * @param Node[] $nodes Array of nodes
    *
    * @return (null | Node[]) Array of nodes
    */
    public function beforeTraverse(array $nodes);
    /**
    * Called when entering a node.
    *
    * Return value semantics:
    null
    => $node stays as-is
    NodeTraverser::DONT_TRAVERSE_CHILDREN
    => Children of $node are not traversed. $node stays as-is
    NodeTraverser::STOP_TRAVERSAL
    => Traversal is aborted. $node stays as-is
    otherwise
    => $node is set to the return value
    *
    * @param Node $node Node
    *
    * @return (null | int | Node) Replacement node (or special return value)
    */
    public function enterNode(Node $node);
    /**
    * Called when leaving a node.
    *
    * Return value semantics:
    null
    => $node stays as-is
    NodeTraverser::REMOVE_NODE
    => $node is removed from the parent array
    NodeTraverser::STOP_TRAVERSAL
    => Traversal is aborted. $node stays as-is
    array (of Nodes)
    => The return value is merged into the parent array (at the position of the $node)
    otherwise
    => $node is set to the return value
    *
    * @param Node $node Node
    *
    * @return (null | int | Node | Node[]) Replacement node (or special return value)
    */
    public function leaveNode(Node $node);
    /**
    * Called once after traversal.
    *
    * Return value semantics:
    null:      $nodes stays as-is
    otherwise: $nodes is set to the return value
    *
    * @param Node[] $nodes Array of nodes
    *
    * @return (null | Node[]) Array of nodes
    */
    public function afterTraverse(array $nodes);
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

use PhabelVendor\PhpParser\Parser\Tokens;
class Lexer
{
    protected $code;
    protected $tokens;
    protected $pos;
    protected $line;
    protected $filePos;
    protected $prevCloseTagHasNewline;
    protected $tokenMap;
    protected $dropTokens;
    protected $identifierTokens;
    private $attributeStartLineUsed;
    private $attributeEndLineUsed;
    private $attributeStartTokenPosUsed;
    private $attributeEndTokenPosUsed;
    private $attributeStartFilePosUsed;
    private $attributeEndFilePosUsed;
    private $attributeCommentsUsed;
    /**
    * Creates a Lexer.
    *
    * @param array $options Options array. Currently only the 'usedAttributes' option is supported,
    which is an array of attributes to add to the AST nodes. Possible
    attributes are: 'comments', 'startLine', 'endLine', 'startTokenPos',
    'endTokenPos', 'startFilePos', 'endFilePos'. The option defaults to the
    first three. For more info see getNextToken() docs.
    */
    public function __construct(array $options = [])
    {
        // Create Map from internal tokens to PhpParser tokens.
        $this->defineCompatibilityTokens();
        $this->tokenMap = $this->createTokenMap();
        $this->identifierTokens = $this->createIdentifierTokenMap();
        // map of tokens to drop while lexing (the map is only used for isset lookup,
        // that's why the value is simply set to 1; the value is never actually used.)
        $this->dropTokens = \array_fill_keys([\T_WHITESPACE, \T_OPEN_TAG, \T_COMMENT, \T_DOC_COMMENT, \T_BAD_CHARACTER], 1);
        $defaultAttributes = ['comments', 'startLine', 'endLine'];
        $usedAttributes = \array_fill_keys($options['usedAttributes'] ?? $defaultAttributes, \true);
        // Create individual boolean properties to make these checks faster.
        $this->attributeStartLineUsed = isset($usedAttributes['startLine']);
        $this->attributeEndLineUsed = isset($usedAttributes['endLine']);
        $this->attributeStartTokenPosUsed = isset($usedAttributes['startTokenPos']);
        $this->attributeEndTokenPosUsed = isset($usedAttributes['endTokenPos']);
        $this->attributeStartFilePosUsed = isset($usedAttributes['startFilePos']);
        $this->attributeEndFilePosUsed = isset($usedAttributes['endFilePos']);
        $this->attributeCommentsUsed = isset($usedAttributes['comments']);
    }
    /**
    * Initializes the lexer for lexing the provided source code.
    *
    * This function does not throw if lexing errors occur. Instead, errors may be retrieved using
    the getErrors() method.
    *
    * @param string $code The source code to lex
    * @param (ErrorHandler | null) $errorHandler Error handler to use for lexing errors. Defaults to
    ErrorHandler\Throwing
    */
    public function startLexing(string $code, ErrorHandler $errorHandler = null)
    {
        if (null === $errorHandler) {
            $errorHandler = new ErrorHandler\Throwing();
        }
        $this->code = $code;
        // keep the code around for __halt_compiler() handling
        $this->pos = -1;
        $this->line = 1;
        $this->filePos = 0;
        // If inline HTML occurs without preceding code, treat it as if it had a leading newline.
        // This ensures proper composability, because having a newline is the "safe" assumption.
        $this->prevCloseTagHasNewline = \true;
        $scream = \ini_set('xdebug.scream', '0');
        $this->tokens = @\token_get_all($code);
        $this->postprocessTokens($errorHandler);
        if (\false !== $scream) {
            \ini_set('xdebug.scream', $scream);
        }
    }
    /**
     *
     */
    private function handleInvalidCharacterRange($start, $end, $line, ErrorHandler $errorHandler)
    {
        $tokens = [];
        for ($i = $start; $i < $end; $i++) {
            $chr = $this->code[$i];
            if ($chr === "\x00") {
                // PHP cuts error message after null byte, so need special case
                $errorMsg = 'Unexpected null byte';
            } else {
                $errorMsg = \sprintf('Unexpected character "%s" (ASCII %d)', $chr, \ord($chr));
            }
            $tokens[] = [\T_BAD_CHARACTER, $chr, $line];
            $errorHandler->handleError(new Error($errorMsg, ['startLine' => $line, 'endLine' => $line, 'startFilePos' => $i, 'endFilePos' => $i]));
        }
        return $tokens;
    }
    /**
     * Check whether comment token is unterminated.
     *
     * @return bool
     */
    private function isUnterminatedComment($token) : bool
    {
        return ($token[0] === \T_COMMENT || $token[0] === \T_DOC_COMMENT) && \Phabel\Target\Php80\Polyfill::substr($token[1], 0, 2) === '/*' && \Phabel\Target\Php80\Polyfill::substr($token[1], -2) !== '*/';
    }
    /**
     *
     */
    protected function postprocessTokens(ErrorHandler $errorHandler)
    {
        // PHP's error handling for token_get_all() is rather bad, so if we want detailed
        // error information we need to compute it ourselves. Invalid character errors are
        // detected by finding "gaps" in the token array. Unterminated comments are detected
        // by checking if a trailing comment has a "*/" at the end.
        //
        // Additionally, we perform a number of canonicalizations here:
        //  * Use the PHP 8.0 comment format, which does not include trailing whitespace anymore.
        //  * Use PHP 8.0 T_NAME_* tokens.
        //  * Use PHP 8.1 T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG and
        //    T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG tokens used to disambiguate intersection types.
        $filePos = 0;
        $line = 1;
        $numTokens = \count($this->tokens);
        for ($i = 0; $i < $numTokens; $i++) {
            $token = $this->tokens[$i];
            // Since PHP 7.4 invalid characters are represented by a T_BAD_CHARACTER token.
            // In this case we only need to emit an error.
            if ($token[0] === \T_BAD_CHARACTER) {
                $this->handleInvalidCharacterRange($filePos, $filePos + 1, $line, $errorHandler);
            }
            if ($token[0] === \T_COMMENT && \Phabel\Target\Php80\Polyfill::substr($token[1], 0, 2) !== '/*' && \preg_match('/(\\r\\n|\\n|\\r)$/D', $token[1], $matches)) {
                $trailingNewline = $matches[0];
                $token[1] = \Phabel\Target\Php80\Polyfill::substr($token[1], 0, -\strlen($trailingNewline));
                $this->tokens[$i] = $token;
                if (isset($this->tokens[$i + 1]) && $this->tokens[$i + 1][0] === \T_WHITESPACE) {
                    // Move trailing newline into following T_WHITESPACE token, if it already exists.
                    $this->tokens[$i + 1][1] = $trailingNewline . $this->tokens[$i + 1][1];
                    $this->tokens[$i + 1][2]--;
                } else {
                    // Otherwise, we need to create a new T_WHITESPACE token.
                    \array_splice($this->tokens, $i + 1, 0, [[\T_WHITESPACE, $trailingNewline, $line]]);
                    $numTokens++;
                }
            }
            // Emulate PHP 8 T_NAME_* tokens, by combining sequences of T_NS_SEPARATOR and T_STRING
            // into a single token.
            if (\is_array($token) && ($token[0] === \T_NS_SEPARATOR || isset($this->identifierTokens[$token[0]]))) {
                $lastWasSeparator = $token[0] === \T_NS_SEPARATOR;
                $text = $token[1];
                for ($j = $i + 1; isset($this->tokens[$j]); $j++) {
                    if ($lastWasSeparator) {
                        if (!isset($this->identifierTokens[$this->tokens[$j][0]])) {
                            break;
                        }
                        $lastWasSeparator = \false;
                    } else {
                        if ($this->tokens[$j][0] !== \T_NS_SEPARATOR) {
                            break;
                        }
                        $lastWasSeparator = \true;
                    }
                    $text .= $this->tokens[$j][1];
                }
                if ($lastWasSeparator) {
                    // Trailing separator is not part of the name.
                    $j--;
                    $text = \Phabel\Target\Php80\Polyfill::substr($text, 0, -1);
                }
                if ($j > $i + 1) {
                    if ($token[0] === \T_NS_SEPARATOR) {
                        $type = \T_NAME_FULLY_QUALIFIED;
                    } else {
                        if ($token[0] === \T_NAMESPACE) {
                            $type = \T_NAME_RELATIVE;
                        } else {
                            $type = \T_NAME_QUALIFIED;
                        }
                    }
                    $token = [$type, $text, $line];
                    \array_splice($this->tokens, $i, $j - $i, [$token]);
                    $numTokens -= $j - $i - 1;
                }
            }
            if ($token === '&') {
                $next = $i + 1;
                while (isset($this->tokens[$next]) && $this->tokens[$next][0] === \T_WHITESPACE) {
                    $next++;
                }
                $followedByVarOrVarArg = isset($this->tokens[$next]) && ($this->tokens[$next][0] === \T_VARIABLE || $this->tokens[$next][0] === \T_ELLIPSIS);
                $this->tokens[$i] = $token = [$followedByVarOrVarArg ? \T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG : \T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG, '&', $line];
            }
            $tokenValue = \is_string($token) ? $token : $token[1];
            $tokenLen = \strlen($tokenValue);
            if (\Phabel\Target\Php80\Polyfill::substr($this->code, $filePos, $tokenLen) !== $tokenValue) {
                // Something is missing, must be an invalid character
                $nextFilePos = \strpos($this->code, $tokenValue, $filePos);
                $badCharTokens = $this->handleInvalidCharacterRange($filePos, $nextFilePos, $line, $errorHandler);
                $filePos = (int) $nextFilePos;
                \array_splice($this->tokens, $i, 0, $badCharTokens);
                $numTokens += \count($badCharTokens);
                $i += \count($badCharTokens);
            }
            $filePos += $tokenLen;
            $line += \Phabel\Target\Php80\Polyfill::substr_count($tokenValue, "\n");
        }
        if ($filePos !== \strlen($this->code)) {
            if (\Phabel\Target\Php80\Polyfill::substr($this->code, $filePos, 2) === '/*') {
                // Unlike PHP, HHVM will drop unterminated comments entirely
                $comment = \Phabel\Target\Php80\Polyfill::substr($this->code, $filePos);
                $errorHandler->handleError(new Error('Unterminated comment', ['startLine' => $line, 'endLine' => $line + \Phabel\Target\Php80\Polyfill::substr_count($comment, "\n"), 'startFilePos' => $filePos, 'endFilePos' => $filePos + \strlen($comment)]));
                // Emulate the PHP behavior
                $isDocComment = isset($comment[3]) && $comment[3] === '*';
                $this->tokens[] = [$isDocComment ? \T_DOC_COMMENT : \T_COMMENT, $comment, $line];
            } else {
                // Invalid characters at the end of the input
                $badCharTokens = $this->handleInvalidCharacterRange($filePos, \strlen($this->code), $line, $errorHandler);
                $this->tokens = \array_merge($this->tokens, $badCharTokens);
            }
            return;
        }
        if (\count($this->tokens) > 0) {
            // Check for unterminated comment
            $lastToken = $this->tokens[\count($this->tokens) - 1];
            if ($this->isUnterminatedComment($lastToken)) {
                $errorHandler->handleError(new Error('Unterminated comment', ['startLine' => $line - \Phabel\Target\Php80\Polyfill::substr_count($lastToken[1], "\n"), 'endLine' => $line, 'startFilePos' => $filePos - \strlen($lastToken[1]), 'endFilePos' => $filePos]));
            }
        }
    }
    /**
    * Fetches the next token.
    *
    * The available attributes are determined by the 'usedAttributes' option, which can
    be specified in the constructor. The following attributes are supported:
    *
    * * 'comments'      => Array of PhpParser\Comment or PhpParser\Comment\Doc instances,
    representing all comments that occurred between the previous
    non-discarded token and the current one.
    'startLine'     => Line in which the node starts.
    'endLine'       => Line in which the node ends.
    'startTokenPos' => Offset into the token array of the first token in the node.
    'endTokenPos'   => Offset into the token array of the last token in the node.
    'startFilePos'  => Offset into the code string of the first character that is part of the node.
    'endFilePos'    => Offset into the code string of the last character that is part of the node.
    *
    * @param mixed $value Variable to store token content in
    * @param mixed $startAttributes Variable to store start attributes in
    * @param mixed $endAttributes Variable to store end attributes in
    *
    * @return int Token id
    */
    public function getNextToken(&$value = null, &$startAttributes = null, &$endAttributes = null) : int
    {
        $startAttributes = [];
        $endAttributes = [];
        while (1) {
            if (isset($this->tokens[++$this->pos])) {
                $token = $this->tokens[$this->pos];
            } else {
                // EOF token with ID 0
                $token = "\x00";
            }
            if ($this->attributeStartLineUsed) {
                $startAttributes['startLine'] = $this->line;
            }
            if ($this->attributeStartTokenPosUsed) {
                $startAttributes['startTokenPos'] = $this->pos;
            }
            if ($this->attributeStartFilePosUsed) {
                $startAttributes['startFilePos'] = $this->filePos;
            }
            if (\is_string($token)) {
                $value = $token;
                if (isset($token[1])) {
                    // bug in token_get_all
                    $this->filePos += 2;
                    $id = \ord('"');
                } else {
                    $this->filePos += 1;
                    $id = \ord($token);
                }
            } elseif (!isset($this->dropTokens[$token[0]])) {
                $value = $token[1];
                $id = $this->tokenMap[$token[0]];
                if (\T_CLOSE_TAG === $token[0]) {
                    $this->prevCloseTagHasNewline = \false !== \strpos($token[1], "\n") || \false !== \strpos($token[1], "\r");
                } elseif (\T_INLINE_HTML === $token[0]) {
                    $startAttributes['hasLeadingNewline'] = $this->prevCloseTagHasNewline;
                }
                $this->line += \Phabel\Target\Php80\Polyfill::substr_count($value, "\n");
                $this->filePos += \strlen($value);
            } else {
                $origLine = $this->line;
                $origFilePos = $this->filePos;
                $this->line += \Phabel\Target\Php80\Polyfill::substr_count($token[1], "\n");
                $this->filePos += \strlen($token[1]);
                if (\T_COMMENT === $token[0] || \T_DOC_COMMENT === $token[0]) {
                    if ($this->attributeCommentsUsed) {
                        $comment = \T_DOC_COMMENT === $token[0] ? new Comment\Doc($token[1], $origLine, $origFilePos, $this->pos, $this->line, $this->filePos - 1, $this->pos) : new Comment($token[1], $origLine, $origFilePos, $this->pos, $this->line, $this->filePos - 1, $this->pos);
                        $startAttributes['comments'][] = $comment;
                    }
                }
                continue;
            }
            if ($this->attributeEndLineUsed) {
                $endAttributes['endLine'] = $this->line;
            }
            if ($this->attributeEndTokenPosUsed) {
                $endAttributes['endTokenPos'] = $this->pos;
            }
            if ($this->attributeEndFilePosUsed) {
                $endAttributes['endFilePos'] = $this->filePos - 1;
            }
            return $id;
        }
        throw new \RuntimeException('Reached end of lexer loop');
    }
    /**
    * Returns the token array for current code.
    *
    * The token array is in the same format as provided by the
    token_get_all() function and does not discard tokens (i.e.
    whitespace and comments are included). The token position
    attributes are against this token array.
    *
    * @return array Array of tokens in token_get_all() format
    */
    public function getTokens() : array
    {
        return $this->tokens;
    }
    /**
     * Handles __halt_compiler() by returning the text after it.
     *
     * @return string Remaining text
     */
    public function handleHaltCompiler() : string
    {
        // text after T_HALT_COMPILER, still including ();
        $textAfter = \Phabel\Target\Php80\Polyfill::substr($this->code, $this->filePos);
        // ensure that it is followed by ();
        // this simplifies the situation, by not allowing any comments
        // in between of the tokens.
        if (!\preg_match('~^\\s*\\(\\s*\\)\\s*(?:;|\\?>\\r?\\n?)~', $textAfter, $matches)) {
            throw new Error('__HALT_COMPILER must be followed by "();"');
        }
        // prevent the lexer from returning any further tokens
        $this->pos = \count($this->tokens);
        // return with (); removed
        return \Phabel\Target\Php80\Polyfill::substr($textAfter, \strlen($matches[0]));
    }
    /**
     *
     */
    private function defineCompatibilityTokens()
    {
        static $compatTokensDefined = \false;
        if ($compatTokensDefined) {
            return;
        }
        $compatTokens = [
            // PHP 7.4
            'T_BAD_CHARACTER',
            'T_FN',
            'T_COALESCE_EQUAL',
            // PHP 8.0
            'T_NAME_QUALIFIED',
            'T_NAME_FULLY_QUALIFIED',
            'T_NAME_RELATIVE',
            'T_MATCH',
            'T_NULLSAFE_OBJECT_OPERATOR',
            'T_ATTRIBUTE',
            // PHP 8.1
            'T_ENUM',
            'T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG',
            'T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG',
            'T_READONLY',
        ];
        // PHP-Parser might be used together with another library that also emulates some or all
        // of these tokens. Perform a sanity-check that all already defined tokens have been
        // assigned a unique ID.
        $usedTokenIds = [];
        foreach ($compatTokens as $token) {
            if (\defined($token)) {
                $tokenId = \constant($token);
                $clashingToken = $usedTokenIds[$tokenId] ?? null;
                if ($clashingToken !== null) {
                    throw new \Error(\sprintf('Token %s has same ID as token %s, you may be using a library with broken token emulation', $token, $clashingToken));
                }
                $usedTokenIds[$tokenId] = $token;
            }
        }
        // Now define any tokens that have not yet been emulated. Try to assign IDs from -1
        // downwards, but skip any IDs that may already be in use.
        $newTokenId = -1;
        foreach ($compatTokens as $token) {
            if (!\defined($token)) {
                while (isset($usedTokenIds[$newTokenId])) {
                    $newTokenId--;
                }
                \define($token, $newTokenId);
                $newTokenId--;
            }
        }
        $compatTokensDefined = \true;
    }
    /**
    * Creates the token map.
    *
    * The token map maps the PHP internal token identifiers
    to the identifiers used by the Parser. Additionally it
    maps T_OPEN_TAG_WITH_ECHO to T_ECHO and T_CLOSE_TAG to ';'.
    *
    * @return array The token map
    */
    protected function createTokenMap() : array
    {
        $tokenMap = [];
        // 256 is the minimum possible token number, as everything below
        // it is an ASCII value
        for ($i = 256; $i < 1000; ++$i) {
            if (\T_DOUBLE_COLON === $i) {
                // T_DOUBLE_COLON is equivalent to T_PAAMAYIM_NEKUDOTAYIM
                $tokenMap[$i] = Tokens::T_PAAMAYIM_NEKUDOTAYIM;
            } elseif (\T_OPEN_TAG_WITH_ECHO === $i) {
                // T_OPEN_TAG_WITH_ECHO with dropped T_OPEN_TAG results in T_ECHO
                $tokenMap[$i] = Tokens::T_ECHO;
            } elseif (\T_CLOSE_TAG === $i) {
                // T_CLOSE_TAG is equivalent to ';'
                $tokenMap[$i] = \ord(';');
            } elseif ('UNKNOWN' !== ($name = \token_name($i))) {
                if ('T_HASHBANG' === $name) {
                    // HHVM uses a special token for #! hashbang lines
                    $tokenMap[$i] = Tokens::T_INLINE_HTML;
                } elseif (\defined($name = Tokens::class . '::' . $name)) {
                    // Other tokens can be mapped directly
                    $tokenMap[$i] = \constant($name);
                }
            }
        }
        // HHVM uses a special token for numbers that overflow to double
        if (\defined('T_ONUMBER')) {
            $tokenMap[\T_ONUMBER] = Tokens::T_DNUMBER;
        }
        // HHVM also has a separate token for the __COMPILER_HALT_OFFSET__ constant
        if (\defined('T_COMPILER_HALT_OFFSET')) {
            $tokenMap[\T_COMPILER_HALT_OFFSET] = Tokens::T_STRING;
        }
        // Assign tokens for which we define compatibility constants, as token_name() does not know them.
        $tokenMap[\T_FN] = Tokens::T_FN;
        $tokenMap[\T_COALESCE_EQUAL] = Tokens::T_COALESCE_EQUAL;
        $tokenMap[\T_NAME_QUALIFIED] = Tokens::T_NAME_QUALIFIED;
        $tokenMap[\T_NAME_FULLY_QUALIFIED] = Tokens::T_NAME_FULLY_QUALIFIED;
        $tokenMap[\T_NAME_RELATIVE] = Tokens::T_NAME_RELATIVE;
        $tokenMap[\T_MATCH] = Tokens::T_MATCH;
        $tokenMap[\T_NULLSAFE_OBJECT_OPERATOR] = Tokens::T_NULLSAFE_OBJECT_OPERATOR;
        $tokenMap[\T_ATTRIBUTE] = Tokens::T_ATTRIBUTE;
        $tokenMap[\T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG;
        $tokenMap[\T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG] = Tokens::T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG;
        $tokenMap[\T_ENUM] = Tokens::T_ENUM;
        $tokenMap[\T_READONLY] = Tokens::T_READONLY;
        return $tokenMap;
    }
    /**
     *
     */
    private function createIdentifierTokenMap() : array
    {
        // Based on semi_reserved production.
        return \array_fill_keys([\T_STRING, \T_STATIC, \T_ABSTRACT, \T_FINAL, \T_PRIVATE, \T_PROTECTED, \T_PUBLIC, \T_READONLY, \T_INCLUDE, \T_INCLUDE_ONCE, \T_EVAL, \T_REQUIRE, \T_REQUIRE_ONCE, \T_LOGICAL_OR, \T_LOGICAL_XOR, \T_LOGICAL_AND, \T_INSTANCEOF, \T_NEW, \T_CLONE, \T_EXIT, \T_IF, \T_ELSEIF, \T_ELSE, \T_ENDIF, \T_ECHO, \T_DO, \T_WHILE, \T_ENDWHILE, \T_FOR, \T_ENDFOR, \T_FOREACH, \T_ENDFOREACH, \T_DECLARE, \T_ENDDECLARE, \T_AS, \T_TRY, \T_CATCH, \T_FINALLY, \T_THROW, \T_USE, \T_INSTEADOF, \T_GLOBAL, \T_VAR, \T_UNSET, \T_ISSET, \T_EMPTY, \T_CONTINUE, \T_GOTO, \T_FUNCTION, \T_CONST, \T_RETURN, \T_PRINT, \T_YIELD, \T_LIST, \T_SWITCH, \T_ENDSWITCH, \T_CASE, \T_DEFAULT, \T_BREAK, \T_ARRAY, \T_CALLABLE, \T_EXTENDS, \T_IMPLEMENTS, \T_NAMESPACE, \T_TRAIT, \T_INTERFACE, \T_CLASS, \T_CLASS_C, \T_TRAIT_C, \T_FUNC_C, \T_METHOD_C, \T_LINE, \T_FILE, \T_DIR, \T_NS_C, \T_HALT_COMPILER, \T_FN, \T_MATCH], \true);
    }
}
<?php

namespace PhabelVendor\PhpParser\Parser;

/* GENERATED file based on grammar/tokens.y */
final class Tokens
{
    const YYERRTOK = 256;
    const T_THROW = 257;
    const T_INCLUDE = 258;
    const T_INCLUDE_ONCE = 259;
    const T_EVAL = 260;
    const T_REQUIRE = 261;
    const T_REQUIRE_ONCE = 262;
    const T_LOGICAL_OR = 263;
    const T_LOGICAL_XOR = 264;
    const T_LOGICAL_AND = 265;
    const T_PRINT = 266;
    const T_YIELD = 267;
    const T_DOUBLE_ARROW = 268;
    const T_YIELD_FROM = 269;
    const T_PLUS_EQUAL = 270;
    const T_MINUS_EQUAL = 271;
    const T_MUL_EQUAL = 272;
    const T_DIV_EQUAL = 273;
    const T_CONCAT_EQUAL = 274;
    const T_MOD_EQUAL = 275;
    const T_AND_EQUAL = 276;
    const T_OR_EQUAL = 277;
    const T_XOR_EQUAL = 278;
    const T_SL_EQUAL = 279;
    const T_SR_EQUAL = 280;
    const T_POW_EQUAL = 281;
    const T_COALESCE_EQUAL = 282;
    const T_COALESCE = 283;
    const T_BOOLEAN_OR = 284;
    const T_BOOLEAN_AND = 285;
    const T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG = 286;
    const T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG = 287;
    const T_IS_EQUAL = 288;
    const T_IS_NOT_EQUAL = 289;
    const T_IS_IDENTICAL = 290;
    const T_IS_NOT_IDENTICAL = 291;
    const T_SPACESHIP = 292;
    const T_IS_SMALLER_OR_EQUAL = 293;
    const T_IS_GREATER_OR_EQUAL = 294;
    const T_SL = 295;
    const T_SR = 296;
    const T_INSTANCEOF = 297;
    const T_INC = 298;
    const T_DEC = 299;
    const T_INT_CAST = 300;
    const T_DOUBLE_CAST = 301;
    const T_STRING_CAST = 302;
    const T_ARRAY_CAST = 303;
    const T_OBJECT_CAST = 304;
    const T_BOOL_CAST = 305;
    const T_UNSET_CAST = 306;
    const T_POW = 307;
    const T_NEW = 308;
    const T_CLONE = 309;
    const T_EXIT = 310;
    const T_IF = 311;
    const T_ELSEIF = 312;
    const T_ELSE = 313;
    const T_ENDIF = 314;
    const T_LNUMBER = 315;
    const T_DNUMBER = 316;
    const T_STRING = 317;
    const T_STRING_VARNAME = 318;
    const T_VARIABLE = 319;
    const T_NUM_STRING = 320;
    const T_INLINE_HTML = 321;
    const T_ENCAPSED_AND_WHITESPACE = 322;
    const T_CONSTANT_ENCAPSED_STRING = 323;
    const T_ECHO = 324;
    const T_DO = 325;
    const T_WHILE = 326;
    const T_ENDWHILE = 327;
    const T_FOR = 328;
    const T_ENDFOR = 329;
    const T_FOREACH = 330;
    const T_ENDFOREACH = 331;
    const T_DECLARE = 332;
    const T_ENDDECLARE = 333;
    const T_AS = 334;
    const T_SWITCH = 335;
    const T_MATCH = 336;
    const T_ENDSWITCH = 337;
    const T_CASE = 338;
    const T_DEFAULT = 339;
    const T_BREAK = 340;
    const T_CONTINUE = 341;
    const T_GOTO = 342;
    const T_FUNCTION = 343;
    const T_FN = 344;
    const T_CONST = 345;
    const T_RETURN = 346;
    const T_TRY = 347;
    const T_CATCH = 348;
    const T_FINALLY = 349;
    const T_USE = 350;
    const T_INSTEADOF = 351;
    const T_GLOBAL = 352;
    const T_STATIC = 353;
    const T_ABSTRACT = 354;
    const T_FINAL = 355;
    const T_PRIVATE = 356;
    const T_PROTECTED = 357;
    const T_PUBLIC = 358;
    const T_READONLY = 359;
    const T_VAR = 360;
    const T_UNSET = 361;
    const T_ISSET = 362;
    const T_EMPTY = 363;
    const T_HALT_COMPILER = 364;
    const T_CLASS = 365;
    const T_TRAIT = 366;
    const T_INTERFACE = 367;
    const T_ENUM = 368;
    const T_EXTENDS = 369;
    const T_IMPLEMENTS = 370;
    const T_OBJECT_OPERATOR = 371;
    const T_NULLSAFE_OBJECT_OPERATOR = 372;
    const T_LIST = 373;
    const T_ARRAY = 374;
    const T_CALLABLE = 375;
    const T_CLASS_C = 376;
    const T_TRAIT_C = 377;
    const T_METHOD_C = 378;
    const T_FUNC_C = 379;
    const T_LINE = 380;
    const T_FILE = 381;
    const T_START_HEREDOC = 382;
    const T_END_HEREDOC = 383;
    const T_DOLLAR_OPEN_CURLY_BRACES = 384;
    const T_CURLY_OPEN = 385;
    const T_PAAMAYIM_NEKUDOTAYIM = 386;
    const T_NAMESPACE = 387;
    const T_NS_C = 388;
    const T_DIR = 389;
    const T_NS_SEPARATOR = 390;
    const T_ELLIPSIS = 391;
    const T_NAME_FULLY_QUALIFIED = 392;
    const T_NAME_QUALIFIED = 393;
    const T_NAME_RELATIVE = 394;
    const T_ATTRIBUTE = 395;
}
<?php

namespace PhabelVendor\PhpParser\Parser;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Scalar;
use PhabelVendor\PhpParser\Node\Stmt;
/* This is an automatically GENERATED file, which should not be manually edited.
 * Instead edit one of the following:
 *  * the grammar files grammar/php5.y or grammar/php7.y
 *  * the skeleton file grammar/parser.template
 *  * the preprocessing script grammar/rebuildParsers.php
 */
class Php7 extends \PhabelVendor\PhpParser\ParserAbstract
{
    protected $tokenToSymbolMapSize = 396;
    protected $actionTableSize = 1196;
    protected $gotoTableSize = 545;
    protected $invalidSymbol = 168;
    protected $errorSymbol = 1;
    protected $defaultAction = -32766;
    protected $unexpectedTokenRule = 32767;
    protected $YY2TBLSTATE = 420;
    protected $numNonLeafStates = 710;
    protected $symbolToName = array("EOF", "error", "T_THROW", "T_INCLUDE", "T_INCLUDE_ONCE", "T_EVAL", "T_REQUIRE", "T_REQUIRE_ONCE", "','", "T_LOGICAL_OR", "T_LOGICAL_XOR", "T_LOGICAL_AND", "T_PRINT", "T_YIELD", "T_DOUBLE_ARROW", "T_YIELD_FROM", "'='", "T_PLUS_EQUAL", "T_MINUS_EQUAL", "T_MUL_EQUAL", "T_DIV_EQUAL", "T_CONCAT_EQUAL", "T_MOD_EQUAL", "T_AND_EQUAL", "T_OR_EQUAL", "T_XOR_EQUAL", "T_SL_EQUAL", "T_SR_EQUAL", "T_POW_EQUAL", "T_COALESCE_EQUAL", "'?'", "':'", "T_COALESCE", "T_BOOLEAN_OR", "T_BOOLEAN_AND", "'|'", "'^'", "T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG", "T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG", "T_IS_EQUAL", "T_IS_NOT_EQUAL", "T_IS_IDENTICAL", "T_IS_NOT_IDENTICAL", "T_SPACESHIP", "'<'", "T_IS_SMALLER_OR_EQUAL", "'>'", "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "'+'", "'-'", "'.'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_MATCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_FN", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_READONLY", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_ENUM", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_NULLSAFE_OBJECT_OPERATOR", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", "T_ATTRIBUTE", "';'", "']'", "'{'", "'}'", "'('", "')'", "'`'", "'\"'", "'\$'");
    protected $tokenToSymbol = array(0, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 56, 166, 168, 167, 55, 168, 168, 163, 164, 53, 50, 8, 51, 52, 54, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 31, 159, 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 70, 168, 160, 36, 168, 165, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 161, 35, 162, 58, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 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, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158);
    protected $action = array(132, 133, 134, 569, 135, 136, 0, 722, 723, 724, 137, 37, 834, 911, 835, 469, -32766, -32766, -32766, -32767, -32767, -32767, -32767, 101, 102, 103, 104, 105, 1068, 1069, 1070, 1067, 1066, 1065, 1071, 716, 715, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32767, -32767, -32767, -32767, -32767, 545, 546, -32766, -32766, 725, -32766, -32766, -32766, 998, 999, 806, 922, 447, 448, 449, 370, 371, 2, 267, 138, 396, 729, 730, 731, 732, 414, -32766, 420, -32766, -32766, -32766, -32766, -32766, 990, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 763, 570, 764, 765, 766, 767, 755, 756, 336, 337, 758, 759, 744, 745, 746, 748, 749, 750, 346, 790, 791, 792, 793, 794, 795, 751, 752, 571, 572, 784, 775, 773, 774, 787, 770, 771, 283, 420, 573, 574, 769, 575, 576, 577, 578, 579, 580, 598, -575, 470, 14, 798, 772, 581, 582, -575, 139, -32766, -32766, -32766, 132, 133, 134, 569, 135, 136, 1017, 722, 723, 724, 137, 37, 1060, -32766, -32766, -32766, 1303, 696, -32766, 1304, -32766, -32766, -32766, -32766, -32766, -32766, -32766, 1068, 1069, 1070, 1067, 1066, 1065, 1071, -32766, 716, 715, 372, 371, 1258, -32766, -32766, -32766, -572, 106, 107, 108, 414, 270, 891, -572, 240, 1193, 1192, 1194, 725, -32766, -32766, -32766, 1046, 109, -32766, -32766, -32766, -32766, 986, 985, 984, 987, 267, 138, 396, 729, 730, 731, 732, 12, -32766, 420, -32766, -32766, -32766, -32766, 998, 999, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 763, 570, 764, 765, 766, 767, 755, 756, 336, 337, 758, 759, 744, 745, 746, 748, 749, 750, 346, 790, 791, 792, 793, 794, 795, 751, 752, 571, 572, 784, 775, 773, 774, 787, 770, 771, 881, 321, 573, 574, 769, 575, 576, 577, 578, 579, 580, -32766, 82, 83, 84, -575, 772, 581, 582, -575, 148, 747, 717, 718, 719, 720, 721, 1278, 722, 723, 724, 760, 761, 36, 1277, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 996, 270, 150, -32766, -32766, -32766, 455, 456, 81, 34, -264, -572, 1016, 109, 320, -572, 893, 725, 682, 803, 128, 998, 999, 592, -32766, 1044, -32766, -32766, -32766, 809, 151, 726, 727, 728, 729, 730, 731, 732, -88, 1198, 796, 278, -526, 283, -32766, -32766, -32766, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743, 763, 786, 764, 765, 766, 767, 755, 756, 757, 785, 758, 759, 744, 745, 746, 748, 749, 750, 789, 790, 791, 792, 793, 794, 795, 751, 752, 753, 754, 784, 775, 773, 774, 787, 770, 771, 144, 804, 762, 768, 769, 776, 777, 779, 778, 780, 781, -314, -526, -526, -193, -192, 772, 783, 782, 49, 50, 51, 500, 52, 53, 239, 807, -526, -86, 54, 55, -111, 56, 996, 253, -32766, -111, 800, -111, -526, 541, -532, -352, 300, -352, 304, -111, -111, -111, -111, -111, -111, -111, -111, 998, 999, 998, 999, 153, -32766, -32766, -32766, 1191, 807, 126, 306, 1293, 57, 58, 103, 104, 105, -111, 59, 1218, 60, 246, 247, 61, 62, 63, 64, 65, 66, 67, 68, -525, 27, 268, 69, 436, 501, -328, 808, -86, 1224, 1225, 502, 1189, 807, 1198, 1230, 293, 1222, 41, 24, 503, 74, 504, 953, 505, 320, 506, 802, 154, 507, 508, 279, 684, 280, 43, 44, 437, 367, 366, 891, 45, 509, 35, 249, -16, -566, 358, 332, 318, -566, 1198, 1193, 1192, 1194, -527, 510, 511, 512, 333, -524, 1274, 48, 716, 715, -525, -525, 334, 513, 514, 807, 1212, 1213, 1214, 1215, 1209, 1210, 292, 360, 284, -525, 285, -314, 1216, 1211, -193, -192, 1193, 1192, 1194, 293, 891, -525, 364, -531, 70, 807, 316, 317, 320, 31, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, -153, -153, -153, 638, 25, -527, -527, 687, 379, 881, -524, -524, 296, 297, 891, -153, 432, -153, 807, -153, -527, -153, 716, 715, 433, -524, 798, 363, -111, 1105, 1107, 365, -527, 434, 891, 140, 435, -524, 954, 127, -524, 320, -111, -111, 688, 813, 381, -529, 11, 834, 155, 835, 867, -111, -111, -111, -111, 47, 293, -32766, 881, 654, 655, 74, 689, 1191, 1045, 320, 708, 149, 399, 157, -32766, -32766, -32766, 32, -32766, -79, -32766, 123, -32766, 716, 715, -32766, 893, 891, 682, -153, -32766, -32766, -32766, 716, 715, 891, -32766, -32766, 124, 881, 129, 74, -32766, 411, 130, 320, -524, -524, 143, 141, -75, -32766, 158, -529, -529, 320, 27, 691, 159, 881, 160, -524, 161, 294, 295, 698, 368, 369, 807, -73, -32766, -72, 1222, -524, 373, 374, 1191, 893, -71, 682, -529, 73, -70, -32766, -32766, -32766, -69, -32766, -68, -32766, 125, -32766, 630, 631, -32766, -67, -66, -47, -51, -32766, -32766, -32766, -18, 147, 271, -32766, -32766, 277, 697, 700, 881, -32766, 411, 890, 893, 146, 682, 282, 881, 907, -32766, 281, 513, 514, 286, 1212, 1213, 1214, 1215, 1209, 1210, 326, 131, 145, 939, 287, 682, 1216, 1211, 109, 270, -32766, 798, 807, -32766, 662, 639, 1191, 657, 72, 675, 1075, 317, 320, -32766, -32766, -32766, 1305, -32766, 301, -32766, 628, -32766, 431, 543, -32766, -32766, 923, 555, 924, -32766, -32766, -32766, 1229, 549, -32766, -32766, -32766, -4, 891, -490, 1191, -32766, 411, 644, 893, 299, 682, -32766, -32766, -32766, -32766, -32766, 893, -32766, 682, -32766, 13, 1231, -32766, 452, 480, 645, 909, -32766, -32766, -32766, -32766, 658, -480, -32766, -32766, 0, 1191, 0, 0, -32766, 411, 0, 298, -32766, -32766, -32766, 305, -32766, -32766, -32766, 0, -32766, 0, 806, -32766, 0, 0, 0, 475, -32766, -32766, -32766, -32766, 0, 7, -32766, -32766, 16, 1191, 561, 596, -32766, 411, 1219, 891, -32766, -32766, -32766, 362, -32766, -32766, -32766, 818, -32766, -267, 881, -32766, 39, 293, 0, 0, -32766, -32766, -32766, 40, 705, 706, -32766, -32766, 872, 963, 940, 947, -32766, 411, 937, 948, 365, 870, 427, 891, 935, -32766, 1049, 291, 1244, 1052, 1053, -111, -111, 1050, 1051, 1057, -560, 1262, 1296, 633, 0, 826, -111, -111, -111, -111, 33, 315, -32766, 361, 683, 686, 690, 692, 1191, 693, 694, 695, 699, 685, 320, -32766, -32766, -32766, 9, -32766, 702, -32766, 868, -32766, 881, 1300, -32766, 893, 1302, 682, -4, -32766, -32766, -32766, 829, 828, 837, -32766, -32766, 916, -242, -242, -242, -32766, 411, 955, 365, 27, 836, 1301, 915, 917, -32766, 914, 1177, 900, 910, -111, -111, 807, 881, 898, 945, 1222, 946, 1299, 1256, 867, -111, -111, -111, -111, 1245, 1263, 1269, 1272, -241, -241, -241, -558, -532, -531, 365, -530, 1, 28, 29, 38, 42, 46, 71, 0, 75, -111, -111, 76, 77, 78, 79, 893, 80, 682, -242, 867, -111, -111, -111, -111, 142, 152, 156, 245, 322, 347, 514, 348, 1212, 1213, 1214, 1215, 1209, 1210, 349, 350, 351, 352, 353, 354, 1216, 1211, 355, 356, 357, 359, 428, 893, -265, 682, -241, -264, 72, 0, 18, 317, 320, 19, 20, 21, 23, 398, 471, 472, 479, 482, 483, 484, 485, 489, 490, 491, 498, 669, 1202, 1145, 1220, 1019, 1018, 1181, -269, -103, 17, 22, 26, 290, 397, 589, 593, 620, 674, 1149, 1197, 1146, 1275, 0, -494, 1162, 0, 1223);
    protected $actionCheck = array(2, 3, 4, 5, 6, 7, 0, 9, 10, 11, 12, 13, 106, 1, 108, 31, 9, 10, 11, 44, 45, 46, 47, 48, 49, 50, 51, 52, 116, 117, 118, 119, 120, 121, 122, 37, 38, 30, 116, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 117, 118, 9, 10, 57, 9, 10, 11, 137, 138, 155, 128, 129, 130, 131, 106, 107, 8, 71, 72, 73, 74, 75, 76, 77, 116, 30, 80, 32, 33, 34, 35, 36, 1, 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, 30, 80, 136, 137, 138, 139, 140, 141, 142, 143, 144, 51, 1, 161, 101, 80, 150, 151, 152, 8, 154, 9, 10, 11, 2, 3, 4, 5, 6, 7, 164, 9, 10, 11, 12, 13, 123, 9, 10, 11, 80, 161, 30, 83, 32, 33, 34, 35, 36, 37, 38, 116, 117, 118, 119, 120, 121, 122, 30, 37, 38, 106, 107, 1, 9, 10, 11, 1, 53, 54, 55, 116, 57, 1, 8, 14, 155, 156, 157, 57, 9, 10, 11, 162, 69, 30, 116, 32, 33, 119, 120, 121, 122, 71, 72, 73, 74, 75, 76, 77, 8, 30, 80, 32, 33, 34, 35, 137, 138, 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, 84, 70, 136, 137, 138, 139, 140, 141, 142, 143, 144, 9, 9, 10, 11, 160, 150, 151, 152, 164, 154, 2, 3, 4, 5, 6, 7, 1, 9, 10, 11, 12, 13, 30, 8, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 116, 57, 14, 9, 10, 11, 134, 135, 161, 8, 164, 160, 1, 69, 167, 164, 159, 57, 161, 80, 8, 137, 138, 1, 30, 1, 32, 33, 34, 1, 14, 71, 72, 73, 74, 75, 76, 77, 31, 1, 80, 30, 70, 30, 9, 10, 11, 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, 8, 156, 136, 137, 138, 139, 140, 141, 142, 143, 144, 8, 134, 135, 8, 8, 150, 151, 152, 2, 3, 4, 5, 6, 7, 97, 82, 149, 31, 12, 13, 101, 15, 116, 8, 116, 106, 80, 108, 161, 85, 163, 106, 113, 108, 8, 116, 117, 118, 119, 120, 121, 122, 123, 137, 138, 137, 138, 14, 9, 10, 11, 80, 82, 14, 8, 85, 50, 51, 50, 51, 52, 128, 56, 1, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 70, 70, 71, 72, 73, 74, 162, 159, 97, 78, 79, 80, 116, 82, 1, 146, 158, 86, 87, 88, 89, 163, 91, 31, 93, 167, 95, 156, 14, 98, 99, 35, 161, 37, 103, 104, 105, 106, 107, 1, 109, 110, 147, 148, 31, 160, 115, 116, 8, 164, 1, 155, 156, 157, 70, 124, 125, 126, 8, 70, 1, 70, 37, 38, 134, 135, 8, 136, 137, 82, 139, 140, 141, 142, 143, 144, 145, 8, 35, 149, 37, 164, 151, 152, 164, 164, 155, 156, 157, 158, 1, 161, 8, 163, 163, 82, 165, 166, 167, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 75, 76, 77, 75, 76, 134, 135, 31, 8, 84, 134, 135, 134, 135, 1, 90, 8, 92, 82, 94, 149, 96, 37, 38, 8, 149, 80, 149, 128, 59, 60, 106, 161, 8, 1, 161, 8, 161, 159, 161, 70, 167, 117, 118, 31, 8, 106, 70, 108, 106, 14, 108, 127, 128, 129, 130, 131, 70, 158, 74, 84, 75, 76, 163, 31, 80, 159, 167, 161, 101, 102, 14, 87, 88, 89, 14, 91, 31, 93, 16, 95, 37, 38, 98, 159, 1, 161, 162, 103, 104, 105, 37, 38, 1, 109, 110, 16, 84, 16, 163, 115, 116, 16, 167, 134, 135, 16, 161, 31, 124, 16, 134, 135, 167, 70, 31, 16, 84, 16, 149, 16, 134, 135, 31, 106, 107, 82, 31, 74, 31, 86, 161, 106, 107, 80, 159, 31, 161, 161, 154, 31, 87, 88, 89, 31, 91, 31, 93, 161, 95, 111, 112, 98, 31, 31, 31, 31, 103, 104, 105, 31, 31, 31, 109, 110, 31, 31, 31, 84, 115, 116, 31, 159, 31, 161, 37, 84, 38, 124, 35, 136, 137, 35, 139, 140, 141, 142, 143, 144, 35, 31, 70, 159, 37, 161, 151, 152, 69, 57, 74, 80, 82, 85, 77, 90, 80, 94, 163, 92, 82, 166, 167, 87, 88, 89, 83, 91, 114, 93, 113, 95, 128, 85, 98, 116, 128, 153, 128, 103, 104, 105, 146, 89, 74, 109, 110, 0, 1, 149, 80, 115, 116, 96, 159, 133, 161, 87, 88, 89, 124, 91, 159, 93, 161, 95, 97, 146, 98, 97, 97, 100, 154, 103, 104, 105, 74, 100, 149, 109, 110, -1, 80, -1, -1, 115, 116, -1, 132, 87, 88, 89, 132, 91, 124, 93, -1, 95, -1, 155, 98, -1, -1, -1, 102, 103, 104, 105, 74, -1, 149, 109, 110, 149, 80, 81, 153, 115, 116, 160, 1, 87, 88, 89, 149, 91, 124, 93, 160, 95, 164, 84, 98, 159, 158, -1, -1, 103, 104, 105, 159, 159, 159, 109, 110, 159, 159, 159, 159, 115, 116, 159, 159, 106, 159, 108, 1, 159, 124, 159, 113, 160, 159, 159, 117, 118, 159, 159, 159, 163, 160, 160, 160, -1, 127, 128, 129, 130, 131, 161, 161, 74, 161, 161, 161, 161, 161, 80, 161, 161, 161, 161, 161, 167, 87, 88, 89, 150, 91, 162, 93, 162, 95, 84, 162, 98, 159, 162, 161, 162, 103, 104, 105, 162, 162, 162, 109, 110, 162, 100, 101, 102, 115, 116, 162, 106, 70, 162, 162, 162, 162, 124, 162, 162, 162, 162, 117, 118, 82, 84, 162, 162, 86, 162, 162, 162, 127, 128, 129, 130, 131, 162, 162, 162, 162, 100, 101, 102, 163, 163, 163, 106, 163, 163, 163, 163, 163, 163, 163, 163, -1, 163, 117, 118, 163, 163, 163, 163, 159, 163, 161, 162, 127, 128, 129, 130, 131, 163, 163, 163, 163, 163, 163, 137, 163, 139, 140, 141, 142, 143, 144, 163, 163, 163, 163, 163, 163, 151, 152, 163, 163, 163, 163, 163, 159, 164, 161, 162, 164, 163, -1, 164, 166, 167, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, 164, -1, 165, 165, -1, 166);
    protected $actionBase = array(0, -2, 154, 565, 876, 948, 984, 514, 53, 398, 837, 307, 307, 67, 307, 307, 307, 653, 724, 724, 732, 724, 616, 673, 204, 204, 204, 625, 625, 625, 625, 694, 694, 831, 831, 863, 799, 765, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 936, 375, 519, 369, 701, 1017, 1023, 1019, 1024, 1015, 1014, 1018, 1020, 1025, 911, 912, 782, 918, 919, 920, 921, 1021, 841, 1016, 1022, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 290, 491, 44, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 382, 160, 160, 160, 187, 684, 684, 341, 203, 610, 47, 985, 985, 985, 985, 985, 985, 985, 985, 985, 985, 144, 144, 7, 7, 7, 7, 7, 371, -25, -25, -25, -25, 540, 385, 102, 576, 358, 45, 377, 460, 460, 360, 231, 231, 231, 231, 231, 231, -78, -78, -78, -78, -78, -66, 319, 457, -94, 396, 423, 586, 586, 586, 586, 423, 423, 423, 423, 750, 1029, 423, 423, 423, 511, 516, 516, 518, 147, 147, 147, 516, 583, 777, 422, 583, 422, 194, 92, 748, -40, 87, 412, 748, 617, 627, 198, 143, 773, 658, 773, 1013, 757, 764, 717, 838, 860, 1026, 800, 908, 806, 910, 219, 686, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 1012, 855, 552, 1013, 286, 855, 855, 855, 552, 552, 552, 552, 552, 552, 552, 552, 552, 552, 679, 286, 568, 626, 286, 794, 552, 375, 758, 375, 375, 375, 375, 958, 375, 375, 375, 375, 375, 375, 970, 769, -16, 375, 519, 12, 12, 547, 83, 12, 12, 12, 12, 375, 375, 375, 658, 781, 713, 666, 792, 448, 781, 781, 781, 438, 444, 193, 447, 570, 523, 580, 760, 760, 767, 929, 929, 760, 759, 760, 767, 934, 760, 929, 805, 359, 648, 577, 611, 656, 929, 478, 760, 760, 760, 760, 665, 760, 467, 433, 760, 760, 785, 774, 789, 60, 929, 929, 929, 789, 596, 751, 751, 751, 811, 812, 746, 771, 567, 498, 677, 348, 779, 771, 771, 760, 640, 746, 771, 746, 771, 747, 771, 771, 771, 746, 771, 759, 585, 771, 734, 668, 224, 771, 6, 935, 937, 354, 940, 932, 941, 979, 942, 943, 851, 956, 933, 945, 931, 930, 780, 703, 720, 790, 729, 928, 768, 768, 768, 925, 768, 768, 768, 768, 768, 768, 768, 768, 703, 788, 804, 733, 783, 960, 722, 726, 725, 868, 1027, 1028, 737, 739, 958, 1006, 953, 803, 730, 992, 967, 866, 848, 968, 969, 993, 1007, 1008, 871, 761, 874, 880, 797, 971, 852, 768, 935, 943, 933, 945, 931, 930, 763, 762, 753, 755, 749, 745, 736, 738, 770, 1009, 924, 835, 830, 970, 926, 703, 839, 986, 847, 994, 995, 850, 801, 772, 840, 881, 972, 975, 976, 853, 1010, 810, 989, 795, 996, 802, 882, 997, 998, 999, 1000, 885, 854, 856, 857, 815, 754, 980, 786, 891, 335, 787, 796, 978, 363, 957, 858, 894, 895, 1001, 1002, 1003, 896, 954, 816, 990, 752, 991, 983, 817, 818, 485, 784, 778, 541, 676, 897, 899, 900, 955, 775, 766, 821, 822, 1011, 901, 697, 824, 740, 902, 1005, 742, 744, 756, 859, 793, 743, 798, 977, 776, 827, 907, 829, 832, 833, 1004, 836, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 458, 458, 458, 458, 458, 458, 307, 307, 307, 307, 0, 0, 307, 0, 0, 0, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 458, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, 423, 423, 291, 291, 0, 291, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 291, 291, 291, 291, 291, 291, 291, 805, 147, 147, 147, 147, 423, 423, 423, 423, 423, -88, -88, 147, 147, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 423, 0, 0, 0, 286, 422, 0, 759, 759, 759, 759, 0, 0, 0, 0, 422, 422, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 286, 422, 0, 286, 0, 759, 759, 423, 805, 805, 314, 423, 0, 0, 0, 0, 286, 759, 286, 552, 422, 552, 552, 12, 375, 314, 608, 608, 608, 608, 0, 658, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 805, 759, 0, 805, 0, 759, 759, 759, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 759, 0, 0, 929, 0, 0, 0, 0, 760, 0, 0, 0, 0, 0, 0, 760, 934, 0, 0, 0, 0, 0, 0, 759, 0, 0, 0, 0, 0, 0, 0, 0, 768, 801, 0, 801, 0, 768, 768, 768);
    protected $actionDefault = array(3, 32767, 103, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 101, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 578, 578, 578, 578, 32767, 32767, 246, 103, 32767, 32767, 454, 372, 372, 372, 32767, 32767, 522, 522, 522, 522, 522, 522, 32767, 32767, 32767, 32767, 32767, 32767, 454, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 101, 32767, 32767, 32767, 37, 7, 8, 10, 11, 50, 17, 310, 32767, 32767, 32767, 32767, 103, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 571, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 458, 437, 438, 440, 441, 371, 523, 577, 313, 574, 370, 146, 325, 315, 234, 316, 250, 459, 251, 460, 463, 464, 211, 279, 367, 150, 401, 455, 403, 453, 457, 402, 377, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 375, 376, 456, 434, 433, 432, 399, 32767, 32767, 400, 404, 374, 407, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 103, 32767, 405, 406, 423, 424, 421, 422, 425, 32767, 426, 427, 428, 429, 32767, 32767, 302, 32767, 32767, 351, 349, 414, 415, 302, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 516, 431, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 103, 32767, 101, 518, 396, 398, 486, 409, 410, 408, 378, 32767, 493, 32767, 103, 495, 32767, 32767, 32767, 112, 32767, 32767, 32767, 517, 32767, 524, 524, 32767, 479, 101, 194, 32767, 194, 194, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 585, 479, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 111, 32767, 194, 111, 32767, 32767, 32767, 101, 194, 194, 194, 194, 194, 194, 194, 194, 194, 194, 189, 32767, 260, 262, 103, 539, 194, 32767, 498, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 491, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 479, 419, 139, 32767, 139, 524, 411, 412, 413, 481, 524, 524, 524, 298, 281, 32767, 32767, 32767, 32767, 496, 496, 101, 101, 101, 101, 491, 32767, 32767, 112, 100, 100, 100, 100, 100, 104, 102, 32767, 32767, 32767, 32767, 100, 32767, 102, 102, 32767, 32767, 217, 208, 215, 102, 32767, 543, 544, 215, 102, 219, 219, 219, 239, 239, 470, 304, 102, 100, 102, 102, 196, 304, 304, 32767, 102, 470, 304, 470, 304, 198, 304, 304, 304, 470, 304, 32767, 102, 304, 210, 100, 100, 304, 32767, 32767, 32767, 481, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 511, 32767, 528, 541, 417, 418, 420, 526, 442, 443, 444, 445, 446, 447, 448, 450, 573, 32767, 485, 32767, 32767, 32767, 32767, 324, 583, 32767, 583, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 584, 32767, 524, 32767, 32767, 32767, 32767, 416, 9, 76, 43, 44, 52, 58, 502, 503, 504, 505, 499, 500, 506, 501, 32767, 32767, 507, 549, 32767, 32767, 525, 576, 32767, 32767, 32767, 32767, 32767, 32767, 139, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 511, 32767, 137, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 524, 32767, 32767, 32767, 300, 301, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 524, 32767, 32767, 32767, 283, 284, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 278, 32767, 32767, 366, 32767, 32767, 32767, 32767, 345, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 152, 152, 3, 3, 327, 152, 152, 152, 327, 152, 327, 327, 327, 152, 152, 152, 152, 152, 152, 272, 184, 254, 257, 239, 239, 152, 337, 152);
    protected $goto = array(194, 194, 670, 422, 643, 463, 1264, 1265, 1022, 416, 308, 309, 329, 563, 314, 421, 330, 423, 622, 801, 678, 637, 586, 651, 652, 653, 165, 165, 165, 165, 218, 195, 191, 191, 175, 177, 213, 191, 191, 191, 191, 191, 192, 192, 192, 192, 192, 192, 186, 187, 188, 189, 190, 215, 213, 216, 521, 522, 412, 523, 525, 526, 527, 528, 529, 530, 531, 532, 1091, 166, 167, 168, 193, 169, 170, 171, 164, 172, 173, 174, 176, 212, 214, 217, 235, 238, 241, 242, 244, 255, 256, 257, 258, 259, 260, 261, 263, 264, 265, 266, 274, 275, 311, 312, 313, 417, 418, 419, 568, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 178, 234, 179, 196, 197, 198, 236, 186, 187, 188, 189, 190, 215, 1091, 199, 180, 181, 182, 200, 196, 183, 237, 201, 199, 163, 202, 203, 184, 204, 205, 206, 185, 207, 208, 209, 210, 211, 323, 323, 323, 323, 827, 608, 608, 824, 547, 538, 342, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1221, 1239, 1239, 288, 288, 288, 288, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 1239, 388, 538, 547, 556, 557, 395, 566, 588, 602, 603, 832, 825, 880, 875, 876, 889, 15, 833, 877, 830, 878, 879, 831, 799, 251, 251, 883, 919, 992, 1000, 1004, 1001, 1005, 1237, 1237, 938, 1043, 1039, 1040, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 1237, 858, 248, 248, 248, 248, 250, 252, 533, 533, 533, 533, 487, 590, 488, 1190, 1190, 997, 1190, 997, 494, 1290, 1290, 560, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 997, 1261, 1261, 1290, 1261, 340, 1190, 930, 402, 677, 1279, 1190, 1190, 1190, 1190, 959, 345, 1190, 1190, 1190, 1271, 1271, 1271, 1271, 606, 640, 345, 345, 1273, 1273, 1273, 1273, 820, 820, 805, 896, 884, 840, 885, 897, 345, 345, 5, 345, 6, 1306, 384, 535, 535, 559, 535, 415, 852, 597, 1257, 839, 540, 524, 524, 345, 1289, 1289, 642, 524, 524, 524, 524, 524, 524, 524, 524, 524, 524, 445, 805, 1140, 805, 1289, 932, 932, 932, 932, 1063, 1064, 445, 926, 933, 386, 390, 548, 587, 591, 1030, 1292, 331, 554, 1259, 1259, 1030, 704, 621, 623, 823, 641, 1250, 319, 303, 660, 664, 973, 668, 676, 969, 429, 553, 962, 936, 936, 934, 936, 703, 601, 537, 971, 966, 343, 344, 663, 817, 595, 609, 612, 613, 614, 615, 634, 635, 636, 680, 439, 1186, 845, 454, 454, 439, 439, 1266, 1267, 820, 901, 1079, 454, 394, 539, 551, 1183, 605, 540, 539, 842, 551, 978, 272, 387, 618, 619, 981, 536, 536, 844, 707, 646, 957, 567, 457, 458, 459, 838, 850, 254, 254, 1297, 1298, 400, 401, 976, 976, 464, 649, 1182, 650, 1028, 404, 405, 406, 1187, 661, 424, 1032, 407, 564, 600, 815, 338, 424, 854, 848, 853, 841, 1027, 1031, 1009, 1002, 1006, 1003, 1007, 1185, 941, 1188, 1247, 1248, 943, 0, 1074, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 439, 0, 468, 439, 585, 1056, 931, 681, 667, 667, 0, 495, 673, 1054, 1171, 912, 0, 0, 1172, 1175, 913, 1176, 0, 0, 0, 0, 0, 0, 1072, 857);
    protected $gotoCheck = array(42, 42, 72, 65, 65, 166, 166, 166, 119, 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, 7, 9, 84, 122, 84, 84, 84, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 23, 23, 23, 23, 15, 104, 104, 26, 75, 75, 93, 104, 104, 104, 104, 104, 104, 104, 104, 104, 104, 160, 160, 24, 24, 24, 24, 160, 160, 160, 160, 160, 160, 160, 160, 160, 160, 75, 75, 75, 75, 75, 75, 75, 75, 75, 75, 15, 27, 15, 15, 15, 15, 75, 15, 15, 15, 15, 15, 15, 6, 5, 5, 15, 87, 87, 87, 87, 87, 87, 161, 161, 49, 15, 15, 15, 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, 45, 5, 5, 5, 5, 5, 5, 103, 103, 103, 103, 147, 103, 147, 72, 72, 72, 72, 72, 147, 173, 173, 162, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 122, 122, 173, 122, 169, 72, 89, 89, 89, 171, 72, 72, 72, 72, 99, 14, 72, 72, 72, 9, 9, 9, 9, 55, 55, 14, 14, 122, 122, 122, 122, 22, 22, 12, 72, 64, 35, 64, 72, 14, 14, 46, 14, 46, 14, 61, 19, 19, 100, 19, 13, 35, 13, 122, 35, 14, 163, 163, 14, 172, 172, 63, 163, 163, 163, 163, 163, 163, 163, 163, 163, 163, 19, 12, 143, 12, 172, 19, 19, 19, 19, 136, 136, 19, 19, 19, 58, 58, 58, 58, 58, 122, 172, 29, 48, 122, 122, 122, 48, 48, 48, 25, 48, 14, 159, 159, 48, 48, 48, 48, 48, 48, 109, 9, 25, 25, 25, 25, 25, 25, 9, 25, 25, 25, 93, 93, 14, 18, 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, 23, 20, 39, 141, 141, 23, 23, 168, 168, 22, 17, 17, 141, 28, 9, 9, 152, 17, 14, 9, 37, 9, 17, 24, 9, 83, 83, 106, 24, 24, 17, 95, 17, 17, 9, 9, 9, 9, 17, 9, 5, 5, 9, 9, 80, 80, 103, 103, 149, 80, 17, 80, 121, 80, 80, 80, 20, 80, 113, 124, 80, 2, 2, 20, 80, 113, 41, 9, 16, 16, 16, 16, 113, 113, 113, 113, 113, 14, 16, 20, 20, 20, 92, -1, 139, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, -1, 82, 23, 8, 8, 16, 8, 8, 8, -1, 8, 8, 8, 78, 78, -1, -1, 78, 78, 78, 78, -1, -1, -1, -1, -1, -1, 16, 16);
    protected $gotoBase = array(0, 0, -203, 0, 0, 221, 208, 10, 512, 7, 0, 0, 24, 1, 5, -174, 47, -23, 105, 61, 38, 0, -10, 158, 181, 379, 164, 205, 102, 84, 0, 0, 0, 0, 0, -43, 0, 107, 0, 104, 0, 54, -1, 0, 0, 235, -384, 0, -307, 210, 0, 0, 0, 0, 0, 266, 0, 0, 324, 0, 0, 286, 0, 103, 298, -236, 0, 0, 0, 0, 0, 0, -6, 0, 0, -167, 0, 0, 129, 62, -14, 0, 53, -22, -669, 0, 0, -52, 0, -11, 0, 0, 68, -299, 0, 52, 0, 0, 0, 262, 288, 0, 0, 227, -73, 0, 87, 0, 0, 118, 0, 0, 0, 209, 0, 0, 0, 0, 0, 6, 0, 108, 15, 0, 46, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 91, 0, 0, 69, 0, 390, 0, 86, 0, 0, 0, -224, 0, 37, 0, 0, 77, 0, 0, 0, 0, 0, 0, 70, -57, -8, 241, 99, 0, 0, -290, 0, 65, 257, 0, 261, 39, -35, 0, 0);
    protected $gotoDefault = array(-32768, 499, 711, 4, 712, 905, 788, 797, 583, 515, 679, 339, 610, 413, 1255, 882, 1078, 565, 816, 1199, 1207, 446, 819, 324, 701, 864, 865, 866, 391, 376, 382, 389, 632, 611, 481, 851, 442, 843, 473, 846, 441, 855, 162, 410, 497, 859, 3, 861, 542, 892, 377, 869, 378, 656, 871, 550, 873, 874, 385, 392, 393, 1083, 558, 607, 886, 243, 552, 887, 375, 888, 895, 380, 383, 665, 453, 492, 486, 403, 1058, 594, 629, 450, 467, 617, 616, 604, 466, 425, 408, 928, 474, 451, 942, 341, 950, 709, 1090, 624, 476, 958, 625, 965, 968, 516, 517, 465, 980, 269, 983, 477, 1015, 647, 648, 995, 626, 627, 1013, 460, 584, 1021, 443, 1029, 1243, 444, 1033, 262, 1036, 276, 409, 426, 1041, 1042, 8, 1048, 671, 672, 10, 273, 496, 1073, 666, 440, 1089, 430, 1159, 1161, 544, 478, 1179, 1178, 659, 493, 1184, 1246, 438, 518, 461, 310, 519, 302, 327, 307, 534, 289, 328, 520, 462, 1252, 1260, 325, 30, 1280, 1291, 335, 562, 599);
    protected $ruleToNonTerminal = array(0, 1, 3, 3, 2, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, 11, 12, 12, 13, 13, 14, 15, 15, 16, 16, 17, 17, 18, 18, 21, 21, 22, 23, 23, 24, 24, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 29, 29, 30, 30, 32, 34, 34, 28, 36, 36, 33, 38, 38, 35, 35, 37, 37, 39, 39, 31, 40, 40, 41, 43, 44, 44, 45, 46, 46, 48, 47, 47, 47, 47, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 25, 25, 68, 68, 71, 71, 70, 69, 69, 62, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 26, 26, 27, 27, 27, 27, 86, 86, 88, 88, 81, 81, 81, 82, 82, 85, 85, 83, 83, 89, 90, 90, 56, 56, 64, 64, 67, 67, 67, 66, 91, 91, 92, 57, 57, 57, 57, 93, 93, 94, 94, 95, 95, 96, 97, 97, 98, 98, 99, 99, 54, 54, 50, 50, 101, 52, 52, 102, 51, 51, 53, 53, 63, 63, 63, 63, 79, 79, 105, 105, 107, 107, 108, 108, 108, 108, 106, 106, 106, 110, 110, 110, 110, 87, 87, 113, 113, 113, 111, 111, 114, 114, 112, 112, 115, 115, 116, 116, 116, 116, 109, 109, 80, 80, 80, 20, 20, 20, 118, 117, 117, 119, 119, 119, 119, 59, 120, 120, 121, 60, 123, 123, 124, 124, 125, 125, 84, 126, 126, 126, 126, 126, 126, 131, 131, 132, 132, 133, 133, 133, 133, 133, 134, 135, 135, 130, 130, 127, 127, 129, 129, 137, 137, 136, 136, 136, 136, 136, 136, 136, 128, 138, 138, 140, 139, 139, 61, 100, 141, 141, 55, 55, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 148, 142, 142, 147, 147, 150, 151, 151, 152, 153, 153, 153, 19, 19, 72, 72, 72, 72, 143, 143, 143, 143, 155, 155, 144, 144, 146, 146, 146, 149, 149, 160, 160, 160, 160, 160, 160, 160, 160, 160, 161, 161, 104, 163, 163, 163, 163, 145, 145, 145, 145, 145, 145, 145, 145, 58, 58, 158, 158, 158, 158, 164, 164, 154, 154, 154, 165, 165, 165, 165, 165, 165, 73, 73, 65, 65, 65, 65, 122, 122, 122, 122, 168, 167, 157, 157, 157, 157, 157, 157, 157, 156, 156, 156, 166, 166, 166, 166, 103, 162, 170, 170, 169, 169, 171, 171, 171, 171, 171, 171, 171, 171, 159, 159, 159, 159, 173, 174, 172, 172, 172, 172, 172, 172, 172, 172, 175, 175, 175, 175);
    protected $ruleToLength = array(1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 2, 1, 3, 4, 1, 2, 0, 1, 1, 1, 1, 1, 3, 5, 4, 3, 4, 2, 3, 1, 1, 7, 6, 2, 3, 1, 2, 3, 1, 2, 3, 1, 1, 3, 1, 3, 1, 2, 2, 3, 1, 3, 2, 3, 1, 3, 2, 0, 1, 1, 1, 1, 1, 3, 7, 10, 5, 7, 9, 5, 3, 3, 3, 3, 3, 3, 1, 2, 5, 7, 9, 6, 5, 6, 3, 2, 1, 1, 1, 0, 2, 1, 3, 8, 0, 4, 2, 1, 3, 0, 1, 0, 1, 0, 1, 3, 1, 8, 9, 8, 7, 6, 8, 0, 2, 0, 2, 1, 2, 2, 0, 2, 0, 2, 0, 2, 2, 1, 3, 1, 4, 1, 4, 1, 1, 4, 2, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 7, 0, 2, 1, 3, 3, 4, 1, 4, 0, 2, 5, 0, 2, 6, 0, 2, 0, 3, 1, 2, 1, 1, 2, 0, 1, 3, 0, 2, 1, 1, 1, 1, 6, 8, 6, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 1, 2, 1, 1, 0, 1, 0, 2, 2, 2, 4, 3, 1, 1, 3, 1, 2, 2, 3, 2, 3, 1, 1, 2, 3, 1, 1, 3, 2, 0, 1, 5, 5, 10, 3, 5, 1, 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, 1, 1, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 3, 1, 1, 3, 2, 2, 3, 1, 0, 1, 1, 3, 3, 3, 4, 1, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 4, 4, 2, 2, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3, 2, 1, 2, 4, 2, 2, 8, 9, 8, 9, 9, 10, 9, 10, 8, 3, 2, 0, 4, 2, 1, 3, 2, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 0, 3, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 4, 1, 1, 3, 1, 1, 1, 1, 1, 3, 2, 3, 0, 1, 1, 3, 1, 1, 1, 1, 1, 3, 1, 1, 4, 4, 1, 4, 4, 0, 1, 1, 1, 3, 3, 1, 4, 2, 2, 1, 3, 1, 4, 4, 3, 3, 3, 3, 1, 3, 1, 1, 3, 1, 1, 4, 1, 1, 1, 3, 1, 1, 2, 1, 3, 4, 3, 2, 0, 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, 3, 6, 3, 1, 1, 2, 1);
    /**
     *
     */
    protected function initReduceCallbacks()
    {
        $this->reduceCallbacks = [0 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 1 => function ($stackPos) {
            $this->semValue = $this->handleNamespaces($this->semStack[$stackPos - (1 - 1)]);
        }, 2 => function ($stackPos) {
            if (\is_array($this->semStack[$stackPos - (2 - 2)])) {
                $this->semValue = \array_merge($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]);
            } else {
                $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
                $this->semValue = $this->semStack[$stackPos - (2 - 1)];
            }
        }, 3 => function ($stackPos) {
            $this->semValue = array();
        }, 4 => function ($stackPos) {
            $startAttributes = $this->lookaheadStartAttributes;
            if (isset($startAttributes['comments'])) {
                $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments']));
            } else {
                $nop = null;
            }
            if ($nop !== null) {
                $this->semStack[$stackPos - (1 - 1)][] = $nop;
            }
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 5 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 6 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 7 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 8 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 9 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 10 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 11 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 12 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 13 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 14 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 15 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 16 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 17 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 18 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 19 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 20 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 21 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 22 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 23 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 24 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 25 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 26 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 27 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 28 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 29 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 30 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 31 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 32 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 33 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 34 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 35 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 36 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 37 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 38 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 39 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 40 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 41 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 42 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 43 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 44 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 45 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 46 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 47 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 48 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 49 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 50 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 51 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 52 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 53 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 54 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 55 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 56 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 57 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 58 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 59 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 60 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 61 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 62 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 63 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 64 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 65 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 66 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 67 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 68 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 69 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 70 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 71 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 72 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 73 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 74 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 75 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 76 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 77 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 78 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 79 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 80 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 81 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 82 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 83 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 84 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 85 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 86 => function ($stackPos) {
            $this->semValue = new Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 87 => function ($stackPos) {
            $this->semValue = new Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 88 => function ($stackPos) {
            $this->semValue = new Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 89 => function ($stackPos) {
            $this->semValue = new Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 90 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 91 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 92 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 93 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 94 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 95 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 96 => function ($stackPos) {
            $this->semValue = new Name(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 97 => function ($stackPos) {
            $this->semValue = new Expr\Variable(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 98 => function ($stackPos) {
            /* nothing */
        }, 99 => function ($stackPos) {
            /* nothing */
        }, 100 => function ($stackPos) {
            /* nothing */
        }, 101 => function ($stackPos) {
            $this->emitError(new Error('A trailing comma is not allowed here', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes));
        }, 102 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 103 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 104 => function ($stackPos) {
            $this->semValue = new Node\Attribute($this->semStack[$stackPos - (1 - 1)], [], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 105 => function ($stackPos) {
            $this->semValue = new Node\Attribute($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 106 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 107 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 108 => function ($stackPos) {
            $this->semValue = new Node\AttributeGroup($this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 109 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 110 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 111 => function ($stackPos) {
            $this->semValue = [];
        }, 112 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 113 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 114 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 115 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 116 => function ($stackPos) {
            $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 117 => function ($stackPos) {
            $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos - (3 - 2)], null, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
            $this->checkNamespace($this->semValue);
        }, 118 => function ($stackPos) {
            $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos - (5 - 2)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
            $this->checkNamespace($this->semValue);
        }, 119 => function ($stackPos) {
            $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
            $this->checkNamespace($this->semValue);
        }, 120 => function ($stackPos) {
            $this->semValue = new Stmt\Use_($this->semStack[$stackPos - (3 - 2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 121 => function ($stackPos) {
            $this->semValue = new Stmt\Use_($this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 122 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 123 => function ($stackPos) {
            $this->semValue = new Stmt\Const_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 124 => function ($stackPos) {
            $this->semValue = Stmt\Use_::TYPE_FUNCTION;
        }, 125 => function ($stackPos) {
            $this->semValue = Stmt\Use_::TYPE_CONSTANT;
        }, 126 => function ($stackPos) {
            $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 6)], $this->semStack[$stackPos - (7 - 2)], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
        }, 127 => function ($stackPos) {
            $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 128 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 129 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 130 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 131 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 132 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 133 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 134 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 135 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 136 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 137 => function ($stackPos) {
            $this->semValue = new Stmt\UseUse($this->semStack[$stackPos - (1 - 1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
            $this->checkUseUse($this->semValue, $stackPos - (1 - 1));
        }, 138 => function ($stackPos) {
            $this->semValue = new Stmt\UseUse($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
            $this->checkUseUse($this->semValue, $stackPos - (3 - 3));
        }, 139 => function ($stackPos) {
            $this->semValue = new Stmt\UseUse($this->semStack[$stackPos - (1 - 1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
            $this->checkUseUse($this->semValue, $stackPos - (1 - 1));
        }, 140 => function ($stackPos) {
            $this->semValue = new Stmt\UseUse($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
            $this->checkUseUse($this->semValue, $stackPos - (3 - 3));
        }, 141 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
            $this->semValue->type = Stmt\Use_::TYPE_NORMAL;
        }, 142 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue->type = $this->semStack[$stackPos - (2 - 1)];
        }, 143 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 144 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 145 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 146 => function ($stackPos) {
            $this->semValue = new Node\Const_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 147 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 148 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 149 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 150 => function ($stackPos) {
            $this->semValue = new Node\Const_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 151 => function ($stackPos) {
            if (\is_array($this->semStack[$stackPos - (2 - 2)])) {
                $this->semValue = \array_merge($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]);
            } else {
                $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
                $this->semValue = $this->semStack[$stackPos - (2 - 1)];
            }
        }, 152 => function ($stackPos) {
            $this->semValue = array();
        }, 153 => function ($stackPos) {
            $startAttributes = $this->lookaheadStartAttributes;
            if (isset($startAttributes['comments'])) {
                $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments']));
            } else {
                $nop = null;
            }
            if ($nop !== null) {
                $this->semStack[$stackPos - (1 - 1)][] = $nop;
            }
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 154 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 155 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 156 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 157 => function ($stackPos) {
            throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 158 => function ($stackPos) {
            if ($this->semStack[$stackPos - (3 - 2)]) {
                $this->semValue = $this->semStack[$stackPos - (3 - 2)];
                $attrs = $this->startAttributeStack[$stackPos - (3 - 1)];
                $stmts = $this->semValue;
                if (!empty($attrs['comments'])) {
                    $stmts[0]->setAttribute('comments', \array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', [])));
                }
            } else {
                $startAttributes = $this->startAttributeStack[$stackPos - (3 - 1)];
                if (isset($startAttributes['comments'])) {
                    $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes);
                } else {
                    $this->semValue = null;
                }
                if (null === $this->semValue) {
                    $this->semValue = array();
                }
            }
        }, 159 => function ($stackPos) {
            $this->semValue = new Stmt\If_($this->semStack[$stackPos - (7 - 3)], ['stmts' => \is_array($this->semStack[$stackPos - (7 - 5)]) ? $this->semStack[$stackPos - (7 - 5)] : array($this->semStack[$stackPos - (7 - 5)]), 'elseifs' => $this->semStack[$stackPos - (7 - 6)], 'else' => $this->semStack[$stackPos - (7 - 7)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
        }, 160 => function ($stackPos) {
            $this->semValue = new Stmt\If_($this->semStack[$stackPos - (10 - 3)], ['stmts' => $this->semStack[$stackPos - (10 - 6)], 'elseifs' => $this->semStack[$stackPos - (10 - 7)], 'else' => $this->semStack[$stackPos - (10 - 8)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes);
        }, 161 => function ($stackPos) {
            $this->semValue = new Stmt\While_($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 162 => function ($stackPos) {
            $this->semValue = new Stmt\Do_($this->semStack[$stackPos - (7 - 5)], \is_array($this->semStack[$stackPos - (7 - 2)]) ? $this->semStack[$stackPos - (7 - 2)] : array($this->semStack[$stackPos - (7 - 2)]), $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
        }, 163 => function ($stackPos) {
            $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos - (9 - 3)], 'cond' => $this->semStack[$stackPos - (9 - 5)], 'loop' => $this->semStack[$stackPos - (9 - 7)], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 164 => function ($stackPos) {
            $this->semValue = new Stmt\Switch_($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 165 => function ($stackPos) {
            $this->semValue = new Stmt\Break_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 166 => function ($stackPos) {
            $this->semValue = new Stmt\Continue_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 167 => function ($stackPos) {
            $this->semValue = new Stmt\Return_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 168 => function ($stackPos) {
            $this->semValue = new Stmt\Global_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 169 => function ($stackPos) {
            $this->semValue = new Stmt\Static_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 170 => function ($stackPos) {
            $this->semValue = new Stmt\Echo_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 171 => function ($stackPos) {
            $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 172 => function ($stackPos) {
            $e = $this->semStack[$stackPos - (2 - 1)];
            if ($e instanceof Expr\Throw_) {
                // For backwards-compatibility reasons, convert throw in statement position into
                // Stmt\Throw_ rather than Stmt\Expression(Expr\Throw_).
                $this->semValue = new Stmt\Throw_($e->expr, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
            } else {
                $this->semValue = new Stmt\Expression($e, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
            }
        }, 173 => function ($stackPos) {
            $this->semValue = new Stmt\Unset_($this->semStack[$stackPos - (5 - 3)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 174 => function ($stackPos) {
            $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos - (7 - 5)][1], 'stmts' => $this->semStack[$stackPos - (7 - 7)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
        }, 175 => function ($stackPos) {
            $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos - (9 - 3)], $this->semStack[$stackPos - (9 - 7)][0], ['keyVar' => $this->semStack[$stackPos - (9 - 5)], 'byRef' => $this->semStack[$stackPos - (9 - 7)][1], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 176 => function ($stackPos) {
            $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos - (6 - 3)], new Expr\Error($this->startAttributeStack[$stackPos - (6 - 4)] + $this->endAttributeStack[$stackPos - (6 - 4)]), ['stmts' => $this->semStack[$stackPos - (6 - 6)]], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 177 => function ($stackPos) {
            $this->semValue = new Stmt\Declare_($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 178 => function ($stackPos) {
            $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 5)], $this->semStack[$stackPos - (6 - 6)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
            $this->checkTryCatch($this->semValue);
        }, 179 => function ($stackPos) {
            $this->semValue = new Stmt\Goto_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 180 => function ($stackPos) {
            $this->semValue = new Stmt\Label($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 181 => function ($stackPos) {
            $this->semValue = array();
            /* means: no statement */
        }, 182 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 183 => function ($stackPos) {
            $startAttributes = $this->startAttributeStack[$stackPos - (1 - 1)];
            if (isset($startAttributes['comments'])) {
                $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes);
            } else {
                $this->semValue = null;
            }
            if ($this->semValue === null) {
                $this->semValue = array();
            }
            /* means: no statement */
        }, 184 => function ($stackPos) {
            $this->semValue = array();
        }, 185 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 186 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 187 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 188 => function ($stackPos) {
            $this->semValue = new Stmt\Catch_($this->semStack[$stackPos - (8 - 3)], $this->semStack[$stackPos - (8 - 4)], $this->semStack[$stackPos - (8 - 7)], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes);
        }, 189 => function ($stackPos) {
            $this->semValue = null;
        }, 190 => function ($stackPos) {
            $this->semValue = new Stmt\Finally_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 191 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 192 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 193 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 194 => function ($stackPos) {
            $this->semValue = \false;
        }, 195 => function ($stackPos) {
            $this->semValue = \true;
        }, 196 => function ($stackPos) {
            $this->semValue = \false;
        }, 197 => function ($stackPos) {
            $this->semValue = \true;
        }, 198 => function ($stackPos) {
            $this->semValue = \false;
        }, 199 => function ($stackPos) {
            $this->semValue = \true;
        }, 200 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 201 => function ($stackPos) {
            $this->semValue = [];
        }, 202 => function ($stackPos) {
            $this->semValue = new Stmt\Function_($this->semStack[$stackPos - (8 - 3)], ['byRef' => $this->semStack[$stackPos - (8 - 2)], 'params' => $this->semStack[$stackPos - (8 - 5)], 'returnType' => $this->semStack[$stackPos - (8 - 7)], 'stmts' => $this->semStack[$stackPos - (8 - 8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes);
        }, 203 => function ($stackPos) {
            $this->semValue = new Stmt\Function_($this->semStack[$stackPos - (9 - 4)], ['byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 6)], 'returnType' => $this->semStack[$stackPos - (9 - 8)], 'stmts' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => $this->semStack[$stackPos - (9 - 1)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 204 => function ($stackPos) {
            $this->semValue = new Stmt\Class_($this->semStack[$stackPos - (8 - 3)], ['type' => $this->semStack[$stackPos - (8 - 2)], 'extends' => $this->semStack[$stackPos - (8 - 4)], 'implements' => $this->semStack[$stackPos - (8 - 5)], 'stmts' => $this->semStack[$stackPos - (8 - 7)], 'attrGroups' => $this->semStack[$stackPos - (8 - 1)]], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes);
            $this->checkClass($this->semValue, $stackPos - (8 - 3));
        }, 205 => function ($stackPos) {
            $this->semValue = new Stmt\Interface_($this->semStack[$stackPos - (7 - 3)], ['extends' => $this->semStack[$stackPos - (7 - 4)], 'stmts' => $this->semStack[$stackPos - (7 - 6)], 'attrGroups' => $this->semStack[$stackPos - (7 - 1)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
            $this->checkInterface($this->semValue, $stackPos - (7 - 3));
        }, 206 => function ($stackPos) {
            $this->semValue = new Stmt\Trait_($this->semStack[$stackPos - (6 - 3)], ['stmts' => $this->semStack[$stackPos - (6 - 5)], 'attrGroups' => $this->semStack[$stackPos - (6 - 1)]], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 207 => function ($stackPos) {
            $this->semValue = new Stmt\Enum_($this->semStack[$stackPos - (8 - 3)], ['scalarType' => $this->semStack[$stackPos - (8 - 4)], 'implements' => $this->semStack[$stackPos - (8 - 5)], 'stmts' => $this->semStack[$stackPos - (8 - 7)], 'attrGroups' => $this->semStack[$stackPos - (8 - 1)]], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes);
            $this->checkEnum($this->semValue, $stackPos - (8 - 3));
        }, 208 => function ($stackPos) {
            $this->semValue = null;
        }, 209 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 210 => function ($stackPos) {
            $this->semValue = null;
        }, 211 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 212 => function ($stackPos) {
            $this->semValue = 0;
        }, 213 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
        }, 214 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_FINAL;
        }, 215 => function ($stackPos) {
            $this->semValue = null;
        }, 216 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 217 => function ($stackPos) {
            $this->semValue = array();
        }, 218 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 219 => function ($stackPos) {
            $this->semValue = array();
        }, 220 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 221 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 222 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 223 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 224 => function ($stackPos) {
            $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]);
        }, 225 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 226 => function ($stackPos) {
            $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]);
        }, 227 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 228 => function ($stackPos) {
            $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]);
        }, 229 => function ($stackPos) {
            $this->semValue = null;
        }, 230 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 231 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 232 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 233 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 234 => function ($stackPos) {
            $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 235 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 236 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 3)];
        }, 237 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 238 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (5 - 3)];
        }, 239 => function ($stackPos) {
            $this->semValue = array();
        }, 240 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 241 => function ($stackPos) {
            $this->semValue = new Stmt\Case_($this->semStack[$stackPos - (4 - 2)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 242 => function ($stackPos) {
            $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 243 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 244 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 245 => function ($stackPos) {
            $this->semValue = new Expr\Match_($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 6)], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
        }, 246 => function ($stackPos) {
            $this->semValue = [];
        }, 247 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 248 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 249 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 250 => function ($stackPos) {
            $this->semValue = new Node\MatchArm($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 251 => function ($stackPos) {
            $this->semValue = new Node\MatchArm(null, $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 252 => function ($stackPos) {
            $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]);
        }, 253 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 254 => function ($stackPos) {
            $this->semValue = array();
        }, 255 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 256 => function ($stackPos) {
            $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos - (5 - 3)], \is_array($this->semStack[$stackPos - (5 - 5)]) ? $this->semStack[$stackPos - (5 - 5)] : array($this->semStack[$stackPos - (5 - 5)]), $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 257 => function ($stackPos) {
            $this->semValue = array();
        }, 258 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 259 => function ($stackPos) {
            $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 6)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 260 => function ($stackPos) {
            $this->semValue = null;
        }, 261 => function ($stackPos) {
            $this->semValue = new Stmt\Else_(\is_array($this->semStack[$stackPos - (2 - 2)]) ? $this->semStack[$stackPos - (2 - 2)] : array($this->semStack[$stackPos - (2 - 2)]), $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 262 => function ($stackPos) {
            $this->semValue = null;
        }, 263 => function ($stackPos) {
            $this->semValue = new Stmt\Else_($this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 264 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false);
        }, 265 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (2 - 2)], \true);
        }, 266 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false);
        }, 267 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false);
        }, 268 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 269 => function ($stackPos) {
            $this->semValue = array();
        }, 270 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 271 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 272 => function ($stackPos) {
            $this->semValue = 0;
        }, 273 => function ($stackPos) {
            $this->checkModifier($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $stackPos - (2 - 2));
            $this->semValue = $this->semStack[$stackPos - (2 - 1)] | $this->semStack[$stackPos - (2 - 2)];
        }, 274 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PUBLIC;
        }, 275 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PROTECTED;
        }, 276 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PRIVATE;
        }, 277 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_READONLY;
        }, 278 => function ($stackPos) {
            $this->semValue = new Node\Param($this->semStack[$stackPos - (6 - 6)], null, $this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 4)], $this->semStack[$stackPos - (6 - 5)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 1)]);
            $this->checkParam($this->semValue);
        }, 279 => function ($stackPos) {
            $this->semValue = new Node\Param($this->semStack[$stackPos - (8 - 6)], $this->semStack[$stackPos - (8 - 8)], $this->semStack[$stackPos - (8 - 3)], $this->semStack[$stackPos - (8 - 4)], $this->semStack[$stackPos - (8 - 5)], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (8 - 2)], $this->semStack[$stackPos - (8 - 1)]);
            $this->checkParam($this->semValue);
        }, 280 => function ($stackPos) {
            $this->semValue = new Node\Param(new Expr\Error($this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes), null, $this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 4)], $this->semStack[$stackPos - (6 - 5)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 1)]);
        }, 281 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 282 => function ($stackPos) {
            $this->semValue = new Node\NullableType($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 283 => function ($stackPos) {
            $this->semValue = new Node\UnionType($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 284 => function ($stackPos) {
            $this->semValue = new Node\IntersectionType($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 285 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 286 => function ($stackPos) {
            $this->semValue = new Node\Name('static', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 287 => function ($stackPos) {
            $this->semValue = $this->handleBuiltinTypes($this->semStack[$stackPos - (1 - 1)]);
        }, 288 => function ($stackPos) {
            $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 289 => function ($stackPos) {
            $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 290 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]);
        }, 291 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 292 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]);
        }, 293 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 294 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]);
        }, 295 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 296 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]);
        }, 297 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 298 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 299 => function ($stackPos) {
            $this->semValue = new Node\NullableType($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 300 => function ($stackPos) {
            $this->semValue = new Node\UnionType($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 301 => function ($stackPos) {
            $this->semValue = new Node\IntersectionType($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 302 => function ($stackPos) {
            $this->semValue = null;
        }, 303 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 304 => function ($stackPos) {
            $this->semValue = null;
        }, 305 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 306 => function ($stackPos) {
            $this->semValue = null;
        }, 307 => function ($stackPos) {
            $this->semValue = array();
        }, 308 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 309 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (3 - 2)]);
        }, 310 => function ($stackPos) {
            $this->semValue = new Node\VariadicPlaceholder($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 311 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 312 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 313 => function ($stackPos) {
            $this->semValue = new Node\Arg($this->semStack[$stackPos - (1 - 1)], \false, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 314 => function ($stackPos) {
            $this->semValue = new Node\Arg($this->semStack[$stackPos - (2 - 2)], \true, \false, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 315 => function ($stackPos) {
            $this->semValue = new Node\Arg($this->semStack[$stackPos - (2 - 2)], \false, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 316 => function ($stackPos) {
            $this->semValue = new Node\Arg($this->semStack[$stackPos - (3 - 3)], \false, \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (3 - 1)]);
        }, 317 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 318 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 319 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 320 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 321 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 322 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 323 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 324 => function ($stackPos) {
            $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos - (1 - 1)], null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 325 => function ($stackPos) {
            $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 326 => function ($stackPos) {
            if ($this->semStack[$stackPos - (2 - 2)] !== null) {
                $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
                $this->semValue = $this->semStack[$stackPos - (2 - 1)];
            }
        }, 327 => function ($stackPos) {
            $this->semValue = array();
        }, 328 => function ($stackPos) {
            $startAttributes = $this->lookaheadStartAttributes;
            if (isset($startAttributes['comments'])) {
                $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments']));
            } else {
                $nop = null;
            }
            if ($nop !== null) {
                $this->semStack[$stackPos - (1 - 1)][] = $nop;
            }
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 329 => function ($stackPos) {
            $this->semValue = new Stmt\Property($this->semStack[$stackPos - (5 - 2)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 1)]);
            $this->checkProperty($this->semValue, $stackPos - (5 - 2));
        }, 330 => function ($stackPos) {
            $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos - (5 - 4)], $this->semStack[$stackPos - (5 - 2)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes, $this->semStack[$stackPos - (5 - 1)]);
            $this->checkClassConst($this->semValue, $stackPos - (5 - 2));
        }, 331 => function ($stackPos) {
            $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos - (10 - 5)], ['type' => $this->semStack[$stackPos - (10 - 2)], 'byRef' => $this->semStack[$stackPos - (10 - 4)], 'params' => $this->semStack[$stackPos - (10 - 7)], 'returnType' => $this->semStack[$stackPos - (10 - 9)], 'stmts' => $this->semStack[$stackPos - (10 - 10)], 'attrGroups' => $this->semStack[$stackPos - (10 - 1)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes);
            $this->checkClassMethod($this->semValue, $stackPos - (10 - 2));
        }, 332 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 333 => function ($stackPos) {
            $this->semValue = new Stmt\EnumCase($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 4)], $this->semStack[$stackPos - (5 - 1)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 334 => function ($stackPos) {
            $this->semValue = null;
            /* will be skipped */
        }, 335 => function ($stackPos) {
            $this->semValue = array();
        }, 336 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 337 => function ($stackPos) {
            $this->semValue = array();
        }, 338 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 339 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 340 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (5 - 1)][0], $this->semStack[$stackPos - (5 - 1)][1], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 341 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], $this->semStack[$stackPos - (4 - 3)], null, $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 342 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 343 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 344 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]);
        }, 345 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 346 => function ($stackPos) {
            $this->semValue = array(null, $this->semStack[$stackPos - (1 - 1)]);
        }, 347 => function ($stackPos) {
            $this->semValue = null;
        }, 348 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 349 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 350 => function ($stackPos) {
            $this->semValue = 0;
        }, 351 => function ($stackPos) {
            $this->semValue = 0;
        }, 352 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 353 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 354 => function ($stackPos) {
            $this->checkModifier($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $stackPos - (2 - 2));
            $this->semValue = $this->semStack[$stackPos - (2 - 1)] | $this->semStack[$stackPos - (2 - 2)];
        }, 355 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PUBLIC;
        }, 356 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PROTECTED;
        }, 357 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PRIVATE;
        }, 358 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_STATIC;
        }, 359 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
        }, 360 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_FINAL;
        }, 361 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_READONLY;
        }, 362 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 363 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 364 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 365 => function ($stackPos) {
            $this->semValue = new Node\VarLikeIdentifier(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 366 => function ($stackPos) {
            $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos - (1 - 1)], null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 367 => function ($stackPos) {
            $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 368 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 369 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 370 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 371 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 372 => function ($stackPos) {
            $this->semValue = array();
        }, 373 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 374 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 375 => function ($stackPos) {
            $this->semValue = new Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 376 => function ($stackPos) {
            $this->semValue = new Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 377 => function ($stackPos) {
            $this->semValue = new Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 378 => function ($stackPos) {
            $this->semValue = new Expr\AssignRef($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 379 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 380 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 381 => function ($stackPos) {
            $this->semValue = new Expr\Clone_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 382 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 383 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 384 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 385 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 386 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 387 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 388 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 389 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 390 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 391 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 392 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 393 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 394 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 395 => function ($stackPos) {
            $this->semValue = new Expr\PostInc($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 396 => function ($stackPos) {
            $this->semValue = new Expr\PreInc($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 397 => function ($stackPos) {
            $this->semValue = new Expr\PostDec($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 398 => function ($stackPos) {
            $this->semValue = new Expr\PreDec($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 399 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 400 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 401 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 402 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 403 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 404 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 405 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 406 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 407 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 408 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 409 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 410 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 411 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 412 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 413 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 414 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 415 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 416 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 417 => function ($stackPos) {
            $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 418 => function ($stackPos) {
            $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 419 => function ($stackPos) {
            $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 420 => function ($stackPos) {
            $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 421 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 422 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 423 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 424 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 425 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 426 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 427 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 428 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 429 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 430 => function ($stackPos) {
            $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 431 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 432 => function ($stackPos) {
            $this->semValue = new Expr\Ternary($this->semStack[$stackPos - (5 - 1)], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 433 => function ($stackPos) {
            $this->semValue = new Expr\Ternary($this->semStack[$stackPos - (4 - 1)], null, $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 434 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 435 => function ($stackPos) {
            $this->semValue = new Expr\Isset_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 436 => function ($stackPos) {
            $this->semValue = new Expr\Empty_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 437 => function ($stackPos) {
            $this->semValue = new Expr\Include_($this->semStack[$stackPos - (2 - 2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 438 => function ($stackPos) {
            $this->semValue = new Expr\Include_($this->semStack[$stackPos - (2 - 2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 439 => function ($stackPos) {
            $this->semValue = new Expr\Eval_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 440 => function ($stackPos) {
            $this->semValue = new Expr\Include_($this->semStack[$stackPos - (2 - 2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 441 => function ($stackPos) {
            $this->semValue = new Expr\Include_($this->semStack[$stackPos - (2 - 2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 442 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 443 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes;
            $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos - (2 - 1)]);
            $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos - (2 - 2)], $attrs);
        }, 444 => function ($stackPos) {
            $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 445 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 446 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 447 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 448 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 449 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes;
            $attrs['kind'] = \strtolower($this->semStack[$stackPos - (2 - 1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
            $this->semValue = new Expr\Exit_($this->semStack[$stackPos - (2 - 2)], $attrs);
        }, 450 => function ($stackPos) {
            $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 451 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 452 => function ($stackPos) {
            $this->semValue = new Expr\ShellExec($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 453 => function ($stackPos) {
            $this->semValue = new Expr\Print_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 454 => function ($stackPos) {
            $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 455 => function ($stackPos) {
            $this->semValue = new Expr\Yield_($this->semStack[$stackPos - (2 - 2)], null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 456 => function ($stackPos) {
            $this->semValue = new Expr\Yield_($this->semStack[$stackPos - (4 - 4)], $this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 457 => function ($stackPos) {
            $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 458 => function ($stackPos) {
            $this->semValue = new Expr\Throw_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 459 => function ($stackPos) {
            $this->semValue = new Expr\ArrowFunction(['static' => \false, 'byRef' => $this->semStack[$stackPos - (8 - 2)], 'params' => $this->semStack[$stackPos - (8 - 4)], 'returnType' => $this->semStack[$stackPos - (8 - 6)], 'expr' => $this->semStack[$stackPos - (8 - 8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes);
        }, 460 => function ($stackPos) {
            $this->semValue = new Expr\ArrowFunction(['static' => \true, 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 5)], 'returnType' => $this->semStack[$stackPos - (9 - 7)], 'expr' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 461 => function ($stackPos) {
            $this->semValue = new Expr\Closure(['static' => \false, 'byRef' => $this->semStack[$stackPos - (8 - 2)], 'params' => $this->semStack[$stackPos - (8 - 4)], 'uses' => $this->semStack[$stackPos - (8 - 6)], 'returnType' => $this->semStack[$stackPos - (8 - 7)], 'stmts' => $this->semStack[$stackPos - (8 - 8)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes);
        }, 462 => function ($stackPos) {
            $this->semValue = new Expr\Closure(['static' => \true, 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 5)], 'uses' => $this->semStack[$stackPos - (9 - 7)], 'returnType' => $this->semStack[$stackPos - (9 - 8)], 'stmts' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => []], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 463 => function ($stackPos) {
            $this->semValue = new Expr\ArrowFunction(['static' => \false, 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 5)], 'returnType' => $this->semStack[$stackPos - (9 - 7)], 'expr' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => $this->semStack[$stackPos - (9 - 1)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 464 => function ($stackPos) {
            $this->semValue = new Expr\ArrowFunction(['static' => \true, 'byRef' => $this->semStack[$stackPos - (10 - 4)], 'params' => $this->semStack[$stackPos - (10 - 6)], 'returnType' => $this->semStack[$stackPos - (10 - 8)], 'expr' => $this->semStack[$stackPos - (10 - 10)], 'attrGroups' => $this->semStack[$stackPos - (10 - 1)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes);
        }, 465 => function ($stackPos) {
            $this->semValue = new Expr\Closure(['static' => \false, 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 5)], 'uses' => $this->semStack[$stackPos - (9 - 7)], 'returnType' => $this->semStack[$stackPos - (9 - 8)], 'stmts' => $this->semStack[$stackPos - (9 - 9)], 'attrGroups' => $this->semStack[$stackPos - (9 - 1)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 466 => function ($stackPos) {
            $this->semValue = new Expr\Closure(['static' => \true, 'byRef' => $this->semStack[$stackPos - (10 - 4)], 'params' => $this->semStack[$stackPos - (10 - 6)], 'uses' => $this->semStack[$stackPos - (10 - 8)], 'returnType' => $this->semStack[$stackPos - (10 - 9)], 'stmts' => $this->semStack[$stackPos - (10 - 10)], 'attrGroups' => $this->semStack[$stackPos - (10 - 1)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes);
        }, 467 => function ($stackPos) {
            $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos - (8 - 4)], 'implements' => $this->semStack[$stackPos - (8 - 5)], 'stmts' => $this->semStack[$stackPos - (8 - 7)], 'attrGroups' => $this->semStack[$stackPos - (8 - 1)]], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes), $this->semStack[$stackPos - (8 - 3)]);
            $this->checkClass($this->semValue[0], -1);
        }, 468 => function ($stackPos) {
            $this->semValue = new Expr\New_($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 469 => function ($stackPos) {
            list($class, $ctorArgs) = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 470 => function ($stackPos) {
            $this->semValue = array();
        }, 471 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 3)];
        }, 472 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 473 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 474 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 475 => function ($stackPos) {
            $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos - (2 - 2)], $this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 476 => function ($stackPos) {
            $this->semValue = new Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 477 => function ($stackPos) {
            $this->semValue = new Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 478 => function ($stackPos) {
            $this->semValue = new Expr\StaticCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 479 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 480 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 481 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 482 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 483 => function ($stackPos) {
            $this->semValue = new Name\FullyQualified(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 484 => function ($stackPos) {
            $this->semValue = new Name\Relative(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 10), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 485 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 486 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 487 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 488 => function ($stackPos) {
            $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
            $this->errorState = 2;
        }, 489 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 490 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 491 => function ($stackPos) {
            $this->semValue = null;
        }, 492 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 493 => function ($stackPos) {
            $this->semValue = array();
        }, 494 => function ($stackPos) {
            $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos - (1 - 1)], '`'), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes));
        }, 495 => function ($stackPos) {
            foreach ($this->semStack[$stackPos - (1 - 1)] as $s) {
                if ($s instanceof Node\Scalar\EncapsedStringPart) {
                    $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', \true);
                }
            }
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 496 => function ($stackPos) {
            $this->semValue = array();
        }, 497 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 498 => function ($stackPos) {
            $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 499 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 500 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 501 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 502 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 503 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 504 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 505 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 506 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 507 => function ($stackPos) {
            $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 508 => function ($stackPos) {
            $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos - (3 - 1)], new Expr\Error($this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)]), $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
            $this->errorState = 2;
        }, 509 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes;
            $attrs['kind'] = Expr\Array_::KIND_SHORT;
            $this->semValue = new Expr\Array_($this->semStack[$stackPos - (3 - 2)], $attrs);
        }, 510 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes;
            $attrs['kind'] = Expr\Array_::KIND_LONG;
            $this->semValue = new Expr\Array_($this->semStack[$stackPos - (4 - 3)], $attrs);
        }, 511 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 512 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes;
            $attrs['kind'] = $this->semStack[$stackPos - (1 - 1)][0] === "'" || $this->semStack[$stackPos - (1 - 1)][1] === "'" && ($this->semStack[$stackPos - (1 - 1)][0] === 'b' || $this->semStack[$stackPos - (1 - 1)][0] === 'B') ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED;
            $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos - (1 - 1)]), $attrs);
        }, 513 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes;
            $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
            foreach ($this->semStack[$stackPos - (3 - 2)] as $s) {
                if ($s instanceof Node\Scalar\EncapsedStringPart) {
                    $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', \true);
                }
            }
            $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos - (3 - 2)], $attrs);
        }, 514 => function ($stackPos) {
            $this->semValue = $this->parseLNumber($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 515 => function ($stackPos) {
            $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos - (1 - 1)]), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 516 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 517 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 518 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 519 => function ($stackPos) {
            $this->semValue = $this->parseDocString($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)], \true);
        }, 520 => function ($stackPos) {
            $this->semValue = $this->parseDocString($this->semStack[$stackPos - (2 - 1)], '', $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (2 - 2)] + $this->endAttributeStack[$stackPos - (2 - 2)], \true);
        }, 521 => function ($stackPos) {
            $this->semValue = $this->parseDocString($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)], \true);
        }, 522 => function ($stackPos) {
            $this->semValue = null;
        }, 523 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 524 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 525 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 526 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 527 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 528 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 529 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 530 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 531 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 532 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 533 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 534 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 535 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 536 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 537 => function ($stackPos) {
            $this->semValue = new Expr\MethodCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 538 => function ($stackPos) {
            $this->semValue = new Expr\NullsafeMethodCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 539 => function ($stackPos) {
            $this->semValue = null;
        }, 540 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 541 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 542 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 543 => function ($stackPos) {
            $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 544 => function ($stackPos) {
            $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 545 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 546 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 547 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 548 => function ($stackPos) {
            $this->semValue = new Expr\Variable(new Expr\Error($this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes), $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
            $this->errorState = 2;
        }, 549 => function ($stackPos) {
            $var = $this->semStack[$stackPos - (1 - 1)]->name;
            $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes) : $var;
        }, 550 => function ($stackPos) {
            $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 551 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 552 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 553 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 554 => function ($stackPos) {
            $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 555 => function ($stackPos) {
            $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 556 => function ($stackPos) {
            $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 557 => function ($stackPos) {
            $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 558 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 559 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 560 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 561 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 562 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 563 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 564 => function ($stackPos) {
            $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
            $this->errorState = 2;
        }, 565 => function ($stackPos) {
            $this->semValue = new Expr\List_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 566 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
            $end = \count($this->semValue) - 1;
            if ($this->semValue[$end] === null) {
                \array_pop($this->semValue);
            }
        }, 567 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 568 => function ($stackPos) {
            /* do nothing -- prevent default action of $$=$this->semStack[$1]. See $551. */
        }, 569 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 570 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 571 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 572 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (2 - 2)], null, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 573 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 574 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (3 - 3)], $this->semStack[$stackPos - (3 - 1)], \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 575 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (4 - 4)], $this->semStack[$stackPos - (4 - 1)], \true, $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 576 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (3 - 3)], $this->semStack[$stackPos - (3 - 1)], \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 577 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (2 - 2)], null, \false, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 578 => function ($stackPos) {
            $this->semValue = null;
        }, 579 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 580 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 581 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 582 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]);
        }, 583 => function ($stackPos) {
            $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 584 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 585 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 586 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 587 => function ($stackPos) {
            $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 588 => function ($stackPos) {
            $this->semValue = new Expr\NullsafePropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 589 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 590 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 591 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 4)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 592 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 593 => function ($stackPos) {
            $this->semValue = new Scalar\String_($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 594 => function ($stackPos) {
            $this->semValue = $this->parseNumString($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 595 => function ($stackPos) {
            $this->semValue = $this->parseNumString('-' . $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 596 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }];
    }
}
<?php

namespace PhabelVendor\PhpParser\Parser;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Scalar;
use PhabelVendor\PhpParser\Node\Stmt;
/* This is an automatically GENERATED file, which should not be manually edited.
 * Instead edit one of the following:
 *  * the grammar files grammar/php5.y or grammar/php7.y
 *  * the skeleton file grammar/parser.template
 *  * the preprocessing script grammar/rebuildParsers.php
 */
class Php5 extends \PhabelVendor\PhpParser\ParserAbstract
{
    protected $tokenToSymbolMapSize = 396;
    protected $actionTableSize = 1093;
    protected $gotoTableSize = 643;
    protected $invalidSymbol = 168;
    protected $errorSymbol = 1;
    protected $defaultAction = -32766;
    protected $unexpectedTokenRule = 32767;
    protected $YY2TBLSTATE = 415;
    protected $numNonLeafStates = 662;
    protected $symbolToName = array("EOF", "error", "T_THROW", "T_INCLUDE", "T_INCLUDE_ONCE", "T_EVAL", "T_REQUIRE", "T_REQUIRE_ONCE", "','", "T_LOGICAL_OR", "T_LOGICAL_XOR", "T_LOGICAL_AND", "T_PRINT", "T_YIELD", "T_DOUBLE_ARROW", "T_YIELD_FROM", "'='", "T_PLUS_EQUAL", "T_MINUS_EQUAL", "T_MUL_EQUAL", "T_DIV_EQUAL", "T_CONCAT_EQUAL", "T_MOD_EQUAL", "T_AND_EQUAL", "T_OR_EQUAL", "T_XOR_EQUAL", "T_SL_EQUAL", "T_SR_EQUAL", "T_POW_EQUAL", "T_COALESCE_EQUAL", "'?'", "':'", "T_COALESCE", "T_BOOLEAN_OR", "T_BOOLEAN_AND", "'|'", "'^'", "T_AMPERSAND_NOT_FOLLOWED_BY_VAR_OR_VARARG", "T_AMPERSAND_FOLLOWED_BY_VAR_OR_VARARG", "T_IS_EQUAL", "T_IS_NOT_EQUAL", "T_IS_IDENTICAL", "T_IS_NOT_IDENTICAL", "T_SPACESHIP", "'<'", "T_IS_SMALLER_OR_EQUAL", "'>'", "T_IS_GREATER_OR_EQUAL", "T_SL", "T_SR", "'+'", "'-'", "'.'", "'*'", "'/'", "'%'", "'!'", "T_INSTANCEOF", "'~'", "T_INC", "T_DEC", "T_INT_CAST", "T_DOUBLE_CAST", "T_STRING_CAST", "T_ARRAY_CAST", "T_OBJECT_CAST", "T_BOOL_CAST", "T_UNSET_CAST", "'@'", "T_POW", "'['", "T_NEW", "T_CLONE", "T_EXIT", "T_IF", "T_ELSEIF", "T_ELSE", "T_ENDIF", "T_LNUMBER", "T_DNUMBER", "T_STRING", "T_STRING_VARNAME", "T_VARIABLE", "T_NUM_STRING", "T_INLINE_HTML", "T_ENCAPSED_AND_WHITESPACE", "T_CONSTANT_ENCAPSED_STRING", "T_ECHO", "T_DO", "T_WHILE", "T_ENDWHILE", "T_FOR", "T_ENDFOR", "T_FOREACH", "T_ENDFOREACH", "T_DECLARE", "T_ENDDECLARE", "T_AS", "T_SWITCH", "T_MATCH", "T_ENDSWITCH", "T_CASE", "T_DEFAULT", "T_BREAK", "T_CONTINUE", "T_GOTO", "T_FUNCTION", "T_FN", "T_CONST", "T_RETURN", "T_TRY", "T_CATCH", "T_FINALLY", "T_USE", "T_INSTEADOF", "T_GLOBAL", "T_STATIC", "T_ABSTRACT", "T_FINAL", "T_PRIVATE", "T_PROTECTED", "T_PUBLIC", "T_VAR", "T_UNSET", "T_ISSET", "T_EMPTY", "T_HALT_COMPILER", "T_CLASS", "T_TRAIT", "T_INTERFACE", "T_EXTENDS", "T_IMPLEMENTS", "T_OBJECT_OPERATOR", "T_LIST", "T_ARRAY", "T_CALLABLE", "T_CLASS_C", "T_TRAIT_C", "T_METHOD_C", "T_FUNC_C", "T_LINE", "T_FILE", "T_START_HEREDOC", "T_END_HEREDOC", "T_DOLLAR_OPEN_CURLY_BRACES", "T_CURLY_OPEN", "T_PAAMAYIM_NEKUDOTAYIM", "T_NAMESPACE", "T_NS_C", "T_DIR", "T_NS_SEPARATOR", "T_ELLIPSIS", "T_NAME_FULLY_QUALIFIED", "T_NAME_QUALIFIED", "T_NAME_RELATIVE", "';'", "'{'", "'}'", "'('", "')'", "'\$'", "'`'", "']'", "'\"'", "T_READONLY", "T_ENUM", "T_NULLSAFE_OBJECT_OPERATOR", "T_ATTRIBUTE");
    protected $tokenToSymbol = array(0, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 56, 163, 168, 160, 55, 168, 168, 158, 159, 53, 50, 8, 51, 52, 54, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 31, 155, 44, 16, 46, 30, 68, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 70, 168, 162, 36, 168, 161, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 156, 35, 157, 58, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 168, 1, 2, 3, 4, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 37, 38, 39, 40, 41, 42, 43, 45, 47, 48, 49, 57, 59, 60, 61, 62, 63, 64, 65, 66, 67, 69, 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, 164, 122, 123, 124, 125, 126, 127, 128, 129, 165, 130, 131, 132, 166, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 167);
    protected $action = array(699, 669, 670, 671, 672, 673, 286, 674, 675, 676, 712, 713, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 0, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32767, -32767, -32767, -32767, 245, 246, 242, 243, 244, -32766, -32766, 677, -32766, 750, -32766, -32766, -32766, -32766, -32766, -32766, -32766, 1224, 245, 246, 1225, 678, 679, 680, 681, 682, 683, 684, -32766, 48, 746, -32766, -32766, -32766, -32766, -32766, -32766, 685, 686, 687, 688, 689, 690, 691, 692, 693, 694, 695, 715, 738, 716, 717, 718, 719, 707, 708, 709, 737, 710, 711, 696, 697, 698, 700, 701, 702, 740, 741, 742, 743, 744, 745, 703, 704, 705, 706, 736, 727, 725, 726, 722, 723, 751, 714, 720, 721, 728, 729, 731, 730, 732, 733, 55, 56, 425, 57, 58, 724, 735, 734, 1073, 59, 60, -224, 61, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32766, 121, -32767, -32767, -32767, -32767, 29, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 1043, 766, 1071, 767, 580, 62, 63, -32766, -32766, -32766, -32766, 64, 516, 65, 294, 295, 66, 67, 68, 69, 70, 71, 72, 73, 822, 25, 302, 74, 418, 981, 983, 1043, 1181, 1095, 1096, 1073, 748, 754, 1075, 1074, 1076, 469, -32766, -32766, -32766, 337, 823, 54, -32767, -32767, -32767, -32767, 98, 99, 100, 101, 102, 220, 221, 222, 78, 361, 1107, -32766, 341, -32766, -32766, -32766, -32766, -32766, 1107, 492, 949, 950, 951, 948, 947, 946, 207, 477, 478, 949, 950, 951, 948, 947, 946, 1043, 479, 480, 52, 1101, 1102, 1103, 1104, 1098, 1099, 319, 872, 668, 667, 27, -511, 1105, 1100, -32766, 130, 1075, 1074, 1076, 345, 668, 667, 41, 126, 341, 334, 369, 336, 426, -128, -128, -128, 896, 897, 468, 220, 221, 222, 811, 1195, 619, 40, 21, 427, -128, 470, -128, 471, -128, 472, -128, 802, 428, -4, 823, 54, 207, 33, 34, 429, 360, 317, 28, 35, 473, -32766, -32766, -32766, 211, 356, 357, 474, 475, -32766, -32766, -32766, 754, 476, 49, 313, 794, 843, 430, 431, 289, 125, -32766, 813, -32766, -32766, -32766, -32766, -32766, -32766, -32766, -32767, -32767, -32767, -32767, -32767, -32766, -32766, -32766, 769, 103, 104, 105, 327, 307, 825, 633, -128, 1075, 1074, 1076, 221, 222, 927, 748, 1146, 106, -32766, 129, -32766, -32766, -32766, -32766, 426, 823, 54, 902, 873, 302, 468, 75, 207, 359, 811, 668, 667, 40, 21, 427, 754, 470, 754, 471, 423, 472, 1043, 127, 428, 435, 1043, 341, 1043, 33, 34, 429, 360, 1181, 415, 35, 473, 122, 10, 315, 128, 356, 357, 474, 475, -32766, -32766, -32766, 768, 476, 668, 667, 758, 843, 430, 431, 754, 1043, 1147, -32766, -32766, -32766, 754, 419, 342, 1215, -32766, 131, -32766, -32766, -32766, 341, 363, 346, 426, 823, 54, 100, 101, 102, 468, 825, 633, -4, 811, 442, 903, 40, 21, 427, 754, 470, 435, 471, 341, 472, 341, 766, 428, 767, -209, -209, -209, 33, 34, 429, 360, 479, 1196, 35, 473, 345, -32766, -32766, -32766, 356, 357, 474, 475, 220, 221, 222, 421, 476, 32, 297, 794, 843, 430, 431, 754, 754, 435, -32766, 341, -32766, -32766, 9, 300, 51, 207, 249, 324, 753, 120, 220, 221, 222, 426, 30, 247, 941, 422, 424, 468, 825, 633, -209, 811, 1043, 1061, 40, 21, 427, 129, 470, 207, 471, 341, 472, 804, 20, 428, 124, -208, -208, -208, 33, 34, 429, 360, 479, 212, 35, 473, 923, -259, 823, 54, 356, 357, 474, 475, -32766, -32766, -32766, 1043, 476, 213, 806, 794, 843, 430, 431, -32766, -32766, 435, 435, 341, 341, 443, 79, 80, 81, -32766, 668, 667, 636, 344, 808, 668, 667, 239, 240, 241, 123, 214, 538, 250, 825, 633, -208, 36, 251, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 252, 307, 426, 220, 221, 222, 823, 54, 468, -32766, 222, 765, 811, 106, 134, 40, 21, 427, 571, 470, 207, 471, 445, 472, 207, -32766, 428, 896, 897, 207, 307, 33, 34, 429, 245, 246, 637, 35, 473, 452, 22, 809, 922, 356, 357, 457, 588, 135, 374, 595, 596, 476, -228, 759, 639, 938, 653, 926, 661, -86, 823, 54, 314, 644, 647, 821, 133, 836, 43, 106, 603, 44, 45, 46, 47, 748, 50, 53, 132, 426, 302, -32766, 520, 825, 633, 468, -84, 607, 577, 811, 641, 362, 40, 21, 427, -278, 470, 754, 471, 954, 472, 441, 627, 428, 823, 54, 574, 844, 33, 34, 429, 11, 615, 845, 35, 473, 444, 461, 285, -511, 356, 357, 592, -419, 593, 1106, 1153, -410, 476, 368, 838, 38, 658, 426, 645, 795, 1052, 0, 325, 468, 0, -32766, 0, 811, 0, 0, 40, 21, 427, 0, 470, 0, 471, 0, 472, 0, 322, 428, 823, 54, 825, 633, 33, 34, 429, 0, 326, 0, 35, 473, 323, 0, 316, 318, 356, 357, -512, 426, 0, 753, 531, 0, 476, 468, 6, 0, 0, 811, 650, 7, 40, 21, 427, 12, 470, 14, 471, 373, 472, -420, 562, 428, 823, 54, 78, -225, 33, 34, 429, 39, 656, 657, 35, 473, 859, 633, 764, 812, 356, 357, 820, 799, 814, 875, 866, 867, 476, 797, 860, 857, 855, 426, 933, 934, 931, 819, 803, 468, 805, 807, 810, 811, 930, 762, 40, 21, 427, 763, 470, 932, 471, 335, 472, 358, 634, 428, 638, 640, 825, 633, 33, 34, 429, 642, 643, 646, 35, 473, 648, 649, 651, 652, 356, 357, 635, 426, 1221, 1223, 761, 842, 476, 468, 248, 760, 841, 811, 1222, 840, 40, 21, 427, 1057, 470, 830, 471, 1045, 472, 839, 1046, 428, 828, 215, 216, 939, 33, 34, 429, 217, 864, 218, 35, 473, 825, 633, 24, 865, 356, 357, 456, 1220, 1189, 209, 1187, 1172, 476, 1185, 215, 216, 1086, 1095, 1096, 914, 217, 1193, 218, 1183, -224, 1097, 26, 31, 37, 42, 76, 77, 210, 288, 209, 292, 293, 308, 309, 310, 311, 339, 1095, 1096, 825, 633, 355, 291, 416, 1152, 1097, 16, 17, 18, 393, 453, 460, 462, 466, 552, 624, 1048, 1051, 904, 1111, 1047, 1023, 563, 1022, 1088, 0, 0, -429, 558, 1041, 1101, 1102, 1103, 1104, 1098, 1099, 398, 1054, 1053, 1056, 1055, 1070, 1105, 1100, 1186, 1171, 1167, 1184, 1085, 1218, 1112, 1166, 219, 558, 599, 1101, 1102, 1103, 1104, 1098, 1099, 398, 0, 0, 0, 0, 0, 1105, 1100, 0, 0, 0, 0, 0, 0, 0, 0, 219);
    protected $actionCheck = array(2, 3, 4, 5, 6, 7, 14, 9, 10, 11, 12, 13, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 0, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 9, 10, 11, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 69, 70, 53, 54, 55, 9, 10, 57, 30, 80, 32, 33, 34, 35, 36, 37, 38, 80, 69, 70, 83, 71, 72, 73, 74, 75, 76, 77, 9, 70, 80, 33, 34, 35, 36, 37, 38, 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, 153, 133, 134, 135, 136, 137, 138, 139, 140, 141, 3, 4, 5, 6, 7, 147, 148, 149, 80, 12, 13, 159, 15, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 156, 44, 45, 46, 47, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 13, 106, 116, 108, 85, 50, 51, 33, 34, 35, 36, 56, 85, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 1, 70, 71, 72, 73, 59, 60, 13, 82, 78, 79, 80, 80, 82, 152, 153, 154, 86, 9, 10, 11, 8, 1, 2, 44, 45, 46, 47, 48, 49, 50, 51, 52, 9, 10, 11, 156, 106, 143, 30, 160, 32, 33, 34, 35, 36, 143, 116, 116, 117, 118, 119, 120, 121, 30, 124, 125, 116, 117, 118, 119, 120, 121, 13, 133, 134, 70, 136, 137, 138, 139, 140, 141, 142, 31, 37, 38, 8, 132, 148, 149, 116, 156, 152, 153, 154, 160, 37, 38, 158, 8, 160, 161, 8, 163, 74, 75, 76, 77, 134, 135, 80, 9, 10, 11, 84, 1, 80, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 155, 98, 0, 1, 2, 30, 103, 104, 105, 106, 132, 8, 109, 110, 9, 10, 11, 8, 115, 116, 117, 118, 9, 10, 11, 82, 123, 70, 8, 126, 127, 128, 129, 8, 156, 30, 155, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 9, 10, 11, 157, 53, 54, 55, 8, 57, 155, 156, 157, 152, 153, 154, 10, 11, 157, 80, 162, 69, 30, 151, 32, 33, 34, 35, 74, 1, 2, 159, 155, 71, 80, 151, 30, 8, 84, 37, 38, 87, 88, 89, 82, 91, 82, 93, 8, 95, 13, 156, 98, 158, 13, 160, 13, 103, 104, 105, 106, 82, 108, 109, 110, 156, 8, 113, 31, 115, 116, 117, 118, 9, 10, 11, 157, 123, 37, 38, 126, 127, 128, 129, 82, 13, 159, 33, 34, 35, 82, 127, 8, 85, 30, 156, 32, 33, 34, 160, 8, 147, 74, 1, 2, 50, 51, 52, 80, 155, 156, 157, 84, 31, 159, 87, 88, 89, 82, 91, 158, 93, 160, 95, 160, 106, 98, 108, 100, 101, 102, 103, 104, 105, 106, 133, 159, 109, 110, 160, 9, 10, 11, 115, 116, 117, 118, 9, 10, 11, 8, 123, 144, 145, 126, 127, 128, 129, 82, 82, 158, 30, 160, 32, 33, 108, 8, 70, 30, 31, 113, 152, 16, 9, 10, 11, 74, 14, 14, 122, 8, 8, 80, 155, 156, 157, 84, 13, 159, 87, 88, 89, 151, 91, 30, 93, 160, 95, 155, 159, 98, 14, 100, 101, 102, 103, 104, 105, 106, 133, 16, 109, 110, 155, 157, 1, 2, 115, 116, 117, 118, 9, 10, 11, 13, 123, 16, 155, 126, 127, 128, 129, 33, 34, 158, 158, 160, 160, 156, 9, 10, 11, 30, 37, 38, 31, 70, 155, 37, 38, 50, 51, 52, 156, 16, 81, 16, 155, 156, 157, 30, 16, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 16, 57, 74, 9, 10, 11, 1, 2, 80, 116, 11, 155, 84, 69, 156, 87, 88, 89, 160, 91, 30, 93, 132, 95, 30, 33, 98, 134, 135, 30, 57, 103, 104, 105, 69, 70, 31, 109, 110, 75, 76, 155, 155, 115, 116, 75, 76, 101, 102, 111, 112, 123, 159, 155, 156, 155, 156, 155, 156, 31, 1, 2, 31, 31, 31, 31, 31, 38, 70, 69, 77, 70, 70, 70, 70, 80, 70, 70, 70, 74, 71, 85, 85, 155, 156, 80, 97, 96, 100, 84, 31, 106, 87, 88, 89, 82, 91, 82, 93, 82, 95, 89, 92, 98, 1, 2, 90, 127, 103, 104, 105, 97, 94, 127, 109, 110, 97, 97, 97, 132, 115, 116, 100, 146, 113, 143, 143, 146, 123, 106, 151, 155, 157, 74, 31, 157, 162, -1, 114, 80, -1, 116, -1, 84, -1, -1, 87, 88, 89, -1, 91, -1, 93, -1, 95, -1, 130, 98, 1, 2, 155, 156, 103, 104, 105, -1, 130, -1, 109, 110, 131, -1, 132, 132, 115, 116, 132, 74, -1, 152, 150, -1, 123, 80, 146, -1, -1, 84, 31, 146, 87, 88, 89, 146, 91, 146, 93, 146, 95, 146, 150, 98, 1, 2, 156, 159, 103, 104, 105, 155, 155, 155, 109, 110, 155, 156, 155, 155, 115, 116, 155, 155, 155, 155, 155, 155, 123, 155, 155, 155, 155, 74, 155, 155, 155, 155, 155, 80, 155, 155, 155, 84, 155, 155, 87, 88, 89, 155, 91, 155, 93, 156, 95, 156, 156, 98, 156, 156, 155, 156, 103, 104, 105, 156, 156, 156, 109, 110, 156, 156, 156, 156, 115, 116, 156, 74, 157, 157, 157, 157, 123, 80, 31, 157, 157, 84, 157, 157, 87, 88, 89, 157, 91, 157, 93, 157, 95, 157, 157, 98, 157, 50, 51, 157, 103, 104, 105, 56, 157, 58, 109, 110, 155, 156, 158, 157, 115, 116, 157, 157, 157, 70, 157, 157, 123, 157, 50, 51, 157, 78, 79, 157, 56, 157, 58, 157, 159, 86, 158, 158, 158, 158, 158, 158, 158, 158, 70, 158, 158, 158, 158, 158, 158, 158, 78, 79, 155, 156, 158, 160, 158, 163, 86, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, 159, -1, -1, 161, 134, 161, 136, 137, 138, 139, 140, 141, 142, 162, 162, 162, 162, 162, 148, 149, 162, 162, 162, 162, 162, 162, 162, 162, 158, 134, 162, 136, 137, 138, 139, 140, 141, 142, -1, -1, -1, -1, -1, 148, 149, -1, -1, -1, -1, -1, -1, -1, -1, 158);
    protected $actionBase = array(0, 227, 326, 400, 474, 233, 132, 132, 752, -2, -2, 138, -2, -2, -2, 663, 761, 815, 761, 586, 717, 859, 859, 859, 244, 256, 256, 256, 413, 583, 583, 880, 546, 169, 415, 444, 409, 200, 200, 200, 200, 137, 137, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, 249, 205, 738, 559, 535, 739, 741, 742, 876, 679, 877, 820, 821, 693, 823, 824, 826, 829, 832, 819, 834, 907, 836, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 67, 536, 299, 510, 230, 44, 652, 652, 652, 652, 652, 652, 652, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 337, 378, 584, 584, 584, 657, 909, 648, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 934, 503, -21, -21, 436, 650, 364, 571, 215, 426, 156, 26, 26, 329, 329, 329, 329, 329, 46, 46, 5, 5, 5, 5, 152, 186, 186, 186, 186, 120, 120, 120, 120, 374, 374, 429, 448, 448, 334, 267, 449, 449, 449, 449, 449, 449, 449, 449, 449, 449, 336, 427, 427, 572, 572, 408, 551, 551, 551, 551, 671, 171, 171, 391, 311, 311, 311, 109, 641, 856, 68, 68, 68, 68, 68, 68, 324, 324, 324, -3, -3, -3, 655, 77, 380, 77, 380, 683, 685, 86, 685, 654, -15, 516, 776, 281, 646, 809, 680, 816, 560, 711, 202, 578, 857, 643, -23, 578, 578, 578, 578, 857, 622, 628, 596, -23, 578, -23, 639, 454, 849, 351, 249, 558, 469, 631, 743, 514, 688, 746, 464, 544, 548, 556, 7, 412, 708, 750, 878, 879, 349, 702, 631, 631, 631, 327, 101, 7, -8, 623, 623, 623, 623, 219, 623, 623, 623, 623, 291, 430, 545, 401, 745, 653, 653, 675, 839, 814, 814, 653, 673, 653, 675, 841, 841, 841, 841, 653, 653, 653, 653, 814, 814, 667, 814, 275, 684, 694, 694, 841, 713, 714, 653, 653, 697, 814, 814, 814, 697, 687, 841, 669, 637, 333, 814, 841, 689, 673, 689, 653, 669, 689, 673, 673, 689, 22, 686, 656, 840, 842, 860, 756, 638, 644, 847, 848, 843, 845, 838, 692, 719, 720, 528, 659, 660, 661, 662, 696, 664, 698, 643, 658, 658, 658, 645, 701, 645, 658, 658, 658, 658, 658, 658, 658, 658, 632, 635, 709, 699, 670, 723, 566, 582, 758, 640, 636, 872, 865, 881, 883, 849, 870, 645, 890, 634, 288, 610, 850, 633, 753, 645, 851, 645, 759, 645, 873, 777, 666, 778, 779, 658, 874, 891, 892, 893, 894, 897, 898, 899, 900, 665, 901, 724, 674, 866, 344, 844, 639, 705, 677, 755, 725, 780, 372, 902, 784, 645, 645, 765, 706, 645, 766, 726, 712, 862, 727, 867, 903, 640, 678, 868, 645, 681, 785, 904, 372, 690, 651, 704, 649, 728, 858, 875, 853, 767, 612, 617, 787, 788, 792, 691, 730, 863, 864, 835, 731, 770, 642, 771, 676, 794, 772, 852, 732, 796, 798, 871, 647, 707, 682, 672, 668, 773, 799, 869, 733, 735, 736, 801, 737, 804, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 137, 137, 137, 137, -2, -2, -2, -2, 0, 0, -2, 0, 0, 0, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 0, 0, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 137, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 602, -21, -21, -21, -21, 602, -21, -21, -21, -21, -21, -21, -21, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, -21, 602, 602, 602, -21, 68, -21, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 602, 0, 0, 602, -21, 602, -21, 602, -21, -21, 602, 602, 602, 602, 602, 602, 602, -21, -21, -21, -21, -21, -21, 0, 324, 324, 324, 324, -21, -21, -21, -21, 68, 68, 147, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 324, 324, -3, -3, 68, 68, 68, 68, 68, 147, 68, 68, -23, 673, 673, 673, 380, 380, 380, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 380, -23, 0, -23, 0, 68, -23, 673, -23, 380, 673, 673, -23, 814, 604, 604, 604, 604, 372, 7, 0, 0, 673, 673, 0, 0, 0, 0, 0, 673, 0, 0, 0, 0, 0, 0, 814, 0, 653, 0, 0, 0, 0, 658, 288, 0, 677, 456, 0, 0, 0, 0, 0, 0, 677, 456, 530, 530, 0, 665, 658, 658, 658, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 372);
    protected $actionDefault = array(3, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 540, 540, 495, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 297, 297, 297, 32767, 32767, 32767, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 528, 32767, 32767, 32767, 32767, 32767, 32767, 381, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 387, 545, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 362, 363, 365, 366, 296, 548, 529, 245, 388, 544, 295, 247, 325, 499, 32767, 32767, 32767, 327, 122, 256, 201, 498, 125, 294, 232, 380, 382, 326, 301, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 300, 454, 359, 358, 357, 456, 32767, 455, 492, 492, 495, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 323, 483, 482, 324, 452, 328, 453, 331, 457, 460, 329, 330, 347, 348, 345, 346, 349, 458, 459, 476, 477, 474, 475, 299, 350, 351, 352, 353, 478, 479, 480, 481, 32767, 32767, 280, 539, 539, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 338, 339, 467, 468, 32767, 236, 236, 236, 236, 281, 236, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 333, 334, 332, 462, 463, 461, 428, 32767, 32767, 32767, 430, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 500, 32767, 32767, 32767, 32767, 32767, 513, 417, 171, 32767, 409, 32767, 171, 171, 171, 171, 32767, 220, 222, 167, 32767, 171, 32767, 486, 32767, 32767, 32767, 32767, 32767, 518, 343, 32767, 32767, 116, 32767, 32767, 32767, 555, 32767, 513, 32767, 116, 32767, 32767, 32767, 32767, 356, 335, 336, 337, 32767, 32767, 517, 511, 470, 471, 472, 473, 32767, 464, 465, 466, 469, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 425, 431, 431, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 516, 515, 32767, 410, 494, 186, 184, 184, 32767, 206, 206, 32767, 32767, 188, 487, 506, 32767, 188, 173, 32767, 398, 175, 494, 32767, 32767, 238, 32767, 238, 32767, 398, 238, 32767, 32767, 238, 32767, 411, 435, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 377, 378, 489, 502, 32767, 503, 32767, 409, 341, 342, 344, 320, 32767, 322, 367, 368, 369, 370, 371, 372, 373, 375, 32767, 415, 32767, 418, 32767, 32767, 32767, 255, 32767, 553, 32767, 32767, 304, 553, 32767, 32767, 32767, 547, 32767, 32767, 298, 32767, 32767, 32767, 32767, 251, 32767, 169, 32767, 537, 32767, 554, 32767, 511, 32767, 340, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 512, 32767, 32767, 32767, 32767, 227, 32767, 448, 32767, 116, 32767, 32767, 32767, 187, 32767, 32767, 302, 246, 32767, 32767, 546, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 114, 32767, 170, 32767, 32767, 32767, 189, 32767, 32767, 511, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 293, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 511, 32767, 32767, 231, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 411, 32767, 274, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 32767, 127, 127, 3, 127, 127, 258, 3, 258, 127, 258, 258, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 214, 217, 206, 206, 164, 127, 127, 266);
    protected $goto = array(166, 140, 140, 140, 166, 187, 168, 144, 147, 141, 142, 143, 149, 163, 163, 163, 163, 144, 144, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 165, 138, 159, 160, 161, 162, 184, 139, 185, 493, 494, 377, 495, 499, 500, 501, 502, 503, 504, 505, 506, 967, 164, 145, 146, 148, 171, 176, 186, 203, 253, 256, 258, 260, 263, 264, 265, 266, 267, 268, 269, 277, 278, 279, 280, 303, 304, 328, 329, 330, 394, 395, 396, 542, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 150, 151, 152, 167, 153, 169, 154, 204, 170, 155, 156, 157, 205, 158, 136, 620, 560, 756, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 560, 1108, 628, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 1108, 757, 888, 888, 508, 1200, 1200, 400, 606, 508, 536, 536, 568, 532, 534, 534, 496, 498, 524, 540, 569, 572, 583, 590, 852, 852, 852, 852, 847, 853, 174, 585, 519, 600, 601, 177, 178, 179, 401, 402, 403, 404, 173, 202, 206, 208, 257, 259, 261, 262, 270, 271, 272, 273, 274, 275, 281, 282, 283, 284, 305, 306, 331, 332, 333, 406, 407, 408, 409, 175, 180, 254, 255, 181, 182, 183, 497, 497, 785, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, 509, 578, 582, 626, 749, 509, 544, 545, 546, 547, 548, 549, 550, 551, 553, 586, 338, 559, 321, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 559, 530, 349, 655, 555, 587, 352, 414, 591, 575, 604, 885, 611, 612, 881, 616, 617, 623, 625, 630, 632, 298, 296, 296, 296, 298, 290, 299, 944, 610, 816, 1170, 613, 436, 436, 375, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, 1072, 1084, 1083, 945, 1065, 1072, 895, 895, 895, 895, 1178, 895, 895, 1212, 1212, 1178, 388, 858, 561, 755, 1072, 1072, 1072, 1072, 1072, 1072, 3, 4, 384, 384, 384, 1212, 874, 856, 854, 856, 654, 465, 511, 883, 878, 1089, 541, 384, 537, 384, 567, 384, 1026, 19, 15, 371, 384, 1226, 510, 1204, 1192, 1192, 1192, 510, 906, 372, 522, 533, 554, 912, 514, 1068, 1069, 13, 1065, 378, 912, 1158, 594, 23, 965, 386, 386, 386, 602, 1066, 1169, 1066, 937, 447, 449, 631, 752, 1177, 1067, 1109, 614, 935, 1177, 605, 1197, 391, 1211, 1211, 543, 892, 386, 1194, 1194, 1194, 399, 518, 1016, 901, 389, 771, 529, 752, 340, 752, 1211, 518, 518, 385, 781, 1214, 770, 772, 1063, 910, 774, 1058, 1176, 659, 953, 514, 782, 862, 915, 450, 573, 1155, 0, 463, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 513, 528, 0, 0, 0, 0, 513, 0, 528, 0, 350, 351, 0, 609, 512, 515, 438, 439, 1064, 618, 0, 0, 0, 0, 0, 0, 0, 0, 0, 779, 1219, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 777, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 523, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 301, 301);
    protected $gotoCheck = array(43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 57, 68, 15, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 68, 126, 9, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 16, 76, 76, 68, 76, 76, 51, 51, 68, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 68, 68, 68, 68, 68, 68, 27, 66, 101, 66, 66, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 117, 117, 29, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 117, 61, 61, 61, 6, 117, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 125, 57, 125, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 32, 71, 32, 32, 69, 69, 69, 32, 40, 40, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 5, 5, 5, 5, 5, 5, 5, 97, 62, 50, 81, 62, 57, 57, 62, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 124, 124, 97, 81, 57, 57, 57, 57, 57, 118, 57, 57, 142, 142, 118, 12, 33, 12, 14, 57, 57, 57, 57, 57, 57, 30, 30, 13, 13, 13, 142, 14, 14, 14, 14, 14, 57, 14, 14, 14, 34, 2, 13, 109, 13, 2, 13, 34, 34, 34, 34, 13, 13, 122, 140, 9, 9, 9, 122, 83, 58, 58, 58, 34, 13, 13, 81, 81, 58, 81, 46, 13, 131, 127, 34, 101, 123, 123, 123, 34, 81, 81, 81, 8, 8, 8, 8, 11, 119, 81, 8, 8, 8, 119, 49, 138, 48, 141, 141, 47, 78, 123, 119, 119, 119, 123, 47, 102, 80, 17, 23, 9, 11, 18, 11, 141, 47, 47, 11, 23, 141, 23, 24, 115, 84, 25, 113, 119, 73, 99, 13, 26, 70, 85, 64, 65, 130, -1, 108, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, 9, -1, 9, -1, 71, 71, -1, 13, 9, 9, 9, 9, 13, 13, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 9, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 101, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 5, 5);
    protected $gotoBase = array(0, 0, -184, 0, 0, 356, 290, 0, 488, 149, 0, 182, 85, 118, 426, 112, 203, 179, 208, 0, 0, 0, 0, 162, 190, 198, 120, 27, 0, 272, -224, 0, -274, 406, 32, 0, 0, 0, 0, 0, 330, 0, 0, -24, 0, 0, 440, 485, 213, 218, 371, -74, 0, 0, 0, 0, 0, 107, 110, 0, 0, -11, -72, 0, 104, 95, -405, 0, -94, 41, 119, -82, 0, 164, 0, 0, -79, 0, 197, 0, 204, 43, 0, 441, 171, 121, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 115, 0, 195, 210, 0, 0, 0, 0, 0, 86, 427, 259, 0, 0, 116, 0, 174, 0, -5, 117, 196, 0, 0, 161, 170, 93, -21, -48, 273, 0, 0, 91, 271, 0, 0, 0, 0, 0, 0, 216, 0, 437, 187, 102, 0, 0);
    protected $gotoDefault = array(-32768, 467, 663, 2, 664, 834, 739, 747, 597, 481, 629, 581, 380, 1188, 791, 792, 793, 381, 367, 482, 379, 410, 405, 780, 773, 775, 783, 172, 411, 786, 1, 788, 517, 824, 1017, 364, 796, 365, 589, 798, 526, 800, 801, 137, 382, 383, 527, 483, 390, 576, 815, 276, 387, 817, 366, 818, 827, 370, 464, 454, 459, 556, 608, 432, 446, 570, 564, 535, 1081, 565, 861, 348, 869, 660, 877, 880, 484, 557, 891, 451, 899, 1094, 397, 905, 911, 916, 287, 919, 417, 412, 584, 924, 925, 5, 929, 621, 622, 8, 312, 952, 598, 966, 420, 1036, 1038, 485, 486, 521, 458, 507, 525, 487, 1059, 440, 413, 1062, 488, 489, 433, 434, 1078, 354, 1163, 353, 448, 320, 1150, 579, 1113, 455, 1203, 1159, 347, 490, 491, 376, 1182, 392, 1198, 437, 1205, 1213, 343, 539, 566);
    protected $ruleToNonTerminal = array(0, 1, 3, 3, 2, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 9, 10, 11, 11, 12, 12, 13, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 18, 18, 19, 19, 21, 21, 17, 17, 22, 22, 23, 23, 24, 24, 25, 25, 20, 20, 26, 28, 28, 29, 30, 30, 32, 31, 31, 31, 31, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, 14, 14, 54, 54, 56, 55, 55, 48, 48, 58, 58, 59, 59, 60, 60, 15, 16, 16, 16, 63, 63, 63, 64, 64, 67, 67, 65, 65, 69, 69, 41, 41, 50, 50, 53, 53, 53, 52, 52, 70, 42, 42, 42, 42, 71, 71, 72, 72, 73, 73, 39, 39, 35, 35, 74, 37, 37, 75, 36, 36, 38, 38, 49, 49, 49, 61, 61, 77, 77, 78, 78, 80, 80, 80, 79, 79, 62, 62, 81, 81, 81, 82, 82, 83, 83, 83, 44, 44, 84, 84, 84, 45, 45, 85, 85, 86, 86, 66, 87, 87, 87, 87, 92, 92, 93, 93, 94, 94, 94, 94, 94, 95, 96, 96, 91, 91, 88, 88, 90, 90, 98, 98, 97, 97, 97, 97, 97, 97, 89, 89, 100, 99, 99, 46, 46, 40, 40, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 43, 34, 34, 47, 47, 105, 105, 106, 106, 106, 106, 112, 101, 101, 108, 108, 114, 114, 115, 116, 116, 116, 116, 116, 116, 68, 68, 57, 57, 57, 57, 102, 102, 120, 120, 117, 117, 121, 121, 121, 121, 103, 103, 103, 107, 107, 107, 113, 113, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, 27, 27, 27, 27, 27, 27, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 111, 111, 104, 104, 104, 104, 127, 127, 130, 130, 129, 129, 131, 131, 51, 51, 51, 51, 133, 133, 132, 132, 132, 132, 132, 134, 134, 119, 119, 122, 122, 118, 118, 136, 135, 135, 135, 135, 123, 123, 123, 123, 110, 110, 124, 124, 124, 124, 76, 137, 137, 138, 138, 138, 109, 109, 139, 139, 140, 140, 140, 140, 140, 125, 125, 125, 125, 142, 143, 141, 141, 141, 141, 141, 141, 141, 144, 144, 144);
    protected $ruleToLength = array(1, 1, 2, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 5, 4, 3, 4, 2, 3, 1, 1, 7, 6, 3, 1, 3, 1, 3, 1, 1, 3, 1, 3, 1, 2, 3, 1, 3, 3, 1, 3, 2, 0, 1, 1, 1, 1, 1, 3, 5, 8, 3, 5, 9, 3, 2, 3, 2, 3, 2, 3, 3, 3, 3, 1, 2, 2, 5, 7, 9, 5, 6, 3, 3, 2, 2, 1, 1, 1, 0, 2, 8, 0, 4, 1, 3, 0, 1, 0, 1, 0, 1, 10, 7, 6, 5, 1, 2, 2, 0, 2, 0, 2, 0, 2, 1, 3, 1, 4, 1, 4, 1, 1, 4, 1, 3, 3, 3, 4, 4, 5, 0, 2, 4, 3, 1, 1, 1, 4, 0, 2, 3, 0, 2, 4, 0, 2, 0, 3, 1, 2, 1, 1, 0, 1, 3, 4, 6, 1, 1, 1, 0, 1, 0, 2, 2, 3, 3, 1, 3, 1, 2, 2, 3, 1, 1, 2, 4, 3, 1, 1, 3, 2, 0, 1, 3, 3, 9, 3, 1, 3, 0, 2, 4, 5, 4, 4, 4, 3, 1, 1, 1, 3, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 3, 3, 1, 0, 1, 1, 3, 3, 4, 4, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 5, 4, 3, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 3, 2, 1, 2, 10, 11, 3, 3, 2, 4, 4, 3, 4, 4, 4, 4, 7, 3, 2, 0, 4, 1, 3, 2, 2, 4, 6, 2, 2, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, 0, 2, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 1, 3, 1, 4, 3, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 4, 3, 1, 3, 1, 1, 3, 3, 0, 2, 0, 1, 3, 1, 3, 1, 1, 1, 1, 1, 6, 4, 3, 4, 2, 4, 4, 1, 3, 1, 2, 1, 1, 4, 1, 1, 3, 6, 4, 4, 4, 4, 1, 4, 0, 1, 1, 3, 1, 1, 4, 3, 1, 1, 1, 0, 0, 2, 3, 1, 3, 1, 4, 2, 2, 2, 2, 1, 2, 1, 1, 1, 4, 3, 3, 3, 6, 3, 1, 1, 1);
    /**
     *
     */
    protected function initReduceCallbacks()
    {
        $this->reduceCallbacks = [0 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 1 => function ($stackPos) {
            $this->semValue = $this->handleNamespaces($this->semStack[$stackPos - (1 - 1)]);
        }, 2 => function ($stackPos) {
            if (\is_array($this->semStack[$stackPos - (2 - 2)])) {
                $this->semValue = \array_merge($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]);
            } else {
                $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
                $this->semValue = $this->semStack[$stackPos - (2 - 1)];
            }
        }, 3 => function ($stackPos) {
            $this->semValue = array();
        }, 4 => function ($stackPos) {
            $startAttributes = $this->lookaheadStartAttributes;
            if (isset($startAttributes['comments'])) {
                $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments']));
            } else {
                $nop = null;
            }
            if ($nop !== null) {
                $this->semStack[$stackPos - (1 - 1)][] = $nop;
            }
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 5 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 6 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 7 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 8 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 9 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 10 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 11 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 12 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 13 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 14 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 15 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 16 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 17 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 18 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 19 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 20 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 21 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 22 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 23 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 24 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 25 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 26 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 27 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 28 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 29 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 30 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 31 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 32 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 33 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 34 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 35 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 36 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 37 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 38 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 39 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 40 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 41 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 42 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 43 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 44 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 45 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 46 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 47 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 48 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 49 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 50 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 51 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 52 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 53 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 54 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 55 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 56 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 57 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 58 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 59 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 60 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 61 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 62 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 63 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 64 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 65 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 66 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 67 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 68 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 69 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 70 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 71 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 72 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 73 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 74 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 75 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 76 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 77 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 78 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 79 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 80 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 81 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 82 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 83 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 84 => function ($stackPos) {
            $this->semValue = new Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 85 => function ($stackPos) {
            $this->semValue = new Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 86 => function ($stackPos) {
            $this->semValue = new Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 87 => function ($stackPos) {
            $this->semValue = new Node\Identifier($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 88 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 89 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 90 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 91 => function ($stackPos) {
            $this->semValue = new Name(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 92 => function ($stackPos) {
            $this->semValue = new Expr\Variable(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 93 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 94 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 95 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 96 => function ($stackPos) {
            $this->semValue = new Stmt\HaltCompiler($this->lexer->handleHaltCompiler(), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 97 => function ($stackPos) {
            $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos - (3 - 2)], null, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_SEMICOLON);
            $this->checkNamespace($this->semValue);
        }, 98 => function ($stackPos) {
            $this->semValue = new Stmt\Namespace_($this->semStack[$stackPos - (5 - 2)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
            $this->checkNamespace($this->semValue);
        }, 99 => function ($stackPos) {
            $this->semValue = new Stmt\Namespace_(null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
            $this->semValue->setAttribute('kind', Stmt\Namespace_::KIND_BRACED);
            $this->checkNamespace($this->semValue);
        }, 100 => function ($stackPos) {
            $this->semValue = new Stmt\Use_($this->semStack[$stackPos - (3 - 2)], Stmt\Use_::TYPE_NORMAL, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 101 => function ($stackPos) {
            $this->semValue = new Stmt\Use_($this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 102 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 103 => function ($stackPos) {
            $this->semValue = new Stmt\Const_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 104 => function ($stackPos) {
            $this->semValue = Stmt\Use_::TYPE_FUNCTION;
        }, 105 => function ($stackPos) {
            $this->semValue = Stmt\Use_::TYPE_CONSTANT;
        }, 106 => function ($stackPos) {
            $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 6)], $this->semStack[$stackPos - (7 - 2)], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
        }, 107 => function ($stackPos) {
            $this->semValue = new Stmt\GroupUse($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 5)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 108 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 109 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 110 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 111 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 112 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 113 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 114 => function ($stackPos) {
            $this->semValue = new Stmt\UseUse($this->semStack[$stackPos - (1 - 1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
            $this->checkUseUse($this->semValue, $stackPos - (1 - 1));
        }, 115 => function ($stackPos) {
            $this->semValue = new Stmt\UseUse($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
            $this->checkUseUse($this->semValue, $stackPos - (3 - 3));
        }, 116 => function ($stackPos) {
            $this->semValue = new Stmt\UseUse($this->semStack[$stackPos - (1 - 1)], null, Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
            $this->checkUseUse($this->semValue, $stackPos - (1 - 1));
        }, 117 => function ($stackPos) {
            $this->semValue = new Stmt\UseUse($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], Stmt\Use_::TYPE_UNKNOWN, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
            $this->checkUseUse($this->semValue, $stackPos - (3 - 3));
        }, 118 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
            $this->semValue->type = Stmt\Use_::TYPE_NORMAL;
        }, 119 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue->type = $this->semStack[$stackPos - (2 - 1)];
        }, 120 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 121 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 122 => function ($stackPos) {
            $this->semValue = new Node\Const_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 123 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 124 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 125 => function ($stackPos) {
            $this->semValue = new Node\Const_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 126 => function ($stackPos) {
            if (\is_array($this->semStack[$stackPos - (2 - 2)])) {
                $this->semValue = \array_merge($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]);
            } else {
                $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
                $this->semValue = $this->semStack[$stackPos - (2 - 1)];
            }
        }, 127 => function ($stackPos) {
            $this->semValue = array();
        }, 128 => function ($stackPos) {
            $startAttributes = $this->lookaheadStartAttributes;
            if (isset($startAttributes['comments'])) {
                $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments']));
            } else {
                $nop = null;
            }
            if ($nop !== null) {
                $this->semStack[$stackPos - (1 - 1)][] = $nop;
            }
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 129 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 130 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 131 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 132 => function ($stackPos) {
            throw new Error('__HALT_COMPILER() can only be used from the outermost scope', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 133 => function ($stackPos) {
            if ($this->semStack[$stackPos - (3 - 2)]) {
                $this->semValue = $this->semStack[$stackPos - (3 - 2)];
                $attrs = $this->startAttributeStack[$stackPos - (3 - 1)];
                $stmts = $this->semValue;
                if (!empty($attrs['comments'])) {
                    $stmts[0]->setAttribute('comments', \array_merge($attrs['comments'], $stmts[0]->getAttribute('comments', [])));
                }
            } else {
                $startAttributes = $this->startAttributeStack[$stackPos - (3 - 1)];
                if (isset($startAttributes['comments'])) {
                    $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes);
                } else {
                    $this->semValue = null;
                }
                if (null === $this->semValue) {
                    $this->semValue = array();
                }
            }
        }, 134 => function ($stackPos) {
            $this->semValue = new Stmt\If_($this->semStack[$stackPos - (5 - 2)], ['stmts' => \is_array($this->semStack[$stackPos - (5 - 3)]) ? $this->semStack[$stackPos - (5 - 3)] : array($this->semStack[$stackPos - (5 - 3)]), 'elseifs' => $this->semStack[$stackPos - (5 - 4)], 'else' => $this->semStack[$stackPos - (5 - 5)]], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 135 => function ($stackPos) {
            $this->semValue = new Stmt\If_($this->semStack[$stackPos - (8 - 2)], ['stmts' => $this->semStack[$stackPos - (8 - 4)], 'elseifs' => $this->semStack[$stackPos - (8 - 5)], 'else' => $this->semStack[$stackPos - (8 - 6)]], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes);
        }, 136 => function ($stackPos) {
            $this->semValue = new Stmt\While_($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 137 => function ($stackPos) {
            $this->semValue = new Stmt\Do_($this->semStack[$stackPos - (5 - 4)], \is_array($this->semStack[$stackPos - (5 - 2)]) ? $this->semStack[$stackPos - (5 - 2)] : array($this->semStack[$stackPos - (5 - 2)]), $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 138 => function ($stackPos) {
            $this->semValue = new Stmt\For_(['init' => $this->semStack[$stackPos - (9 - 3)], 'cond' => $this->semStack[$stackPos - (9 - 5)], 'loop' => $this->semStack[$stackPos - (9 - 7)], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 139 => function ($stackPos) {
            $this->semValue = new Stmt\Switch_($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 140 => function ($stackPos) {
            $this->semValue = new Stmt\Break_(null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 141 => function ($stackPos) {
            $this->semValue = new Stmt\Break_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 142 => function ($stackPos) {
            $this->semValue = new Stmt\Continue_(null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 143 => function ($stackPos) {
            $this->semValue = new Stmt\Continue_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 144 => function ($stackPos) {
            $this->semValue = new Stmt\Return_(null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 145 => function ($stackPos) {
            $this->semValue = new Stmt\Return_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 146 => function ($stackPos) {
            $this->semValue = new Stmt\Global_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 147 => function ($stackPos) {
            $this->semValue = new Stmt\Static_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 148 => function ($stackPos) {
            $this->semValue = new Stmt\Echo_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 149 => function ($stackPos) {
            $this->semValue = new Stmt\InlineHTML($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 150 => function ($stackPos) {
            $this->semValue = new Stmt\Expression($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 151 => function ($stackPos) {
            $this->semValue = new Stmt\Expression($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 152 => function ($stackPos) {
            $this->semValue = new Stmt\Unset_($this->semStack[$stackPos - (5 - 3)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 153 => function ($stackPos) {
            $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos - (7 - 3)], $this->semStack[$stackPos - (7 - 5)][0], ['keyVar' => null, 'byRef' => $this->semStack[$stackPos - (7 - 5)][1], 'stmts' => $this->semStack[$stackPos - (7 - 7)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
        }, 154 => function ($stackPos) {
            $this->semValue = new Stmt\Foreach_($this->semStack[$stackPos - (9 - 3)], $this->semStack[$stackPos - (9 - 7)][0], ['keyVar' => $this->semStack[$stackPos - (9 - 5)], 'byRef' => $this->semStack[$stackPos - (9 - 7)][1], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
        }, 155 => function ($stackPos) {
            $this->semValue = new Stmt\Declare_($this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 156 => function ($stackPos) {
            $this->semValue = new Stmt\TryCatch($this->semStack[$stackPos - (6 - 3)], $this->semStack[$stackPos - (6 - 5)], $this->semStack[$stackPos - (6 - 6)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
            $this->checkTryCatch($this->semValue);
        }, 157 => function ($stackPos) {
            $this->semValue = new Stmt\Throw_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 158 => function ($stackPos) {
            $this->semValue = new Stmt\Goto_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 159 => function ($stackPos) {
            $this->semValue = new Stmt\Label($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 160 => function ($stackPos) {
            $this->semValue = new Stmt\Expression($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 161 => function ($stackPos) {
            $this->semValue = array();
            /* means: no statement */
        }, 162 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 163 => function ($stackPos) {
            $startAttributes = $this->startAttributeStack[$stackPos - (1 - 1)];
            if (isset($startAttributes['comments'])) {
                $this->semValue = new Stmt\Nop($startAttributes + $this->endAttributes);
            } else {
                $this->semValue = null;
            }
            if ($this->semValue === null) {
                $this->semValue = array();
            }
            /* means: no statement */
        }, 164 => function ($stackPos) {
            $this->semValue = array();
        }, 165 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 166 => function ($stackPos) {
            $this->semValue = new Stmt\Catch_(array($this->semStack[$stackPos - (8 - 3)]), $this->semStack[$stackPos - (8 - 4)], $this->semStack[$stackPos - (8 - 7)], $this->startAttributeStack[$stackPos - (8 - 1)] + $this->endAttributes);
        }, 167 => function ($stackPos) {
            $this->semValue = null;
        }, 168 => function ($stackPos) {
            $this->semValue = new Stmt\Finally_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 169 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 170 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 171 => function ($stackPos) {
            $this->semValue = \false;
        }, 172 => function ($stackPos) {
            $this->semValue = \true;
        }, 173 => function ($stackPos) {
            $this->semValue = \false;
        }, 174 => function ($stackPos) {
            $this->semValue = \true;
        }, 175 => function ($stackPos) {
            $this->semValue = \false;
        }, 176 => function ($stackPos) {
            $this->semValue = \true;
        }, 177 => function ($stackPos) {
            $this->semValue = new Stmt\Function_($this->semStack[$stackPos - (10 - 3)], ['byRef' => $this->semStack[$stackPos - (10 - 2)], 'params' => $this->semStack[$stackPos - (10 - 5)], 'returnType' => $this->semStack[$stackPos - (10 - 7)], 'stmts' => $this->semStack[$stackPos - (10 - 9)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes);
        }, 178 => function ($stackPos) {
            $this->semValue = new Stmt\Class_($this->semStack[$stackPos - (7 - 2)], ['type' => $this->semStack[$stackPos - (7 - 1)], 'extends' => $this->semStack[$stackPos - (7 - 3)], 'implements' => $this->semStack[$stackPos - (7 - 4)], 'stmts' => $this->semStack[$stackPos - (7 - 6)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes);
            $this->checkClass($this->semValue, $stackPos - (7 - 2));
        }, 179 => function ($stackPos) {
            $this->semValue = new Stmt\Interface_($this->semStack[$stackPos - (6 - 2)], ['extends' => $this->semStack[$stackPos - (6 - 3)], 'stmts' => $this->semStack[$stackPos - (6 - 5)]], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
            $this->checkInterface($this->semValue, $stackPos - (6 - 2));
        }, 180 => function ($stackPos) {
            $this->semValue = new Stmt\Trait_($this->semStack[$stackPos - (5 - 2)], ['stmts' => $this->semStack[$stackPos - (5 - 4)]], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 181 => function ($stackPos) {
            $this->semValue = 0;
        }, 182 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
        }, 183 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_FINAL;
        }, 184 => function ($stackPos) {
            $this->semValue = null;
        }, 185 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 186 => function ($stackPos) {
            $this->semValue = array();
        }, 187 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 188 => function ($stackPos) {
            $this->semValue = array();
        }, 189 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 190 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 191 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 192 => function ($stackPos) {
            $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]);
        }, 193 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 194 => function ($stackPos) {
            $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]);
        }, 195 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 196 => function ($stackPos) {
            $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]);
        }, 197 => function ($stackPos) {
            $this->semValue = null;
        }, 198 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 199 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 200 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 201 => function ($stackPos) {
            $this->semValue = new Stmt\DeclareDeclare($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 202 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 203 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 3)];
        }, 204 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 205 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (5 - 3)];
        }, 206 => function ($stackPos) {
            $this->semValue = array();
        }, 207 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 208 => function ($stackPos) {
            $this->semValue = new Stmt\Case_($this->semStack[$stackPos - (4 - 2)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 209 => function ($stackPos) {
            $this->semValue = new Stmt\Case_(null, $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 210 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 211 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 212 => function ($stackPos) {
            $this->semValue = \is_array($this->semStack[$stackPos - (1 - 1)]) ? $this->semStack[$stackPos - (1 - 1)] : array($this->semStack[$stackPos - (1 - 1)]);
        }, 213 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 2)];
        }, 214 => function ($stackPos) {
            $this->semValue = array();
        }, 215 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 216 => function ($stackPos) {
            $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos - (3 - 2)], \is_array($this->semStack[$stackPos - (3 - 3)]) ? $this->semStack[$stackPos - (3 - 3)] : array($this->semStack[$stackPos - (3 - 3)]), $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 217 => function ($stackPos) {
            $this->semValue = array();
        }, 218 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 219 => function ($stackPos) {
            $this->semValue = new Stmt\ElseIf_($this->semStack[$stackPos - (4 - 2)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 220 => function ($stackPos) {
            $this->semValue = null;
        }, 221 => function ($stackPos) {
            $this->semValue = new Stmt\Else_(\is_array($this->semStack[$stackPos - (2 - 2)]) ? $this->semStack[$stackPos - (2 - 2)] : array($this->semStack[$stackPos - (2 - 2)]), $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 222 => function ($stackPos) {
            $this->semValue = null;
        }, 223 => function ($stackPos) {
            $this->semValue = new Stmt\Else_($this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 224 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false);
        }, 225 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (2 - 2)], \true);
        }, 226 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)], \false);
        }, 227 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 228 => function ($stackPos) {
            $this->semValue = array();
        }, 229 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 230 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 231 => function ($stackPos) {
            $this->semValue = new Node\Param($this->semStack[$stackPos - (4 - 4)], null, $this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 2)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
            $this->checkParam($this->semValue);
        }, 232 => function ($stackPos) {
            $this->semValue = new Node\Param($this->semStack[$stackPos - (6 - 4)], $this->semStack[$stackPos - (6 - 6)], $this->semStack[$stackPos - (6 - 1)], $this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 3)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
            $this->checkParam($this->semValue);
        }, 233 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 234 => function ($stackPos) {
            $this->semValue = new Node\Identifier('array', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 235 => function ($stackPos) {
            $this->semValue = new Node\Identifier('callable', $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 236 => function ($stackPos) {
            $this->semValue = null;
        }, 237 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 238 => function ($stackPos) {
            $this->semValue = null;
        }, 239 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 2)];
        }, 240 => function ($stackPos) {
            $this->semValue = array();
        }, 241 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 242 => function ($stackPos) {
            $this->semValue = array(new Node\Arg($this->semStack[$stackPos - (3 - 2)], \false, \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes));
        }, 243 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 244 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 245 => function ($stackPos) {
            $this->semValue = new Node\Arg($this->semStack[$stackPos - (1 - 1)], \false, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 246 => function ($stackPos) {
            $this->semValue = new Node\Arg($this->semStack[$stackPos - (2 - 2)], \true, \false, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 247 => function ($stackPos) {
            $this->semValue = new Node\Arg($this->semStack[$stackPos - (2 - 2)], \false, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 248 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 249 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 250 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 251 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 252 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 253 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 254 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 255 => function ($stackPos) {
            $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos - (1 - 1)], null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 256 => function ($stackPos) {
            $this->semValue = new Stmt\StaticVar($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 257 => function ($stackPos) {
            if ($this->semStack[$stackPos - (2 - 2)] !== null) {
                $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
                $this->semValue = $this->semStack[$stackPos - (2 - 1)];
            }
        }, 258 => function ($stackPos) {
            $this->semValue = array();
        }, 259 => function ($stackPos) {
            $startAttributes = $this->lookaheadStartAttributes;
            if (isset($startAttributes['comments'])) {
                $nop = new Stmt\Nop($this->createCommentNopAttributes($startAttributes['comments']));
            } else {
                $nop = null;
            }
            if ($nop !== null) {
                $this->semStack[$stackPos - (1 - 1)][] = $nop;
            }
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 260 => function ($stackPos) {
            $this->semValue = new Stmt\Property($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
            $this->checkProperty($this->semValue, $stackPos - (3 - 1));
        }, 261 => function ($stackPos) {
            $this->semValue = new Stmt\ClassConst($this->semStack[$stackPos - (3 - 2)], 0, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 262 => function ($stackPos) {
            $this->semValue = new Stmt\ClassMethod($this->semStack[$stackPos - (9 - 4)], ['type' => $this->semStack[$stackPos - (9 - 1)], 'byRef' => $this->semStack[$stackPos - (9 - 3)], 'params' => $this->semStack[$stackPos - (9 - 6)], 'returnType' => $this->semStack[$stackPos - (9 - 8)], 'stmts' => $this->semStack[$stackPos - (9 - 9)]], $this->startAttributeStack[$stackPos - (9 - 1)] + $this->endAttributes);
            $this->checkClassMethod($this->semValue, $stackPos - (9 - 1));
        }, 263 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUse($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 264 => function ($stackPos) {
            $this->semValue = array();
        }, 265 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 266 => function ($stackPos) {
            $this->semValue = array();
        }, 267 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 268 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Precedence($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 269 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (5 - 1)][0], $this->semStack[$stackPos - (5 - 1)][1], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 4)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 270 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], $this->semStack[$stackPos - (4 - 3)], null, $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 271 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 272 => function ($stackPos) {
            $this->semValue = new Stmt\TraitUseAdaptation\Alias($this->semStack[$stackPos - (4 - 1)][0], $this->semStack[$stackPos - (4 - 1)][1], null, $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 273 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)]);
        }, 274 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 275 => function ($stackPos) {
            $this->semValue = array(null, $this->semStack[$stackPos - (1 - 1)]);
        }, 276 => function ($stackPos) {
            $this->semValue = null;
        }, 277 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 278 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 279 => function ($stackPos) {
            $this->semValue = 0;
        }, 280 => function ($stackPos) {
            $this->semValue = 0;
        }, 281 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 282 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 283 => function ($stackPos) {
            $this->checkModifier($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $stackPos - (2 - 2));
            $this->semValue = $this->semStack[$stackPos - (2 - 1)] | $this->semStack[$stackPos - (2 - 2)];
        }, 284 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PUBLIC;
        }, 285 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PROTECTED;
        }, 286 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_PRIVATE;
        }, 287 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_STATIC;
        }, 288 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_ABSTRACT;
        }, 289 => function ($stackPos) {
            $this->semValue = Stmt\Class_::MODIFIER_FINAL;
        }, 290 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 291 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 292 => function ($stackPos) {
            $this->semValue = new Node\VarLikeIdentifier(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 293 => function ($stackPos) {
            $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos - (1 - 1)], null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 294 => function ($stackPos) {
            $this->semValue = new Stmt\PropertyProperty($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 295 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 296 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 297 => function ($stackPos) {
            $this->semValue = array();
        }, 298 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 299 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 300 => function ($stackPos) {
            $this->semValue = new Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 301 => function ($stackPos) {
            $this->semValue = new Expr\Assign($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 302 => function ($stackPos) {
            $this->semValue = new Expr\AssignRef($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 303 => function ($stackPos) {
            $this->semValue = new Expr\AssignRef($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 304 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 305 => function ($stackPos) {
            $this->semValue = new Expr\Clone_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 306 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 307 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 308 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 309 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 310 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 311 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 312 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 313 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 314 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 315 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 316 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 317 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 318 => function ($stackPos) {
            $this->semValue = new Expr\AssignOp\Coalesce($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 319 => function ($stackPos) {
            $this->semValue = new Expr\PostInc($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 320 => function ($stackPos) {
            $this->semValue = new Expr\PreInc($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 321 => function ($stackPos) {
            $this->semValue = new Expr\PostDec($this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 322 => function ($stackPos) {
            $this->semValue = new Expr\PreDec($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 323 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 324 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 325 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 326 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 327 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 328 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 329 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 330 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 331 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 332 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 333 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 334 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 335 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 336 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 337 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 338 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 339 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 340 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 341 => function ($stackPos) {
            $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 342 => function ($stackPos) {
            $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 343 => function ($stackPos) {
            $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 344 => function ($stackPos) {
            $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 345 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 346 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 347 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 348 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 349 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Spaceship($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 350 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 351 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 352 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 353 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 354 => function ($stackPos) {
            $this->semValue = new Expr\Instanceof_($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 355 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 356 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 357 => function ($stackPos) {
            $this->semValue = new Expr\Ternary($this->semStack[$stackPos - (5 - 1)], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 358 => function ($stackPos) {
            $this->semValue = new Expr\Ternary($this->semStack[$stackPos - (4 - 1)], null, $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 359 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Coalesce($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 360 => function ($stackPos) {
            $this->semValue = new Expr\Isset_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 361 => function ($stackPos) {
            $this->semValue = new Expr\Empty_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 362 => function ($stackPos) {
            $this->semValue = new Expr\Include_($this->semStack[$stackPos - (2 - 2)], Expr\Include_::TYPE_INCLUDE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 363 => function ($stackPos) {
            $this->semValue = new Expr\Include_($this->semStack[$stackPos - (2 - 2)], Expr\Include_::TYPE_INCLUDE_ONCE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 364 => function ($stackPos) {
            $this->semValue = new Expr\Eval_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 365 => function ($stackPos) {
            $this->semValue = new Expr\Include_($this->semStack[$stackPos - (2 - 2)], Expr\Include_::TYPE_REQUIRE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 366 => function ($stackPos) {
            $this->semValue = new Expr\Include_($this->semStack[$stackPos - (2 - 2)], Expr\Include_::TYPE_REQUIRE_ONCE, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 367 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Int_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 368 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes;
            $attrs['kind'] = $this->getFloatCastKind($this->semStack[$stackPos - (2 - 1)]);
            $this->semValue = new Expr\Cast\Double($this->semStack[$stackPos - (2 - 2)], $attrs);
        }, 369 => function ($stackPos) {
            $this->semValue = new Expr\Cast\String_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 370 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Array_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 371 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Object_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 372 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Bool_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 373 => function ($stackPos) {
            $this->semValue = new Expr\Cast\Unset_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 374 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes;
            $attrs['kind'] = \strtolower($this->semStack[$stackPos - (2 - 1)]) === 'exit' ? Expr\Exit_::KIND_EXIT : Expr\Exit_::KIND_DIE;
            $this->semValue = new Expr\Exit_($this->semStack[$stackPos - (2 - 2)], $attrs);
        }, 375 => function ($stackPos) {
            $this->semValue = new Expr\ErrorSuppress($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 376 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 377 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 378 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 379 => function ($stackPos) {
            $this->semValue = new Expr\ShellExec($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 380 => function ($stackPos) {
            $this->semValue = new Expr\Print_($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 381 => function ($stackPos) {
            $this->semValue = new Expr\Yield_(null, null, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 382 => function ($stackPos) {
            $this->semValue = new Expr\YieldFrom($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 383 => function ($stackPos) {
            $this->semValue = new Expr\Closure(['static' => \false, 'byRef' => $this->semStack[$stackPos - (10 - 2)], 'params' => $this->semStack[$stackPos - (10 - 4)], 'uses' => $this->semStack[$stackPos - (10 - 6)], 'returnType' => $this->semStack[$stackPos - (10 - 7)], 'stmts' => $this->semStack[$stackPos - (10 - 9)]], $this->startAttributeStack[$stackPos - (10 - 1)] + $this->endAttributes);
        }, 384 => function ($stackPos) {
            $this->semValue = new Expr\Closure(['static' => \true, 'byRef' => $this->semStack[$stackPos - (11 - 3)], 'params' => $this->semStack[$stackPos - (11 - 5)], 'uses' => $this->semStack[$stackPos - (11 - 7)], 'returnType' => $this->semStack[$stackPos - (11 - 8)], 'stmts' => $this->semStack[$stackPos - (11 - 10)]], $this->startAttributeStack[$stackPos - (11 - 1)] + $this->endAttributes);
        }, 385 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 386 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 387 => function ($stackPos) {
            $this->semValue = new Expr\Yield_($this->semStack[$stackPos - (2 - 2)], null, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 388 => function ($stackPos) {
            $this->semValue = new Expr\Yield_($this->semStack[$stackPos - (4 - 4)], $this->semStack[$stackPos - (4 - 2)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 389 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes;
            $attrs['kind'] = Expr\Array_::KIND_LONG;
            $this->semValue = new Expr\Array_($this->semStack[$stackPos - (4 - 3)], $attrs);
        }, 390 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes;
            $attrs['kind'] = Expr\Array_::KIND_SHORT;
            $this->semValue = new Expr\Array_($this->semStack[$stackPos - (3 - 2)], $attrs);
        }, 391 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 392 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes;
            $attrs['kind'] = $this->semStack[$stackPos - (4 - 1)][0] === "'" || $this->semStack[$stackPos - (4 - 1)][1] === "'" && ($this->semStack[$stackPos - (4 - 1)][0] === 'b' || $this->semStack[$stackPos - (4 - 1)][0] === 'B') ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED;
            $this->semValue = new Expr\ArrayDimFetch(new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos - (4 - 1)]), $attrs), $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 393 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 394 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 395 => function ($stackPos) {
            $this->semValue = array(new Stmt\Class_(null, ['type' => 0, 'extends' => $this->semStack[$stackPos - (7 - 3)], 'implements' => $this->semStack[$stackPos - (7 - 4)], 'stmts' => $this->semStack[$stackPos - (7 - 6)]], $this->startAttributeStack[$stackPos - (7 - 1)] + $this->endAttributes), $this->semStack[$stackPos - (7 - 2)]);
            $this->checkClass($this->semValue[0], -1);
        }, 396 => function ($stackPos) {
            $this->semValue = new Expr\New_($this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 397 => function ($stackPos) {
            list($class, $ctorArgs) = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = new Expr\New_($class, $ctorArgs, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 398 => function ($stackPos) {
            $this->semValue = array();
        }, 399 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (4 - 3)];
        }, 400 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 401 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 402 => function ($stackPos) {
            $this->semValue = new Expr\ClosureUse($this->semStack[$stackPos - (2 - 2)], $this->semStack[$stackPos - (2 - 1)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 403 => function ($stackPos) {
            $this->semValue = new Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 404 => function ($stackPos) {
            $this->semValue = new Expr\StaticCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 405 => function ($stackPos) {
            $this->semValue = new Expr\StaticCall($this->semStack[$stackPos - (6 - 1)], $this->semStack[$stackPos - (6 - 4)], $this->semStack[$stackPos - (6 - 6)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 406 => function ($stackPos) {
            $this->semValue = $this->fixupPhp5StaticPropCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 407 => function ($stackPos) {
            $this->semValue = new Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 408 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 409 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 410 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 411 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 412 => function ($stackPos) {
            $this->semValue = new Name($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 413 => function ($stackPos) {
            $this->semValue = new Name\FullyQualified(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 414 => function ($stackPos) {
            $this->semValue = new Name\Relative(\Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 10), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 415 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 416 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 417 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 418 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 419 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 420 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 421 => function ($stackPos) {
            $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 422 => function ($stackPos) {
            $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 423 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 424 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 425 => function ($stackPos) {
            $this->semValue = null;
        }, 426 => function ($stackPos) {
            $this->semValue = null;
        }, 427 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 428 => function ($stackPos) {
            $this->semValue = array();
        }, 429 => function ($stackPos) {
            $this->semValue = array(new Scalar\EncapsedStringPart(Scalar\String_::parseEscapeSequences($this->semStack[$stackPos - (1 - 1)], '`', \false), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes));
        }, 430 => function ($stackPos) {
            foreach ($this->semStack[$stackPos - (1 - 1)] as $s) {
                if ($s instanceof Node\Scalar\EncapsedStringPart) {
                    $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '`', \false);
                }
            }
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 431 => function ($stackPos) {
            $this->semValue = array();
        }, 432 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 433 => function ($stackPos) {
            $this->semValue = $this->parseLNumber($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes, \true);
        }, 434 => function ($stackPos) {
            $this->semValue = new Scalar\DNumber(Scalar\DNumber::parse($this->semStack[$stackPos - (1 - 1)]), $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 435 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes;
            $attrs['kind'] = $this->semStack[$stackPos - (1 - 1)][0] === "'" || $this->semStack[$stackPos - (1 - 1)][1] === "'" && ($this->semStack[$stackPos - (1 - 1)][0] === 'b' || $this->semStack[$stackPos - (1 - 1)][0] === 'B') ? Scalar\String_::KIND_SINGLE_QUOTED : Scalar\String_::KIND_DOUBLE_QUOTED;
            $this->semValue = new Scalar\String_(Scalar\String_::parse($this->semStack[$stackPos - (1 - 1)], \false), $attrs);
        }, 436 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Line($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 437 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\File($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 438 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Dir($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 439 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Class_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 440 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Trait_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 441 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Method($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 442 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Function_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 443 => function ($stackPos) {
            $this->semValue = new Scalar\MagicConst\Namespace_($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 444 => function ($stackPos) {
            $this->semValue = $this->parseDocString($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)], \false);
        }, 445 => function ($stackPos) {
            $this->semValue = $this->parseDocString($this->semStack[$stackPos - (2 - 1)], '', $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (2 - 2)] + $this->endAttributeStack[$stackPos - (2 - 2)], \false);
        }, 446 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 447 => function ($stackPos) {
            $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 448 => function ($stackPos) {
            $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 449 => function ($stackPos) {
            $this->semValue = new Expr\Array_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 450 => function ($stackPos) {
            $this->semValue = new Expr\Array_($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 451 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 452 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BooleanOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 453 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BooleanAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 454 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 455 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 456 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\LogicalXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 457 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseOr($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 458 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 459 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseAnd($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 460 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\BitwiseXor($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 461 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Concat($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 462 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Plus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 463 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Minus($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 464 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Mul($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 465 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Div($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 466 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Mod($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 467 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\ShiftLeft($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 468 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\ShiftRight($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 469 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Pow($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 470 => function ($stackPos) {
            $this->semValue = new Expr\UnaryPlus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 471 => function ($stackPos) {
            $this->semValue = new Expr\UnaryMinus($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 472 => function ($stackPos) {
            $this->semValue = new Expr\BooleanNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 473 => function ($stackPos) {
            $this->semValue = new Expr\BitwiseNot($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 474 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Identical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 475 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\NotIdentical($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 476 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Equal($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 477 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\NotEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 478 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Smaller($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 479 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\SmallerOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 480 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\Greater($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 481 => function ($stackPos) {
            $this->semValue = new Expr\BinaryOp\GreaterOrEqual($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 482 => function ($stackPos) {
            $this->semValue = new Expr\Ternary($this->semStack[$stackPos - (5 - 1)], $this->semStack[$stackPos - (5 - 3)], $this->semStack[$stackPos - (5 - 5)], $this->startAttributeStack[$stackPos - (5 - 1)] + $this->endAttributes);
        }, 483 => function ($stackPos) {
            $this->semValue = new Expr\Ternary($this->semStack[$stackPos - (4 - 1)], null, $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 484 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 485 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 486 => function ($stackPos) {
            $this->semValue = new Expr\ConstFetch($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 487 => function ($stackPos) {
            $this->semValue = new Expr\ClassConstFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 488 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 489 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 490 => function ($stackPos) {
            $attrs = $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes;
            $attrs['kind'] = Scalar\String_::KIND_DOUBLE_QUOTED;
            foreach ($this->semStack[$stackPos - (3 - 2)] as $s) {
                if ($s instanceof Node\Scalar\EncapsedStringPart) {
                    $s->value = Node\Scalar\String_::parseEscapeSequences($s->value, '"', \true);
                }
            }
            $this->semValue = new Scalar\Encapsed($this->semStack[$stackPos - (3 - 2)], $attrs);
        }, 491 => function ($stackPos) {
            $this->semValue = $this->parseDocString($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 2)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes, $this->startAttributeStack[$stackPos - (3 - 3)] + $this->endAttributeStack[$stackPos - (3 - 3)], \true);
        }, 492 => function ($stackPos) {
            $this->semValue = array();
        }, 493 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 494 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 495 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos];
        }, 496 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 497 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 498 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (3 - 3)], $this->semStack[$stackPos - (3 - 1)], \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 499 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 500 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 501 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 502 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 503 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 504 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 5)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 505 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 506 => function ($stackPos) {
            $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 507 => function ($stackPos) {
            $this->semValue = new Expr\MethodCall($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 508 => function ($stackPos) {
            $this->semValue = new Expr\FuncCall($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 509 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 510 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 511 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 512 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 513 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 514 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (2 - 2)], $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 515 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 516 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 517 => function ($stackPos) {
            $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 4)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 518 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 519 => function ($stackPos) {
            $var = \Phabel\Target\Php80\Polyfill::substr($this->semStack[$stackPos - (1 - 1)], 1);
            $this->semValue = \is_string($var) ? new Node\VarLikeIdentifier($var, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes) : $var;
        }, 520 => function ($stackPos) {
            $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 521 => function ($stackPos) {
            $this->semValue = new Expr\StaticPropertyFetch($this->semStack[$stackPos - (6 - 1)], $this->semStack[$stackPos - (6 - 5)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 522 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 523 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 524 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 525 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 526 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 527 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 528 => function ($stackPos) {
            $this->semValue = null;
        }, 529 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 530 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 531 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 532 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 533 => function ($stackPos) {
            $this->semValue = new Expr\Error($this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
            $this->errorState = 2;
        }, 534 => function ($stackPos) {
            $this->semValue = new Expr\List_($this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 535 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 536 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 537 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 538 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 539 => function ($stackPos) {
            $this->semValue = null;
        }, 540 => function ($stackPos) {
            $this->semValue = array();
        }, 541 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 542 => function ($stackPos) {
            $this->semStack[$stackPos - (3 - 1)][] = $this->semStack[$stackPos - (3 - 3)];
            $this->semValue = $this->semStack[$stackPos - (3 - 1)];
        }, 543 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 544 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (3 - 3)], $this->semStack[$stackPos - (3 - 1)], \false, $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 545 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (1 - 1)], null, \false, $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 546 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (4 - 4)], $this->semStack[$stackPos - (4 - 1)], \true, $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 547 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (2 - 2)], null, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 548 => function ($stackPos) {
            $this->semValue = new Expr\ArrayItem($this->semStack[$stackPos - (2 - 2)], null, \false, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes, \true, $this->startAttributeStack[$stackPos - (2 - 1)] + $this->endAttributes);
        }, 549 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 550 => function ($stackPos) {
            $this->semStack[$stackPos - (2 - 1)][] = $this->semStack[$stackPos - (2 - 2)];
            $this->semValue = $this->semStack[$stackPos - (2 - 1)];
        }, 551 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (1 - 1)]);
        }, 552 => function ($stackPos) {
            $this->semValue = array($this->semStack[$stackPos - (2 - 1)], $this->semStack[$stackPos - (2 - 2)]);
        }, 553 => function ($stackPos) {
            $this->semValue = new Scalar\EncapsedStringPart($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 554 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 555 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }, 556 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (4 - 1)], $this->semStack[$stackPos - (4 - 3)], $this->startAttributeStack[$stackPos - (4 - 1)] + $this->endAttributes);
        }, 557 => function ($stackPos) {
            $this->semValue = new Expr\PropertyFetch($this->semStack[$stackPos - (3 - 1)], $this->semStack[$stackPos - (3 - 3)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 558 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 559 => function ($stackPos) {
            $this->semValue = new Expr\Variable($this->semStack[$stackPos - (3 - 2)], $this->startAttributeStack[$stackPos - (3 - 1)] + $this->endAttributes);
        }, 560 => function ($stackPos) {
            $this->semValue = new Expr\ArrayDimFetch($this->semStack[$stackPos - (6 - 2)], $this->semStack[$stackPos - (6 - 4)], $this->startAttributeStack[$stackPos - (6 - 1)] + $this->endAttributes);
        }, 561 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (3 - 2)];
        }, 562 => function ($stackPos) {
            $this->semValue = new Scalar\String_($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 563 => function ($stackPos) {
            $this->semValue = $this->parseNumString($this->semStack[$stackPos - (1 - 1)], $this->startAttributeStack[$stackPos - (1 - 1)] + $this->endAttributes);
        }, 564 => function ($stackPos) {
            $this->semValue = $this->semStack[$stackPos - (1 - 1)];
        }];
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\Parser;

use PhabelVendor\PhpParser\Error;
use PhabelVendor\PhpParser\ErrorHandler;
use PhabelVendor\PhpParser\Parser;
class Multiple implements Parser
{
    /** @var Parser[] List of parsers to try, in order of preference */
    private $parsers;
    /**
    * Create a parser which will try multiple parsers in an order of preference.
    *
    * Parsers will be invoked in the order they're provided to the constructor. If one of the
    parsers runs without throwing, it's output is returned. Otherwise the exception that the
    first parser generated is thrown.
    *
    * @param Parser[] $parsers
    */
    public function __construct(array $parsers)
    {
        $this->parsers = $parsers;
    }
    /**
     *
     */
    public function parse(string $code, ErrorHandler $errorHandler = null)
    {
        if (null === $errorHandler) {
            $errorHandler = new ErrorHandler\Throwing();
        }
        list($firstStmts, $firstError) = $this->tryParse($this->parsers[0], $errorHandler, $code);
        if ($firstError === null) {
            return $firstStmts;
        }
        for ($i = 1, $c = \count($this->parsers); $i < $c; ++$i) {
            list($stmts, $error) = $this->tryParse($this->parsers[$i], $errorHandler, $code);
            if ($error === null) {
                return $stmts;
            }
        }
        throw $firstError;
    }
    /**
     *
     */
    private function tryParse(Parser $parser, ErrorHandler $errorHandler, $code)
    {
        $stmts = null;
        $error = null;
        try {
            $stmts = $parser->parse($code, $errorHandler);
        } catch (Error $error) {
        }
        return [$stmts, $error];
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

interface ErrorHandler
{
    /**
     * Handle an error generated during lexing, parsing or some other operation.
     *
     * @param Error $error The error that needs to be handled
     */
    public function handleError(Error $error);
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

class ParserFactory
{
    const PREFER_PHP7 = 1;
    const PREFER_PHP5 = 2;
    const ONLY_PHP7 = 3;
    const ONLY_PHP5 = 4;
    /**
     * Creates a Parser instance, according to the provided kind.
     *
     * @param int $kind One of ::PREFER_PHP7, ::PREFER_PHP5, ::ONLY_PHP7 or ::ONLY_PHP5
     * @param (Lexer | null) $lexer Lexer to use. Defaults to emulative lexer when not specified
     * @param array $parserOptions Parser options. See ParserAbstract::__construct() argument
     *
     * @return Parser The parser instance
     */
    public function create(int $kind, Lexer $lexer = null, array $parserOptions = []) : Parser
    {
        if (null === $lexer) {
            $lexer = new Lexer\Emulative();
        }
        switch ($kind) {
            case self::PREFER_PHP7:
                return new Parser\Multiple([new Parser\Php7($lexer, $parserOptions), new Parser\Php5($lexer, $parserOptions)]);
            case self::PREFER_PHP5:
                return new Parser\Multiple([new Parser\Php5($lexer, $parserOptions), new Parser\Php7($lexer, $parserOptions)]);
            case self::ONLY_PHP7:
                return new Parser\Php7($lexer, $parserOptions);
            case self::ONLY_PHP5:
                return new Parser\Php5($lexer, $parserOptions);
            default:
                throw new \LogicException('Kind must be one of ::PREFER_PHP7, ::PREFER_PHP5, ::ONLY_PHP7 or ::ONLY_PHP5');
        }
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

/**
 * @codeCoverageIgnore
 */
class NodeVisitorAbstract implements NodeVisitor
{
    /**
     *
     */
    public function beforeTraverse(array $nodes)
    {
        return null;
    }
    /**
     *
     */
    public function enterNode(Node $node)
    {
        return null;
    }
    /**
     *
     */
    public function leaveNode(Node $node)
    {
        return null;
    }
    /**
     *
     */
    public function afterTraverse(array $nodes)
    {
        return null;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

interface NodeTraverserInterface
{
    /**
     * Adds a visitor.
     *
     * @param NodeVisitor $visitor Visitor to add
     */
    public function addVisitor(NodeVisitor $visitor);
    /**
     * Removes an added visitor.
     *
     * @param NodeVisitor $visitor
     */
    public function removeVisitor(NodeVisitor $visitor);
    /**
     * Traverses an array of nodes using the registered visitors.
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return Node[] Traversed array of nodes
     */
    public function traverse(array $nodes) : array;
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

class NodeTraverser implements NodeTraverserInterface
{
    /**
     * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CHILDREN, child nodes
     * of the current node will not be traversed for any visitors.
     *
     * For subsequent visitors enterNode() will still be called on the current
     * node and leaveNode() will also be invoked for the current node.
     */
    const DONT_TRAVERSE_CHILDREN = 1;
    /**
     * If NodeVisitor::enterNode() or NodeVisitor::leaveNode() returns
     * STOP_TRAVERSAL, traversal is aborted.
     *
     * The afterTraverse() method will still be invoked.
     */
    const STOP_TRAVERSAL = 2;
    /**
     * If NodeVisitor::leaveNode() returns REMOVE_NODE for a node that occurs
     * in an array, it will be removed from the array.
     *
     * For subsequent visitors leaveNode() will still be invoked for the
     * removed node.
     */
    const REMOVE_NODE = 3;
    /**
     * If NodeVisitor::enterNode() returns DONT_TRAVERSE_CURRENT_AND_CHILDREN, child nodes
     * of the current node will not be traversed for any visitors.
     *
     * For subsequent visitors enterNode() will not be called as well.
     * leaveNode() will be invoked for visitors that has enterNode() method invoked.
     */
    const DONT_TRAVERSE_CURRENT_AND_CHILDREN = 4;
    /** @var NodeVisitor[] Visitors */
    protected $visitors = [];
    /** @var bool Whether traversal should be stopped */
    protected $stopTraversal;
    /**
     *
     */
    public function __construct()
    {
        // for BC
    }
    /**
     * Adds a visitor.
     *
     * @param NodeVisitor $visitor Visitor to add
     */
    public function addVisitor(NodeVisitor $visitor)
    {
        $this->visitors[] = $visitor;
    }
    /**
     * Removes an added visitor.
     *
     * @param NodeVisitor $visitor
     */
    public function removeVisitor(NodeVisitor $visitor)
    {
        foreach ($this->visitors as $index => $storedVisitor) {
            if ($storedVisitor === $visitor) {
                unset($this->visitors[$index]);
                break;
            }
        }
    }
    /**
     * Traverses an array of nodes using the registered visitors.
     *
     * @param Node[] $nodes Array of nodes
     *
     * @return Node[] Traversed array of nodes
     */
    public function traverse(array $nodes) : array
    {
        $this->stopTraversal = \false;
        foreach ($this->visitors as $visitor) {
            if (null !== ($return = $visitor->beforeTraverse($nodes))) {
                $nodes = $return;
            }
        }
        $nodes = $this->traverseArray($nodes);
        foreach ($this->visitors as $visitor) {
            if (null !== ($return = $visitor->afterTraverse($nodes))) {
                $nodes = $return;
            }
        }
        return $nodes;
    }
    /**
     * Recursively traverse a node.
     *
     * @param Node $node Node to traverse.
     *
     * @return Node Result of traversal (may be original node or new one)
     */
    protected function traverseNode(Node $node) : Node
    {
        foreach ($node->getSubNodeNames() as $name) {
            $subNode =& $node->{$name};
            if (\is_array($subNode)) {
                $subNode = $this->traverseArray($subNode);
                if ($this->stopTraversal) {
                    break;
                }
            } elseif ($subNode instanceof Node) {
                $traverseChildren = \true;
                $breakVisitorIndex = null;
                foreach ($this->visitors as $visitorIndex => $visitor) {
                    $return = $visitor->enterNode($subNode);
                    if (null !== $return) {
                        if ($return instanceof Node) {
                            $this->ensureReplacementReasonable($subNode, $return);
                            $subNode = $return;
                        } elseif (self::DONT_TRAVERSE_CHILDREN === $return) {
                            $traverseChildren = \false;
                        } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) {
                            $traverseChildren = \false;
                            $breakVisitorIndex = $visitorIndex;
                            break;
                        } elseif (self::STOP_TRAVERSAL === $return) {
                            $this->stopTraversal = \true;
                            break 2;
                        } else {
                            throw new \LogicException('enterNode() returned invalid value of type ' . \gettype($return));
                        }
                    }
                }
                if ($traverseChildren) {
                    $subNode = $this->traverseNode($subNode);
                    if ($this->stopTraversal) {
                        break;
                    }
                }
                foreach ($this->visitors as $visitorIndex => $visitor) {
                    $return = $visitor->leaveNode($subNode);
                    if (null !== $return) {
                        if ($return instanceof Node) {
                            $this->ensureReplacementReasonable($subNode, $return);
                            $subNode = $return;
                        } elseif (self::STOP_TRAVERSAL === $return) {
                            $this->stopTraversal = \true;
                            break 2;
                        } elseif (\is_array($return)) {
                            throw new \LogicException('leaveNode() may only return an array if the parent structure is an array');
                        } else {
                            throw new \LogicException('leaveNode() returned invalid value of type ' . \gettype($return));
                        }
                    }
                    if ($breakVisitorIndex === $visitorIndex) {
                        break;
                    }
                }
            }
        }
        return $node;
    }
    /**
     * Recursively traverse array (usually of nodes).
     *
     * @param array $nodes Array to traverse
     *
     * @return array Result of traversal (may be original array or changed one)
     */
    protected function traverseArray(array $nodes) : array
    {
        $doNodes = [];
        foreach ($nodes as $i => &$node) {
            if ($node instanceof Node) {
                $traverseChildren = \true;
                $breakVisitorIndex = null;
                foreach ($this->visitors as $visitorIndex => $visitor) {
                    $return = $visitor->enterNode($node);
                    if (null !== $return) {
                        if ($return instanceof Node) {
                            $this->ensureReplacementReasonable($node, $return);
                            $node = $return;
                        } elseif (self::DONT_TRAVERSE_CHILDREN === $return) {
                            $traverseChildren = \false;
                        } elseif (self::DONT_TRAVERSE_CURRENT_AND_CHILDREN === $return) {
                            $traverseChildren = \false;
                            $breakVisitorIndex = $visitorIndex;
                            break;
                        } elseif (self::STOP_TRAVERSAL === $return) {
                            $this->stopTraversal = \true;
                            break 2;
                        } else {
                            throw new \LogicException('enterNode() returned invalid value of type ' . \gettype($return));
                        }
                    }
                }
                if ($traverseChildren) {
                    $node = $this->traverseNode($node);
                    if ($this->stopTraversal) {
                        break;
                    }
                }
                foreach ($this->visitors as $visitorIndex => $visitor) {
                    $return = $visitor->leaveNode($node);
                    if (null !== $return) {
                        if ($return instanceof Node) {
                            $this->ensureReplacementReasonable($node, $return);
                            $node = $return;
                        } elseif (\is_array($return)) {
                            $doNodes[] = [$i, $return];
                            break;
                        } elseif (self::REMOVE_NODE === $return) {
                            $doNodes[] = [$i, []];
                            break;
                        } elseif (self::STOP_TRAVERSAL === $return) {
                            $this->stopTraversal = \true;
                            break 2;
                        } elseif (\false === $return) {
                            throw new \LogicException('bool(false) return from leaveNode() no longer supported. Return NodeTraverser::REMOVE_NODE instead');
                        } else {
                            throw new \LogicException('leaveNode() returned invalid value of type ' . \gettype($return));
                        }
                    }
                    if ($breakVisitorIndex === $visitorIndex) {
                        break;
                    }
                }
            } elseif (\is_array($node)) {
                throw new \LogicException('Invalid node structure: Contains nested arrays');
            }
        }
        if (!empty($doNodes)) {
            while (list($i, $replace) = \array_pop($doNodes)) {
                \array_splice($nodes, $i, 1, $replace);
            }
        }
        return $nodes;
    }
    /**
     *
     */
    private function ensureReplacementReasonable($old, $new)
    {
        if ($old instanceof Node\Stmt && $new instanceof Node\Expr) {
            throw new \LogicException("Trying to replace statement ({$old->getType()}) " . "with expression ({$new->getType()}). Are you missing a " . "Stmt_Expression wrapper?");
        }
        if ($old instanceof Node\Expr && $new instanceof Node\Stmt) {
            throw new \LogicException("Trying to replace expression ({$old->getType()}) " . "with statement ({$new->getType()})");
        }
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\NodeVisitor;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeTraverser;
use PhabelVendor\PhpParser\NodeVisitorAbstract;
/**
 * This visitor can be used to find the first node satisfying some criterion determined by
 * a filter callback.
 */
class FirstFindingVisitor extends NodeVisitorAbstract
{
    /** @var callable Filter callback */
    protected $filterCallback;
    /** @var null|Node Found node */
    protected $foundNode;
    /**
     *
     */
    public function __construct(callable $filterCallback)
    {
        $this->filterCallback = $filterCallback;
    }
    /**
     * Get found node satisfying the filter callback.
     *
     * Returns null if no node satisfies the filter callback.
     *
     * @return (null | Node) Found node (or null if not found)
     */
    public function getFoundNode()
    {
        return $this->foundNode;
    }
    /**
     *
     */
    public function beforeTraverse(array $nodes)
    {
        $this->foundNode = null;
        return null;
    }
    /**
     *
     */
    public function enterNode(Node $node)
    {
        $filterCallback = $this->filterCallback;
        if ($filterCallback($node)) {
            $this->foundNode = $node;
            return NodeTraverser::STOP_TRAVERSAL;
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\NodeVisitor;

use function array_pop;
use function count;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeVisitorAbstract;
/**
 * Visitor that connects a child node to its parent node.
 *
 * On the child node, the parent node can be accessed through
 * <code>$node->getAttribute('parent')</code>.
 */
final class ParentConnectingVisitor extends NodeVisitorAbstract
{
    /**
     * @var Node[]
     */
    private $stack = [];
    /**
     *
     */
    public function beforeTraverse(array $nodes)
    {
        $this->stack = [];
    }
    /**
     *
     */
    public function enterNode(Node $node)
    {
        if (!empty($this->stack)) {
            $node->setAttribute('parent', $this->stack[count($this->stack) - 1]);
        }
        $this->stack[] = $node;
    }
    /**
     *
     */
    public function leaveNode(Node $node)
    {
        array_pop($this->stack);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\NodeVisitor;

use PhabelVendor\PhpParser\ErrorHandler;
use PhabelVendor\PhpParser\NameContext;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Stmt;
use PhabelVendor\PhpParser\NodeVisitorAbstract;
class NameResolver extends NodeVisitorAbstract
{
    /** @var NameContext Naming context */
    protected $nameContext;
    /** @var bool Whether to preserve original names */
    protected $preserveOriginalNames;
    /** @var bool Whether to replace resolved nodes in place, or to add resolvedNode attributes */
    protected $replaceNodes;
    /**
    * Constructs a name resolution visitor.
    *
    * Options:
    preserveOriginalNames (default false): An "originalName" attribute will be added to
    all name nodes that underwent resolution.
    replaceNodes (default true): Resolved names are replaced in-place. Otherwise, a
    resolvedName attribute is added. (Names that cannot be statically resolved receive a
    namespacedName attribute, as usual.)
    *
    * @param (ErrorHandler | null) $errorHandler Error handler
    * @param array $options Options
    */
    public function __construct(ErrorHandler $errorHandler = null, array $options = [])
    {
        $this->nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing());
        $this->preserveOriginalNames = $options['preserveOriginalNames'] ?? \false;
        $this->replaceNodes = $options['replaceNodes'] ?? \true;
    }
    /**
     * Get name resolution context.
     *
     * @return NameContext
     */
    public function getNameContext() : NameContext
    {
        return $this->nameContext;
    }
    /**
     *
     */
    public function beforeTraverse(array $nodes)
    {
        $this->nameContext->startNamespace();
        return null;
    }
    /**
     *
     */
    public function enterNode(Node $node)
    {
        if ($node instanceof Stmt\Namespace_) {
            $this->nameContext->startNamespace($node->name);
        } elseif ($node instanceof Stmt\Use_) {
            foreach ($node->uses as $use) {
                $this->addAlias($use, $node->type, null);
            }
        } elseif ($node instanceof Stmt\GroupUse) {
            foreach ($node->uses as $use) {
                $this->addAlias($use, $node->type, $node->prefix);
            }
        } elseif ($node instanceof Stmt\Class_) {
            if (null !== $node->extends) {
                $node->extends = $this->resolveClassName($node->extends);
            }
            foreach ($node->implements as &$interface) {
                $interface = $this->resolveClassName($interface);
            }
            $this->resolveAttrGroups($node);
            if (null !== $node->name) {
                $this->addNamespacedName($node);
            }
        } elseif ($node instanceof Stmt\Interface_) {
            foreach ($node->extends as &$interface) {
                $interface = $this->resolveClassName($interface);
            }
            $this->resolveAttrGroups($node);
            $this->addNamespacedName($node);
        } elseif ($node instanceof Stmt\Enum_) {
            foreach ($node->implements as &$interface) {
                $interface = $this->resolveClassName($interface);
            }
            $this->resolveAttrGroups($node);
            if (null !== $node->name) {
                $this->addNamespacedName($node);
            }
        } elseif ($node instanceof Stmt\Trait_) {
            $this->resolveAttrGroups($node);
            $this->addNamespacedName($node);
        } elseif ($node instanceof Stmt\Function_) {
            $this->resolveSignature($node);
            $this->resolveAttrGroups($node);
            $this->addNamespacedName($node);
        } elseif ($node instanceof Stmt\ClassMethod || $node instanceof Expr\Closure || $node instanceof Expr\ArrowFunction) {
            $this->resolveSignature($node);
            $this->resolveAttrGroups($node);
        } elseif ($node instanceof Stmt\Property) {
            if (null !== $node->type) {
                $node->type = $this->resolveType($node->type);
            }
            $this->resolveAttrGroups($node);
        } elseif ($node instanceof Stmt\Const_) {
            foreach ($node->consts as $const) {
                $this->addNamespacedName($const);
            }
        } else {
            if ($node instanceof Stmt\ClassConst) {
                $this->resolveAttrGroups($node);
            } else {
                if ($node instanceof Stmt\EnumCase) {
                    $this->resolveAttrGroups($node);
                } elseif ($node instanceof Expr\StaticCall || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\ClassConstFetch || $node instanceof Expr\New_ || $node instanceof Expr\Instanceof_) {
                    if ($node->class instanceof Name) {
                        $node->class = $this->resolveClassName($node->class);
                    }
                } elseif ($node instanceof Stmt\Catch_) {
                    foreach ($node->types as &$type) {
                        $type = $this->resolveClassName($type);
                    }
                } elseif ($node instanceof Expr\FuncCall) {
                    if ($node->name instanceof Name) {
                        $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_FUNCTION);
                    }
                } elseif ($node instanceof Expr\ConstFetch) {
                    $node->name = $this->resolveName($node->name, Stmt\Use_::TYPE_CONSTANT);
                } elseif ($node instanceof Stmt\TraitUse) {
                    foreach ($node->traits as &$trait) {
                        $trait = $this->resolveClassName($trait);
                    }
                    foreach ($node->adaptations as $adaptation) {
                        if (null !== $adaptation->trait) {
                            $adaptation->trait = $this->resolveClassName($adaptation->trait);
                        }
                        if ($adaptation instanceof Stmt\TraitUseAdaptation\Precedence) {
                            foreach ($adaptation->insteadof as &$insteadof) {
                                $insteadof = $this->resolveClassName($insteadof);
                            }
                        }
                    }
                }
            }
        }
        return null;
    }
    /**
     *
     */
    private function addAlias(Stmt\UseUse $use, $type, Name $prefix = null)
    {
        // Add prefix for group uses
        $name = $prefix ? Name::concat($prefix, $use->name) : $use->name;
        // Type is determined either by individual element or whole use declaration
        $type |= $use->type;
        $this->nameContext->addAlias($name, (string) $use->getAlias(), $type, $use->getAttributes());
    }
    /**
     * @param (Stmt\Function_ | Stmt\ClassMethod | Expr\Closure) $node
     */
    private function resolveSignature($node)
    {
        foreach ($node->params as $param) {
            $param->type = $this->resolveType($param->type);
            $this->resolveAttrGroups($param);
        }
        $node->returnType = $this->resolveType($node->returnType);
    }
    /**
     *
     */
    private function resolveType($node)
    {
        if ($node instanceof Name) {
            return $this->resolveClassName($node);
        }
        if ($node instanceof Node\NullableType) {
            $node->type = $this->resolveType($node->type);
            return $node;
        }
        if ($node instanceof Node\UnionType || $node instanceof Node\IntersectionType) {
            foreach ($node->types as &$type) {
                $type = $this->resolveType($type);
            }
            return $node;
        }
        return $node;
    }
    /**
     * Resolve name, according to name resolver options.
     *
     * @param Name $name Function or constant name to resolve
     * @param int $type One of Stmt\Use_::TYPE_*
     *
     * @return Name Resolved name, or original name with attribute
     */
    protected function resolveName(Name $name, int $type) : Name
    {
        if (!$this->replaceNodes) {
            $resolvedName = $this->nameContext->getResolvedName($name, $type);
            if (null !== $resolvedName) {
                $name->setAttribute('resolvedName', $resolvedName);
            } else {
                $name->setAttribute('namespacedName', FullyQualified::concat($this->nameContext->getNamespace(), $name, $name->getAttributes()));
            }
            return $name;
        }
        if ($this->preserveOriginalNames) {
            // Save the original name
            $originalName = $name;
            $name = clone $originalName;
            $name->setAttribute('originalName', $originalName);
        }
        $resolvedName = $this->nameContext->getResolvedName($name, $type);
        if (null !== $resolvedName) {
            return $resolvedName;
        }
        // unqualified names inside a namespace cannot be resolved at compile-time
        // add the namespaced version of the name as an attribute
        $name->setAttribute('namespacedName', FullyQualified::concat($this->nameContext->getNamespace(), $name, $name->getAttributes()));
        return $name;
    }
    /**
     *
     */
    protected function resolveClassName(Name $name)
    {
        return $this->resolveName($name, Stmt\Use_::TYPE_NORMAL);
    }
    /**
     *
     */
    protected function addNamespacedName(Node $node)
    {
        $node->namespacedName = Name::concat($this->nameContext->getNamespace(), (string) $node->name);
    }
    /**
     *
     */
    protected function resolveAttrGroups(Node $node)
    {
        foreach ($node->attrGroups as $attrGroup) {
            foreach ($attrGroup->attrs as $attr) {
                $attr->name = $this->resolveClassName($attr->name);
            }
        }
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\NodeVisitor;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeVisitorAbstract;
/**
 * This visitor can be used to find and collect all nodes satisfying some criterion determined by
 * a filter callback.
 */
class FindingVisitor extends NodeVisitorAbstract
{
    /** @var callable Filter callback */
    protected $filterCallback;
    /** @var Node[] Found nodes */
    protected $foundNodes;
    /**
     *
     */
    public function __construct(callable $filterCallback)
    {
        $this->filterCallback = $filterCallback;
    }
    /**
     * Get found nodes satisfying the filter callback.
     *
     * Nodes are returned in pre-order.
     *
     * @return Node[] Found nodes
     */
    public function getFoundNodes() : array
    {
        return $this->foundNodes;
    }
    /**
     *
     */
    public function beforeTraverse(array $nodes)
    {
        $this->foundNodes = [];
        return null;
    }
    /**
     *
     */
    public function enterNode(Node $node)
    {
        $filterCallback = $this->filterCallback;
        if ($filterCallback($node)) {
            $this->foundNodes[] = $node;
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\NodeVisitor;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeVisitorAbstract;
/**
 * Visitor cloning all nodes and linking to the original nodes using an attribute.
 *
 * This visitor is required to perform format-preserving pretty prints.
 */
class CloningVisitor extends NodeVisitorAbstract
{
    /**
     *
     */
    public function enterNode(Node $origNode)
    {
        $node = clone $origNode;
        $node->setAttribute('origNode', $origNode);
        return $node;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser\NodeVisitor;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeVisitorAbstract;
/**
 * Visitor that connects a child node to its parent node
 * as well as its sibling nodes.
 *
 * On the child node, the parent node can be accessed through
 * <code>$node->getAttribute('parent')</code>, the previous
 * node can be accessed through <code>$node->getAttribute('previous')</code>,
 * and the next node can be accessed through <code>$node->getAttribute('next')</code>.
 */
final class NodeConnectingVisitor extends NodeVisitorAbstract
{
    /**
     * @var Node[]
     */
    private $stack = [];
    /**
     * @var ?Node
     */
    private $previous;
    /**
     *
     */
    public function beforeTraverse(array $nodes)
    {
        $this->stack = [];
        $this->previous = null;
    }
    /**
     *
     */
    public function enterNode(Node $node)
    {
        if (!empty($this->stack)) {
            $node->setAttribute('parent', $this->stack[\count($this->stack) - 1]);
        }
        if ($this->previous !== null && $this->previous->getAttribute('parent') === $node->getAttribute('parent')) {
            $node->setAttribute('previous', $this->previous);
            $this->previous->setAttribute('next', $node);
        }
        $this->stack[] = $node;
    }
    /**
     *
     */
    public function leaveNode(Node $node)
    {
        $this->previous = $node;
        \array_pop($this->stack);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PhpParser;

interface Parser
{
    /**
    * Parses PHP code into a node tree.
    *
    * @param string $code The source code to parse
    * @param (ErrorHandler | null) $errorHandler Error handler to use for lexer/parser errors, defaults
    to ErrorHandler\Throwing.
    *
    * @return (Node\Stmt[] | null) Array of statements (or null non-throwing error handler is used and
    the parser was unable to recover from an error).
    */
    public function parse(string $code, ErrorHandler $errorHandler = null);
}
<?php

namespace PhabelVendor\Psr\Container;

use Throwable;
/**
 * Base interface representing a generic exception in a container.
 */
interface ContainerExceptionInterface extends Throwable
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\Psr\Container;

/**
 * Describes the interface of a container that exposes methods to read its entries.
 */
interface ContainerInterface
{
    /**
     * Finds an entry of the container by its identifier and returns it.
     *
     * @param string $id Identifier of the entry to look for.
     *
     * @throws NotFoundExceptionInterface No entry was found for **this** identifier.
     * @throws ContainerExceptionInterface Error while retrieving the entry.
     *
     * @return mixed Entry.
     */
    public function get(string $id);
    /**
    * Returns true if the container can return an entry for the given identifier.
    Returns false otherwise.
    *
    * `has($id)` returning true does not mean that `get($id)` will not throw an exception.
    It does however mean that `get($id)` will not throw a `NotFoundExceptionInterface`.
    *
    * @param string $id Identifier of the entry to look for.
    *
    * @return bool
    */
    public function has(string $id) : bool;
}
<?php

namespace PhabelVendor\Psr\Container;

/**
 * No entry was found in the container.
 */
interface NotFoundExceptionInterface extends ContainerExceptionInterface
{
}
<?php

namespace PhabelVendor\Psr\Log;

/**
 * This Logger can be used to avoid conditional log calls.
 *
 * Logging should always be optional, and if no logger is provided to your
 * library creating a NullLogger instance to have something to throw logs at
 * is a good way to avoid littering your code with `if ($this->logger) { }`
 * blocks.
 */
class NullLogger extends AbstractLogger
{
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = array())
    {
        // noop
    }
}
<?php

namespace PhabelVendor\Psr\Log;

/**
 * Basic Implementation of LoggerAwareInterface.
 */
trait LoggerAwareTrait
{
    /**
     * The logger instance.
     *
     * @var LoggerInterface|null
     */
    protected $logger;
    /**
     * Sets a logger.
     *
     * @param LoggerInterface $logger
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}
<?php

namespace PhabelVendor\Psr\Log\Test;

/**
 * This class is internal and does not follow the BC promise.
 *
 * Do NOT use this class in any way.
 *
 * @internal
 */
class DummyTest
{
    /**
     *
     */
    public function __toString()
    {
        return 'DummyTest';
    }
}
<?php

namespace PhabelVendor\Psr\Log\Test;

use PhabelVendor\Psr\Log\AbstractLogger;
/**
 * Used for testing purposes.
 *
 * It records all records and gives you access to them for verification.
 *
 * @method bool hasEmergency($record)
 * @method bool hasAlert($record)
 * @method bool hasCritical($record)
 * @method bool hasError($record)
 * @method bool hasWarning($record)
 * @method bool hasNotice($record)
 * @method bool hasInfo($record)
 * @method bool hasDebug($record)
 *
 * @method bool hasEmergencyRecords()
 * @method bool hasAlertRecords()
 * @method bool hasCriticalRecords()
 * @method bool hasErrorRecords()
 * @method bool hasWarningRecords()
 * @method bool hasNoticeRecords()
 * @method bool hasInfoRecords()
 * @method bool hasDebugRecords()
 *
 * @method bool hasEmergencyThatContains($message)
 * @method bool hasAlertThatContains($message)
 * @method bool hasCriticalThatContains($message)
 * @method bool hasErrorThatContains($message)
 * @method bool hasWarningThatContains($message)
 * @method bool hasNoticeThatContains($message)
 * @method bool hasInfoThatContains($message)
 * @method bool hasDebugThatContains($message)
 *
 * @method bool hasEmergencyThatMatches($message)
 * @method bool hasAlertThatMatches($message)
 * @method bool hasCriticalThatMatches($message)
 * @method bool hasErrorThatMatches($message)
 * @method bool hasWarningThatMatches($message)
 * @method bool hasNoticeThatMatches($message)
 * @method bool hasInfoThatMatches($message)
 * @method bool hasDebugThatMatches($message)
 *
 * @method bool hasEmergencyThatPasses($message)
 * @method bool hasAlertThatPasses($message)
 * @method bool hasCriticalThatPasses($message)
 * @method bool hasErrorThatPasses($message)
 * @method bool hasWarningThatPasses($message)
 * @method bool hasNoticeThatPasses($message)
 * @method bool hasInfoThatPasses($message)
 * @method bool hasDebugThatPasses($message)
 */
class TestLogger extends AbstractLogger
{
    /**
     * @var array
     */
    public $records = [];
    public $recordsByLevel = [];
    /**
     * @inheritdoc
     */
    public function log($level, $message, array $context = [])
    {
        $record = ['level' => $level, 'message' => $message, 'context' => $context];
        $this->recordsByLevel[$record['level']][] = $record;
        $this->records[] = $record;
    }
    /**
     *
     */
    public function hasRecords($level)
    {
        return isset($this->recordsByLevel[$level]);
    }
    /**
     *
     */
    public function hasRecord($record, $level)
    {
        if (\is_string($record)) {
            $record = ['message' => $record];
        }
        return $this->hasRecordThatPasses(function ($rec) use($record) {
            if ($rec['message'] !== $record['message']) {
                return \false;
            }
            if (isset($record['context']) && $rec['context'] !== $record['context']) {
                return \false;
            }
            return \true;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatContains($message, $level)
    {
        return $this->hasRecordThatPasses(function ($rec) use($message) {
            return \strpos($rec['message'], $message) !== \false;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatMatches($regex, $level)
    {
        return $this->hasRecordThatPasses(function ($rec) use($regex) {
            return \preg_match($regex, $rec['message']) > 0;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatPasses(callable $predicate, $level)
    {
        if (!isset($this->recordsByLevel[$level])) {
            return \false;
        }
        foreach ($this->recordsByLevel[$level] as $i => $rec) {
            if (\call_user_func($predicate, $rec, $i)) {
                return \true;
            }
        }
        return \false;
    }
    /**
     *
     */
    public function __call($method, $args)
    {
        if (\preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
            $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
            $level = \strtolower($matches[2]);
            if (\method_exists($this, $genericMethod)) {
                $args[] = $level;
                return \call_user_func_array([$this, $genericMethod], $args);
            }
        }
        throw new \BadMethodCallException('Call to undefined method ' . \get_class($this) . '::' . $method . '()');
    }
    /**
     *
     */
    public function reset()
    {
        $this->records = [];
        $this->recordsByLevel = [];
    }
}
<?php

namespace PhabelVendor\Psr\Log\Test;

use PhabelVendor\Psr\Log\LoggerInterface;
use PhabelVendor\Psr\Log\LogLevel;
use PhabelVendor\PHPUnit\Framework\TestCase;
/**
 * Provides a base test class for ensuring compliance with the LoggerInterface.
 *
 * Implementors can extend the class and implement abstract methods to run this
 * as part of their test suite.
 */
abstract class LoggerInterfaceTest extends TestCase
{
    /**
     * @return LoggerInterface
     */
    public abstract function getLogger();
    /**
     * This must return the log messages in order.
     *
     * The simple formatting of the messages is: "<LOG LEVEL> <MESSAGE>".
     *
     * Example ->error('Foo') would yield "error Foo".
     *
     * @return string[]
     */
    public abstract function getLogs();
    /**
     *
     */
    public function testImplements()
    {
        $this->assertInstanceOf('PhabelVendor\\Psr\\Log\\LoggerInterface', $this->getLogger());
    }
    /**
     * @dataProvider provideLevelsAndMessages
     */
    public function testLogsAtAllLevels($level, $message)
    {
        $logger = $this->getLogger();
        $logger->{$level}($message, array('user' => 'Bob'));
        $logger->log($level, $message, array('user' => 'Bob'));
        $expected = array($level . ' message of level ' . $level . ' with context: Bob', $level . ' message of level ' . $level . ' with context: Bob');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function provideLevelsAndMessages()
    {
        return array(LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'));
    }
    /**
     * @expectedException \Psr\Log\InvalidArgumentException
     */
    public function testThrowsOnInvalidLevel()
    {
        $logger = $this->getLogger();
        $logger->log('invalid level', 'Foo');
    }
    /**
     *
     */
    public function testContextReplacement()
    {
        $logger = $this->getLogger();
        $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
        $expected = array('info {Message {nothing} Bob Bar a}');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testObjectCastToString()
    {
        if (\method_exists($this, 'createPartialMock')) {
            $dummy = $this->createPartialMock('PhabelVendor\\Psr\\Log\\Test\\DummyTest', array('__toString'));
        } else {
            $dummy = $this->getMock('PhabelVendor\\Psr\\Log\\Test\\DummyTest', array('__toString'));
        }
        $dummy->expects($this->once())->method('__toString')->will($this->returnValue('DUMMY'));
        $this->getLogger()->warning($dummy);
        $expected = array('warning DUMMY');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testContextCanContainAnything()
    {
        $closed = \fopen('php://memory', 'r');
        \fclose($closed);
        $context = array('bool' => \true, 'null' => null, 'string' => 'Foo', 'int' => 0, 'float' => 0.5, 'nested' => array('with object' => new DummyTest()), 'object' => new \DateTime(), 'resource' => \fopen('php://memory', 'r'), 'closed' => $closed);
        $this->getLogger()->warning('Crazy context data', $context);
        $expected = array('warning Crazy context data');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testContextExceptionKeyCanBeExceptionOrOtherValues()
    {
        $logger = $this->getLogger();
        $logger->warning('Random message', array('exception' => 'oops'));
        $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
        $expected = array('warning Random message', 'critical Uncaught Exception!');
        $this->assertEquals($expected, $this->getLogs());
    }
}
<?php

namespace PhabelVendor\Psr\Log;

/**
 * This is a simple Logger implementation that other Loggers can inherit from.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
abstract class AbstractLogger implements LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
}
<?php

namespace PhabelVendor\Psr\Log;

/**
 * Describes a logger instance.
 *
 * The message MUST be a string or object implementing __toString().
 *
 * The message MAY contain placeholders in the form: {foo} where foo
 * will be replaced by the context data in key "foo".
 *
 * The context array can contain arbitrary data. The only assumption that
 * can be made by implementors is that if an Exception instance is given
 * to produce a stack trace, it MUST be in a key named "exception".
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * for the full interface specification.
 */
interface LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function emergency($message, array $context = array());
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function alert($message, array $context = array());
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function critical($message, array $context = array());
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function error($message, array $context = array());
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function warning($message, array $context = array());
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function notice($message, array $context = array());
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function info($message, array $context = array());
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function debug($message, array $context = array());
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = array());
}
<?php

namespace PhabelVendor\Psr\Log;

/**
 * Describes log levels.
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT = 'alert';
    const CRITICAL = 'critical';
    const ERROR = 'error';
    const WARNING = 'warning';
    const NOTICE = 'notice';
    const INFO = 'info';
    const DEBUG = 'debug';
}
<?php

namespace PhabelVendor\Psr\Log;

/**
 * This is a simple Logger trait that classes unable to extend AbstractLogger
 * (because they extend another class, etc) can include.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
trait LoggerTrait
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public abstract function log($level, $message, array $context = array());
}
<?php

namespace PhabelVendor\Psr\Log;

class InvalidArgumentException extends \InvalidArgumentException
{
}
<?php

namespace PhabelVendor\Psr\Log;

/**
 * Describes a logger-aware instance.
 */
interface LoggerAwareInterface
{
    /**
     * Sets a logger instance on the object.
     *
     * @param LoggerInterface $logger
     *
     * @return void
     */
    public function setLogger(LoggerInterface $logger);
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Lexer;

/**
 * Implementation based on Nette Tokenizer (New BSD License; https://github.com/nette/tokenizer)
 */
class Lexer
{
    public const TOKEN_REFERENCE = 0;
    public const TOKEN_UNION = 1;
    public const TOKEN_INTERSECTION = 2;
    public const TOKEN_NULLABLE = 3;
    public const TOKEN_OPEN_PARENTHESES = 4;
    public const TOKEN_CLOSE_PARENTHESES = 5;
    public const TOKEN_OPEN_ANGLE_BRACKET = 6;
    public const TOKEN_CLOSE_ANGLE_BRACKET = 7;
    public const TOKEN_OPEN_SQUARE_BRACKET = 8;
    public const TOKEN_CLOSE_SQUARE_BRACKET = 9;
    public const TOKEN_COMMA = 10;
    public const TOKEN_VARIADIC = 11;
    public const TOKEN_DOUBLE_COLON = 12;
    public const TOKEN_DOUBLE_ARROW = 13;
    public const TOKEN_EQUAL = 14;
    public const TOKEN_OPEN_PHPDOC = 15;
    public const TOKEN_CLOSE_PHPDOC = 16;
    public const TOKEN_PHPDOC_TAG = 17;
    public const TOKEN_FLOAT = 18;
    public const TOKEN_INTEGER = 19;
    public const TOKEN_SINGLE_QUOTED_STRING = 20;
    public const TOKEN_DOUBLE_QUOTED_STRING = 21;
    public const TOKEN_IDENTIFIER = 22;
    public const TOKEN_THIS_VARIABLE = 23;
    public const TOKEN_VARIABLE = 24;
    public const TOKEN_HORIZONTAL_WS = 25;
    public const TOKEN_PHPDOC_EOL = 26;
    public const TOKEN_OTHER = 27;
    public const TOKEN_END = 28;
    public const TOKEN_COLON = 29;
    public const TOKEN_WILDCARD = 30;
    public const TOKEN_OPEN_CURLY_BRACKET = 31;
    public const TOKEN_CLOSE_CURLY_BRACKET = 32;
    public const TOKEN_LABELS = [self::TOKEN_REFERENCE => '\'&\'', self::TOKEN_UNION => '\'|\'', self::TOKEN_INTERSECTION => '\'&\'', self::TOKEN_NULLABLE => '\'?\'', self::TOKEN_OPEN_PARENTHESES => '\'(\'', self::TOKEN_CLOSE_PARENTHESES => '\')\'', self::TOKEN_OPEN_ANGLE_BRACKET => '\'<\'', self::TOKEN_CLOSE_ANGLE_BRACKET => '\'>\'', self::TOKEN_OPEN_SQUARE_BRACKET => '\'[\'', self::TOKEN_CLOSE_SQUARE_BRACKET => '\']\'', self::TOKEN_OPEN_CURLY_BRACKET => '\'{\'', self::TOKEN_CLOSE_CURLY_BRACKET => '\'}\'', self::TOKEN_COMMA => '\',\'', self::TOKEN_COLON => '\':\'', self::TOKEN_VARIADIC => '\'...\'', self::TOKEN_DOUBLE_COLON => '\'::\'', self::TOKEN_DOUBLE_ARROW => '\'=>\'', self::TOKEN_EQUAL => '\'=\'', self::TOKEN_OPEN_PHPDOC => '\'/**\'', self::TOKEN_CLOSE_PHPDOC => '\'*/\'', self::TOKEN_PHPDOC_TAG => 'TOKEN_PHPDOC_TAG', self::TOKEN_PHPDOC_EOL => 'TOKEN_PHPDOC_EOL', self::TOKEN_FLOAT => 'TOKEN_FLOAT', self::TOKEN_INTEGER => 'TOKEN_INTEGER', self::TOKEN_SINGLE_QUOTED_STRING => 'TOKEN_SINGLE_QUOTED_STRING', self::TOKEN_DOUBLE_QUOTED_STRING => 'TOKEN_DOUBLE_QUOTED_STRING', self::TOKEN_IDENTIFIER => 'type', self::TOKEN_THIS_VARIABLE => '\'$this\'', self::TOKEN_VARIABLE => 'variable', self::TOKEN_HORIZONTAL_WS => 'TOKEN_HORIZONTAL_WS', self::TOKEN_OTHER => 'TOKEN_OTHER', self::TOKEN_END => 'TOKEN_END', self::TOKEN_WILDCARD => '*'];
    public const VALUE_OFFSET = 0;
    public const TYPE_OFFSET = 1;
    /** @var string|null */
    private $regexp;
    /** @var int[]|null */
    private $types;
    /**
     *
     */
    public function tokenize(string $s) : array
    {
        if ($this->regexp === null || $this->types === null) {
            $this->initialize();
        }
        \assert($this->regexp !== null);
        \assert($this->types !== null);
        \preg_match_all($this->regexp, $s, $tokens, \PREG_SET_ORDER);
        $count = \count($this->types);
        foreach ($tokens as &$match) {
            for ($i = 1; $i <= $count; $i++) {
                if ($match[$i] !== null && $match[$i] !== '') {
                    $match = [$match[0], $this->types[$i - 1]];
                    break;
                }
            }
        }
        $tokens[] = ['', self::TOKEN_END];
        return $tokens;
    }
    /**
     *
     */
    private function initialize() : void
    {
        $patterns = [
            // '&' followed by TOKEN_VARIADIC, TOKEN_VARIABLE, TOKEN_EQUAL, TOKEN_EQUAL or TOKEN_CLOSE_PARENTHESES
            self::TOKEN_REFERENCE => '&(?=\\s*+(?:[.,=)]|(?:\\$(?!this(?![0-9a-z_\\x80-\\xFF])))))',
            self::TOKEN_UNION => '\\|',
            self::TOKEN_INTERSECTION => '&',
            self::TOKEN_NULLABLE => '\\?',
            self::TOKEN_OPEN_PARENTHESES => '\\(',
            self::TOKEN_CLOSE_PARENTHESES => '\\)',
            self::TOKEN_OPEN_ANGLE_BRACKET => '<',
            self::TOKEN_CLOSE_ANGLE_BRACKET => '>',
            self::TOKEN_OPEN_SQUARE_BRACKET => '\\[',
            self::TOKEN_CLOSE_SQUARE_BRACKET => '\\]',
            self::TOKEN_OPEN_CURLY_BRACKET => '\\{',
            self::TOKEN_CLOSE_CURLY_BRACKET => '\\}',
            self::TOKEN_COMMA => ',',
            self::TOKEN_VARIADIC => '\\.\\.\\.',
            self::TOKEN_DOUBLE_COLON => '::',
            self::TOKEN_DOUBLE_ARROW => '=>',
            self::TOKEN_EQUAL => '=',
            self::TOKEN_COLON => ':',
            self::TOKEN_OPEN_PHPDOC => '/\\*\\*(?=\\s)\\x20?+',
            self::TOKEN_CLOSE_PHPDOC => '\\*/',
            self::TOKEN_PHPDOC_TAG => '@[a-z][a-z0-9-]*+',
            self::TOKEN_PHPDOC_EOL => '\\r?+\\n[\\x09\\x20]*+(?:\\*(?!/)\\x20?+)?',
            self::TOKEN_FLOAT => '(?:-?[0-9]++\\.[0-9]*+(?:e-?[0-9]++)?)|(?:-?[0-9]*+\\.[0-9]++(?:e-?[0-9]++)?)|(?:-?[0-9]++e-?[0-9]++)',
            self::TOKEN_INTEGER => '-?(?:(?:0b[0-1]++)|(?:0o[0-7]++)|(?:0x[0-9a-f]++)|(?:[0-9]++))',
            self::TOKEN_SINGLE_QUOTED_STRING => '\'(?:\\\\[^\\r\\n]|[^\'\\r\\n\\\\])*+\'',
            self::TOKEN_DOUBLE_QUOTED_STRING => '"(?:\\\\[^\\r\\n]|[^"\\r\\n\\\\])*+"',
            self::TOKEN_IDENTIFIER => '(?:[\\\\]?+[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF-]*+)++',
            self::TOKEN_THIS_VARIABLE => '\\$this(?![0-9a-z_\\x80-\\xFF])',
            self::TOKEN_VARIABLE => '\\$[a-z_\\x80-\\xFF][0-9a-z_\\x80-\\xFF]*+',
            self::TOKEN_HORIZONTAL_WS => '[\\x09\\x20]++',
            self::TOKEN_WILDCARD => '\\*',
            // anything but TOKEN_CLOSE_PHPDOC or TOKEN_HORIZONTAL_WS or TOKEN_EOL
            self::TOKEN_OTHER => '(?:(?!\\*/)[^\\s])++',
        ];
        $this->regexp = '~(' . \implode(')|(', $patterns) . ')~Asi';
        $this->types = \array_keys($patterns);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Parser;

use PhabelVendor\PHPStan\PhpDocParser\Lexer\Lexer;
class ParserException extends \Exception
{
    /** @var string */
    private $currentTokenValue;
    /** @var int */
    private $currentTokenType;
    /** @var int */
    private $currentOffset;
    /** @var int */
    private $expectedTokenType;
    /**
     *
     */
    public function __construct(string $currentTokenValue, int $currentTokenType, int $currentOffset, int $expectedTokenType)
    {
        $this->currentTokenValue = $currentTokenValue;
        $this->currentTokenType = $currentTokenType;
        $this->currentOffset = $currentOffset;
        $this->expectedTokenType = $expectedTokenType;
        $json = \json_encode($currentTokenValue, \JSON_UNESCAPED_UNICODE | \JSON_UNESCAPED_SLASHES);
        \assert($json !== \false);
        parent::__construct(\sprintf('Unexpected token %s, expected %s at offset %d', $json, Lexer::TOKEN_LABELS[$expectedTokenType], $currentOffset));
    }
    /**
     *
     */
    public function getCurrentTokenValue() : string
    {
        return $this->currentTokenValue;
    }
    /**
     *
     */
    public function getCurrentTokenType() : int
    {
        return $this->currentTokenType;
    }
    /**
     *
     */
    public function getCurrentOffset() : int
    {
        return $this->currentOffset;
    }
    /**
     *
     */
    public function getExpectedTokenType() : int
    {
        return $this->expectedTokenType;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Parser;

use PhabelVendor\PHPStan\PhpDocParser\Ast;
use PhabelVendor\PHPStan\PhpDocParser\Lexer\Lexer;
class TypeParser
{
    /** @var ConstExprParser|null */
    private $constExprParser;
    /**
     *
     */
    public function __construct(?ConstExprParser $constExprParser = null)
    {
        $this->constExprParser = $constExprParser;
    }
    /**
     * @phpstan-impure
     */
    public function parse(TokenIterator $tokens) : Ast\Type\TypeNode
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
            $type = $this->parseNullable($tokens);
        } else {
            $type = $this->parseAtomic($tokens);
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_UNION)) {
                $type = $this->parseUnion($tokens, $type);
            } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_INTERSECTION)) {
                $type = $this->parseIntersection($tokens, $type);
            }
        }
        return $type;
    }
    /**
     * @phpstan-impure
     */
    private function parseAtomic(TokenIterator $tokens) : Ast\Type\TypeNode
    {
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
            $type = $this->parse($tokens);
            $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                return $this->tryParseArray($tokens, $type);
            }
            return $type;
        }
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
            $type = new Ast\Type\ThisTypeNode();
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                return $this->tryParseArray($tokens, $type);
            }
            return $type;
        }
        $currentTokenValue = $tokens->currentTokenValue();
        $tokens->pushSavePoint();
        // because of ConstFetchNode
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_IDENTIFIER)) {
            $type = new Ast\Type\IdentifierTypeNode($currentTokenValue);
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
                $tokens->dropSavePoint();
                // because of ConstFetchNode
                if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
                    $tokens->pushSavePoint();
                    $isHtml = $this->isHtml($tokens);
                    $tokens->rollback();
                    if ($isHtml) {
                        return $type;
                    }
                    $type = $this->parseGeneric($tokens, $type);
                    if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                        $type = $this->tryParseArray($tokens, $type);
                    }
                } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
                    $type = $this->tryParseCallable($tokens, $type);
                } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                    $type = $this->tryParseArray($tokens, $type);
                } elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
                    $type = $this->parseArrayShape($tokens, $type);
                    if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                        $type = $this->tryParseArray($tokens, $type);
                    }
                }
                return $type;
            } else {
                $tokens->rollback();
                // because of ConstFetchNode
            }
        } else {
            $tokens->dropSavePoint();
            // because of ConstFetchNode
        }
        $exception = new \PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER);
        if ($this->constExprParser === null) {
            throw $exception;
        }
        try {
            $constExpr = $this->constExprParser->parse($tokens, \true);
            if ($constExpr instanceof Ast\ConstExpr\ConstExprArrayNode) {
                throw $exception;
            }
            return new Ast\Type\ConstTypeNode($constExpr);
        } catch (\LogicException $e) {
            throw $exception;
        }
    }
    /**
     * @phpstan-impure
     */
    private function parseUnion(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\TypeNode
    {
        $types = [$type];
        while ($tokens->tryConsumeTokenType(Lexer::TOKEN_UNION)) {
            $types[] = $this->parseAtomic($tokens);
        }
        return new Ast\Type\UnionTypeNode($types);
    }
    /**
     * @phpstan-impure
     */
    private function parseIntersection(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\TypeNode
    {
        $types = [$type];
        while ($tokens->tryConsumeTokenType(Lexer::TOKEN_INTERSECTION)) {
            $types[] = $this->parseAtomic($tokens);
        }
        return new Ast\Type\IntersectionTypeNode($types);
    }
    /**
     * @phpstan-impure
     */
    private function parseNullable(TokenIterator $tokens) : Ast\Type\TypeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_NULLABLE);
        $type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
            $type = $this->parseGeneric($tokens, $type);
        } elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
            $type = $this->parseArrayShape($tokens, $type);
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
            $type = $this->tryParseArray($tokens, $type);
        }
        return new Ast\Type\NullableTypeNode($type);
    }
    /**
     * @phpstan-impure
     */
    public function isHtml(TokenIterator $tokens) : bool
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
            return \false;
        }
        $htmlTagName = $tokens->currentTokenValue();
        $tokens->next();
        if (!$tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) {
            return \false;
        }
        while (!$tokens->isCurrentTokenType(Lexer::TOKEN_END)) {
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET) && \strpos($tokens->currentTokenValue(), '/' . $htmlTagName . '>') !== \false) {
                return \true;
            }
            $tokens->next();
        }
        return \false;
    }
    /**
     * @phpstan-impure
     */
    public function parseGeneric(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $baseType) : Ast\Type\GenericTypeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET);
        $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        $genericTypes = [$this->parse($tokens)];
        $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
            $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET)) {
                // trailing comma case
                return new Ast\Type\GenericTypeNode($baseType, $genericTypes);
            }
            $genericTypes[] = $this->parse($tokens);
            $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        }
        $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_ANGLE_BRACKET);
        return new Ast\Type\GenericTypeNode($baseType, $genericTypes);
    }
    /**
     * @phpstan-impure
     */
    private function parseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier) : Ast\Type\TypeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
        $parameters = [];
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
            $parameters[] = $this->parseCallableParameter($tokens);
            while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
                $parameters[] = $this->parseCallableParameter($tokens);
            }
        }
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
        $tokens->consumeTokenType(Lexer::TOKEN_COLON);
        $returnType = $this->parseCallableReturnType($tokens);
        return new Ast\Type\CallableTypeNode($identifier, $parameters, $returnType);
    }
    /**
     * @phpstan-impure
     */
    private function parseCallableParameter(TokenIterator $tokens) : Ast\Type\CallableTypeParameterNode
    {
        $type = $this->parse($tokens);
        $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
        $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
            $parameterName = $tokens->currentTokenValue();
            $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
        } else {
            $parameterName = '';
        }
        $isOptional = $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
        return new Ast\Type\CallableTypeParameterNode($type, $isReference, $isVariadic, $parameterName, $isOptional);
    }
    /**
     * @phpstan-impure
     */
    private function parseCallableReturnType(TokenIterator $tokens) : Ast\Type\TypeNode
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_NULLABLE)) {
            $type = $this->parseNullable($tokens);
        } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES)) {
            $type = $this->parse($tokens);
            $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
        } else {
            $type = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_ANGLE_BRACKET)) {
                $type = $this->parseGeneric($tokens, $type);
            } elseif ($type->name === 'array' && $tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET) && !$tokens->isPrecededByHorizontalWhitespace()) {
                $type = $this->parseArrayShape($tokens, $type);
            }
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
            $type = $this->tryParseArray($tokens, $type);
        }
        return $type;
    }
    /**
     * @phpstan-impure
     */
    private function tryParseCallable(TokenIterator $tokens, Ast\Type\IdentifierTypeNode $identifier) : Ast\Type\TypeNode
    {
        try {
            $tokens->pushSavePoint();
            $type = $this->parseCallable($tokens, $identifier);
            $tokens->dropSavePoint();
        } catch (\PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException $e) {
            $tokens->rollback();
            $type = $identifier;
        }
        return $type;
    }
    /**
     * @phpstan-impure
     */
    private function tryParseArray(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\TypeNode
    {
        try {
            while ($tokens->isCurrentTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
                $tokens->pushSavePoint();
                $tokens->consumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET);
                $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
                $tokens->dropSavePoint();
                $type = new Ast\Type\ArrayTypeNode($type);
            }
        } catch (\PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException $e) {
            $tokens->rollback();
        }
        return $type;
    }
    /**
     * @phpstan-impure
     */
    private function parseArrayShape(TokenIterator $tokens, Ast\Type\TypeNode $type) : Ast\Type\ArrayShapeNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_CURLY_BRACKET);
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) {
            return new Ast\Type\ArrayShapeNode([]);
        }
        $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        $items = [$this->parseArrayShapeItem($tokens)];
        $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
            $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET)) {
                // trailing comma case
                return new Ast\Type\ArrayShapeNode($items);
            }
            $items[] = $this->parseArrayShapeItem($tokens);
            $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        }
        $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_CURLY_BRACKET);
        return new Ast\Type\ArrayShapeNode($items);
    }
    /**
     * @phpstan-impure
     */
    private function parseArrayShapeItem(TokenIterator $tokens) : Ast\Type\ArrayShapeItemNode
    {
        try {
            $tokens->pushSavePoint();
            $key = $this->parseArrayShapeKey($tokens);
            $optional = $tokens->tryConsumeTokenType(Lexer::TOKEN_NULLABLE);
            $tokens->consumeTokenType(Lexer::TOKEN_COLON);
            $value = $this->parse($tokens);
            $tokens->dropSavePoint();
            return new Ast\Type\ArrayShapeItemNode($key, $optional, $value);
        } catch (\PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException $e) {
            $tokens->rollback();
            $value = $this->parse($tokens);
            return new Ast\Type\ArrayShapeItemNode(null, \false, $value);
        }
    }
    /**
     * @phpstan-impure
     * @return (Ast\ConstExpr\ConstExprIntegerNode | Ast\ConstExpr\ConstExprStringNode | Ast\Type\IdentifierTypeNode)
     */
    private function parseArrayShapeKey(TokenIterator $tokens)
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
            $key = new Ast\ConstExpr\ConstExprIntegerNode($tokens->currentTokenValue());
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
            $key = new Ast\ConstExpr\ConstExprStringNode(\trim($tokens->currentTokenValue(), "'"));
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
            $key = new Ast\ConstExpr\ConstExprStringNode(\trim($tokens->currentTokenValue(), '"'));
            $tokens->next();
        } else {
            $key = new Ast\Type\IdentifierTypeNode($tokens->currentTokenValue());
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        }
        return $key;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Parser;

use PhabelVendor\PHPStan\PhpDocParser\Ast;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use PhabelVendor\PHPStan\PhpDocParser\Lexer\Lexer;
class PhpDocParser
{
    private const DISALLOWED_DESCRIPTION_START_TOKENS = [Lexer::TOKEN_UNION, Lexer::TOKEN_INTERSECTION];
    /** @var TypeParser */
    private $typeParser;
    /** @var ConstExprParser */
    private $constantExprParser;
    /**
     *
     */
    public function __construct(TypeParser $typeParser, ConstExprParser $constantExprParser)
    {
        $this->typeParser = $typeParser;
        $this->constantExprParser = $constantExprParser;
    }
    /**
     *
     */
    public function parse(TokenIterator $tokens) : Ast\PhpDoc\PhpDocNode
    {
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PHPDOC);
        $tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL);
        $children = [];
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
            $children[] = $this->parseChild($tokens);
            while ($tokens->tryConsumeTokenType(Lexer::TOKEN_PHPDOC_EOL) && !$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC)) {
                $children[] = $this->parseChild($tokens);
            }
        }
        try {
            $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PHPDOC);
        } catch (\PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException $e) {
            $name = '';
            if (\count($children) > 0) {
                $lastChild = $children[\count($children) - 1];
                if ($lastChild instanceof Ast\PhpDoc\PhpDocTagNode) {
                    $name = $lastChild->name;
                }
            }
            $tokens->forwardToTheEnd();
            return new Ast\PhpDoc\PhpDocNode([new Ast\PhpDoc\PhpDocTagNode($name, new Ast\PhpDoc\InvalidTagValueNode($e->getMessage(), $e))]);
        }
        return new Ast\PhpDoc\PhpDocNode(\array_values($children));
    }
    /**
     *
     */
    private function parseChild(TokenIterator $tokens) : Ast\PhpDoc\PhpDocChildNode
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG)) {
            return $this->parseTag($tokens);
        }
        return $this->parseText($tokens);
    }
    /**
     *
     */
    private function parseText(TokenIterator $tokens) : Ast\PhpDoc\PhpDocTextNode
    {
        $text = '';
        while (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
            $text .= $tokens->getSkippedHorizontalWhiteSpaceIfAny() . $tokens->joinUntil(Lexer::TOKEN_PHPDOC_EOL, Lexer::TOKEN_CLOSE_PHPDOC, Lexer::TOKEN_END);
            if (!$tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL)) {
                break;
            }
            $tokens->pushSavePoint();
            $tokens->next();
            if ($tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_TAG) || $tokens->isCurrentTokenType(Lexer::TOKEN_PHPDOC_EOL) || $tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PHPDOC) || $tokens->isCurrentTokenType(Lexer::TOKEN_END)) {
                $tokens->rollback();
                break;
            }
            $tokens->dropSavePoint();
            $text .= "\n";
        }
        return new Ast\PhpDoc\PhpDocTextNode(\trim($text, " \t"));
    }
    /**
     *
     */
    public function parseTag(TokenIterator $tokens) : Ast\PhpDoc\PhpDocTagNode
    {
        $tag = $tokens->currentTokenValue();
        $tokens->next();
        $value = $this->parseTagValue($tokens, $tag);
        return new Ast\PhpDoc\PhpDocTagNode($tag, $value);
    }
    /**
     *
     */
    public function parseTagValue(TokenIterator $tokens, string $tag) : Ast\PhpDoc\PhpDocTagValueNode
    {
        try {
            $tokens->pushSavePoint();
            switch ($tag) {
                case '@param':
                case '@phpstan-param':
                case '@psalm-param':
                    $tagValue = $this->parseParamTagValue($tokens);
                    break;
                case '@var':
                case '@phpstan-var':
                case '@psalm-var':
                    $tagValue = $this->parseVarTagValue($tokens);
                    break;
                case '@return':
                case '@phpstan-return':
                case '@psalm-return':
                    $tagValue = $this->parseReturnTagValue($tokens);
                    break;
                case '@throws':
                case '@phpstan-throws':
                    $tagValue = $this->parseThrowsTagValue($tokens);
                    break;
                case '@mixin':
                    $tagValue = $this->parseMixinTagValue($tokens);
                    break;
                case '@deprecated':
                    $tagValue = $this->parseDeprecatedTagValue($tokens);
                    break;
                case '@property':
                case '@property-read':
                case '@property-write':
                case '@phpstan-property':
                case '@phpstan-property-read':
                case '@phpstan-property-write':
                case '@psalm-property':
                case '@psalm-property-read':
                case '@psalm-property-write':
                    $tagValue = $this->parsePropertyTagValue($tokens);
                    break;
                case '@method':
                case '@phpstan-method':
                case '@psalm-method':
                    $tagValue = $this->parseMethodTagValue($tokens);
                    break;
                case '@template':
                case '@phpstan-template':
                case '@psalm-template':
                case '@template-covariant':
                case '@phpstan-template-covariant':
                case '@psalm-template-covariant':
                    $tagValue = $this->parseTemplateTagValue($tokens);
                    break;
                case '@extends':
                case '@phpstan-extends':
                case '@template-extends':
                    $tagValue = $this->parseExtendsTagValue('@extends', $tokens);
                    break;
                case '@implements':
                case '@phpstan-implements':
                case '@template-implements':
                    $tagValue = $this->parseExtendsTagValue('@implements', $tokens);
                    break;
                case '@use':
                case '@phpstan-use':
                case '@template-use':
                    $tagValue = $this->parseExtendsTagValue('@use', $tokens);
                    break;
                case '@phpstan-type':
                case '@psalm-type':
                    $tagValue = $this->parseTypeAliasTagValue($tokens);
                    break;
                case '@phpstan-import-type':
                case '@psalm-import-type':
                    $tagValue = $this->parseTypeAliasImportTagValue($tokens);
                    break;
                default:
                    $tagValue = new Ast\PhpDoc\GenericTagValueNode($this->parseOptionalDescription($tokens));
                    break;
            }
            $tokens->dropSavePoint();
        } catch (\PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException $e) {
            $tokens->rollback();
            $tagValue = new Ast\PhpDoc\InvalidTagValueNode($this->parseOptionalDescription($tokens), $e);
        }
        return $tagValue;
    }
    /**
     *
     */
    private function parseParamTagValue(TokenIterator $tokens) : Ast\PhpDoc\ParamTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
        $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens);
        return new Ast\PhpDoc\ParamTagValueNode($type, $isVariadic, $parameterName, $description, $isReference);
    }
    /**
     *
     */
    private function parseVarTagValue(TokenIterator $tokens) : Ast\PhpDoc\VarTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $variableName = $this->parseOptionalVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens, $variableName === '');
        return new Ast\PhpDoc\VarTagValueNode($type, $variableName, $description);
    }
    /**
     *
     */
    private function parseReturnTagValue(TokenIterator $tokens) : Ast\PhpDoc\ReturnTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\ReturnTagValueNode($type, $description);
    }
    /**
     *
     */
    private function parseThrowsTagValue(TokenIterator $tokens) : Ast\PhpDoc\ThrowsTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\ThrowsTagValueNode($type, $description);
    }
    /**
     *
     */
    private function parseMixinTagValue(TokenIterator $tokens) : Ast\PhpDoc\MixinTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $description = $this->parseOptionalDescription($tokens, \true);
        return new Ast\PhpDoc\MixinTagValueNode($type, $description);
    }
    /**
     *
     */
    private function parseDeprecatedTagValue(TokenIterator $tokens) : Ast\PhpDoc\DeprecatedTagValueNode
    {
        $description = $this->parseOptionalDescription($tokens);
        return new Ast\PhpDoc\DeprecatedTagValueNode($description);
    }
    /**
     *
     */
    private function parsePropertyTagValue(TokenIterator $tokens) : Ast\PhpDoc\PropertyTagValueNode
    {
        $type = $this->typeParser->parse($tokens);
        $parameterName = $this->parseRequiredVariableName($tokens);
        $description = $this->parseOptionalDescription($tokens);
        return new Ast\PhpDoc\PropertyTagValueNode($type, $parameterName, $description);
    }
    /**
     *
     */
    private function parseMethodTagValue(TokenIterator $tokens) : Ast\PhpDoc\MethodTagValueNode
    {
        $isStatic = $tokens->tryConsumeTokenValue('static');
        $returnTypeOrMethodName = $this->typeParser->parse($tokens);
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
            $returnType = $returnTypeOrMethodName;
            $methodName = $tokens->currentTokenValue();
            $tokens->next();
        } elseif ($returnTypeOrMethodName instanceof Ast\Type\IdentifierTypeNode) {
            $returnType = $isStatic ? new Ast\Type\IdentifierTypeNode('static') : null;
            $methodName = $returnTypeOrMethodName->name;
            $isStatic = \false;
        } else {
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
            // will throw exception
            exit;
        }
        $parameters = [];
        $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
        if (!$tokens->isCurrentTokenType(Lexer::TOKEN_CLOSE_PARENTHESES)) {
            $parameters[] = $this->parseMethodTagValueParameter($tokens);
            while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA)) {
                $parameters[] = $this->parseMethodTagValueParameter($tokens);
            }
        }
        $tokens->consumeTokenType(Lexer::TOKEN_CLOSE_PARENTHESES);
        $description = $this->parseOptionalDescription($tokens);
        return new Ast\PhpDoc\MethodTagValueNode($isStatic, $returnType, $methodName, $parameters, $description);
    }
    /**
     *
     */
    private function parseMethodTagValueParameter(TokenIterator $tokens) : Ast\PhpDoc\MethodTagValueParameterNode
    {
        switch ($tokens->currentTokenType()) {
            case Lexer::TOKEN_IDENTIFIER:
            case Lexer::TOKEN_OPEN_PARENTHESES:
            case Lexer::TOKEN_NULLABLE:
                $parameterType = $this->typeParser->parse($tokens);
                break;
            default:
                $parameterType = null;
        }
        $isReference = $tokens->tryConsumeTokenType(Lexer::TOKEN_REFERENCE);
        $isVariadic = $tokens->tryConsumeTokenType(Lexer::TOKEN_VARIADIC);
        $parameterName = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL)) {
            $defaultValue = $this->constantExprParser->parse($tokens);
        } else {
            $defaultValue = null;
        }
        return new Ast\PhpDoc\MethodTagValueParameterNode($parameterType, $isReference, $isVariadic, $parameterName, $defaultValue);
    }
    /**
     *
     */
    private function parseTemplateTagValue(TokenIterator $tokens) : Ast\PhpDoc\TemplateTagValueNode
    {
        $name = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        if ($tokens->tryConsumeTokenValue('of') || $tokens->tryConsumeTokenValue('as')) {
            $bound = $this->typeParser->parse($tokens);
        } else {
            $bound = null;
        }
        $description = $this->parseOptionalDescription($tokens);
        return new Ast\PhpDoc\TemplateTagValueNode($name, $bound, $description);
    }
    /**
     *
     */
    private function parseExtendsTagValue(string $tagName, TokenIterator $tokens) : Ast\PhpDoc\PhpDocTagValueNode
    {
        $baseType = new IdentifierTypeNode($tokens->currentTokenValue());
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        $type = $this->typeParser->parseGeneric($tokens, $baseType);
        $description = $this->parseOptionalDescription($tokens);
        switch ($tagName) {
            case '@extends':
                return new Ast\PhpDoc\ExtendsTagValueNode($type, $description);
            case '@implements':
                return new Ast\PhpDoc\ImplementsTagValueNode($type, $description);
            case '@use':
                return new Ast\PhpDoc\UsesTagValueNode($type, $description);
        }
        throw new \PhabelVendor\PHPStan\ShouldNotHappenException();
    }
    /**
     *
     */
    private function parseTypeAliasTagValue(TokenIterator $tokens) : Ast\PhpDoc\TypeAliasTagValueNode
    {
        $alias = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        // support psalm-type syntax
        $tokens->tryConsumeTokenType(Lexer::TOKEN_EQUAL);
        $type = $this->typeParser->parse($tokens);
        return new Ast\PhpDoc\TypeAliasTagValueNode($alias, $type);
    }
    /**
     *
     */
    private function parseTypeAliasImportTagValue(TokenIterator $tokens) : Ast\PhpDoc\TypeAliasImportTagValueNode
    {
        $importedAlias = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        if (!$tokens->tryConsumeTokenValue('from')) {
            throw new \PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException($tokens->currentTokenValue(), $tokens->currentTokenType(), $tokens->currentTokenOffset(), Lexer::TOKEN_IDENTIFIER);
        }
        $importedFrom = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        $importedAs = null;
        if ($tokens->tryConsumeTokenValue('as')) {
            $importedAs = $tokens->currentTokenValue();
            $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
        }
        return new Ast\PhpDoc\TypeAliasImportTagValueNode($importedAlias, new IdentifierTypeNode($importedFrom), $importedAs);
    }
    /**
     *
     */
    private function parseOptionalVariableName(TokenIterator $tokens) : string
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_VARIABLE)) {
            $parameterName = $tokens->currentTokenValue();
            $tokens->next();
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_THIS_VARIABLE)) {
            $parameterName = '$this';
            $tokens->next();
        } else {
            $parameterName = '';
        }
        return $parameterName;
    }
    /**
     *
     */
    private function parseRequiredVariableName(TokenIterator $tokens) : string
    {
        $parameterName = $tokens->currentTokenValue();
        $tokens->consumeTokenType(Lexer::TOKEN_VARIABLE);
        return $parameterName;
    }
    /**
     *
     */
    private function parseOptionalDescription(TokenIterator $tokens, bool $limitStartToken = \false) : string
    {
        if ($limitStartToken) {
            foreach (self::DISALLOWED_DESCRIPTION_START_TOKENS as $disallowedStartToken) {
                if (!$tokens->isCurrentTokenType($disallowedStartToken)) {
                    continue;
                }
                $tokens->consumeTokenType(Lexer::TOKEN_OTHER);
                // will throw exception
            }
        }
        return $this->parseText($tokens)->text;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Parser;

use PhabelVendor\PHPStan\PhpDocParser\Ast;
use PhabelVendor\PHPStan\PhpDocParser\Lexer\Lexer;
class ConstExprParser
{
    /**
     *
     */
    public function parse(TokenIterator $tokens, bool $trimStrings = \false) : Ast\ConstExpr\ConstExprNode
    {
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_FLOAT)) {
            $value = $tokens->currentTokenValue();
            $tokens->next();
            return new Ast\ConstExpr\ConstExprFloatNode($value);
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_INTEGER)) {
            $value = $tokens->currentTokenValue();
            $tokens->next();
            return new Ast\ConstExpr\ConstExprIntegerNode($value);
        }
        if ($tokens->isCurrentTokenType(Lexer::TOKEN_SINGLE_QUOTED_STRING)) {
            $value = $tokens->currentTokenValue();
            if ($trimStrings) {
                $value = \trim($tokens->currentTokenValue(), "'");
            }
            $tokens->next();
            return new Ast\ConstExpr\ConstExprStringNode($value);
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_DOUBLE_QUOTED_STRING)) {
            $value = $tokens->currentTokenValue();
            if ($trimStrings) {
                $value = \trim($tokens->currentTokenValue(), '"');
            }
            $tokens->next();
            return new Ast\ConstExpr\ConstExprStringNode($value);
        } elseif ($tokens->isCurrentTokenType(Lexer::TOKEN_IDENTIFIER)) {
            $identifier = $tokens->currentTokenValue();
            $tokens->next();
            switch (\strtolower($identifier)) {
                case 'true':
                    return new Ast\ConstExpr\ConstExprTrueNode();
                case 'false':
                    return new Ast\ConstExpr\ConstExprFalseNode();
                case 'null':
                    return new Ast\ConstExpr\ConstExprNullNode();
                case 'array':
                    $tokens->consumeTokenType(Lexer::TOKEN_OPEN_PARENTHESES);
                    return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_PARENTHESES);
            }
            if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_COLON)) {
                $classConstantName = '';
                $lastType = null;
                while (\true) {
                    if ($lastType !== Lexer::TOKEN_IDENTIFIER && $tokens->currentTokenType() === Lexer::TOKEN_IDENTIFIER) {
                        $classConstantName .= $tokens->currentTokenValue();
                        $tokens->consumeTokenType(Lexer::TOKEN_IDENTIFIER);
                        $lastType = Lexer::TOKEN_IDENTIFIER;
                        continue;
                    }
                    if ($lastType !== Lexer::TOKEN_WILDCARD && $tokens->tryConsumeTokenType(Lexer::TOKEN_WILDCARD)) {
                        $classConstantName .= '*';
                        $lastType = Lexer::TOKEN_WILDCARD;
                        if ($tokens->getSkippedHorizontalWhiteSpaceIfAny() !== '') {
                            break;
                        }
                        continue;
                    }
                    if ($lastType === null) {
                        // trigger parse error if nothing valid was consumed
                        $tokens->consumeTokenType(Lexer::TOKEN_WILDCARD);
                    }
                    break;
                }
                return new Ast\ConstExpr\ConstFetchNode($identifier, $classConstantName);
            }
            return new Ast\ConstExpr\ConstFetchNode('', $identifier);
        } elseif ($tokens->tryConsumeTokenType(Lexer::TOKEN_OPEN_SQUARE_BRACKET)) {
            return $this->parseArray($tokens, Lexer::TOKEN_CLOSE_SQUARE_BRACKET);
        }
        throw new \LogicException($tokens->currentTokenValue());
    }
    /**
     *
     */
    private function parseArray(TokenIterator $tokens, int $endToken) : Ast\ConstExpr\ConstExprArrayNode
    {
        $items = [];
        if (!$tokens->tryConsumeTokenType($endToken)) {
            do {
                $items[] = $this->parseArrayItem($tokens);
            } while ($tokens->tryConsumeTokenType(Lexer::TOKEN_COMMA) && !$tokens->isCurrentTokenType($endToken));
            $tokens->consumeTokenType($endToken);
        }
        return new Ast\ConstExpr\ConstExprArrayNode($items);
    }
    /**
     *
     */
    private function parseArrayItem(TokenIterator $tokens) : Ast\ConstExpr\ConstExprArrayItemNode
    {
        $expr = $this->parse($tokens);
        if ($tokens->tryConsumeTokenType(Lexer::TOKEN_DOUBLE_ARROW)) {
            $key = $expr;
            $value = $this->parse($tokens);
        } else {
            $key = null;
            $value = $expr;
        }
        return new Ast\ConstExpr\ConstExprArrayItemNode($key, $value);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Parser;

use PhabelVendor\PHPStan\PhpDocParser\Lexer\Lexer;
class TokenIterator
{
    /** @var mixed[][] */
    private $tokens;
    /** @var int */
    private $index;
    /** @var int[] */
    private $savePoints = [];
    /**
     *
     */
    public function __construct(array $tokens, int $index = 0)
    {
        $this->tokens = $tokens;
        $this->index = $index;
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== Lexer::TOKEN_HORIZONTAL_WS) {
            return;
        }
        $this->index++;
    }
    /**
     *
     */
    public function currentTokenValue() : string
    {
        return $this->tokens[$this->index][Lexer::VALUE_OFFSET];
    }
    /**
     *
     */
    public function currentTokenType() : int
    {
        return $this->tokens[$this->index][Lexer::TYPE_OFFSET];
    }
    /**
     *
     */
    public function currentTokenOffset() : int
    {
        $offset = 0;
        for ($i = 0; $i < $this->index; $i++) {
            $offset += \strlen($this->tokens[$i][Lexer::VALUE_OFFSET]);
        }
        return $offset;
    }
    /**
     *
     */
    public function isCurrentTokenValue(string $tokenValue) : bool
    {
        return $this->tokens[$this->index][Lexer::VALUE_OFFSET] === $tokenValue;
    }
    /**
     *
     */
    public function isCurrentTokenType(int $tokenType) : bool
    {
        return $this->tokens[$this->index][Lexer::TYPE_OFFSET] === $tokenType;
    }
    /**
     *
     */
    public function isPrecededByHorizontalWhitespace() : bool
    {
        return ($this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] ?? -1) === Lexer::TOKEN_HORIZONTAL_WS;
    }
    /**
     * @param int $tokenType
     * @throws \PHPStan\PhpDocParser\Parser\ParserException
     */
    public function consumeTokenType(int $tokenType) : void
    {
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) {
            $this->throwError($tokenType);
        }
        $this->index++;
        if (($this->tokens[$this->index][Lexer::TYPE_OFFSET] ?? -1) !== Lexer::TOKEN_HORIZONTAL_WS) {
            return;
        }
        $this->index++;
    }
    /**
     * @phpstan-impure
     */
    public function tryConsumeTokenValue(string $tokenValue) : bool
    {
        if ($this->tokens[$this->index][Lexer::VALUE_OFFSET] !== $tokenValue) {
            return \false;
        }
        $this->index++;
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
            $this->index++;
        }
        return \true;
    }
    /**
     * @phpstan-impure
     */
    public function tryConsumeTokenType(int $tokenType) : bool
    {
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== $tokenType) {
            return \false;
        }
        $this->index++;
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
            $this->index++;
        }
        return \true;
    }
    /**
     *
     */
    public function getSkippedHorizontalWhiteSpaceIfAny() : string
    {
        if ($this->index > 0 && $this->tokens[$this->index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS) {
            return $this->tokens[$this->index - 1][Lexer::VALUE_OFFSET];
        }
        return '';
    }
    /**
     * @phpstan-impure
     */
    public function joinUntil(int ...$tokenType) : string
    {
        $s = '';
        while (!\in_array($this->tokens[$this->index][Lexer::TYPE_OFFSET], $tokenType, \true)) {
            $s .= $this->tokens[$this->index++][Lexer::VALUE_OFFSET];
        }
        return $s;
    }
    /**
     *
     */
    public function next() : void
    {
        $this->index++;
        if ($this->tokens[$this->index][Lexer::TYPE_OFFSET] !== Lexer::TOKEN_HORIZONTAL_WS) {
            return;
        }
        $this->index++;
    }
    /**
     * @phpstan-impure
     */
    public function forwardToTheEnd() : void
    {
        $lastToken = \count($this->tokens) - 1;
        $this->index = $lastToken;
    }
    /**
     *
     */
    public function pushSavePoint() : void
    {
        $this->savePoints[] = $this->index;
    }
    /**
     *
     */
    public function dropSavePoint() : void
    {
        \array_pop($this->savePoints);
    }
    /**
     *
     */
    public function rollback() : void
    {
        $index = \array_pop($this->savePoints);
        \assert($index !== null);
        $this->index = $index;
    }
    /**
     * @param int $expectedTokenType
     * @throws \PHPStan\PhpDocParser\Parser\ParserException
     */
    private function throwError(int $expectedTokenType) : void
    {
        throw new \PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException($this->currentTokenValue(), $this->currentTokenType(), $this->currentTokenOffset(), $expectedTokenType);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprFalseNode implements ConstExprNode
{
    use NodeAttributes;
    /**
     *
     */
    public function __toString() : string
    {
        return 'false';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprIntegerNode implements ConstExprNode
{
    use NodeAttributes;
    /** @var string */
    public $value;
    /**
     *
     */
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->value;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprStringNode implements ConstExprNode
{
    use NodeAttributes;
    /** @var string */
    public $value;
    /**
     *
     */
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->value;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprArrayItemNode implements ConstExprNode
{
    use NodeAttributes;
    /** @var ConstExprNode|null */
    public $key;
    /** @var ConstExprNode */
    public $value;
    /**
     *
     */
    public function __construct(?ConstExprNode $key, ConstExprNode $value)
    {
        $this->key = $key;
        $this->value = $value;
    }
    /**
     *
     */
    public function __toString() : string
    {
        if ($this->key !== null) {
            return "{$this->key} => {$this->value}";
        }
        return "{$this->value}";
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\Node;
interface ConstExprNode extends Node
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstFetchNode implements ConstExprNode
{
    use NodeAttributes;
    /** @var string class name for class constants or empty string for non-class constants */
    public $className;
    /** @var string */
    public $name;
    /**
     *
     */
    public function __construct(string $className, string $name)
    {
        $this->className = $className;
        $this->name = $name;
    }
    /**
     *
     */
    public function __toString() : string
    {
        if ($this->className === '') {
            return $this->name;
        }
        return "{$this->className}::{$this->name}";
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprTrueNode implements ConstExprNode
{
    use NodeAttributes;
    /**
     *
     */
    public function __toString() : string
    {
        return 'true';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprNullNode implements ConstExprNode
{
    use NodeAttributes;
    /**
     *
     */
    public function __toString() : string
    {
        return 'null';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprArrayNode implements ConstExprNode
{
    use NodeAttributes;
    /** @var ConstExprArrayItemNode[] */
    public $items;
    /**
     * @param ConstExprArrayItemNode[] $items
     */
    public function __construct(array $items)
    {
        $this->items = $items;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return '[' . \implode(', ', $this->items) . ']';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstExprFloatNode implements ConstExprNode
{
    use NodeAttributes;
    /** @var string */
    public $value;
    /**
     *
     */
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->value;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast;

trait NodeAttributes
{
    /** @var array<string, mixed> */
    private $attributes = [];
    /**
     * @param string $key
     * @param mixed $value
     */
    public function setAttribute(string $key, $value) : void
    {
        $this->attributes[$key] = $value;
    }
    /**
     *
     */
    public function hasAttribute(string $key) : bool
    {
        return \array_key_exists($key, $this->attributes);
    }
    /**
     * @param string $key
     * @return mixed
     */
    public function getAttribute(string $key)
    {
        if ($this->hasAttribute($key)) {
            return $this->attributes[$key];
        }
        return null;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast;

interface Node
{
    /**
     *
     */
    public function __toString() : string;
    /**
     * @param string $key
     * @param mixed $value
     */
    public function setAttribute(string $key, $value) : void;
    /**
     *
     */
    public function hasAttribute(string $key) : bool;
    /**
     * @param string $key
     * @return mixed
     */
    public function getAttribute(string $key);
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class CallableTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var IdentifierTypeNode */
    public $identifier;
    /** @var CallableTypeParameterNode[] */
    public $parameters;
    /** @var TypeNode */
    public $returnType;
    /**
     *
     */
    public function __construct(IdentifierTypeNode $identifier, array $parameters, TypeNode $returnType)
    {
        $this->identifier = $identifier;
        $this->parameters = $parameters;
        $this->returnType = $returnType;
    }
    /**
     *
     */
    public function __toString() : string
    {
        $parameters = \implode(', ', $this->parameters);
        return "{$this->identifier}({$parameters}): {$this->returnType}";
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\Node;
interface TypeNode extends Node
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprIntegerNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprStringNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ArrayShapeItemNode implements TypeNode
{
    use NodeAttributes;
    /** @var ConstExprIntegerNode|ConstExprStringNode|IdentifierTypeNode|null */
    public $keyName;
    /** @var bool */
    public $optional;
    /** @var TypeNode */
    public $valueType;
    /**
     * @param (ConstExprIntegerNode | ConstExprStringNode | IdentifierTypeNode | null) $keyName
     */
    public function __construct($keyName, bool $optional, TypeNode $valueType)
    {
        $this->keyName = $keyName;
        $this->optional = $optional;
        $this->valueType = $valueType;
    }
    /**
     *
     */
    public function __toString() : string
    {
        if ($this->keyName !== null) {
            return \sprintf('%s%s: %s', (string) $this->keyName, $this->optional ? '?' : '', (string) $this->valueType);
        }
        return (string) $this->valueType;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ArrayShapeNode implements TypeNode
{
    use NodeAttributes;
    /** @var ArrayShapeItemNode[] */
    public $items;
    /**
     *
     */
    public function __construct(array $items)
    {
        $this->items = $items;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return 'array{' . \implode(', ', $this->items) . '}';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ThisTypeNode implements TypeNode
{
    use NodeAttributes;
    /**
     *
     */
    public function __toString() : string
    {
        return '$this';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class IdentifierTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var string */
    public $name;
    /**
     *
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class UnionTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var TypeNode[] */
    public $types;
    /**
     *
     */
    public function __construct(array $types)
    {
        $this->types = $types;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return '(' . \implode(' | ', $this->types) . ')';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ArrayTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /**
     *
     */
    public function __construct(TypeNode $type)
    {
        $this->type = $type;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->type . '[]';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\Node;
use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class CallableTypeParameterNode implements Node
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /** @var bool */
    public $isReference;
    /** @var bool */
    public $isVariadic;
    /** @var string (may be empty) */
    public $parameterName;
    /** @var bool */
    public $isOptional;
    /**
     *
     */
    public function __construct(TypeNode $type, bool $isReference, bool $isVariadic, string $parameterName, bool $isOptional)
    {
        $this->type = $type;
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->parameterName = $parameterName;
        $this->isOptional = $isOptional;
    }
    /**
     *
     */
    public function __toString() : string
    {
        $type = "{$this->type} ";
        $isReference = $this->isReference ? '&' : '';
        $isVariadic = $this->isVariadic ? '...' : '';
        $default = $this->isOptional ? ' = default' : '';
        return "{$type}{$isReference}{$isVariadic}{$this->parameterName}{$default}";
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class IntersectionTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var TypeNode[] */
    public $types;
    /**
     *
     */
    public function __construct(array $types)
    {
        $this->types = $types;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return '(' . \implode(' & ', $this->types) . ')';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class NullableTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /**
     *
     */
    public function __construct(TypeNode $type)
    {
        $this->type = $type;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return '?' . $this->type;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class GenericTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var IdentifierTypeNode */
    public $type;
    /** @var TypeNode[] */
    public $genericTypes;
    /**
     *
     */
    public function __construct(IdentifierTypeNode $type, array $genericTypes)
    {
        $this->type = $type;
        $this->genericTypes = $genericTypes;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->type . '<' . \implode(', ', $this->genericTypes) . '>';
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\Type;

use PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class ConstTypeNode implements TypeNode
{
    use NodeAttributes;
    /** @var ConstExprNode */
    public $constExpr;
    /**
     *
     */
    public function __construct(ConstExprNode $constExpr)
    {
        $this->constExpr = $constExpr;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->constExpr->__toString();
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class MixinTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->type} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
class ImplementsTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var GenericTypeNode */
    public $type;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(GenericTypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->type} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class TemplateTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string */
    public $name;
    /** @var TypeNode|null */
    public $bound;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(string $name, ?TypeNode $bound, string $description)
    {
        $this->name = $name;
        $this->bound = $bound;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        $bound = $this->bound !== null ? " of {$this->bound}" : '';
        return \trim("{$this->name}{$bound} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class VarTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /** @var string (may be empty) */
    public $variableName;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(TypeNode $type, string $variableName, string $description)
    {
        $this->type = $type;
        $this->variableName = $variableName;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->type} " . \trim("{$this->variableName} {$this->description}"));
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class ParamTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /** @var bool */
    public $isReference;
    /** @var bool */
    public $isVariadic;
    /** @var string */
    public $parameterName;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(TypeNode $type, bool $isVariadic, string $parameterName, string $description, bool $isReference = \false)
    {
        $this->type = $type;
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->parameterName = $parameterName;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        $reference = $this->isReference ? '&' : '';
        $variadic = $this->isVariadic ? '...' : '';
        return \trim("{$this->type} {$reference}{$variadic}{$this->parameterName} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class PhpDocTextNode implements PhpDocChildNode
{
    use NodeAttributes;
    /** @var string */
    public $text;
    /**
     *
     */
    public function __construct(string $text)
    {
        $this->text = $text;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->text;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class InvalidTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string (may be empty) */
    public $value;
    /** @var \PHPStan\PhpDocParser\Parser\ParserException */
    public $exception;
    /**
     *
     */
    public function __construct(string $value, \PhabelVendor\PHPStan\PhpDocParser\Parser\ParserException $exception)
    {
        $this->value = $value;
        $this->exception = $exception;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->value;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\Node;
use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class PhpDocNode implements Node
{
    use NodeAttributes;
    /** @var PhpDocChildNode[] */
    public $children;
    /**
     * @param PhpDocChildNode[] $children
     */
    public function __construct(array $children)
    {
        $this->children = $children;
    }
    /**
     * @return PhpDocTagNode[]
     */
    public function getTags() : array
    {
        return \array_filter($this->children, static function (PhpDocChildNode $child) : bool {
            return $child instanceof PhpDocTagNode;
        });
    }
    /**
     * @param string $tagName
     * @return PhpDocTagNode[]
     */
    public function getTagsByName(string $tagName) : array
    {
        return \array_filter($this->getTags(), static function (PhpDocTagNode $tag) use($tagName) : bool {
            return $tag->name === $tagName;
        });
    }
    /**
     * @return VarTagValueNode[]
     */
    public function getVarTagValues(string $tagName = '@var') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof VarTagValueNode;
        }), 'value');
    }
    /**
     * @return ParamTagValueNode[]
     */
    public function getParamTagValues(string $tagName = '@param') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof ParamTagValueNode;
        }), 'value');
    }
    /**
     * @return TemplateTagValueNode[]
     */
    public function getTemplateTagValues(string $tagName = '@template') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof TemplateTagValueNode;
        }), 'value');
    }
    /**
     * @return ExtendsTagValueNode[]
     */
    public function getExtendsTagValues(string $tagName = '@extends') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof ExtendsTagValueNode;
        }), 'value');
    }
    /**
     * @return ImplementsTagValueNode[]
     */
    public function getImplementsTagValues(string $tagName = '@implements') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof ImplementsTagValueNode;
        }), 'value');
    }
    /**
     * @return UsesTagValueNode[]
     */
    public function getUsesTagValues(string $tagName = '@use') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof UsesTagValueNode;
        }), 'value');
    }
    /**
     * @return ReturnTagValueNode[]
     */
    public function getReturnTagValues(string $tagName = '@return') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof ReturnTagValueNode;
        }), 'value');
    }
    /**
     * @return ThrowsTagValueNode[]
     */
    public function getThrowsTagValues(string $tagName = '@throws') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof ThrowsTagValueNode;
        }), 'value');
    }
    /**
     * @return MixinTagValueNode[]
     */
    public function getMixinTagValues(string $tagName = '@mixin') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof MixinTagValueNode;
        }), 'value');
    }
    /**
     * @return \PHPStan\PhpDocParser\Ast\PhpDoc\DeprecatedTagValueNode[]
     */
    public function getDeprecatedTagValues() : array
    {
        return \array_column(\array_filter($this->getTagsByName('@deprecated'), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof DeprecatedTagValueNode;
        }), 'value');
    }
    /**
     * @return PropertyTagValueNode[]
     */
    public function getPropertyTagValues(string $tagName = '@property') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof PropertyTagValueNode;
        }), 'value');
    }
    /**
     * @return PropertyTagValueNode[]
     */
    public function getPropertyReadTagValues(string $tagName = '@property-read') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof PropertyTagValueNode;
        }), 'value');
    }
    /**
     * @return PropertyTagValueNode[]
     */
    public function getPropertyWriteTagValues(string $tagName = '@property-write') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof PropertyTagValueNode;
        }), 'value');
    }
    /**
     * @return MethodTagValueNode[]
     */
    public function getMethodTagValues(string $tagName = '@method') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof MethodTagValueNode;
        }), 'value');
    }
    /**
     * @return TypeAliasTagValueNode[]
     */
    public function getTypeAliasTagValues(string $tagName = '@phpstan-type') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof TypeAliasTagValueNode;
        }), 'value');
    }
    /**
     * @return TypeAliasImportTagValueNode[]
     */
    public function getTypeAliasImportTagValues(string $tagName = '@phpstan-import-type') : array
    {
        return \array_column(\array_filter($this->getTagsByName($tagName), static function (PhpDocTagNode $tag) : bool {
            return $tag->value instanceof TypeAliasImportTagValueNode;
        }), 'value');
    }
    /**
     *
     */
    public function __toString() : string
    {
        $children = \array_map(static function (PhpDocChildNode $child) : string {
            $s = (string) $child;
            return $s === '' ? '' : ' ' . $s;
        }, $this->children);
        return "/**\n *" . \implode("\n *", $children) . "\n */";
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class DeprecatedTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(string $description)
    {
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim($this->description);
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class PropertyTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /** @var string */
    public $propertyName;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(TypeNode $type, string $propertyName, string $description)
    {
        $this->type = $type;
        $this->propertyName = $propertyName;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->type} {$this->propertyName} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class ReturnTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->type} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class TypeAliasTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string */
    public $alias;
    /** @var TypeNode */
    public $type;
    /**
     *
     */
    public function __construct(string $alias, TypeNode $type)
    {
        $this->alias = $alias;
        $this->type = $type;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->alias} {$this->type}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
class UsesTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var GenericTypeNode */
    public $type;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(GenericTypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->type} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\Node;
interface PhpDocTagValueNode extends Node
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
class TypeAliasImportTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string */
    public $importedAlias;
    /** @var IdentifierTypeNode */
    public $importedFrom;
    /** @var string|null */
    public $importedAs;
    /**
     *
     */
    public function __construct(string $importedAlias, IdentifierTypeNode $importedFrom, ?string $importedAs)
    {
        $this->importedAlias = $importedAlias;
        $this->importedFrom = $importedFrom;
        $this->importedAs = $importedAs;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->importedAlias} from {$this->importedFrom}" . ($this->importedAs !== null ? " as {$this->importedAs}" : ''));
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\ConstExpr\ConstExprNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Node;
use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class MethodTagValueParameterNode implements Node
{
    use NodeAttributes;
    /** @var TypeNode|null */
    public $type;
    /** @var bool */
    public $isReference;
    /** @var bool */
    public $isVariadic;
    /** @var string */
    public $parameterName;
    /** @var ConstExprNode|null */
    public $defaultValue;
    /**
     *
     */
    public function __construct(?TypeNode $type, bool $isReference, bool $isVariadic, string $parameterName, ?ConstExprNode $defaultValue)
    {
        $this->type = $type;
        $this->isReference = $isReference;
        $this->isVariadic = $isVariadic;
        $this->parameterName = $parameterName;
        $this->defaultValue = $defaultValue;
    }
    /**
     *
     */
    public function __toString() : string
    {
        $type = $this->type !== null ? "{$this->type} " : '';
        $isReference = $this->isReference ? '&' : '';
        $isVariadic = $this->isVariadic ? '...' : '';
        $default = $this->defaultValue !== null ? " = {$this->defaultValue}" : '';
        return "{$type}{$isReference}{$isVariadic}{$this->parameterName}{$default}";
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\GenericTypeNode;
class ExtendsTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var GenericTypeNode */
    public $type;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(GenericTypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->type} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class MethodTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var bool */
    public $isStatic;
    /** @var TypeNode|null */
    public $returnType;
    /** @var string */
    public $methodName;
    /** @var MethodTagValueParameterNode[] */
    public $parameters;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(bool $isStatic, ?TypeNode $returnType, string $methodName, array $parameters, string $description)
    {
        $this->isStatic = $isStatic;
        $this->returnType = $returnType;
        $this->methodName = $methodName;
        $this->parameters = $parameters;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        $static = $this->isStatic ? 'static ' : '';
        $returnType = $this->returnType !== null ? "{$this->returnType} " : '';
        $parameters = \implode(', ', $this->parameters);
        $description = $this->description !== '' ? " {$this->description}" : '';
        return "{$static}{$returnType}{$this->methodName}({$parameters}){$description}";
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class GenericTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var string (may be empty) */
    public $value;
    /**
     *
     */
    public function __construct(string $value)
    {
        $this->value = $value;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->value;
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\Node;
interface PhpDocChildNode extends Node
{
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
class ThrowsTagValueNode implements PhpDocTagValueNode
{
    use NodeAttributes;
    /** @var TypeNode */
    public $type;
    /** @var string (may be empty) */
    public $description;
    /**
     *
     */
    public function __construct(TypeNode $type, string $description)
    {
        $this->type = $type;
        $this->description = $description;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->type} {$this->description}");
    }
}
<?php

declare (strict_types=1);
namespace PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc;

use PhabelVendor\PHPStan\PhpDocParser\Ast\NodeAttributes;
class PhpDocTagNode implements PhpDocChildNode
{
    use NodeAttributes;
    /** @var string */
    public $name;
    /** @var PhpDocTagValueNode */
    public $value;
    /**
     *
     */
    public function __construct(string $name, PhpDocTagValueNode $value)
    {
        $this->name = $name;
        $this->value = $value;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return \trim("{$this->name} {$this->value}");
    }
}
<?php

namespace Phabel;

abstract class EventHandler implements \Phabel\EventHandlerInterface
{
    /**
     *
     */
    public function onStart() : void
    {
    }
    /**
     *
     */
    public function onBeginPluginGraphResolution() : void
    {
    }
    /**
     *
     */
    public function onEndPluginGraphResolution() : void
    {
    }
    /**
     *
     */
    public function onBeginDirectoryTraversal(int $total, int $workers) : void
    {
    }
    /**
     *
     */
    public function onBeginAstTraversal(string $file) : void
    {
    }
    /**
     * @param (int | \Throwable) $iterationsOrError
     */
    public function onEndAstTraversal(string $file, $iterationsOrError) : void
    {
        if (!$iterationsOrError instanceof \Throwable) {
            if (!\is_int($iterationsOrError)) {
                if (!(\is_bool($iterationsOrError) || \is_numeric($iterationsOrError))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #2 ($iterationsOrError) must be of type Throwable|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($iterationsOrError) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                $iterationsOrError = (int) $iterationsOrError;
            }
        }
    }
    /**
     *
     */
    public function onEndDirectoryTraversal() : void
    {
    }
    /**
     *
     */
    public function onBeginClassGraphMerge(int $count) : void
    {
    }
    /**
     *
     */
    public function onClassGraphMerged() : void
    {
    }
    /**
     *
     */
    public function onEndClassGraphMerge() : void
    {
    }
    /**
     *
     */
    public function onEnd() : void
    {
    }
}
<?php

namespace Phabel;

use PhabelVendor\Amp\Parallel\Worker\DefaultPool;
use PhabelVendor\Amp\Promise;
use Phabel\Composer\Transformer;
use Phabel\Plugin\ClassStoragePlugin;
use Phabel\PluginGraph\Graph;
use Phabel\PluginGraph\ResolvedGraph;
use Phabel\Target\Php;
use Phabel\Tasks\Init;
use Phabel\Tasks\Run;
use Phabel\Tasks\Shutdown;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Parser;
use PhabelVendor\PhpParser\ParserFactory;
use PhabelVendor\PhpParser\PrettyPrinter\Standard;
use RuntimeException;
use PhabelVendor\SebastianBergmann\CodeCoverage\CodeCoverage;
use PhabelVendor\SebastianBergmann\CodeCoverage\Driver\Selector;
use PhabelVendor\SebastianBergmann\CodeCoverage\Filter;
use PhabelVendor\SebastianBergmann\CodeCoverage\Report\PHP as PHPReport;
use SplFileInfo;
use SplQueue;
use function PhabelVendor\Amp\call;
use function PhabelVendor\Amp\Promise\wait;
/**
 * AST traverser.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Traverser
{
    /**
     * Resolved plugin graph.
     *
     * @var ResolvedGraph
     */
    private ResolvedGraph $graph;
    /**
     * Parser instance.
     */
    private Parser $parser;
    /**
     * Printer instance.
     */
    private Standard $printer;
    /**
     * Plugin queue for specific package.
     *
     * @var (SplQueue<SplQueue<PluginInterface>> | null)
     */
    private ?SplQueue $packageQueue = null;
    /**
     * Event handler.
     *
     * @var (EventHandlerInterface | null)
     */
    private ?\Phabel\EventHandlerInterface $eventHandler = null;
    /**
     * Input directory.
     *
     * @var string
     */
    private string $input = '';
    /**
     * Output directory.
     *
     * @var string
     */
    private string $output = '';
    /**
     * Package paths.
     *
     * @var array<string, string>
     */
    private array $packagePaths = [];
    /**
     * Composer paths.
     *
     * @var array<string, array{0: string, 1: string}>
     */
    private array $composerPaths = [];
    /**
     * Composer vendor directory.
     *
     * @var string
     */
    private string $composerVendor;
    /**
     * Files to work on.
     *
     * @var list<string>
     */
    private ?array $files = null;
    /**
     * Coverage path.
     *
     * @var string
     */
    private string $coverage = '';
    /**
     * Current input file.
     */
    private string $inputFile = '';
    /**
     * Current output file.
     */
    private string $outputFile = '';
    /**
     * Number of times we traversed directories.
     *
     * @var integer
     */
    private int $count = 0;
    /**
     * Generate traverser from basic plugin instances.
     *
     * @param Plugin ...$plugin Plugins
     *
     * @return self
     */
    public static function fromPlugin(\Phabel\Plugin ...$plugin) : self
    {
        $queue = new SplQueue();
        foreach ($plugin as $p) {
            $queue->enqueue($p);
        }
        $final = new SplQueue();
        $final->enqueue($queue);
        $res = new self();
        $res->graph = new ResolvedGraph($final);
        return $res;
    }
    /**
     * Constructor.
     *
     * @param ?EventHandlerInterface $EventHandlerInterface Event handler
     */
    public function __construct(?\Phabel\EventHandlerInterface $eventHandler = null)
    {
        $this->parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
        $this->printer = new Standard();
        $this->eventHandler = $eventHandler;
    }
    /**
     * Set plugin array.
     *
     * @param array $plugins
     *
     * @psalm-param array<class-string<PluginInterface>, array> $plugins
     *
     * @return self
     */
    public function setPlugins(array $plugins) : self
    {
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onBeginPluginGraphResolution();
        $graph = new Graph();
        foreach ($plugins as $plugin => $config) {
            $graph->addPlugin($plugin, $config, $graph->getPackageContext());
        }
        $this->graph = $graph->flatten();
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndPluginGraphResolution();
        return $this;
    }
    /**
     * Set plugin graph.
     *
     * @param Graph $graph
     *
     * @return self
     */
    public function setPluginGraph(Graph $graph) : self
    {
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onBeginPluginGraphResolution();
        $this->graph = $graph->flatten();
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndPluginGraphResolution();
        return $this;
    }
    /**
     * Get resolved plugin graph.
     *
     * @return ResolvedGraph
     */
    public function getGraph() : ResolvedGraph
    {
        return $this->graph;
    }
    /**
     * Set resolved plugin graph.
     *
     * @param ResolvedGraph $graph Resolved graph
     *
     * @return self
     */
    public function setGraph(ResolvedGraph $graph) : self
    {
        $this->graph = $graph;
        return $this;
    }
    /**
     * Set input path.
     *
     * @param string $input
     * @return self
     */
    public function setInput(string $input) : self
    {
        if (!\file_exists($input)) {
            throw new \RuntimeException("File {$input} does not exist!");
        }
        $this->input = $input;
        return $this;
    }
    /**
     * Set output path.
     *
     * @param string $output
     * @return self
     */
    public function setOutput(string $output) : self
    {
        $this->output = $output;
        return $this;
    }
    /**
     * Set composer paths.
     *
     * @param array<string, array{0: string, 1: string}> $paths
     *
     * @return self
     */
    public function setComposerPaths(array $paths) : self
    {
        $this->composerPaths = $paths;
        $this->composerVendor = \str_replace('\\', '/', \realpath(\getcwd() . '/vendor')) . '/';
        $this->packagePaths = [];
        foreach ($paths as $package => [$old, $new]) {
            $this->packagePaths[$old] = $package;
            $this->packagePaths[$new] = $package;
        }
        return $this;
    }
    /**
     *
     */
    public function getPackageName(string $path) : string
    {
        if (\str_starts_with($path, $this->composerVendor)) {
            [$package] = Transformer::extractTarget(\Phabel\Target\Php80\Polyfill::substr($path, \strlen($this->composerVendor)));
            $result = \implode('/', \array_slice(\explode('/', $package, 3), 0, 2));
            return $result;
        }
        $orig = $path;
        $last = '';
        while (($path = \dirname($path)) !== $last) {
            $last = $path;
            if (isset($this->packagePaths[$path])) {
                return $this->packagePaths[$path];
            }
        }
        throw new RuntimeException("Could not find package for path {$orig}!");
    }
    /**
     * Set coverage path.
     *
     * @param string $coverage
     * @return self
     */
    public function setCoverage(string $coverage) : self
    {
        $this->coverage = $coverage;
        return $this;
    }
    /**
     * Start code coverage.
     *
     * @param string $coveragePath Coverage path
     *
     * @return ?object
     */
    public static function startCoverage(string $coveragePath) : ?object
    {
        if (!$coveragePath || !\class_exists(CodeCoverage::class)) {
            return null;
        }
        try {
            $filter = new Filter();
            $filter->includeDirectory(\realpath(__DIR__ . '/../src'));
            $coverage = new CodeCoverage((new Selector())->forLineCoverage($filter), $filter);
            $coverage->start('phabel');
            return new class($coverage, $coveragePath)
            {
                /**
                 *
                 */
                private string $coveragePath;
                /**
                 *
                 */
                private CodeCoverage $coverage;
                /**
                 *
                 */
                public function __construct(CodeCoverage $coverage, string $coveragePath)
                {
                    $this->coverage = $coverage;
                    $this->coveragePath = $coveragePath;
                }
                /**
                 *
                 */
                public function __destruct()
                {
                    $this->coverage->stop();
                    if (\file_exists($this->coveragePath)) {
                        $this->coverage->merge(require $this->coveragePath);
                    }
                    (new PHPReport())->process($this->coverage, $this->coveragePath);
                }
            };
        } catch (\Throwable $e) {
        }
        return null;
    }
    /**
     * Prepare list of files to work on.
     *
     * @return void
     */
    private function prepareFiles() : void
    {
        if ($this->files === null) {
            if (isset($this->input) && \is_dir($this->input)) {
                if (!\file_exists($this->output)) {
                    \mkdir($this->output, 0777, \true);
                }
                $this->output = \realpath($this->output);
                $this->input = \realpath($this->input);
                $this->files = [];
                \Phabel\Tools::traverseCopy($this->input, $this->output, function (SplFileInfo $f, string $input, string $output) : bool {
                    if ($f->getExtension() === 'php') {
                        $this->files[\str_replace('\\', '/', $input)] = \str_replace('\\', '/', $output);
                        return \true;
                    }
                    return \false;
                });
            } elseif ($this->composerPaths) {
                $autoload = $this->composerVendor . 'autoload.php';
                $composerDir = [$this->composerVendor . 'composer/'];
                foreach (Php::VERSIONS as $target) {
                    $composerDir[] = $this->composerVendor . \Phabel\Target\Php80\Polyfill::substr(Transformer::injectTarget('composer/pkg', $target), 0, -3);
                }
                $cb = function (SplFileInfo $f, string $input, string $output) use($autoload, $composerDir) : bool {
                    if ($f->getExtension() !== 'php') {
                        return \false;
                    }
                    $real = \str_replace('\\', '/', $input);
                    if ($real === $autoload) {
                        return \false;
                    }
                    foreach ($composerDir as $dir) {
                        if (\str_starts_with($real, $dir)) {
                            return \false;
                        }
                    }
                    $this->files[$real] = \str_replace('\\', '/', $output);
                    return \true;
                };
                \Phabel\Tools::traverseCopy($this->composerVendor, $this->composerVendor, $cb);
                foreach ($this->composerPaths as [$old, $new]) {
                    \Phabel\Tools::traverseCopy($old, $new, $cb);
                }
            }
        }
    }
    /**
     * Run phabel asynchronously.
     *
     * @return array
     */
    public function runAsync(int $threads = -1) : array
    {
        return wait($this->runAsyncPromise($threads));
    }
    /**
     * Run phabel asynchronously.
     *
     * @return Promise<array>
     */
    public function runAsyncPromise(int $threads = -1) : Promise
    {
        if (!\interface_exists(Promise::class)) {
            throw new \Phabel\Exception("amphp/parallel must be installed to parallelize transforms!");
        }
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onStart();
        $this->prepareFiles();
        if ($threads === -1) {
            $threads = \Phabel\Tools::getCpuCount();
        }
        $coverages = [];
        return call(function () use(&$coverages, $threads) {
            $packages = [];
            $first = !$this->count++;
            $count = 0;
            $promises = [];
            $classStorage = null;
            $pool = new DefaultPool($threads);
            $promises = [];
            for ($x = 0; $x < $threads; $x++) {
                $promises[] = $pool->enqueue(new Init($this->graph));
            }
            (yield $promises);
            $packages = $this->graph->getPackages();
            unset($this->graph);
            ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onBeginDirectoryTraversal(\count($this->files), $threads);
            $promises = [];
            foreach ($this->files as $input => $output) {
                $promise = call(function () use($pool, $input, $output, $count, $first, &$promises, &$coverages) {
                    ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onBeginAstTraversal($input);
                    $package = null;
                    if ($this->composerPaths) {
                        $package = $this->getPackageName($output);
                    }
                    $res = (yield $pool->enqueue(new Run($input, $output, $package, $this->coverage ? "{$this->coverage}{$count}.php" : '')));
                    if ($this->coverage) {
                        $coverages[] = "{$this->coverage}{$count}.php";
                    }
                    if ($res instanceof \Phabel\ExceptionWrapper) {
                        $res = $res->getException();
                        if (!($first && \str_contains($res->getMessage(), ' while parsing '))) {
                            throw $res;
                        }
                        if (\realpath($input) !== \realpath($output)) {
                            \copy($input, $output);
                        }
                        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndAstTraversal($input, $res);
                    }
                    \chmod($output, \fileperms($input));
                    unset($promises[$count]);
                });
                $promises[$count] = $promise;
                $count++;
            }
            (yield $promises);
            ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndDirectoryTraversal();
            ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onBeginClassGraphMerge($threads);
            $promises = [];
            /** @var ClassStoragePlugin|null */
            $classStorage = null;
            for ($x = 0; $x < $threads; $x++) {
                $promises[] = call(function () use($pool, &$classStorage) {
                    /** @var ClassStoragePlugin */
                    $newClassStorage = (yield $pool->enqueue(new Shutdown()));
                    if (!$classStorage) {
                        $classStorage = $newClassStorage;
                    } else {
                        $classStorage->merge($newClassStorage);
                    }
                    ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onClassGraphMerged();
                });
            }
            (yield $promises);
            ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndClassGraphMerge();
            (yield $pool->shutdown());
            unset($pool);
            if ($classStorage) {
                [$plugins, $this->files] = $classStorage->finish();
                unset($classStorage);
                if ($plugins && $this->files) {
                    $this->input = $this->output;
                    $this->composerPaths = [];
                    $this->setPlugins($plugins);
                    return $this->run();
                }
            }
            /** @var CodeCoverage|null $coverage */
            $coverage = null;
            foreach ($coverages as $file) {
                if (!\file_exists($file)) {
                    continue;
                }
                if (!$coverage) {
                    /** @var CodeCoverage $coverage */
                    $coverage = (include $file);
                    \unlink($file);
                    continue;
                }
                $coverage->merge(include $file);
                \unlink($file);
            }
            if ($coverage) {
                (new PHPReport())->process($coverage, $this->coverage);
            }
            ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEnd();
            return $packages;
        });
    }
    /**
     * Run phabel.
     *
     * @return array<string, string>
     */
    public function run(int $threads = 1) : array
    {
        if ($threads > 1 || $threads === -1) {
            return $this->runAsync($threads);
        }
        \set_error_handler(function (int $errno = 0, string $errstr = '', string $errfile = '', int $errline = -1) : bool {
            // If error is suppressed with @, don't throw an exception
            if (\Phabel\Target\Php80\Polyfill::error_reporting() === 0) {
                return \false;
            }
            throw new \Phabel\Exception($errstr, $errno, null, $errfile, $errline);
        });
        $packages = [];
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onStart();
        $this->prepareFiles();
        while (\true) {
            $this->runInternal();
            $packages += $this->graph->getPackages();
            $classStorage = $this->graph->getClassStorage();
            if (!$classStorage) {
                break;
            }
            [$plugins, $this->files] = $classStorage->finish();
            unset($classStorage);
            if (!$plugins || !$this->files) {
                break;
            }
            $this->input = $this->output;
            $this->composerPaths = [];
            $this->setPlugins($plugins);
        }
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEnd();
        \restore_error_handler();
        return $packages;
    }
    /**
     * Run phabel (internal function).
     *
     * @internal
     */
    public function runInternal() : void
    {
        $_ = self::startCoverage($this->coverage);
        $first = !$this->count++;
        $this->packageQueue = null;
        if (\is_file($this->input)) {
            $this->traverse(\realpath($this->input), \realpath($this->output) ?: $this->output);
            return;
        }
        $this->eventHandler->onBeginDirectoryTraversal(\count($this->files), 1);
        foreach ($this->files as $input => $output) {
            $_ = self::startCoverage($this->coverage);
            if ($this->composerPaths) {
                $this->setPackage($this->getPackageName($output));
            } else {
                $this->packageQueue = null;
            }
            try {
                $it = $this->traverse($input, $output);
            } catch (\Throwable $e) {
                if (!($first && $e instanceof \Phabel\Exception && \str_contains($e->getMessage(), ' while parsing '))) {
                    throw $e;
                }
                if (\realpath($input) !== \realpath($output)) {
                    \copy($input, $output);
                }
                ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndAstTraversal($input, $e);
            }
            \chmod($output, \fileperms($input));
        }
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndDirectoryTraversal();
    }
    /**
     * Set package name.
     *
     * @param ?string $package Package name
     *
     * @return void
     */
    public function setPackage(?string $package) : void
    {
        /** @var SplQueue<SplQueue<PluginInterface>> */
        if (!$package) {
            $this->packageQueue = null;
            return;
        }
        $this->packageQueue = new SplQueue();
        /** @var SplQueue<PluginInterface> */
        $newQueue = new SplQueue();
        foreach ($this->graph->getPlugins() as $queue) {
            if ($newQueue->count()) {
                $this->packageQueue->enqueue($newQueue);
                /** @var SplQueue<PluginInterface> */
                $newQueue = new SplQueue();
            }
            /** @var Plugin */
            foreach ($queue as $plugin) {
                if ($plugin->shouldRun($package)) {
                    $newQueue->enqueue($plugin);
                }
            }
        }
        if ($newQueue->count()) {
            $this->packageQueue->enqueue($newQueue);
        }
    }
    /**
     * Traverse AST of file.
     *
     * @param string $file Relative path
     * @param string $input Input file
     * @param string $output Output file
     *
     * @return int
     */
    public function traverse(string $input, string $output) : int
    {
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onBeginAstTraversal($input);
        /** @var SplQueue<SplQueue<PluginInterface>> */
        $reducedQueue = new SplQueue();
        /** @var SplQueue<PluginInterface> */
        $newQueue = new SplQueue();
        foreach ($this->packageQueue ?? $this->graph->getPlugins() as $queue) {
            if ($newQueue->count()) {
                $reducedQueue->enqueue($newQueue);
                /** @var SplQueue<PluginInterface> */
                $newQueue = new SplQueue();
            }
            /** @var Plugin */
            foreach ($queue as $plugin) {
                if ($plugin->shouldRunFile($input)) {
                    $newQueue->enqueue($plugin);
                }
            }
        }
        if ($newQueue->count()) {
            $reducedQueue->enqueue($newQueue);
        } elseif (!$reducedQueue->count()) {
            if (\realpath($input) !== \realpath($output)) {
                \copy($input, $output);
            }
            ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndAstTraversal($input, 0);
            return 0;
        }
        try {
            $ast = new \Phabel\RootNode($this->parser->parse(\file_get_contents($input)) ?? []);
        } catch (\Throwable $e) {
            $message = $e->getMessage();
            $message .= " while parsing ";
            $message .= $input;
            throw new \Phabel\Exception($message, (int) $e->getCode(), $e, $e->getFile(), $e->getLine());
        }
        $this->inputFile = $input;
        $this->outputFile = $output;
        [$it, $result] = $this->traverseAstInternal($ast, $reducedQueue);
        \file_put_contents($output, $result);
        ($this->eventHandler ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->onEndAstTraversal($input, $it);
        return $it;
    }
    /**
     * Traverse AST.
     *
     * @param Node $node Initial node
     * @param SplQueue $pluginQueue Plugin queue (optional)
     * @param bool $allowMulti Whether to allow multiple iterations on the plugins
     *
     * @psalm-param SplQueue<SplQueue<PluginInterface>> $pluginQueue
     *
     * @return int
     */
    public function traverseAst(Node &$node, SplQueue $pluginQueue = null, bool $allowMulti = \true) : int
    {
        $this->inputFile = '';
        $this->outputFile = '';
        $n = new \Phabel\RootNode([&$node]);
        return $this->traverseAstInternal($n, $pluginQueue, $allowMulti)[0] ?? 0;
    }
    /**
     * Traverse AST.
     *
     * @param RootNode &$node Initial node
     * @param SplQueue $pluginQueue Plugin queue (optional)
     * @param bool $allowMulti Whether to allow multiple iterations on the AST
     *
     * @psalm-param SplQueue<SplQueue<PluginInterface>> $pluginQueue
     * @template T of bool
     *
     * @psalm-param T $allowMulti
     *
     * @return (array{0: int, 1: string} | null)
     * @psalm-return (T is true ? array{0: int, 1: string} : null)
     */
    private function traverseAstInternal(\Phabel\RootNode &$node, SplQueue $pluginQueue = null, bool $allowMulti = \true) : ?array
    {
        $it = 0;
        $result = $this->printer->prettyPrintFile($node->stmts);
        do {
            $context = null;
            try {
                foreach ($pluginQueue ?? $this->packageQueue ?? $this->graph->getPlugins() as $queue) {
                    $context = new \Phabel\Context();
                    $context->setInputFile($this->inputFile);
                    $context->setOutputFile($this->outputFile);
                    $context->push($node);
                    $this->traverseNode($node, $queue, $context);
                    /** @var RootNode $node */
                }
                if (!$allowMulti) {
                    return null;
                }
            } catch (\Throwable $e) {
                $message = $e->getMessage();
                $message .= " while processing ";
                $message .= $this->inputFile;
                $message .= ":";
                try {
                    $message .= $context ? $context->getCurrentChild($context->parents[0])->getStartLine() : "-1";
                } catch (\Throwable $e) {
                    $message .= "-1";
                }
                throw new \Phabel\Exception($message, (int) $e->getCode(), $e, $e->getFile(), $e->getLine());
            }
            $oldResult = $result;
            $result = $this->printer->prettyPrintFile($node->stmts);
            $it++;
        } while ($result !== $oldResult);
        return [$it, $result];
    }
    /**
     * Traverse node.
     *
     * @param Node &$node Node
     * @param SplQueue<PluginInterface> $plugins Plugins
     * @param Context $context Context
     *
     * @return void
     */
    private function traverseNode(Node &$node, SplQueue $plugins, \Phabel\Context $context) : void
    {
        $context->pushResolve($node);
        foreach ($plugins as $plugin) {
            foreach (\Phabel\PluginCache::enterMethods(\get_class($plugin)) as $type => $methods) {
                if (!$node instanceof $type) {
                    continue;
                }
                foreach ($methods as $method) {
                    /** @var Node|null */
                    $result = $plugin->{$method}($node, $context);
                    if ($result instanceof Node) {
                        if (!$result instanceof $node) {
                            $node = $result;
                            continue 2;
                        }
                        $node = $result;
                    }
                }
            }
        }
        $context->push($node);
        /** @var string $name */
        foreach ($node->getSubNodeNames() as $name) {
            $node->setAttribute('currentNode', $name);
            /** @var Node[]|Node|mixed */
            $subNode =& $node->{$name};
            if ($subNode instanceof Node) {
                $this->traverseNode($subNode, $plugins, $context);
                continue;
            }
            if (!\is_array($subNode)) {
                continue;
            }
            for ($index = 0; $index < \count($subNode);) {
                $node->setAttribute('currentNodeIndex', $index);
                if ($subNode[$index] instanceof Node) {
                    $this->traverseNode($subNode[$index], $plugins, $context);
                }
                /**
                 * @psalm-suppress MixedOperand
                 * @var int
                 */
                $index = $node->getAttribute('currentNodeIndex') + 1;
            }
            $node->setAttribute('currentNodeIndex', null);
        }
        $context->pop();
        foreach ($plugins as $plugin) {
            foreach (\Phabel\PluginCache::leaveMethods(\get_class($plugin)) as $type => $methods) {
                if (!$node instanceof $type) {
                    continue;
                }
                foreach ($methods as $method) {
                    /** @var Node|null */
                    $result = $plugin->{$method}($node, $context);
                    if ($result instanceof Node) {
                        if (!$result instanceof $node) {
                            $node = $result;
                            continue 2;
                        }
                        $node = $result;
                    }
                }
            }
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        unset($this->graph);
        while (\gc_collect_cycles()) {
        }
    }
}
<?php

namespace Phabel;

use Phabel\ClassStorage\FunctionStorage;
use Phabel\ClassStorage\Storage;
use Phabel\Plugin\ClassStoragePlugin;
use Phabel\Plugin\TypeHintReplacer;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\NullableType;
use PhabelVendor\PhpParser\Node\UnionType;
final class ClassStorage
{
    const FILE_KEY = 'ClassStorage:file';
    /**
     * Classes.
     *
     * @var array<string, array<string, Storage>>
     */
    private array $classes = [];
    /**
     * Traits.
     *
     * @var array<string, array<string, Storage>>
     */
    private array $traits = [];
    /**
     * Functions.
     *
     * @var array<string, FunctionStorage>
     */
    private array $functions = [];
    /**
     * Files to process.
     *
     * @var array<string, true>
     */
    private array $files = [];
    /**
     * Constructor.
     */
    public function __construct(ClassStoragePlugin $plugin)
    {
        foreach ($plugin->traits as $traits) {
            foreach ($traits as $trait) {
                $trait->resolve($plugin);
            }
        }
        foreach ($plugin->classes as $classes) {
            foreach ($classes as $class) {
                $class->resolve($plugin);
            }
        }
        foreach ($plugin->traits as $name => $fileTraits) {
            foreach ($fileTraits as $file => $trait) {
                $trait = $trait->build();
                $this->traits[$name][$file] = $trait;
                $this->files[$file] = \true;
            }
        }
        foreach ($plugin->classes as $name => $fileClasses) {
            foreach ($fileClasses as $file => $class) {
                $class = $class->build();
                $this->classes[$name][$file] = $class;
                $this->files[$file] = \true;
            }
        }
        $this->functions = $plugin->functions;
    }
    /**
     * Get all files to process.
     *
     * @return array<string, string>
     */
    public function getFiles() : array
    {
        unset($this->files['_']);
        $result = $this->files;
        foreach ($result as $k => $_) {
            $result[$k] = $k;
        }
        return $result;
    }
    /**
     * Check if a file should be processed.
     *
     * @param string $file
     * @return boolean
     */
    public function hasFile(string $file) : bool
    {
        return isset($this->files[$file]);
    }
    /**
     * Get class.
     *
     * @param string $file File name
     * @param string $name Compound name
     *
     * @return Storage
     */
    public function getClass(string $file, string $name) : Storage
    {
        return $this->classes[$name][$file] ?? $this->traits[$name][$file];
    }
    /**
     * Get class by class name.
     *
     * @param class-string $class Class name
     *
     * @return ?Storage
     */
    public function getClassByName(string $class) : ?Storage
    {
        return \array_values($this->classes[$class] ?? [])[0] ?? null;
    }
    /**
     * Get storage.
     *
     * @return \Generator<class-string, Storage, null, void>
     */
    public function getClasses() : \Generator
    {
        foreach ($this->classes as $class => $classes) {
            foreach ($classes as $_ => $storage) {
                (yield $class => $storage);
            }
        }
    }
    /**
     * Get info about function.
     *
     * @param string $function
     * @return (FunctionStorage | null)
     */
    public function getArguments(string $function) : ?FunctionStorage
    {
        return $this->functions[$function] ?? null;
    }
    /**
     * @param (null | Identifier | Name | NullableType | UnionType) $type
     */
    private static function typeArray($type) : array
    {
        if (!(\is_null($type) || $type instanceof Identifier || $type instanceof Name || $type instanceof NullableType || $type instanceof UnionType)) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($type) must be of type Identifier|Name|NullableType|UnionType|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($type) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $types = [];
        if ($type instanceof NullableType) {
            $types = [$type->type, new Identifier('null')];
        } elseif ($type instanceof UnionType) {
            $types = $type->types;
        } elseif (!TypeHintReplacer::replaced($type)) {
            $types = [$type];
        }
        return $types;
    }
    /**
     * Compare two types.
     *
     * @param (null | Identifier | Name | NullableType | UnionType) $typeA
     * @param (null | Identifier | Name | NullableType | UnionType) $typeB
     * @param Storage $ctxA
     * @param Storage $ctxB
     *
     * @return integer
     */
    public function compare($typeA, $typeB, Storage $ctxA, Storage $ctxB) : int
    {
        if (!(\is_null($typeA) || $typeA instanceof Identifier || $typeA instanceof Name || $typeA instanceof NullableType || $typeA instanceof UnionType)) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($typeA) must be of type Identifier|Name|NullableType|UnionType|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($typeA) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if (!(\is_null($typeB) || $typeB instanceof Identifier || $typeB instanceof Name || $typeB instanceof NullableType || $typeB instanceof UnionType)) {
            throw new \TypeError(__METHOD__ . '(): Argument #2 ($typeB) must be of type Identifier|Name|NullableType|UnionType|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($typeB) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $typeA = self::typeArray($typeA);
        $typeB = self::typeArray($typeB);
        if (\count($typeA) !== \count($typeB)) {
            return \count($typeA) <=> \count($typeB);
        }
        if (\count($typeA) + \count($typeB) === 2) {
            $typeA = $typeA[0];
            $typeB = $typeB[0];
            if ($typeA instanceof Name && $typeB instanceof Name && ($classA = $typeA->parts === ['self'] ? $ctxA : $this->getClassByName(\Phabel\Tools::getFqdn($typeA))) && ($classB = $typeA->parts === ['self'] ? $ctxB : $this->getClassByName(\Phabel\Tools::getFqdn($typeB)))) {
                foreach ($classA->getAllChildren() as $child) {
                    if ($child === $classB) {
                        return 1;
                    }
                }
                foreach ($classB->getAllChildren() as $child) {
                    if ($child === $classA) {
                        return -1;
                    }
                }
            }
        }
        return 0;
    }
}
<?php

namespace Phabel;

interface EventHandlerInterface
{
    /**
     *
     */
    public function onStart() : void;
    /**
     *
     */
    public function onBeginPluginGraphResolution() : void;
    /**
     *
     */
    public function onEndPluginGraphResolution() : void;
    /**
     *
     */
    public function onBeginDirectoryTraversal(int $total, int $workers) : void;
    /**
     *
     */
    public function onBeginAstTraversal(string $file) : void;
    /**
     * @param (int | \Throwable) $iterationsOrError
     */
    public function onEndAstTraversal(string $file, $iterationsOrError) : void;
    /**
     *
     */
    public function onEndDirectoryTraversal() : void;
    /**
     *
     */
    public function onBeginClassGraphMerge(int $count) : void;
    /**
     *
     */
    public function onClassGraphMerged() : void;
    /**
     *
     */
    public function onEndClassGraphMerge() : void;
    /**
     *
     */
    public function onEnd() : void;
}
<?php

namespace Phabel;

use Phabel\Cli\Formatter;
use Phabel\Commands\Publish;
use Phabel\Commands\Run;
use PhabelVendor\Symfony\Component\Console\Application;
if (!\class_exists(Run::class)) {
    require __DIR__ . '/../vendor/autoload.php';
}
$app = new Application(Formatter::banner());
$app->add(new Publish());
$app->add(new Run());
$app->run();
<?php

namespace Phabel;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\NodeAbstract;
/**
 * Root node.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class RootNode extends NodeAbstract
{
    /**
     * Children.
     *
     * @var Node[]
     */
    public $stmts = [];
    /**
     *
     */
    public function __construct(array $stmts, array $attributes = [])
    {
        $this->stmts = $stmts;
        parent::__construct($attributes);
    }
    /**
     *
     */
    public function getSubNodeNames() : array
    {
        return ['stmts'];
    }
    /**
     *
     */
    public function getType() : string
    {
        return 'rootNode';
    }
}
<?php

namespace Phabel\Tasks;

use PhabelVendor\Amp\Parallel\Worker\Environment;
use PhabelVendor\Amp\Parallel\Worker\Task;
use Phabel\ExceptionWrapper;
use Phabel\Traverser;
class Run implements Task
{
    /**
     *
     */
    public function __construct(string $input, string $output, ?string $package, string $coverage)
    {
        $this->coverage = $coverage;
        $this->package = $package;
        $this->output = $output;
        $this->input = $input;
    }
    /**
     *
     */
    private string $coverage;
    /**
     *
     */
    private ?string $package;
    /**
     *
     */
    private string $output;
    /**
     *
     */
    private string $input;
    /**
     *
     */
    public function run(Environment $environment)
    {
        try {
            $_ = Traverser::startCoverage($this->coverage);
            /** @var Traverser */
            $traverser = $environment->get(Traverser::class);
            $traverser->setPackage($this->package);
            return $traverser->traverse($this->input, $this->output);
        } catch (\Throwable $e) {
            return new ExceptionWrapper($e);
        }
    }
}
<?php

namespace Phabel\Tasks;

use PhabelVendor\Amp\Parallel\Worker\Environment;
use PhabelVendor\Amp\Parallel\Worker\Task;
use Phabel\Exception;
use Phabel\PluginGraph\ResolvedGraph;
use Phabel\Traverser;
class Init implements Task
{
    /**
     *
     */
    public function __construct(ResolvedGraph $graph)
    {
        $this->graph = $graph;
    }
    /**
     *
     */
    private ResolvedGraph $graph;
    /**
     *
     */
    public function run(Environment $environment)
    {
        if (\function_exists("cli_set_process_title")) {
            try {
                @\cli_set_process_title("Phabel - PHP transpiler worker");
            } catch (\Throwable $e) {
            }
        }
        \set_error_handler(function (int $errno = 0, string $errstr = '', string $errfile = '', int $errline = -1) : bool {
            // If error is suppressed with @, don't throw an exception
            if (\Phabel\Target\Php80\Polyfill::error_reporting() === 0) {
                return \false;
            }
            throw new Exception($errstr, $errno, null, $errfile, $errline);
        });
        $environment->set(Traverser::class, (new Traverser())->setGraph($this->graph));
    }
}
<?php

namespace Phabel\Tasks;

use PhabelVendor\Amp\Parallel\Worker\Environment;
use PhabelVendor\Amp\Parallel\Worker\Task;
use Phabel\Traverser;
class Shutdown implements Task
{
    /**
     *
     */
    public function run(Environment $environment)
    {
        /** @var Traverser */
        $traverser = $environment->get(Traverser::class);
        $environment->delete(Traverser::class);
        return $traverser->getGraph()->getClassStorage();
    }
}
<?php

namespace Phabel;

use Phabel\PluginGraph\PackageContext;
/**
 * Plugin interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
interface PluginInterface
{
    /**
     * Specify which plugins should run before this plugin.
     *
     * @return array Plugin name(s)
     *
     * @psalm-return (class-string<PluginInterface>[] | array<class-string<PluginInterface>, array>)
     */
    public static function previous(array $config) : array;
    /**
    * Specify which plugins should run after this plugin.
    *
    * At each level, the traverser will execute the enter and leave methods of the specified plugins, completing a full AST traversal before starting a new AST traversal for the current plugin.
    Of course, this increases complexity as it forces an additional traversal of the AST.
    *
    * When possible, use the extends method to reduce complexity.
    *
    * @return array Plugin name(s)
    *
    * @psalm-return (class-string<PluginInterface>[] | array<class-string<PluginInterface>, array>)
    */
    public static function next(array $config) : array;
    /**
     * Specify which plugins should run before, possibly with this plugin.
     *
     * At each depth level, the traverser will first execute the enter|leave methods of the specified plugins, then immediately execute the enter|leave methods of the current plugin.
     *
     * This is preferred, and allows only a single traversal of the AST.
     *
     * @return array Plugin name(s)
     *
     * @psalm-return (class-string<PluginInterface>[] | array<class-string<PluginInterface>, array>)
     */
    public static function withPrevious(array $config) : array;
    /**
     * Specify which plugins should run after, possibly with this plugin.
     *
     * @return array Plugin name(s)
     *
     * @psalm-return (class-string<PluginInterface>[] | array<class-string<PluginInterface>, array>)
     */
    public static function withNext(array $config) : array;
    /**
     * Specify a list of composer dependencies.
     *
     * @return array
     */
    public static function getComposerRequires(array $config) : array;
    /**
     * Set configuration array.
     *
     * @param array $config
     *
     * @return void
     */
    public function setConfigArray(array $config) : void;
    /**
     * Set package context.
     *
     * @param PackageContext $ctx Ctx
     *
     * @return void
     */
    public function setPackageContext(PackageContext $ctx) : void;
    /**
     * Get package context.
     *
     * @return PackageContext
     */
    public function getPackageContext() : PackageContext;
    /**
     * Check if plugin should run.
     *
     * @param string $package Package name
     *
     * @return boolean
     */
    public function shouldRun(string $package) : bool;
    /**
     * Check if plugin should run.
     *
     * @param string $file File name
     *
     * @return boolean
     */
    public function shouldRunFile(string $file) : bool;
    /**
     * Get configuration key.
     *
     * @param string $key Key
     * @param mixed $default Default value, if key is not present
     *
     * @return mixed
     */
    public function getConfig(string $key, $default);
    /**
     * Set configuration key.
     *
     * @param string $key Key
     * @param mixed $value Value
     *
     * @return void
     */
    public function setConfig(string $key, $value) : void;
    /**
     * Check if has configuration key.
     *
     * @param string $key Key
     *
     * @return mixed
     */
    public function hasConfig(string $key) : bool;
    /**
     * Merge multiple configurations into one (or more).
     *
     * @param array ...$configs Configurations
     *
     * @return array[]
     */
    public static function mergeConfigs(array ...$configs) : array;
    /**
    * Split configuration.
    *
    * For example, if you have a configuration that enables feature A, B and C, return three configuration arrays each enabling ONLY A, only B and only C.
    This is used for optimizing the AST traversing process during resolution of the plugin graph.
    *
    * @param array $config Configuration
    *
    * @return array[]
    */
    public static function splitConfig(array $config) : array;
}
<?php

namespace Phabel;

/**
 * Exception.
 */
class Exception extends \Exception
{
    /**
     *
     */
    private ?string $trace;
    /**
     * Get trace.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->trace ?? parent::__toString();
    }
    /**
     * Constructor.
     *
     * @param string $message
     * @param integer $code
     * @param \Throwable $previous
     * @param string $file
     * @param int $line
     */
    public function __construct(string $message = '', int $code = 0, \Throwable $previous = null, string $file = '', int $line = -1)
    {
        if ($file !== '') {
            $this->file = $file;
        }
        if ($line !== -1) {
            $this->line = $line;
        }
        parent::__construct($message, $code, $previous);
    }
    /**
     * Set the value of trace.
     *
     * @param ?string $trace
     *
     * @return self
     */
    public function setTrace(?string $trace) : self
    {
        $this->trace = $trace;
        return $this;
    }
}
<?php

namespace PhabelVendor;

if (!\defined('PHABEL_INCLUDED')) {
    \define('PHABEL_INCLUDED', \true);
}
<?php

namespace Phabel\ClassStorage;

use PhabelVendor\PhpParser\Node\Stmt\Class_;
use PhabelVendor\PhpParser\Node\Stmt\ClassMethod;
/**
 * Stores information about a class.
 */
class Storage
{
    private const MODIFIER_NORMAL = 256;
    const STORAGE_KEY = 'Storage:instance';
    /**
     * Method list.
     *
     * @psalm-var array<string, ClassMethod>
     */
    private array $methods = [];
    /**
     * Abstract method list.
     *
     * @psalm-var array<string, ClassMethod>
     */
    private array $abstractMethods = [];
    /**
     * Removed method list.
     *
     * @var array<string, true>
     */
    private array $removedMethods = [];
    /**
     * Classes/interfaces to extend.
     *
     * @var array<class-string, Storage>
     */
    private array $extends = [];
    /**
     * Classes/interfaces that extend us.
     *
     * @var array<class-string, Storage>
     */
    private array $extendedBy = [];
    /**
     * Class name.
     */
    private string $name;
    /**
     * Constructor.
     *
     * @param string $name
     * @param array<string, ClassMethod> $methods
     * @param array<string, ClassMethod> $abstractMethods
     * @param array<class-string, Builder> $extends
     */
    public function build(string $name, array $methods, array $abstractMethods, array $extends)
    {
        $this->name = $name;
        $this->methods = $methods;
        $this->abstractMethods = $abstractMethods;
        foreach ($methods as $method) {
            if ($method->getAttribute(\Phabel\ClassStorage\Builder::STORAGE_KEY)) {
                $method->setAttribute(self::STORAGE_KEY, $method->getAttribute(\Phabel\ClassStorage\Builder::STORAGE_KEY)->build());
                $method->setAttribute(\Phabel\ClassStorage\Builder::STORAGE_KEY, null);
            }
            $method->flags |= self::MODIFIER_NORMAL;
        }
        foreach ($abstractMethods as $method) {
            if ($method->getAttribute(\Phabel\ClassStorage\Builder::STORAGE_KEY)) {
                $method->setAttribute(self::STORAGE_KEY, $method->getAttribute(\Phabel\ClassStorage\Builder::STORAGE_KEY)->build());
                $method->setAttribute(\Phabel\ClassStorage\Builder::STORAGE_KEY, null);
            }
        }
        foreach ($extends as $name => $class) {
            $this->extends[$name] = $class->build();
        }
        foreach ($this->extends as $name => $class) {
            $class->extendedBy[$this->name] = $this;
        }
    }
    /**
     * Get name.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * Get method list.
     *
     * @param int-mask<Class_::MODIFIER_*> $typeMask Mask
     * @param int-mask<Class_::MODIFIER_*> $visibilityMask Mask
     *
     * @return \Generator<string, ClassMethod, null, void>
     */
    public function getMethods(int $typeMask = ~Class_::VISIBILITY_MODIFIER_MASK, int $visibilityMask = Class_::VISIBILITY_MODIFIER_MASK) : \Generator
    {
        if ($typeMask & Class_::MODIFIER_ABSTRACT) {
            foreach ($this->abstractMethods as $name => $method) {
                if (($method->flags | Class_::MODIFIER_ABSTRACT) & $typeMask && $method->flags & $visibilityMask) {
                    (yield $name => $method);
                }
            }
        }
        if ($typeMask & self::MODIFIER_NORMAL) {
            foreach ($this->methods as $name => $method) {
                if ($method->flags & $typeMask && $method->flags & $visibilityMask) {
                    (yield $name => $method);
                }
            }
        }
    }
    /**
     * Get classes which extend this class.
     *
     * @return array<class-string, Storage>
     */
    public function getExtendedBy() : array
    {
        return $this->extendedBy;
    }
    /**
     * Get classes which this class extends.
     *
     * @return array<class-string, Storage>
     */
    public function getExtends() : array
    {
        return $this->extends;
    }
    /**
     * Get all child classes.
     *
     * @return \Generator<void, Storage, null, void>
     */
    public function getAllChildren() : \Generator
    {
        foreach ($this->extendedBy as $class) {
            (yield $class);
            yield from $class->getAllChildren();
        }
    }
    /**
     * Get all parent classes.
     *
     * @return \Generator<void, Storage, null, void>
     */
    public function getAllParents() : \Generator
    {
        foreach ($this->extends as $class) {
            (yield $class);
            yield from $class->getAllParents();
        }
    }
    /**
     * Get all methods which override the specified method in child classes.
     *
     * @param string $method Method
     * @param int-mask<Class_::MODIFIER_*> $typeMask Mask
     * @param int-mask<Class_::MODIFIER_*> $visibilityMask Mask
     *
     * @return \Generator<void, ClassMethod, null, void>
     */
    public function getOverriddenMethods(string $name, int $typeMask = ~Class_::VISIBILITY_MODIFIER_MASK, int $visibilityMask = Class_::VISIBILITY_MODIFIER_MASK) : \Generator
    {
        foreach ($this->getAllChildren() as $child) {
            if (isset($child->abstractMethods[$name])) {
                $method = $child->abstractMethods[$name];
                $flags = $method->flags | Class_::MODIFIER_ABSTRACT;
                if ($flags & $typeMask && $flags & $visibilityMask) {
                    (yield $method);
                }
            }
            if (isset($child->methods[$name])) {
                $method = $child->methods[$name];
                $flags = $method->flags;
                if ($flags & $typeMask && $flags & $visibilityMask) {
                    (yield $method);
                }
            }
        }
    }
    /**
     * Remove method.
     *
     * @param ClassMethod $method Removed method
     *
     * @return bool
     */
    public function removeMethod(ClassMethod $method) : bool
    {
        $name = $method->name->name;
        if ($method->stmts !== null) {
            if (isset($this->methods[$name])) {
                $this->removedMethods[$name] = \true;
                unset($this->methods[$name]);
                return \true;
            }
        } elseif (isset($this->abstractMethods[$name])) {
            $this->removedMethods[$name] = \true;
            unset($this->abstractMethods[$name]);
            return \true;
        }
        return \false;
    }
    /**
     * Process method from AST.
     *
     * @return bool
     */
    public function process(ClassMethod $method) : bool
    {
        $name = $method->name->name;
        if (isset($this->removedMethods[$name])) {
            return \true;
        }
        $myMethod = $this->methods[$name] ?? $this->abstractMethods[$name];
        foreach ($myMethod->getSubNodeNames() as $name) {
            if ($name === 'stmts') {
                continue;
            }
            $method->{$name} = $myMethod->{$name};
        }
        foreach ($myMethod->getAttributes() as $key => $attribute) {
            if (\str_contains($key, ':')) {
                $method->setAttribute($key, $attribute);
            }
        }
        return \false;
    }
}
<?php

namespace Phabel\ClassStorage;

/**
 * Stores information about a function.
 */
class FunctionStorage
{
    /**
     * Constructor.
     *
     * @param array<string, mixed> $arguments
     * @param boolean $hasVariadic
     */
    public function __construct(array $arguments, bool $hasVariadic)
    {
        $this->hasVariadic = $hasVariadic;
        $this->arguments = $arguments;
    }
    /**
     *
     */
    private bool $hasVariadic;
    /**
     *
     */
    private array $arguments;
    /**
     * Get arguments.
     *
     * @return array<string, mixed>
     */
    public function getArguments() : array
    {
        return $this->arguments;
    }
    /**
     * Check if function is variadic.
     *
     * @return boolean
     */
    public function isVariadic() : bool
    {
        return $this->hasVariadic;
    }
}
<?php

namespace Phabel\ClassStorage;

use Phabel\Exception;
use Phabel\Plugin\ClassStoragePlugin;
use Phabel\PluginGraph\CircularException;
use Phabel\Tools;
use PhabelVendor\PhpParser\Node\Stmt\Class_ as StmtClass_;
use PhabelVendor\PhpParser\Node\Stmt\ClassLike;
use PhabelVendor\PhpParser\Node\Stmt\ClassMethod;
use PhabelVendor\PhpParser\Node\Stmt\Interface_;
use PhabelVendor\PhpParser\Node\Stmt\TraitUse;
use PhabelVendor\PhpParser\Node\Stmt\TraitUseAdaptation\Alias;
use PhabelVendor\PhpParser\Node\Stmt\TraitUseAdaptation\Precedence;
/**
 * Builds information about a class.
 */
class Builder
{
    const STORAGE_KEY = 'Storage:tmp';
    /**
     * Method list.
     *
     * @psalm-var array<string, ClassMethod>
     */
    private array $methods = [];
    /**
     * Abstract method list.
     *
     * @psalm-var array<string, ClassMethod>
     */
    private array $abstractMethods = [];
    /**
     * Extended classes/interfaces.
     *
     * @var array<class-string, (Builder | true)>
     */
    private array $extends = [];
    /**
     * Used classes/interfaces.
     *
     * @var array<trait-string, (Builder | true)>
     */
    private array $use = [];
    /**
     * Use aliases.
     *
     * trait => [oldName => [newTrait, newName]]
     *
     * @var array<trait-string, array<string, array{0: trait-string, 1: string}>>
     */
    private array $useAlias = [];
    /**
     * Whether we're resolving.
     */
    private bool $resolving = \false;
    /**
     * Whether we resolved.
     */
    private bool $resolved = \false;
    /**
     * Storage.
     */
    private ?\Phabel\ClassStorage\Storage $storage = null;
    /**
     * Class name.
     */
    private string $name;
    /**
     * Constructor.
     *
     * @param ClassLike $class Class or trait
     */
    public function __construct(ClassLike $class, string $customName = '')
    {
        $this->name = Tools::getFqdn($class, $customName);
        if ($class instanceof Interface_ || $class instanceof StmtClass_) {
            foreach (\is_array($class->extends) ? $class->extends : ($class->extends ? [$class->extends] : []) as $name) {
                $this->extends[Tools::getFqdn($name)] = \true;
            }
            foreach ($class->implements ?? [] as $name) {
                $this->extends[Tools::getFqdn($name)] = \true;
            }
        }
        foreach ($class->stmts as $stmt) {
            if ($stmt instanceof ClassMethod) {
                $this->addMethod($stmt);
            }
            if ($stmt instanceof TraitUse) {
                foreach ($stmt->traits as $trait) {
                    $this->use[Tools::getFqdn($trait)] = \true;
                }
                foreach ($stmt->adaptations as $k => $adapt) {
                    $trait = Tools::getFqdn($adapt->trait ?? $stmt->traits[0]);
                    $method = $adapt->method->name;
                    if ($adapt instanceof Alias) {
                        $this->useAlias[$trait][$method] = [$trait, ($adapt->newName ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->name ?? $method];
                    } elseif ($adapt instanceof Precedence) {
                        foreach ($adapt->insteadof as $name) {
                            $insteadOf = Tools::getFqdn($name);
                            $this->useAlias[$insteadOf][$method] = [$trait, $method];
                        }
                    }
                }
            }
        }
    }
    /**
     * Add method.
     *
     * @param ClassMethod $method
     */
    private function addMethod(ClassMethod $method)
    {
        $method->setAttribute(self::STORAGE_KEY, $this);
        if ($method->stmts === null) {
            $this->abstractMethods[$method->name->name] = $method;
        } else {
            $this->methods[$method->name->name] = $method;
        }
    }
    /**
     * Resolve class tree.
     */
    public function resolve(ClassStoragePlugin $plugin) : self
    {
        if ($this->resolved) {
            return $this;
        }
        if ($this->resolving) {
            $plugins = [$this->name];
            foreach (\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, \DEBUG_BACKTRACE_PROVIDE_OBJECT) as $frame) {
                $plugins[] = $frame['object']->name;
                if ($frame['object'] === $this) {
                    break;
                }
            }
            throw new CircularException($plugins);
        }
        $this->resolving = \true;
        foreach ($this->use as $trait => $_) {
            if (!isset($plugin->traits[$trait])) {
                continue;
            }
            $resolved = \array_values($plugin->traits[$trait])[0]->resolve($plugin);
            foreach ([$resolved->methods, $resolved->abstractMethods] as $list) {
                foreach ($list as $name => $method) {
                    if (isset($this->useAlias[$trait][$name])) {
                        [$newTrait, $name] = $this->useAlias[$trait][$name];
                        if (!isset($plugin->traits[$newTrait])) {
                            continue;
                        }
                        $newTrait = \array_values($plugin->traits[$newTrait])[0]->resolve($plugin);
                        if (isset($newTrait->methods[$name])) {
                            $this->methods[$name] = $newTrait->methods[$name];
                        } elseif (isset($newTrait->abstractMethods[$name])) {
                            $this->abstractMethods[$name] = $newTrait->methods[$name];
                        }
                        continue;
                    }
                    if ($method->stmts === null) {
                        $this->abstractMethods[$name] = $method;
                    } else {
                        $this->methods[$name] = $method;
                    }
                }
            }
        }
        foreach ($this->extends as $class => &$res) {
            if (isset($plugin->classes[$class])) {
                $res = \array_values($plugin->classes[$class])[0];
            } else {
                unset($this->extends[$class]);
            }
        }
        $this->resolving = \false;
        $this->resolved = \true;
        return $this;
    }
    /**
     * Build storage.
     *
     * @return Storage
     */
    public function build() : \Phabel\ClassStorage\Storage
    {
        if (!$this->resolved) {
            throw new Exception("Trying to build an unresolved class!");
        }
        if (!isset($this->storage)) {
            $this->storage = new \Phabel\ClassStorage\Storage();
            $this->storage->build($this->name, $this->methods, $this->abstractMethods, $this->extends);
        }
        return $this->storage;
    }
    /**
     * Debug info.
     */
    public function __debugInfo() : array
    {
        return ['name' => $this->name, 'methods' => \array_keys($this->methods), 'abstractMethods' => \array_keys($this->abstractMethods), 'extends' => $this->extends, 'useAlias' => $this->useAlias, 'use' => $this->use];
    }
}
<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.guard.php';<?php

namespace Phabel;

use PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\Type\TypeNode;
use PhabelVendor\PHPStan\PhpDocParser\Lexer\Lexer;
use PhabelVendor\PHPStan\PhpDocParser\Parser\ConstExprParser;
use PhabelVendor\PHPStan\PhpDocParser\Parser\PhpDocParser as PhpStanDocParser;
use PhabelVendor\PHPStan\PhpDocParser\Parser\TokenIterator;
use PhabelVendor\PHPStan\PhpDocParser\Parser\TypeParser;
/**
 * A wrapper class around phpstan's PHPDoc parser.
 */
class PhpDocParser
{
    /**
     *
     */
    private Lexer $lexer;
    /**
     *
     */
    private PhpStanDocParser $parser;
    /**
     *
     */
    private TypeParser $typeParser;
    /**
     *
     */
    public function __construct()
    {
        $constParser = new ConstExprParser();
        $this->parser = new PhpStanDocParser(new TypeParser($constParser), $constParser);
        $this->typeParser = new TypeParser($constParser);
        $this->lexer = new Lexer();
    }
    /**
     * Parse a phpdoc.
     *
     * @param (string | null) $phpdoc
     * @return (PhpDocNode | null)
     */
    public function parsePhpDoc(?string $phpdoc) : ?PhpDocNode
    {
        if (!$phpdoc) {
            return null;
        }
        return $this->parser->parse(new TokenIterator($this->lexer->tokenize($phpdoc)));
    }
    /**
     * Parse a phpdoc type declaration.
     *
     * @param string $type
     * @return TypeNode
     */
    public function parseType(string $type) : TypeNode
    {
        return $this->typeParser->parse(new TokenIterator($this->lexer->tokenize($type)));
    }
}
<?php

namespace Phabel;

use JsonSerializable;
use Phabel\ClassStorage\Storage;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Expr\MethodCall;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Stmt\ClassLike;
use PhabelVendor\PhpParser\Node\Stmt\ClassMethod;
use PhabelVendor\PhpParser\Node\Stmt\Nop;
abstract class ClassStorageProvider extends \Phabel\Plugin implements JsonSerializable
{
    private const PROCESSED = 'ClassStorageProvider:processed';
    /**
     * Class count.
     */
    private array $count = [];
    /**
     * Process class graph.
     *
     * @param ClassStorage $storage
     * @return bool
     */
    public static abstract function processClassGraph(\Phabel\ClassStorage $storage) : bool;
    /**
     * Enter file.
     *
     * @param RootNode $_
     * @return void
     */
    public function enterRoot(\Phabel\RootNode $_, \Phabel\Context $context) : void
    {
        $this->count[$context->getOutputFile()] = [];
    }
    /**
     * Populate class storage.
     *
     * @param ClassLike $classLike
     * @return void
     */
    public function enterClassStorage(ClassLike $class, \Phabel\Context $context) : void
    {
        if ($class->hasAttribute(self::PROCESSED)) {
            return;
        }
        $class->setAttribute(self::PROCESSED, \true);
        $file = $context->getOutputFile();
        if ($class->name) {
            $name = self::getFqdn($class);
        } else {
            $name = "class@anonymous{$file}";
            $this->count[$file][$name] ??= 0;
            $name .= "@" . $this->count[$file][$name]++;
        }
        $storage = $this->getGlobalClassStorage()->getClass($file, $name);
        foreach ($class->stmts as $k => $stmt) {
            if ($stmt instanceof ClassMethod && $storage->process($stmt)) {
                $class->stmts[$k] = new Nop();
            }
        }
    }
    /**
     *
     */
    public function enterStaticCall(StaticCall $call) : void
    {
        $this->enterCall($call);
    }
    /**
     *
     */
    public function enterFuncCall(FuncCall $call) : void
    {
        $this->enterCall($call);
    }
    /**
     *
     */
    public function enterMethodCall(MethodCall $call) : void
    {
        $this->enterCall($call);
    }
    /**
     * @param (StaticCall | FuncCall | MethodCall) $call
     */
    private function enterCall($call) : void
    {
        if (!($call instanceof StaticCall || $call instanceof FuncCall || $call instanceof MethodCall)) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($call) must be of type StaticCall|FuncCall|MethodCall, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($call) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $args = [];
        $hasNamed = \false;
        foreach ($call->args as $arg) {
            if ($arg->name) {
                $args[$arg->name] = $arg;
                $arg->name = null;
                $hasNamed = \true;
            }
        }
        if (!$hasNamed) {
            return;
        }
        if ($call instanceof FuncCall && $call->name instanceof Name) {
            $func = $this->getGlobalClassStorage()->getArguments($call->name->toLowerString());
            if ($func) {
                $ordered = [];
                foreach ($func->getArguments() as $name => $default) {
                    $ordered[] = $args[$name] ?? $default;
                    unset($args[$name]);
                }
                if ($args && $func->isVariadic()) {
                }
            }
        }
    }
    /**
     * Get global class storage.
     *
     * @return ClassStorage
     */
    public function getGlobalClassStorage() : \Phabel\ClassStorage
    {
        return $this->getConfig(\Phabel\ClassStorage::class, null);
    }
    /**
     * JSON representation.
     *
     * @return string
     */
    public function jsonSerialize() : string
    {
        return \spl_object_hash($this);
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\ArrayDimFetch;
use PhabelVendor\PhpParser\Node\Expr\ClassConstFetch;
use PhabelVendor\PhpParser\Node\Expr\Isset_;
use PhabelVendor\PhpParser\Node\Expr\PropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\StaticPropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\Ternary;
use PhabelVendor\PhpParser\Node\Expr\Variable;
use PhabelVendor\PhpParser\Node\Scalar\LNumber;
use PhabelVendor\PhpParser\Node\Scalar\String_;
use PhabelVendor\PhpParser\Node\VarLikeIdentifier;
use ReflectionClass;
use ReflectionClassConstant;
use ReflectionException;
/**
 * Replace nested expressions in isset.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class IssetExpressionFixer extends Plugin
{
    /**
     * Recursively extract bottom ArrayDimFetch.
     *
     * @param Node $var
     * @return Node
     */
    private static function &extractWorkVar(Node &$var) : Node
    {
        if ($var instanceof ArrayDimFetch && $var->var instanceof ArrayDimFetch) {
            return self::extractWorkVar($var->var);
        }
        return $var;
    }
    /**
     * Wrap boolean isset check.
     *
     * @param Expr $node Node
     *
     * @return ArrayDimFetch
     */
    private static function wrapBoolean(Expr $node) : ArrayDimFetch
    {
        return new ArrayDimFetch(self::callPoly('returnMe', new Ternary($node, self::fromLiteral([0]), self::fromLiteral([]))), new LNumber(0));
    }
    /**
     *
     */
    public function enter(Isset_ $isset) : void
    {
        foreach ($isset->vars as $key => &$var) {
            /** @var array<string, array<class-string<Expr>, true>> */
            $subNodes = $this->getConfig(\get_class($var), \false);
            if (!$subNodes) {
                continue;
            }
            $workVar =& $this->extractWorkVar($var);
            $needsFixing = \false;
            foreach ($subNodes as $key => $types) {
                if (isset($types[self::getClass($workVar->{$key} ?? '')])) {
                    $needsFixing = \true;
                    break;
                }
            }
            if (!$needsFixing) {
                continue;
            }
            switch ($class = \get_class($workVar)) {
                case ArrayDimFetch::class:
                case PropertyFetch::class:
                    if ($key === 'dim') {
                        $workVar->dim = self::callPoly('returnMe', $workVar->dim);
                    } else {
                        $workVar->var = self::callPoly('returnMe', $workVar->var);
                    }
                    break;
                case StaticPropertyFetch::class:
                    $workVar = $this->wrapBoolean(self::callPoly('staticExists', $workVar->class, $workVar->name instanceof VarLikeIdentifier ? new String_($workVar->name->name) : $workVar->name, self::fromLiteral(\true)));
                    break;
                case ClassConstFetch::class:
                    $workVar = $this->wrapBoolean(self::callPoly('staticExists', $workVar->class, new String_($workVar->name->name), self::fromLiteral(\false)));
                    break;
                case Variable::class:
                    $workVar->name = self::callPoly('returnMe', $workVar->name);
                    break;
                default:
                    throw new \RuntimeException("Trying to fix unknown isset expression {$class}");
            }
        }
    }
    /**
     * Returns the data provided.
     *
     * @param mixed $data Data
     *
     * @return mixed
     *
     * @template T
     *
     * @psalm-param T $data data
     *
     * @psalm-return T
     */
    public static function returnMe($data)
    {
        return $data;
    }
    /**
     * Get name of class.
     *
     * @param (class-string | object) $class Class
     *
     * @return class-string
     */
    public static function getClass($class) : string
    {
        return \is_string($class) ? $class : \get_class($class);
    }
    /**
     * Check if static property is set.
     *
     * @param (class-string | object) $class Class
     * @param string $property Property name
     * @param boolean $propertyOrConstant Whether to fetch the property or the constant
     *
     * @return boolean
     */
    public static function staticExists($class, string $property, bool $propertyOrConstant) : bool
    {
        $reflectionClass = new ReflectionClass($class);
        $class = self::getClass($class);
        if ($propertyOrConstant) {
            try {
                $reflection = $reflectionClass->getProperty($property);
            } catch (ReflectionException $e) {
                return \false;
            }
        } elseif (\PHP_VERSION_ID >= 70100) {
            try {
                $reflection = new ReflectionClassConstant($class, $property);
            } catch (ReflectionException $e) {
                return \false;
            }
        } else {
            return isset($reflectionClass->getConstants()[$property]);
        }
        $classCaller = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1]['class'] ?? '';
        $allowProtected = \false;
        $allowPrivate = \false;
        if ($classCaller) {
            if ($class === $classCaller) {
                $allowProtected = $allowPrivate = \true;
            } elseif ($reflectionClass->isSubclassOf($classCaller) || (new ReflectionClass($classCaller))->isSubclassOf($class)) {
                $allowProtected = \true;
            }
        }
        if ($reflection->isPrivate()) {
            return $allowPrivate ? $reflection->getValue() !== null : \false;
        }
        if ($reflection->isProtected()) {
            return $allowProtected ? $reflection->getValue() !== null : \false;
        }
        return $reflection->getValue() !== null;
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr\Yield_;
use PhabelVendor\PhpParser\Node\Expr\YieldFrom;
use PhabelVendor\PhpParser\Node\FunctionLike;
/**
 * Detect usages of yield and yield from.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class GeneratorDetector extends Plugin
{
    /**
     * Whether this function is a generator.
     */
    private const IS_GENERATOR = 'isGenerator';
    /**
     * Return whether this function is a generator.
     *
     * @param FunctionLike $node
     * @return boolean
     */
    public static function isGenerator(FunctionLike $node) : bool
    {
        return $node->getAttribute(self::IS_GENERATOR, \false);
    }
    /**
     *
     */
    public function enterYield(Yield_ $node, Context $ctx) : void
    {
        foreach ($ctx->parents as $parent) {
            if ($parent instanceof FunctionLike) {
                $parent->setAttribute(self::IS_GENERATOR, \true);
                return;
            }
        }
    }
    /**
     *
     */
    public function enterYieldFrom(YieldFrom $node, Context $ctx) : void
    {
        foreach ($ctx->parents as $parent) {
            if ($parent instanceof FunctionLike) {
                $parent->setAttribute(self::IS_GENERATOR, \true);
                return;
            }
        }
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr\Array_;
use PhabelVendor\PhpParser\Node\Expr\ArrayDimFetch;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\AssignRef;
use PhabelVendor\PhpParser\Node\Expr\List_;
use PhabelVendor\PhpParser\Node\Expr\Variable;
use PhabelVendor\PhpParser\Node\Scalar\LNumber;
use PhabelVendor\PhpParser\Node\Stmt\Foreach_;
/**
 * Polyfills unsupported list assignments.
 */
class ListSplitter extends Plugin
{
    /**
     * Parse list foreach with custom keys.
     *
     * @param Foreach_ $node Foreach
     *
     * @return void
     */
    public function enterForeach(Foreach_ $node, Context $ctx) : void
    {
        if (!($node->valueVar instanceof List_ || $node->valueVar instanceof Array_)) {
            return;
        }
        if (!$this->shouldSplit($node->valueVar) && !($this->getConfig('parentExpr', \false) && $ctx->isParentStmt())) {
            return;
        }
        $list = $node->valueVar;
        $var = $node->valueVar = $ctx->getVariable();
        $assignments = self::splitList($list, $var);
        $node->stmts = \array_merge($assignments, $node->stmts);
        $node->byRef = $this->hasReference($list);
    }
    /**
     * Parse list assignment with custom keys.
     *
     * @param Assign $node List assignment
     *
     * @return mixed
     */
    public function enterAssign(Assign $node, Context $ctx)
    {
        if (!($node->var instanceof List_ || $node->var instanceof Array_) || !$this->shouldSplit($node->var)) {
            return;
        }
        $var = $ctx->getVariable();
        $assignments = self::splitList($node->var, $var);
        $hasReference = $this->hasReference($node->var);
        if ($ctx->isParentStmt()) {
            $last = \array_pop($assignments);
            $ctx->insertBefore($node, $hasReference ? new AssignRef($var, $node->expr) : new Assign($var, $node->expr), ...$assignments);
            return $last;
        }
        // On newer versions of php, the list assignment expression returns the original array
        $ctx->insertBefore($node, $hasReference ? new AssignRef($var, $node->expr) : new Assign($var, $node->expr), ...$assignments);
        return $var;
    }
    /**
     * Split referenced list into multiple assignments.
     *
     * @param (Array_ | List_) $list List
     * @param Variable $var Variable
     *
     * @return (Assign | AssignRef)[]
     * @psalm-return array<int, (Assign | AssignRef)>
     */
    public static function splitList($list, Variable $var) : array
    {
        $assignments = [];
        $key = 0;
        // Technically a list assignment does not support mixed keys, but we need this for nested assignments
        foreach ($list->items as $item) {
            if (!$item) {
                $key++;
                continue;
            }
            $curKey = $item->key ?? new LNumber($key++);
            if ($item->byRef) {
                $assignments[] = new AssignRef($item->value, new ArrayDimFetch($var, $curKey));
            } else {
                $assignments[] = new Assign($item->value, new ArrayDimFetch($var, $curKey));
            }
        }
        return $assignments;
    }
    /**
     * Whether we should act on this list.
     *
     * @param (List_ | Array_) $list List
     *
     * @return boolean
     */
    private function hasReference($list) : bool
    {
        $c = $this->getConfigArray();
        $this->setConfigArray(['byRef' => \true]);
        $res = $this->shouldSplit($list);
        $this->setConfigArray($c);
        return $res;
    }
    /**
     * Whether we should act on this list.
     *
     * @param (List_ | Array_) $list List
     *
     * @return boolean
     */
    private function shouldSplit($list) : bool
    {
        foreach ($list->items as $item) {
            if (!$item) {
                continue;
            }
            if ($this->getConfig('byRef', \false) && $item->byRef) {
                return \true;
            } elseif ($this->getConfig('key', \false) && isset($item->key)) {
                return \true;
            } elseif ($item->value instanceof List_ || $item->value instanceof Array_) {
                if ($this->shouldSplit($item->value)) {
                    return \true;
                }
            }
        }
        return \false;
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr\Yield_;
use PhabelVendor\PhpParser\Node\FunctionLike;
/**
 * Detect usages of yield.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class YieldDetector extends Plugin
{
    /**
     *
     */
    public function enterYield(Yield_ $node, Context $ctx) : void
    {
        foreach ($ctx->parents as $parent) {
            if ($parent instanceof FunctionLike) {
                $parent->setAttribute(\Phabel\Plugin\ReGenerator::SHOULD_ATTRIBUTE, \true);
                return;
            }
        }
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\ArrayDimFetch;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\BooleanOr;
use PhabelVendor\PhpParser\Node\Expr\ClassConstFetch;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Expr\Instanceof_;
use PhabelVendor\PhpParser\Node\Expr\MethodCall;
use PhabelVendor\PhpParser\Node\Expr\New_;
use PhabelVendor\PhpParser\Node\Expr\PropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Expr\StaticPropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\Ternary;
use PhabelVendor\PhpParser\Node\Expr\Throw_;
/**
 * Fix nested expressions.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class NestedExpressionFixer extends Plugin
{
    /**
     * Recursively extract bottom ArrayDimFetch.
     *
     * @param Node $var
     * @return Node
     */
    private static function &extractWorkVar(Expr &$var) : Expr
    {
        if ($var instanceof ArrayDimFetch && $var->var instanceof ArrayDimFetch) {
            return self::extractWorkVar($var->var);
        }
        return $var;
    }
    /**
     *
     */
    public function leave(Expr $expr, Context $context) : ?Expr
    {
        /** @var array<string, array<class-string<Expr>, true>> */
        $subNodes = $this->getConfig($class = \get_class($expr), \false);
        if (!$subNodes) {
            return null;
        }
        foreach ($subNodes as $key => $types) {
            /** @var Expr $value */
            $value =& $expr->{$key};
            if (!isset($types[\Phabel\Plugin\IssetExpressionFixer::getClass($value ?? '')])) {
                if (!$value instanceof Expr) {
                    continue;
                }
                $workVar =& $this->extractWorkVar($value);
                if (!isset($types[\get_class($workVar)])) {
                    continue;
                }
            } else {
                $workVar =& $value;
            }
            switch (\get_class($workVar)) {
                case Throw_::class:
                    $workVar = self::callPoly('throwMe', $workVar->expr);
                    continue 2;
            }
            switch ($class) {
                case ArrayDimFetch::class:
                case PropertyFetch::class:
                case MethodCall::class:
                case Instanceof_::class:
                    if ($expr instanceof Instanceof_ && $key === 'class') {
                        return self::callPoly('instanceOf', $expr->expr, $expr->class);
                    }
                    $value = self::callPoly('returnMe', $value);
                    break;
                case New_::class:
                case ClassConstFetch::class:
                    $valueCopy = $value;
                    return new Ternary(new BooleanOr(new Assign($value = $context->getVariable(), $valueCopy), self::fromLiteral(\true)), $expr, self::fromLiteral(\false));
                case StaticCall::class:
                case StaticPropertyFetch::class:
                case FuncCall::class:
                    $valueCopy = $value;
                    $context->insertBefore($expr, new Assign($value = $context->getVariable(), $valueCopy));
                    break;
                default:
                    throw new \RuntimeException("Trying to fix unknown nested expression {$class}");
            }
        }
        return null;
    }
    /**
     * Returns the data provided.
     *
     * @param mixed $data Data
     *
     * @return mixed
     *
     * @template T
     *
     * @psalm-param T $data data
     *
     * @psalm-return T
     */
    public static function returnMe($data)
    {
        return $data;
    }
    /**
     * Throws the exception provided.
     *
     * @param \Throwable $throwable
     *
     * @return void
     *
     * @template T
     *
     * @psalm-param T $data data
     */
    public static function throwMe(\Throwable $throwable)
    {
        throw $throwable;
    }
    /**
     * Check if a is instance of b.
     *
     * @param (class-string | object) $a
     * @param (class-string | object) $b
     *
     * @return boolean
     */
    public static function instanceOf($a, $b) : bool
    {
        return $a instanceof $b;
    }
    /**
     *
     */
    public static function next(array $config) : array
    {
        return [\Phabel\Plugin\NewFixer::class];
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Plugin;
use Phabel\Target\Php;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Scalar\String_;
/**
 * Replace phabel test namespaces with appropriate version.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class PhabelTestGenerator extends Plugin
{
    /**
     *
     */
    private function tryReplace(string $in) : string
    {
        return \preg_replace("~PhabelTest(\\\\+)Target(?:Future)?\\d*~", 'PhabelTest$1Target' . $this->getConfig('target', ''), $in);
    }
    /**
     *
     */
    public function enter(Name $name) : ?Name
    {
        if (\preg_match("~PhabelTest\\\\+Target(?:Future)?\\d*~", $name->toString())) {
            $class = \get_class($name);
            return new $class($this->tryReplace($name->toString()));
        }
        return null;
    }
    /**
     *
     */
    public function enterLiteral(String_ $str) : ?String_
    {
        if (\preg_match("~PhabelTest\\\\+Target(?:Future)?\\d*~", $str->value)) {
            return new String_($this->tryReplace($str->value));
        }
        return null;
    }
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [Php::class => ['target' => $config['target'] % 1000], \Phabel\Plugin\StringConcatOptimizer::class => []];
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Stmt\Expression;
/**
 * Wraps standalone expressions in statements into Stmt\Expressions.
 */
class StmtExprWrapper extends Plugin
{
    /**
     *
     */
    public function enter(Expr $expr, Context $ctx) : ?Expression
    {
        if ($ctx->parents[0]->getAttribute('currentNode') === 'stmts') {
            return new Expression($expr);
        }
        return null;
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use Phabel\Target\Php70\AnonymousClass\AnonymousClassInterface;
use Phabel\Tools;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Comment\Doc;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\AssignRef;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\BooleanAnd;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\BooleanOr;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Concat;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Identical;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Plus;
use PhabelVendor\PhpParser\Node\Expr\BooleanNot;
use PhabelVendor\PhpParser\Node\Expr\Cast;
use PhabelVendor\PhpParser\Node\Expr\Cast\Bool_;
use PhabelVendor\PhpParser\Node\Expr\Cast\Double;
use PhabelVendor\PhpParser\Node\Expr\Cast\Int_;
use PhabelVendor\PhpParser\Node\Expr\Cast\String_ as CastString_;
use PhabelVendor\PhpParser\Node\Expr\ClassConstFetch;
use PhabelVendor\PhpParser\Node\Expr\ConstFetch;
use PhabelVendor\PhpParser\Node\Expr\Instanceof_;
use PhabelVendor\PhpParser\Node\Expr\New_;
use PhabelVendor\PhpParser\Node\Expr\PropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\Variable;
use PhabelVendor\PhpParser\Node\FunctionLike;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\NullableType;
use PhabelVendor\PhpParser\Node\Param;
use PhabelVendor\PhpParser\Node\Scalar\LNumber;
use PhabelVendor\PhpParser\Node\Scalar\MagicConst\Function_ as MagicConstFunction_;
use PhabelVendor\PhpParser\Node\Scalar\MagicConst\Method;
use PhabelVendor\PhpParser\Node\Scalar\String_;
use PhabelVendor\PhpParser\Node\Stmt\Class_ as StmtClass_;
use PhabelVendor\PhpParser\Node\Stmt\ClassLike;
use PhabelVendor\PhpParser\Node\Stmt\ClassMethod;
use PhabelVendor\PhpParser\Node\Stmt\Else_;
use PhabelVendor\PhpParser\Node\Stmt\Expression;
use PhabelVendor\PhpParser\Node\Stmt\Foreach_;
use PhabelVendor\PhpParser\Node\Stmt\If_;
use PhabelVendor\PhpParser\Node\Stmt\Interface_;
use PhabelVendor\PhpParser\Node\Stmt\Property;
use PhabelVendor\PhpParser\Node\Stmt\PropertyProperty;
use PhabelVendor\PhpParser\Node\Stmt\Return_;
use PhabelVendor\PhpParser\Node\Stmt\Throw_;
use PhabelVendor\PhpParser\Node\UnionType;
use PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc\ParamTagValueNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc\PhpDocTagNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode;
use PhabelVendor\PHPStan\PhpDocParser\Ast\PhpDoc\VarTagValueNode;
use SplStack;
/**
 * Replace all usages of a certain type in typehints.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class TypeHintReplacer extends Plugin
{
    /**
     * Force removal of specific typehint via node attribute.
     */
    private const FORCE_ATTRIBUTE = 'TypeHintReplacer:force';
    private const SINGLE_PROPERTY = 'TypeHintReplacer:singleProperty';
    private const IGNORE_RETURN = 0;
    private const VOID_RETURN = 1;
    private const TYPE_RETURN = 2;
    /**
     * Stack.
     *
     * @var SplStack
     * @psalm-var SplStack<(array{0: (self::IGNORE_RETURN | self::VOID_RETURN)} | array{0: self::TYPE_RETURN, 1: Node, 2: bool, 3: bool, 4: Node, 5: callable(Node ...): If_})>
     */
    private SplStack $stack;
    /**
     * Constructor.
     */
    public function __construct()
    {
        /** @psalm-var SplStack<array{0: self::IGNORE_RETURN|self::VOID_RETURN}|array{0: self::TYPE_RETURN, 1: Node, 2: bool, 3: bool, 4: Node, 5: (callable(Node...): If_)}> */
        $this->stack = new SplStack();
    }
    /**
     * Replace typehint.
     *
     * @param (null | Identifier | Name | NullableType | UnionType) $type Type
     *
     * @return bool
     */
    public static function replace(?Node $type) : bool
    {
        if ($type) {
            if ($type->getAttribute(self::FORCE_ATTRIBUTE, \false)) {
                return \false;
            }
            $type->setAttribute(self::FORCE_ATTRIBUTE, \true);
            return \true;
        }
        return \false;
    }
    /**
     * Return whether we replaced this typehint.
     *
     * @param (null | Identifier | Name | NullableType | UnionType) $type Type
     *
     * @return boolean
     */
    public static function replaced(?Node $type) : bool
    {
        if ($type) {
            return $type->getAttribute(self::FORCE_ATTRIBUTE, \false);
        }
        return \true;
    }
    /**
     * Check if we should replace a void return type.
     *
     * @param (Node | null) $returnType
     * @return bool
     */
    private function checkVoid(Context $ctx, PhpDocNode $phpdoc, ?Node $returnType) : bool
    {
        $strip = $returnType instanceof Identifier && $returnType->toLowerString() === 'void' && $this->getConfig('void', $this->getConfig('return', $returnType->getAttribute(self::FORCE_ATTRIBUTE)));
        if ($strip) {
            $ok = \false;
            foreach ($phpdoc->children as $child) {
                if ($child instanceof PhpDocTagNode && $child->value instanceof ReturnTagValueNode) {
                    $ok = \true;
                    break;
                }
            }
            if (!$ok) {
                $phpdoc->children[] = new PhpDocTagNode('@return', new ReturnTagValueNode($ctx->phpdocParser->parseType('void'), ''));
            }
        }
        return $strip;
    }
    /**
     * Resolve special class name.
     *
     * @param (Identifier | Name) $type
     * @param ?Expr $className
     *
     * @return Expr
     */
    private function resolveClassName($type, ?Expr $className) : Expr
    {
        $string = $type instanceof Identifier ? $type->toString() : $type->toCodeString();
        return $type->isSpecialClassName() ? $string === 'self' && $className ? $className : new ClassConstFetch(new Name($string), new Identifier('class')) : new String_($type->toString());
    }
    /**
     * Reduce multiple conditions to a single not.
     *
     * @param non-empty-list<Expr> $conditions
     * @return BooleanNot
     */
    private static function reduceConditions(array $conditions) : BooleanNot
    {
        $initial = \array_shift($conditions);
        return new BooleanNot(empty($conditions) ? $initial : \array_reduce($conditions, fn(Expr $a, Expr $b): BooleanOr => new BooleanOr($a, $b), $initial));
    }
    /**
     * Generate.
     *
     * @param (Name | Identifier)[] $types Types to check
     * @param ?Expr $className Whether the current class is anonymous
     * @param boolean $fromNullable Whether this type is nullable
     *
     * @return array{0: Node, 1: callable(Node ...): If_} The error message, the condition wrapper callback
     * @param (Param | PropertyProperty | null) $param
     */
    private function generateConditions(Context $ctx, PhpDocNode $phpdoc, $param, array $types, ?Expr $className, bool $fromNullable = \false) : array
    {
        if (!($param instanceof Param || $param instanceof PropertyProperty || \is_null($param))) {
            throw new \TypeError(__METHOD__ . '(): Argument #3 ($param) must be of type Param|PropertyProperty|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($param) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $is_return = \false;
        $is_property = \false;
        $is_single_property = \false;
        $is_param = \false;
        $phpdocVar = null;
        if (!$param) {
            $is_return = \true;
            $var = new Variable('phabelReturn');
        } elseif ($param instanceof PropertyProperty) {
            $is_property = \true;
            $is_single_property = $param->getAttribute(self::SINGLE_PROPERTY, \false);
            $phpdocVar = '$' . $param->name;
            $var = new PropertyFetch(new Variable('this'), $param->name);
        } elseif ($param->variadic) {
            $is_param = \true;
            $phpdocVar = '$' . $param->var->name;
            $var = new Variable('phabelVariadic');
        } else {
            $is_param = \true;
            $phpdocVar = '$' . $param->var->name;
            $var = $param->var;
        }
        /** @var Expr[] */
        $typeNames = [];
        /** @var Expr[] */
        $oopNames = [];
        /** @var list<(Expr|array{0: Expr, 1: Expr, 2: class-string<Cast>})> */
        $conditions = [];
        /** @var string Last string type name */
        $stringType = '';
        /** @var array<string, true> */
        $phpdocType = [];
        foreach ($types as $type) {
            if ($type instanceof Identifier) {
                $typeName = $type->toLowerString();
                $phpdocType[$typeName] = \true;
                switch ($typeName) {
                    case 'callable':
                    case 'array':
                    case 'bool':
                    case 'float':
                    case 'int':
                    case 'object':
                    case 'string':
                    case 'resource':
                    case 'null':
                        $stringType = new String_($typeName);
                        if ($typeName === 'int' || $typeName === 'float') {
                            $conditions[] = [Plugin::call("is_{$typeName}", $var), new BooleanOr(Plugin::call("is_bool", $var), Plugin::call("is_numeric", $var)), $typeName === 'int' ? Int_::class : Double::class];
                        } elseif ($typeName === 'bool') {
                            $conditions[] = [Plugin::call("is_{$typeName}", $var), new BooleanOr(new BooleanOr(Plugin::call("is_bool", $var), Plugin::call("is_numeric", $var)), Plugin::call("is_string", $var)), Bool_::class];
                        } elseif ($typeName === 'string') {
                            $conditions[] = [Plugin::call("is_{$typeName}", $var), new BooleanOr(new BooleanOr(Plugin::call("is_string", $var), new BooleanAnd(Plugin::call("is_object", $var), Plugin::call("method_exists", $var, new String_('__toString')))), new BooleanOr(Plugin::call("is_bool", $var), Plugin::call("is_numeric", $var))), CastString_::class];
                        } else {
                            $conditions[] = Plugin::call("is_{$typeName}", $var);
                        }
                        if (\in_array($typeName, ['object', 'callable'])) {
                            $oopNames[] = $stringType;
                        } else {
                            $typeNames[] = $stringType;
                        }
                        break;
                    case 'iterable':
                        $stringType = new String_('iterable');
                        $conditions[] = new BooleanOr(Plugin::call("is_array", $var), new Instanceof_($var, new FullyQualified(\Traversable::class)));
                        $typeNames[] = $stringType;
                        break;
                    case 'mixed':
                        $stringType = new String_('mixed');
                        $conditions[] = Tools::fromLiteral(\true);
                        $oopNames[] = $stringType;
                        break;
                    case 'false':
                        $stringType = new String_('false');
                        $conditions[] = new Identical($var, Tools::fromLiteral(\false));
                        $oopNames[] = $stringType;
                        break;
                    case 'true':
                        $stringType = new String_('true');
                        $conditions[] = new Identical($var, Tools::fromLiteral(\true));
                        $oopNames[] = $stringType;
                        break;
                    default:
                        $stringType = $this->resolveClassName($type, $className);
                        $conditions[] = new Instanceof_($var, new Name($typeName));
                        $oopNames[] = $stringType;
                }
            } else {
                $phpdocType[$type->toCodeString()] = \true;
                $stringType = $this->resolveClassName($type, $className);
                $conditions[] = new Instanceof_($var, $type);
                $oopNames[] = $stringType;
            }
        }
        if (\count($typeNames) + \count($oopNames) > 1) {
            $typeNames = \array_merge($oopNames, $typeNames);
            $stringType = \array_shift($typeNames);
            foreach ($typeNames as $t) {
                $stringType = new Concat($stringType, new String_("|"));
                $stringType = new Concat($stringType, $t);
            }
        }
        if ($fromNullable) {
            $stringType = new Concat(new String_('?'), $stringType);
            $conditions[] = Plugin::call("is_null", $var);
            $phpdocType['null'] = \true;
        }
        $phpdocType = \implode('|', \array_keys($phpdocType));
        $ok = \false;
        foreach ($phpdoc->children as $child) {
            if (!$child instanceof PhpDocTagNode) {
                continue;
            }
            if ($is_return && $child->value instanceof ReturnTagValueNode) {
                $ok = \true;
                break;
            }
            if ($is_param && $child->value instanceof ParamTagValueNode && $child->value->parameterName === $phpdocVar) {
                $ok = \true;
                break;
            }
            if ($is_property && $child->value instanceof VarTagValueNode && ($child->value->variableName === $phpdocVar || $child->value->variableName === '' && $is_single_property)) {
                $ok = \true;
                break;
            }
        }
        if (!$ok) {
            if ($is_param) {
                $phpdoc->children[] = new PhpDocTagNode('@param', new ParamTagValueNode($ctx->phpdocParser->parseType($phpdocType), $param->variadic, $phpdocVar, ''));
            } elseif ($is_return) {
                $phpdoc->children[] = new PhpDocTagNode('@return', new ReturnTagValueNode($ctx->phpdocParser->parseType($phpdocType), ''));
            } elseif ($is_property) {
                $phpdoc->children[] = new PhpDocTagNode('@var', new VarTagValueNode($ctx->phpdocParser->parseType($phpdocType), $phpdocVar, ''));
            }
        }
        $splitConditions = [];
        $currentConditions = [];
        foreach ($conditions as $condition) {
            if (\is_array($condition)) {
                if ($currentConditions) {
                    $currentConditions = $this->reduceConditions($currentConditions);
                    $splitConditions[] = fn(Node ...$stmts): If_ => new If_($currentConditions, ['stmts' => $stmts]);
                }
                $currentConditions = [];
                [$conditionsStrict, $conditionsLoose, $castLoose] = $condition;
                $conditionsStrict = new BooleanNot($conditionsStrict);
                $conditionsLoose = new BooleanNot($conditionsLoose);
                $splitConditions[] = fn(Node ...$stmts): If_ => new If_($conditionsStrict, ['stmts' => [new If_($conditionsLoose, ['stmts' => $stmts, 'else' => new Else_([new Expression(new Assign($var, new $castLoose($var)))])])]]);
            } else {
                $currentConditions[] = $condition;
            }
        }
        if ($currentConditions) {
            $currentConditions = $this->reduceConditions($currentConditions);
            $splitConditions[] = fn(Node ...$stmts): If_ => new If_($currentConditions, ['stmts' => $stmts]);
        }
        return [$stringType, function (Node ...$expr) use($splitConditions) : If_ {
            $prev = $expr;
            foreach ($splitConditions as $func) {
                $prev = [$func(...$prev)];
            }
            return $prev[0];
        }];
    }
    /**
     * Strip typehint.
     *
     * @param ?Param $param Parameter
     * @param (null | Identifier | Name | NullableType | UnionType) $type Type
     * @param ?Expr $className Whether the current class is anonymous
     * @param bool $force Whether to force strip
     *
     * @return (null | array{0: Node, 1: callable(Node ...): If_}) The error message, the condition wrapper callback
     */
    private function strip(Context $ctx, PhpDocNode $phpdoc, $param, ?Node $type, ?Expr $className, bool $nullish, bool $force = \false) : ?array
    {
        if (!($param instanceof Param || $param instanceof PropertyProperty || \is_null($param))) {
            throw new \TypeError(__METHOD__ . '(): Argument #3 ($param) must be of type Param|PropertyProperty|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($param) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        if (!$type) {
            return null;
        }
        $force = $force || $type->getAttribute(self::FORCE_ATTRIBUTE, \false);
        if ($type instanceof UnionType) {
            if (!$this->getConfig('union', $force)) {
                return null;
            }
            return $this->generateConditions($ctx, $phpdoc, $param, $type->types, $className, $nullish);
        }
        if ($type instanceof NullableType && $this->getConfig('nullable', $force)) {
            return $this->generateConditions($ctx, $phpdoc, $param, [$type->type], $className, \true);
        }
        $subType = $type instanceof NullableType ? $type->type : $type;
        if (\in_array($subType->toString(), $this->getConfig('types', [])) || $force) {
            return $this->generateConditions($ctx, $phpdoc, $param, [$subType], $className, $nullish || $type instanceof NullableType);
        }
        return null;
    }
    /**
     * Strip type hints from function.
     *
     * @param FunctionLike $func Function
     *
     * @return ?FunctionLike
     */
    public function enterFunction(FunctionLike $func, Context $ctx) : ?FunctionLike
    {
        $phpdoc = $ctx->phpdocParser->parsePhpDoc($func->getDocComment());
        if (!$phpdoc) {
            $phpdoc = new PhpDocNode([]);
        }
        $functionName = new Method();
        $className = null;
        $returnType = $func->getReturnType();
        if ($func instanceof ClassMethod) {
            /** @var ClassLike */
            $parent = $ctx->parents->top();
            if ($parent instanceof Interface_ || $func->getStmts() === null) {
                foreach ($func->getParams() as $param) {
                    if ($this->strip($ctx, $phpdoc, $param, $param->type, null, \false)) {
                        $param->type = null;
                    }
                }
                if ($this->checkVoid($ctx, $phpdoc, $returnType)) {
                    $func->returnType = null;
                }
                if ($this->strip($ctx, $phpdoc, null, $returnType, null, \false, $this->getConfig('return', \false))) {
                    $func->returnType = null;
                }
                $this->stack->push([self::IGNORE_RETURN]);
                $func->setDocComment(new Doc($phpdoc));
                return null;
            }
            if (!$parent->name) {
                /** @var StmtClass_ $parent */
                if ($parent->extends) {
                    $className = new ClassConstFetch($parent->extends, new Identifier('class'));
                }
                if (!$className) {
                    foreach ($parent->implements as $name) {
                        $className = new ClassConstFetch($name, new Identifier('class'));
                        break;
                    }
                }
                if ($className) {
                    $className = new Concat($className, new String_('@anonymous'));
                } else {
                    $className = new String_('class@anonymous');
                }
                $functionName = new Concat($className, new Concat(new String_(':'), new MagicConstFunction_()));
            }
        }
        $stmts = [];
        foreach ($func->getParams() as $index => $param) {
            $nullish = $param->default instanceof ConstFetch && $param->default->name->toLowerString() === 'null';
            if (!($condition = $this->strip($ctx, $phpdoc, $param, $param->type, $className, $nullish))) {
                continue;
            }
            $index++;
            $param->type = null;
            [$string, $condition] = $condition;
            $start = $param->variadic ? new Concat(new String_("(): Argument #"), new Plus(new LNumber($index), new Variable('phabelVariadicIndex'))) : new String_("(): Argument #{$index} (\$" . $param->var->name . ")");
            $start = new Concat($start, new String_(" must be of type "));
            $start = new Concat($start, $string);
            $start = new Concat($start, new String_(", "));
            $start = new Concat($start, self::callPoly('getDebugType', $param->var));
            $start = new Concat($start, new String_(" given, called in "));
            $start = new Concat($start, self::callPoly('trace'));
            $start = new Concat($functionName, $start);
            $if = $condition(new Throw_(new New_(new FullyQualified(\TypeError::class), [new Arg($start)])));
            if ($param->variadic) {
                $stmts[] = new Foreach_($param->var, new Variable('phabelVariadic'), ['keyVar' => new Variable('phabelVariadicIndex'), 'stmts' => [$if]]);
            } else {
                $stmts[] = $if;
            }
        }
        if ($stmts) {
            $ctx->toClosure($func);
            $func->stmts = \array_merge($stmts, $func->getStmts() ?? []);
        }
        if ($this->checkVoid($ctx, $phpdoc, $returnType)) {
            $ctx->toClosure($func);
            $this->stack->push([self::VOID_RETURN]);
            $func->returnType = null;
            $func->setDocComment(new Doc($phpdoc));
            return $func;
        }
        $var = new Variable('phabelReturn');
        if (!($condition = $this->strip($ctx, $phpdoc, null, $returnType, $className, \false, $this->getConfig('return', \false)))) {
            $this->stack->push([self::IGNORE_RETURN]);
            $func->setDocComment(new Doc($phpdoc));
            return $func;
        }
        $func->returnType = null;
        if (\Phabel\Plugin\GeneratorDetector::isGenerator($func)) {
            $this->stack->push([self::IGNORE_RETURN]);
            $func->setDocComment(new Doc($phpdoc));
            return $func;
        }
        $ctx->toClosure($func);
        $this->stack->push([self::TYPE_RETURN, $functionName, $func->returnsByRef(), ...$condition]);
        $stmts = $func->getStmts();
        $final = \end($stmts);
        if (!$final instanceof Return_) {
            [$string, $condition] = $condition;
            $start = new Concat($functionName, new String_("(): Return value must be of type "));
            $start = new Concat($start, $string);
            $start = new Concat($start, new String_(", none returned in "));
            $start = new Concat($start, self::callPoly('trace'));
            $throw = new Throw_(new New_(new FullyQualified(\TypeError::class), [new Arg($start)]));
            $func->stmts[] = $throw;
        }
        $func->setDocComment(new Doc($phpdoc));
        return $func;
    }
    /**
     *
     */
    public function enterReturn(Return_ $return, Context $ctx) : ?Node
    {
        if ($this->stack->isEmpty()) {
            return null;
        }
        $current = $this->stack->top();
        if ($current[0] === self::IGNORE_RETURN) {
            return null;
        }
        if ($current[0] === self::VOID_RETURN) {
            if ($return->expr !== null) {
                // This should be a transpilation error, wait for better stack traces before throwing here
                return new Throw_(new New_(new FullyQualified(\ParseError::class), [new String_("A void function must not return a value")]));
            }
            return null;
        }
        [, $functionName, $byRef, $string, $condition] = $current;
        $var = new Variable('phabelReturn');
        $assign = new Expression($byRef && $return->expr ? new AssignRef($var, $return->expr) : new Assign($var, $return->expr ?? BuilderHelpers::normalizeValue(null)));
        $start = new Concat($functionName, new String_("(): Return value must be of type "));
        $start = new Concat($start, $string);
        $start = new Concat($start, new String_(", "));
        $start = new Concat($start, self::callPoly('getDebugType', $var));
        $start = new Concat($start, new String_(" returned in "));
        $start = new Concat($start, self::callPoly('trace'));
        $if = $condition(new Throw_(new New_(new FullyQualified(\TypeError::class), [new Arg($start)])));
        $return->expr = $var;
        $ctx->insertBefore($return, $assign, $if);
        return null;
    }
    /**
     *
     */
    public function leaveFunc(FunctionLike $func) : void
    {
        $this->stack->pop();
    }
    /**
     *
     */
    public function enterProperty(Property $stmt, Context $ctx) : void
    {
        if (!$stmt->type || !$stmt->props) {
            return;
        }
        $phpdoc = $ctx->phpdocParser->parsePhpDoc($stmt->getDocComment());
        if (!$phpdoc) {
            $phpdoc = new PhpDocNode([]);
        }
        $stmt->props[0]->setAttribute(self::SINGLE_PROPERTY, \count($stmt->props) === 1);
        $strip = \false;
        foreach ($stmt->props as $property) {
            if ($this->strip($ctx, $phpdoc, $property, $stmt->type, null, \false, $this->getConfig('property', \false))) {
                $strip = \true;
            }
        }
        if ($strip) {
            $stmt->type = null;
        }
        $stmt->setDocComment(new Doc($phpdoc));
    }
    /**
     * Get trace string for errors.
     *
     * @return string
     */
    public static function trace()
    {
        $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, 1)[0];
        return ($trace['file'] ?? '') . ' on line ' . ($trace['line'] ?? '');
    }
    /**
     * Get debug type.
     *
     * @param mixed $value
     * @return string
     */
    public static function getDebugType($value)
    {
        if (\is_object($value) && $value instanceof AnonymousClassInterface) {
            return $value::getPhabelOriginalName();
        }
        return \get_debug_type($value);
    }
    /**
     *
     */
    public static function next(array $config) : array
    {
        return [\Phabel\Plugin\StringConcatOptimizer::class];
    }
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [\Phabel\Plugin\GeneratorDetector::class];
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\FunctionLike;
use SplQueue;
/**
 * Internal regenerator traversor.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class ReGeneratorInternal extends Plugin
{
    /**
     * List of nodes for each case.
     *
     * @var SplQueue<SplQueue<Node>>
     */
    private SplQueue $states;
    /**
     *
     */
    public function __construct()
    {
        $this->states = new SplQueue();
        $this->states->enqueue(new SplQueue());
    }
    /**
     * Push node to current case.
     *
     * @param Node $node Node
     *
     * @return void
     */
    private function pushNode(Node $node) : void
    {
        $this->states->top()->enqueue($node);
    }
    /**
     *
     */
    private function pushState() : int
    {
        $this->states->enqueue(new SplQueue());
        return $this->states->count() - 1;
    }
    /**
     *
     */
    public function enterRoot(FunctionLike $func)
    {
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Plugin;
use Phabel\Target\Php74\ArrowClosure;
use Phabel\Traverser;
use PhabelVendor\PhpParser\Builder\FunctionLike;
/**
 * Regenerator transformer.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class ReGenerator extends Plugin
{
    const SHOULD_ATTRIBUTE = 'shouldRegenerate';
    /**
     * Custom traverser.
     */
    private Traverser $traverser;
    /**
     *
     */
    public function __construct()
    {
        $this->traverser = Traverser::fromPlugin(new \Phabel\Plugin\ReGeneratorInternal());
    }
    /**
     *
     */
    public function enter(FunctionLike $function)
    {
        if (!$function->getAttribute(self::SHOULD_ATTRIBUTE, \false)) {
            return;
        }
        $this->traverser->traverseAst($function);
    }
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [ArrowClosure::class];
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Concat;
use PhabelVendor\PhpParser\Node\Scalar\String_;
use SplQueue;
/**
 * Optimizes concatenation of multiple strings.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class StringConcatOptimizer extends Plugin
{
    /**
     *
     */
    private function enqueue(Concat $concat, SplQueue $queue)
    {
        if ($concat->left instanceof Concat) {
            $this->enqueue($concat->left, $queue);
        } else {
            $queue->enqueue($concat->left);
        }
        if ($concat->right instanceof Concat) {
            $this->enqueue($concat->right, $queue);
        } else {
            $queue->enqueue($concat->right);
        }
    }
    /**
     *
     */
    public function enter(Concat $concat, Context $ctx) : ?Node
    {
        if ($ctx->parents->top() instanceof Concat) {
            return null;
        }
        $concatQueue = new SplQueue();
        $this->enqueue($concat, $concatQueue);
        $newQueue = new SplQueue();
        $prevNode = $concatQueue->dequeue();
        while ($concatQueue->count()) {
            $node = $concatQueue->dequeue();
            if ($node instanceof String_ && $prevNode instanceof String_) {
                $prevNode = new String_($prevNode->value . $node->value);
            } else {
                $newQueue->enqueue($prevNode);
                $prevNode = $node;
            }
        }
        $newQueue->enqueue($prevNode);
        if ($newQueue->count() === 1) {
            return $newQueue->dequeue();
        }
        $concat = new Concat($newQueue->dequeue(), $newQueue->dequeue());
        while ($newQueue->count()) {
            $concat = new Concat($concat, $newQueue->dequeue());
        }
        return $concat;
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Comment\Doc;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\Array_;
use PhabelVendor\PhpParser\Node\Expr\ArrayDimFetch;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\Isset_;
use PhabelVendor\PhpParser\Node\Expr\Variable;
use PhabelVendor\PhpParser\Node\FunctionLike;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Param;
use PhabelVendor\PhpParser\Node\Stmt\If_;
use PhabelVendor\PhpParser\Node\Stmt\Return_;
use PhabelVendor\PhpParser\Node\Stmt\Static_;
use PhabelVendor\PhpParser\Node\Stmt\StaticVar;
use SplStack;
/**
 * Enable memoization of results based on a parameter.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Memoization extends Plugin
{
    /**
     * Stack of cache objects for current function.
     *
     * @var SplStack<(null | ArrayDimFetch)>
     */
    private SplStack $cache;
    /**
     * Constructor function.
     */
    public function __construct()
    {
        $this->cache = new SplStack();
    }
    /**
     * Enter functions.
     *
     * @param FunctionLike $node Function
     *
     * @return void
     */
    public function enterFunctionLike(FunctionLike $node, Context $ctx) : void
    {
        if (!\preg_match_all('/@memoize \\$([\\w\\d_]+)/', (string) ($node->getDocComment() ?? ''), $matches)) {
            $this->cache->push(null);
            return;
        }
        if ($node->getReturnType() instanceof Identifier && $node->getReturnType()->name === 'void') {
            throw new \RuntimeException('Cannot memoize void function');
        }
        /** @var Node[] */
        $toPrepend = [];
        /** @var string[] */
        $memoizeParams = $matches[1];
        /** @var array<string, Param> */
        $params = [];
        foreach ($node->getParams() as $param) {
            if (!$param->var instanceof Variable) {
                continue;
            }
            $params[$param->var->name] = $param;
        }
        /** @var Variable[] */
        $memoizeVars = [];
        foreach ($memoizeParams as $memoizeVar) {
            if (!isset($params[$memoizeVar])) {
                throw new \RuntimeException('Cannot find memoization parameter $' . $memoizeVar);
            }
            $memoizeParam = $params[$memoizeVar];
            if ($memoizeParam->type === null) {
                throw new \RuntimeException('Cannot memoize by untyped parameter $' . $memoizeVar);
            }
            if ($memoizeParam->type instanceof Identifier) {
                if ($memoizeParam->type->name === 'array') {
                    throw new \RuntimeException('Cannot memoize by array parameter $' . $memoizeVar);
                }
                if (\in_array($memoizeParam->type->name, ['string', 'int', 'float', 'bool'])) {
                    $memoizeVars[] = $memoizeParam->var;
                    continue;
                }
            }
            $toPrepend[] = Plugin::assign($variable = new Variable($memoizeParam->var->name . '___memo'), Plugin::call('spl_object_hash', $memoizeParam->var));
            $memoizeVars[] = $variable;
        }
        $toPrepend[] = new Static_([new StaticVar($cache = new Variable('memoizeCache'), new Array_())]);
        foreach ($memoizeVars as $var) {
            $cache = new ArrayDimFetch($cache, $var);
        }
        $toPrepend[] = new If_(new Isset_([$cache]), [new Return_($cache)]);
        $this->cache->push($cache);
        if (empty($toPrepend)) {
            return;
        }
        $ctx->toClosure($node);
        $node->stmts = \array_merge($toPrepend, $node->stmts);
        $node->setDocComment(new Doc(\str_replace("@memoize ", "@memoized ", $node->getDocComment())));
    }
    /**
     * Leave function.
     *
     * @param FunctionLike $fun Function
     *
     * @return void
     */
    public function leaveFunctionLike(FunctionLike $fun, Context $context) : void
    {
        $this->cache->pop();
    }
    /**
     * Enter return expression.
     *
     * @param Return_ $return Return expression
     *
     * @return void
     */
    public function enterReturn(Return_ $return)
    {
        if ($this->cache->count() && $this->cache->top()) {
            $return->expr = new Assign($this->cache->top(), $return->expr);
        }
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\BooleanOr;
use PhabelVendor\PhpParser\Node\Expr\Instanceof_;
use PhabelVendor\PhpParser\Node\Expr\New_;
use PhabelVendor\PhpParser\Node\Expr\Ternary;
use PhabelVendor\PhpParser\Node\Scalar;
use PhabelVendor\PhpParser\NodeFinder;
/**
 * Fix certain new expressions.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class NewFixer extends Plugin
{
    /**
     *
     */
    private NodeFinder $finder;
    /**
     *
     */
    public function __construct()
    {
        $this->finder = new NodeFinder();
    }
    /**
     *
     */
    private function isParenthesised(Node $node) : bool
    {
        return !($node instanceof Expr\Variable || $node instanceof Node\Name || $node instanceof Expr\ArrayDimFetch || $node instanceof Expr\PropertyFetch || $node instanceof Expr\NullsafePropertyFetch || $node instanceof Expr\StaticPropertyFetch || $node instanceof Expr\Array_ || $node instanceof Scalar\String_ || $node instanceof Expr\ConstFetch || $node instanceof Expr\ClassConstFetch);
    }
    /**
     *
     */
    private function hasParenthesised(Node $node) : bool
    {
        return $node instanceof Expr && $this->finder->findFirst($node, fn(Node $node): bool => $this->isParenthesised($node)) !== null;
    }
    /**
     *
     */
    public function enterNew(New_ $new, Context $context)
    {
        if ($this->hasParenthesised($new->class)) {
            $valueCopy = $new->class;
            return new Ternary(new BooleanOr(new Assign($new->class = $context->getVariable(), $valueCopy), self::fromLiteral(\true)), $new, self::fromLiteral(\false));
        }
    }
    /**
     *
     */
    public function enterInstanceof(Instanceof_ $expr)
    {
        if ($this->hasParenthesised($expr->class)) {
            return self::callPoly('instanceOf', $expr->expr, $expr->class);
        }
    }
    /**
     * Check if a is instance of b.
     *
     * @param (class-string | object) $a
     * @param (class-string | object) $b
     *
     * @return boolean
     */
    public static function instanceOf($a, $b) : bool
    {
        return $a instanceof $b;
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Plugin;
use Phabel\Traverser;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\ClosureUse;
use PhabelVendor\PhpParser\Node\Expr\Variable;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class VariableFinder extends Plugin
{
    /**
     * Singleton.
     */
    private static self $singleton;
    /**
     * Traverser.
     */
    private static Traverser $singletonTraverser;
    /**
     * Get found closure uses.
     *
     * @param Node $ast Node tree
     * @param bool $byRef Whether to link by ref found variables
     *
     * @return array<string, ClosureUse>
     */
    public static function find(Node $ast, bool $byRef = \false) : array
    {
        if (!isset(self::$singleton)) {
            self::$singleton = new self();
            self::$singletonTraverser = Traverser::fromPlugin(self::$singleton);
        }
        self::$singleton->setConfig('byRef', $byRef);
        self::$singletonTraverser->traverseAst($ast, null, \false);
        return self::$singleton->getFound();
    }
    /**
     * Constructor.
     */
    private function __construct()
    {
    }
    /**
     * Found array.
     *
     * @var array<string, ClosureUse>
     */
    private array $found = [];
    /**
     * Enter variable.
     *
     * @param Variable $var
     * @return void
     */
    public function enter(Variable $var)
    {
        if (\is_string($var->name) && $var->name !== 'this') {
            $this->found[$var->name] = new ClosureUse($var, $this->getConfig('byRef', \false));
        }
    }
    /**
     * Get found closure uses.
     *
     * @return array<string, ClosureUse>
     */
    private function getFound() : array
    {
        $found = $this->found;
        $this->found = [];
        return $found;
    }
}
<?php

namespace Phabel\Plugin;

use Phabel\Context;
use Phabel\Plugin;
use Phabel\RootNode;
/**
 * Removes the file blocking inclusion of non-transpiled packages.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class ComposerSanitizer extends Plugin
{
    public const FILE_NAME = '___transpiledWithPhabel.php';
    private const MESSAGE = <<<PHP
This package requires transpilation using the phabel.io composer plugin.
To use this package please run composer update, enabling execution of plugins and generation of the lockfile.

PHP;
    /**
     * Get contents of file.
     *
     * @param string $package
     * @return string
     */
    public static function getContents(string $package) : string
    {
        return \sprintf('<?php if (!getenv("PHABEL_INSIDE_COMPOSER")) die("%s: %s");', $package, self::MESSAGE);
    }
    /**
     *
     */
    public function shouldRunFile(string $file) : bool
    {
        return \basename($file) === self::FILE_NAME;
    }
    /**
     *
     */
    public function shouldRun(string $package) : bool
    {
        return \true;
    }
    /**
     * Enter file.
     *
     * @param RootNode $_
     * @return void
     */
    public function enterRoot(RootNode $root, Context $context) : void
    {
        $root->stmts = [];
    }
}
<?php

namespace Phabel\Plugin\ReGenerator;

/**
 * Regenerator class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class ReGenerator implements \Iterator
{
    /**
     * Variable list for context suspension.
     *
     * @var array
     */
    public $variables = [];
    /**
     * Return value.
     *
     * @var mixed
     */
    public $returnValue;
    /**
     * Yield key.
     *
     * @var mixed
     */
    public $yieldKey;
    /**
     * Yield value.
     *
     * @var mixed
     */
    public $yieldValue;
    /**
     * Value sent from the outside.
     *
     * @var mixed
     */
    public $sentValue;
    /**
     * Exception sent from the outside.
     */
    public ?\Throwable $sentException = null;
    /**
     * Current state of state machine.
     */
    public int $state = 0;
    /**
     * Whether the generator has returned.
     */
    public bool $returned = \false;
    /**
     * Whether the generator was started.
     */
    public bool $started = \false;
    /**
     * Actual generator function.
     */
    public \Closure $generator;
    /**
     * Construct regenerator.
     *
     * @param \Closure $function
     */
    public function __construct(\Closure $function)
    {
        $this->generator = $function;
    }
    /**
     * Get return value.
     *
     * @return mixed
     */
    public function getReturn()
    {
        return $this->returnValue;
    }
    /**
     * Start generator.
     *
     * @return void
     */
    private function start() : void
    {
        if (!$this->started) {
            ($this->generator)($this->state, $this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned);
            $this->started = \true;
        }
    }
    /**
     * Send value into generator.
     *
     * @param mixed $value Value
     *
     * @return mixed
     */
    public function send($value)
    {
        $this->start();
        $value = $this->yieldValue;
        if (!$this->returned) {
            $this->sentValue = $value;
            try {
                ($this->generator)($this->state, $this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned);
            } catch (\Throwable $e) {
                $this->returned = \true;
                throw $e;
            } finally {
                $this->sentValue = null;
            }
        }
        return $value;
    }
    /**
     * Throw value into generator.
     *
     * @param \Throwable $throwable Excpeption
     *
     * @return mixed
     */
    public function throw(\Throwable $throwable)
    {
        $this->start();
        $value = $this->yieldValue;
        if (!$this->returned) {
            $this->sentException = $value;
            try {
                ($this->generator)($this->state, $this->variables, $this->yieldKey, $this->yieldValue, $this->sentValue, $this->sentException, $this->returnValue, $this->returned);
            } catch (\Throwable $e) {
                $this->returned = \true;
                throw $e;
            } finally {
                $this->sentException = null;
            }
        }
        return $value;
    }
    /**
     * Get current value.
     *
     * @return mixed
     */
    public function current()
    {
        $this->start();
        return $this->yieldValue;
    }
    /**
     * Get current key.
     *
     * @return mixed
     */
    public function key()
    {
        $this->start();
        return $this->yieldKey;
    }
    /**
     * Advance generator.
     *
     * @return void
     */
    public function next() : void
    {
        $this->send(null);
    }
    /**
     * Rewind generator.
     *
     * @return void
     */
    public function rewind() : void
    {
        if ($this->started && !$this->returned) {
            throw new \Exception('Cannot rewind a generator that was already run');
        }
        $this->state = 0;
        $this->started = \false;
        $this->returned = \false;
        $this->returnValue = null;
        $this->yieldKey = null;
        $this->yieldValue = null;
        $this->sentValue = null;
        $this->sentException = null;
        $this->variables = [];
        $this->start();
    }
    /**
     * Check if generator is valid.
     *
     * @return boolean
     */
    public function valid() : bool
    {
        return !$this->returned;
    }
}
<?php

namespace Phabel\Plugin;

use Exception;
use Phabel\ClassStorage;
use Phabel\ClassStorage\Builder;
use Phabel\ClassStorage\FunctionStorage;
use Phabel\ClassStorage\Storage;
use Phabel\ClassStorageProvider;
use Phabel\Context;
use Phabel\Plugin;
use Phabel\RootNode;
use PhabelVendor\PhpParser\Builder\Class_;
use PhabelVendor\PhpParser\Builder\Method;
use PhabelVendor\PhpParser\Builder\Param;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Expr\MethodCall;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Stmt\Class_ as StmtClass_;
use PhabelVendor\PhpParser\Node\Stmt\ClassLike;
use PhabelVendor\PhpParser\Node\Stmt\ClassMethod;
use PhabelVendor\PhpParser\Node\Stmt\Function_;
use PhabelVendor\PhpParser\Node\Stmt\Trait_;
use PhabelVendor\PhpParser\Node\UnionType;
use ReflectionClass;
use ReflectionFunction;
use ReflectionNamedType;
use ReflectionType;
use ReflectionUnionType;
final class ClassStoragePlugin extends Plugin
{
    private const NAME = 'ClassStoragePlugin:name';
    /**
     * Storage.
     *
     * @var array<string, array<string, Builder>>
     */
    public array $classes = [];
    /**
     * Storage.
     *
     * @var array<string, array<string, Builder>>
     */
    public array $traits = [];
    /**
     * Storage.
     *
     * @var array<string, FunctionStorage>
     */
    public array $functions = [];
    /**
     * Whether we have named argument calls.
     *
     * @var boolean
     */
    private bool $hasNamed = \false;
    /**
     * Count.
     */
    private array $count = [];
    /**
     * Plugins to call during final iteration.
     *
     * @var array<class-string<ClassStorageProvider>, true>
     */
    protected array $finalPlugins = [];
    /**
     * Check if plugin should run.
     *
     * @param string $package Package name
     *
     * @return boolean
     */
    public function shouldRun(string $package) : bool
    {
        return \true;
    }
    /**
     * Check if plugin should run.
     *
     * @param string $file File name
     *
     * @return boolean
     */
    public function shouldRunFile(string $file) : bool
    {
        return !\str_contains($file, 'vendor/composer/');
    }
    /**
     * Set configuration array.
     *
     * @param array $config
     * @return void
     */
    public function setConfigArray(array $config) : void
    {
        parent::setConfigArray($config);
        $this->finalPlugins += $config;
    }
    /**
     *
     */
    private function normalizeType(string $type) : Node
    {
        $result = BuilderHelpers::normalizeType($type);
        if ($result instanceof Name) {
            return new FullyQualified((string) $result);
        }
        return $result;
    }
    /**
     *
     */
    private function buildType(ReflectionType $type) : Node
    {
        if ($type instanceof ReflectionNamedType) {
            return $this->normalizeType($type->getName());
        } elseif ($type instanceof ReflectionUnionType) {
            $types = [];
            foreach ($type->getTypes() as $type) {
                $types[] = $this->normalizeType($type->getName());
            }
            return new UnionType($types);
        }
        return $this->normalizeType((string) $type);
    }
    /**
     * Enter file.
     *
     * @param RootNode $_
     * @return void
     */
    public function enterRoot(RootNode $_, Context $context) : void
    {
        $file = $context->getOutputFile();
        $this->count[$file] = [];
        foreach ($this->traits as $trait => $traits) {
            if (isset($traits[$file])) {
                unset($this->traits[$trait][$file]);
            }
        }
        foreach ($this->classes as $class => $classes) {
            if (isset($classes[$file])) {
                unset($this->classes[$class][$file]);
            }
        }
    }
    /**
     * Add method.
     *
     * @param ClassLike $class
     *
     * @return void
     */
    public function enter(ClassLike $class, Context $context) : void
    {
        $file = $context->getOutputFile();
        if ($class->name) {
            $name = self::getFqdn($class);
        } else {
            $name = "class@anonymous{$file}";
            $this->count[$file][$name] ??= 0;
            $name .= "@" . $this->count[$file][$name]++;
        }
        $class->setAttribute(self::NAME, $name);
        $class->setAttribute(ClassStorage::FILE_KEY, $file);
    }
    /**
     * Add function.
     *
     * @param Function_ $f
     * @return void
     */
    public function enterFunction(Function_ $f, Context $context) : void
    {
        $name = self::getFqdn($f);
        $variadic = \false;
        $args = [];
        foreach ($f->params as $param) {
            if (!$param->variadic) {
                $args[$param->var->name] = $param->default;
            } else {
                $variadic = \true;
            }
        }
        $this->functions[$name] = new FunctionStorage($args, $variadic);
    }
    /**
     *
     */
    public function enterStaticCall(StaticCall $call) : void
    {
        if ($this->hasNamed) {
            return;
        }
        $this->enterCall($call);
    }
    /**
     *
     */
    public function enterFuncCall(FuncCall $call) : void
    {
        if ($this->hasNamed) {
            return;
        }
        $this->enterCall($call);
    }
    /**
     *
     */
    public function enterMethodCall(MethodCall $call) : void
    {
        if ($this->hasNamed) {
            return;
        }
        $this->enterCall($call);
    }
    /**
     * @param (StaticCall | FuncCall | MethodCall) $call
     */
    private function enterCall($call) : void
    {
        if (!($call instanceof StaticCall || $call instanceof FuncCall || $call instanceof MethodCall)) {
            throw new \TypeError(__METHOD__ . '(): Argument #1 ($call) must be of type StaticCall|FuncCall|MethodCall, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($call) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        foreach ($call->args as $arg) {
            if ($arg->name) {
                $this->hasNamed = \true;
                return;
            }
        }
    }
    /**
     * Add method.
     *
     * @param ClassLike $class
     *
     * @return void
     */
    public function leave(ClassLike $class, Context $context) : void
    {
        $file = $context->getOutputFile();
        $name = $class->getAttribute(self::NAME);
        if ($class instanceof Trait_) {
            $this->traits[$name][$file] = new Builder($class);
        } else {
            $this->classes[$name][$file] = new Builder($class, $name);
        }
    }
    /**
     * Merge storage with another.
     *
     * @param self $other
     * @return void
     */
    public function merge($other) : void
    {
        foreach ($other->classes as $class => $classes) {
            foreach ($classes as $file => $builder) {
                if (isset($this->classes[$class][$file])) {
                    throw new Exception('Already exists!');
                }
                $this->classes[$class][$file] = $builder;
            }
        }
        foreach ($other->traits as $class => $traits) {
            foreach ($traits as $file => $builder) {
                if (isset($this->traits[$class][$file])) {
                    throw new Exception('Already exists!');
                }
                $this->traits[$class][$file] = $builder;
            }
        }
        $this->finalPlugins += $other->finalPlugins;
        $this->functions += $other->functions;
    }
    /**
     * Resolve all classes, optionally fixing up a few methods.
     *
     * @return array{0: array, 1: array<string, string>} Config to pass to new Traverser instance
     */
    public function finish() : array
    {
        foreach (\get_declared_classes() as $class) {
            $class = new ReflectionClass($class);
            if ($class->isInternal()) {
                $methods = [];
                foreach ($class->getMethods() as $method) {
                    if ($method->isPrivate()) {
                        $visibility = StmtClass_::MODIFIER_PRIVATE;
                    } elseif ($method->isProtected()) {
                        $visibility = StmtClass_::MODIFIER_PROTECTED;
                    } else {
                        $visibility = StmtClass_::MODIFIER_PUBLIC;
                    }
                    if ($method->isFinal()) {
                        $visibility |= StmtClass_::MODIFIER_FINAL;
                    }
                    if ($method->isAbstract()) {
                        $visibility |= StmtClass_::MODIFIER_ABSTRACT;
                    }
                    $params = [];
                    foreach ($method->getParameters() as $param) {
                        $paramBuilder = new Param($param->name);
                        if ($param->isVariadic()) {
                            $paramBuilder->makeVariadic();
                        }
                        if ($param->isPassedByReference()) {
                            $paramBuilder->makeByRef();
                        }
                        if ($param->isOptional()) {
                            try {
                                $paramBuilder->setDefault($param->getDefaultValue());
                            } catch (\Throwable $e) {
                            }
                        }
                        if ($param->hasType()) {
                            $paramBuilder->setType($this->buildType($param->getType()));
                        }
                        $params[] = $paramBuilder->getNode();
                    }
                    $b = ['flags' => $visibility, 'byRef' => $method->returnsReference(), 'name' => $method->getName(), 'params' => $params];
                    if ($method->hasReturnType()) {
                        $b['returnType'] = $this->buildType($method->getReturnType());
                    }
                    $methods[] = new ClassMethod($method->getName(), $b);
                }
                $classBuilder = new Class_($class->getName());
                $classBuilder->addStmts($methods);
                if ($class->isFinal()) {
                    $classBuilder->makeFinal();
                }
                if ($class->isAbstract()) {
                    $classBuilder->makeAbstract();
                }
                foreach ($class->getInterfaces() as $interface) {
                    $classBuilder->implement($this->normalizeType($interface->getName()));
                }
                $name = $this->normalizeType($class->getName());
                foreach (\get_declared_classes() as $sub) {
                    if (\is_subclass_of($class->getName(), $sub)) {
                        $classBuilder->extend($this->normalizeType($sub));
                    }
                }
                $node = $classBuilder->getNode();
                $node->setAttribute(ClassStorage::FILE_KEY, '_');
                $this->classes[$class->getName()]['_'] = new Builder($node, $class->getName());
            }
        }
        foreach (\get_defined_functions() as $sub) {
            foreach ($sub as $name) {
                $f = new ReflectionFunction($name);
                $args = [];
                $variadic = \false;
                foreach ($f->getParameters() as $param) {
                    if ($param->isVariadic()) {
                        $variadic = \true;
                    } else {
                        $default = null;
                        if ($param->isOptional()) {
                            try {
                                $default = $param->getDefaultValue();
                            } catch (\Throwable $e) {
                            }
                        }
                        $args[$param->getName()] = $default;
                    }
                }
                $this->functions[$name] = new FunctionStorage($args, $variadic);
            }
        }
        $storage = new ClassStorage($this);
        $processedAny = $this->hasNamed;
        do {
            $processed = \false;
            foreach ($this->finalPlugins as $name => $_) {
                $processed = $name::processClassGraph($storage) || $processed;
            }
            $processedAny = $processed || $processedAny;
        } while ($processed);
        if (!$processedAny) {
            return [[], []];
        }
        $result = \array_fill_keys(\array_keys($this->finalPlugins), [ClassStorage::class => $storage]);
        return [$result, $storage->getFiles()];
    }
}
<?php

namespace Phabel;

/**
 * Represent variables currently in scope.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class VariableContext
{
    /**
     * Variable list.
     *
     * @var array<string, true>
     */
    private array $variables;
    /**
     * Constructor.
     *
     * @param array<string, true> $variables Initial variables
     */
    public function __construct(array $variables = [])
    {
        $this->variables = $variables;
    }
    /**
     * Add variable.
     *
     * @param string $var Variable
     *
     * @return void
     */
    public function addVar(string $var) : void
    {
        $this->variables[$var] = \true;
    }
    /**
     * Add variables.
     *
     * @param array<string, true> $vars Variables
     *
     * @return void
     */
    public function addVars(array $vars) : void
    {
        $this->variables += $vars;
    }
    /**
     * Remove variable.
     *
     * @param string $var Variable name
     *
     * @return void
     */
    public function removeVar(string $var) : void
    {
        unset($this->variables[$var]);
    }
    /**
     * Check if variable is present.
     *
     * @param string $var
     * @return boolean
     */
    public function hasVar(string $var) : bool
    {
        return isset($this->variables[$var]);
    }
    /**
     * Get unused variable name.
     *
     * @return string
     */
    public function getVar() : string
    {
        do {
            $var = 'phabel_' . \bin2hex(\random_bytes(8));
        } while (isset($this->variables[$var]));
        $this->variables[$var] = \true;
        return $var;
    }
    /**
     * Get all variables currently defined.
     *
     * @return array
     */
    public function getVars() : array
    {
        return $this->variables;
    }
}
<?php

namespace Phabel\Commands;

use Phabel\Cli\EventHandler as CliEventHandler;
use Phabel\Cli\Formatter;
use Phabel\Cli\SimpleConsoleLogger;
use Phabel\Target\Php;
use Phabel\Traverser;
use Phabel\Version;
use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Helper\ProgressBar;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
class Run extends \Phabel\Commands\BaseCommand
{
    protected static $defaultName = 'run';
    /**
     *
     */
    protected function configure() : void
    {
        $target = \getenv('PHABEL_TARGET') ?: Php::VERSIONS[0];
        $coverage = \getenv('PHABEL_COVERAGE') ?: \false;
        $parallel = \getenv('PHABEL_PARALLEL') ?: 1;
        $this->setDescription('Run transpiler.')->setHelp('This command transpiles the specified files or directories to the specified PHP version.')->addOption('target', null, $target ? InputOption::VALUE_OPTIONAL : InputOption::VALUE_REQUIRED, 'Target PHP version', $target)->addOption('coverage', null, InputOption::VALUE_OPTIONAL, 'PHP coverage path', $coverage)->addOption('parallel', 'j', InputOption::VALUE_OPTIONAL, 'Number of threads to use for transpilation', $parallel)->addOption('install', 'i', InputOption::VALUE_NEGATABLE, 'Whether to install required dependencies automatically', \true)->addArgument('input', InputArgument::REQUIRED, 'Input path')->addArgument('output', InputArgument::REQUIRED, 'Output path');
    }
    /**
     *
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $output->setFormatter(Formatter::getFormatter());
        $output->write(\PHP_EOL . Formatter::BANNER . \PHP_EOL . \PHP_EOL);
        if (!$input->getOption('target')) {
            $output->write("<error>Missing --target parameter or PHABEL_TARGET environment variable!</error>" . \PHP_EOL . \PHP_EOL);
            return Command::INVALID;
        }
        $packages = (new Traverser(new CliEventHandler(new SimpleConsoleLogger($output), !\getenv('CI') && !$output->isDebug() ? fn(int $max): ProgressBar => new ProgressBar($output, $max, -1) : null)))->setPlugins([Php::class => ['target' => Php::normalizeVersion($input->getOption('target'))]])->setInput($input->getArgument('input'))->setOutput($input->getArgument('output'))->setCoverage($input->getOption('coverage') ?: '')->run($input->getOption('parallel'));
        $packages = ['phabel/phabel' => Version::VERSION];
        unset($packages['php'], $packages['php-64bit']);
        if (!empty($packages)) {
            if ($input->getOption('install') && \is_dir($input->getArgument('output'))) {
                \chdir($input->getArgument('output'));
                $cmd = ['composer', 'require'];
                foreach ($packages as $package => $constraint) {
                    $cmd[] = "{$package}:{$constraint}";
                }
                $this->exec($cmd);
            } else {
                $cmd = "composer require ";
                foreach ($packages as $package => $constraint) {
                    $cmd .= \escapeshellarg("{$package}:{$constraint}") . " ";
                }
                $output->write("Please run the following command to install required dependencies:" . \PHP_EOL . \PHP_EOL);
                $output->write("<bold>{$cmd}</bold>" . \PHP_EOL . \PHP_EOL);
            }
        }
        return Command::SUCCESS;
    }
}
<?php

namespace Phabel\Commands;

use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Process\Exception\ProcessFailedException;
use PhabelVendor\Symfony\Component\Process\Process;
abstract class BaseCommand extends Command
{
    /**
     *
     */
    protected function exec(array $command, bool $ignoreResult = \false) : string
    {
        $proc = new Process($command);
        $proc->run();
        if (!$proc->isSuccessful() && !$ignoreResult) {
            throw new ProcessFailedException($proc);
        }
        return $proc->getOutput();
    }
}
<?php

namespace Phabel\Commands;

use Exception;
use Phabel\Cli\Formatter;
use Phabel\Plugin\ComposerSanitizer;
use Phabel\Version;
use PhabelVendor\Symfony\Component\Console\Command\Command;
use PhabelVendor\Symfony\Component\Console\Input\InputArgument;
use PhabelVendor\Symfony\Component\Console\Input\InputInterface;
use PhabelVendor\Symfony\Component\Console\Input\InputOption;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
use PhabelVendor\Symfony\Component\Process\Process;
class Publish extends \Phabel\Commands\BaseCommand
{
    private const PLATFORM_PACKAGE = '{^(?:php(?:-64bit|-ipv6|-zts|-debug)?|hhvm|(?:ext|lib)-[a-z0-9](?:[_.-]?[a-z0-9]+)*|composer-(?:plugin|runtime)-api)$}iD';
    protected static $defaultName = 'publish';
    /**
     *
     */
    private function getMessage(string $ref) : string
    {
        return $this->exec(['git', 'log', '--format=%B', '-n', '1', $ref]);
    }
    /**
     *
     */
    protected function configure() : void
    {
        $tags = new Process(['git', 'tag', '--sort=-creatordate']);
        $tags->run();
        $tags = $tags->isSuccessful() ? \explode("\n", \trim($tags->getOutput())) : [];
        $tag = null;
        foreach ($tags as $tag) {
            if (!\str_contains($this->getMessage($tag), 'Release transpiled using https://phabel.io')) {
                break;
            }
        }
        $this->setDescription('Transpile a release.')->setHelp('This command transpiles the specified (or the latest) git tag.')->addOption("remote", 'r', InputOption::VALUE_OPTIONAL, 'Remote where to push tags', 'origin')->addOption('dry', 'd', InputOption::VALUE_NEGATABLE, "Whether to skip pushing tags to any remote", \false)->addArgument('source', $tag ? InputArgument::OPTIONAL : InputArgument::REQUIRED, 'Source tag name', $tag);
    }
    /**
     *
     */
    private function prepare(string $src, string $dest, ?callable $cb = null) : void
    {
        $this->exec(['git', 'checkout', $src]);
        $message = $this->getMessage($src);
        if (!\file_exists('composer.json')) {
            throw new Exception("composer.json doesn't exist!");
        }
        if ($cb) {
            $json = \json_decode(\file_get_contents('composer.json'), \true);
            $json = $cb($json);
            \file_put_contents('composer.json', \json_encode($json, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES));
            $this->exec(['git', 'commit', '-am', $message . "\nRelease transpiled using https://phabel.io, the PHP transpiler"], \true);
        }
        $this->exec(['git', 'tag', '-d', $dest], \true);
        $this->exec(['git', 'tag', $dest]);
    }
    /**
     *
     */
    protected function execute(InputInterface $input, OutputInterface $output)
    {
        $src = $input->getArgument('source');
        $remote = $input->getOption('remote');
        $output->setFormatter(Formatter::getFormatter());
        \trim($this->exec(['git', 'stash']));
        $branch = \trim($this->exec(["git", 'rev-parse', '--abbrev-ref', 'HEAD']));
        $output->write("<phabel>Tagging transpiled release <bold>{$src}.9998</bold>...</phabel>" . \PHP_EOL);
        $this->prepare($src, "{$src}.9998", function (array $json) : array {
            $version = 'php';
            unset($json['require']['php']);
            if (isset($json['require']['php-64bit'])) {
                unset($json['require']['php-64bit']);
                $version = 'php-64bit';
            }
            $requires = \array_filter($json['require'], fn(string $f) => !\preg_match(self::PLATFORM_PACKAGE, $f), \ARRAY_FILTER_USE_KEY);
            $json['extra'] ??= [];
            $json['extra']['phabel'] ??= [];
            $json['extra']['phabel']['require'] = $requires;
            $json['require'] = \array_merge(['phabel/phabel' => Version::VERSION, $version => '*'], \array_diff_key($json['require'], $requires));
            \file_put_contents(ComposerSanitizer::FILE_NAME, ComposerSanitizer::getContents($json['name'] ?? 'phabel'));
            $this->exec(['git', 'add', ComposerSanitizer::FILE_NAME]);
            $json['autoload'] ??= [];
            $json['autoload']['files'] ??= [];
            $json['autoload']['files'][] = ComposerSanitizer::FILE_NAME;
            return $json;
        });
        $output->write("<phabel>Tagging original release as <bold>{$src}.9999</bold>...</phabel>" . \PHP_EOL);
        $this->prepare($src, "{$src}.9999");
        $this->exec(['git', 'checkout', $branch]);
        $this->exec(['git', 'stash', 'pop'], \true);
        if (!$input->getOption('dry')) {
            $output->write("<phabel>Pushing <bold>{$src}.9998</bold>, <bold>{$src}.9999</bold> to <bold>{$remote}</bold>...</phabel>" . \PHP_EOL);
            $this->exec(['git', 'push', $remote, "{$src}.9998", "{$src}.9999"]);
        }
        $output->write("<phabel>Done!</phabel>\n<phabel>Tell users to require <bold>^{$src}</bold> in their <bold>composer.json</bold> to automatically load the correct transpiled version!</phabel>\n\n<bold>Tip</bold>: Add the following badge to your README to let users know about your minimum supported PHP version, as it won't be shown on packagist.\n<phabel>[![phabel.io](https://phabel.io/badge)](https://phabel.io)</phabel>\n");
        return Command::SUCCESS;
    }
}
<?php

namespace Phabel;

use Phabel\PluginGraph\PackageContext;
use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Name;
/**
 * Plugin.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
abstract class Plugin extends \Phabel\Tools implements \Phabel\PluginInterface
{
    /**
     * Configuration array.
     */
    private array $config = [];
    /**
     * Package context.
     */
    private PackageContext $ctx;
    /**
     * Set configuration array.
     *
     * @param array $config
     * @return void
     */
    public function setConfigArray(array $config) : void
    {
        $this->config = $config;
    }
    /**
     * Get configuration array.
     *
     * @return array
     */
    public function getConfigArray() : array
    {
        return $this->config;
    }
    /**
     * Set package context.
     *
     * @param PackageContext $ctx Ctx
     *
     * @return void
     */
    public function setPackageContext(PackageContext $ctx) : void
    {
        $this->ctx = $ctx;
    }
    /**
     * Get package context.
     *
     * @return PackageContext
     */
    public function getPackageContext() : PackageContext
    {
        return $this->ctx;
    }
    /**
     * Check if plugin should run.
     *
     * @param string $package Package name
     *
     * @return boolean
     */
    public function shouldRun(string $package) : bool
    {
        return $this->ctx->has($package);
    }
    /**
     * Check if plugin should run.
     *
     * @param string $file File name
     *
     * @return boolean
     */
    public function shouldRunFile(string $file) : bool
    {
        return !\str_contains($file, 'vendor/composer/');
    }
    /**
     * Call polyfill function from current plugin.
     *
     * @param string $name Function name
     * @param (Expr | Arg) ...$parameters Parameters
     *
     * @return StaticCall
     */
    protected static function callPoly(string $name, ...$parameters) : StaticCall
    {
        return self::call([static::class, $name], ...$parameters);
    }
    /**
     * {@inheritDoc}
     */
    public function getConfig(string $key, $default)
    {
        return $this->config[$key] ?? $default;
    }
    /**
     * {@inheritDoc}
     */
    public function setConfig(string $key, $value) : void
    {
        $this->config[$key] = $value;
    }
    /**
     * {@inheritDoc}
     */
    public function hasConfig(string $key) : bool
    {
        return isset($this->config[$key]);
    }
    /**
     * {@inheritDoc}
     */
    public static function mergeConfigs(array ...$configs) : array
    {
        $final = [];
        foreach (\array_unique($configs, \SORT_REGULAR) as $config) {
            foreach ($final as $k => $compare) {
                if (empty($intersect = \array_intersect_key($config, $compare)) || $intersect === \array_intersect_key($compare, $config)) {
                    $final[$k] = $config + $compare;
                    continue 2;
                }
            }
            $final[] = $config;
        }
        return $final;
    }
    /**
     * {@inheritDoc}
     */
    public static function splitConfig(array $config) : array
    {
        return empty($config) ? [[]] : \array_chunk($config, 1, \true);
    }
    /**
     * {@inheritDoc}
     */
    public static function getComposerRequires(array $config) : array
    {
        return [];
    }
    /**
     * {@inheritDoc}
     */
    public static function next(array $config) : array
    {
        return [];
    }
    /**
     * {@inheritDoc}
     */
    public static function previous(array $config) : array
    {
        return [];
    }
    /**
     * {@inheritDoc}
     */
    public static function withPrevious(array $config) : array
    {
        return [];
    }
    /**
     * {@inheritDoc}
     */
    public static function withNext(array $config) : array
    {
        return [];
    }
}
<?php

namespace Phabel;

use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\ArrayDimFetch;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\AssignOp;
use PhabelVendor\PhpParser\Node\Expr\AssignRef;
use PhabelVendor\PhpParser\Node\Expr\Cast\String_;
use PhabelVendor\PhpParser\Node\Expr\Clone_;
use PhabelVendor\PhpParser\Node\Expr\Eval_;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Expr\Include_;
use PhabelVendor\PhpParser\Node\Expr\List_;
use PhabelVendor\PhpParser\Node\Expr\MethodCall;
use PhabelVendor\PhpParser\Node\Expr\New_;
use PhabelVendor\PhpParser\Node\Expr\NullsafeMethodCall;
use PhabelVendor\PhpParser\Node\Expr\NullsafePropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\PostDec;
use PhabelVendor\PhpParser\Node\Expr\PostInc;
use PhabelVendor\PhpParser\Node\Expr\PreDec;
use PhabelVendor\PhpParser\Node\Expr\PreInc;
use PhabelVendor\PhpParser\Node\Expr\PropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\ShellExec;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Expr\Variable;
use PhabelVendor\PhpParser\Node\Expr\Yield_;
use PhabelVendor\PhpParser\Node\Expr\YieldFrom;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Stmt\Expression;
use PhabelVendor\PhpParser\ParserFactory;
use ReflectionClass;
/**
 * Various tools.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
abstract class Tools
{
    /**
     * Replace node of one type with another.
     *
     * @param Node $node Original node
     * @param string $class Class of new node
     * @param array $propertyMap Property map between old and new objects
     *
     * @psalm-param class-string<Node> $class Class of new node
     * @psalm-param array<string, string> $propertyMap Property map between old and new objects
     *
     * @psalm-suppress MissingClosureReturnType
     *
     * @return Node
     */
    public static function replaceType(Node $node, string $class, array $propertyMap = []) : Node
    {
        if ($propertyMap) {
            $nodeNew = (new ReflectionClass($class))->newInstanceWithoutConstructor();
            foreach ($propertyMap as $old => $new) {
                $nodeNew->{$new} = $node->{$old};
            }
            $nodeNew->setAttributes($node->getAttributes());
            return $nodeNew;
        }
        return new $class(...[...\array_map(fn(string $name) => $node->{$name}, $node->getSubNodeNames()), $node->getAttributes()]);
    }
    /**
     * Replace type in-place.
     *
     * @param Node &$node Original node
     * @param string $class Class of new node
     * @param array $propertyMap Property map between old and new objects
     *
     * @psalm-param class-string<Node> $class Class of new node
     * @psalm-param array<string, string> $propertyMap Property map between old and new objects
     *
     * @param-out Node &$node
     *
     * @return void
     */
    public static function replaceTypeInPlace(Node &$node, string $class, array $propertyMap = []) : void
    {
        $node = self::replaceType($node, $class, $propertyMap);
    }
    /**
     * Create variable assignment.
     *
     * @param Variable $name Variable
     * @param Expr $expression Expression
     *
     * @return Expression
     */
    public static function assign(Variable $name, Expr $expression) : Expression
    {
        return new Expression(new Assign($name, $expression));
    }
    /**
     * Call function.
     *
     * @param (array{0: class-string, 1: string} | callable-string) $name Function name
     * @param (Expr | Arg) ...$parameters Parameters
     *
     * @return (FuncCall | StaticCall)
     *
     * @template T of (array{0: class-string, 1: string} | callable-string)
     * @psalm-param T $name
     *
     * @psalm-return (T is callable-string ? FuncCall : StaticCall)
     */
    public static function call($name, ...$parameters)
    {
        $parameters = \array_map(fn($data) => $data instanceof Arg ? $data : new Arg($data), $parameters);
        return \is_array($name) ? new StaticCall(new FullyQualified($name[0]), $name[1], $parameters) : new FuncCall(new FullyQualified($name), $parameters);
    }
    /**
     * Call method of object.
     *
     * @param Expr $name Object name
     * @param string $method Method
     * @param (Expr | Arg) ...$parameters Parameters
     *
     * @return MethodCall
     */
    public static function callMethod(Expr $name, string $method, ...$parameters) : MethodCall
    {
        $parameters = \array_map(fn($data) => $data instanceof Arg ? $data : new Arg($data), $parameters);
        return new MethodCall($name, $method, $parameters);
    }
    /**
     * Convert array, int or other literal to node.
     *
     * @param mixed $data Data to convert
     *
     * @return Node
     */
    public static function fromLiteral($data) : Node
    {
        return self::toNode(\var_export($data, \true) . ';');
    }
    /**
     * Convert code to node.
     *
     * @param string $code Code
     *
     * @memoize $code
     *
     * @return Node
     */
    public static function toNode(string $code) : Node
    {
        $res = (new ParserFactory())->create(ParserFactory::PREFER_PHP7)->parse('<?php ' . $code);
        if ($res === null || empty($res) || !$res[0] instanceof Expression || !isset($res[0]->expr)) {
            throw new \RuntimeException('Invalid code was provided!');
        }
        return $res[0]->expr;
    }
    /**
     * Check if this node or any child node have any side effects (like calling other methods, or assigning variables).
     *
     * @param ?Expr $node Node
     *
     * @return bool
     */
    public static function hasSideEffects(?Expr $node) : bool
    {
        if (!$node) {
            return \false;
        }
        if ($node->hasAttribute('hasSideEffects') || $node instanceof String_ || $node instanceof ArrayDimFetch || $node instanceof Assign || $node instanceof AssignOp || $node instanceof AssignRef || $node instanceof Clone_ || $node instanceof Eval_ || $node instanceof FuncCall || $node instanceof Include_ || $node instanceof List_ || $node instanceof MethodCall || $node instanceof New_ || $node instanceof NullsafeMethodCall || $node instanceof NullsafePropertyFetch || $node instanceof PostDec || $node instanceof PostInc || $node instanceof PreDec || $node instanceof PreInc || $node instanceof PropertyFetch || $node instanceof StaticCall || $node instanceof Yield_ || $node instanceof YieldFrom || $node instanceof ShellExec) {
            $node->setAttribute('hasSideEffects', \true);
            return \true;
        }
        /** @var string */
        foreach ($node->getSubNodeNames() as $name) {
            if ($node->{$name} instanceof Expr) {
                if (self::hasSideEffects($node->{$name})) {
                    $node->setAttribute('hasSideEffects', \true);
                    return \true;
                }
            } elseif (\is_array($node->{$name})) {
                /** @var Node|Node[]|string */
                foreach ($node->{$name} as $var) {
                    if ($var instanceof Expr && self::hasSideEffects($var)) {
                        $node->setAttribute('hasSideEffects', \true);
                        return \true;
                    }
                }
            }
        }
        return \false;
    }
    /**
     * Get fully qualified name.
     *
     * @param Node $node
     * @param class-string $alt Alternative name
     *
     * @return class-string
     */
    public static function getFqdn(Node $node, string $alt = '') : string
    {
        if ($node instanceof FullyQualified) {
            return (string) $node;
        }
        if (isset($node->namespacedName)) {
            return (string) $node->namespacedName;
        }
        if (!$node->getAttribute('resolvedName')) {
            if ($alt) {
                return $alt;
            }
            throw new \Phabel\UnresolvedNameException();
        }
        return (string) $node->getAttribute('resolvedName', $node->getAttribute('namespacedName'));
    }
    /**
     * Create a new object extended from this object, with the specified additional trait + interface.
     *
     * @param object $obj
     * @param string $trait
     *
     * @template T of object
     * @psalm-param T $obj
     *
     * @return object
     */
    public static function cloneWithTrait(object $obj, string $trait) : object
    {
        /** @psalm-var int */
        static $count = 0;
        /** @psalm-var array<string, class-string<T>> $memoized */
        static $memoized = [];
        $reflect = new ReflectionClass($obj);
        $r = $reflect;
        while ($r && $r->isAnonymous()) {
            $r = $r->getParentClass();
        }
        $extend = "extends \\" . $r->getName();
        if (isset($memoized["{$trait} {$extend}"])) {
            /** @psalm-suppress MixedMethodCall */
            $newObj = ($phabel_066b42cf321fbe43 = $memoized["{$trait} {$extend}"]) || \true ? new $phabel_066b42cf321fbe43() : \false;
        } else {
            $memoized["{$trait} {$extend}"] = "phabelTmpClass{$count}";
            $eval = "class phabelTmpClass{$count} {$extend} {\n                use \\{$trait};\n                public function __construct() {}\n            }\n            return new phabelTmpClass{$count};";
            $count++;
            /** @var object */
            $newObj = eval($eval);
        }
        $reflectNew = new ReflectionClass($newObj);
        do {
            if ($tmp = $reflectNew->getParentClass()) {
                $reflectNew = $tmp;
            }
            foreach ($reflect->getProperties() as $prop) {
                if ($reflectNew->hasProperty($prop->getName())) {
                    $propNew = $reflectNew->getProperty($prop->getName());
                    $propNew->setAccessible(\true);
                    $prop->setAccessible(\true);
                    $propNew->setValue($newObj, $prop->getValue($obj));
                }
            }
        } while ($reflect = $reflect->getParentClass());
        return $newObj;
    }
    /**
     * Checks private property exists in an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     *
     * @psalm-suppress InvalidScope
     * @psalm-suppress PossiblyInvalidFunctionCall
     * @psalm-suppress MixedReturnStatement
     * @psalm-suppress MixedPropertyFetch
     * @psalm-suppress MixedInferredReturnType
     *
     * @return bool
     * @access public
     */
    public static function hasVar(object $obj, string $var) : bool
    {
        return \Closure::bind(function () use($var) : bool {
            return isset($this->{$var});
        }, $obj, \get_class($obj))->__invoke();
    }
    /**
     * Accesses a private variable from an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     *
     * @psalm-suppress InvalidScope
     * @psalm-suppress PossiblyInvalidFunctionCall
     * @psalm-suppress MixedPropertyFetch
     *
     * @return mixed
     * @access public
     */
    public static function &getVar($obj, string $var)
    {
        return \Closure::bind(
            /** @return mixed */
            function &() use($var) {
                return $this->{$var};
            },
            $obj,
            \get_class($obj)
        )->__invoke();
    }
    /**
     * Sets a private variable in an object.
     *
     * @param object $obj Object
     * @param string $var Attribute name
     * @param mixed $val Attribute value
     *
     * @psalm-suppress InvalidScope
     * @psalm-suppress PossiblyInvalidFunctionCall
     *
     * @return void
     *
     * @access public
     */
    public static function setVar($obj, string $var, &$val) : void
    {
        \Closure::bind(function () use($var, &$val) {
            $this->{$var} =& $val;
        }, $obj, \get_class($obj))->__invoke();
    }
    /**
    * Adapted from https://gist.github.com/divinity76/01ef9ca99c111565a72d3a8a6e42f7fb.
    returns number of cpu cores
    Copyleft 2018, license: WTFPL.
    * @throws \RuntimeException
    * @throws \LogicException
    * @psalm-suppress ForbiddenCode
    */
    public static function getCpuCount() : int
    {
        static $result = -1;
        if ($result !== -1) {
            return $result;
        }
        if (\defined('PHP_WINDOWS_VERSION_MAJOR')) {
            /*
            $str = trim((string) shell_exec('wmic cpu get NumberOfCores 2>&1'));
            if (!preg_match('/(\d+)/', $str, $matches)) {
                throw new \RuntimeException('wmic failed to get number of cpu cores on windows!');
            }
            return ((int) $matches [1]);
            */
            return $result = 1;
        }
        if (self::ini_get('pcre.jit') === '1' && \PHP_OS === 'Darwin' && \version_compare(\PHP_VERSION, '7.3.0') >= 0 && \version_compare(\PHP_VERSION, '7.4.0') < 0) {
            return $result = 1;
        }
        if (!\extension_loaded('pcntl')) {
            return $result = 1;
        }
        $has_nproc = \trim((string) @\shell_exec('command -v nproc'));
        if ($has_nproc) {
            $ret = @\shell_exec('nproc');
            if (\is_string($ret)) {
                $ret = \trim($ret);
                $tmp = \filter_var($ret, \FILTER_VALIDATE_INT);
                if (\is_int($tmp)) {
                    return $result = $tmp;
                }
            }
        }
        $ret = @\shell_exec('sysctl -n hw.ncpu');
        if (\is_string($ret)) {
            $ret = \trim($ret);
            $tmp = \filter_var($ret, \FILTER_VALIDATE_INT);
            if (\is_int($tmp)) {
                return $result = $tmp;
            }
        }
        if (\is_readable('/proc/cpuinfo')) {
            $cpuinfo = \file_get_contents('/proc/cpuinfo');
            $count = \Phabel\Target\Php80\Polyfill::substr_count($cpuinfo, 'processor');
            if ($count > 0) {
                return $result = $count;
            }
        }
        return $result = 1;
    }
    /**
     * Safely get value from php.ini.
     *
     * @param string $key
     * @param mixed $default
     * @return mixed
     */
    public static function ini_get(string $key, $default = null)
    {
        try {
            if (\function_exists('ini_get')) {
                return @\ini_get($key);
            }
        } catch (\Throwable $e) {
        }
        return $default;
    }
    /**
     * Recursively copy a directory to another, calling a callback for files.
     *
     * @param string $input
     * @param string $output
     * @param (callable(SplFileInfo , string , string ): bool | null) $cb
     * @return void
     */
    public static function traverseCopy(string $input, string $output, ?callable $cb = null) : void
    {
        if (!\file_exists($output)) {
            \mkdir($output, 0777, \true);
        }
        $input = \rtrim($input, \DIRECTORY_SEPARATOR);
        $output = \rtrim($output, \DIRECTORY_SEPARATOR);
        $it = new \RecursiveDirectoryIterator($input, \RecursiveDirectoryIterator::SKIP_DOTS);
        $ri = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::SELF_FIRST);
        /** @var \SplFileInfo $file */
        foreach ($ri as $file) {
            $rel = $ri->getSubPathname();
            $sourcePath = $input . \DIRECTORY_SEPARATOR . $rel;
            $targetPath = $output . \DIRECTORY_SEPARATOR . $rel;
            if ($file->isDir()) {
                if (!\file_exists($targetPath)) {
                    \mkdir($targetPath, $file->getPerms(), \true);
                }
            } elseif ($file->isLink()) {
                $dest = $file->getRealPath();
                if ($dest !== \false && \str_starts_with($dest, $input)) {
                    $dest = \trim(\Phabel\Target\Php80\Polyfill::substr($dest, \strlen($input)), \DIRECTORY_SEPARATOR);
                    $dest = \str_repeat('..' . \DIRECTORY_SEPARATOR, \Phabel\Target\Php80\Polyfill::substr_count($rel, \DIRECTORY_SEPARATOR)) . $dest;
                    $link = $output . \DIRECTORY_SEPARATOR . $rel;
                    if (\file_exists($link)) {
                        \unlink($link);
                    }
                    \symlink($dest, $link);
                }
            } elseif ($file->isFile()) {
                if ($cb && $cb($file, $sourcePath, $targetPath)) {
                    // All done!
                } elseif (\realpath($targetPath) !== $file->getRealPath()) {
                    \copy($file->getRealPath(), $targetPath);
                    \chmod($targetPath, $file->getPerms());
                }
            }
        }
    }
}
<?php

namespace Phabel\Composer;

use Phabel\Cli\Formatter;
use Phabel\EventHandler as PhabelEventHandler;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Helper\ProgressBar;
use Throwable;
class EventHandler extends PhabelEventHandler
{
    /**
     * @var OutputFormatter
     */
    private $outputFormatter;
    /**
     * @var null|ProgressBar
     */
    private $progress = null;
    /**
     * Progress bar getter.
     *
     * @var null|(callable(int): ProgressBar)
     */
    private $getProgressBar = null;
    /**
     *
     */
    private int $count = 0;
    /**
     *
     */
    public function __construct($logger, ?callable $getProgressBar)
    {
        $this->logger = $logger;
        $this->outputFormatter = Formatter::getFormatter();
        $this->getProgressBar = $getProgressBar;
    }
    private $logger;
    /**
     *
     */
    public function onBeginPluginGraphResolution() : void
    {
        $this->logger->debug($this->outputFormatter->format("<phabel>Plugin graph resolution in progress...</phabel>"));
    }
    /**
     *
     */
    public function onEndPluginGraphResolution() : void
    {
        $this->logger->debug($this->outputFormatter->format("<phabel>Finished plugin graph resolution!</phabel>"));
    }
    /**
     *
     */
    private function startProgressBar(string $message, int $total, int $workers = 1) : void
    {
        if ($this->getProgressBar) {
            try {
                $this->progress = ($this->getProgressBar)($total);
                $this->progress->setFormat($this->outputFormatter->format('<phabel>%message% <bold>%percent:3s%%</bold></phabel> (%current%/%max%)'));
            } catch (\Throwable $phabel_fa0f792622ceedd2) {
            }
        }
        if ($this->progress) {
            if ($workers > 1) {
                $message .= " ({$workers} threads)";
            }
            $this->progress->setMessage($message);
            $this->progress->clear();
            $this->progress->start();
        } else {
            $this->logger->debug($this->outputFormatter->format("<phabel>{$message}</phabel>"));
        }
    }
    /**
     *
     */
    public function onBeginDirectoryTraversal(int $total, int $workers) : void
    {
        if (!$this->count) {
            $message = 'Transpilation in progress...';
        } else {
            $secondary = $this->count === 1 ? 'covariance and contravariance' : 'further covariance and contravariance';
            $message = "Applying {$secondary} transforms...";
        }
        $this->count++;
        $this->startProgressBar($message, $total, $workers);
    }
    /**
     * @param (int | \Throwable) $iterationsOrError
     */
    public function onEndAstTraversal(string $file, $iterationsOrError) : void
    {
        if (!$iterationsOrError instanceof \Throwable) {
            if (!\is_int($iterationsOrError)) {
                if (!(\is_bool($iterationsOrError) || \is_numeric($iterationsOrError))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #2 ($iterationsOrError) must be of type Throwable|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($iterationsOrError) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                $iterationsOrError = (int) $iterationsOrError;
            }
        }
        ($this->progress ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->advance();
        if ($iterationsOrError instanceof Throwable) {
            $this->logger->error($this->outputFormatter->format(\PHP_EOL . "<error>{$iterationsOrError->getMessage()}!</error>"));
            $this->logger->debug($this->outputFormatter->format("<error>{$iterationsOrError}</error>"));
        } else {
            $this->logger->debug($this->outputFormatter->format("<phabel>Transpiled {$file} in {$iterationsOrError} iterations!</phabel>"));
        }
    }
    /**
     *
     */
    public function onEndDirectoryTraversal() : void
    {
        ($this->progress ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->finish();
        $this->logger->warning("");
    }
    /**
     *
     */
    public function onBeginClassGraphMerge(int $count) : void
    {
        $this->startProgressBar("Merging class graphs...", $count);
    }
    /**
     *
     */
    public function onClassGraphMerged() : void
    {
        ($this->progress ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->advance();
        $this->logger->debug($this->outputFormatter->format("<phabel>Merged class graph!</phabel>"));
    }
    /**
     *
     */
    public function onEndClassGraphMerge() : void
    {
        ($this->progress ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->finish();
    }
    /**
     *
     */
    public function onEnd() : void
    {
        ($this->progress ?? \Phabel\Target\Php80\NullSafe\NullSafe::$singleton)->clear();
        $this->logger->warning($this->outputFormatter->format('<phabel>Done!</phabel>'));
    }
}
<?php

namespace Phabel\Composer;

use Composer\Composer;
use Composer\Console\Application;
use Composer\EventDispatcher\EventSubscriberInterface;
use Composer\Installer\InstallerEvent;
use Composer\IO\IOInterface;
use Composer\Plugin\PluginInterface;
use Composer\Repository\PlatformRepository;
use Composer\Script\Event;
use Composer\Script\ScriptEvents;
use Phabel\Target\Php;
use Phabel\Tools;
use Phabel\Version;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Plugin implements PluginInterface, EventSubscriberInterface
{
    /**
     *
     */
    private string $toRequire = '';
    /**
     * @psalm-suppress MissingConstructor
     */
    private \Phabel\Composer\Transformer $transformer;
    /**
     *
     */
    private ?array $lock = null;
    /**
     * Apply plugin modifications to Composer.
     *
     * @param Composer $composer Composer instance
     * @param IOInterface $io IO instance
     *
     * @return void
     */
    public function activate(Composer $composer, IOInterface $io) : void
    {
        if (!\defined('PHABEL_INCLUDED')) {
            $json = \json_decode(\file_get_contents(__DIR__ . '/../../composer.json'), \true);
            foreach ($json['autoload']['files'] as $file) {
                require_once __DIR__ . '/../../' . $file;
            }
        }
        if (\file_exists('composer.lock')) {
            $this->lock = \json_decode(\file_get_contents('composer.lock'), \true);
        }
        \putenv("PHABEL_INSIDE_COMPOSER=1");
        $rootPackage = $composer->getPackage();
        $php = $rootPackage->getConfig()['platform']['php'] ?? Php::DEFAULT_TARGET;
        $php = Php::normalizeVersion($php);
        $this->transformer = \Phabel\Composer\Transformer::getInstance($io, $php);
        $this->transformer->setInstallationManager($composer->getInstallationManager());
        $this->transformer->preparePackage($rootPackage, $rootPackage->getName());
        foreach ($rootPackage->getRequires() as $link) {
            if (PlatformRepository::isPlatformPackage($link->getTarget())) {
                continue;
            }
            $this->toRequire = $link->getTarget();
        }
        $repoManager = $composer->getRepositoryManager();
        $repos = $repoManager->getRepositories();
        foreach (\array_reverse($repos) as $repo) {
            if (!\method_exists($repo, 'setPhabelTransformer')) {
                $repo = Tools::cloneWithTrait($repo, \Phabel\Composer\Repository::class);
                $repo->setPhabelTransformer($this->transformer);
                $repoManager->prependRepository($repo);
            }
        }
    }
    /**
    * Remove any hooks from Composer.
    *
    * This will be called when a plugin is deactivated before being
    uninstalled, but also before it gets upgraded to a new version
    so the old one can be deactivated and the new one activated.
    *
    * @param Composer $composer
    * @param IOInterface $io
    */
    public function deactivate(Composer $composer, IOInterface $io)
    {
    }
    /**
     * Prepare the plugin to be uninstalled.
     *
     * This will be called after deactivate.
     *
     * @param Composer $composer
     * @param IOInterface $io
     */
    public function uninstall(Composer $composer, IOInterface $io)
    {
    }
    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents()
    {
        return [ScriptEvents::POST_INSTALL_CMD => ['onInstall', 1], ScriptEvents::POST_UPDATE_CMD => ['onUpdate', 1]];
    }
    /**
     *
     */
    public function onInstall(Event $event) : void
    {
        $this->run($event, \false);
    }
    /**
     *
     */
    public function onUpdate(Event $event) : void
    {
        $this->run($event, \true);
    }
    /**
     *
     */
    private function run(Event $event, bool $isUpdate) : void
    {
        $lock = \json_decode(\file_get_contents('composer.lock'), \true);
        if ($this->transformer->transform($lock, $this->lock)) {
            \register_shutdown_function(function () use($isUpdate) {
                /** @var Application */
                $application = ($GLOBALS['application'] ?? null) instanceof Application ? $GLOBALS['application'] : new Application();
                $this->transformer->log("Loading additional dependencies...\n");
                if (!$isUpdate) {
                    $require = $application->find('require');
                    $require->run(new ArrayInput(['packages' => [$this->toRequire]]), new NullOutput());
                } else {
                    $application->setAutoExit(\false);
                    $application->run();
                }
            });
        } else {
            \register_shutdown_function(function () {
                $json = \json_decode(\file_get_contents('composer.json'), \true);
                if (!isset($json['require']['phabel/phabel']) && !isset($json['require-dev']['phabel/phabel'])) {
                    return;
                }
                $old = $json['extra']['phabel']['revision'] ?? -1;
                if ($old === Version::LATEST) {
                    return;
                }
                $json['extra'] ??= [];
                $json['extra']['phabel'] ??= [];
                $json['extra']['phabel']['revision'] = Version::LATEST;
                $json['require'] ??= [];
                $json['require']['php'] = '^8.0';
                $this->transformer->banner();
                $f = [$this->transformer, 'format'];
                $io = $this->transformer->getIo();
                for ($x = $old; $x <= Version::LATEST; $x++) {
                    if (isset(Version::CHANGELOG[$x])) {
                        $io->writeError($f(Version::CHANGELOG[$x]));
                    }
                }
                \file_put_contents('composer.json', \json_encode($json, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES) . \PHP_EOL);
            });
        }
    }
    /**
     * Emitted before composer solves dependencies.
     *
     * @param InstallerEvent $event Event
     *
     * @return void
     */
    public function onDependencySolve(InstallerEvent $event) : void
    {
    }
}
<?php

namespace Phabel\Composer;

use Composer\Package\PackageInterface;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
trait Repository
{
    /**
     *
     */
    private \Phabel\Composer\Transformer $phabelTransformer;
    /**
     * TODO v3 should make this private once we can drop PHP 5.3 support.
     *
     * @param string $name package name (must be lowercased already)
     * @private
     */
    public function isVersionAcceptable($constraint, $name, $versionData, array $acceptableStabilities = null, array $stabilityFlags = null)
    {
        [$name] = $this->phabelTransformer->extractTarget($name);
        return parent::isVersionAcceptable($constraint, $name, $versionData, $acceptableStabilities, $stabilityFlags);
    }
    /**
     * Load packages.
     *
     * @param array $packageNameMap
     * @param array $acceptableStabilities
     * @param array $stabilityFlags
     * @param array $alreadyLoaded
     * @return void
     */
    public function loadPackages(array $packageNameMap, array $acceptableStabilities, array $stabilityFlags, array $alreadyLoaded = [])
    {
        $newAlreadyLoaded = [];
        $newPackageNameMap = [];
        $transformInfo = [];
        foreach ($packageNameMap as $key => $constraint) {
            [$package, $target] = $this->phabelTransformer->extractTarget($key);
            $newPackageNameMap[$target] ??= [];
            $newPackageNameMap[$target][$package] = $constraint;
            $transformInfo[$target] ??= [];
            $transformInfo[$target][$package] = $key;
        }
        foreach ($alreadyLoaded as $key => $versions) {
            [$package, $target] = $this->phabelTransformer->extractTarget($key);
            $newAlreadyLoaded[$target] ??= [];
            $newAlreadyLoaded[$target][$package] = $versions;
        }
        $finalNamesFound = [];
        $finalPackages = [];
        foreach ($newPackageNameMap as $target => $map) {
            $t = $transformInfo[$target];
            $packages = parent::loadPackages($map, $acceptableStabilities, $stabilityFlags, $newAlreadyLoaded[$target] ?? []);
            foreach ($packages['namesFound'] as $package) {
                $finalNamesFound[] = $t[$package];
            }
            foreach ($packages['packages'] as $package) {
                $package = clone $package;
                $this->phabelTransformer->preparePackage($package, $t[$package->getName()], $target);
                $finalPackages[] = $package;
            }
        }
        $packages['namesFound'] = $finalNamesFound;
        $packages['packages'] = $finalPackages;
        /*$missing = \array_diff(\array_keys($packageNameMap), $finalNamesFound);
          if (!empty($missing)) {
              $this->phabelTransformer->getIo()->debug("Could not find the following packages in ".\get_parent_class($this).": ".\implode(", ", $missing));
          } else {
              $this->phabelTransformer->getIo()->debug("Loaded packages in ".\get_parent_class($this).": ".\implode(", ", $finalNamesFound));
          }*/
        return $packages;
    }
    /**
     * Searches for the first match of a package by name and version.
     *
     * @param string $name package name
     * @param (string | \Composer\Semver\Constraint\ConstraintInterface) $constraint package version or version constraint to match against
     *
     * @return (PackageInterface | null)
     */
    public function findPackage($fullName, $constraint)
    {
        [$name, $target] = $this->phabelTransformer->extractTarget($fullName);
        if (!($package = parent::findPackage($name, $constraint))) {
            return null;
        }
        $package = clone $package;
        $this->phabelTransformer->preparePackage($package, $fullName, $target);
        return $package;
    }
    /**
     * Searches for all packages matching a name and optionally a version.
     *
     * @param string $name package name
     * @param (string | \Composer\Semver\Constraint\ConstraintInterface) $constraint package version or version constraint to match against
     *
     * @return PackageInterface[]
     */
    public function findPackages($fullName, $constraint = null)
    {
        [$name, $target] = $this->phabelTransformer->extractTarget($fullName);
        $packages = parent::findPackages($name, $constraint);
        foreach ($packages as &$package) {
            $package = clone $package;
            $this->phabelTransformer->preparePackage($package, $fullName, $target);
        }
        return $packages;
    }
    /**
     * Returns list of registered packages.
     *
     * @return PackageInterface[]
     */
    public function getPackages()
    {
        $packages = parent::getPackages();
        foreach ($packages as &$package) {
            $package = clone $package;
            $this->phabelTransformer->preparePackage($package, $package->getName());
        }
        return $packages;
    }
    /**
     * Set the Transformer.
     *
     * @param Transformer $phabelTransformer
     *
     * @return self
     */
    public function setPhabelTransformer(\Phabel\Composer\Transformer $phabelTransformer) : self
    {
        $this->phabelTransformer = $phabelTransformer;
        return $this;
    }
}
<?php

namespace Phabel\Composer;

use Composer\Installer\InstallationManager;
use Composer\IO\ConsoleIO;
use Composer\IO\IOInterface;
use Composer\Package\AliasPackage;
use Composer\Package\BasePackage;
use Composer\Package\Link;
use Composer\Package\Package;
use Composer\Package\PackageInterface;
use Composer\Repository\PlatformRepository;
use Composer\Semver\Constraint\Constraint as ComposerConstraint;
use Composer\Semver\Constraint\MatchAllConstraint;
use Composer\Semver\VersionParser;
use Phabel\Cli\Formatter;
use Phabel\PluginGraph\Graph;
use Phabel\Target\Php;
use Phabel\Tools;
use Phabel\Traverser;
use ReflectionClass;
use Symfony\Component\Filesystem\Filesystem;
class Transformer
{
    const HEADER = 'phabel-transpiler';
    const SEPARATOR = '.';
    /**
     * IO interface.
     */
    private $outputFormatter;
    /**
     * Version parser.
     */
    private VersionParser $versionParser;
    /**
     * Requires.
     */
    private array $requires = [];
    /**
     * Whether we processed requirements.
     */
    private array $processedRequires = [];
    /**
     * Whether we processed any dependencies.
     */
    private bool $processed = \false;
    /**
     * Whether a progress bar should be shown.
     */
    private bool $doProgress = \true;
    /**
     * Installer.
     *
     * @var InstallationManager
     */
    private InstallationManager $installer;
    /**
     * Instance.
     */
    private static self $instance;
    /**
     * Get singleton.
     *
     * @return self
     */
    public static function getInstance(IOInterface $io, int $version) : self
    {
        self::$instance ??= new self($io, $version);
        return self::$instance;
    }
    /**
     * Constructor.
     *
     * @param IOInterface $io
     */
    private function __construct(IOInterface $io, int $version)
    {
        $this->version = $version;
        $this->io = $io;
        $this->versionParser = new VersionParser();
        $this->outputFormatter = Formatter::getFormatter();
    }
    /**
     *
     */
    private int $version;
    /**
     *
     */
    private IOInterface $io;
    /**
     * Set installation manager.
     *
     * @param InstallationManager $installationManager
     * @return void
     */
    public function setInstallationManager(InstallationManager $installationManager) : void
    {
        $this->installer = $installationManager;
    }
    /**
     * Log text.
     *
     * @param string $text
     * @param int $verbosity
     * @param bool $newline
     * @return void
     */
    public function log(string $text, int $verbosity = IOInterface::NORMAL, bool $newline = \true) : void
    {
        $this->io->writeError($this->format("<phabel>{$text}</phabel>"), $newline, $verbosity);
    }
    /**
     * Format text.
     *
     * @param string $text
     * @return string
     */
    public function format(string $text) : string
    {
        return $this->outputFormatter->format($text);
    }
    /**
     * Print banner.
     *
     * @return void
     */
    public function banner() : void
    {
        static $printed = \false;
        if (!$printed) {
            $printed = \true;
            $this->log(\PHP_EOL . Formatter::BANNER . \PHP_EOL);
        }
    }
    /**
     * Prepare package for phabel tree injection.
     *
     * @param PackageInterface $package Package
     * @param string $newName New package name
     * @param int $target Target
     *
     * @return void
     */
    public function preparePackage(PackageInterface &$package, string $newName, int $target = Php::TARGET_IGNORE) : void
    {
        /**
         * Phabel configuration of current package.
         * @var array
         */
        $config = $package->getExtra()['phabel'] ?? [];
        $myTarget = Php::normalizeVersion($config['target'] ?? $this->version);
        $havePhabel = \false;
        foreach ($package->getRequires() as $link) {
            [$name] = $this->extractTarget($link->getTarget());
            if ($name === 'phabel/phabel') {
                $havePhabel = \true;
            }
            if ($link->getTarget() === 'php') {
                $myTarget = $link->getConstraint()->getLowerBound()->getVersion();
            }
            if ($link->getTarget() === 'php-64bit') {
                $myTarget = $link->getConstraint()->getLowerBound()->getVersion();
            }
        }
        $this->processed = \true;
        if (!$havePhabel) {
            if ($target === Php::TARGET_IGNORE) {
                $this->log("Skipping " . $package->getName() . "={$newName}", IOInterface::VERY_VERBOSE);
                return;
            }
            $myTarget = $target;
        } else {
            $myTarget = Php::normalizeVersion($myTarget);
            $myTarget = \min($myTarget, $target);
        }
        $this->log("Applying " . $package->getName() . "={$newName}", IOInterface::VERY_VERBOSE);
        $this->processedRequires = $this->requires;
        $requires = $this->requires;
        foreach ($config['require'] ?? [] as $name => $constraint) {
            $requires[$this->injectTarget($name, $myTarget)] = $constraint;
        }
        if ($newName !== $package->getName()) {
            if (\method_exists($package, 'setProvides')) {
                $package->setProvides(\array_merge($package->getProvides(), [$package->getName() => new Link($newName, $package->getName(), new ComposerConstraint('=', $package->getVersion()), Link::TYPE_PROVIDE, $package->getVersion())]));
            }
            if (\method_exists($package, 'setConflicts')) {
                $package->setConflicts(\array_merge($package->getConflicts(), [$package->getName() => new Link($newName, $package->getName(), new MatchAllConstraint(), Link::TYPE_CONFLICT, '*')]));
            }
        }
        $base = new ReflectionClass(BasePackage::class);
        $method = $base->getMethod('__construct');
        $method->invokeArgs($package, [$newName]);
        $this->processRequires($package, $myTarget, $requires, $havePhabel);
    }
    /**
     * Add phabel config to all requires.
     *
     * @param PackageInterface $package
     * @param int $target
     * @param array $config
     * @param bool $havePhabel
     *
     * @return void
     */
    private function processRequires(PackageInterface $package, int $target, array $requires, bool $havePhabel)
    {
        $links = [];
        foreach ($package->getRequires() as $name => $link) {
            if (PlatformRepository::isPlatformPackage($link->getTarget())) {
                if ($link->getTarget() === 'php') {
                    $constraint = new ComposerConstraint('>=', Php::unnormalizeVersion($target));
                    $links[$name] = new Link($package->getName(), $link->getTarget(), $constraint, $link->getDescription(), $constraint->getPrettyString());
                } elseif ($link->getTarget() === 'php-64bit') {
                    $constraint = new ComposerConstraint('>=', Php::unnormalizeVersion($target));
                    $links[$name] = new Link($package->getName(), $link->getTarget(), $constraint, $link->getDescription(), $constraint->getPrettyString());
                } else {
                    $links[$name] = $link;
                }
                continue;
            }
            $links[$name] = new Link($package->getName(), $havePhabel ? $link->getTarget() : $this->injectTarget($link->getTarget(), $target), $link->getConstraint(), $link->getDescription(), $link->getPrettyConstraint());
        }
        foreach ($requires as $name => $version) {
            $links[$name] = new Link($package->getName(), $name, $this->versionParser->parseConstraints($version), Link::TYPE_REQUIRE, $version);
        }
        if ($package instanceof Package) {
            $package->setRequires($links);
        } elseif ($package instanceof AliasPackage) {
            $this->processRequires($package->getAliasOf(), $target, $requires, $havePhabel);
        }
    }
    /**
     * Inject target into package name.
     *
     * @param string $package
     * @param int $target
     * @return string
     */
    public static function injectTarget(string $package, int $target) : string
    {
        [$package] = self::extractTarget($package);
        return self::HEADER . $target . self::SEPARATOR . $package;
    }
    /**
     * Look for phabel configuration parameters in constraint.
     *
     * @param string $package package name
     *
     * @return array{0: string, 1: int}
     */
    public static function extractTarget(string $package) : array
    {
        if (\str_starts_with($package, self::HEADER)) {
            [$version, $package] = \explode(self::SEPARATOR, \Phabel\Target\Php80\Polyfill::substr($package, \strlen(self::HEADER)), 2);
            return [$package, $version];
        }
        return [$package, Php::TARGET_IGNORE];
    }
    /**
     * Transform dependencies.
     *
     * @param ?array $lock
     * @param ?array $old
     * @return bool Whether any additional packages should be installed or updated
     */
    public function transform(?array $lock, ?array $old) : bool
    {
        $enabled = \gc_enabled();
        \gc_enable();
        $filesystem = new Filesystem();
        $packages = $lock['packages'] ?? [];
        $this->log("Creating plugin graph...", IOInterface::VERBOSE);
        $missingDeps = \false;
        $paths = [];
        $byName = [];
        foreach ($packages as $package) {
            $config = $package['extra']['phabel'] ?? [];
            $myTarget = Php::normalizeVersion($config['target'] ?? $this->version);
            $havePhabel = \false;
            $have = [];
            foreach ($package['require'] ?? [] as $name => $version) {
                [$name] = $this->extractTarget($name);
                $have[$name] = $version;
                if ($name === 'phabel/phabel') {
                    $havePhabel = \true;
                }
            }
            foreach ($config['require'] ?? [] as $name => $version) {
                [$name] = $this->extractTarget($name);
                if (!isset($have[$name])) {
                    $missingDeps = \true;
                }
            }
            [$name, $target] = $this->extractTarget($package['name']);
            if ($target === Php::TARGET_IGNORE) {
                if (!$havePhabel) {
                    continue;
                }
                $target = $myTarget;
            }
            try {
                $installer = $this->installer->getInstaller($package['type']);
                $p = new Package($package['name'], $package['version'], $package['version']);
                $p->setType($package['type']);
                $current = $installer->getInstallPath($p);
                if (!$filesystem->isAbsolutePath($current)) {
                    $current = \getcwd() . \DIRECTORY_SEPARATOR . $current;
                }
                $p = new Package($name, $package['version'], $package['version']);
                $p->setType($package['type']);
                $new = $installer->getInstallPath($p);
                if (!$filesystem->isAbsolutePath($new)) {
                    $new = \getcwd() . \DIRECTORY_SEPARATOR . $new;
                }
                $paths[$name] = [\rtrim(\str_replace('\\', '/', $current), '/'), \rtrim(\str_replace('\\', '/', $new), '/')];
            } catch (\Throwable $e) {
            }
            $package['phabelTarget'] = (int) $target;
            $package['phabelConfig'] = [$config];
            unset($package['phabelConfig'][0]['target']);
            $byName[$name] = $package;
        }
        do {
            $changed = \false;
            foreach ($byName as $name => $package) {
                $parentConfigs = $package['phabelConfig'];
                foreach ($package['require'] ?? [] as $subName => $constraint) {
                    if (PlatformRepository::isPlatformPackage($subName)) {
                        continue;
                    }
                    [$subName, $target] = $this->extractTarget($subName);
                    if ($target === Php::TARGET_IGNORE) {
                        continue;
                    }
                    foreach ($parentConfigs as $config) {
                        if (!\in_array($config, $byName[$subName]['phabelConfig'])) {
                            $byName[$subName]['phabelConfig'][] = $config;
                            $changed = \true;
                        }
                    }
                }
            }
        } while ($changed);
        $graph = new Graph();
        foreach ($byName as $name => $package) {
            $ctx = $graph->getPackageContext();
            $ctx->addPackage($name);
            $target = ['target' => $package['phabelTarget']];
            foreach ($package['phabelConfig'] as $config) {
                $graph->addPlugin(Php::class, $config + $target, $ctx);
            }
        }
        $traverser = new Traverser(new \Phabel\Composer\EventHandler($this->io, $this->doProgress && $this->io instanceof ConsoleIO && !\getenv('CI') && !$this->io->isDebug() ? fn(int $progress) => $this->io->getProgressBar($progress) : null));
        $traverser->setPluginGraph($graph);
        unset($graph);
        static $lastTry;
        $this->requires = $traverser->getGraph()->getPackages();
        unset($this->requires['phabel/phabel']);
        if (!$this->processedRequires() && $lastTry !== $this->requires) {
            $lastTry = $this->requires;
            if (!$enabled) {
                unset($traverser);
                while (\gc_collect_cycles()) {
                }
                \gc_disable();
            }
            return \true;
        }
        if ($lock && $lock === $old) {
            return $missingDeps;
        }
        if (!$byName) {
            return $missingDeps;
        }
        $this->banner();
        $traverser->setComposerPaths($paths)->run((int) (\getenv('PHABEL_PARALLEL') ?: 1));
        foreach ($paths as [$old, $new]) {
            Tools::traverseCopy($new, $old);
        }
        if (!$enabled) {
            unset($traverser);
            while (\gc_collect_cycles()) {
            }
            \gc_disable();
        }
        return $missingDeps;
    }
    /**
     * Get whether we processed any dependencies.
     *
     * @return bool
     */
    public function processedRequires() : bool
    {
        return $this->processed && $this->processedRequires === $this->requires;
    }
    /**
     * Get IO interface.
     *
     * @return IOInterface
     */
    public function getIo() : IOInterface
    {
        return $this->io;
    }
}
<?php

namespace Phabel\PluginGraph;

use Phabel\Plugin;
use Phabel\PluginInterface;
/**
 * Graph API wrapper.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Graph
{
    /**
     * Graph instance.
     */
    private ?\Phabel\PluginGraph\GraphInternal $graph = null;
    /**
     * Resolved graph instance.
     */
    private ?\Phabel\PluginGraph\ResolvedGraph $resolvedGraph = null;
    /**
     * Constructr.
     */
    public function __construct()
    {
        $this->graph = new \Phabel\PluginGraph\GraphInternal();
    }
    /**
     * Get new package context.
     *
     * @return PackageContext
     */
    public function getPackageContext() : \Phabel\PluginGraph\PackageContext
    {
        return $this->graph->getPackageContext();
    }
    /**
     * Add plugin.
     *
     * @param string $plugin Plugin to add
     * @param array $config Plugin configuration
     * @param PackageContext $ctx Package context
     *
     * @psalm-param class-string<PluginInterface> $plugin Plugin name
     *
     * @return Node[]
     */
    public function addPlugin(string $plugin, array $config, \Phabel\PluginGraph\PackageContext $ctx) : array
    {
        return $this->graph->addPlugin($plugin, $config, $ctx);
    }
    /**
     * Flatten graph.
     *
     * @return ResolvedGraph
     */
    public function flatten() : \Phabel\PluginGraph\ResolvedGraph
    {
        $this->resolvedGraph ??= new \Phabel\PluginGraph\ResolvedGraph(...$this->graph->flatten());
        $this->graph = null;
        while (\gc_collect_cycles()) {
        }
        return $this->resolvedGraph;
    }
}
<?php

namespace Phabel\PluginGraph;

use Phabel\PluginInterface;
/**
 * Circular reference in plugin graph.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class CircularException extends \Exception
{
    /**
     * Plugin array.
     *
     * @var class-string<PluginInterface>[]
     */
    private array $plugins = [];
    /**
     * Constructor.
     *
     * @param class-string<PluginInterface>[] $plugins Plugin array
     * @param \Throwable $previous Previous exception
     */
    public function __construct(array $plugins, \Throwable $previous = null)
    {
        $this->plugins = $plugins;
        parent::__construct("Detected circular reference: " . \implode(" => ", $plugins), 0, $previous);
    }
    /**
     * Get plugins.
     *
     * @return class-string<PluginInterface>[]
     */
    public function getPlugins() : array
    {
        return $this->plugins;
    }
}
<?php

namespace Phabel\PluginGraph;

use Phabel\PluginCache;
use Phabel\PluginInterface;
use SplQueue;
/**
 * Representation of multiple plugins+configs.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Plugins
{
    /**
     * Plugin configs, indexed by plugin name.
     *
     * @var array<class-string<PluginInterface>, array[]>
     */
    public array $plugins = [];
    /**
     * Constructor.
     *
     * @param class-string<PluginInterface> $plugin Plugin
     * @param array $config Config
     */
    public function __construct(string $plugin, array $config)
    {
        $this->plugins[$plugin] = [$config];
    }
    /**
     * Merge with other plugins.
     *
     * @param self $other Plugins
     *
     * @return void
     */
    public function merge(self $other) : void
    {
        foreach ($other->plugins as $plugin => $configs) {
            if (isset($this->plugins[$plugin])) {
                $this->plugins[$plugin] = \array_merge($this->plugins[$plugin], $configs);
            } else {
                $this->plugins[$plugin] = $configs;
            }
        }
    }
    /**
     * Enqueue plugins.
     *
     * @param SplQueue<PluginInterface> $queue
     *
     * @return void
     */
    public function enqueue(SplQueue $queue, \Phabel\PluginGraph\PackageContext $ctx, array &$packages) : void
    {
        foreach ($this->plugins as $plugin => $configs) {
            foreach ($plugin::mergeConfigs(...$configs) as $config) {
                foreach ($plugin::getComposerRequires($config) as $package => $constraint) {
                    $packages[$package] ??= [];
                    $packages[$package][] = $constraint;
                }
                if (PluginCache::isEmpty($plugin)) {
                    continue;
                }
                $pluginObj = new $plugin();
                $pluginObj->setConfigArray($config);
                $pluginObj->setPackageContext($ctx);
                $queue->enqueue($pluginObj);
            }
        }
    }
}
<?php

namespace Phabel\PluginGraph;

use Phabel\Exception;
use Phabel\Plugin\ClassStoragePlugin;
use Phabel\PluginInterface;
use SplQueue;
/**
 * Resolved graph.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
final class ResolvedGraph
{
    /**
     * Plugins.
     *
     * @psalm-var SplQueue<SplQueue<PluginInterface>>
     */
    private SplQueue $plugins;
    /**
     * Packages.
     *
     * @var array<string, string>
     */
    private array $packages = [];
    /**
     * Class storage.
     */
    private ?ClassStoragePlugin $classStorage = null;
    /**
     * Constructor.
     *
     * @param SplQueue<SplQueue<PluginInterface>> $plugins Resolved plugins
     * @param array<string, list<string>> $packages
     */
    public function __construct(SplQueue $plugins, array $packages = [])
    {
        $this->packages = \array_map(fn(array $constraints): string => \implode(':', \array_unique($constraints)), $packages);
        $this->plugins = new SplQueue();
        foreach ($plugins as $queue) {
            $newQueue = new SplQueue();
            foreach ($queue as $plugin) {
                if ($plugin instanceof ClassStoragePlugin) {
                    if ($this->classStorage) {
                        $config = $this->classStorage->mergeConfigs($this->classStorage->getConfigArray(), $plugin->getConfigArray());
                        if (\count($config) !== 1) {
                            throw new Exception('Could not merge class storage config!');
                        }
                        $this->classStorage->setConfigArray($config[0]);
                        continue;
                    }
                    $this->classStorage = $plugin;
                }
                $newQueue->enqueue($plugin);
            }
            if ($newQueue->count()) {
                $this->plugins->enqueue($newQueue);
            }
        }
    }
    /**
     * Get plugins.
     *
     * @return SplQueue
     * @psalm-return SplQueue<SplQueue<PluginInterface>>
     */
    public function getPlugins() : SplQueue
    {
        return $this->plugins;
    }
    /**
     * Get packages.
     *
     * @return array
     * @psalm-return array<string, string>
     */
    public function getPackages() : array
    {
        return $this->packages;
    }
    /**
     * Get class storage.
     *
     * @return ?ClassStoragePlugin
     */
    public function getClassStorage() : ?ClassStoragePlugin
    {
        return $this->classStorage;
    }
    /**
     * Returns graph debug information.
     *
     * @return array
     */
    public function __debugInfo() : array
    {
        $res = [];
        foreach ($this->plugins as $queue) {
            $cur = [];
            foreach ($queue as $plugin) {
                $cur[] = \basename(\str_replace('\\', '/', \get_class($plugin)));
                //[\get_class($plugin), $plugin->getConfigArray()];
            }
            $res[] = $cur;
        }
        return $res;
    }
}
<?php

namespace Phabel\PluginGraph;

use Phabel\Exception;
use Phabel\PluginCache;
use Phabel\PluginInterface;
use SplObjectStorage;
use SplQueue;
/**
 * Represents a plugin with a certain configuration.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Node
{
    /**
     * Plugins and configs.
     *
     * @var Plugins
     */
    public \Phabel\PluginGraph\Plugins $plugin;
    /**
     * Original plugin name.
     *
     * @var class-string<PluginInterface>
     */
    private string $name;
    /**
     * Original plugin name.
     *
     * @var class-string<PluginInterface>
     */
    private string $nameConcat;
    /**
     * Associated package context.
     *
     * @var PackageContext
     */
    private \Phabel\PluginGraph\PackageContext $packageContext;
    /**
     * Nodes that this node requires.
     *
     * @var SplObjectStorage<Node, null>
     */
    private SplObjectStorage $requires;
    /**
     * Nodes that this node extends.
     *
     * @var SplObjectStorage<Node, null>
     */
    private SplObjectStorage $extends;
    /**
     * Nodes that require this node.
     *
     * @var SplObjectStorage<Node, null>
     */
    private SplObjectStorage $requiredBy;
    /**
     * Nodes that extend this node.
     *
     * @var SplObjectStorage<Node, null>
     */
    private SplObjectStorage $extendedBy;
    /**
     * Graph instance.
     */
    private \Phabel\PluginGraph\GraphInternal $graph;
    /**
     * Whether this node was visited when looking for circular requirements.
     */
    private bool $visitedCircular = \false;
    /**
     * Whether this node can be required, or only extended.
     */
    private bool $canBeRequired = \true;
    /**
     * Constructor.
     *
     * @param GraphInternal $graph Graph instance
     */
    public function __construct(\Phabel\PluginGraph\GraphInternal $graph, \Phabel\PluginGraph\PackageContext $ctx)
    {
        $this->packageContext = $ctx;
        $this->graph = $graph;
        $this->requiredBy = new SplObjectStorage();
        $this->extendedBy = new SplObjectStorage();
        $this->requires = new SplObjectStorage();
        $this->extends = new SplObjectStorage();
    }
    /**
     * Initialization function.
     *
     * @param string $plugin Plugin name
     * @param array $config Plugin configuration
     * @param PackageContext $ctx Context
     *
     * @psalm-param class-string<PluginInterface> $plugin Plugin name
     *
     * @return self
     */
    public function init(string $plugin, array $pluginConfig) : self
    {
        $this->name = $plugin;
        $this->plugin = new \Phabel\PluginGraph\Plugins($plugin, $pluginConfig);
        $this->canBeRequired = PluginCache::canBeRequired($plugin);
        foreach (PluginCache::next($plugin, $pluginConfig) as $class => $config) {
            foreach ($this->graph->addPlugin($class, $config, $this->packageContext) as $node) {
                $node->require($this);
            }
        }
        foreach (PluginCache::previous($plugin, $pluginConfig) as $class => $config) {
            foreach ($this->graph->addPlugin($class, $config, $this->packageContext) as $node) {
                $this->require($node);
            }
        }
        foreach (PluginCache::withNext($plugin, $pluginConfig) as $class => $config) {
            foreach ($this->graph->addPlugin($class, $config, $this->packageContext) as $node) {
                $node->extend($this);
            }
        }
        foreach (PluginCache::withPrevious($plugin, $pluginConfig) as $class => $config) {
            foreach ($this->graph->addPlugin($class, $config, $this->packageContext) as $node) {
                $this->extend($node);
            }
        }
        return $this;
    }
    /**
     * Make node require another node.
     *
     * @param self $node Node
     *
     * @return void
     */
    private function require(self $node) : void
    {
        if (!$node->canBeRequired) {
            $this->extend($node);
            return;
        }
        if ($this->extends->contains($node) || $node->extendedBy->contains($this)) {
            $this->extends->detach($node);
            $node->extendedBy->detach($this);
        }
        $this->requires->attach($node);
        $node->requiredBy->attach($this);
        $this->graph->linkNode($this);
    }
    /**
     * Make node extend another node.
     *
     * @param self $node Node
     *
     * @return void
     */
    private function extend(self $node) : void
    {
        if ($this->requires->contains($node) || $node->requiredBy->contains($this)) {
            return;
        }
        $this->extends->attach($node);
        $node->extendedBy->attach($this);
        $this->graph->linkNode($this);
    }
    /**
     * Merge node with another node.
     *
     * @param self $other Other node
     *
     * @return Node
     */
    public function merge(self $other) : \Phabel\PluginGraph\Node
    {
        if ($other->requires->count() || $other->extends->count()) {
            throw new Exception('Cannot merge a node that requires other nodes!');
        }
        $this->packageContext->merge($other->packageContext);
        $this->plugin->merge($other->plugin);
        foreach ($other->requiredBy as $that) {
            $that->require($this);
            $that->requires->detach($other);
        }
        foreach ($other->extendedBy as $that) {
            $that->extend($this);
            $that->extends->detach($other);
        }
        $other->requiredBy = new SplObjectStorage();
        $other->extendedBy = new SplObjectStorage();
        $this->graph->unprocessedNode->detach($other);
        return $this;
    }
    /**
     * Look for circular references, while merging package contexts.
     *
     * @return self
     */
    public function circular() : self
    {
        if ($this->visitedCircular) {
            $plugins = [$this->name];
            foreach (\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS, \DEBUG_BACKTRACE_PROVIDE_OBJECT) as $frame) {
                $plugins[] = $frame['object']->name;
                if ($frame['object'] === $this) {
                    break;
                }
            }
            throw new \Phabel\PluginGraph\CircularException($plugins);
        }
        $this->visitedCircular = \true;
        foreach ($this->requiredBy as $that) {
            $this->packageContext->merge($that->circular()->packageContext);
        }
        foreach ($this->extendedBy as $that) {
            $this->packageContext->merge($that->circular()->packageContext);
        }
        $this->visitedCircular = \false;
        return $this;
    }
    /**
     * Flatten tree.
     *
     * @return array{0: SplQueue<SplQueue<PluginInterface>>, array<string, list<string>>}
     */
    public function flatten() : array
    {
        /** @var SplQueue<PluginInterface> */
        $initQueue = new SplQueue();
        /** @var SplQueue<SplQueue<PluginInterface>> */
        $queue = new SplQueue();
        $queue->enqueue($initQueue);
        $packages = [];
        $this->flattenInternal($queue, $packages);
        if ($this->extendedBy->count() || $this->requiredBy->count()) {
            throw new Exception('Graph resolution has stalled');
        }
        return [$queue, $packages];
    }
    /**
     * Internal flattening.
     *
     * @param SplQueue<SplQueue<PluginInterface>> $queueOfQueues Queue
     *
     * @return void
     */
    private function flattenInternal(SplQueue $queueOfQueues, array &$packages) : void
    {
        $queue = $queueOfQueues->top();
        $this->plugin->enqueue($queue, $this->packageContext, $packages);
        $this->graph->unprocessedNode->detach($this);
        do {
            $processedAny = \false;
            $prevNode = null;
            $toDetach = new SplQueue();
            foreach ($this->extendedBy as $node) {
                $node->extends->detach($this);
                if (\count($node->requires) + \count($node->extends) === 0) {
                    if ($prevNode instanceof self) {
                        $prevNode->merge($node);
                        $toDetach->enqueue($node);
                    } else {
                        $prevNode = $node;
                    }
                }
            }
            foreach ($toDetach as $node) {
                $this->extendedBy->detach($node);
                $this->graph->unprocessedNode->detach($node);
            }
            $prevNode = null;
            $toDetach = new SplQueue();
            foreach ($this->requiredBy as $node) {
                $node->requires->detach($this);
                if (\count($node->requires) + \count($node->extends) === 0) {
                    if ($prevNode instanceof self) {
                        $prevNode->merge($node);
                        $toDetach->enqueue($node);
                    } else {
                        $prevNode = $node;
                    }
                }
            }
            foreach ($toDetach as $node) {
                $this->requiredBy->detach($node);
                $this->graph->unprocessedNode->detach($node);
            }
            $toDetach = new SplQueue();
            foreach ($this->extendedBy as $node) {
                if (\count($node->extends) + \count($node->requires) === 0) {
                    $toDetach->enqueue($node);
                    $node->flattenInternal($queueOfQueues, $packages);
                    $processedAny = \true;
                }
            }
            foreach ($toDetach as $node) {
                $this->extendedBy->detach($node);
            }
            $toDetach = new SplQueue();
            foreach ($this->requiredBy as $node) {
                if (\count($node->extends) + \count($node->requires) === 0) {
                    $toDetach->enqueue($node);
                    if (!$queue->isEmpty()) {
                        $queueOfQueues->enqueue(new SplQueue());
                    }
                    $node->flattenInternal($queueOfQueues, $packages);
                    $processedAny = \true;
                }
            }
            foreach ($toDetach as $node) {
                $this->requiredBy->detach($node);
            }
        } while ($processedAny);
    }
    /**
     * Add packages from package context.
     *
     * @param PackageContext $ctx Package context
     *
     * @return self
     */
    public function addPackages(\Phabel\PluginGraph\PackageContext $ctx) : self
    {
        $this->packageContext->merge($ctx);
        return $this;
    }
}
<?php

namespace Phabel\PluginGraph;

/**
 * List of packages associated with plugin.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class PackageContext
{
    /**
     * Package list.
     *
     * @var array<string, null>
     */
    private array $packages = [];
    /**
     * Add package.
     *
     * @param string $package Package
     *
     * @return void
     */
    public function addPackage(string $package) : void
    {
        $this->packages[$package] = \true;
    }
    /**
     * Merge two contexts.
     *
     * @param self $other Other context
     *
     * @return self New context
     */
    public function merge(self $other) : self
    {
        $this->packages += $other->packages;
        return $this;
    }
    /**
     * Check if a package is present in the package context.
     *
     * @param string $package Package
     *
     * @return boolean
     */
    public function has(string $package) : bool
    {
        return isset($this->packages[$package]);
    }
    /**
     * Get package list.
     *
     * @return array
     */
    public function getPackages() : array
    {
        return \array_values($this->packages);
    }
}
<?php

namespace Phabel\PluginGraph;

use Exception;
use Phabel\Plugin;
use Phabel\PluginInterface;
use SplObjectStorage;
use SplQueue;
/**
 * Internal graph class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class GraphInternal
{
    /**
     * Plugin nodes, indexed by plugin name+config.
     *
     * @var array<class-string<PluginInterface>, array<string, Node>>
     */
    private array $plugins = [];
    /**
     * Package contexts.
     *
     * @var PackageContext[]
     */
    private array $packageContexts = [];
    /**
     * Stores list of Nodes that are not required by any other node.
     *
     * @var SplObjectStorage<Node, null>
     */
    private SplObjectStorage $unlinkedNodes;
    /**
     * Stores list of Nodes that weren't yet processed.
     *
     * @var SplObjectStorage<Node, null>
     */
    public SplObjectStorage $unprocessedNode;
    /**
     * Constructor.
     */
    public function __construct()
    {
        $this->unlinkedNodes = new SplObjectStorage();
        $this->unprocessedNode = new SplObjectStorage();
    }
    /**
     * Get new package context.
     */
    public function getPackageContext() : \Phabel\PluginGraph\PackageContext
    {
        $packageContext = new \Phabel\PluginGraph\PackageContext();
        $this->packageContexts[] = $packageContext;
        return $packageContext;
    }
    /**
     * Add plugin.
     *
     * @param string $plugin Plugin to add
     * @param array $config Plugin configuration
     * @param PackageContext $ctx Package context
     *
     * @psalm-param class-string<PluginInterface> $plugin Plugin to add
     *
     * @return Node[]
     */
    public function addPlugin(string $plugin, array $config, \Phabel\PluginGraph\PackageContext $ctx) : array
    {
        return \array_map(fn(array $config): \Phabel\PluginGraph\Node => $this->addPluginInternal($plugin, $config, $ctx), $plugin::splitConfig($config));
    }
    /**
     * Add plugin.
     *
     * @param string $plugin Plugin to add
     * @param array $config Plugin configuration
     * @param PackageContext $ctx Package context
     *
     * @psalm-param class-string<PluginInterface> $plugin Plugin name
     */
    private function addPluginInternal(string $plugin, array $config, \Phabel\PluginGraph\PackageContext $ctx) : \Phabel\PluginGraph\Node
    {
        $configStr = \json_encode($config);
        if (isset($this->plugins[$plugin][$configStr])) {
            return $this->plugins[$plugin][$configStr]->addPackages($ctx);
        }
        $this->plugins[$plugin][$configStr] = $node = new \Phabel\PluginGraph\Node($this, $ctx);
        $this->unlinkedNodes->attach($node);
        $this->unprocessedNode->attach($node);
        return $node->init($plugin, $config);
    }
    /**
     * Set unlinked node as linked.
     */
    public function linkNode(\Phabel\PluginGraph\Node $node) : void
    {
        if ($this->unlinkedNodes->contains($node)) {
            $this->unlinkedNodes->detach($node);
        }
    }
    /**
     * Flatten graph.
     *
     * @return array{0: SplQueue<SplQueue<PluginInterface>>, 1: array<string, list<string>>}
     */
    public function flatten() : array
    {
        if (!$this->plugins) {
            /** @psalm-var SplQueue<SplQueue<PluginInterface>> */
            return [new SplQueue(), []];
        }
        if ($this->unlinkedNodes->count()) {
            /** @var Node|null $initNode */
            $initNode = null;
            foreach ($this->unlinkedNodes as $node) {
                if ($initNode) {
                    $node = $initNode->merge($node);
                }
                /** @var Node */
                $initNode = $node;
            }
            $this->unlinkedNodes = new SplObjectStorage();
            $this->unlinkedNodes->attach($initNode);
            $this->unprocessedNode->attach($initNode);
            $result = $initNode->circular()->flatten();
        } else {
            $result = \array_values(\array_values($this->plugins)[0])[0]->circular()->flatten();
        }
        if ($this->unprocessedNode->count()) {
            throw new Exception('Did not process entire graph!');
        }
        return $result;
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * Remove void return typehint.
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class VoidReturnType extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['void' => \true]];
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use Phabel\Plugin\ListSplitter;
/**
 * Polyfills keyed list assignment.
 */
class ListKey extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [ListSplitter::class => ['key' => \true]];
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
class IssetExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Stmt\TryCatch;
/**
 * Replace compound catches.
 */
class MultipleCatchReplacer extends Plugin
{
    /**
     * Replace compound catches.
     *
     * Do this while leaving to avoid re-iterating uselessly on duplicated code.
     *
     * @param TryCatch $node Catch stmt
     *
     * @return void
     */
    public function leave(TryCatch $node) : void
    {
        $catches = [];
        foreach ($node->catches as $catch) {
            if (\count($catch->types) === 1) {
                $catches[] = $catch;
            } else {
                foreach ($catch->types as $type) {
                    $ncatch = clone $catch;
                    $ncatch->types = [$type];
                    $catches[] = $ncatch;
                }
            }
        }
        $node->catches = $catches;
    }
}
<?php

namespace Phabel\Target\Php71;

use Closure;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Name;
use ReflectionClass;
use ReflectionFunction;
/**
 * Polyfills Closure::fromCallable.
 */
class ClosureFromCallable extends Plugin
{
    /**
     *
     */
    public function enter(StaticCall $staticCall) : ?StaticCall
    {
        if (!$staticCall->class instanceof Name || self::getFqdn($staticCall->class) !== Closure::class) {
            return null;
        }
        if ($staticCall->name instanceof Expr) {
            return self::callPoly('proxy', $staticCall->name, ...$staticCall->args);
        } elseif (\strtolower($staticCall->name->name) === 'fromcallable') {
            return self::callPoly('fromCallable', $staticCall->args[0]);
        }
        return null;
    }
    /**
     *
     */
    public static function proxy(string $method, ...$args)
    {
        if (\strtolower($method) === 'fromcallable') {
            return self::fromCallable($args[0]);
        }
        return Closure::$method(...$args);
    }
    /**
     * Create closure from callable.
     *
     * @param callable $callable
     * @return Closure
     */
    public static function fromCallable($callable) : Closure
    {
        if ($callable instanceof Closure) {
            return $callable;
        }
        if (\is_object($callable)) {
            $callable = [$callable, '__invoke'];
        }
        if (\is_array($callable)) {
            $method = (new ReflectionClass($callable[0]))->getMethod($callable[1]);
            return \is_string($callable[0]) ? $method->getClosure() : $method->getClosure($callable[0]);
        }
        return (new ReflectionFunction($callable))->getClosure();
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * Remove nullable typehint.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class NullableType extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['nullable' => \true]];
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
class NestedExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Stmt\ClassConst;
/**
 * Removes the class constant visibility modifiers (PHP 7.1).
 */
class ClassConstantVisibilityModifiersRemover extends Plugin
{
    /**
     * Makes public private and protected class constants.
     *
     * @param ClassConst $node Constant
     *
     * @return void
     */
    public function enter(ClassConst $node) : void
    {
        $node->flags = 0;
        // Remove constant modifier
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use Phabel\Target\Polyfill as TargetPolyfill;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Polyfill extends Plugin
{
    // Todo: getopt
    // Todo: DateInterval, DateTime, DateTimeZone, IntlDateFormatter
    // Todo: filters
    // Todo: hashes w/ phpseclib
    // Todo: mb_ereg functions
    // Todo: grapheme_extract
    // Todo: getenv
    // Skip: output buffer functions
    /**
     * @return (array | bool)
     */
    public static function unpack(string $format, string $string, int $offset = 0)
    {
        $phabelReturn = \unpack($format, \Phabel\Target\Php80\Polyfill::substr($string, $offset));
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_array($phabelReturn)) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type array|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | bool)
     */
    public static function long2ip(int $ip)
    {
        $phabelReturn = \long2ip($ip);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | false)
     */
    public static function file_get_contents(...$params)
    {
        if (isset($params[3]) && $params[3] < 0) {
            $f = \fopen($params[0], 'r', $params[1], $params[2]);
            \fseek($f, 0, \SEEK_END);
            \fseek($f, \ftell($f) + $params[3], \SEEK_SET);
            $length = $params[4] ?? null;
            if ($length === null) {
                $phabelReturn = \stream_get_contents($f);
                if (!($phabelReturn === \false)) {
                    if (!\is_string($phabelReturn)) {
                        if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                            throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                        }
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
                return $phabelReturn;
            }
            $phabelReturn = \fread($f, $length);
            if (!($phabelReturn === \false)) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            }
            return $phabelReturn;
        }
        $phabelReturn = \file_get_contents(...$params);
        if (!($phabelReturn === \false)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type false|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                $phabelReturn = (string) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (array | false)
     */
    public static function get_headers(string $url, int $associative = 0, $context = null)
    {
        if (!$context) {
            $phabelReturn = \get_headers($url, $associative);
            if (!(\is_array($phabelReturn) || $phabelReturn === \false)) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        if (\file_get_contents($url, \false, $context) === \false) {
            $phabelReturn = \false;
            if (!(\is_array($phabelReturn) || $phabelReturn === \false)) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        if (!$associative) {
            $phabelReturn = $http_response_header;
            if (!(\is_array($phabelReturn) || $phabelReturn === \false)) {
                throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
            }
            return $phabelReturn;
        }
        $headers = [$http_response_header[0]];
        foreach ($http_response_header as $i => $header) {
            if ($i) {
                [$k, $v] = \explode(":", $header, 2);
                $headers[\trim($k, ' ')] = \trim($v, ' ');
            }
        }
        $phabelReturn = $headers;
        if (!(\is_array($phabelReturn) || $phabelReturn === \false)) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function substr_count(string $haystack, string $needle, int $offset = 0, ?int $length = null) : int
    {
        if ($offset < 0) {
            $offset = \strlen($haystack) + $offset;
        }
        if ($length === null) {
            return \Phabel\Target\Php80\Polyfill::substr_count($haystack, $needle, $offset);
        }
        if ($length === 0) {
            return \Phabel\Target\Php80\Polyfill::substr_count($haystack, $needle, $offset);
        }
        if ($length < 0) {
            $length = \strlen($haystack) - $length;
        }
        return \Phabel\Target\Php80\Polyfill::substr_count($haystack, $needle, $offset);
    }
    /**
     * @return (int | bool)
     */
    public static function strpos(string $haystack, string $needle, int $offset = 0)
    {
        $phabelReturn = \strpos($haystack, $needle, $offset < 0 ? \strlen($haystack) + $offset : $offset);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function stripos(string $haystack, string $needle, int $offset = 0)
    {
        $phabelReturn = \stripos($haystack, $needle, $offset < 0 ? \strlen($haystack) + $offset : $offset);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function mb_strpos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null)
    {
        $encoding ??= \mb_internal_encoding();
        $phabelReturn = \mb_strpos($haystack, $needle, $offset < 0 ? \mb_strlen($haystack, $encoding) + $offset : $offset, $encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function mb_stripos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null)
    {
        $encoding ??= \mb_internal_encoding();
        $phabelReturn = \mb_stripos($haystack, $needle, $offset < 0 ? \mb_strlen($haystack, $encoding) + $offset : $offset, $encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function mb_strimwidth(string $string, int $start, int $width, string $trim_marker = "", ?string $encoding = null) : string
    {
        $encoding ??= \mb_internal_encoding();
        if ($start < 0) {
            $start = \mb_strlen($string, $encoding) + $start;
        } elseif ($width < 0) {
            $width = \mb_strlen($string, $encoding) + $width;
        }
        return \mb_strimwidth($string, $start, $width, $trim_marker, $encoding);
    }
    /**
     * @return (int | bool)
     */
    public static function iconv_strpos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null)
    {
        $encoding ??= \iconv_get_encoding('internal_encoding');
        $phabelReturn = \Phabel\Target\Php80\Polyfill::iconv_strpos($haystack, $needle, $offset < 0 ? \Phabel\Target\Php80\Polyfill::iconv_strlen($haystack, $encoding) + $offset : $offset, $encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function grapheme_strpos(string $haystack, string $needle, int $offset = 0)
    {
        $phabelReturn = \grapheme_strpos($haystack, $needle, $offset < 0 ? \grapheme_strlen($haystack) + $offset : $offset);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function grapheme_stripos(string $haystack, string $needle, int $offset = 0)
    {
        $phabelReturn = \grapheme_stripos($haystack, $needle, $offset < 0 ? \grapheme_strlen($haystack) + $offset : $offset);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * {@inheritDoc}
     */
    public static function withNext(array $config) : array
    {
        return [TargetPolyfill::class => [self::class => \true]];
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use Phabel\Plugin\ListSplitter;
/**
 * Polyfills list expression return value.
 */
class ListExpression extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [ListSplitter::class => ['parentExpr' => \true]];
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr\Array_;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\List_;
use PhabelVendor\PhpParser\Node\Stmt\Foreach_;
/**
 * Replaces [] array list syntax.
 */
class ArrayList extends Plugin
{
    /**
     * Called when entering Foreach_ node.
     *
     * @param Foreach_ $node Node
     *
     * @return void
     */
    public function enterForeach(Foreach_ $node) : void
    {
        if ($node->valueVar instanceof Array_) {
            self::replaceTypeInPlace($node->valueVar, List_::class);
        }
    }
    /**
     * Called when entering list for nested lists.
     *
     * @param List_ $node Node
     *
     * @return void
     */
    public function enterList(List_ $node) : void
    {
        foreach ($node->items as $item) {
            if ($item && $item->value instanceof Array_) {
                self::replaceTypeInPlace($item->value, List_::class);
            }
        }
    }
    /**
     * Parse [] list assignment.
     *
     * @param Assign $node List assignment
     *
     * @return void
     */
    public function enterAssign(Assign $node) : void
    {
        if ($node->var instanceof Array_) {
            $node->var = new List_($node->var->items);
        }
    }
}
<?php

namespace Phabel\Target\Php71;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class IterableHint extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['types' => ['iterable']]];
    }
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Plugin;
use Phabel\Plugin\ClassStoragePlugin;
use Phabel\Target\Php74\TypeContracovariance\TypeContracovariance as T;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class TypeContracovariance extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [ClassStoragePlugin::class => [T::class => \true]];
    }
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Plugin;
class IssetExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr\Array_;
use PhabelVendor\PhpParser\Node\Expr\ArrayItem;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Expr\List_;
use PhabelVendor\PhpParser\Node\Stmt\Foreach_;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class ArrayUnpack extends Plugin
{
    /**
     *
     */
    public function enter(Array_ $array, Context $context) : ?FuncCall
    {
        foreach ($context->parents as $parent) {
            if ($parent instanceof Array_) {
                continue;
            }
            if ($parent instanceof List_) {
                return null;
            }
            /** @var string */
            $key = $parent->getAttribute('currentNode');
            if ($parent instanceof Assign && $key === 'var') {
                return null;
            }
            if ($parent instanceof Foreach_ && $key === 'valueVar') {
                return null;
            }
            break;
        }
        $hasUnpack = \false;
        foreach ($array->items as $item) {
            if (!$item) {
                return null;
            }
            if ($item->unpack) {
                $hasUnpack = \true;
                break;
            }
        }
        if (!$hasUnpack) {
            return null;
        }
        $args = [];
        $current = new Array_();
        /** @var ArrayItem */
        foreach ($array->items as $item) {
            if ($item->unpack) {
                if ($current->items) {
                    $args[] = new Arg($current);
                    $current = new Array_();
                }
                $args[] = new Arg($item->value);
            } else {
                $current->items[] = $item;
            }
        }
        if ($current->items) {
            $args[] = new Arg($current);
        }
        return Plugin::call("array_merge", ...$args);
    }
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Plugin;
class NestedExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Stmt\Class_;
use PhabelVendor\PhpParser\Node\Stmt\ClassMethod;
use Serializable as GlobalSerializable;
/**
 * Implement __serialize and __unserialize.
 */
class Serializable extends Plugin
{
    /*
                public function enter(Class_ $class, Context $context): void
                {
                    /** @var array<string, &ClassMethod> */
    /*
                    $methods = [];
                    foreach ($class->stmts as $stmt) {
                        if ($stmt instanceof ClassMethod) {
                            $name = $stmt->name->toLowerString();
                            $methods[$name] = $stmt;
                        }
                    }
    
                    if (!isset($methods['__serialize']) && !isset($methods['__unserialize'])) {
                        return;
                    }
                    foreach ($class->implements as $name) {
                        $resolved = $context->getNameContext()->getResolvedClassName($name);
                        if ($resolved->toLowerString() === 'serializable' || $name->toLowerString() === 'serializable') {
                            return; // Already implements
                        }
                    }
                    if (isset($methods['__sleep'])) {
                        $methods['__sleep']->name = new Identifier('__phabelSleep');
                    }
                    if (isset($methods['__wakeup'])) {
                        $methods['__wakeup']->name = new Identifier('__phabelWakeup');
                    }
    
                    $class->implements []= new FullyQualified(GlobalSerializable::class);
                }*/
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Plugin;
use Phabel\Target\Polyfill as TargetPolyfill;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Polyfill extends Plugin
{
    // Todo: gmmktime, mktime
    /**
     *
     */
    public static function array_filter(array $array, ?callable $callback = null, int $mode = 0) : array
    {
        $callback ??= fn($v) => $v;
        return \array_filter($array, $callback, $mode);
    }
    /**
     * @param mixed $replacement
     */
    public static function array_splice(array &$array, int $offset, ?int $length = null, $replacement = []) : array
    {
        if (!\true) {
            throw new \TypeError(__METHOD__ . '(): Argument #4 ($replacement) must be of type mixed, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($replacement) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        $length ??= \max(\count($array) - $offset, 0);
        return \array_splice($array, $offset, $length, $replacement);
    }
    /**
     * {@inheritDoc}
     */
    public static function withNext(array $config) : array
    {
        return [TargetPolyfill::class => [self::class => \true]];
    }
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * Implement typed properties.
 */
class TypedProperty extends Plugin
{
    /**
     * {@inheritDoc}
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['property' => \true]];
    }
}
<?php

namespace Phabel\Target\Php74\TypeContracovariance;

use Phabel\ClassStorage;
use Phabel\ClassStorage\Storage;
use Phabel\ClassStorageProvider;
use Phabel\Plugin\TypeHintReplacer;
use SplStack;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class TypeContracovariance extends ClassStorageProvider
{
    /**
     *
     */
    public static function processClassGraph(ClassStorage $storage) : bool
    {
        $changed = \false;
        foreach ($storage->getClasses() as $class) {
            // Contravariance: a parameter type can be less specific (more types) in a child method
            // Covariance: a child method can return a more specific (less types) type
            foreach ($class->getMethods() as $name => $method) {
                $actReturn = \false;
                $act = \array_fill(0, \count($method->params), \false);
                $parentMethods = new SplStack();
                $parentMethods->push($method);
                foreach ($class->getOverriddenMethods($name) as $childMethod) {
                    $childClass = $childMethod->getAttribute(Storage::STORAGE_KEY);
                    foreach ($childMethod->params as $k => $param) {
                        if (isset($method->params[$k]) && $storage->compare($param->type, $method->params[$k]->type, $childClass, $class) > 0) {
                            $act[$k] = \true;
                        }
                    }
                    if ($storage->compare($childMethod->returnType, $method->returnType, $childClass, $class) < 0) {
                        $actReturn = \true;
                    }
                    $parentMethods->push($childMethod);
                }
                $act = \array_keys(\array_filter($act));
                if (!$act && !$actReturn) {
                    continue;
                }
                foreach ($parentMethods as $method) {
                    foreach ($act as $k) {
                        if (isset($method->params[$k])) {
                            $changed = TypeHintReplacer::replace($method->params[$k]->type) || $changed;
                        }
                    }
                    if ($actReturn) {
                        $changed = TypeHintReplacer::replace($method->returnType) || $changed;
                    }
                }
            }
        }
        return $changed;
    }
    /**
     * {@inheritDoc}
     */
    public static function next(array $config) : array
    {
        return [TypeHintReplacer::class];
    }
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Context;
use Phabel\Plugin;
use Phabel\Plugin\VariableFinder;
use PhabelVendor\PhpParser\Node\Expr\ArrowFunction;
use PhabelVendor\PhpParser\Node\Expr\Closure;
use PhabelVendor\PhpParser\Node\Expr\Variable;
use PhabelVendor\PhpParser\Node\Param;
use PhabelVendor\PhpParser\Node\Stmt\Return_;
/**
 * Turn an arrow function into a closure.
 */
class ArrowClosure extends Plugin
{
    /**
     * Enter arrow function.
     *
     * @param ArrowFunction $func Arrow function
     *
     * @return Closure
     */
    public function enter(ArrowFunction $func, Context $context) : Closure
    {
        /** @var array<string, mixed> */
        $nodes = [];
        /** @var string */
        foreach ($func->getSubNodeNames() as $node) {
            /** @var mixed */
            $nodes[$node] = $func->{$node};
        }
        $nodes['stmts'] = [new Return_($func->expr)];
        /** @var array<string, true> */
        $params = [];
        /** @var Param */
        foreach ($nodes['params'] ?? [] as $param) {
            if ($param->var instanceof Variable) {
                /** @var string $param->var->name */
                $params[$param->var->name] = \true;
            }
        }
        $nodes['uses'] = \array_values(\array_intersect_key(\array_diff_key(VariableFinder::find($func->expr), $params), $context->variables->top()->getVars()));
        return new Closure($nodes, $func->getAttributes());
    }
}
<?php

namespace Phabel\Target\Php74;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\AssignOp\Coalesce;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Coalesce as BinaryOpCoalesce;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class NullCoalesceAssignment extends Plugin
{
    /**
     *
     */
    public function enter(Coalesce $coalesce) : Assign
    {
        return new Assign($coalesce->var, new BinaryOpCoalesce($coalesce->var, $coalesce->expr), $coalesce->getAttributes());
    }
}
<?php

namespace Phabel\Target;

use Phabel\Plugin;
use Phabel\Plugin\ComposerSanitizer;
use Phabel\Plugin\NewFixer;
use Phabel\Plugin\StmtExprWrapper;
use Phabel\PluginInterface;
use Phabel\Version;
use PhabelVendor\PhpParser\Node;
/**
 * Makes changes necessary to polyfill syntaxes of various PHP versions.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Php extends Plugin
{
    /**
     * PHP versions.
     *
     * @var int[]
     */
    const VERSIONS = [
        //56,
        //70,
        71,
        72,
        73,
        74,
        80,
    ];
    /**
     * Default target.
     */
    const DEFAULT_TARGET = \PHP_MAJOR_VERSION . \PHP_MINOR_VERSION;
    /**
     * Ignore target.
     */
    const TARGET_IGNORE = 1000;
    /**
     * Polyfill versions.
     */
    const POLYFILL_VERSIONS = ['symfony/polyfill-php56' => '^1.19', 'symfony/polyfill-php70' => '^1.19', 'symfony/polyfill-php71' => '^1.19', 'symfony/polyfill-php72' => '^1.23', 'symfony/polyfill-php73' => '^1.23', 'symfony/polyfill-php74' => '^1.23', 'symfony/polyfill-php80' => '^1.23', 'symfony/polyfill-php81' => '^1.23'];
    /**
     * Normalize target version string.
     *
     * @param string $target
     * @return integer
     */
    public static function normalizeVersion(string $target) : int
    {
        if ($target === 'auto') {
            return (int) self::DEFAULT_TARGET;
        }
        if (\preg_match(":^\\D*(\\d+\\.\\d+)\\..*:", $target, $matches)) {
            $target = $matches[1];
        }
        $target = \str_replace('.', '', $target);
        return (int) (\in_array($target, self::VERSIONS) ? $target : self::DEFAULT_TARGET);
    }
    /**
     * Unnormalize version string.
     *
     * @param int $target
     * @return string
     */
    public static function unnormalizeVersion(int $target) : string
    {
        $target = (string) $target;
        return $target[0] . '.' . $target[1];
    }
    /**
     * Get PHP version range to target.
     *
     * @param int $target
     * @return int[]
     */
    private static function getRange(int $target) : array
    {
        $key = \array_search($target, self::VERSIONS);
        if ($key === \false) {
            if ($target === (int) self::DEFAULT_TARGET) {
                return [];
            }
            return self::getRange((int) self::DEFAULT_TARGET);
        }
        return \array_slice(self::VERSIONS, 1 + $key);
    }
    /**
     *
     */
    public static function getComposerRequires(array $config) : array
    {
        $target = \Phabel\Target\Php::normalizeVersion($config['target'] ?? self::DEFAULT_TARGET);
        $res = ['php' => '>=' . \Phabel\Target\Php::unnormalizeVersion($target) . ' <' . \Phabel\Target\Php::unnormalizeVersion($target + 1), 'phabel/phabel' => Version::VERSION];
        if (\str_starts_with(Node::class, 'Phabel')) {
            return $res;
        }
        foreach (self::getRange($target) as $version) {
            $version = "symfony/polyfill-php{$version}";
            $res[$version] = self::POLYFILL_VERSIONS[$version];
        }
        return $res;
    }
    /**
     *
     */
    public static function previous(array $config) : array
    {
        $classes = [ComposerSanitizer::class => []];
        foreach (self::getRange((int) ($config['target'] ?? self::DEFAULT_TARGET)) as $version) {
            if (!\file_exists($dir = __DIR__ . "/Php{$version}")) {
                continue;
            }
            foreach (\scandir($dir) as $file) {
                if (\Phabel\Target\Php80\Polyfill::substr($file, -4) !== '.php') {
                    continue;
                }
                if (\str_ends_with($file, 'ExpressionFixer.php')) {
                    continue;
                }
                /** @var class-string<PluginInterface> */
                $class = self::class . $version . '\\' . \basename($file, '.php');
                /** @var array */
                $classes[$class] = $config[$class] ?? [];
            }
        }
        return $classes;
    }
    /**
     *
     */
    public static function next(array $config) : array
    {
        $classes = [StmtExprWrapper::class => $config[StmtExprWrapper::class] ?? [], NewFixer::class => []];
        foreach (self::getRange((int) ($config['target'] ?? self::DEFAULT_TARGET)) as $version) {
            if (!\file_exists(__DIR__ . "/Php{$version}")) {
                continue;
            }
            foreach (['Nested', 'Isset'] as $t) {
                /** @var class-string<PluginInterface> */
                $class = self::class . $version . "\\{$t}" . "ExpressionFixer";
                /** @var array */
                $classes[$class] = $config[$class] ?? [];
            }
        }
        return $classes;
    }
}
<?php

namespace Phabel\Target\Php56;

use Phabel\Plugin;
class IssetExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php56;

use Phabel\Plugin;
class NestedExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php73;

use Phabel\Plugin;
class IssetExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php73;

use Phabel\Plugin;
use Phabel\Plugin\NestedExpressionFixer as fixer;
/**
 * Expression fixer for PHP 73.
 */
class NestedExpressionFixer extends Plugin
{
    /**
     * {@inheritDoc}
     */
    public static function next(array $config) : array
    {
        return [fixer::class => ['PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]]]];
    }
}
<?php

namespace Phabel\Target\Php73;

use Phabel\Plugin;
use Phabel\Target\Polyfill as TargetPolyfill;
use PhabelVendor\PhpParser\Node;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Polyfill extends Plugin
{
    // Skip apache_request_headers
    // Todo: setrawcookie
    // Todo: password_hash
    /**
     *
     */
    public static function getComposerRequires(array $config) : array
    {
        if (\str_starts_with(Node::class, 'Phabel')) {
            return [];
        }
        return ['ralouphie/getallheaders' => '^3|^2'];
    }
    /**
     *
     */
    public static function array_push(array &$array, ...$values) : int
    {
        if (\count($values) === 0) {
            return \count($array);
        }
        return \array_push($array, ...$values);
    }
    /**
     *
     */
    public static function array_unshift(array &$array, ...$values) : int
    {
        if (\count($values) === 0) {
            return \count($array);
        }
        return \array_unshift($array, ...$values);
    }
    /**
     * {@inheritDoc}
     */
    public static function withNext(array $config) : array
    {
        return [TargetPolyfill::class => [self::class => \true]];
    }
}
<?php

namespace Phabel\Target\Php73;

use Phabel\Plugin;
use Phabel\Plugin\ListSplitter;
/**
 * Polyfills list assignment by reference.
 */
class ListReference extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [ListSplitter::class => ['byRef' => \true]];
    }
}
<?php

namespace Phabel\Target;

use Phabel\Plugin;
use Phabel\Tools;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\ClassConstFetch;
use PhabelVendor\PhpParser\Node\Expr\Error;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Name;
use ReflectionClass;
use ReflectionMethod;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Polyfill extends Plugin
{
    /**
     *
     */
    private array $functions = [];
    /**
     *
     */
    public static function mergeConfigs(array ...$configs) : array
    {
        $configs = \array_merge(...$configs);
        \krsort($configs, \SORT_STRING);
        $constants = [];
        $functions = [];
        foreach ($configs as $polyfill => $_) {
            $class = new ReflectionClass($polyfill);
            if ($class->hasConstant('CONSTANTS')) {
                $constants = \array_merge_recursive($constants, $class->getConstant('CONSTANTS'));
            }
            foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_STATIC) as $method) {
                if ($method->getDeclaringClass()->getName() === $polyfill) {
                    $functions[$method->getName()] = [$polyfill, $method->getName()];
                }
            }
        }
        return [['constants' => $constants, 'functions' => $functions]];
    }
    /**
     *
     */
    public function shouldRunFile(string $file) : bool
    {
        if (\preg_match(':Target/Php(\\d\\d)/Polyfill.php:', $file, $matches)) {
            $version = \Phabel\Target\Php::normalizeVersion($matches[1]);
            $version = \Phabel\Target\Php::class . $version . '\\Polyfill';
            $this->functions = \array_filter($this->getConfig('functions', []), fn($s) => $s[0] !== $version);
        } else {
            $this->functions = $this->getConfig('functions', []);
        }
        return !\str_contains($file, 'vendor/composer/');
    }
    /**
     *
     */
    public function enterFunc(FuncCall $call) : ?StaticCall
    {
        if (!$call->name instanceof Name) {
            return null;
        }
        $replacement = $this->functions[\strtolower(Tools::getFqdn($call->name, $call->name->toLowerString()))] ?? null;
        if ($replacement) {
            return Tools::call($replacement, ...$call->args);
        }
        return null;
    }
    /**
     *
     */
    public function enterClassConstant(ClassConstFetch $fetch) : ?Node
    {
        if ($fetch->name instanceof Error || !$fetch->class instanceof Name) {
            return null;
        }
        $constants = $this->getConfig('constants', []);
        if (isset($constants[Tools::getFqdn($fetch->class)][$fetch->name->name])) {
            return Tools::fromLiteral($constants[self::getFqdn($fetch->class)][$fetch->name->name]);
        }
        return null;
    }
}
<?php

namespace Phabel\Target\Php72;

use Phabel\Plugin;
class IssetExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php72;

use Phabel\Plugin;
class NestedExpressionFixer extends Plugin
{
}
<?php

namespace Phabel\Target\Php72\TypeContravariance;

use Phabel\ClassStorage;
use Phabel\ClassStorage\Storage;
use Phabel\ClassStorageProvider;
use Phabel\Plugin\TypeHintReplacer;
use PhabelVendor\PhpParser\Node\Stmt\Class_;
use SplStack;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class TypeContravariance extends ClassStorageProvider
{
    /**
     *
     */
    public static function processClassGraph(ClassStorage $storage) : bool
    {
        $changed = \false;
        foreach ($storage->getClasses() as $class) {
            // Can override abstract methods
            foreach ($class->getMethods(Class_::MODIFIER_ABSTRACT) as $name => $method) {
                $parentMethods = new SplStack();
                $parentMethods->push($method);
                foreach ($class->getOverriddenMethods($name, Class_::MODIFIER_ABSTRACT, $method->flags & Class_::VISIBILITY_MODIFIER_MASK) as $childMethod) {
                    $parentMethods->push($childMethod);
                }
                if ($parentMethods->count() === 1) {
                    continue;
                }
                foreach ($parentMethods as $method) {
                    /** @var Storage */
                    $storage = $method->getAttribute(Storage::STORAGE_KEY);
                    $changed = $storage->removeMethod($method) || $changed;
                }
            }
            // Can widen type in inherited methods
            foreach ($class->getMethods() as $name => $method) {
                if ($name === '__construct') {
                    foreach ($class->getOverriddenMethods($name) as $childMethod) {
                        if ($method->isPublic() && ($childMethod->isProtected() || $childMethod->isPrivate()) || $method->isProtected() && $childMethod->isPrivate()) {
                            $old = $childMethod->flags;
                            $childMethod->flags &= ~Class_::VISIBILITY_MODIFIER_MASK;
                            $childMethod->flags |= Class_::MODIFIER_PUBLIC;
                            $changed = $childMethod->flags !== $old || $changed;
                        }
                    }
                    continue;
                }
                $act = \array_fill(0, \count($method->params), \false);
                $parentMethods = new SplStack();
                $parentMethods->push($method);
                foreach ($class->getOverriddenMethods($name) as $childMethod) {
                    foreach ($childMethod->params as $k => $param) {
                        if (!TypeHintReplacer::replaced($method->params[$k]->type ?? null) && TypeHintReplacer::replaced($param->type)) {
                            $act[$k] = \true;
                        }
                    }
                    $parentMethods->push($childMethod);
                }
                $act = \array_keys(\array_filter($act));
                if (!$act) {
                    continue;
                }
                foreach ($parentMethods as $method) {
                    foreach ($act as $k) {
                        if (isset($method->params[$k])) {
                            $changed = TypeHintReplacer::replace($method->params[$k]->type) || $changed;
                        }
                    }
                }
            }
        }
        return $changed;
    }
    /**
     * {@inheritDoc}
     */
    public static function next(array $config) : array
    {
        return [TypeHintReplacer::class];
    }
}
<?php

namespace Phabel\Target\Php72;

use Phabel\Plugin;
use Phabel\Plugin\ClassStoragePlugin;
use Phabel\Target\Php72\TypeContravariance\TypeContravariance as T;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class TypeContravariance extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [ClassStoragePlugin::class => [T::class => \true]];
    }
}
<?php

namespace Phabel\Target\Php72;

use __PHP_Incomplete_Class;
use Phabel\Plugin;
use Phabel\Target\Polyfill as TargetPolyfill;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Polyfill extends Plugin
{
    // Todo: class constants moved from DateTime to DateTimeInterface
    // Todo: misc Date class changes
    // Todo: password_hash: Support for Argon2i passwords using <constant>PASSWORD_ARGON2I</constant> was added
    // Todo: ReflectionClass::getMethods, ReflectionClass::getProperties nullable
    // Todo: substr_compare
    // Skip PREG_UNMATCHED_AS_NULL
    /**
     *
     */
    public static function json_decode(string $json, ?bool $associative = null, int $depth = 512, int $flags = 0)
    {
        $associative ??= !!($flags & \JSON_OBJECT_AS_ARRAY);
        return \json_decode($json, $associative, $depth, $flags);
    }
    /**
     * @param (array | string) $string
     * @param (array | string | null) $from_encoding
     * @return (array | string | bool)
     */
    public static function mb_convert_encoding($string, string $to_encoding, $from_encoding = null)
    {
        if (!\is_string($string)) {
            if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                if (!\is_array($string)) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $string = (string) $string;
            }
        }
        if (!(\is_null($from_encoding) || \is_null($from_encoding))) {
            if (!\is_string($from_encoding)) {
                if (!(\is_string($from_encoding) || \is_object($from_encoding) && \method_exists($from_encoding, '__toString') || (\is_bool($from_encoding) || \is_numeric($from_encoding)))) {
                    if (!\is_array($from_encoding)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #3 ($from_encoding) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($from_encoding) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $from_encoding = (string) $from_encoding;
                }
            }
        }
        $from_encoding ??= \mb_internal_encoding();
        if (\is_array($string)) {
            foreach ($string as $k => $s) {
                if (\is_array($from_encoding)) {
                    $string[$k] = self::mb_convert_encoding($s, $to_encoding, $from_encoding[$k] ?? null);
                } else {
                    $string[$k] = self::mb_convert_encoding($s, $to_encoding, $from_encoding);
                }
            }
            $phabelReturn = $string;
            if (!\is_bool($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                    if (!\is_string($phabelReturn)) {
                        if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                            if (!\is_array($phabelReturn)) {
                                throw new \TypeError(__METHOD__ . '(): Return value must be of type array|string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                            }
                        } else {
                            $phabelReturn = (string) $phabelReturn;
                        }
                    }
                } else {
                    $phabelReturn = (bool) $phabelReturn;
                }
            }
            return $phabelReturn;
        }
        $phabelReturn = \mb_convert_encoding($string, $to_encoding, $from_encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        if (!\is_array($phabelReturn)) {
                            throw new \TypeError(__METHOD__ . '(): Return value must be of type array|string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                        }
                    } else {
                        $phabelReturn = (string) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function number_format(float $num, int $decimals = 0, ?string $decimal_separator = ".", ?string $thousands_separator = ",") : string
    {
        $res = \number_format($num, $decimals, $decimal_separator, $thousands_separator);
        return $res === '-0' ? '0' : $res;
    }
    /**
     *
     */
    public static function is_object($stuff) : bool
    {
        return $stuff instanceof __PHP_Incomplete_Class ? \true : \is_object($stuff);
    }
    /**
     * {@inheritDoc}
     */
    public static function withNext(array $config) : array
    {
        return [TargetPolyfill::class => [self::class => \true]];
    }
}
<?php

namespace Phabel\Target\Php72;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class ObjectTypeHintReplacer extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['types' => ['object']]];
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Context;
use Phabel\Plugin;
use Phabel\Plugin\IssetExpressionFixer as fixer;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\PropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\Variable;
use PhabelVendor\PhpParser\Node\Stmt\ClassMethod;
use PhabelVendor\PhpParser\Node\Stmt\Expression;
use PhabelVendor\PhpParser\Node\Stmt\Property;
use PhabelVendor\PhpParser\Node\Stmt\PropertyProperty;
/**
 * Expression fixer for PHP 80.
 */
class ConstructorPromotion extends Plugin
{
    /**
     *
     */
    public function enter(ClassMethod $classMethod, Context $ctx) : void
    {
        if (\strtolower($classMethod->name) !== '__construct' || $classMethod->stmts === null) {
            return;
        }
        foreach ($classMethod->params as $param) {
            if ($param->flags && $param->var instanceof Variable) {
                $ctx->insertAfter($classMethod, new Property($param->flags, [new PropertyProperty($param->var->name)], [], $param->type));
                \array_unshift($classMethod->stmts, new Expression(new Assign(new PropertyFetch(new Variable('this'), $param->var->name), new Variable($param->var->name))));
                $param->flags = 0;
            }
        }
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Plugin;
use Phabel\Plugin\NestedExpressionFixer;
use Phabel\Target\Php80\NullSafe\NullSafe;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhabelVendor\PhpParser\Node\Expr\MethodCall;
use PhabelVendor\PhpParser\Node\Expr\New_;
use PhabelVendor\PhpParser\Node\Expr\NullsafeMethodCall;
use PhabelVendor\PhpParser\Node\Expr\NullsafePropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\PropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\StaticPropertyFetch;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Param;
/**
 * Polyfill nullsafe expressions.
 */
class NullSafeTransformer extends Plugin
{
    /**
     * Property fetch.
     *
     * @param NullsafePropertyFetch $fetch
     * @return PropertyFetch
     */
    public function enterPropertyFetch(NullsafePropertyFetch $fetch) : PropertyFetch
    {
        return new PropertyFetch(new Coalesce($fetch->var, new StaticPropertyFetch(new FullyQualified(NullSafe::class), 'singleton')), $fetch->name);
    }
    /**
     * Method call.
     *
     * @param NullsafeMethodCall $fetch
     * @return MethodCall
     */
    public function enterMethodCall(NullsafeMethodCall $fetch) : MethodCall
    {
        return new MethodCall(new Coalesce($fetch->var, new StaticPropertyFetch(new FullyQualified(NullSafe::class), 'singleton')), $fetch->name, $fetch->args);
    }
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [NestedExpressionFixer::class => [New_::class => ['class' => [NullsafePropertyFetch::class => \true, NullsafeMethodCall::class => \true]]]];
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Plugin;
use Phabel\Plugin\IssetExpressionFixer as fixer;
/**
 * Expression fixer for PHP 80.
 */
class IssetExpressionFixer extends Plugin
{
    /**
     * {@inheritDoc}
     */
    public static function next(array $config) : array
    {
        return [fixer::class => ['PhabelVendor\\PhpParser\\Node\\Expr\\ArrayDimFetch' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true], 'dim' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\ConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true], 'name' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => ['name' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Variable' => ['name' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]]]];
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Expr\Throw_ as ExprThrow_;
/**
 * Polyfill throw expression.
 */
class ThrowExprReplacer extends Plugin
{
    /**
     *
     */
    public function enter(ExprThrow_ $throw) : StaticCall
    {
        return self::callPoly('throwMe', $throw->expr);
    }
    /**
     *
     */
    public static function throwMe(\Throwable $expr) : void
    {
        throw $expr;
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Plugin;
use Phabel\Plugin\NestedExpressionFixer as fixer;
/**
 * Expression fixer for PHP 80.
 */
class NestedExpressionFixer extends Plugin
{
    /**
     * {@inheritDoc}
     */
    public static function next(array $config) : array
    {
        return [fixer::class => ['PhabelVendor\\PhpParser\\Node\\Expr\\ArrayDimFetch' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true], 'dim' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => ['name' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => ['class' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\YieldFrom' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\ConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => ['class' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\YieldFrom' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\ConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true], 'name' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => ['name' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => ['if' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true], 'else' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Variable' => ['name' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\YieldFrom' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => ['value' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true], 'key' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => ['right' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => ['expr' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true]]]];
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Context;
use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Stmt\Catch_;
/**
 * Polyfill empty catch expression.
 */
class CatchEmpty extends Plugin
{
    /**
     *
     */
    public function enter(Catch_ $catch_, Context $ctx) : void
    {
        if ($catch_->var === null) {
            $catch_->var = $ctx->getVariable();
        }
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * Replace static, mixed and false typehints.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class StaticMixedFalseReplacer extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['types' => ['static', 'mixed', 'false']]];
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Context;
use Phabel\Plugin;
use Phabel\Plugin\VariableFinder;
use PhabelVendor\PhpParser\Node\Arg;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Concat;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Identical;
use PhabelVendor\PhpParser\Node\Expr\Closure;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Expr\Match_;
use PhabelVendor\PhpParser\Node\Expr\New_;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Param;
use PhabelVendor\PhpParser\Node\Scalar\String_;
use PhabelVendor\PhpParser\Node\Stmt\Else_;
use PhabelVendor\PhpParser\Node\Stmt\ElseIf_;
use PhabelVendor\PhpParser\Node\Stmt\If_;
use PhabelVendor\PhpParser\Node\Stmt\Return_;
use PhabelVendor\PhpParser\Node\Stmt\Throw_;
/**
 * Polyfill match expression.
 */
class MatchTransformer extends Plugin
{
    /**
     *
     */
    public function enter(Match_ $match, Context $context) : FuncCall
    {
        $closure = new Closure(['params' => [new Param($var = $context->getVariable())], 'uses' => \array_values(VariableFinder::find($match, \true))]);
        $cases = [];
        $default = null;
        foreach ($match->arms as $arm) {
            if ($arm->conds === null) {
                $default = new Return_($arm->body);
                continue;
            }
            foreach ($arm->conds as $cond) {
                $cases[] = [new Identical($var, $cond), new Return_($arm->body)];
            }
        }
        if (!$default) {
            $string = new Concat(new String_("Unhandled match value of type "), self::call('get_debug_type', $var));
            $default = new Throw_(new New_(new FullyQualified(\UnhandledMatchError::class), [new Arg($string)]));
        }
        if (empty($cases)) {
            $closure->stmts = [$default];
        } else {
            [$ifCond, $ifBody] = \array_shift($cases);
            foreach ($cases as &$case) {
                [$cond, $body] = $case;
                $case = new ElseIf_($cond, [$body]);
            }
            $closure->stmts = [new If_($ifCond, ['stmts' => [$ifBody], 'elseifs' => $cases, 'else' => new Else_([$default])])];
        }
        return new FuncCall($closure, [new Arg($match->cond)]);
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Plugin;
use Phabel\Target\Polyfill as TargetPolyfill;
use Phabel\Tools;
if (!\defined('CAL_EASTER_DEFAULT')) {
    \define('CAL_EASTER_DEFAULT', 0);
}
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Polyfill extends Plugin
{
    // Todo: nullability of a bunch of mb_ functions
    /**
     *
     */
    public static function easter_date(?int $year = null, int $mode = \CAL_EASTER_DEFAULT) : int
    {
        $year ??= (int) \date('Y');
        return \easter_date($year, $mode);
    }
    /**
     *
     */
    public static function easter_days(?int $year = null, int $mode = \CAL_EASTER_DEFAULT) : int
    {
        $year ??= (int) \date('Y');
        return \easter_days($year, $mode);
    }
    /**
     * @return (int | bool)
     */
    public static function unixtojd(?int $timestamp = null)
    {
        $timestamp ??= \time();
        $phabelReturn = \unixtojd($timestamp);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | int | float | bool)
     */
    public static function date_sunrise(int $timestamp, int $returnFormat = \SUNFUNCS_RET_STRING, ?float $latitude = null, ?float $longitude = null, ?float $zenith = null, ?float $utcOffset = null)
    {
        $latitude ??= Tools::ini_get('date.default_latitude');
        $longitude ??= Tools::ini_get('date.default_longitude');
        $zenith ??= Tools::ini_get('date.sunrise_zenith');
        $utcOffset ??= 0;
        $phabelReturn = \date_sunrise($timestamp, $returnFormat, $latitude, $longitude, $zenith, $utcOffset);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_float($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        if (!\is_int($phabelReturn)) {
                            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                                if (!\is_string($phabelReturn)) {
                                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|int|float|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                                    }
                                    $phabelReturn = (string) $phabelReturn;
                                }
                            } else {
                                $phabelReturn = (int) $phabelReturn;
                            }
                        }
                    } else {
                        $phabelReturn = (float) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | int | float | bool)
     */
    public static function date_sunset(int $timestamp, int $returnFormat = \SUNFUNCS_RET_STRING, ?float $latitude = null, ?float $longitude = null, ?float $zenith = null, ?float $utcOffset = null)
    {
        $latitude ??= Tools::ini_get('date.default_latitude');
        $longitude ??= Tools::ini_get('date.default_longitude');
        $zenith ??= Tools::ini_get('date.sunset_zenith');
        $utcOffset ??= 0;
        $phabelReturn = \date_sunset($timestamp, $returnFormat, $latitude, $longitude, $zenith, $utcOffset);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_float($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        if (!\is_int($phabelReturn)) {
                            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                                if (!\is_string($phabelReturn)) {
                                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|int|float|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                                    }
                                    $phabelReturn = (string) $phabelReturn;
                                }
                            } else {
                                $phabelReturn = (int) $phabelReturn;
                            }
                        }
                    } else {
                        $phabelReturn = (float) $phabelReturn;
                    }
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function date(string $format, ?int $timestamp = null) : string
    {
        return \date($format, $timestamp ?? \time());
    }
    /**
     *
     */
    public static function getdate(?int $timestamp = null) : array
    {
        return \getdate($timestamp ?? \time());
    }
    /**
     *
     */
    public static function gmdate(string $format, ?int $timestamp = null) : string
    {
        return \gmdate($format, $timestamp ?? \time());
    }
    /**
     * @return (string | bool)
     */
    public static function gmstrftime(string $format, ?int $timestamp = null)
    {
        $phabelReturn = \gmstrftime($format, $timestamp ?? \time());
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function idate(string $format, ?int $timestamp = null)
    {
        $phabelReturn = \idate($format, $timestamp ?? \time());
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function localtime(?int $timestamp = null, bool $associative = \false) : array
    {
        return \localtime($timestamp ?? \time(), $associative);
    }
    /**
     * @return (string | bool)
     */
    public static function strftime(string $format, ?int $timestamp = null)
    {
        $phabelReturn = \strftime($format, $timestamp ?? \time());
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function strtotime(string $datetime, ?int $baseTimestamp = null)
    {
        $phabelReturn = \strtotime($datetime, $baseTimestamp ?? \time());
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function error_reporting(?int $error_level = null) : int
    {
        return $error_level === null ? \error_reporting() : \error_reporting($error_level);
    }
    /**
     *
     */
    public static function hash_update_file($context, string $filename, $stream_context = null) : bool
    {
        return $stream_context ? \hash_update_file($context, $filename, $stream_context) : \hash_update_file($context, $filename);
    }
    /**
     * @return (array | false)
     */
    public static function iconv_mime_decode_headers(string $headers, int $mode = 0, ?string $encoding = null)
    {
        $phabelReturn = \iconv_mime_decode_headers($headers, $mode, $encoding ?? \iconv_get_encoding('internal_encoding'));
        if (!(\is_array($phabelReturn) || $phabelReturn === \false)) {
            throw new \TypeError(__METHOD__ . '(): Return value must be of type false|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
        }
        return $phabelReturn;
    }
    /**
     * @return (string | bool)
     */
    public static function iconv_mime_decode(string $string, int $mode = 0, ?string $encoding = null)
    {
        $phabelReturn = \iconv_mime_decode($string, $mode, $encoding ?? \iconv_get_encoding('internal_encoding'));
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function iconv_strlen(string $string, ?string $encoding = null)
    {
        $phabelReturn = \iconv_strlen($string, $encoding ?? \iconv_get_encoding('internal_encoding'));
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function iconv_strpos(string $haystack, string $needle, int $offset = 0, ?string $encoding = null)
    {
        $phabelReturn = \iconv_strpos($haystack, $needle, $offset, $encoding ?? \iconv_get_encoding('internal_encoding'));
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (int | bool)
     */
    public static function iconv_strrpos(string $haystack, string $needle, ?string $encoding = null)
    {
        $phabelReturn = \iconv_strrpos($haystack, $needle, $encoding ?? \iconv_get_encoding('internal_encoding'));
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | bool)
     */
    public static function iconv_substr(string $string, int $offset, ?int $length = null, ?string $encoding = null)
    {
        $phabelReturn = \iconv_substr($string, $offset, $length, $encoding ?? \iconv_get_encoding('internal_encoding'));
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function get_resources(?string $type = null) : array
    {
        return $type === null ? \get_resources() : \get_resources($type);
    }
    /**
     * @return (string | bool)
     */
    public static function mhash(int $algo, string $data, ?string $key = null)
    {
        $phabelReturn = $key === null ? \mhash($algo, $data) : \mhash($algo, $data);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function ignore_user_abort(?bool $enable = null) : int
    {
        return $enable === null ? \ignore_user_abort() : \ignore_user_abort($enable);
    }
    /**
     *
     */
    public static function fsockopen(string $hostname, int $port = -1, int &$error_code = null, string &$error_message = null, ?float $timeout = null)
    {
        return $timeout === null ? \fsockopen($hostname, $port, $error_code, $error_message) : \fsockopen($hostname, $port, $error_code, $error_message);
    }
    /**
     *
     */
    public static function ob_implicit_flush(bool $flag = \true) : void
    {
        \ob_implicit_flush((int) $flag);
    }
    /**
     * @param (string | int | null) $algo
     */
    public static function password_hash(string $password, $algo, array $options = []) : string
    {
        if (!\is_null($algo)) {
            if (!\is_int($algo)) {
                if (!(\is_bool($algo) || \is_numeric($algo))) {
                    if (!\is_string($algo)) {
                        if (!(\is_string($algo) || \is_object($algo) && \method_exists($algo, '__toString') || (\is_bool($algo) || \is_numeric($algo)))) {
                            throw new \TypeError(__METHOD__ . '(): Argument #2 ($algo) must be of type string|int|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($algo) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                        }
                        $algo = (string) $algo;
                    }
                } else {
                    $algo = (int) $algo;
                }
            }
        }
        return \password_hash($password, $algo ?? \PASSWORD_DEFAULT, $options);
    }
    /**
     *
     */
    public static function pcntl_async_signals(?bool $enable = null) : bool
    {
        return $enable === null ? \pcntl_async_signals() : \pcntl_async_signals($enable);
    }
    /**
     * @return (int | bool)
     */
    public static function pcntl_getpriority(?int $process_id = null, int $mode = \PRIO_PROCESS)
    {
        $phabelReturn = \pcntl_getpriority($process_id ?? \getmypid(), $mode);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function pcntl_setpriority(int $priority, ?int $process_id = null, int $mode = \PRIO_PROCESS) : bool
    {
        return \pcntl_setpriority($priority, $process_id ?? \getmypid(), $mode);
    }
    /**
     * @param (int | string | bool | null) $value
     */
    public static function readline_info(?string $var_name = null, $value = null)
    {
        if (!(\is_null($value) || \is_null($value))) {
            if (!\is_bool($value)) {
                if (!(\is_bool($value) || \is_numeric($value) || \is_string($value))) {
                    if (!\is_string($value)) {
                        if (!(\is_string($value) || \is_object($value) && \method_exists($value, '__toString') || (\is_bool($value) || \is_numeric($value)))) {
                            if (!\is_int($value)) {
                                if (!(\is_bool($value) || \is_numeric($value))) {
                                    throw new \TypeError(__METHOD__ . '(): Argument #2 ($value) must be of type ?int|string|bool|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($value) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                                }
                                $value = (int) $value;
                            }
                        } else {
                            $value = (string) $value;
                        }
                    }
                } else {
                    $value = (bool) $value;
                }
            }
        }
        return $var_name === null && $value === null ? \readline_info() : \readline_info($var_name, $value);
    }
    /**
     *
     */
    public static function readline_read_history(?string $filename = null) : bool
    {
        return $filename === null ? \readline_read_history() : \readline_read_history($filename);
    }
    /**
     *
     */
    public static function readline_write_history(?string $filename = null) : bool
    {
        return $filename === null ? \readline_read_history() : \readline_write_history($filename);
    }
    /**
     * @return (int | bool)
     */
    public static function session_cache_expire(?int $value = null)
    {
        $phabelReturn = $value === null ? \session_cache_expire() : \session_cache_expire($value);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_int($phabelReturn)) {
                    if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type int|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (int) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | bool)
     */
    public static function session_cache_limiter(?string $value = null)
    {
        $phabelReturn = $value === null ? \session_cache_limiter() : \session_cache_limiter($value);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | bool)
     */
    public static function session_id(?string $id = null)
    {
        $phabelReturn = $id === null ? \session_id() : \session_id($id);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | bool)
     */
    public static function session_module_name(?string $module = null)
    {
        $phabelReturn = $module === null ? \session_module_name() : \session_module_name($module);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | bool)
     */
    public static function session_name(?string $name = null)
    {
        $phabelReturn = $name === null ? \session_name() : \session_name($name);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @return (string | bool)
     */
    public static function session_save_path(?string $path = null)
    {
        $phabelReturn = $path === null ? \session_save_path() : \session_save_path($path);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     * @param (int | array) $lifetime_or_options
     */
    public static function session_set_cookie_params($lifetime_or_options, ?string $path = null, ?string $domain = null, ?bool $secure = null, ?bool $httponly = null) : bool
    {
        if (!\is_array($lifetime_or_options)) {
            if (!\is_int($lifetime_or_options)) {
                if (!(\is_bool($lifetime_or_options) || \is_numeric($lifetime_or_options))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($lifetime_or_options) must be of type int|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($lifetime_or_options) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                $lifetime_or_options = (int) $lifetime_or_options;
            }
        }
        return \is_array($lifetime_or_options) ? \session_set_cookie_params($lifetime_or_options) : \session_set_cookie_params(\array_filter(['lifetime' => $lifetime_or_options, 'path' => $path, 'domain' => $domain, 'secure' => $secure, 'httponly' => $httponly]));
    }
    /**
     *
     */
    public static function spl_autoload_extensions(?string $file_extensions = null) : string
    {
        return $file_extensions === null ? \spl_autoload_extensions() : \spl_autoload_extensions($file_extensions);
    }
    /**
     *
     */
    public static function spl_autoload_register(?callable $callback = null, bool $throw = \true, bool $prepend = \false) : bool
    {
        return \spl_autoload_register($callback ?? 'spl_autoload', $throw, $prepend);
    }
    /**
     *
     */
    public static function spl_autoload(string $class, ?string $file_extensions = null) : void
    {
        $file_extensions === null ? \spl_autoload($class) : \spl_autoload($class, $file_extensions);
    }
    /**
     *
     */
    public static function html_entity_decode(string $string, int $flags = \ENT_COMPAT, ?string $encoding = null) : string
    {
        return \html_entity_decode($string, $flags, $encoding ?? Tools::ini_get('default_charset'));
    }
    /**
     *
     */
    public static function htmlentities(string $string, int $flags = \ENT_COMPAT, ?string $encoding = null, bool $double_encode = \true) : string
    {
        return \htmlentities($string, $flags, $encoding ?? Tools::ini_get('default_charset'), $double_encode);
    }
    /**
     * @return (array | int)
     */
    public static function str_word_count(string $string, int $format = 0, ?string $characters = null)
    {
        $phabelReturn = $format === null ? \str_word_count($string, $format) : \str_word_count($string, $format, $characters);
        if (!\is_int($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn))) {
                if (!\is_array($phabelReturn)) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type array|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $phabelReturn = (int) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function strcspn(string $string, string $characters, int $offset = 0, ?int $length = null) : int
    {
        return $length === null ? \strcspn($string, $characters, $offset) : \strcspn($string, $characters, $offset, $length);
    }
    /**
     * @param (array | string | null) $allowed_tags
     */
    public static function strip_tags(string $string, $allowed_tags = null) : string
    {
        if (!(\is_null($allowed_tags) || \is_null($allowed_tags))) {
            if (!\is_string($allowed_tags)) {
                if (!(\is_string($allowed_tags) || \is_object($allowed_tags) && \method_exists($allowed_tags, '__toString') || (\is_bool($allowed_tags) || \is_numeric($allowed_tags)))) {
                    if (!\is_array($allowed_tags)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #2 ($allowed_tags) must be of type ?array|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($allowed_tags) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $allowed_tags = (string) $allowed_tags;
                }
            }
        }
        return $allowed_tags === null ? \strip_tags($string) : \strip_tags($string, $allowed_tags);
    }
    /**
     *
     */
    public static function strspn(string $string, string $characters, int $offset = 0, ?int $length = null) : int
    {
        return $length === null ? \strspn($string, $characters, $offset) : \strspn($string, $characters, $offset, $length);
    }
    /**
     *
     */
    public static function substr_compare(string $haystack, string $needle, int $offset, ?int $length = null, bool $case_insensitive = \false) : int
    {
        return \substr_compare($haystack, $needle, $offset, $length ?? \max(\strlen($needle), \strlen($haystack) - ($offset < 0 ? \strlen($haystack) + $offset : $offset)), $case_insensitive);
    }
    /**
     *
     */
    public static function substr_count(string $haystack, string $needle, int $offset = 0, ?int $length = null) : int
    {
        return $length === null ? \substr_count($haystack, $needle, $offset) : \substr_count($haystack, $needle, $offset, $length);
    }
    /**
     * @param (array | string) $string
     * @param (array | string) $replace
     * @param (array | int) $offset
     * @param (array | int | null) $length
     * @return (string | array)
     */
    public static function substr_replace($string, $replace, $offset, $length = null)
    {
        if (!\is_string($string)) {
            if (!(\is_string($string) || \is_object($string) && \method_exists($string, '__toString') || (\is_bool($string) || \is_numeric($string)))) {
                if (!\is_array($string)) {
                    throw new \TypeError(__METHOD__ . '(): Argument #1 ($string) must be of type array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($string) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $string = (string) $string;
            }
        }
        if (!\is_string($replace)) {
            if (!(\is_string($replace) || \is_object($replace) && \method_exists($replace, '__toString') || (\is_bool($replace) || \is_numeric($replace)))) {
                if (!\is_array($replace)) {
                    throw new \TypeError(__METHOD__ . '(): Argument #2 ($replace) must be of type array|string, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($replace) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $replace = (string) $replace;
            }
        }
        if (!\is_int($offset)) {
            if (!(\is_bool($offset) || \is_numeric($offset))) {
                if (!\is_array($offset)) {
                    throw new \TypeError(__METHOD__ . '(): Argument #3 ($offset) must be of type array|int, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($offset) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
            } else {
                $offset = (int) $offset;
            }
        }
        if (!(\is_null($length) || \is_null($length))) {
            if (!\is_int($length)) {
                if (!(\is_bool($length) || \is_numeric($length))) {
                    if (!\is_array($length)) {
                        throw new \TypeError(__METHOD__ . '(): Argument #4 ($length) must be of type ?array|int|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($length) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                } else {
                    $length = (int) $length;
                }
            }
        }
        $phabelReturn = $length === null ? \substr_replace($string, $replace, $offset) : \substr_replace($string, $replace, $offset, $length);
        if (!\is_array($phabelReturn)) {
            if (!\is_string($phabelReturn)) {
                if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                    throw new \TypeError(__METHOD__ . '(): Return value must be of type string|array, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                $phabelReturn = (string) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function substr(string $string, int $offset, ?int $length = null) : string
    {
        return $length === null ? \substr($string, $offset) : \substr($string, $offset, $length);
    }
    /**
     * {@inheritDoc}
     */
    public static function withNext(array $config) : array
    {
        return [TargetPolyfill::class => [self::class => \true]];
    }
}
<?php

namespace Phabel\Target\Php80\NullSafe;

/**
 * Nullsafe class.
 */
class NullSafe
{
    /**
     *
     */
    public static self $singleton;
    /**
     * Null.
     *
     * @param mixed $name
     * @param array $arguments
     * @return void
     */
    public function __call($name, array $arguments)
    {
    }
    /**
     * Null.
     *
     * @param mixed $name
     * @param mixed $value
     * @return void
     */
    public function __set($name, $value)
    {
    }
    /**
     * Null.
     *
     * @param mixed $name
     * @return void
     */
    public function __get($name)
    {
    }
}
\Phabel\Target\Php80\NullSafe\NullSafe::$singleton = new \Phabel\Target\Php80\NullSafe\NullSafe();
<?php

namespace Phabel\Target\Php80;

use Phabel\Plugin;
use Phabel\Tools;
use PhabelVendor\PhpParser\Node\Expr\ClassConstFetch;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name;
/**
 * Polyfill fetching class name from object.
 */
class ClassName extends Plugin
{
    /**
     *
     */
    public function enter(ClassConstFetch $fetch) : ?FuncCall
    {
        if ($fetch->name instanceof Identifier && $fetch->name->name === 'class' && !$fetch->class instanceof Name) {
            return Tools::call('get_class', $fetch->class);
        }
        return null;
    }
}
<?php

namespace Phabel\Target\Php80;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * Strip union types, polyfilling type checks.
 */
class UnionTypeStripper extends Plugin
{
    /**
     * {@inheritDoc}
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['union' => \true]];
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use Phabel\Plugin\IssetExpressionFixer as fixer;
/**
 * Expression fixer for PHP 70.
 */
class IssetExpressionFixer extends Plugin
{
    /**
     * {@inheritDoc}
     */
    public static function next(array $config) : array
    {
        return [fixer::class => ['PhabelVendor\\PhpParser\\Node\\Expr\\ArrayDimFetch' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => ['class' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => ['class' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]]]];
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Spaceship;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
/**
 * Polyfill spaceship operator.
 */
class SpaceshipOperatorReplacer extends Plugin
{
    /**
     * Replace spaceship operator.
     *
     * @param Spaceship $node Node
     *
     * @return StaticCall
     */
    public function enter(Spaceship $node) : StaticCall
    {
        return self::callPoly('spaceship', $node->left, $node->right);
    }
    /**
     * Spacesip operator.
     *
     * @param (integer | string | float) $a A
     * @param (integer | string | float) $b B
     *
     * @return integer
     */
    public static function spaceship($a, $b) : int
    {
        return $a < $b ? -1 : ($a === $b ? 0 : 1);
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use Phabel\Plugin\NestedExpressionFixer as fixer;
/**
 * Expression fixer for PHP 70.
 */
class NestedExpressionFixer extends Plugin
{
    /**
     * {@inheritDoc}
     */
    public static function next(array $config) : array
    {
        return [fixer::class => ['PhabelVendor\\PhpParser\\Node\\Expr\\ArrayDimFetch' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => ['class' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => ['name' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => ['var' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => ['class' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]], 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => ['class' => ['PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClassConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ClosureUse' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Include_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticPropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true]]]];
    }
}
<?php

namespace Phabel\Target\Php70\AnonymousClass;

interface AnonymousClassInterface
{
    /**
     * Get original name.
     *
     * @return string
     */
    public static function getPhabelOriginalName();
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Context;
use Phabel\Plugin;
use Phabel\Plugin\StringConcatOptimizer;
use Phabel\Target\Php70\AnonymousClass\AnonymousClassInterface;
use Phabel\Target\Php71\NullableType;
use Phabel\Target\Php74\ArrowClosure;
use Phabel\Target\Php80\UnionTypeStripper;
use PhabelVendor\PhpParser\Builder\Method;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Concat;
use PhabelVendor\PhpParser\Node\Expr\BooleanNot;
use PhabelVendor\PhpParser\Node\Expr\ClassConstFetch;
use PhabelVendor\PhpParser\Node\Expr\New_;
use PhabelVendor\PhpParser\Node\Identifier;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Scalar\String_;
use PhabelVendor\PhpParser\Node\Stmt\Class_;
use PhabelVendor\PhpParser\Node\Stmt\If_;
use PhabelVendor\PhpParser\Node\Stmt\Return_;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class AnonymousClassReplacer extends Plugin
{
    /**
     * Anonymous class count.
     */
    private static int $count = 0;
    /**
     * Enter new.
     *
     * @param New_ $node New stmt
     * @param Context $ctx Context
     *
     * @return void
     */
    public function enterNew(New_ $node, Context $ctx) : void
    {
        $classNode = $node->class;
        if (!$classNode instanceof Node\Stmt\Class_) {
            return;
        }
        $className = null;
        if ($classNode->extends) {
            $className = new ClassConstFetch($classNode->extends, new Identifier('class'));
        }
        if (!$className) {
            foreach ($classNode->implements as $name) {
                $className = new ClassConstFetch($name, new Identifier('class'));
                break;
            }
        }
        if ($className) {
            $className = new Concat($className, new String_('@anonymous'));
        } else {
            $className = new String_('class@anonymous');
        }
        $name = 'PhabelAnonymousClass' . \hash('sha256', $ctx->getOutputFile()) . self::$count++;
        $classNode->stmts[] = (new Method('getPhabelOriginalName'))->makePublic()->makeStatic()->addStmt(new Return_($className))->getNode();
        $classNode->implements[] = new FullyQualified(AnonymousClassInterface::class);
        $classNode->name = new Identifier($name);
        $node->class = new Node\Name($name);
        $ctx->nameResolver->enterNode($classNode);
        $classNode = new If_(new BooleanNot(self::call('class_exists', new ClassConstFetch($node->class, new Identifier('class')))), ['stmts' => [$classNode]]);
        $topClass = null;
        foreach ($ctx->parents as $parent) {
            if ($parent instanceof Class_) {
                $topClass = $parent;
            }
        }
        if ($topClass) {
            $ctx->insertAfter($topClass, $classNode);
        } else {
            $ctx->insertBefore($node, $classNode);
        }
    }
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [ArrowClosure::class, \Phabel\Target\Php70\ReturnTypeHints::class, NullableType::class, UnionTypeStripper::class];
    }
    /**
     *
     */
    public static function next(array $config) : array
    {
        return [StringConcatOptimizer::class];
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Identifier;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class ReservedNameReplacer extends Plugin
{
    /**
     * {@inheritdoc}
     */
    public function leaveNode(Node $node) : void
    {
        if (!($node instanceof Node\Expr\MethodCall || $node instanceof Node\Expr\StaticCall || $node instanceof Node\Stmt\ClassMethod || $node instanceof Node\Expr\ClassConstFetch || $node instanceof Node\Const_) || !$node->name instanceof Identifier) {
            return;
        }
        $name =& $node->name->name;
        if (\in_array(\strtolower($name), ['continue', 'empty', 'use', 'default', 'echo'])) {
            $name .= '_';
        }
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class ScalarTypeHints extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['types' => ['int', 'float', 'string', 'bool']]];
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
use Phabel\Target\Php71\MultipleCatchReplacer;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\BooleanOr;
use PhabelVendor\PhpParser\Node\Expr\Instanceof_;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Param;
use PhabelVendor\PhpParser\Node\Stmt\TryCatch;
/**
 * Replace \Throwable usages.
 */
class ThrowableReplacer extends Plugin
{
    /**
     * Check if plugin should run.
     *
     * @param string $file File name
     *
     * @return boolean
     */
    public function shouldRunFile(string $file) : bool
    {
        return !\str_ends_with($file, 'src/Target/Php70/ThrowableReplacer.php');
    }
    /**
     * Check if type string is \Throwable or Throwable.
     *
     * @param string $type Type string
     *
     * @return boolean
     */
    private static function isThrowable(string $type) : bool
    {
        return $type === \Throwable::class || $type === '\\Throwable';
    }
    /**
     * Check if is a throwable.
     *
     * @param mixed $obj
     * @param mixed $class
     * @return boolean
     */
    public static function isInstanceofThrowable($obj, $class) : bool
    {
        if (\is_string($class) && self::isThrowable($class)) {
            return $obj instanceof \Exception || $obj instanceof \Error;
        }
        return $obj instanceof $class;
    }
    /**
     * Split instance of \Throwable.
     *
     * @param Instanceof_ $node
     *
     * @return ?Node
     */
    public function enterInstanceOf(Instanceof_ $node)
    {
        if ($node->class instanceof Name) {
            if (!$this->isThrowable($node->class->toString())) {
                return null;
            }
            return new BooleanOr(new Instanceof_($node->expr, new FullyQualified('Exception')), new Instanceof_($node->expr, new FullyQualified('Error')));
        }
        return self::callPoly('isInstanceofThrowable', $node->expr, $node->class);
    }
    /**
     * Substitute try-catch.
     *
     * @param TryCatch $node TryCatch node
     *
     * @return void
     */
    public function enterTryCatch(TryCatch $node) : void
    {
        foreach ($node->catches as $catch) {
            $alreadyHasError = \false;
            $next = \false;
            foreach ($catch->types as &$type) {
                if ($type instanceof FullyQualified && $type->getLast() === "Error") {
                    $alreadyHasError = \true;
                }
                if ($this->isThrowable($type->toString())) {
                    $next = \true;
                    $type = new FullyQualified('Exception');
                }
            }
            if ($next && !$alreadyHasError) {
                $catch->types[] = new FullyQualified('Error');
            }
        }
    }
    /**
     *
     */
    public static function withPrevious(array $config) : array
    {
        return [TypeHintReplacer::class => ['type' => [\Throwable::class]], MultipleCatchReplacer::class => []];
    }
}
<?php

namespace Phabel\Target\Php70;

use AssertionError;
use IntlChar;
use Phabel\Plugin;
use Phabel\Target\Php;
use Phabel\Target\Polyfill as TargetPolyfill;
use Phabel\Tools;
use PhabelVendor\PhpParser\Node;
use Throwable;
use ValueError;
\define('BIG_ENDIAN', \pack('L', 1) === \pack('N', 1));
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Polyfill extends Plugin
{
    private const IS_WINDOWS = \PHP_OS_FAMILY === 'Windows';
    public const CONSTANTS = [IntlChar::class => ['NO_NUMERIC_VALUE' => -123456789.0]];
    // Todo: dns_get_record CAA
    // Todo: filters
    // Todo: getenv/putenv
    // Todo: unpack
    /**
     * Get composer requirements.
     *
     * @return array
     */
    public static function getComposerRequires(array $config) : array
    {
        if (\str_starts_with(Node::class, 'Phabel')) {
            return [];
        }
        return ['symfony/polyfill-php72' => Php::POLYFILL_VERSIONS['symfony/polyfill-php72']];
    }
    /**
     * @param (string | Throwable | null) $exception
     */
    public static function assert($assertion, $exception = null) : bool
    {
        if (!($exception instanceof Throwable || \is_null($exception) || \is_null($exception))) {
            if (!\is_string($exception)) {
                if (!(\is_string($exception) || \is_object($exception) && \method_exists($exception, '__toString') || (\is_bool($exception) || \is_numeric($exception)))) {
                    throw new \TypeError(__METHOD__ . '(): Argument #2 ($exception) must be of type ?Throwable|string|null, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($exception) . ' given, called in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                }
                $exception = (string) $exception;
            }
        }
        if ($assertion || Tools::ini_get('zend.assertions') !== 1) {
            return \true;
        }
        $exception = new AssertionError('assert(false)');
        if (\is_null($exception)) {
            $exception = new AssertionError('assert(false)');
        } elseif (\is_string($exception)) {
            $exception = new AssertionError($exception);
        }
        if (Tools::ini_get('assert.exception')) {
            throw $exception;
        }
        \trigger_error("Uncaught {$exception}");
        return \true;
    }
    /**
     *
     */
    public static function dirname(string $path, int $levels = 1) : string
    {
        if ($levels === 1) {
            return \dirname($path);
        }
        if ($levels < 1) {
            throw new ValueError('dirname(): Argument #2 ($levels) must be greater than or equal to 1');
        }
        for ($x = \strlen($path) - 1; $x >= 0 && $levels > 0; $x--) {
            if ($path[$x] === '/' || self::IS_WINDOWS && $path[$x] === '\\') {
                --$levels;
            }
        }
        $path = \substr($path, \max(0, $x));
        return $path === '' ? '.' : $path;
    }
    /**
     *
     */
    public static function get_defined_functions(bool $exclude_disabled = \true) : array
    {
        if ($exclude_disabled) {
            $disabled = \explode(',', Tools::ini_get('disable_functions') ?: '');
            $res = \get_defined_functions();
            $res['internal'] = \array_diff($res['internal'], $disabled);
            return $res;
        }
        return \get_defined_functions();
    }
    /**
     *
     */
    public static function substr(string $string, int $offset, ?int $length = null) : string
    {
        if (\strlen($string) === $offset) {
            return '';
        }
        return \substr($string, $offset, $length);
    }
    /**
     * @return (string | bool)
     */
    public static function iconv_substr(string $string, int $offset, ?int $length = null, ?string $encoding = null)
    {
        $encoding ??= \iconv_get_encoding('internal_encoding');
        $len = \iconv_strlen($string, $encoding);
        if ($len === $offset) {
            $phabelReturn = '';
            if (!\is_bool($phabelReturn)) {
                if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                    if (!\is_string($phabelReturn)) {
                        if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                            throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                        }
                        $phabelReturn = (string) $phabelReturn;
                    }
                } else {
                    $phabelReturn = (bool) $phabelReturn;
                }
            }
            return $phabelReturn;
        }
        $length ??= $len;
        $phabelReturn = \iconv_substr($string, $offset, $length, $encoding);
        if (!\is_bool($phabelReturn)) {
            if (!(\is_bool($phabelReturn) || \is_numeric($phabelReturn) || \is_string($phabelReturn))) {
                if (!\is_string($phabelReturn)) {
                    if (!(\is_string($phabelReturn) || \is_object($phabelReturn) && \method_exists($phabelReturn, '__toString') || (\is_bool($phabelReturn) || \is_numeric($phabelReturn)))) {
                        throw new \TypeError(__METHOD__ . '(): Return value must be of type string|bool, ' . \Phabel\Plugin\TypeHintReplacer::getDebugType($phabelReturn) . ' returned in ' . \Phabel\Plugin\TypeHintReplacer::trace());
                    }
                    $phabelReturn = (string) $phabelReturn;
                }
            } else {
                $phabelReturn = (bool) $phabelReturn;
            }
        }
        return $phabelReturn;
    }
    /**
     *
     */
    public static function pack(string $format, ...$values) : string
    {
        $l = \strlen($format);
        $y = 0;
        $newFormat = '';
        for ($x = 0; $x < $l; $x++) {
            $cur = $format[$x++];
            $repeater = '';
            for (; $x < $l && ($format[$x] === '*' || \is_numeric($format[$x])); $x++) {
                $repeater .= $format[$x];
            }
            $x--;
            $repeaterOrig = $repeater;
            if ($cur === 'a' || $cur === 'A' || $cur === 'h' || $cur === 'H' || $cur === '@') {
                $repeater = 1;
            } else {
                $repeater = $repeater === '*' ? \count($values) - $y : (int) $repeater;
            }
            if (BIG_ENDIAN && $cur === 'g' || !BIG_ENDIAN && $cur === 'G') {
                $cur = '';
                for ($z = $y; $z < $y + $repeater; $z++) {
                    $cur .= 'a4';
                    $values[$z] = \strrev(\pack('f', $values[$z]));
                }
                $newFormat .= $cur;
            } elseif (BIG_ENDIAN && $cur === 'e' || !BIG_ENDIAN && $cur === 'E') {
                $cur = '';
                for ($z = $y; $z < $y + $repeater; $z++) {
                    $cur .= 'a8';
                    $values[$z] = \strrev(\pack('d', $values[$z]));
                }
                $newFormat .= $cur;
            } else {
                $newFormat .= $cur . $repeaterOrig;
            }
        }
        return \pack($newFormat, ...$values);
    }
    /**
     * {@inheritDoc}
     */
    public static function withNext(array $config) : array
    {
        return [TargetPolyfill::class => [self::class => \true]];
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Stmt\GroupUse;
use PhabelVendor\PhpParser\Node\Stmt\Use_;
use PhabelVendor\PhpParser\Node\Stmt\UseUse;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class GroupUseReplacer extends Plugin
{
    /**
     * Replace group use with multiple use statements.
     *
     * @param GroupUse $node Group use statement
     *
     * @return Use_[]
     */
    public function leave(GroupUse $node) : array
    {
        $nodePrefixParts = $node->prefix->parts;
        return \array_map(fn(UseUse $useNode) => $this->createUseNode($nodePrefixParts, $useNode), $node->uses);
    }
    /**
     * Create separate use node.
     *
     * @param string[] $nodePrefixParts Use prefix
     * @param UseUse $useNode Current use node
     *
     * @return Use_ New use node
     */
    protected function createUseNode(array $nodePrefixParts, UseUse $useNode) : Use_
    {
        $nodePrefixParts[] = $useNode->name;
        $nameNode = new Node\Name($nodePrefixParts);
        return new Use_([new UseUse($nameNode, $useNode->alias)], $useNode->type);
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use PhabelVendor\PhpParser\Node\Stmt\Declare_;
use PhabelVendor\PhpParser\Node\Stmt\DeclareDeclare;
use PhabelVendor\PhpParser\Node\Stmt\Nop;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class StrictTypesDeclareStatementRemover extends Plugin
{
    /**
     *
     */
    public function leave(Declare_ $node) : ?Nop
    {
        $node->declares = \array_filter($node->declares, fn(DeclareDeclare $declare) => $declare->key->name !== 'strict_types');
        if (empty($node->declares)) {
            return new Nop();
        }
        return null;
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Context;
use Phabel\Plugin;
use Phabel\RootNode;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\Eval_;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Name;
use PhabelVendor\PhpParser\Node\Stmt\Const_;
/**
 * Converts define() arrays into const arrays.
 */
class DefineArrayReplacer extends Plugin
{
    /**
     * Convert define() arrays into const arrays.
     *
     * @param FuncCall $node Node
     *
     * @return (Const_ | Eval_ | null)
     */
    public function enter(FuncCall $node, Context $context)
    {
        if (!$node->name instanceof Name || $node->name->toString() != 'define') {
            return null;
        }
        $nameNode = $node->args[0]->value;
        $valueNode = $node->args[1]->value;
        if (!$valueNode instanceof Node\Expr\Array_) {
            return null;
        }
        if (!$context->parents->top() instanceof RootNode) {
            return self::callPoly('defineMe', ...$node->args);
        }
        $constNode = new Node\Const_($nameNode->value, $valueNode);
        return new Node\Stmt\Const_([$constNode]);
    }
    /**
     * Define a constant.
     *
     * @param string $name
     * @param array $value
     * @return void
     */
    public static function defineMe(string $name, array $value) : void
    {
        $name = \preg_replace("/[^A-Za-z0-9_]/", '', $name);
        $value = \var_export($value, \true);
        eval("const {$name} = {$value};");
    }
}
<?php

namespace Phabel\Target\Php70\NullCoalesce;

use Phabel\Plugin;
abstract class DisallowedExpressions extends Plugin
{
    const EXPRESSIONS = ['PhabelVendor\\PhpParser\\Node\\Expr\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Assign' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignRef' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BitwiseNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BooleanNot' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Clone_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Closure' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ConstFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Empty_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ErrorSuppress' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Eval_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\FuncCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Instanceof_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Isset_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Match_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\MethodCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\New_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\NullsafeMethodCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\NullsafePropertyFetch' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PostInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreDec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\PreInc' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Print_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\ShellExec' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\StaticCall' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Ternary' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Throw_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryMinus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\UnaryPlus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\YieldFrom' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Yield_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Coalesce' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\AssignOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BitwiseXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\BooleanOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Coalesce' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Concat' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Div' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Equal' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Greater' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\GreaterOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Identical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalAnd' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalOr' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\LogicalXor' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Minus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mod' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Mul' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\NotIdentical' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Plus' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Pow' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftLeft' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\ShiftRight' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Smaller' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\SmallerOrEqual' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\BinaryOp\\Spaceship' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Array_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Bool_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Double' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Int_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\Object_' => \true, 'PhabelVendor\\PhpParser\\Node\\Expr\\Cast\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\DNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\Encapsed' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\LNumber' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\String_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Class_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Dir' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\File' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Function_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Line' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Method' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Namespace_' => \true, 'PhabelVendor\\PhpParser\\Node\\Scalar\\MagicConst\\Trait_' => \true];
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Context;
use Phabel\Plugin;
use Phabel\Target\Php70\NullCoalesce\DisallowedExpressions;
use Phabel\Target\Php74\NullCoalesceAssignment;
use Phabel\Target\Php80\NullSafeTransformer;
use Phabel\Tools;
use PhabelVendor\PhpParser\Node\Expr;
use PhabelVendor\PhpParser\Node\Expr\ArrayDimFetch;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\BooleanAnd;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\NotIdentical;
use PhabelVendor\PhpParser\Node\Expr\Isset_;
use PhabelVendor\PhpParser\Node\Expr\PropertyFetch;
use PhabelVendor\PhpParser\Node\Expr\Ternary;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class NullCoalesceReplacer extends Plugin
{
    /**
     * Recursively extract bottom ArrayDimFetch.
     *
     * @param Expr $var
     * @return Expr
     */
    private static function &extractWorkVar(Expr &$var) : Expr
    {
        if ($var instanceof ArrayDimFetch) {
            return self::extractWorkVar($var->var);
        }
        if ($var instanceof PropertyFetch) {
            return self::extractWorkVar($var->var);
        }
        return $var;
    }
    /**
     * Replace null coalesce.
     *
     * @param Coalesce $node Coalesce
     *
     * @return Ternary
     */
    public function enter(Coalesce $node, Context $ctx) : Ternary
    {
        if (!Tools::hasSideEffects($workVar =& self::extractWorkVar($node->left)) && !isset(DisallowedExpressions::EXPRESSIONS[\get_class($node->left)])) {
            return new Ternary(new Isset_([$node->left]), $node->left, $node->right);
        }
        $valueCopy = $workVar;
        $check = new NotIdentical(Tools::fromLiteral(null), new Assign($workVar = $ctx->getVariable(), $valueCopy));
        return new Ternary($node->left === $workVar ? $check : new BooleanAnd($check, new Isset_([$node->left])), $node->left, $node->right);
    }
    /**
     *
     */
    public static function withPrevious(array $config) : array
    {
        return [NullCoalesceAssignment::class, NullSafeTransformer::class];
    }
}
<?php

namespace Phabel\Target\Php70;

use Phabel\Plugin;
use Phabel\Plugin\TypeHintReplacer;
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class ReturnTypeHints extends Plugin
{
    /**
     *
     */
    public static function previous(array $config) : array
    {
        return [TypeHintReplacer::class => ['return' => \true]];
    }
}
<?php

namespace Phabel;

/**
 * Various version headers.
 */
class Version
{
    /**
     * Latest git tag.
     */
    public const VERSION = '^1.0';
    /**
     * Latest revision.
     */
    public const LATEST = 0;
    /**
     * Changelog.
     */
    public const CHANGELOG = [0 => '<bold>Welcome! You can now use PHP 8 features in your code.</bold>

<bold>Config recap:</bold>
<bold>âœ…</bold> Source PHP version: <phabel>8.0</phabel>
<bold>âœ…</bold> Target PHP version: <phabel>auto</phabel> <bold>(7.1|7.2|7.3|7.4|8.0)</bold>
<bold>âœ…</bold> Dependency transpilation: <phabel>Enabled</phabel>

<phabel>To publish your composer package using phabel, run this command after git tagging a release:</phabel>
<bold>vendor/bin/phabel publish</bold>

<phabel>See https://phabel.io for documentation and more configuration parameters.</phabel>
<bold>Have fun!</bold>
'];
}
<?php

namespace Phabel;

use ReflectionMethod;
/**
 * Caches plugin information.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class PluginCache
{
    /**
     * Enter method names for each plugin.
     *
     * @var array<class-string<PluginInterface>, string[]>
     */
    private static array $enterMethods = [];
    /**
     * Leave method names.
     *
     * @var array<class-string<PluginInterface>, string[]>
     */
    private static array $leaveMethods = [];
    /**
     * Cache method information.
     *
     * @param class-string<PluginInterface> $plugin Plugin
     *
     * @return void
     */
    private static function cacheMethods(string $plugin) : void
    {
        if (!isset(self::$enterMethods[$plugin])) {
            self::$enterMethods[$plugin] = [];
            self::$leaveMethods[$plugin] = [];
            foreach (\get_class_methods($plugin) as $method) {
                if (\str_starts_with($method, 'enter')) {
                    $reflection = new ReflectionMethod($plugin, $method);
                    $type = $reflection->getParameters()[0]->getType()->getName();
                    self::$enterMethods[$plugin][$type][] = $method;
                } elseif (\str_starts_with($method, 'leave')) {
                    $reflection = new ReflectionMethod($plugin, $method);
                    $type = $reflection->getParameters()[0]->getType()->getName();
                    self::$leaveMethods[$plugin][$type][] = $method;
                }
            }
        }
    }
    /**
     * Return whether this plugin can be required by another plugin.
     *
     * If false, this plugin should only be extended by other plugins, to reduce complexity.
     *
     * @param class-string<PluginInterface> $plugin Plugin
     *
     * @return boolean
     */
    public static function canBeRequired(string $plugin) : bool
    {
        self::cacheMethods($plugin);
        return empty(self::$leaveMethods[$plugin]);
    }
    /**
     * Return whether this plugin is empty.
     *
     * @param class-string<PluginInterface> $plugin Plugin
     *
     * @return boolean
     */
    public static function isEmpty(string $plugin) : bool
    {
        self::cacheMethods($plugin);
        return empty(self::$leaveMethods[$plugin]) && empty(self::$enterMethods[$plugin]);
    }
    /**
     * Get enter methods array.
     *
     * @param class-string<PluginInterface> $plugin Plugin name
     *
     * @return array<string, string[]>
     */
    public static function enterMethods(string $plugin) : array
    {
        self::cacheMethods($plugin);
        return self::$enterMethods[$plugin];
    }
    /**
     * Get leave methods array.
     *
     * @param class-string<PluginInterface> $plugin Plugin name
     *
     * @return array<string, string[]>
     */
    public static function leaveMethods(string $plugin) : array
    {
        self::cacheMethods($plugin);
        return self::$leaveMethods[$plugin];
    }
    /**
     * Get previous requirements.
     *
     * @param class-string<PluginInterface> $plugin Plugin
     * @param array $config Config
     *
     * @return array<string, array>
     * @psalm-return array<class-string<PluginInterface>, array>
     */
    public static function previous(string $plugin, array $config) : array
    {
        $pluginConfig = $plugin . \json_encode($config);
        /** @var array<class-string<PluginInterface>, array<class-string<PluginInterface>, array>> */
        static $cache = [];
        if (isset($cache[$pluginConfig])) {
            return $cache[$pluginConfig];
        }
        return $cache[$pluginConfig] = self::simplify($plugin::previous($config));
    }
    /**
     * Get next requirements.
     *
     * @param class-string<PluginInterface> $plugin Plugin
     * @param array $config Config
     *
     * @return array<string, array>
     * @psalm-return array<class-string<PluginInterface>, array>
     */
    public static function next(string $plugin, array $config) : array
    {
        $pluginConfig = $plugin . \json_encode($config);
        /** @var array<class-string<PluginInterface>, array<class-string<PluginInterface>, array>> */
        static $cache = [];
        if (isset($cache[$pluginConfig])) {
            return $cache[$pluginConfig];
        }
        return $cache[$pluginConfig] = self::simplify($plugin::next($config));
    }
    /**
     * Get withPrevious requirements.
     *
     * @param class-string<PluginInterface> $plugin Plugin
     * @param array $config Config
     *
     * @return array<string, array>
     * @psalm-return array<class-string<PluginInterface>, array>
     */
    public static function withPrevious(string $plugin, array $config) : array
    {
        $pluginConfig = $plugin . \json_encode($config);
        /** @var array<class-string<PluginInterface>, array<class-string<PluginInterface>, array>> */
        static $cache = [];
        if (isset($cache[$pluginConfig])) {
            return $cache[$pluginConfig];
        }
        return $cache[$pluginConfig] = self::simplify($plugin::withPrevious($config));
    }
    /**
     * Get withNext requirements.
     *
     * @param class-string<PluginInterface> $plugin Plugin
     * @param array $config Config
     *
     * @return array<string, array>
     * @psalm-return array<class-string<PluginInterface>, array>
     */
    public static function withNext(string $plugin, array $config) : array
    {
        $pluginConfig = $plugin . \json_encode($config);
        /** @var array<class-string<PluginInterface>, array<class-string<PluginInterface>, array>> */
        static $cache = [];
        if (isset($cache[$pluginConfig])) {
            return $cache[$pluginConfig];
        }
        return $cache[$pluginConfig] = self::simplify($plugin::withNext($config));
    }
    /**
     * Simplify requirements.
     *
     * @param (array<class-string<PluginInterface>, array> | class-string<PluginInterface>[]) $requirements Requirements
     *
     * @return array<string, array>
     * @psalm-return array<class-string<PluginInterface>, array>
     */
    private static function simplify(array $requirements) : array
    {
        return isset($requirements[0]) ? \array_fill_keys($requirements, []) : $requirements;
    }
}
<?php

namespace Phabel;

class UnresolvedNameException extends \RuntimeException
{
    /**
     *
     */
    public function __construct()
    {
        parent::__construct('Cannot obtain FQDN from unresolved name!');
    }
}
<?php

namespace Phabel\Cli;

use Phabel\Composer\EventHandler as ComposerEventHandler;
use PhabelVendor\Symfony\Component\Console\Helper\ProgressBar;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutput;
class EventHandler extends ComposerEventHandler
{
    /**
     * Create simple CLI-based preconfigured instance.
     *
     * @return self
     */
    public static function create() : self
    {
        $output = new ConsoleOutput();
        return new self(new \Phabel\Cli\SimpleConsoleLogger($output), fn(int $max): ProgressBar => new ProgressBar($output, $max, -1));
    }
}
<?php

/*
 * This file is part of the Symfony package.
 *
 * (c) Fabien Potencier <fabien@symfony.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Phabel\Cli;

use PhabelVendor\Psr\Log\AbstractLogger;
use PhabelVendor\Psr\Log\InvalidArgumentException;
use PhabelVendor\Psr\Log\LogLevel;
use PhabelVendor\Symfony\Component\Console\Output\ConsoleOutputInterface;
use PhabelVendor\Symfony\Component\Console\Output\OutputInterface;
/**
 * PSR-3 compliant console logger.
 *
 * @author KÃ©vin Dunglas <dunglas@gmail.com>
 *
 * @see https://www.php-fig.org/psr/psr-3/
 */
class SimpleConsoleLogger extends AbstractLogger
{
    public const INFO = 'info';
    public const ERROR = 'error';
    private $verbosityLevelMap = [LogLevel::EMERGENCY => OutputInterface::VERBOSITY_NORMAL, LogLevel::ALERT => OutputInterface::VERBOSITY_NORMAL, LogLevel::CRITICAL => OutputInterface::VERBOSITY_NORMAL, LogLevel::ERROR => OutputInterface::VERBOSITY_NORMAL, LogLevel::WARNING => OutputInterface::VERBOSITY_NORMAL, LogLevel::NOTICE => OutputInterface::VERBOSITY_VERBOSE, LogLevel::INFO => OutputInterface::VERBOSITY_VERY_VERBOSE, LogLevel::DEBUG => OutputInterface::VERBOSITY_DEBUG];
    private $formatLevelMap = [LogLevel::EMERGENCY => self::ERROR, LogLevel::ALERT => self::ERROR, LogLevel::CRITICAL => self::ERROR, LogLevel::ERROR => self::ERROR, LogLevel::WARNING => self::INFO, LogLevel::NOTICE => self::INFO, LogLevel::INFO => self::INFO, LogLevel::DEBUG => self::INFO];
    private $errored = \false;
    /**
     *
     */
    public function __construct($output, array $verbosityLevelMap = [], array $formatLevelMap = [])
    {
        $this->output = $output;
        $this->verbosityLevelMap = $verbosityLevelMap + $this->verbosityLevelMap;
        $this->formatLevelMap = $formatLevelMap + $this->formatLevelMap;
    }
    private $output;
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    public function log($level, $message, array $context = [])
    {
        if (!isset($this->verbosityLevelMap[$level])) {
            throw new InvalidArgumentException(\sprintf('The log level "%s" does not exist.', $level));
        }
        $output = $this->output;
        // Write to the error output if necessary and available
        if (self::ERROR === $this->formatLevelMap[$level]) {
            if ($this->output instanceof ConsoleOutputInterface) {
                $output = $output->getErrorOutput();
            }
            $this->errored = \true;
        }
        // the if condition check isn't necessary -- it's the same one that $output will do internally anyway.
        // We only do it for efficiency here as the message formatting is relatively expensive.
        if ($output->getVerbosity() >= $this->verbosityLevelMap[$level]) {
            $output->writeln(\sprintf('<%1$s>%3$s</%1$s>', $this->formatLevelMap[$level], $level, $this->interpolate($message, $context)), $this->verbosityLevelMap[$level]);
        }
    }
    /**
     * Returns true when any messages have been logged at error levels.
     *
     * @return bool
     */
    public function hasErrored()
    {
        return $this->errored;
    }
    /**
     * Interpolates context values into the message placeholders.
     *
     * @author PHP Framework Interoperability Group
     */
    private function interpolate(string $message, array $context) : string
    {
        if (!\str_contains($message, '{')) {
            return $message;
        }
        $replacements = [];
        foreach ($context as $key => $val) {
            if (null === $val || \is_scalar($val) || \is_object($val) && \method_exists($val, '__toString')) {
                $replacements["{{$key}}"] = $val;
            } elseif ($val instanceof \DateTimeInterface) {
                $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339);
            } elseif (\is_object($val)) {
                $replacements["{{$key}}"] = '[object ' . \get_class($val) . ']';
            } else {
                $replacements["{{$key}}"] = '[' . \gettype($val) . ']';
            }
        }
        return \strtr($message, $replacements);
    }
}
<?php

namespace Phabel\Cli;

use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatter;
use PhabelVendor\Symfony\Component\Console\Formatter\OutputFormatterStyle;
class Formatter
{
    public const BANNER = "<bold>ï¼Šï¼Šï¼Šï¼Šï¼Šï¼Šï¼Šï¼Šï¼Š</>\n<bold>ï¼Š</bold><phabel> ï¼°ï½ˆï½�ï½‚ï½…ï½Œ </><bold>ï¼Š</bold>\n<bold>ï¼Šï¼Šï¼Šï¼Šï¼Šï¼Šï¼Šï¼Šï¼Š</>\n\n<phabel>PHP transpiler - Write and deploy modern PHP 8 code, today: https://phabel.io</phabel>";
    /**
     *
     */
    private static ?OutputFormatter $instance = null;
    /**
     *
     */
    public static function getFormatter() : OutputFormatter
    {
        if (!self::$instance) {
            self::$instance = new OutputFormatter(\true, ['bold' => new OutputFormatterStyle('white', 'default', ['bold']), 'phabel' => new OutputFormatterStyle('blue', 'default', ['bold']), 'error' => new OutputFormatterStyle('red', 'default', ['bold'])]);
        }
        return self::$instance;
    }
    /**
     *
     */
    public static function banner() : string
    {
        return self::getFormatter()->format(self::BANNER);
    }
}
<?php

namespace Phabel;

use Phabel\Target\Php74\ArrowClosure;
use PhabelVendor\PhpParser\BuilderHelpers;
use PhabelVendor\PhpParser\ErrorHandler\Throwing;
use PhabelVendor\PhpParser\NameContext;
use PhabelVendor\PhpParser\Node;
use PhabelVendor\PhpParser\Node\Expr\Array_;
use PhabelVendor\PhpParser\Node\Expr\ArrayDimFetch;
use PhabelVendor\PhpParser\Node\Expr\ArrowFunction;
use PhabelVendor\PhpParser\Node\Expr\Assign;
use PhabelVendor\PhpParser\Node\Expr\AssignOp;
use PhabelVendor\PhpParser\Node\Expr\AssignRef;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\BooleanAnd;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\BooleanOr;
use PhabelVendor\PhpParser\Node\Expr\BinaryOp\Coalesce;
use PhabelVendor\PhpParser\Node\Expr\BooleanNot;
use PhabelVendor\PhpParser\Node\Expr\Cast\Bool_;
use PhabelVendor\PhpParser\Node\Expr\Closure;
use PhabelVendor\PhpParser\Node\Expr\FuncCall;
use PhabelVendor\PhpParser\Node\Expr\List_;
use PhabelVendor\PhpParser\Node\Expr\MethodCall;
use PhabelVendor\PhpParser\Node\Expr\StaticCall;
use PhabelVendor\PhpParser\Node\Expr\Ternary;
use PhabelVendor\PhpParser\Node\Expr\Variable;
use PhabelVendor\PhpParser\Node\FunctionLike;
use PhabelVendor\PhpParser\Node\Name\FullyQualified;
use PhabelVendor\PhpParser\Node\Param;
use PhabelVendor\PhpParser\Node\Stmt\ClassLike;
use PhabelVendor\PhpParser\Node\Stmt\Else_;
use PhabelVendor\PhpParser\Node\Stmt\Expression;
use PhabelVendor\PhpParser\Node\Stmt\Foreach_;
use PhabelVendor\PhpParser\Node\Stmt\If_;
use PhabelVendor\PhpParser\NodeVisitor\NameResolver;
use PhabelVendor\PhpParser\PrettyPrinter\Standard;
use PhabelVendor\PhpParser\PrettyPrinterAbstract;
use SplStack;
/**
 * AST Context.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class Context
{
    /**
     * Parent nodes stack.
     *
     * @var SplStack<Node>
     */
    public SplStack $parents;
    /**
     * Declared variables stack.
     *
     * @var SplStack<VariableContext>
     */
    public SplStack $variables;
    /**
     * Name resolver.
     *
     * @var NameResolver
     */
    public NameResolver $nameResolver;
    /**
     * Pretty printer.
     */
    public PrettyPrinterAbstract $prettyPrinter;
    /**
     * PHPDOC parser.
     */
    public \Phabel\PhpDocParser $phpdocParser;
    /**
     * Arrow closure converter.
     */
    private ArrowClosure $converter;
    /**
     * Current file.
     */
    private string $file;
    /**
     * Current input file.
     */
    private string $inputFile;
    /**
     * Current output file.
     */
    private string $outputFile;
    /**
     * Constructor.
     */
    public function __construct()
    {
        /** @var SplStack<Node> */
        $this->parents = new SplStack();
        /** @var SplStack<VariableContext> */
        $this->variables = new SplStack();
        $this->converter = new ArrowClosure();
        $this->prettyPrinter = new Standard();
        $this->phpdocParser = new \Phabel\PhpDocParser();
        $this->nameResolver = new NameResolver(new Throwing(), ['preserveOriginalNames' => \false, 'replaceNodes' => \false]);
        $this->nameResolver->beforeTraverse([]);
    }
    /**
     * Push node to name resolver.
     *
     * @param Node $node
     * @return void
     */
    public function pushResolve(Node $node) : void
    {
        if (!$node instanceof FullyQualified) {
            $this->nameResolver->enterNode($node);
        }
    }
    /**
     * Push node.
     *
     * @param Node $node Node
     *
     * @return void
     */
    public function push(Node $node) : void
    {
        $this->parents->push($node);
        if ($node instanceof \Phabel\RootNode) {
            $this->variables->push(new \Phabel\VariableContext());
        }
        if ($node instanceof FunctionLike) {
            $variables = \array_fill_keys(\array_map(fn(Param $param): string => $param->var->name, $node->getParams()), \true);
            if ($node instanceof Closure) {
                foreach ($node->uses as $use) {
                    $variables[$use->var->name] = \true;
                    if ($use->byRef) {
                        $this->variables->top()->addVar($use->var->name);
                    }
                }
            } elseif ($node instanceof ArrowFunction) {
                $variables += $this->variables->top()->getVars();
            }
            $this->variables->push(new \Phabel\VariableContext($variables));
        } elseif ($node instanceof Assign || $node instanceof AssignOp || $node instanceof AssignRef) {
            $this->populateVars($node->var);
        } elseif ($node instanceof Foreach_) {
            if ($node->keyVar) {
                $this->populateVars($node->keyVar);
            }
            $this->populateVars($node->valueVar);
        } elseif ($node instanceof MethodCall || $node instanceof StaticCall || $node instanceof FuncCall) {
            // Cover reference parameters
            foreach ($node->args as $argument) {
                $argument = $argument->value;
                while ($argument instanceof ArrayDimFetch && $argument->var instanceof ArrayDimFetch) {
                    $argument = $argument->var;
                }
                if ($argument instanceof Variable && \is_string($argument->name)) {
                    $this->variables->top()->addVar($argument->name);
                }
            }
        }
    }
    /**
     * Populate variables.
     *
     * @return void
     */
    private function populateVars(Node $node) : void
    {
        while ($node instanceof ArrayDimFetch && $node->var instanceof ArrayDimFetch) {
            $node = $node->var;
        }
        if ($node instanceof Variable && \is_string($node->name)) {
            $this->variables->top()->addVar($node->name);
        } elseif ($node instanceof List_ || $node instanceof Array_) {
            foreach ($node->items as $item) {
                if ($item) {
                    $this->populateVars($item->value);
                }
            }
        }
    }
    /**
     * Pop node.
     *
     * @return void
     */
    public function pop() : void
    {
        $popped = $this->parents->pop();
        if ($popped instanceof \Phabel\RootNode || $popped instanceof FunctionLike) {
            $poppedVars = $this->variables->pop();
            if ($popped instanceof ArrowFunction) {
                $this->variables->top()->addVars($poppedVars->getVars());
            }
        }
    }
    /**
     * Return new unoccupied variable.
     *
     * @return Variable
     */
    public function getVariable() : Variable
    {
        return new Variable($this->variables->top()->getVar());
    }
    /**
     * Get child currently being iterated on.
     *
     * @param Node $node
     * @return Node
     */
    public static function getCurrentChild(Node $node) : Node
    {
        return self::getCurrentChildByRef($node);
    }
    /**
     * Get child currently being iterated on, by reference.
     *
     * @param Node $node
     * @return Node
     */
    public static function &getCurrentChildByRef(Node $node) : Node
    {
        if (!($subNode = $node->getAttribute('currentNode'))) {
            throw new \RuntimeException('Node is not a part of the current AST stack!');
        }
        $child =& $node->{$subNode};
        if (null !== ($index = $node->getAttribute('currentNodeIndex'))) {
            return $child[$index];
        }
        return $child;
    }
    /**
     * Insert nodes before node.
     *
     * @param Node $node Node before which to insert nodes
     * @param Node ...$insert Nodes to insert
     * @return void
     */
    public function insertBefore(Node $node, Node ...$insert) : void
    {
        if (empty($insert)) {
            return;
        }
        $found = \false;
        foreach ($this->parents as $cur) {
            if ($found) {
                $parent =& $this->getCurrentChildByRef($cur);
                break;
            }
            if ($this->getCurrentChild($cur) === $node) {
                $found = \true;
                if ($cur instanceof \Phabel\RootNode) {
                    $parent =& $this->parents[\count($this->parents) - 1];
                    break;
                }
            }
        }
        if (!$found) {
            throw new \RuntimeException('Node is not a part of the current AST stack!');
        }
        /** @var string */
        $parentKey = $parent->getAttribute('currentNode');
        if ($parentKey === 'stmts' && !$parent instanceof ClassLike) {
            /** @var int */
            $nodeKeyIndex = $parent->getAttribute('currentNodeIndex');
            \array_splice($parent->{$parentKey}, $nodeKeyIndex, 0, $insert);
            $parent->setAttribute('currentNodeIndex', $nodeKeyIndex + \count($insert));
            return;
            // Done, inserted!
        }
        // Cannot insert, parent is not a statement
        //
        // If we insert before a conditional branch of a conditional expression,
        //   make sure the conditional branch has no side effects;
        //   if it does, turn the entire conditional expression into an if, and bubble it up
        //
        // Unless we want to go crazy, do not consider side effect evaluation order for stuff like function call arguments, maths and so on.
        //
        if ($parent instanceof BooleanOr && $parentKey === 'right' && \Phabel\Tools::hasSideEffects($parent->right)) {
            $result = $this->getVariable();
            $insert = new If_($parent->left, ['stmts' => [new Assign($result, BuilderHelpers::normalizeValue(\true))], 'else' => new Else_([...$insert, new Assign($result, new Bool_($parent->right))])]);
            $parent = $result;
        } elseif ($parent instanceof BooleanAnd && $parentKey === 'right' && \Phabel\Tools::hasSideEffects($parent->right)) {
            $result = $this->getVariable();
            $insert = new If_($parent->left, ['stmts' => [...$insert, new Assign($result, new Bool_($parent->right))], 'else' => new Else_([new Assign($result, BuilderHelpers::normalizeValue(\false))])]);
            $parent = $result;
        } elseif ($parent instanceof Ternary && $parentKey !== 'cond' && (\Phabel\Tools::hasSideEffects($parent->if) || \Phabel\Tools::hasSideEffects($parent->else))) {
            $result = $this->getVariable();
            if (!$parent->if) {
                // ?:
                $insert = new If_(new BooleanNot(new Assign($result, $parent->cond)), ['stmts' => [...$insert, new Assign($result, $parent->else)]]);
            } else {
                $insert = new If_($parent->cond, ['stmts' => [...$parentKey === 'left' ? $insert : [], new Assign($result, $parent->if)], 'else' => new Else_([...$parentKey === 'right' ? $insert : [], new Assign($result, $parent->else)])]);
            }
            $parent = $result;
        } elseif ($parent instanceof Coalesce && $parentKey === 'right' && \Phabel\Tools::hasSideEffects($parent->right)) {
            $result = $this->getVariable();
            $insert = new If_(\Phabel\Plugin::call('is_null', new Assign($result, $parent->left)), ['stmts' => [...$insert, new Assign($result, $parent->right)]]);
            $parent = $result;
        }
        $this->insertBefore($parent, ...\is_array($insert) ? $insert : [$insert]);
    }
    /**
     * Insert nodes after node.
     *
     * @param Node $node Node ater which to insert nodes
     * @param Node ...$nodes Nodes to insert
     * @return void
     */
    public function insertAfter(Node $node, Node ...$nodes) : void
    {
        if (empty($nodes)) {
            return;
        }
        $found = \false;
        foreach ($this->parents as $parent) {
            if ($this->getCurrentChild($parent) === $node) {
                $found = \true;
                break;
            }
        }
        if (!$found) {
            throw new \RuntimeException('Node is not a part of the current AST stack!');
        }
        $subNode = $parent->getAttribute('currentNode');
        $subNodeIndex = $parent->getAttribute('currentNodeIndex');
        \array_splice($parent->{$subNode}, $subNodeIndex + 1, 0, $nodes);
    }
    /**
     * Gets name context.
     *
     * @return NameContext
     */
    public function getNameContext() : NameContext
    {
        return $this->nameResolver->getNameContext();
    }
    /**
     * Check if the parent node is a statement.
     *
     * @return bool
     */
    public function isParentStmt() : bool
    {
        $parent = $this->parents[0];
        return $parent instanceof Expression || $parent->getAttribute('currentNode') === 'stmts';
    }
    /**
     * Dumps AST.
     */
    public function dumpAst(Node $stmt) : string
    {
        return $this->prettyPrinter->prettyPrint($stmt instanceof \Phabel\RootNode ? $stmt->stmts : [$stmt]);
    }
    /**
     * Convert a function to a closure.
     */
    public function toClosure(FunctionLike &$func) : void
    {
        if ($func instanceof ArrowFunction) {
            $func = $this->converter->enter($func, $this);
        }
    }
    /**
     * Get absolute path of current output file.
     *
     * @return string
     */
    public function getOutputFile() : string
    {
        return $this->outputFile;
    }
    /**
     * Set absolute path of current input file.
     *
     * @param string $inputFile Current input file.
     *
     * @return self
     */
    public function setInputFile(string $inputFile) : self
    {
        $this->inputFile = $inputFile;
        return $this;
    }
    /**
     * Get absolute path of current input file.
     *
     * @return string
     */
    public function getInputFile() : string
    {
        return $this->inputFile;
    }
    /**
     * Set absolute path of current output file.
     *
     * @param string $outputFile Current output file.
     *
     * @return self
     */
    public function setOutputFile(string $outputFile) : self
    {
        $this->outputFile = $outputFile;
        return $this;
    }
}
<?php

namespace Phabel;

use SplStack;
final class ExceptionWrapper
{
    /**
     *
     */
    private SplStack $params;
    /**
     *
     */
    public function __construct(\Throwable $e)
    {
        $this->params = new SplStack();
        do {
            $this->params->push([$e->getMessage(), $e->getCode(), $e->getFile(), $e->getLine(), $e->__toString()]);
        } while ($e = $e->getPrevious());
    }
    /**
     *
     */
    public function getException() : \Phabel\Exception
    {
        $previous = null;
        foreach ($this->params as [$message, $code, $file, $line, $trace]) {
            $previous = new \Phabel\Exception($message, $code, $previous, $file, $line);
            $previous->setTrace($trace);
        }
        return $previous;
    }
}
{
    "minimum-stability": "dev",
    "prefer-stable": true,
    "require-dev": {
        "humbug/php-scoper": "^0.15.0",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^7|^8|^9",
        "phpunit/php-code-coverage": "*"
    }
}<?php

require 'tools/ci/functions.php';
$versions = (require 'tools/ci/versions.php');
if ($argc < 2) {
    die("Need a tag name!" . PHP_EOL);
}
$tag = \escapeshellarg($argv[1]);
r("git pull");
r("git checkout master");
foreach ($versions as $version) {
    r("git branch -D master-{$version} || true");
    r("git checkout master-{$version}");
    r("git tag {$tag}.{$version}");
    r("git push origin {$tag}.{$version}");
}
r("git checkout master");
<?php

/**
 * This file generates a set of functions, closures and arrow functions with specific type hints, to test the typehint replacer.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
if (PHP_MAJOR_VERSION < 8) {
    echo "This generator can only run on PHP 8.0+" . PHP_EOL;
    die(1);
}
const CLAZZ = "PhabelTest\\Target\\TypeHintReplacerTest";
/**
 *
 */
function escapeRegex(string $in): string
{
    return \var_export('~' . \str_replace(['\\', '(', ')', '$', '?', '|'], ['\\\\', '\\(', '\\)', '\\$', '\\?', '\\|'], $in) . '~', true);
}
/**
 *
 */
function getErrorMessage(string $scalarParam, string $scalar, string $scalarSane, $wrongVal, string $to): array
{
    try {
        $f = eval("return new class { public function r() { return fn ({$scalarParam} \$data): {$scalar} => \$data; }};");
        $f->r()(eval("return {$wrongVal};"));
    } catch (\Throwable $e) {
        $message = $e->getMessage();
        $message = \str_replace("self", CLAZZ, $message);
        $message = \preg_replace(["/called in .*/", "/.*: /"], ".*", $message);
        if (\preg_match_all("/must be of type (\\S+)/", $message, $matches)) {
            foreach ($matches[1] as $match) {
                $message = \str_replace($match, \str_replace("class@anonymous", CLAZZ, $match), $message);
            }
        }
        $closureMessage = \str_replace("{$to} class@anonymous::{closure}", "{$to} " . CLAZZ . "::PhabelTest\\Target\\{closure}", $message);
        $methodMessage = \str_replace("{$to} class@anonymous::{closure}", "{$to} " . CLAZZ . "::test{$scalarSane}", $message);
        $funcMessage = \str_replace("{$to} class@anonymous::{closure}", "{$to} PhabelTest\\Target\\test{$scalarSane}", $message);
    }
    return [escapeRegex($closureMessage), escapeRegex($methodMessage), escapeRegex($funcMessage)];
}
$SCALARS = ['callable' => ['"is_null"', 'fn (): int => 0', '[$this, "noop"]', '[self::class, "noop"]'], 'array' => ["['lmao']", 'array()'], 'bool' => ["true", "false", '0', '1', '"0"', '"1"', '""', '"aaaa"'], 'iterable' => ["['lmao']", 'array()', '(fn (): \\Generator => yield)()'], 'float' => ["123", "-1", "123.123", "1e3", "true", "false", "'123'", '"123.123"'], 'object' => ["new class{}", '$this'], 'string' => ["'lmao'", 'new class{public function __toString() { return "lmao"; }}', "123", "-1", "123.123", "1e3", "true", "false"], 'self' => ['$this'], 'int' => ["123", "-1", "123.0", "1e3", "true", "false", "'123'", "'123.0'"], '\\' . CLAZZ => ['$this'], '\\Generator' => ['(fn (): \\Generator => yield)()']];
$count = \count($SCALARS);
$k = 0;
foreach ($SCALARS as $scalar => $val) {
    $SCALARS["?{$scalar}"] = [...$val, 'null'];
    $k = ($k + 1) % $count;
    $nextScalar = \array_keys($SCALARS)[$k];
    $nextVal = $SCALARS[$nextScalar];
    $SCALARS["{$scalar}|{$nextScalar}"] = [...$val, ...$nextVal];
}
foreach (\glob("testsGenerated/Target/TypeHintReplacer*") as $file) {
    \unlink($file);
}
$closures = [];
$closuresRet = [];
$classFuncs = '';
$funcs = '';
$k = 0;
$count = 0;
foreach ($SCALARS as $scalar => $vals) {
    foreach ($vals as $val) {
        $self = \strpos($scalar, 'self') !== false;
        $scalarSane = $k++ . \preg_replace("~[^A-Za-z]*~", "", $scalar);
        $wrongVal = \strpos($scalar, 'object') !== false ? 0 : 'new class{}';
        if ($scalar === 'float|object' || $scalar === 'object|string') {
            $wrongVal = 'null';
        }
        [$closureMessage, $methodMessage, $funcMessage] = getErrorMessage($scalar, $scalar, $scalarSane, $wrongVal, "to");
        $closures[] = "[fn ({$scalar} \$data): {$scalar} => \$data, {$val}, {$wrongVal}, {$closureMessage}]";
        $closures[] = "[function ({$scalar} \$data): {$scalar} { return \$data; }, {$val}, {$wrongVal}, {$closureMessage}]";
        $closures[] = "[[\$this, 'test{$scalarSane}'], {$val}, {$wrongVal}, {$methodMessage}]";
        $closures[] = "[[self::class, 'test{$scalarSane}'], {$val}, {$wrongVal}, {$methodMessage}]";
        if (!$self) {
            $closures[] = "['PhabelTest\\Target\\test{$scalarSane}', {$val}, {$wrongVal}, {$funcMessage}]";
        }
        $classFuncs .= "private static function test{$scalarSane}({$scalar} \$data): {$scalar} { return \$data; }\n";
        if (!$self) {
            $funcs .= "function test{$scalarSane}({$scalar} \$data): {$scalar} { return \$data; }\n";
        }
        [$closureMessage, $methodMessage, $funcMessage] = getErrorMessage("", $scalar, "Ret{$scalarSane}", $wrongVal, "value of");
        $closuresRet[] = "[fn (\$data): {$scalar} => \$data, {$val}, {$wrongVal}, {$closureMessage}]";
        $closuresRet[] = "[function (\$data): {$scalar} { return \$data; }, {$val}, {$wrongVal}, {$closureMessage}]";
        $closuresRet[] = "[[\$this, 'testRet{$scalarSane}'], {$val}, {$wrongVal}, {$methodMessage}]";
        $closuresRet[] = "[[self::class, 'testRet{$scalarSane}'], {$val}, {$wrongVal}, {$methodMessage}]";
        if (!$self) {
            $closuresRet[] = "['PhabelTest\\Target\\testRet{$scalarSane}', {$val}, {$wrongVal}, {$funcMessage}]";
        }
        $classFuncs .= "private static function testRet{$scalarSane}(\$data): {$scalar} { return \$data; }\n";
        if (!$self) {
            $funcs .= "function testRet{$scalarSane}(\$data): {$scalar} { return \$data; }\n";
        }
        if (!($count++ % 5)) {
            $i = ($count - 1) / 5;
            $i .= "Test";
            $provider = "[\n" . \implode(",\n", $closures) . "];\n";
            $providerRet = "[\n" . \implode(",\n", $closuresRet) . "];\n";
            $template = <<<EOF
<?php

namespace PhabelTest\\Target;

use PHPUnit\\Framework\\TestCase;

{$funcs}

/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
class TypeHintReplacer{$i} extends TestCase
{
    /**
     * @dataProvider returnDataProvider
     */
    public function testRet(callable \$c, \$data, \$wrongData, string \$exception) {
        \$this->assertTrue(\$data == \$c(\$data));

        \$this->expectExceptionMessageMatches(\$exception);
        \$c(\$wrongData);
    }
    public function returnDataProvider(): array
    {
        return {$providerRet};
    }
    /**
     * @dataProvider paramDataProvider
     */
    public function test(callable \$c, \$data, \$wrongData, string \$exception) {
        \$this->assertTrue(\$data == \$c(\$data));

        \$this->expectExceptionMessageMatches(\$exception);
        \$c(\$wrongData);
    }
    public function paramDataProvider(): array
    {
        return {$provider};
    }
    
    public static function noop() {}
    
    {$classFuncs}
}
EOF;
            $template = \str_replace("TypeHintReplacerTest", "TypeHintReplacer{$i}", $template);
            $classFuncs = '';
            $funcs = '';
            $closures = [];
            $closuresRet = [];
            \file_put_contents("testsGenerated/Target/TypeHintReplacer{$i}.php", $template);
        }
    }
}
<?php

use Amp\Parallel\Worker\DefaultPool;
use Phabel\Cli\EventHandler;
use Phabel\Plugin\PhabelTestGenerator;
use Phabel\Plugin\TypeHintReplacer;
use Phabel\Target\Php;
use Phabel\Traverser;
use SebastianBergmann\CodeCoverage\Driver\Selector;
use SebastianBergmann\CodeCoverage\Filter;
use function Amp\Parallel\Worker\pool;

require_once 'vendor/autoload.php';
$canCoverage = false;
try {
    $filter = new Filter();
    $filter->includeDirectory(\realpath(__DIR__ . '/../src'));
    (new Selector())->forLineCoverage($filter);
    $canCoverage = true;
} catch (\Throwable $e) {
}
if ($canCoverage) {
    pool(new DefaultPool(\getenv('CI') ? 3 : \count(Php::VERSIONS) + 2));
}
const BASE = \PhabelTest\Target\TypeHintReplacerTest::class;
$packages = [];
$packagesSecondary = [];
foreach (Php::VERSIONS as $version) {
    $types = ['callable', 'iterable', 'object', 'self', 'static', 'int', 'float', 'array', 'string', 'bool', \Generator::class, \str_replace("Target", "Target{$version}", \PhabelTest\Target\TypeHintReplacerTest::class)];
    foreach (\glob("testsGenerated/Target/TypeHintReplacer*") as $test) {
        \preg_match("~(TypeHintReplacer\\d+Test)~", $test, $matches);
        $types[] = BASE;
        $types[] = $r = \str_replace("TypeHintReplacerTest", $matches[1], BASE);
        $types[] = \str_replace("Target", "Target{$version}", BASE);
        $types[] = \str_replace("Target", "Target{$version}", $r);
    }
    `rm -rf "testsGenerated/Target{$version}"`;
    `rm -rf "testsGenerated/Target10{$version}"`;
    $packages += (new Traverser(EventHandler::create()))->setPlugins([PhabelTestGenerator::class => ['target' => $version], TypeHintReplacer::class => ['union' => true, 'nullable' => true, 'return' => true, 'types' => $types]])->setInput('testsGenerated/Target')->setOutput("testsGenerated/Target{$version}")->setCoverage("expr{$version}")->runAsync();
    $packagesSecondary += (new Traverser(EventHandler::create()))->setPlugins([PhabelTestGenerator::class => ['target' => 1000 + $version]])->setInput("testsGenerated/Target{$version}")->setOutput("testsGenerated/Target10{$version}")->setCoverage("expr10{$version}")->runAsync();
}
$binary = PHP_SAPI === 'phpdbg' ? PHP_BINARY . " -qrr" : PHP_BINARY;
$current = (int) (PHP_MAJOR_VERSION . PHP_MINOR_VERSION);
foreach (\glob("testsGenerated/*/*.php") as $i => $test) {
    $version = (int) \Phabel\Target\Php80\Polyfill::substr(\basename(\dirname($test)), 6);
    $version = $version ?: 80;
    if ($version > $current) {
        continue;
    }
    echo $test . PHP_EOL;
    \passthru("{$binary} vendor/bin/phpunit -c phpunit-expr.xml {$test} --coverage-php=coverage/phpunitExpr{$i}.php", $ret);
    if ($ret) {
        die($ret);
    }
}
<?php

/**
 * Dump AST of file.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
use PhpParser\ParserFactory;
use PhpParser\PrettyPrinter\Standard;

require 'vendor/autoload.php';
if ($argc < 2) {
    echo "Usage: {$argv[0]} file.php\n";
    die(1);
}
$parser = (new ParserFactory())->create(ParserFactory::PREFER_PHP7);
//$parser = (new ParserFactory)->create(ParserFactory::ONLY_PHP5);
\var_dump($a = $parser->parse(\file_get_contents($argv[1])));
\var_dumP((new Standard())->prettyPrint($a));
<?php

/**
 * This file generates an array containing all possible expression nodes, generated using default parameters.
 * Then, for each expression that accepts another expression as subnode, it tries to use all the expressions generated in the previous step,
 *  for each subnode, to test compatibility with various versions of the PHP lexer.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
use HaydenPierce\ClassFinder\ClassFinder;
use Phabel\Plugin\IssetExpressionFixer;
use Phabel\Plugin\NestedExpressionFixer;
use Phabel\Target\Php;
use Phabel\Tools;
use PhpParser\Builder\Class_;
use PhpParser\Builder\Method;
use PhpParser\Builder\Namespace_;
use PhpParser\Builder\Use_;
use PhpParser\Internal\PrintableNewAnonClassNode;
use PhpParser\Node;
use PhpParser\Node\Arg;
use PhpParser\Node\Expr;
use PhpParser\Node\Expr\Array_;
use PhpParser\Node\Expr\ArrayItem;
use PhpParser\Node\Expr\ArrowFunction;
use PhpParser\Node\Expr\AssignRef;
use PhpParser\Node\Expr\BinaryOp\LogicalAnd;
use PhpParser\Node\Expr\BinaryOp\LogicalOr;
use PhpParser\Node\Expr\BinaryOp\LogicalXor;
use PhpParser\Node\Expr\BitwiseNot;
use PhpParser\Node\Expr\Cast\Unset_;
use PhpParser\Node\Expr\Error;
use PhpParser\Node\Expr\Exit_;
use PhpParser\Node\Expr\Isset_;
use PhpParser\Node\Expr\List_;
use PhpParser\Node\Expr\MethodCall;
use PhpParser\Node\Expr\New_;
use PhpParser\Node\Expr\Print_;
use PhpParser\Node\Expr\PropertyFetch;
use PhpParser\Node\Expr\StaticCall;
use PhpParser\Node\Expr\StaticPropertyFetch;
use PhpParser\Node\Expr\UnaryMinus;
use PhpParser\Node\Expr\UnaryPlus;
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Expr\Yield_;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name;
use PhpParser\Node\Scalar\EncapsedStringPart;
use PhpParser\Node\Stmt\Class_ as StmtClass_;
use PhpParser\Node\Stmt\Expression;
use PhpParser\Node\Stmt\Use_ as StmtUse_;
use PhpParser\Node\VarLikeIdentifier;
use PhpParser\PrettyPrinter\Standard;

require_once 'vendor/autoload.php';
foreach (Php::VERSIONS as $version) {
    if (empty(\shell_exec("which php{$version} 2>&1"))) {
        echo "Could not find PHP {$version}!" . PHP_EOL;
        die(1);
    }
}
class ExpressionGenerator
{
    /**
     *
     */
    private Standard $printer;
    /**
     *
     */
    private function format(Node $code)
    {
        static $count = 0;
        $count++;
        $code = (new Class_("lmao{$count}"))->addStmt((new Method("te"))->addStmt($code)->getNode())->getNode();
        return $this->printer->prettyPrintFile([$code]);
    }
    /**
     *
     */
    private function readUntilPrompt($resource)
    {
        $data = \fread($resource, 6);
        while (!\str_ends_with($data, "php > ")) {
            $data .= \fread($resource, 1);
        }
        return \Phabel\Target\Php80\Polyfill::substr($data, 0, -6);
    }
    /**
     *
     */
    private array $robin = [];
    /**
     *
     */
    private array $processes = [];
    /**
     *
     */
    private array $pipes = [];
    /**
     *
     */
    private function checkSyntaxVersion(int $version, string $code)
    {
        $code = \str_replace(["\n", '<?php'], '', $code) . "\n";
        $x = $this->robin[$version];
        $this->robin[$version]++;
        $this->robin[$version] %= \count($this->pipes[$version]);
        \fputs($this->pipes[$version][$x][0], $code);
        $result = $this->readUntilPrompt($this->pipes[$version][$x][1]);
        $result = \str_replace(['{', '}'], '', \Phabel\Target\Php80\Polyfill::substr(\preg_replace('#\\x1b[[][^A-Za-z]*[A-Za-z]#', '', $result), \strlen($code)));
        $result = \trim($result);
        //var_dump($code, "Result for $version is: $result");
        return \strlen($result) === 0;
    }
    /**
     *
     */
    private function checkSyntax(string $code, int $startFrom = 56)
    {
        if (!$startFrom) {
            return $startFrom;
        }
        foreach (Php::VERSIONS as $version) {
            if ($version < $startFrom) {
                continue;
            }
            if ($this->checkSyntaxVersion($version, $code)) {
                return $version;
            }
        }
        return 0;
    }
    private $result = [
        'main' => [],
        // Needs adaptation for nested expressions
        'isset' => [],
    ];
    /**
     * @psalm-var array<int, array<int, Node>>
     */
    private array $tests = [];
    private $versionMap = [];
    /**
     *
     */
    private function checkPossibleValue($arg, $name, $key, $class, $baseArgs, $isArray)
    {
        $subVersion = \max($this->versionMap[\get_debug_type($arg)] ?? 0, $this->versionMap[$class]);
        $arguments = $baseArgs;
        $arguments[$key] = $isArray ? [$arg] : $arg;
        $code = $this->format($prev = new $class(...$arguments));
        $curVersion = $this->checkSyntax($code, $subVersion);
        if ($curVersion && $curVersion !== $subVersion) {
            $this->result['main'][$curVersion][$class][$name][\get_debug_type($arg)] = true;
            echo "Min {$curVersion} for {$code}\n";
        }
        if ($curVersion && !($class === AssignRef::class && $arg instanceof New_) && !($class === Yield_::class && $name === 'key' && ($arg instanceof LogicalAnd || $arg instanceof LogicalOr || $arg instanceof LogicalXor)) && !(\in_array($class, [MethodCall::class, StaticCall::class]) && $name === 'name' && ($arg instanceof Array_ || $arg instanceof Print_)) && !(\in_array($class, [UnaryPlus::class, UnaryMinus::class, BitwiseNot::class]) && $arg instanceof Array_) && !(\in_array($class, [Variable::class, StaticPropertyFetch::class, PropertyFetch::class]) && $arg instanceof Array_)) {
            $this->tests[] = $prev;
        }
        $code = $this->format(new Isset_([$prev]));
        $curVersion = $this->checkSyntax($code, $subVersion);
        if ($curVersion && $curVersion !== $subVersion) {
            $this->result['isset'][$curVersion][$class][$name][\get_debug_type($arg)] = true;
            echo "Min {$curVersion} for {$code}\n";
        }
        if ($curVersion && !(\in_array($class, [Variable::class, StaticPropertyFetch::class, PropertyFetch::class]) && $arg instanceof Array_)) {
            $this->tests[] = new Isset_([$prev]);
        }
    }
    /**
     *
     */
    public function run()
    {
        $this->printer = new Standard(['shortArraySyntax' => true]);
        foreach (Php::VERSIONS as $version) {
            $cmd = "php{$version} -a 2>&1";
            $this->pipes[$version] = [];
            $this->processes[$version] = [];
            $this->robin[$version] = 0;
            for ($x = 0; $x < 15; $x++) {
                $this->processes[$version][$x] = \proc_open($cmd, [0 => ['pipe', 'r'], 1 => ['pipe', 'w']], $this->pipes[$version][$x]);
                $this->readUntilPrompt($this->pipes[$version][$x][1]);
            }
        }
        /** @var ReflectionClass[] */
        $expressions = [];
        foreach (ClassFinder::getClassesInNamespace('PhpParser', ClassFinder::RECURSIVE_MODE) as $class) {
            $class = new ReflectionClass($class);
            if ($class->isSubclassOf(Expr::class) && !$class->isAbstract() && $class->getName() !== PrintableNewAnonClassNode::class && $class->getName() !== ArrowFunction::class && $class->getName() !== Error::class && $class->getName() !== List_::class && $class->getName() !== ArrayItem::class && $class->getName() !== EncapsedStringPart::class && $class->getName() !== Exit_::class && $class->getName() !== Unset_::class) {
                $expressions[] = $class;
            }
        }
        $instanceArgs = [];
        $instanceArgNames = [];
        $instanceArgTypes = [];
        $exprInstances = [];
        foreach ($expressions as $expr) {
            $class = $expr->getName();
            $method = $expr->getMethod('__construct');
            if ($method->getNumberOfParameters() === 1) {
                $exprInstances[$class] = $expr->newInstance();
                continue;
                // Is a magic constant or such
            }
            \preg_match_all('/@param (?<type>\\S+) +\\$(?<name>\\S+)/', $method->getDocComment(), $matches);
            $types = \array_combine($matches['name'], $matches['type']);
            foreach ($types as &$type) {
                $type = \explode("|", $type);
                foreach ($type as $key => &$subtype) {
                    if (\str_starts_with($subtype, 'Node')) {
                        $subtype = 'PhpParser\\' . $subtype;
                    } elseif ($subtype === 'Error') {
                        unset($type[$key]);
                    } elseif ($subtype === 'Identifier') {
                        $subtype = Identifier::class;
                    } elseif ($subtype === 'Name') {
                        $subtype = Name::class;
                    } elseif ($subtype === 'Expr') {
                        $subtype = Expr::class;
                    } elseif ($subtype === 'VarLikeIdentifier') {
                        $subtype = VarLikeIdentifier::class;
                    }
                }
            }
            $params = $method->getParameters();
            $hasExpr = false;
            $arguments = [];
            $argNames = [];
            $argTypes = [];
            foreach ($params as $key => $param) {
                $paramStr = (string) $param->getType();
                $argNames[] = $param->getName();
                switch ($paramStr) {
                    case Expr::class:
                        $argTypes[$key] = [false, [Expr::class]];
                        $arguments[] = new Variable("test");
                        break;
                    case Variable::class:
                        $arguments[] = new Variable("test");
                        break;
                    case Name::class:
                        $arguments[] = new Name('self');
                        break;
                    case 'array':
                        if (\in_array('Expr[]', $types[$param->getName()] ?? [])) {
                            $argTypes[$key] = [true, [Expr::class]];
                            $arguments[] = [new Variable('test')];
                        } else {
                            $arguments[] = [];
                        }
                        break;
                    case 'bool':
                        $arguments[] = false;
                        break;
                    case 'float':
                    case 'int':
                        $arguments[] = 0;
                        break;
                    case 'string':
                        $arguments[] = 'test';
                        break;
                    default:
                        $argTypes[$key] = [false, $types[$param->getName()]];
                        $arguments[] = new Variable("test");
                        break;
                }
            }
            $exprInstances[$class] = $expr->newInstanceArgs($arguments);
            if (\count($argTypes)) {
                $instanceArgs[$class] = $arguments;
                $instanceArgNames[$class] = $argNames;
                $instanceArgTypes[$class] = $argTypes;
            }
        }
        $disallowedIssetExprs = [];
        foreach ($exprInstances as $expr) {
            if (!$this->checkSyntaxVersion(56, $this->format(new Isset_([$expr])))) {
                $disallowedIssetExprs[\get_class($expr)] = true;
            }
        }
        $disallowedIssetExprs = \var_export($disallowedIssetExprs, true);
        $disallowedIssetExprs = <<<PHP
<?php

namespace Phabel\\Target\\Php70\\NullCoalesce;

use Phabel\\Plugin;

abstract class DisallowedExpressions extends Plugin
{
    const EXPRESSIONS = {$disallowedIssetExprs};
}
PHP;
        \file_put_contents("src/Target/Php70/NullCoalesce/DisallowedExpressions.php", $disallowedIssetExprs);
        foreach ($exprInstances as $class => $instance) {
            $this->versionMap[$class] = $this->checkSyntax($this->format($instance)) ?: 1000;
        }
        $wait = [];
        foreach ($instanceArgTypes as $class => $argTypes) {
            $baseArgs = $instanceArgs[$class];
            foreach ($argTypes as $key => [$isArray, $types]) {
                $name = $instanceArgNames[$class][$key];
                $possibleValues = [];
                foreach ($types as $type) {
                    switch ($type) {
                        case Expr::class:
                            $possibleValues = \array_merge($possibleValues, $exprInstances);
                            break;
                        case Name::class:
                            $possibleValues[] = new Name('self');
                            break;
                        case Variable::class:
                            $possibleValues[] = new Variable("test");
                            break;
                        case Identifier::class:
                            $possibleValues[] = new Identifier('test');
                            break;
                        case VarLikeIdentifier::class:
                            $possibleValues[] = new Identifier('test');
                            break;
                        case StmtClass_::class:
                            // Avoid using anonymous classes
                            //$possibleValues[] = new StmtClass_(null);
                            break;
                        case 'string':
                            $possibleValues[] = 'test';
                            break;
                        case 'null':
                            $possibleValues[] = null;
                            break;
                        default:
                            throw new Exception($type);
                    }
                }
                foreach ($possibleValues as $arg) {
                    $this->checkPossibleValue($arg, $name, $key, $class, $baseArgs, $isArray);
                }
            }
        }
        $keys = [];
        foreach ($this->result['main'] as $version) {
            $keys = \array_merge_recursive($keys, $version);
        }
        foreach ($keys as &$values) {
            $values = \array_keys($values);
        }
        foreach (Php::VERSIONS as $version) {
            foreach (['NestedExpressionFixer', 'IssetExpressionFixer'] as $name) {
                $code = <<<PHP
<?php

namespace Phabel\\Target\\Php{$version};

use Phabel\\Plugin;

class {$name} extends Plugin
{
}
PHP;
                \file_put_contents("src/Target/Php{$version}/{$name}.php", $code);
            }
        }
        \var_dump($keys);
        foreach ($this->result as $type => $results) {
            $name = $type === 'main' ? 'NestedExpressionFixer' : 'IssetExpressionFixer';
            $type = $type === 'main' ? NestedExpressionFixer::class : IssetExpressionFixer::class;
            foreach ($results as $version => $config) {
                $config = \var_export($config, true);
                $code = <<<PHP
<?php

namespace Phabel\\Target\\Php{$version};

use Phabel\\Plugin;
use {$type} as fixer;

/**
 * Expression fixer for PHP {$version}
 */
class {$name} extends Plugin
{
    /**
     * {@inheritDoc}
     */
    public static function next(array \$config): array
    {
        return [
            fixer::class => {$config}
        ];
    }
}
PHP;
                \file_put_contents("src/Target/Php{$version}/{$name}.php", $code);
            }
        }
        $comment = <<<PHP
/**
 * @author Daniil Gentili <daniil@daniil.it>
 * @license MIT
 */
PHP;
        foreach (\glob("testsGenerated/Target/Expression*") as $file) {
            \unlink($file);
        }
        $prettyPrinter = new PhpParser\PrettyPrinter\Standard(['shortArraySyntax' => true]);
        foreach (\array_chunk($this->tests, 100) as $stmts) {
            $i = \hash('sha256', $prettyPrinter->prettyPrintFile($stmts)) . "Test";
            $sortedStmts = [];
            foreach ($stmts as $stmt) {
                $method = 'test' . \hash('sha256', $prettyPrinter->prettyPrintFile([$stmt]));
                $sortedStmts[$method] = (new Method($method))->addStmt(new MethodCall(new Variable('this'), 'assertTrue', [new Arg(Tools::fromLiteral(true))]))->addStmt(new Expression(new ArrowFunction(['expr' => $stmt])))->getNode();
            }
            \ksort($sortedStmts);
            $class = (new Class_("Expression{$i}"))->extend("TestCase")->setDocComment($comment)->addStmts(\array_values($sortedStmts))->getNode();
            $class = (new Namespace_(PhabelTest\Target::class))->addStmt(new Use_(\PHPUnit\Framework\TestCase::class, StmtUse_::TYPE_NORMAL))->addStmt($class)->getNode();
            $class = $prettyPrinter->prettyPrintFile([$class]);
            if (\file_exists("testsGenerated/Target/Expression{$i}.php")) {
                throw new \RuntimeException("Expression{$i}.php already exists!");
            }
            \file_put_contents("testsGenerated/Target/Expression{$i}.php", $class);
        }
    }
}
(new ExpressionGenerator())->run();
<?php

use Phabel\Cli\EventHandler;
use Phabel\Target\Php;
use Phabel\Traverser;

if (!\file_exists('composer.json')) {
    echo "This script must be run from package root" . PHP_EOL;
    die(1);
}
require 'vendor/autoload.php';
require 'ci/functions.php';
if ($argc < 2) {
    $help = <<<EOF
Usage: {$argv[0]} target [ dry ]

target - Target version
dry - 0 or 1, whether to dry-run conversion

EOF;
    echo $help;
    die(1);
}
$target = $argv[1];
$dry = (bool) ($argv[2] ?? '');
$branch = 'master';
$tag = \getenv('shouldTag') ?: null;
$home = \realpath(__DIR__ . '/../');
r("rm -rf ../phabelConvertedInput");
\mkdir('../phabelConvertedInput');
if (!$dry) {
    r("rm -rf ../phabelConvertedRepo");
    r("cp -a {$home} ../phabelConvertedRepo");
    r("rm -rf ../phabelConvertedRepo/vendor");
}
/**
 *
 */
function commit(string $message)
{
    r("cp -a ../phabelConvertedOutput/* ../phabelConvertedRepo");
    \chdir("../phabelConvertedRepo/");
    r("git add -A");
    r("git commit -m " . \escapeshellarg($message));
}
$last = Php::VERSIONS;
$last = \end($last);
foreach ($target === 'all' ? Php::VERSIONS : [$target] as $realTarget) {
    $realTarget = Php::normalizeVersion($realTarget);
    if (!$dry) {
        \chdir("../phabelConvertedRepo");
        \passthru("git branch -D phabel_tmp");
        r("git branch phabel_tmp");
        r("git checkout phabel_tmp");
        r("rm -rf ../phabelConvertedRepo/*");
    }
    r("rm -rf ../phabelConvertedOutput");
    \mkdir('../phabelConvertedOutput');
    $coverage = \getenv('PHABEL_COVERAGE') ?: '';
    if ($coverage) {
        $coverage .= "-{$realTarget}";
    }
    $packages = (new Traverser(EventHandler::create()))->setInput('../phabelConvertedOutput')->setOutput('../phabelConvertedOutput')->setPlugins([Php::class => ['target' => $realTarget]])->setCoverage($coverage)->run((int) (\getenv('PHABEL_PARALLEL') ?: 1));
    \chdir($home);
    r("cp -a * .php-cs-fixer.dist.php ../phabelConvertedInput");
    \chdir("../phabelConvertedInput");
    r("rm -rf vendor-bin/*/vendor");
    if (!empty($packages)) {
        unset($packages['phabel/phabel']);
        $json = \json_decode(\file_get_contents('composer.json'), true);
        foreach ($packages as $package => $constraint) {
            if ($package === 'php') {
                continue;
            }
            if (isset($json['require-dev'][$package])) {
                unset($json['require-dev'][$package]);
            }
            $json['require'][$package] = $constraint;
        }
        \file_put_contents('composer.json', \json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
    }
    r("composer update --no-dev");
    r("rm -rf tests testsGenerated");
    foreach ([Php::VERSIONS[\count(Php::VERSIONS) - 1], $realTarget] as $k => $target) {
        if ($k === 0) {
            $input = "../phabelConvertedInput";
            $output = "../phabelConvertedOutput";
        } else {
            $input = $output = "../phabelConvertedOutput";
        }
        \chdir($input);
        $coverage = \getenv('PHABEL_COVERAGE') ?: '';
        if ($coverage) {
            $coverage .= "-{$target}";
        }
        (new Traverser(EventHandler::create()))->setInput($input)->setOutput($output)->setPlugins([Php::class => ['target' => $target]])->setCoverage($coverage)->run((int) (\getenv('PHABEL_PARALLEL') ?: 1));
        \chdir($output);
        if (!$dry) {
            r("{$home}/vendor/bin/php-cs-fixer fix");
            commit("phabel.io: transpile to {$target}");
        }
    }
    \chdir($home);
    r("cp -a testsGenerated tests ../phabelConvertedOutput");
    \copy("tools/ci/matrix.php", "../phabelConvertedOutput/tools/ci/matrix.php");
    \chdir("../phabelConvertedOutput");
    r("{$home}/vendor/bin/php-scoper add-prefix -c {$home}/scoper.inc.php");
    r("cp -a vendor/symfony/polyfill* build/vendor/symfony");
    r("rm -rf vendor");
    r("cp -a build/. .");
    r("rm -rf build vendor/composer vendor/autoload.php vendor/scoper-autoload.php vendor/bin");
    // Patch symfony/string
    \file_put_contents('vendor/symfony/string/AbstractString.php', \str_replace('\\PREG_UNMATCHED_AS_NULL', "0", \file_get_contents('vendor/symfony/string/AbstractString.php')));
    $replace = 'array_walk_recursive($match, function (&$v){return $v === "" ? null : $v;})';
    \file_put_contents('vendor/symfony/string/AbstractUnicodeString.php', \str_replace(['return $matches;', '\\PREG_UNMATCHED_AS_NULL'], ["{$replace}; return \$matches;", "0"], \file_get_contents('vendor/symfony/string/AbstractUnicodeString.php')));
    \file_put_contents('vendor/symfony/string/ByteString.php', \str_replace(['return $matches;', '\\PREG_UNMATCHED_AS_NULL'], ["{$replace}; return \$matches;", "0"], \file_get_contents('vendor/symfony/string/ByteString.php')));
    \file_put_contents('src/Composer/Plugin.php', \str_replace('PhabelVendor\\Symfony', 'Symfony', \file_get_contents('src/Composer/Plugin.php')));
    \file_put_contents('src/Composer/Transformer.php', \str_replace('PhabelVendor\\Symfony', 'Symfony', \file_get_contents('src/Composer/Transformer.php')));
    \rename("vendor", "vendor-bundle");
    r("find src -type f -exec sed 's/\\\\PhabelVendor\\\\self/self/g' -i {} +");
    \file_put_contents(
        'vendor-bundle/autoload.php',
        <<<PHP
    <?php
    if (file_exists(__DIR__.'/../vendor/autoload.php')) return require __DIR__.'/../vendor/autoload.php';
    return require __DIR__.'/../../../autoload.php';
PHP
    );
    $lock = \json_decode(\file_get_contents('composer.lock'), true);
    $json = \json_decode(\file_get_contents('composer.json'), true);
    $json['require'] = ['php' => $packages['php'], 'ext-json' => $json['require']['ext-json'], 'composer-plugin-api' => $json['require']['composer-plugin-api']];
    $json['require-dev'] = ['bamarni/composer-bin-plugin' => $json['require-dev']['bamarni/composer-bin-plugin'], 'amphp/file' => $json['require-dev']['amphp/file']];
    if ($realTarget === $last) {
        $json['require']['php'] = '>=' . Php::unnormalizeVersion($last);
    }
    foreach ($lock['packages'] as $package) {
        $name = $package['name'];
        if ($name === 'phabel/phabel') {
            continue;
        }
        $json['require'] += \array_filter($package['require'], fn ($s) => \str_starts_with($s, 'ext-'), ARRAY_FILTER_USE_KEY);
        foreach (['psr-4', 'psr-0'] as $type) {
            foreach ($package['autoload'][$type] ?? [] as $namespace => $path) {
                $namespace = \str_starts_with($namespace, 'Symfony\\Polyfill') ? $namespace : "PhabelVendor\\{$namespace}";
                $paths = \is_string($path) ? [$path] : $path;
                $paths = \array_map(fn ($path) => ("vendor-bundle/{$name}/{$path}"), $paths);
                $json['autoload'][$type][$namespace] = $paths;
            }
        }
        foreach (['classmap', 'files'] as $type) {
            $json['autoload'][$type] = \array_merge($json['autoload'][$type] ?? [], \array_map(fn ($path) => ("vendor-bundle/{$name}/{$path}"), $package['autoload'][$type] ?? []));
        }
    }
    /*$it = new \RecursiveDirectoryIterator('src', \RecursiveDirectoryIterator::SKIP_DOTS);
            $ri = new \RecursiveIteratorIterator($it, \RecursiveIteratorIterator::SELF_FIRST);

            $allUses = [];
            foreach ($ri as $file) {
                if ($file->getExtension() !== 'php') {
                    continue;
                }
                if (\preg_match_all('/^use (\S+?)(?: as \S+)?;$/m', \file_get_contents($file->getRealPath()), $uses)) {
                    foreach ($uses[1] as $class) {
                        $allUses []= "\\$class::class";
                    }
                }
            }

            $allUses = \implode(', ', $allUses);
            $allUses = "array_map('class_exists', [$allUses]);";

            \file_put_contents(
                'src/guard.php',
                \file_get_contents('src/guard.php').$allUses
            );*/
    foreach ($json['autoload']['files'] ?? [] as $file) {
        $path = \dirname($file);
        $file = \basename($file);
        \rename("{$path}/{$file}", "{$path}/guard.{$file}");
        \file_put_contents("{$path}/{$file}", "<?php require_once __DIR__.DIRECTORY_SEPARATOR.'guard.{$file}';");
    }
    $json['autoload-dev'] = ['psr-4' => ['PhabelTest\\' => 'tests/']];
    \file_put_contents('composer.json', \json_encode($json, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES));
    if (!$dry) {
        \chdir("../phabelConvertedRepo");
        if ($tag) {
            commit("phabel.io: add dependencies (tag {$tag}.{$target})");
        } else {
            commit("phabel.io: add dependencies");
        }
        r("git push -f origin " . \escapeshellarg("phabel_tmp:{$branch}-{$target}"));
        r("git checkout " . \escapeshellarg($branch));
        r("git branch -D phabel_tmp");
    }
}
<?php

use Phabel\Cli\EventHandler;
use Phabel\Plugin\PhabelTestGenerator;
use Phabel\Target\Php;
use Phabel\Traverser;

require_once 'vendor/autoload.php';
`rm -rf coverage`;
$packages = [];
$packagesSecondary = [];
foreach ([56, 70, ...Php::VERSIONS] as $version) {
    echo "{$version}\n";
    `rm -rf "tests/Target{$version}"`;
    `rm -rf "tests/Target10{$version}"`;
    $packages += (new Traverser(EventHandler::create()))->setPlugins([PhabelTestGenerator::class => ['target' => $version]])->setInput('tests/Target')->setOutput("tests/Target{$version}")->setCoverage("test{$version}")->run(\getenv('PHABEL_PARALLEL') ?: -1);
    (new Traverser(EventHandler::create()))->setPlugins([PhabelTestGenerator::class => ['target' => 1000 + $version]])->setInput("tests/Target{$version}")->setOutput("tests/Target10{$version}")->setCoverage("test10{$version}")->run(\getenv('PHABEL_PARALLEL') ?: -1);
    \unlink("tests/Target{$version}/ComposerTest.php");
    if ($version !== Php::VERSIONS[0]) {
        \unlink("tests/Target10{$version}/ComposerTest.php");
    }
    (new Traverser(EventHandler::create()))->setPlugins([PhabelTestGenerator::class => ['target' => 1000 + $version]])->setInput("tests/TargetFuture")->setOutput("tests/Target{$version}Future")->setCoverage("testFuture{$version}")->run(\getenv('PHABEL_PARALLEL') ?: -1);
}
<?php

$os = ['self-hosted'];
$php = require 'versions.php';

$commit = \trim(\shell_exec("git log -1 --pretty=%H"));
$branch = \trim(\shell_exec("git rev-parse --abbrev-ref HEAD"));
$message = \trim(\shell_exec('git log --format=%B -n 1 '.\escapeshellarg($commit)));

$tag = '';
if (\preg_match('/[(]tag ([^)]+)[)]/', $message, $matches)) {
    $tag = $matches[1];
} elseif (!\str_ends_with(\trim($message), 'notag)')) {
    $tag = \explode("\n", \trim(\shell_exec("git tag --sort=-creatordate")))[0];
    $tag = \preg_replace('/\.\d+$/', '', $tag);
    $tag = \explode('.', $tag);
    $tag[\count($tag)-1]++;
    $tag = \implode('.', $tag);
}

$doBuild = true;

$final = null;
$tail = \substr($branch, -3);
foreach ($php as $version) {
    $version = (string) $version;
    $final = $version[0].".".$version[1];
    if ($tail === "-$version") {
        $doBuild = false;
        break;
    }
}

$matrix = [
    'os' => $os,
    'php' => [$final],
    'shouldBuild' => $doBuild ? $php : [''],
    'shouldTag' => [$tag]
];
$matrix = \json_encode($matrix);

echo "::set-output name=matrix::$matrix".PHP_EOL;
<?php

use SebastianBergmann\CodeCoverage\CodeCoverage;
use SebastianBergmann\CodeCoverage\Report\Clover;
use SebastianBergmann\CodeCoverage\Report\Text;

require 'vendor/autoload.php';
$coverage = null;
foreach (\glob("coverage/*.php") as $file) {
    echo "Processing {$file}..." . PHP_EOL;
    if (!$coverage) {
        $coverage = (include $file);
        continue;
    }
    /** @var CodeCoverage $coverage */
    $coverage->merge(include $file);
}
if ($coverage) {
    (new Clover())->process($coverage, 'coverage/clover.xml');
    echo (new Text(50, 90, true))->process($coverage, true) . PHP_EOL;
}
<?php

return [71, 72, 73, 74, 80];
<?php

use Phabel\Cli\EventHandler;
use Phabel\Target\Php;
use Phabel\Traverser;

require 'functions.php';
r("composer update --prefer-dist --ignore-platform-reqs");
r("composer bin check update --prefer-dist --ignore-platform-reqs");
require 'vendor/autoload.php';
$branch = \getenv('BRANCH') ?: r("git rev-parse --abbrev-ref HEAD");
$version = 80;
if ($branch !== 'master') {
    $version = \Phabel\Target\Php80\Polyfill::substr($version, -2);
}
r("rm -rf ../phabelConvertedVendor");
$packages = (new Traverser(EventHandler::create()))->setPlugins([Php::class => ['target' => $version]])->setInput('vendor-bin/check/vendor')->setOutput('../phabelConvertedVendor')->setCoverage('coverage/convertVendor.php')->run(\getenv('PHABEL_PARALLEL') ?: 1);
r("cp -a vendor-bin/check/vendor/composer ../phabelConvertedVendor");
r("rm -rf vendor-bin/check/vendor");
\rename("../phabelConvertedVendor", "vendor-bin/check/vendor");
$phpunit = \realpath("vendor/bin/phpunit");
\file_put_contents($phpunit, \str_replace('die(1);', '', \file_get_contents($phpunit)));
\chmod($phpunit, 0755);
<?php

/**
 * Run command, exiting with error code if it fails.
 *
 * @param string $cmd
 * @return void
 */
function r(string $cmd)
{
    \passthru($cmd, $ret);
    if ($ret) {
        die($ret);
    }
}
{
    "name": "phabel/phabel",
    "description": "Write and deploy modern PHP 8 code, today.",
    "type": "composer-plugin",
    "require": {
        "php": ">=7.4 <7.5",
        "ext-json": "*",
        "composer-plugin-api": "^2.0",
        "ext-tokenizer": "*"
    },
    "require-dev": {
        "bamarni/composer-bin-plugin": "^1.4",
        "amphp/file": "^2.0"
    },
    "provide": {
        "phabelio/phabel": "self.version"
    },
    "license": "MIT",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "autoload": {
        "psr-4": {
            "Phabel\\": "src",
            "PhabelVendor\\Amp\\": [
                "vendor-bundle/amphp/amp/lib"
            ],
            "PhabelVendor\\Amp\\ByteStream\\": [
                "vendor-bundle/amphp/byte-stream/lib"
            ],
            "PhabelVendor\\Amp\\Parallel\\": [
                "vendor-bundle/amphp/parallel/lib"
            ],
            "PhabelVendor\\Amp\\Parser\\": [
                "vendor-bundle/amphp/parser/lib"
            ],
            "PhabelVendor\\Amp\\Process\\": [
                "vendor-bundle/amphp/process/lib"
            ],
            "PhabelVendor\\Amp\\Serialization\\": [
                "vendor-bundle/amphp/serialization/src"
            ],
            "PhabelVendor\\Amp\\Sync\\": [
                "vendor-bundle/amphp/sync/src"
            ],
            "PhabelVendor\\PhpParser\\": [
                "vendor-bundle/phabel/php-parser/lib/PhpParser"
            ],
            "PhabelVendor\\PHPStan\\PhpDocParser\\": [
                "vendor-bundle/phpstan/phpdoc-parser/src/"
            ],
            "PhabelVendor\\Psr\\Container\\": [
                "vendor-bundle/psr/container/src/"
            ],
            "PhabelVendor\\Psr\\Log\\": [
                "vendor-bundle/psr/log/Psr/Log/"
            ],
            "PhabelVendor\\Symfony\\Component\\Console\\": [
                "vendor-bundle/symfony/console/"
            ],
            "Symfony\\Polyfill\\Ctype\\": [
                "vendor-bundle/symfony/polyfill-ctype/"
            ],
            "Symfony\\Polyfill\\Intl\\Grapheme\\": [
                "vendor-bundle/symfony/polyfill-intl-grapheme/"
            ],
            "Symfony\\Polyfill\\Intl\\Normalizer\\": [
                "vendor-bundle/symfony/polyfill-intl-normalizer/"
            ],
            "Symfony\\Polyfill\\Mbstring\\": [
                "vendor-bundle/symfony/polyfill-mbstring/"
            ],
            "Symfony\\Polyfill\\Php73\\": [
                "vendor-bundle/symfony/polyfill-php73/"
            ],
            "Symfony\\Polyfill\\Php80\\": [
                "vendor-bundle/symfony/polyfill-php80/"
            ],
            "PhabelVendor\\Symfony\\Component\\Process\\": [
                "vendor-bundle/symfony/process/"
            ],
            "PhabelVendor\\Symfony\\Contracts\\Service\\": [
                "vendor-bundle/symfony/service-contracts/"
            ],
            "PhabelVendor\\Symfony\\Component\\String\\": [
                "vendor-bundle/symfony/string/"
            ]
        },
        "files": [
            "src/guard.php",
            "vendor-bundle/amphp/amp/lib/functions.php",
            "vendor-bundle/amphp/amp/lib/Internal/functions.php",
            "vendor-bundle/amphp/byte-stream/lib/functions.php",
            "vendor-bundle/amphp/parallel/lib/Context/functions.php",
            "vendor-bundle/amphp/parallel/lib/Sync/functions.php",
            "vendor-bundle/amphp/parallel/lib/Worker/functions.php",
            "vendor-bundle/amphp/process/lib/functions.php",
            "vendor-bundle/amphp/serialization/src/functions.php",
            "vendor-bundle/amphp/sync/src/functions.php",
            "vendor-bundle/amphp/sync/src/ConcurrentIterator/functions.php",
            "vendor-bundle/symfony/deprecation-contracts/function.php",
            "vendor-bundle/symfony/polyfill-ctype/bootstrap.php",
            "vendor-bundle/symfony/polyfill-intl-grapheme/bootstrap.php",
            "vendor-bundle/symfony/polyfill-intl-normalizer/bootstrap.php",
            "vendor-bundle/symfony/polyfill-mbstring/bootstrap.php",
            "vendor-bundle/symfony/polyfill-php73/bootstrap.php",
            "vendor-bundle/symfony/polyfill-php80/bootstrap.php",
            "vendor-bundle/symfony/string/Resources/functions.php"
        ],
        "classmap": [
            "vendor-bundle/symfony/polyfill-intl-normalizer/Resources/stubs",
            "vendor-bundle/symfony/polyfill-php73/Resources/stubs",
            "vendor-bundle/symfony/polyfill-php80/Resources/stubs"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "PhabelTest\\": "tests/"
        }
    },
    "extra": {
        "class": "Phabel\\Composer\\Plugin",
        "plugin-modifies-downloads": true
    },
    "archive": {
        "exclude": [
            "/tests",
            "/testsGenerated"
        ]
    },
    "scripts": {
        "typeHintGen": "php80 tools/typeHintGen.php",
        "exprGen": "@php tools/exprGen.php",
        "build": [
            "@typeHintGen",
            "@exprGen",
            "@cs-fix",
            "@test"
        ],
        "check": [
            "@cs",
            "@test"
        ],
        "test": [
            "@phpunit",
            "@coverage"
        ],
        "test-simple": "SKIP_COMPOSER=1 php vendor/bin/phpunit --coverage-php=coverage/phpunit.php",
        "test-full": [
            "@phpunit",
            "@phpunitExpr",
            "@coverage"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "phpunit": "@php vendor/bin/phpunit --coverage-php=coverage/phpunit.php",
        "coverage": "@php tools/ci/coverageMerge.php",
        "phpunitExpr": "@php tools/testExprGen.php"
    },
    "config": {
        "process-timeout": 0
    },
    "bin": [
        "bin/phabel"
    ]
}<?php

declare (strict_types=1);
use Isolated\Symfony\Component\Finder\Finder;
return [
    // The prefix configuration. If a non null value will be used, a random prefix will be generated.
    'prefix' => 'PhabelVendor',
    // By default when running php-scoper add-prefix, it will prefix all relevant code found in the current working
    // directory. You can however define which files should be scoped by defining a collection of Finders in the
    // following configuration key.
    //
    // For more see: https://github.com/humbug/php-scoper#finders-and-paths
    'finders' => [Finder::create()->files()->in('src'), Finder::create()->files()->ignoreVCS(true)->notName('/LICENSE|.*\\.md|.*\\.dist|Makefile|composer\\.json|composer\\.lock/')->notPath('/.*symfony\\/polyfill.*/')->exclude(['doc', 'test', 'test_old', 'tests', 'Tests', 'vendor-bin'])->in('vendor'), Finder::create()->append(['composer.json'])],
    // Whitelists a list of files. Unlike the other whitelist related features, this one is about completely leaving
    // a file untouched.
    // Paths are relative to the configuration file unless if they are already absolute
    'files-whitelist' => [],
    // When scoping PHP files, there will be scenarios where some of the code being scoped indirectly references the
    // original namespace. These will include, for example, strings or string manipulations. PHP-Scoper has limited
    // support for prefixing such strings. To circumvent that, you can define patchers to manipulate the file to your
    // heart contents.
    //
    // For more see: https://github.com/humbug/php-scoper#patchers
    'patchers' => [],
    // PHP-Scoper's goal is to make sure that all code for a project lies in a distinct PHP namespace. However, you
    // may want to share a common API between the bundled code of your PHAR and the consumer code. For example if
    // you have a PHPUnit PHAR with isolated code, you still want the PHAR to be able to understand the
    // PHPUnit\Framework\TestCase class.
    //
    // A way to achieve this is by specifying a list of classes to not prefix with the following configuration key. Note
    // that this does not work with functions or constants neither with classes belonging to the global namespace.
    //
    // Fore more see https://github.com/humbug/php-scoper#whitelist
    'whitelist' => ['Phabel\\*', 'Composer\\*'],
    // If `true` then the user defined constants belonging to the global namespace will not be prefixed.
    //
    // For more see https://github.com/humbug/php-scoper#constants--constants--functions-from-the-global-namespace
    'whitelist-global-constants' => true,
    // If `true` then the user defined classes belonging to the global namespace will not be prefixed.
    //
    // For more see https://github.com/humbug/php-scoper#constants--constants--functions-from-the-global-namespace
    'whitelist-global-classes' => true,
    // If `true` then the user defined functions belonging to the global namespace will not be prefixed.
    //
    // For more see https://github.com/humbug/php-scoper#constants--constants--functions-from-the-global-namespace
    'whitelist-global-functions' => true,
];<?php

declare (strict_types=1);
/**
 * Creates EncodingContext objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Encoder;

use LibDNS\Packets\Packet;
use LibDNS\Packets\LabelRegistry;
/**
 * Creates EncodingContext objects
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class EncodingContextFactory
{
    /**
     * Create a new EncodingContext object
     *
     * @param \LibDNS\Packets\Packet $packet The packet to be decoded
     * @param bool $compress Whether message compression is enabled
     * @return \LibDNS\Encoder\EncodingContext
     */
    public function create(Packet $packet, bool $compress) : EncodingContext
    {
        return new EncodingContext($packet, new LabelRegistry(), $compress);
    }
}<?php

declare (strict_types=1);
/**
 * Encodes Message objects to raw network data
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Encoder;

use LibDNS\Packets\PacketFactory;
use LibDNS\Messages\Message;
use LibDNS\Records\Question;
use LibDNS\Records\Resource;
use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
/**
 * Encodes Message objects to raw network data
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Encoder
{
    /**
     * @var \LibDNS\Packets\PacketFactory
     */
    private $packetFactory;
    /**
     * @var \LibDNS\Encoder\EncodingContextFactory
     */
    private $encodingContextFactory;
    /**
     * Constructor
     *
     * @param \LibDNS\Packets\PacketFactory $packetFactory
     * @param \LibDNS\Encoder\EncodingContextFactory $encodingContextFactory
     */
    public function __construct(PacketFactory $packetFactory, EncodingContextFactory $encodingContextFactory)
    {
        $this->packetFactory = $packetFactory;
        $this->encodingContextFactory = $encodingContextFactory;
    }
    /**
     * Encode the header section of the message
     *
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @param \LibDNS\Messages\Message $message
     * @return string
     * @throws \UnexpectedValueException When the header section is invalid
     */
    private function encodeHeader(EncodingContext $encodingContext, Message $message) : string
    {
        $header = ['id' => $message->getID(), 'meta' => 0, 'qd' => $message->getQuestionRecords()->count(), 'an' => $message->getAnswerRecords()->count(), 'ns' => $message->getAuthorityRecords()->count(), 'ar' => $message->getAdditionalRecords()->count()];
        $header['meta'] |= $message->getType() << 15;
        $header['meta'] |= $message->getOpCode() << 11;
        $header['meta'] |= (int) $message->isAuthoritative() << 10;
        $header['meta'] |= (int) $encodingContext->isTruncated() << 9;
        $header['meta'] |= (int) $message->isRecursionDesired() << 8;
        $header['meta'] |= (int) $message->isRecursionAvailable() << 7;
        $header['meta'] |= $message->getResponseCode();
        return \pack('n*', $header['id'], $header['meta'], $header['qd'], $header['an'], $header['ns'], $header['ar']);
    }
    /**
     * Encode an Anything field
     *
     * @param \LibDNS\Records\Types\Anything $anything
     * @return string
     */
    private function encodeAnything(Anything $anything) : string
    {
        return $anything->getValue();
    }
    /**
     * Encode a BitMap field
     *
     * @param \LibDNS\Records\Types\BitMap $bitMap
     * @return string
     */
    private function encodeBitMap(BitMap $bitMap) : string
    {
        return $bitMap->getValue();
    }
    /**
     * Encode a Char field
     *
     * @param \LibDNS\Records\Types\Char $char
     * @return string
     */
    private function encodeChar(Char $char) : string
    {
        return \chr($char->getValue());
    }
    /**
     * Encode a CharacterString field
     *
     * @param \LibDNS\Records\Types\CharacterString $characterString
     * @return string
     */
    private function encodeCharacterString(CharacterString $characterString) : string
    {
        $data = $characterString->getValue();
        return \chr(\strlen($data)) . $data;
    }
    /**
     * Encode a DomainName field
     *
     * @param \LibDNS\Records\Types\DomainName $domainName
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @return string
     */
    private function encodeDomainName(DomainName $domainName, EncodingContext $encodingContext) : string
    {
        $packetIndex = $encodingContext->getPacket()->getLength() + 12;
        $labelRegistry = $encodingContext->getLabelRegistry();
        $result = '';
        $labels = $domainName->getLabels();
        if ($encodingContext->useCompression()) {
            do {
                $part = \implode('.', $labels);
                $index = $labelRegistry->lookupIndex($part);
                if ($index === null) {
                    $labelRegistry->register($part, $packetIndex);
                    $label = \array_shift($labels);
                    $length = \strlen($label);
                    $result .= \chr($length) . $label;
                    $packetIndex += $length + 1;
                } else {
                    $result .= \pack('n', 0b1100000000000000 | $index);
                    break;
                }
            } while ($labels);
            if (!$labels) {
                $result .= "\x00";
            }
        } else {
            foreach ($labels as $label) {
                $result .= \chr(\strlen($label)) . $label;
            }
            $result .= "\x00";
        }
        return $result;
    }
    /**
     * Encode an IPv4Address field
     *
     * @param \LibDNS\Records\Types\IPv4Address $ipv4Address
     * @return string
     */
    private function encodeIPv4Address(IPv4Address $ipv4Address) : string
    {
        $octets = $ipv4Address->getOctets();
        return \pack('C*', $octets[0], $octets[1], $octets[2], $octets[3]);
    }
    /**
     * Encode an IPv6Address field
     *
     * @param \LibDNS\Records\Types\IPv6Address $ipv6Address
     * @return string
     */
    private function encodeIPv6Address(IPv6Address $ipv6Address) : string
    {
        $shorts = $ipv6Address->getShorts();
        return \pack('n*', $shorts[0], $shorts[1], $shorts[2], $shorts[3], $shorts[4], $shorts[5], $shorts[6], $shorts[7]);
    }
    /**
     * Encode a Long field
     *
     * @param \LibDNS\Records\Types\Long $long
     * @return string
     */
    private function encodeLong(Long $long) : string
    {
        return \pack('N', $long->getValue());
    }
    /**
     * Encode a Short field
     *
     * @param \LibDNS\Records\Types\Short $short
     * @return string
     */
    private function encodeShort(Short $short) : string
    {
        return \pack('n', $short->getValue());
    }
    /**
     * Encode a type object
     *
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @param \LibDNS\Records\Types\Type $type
     * @return string
     */
    private function encodeType(EncodingContext $encodingContext, Type $type) : string
    {
        if ($type instanceof Anything) {
            $result = $this->encodeAnything($type);
        } else {
            if ($type instanceof BitMap) {
                $result = $this->encodeBitMap($type);
            } else {
                if ($type instanceof Char) {
                    $result = $this->encodeChar($type);
                } else {
                    if ($type instanceof CharacterString) {
                        $result = $this->encodeCharacterString($type);
                    } else {
                        if ($type instanceof DomainName) {
                            $result = $this->encodeDomainName($type, $encodingContext);
                        } else {
                            if ($type instanceof IPv4Address) {
                                $result = $this->encodeIPv4Address($type);
                            } else {
                                if ($type instanceof IPv6Address) {
                                    $result = $this->encodeIPv6Address($type);
                                } else {
                                    if ($type instanceof Long) {
                                        $result = $this->encodeLong($type);
                                    } else {
                                        if ($type instanceof Short) {
                                            $result = $this->encodeShort($type);
                                        } else {
                                            throw new \InvalidArgumentException('Unknown Type ' . \get_class($type));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return $result;
    }
    /**
     * Encode a question record
     *
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @param \LibDNS\Records\Question $record
     */
    private function encodeQuestionRecord(EncodingContext $encodingContext, Question $record)
    {
        if (!$encodingContext->isTruncated()) {
            $packet = $encodingContext->getPacket();
            $name = $this->encodeDomainName($record->getName(), $encodingContext);
            $meta = \pack('n*', $record->getType(), $record->getClass());
            if (12 + $packet->getLength() + \strlen($name) + 4 > 512) {
                $encodingContext->isTruncated(true);
            } else {
                $packet->write($name);
                $packet->write($meta);
            }
        }
    }
    /**
     * Encode a resource record
     *
     * @param \LibDNS\Encoder\EncodingContext $encodingContext
     * @param \LibDNS\Records\Resource $record
     */
    private function encodeResourceRecord(EncodingContext $encodingContext, Resource $record)
    {
        if (!$encodingContext->isTruncated()) {
            $packet = $encodingContext->getPacket();
            $name = $this->encodeDomainName($record->getName(), $encodingContext);
            $data = '';
            foreach ($record->getData() as $field) {
                $data .= $this->encodeType($encodingContext, $field);
            }
            $meta = \pack('n2Nn', $record->getType(), $record->getClass(), $record->getTTL(), \strlen($data));
            if (12 + $packet->getLength() + \strlen($name) + 10 + \strlen($data) > 512) {
                $encodingContext->isTruncated(true);
            } else {
                $packet->write($name);
                $packet->write($meta);
                $packet->write($data);
            }
        }
    }
    /**
     * Encode a Message to raw network data
     *
     * @param \LibDNS\Messages\Message $message The Message to encode
     * @param bool $compress Enable message compression
     * @return string
     */
    public function encode(Message $message, $compress = true) : string
    {
        $packet = $this->packetFactory->create();
        $encodingContext = $this->encodingContextFactory->create($packet, $compress);
        foreach ($message->getQuestionRecords() as $record) {
            /** @var \LibDNS\Records\Question $record */
            $this->encodeQuestionRecord($encodingContext, $record);
        }
        foreach ($message->getAnswerRecords() as $record) {
            /** @var \LibDNS\Records\Resource $record */
            $this->encodeResourceRecord($encodingContext, $record);
        }
        foreach ($message->getAuthorityRecords() as $record) {
            /** @var \LibDNS\Records\Resource $record */
            $this->encodeResourceRecord($encodingContext, $record);
        }
        foreach ($message->getAdditionalRecords() as $record) {
            /** @var \LibDNS\Records\Resource $record */
            $this->encodeResourceRecord($encodingContext, $record);
        }
        return $this->encodeHeader($encodingContext, $message) . $packet->read($packet->getLength());
    }
}<?php

declare (strict_types=1);
/**
 * Holds data associated with an encode operation
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Encoder;

use LibDNS\Packets\Packet;
use LibDNS\Packets\LabelRegistry;
/**
 * Holds data associated with an encode operation
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class EncodingContext
{
    /**
     * @var \LibDNS\Packets\Packet
     */
    private $packet;
    /**
     * @var \LibDNS\Packets\LabelRegistry
     */
    private $labelRegistry;
    /**
     * @var bool
     */
    private $compress;
    /**
     * @var bool
     */
    private $truncate = false;
    /**
     * Constructor
     *
     * @param \LibDNS\Packets\Packet $packet
     * @param \LibDNS\Packets\LabelRegistry $labelRegistry
     * @param bool $compress
     */
    public function __construct(Packet $packet, LabelRegistry $labelRegistry, bool $compress)
    {
        $this->packet = $packet;
        $this->labelRegistry = $labelRegistry;
        $this->compress = $compress;
    }
    /**
     * Get the packet
     *
     * @return \LibDNS\Packets\Packet
     */
    public function getPacket() : Packet
    {
        return $this->packet;
    }
    /**
     * Get the label registry
     *
     * @return \LibDNS\Packets\LabelRegistry
     */
    public function getLabelRegistry() : LabelRegistry
    {
        return $this->labelRegistry;
    }
    /**
     * Determine whether compression is enabled
     *
     * @return bool
     */
    public function useCompression() : bool
    {
        return $this->compress;
    }
    /**
     * Determine or set whether the message is truncated
     *
     * @param bool $truncate
     * @return bool
     */
    public function isTruncated(bool $truncate = null) : bool
    {
        $result = $this->truncate;
        if ($truncate !== null) {
            $this->truncate = $truncate;
        }
        return $result;
    }
}<?php

declare (strict_types=1);
/**
 * Creates Encoder objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Encoder;

use LibDNS\Packets\PacketFactory;
/**
 * Creates Encoder objects
 *
 * @category LibDNS
 * @package Encoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class EncoderFactory
{
    /**
     * Create a new Encoder object
     *
     * @return \LibDNS\Encoder\Encoder
     */
    public function create() : Encoder
    {
        return new Encoder(new PacketFactory(), new EncodingContextFactory());
    }
}<?php

declare (strict_types=1);
/**
 * Holds data associated with a decode operation
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Decoder;

use LibDNS\Packets\Packet;
use LibDNS\Packets\LabelRegistry;
/**
 * Holds data associated with a decode operation
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class DecodingContext
{
    /**
     * @var \LibDNS\Packets\Packet
     */
    private $packet;
    /**
     * @var \LibDNS\Packets\LabelRegistry
     */
    private $labelRegistry;
    /**
     * @var int
     */
    private $expectedQuestionRecords = 0;
    /**
     * @var int
     */
    private $expectedAnswerRecords = 0;
    /**
     * @var int
     */
    private $expectedAuthorityRecords = 0;
    /**
     * @var int
     */
    private $expectedAdditionalRecords = 0;
    /**
     * Constructor
     *
     * @param \LibDNS\Packets\Packet $packet
     * @param \LibDNS\Packets\LabelRegistry $labelRegistry
     */
    public function __construct(Packet $packet, LabelRegistry $labelRegistry)
    {
        $this->packet = $packet;
        $this->labelRegistry = $labelRegistry;
    }
    /**
     * Get the packet
     *
     * @return \LibDNS\Packets\Packet
     */
    public function getPacket() : Packet
    {
        return $this->packet;
    }
    /**
     * Get the label registry
     *
     * @return \LibDNS\Packets\LabelRegistry
     */
    public function getLabelRegistry() : LabelRegistry
    {
        return $this->labelRegistry;
    }
    /**
     * Get the number of question records expected in the message
     *
     * @return int
     */
    public function getExpectedQuestionRecords() : int
    {
        return $this->expectedQuestionRecords;
    }
    /**
     * Get the number of question records expected in the message
     *
     * @param int $expectedQuestionRecords
     */
    public function setExpectedQuestionRecords(int $expectedQuestionRecords)
    {
        $this->expectedQuestionRecords = $expectedQuestionRecords;
    }
    /**
     * Get the number of answer records expected in the message
     *
     * @return int
     */
    public function getExpectedAnswerRecords() : int
    {
        return $this->expectedAnswerRecords;
    }
    /**
     * Set the number of answer records expected in the message
     *
     * @param int $expectedAnswerRecords
     */
    public function setExpectedAnswerRecords(int $expectedAnswerRecords)
    {
        $this->expectedAnswerRecords = $expectedAnswerRecords;
    }
    /**
     * Get the number of authority records expected in the message
     *
     * @return int
     */
    public function getExpectedAuthorityRecords() : int
    {
        return $this->expectedAuthorityRecords;
    }
    /**
     * Set the number of authority records expected in the message
     *
     * @param int $expectedAuthorityRecords
     */
    public function setExpectedAuthorityRecords(int $expectedAuthorityRecords)
    {
        $this->expectedAuthorityRecords = $expectedAuthorityRecords;
    }
    /**
     * Get the number of additional records expected in the message
     *
     * @return int
     */
    public function getExpectedAdditionalRecords() : int
    {
        return $this->expectedAdditionalRecords;
    }
    /**
     * Set the number of additional records expected in the message
     *
     * @param int $expectedAdditionalRecords
     */
    public function setExpectedAdditionalRecords(int $expectedAdditionalRecords)
    {
        $this->expectedAdditionalRecords = $expectedAdditionalRecords;
    }
}<?php

declare (strict_types=1);
/**
 * Creates Decoder objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Decoder;

use LibDNS\Packets\PacketFactory;
use LibDNS\Messages\MessageFactory;
use LibDNS\Records\RecordCollectionFactory;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\ResourceFactory;
use LibDNS\Records\RDataBuilder;
use LibDNS\Records\RDataFactory;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\TypeFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionManager;
use LibDNS\Records\TypeDefinitions\TypeDefinitionFactory;
use LibDNS\Records\TypeDefinitions\FieldDefinitionFactory;
/**
 * Creates Decoder objects
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class DecoderFactory
{
    /**
     * Create a new Decoder object
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager
     * @param bool $allowTrailingData
     * @return Decoder
     */
    public function create(TypeDefinitionManager $typeDefinitionManager = null, bool $allowTrailingData = true) : Decoder
    {
        $typeBuilder = new TypeBuilder(new TypeFactory());
        return new Decoder(new PacketFactory(), new MessageFactory(new RecordCollectionFactory()), new QuestionFactory(), new ResourceBuilder(new ResourceFactory(), new RDataBuilder(new RDataFactory(), $typeBuilder), $typeDefinitionManager ?: new TypeDefinitionManager(new TypeDefinitionFactory(), new FieldDefinitionFactory())), $typeBuilder, new DecodingContextFactory(), $allowTrailingData);
    }
}<?php

declare (strict_types=1);
/**
 * Creates DecodingContext objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Decoder;

use LibDNS\Packets\Packet;
use LibDNS\Packets\LabelRegistry;
/**
 * Creates DecodingContext objects
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class DecodingContextFactory
{
    /**
     * Create a new DecodingContext object
     *
     * @param \LibDNS\Packets\Packet $packet The packet to be decoded
     * @return \LibDNS\Decoder\DecodingContext
     */
    public function create(Packet $packet) : DecodingContext
    {
        return new DecodingContext($packet, new LabelRegistry());
    }
}<?php

declare (strict_types=1);
/**
 * Decodes raw network data to Message objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Decoder;

use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Packets\Packet;
use LibDNS\Packets\PacketFactory;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\Resource;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\Types;
/**
 * Decodes raw network data to Message objects
 *
 * @category LibDNS
 * @package Decoder
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Decoder
{
    /**
     * @var \LibDNS\Packets\PacketFactory
     */
    private $packetFactory;
    /**
     * @var \LibDNS\Messages\MessageFactory
     */
    private $messageFactory;
    /**
     * @var \LibDNS\Records\QuestionFactory
     */
    private $questionFactory;
    /**
     * @var \LibDNS\Records\ResourceBuilder
     */
    private $resourceBuilder;
    /**
     * @var \LibDNS\Records\Types\TypeBuilder
     */
    private $typeBuilder;
    /**
     * @var \LibDNS\Decoder\DecodingContextFactory
     */
    private $decodingContextFactory;
    /**
     * @var bool
     */
    private $allowTrailingData;
    /**
     * Constructor
     *
     * @param \LibDNS\Packets\PacketFactory $packetFactory
     * @param \LibDNS\Messages\MessageFactory $messageFactory
     * @param \LibDNS\Records\QuestionFactory $questionFactory
     * @param \LibDNS\Records\ResourceBuilder $resourceBuilder
     * @param \LibDNS\Records\Types\TypeBuilder $typeBuilder
     * @param \LibDNS\Decoder\DecodingContextFactory $decodingContextFactory
     * @param bool $allowTrailingData
     */
    public function __construct(PacketFactory $packetFactory, MessageFactory $messageFactory, QuestionFactory $questionFactory, ResourceBuilder $resourceBuilder, TypeBuilder $typeBuilder, DecodingContextFactory $decodingContextFactory, bool $allowTrailingData = true)
    {
        $this->packetFactory = $packetFactory;
        $this->messageFactory = $messageFactory;
        $this->questionFactory = $questionFactory;
        $this->resourceBuilder = $resourceBuilder;
        $this->typeBuilder = $typeBuilder;
        $this->decodingContextFactory = $decodingContextFactory;
        $this->allowTrailingData = $allowTrailingData;
    }
    /**
     * Read a specified number of bytes of data from a packet
     *
     * @param \LibDNS\Packets\Packet $packet
     * @param int $length
     * @return string
     * @throws \UnexpectedValueException When the read operation does not result in the requested number of bytes
     */
    private function readDataFromPacket(Packet $packet, int $length) : string
    {
        if ($packet->getBytesRemaining() < $length) {
            throw new \UnexpectedValueException('Decode error: Incomplete packet (tried to read ' . $length . ' bytes from index ' . $packet->getPointer());
        }
        return $packet->read($length);
    }
    /**
     * Decode the header section of the message
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Messages\Message $message
     * @throws \UnexpectedValueException When the header section is invalid
     */
    private function decodeHeader(DecodingContext $decodingContext, Message $message)
    {
        $header = \unpack('nid/nmeta/nqd/nan/nns/nar', $this->readDataFromPacket($decodingContext->getPacket(), 12));
        if (!$header) {
            throw new \UnexpectedValueException('Decode error: Header unpack failed');
        }
        $message->setID($header['id']);
        $message->setType(($header['meta'] & 0b1000000000000000) >> 15);
        $message->setOpCode(($header['meta'] & 0b111100000000000) >> 11);
        $message->isAuthoritative((bool) (($header['meta'] & 0b10000000000) >> 10));
        $message->isTruncated((bool) (($header['meta'] & 0b1000000000) >> 9));
        $message->isRecursionDesired((bool) (($header['meta'] & 0b100000000) >> 8));
        $message->isRecursionAvailable((bool) (($header['meta'] & 0b10000000) >> 7));
        $message->setResponseCode($header['meta'] & 0b1111);
        $decodingContext->setExpectedQuestionRecords($header['qd']);
        $decodingContext->setExpectedAnswerRecords($header['an']);
        $decodingContext->setExpectedAuthorityRecords($header['ns']);
        $decodingContext->setExpectedAdditionalRecords($header['ar']);
    }
    /**
     * Decode an Anything field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Anything $anything The object to populate with the result
     * @param int $length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeAnything(DecodingContext $decodingContext, Anything $anything, int $length) : int
    {
        $anything->setValue($this->readDataFromPacket($decodingContext->getPacket(), $length));
        return $length;
    }
    /**
     * Decode a BitMap field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\BitMap $bitMap The object to populate with the result
     * @param int $length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeBitMap(DecodingContext $decodingContext, BitMap $bitMap, int $length) : int
    {
        $bitMap->setValue($this->readDataFromPacket($decodingContext->getPacket(), $length));
        return $length;
    }
    /**
     * Decode a Char field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Char $char The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeChar(DecodingContext $decodingContext, Char $char) : int
    {
        $value = \unpack('C', $this->readDataFromPacket($decodingContext->getPacket(), 1))[1];
        $char->setValue($value);
        return 1;
    }
    /**
     * Decode a CharacterString field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\CharacterString $characterString The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeCharacterString(DecodingContext $decodingContext, CharacterString $characterString) : int
    {
        $packet = $decodingContext->getPacket();
        $length = \ord($this->readDataFromPacket($packet, 1));
        $characterString->setValue($this->readDataFromPacket($packet, $length));
        return $length + 1;
    }
    /**
     * Decode a DomainName field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\DomainName $domainName The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeDomainName(DecodingContext $decodingContext, DomainName $domainName) : int
    {
        $packet = $decodingContext->getPacket();
        $startIndex = '0x' . \dechex($packet->getPointer());
        $labelRegistry = $decodingContext->getLabelRegistry();
        $labels = [];
        $totalLength = 0;
        while (++$totalLength && ($length = \ord($this->readDataFromPacket($packet, 1)))) {
            $labelType = $length & 0b11000000;
            if ($labelType === 0b0) {
                $index = $packet->getPointer() - 1;
                $label = $this->readDataFromPacket($packet, $length);
                \array_unshift($labels, [$index, $label]);
                $totalLength += $length;
            } else {
                if ($labelType === 0b11000000) {
                    $index = ($length & 0b111111) << 8 | \ord($this->readDataFromPacket($packet, 1));
                    $ref = $labelRegistry->lookupLabel($index);
                    if ($ref === null) {
                        throw new \UnexpectedValueException('Decode error: Invalid compression pointer reference in domain name at position ' . $startIndex);
                    }
                    \array_unshift($labels, $ref);
                    $totalLength++;
                    break;
                } else {
                    throw new \UnexpectedValueException('Decode error: Invalid label type ' . $labelType . 'in domain name at position ' . $startIndex);
                }
            }
        }
        $result = [];
        foreach ($labels as $label) {
            if (\is_int($label[0])) {
                \array_unshift($result, $label[1]);
                $labelRegistry->register($result, $label[0]);
            } else {
                $result = $label;
            }
        }
        $domainName->setLabels($result);
        return $totalLength;
    }
    /**
     * Decode an IPv4Address field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\IPv4Address $ipv4Address The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeIPv4Address(DecodingContext $decodingContext, IPv4Address $ipv4Address) : int
    {
        $octets = \unpack('C4', $this->readDataFromPacket($decodingContext->getPacket(), 4));
        $ipv4Address->setOctets($octets);
        return 4;
    }
    /**
     * Decode an IPv6Address field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\IPv6Address $ipv6Address The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeIPv6Address(DecodingContext $decodingContext, IPv6Address $ipv6Address) : int
    {
        $shorts = \unpack('n8', $this->readDataFromPacket($decodingContext->getPacket(), 16));
        $ipv6Address->setShorts($shorts);
        return 16;
    }
    /**
     * Decode a Long field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Long $long The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeLong(DecodingContext $decodingContext, Long $long) : int
    {
        $value = \unpack('N', $this->readDataFromPacket($decodingContext->getPacket(), 4))[1];
        $long->setValue($value);
        return 4;
    }
    /**
     * Decode a Short field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Short $short The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeShort(DecodingContext $decodingContext, Short $short) : int
    {
        $value = \unpack('n', $this->readDataFromPacket($decodingContext->getPacket(), 2))[1];
        $short->setValue($value);
        return 2;
    }
    /**
     * Decode a Type field
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @param \LibDNS\Records\Types\Type $type The object to populate with the result
     * @param int $length Expected data length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     * @throws \InvalidArgumentException When the Type subtype is unknown
     */
    private function decodeType(DecodingContext $decodingContext, Type $type, int $length) : int
    {
        if ($type instanceof Anything) {
            $result = $this->decodeAnything($decodingContext, $type, $length);
        } else {
            if ($type instanceof BitMap) {
                $result = $this->decodeBitMap($decodingContext, $type, $length);
            } else {
                if ($type instanceof Char) {
                    $result = $this->decodeChar($decodingContext, $type);
                } else {
                    if ($type instanceof CharacterString) {
                        $result = $this->decodeCharacterString($decodingContext, $type);
                    } else {
                        if ($type instanceof DomainName) {
                            $result = $this->decodeDomainName($decodingContext, $type);
                        } else {
                            if ($type instanceof IPv4Address) {
                                $result = $this->decodeIPv4Address($decodingContext, $type);
                            } else {
                                if ($type instanceof IPv6Address) {
                                    $result = $this->decodeIPv6Address($decodingContext, $type);
                                } else {
                                    if ($type instanceof Long) {
                                        $result = $this->decodeLong($decodingContext, $type);
                                    } else {
                                        if ($type instanceof Short) {
                                            $result = $this->decodeShort($decodingContext, $type);
                                        } else {
                                            throw new \InvalidArgumentException('Unknown Type ' . \get_class($type));
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        return $result;
    }
    /**
     * Decode a question record
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @return \LibDNS\Records\Question
     * @throws \UnexpectedValueException When the record is invalid
     */
    private function decodeQuestionRecord(DecodingContext $decodingContext) : Question
    {
        /** @var \LibDNS\Records\Types\DomainName $domainName */
        $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
        $this->decodeDomainName($decodingContext, $domainName);
        $meta = \unpack('ntype/nclass', $this->readDataFromPacket($decodingContext->getPacket(), 4));
        $question = $this->questionFactory->create($meta['type']);
        $question->setName($domainName);
        $question->setClass($meta['class']);
        return $question;
    }
    /**
     * Decode a resource record
     *
     * @param \LibDNS\Decoder\DecodingContext $decodingContext
     * @return \LibDNS\Records\Resource
     * @throws \UnexpectedValueException When the record is invalid
     * @throws \InvalidArgumentException When a type subtype is unknown
     */
    private function decodeResourceRecord(DecodingContext $decodingContext) : Resource
    {
        /** @var \LibDNS\Records\Types\DomainName $domainName */
        $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
        $this->decodeDomainName($decodingContext, $domainName);
        $meta = \unpack('ntype/nclass/Nttl/nlength', $this->readDataFromPacket($decodingContext->getPacket(), 10));
        $resource = $this->resourceBuilder->build($meta['type']);
        $resource->setName($domainName);
        $resource->setClass($meta['class']);
        $resource->setTTL($meta['ttl']);
        $data = $resource->getData();
        $remainingLength = $meta['length'];
        $fieldDef = $index = null;
        foreach ($resource->getData()->getTypeDefinition() as $index => $fieldDef) {
            $field = $this->typeBuilder->build($fieldDef->getType());
            $remainingLength -= $this->decodeType($decodingContext, $field, $remainingLength);
            $data->setField($index, $field);
        }
        if ($fieldDef->allowsMultiple()) {
            while ($remainingLength) {
                $field = $this->typeBuilder->build($fieldDef->getType());
                $remainingLength -= $this->decodeType($decodingContext, $field, $remainingLength);
                $data->setField(++$index, $field);
            }
        }
        if ($remainingLength !== 0) {
            throw new \UnexpectedValueException('Decode error: Invalid length for record data section');
        }
        return $resource;
    }
    /**
     * Decode a Message from raw network data
     *
     * @param string $data The data string to decode
     * @return \LibDNS\Messages\Message
     * @throws \UnexpectedValueException When the packet data is invalid
     * @throws \InvalidArgumentException When a type subtype is unknown
     */
    public function decode(string $data) : Message
    {
        $packet = $this->packetFactory->create($data);
        $decodingContext = $this->decodingContextFactory->create($packet);
        $message = $this->messageFactory->create();
        $this->decodeHeader($decodingContext, $message);
        $questionRecords = $message->getQuestionRecords();
        $expected = $decodingContext->getExpectedQuestionRecords();
        for ($i = 0; $i < $expected; $i++) {
            $questionRecords->add($this->decodeQuestionRecord($decodingContext));
        }
        $answerRecords = $message->getAnswerRecords();
        $expected = $decodingContext->getExpectedAnswerRecords();
        for ($i = 0; $i < $expected; $i++) {
            $answerRecords->add($this->decodeResourceRecord($decodingContext));
        }
        $authorityRecords = $message->getAuthorityRecords();
        $expected = $decodingContext->getExpectedAuthorityRecords();
        for ($i = 0; $i < $expected; $i++) {
            $authorityRecords->add($this->decodeResourceRecord($decodingContext));
        }
        $additionalRecords = $message->getAdditionalRecords();
        $expected = $decodingContext->getExpectedAdditionalRecords();
        for ($i = 0; $i < $expected; $i++) {
            $additionalRecords->add($this->decodeResourceRecord($decodingContext));
        }
        if (!$this->allowTrailingData && $packet->getBytesRemaining() !== 0) {
            throw new \UnexpectedValueException('Decode error: Unexpected data at end of packet');
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible message response codes
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Enumeration;
/**
 * Enumeration of possible message types
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class MessageResponseCodes extends Enumeration
{
    const NO_ERROR = 0;
    const FORMAT_ERROR = 1;
    const SERVER_FAILURE = 2;
    const NAME_ERROR = 3;
    const NOT_IMPLEMENTED = 4;
    const REFUSED = 5;
}<?php

declare (strict_types=1);
/**
 * Represents a DNS protocol message
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Records\RecordCollection;
use LibDNS\Records\RecordCollectionFactory;
use LibDNS\Records\RecordTypes;
/**
 * Represents a DNS protocol message
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Message
{
    /**
     * @var int Unsigned short that identifies the DNS transaction
     */
    private $id = 0;
    /**
     * @var int Indicates the type of the message, can be indicated using the MessageTypes enum
     */
    private $type = -1;
    /**
     * @var int Message opcode, can be indicated using the MessageOpCodes enum
     */
    private $opCode = MessageOpCodes::QUERY;
    /**
     * @var bool Whether a response message is authoritative
     */
    private $authoritative = false;
    /**
     * @var bool Whether the message is truncated
     */
    private $truncated = false;
    /**
     * @var bool Whether a query desires the server to recurse the lookup
     */
    private $recursionDesired = true;
    /**
     * @var bool Whether a server could provide recursion in a response
     */
    private $recursionAvailable = false;
    /**
     * @var int Message response code, can be indicated using the MessageResponseCodes enum
     */
    private $responseCode = MessageResponseCodes::NO_ERROR;
    /**
     * @var \LibDNS\Records\RecordCollection Collection of question records
     */
    private $questionRecords;
    /**
     * @var \LibDNS\Records\RecordCollection Collection of question records
     */
    private $answerRecords;
    /**
     * @var \LibDNS\Records\RecordCollection Collection of authority records
     */
    private $authorityRecords;
    /**
     * @var \LibDNS\Records\RecordCollection Collection of authority records
     */
    private $additionalRecords;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\RecordCollectionFactory $recordCollectionFactory Factory which makes RecordCollection objects
     * @param int $type Value of the message type field
     * @throws \RangeException When the supplied message type is outside the valid range 0 - 1
     */
    public function __construct(RecordCollectionFactory $recordCollectionFactory, int $type = null)
    {
        $this->questionRecords = $recordCollectionFactory->create(RecordTypes::QUESTION);
        $this->answerRecords = $recordCollectionFactory->create(RecordTypes::RESOURCE);
        $this->authorityRecords = $recordCollectionFactory->create(RecordTypes::RESOURCE);
        $this->additionalRecords = $recordCollectionFactory->create(RecordTypes::RESOURCE);
        if ($type !== null) {
            $this->setType($type);
        }
    }
    /**
     * Get the value of the message ID field
     *
     * @return int
     */
    public function getID() : int
    {
        return $this->id;
    }
    /**
     * Set the value of the message ID field
     *
     * @param int $id The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 65535
     */
    public function setID(int $id)
    {
        if ($id < 0 || $id > 65535) {
            throw new \RangeException('Message ID must be in the range 0 - 65535');
        }
        $this->id = $id;
    }
    /**
     * Get the value of the message type field
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     * Set the value of the message type field
     *
     * @param int $type The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 1
     */
    public function setType(int $type)
    {
        if ($type < 0 || $type > 1) {
            throw new \RangeException('Message type must be in the range 0 - 1');
        }
        $this->type = $type;
    }
    /**
     * Get the value of the message opcode field
     *
     * @return int
     */
    public function getOpCode() : int
    {
        return $this->opCode;
    }
    /**
     * Set the value of the message opcode field
     *
     * @param int $opCode The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 15
     */
    public function setOpCode(int $opCode)
    {
        if ($opCode < 0 || $opCode > 15) {
            throw new \RangeException('Message opcode must be in the range 0 - 15');
        }
        $this->opCode = $opCode;
    }
    /**
     * Inspect the value of the authoritative field and optionally set a new value
     *
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isAuthoritative(bool $newValue = null) : bool
    {
        $result = $this->authoritative;
        if ($newValue !== null) {
            $this->authoritative = $newValue;
        }
        return $result;
    }
    /**
     * Inspect the value of the truncated field and optionally set a new value
     *
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isTruncated(bool $newValue = null) : bool
    {
        $result = $this->truncated;
        if ($newValue !== null) {
            $this->truncated = $newValue;
        }
        return $result;
    }
    /**
     * Inspect the value of the recusion desired field and optionally set a new value
     *
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isRecursionDesired(bool $newValue = null) : bool
    {
        $result = $this->recursionDesired;
        if ($newValue !== null) {
            $this->recursionDesired = $newValue;
        }
        return $result;
    }
    /**
     * Inspect the value of the recursion available field and optionally set a new value
     *
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isRecursionAvailable(bool $newValue = null) : bool
    {
        $result = $this->recursionAvailable;
        if ($newValue !== null) {
            $this->recursionAvailable = $newValue;
        }
        return $result;
    }
    /**
     * Get the value of the message response code field
     *
     * @return int
     */
    public function getResponseCode() : int
    {
        return $this->responseCode;
    }
    /**
     * Set the value of the message response code field
     *
     * @param int $responseCode The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 15
     */
    public function setResponseCode(int $responseCode)
    {
        if ($responseCode < 0 || $responseCode > 15) {
            throw new \RangeException('Message response code must be in the range 0 - 15');
        }
        $this->responseCode = $responseCode;
    }
    /**
     * Get the question records collection
     *
     * @return \LibDNS\Records\RecordCollection
     */
    public function getQuestionRecords() : RecordCollection
    {
        return $this->questionRecords;
    }
    /**
     * Get the answer records collection
     *
     * @return \LibDNS\Records\RecordCollection
     */
    public function getAnswerRecords() : RecordCollection
    {
        return $this->answerRecords;
    }
    /**
     * Get the authority records collection
     *
     * @return \LibDNS\Records\RecordCollection
     */
    public function getAuthorityRecords() : RecordCollection
    {
        return $this->authorityRecords;
    }
    /**
     * Get the additional records collection
     *
     * @return \LibDNS\Records\RecordCollection
     */
    public function getAdditionalRecords() : RecordCollection
    {
        return $this->additionalRecords;
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible message types
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Enumeration;
/**
 * Enumeration of possible message types
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class MessageTypes extends Enumeration
{
    const QUERY = 0;
    const RESPONSE = 1;
}<?php

declare (strict_types=1);
/**
 * Factory which creates Message objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Records\RecordCollectionFactory;
/**
 * Factory which creates Message objects
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class MessageFactory
{
    /**
     * Create a new Message object
     *
     * @param int $type Value of the message type field
     * @return \LibDNS\Messages\Message
     */
    public function create(int $type = null) : Message
    {
        return new Message(new RecordCollectionFactory(), $type);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible message opcodes
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Messages;

use LibDNS\Enumeration;
/**
 * Enumeration of possible message types
 *
 * @category LibDNS
 * @package Messages
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class MessageOpCodes extends Enumeration
{
    const QUERY = 0;
    const IQUERY = 1;
    const STATUS = 2;
}<?php

declare (strict_types=1);
/**
 * Base class for enumerations to prevent instantiation
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package LibDNS
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS;

/**
 * Base class for enumerations to prevent instantiation
 *
 * @category LibDNS
 * @package LibDNS
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class Enumeration
{
    /**
     *
     */
    protected final function __construct()
    {
        throw new \LogicException('Enumerations cannot be instantiated');
    }
}<?php

declare (strict_types=1);
namespace LibDNS;

if (\function_exists('idn_to_ascii')) {
    /**
     *
     */
    function normalize_name(string $label) : string
    {
        if (false === ($result = \idn_to_ascii($label, 0, INTL_IDNA_VARIANT_UTS46))) {
            throw new \InvalidArgumentException("Label '{$label}' could not be processed for IDN");
        }
        return $result;
    }
} else {
    /**
     *
     */
    function normalize_name(string $label) : string
    {
        if (\preg_match('/[\\x80-\\xff]/', $label)) {
            throw new \InvalidArgumentException("Label '{$label}' contains non-ASCII characters and IDN support is not available." . " Verify that ext/intl is installed for IDN support.");
        }
        return \strtolower($label);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible resource QCLASS values
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

/**
 * Enumeration of possible resource QCLASS values
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class ResourceQClasses extends ResourceClasses
{
    const ANY = 255;
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible record types
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Enumeration;
/**
 * Enumeration of possible record types
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class RecordTypes extends Enumeration
{
    const QUESTION = 0;
    const RESOURCE = 1;
}<?php

declare (strict_types=1);
/**
 * Creates ResourceBuilder objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\TypeFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionManager;
use LibDNS\Records\TypeDefinitions\TypeDefinitionFactory;
use LibDNS\Records\TypeDefinitions\FieldDefinitionFactory;
/**
 * Creates ResourceBuilder objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class ResourceBuilderFactory
{
    /**
     * Create a new ResourceBuilder object
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager
     * @return \LibDNS\Records\ResourceBuilder
     */
    public function create(TypeDefinitionManager $typeDefinitionManager = null) : ResourceBuilder
    {
        return new ResourceBuilder(new ResourceFactory(), new RDataBuilder(new RDataFactory(), new TypeBuilder(new TypeFactory())), $typeDefinitionManager ?: new TypeDefinitionManager(new TypeDefinitionFactory(), new FieldDefinitionFactory()));
    }
}<?php

declare (strict_types=1);
/**
 * Collection of Record objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

/**
 * Collection of Record objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RecordCollection implements \IteratorAggregate, \Countable
{
    /**
     * @var \LibDNS\Records\Record[] List of records held in the collection
     */
    private $records = [];
    /**
     * @var \LibDNS\Records\Record[][] Map of Records in the collection grouped by record name
     */
    private $nameMap = [];
    /**
     * @var int Number of Records in the collection
     */
    private $length = 0;
    /**
     * @var int Whether the collection holds question or resource records
     */
    private $type;
    /**
     * Constructor
     *
     * @param int $type Can be indicated using the RecordTypes enum
     * @throws \InvalidArgumentException When the specified record type is invalid
     */
    public function __construct($type)
    {
        if ($type !== RecordTypes::QUESTION && $type !== RecordTypes::RESOURCE) {
            throw new \InvalidArgumentException('Record type must be QUESTION or RESOURCE');
        }
        $this->type = $type;
    }
    /**
     * Add a record to the correct bucket in the name map
     *
     * @param \LibDNS\Records\Record $record The record to add
     */
    private function addToNameMap(Record $record)
    {
        if (!isset($this->nameMap[$name = (string) $record->getName()])) {
            $this->nameMap[$name] = [];
        }
        $this->nameMap[$name][] = $record;
    }
    /**
     * Remove a record from the name map
     *
     * @param \LibDNS\Records\Record $record The record to remove
     */
    private function removeFromNameMap(Record $record)
    {
        if (!empty($this->nameMap[$name = (string) $record->getName()])) {
            foreach ($this->nameMap[$name] as $key => $item) {
                if ($item === $record) {
                    \array_splice($this->nameMap[$name], $key, 1);
                    break;
                }
            }
        }
        if (empty($this->nameMap[$name])) {
            unset($this->nameMap[$name]);
        }
    }
    /**
     * Add a record to the collection
     *
     * @param \LibDNS\Records\Record $record The record to add
     * @throws \InvalidArgumentException When the wrong record type is supplied
     */
    public function add(Record $record)
    {
        if ($this->type === RecordTypes::QUESTION && !$record instanceof Question || $this->type === RecordTypes::RESOURCE && !$record instanceof Resource) {
            throw new \InvalidArgumentException('Incorrect record type for this collection');
        }
        $this->records[] = $record;
        $this->addToNameMap($record);
        $this->length++;
    }
    /**
     * Remove a record from the collection
     *
     * @param \LibDNS\Records\Record $record The record to remove
     */
    public function remove(Record $record)
    {
        foreach ($this->records as $key => $item) {
            if ($item === $record) {
                array_splice($this->records, $key, 1);
                $this->removeFromNameMap($record);
                $this->length--;
                return;
            }
        }
        throw new \InvalidArgumentException('The supplied record is not a member of this collection');
    }
    /**
     * Test whether the collection contains a specific record
     *
     * @param \LibDNS\Records\Record $record The record to search for
     * @param bool $sameInstance Whether to perform strict comparisons in search
     * @return bool
     */
    public function contains(Record $record, bool $sameInstance = false) : bool
    {
        return \in_array($record, $this->records, $sameInstance);
    }
    /**
     * Get all records in the collection that refer to the specified name
     *
     * @param string $name The name to match records against
     * @return \LibDNS\Records\Record[]
     */
    public function getRecordsByName(string $name) : array
    {
        return $this->nameMap[\strtolower($name)] ?? [];
    }
    /**
     * Get a record from the collection by index
     *
     * @param int $index Record index
     * @return \LibDNS\Records\Record
     * @throws \OutOfBoundsException When the supplied index does not refer to a valid record
     */
    public function getRecordByIndex(int $index) : Record
    {
        if (isset($this->records[$index])) {
            return $this->records[$index];
        }
        throw new \OutOfBoundsException('The specified index ' . $index . ' does not exist in the collection');
    }
    /**
     * Remove all records in the collection that refer to the specified name
     *
     * @param string $name The name to match records against
     * @return int The number of records removed
     */
    public function clearRecordsByName(string $name) : int
    {
        $count = 0;
        if (isset($this->nameMap[$name = \strtolower($name)])) {
            unset($this->nameMap[$name]);
            foreach ($this->records as $index => $record) {
                if ($record->getName() === $name) {
                    unset($this->records[$index]);
                    $count++;
                }
            }
            $this->records = \array_values($this->records);
        }
        return $count;
    }
    /**
     * Remove all records from the collection
     */
    public function clear()
    {
        $this->records = $this->nameMap = [];
        $this->length = 0;
    }
    /**
     * Get a list of all names referenced by records in the collection
     *
     * @return string[]
     */
    public function getNames() : array
    {
        return \array_keys($this->nameMap);
    }
    /**
     * Get whether the collection holds question or resource records
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     * Retrieve an iterator (IteratorAggregate interface)
     *
     * @return \Iterator
     */
    public function getIterator() : \Iterator
    {
        return new \ArrayIterator($this->records);
    }
    /**
     * Get the number of records in the collection (Countable interface)
     *
     * @return int
     */
    public function count() : int
    {
        return $this->length;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a DNS resource record
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeFactory;
/**
 * Represents a DNS resource record
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Resource extends Record
{
    /**
     * @var int Value of the resource's time-to-live property
     */
    private $ttl;
    /**
     * @var \LibDNS\Records\RData
     */
    private $data;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\Types\TypeFactory $typeFactory
     * @param int $type Can be indicated using the ResourceTypes enum
     * @param \LibDNS\Records\RData $data
     */
    public function __construct(TypeFactory $typeFactory, int $type, RData $data)
    {
        $this->typeFactory = $typeFactory;
        $this->type = $type;
        $this->data = $data;
    }
    /**
     * Get the value of the record TTL field
     *
     * @return int
     */
    public function getTTL() : int
    {
        return $this->ttl;
    }
    /**
     * Set the value of the record TTL field
     *
     * @param int $ttl The new value
     * @throws \RangeException When the supplied value is outside the valid range 0 - 4294967296
     */
    public function setTTL(int $ttl)
    {
        if ($ttl < 0 || $ttl > 4294967296) {
            throw new \RangeException('Record class must be in the range 0 - 4294967296');
        }
        $this->ttl = $ttl;
    }
    /**
     * Get the value of the resource data field
     *
     * @return \LibDNS\Records\RData
     */
    public function getData() : RData
    {
        return $this->data;
    }
}<?php

declare (strict_types=1);
/**
 * Creates RecordCollection objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

/**
 * Creates RecordCollection objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RecordCollectionFactory
{
    /**
     * Create a new RecordCollection object
     *
     * @param int $type Can be indicated using the RecordTypes enum
     * @return \LibDNS\Records\RecordCollection
     * @throws \InvalidArgumentException When the specified record type is invalid
     */
    public function create(int $type) : RecordCollection
    {
        return new RecordCollection($type);
    }
}<?php

declare (strict_types=1);
/**
 * Represents the RDATA section of a resource record
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\Type;
use LibDNS\Records\TypeDefinitions\TypeDefinition;
/**
 * Represents a data type comprising multiple simple types
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RData implements \IteratorAggregate, \Countable
{
    /**
     * @var \LibDNS\Records\Types\Type[] The items that make up the complex type
     */
    private $fields = [];
    /**
     * @var \LibDNS\Records\TypeDefinitions\TypeDefinition Structural definition of the fields
     */
    private $typeDef;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinition $typeDef
     */
    public function __construct(TypeDefinition $typeDef)
    {
        $this->typeDef = $typeDef;
    }
    /**
     * Magic method for type coersion to string
     *
     * @return string
     */
    public function __toString()
    {
        if ($handler = $this->typeDef->getToStringFunction()) {
            $result = \call_user_func_array($handler, $this->fields);
        } else {
            $result = \implode(',', $this->fields);
        }
        return $result;
    }
    /**
     * Get the field indicated by the supplied index
     *
     * @param int $index
     * @return \LibDNS\Records\Types\Type
     * @throws \OutOfBoundsException When the supplied index does not refer to a valid field
     */
    public function getField(int $index)
    {
        if (!isset($this->fields[$index])) {
            throw new \OutOfBoundsException('Index ' . $index . ' does not refer to a valid field');
        }
        return $this->fields[$index];
    }
    /**
     * Set the field indicated by the supplied index
     *
     * @param int $index
     * @param \LibDNS\Records\Types\Type $value
     * @throws \InvalidArgumentException When the supplied index/value pair does not match the type definition
     */
    public function setField(int $index, Type $value)
    {
        if (!$this->typeDef->getFieldDefinition($index)->assertDataValid($value)) {
            throw new \InvalidArgumentException('The supplied value is not valid for the specified index');
        }
        $this->fields[$index] = $value;
    }
    /**
     * Get the field indicated by the supplied name
     *
     * @param string $name
     * @return \LibDNS\Records\Types\Type
     * @throws \OutOfBoundsException When the supplied name does not refer to a valid field
     */
    public function getFieldByName(string $name) : Type
    {
        return $this->getField($this->typeDef->getFieldIndexByName($name));
    }
    /**
     * Set the field indicated by the supplied name
     *
     * @param string $name
     * @param \LibDNS\Records\Types\Type $value
     * @throws \OutOfBoundsException When the supplied name does not refer to a valid field
     * @throws \InvalidArgumentException When the supplied value does not match the type definition
     */
    public function setFieldByName(string $name, Type $value)
    {
        $this->setField($this->typeDef->getFieldIndexByName($name), $value);
    }
    /**
     * Get the structural definition of the fields
     *
     * @return \LibDNS\Records\TypeDefinitions\TypeDefinition
     */
    public function getTypeDefinition() : TypeDefinition
    {
        return $this->typeDef;
    }
    /**
     * Retrieve an iterator (IteratorAggregate interface)
     *
     * @return \Iterator
     */
    public function getIterator() : \Iterator
    {
        return new \ArrayIterator($this->fields);
    }
    /**
     * Get the number of fields (Countable interface)
     *
     * @return int
     */
    public function count() : int
    {
        return \count($this->fields);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible resource CLASS values
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Enumeration;
/**
 * Enumeration of possible resource CLASS values
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class ResourceClasses extends Enumeration
{
    const IN = 1;
    const CS = 2;
    const CH = 3;
    const HS = 4;
}<?php

declare (strict_types=1);
/**
 * Creates Resource objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeFactory;
/**
 * Creates Resource objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class ResourceFactory
{
    /**
     * Create a new Resource object
     *
     * @param int $type Can be indicated using the ResourceTypes enum
     * @param \LibDNS\Records\RData $data
     * @return \LibDNS\Records\Resource
     */
    public function create(int $type, RData $data) : Resource
    {
        return new Resource(new TypeFactory(), $type, $data);
    }
}<?php

declare (strict_types=1);
/**
 * Creates RData objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\TypeDefinitions\TypeDefinition;
/**
 * Creates RData objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RDataFactory
{
    /**
     * Create a new RData object
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinition $typeDefinition
     * @return \LibDNS\Records\RData
     */
    public function create(TypeDefinition $typeDefinition) : RData
    {
        return new RData($typeDefinition);
    }
}<?php

declare (strict_types=1);
/**
 * Builds Resource objects of a specific type
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\TypeDefinitions\TypeDefinitionManager;
/**
 * Builds Resource objects of a specific type
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class ResourceBuilder
{
    /**
     * @var \LibDNS\Records\ResourceFactory
     */
    private $resourceFactory;
    /**
     * @var \LibDNS\Records\RDataBuilder
     */
    private $rDataBuilder;
    /**
     * @var \LibDNS\Records\TypeDefinitions\TypeDefinitionManager
     */
    private $typeDefinitionManager;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\ResourceFactory $resourceFactory
     * @param \LibDNS\Records\RDataBuilder $rDataBuilder
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager
     */
    public function __construct(ResourceFactory $resourceFactory, RDataBuilder $rDataBuilder, TypeDefinitionManager $typeDefinitionManager)
    {
        $this->resourceFactory = $resourceFactory;
        $this->rDataBuilder = $rDataBuilder;
        $this->typeDefinitionManager = $typeDefinitionManager;
    }
    /**
     * Create a new Resource object
     *
     * @param int $type Type of the resource, can be indicated using the ResourceTypes enum
     * @return \LibDNS\Records\Resource
     */
    public function build(int $type) : Resource
    {
        $typeDefinition = $this->typeDefinitionManager->getTypeDefinition($type);
        $rData = $this->rDataBuilder->build($typeDefinition);
        return $this->resourceFactory->create($type, $rData);
    }
}<?php

declare (strict_types=1);
/**
 * Defines a field in a type
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
use LibDNS\Records\Types\Types;
/**
 * Defines a field in a type
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class FieldDefinition
{
    /**
     * @var int
     */
    private $index;
    /**
     * @var string
     */
    private $name;
    /**
     * @var int
     */
    private $type;
    /**
     * @var bool
     */
    private $allowsMultiple;
    /**
     * @var int
     */
    private $minimumValues;
    /**
     * Constructor
     *
     * @param int $index
     * @param string $name
     * @param int $type
     * @param bool $allowsMultiple
     * @param int $minimumValues
     */
    public function __construct(int $index, string $name, int $type, bool $allowsMultiple, int $minimumValues)
    {
        $this->index = $index;
        $this->name = $name;
        $this->type = $type;
        $this->allowsMultiple = $allowsMultiple;
        $this->minimumValues = $minimumValues;
    }
    /**
     * Get the index of the field in the containing type
     *
     * @return int
     */
    public function getIndex() : int
    {
        return $this->index;
    }
    /**
     * Get the name of the field
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * Get the type of the field
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     * Determine whether the field allows multiple values
     *
     * @return bool
     */
    public function allowsMultiple() : bool
    {
        return $this->allowsMultiple;
    }
    /**
     * Get the minimum number of values for the field
     *
     * @return int
     */
    public function getMinimumValues() : int
    {
        return $this->minimumValues;
    }
    /**
     * Assert that a Type object is valid for this field
     *
     * @param \LibDNS\Records\Types\Type
     * @return bool
     */
    public function assertDataValid(Type $value) : bool
    {
        return $this->type & Types::ANYTHING && $value instanceof Anything || $this->type & Types::BITMAP && $value instanceof BitMap || $this->type & Types::CHAR && $value instanceof Char || $this->type & Types::CHARACTER_STRING && $value instanceof CharacterString || $this->type & Types::DOMAIN_NAME && $value instanceof DomainName || $this->type & Types::IPV4_ADDRESS && $value instanceof IPv4Address || $this->type & Types::IPV6_ADDRESS && $value instanceof IPv6Address || $this->type & Types::LONG && $value instanceof Long || $this->type & Types::SHORT && $value instanceof Short;
    }
}<?php

declare (strict_types=1);
/**
 * Defines a data type comprising multiple fields
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

/**
 * Defines a data type comprising multiple fields
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeDefinition implements \IteratorAggregate, \Countable
{
    /**
     * @var FieldDefinitionFactory Creates FieldDefinition objects
     */
    private $fieldDefFactory;
    /**
     * @var int Number of fields in the type
     */
    private $fieldCount;
    /**
     * @var \LibDNS\Records\TypeDefinitions\FieldDefinition The last field defined by the type
     */
    private $lastField;
    /**
     * @var int[] Map of field indexes to type identifiers
     */
    private $fieldDefs = [];
    /**
     * @var int[] Map of field names to indexes
     */
    private $fieldNameMap = [];
    /**
     * @var callable Custom implementation for __toString() handling
     */
    private $toStringFunction;
    /**
     * Constructor
     *
     * @param FieldDefinitionFactory $fieldDefFactory
     * @param array $definition Structural definition of the fields
     * @throws \InvalidArgumentException When the type definition is invalid
     */
    public function __construct(FieldDefinitionFactory $fieldDefFactory, array $definition)
    {
        $this->fieldDefFactory = $fieldDefFactory;
        if (isset($definition['__toString'])) {
            if (!\is_callable($definition['__toString'])) {
                throw new \InvalidArgumentException('Invalid type definition: __toString() implementation is not callable');
            }
            $this->toStringFunction = $definition['__toString'];
            unset($definition['__toString']);
        }
        $this->fieldCount = \count($definition);
        $index = 0;
        foreach ($definition as $name => $type) {
            $this->registerField($index++, $name, $type);
        }
    }
    /**
     * Register a field from the type definition
     *
     * @param int $index
     * @param string $name
     * @param int $type
     * @throws \InvalidArgumentException When the field definition is invalid
     */
    private function registerField(int $index, string $name, int $type)
    {
        if (!\preg_match('/^(?P<name>[\\w\\-]+)(?P<quantifier>\\+|\\*)?(?P<minimum>(?<=\\+)\\d+)?$/', \strtolower($name), $matches)) {
            throw new \InvalidArgumentException('Invalid field definition ' . $name . ': Syntax error');
        }
        if (isset($matches['quantifier'])) {
            if ($index !== $this->fieldCount - 1) {
                throw new \InvalidArgumentException('Invalid field definition ' . $name . ': Quantifiers only allowed in last field');
            }
            if (!isset($matches['minimum'])) {
                $matches['minimum'] = $matches['quantifier'] === '+' ? 1 : 0;
            }
            $allowsMultiple = true;
            $minimumValues = (int) $matches['minimum'];
        } else {
            $allowsMultiple = false;
            $minimumValues = 0;
        }
        $this->fieldDefs[$index] = $this->fieldDefFactory->create($index, $matches['name'], $type, $allowsMultiple, $minimumValues);
        if ($index === $this->fieldCount - 1) {
            $this->lastField = $this->fieldDefs[$index];
        }
        $this->fieldNameMap[$matches['name']] = $index;
    }
    /**
     * Get the field definition indicated by the supplied index
     *
     * @param int $index
     * @return \LibDNS\Records\TypeDefinitions\FieldDefinition
     * @throws \OutOfBoundsException When the supplied index does not refer to a valid field
     */
    public function getFieldDefinition(int $index) : FieldDefinition
    {
        if (isset($this->fieldDefs[$index])) {
            $fieldDef = $this->fieldDefs[$index];
        } else {
            if ($index >= 0 && $this->lastField->allowsMultiple()) {
                $fieldDef = $this->lastField;
            } else {
                throw new \OutOfBoundsException('Index ' . $index . ' does not refer to a valid field');
            }
        }
        return $fieldDef;
    }
    /**
     * Get the field index indicated by the supplied name
     *
     * @param string $name
     * @return int
     * @throws \OutOfBoundsException When the supplied name does not refer to a valid field
     */
    public function getFieldIndexByName($name) : int
    {
        $fieldName = \strtolower($name);
        if (!isset($this->fieldNameMap[$fieldName])) {
            throw new \OutOfBoundsException('Name ' . $name . ' does not refer to a valid field');
        }
        return $this->fieldNameMap[$fieldName];
    }
    /**
     * Get the __toString() implementation
     *
     * @return (callable | null)
     */
    public function getToStringFunction()
    {
        return $this->toStringFunction;
    }
    /**
     * Set the __toString() implementation
     *
     * @param callable $function
     */
    public function setToStringFunction(callable $function)
    {
        $this->toStringFunction = $function;
    }
    /**
     * Retrieve an iterator (IteratorAggregate interface)
     *
     * @return \Iterator
     */
    public function getIterator() : \Iterator
    {
        return new \ArrayIterator($this->fieldDefs);
    }
    /**
     * Get the number of fields (Countable interface)
     *
     * @return int
     */
    public function count() : int
    {
        return $this->fieldCount;
    }
}<?php

declare (strict_types=1);
/**
 * Holds data about how the RDATA sections of known resource record types are structured
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

use LibDNS\Records\ResourceTypes;
use LibDNS\Records\Types\Types;
use LibDNS\Records\Types\DomainName;
/**
 * Holds data about how the RDATA sections of known resource record types are structured
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeDefinitionManager
{
    /**
     * @var array[] How the RDATA sections of known resource record types are structured
     */
    private $definitions = [];
    /**
     * @var array Cache of created definitions
     */
    private $typeDefs = [];
    /**
     * @var \LibDNS\Records\TypeDefinitions\TypeDefinitionFactory
     */
    private $typeDefFactory;
    /**
     * @var \LibDNS\Records\TypeDefinitions\FieldDefinitionFactory
     */
    private $fieldDefFactory;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionFactory $typeDefFactory
     * @param \LibDNS\Records\TypeDefinitions\FieldDefinitionFactory $fieldDefFactory
     */
    public function __construct(TypeDefinitionFactory $typeDefFactory, FieldDefinitionFactory $fieldDefFactory)
    {
        $this->typeDefFactory = $typeDefFactory;
        $this->fieldDefFactory = $fieldDefFactory;
        $this->setDefinitions();
    }
    /**
     * Set the internal definitions structure
     */
    private function setDefinitions()
    {
        // This is defined in a method because PHP doesn't let you define properties with
        // expressions at the class level. If anyone has a better way to do this I am open
        // to any and all suggestions.
        $this->definitions = [ResourceTypes::A => [
            // RFC 1035
            'address' => Types::IPV4_ADDRESS,
        ], ResourceTypes::AAAA => [
            // RFC 3596
            'address' => Types::IPV6_ADDRESS,
        ], ResourceTypes::AFSDB => [
            // RFC 1183
            'subtype' => Types::SHORT,
            'hostname' => Types::DOMAIN_NAME,
        ], ResourceTypes::CAA => [
            // RFC 6844
            'flags' => Types::DOMAIN_NAME,
            'tag' => Types::CHARACTER_STRING,
            'value' => Types::ANYTHING,
        ], ResourceTypes::CERT => [
            // RFC 4398
            'type' => Types::SHORT,
            'key-tag' => Types::SHORT,
            'algorithm' => Types::CHAR,
            'certificate' => Types::ANYTHING,
        ], ResourceTypes::CNAME => [
            // RFC 1035
            'cname' => Types::DOMAIN_NAME,
        ], ResourceTypes::DHCID => [
            // RFC 4701
            'identifier-type' => Types::SHORT,
            'digest-type' => Types::CHAR,
            'digest' => Types::ANYTHING,
        ], ResourceTypes::DLV => [
            // RFC 4034
            'key-tag' => Types::SHORT,
            'algorithm' => Types::CHAR,
            'digest-type' => Types::CHAR,
            'digest' => Types::ANYTHING,
        ], ResourceTypes::DNAME => [
            // RFC 4034
            'target' => Types::DOMAIN_NAME,
        ], ResourceTypes::DNSKEY => [
            // RFC 6672
            'flags' => Types::SHORT,
            'protocol' => Types::CHAR,
            'algorithm' => Types::CHAR,
            'public-key' => Types::ANYTHING,
        ], ResourceTypes::DS => [
            // RFC 4034
            'key-tag' => Types::SHORT,
            'algorithm' => Types::CHAR,
            'digest-type' => Types::CHAR,
            'digest' => Types::ANYTHING,
        ], ResourceTypes::HINFO => [
            // RFC 1035
            'cpu' => Types::CHARACTER_STRING,
            'os' => Types::CHARACTER_STRING,
        ], ResourceTypes::ISDN => [
            // RFC 1183
            'isdn-address' => Types::CHARACTER_STRING,
            'sa' => Types::CHARACTER_STRING,
        ], ResourceTypes::KEY => [
            // RFC 2535
            'flags' => Types::SHORT,
            'protocol' => Types::CHAR,
            'algorithm' => Types::CHAR,
            'public-key' => Types::ANYTHING,
        ], ResourceTypes::KX => [
            // RFC 2230
            'preference' => Types::SHORT,
            'exchange' => Types::DOMAIN_NAME,
        ], ResourceTypes::LOC => [
            // RFC 1876
            'version' => Types::CHAR,
            'size' => Types::CHAR,
            'horizontal-precision' => Types::CHAR,
            'vertical-precision' => Types::CHAR,
            'latitude' => Types::LONG,
            'longitude' => Types::LONG,
            'altitude' => Types::LONG,
        ], ResourceTypes::MB => [
            // RFC 1035
            'madname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MD => [
            // RFC 1035
            'madname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MF => [
            // RFC 1035
            'madname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MG => [
            // RFC 1035
            'mgmname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MINFO => [
            // RFC 1035
            'rmailbx' => Types::DOMAIN_NAME,
            'emailbx' => Types::DOMAIN_NAME,
        ], ResourceTypes::MR => [
            // RFC 1035
            'newname' => Types::DOMAIN_NAME,
        ], ResourceTypes::MX => [
            // RFC 1035
            'preference' => Types::SHORT,
            'exchange' => Types::DOMAIN_NAME,
        ], ResourceTypes::NAPTR => [
            // RFC 3403
            'order' => Types::SHORT,
            'preference' => Types::SHORT,
            'flags' => Types::CHARACTER_STRING,
            'services' => Types::CHARACTER_STRING,
            'regexp' => Types::CHARACTER_STRING,
            'replacement' => Types::DOMAIN_NAME,
        ], ResourceTypes::NS => [
            // RFC 1035
            'nsdname' => Types::DOMAIN_NAME,
        ], ResourceTypes::NULL => [
            // RFC 1035
            'data' => Types::ANYTHING,
        ], ResourceTypes::PTR => [
            // RFC 1035
            'ptrdname' => Types::DOMAIN_NAME,
        ], ResourceTypes::RP => [
            // RFC 1183
            'mbox-dname' => Types::DOMAIN_NAME,
            'txt-dname' => Types::DOMAIN_NAME,
        ], ResourceTypes::RT => [
            // RFC 1183
            'preference' => Types::SHORT,
            'intermediate-host' => Types::DOMAIN_NAME,
        ], ResourceTypes::SIG => [
            // RFC 4034
            'type-covered' => Types::SHORT,
            'algorithm' => Types::CHAR,
            'labels' => Types::CHAR,
            'original-ttl' => Types::LONG,
            'signature-expiration' => Types::LONG,
            'signature-inception' => Types::LONG,
            'key-tag' => Types::SHORT,
            'signers-name' => Types::DOMAIN_NAME,
            'signature' => Types::ANYTHING,
        ], ResourceTypes::SOA => [
            // RFC 1035
            'mname' => Types::DOMAIN_NAME,
            'rname' => Types::DOMAIN_NAME,
            'serial' => Types::LONG,
            'refresh' => Types::LONG,
            'retry' => Types::LONG,
            'expire' => Types::LONG,
            'minimum' => Types::LONG,
        ], ResourceTypes::SPF => [
            // RFC 4408
            'data+' => Types::CHARACTER_STRING,
        ], ResourceTypes::SRV => [
            // RFC 2782
            'priority' => Types::SHORT,
            'weight' => Types::SHORT,
            'port' => Types::SHORT,
            'name' => Types::DOMAIN_NAME | DomainName::FLAG_NO_COMPRESSION,
        ], ResourceTypes::TXT => [
            // RFC 1035
            'txtdata+' => Types::CHARACTER_STRING,
        ], ResourceTypes::WKS => [
            // RFC 1035
            'address' => Types::IPV4_ADDRESS,
            'protocol' => Types::SHORT,
            'bit-map' => Types::BITMAP,
        ], ResourceTypes::X25 => [
            // RFC 1183
            'psdn-address' => Types::CHARACTER_STRING,
        ]];
    }
    /**
     * Get a type definition for a record type if it is known
     *
     * @param int $recordType Resource type, can be indicated using the ResourceTypes enum
     * @return \LibDNS\Records\TypeDefinitions\TypeDefinition
     */
    public function getTypeDefinition(int $recordType)
    {
        if (!isset($this->typeDefs[$recordType])) {
            $definition = isset($this->definitions[$recordType]) ? $this->definitions[$recordType] : ['data' => Types::ANYTHING];
            $this->typeDefs[$recordType] = $this->typeDefFactory->create($this->fieldDefFactory, $definition);
        }
        return $this->typeDefs[$recordType];
    }
    /**
     * Register a custom type definition
     *
     * @param int $recordType Resource type, can be indicated using the ResourceTypes enum
     * @param (int[] | \LibDNS\Records\TypeDefinitions\TypeDefinition) $definition
     * @throws \InvalidArgumentException When the type definition is invalid
     */
    public function registerTypeDefinition(int $recordType, $definition)
    {
        if (!$definition instanceof TypeDefinition) {
            if (!\is_array($definition)) {
                throw new \InvalidArgumentException('Definition must be an array or an instance of ' . __NAMESPACE__ . '\\TypeDefinition');
            }
            $definition = $this->typeDefFactory->create($this->fieldDefFactory, $definition);
        }
        $this->typeDefs[$recordType] = $definition;
    }
}<?php

declare (strict_types=1);
/**
 * Creates TypeDefinition objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

/**
 * Creates TypeDefinition objects
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeDefinitionFactory
{
    /**
     * Create a new TypeDefinition object
     *
     * @param FieldDefinitionFactory $fieldDefinitionFactory
     * @param int[] $definition Structural definition of the fields
     * @return \LibDNS\Records\TypeDefinitions\TypeDefinition
     * @throws \InvalidArgumentException When the type definition is invalid
     */
    public function create(FieldDefinitionFactory $fieldDefinitionFactory, array $definition) : TypeDefinition
    {
        return new TypeDefinition($fieldDefinitionFactory, $definition);
    }
}<?php

declare (strict_types=1);
/**
 * Creates TypeDefinitionManager objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

/**
 * Creates TypeDefinitionManager objects
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeDefinitionManagerFactory
{
    /**
     * Create a new TypeDefinitionManager object
     *
     * @return \LibDNS\Records\TypeDefinitions\TypeDefinitionManager
     */
    public function create() : TypeDefinitionManager
    {
        return new TypeDefinitionManager(new TypeDefinitionFactory(), new FieldDefinitionFactory());
    }
}<?php

declare (strict_types=1);
/**
 * Creates FieldDefinition objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\TypeDefinitions;

/**
 * Creates FieldDefinition objects
 *
 * @category LibDNS
 * @package TypeDefinitions
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class FieldDefinitionFactory
{
    /**
     * Create a new FieldDefinition object
     *
     * @param int $index
     * @param string $name
     * @param int $type
     * @param bool $allowsMultiple
     * @param int $minimumValues
     * @return \LibDNS\Records\TypeDefinitions\FieldDefinition
     */
    public function create(int $index, string $name, int $type, bool $allowsMultiple, int $minimumValues) : FieldDefinition
    {
        return new FieldDefinition($index, $name, $type, $allowsMultiple, $minimumValues);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible resource TYPE values
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Enumeration;
/**
 * Enumeration of possible resource TYPE values
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class ResourceTypes extends Enumeration
{
    const A = 1;
    const AAAA = 28;
    const AFSDB = 18;
    //    const APL        = 42;
    const CAA = 257;
    const CERT = 37;
    const CNAME = 5;
    const DHCID = 49;
    const DLV = 32769;
    const DNAME = 39;
    const DNSKEY = 48;
    const DS = 43;
    const HINFO = 13;
    //    const HIP        = 55;
    //    const IPSECKEY   = 45;
    const KEY = 25;
    const KX = 36;
    const ISDN = 20;
    const LOC = 29;
    const MB = 7;
    const MD = 3;
    const MF = 4;
    const MG = 8;
    const MINFO = 14;
    const MR = 9;
    const MX = 15;
    const NAPTR = 35;
    const NS = 2;
    //    const NSEC       = 47;
    //    const NSEC3      = 50;
    //    const NSEC3PARAM = 50;
    const NULL = 10;
    const PTR = 12;
    const RP = 17;
    //    const RRSIG      = 46;
    const RT = 21;
    const SIG = 24;
    const SOA = 6;
    const SPF = 99;
    const SRV = 33;
    const TXT = 16;
    const WKS = 11;
    const X25 = 19;
}<?php

declare (strict_types=1);
/**
 * Creates Question objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeFactory;
/**
 * Creates Question objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class QuestionFactory
{
    /**
     * Create a new Question object
     *
     * @param int $type The resource type
     * @return \LibDNS\Records\Question
     */
    public function create(int $type) : Question
    {
        return new Question(new TypeFactory(), $type);
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of simple data types
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

use LibDNS\Enumeration;
/**
 * Enumeration of simple data types
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class Types extends Enumeration
{
    const ANYTHING = 0b1;
    const BITMAP = 0b10;
    const CHAR = 0b100;
    const CHARACTER_STRING = 0b1000;
    const DOMAIN_NAME = 0b10000;
    const IPV4_ADDRESS = 0b100000;
    const IPV6_ADDRESS = 0b1000000;
    const LONG = 0b10000000;
    const SHORT = 0b100000000;
}<?php

declare (strict_types=1);
/**
 * Represents an IPv4 address
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents an IPv4 address
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class IPv4Address extends Type
{
    /**
     * @var string
     */
    protected $value = '0.0.0.0';
    /**
     * @var int[] The octets of the address
     */
    private $octets = [0, 0, 0, 0];
    /**
     * Constructor
     *
     * @param (string | int[]) $value String representation or octet list
     * @throws \UnexpectedValueException When the supplied value is not a valid IPv4 address
     */
    public function __construct($value = null)
    {
        if (\is_array($value)) {
            $this->setOctets($value);
        } else {
            parent::__construct($value);
        }
    }
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is outside the valid length range 0 - 65535
     */
    public function setValue($value)
    {
        $this->setOctets(\explode('.', (string) $value));
    }
    /**
     * Get the address octets
     *
     * @return int[]
     */
    public function getOctets() : array
    {
        return $this->octets;
    }
    /**
     * Set the address octets
     *
     * @param int[] $octets The new address octets
     * @throws \UnexpectedValueException When the supplied octet list is not a valid IPv4 address
     */
    public function setOctets(array $octets)
    {
        if (\count($octets) !== 4) {
            throw new \UnexpectedValueException('Octet list is not a valid IPv4 address: invalid octet count');
        }
        foreach ($octets as &$octet) {
            if (!\is_int($octet) && !\ctype_digit((string) $octet) || $octet < 0x0 || $octet > 0xff) {
                throw new \UnexpectedValueException('Octet list is not a valid IPv4 address: invalid octet value ' . $octet);
            }
            $octet = (int) $octet;
        }
        $this->octets = \array_values($octets);
        $this->value = \implode('.', $this->octets);
    }
}<?php

declare (strict_types=1);
/**
 * Represents an 8-bit unsigned integer
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents an 8-bit unsigned integer
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Char extends Type
{
    /**
     * @var int
     */
    protected $value = 0;
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnderflowException When the supplied value is less than 0
     * @throws \OverflowException When the supplied value is greater than 255
     */
    public function setValue($value)
    {
        $value = (int) $value;
        if ($value < 0) {
            throw new \UnderflowException('Char value must be in the range 0 - 255');
        } else {
            if ($value > 255) {
                throw new \OverflowException('Char value must be in the range 0 - 255');
            }
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a bit map
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a bit map
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class BitMap extends Type
{
    /**
     * @var string
     */
    protected $value = '';
    /**
     * Set the internal value
     *
     * @param string $value The new value
     */
    public function setValue($value)
    {
        $this->value = (string) $value;
    }
    /**
     * Inspect the value of the bit at the specific index and optionally set a new value
     *
     * @param int $index
     * @param bool $newValue The new value
     * @return bool The old value
     */
    public function isBitSet(int $index, bool $newValue = null) : bool
    {
        $charIndex = (int) ($index / 8);
        $bitMask = 0b10000000 >> $index % 8;
        $result = false;
        if (isset($this->value[$charIndex])) {
            $result = (bool) (\ord($this->value[$charIndex]) & $bitMask);
        }
        if (isset($newValue) && $newValue != $result) {
            if (!isset($this->value[$charIndex])) {
                $this->value = \str_pad($this->value, $charIndex + 1, "\x00", STR_PAD_RIGHT);
            }
            $this->value[$charIndex] = \chr(\ord($this->value[$charIndex]) & ~$bitMask | ($newValue ? $bitMask : 0));
        }
        return $result;
    }
}<?php

declare (strict_types=1);
/**
 * Represents an IPv6 address
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents an IPv6 address
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class IPv6Address extends Type
{
    /**
     * @var string
     */
    protected $value = '::';
    /**
     * @var int[] The shorts of the address
     */
    private $shorts = [0, 0, 0, 0, 0, 0, 0, 0];
    /**
     * Create a compressed string representation of an IPv6 address
     *
     * @param int[] $shorts Address shorts
     * @return string
     */
    private function createCompressedString($shorts)
    {
        $compressLen = $compressPos = $currentLen = $currentPos = 0;
        $inBlock = false;
        for ($i = 0; $i < 8; $i++) {
            if ($shorts[$i] === 0) {
                if (!$inBlock) {
                    $inBlock = true;
                    $currentPos = $i;
                }
                $currentLen++;
            } else {
                if ($inBlock) {
                    if ($currentLen > $compressLen) {
                        $compressLen = $currentLen;
                        $compressPos = $currentPos;
                    }
                    $inBlock = false;
                    $currentPos = $currentLen = 0;
                }
            }
            $shorts[$i] = \dechex($shorts[$i]);
        }
        if ($inBlock) {
            $compressLen = $currentLen;
            $compressPos = $currentPos;
        }
        if ($compressLen > 1) {
            if ($compressLen === 8) {
                $replace = ['', '', ''];
            } else {
                if ($compressPos === 0 || $compressPos + $compressLen === 8) {
                    $replace = ['', ''];
                } else {
                    $replace = [''];
                }
            }
            \array_splice($shorts, $compressPos, $compressLen, $replace);
        }
        return \implode(':', $shorts);
    }
    /**
     * Constructor
     *
     * @param (string | int[]) $value String representation or shorts list
     * @throws \UnexpectedValueException When the supplied value is not a valid IPv6 address
     */
    public function __construct($value = null)
    {
        if (\is_array($value)) {
            $this->setShorts($value);
        } else {
            parent::__construct($value);
        }
    }
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is outside the valid length range 0 - 65535
     */
    public function setValue($value)
    {
        $shorts = \explode(':', (string) $value);
        $count = \count($shorts);
        if ($count < 3 || $count > 8) {
            throw new \UnexpectedValueException('Value is not a valid IPv6 address: invalid short count');
        } else {
            if ($shorts[0] === '' && $shorts[1] === '') {
                $shorts = \array_pad($shorts, -8, '0');
            } else {
                if ($shorts[$count - 2] === '' && $shorts[$count - 1] === '') {
                    $shorts = \array_pad($shorts, 8, '0');
                } else {
                    if (false !== ($pos = \array_search('', $shorts, true))) {
                        \array_splice($shorts, $pos, 1, \array_fill(0, 8 - ($count - 1), '0'));
                    }
                }
            }
        }
        $this->setShorts(\array_map('hexdec', $shorts));
    }
    /**
     * Get the address shorts
     *
     * @return int[]
     */
    public function getShorts() : array
    {
        return $this->shorts;
    }
    /**
     * Set the address shorts
     *
     * @param int[] $shorts The new address shorts
     * @throws \UnexpectedValueException When the supplied short list is not a valid IPv6 address
     */
    public function setShorts(array $shorts)
    {
        if (\count($shorts) !== 8) {
            throw new \UnexpectedValueException('Short list is not a valid IPv6 address: invalid short count');
        }
        foreach ($shorts as &$short) {
            if (!\is_int($short) && !\ctype_digit((string) $short) || $short < 0x0 || $short > 0xffff) {
                throw new \UnexpectedValueException('Short list is not a valid IPv6 address: invalid short value ' . $short);
            }
            $short = (int) $short;
        }
        $this->shorts = \array_values($shorts);
        $this->value = $this->createCompressedString($this->shorts);
    }
}<?php

declare (strict_types=1);
/**
 * Base class for simple data types
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Base class for simple data types
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class Type
{
    /**
     * @var mixed The internal value
     */
    protected $value;
    /**
     * Constructor
     *
     * @param string $value Internal value
     * @throws \RuntimeException When the supplied value is invalid
     */
    public function __construct(string $value = null)
    {
        if (isset($value)) {
            $this->setValue($value);
        }
    }
    /**
     * Magic method for type coercion to string
     *
     * @return string
     */
    public function __toString() : string
    {
        return (string) $this->value;
    }
    /**
     * Get the internal value
     *
     * @return mixed
     */
    public function getValue()
    {
        return $this->value;
    }
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \RuntimeException When the supplied value is invalid
     */
    public abstract function setValue($value);
}<?php

declare (strict_types=1);
/**
 * Creates Type objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Creates Type objects
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeFactory
{
    /**
     * Create a new Anything object
     *
     * @param string $value
     * @return \LibDNS\Records\Types\Anything
     */
    public function createAnything(string $value = null)
    {
        return new Anything($value);
    }
    /**
     * Create a new BitMap object
     *
     * @param string $value
     * @return \LibDNS\Records\Types\BitMap
     */
    public function createBitMap(string $value = null)
    {
        return new BitMap($value);
    }
    /**
     * Create a new Char object
     *
     * @param int $value
     * @return \LibDNS\Records\Types\Char
     */
    public function createChar(int $value = null)
    {
        return new Char((string) $value);
    }
    /**
     * Create a new CharacterString object
     *
     * @param string $value
     * @return \LibDNS\Records\Types\CharacterString
     */
    public function createCharacterString(string $value = null)
    {
        return new CharacterString($value);
    }
    /**
     * Create a new DomainName object
     *
     * @param (string | string[]) $value
     * @return \LibDNS\Records\Types\DomainName
     */
    public function createDomainName($value = null)
    {
        return new DomainName($value);
    }
    /**
     * Create a new IPv4Address object
     *
     * @param (string | int[]) $value
     * @return \LibDNS\Records\Types\IPv4Address
     */
    public function createIPv4Address($value = null)
    {
        return new IPv4Address($value);
    }
    /**
     * Create a new IPv6Address object
     *
     * @param (string | int[]) $value
     * @return \LibDNS\Records\Types\IPv6Address
     */
    public function createIPv6Address($value = null)
    {
        return new IPv6Address($value);
    }
    /**
     * Create a new Long object
     *
     * @param int $value
     * @return \LibDNS\Records\Types\Long
     */
    public function createLong(int $value = null)
    {
        return new Long((string) $value);
    }
    /**
     * Create a new Short object
     *
     * @param int $value
     * @return \LibDNS\Records\Types\Short
     */
    public function createShort(int $value = null)
    {
        return new Short((string) $value);
    }
}<?php

declare (strict_types=1);
/**
 * Represents a binary character string
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a binary character string
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class CharacterString extends Type
{
    /**
     * @var string
     */
    protected $value = '';
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is outside the valid length range 0 - 255
     */
    public function setValue($value)
    {
        $value = (string) $value;
        if (\strlen($value) > 255) {
            throw new \UnexpectedValueException('Character string length must be in the range 0 - 255');
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a 16-bit unsigned integer
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a 16-bit unsigned integer
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Short extends Type
{
    /**
     * @var int
     */
    protected $value = 0;
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnderflowException When the supplied value is less than 0
     * @throws \OverflowException When the supplied value is greater than 65535
     */
    public function setValue($value)
    {
        $value = (int) $value;
        if ($value < 0) {
            throw new \UnderflowException('Short integer value must be in the range 0 - 65535');
        } else {
            if ($value > 0xffff) {
                throw new \OverflowException('Short integer value must be in the range 0 - 65535');
            }
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a generic binary data string
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a generic binary data string
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Anything extends Type
{
    /**
     * @var string
     */
    protected $value = '';
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is outside the valid length range 0 - 65535
     */
    public function setValue($value)
    {
        $value = (string) $value;
        if (\strlen($value) > 65535) {
            throw new \UnexpectedValueException('Untyped string length must be in the range 0 - 65535');
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a 32-bit unsigned integer
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a 32-bit unsigned integer
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Long extends Type
{
    /**
     * @var int
     */
    protected $value = 0;
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnderflowException When the supplied value is less than 0
     * @throws \OverflowException When the supplied value is greater than 4294967296
     */
    public function setValue($value)
    {
        $value = (int) $value;
        if ($value < 0) {
            throw new \UnderflowException('Long integer value must be in the range 0 - 4294967296');
        } else {
            if ($value > 0xffffffff) {
                throw new \OverflowException('Long integer value must be in the range 0 - 4294967296');
            }
        }
        $this->value = $value;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a fully qualified domain name
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Represents a fully qualified domain name
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class DomainName extends Type
{
    const FLAG_NO_COMPRESSION = 0x80000000;
    /**
     * @var string
     */
    protected $value = '';
    /**
     * @var string[] The value as a list of labels
     */
    private $labels = [];
    /**
     * Constructor
     *
     * @param (string | string[]) $value
     * @throws \UnexpectedValueException When the supplied value is not a valid domain name
     */
    public function __construct($value = null)
    {
        if (\is_array($value)) {
            $this->setLabels($value);
        } else {
            parent::__construct($value);
        }
    }
    /**
     * Set the internal value
     *
     * @param string $value The new value
     * @throws \UnexpectedValueException When the supplied value is not a valid domain name
     */
    public function setValue($value)
    {
        $this->setLabels(\explode('.', (string) $value));
    }
    /**
     * Get the domain name labels
     *
     * @param bool $tldFirst Whether to return the label list ordered with the TLD label first
     * @return string[]
     */
    public function getLabels($tldFirst = false) : array
    {
        return $tldFirst ? \array_reverse($this->labels) : $this->labels;
    }
    /**
     * Set the domain name labels
     *
     * @param string[] $labels The new label list
     * @param bool $tldFirst Whether the supplied label list is ordered with the TLD label first
     * @throws \UnexpectedValueException When the supplied label list is not a valid domain name
     */
    public function setLabels(array $labels, $tldFirst = false)
    {
        if (!$labels) {
            $this->labels = [];
            $this->value = '';
            return;
        }
        $length = $count = 0;
        foreach ($labels as &$label) {
            $label = \LibDNS\normalize_name($label);
            $labelLength = \strlen($label);
            if ($labelLength > 63) {
                throw new \InvalidArgumentException('Label list is not a valid domain name: Label ' . $label . ' length exceeds 63 byte limit');
            }
            $length += $labelLength + 1;
            $count++;
        }
        $tld = $tldFirst ? $labels[0] : $labels[$count - 1];
        if ($tld === '') {
            $length--;
        }
        if ($length + 1 > 255) {
            throw new \InvalidArgumentException('Label list is not a valid domain name: Total length exceeds 255 byte limit');
        }
        $this->labels = $tldFirst ? \array_reverse($labels) : $labels;
        $this->value = \implode('.', $this->labels);
    }
}<?php

declare (strict_types=1);
/**
 * Builds Types from type definitions
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records\Types;

/**
 * Builds Types from type definitions
 *
 * @category LibDNS
 * @package Types
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class TypeBuilder
{
    /**
     * @var \LibDNS\Records\Types\TypeFactory
     */
    private $typeFactory;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\Types\TypeFactory $typeFactory
     */
    public function __construct(TypeFactory $typeFactory)
    {
        $this->typeFactory = $typeFactory;
    }
    /**
     * Build a new Type object corresponding to a resource record type
     *
     * @param int $type Data type, can be indicated using the Types enum
     * @return \LibDNS\Records\Types\Type
     */
    public function build(int $type) : Type
    {
        static $typeMap = [Types::ANYTHING => 'createAnything', Types::BITMAP => 'createBitMap', Types::CHAR => 'createChar', Types::CHARACTER_STRING => 'createCharacterString', Types::DOMAIN_NAME => 'createDomainName', Types::IPV4_ADDRESS => 'createIPv4Address', Types::IPV6_ADDRESS => 'createIPv6Address', Types::LONG => 'createLong', Types::SHORT => 'createShort'];
        if (!isset($typeMap[$type])) {
            throw new \InvalidArgumentException('Invalid Type identifier ' . $type);
        }
        return $this->typeFactory->{$typeMap[$type]}();
    }
}<?php

declare (strict_types=1);
/**
 * Enumeration of possible resource QTYPE values
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

/**
 * Enumeration of possible resource QTYPE values
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
final class ResourceQTypes extends ResourceTypes
{
    const AXFR = 252;
    const MAILB = 253;
    const MAILA = 254;
    const ALL = 255;
}<?php

declare (strict_types=1);
/**
 * Builds RData objects from a type definition
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\TypeDefinitions\TypeDefinition;
use LibDNS\Records\Types\TypeBuilder;
/**
 * Creates RData objects
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class RDataBuilder
{
    /**
     * @var \LibDNS\Records\RDataFactory
     */
    private $rDataFactory;
    /**
     * @var \LibDNS\Records\Types\TypeBuilder
     */
    private $typeBuilder;
    /**
     * Constructor
     *
     * @param \LibDNS\Records\RDataFactory $rDataFactory
     * @param \LibDNS\Records\Types\TypeBuilder $typeBuilder
     */
    public function __construct(RDataFactory $rDataFactory, TypeBuilder $typeBuilder)
    {
        $this->rDataFactory = $rDataFactory;
        $this->typeBuilder = $typeBuilder;
    }
    /**
     * Create a new RData object
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinition $typeDefinition
     * @return \LibDNS\Records\RData
     */
    public function build(TypeDefinition $typeDefinition) : RData
    {
        $rData = $this->rDataFactory->create($typeDefinition);
        foreach ($typeDefinition as $index => $type) {
            $rData->setField($index, $this->typeBuilder->build($type->getType()));
        }
        return $rData;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a DNS question record
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\TypeFactory;
/**
 * Represents a DNS question record
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Question extends Record
{
    /**
     * Constructor
     *
     * @param \LibDNS\Records\Types\TypeFactory $typeFactory
     * @param int $type Resource type being requested, can be indicated using the ResourceQTypes enum
     */
    public function __construct(TypeFactory $typeFactory, int $type)
    {
        $this->typeFactory = $typeFactory;
        $this->type = $type;
    }
}<?php

declare (strict_types=1);
/**
 * Represents a DNS record
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Records;

use LibDNS\Records\Types\DomainName;
/**
 * Represents a DNS record
 *
 * @category LibDNS
 * @package Records
 * @author Chris Wright <https://github.com/DaveRandom>
 */
abstract class Record
{
    /**
     * @var \LibDNS\Records\Types\TypeFactory
     */
    protected $typeFactory;
    /**
     * @var \LibDNS\Records\Types\DomainName
     */
    protected $name;
    /**
     * @var int
     */
    protected $type;
    /**
     * @var int
     */
    protected $class = ResourceClasses::IN;
    /**
     * Get the value of the record name field
     *
     * @return \LibDNS\Records\Types\DomainName
     */
    public function getName() : DomainName
    {
        return $this->name;
    }
    /**
     * Set the value of the record name field
     *
     * @param (string | \LibDNS\Records\Types\DomainName) $name
     * @throws \UnexpectedValueException When the supplied value is not a valid domain name
     */
    public function setName($name)
    {
        if (!$name instanceof DomainName) {
            $name = $this->typeFactory->createDomainName((string) $name);
        }
        $this->name = $name;
    }
    /**
     * Get the value of the record type field
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     * Get the value of the record class field
     *
     * @return int
     */
    public function getClass() : int
    {
        return $this->class;
    }
    /**
     * Set the value of the record class field
     *
     * @param int $class The new value, can be indicated using the ResourceClasses/ResourceQClasses enums
     * @throws \RangeException When the supplied value is outside the valid range 0 - 65535
     */
    public function setClass(int $class)
    {
        if ($class < 0 || $class > 65535) {
            throw new \RangeException('Record class must be in the range 0 - 65535');
        }
        $this->class = $class;
    }
}<?php

declare (strict_types=1);
/**
 * Creates Packet objects
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Packets;

/**
 * Creates Packet objects
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class PacketFactory
{
    /**
     * Create a new Packet object
     *
     * @param string $data
     * @return \LibDNS\Packets\Packet
     */
    public function create(string $data = '') : Packet
    {
        return new Packet($data);
    }
}<?php

declare (strict_types=1);
/**
 * Represents a raw network data packet
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Packets;

/**
 * Represents a raw network data packet
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class Packet
{
    /**
     * @var string
     */
    private $data;
    /**
     * @var int Data length
     */
    private $length;
    /**
     * @var int Read pointer
     */
    private $pointer = 0;
    /**
     * Constructor
     *
     * @param string $data The initial packet raw data
     */
    public function __construct(string $data = '')
    {
        $this->data = $data;
        $this->length = \strlen($this->data);
    }
    /**
     * Read bytes from the packet data
     *
     * @param int $length The number of bytes to read
     * @return string
     * @throws \OutOfBoundsException When the pointer position is invalid or the supplied length is negative
     */
    public function read(int $length = null) : string
    {
        if ($this->pointer > $this->length) {
            throw new \OutOfBoundsException('Pointer position invalid');
        }
        if ($length === null) {
            $result = \Phabel\Target\Php80\Polyfill::substr($this->data, $this->pointer);
            $this->pointer = $this->length;
        } else {
            if ($length < 0) {
                throw new \OutOfBoundsException('Length must be a positive integer');
            }
            $result = \Phabel\Target\Php80\Polyfill::substr($this->data, $this->pointer, $length);
            $this->pointer += $length;
        }
        return $result;
    }
    /**
     * Append data to the packet
     *
     * @param string $data The data to append
     * @return int The number of bytes written
     */
    public function write(string $data) : int
    {
        $length = \strlen($data);
        $this->data .= $data;
        $this->length += $length;
        return $length;
    }
    /**
     * Reset the read pointer
     */
    public function reset()
    {
        $this->pointer = 0;
    }
    /**
     * Get the pointer index
     *
     * @return int
     */
    public function getPointer() : int
    {
        return $this->pointer;
    }
    /**
     * Get the data length
     *
     * @return int
     */
    public function getLength() : int
    {
        return $this->length;
    }
    /**
     * Get the number of remaining bytes from the pointer position
     *
     * @return int
     */
    public function getBytesRemaining() : int
    {
        return $this->length - $this->pointer;
    }
}<?php

declare (strict_types=1);
/**
 * Maintains a list of the relationships between domain name labels and the first point at
 * which they appear in a packet
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace LibDNS\Packets;

/**
 * Creates Packet objects
 *
 * @category LibDNS
 * @package Packets
 * @author Chris Wright <https://github.com/DaveRandom>
 */
class LabelRegistry
{
    /**
     * @var int[] Map of labels to indexes
     */
    private $labels = [];
    /**
     * @var string[][] Map of indexes to labels
     */
    private $indexes = [];
    /**
     * Register a new relationship
     *
     * @param (string | string[]) $labels
     * @param int $index
     */
    public function register($labels, int $index)
    {
        if (\is_array($labels)) {
            $labelsArr = $labels;
            $labelsStr = \implode('.', $labels);
        } else {
            $labelsArr = \explode('.', $labels);
            $labelsStr = (string) $labels;
        }
        if (!isset($this->labels[$labelsStr]) || $index < $this->labels[$labelsStr]) {
            $this->labels[$labelsStr] = $index;
        }
        $this->indexes[$index] = $labelsArr;
    }
    /**
     * Lookup the index of a label
     *
     * @param string $label
     * @return (int | null)
     */
    public function lookupIndex(string $label)
    {
        return $this->labels[$label] ?? null;
    }
    /**
     * Lookup the label at an index
     *
     * @param int $index
     * @return (string[] | null)
     */
    public function lookupLabel(int $index)
    {
        return $this->indexes[$index] ?? null;
    }
}<?php

/**
 * This file was automatically generated by autoload_generator.php
 *
 * Do not edit this file directly
 */
\Phabel\Target\Php80\Polyfill::spl_autoload_register(function ($className) {
    static $classMap;
    if (!isset($classMap)) {
        $classMap = ['libdns\\decoder\\decoder' => __DIR__ . '/../src/Decoder/Decoder.php', 'libdns\\decoder\\decoderfactory' => __DIR__ . '/../src/Decoder/DecoderFactory.php', 'libdns\\decoder\\decodingcontext' => __DIR__ . '/../src/Decoder/DecodingContext.php', 'libdns\\decoder\\decodingcontextfactory' => __DIR__ . '/../src/Decoder/DecodingContextFactory.php', 'libdns\\encoder\\encoder' => __DIR__ . '/../src/Encoder/Encoder.php', 'libdns\\encoder\\encoderfactory' => __DIR__ . '/../src/Encoder/EncoderFactory.php', 'libdns\\encoder\\encodingcontext' => __DIR__ . '/../src/Encoder/EncodingContext.php', 'libdns\\encoder\\encodingcontextfactory' => __DIR__ . '/../src/Encoder/EncodingContextFactory.php', 'libdns\\enumeration' => __DIR__ . '/../src/Enumeration.php', 'libdns\\messages\\message' => __DIR__ . '/../src/Messages/Message.php', 'libdns\\messages\\messagefactory' => __DIR__ . '/../src/Messages/MessageFactory.php', 'libdns\\messages\\messageopcodes' => __DIR__ . '/../src/Messages/MessageOpCodes.php', 'libdns\\messages\\messageresponsecodes' => __DIR__ . '/../src/Messages/MessageResponseCodes.php', 'libdns\\messages\\messagetypes' => __DIR__ . '/../src/Messages/MessageTypes.php', 'libdns\\packets\\labelregistry' => __DIR__ . '/../src/Packets/LabelRegistry.php', 'libdns\\packets\\packet' => __DIR__ . '/../src/Packets/Packet.php', 'libdns\\packets\\packetfactory' => __DIR__ . '/../src/Packets/PacketFactory.php', 'libdns\\records\\question' => __DIR__ . '/../src/Records/Question.php', 'libdns\\records\\questionfactory' => __DIR__ . '/../src/Records/QuestionFactory.php', 'libdns\\records\\rdata' => __DIR__ . '/../src/Records/RData.php', 'libdns\\records\\rdatabuilder' => __DIR__ . '/../src/Records/RDataBuilder.php', 'libdns\\records\\rdatafactory' => __DIR__ . '/../src/Records/RDataFactory.php', 'libdns\\records\\record' => __DIR__ . '/../src/Records/Record.php', 'libdns\\records\\recordcollection' => __DIR__ . '/../src/Records/RecordCollection.php', 'libdns\\records\\recordcollectionfactory' => __DIR__ . '/../src/Records/RecordCollectionFactory.php', 'libdns\\records\\recordtypes' => __DIR__ . '/../src/Records/RecordTypes.php', 'libdns\\records\\resource' => __DIR__ . '/../src/Records/Resource.php', 'libdns\\records\\resourcebuilder' => __DIR__ . '/../src/Records/ResourceBuilder.php', 'libdns\\records\\resourcebuilderfactory' => __DIR__ . '/../src/Records/ResourceBuilderFactory.php', 'libdns\\records\\resourceclasses' => __DIR__ . '/../src/Records/ResourceClasses.php', 'libdns\\records\\resourcefactory' => __DIR__ . '/../src/Records/ResourceFactory.php', 'libdns\\records\\resourceqclasses' => __DIR__ . '/../src/Records/ResourceQClasses.php', 'libdns\\records\\resourceqtypes' => __DIR__ . '/../src/Records/ResourceQTypes.php', 'libdns\\records\\resourcetypes' => __DIR__ . '/../src/Records/ResourceTypes.php', 'libdns\\records\\typedefinitions\\fielddefinition' => __DIR__ . '/../src/Records/TypeDefinitions/FieldDefinition.php', 'libdns\\records\\typedefinitions\\fielddefinitionfactory' => __DIR__ . '/../src/Records/TypeDefinitions/FieldDefinitionFactory.php', 'libdns\\records\\typedefinitions\\typedefinition' => __DIR__ . '/../src/Records/TypeDefinitions/TypeDefinition.php', 'libdns\\records\\typedefinitions\\typedefinitionfactory' => __DIR__ . '/../src/Records/TypeDefinitions/TypeDefinitionFactory.php', 'libdns\\records\\typedefinitions\\typedefinitionmanager' => __DIR__ . '/../src/Records/TypeDefinitions/TypeDefinitionManager.php', 'libdns\\records\\typedefinitions\\typedefinitionmanagerfactory' => __DIR__ . '/../src/Records/TypeDefinitions/TypeDefinitionManagerFactory.php', 'libdns\\records\\types\\anything' => __DIR__ . '/../src/Records/Types/Anything.php', 'libdns\\records\\types\\bitmap' => __DIR__ . '/../src/Records/Types/BitMap.php', 'libdns\\records\\types\\char' => __DIR__ . '/../src/Records/Types/Char.php', 'libdns\\records\\types\\characterstring' => __DIR__ . '/../src/Records/Types/CharacterString.php', 'libdns\\records\\types\\domainname' => __DIR__ . '/../src/Records/Types/DomainName.php', 'libdns\\records\\types\\ipv4address' => __DIR__ . '/../src/Records/Types/IPv4Address.php', 'libdns\\records\\types\\ipv6address' => __DIR__ . '/../src/Records/Types/IPv6Address.php', 'libdns\\records\\types\\long' => __DIR__ . '/../src/Records/Types/Long.php', 'libdns\\records\\types\\short' => __DIR__ . '/../src/Records/Types/Short.php', 'libdns\\records\\types\\type' => __DIR__ . '/../src/Records/Types/Type.php', 'libdns\\records\\types\\typebuilder' => __DIR__ . '/../src/Records/Types/TypeBuilder.php', 'libdns\\records\\types\\typefactory' => __DIR__ . '/../src/Records/Types/TypeFactory.php', 'libdns\\records\\types\\types' => __DIR__ . '/../src/Records/Types/Types.php'];
    }
    $className = strtolower($className);
    if (isset($classMap[$className])) {
        /** @noinspection PhpIncludeInspection */
        require $classMap[$className];
    }
});<?php

/**
 * Makes a simple A record lookup query and outputs the results
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Examples
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 1.0.0
 */
namespace LibDNS\Examples;

use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\ResourceQTypes;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Decoder\DecoderFactory;
// Config
$queryName = 'faÃŸ.de';
$serverIP = '8.8.8.8';
$requestTimeout = 3;
require __DIR__ . '/autoload.php';
// Create question record
$question = (new QuestionFactory())->create(ResourceQTypes::A);
$question->setName($queryName);
// Create request message
$request = (new MessageFactory())->create(MessageTypes::QUERY);
$request->getQuestionRecords()->add($question);
$request->isRecursionDesired(true);
// Encode request message
$encoder = (new EncoderFactory())->create();
$requestPacket = $encoder->encode($request);
echo "\n" . $queryName . ":\n";
// Send request
$socket = stream_socket_client("udp://{$serverIP}:53");
stream_socket_sendto($socket, $requestPacket);
$r = [$socket];
$w = $e = [];
if (!stream_select($r, $w, $e, $requestTimeout)) {
    echo "    Request timeout.\n";
    exit;
}
// Decode response message
$decoder = (new DecoderFactory())->create();
$responsePacket = fread($socket, 512);
$response = $decoder->decode($responsePacket);
// Handle response
if ($response->getResponseCode() !== 0) {
    echo "    Server returned error code " . $response->getResponseCode() . ".\n";
    exit;
}
$answers = $response->getAnswerRecords();
if (count($answers)) {
    foreach ($response->getAnswerRecords() as $record) {
        /** @var \LibDNS\Records\Resource $record */
        echo "    " . $record->getData() . "\n";
    }
} else {
    echo "    Not found.\n";
}<?php

/**
 * Makes a simple A record lookup query and outputs the results
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Examples
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 1.0.0
 */
namespace LibDNS\Examples;

use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\ResourceTypes;
use LibDNS\Records\ResourceQTypes;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionManagerFactory;
// Config
$queryName = 'google.com';
$serverIP = '8.8.8.8';
$requestTimeout = 3;
require __DIR__ . '/autoload.php';
// Create question record
$question = (new QuestionFactory())->create(ResourceQTypes::SOA);
$question->setName($queryName);
// Create request message
$request = (new MessageFactory())->create(MessageTypes::QUERY);
$request->getQuestionRecords()->add($question);
$request->isRecursionDesired(true);
// Encode request message
$encoder = (new EncoderFactory())->create();
$requestPacket = $encoder->encode($request);
echo "\n" . $queryName . ":\n";
// Send request
$socket = stream_socket_client("udp://{$serverIP}:53");
stream_socket_sendto($socket, $requestPacket);
$r = [$socket];
$w = $e = [];
if (!stream_select($r, $w, $e, $requestTimeout)) {
    echo "    Request timeout.\n";
    exit;
}
// Create type definition manager for custom manipulation
$typeDefs = (new TypeDefinitionManagerFactory())->create();
$typeDefs->getTypeDefinition(ResourceTypes::SOA)->setToStringFunction(function ($mname, $rname, $serial, $refresh, $retry, $expire, $minimum) {
    return <<<DATA
{
    Primary Name Server : {$mname}
    Responsible Mail    : {$rname}
    Serial              : {$serial}
    Refresh             : {$refresh}
    Retry               : {$retry}
    Expire              : {$expire}
    Default TTL         : {$minimum}
}
DATA;
});
// Decode response message
$decoder = (new DecoderFactory())->create($typeDefs);
$responsePacket = fread($socket, 512);
$response = $decoder->decode($responsePacket);
// Handle response
if ($response->getResponseCode() !== 0) {
    echo "    Server returned error code " . $response->getResponseCode() . ".\n";
    exit;
}
$answers = $response->getAnswerRecords();
if (count($answers)) {
    foreach ($response->getAnswerRecords() as $record) {
        /** @var \LibDNS\Records\Resource $record */
        echo "    " . $record->getData() . "\n";
    }
} else {
    echo "    Not found.\n";
}<?php

/**
 * Generates a class-map based autoloader file for the examples directory
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Tools
 * @author Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 1.0.0
 */
namespace LibDNS\Tools;

use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
use FilesystemIterator;
\Phabel\Target\Php80\Polyfill::error_reporting(0);
ini_set('display_errors', 0);
if (!isset($argv[1])) {
    $srcDir = getcwd();
} else {
    if (in_array(strtolower($argv[1]), ['--help', '?', '/?'])) {
        exit("Syntax: " . __FILE__ . " [source directory]\n");
    } else {
        if (!is_dir($srcDir = $argv[1])) {
            exit("Invalid source directory\n\nSyntax: " . __FILE__ . " [source directory]\n");
        }
    }
}
$srcDir = str_replace('\\', '/', $srcDir);
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($srcDir, FilesystemIterator::KEY_AS_PATHNAME | FilesystemIterator::CURRENT_AS_FILEINFO | FilesystemIterator::SKIP_DOTS));
$items = [];
$stripLength = strlen($srcDir) + 1;
$maxLength = 0;
foreach ($iterator as $item) {
    if ($item->isFile() && $item->getFilename() !== 'autoload.php' && strtolower($item->getExtension()) === 'php') {
        $classPath = \Phabel\Target\Php80\Polyfill::substr($item->getPath() . '\\' . $item->getBasename('.' . $item->getExtension()), $stripLength);
        $lookupName = strtolower(str_replace('/', '\\', $classPath));
        $loadPath = "__DIR__ . '/{$srcDir}/" . str_replace('\\', '/', $classPath) . ".php'";
        $length = strlen($classPath);
        if ($length > $maxLength) {
            $maxLength = $length;
        }
        $items[$lookupName] = $loadPath;
    }
}
unset($iterator);
$output = <<<'PHP'
<?php
/**
 * This file was automatically generated by autoload_generator.php
 *
 * Do not edit this file directly
 */

spl_autoload_register(function($className) {
    static $classMap;
    if (!isset($classMap)) {
        $classMap = [
PHP;
$maxLength += 2;
foreach ($items as $lookupName => $loadPath) {
    $output .= "\n            " . str_pad("'" . $lookupName . "'", $maxLength, ' ', STR_PAD_RIGHT) . " => {$loadPath},";
}
$output .= <<<'PHP'

        ];
    }

    $className = strtolower($className);
    if (isset($classMap[$className])) {
        /** @noinspection PhpIncludeInspection */
        require $classMap[$className];
    }
});

PHP;
file_put_contents(getcwd() . '/autoload.php', $output);{
    "name": "daverandom/libdns",
    "description": "DNS protocol implementation written in pure PHP",
    "license": "MIT",
    "keywords": ["dns"],
    "require": {
        "php": ">=7.0",
        "ext-ctype": "*"
    },
    "autoload": {
        "psr-4": {
            "LibDNS\\": "src/"
        },
        "files": ["src/functions.php"]
    },
    "support": {
        "issues": "https://github.com/DaveRandom/LibDNS/issues"
    },
    "suggest": {
        "ext-intl": "Required for IDN support"
    }
}
<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriInterface;
use League\Uri\Exceptions\SyntaxError;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use function is_object;
use function is_scalar;
use function method_exists;
use function sprintf;
final class Http implements Psr7UriInterface, \JsonSerializable
{
    /**
     * @var UriInterface
     */
    private $uri;
    /**
     * New instance.
     */
    private function __construct(UriInterface $uri)
    {
        $this->validate($uri);
        $this->uri = $uri;
    }
    /**
     * Validate the submitted uri against PSR-7 UriInterface.
     *
     * @throws SyntaxError if the given URI does not follow PSR-7 UriInterface rules
     */
    private function validate(UriInterface $uri) : void
    {
        $scheme = $uri->getScheme();
        if (null === $scheme && '' === $uri->getHost()) {
            throw new SyntaxError(sprintf('an URI without scheme can not contains a empty host string according to PSR-7: %s', (string) $uri));
        }
        $port = $uri->getPort();
        if (null !== $port && ($port < 0 || $port > 65535)) {
            throw new SyntaxError(sprintf('The URI port is outside the established TCP and UDP port ranges: %s', (string) $uri->getPort()));
        }
    }
    /**
     * Static method called by PHP's var export.
     */
    public static function __set_state(array $components) : self
    {
        return new self($components['uri']);
    }
    /**
     * Create a new instance from a string.
     *
     * @param (string | mixed) $uri
     */
    public static function createFromString($uri = '') : self
    {
        return new self(Uri::createFromString($uri));
    }
    /**
    * Create a new instance from a hash of parse_url parts.
    *
    * @param array $components a hash representation of the URI similar
    to PHP parse_url function result
    */
    public static function createFromComponents(array $components) : self
    {
        return new self(Uri::createFromComponents($components));
    }
    /**
     * Create a new instance from the environment.
     */
    public static function createFromServer(array $server) : self
    {
        return new self(Uri::createFromServer($server));
    }
    /**
     * Create a new instance from a URI and a Base URI.
     *
     * The returned URI must be absolute.
     *
     * @param mixed $uri the input URI to create
     * @param mixed $base_uri the base URI used for reference
     */
    public static function createFromBaseUri($uri, $base_uri = null) : self
    {
        return new self(Uri::createFromBaseUri($uri, $base_uri));
    }
    /**
     * Create a new instance from a URI object.
     *
     * @param (Psr7UriInterface | UriInterface) $uri the input URI to create
     */
    public static function createFromUri($uri) : self
    {
        if ($uri instanceof UriInterface) {
            return new self($uri);
        }
        return new self(Uri::createFromUri($uri));
    }
    /**
     * {@inheritDoc}
     */
    public function getScheme() : string
    {
        return (string) $this->uri->getScheme();
    }
    /**
     * {@inheritDoc}
     */
    public function getAuthority() : string
    {
        return (string) $this->uri->getAuthority();
    }
    /**
     * {@inheritDoc}
     */
    public function getUserInfo() : string
    {
        return (string) $this->uri->getUserInfo();
    }
    /**
     * {@inheritDoc}
     */
    public function getHost() : string
    {
        return (string) $this->uri->getHost();
    }
    /**
     * {@inheritDoc}
     */
    public function getPort() : ?int
    {
        return $this->uri->getPort();
    }
    /**
     * {@inheritDoc}
     */
    public function getPath() : string
    {
        return $this->uri->getPath();
    }
    /**
     * {@inheritDoc}
     */
    public function getQuery() : string
    {
        return (string) $this->uri->getQuery();
    }
    /**
     * {@inheritDoc}
     */
    public function getFragment() : string
    {
        return (string) $this->uri->getFragment();
    }
    /**
     * {@inheritDoc}
     */
    public function withScheme($scheme) : self
    {
        $scheme = $this->filterInput($scheme);
        if ('' === $scheme) {
            $scheme = null;
        }
        $uri = $this->uri->withScheme($scheme);
        if ($uri->getScheme() === $this->uri->getScheme()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * Safely stringify input when possible.
     *
     * @param mixed $str the value to evaluate as a string
     *
     * @throws SyntaxError if the submitted data can not be converted to string
     *
     * @return (string | mixed)
     */
    private function filterInput($str)
    {
        if (is_scalar($str) || is_object($str) && method_exists($str, '__toString')) {
            return (string) $str;
        }
        return $str;
    }
    /**
     * {@inheritDoc}
     */
    public function withUserInfo($user, $password = null) : self
    {
        $user = $this->filterInput($user);
        if ('' === $user) {
            $user = null;
        }
        $uri = $this->uri->withUserInfo($user, $password);
        if ($uri->getUserInfo() === $this->uri->getUserInfo()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withHost($host) : self
    {
        $host = $this->filterInput($host);
        if ('' === $host) {
            $host = null;
        }
        $uri = $this->uri->withHost($host);
        if ($uri->getHost() === $this->uri->getHost()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withPort($port) : self
    {
        $uri = $this->uri->withPort($port);
        if ($uri->getPort() === $this->uri->getPort()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withPath($path) : self
    {
        $uri = $this->uri->withPath($path);
        if ($uri->getPath() === $this->uri->getPath()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withQuery($query) : self
    {
        $query = $this->filterInput($query);
        if ('' === $query) {
            $query = null;
        }
        $uri = $this->uri->withQuery($query);
        if ($uri->getQuery() === $this->uri->getQuery()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function withFragment($fragment) : self
    {
        $fragment = $this->filterInput($fragment);
        if ('' === $fragment) {
            $fragment = null;
        }
        $uri = $this->uri->withFragment($fragment);
        if ($uri->getFragment() === $this->uri->getFragment()) {
            return $this;
        }
        return new self($uri);
    }
    /**
     * {@inheritDoc}
     */
    public function __toString() : string
    {
        return $this->uri->__toString();
    }
    /**
     * {@inheritDoc}
     */
    public function jsonSerialize() : string
    {
        return $this->uri->__toString();
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriInterface;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use function explode;
use function implode;
use function preg_replace_callback;
use function rawurldecode;
use function sprintf;
final class UriInfo
{
    private const REGEXP_ENCODED_CHARS = ',%(2[D|E]|3[0-9]|4[1-9|A-F]|5[0-9|A|F]|6[1-9|A-F]|7[0-9|E]),i';
    private const WHATWG_SPECIAL_SCHEMES = ['ftp', 'http', 'https', 'ws', 'wss'];
    /**
     * @codeCoverageIgnore
     */
    private function __construct()
    {
    }
    /**
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    private static function emptyComponentValue($uri) : ?string
    {
        return $uri instanceof Psr7UriInterface ? '' : null;
    }
    /**
    * Filter the URI object.
    *
    * To be valid an URI MUST implement at least one of the following interface:
    - League\Uri\UriInterface
    - Psr\Http\Message\UriInterface
    *
    * @param mixed $uri the URI to validate
    *
    * @throws \TypeError if the URI object does not implements the supported interfaces.
    *
    * @return (Psr7UriInterface | UriInterface)
    */
    private static function filterUri($uri)
    {
        if ($uri instanceof Psr7UriInterface || $uri instanceof UriInterface) {
            return $uri;
        }
        throw new \TypeError(sprintf('The uri must be a valid URI object received `%s`', is_object($uri) ? get_class($uri) : gettype($uri)));
    }
    /**
     * Normalize an URI for comparison.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     *
     * @return (Psr7UriInterface | UriInterface)
     */
    private static function normalize($uri)
    {
        $uri = self::filterUri($uri);
        $null = self::emptyComponentValue($uri);
        $path = $uri->getPath();
        if ('/' === ($path[0] ?? '') || '' !== $uri->getScheme() . $uri->getAuthority()) {
            $path = UriResolver::resolve($uri, $uri->withPath('')->withQuery($null))->getPath();
        }
        $query = $uri->getQuery();
        $fragment = $uri->getFragment();
        $fragmentOrig = $fragment;
        $pairs = null === $query ? [] : explode('&', $query);
        sort($pairs, SORT_REGULAR);
        $replace = static function (array $matches) : string {
            return rawurldecode($matches[0]);
        };
        $retval = preg_replace_callback(self::REGEXP_ENCODED_CHARS, $replace, [$path, implode('&', $pairs), $fragment]);
        if (null !== $retval) {
            [$path, $query, $fragment] = $retval + ['', $null, $null];
        }
        if ($null !== $uri->getAuthority() && '' === $path) {
            $path = '/';
        }
        return $uri->withHost(Uri::createFromComponents(['host' => $uri->getHost()])->getHost())->withPath($path)->withQuery([] === $pairs ? $null : $query)->withFragment($null === $fragmentOrig ? $fragmentOrig : $fragment);
    }
    /**
     * Tell whether the URI represents an absolute URI.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    public static function isAbsolute($uri) : bool
    {
        return self::emptyComponentValue($uri) !== self::filterUri($uri)->getScheme();
    }
    /**
     * Tell whether the URI represents a network path.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    public static function isNetworkPath($uri) : bool
    {
        $uri = self::filterUri($uri);
        $null = self::emptyComponentValue($uri);
        return $null === $uri->getScheme() && $null !== $uri->getAuthority();
    }
    /**
     * Tell whether the URI represents an absolute path.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    public static function isAbsolutePath($uri) : bool
    {
        $uri = self::filterUri($uri);
        $null = self::emptyComponentValue($uri);
        return $null === $uri->getScheme() && $null === $uri->getAuthority() && '/' === ($uri->getPath()[0] ?? '');
    }
    /**
     * Tell whether the URI represents a relative path.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    public static function isRelativePath($uri) : bool
    {
        $uri = self::filterUri($uri);
        $null = self::emptyComponentValue($uri);
        return $null === $uri->getScheme() && $null === $uri->getAuthority() && '/' !== ($uri->getPath()[0] ?? '');
    }
    /**
     * Tell whether both URI refers to the same document.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     * @param (Psr7UriInterface | UriInterface) $base_uri
     */
    public static function isSameDocument($uri, $base_uri) : bool
    {
        $uri = self::normalize($uri);
        $base_uri = self::normalize($base_uri);
        return (string) $uri->withFragment($uri instanceof Psr7UriInterface ? '' : null) === (string) $base_uri->withFragment($base_uri instanceof Psr7UriInterface ? '' : null);
    }
    /**
    * Returns the URI origin property as defined by WHATWG URL living standard.
    *
    * {@see https://url.spec.whatwg.org/#origin}
    *
    * For URI without a special scheme the method returns null
    For URI with the file scheme the method will return null (as this is left to the implementation decision)
    For URI with a special scheme the method returns the scheme followed by its authority (without the userinfo part)
    *
    * @param (Psr7UriInterface | UriInterface) $uri
    */
    public static function getOrigin($uri) : ?string
    {
        $scheme = self::filterUri($uri)->getScheme();
        if ('blob' === $scheme) {
            $uri = Uri::createFromString($uri->getPath());
            $scheme = $uri->getScheme();
        }
        if (in_array($scheme, self::WHATWG_SPECIAL_SCHEMES, true)) {
            $null = self::emptyComponentValue($uri);
            return (string) $uri->withFragment($null)->withQuery($null)->withPath('')->withUserInfo($null, null);
        }
        return null;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriInterface;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use function array_pop;
use function array_reduce;
use function count;
use function end;
use function explode;
use function gettype;
use function implode;
use function in_array;
use function sprintf;
use function str_repeat;
use function strpos;
use function substr;
final class UriResolver
{
    /**
     * @var array<string,int>
     */
    const DOT_SEGMENTS = ['.' => 1, '..' => 1];
    /**
     * @codeCoverageIgnore
     */
    private function __construct()
    {
    }
    /**
    * Resolve an URI against a base URI using RFC3986 rules.
    *
    * If the first argument is a UriInterface the method returns a UriInterface object
    If the first argument is a Psr7UriInterface the method returns a Psr7UriInterface object
    *
    * @param (Psr7UriInterface | UriInterface) $uri
    * @param (Psr7UriInterface | UriInterface) $base_uri
    *
    * @return (Psr7UriInterface | UriInterface)
    */
    public static function resolve($uri, $base_uri)
    {
        self::filterUri($uri);
        self::filterUri($base_uri);
        $null = $uri instanceof Psr7UriInterface ? '' : null;
        if ($null !== $uri->getScheme()) {
            return $uri->withPath(self::removeDotSegments($uri->getPath()));
        }
        if ($null !== $uri->getAuthority()) {
            return $uri->withScheme($base_uri->getScheme())->withPath(self::removeDotSegments($uri->getPath()));
        }
        $user = $null;
        $pass = null;
        $userInfo = $base_uri->getUserInfo();
        if (null !== $userInfo) {
            [$user, $pass] = explode(':', $userInfo, 2) + [1 => null];
        }
        [$uri_path, $uri_query] = self::resolvePathAndQuery($uri, $base_uri);
        return $uri->withPath(self::removeDotSegments($uri_path))->withQuery($uri_query)->withHost($base_uri->getHost())->withPort($base_uri->getPort())->withUserInfo((string) $user, $pass)->withScheme($base_uri->getScheme());
    }
    /**
     * Filter the URI object.
     *
     * @param mixed $uri an URI object
     *
     * @throws \TypeError if the URI object does not implements the supported interfaces.
     */
    private static function filterUri($uri) : void
    {
        if (!$uri instanceof UriInterface && !$uri instanceof Psr7UriInterface) {
            throw new \TypeError(sprintf('The uri must be a valid URI object received `%s`', gettype($uri)));
        }
    }
    /**
     * Remove dot segments from the URI path.
     */
    private static function removeDotSegments(string $path) : string
    {
        if (false === strpos($path, '.')) {
            return $path;
        }
        $old_segments = explode('/', $path);
        $new_path = implode('/', array_reduce($old_segments, [UriResolver::class, 'reducer'], []));
        if (isset(self::DOT_SEGMENTS[end($old_segments)])) {
            $new_path .= '/';
        }
        // @codeCoverageIgnoreStart
        // added because some PSR-7 implementations do not respect RFC3986
        if (0 === strpos($path, '/') && 0 !== strpos($new_path, '/')) {
            return '/' . $new_path;
        }
        // @codeCoverageIgnoreEnd
        return $new_path;
    }
    /**
     * Remove dot segments.
     *
     * @return array<int, string>
     */
    private static function reducer(array $carry, string $segment) : array
    {
        if ('..' === $segment) {
            array_pop($carry);
            return $carry;
        }
        if (!isset(self::DOT_SEGMENTS[$segment])) {
            $carry[] = $segment;
        }
        return $carry;
    }
    /**
     * Resolve an URI path and query component.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     * @param (Psr7UriInterface | UriInterface) $base_uri
     *
     * @return array{0: string, 1: (string | null)}
     */
    private static function resolvePathAndQuery($uri, $base_uri) : array
    {
        $target_path = $uri->getPath();
        $target_query = $uri->getQuery();
        $null = $uri instanceof Psr7UriInterface ? '' : null;
        $baseNull = $base_uri instanceof Psr7UriInterface ? '' : null;
        if (0 === strpos($target_path, '/')) {
            return [$target_path, $target_query];
        }
        if ('' === $target_path) {
            if ($null === $target_query) {
                $target_query = $base_uri->getQuery();
            }
            $target_path = $base_uri->getPath();
            //@codeCoverageIgnoreStart
            //because some PSR-7 Uri implementations allow this RFC3986 forbidden construction
            if ($baseNull !== $base_uri->getAuthority() && 0 !== strpos($target_path, '/')) {
                $target_path = '/' . $target_path;
            }
            //@codeCoverageIgnoreEnd
            return [$target_path, $target_query];
        }
        $base_path = $base_uri->getPath();
        if ($baseNull !== $base_uri->getAuthority() && '' === $base_path) {
            $target_path = '/' . $target_path;
        }
        if ('' !== $base_path) {
            $segments = explode('/', $base_path);
            array_pop($segments);
            if ([] !== $segments) {
                $target_path = implode('/', $segments) . '/' . $target_path;
            }
        }
        return [$target_path, $target_query];
    }
    /**
    * Relativize an URI according to a base URI.
    *
    * This method MUST retain the state of the submitted URI instance, and return
    an URI instance of the same type that contains the applied modifications.
    *
    * This method MUST be transparent when dealing with error and exceptions.
    It MUST not alter of silence them apart from validating its own parameters.
    *
    * @param (Psr7UriInterface | UriInterface) $uri
    * @param (Psr7UriInterface | UriInterface) $base_uri
    *
    * @return (Psr7UriInterface | UriInterface)
    */
    public static function relativize($uri, $base_uri)
    {
        self::filterUri($uri);
        self::filterUri($base_uri);
        $uri = self::formatHost($uri);
        $base_uri = self::formatHost($base_uri);
        if (!self::isRelativizable($uri, $base_uri)) {
            return $uri;
        }
        $null = $uri instanceof Psr7UriInterface ? '' : null;
        $uri = $uri->withScheme($null)->withPort(null)->withUserInfo($null)->withHost($null);
        $target_path = $uri->getPath();
        if ($target_path !== $base_uri->getPath()) {
            return $uri->withPath(self::relativizePath($target_path, $base_uri->getPath()));
        }
        if (self::componentEquals('getQuery', $uri, $base_uri)) {
            return $uri->withPath('')->withQuery($null);
        }
        if ($null === $uri->getQuery()) {
            return $uri->withPath(self::formatPathWithEmptyBaseQuery($target_path));
        }
        return $uri->withPath('');
    }
    /**
     * Tells whether the component value from both URI object equals.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     * @param (Psr7UriInterface | UriInterface) $base_uri
     */
    private static function componentEquals(string $method, $uri, $base_uri) : bool
    {
        return self::getComponent($method, $uri) === self::getComponent($method, $base_uri);
    }
    /**
     * Returns the component value from the submitted URI object.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     */
    private static function getComponent(string $method, $uri) : ?string
    {
        $component = $uri->{$method}();
        if ($uri instanceof Psr7UriInterface && '' === $component) {
            return null;
        }
        return $component;
    }
    /**
     * Filter the URI object.
     *
     * @param (null | mixed) $uri
     *
     * @throws \TypeError if the URI object does not implements the supported interfaces.
     *
     * @return (Psr7UriInterface | UriInterface)
     */
    private static function formatHost($uri)
    {
        if (!$uri instanceof Psr7UriInterface) {
            return $uri;
        }
        $host = $uri->getHost();
        if ('' === $host) {
            return $uri;
        }
        return $uri->withHost((string) Uri::createFromComponents(['host' => $host])->getHost());
    }
    /**
     * Tell whether the submitted URI object can be relativize.
     *
     * @param (Psr7UriInterface | UriInterface) $uri
     * @param (Psr7UriInterface | UriInterface) $base_uri
     */
    private static function isRelativizable($uri, $base_uri) : bool
    {
        return !UriInfo::isRelativePath($uri) && self::componentEquals('getScheme', $uri, $base_uri) && self::componentEquals('getAuthority', $uri, $base_uri);
    }
    /**
     * Relative the URI for a authority-less target URI.
     */
    private static function relativizePath(string $path, string $basepath) : string
    {
        $base_segments = self::getSegments($basepath);
        $target_segments = self::getSegments($path);
        $target_basename = array_pop($target_segments);
        array_pop($base_segments);
        foreach ($base_segments as $offset => $segment) {
            if (!isset($target_segments[$offset]) || $segment !== $target_segments[$offset]) {
                break;
            }
            unset($base_segments[$offset], $target_segments[$offset]);
        }
        $target_segments[] = $target_basename;
        return self::formatPath(str_repeat('../', count($base_segments)) . implode('/', $target_segments), $basepath);
    }
    /**
     * returns the path segments.
     *
     * @return string[]
     */
    private static function getSegments(string $path) : array
    {
        if ('' !== $path && '/' === $path[0]) {
            $path = \Phabel\Target\Php80\Polyfill::substr($path, 1);
        }
        return explode('/', $path);
    }
    /**
     * Formatting the path to keep a valid URI.
     */
    private static function formatPath(string $path, string $basepath) : string
    {
        if ('' === $path) {
            return in_array($basepath, ['', '/'], true) ? $basepath : './';
        }
        if (false === ($colon_pos = strpos($path, ':'))) {
            return $path;
        }
        $slash_pos = strpos($path, '/');
        if (false === $slash_pos || $colon_pos < $slash_pos) {
            return "./{$path}";
        }
        return $path;
    }
    /**
     * Formatting the path to keep a resolvable URI.
     */
    private static function formatPathWithEmptyBaseQuery(string $path) : string
    {
        $target_segments = self::getSegments($path);
        /** @var string $basename */
        $basename = end($target_segments);
        return '' === $basename ? './' : $basename;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriInterface;
use League\Uri\Exceptions\FileinfoSupportMissing;
use League\Uri\Exceptions\IdnaConversionFailed;
use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
use League\Uri\Idna\Idna;
use Psr\Http\Message\UriInterface as Psr7UriInterface;
use function array_filter;
use function array_map;
use function base64_decode;
use function base64_encode;
use function count;
use function explode;
use function file_get_contents;
use function filter_var;
use function implode;
use function in_array;
use function inet_pton;
use function is_object;
use function is_scalar;
use function method_exists;
use function preg_match;
use function preg_replace;
use function preg_replace_callback;
use function rawurlencode;
use function sprintf;
use function str_replace;
use function strlen;
use function strpos;
use function strspn;
use function strtolower;
use function substr;
use const FILEINFO_MIME;
use const FILTER_FLAG_IPV4;
use const FILTER_FLAG_IPV6;
use const FILTER_NULL_ON_FAILURE;
use const FILTER_VALIDATE_BOOLEAN;
use const FILTER_VALIDATE_IP;
final class Uri implements UriInterface
{
    /**
     * RFC3986 invalid characters.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-2.2
     *
     * @var string
     */
    private const REGEXP_INVALID_CHARS = '/[\\x00-\\x1f\\x7f]/';
    /**
     * RFC3986 Sub delimiter characters regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-2.2
     *
     * @var string
     */
    private const REGEXP_CHARS_SUBDELIM = "\\!\$&'\\(\\)\\*\\+,;\\=%";
    /**
     * RFC3986 unreserved characters regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-2.3
     *
     * @var string
     */
    private const REGEXP_CHARS_UNRESERVED = 'A-Za-z0-9_\\-\\.~';
    /**
     * RFC3986 schema regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.1
     */
    private const REGEXP_SCHEME = ',^[a-z]([-a-z0-9+.]+)?$,i';
    /**
     * RFC3986 host identified by a registered name regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_HOST_REGNAME = '/^(
        (?<unreserved>[a-z0-9_~\\-\\.])|
        (?<sub_delims>[!$&\'()*+,;=])|
        (?<encoded>%[A-F0-9]{2})
    )+$/x';
    /**
     * RFC3986 delimiters of the generic URI components regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-2.2
     */
    private const REGEXP_HOST_GEN_DELIMS = '/[:\\/?#\\[\\]@ ]/';
    // Also includes space.
    /**
     * RFC3986 IPvFuture regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_HOST_IPFUTURE = '/^
        v(?<version>[A-F0-9])+\\.
        (?:
            (?<unreserved>[a-z0-9_~\\-\\.])|
            (?<sub_delims>[!$&\'()*+,;=:])  # also include the : character
        )+
    $/ix';
    /**
     * RFC3986 IPvFuture host and port component.
     */
    private const REGEXP_HOST_PORT = ',^(?<host>(\\[.*]|[^:])*)(:(?<port>[^/?#]*))?$,x';
    /**
     * Significant 10 bits of IP to detect Zone ID regular expression pattern.
     */
    private const HOST_ADDRESS_BLOCK = "\xfe\x80";
    /**
     * Regular expression pattern to for file URI.
     * <volume> contains the volume but not the volume separator.
     * The volume separator may be URL-encoded (`|` as `%7C`) by ::formatPath(),
     * so we account for that here.
     */
    private const REGEXP_FILE_PATH = ',^(?<delim>/)?(?<volume>[a-zA-Z])(?:[:|\\|]|%7C)(?<rest>.*)?,';
    /**
     * Mimetype regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc2397
     */
    private const REGEXP_MIMETYPE = ',^\\w+/[-.\\w]+(?:\\+[-.\\w]+)?$,';
    /**
     * Base64 content regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc2397
     */
    private const REGEXP_BINARY = ',(;|^)base64$,';
    /**
     * Windows file path string regular expression pattern.
     * <root> contains both the volume and volume separator.
     */
    private const REGEXP_WINDOW_PATH = ',^(?<root>[a-zA-Z][:|\\|]),';
    /**
     * Supported schemes and corresponding default port.
     *
     * @var array
     */
    private const SCHEME_DEFAULT_PORT = ['data' => null, 'file' => null, 'ftp' => 21, 'gopher' => 70, 'http' => 80, 'https' => 443, 'ws' => 80, 'wss' => 443];
    /**
     * URI validation methods per scheme.
     *
     * @var array
     */
    private const SCHEME_VALIDATION_METHOD = ['data' => 'isUriWithSchemeAndPathOnly', 'file' => 'isUriWithSchemeHostAndPathOnly', 'ftp' => 'isNonEmptyHostUriWithoutFragmentAndQuery', 'gopher' => 'isNonEmptyHostUriWithoutFragmentAndQuery', 'http' => 'isNonEmptyHostUri', 'https' => 'isNonEmptyHostUri', 'ws' => 'isNonEmptyHostUriWithoutFragment', 'wss' => 'isNonEmptyHostUriWithoutFragment'];
    /**
     * All ASCII letters sorted by typical frequency of occurrence.
     *
     * @var string
     */
    private const ASCII = " eiasntrolud][cmp'\ng|hv.fb,:=-q10C2*yx)(L9AS/P\"EjMIk3>5T<D4}B{8FwR67UGN;JzV#HOW_&!K?XQ%Y\\\tZ+~^\$@`\x00\x01\x02\x03\x04\x05\x06\x07\x08\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
    /**
     * URI scheme component.
     *
     * @var string|null
     */
    private $scheme;
    /**
     * URI user info part.
     *
     * @var string|null
     */
    private $user_info;
    /**
     * URI host component.
     *
     * @var string|null
     */
    private $host;
    /**
     * URI port component.
     *
     * @var int|null
     */
    private $port;
    /**
     * URI authority string representation.
     *
     * @var string|null
     */
    private $authority;
    /**
     * URI path component.
     *
     * @var string
     */
    private $path = '';
    /**
     * URI query component.
     *
     * @var string|null
     */
    private $query;
    /**
     * URI fragment component.
     *
     * @var string|null
     */
    private $fragment;
    /**
     * URI string representation.
     *
     * @var string|null
     */
    private $uri;
    /**
     * Create a new instance.
     *
     * @param ?string $scheme
     * @param ?string $user
     * @param ?string $pass
     * @param ?string $host
     * @param ?int $port
     * @param ?string $query
     * @param ?string $fragment
     */
    private function __construct(?string $scheme, ?string $user, ?string $pass, ?string $host, ?int $port, string $path, ?string $query, ?string $fragment)
    {
        $this->scheme = $this->formatScheme($scheme);
        $this->user_info = $this->formatUserInfo($user, $pass);
        $this->host = $this->formatHost($host);
        $this->port = $this->formatPort($port);
        $this->authority = $this->setAuthority();
        $this->path = $this->formatPath($path);
        $this->query = $this->formatQueryAndFragment($query);
        $this->fragment = $this->formatQueryAndFragment($fragment);
        $this->assertValidState();
    }
    /**
     * Format the Scheme and Host component.
     *
     * @param ?string $scheme
     *
     * @throws SyntaxError if the scheme is invalid
     */
    private function formatScheme(?string $scheme) : ?string
    {
        if (null === $scheme) {
            return $scheme;
        }
        $formatted_scheme = strtolower($scheme);
        if (1 === preg_match(self::REGEXP_SCHEME, $formatted_scheme)) {
            return $formatted_scheme;
        }
        throw new SyntaxError(sprintf('The scheme `%s` is invalid.', $scheme));
    }
    /**
     * Set the UserInfo component.
     *
     * @param ?string $user
     * @param ?string $password
     */
    private function formatUserInfo(?string $user, ?string $password) : ?string
    {
        if (null === $user) {
            return $user;
        }
        static $user_pattern = '/(?:[^%' . self::REGEXP_CHARS_UNRESERVED . self::REGEXP_CHARS_SUBDELIM . ']++|%(?![A-Fa-f0-9]{2}))/';
        $user = preg_replace_callback($user_pattern, [Uri::class, 'urlEncodeMatch'], $user);
        if (null === $password) {
            return $user;
        }
        static $password_pattern = '/(?:[^%:' . self::REGEXP_CHARS_UNRESERVED . self::REGEXP_CHARS_SUBDELIM . ']++|%(?![A-Fa-f0-9]{2}))/';
        return $user . ':' . preg_replace_callback($password_pattern, [Uri::class, 'urlEncodeMatch'], $password);
    }
    /**
     * Returns the RFC3986 encoded string matched.
     */
    private static function urlEncodeMatch(array $matches) : string
    {
        return rawurlencode($matches[0]);
    }
    /**
     * Validate and Format the Host component.
     *
     * @param ?string $host
     */
    private function formatHost(?string $host) : ?string
    {
        if (null === $host || '' === $host) {
            return $host;
        }
        if ('[' !== $host[0]) {
            return $this->formatRegisteredName($host);
        }
        return $this->formatIp($host);
    }
    /**
     * Validate and format a registered name.
     *
     * The host is converted to its ascii representation if needed
     *
     * @throws IdnSupportMissing if the submitted host required missing or misconfigured IDN support
     * @throws SyntaxError if the submitted host is not a valid registered name
     */
    private function formatRegisteredName(string $host) : string
    {
        $formatted_host = rawurldecode($host);
        if (1 === preg_match(self::REGEXP_HOST_REGNAME, $formatted_host)) {
            return $formatted_host;
        }
        if (1 === preg_match(self::REGEXP_HOST_GEN_DELIMS, $formatted_host)) {
            throw new SyntaxError(sprintf('The host `%s` is invalid : a registered name can not contain URI delimiters or spaces', $host));
        }
        $info = Idna::toAscii($host, Idna::IDNA2008_ASCII);
        if (0 !== $info->errors()) {
            throw IdnaConversionFailed::dueToIDNAError($host, $info);
        }
        return $info->result();
    }
    /**
     * Validate and Format the IPv6/IPvfuture host.
     *
     * @throws SyntaxError if the submitted host is not a valid IP host
     */
    private function formatIp(string $host) : string
    {
        $ip = \Phabel\Target\Php80\Polyfill::substr($host, 1, -1);
        if (false !== filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return $host;
        }
        if (1 === preg_match(self::REGEXP_HOST_IPFUTURE, $ip, $matches) && !in_array($matches['version'], ['4', '6'], true)) {
            return $host;
        }
        $pos = strpos($ip, '%');
        if (false === $pos) {
            throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host));
        }
        if (1 === preg_match(self::REGEXP_HOST_GEN_DELIMS, rawurldecode(\Phabel\Target\Php80\Polyfill::substr($ip, $pos)))) {
            throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host));
        }
        $ip = \Phabel\Target\Php80\Polyfill::substr($ip, 0, $pos);
        if (false === filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host));
        }
        //Only the address block fe80::/10 can have a Zone ID attach to
        //let's detect the link local significant 10 bits
        if (0 === strpos((string) inet_pton($ip), self::HOST_ADDRESS_BLOCK)) {
            return $host;
        }
        throw new SyntaxError(sprintf('The host `%s` is invalid : the IP host is malformed', $host));
    }
    /**
     * Format the Port component.
     *
     * @param (null | mixed) $port
     *
     * @throws SyntaxError
     */
    private function formatPort($port = null) : ?int
    {
        if (null === $port || '' === $port) {
            return null;
        }
        if (!is_int($port) && !(is_string($port) && 1 === preg_match('/^\\d*$/', $port))) {
            throw new SyntaxError(sprintf('The port `%s` is invalid', $port));
        }
        $port = (int) $port;
        if (0 > $port) {
            throw new SyntaxError(sprintf('The port `%s` is invalid', $port));
        }
        $defaultPort = self::SCHEME_DEFAULT_PORT[$this->scheme] ?? null;
        if ($defaultPort === $port) {
            return null;
        }
        return $port;
    }
    /**
     * {@inheritDoc}
     */
    public static function __set_state(array $components) : self
    {
        $components['user'] = null;
        $components['pass'] = null;
        if (null !== $components['user_info']) {
            [$components['user'], $components['pass']] = explode(':', $components['user_info'], 2) + [1 => null];
        }
        return new self($components['scheme'], $components['user'], $components['pass'], $components['host'], $components['port'], $components['path'], $components['query'], $components['fragment']);
    }
    /**
     * Create a new instance from a URI and a Base URI.
     *
     * The returned URI must be absolute.
     *
     * @param mixed $uri the input URI to create
     * @param (null | mixed) $base_uri the base URI used for reference
     */
    public static function createFromBaseUri($uri, $base_uri = null) : UriInterface
    {
        if (!$uri instanceof UriInterface) {
            $uri = self::createFromString($uri);
        }
        if (null === $base_uri) {
            if (null === $uri->getScheme()) {
                throw new SyntaxError(sprintf('the URI `%s` must be absolute', (string) $uri));
            }
            if (null === $uri->getAuthority()) {
                return $uri;
            }
            /** @var UriInterface $uri */
            $uri = UriResolver::resolve($uri, $uri->withFragment(null)->withQuery(null)->withPath(''));
            return $uri;
        }
        if (!$base_uri instanceof UriInterface) {
            $base_uri = self::createFromString($base_uri);
        }
        if (null === $base_uri->getScheme()) {
            throw new SyntaxError(sprintf('the base URI `%s` must be absolute', (string) $base_uri));
        }
        /** @var UriInterface $uri */
        $uri = UriResolver::resolve($uri, $base_uri);
        return $uri;
    }
    /**
     * Create a new instance from a string.
     *
     * @param (string | mixed) $uri
     */
    public static function createFromString($uri = '') : self
    {
        $components = UriString::parse($uri);
        return new self($components['scheme'], $components['user'], $components['pass'], $components['host'], $components['port'], $components['path'], $components['query'], $components['fragment']);
    }
    /**
    * Create a new instance from a hash of parse_url parts.
    *
    * Create an new instance from a hash representation of the URI similar
    to PHP parse_url function result
    *
    * @param array<string, mixed> $components
    */
    public static function createFromComponents(array $components = []) : self
    {
        $components += ['scheme' => null, 'user' => null, 'pass' => null, 'host' => null, 'port' => null, 'path' => '', 'query' => null, 'fragment' => null];
        return new self($components['scheme'], $components['user'], $components['pass'], $components['host'], $components['port'], $components['path'], $components['query'], $components['fragment']);
    }
    /**
     * Create a new instance from a data file path.
     *
     * @param (resource | null) $context
     *
     * @throws FileinfoSupportMissing If ext/fileinfo is not installed
     * @throws SyntaxError If the file does not exist or is not readable
     */
    public static function createFromDataPath(string $path, $context = null) : self
    {
        static $finfo_support = null;
        $finfo_support = $finfo_support ?? class_exists(\finfo::class);
        // @codeCoverageIgnoreStart
        if (!$finfo_support) {
            throw new FileinfoSupportMissing(sprintf('Please install ext/fileinfo to use the %s() method.', __METHOD__));
        }
        // @codeCoverageIgnoreEnd
        $file_args = [$path, false];
        $mime_args = [$path, FILEINFO_MIME];
        if (null !== $context) {
            $file_args[] = $context;
            $mime_args[] = $context;
        }
        $raw = @file_get_contents(...$file_args);
        if (false === $raw) {
            throw new SyntaxError(sprintf('The file `%s` does not exist or is not readable', $path));
        }
        $mimetype = (string) (new \finfo(FILEINFO_MIME))->file(...$mime_args);
        return Uri::createFromComponents(['scheme' => 'data', 'path' => str_replace(' ', '', $mimetype . ';base64,' . base64_encode($raw))]);
    }
    /**
     * Create a new instance from a Unix path string.
     */
    public static function createFromUnixPath(string $uri = '') : self
    {
        $uri = implode('/', array_map('rawurlencode', explode('/', $uri)));
        if ('/' !== ($uri[0] ?? '')) {
            return Uri::createFromComponents(['path' => $uri]);
        }
        return Uri::createFromComponents(['path' => $uri, 'scheme' => 'file', 'host' => '']);
    }
    /**
     * Create a new instance from a local Windows path string.
     */
    public static function createFromWindowsPath(string $uri = '') : self
    {
        $root = '';
        if (1 === preg_match(self::REGEXP_WINDOW_PATH, $uri, $matches)) {
            $root = \Phabel\Target\Php80\Polyfill::substr($matches['root'], 0, -1) . ':';
            $uri = \Phabel\Target\Php80\Polyfill::substr($uri, strlen($root));
        }
        $uri = str_replace('\\', '/', $uri);
        $uri = implode('/', array_map('rawurlencode', explode('/', $uri)));
        //Local Windows absolute path
        if ('' !== $root) {
            return Uri::createFromComponents(['path' => '/' . $root . $uri, 'scheme' => 'file', 'host' => '']);
        }
        //UNC Windows Path
        if ('//' !== \Phabel\Target\Php80\Polyfill::substr($uri, 0, 2)) {
            return Uri::createFromComponents(['path' => $uri]);
        }
        $parts = explode('/', \Phabel\Target\Php80\Polyfill::substr($uri, 2), 2) + [1 => null];
        return Uri::createFromComponents(['host' => $parts[0], 'path' => '/' . $parts[1], 'scheme' => 'file']);
    }
    /**
     * Create a new instance from a URI object.
     *
     * @param (Psr7UriInterface | UriInterface) $uri the input URI to create
     */
    public static function createFromUri($uri) : self
    {
        if ($uri instanceof UriInterface) {
            $user_info = $uri->getUserInfo();
            $user = null;
            $pass = null;
            if (null !== $user_info) {
                [$user, $pass] = explode(':', $user_info, 2) + [1 => null];
            }
            return new self($uri->getScheme(), $user, $pass, $uri->getHost(), $uri->getPort(), $uri->getPath(), $uri->getQuery(), $uri->getFragment());
        }
        if (!$uri instanceof Psr7UriInterface) {
            throw new \TypeError(sprintf('The object must implement the `%s` or the `%s`', Psr7UriInterface::class, UriInterface::class));
        }
        $scheme = $uri->getScheme();
        if ('' === $scheme) {
            $scheme = null;
        }
        $fragment = $uri->getFragment();
        if ('' === $fragment) {
            $fragment = null;
        }
        $query = $uri->getQuery();
        if ('' === $query) {
            $query = null;
        }
        $host = $uri->getHost();
        if ('' === $host) {
            $host = null;
        }
        $user_info = $uri->getUserInfo();
        $user = null;
        $pass = null;
        if ('' !== $user_info) {
            [$user, $pass] = explode(':', $user_info, 2) + [1 => null];
        }
        return new self($scheme, $user, $pass, $host, $uri->getPort(), $uri->getPath(), $query, $fragment);
    }
    /**
     * Create a new instance from the environment.
     */
    public static function createFromServer(array $server) : self
    {
        [$user, $pass] = self::fetchUserInfo($server);
        [$host, $port] = self::fetchHostname($server);
        [$path, $query] = self::fetchRequestUri($server);
        return Uri::createFromComponents(['scheme' => self::fetchScheme($server), 'user' => $user, 'pass' => $pass, 'host' => $host, 'port' => $port, 'path' => $path, 'query' => $query]);
    }
    /**
     * Returns the environment scheme.
     */
    private static function fetchScheme(array $server) : string
    {
        $server += ['HTTPS' => ''];
        $res = filter_var($server['HTTPS'], FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
        return false !== $res ? 'https' : 'http';
    }
    /**
     * Returns the environment user info.
     *
     * @return array{0: ?string, 1: ?string}
     */
    private static function fetchUserInfo(array $server) : array
    {
        $server += ['PHP_AUTH_USER' => null, 'PHP_AUTH_PW' => null, 'HTTP_AUTHORIZATION' => ''];
        $user = $server['PHP_AUTH_USER'];
        $pass = $server['PHP_AUTH_PW'];
        if (0 === strpos(strtolower($server['HTTP_AUTHORIZATION']), 'basic')) {
            $userinfo = base64_decode(\Phabel\Target\Php80\Polyfill::substr($server['HTTP_AUTHORIZATION'], 6), true);
            if (false === $userinfo) {
                throw new SyntaxError('The user info could not be detected');
            }
            [$user, $pass] = explode(':', $userinfo, 2) + [1 => null];
        }
        if (null !== $user) {
            $user = rawurlencode($user);
        }
        if (null !== $pass) {
            $pass = rawurlencode($pass);
        }
        return [$user, $pass];
    }
    /**
     * Returns the environment host.
     *
     * @throws SyntaxError If the host can not be detected
     *
     * @return array{0: ?string, 1: ?string}
     */
    private static function fetchHostname(array $server) : array
    {
        $server += ['SERVER_PORT' => null];
        if (null !== $server['SERVER_PORT']) {
            $server['SERVER_PORT'] = (int) $server['SERVER_PORT'];
        }
        if (isset($server['HTTP_HOST']) && 1 === preg_match(self::REGEXP_HOST_PORT, $server['HTTP_HOST'], $matches)) {
            return [$matches['host'], isset($matches['port']) ? (int) $matches['port'] : $server['SERVER_PORT']];
        }
        if (!isset($server['SERVER_ADDR'])) {
            throw new SyntaxError('The host could not be detected');
        }
        if (false === filter_var($server['SERVER_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
            $server['SERVER_ADDR'] = '[' . $server['SERVER_ADDR'] . ']';
        }
        return [$server['SERVER_ADDR'], $server['SERVER_PORT']];
    }
    /**
     * Returns the environment path.
     *
     * @return array{0: ?string, 1: ?string}
     */
    private static function fetchRequestUri(array $server) : array
    {
        $server += ['IIS_WasUrlRewritten' => null, 'UNENCODED_URL' => '', 'PHP_SELF' => '', 'QUERY_STRING' => null];
        if ('1' === $server['IIS_WasUrlRewritten'] && '' !== $server['UNENCODED_URL']) {
            /** @var array{0:?string, 1:?string} $retval */
            $retval = explode('?', $server['UNENCODED_URL'], 2) + [1 => null];
            return $retval;
        }
        if (isset($server['REQUEST_URI'])) {
            [$path] = explode('?', $server['REQUEST_URI'], 2);
            $query = '' !== $server['QUERY_STRING'] ? $server['QUERY_STRING'] : null;
            return [$path, $query];
        }
        return [$server['PHP_SELF'], $server['QUERY_STRING']];
    }
    /**
     * Generate the URI authority part.
     */
    private function setAuthority() : ?string
    {
        $authority = null;
        if (null !== $this->user_info) {
            $authority = $this->user_info . '@';
        }
        if (null !== $this->host) {
            $authority .= $this->host;
        }
        if (null !== $this->port) {
            $authority .= ':' . $this->port;
        }
        return $authority;
    }
    /**
     * Format the Path component.
     */
    private function formatPath(string $path) : string
    {
        $path = $this->formatDataPath($path);
        static $pattern = '/(?:[^' . self::REGEXP_CHARS_UNRESERVED . self::REGEXP_CHARS_SUBDELIM . '%:@\\/}{]++|%(?![A-Fa-f0-9]{2}))/';
        $path = (string) preg_replace_callback($pattern, [Uri::class, 'urlEncodeMatch'], $path);
        return $this->formatFilePath($path);
    }
    /**
     * Filter the Path component.
     *
     * @link https://tools.ietf.org/html/rfc2397
     *
     * @throws SyntaxError If the path is not compliant with RFC2397
     */
    private function formatDataPath(string $path) : string
    {
        if ('data' !== $this->scheme) {
            return $path;
        }
        if ('' == $path) {
            return 'text/plain;charset=us-ascii,';
        }
        if (strlen($path) !== \Phabel\Target\Php80\Polyfill::strspn($path, self::ASCII) || false === strpos($path, ',')) {
            throw new SyntaxError(sprintf('The path `%s` is invalid according to RFC2937', $path));
        }
        $parts = explode(',', $path, 2) + [1 => null];
        $mediatype = explode(';', (string) $parts[0], 2) + [1 => null];
        $data = (string) $parts[1];
        $mimetype = $mediatype[0];
        if (null === $mimetype || '' === $mimetype) {
            $mimetype = 'text/plain';
        }
        $parameters = $mediatype[1];
        if (null === $parameters || '' === $parameters) {
            $parameters = 'charset=us-ascii';
        }
        $this->assertValidPath($mimetype, $parameters, $data);
        return $mimetype . ';' . $parameters . ',' . $data;
    }
    /**
     * Assert the path is a compliant with RFC2397.
     *
     * @link https://tools.ietf.org/html/rfc2397
     *
     * @throws SyntaxError If the mediatype or the data are not compliant with the RFC2397
     */
    private function assertValidPath(string $mimetype, string $parameters, string $data) : void
    {
        if (1 !== preg_match(self::REGEXP_MIMETYPE, $mimetype)) {
            throw new SyntaxError(sprintf('The path mimetype `%s` is invalid', $mimetype));
        }
        $is_binary = 1 === preg_match(self::REGEXP_BINARY, $parameters, $matches);
        if ($is_binary) {
            $parameters = \Phabel\Target\Php80\Polyfill::substr($parameters, 0, -strlen($matches[0]));
        }
        $res = array_filter(array_filter(explode(';', $parameters), [$this, 'validateParameter']));
        if ([] !== $res) {
            throw new SyntaxError(sprintf('The path paremeters `%s` is invalid', $parameters));
        }
        if (!$is_binary) {
            return;
        }
        $res = base64_decode($data, true);
        if (false === $res || $data !== base64_encode($res)) {
            throw new SyntaxError(sprintf('The path data `%s` is invalid', $data));
        }
    }
    /**
     * Validate mediatype parameter.
     */
    private function validateParameter(string $parameter) : bool
    {
        $properties = explode('=', $parameter);
        return 2 != count($properties) || 'base64' === strtolower($properties[0]);
    }
    /**
     * Format path component for file scheme.
     */
    private function formatFilePath(string $path) : string
    {
        if ('file' !== $this->scheme) {
            return $path;
        }
        $replace = static function (array $matches) : string {
            return $matches['delim'] . $matches['volume'] . ':' . $matches['rest'];
        };
        return (string) preg_replace_callback(self::REGEXP_FILE_PATH, $replace, $path);
    }
    /**
    * Format the Query or the Fragment component.
    *
    * Returns a array containing:
    <ul>
    <li> the formatted component (a string or null)</li>
    <li> a boolean flag telling wether the delimiter is to be added to the component
    when building the URI string representation</li>
    </ul>
    *
    * @param ?string $component
    */
    private function formatQueryAndFragment(?string $component) : ?string
    {
        if (null === $component || '' === $component) {
            return $component;
        }
        static $pattern = '/(?:[^' . self::REGEXP_CHARS_UNRESERVED . self::REGEXP_CHARS_SUBDELIM . '%:@\\/\\?]++|%(?![A-Fa-f0-9]{2}))/';
        return preg_replace_callback($pattern, [Uri::class, 'urlEncodeMatch'], $component);
    }
    /**
     * assert the URI internal state is valid.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3
     * @link https://tools.ietf.org/html/rfc3986#section-3.3
     *
     * @throws SyntaxError if the URI is in an invalid state according to RFC3986
     * @throws SyntaxError if the URI is in an invalid state according to scheme specific rules
     */
    private function assertValidState() : void
    {
        if (null !== $this->authority && ('' !== $this->path && '/' !== $this->path[0])) {
            throw new SyntaxError('If an authority is present the path must be empty or start with a `/`.');
        }
        if (null === $this->authority && 0 === strpos($this->path, '//')) {
            throw new SyntaxError(sprintf('If there is no authority the path `%s` can not start with a `//`.', $this->path));
        }
        $pos = strpos($this->path, ':');
        if (null === $this->authority && null === $this->scheme && false !== $pos && false === strpos(\Phabel\Target\Php80\Polyfill::substr($this->path, 0, $pos), '/')) {
            throw new SyntaxError('In absence of a scheme and an authority the first path segment cannot contain a colon (":") character.');
        }
        $validationMethod = self::SCHEME_VALIDATION_METHOD[$this->scheme] ?? null;
        if (null === $validationMethod || true === $this->{$validationMethod}()) {
            $this->uri = null;
            return;
        }
        throw new SyntaxError(sprintf('The uri `%s` is invalid for the `%s` scheme.', (string) $this, $this->scheme));
    }
    /**
     * URI validation for URI schemes which allows only scheme and path components.
     */
    private function isUriWithSchemeAndPathOnly() : bool
    {
        return null === $this->authority && null === $this->query && null === $this->fragment;
    }
    /**
     * URI validation for URI schemes which allows only scheme, host and path components.
     */
    private function isUriWithSchemeHostAndPathOnly() : bool
    {
        return null === $this->user_info && null === $this->port && null === $this->query && null === $this->fragment && !('' != $this->scheme && null === $this->host);
    }
    /**
     * URI validation for URI schemes which disallow the empty '' host.
     */
    private function isNonEmptyHostUri() : bool
    {
        return '' !== $this->host && !(null !== $this->scheme && null === $this->host);
    }
    /**
    * URI validation for URIs schemes which disallow the empty '' host
    and forbids the fragment component.
    */
    private function isNonEmptyHostUriWithoutFragment() : bool
    {
        return $this->isNonEmptyHostUri() && null === $this->fragment;
    }
    /**
    * URI validation for URIs schemes which disallow the empty '' host
    and forbids fragment and query components.
    */
    private function isNonEmptyHostUriWithoutFragmentAndQuery() : bool
    {
        return $this->isNonEmptyHostUri() && null === $this->fragment && null === $this->query;
    }
    /**
     * Generate the URI string representation from its components.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-5.3
     *
     * @param ?string $scheme
     * @param ?string $authority
     * @param ?string $query
     * @param ?string $fragment
     */
    private function getUriString(?string $scheme, ?string $authority, string $path, ?string $query, ?string $fragment) : string
    {
        if (null !== $scheme) {
            $scheme = $scheme . ':';
        }
        if (null !== $authority) {
            $authority = '//' . $authority;
        }
        if (null !== $query) {
            $query = '?' . $query;
        }
        if (null !== $fragment) {
            $fragment = '#' . $fragment;
        }
        return $scheme . $authority . $path . $query . $fragment;
    }
    /**
     *
     */
    public function toString() : string
    {
        $this->uri = $this->uri ?? $this->getUriString($this->scheme, $this->authority, $this->path, $this->query, $this->fragment);
        return $this->uri;
    }
    /**
     * {@inheritDoc}
     */
    public function __toString() : string
    {
        return $this->toString();
    }
    /**
     * {@inheritDoc}
     */
    public function jsonSerialize() : string
    {
        return $this->toString();
    }
    /**
     * {@inheritDoc}
     *
     * @return array{scheme: ?string, user_info: ?string, host: ?string, port: ?int, path: string, query: ?string, fragment: ?string}
     */
    public function __debugInfo() : array
    {
        return ['scheme' => $this->scheme, 'user_info' => isset($this->user_info) ? preg_replace(',:(.*).?$,', ':***', $this->user_info) : null, 'host' => $this->host, 'port' => $this->port, 'path' => $this->path, 'query' => $this->query, 'fragment' => $this->fragment];
    }
    /**
     * {@inheritDoc}
     */
    public function getScheme() : ?string
    {
        return $this->scheme;
    }
    /**
     * {@inheritDoc}
     */
    public function getAuthority() : ?string
    {
        return $this->authority;
    }
    /**
     * {@inheritDoc}
     */
    public function getUserInfo() : ?string
    {
        return $this->user_info;
    }
    /**
     * {@inheritDoc}
     */
    public function getHost() : ?string
    {
        return $this->host;
    }
    /**
     * {@inheritDoc}
     */
    public function getPort() : ?int
    {
        return $this->port;
    }
    /**
     * {@inheritDoc}
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     * {@inheritDoc}
     */
    public function getQuery() : ?string
    {
        return $this->query;
    }
    /**
     * {@inheritDoc}
     */
    public function getFragment() : ?string
    {
        return $this->fragment;
    }
    /**
     * {@inheritDoc}
     */
    public function withScheme($scheme) : UriInterface
    {
        $scheme = $this->formatScheme($this->filterString($scheme));
        if ($scheme === $this->scheme) {
            return $this;
        }
        $clone = clone $this;
        $clone->scheme = $scheme;
        $clone->port = $clone->formatPort($clone->port);
        $clone->authority = $clone->setAuthority();
        $clone->assertValidState();
        return $clone;
    }
    /**
     * Filter a string.
     *
     * @param mixed $str the value to evaluate as a string
     *
     * @throws SyntaxError if the submitted data can not be converted to string
     */
    private function filterString($str) : ?string
    {
        if (null === $str) {
            return $str;
        }
        if (is_object($str) && method_exists($str, '__toString')) {
            $str = (string) $str;
        }
        if (!is_scalar($str)) {
            throw new \TypeError(sprintf('The component must be a string, a scalar or a stringable object %s given.', gettype($str)));
        }
        $str = (string) $str;
        if (1 !== preg_match(self::REGEXP_INVALID_CHARS, $str)) {
            return $str;
        }
        throw new SyntaxError(sprintf('The component `%s` contains invalid characters.', $str));
    }
    /**
     * {@inheritDoc}
     */
    public function withUserInfo($user, $password = null) : UriInterface
    {
        $user_info = null;
        $user = $this->filterString($user);
        if (null !== $password) {
            $password = $this->filterString($password);
        }
        if ('' !== $user) {
            $user_info = $this->formatUserInfo($user, $password);
        }
        if ($user_info === $this->user_info) {
            return $this;
        }
        $clone = clone $this;
        $clone->user_info = $user_info;
        $clone->authority = $clone->setAuthority();
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withHost($host) : UriInterface
    {
        $host = $this->formatHost($this->filterString($host));
        if ($host === $this->host) {
            return $this;
        }
        $clone = clone $this;
        $clone->host = $host;
        $clone->authority = $clone->setAuthority();
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withPort($port) : UriInterface
    {
        $port = $this->formatPort($port);
        if ($port === $this->port) {
            return $this;
        }
        $clone = clone $this;
        $clone->port = $port;
        $clone->authority = $clone->setAuthority();
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withPath($path) : UriInterface
    {
        $path = $this->filterString($path);
        if (null === $path) {
            throw new \TypeError('A path must be a string NULL given.');
        }
        $path = $this->formatPath($path);
        if ($path === $this->path) {
            return $this;
        }
        $clone = clone $this;
        $clone->path = $path;
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withQuery($query) : UriInterface
    {
        $query = $this->formatQueryAndFragment($this->filterString($query));
        if ($query === $this->query) {
            return $this;
        }
        $clone = clone $this;
        $clone->query = $query;
        $clone->assertValidState();
        return $clone;
    }
    /**
     * {@inheritDoc}
     */
    public function withFragment($fragment) : UriInterface
    {
        $fragment = $this->formatQueryAndFragment($this->filterString($fragment));
        if ($fragment === $this->fragment) {
            return $this;
        }
        $clone = clone $this;
        $clone->fragment = $fragment;
        $clone->assertValidState();
        return $clone;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Contracts\UriException;
class TemplateCanNotBeExpanded extends \InvalidArgumentException implements UriException
{
    /**
     *
     */
    public static function dueToUnableToProcessValueListWithPrefix(string $variableName) : self
    {
        return new self('The ":" modifier can not be applied on "' . $variableName . '" since it is a list of values.');
    }
    /**
     *
     */
    public static function dueToNestedListOfValue(string $variableName) : self
    {
        return new self('The "' . $variableName . '" can not be a nested list.');
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\UriTemplate;

use League\Uri\Exceptions\SyntaxError;
use League\Uri\Exceptions\TemplateCanNotBeExpanded;
use function array_filter;
use function array_keys;
use function array_map;
use function array_unique;
use function explode;
use function implode;
use function preg_match;
use function rawurlencode;
use function str_replace;
use function strpos;
use function substr;
final class Expression
{
    /**
     * Expression regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc6570#section-2.2
     */
    private const REGEXP_EXPRESSION = '/^\\{
        (?:
            (?<operator>[\\.\\/;\\?&\\=,\\!@\\|\\+#])?
            (?<variables>[^\\}]*)
        )
    \\}$/x';
    /**
     * Reserved Operator characters.
     *
     * @link https://tools.ietf.org/html/rfc6570#section-2.2
     */
    private const RESERVED_OPERATOR = '=,!@|';
    /**
     * Processing behavior according to the expression type operator.
     *
     * @link https://tools.ietf.org/html/rfc6570#appendix-A
     */
    private const OPERATOR_HASH_LOOKUP = ['' => ['prefix' => '', 'joiner' => ',', 'query' => false], '+' => ['prefix' => '', 'joiner' => ',', 'query' => false], '#' => ['prefix' => '#', 'joiner' => ',', 'query' => false], '.' => ['prefix' => '.', 'joiner' => '.', 'query' => false], '/' => ['prefix' => '/', 'joiner' => '/', 'query' => false], ';' => ['prefix' => ';', 'joiner' => ';', 'query' => true], '?' => ['prefix' => '?', 'joiner' => '&', 'query' => true], '&' => ['prefix' => '&', 'joiner' => '&', 'query' => true]];
    /**
     * @var string
     */
    private $operator;
    /**
     * @var string
     */
    private $joiner;
    /**
     * @var array<VarSpecifier>
     */
    private $varSpecifiers;
    /**
     * @var array<string>
     */
    private $variableNames;
    /**
     * @var string
     */
    private $expressionString;
    /**
     *
     */
    private function __construct(string $operator, VarSpecifier ...$varSpecifiers)
    {
        $this->operator = $operator;
        $this->varSpecifiers = $varSpecifiers;
        $this->joiner = self::OPERATOR_HASH_LOOKUP[$operator]['joiner'];
        $this->variableNames = $this->setVariableNames();
        $this->expressionString = $this->setExpressionString();
    }
    /**
     * @return array<string>
     */
    private function setVariableNames() : array
    {
        $mapper = static function (VarSpecifier $varSpecifier) : string {
            return $varSpecifier->name();
        };
        return array_unique(array_map($mapper, $this->varSpecifiers));
    }
    /**
     *
     */
    private function setExpressionString() : string
    {
        $mapper = static function (VarSpecifier $variable) : string {
            return $variable->toString();
        };
        $varSpecifierString = implode(',', array_map($mapper, $this->varSpecifiers));
        return '{' . $this->operator . $varSpecifierString . '}';
    }
    /**
     * {@inheritDoc}
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['operator'], ...$properties['varSpecifiers']);
    }
    /**
     * @throws SyntaxError if the expression is invalid
     * @throws SyntaxError if the operator used in the expression is invalid
     * @throws SyntaxError if the variable specifiers is invalid
     */
    public static function createFromString(string $expression) : self
    {
        if (1 !== preg_match(self::REGEXP_EXPRESSION, $expression, $parts)) {
            throw new SyntaxError('The expression "' . $expression . '" is invalid.');
        }
        /** @var array{operator:string, variables:string} $parts */
        $parts = $parts + ['operator' => ''];
        if ('' !== $parts['operator'] && false !== strpos(self::RESERVED_OPERATOR, $parts['operator'])) {
            throw new SyntaxError('The operator used in the expression "' . $expression . '" is reserved.');
        }
        $mapper = static function (string $varSpec) : VarSpecifier {
            return VarSpecifier::createFromString($varSpec);
        };
        return new Expression($parts['operator'], ...array_map($mapper, explode(',', $parts['variables'])));
    }
    /**
     * Returns the expression string representation.
     *
     */
    public function toString() : string
    {
        return $this->expressionString;
    }
    /**
     * @return array<string>
     */
    public function variableNames() : array
    {
        return $this->variableNames;
    }
    /**
     *
     */
    public function expand(VariableBag $variables) : string
    {
        $parts = [];
        foreach ($this->varSpecifiers as $varSpecifier) {
            $parts[] = $this->replace($varSpecifier, $variables);
        }
        $nullFilter = static function ($value) : bool {
            return '' !== $value;
        };
        $expanded = implode($this->joiner, array_filter($parts, $nullFilter));
        if ('' === $expanded) {
            return $expanded;
        }
        $prefix = self::OPERATOR_HASH_LOOKUP[$this->operator]['prefix'];
        if ('' === $prefix) {
            return $expanded;
        }
        return $prefix . $expanded;
    }
    /**
     * Replaces an expression with the given variables.
     *
     * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied
     * @throws TemplateCanNotBeExpanded if the variables contains nested array values
     */
    private function replace(VarSpecifier $varSpec, VariableBag $variables) : string
    {
        $value = $variables->fetch($varSpec->name());
        if (null === $value) {
            return '';
        }
        $useQuery = self::OPERATOR_HASH_LOOKUP[$this->operator]['query'];
        [$expanded, $actualQuery] = $this->inject($value, $varSpec, $useQuery);
        if (!$actualQuery) {
            return $expanded;
        }
        if ('&' !== $this->joiner && '' === $expanded) {
            return $varSpec->name();
        }
        return $varSpec->name() . '=' . $expanded;
    }
    /**
     * @param (string | array<string>) $value
     *
     * @return array{0: string, 1: bool}
     */
    private function inject($value, VarSpecifier $varSpec, bool $useQuery) : array
    {
        if (is_string($value)) {
            return $this->replaceString($value, $varSpec, $useQuery);
        }
        return $this->replaceList($value, $varSpec, $useQuery);
    }
    /**
     * Expands an expression using a string value.
     *
     * @return array{0: string, 1: bool}
     */
    private function replaceString(string $value, VarSpecifier $varSpec, bool $useQuery) : array
    {
        if (':' === $varSpec->modifier()) {
            $value = \Phabel\Target\Php80\Polyfill::substr($value, 0, $varSpec->position());
        }
        $expanded = rawurlencode($value);
        if ('+' === $this->operator || '#' === $this->operator) {
            return [$this->decodeReserved($expanded), $useQuery];
        }
        return [$expanded, $useQuery];
    }
    /**
     * Expands an expression using a list of values.
     *
     * @param array<string> $value
     *
     * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied
     *
     * @return array{0: string, 1: bool}
     */
    private function replaceList(array $value, VarSpecifier $varSpec, bool $useQuery) : array
    {
        if ([] === $value) {
            return ['', false];
        }
        if (':' === $varSpec->modifier()) {
            throw TemplateCanNotBeExpanded::dueToUnableToProcessValueListWithPrefix($varSpec->name());
        }
        $pairs = [];
        $isAssoc = $this->isAssoc($value);
        foreach ($value as $key => $var) {
            if ($isAssoc) {
                $key = rawurlencode((string) $key);
            }
            $var = rawurlencode($var);
            if ('+' === $this->operator || '#' === $this->operator) {
                $var = $this->decodeReserved($var);
            }
            if ('*' === $varSpec->modifier()) {
                if ($isAssoc) {
                    $var = $key . '=' . $var;
                } elseif ($key > 0 && $useQuery) {
                    $var = $varSpec->name() . '=' . $var;
                }
            }
            $pairs[$key] = $var;
        }
        if ('*' === $varSpec->modifier()) {
            if ($isAssoc) {
                // Don't prepend the value name when using the explode
                // modifier with an associative array.
                $useQuery = false;
            }
            return [implode($this->joiner, $pairs), $useQuery];
        }
        if ($isAssoc) {
            // When an associative array is encountered and the
            // explode modifier is not set, then the result must be
            // a comma separated list of keys followed by their
            // respective values.
            foreach ($pairs as $offset => &$data) {
                $data = $offset . ',' . $data;
            }
            unset($data);
        }
        return [implode(',', $pairs), $useQuery];
    }
    /**
    * Determines if an array is associative.
    *
    * This makes the assumption that input arrays are sequences or hashes.
    This assumption is a trade-off for accuracy in favor of speed, but it
    should work in almost every case where input is supplied for a URI
    template.
    */
    private function isAssoc(array $array) : bool
    {
        return [] !== $array && 0 !== array_keys($array)[0];
    }
    /**
     * Removes percent encoding on reserved characters (used with + and # modifiers).
     */
    private function decodeReserved(string $str) : string
    {
        static $delimiters = [':', '/', '?', '#', '[', ']', '@', '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';', '='];
        static $delimitersEncoded = ['%3A', '%2F', '%3F', '%23', '%5B', '%5D', '%40', '%21', '%24', '%26', '%27', '%28', '%29', '%2A', '%2B', '%2C', '%3B', '%3D'];
        return str_replace($delimitersEncoded, $delimiters, $str);
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\UriTemplate;

use League\Uri\Exceptions\SyntaxError;
use function preg_match;
final class VarSpecifier
{
    /**
     * Variables specification regular expression pattern.
     *
     * @link https://tools.ietf.org/html/rfc6570#section-2.3
     */
    private const REGEXP_VARSPEC = '/^
        (?<name>(?:[A-z0-9_\\.]|%[0-9a-fA-F]{2})+)
        (?<modifier>\\:(?<position>\\d+)|\\*)?
    $/x';
    /**
     * @var string
     */
    private $name;
    /**
     * @var string
     */
    private $modifier;
    /**
     * @var int
     */
    private $position;
    /**
     *
     */
    private function __construct(string $name, string $modifier, int $position)
    {
        $this->name = $name;
        $this->modifier = $modifier;
        $this->position = $position;
    }
    /**
     * {@inheritDoc}
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['name'], $properties['modifier'], $properties['position']);
    }
    /**
     *
     */
    public static function createFromString(string $specification) : self
    {
        if (1 !== preg_match(self::REGEXP_VARSPEC, $specification, $parsed)) {
            throw new SyntaxError('The variable specification "' . $specification . '" is invalid.');
        }
        $parsed += ['modifier' => '', 'position' => ''];
        if ('' !== $parsed['position']) {
            $parsed['position'] = (int) $parsed['position'];
            $parsed['modifier'] = ':';
        }
        if ('' === $parsed['position']) {
            $parsed['position'] = 0;
        }
        if (10000 <= $parsed['position']) {
            throw new SyntaxError('The variable specification "' . $specification . '" is invalid the position modifier must be lower than 10000.');
        }
        return new self($parsed['name'], $parsed['modifier'], $parsed['position']);
    }
    /**
     *
     */
    public function toString() : string
    {
        if (0 < $this->position) {
            return $this->name . $this->modifier . $this->position;
        }
        return $this->name . $this->modifier;
    }
    /**
     *
     */
    public function name() : string
    {
        return $this->name;
    }
    /**
     *
     */
    public function modifier() : string
    {
        return $this->modifier;
    }
    /**
     *
     */
    public function position() : int
    {
        return $this->position;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\UriTemplate;

use League\Uri\Exceptions\TemplateCanNotBeExpanded;
use function gettype;
use function is_array;
use function is_bool;
use function is_object;
use function is_scalar;
use function method_exists;
use function sprintf;
final class VariableBag
{
    /**
     * @var array<string,string|array<string>>
     */
    private $variables = [];
    /**
     * @param iterable<string, mixed> $variables
     */
    public function __construct(iterable $variables = [])
    {
        foreach ($variables as $name => $value) {
            $this->assign($name, $value);
        }
    }
    /**
     *
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['variables']);
    }
    /**
     * @return array<string, (string | array<string>)>
     */
    public function all() : array
    {
        return $this->variables;
    }
    /**
     * Fetches the variable value if none found returns null.
     *
     * @return (null | string | array<string>)
     */
    public function fetch(string $name)
    {
        return $this->variables[$name] ?? null;
    }
    /**
     * @param (string | array<string>) $value
     */
    public function assign(string $name, $value) : void
    {
        $this->variables[$name] = $this->normalizeValue($value, $name, true);
    }
    /**
     * @param mixed $value the value to be expanded
     *
     * @throws TemplateCanNotBeExpanded if the value contains nested list
     *
     * @return (string | array<string>)
     */
    private function normalizeValue($value, string $name, bool $isNestedListAllowed)
    {
        if (is_bool($value)) {
            return true === $value ? '1' : '0';
        }
        if (null === $value || is_scalar($value) || is_object($value) && method_exists($value, '__toString')) {
            return (string) $value;
        }
        if (!is_array($value)) {
            throw new \TypeError(sprintf('The variable ' . $name . ' must be NULL, a scalar or a stringable object `%s` given', gettype($value)));
        }
        if (!$isNestedListAllowed) {
            throw TemplateCanNotBeExpanded::dueToNestedListOfValue($name);
        }
        foreach ($value as &$var) {
            $var = self::normalizeValue($var, $name, false);
        }
        unset($var);
        return $value;
    }
    /**
     * Replaces elements from passed variables into the current instance.
     */
    public function replace(VariableBag $variables) : self
    {
        $instance = clone $this;
        $instance->variables += $variables->variables;
        return $instance;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\UriTemplate;

use League\Uri\Exceptions\SyntaxError;
use League\Uri\Exceptions\TemplateCanNotBeExpanded;
use function array_merge;
use function array_unique;
use function gettype;
use function is_object;
use function is_string;
use function method_exists;
use function preg_match_all;
use function preg_replace;
use function sprintf;
use function strpos;
use const PREG_SET_ORDER;
final class Template
{
    /**
     * Expression regular expression pattern.
     */
    private const REGEXP_EXPRESSION_DETECTOR = '/\\{[^\\}]*\\}/x';
    /**
     * @var string
     */
    private $template;
    /**
     * @var array<string, Expression>
     */
    private $expressions = [];
    /**
     * @var array<string>
     */
    private $variableNames;
    /**
     *
     */
    private function __construct(string $template, Expression ...$expressions)
    {
        $this->template = $template;
        $variableNames = [];
        foreach ($expressions as $expression) {
            $this->expressions[$expression->toString()] = $expression;
            $variableNames[] = $expression->variableNames();
        }
        $this->variableNames = array_unique(array_merge([], ...$variableNames));
    }
    /**
     * {@inheritDoc}
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['template'], ...array_values($properties['expressions']));
    }
    /**
     * @param (object | string) $template a string or an object with the __toString method
     *
     * @throws \TypeError if the template is not a string or an object with the __toString method
     * @throws SyntaxError if the template contains invalid expressions
     * @throws SyntaxError if the template contains invalid variable specification
     */
    public static function createFromString($template) : self
    {
        if (is_object($template) && method_exists($template, '__toString')) {
            $template = (string) $template;
        }
        if (!is_string($template)) {
            throw new \TypeError(sprintf('The template must be a string or a stringable object %s given.', gettype($template)));
        }
        /** @var string $remainder */
        $remainder = preg_replace(self::REGEXP_EXPRESSION_DETECTOR, '', $template);
        if (false !== strpos($remainder, '{') || false !== strpos($remainder, '}')) {
            throw new SyntaxError('The template "' . $template . '" contains invalid expressions.');
        }
        $names = [];
        preg_match_all(self::REGEXP_EXPRESSION_DETECTOR, $template, $findings, PREG_SET_ORDER);
        $arguments = [];
        foreach ($findings as $finding) {
            if (!isset($names[$finding[0]])) {
                $arguments[] = Expression::createFromString($finding[0]);
                $names[$finding[0]] = 1;
            }
        }
        return new self($template, ...$arguments);
    }
    /**
     *
     */
    public function toString() : string
    {
        return $this->template;
    }
    /**
     * @return array<string>
     */
    public function variableNames() : array
    {
        return $this->variableNames;
    }
    /**
     * @throws TemplateCanNotBeExpanded if the variables is an array and a ":" modifier needs to be applied
     * @throws TemplateCanNotBeExpanded if the variables contains nested array values
     */
    public function expand(VariableBag $variables) : string
    {
        $uriString = $this->template;
        /** @var Expression $expression */
        foreach ($this->expressions as $pattern => $expression) {
            $uriString = str_replace($pattern, $expression->expand($variables), $uriString);
        }
        return $uriString;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Exceptions\IdnaConversionFailed;
use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
use League\Uri\Idna\Idna;
use function array_merge;
use function explode;
use function filter_var;
use function gettype;
use function inet_pton;
use function is_object;
use function is_scalar;
use function method_exists;
use function preg_match;
use function rawurldecode;
use function sprintf;
use function strpos;
use function substr;
use const FILTER_FLAG_IPV6;
use const FILTER_VALIDATE_IP;
/**
 * A class to parse a URI string according to RFC3986.
 *
 * @link    https://tools.ietf.org/html/rfc3986
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   6.0.0
 */
final class UriString
{
    /**
     * Default URI component values.
     */
    private const URI_COMPONENTS = ['scheme' => null, 'user' => null, 'pass' => null, 'host' => null, 'port' => null, 'path' => '', 'query' => null, 'fragment' => null];
    /**
     * Simple URI which do not need any parsing.
     */
    private const URI_SCHORTCUTS = ['' => [], '#' => ['fragment' => ''], '?' => ['query' => ''], '?#' => ['query' => '', 'fragment' => ''], '/' => ['path' => '/'], '//' => ['host' => '']];
    /**
     * Range of invalid characters in URI string.
     */
    private const REGEXP_INVALID_URI_CHARS = '/[\\x00-\\x1f\\x7f]/';
    /**
     * RFC3986 regular expression URI splitter.
     *
     * @link https://tools.ietf.org/html/rfc3986#appendix-B
     */
    private const REGEXP_URI_PARTS = ',^
        (?<scheme>(?<scontent>[^:/?\\#]+):)?    # URI scheme component
        (?<authority>//(?<acontent>[^/?\\#]*))? # URI authority part
        (?<path>[^?\\#]*)                       # URI path component
        (?<query>\\?(?<qcontent>[^\\#]*))?       # URI query component
        (?<fragment>\\#(?<fcontent>.*))?        # URI fragment component
    ,x';
    /**
     * URI scheme regular expresssion.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.1
     */
    private const REGEXP_URI_SCHEME = '/^([a-z][a-z\\d\\+\\.\\-]*)?$/i';
    /**
     * IPvFuture regular expression.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_IP_FUTURE = '/^
        v(?<version>[A-F0-9])+\\.
        (?:
            (?<unreserved>[a-z0-9_~\\-\\.])|
            (?<sub_delims>[!$&\'()*+,;=:])  # also include the : character
        )+
    $/ix';
    /**
     * General registered name regular expression.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_REGISTERED_NAME = '/(?(DEFINE)
        (?<unreserved>[a-z0-9_~\\-])   # . is missing as it is used to separate labels
        (?<sub_delims>[!$&\'()*+,;=])
        (?<encoded>%[A-F0-9]{2})
        (?<reg_name>(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*)
    )
    ^(?:(?&reg_name)\\.)*(?&reg_name)\\.?$/ix';
    /**
     * Invalid characters in host regular expression.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    private const REGEXP_INVALID_HOST_CHARS = '/
        [:\\/?#\\[\\]@ ]  # gen-delims characters as well as the space character
    /ix';
    /**
     * Invalid path for URI without scheme and authority regular expression.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.3
     */
    private const REGEXP_INVALID_PATH = ',^(([^/]*):)(.*)?/,';
    /**
     * Host and Port splitter regular expression.
     */
    private const REGEXP_HOST_PORT = ',^(?<host>\\[.*\\]|[^:]*)(:(?<port>.*))?$,';
    /**
     * IDN Host detector regular expression.
     */
    private const REGEXP_IDN_PATTERN = '/[^\\x20-\\x7f]/';
    /**
     * Only the address block fe80::/10 can have a Zone ID attach to
     * let's detect the link local significant 10 bits.
     */
    private const ZONE_ID_ADDRESS_BLOCK = "\xfe\x80";
    /**
    * Generate an URI string representation from its parsed representation
    returned by League\Uri\parse() or PHP's parse_url.
    *
    * If you supply your own array, you are responsible for providing
    valid components without their URI delimiters.
    *
    * @link https://tools.ietf.org/html/rfc3986#section-5.3
    * @link https://tools.ietf.org/html/rfc3986#section-7.5
    *
    * @param array{scheme: ?string, user: ?string, pass: ?string, host: ?string, port: ?int, path: string, query: ?string, fragment: ?string} $components
    */
    public static function build(array $components) : string
    {
        $result = $components['path'] ?? '';
        if (isset($components['query'])) {
            $result .= '?' . $components['query'];
        }
        if (isset($components['fragment'])) {
            $result .= '#' . $components['fragment'];
        }
        $scheme = null;
        if (isset($components['scheme'])) {
            $scheme = $components['scheme'] . ':';
        }
        if (!isset($components['host'])) {
            return $scheme . $result;
        }
        $scheme .= '//';
        $authority = $components['host'];
        if (isset($components['port'])) {
            $authority .= ':' . $components['port'];
        }
        if (!isset($components['user'])) {
            return $scheme . $authority . $result;
        }
        $authority = '@' . $authority;
        if (!isset($components['pass'])) {
            return $scheme . $components['user'] . $authority . $result;
        }
        return $scheme . $components['user'] . ':' . $components['pass'] . $authority . $result;
    }
    /**
    * Parse an URI string into its components.
    *
    * This method parses a URI and returns an associative array containing any
    of the various components of the URI that are present.
    *
    * <code>
    $components = (new Parser())->parse('http://foo@test.example.com:42?query#');
    var_export($components);
    //will display
    array(
    'scheme' => 'http',           // the URI scheme component
    'user' => 'foo',              // the URI user component
    'pass' => null,               // the URI pass component
    'host' => 'test.example.com', // the URI host component
    'port' => 42,                 // the URI port component
    'path' => '',                 // the URI path component
    'query' => 'query',           // the URI query component
    'fragment' => '',             // the URI fragment component
    );
    </code>
    *
    * The returned array is similar to PHP's parse_url return value with the following
    differences:
    *
    * <ul>
    <li>All components are always present in the returned array</li>
    <li>Empty and undefined component are treated differently. And empty component is
    set to the empty string while an undefined component is set to the `null` value.</li>
    <li>The path component is never undefined</li>
    <li>The method parses the URI following the RFC3986 rules but you are still
    required to validate the returned components against its related scheme specific rules.</li>
    </ul>
    *
    * @link https://tools.ietf.org/html/rfc3986
    *
    * @param mixed $uri any scalar or stringable object
    *
    * @throws SyntaxError if the URI contains invalid characters
    * @throws SyntaxError if the URI contains an invalid scheme
    * @throws SyntaxError if the URI contains an invalid path
    *
    * @return array{scheme: ?string, user: ?string, pass: ?string, host: ?string, port: ?int, path: string, query: ?string, fragment: ?string}
    */
    public static function parse($uri) : array
    {
        if (is_object($uri) && method_exists($uri, '__toString')) {
            $uri = (string) $uri;
        }
        if (!is_scalar($uri)) {
            throw new \TypeError(sprintf('The uri must be a scalar or a stringable object `%s` given', gettype($uri)));
        }
        $uri = (string) $uri;
        if (isset(self::URI_SCHORTCUTS[$uri])) {
            /** @var array{scheme:?string, user:?string, pass:?string, host:?string, port:?int, path:string, query:?string, fragment:?string} $components */
            $components = array_merge(self::URI_COMPONENTS, self::URI_SCHORTCUTS[$uri]);
            return $components;
        }
        if (1 === preg_match(self::REGEXP_INVALID_URI_CHARS, $uri)) {
            throw new SyntaxError(sprintf('The uri `%s` contains invalid characters', $uri));
        }
        //if the first character is a known URI delimiter parsing can be simplified
        $first_char = $uri[0];
        //The URI is made of the fragment only
        if ('#' === $first_char) {
            [, $fragment] = explode('#', $uri, 2);
            $components = self::URI_COMPONENTS;
            $components['fragment'] = $fragment;
            return $components;
        }
        //The URI is made of the query and fragment
        if ('?' === $first_char) {
            [, $partial] = explode('?', $uri, 2);
            [$query, $fragment] = explode('#', $partial, 2) + [1 => null];
            $components = self::URI_COMPONENTS;
            $components['query'] = $query;
            $components['fragment'] = $fragment;
            return $components;
        }
        //use RFC3986 URI regexp to split the URI
        preg_match(self::REGEXP_URI_PARTS, $uri, $parts);
        $parts += ['query' => '', 'fragment' => ''];
        if (':' === $parts['scheme'] || 1 !== preg_match(self::REGEXP_URI_SCHEME, $parts['scontent'])) {
            throw new SyntaxError(sprintf('The uri `%s` contains an invalid scheme', $uri));
        }
        if ('' === $parts['scheme'] . $parts['authority'] && 1 === preg_match(self::REGEXP_INVALID_PATH, $parts['path'])) {
            throw new SyntaxError(sprintf('The uri `%s` contains an invalid path.', $uri));
        }
        /** @var array{scheme:?string, user:?string, pass:?string, host:?string, port:?int, path:string, query:?string, fragment:?string} $components */
        $components = array_merge(self::URI_COMPONENTS, '' === $parts['authority'] ? [] : self::parseAuthority($parts['acontent']), ['path' => $parts['path'], 'scheme' => '' === $parts['scheme'] ? null : $parts['scontent'], 'query' => '' === $parts['query'] ? null : $parts['qcontent'], 'fragment' => '' === $parts['fragment'] ? null : $parts['fcontent']]);
        return $components;
    }
    /**
     * Parses the URI authority part.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2
     *
     * @throws SyntaxError If the port component is invalid
     *
     * @return array{user: ?string, pass: ?string, host: ?string, port: ?int}
     */
    private static function parseAuthority(string $authority) : array
    {
        $components = ['user' => null, 'pass' => null, 'host' => '', 'port' => null];
        if ('' === $authority) {
            return $components;
        }
        $parts = explode('@', $authority, 2);
        if (isset($parts[1])) {
            [$components['user'], $components['pass']] = explode(':', $parts[0], 2) + [1 => null];
        }
        preg_match(self::REGEXP_HOST_PORT, $parts[1] ?? $parts[0], $matches);
        $matches += ['port' => ''];
        $components['port'] = self::filterPort($matches['port']);
        $components['host'] = self::filterHost($matches['host']);
        return $components;
    }
    /**
     * Filter and format the port component.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     *
     * @throws SyntaxError if the registered name is invalid
     */
    private static function filterPort(string $port) : ?int
    {
        if ('' === $port) {
            return null;
        }
        if (1 === preg_match('/^\\d*$/', $port)) {
            return (int) $port;
        }
        throw new SyntaxError(sprintf('The port `%s` is invalid', $port));
    }
    /**
     * Returns whether a hostname is valid.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     *
     * @throws SyntaxError if the registered name is invalid
     */
    private static function filterHost(string $host) : string
    {
        if ('' === $host) {
            return $host;
        }
        if ('[' !== $host[0] || ']' !== \Phabel\Target\Php80\Polyfill::substr($host, -1)) {
            return self::filterRegisteredName($host);
        }
        if (!self::isIpHost(\Phabel\Target\Php80\Polyfill::substr($host, 1, -1))) {
            throw new SyntaxError(sprintf('Host `%s` is invalid : the IP host is malformed', $host));
        }
        return $host;
    }
    /**
     * Returns whether the host is an IPv4 or a registered named.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     *
     * @throws SyntaxError if the registered name is invalid
     * @throws IdnSupportMissing if IDN support or ICU requirement are not available or met.
     */
    private static function filterRegisteredName(string $host) : string
    {
        $formatted_host = rawurldecode($host);
        if (1 === preg_match(self::REGEXP_REGISTERED_NAME, $formatted_host)) {
            return $host;
        }
        //to test IDN host non-ascii characters must be present in the host
        if (1 !== preg_match(self::REGEXP_IDN_PATTERN, $formatted_host)) {
            throw new SyntaxError(sprintf('Host `%s` is invalid : the host is not a valid registered name', $host));
        }
        $info = Idna::toAscii($host, Idna::IDNA2008_ASCII);
        if (0 !== $info->errors()) {
            throw IdnaConversionFailed::dueToIDNAError($host, $info);
        }
        return $host;
    }
    /**
     * Validates a IPv6/IPvfuture host.
     *
     * @link https://tools.ietf.org/html/rfc3986#section-3.2.2
     * @link https://tools.ietf.org/html/rfc6874#section-2
     * @link https://tools.ietf.org/html/rfc6874#section-4
     */
    private static function isIpHost(string $ip_host) : bool
    {
        if (false !== filter_var($ip_host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return true;
        }
        if (1 === preg_match(self::REGEXP_IP_FUTURE, $ip_host, $matches)) {
            return !in_array($matches['version'], ['4', '6'], true);
        }
        $pos = strpos($ip_host, '%');
        if (false === $pos || 1 === preg_match(self::REGEXP_INVALID_HOST_CHARS, rawurldecode(\Phabel\Target\Php80\Polyfill::substr($ip_host, $pos)))) {
            return false;
        }
        $ip_host = \Phabel\Target\Php80\Polyfill::substr($ip_host, 0, $pos);
        return false !== filter_var($ip_host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) && 0 === strpos((string) inet_pton($ip_host), self::ZONE_ID_ADDRESS_BLOCK);
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use Psr\Http\Message\UriFactoryInterface;
use Psr\Http\Message\UriInterface;
final class HttpFactory implements UriFactoryInterface
{
    /**
     *
     */
    public function createUri(string $uri = '') : UriInterface
    {
        return Http::createFromString($uri);
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use League\Uri\Contracts\UriException;
use League\Uri\Contracts\UriInterface;
use League\Uri\Exceptions\SyntaxError;
use League\Uri\Exceptions\TemplateCanNotBeExpanded;
use League\Uri\UriTemplate\Template;
use League\Uri\UriTemplate\VariableBag;
/**
 * Defines the URI Template syntax and the process for expanding a URI Template into a URI reference.
 *
 * @link    https://tools.ietf.org/html/rfc6570
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   6.1.0
 *
 * Based on GuzzleHttp\UriTemplate class in Guzzle v6.5.
 * @link https://github.com/guzzle/guzzle/blob/6.5/src/UriTemplate.php
 */
final class UriTemplate
{
    /**
     * @var Template
     */
    private $template;
    /**
     * @var VariableBag
     */
    private $defaultVariables;
    /**
     * @param (object | string) $template a string or an object with the __toString method
     *
     * @throws \TypeError if the template is not a string or an object with the __toString method
     * @throws SyntaxError if the template syntax is invalid
     * @throws TemplateCanNotBeExpanded if the template variables are invalid
     */
    public function __construct($template, array $defaultVariables = [])
    {
        $this->template = Template::createFromString($template);
        $this->defaultVariables = $this->filterVariables($defaultVariables);
    }
    /**
     *
     */
    public static function __set_state(array $properties) : self
    {
        return new self($properties['template']->toString(), $properties['defaultVariables']->all());
    }
    /**
     * Filters out variables for the given template.
     *
     * @param array<string, (string | array<string>)> $variables
     */
    private function filterVariables(array $variables) : VariableBag
    {
        $output = new VariableBag();
        foreach ($this->template->variableNames() as $name) {
            if (isset($variables[$name])) {
                $output->assign($name, $variables[$name]);
            }
        }
        return $output;
    }
    /**
     * The template string.
     */
    public function getTemplate() : string
    {
        return $this->template->toString();
    }
    /**
     * Returns the names of the variables in the template, in order.
     *
     * @return string[]
     */
    public function getVariableNames() : array
    {
        return $this->template->variableNames();
    }
    /**
     * Returns the default values used to expand the template.
     *
     * The returned list only contains variables whose name is part of the current template.
     *
     * @return array<string, (string | array)>
     */
    public function getDefaultVariables() : array
    {
        return $this->defaultVariables->all();
    }
    /**
    * Returns a new instance with the updated default variables.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified default variables.
    *
    * If present, variables whose name is not part of the current template
    possible variable names are removed.
    */
    public function withDefaultVariables(array $defaultDefaultVariables) : self
    {
        $clone = clone $this;
        $clone->defaultVariables = $this->filterVariables($defaultDefaultVariables);
        return $clone;
    }
    /**
     * @throws TemplateCanNotBeExpanded if the variable contains nested array values
     * @throws UriException if the resulting expansion can not be converted to a UriInterface instance
     */
    public function expand(array $variables = []) : UriInterface
    {
        $uriString = $this->template->expand($this->filterVariables($variables)->replace($this->defaultVariables));
        return Uri::createFromString($uriString);
    }
}<?php

$header = <<<EOF
League.Uri (https://uri.thephpleague.com)

(c) Ignace Nyamagana Butera <nyamsprod@gmail.com>

For the full copyright and license information, please view the LICENSE
file that was distributed with this source code.
EOF;
$finder = PhpCsFixer\Finder::create()->in(__DIR__ . '/src')->in(__DIR__ . '/benchmark');
$config = new PhpCsFixer\Config();
return $config->setRules(['@PSR2' => true, 'array_syntax' => ['syntax' => 'short'], 'concat_space' => ['spacing' => 'none'], 'header_comment' => ['comment_type' => 'PHPDoc', 'header' => $header, 'location' => 'after_open', 'separate' => 'both'], 'new_with_braces' => true, 'no_blank_lines_after_phpdoc' => true, 'no_empty_phpdoc' => true, 'no_empty_comment' => true, 'no_leading_import_slash' => true, 'no_superfluous_phpdoc_tags' => true, 'no_trailing_comma_in_singleline_array' => true, 'no_unused_imports' => true, 'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'], 'phpdoc_add_missing_param_annotation' => ['only_untyped' => false], 'phpdoc_align' => true, 'phpdoc_no_empty_return' => true, 'phpdoc_order' => true, 'phpdoc_scalar' => true, 'phpdoc_to_comment' => true, 'phpdoc_summary' => true, 'psr_autoloading' => true, 'return_type_declaration' => ['space_before' => 'none'], 'single_blank_line_before_namespace' => true, 'single_quote' => true, 'space_after_semicolon' => true, 'ternary_operator_spaces' => true, 'trailing_comma_in_multiline' => true, 'trim_array_spaces' => true, 'whitespace_after_comma_in_array' => true, 'yoda_style' => true])->setFinder($finder);{
    "name": "league/uri",
    "type": "library",
    "description" : "URI manipulation library",
    "keywords": [
        "url",
        "uri",
        "rfc3986",
        "rfc3987",
        "rfc6570",
        "psr-7",
        "parse_url",
        "http",
        "https",
        "ws",
        "ftp",
        "data-uri",
        "file-uri",
        "middleware",
        "parse_str",
        "query-string",
        "querystring",
        "hostname",
        "uri-template"
    ],
    "license": "MIT",
    "homepage": "http://uri.thephpleague.com",
    "authors": [
        {
            "name" : "Ignace Nyamagana Butera",
            "email" : "nyamsprod@gmail.com",
            "homepage" : "https://nyamsprod.com"
        }
    ],
    "support": {
        "forum": "https://thephpleague.slack.com",
        "docs": "https://uri.thephpleague.com",
        "issues": "https://github.com/thephpleague/uri/issues"
    },
    "funding": [
        {
            "type": "github",
            "url": "https://github.com/sponsors/nyamsprod"
        }
    ],
    "require": {
        "php": "^7.3 || ^8.0",
        "ext-json": "*",
        "psr/http-message": "^1.0",
        "league/uri-interfaces": "^2.3"
    },
    "require-dev": {
        "friendsofphp/php-cs-fixer": "^2.19 || ^3.0",
        "phpunit/phpunit" : "^8.0 || ^9.0",
        "phpstan/phpstan": "^0.12.90",
        "phpstan/phpstan-strict-rules": "^0.12.11",
        "phpstan/phpstan-phpunit": "^0.12.22",
        "psr/http-factory": "^1.0"
    },
    "autoload": {
        "psr-4": {
            "League\\Uri\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "LeagueTest\\Uri\\": "tests"
        }
    },
    "conflict": {
        "league/uri-schemes": "^1.0"
    },
    "scripts": {
        "phpcs": "php-cs-fixer fix -v --diff --dry-run --allow-risky=yes --ansi",
        "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi",
        "phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi --memory-limit=256M",
        "phpunit": "phpunit --coverage-text",
        "test": [
            "@phpunit",
            "@phpstan",
            "@phpcs"
        ]
    },
    "scripts-descriptions": {
        "phpcs": "Runs coding style test suite",
        "phpstan": "Runs complete codebase static analysis",
        "phpunit": "Runs unit and functional testing",
        "test": "Runs full test suite"
    },
    "suggest": {
        "league/uri-components" : "Needed to easily manipulate URI objects",
        "ext-intl" : "Needed to improve host validation",
        "ext-fileinfo": "Needed to create Data URI from a filepath",
        "psr/http-factory": "Needed to use the URI factory"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "6.x-dev"
        }
    },
    "config": {
        "sort-packages": true
    }
}
<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

/**
 * An exception thrown if the IDN support is missing or
 * the ICU is not at least version 4.6.
 *
 * @see     https://tools.ietf.org/html/rfc3986
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   1.4.0
 */
class MissingIdnSupport extends Exception
{
}<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use InvalidArgumentException;
/**
 * An exception thrown on parse attempts of invalid URIs.
 *
 * @see     https://tools.ietf.org/html/rfc3986
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   0.2.0
 */
class Exception extends InvalidArgumentException
{
    /**
     * Returns a new Instance from an error in URI characters.
     *
     * @return static
     */
    public static function createFromInvalidCharacters(string $uri)
    {
        return new static(sprintf('The submitted uri `%s` contains invalid characters', $uri));
    }
    /**
     * Returns a new Instance from an error in URI characters.
     *
     * @return static
     */
    public static function createFromInvalidScheme(string $uri)
    {
        return new static(sprintf('The submitted uri `%s` contains an invalid scheme', $uri));
    }
    /**
     * Returns a new Instance from an error in Host validation.
     *
     * @return static
     */
    public static function createFromInvalidHost(string $host)
    {
        return new static(sprintf('The submitted host `%s` is invalid', $host));
    }
    /**
     * Returns a new Instance from an error in port validation.
     *
     * @return static
     */
    public static function createFromInvalidHostname(string $hostname)
    {
        return new static(sprintf('The submitted hostname `%s` is invalid', $hostname));
    }
    /**
     * Returns a new Instance from an error in port validation.
     *
     * @param (string | int) $port
     *
     * @return static
     */
    public static function createFromInvalidPort($port)
    {
        return new static(sprintf('The submitted port `%s` is invalid', $port));
    }
    /**
     * Returns a new Instance from an error in Uri path component.
     *
     * @return static
     */
    public static function createFromInvalidPath(string $uri)
    {
        return new static(sprintf('The submitted uri `%s` contains an invalid path', $uri));
    }
}<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

/**
 * Returns whether the URI host component is valid according to RFC3986.
 *
 * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
 * @see Parser::isHost()
 */
function is_host(string $host) : bool
{
    static $parser;
    $parser = $parser ?? new Parser();
    return $parser->isHost($host);
}
/**
 * Returns whether the URI port component is valid according to RFC3986.
 *
 * @see https://tools.ietf.org/html/rfc3986#section-3.2.3
 * @see Parser::isPort()
 */
function is_port($port) : bool
{
    static $parser;
    $parser = $parser ?? new Parser();
    return $parser->isPort($port);
}
/**
 * Returns whether the URI scheme component is valid according to RFC3986.
 *
 * @see https://tools.ietf.org/html/rfc3986#section-3.1
 * @see Parser::isScheme()
 */
function is_scheme(string $scheme) : bool
{
    static $parser;
    $parser = $parser ?? new Parser();
    return $parser->isScheme($scheme);
}
/**
* Parse an URI string into its components.
*
* This method parses a URL and returns an associative array containing any
of the various components of the URL that are present.
*
* @see https://tools.ietf.org/html/rfc3986
* @see https://tools.ietf.org/html/rfc3986#section-2
* @see Parser::parse()
*
* @throws Exception if the URI contains invalid characters
*/
function parse(string $uri) : array
{
    static $parser;
    $parser = $parser ?? new Parser();
    return $parser->parse($uri);
}
/**
* Generate an URI string representation from its parsed representation
returned by League\Uri\Parser::parse() or PHP's parse_url.
*
* If you supply your own array, you are responsible for providing
valid components without their URI delimiters.
*
* For security reasons the password (pass) component has been deprecated
as per RFC3986 and is never returned in the URI string
*
* @see https://tools.ietf.org/html/rfc3986#section-5.3
* @see https://tools.ietf.org/html/rfc3986#section-7.5
*/
function build(array $components) : string
{
    $uri = $components['path'] ?? '';
    if (isset($components['query'])) {
        $uri .= '?' . $components['query'];
    }
    if (isset($components['fragment'])) {
        $uri .= '#' . $components['fragment'];
    }
    if (isset($components['host'])) {
        $authority = $components['host'];
        if (isset($components['port'])) {
            $authority .= ':' . $components['port'];
        }
        if (isset($components['user'])) {
            $authority = $components['user'] . '@' . $authority;
        }
        $uri = '//' . $authority . $uri;
    }
    if (isset($components['scheme'])) {
        return $components['scheme'] . ':' . $uri;
    }
    return $uri;
}<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
if (!function_exists('League\\Uri\\parse')) {
    require __DIR__ . '/functions.php';
}<?php

/**
 * League.Uri (http://uri.thephpleague.com/parser).
 *
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @license https://github.com/thephpleague/uri-parser/blob/master/LICENSE (MIT License)
 * @version 1.4.1
 * @link    https://uri.thephpleague.com/parser/
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri;

use UnexpectedValueException;
/**
 * A class to parse a URI string according to RFC3986.
 *
 * @see     https://tools.ietf.org/html/rfc3986
 * @package League\Uri
 * @author  Ignace Nyamagana Butera <nyamsprod@gmail.com>
 * @since   0.1.0
 */
class Parser
{
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const INVALID_URI_CHARS = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\v\f\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f";
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const SCHEME_VALID_STARTING_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const SCHEME_VALID_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+.-';
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const LABEL_VALID_STARTING_CHARS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const LOCAL_LINK_PREFIX = '1111111010';
    const URI_COMPONENTS = ['scheme' => null, 'user' => null, 'pass' => null, 'host' => null, 'port' => null, 'path' => '', 'query' => null, 'fragment' => null];
    /** @deprecated 1.4.0 will be removed in the next major point release */
    const SUB_DELIMITERS = '!$&\'()*+,;=';
    /**
     * Returns whether a scheme is valid.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.1
     */
    public function isScheme(string $scheme) : bool
    {
        static $pattern = '/^[a-z][a-z0-9\\+\\.\\-]*$/i';
        return '' === $scheme || 1 === preg_match($pattern, $scheme);
    }
    /**
     * Returns whether a hostname is valid.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    public function isHost(string $host) : bool
    {
        return '' === $host || $this->isIpHost($host) || $this->isRegisteredName($host);
    }
    /**
     * Validate a IPv6/IPvfuture host.
     *
     * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
     * @see http://tools.ietf.org/html/rfc6874#section-2
     * @see http://tools.ietf.org/html/rfc6874#section-4
     */
    private function isIpHost(string $host) : bool
    {
        if ('[' !== ($host[0] ?? '') || ']' !== \Phabel\Target\Php80\Polyfill::substr($host, -1)) {
            return false;
        }
        $ip = \Phabel\Target\Php80\Polyfill::substr($host, 1, -1);
        if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return true;
        }
        static $ip_future = '/^
            v(?<version>[A-F0-9])+\\.
            (?:
                (?<unreserved>[a-z0-9_~\\-\\.])|
                (?<sub_delims>[!$&\'()*+,;=:])  # also include the : character
            )+
        $/ix';
        if (1 === preg_match($ip_future, $ip, $matches) && !in_array($matches['version'], ['4', '6'], true)) {
            return true;
        }
        if (false === ($pos = strpos($ip, '%'))) {
            return false;
        }
        static $gen_delims = '/[:\\/?#\\[\\]@ ]/';
        // Also includes space.
        if (1 === preg_match($gen_delims, rawurldecode(\Phabel\Target\Php80\Polyfill::substr($ip, $pos)))) {
            return false;
        }
        $ip = \Phabel\Target\Php80\Polyfill::substr($ip, 0, $pos);
        if (!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return false;
        }
        //Only the address block fe80::/10 can have a Zone ID attach to
        //let's detect the link local significant 10 bits
        static $address_block = "\xfe\x80";
        return 0 === strpos((string) inet_pton($ip), $address_block);
    }
    /**
    * Returns whether the host is an IPv4 or a registered named.
    *
    * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
    *
    * @throws MissingIdnSupport if the registered name contains non-ASCII characters
    and IDN support or ICU requirement are not available or met.
    *
    */
    protected function isRegisteredName(string $host) : bool
    {
        // Note that unreserved is purposely missing . as it is used to separate labels.
        static $reg_name = '/(?(DEFINE)
                (?<unreserved>[a-z0-9_~\\-])
                (?<sub_delims>[!$&\'()*+,;=])
                (?<encoded>%[A-F0-9]{2})
                (?<reg_name>(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*)
            )
            ^(?:(?&reg_name)\\.)*(?&reg_name)\\.?$/ix';
        if (1 === preg_match($reg_name, $host)) {
            return true;
        }
        //to test IDN host non-ascii characters must be present in the host
        static $idn_pattern = '/[^\\x20-\\x7f]/';
        if (1 !== preg_match($idn_pattern, $host)) {
            return false;
        }
        static $idn_support = null;
        $idn_support = $idn_support ?? function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46');
        // @codeCoverageIgnoreStart
        // added because it is not possible in travis to disabled the ext/intl extension
        // see travis issue https://github.com/travis-ci/travis-ci/issues/4701
        if (!$idn_support) {
            throw new MissingIdnSupport(sprintf('the host `%s` could not be processed for IDN. Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.', $host));
        }
        // @codeCoverageIgnoreEnd
        $ascii_host = idn_to_ascii($host, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46, $arr);
        // @codeCoverageIgnoreStart
        if (false === $ascii_host && 0 === $arr['errors']) {
            throw new UnexpectedValueException(sprintf('The Intl extension is misconfigured for %s, please correct this issue before proceeding.', PHP_OS));
        }
        // @codeCoverageIgnoreEnd
        return 0 === $arr['errors'];
    }
    /**
     * Returns whether a port is valid.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    public function isPort($port) : bool
    {
        static $pattern = '/^[0-9]+$/';
        if (null === $port || '' === $port) {
            return true;
        }
        return 1 === preg_match($pattern, (string) $port);
    }
    /**
     * Parse a URI string into its components.
     *
     * @see Parser::parse
     *
     * @throws Exception if the URI contains invalid characters
     */
    public function __invoke(string $uri) : array
    {
        return $this->parse($uri);
    }
    /**
    * Parse an URI string into its components.
    *
    * This method parses a URI and returns an associative array containing any
    of the various components of the URI that are present.
    *
    * <code>
    $components = (new Parser())->parse('http://foo@test.example.com:42?query#');
    var_export($components);
    //will display
    array(
    'scheme' => 'http',           // the URI scheme component
    'user' => 'foo',              // the URI user component
    'pass' => null,               // the URI pass component
    'host' => 'test.example.com', // the URI host component
    'port' => 42,                 // the URI port component
    'path' => '',                 // the URI path component
    'query' => 'query',           // the URI query component
    'fragment' => '',             // the URI fragment component
    );
    </code>
    *
    * The returned array is similar to PHP's parse_url return value with the following
    differences:
    *
    * <ul>
    <li>All components are always present in the returned array</li>
    <li>Empty and undefined component are treated differently. And empty component is
    set to the empty string while an undefined component is set to the `null` value.</li>
    <li>The path component is never undefined</li>
    <li>The method parses the URI following the RFC3986 rules but you are still
    required to validate the returned components against its related scheme specific rules.</li>
    </ul>
    *
    * @see https://tools.ietf.org/html/rfc3986
    * @see https://tools.ietf.org/html/rfc3986#section-2
    *
    * @throws Exception if the URI contains invalid characters
    */
    public function parse(string $uri) : array
    {
        static $pattern = '/[\\x00-\\x1f\\x7f]/';
        //simple URI which do not need any parsing
        static $simple_uri = ['' => [], '#' => ['fragment' => ''], '?' => ['query' => ''], '?#' => ['query' => '', 'fragment' => ''], '/' => ['path' => '/'], '//' => ['host' => '']];
        if (isset($simple_uri[$uri])) {
            return array_merge(self::URI_COMPONENTS, $simple_uri[$uri]);
        }
        if (1 === preg_match($pattern, $uri)) {
            throw Exception::createFromInvalidCharacters($uri);
        }
        //if the first character is a known URI delimiter parsing can be simplified
        $first_char = $uri[0];
        //The URI is made of the fragment only
        if ('#' === $first_char) {
            $components = self::URI_COMPONENTS;
            $components['fragment'] = (string) \Phabel\Target\Php80\Polyfill::substr($uri, 1);
            return $components;
        }
        //The URI is made of the query and fragment
        if ('?' === $first_char) {
            $components = self::URI_COMPONENTS;
            list($components['query'], $components['fragment']) = explode('#', \Phabel\Target\Php80\Polyfill::substr($uri, 1), 2) + [1 => null];
            return $components;
        }
        //The URI does not contain any scheme part
        if (0 === strpos($uri, '//')) {
            return $this->parseSchemeSpecificPart($uri);
        }
        //The URI is made of a path, query and fragment
        if ('/' === $first_char || false === strpos($uri, ':')) {
            return $this->parsePathQueryAndFragment($uri);
        }
        //Fallback parser
        return $this->fallbackParser($uri);
    }
    /**
    * Extract components from a URI without a scheme part.
    *
    * The URI MUST start with the authority component
    preceded by its delimiter the double slash ('//')
    *
    * Example: //user:pass@host:42/path?query#fragment
    *
    * The authority MUST adhere to the RFC3986 requirements.
    *
    * If the URI contains a path component, it MUST be empty or absolute
    according to RFC3986 path classification.
    *
    * This method returns an associative array containing all URI components.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.2
    * @see https://tools.ietf.org/html/rfc3986#section-3.3
    *
    * @throws Exception If any component of the URI is invalid
    */
    protected function parseSchemeSpecificPart(string $uri) : array
    {
        //We remove the authority delimiter
        $remaining_uri = (string) \Phabel\Target\Php80\Polyfill::substr($uri, 2);
        $components = self::URI_COMPONENTS;
        //Parsing is done from the right upmost part to the left
        //1 - detect fragment, query and path part if any
        list($remaining_uri, $components['fragment']) = explode('#', $remaining_uri, 2) + [1 => null];
        list($remaining_uri, $components['query']) = explode('?', $remaining_uri, 2) + [1 => null];
        if (false !== strpos($remaining_uri, '/')) {
            list($remaining_uri, $components['path']) = explode('/', $remaining_uri, 2) + [1 => null];
            $components['path'] = '/' . $components['path'];
        }
        //2 - The $remaining_uri represents the authority part
        //if the authority part is empty parsing is simplified
        if ('' === $remaining_uri) {
            $components['host'] = '';
            return $components;
        }
        //otherwise we split the authority into the user information and the hostname parts
        $parts = explode('@', $remaining_uri, 2);
        $hostname = $parts[1] ?? $parts[0];
        $user_info = isset($parts[1]) ? $parts[0] : null;
        if (null !== $user_info) {
            list($components['user'], $components['pass']) = explode(':', $user_info, 2) + [1 => null];
        }
        list($components['host'], $components['port']) = $this->parseHostname($hostname);
        return $components;
    }
    /**
     * Parse and validate the URI hostname.
     *
     * @throws Exception If the hostname is invalid
     */
    protected function parseHostname(string $hostname) : array
    {
        if (false === strpos($hostname, '[')) {
            list($host, $port) = explode(':', $hostname, 2) + [1 => null];
            return [$this->filterHost($host), $this->filterPort($port)];
        }
        $delimiter_offset = strpos($hostname, ']') + 1;
        if (isset($hostname[$delimiter_offset]) && ':' !== $hostname[$delimiter_offset]) {
            throw Exception::createFromInvalidHostname($hostname);
        }
        return [$this->filterHost(\Phabel\Target\Php80\Polyfill::substr($hostname, 0, $delimiter_offset)), $this->filterPort(\Phabel\Target\Php80\Polyfill::substr($hostname, ++$delimiter_offset))];
    }
    /**
     * validate the host component.
     *
     * @param (string | null) $host
     *
     * @throws Exception If the hostname is invalid
     *
     * @return (string | null)
     */
    protected function filterHost($host)
    {
        if (null === $host || $this->isHost($host)) {
            return $host;
        }
        throw Exception::createFromInvalidHost($host);
    }
    /**
     * Validate a port number.
     *
     * An exception is raised for ports outside the established TCP and UDP port ranges.
     *
     * @param mixed $port the port number
     *
     * @throws Exception If the port number is invalid.
     *
     * @return (null | int)
     */
    protected function filterPort($port)
    {
        static $pattern = '/^[0-9]+$/';
        if (null === $port || false === $port || '' === $port) {
            return null;
        }
        if (1 !== preg_match($pattern, (string) $port)) {
            throw Exception::createFromInvalidPort($port);
        }
        return (int) $port;
    }
    /**
    * Extract Components from an URI without scheme or authority part.
    *
    * The URI contains a path component and MUST adhere to path requirements
    of RFC3986. The path can be
    *
    * <code>
    path   = path-abempty    ; begins with "/" or is empty
    / path-absolute   ; begins with "/" but not "//"
    / path-noscheme   ; begins with a non-colon segment
    / path-rootless   ; begins with a segment
    / path-empty      ; zero characters
    </code>
    *
    * ex: path?q#f
    ex: /path
    ex: /pa:th#f
    *
    * This method returns an associative array containing all URI components.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.3
    *
    * @throws Exception If the path component is invalid
    */
    protected function parsePathQueryAndFragment(string $uri) : array
    {
        //No scheme is present so we ensure that the path respects RFC3986
        if (false !== ($pos = strpos($uri, ':')) && false === strpos(\Phabel\Target\Php80\Polyfill::substr($uri, 0, $pos), '/')) {
            throw Exception::createFromInvalidPath($uri);
        }
        $components = self::URI_COMPONENTS;
        //Parsing is done from the right upmost part to the left
        //1 - detect the fragment part if any
        list($remaining_uri, $components['fragment']) = explode('#', $uri, 2) + [1 => null];
        //2 - detect the query and the path part
        list($components['path'], $components['query']) = explode('?', $remaining_uri, 2) + [1 => null];
        return $components;
    }
    /**
    * Extract components from an URI containing a colon.
    *
    * Depending on the colon ":" position and on the string
    composition before the presence of the colon, the URI
    will be considered to have an scheme or not.
    *
    * <ul>
    <li>In case no valid scheme is found according to RFC3986 the URI will
    be parsed as an URI without a scheme and an authority</li>
    <li>In case an authority part is detected the URI specific part is parsed
    as an URI without scheme</li>
    </ul>
    *
    * ex: email:johndoe@thephpleague.com?subject=Hellow%20World!
    *
    * This method returns an associative array containing all
    the URI components.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.1
    * @see Parser::parsePathQueryAndFragment
    * @see Parser::parseSchemeSpecificPart
    *
    * @throws Exception If the URI scheme component is empty
    */
    protected function fallbackParser(string $uri) : array
    {
        //1 - we split the URI on the first detected colon character
        $parts = explode(':', $uri, 2);
        $remaining_uri = $parts[1] ?? $parts[0];
        $scheme = isset($parts[1]) ? $parts[0] : null;
        //1.1 - a scheme can not be empty (ie a URI can not start with a colon)
        if ('' === $scheme) {
            throw Exception::createFromInvalidScheme($uri);
        }
        //2 - depending on the scheme presence and validity we will differ the parsing
        //2.1 - If the scheme part is invalid the URI may be an URI with a path-noscheme
        //      let's differ the parsing to the Parser::parsePathQueryAndFragment method
        if (!$this->isScheme($scheme)) {
            return $this->parsePathQueryAndFragment($uri);
        }
        $components = self::URI_COMPONENTS;
        $components['scheme'] = $scheme;
        //2.2 - if no scheme specific part is detect parsing is finished
        if ('' == $remaining_uri) {
            return $components;
        }
        //2.3 - if the scheme specific part is a double forward slash
        if ('//' === $remaining_uri) {
            $components['host'] = '';
            return $components;
        }
        //2.4 - if the scheme specific part starts with double forward slash
        //      we differ the remaining parsing to the Parser::parseSchemeSpecificPart method
        if (0 === strpos($remaining_uri, '//')) {
            $components = $this->parseSchemeSpecificPart($remaining_uri);
            $components['scheme'] = $scheme;
            return $components;
        }
        //2.5 - Parsing is done from the right upmost part to the left from the scheme specific part
        //2.5.1 - detect the fragment part if any
        list($remaining_uri, $components['fragment']) = explode('#', $remaining_uri, 2) + [1 => null];
        //2.5.2 - detect the part and query part if any
        list($components['path'], $components['query']) = explode('?', $remaining_uri, 2) + [1 => null];
        return $components;
    }
    /**
    * Convert a registered name label to its IDNA ASCII form.
    *
    * DEPRECATION WARNING! This method will be removed in the next major point release
    *
    * @deprecated 1.4.0 this method is no longer used to validate RFC3987 compliant host component
    * @codeCoverageIgnore
    *
    * Conversion is done only if the label contains none valid label characters
    if a '%' sub delimiter is detected the label MUST be rawurldecode prior to
    making the conversion
    *
    * @return (string | false)
    */
    protected function toAscii(string $label)
    {
        trigger_error(self::class . '::' . __METHOD__ . ' is deprecated and will be removed in the next major point release', E_USER_DEPRECATED);
        if (false !== strpos($label, '%')) {
            $label = rawurldecode($label);
        }
        static $idn_support = null;
        $idn_support = $idn_support ?? function_exists('idn_to_ascii') && defined('INTL_IDNA_VARIANT_UTS46');
        if (!$idn_support) {
            throw new MissingIdnSupport(sprintf('the label `%s` could not be processed for IDN. Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.', $label));
        }
        $ascii_host = idn_to_ascii($label, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46, $arr);
        if (false === $ascii_host && 0 === $arr['errors']) {
            throw new UnexpectedValueException(sprintf('The Intl extension is misconfigured for %s, please correct this issue before proceeding.', PHP_OS));
        }
        return $ascii_host;
    }
    /**
     * Returns whether the registered name label is valid.
     *
     * DEPRECATION WARNING! This method will be removed in the next major point release
     *
     * @deprecated 1.4.0 this method is no longer used to validated the host component
     * @codeCoverageIgnore
     *
     * A valid registered name label MUST conform to the following ABNF
     *
     * reg-name = *( unreserved / pct-encoded / sub-delims )
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     *
     * @param string $label
     */
    protected function isHostLabel($label) : bool
    {
        trigger_error(self::class . '::' . __METHOD__ . ' is deprecated and will be removed in the next major point release', E_USER_DEPRECATED);
        return '' != $label && 63 >= strlen($label) && strlen($label) == \Phabel\Target\Php80\Polyfill::strspn($label, self::LABEL_VALID_STARTING_CHARS . '-_~' . self::SUB_DELIMITERS);
    }
    /**
     * Validate an IPv6 host.
     *
     * DEPRECATION WARNING! This method will be removed in the next major point release
     *
     * @deprecated 1.4.0 this method is no longer used to validated the host component
     * @codeCoverageIgnore
     *
     * @see http://tools.ietf.org/html/rfc6874#section-2
     * @see http://tools.ietf.org/html/rfc6874#section-4
     */
    protected function isIpv6Host(string $ipv6) : bool
    {
        trigger_error(self::class . '::' . __METHOD__ . ' is deprecated and will be removed in the next major point release', E_USER_DEPRECATED);
        if ('[' !== ($ipv6[0] ?? '') || ']' !== \Phabel\Target\Php80\Polyfill::substr($ipv6, -1)) {
            return false;
        }
        $ipv6 = \Phabel\Target\Php80\Polyfill::substr($ipv6, 1, -1);
        if (false === ($pos = strpos($ipv6, '%'))) {
            return (bool) filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
        }
        $scope = rawurldecode(\Phabel\Target\Php80\Polyfill::substr($ipv6, $pos));
        if (strlen($scope) !== \Phabel\Target\Php80\Polyfill::strcspn($scope, '?#@[]')) {
            return false;
        }
        $ipv6 = \Phabel\Target\Php80\Polyfill::substr($ipv6, 0, $pos);
        if (!filter_var($ipv6, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
            return false;
        }
        //Only the address block fe80::/10 can have a Zone ID attach to
        //let's detect the link local significant 10 bits
        return 0 === strpos((string) inet_pton($ipv6), "\xfe\x80");
    }
}{
    "name": "league/uri-parser",
    "type": "library",
    "description" : "userland URI parser RFC 3986 compliant",
    "keywords": [
        "url",
        "uri",
        "rfc3986",
        "rfc3987",
        "parse_url",
        "parser"
    ],
    "license": "MIT",
    "homepage": "https://github.com/thephpleague/uri-parser",
    "authors": [
        {
            "name" : "Ignace Nyamagana Butera",
            "email" : "nyamsprod@gmail.com",
            "homepage" : "https://nyamsprod.com"
        }
    ],
    "require": {
        "php" : ">=7.0.0"
    },
    "require-dev": {
        "friendsofphp/php-cs-fixer": "^2.0",
        "phpunit/phpunit" : "^6.0",
        "phpstan/phpstan": "^0.9.2",
        "phpstan/phpstan-strict-rules": "^0.9.0",
        "phpstan/phpstan-phpunit": "^0.9.4"
    },
    "autoload": {
        "psr-4": {
            "League\\Uri\\": "src"
        },
        "files": ["src/functions_include.php"]
    },
    "autoload-dev": {
        "psr-4": {
            "LeagueTest\\Uri\\Parser\\": "tests"
        }
    },
    "suggest": {
        "ext-intl" : "Allow parsing RFC3987 compliant hosts",
        "league/uri-schemes": "Allow validating and normalizing URI parsing results"
    },
    "scripts": {
        "phpcs": "php-cs-fixer fix -v --diff --dry-run --allow-risky=yes;",
        "phpstan-src": "phpstan analyse -l 7 -c phpstan.src.neon src",
        "phpstan-tests": "phpstan analyse -l 7 -c phpstan.tests.neon tests",
        "phpstan": [
            "@phpstan-src",
            "@phpstan-tests"
        ],
        "phpunit": "phpunit --coverage-text",
        "test": [
            "@phpunit",
            "@phpcs",
            "@phpstan"
        ]
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    },
    "config": {
        "sort-packages": true
    }
}
<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Idna;

use function array_filter;
use const ARRAY_FILTER_USE_KEY;
/**
 * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html
 */
final class IdnaInfo
{
    private const ERRORS = [Idna::ERROR_EMPTY_LABEL => 'a non-final domain name label (or the whole domain name) is empty', Idna::ERROR_LABEL_TOO_LONG => 'a domain name label is longer than 63 bytes', Idna::ERROR_DOMAIN_NAME_TOO_LONG => 'a domain name is longer than 255 bytes in its storage form', Idna::ERROR_LEADING_HYPHEN => 'a label starts with a hyphen-minus ("-")', Idna::ERROR_TRAILING_HYPHEN => 'a label ends with a hyphen-minus ("-")', Idna::ERROR_HYPHEN_3_4 => 'a label contains hyphen-minus ("-") in the third and fourth positions', Idna::ERROR_LEADING_COMBINING_MARK => 'a label starts with a combining mark', Idna::ERROR_DISALLOWED => 'a label or domain name contains disallowed characters', Idna::ERROR_PUNYCODE => 'a label starts with "xn--" but does not contain valid Punycode', Idna::ERROR_LABEL_HAS_DOT => 'a label contains a dot=full stop', Idna::ERROR_INVALID_ACE_LABEL => 'An ACE label does not contain a valid label string', Idna::ERROR_BIDI => 'a label does not meet the IDNA BiDi requirements (for right-to-left characters)', Idna::ERROR_CONTEXTJ => 'a label does not meet the IDNA CONTEXTJ requirements', Idna::ERROR_CONTEXTO_DIGITS => 'a label does not meet the IDNA CONTEXTO requirements for digits', Idna::ERROR_CONTEXTO_PUNCTUATION => 'a label does not meet the IDNA CONTEXTO requirements for punctuation characters. Some punctuation characters "Would otherwise have been DISALLOWED" but are allowed in certain contexts'];
    /** @var string */
    private $result;
    /** @var bool */
    private $isTransitionalDifferent;
    /** @var int */
    private $errors;
    /**
     * @var array<int, string>
     */
    private $errorList;
    /**
     *
     */
    private function __construct(string $result, bool $isTransitionalDifferent, int $errors)
    {
        $this->result = $result;
        $this->errors = $errors;
        $this->isTransitionalDifferent = $isTransitionalDifferent;
        $this->errorList = array_filter(self::ERRORS, function (int $error) : bool {
            return 0 !== ($error & $this->errors);
        }, ARRAY_FILTER_USE_KEY);
    }
    /**
     * @param array{result: string, isTransitionalDifferent: bool, errors: int} $infos
     */
    public static function fromIntl(array $infos) : self
    {
        return new self($infos['result'], $infos['isTransitionalDifferent'], $infos['errors']);
    }
    /**
     * @param array{result: string, isTransitionalDifferent: bool, errors: int} $properties
     */
    public static function __set_state(array $properties) : self
    {
        return self::fromIntl($properties);
    }
    /**
     *
     */
    public function result() : string
    {
        return $this->result;
    }
    /**
     *
     */
    public function isTransitionalDifferent() : bool
    {
        return $this->isTransitionalDifferent;
    }
    /**
     *
     */
    public function errors() : int
    {
        return $this->errors;
    }
    /**
     *
     */
    public function error(int $error) : ?string
    {
        return $this->errorList[$error] ?? null;
    }
    /**
     * @return array<int, string>
     */
    public function errorList() : array
    {
        return $this->errorList;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Idna;

use League\Uri\Exceptions\IdnaConversionFailed;
use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
use function defined;
use function function_exists;
use function idn_to_ascii;
use function idn_to_utf8;
use function rawurldecode;
use const INTL_IDNA_VARIANT_UTS46;
/**
 * @see https://unicode-org.github.io/icu-docs/apidoc/released/icu4c/uidna_8h.html
 */
final class Idna
{
    private const REGEXP_IDNA_PATTERN = '/[^\\x20-\\x7f]/';
    private const MAX_DOMAIN_LENGTH = 253;
    private const MAX_LABEL_LENGTH = 63;
    /**
     * General registered name regular expression.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     * @see https://regex101.com/r/fptU8V/1
     */
    private const REGEXP_REGISTERED_NAME = '/
        (?(DEFINE)
            (?<unreserved>[a-z0-9_~\\-])   # . is missing as it is used to separate labels
            (?<sub_delims>[!$&\'()*+,;=])
            (?<encoded>%[A-F0-9]{2})
            (?<reg_name>(?:(?&unreserved)|(?&sub_delims)|(?&encoded))*)
        )
            ^(?:(?&reg_name)\\.)*(?&reg_name)\\.?$
        /ix';
    /**
     * IDNA options.
     */
    public const IDNA_DEFAULT = 0;
    public const IDNA_ALLOW_UNASSIGNED = 1;
    public const IDNA_USE_STD3_RULES = 2;
    public const IDNA_CHECK_BIDI = 4;
    public const IDNA_CHECK_CONTEXTJ = 8;
    public const IDNA_NONTRANSITIONAL_TO_ASCII = 0x10;
    public const IDNA_NONTRANSITIONAL_TO_UNICODE = 0x20;
    public const IDNA_CHECK_CONTEXTO = 0x40;
    /**
     * IDNA errors.
     */
    public const ERROR_NONE = 0;
    public const ERROR_EMPTY_LABEL = 1;
    public const ERROR_LABEL_TOO_LONG = 2;
    public const ERROR_DOMAIN_NAME_TOO_LONG = 4;
    public const ERROR_LEADING_HYPHEN = 8;
    public const ERROR_TRAILING_HYPHEN = 0x10;
    public const ERROR_HYPHEN_3_4 = 0x20;
    public const ERROR_LEADING_COMBINING_MARK = 0x40;
    public const ERROR_DISALLOWED = 0x80;
    public const ERROR_PUNYCODE = 0x100;
    public const ERROR_LABEL_HAS_DOT = 0x200;
    public const ERROR_INVALID_ACE_LABEL = 0x400;
    public const ERROR_BIDI = 0x800;
    public const ERROR_CONTEXTJ = 0x1000;
    public const ERROR_CONTEXTO_PUNCTUATION = 0x2000;
    public const ERROR_CONTEXTO_DIGITS = 0x4000;
    /**
     * IDNA default options.
     */
    public const IDNA2008_ASCII = self::IDNA_NONTRANSITIONAL_TO_ASCII | self::IDNA_CHECK_BIDI | self::IDNA_USE_STD3_RULES | self::IDNA_CHECK_CONTEXTJ;
    public const IDNA2008_UNICODE = self::IDNA_NONTRANSITIONAL_TO_UNICODE | self::IDNA_CHECK_BIDI | self::IDNA_USE_STD3_RULES | self::IDNA_CHECK_CONTEXTJ;
    /**
     * @codeCoverageIgnore
     */
    private static function supportsIdna() : void
    {
        static $idnSupport;
        if (null === $idnSupport) {
            $idnSupport = function_exists('\\idn_to_ascii') && defined('\\INTL_IDNA_VARIANT_UTS46');
        }
        if (!$idnSupport) {
            throw new IdnSupportMissing('IDN host can not be processed. Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.');
        }
    }
    /**
     * Converts the input to its IDNA ASCII form.
     *
     * This method returns the string converted to IDN ASCII form
     *
     * @throws SyntaxError if the string can not be converted to ASCII using IDN UTS46 algorithm
     */
    public static function toAscii(string $domain, int $options) : IdnaInfo
    {
        $domain = rawurldecode($domain);
        if (1 === preg_match(self::REGEXP_IDNA_PATTERN, $domain)) {
            self::supportsIdna();
            /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */
            idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
            if ([] === $idnaInfo) {
                return IdnaInfo::fromIntl(['result' => strtolower($domain), 'isTransitionalDifferent' => false, 'errors' => self::validateDomainAndLabelLength($domain)]);
            }
            /* @var array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */
            return IdnaInfo::fromIntl($idnaInfo);
        }
        $error = self::ERROR_NONE;
        if (1 !== preg_match(self::REGEXP_REGISTERED_NAME, $domain)) {
            $error |= self::ERROR_DISALLOWED;
        }
        return IdnaInfo::fromIntl(['result' => strtolower($domain), 'isTransitionalDifferent' => false, 'errors' => self::validateDomainAndLabelLength($domain) | $error]);
    }
    /**
     * Converts the input to its IDNA UNICODE form.
     *
     * This method returns the string converted to IDN UNICODE form
     *
     * @throws SyntaxError if the string can not be converted to UNICODE using IDN UTS46 algorithm
     */
    public static function toUnicode(string $domain, int $options) : IdnaInfo
    {
        $domain = rawurldecode($domain);
        if (false === stripos($domain, 'xn--')) {
            return IdnaInfo::fromIntl(['result' => $domain, 'isTransitionalDifferent' => false, 'errors' => self::ERROR_NONE]);
        }
        self::supportsIdna();
        /* @param-out array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */
        idn_to_utf8($domain, $options, INTL_IDNA_VARIANT_UTS46, $idnaInfo);
        if ([] === $idnaInfo) {
            throw IdnaConversionFailed::dueToInvalidHost($domain);
        }
        /* @var array{errors: int, isTransitionalDifferent: bool, result: string} $idnaInfo */
        return IdnaInfo::fromIntl($idnaInfo);
    }
    /**
     * Adapted from https://github.com/TRowbotham/idna.
     *
     * @see https://github.com/TRowbotham/idna/blob/master/src/Idna.php#L236
     */
    private static function validateDomainAndLabelLength(string $domain) : int
    {
        $error = self::ERROR_NONE;
        $labels = explode('.', $domain);
        $maxDomainSize = self::MAX_DOMAIN_LENGTH;
        $length = count($labels);
        // If the last label is empty and it is not the first label, then it is the root label.
        // Increase the max size by 1, making it 254, to account for the root label's "."
        // delimiter. This also means we don't need to check the last label's length for being too
        // long.
        if ($length > 1 && $labels[$length - 1] === '') {
            ++$maxDomainSize;
            array_pop($labels);
        }
        if (strlen($domain) > $maxDomainSize) {
            $error |= self::ERROR_DOMAIN_NAME_TOO_LONG;
        }
        foreach ($labels as $label) {
            if (strlen($label) > self::MAX_LABEL_LENGTH) {
                $error |= self::ERROR_LABEL_TOO_LONG;
                break;
            }
        }
        return $error;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Contracts\UriException;
class FileinfoSupportMissing extends \RuntimeException implements UriException
{
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Contracts\UriException;
class SyntaxError extends \InvalidArgumentException implements UriException
{
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Contracts\UriException;
class IdnSupportMissing extends \RuntimeException implements UriException
{
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Exceptions;

use League\Uri\Idna\IdnaInfo;
final class IdnaConversionFailed extends SyntaxError
{
    /** @var IdnaInfo|null  */
    private $idnaInfo;
    /**
     *
     */
    private function __construct(string $message, IdnaInfo $idnaInfo = null)
    {
        parent::__construct($message);
        $this->idnaInfo = $idnaInfo;
    }
    /**
     *
     */
    public static function dueToIDNAError(string $domain, IdnaInfo $idnaInfo) : self
    {
        return new self('The host `' . $domain . '` is invalid : ' . implode(', ', $idnaInfo->errorList()) . ' .', $idnaInfo);
    }
    /**
     *
     */
    public static function dueToInvalidHost(string $domain) : self
    {
        return new self('The host `' . $domain . '` is not a valid IDN host');
    }
    /**
     *
     */
    public function idnaInfo() : ?IdnaInfo
    {
        return $this->idnaInfo;
    }
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\SyntaxError;
/**
 * @extends \IteratorAggregate<string>
 */
interface DomainHostInterface extends \Countable, HostInterface, \IteratorAggregate
{
    /**
     * Returns the labels total number.
     */
    public function count() : int;
    /**
     * Iterate over the Domain labels.
     *
     * @return \Iterator<string>
     */
    public function getIterator() : \Iterator;
    /**
     * Retrieves a single host label.
     *
     * If the label offset has not been set, returns the null value.
     */
    public function get(int $offset) : ?string;
    /**
     * Returns the associated key for a specific label or all the keys.
     *
     * @param ?string $label
     *
     * @return int[]
     */
    public function keys(?string $label = null) : array;
    /**
     * Tells whether the domain is absolute.
     */
    public function isAbsolute() : bool;
    /**
     * Prepends a label to the host.
     */
    public function prepend(string $label) : self;
    /**
     * Appends a label to the host.
     */
    public function append(string $label) : self;
    /**
     * Returns an instance with its Root label.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    public function withRootLabel() : self;
    /**
     * Returns an instance without its Root label.
     *
     * @see https://tools.ietf.org/html/rfc3986#section-3.2.2
     */
    public function withoutRootLabel() : self;
    /**
    * Returns an instance with the modified label.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the new label
    *
    * If $key is non-negative, the added label will be the label at $key position from the start.
    If $key is negative, the added label will be the label at $key position from the end.
    *
    * @throws SyntaxError If the key is invalid
    */
    public function withLabel(int $key, string $label) : self;
    /**
    * Returns an instance without the specified label.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified component
    *
    * If $key is non-negative, the removed label will be the label at $key position from the start.
    If $key is negative, the removed label will be the label at $key position from the end.
    *
    * @param int ...$keys
    *
    * @throws SyntaxError If the key is invalid
    */
    public function withoutLabel(int ...$keys) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface PortInterface extends UriComponentInterface
{
    /**
     * Returns the integer representation of the Port.
     */
    public function toInt() : ?int;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
interface UriInterface extends \JsonSerializable
{
    /**
     * Returns the string representation as a URI reference.
     *
     * @see http://tools.ietf.org/html/rfc3986#section-4.1
     */
    public function __toString() : string;
    /**
     * Returns the string representation as a URI reference.
     *
     * @see http://tools.ietf.org/html/rfc3986#section-4.1
     * @see ::__toString
     */
    public function jsonSerialize() : string;
    /**
    * Retrieve the scheme component of the URI.
    *
    * If no scheme is present, this method MUST return a null value.
    *
    * The value returned MUST be normalized to lowercase, per RFC 3986
    Section 3.1.
    *
    * The trailing ":" character is not part of the scheme and MUST NOT be
    added.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.1
    */
    public function getScheme() : ?string;
    /**
    * Retrieve the authority component of the URI.
    *
    * If no scheme is present, this method MUST return a null value.
    *
    * If the port component is not set or is the standard port for the current
    scheme, it SHOULD NOT be included.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.2
    */
    public function getAuthority() : ?string;
    /**
    * Retrieve the user information component of the URI.
    *
    * If no scheme is present, this method MUST return a null value.
    *
    * If a user is present in the URI, this will return that value;
    additionally, if the password is also present, it will be appended to the
    user value, with a colon (":") separating the values.
    *
    * The trailing "@" character is not part of the user information and MUST
    NOT be added.
    */
    public function getUserInfo() : ?string;
    /**
    * Retrieve the host component of the URI.
    *
    * If no host is present this method MUST return a null value.
    *
    * The value returned MUST be normalized to lowercase, per RFC 3986
    Section 3.2.2.
    *
    * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
    */
    public function getHost() : ?string;
    /**
    * Retrieve the port component of the URI.
    *
    * If a port is present, and it is non-standard for the current scheme,
    this method MUST return it as an integer. If the port is the standard port
    used with the current scheme, this method SHOULD return null.
    *
    * If no port is present, and no scheme is present, this method MUST return
    a null value.
    *
    * If no port is present, but a scheme is present, this method MAY return
    the standard port for that scheme, but SHOULD return null.
    */
    public function getPort() : ?int;
    /**
    * Retrieve the path component of the URI.
    *
    * The path can either be empty or absolute (starting with a slash) or
    rootless (not starting with a slash). Implementations MUST support all
    three syntaxes.
    *
    * Normally, the empty path "" and absolute path "/" are considered equal as
    defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
    do this normalization because in contexts with a trimmed base path, e.g.
    the front controller, this difference becomes significant. It's the task
    of the user to handle both "" and "/".
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.3.
    *
    * As an example, if the value should include a slash ("/") not intended as
    delimiter between path segments, that value MUST be passed in encoded
    form (e.g., "%2F") to the instance.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.3
    */
    public function getPath() : string;
    /**
    * Retrieve the query string of the URI.
    *
    * If no host is present this method MUST return a null value.
    *
    * The leading "?" character is not part of the query and MUST NOT be
    added.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.4.
    *
    * As an example, if a value in a key/value pair of the query string should
    include an ampersand ("&") not intended as a delimiter between values,
    that value MUST be passed in encoded form (e.g., "%26") to the instance.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.4
    */
    public function getQuery() : ?string;
    /**
    * Retrieve the fragment component of the URI.
    *
    * If no host is present this method MUST return a null value.
    *
    * The leading "#" character is not part of the fragment and MUST NOT be
    added.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.5.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.5
    */
    public function getFragment() : ?string;
    /**
    * Return an instance with the specified scheme.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified scheme.
    *
    * A null value provided for the scheme is equivalent to removing the scheme
    information.
    *
    * @param ?string $scheme
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withScheme(?string $scheme) : self;
    /**
    * Return an instance with the specified user information.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified user information.
    *
    * Password is optional, but the user information MUST include the
    user; a null value for the user is equivalent to removing user
    information.
    *
    * @param ?string $user
    * @param ?string $password
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withUserInfo(?string $user, ?string $password = null) : self;
    /**
    * Return an instance with the specified host.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified host.
    *
    * A null value provided for the host is equivalent to removing the host
    information.
    *
    * @param ?string $host
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    * @throws IdnSupportMissing for component or transformations
    requiring IDN support when IDN support is not present
    or misconfigured.
    */
    public function withHost(?string $host) : self;
    /**
    * Return an instance with the specified port.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified port.
    *
    * A null value provided for the port is equivalent to removing the port
    information.
    *
    * @param ?int $port
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withPort(?int $port) : self;
    /**
    * Return an instance with the specified path.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified path.
    *
    * The path can either be empty or absolute (starting with a slash) or
    rootless (not starting with a slash). Implementations MUST support all
    three syntaxes.
    *
    * Users can provide both encoded and decoded path characters.
    Implementations ensure the correct encoding as outlined in getPath().
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withPath(string $path) : self;
    /**
    * Return an instance with the specified query string.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified query string.
    *
    * Users can provide both encoded and decoded query characters.
    Implementations ensure the correct encoding as outlined in getQuery().
    *
    * A null value provided for the query is equivalent to removing the query
    information.
    *
    * @param ?string $query
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withQuery(?string $query) : self;
    /**
    * Return an instance with the specified URI fragment.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified URI fragment.
    *
    * Users can provide both encoded and decoded fragment characters.
    Implementations ensure the correct encoding as outlined in getFragment().
    *
    * A null value provided for the fragment is equivalent to removing the fragment
    information.
    *
    * @param ?string $fragment
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withFragment(?string $fragment) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface UserInfoInterface extends UriComponentInterface
{
    /**
     * Returns the user component part.
     */
    public function getUser() : ?string;
    /**
     * Returns the pass component part.
     */
    public function getPass() : ?string;
    /**
    * Returns an instance with the specified user and/or pass.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified user.
    *
    * An empty user is equivalent to removing the user information.
    *
    * @param ?string $user
    * @param ?string $pass
    */
    public function withUserInfo(?string $user, ?string $pass = null) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use Throwable;
interface UriException extends Throwable
{
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
interface UriComponentInterface extends \JsonSerializable
{
    /**
    * Returns the instance content.
    *
    * If the instance is defined, the value returned MUST be encoded according to the
    selected encoding algorithm. In any case, the value MUST NOT double-encode any character
    depending on the selected encoding algorithm.
    *
    * To determine what characters to encode, please refer to RFC 3986, Sections 2 and 3.
    or RFC 3987 Section 3. By default the content is encoded according to RFC3986
    *
    * If the instance is not defined null is returned
    */
    public function getContent() : ?string;
    /**
    * Returns the instance string representation.
    *
    * If the instance is defined, the value returned MUST be percent-encoded,
    but MUST NOT double-encode any characters. To determine what characters
    to encode, please refer to RFC 3986, Sections 2 and 3.
    *
    * If the instance is not defined an empty string is returned
    */
    public function __toString() : string;
    /**
    * Returns the instance json representation.
    *
    * If the instance is defined, the value returned MUST be percent-encoded,
    but MUST NOT double-encode any characters. To determine what characters
    to encode, please refer to RFC 3986 or RFC 1738.
    *
    * If the instance is not defined null is returned
    */
    public function jsonSerialize() : ?string;
    /**
    * Returns the instance string representation with its optional URI delimiters.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode any
    characters. To determine what characters to encode, please refer to RFC 3986,
    Sections 2 and 3.
    *
    * If the instance is not defined an empty string is returned
    */
    public function getUriComponent() : string;
    /**
    * Returns an instance with the specified content.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified content.
    *
    * Users can provide both encoded and decoded content characters.
    *
    * A null value is equivalent to removing the component content.
    *
    *
    * @param ?string $content
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    * @throws IdnSupportMissing for component or transformations
    requiring IDN support when IDN support is not present
    or misconfigured.
    */
    public function withContent(?string $content) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface DataPathInterface extends PathInterface
{
    /**
     * Retrieve the data mime type associated to the URI.
     *
     * If no mimetype is present, this method MUST return the default mimetype 'text/plain'.
     *
     * @see http://tools.ietf.org/html/rfc2397#section-2
     */
    public function getMimeType() : string;
    /**
     * Retrieve the parameters associated with the Mime Type of the URI.
     *
     * If no parameters is present, this method MUST return the default parameter 'charset=US-ASCII'.
     *
     * @see http://tools.ietf.org/html/rfc2397#section-2
     */
    public function getParameters() : string;
    /**
     * Retrieve the mediatype associated with the URI.
     *
     * If no mediatype is present, this method MUST return the default parameter 'text/plain;charset=US-ASCII'.
     *
     * @see http://tools.ietf.org/html/rfc2397#section-3
     *
     * @return string The URI scheme.
     */
    public function getMediaType() : string;
    /**
    * Retrieves the data string.
    *
    * Retrieves the data part of the path. If no data part is provided return
    a empty string
    */
    public function getData() : string;
    /**
     * Tells whether the data is binary safe encoded.
     */
    public function isBinaryData() : bool;
    /**
     * Save the data to a specific file.
     */
    public function save(string $path, string $mode = 'w') : \SplFileObject;
    /**
    * Returns an instance where the data part is base64 encoded.
    *
    * This method MUST retain the state of the current instance, and return
    an instance where the data part is base64 encoded
    */
    public function toBinary() : self;
    /**
    * Returns an instance where the data part is url encoded following RFC3986 rules.
    *
    * This method MUST retain the state of the current instance, and return
    an instance where the data part is url encoded
    */
    public function toAscii() : self;
    /**
    * Return an instance with the specified mediatype parameters.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified mediatype parameters.
    *
    * Users must provide encoded characters.
    *
    * An empty parameters value is equivalent to removing the parameter.
    */
    public function withParameters(string $parameters) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\IdnSupportMissing;
use League\Uri\Exceptions\SyntaxError;
interface AuthorityInterface extends UriComponentInterface
{
    /**
     * Returns the host component of the authority.
     */
    public function getHost() : ?string;
    /**
     * Returns the port component of the authority.
     */
    public function getPort() : ?int;
    /**
     * Returns the user information component of the authority.
     */
    public function getUserInfo() : ?string;
    /**
    * Return an instance with the specified host.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified host.
    *
    * A null value provided for the host is equivalent to removing the host
    information.
    *
    * @param ?string $host
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    * @throws IdnSupportMissing for component or transformations
    requiring IDN support when IDN support is not present
    or misconfigured.
    */
    public function withHost(?string $host) : self;
    /**
    * Return an instance with the specified port.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified port.
    *
    * A null value provided for the port is equivalent to removing the port
    information.
    *
    * @param ?int $port
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withPort(?int $port) : self;
    /**
    * Return an instance with the specified user information.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified user information.
    *
    * Password is optional, but the user information MUST include the
    user; a null value for the user is equivalent to removing user
    information.
    *
    * @param ?string $user
    * @param ?string $password
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withUserInfo(?string $user, ?string $password = null) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface IpHostInterface extends HostInterface
{
    /**
     * Returns whether or not the host is an IPv4 address.
     */
    public function isIpv4() : bool;
    /**
     * Returns whether or not the host is an IPv6 address.
     */
    public function isIpv6() : bool;
    /**
     * Returns whether or not the host is an IPv6 address.
     */
    public function isIpFuture() : bool;
    /**
     * Returns whether or not the host has a ZoneIdentifier.
     *
     * @see http://tools.ietf.org/html/rfc6874#section-4
     */
    public function hasZoneIdentifier() : bool;
    /**
    * Returns an host without its zone identifier according to RFC6874.
    *
    * This method MUST retain the state of the current instance, and return
    an instance without the host zone identifier according to RFC6874
    *
    * @see http://tools.ietf.org/html/rfc6874#section-4
    */
    public function withoutZoneIdentifier() : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface HostInterface extends UriComponentInterface
{
    /**
     * Returns the ascii representation.
     */
    public function toAscii() : ?string;
    /**
     * Returns the unicode representation.
     */
    public function toUnicode() : ?string;
    /**
     * Returns the IP version.
     *
     * If the host is a not an IP this method will return null
     */
    public function getIpVersion() : ?string;
    /**
     * Returns the IP component If the Host is an IP address.
     *
     * If the host is a not an IP this method will return null
     */
    public function getIp() : ?string;
    /**
     * Tells whether the host is a domain name.
     */
    public function isDomain() : bool;
    /**
     * Tells whether the host is an IP Address.
     */
    public function isIp() : bool;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\SyntaxError;
/**
 * @extends \IteratorAggregate<string>
 */
interface SegmentedPathInterface extends \Countable, \IteratorAggregate, PathInterface
{
    /**
     * Returns the total number of segments in the path.
     */
    public function count() : int;
    /**
     * Iterate over the path segment.
     *
     * @return \Iterator<string>
     */
    public function getIterator() : \Iterator;
    /**
     * Returns parent directory's path.
     */
    public function getDirname() : string;
    /**
     * Returns the path basename.
     */
    public function getBasename() : string;
    /**
     * Returns the basename extension.
     */
    public function getExtension() : string;
    /**
     * Retrieves a single path segment.
     *
     * If the segment offset has not been set, returns null.
     */
    public function get(int $offset) : ?string;
    /**
    * Returns the associated key for a specific segment.
    *
    * If a value is specified only the keys associated with
    the given value will be returned
    *
    * @param ?string $segment
    *
    * @return int[]
    */
    public function keys(?string $segment = null) : array;
    /**
     * Appends a segment to the path.
     */
    public function append(string $segment) : self;
    /**
     * Prepends a segment to the path.
     */
    public function prepend(string $segment) : self;
    /**
    * Returns an instance with the modified segment.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the new segment
    *
    * If $key is non-negative, the added segment will be the segment at $key position from the start.
    If $key is negative, the added segment will be the segment at $key position from the end.
    *
    * @param ?string $segment
    *
    * @throws SyntaxError If the key is invalid
    */
    public function withSegment(int $key, ?string $segment) : self;
    /**
    * Returns an instance without the specified segment.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified component
    *
    * If $key is non-negative, the removed segment will be the segment at $key position from the start.
    If $key is negative, the removed segment will be the segment at $key position from the end.
    *
    * @param int ...$keys remaining keys to remove
    *
    * @throws SyntaxError If the key is invalid
    */
    public function withoutSegment(int ...$keys) : self;
    /**
    * Returns an instance without duplicate delimiters.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component normalized by removing
    multiple consecutive empty segment
    */
    public function withoutEmptySegments() : self;
    /**
    * Returns an instance with the specified parent directory's path.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the extension basename modified.
    *
    * @param ?string $path
    */
    public function withDirname(?string $path) : self;
    /**
    * Returns an instance with the specified basename.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the extension basename modified.
    *
    * @param ?string $basename
    */
    public function withBasename(?string $basename) : self;
    /**
    * Returns an instance with the specified basename extension.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the extension basename modified.
    *
    * @param ?string $extension
    */
    public function withExtension(?string $extension) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

/**
 * @extends \IteratorAggregate<array{0:string, 1:string|null}>
 */
interface QueryInterface extends \Countable, \IteratorAggregate, UriComponentInterface
{
    /**
     * Returns the query separator.
     */
    public function getSeparator() : string;
    /**
     * Returns the number of key/value pairs present in the object.
     */
    public function count() : int;
    /**
    * Returns an iterator allowing to go through all key/value pairs contained in this object.
    *
    * The pair is represented as an array where the first value is the pair key
    and the second value the pair value.
    *
    * The key of each pair is a string
    The value of each pair is a scalar or the null value
    *
    * @return \Iterator<int, array{0: string, 1: (string | null)}>
    */
    public function getIterator() : \Iterator;
    /**
    * Returns an iterator allowing to go through all key/value pairs contained in this object.
    *
    * The return type is as a Iterator where its offset is the pair key and its value the pair value.
    *
    * The key of each pair is a string
    The value of each pair is a scalar or the null value
    *
    * @return iterable<string, (string | null)>
    */
    public function pairs() : iterable;
    /**
     * Tells whether a pair with a specific name exists.
     *
     * @see https://url.spec.whatwg.org/#dom-urlsearchparams-has
     */
    public function has(string $key) : bool;
    /**
     * Returns the first value associated to the given pair name.
     *
     * If no value is found null is returned
     *
     * @see https://url.spec.whatwg.org/#dom-urlsearchparams-get
     */
    public function get(string $key) : ?string;
    /**
    * Returns all the values associated to the given pair name as an array or all
    the instance pairs.
    *
    * If no value is found an empty array is returned
    *
    * @see https://url.spec.whatwg.org/#dom-urlsearchparams-getall
    *
    * @return array<int, (string | null)>
    */
    public function getAll(string $key) : array;
    /**
    * Returns the store PHP variables as elements of an array.
    *
    * The result is similar as PHP parse_str when used with its
    second argument with the difference that variable names are
    not mangled.
    *
    * If a key is submitted it will returns the value attached to it or null
    *
    * @see http://php.net/parse_str
    * @see https://wiki.php.net/rfc/on_demand_name_mangling
    *
    * @param ?string $key
    * @return mixed the collection of stored PHP variables or the empty array if no input is given,
    the single value of a stored PHP variable or null if the variable is not present in the collection
    */
    public function params(?string $key = null);
    /**
     * Returns the RFC1738 encoded query.
     */
    public function toRFC1738() : ?string;
    /**
     * Returns the RFC3986 encoded query.
     *
     * @see ::getContent
     */
    public function toRFC3986() : ?string;
    /**
    * Returns an instance with a different separator.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the query component with a different separator
    */
    public function withSeparator(string $separator) : self;
    /**
    * Sorts the query string by offset, maintaining offset to data correlations.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * @see https://url.spec.whatwg.org/#dom-urlsearchparams-sort
    */
    public function sort() : self;
    /**
    * Returns an instance without duplicate key/value pair.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the query component normalized by removing
    duplicate pairs whose key/value are the same.
    */
    public function withoutDuplicates() : self;
    /**
    * Returns an instance without empty key/value where the value is the null value.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the query component normalized by removing
    empty pairs.
    *
    * A pair is considered empty if its value is equal to the null value
    */
    public function withoutEmptyPairs() : self;
    /**
    * Returns an instance where numeric indices associated to PHP's array like key are removed.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the query component normalized so that numeric indexes
    are removed from the pair key value.
    *
    * ie.: toto[3]=bar[3]&foo=bar becomes toto[]=bar[3]&foo=bar
    */
    public function withoutNumericIndices() : self;
    /**
    * Returns an instance with the a new key/value pair added to it.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * If the pair already exists the value will replace the existing value.
    *
    * @see https://url.spec.whatwg.org/#dom-urlsearchparams-set
    *
    * @param ?string $value
    */
    public function withPair(string $key, ?string $value) : self;
    /**
    * Returns an instance with the new pairs set to it.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * @see ::withPair
    */
    public function merge(string $query) : self;
    /**
    * Returns an instance without the specified keys.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified component
    *
    * @param string ...$keys
    */
    public function withoutPair(string ...$keys) : self;
    /**
    * Returns a new instance with a specified key/value pair appended as a new pair.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * @param ?string $value
    */
    public function appendTo(string $key, ?string $value) : self;
    /**
    * Returns an instance with the new pairs appended to it.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified query
    *
    * If the pair already exists the value will be added to it.
    */
    public function append(string $query) : self;
    /**
    * Returns an instance without the specified params.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the modified component without PHP's value.
    PHP's mangled is not taken into account.
    *
    * @param string ...$keys
    */
    public function withoutParam(string ...$keys) : self;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

interface FragmentInterface extends UriComponentInterface
{
    /**
     * Returns the decoded fragment.
     */
    public function decoded() : ?string;
}<?php

/**
 * League.Uri (https://uri.thephpleague.com)
 *
 * (c) Ignace Nyamagana Butera <nyamsprod@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
declare (strict_types=1);
namespace League\Uri\Contracts;

use League\Uri\Exceptions\SyntaxError;
interface PathInterface extends UriComponentInterface
{
    /**
     * Returns the decoded path.
     */
    public function decoded() : string;
    /**
     * Returns whether or not the path is absolute or relative.
     */
    public function isAbsolute() : bool;
    /**
     * Returns whether or not the path has a trailing delimiter.
     */
    public function hasTrailingSlash() : bool;
    /**
    * Returns an instance without dot segments.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component normalized by removing
    the dot segment.
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withoutDotSegments() : self;
    /**
    * Returns an instance with a leading slash.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component with a leading slash
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withLeadingSlash() : self;
    /**
    * Returns an instance without a leading slash.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component without a leading slash
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withoutLeadingSlash() : self;
    /**
    * Returns an instance with a trailing slash.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component with a trailing slash
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withTrailingSlash() : self;
    /**
    * Returns an instance without a trailing slash.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the path component without a trailing slash
    *
    * @throws SyntaxError for invalid component or transformations
    that would result in a object in invalid state.
    */
    public function withoutTrailingSlash() : self;
}{
    "name": "league/uri-interfaces",
    "description" : "Common interface for URI representation",
    "keywords": [
        "url",
        "uri",
        "rfc3986",
        "rfc3987"
    ],
    "license": "MIT",
    "homepage": "http://github.com/thephpleague/uri-interfaces",
    "authors": [
        {
            "name" : "Ignace Nyamagana Butera",
            "email" : "nyamsprod@gmail.com",
            "homepage" : "https://nyamsprod.com"
        }
    ],
    "funding": [
        {
            "type": "github",
            "url": "https://github.com/sponsors/nyamsprod"
        }
    ],
    "require": {
        "php" : "^7.2 || ^8.0",
        "ext-json": "*"
    },
    "require-dev": {
        "friendsofphp/php-cs-fixer": "^2.19",
        "phpstan/phpstan": "^0.12.90",
        "phpstan/phpstan-strict-rules": "^0.12.9",
        "phpstan/phpstan-phpunit": "^0.12.19",
        "phpunit/phpunit": "^8.5.15 || ^9.5"
    },
    "autoload": {
        "psr-4": {
            "League\\Uri\\": "src/"
        }
    },
    "scripts": {
        "phpunit": "phpunit --coverage-text",
        "phpcs": "php-cs-fixer fix --dry-run --diff -vvv --allow-risky=yes --ansi",
        "phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi",
        "phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi --memory-limit 192M",
        "test": [
            "@phpunit",
            "@phpstan",
            "@phpcs:fix"
        ]
    },
    "scripts-descriptions": {
        "phpunit": "Runs package test suite",
        "phpstan": "Runs complete codebase static analysis",
        "phpcs": "Runs coding style testing",
        "phpcs:fix": "Fix coding style issues",
        "test": "Runs all tests"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.x-dev"
        }
    },
    "suggest": {
        "ext-intl": "to use the IDNA feature",
        "symfony/intl": "to use the IDNA feature via Symfony Polyfill"
    }
}
<?php

$dist = dirname(__DIR__) . '/dist';
if (!is_dir($dist)) {
    mkdir($dist, 0755);
}
if (file_exists($dist . '/random_compat.phar')) {
    unlink($dist . '/random_compat.phar');
}
$phar = new Phar($dist . '/random_compat.phar', FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME, 'random_compat.phar');
rename(dirname(__DIR__) . '/lib/random.php', dirname(__DIR__) . '/lib/index.php');
$phar->buildFromDirectory(dirname(__DIR__) . '/lib');
rename(dirname(__DIR__) . '/lib/index.php', dirname(__DIR__) . '/lib/random.php');
/**
 * If we pass an (optional) path to a private key as a second argument, we will
 * sign the Phar with OpenSSL.
 * 
 * If you leave this out, it will produce an unsigned .phar!
 */
if ($argc > 1) {
    if (!@is_readable($argv[1])) {
        echo 'Could not read the private key file:', $argv[1], "\n";
        exit(255);
    }
    $pkeyFile = file_get_contents($argv[1]);
    $private = openssl_get_privatekey($pkeyFile);
    if ($private !== false) {
        $pkey = '';
        openssl_pkey_export($private, $pkey);
        $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
        /**
         * Save the corresponding public key to the file
         */
        if (!@is_readable($dist . '/random_compat.phar.pubkey')) {
            $details = openssl_pkey_get_details($private);
            file_put_contents($dist . '/random_compat.phar.pubkey', $details['key']);
        }
    } else {
        echo 'An error occurred reading the private key from OpenSSL.', "\n";
        exit(255);
    }
}<?php

require_once 'lib/byte_safe_strings.php';
require_once 'lib/cast_to_int.php';
require_once 'lib/error_polyfill.php';
require_once 'other/ide_stubs/libsodium.php';
require_once 'lib/random.php';
$int = random_int(0, 65536);{
  "name":         "paragonie/random_compat",
  "description":  "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
  "keywords": [
    "csprng",
    "random",
    "polyfill",
    "pseudorandom"
  ],
  "license":      "MIT",
  "type":         "library",
  "authors": [
    {
      "name":     "Paragon Initiative Enterprises",
      "email":    "security@paragonie.com",
      "homepage": "https://paragonie.com"
    }
  ],
  "support": {
    "issues":     "https://github.com/paragonie/random_compat/issues",
    "email":      "info@paragonie.com",
    "source":     "https://github.com/paragonie/random_compat"
  },
  "require": {
    "php": ">= 7"
  },
  "require-dev": {
    "vimeo/psalm": "^1",
    "phpunit/phpunit": "4.*|5.*"
  },
  "suggest": {
    "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
  }
}
<?php

/**
 * Random_* Compatibility Library
 * for using the new PHP 7 random_* API in PHP 5 projects
 *
 * @version 2.99.99
 * @released 2018-06-06
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
// NOP<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base32
 * [A-Z][2-7]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base32 implements EncoderInterface
{
    /**
     * Decode a Base32-encoded string into raw binary
     *
     * @param string $encodedString
     * @param bool $strictPadding
     * @return string
     */
    public static function decode(string $encodedString, bool $strictPadding = false) : string
    {
        return static::doDecode($encodedString, false, $strictPadding);
    }
    /**
     * Decode an uppercase Base32-encoded string into raw binary
     *
     * @param string $src
     * @param bool $strictPadding
     * @return string
     */
    public static function decodeUpper(string $src, bool $strictPadding = false) : string
    {
        return static::doDecode($src, true, $strictPadding);
    }
    /**
     * Encode into Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encode(string $src) : string
    {
        return static::doEncode($src, false, true);
    }
    /**
     * Encode into Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encodeUnpadded(string $src) : string
    {
        return static::doEncode($src, false, false);
    }
    /**
     * Encode into uppercase Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encodeUpper(string $src) : string
    {
        return static::doEncode($src, true, true);
    }
    /**
     * Encode into uppercase Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encodeUpperUnpadded(string $src) : string
    {
        return static::doEncode($src, true, false);
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 5-bit integers
    into 8-bit integers.
    *
    * @param int $src
    * @return int
    */
    protected static function decode5Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 96 && $src < 123) $ret += $src - 97 + 1; // -64
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 96;
        // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
        $ret += (0x31 - $src & $src - 0x38) >> 8 & $src - 23;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 5-bit integers
    into 8-bit integers.
    *
    * Uppercase variant.
    *
    * @param int $src
    * @return int
    */
    protected static function decode5BitsUpper(int $src) : int
    {
        $ret = -1;
        // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
        $ret += (0x31 - $src & $src - 0x38) >> 8 & $src - 23;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 5-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode5Bits(int $src) : string
    {
        $diff = 0x61;
        // if ($src > 25) $ret -= 72;
        $diff -= 25 - $src >> 8 & 73;
        return \pack('C', $src + $diff);
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 5-bit integers.
    *
    * Uppercase variant.
    *
    * @param int $src
    * @return string
    */
    protected static function encode5BitsUpper(int $src) : string
    {
        $diff = 0x41;
        // if ($src > 25) $ret -= 40;
        $diff -= 25 - $src >> 8 & 41;
        return \pack('C', $src + $diff);
    }
    /**
     * Base32 decoding
     *
     * @param string $src
     * @param bool $upper
     * @param bool $strictPadding
     * @return string
     * @throws \TypeError
     * @psalm-suppress RedundantCondition
     */
    protected static function doDecode(string $src, bool $upper = false, bool $strictPadding = false) : string
    {
        // We do this to reduce code duplication:
        $method = $upper ? 'decode5BitsUpper' : 'decode5Bits';
        // Remove padding
        $srcLen = Binary::safeStrlen($src);
        if ($srcLen === 0) {
            return '';
        }
        if ($strictPadding) {
            if (($srcLen & 7) === 0) {
                for ($j = 0; $j < 7; ++$j) {
                    if ($src[$srcLen - 1] === '=') {
                        $srcLen--;
                    } else {
                        break;
                    }
                }
            }
            if (($srcLen & 7) === 1) {
                throw new \RangeException('Incorrect padding');
            }
        } else {
            $src = \rtrim($src, '=');
            $srcLen = Binary::safeStrlen($src);
        }
        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 8 <= $srcLen; $i += 8) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 8));
            /** @var int $c0 */
            $c0 = static::$method($chunk[1]);
            /** @var int $c1 */
            $c1 = static::$method($chunk[2]);
            /** @var int $c2 */
            $c2 = static::$method($chunk[3]);
            /** @var int $c3 */
            $c3 = static::$method($chunk[4]);
            /** @var int $c4 */
            $c4 = static::$method($chunk[5]);
            /** @var int $c5 */
            $c5 = static::$method($chunk[6]);
            /** @var int $c6 */
            $c6 = static::$method($chunk[7]);
            /** @var int $c7 */
            $c7 = static::$method($chunk[8]);
            $dest .= \pack('CCCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2 | $c6 >> 3) & 0xff, ($c6 << 5 | $c7) & 0xff);
            $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
            /** @var int $c0 */
            $c0 = static::$method($chunk[1]);
            if ($i + 6 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                /** @var int $c5 */
                $c5 = static::$method($chunk[6]);
                /** @var int $c6 */
                $c6 = static::$method($chunk[7]);
                $dest .= \pack('CCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2 | $c6 >> 3) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
            } elseif ($i + 5 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                /** @var int $c5 */
                $c5 = static::$method($chunk[6]);
                $dest .= \pack('CCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8;
            } elseif ($i + 4 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                $dest .= \pack('CCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
            } elseif ($i + 3 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                $dest .= \pack('CC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
            } elseif ($i + 2 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                $dest .= \pack('CC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1) & 0xff);
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                $dest .= \pack('C', ($c0 << 3 | $c1 >> 2) & 0xff);
                $err |= ($c0 | $c1) >> 8;
            } else {
                $dest .= \pack('C', $c0 << 3 & 0xff);
                $err |= $c0 >> 8;
            }
        }
        /** @var bool $check */
        $check = $err === 0;
        if (!$check) {
            throw new \RangeException('Base32::doDecode() only expects characters in the correct base32 alphabet');
        }
        return $dest;
    }
    /**
     * Base32 Encoding
     *
     * @param string $src
     * @param bool $upper
     * @param bool $pad
     * @return string
     * @throws \TypeError
     */
    protected static function doEncode(string $src, bool $upper = false, $pad = true) : string
    {
        // We do this to reduce code duplication:
        $method = $upper ? 'encode5BitsUpper' : 'encode5Bits';
        $dest = '';
        $srcLen = Binary::safeStrlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 5 <= $srcLen; $i += 5) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 5));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];
            $b3 = $chunk[4];
            $b4 = $chunk[5];
            $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method(($b2 << 1 | $b3 >> 7) & 31) . static::$method($b3 >> 2 & 31) . static::$method(($b3 << 3 | $b4 >> 5) & 31) . static::$method($b4 & 31);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 3 < $srcLen) {
                $b1 = $chunk[2];
                $b2 = $chunk[3];
                $b3 = $chunk[4];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method(($b2 << 1 | $b3 >> 7) & 31) . static::$method($b3 >> 2 & 31) . static::$method($b3 << 3 & 31);
                if ($pad) {
                    $dest .= '=';
                }
            } elseif ($i + 2 < $srcLen) {
                $b1 = $chunk[2];
                $b2 = $chunk[3];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method($b2 << 1 & 31);
                if ($pad) {
                    $dest .= '===';
                }
            } elseif ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method($b1 << 4 & 31);
                if ($pad) {
                    $dest .= '====';
                }
            } else {
                $dest .= static::$method($b0 >> 3 & 31) . static::$method($b0 << 2 & 31);
                if ($pad) {
                    $dest .= '======';
                }
            }
        }
        return $dest;
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Hex
 * @package ParagonIE\ConstantTime
 */
abstract class Hex implements EncoderInterface
{
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $binString (raw binary)
    * @return string
    * @throws \TypeError
    */
    public static function encode(string $binString) : string
    {
        /** @var string $hex */
        $hex = '';
        $len = Binary::safeStrlen($binString);
        for ($i = 0; $i < $len; ++$i) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C', Binary::safeSubstr($binString, $i, 1));
            /** @var int $c */
            $c = $chunk[1] & 0xf;
            /** @var int $b */
            $b = $chunk[1] >> 4;
            $hex .= pack('CC', 87 + $b + ($b - 10 >> 8 & ~38), 87 + $c + ($c - 10 >> 8 & ~38));
        }
        return $hex;
    }
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks, returning uppercase letters (as per RFC 4648)
    *
    * @param string $binString (raw binary)
    * @return string
    * @throws \TypeError
    */
    public static function encodeUpper(string $binString) : string
    {
        /** @var string $hex */
        $hex = '';
        /** @var int $len */
        $len = Binary::safeStrlen($binString);
        for ($i = 0; $i < $len; ++$i) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C', Binary::safeSubstr($binString, $i, 2));
            /** @var int $c */
            $c = $chunk[1] & 0xf;
            /** @var int $b */
            $b = $chunk[1] >> 4;
            $hex .= pack('CC', 55 + $b + ($b - 10 >> 8 & ~6), 55 + $c + ($c - 10 >> 8 & ~6));
        }
        return $hex;
    }
    /**
    * Convert a hexadecimal string into a binary string without cache-timing
    leaks
    *
    * @param string $encodedString
    * @param bool $strictPadding
    * @return string (raw binary)
    * @throws \RangeException
    */
    public static function decode(string $encodedString, bool $strictPadding = false) : string
    {
        /** @var int $hex_pos */
        $hex_pos = 0;
        /** @var string $bin */
        $bin = '';
        /** @var int $c_acc */
        $c_acc = 0;
        /** @var int $hex_len */
        $hex_len = Binary::safeStrlen($encodedString);
        /** @var int $state */
        $state = 0;
        if (($hex_len & 1) !== 0) {
            if ($strictPadding) {
                throw new \RangeException('Expected an even number of hexadecimal characters');
            } else {
                $encodedString = '0' . $encodedString;
                ++$hex_len;
            }
        }
        /** @var array<int, int> $chunk */
        $chunk = \unpack('C*', $encodedString);
        while ($hex_pos < $hex_len) {
            ++$hex_pos;
            /** @var int $c */
            $c = $chunk[$hex_pos];
            /** @var int $c_num */
            $c_num = $c ^ 48;
            /** @var int $c_num0 */
            $c_num0 = $c_num - 10 >> 8;
            /** @var int $c_alpha */
            $c_alpha = ($c & ~32) - 55;
            /** @var int $c_alpha0 */
            $c_alpha0 = ($c_alpha - 10 ^ $c_alpha - 16) >> 8;
            if (($c_num0 | $c_alpha0) === 0) {
                throw new \RangeException('Expected hexadecimal character');
            }
            /** @var int $c_val */
            $c_val = $c_num0 & $c_num | $c_alpha & $c_alpha0;
            if ($state === 0) {
                $c_acc = $c_val * 16;
            } else {
                $bin .= \pack('C', $c_acc | $c_val);
            }
            $state ^= 1;
        }
        return $bin;
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64DotSlash
 * ./[A-Z][a-z][0-9]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64DotSlash extends Base64
{
    /**
    * Uses bitwise operators instead of table-lookups to turn 6-bit integers
    into 8-bit integers.
    *
    * Base64 character set:
    ./         [A-Z]      [a-z]     [0-9]
    0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39
    *
    * @param int $src
    * @return int
    */
    protected static function decode6Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45
        $ret += (0x2d - $src & $src - 0x30) >> 8 & $src - 45;
        // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 62;
        // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 68;
        // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 7;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 6-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode6Bits(int $src) : string
    {
        $src += 0x2e;
        // if ($src > 0x2f) $src += 0x41 - 0x30; // 17
        $src += 0x2f - $src >> 8 & 17;
        // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
        $src += 0x5a - $src >> 8 & 6;
        // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75
        $src -= 0x7a - $src >> 8 & 75;
        return \pack('C', $src);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Encoding
 * @package ParagonIE\ConstantTime
 */
abstract class Encoding
{
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32Encode(string $str) : string
    {
        return Base32::encode($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32EncodeUpper(string $str) : string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32 decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32Decode(string $str) : string
    {
        return Base32::decode($str);
    }
    /**
     * RFC 4648 Base32 decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32DecodeUpper(string $str) : string
    {
        return Base32::decodeUpper($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexEncode(string $str) : string
    {
        return Base32Hex::encode($str);
    }
    /**
     * RFC 4648 Base32Hex encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexEncodeUpper(string $str) : string
    {
        return Base32Hex::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32Hex decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexDecode(string $str) : string
    {
        return Base32Hex::decode($str);
    }
    /**
     * RFC 4648 Base32Hex decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexDecodeUpper(string $str) : string
    {
        return Base32Hex::decodeUpper($str);
    }
    /**
     * RFC 4648 Base64 encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64Encode(string $str) : string
    {
        return Base64::encode($str);
    }
    /**
     * RFC 4648 Base64 decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64Decode(string $str) : string
    {
        return Base64::decode($str);
    }
    /**
     * Encode into Base64
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64EncodeDotSlash(string $str) : string
    {
        return Base64DotSlash::encode($str);
    }
    /**
     * Decode from base64 to raw binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $str
     * @return string
     * @throws \RangeException
     * @throws \TypeError
     */
    public static function base64DecodeDotSlash(string $str) : string
    {
        return Base64DotSlash::decode($str);
    }
    /**
     * Encode into Base64
     *
     * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64EncodeDotSlashOrdered(string $str) : string
    {
        return Base64DotSlashOrdered::encode($str);
    }
    /**
     * Decode from base64 to raw binary
     *
     * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
     *
     * @param string $str
     * @return string
     * @throws \RangeException
     * @throws \TypeError
     */
    public static function base64DecodeDotSlashOrdered(string $str) : string
    {
        return Base64DotSlashOrdered::decode($str);
    }
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $bin_string (raw binary)
    * @return string
    * @throws \TypeError
    */
    public static function hexEncode(string $bin_string) : string
    {
        return Hex::encode($bin_string);
    }
    /**
    * Convert a hexadecimal string into a binary string without cache-timing
    leaks
    *
    * @param string $hex_string
    * @return string (raw binary)
    * @throws \RangeException
    */
    public static function hexDecode(string $hex_string) : string
    {
        return Hex::decode($hex_string);
    }
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $bin_string (raw binary)
    * @return string
    * @throws \TypeError
    */
    public static function hexEncodeUpper(string $bin_string) : string
    {
        return Hex::encodeUpper($bin_string);
    }
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $bin_string (raw binary)
    * @return string
    */
    public static function hexDecodeUpper(string $bin_string) : string
    {
        return Hex::decode($bin_string);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base32Hex
 * [0-9][A-V]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base32Hex extends Base32
{
    /**
    * Uses bitwise operators instead of table-lookups to turn 5-bit integers
    into 8-bit integers.
    *
    * @param int $src
    * @return int
    */
    protected static function decode5Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src - 47;
        // if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86
        $ret += (0x60 - $src & $src - 0x77) >> 8 & $src - 86;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 5-bit integers
    into 8-bit integers.
    *
    * @param int $src
    * @return int
    */
    protected static function decode5BitsUpper(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src - 47;
        // if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54
        $ret += (0x40 - $src & $src - 0x57) >> 8 & $src - 54;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 5-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode5Bits(int $src) : string
    {
        $src += 0x30;
        // if ($src > 0x39) $src += 0x61 - 0x3a; // 39
        $src += 0x39 - $src >> 8 & 39;
        return \pack('C', $src);
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 5-bit integers.
    *
    * Uppercase variant.
    *
    * @param int $src
    * @return string
    */
    protected static function encode5BitsUpper(int $src) : string
    {
        $src += 0x30;
        // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
        $src += 0x39 - $src >> 8 & 7;
        return \pack('C', $src);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64UrlSafe
 * [A-Z][a-z][0-9]\-_
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64UrlSafe extends Base64
{
    /**
    * Uses bitwise operators instead of table-lookups to turn 6-bit integers
    into 8-bit integers.
    *
    * Base64 character set:
    [A-Z]      [a-z]      [0-9]      -     _
    0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2d, 0x5f
    *
    * @param int $src
    * @return int
    */
    protected static function decode6Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 70;
        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 5;
        // if ($src == 0x2c) $ret += 62 + 1;
        $ret += (0x2c - $src & $src - 0x2e) >> 8 & 63;
        // if ($src == 0x5f) ret += 63 + 1;
        $ret += (0x5e - $src & $src - 0x60) >> 8 & 64;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 6-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode6Bits(int $src) : string
    {
        $diff = 0x41;
        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += 25 - $src >> 8 & 6;
        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= 51 - $src >> 8 & 75;
        // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
        $diff -= 61 - $src >> 8 & 13;
        // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
        $diff += 62 - $src >> 8 & 49;
        return \pack('C', $src + $diff);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Interface EncoderInterface
 * @package ParagonIE\ConstantTime
 */
interface EncoderInterface
{
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $binString (raw binary)
    * @return string
    */
    public static function encode(string $binString) : string;
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $encodedString
    * @param bool $strictPadding Error on invalid padding
    * @return string (raw binary)
    */
    public static function decode(string $encodedString, bool $strictPadding = false) : string;
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64
 * [A-Z][a-z][0-9]+/
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64 implements EncoderInterface
{
    /**
     * Encode into Base64
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encode(string $src) : string
    {
        return static::doEncode($src, true);
    }
    /**
     * Encode into Base64, no = padding
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encodeUnpadded(string $src) : string
    {
        return static::doEncode($src, false);
    }
    /**
     * @param string $src
     * @param bool $pad Include = padding?
     * @return string
     * @throws \TypeError
     */
    protected static function doEncode(string $src, bool $pad = true) : string
    {
        $dest = '';
        $srcLen = Binary::safeStrlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 3));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];
            $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits(($b0 << 4 | $b1 >> 4) & 63) . static::encode6Bits(($b1 << 2 | $b2 >> 6) & 63) . static::encode6Bits($b2 & 63);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits(($b0 << 4 | $b1 >> 4) & 63) . static::encode6Bits($b1 << 2 & 63);
                if ($pad) {
                    $dest .= '=';
                }
            } else {
                $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits($b0 << 4 & 63);
                if ($pad) {
                    $dest .= '==';
                }
            }
        }
        return $dest;
    }
    /**
     * decode from base64 into binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $encodedString
     * @param bool $strictPadding
     * @return string
     * @throws \RangeException
     * @throws \TypeError
     * @psalm-suppress RedundantCondition
     */
    public static function decode(string $encodedString, bool $strictPadding = false) : string
    {
        // Remove padding
        $srcLen = Binary::safeStrlen($encodedString);
        if ($srcLen === 0) {
            return '';
        }
        if ($strictPadding) {
            if (($srcLen & 3) === 0) {
                if ($encodedString[$srcLen - 1] === '=') {
                    $srcLen--;
                    if ($encodedString[$srcLen - 1] === '=') {
                        $srcLen--;
                    }
                }
            }
            if (($srcLen & 3) === 1) {
                throw new \RangeException('Incorrect padding');
            }
            if ($encodedString[$srcLen - 1] === '=') {
                throw new \RangeException('Incorrect padding');
            }
        } else {
            $encodedString = \rtrim($encodedString, '=');
            $srcLen = Binary::safeStrlen($encodedString);
        }
        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, 4));
            $c0 = static::decode6Bits($chunk[1]);
            $c1 = static::decode6Bits($chunk[2]);
            $c2 = static::decode6Bits($chunk[3]);
            $c3 = static::decode6Bits($chunk[4]);
            $dest .= \pack('CCC', ($c0 << 2 | $c1 >> 4) & 0xff, ($c1 << 4 | $c2 >> 2) & 0xff, ($c2 << 6 | $c3) & 0xff);
            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, $srcLen - $i));
            $c0 = static::decode6Bits($chunk[1]);
            if ($i + 2 < $srcLen) {
                $c1 = static::decode6Bits($chunk[2]);
                $c2 = static::decode6Bits($chunk[3]);
                $dest .= \pack('CC', ($c0 << 2 | $c1 >> 4) & 0xff, ($c1 << 4 | $c2 >> 2) & 0xff);
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                $c1 = static::decode6Bits($chunk[2]);
                $dest .= \pack('C', ($c0 << 2 | $c1 >> 4) & 0xff);
                $err |= ($c0 | $c1) >> 8;
            } elseif ($i < $srcLen && $strictPadding) {
                $err |= 1;
            }
        }
        /** @var bool $check */
        $check = $err === 0;
        if (!$check) {
            throw new \RangeException('Base64::decode() only expects characters in the correct base64 alphabet');
        }
        return $dest;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 6-bit integers
    into 8-bit integers.
    *
    * Base64 character set:
    [A-Z]      [a-z]      [0-9]      +     /
    0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
    *
    * @param int $src
    * @return int
    */
    protected static function decode6Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 70;
        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 5;
        // if ($src == 0x2b) $ret += 62 + 1;
        $ret += (0x2a - $src & $src - 0x2c) >> 8 & 63;
        // if ($src == 0x2f) ret += 63 + 1;
        $ret += (0x2e - $src & $src - 0x30) >> 8 & 64;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 6-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode6Bits(int $src) : string
    {
        $diff = 0x41;
        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += 25 - $src >> 8 & 6;
        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= 51 - $src >> 8 & 75;
        // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
        $diff -= 61 - $src >> 8 & 15;
        // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
        $diff += 62 - $src >> 8 & 3;
        return \pack('C', $src + $diff);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64DotSlashOrdered
 * ./[0-9][A-Z][a-z]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64DotSlashOrdered extends Base64
{
    /**
    * Uses bitwise operators instead of table-lookups to turn 6-bit integers
    into 8-bit integers.
    *
    * Base64 character set:
    [.-9]      [A-Z]      [a-z]
    0x2e-0x39, 0x41-0x5a, 0x61-0x7a
    *
    * @param int $src
    * @return int
    */
    protected static function decode6Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45
        $ret += (0x2d - $src & $src - 0x3a) >> 8 & $src - 45;
        // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 52;
        // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 58;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 6-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode6Bits(int $src) : string
    {
        $src += 0x2e;
        // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
        $src += 0x39 - $src >> 8 & 7;
        // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
        $src += 0x5a - $src >> 8 & 6;
        return \pack('C', $src);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class RFC4648
 *
 * This class conforms strictly to the RFC
 *
 * @package ParagonIE\ConstantTime
 */
abstract class RFC4648
{
    /**
     * RFC 4648 Base64 encoding
     *
     * "foo" -> "Zm9v"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64Encode(string $str) : string
    {
        return Base64::encode($str);
    }
    /**
     * RFC 4648 Base64 decoding
     *
     * "Zm9v" -> "foo"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64Decode(string $str) : string
    {
        return Base64::decode($str, true);
    }
    /**
     * RFC 4648 Base64 (URL Safe) encoding
     *
     * "foo" -> "Zm9v"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64UrlSafeEncode(string $str) : string
    {
        return Base64UrlSafe::encode($str);
    }
    /**
     * RFC 4648 Base64 (URL Safe) decoding
     *
     * "Zm9v" -> "foo"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64UrlSafeDecode(string $str) : string
    {
        return Base64UrlSafe::decode($str, true);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * "foo" -> "MZXW6==="
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32Encode(string $str) : string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * "MZXW6===" -> "foo"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32Decode(string $str) : string
    {
        return Base32::decodeUpper($str, true);
    }
    /**
     * RFC 4648 Base32-Hex encoding
     *
     * "foo" -> "CPNMU==="
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexEncode(string $str) : string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32-Hex decoding
     *
     * "CPNMU===" -> "foo"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexDecode(string $str) : string
    {
        return Base32::decodeUpper($str, true);
    }
    /**
     * RFC 4648 Base16 decoding
     *
     * "foo" -> "666F6F"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base16Encode(string $str) : string
    {
        return Hex::encodeUpper($str);
    }
    /**
     * RFC 4648 Base16 decoding
     *
     * "666F6F" -> "foo"
     *
     * @param string $str
     * @return string
     */
    public static function base16Decode(string $str) : string
    {
        return Hex::decode($str, true);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Binary
 *
 * Binary string operators that don't choke on
 * mbstring.func_overload
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Binary
{
    /**
     * Safe string length
     *
     * @ref mbstring.func_overload
     *
     * @param string $str
     * @return int
     */
    public static function safeStrlen(string $str) : int
    {
        if (\function_exists('mb_strlen')) {
            return (int) \mb_strlen($str, '8bit');
        } else {
            return \strlen($str);
        }
    }
    /**
     * Safe substring
     *
     * @ref mbstring.func_overload
     *
     * @staticvar boolean $exists
     * @param string $str
     * @param int $start
     * @param int $length
     * @return string
     * @throws \TypeError
     */
    public static function safeSubstr(string $str, int $start = 0, $length = null) : string
    {
        if ($length === 0) {
            return '';
        }
        if (\function_exists('mb_substr')) {
            return \mb_substr($str, $start, $length, '8bit');
        }
        // Unlike mb_substr(), substr() doesn't accept NULL for length
        if ($length !== null) {
            return \Phabel\Target\Php80\Polyfill::substr($str, $start, $length);
        } else {
            return \Phabel\Target\Php80\Polyfill::substr($str, $start);
        }
    }
}{
  "name": "paragonie/constant_time_encoding",
  "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
  "keywords": [
    "base64",
    "encoding",
    "rfc4648",
    "base32",
    "base16",
    "hex",
    "bin2hex",
    "hex2bin",
    "base64_encode",
    "base64_decode",
    "base32_encode",
    "base32_decode"
  ],
  "license": "MIT",
  "type": "library",
  "authors": [
      {
        "name":     "Paragon Initiative Enterprises",
        "email":    "security@paragonie.com",
        "homepage": "https://paragonie.com",
        "role":     "Maintainer"
      },
      {
        "name":     "Steve 'Sc00bz' Thomas",
        "email":    "steve@tobtu.com",
        "homepage": "https://www.tobtu.com",
        "role":     "Original Developer"
      }
  ],
  "support": {
    "issues":   "https://github.com/paragonie/constant_time_encoding/issues",
    "email":    "info@paragonie.com",
    "source":   "https://github.com/paragonie/constant_time_encoding"
  },
  "require": {
    "php": "^7|^8"
  },
  "require-dev": {
    "phpunit/phpunit": "^6|^7|^8|^9",
    "vimeo/psalm": "^1|^2|^3|^4"
  },
  "autoload": {
    "psr-4": {
      "ParagonIE\\ConstantTime\\": "src/"
    }
  }
}
{
    "name": "kelunik/certificate",
    "description": "Access certificate details and transform between different formats.",
    "type": "library",
    "minimum-stability": "dev",
    "prefer-stable": true,
    "license": "MIT",
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "keywords": [
        "certificate",
        "certificates",
        "openssl",
        "x509",
        "pem",
        "der"
    ],
    "support": {
        "issues": "https://github.com/kelunik/certificate/issues"
    },
    "require": {
        "php": ">=5.4",
        "ext-openssl": "*"
    },
    "require-dev": {
        "phpunit/phpunit": "^4.8",
        "fabpot/php-cs-fixer": "^1.9"
    },
    "autoload": {
        "psr-4": {
            "Kelunik\\Certificate\\": "lib"
        }
    }
}
<?php

namespace Kelunik\Certificate;

class Profile
{
    private $commonName;
    private $organizationName;
    private $country;
    /**
     *
     */
    public function __construct($commonName, $organizationName, $country)
    {
        $this->commonName = $commonName;
        $this->organizationName = $organizationName;
        $this->country = $country;
    }
    /**
     *
     */
    public function getCommonName()
    {
        return $this->commonName;
    }
    /**
     *
     */
    public function getOrganizationName()
    {
        return $this->organizationName;
    }
    /**
     *
     */
    public function getCountry()
    {
        return $this->country;
    }
}<?php

namespace Kelunik\Certificate;

class InvalidCertificateException extends \Exception
{
}<?php

namespace Kelunik\Certificate;

class Certificate
{
    private $pem;
    private $info;
    private $issuer;
    private $subject;
    /**
     *
     */
    public function __construct($pem)
    {
        if (is_string($pem)) {
            if (!($cert = @openssl_x509_read($pem))) {
                throw new InvalidCertificateException("Invalid PEM encoded certificate!");
            }
        } else {
            if (\is_resource($pem)) {
                if (\get_resource_type($pem) !== "OpenSSL X.509") {
                    throw new InvalidCertificateException("Invalid resource of type other than 'OpenSSL X.509'!");
                }
                $cert = $pem;
            } else {
                throw new \InvalidArgumentException("Invalid variable type, expected string|resource, got " . gettype($pem));
            }
        }
        if (\openssl_x509_export($pem, $this->pem) === false) {
            throw new InvalidCertificateException("Could not convert 'OpenSSL X.509' resource to PEM!");
        }
        if (!($this->info = openssl_x509_parse($cert))) {
            throw new InvalidCertificateException("Invalid PEM encoded certificate!");
        }
    }
    /**
     *
     */
    public function getNames()
    {
        $san = isset($this->info["extensions"]["subjectAltName"]) ? $this->info["extensions"]["subjectAltName"] : "";
        $names = [];
        $parts = array_map("trim", explode(",", $san));
        foreach ($parts as $part) {
            if (stripos($part, "dns:") === 0) {
                $names[] = \Phabel\Target\Php80\Polyfill::substr($part, 4);
            }
        }
        $names = array_map("strtolower", $names);
        $names = array_unique($names);
        sort($names);
        return $names;
    }
    /**
     *
     */
    public function getSubject()
    {
        if ($this->subject === null) {
            $this->subject = new Profile(isset($this->info["subject"]["CN"]) ? $this->info["subject"]["CN"] : null, isset($this->info["subject"]["O"]) ? $this->info["subject"]["O"] : null, isset($this->info["subject"]["C"]) ? $this->info["subject"]["C"] : null);
        }
        return $this->subject;
    }
    /**
     *
     */
    public function getIssuer()
    {
        if ($this->issuer === null) {
            $this->issuer = new Profile(isset($this->info["issuer"]["CN"]) ? $this->info["issuer"]["CN"] : null, isset($this->info["issuer"]["O"]) ? $this->info["issuer"]["O"] : null, isset($this->info["issuer"]["C"]) ? $this->info["issuer"]["C"] : null);
        }
        return $this->issuer;
    }
    /**
     *
     */
    public function getSerialNumber()
    {
        return $this->info["serialNumber"];
    }
    /**
     *
     */
    public function getValidFrom()
    {
        return $this->info["validFrom_time_t"];
    }
    /**
     *
     */
    public function getValidTo()
    {
        return $this->info["validTo_time_t"];
    }
    /**
     *
     */
    public function getSignatureType()
    {
        // https://3v4l.org/Iu3T2
        if (!isset($this->info["signatureTypeSN"])) {
            throw new FieldNotSupportedException("Signature type is not supported in this version of PHP. Please update your version to a higher bugfix version. See: https://3v4l.org/Iu3T2");
        }
        return $this->info["signatureTypeSN"];
    }
    /**
     *
     */
    public function isSelfSigned()
    {
        return $this->info["subject"] === $this->info["issuer"];
    }
    /**
     *
     */
    public function toPem()
    {
        return $this->pem;
    }
    /**
     *
     */
    public function toDer()
    {
        return self::pemToDer($this->pem);
    }
    /**
     *
     */
    public function __toString()
    {
        return $this->pem;
    }
    /**
     *
     */
    public function __debugInfo()
    {
        return ["commonName" => $this->getSubject()->getCommonName(), "names" => $this->getNames(), "issuedBy" => $this->getIssuer()->getCommonName(), "validFrom" => \Phabel\Target\Php80\Polyfill::date("d.m.Y", $this->getValidFrom()), "validTo" => \Phabel\Target\Php80\Polyfill::date("d.m.Y", $this->getValidTo())];
    }
    /**
     *
     */
    public static function derToPem($der)
    {
        if (!is_string($der)) {
            throw new \InvalidArgumentException("\$der must be a string, " . gettype($der) . " given.");
        }
        return sprintf("-----BEGIN CERTIFICATE-----\n%s-----END CERTIFICATE-----\n", chunk_split(base64_encode($der), 64, "\n"));
    }
    /**
     *
     */
    public static function pemToDer($pem)
    {
        if (!is_string($pem)) {
            throw new \InvalidArgumentException("\$pem must be a string, " . gettype($pem) . " given.");
        }
        $pattern = "@-----BEGIN CERTIFICATE-----\n([a-zA-Z0-9+/=\n]+)-----END CERTIFICATE-----@";
        if (!preg_match($pattern, $pem, $match)) {
            throw new InvalidCertificateException("Invalid PEM could not be converted to DER format.");
        }
        return base64_decode(str_replace(["\n", "\r"], "", trim($match[1])));
    }
}<?php

namespace Kelunik\Certificate;

class FieldNotSupportedException extends \Exception
{
}<?php

$dist = dirname(__DIR__) . '/dist';
if (!is_dir($dist)) {
    mkdir($dist, 0755);
}
if (file_exists($dist . '/random_compat.phar')) {
    unlink($dist . '/random_compat.phar');
}
$phar = new Phar($dist . '/random_compat.phar', FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME, 'random_compat.phar');
rename(dirname(__DIR__) . '/lib/random.php', dirname(__DIR__) . '/lib/index.php');
$phar->buildFromDirectory(dirname(__DIR__) . '/lib');
rename(dirname(__DIR__) . '/lib/index.php', dirname(__DIR__) . '/lib/random.php');
/**
 * If we pass an (optional) path to a private key as a second argument, we will
 * sign the Phar with OpenSSL.
 * 
 * If you leave this out, it will produce an unsigned .phar!
 */
if ($argc > 1) {
    if (!@is_readable($argv[1])) {
        echo 'Could not read the private key file:', $argv[1], "\n";
        exit(255);
    }
    $pkeyFile = file_get_contents($argv[1]);
    $private = openssl_get_privatekey($pkeyFile);
    if ($private !== false) {
        $pkey = '';
        openssl_pkey_export($private, $pkey);
        $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey);
        /**
         * Save the corresponding public key to the file
         */
        if (!@is_readable($dist . '/random_compat.phar.pubkey')) {
            $details = openssl_pkey_get_details($private);
            file_put_contents($dist . '/random_compat.phar.pubkey', $details['key']);
        }
    } else {
        echo 'An error occurred reading the private key from OpenSSL.', "\n";
        exit(255);
    }
}<?php

require_once 'lib/byte_safe_strings.php';
require_once 'lib/cast_to_int.php';
require_once 'lib/error_polyfill.php';
require_once 'other/ide_stubs/libsodium.php';
require_once 'lib/random.php';
$int = random_int(0, 65536);{
  "name":         "paragonie/random_compat",
  "description":  "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
  "keywords": [
    "csprng",
    "random",
    "polyfill",
    "pseudorandom"
  ],
  "license":      "MIT",
  "type":         "library",
  "authors": [
    {
      "name":     "Paragon Initiative Enterprises",
      "email":    "security@paragonie.com",
      "homepage": "https://paragonie.com"
    }
  ],
  "support": {
    "issues":     "https://github.com/paragonie/random_compat/issues",
    "email":      "info@paragonie.com",
    "source":     "https://github.com/paragonie/random_compat"
  },
  "require": {
    "php": ">= 7"
  },
  "require-dev": {
    "vimeo/psalm": "^1",
    "phpunit/phpunit": "4.*|5.*"
  },
  "suggest": {
    "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
  }
}
<?php

/**
 * Random_* Compatibility Library
 * for using the new PHP 7 random_* API in PHP 5 projects
 *
 * @version 2.99.99
 * @released 2018-06-06
 *
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 - 2018 Paragon Initiative Enterprises
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
// NOP<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base32
 * [A-Z][2-7]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base32 implements EncoderInterface
{
    /**
     * Decode a Base32-encoded string into raw binary
     *
     * @param string $encodedString
     * @param bool $strictPadding
     * @return string
     */
    public static function decode(string $encodedString, bool $strictPadding = false) : string
    {
        return static::doDecode($encodedString, false, $strictPadding);
    }
    /**
     * Decode an uppercase Base32-encoded string into raw binary
     *
     * @param string $src
     * @param bool $strictPadding
     * @return string
     */
    public static function decodeUpper(string $src, bool $strictPadding = false) : string
    {
        return static::doDecode($src, true, $strictPadding);
    }
    /**
     * Encode into Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encode(string $src) : string
    {
        return static::doEncode($src, false, true);
    }
    /**
     * Encode into Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encodeUnpadded(string $src) : string
    {
        return static::doEncode($src, false, false);
    }
    /**
     * Encode into uppercase Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encodeUpper(string $src) : string
    {
        return static::doEncode($src, true, true);
    }
    /**
     * Encode into uppercase Base32 (RFC 4648)
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encodeUpperUnpadded(string $src) : string
    {
        return static::doEncode($src, true, false);
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 5-bit integers
    into 8-bit integers.
    *
    * @param int $src
    * @return int
    */
    protected static function decode5Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 96 && $src < 123) $ret += $src - 97 + 1; // -64
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 96;
        // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
        $ret += (0x31 - $src & $src - 0x38) >> 8 & $src - 23;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 5-bit integers
    into 8-bit integers.
    *
    * Uppercase variant.
    *
    * @param int $src
    * @return int
    */
    protected static function decode5BitsUpper(int $src) : int
    {
        $ret = -1;
        // if ($src > 64 && $src < 91) $ret += $src - 65 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x31 && $src < 0x38) $ret += $src - 24 + 1; // -23
        $ret += (0x31 - $src & $src - 0x38) >> 8 & $src - 23;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 5-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode5Bits(int $src) : string
    {
        $diff = 0x61;
        // if ($src > 25) $ret -= 72;
        $diff -= 25 - $src >> 8 & 73;
        return \pack('C', $src + $diff);
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 5-bit integers.
    *
    * Uppercase variant.
    *
    * @param int $src
    * @return string
    */
    protected static function encode5BitsUpper(int $src) : string
    {
        $diff = 0x41;
        // if ($src > 25) $ret -= 40;
        $diff -= 25 - $src >> 8 & 41;
        return \pack('C', $src + $diff);
    }
    /**
     * Base32 decoding
     *
     * @param string $src
     * @param bool $upper
     * @param bool $strictPadding
     * @return string
     * @throws \TypeError
     * @psalm-suppress RedundantCondition
     */
    protected static function doDecode(string $src, bool $upper = false, bool $strictPadding = false) : string
    {
        // We do this to reduce code duplication:
        $method = $upper ? 'decode5BitsUpper' : 'decode5Bits';
        // Remove padding
        $srcLen = Binary::safeStrlen($src);
        if ($srcLen === 0) {
            return '';
        }
        if ($strictPadding) {
            if (($srcLen & 7) === 0) {
                for ($j = 0; $j < 7; ++$j) {
                    if ($src[$srcLen - 1] === '=') {
                        $srcLen--;
                    } else {
                        break;
                    }
                }
            }
            if (($srcLen & 7) === 1) {
                throw new \RangeException('Incorrect padding');
            }
        } else {
            $src = \rtrim($src, '=');
            $srcLen = Binary::safeStrlen($src);
        }
        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 8 <= $srcLen; $i += 8) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 8));
            /** @var int $c0 */
            $c0 = static::$method($chunk[1]);
            /** @var int $c1 */
            $c1 = static::$method($chunk[2]);
            /** @var int $c2 */
            $c2 = static::$method($chunk[3]);
            /** @var int $c3 */
            $c3 = static::$method($chunk[4]);
            /** @var int $c4 */
            $c4 = static::$method($chunk[5]);
            /** @var int $c5 */
            $c5 = static::$method($chunk[6]);
            /** @var int $c6 */
            $c6 = static::$method($chunk[7]);
            /** @var int $c7 */
            $c7 = static::$method($chunk[8]);
            $dest .= \pack('CCCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2 | $c6 >> 3) & 0xff, ($c6 << 5 | $c7) & 0xff);
            $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6 | $c7) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
            /** @var int $c0 */
            $c0 = static::$method($chunk[1]);
            if ($i + 6 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                /** @var int $c5 */
                $c5 = static::$method($chunk[6]);
                /** @var int $c6 */
                $c6 = static::$method($chunk[7]);
                $dest .= \pack('CCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2 | $c6 >> 3) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5 | $c6) >> 8;
            } elseif ($i + 5 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                /** @var int $c5 */
                $c5 = static::$method($chunk[6]);
                $dest .= \pack('CCCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff, ($c4 << 7 | $c5 << 2) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4 | $c5) >> 8;
            } elseif ($i + 4 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                /** @var int $c4 */
                $c4 = static::$method($chunk[5]);
                $dest .= \pack('CCC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff, ($c3 << 4 | $c4 >> 1) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3 | $c4) >> 8;
            } elseif ($i + 3 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                /** @var int $c3 */
                $c3 = static::$method($chunk[4]);
                $dest .= \pack('CC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1 | $c3 >> 4) & 0xff);
                $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
            } elseif ($i + 2 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                /** @var int $c2 */
                $c2 = static::$method($chunk[3]);
                $dest .= \pack('CC', ($c0 << 3 | $c1 >> 2) & 0xff, ($c1 << 6 | $c2 << 1) & 0xff);
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                /** @var int $c1 */
                $c1 = static::$method($chunk[2]);
                $dest .= \pack('C', ($c0 << 3 | $c1 >> 2) & 0xff);
                $err |= ($c0 | $c1) >> 8;
            } else {
                $dest .= \pack('C', $c0 << 3 & 0xff);
                $err |= $c0 >> 8;
            }
        }
        /** @var bool $check */
        $check = $err === 0;
        if (!$check) {
            throw new \RangeException('Base32::doDecode() only expects characters in the correct base32 alphabet');
        }
        return $dest;
    }
    /**
     * Base32 Encoding
     *
     * @param string $src
     * @param bool $upper
     * @param bool $pad
     * @return string
     * @throws \TypeError
     */
    protected static function doEncode(string $src, bool $upper = false, $pad = true) : string
    {
        // We do this to reduce code duplication:
        $method = $upper ? 'encode5BitsUpper' : 'encode5Bits';
        $dest = '';
        $srcLen = Binary::safeStrlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 5 <= $srcLen; $i += 5) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 5));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];
            $b3 = $chunk[4];
            $b4 = $chunk[5];
            $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method(($b2 << 1 | $b3 >> 7) & 31) . static::$method($b3 >> 2 & 31) . static::$method(($b3 << 3 | $b4 >> 5) & 31) . static::$method($b4 & 31);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 3 < $srcLen) {
                $b1 = $chunk[2];
                $b2 = $chunk[3];
                $b3 = $chunk[4];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method(($b2 << 1 | $b3 >> 7) & 31) . static::$method($b3 >> 2 & 31) . static::$method($b3 << 3 & 31);
                if ($pad) {
                    $dest .= '=';
                }
            } elseif ($i + 2 < $srcLen) {
                $b1 = $chunk[2];
                $b2 = $chunk[3];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method(($b1 << 4 | $b2 >> 4) & 31) . static::$method($b2 << 1 & 31);
                if ($pad) {
                    $dest .= '===';
                }
            } elseif ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .= static::$method($b0 >> 3 & 31) . static::$method(($b0 << 2 | $b1 >> 6) & 31) . static::$method($b1 >> 1 & 31) . static::$method($b1 << 4 & 31);
                if ($pad) {
                    $dest .= '====';
                }
            } else {
                $dest .= static::$method($b0 >> 3 & 31) . static::$method($b0 << 2 & 31);
                if ($pad) {
                    $dest .= '======';
                }
            }
        }
        return $dest;
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Hex
 * @package ParagonIE\ConstantTime
 */
abstract class Hex implements EncoderInterface
{
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $binString (raw binary)
    * @return string
    * @throws \TypeError
    */
    public static function encode(string $binString) : string
    {
        /** @var string $hex */
        $hex = '';
        $len = Binary::safeStrlen($binString);
        for ($i = 0; $i < $len; ++$i) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C', Binary::safeSubstr($binString, $i, 1));
            /** @var int $c */
            $c = $chunk[1] & 0xf;
            /** @var int $b */
            $b = $chunk[1] >> 4;
            $hex .= pack('CC', 87 + $b + ($b - 10 >> 8 & ~38), 87 + $c + ($c - 10 >> 8 & ~38));
        }
        return $hex;
    }
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks, returning uppercase letters (as per RFC 4648)
    *
    * @param string $binString (raw binary)
    * @return string
    * @throws \TypeError
    */
    public static function encodeUpper(string $binString) : string
    {
        /** @var string $hex */
        $hex = '';
        /** @var int $len */
        $len = Binary::safeStrlen($binString);
        for ($i = 0; $i < $len; ++$i) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C', Binary::safeSubstr($binString, $i, 2));
            /** @var int $c */
            $c = $chunk[1] & 0xf;
            /** @var int $b */
            $b = $chunk[1] >> 4;
            $hex .= pack('CC', 55 + $b + ($b - 10 >> 8 & ~6), 55 + $c + ($c - 10 >> 8 & ~6));
        }
        return $hex;
    }
    /**
    * Convert a hexadecimal string into a binary string without cache-timing
    leaks
    *
    * @param string $encodedString
    * @param bool $strictPadding
    * @return string (raw binary)
    * @throws \RangeException
    */
    public static function decode(string $encodedString, bool $strictPadding = false) : string
    {
        /** @var int $hex_pos */
        $hex_pos = 0;
        /** @var string $bin */
        $bin = '';
        /** @var int $c_acc */
        $c_acc = 0;
        /** @var int $hex_len */
        $hex_len = Binary::safeStrlen($encodedString);
        /** @var int $state */
        $state = 0;
        if (($hex_len & 1) !== 0) {
            if ($strictPadding) {
                throw new \RangeException('Expected an even number of hexadecimal characters');
            } else {
                $encodedString = '0' . $encodedString;
                ++$hex_len;
            }
        }
        /** @var array<int, int> $chunk */
        $chunk = \unpack('C*', $encodedString);
        while ($hex_pos < $hex_len) {
            ++$hex_pos;
            /** @var int $c */
            $c = $chunk[$hex_pos];
            /** @var int $c_num */
            $c_num = $c ^ 48;
            /** @var int $c_num0 */
            $c_num0 = $c_num - 10 >> 8;
            /** @var int $c_alpha */
            $c_alpha = ($c & ~32) - 55;
            /** @var int $c_alpha0 */
            $c_alpha0 = ($c_alpha - 10 ^ $c_alpha - 16) >> 8;
            if (($c_num0 | $c_alpha0) === 0) {
                throw new \RangeException('Expected hexadecimal character');
            }
            /** @var int $c_val */
            $c_val = $c_num0 & $c_num | $c_alpha & $c_alpha0;
            if ($state === 0) {
                $c_acc = $c_val * 16;
            } else {
                $bin .= \pack('C', $c_acc | $c_val);
            }
            $state ^= 1;
        }
        return $bin;
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64DotSlash
 * ./[A-Z][a-z][0-9]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64DotSlash extends Base64
{
    /**
    * Uses bitwise operators instead of table-lookups to turn 6-bit integers
    into 8-bit integers.
    *
    * Base64 character set:
    ./         [A-Z]      [a-z]     [0-9]
    0x2e-0x2f, 0x41-0x5a, 0x61-0x7a, 0x30-0x39
    *
    * @param int $src
    * @return int
    */
    protected static function decode6Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x2d && $src < 0x30) ret += $src - 0x2e + 1; // -45
        $ret += (0x2d - $src & $src - 0x30) >> 8 & $src - 45;
        // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 2 + 1; // -62
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 62;
        // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 28 + 1; // -68
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 68;
        // if ($src > 0x2f && $src < 0x3a) ret += $src - 0x30 + 54 + 1; // 7
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 7;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 6-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode6Bits(int $src) : string
    {
        $src += 0x2e;
        // if ($src > 0x2f) $src += 0x41 - 0x30; // 17
        $src += 0x2f - $src >> 8 & 17;
        // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
        $src += 0x5a - $src >> 8 & 6;
        // if ($src > 0x7a) $src += 0x30 - 0x7b; // -75
        $src -= 0x7a - $src >> 8 & 75;
        return \pack('C', $src);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Encoding
 * @package ParagonIE\ConstantTime
 */
abstract class Encoding
{
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32Encode(string $str) : string
    {
        return Base32::encode($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32EncodeUpper(string $str) : string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32 decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32Decode(string $str) : string
    {
        return Base32::decode($str);
    }
    /**
     * RFC 4648 Base32 decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32DecodeUpper(string $str) : string
    {
        return Base32::decodeUpper($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexEncode(string $str) : string
    {
        return Base32Hex::encode($str);
    }
    /**
     * RFC 4648 Base32Hex encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexEncodeUpper(string $str) : string
    {
        return Base32Hex::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32Hex decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexDecode(string $str) : string
    {
        return Base32Hex::decode($str);
    }
    /**
     * RFC 4648 Base32Hex decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexDecodeUpper(string $str) : string
    {
        return Base32Hex::decodeUpper($str);
    }
    /**
     * RFC 4648 Base64 encoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64Encode(string $str) : string
    {
        return Base64::encode($str);
    }
    /**
     * RFC 4648 Base64 decoding
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64Decode(string $str) : string
    {
        return Base64::decode($str);
    }
    /**
     * Encode into Base64
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64EncodeDotSlash(string $str) : string
    {
        return Base64DotSlash::encode($str);
    }
    /**
     * Decode from base64 to raw binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $str
     * @return string
     * @throws \RangeException
     * @throws \TypeError
     */
    public static function base64DecodeDotSlash(string $str) : string
    {
        return Base64DotSlash::decode($str);
    }
    /**
     * Encode into Base64
     *
     * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64EncodeDotSlashOrdered(string $str) : string
    {
        return Base64DotSlashOrdered::encode($str);
    }
    /**
     * Decode from base64 to raw binary
     *
     * Base64 character set "[.-9][A-Z][a-z]" or "./[0-9][A-Z][a-z]"
     *
     * @param string $str
     * @return string
     * @throws \RangeException
     * @throws \TypeError
     */
    public static function base64DecodeDotSlashOrdered(string $str) : string
    {
        return Base64DotSlashOrdered::decode($str);
    }
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $bin_string (raw binary)
    * @return string
    * @throws \TypeError
    */
    public static function hexEncode(string $bin_string) : string
    {
        return Hex::encode($bin_string);
    }
    /**
    * Convert a hexadecimal string into a binary string without cache-timing
    leaks
    *
    * @param string $hex_string
    * @return string (raw binary)
    * @throws \RangeException
    */
    public static function hexDecode(string $hex_string) : string
    {
        return Hex::decode($hex_string);
    }
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $bin_string (raw binary)
    * @return string
    * @throws \TypeError
    */
    public static function hexEncodeUpper(string $bin_string) : string
    {
        return Hex::encodeUpper($bin_string);
    }
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $bin_string (raw binary)
    * @return string
    */
    public static function hexDecodeUpper(string $bin_string) : string
    {
        return Hex::decode($bin_string);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base32Hex
 * [0-9][A-V]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base32Hex extends Base32
{
    /**
    * Uses bitwise operators instead of table-lookups to turn 5-bit integers
    into 8-bit integers.
    *
    * @param int $src
    * @return int
    */
    protected static function decode5Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src - 47;
        // if ($src > 0x60 && $src < 0x77) ret += $src - 0x61 + 10 + 1; // -86
        $ret += (0x60 - $src & $src - 0x77) >> 8 & $src - 86;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 5-bit integers
    into 8-bit integers.
    *
    * @param int $src
    * @return int
    */
    protected static function decode5BitsUpper(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x30 && $src < 0x3a) ret += $src - 0x2e + 1; // -47
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src - 47;
        // if ($src > 0x40 && $src < 0x57) ret += $src - 0x41 + 10 + 1; // -54
        $ret += (0x40 - $src & $src - 0x57) >> 8 & $src - 54;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 5-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode5Bits(int $src) : string
    {
        $src += 0x30;
        // if ($src > 0x39) $src += 0x61 - 0x3a; // 39
        $src += 0x39 - $src >> 8 & 39;
        return \pack('C', $src);
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 5-bit integers.
    *
    * Uppercase variant.
    *
    * @param int $src
    * @return string
    */
    protected static function encode5BitsUpper(int $src) : string
    {
        $src += 0x30;
        // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
        $src += 0x39 - $src >> 8 & 7;
        return \pack('C', $src);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64UrlSafe
 * [A-Z][a-z][0-9]\-_
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64UrlSafe extends Base64
{
    /**
    * Uses bitwise operators instead of table-lookups to turn 6-bit integers
    into 8-bit integers.
    *
    * Base64 character set:
    [A-Z]      [a-z]      [0-9]      -     _
    0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2d, 0x5f
    *
    * @param int $src
    * @return int
    */
    protected static function decode6Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 70;
        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 5;
        // if ($src == 0x2c) $ret += 62 + 1;
        $ret += (0x2c - $src & $src - 0x2e) >> 8 & 63;
        // if ($src == 0x5f) ret += 63 + 1;
        $ret += (0x5e - $src & $src - 0x60) >> 8 & 64;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 6-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode6Bits(int $src) : string
    {
        $diff = 0x41;
        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += 25 - $src >> 8 & 6;
        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= 51 - $src >> 8 & 75;
        // if ($src > 61) $diff += 0x2d - 0x30 - 10; // -13
        $diff -= 61 - $src >> 8 & 13;
        // if ($src > 62) $diff += 0x5f - 0x2b - 1; // 3
        $diff += 62 - $src >> 8 & 49;
        return \pack('C', $src + $diff);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Interface EncoderInterface
 * @package ParagonIE\ConstantTime
 */
interface EncoderInterface
{
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $binString (raw binary)
    * @return string
    */
    public static function encode(string $binString) : string;
    /**
    * Convert a binary string into a hexadecimal string without cache-timing
    leaks
    *
    * @param string $encodedString
    * @param bool $strictPadding Error on invalid padding
    * @return string (raw binary)
    */
    public static function decode(string $encodedString, bool $strictPadding = false) : string;
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64
 * [A-Z][a-z][0-9]+/
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64 implements EncoderInterface
{
    /**
     * Encode into Base64
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encode(string $src) : string
    {
        return static::doEncode($src, true);
    }
    /**
     * Encode into Base64, no = padding
     *
     * Base64 character set "[A-Z][a-z][0-9]+/"
     *
     * @param string $src
     * @return string
     * @throws \TypeError
     */
    public static function encodeUnpadded(string $src) : string
    {
        return static::doEncode($src, false);
    }
    /**
     * @param string $src
     * @param bool $pad Include = padding?
     * @return string
     * @throws \TypeError
     */
    protected static function doEncode(string $src, bool $pad = true) : string
    {
        $dest = '';
        $srcLen = Binary::safeStrlen($src);
        // Main loop (no padding):
        for ($i = 0; $i + 3 <= $srcLen; $i += 3) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, 3));
            $b0 = $chunk[1];
            $b1 = $chunk[2];
            $b2 = $chunk[3];
            $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits(($b0 << 4 | $b1 >> 4) & 63) . static::encode6Bits(($b1 << 2 | $b2 >> 6) & 63) . static::encode6Bits($b2 & 63);
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($src, $i, $srcLen - $i));
            $b0 = $chunk[1];
            if ($i + 1 < $srcLen) {
                $b1 = $chunk[2];
                $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits(($b0 << 4 | $b1 >> 4) & 63) . static::encode6Bits($b1 << 2 & 63);
                if ($pad) {
                    $dest .= '=';
                }
            } else {
                $dest .= static::encode6Bits($b0 >> 2) . static::encode6Bits($b0 << 4 & 63);
                if ($pad) {
                    $dest .= '==';
                }
            }
        }
        return $dest;
    }
    /**
     * decode from base64 into binary
     *
     * Base64 character set "./[A-Z][a-z][0-9]"
     *
     * @param string $encodedString
     * @param bool $strictPadding
     * @return string
     * @throws \RangeException
     * @throws \TypeError
     * @psalm-suppress RedundantCondition
     */
    public static function decode(string $encodedString, bool $strictPadding = false) : string
    {
        // Remove padding
        $srcLen = Binary::safeStrlen($encodedString);
        if ($srcLen === 0) {
            return '';
        }
        if ($strictPadding) {
            if (($srcLen & 3) === 0) {
                if ($encodedString[$srcLen - 1] === '=') {
                    $srcLen--;
                    if ($encodedString[$srcLen - 1] === '=') {
                        $srcLen--;
                    }
                }
            }
            if (($srcLen & 3) === 1) {
                throw new \RangeException('Incorrect padding');
            }
            if ($encodedString[$srcLen - 1] === '=') {
                throw new \RangeException('Incorrect padding');
            }
        } else {
            $encodedString = \rtrim($encodedString, '=');
            $srcLen = Binary::safeStrlen($encodedString);
        }
        $err = 0;
        $dest = '';
        // Main loop (no padding):
        for ($i = 0; $i + 4 <= $srcLen; $i += 4) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, 4));
            $c0 = static::decode6Bits($chunk[1]);
            $c1 = static::decode6Bits($chunk[2]);
            $c2 = static::decode6Bits($chunk[3]);
            $c3 = static::decode6Bits($chunk[4]);
            $dest .= \pack('CCC', ($c0 << 2 | $c1 >> 4) & 0xff, ($c1 << 4 | $c2 >> 2) & 0xff, ($c2 << 6 | $c3) & 0xff);
            $err |= ($c0 | $c1 | $c2 | $c3) >> 8;
        }
        // The last chunk, which may have padding:
        if ($i < $srcLen) {
            /** @var array<int, int> $chunk */
            $chunk = \unpack('C*', Binary::safeSubstr($encodedString, $i, $srcLen - $i));
            $c0 = static::decode6Bits($chunk[1]);
            if ($i + 2 < $srcLen) {
                $c1 = static::decode6Bits($chunk[2]);
                $c2 = static::decode6Bits($chunk[3]);
                $dest .= \pack('CC', ($c0 << 2 | $c1 >> 4) & 0xff, ($c1 << 4 | $c2 >> 2) & 0xff);
                $err |= ($c0 | $c1 | $c2) >> 8;
            } elseif ($i + 1 < $srcLen) {
                $c1 = static::decode6Bits($chunk[2]);
                $dest .= \pack('C', ($c0 << 2 | $c1 >> 4) & 0xff);
                $err |= ($c0 | $c1) >> 8;
            } elseif ($i < $srcLen && $strictPadding) {
                $err |= 1;
            }
        }
        /** @var bool $check */
        $check = $err === 0;
        if (!$check) {
            throw new \RangeException('Base64::decode() only expects characters in the correct base64 alphabet');
        }
        return $dest;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 6-bit integers
    into 8-bit integers.
    *
    * Base64 character set:
    [A-Z]      [a-z]      [0-9]      +     /
    0x41-0x5a, 0x61-0x7a, 0x30-0x39, 0x2b, 0x2f
    *
    * @param int $src
    * @return int
    */
    protected static function decode6Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x40 && $src < 0x5b) $ret += $src - 0x41 + 1; // -64
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 64;
        // if ($src > 0x60 && $src < 0x7b) $ret += $src - 0x61 + 26 + 1; // -70
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 70;
        // if ($src > 0x2f && $src < 0x3a) $ret += $src - 0x30 + 52 + 1; // 5
        $ret += (0x2f - $src & $src - 0x3a) >> 8 & $src + 5;
        // if ($src == 0x2b) $ret += 62 + 1;
        $ret += (0x2a - $src & $src - 0x2c) >> 8 & 63;
        // if ($src == 0x2f) ret += 63 + 1;
        $ret += (0x2e - $src & $src - 0x30) >> 8 & 64;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 6-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode6Bits(int $src) : string
    {
        $diff = 0x41;
        // if ($src > 25) $diff += 0x61 - 0x41 - 26; // 6
        $diff += 25 - $src >> 8 & 6;
        // if ($src > 51) $diff += 0x30 - 0x61 - 26; // -75
        $diff -= 51 - $src >> 8 & 75;
        // if ($src > 61) $diff += 0x2b - 0x30 - 10; // -15
        $diff -= 61 - $src >> 8 & 15;
        // if ($src > 62) $diff += 0x2f - 0x2b - 1; // 3
        $diff += 62 - $src >> 8 & 3;
        return \pack('C', $src + $diff);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Base64DotSlashOrdered
 * ./[0-9][A-Z][a-z]
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Base64DotSlashOrdered extends Base64
{
    /**
    * Uses bitwise operators instead of table-lookups to turn 6-bit integers
    into 8-bit integers.
    *
    * Base64 character set:
    [.-9]      [A-Z]      [a-z]
    0x2e-0x39, 0x41-0x5a, 0x61-0x7a
    *
    * @param int $src
    * @return int
    */
    protected static function decode6Bits(int $src) : int
    {
        $ret = -1;
        // if ($src > 0x2d && $src < 0x3a) ret += $src - 0x2e + 1; // -45
        $ret += (0x2d - $src & $src - 0x3a) >> 8 & $src - 45;
        // if ($src > 0x40 && $src < 0x5b) ret += $src - 0x41 + 12 + 1; // -52
        $ret += (0x40 - $src & $src - 0x5b) >> 8 & $src - 52;
        // if ($src > 0x60 && $src < 0x7b) ret += $src - 0x61 + 38 + 1; // -58
        $ret += (0x60 - $src & $src - 0x7b) >> 8 & $src - 58;
        return $ret;
    }
    /**
    * Uses bitwise operators instead of table-lookups to turn 8-bit integers
    into 6-bit integers.
    *
    * @param int $src
    * @return string
    */
    protected static function encode6Bits(int $src) : string
    {
        $src += 0x2e;
        // if ($src > 0x39) $src += 0x41 - 0x3a; // 7
        $src += 0x39 - $src >> 8 & 7;
        // if ($src > 0x5a) $src += 0x61 - 0x5b; // 6
        $src += 0x5a - $src >> 8 & 6;
        return \pack('C', $src);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class RFC4648
 *
 * This class conforms strictly to the RFC
 *
 * @package ParagonIE\ConstantTime
 */
abstract class RFC4648
{
    /**
     * RFC 4648 Base64 encoding
     *
     * "foo" -> "Zm9v"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64Encode(string $str) : string
    {
        return Base64::encode($str);
    }
    /**
     * RFC 4648 Base64 decoding
     *
     * "Zm9v" -> "foo"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64Decode(string $str) : string
    {
        return Base64::decode($str, true);
    }
    /**
     * RFC 4648 Base64 (URL Safe) encoding
     *
     * "foo" -> "Zm9v"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64UrlSafeEncode(string $str) : string
    {
        return Base64UrlSafe::encode($str);
    }
    /**
     * RFC 4648 Base64 (URL Safe) decoding
     *
     * "Zm9v" -> "foo"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base64UrlSafeDecode(string $str) : string
    {
        return Base64UrlSafe::decode($str, true);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * "foo" -> "MZXW6==="
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32Encode(string $str) : string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32 encoding
     *
     * "MZXW6===" -> "foo"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32Decode(string $str) : string
    {
        return Base32::decodeUpper($str, true);
    }
    /**
     * RFC 4648 Base32-Hex encoding
     *
     * "foo" -> "CPNMU==="
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexEncode(string $str) : string
    {
        return Base32::encodeUpper($str);
    }
    /**
     * RFC 4648 Base32-Hex decoding
     *
     * "CPNMU===" -> "foo"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base32HexDecode(string $str) : string
    {
        return Base32::decodeUpper($str, true);
    }
    /**
     * RFC 4648 Base16 decoding
     *
     * "foo" -> "666F6F"
     *
     * @param string $str
     * @return string
     * @throws \TypeError
     */
    public static function base16Encode(string $str) : string
    {
        return Hex::encodeUpper($str);
    }
    /**
     * RFC 4648 Base16 decoding
     *
     * "666F6F" -> "foo"
     *
     * @param string $str
     * @return string
     */
    public static function base16Decode(string $str) : string
    {
        return Hex::decode($str, true);
    }
}<?php

declare (strict_types=1);
namespace ParagonIE\ConstantTime;

/**
 *  Copyright (c) 2016 - 2018 Paragon Initiative Enterprises.
 *  Copyright (c) 2014 Steve "Sc00bz" Thomas (steve at tobtu dot com)
 *
 *  Permission is hereby granted, free of charge, to any person obtaining a copy
 *  of this software and associated documentation files (the "Software"), to deal
 *  in the Software without restriction, including without limitation the rights
 *  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 *  copies of the Software, and to permit persons to whom the Software is
 *  furnished to do so, subject to the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included in all
 *  copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 *  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 *  SOFTWARE.
 */
/**
 * Class Binary
 *
 * Binary string operators that don't choke on
 * mbstring.func_overload
 *
 * @package ParagonIE\ConstantTime
 */
abstract class Binary
{
    /**
     * Safe string length
     *
     * @ref mbstring.func_overload
     *
     * @param string $str
     * @return int
     */
    public static function safeStrlen(string $str) : int
    {
        if (\function_exists('mb_strlen')) {
            return (int) \mb_strlen($str, '8bit');
        } else {
            return \strlen($str);
        }
    }
    /**
     * Safe substring
     *
     * @ref mbstring.func_overload
     *
     * @staticvar boolean $exists
     * @param string $str
     * @param int $start
     * @param int $length
     * @return string
     * @throws \TypeError
     */
    public static function safeSubstr(string $str, int $start = 0, $length = null) : string
    {
        if ($length === 0) {
            return '';
        }
        if (\function_exists('mb_substr')) {
            return \mb_substr($str, $start, $length, '8bit');
        }
        // Unlike mb_substr(), substr() doesn't accept NULL for length
        if ($length !== null) {
            return \Phabel\Target\Php80\Polyfill::substr($str, $start, $length);
        } else {
            return \Phabel\Target\Php80\Polyfill::substr($str, $start);
        }
    }
}{
  "name": "paragonie/constant_time_encoding",
  "description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
  "keywords": [
    "base64",
    "encoding",
    "rfc4648",
    "base32",
    "base16",
    "hex",
    "bin2hex",
    "hex2bin",
    "base64_encode",
    "base64_decode",
    "base32_encode",
    "base32_decode"
  ],
  "license": "MIT",
  "type": "library",
  "authors": [
      {
        "name":     "Paragon Initiative Enterprises",
        "email":    "security@paragonie.com",
        "homepage": "https://paragonie.com",
        "role":     "Maintainer"
      },
      {
        "name":     "Steve 'Sc00bz' Thomas",
        "email":    "steve@tobtu.com",
        "homepage": "https://www.tobtu.com",
        "role":     "Original Developer"
      }
  ],
  "support": {
    "issues":   "https://github.com/paragonie/constant_time_encoding/issues",
    "email":    "info@paragonie.com",
    "source":   "https://github.com/paragonie/constant_time_encoding"
  },
  "require": {
    "php": "^7|^8"
  },
  "require-dev": {
    "phpunit/phpunit": "^6|^7|^8|^9",
    "vimeo/psalm": "^1|^2|^3|^4"
  },
  "autoload": {
    "psr-4": {
      "ParagonIE\\ConstantTime\\": "src/"
    }
  }
}
{
    "name": "phpseclib/phpseclib",
    "type": "library",
    "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
    "keywords": [
        "security",
        "crypto",
        "cryptography",
        "encryption",
        "signature",
        "signing",
        "rsa",
        "aes",
        "blowfish",
        "twofish",
        "ssh",
        "sftp",
        "x509",
        "x.509",
        "asn1",
        "asn.1",
        "BigInteger"
        ],
    "homepage": "http://phpseclib.sourceforge.net",
    "license": "MIT",
    "authors": [
        {
            "name": "Jim Wigginton",
            "email": "terrafrost@php.net",
            "role": "Lead Developer"
        },
        {
            "name": "Patrick Monnerat",
            "email": "pm@datasphere.ch",
            "role": "Developer"
        },
        {
            "name": "Andreas Fischer",
            "email": "bantu@phpbb.com",
            "role": "Developer"
        },
        {
            "name": "Hans-JÃ¼rgen Petrich",
            "email": "petrich@tronic-media.com",
            "role": "Developer"
        },
        {
            "name": "Graham Campbell",
            "email": "graham@alt-three.com",
            "role": "Developer"
        }
    ],
    "require": {
        "paragonie/constant_time_encoding": "^1|^2",
        "paragonie/random_compat": "^1.4|^2.0|^9.99.99",
        "php": ">=5.6.1"
    },
    "require-dev": {
        "phing/phing": "~2.7",
        "phpunit/phpunit": "^5.7|^6.0|^9.4",
        "squizlabs/php_codesniffer": "~2.0"
    },
    "suggest": {
        "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
        "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations.",
        "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
        "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations."
    },
    "autoload": {
        "files": [
            "phpseclib/bootstrap.php"
        ],
        "psr-4": {
            "phpseclib3\\": "phpseclib/"
        }
    }
}
<?php

/**
 * Pure-PHP implementation of AES.
 *
 * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * NOTE: Since AES.php is (for compatibility and phpseclib-historical reasons) virtually
 * just a wrapper to Rijndael.php you may consider using Rijndael.php instead of
 * to save one include_once().
 *
 * If {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
 * {@link self::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's 136-bits
 * it'll be null-padded to 192-bits and 192 bits will be the key length until {@link self::setKey() setKey()}
 * is called, again, at which point, it'll be recalculated.
 *
 * Since \phpseclib3\Crypt\AES extends \phpseclib3\Crypt\Rijndael, some functions are available to be called that, in the context of AES, don't
 * make a whole lot of sense.  {@link self::setBlockLength() setBlockLength()}, for instance.  Calling that function,
 * however possible, won't do anything (AES has a fixed block length whereas Rijndael has a variable one).
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $aes = new \phpseclib3\Crypt\AES('ctr');
 *
 *    $aes->setKey('abcdefghijklmnop');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $aes->decrypt($aes->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   AES
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2008 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

/**
 * Pure-PHP implementation of AES.
 *
 * @package AES
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class AES extends Rijndael
{
    /**
     * Dummy function
     *
     * Since \phpseclib3\Crypt\AES extends \phpseclib3\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything.
     *
     * @see \phpseclib3\Crypt\Rijndael::setBlockLength()
     * @access public
     * @param int $length
     * @throws \BadMethodCallException anytime it's called
     */
    public function setBlockLength($length)
    {
        throw new \BadMethodCallException('The block length cannot be set for AES.');
    }
    /**
     * Sets the key length
     *
     * Valid key lengths are 128, 192, and 256.  Set the link to bool(false) to disable a fixed key length
     *
     * @see \phpseclib3\Crypt\Rijndael:setKeyLength()
     * @access public
     * @param int $length
     * @throws \LengthException if the key length isn't supported
     */
    public function setKeyLength($length)
    {
        switch ($length) {
            case 128:
            case 192:
            case 256:
                break;
            default:
                throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 128, 192 or 256 supported');
        }
        parent::setKeyLength($length);
    }
    /**
     * Sets the key.
     *
     * Rijndael supports five different key lengths, AES only supports three.
     *
     * @see \phpseclib3\Crypt\Rijndael:setKey()
     * @see setKeyLength()
     * @access public
     * @param string $key
     * @throws \LengthException if the key length isn't supported
     */
    public function setKey($key)
    {
        switch (strlen($key)) {
            case 16:
            case 24:
            case 32:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
        }
        parent::setKey($key);
    }
}<?php

/**
 * Wrapper around hash() and hash_hmac() functions supporting truncated hashes
 * such as sha256-96.  Any hash algorithm returned by hash_algos() (and
 * truncated versions thereof) are supported.
 *
 * If {@link self::setKey() setKey()} is called, {@link self::hash() hash()} will
 * return the HMAC as opposed to the hash.
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $hash = new \phpseclib3\Crypt\Hash('sha512');
 *
 *    $hash->setKey('abcdefg');
 *
 *    echo base64_encode($hash->hash('abcdefg'));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Hash
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @author    Andreas Fischer <bantu@phpbb.com>
 * @copyright 2015 Andreas Fischer
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\AES;
use phpseclib3\Math\PrimeField;
/**
 * @package Hash
 * @author  Jim Wigginton <terrafrost@php.net>
 * @author  Andreas Fischer <bantu@phpbb.com>
 * @access  public
 */
class Hash
{
    /**
     * Padding Types
     *
     * @access private
     */
    //const PADDING_KECCAK = 1;
    /**
     * Padding Types
     *
     * @access private
     */
    const PADDING_SHA3 = 2;
    /**
     * Padding Types
     *
     * @access private
     */
    const PADDING_SHAKE = 3;
    /**
     * Padding Type
     *
     * Only used by SHA3
     *
     * @var int
     * @access private
     */
    private $paddingType = 0;
    /**
     * Hash Parameter
     *
     * @see self::setHash()
     * @var int
     * @access private
     */
    private $hashParam;
    /**
     * Byte-length of hash output (Internal HMAC)
     *
     * @see self::setHash()
     * @var int
     * @access private
     */
    private $length;
    /**
     * Hash Algorithm
     *
     * @see self::setHash()
     * @var string
     * @access private
     */
    private $algo;
    /**
     * Key
     *
     * @see self::setKey()
     * @var string
     * @access private
     */
    private $key = false;
    /**
     * Nonce
     *
     * @see self::setNonce()
     * @var string
     * @access private
     */
    private $nonce = false;
    /**
     * Hash Parameters
     *
     * @var array
     * @access private
     */
    private $parameters = [];
    /**
     * Computed Key
     *
     * @see self::_computeKey()
     * @var string
     * @access private
     */
    private $computedKey = false;
    /**
     * Outer XOR (Internal HMAC)
     *
     * Used only for sha512/*
     *
     * @see self::hash()
     * @var string
     * @access private
     */
    private $opad;
    /**
     * Inner XOR (Internal HMAC)
     *
     * Used only for sha512/*
     *
     * @see self::hash()
     * @var string
     * @access private
     */
    private $ipad;
    /**
     * Recompute AES Key
     *
     * Used only for umac
     *
     * @see self::hash()
     * @var boolean
     * @access private
     */
    private $recomputeAESKey;
    /**
     * umac cipher object
     *
     * @see self::hash()
     * @var \phpseclib3\Crypt\AES
     * @access private
     */
    private $c;
    /**
     * umac pad
     *
     * @see self::hash()
     * @var string
     * @access private
     */
    private $pad;
    /**#@+
     * UMAC variables
     *
     * @var PrimeField
     */
    private static $factory36;
    private static $factory64;
    private static $factory128;
    private static $offset64;
    private static $offset128;
    private static $marker64;
    private static $marker128;
    private static $maxwordrange64;
    private static $maxwordrange128;
    /**#@-*/
    /**
     * Default Constructor.
     *
     * @param string $hash
     * @access public
     */
    public function __construct($hash = 'sha256')
    {
        $this->setHash($hash);
    }
    /**
     * Sets the key for HMACs
     *
     * Keys can be of any length.
     *
     * @access public
     * @param string $key
     */
    public function setKey($key = false)
    {
        $this->key = $key;
        $this->computeKey();
        $this->recomputeAESKey = true;
    }
    /**
     * Sets the nonce for UMACs
     *
     * Keys can be of any length.
     *
     * @access public
     * @param string $nonce
     */
    public function setNonce($nonce = false)
    {
        switch (true) {
            case !is_string($nonce):
            case strlen($nonce) > 0 && strlen($nonce) <= 16:
                $this->recomputeAESKey = true;
                $this->nonce = $nonce;
                return;
        }
        throw new \LengthException('The nonce length must be between 1 and 16 bytes, inclusive');
    }
    /**
    * Pre-compute the key used by the HMAC
    *
    * Quoting http://tools.ietf.org/html/rfc2104#section-2, "Applications that use keys longer than B bytes
    will first hash the key using H and then use the resultant L byte string as the actual key to HMAC."
    *
    * As documented in https://www.reddit.com/r/PHP/comments/9nct2l/symfonypolyfill_hash_pbkdf2_correct_fix_for/
    when doing an HMAC multiple times it's faster to compute the hash once instead of computing it during
    every call
    *
    * @access private
    */
    private function computeKey()
    {
        if ($this->key === false) {
            $this->computedKey = false;
            return;
        }
        if (strlen($this->key) <= $this->getBlockLengthInBytes()) {
            $this->computedKey = $this->key;
            return;
        }
        $this->computedKey = is_array($this->algo) ? call_user_func($this->algo, $this->key) : hash($this->algo, $this->key, true);
    }
    /**
     * Gets the hash function.
     *
     * As set by the constructor or by the setHash() method.
     *
     * @access public
     * @return string
     */
    public function getHash()
    {
        return $this->hashParam;
    }
    /**
     * Sets the hash function.
     *
     * @access public
     * @param string $hash
     */
    public function setHash($hash)
    {
        $this->hashParam = $hash = strtolower($hash);
        switch ($hash) {
            case 'umac-32':
            case 'umac-64':
            case 'umac-96':
            case 'umac-128':
                $this->blockSize = 128;
                $this->length = abs(\Phabel\Target\Php80\Polyfill::substr($hash, -3)) >> 3;
                $this->algo = 'umac';
                return;
            case 'md2-96':
            case 'md5-96':
            case 'sha1-96':
            case 'sha224-96':
            case 'sha256-96':
            case 'sha384-96':
            case 'sha512-96':
            case 'sha512/224-96':
            case 'sha512/256-96':
                $hash = \Phabel\Target\Php80\Polyfill::substr($hash, 0, -3);
                $this->length = 12;
                // 96 / 8 = 12
                break;
            case 'md2':
            case 'md5':
                $this->length = 16;
                break;
            case 'sha1':
                $this->length = 20;
                break;
            case 'sha224':
            case 'sha512/224':
            case 'sha3-224':
                $this->length = 28;
                break;
            case 'sha256':
            case 'sha512/256':
            case 'sha3-256':
                $this->length = 32;
                break;
            case 'sha384':
            case 'sha3-384':
                $this->length = 48;
                break;
            case 'sha512':
            case 'sha3-512':
                $this->length = 64;
                break;
            default:
                if (preg_match('#^(shake(?:128|256))-(\\d+)$#', $hash, $matches)) {
                    $this->paddingType = self::PADDING_SHAKE;
                    $hash = $matches[1];
                    $this->length = $matches[2] >> 3;
                } else {
                    throw new UnsupportedAlgorithmException("{$hash} is not a supported algorithm");
                }
        }
        switch ($hash) {
            case 'md2':
            case 'md2-96':
                $this->blockSize = 128;
                break;
            case 'md5-96':
            case 'sha1-96':
            case 'sha224-96':
            case 'sha256-96':
            case 'md5':
            case 'sha1':
            case 'sha224':
            case 'sha256':
                $this->blockSize = 512;
                break;
            case 'sha3-224':
                $this->blockSize = 1152;
                // 1600 - 2*224
                break;
            case 'sha3-256':
            case 'shake256':
                $this->blockSize = 1088;
                // 1600 - 2*256
                break;
            case 'sha3-384':
                $this->blockSize = 832;
                // 1600 - 2*384
                break;
            case 'sha3-512':
                $this->blockSize = 576;
                // 1600 - 2*512
                break;
            case 'shake128':
                $this->blockSize = 1344;
                // 1600 - 2*128
                break;
            default:
                $this->blockSize = 1024;
        }
        if (in_array(\Phabel\Target\Php80\Polyfill::substr($hash, 0, 5), ['sha3-', 'shake'])) {
            // PHP 7.1.0 introduced support for "SHA3 fixed mode algorithms":
            // http://php.net/ChangeLog-7.php#7.1.0
            if (version_compare(PHP_VERSION, '7.1.0') < 0 || \Phabel\Target\Php80\Polyfill::substr($hash, 0, 5) == 'shake') {
                //preg_match('#(\d+)$#', $hash, $matches);
                //$this->parameters['capacity'] = 2 * $matches[1]; // 1600 - $this->blockSize
                //$this->parameters['rate'] = 1600 - $this->parameters['capacity']; // == $this->blockSize
                if (!$this->paddingType) {
                    $this->paddingType = self::PADDING_SHA3;
                }
                $this->parameters = ['capacity' => 1600 - $this->blockSize, 'rate' => $this->blockSize, 'length' => $this->length, 'padding' => $this->paddingType];
                $hash = ['phpseclib3\\Crypt\\Hash', PHP_INT_SIZE == 8 ? 'sha3_64' : 'sha3_32'];
            }
        }
        if ($hash == 'sha512/224' || $hash == 'sha512/256') {
            // PHP 7.1.0 introduced sha512/224 and sha512/256 support:
            // http://php.net/ChangeLog-7.php#7.1.0
            if (version_compare(PHP_VERSION, '7.1.0') < 0) {
                // from http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf#page=24
                $initial = $hash == 'sha512/256' ? ['22312194FC2BF72C', '9F555FA3C84C64C2', '2393B86B6F53B151', '963877195940EABD', '96283EE2A88EFFE3', 'BE5E1E2553863992', '2B0199FC2C85B8AA', '0EB72DDC81C52CA2'] : ['8C3D37C819544DA2', '73E1996689DCD4D6', '1DFAB7AE32FF9C82', '679DD514582F9FCF', '0F6D2B697BD44DA8', '77E36F7304C48942', '3F9D85A86A1D36C8', '1112E6AD91D692A1'];
                for ($i = 0; $i < 8; $i++) {
                    $initial[$i] = new BigInteger($initial[$i], 16);
                    $initial[$i]->setPrecision(64);
                }
                $this->parameters = compact('initial');
                $hash = ['phpseclib3\\Crypt\\Hash', 'sha512'];
            }
        }
        if (is_array($hash)) {
            $b = $this->blockSize >> 3;
            $this->ipad = str_repeat(chr(0x36), $b);
            $this->opad = str_repeat(chr(0x5c), $b);
        }
        $this->algo = $hash;
        $this->computeKey();
    }
    /**
     * KDF: Key-Derivation Function
     *
     * The key-derivation function generates pseudorandom bits used to key the hash functions.
     *
     * @param int $index a non-negative integer less than 2^64
     * @param int $numbytes a non-negative integer less than 2^64
     * @return string string of length numbytes bytes
     */
    private function kdf($index, $numbytes)
    {
        $this->c->setIV(pack('N4', 0, $index, 0, 1));
        return $this->c->encrypt(str_repeat("\x00", $numbytes));
    }
    /**
     * PDF Algorithm
     *
     * @return string string of length taglen bytes.
     */
    private function pdf()
    {
        $k = $this->key;
        $nonce = $this->nonce;
        $taglen = $this->length;
        //
        // Extract and zero low bit(s) of Nonce if needed
        //
        if ($taglen <= 8) {
            $last = strlen($nonce) - 1;
            $mask = $taglen == 4 ? "\x03" : "\x01";
            $index = $nonce[$last] & $mask;
            $nonce[$last] = $nonce[$last] ^ $index;
        }
        //
        // Make Nonce BLOCKLEN bytes by appending zeroes if needed
        //
        $nonce = str_pad($nonce, 16, "\x00");
        //
        // Generate subkey, encipher and extract indexed substring
        //
        $kp = $this->kdf(0, 16);
        $c = new AES('ctr');
        $c->disablePadding();
        $c->setKey($kp);
        $c->setIV($nonce);
        $t = $c->encrypt("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
        // we could use ord() but per https://paragonie.com/blog/2016/06/constant-time-encoding-boring-cryptography-rfc-4648-and-you
        // unpack() doesn't leak timing info
        return $taglen <= 8 ? \Phabel\Target\Php80\Polyfill::substr($t, unpack('C', $index)[1] * $taglen, $taglen) : \Phabel\Target\Php80\Polyfill::substr($t, 0, $taglen);
    }
    /**
     * UHASH Algorithm
     *
     * @param string $m string of length less than 2^67 bits.
     * @param int $taglen the integer 4, 8, 12 or 16.
     * @return string string of length taglen bytes.
     */
    private function uhash($m, $taglen)
    {
        //
        // One internal iteration per 4 bytes of output
        //
        $iters = $taglen >> 2;
        //
        // Define total key needed for all iterations using KDF.
        // L1Key reuses most key material between iterations.
        //
        //$L1Key  = $this->kdf(1, 1024 + ($iters - 1) * 16);
        $L1Key = $this->kdf(1, (1024 + ($iters - 1)) * 16);
        $L2Key = $this->kdf(2, $iters * 24);
        $L3Key1 = $this->kdf(3, $iters * 64);
        $L3Key2 = $this->kdf(4, $iters * 4);
        //
        // For each iteration, extract key and do three-layer hash.
        // If bytelength(M) <= 1024, then skip L2-HASH.
        //
        $y = '';
        for ($i = 0; $i < $iters; $i++) {
            $L1Key_i = \Phabel\Target\Php80\Polyfill::substr($L1Key, $i * 16, 1024);
            $L2Key_i = \Phabel\Target\Php80\Polyfill::substr($L2Key, $i * 24, 24);
            $L3Key1_i = \Phabel\Target\Php80\Polyfill::substr($L3Key1, $i * 64, 64);
            $L3Key2_i = \Phabel\Target\Php80\Polyfill::substr($L3Key2, $i * 4, 4);
            $a = self::L1Hash($L1Key_i, $m);
            $b = strlen($m) <= 1024 ? "\x00\x00\x00\x00\x00\x00\x00\x00{$a}" : self::L2Hash($L2Key_i, $a);
            $c = self::L3Hash($L3Key1_i, $L3Key2_i, $b);
            $y .= $c;
        }
        return $y;
    }
    /**
    * L1-HASH Algorithm
    *
    * The first-layer hash breaks the message into 1024-byte chunks and
    hashes each with a function called NH.  Concatenating the results
    forms a string, which is up to 128 times shorter than the original.
    *
    * @param string $k string of length 1024 bytes.
    * @param string $m string of length less than 2^67 bits.
    * @return string string of length (8 * ceil(bitlength(M)/8192)) bytes.
    */
    private static function L1Hash($k, $m)
    {
        //
        // Break M into 1024 byte chunks (final chunk may be shorter)
        //
        $m = str_split($m, 1024);
        //
        // For each chunk, except the last: endian-adjust, NH hash
        // and add bit-length.  Use results to build Y.
        //
        $length = new BigInteger(1024 * 8);
        $y = '';
        for ($i = 0; $i < count($m) - 1; $i++) {
            $m[$i] = pack('N*', ...unpack('V*', $m[$i]));
            // ENDIAN-SWAP
            $y .= static::nh($k, $m[$i], $length);
        }
        //
        // For the last chunk: pad to 32-byte boundary, endian-adjust,
        // NH hash and add bit-length.  Concatenate the result to Y.
        //
        $length = strlen($m[$i]);
        $pad = 32 - $length % 32;
        $pad = max(32, $length + $pad % 32);
        $m[$i] = str_pad($m[$i], $pad, "\x00");
        // zeropad
        $m[$i] = pack('N*', ...unpack('V*', $m[$i]));
        // ENDIAN-SWAP
        $y .= static::nh($k, $m[$i], new BigInteger($length * 8));
        return $y;
    }
    /**
     * NH Algorithm
     *
     * @param string $k string of length 1024 bytes.
     * @param string $m string with length divisible by 32 bytes.
     * @return string string of length 8 bytes.
     */
    private static function nh($k, $m, $length)
    {
        $toUInt32 = function ($x) {
            $x = new BigInteger($x, 256);
            $x->setPrecision(32);
            return $x;
        };
        //
        // Break M and K into 4-byte chunks
        //
        //$t = strlen($m) >> 2;
        $m = str_split($m, 4);
        $t = count($m);
        $k = str_split($k, 4);
        $k = array_pad(array_slice($k, 0, $t), $t, 0);
        $m = array_map($toUInt32, $m);
        $k = array_map($toUInt32, $k);
        //
        // Perform NH hash on the chunks, pairing words for multiplication
        // which are 4 apart to accommodate vector-parallelism.
        //
        $y = new BigInteger();
        $y->setPrecision(64);
        $i = 0;
        while ($i < $t) {
            $temp = $m[$i]->add($k[$i]);
            $temp->setPrecision(64);
            $temp = $temp->multiply($m[$i + 4]->add($k[$i + 4]));
            $y = $y->add($temp);
            $temp = $m[$i + 1]->add($k[$i + 1]);
            $temp->setPrecision(64);
            $temp = $temp->multiply($m[$i + 5]->add($k[$i + 5]));
            $y = $y->add($temp);
            $temp = $m[$i + 2]->add($k[$i + 2]);
            $temp->setPrecision(64);
            $temp = $temp->multiply($m[$i + 6]->add($k[$i + 6]));
            $y = $y->add($temp);
            $temp = $m[$i + 3]->add($k[$i + 3]);
            $temp->setPrecision(64);
            $temp = $temp->multiply($m[$i + 7]->add($k[$i + 7]));
            $y = $y->add($temp);
            $i += 8;
        }
        return $y->add($length)->toBytes();
    }
    /**
    * L2-HASH: Second-Layer Hash
    *
    * The second-layer rehashes the L1-HASH output using a polynomial hash
    called POLY.  If the L1-HASH output is long, then POLY is called once
    on a prefix of the L1-HASH output and called using different settings
    on the remainder.  (This two-step hashing of the L1-HASH output is
    needed only if the message length is greater than 16 megabytes.)
    Careful implementation of POLY is necessary to avoid a possible
    timing attack (see Section 6.6 for more information).
    *
    * @param string $k string of length 24 bytes.
    * @param string $m string of length less than 2^64 bytes.
    * @return string string of length 16 bytes.
    */
    private static function L2Hash($k, $m)
    {
        //
        //  Extract keys and restrict to special key-sets
        //
        $k64 = $k & "\x01\xff\xff\xff\x01\xff\xff\xff";
        $k64 = new BigInteger($k64, 256);
        $k128 = \Phabel\Target\Php80\Polyfill::substr($k, 8) & "\x01\xff\xff\xff\x01\xff\xff\xff\x01\xff\xff\xff\x01\xff\xff\xff";
        $k128 = new BigInteger($k128, 256);
        //
        // If M is no more than 2^17 bytes, hash under 64-bit prime,
        // otherwise, hash first 2^17 bytes under 64-bit prime and
        // remainder under 128-bit prime.
        //
        if (strlen($m) <= 0x20000) {
            // 2^14 64-bit words
            $y = self::poly(64, self::$maxwordrange64, $k64, $m);
        } else {
            $m_1 = \Phabel\Target\Php80\Polyfill::substr($m, 0, 0x20000);
            // 1 << 17
            $m_2 = \Phabel\Target\Php80\Polyfill::substr($m, 0x20000) . "\x80";
            $length = strlen($m_2);
            $pad = 16 - $length % 16;
            $pad %= 16;
            $m_2 = str_pad($m_2, $length + $pad, "\x00");
            // zeropad
            $y = self::poly(64, self::$maxwordrange64, $k64, $m_1);
            $y = str_pad($y, 16, "\x00", STR_PAD_LEFT);
            $y = self::poly(128, self::$maxwordrange128, $k128, $y . $m_2);
        }
        return str_pad($y, 16, "\x00", STR_PAD_LEFT);
    }
    /**
     * POLY Algorithm
     *
     * @param int $wordbits the integer 64 or 128.
     * @param BigInteger $maxwordrange positive integer less than 2^wordbits.
     * @param BigInteger $k integer in the range 0 ... prime(wordbits) - 1.
     * @param string $m string with length divisible by (wordbits / 8) bytes.
     * @return integer in the range 0 ... prime(wordbits) - 1.
     */
    private static function poly($wordbits, $maxwordrange, $k, $m)
    {
        //
        // Define constants used for fixing out-of-range words
        //
        $wordbytes = $wordbits >> 3;
        if ($wordbits == 128) {
            $factory = self::$factory128;
            $offset = self::$offset128;
            $marker = self::$marker128;
        } else {
            $factory = self::$factory64;
            $offset = self::$offset64;
            $marker = self::$marker64;
        }
        $k = $factory->newInteger($k);
        //
        // Break M into chunks of length wordbytes bytes
        //
        $m_i = str_split($m, $wordbytes);
        //
        // Each input word m is compared with maxwordrange.  If not smaller
        // then 'marker' and (m - offset), both in range, are hashed.
        //
        $y = $factory->newInteger(new BigInteger(1));
        foreach ($m_i as $m) {
            $m = $factory->newInteger(new BigInteger($m, 256));
            if ($m->compare($maxwordrange) >= 0) {
                $y = $k->multiply($y)->add($marker);
                $y = $k->multiply($y)->add($m->subtract($offset));
            } else {
                $y = $k->multiply($y)->add($m);
            }
        }
        return $y->toBytes();
    }
    /**
    * L3-HASH: Third-Layer Hash
    *
    * The output from L2-HASH is 16 bytes long.  This final hash function
    hashes the 16-byte string to a fixed length of 4 bytes.
    *
    * @param string $k1 string of length 64 bytes.
    * @param string $k2 string of length 4 bytes.
    * @param string $m string of length 16 bytes.
    * @return string string of length 4 bytes.
    */
    private static function L3Hash($k1, $k2, $m)
    {
        $factory = self::$factory36;
        $y = $factory->newInteger(new BigInteger());
        for ($i = 0; $i < 8; $i++) {
            $m_i = $factory->newInteger(new BigInteger(\Phabel\Target\Php80\Polyfill::substr($m, 2 * $i, 2), 256));
            $k_i = $factory->newInteger(new BigInteger(\Phabel\Target\Php80\Polyfill::substr($k1, 8 * $i, 8), 256));
            $y = $y->add($m_i->multiply($k_i));
        }
        $y = str_pad(\Phabel\Target\Php80\Polyfill::substr($y->toBytes(), -4), 4, "\x00", STR_PAD_LEFT);
        $y = $y ^ $k2;
        return $y;
    }
    /**
     * Compute the Hash / HMAC / UMAC.
     *
     * @access public
     * @param string $text
     * @return string
     */
    public function hash($text)
    {
        $algo = $this->algo;
        if ($algo == 'umac') {
            if ($this->recomputeAESKey) {
                if (!is_string($this->nonce)) {
                    throw new InsufficientSetupException('No nonce has been set');
                }
                if (!is_string($this->key)) {
                    throw new InsufficientSetupException('No key has been set');
                }
                if (strlen($this->key) != 16) {
                    throw new \LengthException('Key must be 16 bytes long');
                }
                if (!isset(self::$maxwordrange64)) {
                    $one = new BigInteger(1);
                    $prime36 = new BigInteger("\x00\x00\x00\x0f\xff\xff\xff\xfb", 256);
                    self::$factory36 = new PrimeField($prime36);
                    $prime64 = new BigInteger("\xff\xff\xff\xff\xff\xff\xff\xc5", 256);
                    self::$factory64 = new PrimeField($prime64);
                    $prime128 = new BigInteger("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xffa", 256);
                    self::$factory128 = new PrimeField($prime128);
                    self::$offset64 = new BigInteger("\x01\x00\x00\x00\x00\x00\x00\x00\x00", 256);
                    self::$offset64 = self::$factory64->newInteger(self::$offset64->subtract($prime64));
                    self::$offset128 = new BigInteger("\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 256);
                    self::$offset128 = self::$factory128->newInteger(self::$offset128->subtract($prime128));
                    self::$marker64 = self::$factory64->newInteger($prime64->subtract($one));
                    self::$marker128 = self::$factory128->newInteger($prime128->subtract($one));
                    $maxwordrange64 = $one->bitwise_leftShift(64)->subtract($one->bitwise_leftShift(32));
                    self::$maxwordrange64 = self::$factory64->newInteger($maxwordrange64);
                    $maxwordrange128 = $one->bitwise_leftShift(128)->subtract($one->bitwise_leftShift(96));
                    self::$maxwordrange128 = self::$factory128->newInteger($maxwordrange128);
                }
                $this->c = new AES('ctr');
                $this->c->disablePadding();
                $this->c->setKey($this->key);
                $this->pad = $this->pdf();
                $this->recomputeAESKey = false;
            }
            $hashedmessage = $this->uhash($text, $this->length);
            return $hashedmessage ^ $this->pad;
        }
        if (is_array($algo)) {
            if (empty($this->key) || !is_string($this->key)) {
                return \Phabel\Target\Php80\Polyfill::substr($algo($text, ...array_values($this->parameters)), 0, $this->length);
            }
            // SHA3 HMACs are discussed at https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=30
            $key = str_pad($this->computedKey, $b, chr(0));
            $temp = $this->ipad ^ $key;
            $temp .= $text;
            $temp = \Phabel\Target\Php80\Polyfill::substr($algo($temp, ...array_values($this->parameters)), 0, $this->length);
            $output = $this->opad ^ $key;
            $output .= $temp;
            $output = $algo($output, ...array_values($this->parameters));
            return \Phabel\Target\Php80\Polyfill::substr($output, 0, $this->length);
        }
        $output = !empty($this->key) || is_string($this->key) ? hash_hmac($algo, $text, $this->computedKey, true) : hash($algo, $text, true);
        return strlen($output) > $this->length ? \Phabel\Target\Php80\Polyfill::substr($output, 0, $this->length) : $output;
    }
    /**
     * Returns the hash length (in bits)
     *
     * @access public
     * @return int
     */
    public function getLength()
    {
        return $this->length << 3;
    }
    /**
     * Returns the hash length (in bytes)
     *
     * @access public
     * @return int
     */
    public function getLengthInBytes()
    {
        return $this->length;
    }
    /**
     * Returns the block length (in bits)
     *
     * @access public
     * @return int
     */
    public function getBlockLength()
    {
        return $this->blockSize;
    }
    /**
     * Returns the block length (in bytes)
     *
     * @access public
     * @return int
     */
    public function getBlockLengthInBytes()
    {
        return $this->blockSize >> 3;
    }
    /**
     * Pads SHA3 based on the mode
     *
     * @access private
     * @param int $padLength
     * @param int $padType
     * @return string
     */
    private static function sha3_pad($padLength, $padType)
    {
        switch ($padType) {
            //case self::PADDING_KECCAK:
            //    $temp = chr(0x06) . str_repeat("\0", $padLength - 1);
            //    $temp[$padLength - 1] = $temp[$padLength - 1] | chr(0x80);
            //    return $temp
            case self::PADDING_SHAKE:
                $temp = chr(0x1f) . str_repeat("\x00", $padLength - 1);
                $temp[$padLength - 1] = $temp[$padLength - 1] | chr(0x80);
                return $temp;
            //case self::PADDING_SHA3:
            default:
                // from https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf#page=36
                return $padLength == 1 ? chr(0x86) : chr(0x6) . str_repeat("\x00", $padLength - 2) . chr(0x80);
        }
    }
    /**
    * Pure-PHP 32-bit implementation of SHA3
    *
    * Whereas BigInteger.php's 32-bit engine works on PHP 64-bit this 32-bit implementation
    of SHA3 will *not* work on PHP 64-bit. This is because this implementation
    employees bitwise NOTs and bitwise left shifts. And the round constants only work
    on 32-bit PHP. eg. dechex(-2147483648) returns 80000000 on 32-bit PHP and
    FFFFFFFF80000000 on 64-bit PHP. Sure, we could do bitwise ANDs but that would slow
    things down.
    *
    * SHA512 requires BigInteger to simulate 64-bit unsigned integers because SHA2 employees
    addition whereas SHA3 just employees bitwise operators. PHP64 only supports signed
    64-bit integers, which complicates addition, whereas that limitation isn't an issue
    for SHA3.
    *
    * In https://ws680.nist.gov/publication/get_pdf.cfm?pub_id=919061#page=16 KECCAK[C] is
    defined as "the KECCAK instance with KECCAK-f[1600] as the underlying permutation and
    capacity c". This is relevant because, altho the KECCAK standard defines a mode
    (KECCAK-f[800]) designed for 32-bit machines that mode is incompatible with SHA3
    *
    * @access private
    * @param string $p
    * @param int $c
    * @param int $r
    * @param int $d
    * @param int $padType
    */
    private static function sha3_32($p, $c, $r, $d, $padType)
    {
        $block_size = $r >> 3;
        $padLength = $block_size - strlen($p) % $block_size;
        $num_ints = $block_size >> 2;
        $p .= static::sha3_pad($padLength, $padType);
        $n = strlen($p) / $r;
        // number of blocks
        $s = [[[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], [[0, 0], [0, 0], [0, 0], [0, 0], [0, 0]]];
        $p = str_split($p, $block_size);
        foreach ($p as $pi) {
            $pi = unpack('V*', $pi);
            $x = $y = 0;
            for ($i = 1; $i <= $num_ints; $i += 2) {
                $s[$x][$y][0] ^= $pi[$i + 1];
                $s[$x][$y][1] ^= $pi[$i];
                if (++$y == 5) {
                    $y = 0;
                    $x++;
                }
            }
            static::processSHA3Block32($s);
        }
        $z = '';
        $i = $j = 0;
        while (strlen($z) < $d) {
            $z .= pack('V2', $s[$i][$j][1], $s[$i][$j++][0]);
            if ($j == 5) {
                $j = 0;
                $i++;
                if ($i == 5) {
                    $i = 0;
                    static::processSHA3Block32($s);
                }
            }
        }
        return $z;
    }
    /**
     * 32-bit block processing method for SHA3
     *
     * @access private
     * @param array $s
     */
    private static function processSHA3Block32(&$s)
    {
        static $rotationOffsets = [[0, 1, 62, 28, 27], [36, 44, 6, 55, 20], [3, 10, 43, 25, 39], [41, 45, 15, 21, 8], [18, 2, 61, 56, 14]];
        // the standards give these constants in hexadecimal notation. it's tempting to want to use
        // that same notation, here, however, we can't, because 0x80000000, on PHP32, is a positive
        // float - not the negative int that we need to be in PHP32. so we use -2147483648 instead
        static $roundConstants = [[0, 1], [0, 32898], [-2147483648, 32906], [-2147483648, -2147450880], [0, 32907], [0, -2147483647], [-2147483648, -2147450751], [-2147483648, 32777], [0, 138], [0, 136], [0, -2147450871], [0, -2147483638], [0, -2147450741], [-2147483648, 139], [-2147483648, 32905], [-2147483648, 32771], [-2147483648, 32770], [-2147483648, 128], [0, 32778], [-2147483648, -2147483638], [-2147483648, -2147450751], [-2147483648, 32896], [0, -2147483647], [-2147483648, -2147450872]];
        for ($round = 0; $round < 24; $round++) {
            // theta step
            $parity = $rotated = [];
            for ($i = 0; $i < 5; $i++) {
                $parity[] = [$s[0][$i][0] ^ $s[1][$i][0] ^ $s[2][$i][0] ^ $s[3][$i][0] ^ $s[4][$i][0], $s[0][$i][1] ^ $s[1][$i][1] ^ $s[2][$i][1] ^ $s[3][$i][1] ^ $s[4][$i][1]];
                $rotated[] = static::rotateLeft32($parity[$i], 1);
            }
            $temp = [[$parity[4][0] ^ $rotated[1][0], $parity[4][1] ^ $rotated[1][1]], [$parity[0][0] ^ $rotated[2][0], $parity[0][1] ^ $rotated[2][1]], [$parity[1][0] ^ $rotated[3][0], $parity[1][1] ^ $rotated[3][1]], [$parity[2][0] ^ $rotated[4][0], $parity[2][1] ^ $rotated[4][1]], [$parity[3][0] ^ $rotated[0][0], $parity[3][1] ^ $rotated[0][1]]];
            for ($i = 0; $i < 5; $i++) {
                for ($j = 0; $j < 5; $j++) {
                    $s[$i][$j][0] ^= $temp[$j][0];
                    $s[$i][$j][1] ^= $temp[$j][1];
                }
            }
            $st = $s;
            // rho and pi steps
            for ($i = 0; $i < 5; $i++) {
                for ($j = 0; $j < 5; $j++) {
                    $st[(2 * $i + 3 * $j) % 5][$j] = static::rotateLeft32($s[$j][$i], $rotationOffsets[$j][$i]);
                }
            }
            // chi step
            for ($i = 0; $i < 5; $i++) {
                $s[$i][0] = [$st[$i][0][0] ^ ~$st[$i][1][0] & $st[$i][2][0], $st[$i][0][1] ^ ~$st[$i][1][1] & $st[$i][2][1]];
                $s[$i][1] = [$st[$i][1][0] ^ ~$st[$i][2][0] & $st[$i][3][0], $st[$i][1][1] ^ ~$st[$i][2][1] & $st[$i][3][1]];
                $s[$i][2] = [$st[$i][2][0] ^ ~$st[$i][3][0] & $st[$i][4][0], $st[$i][2][1] ^ ~$st[$i][3][1] & $st[$i][4][1]];
                $s[$i][3] = [$st[$i][3][0] ^ ~$st[$i][4][0] & $st[$i][0][0], $st[$i][3][1] ^ ~$st[$i][4][1] & $st[$i][0][1]];
                $s[$i][4] = [$st[$i][4][0] ^ ~$st[$i][0][0] & $st[$i][1][0], $st[$i][4][1] ^ ~$st[$i][0][1] & $st[$i][1][1]];
            }
            // iota step
            $s[0][0][0] ^= $roundConstants[$round][0];
            $s[0][0][1] ^= $roundConstants[$round][1];
        }
    }
    /**
     * Rotate 32-bit int
     *
     * @access private
     * @param array $x
     * @param int $shift
     */
    private static function rotateLeft32($x, $shift)
    {
        if ($shift < 32) {
            list($hi, $lo) = $x;
        } else {
            $shift -= 32;
            list($lo, $hi) = $x;
        }
        return [$hi << $shift | $lo >> 32 - $shift & (1 << $shift) - 1, $lo << $shift | $hi >> 32 - $shift & (1 << $shift) - 1];
    }
    /**
     * Pure-PHP 64-bit implementation of SHA3
     *
     * @access private
     * @param string $p
     * @param int $c
     * @param int $r
     * @param int $d
     * @param int $padType
     */
    private static function sha3_64($p, $c, $r, $d, $padType)
    {
        $block_size = $r >> 3;
        $padLength = $block_size - strlen($p) % $block_size;
        $num_ints = $block_size >> 2;
        $p .= static::sha3_pad($padLength, $padType);
        $n = strlen($p) / $r;
        // number of blocks
        $s = [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]];
        $p = str_split($p, $block_size);
        foreach ($p as $pi) {
            $pi = unpack('P*', $pi);
            $x = $y = 0;
            foreach ($pi as $subpi) {
                $s[$x][$y++] ^= $subpi;
                if ($y == 5) {
                    $y = 0;
                    $x++;
                }
            }
            static::processSHA3Block64($s);
        }
        $z = '';
        $i = $j = 0;
        while (strlen($z) < $d) {
            $z .= pack('P', $s[$i][$j++]);
            if ($j == 5) {
                $j = 0;
                $i++;
                if ($i == 5) {
                    $i = 0;
                    static::processSHA3Block64($s);
                }
            }
        }
        return $z;
    }
    /**
     * 64-bit block processing method for SHA3
     *
     * @access private
     * @param array $s
     */
    private static function processSHA3Block64(&$s)
    {
        static $rotationOffsets = [[0, 1, 62, 28, 27], [36, 44, 6, 55, 20], [3, 10, 43, 25, 39], [41, 45, 15, 21, 8], [18, 2, 61, 56, 14]];
        static $roundConstants = [1, 32898, -9223372036854742902, -9223372034707259392, 32907, 2147483649, -9223372034707259263, -9223372036854743031, 138, 136, 2147516425, 2147483658, 2147516555, -9223372036854775669, -9223372036854742903, -9223372036854743037, -9223372036854743038, -9223372036854775680, 32778, -9223372034707292150, -9223372034707259263, -9223372036854742912, 2147483649, -9223372034707259384];
        for ($round = 0; $round < 24; $round++) {
            // theta step
            $parity = [];
            for ($i = 0; $i < 5; $i++) {
                $parity[] = $s[0][$i] ^ $s[1][$i] ^ $s[2][$i] ^ $s[3][$i] ^ $s[4][$i];
            }
            $temp = [$parity[4] ^ static::rotateLeft64($parity[1], 1), $parity[0] ^ static::rotateLeft64($parity[2], 1), $parity[1] ^ static::rotateLeft64($parity[3], 1), $parity[2] ^ static::rotateLeft64($parity[4], 1), $parity[3] ^ static::rotateLeft64($parity[0], 1)];
            for ($i = 0; $i < 5; $i++) {
                for ($j = 0; $j < 5; $j++) {
                    $s[$i][$j] ^= $temp[$j];
                }
            }
            $st = $s;
            // rho and pi steps
            for ($i = 0; $i < 5; $i++) {
                for ($j = 0; $j < 5; $j++) {
                    $st[(2 * $i + 3 * $j) % 5][$j] = static::rotateLeft64($s[$j][$i], $rotationOffsets[$j][$i]);
                }
            }
            // chi step
            for ($i = 0; $i < 5; $i++) {
                $s[$i] = [$st[$i][0] ^ ~$st[$i][1] & $st[$i][2], $st[$i][1] ^ ~$st[$i][2] & $st[$i][3], $st[$i][2] ^ ~$st[$i][3] & $st[$i][4], $st[$i][3] ^ ~$st[$i][4] & $st[$i][0], $st[$i][4] ^ ~$st[$i][0] & $st[$i][1]];
            }
            // iota step
            $s[0][0] ^= $roundConstants[$round];
        }
    }
    /**
     * Rotate 64-bit int
     *
     * @access private
     * @param int $x
     * @param int $shift
     */
    private static function rotateLeft64($x, $shift)
    {
        return $x << $shift | $x >> 64 - $shift & (1 << $shift) - 1;
    }
    /**
     * Pure-PHP implementation of SHA512
     *
     * @access private
     * @param string $m
     * @param array $hash
     * @return string
     */
    private static function sha512($m, $hash)
    {
        static $k;
        if (!isset($k)) {
            // Initialize table of round constants
            // (first 64 bits of the fractional parts of the cube roots of the first 80 primes 2..409)
            $k = ['428a2f98d728ae22', '7137449123ef65cd', 'b5c0fbcfec4d3b2f', 'e9b5dba58189dbbc', '3956c25bf348b538', '59f111f1b605d019', '923f82a4af194f9b', 'ab1c5ed5da6d8118', 'd807aa98a3030242', '12835b0145706fbe', '243185be4ee4b28c', '550c7dc3d5ffb4e2', '72be5d74f27b896f', '80deb1fe3b1696b1', '9bdc06a725c71235', 'c19bf174cf692694', 'e49b69c19ef14ad2', 'efbe4786384f25e3', '0fc19dc68b8cd5b5', '240ca1cc77ac9c65', '2de92c6f592b0275', '4a7484aa6ea6e483', '5cb0a9dcbd41fbd4', '76f988da831153b5', '983e5152ee66dfab', 'a831c66d2db43210', 'b00327c898fb213f', 'bf597fc7beef0ee4', 'c6e00bf33da88fc2', 'd5a79147930aa725', '06ca6351e003826f', '142929670a0e6e70', '27b70a8546d22ffc', '2e1b21385c26c926', '4d2c6dfc5ac42aed', '53380d139d95b3df', '650a73548baf63de', '766a0abb3c77b2a8', '81c2c92e47edaee6', '92722c851482353b', 'a2bfe8a14cf10364', 'a81a664bbc423001', 'c24b8b70d0f89791', 'c76c51a30654be30', 'd192e819d6ef5218', 'd69906245565a910', 'f40e35855771202a', '106aa07032bbd1b8', '19a4c116b8d2d0c8', '1e376c085141ab53', '2748774cdf8eeb99', '34b0bcb5e19b48a8', '391c0cb3c5c95a63', '4ed8aa4ae3418acb', '5b9cca4f7763e373', '682e6ff3d6b2b8a3', '748f82ee5defb2fc', '78a5636f43172f60', '84c87814a1f0ab72', '8cc702081a6439ec', '90befffa23631e28', 'a4506cebde82bde9', 'bef9a3f7b2c67915', 'c67178f2e372532b', 'ca273eceea26619c', 'd186b8c721c0c207', 'eada7dd6cde0eb1e', 'f57d4f7fee6ed178', '06f067aa72176fba', '0a637dc5a2c898a6', '113f9804bef90dae', '1b710b35131c471b', '28db77f523047d84', '32caab7b40c72493', '3c9ebe0a15c9bebc', '431d67c49c100d4c', '4cc5d4becb3e42b6', '597f299cfc657e2a', '5fcb6fab3ad6faec', '6c44198c4a475817'];
            for ($i = 0; $i < 80; $i++) {
                $k[$i] = new BigInteger($k[$i], 16);
            }
        }
        // Pre-processing
        $length = strlen($m);
        // to round to nearest 112 mod 128, we'll add 128 - (length + (128 - 112)) % 128
        $m .= str_repeat(chr(0), 128 - ($length + 16 & 0x7f));
        $m[$length] = chr(0x80);
        // we don't support hashing strings 512MB long
        $m .= pack('N4', 0, 0, 0, $length << 3);
        // Process the message in successive 1024-bit chunks
        $chunks = str_split($m, 128);
        foreach ($chunks as $chunk) {
            $w = [];
            for ($i = 0; $i < 16; $i++) {
                $temp = new BigInteger(Strings::shift($chunk, 8), 256);
                $temp->setPrecision(64);
                $w[] = $temp;
            }
            // Extend the sixteen 32-bit words into eighty 32-bit words
            for ($i = 16; $i < 80; $i++) {
                $temp = [$w[$i - 15]->bitwise_rightRotate(1), $w[$i - 15]->bitwise_rightRotate(8), $w[$i - 15]->bitwise_rightShift(7)];
                $s0 = $temp[0]->bitwise_xor($temp[1]);
                $s0 = $s0->bitwise_xor($temp[2]);
                $temp = [$w[$i - 2]->bitwise_rightRotate(19), $w[$i - 2]->bitwise_rightRotate(61), $w[$i - 2]->bitwise_rightShift(6)];
                $s1 = $temp[0]->bitwise_xor($temp[1]);
                $s1 = $s1->bitwise_xor($temp[2]);
                $w[$i] = clone $w[$i - 16];
                $w[$i] = $w[$i]->add($s0);
                $w[$i] = $w[$i]->add($w[$i - 7]);
                $w[$i] = $w[$i]->add($s1);
            }
            // Initialize hash value for this chunk
            $a = clone $hash[0];
            $b = clone $hash[1];
            $c = clone $hash[2];
            $d = clone $hash[3];
            $e = clone $hash[4];
            $f = clone $hash[5];
            $g = clone $hash[6];
            $h = clone $hash[7];
            // Main loop
            for ($i = 0; $i < 80; $i++) {
                $temp = [$a->bitwise_rightRotate(28), $a->bitwise_rightRotate(34), $a->bitwise_rightRotate(39)];
                $s0 = $temp[0]->bitwise_xor($temp[1]);
                $s0 = $s0->bitwise_xor($temp[2]);
                $temp = [$a->bitwise_and($b), $a->bitwise_and($c), $b->bitwise_and($c)];
                $maj = $temp[0]->bitwise_xor($temp[1]);
                $maj = $maj->bitwise_xor($temp[2]);
                $t2 = $s0->add($maj);
                $temp = [$e->bitwise_rightRotate(14), $e->bitwise_rightRotate(18), $e->bitwise_rightRotate(41)];
                $s1 = $temp[0]->bitwise_xor($temp[1]);
                $s1 = $s1->bitwise_xor($temp[2]);
                $temp = [$e->bitwise_and($f), $g->bitwise_and($e->bitwise_not())];
                $ch = $temp[0]->bitwise_xor($temp[1]);
                $t1 = $h->add($s1);
                $t1 = $t1->add($ch);
                $t1 = $t1->add($k[$i]);
                $t1 = $t1->add($w[$i]);
                $h = clone $g;
                $g = clone $f;
                $f = clone $e;
                $e = $d->add($t1);
                $d = clone $c;
                $c = clone $b;
                $b = clone $a;
                $a = $t1->add($t2);
            }
            // Add this chunk's hash to result so far
            $hash = [$hash[0]->add($a), $hash[1]->add($b), $hash[2]->add($c), $hash[3]->add($d), $hash[4]->add($e), $hash[5]->add($f), $hash[6]->add($g), $hash[7]->add($h)];
        }
        // Produce the final hash value (big-endian)
        // (\phpseclib3\Crypt\Hash::hash() trims the output for hashes but not for HMACs.  as such, we trim the output here)
        $temp = $hash[0]->toBytes() . $hash[1]->toBytes() . $hash[2]->toBytes() . $hash[3]->toBytes() . $hash[4]->toBytes() . $hash[5]->toBytes() . $hash[6]->toBytes() . $hash[7]->toBytes();
        return $temp;
    }
    /**
     * __toString() magic method
     */
    public function __toString()
    {
        return $this->getHash();
    }
}<?php

/**
 * Pure-PHP implementation of EC.
 *
 * PHP version 5
 *
 * Here's an example of how to create signatures and verify signatures with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $private = \phpseclib3\Crypt\EC::createKey('secp256k1');
 * $public = $private->getPublicKey();
 *
 * $plaintext = 'terrafrost';
 *
 * $signature = $private->sign($plaintext);
 *
 * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\EC\PrivateKey;
use phpseclib3\Crypt\EC\PublicKey;
use phpseclib3\Crypt\EC\Parameters;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Crypt\EC\Curves\Ed448;
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
use phpseclib3\File\ASN1\Maps\ECParameters;
use phpseclib3\File\ASN1;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Exception\UnsupportedOperationException;
/**
 * Pure-PHP implementation of EC.
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EC extends AsymmetricKey
{
    /**
     * Algorithm Name
     *
     * @var string
     * @access private
     */
    const ALGORITHM = 'EC';
    /**
     * Public Key QA
     *
     * @var object[]
     */
    protected $QA;
    /**
     * Curve
     *
     * @var \phpseclib3\Crypt\EC\BaseCurves\Base
     */
    protected $curve;
    /**
     * Signature Format
     *
     * @var string
     * @access private
     */
    protected $format;
    /**
     * Signature Format (Short)
     *
     * @var string
     * @access private
     */
    protected $shortFormat;
    /**
     * Curve Name
     *
     * @var string
     */
    private $curveName;
    /**
     * Curve Order
     *
     * Used for deterministic ECDSA
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected $q;
    /**
     * Alias for the private key
     *
     * Used for deterministic ECDSA. AsymmetricKey expects $x. I don't like x because
     * with x you have x * the base point yielding an (x, y)-coordinate that is the
     * public key. But the x is different depending on which side of the equal sign
     * you're on. It's less ambiguous if you do dA * base point = (x, y)-coordinate.
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected $x;
    /**
     * Context
     *
     * @var string
     */
    protected $context;
    /**
     * Create public / private key pair.
     *
     * @access public
     * @param string $curve
     * @return \phpseclib3\Crypt\EC\PrivateKey
     */
    public static function createKey($curve)
    {
        self::initialize_static_variables();
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        $curve = strtolower($curve);
        if (self::$engines['libsodium'] && $curve == 'ed25519' && function_exists('sodium_crypto_sign_keypair')) {
            $kp = sodium_crypto_sign_keypair();
            $privatekey = EC::loadFormat('libsodium', sodium_crypto_sign_secretkey($kp));
            //$publickey = EC::loadFormat('libsodium', sodium_crypto_sign_publickey($kp));
            $privatekey->curveName = 'Ed25519';
            //$publickey->curveName = $curve;
            return $privatekey;
        }
        $privatekey = new PrivateKey();
        $curveName = $curve;
        if (preg_match('#(?:^curve|^ed)\\d+$#', $curveName)) {
            $curveName = ucfirst($curveName);
        } elseif (\Phabel\Target\Php80\Polyfill::substr($curveName, 0, 10) == 'brainpoolp') {
            $curveName = 'brainpoolP' . \Phabel\Target\Php80\Polyfill::substr($curveName, 10);
        }
        $curve = '\\phpseclib3\\Crypt\\EC\\Curves\\' . $curveName;
        if (!class_exists($curve)) {
            throw new UnsupportedCurveException('Named Curve of ' . $curveName . ' is not supported');
        }
        $reflect = new \ReflectionClass($curve);
        $curveName = $reflect->isFinal() ? $reflect->getParentClass()->getShortName() : $reflect->getShortName();
        $curve = new $curve();
        $privatekey->dA = $dA = $curve->createRandomMultiplier();
        if ($curve instanceof Curve25519 && self::$engines['libsodium']) {
            //$r = pack('H*', '0900000000000000000000000000000000000000000000000000000000000000');
            //$QA = sodium_crypto_scalarmult($dA->toBytes(), $r);
            $QA = sodium_crypto_box_publickey_from_secretkey($dA->toBytes());
            $privatekey->QA = [$curve->convertInteger(new BigInteger(strrev($QA), 256))];
        } else {
            $privatekey->QA = $curve->multiplyPoint($curve->getBasePoint(), $dA);
        }
        $privatekey->curve = $curve;
        //$publickey = clone $privatekey;
        //unset($publickey->dA);
        //unset($publickey->x);
        $privatekey->curveName = $curveName;
        //$publickey->curveName = $curveName;
        if ($privatekey->curve instanceof TwistedEdwardsCurve) {
            return $privatekey->withHash($curve::HASH);
        }
        return $privatekey;
    }
    /**
     * OnLoad Handler
     *
     * @return bool
     * @access protected
     * @param array $components
     */
    protected static function onLoad($components)
    {
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        if (!isset($components['dA']) && !isset($components['QA'])) {
            $new = new Parameters();
            $new->curve = $components['curve'];
            return $new;
        }
        $new = isset($components['dA']) ? new PrivateKey() : new PublicKey();
        $new->curve = $components['curve'];
        $new->QA = $components['QA'];
        if (isset($components['dA'])) {
            $new->dA = $components['dA'];
        }
        if ($new->curve instanceof TwistedEdwardsCurve) {
            return $new->withHash($components['curve']::HASH);
        }
        return $new;
    }
    /**
     * Constructor
     *
     * PublicKey and PrivateKey objects can only be created from abstract RSA class
     */
    protected function __construct()
    {
        $this->sigFormat = self::validatePlugin('Signature', 'ASN1');
        $this->shortFormat = 'ASN1';
        parent::__construct();
    }
    /**
     * Returns the curve
     *
     * Returns a string if it's a named curve, an array if not
     *
     * @access public
     * @return (string | array)
     */
    public function getCurve()
    {
        if ($this->curveName) {
            return $this->curveName;
        }
        if ($this->curve instanceof MontgomeryCurve) {
            $this->curveName = $this->curve instanceof Curve25519 ? 'Curve25519' : 'Curve448';
            return $this->curveName;
        }
        if ($this->curve instanceof TwistedEdwardsCurve) {
            $this->curveName = $this->curve instanceof Ed25519 ? 'Ed25519' : 'Ed448';
            return $this->curveName;
        }
        $params = $this->getParameters()->toString('PKCS8', ['namedCurve' => true]);
        $decoded = ASN1::extractBER($params);
        $decoded = ASN1::decodeBER($decoded);
        $decoded = ASN1::asn1map($decoded[0], ECParameters::MAP);
        if (isset($decoded['namedCurve'])) {
            $this->curveName = $decoded['namedCurve'];
            return $decoded['namedCurve'];
        }
        if (!$namedCurves) {
            PKCS1::useSpecifiedCurve();
        }
        return $decoded;
    }
    /**
    * Returns the key size
    *
    * Quoting https://tools.ietf.org/html/rfc5656#section-2,
    *
    * "The size of a set of elliptic curve domain parameters on a prime
    curve is defined as the number of bits in the binary representation
    of the field order, commonly denoted by p.  Size on a
    characteristic-2 curve is defined as the number of bits in the binary
    representation of the field, commonly denoted by m.  A set of
    elliptic curve domain parameters defines a group of order n generated
    by a base point P"
    *
    * @access public
    * @return int
    */
    public function getLength()
    {
        return $this->curve->getLength();
    }
    /**
     * Returns the current engine being used
     *
     * @see self::useInternalEngine()
     * @see self::useBestEngine()
     * @access public
     * @return string
     */
    public function getEngine()
    {
        if ($this->curve instanceof TwistedEdwardsCurve) {
            return $this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context) ? 'libsodium' : 'PHP';
        }
        return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ? 'OpenSSL' : 'PHP';
    }
    /**
     * Returns the public key coordinates as a string
     *
     * Used by ECDH
     *
     * @return string
     */
    public function getEncodedCoordinates()
    {
        if ($this->curve instanceof MontgomeryCurve) {
            return strrev($this->QA[0]->toBytes(true));
        }
        if ($this->curve instanceof TwistedEdwardsCurve) {
            return $this->curve->encodePoint($this->QA);
        }
        return "\x04" . $this->QA[0]->toBytes(true) . $this->QA[1]->toBytes(true);
    }
    /**
     * Returns the parameters
     *
     * @see self::getPublicKey()
     * @access public
     * @param string $type optional
     * @return mixed
     */
    public function getParameters($type = 'PKCS1')
    {
        $type = self::validatePlugin('Keys', $type, 'saveParameters');
        $key = $type::saveParameters($this->curve);
        return EC::load($key, 'PKCS1')->withHash($this->hash->getHash())->withSignatureFormat($this->shortFormat);
    }
    /**
     * Determines the signature padding mode
     *
     * Valid values are: ASN1, SSH2, Raw
     *
     * @access public
     * @param string $format
     */
    public function withSignatureFormat($format)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
        }
        $new = clone $this;
        $new->shortFormat = $format;
        $new->sigFormat = self::validatePlugin('Signature', $format);
        return $new;
    }
    /**
     * Returns the signature format currently being used
     *
     * @access public
     */
    public function getSignatureFormat()
    {
        return $this->shortFormat;
    }
    /**
     * Sets the context
     *
     * Used by Ed25519 / Ed448.
     *
     * @see self::sign()
     * @see self::verify()
     * @access public
     * @param string $context optional
     */
    public function withContext($context = null)
    {
        if (!$this->curve instanceof TwistedEdwardsCurve) {
            throw new UnsupportedCurveException('Only Ed25519 and Ed448 support contexts');
        }
        $new = clone $this;
        if (!isset($context)) {
            $new->context = null;
            return $new;
        }
        if (!is_string($context)) {
            throw new \InvalidArgumentException('setContext expects a string');
        }
        if (strlen($context) > 255) {
            throw new \LengthException('The context is supposed to be, at most, 255 bytes long');
        }
        $new->context = $context;
        return $new;
    }
    /**
     * Returns the signature format currently being used
     *
     * @access public
     */
    public function getContext()
    {
        return $this->context;
    }
    /**
     * Determines which hashing function should be used
     *
     * @access public
     * @param string $hash
     */
    public function withHash($hash)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
        }
        if ($this->curve instanceof Ed25519 && $hash != 'sha512') {
            throw new UnsupportedAlgorithmException('Ed25519 only supports sha512 as a hash');
        }
        if ($this->curve instanceof Ed448 && $hash != 'shake256-912') {
            throw new UnsupportedAlgorithmException('Ed448 only supports shake256 with a length of 114 bytes');
        }
        return parent::withHash($hash);
    }
    /**
     * __toString() magic method
     *
     * @return string
     */
    public function __toString()
    {
        if ($this->curve instanceof MontgomeryCurve) {
            return '';
        }
        return parent::__toString();
    }
}<?php

/**
 * Pure-PHP PKCS#1 (v2.1) compliant implementation of RSA.
 *
 * PHP version 5
 *
 * Here's an example of how to encrypt and decrypt text with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $private = \phpseclib3\Crypt\RSA::createKey();
 * $public = $private->getPublicKey();
 *
 * $plaintext = 'terrafrost';
 *
 * $ciphertext = $public->encrypt($plaintext);
 *
 * echo $private->decrypt($ciphertext);
 * ?>
 * </code>
 *
 * Here's an example of how to create signatures and verify signatures with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $private = \phpseclib3\Crypt\RSA::createKey();
 * $public = $private->getPublicKey();
 *
 * $plaintext = 'terrafrost';
 *
 * $signature = $private->sign($plaintext);
 *
 * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
 * ?>
 * </code>
 *
 * One thing to consider when using this: so phpseclib uses PSS mode by default.
 * Technically, id-RSASSA-PSS has a different key format than rsaEncryption. So
 * should phpseclib save to the id-RSASSA-PSS format by default or the
 * rsaEncryption format? For stand-alone keys I figure rsaEncryption is better
 * because SSH doesn't use PSS and idk how many SSH servers would be able to
 * decode an id-RSASSA-PSS key. For X.509 certificates the id-RSASSA-PSS
 * format is used by default (unless you change it up to use PKCS1 instead)
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\RSA\PrivateKey;
use phpseclib3\Crypt\RSA\PublicKey;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Exception\InconsistentSetupException;
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
/**
 * Pure-PHP PKCS#1 compliant implementation of RSA.
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RSA extends AsymmetricKey
{
    /**
     * Algorithm Name
     *
     * @var string
     * @access private
     */
    const ALGORITHM = 'RSA';
    /**
     * Use {@link http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding Optimal Asymmetric Encryption Padding}
     * (OAEP) for encryption / decryption.
     *
     * Uses sha256 by default
     *
     * @see self::setHash()
     * @see self::setMGFHash()
     * @access public
     * @see self::encrypt()
     * @see self::decrypt()
     */
    const ENCRYPTION_OAEP = 1;
    /**
     * Use PKCS#1 padding.
     *
     * Although self::PADDING_OAEP / self::PADDING_PSS  offers more security, including PKCS#1 padding is necessary for purposes of backwards
     * compatibility with protocols (like SSH-1) written before OAEP's introduction.
     *
     * @access public
     * @see self::encrypt()
     * @see self::decrypt()
     */
    const ENCRYPTION_PKCS1 = 2;
    /**
     * Do not use any padding
     *
     * Although this method is not recommended it can none-the-less sometimes be useful if you're trying to decrypt some legacy
     * stuff, if you're trying to diagnose why an encrypted message isn't decrypting, etc.
     *
     * @access public
     * @see self::encrypt()
     * @see self::decrypt()
     */
    const ENCRYPTION_NONE = 4;
    /**
     * Use the Probabilistic Signature Scheme for signing
     *
     * Uses sha256 and 0 as the salt length
     *
     * @see self::setSaltLength()
     * @see self::setMGFHash()
     * @see self::setHash()
     * @see self::sign()
     * @see self::verify()
     * @see self::setHash()
     * @access public
     */
    const SIGNATURE_PSS = 16;
    /**
     * Use a relaxed version of PKCS#1 padding for signature verification
     *
     * @see self::sign()
     * @see self::verify()
     * @see self::setHash()
     * @access public
     */
    const SIGNATURE_RELAXED_PKCS1 = 32;
    /**
     * Use PKCS#1 padding for signature verification
     *
     * @see self::sign()
     * @see self::verify()
     * @see self::setHash()
     * @access public
     */
    const SIGNATURE_PKCS1 = 64;
    /**
     * Encryption padding mode
     *
     * @var int
     * @access private
     */
    protected $encryptionPadding = self::ENCRYPTION_OAEP;
    /**
     * Signature padding mode
     *
     * @var int
     * @access private
     */
    protected $signaturePadding = self::SIGNATURE_PSS;
    /**
     * Length of hash function output
     *
     * @var int
     * @access private
     */
    protected $hLen;
    /**
     * Length of salt
     *
     * @var int
     * @access private
     */
    protected $sLen;
    /**
     * Label
     *
     * @var string
     * @access private
     */
    protected $label = '';
    /**
     * Hash function for the Mask Generation Function
     *
     * @var \phpseclib3\Crypt\Hash
     * @access private
     */
    protected $mgfHash;
    /**
     * Length of MGF hash function output
     *
     * @var int
     * @access private
     */
    protected $mgfHLen;
    /**
     * Modulus (ie. n)
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $modulus;
    /**
     * Modulus length
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $k;
    /**
     * Exponent (ie. e or d)
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $exponent;
    /**
     * Default public exponent
     *
     * @var int
     * @link http://en.wikipedia.org/wiki/65537_%28number%29
     * @access private
     */
    private static $defaultExponent = 65537;
    /**
     * Enable Blinding?
     *
     * @var bool
     * @access private
     */
    protected static $enableBlinding = true;
    /**
     * OpenSSL configuration file name.
     *
     * @see self::createKey()
     * @var ?string
     */
    protected static $configFile;
    /**
     * Smallest Prime
     *
     * Per <http://cseweb.ucsd.edu/~hovav/dist/survey.pdf#page=5>, this number ought not result in primes smaller
     * than 256 bits. As a consequence if the key you're trying to create is 1024 bits and you've set smallestPrime
     * to 384 bits then you're going to get a 384 bit prime and a 640 bit prime (384 + 1024 % 384). At least if
     * engine is set to self::ENGINE_INTERNAL. If Engine is set to self::ENGINE_OPENSSL then smallest Prime is
     * ignored (ie. multi-prime RSA support is more intended as a way to speed up RSA key generation when there's
     * a chance neither gmp nor OpenSSL are installed)
     *
     * @var int
     * @access private
     */
    private static $smallestPrime = 4096;
    /**
     * Sets the public exponent for key generation
     *
     * This will be 65537 unless changed.
     *
     * @access public
     * @param int $val
     */
    public static function setExponent($val)
    {
        self::$defaultExponent = $val;
    }
    /**
     * Sets the smallest prime number in bits. Used for key generation
     *
     * This will be 4096 unless changed.
     *
     * @access public
     * @param int $val
     */
    public static function setSmallestPrime($val)
    {
        self::$smallestPrime = $val;
    }
    /**
     * Sets the OpenSSL config file path
     *
     * Set to the empty string to use the default config file
     *
     * @access public
     * @param string $val
     */
    public static function setOpenSSLConfigPath($val)
    {
        self::$configFile = $val;
    }
    /**
     * Create a private key
     *
     * The public key can be extracted from the private key
     *
     * @return RSA
     * @access public
     * @param int $bits
     */
    public static function createKey($bits = 2048)
    {
        self::initialize_static_variables();
        $regSize = $bits >> 1;
        // divide by two to see how many bits P and Q would be
        if ($regSize > self::$smallestPrime) {
            $num_primes = floor($bits / self::$smallestPrime);
            $regSize = self::$smallestPrime;
        } else {
            $num_primes = 2;
        }
        if ($num_primes == 2 && $bits >= 384 && self::$defaultExponent == 65537) {
            if (!isset(self::$engines['PHP'])) {
                self::useBestEngine();
            }
            // OpenSSL uses 65537 as the exponent and requires RSA keys be 384 bits minimum
            if (self::$engines['OpenSSL']) {
                $config = [];
                if (self::$configFile) {
                    $config['config'] = self::$configFile;
                }
                $rsa = openssl_pkey_new(['private_key_bits' => $bits] + $config);
                openssl_pkey_export($rsa, $privatekeystr, null, $config);
                // clear the buffer of error strings stemming from a minimalistic openssl.cnf
                while (openssl_error_string() !== false) {
                }
                return RSA::load($privatekeystr);
            }
        }
        static $e;
        if (!isset($e)) {
            $e = new BigInteger(self::$defaultExponent);
        }
        $n = clone self::$one;
        $exponents = $coefficients = $primes = [];
        $lcm = ['top' => clone self::$one, 'bottom' => false];
        do {
            for ($i = 1; $i <= $num_primes; $i++) {
                if ($i != $num_primes) {
                    $primes[$i] = BigInteger::randomPrime($regSize);
                } else {
                    extract(BigInteger::minMaxBits($bits));
                    /** @var BigInteger $min
                     *  @var BigInteger $max
                     */
                    list($min) = $min->divide($n);
                    $min = $min->add(self::$one);
                    list($max) = $max->divide($n);
                    $primes[$i] = BigInteger::randomRangePrime($min, $max);
                }
                // the first coefficient is calculated differently from the rest
                // ie. instead of being $primes[1]->modInverse($primes[2]), it's $primes[2]->modInverse($primes[1])
                if ($i > 2) {
                    $coefficients[$i] = $n->modInverse($primes[$i]);
                }
                $n = $n->multiply($primes[$i]);
                $temp = $primes[$i]->subtract(self::$one);
                // textbook RSA implementations use Euler's totient function instead of the least common multiple.
                // see http://en.wikipedia.org/wiki/Euler%27s_totient_function
                $lcm['top'] = $lcm['top']->multiply($temp);
                $lcm['bottom'] = $lcm['bottom'] === false ? $temp : $lcm['bottom']->gcd($temp);
            }
            list($temp) = $lcm['top']->divide($lcm['bottom']);
            $gcd = $temp->gcd($e);
            $i0 = 1;
        } while (!$gcd->equals(self::$one));
        $coefficients[2] = $primes[2]->modInverse($primes[1]);
        $d = $e->modInverse($temp);
        foreach ($primes as $i => $prime) {
            $temp = $prime->subtract(self::$one);
            $exponents[$i] = $e->modInverse($temp);
        }
        // from <http://tools.ietf.org/html/rfc3447#appendix-A.1.2>:
        // RSAPrivateKey ::= SEQUENCE {
        //     version           Version,
        //     modulus           INTEGER,  -- n
        //     publicExponent    INTEGER,  -- e
        //     privateExponent   INTEGER,  -- d
        //     prime1            INTEGER,  -- p
        //     prime2            INTEGER,  -- q
        //     exponent1         INTEGER,  -- d mod (p-1)
        //     exponent2         INTEGER,  -- d mod (q-1)
        //     coefficient       INTEGER,  -- (inverse of q) mod p
        //     otherPrimeInfos   OtherPrimeInfos OPTIONAL
        // }
        $privatekey = new PrivateKey();
        $privatekey->modulus = $n;
        $privatekey->k = $bits >> 3;
        $privatekey->publicExponent = $e;
        $privatekey->exponent = $d;
        $privatekey->primes = $primes;
        $privatekey->exponents = $exponents;
        $privatekey->coefficients = $coefficients;
        /*
        $publickey = new PublicKey;
        $publickey->modulus = $n;
        $publickey->k = $bits >> 3;
        $publickey->exponent = $e;
        $publickey->publicExponent = $e;
        $publickey->isPublic = true;
        */
        return $privatekey;
    }
    /**
     * OnLoad Handler
     *
     * @return bool
     * @access protected
     * @param array $components
     */
    protected static function onLoad($components)
    {
        $key = $components['isPublicKey'] ? new PublicKey() : new PrivateKey();
        $key->modulus = $components['modulus'];
        $key->publicExponent = $components['publicExponent'];
        $key->k = $key->modulus->getLengthInBytes();
        if ($components['isPublicKey'] || !isset($components['privateExponent'])) {
            $key->exponent = $key->publicExponent;
        } else {
            $key->privateExponent = $components['privateExponent'];
            $key->exponent = $key->privateExponent;
            $key->primes = $components['primes'];
            $key->exponents = $components['exponents'];
            $key->coefficients = $components['coefficients'];
        }
        if ($components['format'] == PSS::class) {
            // in the X509 world RSA keys are assumed to use PKCS1 padding by default. only if the key is
            // explicitly a PSS key is the use of PSS assumed. phpseclib does not work like this. phpseclib
            // uses PSS padding by default. it assumes the more secure method by default and altho it provides
            // for the less secure PKCS1 method you have to go out of your way to use it. this is consistent
            // with the latest trends in crypto. libsodium (NaCl) is actually a little more extreme in that
            // not only does it defaults to the most secure methods - it doesn't even let you choose less
            // secure methods
            //$key = $key->withPadding(self::SIGNATURE_PSS);
            if (isset($components['hash'])) {
                $key = $key->withHash($components['hash']);
            }
            if (isset($components['MGFHash'])) {
                $key = $key->withMGFHash($components['MGFHash']);
            }
            if (isset($components['saltLength'])) {
                $key = $key->withSaltLength($components['saltLength']);
            }
        }
        return $key;
    }
    /**
     * Initialize static variables
     */
    protected static function initialize_static_variables()
    {
        if (!isset(self::$configFile)) {
            self::$configFile = dirname(__FILE__) . '/../openssl.cnf';
        }
        parent::initialize_static_variables();
    }
    /**
     * Constructor
     *
     * PublicKey and PrivateKey objects can only be created from abstract RSA class
     */
    protected function __construct()
    {
        parent::__construct();
        $this->hLen = $this->hash->getLengthInBytes();
        $this->mgfHash = new Hash('sha256');
        $this->mgfHLen = $this->mgfHash->getLengthInBytes();
    }
    /**
     * Integer-to-Octet-String primitive
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-4.1 RFC3447#section-4.1}.
     *
     * @access private
     * @param (bool | \phpseclib3\Math\BigInteger) $x
     * @param int $xLen
     * @return (bool | string)
     */
    protected function i2osp($x, $xLen)
    {
        if ($x === false) {
            return false;
        }
        $x = $x->toBytes();
        if (strlen($x) > $xLen) {
            throw new \OutOfRangeException('Resultant string length out of range');
        }
        return str_pad($x, $xLen, chr(0), STR_PAD_LEFT);
    }
    /**
     * Octet-String-to-Integer primitive
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-4.2 RFC3447#section-4.2}.
     *
     * @access private
     * @param string $x
     * @return \phpseclib3\Math\BigInteger
     */
    protected function os2ip($x)
    {
        return new BigInteger($x, 256);
    }
    /**
     * EMSA-PKCS1-V1_5-ENCODE
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-9.2 RFC3447#section-9.2}.
     *
     * @access private
     * @param string $m
     * @param int $emLen
     * @throws \LengthException if the intended encoded message length is too short
     * @return string
     */
    protected function emsa_pkcs1_v1_5_encode($m, $emLen)
    {
        $h = $this->hash->hash($m);
        // see http://tools.ietf.org/html/rfc3447#page-43
        switch ($this->hash->getHash()) {
            case 'md2':
                $t = "0 0\f\x06\x08*\x86H\x86\xf7\r\x02\x02\x05\x00\x04\x10";
                break;
            case 'md5':
                $t = "0 0\f\x06\x08*\x86H\x86\xf7\r\x02\x05\x05\x00\x04\x10";
                break;
            case 'sha1':
                $t = "0!0\t\x06\x05+\x0e\x03\x02\x1a\x05\x00\x04\x14";
                break;
            case 'sha256':
                $t = "010\r\x06\t`\x86H\x01e\x03\x04\x02\x01\x05\x00\x04 ";
                break;
            case 'sha384':
                $t = "0A0\r\x06\t`\x86H\x01e\x03\x04\x02\x02\x05\x00\x040";
                break;
            case 'sha512':
                $t = "0Q0\r\x06\t`\x86H\x01e\x03\x04\x02\x03\x05\x00\x04@";
                break;
            // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40
            case 'sha224':
                $t = "0-0\r\x06\t`\x86H\x01e\x03\x04\x02\x04\x05\x00\x04\x1c";
                break;
            case 'sha512/224':
                $t = "0-0\r\x06\t`\x86H\x01e\x03\x04\x02\x05\x05\x00\x04\x1c";
                break;
            case 'sha512/256':
                $t = "010\r\x06\t`\x86H\x01e\x03\x04\x02\x06\x05\x00\x04 ";
        }
        $t .= $h;
        $tLen = strlen($t);
        if ($emLen < $tLen + 11) {
            throw new \LengthException('Intended encoded message length too short');
        }
        $ps = str_repeat(chr(0xff), $emLen - $tLen - 3);
        $em = "\x00\x01{$ps}\x00{$t}";
        return $em;
    }
    /**
    * EMSA-PKCS1-V1_5-ENCODE (without NULL)
    *
    * Quoting https://tools.ietf.org/html/rfc8017#page-65,
    *
    * "The parameters field associated with id-sha1, id-sha224, id-sha256,
    id-sha384, id-sha512, id-sha512/224, and id-sha512/256 should
    generally be omitted, but if present, it shall have a value of type
    NULL"
    *
    * @access private
    * @param string $m
    * @param int $emLen
    * @return string
    */
    protected function emsa_pkcs1_v1_5_encode_without_null($m, $emLen)
    {
        $h = $this->hash->hash($m);
        // see http://tools.ietf.org/html/rfc3447#page-43
        switch ($this->hash->getHash()) {
            case 'sha1':
                $t = "0\x1f0\x07\x06\x05+\x0e\x03\x02\x1a\x04\x14";
                break;
            case 'sha256':
                $t = "0/0\v\x06\t`\x86H\x01e\x03\x04\x02\x01\x04 ";
                break;
            case 'sha384':
                $t = "0?0\v\x06\t`\x86H\x01e\x03\x04\x02\x02\x040";
                break;
            case 'sha512':
                $t = "0O0\v\x06\t`\x86H\x01e\x03\x04\x02\x03\x04@";
                break;
            // from https://www.emc.com/collateral/white-papers/h11300-pkcs-1v2-2-rsa-cryptography-standard-wp.pdf#page=40
            case 'sha224':
                $t = "0+0\v\x06\t`\x86H\x01e\x03\x04\x02\x04\x04\x1c";
                break;
            case 'sha512/224':
                $t = "0+0\v\x06\t`\x86H\x01e\x03\x04\x02\x05\x04\x1c";
                break;
            case 'sha512/256':
                $t = "0/0\v\x06\t`\x86H\x01e\x03\x04\x02\x06\x04 ";
                break;
            default:
                throw new UnsupportedAlgorithmException('md2 and md5 require NULLs');
        }
        $t .= $h;
        $tLen = strlen($t);
        if ($emLen < $tLen + 11) {
            throw new \LengthException('Intended encoded message length too short');
        }
        $ps = str_repeat(chr(0xff), $emLen - $tLen - 3);
        $em = "\x00\x01{$ps}\x00{$t}";
        return $em;
    }
    /**
     * MGF1
     *
     * See {@link http://tools.ietf.org/html/rfc3447#appendix-B.2.1 RFC3447#appendix-B.2.1}.
     *
     * @access private
     * @param string $mgfSeed
     * @param int $maskLen
     * @return string
     */
    protected function mgf1($mgfSeed, $maskLen)
    {
        // if $maskLen would yield strings larger than 4GB, PKCS#1 suggests a "Mask too long" error be output.
        $t = '';
        $count = ceil($maskLen / $this->mgfHLen);
        for ($i = 0; $i < $count; $i++) {
            $c = pack('N', $i);
            $t .= $this->mgfHash->hash($mgfSeed . $c);
        }
        return \Phabel\Target\Php80\Polyfill::substr($t, 0, $maskLen);
    }
    /**
     * Returns the key size
     *
     * More specifically, this returns the size of the modulo in bits.
     *
     * @access public
     * @return int
     */
    public function getLength()
    {
        return !isset($this->modulus) ? 0 : $this->modulus->getLength();
    }
    /**
    * Determines which hashing function should be used
    *
    * Used with signature production / verification and (if the encryption mode is self::PADDING_OAEP) encryption and
    decryption.
    *
    * @access public
    * @param string $hash
    */
    public function withHash($hash)
    {
        $new = clone $this;
        // \phpseclib3\Crypt\Hash supports algorithms that PKCS#1 doesn't support.  md5-96 and sha1-96, for example.
        switch (strtolower($hash)) {
            case 'md2':
            case 'md5':
            case 'sha1':
            case 'sha256':
            case 'sha384':
            case 'sha512':
            case 'sha224':
            case 'sha512/224':
            case 'sha512/256':
                $new->hash = new Hash($hash);
                break;
            default:
                throw new UnsupportedAlgorithmException('The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256');
        }
        $new->hLen = $new->hash->getLengthInBytes();
        return $new;
    }
    /**
    * Determines which hashing function should be used for the mask generation function
    *
    * The mask generation function is used by self::PADDING_OAEP and self::PADDING_PSS and although it's
    best if Hash and MGFHash are set to the same thing this is not a requirement.
    *
    * @access public
    * @param string $hash
    */
    public function withMGFHash($hash)
    {
        $new = clone $this;
        // \phpseclib3\Crypt\Hash supports algorithms that PKCS#1 doesn't support.  md5-96 and sha1-96, for example.
        switch (strtolower($hash)) {
            case 'md2':
            case 'md5':
            case 'sha1':
            case 'sha256':
            case 'sha384':
            case 'sha512':
            case 'sha224':
            case 'sha512/224':
            case 'sha512/256':
                $new->mgfHash = new Hash($hash);
                break;
            default:
                throw new UnsupportedAlgorithmException('The only supported hash algorithms are: md2, md5, sha1, sha256, sha384, sha512, sha224, sha512/224, sha512/256');
        }
        $new->mgfHLen = $new->mgfHash->getLengthInBytes();
        return $new;
    }
    /**
     * Returns the MGF hash algorithm currently being used
     *
     * @access public
     */
    public function getMGFHash()
    {
        return clone $this->mgfHash;
    }
    /**
    * Determines the salt length
    *
    * Used by RSA::PADDING_PSS
    *
    * To quote from {@link http://tools.ietf.org/html/rfc3447#page-38 RFC3447#page-38}:
    *
    * Typical salt lengths in octets are hLen (the length of the output
    of the hash function Hash) and 0.
    *
    * @access public
    * @param int $sLen
    */
    public function withSaltLength($sLen)
    {
        $new = clone $this;
        $new->sLen = $sLen;
        return $new;
    }
    /**
     * Returns the salt length currently being used
     *
     * @access public
     */
    public function getSaltLength()
    {
        return $this->sLen !== null ? $this->sLen : $this->hLen;
    }
    /**
    * Determines the label
    *
    * Used by RSA::PADDING_OAEP
    *
    * To quote from {@link http://tools.ietf.org/html/rfc3447#page-17 RFC3447#page-17}:
    *
    * Both the encryption and the decryption operations of RSAES-OAEP take
    the value of a label L as input.  In this version of PKCS #1, L is
    the empty string; other uses of the label are outside the scope of
    this document.
    *
    * @access public
    * @param string $label
    */
    public function withLabel($label)
    {
        $new = clone $this;
        $new->label = $label;
        return $new;
    }
    /**
     * Returns the label currently being used
     *
     * @access public
     */
    public function getLabel()
    {
        return $this->label;
    }
    /**
     * Determines the padding modes
     *
     * Example: $key->withPadding(RSA::ENCRYPTION_PKCS1 | RSA::SIGNATURE_PKCS1);
     *
     * @access public
     * @param int $padding
     */
    public function withPadding($padding)
    {
        $masks = [self::ENCRYPTION_OAEP, self::ENCRYPTION_PKCS1, self::ENCRYPTION_NONE];
        $numSelected = 0;
        $selected = 0;
        foreach ($masks as $mask) {
            if ($padding & $mask) {
                $selected = $mask;
                $numSelected++;
            }
        }
        if ($numSelected > 1) {
            throw new InconsistentSetupException('Multiple encryption padding modes have been selected; at most only one should be selected');
        }
        $encryptionPadding = $selected;
        $masks = [self::SIGNATURE_PSS, self::SIGNATURE_RELAXED_PKCS1, self::SIGNATURE_PKCS1];
        $numSelected = 0;
        $selected = 0;
        foreach ($masks as $mask) {
            if ($padding & $mask) {
                $selected = $mask;
                $numSelected++;
            }
        }
        if ($numSelected > 1) {
            throw new InconsistentSetupException('Multiple signature padding modes have been selected; at most only one should be selected');
        }
        $signaturePadding = $selected;
        $new = clone $this;
        $new->encryptionPadding = $encryptionPadding;
        $new->signaturePadding = $signaturePadding;
        return $new;
    }
    /**
     * Returns the padding currently being used
     *
     * @access public
     */
    public function getPadding()
    {
        return $this->signaturePadding | $this->encryptionPadding;
    }
    /**
    * Returns the current engine being used
    *
    * OpenSSL is only used in this class (and it's subclasses) for key generation
    Even then it depends on the parameters you're using. It's not used for
    multi-prime RSA nor is it used if the key length is outside of the range
    supported by OpenSSL
    *
    * @see self::useInternalEngine()
    * @see self::useBestEngine()
    * @access public
    * @return string
    */
    public function getEngine()
    {
        return self::$engines['OpenSSL'] && self::$defaultExponent == 65537 ? 'OpenSSL' : 'PHP';
    }
    /**
     * Enable RSA Blinding
     *
     * @access public
     */
    public static function enableBlinding()
    {
        static::$enableBlinding = true;
    }
    /**
     * Disable RSA Blinding
     *
     * @access public
     */
    public static function disableBlinding()
    {
        static::$enableBlinding = false;
    }
}<?php

/**
 * Pure-PHP implementation of RC2.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://tools.ietf.org/html/rfc2268}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $rc2 = new \phpseclib3\Crypt\RC2('ctr');
 *
 *    $rc2->setKey('abcdefgh');
 *
 *    $plaintext = str_repeat('a', 1024);
 *
 *    echo $rc2->decrypt($rc2->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category Crypt
 * @package  RC2
 * @author   Patrick Monnerat <pm@datasphere.ch>
 * @license  http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link     http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
use phpseclib3\Exception\BadModeException;
/**
 * Pure-PHP implementation of RC2.
 *
 * @package RC2
 * @access  public
 */
class RC2 extends BlockCipher
{
    /**
     * Block Length of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
     * @var int
     * @access private
     */
    protected $block_size = 8;
    /**
     * The Key
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::key
     * @see self::setKey()
     * @var string
     * @access private
     */
    protected $key;
    /**
     * The Original (unpadded) Key
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::key
     * @see self::setKey()
     * @see self::encrypt()
     * @see self::decrypt()
     * @var string
     * @access private
     */
    private $orig_key;
    /**
     * Don't truncate / null pad key
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::clearBuffers()
     * @var bool
     * @access private
     */
    private $skip_key_adjustment = true;
    /**
     * Key Length (in bytes)
     *
     * @see \phpseclib3\Crypt\RC2::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 16;
    // = 128 bits
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'rc2';
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 500;
    /**
     * The key length in bits.
     *
     * {@internal Should be in range [1..1024].}
     *
     * {@internal Changing this value after setting the key has no effect.}
     *
     * @see self::setKeyLength()
     * @see self::setKey()
     * @var int
     * @access private
     */
    private $default_key_length = 1024;
    /**
     * The key length in bits.
     *
     * {@internal Should be in range [1..1024].}
     *
     * @see self::isValidEnine()
     * @see self::setKey()
     * @var int
     * @access private
     */
    private $current_key_length;
    /**
     * The Key Schedule
     *
     * @see self::setupKey()
     * @var array
     * @access private
     */
    private $keys;
    /**
     * Key expansion randomization table.
     * Twice the same 256-value sequence to save a modulus in key expansion.
     *
     * @see self::setKey()
     * @var array
     * @access private
     */
    private static $pitable = [0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x9, 0x81, 0x7d, 0x32, 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0xb, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 0x6f, 0xbf, 0xe, 0xda, 0x46, 0x69, 0x7, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x3, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x6, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x8, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x4, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0xf, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x2, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x5, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x0, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x1, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0xd, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0xc, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0xa, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad, 0xd9, 0x78, 0xf9, 0xc4, 0x19, 0xdd, 0xb5, 0xed, 0x28, 0xe9, 0xfd, 0x79, 0x4a, 0xa0, 0xd8, 0x9d, 0xc6, 0x7e, 0x37, 0x83, 0x2b, 0x76, 0x53, 0x8e, 0x62, 0x4c, 0x64, 0x88, 0x44, 0x8b, 0xfb, 0xa2, 0x17, 0x9a, 0x59, 0xf5, 0x87, 0xb3, 0x4f, 0x13, 0x61, 0x45, 0x6d, 0x8d, 0x9, 0x81, 0x7d, 0x32, 0xbd, 0x8f, 0x40, 0xeb, 0x86, 0xb7, 0x7b, 0xb, 0xf0, 0x95, 0x21, 0x22, 0x5c, 0x6b, 0x4e, 0x82, 0x54, 0xd6, 0x65, 0x93, 0xce, 0x60, 0xb2, 0x1c, 0x73, 0x56, 0xc0, 0x14, 0xa7, 0x8c, 0xf1, 0xdc, 0x12, 0x75, 0xca, 0x1f, 0x3b, 0xbe, 0xe4, 0xd1, 0x42, 0x3d, 0xd4, 0x30, 0xa3, 0x3c, 0xb6, 0x26, 0x6f, 0xbf, 0xe, 0xda, 0x46, 0x69, 0x7, 0x57, 0x27, 0xf2, 0x1d, 0x9b, 0xbc, 0x94, 0x43, 0x3, 0xf8, 0x11, 0xc7, 0xf6, 0x90, 0xef, 0x3e, 0xe7, 0x6, 0xc3, 0xd5, 0x2f, 0xc8, 0x66, 0x1e, 0xd7, 0x8, 0xe8, 0xea, 0xde, 0x80, 0x52, 0xee, 0xf7, 0x84, 0xaa, 0x72, 0xac, 0x35, 0x4d, 0x6a, 0x2a, 0x96, 0x1a, 0xd2, 0x71, 0x5a, 0x15, 0x49, 0x74, 0x4b, 0x9f, 0xd0, 0x5e, 0x4, 0x18, 0xa4, 0xec, 0xc2, 0xe0, 0x41, 0x6e, 0xf, 0x51, 0xcb, 0xcc, 0x24, 0x91, 0xaf, 0x50, 0xa1, 0xf4, 0x70, 0x39, 0x99, 0x7c, 0x3a, 0x85, 0x23, 0xb8, 0xb4, 0x7a, 0xfc, 0x2, 0x36, 0x5b, 0x25, 0x55, 0x97, 0x31, 0x2d, 0x5d, 0xfa, 0x98, 0xe3, 0x8a, 0x92, 0xae, 0x5, 0xdf, 0x29, 0x10, 0x67, 0x6c, 0xba, 0xc9, 0xd3, 0x0, 0xe6, 0xcf, 0xe1, 0x9e, 0xa8, 0x2c, 0x63, 0x16, 0x1, 0x3f, 0x58, 0xe2, 0x89, 0xa9, 0xd, 0x38, 0x34, 0x1b, 0xab, 0x33, 0xff, 0xb0, 0xbb, 0x48, 0xc, 0x5f, 0xb9, 0xb1, 0xcd, 0x2e, 0xc5, 0xf3, 0xdb, 0x47, 0xe5, 0xa5, 0x9c, 0x77, 0xa, 0xa6, 0x20, 0x68, 0xfe, 0x7f, 0xc1, 0xad];
    /**
     * Inverse key expansion randomization table.
     *
     * @see self::setKey()
     * @var array
     * @access private
     */
    private static $invpitable = [0xd1, 0xda, 0xb9, 0x6f, 0x9c, 0xc8, 0x78, 0x66, 0x80, 0x2c, 0xf8, 0x37, 0xea, 0xe0, 0x62, 0xa4, 0xcb, 0x71, 0x50, 0x27, 0x4b, 0x95, 0xd9, 0x20, 0x9d, 0x4, 0x91, 0xe3, 0x47, 0x6a, 0x7e, 0x53, 0xfa, 0x3a, 0x3b, 0xb4, 0xa8, 0xbc, 0x5f, 0x68, 0x8, 0xca, 0x8f, 0x14, 0xd7, 0xc0, 0xef, 0x7b, 0x5b, 0xbf, 0x2f, 0xe5, 0xe2, 0x8c, 0xba, 0x12, 0xe1, 0xaf, 0xb2, 0x54, 0x5d, 0x59, 0x76, 0xdb, 0x32, 0xa2, 0x58, 0x6e, 0x1c, 0x29, 0x64, 0xf3, 0xe9, 0x96, 0xc, 0x98, 0x19, 0x8d, 0x3e, 0x26, 0xab, 0xa5, 0x85, 0x16, 0x40, 0xbd, 0x49, 0x67, 0xdc, 0x22, 0x94, 0xbb, 0x3c, 0xc1, 0x9b, 0xeb, 0x45, 0x28, 0x18, 0xd8, 0x1a, 0x42, 0x7d, 0xcc, 0xfb, 0x65, 0x8e, 0x3d, 0xcd, 0x2a, 0xa3, 0x60, 0xae, 0x93, 0x8a, 0x48, 0x97, 0x51, 0x15, 0xf7, 0x1, 0xb, 0xb7, 0x36, 0xb1, 0x2e, 0x11, 0xfd, 0x84, 0x2d, 0x3f, 0x13, 0x88, 0xb3, 0x34, 0x24, 0x1b, 0xde, 0xc5, 0x1d, 0x4d, 0x2b, 0x17, 0x31, 0x74, 0xa9, 0xc6, 0x43, 0x6d, 0x39, 0x90, 0xbe, 0xc3, 0xb0, 0x21, 0x6b, 0xf6, 0xf, 0xd5, 0x99, 0xd, 0xac, 0x1f, 0x5c, 0x9e, 0xf5, 0xf9, 0x4c, 0xd6, 0xdf, 0x89, 0xe4, 0x8b, 0xff, 0xc7, 0xaa, 0xe7, 0xed, 0x46, 0x25, 0xb6, 0x6, 0x5e, 0x35, 0xb5, 0xec, 0xce, 0xe8, 0x6c, 0x30, 0x55, 0x61, 0x4a, 0xfe, 0xa0, 0x79, 0x3, 0xf0, 0x10, 0x72, 0x7c, 0xcf, 0x52, 0xa6, 0xa7, 0xee, 0x44, 0xd3, 0x9a, 0x57, 0x92, 0xd0, 0x5a, 0x7a, 0x41, 0x7f, 0xe, 0x0, 0x63, 0xf2, 0x4f, 0x5, 0x83, 0xc9, 0xa1, 0xd4, 0xdd, 0xc4, 0x56, 0xf4, 0xd2, 0x77, 0x81, 0x9, 0x82, 0x33, 0x9f, 0x7, 0x86, 0x75, 0x38, 0x4e, 0x69, 0xf1, 0xad, 0x23, 0x73, 0x87, 0x70, 0x2, 0xc2, 0x1e, 0xb8, 0xa, 0xfc, 0xe6];
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws \InvalidArgumentException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new BadModeException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        switch ($engine) {
            case self::ENGINE_OPENSSL:
                if ($this->current_key_length != 128 || strlen($this->orig_key) < 16) {
                    return false;
                }
                $this->cipher_name_openssl_ecb = 'rc2-ecb';
                $this->cipher_name_openssl = 'rc2-' . $this->openssl_translate_mode();
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
    * Sets the key length.
    *
    * Valid key lengths are 8 to 1024.
    Calling this function after setting the key has no effect until the next
    \phpseclib3\Crypt\RC2::setKey() call.
    *
    * @access public
    * @param int $length in bits
    * @throws \LengthException if the key length isn't supported
    */
    public function setKeyLength($length)
    {
        if ($length < 8 || $length > 1024) {
            throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
        }
        $this->default_key_length = $this->current_key_length = $length;
        $this->explicit_key_length = $length >> 3;
    }
    /**
     * Returns the current key length
     *
     * @access public
     * @return int
     */
    public function getKeyLength()
    {
        return $this->current_key_length;
    }
    /**
    * Sets the key.
    *
    * Keys can be of any length. RC2, itself, uses 8 to 1024 bit keys (eg.
    strlen($key) <= 128), however, we only use the first 128 bytes if $key
    has more then 128 bytes in it, and set $key to a single null byte if
    it is empty.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
    * @access public
    * @param string $key
    * @param (int | boolean) $t1 optional Effective key length in bits.
    * @throws \LengthException if the key length isn't supported
    */
    public function setKey($key, $t1 = false)
    {
        $this->orig_key = $key;
        if ($t1 === false) {
            $t1 = $this->default_key_length;
        }
        if ($t1 < 1 || $t1 > 1024) {
            throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 1024 bits, inclusive, are supported');
        }
        $this->current_key_length = $t1;
        if (strlen($key) < 1 || strlen($key) > 128) {
            throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes between 8 and 1024 bits, inclusive, are supported');
        }
        $t = strlen($key);
        // The mcrypt RC2 implementation only supports effective key length
        // of 1024 bits. It is however possible to handle effective key
        // lengths in range 1..1024 by expanding the key and applying
        // inverse pitable mapping to the first byte before submitting it
        // to mcrypt.
        // Key expansion.
        $l = array_values(unpack('C*', $key));
        $t8 = $t1 + 7 >> 3;
        $tm = 0xff >> 8 * $t8 - $t1;
        // Expand key.
        $pitable = self::$pitable;
        for ($i = $t; $i < 128; $i++) {
            $l[$i] = $pitable[$l[$i - 1] + $l[$i - $t]];
        }
        $i = 128 - $t8;
        $l[$i] = $pitable[$l[$i] & $tm];
        while ($i--) {
            $l[$i] = $pitable[$l[$i + 1] ^ $l[$i + $t8]];
        }
        // Prepare the key for mcrypt.
        $l[0] = self::$invpitable[$l[0]];
        array_unshift($l, 'C*');
        $this->key = pack(...$l);
        $this->key_length = strlen($this->key);
        $this->changed = $this->nonIVChanged = true;
        $this->setEngine();
    }
    /**
     * Encrypts a message.
     *
     * Mostly a wrapper for \phpseclib3\Crypt\Common\SymmetricKey::encrypt, with some additional OpenSSL handling code
     *
     * @see self::decrypt()
     * @access public
     * @param string $plaintext
     * @return string $ciphertext
     */
    public function encrypt($plaintext)
    {
        if ($this->engine == self::ENGINE_OPENSSL) {
            $temp = $this->key;
            $this->key = $this->orig_key;
            $result = parent::encrypt($plaintext);
            $this->key = $temp;
            return $result;
        }
        return parent::encrypt($plaintext);
    }
    /**
     * Decrypts a message.
     *
     * Mostly a wrapper for \phpseclib3\Crypt\Common\SymmetricKey::decrypt, with some additional OpenSSL handling code
     *
     * @see self::encrypt()
     * @access public
     * @param string $ciphertext
     * @return string $plaintext
     */
    public function decrypt($ciphertext)
    {
        if ($this->engine == self::ENGINE_OPENSSL) {
            $temp = $this->key;
            $this->key = $this->orig_key;
            $result = parent::decrypt($ciphertext);
            $this->key = $temp;
            return $result;
        }
        return parent::decrypt($ciphertext);
    }
    /**
     * Encrypts a block
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
        $keys = $this->keys;
        $limit = 20;
        $actions = [$limit => 44, 44 => 64];
        $j = 0;
        for (;;) {
            // Mixing round.
            $r0 = ($r0 + $keys[$j++] + (($r1 ^ $r2) & $r3 ^ $r1) & 0xffff) << 1;
            $r0 |= $r0 >> 16;
            $r1 = ($r1 + $keys[$j++] + (($r2 ^ $r3) & $r0 ^ $r2) & 0xffff) << 2;
            $r1 |= $r1 >> 16;
            $r2 = ($r2 + $keys[$j++] + (($r3 ^ $r0) & $r1 ^ $r3) & 0xffff) << 3;
            $r2 |= $r2 >> 16;
            $r3 = ($r3 + $keys[$j++] + (($r0 ^ $r1) & $r2 ^ $r0) & 0xffff) << 5;
            $r3 |= $r3 >> 16;
            if ($j === $limit) {
                if ($limit === 64) {
                    break;
                }
                // Mashing round.
                $r0 += $keys[$r3 & 0x3f];
                $r1 += $keys[$r0 & 0x3f];
                $r2 += $keys[$r1 & 0x3f];
                $r3 += $keys[$r2 & 0x3f];
                $limit = $actions[$limit];
            }
        }
        return pack('vvvv', $r0, $r1, $r2, $r3);
    }
    /**
     * Decrypts a block
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        list($r0, $r1, $r2, $r3) = array_values(unpack('v*', $in));
        $keys = $this->keys;
        $limit = 44;
        $actions = [$limit => 20, 20 => 0];
        $j = 64;
        for (;;) {
            // R-mixing round.
            $r3 = ($r3 | $r3 << 16) >> 5;
            $r3 = $r3 - $keys[--$j] - (($r0 ^ $r1) & $r2 ^ $r0) & 0xffff;
            $r2 = ($r2 | $r2 << 16) >> 3;
            $r2 = $r2 - $keys[--$j] - (($r3 ^ $r0) & $r1 ^ $r3) & 0xffff;
            $r1 = ($r1 | $r1 << 16) >> 2;
            $r1 = $r1 - $keys[--$j] - (($r2 ^ $r3) & $r0 ^ $r2) & 0xffff;
            $r0 = ($r0 | $r0 << 16) >> 1;
            $r0 = $r0 - $keys[--$j] - (($r1 ^ $r2) & $r3 ^ $r1) & 0xffff;
            if ($j === $limit) {
                if ($limit === 0) {
                    break;
                }
                // R-mashing round.
                $r3 = $r3 - $keys[$r2 & 0x3f] & 0xffff;
                $r2 = $r2 - $keys[$r1 & 0x3f] & 0xffff;
                $r1 = $r1 - $keys[$r0 & 0x3f] & 0xffff;
                $r0 = $r0 - $keys[$r3 & 0x3f] & 0xffff;
                $limit = $actions[$limit];
            }
        }
        return pack('vvvv', $r0, $r1, $r2, $r3);
    }
    /**
     * Creates the key schedule
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
     * @access private
     */
    protected function setupKey()
    {
        if (!isset($this->key)) {
            $this->setKey('');
        }
        // Key has already been expanded in \phpseclib3\Crypt\RC2::setKey():
        // Only the first value must be altered.
        $l = unpack('Ca/Cb/v*', $this->key);
        array_unshift($l, self::$pitable[$l['a']] | $l['b'] << 8);
        unset($l['a']);
        unset($l['b']);
        $this->keys = $l;
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        // Init code for both, encrypt and decrypt.
        $init_crypt = '$keys = $this->keys;';
        $keys = $this->keys;
        // $in is the current 8 bytes block which has to be en/decrypt
        $encrypt_block = $decrypt_block = '
            $in = unpack("v4", $in);
            $r0 = $in[1];
            $r1 = $in[2];
            $r2 = $in[3];
            $r3 = $in[4];
        ';
        // Create code for encryption.
        $limit = 20;
        $actions = [$limit => 44, 44 => 64];
        $j = 0;
        for (;;) {
            // Mixing round.
            $encrypt_block .= '
                $r0 = (($r0 + ' . $keys[$j++] . ' +
                       ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF) << 1;
                $r0 |= $r0 >> 16;
                $r1 = (($r1 + ' . $keys[$j++] . ' +
                       ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF) << 2;
                $r1 |= $r1 >> 16;
                $r2 = (($r2 + ' . $keys[$j++] . ' +
                       ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF) << 3;
                $r2 |= $r2 >> 16;
                $r3 = (($r3 + ' . $keys[$j++] . ' +
                       ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF) << 5;
                $r3 |= $r3 >> 16;';
            if ($j === $limit) {
                if ($limit === 64) {
                    break;
                }
                // Mashing round.
                $encrypt_block .= '
                    $r0 += $keys[$r3 & 0x3F];
                    $r1 += $keys[$r0 & 0x3F];
                    $r2 += $keys[$r1 & 0x3F];
                    $r3 += $keys[$r2 & 0x3F];';
                $limit = $actions[$limit];
            }
        }
        $encrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
        // Create code for decryption.
        $limit = 44;
        $actions = [$limit => 20, 20 => 0];
        $j = 64;
        for (;;) {
            // R-mixing round.
            $decrypt_block .= '
                $r3 = ($r3 | ($r3 << 16)) >> 5;
                $r3 = ($r3 - ' . $keys[--$j] . ' -
                       ((($r0 ^ $r1) & $r2) ^ $r0)) & 0xFFFF;
                $r2 = ($r2 | ($r2 << 16)) >> 3;
                $r2 = ($r2 - ' . $keys[--$j] . ' -
                       ((($r3 ^ $r0) & $r1) ^ $r3)) & 0xFFFF;
                $r1 = ($r1 | ($r1 << 16)) >> 2;
                $r1 = ($r1 - ' . $keys[--$j] . ' -
                       ((($r2 ^ $r3) & $r0) ^ $r2)) & 0xFFFF;
                $r0 = ($r0 | ($r0 << 16)) >> 1;
                $r0 = ($r0 - ' . $keys[--$j] . ' -
                       ((($r1 ^ $r2) & $r3) ^ $r1)) & 0xFFFF;';
            if ($j === $limit) {
                if ($limit === 0) {
                    break;
                }
                // R-mashing round.
                $decrypt_block .= '
                    $r3 = ($r3 - $keys[$r2 & 0x3F]) & 0xFFFF;
                    $r2 = ($r2 - $keys[$r1 & 0x3F]) & 0xFFFF;
                    $r1 = ($r1 - $keys[$r0 & 0x3F]) & 0xFFFF;
                    $r0 = ($r0 - $keys[$r3 & 0x3F]) & 0xFFFF;';
                $limit = $actions[$limit];
            }
        }
        $decrypt_block .= '$in = pack("v4", $r0, $r1, $r2, $r3);';
        // Creates the inline-crypt function
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => $init_crypt, 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block]);
    }
}<?php

/**
 * PKCS#8 Formatted RSA-PSS Key Handler
 *
 * PHP version 5
 *
 * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to "openssl genpkey -algorithm rsa-pss".
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted RSA-PSS Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PSS extends Progenitor
{
    /**
     * OID Name
     *
     * @var string
     * @access private
     */
    const OID_NAME = 'id-RSASSA-PSS';
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = '1.2.840.113549.1.1.10';
    /**
     * OIDs loaded
     *
     * @var bool
     * @access private
     */
    private static $oidsLoaded = false;
    /**
     * Child OIDs loaded
     *
     * @var bool
     * @access private
     */
    protected static $childOIDsLoaded = false;
    /**
     * Initialize static variables
     */
    private static function initialize_static_variables()
    {
        if (!self::$oidsLoaded) {
            ASN1::loadOIDs(['md2' => '1.2.840.113549.2.2', 'md4' => '1.2.840.113549.2.4', 'md5' => '1.2.840.113549.2.5', 'id-sha1' => '1.3.14.3.2.26', 'id-sha256' => '2.16.840.1.101.3.4.2.1', 'id-sha384' => '2.16.840.1.101.3.4.2.2', 'id-sha512' => '2.16.840.1.101.3.4.2.3', 'id-sha224' => '2.16.840.1.101.3.4.2.4', 'id-sha512/224' => '2.16.840.1.101.3.4.2.5', 'id-sha512/256' => '2.16.840.1.101.3.4.2.6', 'id-mgf1' => '1.2.840.113549.1.1.8']);
            self::$oidsLoaded = true;
        }
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $components = ['isPublicKey' => strpos($key, 'PUBLIC') !== false];
        $key = parent::load($key, $password);
        $type = isset($key['privateKey']) ? 'private' : 'public';
        $result = $components + PKCS1::load($key[$type . 'Key']);
        if (isset($key[$type . 'KeyAlgorithm']['parameters'])) {
            $decoded = ASN1::decodeBER($key[$type . 'KeyAlgorithm']['parameters']);
            if ($decoded === false) {
                throw new \UnexpectedValueException('Unable to decode parameters');
            }
            $params = ASN1::asn1map($decoded[0], Maps\RSASSA_PSS_params::MAP);
        } else {
            $params = [];
        }
        if (isset($params['maskGenAlgorithm']['parameters'])) {
            $decoded = ASN1::decodeBER($params['maskGenAlgorithm']['parameters']);
            if ($decoded === false) {
                throw new \UnexpectedValueException('Unable to decode parameters');
            }
            $params['maskGenAlgorithm']['parameters'] = ASN1::asn1map($decoded[0], Maps\HashAlgorithm::MAP);
        } else {
            $params['maskGenAlgorithm'] = ['algorithm' => 'id-mgf1', 'parameters' => ['algorithm' => 'id-sha1']];
        }
        if (!isset($params['hashAlgorithm']['algorithm'])) {
            $params['hashAlgorithm']['algorithm'] = 'id-sha1';
        }
        $result['hash'] = str_replace('id-', '', $params['hashAlgorithm']['algorithm']);
        $result['MGFHash'] = str_replace('id-', '', $params['maskGenAlgorithm']['parameters']['algorithm']);
        if (isset($params['saltLength'])) {
            $result['saltLength'] = (int) $params['saltLength']->toString();
        }
        if (isset($key['meta'])) {
            $result['meta'] = $key['meta'];
        }
        return $result;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        self::initialize_static_variables();
        $key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients);
        $key = ASN1::extractBER($key);
        $params = self::savePSSParams($options);
        return self::wrapPrivateKey($key, [], $params, $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = [])
    {
        self::initialize_static_variables();
        $key = PKCS1::savePublicKey($n, $e);
        $key = ASN1::extractBER($key);
        $params = self::savePSSParams($options);
        return self::wrapPublicKey($key, $params);
    }
    /**
     * Encodes PSS parameters
     *
     * @access public
     * @param array $options
     * @return string
     */
    public static function savePSSParams(array $options)
    {
        /*
         The trailerField field is an integer.  It provides
         compatibility with IEEE Std 1363a-2004 [P1363A].  The value
         MUST be 1, which represents the trailer field with hexadecimal
         value 0xBC.  Other trailer fields, including the trailer field
         composed of HashID concatenated with 0xCC that is specified in
         IEEE Std 1363a, are not supported.  Implementations that
         perform signature generation MUST omit the trailerField field,
         indicating that the default trailer field value was used.
         Implementations that perform signature validation MUST
         recognize both a present trailerField field with value 1 and an
         absent trailerField field.
        
         source: https://tools.ietf.org/html/rfc4055#page-9
        */
        $params = ['trailerField' => new BigInteger(1)];
        if (isset($options['hash'])) {
            $params['hashAlgorithm']['algorithm'] = 'id-' . $options['hash'];
        }
        if (isset($options['MGFHash'])) {
            $temp = ['algorithm' => 'id-' . $options['MGFHash']];
            $temp = ASN1::encodeDER($temp, Maps\HashAlgorithm::MAP);
            $params['maskGenAlgorithm'] = ['algorithm' => 'id-mgf1', 'parameters' => new ASN1\Element($temp)];
        }
        if (isset($options['saltLength'])) {
            $params['saltLength'] = new BigInteger($options['saltLength']);
        }
        return new ASN1\Element(ASN1::encodeDER($params, Maps\RSASSA_PSS_params::MAP));
    }
}<?php

/**
 * PKCS#1 Formatted RSA Key Handler
 *
 * PHP version 5
 *
 * Used by File/X509.php
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN RSA PRIVATE KEY-----
 * -----BEGIN RSA PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pem format (as specified by -m)
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#1 Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends Progenitor
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (strpos($key, 'PUBLIC') !== false) {
            $components = ['isPublicKey' => true];
        } elseif (strpos($key, 'PRIVATE') !== false) {
            $components = ['isPublicKey' => false];
        } else {
            $components = [];
        }
        $key = parent::load($key, $password);
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $key = ASN1::asn1map($decoded[0], Maps\RSAPrivateKey::MAP);
        if (is_array($key)) {
            $components += ['modulus' => $key['modulus'], 'publicExponent' => $key['publicExponent'], 'privateExponent' => $key['privateExponent'], 'primes' => [1 => $key['prime1'], $key['prime2']], 'exponents' => [1 => $key['exponent1'], $key['exponent2']], 'coefficients' => [2 => $key['coefficient']]];
            if ($key['version'] == 'multi') {
                foreach ($key['otherPrimeInfos'] as $primeInfo) {
                    $components['primes'][] = $primeInfo['prime'];
                    $components['exponents'][] = $primeInfo['exponent'];
                    $components['coefficients'][] = $primeInfo['coefficient'];
                }
            }
            if (!isset($components['isPublicKey'])) {
                $components['isPublicKey'] = false;
            }
            return $components;
        }
        $key = ASN1::asn1map($decoded[0], Maps\RSAPublicKey::MAP);
        if (!is_array($key)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping');
        }
        if (!isset($components['isPublicKey'])) {
            $components['isPublicKey'] = true;
        }
        return $components + $key;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        $num_primes = count($primes);
        $key = ['version' => $num_primes == 2 ? 'two-prime' : 'multi', 'modulus' => $n, 'publicExponent' => $e, 'privateExponent' => $d, 'prime1' => $primes[1], 'prime2' => $primes[2], 'exponent1' => $exponents[1], 'exponent2' => $exponents[2], 'coefficient' => $coefficients[2]];
        for ($i = 3; $i <= $num_primes; $i++) {
            $key['otherPrimeInfos'][] = ['prime' => $primes[$i], 'exponent' => $exponents[$i], 'coefficient' => $coefficients[$i]];
        }
        $key = ASN1::encodeDER($key, Maps\RSAPrivateKey::MAP);
        return self::wrapPrivateKey($key, 'RSA', $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        $key = ['modulus' => $n, 'publicExponent' => $e];
        $key = ASN1::encodeDER($key, Maps\RSAPublicKey::MAP);
        return self::wrapPublicKey($key, 'RSA');
    }
}<?php

/**
 * PKCS#8 Formatted RSA Key Handler
 *
 * PHP version 5
 *
 * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
 * is specific to private keys it's basically creating a DER-encoded wrapper
 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends Progenitor
{
    /**
     * OID Name
     *
     * @var string
     * @access private
     */
    const OID_NAME = 'rsaEncryption';
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = '1.2.840.113549.1.1.1';
    /**
     * Child OIDs loaded
     *
     * @var bool
     * @access private
     */
    protected static $childOIDsLoaded = false;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (strpos($key, 'PUBLIC') !== false) {
            $components = ['isPublicKey' => true];
        } elseif (strpos($key, 'PRIVATE') !== false) {
            $components = ['isPublicKey' => false];
        } else {
            $components = [];
        }
        $key = parent::load($key, $password);
        if (isset($key['privateKey'])) {
            if (!isset($components['isPublicKey'])) {
                $components['isPublicKey'] = false;
            }
            $type = 'private';
        } else {
            if (!isset($components['isPublicKey'])) {
                $components['isPublicKey'] = true;
            }
            $type = 'public';
        }
        $result = $components + PKCS1::load($key[$type . 'Key']);
        if (isset($key['meta'])) {
            $result['meta'] = $key['meta'];
        }
        return $result;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        $key = PKCS1::savePrivateKey($n, $e, $d, $primes, $exponents, $coefficients);
        $key = ASN1::extractBER($key);
        return self::wrapPrivateKey($key, [], null, $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = [])
    {
        $key = PKCS1::savePublicKey($n, $e);
        $key = ASN1::extractBER($key);
        return self::wrapPublicKey($key, null);
    }
}<?php

/**
 * PuTTY Formatted RSA Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor;
/**
 * PuTTY Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PuTTY extends Progenitor
{
    /**
     * Public Handler
     *
     * @var string
     * @access private
     */
    const PUBLIC_HANDLER = 'phpseclib3\\Crypt\\RSA\\Formats\\Keys\\OpenSSH';
    /**
     * Algorithm Identifier
     *
     * @var array
     * @access private
     */
    protected static $types = ['ssh-rsa'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        $components = parent::load($key, $password);
        if (!isset($components['private'])) {
            return $components;
        }
        extract($components);
        unset($components['public'], $components['private']);
        $isPublicKey = false;
        $result = Strings::unpackSSH2('ii', $public);
        if ($result === false) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        list($publicExponent, $modulus) = $result;
        $result = Strings::unpackSSH2('iiii', $private);
        if ($result === false) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $primes = $coefficients = [];
        list($privateExponent, $primes[1], $primes[2], $coefficients[2]) = $result;
        $temp = $primes[1]->subtract($one);
        $exponents = [1 => $publicExponent->modInverse($temp)];
        $temp = $primes[2]->subtract($one);
        $exponents[] = $publicExponent->modInverse($temp);
        return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey');
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        if (count($primes) != 2) {
            throw new \InvalidArgumentException('PuTTY does not support multi-prime RSA keys');
        }
        $public = Strings::packSSH2('ii', $e, $n);
        $private = Strings::packSSH2('iiii', $d, $primes[1], $primes[2], $coefficients[2]);
        return self::wrapPrivateKey($public, $private, 'ssh-rsa', $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        return self::wrapPublicKey(Strings::packSSH2('ii', $e, $n), 'ssh-rsa');
    }
}<?php

/**
 * XML Formatted RSA Key Handler
 *
 * More info:
 *
 * http://www.w3.org/TR/xmldsig-core/#sec-RSAKeyValue
 * http://www.w3.org/TR/xkms2/#XKMS_2_0_Paragraph_269
 * http://en.wikipedia.org/wiki/XML_Signature
 * http://en.wikipedia.org/wiki/XKMS
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * XML Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class XML
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $components = ['isPublicKey' => false, 'primes' => [], 'exponents' => [], 'coefficients' => []];
        $use_errors = libxml_use_internal_errors(true);
        $dom = new \DOMDocument();
        if (\Phabel\Target\Php80\Polyfill::substr($key, 0, 5) != '<?xml') {
            $key = '<xml>' . $key . '</xml>';
        }
        if (!$dom->loadXML($key)) {
            throw new \UnexpectedValueException('Key does not appear to contain XML');
        }
        $xpath = new \DOMXPath($dom);
        $keys = ['modulus', 'exponent', 'p', 'q', 'dp', 'dq', 'inverseq', 'd'];
        foreach ($keys as $key) {
            // $dom->getElementsByTagName($key) is case-sensitive
            $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='{$key}']");
            if (!$temp->length) {
                continue;
            }
            $value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256);
            switch ($key) {
                case 'modulus':
                    $components['modulus'] = $value;
                    break;
                case 'exponent':
                    $components['publicExponent'] = $value;
                    break;
                case 'p':
                    $components['primes'][1] = $value;
                    break;
                case 'q':
                    $components['primes'][2] = $value;
                    break;
                case 'dp':
                    $components['exponents'][1] = $value;
                    break;
                case 'dq':
                    $components['exponents'][2] = $value;
                    break;
                case 'inverseq':
                    $components['coefficients'][2] = $value;
                    break;
                case 'd':
                    $components['privateExponent'] = $value;
            }
        }
        libxml_use_internal_errors($use_errors);
        foreach ($components as $key => $value) {
            if (is_array($value) && !count($value)) {
                unset($components[$key]);
            }
        }
        if (isset($components['modulus']) && isset($components['publicExponent'])) {
            if (count($components) == 3) {
                $components['isPublicKey'] = true;
            }
            return $components;
        }
        throw new \UnexpectedValueException('Modulus / exponent not present');
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '')
    {
        if (count($primes) != 2) {
            throw new \InvalidArgumentException('XML does not support multi-prime RSA keys');
        }
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('XML private keys do not support encryption');
        }
        return '<RSAKeyPair>
  <Modulus>' . Base64::encode($n->toBytes()) . '</Modulus>
  <Exponent>' . Base64::encode($e->toBytes()) . '</Exponent>
  <P>' . Base64::encode($primes[1]->toBytes()) . '</P>
  <Q>' . Base64::encode($primes[2]->toBytes()) . '</Q>
  <DP>' . Base64::encode($exponents[1]->toBytes()) . '</DP>
  <DQ>' . Base64::encode($exponents[2]->toBytes()) . '</DQ>
  <InverseQ>' . Base64::encode($coefficients[2]->toBytes()) . '</InverseQ>
  <D>' . Base64::encode($d->toBytes()) . '</D>
</RSAKeyPair>';
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        return '<RSAKeyValue>
  <Modulus>' . Base64::encode($n->toBytes()) . '</Modulus>
  <Exponent>' . Base64::encode($e->toBytes()) . '</Exponent>
</RSAKeyValue>';
    }
}<?php

/**
 * OpenSSH Formatted RSA Key Handler
 *
 * PHP version 5
 *
 * Place in $HOME/.ssh/authorized_keys
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor;
/**
 * OpenSSH Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSH extends Progenitor
{
    /**
     * Supported Key Types
     *
     * @var array
     */
    protected static $types = ['ssh-rsa'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        $parsed = parent::load($key, $password);
        if (isset($parsed['paddedKey'])) {
            list($type) = Strings::unpackSSH2('s', $parsed['paddedKey']);
            if ($type != $parsed['type']) {
                throw new \RuntimeException("The public and private keys are not of the same type ({$type} vs {$parsed['type']})");
            }
            $primes = $coefficients = [];
            list($modulus, $publicExponent, $privateExponent, $coefficients[2], $primes[1], $primes[2], $comment, ) = Strings::unpackSSH2('i6s', $parsed['paddedKey']);
            $temp = $primes[1]->subtract($one);
            $exponents = [1 => $publicExponent->modInverse($temp)];
            $temp = $primes[2]->subtract($one);
            $exponents[] = $publicExponent->modInverse($temp);
            $isPublicKey = false;
            return compact('publicExponent', 'modulus', 'privateExponent', 'primes', 'coefficients', 'exponents', 'comment', 'isPublicKey');
        }
        list($publicExponent, $modulus) = Strings::unpackSSH2('ii', $parsed['publicKey']);
        return ['isPublicKey' => true, 'modulus' => $modulus, 'publicExponent' => $publicExponent, 'comment' => $parsed['comment']];
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e, array $options = [])
    {
        $RSAPublicKey = Strings::packSSH2('sii', 'ssh-rsa', $e, $n);
        if (isset($options['binary']) ? $options['binary'] : self::$binary) {
            return $RSAPublicKey;
        }
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        $RSAPublicKey = 'ssh-rsa ' . base64_encode($RSAPublicKey) . ' ' . $comment;
        return $RSAPublicKey;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        $publicKey = self::savePublicKey($n, $e, ['binary' => true]);
        $privateKey = Strings::packSSH2('si6', 'ssh-rsa', $n, $e, $d, $coefficients[2], $primes[1], $primes[2]);
        return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
    }
}<?php

/**
 * Miccrosoft BLOB Formatted RSA Key Handler
 *
 * More info:
 *
 * https://msdn.microsoft.com/en-us/library/windows/desktop/aa375601(v=vs.85).aspx
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * Microsoft BLOB Formatted RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MSBLOB
{
    /**
     * Public/Private Key Pair
     *
     * @access private
     */
    const PRIVATEKEYBLOB = 0x7;
    /**
     * Public Key
     *
     * @access private
     */
    const PUBLICKEYBLOB = 0x6;
    /**
     * Public Key
     *
     * @access private
     */
    const PUBLICKEYBLOBEX = 0xa;
    /**
     * RSA public key exchange algorithm
     *
     * @access private
     */
    const CALG_RSA_KEYX = 0xa400;
    /**
     * RSA public key exchange algorithm
     *
     * @access private
     */
    const CALG_RSA_SIGN = 0x2400;
    /**
     * Public Key
     *
     * @access private
     */
    const RSA1 = 0x31415352;
    /**
     * Private Key
     *
     * @access private
     */
    const RSA2 = 0x32415352;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $key = Base64::decode($key);
        if (!is_string($key)) {
            throw new \UnexpectedValueException('Base64 decoding produced an error');
        }
        if (strlen($key) < 20) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        // PUBLICKEYSTRUC  publickeystruc
        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387453(v=vs.85).aspx
        extract(unpack('atype/aversion/vreserved/Valgo', Strings::shift($key, 8)));
        /**
         * @var string $type
         * @var string $version
         * @var integer $reserved
         * @var integer $algo
         */
        switch (ord($type)) {
            case self::PUBLICKEYBLOB:
            case self::PUBLICKEYBLOBEX:
                $publickey = true;
                break;
            case self::PRIVATEKEYBLOB:
                $publickey = false;
                break;
            default:
                throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $components = ['isPublicKey' => $publickey];
        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa375549(v=vs.85).aspx
        switch ($algo) {
            case self::CALG_RSA_KEYX:
            case self::CALG_RSA_SIGN:
                break;
            default:
                throw new \UnexpectedValueException('Key appears to be malformed');
        }
        // RSAPUBKEY rsapubkey
        // https://msdn.microsoft.com/en-us/library/windows/desktop/aa387685(v=vs.85).aspx
        // could do V for pubexp but that's unsigned 32-bit whereas some PHP installs only do signed 32-bit
        extract(unpack('Vmagic/Vbitlen/a4pubexp', Strings::shift($key, 12)));
        /**
         * @var integer $magic
         * @var integer $bitlen
         * @var string $pubexp
         */
        switch ($magic) {
            case self::RSA2:
                $components['isPublicKey'] = false;
            case self::RSA1:
                break;
            default:
                throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $baseLength = $bitlen / 16;
        if (strlen($key) != 2 * $baseLength && strlen($key) != 9 * $baseLength) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $components[$components['isPublicKey'] ? 'publicExponent' : 'privateExponent'] = new BigInteger(strrev($pubexp), 256);
        // BYTE modulus[rsapubkey.bitlen/8]
        $components['modulus'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256);
        if ($publickey) {
            return $components;
        }
        $components['isPublicKey'] = false;
        // BYTE prime1[rsapubkey.bitlen/16]
        $components['primes'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
        // BYTE prime2[rsapubkey.bitlen/16]
        $components['primes'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256);
        // BYTE exponent1[rsapubkey.bitlen/16]
        $components['exponents'] = [1 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
        // BYTE exponent2[rsapubkey.bitlen/16]
        $components['exponents'][] = new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256);
        // BYTE coefficient[rsapubkey.bitlen/16]
        $components['coefficients'] = [2 => new BigInteger(strrev(Strings::shift($key, $bitlen / 16)), 256)];
        if (isset($components['privateExponent'])) {
            $components['publicExponent'] = $components['privateExponent'];
        }
        // BYTE privateExponent[rsapubkey.bitlen/8]
        $components['privateExponent'] = new BigInteger(strrev(Strings::shift($key, $bitlen / 8)), 256);
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '')
    {
        if (count($primes) != 2) {
            throw new \InvalidArgumentException('MSBLOB does not support multi-prime RSA keys');
        }
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('MSBLOB private keys do not support encryption');
        }
        $n = strrev($n->toBytes());
        $e = str_pad(strrev($e->toBytes()), 4, "\x00");
        $key = pack('aavV', chr(self::PRIVATEKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
        $key .= pack('VVa*', self::RSA2, 8 * strlen($n), $e);
        $key .= $n;
        $key .= strrev($primes[1]->toBytes());
        $key .= strrev($primes[2]->toBytes());
        $key .= strrev($exponents[1]->toBytes());
        $key .= strrev($exponents[2]->toBytes());
        $key .= strrev($coefficients[2]->toBytes());
        $key .= strrev($d->toBytes());
        return Base64::encode($key);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return string
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        $n = strrev($n->toBytes());
        $e = str_pad(strrev($e->toBytes()), 4, "\x00");
        $key = pack('aavV', chr(self::PUBLICKEYBLOB), chr(2), 0, self::CALG_RSA_KEYX);
        $key .= pack('VVa*', self::RSA1, 8 * strlen($n), $e);
        $key .= $n;
        return Base64::encode($key);
    }
}<?php

/**
 * Raw RSA Key Handler
 *
 * PHP version 5
 *
 * An array containing two \phpseclib3\Math\BigInteger objects.
 *
 * The exponent can be indexed with any of the following:
 *
 * 0, e, exponent, publicExponent
 *
 * The modulus can be indexed with any of the following:
 *
 * 1, n, modulo, modulus
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
/**
 * Raw RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!is_array($key)) {
            throw new \UnexpectedValueException('Key should be a array - not a ' . gettype($key));
        }
        $key = array_change_key_case($key, CASE_LOWER);
        $components = ['isPublicKey' => false];
        foreach (['e', 'exponent', 'publicexponent', 0, 'privateexponent', 'd'] as $index) {
            if (isset($key[$index])) {
                $components['publicExponent'] = $key[$index];
                break;
            }
        }
        foreach (['n', 'modulo', 'modulus', 1] as $index) {
            if (isset($key[$index])) {
                $components['modulus'] = $key[$index];
                break;
            }
        }
        if (!isset($components['publicExponent']) || !isset($components['modulus'])) {
            throw new \UnexpectedValueException('Modulus / exponent not present');
        }
        if (isset($key['primes'])) {
            $components['primes'] = $key['primes'];
        } else {
            if (isset($key['p']) && isset($key['q'])) {
                $indices = [['p', 'q'], ['prime1', 'prime2']];
                foreach ($indices as $index) {
                    list($i0, $i1) = $index;
                    if (isset($key[$i0]) && isset($key[$i1])) {
                        $components['primes'] = [1 => $key[$i0], $key[$i1]];
                    }
                }
            }
        }
        if (isset($key['exponents'])) {
            $components['exponents'] = $key['exponents'];
        } else {
            $indices = [['dp', 'dq'], ['exponent1', 'exponent2']];
            foreach ($indices as $index) {
                list($i0, $i1) = $index;
                if (isset($key[$i0]) && isset($key[$i1])) {
                    $components['exponents'] = [1 => $key[$i0], $key[$i1]];
                }
            }
        }
        if (isset($key['coefficients'])) {
            $components['coefficients'] = $key['coefficients'];
        } else {
            foreach (['inverseq', 'q\'', 'coefficient'] as $index) {
                if (isset($key[$index])) {
                    $components['coefficients'] = [2 => $key[$index]];
                }
            }
        }
        if (!isset($components['primes'])) {
            $components['isPublicKey'] = true;
            return $components;
        }
        if (!isset($components['exponents'])) {
            $one = new BigInteger(1);
            $temp = $components['primes'][1]->subtract($one);
            $exponents = [1 => $components['publicExponent']->modInverse($temp)];
            $temp = $components['primes'][2]->subtract($one);
            $exponents[] = $components['publicExponent']->modInverse($temp);
            $components['exponents'] = $exponents;
        }
        if (!isset($components['coefficients'])) {
            $components['coefficients'] = [2 => $components['primes'][2]->modInverse($components['primes'][1])];
        }
        foreach (['privateexponent', 'd'] as $index) {
            if (isset($key[$index])) {
                $components['privateExponent'] = $key[$index];
                break;
            }
        }
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @param \phpseclib3\Math\BigInteger $d
     * @param array $primes
     * @param array $exponents
     * @param array $coefficients
     * @param string $password optional
     * @param array $options optional
     * @return array
     */
    public static function savePrivateKey(BigInteger $n, BigInteger $e, BigInteger $d, array $primes, array $exponents, array $coefficients, $password = '', array $options = [])
    {
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('Raw private keys do not support encryption');
        }
        return ['e' => clone $e, 'n' => clone $n, 'd' => clone $d, 'primes' => array_map(function ($var) {
            return clone $var;
        }, $primes), 'exponents' => array_map(function ($var) {
            return clone $var;
        }, $exponents), 'coefficients' => array_map(function ($var) {
            return clone $var;
        }, $coefficients)];
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $n
     * @param \phpseclib3\Math\BigInteger $e
     * @return array
     */
    public static function savePublicKey(BigInteger $n, BigInteger $e)
    {
        return ['e' => clone $e, 'n' => clone $n];
    }
}<?php

/**
 * RSA Private Key
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA;

use phpseclib3\Crypt\RSA;
use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Hash;
use phpseclib3\Exceptions\NoKeyLoadedException;
use phpseclib3\Exception\UnsupportedFormatException;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\Common;
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
/**
 * Raw RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrivateKey extends RSA implements Common\PrivateKey
{
    use Common\Traits\PasswordProtected;
    /**
     * Primes for Chinese Remainder Theorem (ie. p and q)
     *
     * @var array
     * @access private
     */
    protected $primes;
    /**
     * Exponents for Chinese Remainder Theorem (ie. dP and dQ)
     *
     * @var array
     * @access private
     */
    protected $exponents;
    /**
     * Coefficients for Chinese Remainder Theorem (ie. qInv)
     *
     * @var array
     * @access private
     */
    protected $coefficients;
    /**
     * Public Exponent
     *
     * @var mixed
     * @access private
     */
    protected $publicExponent = false;
    /**
     * RSADP
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.2 RFC3447#section-5.1.2}.
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $c
     * @return (bool | \phpseclib3\Math\BigInteger)
     */
    private function rsadp($c)
    {
        if ($c->compare(self::$zero) < 0 || $c->compare($this->modulus) > 0) {
            throw new \OutOfRangeException('Ciphertext representative out of range');
        }
        return $this->exponentiate($c);
    }
    /**
     * RSASP1
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.1 RFC3447#section-5.2.1}.
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $m
     * @return (bool | \phpseclib3\Math\BigInteger)
     */
    private function rsasp1($m)
    {
        if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) {
            throw new \OutOfRangeException('Signature representative out of range');
        }
        return $this->exponentiate($m);
    }
    /**
     * Exponentiate
     *
     * @param \phpseclib3\Math\BigInteger $x
     * @return \phpseclib3\Math\BigInteger
     */
    protected function exponentiate(BigInteger $x)
    {
        switch (true) {
            case empty($this->primes):
            case $this->primes[1]->equals(self::$zero):
            case empty($this->coefficients):
            case $this->coefficients[2]->equals(self::$zero):
            case empty($this->exponents):
            case $this->exponents[1]->equals(self::$zero):
                return $x->modPow($this->exponent, $this->modulus);
        }
        $num_primes = count($this->primes);
        if (!static::$enableBlinding) {
            $m_i = [1 => $x->modPow($this->exponents[1], $this->primes[1]), 2 => $x->modPow($this->exponents[2], $this->primes[2])];
            $h = $m_i[1]->subtract($m_i[2]);
            $h = $h->multiply($this->coefficients[2]);
            list(, $h) = $h->divide($this->primes[1]);
            $m = $m_i[2]->add($h->multiply($this->primes[2]));
            $r = $this->primes[1];
            for ($i = 3; $i <= $num_primes; $i++) {
                $m_i = $x->modPow($this->exponents[$i], $this->primes[$i]);
                $r = $r->multiply($this->primes[$i - 1]);
                $h = $m_i->subtract($m);
                $h = $h->multiply($this->coefficients[$i]);
                list(, $h) = $h->divide($this->primes[$i]);
                $m = $m->add($r->multiply($h));
            }
        } else {
            $smallest = $this->primes[1];
            for ($i = 2; $i <= $num_primes; $i++) {
                if ($smallest->compare($this->primes[$i]) > 0) {
                    $smallest = $this->primes[$i];
                }
            }
            $r = BigInteger::randomRange(self::$one, $smallest->subtract(self::$one));
            $m_i = [1 => $this->blind($x, $r, 1), 2 => $this->blind($x, $r, 2)];
            $h = $m_i[1]->subtract($m_i[2]);
            $h = $h->multiply($this->coefficients[2]);
            list(, $h) = $h->divide($this->primes[1]);
            $m = $m_i[2]->add($h->multiply($this->primes[2]));
            $r = $this->primes[1];
            for ($i = 3; $i <= $num_primes; $i++) {
                $m_i = $this->blind($x, $r, $i);
                $r = $r->multiply($this->primes[$i - 1]);
                $h = $m_i->subtract($m);
                $h = $h->multiply($this->coefficients[$i]);
                list(, $h) = $h->divide($this->primes[$i]);
                $m = $m->add($r->multiply($h));
            }
        }
        return $m;
    }
    /**
    * Performs RSA Blinding
    *
    * Protects against timing attacks by employing RSA Blinding.
    Returns $x->modPow($this->exponents[$i], $this->primes[$i])
    *
    * @access private
    * @param \phpseclib3\Math\BigInteger $x
    * @param \phpseclib3\Math\BigInteger $r
    * @param int $i
    * @return \phpseclib3\Math\BigInteger
    */
    private function blind($x, $r, $i)
    {
        $x = $x->multiply($r->modPow($this->publicExponent, $this->primes[$i]));
        $x = $x->modPow($this->exponents[$i], $this->primes[$i]);
        $r = $r->modInverse($this->primes[$i]);
        $x = $x->multiply($r);
        list(, $x) = $x->divide($this->primes[$i]);
        return $x;
    }
    /**
     * EMSA-PSS-ENCODE
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.1 RFC3447#section-9.1.1}.
     *
     * @return string
     * @access private
     * @param string $m
     * @throws \RuntimeException on encoding error
     * @param int $emBits
     */
    private function emsa_pss_encode($m, $emBits)
    {
        // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
        // be output.
        $emLen = $emBits + 1 >> 3;
        // ie. ceil($emBits / 8)
        $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
        $mHash = $this->hash->hash($m);
        if ($emLen < $this->hLen + $sLen + 2) {
            throw new \LengthException('RSA modulus too short');
        }
        $salt = Random::string($sLen);
        $m2 = "\x00\x00\x00\x00\x00\x00\x00\x00" . $mHash . $salt;
        $h = $this->hash->hash($m2);
        $ps = str_repeat(chr(0), $emLen - $sLen - $this->hLen - 2);
        $db = $ps . chr(1) . $salt;
        $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1);
        $maskedDB = $db ^ $dbMask;
        $maskedDB[0] = ~chr(0xff << ($emBits & 7)) & $maskedDB[0];
        $em = $maskedDB . $h . chr(0xbc);
        return $em;
    }
    /**
     * RSASSA-PSS-SIGN
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.1 RFC3447#section-8.1.1}.
     *
     * @access private
     * @param string $m
     * @return (bool | string)
     */
    private function rsassa_pss_sign($m)
    {
        // EMSA-PSS encoding
        $em = $this->emsa_pss_encode($m, 8 * $this->k - 1);
        // RSA signature
        $m = $this->os2ip($em);
        $s = $this->rsasp1($m);
        $s = $this->i2osp($s, $this->k);
        // Output the signature S
        return $s;
    }
    /**
     * RSASSA-PKCS1-V1_5-SIGN
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.1 RFC3447#section-8.2.1}.
     *
     * @access private
     * @param string $m
     * @throws \LengthException if the RSA modulus is too short
     * @return (bool | string)
     */
    private function rsassa_pkcs1_v1_5_sign($m)
    {
        // EMSA-PKCS1-v1_5 encoding
        // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus
        // too short" and stop.
        try {
            $em = $this->emsa_pkcs1_v1_5_encode($m, $this->k);
        } catch (\LengthException $e) {
            throw new \LengthException('RSA modulus too short');
        }
        // RSA signature
        $m = $this->os2ip($em);
        $s = $this->rsasp1($m);
        $s = $this->i2osp($s, $this->k);
        // Output the signature S
        return $s;
    }
    /**
     * Create a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @return string
     */
    public function sign($message)
    {
        switch ($this->signaturePadding) {
            case self::SIGNATURE_PKCS1:
            case self::SIGNATURE_RELAXED_PKCS1:
                return $this->rsassa_pkcs1_v1_5_sign($message);
            //case self::SIGNATURE_PSS:
            default:
                return $this->rsassa_pss_sign($message);
        }
    }
    /**
     * RSAES-PKCS1-V1_5-DECRYPT
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.2 RFC3447#section-7.2.2}.
     *
     * @access private
     * @param string $c
     * @return (bool | string)
     */
    private function rsaes_pkcs1_v1_5_decrypt($c)
    {
        // Length checking
        if (strlen($c) != $this->k) {
            // or if k < 11
            throw new \LengthException('Ciphertext representative too long');
        }
        // RSA decryption
        $c = $this->os2ip($c);
        $m = $this->rsadp($c);
        $em = $this->i2osp($m, $this->k);
        // EME-PKCS1-v1_5 decoding
        if (ord($em[0]) != 0 || ord($em[1]) > 2) {
            throw new \RuntimeException('Decryption error');
        }
        $ps = \Phabel\Target\Php80\Polyfill::substr($em, 2, strpos($em, chr(0), 2) - 2);
        $m = \Phabel\Target\Php80\Polyfill::substr($em, strlen($ps) + 3);
        if (strlen($ps) < 8) {
            throw new \RuntimeException('Decryption error');
        }
        // Output M
        return $m;
    }
    /**
    * RSAES-OAEP-DECRYPT
    *
    * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.2 RFC3447#section-7.1.2}.  The fact that the error
    messages aren't distinguishable from one another hinders debugging, but, to quote from RFC3447#section-7.1.2:
    *
    * Note.  Care must be taken to ensure that an opponent cannot
    distinguish the different error conditions in Step 3.g, whether by
    error message or timing, or, more generally, learn partial
    information about the encoded message EM.  Otherwise an opponent may
    be able to obtain useful information about the decryption of the
    ciphertext C, leading to a chosen-ciphertext attack such as the one
    observed by Manger [36].
    *
    * @access private
    * @param string $c
    * @return (bool | string)
    */
    private function rsaes_oaep_decrypt($c)
    {
        // Length checking
        // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
        // be output.
        if (strlen($c) != $this->k || $this->k < 2 * $this->hLen + 2) {
            throw new \LengthException('Ciphertext representative too long');
        }
        // RSA decryption
        $c = $this->os2ip($c);
        $m = $this->rsadp($c);
        $em = $this->i2osp($m, $this->k);
        // EME-OAEP decoding
        $lHash = $this->hash->hash($this->label);
        $y = ord($em[0]);
        $maskedSeed = \Phabel\Target\Php80\Polyfill::substr($em, 1, $this->hLen);
        $maskedDB = \Phabel\Target\Php80\Polyfill::substr($em, $this->hLen + 1);
        $seedMask = $this->mgf1($maskedDB, $this->hLen);
        $seed = $maskedSeed ^ $seedMask;
        $dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1);
        $db = $maskedDB ^ $dbMask;
        $lHash2 = \Phabel\Target\Php80\Polyfill::substr($db, 0, $this->hLen);
        $m = \Phabel\Target\Php80\Polyfill::substr($db, $this->hLen);
        $hashesMatch = hash_equals($lHash, $lHash2);
        $leadingZeros = 1;
        $patternMatch = 0;
        $offset = 0;
        for ($i = 0; $i < strlen($m); $i++) {
            $patternMatch |= $leadingZeros & $m[$i] === "\x01";
            $leadingZeros &= $m[$i] === "\x00";
            $offset += $patternMatch ? 0 : 1;
        }
        // we do | instead of || to avoid https://en.wikipedia.org/wiki/Short-circuit_evaluation
        // to protect against timing attacks
        if (!$hashesMatch | !$patternMatch) {
            throw new \RuntimeException('Decryption error');
        }
        // Output the message M
        return \Phabel\Target\Php80\Polyfill::substr($m, $offset + 1);
    }
    /**
     * Raw Encryption / Decryption
     *
     * Doesn't use padding and is not recommended.
     *
     * @access private
     * @param string $m
     * @return (bool | string)
     * @throws \LengthException if strlen($m) > $this->k
     */
    private function raw_encrypt($m)
    {
        if (strlen($m) > $this->k) {
            throw new \LengthException('Ciphertext representative too long');
        }
        $temp = $this->os2ip($m);
        $temp = $this->rsadp($temp);
        return $this->i2osp($temp, $this->k);
    }
    /**
     * Decryption
     *
     * @see self::encrypt()
     * @access public
     * @param string $ciphertext
     * @return (bool | string)
     */
    public function decrypt($ciphertext)
    {
        switch ($this->encryptionPadding) {
            case self::ENCRYPTION_NONE:
                return $this->raw_encrypt($ciphertext);
            case self::ENCRYPTION_PKCS1:
                return $this->rsaes_pkcs1_v1_5_decrypt($ciphertext);
            //case self::ENCRYPTION_OAEP:
            default:
                return $this->rsaes_oaep_decrypt($ciphertext);
        }
    }
    /**
     * Returns the public key
     *
     * @access public
     * @return mixed
     */
    public function getPublicKey()
    {
        $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey');
        if (empty($this->modulus) || empty($this->publicExponent)) {
            throw new \RuntimeException('Public key components not found');
        }
        $key = $type::savePublicKey($this->modulus, $this->publicExponent);
        return RSA::loadFormat('PKCS8', $key)->withHash($this->hash->getHash())->withMGFHash($this->mgfHash->getHash())->withSaltLength($this->sLen)->withLabel($this->label)->withPadding($this->signaturePadding | $this->encryptionPadding);
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, empty($this->primes) ? 'savePublicKey' : 'savePrivateKey');
        if ($type == PSS::class) {
            if ($this->signaturePadding == self::SIGNATURE_PSS) {
                $options += ['hash' => $this->hash->getHash(), 'MGFHash' => $this->mgfHash->getHash(), 'saltLength' => $this->getSaltLength()];
            } else {
                throw new UnsupportedFormatException('The PSS format can only be used when the signature method has been explicitly set to PSS');
            }
        }
        if (empty($this->primes)) {
            return $type::savePublicKey($this->modulus, $this->exponent, $options);
        }
        return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password, $options);
        /*
        $key = $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $this->primes, $this->exponents, $this->coefficients, $this->password, $options);
        if ($key !== false || count($this->primes) == 2) {
            return $key;
        }
        
        $nSize = $this->getSize() >> 1;
        
        $primes = [1 => clone self::$one, clone self::$one];
        $i = 1;
        foreach ($this->primes as $prime) {
            $primes[$i] = $primes[$i]->multiply($prime);
            if ($primes[$i]->getLength() >= $nSize) {
                $i++;
            }
        }
        
        $exponents = [];
        $coefficients = [2 => $primes[2]->modInverse($primes[1])];
        
        foreach ($primes as $i => $prime) {
            $temp = $prime->subtract(self::$one);
            $exponents[$i] = $this->modulus->modInverse($temp);
        }
        
        return $type::savePrivateKey($this->modulus, $this->publicExponent, $this->exponent, $primes, $exponents, $coefficients, $this->password, $options);
        */
    }
}<?php

/**
 * RSA Public Key
 *
 * @category  Crypt
 * @package   RSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\RSA;

use phpseclib3\Crypt\RSA;
use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Hash;
use phpseclib3\Exception\NoKeyLoadedException;
use phpseclib3\Exception\UnsupportedFormatException;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\Common;
use phpseclib3\File\ASN1\Maps\DigestInfo;
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
/**
 * Raw RSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PublicKey extends RSA implements Common\PublicKey
{
    use Common\Traits\Fingerprint;
    /**
     * Exponentiate
     *
     * @param \phpseclib3\Math\BigInteger $x
     * @return \phpseclib3\Math\BigInteger
     */
    private function exponentiate(BigInteger $x)
    {
        return $x->modPow($this->exponent, $this->modulus);
    }
    /**
     * RSAVP1
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-5.2.2 RFC3447#section-5.2.2}.
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $s
     * @return (bool | \phpseclib3\Math\BigInteger)
     */
    private function rsavp1($s)
    {
        if ($s->compare(self::$zero) < 0 || $s->compare($this->modulus) > 0) {
            return false;
        }
        return $this->exponentiate($s);
    }
    /**
     * RSASSA-PKCS1-V1_5-VERIFY
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-8.2.2 RFC3447#section-8.2.2}.
     *
     * @access private
     * @param string $m
     * @param string $s
     * @throws \LengthException if the RSA modulus is too short
     * @return bool
     */
    private function rsassa_pkcs1_v1_5_verify($m, $s)
    {
        // Length checking
        if (strlen($s) != $this->k) {
            return false;
        }
        // RSA verification
        $s = $this->os2ip($s);
        $m2 = $this->rsavp1($s);
        if ($m2 === false) {
            return false;
        }
        $em = $this->i2osp($m2, $this->k);
        if ($em === false) {
            return false;
        }
        // EMSA-PKCS1-v1_5 encoding
        $exception = false;
        // If the encoding operation outputs "intended encoded message length too short," output "RSA modulus
        // too short" and stop.
        try {
            $em2 = $this->emsa_pkcs1_v1_5_encode($m, $this->k);
            $r1 = hash_equals($em, $em2);
        } catch (\LengthException $e) {
            $exception = true;
        }
        try {
            $em3 = $this->emsa_pkcs1_v1_5_encode_without_null($m, $this->k);
            $r2 = hash_equals($em, $em3);
        } catch (\LengthException $e) {
            $exception = true;
        } catch (UnsupportedAlgorithmException $e) {
            $r2 = false;
        }
        if ($exception) {
            throw new \LengthException('RSA modulus too short');
        }
        // Compare
        return $r1 || $r2;
    }
    /**
    * RSASSA-PKCS1-V1_5-VERIFY (relaxed matching)
    *
    * Per {@link http://tools.ietf.org/html/rfc3447#page-43 RFC3447#page-43} PKCS1 v1.5
    specified the use BER encoding rather than DER encoding that PKCS1 v2.0 specified.
    This means that under rare conditions you can have a perfectly valid v1.5 signature
    that fails to validate with _rsassa_pkcs1_v1_5_verify(). PKCS1 v2.1 also recommends
    that if you're going to validate these types of signatures you "should indicate
    whether the underlying BER encoding is a DER encoding and hence whether the signature
    is valid with respect to the specification given in [PKCS1 v2.0+]". so if you do
    $rsa->getLastPadding() and get RSA::PADDING_RELAXED_PKCS1 back instead of
    RSA::PADDING_PKCS1... that means BER encoding was used.
    *
    * @access private
    * @param string $m
    * @param string $s
    * @return bool
    */
    private function rsassa_pkcs1_v1_5_relaxed_verify($m, $s)
    {
        // Length checking
        if (strlen($s) != $this->k) {
            return false;
        }
        // RSA verification
        $s = $this->os2ip($s);
        $m2 = $this->rsavp1($s);
        if ($m2 === false) {
            return false;
        }
        $em = $this->i2osp($m2, $this->k);
        if ($em === false) {
            return false;
        }
        if (Strings::shift($em, 2) != "\x00\x01") {
            return false;
        }
        $em = ltrim($em, "\xff");
        if (Strings::shift($em) != "\x00") {
            return false;
        }
        $decoded = ASN1::decodeBER($em);
        if (!is_array($decoded) || empty($decoded[0]) || strlen($em) > $decoded[0]['length']) {
            return false;
        }
        static $oids;
        if (!isset($oids)) {
            $oids = [
                'md2' => '1.2.840.113549.2.2',
                'md4' => '1.2.840.113549.2.4',
                // from PKCS1 v1.5
                'md5' => '1.2.840.113549.2.5',
                'id-sha1' => '1.3.14.3.2.26',
                'id-sha256' => '2.16.840.1.101.3.4.2.1',
                'id-sha384' => '2.16.840.1.101.3.4.2.2',
                'id-sha512' => '2.16.840.1.101.3.4.2.3',
                // from PKCS1 v2.2
                'id-sha224' => '2.16.840.1.101.3.4.2.4',
                'id-sha512/224' => '2.16.840.1.101.3.4.2.5',
                'id-sha512/256' => '2.16.840.1.101.3.4.2.6',
            ];
            ASN1::loadOIDs($oids);
        }
        $decoded = ASN1::asn1map($decoded[0], DigestInfo::MAP);
        if (!isset($decoded) || $decoded === false) {
            return false;
        }
        if (!isset($oids[$decoded['digestAlgorithm']['algorithm']])) {
            return false;
        }
        if (isset($decoded['digestAlgorithm']['parameters']) && $decoded['digestAlgorithm']['parameters'] !== ['null' => '']) {
            return false;
        }
        $hash = $decoded['digestAlgorithm']['algorithm'];
        $hash = \Phabel\Target\Php80\Polyfill::substr($hash, 0, 3) == 'id-' ? \Phabel\Target\Php80\Polyfill::substr($hash, 3) : $hash;
        $hash = new Hash($hash);
        $em = $hash->hash($m);
        $em2 = $decoded['digest'];
        return hash_equals($em, $em2);
    }
    /**
     * EMSA-PSS-VERIFY
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-9.1.2 RFC3447#section-9.1.2}.
     *
     * @access private
     * @param string $m
     * @param string $em
     * @param int $emBits
     * @return string
     */
    private function emsa_pss_verify($m, $em, $emBits)
    {
        // if $m is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
        // be output.
        $emLen = $emBits + 7 >> 3;
        // ie. ceil($emBits / 8);
        $sLen = $this->sLen !== null ? $this->sLen : $this->hLen;
        $mHash = $this->hash->hash($m);
        if ($emLen < $this->hLen + $sLen + 2) {
            return false;
        }
        if ($em[strlen($em) - 1] != chr(0xbc)) {
            return false;
        }
        $maskedDB = \Phabel\Target\Php80\Polyfill::substr($em, 0, -$this->hLen - 1);
        $h = \Phabel\Target\Php80\Polyfill::substr($em, -$this->hLen - 1, $this->hLen);
        $temp = chr(0xff << ($emBits & 7));
        if ((~$maskedDB[0] & $temp) != $temp) {
            return false;
        }
        $dbMask = $this->mgf1($h, $emLen - $this->hLen - 1);
        $db = $maskedDB ^ $dbMask;
        $db[0] = ~chr(0xff << ($emBits & 7)) & $db[0];
        $temp = $emLen - $this->hLen - $sLen - 2;
        if (\Phabel\Target\Php80\Polyfill::substr($db, 0, $temp) != str_repeat(chr(0), $temp) || ord($db[$temp]) != 1) {
            return false;
        }
        $salt = \Phabel\Target\Php80\Polyfill::substr($db, $temp + 1);
        // should be $sLen long
        $m2 = "\x00\x00\x00\x00\x00\x00\x00\x00" . $mHash . $salt;
        $h2 = $this->hash->hash($m2);
        return hash_equals($h, $h2);
    }
    /**
     * RSASSA-PSS-VERIFY
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-8.1.2 RFC3447#section-8.1.2}.
     *
     * @access private
     * @param string $m
     * @param string $s
     * @return (bool | string)
     */
    private function rsassa_pss_verify($m, $s)
    {
        // Length checking
        if (strlen($s) != $this->k) {
            return false;
        }
        // RSA verification
        $modBits = strlen($this->modulus->toBits());
        $s2 = $this->os2ip($s);
        $m2 = $this->rsavp1($s2);
        $em = $this->i2osp($m2, $this->k);
        if ($em === false) {
            return false;
        }
        // EMSA-PSS verification
        return $this->emsa_pss_verify($m, $em, $modBits - 1);
    }
    /**
     * Verifies a signature
     *
     * @see self::sign()
     * @param string $message
     * @param string $signature
     * @return bool
     */
    public function verify($message, $signature)
    {
        switch ($this->signaturePadding) {
            case self::SIGNATURE_RELAXED_PKCS1:
                return $this->rsassa_pkcs1_v1_5_relaxed_verify($message, $signature);
            case self::SIGNATURE_PKCS1:
                return $this->rsassa_pkcs1_v1_5_verify($message, $signature);
            //case self::SIGNATURE_PSS:
            default:
                return $this->rsassa_pss_verify($message, $signature);
        }
    }
    /**
     * RSAES-PKCS1-V1_5-ENCRYPT
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-7.2.1 RFC3447#section-7.2.1}.
     *
     * @access private
     * @param string $m
     * @param bool $pkcs15_compat optional
     * @throws \LengthException if strlen($m) > $this->k - 11
     * @return (bool | string)
     */
    private function rsaes_pkcs1_v1_5_encrypt($m, $pkcs15_compat = false)
    {
        $mLen = strlen($m);
        // Length checking
        if ($mLen > $this->k - 11) {
            throw new \LengthException('Message too long');
        }
        // EME-PKCS1-v1_5 encoding
        $psLen = $this->k - $mLen - 3;
        $ps = '';
        while (strlen($ps) != $psLen) {
            $temp = Random::string($psLen - strlen($ps));
            $temp = str_replace("\x00", '', $temp);
            $ps .= $temp;
        }
        $type = 2;
        $em = chr(0) . chr($type) . $ps . chr(0) . $m;
        // RSA encryption
        $m = $this->os2ip($em);
        $c = $this->rsaep($m);
        $c = $this->i2osp($c, $this->k);
        // Output the ciphertext C
        return $c;
    }
    /**
    * RSAES-OAEP-ENCRYPT
    *
    * See {@link http://tools.ietf.org/html/rfc3447#section-7.1.1 RFC3447#section-7.1.1} and
    {http://en.wikipedia.org/wiki/Optimal_Asymmetric_Encryption_Padding OAES}.
    *
    * @access private
    * @param string $m
    * @throws \LengthException if strlen($m) > $this->k - 2 * $this->hLen - 2
    * @return string
    */
    private function rsaes_oaep_encrypt($m)
    {
        $mLen = strlen($m);
        // Length checking
        // if $l is larger than two million terrabytes and you're using sha1, PKCS#1 suggests a "Label too long" error
        // be output.
        if ($mLen > $this->k - 2 * $this->hLen - 2) {
            throw new \LengthException('Message too long');
        }
        // EME-OAEP encoding
        $lHash = $this->hash->hash($this->label);
        $ps = str_repeat(chr(0), $this->k - $mLen - 2 * $this->hLen - 2);
        $db = $lHash . $ps . chr(1) . $m;
        $seed = Random::string($this->hLen);
        $dbMask = $this->mgf1($seed, $this->k - $this->hLen - 1);
        $maskedDB = $db ^ $dbMask;
        $seedMask = $this->mgf1($maskedDB, $this->hLen);
        $maskedSeed = $seed ^ $seedMask;
        $em = chr(0) . $maskedSeed . $maskedDB;
        // RSA encryption
        $m = $this->os2ip($em);
        $c = $this->rsaep($m);
        $c = $this->i2osp($c, $this->k);
        // Output the ciphertext C
        return $c;
    }
    /**
     * RSAEP
     *
     * See {@link http://tools.ietf.org/html/rfc3447#section-5.1.1 RFC3447#section-5.1.1}.
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $m
     * @return (bool | \phpseclib3\Math\BigInteger)
     */
    private function rsaep($m)
    {
        if ($m->compare(self::$zero) < 0 || $m->compare($this->modulus) > 0) {
            throw new \OutOfRangeException('Message representative out of range');
        }
        return $this->exponentiate($m);
    }
    /**
     * Raw Encryption / Decryption
     *
     * Doesn't use padding and is not recommended.
     *
     * @access private
     * @param string $m
     * @return (bool | string)
     * @throws \LengthException if strlen($m) > $this->k
     */
    private function raw_encrypt($m)
    {
        if (strlen($m) > $this->k) {
            throw new \LengthException('Message too long');
        }
        $temp = $this->os2ip($m);
        $temp = $this->rsaep($temp);
        return $this->i2osp($temp, $this->k);
    }
    /**
    * Encryption
    *
    * Both self::PADDING_OAEP and self::PADDING_PKCS1 both place limits on how long $plaintext can be.
    If $plaintext exceeds those limits it will be broken up so that it does and the resultant ciphertext's will
    be concatenated together.
    *
    * @see self::decrypt()
    * @access public
    * @param string $plaintext
    * @return (bool | string)
    * @throws \LengthException if the RSA modulus is too short
    */
    public function encrypt($plaintext)
    {
        switch ($this->encryptionPadding) {
            case self::ENCRYPTION_NONE:
                return $this->raw_encrypt($plaintext);
            case self::ENCRYPTION_PKCS1:
                return $this->rsaes_pkcs1_v1_5_encrypt($plaintext);
            //case self::ENCRYPTION_OAEP:
            default:
                return $this->rsaes_oaep_encrypt($plaintext);
        }
    }
    /**
    * Returns the public key
    *
    * The public key is only returned under two circumstances - if the private key had the public key embedded within it
    or if the public key was set via setPublicKey().  If the currently loaded key is supposed to be the public key this
    function won't return it since this library, for the most part, doesn't distinguish between public and private keys.
    *
    * @param string $type
    * @param array $options optional
    * @return mixed
    */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePublicKey');
        if ($type == PSS::class) {
            if ($this->signaturePadding == self::SIGNATURE_PSS) {
                $options += ['hash' => $this->hash->getHash(), 'MGFHash' => $this->mgfHash->getHash(), 'saltLength' => $this->getSaltLength()];
            } else {
                throw new UnsupportedFormatException('The PSS format can only be used when the signature method has been explicitly set to PSS');
            }
        }
        return $type::savePublicKey($this->modulus, $this->publicExponent, $options);
    }
    /**
     * Converts a public key to a private key
     *
     * @return RSA
     */
    public function asPrivateKey()
    {
        $new = new PrivateKey();
        $new->exponent = $this->exponent;
        $new->modulus = $this->modulus;
        $new->k = $this->k;
        $new->format = $this->format;
        return $new->withHash($this->hash->getHash())->withMGFHash($this->mgfHash->getHash())->withSaltLength($this->sLen)->withLabel($this->label)->withPadding($this->signaturePadding | $this->encryptionPadding);
    }
}<?php

/**
 * PublicKeyLoader
 *
 * Returns a PublicKey or PrivateKey object.
 *
 * @category  Crypt
 * @package   PublicKeyLoader
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\Common\PublicKey;
use phpseclib3\Crypt\Common\PrivateKey;
use phpseclib3\Exception\NoKeyLoadedException;
use phpseclib3\File\X509;
/**
 * PublicKeyLoader
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PublicKeyLoader
{
    /**
     * Loads a public or private key
     *
     * @return AsymmetricKey
     * @access public
     * @param (string | array) $key
     * @param string $password optional
     */
    public static function load($key, $password = false)
    {
        try {
            return EC::load($key, $password);
        } catch (NoKeyLoadedException $e) {
        }
        try {
            return RSA::load($key, $password);
        } catch (NoKeyLoadedException $e) {
        }
        try {
            return DSA::load($key, $password);
        } catch (NoKeyLoadedException $e) {
        }
        try {
            $x509 = new X509();
            $x509->loadX509($key);
            $key = $x509->getPublicKey();
            if ($key) {
                return $key;
            }
        } catch (\Exception $e) {
        }
        throw new NoKeyLoadedException('Unable to read key');
    }
    /**
     * Loads a private key
     *
     * @return PrivateKey
     * @access public
     * @param (string | array) $key
     * @param string $password optional
     */
    public static function loadPrivateKey($key, $password = false)
    {
        $key = self::load($key, $password);
        if (!$key instanceof PrivateKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a private key');
        }
        return $key;
    }
    /**
     * Loads a public key
     *
     * @return PublicKey
     * @access public
     * @param (string | array) $key
     */
    public static function loadPublicKey($key)
    {
        $key = self::load($key);
        if (!$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a public key');
        }
        return $key;
    }
    /**
     * Loads parameters
     *
     * @return AsymmetricKey
     * @access public
     * @param (string | array) $key
     */
    public static function loadParameters($key)
    {
        $key = self::load($key);
        if (!$key instanceof PrivateKey && !$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a parameter');
        }
        return $key;
    }
}<?php

/**
 * PKCS#1 Formatted DSA Key Handler
 *
 * PHP version 5
 *
 * Used by File/X509.php
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN DSA PRIVATE KEY-----
 * -----BEGIN DSA PUBLIC KEY-----
 * -----BEGIN DSA PARAMETERS-----
 *
 * Analogous to ssh-keygen's pem format (as specified by -m)
 *
 * Also, technically, PKCS1 decribes RSA but I am not aware of a formal specification for DSA.
 * The DSA private key format seems to have been adapted from the RSA private key format so
 * we're just re-using that as the name.
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use ParagonIE\ConstantTime\Base64;
/**
 * PKCS#1 Formatted DSA Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends Progenitor
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $key = parent::load($key, $password);
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $key = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP);
        if (is_array($key)) {
            return $key;
        }
        $key = ASN1::asn1map($decoded[0], Maps\DSAPrivateKey::MAP);
        if (is_array($key)) {
            return $key;
        }
        $key = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
        if (is_array($key)) {
            return $key;
        }
        throw new \RuntimeException('Unable to perform ASN1 mapping');
    }
    /**
     * Convert DSA parameters to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @return string
     */
    public static function saveParameters(BigInteger $p, BigInteger $q, BigInteger $g)
    {
        $key = ['p' => $p, 'q' => $q, 'g' => $g];
        $key = ASN1::encodeDER($key, Maps\DSAParams::MAP);
        return "-----BEGIN DSA PARAMETERS-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END DSA PARAMETERS-----\r\n";
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = [])
    {
        $key = ['version' => 0, 'p' => $p, 'q' => $q, 'g' => $g, 'y' => $y, 'x' => $x];
        $key = ASN1::encodeDER($key, Maps\DSAPrivateKey::MAP);
        return self::wrapPrivateKey($key, 'DSA', $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y)
    {
        $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP);
        return self::wrapPublicKey($key, 'DSA');
    }
}<?php

/**
 * PKCS#8 Formatted DSA Key Handler
 *
 * PHP version 5
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
 * is specific to private keys it's basically creating a DER-encoded wrapper
 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends Progenitor
{
    /**
     * OID Name
     *
     * @var string
     * @access private
     */
    const OID_NAME = 'id-dsa';
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = '1.2.840.10040.4.1';
    /**
     * Child OIDs loaded
     *
     * @var bool
     * @access private
     */
    protected static $childOIDsLoaded = false;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $isPublic = strpos($key, 'PUBLIC') !== false;
        $key = parent::load($key, $password);
        $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
        switch (true) {
            case !$isPublic && $type == 'publicKey':
                throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
            case $isPublic && $type == 'privateKey':
                throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
        }
        $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER of parameters');
        }
        $components = ASN1::asn1map($decoded[0], Maps\DSAParams::MAP);
        if (!is_array($components)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping on parameters');
        }
        $decoded = ASN1::decodeBER($key[$type]);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $var = $type == 'privateKey' ? 'x' : 'y';
        $components[$var] = ASN1::asn1map($decoded[0], Maps\DSAPublicKey::MAP);
        if (!$components[$var] instanceof BigInteger) {
            throw new \RuntimeException('Unable to perform ASN1 mapping');
        }
        if (isset($key['meta'])) {
            $components['meta'] = $key['meta'];
        }
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = [])
    {
        $params = ['p' => $p, 'q' => $q, 'g' => $g];
        $params = ASN1::encodeDER($params, Maps\DSAParams::MAP);
        $params = new ASN1\Element($params);
        $key = ASN1::encodeDER($x, Maps\DSAPublicKey::MAP);
        return self::wrapPrivateKey($key, [], $params, $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, array $options = [])
    {
        $params = ['p' => $p, 'q' => $q, 'g' => $g];
        $params = ASN1::encodeDER($params, Maps\DSAParams::MAP);
        $params = new ASN1\Element($params);
        $key = ASN1::encodeDER($y, Maps\DSAPublicKey::MAP);
        return self::wrapPublicKey($key, $params);
    }
}<?php

/**
 * PuTTY Formatted DSA Key Handler
 *
 * puttygen does not generate DSA keys with an N of anything other than 160, however,
 * it can still load them and convert them. PuTTY will load them, too, but SSH servers
 * won't accept them. Since PuTTY formatted keys are primarily used with SSH this makes
 * keys with N > 160 kinda useless, hence this handlers not supporting such keys.
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor;
/**
 * PuTTY Formatted DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PuTTY extends Progenitor
{
    /**
     * Public Handler
     *
     * @var string
     * @access private
     */
    const PUBLIC_HANDLER = 'phpseclib3\\Crypt\\DSA\\Formats\\Keys\\OpenSSH';
    /**
     * Algorithm Identifier
     *
     * @var array
     * @access private
     */
    protected static $types = ['ssh-dss'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $components = parent::load($key, $password);
        if (!isset($components['private'])) {
            return $components;
        }
        extract($components);
        unset($components['public'], $components['private']);
        list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $public);
        list($x) = Strings::unpackSSH2('i', $private);
        return compact('p', 'q', 'g', 'y', 'x', 'comment');
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = false, array $options = [])
    {
        if ($q->getLength() != 160) {
            throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
        }
        $public = Strings::packSSH2('iiii', $p, $q, $g, $y);
        $private = Strings::packSSH2('i', $x);
        return self::wrapPrivateKey($public, $private, 'ssh-dsa', $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y)
    {
        if ($q->getLength() != 160) {
            throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
        }
        return self::wrapPublicKey(Strings::packSSH2('iiii', $p, $q, $g, $y), 'ssh-dsa');
    }
}<?php

/**
 * XML Formatted DSA Key Handler
 *
 * While XKMS defines a private key format for RSA it does not do so for DSA. Quoting that standard:
 *
 * "[XKMS] does not specify private key parameters for the DSA signature algorithm since the algorithm only
 *  supports signature modes and so the application of server generated keys and key recovery is of limited
 *  value"
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
/**
 * XML Formatted DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class XML
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $use_errors = libxml_use_internal_errors(true);
        $dom = new \DOMDocument();
        if (\Phabel\Target\Php80\Polyfill::substr($key, 0, 5) != '<?xml') {
            $key = '<xml>' . $key . '</xml>';
        }
        if (!$dom->loadXML($key)) {
            throw new \UnexpectedValueException('Key does not appear to contain XML');
        }
        $xpath = new \DOMXPath($dom);
        $keys = ['p', 'q', 'g', 'y', 'j', 'seed', 'pgencounter'];
        foreach ($keys as $key) {
            // $dom->getElementsByTagName($key) is case-sensitive
            $temp = $xpath->query("//*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='{$key}']");
            if (!$temp->length) {
                continue;
            }
            $value = new BigInteger(Base64::decode($temp->item(0)->nodeValue), 256);
            switch ($key) {
                case 'p':
                    // a prime modulus meeting the [DSS] requirements
                    // Parameters P, Q, and G can be public and common to a group of users. They might be known
                    // from application context. As such, they are optional but P and Q must either both appear
                    // or both be absent
                    $components['p'] = $value;
                    break;
                case 'q':
                    // an integer in the range 2**159 < Q < 2**160 which is a prime divisor of P-1
                    $components['q'] = $value;
                    break;
                case 'g':
                    // an integer with certain properties with respect to P and Q
                    $components['g'] = $value;
                    break;
                case 'y':
                    // G**X mod P (where X is part of the private key and not made public)
                    $components['y'] = $value;
                // the remaining options do not do anything
                case 'j':
                // (P - 1) / Q
                // Parameter J is available for inclusion solely for efficiency as it is calculatable from
                // P and Q
                case 'seed':
                // a DSA prime generation seed
                // Parameters seed and pgenCounter are used in the DSA prime number generation algorithm
                // specified in [DSS]. As such, they are optional but must either both be present or both
                // be absent
                case 'pgencounter':
            }
        }
        libxml_use_internal_errors($use_errors);
        if (!isset($components['y'])) {
            throw new \UnexpectedValueException('Key is missing y component');
        }
        switch (true) {
            case !isset($components['p']):
            case !isset($components['q']):
            case !isset($components['g']):
                return ['y' => $components['y']];
        }
        return $components;
    }
    /**
     * Convert a public key to the appropriate format
     *
     * See https://www.w3.org/TR/xmldsig-core/#sec-DSAKeyValue
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y)
    {
        return '<DSAKeyValue>
  <P>' . Base64::encode($p->toBytes()) . '</P>
  <Q>' . Base64::encode($q->toBytes()) . '</Q>
  <G>' . Base64::encode($g->toBytes()) . '</G>
  <Y>' . Base64::encode($y->toBytes()) . '</Y>
</DSAKeyValue>';
    }
}<?php

/**
 * OpenSSH Formatted DSA Key Handler
 *
 * PHP version 5
 *
 * Place in $HOME/.ssh/authorized_keys
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor;
/**
 * OpenSSH Formatted DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSH extends Progenitor
{
    /**
     * Supported Key Types
     *
     * @var array
     */
    protected static $types = ['ssh-dss'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $parsed = parent::load($key, $password);
        if (isset($parsed['paddedKey'])) {
            list($type) = Strings::unpackSSH2('s', $parsed['paddedKey']);
            if ($type != $parsed['type']) {
                throw new \RuntimeException("The public and private keys are not of the same type ({$type} vs {$parsed['type']})");
            }
            list($p, $q, $g, $y, $x, $comment) = Strings::unpackSSH2('i5s', $parsed['paddedKey']);
            return compact('p', 'q', 'g', 'y', 'x', 'comment');
        }
        list($p, $q, $g, $y) = Strings::unpackSSH2('iiii', $parsed['publicKey']);
        $comment = $parsed['comment'];
        return compact('p', 'q', 'g', 'y', 'comment');
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, array $options = [])
    {
        if ($q->getLength() != 160) {
            throw new \InvalidArgumentException('SSH only supports keys with an N (length of Group Order q) of 160');
        }
        // from <http://tools.ietf.org/html/rfc4253#page-15>:
        // string    "ssh-dss"
        // mpint     p
        // mpint     q
        // mpint     g
        // mpint     y
        $DSAPublicKey = Strings::packSSH2('siiii', 'ssh-dss', $p, $q, $g, $y);
        if (isset($options['binary']) ? $options['binary'] : self::$binary) {
            return $DSAPublicKey;
        }
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        $DSAPublicKey = 'ssh-dss ' . base64_encode($DSAPublicKey) . ' ' . $comment;
        return $DSAPublicKey;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '', array $options = [])
    {
        $publicKey = self::savePublicKey($p, $q, $g, $y, ['binary' => true]);
        $privateKey = Strings::packSSH2('si5', 'ssh-dss', $p, $q, $g, $y, $x);
        return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
    }
}<?php

/**
 * Raw DSA Key Handler
 *
 * PHP version 5
 *
 * Reads and creates arrays as DSA keys
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Keys;

use phpseclib3\Math\BigInteger;
/**
 * Raw DSA Key Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param array $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!is_array($key)) {
            throw new \UnexpectedValueException('Key should be a array - not a ' . gettype($key));
        }
        switch (true) {
            case !isset($key['p']) || !isset($key['q']) || !isset($key['g']):
            case !$key['p'] instanceof BigInteger:
            case !$key['q'] instanceof BigInteger:
            case !$key['g'] instanceof BigInteger:
            case !isset($key['x']) && !isset($key['y']):
            case isset($key['x']) && !$key['x'] instanceof BigInteger:
            case isset($key['y']) && !$key['y'] instanceof BigInteger:
                throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $options = ['p' => 1, 'q' => 1, 'g' => 1, 'x' => 1, 'y' => 1];
        return array_intersect_key($key, $options);
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @param \phpseclib3\Math\BigInteger $x
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y, BigInteger $x, $password = '')
    {
        return compact('p', 'q', 'g', 'y', 'x');
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $p
     * @param \phpseclib3\Math\BigInteger $q
     * @param \phpseclib3\Math\BigInteger $g
     * @param \phpseclib3\Math\BigInteger $y
     * @return string
     */
    public static function savePublicKey(BigInteger $p, BigInteger $q, BigInteger $g, BigInteger $y)
    {
        return compact('p', 'q', 'g', 'y');
    }
}<?php

/**
 * ASN1 Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures in the format described in
 * https://tools.ietf.org/html/rfc3279#section-2.2.2
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Signature;

use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1 as Encoder;
use phpseclib3\File\ASN1\Maps;
/**
 * ASN1 Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ASN1
{
    /**
     * Loads a signature
     *
     * @access public
     * @param string $sig
     * @return (array | bool)
     */
    public static function load($sig)
    {
        if (!is_string($sig)) {
            return false;
        }
        $decoded = Encoder::decodeBER($sig);
        if (empty($decoded)) {
            return false;
        }
        $components = Encoder::asn1map($decoded[0], Maps\DssSigValue::MAP);
        return $components;
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s)
    {
        return Encoder::encodeDER(compact('r', 's'), Maps\DssSigValue::MAP);
    }
}<?php

/**
 * Raw DSA Signature Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Signature;

use phpseclib3\Crypt\Common\Formats\Signature\Raw as Progenitor;
/**
 * Raw DSA Signature Handler
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw extends Progenitor
{
}<?php

/**
 * SSH2 Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures in the format used by SSH2
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA\Formats\Signature;

use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
/**
 * SSH2 Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SSH2
{
    /**
     * Loads a signature
     *
     * @access public
     * @param string $sig
     * @return mixed
     */
    public static function load($sig)
    {
        if (!is_string($sig)) {
            return false;
        }
        $result = Strings::unpackSSH2('ss', $sig);
        if ($result === false) {
            return false;
        }
        list($type, $blob) = $result;
        if ($type != 'ssh-dss' || strlen($blob) != 40) {
            return false;
        }
        return ['r' => new BigInteger(\Phabel\Target\Php80\Polyfill::substr($blob, 0, 20), 256), 's' => new BigInteger(\Phabel\Target\Php80\Polyfill::substr($blob, 20), 256)];
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s)
    {
        if ($r->getLength() > 160 || $s->getLength() > 160) {
            return false;
        }
        return Strings::packSSH2('ss', 'ssh-dss', str_pad($r->toBytes(), 20, "\x00", STR_PAD_LEFT) . str_pad($s->toBytes(), 20, "\x00", STR_PAD_LEFT));
    }
}<?php

/**
 * DSA Parameters
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA;

use phpseclib3\Crypt\DSA;
/**
 * DSA Parameters
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Parameters extends DSA
{
    /**
     * Returns the parameters
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type = 'PKCS1', array $options = [])
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        return $type::saveParameters($this->p, $this->q, $this->g, $options);
    }
}<?php

/**
 * DSA Private Key
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA;

use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common;
/**
 * DSA Private Key
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrivateKey extends DSA implements Common\PrivateKey
{
    use Common\Traits\PasswordProtected;
    /**
     * DSA secret exponent x
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $x;
    /**
    * Returns the public key
    *
    * If you do "openssl rsa -in private.rsa -pubout -outform PEM" you get a PKCS8 formatted key
    that contains a publicKeyAlgorithm AlgorithmIdentifier and a publicKey BIT STRING.
    An AlgorithmIdentifier contains an OID and a parameters field. With RSA public keys this
    parameters field is NULL. With DSA PKCS8 public keys it is not - it contains the p, q and g
    variables. The publicKey BIT STRING contains, simply, the y variable. This can be verified
    by getting a DSA PKCS8 public key:
    *
    * "openssl dsa -in private.dsa -pubout -outform PEM"
    *
    * ie. just swap out rsa with dsa in the rsa command above.
    *
    * A PKCS1 public key corresponds to the publicKey portion of the PKCS8 key. In the case of RSA
    the publicKey portion /is/ the key. In the case of DSA it is not. You cannot verify a signature
    without the parameters and the PKCS1 DSA public key format does not include the parameters.
    *
    * @see self::getPrivateKey()
    * @access public
    * @return mixed
    */
    public function getPublicKey()
    {
        $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey');
        if (!isset($this->y)) {
            $this->y = $this->g->powMod($this->x, $this->p);
        }
        $key = $type::savePublicKey($this->p, $this->q, $this->g, $this->y);
        return DSA::loadFormat('PKCS8', $key)->withHash($this->hash->getHash())->withSignatureFormat($this->shortFormat);
    }
    /**
     * Create a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @return mixed
     */
    public function sign($message)
    {
        $format = $this->sigFormat;
        if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
            $signature = '';
            $result = openssl_sign($message, $signature, $this->toString('PKCS8'), $this->hash->getHash());
            if ($result) {
                if ($this->shortFormat == 'ASN1') {
                    return $signature;
                }
                extract(ASN1Signature::load($signature));
                return $format::save($r, $s);
            }
        }
        $h = $this->hash->hash($message);
        $h = $this->bits2int($h);
        while (true) {
            $k = BigInteger::randomRange(self::$one, $this->q->subtract(self::$one));
            $r = $this->g->powMod($k, $this->p);
            list(, $r) = $r->divide($this->q);
            if ($r->equals(self::$zero)) {
                continue;
            }
            $kinv = $k->modInverse($this->q);
            $temp = $h->add($this->x->multiply($r));
            $temp = $kinv->multiply($temp);
            list(, $s) = $temp->divide($this->q);
            if (!$s->equals(self::$zero)) {
                break;
            }
        }
        // the following is an RFC6979 compliant implementation of deterministic DSA
        // it's unused because it's mainly intended for use when a good CSPRNG isn't
        // available. if phpseclib's CSPRNG isn't good then even key generation is
        // suspect
        /*
        $h1 = $this->hash->hash($message);
        $k = $this->computek($h1);
        $r = $this->g->powMod($k, $this->p);
        list(, $r) = $r->divide($this->q);
        $kinv = $k->modInverse($this->q);
        $h1 = $this->bits2int($h1);
        $temp = $h1->add($this->x->multiply($r));
        $temp = $kinv->multiply($temp);
        list(, $s) = $temp->divide($this->q);
        */
        return $format::save($r, $s);
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePrivateKey');
        if (!isset($this->y)) {
            $this->y = $this->g->powMod($this->x, $this->p);
        }
        return $type::savePrivateKey($this->p, $this->q, $this->g, $this->y, $this->x, $this->password, $options);
    }
}<?php

/**
 * DSA Public Key
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DSA;

use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\DSA\Formats\Signature\ASN1 as ASN1Signature;
use phpseclib3\Crypt\Common;
/**
 * DSA Public Key
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PublicKey extends DSA implements Common\PublicKey
{
    use Common\Traits\Fingerprint;
    /**
     * Verify a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @param string $signature
     * @return mixed
     */
    public function verify($message, $signature)
    {
        $format = $this->sigFormat;
        $params = $format::load($signature);
        if ($params === false || count($params) != 2) {
            return false;
        }
        extract($params);
        if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
            $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature;
            $result = openssl_verify($message, $sig, $this->toString('PKCS8'), $this->hash->getHash());
            if ($result != -1) {
                return (bool) $result;
            }
        }
        $q_1 = $this->q->subtract(self::$one);
        if (!$r->between(self::$one, $q_1) || !$s->between(self::$one, $q_1)) {
            return false;
        }
        $w = $s->modInverse($this->q);
        $h = $this->hash->hash($message);
        $h = $this->bits2int($h);
        list(, $u1) = $h->multiply($w)->divide($this->q);
        list(, $u2) = $r->multiply($w)->divide($this->q);
        $v1 = $this->g->powMod($u1, $this->p);
        $v2 = $this->y->powMod($u2, $this->p);
        list(, $v) = $v1->multiply($v2)->divide($this->p);
        list(, $v) = $v->divide($this->q);
        return $v->equals($r);
    }
    /**
     * Returns the public key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePublicKey');
        return $type::savePublicKey($this->p, $this->q, $this->g, $this->y, $options);
    }
}<?php

/**
 * Pure-PHP FIPS 186-4 compliant implementation of DSA.
 *
 * PHP version 5
 *
 * Here's an example of how to create signatures and verify signatures with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $private = \phpseclib3\Crypt\DSA::createKey();
 * $public = $private->getPublicKey();
 *
 * $plaintext = 'terrafrost';
 *
 * $signature = $private->sign($plaintext);
 *
 * echo $public->verify($plaintext, $signature) ? 'verified' : 'unverified';
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\DSA\PrivateKey;
use phpseclib3\Crypt\DSA\PublicKey;
use phpseclib3\Crypt\DSA\Parameters;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\InsufficientSetupException;
/**
 * Pure-PHP FIPS 186-4 compliant implementation of DSA.
 *
 * @package DSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DSA extends AsymmetricKey
{
    /**
     * Algorithm Name
     *
     * @var string
     * @access private
     */
    const ALGORITHM = 'DSA';
    /**
     * DSA Prime P
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $p;
    /**
     * DSA Group Order q
     *
     * Prime divisor of p-1
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $q;
    /**
     * DSA Group Generator G
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $g;
    /**
     * DSA public key value y
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $y;
    /**
     * Signature Format
     *
     * @var string
     * @access private
     */
    protected $sigFormat;
    /**
     * Signature Format (Short)
     *
     * @var string
     * @access private
     */
    protected $shortFormat;
    /**
     * Create DSA parameters
     *
     * @access public
     * @param int $L
     * @param int $N
     * @return (\phpseclib3\Crypt\DSA | bool)
     */
    public static function createParameters($L = 2048, $N = 224)
    {
        self::initialize_static_variables();
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        switch (true) {
            case $N == 160:
            /*
              in FIPS 186-1 and 186-2 N was fixed at 160 whereas K had an upper bound of 1024.
              RFC 4253 (SSH Transport Layer Protocol) references FIPS 186-2 and as such most
              SSH DSA implementations only support keys with an N of 160.
              puttygen let's you set the size of L (but not the size of N) and uses 2048 as the
              default L value. that's not really compliant with any of the FIPS standards, however,
              for the purposes of maintaining compatibility with puttygen, we'll support it 
            */
            //case ($L >= 512 || $L <= 1024) && (($L & 0x3F) == 0) && $N == 160:
            // FIPS 186-3 changed this as follows:
            //case $L == 1024 && $N == 160:
            case $L == 2048 && $N == 224:
            case $L == 2048 && $N == 256:
            case $L == 3072 && $N == 256:
                break;
            default:
                throw new \InvalidArgumentException('Invalid values for N and L');
        }
        $two = new BigInteger(2);
        $q = BigInteger::randomPrime($N);
        $divisor = $q->multiply($two);
        do {
            $x = BigInteger::random($L);
            list(, $c) = $x->divide($divisor);
            $p = $x->subtract($c->subtract(self::$one));
        } while ($p->getLength() != $L || !$p->isPrime());
        $p_1 = $p->subtract(self::$one);
        list($e) = $p_1->divide($q);
        // quoting http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf#page=50 ,
        // "h could be obtained from a random number generator or from a counter that
        //  changes after each use". PuTTY (sshdssg.c) starts h off at 1 and increments
        // it on each loop. wikipedia says "commonly h = 2 is used" so we'll just do that
        $h = clone $two;
        while (true) {
            $g = $h->powMod($e, $p);
            if (!$g->equals(self::$one)) {
                break;
            }
            $h = $h->add(self::$one);
        }
        $dsa = new Parameters();
        $dsa->p = $p;
        $dsa->q = $q;
        $dsa->g = $g;
        return $dsa;
    }
    /**
    * Create public / private key pair.
    *
    * This method is a bit polymorphic. It can take a DSA/Parameters object, L / N as two distinct parameters or
    no parameters (at which point L and N will be generated with this method)
    *
    * Returns the private key, from which the publickey can be extracted
    *
    * @param int[] ...$args
    * @access public
    * @return DSA\PrivateKey
    */
    public static function createKey(...$args)
    {
        self::initialize_static_variables();
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        if (count($args) == 2 && is_int($args[0]) && is_int($args[1])) {
            $params = self::createParameters($args[0], $args[1]);
        } else {
            if (count($args) == 1 && $args[0] instanceof Parameters) {
                $params = $args[0];
            } else {
                if (!count($args)) {
                    $params = self::createParameters();
                } else {
                    throw new InsufficientSetupException('Valid parameters are either two integers (L and N), a single DSA object or no parameters at all.');
                }
            }
        }
        $private = new PrivateKey();
        $private->p = $params->p;
        $private->q = $params->q;
        $private->g = $params->g;
        $private->x = BigInteger::randomRange(self::$one, $private->q->subtract(self::$one));
        $private->y = $private->g->powMod($private->x, $private->p);
        //$public = clone $private;
        //unset($public->x);
        return $private->withHash($params->hash->getHash())->withSignatureFormat($params->shortFormat);
    }
    /**
     * OnLoad Handler
     *
     * @return bool
     * @access protected
     * @param array $components
     */
    protected static function onLoad($components)
    {
        if (!isset(self::$engines['PHP'])) {
            self::useBestEngine();
        }
        if (!isset($components['x']) && !isset($components['y'])) {
            $new = new Parameters();
        } else {
            if (isset($components['x'])) {
                $new = new PrivateKey();
                $new->x = $components['x'];
            } else {
                $new = new PublicKey();
            }
        }
        $new->p = $components['p'];
        $new->q = $components['q'];
        $new->g = $components['g'];
        if (isset($components['y'])) {
            $new->y = $components['y'];
        }
        return $new;
    }
    /**
     * Constructor
     *
     * PublicKey and PrivateKey objects can only be created from abstract RSA class
     */
    protected function __construct()
    {
        $this->sigFormat = self::validatePlugin('Signature', 'ASN1');
        $this->shortFormat = 'ASN1';
        parent::__construct();
    }
    /**
     * Returns the key size
     *
     * More specifically, this L (the length of DSA Prime P) and N (the length of DSA Group Order q)
     *
     * @access public
     * @return array
     */
    public function getLength()
    {
        return ['L' => $this->p->getLength(), 'N' => $this->q->getLength()];
    }
    /**
     * Returns the current engine being used
     *
     * @see self::useInternalEngine()
     * @see self::useBestEngine()
     * @access public
     * @return string
     */
    public function getEngine()
    {
        return self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods()) ? 'OpenSSL' : 'PHP';
    }
    /**
    * Returns the parameters
    *
    * A public / private key is only returned if the currently loaded "key" contains an x or y
    value.
    *
    * @see self::getPublicKey()
    * @access public
    * @return mixed
    */
    public function getParameters()
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        $key = $type::saveParameters($this->p, $this->q, $this->g);
        return DSA::load($key, 'PKCS1')->withHash($this->hash->getHash())->withSignatureFormat($this->shortFormat);
    }
    /**
     * Determines the signature padding mode
     *
     * Valid values are: ASN1, SSH2, Raw
     *
     * @access public
     * @param string $format
     */
    public function withSignatureFormat($format)
    {
        $new = clone $this;
        $new->shortFormat = $format;
        $new->sigFormat = self::validatePlugin('Signature', $format);
        return $new;
    }
    /**
     * Returns the signature format currently being used
     *
     * @access public
     */
    public function getSignatureFormat()
    {
        return $this->shortFormat;
    }
}<?php

/**
 * Pure-PHP implementation of Triple DES.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.  Operates in the EDE3 mode (encrypt-decrypt-encrypt).
 *
 * PHP version 5
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $des = new \phpseclib3\Crypt\TripleDES('ctr');
 *
 *    $des->setKey('abcdefghijklmnopqrstuvwx');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $des->decrypt($des->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   TripleDES
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

/**
 * Pure-PHP implementation of Triple DES.
 *
 * @package TripleDES
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class TripleDES extends DES
{
    /**
     * Encrypt / decrypt using inner chaining
     *
     * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3).
     */
    const MODE_3CBC = -2;
    /**
     * Encrypt / decrypt using outer chaining
     *
     * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib3\Crypt\Common\BlockCipher::MODE_CBC.
     */
    const MODE_CBC3 = self::MODE_CBC;
    /**
     * Key Length (in bytes)
     *
     * @see \phpseclib3\Crypt\TripleDES::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 24;
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\DES::cipher_name_mcrypt
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'tripledes';
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 750;
    /**
     * max possible size of $key
     *
     * @see self::setKey()
     * @see \phpseclib3\Crypt\DES::setKey()
     * @var string
     * @access private
     */
    protected $key_length_max = 24;
    /**
     * Internal flag whether using self::MODE_3CBC or not
     *
     * @var bool
     * @access private
     */
    private $mode_3cbc;
    /**
     * The \phpseclib3\Crypt\DES objects
     *
     * Used only if $mode_3cbc === true
     *
     * @var array
     * @access private
     */
    private $des;
    /**
     * Default Constructor.
     *
     * Determines whether or not the mcrypt or OpenSSL extensions should be used.
     *
     * $mode could be:
     *
     * - ecb
     *
     * - cbc
     *
     * - ctr
     *
     * - cfb
     *
     * - ofb
     *
     * - 3cbc
     *
     * - cbc3 (same as cbc)
     *
     * @see \phpseclib3\Crypt\DES::__construct()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param string $mode
     * @access public
     */
    public function __construct($mode)
    {
        switch (strtolower($mode)) {
            // In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC
            // and additional flag us internally as 3CBC
            case '3cbc':
                parent::__construct('cbc');
                $this->mode_3cbc = true;
                // This three $des'es will do the 3CBC work (if $key > 64bits)
                $this->des = [new DES('cbc'), new DES('cbc'), new DES('cbc')];
                // we're going to be doing the padding, ourselves, so disable it in the \phpseclib3\Crypt\DES objects
                $this->des[0]->disablePadding();
                $this->des[1]->disablePadding();
                $this->des[2]->disablePadding();
                break;
            case 'cbc3':
                $mode = 'cbc';
            // If not 3CBC, we init as usual
            default:
                parent::__construct($mode);
                if ($this->mode == self::MODE_STREAM) {
                    throw new BadModeException('Block ciphers cannot be ran in stream mode');
                }
        }
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        if ($engine == self::ENGINE_OPENSSL) {
            $this->cipher_name_openssl_ecb = 'des-ede3';
            $mode = $this->openssl_translate_mode();
            $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode;
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Sets the initialization vector.
     *
     * SetIV is not required when \phpseclib3\Crypt\Common\SymmetricKey::MODE_ECB is being used.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setIV()
     * @access public
     * @param string $iv
     */
    public function setIV($iv)
    {
        parent::setIV($iv);
        if ($this->mode_3cbc) {
            $this->des[0]->setIV($iv);
            $this->des[1]->setIV($iv);
            $this->des[2]->setIV($iv);
        }
    }
    /**
     * Sets the key length.
     *
     * Valid key lengths are 128 and 192 bits.
     *
     * If you want to use a 64-bit key use DES.php
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey:setKeyLength()
     * @access public
     * @throws \LengthException if the key length is invalid
     * @param int $length
     */
    public function setKeyLength($length)
    {
        switch ($length) {
            case 128:
            case 192:
                break;
            default:
                throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128 or 192 bits are supported');
        }
        parent::setKeyLength($length);
    }
    /**
     * Sets the key.
     *
     * Triple DES can use 128-bit (eg. strlen($key) == 16) or 192-bit (eg. strlen($key) == 24) keys.
     *
     * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
     *
     * @access public
     * @see \phpseclib3\Crypt\DES::setKey()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
     * @throws \LengthException if the key length is invalid
     * @param string $key
     */
    public function setKey($key)
    {
        if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
            throw new \LengthException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
        }
        switch (strlen($key)) {
            case 16:
                $key .= \Phabel\Target\Php80\Polyfill::substr($key, 0, 8);
                break;
            case 24:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 24 are supported');
        }
        // copied from self::setKey()
        $this->key = $key;
        $this->key_length = strlen($key);
        $this->changed = $this->nonIVChanged = true;
        $this->setEngine();
        if ($this->mode_3cbc) {
            $this->des[0]->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, 8));
            $this->des[1]->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 8, 8));
            $this->des[2]->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 16, 8));
        }
    }
    /**
     * Encrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @access public
     * @param string $plaintext
     * @return string $cipertext
     */
    public function encrypt($plaintext)
    {
        // parent::en/decrypt() is able to do all the work for all modes and keylengths,
        // except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits
        // if the key is smaller then 8, do what we'd normally do
        if ($this->mode_3cbc && strlen($this->key) > 8) {
            return $this->des[2]->encrypt($this->des[1]->decrypt($this->des[0]->encrypt($this->pad($plaintext))));
        }
        return parent::encrypt($plaintext);
    }
    /**
     * Decrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @access public
     * @param string $ciphertext
     * @return string $plaintext
     */
    public function decrypt($ciphertext)
    {
        if ($this->mode_3cbc && strlen($this->key) > 8) {
            return $this->unpad($this->des[0]->decrypt($this->des[1]->encrypt($this->des[2]->decrypt(str_pad($ciphertext, strlen($ciphertext) + 7 & 0xfffffff8, "\x00")))));
        }
        return parent::decrypt($ciphertext);
    }
    /**
    * Treat consecutive "packets" as if they are a continuous buffer.
    *
    * Say you have a 16-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
    will yield different outputs:
    *
    * <code>
    echo $des->encrypt(substr($plaintext, 0, 8));
    echo $des->encrypt(substr($plaintext, 8, 8));
    </code>
    <code>
    echo $des->encrypt($plaintext);
    </code>
    *
    * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
    another, as demonstrated with the following:
    *
    * <code>
    $des->encrypt(substr($plaintext, 0, 8));
    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
    </code>
    <code>
    echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
    </code>
    *
    * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
    outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
    decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
    *
    * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\DES() object changes after each
    encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
    continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
    however, they are also less intuitive and more likely to cause you problems.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::enableContinuousBuffer()
    * @see self::disableContinuousBuffer()
    * @access public
    */
    public function enableContinuousBuffer()
    {
        parent::enableContinuousBuffer();
        if ($this->mode_3cbc) {
            $this->des[0]->enableContinuousBuffer();
            $this->des[1]->enableContinuousBuffer();
            $this->des[2]->enableContinuousBuffer();
        }
    }
    /**
     * Treat consecutive packets as if they are a discontinuous buffer.
     *
     * The default behavior.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::disableContinuousBuffer()
     * @see self::enableContinuousBuffer()
     * @access public
     */
    public function disableContinuousBuffer()
    {
        parent::disableContinuousBuffer();
        if ($this->mode_3cbc) {
            $this->des[0]->disableContinuousBuffer();
            $this->des[1]->disableContinuousBuffer();
            $this->des[2]->disableContinuousBuffer();
        }
    }
    /**
     * Creates the key schedule
     *
     * @see \phpseclib3\Crypt\DES::setupKey()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
     * @access private
     */
    protected function setupKey()
    {
        switch (true) {
            // if $key <= 64bits we configure our internal pure-php cipher engine
            // to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same.
            case strlen($this->key) <= 8:
                $this->des_rounds = 1;
                break;
            // otherwise, if $key > 64bits, we configure our engine to work as 3DES.
            default:
                $this->des_rounds = 3;
                // (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately.
                if ($this->mode_3cbc) {
                    $this->des[0]->setupKey();
                    $this->des[1]->setupKey();
                    $this->des[2]->setupKey();
                    // because $des[0-2] will, now, do all the work we can return here
                    // not need unnecessary stress parent::setupKey() with our, now unused, $key.
                    return;
                }
        }
        // setup our key
        parent::setupKey();
    }
    /**
     * Sets the internal crypt engine
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setPreferredEngine()
     * @param int $engine
     * @access public
     */
    public function setPreferredEngine($engine)
    {
        if ($this->mode_3cbc) {
            $this->des[0]->setPreferredEngine($engine);
            $this->des[1]->setPreferredEngine($engine);
            $this->des[2]->setPreferredEngine($engine);
        }
        parent::setPreferredEngine($engine);
    }
}<?php

/**
 * Pure-PHP implementation of Twofish.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://en.wikipedia.org/wiki/Twofish Wikipedia description of Twofish}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $twofish = new \phpseclib3\Crypt\Twofish('ctr');
 *
 *    $twofish->setKey('12345678901234567890123456789012');
 *
 *    $plaintext = str_repeat('a', 1024);
 *
 *    echo $twofish->decrypt($twofish->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Twofish
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
use phpseclib3\Exception\BadModeException;
/**
 * Pure-PHP implementation of Twofish.
 *
 * @package Twofish
 * @author  Jim Wigginton <terrafrost@php.net>
 * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
 * @access  public
 */
class Twofish extends BlockCipher
{
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'twofish';
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 800;
    /**
     * Q-Table
     *
     * @var array
     * @access private
     */
    private static $q0 = [0xa9, 0x67, 0xb3, 0xe8, 0x4, 0xfd, 0xa3, 0x76, 0x9a, 0x92, 0x80, 0x78, 0xe4, 0xdd, 0xd1, 0x38, 0xd, 0xc6, 0x35, 0x98, 0x18, 0xf7, 0xec, 0x6c, 0x43, 0x75, 0x37, 0x26, 0xfa, 0x13, 0x94, 0x48, 0xf2, 0xd0, 0x8b, 0x30, 0x84, 0x54, 0xdf, 0x23, 0x19, 0x5b, 0x3d, 0x59, 0xf3, 0xae, 0xa2, 0x82, 0x63, 0x1, 0x83, 0x2e, 0xd9, 0x51, 0x9b, 0x7c, 0xa6, 0xeb, 0xa5, 0xbe, 0x16, 0xc, 0xe3, 0x61, 0xc0, 0x8c, 0x3a, 0xf5, 0x73, 0x2c, 0x25, 0xb, 0xbb, 0x4e, 0x89, 0x6b, 0x53, 0x6a, 0xb4, 0xf1, 0xe1, 0xe6, 0xbd, 0x45, 0xe2, 0xf4, 0xb6, 0x66, 0xcc, 0x95, 0x3, 0x56, 0xd4, 0x1c, 0x1e, 0xd7, 0xfb, 0xc3, 0x8e, 0xb5, 0xe9, 0xcf, 0xbf, 0xba, 0xea, 0x77, 0x39, 0xaf, 0x33, 0xc9, 0x62, 0x71, 0x81, 0x79, 0x9, 0xad, 0x24, 0xcd, 0xf9, 0xd8, 0xe5, 0xc5, 0xb9, 0x4d, 0x44, 0x8, 0x86, 0xe7, 0xa1, 0x1d, 0xaa, 0xed, 0x6, 0x70, 0xb2, 0xd2, 0x41, 0x7b, 0xa0, 0x11, 0x31, 0xc2, 0x27, 0x90, 0x20, 0xf6, 0x60, 0xff, 0x96, 0x5c, 0xb1, 0xab, 0x9e, 0x9c, 0x52, 0x1b, 0x5f, 0x93, 0xa, 0xef, 0x91, 0x85, 0x49, 0xee, 0x2d, 0x4f, 0x8f, 0x3b, 0x47, 0x87, 0x6d, 0x46, 0xd6, 0x3e, 0x69, 0x64, 0x2a, 0xce, 0xcb, 0x2f, 0xfc, 0x97, 0x5, 0x7a, 0xac, 0x7f, 0xd5, 0x1a, 0x4b, 0xe, 0xa7, 0x5a, 0x28, 0x14, 0x3f, 0x29, 0x88, 0x3c, 0x4c, 0x2, 0xb8, 0xda, 0xb0, 0x17, 0x55, 0x1f, 0x8a, 0x7d, 0x57, 0xc7, 0x8d, 0x74, 0xb7, 0xc4, 0x9f, 0x72, 0x7e, 0x15, 0x22, 0x12, 0x58, 0x7, 0x99, 0x34, 0x6e, 0x50, 0xde, 0x68, 0x65, 0xbc, 0xdb, 0xf8, 0xc8, 0xa8, 0x2b, 0x40, 0xdc, 0xfe, 0x32, 0xa4, 0xca, 0x10, 0x21, 0xf0, 0xd3, 0x5d, 0xf, 0x0, 0x6f, 0x9d, 0x36, 0x42, 0x4a, 0x5e, 0xc1, 0xe0];
    /**
     * Q-Table
     *
     * @var array
     * @access private
     */
    private static $q1 = [0x75, 0xf3, 0xc6, 0xf4, 0xdb, 0x7b, 0xfb, 0xc8, 0x4a, 0xd3, 0xe6, 0x6b, 0x45, 0x7d, 0xe8, 0x4b, 0xd6, 0x32, 0xd8, 0xfd, 0x37, 0x71, 0xf1, 0xe1, 0x30, 0xf, 0xf8, 0x1b, 0x87, 0xfa, 0x6, 0x3f, 0x5e, 0xba, 0xae, 0x5b, 0x8a, 0x0, 0xbc, 0x9d, 0x6d, 0xc1, 0xb1, 0xe, 0x80, 0x5d, 0xd2, 0xd5, 0xa0, 0x84, 0x7, 0x14, 0xb5, 0x90, 0x2c, 0xa3, 0xb2, 0x73, 0x4c, 0x54, 0x92, 0x74, 0x36, 0x51, 0x38, 0xb0, 0xbd, 0x5a, 0xfc, 0x60, 0x62, 0x96, 0x6c, 0x42, 0xf7, 0x10, 0x7c, 0x28, 0x27, 0x8c, 0x13, 0x95, 0x9c, 0xc7, 0x24, 0x46, 0x3b, 0x70, 0xca, 0xe3, 0x85, 0xcb, 0x11, 0xd0, 0x93, 0xb8, 0xa6, 0x83, 0x20, 0xff, 0x9f, 0x77, 0xc3, 0xcc, 0x3, 0x6f, 0x8, 0xbf, 0x40, 0xe7, 0x2b, 0xe2, 0x79, 0xc, 0xaa, 0x82, 0x41, 0x3a, 0xea, 0xb9, 0xe4, 0x9a, 0xa4, 0x97, 0x7e, 0xda, 0x7a, 0x17, 0x66, 0x94, 0xa1, 0x1d, 0x3d, 0xf0, 0xde, 0xb3, 0xb, 0x72, 0xa7, 0x1c, 0xef, 0xd1, 0x53, 0x3e, 0x8f, 0x33, 0x26, 0x5f, 0xec, 0x76, 0x2a, 0x49, 0x81, 0x88, 0xee, 0x21, 0xc4, 0x1a, 0xeb, 0xd9, 0xc5, 0x39, 0x99, 0xcd, 0xad, 0x31, 0x8b, 0x1, 0x18, 0x23, 0xdd, 0x1f, 0x4e, 0x2d, 0xf9, 0x48, 0x4f, 0xf2, 0x65, 0x8e, 0x78, 0x5c, 0x58, 0x19, 0x8d, 0xe5, 0x98, 0x57, 0x67, 0x7f, 0x5, 0x64, 0xaf, 0x63, 0xb6, 0xfe, 0xf5, 0xb7, 0x3c, 0xa5, 0xce, 0xe9, 0x68, 0x44, 0xe0, 0x4d, 0x43, 0x69, 0x29, 0x2e, 0xac, 0x15, 0x59, 0xa8, 0xa, 0x9e, 0x6e, 0x47, 0xdf, 0x34, 0x35, 0x6a, 0xcf, 0xdc, 0x22, 0xc9, 0xc0, 0x9b, 0x89, 0xd4, 0xed, 0xab, 0x12, 0xa2, 0xd, 0x52, 0xbb, 0x2, 0x2f, 0xa9, 0xd7, 0x61, 0x1e, 0xb4, 0x50, 0x4, 0xf6, 0xc2, 0x16, 0x25, 0x86, 0x56, 0x55, 0x9, 0xbe, 0x91];
    /**
     * M-Table
     *
     * @var array
     * @access private
     */
    private static $m0 = [0xbcbc3275, 0xecec21f3, 0x202043c6, 0xb3b3c9f4, 0xdada03db, 0x2028b7b, 0xe2e22bfb, 0x9e9efac8, 0xc9c9ec4a, 0xd4d409d3, 0x18186be6, 0x1e1e9f6b, 0x98980e45, 0xb2b2387d, 0xa6a6d2e8, 0x2626b74b, 0x3c3c57d6, 0x93938a32, 0x8282eed8, 0x525298fd, 0x7b7bd437, 0xbbbb3771, 0x5b5b97f1, 0x474783e1, 0x24243c30, 0x5151e20f, 0xbabac6f8, 0x4a4af31b, 0xbfbf4887, 0xd0d70fa, 0xb0b0b306, 0x7575de3f, 0xd2d2fd5e, 0x7d7d20ba, 0x666631ae, 0x3a3aa35b, 0x59591c8a, 0x0, 0xcdcd93bc, 0x1a1ae09d, 0xaeae2c6d, 0x7f7fabc1, 0x2b2bc7b1, 0xbebeb90e, 0xe0e0a080, 0x8a8a105d, 0x3b3b52d2, 0x6464bad5, 0xd8d888a0, 0xe7e7a584, 0x5f5fe807, 0x1b1b1114, 0x2c2cc2b5, 0xfcfcb490, 0x3131272c, 0x808065a3, 0x73732ab2, 0xc0c8173, 0x79795f4c, 0x6b6b4154, 0x4b4b0292, 0x53536974, 0x94948f36, 0x83831f51, 0x2a2a3638, 0xc4c49cb0, 0x2222c8bd, 0xd5d5f85a, 0xbdbdc3fc, 0x48487860, 0xffffce62, 0x4c4c0796, 0x4141776c, 0xc7c7e642, 0xebeb24f7, 0x1c1c1410, 0x5d5d637c, 0x36362228, 0x6767c027, 0xe9e9af8c, 0x4444f913, 0x1414ea95, 0xf5f5bb9c, 0xcfcf18c7, 0x3f3f2d24, 0xc0c0e346, 0x7272db3b, 0x54546c70, 0x29294cca, 0xf0f035e3, 0x808fe85, 0xc6c617cb, 0xf3f34f11, 0x8c8ce4d0, 0xa4a45993, 0xcaca96b8, 0x68683ba6, 0xb8b84d83, 0x38382820, 0xe5e52eff, 0xadad569f, 0xb0b8477, 0xc8c81dc3, 0x9999ffcc, 0x5858ed03, 0x19199a6f, 0xe0e0a08, 0x95957ebf, 0x70705040, 0xf7f730e7, 0x6e6ecf2b, 0x1f1f6ee2, 0xb5b53d79, 0x9090f0c, 0x616134aa, 0x57571682, 0x9f9f0b41, 0x9d9d803a, 0x111164ea, 0x2525cdb9, 0xafafdde4, 0x4545089a, 0xdfdf8da4, 0xa3a35c97, 0xeaead57e, 0x353558da, 0xededd07a, 0x4343fc17, 0xf8f8cb66, 0xfbfbb194, 0x3737d3a1, 0xfafa401d, 0xc2c2683d, 0xb4b4ccf0, 0x32325dde, 0x9c9c71b3, 0x5656e70b, 0xe3e3da72, 0x878760a7, 0x15151b1c, 0xf9f93aef, 0x6363bfd1, 0x3434a953, 0x9a9a853e, 0xb1b1428f, 0x7c7cd133, 0x88889b26, 0x3d3da65f, 0xa1a1d7ec, 0xe4e4df76, 0x8181942a, 0x91910149, 0xf0ffb81, 0xeeeeaa88, 0x161661ee, 0xd7d77321, 0x9797f5c4, 0xa5a5a81a, 0xfefe3feb, 0x6d6db5d9, 0x7878aec5, 0xc5c56d39, 0x1d1de599, 0x7676a4cd, 0x3e3edcad, 0xcbcb6731, 0xb6b6478b, 0xefef5b01, 0x12121e18, 0x6060c523, 0x6a6ab0dd, 0x4d4df61f, 0xcecee94e, 0xdede7c2d, 0x55559df9, 0x7e7e5a48, 0x2121b24f, 0x3037af2, 0xa0a02665, 0x5e5e198e, 0x5a5a6678, 0x65654b5c, 0x62624e58, 0xfdfd4519, 0x606f48d, 0x404086e5, 0xf2f2be98, 0x3333ac57, 0x17179067, 0x5058e7f, 0xe8e85e05, 0x4f4f7d64, 0x89896aaf, 0x10109563, 0x74742fb6, 0xa0a75fe, 0x5c5c92f5, 0x9b9b74b7, 0x2d2d333c, 0x3030d6a5, 0x2e2e49ce, 0x494989e9, 0x46467268, 0x77775544, 0xa8a8d8e0, 0x9696044d, 0x2828bd43, 0xa9a92969, 0xd9d97929, 0x8686912e, 0xd1d187ac, 0xf4f44a15, 0x8d8d1559, 0xd6d682a8, 0xb9b9bc0a, 0x42420d9e, 0xf6f6c16e, 0x2f2fb847, 0xdddd06df, 0x23233934, 0xcccc6235, 0xf1f1c46a, 0xc1c112cf, 0x8585ebdc, 0x8f8f9e22, 0x7171a1c9, 0x9090f0c0, 0xaaaa539b, 0x101f189, 0x8b8be1d4, 0x4e4e8ced, 0x8e8e6fab, 0xababa212, 0x6f6f3ea2, 0xe6e6540d, 0xdbdbf252, 0x92927bbb, 0xb7b7b602, 0x6969ca2f, 0x3939d9a9, 0xd3d30cd7, 0xa7a72361, 0xa2a2ad1e, 0xc3c399b4, 0x6c6c4450, 0x7070504, 0x4047ff6, 0x272746c2, 0xacaca716, 0xd0d07625, 0x50501386, 0xdcdcf756, 0x84841a55, 0xe1e15109, 0x7a7a25be, 0x1313ef91];
    /**
     * M-Table
     *
     * @var array
     * @access private
     */
    private static $m1 = [0xa9d93939, 0x67901717, 0xb3719c9c, 0xe8d2a6a6, 0x4050707, 0xfd985252, 0xa3658080, 0x76dfe4e4, 0x9a084545, 0x92024b4b, 0x80a0e0e0, 0x78665a5a, 0xe4ddafaf, 0xddb06a6a, 0xd1bf6363, 0x38362a2a, 0xd54e6e6, 0xc6432020, 0x3562cccc, 0x98bef2f2, 0x181e1212, 0xf724ebeb, 0xecd7a1a1, 0x6c774141, 0x43bd2828, 0x7532bcbc, 0x37d47b7b, 0x269b8888, 0xfa700d0d, 0x13f94444, 0x94b1fbfb, 0x485a7e7e, 0xf27a0303, 0xd0e48c8c, 0x8b47b6b6, 0x303c2424, 0x84a5e7e7, 0x54416b6b, 0xdf06dddd, 0x23c56060, 0x1945fdfd, 0x5ba33a3a, 0x3d68c2c2, 0x59158d8d, 0xf321ecec, 0xae316666, 0xa23e6f6f, 0x82165757, 0x63951010, 0x15befef, 0x834db8b8, 0x2e918686, 0xd9b56d6d, 0x511f8383, 0x9b53aaaa, 0x7c635d5d, 0xa63b6868, 0xeb3ffefe, 0xa5d63030, 0xbe257a7a, 0x16a7acac, 0xc0f0909, 0xe335f0f0, 0x6123a7a7, 0xc0f09090, 0x8cafe9e9, 0x3a809d9d, 0xf5925c5c, 0x73810c0c, 0x2c273131, 0x2576d0d0, 0xbe75656, 0xbb7b9292, 0x4ee9cece, 0x89f10101, 0x6b9f1e1e, 0x53a93434, 0x6ac4f1f1, 0xb499c3c3, 0xf1975b5b, 0xe1834747, 0xe66b1818, 0xbdc82222, 0x450e9898, 0xe26e1f1f, 0xf4c9b3b3, 0xb62f7474, 0x66cbf8f8, 0xccff9999, 0x95ea1414, 0x3ed5858, 0x56f7dcdc, 0xd4e18b8b, 0x1c1b1515, 0x1eada2a2, 0xd70cd3d3, 0xfb2be2e2, 0xc31dc8c8, 0x8e195e5e, 0xb5c22c2c, 0xe9894949, 0xcf12c1c1, 0xbf7e9595, 0xba207d7d, 0xea641111, 0x77840b0b, 0x396dc5c5, 0xaf6a8989, 0x33d17c7c, 0xc9a17171, 0x62ceffff, 0x7137bbbb, 0x81fb0f0f, 0x793db5b5, 0x951e1e1, 0xaddc3e3e, 0x242d3f3f, 0xcda47676, 0xf99d5555, 0xd8ee8282, 0xe5864040, 0xc5ae7878, 0xb9cd2525, 0x4d049696, 0x44557777, 0x80a0e0e, 0x86135050, 0xe730f7f7, 0xa1d33737, 0x1d40fafa, 0xaa346161, 0xed8c4e4e, 0x6b3b0b0, 0x706c5454, 0xb22a7373, 0xd2523b3b, 0x410b9f9f, 0x7b8b0202, 0xa088d8d8, 0x114ff3f3, 0x3167cbcb, 0xc2462727, 0x27c06767, 0x90b4fcfc, 0x20283838, 0xf67f0404, 0x60784848, 0xff2ee5e5, 0x96074c4c, 0x5c4b6565, 0xb1c72b2b, 0xab6f8e8e, 0x9e0d4242, 0x9cbbf5f5, 0x52f2dbdb, 0x1bf34a4a, 0x5fa63d3d, 0x9359a4a4, 0xabcb9b9, 0xef3af9f9, 0x91ef1313, 0x85fe0808, 0x49019191, 0xee611616, 0x2d7cdede, 0x4fb22121, 0x8f42b1b1, 0x3bdb7272, 0x47b82f2f, 0x8748bfbf, 0x6d2caeae, 0x46e3c0c0, 0xd6573c3c, 0x3e859a9a, 0x6929a9a9, 0x647d4f4f, 0x2a948181, 0xce492e2e, 0xcb17c6c6, 0x2fca6969, 0xfcc3bdbd, 0x975ca3a3, 0x55ee8e8, 0x7ad0eded, 0xac87d1d1, 0x7f8e0505, 0xd5ba6464, 0x1aa8a5a5, 0x4bb72626, 0xeb9bebe, 0xa7608787, 0x5af8d5d5, 0x28223636, 0x14111b1b, 0x3fde7575, 0x2979d9d9, 0x88aaeeee, 0x3c332d2d, 0x4c5f7979, 0x2b6b7b7, 0xb896caca, 0xda583535, 0xb09cc4c4, 0x17fc4343, 0x551a8484, 0x1ff64d4d, 0x8a1c5959, 0x7d38b2b2, 0x57ac3333, 0xc718cfcf, 0x8df40606, 0x74695353, 0xb7749b9b, 0xc4f59797, 0x9f56adad, 0x72dae3e3, 0x7ed5eaea, 0x154af4f4, 0x229e8f8f, 0x12a2abab, 0x584e6262, 0x7e85f5f, 0x99e51d1d, 0x34392323, 0x6ec1f6f6, 0x50446c6c, 0xde5d3232, 0x68724646, 0x6526a0a0, 0xbc93cdcd, 0xdb03dada, 0xf8c6baba, 0xc8fa9e9e, 0xa882d6d6, 0x2bcf6e6e, 0x40507070, 0xdceb8585, 0xfe750a0a, 0x328a9393, 0xa48ddfdf, 0xca4c2929, 0x10141c1c, 0x2173d7d7, 0xf0ccb4b4, 0xd309d4d4, 0x5d108a8a, 0xfe25151, 0x0, 0x6f9a1919, 0x9de01a1a, 0x368f9494, 0x42e6c7c7, 0x4aecc9c9, 0x5efdd2d2, 0xc1ab7f7f, 0xe0d8a8a8];
    /**
     * M-Table
     *
     * @var array
     * @access private
     */
    private static $m2 = [0xbc75bc32, 0xecf3ec21, 0x20c62043, 0xb3f4b3c9, 0xdadbda03, 0x27b028b, 0xe2fbe22b, 0x9ec89efa, 0xc94ac9ec, 0xd4d3d409, 0x18e6186b, 0x1e6b1e9f, 0x9845980e, 0xb27db238, 0xa6e8a6d2, 0x264b26b7, 0x3cd63c57, 0x9332938a, 0x82d882ee, 0x52fd5298, 0x7b377bd4, 0xbb71bb37, 0x5bf15b97, 0x47e14783, 0x2430243c, 0x510f51e2, 0xbaf8bac6, 0x4a1b4af3, 0xbf87bf48, 0xdfa0d70, 0xb006b0b3, 0x753f75de, 0xd25ed2fd, 0x7dba7d20, 0x66ae6631, 0x3a5b3aa3, 0x598a591c, 0x0, 0xcdbccd93, 0x1a9d1ae0, 0xae6dae2c, 0x7fc17fab, 0x2bb12bc7, 0xbe0ebeb9, 0xe080e0a0, 0x8a5d8a10, 0x3bd23b52, 0x64d564ba, 0xd8a0d888, 0xe784e7a5, 0x5f075fe8, 0x1b141b11, 0x2cb52cc2, 0xfc90fcb4, 0x312c3127, 0x80a38065, 0x73b2732a, 0xc730c81, 0x794c795f, 0x6b546b41, 0x4b924b02, 0x53745369, 0x9436948f, 0x8351831f, 0x2a382a36, 0xc4b0c49c, 0x22bd22c8, 0xd55ad5f8, 0xbdfcbdc3, 0x48604878, 0xff62ffce, 0x4c964c07, 0x416c4177, 0xc742c7e6, 0xebf7eb24, 0x1c101c14, 0x5d7c5d63, 0x36283622, 0x672767c0, 0xe98ce9af, 0x441344f9, 0x149514ea, 0xf59cf5bb, 0xcfc7cf18, 0x3f243f2d, 0xc046c0e3, 0x723b72db, 0x5470546c, 0x29ca294c, 0xf0e3f035, 0x88508fe, 0xc6cbc617, 0xf311f34f, 0x8cd08ce4, 0xa493a459, 0xcab8ca96, 0x68a6683b, 0xb883b84d, 0x38203828, 0xe5ffe52e, 0xad9fad56, 0xb770b84, 0xc8c3c81d, 0x99cc99ff, 0x580358ed, 0x196f199a, 0xe080e0a, 0x95bf957e, 0x70407050, 0xf7e7f730, 0x6e2b6ecf, 0x1fe21f6e, 0xb579b53d, 0x90c090f, 0x61aa6134, 0x57825716, 0x9f419f0b, 0x9d3a9d80, 0x11ea1164, 0x25b925cd, 0xafe4afdd, 0x459a4508, 0xdfa4df8d, 0xa397a35c, 0xea7eead5, 0x35da3558, 0xed7aedd0, 0x431743fc, 0xf866f8cb, 0xfb94fbb1, 0x37a137d3, 0xfa1dfa40, 0xc23dc268, 0xb4f0b4cc, 0x32de325d, 0x9cb39c71, 0x560b56e7, 0xe372e3da, 0x87a78760, 0x151c151b, 0xf9eff93a, 0x63d163bf, 0x345334a9, 0x9a3e9a85, 0xb18fb142, 0x7c337cd1, 0x8826889b, 0x3d5f3da6, 0xa1eca1d7, 0xe476e4df, 0x812a8194, 0x91499101, 0xf810ffb, 0xee88eeaa, 0x16ee1661, 0xd721d773, 0x97c497f5, 0xa51aa5a8, 0xfeebfe3f, 0x6dd96db5, 0x78c578ae, 0xc539c56d, 0x1d991de5, 0x76cd76a4, 0x3ead3edc, 0xcb31cb67, 0xb68bb647, 0xef01ef5b, 0x1218121e, 0x602360c5, 0x6add6ab0, 0x4d1f4df6, 0xce4ecee9, 0xde2dde7c, 0x55f9559d, 0x7e487e5a, 0x214f21b2, 0x3f2037a, 0xa065a026, 0x5e8e5e19, 0x5a785a66, 0x655c654b, 0x6258624e, 0xfd19fd45, 0x68d06f4, 0x40e54086, 0xf298f2be, 0x335733ac, 0x17671790, 0x57f058e, 0xe805e85e, 0x4f644f7d, 0x89af896a, 0x10631095, 0x74b6742f, 0xafe0a75, 0x5cf55c92, 0x9bb79b74, 0x2d3c2d33, 0x30a530d6, 0x2ece2e49, 0x49e94989, 0x46684672, 0x77447755, 0xa8e0a8d8, 0x964d9604, 0x284328bd, 0xa969a929, 0xd929d979, 0x862e8691, 0xd1acd187, 0xf415f44a, 0x8d598d15, 0xd6a8d682, 0xb90ab9bc, 0x429e420d, 0xf66ef6c1, 0x2f472fb8, 0xdddfdd06, 0x23342339, 0xcc35cc62, 0xf16af1c4, 0xc1cfc112, 0x85dc85eb, 0x8f228f9e, 0x71c971a1, 0x90c090f0, 0xaa9baa53, 0x18901f1, 0x8bd48be1, 0x4eed4e8c, 0x8eab8e6f, 0xab12aba2, 0x6fa26f3e, 0xe60de654, 0xdb52dbf2, 0x92bb927b, 0xb702b7b6, 0x692f69ca, 0x39a939d9, 0xd3d7d30c, 0xa761a723, 0xa21ea2ad, 0xc3b4c399, 0x6c506c44, 0x7040705, 0x4f6047f, 0x27c22746, 0xac16aca7, 0xd025d076, 0x50865013, 0xdc56dcf7, 0x8455841a, 0xe109e151, 0x7abe7a25, 0x139113ef];
    /**
     * M-Table
     *
     * @var array
     * @access private
     */
    private static $m3 = [0xd939a9d9, 0x90176790, 0x719cb371, 0xd2a6e8d2, 0x5070405, 0x9852fd98, 0x6580a365, 0xdfe476df, 0x8459a08, 0x24b9202, 0xa0e080a0, 0x665a7866, 0xddafe4dd, 0xb06addb0, 0xbf63d1bf, 0x362a3836, 0x54e60d54, 0x4320c643, 0x62cc3562, 0xbef298be, 0x1e12181e, 0x24ebf724, 0xd7a1ecd7, 0x77416c77, 0xbd2843bd, 0x32bc7532, 0xd47b37d4, 0x9b88269b, 0x700dfa70, 0xf94413f9, 0xb1fb94b1, 0x5a7e485a, 0x7a03f27a, 0xe48cd0e4, 0x47b68b47, 0x3c24303c, 0xa5e784a5, 0x416b5441, 0x6dddf06, 0xc56023c5, 0x45fd1945, 0xa33a5ba3, 0x68c23d68, 0x158d5915, 0x21ecf321, 0x3166ae31, 0x3e6fa23e, 0x16578216, 0x95106395, 0x5bef015b, 0x4db8834d, 0x91862e91, 0xb56dd9b5, 0x1f83511f, 0x53aa9b53, 0x635d7c63, 0x3b68a63b, 0x3ffeeb3f, 0xd630a5d6, 0x257abe25, 0xa7ac16a7, 0xf090c0f, 0x35f0e335, 0x23a76123, 0xf090c0f0, 0xafe98caf, 0x809d3a80, 0x925cf592, 0x810c7381, 0x27312c27, 0x76d02576, 0xe7560be7, 0x7b92bb7b, 0xe9ce4ee9, 0xf10189f1, 0x9f1e6b9f, 0xa93453a9, 0xc4f16ac4, 0x99c3b499, 0x975bf197, 0x8347e183, 0x6b18e66b, 0xc822bdc8, 0xe98450e, 0x6e1fe26e, 0xc9b3f4c9, 0x2f74b62f, 0xcbf866cb, 0xff99ccff, 0xea1495ea, 0xed5803ed, 0xf7dc56f7, 0xe18bd4e1, 0x1b151c1b, 0xada21ead, 0xcd3d70c, 0x2be2fb2b, 0x1dc8c31d, 0x195e8e19, 0xc22cb5c2, 0x8949e989, 0x12c1cf12, 0x7e95bf7e, 0x207dba20, 0x6411ea64, 0x840b7784, 0x6dc5396d, 0x6a89af6a, 0xd17c33d1, 0xa171c9a1, 0xceff62ce, 0x37bb7137, 0xfb0f81fb, 0x3db5793d, 0x51e10951, 0xdc3eaddc, 0x2d3f242d, 0xa476cda4, 0x9d55f99d, 0xee82d8ee, 0x8640e586, 0xae78c5ae, 0xcd25b9cd, 0x4964d04, 0x55774455, 0xa0e080a, 0x13508613, 0x30f7e730, 0xd337a1d3, 0x40fa1d40, 0x3461aa34, 0x8c4eed8c, 0xb3b006b3, 0x6c54706c, 0x2a73b22a, 0x523bd252, 0xb9f410b, 0x8b027b8b, 0x88d8a088, 0x4ff3114f, 0x67cb3167, 0x4627c246, 0xc06727c0, 0xb4fc90b4, 0x28382028, 0x7f04f67f, 0x78486078, 0x2ee5ff2e, 0x74c9607, 0x4b655c4b, 0xc72bb1c7, 0x6f8eab6f, 0xd429e0d, 0xbbf59cbb, 0xf2db52f2, 0xf34a1bf3, 0xa63d5fa6, 0x59a49359, 0xbcb90abc, 0x3af9ef3a, 0xef1391ef, 0xfe0885fe, 0x1914901, 0x6116ee61, 0x7cde2d7c, 0xb2214fb2, 0x42b18f42, 0xdb723bdb, 0xb82f47b8, 0x48bf8748, 0x2cae6d2c, 0xe3c046e3, 0x573cd657, 0x859a3e85, 0x29a96929, 0x7d4f647d, 0x94812a94, 0x492ece49, 0x17c6cb17, 0xca692fca, 0xc3bdfcc3, 0x5ca3975c, 0x5ee8055e, 0xd0ed7ad0, 0x87d1ac87, 0x8e057f8e, 0xba64d5ba, 0xa8a51aa8, 0xb7264bb7, 0xb9be0eb9, 0x6087a760, 0xf8d55af8, 0x22362822, 0x111b1411, 0xde753fde, 0x79d92979, 0xaaee88aa, 0x332d3c33, 0x5f794c5f, 0xb6b702b6, 0x96cab896, 0x5835da58, 0x9cc4b09c, 0xfc4317fc, 0x1a84551a, 0xf64d1ff6, 0x1c598a1c, 0x38b27d38, 0xac3357ac, 0x18cfc718, 0xf4068df4, 0x69537469, 0x749bb774, 0xf597c4f5, 0x56ad9f56, 0xdae372da, 0xd5ea7ed5, 0x4af4154a, 0x9e8f229e, 0xa2ab12a2, 0x4e62584e, 0xe85f07e8, 0xe51d99e5, 0x39233439, 0xc1f66ec1, 0x446c5044, 0x5d32de5d, 0x72466872, 0x26a06526, 0x93cdbc93, 0x3dadb03, 0xc6baf8c6, 0xfa9ec8fa, 0x82d6a882, 0xcf6e2bcf, 0x50704050, 0xeb85dceb, 0x750afe75, 0x8a93328a, 0x8ddfa48d, 0x4c29ca4c, 0x141c1014, 0x73d72173, 0xccb4f0cc, 0x9d4d309, 0x108a5d10, 0xe2510fe2, 0x0, 0x9a196f9a, 0xe01a9de0, 0x8f94368f, 0xe6c742e6, 0xecc94aec, 0xfdd25efd, 0xab7fc1ab, 0xd8a8e0d8];
    /**
     * The Key Schedule Array
     *
     * @var array
     * @access private
     */
    private $K = [];
    /**
     * The Key depended S-Table 0
     *
     * @var array
     * @access private
     */
    private $S0 = [];
    /**
     * The Key depended S-Table 1
     *
     * @var array
     * @access private
     */
    private $S1 = [];
    /**
     * The Key depended S-Table 2
     *
     * @var array
     * @access private
     */
    private $S2 = [];
    /**
     * The Key depended S-Table 3
     *
     * @var array
     * @access private
     */
    private $S3 = [];
    /**
     * Holds the last used key
     *
     * @var array
     * @access private
     */
    private $kl;
    /**
     * The Key Length (in bytes)
     *
     * @see Crypt_Twofish::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 16;
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws BadModeException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new BadModeException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
     * Sets the key length.
     *
     * Valid key lengths are 128, 192 or 256 bits
     *
     * @access public
     * @param int $length
     */
    public function setKeyLength($length)
    {
        switch ($length) {
            case 128:
            case 192:
            case 256:
                break;
            default:
                throw new \LengthException('Key of size ' . $length . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
        }
        parent::setKeyLength($length);
    }
    /**
     * Sets the key.
     *
     * Rijndael supports five different key lengths
     *
     * @see setKeyLength()
     * @access public
     * @param string $key
     * @throws \LengthException if the key length isn't supported
     */
    public function setKey($key)
    {
        switch (strlen($key)) {
            case 16:
            case 24:
            case 32:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 24 or 32 supported');
        }
        parent::setKey($key);
    }
    /**
     * Setup the key (expansion)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
     * @access private
     */
    protected function setupKey()
    {
        if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
            // already expanded
            return;
        }
        $this->kl = ['key' => $this->key];
        /* Key expanding and generating the key-depended s-boxes */
        $le_longs = unpack('V*', $this->key);
        $key = unpack('C*', $this->key);
        $m0 = self::$m0;
        $m1 = self::$m1;
        $m2 = self::$m2;
        $m3 = self::$m3;
        $q0 = self::$q0;
        $q1 = self::$q1;
        $K = $S0 = $S1 = $S2 = $S3 = [];
        switch (strlen($this->key)) {
            case 16:
                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[1], $le_longs[2]);
                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[3], $le_longs[4]);
                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
                    $A = $m0[$q0[$q0[$i] ^ $key[9]] ^ $key[1]] ^ $m1[$q0[$q1[$i] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$i] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$i] ^ $key[12]] ^ $key[4]];
                    $B = $m0[$q0[$q0[$j] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$j] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$j] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$j] ^ $key[16]] ^ $key[8]];
                    $B = $B << 8 | $B >> 24 & 0xff;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A << 9 | $A >> 23 & 0x1ff;
                }
                for ($i = 0; $i < 256; ++$i) {
                    $S0[$i] = $m0[$q0[$q0[$i] ^ $s4] ^ $s0];
                    $S1[$i] = $m1[$q0[$q1[$i] ^ $s5] ^ $s1];
                    $S2[$i] = $m2[$q1[$q0[$i] ^ $s6] ^ $s2];
                    $S3[$i] = $m3[$q1[$q1[$i] ^ $s7] ^ $s3];
                }
                break;
            case 24:
                list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[1], $le_longs[2]);
                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[3], $le_longs[4]);
                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[5], $le_longs[6]);
                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
                    $A = $m0[$q0[$q0[$q1[$i] ^ $key[17]] ^ $key[9]] ^ $key[1]] ^ $m1[$q0[$q1[$q1[$i] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$q0[$i] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$q0[$i] ^ $key[20]] ^ $key[12]] ^ $key[4]];
                    $B = $m0[$q0[$q0[$q1[$j] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$q1[$j] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$q0[$j] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$q0[$j] ^ $key[24]] ^ $key[16]] ^ $key[8]];
                    $B = $B << 8 | $B >> 24 & 0xff;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A << 9 | $A >> 23 & 0x1ff;
                }
                for ($i = 0; $i < 256; ++$i) {
                    $S0[$i] = $m0[$q0[$q0[$q1[$i] ^ $s8] ^ $s4] ^ $s0];
                    $S1[$i] = $m1[$q0[$q1[$q1[$i] ^ $s9] ^ $s5] ^ $s1];
                    $S2[$i] = $m2[$q1[$q0[$q0[$i] ^ $sa] ^ $s6] ^ $s2];
                    $S3[$i] = $m3[$q1[$q1[$q0[$i] ^ $sb] ^ $s7] ^ $s3];
                }
                break;
            default:
                // 32
                list($sf, $se, $sd, $sc) = $this->mdsrem($le_longs[1], $le_longs[2]);
                list($sb, $sa, $s9, $s8) = $this->mdsrem($le_longs[3], $le_longs[4]);
                list($s7, $s6, $s5, $s4) = $this->mdsrem($le_longs[5], $le_longs[6]);
                list($s3, $s2, $s1, $s0) = $this->mdsrem($le_longs[7], $le_longs[8]);
                for ($i = 0, $j = 1; $i < 40; $i += 2, $j += 2) {
                    $A = $m0[$q0[$q0[$q1[$q1[$i] ^ $key[25]] ^ $key[17]] ^ $key[9]] ^ $key[1]] ^ $m1[$q0[$q1[$q1[$q0[$i] ^ $key[26]] ^ $key[18]] ^ $key[10]] ^ $key[2]] ^ $m2[$q1[$q0[$q0[$q0[$i] ^ $key[27]] ^ $key[19]] ^ $key[11]] ^ $key[3]] ^ $m3[$q1[$q1[$q0[$q1[$i] ^ $key[28]] ^ $key[20]] ^ $key[12]] ^ $key[4]];
                    $B = $m0[$q0[$q0[$q1[$q1[$j] ^ $key[29]] ^ $key[21]] ^ $key[13]] ^ $key[5]] ^ $m1[$q0[$q1[$q1[$q0[$j] ^ $key[30]] ^ $key[22]] ^ $key[14]] ^ $key[6]] ^ $m2[$q1[$q0[$q0[$q0[$j] ^ $key[31]] ^ $key[23]] ^ $key[15]] ^ $key[7]] ^ $m3[$q1[$q1[$q0[$q1[$j] ^ $key[32]] ^ $key[24]] ^ $key[16]] ^ $key[8]];
                    $B = $B << 8 | $B >> 24 & 0xff;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A;
                    $A = self::safe_intval($A + $B);
                    $K[] = $A << 9 | $A >> 23 & 0x1ff;
                }
                for ($i = 0; $i < 256; ++$i) {
                    $S0[$i] = $m0[$q0[$q0[$q1[$q1[$i] ^ $sc] ^ $s8] ^ $s4] ^ $s0];
                    $S1[$i] = $m1[$q0[$q1[$q1[$q0[$i] ^ $sd] ^ $s9] ^ $s5] ^ $s1];
                    $S2[$i] = $m2[$q1[$q0[$q0[$q0[$i] ^ $se] ^ $sa] ^ $s6] ^ $s2];
                    $S3[$i] = $m3[$q1[$q1[$q0[$q1[$i] ^ $sf] ^ $sb] ^ $s7] ^ $s3];
                }
        }
        $this->K = $K;
        $this->S0 = $S0;
        $this->S1 = $S1;
        $this->S2 = $S2;
        $this->S3 = $S3;
    }
    /**
     * _mdsrem function using by the twofish cipher algorithm
     *
     * @access private
     * @param string $A
     * @param string $B
     * @return array
     */
    private function mdsrem($A, $B)
    {
        // No gain by unrolling this loop.
        for ($i = 0; $i < 8; ++$i) {
            // Get most significant coefficient.
            $t = 0xff & $B >> 24;
            // Shift the others up.
            $B = $B << 8 | 0xff & $A >> 24;
            $A <<= 8;
            $u = $t << 1;
            // Subtract the modular polynomial on overflow.
            if ($t & 0x80) {
                $u ^= 0x14d;
            }
            // Remove t * (a * x^2 + 1).
            $B ^= $t ^ $u << 16;
            // Form u = a*t + t/a = t*(a + 1/a).
            $u ^= 0x7fffffff & $t >> 1;
            // Add the modular polynomial on underflow.
            if ($t & 0x1) {
                $u ^= 0xa6;
            }
            // Remove t * (a + 1/a) * (x^3 + x).
            $B ^= $u << 24 | $u << 8;
        }
        return [0xff & $B >> 24, 0xff & $B >> 16, 0xff & $B >> 8, 0xff & $B];
    }
    /**
     * Encrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        $S0 = $this->S0;
        $S1 = $this->S1;
        $S2 = $this->S2;
        $S3 = $this->S3;
        $K = $this->K;
        $in = unpack("V4", $in);
        $R0 = $K[0] ^ $in[1];
        $R1 = $K[1] ^ $in[2];
        $R2 = $K[2] ^ $in[3];
        $R3 = $K[3] ^ $in[4];
        $ki = 7;
        while ($ki < 39) {
            $t0 = $S0[$R0 & 0xff] ^ $S1[$R0 >> 8 & 0xff] ^ $S2[$R0 >> 16 & 0xff] ^ $S3[$R0 >> 24 & 0xff];
            $t1 = $S0[$R1 >> 24 & 0xff] ^ $S1[$R1 & 0xff] ^ $S2[$R1 >> 8 & 0xff] ^ $S3[$R1 >> 16 & 0xff];
            $R2 ^= self::safe_intval($t0 + $t1 + $K[++$ki]);
            $R2 = $R2 >> 1 & 0x7fffffff | $R2 << 31;
            $R3 = ($R3 >> 31 & 1 | $R3 << 1) ^ self::safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
            $t0 = $S0[$R2 & 0xff] ^ $S1[$R2 >> 8 & 0xff] ^ $S2[$R2 >> 16 & 0xff] ^ $S3[$R2 >> 24 & 0xff];
            $t1 = $S0[$R3 >> 24 & 0xff] ^ $S1[$R3 & 0xff] ^ $S2[$R3 >> 8 & 0xff] ^ $S3[$R3 >> 16 & 0xff];
            $R0 ^= self::safe_intval($t0 + $t1 + $K[++$ki]);
            $R0 = $R0 >> 1 & 0x7fffffff | $R0 << 31;
            $R1 = ($R1 >> 31 & 1 | $R1 << 1) ^ self::safe_intval($t0 + ($t1 << 1) + $K[++$ki]);
        }
        // @codingStandardsIgnoreStart
        return pack("V4", $K[4] ^ $R2, $K[5] ^ $R3, $K[6] ^ $R0, $K[7] ^ $R1);
        // @codingStandardsIgnoreEnd
    }
    /**
     * Decrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        $S0 = $this->S0;
        $S1 = $this->S1;
        $S2 = $this->S2;
        $S3 = $this->S3;
        $K = $this->K;
        $in = unpack("V4", $in);
        $R0 = $K[4] ^ $in[1];
        $R1 = $K[5] ^ $in[2];
        $R2 = $K[6] ^ $in[3];
        $R3 = $K[7] ^ $in[4];
        $ki = 40;
        while ($ki > 8) {
            $t0 = $S0[$R0 & 0xff] ^ $S1[$R0 >> 8 & 0xff] ^ $S2[$R0 >> 16 & 0xff] ^ $S3[$R0 >> 24 & 0xff];
            $t1 = $S0[$R1 >> 24 & 0xff] ^ $S1[$R1 & 0xff] ^ $S2[$R1 >> 8 & 0xff] ^ $S3[$R1 >> 16 & 0xff];
            $R3 ^= self::safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
            $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
            $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ self::safe_intval($t0 + $t1 + $K[--$ki]);
            $t0 = $S0[$R2 & 0xff] ^ $S1[$R2 >> 8 & 0xff] ^ $S2[$R2 >> 16 & 0xff] ^ $S3[$R2 >> 24 & 0xff];
            $t1 = $S0[$R3 >> 24 & 0xff] ^ $S1[$R3 & 0xff] ^ $S2[$R3 >> 8 & 0xff] ^ $S3[$R3 >> 16 & 0xff];
            $R1 ^= self::safe_intval($t0 + ($t1 << 1) + $K[--$ki]);
            $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
            $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ self::safe_intval($t0 + $t1 + $K[--$ki]);
        }
        // @codingStandardsIgnoreStart
        return pack("V4", $K[0] ^ $R2, $K[1] ^ $R3, $K[2] ^ $R0, $K[3] ^ $R1);
        // @codingStandardsIgnoreEnd
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        $K = $this->K;
        $init_crypt = '
            static $S0, $S1, $S2, $S3;
            if (!$S0) {
                for ($i = 0; $i < 256; ++$i) {
                    $S0[] = (int)$this->S0[$i];
                    $S1[] = (int)$this->S1[$i];
                    $S2[] = (int)$this->S2[$i];
                    $S3[] = (int)$this->S3[$i];
                }
            }
        ';
        $safeint = self::safe_intval_inline();
        // Generating encrypt code:
        $encrypt_block = '
            $in = unpack("V4", $in);
            $R0 = ' . $K[0] . ' ^ $in[1];
            $R1 = ' . $K[1] . ' ^ $in[2];
            $R2 = ' . $K[2] . ' ^ $in[3];
            $R3 = ' . $K[3] . ' ^ $in[4];
        ';
        for ($ki = 7, $i = 0; $i < 8; ++$i) {
            $encrypt_block .= '
                $t0 = $S0[ $R0        & 0xff] ^
                      $S1[($R0 >>  8) & 0xff] ^
                      $S2[($R0 >> 16) & 0xff] ^
                      $S3[($R0 >> 24) & 0xff];
                $t1 = $S0[($R1 >> 24) & 0xff] ^
                      $S1[ $R1        & 0xff] ^
                      $S2[($R1 >>  8) & 0xff] ^
                      $S3[($R1 >> 16) & 0xff];
                    $R2^= ' . sprintf($safeint, '$t0 + $t1 + ' . $K[++$ki]) . ';
                $R2 = ($R2 >> 1 & 0x7fffffff) | ($R2 << 31);
                $R3 = ((($R3 >> 31) & 1) | ($R3 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';

                $t0 = $S0[ $R2        & 0xff] ^
                      $S1[($R2 >>  8) & 0xff] ^
                      $S2[($R2 >> 16) & 0xff] ^
                      $S3[($R2 >> 24) & 0xff];
                $t1 = $S0[($R3 >> 24) & 0xff] ^
                      $S1[ $R3        & 0xff] ^
                      $S2[($R3 >>  8) & 0xff] ^
                      $S3[($R3 >> 16) & 0xff];
                $R0^= ' . sprintf($safeint, '($t0 + $t1 + ' . $K[++$ki] . ')') . ';
                $R0 = ($R0 >> 1 & 0x7fffffff) | ($R0 << 31);
                $R1 = ((($R1 >> 31) & 1) | ($R1 << 1)) ^ ' . sprintf($safeint, '($t0 + ($t1 << 1) + ' . $K[++$ki] . ')') . ';
            ';
        }
        $encrypt_block .= '
            $in = pack("V4", ' . $K[4] . ' ^ $R2,
                             ' . $K[5] . ' ^ $R3,
                             ' . $K[6] . ' ^ $R0,
                             ' . $K[7] . ' ^ $R1);
        ';
        // Generating decrypt code:
        $decrypt_block = '
            $in = unpack("V4", $in);
            $R0 = ' . $K[4] . ' ^ $in[1];
            $R1 = ' . $K[5] . ' ^ $in[2];
            $R2 = ' . $K[6] . ' ^ $in[3];
            $R3 = ' . $K[7] . ' ^ $in[4];
        ';
        for ($ki = 40, $i = 0; $i < 8; ++$i) {
            $decrypt_block .= '
                $t0 = $S0[$R0       & 0xff] ^
                      $S1[$R0 >>  8 & 0xff] ^
                      $S2[$R0 >> 16 & 0xff] ^
                      $S3[$R0 >> 24 & 0xff];
                $t1 = $S0[$R1 >> 24 & 0xff] ^
                      $S1[$R1       & 0xff] ^
                      $S2[$R1 >>  8 & 0xff] ^
                      $S3[$R1 >> 16 & 0xff];
                $R3^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
                $R3 = $R3 >> 1 & 0x7fffffff | $R3 << 31;
                $R2 = ($R2 >> 31 & 0x1 | $R2 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + ' . $K[--$ki] . ')') . ';

                $t0 = $S0[$R2       & 0xff] ^
                      $S1[$R2 >>  8 & 0xff] ^
                      $S2[$R2 >> 16 & 0xff] ^
                      $S3[$R2 >> 24 & 0xff];
                $t1 = $S0[$R3 >> 24 & 0xff] ^
                      $S1[$R3       & 0xff] ^
                      $S2[$R3 >>  8 & 0xff] ^
                      $S3[$R3 >> 16 & 0xff];
                $R1^= ' . sprintf($safeint, '$t0 + ($t1 << 1) + ' . $K[--$ki]) . ';
                $R1 = $R1 >> 1 & 0x7fffffff | $R1 << 31;
                $R0 = ($R0 >> 31 & 0x1 | $R0 << 1) ^ ' . sprintf($safeint, '($t0 + $t1 + ' . $K[--$ki] . ')') . ';
            ';
        }
        $decrypt_block .= '
            $in = pack("V4", ' . $K[0] . ' ^ $R2,
                             ' . $K[1] . ' ^ $R3,
                             ' . $K[2] . ' ^ $R0,
                             ' . $K[3] . ' ^ $R1);
        ';
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => $init_crypt, 'init_encrypt' => '', 'init_decrypt' => '', 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block]);
    }
}<?php

/**
 * Pure-PHP implementation of DES.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://en.wikipedia.org/wiki/DES_supplementary_material Wikipedia: DES supplementary material}
 *  - {@link http://www.itl.nist.gov/fipspubs/fip46-2.htm FIPS 46-2 - (DES), Data Encryption Standard}
 *  - {@link http://www.cs.eku.edu/faculty/styer/460/Encrypt/JS-DES.html JavaScript DES Example}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $des = new \phpseclib3\Crypt\DES('ctr');
 *
 *    $des->setKey('abcdefgh');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $des->decrypt($des->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   DES
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
use phpseclib3\Exception\BadModeException;
/**
 * Pure-PHP implementation of DES.
 *
 * @package DES
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class DES extends BlockCipher
{
    /**
     * Contains $keys[self::ENCRYPT]
     *
     * @access private
     * @see \phpseclib3\Crypt\DES::setupKey()
     * @see \phpseclib3\Crypt\DES::processBlock()
     */
    const ENCRYPT = 0;
    /**
     * Contains $keys[self::DECRYPT]
     *
     * @access private
     * @see \phpseclib3\Crypt\DES::setupKey()
     * @see \phpseclib3\Crypt\DES::processBlock()
     */
    const DECRYPT = 1;
    /**
     * Block Length of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
     * @var int
     * @access private
     */
    protected $block_size = 8;
    /**
     * Key Length (in bytes)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 8;
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'des';
    /**
     * The OpenSSL names of the cipher / modes
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::openssl_mode_names
     * @var array
     * @access private
     */
    protected $openssl_mode_names = [self::MODE_ECB => 'des-ecb', self::MODE_CBC => 'des-cbc', self::MODE_CFB => 'des-cfb', self::MODE_OFB => 'des-ofb'];
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 500;
    /**
     * Switch for DES/3DES encryption
     *
     * Used only if $engine == self::ENGINE_INTERNAL
     *
     * @see self::setupKey()
     * @see self::processBlock()
     * @var int
     * @access private
     */
    protected $des_rounds = 1;
    /**
     * max possible size of $key
     *
     * @see self::setKey()
     * @var string
     * @access private
     */
    protected $key_length_max = 8;
    /**
     * The Key Schedule
     *
     * @see self::setupKey()
     * @var array
     * @access private
     */
    private $keys;
    /**
     * Shuffle table.
     *
     * For each byte value index, the entry holds an 8-byte string
     * with each byte containing all bits in the same state as the
     * corresponding bit in the index value.
     *
     * @see self::processBlock()
     * @see self::setupKey()
     * @var array
     * @access private
     */
    protected static $shuffle = ["\x00\x00\x00\x00\x00\x00\x00\x00", "\x00\x00\x00\x00\x00\x00\x00\xff", "\x00\x00\x00\x00\x00\x00\xff\x00", "\x00\x00\x00\x00\x00\x00\xff\xff", "\x00\x00\x00\x00\x00\xff\x00\x00", "\x00\x00\x00\x00\x00\xff\x00\xff", "\x00\x00\x00\x00\x00\xff\xff\x00", "\x00\x00\x00\x00\x00\xff\xff\xff", "\x00\x00\x00\x00\xff\x00\x00\x00", "\x00\x00\x00\x00\xff\x00\x00\xff", "\x00\x00\x00\x00\xff\x00\xff\x00", "\x00\x00\x00\x00\xff\x00\xff\xff", "\x00\x00\x00\x00\xff\xff\x00\x00", "\x00\x00\x00\x00\xff\xff\x00\xff", "\x00\x00\x00\x00\xff\xff\xff\x00", "\x00\x00\x00\x00\xff\xff\xff\xff", "\x00\x00\x00\xff\x00\x00\x00\x00", "\x00\x00\x00\xff\x00\x00\x00\xff", "\x00\x00\x00\xff\x00\x00\xff\x00", "\x00\x00\x00\xff\x00\x00\xff\xff", "\x00\x00\x00\xff\x00\xff\x00\x00", "\x00\x00\x00\xff\x00\xff\x00\xff", "\x00\x00\x00\xff\x00\xff\xff\x00", "\x00\x00\x00\xff\x00\xff\xff\xff", "\x00\x00\x00\xff\xff\x00\x00\x00", "\x00\x00\x00\xff\xff\x00\x00\xff", "\x00\x00\x00\xff\xff\x00\xff\x00", "\x00\x00\x00\xff\xff\x00\xff\xff", "\x00\x00\x00\xff\xff\xff\x00\x00", "\x00\x00\x00\xff\xff\xff\x00\xff", "\x00\x00\x00\xff\xff\xff\xff\x00", "\x00\x00\x00\xff\xff\xff\xff\xff", "\x00\x00\xff\x00\x00\x00\x00\x00", "\x00\x00\xff\x00\x00\x00\x00\xff", "\x00\x00\xff\x00\x00\x00\xff\x00", "\x00\x00\xff\x00\x00\x00\xff\xff", "\x00\x00\xff\x00\x00\xff\x00\x00", "\x00\x00\xff\x00\x00\xff\x00\xff", "\x00\x00\xff\x00\x00\xff\xff\x00", "\x00\x00\xff\x00\x00\xff\xff\xff", "\x00\x00\xff\x00\xff\x00\x00\x00", "\x00\x00\xff\x00\xff\x00\x00\xff", "\x00\x00\xff\x00\xff\x00\xff\x00", "\x00\x00\xff\x00\xff\x00\xff\xff", "\x00\x00\xff\x00\xff\xff\x00\x00", "\x00\x00\xff\x00\xff\xff\x00\xff", "\x00\x00\xff\x00\xff\xff\xff\x00", "\x00\x00\xff\x00\xff\xff\xff\xff", "\x00\x00\xff\xff\x00\x00\x00\x00", "\x00\x00\xff\xff\x00\x00\x00\xff", "\x00\x00\xff\xff\x00\x00\xff\x00", "\x00\x00\xff\xff\x00\x00\xff\xff", "\x00\x00\xff\xff\x00\xff\x00\x00", "\x00\x00\xff\xff\x00\xff\x00\xff", "\x00\x00\xff\xff\x00\xff\xff\x00", "\x00\x00\xff\xff\x00\xff\xff\xff", "\x00\x00\xff\xff\xff\x00\x00\x00", "\x00\x00\xff\xff\xff\x00\x00\xff", "\x00\x00\xff\xff\xff\x00\xff\x00", "\x00\x00\xff\xff\xff\x00\xff\xff", "\x00\x00\xff\xff\xff\xff\x00\x00", "\x00\x00\xff\xff\xff\xff\x00\xff", "\x00\x00\xff\xff\xff\xff\xff\x00", "\x00\x00\xff\xff\xff\xff\xff\xff", "\x00\xff\x00\x00\x00\x00\x00\x00", "\x00\xff\x00\x00\x00\x00\x00\xff", "\x00\xff\x00\x00\x00\x00\xff\x00", "\x00\xff\x00\x00\x00\x00\xff\xff", "\x00\xff\x00\x00\x00\xff\x00\x00", "\x00\xff\x00\x00\x00\xff\x00\xff", "\x00\xff\x00\x00\x00\xff\xff\x00", "\x00\xff\x00\x00\x00\xff\xff\xff", "\x00\xff\x00\x00\xff\x00\x00\x00", "\x00\xff\x00\x00\xff\x00\x00\xff", "\x00\xff\x00\x00\xff\x00\xff\x00", "\x00\xff\x00\x00\xff\x00\xff\xff", "\x00\xff\x00\x00\xff\xff\x00\x00", "\x00\xff\x00\x00\xff\xff\x00\xff", "\x00\xff\x00\x00\xff\xff\xff\x00", "\x00\xff\x00\x00\xff\xff\xff\xff", "\x00\xff\x00\xff\x00\x00\x00\x00", "\x00\xff\x00\xff\x00\x00\x00\xff", "\x00\xff\x00\xff\x00\x00\xff\x00", "\x00\xff\x00\xff\x00\x00\xff\xff", "\x00\xff\x00\xff\x00\xff\x00\x00", "\x00\xff\x00\xff\x00\xff\x00\xff", "\x00\xff\x00\xff\x00\xff\xff\x00", "\x00\xff\x00\xff\x00\xff\xff\xff", "\x00\xff\x00\xff\xff\x00\x00\x00", "\x00\xff\x00\xff\xff\x00\x00\xff", "\x00\xff\x00\xff\xff\x00\xff\x00", "\x00\xff\x00\xff\xff\x00\xff\xff", "\x00\xff\x00\xff\xff\xff\x00\x00", "\x00\xff\x00\xff\xff\xff\x00\xff", "\x00\xff\x00\xff\xff\xff\xff\x00", "\x00\xff\x00\xff\xff\xff\xff\xff", "\x00\xff\xff\x00\x00\x00\x00\x00", "\x00\xff\xff\x00\x00\x00\x00\xff", "\x00\xff\xff\x00\x00\x00\xff\x00", "\x00\xff\xff\x00\x00\x00\xff\xff", "\x00\xff\xff\x00\x00\xff\x00\x00", "\x00\xff\xff\x00\x00\xff\x00\xff", "\x00\xff\xff\x00\x00\xff\xff\x00", "\x00\xff\xff\x00\x00\xff\xff\xff", "\x00\xff\xff\x00\xff\x00\x00\x00", "\x00\xff\xff\x00\xff\x00\x00\xff", "\x00\xff\xff\x00\xff\x00\xff\x00", "\x00\xff\xff\x00\xff\x00\xff\xff", "\x00\xff\xff\x00\xff\xff\x00\x00", "\x00\xff\xff\x00\xff\xff\x00\xff", "\x00\xff\xff\x00\xff\xff\xff\x00", "\x00\xff\xff\x00\xff\xff\xff\xff", "\x00\xff\xff\xff\x00\x00\x00\x00", "\x00\xff\xff\xff\x00\x00\x00\xff", "\x00\xff\xff\xff\x00\x00\xff\x00", "\x00\xff\xff\xff\x00\x00\xff\xff", "\x00\xff\xff\xff\x00\xff\x00\x00", "\x00\xff\xff\xff\x00\xff\x00\xff", "\x00\xff\xff\xff\x00\xff\xff\x00", "\x00\xff\xff\xff\x00\xff\xff\xff", "\x00\xff\xff\xff\xff\x00\x00\x00", "\x00\xff\xff\xff\xff\x00\x00\xff", "\x00\xff\xff\xff\xff\x00\xff\x00", "\x00\xff\xff\xff\xff\x00\xff\xff", "\x00\xff\xff\xff\xff\xff\x00\x00", "\x00\xff\xff\xff\xff\xff\x00\xff", "\x00\xff\xff\xff\xff\xff\xff\x00", "\x00\xff\xff\xff\xff\xff\xff\xff", "\xff\x00\x00\x00\x00\x00\x00\x00", "\xff\x00\x00\x00\x00\x00\x00\xff", "\xff\x00\x00\x00\x00\x00\xff\x00", "\xff\x00\x00\x00\x00\x00\xff\xff", "\xff\x00\x00\x00\x00\xff\x00\x00", "\xff\x00\x00\x00\x00\xff\x00\xff", "\xff\x00\x00\x00\x00\xff\xff\x00", "\xff\x00\x00\x00\x00\xff\xff\xff", "\xff\x00\x00\x00\xff\x00\x00\x00", "\xff\x00\x00\x00\xff\x00\x00\xff", "\xff\x00\x00\x00\xff\x00\xff\x00", "\xff\x00\x00\x00\xff\x00\xff\xff", "\xff\x00\x00\x00\xff\xff\x00\x00", "\xff\x00\x00\x00\xff\xff\x00\xff", "\xff\x00\x00\x00\xff\xff\xff\x00", "\xff\x00\x00\x00\xff\xff\xff\xff", "\xff\x00\x00\xff\x00\x00\x00\x00", "\xff\x00\x00\xff\x00\x00\x00\xff", "\xff\x00\x00\xff\x00\x00\xff\x00", "\xff\x00\x00\xff\x00\x00\xff\xff", "\xff\x00\x00\xff\x00\xff\x00\x00", "\xff\x00\x00\xff\x00\xff\x00\xff", "\xff\x00\x00\xff\x00\xff\xff\x00", "\xff\x00\x00\xff\x00\xff\xff\xff", "\xff\x00\x00\xff\xff\x00\x00\x00", "\xff\x00\x00\xff\xff\x00\x00\xff", "\xff\x00\x00\xff\xff\x00\xff\x00", "\xff\x00\x00\xff\xff\x00\xff\xff", "\xff\x00\x00\xff\xff\xff\x00\x00", "\xff\x00\x00\xff\xff\xff\x00\xff", "\xff\x00\x00\xff\xff\xff\xff\x00", "\xff\x00\x00\xff\xff\xff\xff\xff", "\xff\x00\xff\x00\x00\x00\x00\x00", "\xff\x00\xff\x00\x00\x00\x00\xff", "\xff\x00\xff\x00\x00\x00\xff\x00", "\xff\x00\xff\x00\x00\x00\xff\xff", "\xff\x00\xff\x00\x00\xff\x00\x00", "\xff\x00\xff\x00\x00\xff\x00\xff", "\xff\x00\xff\x00\x00\xff\xff\x00", "\xff\x00\xff\x00\x00\xff\xff\xff", "\xff\x00\xff\x00\xff\x00\x00\x00", "\xff\x00\xff\x00\xff\x00\x00\xff", "\xff\x00\xff\x00\xff\x00\xff\x00", "\xff\x00\xff\x00\xff\x00\xff\xff", "\xff\x00\xff\x00\xff\xff\x00\x00", "\xff\x00\xff\x00\xff\xff\x00\xff", "\xff\x00\xff\x00\xff\xff\xff\x00", "\xff\x00\xff\x00\xff\xff\xff\xff", "\xff\x00\xff\xff\x00\x00\x00\x00", "\xff\x00\xff\xff\x00\x00\x00\xff", "\xff\x00\xff\xff\x00\x00\xff\x00", "\xff\x00\xff\xff\x00\x00\xff\xff", "\xff\x00\xff\xff\x00\xff\x00\x00", "\xff\x00\xff\xff\x00\xff\x00\xff", "\xff\x00\xff\xff\x00\xff\xff\x00", "\xff\x00\xff\xff\x00\xff\xff\xff", "\xff\x00\xff\xff\xff\x00\x00\x00", "\xff\x00\xff\xff\xff\x00\x00\xff", "\xff\x00\xff\xff\xff\x00\xff\x00", "\xff\x00\xff\xff\xff\x00\xff\xff", "\xff\x00\xff\xff\xff\xff\x00\x00", "\xff\x00\xff\xff\xff\xff\x00\xff", "\xff\x00\xff\xff\xff\xff\xff\x00", "\xff\x00\xff\xff\xff\xff\xff\xff", "\xff\xff\x00\x00\x00\x00\x00\x00", "\xff\xff\x00\x00\x00\x00\x00\xff", "\xff\xff\x00\x00\x00\x00\xff\x00", "\xff\xff\x00\x00\x00\x00\xff\xff", "\xff\xff\x00\x00\x00\xff\x00\x00", "\xff\xff\x00\x00\x00\xff\x00\xff", "\xff\xff\x00\x00\x00\xff\xff\x00", "\xff\xff\x00\x00\x00\xff\xff\xff", "\xff\xff\x00\x00\xff\x00\x00\x00", "\xff\xff\x00\x00\xff\x00\x00\xff", "\xff\xff\x00\x00\xff\x00\xff\x00", "\xff\xff\x00\x00\xff\x00\xff\xff", "\xff\xff\x00\x00\xff\xff\x00\x00", "\xff\xff\x00\x00\xff\xff\x00\xff", "\xff\xff\x00\x00\xff\xff\xff\x00", "\xff\xff\x00\x00\xff\xff\xff\xff", "\xff\xff\x00\xff\x00\x00\x00\x00", "\xff\xff\x00\xff\x00\x00\x00\xff", "\xff\xff\x00\xff\x00\x00\xff\x00", "\xff\xff\x00\xff\x00\x00\xff\xff", "\xff\xff\x00\xff\x00\xff\x00\x00", "\xff\xff\x00\xff\x00\xff\x00\xff", "\xff\xff\x00\xff\x00\xff\xff\x00", "\xff\xff\x00\xff\x00\xff\xff\xff", "\xff\xff\x00\xff\xff\x00\x00\x00", "\xff\xff\x00\xff\xff\x00\x00\xff", "\xff\xff\x00\xff\xff\x00\xff\x00", "\xff\xff\x00\xff\xff\x00\xff\xff", "\xff\xff\x00\xff\xff\xff\x00\x00", "\xff\xff\x00\xff\xff\xff\x00\xff", "\xff\xff\x00\xff\xff\xff\xff\x00", "\xff\xff\x00\xff\xff\xff\xff\xff", "\xff\xff\xff\x00\x00\x00\x00\x00", "\xff\xff\xff\x00\x00\x00\x00\xff", "\xff\xff\xff\x00\x00\x00\xff\x00", "\xff\xff\xff\x00\x00\x00\xff\xff", "\xff\xff\xff\x00\x00\xff\x00\x00", "\xff\xff\xff\x00\x00\xff\x00\xff", "\xff\xff\xff\x00\x00\xff\xff\x00", "\xff\xff\xff\x00\x00\xff\xff\xff", "\xff\xff\xff\x00\xff\x00\x00\x00", "\xff\xff\xff\x00\xff\x00\x00\xff", "\xff\xff\xff\x00\xff\x00\xff\x00", "\xff\xff\xff\x00\xff\x00\xff\xff", "\xff\xff\xff\x00\xff\xff\x00\x00", "\xff\xff\xff\x00\xff\xff\x00\xff", "\xff\xff\xff\x00\xff\xff\xff\x00", "\xff\xff\xff\x00\xff\xff\xff\xff", "\xff\xff\xff\xff\x00\x00\x00\x00", "\xff\xff\xff\xff\x00\x00\x00\xff", "\xff\xff\xff\xff\x00\x00\xff\x00", "\xff\xff\xff\xff\x00\x00\xff\xff", "\xff\xff\xff\xff\x00\xff\x00\x00", "\xff\xff\xff\xff\x00\xff\x00\xff", "\xff\xff\xff\xff\x00\xff\xff\x00", "\xff\xff\xff\xff\x00\xff\xff\xff", "\xff\xff\xff\xff\xff\x00\x00\x00", "\xff\xff\xff\xff\xff\x00\x00\xff", "\xff\xff\xff\xff\xff\x00\xff\x00", "\xff\xff\xff\xff\xff\x00\xff\xff", "\xff\xff\xff\xff\xff\xff\x00\x00", "\xff\xff\xff\xff\xff\xff\x00\xff", "\xff\xff\xff\xff\xff\xff\xff\x00", "\xff\xff\xff\xff\xff\xff\xff\xff"];
    /**
     * IP mapping helper table.
     *
     * Indexing this table with each source byte performs the initial bit permutation.
     *
     * @var array
     * @access private
     */
    protected static $ipmap = [0x0, 0x10, 0x1, 0x11, 0x20, 0x30, 0x21, 0x31, 0x2, 0x12, 0x3, 0x13, 0x22, 0x32, 0x23, 0x33, 0x40, 0x50, 0x41, 0x51, 0x60, 0x70, 0x61, 0x71, 0x42, 0x52, 0x43, 0x53, 0x62, 0x72, 0x63, 0x73, 0x4, 0x14, 0x5, 0x15, 0x24, 0x34, 0x25, 0x35, 0x6, 0x16, 0x7, 0x17, 0x26, 0x36, 0x27, 0x37, 0x44, 0x54, 0x45, 0x55, 0x64, 0x74, 0x65, 0x75, 0x46, 0x56, 0x47, 0x57, 0x66, 0x76, 0x67, 0x77, 0x80, 0x90, 0x81, 0x91, 0xa0, 0xb0, 0xa1, 0xb1, 0x82, 0x92, 0x83, 0x93, 0xa2, 0xb2, 0xa3, 0xb3, 0xc0, 0xd0, 0xc1, 0xd1, 0xe0, 0xf0, 0xe1, 0xf1, 0xc2, 0xd2, 0xc3, 0xd3, 0xe2, 0xf2, 0xe3, 0xf3, 0x84, 0x94, 0x85, 0x95, 0xa4, 0xb4, 0xa5, 0xb5, 0x86, 0x96, 0x87, 0x97, 0xa6, 0xb6, 0xa7, 0xb7, 0xc4, 0xd4, 0xc5, 0xd5, 0xe4, 0xf4, 0xe5, 0xf5, 0xc6, 0xd6, 0xc7, 0xd7, 0xe6, 0xf6, 0xe7, 0xf7, 0x8, 0x18, 0x9, 0x19, 0x28, 0x38, 0x29, 0x39, 0xa, 0x1a, 0xb, 0x1b, 0x2a, 0x3a, 0x2b, 0x3b, 0x48, 0x58, 0x49, 0x59, 0x68, 0x78, 0x69, 0x79, 0x4a, 0x5a, 0x4b, 0x5b, 0x6a, 0x7a, 0x6b, 0x7b, 0xc, 0x1c, 0xd, 0x1d, 0x2c, 0x3c, 0x2d, 0x3d, 0xe, 0x1e, 0xf, 0x1f, 0x2e, 0x3e, 0x2f, 0x3f, 0x4c, 0x5c, 0x4d, 0x5d, 0x6c, 0x7c, 0x6d, 0x7d, 0x4e, 0x5e, 0x4f, 0x5f, 0x6e, 0x7e, 0x6f, 0x7f, 0x88, 0x98, 0x89, 0x99, 0xa8, 0xb8, 0xa9, 0xb9, 0x8a, 0x9a, 0x8b, 0x9b, 0xaa, 0xba, 0xab, 0xbb, 0xc8, 0xd8, 0xc9, 0xd9, 0xe8, 0xf8, 0xe9, 0xf9, 0xca, 0xda, 0xcb, 0xdb, 0xea, 0xfa, 0xeb, 0xfb, 0x8c, 0x9c, 0x8d, 0x9d, 0xac, 0xbc, 0xad, 0xbd, 0x8e, 0x9e, 0x8f, 0x9f, 0xae, 0xbe, 0xaf, 0xbf, 0xcc, 0xdc, 0xcd, 0xdd, 0xec, 0xfc, 0xed, 0xfd, 0xce, 0xde, 0xcf, 0xdf, 0xee, 0xfe, 0xef, 0xff];
    /**
     * Inverse IP mapping helper table.
     * Indexing this table with a byte value reverses the bit order.
     *
     * @var array
     * @access private
     */
    protected static $invipmap = [0x0, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 0x8, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 0x4, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 0xc, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 0x2, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 0xa, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 0x6, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 0xe, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 0x1, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 0x9, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 0x5, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 0xd, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 0x3, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 0xb, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 0x7, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 0xf, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff];
    /**
     * Pre-permuted S-box1
     *
     * Each box ($sbox1-$sbox8) has been vectorized, then each value pre-permuted using the
     * P table: concatenation can then be replaced by exclusive ORs.
     *
     * @var array
     * @access private
     */
    protected static $sbox1 = [0x808200, 0x0, 0x8000, 0x808202, 0x808002, 0x8202, 0x2, 0x8000, 0x200, 0x808200, 0x808202, 0x200, 0x800202, 0x808002, 0x800000, 0x2, 0x202, 0x800200, 0x800200, 0x8200, 0x8200, 0x808000, 0x808000, 0x800202, 0x8002, 0x800002, 0x800002, 0x8002, 0x0, 0x202, 0x8202, 0x800000, 0x8000, 0x808202, 0x2, 0x808000, 0x808200, 0x800000, 0x800000, 0x200, 0x808002, 0x8000, 0x8200, 0x800002, 0x200, 0x2, 0x800202, 0x8202, 0x808202, 0x8002, 0x808000, 0x800202, 0x800002, 0x202, 0x8202, 0x808200, 0x202, 0x800200, 0x800200, 0x0, 0x8002, 0x8200, 0x0, 0x808002];
    /**
     * Pre-permuted S-box2
     *
     * @var array
     * @access private
     */
    protected static $sbox2 = [0x40084010, 0x40004000, 0x4000, 0x84010, 0x80000, 0x10, 0x40080010, 0x40004010, 0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x80000, 0x10, 0x40080010, 0x84000, 0x80010, 0x40004010, 0x0, 0x40000000, 0x4000, 0x84010, 0x40080000, 0x80010, 0x40000010, 0x0, 0x84000, 0x4010, 0x40084000, 0x40080000, 0x4010, 0x0, 0x84010, 0x40080010, 0x80000, 0x40004010, 0x40080000, 0x40084000, 0x4000, 0x40080000, 0x40004000, 0x10, 0x40084010, 0x84010, 0x10, 0x4000, 0x40000000, 0x4010, 0x40084000, 0x80000, 0x40000010, 0x80010, 0x40004010, 0x40000010, 0x80010, 0x84000, 0x0, 0x40004000, 0x4010, 0x40000000, 0x40080010, 0x40084010, 0x84000];
    /**
     * Pre-permuted S-box3
     *
     * @var array
     * @access private
     */
    protected static $sbox3 = [0x104, 0x4010100, 0x0, 0x4010004, 0x4000100, 0x0, 0x10104, 0x4000100, 0x10004, 0x4000004, 0x4000004, 0x10000, 0x4010104, 0x10004, 0x4010000, 0x104, 0x4000000, 0x4, 0x4010100, 0x100, 0x10100, 0x4010000, 0x4010004, 0x10104, 0x4000104, 0x10100, 0x10000, 0x4000104, 0x4, 0x4010104, 0x100, 0x4000000, 0x4010100, 0x4000000, 0x10004, 0x104, 0x10000, 0x4010100, 0x4000100, 0x0, 0x100, 0x10004, 0x4010104, 0x4000100, 0x4000004, 0x100, 0x0, 0x4010004, 0x4000104, 0x10000, 0x4000000, 0x4010104, 0x4, 0x10104, 0x10100, 0x4000004, 0x4010000, 0x4000104, 0x104, 0x4010000, 0x10104, 0x4, 0x4010004, 0x10100];
    /**
     * Pre-permuted S-box4
     *
     * @var array
     * @access private
     */
    protected static $sbox4 = [0x80401000, 0x80001040, 0x80001040, 0x40, 0x401040, 0x80400040, 0x80400000, 0x80001000, 0x0, 0x401000, 0x401000, 0x80401040, 0x80000040, 0x0, 0x400040, 0x80400000, 0x80000000, 0x1000, 0x400000, 0x80401000, 0x40, 0x400000, 0x80001000, 0x1040, 0x80400040, 0x80000000, 0x1040, 0x400040, 0x1000, 0x401040, 0x80401040, 0x80000040, 0x400040, 0x80400000, 0x401000, 0x80401040, 0x80000040, 0x0, 0x0, 0x401000, 0x1040, 0x400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x40, 0x80401040, 0x80000040, 0x80000000, 0x1000, 0x80400000, 0x80001000, 0x401040, 0x80400040, 0x80001000, 0x1040, 0x400000, 0x80401000, 0x40, 0x400000, 0x1000, 0x401040];
    /**
     * Pre-permuted S-box5
     *
     * @var array
     * @access private
     */
    protected static $sbox5 = [0x80, 0x1040080, 0x1040000, 0x21000080, 0x40000, 0x80, 0x20000000, 0x1040000, 0x20040080, 0x40000, 0x1000080, 0x20040080, 0x21000080, 0x21040000, 0x40080, 0x20000000, 0x1000000, 0x20040000, 0x20040000, 0x0, 0x20000080, 0x21040080, 0x21040080, 0x1000080, 0x21040000, 0x20000080, 0x0, 0x21000000, 0x1040080, 0x1000000, 0x21000000, 0x40080, 0x40000, 0x21000080, 0x80, 0x1000000, 0x20000000, 0x1040000, 0x21000080, 0x20040080, 0x1000080, 0x20000000, 0x21040000, 0x1040080, 0x20040080, 0x80, 0x1000000, 0x21040000, 0x21040080, 0x40080, 0x21000000, 0x21040080, 0x1040000, 0x0, 0x20040000, 0x21000000, 0x40080, 0x1000080, 0x20000080, 0x40000, 0x0, 0x20040000, 0x1040080, 0x20000080];
    /**
     * Pre-permuted S-box6
     *
     * @var array
     * @access private
     */
    protected static $sbox6 = [0x10000008, 0x10200000, 0x2000, 0x10202008, 0x10200000, 0x8, 0x10202008, 0x200000, 0x10002000, 0x202008, 0x200000, 0x10000008, 0x200008, 0x10002000, 0x10000000, 0x2008, 0x0, 0x200008, 0x10002008, 0x2000, 0x202000, 0x10002008, 0x8, 0x10200008, 0x10200008, 0x0, 0x202008, 0x10202000, 0x2008, 0x202000, 0x10202000, 0x10000000, 0x10002000, 0x8, 0x10200008, 0x202000, 0x10202008, 0x200000, 0x2008, 0x10000008, 0x200000, 0x10002000, 0x10000000, 0x2008, 0x10000008, 0x10202008, 0x202000, 0x10200000, 0x202008, 0x10202000, 0x0, 0x10200008, 0x8, 0x2000, 0x10200000, 0x202008, 0x2000, 0x200008, 0x10002008, 0x0, 0x10202000, 0x10000000, 0x200008, 0x10002008];
    /**
     * Pre-permuted S-box7
     *
     * @var array
     * @access private
     */
    protected static $sbox7 = [0x100000, 0x2100001, 0x2000401, 0x0, 0x400, 0x2000401, 0x100401, 0x2100400, 0x2100401, 0x100000, 0x0, 0x2000001, 0x1, 0x2000000, 0x2100001, 0x401, 0x2000400, 0x100401, 0x100001, 0x2000400, 0x2000001, 0x2100000, 0x2100400, 0x100001, 0x2100000, 0x400, 0x401, 0x2100401, 0x100400, 0x1, 0x2000000, 0x100400, 0x2000000, 0x100400, 0x100000, 0x2000401, 0x2000401, 0x2100001, 0x2100001, 0x1, 0x100001, 0x2000000, 0x2000400, 0x100000, 0x2100400, 0x401, 0x100401, 0x2100400, 0x401, 0x2000001, 0x2100401, 0x2100000, 0x100400, 0x0, 0x1, 0x2100401, 0x0, 0x100401, 0x2100000, 0x400, 0x2000001, 0x2000400, 0x400, 0x100001];
    /**
     * Pre-permuted S-box8
     *
     * @var array
     * @access private
     */
    protected static $sbox8 = [0x8000820, 0x800, 0x20000, 0x8020820, 0x8000000, 0x8000820, 0x20, 0x8000000, 0x20020, 0x8020000, 0x8020820, 0x20800, 0x8020800, 0x20820, 0x800, 0x20, 0x8020000, 0x8000020, 0x8000800, 0x820, 0x20800, 0x20020, 0x8020020, 0x8020800, 0x820, 0x0, 0x0, 0x8020020, 0x8000020, 0x8000800, 0x20820, 0x20000, 0x20820, 0x20000, 0x8020800, 0x800, 0x20, 0x8020020, 0x800, 0x20820, 0x8000800, 0x20, 0x8000020, 0x8020000, 0x8020020, 0x8000000, 0x20000, 0x8000820, 0x0, 0x8020820, 0x20020, 0x8000020, 0x8020000, 0x8000800, 0x8000820, 0x0, 0x8020820, 0x20800, 0x20800, 0x820, 0x820, 0x20020, 0x8000000, 0x8020800];
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws BadModeException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new BadModeException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        if ($this->key_length_max == 8) {
            if ($engine == self::ENGINE_OPENSSL) {
                $this->cipher_name_openssl_ecb = 'des-ecb';
                $this->cipher_name_openssl = 'des-' . $this->openssl_translate_mode();
            }
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Sets the key.
     *
     * Keys must be 64-bits long or 8 bytes long.
     *
     * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setKey()
     * @access public
     * @param string $key
     */
    public function setKey($key)
    {
        if (!$this instanceof TripleDES && strlen($key) != 8) {
            throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of size 8 are supported');
        }
        // Sets the key
        parent::setKey($key);
    }
    /**
     * Encrypts a block
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encryptBlock()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see self::encrypt()
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        return $this->processBlock($in, self::ENCRYPT);
    }
    /**
     * Decrypts a block
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decryptBlock()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @see self::decrypt()
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        return $this->processBlock($in, self::DECRYPT);
    }
    /**
    * Encrypts or decrypts a 64-bit block
    *
    * $mode should be either self::ENCRYPT or self::DECRYPT.  See
    {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
    idea of what this function does.
    *
    * @see self::encryptBlock()
    * @see self::decryptBlock()
    * @access private
    * @param string $block
    * @param int $mode
    * @return string
    */
    private function processBlock($block, $mode)
    {
        static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
        if (!$sbox1) {
            $sbox1 = array_map('intval', self::$sbox1);
            $sbox2 = array_map('intval', self::$sbox2);
            $sbox3 = array_map('intval', self::$sbox3);
            $sbox4 = array_map('intval', self::$sbox4);
            $sbox5 = array_map('intval', self::$sbox5);
            $sbox6 = array_map('intval', self::$sbox6);
            $sbox7 = array_map('intval', self::$sbox7);
            $sbox8 = array_map('intval', self::$sbox8);
            /* Merge $shuffle with $[inv]ipmap */
            for ($i = 0; $i < 256; ++$i) {
                $shuffleip[] = self::$shuffle[self::$ipmap[$i]];
                $shuffleinvip[] = self::$shuffle[self::$invipmap[$i]];
            }
        }
        $keys = $this->keys[$mode];
        $ki = -1;
        // Do the initial IP permutation.
        $t = unpack('Nl/Nr', $block);
        list($l, $r) = [$t['l'], $t['r']];
        $block = $shuffleip[$r & 0xff] & "\x80\x80\x80\x80\x80\x80\x80\x80" | $shuffleip[$r >> 8 & 0xff] & "@@@@@@@@" | $shuffleip[$r >> 16 & 0xff] & "        " | $shuffleip[$r >> 24 & 0xff] & "\x10\x10\x10\x10\x10\x10\x10\x10" | $shuffleip[$l & 0xff] & "\x08\x08\x08\x08\x08\x08\x08\x08" | $shuffleip[$l >> 8 & 0xff] & "\x04\x04\x04\x04\x04\x04\x04\x04" | $shuffleip[$l >> 16 & 0xff] & "\x02\x02\x02\x02\x02\x02\x02\x02" | $shuffleip[$l >> 24 & 0xff] & "\x01\x01\x01\x01\x01\x01\x01\x01";
        // Extract L0 and R0.
        $t = unpack('Nl/Nr', $block);
        list($l, $r) = [$t['l'], $t['r']];
        for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
            // Perform the 16 steps.
            for ($i = 0; $i < 16; $i++) {
                // start of "the Feistel (F) function" - see the following URL:
                // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
                // Merge key schedule.
                $b1 = $r >> 3 & 0x1fffffff ^ $r << 29 ^ $keys[++$ki];
                $b2 = $r >> 31 & 0x1 ^ $r << 1 ^ $keys[++$ki];
                // S-box indexing.
                $t = $sbox1[$b1 >> 24 & 0x3f] ^ $sbox2[$b2 >> 24 & 0x3f] ^ $sbox3[$b1 >> 16 & 0x3f] ^ $sbox4[$b2 >> 16 & 0x3f] ^ $sbox5[$b1 >> 8 & 0x3f] ^ $sbox6[$b2 >> 8 & 0x3f] ^ $sbox7[$b1 & 0x3f] ^ $sbox8[$b2 & 0x3f] ^ $l;
                // end of "the Feistel (F) function"
                $l = $r;
                $r = $t;
            }
            // Last step should not permute L & R.
            $t = $l;
            $l = $r;
            $r = $t;
        }
        // Perform the inverse IP permutation.
        return $shuffleinvip[$r >> 24 & 0xff] & "\x80\x80\x80\x80\x80\x80\x80\x80" | $shuffleinvip[$l >> 24 & 0xff] & "@@@@@@@@" | $shuffleinvip[$r >> 16 & 0xff] & "        " | $shuffleinvip[$l >> 16 & 0xff] & "\x10\x10\x10\x10\x10\x10\x10\x10" | $shuffleinvip[$r >> 8 & 0xff] & "\x08\x08\x08\x08\x08\x08\x08\x08" | $shuffleinvip[$l >> 8 & 0xff] & "\x04\x04\x04\x04\x04\x04\x04\x04" | $shuffleinvip[$r & 0xff] & "\x02\x02\x02\x02\x02\x02\x02\x02" | $shuffleinvip[$l & 0xff] & "\x01\x01\x01\x01\x01\x01\x01\x01";
    }
    /**
     * Creates the key schedule
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
     * @access private
     */
    protected function setupKey()
    {
        if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->des_rounds === $this->kl['des_rounds']) {
            // already expanded
            return;
        }
        $this->kl = ['key' => $this->key, 'des_rounds' => $this->des_rounds];
        static $shifts = [
            // number of key bits shifted per round
            1,
            1,
            2,
            2,
            2,
            2,
            2,
            2,
            1,
            2,
            2,
            2,
            2,
            2,
            2,
            1,
        ];
        static $pc1map = [0x0, 0x0, 0x8, 0x8, 0x4, 0x4, 0xc, 0xc, 0x2, 0x2, 0xa, 0xa, 0x6, 0x6, 0xe, 0xe, 0x10, 0x10, 0x18, 0x18, 0x14, 0x14, 0x1c, 0x1c, 0x12, 0x12, 0x1a, 0x1a, 0x16, 0x16, 0x1e, 0x1e, 0x20, 0x20, 0x28, 0x28, 0x24, 0x24, 0x2c, 0x2c, 0x22, 0x22, 0x2a, 0x2a, 0x26, 0x26, 0x2e, 0x2e, 0x30, 0x30, 0x38, 0x38, 0x34, 0x34, 0x3c, 0x3c, 0x32, 0x32, 0x3a, 0x3a, 0x36, 0x36, 0x3e, 0x3e, 0x40, 0x40, 0x48, 0x48, 0x44, 0x44, 0x4c, 0x4c, 0x42, 0x42, 0x4a, 0x4a, 0x46, 0x46, 0x4e, 0x4e, 0x50, 0x50, 0x58, 0x58, 0x54, 0x54, 0x5c, 0x5c, 0x52, 0x52, 0x5a, 0x5a, 0x56, 0x56, 0x5e, 0x5e, 0x60, 0x60, 0x68, 0x68, 0x64, 0x64, 0x6c, 0x6c, 0x62, 0x62, 0x6a, 0x6a, 0x66, 0x66, 0x6e, 0x6e, 0x70, 0x70, 0x78, 0x78, 0x74, 0x74, 0x7c, 0x7c, 0x72, 0x72, 0x7a, 0x7a, 0x76, 0x76, 0x7e, 0x7e, 0x80, 0x80, 0x88, 0x88, 0x84, 0x84, 0x8c, 0x8c, 0x82, 0x82, 0x8a, 0x8a, 0x86, 0x86, 0x8e, 0x8e, 0x90, 0x90, 0x98, 0x98, 0x94, 0x94, 0x9c, 0x9c, 0x92, 0x92, 0x9a, 0x9a, 0x96, 0x96, 0x9e, 0x9e, 0xa0, 0xa0, 0xa8, 0xa8, 0xa4, 0xa4, 0xac, 0xac, 0xa2, 0xa2, 0xaa, 0xaa, 0xa6, 0xa6, 0xae, 0xae, 0xb0, 0xb0, 0xb8, 0xb8, 0xb4, 0xb4, 0xbc, 0xbc, 0xb2, 0xb2, 0xba, 0xba, 0xb6, 0xb6, 0xbe, 0xbe, 0xc0, 0xc0, 0xc8, 0xc8, 0xc4, 0xc4, 0xcc, 0xcc, 0xc2, 0xc2, 0xca, 0xca, 0xc6, 0xc6, 0xce, 0xce, 0xd0, 0xd0, 0xd8, 0xd8, 0xd4, 0xd4, 0xdc, 0xdc, 0xd2, 0xd2, 0xda, 0xda, 0xd6, 0xd6, 0xde, 0xde, 0xe0, 0xe0, 0xe8, 0xe8, 0xe4, 0xe4, 0xec, 0xec, 0xe2, 0xe2, 0xea, 0xea, 0xe6, 0xe6, 0xee, 0xee, 0xf0, 0xf0, 0xf8, 0xf8, 0xf4, 0xf4, 0xfc, 0xfc, 0xf2, 0xf2, 0xfa, 0xfa, 0xf6, 0xf6, 0xfe, 0xfe];
        // Mapping tables for the PC-2 transformation.
        static $pc2mapc1 = [0x0, 0x400, 0x200000, 0x200400, 0x1, 0x401, 0x200001, 0x200401, 0x2000000, 0x2000400, 0x2200000, 0x2200400, 0x2000001, 0x2000401, 0x2200001, 0x2200401];
        static $pc2mapc2 = [0x0, 0x800, 0x8000000, 0x8000800, 0x10000, 0x10800, 0x8010000, 0x8010800, 0x0, 0x800, 0x8000000, 0x8000800, 0x10000, 0x10800, 0x8010000, 0x8010800, 0x100, 0x900, 0x8000100, 0x8000900, 0x10100, 0x10900, 0x8010100, 0x8010900, 0x100, 0x900, 0x8000100, 0x8000900, 0x10100, 0x10900, 0x8010100, 0x8010900, 0x10, 0x810, 0x8000010, 0x8000810, 0x10010, 0x10810, 0x8010010, 0x8010810, 0x10, 0x810, 0x8000010, 0x8000810, 0x10010, 0x10810, 0x8010010, 0x8010810, 0x110, 0x910, 0x8000110, 0x8000910, 0x10110, 0x10910, 0x8010110, 0x8010910, 0x110, 0x910, 0x8000110, 0x8000910, 0x10110, 0x10910, 0x8010110, 0x8010910, 0x40000, 0x40800, 0x8040000, 0x8040800, 0x50000, 0x50800, 0x8050000, 0x8050800, 0x40000, 0x40800, 0x8040000, 0x8040800, 0x50000, 0x50800, 0x8050000, 0x8050800, 0x40100, 0x40900, 0x8040100, 0x8040900, 0x50100, 0x50900, 0x8050100, 0x8050900, 0x40100, 0x40900, 0x8040100, 0x8040900, 0x50100, 0x50900, 0x8050100, 0x8050900, 0x40010, 0x40810, 0x8040010, 0x8040810, 0x50010, 0x50810, 0x8050010, 0x8050810, 0x40010, 0x40810, 0x8040010, 0x8040810, 0x50010, 0x50810, 0x8050010, 0x8050810, 0x40110, 0x40910, 0x8040110, 0x8040910, 0x50110, 0x50910, 0x8050110, 0x8050910, 0x40110, 0x40910, 0x8040110, 0x8040910, 0x50110, 0x50910, 0x8050110, 0x8050910, 0x1000000, 0x1000800, 0x9000000, 0x9000800, 0x1010000, 0x1010800, 0x9010000, 0x9010800, 0x1000000, 0x1000800, 0x9000000, 0x9000800, 0x1010000, 0x1010800, 0x9010000, 0x9010800, 0x1000100, 0x1000900, 0x9000100, 0x9000900, 0x1010100, 0x1010900, 0x9010100, 0x9010900, 0x1000100, 0x1000900, 0x9000100, 0x9000900, 0x1010100, 0x1010900, 0x9010100, 0x9010900, 0x1000010, 0x1000810, 0x9000010, 0x9000810, 0x1010010, 0x1010810, 0x9010010, 0x9010810, 0x1000010, 0x1000810, 0x9000010, 0x9000810, 0x1010010, 0x1010810, 0x9010010, 0x9010810, 0x1000110, 0x1000910, 0x9000110, 0x9000910, 0x1010110, 0x1010910, 0x9010110, 0x9010910, 0x1000110, 0x1000910, 0x9000110, 0x9000910, 0x1010110, 0x1010910, 0x9010110, 0x9010910, 0x1040000, 0x1040800, 0x9040000, 0x9040800, 0x1050000, 0x1050800, 0x9050000, 0x9050800, 0x1040000, 0x1040800, 0x9040000, 0x9040800, 0x1050000, 0x1050800, 0x9050000, 0x9050800, 0x1040100, 0x1040900, 0x9040100, 0x9040900, 0x1050100, 0x1050900, 0x9050100, 0x9050900, 0x1040100, 0x1040900, 0x9040100, 0x9040900, 0x1050100, 0x1050900, 0x9050100, 0x9050900, 0x1040010, 0x1040810, 0x9040010, 0x9040810, 0x1050010, 0x1050810, 0x9050010, 0x9050810, 0x1040010, 0x1040810, 0x9040010, 0x9040810, 0x1050010, 0x1050810, 0x9050010, 0x9050810, 0x1040110, 0x1040910, 0x9040110, 0x9040910, 0x1050110, 0x1050910, 0x9050110, 0x9050910, 0x1040110, 0x1040910, 0x9040110, 0x9040910, 0x1050110, 0x1050910, 0x9050110, 0x9050910];
        static $pc2mapc3 = [0x0, 0x4, 0x1000, 0x1004, 0x0, 0x4, 0x1000, 0x1004, 0x10000000, 0x10000004, 0x10001000, 0x10001004, 0x10000000, 0x10000004, 0x10001000, 0x10001004, 0x20, 0x24, 0x1020, 0x1024, 0x20, 0x24, 0x1020, 0x1024, 0x10000020, 0x10000024, 0x10001020, 0x10001024, 0x10000020, 0x10000024, 0x10001020, 0x10001024, 0x80000, 0x80004, 0x81000, 0x81004, 0x80000, 0x80004, 0x81000, 0x81004, 0x10080000, 0x10080004, 0x10081000, 0x10081004, 0x10080000, 0x10080004, 0x10081000, 0x10081004, 0x80020, 0x80024, 0x81020, 0x81024, 0x80020, 0x80024, 0x81020, 0x81024, 0x10080020, 0x10080024, 0x10081020, 0x10081024, 0x10080020, 0x10080024, 0x10081020, 0x10081024, 0x20000000, 0x20000004, 0x20001000, 0x20001004, 0x20000000, 0x20000004, 0x20001000, 0x20001004, 0x30000000, 0x30000004, 0x30001000, 0x30001004, 0x30000000, 0x30000004, 0x30001000, 0x30001004, 0x20000020, 0x20000024, 0x20001020, 0x20001024, 0x20000020, 0x20000024, 0x20001020, 0x20001024, 0x30000020, 0x30000024, 0x30001020, 0x30001024, 0x30000020, 0x30000024, 0x30001020, 0x30001024, 0x20080000, 0x20080004, 0x20081000, 0x20081004, 0x20080000, 0x20080004, 0x20081000, 0x20081004, 0x30080000, 0x30080004, 0x30081000, 0x30081004, 0x30080000, 0x30080004, 0x30081000, 0x30081004, 0x20080020, 0x20080024, 0x20081020, 0x20081024, 0x20080020, 0x20080024, 0x20081020, 0x20081024, 0x30080020, 0x30080024, 0x30081020, 0x30081024, 0x30080020, 0x30080024, 0x30081020, 0x30081024, 0x2, 0x6, 0x1002, 0x1006, 0x2, 0x6, 0x1002, 0x1006, 0x10000002, 0x10000006, 0x10001002, 0x10001006, 0x10000002, 0x10000006, 0x10001002, 0x10001006, 0x22, 0x26, 0x1022, 0x1026, 0x22, 0x26, 0x1022, 0x1026, 0x10000022, 0x10000026, 0x10001022, 0x10001026, 0x10000022, 0x10000026, 0x10001022, 0x10001026, 0x80002, 0x80006, 0x81002, 0x81006, 0x80002, 0x80006, 0x81002, 0x81006, 0x10080002, 0x10080006, 0x10081002, 0x10081006, 0x10080002, 0x10080006, 0x10081002, 0x10081006, 0x80022, 0x80026, 0x81022, 0x81026, 0x80022, 0x80026, 0x81022, 0x81026, 0x10080022, 0x10080026, 0x10081022, 0x10081026, 0x10080022, 0x10080026, 0x10081022, 0x10081026, 0x20000002, 0x20000006, 0x20001002, 0x20001006, 0x20000002, 0x20000006, 0x20001002, 0x20001006, 0x30000002, 0x30000006, 0x30001002, 0x30001006, 0x30000002, 0x30000006, 0x30001002, 0x30001006, 0x20000022, 0x20000026, 0x20001022, 0x20001026, 0x20000022, 0x20000026, 0x20001022, 0x20001026, 0x30000022, 0x30000026, 0x30001022, 0x30001026, 0x30000022, 0x30000026, 0x30001022, 0x30001026, 0x20080002, 0x20080006, 0x20081002, 0x20081006, 0x20080002, 0x20080006, 0x20081002, 0x20081006, 0x30080002, 0x30080006, 0x30081002, 0x30081006, 0x30080002, 0x30080006, 0x30081002, 0x30081006, 0x20080022, 0x20080026, 0x20081022, 0x20081026, 0x20080022, 0x20080026, 0x20081022, 0x20081026, 0x30080022, 0x30080026, 0x30081022, 0x30081026, 0x30080022, 0x30080026, 0x30081022, 0x30081026];
        static $pc2mapc4 = [0x0, 0x100000, 0x8, 0x100008, 0x200, 0x100200, 0x208, 0x100208, 0x0, 0x100000, 0x8, 0x100008, 0x200, 0x100200, 0x208, 0x100208, 0x4000000, 0x4100000, 0x4000008, 0x4100008, 0x4000200, 0x4100200, 0x4000208, 0x4100208, 0x4000000, 0x4100000, 0x4000008, 0x4100008, 0x4000200, 0x4100200, 0x4000208, 0x4100208, 0x2000, 0x102000, 0x2008, 0x102008, 0x2200, 0x102200, 0x2208, 0x102208, 0x2000, 0x102000, 0x2008, 0x102008, 0x2200, 0x102200, 0x2208, 0x102208, 0x4002000, 0x4102000, 0x4002008, 0x4102008, 0x4002200, 0x4102200, 0x4002208, 0x4102208, 0x4002000, 0x4102000, 0x4002008, 0x4102008, 0x4002200, 0x4102200, 0x4002208, 0x4102208, 0x0, 0x100000, 0x8, 0x100008, 0x200, 0x100200, 0x208, 0x100208, 0x0, 0x100000, 0x8, 0x100008, 0x200, 0x100200, 0x208, 0x100208, 0x4000000, 0x4100000, 0x4000008, 0x4100008, 0x4000200, 0x4100200, 0x4000208, 0x4100208, 0x4000000, 0x4100000, 0x4000008, 0x4100008, 0x4000200, 0x4100200, 0x4000208, 0x4100208, 0x2000, 0x102000, 0x2008, 0x102008, 0x2200, 0x102200, 0x2208, 0x102208, 0x2000, 0x102000, 0x2008, 0x102008, 0x2200, 0x102200, 0x2208, 0x102208, 0x4002000, 0x4102000, 0x4002008, 0x4102008, 0x4002200, 0x4102200, 0x4002208, 0x4102208, 0x4002000, 0x4102000, 0x4002008, 0x4102008, 0x4002200, 0x4102200, 0x4002208, 0x4102208, 0x20000, 0x120000, 0x20008, 0x120008, 0x20200, 0x120200, 0x20208, 0x120208, 0x20000, 0x120000, 0x20008, 0x120008, 0x20200, 0x120200, 0x20208, 0x120208, 0x4020000, 0x4120000, 0x4020008, 0x4120008, 0x4020200, 0x4120200, 0x4020208, 0x4120208, 0x4020000, 0x4120000, 0x4020008, 0x4120008, 0x4020200, 0x4120200, 0x4020208, 0x4120208, 0x22000, 0x122000, 0x22008, 0x122008, 0x22200, 0x122200, 0x22208, 0x122208, 0x22000, 0x122000, 0x22008, 0x122008, 0x22200, 0x122200, 0x22208, 0x122208, 0x4022000, 0x4122000, 0x4022008, 0x4122008, 0x4022200, 0x4122200, 0x4022208, 0x4122208, 0x4022000, 0x4122000, 0x4022008, 0x4122008, 0x4022200, 0x4122200, 0x4022208, 0x4122208, 0x20000, 0x120000, 0x20008, 0x120008, 0x20200, 0x120200, 0x20208, 0x120208, 0x20000, 0x120000, 0x20008, 0x120008, 0x20200, 0x120200, 0x20208, 0x120208, 0x4020000, 0x4120000, 0x4020008, 0x4120008, 0x4020200, 0x4120200, 0x4020208, 0x4120208, 0x4020000, 0x4120000, 0x4020008, 0x4120008, 0x4020200, 0x4120200, 0x4020208, 0x4120208, 0x22000, 0x122000, 0x22008, 0x122008, 0x22200, 0x122200, 0x22208, 0x122208, 0x22000, 0x122000, 0x22008, 0x122008, 0x22200, 0x122200, 0x22208, 0x122208, 0x4022000, 0x4122000, 0x4022008, 0x4122008, 0x4022200, 0x4122200, 0x4022208, 0x4122208, 0x4022000, 0x4122000, 0x4022008, 0x4122008, 0x4022200, 0x4122200, 0x4022208, 0x4122208];
        static $pc2mapd1 = [0x0, 0x1, 0x8000000, 0x8000001, 0x200000, 0x200001, 0x8200000, 0x8200001, 0x2, 0x3, 0x8000002, 0x8000003, 0x200002, 0x200003, 0x8200002, 0x8200003];
        static $pc2mapd2 = [0x0, 0x100000, 0x800, 0x100800, 0x0, 0x100000, 0x800, 0x100800, 0x4000000, 0x4100000, 0x4000800, 0x4100800, 0x4000000, 0x4100000, 0x4000800, 0x4100800, 0x4, 0x100004, 0x804, 0x100804, 0x4, 0x100004, 0x804, 0x100804, 0x4000004, 0x4100004, 0x4000804, 0x4100804, 0x4000004, 0x4100004, 0x4000804, 0x4100804, 0x0, 0x100000, 0x800, 0x100800, 0x0, 0x100000, 0x800, 0x100800, 0x4000000, 0x4100000, 0x4000800, 0x4100800, 0x4000000, 0x4100000, 0x4000800, 0x4100800, 0x4, 0x100004, 0x804, 0x100804, 0x4, 0x100004, 0x804, 0x100804, 0x4000004, 0x4100004, 0x4000804, 0x4100804, 0x4000004, 0x4100004, 0x4000804, 0x4100804, 0x200, 0x100200, 0xa00, 0x100a00, 0x200, 0x100200, 0xa00, 0x100a00, 0x4000200, 0x4100200, 0x4000a00, 0x4100a00, 0x4000200, 0x4100200, 0x4000a00, 0x4100a00, 0x204, 0x100204, 0xa04, 0x100a04, 0x204, 0x100204, 0xa04, 0x100a04, 0x4000204, 0x4100204, 0x4000a04, 0x4100a04, 0x4000204, 0x4100204, 0x4000a04, 0x4100a04, 0x200, 0x100200, 0xa00, 0x100a00, 0x200, 0x100200, 0xa00, 0x100a00, 0x4000200, 0x4100200, 0x4000a00, 0x4100a00, 0x4000200, 0x4100200, 0x4000a00, 0x4100a00, 0x204, 0x100204, 0xa04, 0x100a04, 0x204, 0x100204, 0xa04, 0x100a04, 0x4000204, 0x4100204, 0x4000a04, 0x4100a04, 0x4000204, 0x4100204, 0x4000a04, 0x4100a04, 0x20000, 0x120000, 0x20800, 0x120800, 0x20000, 0x120000, 0x20800, 0x120800, 0x4020000, 0x4120000, 0x4020800, 0x4120800, 0x4020000, 0x4120000, 0x4020800, 0x4120800, 0x20004, 0x120004, 0x20804, 0x120804, 0x20004, 0x120004, 0x20804, 0x120804, 0x4020004, 0x4120004, 0x4020804, 0x4120804, 0x4020004, 0x4120004, 0x4020804, 0x4120804, 0x20000, 0x120000, 0x20800, 0x120800, 0x20000, 0x120000, 0x20800, 0x120800, 0x4020000, 0x4120000, 0x4020800, 0x4120800, 0x4020000, 0x4120000, 0x4020800, 0x4120800, 0x20004, 0x120004, 0x20804, 0x120804, 0x20004, 0x120004, 0x20804, 0x120804, 0x4020004, 0x4120004, 0x4020804, 0x4120804, 0x4020004, 0x4120004, 0x4020804, 0x4120804, 0x20200, 0x120200, 0x20a00, 0x120a00, 0x20200, 0x120200, 0x20a00, 0x120a00, 0x4020200, 0x4120200, 0x4020a00, 0x4120a00, 0x4020200, 0x4120200, 0x4020a00, 0x4120a00, 0x20204, 0x120204, 0x20a04, 0x120a04, 0x20204, 0x120204, 0x20a04, 0x120a04, 0x4020204, 0x4120204, 0x4020a04, 0x4120a04, 0x4020204, 0x4120204, 0x4020a04, 0x4120a04, 0x20200, 0x120200, 0x20a00, 0x120a00, 0x20200, 0x120200, 0x20a00, 0x120a00, 0x4020200, 0x4120200, 0x4020a00, 0x4120a00, 0x4020200, 0x4120200, 0x4020a00, 0x4120a00, 0x20204, 0x120204, 0x20a04, 0x120a04, 0x20204, 0x120204, 0x20a04, 0x120a04, 0x4020204, 0x4120204, 0x4020a04, 0x4120a04, 0x4020204, 0x4120204, 0x4020a04, 0x4120a04];
        static $pc2mapd3 = [0x0, 0x10000, 0x2000000, 0x2010000, 0x20, 0x10020, 0x2000020, 0x2010020, 0x40000, 0x50000, 0x2040000, 0x2050000, 0x40020, 0x50020, 0x2040020, 0x2050020, 0x2000, 0x12000, 0x2002000, 0x2012000, 0x2020, 0x12020, 0x2002020, 0x2012020, 0x42000, 0x52000, 0x2042000, 0x2052000, 0x42020, 0x52020, 0x2042020, 0x2052020, 0x0, 0x10000, 0x2000000, 0x2010000, 0x20, 0x10020, 0x2000020, 0x2010020, 0x40000, 0x50000, 0x2040000, 0x2050000, 0x40020, 0x50020, 0x2040020, 0x2050020, 0x2000, 0x12000, 0x2002000, 0x2012000, 0x2020, 0x12020, 0x2002020, 0x2012020, 0x42000, 0x52000, 0x2042000, 0x2052000, 0x42020, 0x52020, 0x2042020, 0x2052020, 0x10, 0x10010, 0x2000010, 0x2010010, 0x30, 0x10030, 0x2000030, 0x2010030, 0x40010, 0x50010, 0x2040010, 0x2050010, 0x40030, 0x50030, 0x2040030, 0x2050030, 0x2010, 0x12010, 0x2002010, 0x2012010, 0x2030, 0x12030, 0x2002030, 0x2012030, 0x42010, 0x52010, 0x2042010, 0x2052010, 0x42030, 0x52030, 0x2042030, 0x2052030, 0x10, 0x10010, 0x2000010, 0x2010010, 0x30, 0x10030, 0x2000030, 0x2010030, 0x40010, 0x50010, 0x2040010, 0x2050010, 0x40030, 0x50030, 0x2040030, 0x2050030, 0x2010, 0x12010, 0x2002010, 0x2012010, 0x2030, 0x12030, 0x2002030, 0x2012030, 0x42010, 0x52010, 0x2042010, 0x2052010, 0x42030, 0x52030, 0x2042030, 0x2052030, 0x20000000, 0x20010000, 0x22000000, 0x22010000, 0x20000020, 0x20010020, 0x22000020, 0x22010020, 0x20040000, 0x20050000, 0x22040000, 0x22050000, 0x20040020, 0x20050020, 0x22040020, 0x22050020, 0x20002000, 0x20012000, 0x22002000, 0x22012000, 0x20002020, 0x20012020, 0x22002020, 0x22012020, 0x20042000, 0x20052000, 0x22042000, 0x22052000, 0x20042020, 0x20052020, 0x22042020, 0x22052020, 0x20000000, 0x20010000, 0x22000000, 0x22010000, 0x20000020, 0x20010020, 0x22000020, 0x22010020, 0x20040000, 0x20050000, 0x22040000, 0x22050000, 0x20040020, 0x20050020, 0x22040020, 0x22050020, 0x20002000, 0x20012000, 0x22002000, 0x22012000, 0x20002020, 0x20012020, 0x22002020, 0x22012020, 0x20042000, 0x20052000, 0x22042000, 0x22052000, 0x20042020, 0x20052020, 0x22042020, 0x22052020, 0x20000010, 0x20010010, 0x22000010, 0x22010010, 0x20000030, 0x20010030, 0x22000030, 0x22010030, 0x20040010, 0x20050010, 0x22040010, 0x22050010, 0x20040030, 0x20050030, 0x22040030, 0x22050030, 0x20002010, 0x20012010, 0x22002010, 0x22012010, 0x20002030, 0x20012030, 0x22002030, 0x22012030, 0x20042010, 0x20052010, 0x22042010, 0x22052010, 0x20042030, 0x20052030, 0x22042030, 0x22052030, 0x20000010, 0x20010010, 0x22000010, 0x22010010, 0x20000030, 0x20010030, 0x22000030, 0x22010030, 0x20040010, 0x20050010, 0x22040010, 0x22050010, 0x20040030, 0x20050030, 0x22040030, 0x22050030, 0x20002010, 0x20012010, 0x22002010, 0x22012010, 0x20002030, 0x20012030, 0x22002030, 0x22012030, 0x20042010, 0x20052010, 0x22042010, 0x22052010, 0x20042030, 0x20052030, 0x22042030, 0x22052030];
        static $pc2mapd4 = [0x0, 0x400, 0x1000000, 0x1000400, 0x0, 0x400, 0x1000000, 0x1000400, 0x100, 0x500, 0x1000100, 0x1000500, 0x100, 0x500, 0x1000100, 0x1000500, 0x10000000, 0x10000400, 0x11000000, 0x11000400, 0x10000000, 0x10000400, 0x11000000, 0x11000400, 0x10000100, 0x10000500, 0x11000100, 0x11000500, 0x10000100, 0x10000500, 0x11000100, 0x11000500, 0x80000, 0x80400, 0x1080000, 0x1080400, 0x80000, 0x80400, 0x1080000, 0x1080400, 0x80100, 0x80500, 0x1080100, 0x1080500, 0x80100, 0x80500, 0x1080100, 0x1080500, 0x10080000, 0x10080400, 0x11080000, 0x11080400, 0x10080000, 0x10080400, 0x11080000, 0x11080400, 0x10080100, 0x10080500, 0x11080100, 0x11080500, 0x10080100, 0x10080500, 0x11080100, 0x11080500, 0x8, 0x408, 0x1000008, 0x1000408, 0x8, 0x408, 0x1000008, 0x1000408, 0x108, 0x508, 0x1000108, 0x1000508, 0x108, 0x508, 0x1000108, 0x1000508, 0x10000008, 0x10000408, 0x11000008, 0x11000408, 0x10000008, 0x10000408, 0x11000008, 0x11000408, 0x10000108, 0x10000508, 0x11000108, 0x11000508, 0x10000108, 0x10000508, 0x11000108, 0x11000508, 0x80008, 0x80408, 0x1080008, 0x1080408, 0x80008, 0x80408, 0x1080008, 0x1080408, 0x80108, 0x80508, 0x1080108, 0x1080508, 0x80108, 0x80508, 0x1080108, 0x1080508, 0x10080008, 0x10080408, 0x11080008, 0x11080408, 0x10080008, 0x10080408, 0x11080008, 0x11080408, 0x10080108, 0x10080508, 0x11080108, 0x11080508, 0x10080108, 0x10080508, 0x11080108, 0x11080508, 0x1000, 0x1400, 0x1001000, 0x1001400, 0x1000, 0x1400, 0x1001000, 0x1001400, 0x1100, 0x1500, 0x1001100, 0x1001500, 0x1100, 0x1500, 0x1001100, 0x1001500, 0x10001000, 0x10001400, 0x11001000, 0x11001400, 0x10001000, 0x10001400, 0x11001000, 0x11001400, 0x10001100, 0x10001500, 0x11001100, 0x11001500, 0x10001100, 0x10001500, 0x11001100, 0x11001500, 0x81000, 0x81400, 0x1081000, 0x1081400, 0x81000, 0x81400, 0x1081000, 0x1081400, 0x81100, 0x81500, 0x1081100, 0x1081500, 0x81100, 0x81500, 0x1081100, 0x1081500, 0x10081000, 0x10081400, 0x11081000, 0x11081400, 0x10081000, 0x10081400, 0x11081000, 0x11081400, 0x10081100, 0x10081500, 0x11081100, 0x11081500, 0x10081100, 0x10081500, 0x11081100, 0x11081500, 0x1008, 0x1408, 0x1001008, 0x1001408, 0x1008, 0x1408, 0x1001008, 0x1001408, 0x1108, 0x1508, 0x1001108, 0x1001508, 0x1108, 0x1508, 0x1001108, 0x1001508, 0x10001008, 0x10001408, 0x11001008, 0x11001408, 0x10001008, 0x10001408, 0x11001008, 0x11001408, 0x10001108, 0x10001508, 0x11001108, 0x11001508, 0x10001108, 0x10001508, 0x11001108, 0x11001508, 0x81008, 0x81408, 0x1081008, 0x1081408, 0x81008, 0x81408, 0x1081008, 0x1081408, 0x81108, 0x81508, 0x1081108, 0x1081508, 0x81108, 0x81508, 0x1081108, 0x1081508, 0x10081008, 0x10081408, 0x11081008, 0x11081408, 0x10081008, 0x10081408, 0x11081008, 0x11081408, 0x10081108, 0x10081508, 0x11081108, 0x11081508, 0x10081108, 0x10081508, 0x11081108, 0x11081508];
        $keys = [];
        for ($des_round = 0; $des_round < $this->des_rounds; ++$des_round) {
            // pad the key and remove extra characters as appropriate.
            $key = str_pad(\Phabel\Target\Php80\Polyfill::substr($this->key, $des_round * 8, 8), 8, "\x00");
            // Perform the PC/1 transformation and compute C and D.
            $t = unpack('Nl/Nr', $key);
            list($l, $r) = [$t['l'], $t['r']];
            $key = self::$shuffle[$pc1map[$r & 0xff]] & "\x80\x80\x80\x80\x80\x80\x80\x00" | self::$shuffle[$pc1map[$r >> 8 & 0xff]] & "@@@@@@@\x00" | self::$shuffle[$pc1map[$r >> 16 & 0xff]] & "       \x00" | self::$shuffle[$pc1map[$r >> 24 & 0xff]] & "\x10\x10\x10\x10\x10\x10\x10\x00" | self::$shuffle[$pc1map[$l & 0xff]] & "\x08\x08\x08\x08\x08\x08\x08\x00" | self::$shuffle[$pc1map[$l >> 8 & 0xff]] & "\x04\x04\x04\x04\x04\x04\x04\x00" | self::$shuffle[$pc1map[$l >> 16 & 0xff]] & "\x02\x02\x02\x02\x02\x02\x02\x00" | self::$shuffle[$pc1map[$l >> 24 & 0xff]] & "\x01\x01\x01\x01\x01\x01\x01\x00";
            $key = unpack('Nc/Nd', $key);
            $c = $key['c'] >> 4 & 0xfffffff;
            $d = $key['d'] >> 4 & 0xffffff0 | $key['c'] & 0xf;
            $keys[$des_round] = [self::ENCRYPT => [], self::DECRYPT => array_fill(0, 32, 0)];
            for ($i = 0, $ki = 31; $i < 16; ++$i, $ki -= 2) {
                $c <<= $shifts[$i];
                $c = ($c | $c >> 28) & 0xfffffff;
                $d <<= $shifts[$i];
                $d = ($d | $d >> 28) & 0xfffffff;
                // Perform the PC-2 transformation.
                $cp = $pc2mapc1[$c >> 24] | $pc2mapc2[$c >> 16 & 0xff] | $pc2mapc3[$c >> 8 & 0xff] | $pc2mapc4[$c & 0xff];
                $dp = $pc2mapd1[$d >> 24] | $pc2mapd2[$d >> 16 & 0xff] | $pc2mapd3[$d >> 8 & 0xff] | $pc2mapd4[$d & 0xff];
                // Reorder: odd bytes/even bytes. Push the result in key schedule.
                $val1 = $cp & 0xff000000 | $cp << 8 & 0xff0000 | $dp >> 16 & 0xff00 | $dp >> 8 & 0xff;
                $val2 = $cp << 8 & 0xff000000 | $cp << 16 & 0xff0000 | $dp >> 8 & 0xff00 | $dp & 0xff;
                $keys[$des_round][self::ENCRYPT][] = $val1;
                $keys[$des_round][self::DECRYPT][$ki - 1] = $val1;
                $keys[$des_round][self::ENCRYPT][] = $val2;
                $keys[$des_round][self::DECRYPT][$ki] = $val2;
            }
        }
        switch ($this->des_rounds) {
            case 3:
                // 3DES keys
                $this->keys = [self::ENCRYPT => array_merge($keys[0][self::ENCRYPT], $keys[1][self::DECRYPT], $keys[2][self::ENCRYPT]), self::DECRYPT => array_merge($keys[2][self::DECRYPT], $keys[1][self::ENCRYPT], $keys[0][self::DECRYPT])];
                break;
            // case 1: // DES keys
            default:
                $this->keys = [self::ENCRYPT => $keys[0][self::ENCRYPT], self::DECRYPT => $keys[0][self::DECRYPT]];
        }
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        // Engine configuration for:
        // -  DES ($des_rounds == 1) or
        // - 3DES ($des_rounds == 3)
        $des_rounds = $this->des_rounds;
        $init_crypt = 'static $sbox1, $sbox2, $sbox3, $sbox4, $sbox5, $sbox6, $sbox7, $sbox8, $shuffleip, $shuffleinvip;
            if (!$sbox1) {
                $sbox1 = array_map("intval", self::$sbox1);
                $sbox2 = array_map("intval", self::$sbox2);
                $sbox3 = array_map("intval", self::$sbox3);
                $sbox4 = array_map("intval", self::$sbox4);
                $sbox5 = array_map("intval", self::$sbox5);
                $sbox6 = array_map("intval", self::$sbox6);
                $sbox7 = array_map("intval", self::$sbox7);
                $sbox8 = array_map("intval", self::$sbox8);
                for ($i = 0; $i < 256; ++$i) {
                    $shuffleip[]    =  self::$shuffle[self::$ipmap[$i]];
                    $shuffleinvip[] =  self::$shuffle[self::$invipmap[$i]];
                }
            }
        ';
        $k = [self::ENCRYPT => $this->keys[self::ENCRYPT], self::DECRYPT => $this->keys[self::DECRYPT]];
        $init_encrypt = '';
        $init_decrypt = '';
        // Creating code for en- and decryption.
        $crypt_block = [];
        foreach ([self::ENCRYPT, self::DECRYPT] as $c) {
            /* Do the initial IP permutation. */
            $crypt_block[$c] = '
                $in = unpack("N*", $in);
                $l  = $in[1];
                $r  = $in[2];
                $in = unpack("N*",
                    ($shuffleip[ $r        & 0xFF] & "\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80") |
                    ($shuffleip[($r >>  8) & 0xFF] & "\\x40\\x40\\x40\\x40\\x40\\x40\\x40\\x40") |
                    ($shuffleip[($r >> 16) & 0xFF] & "\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20") |
                    ($shuffleip[($r >> 24) & 0xFF] & "\\x10\\x10\\x10\\x10\\x10\\x10\\x10\\x10") |
                    ($shuffleip[ $l        & 0xFF] & "\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08") |
                    ($shuffleip[($l >>  8) & 0xFF] & "\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04") |
                    ($shuffleip[($l >> 16) & 0xFF] & "\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02") |
                    ($shuffleip[($l >> 24) & 0xFF] & "\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01")
                );
                
                $l = $in[1];
                $r = $in[2];
            ';
            $l = '$l';
            $r = '$r';
            // Perform DES or 3DES.
            for ($ki = -1, $des_round = 0; $des_round < $des_rounds; ++$des_round) {
                // Perform the 16 steps.
                for ($i = 0; $i < 16; ++$i) {
                    // start of "the Feistel (F) function" - see the following URL:
                    // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
                    // Merge key schedule.
                    $crypt_block[$c] .= '
                        $b1 = ((' . $r . ' >>  3) & 0x1FFFFFFF)  ^ (' . $r . ' << 29) ^ ' . $k[$c][++$ki] . ';
                        $b2 = ((' . $r . ' >> 31) & 0x00000001)  ^ (' . $r . ' <<  1) ^ ' . $k[$c][++$ki] . ';' . $l . ' = $sbox1[($b1 >> 24) & 0x3F] ^ $sbox2[($b2 >> 24) & 0x3F] ^
                                 $sbox3[($b1 >> 16) & 0x3F] ^ $sbox4[($b2 >> 16) & 0x3F] ^
                                 $sbox5[($b1 >>  8) & 0x3F] ^ $sbox6[($b2 >>  8) & 0x3F] ^
                                 $sbox7[ $b1        & 0x3F] ^ $sbox8[ $b2        & 0x3F] ^ ' . $l . ';
                    ';
                    // end of "the Feistel (F) function"
                    // swap L & R
                    list($l, $r) = [$r, $l];
                }
                list($l, $r) = [$r, $l];
            }
            // Perform the inverse IP permutation.
            $crypt_block[$c] .= '$in =
                ($shuffleinvip[($l >> 24) & 0xFF] & "\\x80\\x80\\x80\\x80\\x80\\x80\\x80\\x80") |
                ($shuffleinvip[($r >> 24) & 0xFF] & "\\x40\\x40\\x40\\x40\\x40\\x40\\x40\\x40") |
                ($shuffleinvip[($l >> 16) & 0xFF] & "\\x20\\x20\\x20\\x20\\x20\\x20\\x20\\x20") |
                ($shuffleinvip[($r >> 16) & 0xFF] & "\\x10\\x10\\x10\\x10\\x10\\x10\\x10\\x10") |
                ($shuffleinvip[($l >>  8) & 0xFF] & "\\x08\\x08\\x08\\x08\\x08\\x08\\x08\\x08") |
                ($shuffleinvip[($r >>  8) & 0xFF] & "\\x04\\x04\\x04\\x04\\x04\\x04\\x04\\x04") |
                ($shuffleinvip[ $l        & 0xFF] & "\\x02\\x02\\x02\\x02\\x02\\x02\\x02\\x02") |
                ($shuffleinvip[ $r        & 0xFF] & "\\x01\\x01\\x01\\x01\\x01\\x01\\x01\\x01");
            ';
        }
        // Creates the inline-crypt function
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => $init_crypt, 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $crypt_block[self::ENCRYPT], 'decrypt_block' => $crypt_block[self::DECRYPT]]);
    }
}<?php

/**
 * "PKCS1" Formatted EC Key Handler
 *
 * PHP version 5
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN DH PARAMETERS-----
 *
 * Technically, PKCS1 is for RSA keys, only, but we're using PKCS1 to describe
 * DSA, whose format isn't really formally described anywhere, so might as well
 * use it to describe this, too.
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
/**
 * "PKCS1" Formatted DH Key Handler
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends Progenitor
{
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $key = parent::load($key, $password);
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $components = ASN1::asn1map($decoded[0], Maps\DHParameter::MAP);
        if (!is_array($components)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping on parameters');
        }
        return $components;
    }
    /**
     * Convert EC parameters to the appropriate format
     *
     * @access public
     * @return string
     */
    public static function saveParameters(BigInteger $prime, BigInteger $base, array $options = [])
    {
        $params = ['prime' => $prime, 'base' => $base];
        $params = ASN1::encodeDER($params, Maps\DHParameter::MAP);
        return "-----BEGIN DH PARAMETERS-----\r\n" . chunk_split(base64_encode($params), 64) . "-----END DH PARAMETERS-----\r\n";
    }
}<?php

/**
 * PKCS#8 Formatted DH Key Handler
 *
 * PHP version 5
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted DH Key Handler
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends Progenitor
{
    /**
     * OID Name
     *
     * @var string
     * @access private
     */
    const OID_NAME = 'dhKeyAgreement';
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = '1.2.840.113549.1.3.1';
    /**
     * Child OIDs loaded
     *
     * @var bool
     * @access private
     */
    protected static $childOIDsLoaded = false;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $isPublic = strpos($key, 'PUBLIC') !== false;
        $key = parent::load($key, $password);
        $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
        switch (true) {
            case !$isPublic && $type == 'publicKey':
                throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
            case $isPublic && $type == 'privateKey':
                throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
        }
        $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER of parameters');
        }
        $components = ASN1::asn1map($decoded[0], Maps\DHParameter::MAP);
        if (!is_array($components)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping on parameters');
        }
        $decoded = ASN1::decodeBER($key[$type]);
        switch (true) {
            case empty($decoded):
            case !is_array($decoded):
            case !isset($decoded[0]['content']):
            case !$decoded[0]['content'] instanceof BigInteger:
                throw new \RuntimeException('Unable to decode BER of parameters');
        }
        $components[$type] = $decoded[0]['content'];
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $prime
     * @param \phpseclib3\Math\BigInteger $base
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Math\BigInteger $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $prime, BigInteger $base, BigInteger $privateKey, BigInteger $publicKey, $password = '', array $options = [])
    {
        $params = ['prime' => $prime, 'base' => $base];
        $params = ASN1::encodeDER($params, Maps\DHParameter::MAP);
        $params = new ASN1\Element($params);
        $key = ASN1::encodeDER($privateKey, ['type' => ASN1::TYPE_INTEGER]);
        return self::wrapPrivateKey($key, [], $params, $password, $options);
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $prime
     * @param \phpseclib3\Math\BigInteger $base
     * @param \phpseclib3\Math\BigInteger $publicKey
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BigInteger $prime, BigInteger $base, BigInteger $publicKey, array $options = [])
    {
        $params = ['prime' => $prime, 'base' => $base];
        $params = ASN1::encodeDER($params, Maps\DHParameter::MAP);
        $params = new ASN1\Element($params);
        $key = ASN1::encodeDER($publicKey, ['type' => ASN1::TYPE_INTEGER]);
        return self::wrapPublicKey($key, $params);
    }
}<?php

/**
 * DH Parameters
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH;

use phpseclib3\Crypt\DH;
/**
 * DH Parameters
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Parameters extends DH
{
    /**
     * Returns the parameters
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type = 'PKCS1', array $options = [])
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        return $type::saveParameters($this->prime, $this->base, $options);
    }
}<?php

/**
 * DH Private Key
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH;

use phpseclib3\Crypt\DH;
use phpseclib3\Crypt\Common;
/**
 * DH Private Key
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrivateKey extends DH
{
    use Common\Traits\PasswordProtected;
    /**
     * Private Key
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $privateKey;
    /**
     * Public Key
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $publicKey;
    /**
     * Returns the public key
     *
     * @access public
     * @return DH\PublicKey
     */
    public function getPublicKey()
    {
        $type = self::validatePlugin('Keys', 'PKCS8', 'savePublicKey');
        if (!isset($this->publicKey)) {
            $this->publicKey = $this->base->powMod($this->privateKey, $this->prime);
        }
        $key = $type::savePublicKey($this->prime, $this->base, $this->publicKey);
        return DH::loadFormat('PKCS8', $key);
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePrivateKey');
        if (!isset($this->publicKey)) {
            $this->publicKey = $this->base->powMod($this->privateKey, $this->prime);
        }
        return $type::savePrivateKey($this->prime, $this->base, $this->privateKey, $this->publicKey, $this->password, $options);
    }
}<?php

/**
 * DH Public Key
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\DH;

use phpseclib3\Crypt\DH;
use phpseclib3\Crypt\Common;
/**
 * DH Public Key
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PublicKey extends DH
{
    use Common\Traits\Fingerprint;
    /**
     * Returns the public key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePublicKey');
        return $type::savePublicKey($this->prime, $this->base, $this->publicKey, $options);
    }
    /**
     * Returns the public key as a BigInteger
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function toBigInteger()
    {
        return $this->publicKey;
    }
}<?php

/**
 * Pure-PHP implementation of Rijndael.
 *
 * Uses mcrypt, if available/possible, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * If {@link self::setBlockLength() setBlockLength()} isn't called, it'll be assumed to be 128 bits.  If
 * {@link self::setKeyLength() setKeyLength()} isn't called, it'll be calculated from
 * {@link self::setKey() setKey()}.  ie. if the key is 128-bits, the key length will be 128-bits.  If it's
 * 136-bits it'll be null-padded to 192-bits and 192 bits will be the key length until
 * {@link self::setKey() setKey()} is called, again, at which point, it'll be recalculated.
 *
 * Not all Rijndael implementations may support 160-bits or 224-bits as the block length / key length.  mcrypt, for example,
 * does not.  AES, itself, only supports block lengths of 128 and key lengths of 128, 192, and 256.
 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=10 Rijndael-ammended.pdf#page=10} defines the
 * algorithm for block lengths of 192 and 256 but not for block lengths / key lengths of 160 and 224.  Indeed, 160 and 224
 * are first defined as valid key / block lengths in
 * {@link http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=44 Rijndael-ammended.pdf#page=44}:
 * Extensions: Other block and Cipher Key lengths.
 * Note: Use of 160/224-bit Keys must be explicitly set by setKeyLength(160) respectively setKeyLength(224).
 *
 * {@internal The variable names are the same as those in
 * {@link http://www.csrc.nist.gov/publications/fips/fips197/fips-197.pdf#page=10 fips-197.pdf#page=10}.}}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $rijndael = new \phpseclib3\Crypt\Rijndael('ctr');
 *
 *    $rijndael->setKey('abcdefghijklmnop');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $rijndael->decrypt($rijndael->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Rijndael
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2008 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\BadModeException;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Exception\InconsistentSetupException;
use phpseclib3\Exception\BadDecryptionException;
/**
 * Pure-PHP implementation of Rijndael.
 *
 * @package Rijndael
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Rijndael extends BlockCipher
{
    /**
     * The mcrypt specific name of the cipher
     *
     * Mcrypt is useable for 128/192/256-bit $block_size/$key_length. For 160/224 not.
     * \phpseclib3\Crypt\Rijndael determines automatically whether mcrypt is useable
     * or not for the current $block_size/$key_length.
     * In case of, $cipher_name_mcrypt will be set dynamically at run time accordingly.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @see \phpseclib3\Crypt\Common\SymmetricKey::engine
     * @see self::isValidEngine()
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'rijndael-128';
    /**
     * The Key Schedule
     *
     * @see self::setup()
     * @var array
     * @access private
     */
    private $w;
    /**
     * The Inverse Key Schedule
     *
     * @see self::setup()
     * @var array
     * @access private
     */
    private $dw;
    /**
     * The Block Length divided by 32
     *
     * {@internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4.  Exists in conjunction with $block_size
     *    because the encryption / decryption / key schedule creation requires this number and not $block_size.  We could
     *    derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
     *    of that, we'll just precompute it once.}
     *
     * @see self::setBlockLength()
     * @var int
     * @access private
     */
    private $Nb = 4;
    /**
     * The Key Length (in bytes)
     *
     * {@internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $Nk
     *    because the encryption / decryption / key schedule creation requires this number and not $key_length.  We could
     *    derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
     *    of that, we'll just precompute it once.}
     *
     * @see self::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 16;
    /**
     * The Key Length divided by 32
     *
     * @see self::setKeyLength()
     * @var int
     * @access private
     * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
     */
    private $Nk = 4;
    /**
     * The Number of Rounds
     *
     * {@internal The max value is 14, the min value is 10.}
     *
     * @var int
     * @access private
     */
    private $Nr;
    /**
     * Shift offsets
     *
     * @var array
     * @access private
     */
    private $c;
    /**
     * Holds the last used key- and block_size information
     *
     * @var array
     * @access private
     */
    private $kl;
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws \InvalidArgumentException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new BadModeException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
    * Sets the key length.
    *
    * Valid key lengths are 128, 160, 192, 224, and 256.
    *
    * Note: phpseclib extends Rijndael (and AES) for using 160- and 224-bit keys but they are officially not defined
    and the most (if not all) implementations are not able using 160/224-bit keys but round/pad them up to
    192/256 bits as, for example, mcrypt will do.
    *
    * That said, if you want be compatible with other Rijndael and AES implementations,
    you should not setKeyLength(160) or setKeyLength(224).
    *
    * Additional: In case of 160- and 224-bit keys, phpseclib will/can, for that reason, not use
    the mcrypt php extension, even if available.
    This results then in slower encryption.
    *
    * @access public
    * @throws \LengthException if the key length is invalid
    * @param int $length
    */
    public function setKeyLength($length)
    {
        switch ($length) {
            case 128:
            case 160:
            case 192:
            case 224:
            case 256:
                $this->key_length = $length >> 3;
                break;
            default:
                throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported');
        }
        parent::setKeyLength($length);
    }
    /**
     * Sets the key.
     *
     * Rijndael supports five different key lengths
     *
     * @see setKeyLength()
     * @access public
     * @param string $key
     * @throws \LengthException if the key length isn't supported
     */
    public function setKey($key)
    {
        switch (strlen($key)) {
            case 16:
            case 20:
            case 24:
            case 28:
            case 32:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16, 20, 24, 28 or 32 are supported');
        }
        parent::setKey($key);
    }
    /**
     * Sets the block length
     *
     * Valid block lengths are 128, 160, 192, 224, and 256.
     *
     * @access public
     * @param int $length
     */
    public function setBlockLength($length)
    {
        switch ($length) {
            case 128:
            case 160:
            case 192:
            case 224:
            case 256:
                break;
            default:
                throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes 128, 160, 192, 224 or 256 bits are supported');
        }
        $this->Nb = $length >> 5;
        $this->block_size = $length >> 3;
        $this->changed = $this->nonIVChanged = true;
        $this->setEngine();
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        switch ($engine) {
            case self::ENGINE_LIBSODIUM:
                return function_exists('sodium_crypto_aead_aes256gcm_is_available') && sodium_crypto_aead_aes256gcm_is_available() && $this->mode == self::MODE_GCM && $this->key_length == 32 && $this->nonce && strlen($this->nonce) == 12 && $this->block_size == 16;
            case self::ENGINE_OPENSSL_GCM:
                if (!extension_loaded('openssl')) {
                    return false;
                }
                $methods = openssl_get_cipher_methods();
                return $this->mode == self::MODE_GCM && version_compare(PHP_VERSION, '7.1.0', '>=') && in_array('aes-' . $this->getKeyLength() . '-gcm', $methods) && $this->block_size == 16;
            case self::ENGINE_OPENSSL:
                if ($this->block_size != 16) {
                    return false;
                }
                $this->cipher_name_openssl_ecb = 'aes-' . ($this->key_length << 3) . '-ecb';
                $this->cipher_name_openssl = 'aes-' . ($this->key_length << 3) . '-' . $this->openssl_translate_mode();
                break;
            case self::ENGINE_MCRYPT:
                $this->cipher_name_mcrypt = 'rijndael-' . ($this->block_size << 3);
                if ($this->key_length % 8) {
                    // is it a 160/224-bit key?
                    // mcrypt is not usable for them, only for 128/192/256-bit keys
                    return false;
                }
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Encrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        static $tables;
        if (empty($tables)) {
            $tables =& $this->getTables();
        }
        $t0 = $tables[0];
        $t1 = $tables[1];
        $t2 = $tables[2];
        $t3 = $tables[3];
        $sbox = $tables[4];
        $state = [];
        $words = unpack('N*', $in);
        $c = $this->c;
        $w = $this->w;
        $Nb = $this->Nb;
        $Nr = $this->Nr;
        // addRoundKey
        $wc = $Nb - 1;
        foreach ($words as $word) {
            $state[] = $word ^ $w[++$wc];
        }
        // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
        // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
        // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
        // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
        // Unfortunately, the description given there is not quite correct.  Per aes.spec.v316.pdf#page=19 [1],
        // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
        // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
        $temp = [];
        for ($round = 1; $round < $Nr; ++$round) {
            $i = 0;
            // $c[0] == 0
            $j = $c[1];
            $k = $c[2];
            $l = $c[3];
            while ($i < $Nb) {
                $temp[$i] = $t0[$state[$i] >> 24 & 0xff] ^ $t1[$state[$j] >> 16 & 0xff] ^ $t2[$state[$k] >> 8 & 0xff] ^ $t3[$state[$l] & 0xff] ^ $w[++$wc];
                ++$i;
                $j = ($j + 1) % $Nb;
                $k = ($k + 1) % $Nb;
                $l = ($l + 1) % $Nb;
            }
            $state = $temp;
        }
        // subWord
        for ($i = 0; $i < $Nb; ++$i) {
            $state[$i] = $sbox[$state[$i] & 0xff] | $sbox[$state[$i] >> 8 & 0xff] << 8 | $sbox[$state[$i] >> 16 & 0xff] << 16 | $sbox[$state[$i] >> 24 & 0xff] << 24;
        }
        // shiftRows + addRoundKey
        $i = 0;
        // $c[0] == 0
        $j = $c[1];
        $k = $c[2];
        $l = $c[3];
        while ($i < $Nb) {
            $temp[$i] = $state[$i] & 0xff000000 ^ $state[$j] & 0xff0000 ^ $state[$k] & 0xff00 ^ $state[$l] & 0xff ^ $w[$i];
            ++$i;
            $j = ($j + 1) % $Nb;
            $k = ($k + 1) % $Nb;
            $l = ($l + 1) % $Nb;
        }
        return pack('N*', ...$temp);
    }
    /**
     * Decrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        static $invtables;
        if (empty($invtables)) {
            $invtables =& $this->getInvTables();
        }
        $dt0 = $invtables[0];
        $dt1 = $invtables[1];
        $dt2 = $invtables[2];
        $dt3 = $invtables[3];
        $isbox = $invtables[4];
        $state = [];
        $words = unpack('N*', $in);
        $c = $this->c;
        $dw = $this->dw;
        $Nb = $this->Nb;
        $Nr = $this->Nr;
        // addRoundKey
        $wc = $Nb - 1;
        foreach ($words as $word) {
            $state[] = $word ^ $dw[++$wc];
        }
        $temp = [];
        for ($round = $Nr - 1; $round > 0; --$round) {
            $i = 0;
            // $c[0] == 0
            $j = $Nb - $c[1];
            $k = $Nb - $c[2];
            $l = $Nb - $c[3];
            while ($i < $Nb) {
                $temp[$i] = $dt0[$state[$i] >> 24 & 0xff] ^ $dt1[$state[$j] >> 16 & 0xff] ^ $dt2[$state[$k] >> 8 & 0xff] ^ $dt3[$state[$l] & 0xff] ^ $dw[++$wc];
                ++$i;
                $j = ($j + 1) % $Nb;
                $k = ($k + 1) % $Nb;
                $l = ($l + 1) % $Nb;
            }
            $state = $temp;
        }
        // invShiftRows + invSubWord + addRoundKey
        $i = 0;
        // $c[0] == 0
        $j = $Nb - $c[1];
        $k = $Nb - $c[2];
        $l = $Nb - $c[3];
        while ($i < $Nb) {
            $word = $state[$i] & 0xff000000 | $state[$j] & 0xff0000 | $state[$k] & 0xff00 | $state[$l] & 0xff;
            $temp[$i] = $dw[$i] ^ ($isbox[$word & 0xff] | $isbox[$word >> 8 & 0xff] << 8 | $isbox[$word >> 16 & 0xff] << 16 | $isbox[$word >> 24 & 0xff] << 24);
            ++$i;
            $j = ($j + 1) % $Nb;
            $k = ($k + 1) % $Nb;
            $l = ($l + 1) % $Nb;
        }
        return pack('N*', ...$temp);
    }
    /**
    * Setup the self::ENGINE_INTERNAL $engine
    *
    * (re)init, if necessary, the internal cipher $engine and flush all $buffers
    Used (only) if $engine == self::ENGINE_INTERNAL
    *
    * _setup() will be called each time if $changed === true
    typically this happens when using one or more of following public methods:
    *
    * - setKey()
    *
    * - setIV()
    *
    * - disableContinuousBuffer()
    *
    * - First run of encrypt() / decrypt() with no init-settings
    *
    * {@internal setup() is always called before en/decryption.}
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::setKey()
    * @see self::setIV()
    * @see self::disableContinuousBuffer()
    * @access private
    */
    protected function setup()
    {
        if (!$this->changed) {
            return;
        }
        parent::setup();
        if (is_string($this->iv) && strlen($this->iv) != $this->block_size) {
            throw new InconsistentSetupException('The IV length (' . strlen($this->iv) . ') does not match the block size (' . $this->block_size . ')');
        }
    }
    /**
     * Setup the key (expansion)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupKey()
     * @access private
     */
    protected function setupKey()
    {
        // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
        // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
        static $rcon = [0, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000, 0x6c000000, 0xd8000000, 0xab000000, 0x4d000000, 0x9a000000, 0x2f000000, 0x5e000000, 0xbc000000, 0x63000000, 0xc6000000, 0x97000000, 0x35000000, 0x6a000000, 0xd4000000, 0xb3000000, 0x7d000000, 0xfa000000, 0xef000000, 0xc5000000, 0x91000000];
        if (isset($this->kl['key']) && $this->key === $this->kl['key'] && $this->key_length === $this->kl['key_length'] && $this->block_size === $this->kl['block_size']) {
            // already expanded
            return;
        }
        $this->kl = ['key' => $this->key, 'key_length' => $this->key_length, 'block_size' => $this->block_size];
        $this->Nk = $this->key_length >> 2;
        // see Rijndael-ammended.pdf#page=44
        $this->Nr = max($this->Nk, $this->Nb) + 6;
        // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
        //     "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
        // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
        //     "Table 2: Shift offsets for different block lengths"
        switch ($this->Nb) {
            case 4:
            case 5:
            case 6:
                $this->c = [0, 1, 2, 3];
                break;
            case 7:
                $this->c = [0, 1, 2, 4];
                break;
            case 8:
                $this->c = [0, 1, 3, 4];
        }
        $w = array_values(unpack('N*words', $this->key));
        $length = $this->Nb * ($this->Nr + 1);
        for ($i = $this->Nk; $i < $length; $i++) {
            $temp = $w[$i - 1];
            if ($i % $this->Nk == 0) {
                // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
                // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
                // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
                // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
                $temp = $temp << 8 & 0xffffff00 | $temp >> 24 & 0xff;
                // rotWord
                $temp = $this->subWord($temp) ^ $rcon[$i / $this->Nk];
            } elseif ($this->Nk > 6 && $i % $this->Nk == 4) {
                $temp = $this->subWord($temp);
            }
            $w[$i] = $w[$i - $this->Nk] ^ $temp;
        }
        // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
        // and generate the inverse key schedule.  more specifically,
        // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
        // "The key expansion for the Inverse Cipher is defined as follows:
        //        1. Apply the Key Expansion.
        //        2. Apply InvMixColumn to all Round Keys except the first and the last one."
        // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
        list($dt0, $dt1, $dt2, $dt3) = $this->getInvTables();
        $temp = $this->w = $this->dw = [];
        for ($i = $row = $col = 0; $i < $length; $i++, $col++) {
            if ($col == $this->Nb) {
                if ($row == 0) {
                    $this->dw[0] = $this->w[0];
                } else {
                    // subWord + invMixColumn + invSubWord = invMixColumn
                    $j = 0;
                    while ($j < $this->Nb) {
                        $dw = $this->subWord($this->w[$row][$j]);
                        $temp[$j] = $dt0[$dw >> 24 & 0xff] ^ $dt1[$dw >> 16 & 0xff] ^ $dt2[$dw >> 8 & 0xff] ^ $dt3[$dw & 0xff];
                        $j++;
                    }
                    $this->dw[$row] = $temp;
                }
                $col = 0;
                $row++;
            }
            $this->w[$row][$col] = $w[$i];
        }
        $this->dw[$row] = $this->w[$row];
        // Converting to 1-dim key arrays (both ascending)
        $this->dw = array_reverse($this->dw);
        $w = array_pop($this->w);
        $dw = array_pop($this->dw);
        foreach ($this->w as $r => $wr) {
            foreach ($wr as $c => $wc) {
                $w[] = $wc;
                $dw[] = $this->dw[$r][$c];
            }
        }
        $this->w = $w;
        $this->dw = $dw;
    }
    /**
     * Performs S-Box substitutions
     *
     * @return array
     * @access private
     * @param int $word
     */
    private function subWord($word)
    {
        static $sbox;
        if (empty($sbox)) {
            list(, , , , $sbox) = self::getTables();
        }
        return $sbox[$word & 0xff] | $sbox[$word >> 8 & 0xff] << 8 | $sbox[$word >> 16 & 0xff] << 16 | $sbox[$word >> 24 & 0xff] << 24;
    }
    /**
     * Provides the mixColumns and sboxes tables
     *
     * @see self::encryptBlock()
     * @see self::setupInlineCrypt()
     * @see self::subWord()
     * @access private
     * @return array &$tables
     */
    protected function &getTables()
    {
        static $tables;
        if (empty($tables)) {
            // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
            // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
            // those are the names we'll use.
            $t3 = array_map('intval', [
                // with array_map('intval', ...) we ensure we have only int's and not
                // some slower floats converted by php automatically on high values
                0x6363a5c6,
                0x7c7c84f8,
                0x777799ee,
                0x7b7b8df6,
                0xf2f20dff,
                0x6b6bbdd6,
                0x6f6fb1de,
                0xc5c55491,
                0x30305060,
                0x1010302,
                0x6767a9ce,
                0x2b2b7d56,
                0xfefe19e7,
                0xd7d762b5,
                0xababe64d,
                0x76769aec,
                0xcaca458f,
                0x82829d1f,
                0xc9c94089,
                0x7d7d87fa,
                0xfafa15ef,
                0x5959ebb2,
                0x4747c98e,
                0xf0f00bfb,
                0xadadec41,
                0xd4d467b3,
                0xa2a2fd5f,
                0xafafea45,
                0x9c9cbf23,
                0xa4a4f753,
                0x727296e4,
                0xc0c05b9b,
                0xb7b7c275,
                0xfdfd1ce1,
                0x9393ae3d,
                0x26266a4c,
                0x36365a6c,
                0x3f3f417e,
                0xf7f702f5,
                0xcccc4f83,
                0x34345c68,
                0xa5a5f451,
                0xe5e534d1,
                0xf1f108f9,
                0x717193e2,
                0xd8d873ab,
                0x31315362,
                0x15153f2a,
                0x4040c08,
                0xc7c75295,
                0x23236546,
                0xc3c35e9d,
                0x18182830,
                0x9696a137,
                0x5050f0a,
                0x9a9ab52f,
                0x707090e,
                0x12123624,
                0x80809b1b,
                0xe2e23ddf,
                0xebeb26cd,
                0x2727694e,
                0xb2b2cd7f,
                0x75759fea,
                0x9091b12,
                0x83839e1d,
                0x2c2c7458,
                0x1a1a2e34,
                0x1b1b2d36,
                0x6e6eb2dc,
                0x5a5aeeb4,
                0xa0a0fb5b,
                0x5252f6a4,
                0x3b3b4d76,
                0xd6d661b7,
                0xb3b3ce7d,
                0x29297b52,
                0xe3e33edd,
                0x2f2f715e,
                0x84849713,
                0x5353f5a6,
                0xd1d168b9,
                0x0,
                0xeded2cc1,
                0x20206040,
                0xfcfc1fe3,
                0xb1b1c879,
                0x5b5bedb6,
                0x6a6abed4,
                0xcbcb468d,
                0xbebed967,
                0x39394b72,
                0x4a4ade94,
                0x4c4cd498,
                0x5858e8b0,
                0xcfcf4a85,
                0xd0d06bbb,
                0xefef2ac5,
                0xaaaae54f,
                0xfbfb16ed,
                0x4343c586,
                0x4d4dd79a,
                0x33335566,
                0x85859411,
                0x4545cf8a,
                0xf9f910e9,
                0x2020604,
                0x7f7f81fe,
                0x5050f0a0,
                0x3c3c4478,
                0x9f9fba25,
                0xa8a8e34b,
                0x5151f3a2,
                0xa3a3fe5d,
                0x4040c080,
                0x8f8f8a05,
                0x9292ad3f,
                0x9d9dbc21,
                0x38384870,
                0xf5f504f1,
                0xbcbcdf63,
                0xb6b6c177,
                0xdada75af,
                0x21216342,
                0x10103020,
                0xffff1ae5,
                0xf3f30efd,
                0xd2d26dbf,
                0xcdcd4c81,
                0xc0c1418,
                0x13133526,
                0xecec2fc3,
                0x5f5fe1be,
                0x9797a235,
                0x4444cc88,
                0x1717392e,
                0xc4c45793,
                0xa7a7f255,
                0x7e7e82fc,
                0x3d3d477a,
                0x6464acc8,
                0x5d5de7ba,
                0x19192b32,
                0x737395e6,
                0x6060a0c0,
                0x81819819,
                0x4f4fd19e,
                0xdcdc7fa3,
                0x22226644,
                0x2a2a7e54,
                0x9090ab3b,
                0x8888830b,
                0x4646ca8c,
                0xeeee29c7,
                0xb8b8d36b,
                0x14143c28,
                0xdede79a7,
                0x5e5ee2bc,
                0xb0b1d16,
                0xdbdb76ad,
                0xe0e03bdb,
                0x32325664,
                0x3a3a4e74,
                0xa0a1e14,
                0x4949db92,
                0x6060a0c,
                0x24246c48,
                0x5c5ce4b8,
                0xc2c25d9f,
                0xd3d36ebd,
                0xacacef43,
                0x6262a6c4,
                0x9191a839,
                0x9595a431,
                0xe4e437d3,
                0x79798bf2,
                0xe7e732d5,
                0xc8c8438b,
                0x3737596e,
                0x6d6db7da,
                0x8d8d8c01,
                0xd5d564b1,
                0x4e4ed29c,
                0xa9a9e049,
                0x6c6cb4d8,
                0x5656faac,
                0xf4f407f3,
                0xeaea25cf,
                0x6565afca,
                0x7a7a8ef4,
                0xaeaee947,
                0x8081810,
                0xbabad56f,
                0x787888f0,
                0x25256f4a,
                0x2e2e725c,
                0x1c1c2438,
                0xa6a6f157,
                0xb4b4c773,
                0xc6c65197,
                0xe8e823cb,
                0xdddd7ca1,
                0x74749ce8,
                0x1f1f213e,
                0x4b4bdd96,
                0xbdbddc61,
                0x8b8b860d,
                0x8a8a850f,
                0x707090e0,
                0x3e3e427c,
                0xb5b5c471,
                0x6666aacc,
                0x4848d890,
                0x3030506,
                0xf6f601f7,
                0xe0e121c,
                0x6161a3c2,
                0x35355f6a,
                0x5757f9ae,
                0xb9b9d069,
                0x86869117,
                0xc1c15899,
                0x1d1d273a,
                0x9e9eb927,
                0xe1e138d9,
                0xf8f813eb,
                0x9898b32b,
                0x11113322,
                0x6969bbd2,
                0xd9d970a9,
                0x8e8e8907,
                0x9494a733,
                0x9b9bb62d,
                0x1e1e223c,
                0x87879215,
                0xe9e920c9,
                0xcece4987,
                0x5555ffaa,
                0x28287850,
                0xdfdf7aa5,
                0x8c8c8f03,
                0xa1a1f859,
                0x89898009,
                0xd0d171a,
                0xbfbfda65,
                0xe6e631d7,
                0x4242c684,
                0x6868b8d0,
                0x4141c382,
                0x9999b029,
                0x2d2d775a,
                0xf0f111e,
                0xb0b0cb7b,
                0x5454fca8,
                0xbbbbd66d,
                0x16163a2c,
            ]);
            foreach ($t3 as $t3i) {
                $t0[] = $t3i << 24 & 0xff000000 | $t3i >> 8 & 0xffffff;
                $t1[] = $t3i << 16 & 0xffff0000 | $t3i >> 16 & 0xffff;
                $t2[] = $t3i << 8 & 0xffffff00 | $t3i >> 24 & 0xff;
            }
            $tables = [
                // The Precomputed mixColumns tables t0 - t3
                $t0,
                $t1,
                $t2,
                $t3,
                // The SubByte S-Box
                [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x1, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x4, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x5, 0x9a, 0x7, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x9, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x0, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x2, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0xc, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0xb, 0xdb, 0xe0, 0x32, 0x3a, 0xa, 0x49, 0x6, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x8, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x3, 0xf6, 0xe, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0xd, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0xf, 0xb0, 0x54, 0xbb, 0x16],
            ];
        }
        return $tables;
    }
    /**
     * Provides the inverse mixColumns and inverse sboxes tables
     *
     * @see self::decryptBlock()
     * @see self::setupInlineCrypt()
     * @see self::setupKey()
     * @access private
     * @return array &$tables
     */
    protected function &getInvTables()
    {
        static $tables;
        if (empty($tables)) {
            $dt3 = array_map('intval', [0xf4a75051, 0x4165537e, 0x17a4c31a, 0x275e963a, 0xab6bcb3b, 0x9d45f11f, 0xfa58abac, 0xe303934b, 0x30fa5520, 0x766df6ad, 0xcc769188, 0x24c25f5, 0xe5d7fc4f, 0x2acbd7c5, 0x35448026, 0x62a38fb5, 0xb15a49de, 0xba1b6725, 0xea0e9845, 0xfec0e15d, 0x2f7502c3, 0x4cf01281, 0x4697a38d, 0xd3f9c66b, 0x8f5fe703, 0x929c9515, 0x6d7aebbf, 0x5259da95, 0xbe832dd4, 0x7421d358, 0xe0692949, 0xc9c8448e, 0xc2896a75, 0x8e7978f4, 0x583e6b99, 0xb971dd27, 0xe14fb6be, 0x88ad17f0, 0x20ac66c9, 0xce3ab47d, 0xdf4a1863, 0x1a3182e5, 0x51336097, 0x537f4562, 0x6477e0b1, 0x6bae84bb, 0x81a01cfe, 0x82b94f9, 0x48685870, 0x45fd198f, 0xde6c8794, 0x7bf8b752, 0x73d323ab, 0x4b02e272, 0x1f8f57e3, 0x55ab2a66, 0xeb2807b2, 0xb5c2032f, 0xc57b9a86, 0x3708a5d3, 0x2887f230, 0xbfa5b223, 0x36aba02, 0x16825ced, 0xcf1c2b8a, 0x79b492a7, 0x7f2f0f3, 0x69e2a14e, 0xdaf4cd65, 0x5bed506, 0x34621fd1, 0xa6fe8ac4, 0x2e539d34, 0xf355a0a2, 0x8ae13205, 0xf6eb75a4, 0x83ec390b, 0x60efaa40, 0x719f065e, 0x6e1051bd, 0x218af93e, 0xdd063d96, 0x3e05aedd, 0xe6bd464d, 0x548db591, 0xc45d0571, 0x6d46f04, 0x5015ff60, 0x98fb2419, 0xbde997d6, 0x4043cc89, 0xd99e7767, 0xe842bdb0, 0x898b8807, 0x195b38e7, 0xc8eedb79, 0x7c0a47a1, 0x420fe97c, 0x841ec9f8, 0x0, 0x80868309, 0x2bed4832, 0x1170ac1e, 0x5a724e6c, 0xefffbfd, 0x8538560f, 0xaed51e3d, 0x2d392736, 0xfd9640a, 0x5ca62168, 0x5b54d19b, 0x362e3a24, 0xa67b10c, 0x57e70f93, 0xee96d2b4, 0x9b919e1b, 0xc0c54f80, 0xdc20a261, 0x774b695a, 0x121a161c, 0x93ba0ae2, 0xa02ae5c0, 0x22e0433c, 0x1b171d12, 0x90d0b0e, 0x8bc7adf2, 0xb6a8b92d, 0x1ea9c814, 0xf1198557, 0x75074caf, 0x99ddbbee, 0x7f60fda3, 0x1269ff7, 0x72f5bc5c, 0x663bc544, 0xfb7e345b, 0x4329768b, 0x23c6dccb, 0xedfc68b6, 0xe4f163b8, 0x31dccad7, 0x63851042, 0x97224013, 0xc6112084, 0x4a247d85, 0xbb3df8d2, 0xf93211ae, 0x29a16dc7, 0x9e2f4b1d, 0xb230f3dc, 0x8652ec0d, 0xc1e3d077, 0xb3166c2b, 0x70b999a9, 0x9448fa11, 0xe9642247, 0xfc8cc4a8, 0xf03f1aa0, 0x7d2cd856, 0x3390ef22, 0x494ec787, 0x38d1c1d9, 0xcaa2fe8c, 0xd40b3698, 0xf581cfa6, 0x7ade28a5, 0xb78e26da, 0xadbfa43f, 0x3a9de42c, 0x78920d50, 0x5fcc9b6a, 0x7e466254, 0x8d13c2f6, 0xd8b8e890, 0x39f75e2e, 0xc3aff582, 0x5d80be9f, 0xd0937c69, 0xd52da96f, 0x2512b3cf, 0xac993bc8, 0x187da710, 0x9c636ee8, 0x3bbb7bdb, 0x267809cd, 0x5918f46e, 0x9ab701ec, 0x4f9aa883, 0x956e65e6, 0xffe67eaa, 0xbccf0821, 0x15e8e6ef, 0xe79bd9ba, 0x6f36ce4a, 0x9f09d4ea, 0xb07cd629, 0xa4b2af31, 0x3f23312a, 0xa59430c6, 0xa266c035, 0x4ebc3774, 0x82caa6fc, 0x90d0b0e0, 0xa7d81533, 0x4984af1, 0xecdaf741, 0xcd500e7f, 0x91f62f17, 0x4dd68d76, 0xefb04d43, 0xaa4d54cc, 0x9604dfe4, 0xd1b5e39e, 0x6a881b4c, 0x2c1fb8c1, 0x65517f46, 0x5eea049d, 0x8c355d01, 0x877473fa, 0xb412efb, 0x671d5ab3, 0xdbd25292, 0x105633e9, 0xd647136d, 0xd7618c9a, 0xa10c7a37, 0xf8148e59, 0x133c89eb, 0xa927eece, 0x61c935b7, 0x1ce5ede1, 0x47b13c7a, 0xd2df599c, 0xf2733f55, 0x14ce7918, 0xc737bf73, 0xf7cdea53, 0xfdaa5b5f, 0x3d6f14df, 0x44db8678, 0xaff381ca, 0x68c43eb9, 0x24342c38, 0xa3405fc2, 0x1dc37216, 0xe2250cbc, 0x3c498b28, 0xd9541ff, 0xa8017139, 0xcb3de08, 0xb4e49cd8, 0x56c19064, 0xcb84617b, 0x32b670d5, 0x6c5c7448, 0xb85742d0]);
            foreach ($dt3 as $dt3i) {
                $dt0[] = $dt3i << 24 & 0xff000000 | $dt3i >> 8 & 0xffffff;
                $dt1[] = $dt3i << 16 & 0xffff0000 | $dt3i >> 16 & 0xffff;
                $dt2[] = $dt3i << 8 & 0xffffff00 | $dt3i >> 24 & 0xff;
            }
            $tables = [
                // The Precomputed inverse mixColumns tables dt0 - dt3
                $dt0,
                $dt1,
                $dt2,
                $dt3,
                // The inverse SubByte S-Box
                [0x52, 0x9, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0xb, 0x42, 0xfa, 0xc3, 0x4e, 0x8, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x0, 0x8c, 0xbc, 0xd3, 0xa, 0xf7, 0xe4, 0x58, 0x5, 0xb8, 0xb3, 0x45, 0x6, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0xf, 0x2, 0xc1, 0xaf, 0xbd, 0x3, 0x1, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0xe, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x7, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0xd, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x4, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0xc, 0x7d],
            ];
        }
        return $tables;
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        $w = $this->w;
        $dw = $this->dw;
        $init_encrypt = '';
        $init_decrypt = '';
        $Nr = $this->Nr;
        $Nb = $this->Nb;
        $c = $this->c;
        // Generating encrypt code:
        $init_encrypt .= '
            static $tables;
            if (empty($tables)) {
                $tables = &$this->getTables();
            }
            $t0   = $tables[0];
            $t1   = $tables[1];
            $t2   = $tables[2];
            $t3   = $tables[3];
            $sbox = $tables[4];
        ';
        $s = 'e';
        $e = 's';
        $wc = $Nb - 1;
        // Preround: addRoundKey
        $encrypt_block = '$in = unpack("N*", $in);
';
        for ($i = 0; $i < $Nb; ++$i) {
            $encrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $w[++$wc] . ";\n";
        }
        // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
        for ($round = 1; $round < $Nr; ++$round) {
            list($s, $e) = [$e, $s];
            for ($i = 0; $i < $Nb; ++$i) {
                $encrypt_block .= '$' . $e . $i . ' =
                    $t0[($' . $s . $i . ' >> 24) & 0xff] ^
                    $t1[($' . $s . ($i + $c[1]) % $Nb . ' >> 16) & 0xff] ^
                    $t2[($' . $s . ($i + $c[2]) % $Nb . ' >>  8) & 0xff] ^
                    $t3[ $' . $s . ($i + $c[3]) % $Nb . '        & 0xff] ^
                    ' . $w[++$wc] . ";\n";
            }
        }
        // Finalround: subWord + shiftRows + addRoundKey
        for ($i = 0; $i < $Nb; ++$i) {
            $encrypt_block .= '$' . $e . $i . ' =
                 $sbox[ $' . $e . $i . '        & 0xff]        |
                ($sbox[($' . $e . $i . ' >>  8) & 0xff] <<  8) |
                ($sbox[($' . $e . $i . ' >> 16) & 0xff] << 16) |
                ($sbox[($' . $e . $i . ' >> 24) & 0xff] << 24);
';
        }
        $encrypt_block .= '$in = pack("N*"
';
        for ($i = 0; $i < $Nb; ++$i) {
            $encrypt_block .= ',
                ($' . $e . $i . ' & ' . (int) 0xff000000 . ') ^
                ($' . $e . ($i + $c[1]) % $Nb . ' &         0x00FF0000   ) ^
                ($' . $e . ($i + $c[2]) % $Nb . ' &         0x0000FF00   ) ^
                ($' . $e . ($i + $c[3]) % $Nb . ' &         0x000000FF   ) ^
                ' . $w[$i] . "\n";
        }
        $encrypt_block .= ');';
        // Generating decrypt code:
        $init_decrypt .= '
            static $invtables;
            if (empty($invtables)) {
                $invtables = &$this->getInvTables();
            }
            $dt0   = $invtables[0];
            $dt1   = $invtables[1];
            $dt2   = $invtables[2];
            $dt3   = $invtables[3];
            $isbox = $invtables[4];
        ';
        $s = 'e';
        $e = 's';
        $wc = $Nb - 1;
        // Preround: addRoundKey
        $decrypt_block = '$in = unpack("N*", $in);
';
        for ($i = 0; $i < $Nb; ++$i) {
            $decrypt_block .= '$s' . $i . ' = $in[' . ($i + 1) . '] ^ ' . $dw[++$wc] . ';
';
        }
        // Mainrounds: shiftRows + subWord + mixColumns + addRoundKey
        for ($round = 1; $round < $Nr; ++$round) {
            list($s, $e) = [$e, $s];
            for ($i = 0; $i < $Nb; ++$i) {
                $decrypt_block .= '$' . $e . $i . ' =
                    $dt0[($' . $s . $i . ' >> 24) & 0xff] ^
                    $dt1[($' . $s . ($Nb + $i - $c[1]) % $Nb . ' >> 16) & 0xff] ^
                    $dt2[($' . $s . ($Nb + $i - $c[2]) % $Nb . ' >>  8) & 0xff] ^
                    $dt3[ $' . $s . ($Nb + $i - $c[3]) % $Nb . '        & 0xff] ^
                    ' . $dw[++$wc] . ";\n";
            }
        }
        // Finalround: subWord + shiftRows + addRoundKey
        for ($i = 0; $i < $Nb; ++$i) {
            $decrypt_block .= '$' . $e . $i . ' =
                 $isbox[ $' . $e . $i . '        & 0xff]        |
                ($isbox[($' . $e . $i . ' >>  8) & 0xff] <<  8) |
                ($isbox[($' . $e . $i . ' >> 16) & 0xff] << 16) |
                ($isbox[($' . $e . $i . ' >> 24) & 0xff] << 24);
';
        }
        $decrypt_block .= '$in = pack("N*"
';
        for ($i = 0; $i < $Nb; ++$i) {
            $decrypt_block .= ',
                ($' . $e . $i . ' & ' . (int) 0xff000000 . ') ^
                ($' . $e . ($Nb + $i - $c[1]) % $Nb . ' &         0x00FF0000   ) ^
                ($' . $e . ($Nb + $i - $c[2]) % $Nb . ' &         0x0000FF00   ) ^
                ($' . $e . ($Nb + $i - $c[3]) % $Nb . ' &         0x000000FF   ) ^
                ' . $dw[$i] . "\n";
        }
        $decrypt_block .= ');';
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => '', 'init_encrypt' => $init_encrypt, 'init_decrypt' => $init_decrypt, 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block]);
    }
    /**
     * Encrypts a message.
     *
     * @see self::decrypt()
     * @see parent::encrypt()
     * @access public
     * @param string $plaintext
     * @return string
     */
    public function encrypt($plaintext)
    {
        $this->setup();
        switch ($this->engine) {
            case self::ENGINE_LIBSODIUM:
                $this->newtag = sodium_crypto_aead_aes256gcm_encrypt($plaintext, $this->aad, $this->nonce, $this->key);
                return Strings::shift($this->newtag, strlen($plaintext));
            case self::ENGINE_OPENSSL_GCM:
                return openssl_encrypt($plaintext, 'aes-' . $this->getKeyLength() . '-gcm', $this->key, OPENSSL_RAW_DATA, $this->nonce, $this->newtag, $this->aad);
        }
        return parent::encrypt($plaintext);
    }
    /**
     * Decrypts a message.
     *
     * @see self::encrypt()
     * @see parent::decrypt()
     * @access public
     * @param string $ciphertext
     * @return string
     */
    public function decrypt($ciphertext)
    {
        $this->setup();
        switch ($this->engine) {
            case self::ENGINE_LIBSODIUM:
                if ($this->oldtag === false) {
                    throw new InsufficientSetupException('Authentication Tag has not been set');
                }
                if (strlen($this->oldtag) != 16) {
                    break;
                }
                $plaintext = sodium_crypto_aead_aes256gcm_decrypt($ciphertext . $this->oldtag, $this->aad, $this->nonce, $this->key);
                if ($plaintext === false) {
                    $this->oldtag = false;
                    throw new BadDecryptionException('Error decrypting ciphertext with libsodium');
                }
                return $plaintext;
            case self::ENGINE_OPENSSL_GCM:
                if ($this->oldtag === false) {
                    throw new InsufficientSetupException('Authentication Tag has not been set');
                }
                $plaintext = openssl_decrypt($ciphertext, 'aes-' . $this->getKeyLength() . '-gcm', $this->key, OPENSSL_RAW_DATA, $this->nonce, $this->oldtag, $this->aad);
                if ($plaintext === false) {
                    $this->oldtag = false;
                    throw new BadDecryptionException('Error decrypting ciphertext with OpenSSL');
                }
                return $plaintext;
        }
        return parent::decrypt($ciphertext);
    }
}<?php

/**
 * libsodium Key Handler
 *
 * Different NaCl implementations store the key differently.
 * https://blog.mozilla.org/warner/2011/11/29/ed25519-keys/ elaborates.
 * libsodium appears to use the same format as SUPERCOP.
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * libsodium Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class libsodium
{
    use Common;
    /**
     * Is invisible flag
     *
     * @access private
     */
    const IS_INVISIBLE = true;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        switch (strlen($key)) {
            case 32:
                $public = $key;
                break;
            case 64:
                $private = \Phabel\Target\Php80\Polyfill::substr($key, 0, 32);
                $public = \Phabel\Target\Php80\Polyfill::substr($key, -32);
                break;
            case 96:
                $public = \Phabel\Target\Php80\Polyfill::substr($key, -32);
                if (\Phabel\Target\Php80\Polyfill::substr($key, 32, 32) != $public) {
                    throw new \RuntimeException('Keys with 96 bytes should have the 2nd and 3rd set of 32 bytes match');
                }
                $private = \Phabel\Target\Php80\Polyfill::substr($key, 0, 32);
                break;
            default:
                throw new \RuntimeException('libsodium keys need to either be 32 bytes long, 64 bytes long or 96 bytes long');
        }
        $curve = new Ed25519();
        $components = ['curve' => $curve];
        if (isset($private)) {
            $components['dA'] = $curve->extractSecret($private);
        }
        $components['QA'] = isset($public) ? self::extractPoint($public, $curve) : $curve->multiplyPoint($curve->getBasePoint(), $components['dA']);
        return $components;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @return string
     */
    public static function savePublicKey(Ed25519 $curve, array $publicKey)
    {
        return $curve->encodePoint($publicKey);
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, Ed25519 $curve, array $publicKey, $password = '')
    {
        if (!isset($privateKey->secret)) {
            throw new \RuntimeException('Private Key does not have a secret set');
        }
        if (strlen($privateKey->secret) != 32) {
            throw new \RuntimeException('Private Key secret is not of the correct length');
        }
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('libsodium private keys do not support encryption');
        }
        return $privateKey->secret . $curve->encodePoint($publicKey);
    }
}<?php

/**
 * "PKCS1" (RFC5915) Formatted EC Key Handler
 *
 * PHP version 5
 *
 * Used by File/X509.php
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN EC PRIVATE KEY-----
 * -----BEGIN EC PARAMETERS-----
 *
 * Technically, PKCS1 is for RSA keys, only, but we're using PKCS1 to describe
 * DSA, whose format isn't really formally described anywhere, so might as well
 * use it to describe this, too. PKCS1 is easier to remember than RFC5915, after
 * all. I suppose this could also be named IETF but idk
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Crypt\Common\Formats\Keys\PKCS1 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Math\BigInteger;
use ParagonIE\ConstantTime\Base64;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Common\Functions\Strings;
/**
 * "PKCS1" (RFC5915) Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends Progenitor
{
    use Common;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (strpos($key, 'BEGIN EC PARAMETERS') && strpos($key, 'BEGIN EC PRIVATE KEY')) {
            $components = [];
            preg_match('#-*BEGIN EC PRIVATE KEY-*[^-]*-*END EC PRIVATE KEY-*#s', $key, $matches);
            $decoded = parent::load($matches[0], $password);
            $decoded = ASN1::decodeBER($decoded);
            if (empty($decoded)) {
                throw new \RuntimeException('Unable to decode BER');
            }
            $ecPrivate = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
            if (!is_array($ecPrivate)) {
                throw new \RuntimeException('Unable to perform ASN1 mapping');
            }
            if (isset($ecPrivate['parameters'])) {
                $components['curve'] = self::loadCurveByParam($ecPrivate['parameters']);
            }
            preg_match('#-*BEGIN EC PARAMETERS-*[^-]*-*END EC PARAMETERS-*#s', $key, $matches);
            $decoded = parent::load($matches[0], '');
            $decoded = ASN1::decodeBER($decoded);
            if (empty($decoded)) {
                throw new \RuntimeException('Unable to decode BER');
            }
            $ecParams = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
            if (!is_array($ecParams)) {
                throw new \RuntimeException('Unable to perform ASN1 mapping');
            }
            $ecParams = self::loadCurveByParam($ecParams);
            // comparing $ecParams and $components['curve'] directly won't work because they'll have different Math\Common\FiniteField classes
            // even if the modulo is the same
            if (isset($components['curve']) && self::encodeParameters($ecParams, false, []) != self::encodeParameters($components['curve'], false, [])) {
                throw new \RuntimeException('EC PARAMETERS does not correspond to EC PRIVATE KEY');
            }
            if (!isset($components['curve'])) {
                $components['curve'] = $ecParams;
            }
            $components['dA'] = new BigInteger($ecPrivate['privateKey'], 256);
            $components['curve']->rangeCheck($components['dA']);
            $components['QA'] = isset($ecPrivate['publicKey']) ? self::extractPoint($ecPrivate['publicKey'], $components['curve']) : $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
            return $components;
        }
        $key = parent::load($key, $password);
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        $key = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
        if (is_array($key)) {
            return ['curve' => self::loadCurveByParam($key)];
        }
        $key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
        if (!is_array($key)) {
            throw new \RuntimeException('Unable to perform ASN1 mapping');
        }
        if (!isset($key['parameters'])) {
            throw new \RuntimeException('Key cannot be loaded without parameters');
        }
        $components = [];
        $components['curve'] = self::loadCurveByParam($key['parameters']);
        $components['dA'] = new BigInteger($key['privateKey'], 256);
        $components['QA'] = isset($ecPrivate['publicKey']) ? self::extractPoint($ecPrivate['publicKey'], $components['curve']) : $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
        return $components;
    }
    /**
     * Convert EC parameters to the appropriate format
     *
     * @access public
     * @return string
     */
    public static function saveParameters(BaseCurve $curve, array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('TwistedEdwards and Montgomery Curves are not supported');
        }
        $key = self::encodeParameters($curve, false, $options);
        return "-----BEGIN EC PARAMETERS-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END EC PARAMETERS-----\r\n";
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = '', array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('TwistedEdwards Curves are not supported');
        }
        $publicKey = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        $key = ['version' => 'ecPrivkeyVer1', 'privateKey' => $privateKey->toBytes(), 'parameters' => new ASN1\Element(self::encodeParameters($curve)), 'publicKey' => "\x00" . $publicKey];
        $key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP);
        return self::wrapPrivateKey($key, 'EC', $password, $options);
    }
}<?php

/**
 * PKCS#8 Formatted EC Key Handler
 *
 * PHP version 5
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
 * is specific to private keys it's basically creating a DER-encoded wrapper
 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Common\Formats\Keys\PKCS8 as Progenitor;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Crypt\EC\Curves\Ed448;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Common\Functions\Strings;
/**
 * PKCS#8 Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends Progenitor
{
    use Common;
    /**
     * OID Name
     *
     * @var array
     * @access private
     */
    const OID_NAME = ['id-ecPublicKey', 'id-Ed25519', 'id-Ed448'];
    /**
     * OID Value
     *
     * @var string
     * @access private
     */
    const OID_VALUE = ['1.2.840.10045.2.1', '1.3.101.112', '1.3.101.113'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        // initialize_static_variables() is defined in both the trait and the parent class
        // when it's defined in two places it's the traits one that's called
        // the parent one is needed, as well, but the parent one is called by other methods
        // in the parent class as needed and in the context of the parent it's the parent
        // one that's called
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $isPublic = strpos($key, 'PUBLIC') !== false;
        $key = parent::load($key, $password);
        $type = isset($key['privateKey']) ? 'privateKey' : 'publicKey';
        switch (true) {
            case !$isPublic && $type == 'publicKey':
                throw new \UnexpectedValueException('Human readable string claims non-public key but DER encoded string claims public key');
            case $isPublic && $type == 'privateKey':
                throw new \UnexpectedValueException('Human readable string claims public key but DER encoded string claims private key');
        }
        switch ($key[$type . 'Algorithm']['algorithm']) {
            case 'id-Ed25519':
            case 'id-Ed448':
                return self::loadEdDSA($key);
        }
        $decoded = ASN1::decodeBER($key[$type . 'Algorithm']['parameters']->element);
        $params = ASN1::asn1map($decoded[0], Maps\ECParameters::MAP);
        if (!$params) {
            throw new \RuntimeException('Unable to decode the parameters using Maps\\ECParameters');
        }
        $components = [];
        $components['curve'] = self::loadCurveByParam($params);
        if ($isPublic) {
            $components['QA'] = self::extractPoint("\x00" . $key['publicKey'], $components['curve']);
            return $components;
        }
        $decoded = ASN1::decodeBER($key['privateKey']);
        $key = ASN1::asn1map($decoded[0], Maps\ECPrivateKey::MAP);
        if (isset($key['parameters']) && $params != $key['parameters']) {
            throw new \RuntimeException('The PKCS8 parameter field does not match the private key parameter field');
        }
        $components['dA'] = new BigInteger($key['privateKey'], 256);
        $components['curve']->rangeCheck($components['dA']);
        $components['QA'] = isset($key['publicKey']) ? self::extractPoint($key['publicKey'], $components['curve']) : $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
        return $components;
    }
    /**
     * Break a public or private EdDSA key down into its constituent components
     *
     * @return array
     */
    private static function loadEdDSA(array $key)
    {
        $components = [];
        if (isset($key['privateKey'])) {
            $components['curve'] = $key['privateKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448();
            // 0x04 == octet string
            // 0x20 == length (32 bytes)
            if (\Phabel\Target\Php80\Polyfill::substr($key['privateKey'], 0, 2) != "\x04 ") {
                throw new \RuntimeException('The first two bytes of the private key field should be 0x0420');
            }
            $components['dA'] = $components['curve']->extractSecret(\Phabel\Target\Php80\Polyfill::substr($key['privateKey'], 2));
        }
        if (isset($key['publicKey'])) {
            if (!isset($components['curve'])) {
                $components['curve'] = $key['publicKeyAlgorithm']['algorithm'] == 'id-Ed25519' ? new Ed25519() : new Ed448();
            }
            $components['QA'] = self::extractPoint($key['publicKey'], $components['curve']);
        }
        if (isset($key['privateKey']) && !isset($components['QA'])) {
            $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
        }
        return $components;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('Montgomery Curves are not supported');
        }
        if ($curve instanceof TwistedEdwardsCurve) {
            return self::wrapPublicKey($curve->encodePoint($publicKey), null, $curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448');
        }
        $params = new ASN1\Element(self::encodeParameters($curve, false, $options));
        $key = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        return self::wrapPublicKey($key, $params, 'id-ecPublicKey');
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = '', array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('Montgomery Curves are not supported');
        }
        if ($curve instanceof TwistedEdwardsCurve) {
            return self::wrapPrivateKey("\x04 " . $privateKey->secret, [], null, $password, $curve instanceof Ed25519 ? 'id-Ed25519' : 'id-Ed448', "\x00" . $curve->encodePoint($publicKey));
        }
        $publicKey = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        $params = new ASN1\Element(self::encodeParameters($curve, false, $options));
        $key = [
            'version' => 'ecPrivkeyVer1',
            'privateKey' => $privateKey->toBytes(),
            //'parameters' => $params,
            'publicKey' => "\x00" . $publicKey,
        ];
        $key = ASN1::encodeDER($key, Maps\ECPrivateKey::MAP);
        return self::wrapPrivateKey($key, [], $params, $password, 'id-ecPublicKey', '', $options);
    }
}<?php

/**
 * PuTTY Formatted EC Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\PuTTY as Progenitor;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
/**
 * PuTTY Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PuTTY extends Progenitor
{
    use Common;
    /**
     * Public Handler
     *
     * @var string
     * @access private
     */
    const PUBLIC_HANDLER = 'phpseclib3\\Crypt\\EC\\Formats\\Keys\\OpenSSH';
    /**
     * Supported Key Types
     *
     * @var array
     * @access private
     */
    protected static $types = ['ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $components = parent::load($key, $password);
        if (!isset($components['private'])) {
            return $components;
        }
        $private = $components['private'];
        $temp = Base64::encode(Strings::packSSH2('s', $components['type']) . $components['public']);
        $components = OpenSSH::load($components['type'] . ' ' . $temp . ' ' . $components['comment']);
        if ($components['curve'] instanceof TwistedEdwardsCurve) {
            if (Strings::shift($private, 4) != "\x00\x00\x00 ") {
                throw new \RuntimeException('Length of ssh-ed25519 key should be 32');
            }
            $components['dA'] = $components['curve']->extractSecret($private);
        } else {
            list($components['dA']) = Strings::unpackSSH2('i', $private);
            $components['curve']->rangeCheck($components['dA']);
        }
        return $components;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = false, array $options = [])
    {
        self::initialize_static_variables();
        $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
        $name = $public[0];
        $public = Base64::decode($public[1]);
        list(, $length) = unpack('N', Strings::shift($public, 4));
        Strings::shift($public, $length);
        // PuTTY pads private keys with a null byte per the following:
        // https://github.com/github/putty/blob/a3d14d77f566a41fc61dfdc5c2e0e384c9e6ae8b/sshecc.c#L1926
        if (!$curve instanceof TwistedEdwardsCurve) {
            $private = $privateKey->toBytes();
            if (!(strlen($privateKey->toBits()) & 7)) {
                $private = "\x00{$private}";
            }
        }
        $private = $curve instanceof TwistedEdwardsCurve ? Strings::packSSH2('s', $privateKey->secret) : Strings::packSSH2('s', $private);
        return self::wrapPrivateKey($public, $private, $name, $password, $options);
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField[] $publicKey
     * @return string
     */
    public static function savePublicKey(BaseCurve $curve, array $publicKey)
    {
        $public = explode(' ', OpenSSH::savePublicKey($curve, $publicKey));
        $type = $public[0];
        $public = Base64::decode($public[1]);
        list(, $length) = unpack('N', Strings::shift($public, 4));
        Strings::shift($public, $length);
        return self::wrapPublicKey($public, $type);
    }
}<?php

/**
 * XML Formatted EC Key Handler
 *
 * More info:
 *
 * https://www.w3.org/TR/xmldsig-core/#sec-ECKeyValue
 * http://en.wikipedia.org/wiki/XML_Signature
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Crypt\EC\BaseCurves\Prime as PrimeCurve;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedCurveException;
/**
 * XML Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class XML
{
    use Common;
    /**
     * Default namespace
     *
     * @var string
     */
    private static $namespace;
    /**
     * Flag for using RFC4050 syntax
     *
     * @var bool
     */
    private static $rfc4050 = false;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        $use_errors = libxml_use_internal_errors(true);
        $temp = self::isolateNamespace($key, 'http://www.w3.org/2009/xmldsig11#');
        if ($temp) {
            $key = $temp;
        }
        $temp = self::isolateNamespace($key, 'http://www.w3.org/2001/04/xmldsig-more#');
        if ($temp) {
            $key = $temp;
        }
        $dom = new \DOMDocument();
        if (\Phabel\Target\Php80\Polyfill::substr($key, 0, 5) != '<?xml') {
            $key = '<xml>' . $key . '</xml>';
        }
        if (!$dom->loadXML($key)) {
            libxml_use_internal_errors($use_errors);
            throw new \UnexpectedValueException('Key does not appear to contain XML');
        }
        $xpath = new \DOMXPath($dom);
        libxml_use_internal_errors($use_errors);
        $curve = self::loadCurveByParam($xpath);
        $pubkey = self::query($xpath, 'publickey', 'Public Key is not present');
        $QA = self::query($xpath, 'ecdsakeyvalue')->length ? self::extractPointRFC4050($xpath, $curve) : self::extractPoint("\x00" . $pubkey, $curve);
        libxml_use_internal_errors($use_errors);
        return compact('curve', 'QA');
    }
    /**
     * Case-insensitive xpath query
     *
     * @param \DOMXPath $xpath
     * @param string $name
     * @param string $error optional
     * @param bool $decode optional
     * @return \DOMNodeList
     */
    private static function query($xpath, $name, $error = null, $decode = true)
    {
        $query = '/';
        $names = explode('/', $name);
        foreach ($names as $name) {
            $query .= "/*[translate(local-name(), 'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='{$name}']";
        }
        $result = $xpath->query($query);
        if (!isset($error)) {
            return $result;
        }
        if (!$result->length) {
            throw new \RuntimeException($error);
        }
        return $decode ? self::decodeValue($result->item(0)->textContent) : $result->item(0)->textContent;
    }
    /**
     * Finds the first element in the relevant namespace, strips the namespacing and returns the XML for that element.
     *
     * @param string $xml
     * @param string $ns
     */
    private static function isolateNamespace($xml, $ns)
    {
        $dom = new \DOMDocument();
        if (!$dom->loadXML($xml)) {
            return false;
        }
        $xpath = new \DOMXPath($dom);
        $nodes = $xpath->query("//*[namespace::*[.='{$ns}'] and not(../namespace::*[.='{$ns}'])]");
        if (!$nodes->length) {
            return false;
        }
        $node = $nodes->item(0);
        $ns_name = $node->lookupPrefix($ns);
        $node->removeAttributeNS($ns, $ns_name);
        return $dom->saveXML($node);
    }
    /**
     * Decodes the value
     *
     * @param string $value
     */
    private static function decodeValue($value)
    {
        return Base64::decode(str_replace(["\r", "\n", ' ', "\t"], '', $value));
    }
    /**
     * Extract points from an XML document
     *
     * @param \DOMXPath $xpath
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @return object[]
     */
    private static function extractPointRFC4050(\DOMXPath $xpath, BaseCurve $curve)
    {
        $x = self::query($xpath, 'publickey/x');
        $y = self::query($xpath, 'publickey/y');
        if (!$x->length || !$x->item(0)->hasAttribute('Value')) {
            throw new \RuntimeException('Public Key / X coordinate not found');
        }
        if (!$y->length || !$y->item(0)->hasAttribute('Value')) {
            throw new \RuntimeException('Public Key / Y coordinate not found');
        }
        $point = [$curve->convertInteger(new BigInteger($x->item(0)->getAttribute('Value'))), $curve->convertInteger(new BigInteger($y->item(0)->getAttribute('Value')))];
        if (!$curve->verifyPoint($point)) {
            throw new \RuntimeException('Unable to verify that point exists on curve');
        }
        return $point;
    }
    /**
    * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based
    on the curve parameters
    *
    * @param \DomXPath $xpath
    * @return (\phpseclib3\Crypt\EC\BaseCurves\Base | false)
    */
    private static function loadCurveByParam(\DOMXPath $xpath)
    {
        $namedCurve = self::query($xpath, 'namedcurve');
        if ($namedCurve->length == 1) {
            $oid = $namedCurve->item(0)->getAttribute('URN');
            $oid = preg_replace('#[^\\d.]#', '', $oid);
            $name = array_search($oid, self::$curveOIDs);
            if ($name === false) {
                throw new UnsupportedCurveException('Curve with OID of ' . $oid . ' is not supported');
            }
            $curve = '\\phpseclib3\\Crypt\\EC\\Curves\\' . $name;
            if (!class_exists($curve)) {
                throw new UnsupportedCurveException('Named Curve of ' . $name . ' is not supported');
            }
            return new $curve();
        }
        $params = self::query($xpath, 'explicitparams');
        if ($params->length) {
            return self::loadCurveByParamRFC4050($xpath);
        }
        $params = self::query($xpath, 'ecparameters');
        if (!$params->length) {
            throw new \RuntimeException('No parameters are present');
        }
        $fieldTypes = ['prime-field' => ['fieldid/prime/p'], 'gnb' => ['fieldid/gnb/m'], 'tnb' => ['fieldid/tnb/k'], 'pnb' => ['fieldid/pnb/k1', 'fieldid/pnb/k2', 'fieldid/pnb/k3'], 'unknown' => []];
        foreach ($fieldTypes as $type => $queries) {
            foreach ($queries as $query) {
                $result = self::query($xpath, $query);
                if (!$result->length) {
                    continue 2;
                }
                $param = preg_replace('#.*/#', '', $query);
                ${$param} = self::decodeValue($result->item(0)->textContent);
            }
            break;
        }
        $a = self::query($xpath, 'curve/a', 'A coefficient is not present');
        $b = self::query($xpath, 'curve/b', 'B coefficient is not present');
        $base = self::query($xpath, 'base', 'Base point is not present');
        $order = self::query($xpath, 'order', 'Order is not present');
        switch ($type) {
            case 'prime-field':
                $curve = new PrimeCurve();
                $curve->setModulo(new BigInteger($p, 256));
                $curve->setCoefficients(new BigInteger($a, 256), new BigInteger($b, 256));
                $point = self::extractPoint("\x00" . $base, $curve);
                $curve->setBasePoint(...$point);
                $curve->setOrder(new BigInteger($order, 256));
                return $curve;
            case 'gnb':
            case 'tnb':
            case 'pnb':
            default:
                throw new UnsupportedCurveException('Field Type of ' . $type . ' is not supported');
        }
    }
    /**
    * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based
    on the curve parameters
    *
    * @param \DomXPath $xpath
    * @return (\phpseclib3\Crypt\EC\BaseCurves\Base | false)
    */
    private static function loadCurveByParamRFC4050(\DOMXPath $xpath)
    {
        $fieldTypes = ['prime-field' => ['primefieldparamstype/p'], 'unknown' => []];
        foreach ($fieldTypes as $type => $queries) {
            foreach ($queries as $query) {
                $result = self::query($xpath, $query);
                if (!$result->length) {
                    continue 2;
                }
                $param = preg_replace('#.*/#', '', $query);
                ${$param} = $result->item(0)->textContent;
            }
            break;
        }
        $a = self::query($xpath, 'curveparamstype/a', 'A coefficient is not present', false);
        $b = self::query($xpath, 'curveparamstype/b', 'B coefficient is not present', false);
        $x = self::query($xpath, 'basepointparams/basepoint/ecpointtype/x', 'Base Point X is not present', false);
        $y = self::query($xpath, 'basepointparams/basepoint/ecpointtype/y', 'Base Point Y is not present', false);
        $order = self::query($xpath, 'order', 'Order is not present', false);
        switch ($type) {
            case 'prime-field':
                $curve = new PrimeCurve();
                $p = str_replace(["\r", "\n", ' ', "\t"], '', $p);
                $curve->setModulo(new BigInteger($p));
                $a = str_replace(["\r", "\n", ' ', "\t"], '', $a);
                $b = str_replace(["\r", "\n", ' ', "\t"], '', $b);
                $curve->setCoefficients(new BigInteger($a), new BigInteger($b));
                $x = str_replace(["\r", "\n", ' ', "\t"], '', $x);
                $y = str_replace(["\r", "\n", ' ', "\t"], '', $y);
                $curve->setBasePoint(new BigInteger($x), new BigInteger($y));
                $order = str_replace(["\r", "\n", ' ', "\t"], '', $order);
                $curve->setOrder(new BigInteger($order));
                return $curve;
            default:
                throw new UnsupportedCurveException('Field Type of ' . $type . ' is not supported');
        }
    }
    /**
     * Sets the namespace. dsig11 is the most common one.
     *
     * Set to null to unset. Used only for creating public keys.
     *
     * @param string $namespace
     */
    public static function setNamespace($namespace)
    {
        self::$namespace = $namespace;
    }
    /**
     * Uses the XML syntax specified in https://tools.ietf.org/html/rfc4050
     */
    public static function enableRFC4050Syntax()
    {
        self::$rfc4050 = true;
    }
    /**
     * Uses the XML syntax specified in https://www.w3.org/TR/xmldsig-core/#sec-ECParameters
     */
    public static function disableRFC4050Syntax()
    {
        self::$rfc4050 = false;
    }
    /**
     * Convert a public key to the appropriate format
     *
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
    {
        self::initialize_static_variables();
        if ($curve instanceof TwistedEdwardsCurve || $curve instanceof MontgomeryCurve) {
            throw new UnsupportedCurveException('TwistedEdwards and Montgomery Curves are not supported');
        }
        if (empty(static::$namespace)) {
            $pre = $post = '';
        } else {
            $pre = static::$namespace . ':';
            $post = ':' . static::$namespace;
        }
        if (self::$rfc4050) {
            return '<' . $pre . 'ECDSAKeyValue xmlns' . $post . '="http://www.w3.org/2001/04/xmldsig-more#">
' . self::encodeXMLParameters($curve, $pre, $options) . '
<' . $pre . 'PublicKey>
<' . $pre . 'X Value="' . $publicKey[0] . '" />
<' . $pre . 'Y Value="' . $publicKey[1] . '" />
</' . $pre . 'PublicKey>
</' . $pre . 'ECDSAKeyValue>';
        }
        $publicKey = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        return '<' . $pre . 'ECDSAKeyValue xmlns' . $post . '="http://www.w3.org/2009/xmldsig11#">
' . self::encodeXMLParameters($curve, $pre, $options) . '
<' . $pre . 'PublicKey>' . Base64::encode($publicKey) . '</' . $pre . 'PublicKey>
</' . $pre . 'ECDSAKeyValue>';
    }
    /**
     * Encode Parameters
     *
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param string $pre
     * @param array $options optional
     * @return (string | false)
     */
    private static function encodeXMLParameters(BaseCurve $curve, $pre, array $options = [])
    {
        $result = self::encodeParameters($curve, true, $options);
        if (isset($result['namedCurve'])) {
            $namedCurve = '<' . $pre . 'NamedCurve URI="urn:oid:' . self::$curveOIDs[$result['namedCurve']] . '" />';
            return self::$rfc4050 ? '<DomainParameters>' . str_replace('URI', 'URN', $namedCurve) . '</DomainParameters>' : $namedCurve;
        }
        if (self::$rfc4050) {
            $xml = '<' . $pre . 'ExplicitParams>
<' . $pre . 'FieldParams>
';
            $temp = $result['specifiedCurve'];
            switch ($temp['fieldID']['fieldType']) {
                case 'prime-field':
                    $xml .= '<' . $pre . 'PrimeFieldParamsType>
<' . $pre . 'P>' . $temp['fieldID']['parameters'] . '</' . $pre . 'P>
</' . $pre . 'PrimeFieldParamsType>
';
                    $a = $curve->getA();
                    $b = $curve->getB();
                    list($x, $y) = $curve->getBasePoint();
                    break;
                default:
                    throw new UnsupportedCurveException('Field Type of ' . $temp['fieldID']['fieldType'] . ' is not supported');
            }
            $xml .= '</' . $pre . 'FieldParams>
<' . $pre . 'CurveParamsType>
<' . $pre . 'A>' . $a . '</' . $pre . 'A>
<' . $pre . 'B>' . $b . '</' . $pre . 'B>
</' . $pre . 'CurveParamsType>
<' . $pre . 'BasePointParams>
<' . $pre . 'BasePoint>
<' . $pre . 'ECPointType>
<' . $pre . 'X>' . $x . '</' . $pre . 'X>
<' . $pre . 'Y>' . $y . '</' . $pre . 'Y>
</' . $pre . 'ECPointType>
</' . $pre . 'BasePoint>
<' . $pre . 'Order>' . $curve->getOrder() . '</' . $pre . 'Order>
</' . $pre . 'BasePointParams>
</' . $pre . 'ExplicitParams>
';
            return $xml;
        }
        if (isset($result['specifiedCurve'])) {
            $xml = '<' . $pre . 'ECParameters>
<' . $pre . 'FieldID>
';
            $temp = $result['specifiedCurve'];
            switch ($temp['fieldID']['fieldType']) {
                case 'prime-field':
                    $xml .= '<' . $pre . 'Prime>
<' . $pre . 'P>' . Base64::encode($temp['fieldID']['parameters']->toBytes()) . '</' . $pre . 'P>
</' . $pre . 'Prime>
';
                    break;
                default:
                    throw new UnsupportedCurveException('Field Type of ' . $temp['fieldID']['fieldType'] . ' is not supported');
            }
            $xml .= '</' . $pre . 'FieldID>
<' . $pre . 'Curve>
<' . $pre . 'A>' . Base64::encode($temp['curve']['a']) . '</' . $pre . 'A>
<' . $pre . 'B>' . Base64::encode($temp['curve']['b']) . '</' . $pre . 'B>
</' . $pre . 'Curve>
<' . $pre . 'Base>' . Base64::encode($temp['base']) . '</' . $pre . 'Base>
<' . $pre . 'Order>' . Base64::encode($temp['order']) . '</' . $pre . 'Order>
</' . $pre . 'ECParameters>';
            return $xml;
        }
    }
}<?php

/**
 * OpenSSH Formatted EC Key Handler
 *
 * PHP version 5
 *
 * Place in $HOME/.ssh/authorized_keys
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\Formats\Keys\OpenSSH as Progenitor;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Crypt\EC\Curves\Ed25519;
/**
 * OpenSSH Formatted EC Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSH extends Progenitor
{
    use Common;
    /**
     * Supported Key Types
     *
     * @var array
     */
    protected static $types = ['ecdsa-sha2-nistp256', 'ecdsa-sha2-nistp384', 'ecdsa-sha2-nistp521', 'ssh-ed25519'];
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        $parsed = parent::load($key, $password);
        if (isset($parsed['paddedKey'])) {
            $paddedKey = $parsed['paddedKey'];
            list($type) = Strings::unpackSSH2('s', $paddedKey);
            if ($type != $parsed['type']) {
                throw new \RuntimeException("The public and private keys are not of the same type ({$type} vs {$parsed['type']})");
            }
            if ($type == 'ssh-ed25519') {
                list(, $key, $comment) = Strings::unpackSSH2('sss', $paddedKey);
                $key = libsodium::load($key);
                $key['comment'] = $comment;
                return $key;
            }
            list($curveName, $publicKey, $privateKey, $comment) = Strings::unpackSSH2('ssis', $paddedKey);
            $curve = self::loadCurveByParam(['namedCurve' => $curveName]);
            $curve->rangeCheck($privateKey);
            return ['curve' => $curve, 'dA' => $privateKey, 'QA' => self::extractPoint("\x00{$publicKey}", $curve), 'comment' => $comment];
        }
        if ($parsed['type'] == 'ssh-ed25519') {
            if (Strings::shift($parsed['publicKey'], 4) != "\x00\x00\x00 ") {
                throw new \RuntimeException('Length of ssh-ed25519 key should be 32');
            }
            $curve = new Ed25519();
            $qa = self::extractPoint($parsed['publicKey'], $curve);
        } else {
            list($curveName, $publicKey) = Strings::unpackSSH2('ss', $parsed['publicKey']);
            $curveName = '\\phpseclib3\\Crypt\\EC\\Curves\\' . $curveName;
            $curve = new $curveName();
            $qa = self::extractPoint("\x00" . $publicKey, $curve);
        }
        return ['curve' => $curve, 'QA' => $qa, 'comment' => $parsed['comment']];
    }
    /**
     * Returns the alias that corresponds to a curve
     *
     * @return string
     */
    private static function getAlias(BaseCurve $curve)
    {
        self::initialize_static_variables();
        $reflect = new \ReflectionClass($curve);
        $name = $reflect->getShortName();
        $oid = self::$curveOIDs[$name];
        $aliases = array_filter(self::$curveOIDs, function ($v) use($oid) {
            return $v == $oid;
        });
        $aliases = array_keys($aliases);
        for ($i = 0; $i < count($aliases); $i++) {
            if (in_array('ecdsa-sha2-' . $aliases[$i], self::$types)) {
                $alias = $aliases[$i];
                break;
            }
        }
        if (!isset($alias)) {
            throw new UnsupportedCurveException($name . ' is not a curve that the OpenSSH plugin supports');
        }
        return $alias;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param array $options optional
     * @return string
     */
    public static function savePublicKey(BaseCurve $curve, array $publicKey, array $options = [])
    {
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        if ($curve instanceof Ed25519) {
            $key = Strings::packSSH2('ss', 'ssh-ed25519', $curve->encodePoint($publicKey));
            if (isset($options['binary']) ? $options['binary'] : self::$binary) {
                return $key;
            }
            $key = 'ssh-ed25519 ' . base64_encode($key) . ' ' . $comment;
            return $key;
        }
        $alias = self::getAlias($curve);
        $points = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        $key = Strings::packSSH2('sss', 'ecdsa-sha2-' . $alias, $alias, $points);
        if (isset($options['binary']) ? $options['binary'] : self::$binary) {
            return $key;
        }
        $key = 'ecdsa-sha2-' . $alias . ' ' . base64_encode($key) . ' ' . $comment;
        return $key;
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\Curves\Ed25519 $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @param array $options optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, BaseCurve $curve, array $publicKey, $password = '', array $options = [])
    {
        if ($curve instanceof Ed25519) {
            if (!isset($privateKey->secret)) {
                throw new \RuntimeException('Private Key does not have a secret set');
            }
            if (strlen($privateKey->secret) != 32) {
                throw new \RuntimeException('Private Key secret is not of the correct length');
            }
            $pubKey = $curve->encodePoint($publicKey);
            $publicKey = Strings::packSSH2('ss', 'ssh-ed25519', $pubKey);
            $privateKey = Strings::packSSH2('sss', 'ssh-ed25519', $pubKey, $privateKey->secret . $pubKey);
            return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
        }
        $alias = self::getAlias($curve);
        $points = "\x04" . $publicKey[0]->toBytes() . $publicKey[1]->toBytes();
        $publicKey = self::savePublicKey($curve, $publicKey, ['binary' => true]);
        $privateKey = Strings::packSSH2('sssi', 'ecdsa-sha2-' . $alias, $alias, $points, $privateKey);
        return self::wrapPrivateKey($publicKey, $privateKey, $password, $options);
    }
}<?php

/**
 * Generic EC Key Parsing Helper functions
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Crypt\EC\BaseCurves\Base as BaseCurve;
use phpseclib3\Crypt\EC\BaseCurves\Prime as PrimeCurve;
use phpseclib3\Crypt\EC\BaseCurves\Binary as BinaryCurve;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\PrimeField;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Exception\UnsupportedCurveException;
/**
 * Generic EC Key Parsing Helper functions
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
trait Common
{
    /**
     * Curve OIDs
     *
     * @var array
     */
    private static $curveOIDs = [];
    /**
     * Child OIDs loaded
     *
     * @var bool
     */
    protected static $childOIDsLoaded = false;
    /**
     * Use Named Curves
     *
     * @var bool
     */
    private static $useNamedCurves = true;
    /**
     * Initialize static variables
     */
    private static function initialize_static_variables()
    {
        if (empty(self::$curveOIDs)) {
            // the sec* curves are from the standards for efficient cryptography group
            // sect* curves are curves over binary finite fields
            // secp* curves are curves over prime finite fields
            // sec*r* curves are regular curves; sec*k* curves are koblitz curves
            // brainpool*r* curves are regular prime finite field curves
            // brainpool*t* curves are twisted versions of the brainpool*r* curves
            self::$curveOIDs = [
                'prime192v1' => '1.2.840.10045.3.1.1',
                // J.5.1, example 1 (aka secp192r1)
                'prime192v2' => '1.2.840.10045.3.1.2',
                // J.5.1, example 2
                'prime192v3' => '1.2.840.10045.3.1.3',
                // J.5.1, example 3
                'prime239v1' => '1.2.840.10045.3.1.4',
                // J.5.2, example 1
                'prime239v2' => '1.2.840.10045.3.1.5',
                // J.5.2, example 2
                'prime239v3' => '1.2.840.10045.3.1.6',
                // J.5.2, example 3
                'prime256v1' => '1.2.840.10045.3.1.7',
                // J.5.3, example 1 (aka secp256r1)
                // https://tools.ietf.org/html/rfc5656#section-10
                'nistp256' => '1.2.840.10045.3.1.7',
                // aka secp256r1
                'nistp384' => '1.3.132.0.34',
                // aka secp384r1
                'nistp521' => '1.3.132.0.35',
                // aka secp521r1
                'nistk163' => '1.3.132.0.1',
                // aka sect163k1
                'nistp192' => '1.2.840.10045.3.1.1',
                // aka secp192r1
                'nistp224' => '1.3.132.0.33',
                // aka secp224r1
                'nistk233' => '1.3.132.0.26',
                // aka sect233k1
                'nistb233' => '1.3.132.0.27',
                // aka sect233r1
                'nistk283' => '1.3.132.0.16',
                // aka sect283k1
                'nistk409' => '1.3.132.0.36',
                // aka sect409k1
                'nistb409' => '1.3.132.0.37',
                // aka sect409r1
                'nistt571' => '1.3.132.0.38',
                // aka sect571k1
                // from https://tools.ietf.org/html/rfc5915
                'secp192r1' => '1.2.840.10045.3.1.1',
                // aka prime192v1
                'sect163k1' => '1.3.132.0.1',
                'sect163r2' => '1.3.132.0.15',
                'secp224r1' => '1.3.132.0.33',
                'sect233k1' => '1.3.132.0.26',
                'sect233r1' => '1.3.132.0.27',
                'secp256r1' => '1.2.840.10045.3.1.7',
                // aka prime256v1
                'sect283k1' => '1.3.132.0.16',
                'sect283r1' => '1.3.132.0.17',
                'secp384r1' => '1.3.132.0.34',
                'sect409k1' => '1.3.132.0.36',
                'sect409r1' => '1.3.132.0.37',
                'secp521r1' => '1.3.132.0.35',
                'sect571k1' => '1.3.132.0.38',
                'sect571r1' => '1.3.132.0.39',
                // from http://www.secg.org/SEC2-Ver-1.0.pdf
                'secp112r1' => '1.3.132.0.6',
                'secp112r2' => '1.3.132.0.7',
                'secp128r1' => '1.3.132.0.28',
                'secp128r2' => '1.3.132.0.29',
                'secp160k1' => '1.3.132.0.9',
                'secp160r1' => '1.3.132.0.8',
                'secp160r2' => '1.3.132.0.30',
                'secp192k1' => '1.3.132.0.31',
                'secp224k1' => '1.3.132.0.32',
                'secp256k1' => '1.3.132.0.10',
                'sect113r1' => '1.3.132.0.4',
                'sect113r2' => '1.3.132.0.5',
                'sect131r1' => '1.3.132.0.22',
                'sect131r2' => '1.3.132.0.23',
                'sect163r1' => '1.3.132.0.2',
                'sect193r1' => '1.3.132.0.24',
                'sect193r2' => '1.3.132.0.25',
                'sect239k1' => '1.3.132.0.3',
                // from http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.202.2977&rep=rep1&type=pdf#page=36
                /*
                'c2pnb163v1' => '1.2.840.10045.3.0.1', // J.4.1, example 1
                'c2pnb163v2' => '1.2.840.10045.3.0.2', // J.4.1, example 2
                'c2pnb163v3' => '1.2.840.10045.3.0.3', // J.4.1, example 3
                'c2pnb172w1' => '1.2.840.10045.3.0.4', // J.4.2, example 1
                'c2tnb191v1' => '1.2.840.10045.3.0.5', // J.4.3, example 1
                'c2tnb191v2' => '1.2.840.10045.3.0.6', // J.4.3, example 2
                'c2tnb191v3' => '1.2.840.10045.3.0.7', // J.4.3, example 3
                'c2onb191v4' => '1.2.840.10045.3.0.8', // J.4.3, example 4
                'c2onb191v5' => '1.2.840.10045.3.0.9', // J.4.3, example 5
                'c2pnb208w1' => '1.2.840.10045.3.0.10', // J.4.4, example 1
                'c2tnb239v1' => '1.2.840.10045.3.0.11', // J.4.5, example 1
                'c2tnb239v2' => '1.2.840.10045.3.0.12', // J.4.5, example 2
                'c2tnb239v3' => '1.2.840.10045.3.0.13', // J.4.5, example 3
                'c2onb239v4' => '1.2.840.10045.3.0.14', // J.4.5, example 4
                'c2onb239v5' => '1.2.840.10045.3.0.15', // J.4.5, example 5
                'c2pnb272w1' => '1.2.840.10045.3.0.16', // J.4.6, example 1
                'c2pnb304w1' => '1.2.840.10045.3.0.17', // J.4.7, example 1
                'c2tnb359v1' => '1.2.840.10045.3.0.18', // J.4.8, example 1
                'c2pnb368w1' => '1.2.840.10045.3.0.19', // J.4.9, example 1
                'c2tnb431r1' => '1.2.840.10045.3.0.20', // J.4.10, example 1
                */
                // http://www.ecc-brainpool.org/download/Domain-parameters.pdf
                // https://tools.ietf.org/html/rfc5639
                'brainpoolP160r1' => '1.3.36.3.3.2.8.1.1.1',
                'brainpoolP160t1' => '1.3.36.3.3.2.8.1.1.2',
                'brainpoolP192r1' => '1.3.36.3.3.2.8.1.1.3',
                'brainpoolP192t1' => '1.3.36.3.3.2.8.1.1.4',
                'brainpoolP224r1' => '1.3.36.3.3.2.8.1.1.5',
                'brainpoolP224t1' => '1.3.36.3.3.2.8.1.1.6',
                'brainpoolP256r1' => '1.3.36.3.3.2.8.1.1.7',
                'brainpoolP256t1' => '1.3.36.3.3.2.8.1.1.8',
                'brainpoolP320r1' => '1.3.36.3.3.2.8.1.1.9',
                'brainpoolP320t1' => '1.3.36.3.3.2.8.1.1.10',
                'brainpoolP384r1' => '1.3.36.3.3.2.8.1.1.11',
                'brainpoolP384t1' => '1.3.36.3.3.2.8.1.1.12',
                'brainpoolP512r1' => '1.3.36.3.3.2.8.1.1.13',
                'brainpoolP512t1' => '1.3.36.3.3.2.8.1.1.14',
            ];
            ASN1::loadOIDs([
                'prime-field' => '1.2.840.10045.1.1',
                'characteristic-two-field' => '1.2.840.10045.1.2',
                'characteristic-two-basis' => '1.2.840.10045.1.2.3',
                // per http://www.secg.org/SEC1-Ver-1.0.pdf#page=84, gnBasis "not used here"
                'gnBasis' => '1.2.840.10045.1.2.3.1',
                // NULL
                'tpBasis' => '1.2.840.10045.1.2.3.2',
                // Trinomial
                'ppBasis' => '1.2.840.10045.1.2.3.3',
            ] + self::$curveOIDs);
        }
    }
    /**
    * Explicitly set the curve
    *
    * If the key contains an implicit curve phpseclib needs the curve
    to be explicitly provided
    *
    * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
    */
    public static function setImplicitCurve(BaseCurve $curve)
    {
        self::$implicitCurve = $curve;
    }
    /**
    * Returns an instance of \phpseclib3\Crypt\EC\BaseCurves\Base based
    on the curve parameters
    *
    * @param array $params
    * @return (\phpseclib3\Crypt\EC\BaseCurves\Base | false)
    */
    protected static function loadCurveByParam(array $params)
    {
        if (count($params) > 1) {
            throw new \RuntimeException('No parameters are present');
        }
        if (isset($params['namedCurve'])) {
            $curve = '\\phpseclib3\\Crypt\\EC\\Curves\\' . $params['namedCurve'];
            if (!class_exists($curve)) {
                throw new UnsupportedCurveException('Named Curve of ' . $params['namedCurve'] . ' is not supported');
            }
            return new $curve();
        }
        if (isset($params['implicitCurve'])) {
            if (!isset(self::$implicitCurve)) {
                throw new \RuntimeException('Implicit curves can be provided by calling setImplicitCurve');
            }
            return self::$implicitCurve;
        }
        if (isset($params['specifiedCurve'])) {
            $data = $params['specifiedCurve'];
            switch ($data['fieldID']['fieldType']) {
                case 'prime-field':
                    $curve = new PrimeCurve();
                    $curve->setModulo($data['fieldID']['parameters']);
                    $curve->setCoefficients(new BigInteger($data['curve']['a'], 256), new BigInteger($data['curve']['b'], 256));
                    $point = self::extractPoint("\x00" . $data['base'], $curve);
                    $curve->setBasePoint(...$point);
                    $curve->setOrder($data['order']);
                    return $curve;
                case 'characteristic-two-field':
                    $curve = new BinaryCurve();
                    $params = ASN1::decodeBER($data['fieldID']['parameters']);
                    $params = ASN1::asn1map($params[0], Maps\Characteristic_two::MAP);
                    $modulo = [(int) $params['m']->toString()];
                    switch ($params['basis']) {
                        case 'tpBasis':
                            $modulo[] = (int) $params['parameters']->toString();
                            break;
                        case 'ppBasis':
                            $temp = ASN1::decodeBER($params['parameters']);
                            $temp = ASN1::asn1map($temp[0], Maps\Pentanomial::MAP);
                            $modulo[] = (int) $temp['k3']->toString();
                            $modulo[] = (int) $temp['k2']->toString();
                            $modulo[] = (int) $temp['k1']->toString();
                    }
                    $modulo[] = 0;
                    $curve->setModulo(...$modulo);
                    $len = ceil($modulo[0] / 8);
                    $curve->setCoefficients(Hex::encode($data['curve']['a']), Hex::encode($data['curve']['b']));
                    $point = self::extractPoint("\x00" . $data['base'], $curve);
                    $curve->setBasePoint(...$point);
                    $curve->setOrder($data['order']);
                    return $curve;
                default:
                    throw new UnsupportedCurveException('Field Type of ' . $data['fieldID']['fieldType'] . ' is not supported');
            }
        }
        throw new \RuntimeException('No valid parameters are present');
    }
    /**
     * Extract points from a string
     *
     * Supports both compressed and uncompressed points
     *
     * @param string $str
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @return object[]
     */
    public static function extractPoint($str, BaseCurve $curve)
    {
        if ($curve instanceof TwistedEdwardsCurve) {
            // first step of point deciding as discussed at the following URL's:
            // https://tools.ietf.org/html/rfc8032#section-5.1.3
            // https://tools.ietf.org/html/rfc8032#section-5.2.3
            $y = $str;
            $y = strrev($y);
            $sign = (bool) (ord($y[0]) & 0x80);
            $y[0] = $y[0] & chr(0x7f);
            $y = new BigInteger($y, 256);
            if ($y->compare($curve->getModulo()) >= 0) {
                throw new \RuntimeException('The Y coordinate should not be >= the modulo');
            }
            $point = $curve->recoverX($y, $sign);
            if (!$curve->verifyPoint($point)) {
                throw new \RuntimeException('Unable to verify that point exists on curve');
            }
            return $point;
        }
        // the first byte of a bit string represents the number of bits in the last byte that are to be ignored but,
        // currently, bit strings wanting a non-zero amount of bits trimmed are not supported
        if (($val = Strings::shift($str)) != "\x00") {
            throw new \UnexpectedValueException('extractPoint expects the first byte to be null - not ' . Hex::encode($val));
        }
        if ($str == "\x00") {
            return [];
        }
        $keylen = strlen($str);
        $order = $curve->getLengthInBytes();
        // point compression is being used
        if ($keylen == $order + 1) {
            return $curve->derivePoint($str);
        }
        // point compression is not being used
        if ($keylen == 2 * $order + 1) {
            preg_match("#(.)(.{{$order}})(.{{$order}})#s", $str, $matches);
            list(, $w, $x, $y) = $matches;
            if ($w != "\x04") {
                throw new \UnexpectedValueException('The first byte of an uncompressed point should be 04 - not ' . Hex::encode($val));
            }
            $point = [$curve->convertInteger(new BigInteger($x, 256)), $curve->convertInteger(new BigInteger($y, 256))];
            if (!$curve->verifyPoint($point)) {
                throw new \RuntimeException('Unable to verify that point exists on curve');
            }
            return $point;
        }
        throw new \UnexpectedValueException('The string representation of the points is not of an appropriate length');
    }
    /**
     * Encode Parameters
     *
     * @todo Maybe at some point this could be moved to __toString() for each of the curves?
     * @param \phpseclib3\Crypt\EC\BaseCurves\Base $curve
     * @param bool $returnArray optional
     * @param array $options optional
     * @return (string | false)
     */
    private static function encodeParameters(BaseCurve $curve, $returnArray = false, array $options = [])
    {
        $useNamedCurves = isset($options['namedCurve']) ? $options['namedCurve'] : self::$useNamedCurves;
        $reflect = new \ReflectionClass($curve);
        $name = $reflect->getShortName();
        if ($useNamedCurves) {
            if (isset(self::$curveOIDs[$name])) {
                if ($reflect->isFinal()) {
                    $reflect = $reflect->getParentClass();
                    $name = $reflect->getShortName();
                }
                return $returnArray ? ['namedCurve' => $name] : ASN1::encodeDER(['namedCurve' => $name], Maps\ECParameters::MAP);
            }
            foreach (new \DirectoryIterator(__DIR__ . '/../../Curves/') as $file) {
                if ($file->getExtension() != 'php') {
                    continue;
                }
                $testName = $file->getBasename('.php');
                $class = 'phpseclib3\\Crypt\\EC\\Curves\\' . $testName;
                $reflect = new \ReflectionClass($class);
                if ($reflect->isFinal()) {
                    continue;
                }
                $candidate = new $class();
                switch ($name) {
                    case 'Prime':
                        if (!$candidate instanceof PrimeCurve) {
                            break;
                        }
                        if (!$candidate->getModulo()->equals($curve->getModulo())) {
                            break;
                        }
                        if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) {
                            break;
                        }
                        if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) {
                            break;
                        }
                        list($candidateX, $candidateY) = $candidate->getBasePoint();
                        list($curveX, $curveY) = $curve->getBasePoint();
                        if ($candidateX->toBytes() != $curveX->toBytes()) {
                            break;
                        }
                        if ($candidateY->toBytes() != $curveY->toBytes()) {
                            break;
                        }
                        return $returnArray ? ['namedCurve' => $testName] : ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP);
                    case 'Binary':
                        if (!$candidate instanceof BinaryCurve) {
                            break;
                        }
                        if ($candidate->getModulo() != $curve->getModulo()) {
                            break;
                        }
                        if ($candidate->getA()->toBytes() != $curve->getA()->toBytes()) {
                            break;
                        }
                        if ($candidate->getB()->toBytes() != $curve->getB()->toBytes()) {
                            break;
                        }
                        list($candidateX, $candidateY) = $candidate->getBasePoint();
                        list($curveX, $curveY) = $curve->getBasePoint();
                        if ($candidateX->toBytes() != $curveX->toBytes()) {
                            break;
                        }
                        if ($candidateY->toBytes() != $curveY->toBytes()) {
                            break;
                        }
                        return $returnArray ? ['namedCurve' => $testName] : ASN1::encodeDER(['namedCurve' => $testName], Maps\ECParameters::MAP);
                }
            }
        }
        $order = $curve->getOrder();
        // we could try to calculate the order thusly:
        // https://crypto.stackexchange.com/a/27914/4520
        // https://en.wikipedia.org/wiki/Schoof%E2%80%93Elkies%E2%80%93Atkin_algorithm
        if (!$order) {
            throw new \RuntimeException('Specified Curves need the order to be specified');
        }
        $point = $curve->getBasePoint();
        $x = $point[0]->toBytes();
        $y = $point[1]->toBytes();
        if ($curve instanceof PrimeCurve) {
            /*
             * valid versions are:
             *
             * ecdpVer1:
             *   - neither the curve or the base point are generated verifiably randomly.
             * ecdpVer2:
             *   - curve and base point are generated verifiably at random and curve.seed is present
             * ecdpVer3:
             *   - base point is generated verifiably at random but curve is not. curve.seed is present
             */
            // other (optional) parameters can be calculated using the methods discused at
            // https://crypto.stackexchange.com/q/28947/4520
            $data = ['version' => 'ecdpVer1', 'fieldID' => ['fieldType' => 'prime-field', 'parameters' => $curve->getModulo()], 'curve' => ['a' => $curve->getA()->toBytes(), 'b' => $curve->getB()->toBytes()], 'base' => "\x04" . $x . $y, 'order' => $order];
            return $returnArray ? ['specifiedCurve' => $data] : ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP);
        }
        if ($curve instanceof BinaryCurve) {
            $modulo = $curve->getModulo();
            $basis = count($modulo);
            $m = array_shift($modulo);
            array_pop($modulo);
            // the last parameter should always be 0
            //rsort($modulo);
            switch ($basis) {
                case 3:
                    $basis = 'tpBasis';
                    $modulo = new BigInteger($modulo[0]);
                    break;
                case 5:
                    $basis = 'ppBasis';
                    // these should be in strictly ascending order (hence the commented out rsort above)
                    $modulo = ['k1' => new BigInteger($modulo[2]), 'k2' => new BigInteger($modulo[1]), 'k3' => new BigInteger($modulo[0])];
                    $modulo = ASN1::encodeDER($modulo, Maps\Pentanomial::MAP);
                    $modulo = new ASN1\Element($modulo);
            }
            $params = ASN1::encodeDER(['m' => new BigInteger($m), 'basis' => $basis, 'parameters' => $modulo], Maps\Characteristic_two::MAP);
            $params = new ASN1\Element($params);
            $a = ltrim($curve->getA()->toBytes(), "\x00");
            if (!strlen($a)) {
                $a = "\x00";
            }
            $b = ltrim($curve->getB()->toBytes(), "\x00");
            if (!strlen($b)) {
                $b = "\x00";
            }
            $data = ['version' => 'ecdpVer1', 'fieldID' => ['fieldType' => 'characteristic-two-field', 'parameters' => $params], 'curve' => ['a' => $a, 'b' => $b], 'base' => "\x04" . $x . $y, 'order' => $order];
            return $returnArray ? ['specifiedCurve' => $data] : ASN1::encodeDER(['specifiedCurve' => $data], Maps\ECParameters::MAP);
        }
        throw new UnsupportedCurveException('Curve cannot be serialized');
    }
    /**
    * Use Specified Curve
    *
    * A specified curve has all the coefficients, the base points, etc, explicitely included.
    A specified curve is a more verbose way of representing a curve
    */
    public static function useSpecifiedCurve()
    {
        self::$useNamedCurves = false;
    }
    /**
    * Use Named Curve
    *
    * A named curve does not include any parameters. It is up to the EC parameters to
    know what the coefficients, the base points, etc, are from the name of the curve.
    A named curve is a more concise way of representing a curve
    */
    public static function useNamedCurve()
    {
        self::$useNamedCurves = true;
    }
}<?php

/**
 * Montgomery Private Key Handler
 *
 * "Naked" Curve25519 private keys can pretty much be any sequence of random 32x bytes so unless
 * we have a "hidden" key handler pretty much every 32 byte string will be loaded as a curve25519
 * private key even if it probably isn't one by PublicKeyLoader.
 *
 * "Naked" Curve25519 public keys also a string of 32 bytes so distinguishing between a "naked"
 * curve25519 private key and a public key is nigh impossible, hence separate plugins for each
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\Curves\Curve448;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Math\BigInteger;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * Montgomery Curve Private Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MontgomeryPrivate
{
    /**
     * Is invisible flag
     *
     * @access private
     */
    const IS_INVISIBLE = true;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        switch (strlen($key)) {
            case 32:
                $curve = new Curve25519();
                break;
            case 56:
                $curve = new Curve448();
                break;
            default:
                throw new \LengthException('The only supported lengths are 32 and 56');
        }
        $components = ['curve' => $curve];
        $components['dA'] = new BigInteger($key, 256);
        $curve->rangeCheck($components['dA']);
        // note that EC::getEncodedCoordinates does some additional "magic" (it does strrev on the result)
        $components['QA'] = $components['curve']->multiplyPoint($components['curve']->getBasePoint(), $components['dA']);
        return $components;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @return string
     */
    public static function savePublicKey(MontgomeryCurve $curve, array $publicKey)
    {
        return strrev($publicKey[0]->toBytes());
    }
    /**
     * Convert a private key to the appropriate format.
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $privateKey
     * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @param string $password optional
     * @return string
     */
    public static function savePrivateKey(BigInteger $privateKey, MontgomeryCurve $curve, array $publicKey, $password = '')
    {
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('MontgomeryPrivate private keys do not support encryption');
        }
        return $privateKey->toBytes();
    }
}<?php

/**
 * Montgomery Public Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Keys;

use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\Curves\Curve448;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Math\Common\FiniteField\Integer;
use phpseclib3\Math\BigInteger;
/**
 * Montgomery Public Key Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MontgomeryPublic
{
    /**
     * Is invisible flag
     *
     * @access private
     */
    const IS_INVISIBLE = true;
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    public static function load($key, $password = '')
    {
        switch (strlen($key)) {
            case 32:
                $curve = new Curve25519();
                break;
            case 56:
                $curve = new Curve448();
                break;
            default:
                throw new \LengthException('The only supported lengths are 32 and 56');
        }
        $components = ['curve' => $curve];
        $components['QA'] = [$components['curve']->convertInteger(new BigInteger(strrev($key), 256))];
        return $components;
    }
    /**
     * Convert an EC public key to the appropriate format
     *
     * @access public
     * @param \phpseclib3\Crypt\EC\BaseCurves\Montgomery $curve
     * @param \phpseclib3\Math\Common\FiniteField\Integer[] $publicKey
     * @return string
     */
    public static function savePublicKey(MontgomeryCurve $curve, array $publicKey)
    {
        return strrev($publicKey[0]->toBytes());
    }
}<?php

/**
 * ASN1 Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures in the format described in
 * https://tools.ietf.org/html/rfc3279#section-2.2.3
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Signature;

use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1 as Encoder;
use phpseclib3\File\ASN1\Maps\EcdsaSigValue;
/**
 * ASN1 Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ASN1
{
    /**
     * Loads a signature
     *
     * @access public
     * @param string $sig
     * @return array
     */
    public static function load($sig)
    {
        if (!is_string($sig)) {
            return false;
        }
        $decoded = Encoder::decodeBER($sig);
        if (empty($decoded)) {
            return false;
        }
        $components = Encoder::asn1map($decoded[0], EcdsaSigValue::MAP);
        return $components;
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s)
    {
        return Encoder::encodeDER(compact('r', 's'), EcdsaSigValue::MAP);
    }
}<?php

/**
 * Raw EC Signature Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   DSA
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Signature;

use phpseclib3\Crypt\Common\Formats\Signature\Raw as Progenitor;
/**
 * Raw DSA Signature Handler
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw extends Progenitor
{
}<?php

/**
 * SSH2 Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures in the format used by SSH2
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC\Formats\Signature;

use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
/**
 * SSH2 Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SSH2
{
    /**
     * Loads a signature
     *
     * @access public
     * @param string $sig
     * @return mixed
     */
    public static function load($sig)
    {
        if (!is_string($sig)) {
            return false;
        }
        $result = Strings::unpackSSH2('ss', $sig);
        if ($result === false) {
            return false;
        }
        list($type, $blob) = $result;
        switch ($type) {
            // see https://tools.ietf.org/html/rfc5656#section-3.1.2
            case 'ecdsa-sha2-nistp256':
            case 'ecdsa-sha2-nistp384':
            case 'ecdsa-sha2-nistp521':
                break;
            default:
                return false;
        }
        $result = Strings::unpackSSH2('ii', $blob);
        if ($result === false) {
            return false;
        }
        return ['r' => $result[0], 's' => $result[1]];
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @param string $curve
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s, $curve)
    {
        switch ($curve) {
            case 'secp256r1':
                $curve = 'nistp256';
                break;
            case 'secp384r1':
                $curve = 'nistp384';
                break;
            case 'secp521r1':
                $curve = 'nistp521';
                break;
            default:
                return false;
        }
        $blob = Strings::packSSH2('ii', $r, $s);
        return Strings::packSSH2('ss', 'ecdsa-sha2-' . $curve, $blob);
    }
}<?php

/**
 * EC Parameters
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC;

use phpseclib3\Crypt\EC;
/**
 * EC Parameters
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Parameters extends EC
{
    /**
     * Returns the parameters
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type = 'PKCS1', array $options = [])
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        return $type::saveParameters($this->curve, $options);
    }
}<?php

/**
 * EC Private Key
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC;

use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
use phpseclib3\Crypt\Common;
use phpseclib3\Exception\UnsupportedOperationException;
use phpseclib3\Common\Functions\Strings;
/**
 * EC Private Key
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrivateKey extends EC implements Common\PrivateKey
{
    use Common\Traits\PasswordProtected;
    /**
     * Private Key dA
     *
     * sign() converts this to a BigInteger so one might wonder why this is a FiniteFieldInteger instead of
     * a BigInteger. That's because a FiniteFieldInteger, when converted to a byte string, is null padded by
     * a certain amount whereas a BigInteger isn't.
     *
     * @var object
     */
    protected $dA;
    /**
     * Multiplies an encoded point by the private key
     *
     * Used by ECDH
     *
     * @param string $coordinates
     * @return string
     */
    public function multiply($coordinates)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            if ($this->curve instanceof Curve25519 && self::$engines['libsodium']) {
                return sodium_crypto_scalarmult($this->dA->toBytes(), $coordinates);
            }
            $point = [$this->curve->convertInteger(new BigInteger(strrev($coordinates), 256))];
            $point = $this->curve->multiplyPoint($point, $this->dA);
            return strrev($point[0]->toBytes(true));
        }
        if (!$this->curve instanceof TwistedEdwardsCurve) {
            $coordinates = "\x00{$coordinates}";
        }
        $point = PKCS1::extractPoint($coordinates, $this->curve);
        $point = $this->curve->multiplyPoint($point, $this->dA);
        if ($this->curve instanceof TwistedEdwardsCurve) {
            return $this->curve->encodePoint($point);
        }
        if (empty($point)) {
            throw new \RuntimeException('The infinity point is invalid');
        }
        return "\x04" . $point[0]->toBytes(true) . $point[1]->toBytes(true);
    }
    /**
     * Create a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @return mixed
     */
    public function sign($message)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
        }
        $dA = $this->dA;
        $order = $this->curve->getOrder();
        $shortFormat = $this->shortFormat;
        $format = $this->sigFormat;
        if ($format === false) {
            return false;
        }
        if ($this->curve instanceof TwistedEdwardsCurve) {
            if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
                $result = sodium_crypto_sign_detached($message, $this->toString('libsodium'));
                return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $result) : $result;
            }
            // contexts (Ed25519ctx) are supported but prehashing (Ed25519ph) is not.
            // quoting https://tools.ietf.org/html/rfc8032#section-8.5 ,
            // "The Ed25519ph and Ed448ph variants ... SHOULD NOT be used"
            $A = $this->curve->encodePoint($this->QA);
            $curve = $this->curve;
            $hash = new Hash($curve::HASH);
            $secret = \Phabel\Target\Php80\Polyfill::substr($hash->hash($this->dA->secret), $curve::SIZE);
            if ($curve instanceof Ed25519) {
                $dom = !isset($this->context) ? '' : 'SigEd25519 no Ed25519 collisions ' . chr(strlen($this->context)) . $this->context;
            } else {
                $context = isset($this->context) ? $this->context : '';
                $dom = 'SigEd448 ' . chr(strlen($context)) . $context;
            }
            // SHA-512(dom2(F, C) || prefix || PH(M))
            $r = $hash->hash($dom . $secret . $message);
            $r = strrev($r);
            $r = new BigInteger($r, 256);
            list(, $r) = $r->divide($order);
            $R = $curve->multiplyPoint($curve->getBasePoint(), $r);
            $R = $curve->encodePoint($R);
            $k = $hash->hash($dom . $R . $A . $message);
            $k = strrev($k);
            $k = new BigInteger($k, 256);
            list(, $k) = $k->divide($order);
            $S = $k->multiply($dA)->add($r);
            list(, $S) = $S->divide($order);
            $S = str_pad(strrev($S->toBytes()), $curve::SIZE, "\x00");
            return $shortFormat == 'SSH2' ? Strings::packSSH2('ss', 'ssh-' . strtolower($this->getCurve()), $R . $S) : $R . $S;
        }
        if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
            $signature = '';
            // altho PHP's OpenSSL bindings only supported EC key creation in PHP 7.1 they've long
            // supported signing / verification
            // we use specified curves to avoid issues with OpenSSL possibly not supporting a given named curve;
            // doing this may mean some curve-specific optimizations can't be used but idk if OpenSSL even
            // has curve-specific optimizations
            $result = openssl_sign($message, $signature, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash());
            if ($result) {
                if ($shortFormat == 'ASN1') {
                    return $signature;
                }
                extract(ASN1Signature::load($signature));
                return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s);
            }
        }
        $e = $this->hash->hash($message);
        $e = new BigInteger($e, 256);
        $Ln = $this->hash->getLength() - $order->getLength();
        $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e;
        while (true) {
            $k = BigInteger::randomRange(self::$one, $order->subtract(self::$one));
            list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $k);
            $x = $x->toBigInteger();
            list(, $r) = $x->divide($order);
            if ($r->equals(self::$zero)) {
                continue;
            }
            $kinv = $k->modInverse($order);
            $temp = $z->add($dA->multiply($r));
            $temp = $kinv->multiply($temp);
            list(, $s) = $temp->divide($order);
            if (!$s->equals(self::$zero)) {
                break;
            }
        }
        // the following is an RFC6979 compliant implementation of deterministic ECDSA
        // it's unused because it's mainly intended for use when a good CSPRNG isn't
        // available. if phpseclib's CSPRNG isn't good then even key generation is
        // suspect
        /*
        // if this were actually being used it'd probably be better if this lived in load() and createKey()
        $this->q = $this->curve->getOrder();
        $dA = $this->dA->toBigInteger();
        $this->x = $dA;
        
        $h1 = $this->hash->hash($message);
        $k = $this->computek($h1);
        list($x, $y) = $this->curve->multiplyPoint($this->curve->getBasePoint(), $k);
        $x = $x->toBigInteger();
        list(, $r) = $x->divide($this->q);
        $kinv = $k->modInverse($this->q);
        $h1 = $this->bits2int($h1);
        $temp = $h1->add($dA->multiply($r));
        $temp = $kinv->multiply($temp);
        list(, $s) = $temp->divide($this->q);
        */
        return $shortFormat == 'SSH2' ? $format::save($r, $s, $this->getCurve()) : $format::save($r, $s);
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePrivateKey');
        return $type::savePrivateKey($this->dA, $this->curve, $this->QA, $this->password, $options);
    }
    /**
     * Returns the public key
     *
     * @see self::getPrivateKey()
     * @access public
     * @return mixed
     */
    public function getPublicKey()
    {
        $format = 'PKCS8';
        if ($this->curve instanceof MontgomeryCurve) {
            $format = 'MontgomeryPublic';
        }
        $type = self::validatePlugin('Keys', $format, 'savePublicKey');
        $key = $type::savePublicKey($this->curve, $this->QA);
        $key = EC::loadFormat($format, $key);
        if ($this->curve instanceof MontgomeryCurve) {
            return $key;
        }
        $key = $key->withHash($this->hash->getHash())->withSignatureFormat($this->shortFormat);
        if ($this->curve instanceof TwistedEdwardsCurve) {
            $key = $key->withContext($this->context);
        }
        return $key;
    }
}<?php

/**
 * sect131r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect131r2 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(131, 8, 3, 2, 0);
        $this->setCoefficients('03E5A88919D7CAFCBF415F07C2176573B2', '04B8266A46C55657AC734CE38F018F2192');
        $this->setBasePoint('0356DCD8F2F95031AD652D23951BB366A8', '0648F06D867940A5366D9E265DE9EB240F');
        $this->setOrder(new BigInteger('0400000000000000016954A233049BA98F', 16));
    }
}<?php

/**
 * brainpoolP192t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP192t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297', 16));
        $this->setCoefficients(
            new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294', 16),
            // eg. -3
            new BigInteger('13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79', 16)
        );
        $this->setBasePoint(new BigInteger('3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129', 16), new BigInteger('097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9', 16));
        $this->setOrder(new BigInteger('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16));
    }
}<?php

/**
 * secp192k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime;
use phpseclib3\Math\BigInteger;
class secp192k1 extends KoblitzPrime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37', 16));
        $this->setCoefficients(new BigInteger('000000000000000000000000000000000000000000000000', 16), new BigInteger('000000000000000000000000000000000000000000000003', 16));
        $this->setBasePoint(new BigInteger('DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D', 16), new BigInteger('9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D', 16));
        $this->basis = [];
        $this->basis[] = ['a' => new BigInteger('00B3FB3400DEC5C4ADCEB8655C', -16), 'b' => new BigInteger('8EE96418CCF4CFC7124FDA0F', -16)];
        $this->basis[] = ['a' => new BigInteger('01D90D03E8F096B9948B20F0A9', -16), 'b' => new BigInteger('42E49819ABBA9474E1083F6B', -16)];
        $this->beta = $this->factory->newInteger(new BigInteger('447A96E6C647963E2F7809FEAAB46947F34B0AA3CA0BBA74', -16));
    }
}<?php

/**
 * sect113r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect113r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(113, 9, 0);
        $this->setCoefficients('003088250CA6E7C7FE649CE85820F7', '00E8BEE4D3E2260744188BE0E9C723');
        $this->setBasePoint('009D73616F35F4AB1407D73562C10F', '00A52830277958EE84D1315ED31886');
        $this->setOrder(new BigInteger('0100000000000000D9CCEC8A39E56F', 16));
    }
}<?php

/**
 * Ed448
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
class Ed448 extends TwistedEdwards
{
    const HASH = 'shake256-912';
    const SIZE = 57;
    /**
     *
     */
    public function __construct()
    {
        // 2^448 - 2^224 - 1
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(
            new BigInteger(1),
            // -39081
            new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF6756', 16)
        );
        $this->setBasePoint(new BigInteger('4F1970C66BED0DED221D15A622BF36DA9E146570470F1767EA6DE324A3D3A46412AE1AF72AB66511433B80E18B00938E2626A82BC70CC05E', 16), new BigInteger('693F46716EB6BC248876203756C9C7624BEA73736CA3984087789C1E05A0C2D73AD3FF1CE67C39C4FDBD132C4ED7C8AD9808795BF230FA14', 16));
        $this->setOrder(new BigInteger('3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3', 16));
    }
    /**
     * Recover X from Y
     *
     * Implements steps 2-4 at https://tools.ietf.org/html/rfc8032#section-5.2.3
     *
     * Used by EC\Keys\Common.php
     *
     * @param BigInteger $y
     * @param boolean $sign
     * @return object[]
     */
    public function recoverX(BigInteger $y, $sign)
    {
        $y = $this->factory->newInteger($y);
        $y2 = $y->multiply($y);
        $u = $y2->subtract($this->one);
        $v = $this->d->multiply($y2)->subtract($this->one);
        $x2 = $u->divide($v);
        if ($x2->equals($this->zero)) {
            if ($sign) {
                throw new \RuntimeException('Unable to recover X coordinate (x2 = 0)');
            }
            return clone $this->zero;
        }
        // find the square root
        $exp = $this->getModulo()->add(new BigInteger(1));
        $exp = $exp->bitwise_rightShift(2);
        $x = $x2->pow($exp);
        if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
            throw new \RuntimeException('Unable to recover X coordinate');
        }
        if ($x->isOdd() != $sign) {
            $x = $x->negate();
        }
        return [$x, $y];
    }
    /**
     * Extract Secret Scalar
     *
     * Implements steps 1-3 at https://tools.ietf.org/html/rfc8032#section-5.2.5
     *
     * Used by the various key handlers
     *
     * @param string $str
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function extractSecret($str)
    {
        if (strlen($str) != 57) {
            throw new \LengthException('Private Key should be 57-bytes long');
        }
        // 1.  Hash the 57-byte private key using SHAKE256(x, 114), storing the
        //     digest in a 114-octet large buffer, denoted h.  Only the lower 57
        //     bytes are used for generating the public key.
        $hash = new Hash('shake256-912');
        $h = $hash->hash($str);
        $h = \Phabel\Target\Php80\Polyfill::substr($h, 0, 57);
        // 2.  Prune the buffer: The two least significant bits of the first
        //     octet are cleared, all eight bits the last octet are cleared, and
        //     the highest bit of the second to last octet is set.
        $h[0] = $h[0] & chr(0xfc);
        $h = strrev($h);
        $h[0] = "\x00";
        $h[1] = $h[1] | chr(0x80);
        // 3.  Interpret the buffer as the little-endian integer, forming a
        //     secret scalar s.
        $dA = new BigInteger($h, 256);
        $dA->secret = $str;
        return $dA;
    }
    /**
     * Encode a point as a string
     *
     * @param array $point
     * @return string
     */
    public function encodePoint($point)
    {
        list($x, $y) = $point;
        $y = "\x00" . $y->toBytes();
        if ($x->isOdd()) {
            $y[0] = $y[0] | chr(0x80);
        }
        $y = strrev($y);
        return $y;
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function createRandomMultiplier()
    {
        return $this->extractSecret(Random::string(57));
    }
    /**
    * Converts an affine point to an extended homogeneous coordinate
    *
    * From https://tools.ietf.org/html/rfc8032#section-5.2.4 :
    *
    * A point (x,y) is represented in extended homogeneous coordinates (X, Y, Z, T),
    with x = X/Z, y = Y/Z, x * y = T/Z.
    *
    * @return \phpseclib3\Math\PrimeField\Integer[]
    */
    public function convertToInternal(array $p)
    {
        if (empty($p)) {
            return [clone $this->zero, clone $this->one, clone $this->one];
        }
        if (isset($p[2])) {
            return $p;
        }
        $p[2] = clone $this->one;
        return $p;
    }
    /**
     * Doubles a point on a curve
     *
     * @return FiniteField[]
     */
    public function doublePoint(array $p)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p)) {
            return [];
        }
        if (!isset($p[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        // from https://tools.ietf.org/html/rfc8032#page-18
        list($x1, $y1, $z1) = $p;
        $b = $x1->add($y1);
        $b = $b->multiply($b);
        $c = $x1->multiply($x1);
        $d = $y1->multiply($y1);
        $e = $c->add($d);
        $h = $z1->multiply($z1);
        $j = $e->subtract($this->two->multiply($h));
        $x3 = $b->subtract($e)->multiply($j);
        $y3 = $c->subtract($d)->multiply($e);
        $z3 = $e->multiply($j);
        return [$x3, $y3, $z3];
    }
    /**
     * Adds two points on the curve
     *
     * @return FiniteField[]
     */
    public function addPoint(array $p, array $q)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            if (count($q)) {
                return $q;
            }
            if (count($p)) {
                return $p;
            }
            return [];
        }
        if (!isset($p[2]) || !isset($q[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        if ($p[0]->equals($q[0])) {
            return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
        }
        // from https://tools.ietf.org/html/rfc8032#page-17
        list($x1, $y1, $z1) = $p;
        list($x2, $y2, $z2) = $q;
        $a = $z1->multiply($z2);
        $b = $a->multiply($a);
        $c = $x1->multiply($x2);
        $d = $y1->multiply($y2);
        $e = $this->d->multiply($c)->multiply($d);
        $f = $b->subtract($e);
        $g = $b->add($e);
        $h = $x1->add($y1)->multiply($x2->add($y2));
        $x3 = $a->multiply($f)->multiply($h->subtract($c)->subtract($d));
        $y3 = $a->multiply($g)->multiply($d->subtract($c));
        $z3 = $f->multiply($g);
        return [$x3, $y3, $z3];
    }
}<?php

/**
 * sect113r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect113r2 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(113, 9, 0);
        $this->setCoefficients('00689918DBEC7E5A0DD6DFC0AA55C7', '0095E9A9EC9B297BD4BF36E059184F');
        $this->setBasePoint('01A57A6A7B26CA5EF52FCDB8164797', '00B3ADC94ED1FE674C06E695BABA1D');
        $this->setOrder(new BigInteger('010000000000000108789B2496AF93', 16));
    }
}<?php

/**
 * prime192v1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class prime192v1 extends secp192r1
{
}<?php

/**
 * sect409r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect409r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(409, 87, 0);
        $this->setCoefficients('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', '0021A5C2C8EE9FEB5C4B9A753B7B476B7FD6422EF1F3DD674761FA99D6AC27C8A9A197B272822F6CD57A55AA4F50AE317B13545F');
        $this->setBasePoint('015D4860D088DDB3496B0C6064756260441CDE4AF1771D4DB01FFE5B34E59703DC255A868A1180515603AEAB60794E54BB7996A7', '0061B1CFAB6BE5F32BBFA78324ED106A7636B9C5A7BD198D0158AA4F5488D08F38514F1FDF4B4F40D2181B3681C364BA0273C706');
        $this->setOrder(new BigInteger('010000000000000000000000000000000000000000000000000001E2AAD6A612F33307BE5FA47C3C9E052F838164CD37D9A21173', 16));
    }
}<?php

/**
 * brainpoolP384r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP384r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53', 16));
        $this->setCoefficients(new BigInteger('7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826', 16), new BigInteger('4A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11', 16));
        $this->setBasePoint(new BigInteger('1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E', 16), new BigInteger('8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315', 16));
        $this->setOrder(new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565', 16));
    }
}<?php

/**
 * nistk233
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistk233 extends sect233k1
{
}<?php

/**
 * secp128r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp128r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC', 16), new BigInteger('E87579C11079F43DD824993C2CEE5ED3', 16));
        $this->setBasePoint(new BigInteger('161FF7528B899B2D0C28607CA52C5B86', 16), new BigInteger('CF5AC8395BAFEB13C02DA292DDED7A83', 16));
        $this->setOrder(new BigInteger('FFFFFFFE0000000075A30D1B9038A115', 16));
    }
}<?php

/**
 * Curve25519
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Montgomery;
use phpseclib3\Math\BigInteger;
class Curve25519 extends Montgomery
{
    /**
     *
     */
    public function __construct()
    {
        // 2^255 - 19
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16));
        $this->a24 = $this->factory->newInteger(new BigInteger('121666'));
        $this->p = [$this->factory->newInteger(new BigInteger(9))];
        // 2^252 + 0x14def9dea2f79cd65812631a5cf5d3ed
        $this->setOrder(new BigInteger('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED', 16));
        /*
        $this->setCoefficients(
            new BigInteger('486662'), // a
        );
        $this->setBasePoint(
            new BigInteger(9),
            new BigInteger('14781619447589544791020593568409986887264606134616475288964881837755586237401')
        );
        */
    }
    /**
     * Multiply a point on the curve by a scalar
     *
     * Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8
     *
     * @return array
     */
    public function multiplyPoint(array $p, BigInteger $d)
    {
        //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes())));
        //return [$this->factory->newInteger(new BigInteger($r, 256))];
        $d = $d->toBytes();
        $d &= "\xf8" . str_repeat("\xff", 30) . "";
        $d = strrev($d);
        $d |= "@";
        $d = new BigInteger($d, -256);
        return parent::multiplyPoint($p, $d);
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return BigInteger
     */
    public function createRandomMultiplier()
    {
        return BigInteger::random(256);
    }
    /**
     * Performs range check
     */
    public function rangeCheck(BigInteger $x)
    {
        if ($x->getLength() > 256 || $x->isNegative()) {
            throw new \RangeException('x must be a positive integer less than 256 bytes in length');
        }
    }
}<?php

/**
 * brainpoolP320t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP320t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27', 16));
        $this->setCoefficients(
            new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24', 16),
            // eg. -3
            new BigInteger('A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353', 16)
        );
        $this->setBasePoint(new BigInteger('925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52', 16), new BigInteger('63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3', 16));
        $this->setOrder(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311', 16));
    }
}<?php

/**
 * brainpoolP256t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP256t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16));
        $this->setCoefficients(
            new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374', 16),
            // eg. -3
            new BigInteger('662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04', 16)
        );
        $this->setBasePoint(new BigInteger('A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4', 16), new BigInteger('2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE', 16));
        $this->setOrder(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16));
    }
}<?php

/**
 * sect163k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect163k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(163, 7, 6, 3, 0);
        $this->setCoefficients('000000000000000000000000000000000000000001', '000000000000000000000000000000000000000001');
        $this->setBasePoint('02FE13C0537BBC11ACAA07D793DE4E6D5E5C94EEE8', '0289070FB05D38FF58321F2E800536D538CCDAA3D9');
        $this->setOrder(new BigInteger('04000000000000000000020108A2E0CC0D99F8A5EF', 16));
    }
}<?php

/**
 * brainpoolP320r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP320r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27', 16));
        $this->setCoefficients(new BigInteger('3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4', 16), new BigInteger('520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6', 16));
        $this->setBasePoint(new BigInteger('43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611', 16), new BigInteger('14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1', 16));
        $this->setOrder(new BigInteger('D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311', 16));
    }
}<?php

/**
 * sect283k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect283k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(283, 12, 7, 5, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('0503213F78CA44883F1A3B8162F188E553CD265F23C1567A16876913B0C2AC2458492836', '01CCDA380F1C9E318D90F95D07E5426FE87E45C0E8184698E45962364E34116177DD2259');
        $this->setOrder(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE9AE2ED07577265DFF7F94451E061E163C61', 16));
    }
}<?php

/**
 * sect131r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect131r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(131, 8, 3, 2, 0);
        $this->setCoefficients('07A11B09A76B562144418FF3FF8C2570B8', '0217C05610884B63B9C6C7291678F9D341');
        $this->setBasePoint('0081BAF91FDF9833C40F9C181343638399', '078C6E7EA38C001F73C8134B1B4EF9E150');
        $this->setOrder(new BigInteger('0400000000000000023123953A9464B54D', 16));
    }
}<?php

/**
 * secp192r1
 *
 * This is the NIST P-192 curve
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp192r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $modulo = new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16);
        $this->setModulo($modulo);
        // algorithm 2.27 from http://diamond.boisestate.edu/~liljanab/MATH308/GuideToECC.pdf#page=66
        /* in theory this should be faster than regular modular reductions save for one small issue.
              to convert to / from base-2**8 with BCMath you have to call bcmul() and bcdiv() a lot.
              to convert to / from base-2**8 with PHP64 you have to call base256_rshift() a lot.
              in short, converting to / from base-2**8 is pretty expensive and that expense is
              enough to offset whatever else might be gained by a simplified reduction algorithm.
              now, if PHP supported unsigned integers things might be different. no bit-shifting
              would be required for the PHP engine and it'd be a lot faster. but as is, BigInteger
              uses base-2**31 or base-2**26 depending on whether or not the system is has a 32-bit
              or a 64-bit OS.           
           */
        /*
        $m_length = $this->getLengthInBytes();
        $this->setReduction(function($c) use ($m_length) {
            $cBytes = $c->toBytes();
            $className = $this->className;
        
            if (strlen($cBytes) > 2 * $m_length) {
                list(, $r) = $c->divide($className::$modulo);
                return $r;
            }
        
            $c = str_pad($cBytes, 48, "\0", STR_PAD_LEFT);
            $c = array_reverse(str_split($c, 8));
        
            $null = "\0\0\0\0\0\0\0\0";
            $s1 = new BigInteger($c[2] . $c[1] . $c[0], 256);
            $s2 = new BigInteger($null . $c[3] . $c[3], 256);
            $s3 = new BigInteger($c[4] . $c[4] . $null, 256);
            $s4 = new BigInteger($c[5] . $c[5] . $c[5], 256);
        
            $r = $s1->add($s2)->add($s3)->add($s4);
            while ($r->compare($className::$modulo) >= 0) {
                $r = $r->subtract($className::$modulo);
            }
        
            return $r;
        });
        */
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), new BigInteger('64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1', 16));
        $this->setBasePoint(new BigInteger('188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012', 16), new BigInteger('07192B95FFC8DA78631011ED6B24CDD573F977A11E794811', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831', 16));
    }
}<?php

/**
 * Curve448
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Montgomery;
use phpseclib3\Math\BigInteger;
class Curve448 extends Montgomery
{
    /**
     *
     */
    public function __construct()
    {
        // 2^448 - 2^224 - 1
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->a24 = $this->factory->newInteger(new BigInteger('39081'));
        $this->p = [$this->factory->newInteger(new BigInteger(5))];
        // 2^446 - 0x8335dc163bb124b65129c96fde933d8d723a70aadc873d6d54a7bb0d
        $this->setOrder(new BigInteger('3FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7CCA23E9C44EDB49AED63690216CC2728DC58F552378C292AB5844F3', 16));
        /*
        $this->setCoefficients(
            new BigInteger('156326'), // a
        );
        $this->setBasePoint(
            new BigInteger(5),
            new BigInteger(
                '355293926785568175264127502063783334808976399387714271831880898' .
                '435169088786967410002932673765864550910142774147268105838985595290' .
                '606362')
        );
        */
    }
    /**
     * Multiply a point on the curve by a scalar
     *
     * Modifies the scalar as described at https://tools.ietf.org/html/rfc7748#page-8
     *
     * @return array
     */
    public function multiplyPoint(array $p, BigInteger $d)
    {
        //$r = strrev(sodium_crypto_scalarmult($d->toBytes(), strrev($p[0]->toBytes())));
        //return [$this->factory->newInteger(new BigInteger($r, 256))];
        $d = $d->toBytes();
        $d[0] = $d[0] & "\xfc";
        $d = strrev($d);
        $d |= "\x80";
        $d = new BigInteger($d, 256);
        return parent::multiplyPoint($p, $d);
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return BigInteger
     */
    public function createRandomMultiplier()
    {
        return BigInteger::random(446);
    }
    /**
     * Performs range check
     */
    public function rangeCheck(BigInteger $x)
    {
        if ($x->getLength() > 448 || $x->isNegative()) {
            throw new \RangeException('x must be a positive integer less than 446 bytes in length');
        }
    }
}<?php

/**
 * secp112r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp112r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('DB7C2ABF62E35E668076BEAD208B', 16));
        $this->setCoefficients(new BigInteger('DB7C2ABF62E35E668076BEAD2088', 16), new BigInteger('659EF8BA043916EEDE8911702B22', 16));
        $this->setBasePoint(new BigInteger('09487239995A5EE76B55F9C2F098', 16), new BigInteger('A89CE5AF8724C0A23E0E0FF77500', 16));
        $this->setOrder(new BigInteger('DB7C2ABF62E35E7628DFAC6561C5', 16));
    }
}<?php

/**
 * nistk163
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistk163 extends sect163k1
{
}<?php

/**
 * prime239v3
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime239v3 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), new BigInteger('255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E', 16));
        $this->setBasePoint(new BigInteger('6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A', 16), new BigInteger('1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3', 16));
        $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551', 16));
    }
}<?php

/**
 * secp128r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp128r2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        // same as secp128r1
        $this->setModulo(new BigInteger('FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('D6031998D1B3BBFEBF59CC9BBFF9AEE1', 16), new BigInteger('5EEEFCA380D02919DC2C6558BB6D8A5D', 16));
        $this->setBasePoint(new BigInteger('7B6AA5D85E572983E6FB32A7CDEBC140', 16), new BigInteger('27B6916A894D3AEE7106FE805FC34B44', 16));
        $this->setOrder(new BigInteger('3FFFFFFF7FFFFFFFBE0024720613B5A3', 16));
    }
}<?php

/**
 * brainpoolP256r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP256r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377', 16));
        $this->setCoefficients(new BigInteger('7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9', 16), new BigInteger('26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6', 16));
        $this->setBasePoint(new BigInteger('8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262', 16), new BigInteger('547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997', 16));
        $this->setOrder(new BigInteger('A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7', 16));
    }
}<?php

/**
 * prime256v1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class prime256v1 extends secp256r1
{
}<?php

/**
 * brainpoolP192r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP192r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297', 16));
        $this->setCoefficients(new BigInteger('6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF', 16), new BigInteger('469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9', 16));
        $this->setBasePoint(new BigInteger('C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6', 16), new BigInteger('14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F', 16));
        $this->setOrder(new BigInteger('C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1', 16));
    }
}<?php

/**
 * prime192v2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime192v2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), new BigInteger('CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953', 16));
        $this->setBasePoint(new BigInteger('EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A', 16), new BigInteger('6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31', 16));
    }
}<?php

/**
 * sect239k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect239k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(239, 158, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('29A0B6A887A983E9730988A68727A8B2D126C44CC2CC7B2A6555193035DC', '76310804F12E549BDB011C103089E73510ACB275FC312A5DC6B76553F0CA');
        $this->setOrder(new BigInteger('2000000000000000000000000000005A79FEC67CB6E91F1C1DA800E478A5', 16));
    }
}<?php

/**
 * sect233r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect233r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(233, 74, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000001', '0066647EDE6C332C7F8C0923BB58213B333B20E9CE4281FE115F7D8F90AD');
        $this->setBasePoint('00FAC9DFCBAC8313BB2139F1BB755FEF65BC391F8B36F8F8EB7371FD558B', '01006A08A41903350678E58528BEBF8A0BEFF867A7CA36716F7E01F81052');
        $this->setOrder(new BigInteger('01000000000000000000000000000013E974E72F8A6922031D2603CFE0D7', 16));
    }
}<?php

/**
 * sect163r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect163r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(163, 7, 6, 3, 0);
        $this->setCoefficients('07B6882CAAEFA84F9554FF8428BD88E246D2782AE2', '0713612DCDDCB40AAB946BDA29CA91F73AF958AFD9');
        $this->setBasePoint('0369979697AB43897789566789567F787A7876A654', '00435EDB42EFAFB2989D51FEFCE3C80988F41FF883');
        $this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFF48AAB689C29CA710279B', 16));
    }
}<?php

/**
 * nistp256
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp256 extends secp256r1
{
}<?php

/**
 * sect233k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect233k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(233, 74, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('017232BA853A7E731AF129F22FF4149563A419C26BF50A4C9D6EEFAD6126', '01DB537DECE819B7F70F555A67C427A8CD9BF18AEB9B56E0C11056FAE6A3');
        $this->setOrder(new BigInteger('8000000000000000000000000000069D5BB915BCD46EFB1AD5F173ABDF', 16));
    }
}<?php

/**
 * nistk409
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistk409 extends sect409k1
{
}<?php

/**
 * brainpoolP512t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP512t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3', 16));
        $this->setCoefficients(
            new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0', 16),
            // eg. -3
            new BigInteger('7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E', 16)
        );
        $this->setBasePoint(new BigInteger('640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA', 16), new BigInteger('5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332', 16));
        $this->setOrder(new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069', 16));
    }
}<?php

/**
 * sect163r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect163r2 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(163, 7, 6, 3, 0);
        $this->setCoefficients('000000000000000000000000000000000000000001', '020A601907B8C953CA1481EB10512F78744A3205FD');
        $this->setBasePoint('03F0EBA16286A2D57EA0991168D4994637E8343E36', '00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1');
        $this->setOrder(new BigInteger('040000000000000000000292FE77E70C12A4234C33', 16));
    }
}<?php

/**
 * brainpoolP384t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP384t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53', 16));
        $this->setCoefficients(
            new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50', 16),
            // eg. -3
            new BigInteger('7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE', 16)
        );
        $this->setBasePoint(new BigInteger('18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC', 16), new BigInteger('25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928', 16));
        $this->setOrder(new BigInteger('8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565', 16));
    }
}<?php

/**
 * sect571k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect571k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(571, 10, 5, 2, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('026EB7A859923FBC82189631F8103FE4AC9CA2970012D5D46024804801841CA44370958493B205E647DA304DB4CEB08CBBD1BA39494776FB988B47174DCA88C7E2945283A01C8972', '0349DC807F4FBF374F4AEADE3BCA95314DD58CEC9F307A54FFC61EFC006D8A2C9D4979C0AC44AEA74FBEBBB9F772AEDCB620B01A7BA7AF1B320430C8591984F601CD4C143EF1C7A3');
        $this->setOrder(new BigInteger('020000000000000000000000000000000000000000000000000000000000000000000000131850E1F19A63E4B391A8DB917F4138B630D84BE5D639381E91DEB45CFE778F637C1001', 16));
    }
}<?php

/**
 * secp521r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp521r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC', 16), new BigInteger('0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00', 16));
        $this->setBasePoint(new BigInteger('00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66', 16), new BigInteger('011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650', 16));
        $this->setOrder(new BigInteger('01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409', 16));
    }
}<?php

/**
 * sect283k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistk283 extends sect283k1
{
}<?php

/**
 * prime239v2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime239v2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), new BigInteger('617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C', 16));
        $this->setBasePoint(new BigInteger('38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7', 16), new BigInteger('5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA', 16));
        $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063', 16));
    }
}<?php

/**
 * secp160k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime;
use phpseclib3\Math\BigInteger;
class secp160k1 extends KoblitzPrime
{
    /**
     *
     */
    public function __construct()
    {
        // same as secp160r2
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73', 16));
        $this->setCoefficients(new BigInteger('0000000000000000000000000000000000000000', 16), new BigInteger('0000000000000000000000000000000000000007', 16));
        $this->setBasePoint(new BigInteger('3B4C382CE37AA192A4019E763036F4F5DD4D7EBB', 16), new BigInteger('938CF935318FDCED6BC28286531733C3F03C4FEE', 16));
        $this->setOrder(new BigInteger('0100000000000000000001B8FA16DFAB9ACA16B6B3', 16));
        $this->basis = [];
        $this->basis[] = ['a' => new BigInteger('0096341F1138933BC2F505', -16), 'b' => new BigInteger('FF6E9D0418C67BB8D5F562', -16)];
        $this->basis[] = ['a' => new BigInteger('01BDCB3A09AAAABEAFF4A8', -16), 'b' => new BigInteger('04D12329FF0EF498EA67', -16)];
        $this->beta = $this->factory->newInteger(new BigInteger('645B7345A143464942CC46D7CF4D5D1E1E6CBB68', -16));
    }
}<?php

/**
 * secp112r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp112r2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        // same modulo as secp112r1
        $this->setModulo(new BigInteger('DB7C2ABF62E35E668076BEAD208B', 16));
        $this->setCoefficients(new BigInteger('6127C24C05F38A0AAAF65C0EF02C', 16), new BigInteger('51DEF1815DB5ED74FCC34C85D709', 16));
        $this->setBasePoint(new BigInteger('4BA30AB5E892B4E1649DD0928643', 16), new BigInteger('ADCD46F5882E3747DEF36E956E97', 16));
        $this->setOrder(new BigInteger('36DF0AAFD8B8D7597CA10520D04B', 16));
    }
}<?php

/**
 * secp256r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp256r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC', 16), new BigInteger('5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B', 16));
        $this->setBasePoint(new BigInteger('6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296', 16), new BigInteger('4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5', 16));
        $this->setOrder(new BigInteger('FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551', 16));
    }
}<?php

/**
 * secp256k1
 *
 * This is the curve used in Bitcoin
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

//use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime;
use phpseclib3\Math\BigInteger;
//class secp256k1 extends Prime
class secp256k1 extends KoblitzPrime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F', 16));
        $this->setCoefficients(new BigInteger('0000000000000000000000000000000000000000000000000000000000000000', 16), new BigInteger('0000000000000000000000000000000000000000000000000000000000000007', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141', 16));
        $this->setBasePoint(new BigInteger('79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798', 16), new BigInteger('483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8', 16));
        $this->basis = [];
        $this->basis[] = ['a' => new BigInteger('3086D221A7D46BCDE86C90E49284EB15', -16), 'b' => new BigInteger('FF1BBC8129FEF177D790AB8056F5401B3D', -16)];
        $this->basis[] = ['a' => new BigInteger('114CA50F7A8E2F3F657C1108D9D44CFD8', -16), 'b' => new BigInteger('3086D221A7D46BCDE86C90E49284EB15', -16)];
        $this->beta = $this->factory->newInteger(new BigInteger('7AE96A2B657C07106E64479EAC3434E99CF0497512F58995C1396C28719501EE', -16));
    }
}<?php

/**
 * prime192v3
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime192v3 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC', 16), new BigInteger('22123DC2395A05CAA7423DAECCC94760A7D462256BD56916', 16));
        $this->setBasePoint(new BigInteger('7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896', 16), new BigInteger('38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13', 16));
    }
}<?php

/**
 * brainpoolP160t1
 *
 * This curve is a twisted version of brainpoolP160r1 with A = -3. With brainpool,
 * the curves ending in r1 are the "regular" curves and the curves ending in "t1"
 * are the twisted version of the r1 curves. Per https://tools.ietf.org/html/rfc5639#page-7
 * you can convert a point on an r1 curve to a point on a t1 curve thusly:
 *
 *     F(x,y) := (x*Z^2, y*Z^3)
 *
 * The advantage of A = -3 is that some of the point doubling and point addition can be
 * slightly optimized. See http://hyperelliptic.org/EFD/g1p/auto-shortw-projective-3.html
 * vs http://hyperelliptic.org/EFD/g1p/auto-shortw-projective.html for example.
 *
 * phpseclib does not currently take advantage of this optimization opportunity
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP160t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620F', 16));
        $this->setCoefficients(
            new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620C', 16),
            // eg. -3
            new BigInteger('7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380', 16)
        );
        $this->setBasePoint(new BigInteger('B199B13B9B34EFC1397E64BAEB05ACC265FF2378', 16), new BigInteger('ADD6718B7C7C1961F0991B842443772152C9E0AD', 16));
        $this->setOrder(new BigInteger('E95E4A5F737059DC60DF5991D45029409E60FC09', 16));
    }
}<?php

/**
 * brainpoolP160r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP160r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('E95E4A5F737059DC60DFC7AD95B3D8139515620F', 16));
        $this->setCoefficients(new BigInteger('340E7BE2A280EB74E2BE61BADA745D97E8F7C300', 16), new BigInteger('1E589A8595423412134FAA2DBDEC95C8D8675E58', 16));
        $this->setBasePoint(new BigInteger('BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3', 16), new BigInteger('1667CB477A1A8EC338F94741669C976316DA6321', 16));
        $this->setOrder(new BigInteger('E95E4A5F737059DC60DF5991D45029409E60FC09', 16));
    }
}<?php

/**
 * secp224r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp224r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE', 16), new BigInteger('B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4', 16));
        $this->setBasePoint(new BigInteger('B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21', 16), new BigInteger('BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D', 16));
    }
}<?php

/**
 * nistt571
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistt571 extends sect571k1
{
}<?php

/**
 * brainpoolP512r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP512r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3', 16));
        $this->setCoefficients(new BigInteger('7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA', 16), new BigInteger('3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723', 16));
        $this->setBasePoint(new BigInteger('81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822', 16), new BigInteger('7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892', 16));
        $this->setOrder(new BigInteger('AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069', 16));
    }
}<?php

/**
 * nistp192
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp192 extends secp192r1
{
}<?php

/**
 * nistp521
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp521 extends secp521r1
{
}<?php

/**
 * nistp224
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp224 extends secp224r1
{
}<?php

/**
 * secp224k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\KoblitzPrime;
use phpseclib3\Math\BigInteger;
class secp224k1 extends KoblitzPrime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D', 16));
        $this->setCoefficients(new BigInteger('00000000000000000000000000000000000000000000000000000000', 16), new BigInteger('00000000000000000000000000000000000000000000000000000005', 16));
        $this->setBasePoint(new BigInteger('A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C', 16), new BigInteger('7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5', 16));
        $this->setOrder(new BigInteger('010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7', 16));
        $this->basis = [];
        $this->basis[] = ['a' => new BigInteger('00B8ADF1378A6EB73409FA6C9C637D', -16), 'b' => new BigInteger('94730F82B358A3776A826298FA6F', -16)];
        $this->basis[] = ['a' => new BigInteger('01DCE8D2EC6184CAF0A972769FCC8B', -16), 'b' => new BigInteger('4D2100BA3DC75AAB747CCF355DEC', -16)];
        $this->beta = $this->factory->newInteger(new BigInteger('01F178FFA4B17C89E6F73AECE2AAD57AF4C0A748B63C830947B27E04', -16));
    }
}<?php

/**
 * nistp384
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistp384 extends secp384r1
{
}<?php

/**
 * secp160r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp160r2 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        // same as secp160k1
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70', 16), new BigInteger('B4E134D3FB59EB8BAB57274904664D5AF50388BA', 16));
        $this->setBasePoint(new BigInteger('52DCB034293A117E1F4FF11B30F7199D3144CE6D', 16), new BigInteger('FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E', 16));
        $this->setOrder(new BigInteger('0100000000000000000000351EE786A818F3A1A16B', 16));
    }
}<?php

/**
 * prime239v1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class prime239v1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC', 16), new BigInteger('6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A', 16));
        $this->setBasePoint(new BigInteger('0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF', 16), new BigInteger('7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE', 16));
        $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B', 16));
    }
}<?php

/**
 * Ed25519
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
class Ed25519 extends TwistedEdwards
{
    const HASH = 'sha512';
    /*
      Per https://tools.ietf.org/html/rfc8032#page-6 EdDSA has several parameters, one of which is b:
    
      2.   An integer b with 2^(b-1) > p.  EdDSA public keys have exactly b
           bits, and EdDSA signatures have exactly 2*b bits.  b is
           recommended to be a multiple of 8, so public key and signature
           lengths are an integral number of octets.
    
      SIZE corresponds to b
    */
    const SIZE = 32;
    /**
     *
     */
    public function __construct()
    {
        // 2^255 - 19
        $this->setModulo(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFED', 16));
        $this->setCoefficients(
            // -1
            new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEC', 16),
            // a
            // -121665/121666
            new BigInteger('52036CEE2B6FFE738CC740797779E89800700A4D4141D8AB75EB4DCA135978A3', 16)
        );
        $this->setBasePoint(new BigInteger('216936D3CD6E53FEC0A4E231FDD6DC5C692CC7609525A7B2C9562D608F25D51A', 16), new BigInteger('6666666666666666666666666666666666666666666666666666666666666658', 16));
        $this->setOrder(new BigInteger('1000000000000000000000000000000014DEF9DEA2F79CD65812631A5CF5D3ED', 16));
        // algorithm 14.47 from http://cacr.uwaterloo.ca/hac/about/chap14.pdf#page=16
        /*
        $this->setReduction(function($x) {
            $parts = $x->bitwise_split(255);
            $className = $this->className;
        
            if (count($parts) > 2) {
                list(, $r) = $x->divide($className::$modulo);
                return $r;
            }
        
            $zero = new BigInteger();
            $c = new BigInteger(19);
        
            switch (count($parts)) {
                case 2:
                    list($qi, $ri) = $parts;
                    break;
                case 1:
                    $qi = $zero;
                    list($ri) = $parts;
                    break;
                case 0:
                    return $zero;
            }
            $r = $ri;
        
            while ($qi->compare($zero) > 0) {
                $temp = $qi->multiply($c)->bitwise_split(255);
                if (count($temp) == 2) {
                    list($qi, $ri) = $temp;
                } else {
                    $qi = $zero;
                    list($ri) = $temp;
                }
                $r = $r->add($ri);
            }
        
            while ($r->compare($className::$modulo) > 0) {
                $r = $r->subtract($className::$modulo);
            }
            return $r;
        });
        */
    }
    /**
     * Recover X from Y
     *
     * Implements steps 2-4 at https://tools.ietf.org/html/rfc8032#section-5.1.3
     *
     * Used by EC\Keys\Common.php
     *
     * @param BigInteger $y
     * @param boolean $sign
     * @return object[]
     */
    public function recoverX(BigInteger $y, $sign)
    {
        $y = $this->factory->newInteger($y);
        $y2 = $y->multiply($y);
        $u = $y2->subtract($this->one);
        $v = $this->d->multiply($y2)->add($this->one);
        $x2 = $u->divide($v);
        if ($x2->equals($this->zero)) {
            if ($sign) {
                throw new \RuntimeException('Unable to recover X coordinate (x2 = 0)');
            }
            return clone $this->zero;
        }
        // find the square root
        /* we don't do $x2->squareRoot() because, quoting from
                   https://tools.ietf.org/html/rfc8032#section-5.1.1:
        
                   "For point decoding or "decompression", square roots modulo p are
                    needed.  They can be computed using the Tonelli-Shanks algorithm or
                    the special case for p = 5 (mod 8).  To find a square root of a,
                    first compute the candidate root x = a^((p+3)/8) (mod p)."
                 */
        $exp = $this->getModulo()->add(new BigInteger(3));
        $exp = $exp->bitwise_rightShift(3);
        $x = $x2->pow($exp);
        // If v x^2 = -u (mod p), set x <-- x * 2^((p-1)/4), which is a square root.
        if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
            $temp = $this->getModulo()->subtract(new BigInteger(1));
            $temp = $temp->bitwise_rightShift(2);
            $temp = $this->two->pow($temp);
            $x = $x->multiply($temp);
            if (!$x->multiply($x)->subtract($x2)->equals($this->zero)) {
                throw new \RuntimeException('Unable to recover X coordinate');
            }
        }
        if ($x->isOdd() != $sign) {
            $x = $x->negate();
        }
        return [$x, $y];
    }
    /**
     * Extract Secret Scalar
     *
     * Implements steps 1-3 at https://tools.ietf.org/html/rfc8032#section-5.1.5
     *
     * Used by the various key handlers
     *
     * @param string $str
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function extractSecret($str)
    {
        if (strlen($str) != 32) {
            throw new \LengthException('Private Key should be 32-bytes long');
        }
        // 1.  Hash the 32-byte private key using SHA-512, storing the digest in
        //     a 64-octet large buffer, denoted h.  Only the lower 32 bytes are
        //     used for generating the public key.
        $hash = new Hash('sha512');
        $h = $hash->hash($str);
        $h = \Phabel\Target\Php80\Polyfill::substr($h, 0, 32);
        // 2.  Prune the buffer: The lowest three bits of the first octet are
        //     cleared, the highest bit of the last octet is cleared, and the
        //     second highest bit of the last octet is set.
        $h[0] = $h[0] & chr(0xf8);
        $h = strrev($h);
        $h[0] = $h[0] & chr(0x3f) | chr(0x40);
        // 3.  Interpret the buffer as the little-endian integer, forming a
        //     secret scalar s.
        $dA = new BigInteger($h, 256);
        $dA->secret = $str;
        return $dA;
    }
    /**
     * Encode a point as a string
     *
     * @param array $point
     * @return string
     */
    public function encodePoint($point)
    {
        list($x, $y) = $point;
        $y = $y->toBytes();
        $y[0] = $y[0] & chr(0x7f);
        if ($x->isOdd()) {
            $y[0] = $y[0] | chr(0x80);
        }
        $y = strrev($y);
        return $y;
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function createRandomMultiplier()
    {
        return $this->extractSecret(Random::string(32));
    }
    /**
    * Converts an affine point to an extended homogeneous coordinate
    *
    * From https://tools.ietf.org/html/rfc8032#section-5.1.4 :
    *
    * A point (x,y) is represented in extended homogeneous coordinates (X, Y, Z, T),
    with x = X/Z, y = Y/Z, x * y = T/Z.
    *
    * @return \phpseclib3\Math\PrimeField\Integer[]
    */
    public function convertToInternal(array $p)
    {
        if (empty($p)) {
            return [clone $this->zero, clone $this->one, clone $this->one, clone $this->zero];
        }
        if (isset($p[2])) {
            return $p;
        }
        $p[2] = clone $this->one;
        $p[3] = $p[0]->multiply($p[1]);
        return $p;
    }
    /**
     * Doubles a point on a curve
     *
     * @return FiniteField[]
     */
    public function doublePoint(array $p)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p)) {
            return [];
        }
        if (!isset($p[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        // from https://tools.ietf.org/html/rfc8032#page-12
        list($x1, $y1, $z1, $t1) = $p;
        $a = $x1->multiply($x1);
        $b = $y1->multiply($y1);
        $c = $this->two->multiply($z1)->multiply($z1);
        $h = $a->add($b);
        $temp = $x1->add($y1);
        $e = $h->subtract($temp->multiply($temp));
        $g = $a->subtract($b);
        $f = $c->add($g);
        $x3 = $e->multiply($f);
        $y3 = $g->multiply($h);
        $t3 = $e->multiply($h);
        $z3 = $f->multiply($g);
        return [$x3, $y3, $z3, $t3];
    }
    /**
     * Adds two points on the curve
     *
     * @return FiniteField[]
     */
    public function addPoint(array $p, array $q)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            if (count($q)) {
                return $q;
            }
            if (count($p)) {
                return $p;
            }
            return [];
        }
        if (!isset($p[2]) || !isset($q[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        if ($p[0]->equals($q[0])) {
            return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
        }
        // from https://tools.ietf.org/html/rfc8032#page-12
        list($x1, $y1, $z1, $t1) = $p;
        list($x2, $y2, $z2, $t2) = $q;
        $a = $y1->subtract($x1)->multiply($y2->subtract($x2));
        $b = $y1->add($x1)->multiply($y2->add($x2));
        $c = $t1->multiply($this->two)->multiply($this->d)->multiply($t2);
        $d = $z1->multiply($this->two)->multiply($z2);
        $e = $b->subtract($a);
        $f = $d->subtract($c);
        $g = $d->add($c);
        $h = $b->add($a);
        $x3 = $e->multiply($f);
        $y3 = $g->multiply($h);
        $t3 = $e->multiply($h);
        $z3 = $f->multiply($g);
        return [$x3, $y3, $z3, $t3];
    }
}<?php

/**
 * secp160r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp160r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC', 16), new BigInteger('1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45', 16));
        $this->setBasePoint(new BigInteger('4A96B5688EF573284664698968C38BB913CBFC82', 16), new BigInteger('23A628553168947D59DCC912042351377AC5FB32', 16));
        $this->setOrder(new BigInteger('0100000000000000000001F4C8F927AED3CA752257', 16));
    }
}<?php

/**
 * nistb233
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistb233 extends sect233r1
{
}<?php

/**
 * brainpoolP224t1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP224t1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF', 16));
        $this->setCoefficients(
            new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC', 16),
            // eg. -3
            new BigInteger('4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D', 16)
        );
        $this->setBasePoint(new BigInteger('6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580', 16), new BigInteger('0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C', 16));
        $this->setOrder(new BigInteger('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16));
    }
}<?php

/**
 * brainpoolP224r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class brainpoolP224r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF', 16));
        $this->setCoefficients(new BigInteger('68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43', 16), new BigInteger('2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B', 16));
        $this->setBasePoint(new BigInteger('0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D', 16), new BigInteger('58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD', 16));
        $this->setOrder(new BigInteger('D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F', 16));
    }
}<?php

/**
 * sect283r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect283r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(283, 12, 7, 5, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000000000000001', '027B680AC8B8596DA5A4AF8A19A0303FCA97FD7645309FA2A581485AF6263E313B79A2F5');
        $this->setBasePoint('05F939258DB7DD90E1934F8C70B0DFEC2EED25B8557EAC9C80E2E198F8CDBECD86B12053', '03676854FE24141CB98FE6D4B20D02B4516FF702350EDDB0826779C813F0DF45BE8112F4');
        $this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEF90399660FC938A90165B042A7CEFADB307', 16));
    }
}<?php

/**
 * secp384r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Prime;
use phpseclib3\Math\BigInteger;
class secp384r1 extends Prime
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF', 16));
        $this->setCoefficients(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC', 16), new BigInteger('B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF', 16));
        $this->setBasePoint(new BigInteger('AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7', 16), new BigInteger('3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F', 16));
        $this->setOrder(new BigInteger('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973', 16));
    }
}<?php

/**
 * sect193r2
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect193r2 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(193, 15, 0);
        $this->setCoefficients('0163F35A5137C2CE3EA6ED8667190B0BC43ECD69977702709B', '00C9BB9E8927D4D64C377E2AB2856A5B16E3EFB7F61D4316AE');
        $this->setBasePoint('00D9B67D192E0367C803F39E1A7E82CA14A651350AAE617E8F', '01CE94335607C304AC29E7DEFBD9CA01F596F927224CDECF6C');
        $this->setOrder(new BigInteger('010000000000000000000000015AAB561B005413CCD4EE99D5', 16));
    }
}<?php

/**
 * sect193r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect193r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(193, 15, 0);
        $this->setCoefficients('0017858FEB7A98975169E171F77B4087DE098AC8A911DF7B01', '00FDFB49BFE6C3A89FACADAA7A1E5BBC7CC1C2E5D831478814');
        $this->setBasePoint('01F481BC5F0FF84A74AD6CDF6FDEF4BF6179625372D8C0C5E1', '0025E399F2903712CCF3EA9E3A1AD17FB0B3201B6AF7CE1B05');
        $this->setOrder(new BigInteger('01000000000000000000000000C7F34A778F443ACC920EBA49', 16));
    }
}<?php

/**
 * sect409k1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect409k1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(409, 87, 0);
        $this->setCoefficients('00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001');
        $this->setBasePoint('0060F05F658F49C1AD3AB1890F7184210EFD0987E307C84C27ACCFB8F9F67CC2C460189EB5AAAA62EE222EB1B35540CFE9023746', '01E369050B7C4E42ACBA1DACBF04299C3460782F918EA427E6325165E9EA10E3DA5F6C42E9C55215AA9CA27A5863EC48D8E0286B');
        $this->setOrder(new BigInteger('7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE5F83B2D4EA20400EC4557D5ED3E3E7CA5B4B5C83B8E01E5FCF', 16));
    }
}<?php

/**
 * sect571r1
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wiggint  on <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

use phpseclib3\Crypt\EC\BaseCurves\Binary;
use phpseclib3\Math\BigInteger;
class sect571r1 extends Binary
{
    /**
     *
     */
    public function __construct()
    {
        $this->setModulo(571, 10, 5, 2, 0);
        $this->setCoefficients('000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', '02F40E7E2221F295DE297117B7F3D62F5C6A97FFCB8CEFF1CD6BA8CE4A9A18AD84FFABBD8EFA59332BE7AD6756A66E294AFD185A78FF12AA520E4DE739BACA0C7FFEFF7F2955727A');
        $this->setBasePoint('0303001D34B856296C16C0D40D3CD7750A93D1D2955FA80AA5F40FC8DB7B2ABDBDE53950F4C0D293CDD711A35B67FB1499AE60038614F1394ABFA3B4C850D927E1E7769C8EEC2D19', '037BF27342DA639B6DCCFFFEB73D69D78C6C27A6009CBBCA1980F8533921E8A684423E43BAB08A576291AF8F461BB2A8B3531D2F0485C19B16E2F1516E23DD3C1A4827AF1B8AC15B');
        $this->setOrder(new BigInteger('03FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE661CE18FF55987308059B186823851EC7DD9CA1161DE93D5174D66E8382E9BB2FE84E47', 16));
    }
}<?php

/**
 * nistb409
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\Curves;

final class nistb409 extends sect409r1
{
}<?php

/**
 * Generalized Koblitz Curves over y^2 = x^3 + b.
 *
 * According to http://www.secg.org/SEC2-Ver-1.0.pdf Koblitz curves are over the GF(2**m)
 * finite field. Both the $a$ and $b$ coefficients are either 0 or 1. However, SEC2
 * generalizes the definition to include curves over GF(P) "which possess an efficiently
 * computable endomorphism".
 *
 * For these generalized Koblitz curves $b$ doesn't have to be 0 or 1. Whether or not $a$
 * has any restrictions on it is unclear, however, for all the GF(P) Koblitz curves defined
 * in SEC2 v1.0 $a$ is $0$ so all of the methods defined herein will assume that it is.
 *
 * I suppose we could rename the $b$ coefficient to $a$, however, the documentation refers
 * to $b$ so we'll just keep it.
 *
 * If a later version of SEC2 comes out wherein some $a$ values are non-zero we can create a
 * new method for those. eg. KoblitzA1Prime.php or something.
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\PrimeField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
/**
 * Curves over y^2 = x^3 + b
 *
 * @package KoblitzPrime
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class KoblitzPrime extends Prime
{
    // don't overwrite setCoefficients() with one that only accepts one parameter so that
    // one might be able to switch between KoblitzPrime and Prime more easily (for benchmarking
    // purposes).
    /**
     * Multiply and Add Points
     *
     * Uses a efficiently computable endomorphism to achieve a slight speedup
     *
     * Adapted from https://git.io/vxbrP
     *
     * @return int[]
     */
    public function multiplyAddPoints(array $points, array $scalars)
    {
        static $zero, $one, $two;
        if (!isset($two)) {
            $two = new BigInteger(2);
            $one = new BigInteger(1);
        }
        if (!isset($this->beta)) {
            // get roots
            $inv = $this->one->divide($this->two)->negate();
            $s = $this->three->negate()->squareRoot()->multiply($inv);
            $betas = [$inv->add($s), $inv->subtract($s)];
            $this->beta = $betas[0]->compare($betas[1]) < 0 ? $betas[0] : $betas[1];
            //echo strtoupper($this->beta->toHex(true)) . "\n"; exit;
        }
        if (!isset($this->basis)) {
            $factory = new PrimeField($this->order);
            $tempOne = $factory->newInteger($one);
            $tempTwo = $factory->newInteger($two);
            $tempThree = $factory->newInteger(new BigInteger(3));
            $inv = $tempOne->divide($tempTwo)->negate();
            $s = $tempThree->negate()->squareRoot()->multiply($inv);
            $lambdas = [$inv->add($s), $inv->subtract($s)];
            $lhs = $this->multiplyPoint($this->p, $lambdas[0])[0];
            $rhs = $this->p[0]->multiply($this->beta);
            $lambda = $lhs->equals($rhs) ? $lambdas[0] : $lambdas[1];
            $this->basis = static::extendedGCD($lambda->toBigInteger(), $this->order);
            ///*
            foreach ($this->basis as $basis) {
                echo strtoupper($basis['a']->toHex(true)) . "\n";
                echo strtoupper($basis['b']->toHex(true)) . "\n\n";
            }
            exit;
            //*/
        }
        $npoints = $nscalars = [];
        for ($i = 0; $i < count($points); $i++) {
            $p = $points[$i];
            $k = $scalars[$i]->toBigInteger();
            // begin split
            list($v1, $v2) = $this->basis;
            $c1 = $v2['b']->multiply($k);
            list($c1, $r) = $c1->divide($this->order);
            if ($this->order->compare($r->multiply($two)) <= 0) {
                $c1 = $c1->add($one);
            }
            $c2 = $v1['b']->negate()->multiply($k);
            list($c2, $r) = $c2->divide($this->order);
            if ($this->order->compare($r->multiply($two)) <= 0) {
                $c2 = $c2->add($one);
            }
            $p1 = $c1->multiply($v1['a']);
            $p2 = $c2->multiply($v2['a']);
            $q1 = $c1->multiply($v1['b']);
            $q2 = $c2->multiply($v2['b']);
            $k1 = $k->subtract($p1)->subtract($p2);
            $k2 = $q1->add($q2)->negate();
            // end split
            $beta = [$p[0]->multiply($this->beta), $p[1], clone $this->one];
            if (isset($p['naf'])) {
                $beta['naf'] = array_map(function ($p) {
                    return [$p[0]->multiply($this->beta), $p[1], clone $this->one];
                }, $p['naf']);
                $beta['nafwidth'] = $p['nafwidth'];
            }
            if ($k1->isNegative()) {
                $k1 = $k1->negate();
                $p = $this->negatePoint($p);
            }
            if ($k2->isNegative()) {
                $k2 = $k2->negate();
                $beta = $this->negatePoint($beta);
            }
            $pos = 2 * $i;
            $npoints[$pos] = $p;
            $nscalars[$pos] = $this->factory->newInteger($k1);
            $pos++;
            $npoints[$pos] = $beta;
            $nscalars[$pos] = $this->factory->newInteger($k2);
        }
        return parent::multiplyAddPoints($npoints, $nscalars);
    }
    /**
     * Returns the numerator and denominator of the slope
     *
     * @return FiniteField[]
     */
    protected function doublePointHelper(array $p)
    {
        $numerator = $this->three->multiply($p[0])->multiply($p[0]);
        $denominator = $this->two->multiply($p[1]);
        return [$numerator, $denominator];
    }
    /**
     * Doubles a jacobian coordinate on the curve
     *
     * See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
     *
     * @return FiniteField[]
     */
    protected function jacobianDoublePoint(array $p)
    {
        list($x1, $y1, $z1) = $p;
        $a = $x1->multiply($x1);
        $b = $y1->multiply($y1);
        $c = $b->multiply($b);
        $d = $x1->add($b);
        $d = $d->multiply($d)->subtract($a)->subtract($c)->multiply($this->two);
        $e = $this->three->multiply($a);
        $f = $e->multiply($e);
        $x3 = $f->subtract($this->two->multiply($d));
        $y3 = $e->multiply($d->subtract($x3))->subtract($this->eight->multiply($c));
        $z3 = $this->two->multiply($y1)->multiply($z1);
        return [$x3, $y3, $z3];
    }
    /**
     * Doubles a "fresh" jacobian coordinate on the curve
     *
     * See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-mdbl-2007-bl
     *
     * @return FiniteField[]
     */
    protected function jacobianDoublePointMixed(array $p)
    {
        list($x1, $y1) = $p;
        $xx = $x1->multiply($x1);
        $yy = $y1->multiply($y1);
        $yyyy = $yy->multiply($yy);
        $s = $x1->add($yy);
        $s = $s->multiply($s)->subtract($xx)->subtract($yyyy)->multiply($this->two);
        $m = $this->three->multiply($xx);
        $t = $m->multiply($m)->subtract($this->two->multiply($s));
        $x3 = $t;
        $y3 = $s->subtract($t);
        $y3 = $m->multiply($y3)->subtract($this->eight->multiply($yyyy));
        $z3 = $this->two->multiply($y1);
        return [$x3, $y3, $z3];
    }
    /**
     * Tests whether or not the x / y values satisfy the equation
     *
     * @return boolean
     */
    public function verifyPoint(array $p)
    {
        list($x, $y) = $p;
        $lhs = $y->multiply($y);
        $temp = $x->multiply($x)->multiply($x);
        $rhs = $temp->add($this->b);
        return $lhs->equals($rhs);
    }
    /**
    * Calculates the parameters needed from the Euclidean algorithm as discussed at
    http://diamond.boisestate.edu/~liljanab/MATH308/GuideToECC.pdf#page=148
    *
    * @param BigInteger $u
    * @param BigInteger $v
    * @return BigInteger[]
    */
    protected static function extendedGCD(BigInteger $u, BigInteger $v)
    {
        $one = new BigInteger(1);
        $zero = new BigInteger();
        $a = clone $one;
        $b = clone $zero;
        $c = clone $zero;
        $d = clone $one;
        $stop = $v->bitwise_rightShift($v->getLength() >> 1);
        $a1 = clone $zero;
        $b1 = clone $zero;
        $a2 = clone $zero;
        $b2 = clone $zero;
        $postGreatestIndex = 0;
        while (!$v->equals($zero)) {
            list($q) = $u->divide($v);
            $temp = $u;
            $u = $v;
            $v = $temp->subtract($v->multiply($q));
            $temp = $a;
            $a = $c;
            $c = $temp->subtract($a->multiply($q));
            $temp = $b;
            $b = $d;
            $d = $temp->subtract($b->multiply($q));
            if ($v->compare($stop) > 0) {
                $a0 = $v;
                $b0 = $c;
            } else {
                $postGreatestIndex++;
            }
            if ($postGreatestIndex == 1) {
                $a1 = $v;
                $b1 = $c->negate();
            }
            if ($postGreatestIndex == 2) {
                $rhs = $a0->multiply($a0)->add($b0->multiply($b0));
                $lhs = $v->multiply($v)->add($b->multiply($b));
                if ($lhs->compare($rhs) <= 0) {
                    $a2 = $a0;
                    $b2 = $b0->negate();
                } else {
                    $a2 = $v;
                    $b2 = $c->negate();
                }
                break;
            }
        }
        return [['a' => $a1, 'b' => $b1], ['a' => $a2, 'b' => $b2]];
    }
}<?php

/**
 * Curves over y^2 = x^3 + a*x + x
 *
 * Technically, a Montgomery curve has a coefficient for y^2 but for Curve25519 and Curve448 that
 * coefficient is 1.
 *
 * Curve25519 and Curve448 do not make use of the y coordinate, which makes it unsuitable for use
 * with ECDSA / EdDSA. A few other differences between Curve25519 and Ed25519 are discussed at
 * https://crypto.stackexchange.com/a/43058/4520
 *
 * More info:
 *
 * https://en.wikipedia.org/wiki/Montgomery_curve
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\PrimeField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\EC\Curves\Curve25519;
use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
/**
 * Curves over y^2 = x^3 + a*x + x
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Montgomery extends Base
{
    /**
     * Prime Field Integer factory
     *
     * @var \phpseclib3\Math\PrimeField
     */
    protected $factory;
    /**
     * Cofficient for x
     *
     * @var object
     */
    protected $a;
    /**
     * Constant used for point doubling
     *
     * @var object
     */
    protected $a24;
    /**
     * The Number Zero
     *
     * @var object
     */
    protected $zero;
    /**
     * The Number One
     *
     * @var object
     */
    protected $one;
    /**
     * Base Point
     *
     * @var object
     */
    protected $p;
    /**
     * The modulo
     *
     * @var BigInteger
     */
    protected $modulo;
    /**
     * The Order
     *
     * @var BigInteger
     */
    protected $order;
    /**
     * Sets the modulo
     */
    public function setModulo(BigInteger $modulo)
    {
        $this->modulo = $modulo;
        $this->factory = new PrimeField($modulo);
        $this->zero = $this->factory->newInteger(new BigInteger());
        $this->one = $this->factory->newInteger(new BigInteger(1));
    }
    /**
     * Set coefficients a
     */
    public function setCoefficients(BigInteger $a)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->a = $this->factory->newInteger($a);
        $two = $this->factory->newInteger(new BigInteger(2));
        $four = $this->factory->newInteger(new BigInteger(4));
        $this->a24 = $this->a->subtract($two)->divide($four);
    }
    /**
     * Set x and y coordinates for the base point
     *
     * @param (BigInteger | PrimeInteger) $x
     * @param (BigInteger | PrimeInteger) $y
     * @return PrimeInteger[]
     */
    public function setBasePoint($x, $y)
    {
        switch (true) {
            case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
            case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
        }
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->p = [$x instanceof BigInteger ? $this->factory->newInteger($x) : $x, $y instanceof BigInteger ? $this->factory->newInteger($y) : $y];
    }
    /**
     * Retrieve the base point as an array
     *
     * @return array
     */
    public function getBasePoint()
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        /*
        if (!isset($this->p)) {
            throw new \RuntimeException('setBasePoint needs to be called before this method');
        }
        */
        return $this->p;
    }
    /**
     * Doubles and adds a point on a curve
     *
     * See https://tools.ietf.org/html/draft-ietf-tls-curve25519-01#appendix-A.1.3
     *
     * @return FiniteField[][]
     */
    private function doubleAndAddPoint(array $p, array $q, PrimeInteger $x1)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            return [];
        }
        if (!isset($p[1])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to XZ coordinates');
        }
        list($x2, $z2) = $p;
        list($x3, $z3) = $q;
        $a = $x2->add($z2);
        $aa = $a->multiply($a);
        $b = $x2->subtract($z2);
        $bb = $b->multiply($b);
        $e = $aa->subtract($bb);
        $c = $x3->add($z3);
        $d = $x3->subtract($z3);
        $da = $d->multiply($a);
        $cb = $c->multiply($b);
        $temp = $da->add($cb);
        $x5 = $temp->multiply($temp);
        $temp = $da->subtract($cb);
        $z5 = $x1->multiply($temp->multiply($temp));
        $x4 = $aa->multiply($bb);
        $temp = static::class == Curve25519::class ? $bb : $aa;
        $z4 = $e->multiply($temp->add($this->a24->multiply($e)));
        return [[$x4, $z4], [$x5, $z5]];
    }
    /**
    * Multiply a point on the curve by a scalar
    *
    * Uses the montgomery ladder technique as described here:
    *
    * https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder
    https://github.com/phpecc/phpecc/issues/16#issuecomment-59176772
    *
    * @return array
    */
    public function multiplyPoint(array $p, BigInteger $d)
    {
        $p1 = [$this->one, $this->zero];
        $alreadyInternal = isset($x[1]);
        $p2 = $this->convertToInternal($p);
        $x = $p[0];
        $b = $d->toBits();
        $b = str_pad($b, 256, '0', STR_PAD_LEFT);
        for ($i = 0; $i < strlen($b); $i++) {
            $b_i = (int) $b[$i];
            if ($b_i) {
                list($p2, $p1) = $this->doubleAndAddPoint($p2, $p1, $x);
            } else {
                list($p1, $p2) = $this->doubleAndAddPoint($p1, $p2, $x);
            }
        }
        return $alreadyInternal ? $p1 : $this->convertToAffine($p1);
    }
    /**
     * Converts an affine point to an XZ coordinate
     *
     * From https://hyperelliptic.org/EFD/g1p/auto-montgom-xz.html
     *
     * XZ coordinates represent x y as X Z satsfying the following equations:
     *
     * x=X/Z
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToInternal(array $p)
    {
        if (empty($p)) {
            return [clone $this->zero, clone $this->one];
        }
        if (isset($p[1])) {
            return $p;
        }
        $p[1] = clone $this->one;
        return $p;
    }
    /**
     * Returns the affine point
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToAffine(array $p)
    {
        if (!isset($p[1])) {
            return $p;
        }
        list($x, $z) = $p;
        return [$x->divide($z)];
    }
}<?php

/**
 * Curves over a*x^2 + y^2 = 1 + d*x^2*y^2
 *
 * http://www.secg.org/SEC2-Ver-1.0.pdf provides for curves with custom parameters.
 * ie. the coefficients can be arbitrary set through specially formatted keys, etc.
 * As such, Prime.php is built very generically and it's not able to take full
 * advantage of curves with 0 coefficients to produce simplified point doubling,
 * point addition. Twisted Edwards curves, in contrast, do not have a way, currently,
 * to customize them. As such, we can omit the super generic stuff from this class
 * and let the named curves (Ed25519 and Ed448) define their own custom tailored
 * point addition and point doubling methods.
 *
 * More info:
 *
 * https://en.wikipedia.org/wiki/Twisted_Edwards_curve
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Math\PrimeField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
/**
 * Curves over a*x^2 + y^2 = 1 + d*x^2*y^2
 *
 * @package Prime
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class TwistedEdwards extends Base
{
    /**
     * The modulo
     *
     * @var BigInteger
     */
    protected $modulo;
    /**
     * Cofficient for x^2
     *
     * @var object
     */
    protected $a;
    /**
     * Cofficient for x^2*y^2
     *
     * @var object
     */
    protected $d;
    /**
     * Base Point
     *
     * @var object[]
     */
    protected $p;
    /**
     * The number zero over the specified finite field
     *
     * @var object
     */
    protected $zero;
    /**
     * The number one over the specified finite field
     *
     * @var object
     */
    protected $one;
    /**
     * The number two over the specified finite field
     *
     * @var object
     */
    protected $two;
    /**
     * Sets the modulo
     */
    public function setModulo(BigInteger $modulo)
    {
        $this->modulo = $modulo;
        $this->factory = new PrimeField($modulo);
        $this->zero = $this->factory->newInteger(new BigInteger(0));
        $this->one = $this->factory->newInteger(new BigInteger(1));
        $this->two = $this->factory->newInteger(new BigInteger(2));
    }
    /**
     * Set coefficients a and b
     */
    public function setCoefficients(BigInteger $a, BigInteger $d)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->a = $this->factory->newInteger($a);
        $this->d = $this->factory->newInteger($d);
    }
    /**
     * Set x and y coordinates for the base point
     */
    public function setBasePoint($x, $y)
    {
        switch (true) {
            case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
            case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
        }
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->p = [$x instanceof BigInteger ? $this->factory->newInteger($x) : $x, $y instanceof BigInteger ? $this->factory->newInteger($y) : $y];
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getA()
    {
        return $this->a;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getD()
    {
        return $this->d;
    }
    /**
     * Retrieve the base point as an array
     *
     * @return array
     */
    public function getBasePoint()
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        /*
        if (!isset($this->p)) {
            throw new \RuntimeException('setBasePoint needs to be called before this method');
        }
        */
        return $this->p;
    }
    /**
     * Returns the affine point
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToAffine(array $p)
    {
        if (!isset($p[2])) {
            return $p;
        }
        list($x, $y, $z) = $p;
        $z = $this->one->divide($z);
        return [$x->multiply($z), $y->multiply($z)];
    }
    /**
     * Returns the modulo
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function getModulo()
    {
        return $this->modulo;
    }
    /**
     * Tests whether or not the x / y values satisfy the equation
     *
     * @return boolean
     */
    public function verifyPoint(array $p)
    {
        list($x, $y) = $p;
        $x2 = $x->multiply($x);
        $y2 = $y->multiply($y);
        $lhs = $this->a->multiply($x2)->add($y2);
        $rhs = $this->d->multiply($x2)->multiply($y2)->add($this->one);
        return $lhs->equals($rhs);
    }
}<?php

/**
 * Curves over y^2 = x^3 + a*x + b
 *
 * These are curves used in SEC 2 over prime fields: http://www.secg.org/SEC2-Ver-1.0.pdf
 * The curve is a weierstrass curve with a[1], a[3] and a[2] set to 0.
 *
 * Uses Jacobian Coordinates for speed if able:
 *
 * https://en.wikipedia.org/wiki/Jacobian_curve
 * https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Math\Common\FiniteField\Integer;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\PrimeField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\PrimeField\Integer as PrimeInteger;
/**
 * Curves over y^2 = x^3 + a*x + b
 *
 * @package Prime
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Prime extends Base
{
    /**
     * Prime Field Integer factory
     *
     * @var \phpseclib3\Math\PrimeFields
     */
    protected $factory;
    /**
     * Cofficient for x^1
     *
     * @var object
     */
    protected $a;
    /**
     * Cofficient for x^0
     *
     * @var object
     */
    protected $b;
    /**
     * Base Point
     *
     * @var object
     */
    protected $p;
    /**
     * The number one over the specified finite field
     *
     * @var object
     */
    protected $one;
    /**
     * The number two over the specified finite field
     *
     * @var object
     */
    protected $two;
    /**
     * The number three over the specified finite field
     *
     * @var object
     */
    protected $three;
    /**
     * The number four over the specified finite field
     *
     * @var object
     */
    protected $four;
    /**
     * The number eight over the specified finite field
     *
     * @var object
     */
    protected $eight;
    /**
     * The modulo
     *
     * @var BigInteger
     */
    protected $modulo;
    /**
     * The Order
     *
     * @var BigInteger
     */
    protected $order;
    /**
     * Sets the modulo
     */
    public function setModulo(BigInteger $modulo)
    {
        $this->modulo = $modulo;
        $this->factory = new PrimeField($modulo);
        $this->two = $this->factory->newInteger(new BigInteger(2));
        $this->three = $this->factory->newInteger(new BigInteger(3));
        // used by jacobian coordinates
        $this->one = $this->factory->newInteger(new BigInteger(1));
        $this->four = $this->factory->newInteger(new BigInteger(4));
        $this->eight = $this->factory->newInteger(new BigInteger(8));
    }
    /**
     * Set coefficients a and b
     */
    public function setCoefficients(BigInteger $a, BigInteger $b)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->a = $this->factory->newInteger($a);
        $this->b = $this->factory->newInteger($b);
    }
    /**
     * Set x and y coordinates for the base point
     *
     * @param (BigInteger | PrimeInteger) $x
     * @param (BigInteger | PrimeInteger) $y
     * @return PrimeInteger[]
     */
    public function setBasePoint($x, $y)
    {
        switch (true) {
            case !$x instanceof BigInteger && !$x instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 1 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
            case !$y instanceof BigInteger && !$y instanceof PrimeInteger:
                throw new \UnexpectedValueException('Argument 2 passed to Prime::setBasePoint() must be an instance of either BigInteger or PrimeField\\Integer');
        }
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->p = [$x instanceof BigInteger ? $this->factory->newInteger($x) : $x, $y instanceof BigInteger ? $this->factory->newInteger($y) : $y];
    }
    /**
     * Retrieve the base point as an array
     *
     * @return array
     */
    public function getBasePoint()
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        /*
        if (!isset($this->p)) {
            throw new \RuntimeException('setBasePoint needs to be called before this method');
        }
        */
        return $this->p;
    }
    /**
     * Adds two "fresh" jacobian form on the curve
     *
     * @return FiniteField[]
     */
    protected function jacobianAddPointMixedXY(array $p, array $q)
    {
        list($u1, $s1) = $p;
        list($u2, $s2) = $q;
        if ($u1->equals($u2)) {
            if (!$s1->equals($s2)) {
                return [];
            } else {
                return $this->doublePoint($p);
            }
        }
        $h = $u2->subtract($u1);
        $r = $s2->subtract($s1);
        $h2 = $h->multiply($h);
        $h3 = $h2->multiply($h);
        $v = $u1->multiply($h2);
        $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
        $y3 = $r->multiply($v->subtract($x3))->subtract($s1->multiply($h3));
        return [$x3, $y3, $h];
    }
    /**
     * Adds one "fresh" jacobian form on the curve
     *
     * The second parameter should be the "fresh" one
     *
     * @return FiniteField[]
     */
    protected function jacobianAddPointMixedX(array $p, array $q)
    {
        list($u1, $s1, $z1) = $p;
        list($x2, $y2) = $q;
        $z12 = $z1->multiply($z1);
        $u2 = $x2->multiply($z12);
        $s2 = $y2->multiply($z12->multiply($z1));
        if ($u1->equals($u2)) {
            if (!$s1->equals($s2)) {
                return [];
            } else {
                return $this->doublePoint($p);
            }
        }
        $h = $u2->subtract($u1);
        $r = $s2->subtract($s1);
        $h2 = $h->multiply($h);
        $h3 = $h2->multiply($h);
        $v = $u1->multiply($h2);
        $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
        $y3 = $r->multiply($v->subtract($x3))->subtract($s1->multiply($h3));
        $z3 = $h->multiply($z1);
        return [$x3, $y3, $z3];
    }
    /**
     * Adds two jacobian coordinates on the curve
     *
     * @return FiniteField[]
     */
    protected function jacobianAddPoint(array $p, array $q)
    {
        list($x1, $y1, $z1) = $p;
        list($x2, $y2, $z2) = $q;
        $z12 = $z1->multiply($z1);
        $z22 = $z2->multiply($z2);
        $u1 = $x1->multiply($z22);
        $u2 = $x2->multiply($z12);
        $s1 = $y1->multiply($z22->multiply($z2));
        $s2 = $y2->multiply($z12->multiply($z1));
        if ($u1->equals($u2)) {
            if (!$s1->equals($s2)) {
                return [];
            } else {
                return $this->doublePoint($p);
            }
        }
        $h = $u2->subtract($u1);
        $r = $s2->subtract($s1);
        $h2 = $h->multiply($h);
        $h3 = $h2->multiply($h);
        $v = $u1->multiply($h2);
        $x3 = $r->multiply($r)->subtract($h3)->subtract($v->multiply($this->two));
        $y3 = $r->multiply($v->subtract($x3))->subtract($s1->multiply($h3));
        $z3 = $h->multiply($z1)->multiply($z2);
        return [$x3, $y3, $z3];
    }
    /**
     * Adds two points on the curve
     *
     * @return FiniteField[]
     */
    public function addPoint(array $p, array $q)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            if (count($q)) {
                return $q;
            }
            if (count($p)) {
                return $p;
            }
            return [];
        }
        // use jacobian coordinates
        if (isset($p[2]) && isset($q[2])) {
            if (isset($p['fresh']) && isset($q['fresh'])) {
                return $this->jacobianAddPointMixedXY($p, $q);
            }
            if (isset($p['fresh'])) {
                return $this->jacobianAddPointMixedX($q, $p);
            }
            if (isset($q['fresh'])) {
                return $this->jacobianAddPointMixedX($p, $q);
            }
            return $this->jacobianAddPoint($p, $q);
        }
        if (isset($p[2]) || isset($q[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to Jacobi coordinates or vice versa');
        }
        if ($p[0]->equals($q[0])) {
            if (!$p[1]->equals($q[1])) {
                return [];
            } else {
                // eg. doublePoint
                list($numerator, $denominator) = $this->doublePointHelper($p);
            }
        } else {
            $numerator = $q[1]->subtract($p[1]);
            $denominator = $q[0]->subtract($p[0]);
        }
        $slope = $numerator->divide($denominator);
        $x = $slope->multiply($slope)->subtract($p[0])->subtract($q[0]);
        $y = $slope->multiply($p[0]->subtract($x))->subtract($p[1]);
        return [$x, $y];
    }
    /**
     * Returns the numerator and denominator of the slope
     *
     * @return FiniteField[]
     */
    protected function doublePointHelper(array $p)
    {
        $numerator = $this->three->multiply($p[0])->multiply($p[0])->add($this->a);
        $denominator = $this->two->multiply($p[1]);
        return [$numerator, $denominator];
    }
    /**
     * Doubles a jacobian coordinate on the curve
     *
     * @return FiniteField[]
     */
    protected function jacobianDoublePoint(array $p)
    {
        list($x, $y, $z) = $p;
        $x2 = $x->multiply($x);
        $y2 = $y->multiply($y);
        $z2 = $z->multiply($z);
        $s = $this->four->multiply($x)->multiply($y2);
        $m1 = $this->three->multiply($x2);
        $m2 = $this->a->multiply($z2->multiply($z2));
        $m = $m1->add($m2);
        $x1 = $m->multiply($m)->subtract($this->two->multiply($s));
        $y1 = $m->multiply($s->subtract($x1))->subtract($this->eight->multiply($y2->multiply($y2)));
        $z1 = $this->two->multiply($y)->multiply($z);
        return [$x1, $y1, $z1];
    }
    /**
     * Doubles a "fresh" jacobian coordinate on the curve
     *
     * @return FiniteField[]
     */
    protected function jacobianDoublePointMixed(array $p)
    {
        list($x, $y) = $p;
        $x2 = $x->multiply($x);
        $y2 = $y->multiply($y);
        $s = $this->four->multiply($x)->multiply($y2);
        $m1 = $this->three->multiply($x2);
        $m = $m1->add($this->a);
        $x1 = $m->multiply($m)->subtract($this->two->multiply($s));
        $y1 = $m->multiply($s->subtract($x1))->subtract($this->eight->multiply($y2->multiply($y2)));
        $z1 = $this->two->multiply($y);
        return [$x1, $y1, $z1];
    }
    /**
     * Doubles a point on a curve
     *
     * @return FiniteField[]
     */
    public function doublePoint(array $p)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p)) {
            return [];
        }
        // use jacobian coordinates
        if (isset($p[2])) {
            if (isset($p['fresh'])) {
                return $this->jacobianDoublePointMixed($p);
            }
            return $this->jacobianDoublePoint($p);
        }
        list($numerator, $denominator) = $this->doublePointHelper($p);
        $slope = $numerator->divide($denominator);
        $x = $slope->multiply($slope)->subtract($p[0])->subtract($p[0]);
        $y = $slope->multiply($p[0]->subtract($x))->subtract($p[1]);
        return [$x, $y];
    }
    /**
     * Returns the X coordinate and the derived Y coordinate
     *
     * @return array
     */
    public function derivePoint($m)
    {
        $y = ord(Strings::shift($m));
        $x = new BigInteger($m, 256);
        $xp = $this->convertInteger($x);
        switch ($y) {
            case 2:
                $ypn = false;
                break;
            case 3:
                $ypn = true;
                break;
            default:
                throw new \RuntimeException('Coordinate not in recognized format');
        }
        $temp = $xp->multiply($this->a);
        $temp = $xp->multiply($xp)->multiply($xp)->add($temp);
        $temp = $temp->add($this->b);
        $b = $temp->squareRoot();
        if (!$b) {
            throw new \RuntimeException('Unable to derive Y coordinate');
        }
        $bn = $b->isOdd();
        $yp = $ypn == $bn ? $b : $b->negate();
        return [$xp, $yp];
    }
    /**
     * Tests whether or not the x / y values satisfy the equation
     *
     * @return boolean
     */
    public function verifyPoint(array $p)
    {
        list($x, $y) = $p;
        $lhs = $y->multiply($y);
        $temp = $x->multiply($this->a);
        $temp = $x->multiply($x)->multiply($x)->add($temp);
        $rhs = $temp->add($this->b);
        return $lhs->equals($rhs);
    }
    /**
     * Returns the modulo
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function getModulo()
    {
        return $this->modulo;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getA()
    {
        return $this->a;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getB()
    {
        return $this->b;
    }
    /**
     * Multiply and Add Points
     *
     * Adapted from https://git.io/vxPUH
     *
     * @return int[]
     */
    public function multiplyAddPoints(array $points, array $scalars)
    {
        $length = count($points);
        foreach ($points as &$point) {
            $point = $this->convertToInternal($point);
        }
        $wnd = [$this->getNAFPoints($points[0], 7)];
        $wndWidth = [isset($points[0]['nafwidth']) ? $points[0]['nafwidth'] : 7];
        for ($i = 1; $i < $length; $i++) {
            $wnd[] = $this->getNAFPoints($points[$i], 1);
            $wndWidth[] = isset($points[$i]['nafwidth']) ? $points[$i]['nafwidth'] : 1;
        }
        $naf = [];
        // comb all window NAFs
        $max = 0;
        for ($i = $length - 1; $i >= 1; $i -= 2) {
            $a = $i - 1;
            $b = $i;
            if ($wndWidth[$a] != 1 || $wndWidth[$b] != 1) {
                $naf[$a] = $scalars[$a]->getNAF($wndWidth[$a]);
                $naf[$b] = $scalars[$b]->getNAF($wndWidth[$b]);
                $max = max(count($naf[$a]), count($naf[$b]), $max);
                continue;
            }
            $comb = [
                $points[$a],
                // 1
                null,
                // 3
                null,
                // 5
                $points[$b],
            ];
            $comb[1] = $this->addPoint($points[$a], $points[$b]);
            $comb[2] = $this->addPoint($points[$a], $this->negatePoint($points[$b]));
            $index = [
                -3,
                /* -1 -1 */
                -1,
                /* -1  0 */
                -5,
                /* -1  1 */
                -7,
                /*  0 -1 */
                0,
                /*  0 -1 */
                7,
                /*  0  1 */
                5,
                /*  1 -1 */
                1,
                /*  1  0 */
                3,
            ];
            $jsf = self::getJSFPoints($scalars[$a], $scalars[$b]);
            $max = max(count($jsf[0]), $max);
            if ($max > 0) {
                $naf[$a] = array_fill(0, $max, 0);
                $naf[$b] = array_fill(0, $max, 0);
            } else {
                $naf[$a] = [];
                $naf[$b] = [];
            }
            for ($j = 0; $j < $max; $j++) {
                $ja = isset($jsf[0][$j]) ? $jsf[0][$j] : 0;
                $jb = isset($jsf[1][$j]) ? $jsf[1][$j] : 0;
                $naf[$a][$j] = $index[3 * ($ja + 1) + $jb + 1];
                $naf[$b][$j] = 0;
                $wnd[$a] = $comb;
            }
        }
        $acc = [];
        $temp = [0, 0, 0, 0];
        for ($i = $max; $i >= 0; $i--) {
            $k = 0;
            while ($i >= 0) {
                $zero = true;
                for ($j = 0; $j < $length; $j++) {
                    $temp[$j] = isset($naf[$j][$i]) ? $naf[$j][$i] : 0;
                    if ($temp[$j] != 0) {
                        $zero = false;
                    }
                }
                if (!$zero) {
                    break;
                }
                $k++;
                $i--;
            }
            if ($i >= 0) {
                $k++;
            }
            while ($k--) {
                $acc = $this->doublePoint($acc);
            }
            if ($i < 0) {
                break;
            }
            for ($j = 0; $j < $length; $j++) {
                $z = $temp[$j];
                $p = null;
                if ($z == 0) {
                    continue;
                }
                $p = $z > 0 ? $wnd[$j][$z - 1 >> 1] : $this->negatePoint($wnd[$j][-$z - 1 >> 1]);
                $acc = $this->addPoint($acc, $p);
            }
        }
        return $this->convertToAffine($acc);
    }
    /**
     * Precomputes NAF points
     *
     * Adapted from https://git.io/vxY1f
     *
     * @return int[]
     */
    private function getNAFPoints($point, $wnd)
    {
        if (isset($point['naf'])) {
            return $point['naf'];
        }
        $res = [$point];
        $max = (1 << $wnd) - 1;
        $dbl = $max == 1 ? null : $this->doublePoint($point);
        for ($i = 1; $i < $max; $i++) {
            $res[] = $this->addPoint($res[$i - 1], $dbl);
        }
        $point['naf'] = $res;
        /*
        $str = '';
        foreach ($res as $re) {
            $re[0] = bin2hex($re[0]->toBytes());
            $re[1] = bin2hex($re[1]->toBytes());
            $str.= "            ['$re[0]', '$re[1]'],\r\n";
        }
        file_put_contents('temp.txt', $str);
        exit;
        */
        return $res;
    }
    /**
     * Precomputes points in Joint Sparse Form
     *
     * Adapted from https://git.io/vxrpD
     *
     * @return int[]
     */
    private static function getJSFPoints(Integer $k1, Integer $k2)
    {
        static $three;
        if (!isset($three)) {
            $three = new BigInteger(3);
        }
        $jsf = [[], []];
        $k1 = $k1->toBigInteger();
        $k2 = $k2->toBigInteger();
        $d1 = 0;
        $d2 = 0;
        while ($k1->compare(new BigInteger(-$d1)) > 0 || $k2->compare(new BigInteger(-$d2)) > 0) {
            // first phase
            $m14 = $k1->testBit(0) + 2 * $k1->testBit(1);
            $m14 += $d1;
            $m14 &= 3;
            $m24 = $k2->testBit(0) + 2 * $k2->testBit(1);
            $m24 += $d2;
            $m24 &= 3;
            if ($m14 == 3) {
                $m14 = -1;
            }
            if ($m24 == 3) {
                $m24 = -1;
            }
            $u1 = 0;
            if ($m14 & 1) {
                // if $m14 is odd
                $m8 = $k1->testBit(0) + 2 * $k1->testBit(1) + 4 * $k1->testBit(2);
                $m8 += $d1;
                $m8 &= 7;
                $u1 = ($m8 == 3 || $m8 == 5) && $m24 == 2 ? -$m14 : $m14;
            }
            $jsf[0][] = $u1;
            $u2 = 0;
            if ($m24 & 1) {
                // if $m24 is odd
                $m8 = $k2->testBit(0) + 2 * $k2->testBit(1) + 4 * $k2->testBit(2);
                $m8 += $d2;
                $m8 &= 7;
                $u2 = ($m8 == 3 || $m8 == 5) && $m14 == 2 ? -$m24 : $m24;
            }
            $jsf[1][] = $u2;
            // second phase
            if (2 * $d1 == $u1 + 1) {
                $d1 = 1 - $d1;
            }
            if (2 * $d2 == $u2 + 1) {
                $d2 = 1 - $d2;
            }
            $k1 = $k1->bitwise_rightShift(1);
            $k2 = $k2->bitwise_rightShift(1);
        }
        return $jsf;
    }
    /**
    * Returns the affine point
    *
    * A Jacobian Coordinate is of the form (x, y, z).
    To convert a Jacobian Coordinate to an Affine Point
    you do (x / z^2, y / z^3)
    *
    * @return \phpseclib3\Math\PrimeField\Integer[]
    */
    public function convertToAffine(array $p)
    {
        if (!isset($p[2])) {
            return $p;
        }
        list($x, $y, $z) = $p;
        $z = $this->one->divide($z);
        $z2 = $z->multiply($z);
        return [$x->multiply($z2), $y->multiply($z2)->multiply($z)];
    }
    /**
     * Converts an affine point to a jacobian coordinate
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToInternal(array $p)
    {
        if (isset($p[2])) {
            return $p;
        }
        $p[2] = clone $this->one;
        $p['fresh'] = true;
        return $p;
    }
}<?php

/**
 * Curves over y^2 + x*y = x^3 + a*x^2 + b
 *
 * These are curves used in SEC 2 over prime fields: http://www.secg.org/SEC2-Ver-1.0.pdf
 * The curve is a weierstrass curve with a[3] and a[2] set to 0.
 *
 * Uses Jacobian Coordinates for speed if able:
 *
 * https://en.wikipedia.org/wiki/Jacobian_curve
 * https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\BinaryField;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\BinaryField\Integer as BinaryInteger;
/**
 * Curves over y^2 + x*y = x^3 + a*x^2 + b
 *
 * @package Binary
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Binary extends Base
{
    /**
     * Binary Field Integer factory
     *
     * @var \phpseclib3\Math\BinaryField
     */
    protected $factory;
    /**
     * Cofficient for x^1
     *
     * @var object
     */
    protected $a;
    /**
     * Cofficient for x^0
     *
     * @var object
     */
    protected $b;
    /**
     * Base Point
     *
     * @var object
     */
    protected $p;
    /**
     * The number one over the specified finite field
     *
     * @var object
     */
    protected $one;
    /**
     * The modulo
     *
     * @var BigInteger
     */
    protected $modulo;
    /**
     * The Order
     *
     * @var BigInteger
     */
    protected $order;
    /**
     * Sets the modulo
     */
    public function setModulo(...$modulo)
    {
        $this->modulo = $modulo;
        $this->factory = new BinaryField(...$modulo);
        $this->one = $this->factory->newInteger("\x01");
    }
    /**
     * Set coefficients a and b
     *
     * @param string $a
     * @param string $b
     */
    public function setCoefficients($a, $b)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->a = $this->factory->newInteger(pack('H*', $a));
        $this->b = $this->factory->newInteger(pack('H*', $b));
    }
    /**
     * Set x and y coordinates for the base point
     *
     * @param (string | BinaryInteger) $x
     * @param (string | BinaryInteger) $y
     */
    public function setBasePoint($x, $y)
    {
        switch (true) {
            case !is_string($x) && !$x instanceof BinaryInteger:
                throw new \UnexpectedValueException('Argument 1 passed to Binary::setBasePoint() must be a string or an instance of BinaryField\\Integer');
            case !is_string($y) && !$y instanceof BinaryInteger:
                throw new \UnexpectedValueException('Argument 2 passed to Binary::setBasePoint() must be a string or an instance of BinaryField\\Integer');
        }
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        $this->p = [is_string($x) ? $this->factory->newInteger(pack('H*', $x)) : $x, is_string($y) ? $this->factory->newInteger(pack('H*', $y)) : $y];
    }
    /**
     * Retrieve the base point as an array
     *
     * @return array
     */
    public function getBasePoint()
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        /*
        if (!isset($this->p)) {
            throw new \RuntimeException('setBasePoint needs to be called before this method');
        }
        */
        return $this->p;
    }
    /**
     * Adds two points on the curve
     *
     * @return FiniteField[]
     */
    public function addPoint(array $p, array $q)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p) || !count($q)) {
            if (count($q)) {
                return $q;
            }
            if (count($p)) {
                return $p;
            }
            return [];
        }
        if (!isset($p[2]) || !isset($q[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        if ($p[0]->equals($q[0])) {
            return !$p[1]->equals($q[1]) ? [] : $this->doublePoint($p);
        }
        // formulas from http://hyperelliptic.org/EFD/g12o/auto-shortw-jacobian.html
        list($x1, $y1, $z1) = $p;
        list($x2, $y2, $z2) = $q;
        $o1 = $z1->multiply($z1);
        $b = $x2->multiply($o1);
        if ($z2->equals($this->one)) {
            $d = $y2->multiply($o1)->multiply($z1);
            $e = $x1->add($b);
            $f = $y1->add($d);
            $z3 = $e->multiply($z1);
            $h = $f->multiply($x2)->add($z3->multiply($y2));
            $i = $f->add($z3);
            $g = $z3->multiply($z3);
            $p1 = $this->a->multiply($g);
            $p2 = $f->multiply($i);
            $p3 = $e->multiply($e)->multiply($e);
            $x3 = $p1->add($p2)->add($p3);
            $y3 = $i->multiply($x3)->add($g->multiply($h));
            return [$x3, $y3, $z3];
        }
        $o2 = $z2->multiply($z2);
        $a = $x1->multiply($o2);
        $c = $y1->multiply($o2)->multiply($z2);
        $d = $y2->multiply($o1)->multiply($z1);
        $e = $a->add($b);
        $f = $c->add($d);
        $g = $e->multiply($z1);
        $h = $f->multiply($x2)->add($g->multiply($y2));
        $z3 = $g->multiply($z2);
        $i = $f->add($z3);
        $p1 = $this->a->multiply($z3->multiply($z3));
        $p2 = $f->multiply($i);
        $p3 = $e->multiply($e)->multiply($e);
        $x3 = $p1->add($p2)->add($p3);
        $y3 = $i->multiply($x3)->add($g->multiply($g)->multiply($h));
        return [$x3, $y3, $z3];
    }
    /**
     * Doubles a point on a curve
     *
     * @return FiniteField[]
     */
    public function doublePoint(array $p)
    {
        if (!isset($this->factory)) {
            throw new \RuntimeException('setModulo needs to be called before this method');
        }
        if (!count($p)) {
            return [];
        }
        if (!isset($p[2])) {
            throw new \RuntimeException('Affine coordinates need to be manually converted to "Jacobi" coordinates or vice versa');
        }
        // formulas from http://hyperelliptic.org/EFD/g12o/auto-shortw-jacobian.html
        list($x1, $y1, $z1) = $p;
        $a = $x1->multiply($x1);
        $b = $a->multiply($a);
        if ($z1->equals($this->one)) {
            $x3 = $b->add($this->b);
            $z3 = clone $x1;
            $p1 = $a->add($y1)->add($z3)->multiply($this->b);
            $p2 = $a->add($y1)->multiply($b);
            $y3 = $p1->add($p2);
            return [$x3, $y3, $z3];
        }
        $c = $z1->multiply($z1);
        $d = $c->multiply($c);
        $x3 = $b->add($this->b->multiply($d->multiply($d)));
        $z3 = $x1->multiply($c);
        $p1 = $b->multiply($z3);
        $p2 = $a->add($y1->multiply($z1))->add($z3)->multiply($x3);
        $y3 = $p1->add($p2);
        return [$x3, $y3, $z3];
    }
    /**
    * Returns the X coordinate and the derived Y coordinate
    *
    * Not supported because it is covered by patents.
    Quoting https://www.openssl.org/docs/man1.1.0/apps/ecparam.html ,
    *
    * "Due to patent issues the compressed option is disabled by default for binary curves
    and can be enabled by defining the preprocessor macro OPENSSL_EC_BIN_PT_COMP at
    compile time."
    *
    * @return array
    */
    public function derivePoint($m)
    {
        throw new \RuntimeException('Point compression on binary finite field elliptic curves is not supported');
    }
    /**
     * Tests whether or not the x / y values satisfy the equation
     *
     * @return boolean
     */
    public function verifyPoint(array $p)
    {
        list($x, $y) = $p;
        $lhs = $y->multiply($y);
        $lhs = $lhs->add($x->multiply($y));
        $x2 = $x->multiply($x);
        $x3 = $x2->multiply($x);
        $rhs = $x3->add($this->a->multiply($x2))->add($this->b);
        return $lhs->equals($rhs);
    }
    /**
     * Returns the modulo
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function getModulo()
    {
        return $this->modulo;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getA()
    {
        return $this->a;
    }
    /**
     * Returns the a coefficient
     *
     * @return \phpseclib3\Math\PrimeField\Integer
     */
    public function getB()
    {
        return $this->b;
    }
    /**
    * Returns the affine point
    *
    * A Jacobian Coordinate is of the form (x, y, z).
    To convert a Jacobian Coordinate to an Affine Point
    you do (x / z^2, y / z^3)
    *
    * @return \phpseclib3\Math\PrimeField\Integer[]
    */
    public function convertToAffine(array $p)
    {
        if (!isset($p[2])) {
            return $p;
        }
        list($x, $y, $z) = $p;
        $z = $this->one->divide($z);
        $z2 = $z->multiply($z);
        return [$x->multiply($z2), $y->multiply($z2)->multiply($z)];
    }
    /**
     * Converts an affine point to a jacobian coordinate
     *
     * @return \phpseclib3\Math\PrimeField\Integer[]
     */
    public function convertToInternal(array $p)
    {
        if (isset($p[2])) {
            return $p;
        }
        $p[2] = clone $this->one;
        $p['fresh'] = true;
        return $p;
    }
}<?php

/**
 * Curve methods common to all curves
 *
 * PHP version 5 and 7
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Crypt\EC\BaseCurves;

use phpseclib3\Math\BigInteger;
/**
 * Base
 *
 * @package Prime
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Base
{
    /**
     * Doubles
     *
     * @var object[]
     */
    protected $doubles;
    /**
     * NAF Points
     *
     * @var int[]
     */
    private $naf;
    /**
     * The Order
     *
     * @var BigInteger
     */
    protected $order;
    /**
     * Finite Field Integer factory
     *
     * @var \phpseclib3\Math\FiniteField\Integer
     */
    protected $factory;
    /**
     * Returns a random integer
     *
     * @return object
     */
    public function randomInteger()
    {
        return $this->factory->randomInteger();
    }
    /**
     * Converts a BigInteger to a \phpseclib3\Math\FiniteField\Integer integer
     *
     * @return object
     */
    public function convertInteger(BigInteger $x)
    {
        return $this->factory->newInteger($x);
    }
    /**
     * Returns the length, in bytes, of the modulo
     *
     * @return integer
     */
    public function getLengthInBytes()
    {
        return $this->factory->getLengthInBytes();
    }
    /**
     * Returns the length, in bits, of the modulo
     *
     * @return integer
     */
    public function getLength()
    {
        return $this->factory->getLength();
    }
    /**
    * Multiply a point on the curve by a scalar
    *
    * Uses the montgomery ladder technique as described here:
    *
    * https://en.wikipedia.org/wiki/Elliptic_curve_point_multiplication#Montgomery_ladder
    https://github.com/phpecc/phpecc/issues/16#issuecomment-59176772
    *
    * @return array
    */
    public function multiplyPoint(array $p, BigInteger $d)
    {
        $alreadyInternal = isset($p[2]);
        $r = $alreadyInternal ? [[], $p] : [[], $this->convertToInternal($p)];
        $d = $d->toBits();
        for ($i = 0; $i < strlen($d); $i++) {
            $d_i = (int) $d[$i];
            $r[1 - $d_i] = $this->addPoint($r[0], $r[1]);
            $r[$d_i] = $this->doublePoint($r[$d_i]);
        }
        return $alreadyInternal ? $r[0] : $this->convertToAffine($r[0]);
    }
    /**
     * Creates a random scalar multiplier
     *
     * @return BigInteger
     */
    public function createRandomMultiplier()
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        return BigInteger::randomRange($one, $this->order->subtract($one));
    }
    /**
     * Performs range check
     */
    public function rangeCheck(BigInteger $x)
    {
        static $zero;
        if (!isset($zero)) {
            $zero = new BigInteger();
        }
        if (!isset($this->order)) {
            throw new \RuntimeException('setOrder needs to be called before this method');
        }
        if ($x->compare($this->order) > 0 || $x->compare($zero) <= 0) {
            throw new \RangeException('x must be between 1 and the order of the curve');
        }
    }
    /**
     * Sets the Order
     */
    public function setOrder(BigInteger $order)
    {
        $this->order = $order;
    }
    /**
     * Returns the Order
     *
     * @return \phpseclib3\Math\BigInteger
     */
    public function getOrder()
    {
        return $this->order;
    }
    /**
     * Use a custom defined modular reduction function
     *
     * @return object
     */
    public function setReduction(callable $func)
    {
        $this->factory->setReduction($func);
    }
    /**
     * Returns the affine point
     *
     * @return object[]
     */
    public function convertToAffine(array $p)
    {
        return $p;
    }
    /**
     * Converts an affine point to a jacobian coordinate
     *
     * @return object[]
     */
    public function convertToInternal(array $p)
    {
        return $p;
    }
    /**
     * Negates a point
     *
     * @return object[]
     */
    public function negatePoint(array $p)
    {
        $temp = [$p[0], $p[1]->negate()];
        if (isset($p[2])) {
            $temp[] = $p[2];
        }
        return $temp;
    }
    /**
     * Multiply and Add Points
     *
     * @return int[]
     */
    public function multiplyAddPoints(array $points, array $scalars)
    {
        $p1 = $this->convertToInternal($points[0]);
        $p2 = $this->convertToInternal($points[1]);
        $p1 = $this->multiplyPoint($p1, $scalars[0]);
        $p2 = $this->multiplyPoint($p2, $scalars[1]);
        $r = $this->addPoint($p1, $p2);
        return $this->convertToAffine($r);
    }
}<?php

/**
 * EC Public Key
 *
 * @category  Crypt
 * @package   EC
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\EC;

use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\Hash;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\EC\Formats\Signature\ASN1 as ASN1Signature;
use phpseclib3\Crypt\EC\BaseCurves\TwistedEdwards as TwistedEdwardsCurve;
use phpseclib3\Crypt\EC\BaseCurves\Montgomery as MontgomeryCurve;
use phpseclib3\Crypt\EC\Curves\Ed25519;
use phpseclib3\Crypt\EC\Formats\Keys\PKCS1;
use phpseclib3\Crypt\Common;
use phpseclib3\Exception\UnsupportedOperationException;
use phpseclib3\Common\Functions\Strings;
/**
 * EC Public Key
 *
 * @package EC
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PublicKey extends EC implements Common\PublicKey
{
    use Common\Traits\Fingerprint;
    /**
     * Verify a signature
     *
     * @see self::verify()
     * @access public
     * @param string $message
     * @param string $signature
     * @return mixed
     */
    public function verify($message, $signature)
    {
        if ($this->curve instanceof MontgomeryCurve) {
            throw new UnsupportedOperationException('Montgomery Curves cannot be used to create signatures');
        }
        $shortFormat = $this->shortFormat;
        $format = $this->sigFormat;
        if ($format === false) {
            return false;
        }
        $order = $this->curve->getOrder();
        if ($this->curve instanceof TwistedEdwardsCurve) {
            if ($shortFormat == 'SSH2') {
                list(, $signature) = Strings::unpackSSH2('ss', $signature);
            }
            if ($this->curve instanceof Ed25519 && self::$engines['libsodium'] && !isset($this->context)) {
                return sodium_crypto_sign_verify_detached($signature, $message, $this->toString('libsodium'));
            }
            $curve = $this->curve;
            if (strlen($signature) != 2 * $curve::SIZE) {
                return false;
            }
            $R = \Phabel\Target\Php80\Polyfill::substr($signature, 0, $curve::SIZE);
            $S = \Phabel\Target\Php80\Polyfill::substr($signature, $curve::SIZE);
            try {
                $R = PKCS1::extractPoint($R, $curve);
                $R = $this->curve->convertToInternal($R);
            } catch (\Exception $e) {
                return false;
            }
            $S = strrev($S);
            $S = new BigInteger($S, 256);
            if ($S->compare($order) >= 0) {
                return false;
            }
            $A = $curve->encodePoint($this->QA);
            if ($curve instanceof Ed25519) {
                $dom2 = !isset($this->context) ? '' : 'SigEd25519 no Ed25519 collisions ' . chr(strlen($this->context)) . $this->context;
            } else {
                $context = isset($this->context) ? $this->context : '';
                $dom2 = 'SigEd448 ' . chr(strlen($context)) . $context;
            }
            $hash = new Hash($curve::HASH);
            $k = $hash->hash($dom2 . \Phabel\Target\Php80\Polyfill::substr($signature, 0, $curve::SIZE) . $A . $message);
            $k = strrev($k);
            $k = new BigInteger($k, 256);
            list(, $k) = $k->divide($order);
            $qa = $curve->convertToInternal($this->QA);
            $lhs = $curve->multiplyPoint($curve->getBasePoint(), $S);
            $rhs = $curve->multiplyPoint($qa, $k);
            $rhs = $curve->addPoint($rhs, $R);
            $rhs = $curve->convertToAffine($rhs);
            return $lhs[0]->equals($rhs[0]) && $lhs[1]->equals($rhs[1]);
        }
        $params = $format::load($signature);
        if ($params === false || count($params) != 2) {
            return false;
        }
        extract($params);
        if (self::$engines['OpenSSL'] && in_array($this->hash->getHash(), openssl_get_md_methods())) {
            $sig = $format != 'ASN1' ? ASN1Signature::save($r, $s) : $signature;
            $result = openssl_verify($message, $sig, $this->toString('PKCS8', ['namedCurve' => false]), $this->hash->getHash());
            if ($result != -1) {
                return (bool) $result;
            }
        }
        $n_1 = $order->subtract(self::$one);
        if (!$r->between(self::$one, $n_1) || !$s->between(self::$one, $n_1)) {
            return false;
        }
        $e = $this->hash->hash($message);
        $e = new BigInteger($e, 256);
        $Ln = $this->hash->getLength() - $order->getLength();
        $z = $Ln > 0 ? $e->bitwise_rightShift($Ln) : $e;
        $w = $s->modInverse($order);
        list(, $u1) = $z->multiply($w)->divide($order);
        list(, $u2) = $r->multiply($w)->divide($order);
        $u1 = $this->curve->convertInteger($u1);
        $u2 = $this->curve->convertInteger($u2);
        list($x1, $y1) = $this->curve->multiplyAddPoints([$this->curve->getBasePoint(), $this->QA], [$u1, $u2]);
        $x1 = $x1->toBigInteger();
        list(, $x1) = $x1->divide($order);
        return $x1->equals($r);
    }
    /**
     * Returns the public key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        $type = self::validatePlugin('Keys', $type, 'savePublicKey');
        return $type::savePublicKey($this->curve, $this->QA, $options);
    }
}<?php

/**
 * Pure-PHP implementation of RC4.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://www.mozilla.org/projects/security/pki/nss/draft-kaukonen-cipher-arcfour-03.txt ARCFOUR Algorithm}
 *  - {@link http://en.wikipedia.org/wiki/RC4 - Wikipedia: RC4}
 *
 * RC4 is also known as ARCFOUR or ARC4.  The reason is elaborated upon at Wikipedia.  This class is named RC4 and not
 * ARCFOUR or ARC4 because RC4 is how it is referred to in the SSH1 specification.
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $rc4 = new \phpseclib3\Crypt\RC4();
 *
 *    $rc4->setKey('abcdefgh');
 *
 *    $size = 10 * 1024;
 *    $plaintext = '';
 *    for ($i = 0; $i < $size; $i++) {
 *        $plaintext.= 'a';
 *    }
 *
 *    echo $rc4->decrypt($rc4->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   RC4
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\StreamCipher;
/**
 * Pure-PHP implementation of RC4.
 *
 * @package RC4
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class RC4 extends StreamCipher
{
    /**
     * @access private
     * @see \phpseclib3\Crypt\RC4::_crypt()
     */
    const ENCRYPT = 0;
    /**
     * @access private
     * @see \phpseclib3\Crypt\RC4::_crypt()
     */
    const DECRYPT = 1;
    /**
     * Key Length (in bytes)
     *
     * @see \phpseclib3\Crypt\RC4::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 128;
    // = 1024 bits
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'arcfour';
    /**
     * The Key
     *
     * @see self::setKey()
     * @var string
     * @access private
     */
    protected $key;
    /**
     * The Key Stream for decryption and encryption
     *
     * @see self::setKey()
     * @var array
     * @access private
     */
    private $stream;
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        if ($engine == self::ENGINE_OPENSSL) {
            if ($this->continuousBuffer) {
                return false;
            }
            if (version_compare(PHP_VERSION, '5.3.7') >= 0) {
                $this->cipher_name_openssl = 'rc4-40';
            } else {
                switch (strlen($this->key)) {
                    case 5:
                        $this->cipher_name_openssl = 'rc4-40';
                        break;
                    case 8:
                        $this->cipher_name_openssl = 'rc4-64';
                        break;
                    case 16:
                        $this->cipher_name_openssl = 'rc4';
                        break;
                    default:
                        return false;
                }
            }
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Sets the key length
     *
     * Keys can be between 1 and 256 bytes long.
     *
     * @access public
     * @param int $length
     * @throws \LengthException if the key length is invalid
     */
    public function setKeyLength($length)
    {
        if ($length < 8 || $length > 2048) {
            throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys between 1 and 256 bytes are supported');
        }
        $this->key_length = $length >> 3;
        parent::setKeyLength($length);
    }
    /**
     * Sets the key length
     *
     * Keys can be between 1 and 256 bytes long.
     *
     * @access public
     * @param string $key
     */
    public function setKey($key)
    {
        $length = strlen($key);
        if ($length < 1 || $length > 256) {
            throw new \LengthException('Key size of ' . $length . ' bytes is not supported by RC4. Keys must be between 1 and 256 bytes long');
        }
        parent::setKey($key);
    }
    /**
     * Encrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @see self::crypt()
     * @access public
     * @param string $plaintext
     * @return string $ciphertext
     */
    public function encrypt($plaintext)
    {
        if ($this->engine != self::ENGINE_INTERNAL) {
            return parent::encrypt($plaintext);
        }
        return $this->crypt($plaintext, self::ENCRYPT);
    }
    /**
    * Decrypts a message.
    *
    * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
    At least if the continuous buffer is disabled.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
    * @see self::crypt()
    * @access public
    * @param string $ciphertext
    * @return string $plaintext
    */
    public function decrypt($ciphertext)
    {
        if ($this->engine != self::ENGINE_INTERNAL) {
            return parent::decrypt($ciphertext);
        }
        return $this->crypt($ciphertext, self::DECRYPT);
    }
    /**
     * Encrypts a block
     *
     * @access private
     * @param string $in
     */
    protected function encryptBlock($in)
    {
        // RC4 does not utilize this method
    }
    /**
     * Decrypts a block
     *
     * @access private
     * @param string $in
     */
    protected function decryptBlock($in)
    {
        // RC4 does not utilize this method
    }
    /**
     * Setup the key (expansion)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
     * @access private
     */
    protected function setupKey()
    {
        $key = $this->key;
        $keyLength = strlen($key);
        $keyStream = range(0, 255);
        $j = 0;
        for ($i = 0; $i < 256; $i++) {
            $j = $j + $keyStream[$i] + ord($key[$i % $keyLength]) & 255;
            $temp = $keyStream[$i];
            $keyStream[$i] = $keyStream[$j];
            $keyStream[$j] = $temp;
        }
        $this->stream = [];
        $this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = [
            0,
            // index $i
            0,
            // index $j
            $keyStream,
        ];
    }
    /**
     * Encrypts or decrypts a message.
     *
     * @see self::encrypt()
     * @see self::decrypt()
     * @access private
     * @param string $text
     * @param int $mode
     * @return string $text
     */
    private function crypt($text, $mode)
    {
        if ($this->changed) {
            $this->setup();
        }
        $stream =& $this->stream[$mode];
        if ($this->continuousBuffer) {
            $i =& $stream[0];
            $j =& $stream[1];
            $keyStream =& $stream[2];
        } else {
            $i = $stream[0];
            $j = $stream[1];
            $keyStream = $stream[2];
        }
        $len = strlen($text);
        for ($k = 0; $k < $len; ++$k) {
            $i = $i + 1 & 255;
            $ksi = $keyStream[$i];
            $j = $j + $ksi & 255;
            $ksj = $keyStream[$j];
            $keyStream[$i] = $ksj;
            $keyStream[$j] = $ksi;
            $text[$k] = $text[$k] ^ chr($keyStream[$ksj + $ksi & 255]);
        }
        return $text;
    }
}<?php

/**
 * PKCS Formatted Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

/**
 * PKCS1 Formatted Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS
{
    /**
     * Auto-detect the format
     */
    const MODE_ANY = 0;
    /**
     * Require base64-encoded PEM's be supplied
     */
    const MODE_PEM = 1;
    /**
     * Require raw DER's be supplied
     */
    const MODE_DER = 2;
    /**#@-*/
    /**
     * Is the key a base-64 encoded PEM, DER or should it be auto-detected?
     *
     * @access private
     * @var int
     */
    protected static $format = self::MODE_ANY;
    /**
     * Require base64-encoded PEM's be supplied
     *
     * @access public
     */
    public static function requirePEM()
    {
        self::$format = self::MODE_PEM;
    }
    /**
     * Require raw DER's be supplied
     *
     * @access public
     */
    public static function requireDER()
    {
        self::$format = self::MODE_DER;
    }
    /**
     * Accept any format and auto detect the format
     *
     * This is the default setting
     *
     * @access public
     */
    public static function requireAny()
    {
        self::$format = self::MODE_ANY;
    }
}<?php

/**
 * PKCS1 Formatted Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\AES;
use phpseclib3\Crypt\DES;
use phpseclib3\Crypt\TripleDES;
use phpseclib3\File\ASN1;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedAlgorithmException;
/**
 * PKCS1 Formatted Key Handler
 *
 * @package RSA
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS1 extends PKCS
{
    /**
     * Default encryption algorithm
     *
     * @var string
     * @access private
     */
    private static $defaultEncryptionAlgorithm = 'AES-128-CBC';
    /**
     * Sets the default encryption algorithm
     *
     * @access public
     * @param string $algo
     */
    public static function setEncryptionAlgorithm($algo)
    {
        self::$defaultEncryptionAlgorithm = $algo;
    }
    /**
     * Returns the mode constant corresponding to the mode string
     *
     * @access public
     * @param string $mode
     * @return int
     * @throws \UnexpectedValueException if the block cipher mode is unsupported
     */
    private static function getEncryptionMode($mode)
    {
        switch ($mode) {
            case 'CBC':
            case 'ECB':
            case 'CFB':
            case 'OFB':
            case 'CTR':
                return $mode;
        }
        throw new \UnexpectedValueException('Unsupported block cipher mode of operation');
    }
    /**
     * Returns a cipher object corresponding to a string
     *
     * @access public
     * @param string $algo
     * @return string
     * @throws \UnexpectedValueException if the encryption algorithm is unsupported
     */
    private static function getEncryptionObject($algo)
    {
        $modes = '(CBC|ECB|CFB|OFB|CTR)';
        switch (true) {
            case preg_match("#^AES-(128|192|256)-{$modes}\$#", $algo, $matches):
                $cipher = new AES(self::getEncryptionMode($matches[2]));
                $cipher->setKeyLength($matches[1]);
                return $cipher;
            case preg_match("#^DES-EDE3-{$modes}\$#", $algo, $matches):
                return new TripleDES(self::getEncryptionMode($matches[1]));
            case preg_match("#^DES-{$modes}\$#", $algo, $matches):
                return new DES(self::getEncryptionMode($matches[1]));
            default:
                throw new UnsupportedAlgorithmException($algo . ' is not a supported algorithm');
        }
    }
    /**
     * Generate a symmetric key for PKCS#1 keys
     *
     * @access private
     * @param string $password
     * @param string $iv
     * @param int $length
     * @return string
     */
    private static function generateSymmetricKey($password, $iv, $length)
    {
        $symkey = '';
        $iv = \Phabel\Target\Php80\Polyfill::substr($iv, 0, 8);
        while (strlen($symkey) < $length) {
            $symkey .= md5($symkey . $password . $iv, true);
        }
        return \Phabel\Target\Php80\Polyfill::substr($symkey, 0, $length);
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    protected static function load($key, $password)
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        /* Although PKCS#1 proposes a format that public and private keys can use, encrypting them is
                   "outside the scope" of PKCS#1.  PKCS#1 then refers you to PKCS#12 and PKCS#15 if you're wanting to
                   protect private keys, however, that's not what OpenSSL* does.  OpenSSL protects private keys by adding
                   two new "fields" to the key - DEK-Info and Proc-Type.  These fields are discussed here:
        
                   http://tools.ietf.org/html/rfc1421#section-4.6.1.1
                   http://tools.ietf.org/html/rfc1421#section-4.6.1.3
        
                   DES-EDE3-CBC as an algorithm, however, is not discussed anywhere, near as I can tell.
                   DES-CBC and DES-EDE are discussed in RFC1423, however, DES-EDE3-CBC isn't, nor is its key derivation
                   function.  As is, the definitive authority on this encoding scheme isn't the IETF but rather OpenSSL's
                   own implementation.  ie. the implementation *is* the standard and any bugs that may exist in that
                   implementation are part of the standard, as well.
        
                   * OpenSSL is the de facto standard.  It's utilized by OpenSSH and other projects */
        if (preg_match('#DEK-Info: (.+),(.+)#', $key, $matches)) {
            $iv = Hex::decode(trim($matches[2]));
            // remove the Proc-Type / DEK-Info sections as they're no longer needed
            $key = preg_replace('#^(?:Proc-Type|DEK-Info): .*#m', '', $key);
            $ciphertext = ASN1::extractBER($key);
            if ($ciphertext === false) {
                $ciphertext = $key;
            }
            $crypto = self::getEncryptionObject($matches[1]);
            $crypto->setKey(self::generateSymmetricKey($password, $iv, $crypto->getKeyLength() >> 3));
            $crypto->setIV($iv);
            $key = $crypto->decrypt($ciphertext);
        } else {
            if (self::$format != self::MODE_DER) {
                $decoded = ASN1::extractBER($key);
                if ($decoded !== false) {
                    $key = $decoded;
                } elseif (self::$format == self::MODE_PEM) {
                    throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text');
                }
            }
        }
        return $key;
    }
    /**
     * Wrap a private key appropriately
     *
     * @access public
     * @param string $key
     * @param string $type
     * @param string $password
     * @param array $options optional
     * @return string
     */
    protected static function wrapPrivateKey($key, $type, $password, array $options = [])
    {
        if (empty($password) || !is_string($password)) {
            return "-----BEGIN {$type} PRIVATE KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END {$type} PRIVATE KEY-----";
        }
        $encryptionAlgorithm = isset($options['encryptionAlgorithm']) ? $options['encryptionAlgorithm'] : self::$defaultEncryptionAlgorithm;
        $cipher = self::getEncryptionObject($encryptionAlgorithm);
        $iv = Random::string($cipher->getBlockLength() >> 3);
        $cipher->setKey(self::generateSymmetricKey($password, $iv, $cipher->getKeyLength() >> 3));
        $cipher->setIV($iv);
        $iv = strtoupper(Hex::encode($iv));
        return "-----BEGIN {$type} PRIVATE KEY-----\r\n" . 'Proc-Type: 4,ENCRYPTED
DEK-Info: ' . $encryptionAlgorithm . ",{$iv}\r\n" . "\r\n" . chunk_split(Base64::encode($cipher->encrypt($key)), 64) . "-----END {$type} PRIVATE KEY-----";
    }
    /**
     * Wrap a public key appropriately
     *
     * @access public
     * @param string $key
     * @param string $type
     * @return string
     */
    protected static function wrapPublicKey($key, $type)
    {
        return "-----BEGIN {$type} PUBLIC KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END {$type} PUBLIC KEY-----";
    }
}<?php

/**
 * PKCS#8 Formatted Key Handler
 *
 * PHP version 5
 *
 * Used by PHP's openssl_public_encrypt() and openssl's rsautl (when -pubin is set)
 *
 * Processes keys with the following headers:
 *
 * -----BEGIN ENCRYPTED PRIVATE KEY-----
 * -----BEGIN PRIVATE KEY-----
 * -----BEGIN PUBLIC KEY-----
 *
 * Analogous to ssh-keygen's pkcs8 format (as specified by -m). Although PKCS8
 * is specific to private keys it's basically creating a DER-encoded wrapper
 * for keys. This just extends that same concept to public keys (much like ssh-keygen)
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Crypt\DES;
use phpseclib3\Crypt\RC2;
use phpseclib3\Crypt\RC4;
use phpseclib3\Crypt\AES;
use phpseclib3\Crypt\TripleDES;
use phpseclib3\Crypt\Random;
use phpseclib3\Math\BigInteger;
use phpseclib3\File\ASN1;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedAlgorithmException;
/**
 * PKCS#8 Formatted Key Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS8 extends PKCS
{
    /**
     * Default encryption algorithm
     *
     * @var string
     * @access private
     */
    private static $defaultEncryptionAlgorithm = 'id-PBES2';
    /**
     * Default encryption scheme
     *
     * Only used when defaultEncryptionAlgorithm is id-PBES2
     *
     * @var string
     * @access private
     */
    private static $defaultEncryptionScheme = 'aes128-CBC-PAD';
    /**
     * Default PRF
     *
     * Only used when defaultEncryptionAlgorithm is id-PBES2
     *
     * @var string
     * @access private
     */
    private static $defaultPRF = 'id-hmacWithSHA256';
    /**
     * Default Iteration Count
     *
     * @var int
     * @access private
     */
    private static $defaultIterationCount = 2048;
    /**
     * OIDs loaded
     *
     * @var bool
     * @access private
     */
    private static $oidsLoaded = false;
    /**
     * Sets the default encryption algorithm
     *
     * @access public
     * @param string $algo
     */
    public static function setEncryptionAlgorithm($algo)
    {
        self::$defaultEncryptionAlgorithm = $algo;
    }
    /**
     * Sets the default encryption algorithm for PBES2
     *
     * @access public
     * @param string $algo
     */
    public static function setEncryptionScheme($algo)
    {
        self::$defaultEncryptionScheme = $algo;
    }
    /**
     * Sets the iteration count
     *
     * @access public
     * @param int $count
     */
    public static function setIterationCount($count)
    {
        self::$defaultIterationCount = $count;
    }
    /**
     * Sets the PRF for PBES2
     *
     * @access public
     * @param string $algo
     */
    public static function setPRF($algo)
    {
        self::$defaultPRF = $algo;
    }
    /**
     * Returns a SymmetricKey object based on a PBES1 $algo
     *
     * @return \phpseclib3\Crypt\Common\SymmetricKey
     * @access public
     * @param string $algo
     */
    private static function getPBES1EncryptionObject($algo)
    {
        $algo = preg_match('#^pbeWith(?:MD2|MD5|SHA1|SHA)And(.*?)-CBC$#', $algo, $matches) ? $matches[1] : \Phabel\Target\Php80\Polyfill::substr($algo, 13);
        // strlen('pbeWithSHAAnd') == 13
        switch ($algo) {
            case 'DES':
                $cipher = new DES('cbc');
                break;
            case 'RC2':
                $cipher = new RC2('cbc');
                break;
            case '3-KeyTripleDES':
                $cipher = new TripleDES('cbc');
                break;
            case '2-KeyTripleDES':
                $cipher = new TripleDES('cbc');
                $cipher->setKeyLength(128);
                break;
            case '128BitRC2':
                $cipher = new RC2('cbc');
                $cipher->setKeyLength(128);
                break;
            case '40BitRC2':
                $cipher = new RC2('cbc');
                $cipher->setKeyLength(40);
                break;
            case '128BitRC4':
                $cipher = new RC4();
                $cipher->setKeyLength(128);
                break;
            case '40BitRC4':
                $cipher = new RC4();
                $cipher->setKeyLength(40);
                break;
            default:
                throw new UnsupportedAlgorithmException("{$algo} is not a supported algorithm");
        }
        return $cipher;
    }
    /**
     * Returns a hash based on a PBES1 $algo
     *
     * @return string
     * @access public
     * @param string $algo
     */
    private static function getPBES1Hash($algo)
    {
        if (preg_match('#^pbeWith(MD2|MD5|SHA1|SHA)And.*?-CBC$#', $algo, $matches)) {
            return $matches[1] == 'SHA' ? 'sha1' : $matches[1];
        }
        return 'sha1';
    }
    /**
     * Returns a KDF baesd on a PBES1 $algo
     *
     * @return string
     * @access public
     * @param string $algo
     */
    private static function getPBES1KDF($algo)
    {
        switch ($algo) {
            case 'pbeWithMD2AndDES-CBC':
            case 'pbeWithMD2AndRC2-CBC':
            case 'pbeWithMD5AndDES-CBC':
            case 'pbeWithMD5AndRC2-CBC':
            case 'pbeWithSHA1AndDES-CBC':
            case 'pbeWithSHA1AndRC2-CBC':
                return 'pbkdf1';
        }
        return 'pkcs12';
    }
    /**
     * Returns a SymmetricKey object baesd on a PBES2 $algo
     *
     * @return SymmetricKey
     * @access public
     * @param string $algo
     */
    private static function getPBES2EncryptionObject($algo)
    {
        switch ($algo) {
            case 'desCBC':
                $cipher = new TripleDES('cbc');
                break;
            case 'des-EDE3-CBC':
                $cipher = new TripleDES('cbc');
                break;
            case 'rc2CBC':
                $cipher = new RC2('cbc');
                // in theory this can be changed
                $cipher->setKeyLength(128);
                break;
            case 'rc5-CBC-PAD':
                throw new UnsupportedAlgorithmException('rc5-CBC-PAD is not supported for PBES2 PKCS#8 keys');
            case 'aes128-CBC-PAD':
            case 'aes192-CBC-PAD':
            case 'aes256-CBC-PAD':
                $cipher = new AES('cbc');
                $cipher->setKeyLength(\Phabel\Target\Php80\Polyfill::substr($algo, 3, 3));
                break;
            default:
                throw new UnsupportedAlgorithmException("{$algo} is not supported");
        }
        return $cipher;
    }
    /**
     * Initialize static variables
     *
     * @access private
     */
    private static function initialize_static_variables()
    {
        if (!static::$childOIDsLoaded) {
            ASN1::loadOIDs(is_array(static::OID_NAME) ? array_combine(static::OID_NAME, static::OID_VALUE) : [static::OID_NAME => static::OID_VALUE]);
            static::$childOIDsLoaded = true;
        }
        if (!self::$oidsLoaded) {
            // from https://tools.ietf.org/html/rfc2898
            ASN1::loadOIDs([
                // PBES1 encryption schemes
                'pbeWithMD2AndDES-CBC' => '1.2.840.113549.1.5.1',
                'pbeWithMD2AndRC2-CBC' => '1.2.840.113549.1.5.4',
                'pbeWithMD5AndDES-CBC' => '1.2.840.113549.1.5.3',
                'pbeWithMD5AndRC2-CBC' => '1.2.840.113549.1.5.6',
                'pbeWithSHA1AndDES-CBC' => '1.2.840.113549.1.5.10',
                'pbeWithSHA1AndRC2-CBC' => '1.2.840.113549.1.5.11',
                // from PKCS#12:
                // https://tools.ietf.org/html/rfc7292
                'pbeWithSHAAnd128BitRC4' => '1.2.840.113549.1.12.1.1',
                'pbeWithSHAAnd40BitRC4' => '1.2.840.113549.1.12.1.2',
                'pbeWithSHAAnd3-KeyTripleDES-CBC' => '1.2.840.113549.1.12.1.3',
                'pbeWithSHAAnd2-KeyTripleDES-CBC' => '1.2.840.113549.1.12.1.4',
                'pbeWithSHAAnd128BitRC2-CBC' => '1.2.840.113549.1.12.1.5',
                'pbeWithSHAAnd40BitRC2-CBC' => '1.2.840.113549.1.12.1.6',
                'id-PBKDF2' => '1.2.840.113549.1.5.12',
                'id-PBES2' => '1.2.840.113549.1.5.13',
                'id-PBMAC1' => '1.2.840.113549.1.5.14',
                // from PKCS#5 v2.1:
                // http://www.rsa.com/rsalabs/pkcs/files/h11302-wp-pkcs5v2-1-password-based-cryptography-standard.pdf
                'id-hmacWithSHA1' => '1.2.840.113549.2.7',
                'id-hmacWithSHA224' => '1.2.840.113549.2.8',
                'id-hmacWithSHA256' => '1.2.840.113549.2.9',
                'id-hmacWithSHA384' => '1.2.840.113549.2.10',
                'id-hmacWithSHA512' => '1.2.840.113549.2.11',
                'id-hmacWithSHA512-224' => '1.2.840.113549.2.12',
                'id-hmacWithSHA512-256' => '1.2.840.113549.2.13',
                'desCBC' => '1.3.14.3.2.7',
                'des-EDE3-CBC' => '1.2.840.113549.3.7',
                'rc2CBC' => '1.2.840.113549.3.2',
                'rc5-CBC-PAD' => '1.2.840.113549.3.9',
                'aes128-CBC-PAD' => '2.16.840.1.101.3.4.1.2',
                'aes192-CBC-PAD' => '2.16.840.1.101.3.4.1.22',
                'aes256-CBC-PAD' => '2.16.840.1.101.3.4.1.42',
            ]);
            self::$oidsLoaded = true;
        }
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password optional
     * @return array
     */
    protected static function load($key, $password = '')
    {
        $decoded = self::preParse($key);
        $meta = [];
        $decrypted = ASN1::asn1map($decoded[0], Maps\EncryptedPrivateKeyInfo::MAP);
        if (strlen($password) && is_array($decrypted)) {
            $algorithm = $decrypted['encryptionAlgorithm']['algorithm'];
            switch ($algorithm) {
                // PBES1
                case 'pbeWithMD2AndDES-CBC':
                case 'pbeWithMD2AndRC2-CBC':
                case 'pbeWithMD5AndDES-CBC':
                case 'pbeWithMD5AndRC2-CBC':
                case 'pbeWithSHA1AndDES-CBC':
                case 'pbeWithSHA1AndRC2-CBC':
                case 'pbeWithSHAAnd3-KeyTripleDES-CBC':
                case 'pbeWithSHAAnd2-KeyTripleDES-CBC':
                case 'pbeWithSHAAnd128BitRC2-CBC':
                case 'pbeWithSHAAnd40BitRC2-CBC':
                case 'pbeWithSHAAnd128BitRC4':
                case 'pbeWithSHAAnd40BitRC4':
                    $cipher = self::getPBES1EncryptionObject($algorithm);
                    $hash = self::getPBES1Hash($algorithm);
                    $kdf = self::getPBES1KDF($algorithm);
                    $meta['meta']['algorithm'] = $algorithm;
                    $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
                    extract(ASN1::asn1map($temp[0], Maps\PBEParameter::MAP));
                    $iterationCount = (int) $iterationCount->toString();
                    $cipher->setPassword($password, $kdf, $hash, $salt, $iterationCount);
                    $key = $cipher->decrypt($decrypted['encryptedData']);
                    $decoded = ASN1::decodeBER($key);
                    if (empty($decoded)) {
                        throw new \RuntimeException('Unable to decode BER 2');
                    }
                    break;
                case 'id-PBES2':
                    $meta['meta']['algorithm'] = $algorithm;
                    $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
                    $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP);
                    extract($temp);
                    $cipher = self::getPBES2EncryptionObject($encryptionScheme['algorithm']);
                    $meta['meta']['cipher'] = $encryptionScheme['algorithm'];
                    $temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
                    $temp = ASN1::asn1map($temp[0], Maps\PBES2params::MAP);
                    extract($temp);
                    if (!$cipher instanceof RC2) {
                        $cipher->setIV($encryptionScheme['parameters']['octetString']);
                    } else {
                        $temp = ASN1::decodeBER($encryptionScheme['parameters']);
                        extract(ASN1::asn1map($temp[0], Maps\RC2CBCParameter::MAP));
                        $effectiveKeyLength = (int) $rc2ParametersVersion->toString();
                        switch ($effectiveKeyLength) {
                            case 160:
                                $effectiveKeyLength = 40;
                                break;
                            case 120:
                                $effectiveKeyLength = 64;
                                break;
                            case 58:
                                $effectiveKeyLength = 128;
                                break;
                        }
                        $cipher->setIV($iv);
                        $cipher->setKeyLength($effectiveKeyLength);
                    }
                    $meta['meta']['keyDerivationFunc'] = $keyDerivationFunc['algorithm'];
                    switch ($keyDerivationFunc['algorithm']) {
                        case 'id-PBKDF2':
                            $temp = ASN1::decodeBER($keyDerivationFunc['parameters']);
                            $prf = ['algorithm' => 'id-hmacWithSHA1'];
                            $params = ASN1::asn1map($temp[0], Maps\PBKDF2params::MAP);
                            extract($params);
                            $meta['meta']['prf'] = $prf['algorithm'];
                            $hash = str_replace('-', '/', \Phabel\Target\Php80\Polyfill::substr($prf['algorithm'], 11));
                            $params = [$password, 'pbkdf2', $hash, $salt, (int) $iterationCount->toString()];
                            if (isset($keyLength)) {
                                $params[] = (int) $keyLength->toString();
                            }
                            $cipher->setPassword(...$params);
                            $key = $cipher->decrypt($decrypted['encryptedData']);
                            $decoded = ASN1::decodeBER($key);
                            if (empty($decoded)) {
                                throw new \RuntimeException('Unable to decode BER 3');
                            }
                            break;
                        default:
                            throw new UnsupportedAlgorithmException('Only PBKDF2 is supported for PBES2 PKCS#8 keys');
                    }
                    break;
                case 'id-PBMAC1':
                    //$temp = ASN1::decodeBER($decrypted['encryptionAlgorithm']['parameters']);
                    //$value = ASN1::asn1map($temp[0], Maps\PBMAC1params::MAP);
                    // since i can't find any implementation that does PBMAC1 it is unsupported
                    throw new UnsupportedAlgorithmException('Only PBES1 and PBES2 PKCS#8 keys are supported.');
            }
        }
        $private = ASN1::asn1map($decoded[0], Maps\OneAsymmetricKey::MAP);
        if (is_array($private)) {
            if (isset($private['privateKeyAlgorithm']['parameters']) && !$private['privateKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][1]['content'][1])) {
                $temp = $decoded[0]['content'][1]['content'][1];
                $private['privateKeyAlgorithm']['parameters'] = new ASN1\Element(\Phabel\Target\Php80\Polyfill::substr($key, $temp['start'], $temp['length']));
            }
            if (is_array(static::OID_NAME)) {
                if (!in_array($private['privateKeyAlgorithm']['algorithm'], static::OID_NAME)) {
                    throw new UnsupportedAlgorithmException($private['privateKeyAlgorithm']['algorithm'] . ' is not a supported key type');
                }
            } else {
                if ($private['privateKeyAlgorithm']['algorithm'] != static::OID_NAME) {
                    throw new UnsupportedAlgorithmException('Only ' . static::OID_NAME . ' keys are supported; this is a ' . $private['privateKeyAlgorithm']['algorithm'] . ' key');
                }
            }
            if (isset($private['publicKey'])) {
                if ($private['publicKey'][0] != "\x00") {
                    throw new \UnexpectedValueException('The first byte of the public key should be null - not ' . bin2hex($private['publicKey'][0]));
                }
                $private['publicKey'] = \Phabel\Target\Php80\Polyfill::substr($private['publicKey'], 1);
            }
            return $private + $meta;
        }
        // EncryptedPrivateKeyInfo and PublicKeyInfo have largely identical "signatures". the only difference
        // is that the former has an octet string and the later has a bit string. the first byte of a bit
        // string represents the number of bits in the last byte that are to be ignored but, currently,
        // bit strings wanting a non-zero amount of bits trimmed are not supported
        $public = ASN1::asn1map($decoded[0], Maps\PublicKeyInfo::MAP);
        if (is_array($public)) {
            if ($public['publicKey'][0] != "\x00") {
                throw new \UnexpectedValueException('The first byte of the public key should be null - not ' . bin2hex($public['publicKey'][0]));
            }
            if (is_array(static::OID_NAME)) {
                if (!in_array($public['publicKeyAlgorithm']['algorithm'], static::OID_NAME)) {
                    throw new UnsupportedAlgorithmException($public['publicKeyAlgorithm']['algorithm'] . ' is not a supported key type');
                }
            } else {
                if ($public['publicKeyAlgorithm']['algorithm'] != static::OID_NAME) {
                    throw new UnsupportedAlgorithmException('Only ' . static::OID_NAME . ' keys are supported; this is a ' . $public['publicKeyAlgorithm']['algorithm'] . ' key');
                }
            }
            if (isset($public['publicKeyAlgorithm']['parameters']) && !$public['publicKeyAlgorithm']['parameters'] instanceof ASN1\Element && isset($decoded[0]['content'][0]['content'][1])) {
                $temp = $decoded[0]['content'][0]['content'][1];
                $public['publicKeyAlgorithm']['parameters'] = new ASN1\Element(\Phabel\Target\Php80\Polyfill::substr($key, $temp['start'], $temp['length']));
            }
            $public['publicKey'] = \Phabel\Target\Php80\Polyfill::substr($public['publicKey'], 1);
            return $public;
        }
        throw new \RuntimeException('Unable to parse using either OneAsymmetricKey or PublicKeyInfo ASN1 maps');
    }
    /**
     * Wrap a private key appropriately
     *
     * @access public
     * @param string $key
     * @param string $attr
     * @param mixed $params
     * @param string $password
     * @param string $oid optional
     * @param string $publicKey optional
     * @param array $options optional
     * @return string
     */
    protected static function wrapPrivateKey($key, $attr, $params, $password, $oid = null, $publicKey = '', array $options = [])
    {
        self::initialize_static_variables();
        $key = ['version' => 'v1', 'privateKeyAlgorithm' => ['algorithm' => is_string(static::OID_NAME) ? static::OID_NAME : $oid, 'parameters' => $params], 'privateKey' => $key];
        if (!empty($attr)) {
            $key['attributes'] = $attr;
        }
        if (!empty($publicKey)) {
            $key['version'] = 'v2';
            $key['publicKey'] = $publicKey;
        }
        $key = ASN1::encodeDER($key, Maps\OneAsymmetricKey::MAP);
        if (!empty($password) && is_string($password)) {
            $salt = Random::string(8);
            $iterationCount = isset($options['iterationCount']) ? $options['iterationCount'] : self::$defaultIterationCount;
            $encryptionAlgorithm = isset($options['encryptionAlgorithm']) ? $options['encryptionAlgorithm'] : self::$defaultEncryptionAlgorithm;
            $encryptionScheme = isset($options['encryptionScheme']) ? $options['encryptionScheme'] : self::$defaultEncryptionScheme;
            $prf = isset($options['PRF']) ? $options['PRF'] : self::$defaultPRF;
            if ($encryptionAlgorithm == 'id-PBES2') {
                $crypto = self::getPBES2EncryptionObject($encryptionScheme);
                $hash = str_replace('-', '/', \Phabel\Target\Php80\Polyfill::substr($prf, 11));
                $kdf = 'pbkdf2';
                $iv = Random::string($crypto->getBlockLength() >> 3);
                $PBKDF2params = ['salt' => $salt, 'iterationCount' => $iterationCount, 'prf' => ['algorithm' => $prf, 'parameters' => null]];
                $PBKDF2params = ASN1::encodeDER($PBKDF2params, Maps\PBKDF2params::MAP);
                if (!$crypto instanceof RC2) {
                    $params = ['octetString' => $iv];
                } else {
                    $params = ['rc2ParametersVersion' => 58, 'iv' => $iv];
                    $params = ASN1::encodeDER($params, Maps\RC2CBCParameter::MAP);
                    $params = new ASN1\Element($params);
                }
                $params = ['keyDerivationFunc' => ['algorithm' => 'id-PBKDF2', 'parameters' => new ASN1\Element($PBKDF2params)], 'encryptionScheme' => ['algorithm' => $encryptionScheme, 'parameters' => $params]];
                $params = ASN1::encodeDER($params, Maps\PBES2params::MAP);
                $crypto->setIV($iv);
            } else {
                $crypto = self::getPBES1EncryptionObject($encryptionAlgorithm);
                $hash = self::getPBES1Hash($encryptionAlgorithm);
                $kdf = self::getPBES1KDF($encryptionAlgorithm);
                $params = ['salt' => $salt, 'iterationCount' => $iterationCount];
                $params = ASN1::encodeDER($params, Maps\PBEParameter::MAP);
            }
            $crypto->setPassword($password, $kdf, $hash, $salt, $iterationCount);
            $key = $crypto->encrypt($key);
            $key = ['encryptionAlgorithm' => ['algorithm' => $encryptionAlgorithm, 'parameters' => new ASN1\Element($params)], 'encryptedData' => $key];
            $key = ASN1::encodeDER($key, Maps\EncryptedPrivateKeyInfo::MAP);
            return "-----BEGIN ENCRYPTED PRIVATE KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END ENCRYPTED PRIVATE KEY-----";
        }
        return "-----BEGIN PRIVATE KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END PRIVATE KEY-----";
    }
    /**
     * Wrap a public key appropriately
     *
     * @access public
     * @param string $key
     * @param mixed $params
     * @param string $oid
     * @return string
     */
    protected static function wrapPublicKey($key, $params, $oid = null)
    {
        self::initialize_static_variables();
        $key = ['publicKeyAlgorithm' => ['algorithm' => is_string(static::OID_NAME) ? static::OID_NAME : $oid, 'parameters' => $params], 'publicKey' => "\x00" . $key];
        $key = ASN1::encodeDER($key, Maps\PublicKeyInfo::MAP);
        return "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(Base64::encode($key), 64) . "-----END PUBLIC KEY-----";
    }
    /**
     * Perform some preliminary parsing of the key
     *
     * @param string $key
     * @return array
     */
    private static function preParse(&$key)
    {
        self::initialize_static_variables();
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (self::$format != self::MODE_DER) {
            $decoded = ASN1::extractBER($key);
            if ($decoded !== false) {
                $key = $decoded;
            } elseif (self::$format == self::MODE_PEM) {
                throw new \UnexpectedValueException('Expected base64-encoded PEM format but was unable to decode base64 text');
            }
        }
        $decoded = ASN1::decodeBER($key);
        if (empty($decoded)) {
            throw new \RuntimeException('Unable to decode BER');
        }
        return $decoded;
    }
    /**
     * Returns the encryption parameters used by the key
     *
     * @param string $key
     * @return array
     */
    public static function extractEncryptionAlgorithm($key)
    {
        $decoded = self::preParse($key);
        $r = ASN1::asn1map($decoded[0], ASN1\Maps\EncryptedPrivateKeyInfo::MAP);
        if (!is_array($r)) {
            throw new \RuntimeException('Unable to parse using EncryptedPrivateKeyInfo map');
        }
        if ($r['encryptionAlgorithm']['algorithm'] == 'id-PBES2') {
            $decoded = ASN1::decodeBER($r['encryptionAlgorithm']['parameters']->element);
            $r['encryptionAlgorithm']['parameters'] = ASN1::asn1map($decoded[0], ASN1\Maps\PBES2params::MAP);
            $kdf =& $r['encryptionAlgorithm']['parameters']['keyDerivationFunc'];
            switch ($kdf['algorithm']) {
                case 'id-PBKDF2':
                    $decoded = ASN1::decodeBER($kdf['parameters']->element);
                    $kdf['parameters'] = ASN1::asn1map($decoded[0], Maps\PBKDF2params::MAP);
            }
        }
        return $r['encryptionAlgorithm'];
    }
}<?php

/**
 * PuTTY Formatted Key Handler
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib3\Crypt\AES;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Exception\UnsupportedAlgorithmException;
/**
 * PuTTY Formatted Key Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PuTTY
{
    /**
     * Default comment
     *
     * @var string
     * @access private
     */
    private static $comment = 'phpseclib-generated-key';
    /**
     * Sets the default comment
     *
     * @access public
     * @param string $comment
     */
    public static function setComment($comment)
    {
        self::$comment = str_replace(["\r", "\n"], '', $comment);
    }
    /**
     * Generate a symmetric key for PuTTY keys
     *
     * @access public
     * @param string $password
     * @param int $length
     * @return string
     */
    private static function generateSymmetricKey($password, $length)
    {
        $symkey = '';
        $sequence = 0;
        while (strlen($symkey) < $length) {
            $temp = pack('Na*', $sequence++, $password);
            $symkey .= Hex::decode(sha1($temp));
        }
        return \Phabel\Target\Php80\Polyfill::substr($symkey, 0, $length);
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * @access public
     * @param string $key
     * @param string $password
     * @return array
     */
    public static function load($key, $password)
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        if (strpos($key, 'BEGIN SSH2 PUBLIC KEY') !== false) {
            $lines = preg_split('#[\\r\\n]+#', $key);
            switch (true) {
                case $lines[0] != '---- BEGIN SSH2 PUBLIC KEY ----':
                    throw new \UnexpectedValueException('Key doesn\'t start with ---- BEGIN SSH2 PUBLIC KEY ----');
                case $lines[count($lines) - 1] != '---- END SSH2 PUBLIC KEY ----':
                    throw new \UnexpectedValueException('Key doesn\'t end with ---- END SSH2 PUBLIC KEY ----');
            }
            $lines = array_splice($lines, 1, -1);
            $lines = array_map(function ($line) {
                return rtrim($line, "\r\n");
            }, $lines);
            $data = $current = '';
            $values = [];
            $in_value = false;
            foreach ($lines as $line) {
                switch (true) {
                    case preg_match('#^(.*?): (.*)#', $line, $match):
                        $in_value = $line[strlen($line) - 1] == '\\';
                        $current = strtolower($match[1]);
                        $values[$current] = $in_value ? \Phabel\Target\Php80\Polyfill::substr($match[2], 0, -1) : $match[2];
                        break;
                    case $in_value:
                        $in_value = $line[strlen($line) - 1] == '\\';
                        $values[$current] .= $in_value ? \Phabel\Target\Php80\Polyfill::substr($line, 0, -1) : $line;
                        break;
                    default:
                        $data .= $line;
                }
            }
            $components = call_user_func([static::PUBLIC_HANDLER, 'load'], $data);
            if ($components === false) {
                throw new \UnexpectedValueException('Unable to decode public key');
            }
            $components += $values;
            $components['comment'] = str_replace(['\\\\', '\\"'], ['\\', '"'], $values['comment']);
            return $components;
        }
        $components = [];
        $key = preg_split('#\\r\\n|\\r|\\n#', trim($key));
        $type = trim(preg_replace('#PuTTY-User-Key-File-2: (.+)#', '$1', $key[0]));
        $components['type'] = $type;
        if (!in_array($type, static::$types)) {
            $error = count(static::$types) == 1 ? 'Only ' . static::$types[0] . ' keys are supported. ' : '';
            throw new UnsupportedAlgorithmException($error . 'This is an unsupported ' . $type . ' key');
        }
        $encryption = trim(preg_replace('#Encryption: (.+)#', '$1', $key[1]));
        $components['comment'] = trim(preg_replace('#Comment: (.+)#', '$1', $key[2]));
        $publicLength = trim(preg_replace('#Public-Lines: (\\d+)#', '$1', $key[3]));
        $public = Base64::decode(implode('', array_map('trim', array_slice($key, 4, $publicLength))));
        $source = Strings::packSSH2('ssss', $type, $encryption, $components['comment'], $public);
        extract(unpack('Nlength', Strings::shift($public, 4)));
        $newtype = Strings::shift($public, $length);
        if ($newtype != $type) {
            throw new \RuntimeException('The binary type does not match the human readable type field');
        }
        $components['public'] = $public;
        $privateLength = trim(preg_replace('#Private-Lines: (\\d+)#', '$1', $key[$publicLength + 4]));
        $private = Base64::decode(implode('', array_map('trim', array_slice($key, $publicLength + 5, $privateLength))));
        switch ($encryption) {
            case 'aes256-cbc':
                $symkey = self::generateSymmetricKey($password, 32);
                $crypto = new AES('cbc');
        }
        $hashkey = 'putty-private-key-file-mac-key';
        if ($encryption != 'none') {
            $hashkey .= $password;
            $crypto->setKey($symkey);
            $crypto->setIV(str_repeat("\x00", $crypto->getBlockLength() >> 3));
            $crypto->disablePadding();
            $private = $crypto->decrypt($private);
        }
        $source .= Strings::packSSH2('s', $private);
        $hash = new Hash('sha1');
        $hash->setKey(sha1($hashkey, true));
        $hmac = trim(preg_replace('#Private-MAC: (.+)#', '$1', $key[$publicLength + $privateLength + 5]));
        $hmac = Hex::decode($hmac);
        if (!hash_equals($hash->hash($source), $hmac)) {
            throw new \UnexpectedValueException('MAC validation error');
        }
        $components['private'] = $private;
        return $components;
    }
    /**
     * Wrap a private key appropriately
     *
     * @access private
     * @param string $public
     * @param string $private
     * @param string $type
     * @param string $password
     * @param array $options optional
     * @return string
     */
    protected static function wrapPrivateKey($public, $private, $type, $password, array $options = [])
    {
        $encryption = !empty($password) || is_string($password) ? 'aes256-cbc' : 'none';
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        $key = "PuTTY-User-Key-File-2: " . $type . "\r\nEncryption: ";
        $key .= $encryption;
        $key .= "\r\nComment: " . $comment . "\r\n";
        $public = Strings::packSSH2('s', $type) . $public;
        $source = Strings::packSSH2('ssss', $type, $encryption, $comment, $public);
        $public = Base64::encode($public);
        $key .= "Public-Lines: " . (strlen($public) + 63 >> 6) . "\r\n";
        $key .= chunk_split($public, 64);
        if (empty($password) && !is_string($password)) {
            $source .= Strings::packSSH2('s', $private);
            $hashkey = 'putty-private-key-file-mac-key';
        } else {
            $private .= Random::string(16 - (strlen($private) & 15));
            $source .= Strings::packSSH2('s', $private);
            $crypto = new AES('cbc');
            $crypto->setKey(self::generateSymmetricKey($password, 32));
            $crypto->setIV(str_repeat("\x00", $crypto->getBlockLength() >> 3));
            $crypto->disablePadding();
            $private = $crypto->encrypt($private);
            $hashkey = 'putty-private-key-file-mac-key' . $password;
        }
        $private = Base64::encode($private);
        $key .= 'Private-Lines: ' . (strlen($private) + 63 >> 6) . "\r\n";
        $key .= chunk_split($private, 64);
        $hash = new Hash('sha1');
        $hash->setKey(sha1($hashkey, true));
        $key .= 'Private-MAC: ' . Hex::encode($hash->hash($source)) . "\r\n";
        return $key;
    }
    /**
     * Wrap a public key appropriately
     *
     * This is basically the format described in RFC 4716 (https://tools.ietf.org/html/rfc4716)
     *
     * @access private
     * @param string $key
     * @param string $type
     * @return string
     */
    protected static function wrapPublicKey($key, $type)
    {
        $key = pack('Na*a*', strlen($type), $type, $key);
        $key = '---- BEGIN SSH2 PUBLIC KEY ----
Comment: "' . str_replace(['\\', '"'], ['\\\\', '\\"'], self::$comment) . "\"\r\n" . chunk_split(Base64::encode($key), 64) . '---- END SSH2 PUBLIC KEY ----';
        return $key;
    }
}<?php

/**
 * OpenSSH Key Handler
 *
 * PHP version 5
 *
 * Place in $HOME/.ssh/authorized_keys
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Keys;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Random;
use phpseclib3\Exception\UnsupportedFormatException;
/**
 * OpenSSH Formatted RSA Key Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSH
{
    /**
     * Default comment
     *
     * @var string
     * @access private
     */
    protected static $comment = 'phpseclib-generated-key';
    /**
     * Binary key flag
     *
     * @var bool
     * @access private
     */
    protected static $binary = false;
    /**
     * Sets the default comment
     *
     * @access public
     * @param string $comment
     */
    public static function setComment($comment)
    {
        self::$comment = str_replace(["\r", "\n"], '', $comment);
    }
    /**
     * Break a public or private key down into its constituent components
     *
     * $type can be either ssh-dss or ssh-rsa
     *
     * @access public
     * @param string $key
     * @param string $password
     * @return array
     */
    public static function load($key, $password = '')
    {
        if (!Strings::is_stringable($key)) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        // key format is described here:
        // https://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL.key?annotate=HEAD
        if (strpos($key, 'BEGIN OPENSSH PRIVATE KEY') !== false) {
            $key = preg_replace('#(?:^-.*?-[\\r\\n]*$)|\\s#ms', '', $key);
            $key = Base64::decode($key);
            $magic = Strings::shift($key, 15);
            if ($magic != "openssh-key-v1\x00") {
                throw new \RuntimeException('Expected openssh-key-v1');
            }
            list($ciphername, $kdfname, $kdfoptions, $numKeys) = Strings::unpackSSH2('sssN', $key);
            if ($numKeys != 1) {
                // if we wanted to support multiple keys we could update PublicKeyLoader to preview what the # of keys
                // would be; it'd then call Common\Keys\OpenSSH.php::load() and get the paddedKey. it'd then pass
                // that to the appropriate key loading parser $numKey times or something
                throw new \RuntimeException('Although the OpenSSH private key format supports multiple keys phpseclib does not');
            }
            if (strlen($kdfoptions) || $kdfname != 'none' || $ciphername != 'none') {
                /*
                  OpenSSH private keys use a customized version of bcrypt. specifically, instead of encrypting
                  OrpheanBeholderScryDoubt 64 times OpenSSH's bcrypt variant encrypts
                  OxychromaticBlowfishSwatDynamite 64 times. so we can't use crypt().
                
                  bcrypt is basically Blowfish with an altered key expansion. whereas Blowfish just runs the
                  key through the key expansion bcrypt interleaves the key expansion with the salt and
                  password. this renders openssl / mcrypt unusuable. this forces us to use a pure-PHP implementation
                  of bcrypt. the problem with that is that pure-PHP is too slow to be practically useful.
                
                  in addition to encrypting a different string 64 times the OpenSSH implementation also performs bcrypt
                  from scratch $rounds times. calling crypt() 64x with bcrypt takes 0.7s. PHP is going to be naturally
                  slower. pure-PHP is 215x slower than OpenSSL for AES and pure-PHP is 43x slower for bcrypt.
                  43 * 0.7 = 30s. no one wants to wait 30s to load a private key.
                
                  another way to think about this..  according to wikipedia's article on Blowfish,
                  "Each new key requires pre-processing equivalent to encrypting about 4 kilobytes of text".
                  key expansion is done (9+64*2)*160 times. multiply that by 4 and it turns out that Blowfish,
                  OpenSSH style, is the equivalent of encrypting ~80mb of text.
                
                  more supporting evidence: sodium_compat does not implement Argon2 (another password hashing
                  algorithm) because "It's not feasible to polyfill scrypt or Argon2 into PHP and get reasonable
                  performance. Users would feel motivated to select parameters that downgrade security to avoid
                  denial of service (DoS) attacks. The only winning move is not to play"
                    -- https://github.com/paragonie/sodium_compat/blob/master/README.md
                */
                throw new \RuntimeException('Encrypted OpenSSH private keys are not supported');
                //list($salt, $rounds) = Strings::unpackSSH2('sN', $kdfoptions);
            }
            list($publicKey, $paddedKey) = Strings::unpackSSH2('ss', $key);
            list($type) = Strings::unpackSSH2('s', $publicKey);
            list($checkint1, $checkint2) = Strings::unpackSSH2('NN', $paddedKey);
            // any leftover bytes in $paddedKey are for padding? but they should be sequential bytes. eg. 1, 2, 3, etc.
            if ($checkint1 != $checkint2) {
                throw new \RuntimeException('The two checkints do not match');
            }
            self::checkType($type);
            return compact('type', 'publicKey', 'paddedKey');
        }
        $parts = explode(' ', $key, 3);
        if (!isset($parts[1])) {
            $key = base64_decode($parts[0]);
            $comment = isset($parts[1]) ? $parts[1] : false;
        } else {
            $asciiType = $parts[0];
            self::checkType($parts[0]);
            $key = base64_decode($parts[1]);
            $comment = isset($parts[2]) ? $parts[2] : false;
        }
        if ($key === false) {
            throw new \UnexpectedValueException('Key should be a string - not a ' . gettype($key));
        }
        list($type) = Strings::unpackSSH2('s', $key);
        self::checkType($type);
        if (isset($asciiType) && $asciiType != $type) {
            throw new \RuntimeException('Two different types of keys are claimed: ' . $asciiType . ' and ' . $type);
        }
        if (strlen($key) <= 4) {
            throw new \UnexpectedValueException('Key appears to be malformed');
        }
        $publicKey = $key;
        return compact('type', 'publicKey', 'comment');
    }
    /**
    * Toggle between binary and printable keys
    *
    * Printable keys are what are generated by default. These are the ones that go in
    $HOME/.ssh/authorized_key.
    *
    * @access public
    * @param bool $enabled
    */
    public static function setBinaryOutput($enabled)
    {
        self::$binary = $enabled;
    }
    /**
     * Checks to see if the type is valid
     *
     * @access private
     * @param string $candidate
     */
    private static function checkType($candidate)
    {
        if (!in_array($candidate, static::$types)) {
            throw new \RuntimeException("The key type ({$candidate}) is not equal to: " . implode(',', static::$types));
        }
    }
    /**
     * Wrap a private key appropriately
     *
     * @access public
     * @param string $publicKey
     * @param string $privateKey
     * @param string $password
     * @param array $options
     * @return string
     */
    protected static function wrapPrivateKey($publicKey, $privateKey, $password, $options)
    {
        if (!empty($password) && is_string($password)) {
            throw new UnsupportedFormatException('Encrypted OpenSSH private keys are not supported');
        }
        list(, $checkint) = unpack('N', Random::string(4));
        $comment = isset($options['comment']) ? $options['comment'] : self::$comment;
        $paddedKey = Strings::packSSH2('NN', $checkint, $checkint) . $privateKey . Strings::packSSH2('s', $comment);
        /*
          from http://tools.ietf.org/html/rfc4253#section-6 :
        
          Note that the length of the concatenation of 'packet_length',
          'padding_length', 'payload', and 'random padding' MUST be a multiple
          of the cipher block size or 8, whichever is larger.
        */
        $paddingLength = 7 * strlen($paddedKey) % 8;
        for ($i = 1; $i <= $paddingLength; $i++) {
            $paddedKey .= chr($i);
        }
        $key = Strings::packSSH2('sssNss', 'none', 'none', '', 1, $publicKey, $paddedKey);
        $key = "openssh-key-v1\x00{$key}";
        return "-----BEGIN OPENSSH PRIVATE KEY-----\n" . chunk_split(Base64::encode($key), 70, "\n") . "-----END OPENSSH PRIVATE KEY-----\n";
    }
}<?php

/**
 * Raw Signature Handler
 *
 * PHP version 5
 *
 * Handles signatures as arrays
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Formats\Signature;

use phpseclib3\Math\BigInteger;
/**
 * Raw Signature Handler
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Raw
{
    /**
     * Loads a signature
     *
     * @access public
     * @param array $sig
     * @return (array | bool)
     */
    public static function load($sig)
    {
        switch (true) {
            case !is_array($sig):
            case !isset($sig['r']) || !isset($sig['s']):
            case !$sig['r'] instanceof BigInteger:
            case !$sig['s'] instanceof BigInteger:
                return false;
        }
        return ['r' => $sig['r'], 's' => $sig['s']];
    }
    /**
     * Returns a signature in the appropriate format
     *
     * @access public
     * @param \phpseclib3\Math\BigInteger $r
     * @param \phpseclib3\Math\BigInteger $s
     * @return string
     */
    public static function save(BigInteger $r, BigInteger $s)
    {
        return compact('r', 's');
    }
}<?php

/**
 * Base Class for all block ciphers
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   BlockCipher
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

/**
 * Base Class for all block cipher classes
 *
 * @package BlockCipher
 * @author  Jim Wigginton <terrafrost@php.net>
 */
abstract class BlockCipher extends SymmetricKey
{
}<?php

/**
 * PrivateKey interface
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

/**
 * PrivateKey interface
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
interface PrivateKey
{
    /**
     *
     */
    public function sign($message);
    //public function decrypt($ciphertext);
    /**
     *
     */
    public function getPublicKey();
    /**
     *
     */
    public function toString($type, array $options = []);
    /**
     *
     */
    public function withPassword($string = false);
}<?php

/**
 * PublicKey interface
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

/**
 * PublicKey interface
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
interface PublicKey
{
    /**
     *
     */
    public function verify($message, $signature);
    //public function encrypt($plaintext);
    /**
     *
     */
    public function toString($type, array $options = []);
    /**
     *
     */
    public function getFingerprint($algorithm);
}<?php

/**
 * Base Class for all stream ciphers
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   StreamCipher
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

/**
 * Base Class for all stream cipher classes
 *
 * @package StreamCipher
 * @author  Jim Wigginton <terrafrost@php.net>
 */
abstract class StreamCipher extends SymmetricKey
{
    /**
     * Block Length of the cipher
     *
     * Stream ciphers do not have a block size
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
     * @var int
     * @access private
     */
    protected $block_size = 0;
    /**
     * Default Constructor.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @return \phpseclib3\Crypt\Common\StreamCipher
     */
    public function __construct()
    {
        parent::__construct('stream');
    }
    /**
     * Stream ciphers not use an IV
     *
     * @access public
     * @return bool
     */
    public function usesIV()
    {
        return false;
    }
}<?php

/**
 * Base Class for all \phpseclib3\Crypt\* cipher classes
 *
 * PHP version 5
 *
 * Internally for phpseclib developers:
 *  If you plan to add a new cipher class, please note following rules:
 *
 *  - The new \phpseclib3\Crypt\* cipher class should extend \phpseclib3\Crypt\Common\SymmetricKey
 *
 *  - Following methods are then required to be overridden/overloaded:
 *
 *    - encryptBlock()
 *
 *    - decryptBlock()
 *
 *    - setupKey()
 *
 *  - All other methods are optional to be overridden/overloaded
 *
 *  - Look at the source code of the current ciphers how they extend \phpseclib3\Crypt\Common\SymmetricKey
 *    and take one of them as a start up for the new cipher class.
 *
 *  - Please read all the other comments/notes/hints here also for each class var/method
 *
 * @category  Crypt
 * @package   Base
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

use phpseclib3\Crypt\Hash;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\BinaryField;
use phpseclib3\Math\PrimeField;
use phpseclib3\Exception\BadDecryptionException;
use phpseclib3\Exception\BadModeException;
use phpseclib3\Exception\InconsistentSetupException;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Exception\UnsupportedAlgorithmException;
/**
 * Base Class for all \phpseclib3\Crypt\* cipher classes
 *
 * @package Base
 * @author  Jim Wigginton <terrafrost@php.net>
 * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
 */
abstract class SymmetricKey
{
    /**
     * Encrypt / decrypt using the Counter mode.
     *
     * Set to -1 since that's what Crypt/Random.php uses to index the CTR mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Counter_.28CTR.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_CTR = -1;
    /**
     * Encrypt / decrypt using the Electronic Code Book mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_ECB = 1;
    /**
     * Encrypt / decrypt using the Code Book Chaining mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_CBC = 2;
    /**
     * Encrypt / decrypt using the Cipher Feedback mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher_feedback_.28CFB.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_CFB = 3;
    /**
     * Encrypt / decrypt using the Cipher Feedback mode (8bit)
     *
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_CFB8 = 38;
    /**
     * Encrypt / decrypt using the Output Feedback mode.
     *
     * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Output_feedback_.28OFB.29
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_OFB = 4;
    /**
     * Encrypt / decrypt using Galois/Counter mode.
     *
     * @link https://en.wikipedia.org/wiki/Galois/Counter_Mode
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_GCM = 5;
    /**
     * Encrypt / decrypt using streaming mode.
     *
     * @access public
     * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     */
    const MODE_STREAM = 6;
    /**
     * Mode Map
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const MODE_MAP = ['ctr' => self::MODE_CTR, 'ecb' => self::MODE_ECB, 'cbc' => self::MODE_CBC, 'cfb' => self::MODE_CFB, 'cfb8' => self::MODE_CFB8, 'ofb' => self::MODE_OFB, 'gcm' => self::MODE_GCM, 'stream' => self::MODE_STREAM];
    /**
     * Base value for the internal implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_INTERNAL = 1;
    /**
     * Base value for the eval() implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_EVAL = 2;
    /**
     * Base value for the mcrypt implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_MCRYPT = 3;
    /**
     * Base value for the openssl implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_OPENSSL = 4;
    /**
     * Base value for the libsodium implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_LIBSODIUM = 5;
    /**
     * Base value for the openssl / gcm implementation $engine switch
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     */
    const ENGINE_OPENSSL_GCM = 6;
    /**
     * Engine Reverse Map
     *
     * @access private
     * @see \phpseclib3\Crypt\Common\SymmetricKey::getEngine()
     */
    const ENGINE_MAP = [self::ENGINE_INTERNAL => 'PHP', self::ENGINE_EVAL => 'Eval', self::ENGINE_MCRYPT => 'mcrypt', self::ENGINE_OPENSSL => 'OpenSSL', self::ENGINE_LIBSODIUM => 'libsodium', self::ENGINE_OPENSSL_GCM => 'OpenSSL (GCM)'];
    /**
     * The Encryption Mode
     *
     * @see self::__construct()
     * @var int
     * @access private
     */
    protected $mode;
    /**
     * The Block Length of the block cipher
     *
     * @var int
     * @access private
     */
    protected $block_size = 16;
    /**
     * The Key
     *
     * @see self::setKey()
     * @var string
     * @access private
     */
    protected $key = false;
    /**
     * The Initialization Vector
     *
     * @see self::setIV()
     * @var string
     * @access private
     */
    protected $iv = false;
    /**
     * A "sliding" Initialization Vector
     *
     * @see self::enableContinuousBuffer()
     * @see self::clearBuffers()
     * @var string
     * @access private
     */
    protected $encryptIV;
    /**
     * A "sliding" Initialization Vector
     *
     * @see self::enableContinuousBuffer()
     * @see self::clearBuffers()
     * @var string
     * @access private
     */
    protected $decryptIV;
    /**
     * Continuous Buffer status
     *
     * @see self::enableContinuousBuffer()
     * @var bool
     * @access private
     */
    protected $continuousBuffer = false;
    /**
     * Encryption buffer for CTR, OFB and CFB modes
     *
     * @see self::encrypt()
     * @see self::clearBuffers()
     * @var array
     * @access private
     */
    protected $enbuffer;
    /**
     * Decryption buffer for CTR, OFB and CFB modes
     *
     * @see self::decrypt()
     * @see self::clearBuffers()
     * @var array
     * @access private
     */
    protected $debuffer;
    /**
     * mcrypt resource for encryption
     *
     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
     *
     * @see self::encrypt()
     * @var resource
     * @access private
     */
    private $enmcrypt;
    /**
     * mcrypt resource for decryption
     *
     * The mcrypt resource can be recreated every time something needs to be created or it can be created just once.
     * Since mcrypt operates in continuous mode, by default, it'll need to be recreated when in non-continuous mode.
     *
     * @see self::decrypt()
     * @var resource
     * @access private
     */
    private $demcrypt;
    /**
     * Does the enmcrypt resource need to be (re)initialized?
     *
     * @see \phpseclib3\Crypt\Twofish::setKey()
     * @see \phpseclib3\Crypt\Twofish::setIV()
     * @var bool
     * @access private
     */
    private $enchanged = true;
    /**
     * Does the demcrypt resource need to be (re)initialized?
     *
     * @see \phpseclib3\Crypt\Twofish::setKey()
     * @see \phpseclib3\Crypt\Twofish::setIV()
     * @var bool
     * @access private
     */
    private $dechanged = true;
    /**
     * mcrypt resource for CFB mode
     *
     * mcrypt's CFB mode, in (and only in) buffered context,
     * is broken, so phpseclib implements the CFB mode by it self,
     * even when the mcrypt php extension is available.
     *
     * In order to do the CFB-mode work (fast) phpseclib
     * use a separate ECB-mode mcrypt resource.
     *
     * @link http://phpseclib.sourceforge.net/cfb-demo.phps
     * @see self::encrypt()
     * @see self::decrypt()
     * @see self::setupMcrypt()
     * @var resource
     * @access private
     */
    private $ecb;
    /**
     * Optimizing value while CFB-encrypting
     *
     * Only relevant if $continuousBuffer enabled
     * and $engine == self::ENGINE_MCRYPT
     *
     * It's faster to re-init $enmcrypt if
     * $buffer bytes > $cfb_init_len than
     * using the $ecb resource furthermore.
     *
     * This value depends of the chosen cipher
     * and the time it would be needed for it's
     * initialization [by mcrypt_generic_init()]
     * which, typically, depends on the complexity
     * on its internaly Key-expanding algorithm.
     *
     * @see self::encrypt()
     * @var int
     * @access private
     */
    protected $cfb_init_len = 600;
    /**
     * Does internal cipher state need to be (re)initialized?
     *
     * @see self::setKey()
     * @see self::setIV()
     * @see self::disableContinuousBuffer()
     * @var bool
     * @access private
     */
    protected $changed = true;
    /**
     * Does Eval engie need to be (re)initialized?
     *
     * @see self::setup()
     * @var bool
     * @access private
     */
    protected $nonIVChanged = true;
    /**
     * Padding status
     *
     * @see self::enablePadding()
     * @var bool
     * @access private
     */
    private $padding = true;
    /**
     * Is the mode one that is paddable?
     *
     * @see self::__construct()
     * @var bool
     * @access private
     */
    private $paddable = false;
    /**
     * Holds which crypt engine internaly should be use,
     * which will be determined automatically on __construct()
     *
     * Currently available $engines are:
     * - self::ENGINE_LIBSODIUM   (very fast, php-extension: libsodium, extension_loaded('libsodium') required)
     * - self::ENGINE_OPENSSL_GCM (very fast, php-extension: openssl, extension_loaded('openssl') required)
     * - self::ENGINE_OPENSSL     (very fast, php-extension: openssl, extension_loaded('openssl') required)
     * - self::ENGINE_MCRYPT      (fast, php-extension: mcrypt, extension_loaded('mcrypt') required)
     * - self::ENGINE_EVAL        (medium, pure php-engine, no php-extension required)
     * - self::ENGINE_INTERNAL    (slower, pure php-engine, no php-extension required)
     *
     * @see self::setEngine()
     * @see self::encrypt()
     * @see self::decrypt()
     * @var int
     * @access private
     */
    protected $engine;
    /**
     * Holds the preferred crypt engine
     *
     * @see self::setEngine()
     * @see self::setPreferredEngine()
     * @var int
     * @access private
     */
    private $preferredEngine;
    /**
     * The mcrypt specific name of the cipher
     *
     * Only used if $engine == self::ENGINE_MCRYPT
     *
     * @link http://www.php.net/mcrypt_module_open
     * @link http://www.php.net/mcrypt_list_algorithms
     * @see self::setupMcrypt()
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt;
    /**
     * The openssl specific name of the cipher
     *
     * Only used if $engine == self::ENGINE_OPENSSL
     *
     * @link http://www.php.net/openssl-get-cipher-methods
     * @var string
     * @access private
     */
    protected $cipher_name_openssl;
    /**
     * The openssl specific name of the cipher in ECB mode
     *
     * If OpenSSL does not support the mode we're trying to use (CTR)
     * it can still be emulated with ECB mode.
     *
     * @link http://www.php.net/openssl-get-cipher-methods
     * @var string
     * @access private
     */
    protected $cipher_name_openssl_ecb;
    /**
     * The default salt used by setPassword()
     *
     * @see self::setPassword()
     * @var string
     * @access private
     */
    private $password_default_salt = 'phpseclib/salt';
    /**
     * The name of the performance-optimized callback function
     *
     * Used by encrypt() / decrypt()
     * only if $engine == self::ENGINE_INTERNAL
     *
     * @see self::encrypt()
     * @see self::decrypt()
     * @see self::setupInlineCrypt()
     * @var Callback
     * @access private
     */
    protected $inline_crypt;
    /**
     * If OpenSSL can be used in ECB but not in CTR we can emulate CTR
     *
     * @see self::openssl_ctr_process()
     * @var bool
     * @access private
     */
    private $openssl_emulate_ctr = false;
    /**
     * Don't truncate / null pad key
     *
     * @see self::clearBuffers()
     * @var bool
     * @access private
     */
    private $skip_key_adjustment = false;
    /**
     * Has the key length explicitly been set or should it be derived from the key, itself?
     *
     * @see self::setKeyLength()
     * @var bool
     * @access private
     */
    protected $explicit_key_length = false;
    /**
     * Hash subkey for GHASH
     *
     * @see self::setupGCM()
     * @see self::ghash()
     * @var BinaryField\Integer
     * @access private
     */
    private $h;
    /**
     * Additional authenticated data
     *
     * @var string
     * @access private
     */
    protected $aad = '';
    /**
     * Authentication Tag produced after a round of encryption
     *
     * @var string
     * @access private
     */
    protected $newtag = false;
    /**
     * Authentication Tag to be verified during decryption
     *
     * @var string
     * @access private
     */
    protected $oldtag = false;
    /**
     * GCM Binary Field
     *
     * @see self::__construct()
     * @see self::ghash()
     * @var BinaryField
     * @access private
     */
    private static $gcmField;
    /**
     * Poly1305 Prime Field
     *
     * @see self::enablePoly1305()
     * @see self::poly1305()
     * @var PrimeField
     * @access private
     */
    private static $poly1305Field;
    /**
     * Poly1305 Key
     *
     * @see self::setPoly1305Key()
     * @see self::poly1305()
     * @var string
     * @access private
     */
    protected $poly1305Key;
    /**
     * Poly1305 Flag
     *
     * @see self::setPoly1305Key()
     * @see self::enablePoly1305()
     * @var boolean
     * @access private
     */
    protected $usePoly1305 = false;
    /**
     * The Original Initialization Vector
     *
     * GCM uses the nonce to build the IV but we want to be able to distinguish between nonce-derived
     * IV's and user-set IV's
     *
     * @see self::setIV()
     * @var string
     * @access private
     */
    private $origIV = false;
    /**
     * Nonce
     *
     * Only used with GCM. We could re-use setIV() but nonce's can be of a different length and
     * toggling between GCM and other modes could be more complicated if we re-used setIV()
     *
     * @see self::setNonce()
     * @var string
     * @access private
     */
    protected $nonce = false;
    /**
     * Default Constructor.
     *
     * $mode could be:
     *
     * - ecb
     *
     * - cbc
     *
     * - ctr
     *
     * - cfb
     *
     * - cfb8
     *
     * - ofb
     *
     * - gcm
     *
     * @param string $mode
     * @access public
     * @throws BadModeException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        $mode = strtolower($mode);
        // necessary because of 5.6 compatibility; we can't do isset(self::MODE_MAP[$mode]) in 5.6
        $map = self::MODE_MAP;
        if (!isset($map[$mode])) {
            throw new BadModeException('No valid mode has been specified');
        }
        $mode = self::MODE_MAP[$mode];
        // $mode dependent settings
        switch ($mode) {
            case self::MODE_ECB:
            case self::MODE_CBC:
                $this->paddable = true;
                break;
            case self::MODE_CTR:
            case self::MODE_CFB:
            case self::MODE_CFB8:
            case self::MODE_OFB:
            case self::MODE_STREAM:
                $this->paddable = false;
                break;
            case self::MODE_GCM:
                if ($this->block_size != 16) {
                    throw new BadModeException('GCM is only valid for block ciphers with a block size of 128 bits');
                }
                if (!isset(self::$gcmField)) {
                    self::$gcmField = new BinaryField(128, 7, 2, 1, 0);
                }
                $this->paddable = false;
                break;
            default:
                throw new BadModeException('No valid mode has been specified');
        }
        $this->mode = $mode;
    }
    /**
     * Sets the initialization vector.
     *
     * setIV() is not required when ecb or gcm modes are being used.
     *
     * {@internal Can be overwritten by a sub class, but does not have to be}
     *
     * @access public
     * @param string $iv
     * @throws \LengthException if the IV length isn't equal to the block size
     * @throws \BadMethodCallException if an IV is provided when one shouldn't be
     */
    public function setIV($iv)
    {
        if ($this->mode == self::MODE_ECB) {
            throw new \BadMethodCallException('This mode does not require an IV.');
        }
        if ($this->mode == self::MODE_GCM) {
            throw new \BadMethodCallException('Use setNonce instead');
        }
        if (!$this->usesIV()) {
            throw new \BadMethodCallException('This algorithm does not use an IV.');
        }
        if (strlen($iv) != $this->block_size) {
            throw new \LengthException('Received initialization vector of size ' . strlen($iv) . ', but size ' . $this->block_size . ' is required');
        }
        $this->iv = $this->origIV = $iv;
        $this->changed = true;
    }
    /**
     * Enables Poly1305 mode.
     *
     * Once enabled Poly1305 cannot be disabled.
     *
     * @access public
     * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode
     */
    public function enablePoly1305()
    {
        if ($this->mode == self::MODE_GCM) {
            throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode');
        }
        $this->usePoly1305 = true;
    }
    /**
    * Enables Poly1305 mode.
    *
    * Once enabled Poly1305 cannot be disabled. If $key is not passed then an attempt to call createPoly1305Key
    will be made.
    *
    * @access public
    * @param string $key optional
    * @throws \LengthException if the key isn't long enough
    * @throws \BadMethodCallException if Poly1305 is enabled whilst in GCM mode
    */
    public function setPoly1305Key($key = null)
    {
        if ($this->mode == self::MODE_GCM) {
            throw new \BadMethodCallException('Poly1305 cannot be used in GCM mode');
        }
        if (!is_string($key) || strlen($key) != 32) {
            throw new \LengthException('The Poly1305 key must be 32 bytes long (256 bits)');
        }
        if (!isset(self::$poly1305Field)) {
            // 2^130-5
            self::$poly1305Field = new PrimeField(new BigInteger('3fffffffffffffffffffffffffffffffb', 16));
        }
        $this->poly1305Key = $key;
        $this->usePoly1305 = true;
    }
    /**
     * Sets the nonce.
     *
     * setNonce() is only required when gcm is used
     *
     * @access public
     * @param string $nonce
     * @throws \BadMethodCallException if an nonce is provided when one shouldn't be
     */
    public function setNonce($nonce)
    {
        if ($this->mode != self::MODE_GCM) {
            throw new \BadMethodCallException('Nonces are only used in GCM mode.');
        }
        $this->nonce = $nonce;
        $this->setEngine();
    }
    /**
     * Sets additional authenticated data
     *
     * setAAD() is only used by gcm or in poly1305 mode
     *
     * @access public
     * @param string $aad
     * @throws \BadMethodCallException if mode isn't GCM or if poly1305 isn't being utilized
     */
    public function setAAD($aad)
    {
        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
            throw new \BadMethodCallException('Additional authenticated data is only utilized in GCM mode or with Poly1305');
        }
        $this->aad = $aad;
    }
    /**
     * Returns whether or not the algorithm uses an IV
     *
     * @access public
     * @return bool
     */
    public function usesIV()
    {
        return $this->mode != self::MODE_GCM && $this->mode != self::MODE_ECB;
    }
    /**
     * Returns whether or not the algorithm uses a nonce
     *
     * @access public
     * @return bool
     */
    public function usesNonce()
    {
        return $this->mode == self::MODE_GCM;
    }
    /**
     * Returns the current key length in bits
     *
     * @access public
     * @return int
     */
    public function getKeyLength()
    {
        return $this->key_length << 3;
    }
    /**
     * Returns the current block length in bits
     *
     * @access public
     * @return int
     */
    public function getBlockLength()
    {
        return $this->block_size << 3;
    }
    /**
     * Returns the current block length in bytes
     *
     * @access public
     * @return int
     */
    public function getBlockLengthInBytes()
    {
        return $this->block_size;
    }
    /**
     * Sets the key length.
     *
     * Keys with explicitly set lengths need to be treated accordingly
     *
     * @access public
     * @param int $length
     */
    public function setKeyLength($length)
    {
        $this->explicit_key_length = $length >> 3;
        if (is_string($this->key) && strlen($this->key) != $this->explicit_key_length) {
            $this->key = false;
            throw new InconsistentSetupException('Key has already been set and is not ' . $this->explicit_key_length . ' bytes long');
        }
    }
    /**
    * Sets the key.
    *
    * The min/max length(s) of the key depends on the cipher which is used.
    If the key not fits the length(s) of the cipher it will paded with null bytes
    up to the closest valid key length.  If the key is more than max length,
    we trim the excess bits.
    *
    * If the key is not explicitly set, it'll be assumed to be all null bytes.
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @access public
    * @param string $key
    */
    public function setKey($key)
    {
        if ($this->explicit_key_length !== false && strlen($key) != $this->explicit_key_length) {
            throw new InconsistentSetupException('Key length has already been set to ' . $this->explicit_key_length . ' bytes and this key is ' . strlen($key) . ' bytes');
        }
        $this->key = $key;
        $this->key_length = strlen($key);
        $this->setEngine();
    }
    /**
    * Sets the password.
    *
    * Depending on what $method is set to, setPassword()'s (optional) parameters are as follows:
    {@link http://en.wikipedia.org/wiki/PBKDF2 pbkdf2} or pbkdf1:
    $hash, $salt, $count, $dkLen
    *
    * Where $hash (default = sha1) currently supports the following hashes: see: Crypt/Hash.php
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see Crypt/Hash.php
    * @param string $password
    * @param string $method
    * @param string[] ...$func_args
    * @throws \LengthException if pbkdf1 is being used and the derived key length exceeds the hash length
    * @return bool
    * @access public
    */
    public function setPassword($password, $method = 'pbkdf2', ...$func_args)
    {
        $key = '';
        $method = strtolower($method);
        switch ($method) {
            case 'pkcs12':
            // from https://tools.ietf.org/html/rfc7292#appendix-B.2
            case 'pbkdf1':
            case 'pbkdf2':
                // Hash function
                $hash = isset($func_args[0]) ? strtolower($func_args[0]) : 'sha1';
                $hashObj = new Hash();
                $hashObj->setHash($hash);
                // WPA and WPA2 use the SSID as the salt
                $salt = isset($func_args[1]) ? $func_args[1] : $this->password_default_salt;
                // RFC2898#section-4.2 uses 1,000 iterations by default
                // WPA and WPA2 use 4,096.
                $count = isset($func_args[2]) ? $func_args[2] : 1000;
                // Keylength
                if (isset($func_args[3])) {
                    if ($func_args[3] <= 0) {
                        throw new \LengthException('Derived key length cannot be longer 0 or less');
                    }
                    $dkLen = $func_args[3];
                } else {
                    $key_length = $this->explicit_key_length !== false ? $this->explicit_key_length : $this->key_length;
                    $dkLen = $method == 'pbkdf1' ? 2 * $key_length : $key_length;
                }
                switch (true) {
                    case $method == 'pkcs12':
                        /*
                        In this specification, however, all passwords are created from
                        BMPStrings with a NULL terminator.  This means that each character in
                        the original BMPString is encoded in 2 bytes in big-endian format
                        (most-significant byte first).  There are no Unicode byte order
                        marks.  The 2 bytes produced from the last character in the BMPString
                        are followed by 2 additional bytes with the value 0x00.
                        
                        -- https://tools.ietf.org/html/rfc7292#appendix-B.1
                        */
                        $password = "\x00" . chunk_split($password, 1, "\x00") . "\x00";
                        /*
                        This standard specifies 3 different values for the ID byte mentioned
                        above:
                        
                        1.  If ID=1, then the pseudorandom bits being produced are to be used
                            as key material for performing encryption or decryption.
                        
                        2.  If ID=2, then the pseudorandom bits being produced are to be used
                            as an IV (Initial Value) for encryption or decryption.
                        
                        3.  If ID=3, then the pseudorandom bits being produced are to be used
                            as an integrity key for MACing.
                        */
                        // Construct a string, D (the "diversifier"), by concatenating v/8
                        // copies of ID.
                        $blockLength = $hashObj->getBlockLengthInBytes();
                        $d1 = str_repeat(chr(1), $blockLength);
                        $d2 = str_repeat(chr(2), $blockLength);
                        $s = '';
                        if (strlen($salt)) {
                            while (strlen($s) < $blockLength) {
                                $s .= $salt;
                            }
                        }
                        $s = \Phabel\Target\Php80\Polyfill::substr($s, 0, $blockLength);
                        $p = '';
                        if (strlen($password)) {
                            while (strlen($p) < $blockLength) {
                                $p .= $password;
                            }
                        }
                        $p = \Phabel\Target\Php80\Polyfill::substr($p, 0, $blockLength);
                        $i = $s . $p;
                        $this->setKey(self::pkcs12helper($dkLen, $hashObj, $i, $d1, $count));
                        if ($this->usesIV()) {
                            $this->setIV(self::pkcs12helper($this->block_size, $hashObj, $i, $d2, $count));
                        }
                        return true;
                    case $method == 'pbkdf1':
                        if ($dkLen > $hashObj->getLengthInBytes()) {
                            throw new \LengthException('Derived key length cannot be longer than the hash length');
                        }
                        $t = $password . $salt;
                        for ($i = 0; $i < $count; ++$i) {
                            $t = $hashObj->hash($t);
                        }
                        $key = \Phabel\Target\Php80\Polyfill::substr($t, 0, $dkLen);
                        $this->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $dkLen >> 1));
                        if ($this->usesIV()) {
                            $this->setIV(\Phabel\Target\Php80\Polyfill::substr($key, $dkLen >> 1));
                        }
                        return true;
                    case !in_array($hash, hash_algos()):
                        $i = 1;
                        $hashObj->setKey($password);
                        while (strlen($key) < $dkLen) {
                            $f = $u = $hashObj->hash($salt . pack('N', $i++));
                            for ($j = 2; $j <= $count; ++$j) {
                                $u = $hashObj->hash($u);
                                $f ^= $u;
                            }
                            $key .= $f;
                        }
                        $key = \Phabel\Target\Php80\Polyfill::substr($key, 0, $dkLen);
                        break;
                    default:
                        $key = hash_pbkdf2($hash, $password, $salt, $count, $dkLen, true);
                }
                break;
            default:
                throw new UnsupportedAlgorithmException($method . ' is not a supported password hashing method');
        }
        $this->setKey($key);
        return true;
    }
    /**
     * PKCS#12 KDF Helper Function
     *
     * As discussed here:
     *
     * {@link https://tools.ietf.org/html/rfc7292#appendix-B}
     *
     * @see self::setPassword()
     * @access private
     * @param int $n
     * @param \phpseclib3\Crypt\Hash $hashObj
     * @param string $i
     * @param string $d
     * @param int $count
     * @return string $a
     */
    private static function pkcs12helper($n, $hashObj, $i, $d, $count)
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        $blockLength = $hashObj->getBlockLength() >> 3;
        $c = ceil($n / $hashObj->getLengthInBytes());
        $a = '';
        for ($j = 1; $j <= $c; $j++) {
            $ai = $d . $i;
            for ($k = 0; $k < $count; $k++) {
                $ai = $hashObj->hash($ai);
            }
            $b = '';
            while (strlen($b) < $blockLength) {
                $b .= $ai;
            }
            $b = \Phabel\Target\Php80\Polyfill::substr($b, 0, $blockLength);
            $b = new BigInteger($b, 256);
            $newi = '';
            for ($k = 0; $k < strlen($i); $k += $blockLength) {
                $temp = \Phabel\Target\Php80\Polyfill::substr($i, $k, $blockLength);
                $temp = new BigInteger($temp, 256);
                $temp->setPrecision($blockLength << 3);
                $temp = $temp->add($b);
                $temp = $temp->add($one);
                $newi .= $temp->toBytes(false);
            }
            $i = $newi;
            $a .= $ai;
        }
        return \Phabel\Target\Php80\Polyfill::substr($a, 0, $n);
    }
    /**
    * Encrypts a message.
    *
    * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other cipher
    implementations may or may not pad in the same manner.  Other common approaches to padding and the reasons why it's
    necessary are discussed in the following
    URL:
    *
    * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
    *
    * An alternative to padding is to, separately, send the length of the file.  This is what SSH, in fact, does.
    strlen($plaintext) will still need to be a multiple of the block size, however, arbitrary values can be added to make it that
    length.
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::decrypt()
    * @access public
    * @param string $plaintext
    * @return string $ciphertext
    */
    public function encrypt($plaintext)
    {
        if ($this->paddable) {
            $plaintext = $this->pad($plaintext);
        }
        $this->setup();
        if ($this->mode == self::MODE_GCM) {
            $oldIV = $this->iv;
            Strings::increment_str($this->iv);
            $cipher = new static('ctr');
            $cipher->setKey($this->key);
            $cipher->setIV($this->iv);
            $ciphertext = $cipher->encrypt($plaintext);
            $s = $this->ghash(self::nullPad128($this->aad) . self::nullPad128($ciphertext) . self::len64($this->aad) . self::len64($ciphertext));
            $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV;
            $this->newtag = $cipher->encrypt($s);
            return $ciphertext;
        }
        if (isset($this->poly1305Key)) {
            $cipher = clone $this;
            unset($cipher->poly1305Key);
            $this->usePoly1305 = false;
            $ciphertext = $cipher->encrypt($plaintext);
            $this->newtag = $this->poly1305($ciphertext);
            return $ciphertext;
        }
        if ($this->engine === self::ENGINE_OPENSSL) {
            switch ($this->mode) {
                case self::MODE_STREAM:
                    return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                case self::MODE_ECB:
                    return openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                case self::MODE_CBC:
                    $result = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV);
                    if ($this->continuousBuffer) {
                        $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($result, -$this->block_size);
                    }
                    return $result;
                case self::MODE_CTR:
                    return $this->openssl_ctr_process($plaintext, $this->encryptIV, $this->enbuffer);
                case self::MODE_CFB:
                    // cfb loosely routines inspired by openssl's:
                    // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
                    $ciphertext = '';
                    if ($this->continuousBuffer) {
                        $iv =& $this->encryptIV;
                        $pos =& $this->enbuffer['pos'];
                    } else {
                        $iv = $this->encryptIV;
                        $pos = 0;
                    }
                    $len = strlen($plaintext);
                    $i = 0;
                    if ($pos) {
                        $orig_pos = $pos;
                        $max = $this->block_size - $pos;
                        if ($len >= $max) {
                            $i = $max;
                            $len -= $max;
                            $pos = 0;
                        } else {
                            $i = $len;
                            $pos += $len;
                            $len = 0;
                        }
                        // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
                        $ciphertext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $plaintext;
                        $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $ciphertext, $orig_pos, $i);
                        $plaintext = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i);
                    }
                    $overflow = $len % $this->block_size;
                    if ($overflow) {
                        $ciphertext .= openssl_encrypt(\Phabel\Target\Php80\Polyfill::substr($plaintext, 0, -$overflow) . str_repeat("\x00", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        $iv = Strings::pop($ciphertext, $this->block_size);
                        $size = $len - $overflow;
                        $block = $iv ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, -$overflow);
                        $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $block, 0, $overflow);
                        $ciphertext .= $block;
                        $pos = $overflow;
                    } elseif ($len) {
                        $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        $iv = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$this->block_size);
                    }
                    return $ciphertext;
                case self::MODE_CFB8:
                    $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->encryptIV);
                    if ($this->continuousBuffer) {
                        if (($len = strlen($ciphertext)) >= $this->block_size) {
                            $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$this->block_size);
                        } else {
                            $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($this->encryptIV, $len - $this->block_size) . \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                        }
                    }
                    return $ciphertext;
                case self::MODE_OFB:
                    return $this->openssl_ofb_process($plaintext, $this->encryptIV, $this->enbuffer);
            }
        }
        if ($this->engine === self::ENGINE_MCRYPT) {
            set_error_handler(function () {
            });
            if ($this->enchanged) {
                mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV));
                $this->enchanged = false;
            }
            // re: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
            // using mcrypt's default handing of CFB the above would output two different things.  using phpseclib's
            // rewritten CFB implementation the above outputs the same thing twice.
            if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
                $block_size = $this->block_size;
                $iv =& $this->encryptIV;
                $pos =& $this->enbuffer['pos'];
                $len = strlen($plaintext);
                $ciphertext = '';
                $i = 0;
                if ($pos) {
                    $orig_pos = $pos;
                    $max = $block_size - $pos;
                    if ($len >= $max) {
                        $i = $max;
                        $len -= $max;
                        $pos = 0;
                    } else {
                        $i = $len;
                        $pos += $len;
                        $len = 0;
                    }
                    $ciphertext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $plaintext;
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $ciphertext, $orig_pos, $i);
                    $this->enbuffer['enmcrypt_init'] = true;
                }
                if ($len >= $block_size) {
                    if ($this->enbuffer['enmcrypt_init'] === false || $len > $this->cfb_init_len) {
                        if ($this->enbuffer['enmcrypt_init'] === true) {
                            mcrypt_generic_init($this->enmcrypt, $this->key, $iv);
                            $this->enbuffer['enmcrypt_init'] = false;
                        }
                        $ciphertext .= mcrypt_generic($this->enmcrypt, \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $len - $len % $block_size));
                        $iv = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$block_size);
                        $len %= $block_size;
                    } else {
                        while ($len >= $block_size) {
                            $iv = mcrypt_generic($this->ecb, $iv) ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                            $ciphertext .= $iv;
                            $len -= $block_size;
                            $i += $block_size;
                        }
                    }
                }
                if ($len) {
                    $iv = mcrypt_generic($this->ecb, $iv);
                    $block = $iv ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, -$len);
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $block, 0, $len);
                    $ciphertext .= $block;
                    $pos = $len;
                }
                restore_error_handler();
                return $ciphertext;
            }
            $ciphertext = mcrypt_generic($this->enmcrypt, $plaintext);
            if (!$this->continuousBuffer) {
                mcrypt_generic_init($this->enmcrypt, $this->key, $this->getIV($this->encryptIV));
            }
            restore_error_handler();
            return $ciphertext;
        }
        if ($this->engine === self::ENGINE_EVAL) {
            $inline = $this->inline_crypt;
            return $inline('encrypt', $plaintext);
        }
        $buffer =& $this->enbuffer;
        $block_size = $this->block_size;
        $ciphertext = '';
        switch ($this->mode) {
            case self::MODE_ECB:
                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                    $ciphertext .= $this->encryptBlock(\Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size));
                }
                break;
            case self::MODE_CBC:
                $xor = $this->encryptIV;
                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                    $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                    $block = $this->encryptBlock($block ^ $xor);
                    $xor = $block;
                    $ciphertext .= $block;
                }
                if ($this->continuousBuffer) {
                    $this->encryptIV = $xor;
                }
                break;
            case self::MODE_CTR:
                $xor = $this->encryptIV;
                if (strlen($buffer['ciphertext'])) {
                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                        if (strlen($block) > strlen($buffer['ciphertext'])) {
                            $buffer['ciphertext'] .= $this->encryptBlock($xor);
                        }
                        Strings::increment_str($xor);
                        $key = Strings::shift($buffer['ciphertext'], $block_size);
                        $ciphertext .= $block ^ $key;
                    }
                } else {
                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                        $key = $this->encryptBlock($xor);
                        Strings::increment_str($xor);
                        $ciphertext .= $block ^ $key;
                    }
                }
                if ($this->continuousBuffer) {
                    $this->encryptIV = $xor;
                    if ($start = strlen($plaintext) % $block_size) {
                        $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['ciphertext'];
                    }
                }
                break;
            case self::MODE_CFB:
                // cfb loosely routines inspired by openssl's:
                // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
                if ($this->continuousBuffer) {
                    $iv =& $this->encryptIV;
                    $pos =& $buffer['pos'];
                } else {
                    $iv = $this->encryptIV;
                    $pos = 0;
                }
                $len = strlen($plaintext);
                $i = 0;
                if ($pos) {
                    $orig_pos = $pos;
                    $max = $block_size - $pos;
                    if ($len >= $max) {
                        $i = $max;
                        $len -= $max;
                        $pos = 0;
                    } else {
                        $i = $len;
                        $pos += $len;
                        $len = 0;
                    }
                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
                    $ciphertext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $plaintext;
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $ciphertext, $orig_pos, $i);
                }
                while ($len >= $block_size) {
                    $iv = $this->encryptBlock($iv) ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                    $ciphertext .= $iv;
                    $len -= $block_size;
                    $i += $block_size;
                }
                if ($len) {
                    $iv = $this->encryptBlock($iv);
                    $block = $iv ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, $i);
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, $block, 0, $len);
                    $ciphertext .= $block;
                    $pos = $len;
                }
                break;
            case self::MODE_CFB8:
                $ciphertext = '';
                $len = strlen($plaintext);
                $iv = $this->encryptIV;
                for ($i = 0; $i < $len; ++$i) {
                    $ciphertext .= $c = $plaintext[$i] ^ $this->encryptBlock($iv);
                    $iv = \Phabel\Target\Php80\Polyfill::substr($iv, 1) . $c;
                }
                if ($this->continuousBuffer) {
                    if ($len >= $block_size) {
                        $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$block_size);
                    } else {
                        $this->encryptIV = \Phabel\Target\Php80\Polyfill::substr($this->encryptIV, $len - $block_size) . \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                    }
                }
                break;
            case self::MODE_OFB:
                $xor = $this->encryptIV;
                if (strlen($buffer['xor'])) {
                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                        if (strlen($block) > strlen($buffer['xor'])) {
                            $xor = $this->encryptBlock($xor);
                            $buffer['xor'] .= $xor;
                        }
                        $key = Strings::shift($buffer['xor'], $block_size);
                        $ciphertext .= $block ^ $key;
                    }
                } else {
                    for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                        $xor = $this->encryptBlock($xor);
                        $ciphertext .= \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size) ^ $xor;
                    }
                    $key = $xor;
                }
                if ($this->continuousBuffer) {
                    $this->encryptIV = $xor;
                    if ($start = strlen($plaintext) % $block_size) {
                        $buffer['xor'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['xor'];
                    }
                }
                break;
            case self::MODE_STREAM:
                $ciphertext = $this->encryptBlock($plaintext);
                break;
        }
        return $ciphertext;
    }
    /**
    * Decrypts a message.
    *
    * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
    it is.
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::encrypt()
    * @access public
    * @param string $ciphertext
    * @return string $plaintext
    * @throws \LengthException if we're inside a block cipher and the ciphertext length is not a multiple of the block size
    */
    public function decrypt($ciphertext)
    {
        if ($this->paddable && strlen($ciphertext) % $this->block_size) {
            throw new \LengthException('The ciphertext length (' . strlen($ciphertext) . ') needs to be a multiple of the block size (' . $this->block_size . ')');
        }
        $this->setup();
        if ($this->mode == self::MODE_GCM || isset($this->poly1305Key)) {
            if ($this->oldtag === false) {
                throw new InsufficientSetupException('Authentication Tag has not been set');
            }
            if (isset($this->poly1305Key)) {
                $newtag = $this->poly1305($ciphertext);
            } else {
                $oldIV = $this->iv;
                Strings::increment_str($this->iv);
                $cipher = new static('ctr');
                $cipher->setKey($this->key);
                $cipher->setIV($this->iv);
                $plaintext = $cipher->decrypt($ciphertext);
                $s = $this->ghash(self::nullPad128($this->aad) . self::nullPad128($ciphertext) . self::len64($this->aad) . self::len64($ciphertext));
                $cipher->encryptIV = $this->iv = $this->encryptIV = $this->decryptIV = $oldIV;
                $newtag = $cipher->encrypt($s);
            }
            if ($this->oldtag != \Phabel\Target\Php80\Polyfill::substr($newtag, 0, strlen($newtag))) {
                $cipher = clone $this;
                unset($cipher->poly1305Key);
                $this->usePoly1305 = false;
                $plaintext = $cipher->decrypt($ciphertext);
                $this->oldtag = false;
                throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
            }
            $this->oldtag = false;
            return $plaintext;
        }
        if ($this->engine === self::ENGINE_OPENSSL) {
            switch ($this->mode) {
                case self::MODE_STREAM:
                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                    break;
                case self::MODE_ECB:
                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                    break;
                case self::MODE_CBC:
                    $offset = $this->block_size;
                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV);
                    if ($this->continuousBuffer) {
                        $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$offset, $this->block_size);
                    }
                    break;
                case self::MODE_CTR:
                    $plaintext = $this->openssl_ctr_process($ciphertext, $this->decryptIV, $this->debuffer);
                    break;
                case self::MODE_CFB:
                    // cfb loosely routines inspired by openssl's:
                    // {@link http://cvs.openssl.org/fileview?f=openssl/crypto/modes/cfb128.c&v=1.3.2.2.2.1}
                    $plaintext = '';
                    if ($this->continuousBuffer) {
                        $iv =& $this->decryptIV;
                        $pos =& $this->buffer['pos'];
                    } else {
                        $iv = $this->decryptIV;
                        $pos = 0;
                    }
                    $len = strlen($ciphertext);
                    $i = 0;
                    if ($pos) {
                        $orig_pos = $pos;
                        $max = $this->block_size - $pos;
                        if ($len >= $max) {
                            $i = $max;
                            $len -= $max;
                            $pos = 0;
                        } else {
                            $i = $len;
                            $pos += $len;
                            $len = 0;
                        }
                        // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $this->blocksize
                        $plaintext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $ciphertext;
                        $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, $i), $orig_pos, $i);
                        $ciphertext = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i);
                    }
                    $overflow = $len % $this->block_size;
                    if ($overflow) {
                        $plaintext .= openssl_decrypt(\Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, -$overflow), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        if ($len - $overflow) {
                            $iv = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$overflow - $this->block_size, -$overflow);
                        }
                        $iv = openssl_encrypt(str_repeat("\x00", $this->block_size), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        $plaintext .= $iv ^ \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$overflow);
                        $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$overflow), 0, $overflow);
                        $pos = $overflow;
                    } elseif ($len) {
                        $plaintext .= openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $iv);
                        $iv = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$this->block_size);
                    }
                    break;
                case self::MODE_CFB8:
                    $plaintext = openssl_decrypt($ciphertext, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $this->decryptIV);
                    if ($this->continuousBuffer) {
                        if (($len = strlen($ciphertext)) >= $this->block_size) {
                            $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$this->block_size);
                        } else {
                            $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($this->decryptIV, $len - $this->block_size) . \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                        }
                    }
                    break;
                case self::MODE_OFB:
                    $plaintext = $this->openssl_ofb_process($ciphertext, $this->decryptIV, $this->debuffer);
            }
            return $this->paddable ? $this->unpad($plaintext) : $plaintext;
        }
        if ($this->engine === self::ENGINE_MCRYPT) {
            set_error_handler(function () {
            });
            $block_size = $this->block_size;
            if ($this->dechanged) {
                mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV));
                $this->dechanged = false;
            }
            if ($this->mode == self::MODE_CFB && $this->continuousBuffer) {
                $iv =& $this->decryptIV;
                $pos =& $this->debuffer['pos'];
                $len = strlen($ciphertext);
                $plaintext = '';
                $i = 0;
                if ($pos) {
                    $orig_pos = $pos;
                    $max = $block_size - $pos;
                    if ($len >= $max) {
                        $i = $max;
                        $len -= $max;
                        $pos = 0;
                    } else {
                        $i = $len;
                        $pos += $len;
                        $len = 0;
                    }
                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
                    $plaintext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $ciphertext;
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, $i), $orig_pos, $i);
                }
                if ($len >= $block_size) {
                    $cb = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $len - $len % $block_size);
                    $plaintext .= mcrypt_generic($this->ecb, $iv . $cb) ^ $cb;
                    $iv = \Phabel\Target\Php80\Polyfill::substr($cb, -$block_size);
                    $len %= $block_size;
                }
                if ($len) {
                    $iv = mcrypt_generic($this->ecb, $iv);
                    $plaintext .= $iv ^ \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len), 0, $len);
                    $pos = $len;
                }
                restore_error_handler();
                return $plaintext;
            }
            $plaintext = mdecrypt_generic($this->demcrypt, $ciphertext);
            if (!$this->continuousBuffer) {
                mcrypt_generic_init($this->demcrypt, $this->key, $this->getIV($this->decryptIV));
            }
            restore_error_handler();
            return $this->paddable ? $this->unpad($plaintext) : $plaintext;
        }
        if ($this->engine === self::ENGINE_EVAL) {
            $inline = $this->inline_crypt;
            return $inline('decrypt', $ciphertext);
        }
        $block_size = $this->block_size;
        $buffer =& $this->debuffer;
        $plaintext = '';
        switch ($this->mode) {
            case self::MODE_ECB:
                for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                    $plaintext .= $this->decryptBlock(\Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size));
                }
                break;
            case self::MODE_CBC:
                $xor = $this->decryptIV;
                for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                    $block = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                    $plaintext .= $this->decryptBlock($block) ^ $xor;
                    $xor = $block;
                }
                if ($this->continuousBuffer) {
                    $this->decryptIV = $xor;
                }
                break;
            case self::MODE_CTR:
                $xor = $this->decryptIV;
                if (strlen($buffer['ciphertext'])) {
                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                        if (strlen($block) > strlen($buffer['ciphertext'])) {
                            $buffer['ciphertext'] .= $this->encryptBlock($xor);
                        }
                        Strings::increment_str($xor);
                        $key = Strings::shift($buffer['ciphertext'], $block_size);
                        $plaintext .= $block ^ $key;
                    }
                } else {
                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                        $key = $this->encryptBlock($xor);
                        Strings::increment_str($xor);
                        $plaintext .= $block ^ $key;
                    }
                }
                if ($this->continuousBuffer) {
                    $this->decryptIV = $xor;
                    if ($start = strlen($ciphertext) % $block_size) {
                        $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['ciphertext'];
                    }
                }
                break;
            case self::MODE_CFB:
                if ($this->continuousBuffer) {
                    $iv =& $this->decryptIV;
                    $pos =& $buffer['pos'];
                } else {
                    $iv = $this->decryptIV;
                    $pos = 0;
                }
                $len = strlen($ciphertext);
                $i = 0;
                if ($pos) {
                    $orig_pos = $pos;
                    $max = $block_size - $pos;
                    if ($len >= $max) {
                        $i = $max;
                        $len -= $max;
                        $pos = 0;
                    } else {
                        $i = $len;
                        $pos += $len;
                        $len = 0;
                    }
                    // ie. $i = min($max, $len), $len-= $i, $pos+= $i, $pos%= $blocksize
                    $plaintext = \Phabel\Target\Php80\Polyfill::substr($iv, $orig_pos) ^ $ciphertext;
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, $i), $orig_pos, $i);
                }
                while ($len >= $block_size) {
                    $iv = $this->encryptBlock($iv);
                    $cb = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                    $plaintext .= $iv ^ $cb;
                    $iv = $cb;
                    $len -= $block_size;
                    $i += $block_size;
                }
                if ($len) {
                    $iv = $this->encryptBlock($iv);
                    $plaintext .= $iv ^ \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i);
                    $iv = \Phabel\Target\Php80\Polyfill::substr_replace($iv, \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i), 0, $len);
                    $pos = $len;
                }
                break;
            case self::MODE_CFB8:
                $plaintext = '';
                $len = strlen($ciphertext);
                $iv = $this->decryptIV;
                for ($i = 0; $i < $len; ++$i) {
                    $plaintext .= $ciphertext[$i] ^ $this->encryptBlock($iv);
                    $iv = \Phabel\Target\Php80\Polyfill::substr($iv, 1) . $ciphertext[$i];
                }
                if ($this->continuousBuffer) {
                    if ($len >= $block_size) {
                        $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$block_size);
                    } else {
                        $this->decryptIV = \Phabel\Target\Php80\Polyfill::substr($this->decryptIV, $len - $block_size) . \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$len);
                    }
                }
                break;
            case self::MODE_OFB:
                $xor = $this->decryptIV;
                if (strlen($buffer['xor'])) {
                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                        $block = \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size);
                        if (strlen($block) > strlen($buffer['xor'])) {
                            $xor = $this->encryptBlock($xor);
                            $buffer['xor'] .= $xor;
                        }
                        $key = Strings::shift($buffer['xor'], $block_size);
                        $plaintext .= $block ^ $key;
                    }
                } else {
                    for ($i = 0; $i < strlen($ciphertext); $i += $block_size) {
                        $xor = $this->encryptBlock($xor);
                        $plaintext .= \Phabel\Target\Php80\Polyfill::substr($ciphertext, $i, $block_size) ^ $xor;
                    }
                    $key = $xor;
                }
                if ($this->continuousBuffer) {
                    $this->decryptIV = $xor;
                    if ($start = strlen($ciphertext) % $block_size) {
                        $buffer['xor'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['xor'];
                    }
                }
                break;
            case self::MODE_STREAM:
                $plaintext = $this->decryptBlock($ciphertext);
                break;
        }
        return $this->paddable ? $this->unpad($plaintext) : $plaintext;
    }
    /**
     * Get the authentication tag
     *
     * Only used in GCM or Poly1305 mode
     *
     * @see self::encrypt()
     * @param int $length optional
     * @return string
     * @access public
     * @throws \LengthException if $length isn't of a sufficient length
     * @throws \RuntimeException if GCM mode isn't being used
     */
    public function getTag($length = 16)
    {
        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
            throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305');
        }
        if ($this->newtag === false) {
            throw new \BadMethodCallException('A tag can only be returned after a round of encryption has been performed');
        }
        // the tag is 128-bits. it can't be greater than 16 bytes because that's bigger than the tag is. if it
        // were 0 you might as well be doing CTR and less than 4 provides minimal security that could be trivially
        // easily brute forced.
        // see https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=36
        // for more info
        if ($length < 4 || $length > 16) {
            throw new \LengthException('The authentication tag must be between 4 and 16 bytes long');
        }
        return $length == 16 ? $this->newtag : \Phabel\Target\Php80\Polyfill::substr($this->newtag, 0, $length);
    }
    /**
     * Sets the authentication tag
     *
     * Only used in GCM mode
     *
     * @see self::decrypt()
     * @param string $tag
     * @access public
     * @throws \LengthException if $length isn't of a sufficient length
     * @throws \RuntimeException if GCM mode isn't being used
     */
    public function setTag($tag)
    {
        if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) {
            $this->createPoly1305Key();
        }
        if ($this->mode != self::MODE_GCM && !$this->usePoly1305) {
            throw new \BadMethodCallException('Authentication tags are only utilized in GCM mode or with Poly1305');
        }
        $length = strlen($tag);
        if ($length < 4 || $length > 16) {
            throw new \LengthException('The authentication tag must be between 4 and 16 bytes long');
        }
        $this->oldtag = $tag;
    }
    /**
     * Get the IV
     *
     * mcrypt requires an IV even if ECB is used
     *
     * @see self::encrypt()
     * @see self::decrypt()
     * @param string $iv
     * @return string
     * @access private
     */
    protected function getIV($iv)
    {
        return $this->mode == self::MODE_ECB ? str_repeat("\x00", $this->block_size) : $iv;
    }
    /**
    * OpenSSL CTR Processor
    *
    * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
    for CTR is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt()
    and SymmetricKey::decrypt(). Also, OpenSSL doesn't implement CTR for all of it's symmetric ciphers so this
    function will emulate CTR with ECB when necessary.
    *
    * @see self::encrypt()
    * @see self::decrypt()
    * @param string $plaintext
    * @param string $encryptIV
    * @param array $buffer
    * @return string
    * @access private
    */
    private function openssl_ctr_process($plaintext, &$encryptIV, &$buffer)
    {
        $ciphertext = '';
        $block_size = $this->block_size;
        $key = $this->key;
        if ($this->openssl_emulate_ctr) {
            $xor = $encryptIV;
            if (strlen($buffer['ciphertext'])) {
                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                    $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                    if (strlen($block) > strlen($buffer['ciphertext'])) {
                        $buffer['ciphertext'] .= openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                    }
                    Strings::increment_str($xor);
                    $otp = Strings::shift($buffer['ciphertext'], $block_size);
                    $ciphertext .= $block ^ $otp;
                }
            } else {
                for ($i = 0; $i < strlen($plaintext); $i += $block_size) {
                    $block = \Phabel\Target\Php80\Polyfill::substr($plaintext, $i, $block_size);
                    $otp = openssl_encrypt($xor, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
                    Strings::increment_str($xor);
                    $ciphertext .= $block ^ $otp;
                }
            }
            if ($this->continuousBuffer) {
                $encryptIV = $xor;
                if ($start = strlen($plaintext) % $block_size) {
                    $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($key, $start) . $buffer['ciphertext'];
                }
            }
            return $ciphertext;
        }
        if (strlen($buffer['ciphertext'])) {
            $ciphertext = $plaintext ^ Strings::shift($buffer['ciphertext'], strlen($plaintext));
            $plaintext = \Phabel\Target\Php80\Polyfill::substr($plaintext, strlen($ciphertext));
            if (!strlen($plaintext)) {
                return $ciphertext;
            }
        }
        $overflow = strlen($plaintext) % $block_size;
        if ($overflow) {
            $plaintext2 = Strings::pop($plaintext, $overflow);
            // ie. trim $plaintext to a multiple of $block_size and put rest of $plaintext in $plaintext2
            $encrypted = openssl_encrypt($plaintext . str_repeat("\x00", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
            $temp = Strings::pop($encrypted, $block_size);
            $ciphertext .= $encrypted . ($plaintext2 ^ $temp);
            if ($this->continuousBuffer) {
                $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($temp, $overflow);
                $encryptIV = $temp;
            }
        } elseif (!strlen($buffer['ciphertext'])) {
            $ciphertext .= openssl_encrypt($plaintext . str_repeat("\x00", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
            $temp = Strings::pop($ciphertext, $block_size);
            if ($this->continuousBuffer) {
                $encryptIV = $temp;
            }
        }
        if ($this->continuousBuffer) {
            $encryptIV = openssl_decrypt($encryptIV, $this->cipher_name_openssl_ecb, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING);
            if ($overflow) {
                Strings::increment_str($encryptIV);
            }
        }
        return $ciphertext;
    }
    /**
    * OpenSSL OFB Processor
    *
    * PHP's OpenSSL bindings do not operate in continuous mode so we'll wrap around it. Since the keystream
    for OFB is the same for both encrypting and decrypting this function is re-used by both SymmetricKey::encrypt()
    and SymmetricKey::decrypt().
    *
    * @see self::encrypt()
    * @see self::decrypt()
    * @param string $plaintext
    * @param string $encryptIV
    * @param array $buffer
    * @return string
    * @access private
    */
    private function openssl_ofb_process($plaintext, &$encryptIV, &$buffer)
    {
        if (strlen($buffer['xor'])) {
            $ciphertext = $plaintext ^ $buffer['xor'];
            $buffer['xor'] = \Phabel\Target\Php80\Polyfill::substr($buffer['xor'], strlen($ciphertext));
            $plaintext = \Phabel\Target\Php80\Polyfill::substr($plaintext, strlen($ciphertext));
        } else {
            $ciphertext = '';
        }
        $block_size = $this->block_size;
        $len = strlen($plaintext);
        $key = $this->key;
        $overflow = $len % $block_size;
        if (strlen($plaintext)) {
            if ($overflow) {
                $ciphertext .= openssl_encrypt(\Phabel\Target\Php80\Polyfill::substr($plaintext, 0, -$overflow) . str_repeat("\x00", $block_size), $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
                $xor = Strings::pop($ciphertext, $block_size);
                if ($this->continuousBuffer) {
                    $encryptIV = $xor;
                }
                $ciphertext .= Strings::shift($xor, $overflow) ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, -$overflow);
                if ($this->continuousBuffer) {
                    $buffer['xor'] = $xor;
                }
            } else {
                $ciphertext = openssl_encrypt($plaintext, $this->cipher_name_openssl, $key, OPENSSL_RAW_DATA | OPENSSL_ZERO_PADDING, $encryptIV);
                if ($this->continuousBuffer) {
                    $encryptIV = \Phabel\Target\Php80\Polyfill::substr($ciphertext, -$block_size) ^ \Phabel\Target\Php80\Polyfill::substr($plaintext, -$block_size);
                }
            }
        }
        return $ciphertext;
    }
    /**
     * phpseclib <-> OpenSSL Mode Mapper
     *
     * May need to be overwritten by classes extending this one in some cases
     *
     * @return string
     * @access private
     */
    protected function openssl_translate_mode()
    {
        switch ($this->mode) {
            case self::MODE_ECB:
                return 'ecb';
            case self::MODE_CBC:
                return 'cbc';
            case self::MODE_CTR:
            case self::MODE_GCM:
                return 'ctr';
            case self::MODE_CFB:
                return 'cfb';
            case self::MODE_CFB8:
                return 'cfb8';
            case self::MODE_OFB:
                return 'ofb';
        }
    }
    /**
    * Pad "packets".
    *
    * Block ciphers working by encrypting between their specified [$this->]block_size at a time
    If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
    pad the input so that it is of the proper length.
    *
    * Padding is enabled by default.  Sometimes, however, it is undesirable to pad strings.  Such is the case in SSH,
    where "packets" are padded with random bytes before being encrypted.  Unpad these packets and you risk stripping
    away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
    transmitted separately)
    *
    * @see self::disablePadding()
    * @access public
    */
    public function enablePadding()
    {
        $this->padding = true;
    }
    /**
     * Do not pad packets.
     *
     * @see self::enablePadding()
     * @access public
     */
    public function disablePadding()
    {
        $this->padding = false;
    }
    /**
    * Treat consecutive "packets" as if they are a continuous buffer.
    *
    * Say you have a 32-byte plaintext $plaintext.  Using the default behavior, the two following code snippets
    will yield different outputs:
    *
    * <code>
    echo $rijndael->encrypt(substr($plaintext,  0, 16));
    echo $rijndael->encrypt(substr($plaintext, 16, 16));
    </code>
    <code>
    echo $rijndael->encrypt($plaintext);
    </code>
    *
    * The solution is to enable the continuous buffer.  Although this will resolve the above discrepancy, it creates
    another, as demonstrated with the following:
    *
    * <code>
    $rijndael->encrypt(substr($plaintext, 0, 16));
    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
    </code>
    <code>
    echo $rijndael->decrypt($rijndael->encrypt(substr($plaintext, 16, 16)));
    </code>
    *
    * With the continuous buffer disabled, these would yield the same output.  With it enabled, they yield different
    outputs.  The reason is due to the fact that the initialization vector's change after every encryption /
    decryption round when the continuous buffer is enabled.  When it's disabled, they remain constant.
    *
    * Put another way, when the continuous buffer is enabled, the state of the \phpseclib3\Crypt\*() object changes after each
    encryption / decryption round, whereas otherwise, it'd remain constant.  For this reason, it's recommended that
    continuous buffers not be used.  They do offer better security and are, in fact, sometimes required (SSH uses them),
    however, they are also less intuitive and more likely to cause you problems.
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::disableContinuousBuffer()
    * @access public
    */
    public function enableContinuousBuffer()
    {
        if ($this->mode == self::MODE_ECB) {
            return;
        }
        if ($this->mode == self::MODE_GCM) {
            throw new \BadMethodCallException('This mode does not run in continuous mode');
        }
        $this->continuousBuffer = true;
        $this->setEngine();
    }
    /**
     * Treat consecutive packets as if they are a discontinuous buffer.
     *
     * The default behavior.
     *
     * {@internal Could, but not must, extend by the child Crypt_* class}
     *
     * @see self::enableContinuousBuffer()
     * @access public
     */
    public function disableContinuousBuffer()
    {
        if ($this->mode == self::MODE_ECB) {
            return;
        }
        if (!$this->continuousBuffer) {
            return;
        }
        $this->continuousBuffer = false;
        $this->setEngine();
    }
    /**
     * Test for engine validity
     *
     * @see self::__construct()
     * @param int $engine
     * @access private
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        switch ($engine) {
            case self::ENGINE_OPENSSL:
                $this->openssl_emulate_ctr = false;
                $result = $this->cipher_name_openssl && extension_loaded('openssl');
                if (!$result) {
                    return false;
                }
                $methods = openssl_get_cipher_methods();
                if (in_array($this->cipher_name_openssl, $methods)) {
                    return true;
                }
                // not all of openssl's symmetric cipher's support ctr. for those
                // that don't we'll emulate it
                switch ($this->mode) {
                    case self::MODE_CTR:
                        if (in_array($this->cipher_name_openssl_ecb, $methods)) {
                            $this->openssl_emulate_ctr = true;
                            return true;
                        }
                }
                return false;
            case self::ENGINE_MCRYPT:
                set_error_handler(function () {
                });
                $result = $this->cipher_name_mcrypt && extension_loaded('mcrypt') && in_array($this->cipher_name_mcrypt, mcrypt_list_algorithms());
                restore_error_handler();
                return $result;
            case self::ENGINE_EVAL:
                return method_exists($this, 'setupInlineCrypt');
            case self::ENGINE_INTERNAL:
                return true;
        }
        return false;
    }
    /**
     * Test for engine validity
     *
     * @see self::__construct()
     * @param string $engine
     * @access public
     * @return bool
     */
    public function isValidEngine($engine)
    {
        static $reverseMap;
        if (!isset($reverseMap)) {
            $reverseMap = array_map('strtolower', self::ENGINE_MAP);
            $reverseMap = array_flip($reverseMap);
        }
        $engine = strtolower($engine);
        if (!isset($reverseMap[$engine])) {
            return false;
        }
        return $this->isValidEngineHelper($reverseMap[$engine]);
    }
    /**
     * Sets the preferred crypt engine
     *
     * Currently, $engine could be:
     *
     * - libsodium[very fast]
     *
     * - OpenSSL  [very fast]
     *
     * - mcrypt   [fast]
     *
     * - Eval     [slow]
     *
     * - PHP      [slowest]
     *
     * If the preferred crypt engine is not available the fastest available one will be used
     *
     * @see self::__construct()
     * @param string $engine
     * @access public
     */
    public function setPreferredEngine($engine)
    {
        static $reverseMap;
        if (!isset($reverseMap)) {
            $reverseMap = array_map('strtolower', self::ENGINE_MAP);
            $reverseMap = array_flip($reverseMap);
        }
        $engine = strtolower($engine);
        $this->preferredEngine = isset($reverseMap[$engine]) ? $reverseMap[$engine] : self::ENGINE_LIBSODIUM;
        $this->setEngine();
    }
    /**
     * Returns the engine currently being utilized
     *
     * @see self::setEngine()
     * @access public
     */
    public function getEngine()
    {
        return self::ENGINE_MAP[$this->engine];
    }
    /**
     * Sets the engine as appropriate
     *
     * @see self::__construct()
     * @access private
     */
    protected function setEngine()
    {
        $this->engine = null;
        $candidateEngines = [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM, self::ENGINE_OPENSSL, self::ENGINE_MCRYPT, self::ENGINE_EVAL];
        if (isset($this->preferredEngine)) {
            $temp = [$this->preferredEngine];
            $candidateEngines = array_merge($temp, array_diff($candidateEngines, $temp));
        }
        foreach ($candidateEngines as $engine) {
            if ($this->isValidEngineHelper($engine)) {
                $this->engine = $engine;
                break;
            }
        }
        if (!$this->engine) {
            $this->engine = self::ENGINE_INTERNAL;
        }
        if ($this->engine != self::ENGINE_MCRYPT && $this->enmcrypt) {
            set_error_handler(function () {
            });
            // Closing the current mcrypt resource(s). _mcryptSetup() will, if needed,
            // (re)open them with the module named in $this->cipher_name_mcrypt
            mcrypt_module_close($this->enmcrypt);
            mcrypt_module_close($this->demcrypt);
            $this->enmcrypt = null;
            $this->demcrypt = null;
            if ($this->ecb) {
                mcrypt_module_close($this->ecb);
                $this->ecb = null;
            }
            restore_error_handler();
        }
        $this->changed = $this->nonIVChanged = true;
    }
    /**
     * Encrypts a block
     *
     * Note: Must be extended by the child \phpseclib3\Crypt\* class
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected abstract function encryptBlock($in);
    /**
     * Decrypts a block
     *
     * Note: Must be extended by the child \phpseclib3\Crypt\* class
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected abstract function decryptBlock($in);
    /**
     * Setup the key (expansion)
     *
     * Only used if $engine == self::ENGINE_INTERNAL
     *
     * Note: Must extend by the child \phpseclib3\Crypt\* class
     *
     * @see self::setup()
     * @access private
     */
    protected abstract function setupKey();
    /**
    * Setup the self::ENGINE_INTERNAL $engine
    *
    * (re)init, if necessary, the internal cipher $engine and flush all $buffers
    Used (only) if $engine == self::ENGINE_INTERNAL
    *
    * _setup() will be called each time if $changed === true
    typically this happens when using one or more of following public methods:
    *
    * - setKey()
    *
    * - setIV()
    *
    * - disableContinuousBuffer()
    *
    * - First run of encrypt() / decrypt() with no init-settings
    *
    * {@internal setup() is always called before en/decryption.}
    *
    * {@internal Could, but not must, extend by the child Crypt_* class}
    *
    * @see self::setKey()
    * @see self::setIV()
    * @see self::disableContinuousBuffer()
    * @access private
    */
    protected function setup()
    {
        if (!$this->changed) {
            return;
        }
        $this->changed = false;
        if ($this->usePoly1305 && !isset($this->poly1305Key) && method_exists($this, 'createPoly1305Key')) {
            $this->createPoly1305Key();
        }
        $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'xor' => '', 'pos' => 0, 'enmcrypt_init' => true];
        //$this->newtag = $this->oldtag = false;
        if ($this->usesNonce()) {
            if ($this->nonce === false) {
                throw new InsufficientSetupException('No nonce has been defined');
            }
            if ($this->mode == self::MODE_GCM && !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) {
                $this->setupGCM();
            }
        } else {
            $this->iv = $this->origIV;
        }
        if ($this->iv === false && !in_array($this->mode, [self::MODE_STREAM, self::MODE_ECB])) {
            if ($this->mode != self::MODE_GCM || !in_array($this->engine, [self::ENGINE_LIBSODIUM, self::ENGINE_OPENSSL_GCM])) {
                throw new InsufficientSetupException('No IV has been defined');
            }
        }
        if ($this->key === false) {
            throw new InsufficientSetupException('No key has been defined');
        }
        $this->encryptIV = $this->decryptIV = $this->iv;
        switch ($this->engine) {
            case self::ENGINE_MCRYPT:
                $this->enchanged = $this->dechanged = true;
                set_error_handler(function () {
                });
                if (!isset($this->enmcrypt)) {
                    static $mcrypt_modes = [self::MODE_CTR => 'ctr', self::MODE_ECB => MCRYPT_MODE_ECB, self::MODE_CBC => MCRYPT_MODE_CBC, self::MODE_CFB => 'ncfb', self::MODE_CFB8 => MCRYPT_MODE_CFB, self::MODE_OFB => MCRYPT_MODE_NOFB, self::MODE_STREAM => MCRYPT_MODE_STREAM];
                    $this->demcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
                    $this->enmcrypt = mcrypt_module_open($this->cipher_name_mcrypt, '', $mcrypt_modes[$this->mode], '');
                    // we need the $ecb mcrypt resource (only) in MODE_CFB with enableContinuousBuffer()
                    // to workaround mcrypt's broken ncfb implementation in buffered mode
                    // see: {@link http://phpseclib.sourceforge.net/cfb-demo.phps}
                    if ($this->mode == self::MODE_CFB) {
                        $this->ecb = mcrypt_module_open($this->cipher_name_mcrypt, '', MCRYPT_MODE_ECB, '');
                    }
                }
                // else should mcrypt_generic_deinit be called?
                if ($this->mode == self::MODE_CFB) {
                    mcrypt_generic_init($this->ecb, $this->key, str_repeat("\x00", $this->block_size));
                }
                restore_error_handler();
                break;
            case self::ENGINE_INTERNAL:
                $this->setupKey();
                break;
            case self::ENGINE_EVAL:
                if ($this->nonIVChanged) {
                    $this->setupKey();
                    $this->setupInlineCrypt();
                }
        }
        $this->nonIVChanged = false;
    }
    /**
    * Pads a string
    *
    * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
    $this->block_size - (strlen($text) % $this->block_size) bytes are added, each of which is equal to
    chr($this->block_size - (strlen($text) % $this->block_size)
    *
    * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
    and padding will, hence forth, be enabled.
    *
    * @see self::unpad()
    * @param string $text
    * @throws \LengthException if padding is disabled and the plaintext's length is not a multiple of the block size
    * @access private
    * @return string
    */
    protected function pad($text)
    {
        $length = strlen($text);
        if (!$this->padding) {
            if ($length % $this->block_size == 0) {
                return $text;
            } else {
                throw new \LengthException("The plaintext's length ({$length}) is not a multiple of the block size ({$this->block_size}). Try enabling padding.");
            }
        }
        $pad = $this->block_size - $length % $this->block_size;
        return str_pad($text, $length + $pad, chr($pad));
    }
    /**
    * Unpads a string.
    *
    * If padding is enabled and the reported padding length is invalid the encryption key will be assumed to be wrong
    and false will be returned.
    *
    * @see self::pad()
    * @param string $text
    * @throws \LengthException if the ciphertext's length is not a multiple of the block size
    * @access private
    * @return string
    */
    protected function unpad($text)
    {
        if (!$this->padding) {
            return $text;
        }
        $length = ord($text[strlen($text) - 1]);
        if (!$length || $length > $this->block_size) {
            throw new BadDecryptionException("The ciphertext has an invalid padding length ({$length}) compared to the block size ({$this->block_size})");
        }
        return \Phabel\Target\Php80\Polyfill::substr($text, 0, -$length);
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * Stores the created (or existing) callback function-name
     * in $this->inline_crypt
     *
     * Internally for phpseclib developers:
     *
     *     _setupInlineCrypt() would be called only if:
     *
     *     - $this->engine === self::ENGINE_EVAL
     *
     *     - each time on _setup(), after(!) _setupKey()
     *
     *
     *     This ensures that _setupInlineCrypt() has always a
     *     full ready2go initializated internal cipher $engine state
     *     where, for example, the keys already expanded,
     *     keys/block_size calculated and such.
     *
     *     It is, each time if called, the responsibility of _setupInlineCrypt():
     *
     *     - to set $this->inline_crypt to a valid and fully working callback function
     *       as a (faster) replacement for encrypt() / decrypt()
     *
     *     - NOT to create unlimited callback functions (for memory reasons!)
     *       no matter how often _setupInlineCrypt() would be called. At some
     *       point of amount they must be generic re-useable.
     *
     *     - the code of _setupInlineCrypt() it self,
     *       and the generated callback code,
     *       must be, in following order:
     *       - 100% safe
     *       - 100% compatible to encrypt()/decrypt()
     *       - using only php5+ features/lang-constructs/php-extensions if
     *         compatibility (down to php4) or fallback is provided
     *       - readable/maintainable/understandable/commented and... not-cryptic-styled-code :-)
     *       - >= 10% faster than encrypt()/decrypt() [which is, by the way,
     *         the reason for the existence of _setupInlineCrypt() :-)]
     *       - memory-nice
     *       - short (as good as possible)
     *
     * Note: - _setupInlineCrypt() is using _createInlineCryptFunction() to create the full callback function code.
     *       - In case of using inline crypting, _setupInlineCrypt() must extend by the child \phpseclib3\Crypt\* class.
     *       - The following variable names are reserved:
     *         - $_*  (all variable names prefixed with an underscore)
     *         - $self (object reference to it self. Do not use $this, but $self instead)
     *         - $in (the content of $in has to en/decrypt by the generated code)
     *       - The callback function should not use the 'return' statement, but en/decrypt'ing the content of $in only
     *
     * {@internal If a Crypt_* class providing inline crypting it must extend _setupInlineCrypt()}
     *
     * @see self::setup()
     * @see self::createInlineCryptFunction()
     * @see self::encrypt()
     * @see self::decrypt()
     * @access private
     */
    //protected function setupInlineCrypt();
    /**
    * Creates the performance-optimized function for en/decrypt()
    *
    * Internally for phpseclib developers:
    *
    * _createInlineCryptFunction():
    *
    * - merge the $cipher_code [setup'ed by _setupInlineCrypt()]
    with the current [$this->]mode of operation code
    *
    * - create the $inline function, which called by encrypt() / decrypt()
    as its replacement to speed up the en/decryption operations.
    *
    * - return the name of the created $inline callback function
    *
    * - used to speed up en/decryption
    *
    *
    *
    * The main reason why can speed up things [up to 50%] this way are:
    *
    * - using variables more effective then regular.
    (ie no use of expensive arrays but integers $k_0, $k_1 ...
    or even, for example, the pure $key[] values hardcoded)
    *
    * - avoiding 1000's of function calls of ie _encryptBlock()
    but inlining the crypt operations.
    in the mode of operation for() loop.
    *
    * - full loop unroll the (sometimes key-dependent) rounds
    avoiding this way ++$i counters and runtime-if's etc...
    *
    * The basic code architectur of the generated $inline en/decrypt()
    lambda function, in pseudo php, is:
    *
    * <code>
    +----------------------------------------------------------------------------------------------+
    | callback $inline = create_function:                                                          |
    | lambda_function_0001_crypt_ECB($action, $text)                                               |
    | {                                                                                            |
    |     INSERT PHP CODE OF:                                                                      |
    |     $cipher_code['init_crypt'];                  // general init code.                       |
    |                                                  // ie: $sbox'es declarations used for       |
    |                                                  //     encrypt and decrypt'ing.             |
    |                                                                                              |
    |     switch ($action) {                                                                       |
    |         case 'encrypt':                                                                      |
    |             INSERT PHP CODE OF:                                                              |
    |             $cipher_code['init_encrypt'];       // encrypt sepcific init code.               |
    |                                                    ie: specified $key or $box                |
    |                                                        declarations for encrypt'ing.         |
    |                                                                                              |
    |             foreach ($ciphertext) {                                                          |
    |                 $in = $block_size of $ciphertext;                                            |
    |                                                                                              |
    |                 INSERT PHP CODE OF:                                                          |
    |                 $cipher_code['encrypt_block'];  // encrypt's (string) $in, which is always:  |
    |                                                 // strlen($in) == $this->block_size          |
    |                                                 // here comes the cipher algorithm in action |
    |                                                 // for encryption.                           |
    |                                                 // $cipher_code['encrypt_block'] has to      |
    |                                                 // encrypt the content of the $in variable   |
    |                                                                                              |
    |                 $plaintext .= $in;                                                           |
    |             }                                                                                |
    |             return $plaintext;                                                               |
    |                                                                                              |
    |         case 'decrypt':                                                                      |
    |             INSERT PHP CODE OF:                                                              |
    |             $cipher_code['init_decrypt'];       // decrypt sepcific init code                |
    |                                                    ie: specified $key or $box                |
    |                                                        declarations for decrypt'ing.         |
    |             foreach ($plaintext) {                                                           |
    |                 $in = $block_size of $plaintext;                                             |
    |                                                                                              |
    |                 INSERT PHP CODE OF:                                                          |
    |                 $cipher_code['decrypt_block'];  // decrypt's (string) $in, which is always   |
    |                                                 // strlen($in) == $this->block_size          |
    |                                                 // here comes the cipher algorithm in action |
    |                                                 // for decryption.                           |
    |                                                 // $cipher_code['decrypt_block'] has to      |
    |                                                 // decrypt the content of the $in variable   |
    |                 $ciphertext .= $in;                                                          |
    |             }                                                                                |
    |             return $ciphertext;                                                              |
    |     }                                                                                        |
    | }                                                                                            |
    +----------------------------------------------------------------------------------------------+
    </code>
    *
    * See also the \phpseclib3\Crypt\*::_setupInlineCrypt()'s for
    productive inline $cipher_code's how they works.
    *
    * Structure of:
    <code>
    $cipher_code = [
    'init_crypt'    => (string) '', // optional
    'init_encrypt'  => (string) '', // optional
    'init_decrypt'  => (string) '', // optional
    'encrypt_block' => (string) '', // required
    'decrypt_block' => (string) ''  // required
    ];
    </code>
    *
    * @see self::setupInlineCrypt()
    * @see self::encrypt()
    * @see self::decrypt()
    * @param array $cipher_code
    * @access private
    * @return string (the name of the created callback function)
    */
    protected function createInlineCryptFunction($cipher_code)
    {
        $block_size = $this->block_size;
        // optional
        $init_crypt = isset($cipher_code['init_crypt']) ? $cipher_code['init_crypt'] : '';
        $init_encrypt = isset($cipher_code['init_encrypt']) ? $cipher_code['init_encrypt'] : '';
        $init_decrypt = isset($cipher_code['init_decrypt']) ? $cipher_code['init_decrypt'] : '';
        // required
        $encrypt_block = $cipher_code['encrypt_block'];
        $decrypt_block = $cipher_code['decrypt_block'];
        // Generating mode of operation inline code,
        // merged with the $cipher_code algorithm
        // for encrypt- and decryption.
        switch ($this->mode) {
            case self::MODE_ECB:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);

                    for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                        $in = substr($_text, $_i, ' . $block_size . ');
                        ' . $encrypt_block . '
                        $_ciphertext.= $in;
                    }

                    return $_ciphertext;
                    ';
                $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0));
                    $_ciphertext_len = strlen($_text);

                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                        $in = substr($_text, $_i, ' . $block_size . ');
                        ' . $decrypt_block . '
                        $_plaintext.= $in;
                    }

                    return $this->unpad($_plaintext);
                    ';
                break;
            case self::MODE_CTR:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);
                    $_xor = $this->encryptIV;
                    $_buffer = &$this->enbuffer;
                    if (strlen($_buffer["ciphertext"])) {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
                                $in = $_xor;
                                ' . $encrypt_block . '
                                \\phpseclib3\\Common\\Functions\\Strings::increment_str($_xor);
                                $_buffer["ciphertext"].= $in;
                            }
                            $_key = \\phpseclib3\\Common\\Functions\\Strings::shift($_buffer["ciphertext"], ' . $block_size . ');
                            $_ciphertext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            $in = $_xor;
                            ' . $encrypt_block . '
                            \\phpseclib3\\Common\\Functions\\Strings::increment_str($_xor);
                            $_key = $in;
                            $_ciphertext.= $_block ^ $_key;
                        }
                    }
                    if ($this->continuousBuffer) {
                        $this->encryptIV = $_xor;
                        if ($_start = $_plaintext_len % ' . $block_size . ') {
                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
                        }
                    }

                    return $_ciphertext;
                ';
                $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_ciphertext_len = strlen($_text);
                    $_xor = $this->decryptIV;
                    $_buffer = &$this->debuffer;

                    if (strlen($_buffer["ciphertext"])) {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            if (strlen($_block) > strlen($_buffer["ciphertext"])) {
                                $in = $_xor;
                                ' . $encrypt_block . '
                                \\phpseclib3\\Common\\Functions\\Strings::increment_str($_xor);
                                $_buffer["ciphertext"].= $in;
                            }
                            $_key = \\phpseclib3\\Common\\Functions\\Strings::shift($_buffer["ciphertext"], ' . $block_size . ');
                            $_plaintext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            $in = $_xor;
                            ' . $encrypt_block . '
                            \\phpseclib3\\Common\\Functions\\Strings::increment_str($_xor);
                            $_key = $in;
                            $_plaintext.= $_block ^ $_key;
                        }
                    }
                    if ($this->continuousBuffer) {
                        $this->decryptIV = $_xor;
                        if ($_start = $_ciphertext_len % ' . $block_size . ') {
                            $_buffer["ciphertext"] = substr($_key, $_start) . $_buffer["ciphertext"];
                        }
                    }

                    return $_plaintext;
                    ';
                break;
            case self::MODE_CFB:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_buffer = &$this->enbuffer;

                    if ($this->continuousBuffer) {
                        $_iv = &$this->encryptIV;
                        $_pos = &$_buffer["pos"];
                    } else {
                        $_iv = $this->encryptIV;
                        $_pos = 0;
                    }
                    $_len = strlen($_text);
                    $_i = 0;
                    if ($_pos) {
                        $_orig_pos = $_pos;
                        $_max = ' . $block_size . ' - $_pos;
                        if ($_len >= $_max) {
                            $_i = $_max;
                            $_len-= $_max;
                            $_pos = 0;
                        } else {
                            $_i = $_len;
                            $_pos+= $_len;
                            $_len = 0;
                        }
                        $_ciphertext = substr($_iv, $_orig_pos) ^ $_text;
                        $_iv = substr_replace($_iv, $_ciphertext, $_orig_pos, $_i);
                    }
                    while ($_len >= ' . $block_size . ') {
                        $in = $_iv;
                        ' . $encrypt_block . ';
                        $_iv = $in ^ substr($_text, $_i, ' . $block_size . ');
                        $_ciphertext.= $_iv;
                        $_len-= ' . $block_size . ';
                        $_i+= ' . $block_size . ';
                    }
                    if ($_len) {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_iv = $in;
                        $_block = $_iv ^ substr($_text, $_i);
                        $_iv = substr_replace($_iv, $_block, 0, $_len);
                        $_ciphertext.= $_block;
                        $_pos = $_len;
                    }
                    return $_ciphertext;
                ';
                $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_buffer = &$this->debuffer;

                    if ($this->continuousBuffer) {
                        $_iv = &$this->decryptIV;
                        $_pos = &$_buffer["pos"];
                    } else {
                        $_iv = $this->decryptIV;
                        $_pos = 0;
                    }
                    $_len = strlen($_text);
                    $_i = 0;
                    if ($_pos) {
                        $_orig_pos = $_pos;
                        $_max = ' . $block_size . ' - $_pos;
                        if ($_len >= $_max) {
                            $_i = $_max;
                            $_len-= $_max;
                            $_pos = 0;
                        } else {
                            $_i = $_len;
                            $_pos+= $_len;
                            $_len = 0;
                        }
                        $_plaintext = substr($_iv, $_orig_pos) ^ $_text;
                        $_iv = substr_replace($_iv, substr($_text, 0, $_i), $_orig_pos, $_i);
                    }
                    while ($_len >= ' . $block_size . ') {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_iv = $in;
                        $cb = substr($_text, $_i, ' . $block_size . ');
                        $_plaintext.= $_iv ^ $cb;
                        $_iv = $cb;
                        $_len-= ' . $block_size . ';
                        $_i+= ' . $block_size . ';
                    }
                    if ($_len) {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_iv = $in;
                        $_plaintext.= $_iv ^ substr($_text, $_i);
                        $_iv = substr_replace($_iv, substr($_text, $_i), 0, $_len);
                        $_pos = $_len;
                    }

                    return $_plaintext;
                    ';
                break;
            case self::MODE_CFB8:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_len = strlen($_text);
                    $_iv = $this->encryptIV;

                    for ($_i = 0; $_i < $_len; ++$_i) {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_ciphertext .= ($_c = $_text[$_i] ^ $in);
                        $_iv = substr($_iv, 1) . $_c;
                    }

                    if ($this->continuousBuffer) {
                        if ($_len >= ' . $block_size . ') {
                            $this->encryptIV = substr($_ciphertext, -' . $block_size . ');
                        } else {
                            $this->encryptIV = substr($this->encryptIV, $_len - ' . $block_size . ') . substr($_ciphertext, -$_len);
                        }
                    }

                    return $_ciphertext;
                    ';
                $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_len = strlen($_text);
                    $_iv = $this->decryptIV;

                    for ($_i = 0; $_i < $_len; ++$_i) {
                        $in = $_iv;
                        ' . $encrypt_block . '
                        $_plaintext .= $_text[$_i] ^ $in;
                        $_iv = substr($_iv, 1) . $_text[$_i];
                    }

                    if ($this->continuousBuffer) {
                        if ($_len >= ' . $block_size . ') {
                            $this->decryptIV = substr($_text, -' . $block_size . ');
                        } else {
                            $this->decryptIV = substr($this->decryptIV, $_len - ' . $block_size . ') . substr($_text, -$_len);
                        }
                    }

                    return $_plaintext;
                    ';
                break;
            case self::MODE_OFB:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);
                    $_xor = $this->encryptIV;
                    $_buffer = &$this->enbuffer;

                    if (strlen($_buffer["xor"])) {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            if (strlen($_block) > strlen($_buffer["xor"])) {
                                $in = $_xor;
                                ' . $encrypt_block . '
                                $_xor = $in;
                                $_buffer["xor"].= $_xor;
                            }
                            $_key = \\phpseclib3\\Common\\Functions\\Strings::shift($_buffer["xor"], ' . $block_size . ');
                            $_ciphertext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                            $in = $_xor;
                            ' . $encrypt_block . '
                            $_xor = $in;
                            $_ciphertext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor;
                        }
                        $_key = $_xor;
                    }
                    if ($this->continuousBuffer) {
                        $this->encryptIV = $_xor;
                        if ($_start = $_plaintext_len % ' . $block_size . ') {
                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
                        }
                    }
                    return $_ciphertext;
                    ';
                $decrypt = $init_encrypt . '
                    $_plaintext = "";
                    $_ciphertext_len = strlen($_text);
                    $_xor = $this->decryptIV;
                    $_buffer = &$this->debuffer;

                    if (strlen($_buffer["xor"])) {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                            $_block = substr($_text, $_i, ' . $block_size . ');
                            if (strlen($_block) > strlen($_buffer["xor"])) {
                                $in = $_xor;
                                ' . $encrypt_block . '
                                $_xor = $in;
                                $_buffer["xor"].= $_xor;
                            }
                            $_key = \\phpseclib3\\Common\\Functions\\Strings::shift($_buffer["xor"], ' . $block_size . ');
                            $_plaintext.= $_block ^ $_key;
                        }
                    } else {
                        for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                            $in = $_xor;
                            ' . $encrypt_block . '
                            $_xor = $in;
                            $_plaintext.= substr($_text, $_i, ' . $block_size . ') ^ $_xor;
                        }
                        $_key = $_xor;
                    }
                    if ($this->continuousBuffer) {
                        $this->decryptIV = $_xor;
                        if ($_start = $_ciphertext_len % ' . $block_size . ') {
                             $_buffer["xor"] = substr($_key, $_start) . $_buffer["xor"];
                        }
                    }
                    return $_plaintext;
                    ';
                break;
            case self::MODE_STREAM:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    ' . $encrypt_block . '
                    return $_ciphertext;
                    ';
                $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    ' . $decrypt_block . '
                    return $_plaintext;
                    ';
                break;
            // case self::MODE_CBC:
            default:
                $encrypt = $init_encrypt . '
                    $_ciphertext = "";
                    $_plaintext_len = strlen($_text);

                    $in = $this->encryptIV;

                    for ($_i = 0; $_i < $_plaintext_len; $_i+= ' . $block_size . ') {
                        $in = substr($_text, $_i, ' . $block_size . ') ^ $in;
                        ' . $encrypt_block . '
                        $_ciphertext.= $in;
                    }

                    if ($this->continuousBuffer) {
                        $this->encryptIV = $in;
                    }

                    return $_ciphertext;
                    ';
                $decrypt = $init_decrypt . '
                    $_plaintext = "";
                    $_text = str_pad($_text, strlen($_text) + (' . $block_size . ' - strlen($_text) % ' . $block_size . ') % ' . $block_size . ', chr(0));
                    $_ciphertext_len = strlen($_text);

                    $_iv = $this->decryptIV;

                    for ($_i = 0; $_i < $_ciphertext_len; $_i+= ' . $block_size . ') {
                        $in = $_block = substr($_text, $_i, ' . $block_size . ');
                        ' . $decrypt_block . '
                        $_plaintext.= $in ^ $_iv;
                        $_iv = $_block;
                    }

                    if ($this->continuousBuffer) {
                        $this->decryptIV = $_iv;
                    }

                    return $this->unpad($_plaintext);
                    ';
                break;
        }
        // Before discrediting this, please read the following:
        // @see https://github.com/phpseclib/phpseclib/issues/1293
        // @see https://github.com/phpseclib/phpseclib/pull/1143
        eval('$func = function ($_action, $_text) { ' . $init_crypt . 'if ($_action == "encrypt") { ' . $encrypt . ' } else { ' . $decrypt . ' }};');
        return \Closure::bind($func, $this, static::class);
    }
    /**
     * Convert float to int
     *
     * On ARM CPUs converting floats to ints doesn't always work
     *
     * @access private
     * @param string $x
     * @return int
     */
    protected static function safe_intval($x)
    {
        switch (true) {
            case is_int($x):
            // PHP 5.3, per http://php.net/releases/5_3_0.php, introduced "more consistent float rounding"
            case (php_uname('m') & "\xdf\xdf\xdf") != 'ARM':
                return $x;
        }
        return fmod($x, 0x80000000) & 0x7fffffff | (fmod(floor($x / 0x80000000), 2) & 1) << 31;
    }
    /**
     * eval()'able string for in-line float to int
     *
     * @access private
     * @return string
     */
    protected static function safe_intval_inline()
    {
        switch (true) {
            case defined('PHP_INT_SIZE') && PHP_INT_SIZE == 8:
            case (php_uname('m') & "\xdf\xdf\xdf") != 'ARM':
                return '%s';
                break;
            default:
                $safeint = '(is_int($temp = %s) ? $temp : (fmod($temp, 0x80000000) & 0x7FFFFFFF) | ';
                return $safeint . '((fmod(floor($temp / 0x80000000), 2) & 1) << 31))';
        }
    }
    /**
    * Sets up GCM parameters
    *
    * See steps 1-2 of https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=23
    for more info
    *
    * @access private
    */
    private function setupGCM()
    {
        // don't keep on re-calculating $this->h
        if (!$this->h || $this->h->key != $this->key) {
            $cipher = new static('ecb');
            $cipher->setKey($this->key);
            $cipher->disablePadding();
            $this->h = self::$gcmField->newInteger(Strings::switchEndianness($cipher->encrypt("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")));
            $this->h->key = $this->key;
        }
        if (strlen($this->nonce) == 12) {
            $this->iv = $this->nonce . "\x00\x00\x00\x01";
        } else {
            $this->iv = $this->ghash(self::nullPad128($this->nonce) . str_repeat("\x00", 8) . self::len64($this->nonce));
        }
    }
    /**
    * Performs GHASH operation
    *
    * See https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=20
    for more info
    *
    * @see self::decrypt()
    * @see self::encrypt()
    * @access private
    * @param string $x
    * @return string
    */
    private function ghash($x)
    {
        $h = $this->h;
        $y = ["\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"];
        $x = str_split($x, 16);
        $n = 0;
        // the switchEndianness calls are necessary because the multiplication algorithm in BinaryField/Integer
        // interprets strings as polynomials in big endian order whereas in GCM they're interpreted in little
        // endian order per https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38d.pdf#page=19.
        // big endian order is what binary field elliptic curves use per http://www.secg.org/sec1-v2.pdf#page=18.
        // we could switchEndianness here instead of in the while loop but doing so in the while loop seems like it
        // might be slightly more performant
        //$x = Strings::switchEndianness($x);
        foreach ($x as $xn) {
            $xn = Strings::switchEndianness($xn);
            $t = $y[$n] ^ $xn;
            $temp = self::$gcmField->newInteger($t);
            $y[++$n] = $temp->multiply($h)->toBytes();
            $y[$n] = \Phabel\Target\Php80\Polyfill::substr($y[$n], 1);
        }
        $y[$n] = Strings::switchEndianness($y[$n]);
        return $y[$n];
    }
    /**
     * Returns the bit length of a string in a packed format
     *
     * @see self::decrypt()
     * @see self::encrypt()
     * @see self::setupGCM()
     * @access private
     * @param string $str
     * @return string
     */
    private static function len64($str)
    {
        return "\x00\x00\x00\x00" . pack('N', 8 * strlen($str));
    }
    /**
     * NULL pads a string to be a multiple of 128
     *
     * @see self::decrypt()
     * @see self::encrypt()
     * @see self::setupGCM()
     * @access private
     * @param string $str
     * @return string
     */
    protected static function nullPad128($str)
    {
        $len = strlen($str);
        return $str . str_repeat("\x00", 16 * ceil($len / 16) - $len);
    }
    /**
    * Calculates Poly1305 MAC
    *
    * On my system ChaCha20, with libsodium, takes 0.5s. With this custom Poly1305 implementation
    it takes 1.2s.
    *
    * @see self::decrypt()
    * @see self::encrypt()
    * @access private
    * @param string $text
    * @return string
    */
    protected function poly1305($text)
    {
        $s = $this->poly1305Key;
        // strlen($this->poly1305Key) == 32
        $r = Strings::shift($s, 16);
        $r = strrev($r);
        $r &= "\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xfc\x0f\xff\xff\xff";
        $s = strrev($s);
        $r = self::$poly1305Field->newInteger(new BigInteger($r, 256));
        $s = self::$poly1305Field->newInteger(new BigInteger($s, 256));
        $a = self::$poly1305Field->newInteger(new BigInteger());
        $blocks = str_split($text, 16);
        foreach ($blocks as $block) {
            $n = strrev($block . chr(1));
            $n = self::$poly1305Field->newInteger(new BigInteger($n, 256));
            $a = $a->add($n);
            $a = $a->multiply($r);
        }
        $r = $a->toBigInteger()->add($s->toBigInteger());
        $mask = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff";
        return strrev($r->toBytes()) & $mask;
    }
    /**
     * Return the mode
     *
     * You can do $obj instanceof AES or whatever to get the cipher but you can't do that to get the mode
     *
     * @access public
     * @return string
     */
    public function getMode()
    {
        return array_flip(self::MODE_MAP)[$this->mode];
    }
}<?php

/**
 * Base Class for all asymmetric key ciphers
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   AsymmetricKey
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common;

use phpseclib3\Exception\UnsupportedFormatException;
use phpseclib3\Exception\NoKeyLoadedException;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\ECDSA;
/**
 * Base Class for all asymmetric cipher classes
 *
 * @package AsymmetricKey
 * @author  Jim Wigginton <terrafrost@php.net>
 */
abstract class AsymmetricKey
{
    /**
     * Precomputed Zero
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected static $zero;
    /**
     * Precomputed One
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected static $one;
    /**
     * Format of the loaded key
     *
     * @var string
     * @access private
     */
    protected $format;
    /**
     * Hash function
     *
     * @var \phpseclib3\Crypt\Hash
     * @access private
     */
    protected $hash;
    /**
     * HMAC function
     *
     * @var \phpseclib3\Crypt\Hash
     * @access private
     */
    private $hmac;
    /**
     * Supported plugins (lower case)
     *
     * @see self::initialize_static_variables()
     * @var array
     * @access private
     */
    private static $plugins = [];
    /**
     * Invisible plugins
     *
     * @see self::initialize_static_variables()
     * @var array
     * @access private
     */
    private static $invisiblePlugins = [];
    /**
     * Supported signature formats (lower case)
     *
     * @see self::initialize_static_variables()
     * @var array
     * @access private
     */
    private static $signatureFormats = [];
    /**
     * Supported signature formats (original case)
     *
     * @see self::initialize_static_variables()
     * @var array
     * @access private
     */
    private static $signatureFileFormats = [];
    /**
     * Available Engines
     *
     * @var boolean[]
     * @access private
     */
    protected static $engines = [];
    /**
     * Key Comment
     *
     * @var null|string
     * @access private
     */
    private $comment;
    /**
     * The constructor
     */
    protected function __construct()
    {
        self::initialize_static_variables();
        $this->hash = new Hash('sha256');
        $this->hmac = new Hash('sha256');
    }
    /**
     * Initialize static variables
     */
    protected static function initialize_static_variables()
    {
        if (!isset(self::$zero)) {
            self::$zero = new BigInteger(0);
            self::$one = new BigInteger(1);
        }
        self::loadPlugins('Keys');
        if (static::ALGORITHM != 'RSA' && static::ALGORITHM != 'DH') {
            self::loadPlugins('Signature');
        }
    }
    /**
     * Load the key
     *
     * @param string $key
     * @param string $password optional
     * @return AsymmetricKey
     */
    public static function load($key, $password = false)
    {
        self::initialize_static_variables();
        $components = false;
        foreach (self::$plugins[static::ALGORITHM]['Keys'] as $format) {
            if (isset(self::$invisiblePlugins[static::ALGORITHM]) && in_array($format, self::$invisiblePlugins[static::ALGORITHM])) {
                continue;
            }
            try {
                $components = $format::load($key, $password);
            } catch (\Exception $e) {
                $components = false;
            }
            if ($components !== false) {
                break;
            }
        }
        if ($components === false) {
            throw new NoKeyLoadedException('Unable to read key');
        }
        $components['format'] = $format;
        $comment = isset($components['comment']) ? $components['comment'] : null;
        $new = static::onLoad($components);
        $new->format = $format;
        $new->comment = $comment;
        return $new instanceof PrivateKey ? $new->withPassword($password) : $new;
    }
    /**
     * Loads a private key
     *
     * @return PrivateKey
     * @access public
     * @param (string | array) $key
     * @param string $password optional
     */
    public static function loadPrivateKey($key, $password = '')
    {
        $key = self::load($key, $password);
        if (!$key instanceof PrivateKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a private key');
        }
        return $key;
    }
    /**
     * Loads a public key
     *
     * @return PublicKey
     * @access public
     * @param (string | array) $key
     */
    public static function loadPublicKey($key)
    {
        $key = self::load($key);
        if (!$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a public key');
        }
        return $key;
    }
    /**
     * Loads parameters
     *
     * @return AsymmetricKey
     * @access public
     * @param (string | array) $key
     */
    public static function loadParameters($key)
    {
        $key = self::load($key);
        if (!$key instanceof PrivateKey && !$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a parameter');
        }
        return $key;
    }
    /**
     * Load the key, assuming a specific format
     *
     * @param string $type
     * @param string $key
     * @param string $password optional
     * @return AsymmetricKey
     */
    public static function loadFormat($type, $key, $password = false)
    {
        self::initialize_static_variables();
        $components = false;
        $format = strtolower($type);
        if (isset(self::$plugins[static::ALGORITHM]['Keys'][$format])) {
            $format = self::$plugins[static::ALGORITHM]['Keys'][$format];
            $components = $format::load($key, $password);
        }
        if ($components === false) {
            throw new NoKeyLoadedException('Unable to read key');
        }
        $components['format'] = $format;
        $new = static::onLoad($components);
        $new->format = $format;
        return $new instanceof PrivateKey ? $new->withPassword($password) : $new;
    }
    /**
     * Loads a private key
     *
     * @return PrivateKey
     * @access public
     * @param string $type
     * @param string $key
     * @param string $password optional
     */
    public static function loadPrivateKeyFormat($type, $key, $password = false)
    {
        $key = self::loadFormat($type, $key, $password);
        if (!$key instanceof PrivateKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a private key');
        }
        return $key;
    }
    /**
     * Loads a public key
     *
     * @return PublicKey
     * @access public
     * @param string $type
     * @param string $key
     */
    public static function loadPublicKeyFormat($type, $key)
    {
        $key = self::loadFormat($type, $key);
        if (!$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a public key');
        }
        return $key;
    }
    /**
     * Loads parameters
     *
     * @return AsymmetricKey
     * @access public
     * @param string $type
     * @param (string | array) $key
     */
    public static function loadParametersFormat($type, $key)
    {
        $key = self::loadFormat($type, $key);
        if (!$key instanceof PrivateKey && !$key instanceof PublicKey) {
            throw new NoKeyLoadedException('The key that was loaded was not a parameter');
        }
        return $key;
    }
    /**
     * Validate Plugin
     *
     * @access private
     * @param string $format
     * @param string $type
     * @param string $method optional
     * @return mixed
     */
    protected static function validatePlugin($format, $type, $method = NULL)
    {
        $type = strtolower($type);
        if (!isset(self::$plugins[static::ALGORITHM][$format][$type])) {
            throw new UnsupportedFormatException("{$type} is not a supported format");
        }
        $type = self::$plugins[static::ALGORITHM][$format][$type];
        if (isset($method) && !method_exists($type, $method)) {
            throw new UnsupportedFormatException("{$type} does not implement {$method}");
        }
        return $type;
    }
    /**
     * Load Plugins
     *
     * @access private
     * @param string $format
     */
    private static function loadPlugins($format)
    {
        if (!isset(self::$plugins[static::ALGORITHM][$format])) {
            self::$plugins[static::ALGORITHM][$format] = [];
            foreach (new \DirectoryIterator(__DIR__ . '/../' . static::ALGORITHM . '/Formats/' . $format . '/') as $file) {
                if ($file->getExtension() != 'php') {
                    continue;
                }
                $name = $file->getBasename('.php');
                if ($name[0] == '.') {
                    continue;
                }
                $type = 'phpseclib3\\Crypt\\' . static::ALGORITHM . '\\Formats\\' . $format . '\\' . $name;
                $reflect = new \ReflectionClass($type);
                if ($reflect->isTrait()) {
                    continue;
                }
                self::$plugins[static::ALGORITHM][$format][strtolower($name)] = $type;
                if ($reflect->hasConstant('IS_INVISIBLE')) {
                    self::$invisiblePlugins[static::ALGORITHM][] = $type;
                }
            }
        }
    }
    /**
     * Returns a list of supported formats.
     *
     * @access public
     * @return array
     */
    public static function getSupportedKeyFormats()
    {
        self::initialize_static_variables();
        return self::$plugins[static::ALGORITHM]['Keys'];
    }
    /**
    * Add a fileformat plugin
    *
    * The plugin needs to either already be loaded or be auto-loadable.
    Loading a plugin whose shortname overwrite an existing shortname will overwrite the old plugin.
    *
    * @see self::load()
    * @param string $fullname
    * @access public
    * @return bool
    */
    public static function addFileFormat($fullname)
    {
        self::initialize_static_variables();
        if (class_exists($fullname)) {
            $meta = new \ReflectionClass($fullname);
            $shortname = $meta->getShortName();
            self::$plugins[static::ALGORITHM]['Keys'][strtolower($shortname)] = $fullname;
            if ($meta->hasConstant('IS_INVISIBLE')) {
                self::$invisiblePlugins[static::ALGORITHM] = strtolower($name);
            }
        }
    }
    /**
    * Returns the format of the loaded key.
    *
    * If the key that was loaded wasn't in a valid or if the key was auto-generated
    with RSA::createKey() then this will throw an exception.
    *
    * @see self::load()
    * @access public
    * @return mixed
    */
    public function getLoadedFormat()
    {
        if (empty($this->format)) {
            throw new NoKeyLoadedException('This key was created with createKey - it was not loaded with load. Therefore there is no "loaded format"');
        }
        $meta = new \ReflectionClass($this->format);
        return $meta->getShortName();
    }
    /**
     * Returns the key's comment
     *
     * Not all key formats support comments. If you want to set a comment use toString()
     *
     * @access public
     * @return (null | string)
     */
    public function getComment()
    {
        return $this->comment;
    }
    /**
     * Tests engine validity
     *
     * @access public
     */
    public static function useBestEngine()
    {
        static::$engines = [
            'PHP' => true,
            'OpenSSL' => extension_loaded('openssl'),
            // this test can be satisfied by either of the following:
            // http://php.net/manual/en/book.sodium.php
            // https://github.com/paragonie/sodium_compat
            'libsodium' => function_exists('sodium_crypto_sign_keypair'),
        ];
        return static::$engines;
    }
    /**
     * Flag to use internal engine only (useful for unit testing)
     *
     * @access public
     */
    public static function useInternalEngine()
    {
        static::$engines = ['PHP' => true, 'OpenSSL' => false, 'libsodium' => false];
    }
    /**
     * __toString() magic method
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toString('PKCS8');
    }
    /**
     * Determines which hashing function should be used
     *
     * @access public
     * @param string $hash
     */
    public function withHash($hash)
    {
        $new = clone $this;
        $new->hash = new Hash($hash);
        $new->hmac = new Hash($hash);
        return $new;
    }
    /**
     * Returns the hash algorithm currently being used
     *
     * @access public
     */
    public function getHash()
    {
        return clone $this->hash;
    }
    /**
    * Compute the pseudorandom k for signature generation,
    using the process specified for deterministic DSA.
    *
    * @access public
    * @param string $h1
    * @return string
    */
    protected function computek($h1)
    {
        $v = str_repeat("\x01", strlen($h1));
        $k = str_repeat("\x00", strlen($h1));
        $x = $this->int2octets($this->x);
        $h1 = $this->bits2octets($h1);
        $this->hmac->setKey($k);
        $k = $this->hmac->hash($v . "\x00" . $x . $h1);
        $this->hmac->setKey($k);
        $v = $this->hmac->hash($v);
        $k = $this->hmac->hash($v . "\x01" . $x . $h1);
        $this->hmac->setKey($k);
        $v = $this->hmac->hash($v);
        $qlen = $this->q->getLengthInBytes();
        while (true) {
            $t = '';
            while (strlen($t) < $qlen) {
                $v = $this->hmac->hash($v);
                $t = $t . $v;
            }
            $k = $this->bits2int($t);
            if (!$k->equals(self::$zero) && $k->compare($this->q) < 0) {
                break;
            }
            $k = $this->hmac->hash($v . "\x00");
            $this->hmac->setKey($k);
            $v = $this->hmac->hash($v);
        }
        return $k;
    }
    /**
     * Integer to Octet String
     *
     * @access private
     * @param \phpseclib3\Math\BigInteger $v
     * @return string
     */
    private function int2octets($v)
    {
        $out = $v->toBytes();
        $rolen = $this->q->getLengthInBytes();
        if (strlen($out) < $rolen) {
            return str_pad($out, $rolen, "\x00", STR_PAD_LEFT);
        } else {
            if (strlen($out) > $rolen) {
                return \Phabel\Target\Php80\Polyfill::substr($out, -$rolen);
            } else {
                return $out;
            }
        }
    }
    /**
     * Bit String to Integer
     *
     * @access private
     * @param string $in
     * @return \phpseclib3\Math\BigInteger
     */
    protected function bits2int($in)
    {
        $v = new BigInteger($in, 256);
        $vlen = strlen($in) << 3;
        $qlen = $this->q->getLength();
        if ($vlen > $qlen) {
            return $v->bitwise_rightShift($vlen - $qlen);
        }
        return $v;
    }
    /**
     * Bit String to Octet String
     *
     * @access private
     * @param string $in
     * @return string
     */
    private function bits2octets($in)
    {
        $z1 = $this->bits2int($in);
        $z2 = $z1->subtract($this->q);
        return $z2->compare(self::$zero) < 0 ? $this->int2octets($z1) : $this->int2octets($z2);
    }
}<?php

/**
 * Password Protected Trait for Private Keys
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Traits;

/**
 * Password Protected Trait for Private Keys
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
trait PasswordProtected
{
    /**
     * Password
     *
     * @var string|bool
     */
    private $password = false;
    /**
    * Sets the password
    *
    * Private keys can be encrypted with a password.  To unset the password, pass in the empty string or false.
    Or rather, pass in $password such that empty($password) && !is_string($password) is true.
    *
    * @see self::createKey()
    * @see self::load()
    * @access public
    * @param (string | boolean) $password
    */
    public function withPassword($password = false)
    {
        $new = clone $this;
        $new->password = $password;
        return $new;
    }
}<?php

/**
 * Fingerprint Trait for Public Keys
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Common
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt\Common\Traits;

use phpseclib3\Crypt\Hash;
/**
 * Fingerprint Trait for Private Keys
 *
 * @package Common
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
trait Fingerprint
{
    /**
    * Returns the public key's fingerprint
    *
    * The public key's fingerprint is returned, which is equivalent to running `ssh-keygen -lf rsa.pub`. If there is
    no public key currently loaded, false is returned.
    Example output (md5): "c1:b1:30:29:d7:b8:de:6c:97:77:10:d7:46:41:63:87" (as specified by RFC 4716)
    *
    * @access public
    * @param string $algorithm The hashing algorithm to be used. Valid options are 'md5' and 'sha256'. False is returned
    for invalid values.
    * @return mixed
    */
    public function getFingerprint($algorithm = 'md5')
    {
        $type = self::validatePlugin('Keys', 'OpenSSH', 'savePublicKey');
        if ($type === false) {
            return false;
        }
        $key = $this->toString('OpenSSH', ['binary' => true]);
        if ($key === false) {
            return false;
        }
        switch ($algorithm) {
            case 'sha256':
                $hash = new Hash('sha256');
                $base = base64_encode($hash->hash($key));
                return \Phabel\Target\Php80\Polyfill::substr($base, 0, strlen($base) - 1);
            case 'md5':
                return \Phabel\Target\Php80\Polyfill::substr(chunk_split(md5($key), 2, ':'), 0, -1);
            default:
                return false;
        }
    }
}<?php

/**
 * Pure-PHP (EC)DH implementation
 *
 * PHP version 5
 *
 * Here's an example of how to compute a shared secret with this library:
 * <code>
 * <?php
 * include 'vendor/autoload.php';
 *
 * $ourPrivate = \phpseclib3\Crypt\DH::createKey();
 * $secret = DH::computeSecret($ourPrivate, $theirPublic);
 *
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   DH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Exception\NoKeyLoadedException;
use phpseclib3\Exception\UnsupportedOperationException;
use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\Crypt\DH\PrivateKey;
use phpseclib3\Crypt\DH\PublicKey;
use phpseclib3\Crypt\DH\Parameters;
use phpseclib3\Math\BigInteger;
/**
 * Pure-PHP (EC)DH implementation
 *
 * @package DH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DH extends AsymmetricKey
{
    /**
     * Algorithm Name
     *
     * @var string
     * @access private
     */
    const ALGORITHM = 'DH';
    /**
     * DH prime
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $prime;
    /**
     * DH Base
     *
     * Prime divisor of p-1
     *
     * @var \phpseclib3\Math\BigInteger
     * @access private
     */
    protected $base;
    /**
    * Create DH parameters
    *
    * This method is a bit polymorphic. It can take any of the following:
    - two BigInteger's (prime and base)
    - an integer representing the size of the prime in bits (the base is assumed to be 2)
    - a string (eg. diffie-hellman-group14-sha1)
    *
    * @access public
    * @return (\phpseclib3\Crypt\DH | bool)
    */
    public static function createParameters(...$args)
    {
        $params = new Parameters();
        if (count($args) == 2 && $args[0] instanceof BigInteger && $args[1] instanceof BigInteger) {
            //if (!$args[0]->isPrime()) {
            //    throw new \InvalidArgumentException('The first parameter should be a prime number');
            //}
            $params->prime = $args[0];
            $params->base = $args[1];
            return $params;
        } elseif (count($args) == 1 && is_numeric($args[0])) {
            $params->prime = BigInteger::randomPrime($args[0]);
            $params->base = new BigInteger(2);
            return $params;
        } elseif (count($args) != 1 || !is_string($args[0])) {
            throw new \InvalidArgumentException('Valid parameters are either: two BigInteger\'s (prime and base), a single integer (the length of the prime; base is assumed to be 2) or a string');
        }
        switch ($args[0]) {
            // see http://tools.ietf.org/html/rfc2409#section-6.2 and
            // http://tools.ietf.org/html/rfc2412, appendex E
            case 'diffie-hellman-group1-sha1':
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF';
                break;
            // see http://tools.ietf.org/html/rfc3526#section-3
            case 'diffie-hellman-group14-sha1':
            // 2048-bit MODP Group
            case 'diffie-hellman-group14-sha256':
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF';
                break;
            // see https://tools.ietf.org/html/rfc3526#section-4
            case 'diffie-hellman-group15-sha512':
                // 3072-bit MODP Group
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF';
                break;
            // see https://tools.ietf.org/html/rfc3526#section-5
            case 'diffie-hellman-group16-sha512':
                // 4096-bit MODP Group
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199FFFFFFFFFFFFFFFF';
                break;
            // see https://tools.ietf.org/html/rfc3526#section-6
            case 'diffie-hellman-group17-sha512':
                // 6144-bit MODP Group
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF';
                break;
            // see https://tools.ietf.org/html/rfc3526#section-7
            case 'diffie-hellman-group18-sha512':
                // 8192-bit MODP Group
                $prime = 'FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D788719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA993B4EA988D8FDDC186FFB7DC90A6C08F4DF435C93402849236C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BDF8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1BDB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F323A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AACC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE32806A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55CDA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E438777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F5683423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD922222E04A4037C0713EB57A81A23F0C73473FC646CEA306B4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A364597E899A0255DC164F31CC50846851DF9AB48195DED7EA1B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F924009438B481C6CD7889A002ED5EE382BC9190DA6FC026E479558E4475677E9AA9E3050E2765694DFC81F56E880B96E7160C980DD98EDD3DFFFFFFFFFFFFFFFFF';
                break;
            default:
                throw new \InvalidArgumentException('Invalid named prime provided');
        }
        $params->prime = new BigInteger($prime, 16);
        $params->base = new BigInteger(2);
        return $params;
    }
    /**
    * Create public / private key pair.
    *
    * The rationale for the second parameter is described in http://tools.ietf.org/html/rfc4419#section-6.2 :
    *
    * "To increase the speed of the key exchange, both client and server may
    reduce the size of their private exponents.  It should be at least
    twice as long as the key material that is generated from the shared
    secret.  For more details, see the paper by van Oorschot and Wiener
    [VAN-OORSCHOT]."
    *
    * $length is in bits
    *
    * @param Parameters $params
    * @param int $length optional
    * @access public
    * @return DH\PrivateKey
    */
    public static function createKey(Parameters $params, $length = 0)
    {
        $one = new BigInteger(1);
        if ($length) {
            $max = $one->bitwise_leftShift($length);
            $max = $max->subtract($one);
        } else {
            $max = $params->prime->subtract($one);
        }
        $key = new PrivateKey();
        $key->prime = $params->prime;
        $key->base = $params->base;
        $key->privateKey = BigInteger::randomRange($one, $max);
        $key->publicKey = $key->base->powMod($key->privateKey, $key->prime);
        return $key;
    }
    /**
     * Compute Shared Secret
     *
     * @param (PrivateKey | EC) $private
     * @param (PublicKey | BigInteger | string) $public
     * @access public
     * @return mixed
     */
    public static function computeSecret($private, $public)
    {
        if ($private instanceof PrivateKey) {
            // DH\PrivateKey
            switch (true) {
                case $public instanceof PublicKey:
                    if (!$private->prime->equals($public->prime) || !$private->base->equals($public->base)) {
                        throw new \InvalidArgumentException('The public and private key do not share the same prime and / or base numbers');
                    }
                    return $public->publicKey->powMod($private->privateKey, $private->prime)->toBytes(true);
                case is_string($public):
                    $public = new BigInteger($public, -256);
                case $public instanceof BigInteger:
                    return $public->powMod($private->privateKey, $private->prime)->toBytes(true);
                default:
                    throw new \InvalidArgumentException('$public needs to be an instance of DH\\PublicKey, a BigInteger or a string');
            }
        }
        if ($private instanceof EC\PrivateKey) {
            switch (true) {
                case $public instanceof EC\PublicKey:
                    $public = $public->getEncodedCoordinates();
                case is_string($public):
                    $point = $private->multiply($public);
                    switch ($private->getCurve()) {
                        case 'Curve25519':
                        case 'Curve448':
                            $secret = $point;
                            break;
                        default:
                            // according to https://www.secg.org/sec1-v2.pdf#page=33 only X is returned
                            $secret = \Phabel\Target\Php80\Polyfill::substr($point, 1, strlen($point) - 1 >> 1);
                    }
                    /*
                    if (($secret[0] & "\x80") === "\x80") {
                        $secret = "\0$secret";
                    }
                    */
                    return $secret;
                default:
                    throw new \InvalidArgumentException('$public needs to be an instance of EC\\PublicKey or a string (an encoded coordinate)');
            }
        }
    }
    /**
     * Load the key
     *
     * @param string $key
     * @param string $password optional
     * @return AsymmetricKey
     */
    public static function load($key, $password = false)
    {
        try {
            return EC::load($key, $password);
        } catch (NoKeyLoadedException $e) {
        }
        return parent::load($key, $password);
    }
    /**
     * OnLoad Handler
     *
     * @return bool
     * @access protected
     * @param array $components
     */
    protected static function onLoad($components)
    {
        if (!isset($components['privateKey']) && !isset($components['publicKey'])) {
            $new = new Parameters();
        } else {
            $new = isset($components['privateKey']) ? new PrivateKey() : new PublicKey();
        }
        $new->prime = $components['prime'];
        $new->base = $components['base'];
        if (isset($components['privateKey'])) {
            $new->privateKey = $components['privateKey'];
        }
        if (isset($components['publicKey'])) {
            $new->publicKey = $components['publicKey'];
        }
        return $new;
    }
    /**
     * Determines which hashing function should be used
     *
     * @access public
     * @param string $hash
     */
    public function withHash($hash)
    {
        throw new UnsupportedOperationException('DH does not use a hash algorithm');
    }
    /**
     * Returns the hash algorithm currently being used
     *
     * @access public
     */
    public function getHash()
    {
        throw new UnsupportedOperationException('DH does not use a hash algorithm');
    }
    /**
    * Returns the parameters
    *
    * A public / private key is only returned if the currently loaded "key" contains an x or y
    value.
    *
    * @see self::getPublicKey()
    * @access public
    * @return mixed
    */
    public function getParameters()
    {
        $type = self::validatePlugin('Keys', 'PKCS1', 'saveParameters');
        $key = $type::saveParameters($this->prime, $this->base);
        return self::load($key, 'PKCS1');
    }
}<?php

/**
 * Pure-PHP implementation of ChaCha20.
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   ChaCha20
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Exception\BadDecryptionException;
/**
 * Pure-PHP implementation of ChaCha20.
 *
 * @package ChaCha20
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class ChaCha20 extends Salsa20
{
    /**
     * The OpenSSL specific name of the cipher
     *
     * @var string
     */
    protected $cipher_name_openssl = 'chacha20';
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::__construct()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        switch ($engine) {
            case self::ENGINE_LIBSODIUM:
                // PHP 7.2.0 (30 Nov 2017) added support for libsodium
                // we could probably make it so that if $this->counter == 0 then the first block would be done with either OpenSSL
                // or PHP and then subsequent blocks would then be done with libsodium but idk - it's not a high priority atm
                // we could also make it so that if $this->counter == 0 and $this->continuousBuffer then do the first string
                // with libsodium and subsequent strings with openssl or pure-PHP but again not a high priority
                return function_exists('sodium_crypto_aead_chacha20poly1305_ietf_encrypt') && $this->key_length == 32 && ($this->usePoly1305 && !isset($this->poly1305Key) && $this->counter == 0 || $this->counter == 1) && !$this->continuousBuffer;
            case self::ENGINE_OPENSSL:
                // OpenSSL 1.1.0 (released 25 Aug 2016) added support for chacha20.
                // PHP didn't support OpenSSL 1.1.0 until 7.0.19 (11 May 2017)
                // if you attempt to provide openssl with a 128 bit key (as opposed to a 256 bit key) openssl will null
                // pad the key to 256 bits and still use the expansion constant for 256-bit keys. the fact that
                // openssl treats the IV as both the counter and nonce, however, let's us use openssl in continuous mode
                // whereas libsodium does not
                if ($this->key_length != 32) {
                    return false;
                }
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Encrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @see self::crypt()
     * @param string $plaintext
     * @return string $ciphertext
     */
    public function encrypt($plaintext)
    {
        $this->setup();
        if ($this->engine == self::ENGINE_LIBSODIUM) {
            return $this->encrypt_with_libsodium($plaintext);
        }
        return parent::encrypt($plaintext);
    }
    /**
    * Decrypts a message.
    *
    * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
    At least if the continuous buffer is disabled.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
    * @see self::crypt()
    * @param string $ciphertext
    * @return string $plaintext
    */
    public function decrypt($ciphertext)
    {
        $this->setup();
        if ($this->engine == self::ENGINE_LIBSODIUM) {
            return $this->decrypt_with_libsodium($ciphertext);
        }
        return parent::decrypt($ciphertext);
    }
    /**
     * Encrypts a message with libsodium
     *
     * @see self::encrypt()
     * @param string $plaintext
     * @return string $text
     */
    private function encrypt_with_libsodium($plaintext)
    {
        $params = [$plaintext, $this->aad, $this->nonce, $this->key];
        $ciphertext = strlen($this->nonce) == 8 ? sodium_crypto_aead_chacha20poly1305_encrypt(...$params) : sodium_crypto_aead_chacha20poly1305_ietf_encrypt(...$params);
        if (!$this->usePoly1305) {
            return \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, strlen($plaintext));
        }
        $newciphertext = \Phabel\Target\Php80\Polyfill::substr($ciphertext, 0, strlen($plaintext));
        $this->newtag = $this->usingGeneratedPoly1305Key && strlen($this->nonce) == 12 ? \Phabel\Target\Php80\Polyfill::substr($ciphertext, strlen($plaintext)) : $this->poly1305($newciphertext);
        return $newciphertext;
    }
    /**
     * Decrypts a message with libsodium
     *
     * @see self::decrypt()
     * @param string $ciphertext
     * @return string $text
     */
    private function decrypt_with_libsodium($ciphertext)
    {
        $params = [$ciphertext, $this->aad, $this->nonce, $this->key];
        if (isset($this->poly1305Key)) {
            if ($this->oldtag === false) {
                throw new InsufficientSetupException('Authentication Tag has not been set');
            }
            if ($this->usingGeneratedPoly1305Key && strlen($this->nonce) == 12) {
                $plaintext = sodium_crypto_aead_chacha20poly1305_ietf_decrypt(...$params);
                $this->oldtag = false;
                if ($plaintext === false) {
                    throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
                }
                return $plaintext;
            }
            $newtag = $this->poly1305($ciphertext);
            if ($this->oldtag != \Phabel\Target\Php80\Polyfill::substr($newtag, 0, strlen($this->oldtag))) {
                $this->oldtag = false;
                throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
            }
            $this->oldtag = false;
        }
        $plaintext = strlen($this->nonce) == 8 ? sodium_crypto_aead_chacha20poly1305_encrypt(...$params) : sodium_crypto_aead_chacha20poly1305_ietf_encrypt(...$params);
        return \Phabel\Target\Php80\Polyfill::substr($plaintext, 0, strlen($ciphertext));
    }
    /**
     * Sets the nonce.
     *
     * @param string $nonce
     */
    public function setNonce($nonce)
    {
        if (!is_string($nonce)) {
            throw new \UnexpectedValueException('The nonce should be a string');
        }
        /*
         from https://tools.ietf.org/html/rfc7539#page-7
        
         "Note also that the original ChaCha had a 64-bit nonce and 64-bit
          block count.  We have modified this here to be more consistent with
          recommendations in Section 3.2 of [RFC5116]."
        */
        switch (strlen($nonce)) {
            case 8:
            // 64 bits
            case 12:
                // 96 bits
                break;
            default:
                throw new \LengthException('Nonce of size ' . strlen($nonce) . ' not supported by this algorithm. Only 64-bit nonces or 96-bit nonces are supported');
        }
        $this->nonce = $nonce;
        $this->changed = true;
        $this->setEngine();
    }
    /**
    * Setup the self::ENGINE_INTERNAL $engine
    *
    * (re)init, if necessary, the internal cipher $engine
    *
    * _setup() will be called each time if $changed === true
    typically this happens when using one or more of following public methods:
    *
    * - setKey()
    *
    * - setNonce()
    *
    * - First run of encrypt() / decrypt() with no init-settings
    *
    * @see self::setKey()
    * @see self::setNonce()
    * @see self::disableContinuousBuffer()
    */
    protected function setup()
    {
        if (!$this->changed) {
            return;
        }
        $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'counter' => $this->counter];
        $this->changed = $this->nonIVChanged = false;
        if ($this->nonce === false) {
            throw new InsufficientSetupException('No nonce has been defined');
        }
        if ($this->key === false) {
            throw new InsufficientSetupException('No key has been defined');
        }
        if ($this->usePoly1305 && !isset($this->poly1305Key)) {
            $this->usingGeneratedPoly1305Key = true;
            if ($this->engine == self::ENGINE_LIBSODIUM) {
                return;
            }
            $this->createPoly1305Key();
        }
        $key = $this->key;
        if (strlen($key) == 16) {
            $constant = 'expand 16-byte k';
            $key .= $key;
        } else {
            $constant = 'expand 32-byte k';
        }
        $this->p1 = $constant . $key;
        $this->p2 = $this->nonce;
        if (strlen($this->nonce) == 8) {
            $this->p2 = "\x00\x00\x00\x00" . $this->p2;
        }
    }
    /**
     * The quarterround function
     *
     * @param int $a
     * @param int $b
     * @param int $c
     * @param int $d
     */
    protected static function quarterRound(&$a, &$b, &$c, &$d)
    {
        $a += $b;
        $d = self::leftRotate($d ^ $a, 16);
        $c += $d;
        $b = self::leftRotate($b ^ $c, 12);
        $a += $b;
        $d = self::leftRotate($d ^ $a, 8);
        $c += $d;
        $b = self::leftRotate($b ^ $c, 7);
    }
    /**
     * The doubleround function
     *
     * @param int $x0 (by reference)
     * @param int $x1 (by reference)
     * @param int $x2 (by reference)
     * @param int $x3 (by reference)
     * @param int $x4 (by reference)
     * @param int $x5 (by reference)
     * @param int $x6 (by reference)
     * @param int $x7 (by reference)
     * @param int $x8 (by reference)
     * @param int $x9 (by reference)
     * @param int $x10 (by reference)
     * @param int $x11 (by reference)
     * @param int $x12 (by reference)
     * @param int $x13 (by reference)
     * @param int $x14 (by reference)
     * @param int $x15 (by reference)
     */
    protected static function doubleRound(&$x0, &$x1, &$x2, &$x3, &$x4, &$x5, &$x6, &$x7, &$x8, &$x9, &$x10, &$x11, &$x12, &$x13, &$x14, &$x15)
    {
        // columnRound
        static::quarterRound($x0, $x4, $x8, $x12);
        static::quarterRound($x1, $x5, $x9, $x13);
        static::quarterRound($x2, $x6, $x10, $x14);
        static::quarterRound($x3, $x7, $x11, $x15);
        // rowRound
        static::quarterRound($x0, $x5, $x10, $x15);
        static::quarterRound($x1, $x6, $x11, $x12);
        static::quarterRound($x2, $x7, $x8, $x13);
        static::quarterRound($x3, $x4, $x9, $x14);
    }
    /**
    * The Salsa20 hash function function
    *
    * On my laptop this loop unrolled / function dereferenced version of parent::salsa20 encrypts 1mb of text in
    0.65s vs the 0.85s that it takes with the parent method.
    *
    * If we were free to assume that the host OS would always be 64-bits then the if condition in leftRotate could
    be eliminated and we could knock this done to 0.60s.
    *
    * For comparison purposes, RC4 takes 0.16s and AES in CTR mode with the Eval engine takes 0.48s.
    AES in CTR mode with the PHP engine takes 1.19s. Salsa20 / ChaCha20 do not benefit as much from the Eval
    approach due to the fact that there are a lot less variables to de-reference, fewer loops to unroll, etc
    *
    * @param string $x
    */
    protected static function salsa20($x)
    {
        list(, $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15) = unpack('V*', $x);
        $z0 = $x0;
        $z1 = $x1;
        $z2 = $x2;
        $z3 = $x3;
        $z4 = $x4;
        $z5 = $x5;
        $z6 = $x6;
        $z7 = $x7;
        $z8 = $x8;
        $z9 = $x9;
        $z10 = $x10;
        $z11 = $x11;
        $z12 = $x12;
        $z13 = $x13;
        $z14 = $x14;
        $z15 = $x15;
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        // columnRound
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 16);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 12);
        $x0 += $x4;
        $x12 = self::leftRotate($x12 ^ $x0, 8);
        $x8 += $x12;
        $x4 = self::leftRotate($x4 ^ $x8, 7);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 16);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 12);
        $x1 += $x5;
        $x13 = self::leftRotate($x13 ^ $x1, 8);
        $x9 += $x13;
        $x5 = self::leftRotate($x5 ^ $x9, 7);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 16);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 12);
        $x2 += $x6;
        $x14 = self::leftRotate($x14 ^ $x2, 8);
        $x10 += $x14;
        $x6 = self::leftRotate($x6 ^ $x10, 7);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 16);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 12);
        $x3 += $x7;
        $x15 = self::leftRotate($x15 ^ $x3, 8);
        $x11 += $x15;
        $x7 = self::leftRotate($x7 ^ $x11, 7);
        // rowRound
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 16);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 12);
        $x0 += $x5;
        $x15 = self::leftRotate($x15 ^ $x0, 8);
        $x10 += $x15;
        $x5 = self::leftRotate($x5 ^ $x10, 7);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 16);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 12);
        $x1 += $x6;
        $x12 = self::leftRotate($x12 ^ $x1, 8);
        $x11 += $x12;
        $x6 = self::leftRotate($x6 ^ $x11, 7);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 16);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 12);
        $x2 += $x7;
        $x13 = self::leftRotate($x13 ^ $x2, 8);
        $x8 += $x13;
        $x7 = self::leftRotate($x7 ^ $x8, 7);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 16);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 12);
        $x3 += $x4;
        $x14 = self::leftRotate($x14 ^ $x3, 8);
        $x9 += $x14;
        $x4 = self::leftRotate($x4 ^ $x9, 7);
        $x0 += $z0;
        $x1 += $z1;
        $x2 += $z2;
        $x3 += $z3;
        $x4 += $z4;
        $x5 += $z5;
        $x6 += $z6;
        $x7 += $z7;
        $x8 += $z8;
        $x9 += $z9;
        $x10 += $z10;
        $x11 += $z11;
        $x12 += $z12;
        $x13 += $z13;
        $x14 += $z14;
        $x15 += $z15;
        return pack('V*', $x0, $x1, $x2, $x3, $x4, $x5, $x6, $x7, $x8, $x9, $x10, $x11, $x12, $x13, $x14, $x15);
    }
}<?php

/**
 * Pure-PHP implementation of Blowfish.
 *
 * Uses mcrypt, if available, and an internal implementation, otherwise.
 *
 * PHP version 5
 *
 * Useful resources are as follows:
 *
 *  - {@link http://en.wikipedia.org/wiki/Blowfish_(cipher) Wikipedia description of Blowfish}
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $blowfish = new \phpseclib3\Crypt\Blowfish('ctr');
 *
 *    $blowfish->setKey('12345678901234567890123456789012');
 *
 *    $plaintext = str_repeat('a', 1024);
 *
 *    echo $blowfish->decrypt($blowfish->encrypt($plaintext));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Blowfish
 * @author    Jim Wigginton <terrafrost@php.net>
 * @author    Hans-Juergen Petrich <petrich@tronic-media.com>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\BlockCipher;
/**
 * Pure-PHP implementation of Blowfish.
 *
 * @package Blowfish
 * @author  Jim Wigginton <terrafrost@php.net>
 * @author  Hans-Juergen Petrich <petrich@tronic-media.com>
 * @access  public
 */
class Blowfish extends BlockCipher
{
    /**
     * Block Length of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::block_size
     * @var int
     * @access private
     */
    protected $block_size = 8;
    /**
     * The mcrypt specific name of the cipher
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cipher_name_mcrypt
     * @var string
     * @access private
     */
    protected $cipher_name_mcrypt = 'blowfish';
    /**
     * Optimizing value while CFB-encrypting
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::cfb_init_len
     * @var int
     * @access private
     */
    protected $cfb_init_len = 500;
    /**
     * The fixed subkeys boxes ($sbox0 - $sbox3) with 256 entries each
     *
     * S-Box 0
     *
     * @access private
     * @var    array
     */
    private static $sbox0 = [0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x801f2e2, 0x858efc16, 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0xd95748f, 0x728eb658, 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0xf6d6ff3, 0x83f44239, 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, 0x75372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, 0x976ce0bd, 0x4c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x250e2d, 0x2071b35e, 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x2e5b9c5, 0x83260376, 0x6295cfa9, 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x8ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, 0x53b02d5d, 0xa99f8fa1, 0x8ba4799, 0x6e85076a];
    /**
     * S-Box 1
     *
     * @access private
     * @var    array
     */
    private static $sbox1 = [0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x21ecc5e, 0x9686b3f, 0x3ebaefc9, 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, 0xf01c1f04, 0x200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, 0xc8b57634, 0x9af3dda7, 0xa9446146, 0xfd0030e, 0xecc8c73e, 0xa4751e41, 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x43556f1, 0xd7a3c76b, 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x18cff28, 0xc332ddef, 0xbe6c5aa5, 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, 0x334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, 0x11ed935f, 0x16681281, 0xe358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, 0x95bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0xc55f5ea, 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, 0x9e447a2e, 0xc3453484, 0xfdd56705, 0xe1e9ec9, 0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7];
    /**
     * S-Box 2
     *
     * @access private
     * @var    array
     */
    private static $sbox2 = [0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x3bd9785, 0x7fac6dd0, 0x31cb8504, 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, 0xa2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, 0xfdf8e802, 0x4272f70, 0x80bb155c, 0x5282ce3, 0x95c11548, 0xe4c66d22, 0x48c1133f, 0xc70f86dc, 0x7f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, 0xdff8e8a3, 0x1f636c1b, 0xe12b4c2, 0x2e1329e, 0xaf664fd1, 0xcad18115, 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0xa476341, 0x992eff74, 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, 0x6a124237, 0xb79251e7, 0x6a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0xa121386, 0xd90cec6e, 0xd5abea2a, 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x9f0be8c, 0x4a99a025, 0x1d6efe10, 0x1ab93d1d, 0xba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0xde6d027, 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, 0x6058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, 0xed545578, 0x8fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0];
    /**
     * S-Box 3
     *
     * @access private
     * @var    array
     */
    private static $sbox3 = [0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, 0x2cf0b7d9, 0x22b8b51, 0x96d5ac3a, 0x17da67d, 0xd1cf3ed6, 0x7c7d2d28, 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, 0x3a16125, 0x564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, 0x3563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x9072166, 0xb39a460a, 0x6445c0dd, 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, 0x34d2466a, 0x115af84, 0xe1b00428, 0x95983a1d, 0x6b89fb4, 0xce6ea048, 0x6f3f3b82, 0x3520ab82, 0x11a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, 0xd0dadecb, 0xd50ada38, 0x339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, 0xf91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, 0xe60b6f47, 0xfe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x2fb8a8c, 0x1c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6];
    /**
     * P-Array consists of 18 32-bit subkeys
     *
     * @var array
     * @access private
     */
    private static $parray = [0x243f6a88, 0x85a308d3, 0x13198a2e, 0x3707344, 0xa4093822, 0x299f31d0, 0x82efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b];
    /**
     * The BCTX-working Array
     *
     * Holds the expanded key [p] and the key-depended s-boxes [sb]
     *
     * @var array
     * @access private
     */
    private $bctx;
    /**
     * Holds the last used key
     *
     * @var array
     * @access private
     */
    private $kl;
    /**
     * The Key Length (in bytes)
     * {@internal The max value is 256 / 8 = 32, the min value is 128 / 8 = 16.  Exists in conjunction with $Nk
     *    because the encryption / decryption / key schedule creation requires this number and not $key_length.  We could
     *    derive this from $key_length or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
     *    of that, we'll just precompute it once.}
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::setKeyLength()
     * @var int
     * @access private
     */
    protected $key_length = 16;
    /**
     * Default Constructor.
     *
     * @param string $mode
     * @access public
     * @throws \InvalidArgumentException if an invalid / unsupported mode is provided
     */
    public function __construct($mode)
    {
        parent::__construct($mode);
        if ($this->mode == self::MODE_STREAM) {
            throw new \InvalidArgumentException('Block ciphers cannot be ran in stream mode');
        }
    }
    /**
     * Sets the key length.
     *
     * Key lengths can be between 32 and 448 bits.
     *
     * @access public
     * @param int $length
     */
    public function setKeyLength($length)
    {
        if ($length < 32 || $length > 448) {
            throw new \LengthException('Key size of ' . $length . ' bits is not supported by this algorithm. Only keys of sizes between 32 and 448 bits are supported');
        }
        $this->key_length = $length >> 3;
        parent::setKeyLength($length);
    }
    /**
     * Test for engine validity
     *
     * This is mainly just a wrapper to set things up for \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::isValidEngine()
     * @param int $engine
     * @access protected
     * @return bool
     */
    protected function isValidEngineHelper($engine)
    {
        if ($engine == self::ENGINE_OPENSSL) {
            if (version_compare(PHP_VERSION, '5.3.7') < 0 && $this->key_length != 16) {
                return false;
            }
            if ($this->key_length < 16) {
                return false;
            }
            $this->cipher_name_openssl_ecb = 'bf-ecb';
            $this->cipher_name_openssl = 'bf-' . $this->openssl_translate_mode();
        }
        return parent::isValidEngineHelper($engine);
    }
    /**
     * Setup the key (expansion)
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupKey()
     * @access private
     */
    protected function setupKey()
    {
        if (isset($this->kl['key']) && $this->key === $this->kl['key']) {
            // already expanded
            return;
        }
        $this->kl = ['key' => $this->key];
        /* key-expanding p[] and S-Box building sb[] */
        $this->bctx = ['p' => [], 'sb' => [self::$sbox0, self::$sbox1, self::$sbox2, self::$sbox3]];
        // unpack binary string in unsigned chars
        $key = array_values(unpack('C*', $this->key));
        $keyl = count($key);
        for ($j = 0, $i = 0; $i < 18; ++$i) {
            // xor P1 with the first 32-bits of the key, xor P2 with the second 32-bits ...
            for ($data = 0, $k = 0; $k < 4; ++$k) {
                $data = $data << 8 | $key[$j];
                if (++$j >= $keyl) {
                    $j = 0;
                }
            }
            $this->bctx['p'][] = self::$parray[$i] ^ $data;
        }
        // encrypt the zero-string, replace P1 and P2 with the encrypted data,
        // encrypt P3 and P4 with the new P1 and P2, do it with all P-array and subkeys
        $data = "\x00\x00\x00\x00\x00\x00\x00\x00";
        for ($i = 0; $i < 18; $i += 2) {
            list($l, $r) = array_values(unpack('N*', $data = $this->encryptBlock($data)));
            $this->bctx['p'][$i] = $l;
            $this->bctx['p'][$i + 1] = $r;
        }
        for ($i = 0; $i < 4; ++$i) {
            for ($j = 0; $j < 256; $j += 2) {
                list($l, $r) = array_values(unpack('N*', $data = $this->encryptBlock($data)));
                $this->bctx['sb'][$i][$j] = $l;
                $this->bctx['sb'][$i][$j + 1] = $r;
            }
        }
    }
    /**
     * Encrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function encryptBlock($in)
    {
        $p = $this->bctx['p'];
        // extract($this->bctx['sb'], EXTR_PREFIX_ALL, 'sb'); // slower
        $sb_0 = $this->bctx['sb'][0];
        $sb_1 = $this->bctx['sb'][1];
        $sb_2 = $this->bctx['sb'][2];
        $sb_3 = $this->bctx['sb'][3];
        $in = unpack('N*', $in);
        $l = $in[1];
        $r = $in[2];
        for ($i = 0; $i < 16; $i += 2) {
            $l ^= $p[$i];
            $r ^= self::safe_intval((self::safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^ $sb_2[$l >> 8 & 0xff]) + $sb_3[$l & 0xff]);
            $r ^= $p[$i + 1];
            $l ^= self::safe_intval((self::safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^ $sb_2[$r >> 8 & 0xff]) + $sb_3[$r & 0xff]);
        }
        return pack('N*', $r ^ $p[17], $l ^ $p[16]);
    }
    /**
     * Decrypts a block
     *
     * @access private
     * @param string $in
     * @return string
     */
    protected function decryptBlock($in)
    {
        $p = $this->bctx['p'];
        $sb_0 = $this->bctx['sb'][0];
        $sb_1 = $this->bctx['sb'][1];
        $sb_2 = $this->bctx['sb'][2];
        $sb_3 = $this->bctx['sb'][3];
        $in = unpack('N*', $in);
        $l = $in[1];
        $r = $in[2];
        for ($i = 17; $i > 2; $i -= 2) {
            $l ^= $p[$i];
            $r ^= self::safe_intval((self::safe_intval($sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]) ^ $sb_2[$l >> 8 & 0xff]) + $sb_3[$l & 0xff]);
            $r ^= $p[$i - 1];
            $l ^= self::safe_intval((self::safe_intval($sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]) ^ $sb_2[$r >> 8 & 0xff]) + $sb_3[$r & 0xff]);
        }
        return pack('N*', $r ^ $p[0], $l ^ $p[1]);
    }
    /**
     * Setup the performance-optimized function for de/encrypt()
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::_setupInlineCrypt()
     * @access private
     */
    protected function setupInlineCrypt()
    {
        $p = $this->bctx['p'];
        $init_crypt = '
            static $sb_0, $sb_1, $sb_2, $sb_3;
            if (!$sb_0) {
                $sb_0 = $this->bctx["sb"][0];
                $sb_1 = $this->bctx["sb"][1];
                $sb_2 = $this->bctx["sb"][2];
                $sb_3 = $this->bctx["sb"][3];
            }
        ';
        $safeint = self::safe_intval_inline();
        // Generating encrypt code:
        $encrypt_block = '
            $in = unpack("N*", $in);
            $l = $in[1];
            $r = $in[2];
        ';
        for ($i = 0; $i < 16; $i += 2) {
            $encrypt_block .= '
                $l^= ' . $p[$i] . ';
                $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
                      $sb_2[$l >>  8 & 0xff]) +
                      $sb_3[$l       & 0xff]') . ';

                $r^= ' . $p[$i + 1] . ';
                $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . '  ^
                      $sb_2[$r >>  8 & 0xff]) +
                      $sb_3[$r       & 0xff]') . ';
            ';
        }
        $encrypt_block .= '
            $in = pack("N*",
                $r ^ ' . $p[17] . ',
                $l ^ ' . $p[16] . '
            );
        ';
        // Generating decrypt code:
        $decrypt_block = '
            $in = unpack("N*", $in);
            $l = $in[1];
            $r = $in[2];
        ';
        for ($i = 17; $i > 2; $i -= 2) {
            $decrypt_block .= '
                $l^= ' . $p[$i] . ';
                $r^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$l >> 24 & 0xff] + $sb_1[$l >> 16 & 0xff]') . ' ^
                      $sb_2[$l >>  8 & 0xff]) +
                      $sb_3[$l       & 0xff]') . ';

                $r^= ' . $p[$i - 1] . ';
                $l^= ' . sprintf($safeint, '(' . sprintf($safeint, '$sb_0[$r >> 24 & 0xff] + $sb_1[$r >> 16 & 0xff]') . ' ^
                      $sb_2[$r >>  8 & 0xff]) +
                      $sb_3[$r       & 0xff]') . ';
            ';
        }
        $decrypt_block .= '
            $in = pack("N*",
                $r ^ ' . $p[0] . ',
                $l ^ ' . $p[1] . '
            );
        ';
        $this->inline_crypt = $this->createInlineCryptFunction(['init_crypt' => $init_crypt, 'init_encrypt' => '', 'init_decrypt' => '', 'encrypt_block' => $encrypt_block, 'decrypt_block' => $decrypt_block]);
    }
}<?php

/**
 * Random Number Generator
 *
 * PHP version 5
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    echo bin2hex(\phpseclib3\Crypt\Random::string(8));
 * ?>
 * </code>
 *
 * @category  Crypt
 * @package   Random
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

/**
 * Pure-PHP Random Number Generator
 *
 * @package Random
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Random
{
    /**
    * Generate a random string.
    *
    * Although microoptimizations are generally discouraged as they impair readability this function is ripe with
    microoptimizations because this function has the potential of being called a huge number of times.
    eg. for RSA key generation.
    *
    * @param int $length
    * @throws \RuntimeException if a symmetric cipher is needed but not loaded
    * @return string
    */
    public static function string($length)
    {
        if (!$length) {
            return '';
        }
        try {
            return \random_bytes($length);
        } catch (\Exception $e) {
            // random_compat will throw an Exception, which in PHP 5 does not implement Throwable
        } catch (\Throwable $e) {
            // If a sufficient source of randomness is unavailable, random_bytes() will throw an
            // object that implements the Throwable interface (Exception, TypeError, Error).
            // We don't actually need to do anything here. The string() method should just continue
            // as normal. Note, however, that if we don't have a sufficient source of randomness for
            // random_bytes(), most of the other calls here will fail too, so we'll end up using
            // the PHP implementation.
        }
        // at this point we have no choice but to use a pure-PHP CSPRNG
        // cascade entropy across multiple PHP instances by fixing the session and collecting all
        // environmental variables, including the previous session data and the current session
        // data.
        //
        // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively)
        // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but
        // PHP isn't low level to be able to use those as sources and on a web server there's not likely
        // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use
        // however, a ton of people visiting the website. obviously you don't want to base your seeding
        // solely on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled
        // by the user and (2) this isn't just looking at the data sent by the current user - it's based
        // on the data sent by all users. one user requests the page and a hash of their info is saved.
        // another user visits the page and the serialization of their data is utilized along with the
        // server environment stuff and a hash of the previous http request data (which itself utilizes
        // a hash of the session data before that). certainly an attacker should be assumed to have
        // full control over his own http requests. he, however, is not going to have control over
        // everyone's http requests.
        static $crypto = false, $v;
        if ($crypto === false) {
            // save old session data
            $old_session_id = \Phabel\Target\Php80\Polyfill::session_id();
            $old_use_cookies = ini_get('session.use_cookies');
            $old_session_cache_limiter = \Phabel\Target\Php80\Polyfill::session_cache_limiter();
            $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false;
            if ($old_session_id != '') {
                session_write_close();
            }
            \Phabel\Target\Php80\Polyfill::session_id(1);
            ini_set('session.use_cookies', 0);
            \Phabel\Target\Php80\Polyfill::session_cache_limiter('');
            session_start();
            $v = (isset($_SERVER) ? self::safe_serialize($_SERVER) : '') . (isset($_POST) ? self::safe_serialize($_POST) : '') . (isset($_GET) ? self::safe_serialize($_GET) : '') . (isset($_COOKIE) ? self::safe_serialize($_COOKIE) : '') . self::safe_serialize($GLOBALS) . self::safe_serialize($_SESSION) . self::safe_serialize($_OLD_SESSION);
            $v = $seed = $_SESSION['seed'] = sha1($v, true);
            if (!isset($_SESSION['count'])) {
                $_SESSION['count'] = 0;
            }
            $_SESSION['count']++;
            session_write_close();
            // restore old session data
            if ($old_session_id != '') {
                \Phabel\Target\Php80\Polyfill::session_id($old_session_id);
                session_start();
                ini_set('session.use_cookies', $old_use_cookies);
                \Phabel\Target\Php80\Polyfill::session_cache_limiter($old_session_cache_limiter);
            } else {
                if ($_OLD_SESSION !== false) {
                    $_SESSION = $_OLD_SESSION;
                    unset($_OLD_SESSION);
                } else {
                    unset($_SESSION);
                }
            }
            // in SSH2 a shared secret and an exchange hash are generated through the key exchange process.
            // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C.
            // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the
            // original hash and the current hash. we'll be emulating that. for more info see the following URL:
            //
            // http://tools.ietf.org/html/rfc4253#section-7.2
            //
            // see the is_string($crypto) part for an example of how to expand the keys
            $key = sha1($seed . 'A', true);
            $iv = sha1($seed . 'C', true);
            // ciphers are used as per the nist.gov link below. also, see this link:
            //
            // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives
            switch (true) {
                case class_exists('\\phpseclib3\\Crypt\\AES'):
                    $crypto = new AES('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\Twofish'):
                    $crypto = new Twofish('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\Blowfish'):
                    $crypto = new Blowfish('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\TripleDES'):
                    $crypto = new TripleDES('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\DES'):
                    $crypto = new DES('ctr');
                    break;
                case class_exists('\\phpseclib3\\Crypt\\RC4'):
                    $crypto = new RC4();
                    break;
                default:
                    throw new \RuntimeException(__CLASS__ . ' requires at least one symmetric cipher be loaded');
            }
            $crypto->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $crypto->getKeyLength() >> 3));
            $crypto->setIV(\Phabel\Target\Php80\Polyfill::substr($iv, 0, $crypto->getBlockLength() >> 3));
            $crypto->enableContinuousBuffer();
        }
        //return $crypto->encrypt(str_repeat("\0", $length));
        // the following is based off of ANSI X9.31:
        //
        // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf
        //
        // OpenSSL uses that same standard for it's random numbers:
        //
        // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c
        // (do a search for "ANS X9.31 A.2.4")
        $result = '';
        while (strlen($result) < $length) {
            $i = $crypto->encrypt(microtime());
            // strlen(microtime()) == 21
            $r = $crypto->encrypt($i ^ $v);
            // strlen($v) == 20
            $v = $crypto->encrypt($r ^ $i);
            // strlen($r) == 20
            $result .= $r;
        }
        return \Phabel\Target\Php80\Polyfill::substr($result, 0, $length);
    }
    /**
     * Safely serialize variables
     *
     * If a class has a private __sleep() it'll emit a warning
     * @return mixed
     * @param mixed $arr
     */
    private static function safe_serialize(&$arr)
    {
        if (is_object($arr)) {
            return '';
        }
        if (!is_array($arr)) {
            return serialize($arr);
        }
        // prevent circular array recursion
        if (isset($arr['__phpseclib_marker'])) {
            return '';
        }
        $safearr = [];
        $arr['__phpseclib_marker'] = true;
        foreach (array_keys($arr) as $key) {
            // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage
            if ($key !== '__phpseclib_marker') {
                $safearr[$key] = self::safe_serialize($arr[$key]);
            }
        }
        unset($arr['__phpseclib_marker']);
        return serialize($safearr);
    }
}<?php

/**
 * Pure-PHP implementation of Salsa20.
 *
 * PHP version 5
 *
 * @category  Crypt
 * @package   Salsa20
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2019 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Crypt;

use phpseclib3\Crypt\Common\StreamCipher;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Exception\BadDecryptionException;
use phpseclib3\Common\Functions\Strings;
/**
 * Pure-PHP implementation of Salsa20.
 *
 * @package Salsa20
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Salsa20 extends StreamCipher
{
    /**
     * Part 1 of the state
     *
     * @var string|false
     */
    protected $p1 = false;
    /**
     * Part 2 of the state
     *
     * @var string|false
     */
    protected $p2 = false;
    /**
     * Key Length (in bytes)
     *
     * @var int
     */
    protected $key_length = 32;
    // = 256 bits
    /**
     * @access private
     * @see \phpseclib3\Crypt\Salsa20::crypt()
     */
    const ENCRYPT = 0;
    /**
     * @access private
     * @see \phpseclib3\Crypt\Salsa20::crypt()
     */
    const DECRYPT = 1;
    /**
     * Encryption buffer for continuous mode
     *
     * @var array
     */
    protected $enbuffer;
    /**
     * Decryption buffer for continuous mode
     *
     * @var array
     */
    protected $debuffer;
    /**
     * Counter
     *
     * @var int
     */
    protected $counter = 0;
    /**
     * Using Generated Poly1305 Key
     *
     * @var boolean
     */
    protected $usingGeneratedPoly1305Key = false;
    /**
     * Salsa20 uses a nonce
     *
     * @return bool
     */
    public function usesNonce()
    {
        return true;
    }
    /**
     * Sets the key.
     *
     * @param string $key
     * @throws \LengthException if the key length isn't supported
     */
    public function setKey($key)
    {
        switch (strlen($key)) {
            case 16:
            case 32:
                break;
            default:
                throw new \LengthException('Key of size ' . strlen($key) . ' not supported by this algorithm. Only keys of sizes 16 or 32 are supported');
        }
        parent::setKey($key);
    }
    /**
     * Sets the nonce.
     *
     * @param string $nonce
     */
    public function setNonce($nonce)
    {
        if (strlen($nonce) != 8) {
            throw new \LengthException('Nonce of size ' . strlen($key) . ' not supported by this algorithm. Only an 64-bit nonce is supported');
        }
        $this->nonce = $nonce;
        $this->changed = true;
        $this->setEngine();
    }
    /**
     * Sets the counter.
     *
     * @param int $counter
     */
    public function setCounter($counter)
    {
        $this->counter = $counter;
        $this->setEngine();
    }
    /**
     * Creates a Poly1305 key using the method discussed in RFC8439
     *
     * See https://tools.ietf.org/html/rfc8439#section-2.6.1
     */
    protected function createPoly1305Key()
    {
        if ($this->nonce === false) {
            throw new InsufficientSetupException('No nonce has been defined');
        }
        if ($this->key === false) {
            throw new InsufficientSetupException('No key has been defined');
        }
        $c = clone $this;
        $c->setCounter(0);
        $c->usePoly1305 = false;
        $block = $c->encrypt(str_repeat("\x00", 256));
        $this->setPoly1305Key(\Phabel\Target\Php80\Polyfill::substr($block, 0, 32));
        if ($this->counter == 0) {
            $this->counter++;
        }
    }
    /**
    * Setup the self::ENGINE_INTERNAL $engine
    *
    * (re)init, if necessary, the internal cipher $engine
    *
    * _setup() will be called each time if $changed === true
    typically this happens when using one or more of following public methods:
    *
    * - setKey()
    *
    * - setNonce()
    *
    * - First run of encrypt() / decrypt() with no init-settings
    *
    * @see self::setKey()
    * @see self::setNonce()
    * @see self::disableContinuousBuffer()
    */
    protected function setup()
    {
        if (!$this->changed) {
            return;
        }
        $this->enbuffer = $this->debuffer = ['ciphertext' => '', 'counter' => $this->counter];
        $this->changed = $this->nonIVChanged = false;
        if ($this->nonce === false) {
            throw new InsufficientSetupException('No nonce has been defined');
        }
        if ($this->key === false) {
            throw new InsufficientSetupException('No key has been defined');
        }
        if ($this->usePoly1305 && !isset($this->poly1305Key)) {
            $this->usingGeneratedPoly1305Key = true;
            $this->createPoly1305Key();
        }
        $key = $this->key;
        if (strlen($key) == 16) {
            $constant = 'expand 16-byte k';
            $key .= $key;
        } else {
            $constant = 'expand 32-byte k';
        }
        $this->p1 = \Phabel\Target\Php80\Polyfill::substr($constant, 0, 4) . \Phabel\Target\Php80\Polyfill::substr($key, 0, 16) . \Phabel\Target\Php80\Polyfill::substr($constant, 4, 4) . $this->nonce . "\x00\x00\x00\x00";
        $this->p2 = \Phabel\Target\Php80\Polyfill::substr($constant, 8, 4) . \Phabel\Target\Php80\Polyfill::substr($key, 16, 16) . \Phabel\Target\Php80\Polyfill::substr($constant, 12, 4);
    }
    /**
     * Setup the key (expansion)
     */
    protected function setupKey()
    {
        // Salsa20 does not utilize this method
    }
    /**
     * Encrypts a message.
     *
     * @see \phpseclib3\Crypt\Common\SymmetricKey::decrypt()
     * @see self::crypt()
     * @param string $plaintext
     * @return string $ciphertext
     */
    public function encrypt($plaintext)
    {
        $ciphertext = $this->crypt($plaintext, self::ENCRYPT);
        if (isset($this->poly1305Key)) {
            $this->newtag = $this->poly1305($ciphertext);
        }
        return $ciphertext;
    }
    /**
    * Decrypts a message.
    *
    * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
    At least if the continuous buffer is disabled.
    *
    * @see \phpseclib3\Crypt\Common\SymmetricKey::encrypt()
    * @see self::crypt()
    * @param string $ciphertext
    * @return string $plaintext
    */
    public function decrypt($ciphertext)
    {
        if (isset($this->poly1305Key)) {
            if ($this->oldtag === false) {
                throw new InsufficientSetupException('Authentication Tag has not been set');
            }
            $newtag = $this->poly1305($ciphertext);
            if ($this->oldtag != \Phabel\Target\Php80\Polyfill::substr($newtag, 0, strlen($this->oldtag))) {
                $this->oldtag = false;
                throw new BadDecryptionException('Derived authentication tag and supplied authentication tag do not match');
            }
            $this->oldtag = false;
        }
        return $this->crypt($ciphertext, self::DECRYPT);
    }
    /**
     * Encrypts a block
     *
     * @param string $in
     */
    protected function encryptBlock($in)
    {
        // Salsa20 does not utilize this method
    }
    /**
     * Decrypts a block
     *
     * @param string $in
     */
    protected function decryptBlock($in)
    {
        // Salsa20 does not utilize this method
    }
    /**
     * Encrypts or decrypts a message.
     *
     * @see self::encrypt()
     * @see self::decrypt()
     * @param string $text
     * @param int $mode
     * @return string $text
     */
    private function crypt($text, $mode)
    {
        $this->setup();
        if (!$this->continuousBuffer) {
            if ($this->engine == self::ENGINE_OPENSSL) {
                $iv = pack('V', $this->counter) . $this->p2;
                return openssl_encrypt($text, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA, $iv);
            }
            $i = $this->counter;
            $blocks = str_split($text, 64);
            foreach ($blocks as &$block) {
                $block ^= static::salsa20($this->p1 . pack('V', $i++) . $this->p2);
            }
            return implode('', $blocks);
        }
        if ($mode == self::ENCRYPT) {
            $buffer =& $this->enbuffer;
        } else {
            $buffer =& $this->debuffer;
        }
        if (strlen($buffer['ciphertext'])) {
            $ciphertext = $text ^ Strings::shift($buffer['ciphertext'], strlen($text));
            $text = \Phabel\Target\Php80\Polyfill::substr($text, strlen($ciphertext));
            if (!strlen($text)) {
                return $ciphertext;
            }
        }
        $overflow = strlen($text) % 64;
        // & 0x3F
        if ($overflow) {
            $text2 = Strings::pop($text, $overflow);
            if ($this->engine == self::ENGINE_OPENSSL) {
                $iv = pack('V', $buffer['counter']) . $this->p2;
                // at this point $text should be a multiple of 64
                $buffer['counter'] += (strlen($text) >> 6) + 1;
                // ie. divide by 64
                $encrypted = openssl_encrypt($text . str_repeat("\x00", 64), $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA, $iv);
                $temp = Strings::pop($encrypted, 64);
            } else {
                $blocks = str_split($text, 64);
                if (strlen($text)) {
                    foreach ($blocks as &$block) {
                        $block ^= static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2);
                    }
                }
                $encrypted = implode('', $blocks);
                $temp = static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2);
            }
            $ciphertext .= $encrypted . ($text2 ^ $temp);
            $buffer['ciphertext'] = \Phabel\Target\Php80\Polyfill::substr($temp, $overflow);
        } elseif (!strlen($buffer['ciphertext'])) {
            if ($this->engine == self::ENGINE_OPENSSL) {
                $iv = pack('V', $buffer['counter']) . $this->p2;
                $buffer['counter'] += strlen($text) >> 6;
                $ciphertext .= openssl_encrypt($text, $this->cipher_name_openssl, $this->key, OPENSSL_RAW_DATA, $iv);
            } else {
                $blocks = str_split($text, 64);
                foreach ($blocks as &$block) {
                    $block ^= static::salsa20($this->p1 . pack('V', $buffer['counter']++) . $this->p2);
                }
                $ciphertext .= implode('', $blocks);
            }
        }
        return $ciphertext;
    }
    /**
     * Left Rotate
     *
     * @param int $x
     * @param int $n
     * @return int
     */
    protected static function leftRotate($x, $n)
    {
        $r1 = $x << $n;
        if (PHP_INT_SIZE == 8) {
            $r1 &= 0xffffffff;
            $r2 = ($x & 0xffffffff) >> 32 - $n;
        } else {
            $r2 = $x >> 32 - $n;
            $r2 &= (1 << $n) - 1;
        }
        return $r1 | $r2;
    }
    /**
     * The quarterround function
     *
     * @param int $a
     * @param int $b
     * @param int $c
     * @param int $d
     */
    protected static function quarterRound(&$a, &$b, &$c, &$d)
    {
        $b ^= self::leftRotate($a + $d, 7);
        $c ^= self::leftRotate($b + $a, 9);
        $d ^= self::leftRotate($c + $b, 13);
        $a ^= self::leftRotate($d + $c, 18);
    }
    /**
     * The doubleround function
     *
     * @param int $x0 (by reference)
     * @param int $x1 (by reference)
     * @param int $x2 (by reference)
     * @param int $x3 (by reference)
     * @param int $x4 (by reference)
     * @param int $x5 (by reference)
     * @param int $x6 (by reference)
     * @param int $x7 (by reference)
     * @param int $x8 (by reference)
     * @param int $x9 (by reference)
     * @param int $x10 (by reference)
     * @param int $x11 (by reference)
     * @param int $x12 (by reference)
     * @param int $x13 (by reference)
     * @param int $x14 (by reference)
     * @param int $x15 (by reference)
     */
    protected static function doubleRound(&$x0, &$x1, &$x2, &$x3, &$x4, &$x5, &$x6, &$x7, &$x8, &$x9, &$x10, &$x11, &$x12, &$x13, &$x14, &$x15)
    {
        // columnRound
        static::quarterRound($x0, $x4, $x8, $x12);
        static::quarterRound($x5, $x9, $x13, $x1);
        static::quarterRound($x10, $x14, $x2, $x6);
        static::quarterRound($x15, $x3, $x7, $x11);
        // rowRound
        static::quarterRound($x0, $x1, $x2, $x3);
        static::quarterRound($x5, $x6, $x7, $x4);
        static::quarterRound($x10, $x11, $x8, $x9);
        static::quarterRound($x15, $x12, $x13, $x14);
    }
    /**
     * The Salsa20 hash function function
     *
     * @param string $x
     */
    protected static function salsa20($x)
    {
        $z = $x = unpack('V*', $x);
        for ($i = 0; $i < 10; $i++) {
            static::doubleRound(...$z);
        }
        for ($i = 1; $i <= 16; $i++) {
            $x[$i] += $z[$i];
        }
        return pack('V*', ...$x);
    }
    /**
     * Calculates Poly1305 MAC
     *
     * @see self::decrypt()
     * @see self::encrypt()
     * @access private
     * @param string $ciphertext
     * @return string
     */
    protected function poly1305($ciphertext)
    {
        if (!$this->usingGeneratedPoly1305Key) {
            return parent::poly1305($this->aad . $ciphertext);
        } else {
            /*
            sodium_crypto_aead_chacha20poly1305_encrypt does not calculate the poly1305 tag
            the same way sodium_crypto_aead_chacha20poly1305_ietf_encrypt does. you can see
            how the latter encrypts it in Salsa20::encrypt(). here's how the former encrypts
            it:
            
            $this->newtag = $this->poly1305(
                $this->aad .
                pack('V', strlen($this->aad)) . "\0\0\0\0" .
                $ciphertext .
                pack('V', strlen($ciphertext)) . "\0\0\0\0"
            );
            
            phpseclib opts to use the IETF construction, even when the nonce is 64-bits
            instead of 96-bits
            */
            return parent::poly1305(self::nullPad128($this->aad) . self::nullPad128($ciphertext) . pack('V', strlen($this->aad)) . "\x00\x00\x00\x00" . pack('V', strlen($ciphertext)) . "\x00\x00\x00\x00");
        }
    }
}<?php

/**
 * Pure-PHP implementation of SFTP.
 *
 * PHP version 5
 *
 * Supports SFTPv2/3/4/5/6. Defaults to v3.
 *
 * The API for this library is modeled after the API from PHP's {@link http://php.net/book.ftp FTP extension}.
 *
 * Here's a short example of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $sftp = new \phpseclib3\Net\SFTP('www.domain.tld');
 *    if (!$sftp->login('username', 'password')) {
 *        exit('Login Failed');
 *    }
 *
 *    echo $sftp->pwd() . "\r\n";
 *    $sftp->put('filename.ext', 'hello, world!');
 *    print_r($sftp->nlist());
 * ?>
 * </code>
 *
 * @category  Net
 * @package   SFTP
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Net;

use phpseclib3\Exception\FileNotFoundException;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\AsymmetricKey;
use phpseclib3\System\SSH\Agent;
/**
 * Pure-PHP implementations of SFTP.
 *
 * @package SFTP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class SFTP extends SSH2
{
    /**
     * SFTP channel constant
     *
     * \phpseclib3\Net\SSH2::exec() uses 0 and \phpseclib3\Net\SSH2::read() / \phpseclib3\Net\SSH2::write() use 1.
     *
     * @see \phpseclib3\Net\SSH2::send_channel_packet()
     * @see \phpseclib3\Net\SSH2::get_channel_packet()
     * @access private
     */
    const CHANNEL = 0x100;
    /**
     * Reads data from a local file.
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    const SOURCE_LOCAL_FILE = 1;
    /**
     * Reads data from a string.
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    // this value isn't really used anymore but i'm keeping it reserved for historical reasons
    const SOURCE_STRING = 2;
    /**
     * Reads data from callback:
     * function callback($length) returns string to proceed, null for EOF
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    const SOURCE_CALLBACK = 16;
    /**
     * Resumes an upload
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    const RESUME = 4;
    /**
     * Append a local file to an already existing remote file
     *
     * @access public
     * @see \phpseclib3\Net\SFTP::put()
     */
    const RESUME_START = 8;
    /**
     * Packet Types
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $packet_types = [];
    /**
     * Status Codes
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $status_codes = [];
    /**
     * The Request ID
     *
     * The request ID exists in the off chance that a packet is sent out-of-order.  Of course, this library doesn't support
     * concurrent actions, so it's somewhat academic, here.
     *
     * @var boolean
     * @see self::_send_sftp_packet()
     * @access private
     */
    private $use_request_id = false;
    /**
     * The Packet Type
     *
     * The request ID exists in the off chance that a packet is sent out-of-order.  Of course, this library doesn't support
     * concurrent actions, so it's somewhat academic, here.
     *
     * @var int
     * @see self::_get_sftp_packet()
     * @access private
     */
    private $packet_type = -1;
    /**
     * Packet Buffer
     *
     * @var string
     * @see self::_get_sftp_packet()
     * @access private
     */
    private $packet_buffer = '';
    /**
     * Extensions supported by the server
     *
     * @var array
     * @see self::_initChannel()
     * @access private
     */
    private $extensions = [];
    /**
     * Server SFTP version
     *
     * @var int
     * @see self::_initChannel()
     * @access private
     */
    private $version;
    /**
     * Default Server SFTP version
     *
     * @var int
     * @see self::_initChannel()
     * @access private
     */
    private $defaultVersion;
    /**
     * Preferred SFTP version
     *
     * @var int
     * @see self::_initChannel()
     * @access private
     */
    private $preferredVersion = 3;
    /**
     * Current working directory
     *
     * @var string
     * @see self::realpath()
     * @see self::chdir()
     * @access private
     */
    private $pwd = false;
    /**
     * Packet Type Log
     *
     * @see self::getLog()
     * @var array
     * @access private
     */
    private $packet_type_log = [];
    /**
     * Packet Log
     *
     * @see self::getLog()
     * @var array
     * @access private
     */
    private $packet_log = [];
    /**
     * Error information
     *
     * @see self::getSFTPErrors()
     * @see self::getLastSFTPError()
     * @var array
     * @access private
     */
    private $sftp_errors = [];
    /**
     * Stat Cache
     *
     * Rather than always having to open a directory and close it immediately there after to see if a file is a directory
     * we'll cache the results.
     *
     * @see self::_update_stat_cache()
     * @see self::_remove_from_stat_cache()
     * @see self::_query_stat_cache()
     * @var array
     * @access private
     */
    private $stat_cache = [];
    /**
     * Max SFTP Packet Size
     *
     * @see self::__construct()
     * @see self::get()
     * @var array
     * @access private
     */
    private $max_sftp_packet;
    /**
     * Stat Cache Flag
     *
     * @see self::disableStatCache()
     * @see self::enableStatCache()
     * @var bool
     * @access private
     */
    private $use_stat_cache = true;
    /**
     * Sort Options
     *
     * @see self::_comparator()
     * @see self::setListOrder()
     * @var array
     * @access private
     */
    protected $sortOptions = [];
    /**
     * Canonicalization Flag
     *
     * Determines whether or not paths should be canonicalized before being
     * passed on to the remote server.
     *
     * @see self::enablePathCanonicalization()
     * @see self::disablePathCanonicalization()
     * @see self::realpath()
     * @var bool
     * @access private
     */
    private $canonicalize_paths = true;
    /**
     * Request Buffers
     *
     * @see self::_get_sftp_packet()
     * @var array
     * @access private
     */
    private $requestBuffer = [];
    /**
     * Preserve timestamps on file downloads / uploads
     *
     * @see self::get()
     * @see self::put()
     * @var bool
     * @access private
     */
    private $preserveTime = false;
    /**
     * Arbitrary Length Packets Flag
     *
     * Determines whether or not packets of any length should be allowed,
     * in cases where the server chooses the packet length (such as
     * directory listings). By default, packets are only allowed to be
     * 256 * 1024 bytes (SFTP_MAX_MSG_LENGTH from OpenSSH's sftp-common.h)
     *
     * @see self::enableArbitraryLengthPackets()
     * @see self::_get_sftp_packet()
     * @var bool
     * @access private
     */
    private $allow_arbitrary_length_packets = false;
    /**
     * Was the last packet due to the channels being closed or not?
     *
     * @see self::get()
     * @see self::get_sftp_packet()
     * @var bool
     * @access private
     */
    private $channel_close = false;
    /**
     * Has the SFTP channel been partially negotiated?
     *
     * @var bool
     * @access private
     */
    private $partial_init = false;
    /**
     * Default Constructor.
     *
     * Connects to an SFTP server
     *
     * @param string $host
     * @param int $port
     * @param int $timeout
     * @return \phpseclib3\Net\SFTP
     * @access public
     */
    public function __construct($host, $port = 22, $timeout = 10)
    {
        parent::__construct($host, $port, $timeout);
        $this->max_sftp_packet = 1 << 15;
        $this->packet_types = [1 => 'NET_SFTP_INIT', 2 => 'NET_SFTP_VERSION', 3 => 'NET_SFTP_OPEN', 4 => 'NET_SFTP_CLOSE', 5 => 'NET_SFTP_READ', 6 => 'NET_SFTP_WRITE', 7 => 'NET_SFTP_LSTAT', 9 => 'NET_SFTP_SETSTAT', 10 => 'NET_SFTP_FSETSTAT', 11 => 'NET_SFTP_OPENDIR', 12 => 'NET_SFTP_READDIR', 13 => 'NET_SFTP_REMOVE', 14 => 'NET_SFTP_MKDIR', 15 => 'NET_SFTP_RMDIR', 16 => 'NET_SFTP_REALPATH', 17 => 'NET_SFTP_STAT', 18 => 'NET_SFTP_RENAME', 19 => 'NET_SFTP_READLINK', 20 => 'NET_SFTP_SYMLINK', 21 => 'NET_SFTP_LINK', 101 => 'NET_SFTP_STATUS', 102 => 'NET_SFTP_HANDLE', 103 => 'NET_SFTP_DATA', 104 => 'NET_SFTP_NAME', 105 => 'NET_SFTP_ATTRS', 200 => 'NET_SFTP_EXTENDED'];
        $this->status_codes = [0 => 'NET_SFTP_STATUS_OK', 1 => 'NET_SFTP_STATUS_EOF', 2 => 'NET_SFTP_STATUS_NO_SUCH_FILE', 3 => 'NET_SFTP_STATUS_PERMISSION_DENIED', 4 => 'NET_SFTP_STATUS_FAILURE', 5 => 'NET_SFTP_STATUS_BAD_MESSAGE', 6 => 'NET_SFTP_STATUS_NO_CONNECTION', 7 => 'NET_SFTP_STATUS_CONNECTION_LOST', 8 => 'NET_SFTP_STATUS_OP_UNSUPPORTED', 9 => 'NET_SFTP_STATUS_INVALID_HANDLE', 10 => 'NET_SFTP_STATUS_NO_SUCH_PATH', 11 => 'NET_SFTP_STATUS_FILE_ALREADY_EXISTS', 12 => 'NET_SFTP_STATUS_WRITE_PROTECT', 13 => 'NET_SFTP_STATUS_NO_MEDIA', 14 => 'NET_SFTP_STATUS_NO_SPACE_ON_FILESYSTEM', 15 => 'NET_SFTP_STATUS_QUOTA_EXCEEDED', 16 => 'NET_SFTP_STATUS_UNKNOWN_PRINCIPAL', 17 => 'NET_SFTP_STATUS_LOCK_CONFLICT', 18 => 'NET_SFTP_STATUS_DIR_NOT_EMPTY', 19 => 'NET_SFTP_STATUS_NOT_A_DIRECTORY', 20 => 'NET_SFTP_STATUS_INVALID_FILENAME', 21 => 'NET_SFTP_STATUS_LINK_LOOP', 22 => 'NET_SFTP_STATUS_CANNOT_DELETE', 23 => 'NET_SFTP_STATUS_INVALID_PARAMETER', 24 => 'NET_SFTP_STATUS_FILE_IS_A_DIRECTORY', 25 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_CONFLICT', 26 => 'NET_SFTP_STATUS_BYTE_RANGE_LOCK_REFUSED', 27 => 'NET_SFTP_STATUS_DELETE_PENDING', 28 => 'NET_SFTP_STATUS_FILE_CORRUPT', 29 => 'NET_SFTP_STATUS_OWNER_INVALID', 30 => 'NET_SFTP_STATUS_GROUP_INVALID', 31 => 'NET_SFTP_STATUS_NO_MATCHING_BYTE_RANGE_LOCK'];
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
        // the order, in this case, matters quite a lot - see \phpseclib3\Net\SFTP::_parseAttributes() to understand why
        $this->attributes = [
            0x1 => 'NET_SFTP_ATTR_SIZE',
            0x2 => 'NET_SFTP_ATTR_UIDGID',
            // defined in SFTPv3, removed in SFTPv4+
            0x80 => 'NET_SFTP_ATTR_OWNERGROUP',
            // defined in SFTPv4+
            0x4 => 'NET_SFTP_ATTR_PERMISSIONS',
            0x8 => 'NET_SFTP_ATTR_ACCESSTIME',
            0x10 => 'NET_SFTP_ATTR_CREATETIME',
            // SFTPv4+
            0x20 => 'NET_SFTP_ATTR_MODIFYTIME',
            0x40 => 'NET_SFTP_ATTR_ACL',
            0x100 => 'NET_SFTP_ATTR_SUBSECOND_TIMES',
            0x200 => 'NET_SFTP_ATTR_BITS',
            // SFTPv5+
            0x400 => 'NET_SFTP_ATTR_ALLOCATION_SIZE',
            // SFTPv6+
            0x800 => 'NET_SFTP_ATTR_TEXT_HINT',
            0x1000 => 'NET_SFTP_ATTR_MIME_TYPE',
            0x2000 => 'NET_SFTP_ATTR_LINK_COUNT',
            0x4000 => 'NET_SFTP_ATTR_UNTRANSLATED_NAME',
            0x8000 => 'NET_SFTP_ATTR_CTIME',
            // 0x80000000 will yield a floating point on 32-bit systems and converting floating points to integers
            // yields inconsistent behavior depending on how php is compiled.  so we left shift -1 (which, in
            // two's compliment, consists of all 1 bits) by 31.  on 64-bit systems this'll yield 0xFFFFFFFF80000000.
            // that's not a problem, however, and 'anded' and a 32-bit number, as all the leading 1 bits are ignored.
            -1 << 31 & 0xffffffff => 'NET_SFTP_ATTR_EXTENDED',
        ];
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
        // the flag definitions change somewhat in SFTPv5+.  if SFTPv5+ support is added to this library, maybe name
        // the array for that $this->open5_flags and similarly alter the constant names.
        $this->open_flags = [0x1 => 'NET_SFTP_OPEN_READ', 0x2 => 'NET_SFTP_OPEN_WRITE', 0x4 => 'NET_SFTP_OPEN_APPEND', 0x8 => 'NET_SFTP_OPEN_CREATE', 0x10 => 'NET_SFTP_OPEN_TRUNCATE', 0x20 => 'NET_SFTP_OPEN_EXCL', 0x40 => 'NET_SFTP_OPEN_TEXT'];
        // SFTPv5+ changed the flags up:
        // https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-8.1.1.3
        $this->open_flags5 = [
            // when SSH_FXF_ACCESS_DISPOSITION is a 3 bit field that controls how the file is opened
            0x0 => 'NET_SFTP_OPEN_CREATE_NEW',
            0x1 => 'NET_SFTP_OPEN_CREATE_TRUNCATE',
            0x2 => 'NET_SFTP_OPEN_OPEN_EXISTING',
            0x3 => 'NET_SFTP_OPEN_OPEN_OR_CREATE',
            0x4 => 'NET_SFTP_OPEN_TRUNCATE_EXISTING',
            // the rest of the flags are not supported
            0x8 => 'NET_SFTP_OPEN_APPEND_DATA',
            // "the offset field of SS_FXP_WRITE requests is ignored"
            0x10 => 'NET_SFTP_OPEN_APPEND_DATA_ATOMIC',
            0x20 => 'NET_SFTP_OPEN_TEXT_MODE',
            0x40 => 'NET_SFTP_OPEN_BLOCK_READ',
            0x80 => 'NET_SFTP_OPEN_BLOCK_WRITE',
            0x100 => 'NET_SFTP_OPEN_BLOCK_DELETE',
            0x200 => 'NET_SFTP_OPEN_BLOCK_ADVISORY',
            0x400 => 'NET_SFTP_OPEN_NOFOLLOW',
            0x800 => 'NET_SFTP_OPEN_DELETE_ON_CLOSE',
            0x1000 => 'NET_SFTP_OPEN_ACCESS_AUDIT_ALARM_INFO',
            0x2000 => 'NET_SFTP_OPEN_ACCESS_BACKUP',
            0x4000 => 'NET_SFTP_OPEN_BACKUP_STREAM',
            0x8000 => 'NET_SFTP_OPEN_OVERRIDE_OWNER',
        ];
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2
        // see \phpseclib3\Net\SFTP::_parseLongname() for an explanation
        $this->file_types = [
            1 => 'NET_SFTP_TYPE_REGULAR',
            2 => 'NET_SFTP_TYPE_DIRECTORY',
            3 => 'NET_SFTP_TYPE_SYMLINK',
            4 => 'NET_SFTP_TYPE_SPECIAL',
            5 => 'NET_SFTP_TYPE_UNKNOWN',
            // the following types were first defined for use in SFTPv5+
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
            6 => 'NET_SFTP_TYPE_SOCKET',
            7 => 'NET_SFTP_TYPE_CHAR_DEVICE',
            8 => 'NET_SFTP_TYPE_BLOCK_DEVICE',
            9 => 'NET_SFTP_TYPE_FIFO',
        ];
        $this->define_array($this->packet_types, $this->status_codes, $this->attributes, $this->open_flags, $this->open_flags5, $this->file_types);
        if (!defined('NET_SFTP_QUEUE_SIZE')) {
            define('NET_SFTP_QUEUE_SIZE', 32);
        }
        if (!defined('NET_SFTP_UPLOAD_QUEUE_SIZE')) {
            define('NET_SFTP_UPLOAD_QUEUE_SIZE', 1024);
        }
    }
    /**
     * Check a few things before SFTP functions are called
     *
     * @return bool
     * @access public
     */
    private function precheck()
    {
        if (!($this->bitmap & SSH2::MASK_LOGIN)) {
            return false;
        }
        if ($this->pwd === false) {
            return $this->init_sftp_connection();
        }
        return true;
    }
    /**
     * Partially initialize an SFTP connection
     *
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    private function partial_init_sftp_connection()
    {
        $this->window_size_server_to_client[self::CHANNEL] = $this->window_size;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL, $this->window_size, 0x4000);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_OPEN;
        $response = $this->get_channel_packet(self::CHANNEL, true);
        if ($response === true && $this->isTimeout()) {
            return false;
        }
        $packet = Strings::packSSH2('CNsbs', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], 'subsystem', true, 'sftp');
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
        $response = $this->get_channel_packet(self::CHANNEL, true);
        if ($response === false) {
            // from PuTTY's psftp.exe
            $command = 'test -x /usr/lib/sftp-server && exec /usr/lib/sftp-server
test -x /usr/local/lib/sftp-server && exec /usr/local/lib/sftp-server
exec sftp-server';
            // we don't do $this->exec($command, false) because exec() operates on a different channel and plus the SSH_MSG_CHANNEL_OPEN that exec() does
            // is redundant
            $packet = Strings::packSSH2('CNsCs', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL], 'exec', 1, $command);
            $this->send_binary_packet($packet);
            $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_REQUEST;
            $response = $this->get_channel_packet(self::CHANNEL, true);
            if ($response === false) {
                return false;
            }
        } else {
            if ($response === true && $this->isTimeout()) {
                return false;
            }
        }
        $this->channel_status[self::CHANNEL] = NET_SSH2_MSG_CHANNEL_DATA;
        $this->send_sftp_packet(NET_SFTP_INIT, "\x00\x00\x00\x03");
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_VERSION) {
            throw new \UnexpectedValueException('Expected NET_SFTP_VERSION. Got packet type: ' . $this->packet_type);
        }
        $this->use_request_id = true;
        list($this->defaultVersion) = Strings::unpackSSH2('N', $response);
        while (!empty($response)) {
            list($key, $value) = Strings::unpackSSH2('ss', $response);
            $this->extensions[$key] = $value;
        }
        $this->partial_init = true;
        return true;
    }
    /**
     * (Re)initializes the SFTP channel
     *
     * @return bool
     * @access private
     */
    private function init_sftp_connection()
    {
        if (!$this->partial_init && !$this->partial_init_sftp_connection()) {
            return false;
        }
        /*
         A Note on SFTPv4/5/6 support:
         <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.1> states the following:
        
         "If the client wishes to interoperate with servers that support noncontiguous version
          numbers it SHOULD send '3'"
        
         Given that the server only sends its version number after the client has already done so, the above
         seems to be suggesting that v3 should be the default version.  This makes sense given that v3 is the
         most popular.
        
         <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.5> states the following;
        
         "If the server did not send the "versions" extension, or the version-from-list was not included, the
          server MAY send a status response describing the failure, but MUST then close the channel without
          processing any further requests."
        
         So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
         a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4?  If it only implements
         v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
         in draft-ietf-secsh-filexfer-13 would be quite impossible.  As such, what \phpseclib3\Net\SFTP would do is close the
         channel and reopen it with a new and updated SSH_FXP_INIT packet.
        */
        $this->version = $this->defaultVersion;
        if (isset($this->extensions['versions']) && (!$this->preferredVersion || $this->preferredVersion != $this->version)) {
            $versions = explode(',', $this->extensions['versions']);
            $supported = [6, 5, 4];
            if ($this->preferredVersion) {
                $supported = array_diff($supported, [$this->preferredVersion]);
                array_unshift($supported, $this->preferredVersion);
            }
            foreach ($supported as $ver) {
                if (in_array($ver, $versions)) {
                    if ($ver === $this->version) {
                        break;
                    }
                    $this->version = (int) $ver;
                    $packet = Strings::packSSH2('ss', 'version-select', "{$ver}");
                    $this->send_sftp_packet(NET_SFTP_EXTENDED, $packet);
                    $response = $this->get_sftp_packet();
                    if ($this->packet_type != NET_SFTP_STATUS) {
                        throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
                    }
                    list($status) = Strings::unpackSSH2('N', $response);
                    if ($status != NET_SFTP_STATUS_OK) {
                        $this->logError($response, $status);
                        throw new \UnexpectedValueException('Expected NET_SFTP_STATUS_OK.  Got ' . $status);
                    }
                    break;
                }
            }
        }
        /*
         SFTPv4+ defines a 'newline' extension.  SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com',
         however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's
         not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for
         one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
         'newline@vandyke.com' would.
        */
        /*
        if (isset($this->extensions['newline@vandyke.com'])) {
            $this->extensions['newline'] = $this->extensions['newline@vandyke.com'];
            unset($this->extensions['newline@vandyke.com']);
        }
        */
        if ($this->version < 2 || $this->version > 6) {
            return false;
        }
        $this->pwd = true;
        $this->pwd = $this->realpath('.');
        $this->update_stat_cache($this->pwd, []);
        return true;
    }
    /**
     * Disable the stat cache
     *
     * @access public
     */
    public function disableStatCache()
    {
        $this->use_stat_cache = false;
    }
    /**
     * Enable the stat cache
     *
     * @access public
     */
    public function enableStatCache()
    {
        $this->use_stat_cache = true;
    }
    /**
     * Clear the stat cache
     *
     * @access public
     */
    public function clearStatCache()
    {
        $this->stat_cache = [];
    }
    /**
     * Enable path canonicalization
     *
     * @access public
     */
    public function enablePathCanonicalization()
    {
        $this->canonicalize_paths = true;
    }
    /**
     * Enable path canonicalization
     *
     * @access public
     */
    public function disablePathCanonicalization()
    {
        $this->canonicalize_paths = false;
    }
    /**
     * Enable arbitrary length packets
     *
     * @access public
     */
    public function enableArbitraryLengthPackets()
    {
        $this->allow_arbitrary_length_packets = true;
    }
    /**
     * Disable arbitrary length packets
     *
     * @access public
     */
    public function disableArbitraryLengthPackets()
    {
        $this->allow_arbitrary_length_packets = false;
    }
    /**
     * Returns the current directory name
     *
     * @return mixed
     * @access public
     */
    public function pwd()
    {
        if (!$this->precheck()) {
            return false;
        }
        return $this->pwd;
    }
    /**
     * Logs errors
     *
     * @param string $response
     * @param int $status
     * @access private
     */
    private function logError($response, $status = -1)
    {
        if ($status == -1) {
            list($status) = Strings::unpackSSH2('N', $response);
        }
        $error = $this->status_codes[$status];
        if ($this->version > 2) {
            list($message) = Strings::unpackSSH2('s', $response);
            $this->sftp_errors[] = "{$error}: {$message}";
        } else {
            $this->sftp_errors[] = $error;
        }
    }
    /**
    * Canonicalize the Server-Side Path Name
    *
    * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it.  Returns
    the absolute (canonicalized) path.
    *
    * If canonicalize_paths has been disabled using disablePathCanonicalization(), $path is returned as-is.
    *
    * @see self::chdir()
    * @see self::disablePathCanonicalization()
    * @param string $path
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @return mixed
    * @access public
    */
    public function realpath($path)
    {
        if ($this->precheck() === false) {
            return false;
        }
        if (!$this->canonicalize_paths) {
            return $path;
        }
        if ($this->pwd === true) {
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
            $this->send_sftp_packet(NET_SFTP_REALPATH, Strings::packSSH2('s', $path));
            $response = $this->get_sftp_packet();
            switch ($this->packet_type) {
                case NET_SFTP_NAME:
                    // although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following
                    // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
                    // at is the first part and that part is defined the same in SFTP versions 3 through 6.
                    list(, $filename) = Strings::unpackSSH2('Ns', $response);
                    return $filename;
                case NET_SFTP_STATUS:
                    $this->logError($response);
                    return false;
                default:
                    throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
            }
        }
        if (!strlen($path) || $path[0] != '/') {
            $path = $this->pwd . '/' . $path;
        }
        $path = explode('/', $path);
        $new = [];
        foreach ($path as $dir) {
            if (!strlen($dir)) {
                continue;
            }
            switch ($dir) {
                case '..':
                    array_pop($new);
                case '.':
                    break;
                default:
                    $new[] = $dir;
            }
        }
        return '/' . implode('/', $new);
    }
    /**
     * Changes the current directory
     *
     * @param string $dir
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    public function chdir($dir)
    {
        if (!$this->precheck()) {
            return false;
        }
        // assume current dir if $dir is empty
        if ($dir === '') {
            $dir = './';
            // suffix a slash if needed
        } elseif ($dir[strlen($dir) - 1] != '/') {
            $dir .= '/';
        }
        $dir = $this->realpath($dir);
        // confirm that $dir is, in fact, a valid directory
        if ($this->use_stat_cache && is_array($this->query_stat_cache($dir))) {
            $this->pwd = $dir;
            return true;
        }
        // we could do a stat on the alleged $dir to see if it's a directory but that doesn't tell us
        // the currently logged in user has the appropriate permissions or not. maybe you could see if
        // the file's uid / gid match the currently logged in user's uid / gid but how there's no easy
        // way to get those with SFTP
        $this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir));
        // see \phpseclib3\Net\SFTP::nlist() for a more thorough explanation of the following
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                $handle = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUSGot packet type: ' . $this->packet_type);
        }
        if (!$this->close_handle($handle)) {
            return false;
        }
        $this->update_stat_cache($dir, []);
        $this->pwd = $dir;
        return true;
    }
    /**
     * Returns a list of files in the given directory
     *
     * @param string $dir
     * @param bool $recursive
     * @return mixed
     * @access public
     */
    public function nlist($dir = '.', $recursive = false)
    {
        return $this->nlist_helper($dir, $recursive, '');
    }
    /**
     * Helper method for nlist
     *
     * @param string $dir
     * @param bool $recursive
     * @param string $relativeDir
     * @return mixed
     * @access private
     */
    private function nlist_helper($dir, $recursive, $relativeDir)
    {
        $files = $this->readlist($dir, false);
        if (!$recursive || $files === false) {
            return $files;
        }
        $result = [];
        foreach ($files as $value) {
            if ($value == '.' || $value == '..') {
                $result[] = $relativeDir . $value;
                continue;
            }
            if (is_array($this->query_stat_cache($this->realpath($dir . '/' . $value)))) {
                $temp = $this->nlist_helper($dir . '/' . $value, true, $relativeDir . $value . '/');
                $temp = is_array($temp) ? $temp : [];
                $result = array_merge($result, $temp);
            } else {
                $result[] = $relativeDir . $value;
            }
        }
        return $result;
    }
    /**
     * Returns a detailed list of files in the given directory
     *
     * @param string $dir
     * @param bool $recursive
     * @return mixed
     * @access public
     */
    public function rawlist($dir = '.', $recursive = false)
    {
        $files = $this->readlist($dir, true);
        if (!$recursive || $files === false) {
            return $files;
        }
        static $depth = 0;
        foreach ($files as $key => $value) {
            if ($depth != 0 && $key == '..') {
                unset($files[$key]);
                continue;
            }
            $is_directory = false;
            if ($key != '.' && $key != '..') {
                if ($this->use_stat_cache) {
                    $is_directory = is_array($this->query_stat_cache($this->realpath($dir . '/' . $key)));
                } else {
                    $stat = $this->lstat($dir . '/' . $key);
                    $is_directory = $stat && $stat['type'] === NET_SFTP_TYPE_DIRECTORY;
                }
            }
            if ($is_directory) {
                $depth++;
                $files[$key] = $this->rawlist($dir . '/' . $key, true);
                $depth--;
            } else {
                $files[$key] = (object) $value;
            }
        }
        return $files;
    }
    /**
     * Reads a list, be it detailed or not, of files in the given directory
     *
     * @param string $dir
     * @param bool $raw
     * @return mixed
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @access private
     */
    private function readlist($dir, $raw = true)
    {
        if (!$this->precheck()) {
            return false;
        }
        $dir = $this->realpath($dir . '/');
        if ($dir === false) {
            return false;
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
        $this->send_sftp_packet(NET_SFTP_OPENDIR, Strings::packSSH2('s', $dir));
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2
                // since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that
                // represent the length of the string and leave it at that
                $handle = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        $this->update_stat_cache($dir, []);
        $contents = [];
        while (true) {
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
            // why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
            // SSH_MSG_CHANNEL_DATA messages is not known to me.
            $this->send_sftp_packet(NET_SFTP_READDIR, Strings::packSSH2('s', $handle));
            $response = $this->get_sftp_packet();
            switch ($this->packet_type) {
                case NET_SFTP_NAME:
                    list($count) = Strings::unpackSSH2('N', $response);
                    for ($i = 0; $i < $count; $i++) {
                        list($shortname) = Strings::unpackSSH2('s', $response);
                        // SFTPv4 "removed the long filename from the names structure-- it can now be
                        //         built from information available in the attrs structure."
                        if ($this->version < 4) {
                            list($longname) = Strings::unpackSSH2('s', $response);
                        }
                        $attributes = $this->parseAttributes($response);
                        if (!isset($attributes['type']) && $this->version < 4) {
                            $fileType = $this->parseLongname($longname);
                            if ($fileType) {
                                $attributes['type'] = $fileType;
                            }
                        }
                        $contents[$shortname] = $attributes + ['filename' => $shortname];
                        if (isset($attributes['type']) && $attributes['type'] == NET_SFTP_TYPE_DIRECTORY && ($shortname != '.' && $shortname != '..')) {
                            $this->update_stat_cache($dir . '/' . $shortname, []);
                        } else {
                            if ($shortname == '..') {
                                $temp = $this->realpath($dir . '/..') . '/.';
                            } else {
                                $temp = $dir . '/' . $shortname;
                            }
                            $this->update_stat_cache($temp, (object) ['lstat' => $attributes]);
                        }
                        // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
                        // final SSH_FXP_STATUS packet should tell us that, already.
                    }
                    break;
                case NET_SFTP_STATUS:
                    list($status) = Strings::unpackSSH2('N', $response);
                    if ($status != NET_SFTP_STATUS_EOF) {
                        $this->logError($response, $status);
                        return false;
                    }
                    break 2;
                default:
                    throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
            }
        }
        if (!$this->close_handle($handle)) {
            return false;
        }
        if (count($this->sortOptions)) {
            uasort($contents, [&$this, 'comparator']);
        }
        return $raw ? $contents : array_map('strval', array_keys($contents));
    }
    /**
     * Compares two rawlist entries using parameters set by setListOrder()
     *
     * Intended for use with uasort()
     *
     * @param array $a
     * @param array $b
     * @return int
     * @access private
     */
    private function comparator($a, $b)
    {
        switch (true) {
            case $a['filename'] === '.' || $b['filename'] === '.':
                if ($a['filename'] === $b['filename']) {
                    return 0;
                }
                return $a['filename'] === '.' ? -1 : 1;
            case $a['filename'] === '..' || $b['filename'] === '..':
                if ($a['filename'] === $b['filename']) {
                    return 0;
                }
                return $a['filename'] === '..' ? -1 : 1;
            case isset($a['type']) && $a['type'] === NET_SFTP_TYPE_DIRECTORY:
                if (!isset($b['type'])) {
                    return 1;
                }
                if ($b['type'] !== $a['type']) {
                    return -1;
                }
                break;
            case isset($b['type']) && $b['type'] === NET_SFTP_TYPE_DIRECTORY:
                return 1;
        }
        foreach ($this->sortOptions as $sort => $order) {
            if (!isset($a[$sort]) || !isset($b[$sort])) {
                if (isset($a[$sort])) {
                    return -1;
                }
                if (isset($b[$sort])) {
                    return 1;
                }
                return 0;
            }
            switch ($sort) {
                case 'filename':
                    $result = strcasecmp($a['filename'], $b['filename']);
                    if ($result) {
                        return $order === SORT_DESC ? -$result : $result;
                    }
                    break;
                case 'mode':
                    $a[$sort] &= 07777;
                    $b[$sort] &= 07777;
                default:
                    if ($a[$sort] === $b[$sort]) {
                        break;
                    }
                    return $order === SORT_ASC ? $a[$sort] - $b[$sort] : $b[$sort] - $a[$sort];
            }
        }
    }
    /**
    * Defines how nlist() and rawlist() will be sorted - if at all.
    *
    * If sorting is enabled directories and files will be sorted independently with
    directories appearing before files in the resultant array that is returned.
    *
    * Any parameter returned by stat is a valid sort parameter for this function.
    Filename comparisons are case insensitive.
    *
    * Examples:
    *
    * $sftp->setListOrder('filename', SORT_ASC);
    $sftp->setListOrder('size', SORT_DESC, 'filename', SORT_ASC);
    $sftp->setListOrder(true);
    Separates directories from files but doesn't do any sorting beyond that
    $sftp->setListOrder();
    Don't do any sort of sorting
    *
    * @param string[] ...$args
    * @access public
    */
    public function setListOrder(...$args)
    {
        $this->sortOptions = [];
        if (empty($args)) {
            return;
        }
        $len = count($args) & 0x7ffffffe;
        for ($i = 0; $i < $len; $i += 2) {
            $this->sortOptions[$args[$i]] = $args[$i + 1];
        }
        if (!count($this->sortOptions)) {
            $this->sortOptions = ['bogus' => true];
        }
    }
    /**
     * Save files / directories to cache
     *
     * @param string $path
     * @param mixed $value
     * @access private
     */
    private function update_stat_cache($path, $value)
    {
        if ($this->use_stat_cache === false) {
            return;
        }
        // preg_replace('#^/|/(?=/)|/$#', '', $dir) == str_replace('//', '/', trim($path, '/'))
        $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
        $temp =& $this->stat_cache;
        $max = count($dirs) - 1;
        foreach ($dirs as $i => $dir) {
            // if $temp is an object that means one of two things.
            //  1. a file was deleted and changed to a directory behind phpseclib's back
            //  2. it's a symlink. when lstat is done it's unclear what it's a symlink to
            if (is_object($temp)) {
                $temp = [];
            }
            if (!isset($temp[$dir])) {
                $temp[$dir] = [];
            }
            if ($i === $max) {
                if (is_object($temp[$dir]) && is_object($value)) {
                    if (!isset($value->stat) && isset($temp[$dir]->stat)) {
                        $value->stat = $temp[$dir]->stat;
                    }
                    if (!isset($value->lstat) && isset($temp[$dir]->lstat)) {
                        $value->lstat = $temp[$dir]->lstat;
                    }
                }
                $temp[$dir] = $value;
                break;
            }
            $temp =& $temp[$dir];
        }
    }
    /**
     * Remove files / directories from cache
     *
     * @param string $path
     * @return bool
     * @access private
     */
    private function remove_from_stat_cache($path)
    {
        $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
        $temp =& $this->stat_cache;
        $max = count($dirs) - 1;
        foreach ($dirs as $i => $dir) {
            if (!is_array($temp)) {
                return false;
            }
            if ($i === $max) {
                unset($temp[$dir]);
                return true;
            }
            if (!isset($temp[$dir])) {
                return false;
            }
            $temp =& $temp[$dir];
        }
    }
    /**
     * Checks cache for path
     *
     * Mainly used by file_exists
     *
     * @param string $path
     * @return mixed
     * @access private
     */
    private function query_stat_cache($path)
    {
        $dirs = explode('/', preg_replace('#^/|/(?=/)|/$#', '', $path));
        $temp =& $this->stat_cache;
        foreach ($dirs as $dir) {
            if (!is_array($temp)) {
                return null;
            }
            if (!isset($temp[$dir])) {
                return null;
            }
            $temp =& $temp[$dir];
        }
        return $temp;
    }
    /**
     * Returns general information about a file.
     *
     * Returns an array on success and false otherwise.
     *
     * @param string $filename
     * @return mixed
     * @access public
     */
    public function stat($filename)
    {
        if (!$this->precheck()) {
            return false;
        }
        $filename = $this->realpath($filename);
        if ($filename === false) {
            return false;
        }
        if ($this->use_stat_cache) {
            $result = $this->query_stat_cache($filename);
            if (is_array($result) && isset($result['.']) && isset($result['.']->stat)) {
                return $result['.']->stat;
            }
            if (is_object($result) && isset($result->stat)) {
                return $result->stat;
            }
        }
        $stat = $this->stat_helper($filename, NET_SFTP_STAT);
        if ($stat === false) {
            $this->remove_from_stat_cache($filename);
            return false;
        }
        if (isset($stat['type'])) {
            if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
                $filename .= '/.';
            }
            $this->update_stat_cache($filename, (object) ['stat' => $stat]);
            return $stat;
        }
        $pwd = $this->pwd;
        $stat['type'] = $this->chdir($filename) ? NET_SFTP_TYPE_DIRECTORY : NET_SFTP_TYPE_REGULAR;
        $this->pwd = $pwd;
        if ($stat['type'] == NET_SFTP_TYPE_DIRECTORY) {
            $filename .= '/.';
        }
        $this->update_stat_cache($filename, (object) ['stat' => $stat]);
        return $stat;
    }
    /**
     * Returns general information about a file or symbolic link.
     *
     * Returns an array on success and false otherwise.
     *
     * @param string $filename
     * @return mixed
     * @access public
     */
    public function lstat($filename)
    {
        if (!$this->precheck()) {
            return false;
        }
        $filename = $this->realpath($filename);
        if ($filename === false) {
            return false;
        }
        if ($this->use_stat_cache) {
            $result = $this->query_stat_cache($filename);
            if (is_array($result) && isset($result['.']) && isset($result['.']->lstat)) {
                return $result['.']->lstat;
            }
            if (is_object($result) && isset($result->lstat)) {
                return $result->lstat;
            }
        }
        $lstat = $this->stat_helper($filename, NET_SFTP_LSTAT);
        if ($lstat === false) {
            $this->remove_from_stat_cache($filename);
            return false;
        }
        if (isset($lstat['type'])) {
            if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
                $filename .= '/.';
            }
            $this->update_stat_cache($filename, (object) ['lstat' => $lstat]);
            return $lstat;
        }
        $stat = $this->stat_helper($filename, NET_SFTP_STAT);
        if ($lstat != $stat) {
            $lstat = array_merge($lstat, ['type' => NET_SFTP_TYPE_SYMLINK]);
            $this->update_stat_cache($filename, (object) ['lstat' => $lstat]);
            return $stat;
        }
        $pwd = $this->pwd;
        $lstat['type'] = $this->chdir($filename) ? NET_SFTP_TYPE_DIRECTORY : NET_SFTP_TYPE_REGULAR;
        $this->pwd = $pwd;
        if ($lstat['type'] == NET_SFTP_TYPE_DIRECTORY) {
            $filename .= '/.';
        }
        $this->update_stat_cache($filename, (object) ['lstat' => $lstat]);
        return $lstat;
    }
    /**
    * Returns general information about a file or symbolic link
    *
    * Determines information without calling \phpseclib3\Net\SFTP::realpath().
    The second parameter can be either NET_SFTP_STAT or NET_SFTP_LSTAT.
    *
    * @param string $filename
    * @param int $type
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @return mixed
    * @access private
    */
    private function stat_helper($filename, $type)
    {
        // SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
        $packet = Strings::packSSH2('s', $filename);
        $this->send_sftp_packet($type, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_ATTRS:
                return $this->parseAttributes($response);
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
        }
        throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
    }
    /**
     * Truncates a file to a given length
     *
     * @param string $filename
     * @param int $new_size
     * @return bool
     * @access public
     */
    public function truncate($filename, $new_size)
    {
        $attr = Strings::packSSH2('NQ', NET_SFTP_ATTR_SIZE, $new_size);
        return $this->setstat($filename, $attr, false);
    }
    /**
     * Sets access and modification time of file.
     *
     * If the file does not exist, it will be created.
     *
     * @param string $filename
     * @param int $time
     * @param int $atime
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    public function touch($filename, $time = null, $atime = null)
    {
        if (!$this->precheck()) {
            return false;
        }
        $filename = $this->realpath($filename);
        if ($filename === false) {
            return false;
        }
        if (!isset($time)) {
            $time = time();
        }
        if (!isset($atime)) {
            $atime = $time;
        }
        $attr = $this->version < 4 ? pack('N3', NET_SFTP_ATTR_ACCESSTIME, $atime, $time) : Strings::packSSH2('NQ2', NET_SFTP_ATTR_ACCESSTIME | NET_SFTP_ATTR_MODIFYTIME, $atime, $time);
        $packet = Strings::packSSH2('s', $filename);
        $packet .= $this->version >= 5 ? pack('N2', 0, NET_SFTP_OPEN_OPEN_EXISTING) : pack('N', NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE | NET_SFTP_OPEN_EXCL);
        $packet .= $attr;
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                return $this->close_handle(\Phabel\Target\Php80\Polyfill::substr($response, 4));
            case NET_SFTP_STATUS:
                $this->logError($response);
                break;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        return $this->setstat($filename, $attr, false);
    }
    /**
    * Changes file or directory owner
    *
    * $uid should be an int for SFTPv3 and a string for SFTPv4+. Ideally the string
    would be of the form "user@dns_domain" but it does not need to be.
    `$sftp->getSupportedVersions()['version']` will return the specific version
    that's being used.
    *
    * Returns true on success or false on error.
    *
    * @param string $filename
    * @param (int | string) $uid
    * @param bool $recursive
    * @return bool
    * @access public
    */
    public function chown($filename, $uid, $recursive = false)
    {
        /*
          quoting <https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.5>,
        
          "To avoid a representation that is tied to a particular underlying
           implementation at the client or server, the use of UTF-8 strings has
           been chosen.  The string should be of the form "user@dns_domain".
           This will allow for a client and server that do not use the same
           local representation the ability to translate to a common syntax that
           can be interpreted by both.  In the case where there is no
           translation available to the client or server, the attribute value
           must be constructed without the "@"."
        
          phpseclib _could_ auto append the dns_domain to $uid BUT what if it shouldn't
          have one? phpseclib would have no way of knowing so rather than guess phpseclib
          will just use whatever value the user provided
        */
        $attr = $this->version < 4 ? pack('N3', NET_SFTP_ATTR_UIDGID, $uid, -1) : Strings::packSSH2('Nss', NET_SFTP_ATTR_OWNERGROUP, $uid, '');
        return $this->setstat($filename, $attr, $recursive);
    }
    /**
    * Changes file or directory group
    *
    * $gid should be an int for SFTPv3 and a string for SFTPv4+. Ideally the string
    would be of the form "user@dns_domain" but it does not need to be.
    `$sftp->getSupportedVersions()['version']` will return the specific version
    that's being used.
    *
    * Returns true on success or false on error.
    *
    * @param string $filename
    * @param (int | string) $gid
    * @param bool $recursive
    * @return bool
    * @access public
    */
    public function chgrp($filename, $gid, $recursive = false)
    {
        $attr = $this->version < 4 ? pack('N3', NET_SFTP_ATTR_UIDGID, $gid, -1) : Strings::packSSH2('Nss', NET_SFTP_ATTR_OWNERGROUP, '', $gid);
        return $this->setstat($filename, $attr, $recursive);
    }
    /**
    * Set permissions on a file.
    *
    * Returns the new file permissions on success or false on error.
    If $recursive is true than this just returns true or false.
    *
    * @param int $mode
    * @param string $filename
    * @param bool $recursive
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @return mixed
    * @access public
    */
    public function chmod($mode, $filename, $recursive = false)
    {
        if (is_string($mode) && is_int($filename)) {
            $temp = $mode;
            $mode = $filename;
            $filename = $temp;
        }
        $attr = pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
        if (!$this->setstat($filename, $attr, $recursive)) {
            return false;
        }
        if ($recursive) {
            return true;
        }
        $filename = $this->realpath($filename);
        // rather than return what the permissions *should* be, we'll return what they actually are.  this will also
        // tell us if the file actually exists.
        // incidentally, SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
        $packet = pack('Na*', strlen($filename), $filename);
        $this->send_sftp_packet(NET_SFTP_STAT, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_ATTRS:
                $attrs = $this->parseAttributes($response);
                return $attrs['mode'];
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
        }
        throw new \UnexpectedValueException('Expected NET_SFTP_ATTRS or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
    }
    /**
     * Sets information about a file
     *
     * @param string $filename
     * @param string $attr
     * @param bool $recursive
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access private
     */
    private function setstat($filename, $attr, $recursive)
    {
        if (!$this->precheck()) {
            return false;
        }
        $filename = $this->realpath($filename);
        if ($filename === false) {
            return false;
        }
        $this->remove_from_stat_cache($filename);
        if ($recursive) {
            $i = 0;
            $result = $this->setstat_recursive($filename, $attr, $i);
            $this->read_put_responses($i);
            return $result;
        }
        $packet = Strings::packSSH2('s', $filename);
        $packet .= $this->version >= 4 ? pack('a*Ca*', \Phabel\Target\Php80\Polyfill::substr($attr, 0, 4), NET_SFTP_TYPE_UNKNOWN, \Phabel\Target\Php80\Polyfill::substr($attr, 4)) : $attr;
        $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet);
        /*
         "Because some systems must use separate system calls to set various attributes, it is possible that a failure
          response will be returned, but yet some of the attributes may be have been successfully modified.  If possible,
          servers SHOULD avoid this situation; however, clients MUST be aware that this is possible."
        
          -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6
        */
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        return true;
    }
    /**
     * Recursively sets information on directories on the SFTP server
     *
     * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
     *
     * @param string $path
     * @param string $attr
     * @param int $i
     * @return bool
     * @access private
     */
    private function setstat_recursive($path, $attr, &$i)
    {
        if (!$this->read_put_responses($i)) {
            return false;
        }
        $i = 0;
        $entries = $this->readlist($path, true);
        if ($entries === false) {
            return $this->setstat($path, $attr, false);
        }
        // normally $entries would have at least . and .. but it might not if the directories
        // permissions didn't allow reading
        if (empty($entries)) {
            return false;
        }
        unset($entries['.'], $entries['..']);
        foreach ($entries as $filename => $props) {
            if (!isset($props['type'])) {
                return false;
            }
            $temp = $path . '/' . $filename;
            if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) {
                if (!$this->setstat_recursive($temp, $attr, $i)) {
                    return false;
                }
            } else {
                $packet = Strings::packSSH2('s', $temp);
                $packet .= $this->version >= 4 ? pack('Ca*', NET_SFTP_TYPE_UNKNOWN, $attr) : $attr;
                $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet);
                $i++;
                if ($i >= NET_SFTP_QUEUE_SIZE) {
                    if (!$this->read_put_responses($i)) {
                        return false;
                    }
                    $i = 0;
                }
            }
        }
        $packet = Strings::packSSH2('s', $path);
        $packet .= $this->version >= 4 ? pack('Ca*', NET_SFTP_TYPE_UNKNOWN, $attr) : $atr;
        $this->send_sftp_packet(NET_SFTP_SETSTAT, $packet);
        $i++;
        if ($i >= NET_SFTP_QUEUE_SIZE) {
            if (!$this->read_put_responses($i)) {
                return false;
            }
            $i = 0;
        }
        return true;
    }
    /**
     * Return the target of a symbolic link
     *
     * @param string $link
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return mixed
     * @access public
     */
    public function readlink($link)
    {
        if (!$this->precheck()) {
            return false;
        }
        $link = $this->realpath($link);
        $this->send_sftp_packet(NET_SFTP_READLINK, Strings::packSSH2('s', $link));
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_NAME:
                break;
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_NAME or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($count) = Strings::unpackSSH2('N', $response);
        // the file isn't a symlink
        if (!$count) {
            return false;
        }
        list($filename) = Strings::unpackSSH2('s', $response);
        return $filename;
    }
    /**
     * Create a symlink
     *
     * symlink() creates a symbolic link to the existing target with the specified name link.
     *
     * @param string $target
     * @param string $link
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    public function symlink($target, $link)
    {
        if (!$this->precheck()) {
            return false;
        }
        //$target = $this->realpath($target);
        $link = $this->realpath($link);
        /* quoting https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-09#section-12.1 :
        
                   Changed the SYMLINK packet to be LINK and give it the ability to
                   create hard links.  Also change it's packet number because many
                   implementation implemented SYMLINK with the arguments reversed.
                   Hopefully the new argument names make it clear which way is which.
                */
        if ($this->version == 6) {
            $type = NET_SFTP_LINK;
            $packet = Strings::packSSH2('ssC', $link, $target, 1);
        } else {
            $type = NET_SFTP_SYMLINK;
            /* quoting http://bxr.su/OpenBSD/usr.bin/ssh/PROTOCOL#347 :
            
                           3.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
            
                           When OpenSSH's sftp-server was implemented, the order of the arguments
                           to the SSH_FXP_SYMLINK method was inadvertently reversed. Unfortunately,
                           the reversal was not noticed until the server was widely deployed. Since
                           fixing this to follow the specification would cause incompatibility, the
                           current order was retained. For correct operation, clients should send
                           SSH_FXP_SYMLINK as follows:
            
                               uint32      id
                               string      targetpath
                               string      linkpath */
            $packet = \Phabel\Target\Php80\Polyfill::substr($this->server_identifier, 0, 15) == 'SSH-2.0-OpenSSH' ? Strings::packSSH2('ss', $target, $link) : Strings::packSSH2('ss', $link, $target);
        }
        $this->send_sftp_packet($type, $packet);
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        return true;
    }
    /**
     * Creates a directory.
     *
     * @param string $dir
     * @param int $mode
     * @param bool $recursive
     * @return bool
     * @access public
     */
    public function mkdir($dir, $mode = -1, $recursive = false)
    {
        if (!$this->precheck()) {
            return false;
        }
        $dir = $this->realpath($dir);
        if ($recursive) {
            $dirs = explode('/', preg_replace('#/(?=/)|/$#', '', $dir));
            if (empty($dirs[0])) {
                array_shift($dirs);
                $dirs[0] = '/' . $dirs[0];
            }
            for ($i = 0; $i < count($dirs); $i++) {
                $temp = array_slice($dirs, 0, $i + 1);
                $temp = implode('/', $temp);
                $result = $this->mkdir_helper($temp, $mode);
            }
            return $result;
        }
        return $this->mkdir_helper($dir, $mode);
    }
    /**
     * Helper function for directory creation
     *
     * @param string $dir
     * @param int $mode
     * @return bool
     * @access private
     */
    private function mkdir_helper($dir, $mode)
    {
        // send SSH_FXP_MKDIR without any attributes (that's what the \0\0\0\0 is doing)
        $this->send_sftp_packet(NET_SFTP_MKDIR, Strings::packSSH2('s', $dir) . "\x00\x00\x00\x00");
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        if ($mode !== -1) {
            $this->chmod($mode, $dir);
        }
        return true;
    }
    /**
     * Removes a directory.
     *
     * @param string $dir
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @return bool
     * @access public
     */
    public function rmdir($dir)
    {
        if (!$this->precheck()) {
            return false;
        }
        $dir = $this->realpath($dir);
        if ($dir === false) {
            return false;
        }
        $this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $dir));
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
            $this->logError($response, $status);
            return false;
        }
        $this->remove_from_stat_cache($dir);
        // the following will do a soft delete, which would be useful if you deleted a file
        // and then tried to do a stat on the deleted file. the above, in contrast, does
        // a hard delete
        //$this->update_stat_cache($dir, false);
        return true;
    }
    /**
    * Uploads a file to the SFTP server.
    *
    * By default, \phpseclib3\Net\SFTP::put() does not read from the local filesystem.  $data is dumped directly into $remote_file.
    So, for example, if you set $data to 'filename.ext' and then do \phpseclib3\Net\SFTP::get(), you will get a file, twelve bytes
    long, containing 'filename.ext' as its contents.
    *
    * Setting $mode to self::SOURCE_LOCAL_FILE will change the above behavior.  With self::SOURCE_LOCAL_FILE, $remote_file will
    contain as many bytes as filename.ext does on your local filesystem.  If your filename.ext is 1MB then that is how
    large $remote_file will be, as well.
    *
    * Setting $mode to self::SOURCE_CALLBACK will use $data as callback function, which gets only one parameter -- number
    of bytes to return, and returns a string if there is some data or null if there is no more data
    *
    * If $data is a resource then it'll be used as a resource instead.
    *
    * Currently, only binary mode is supported.  As such, if the line endings need to be adjusted, you will need to take
    care of that, yourself.
    *
    * $mode can take an additional two parameters - self::RESUME and self::RESUME_START. These are bitwise AND'd with
    $mode. So if you want to resume upload of a 300mb file on the local file system you'd set $mode to the following:
    *
    * self::SOURCE_LOCAL_FILE | self::RESUME
    *
    * If you wanted to simply append the full contents of a local file to the full contents of a remote file you'd replace
    self::RESUME with self::RESUME_START.
    *
    * If $mode & (self::RESUME | self::RESUME_START) then self::RESUME_START will be assumed.
    *
    * $start and $local_start give you more fine grained control over this process and take precident over self::RESUME
    when they're non-negative. ie. $start could let you write at the end of a file (like self::RESUME) or in the middle
    of one. $local_start could let you start your reading from the end of a file (like self::RESUME_START) or in the
    middle of one.
    *
    * Setting $local_start to > 0 or $mode | self::RESUME_START doesn't do anything unless $mode | self::SOURCE_LOCAL_FILE.
    *
    * {@internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - \phpseclib3\Net\SFTP::setMode().}
    *
    * @param string $remote_file
    * @param (string | resource) $data
    * @param int $mode
    * @param int $start
    * @param int $local_start
    * @param (callable | null) $progressCallback
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @throws \BadFunctionCallException if you're uploading via a callback and the callback function is invalid
    * @throws \phpseclib3\Exception\FileNotFoundException if you're uploading via a file and the file doesn't exist
    * @return bool
    * @access public
    */
    public function put($remote_file, $data, $mode = self::SOURCE_STRING, $start = -1, $local_start = -1, $progressCallback = null)
    {
        if (!$this->precheck()) {
            return false;
        }
        $remote_file = $this->realpath($remote_file);
        if ($remote_file === false) {
            return false;
        }
        $this->remove_from_stat_cache($remote_file);
        if ($this->version >= 5) {
            $flags = NET_SFTP_OPEN_OPEN_OR_CREATE;
        } else {
            $flags = NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE;
            // according to the SFTP specs, NET_SFTP_OPEN_APPEND should "force all writes to append data at the end of the file."
            // in practice, it doesn't seem to do that.
            //$flags|= ($mode & self::RESUME) ? NET_SFTP_OPEN_APPEND : NET_SFTP_OPEN_TRUNCATE;
        }
        if ($start >= 0) {
            $offset = $start;
        } elseif ($mode & self::RESUME) {
            // if NET_SFTP_OPEN_APPEND worked as it should _size() wouldn't need to be called
            $size = $this->stat($remote_file)['size'];
            $offset = $size !== false ? $size : 0;
        } else {
            $offset = 0;
            if ($this->version >= 5) {
                $flags = NET_SFTP_OPEN_CREATE_TRUNCATE;
            } else {
                $flags |= NET_SFTP_OPEN_TRUNCATE;
            }
        }
        $this->remove_from_stat_cache($remote_file);
        $packet = Strings::packSSH2('s', $remote_file);
        $packet .= $this->version >= 5 ? pack('N3', 0, $flags, 0) : pack('N2', $flags, 0);
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                $handle = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
        $dataCallback = false;
        switch (true) {
            case $mode & self::SOURCE_CALLBACK:
                if (!is_callable($data)) {
                    throw new \BadFunctionCallException("\$data should be is_callable() if you specify SOURCE_CALLBACK flag");
                }
                $dataCallback = $data;
                // do nothing
                break;
            case is_resource($data):
                $mode = $mode & ~self::SOURCE_LOCAL_FILE;
                $info = stream_get_meta_data($data);
                if ($info['wrapper_type'] == 'PHP' && $info['stream_type'] == 'Input') {
                    $fp = fopen('php://memory', 'w+');
                    stream_copy_to_stream($data, $fp);
                    rewind($fp);
                } else {
                    $fp = $data;
                }
                break;
            case $mode & self::SOURCE_LOCAL_FILE:
                if (!is_file($data)) {
                    throw new FileNotFoundException("{$data} is not a valid file");
                }
                $fp = @fopen($data, 'rb');
                if (!$fp) {
                    return false;
                }
        }
        if (isset($fp)) {
            $stat = fstat($fp);
            $size = !empty($stat) ? $stat['size'] : 0;
            if ($local_start >= 0) {
                fseek($fp, $local_start);
                $size -= $local_start;
            }
        } elseif ($dataCallback) {
            $size = 0;
        } else {
            $size = strlen($data);
        }
        $sent = 0;
        $size = $size < 0 ? ($size & 0x7fffffff) + 0x80000000 : $size;
        $sftp_packet_size = $this->max_sftp_packet;
        // make the SFTP packet be exactly the SFTP packet size by including the bytes in the NET_SFTP_WRITE packets "header"
        $sftp_packet_size -= strlen($handle) + 25;
        $i = $j = 0;
        while ($dataCallback || ($size === 0 || $sent < $size)) {
            if ($dataCallback) {
                $temp = $dataCallback($sftp_packet_size);
                if (is_null($temp)) {
                    break;
                }
            } else {
                $temp = isset($fp) ? fread($fp, $sftp_packet_size) : \Phabel\Target\Php80\Polyfill::substr($data, $sent, $sftp_packet_size);
                if ($temp === false || $temp === '') {
                    break;
                }
            }
            $subtemp = $offset + $sent;
            $packet = pack('Na*N3a*', strlen($handle), $handle, $subtemp / 4294967296, $subtemp, strlen($temp), $temp);
            try {
                $this->send_sftp_packet(NET_SFTP_WRITE, $packet, $j);
            } catch (\Exception $e) {
                if ($mode & self::SOURCE_LOCAL_FILE) {
                    fclose($fp);
                }
                throw $e;
            }
            $sent += strlen($temp);
            if (is_callable($progressCallback)) {
                $progressCallback($sent);
            }
            $i++;
            $j++;
            if ($i == NET_SFTP_UPLOAD_QUEUE_SIZE) {
                if (!$this->read_put_responses($i)) {
                    $i = 0;
                    break;
                }
                $i = 0;
            }
        }
        $result = $this->close_handle($handle);
        if (!$this->read_put_responses($i)) {
            if ($mode & self::SOURCE_LOCAL_FILE) {
                fclose($fp);
            }
            $this->close_handle($handle);
            return false;
        }
        if ($mode & SFTP::SOURCE_LOCAL_FILE) {
            if (isset($fp) && is_resource($fp)) {
                fclose($fp);
            }
            if ($this->preserveTime) {
                $stat = stat($data);
                $attr = $this->version < 4 ? pack('N3', NET_SFTP_ATTR_ACCESSTIME, $stat['atime'], $stat['time']) : Strings::packSSH2('NQ2', NET_SFTP_ATTR_ACCESSTIME | NET_SFTP_ATTR_MODIFYTIME, $stat['atime'], $stat['time']);
                if (!$this->setstat($remote_file, $attr, false)) {
                    throw new \RuntimeException('Error setting file time');
                }
            }
        }
        return $result;
    }
    /**
    * Reads multiple successive SSH_FXP_WRITE responses
    *
    * Sending an SSH_FXP_WRITE packet and immediately reading its response isn't as efficient as blindly sending out $i
    SSH_FXP_WRITEs, in succession, and then reading $i responses.
    *
    * @param int $i
    * @return bool
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @access private
    */
    private function read_put_responses($i)
    {
        while ($i--) {
            $response = $this->get_sftp_packet();
            if ($this->packet_type != NET_SFTP_STATUS) {
                throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
            }
            list($status) = Strings::unpackSSH2('N', $response);
            if ($status != NET_SFTP_STATUS_OK) {
                $this->logError($response, $status);
                break;
            }
        }
        return $i < 0;
    }
    /**
     * Close handle
     *
     * @param string $handle
     * @return bool
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @access private
     */
    private function close_handle($handle)
    {
        $this->send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle));
        // "The client MUST release all resources associated with the handle regardless of the status."
        //  -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        return true;
    }
    /**
    * Downloads a file from the SFTP server.
    *
    * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
    the operation was unsuccessful.  If $local_file is defined, returns true or false depending on the success of the
    operation.
    *
    * $offset and $length can be used to download files in chunks.
    *
    * @param string $remote_file
    * @param (string | bool | resource | callable) $local_file
    * @param int $offset
    * @param int $length
    * @param (callable | null) $progressCallback
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @return mixed
    * @access public
    */
    public function get($remote_file, $local_file = false, $offset = 0, $length = -1, $progressCallback = null)
    {
        if (!$this->precheck()) {
            return false;
        }
        $remote_file = $this->realpath($remote_file);
        if ($remote_file === false) {
            return false;
        }
        $packet = Strings::packSSH2('s', $remote_file);
        $packet .= $this->version >= 5 ? pack('N3', 0, NET_SFTP_OPEN_OPEN_EXISTING, 0) : pack('N2', NET_SFTP_OPEN_READ, 0);
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                $handle = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                break;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                $this->logError($response);
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        if (is_resource($local_file)) {
            $fp = $local_file;
            $stat = fstat($fp);
            $res_offset = $stat['size'];
        } else {
            $res_offset = 0;
            if ($local_file !== false && !is_callable($local_file)) {
                $fp = fopen($local_file, 'wb');
                if (!$fp) {
                    return false;
                }
            } else {
                $content = '';
            }
        }
        $fclose_check = $local_file !== false && !is_callable($local_file) && !is_resource($local_file);
        $start = $offset;
        $read = 0;
        while (true) {
            $i = 0;
            while ($i < NET_SFTP_QUEUE_SIZE && ($length < 0 || $read < $length)) {
                $tempoffset = $start + $read;
                $packet_size = $length > 0 ? min($this->max_sftp_packet, $length - $read) : $this->max_sftp_packet;
                $packet = Strings::packSSH2('sN3', $handle, $tempoffset / 4294967296, $tempoffset, $packet_size);
                try {
                    $this->send_sftp_packet(NET_SFTP_READ, $packet, $i);
                } catch (\Exception $e) {
                    if ($fclose_check) {
                        fclose($fp);
                    }
                    throw $e;
                }
                $packet = null;
                $read += $packet_size;
                $i++;
            }
            if (!$i) {
                break;
            }
            $packets_sent = $i - 1;
            $clear_responses = false;
            while ($i > 0) {
                $i--;
                if ($clear_responses) {
                    $this->get_sftp_packet($packets_sent - $i);
                    continue;
                } else {
                    $response = $this->get_sftp_packet($packets_sent - $i);
                }
                switch ($this->packet_type) {
                    case NET_SFTP_DATA:
                        $temp = \Phabel\Target\Php80\Polyfill::substr($response, 4);
                        $offset += strlen($temp);
                        if ($local_file === false) {
                            $content .= $temp;
                        } elseif (is_callable($local_file)) {
                            $local_file($temp);
                        } else {
                            fputs($fp, $temp);
                        }
                        if (is_callable($progressCallback)) {
                            call_user_func($progressCallback, $offset);
                        }
                        $temp = null;
                        break;
                    case NET_SFTP_STATUS:
                        // could, in theory, return false if !strlen($content) but we'll hold off for the time being
                        $this->logError($response);
                        $clear_responses = true;
                        // don't break out of the loop yet, so we can read the remaining responses
                        break;
                    default:
                        if ($fclose_check) {
                            fclose($fp);
                        }
                        if ($this->channel_close) {
                            $this->partial_init = false;
                            $this->init_sftp_connection();
                            return false;
                        } else {
                            throw new \UnexpectedValueException('Expected NET_SFTP_DATA or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
                        }
                }
                $response = null;
            }
            if ($clear_responses) {
                break;
            }
        }
        if ($length > 0 && $length <= $offset - $start) {
            if ($local_file === false) {
                $content = \Phabel\Target\Php80\Polyfill::substr($content, 0, $length);
            } else {
                ftruncate($fp, $length + $res_offset);
            }
        }
        if ($fclose_check) {
            fclose($fp);
            if ($this->preserveTime) {
                $stat = $this->stat($remote_file);
                touch($local_file, $stat['mtime'], $stat['atime']);
            }
        }
        if (!$this->close_handle($handle)) {
            return false;
        }
        // if $content isn't set that means a file was written to
        return isset($content) ? $content : true;
    }
    /**
     * Deletes a file on the SFTP server.
     *
     * @param string $path
     * @param bool $recursive
     * @return bool
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @access public
     */
    public function delete($path, $recursive = true)
    {
        if (!$this->precheck()) {
            return false;
        }
        if (is_object($path)) {
            // It's an object. Cast it as string before we check anything else.
            $path = (string) $path;
        }
        if (!is_string($path) || $path == '') {
            return false;
        }
        $path = $this->realpath($path);
        if ($path === false) {
            return false;
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
        $this->send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path));
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            if (!$recursive) {
                return false;
            }
            $i = 0;
            $result = $this->delete_recursive($path, $i);
            $this->read_put_responses($i);
            return $result;
        }
        $this->remove_from_stat_cache($path);
        return true;
    }
    /**
     * Recursively deletes directories on the SFTP server
     *
     * Minimizes directory lookups and SSH_FXP_STATUS requests for speed.
     *
     * @param string $path
     * @param int $i
     * @return bool
     * @access private
     */
    private function delete_recursive($path, &$i)
    {
        if (!$this->read_put_responses($i)) {
            return false;
        }
        $i = 0;
        $entries = $this->readlist($path, true);
        // normally $entries would have at least . and .. but it might not if the directories
        // permissions didn't allow reading
        if (empty($entries)) {
            return false;
        }
        unset($entries['.'], $entries['..']);
        foreach ($entries as $filename => $props) {
            if (!isset($props['type'])) {
                return false;
            }
            $temp = $path . '/' . $filename;
            if ($props['type'] == NET_SFTP_TYPE_DIRECTORY) {
                if (!$this->delete_recursive($temp, $i)) {
                    return false;
                }
            } else {
                $this->send_sftp_packet(NET_SFTP_REMOVE, Strings::packSSH2('s', $temp));
                $this->remove_from_stat_cache($temp);
                $i++;
                if ($i >= NET_SFTP_QUEUE_SIZE) {
                    if (!$this->read_put_responses($i)) {
                        return false;
                    }
                    $i = 0;
                }
            }
        }
        $this->send_sftp_packet(NET_SFTP_RMDIR, Strings::packSSH2('s', $path));
        $this->remove_from_stat_cache($path);
        $i++;
        if ($i >= NET_SFTP_QUEUE_SIZE) {
            if (!$this->read_put_responses($i)) {
                return false;
            }
            $i = 0;
        }
        return true;
    }
    /**
     * Checks whether a file or directory exists
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function file_exists($path)
    {
        if ($this->use_stat_cache) {
            if (!$this->precheck()) {
                return false;
            }
            $path = $this->realpath($path);
            $result = $this->query_stat_cache($path);
            if (isset($result)) {
                // return true if $result is an array or if it's an stdClass object
                return $result !== false;
            }
        }
        return $this->stat($path) !== false;
    }
    /**
     * Tells whether the filename is a directory
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_dir($path)
    {
        $result = $this->get_stat_cache_prop($path, 'type');
        if ($result === false) {
            return false;
        }
        return $result === NET_SFTP_TYPE_DIRECTORY;
    }
    /**
     * Tells whether the filename is a regular file
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_file($path)
    {
        $result = $this->get_stat_cache_prop($path, 'type');
        if ($result === false) {
            return false;
        }
        return $result === NET_SFTP_TYPE_REGULAR;
    }
    /**
     * Tells whether the filename is a symbolic link
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_link($path)
    {
        $result = $this->get_lstat_cache_prop($path, 'type');
        if ($result === false) {
            return false;
        }
        return $result === NET_SFTP_TYPE_SYMLINK;
    }
    /**
     * Tells whether a file exists and is readable
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_readable($path)
    {
        if (!$this->precheck()) {
            return false;
        }
        $packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_READ, 0);
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                return true;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                return false;
            default:
                throw new \UnexpectedValueException('Expected NET_SFTP_HANDLE or NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
    }
    /**
     * Tells whether the filename is writable
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_writable($path)
    {
        if (!$this->precheck()) {
            return false;
        }
        $packet = Strings::packSSH2('sNN', $this->realpath($path), NET_SFTP_OPEN_WRITE, 0);
        $this->send_sftp_packet(NET_SFTP_OPEN, $packet);
        $response = $this->get_sftp_packet();
        switch ($this->packet_type) {
            case NET_SFTP_HANDLE:
                return true;
            case NET_SFTP_STATUS:
                // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
                return false;
            default:
                throw new \UnexpectedValueException('Expected SSH_FXP_HANDLE or SSH_FXP_STATUS. Got packet type: ' . $this->packet_type);
        }
    }
    /**
     * Tells whether the filename is writeable
     *
     * Alias of is_writable
     *
     * @param string $path
     * @return bool
     * @access public
     */
    public function is_writeable($path)
    {
        return $this->is_writable($path);
    }
    /**
     * Gets last access time of file
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function fileatime($path)
    {
        return $this->get_stat_cache_prop($path, 'atime');
    }
    /**
     * Gets file modification time
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function filemtime($path)
    {
        return $this->get_stat_cache_prop($path, 'mtime');
    }
    /**
     * Gets file permissions
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function fileperms($path)
    {
        return $this->get_stat_cache_prop($path, 'mode');
    }
    /**
     * Gets file owner
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function fileowner($path)
    {
        return $this->get_stat_cache_prop($path, 'uid');
    }
    /**
     * Gets file group
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function filegroup($path)
    {
        return $this->get_stat_cache_prop($path, 'gid');
    }
    /**
     * Gets file size
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function filesize($path)
    {
        return $this->get_stat_cache_prop($path, 'size');
    }
    /**
     * Gets file type
     *
     * @param string $path
     * @return mixed
     * @access public
     */
    public function filetype($path)
    {
        $type = $this->get_stat_cache_prop($path, 'type');
        if ($type === false) {
            return false;
        }
        switch ($type) {
            case NET_SFTP_TYPE_BLOCK_DEVICE:
                return 'block';
            case NET_SFTP_TYPE_CHAR_DEVICE:
                return 'char';
            case NET_SFTP_TYPE_DIRECTORY:
                return 'dir';
            case NET_SFTP_TYPE_FIFO:
                return 'fifo';
            case NET_SFTP_TYPE_REGULAR:
                return 'file';
            case NET_SFTP_TYPE_SYMLINK:
                return 'link';
            default:
                return false;
        }
    }
    /**
     * Return a stat properity
     *
     * Uses cache if appropriate.
     *
     * @param string $path
     * @param string $prop
     * @return mixed
     * @access private
     */
    private function get_stat_cache_prop($path, $prop)
    {
        return $this->get_xstat_cache_prop($path, $prop, 'stat');
    }
    /**
     * Return an lstat properity
     *
     * Uses cache if appropriate.
     *
     * @param string $path
     * @param string $prop
     * @return mixed
     * @access private
     */
    private function get_lstat_cache_prop($path, $prop)
    {
        return $this->get_xstat_cache_prop($path, $prop, 'lstat');
    }
    /**
     * Return a stat or lstat properity
     *
     * Uses cache if appropriate.
     *
     * @param string $path
     * @param string $prop
     * @param string $type
     * @return mixed
     * @access private
     */
    private function get_xstat_cache_prop($path, $prop, $type)
    {
        if (!$this->precheck()) {
            return false;
        }
        if ($this->use_stat_cache) {
            $path = $this->realpath($path);
            $result = $this->query_stat_cache($path);
            if (is_object($result) && isset($result->{$type})) {
                return $result->{$type}[$prop];
            }
        }
        $result = $this->{$type}($path);
        if ($result === false || !isset($result[$prop])) {
            return false;
        }
        return $result[$prop];
    }
    /**
     * Renames a file or a directory on the SFTP server.
     *
     * If the file already exists this will return false
     *
     * @param string $oldname
     * @param string $newname
     * @return bool
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @access public
     */
    public function rename($oldname, $newname)
    {
        if (!$this->precheck()) {
            return false;
        }
        $oldname = $this->realpath($oldname);
        $newname = $this->realpath($newname);
        if ($oldname === false || $newname === false) {
            return false;
        }
        // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
        $packet = Strings::packSSH2('ss', $oldname, $newname);
        if ($this->version >= 5) {
            /* quoting https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-6.5 ,
            
                           'flags' is 0 or a combination of:
            
                               SSH_FXP_RENAME_OVERWRITE  0x00000001
                               SSH_FXP_RENAME_ATOMIC     0x00000002
                               SSH_FXP_RENAME_NATIVE     0x00000004
            
                           (none of these are currently supported) */
            $packet .= "\x00\x00\x00\x00";
        }
        $this->send_sftp_packet(NET_SFTP_RENAME, $packet);
        $response = $this->get_sftp_packet();
        if ($this->packet_type != NET_SFTP_STATUS) {
            throw new \UnexpectedValueException('Expected NET_SFTP_STATUS. Got packet type: ' . $this->packet_type);
        }
        // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
        list($status) = Strings::unpackSSH2('N', $response);
        if ($status != NET_SFTP_STATUS_OK) {
            $this->logError($response, $status);
            return false;
        }
        // don't move the stat cache entry over since this operation could very well change the
        // atime and mtime attributes
        //$this->update_stat_cache($newname, $this->query_stat_cache($oldname));
        $this->remove_from_stat_cache($oldname);
        $this->remove_from_stat_cache($newname);
        return true;
    }
    /**
     * Parse Time
     *
     * See '7.7.  Times' of draft-ietf-secsh-filexfer-13 for more info.
     *
     * @param string $key
     * @param int $flags
     * @param string $response
     * @return array
     * @access private
     */
    private function parseTime($key, $flags, &$response)
    {
        $attr = [];
        list($attr[$key]) = Strings::unpackSSH2('Q', $response);
        if ($flags & NET_SFTP_ATTR_SUBSECOND_TIMES) {
            list($attr[key . '-nseconds']) = Strings::unpackSSH2('N', $response);
        }
        return $attr;
    }
    /**
     * Parse Attributes
     *
     * See '7.  File Attributes' of draft-ietf-secsh-filexfer-13 for more info.
     *
     * @param string $response
     * @return array
     * @access private
     */
    protected function parseAttributes(&$response)
    {
        if ($this->version >= 4) {
            list($flags, $attr['type']) = Strings::unpackSSH2('NC', $response);
        } else {
            list($flags) = Strings::unpackSSH2('N', $response);
        }
        foreach ($this->attributes as $key => $value) {
            switch ($flags & $key) {
                case NET_SFTP_ATTR_UIDGID:
                    if ($this->version > 3) {
                        continue 2;
                    }
                    break;
                case NET_SFTP_ATTR_CREATETIME:
                case NET_SFTP_ATTR_MODIFYTIME:
                case NET_SFTP_ATTR_ACL:
                case NET_SFTP_ATTR_OWNERGROUP:
                case NET_SFTP_ATTR_SUBSECOND_TIMES:
                    if ($this->version < 4) {
                        continue 2;
                    }
                    break;
                case NET_SFTP_ATTR_BITS:
                    if ($this->version < 5) {
                        continue 2;
                    }
                    break;
                case NET_SFTP_ATTR_ALLOCATION_SIZE:
                case NET_SFTP_ATTR_TEXT_HINT:
                case NET_SFTP_ATTR_MIME_TYPE:
                case NET_SFTP_ATTR_LINK_COUNT:
                case NET_SFTP_ATTR_UNTRANSLATED_NAME:
                case NET_SFTP_ATTR_CTIME:
                    if ($this->version < 6) {
                        continue 2;
                    }
            }
            switch ($flags & $key) {
                case NET_SFTP_ATTR_SIZE:
                    // 0x00000001
                    // The size attribute is defined as an unsigned 64-bit integer.
                    // The following will use floats on 32-bit platforms, if necessary.
                    // As can be seen in the BigInteger class, floats are generally
                    // IEEE 754 binary64 "double precision" on such platforms and
                    // as such can represent integers of at least 2^50 without loss
                    // of precision. Interpreted in filesize, 2^50 bytes = 1024 TiB.
                    list($attr['size']) = Strings::unpackSSH2('Q', $response);
                    break;
                case NET_SFTP_ATTR_UIDGID:
                    // 0x00000002 (SFTPv3 only)
                    list($attr['uid'], $attr['gid']) = Strings::unpackSSH2('NN', $response);
                    break;
                case NET_SFTP_ATTR_PERMISSIONS:
                    // 0x00000004
                    list($attr['mode']) = Strings::unpackSSH2('N', $response);
                    $fileType = $this->parseMode($attr['mode']);
                    if ($this->version < 4 && $fileType !== false) {
                        $attr += ['type' => $fileType];
                    }
                    break;
                case NET_SFTP_ATTR_ACCESSTIME:
                    // 0x00000008
                    if ($this->version >= 4) {
                        $attr += $this->parseTime('atime', $flags, $response);
                        break;
                    }
                    list($attr['atime'], $attr['mtime']) = Strings::unpackSSH2('NN', $response);
                    break;
                case NET_SFTP_ATTR_CREATETIME:
                    // 0x00000010 (SFTPv4+)
                    $attr += $this->parseTime('createtime', $flags, $response);
                    break;
                case NET_SFTP_ATTR_MODIFYTIME:
                    // 0x00000020
                    $attr += $this->parseTime('mtime', $flags, $response);
                    break;
                case NET_SFTP_ATTR_ACL:
                    // 0x00000040
                    // access control list
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-04#section-5.7
                    // currently unsupported
                    list($count) = Strings::unpackSSH2('N', $response);
                    for ($i = 0; $i < $count; $i++) {
                        list($type, $flag, $mask, $who) = Strings::unpackSSH2('N3s', $result);
                    }
                    break;
                case NET_SFTP_ATTR_OWNERGROUP:
                    // 0x00000080
                    list($attr['owner'], $attr['$group']) = Strings::unpackSSH2('ss', $response);
                    break;
                case NET_SFTP_ATTR_SUBSECOND_TIMES:
                    // 0x00000100
                    break;
                case NET_SFTP_ATTR_BITS:
                    // 0x00000200 (SFTPv5+)
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-05#section-5.8
                    // currently unsupported
                    // tells if you file is:
                    // readonly, system, hidden, case inensitive, archive, encrypted, compressed, sparse
                    // append only, immutable, sync
                    list($attrib_bits, $attrib_bits_valid) = Strings::unpackSSH2('N2', $response);
                    // if we were actually gonna implement the above it ought to be
                    // $attr['attrib-bits'] and $attr['attrib-bits-valid']
                    // eg. - instead of _
                    break;
                case NET_SFTP_ATTR_ALLOCATION_SIZE:
                    // 0x00000400 (SFTPv6+)
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.4
                    // represents the number of bytes that the file consumes on the disk. will
                    // usually be larger than the 'size' field
                    list($attr['allocation-size']) = Strings::unpack('Q', $response);
                    break;
                case NET_SFTP_ATTR_TEXT_HINT:
                    // 0x00000800
                    // https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.10
                    // currently unsupported
                    // tells if file is "known text", "guessed text", "known binary", "guessed binary"
                    list($text_hint) = Strings::unpackSSH2('C', $response);
                    // the above should be $attr['text-hint']
                    break;
                case NET_SFTP_ATTR_MIME_TYPE:
                    // 0x00001000
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.11
                    list($attr['mime-type']) = Strings::unpackSSH2('s', $response);
                    break;
                case NET_SFTP_ATTR_LINK_COUNT:
                    // 0x00002000
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.12
                    list($attr['link-count']) = Strings::unpackSS2('N', $response);
                    break;
                case NET_SFTP_ATTR_UNTRANSLATED_NAME:
                    // 0x00004000
                    // see https://datatracker.ietf.org/doc/html/draft-ietf-secsh-filexfer-13#section-7.13
                    list($attr['untranslated-name']) = Strings::unpackSSH2('s', $response);
                    break;
                case NET_SFTP_ATTR_CTIME:
                    // 0x00008000
                    // 'ctime' contains the last time the file attributes were changed.  The
                    // exact meaning of this field depends on the server.
                    $attr += $this->parseTime('ctime', $flags, $response);
                    break;
                case NET_SFTP_ATTR_EXTENDED:
                    // 0x80000000
                    list($count) = Strings::unpackSSH2('N', $response);
                    for ($i = 0; $i < $count; $i++) {
                        list($key, $value) = Strings::unpackSSH2('ss', $response);
                        $attr[$key] = $value;
                    }
            }
        }
        return $attr;
    }
    /**
     * Attempt to identify the file type
     *
     * Quoting the SFTP RFC, "Implementations MUST NOT send bits that are not defined" but they seem to anyway
     *
     * @param int $mode
     * @return int
     * @access private
     */
    private function parseMode($mode)
    {
        // values come from http://lxr.free-electrons.com/source/include/uapi/linux/stat.h#L12
        // see, also, http://linux.die.net/man/2/stat
        switch ($mode & 0170000) {
            // ie. 1111 0000 0000 0000
            case 00:
                // no file type specified - figure out the file type using alternative means
                return false;
            case 040000:
                return NET_SFTP_TYPE_DIRECTORY;
            case 0100000:
                return NET_SFTP_TYPE_REGULAR;
            case 0120000:
                return NET_SFTP_TYPE_SYMLINK;
            // new types introduced in SFTPv5+
            // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-05#section-5.2
            case 010000:
                // named pipe (fifo)
                return NET_SFTP_TYPE_FIFO;
            case 020000:
                // character special
                return NET_SFTP_TYPE_CHAR_DEVICE;
            case 060000:
                // block special
                return NET_SFTP_TYPE_BLOCK_DEVICE;
            case 0140000:
                // socket
                return NET_SFTP_TYPE_SOCKET;
            case 0160000:
                // whiteout
                // "SPECIAL should be used for files that are of
                //  a known type which cannot be expressed in the protocol"
                return NET_SFTP_TYPE_SPECIAL;
            default:
                return NET_SFTP_TYPE_UNKNOWN;
        }
    }
    /**
    * Parse Longname
    *
    * SFTPv3 doesn't provide any easy way of identifying a file type.  You could try to open
    a file as a directory and see if an error is returned or you could try to parse the
    SFTPv3-specific longname field of the SSH_FXP_NAME packet.  That's what this function does.
    The result is returned using the
    {@link http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-5.2 SFTPv4 type constants}.
    *
    * If the longname is in an unrecognized format bool(false) is returned.
    *
    * @param string $longname
    * @return mixed
    * @access private
    */
    private function parseLongname($longname)
    {
        // http://en.wikipedia.org/wiki/Unix_file_types
        // http://en.wikipedia.org/wiki/Filesystem_permissions#Notation_of_traditional_Unix_permissions
        if (preg_match('#^[^/]([r-][w-][xstST-]){3}#', $longname)) {
            switch ($longname[0]) {
                case '-':
                    return NET_SFTP_TYPE_REGULAR;
                case 'd':
                    return NET_SFTP_TYPE_DIRECTORY;
                case 'l':
                    return NET_SFTP_TYPE_SYMLINK;
                default:
                    return NET_SFTP_TYPE_SPECIAL;
            }
        }
        return false;
    }
    /**
     * Sends SFTP Packets
     *
     * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
     *
     * @param int $type
     * @param string $data
     * @param int $request_id
     * @see self::_get_sftp_packet()
     * @see self::send_channel_packet()
     * @return bool
     * @access private
     */
    private function send_sftp_packet($type, $data, $request_id = 1)
    {
        // in SSH2.php the timeout is cumulative per function call. eg. exec() will
        // timeout after 10s. but for SFTP.php it's cumulative per packet
        $this->curTimeout = $this->timeout;
        $packet = $this->use_request_id ? pack('NCNa*', strlen($data) + 5, $type, $request_id, $data) : pack('NCa*', strlen($data) + 1, $type, $data);
        $start = microtime(true);
        $result = $this->send_channel_packet(self::CHANNEL, $packet);
        $stop = microtime(true);
        if (defined('NET_SFTP_LOGGING')) {
            $packet_type = '-> ' . $this->packet_types[$type] . ' (' . round($stop - $start, 4) . 's)';
            if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
                switch (PHP_SAPI) {
                    case 'cli':
                        $start = $stop = "\r\n";
                        break;
                    default:
                        $start = '<pre>';
                        $stop = '</pre>';
                }
                echo $start . $this->format_log([$data], [$packet_type]) . $stop;
                @flush();
                @ob_flush();
            } else {
                $this->packet_type_log[] = $packet_type;
                if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
                    $this->packet_log[] = $data;
                }
            }
        }
        return $result;
    }
    /**
     * Resets a connection for re-use
     *
     * @param int $reason
     * @access private
     */
    protected function reset_connection($reason)
    {
        parent::reset_connection($reason);
        $this->use_request_id = false;
        $this->pwd = false;
        $this->requestBuffer = [];
    }
    /**
    * Receives SFTP Packets
    *
    * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
    *
    * Incidentally, the number of SSH_MSG_CHANNEL_DATA messages has no bearing on the number of SFTP packets present.
    There can be one SSH_MSG_CHANNEL_DATA messages containing two SFTP packets or there can be two SSH_MSG_CHANNEL_DATA
    messages containing one SFTP packet.
    *
    * @see self::_send_sftp_packet()
    * @return string
    * @access private
    */
    private function get_sftp_packet($request_id = null)
    {
        $this->channel_close = false;
        if (isset($request_id) && isset($this->requestBuffer[$request_id])) {
            $this->packet_type = $this->requestBuffer[$request_id]['packet_type'];
            $temp = $this->requestBuffer[$request_id]['packet'];
            unset($this->requestBuffer[$request_id]);
            return $temp;
        }
        // in SSH2.php the timeout is cumulative per function call. eg. exec() will
        // timeout after 10s. but for SFTP.php it's cumulative per packet
        $this->curTimeout = $this->timeout;
        $start = microtime(true);
        // SFTP packet length
        while (strlen($this->packet_buffer) < 4) {
            $temp = $this->get_channel_packet(self::CHANNEL, true);
            if ($temp === true) {
                if ($this->channel_status[self::CHANNEL] === NET_SSH2_MSG_CHANNEL_CLOSE) {
                    $this->channel_close = true;
                }
                $this->packet_type = false;
                $this->packet_buffer = '';
                return false;
            }
            $this->packet_buffer .= $temp;
        }
        if (strlen($this->packet_buffer) < 4) {
            throw new \RuntimeException('Packet is too small');
        }
        extract(unpack('Nlength', Strings::shift($this->packet_buffer, 4)));
        /** @var integer $length */
        $tempLength = $length;
        $tempLength -= strlen($this->packet_buffer);
        // 256 * 1024 is what SFTP_MAX_MSG_LENGTH is set to in OpenSSH's sftp-common.h
        if (!$this->allow_arbitrary_length_packets && !$this->use_request_id && $tempLength > 256 * 1024) {
            throw new \RuntimeException('Invalid Size');
        }
        // SFTP packet type and data payload
        while ($tempLength > 0) {
            $temp = $this->get_channel_packet(self::CHANNEL, true);
            if (is_bool($temp)) {
                $this->packet_type = false;
                $this->packet_buffer = '';
                return false;
            }
            $this->packet_buffer .= $temp;
            $tempLength -= strlen($temp);
        }
        $stop = microtime(true);
        $this->packet_type = ord(Strings::shift($this->packet_buffer));
        if ($this->use_request_id) {
            extract(unpack('Npacket_id', Strings::shift($this->packet_buffer, 4)));
            // remove the request id
            $length -= 5;
            // account for the request id and the packet type
        } else {
            $length -= 1;
            // account for the packet type
        }
        $packet = Strings::shift($this->packet_buffer, $length);
        if (defined('NET_SFTP_LOGGING')) {
            $packet_type = '<- ' . $this->packet_types[$this->packet_type] . ' (' . round($stop - $start, 4) . 's)';
            if (NET_SFTP_LOGGING == self::LOG_REALTIME) {
                switch (PHP_SAPI) {
                    case 'cli':
                        $start = $stop = "\r\n";
                        break;
                    default:
                        $start = '<pre>';
                        $stop = '</pre>';
                }
                echo $start . $this->format_log([$packet], [$packet_type]) . $stop;
                @flush();
                @ob_flush();
            } else {
                $this->packet_type_log[] = $packet_type;
                if (NET_SFTP_LOGGING == self::LOG_COMPLEX) {
                    $this->packet_log[] = $packet;
                }
            }
        }
        if (isset($request_id) && $this->use_request_id && $packet_id != $request_id) {
            $this->requestBuffer[$packet_id] = ['packet_type' => $this->packet_type, 'packet' => $packet];
            return $this->get_sftp_packet($request_id);
        }
        return $packet;
    }
    /**
     * Returns a log of the packets that have been sent and received.
     *
     * Returns a string if NET_SFTP_LOGGING == self::LOG_COMPLEX, an array if NET_SFTP_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SFTP_LOGGING')
     *
     * @access public
     * @return (array | string)
     */
    public function getSFTPLog()
    {
        if (!defined('NET_SFTP_LOGGING')) {
            return false;
        }
        switch (NET_SFTP_LOGGING) {
            case self::LOG_COMPLEX:
                return $this->format_log($this->packet_log, $this->packet_type_log);
                break;
            //case self::LOG_SIMPLE:
            default:
                return $this->packet_type_log;
        }
    }
    /**
     * Returns all errors
     *
     * @return array
     * @access public
     */
    public function getSFTPErrors()
    {
        return $this->sftp_errors;
    }
    /**
     * Returns the last error
     *
     * @return string
     * @access public
     */
    public function getLastSFTPError()
    {
        return count($this->sftp_errors) ? $this->sftp_errors[count($this->sftp_errors) - 1] : '';
    }
    /**
     * Get supported SFTP versions
     *
     * @return array
     * @access public
     */
    public function getSupportedVersions()
    {
        if (!($this->bitmap & SSH2::MASK_LOGIN)) {
            return false;
        }
        if (!$this->partial_init) {
            $this->partial_init_sftp_connection();
        }
        $temp = ['version' => $this->defaultVersion];
        if (isset($this->extensions['versions'])) {
            $temp['extensions'] = $this->extensions['versions'];
        }
        return $temp;
    }
    /**
     * Get supported SFTP versions
     *
     * @return array
     * @access public
     */
    public function getNegotiatedVersion()
    {
        if (!$this->precheck()) {
            return false;
        }
        return $this->version;
    }
    /**
    * Set preferred version
    *
    * If you're preferred version isn't supported then the highest supported
    version of SFTP will be utilized. Set to null or false or int(0) to
    unset the preferred version
    *
    * @param int $version
    * @access public
    */
    public function setPreferredVersion($version)
    {
        $this->preferredVersion = $version;
    }
    /**
     * Disconnect
     *
     * @param int $reason
     * @return bool
     * @access protected
     */
    protected function disconnect_helper($reason)
    {
        $this->pwd = false;
        parent::disconnect_helper($reason);
    }
    /**
     * Enable Date Preservation
     *
     * @access public
     */
    public function enableDatePreservation()
    {
        $this->preserveTime = true;
    }
    /**
     * Disable Date Preservation
     *
     * @access public
     */
    public function disableDatePreservation()
    {
        $this->preserveTime = false;
    }
}<?php

/**
 * Pure-PHP implementation of SSHv2.
 *
 * PHP version 5
 *
 * Here are some examples of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $ssh = new \phpseclib3\Net\SSH2('www.domain.tld');
 *    if (!$ssh->login('username', 'password')) {
 *        exit('Login Failed');
 *    }
 *
 *    echo $ssh->exec('pwd');
 *    echo $ssh->exec('ls -la');
 * ?>
 * </code>
 *
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $key = \phpseclib3\Crypt\PublicKeyLoader::load('...', '(optional) password');
 *
 *    $ssh = new \phpseclib3\Net\SSH2('www.domain.tld');
 *    if (!$ssh->login('username', $key)) {
 *        exit('Login Failed');
 *    }
 *
 *    echo $ssh->read('username@username:~$');
 *    $ssh->write("ls -la\n");
 *    echo $ssh->read('username@username:~$');
 * ?>
 * </code>
 *
 * @category  Net
 * @package   SSH2
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2007 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Net;

use phpseclib3\Crypt\Blowfish;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\RC4;
use phpseclib3\Crypt\Rijndael;
use phpseclib3\Crypt\Common\PrivateKey;
use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\DH;
use phpseclib3\Crypt\TripleDES;
use phpseclib3\Crypt\Twofish;
use phpseclib3\Crypt\ChaCha20;
use phpseclib3\Math\BigInteger;
// Used to do Diffie-Hellman key exchange and DSA/RSA signature verification.
use phpseclib3\System\SSH\Agent;
use phpseclib3\System\SSH\Agent\Identity as AgentIdentity;
use phpseclib3\Exception\NoSupportedAlgorithmsException;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\Exception\UnsupportedCurveException;
use phpseclib3\Exception\ConnectionClosedException;
use phpseclib3\Exception\UnableToConnectException;
use phpseclib3\Exception\InsufficientSetupException;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\AsymmetricKey;
/**#@+
 * @access private
 */
/**
 * No compression
 */
define('NET_SSH2_COMPRESSION_NONE', 1);
/**
 * zlib compression
 */
define('NET_SSH2_COMPRESSION_ZLIB', 2);
/**
 * zlib@openssh.com
 */
define('NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH', 3);
/**#@-*/
/**
 * Pure-PHP implementation of SSHv2.
 *
 * @package SSH2
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class SSH2
{
    // Execution Bitmap Masks
    const MASK_CONSTRUCTOR = 0x1;
    const MASK_CONNECTED = 0x2;
    const MASK_LOGIN_REQ = 0x4;
    const MASK_LOGIN = 0x8;
    const MASK_SHELL = 0x10;
    const MASK_WINDOW_ADJUST = 0x20;
    /*
     * Channel constants
     *
     * RFC4254 refers not to client and server channels but rather to sender and recipient channels.  we don't refer
     * to them in that way because RFC4254 toggles the meaning. the client sends a SSH_MSG_CHANNEL_OPEN message with
     * a sender channel and the server sends a SSH_MSG_CHANNEL_OPEN_CONFIRMATION in response, with a sender and a
     * recipient channel.  at first glance, you might conclude that SSH_MSG_CHANNEL_OPEN_CONFIRMATION's sender channel
     * would be the same thing as SSH_MSG_CHANNEL_OPEN's sender channel, but it's not, per this snippet:
     *     The 'recipient channel' is the channel number given in the original
     *     open request, and 'sender channel' is the channel number allocated by
     *     the other side.
     *
     * @see \phpseclib3\Net\SSH2::send_channel_packet()
     * @see \phpseclib3\Net\SSH2::get_channel_packet()
     * @access private
     */
    const CHANNEL_EXEC = 1;
    // PuTTy uses 0x100
    const CHANNEL_SHELL = 2;
    const CHANNEL_SUBSYSTEM = 3;
    const CHANNEL_AGENT_FORWARD = 4;
    const CHANNEL_KEEP_ALIVE = 5;
    /**
     * Returns the message numbers
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_SIMPLE = 1;
    /**
     * Returns the message content
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_COMPLEX = 2;
    /**
     * Outputs the content real-time
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_REALTIME = 3;
    /**
     * Dumps the content real-time to a file
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_REALTIME_FILE = 4;
    /**
     * Make sure that the log never gets larger than this
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::getLog()
     */
    const LOG_MAX_SIZE = 1048576;
    // 1024 * 1024
    /**
     * Returns when a string matching $expect exactly is found
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::read()
     */
    const READ_SIMPLE = 1;
    /**
     * Returns when a string matching the regular expression $expect is found
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::read()
     */
    const READ_REGEX = 2;
    /**
     * Returns whenever a data packet is received.
     *
     * Some data packets may only contain a single character so it may be necessary
     * to call read() multiple times when using this option
     *
     * @access public
     * @see \phpseclib3\Net\SSH2::read()
     */
    const READ_NEXT = 3;
    /**
     * The SSH identifier
     *
     * @var string
     * @access private
     */
    private $identifier;
    /**
     * The Socket Object
     *
     * @var object
     * @access private
     */
    public $fsock;
    /**
     * Execution Bitmap
     *
     * The bits that are set represent functions that have been called already.  This is used to determine
     * if a requisite function has been successfully executed.  If not, an error should be thrown.
     *
     * @var int
     * @access private
     */
    protected $bitmap = 0;
    /**
     * Error information
     *
     * @see self::getErrors()
     * @see self::getLastError()
     * @var array
     * @access private
     */
    private $errors = [];
    /**
     * Server Identifier
     *
     * @see self::getServerIdentification()
     * @var array|false
     * @access private
     */
    protected $server_identifier = false;
    /**
     * Key Exchange Algorithms
     *
     * @see self::getKexAlgorithims()
     * @var array|false
     * @access private
     */
    private $kex_algorithms = false;
    /**
     * Key Exchange Algorithm
     *
     * @see self::getMethodsNegotiated()
     * @var string|false
     * @access private
     */
    private $kex_algorithm = false;
    /**
     * Minimum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
     *
     * @see self::_key_exchange()
     * @var int
     * @access private
     */
    private $kex_dh_group_size_min = 1536;
    /**
     * Preferred Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
     *
     * @see self::_key_exchange()
     * @var int
     * @access private
     */
    private $kex_dh_group_size_preferred = 2048;
    /**
     * Maximum Diffie-Hellman Group Bit Size in RFC 4419 Key Exchange Methods
     *
     * @see self::_key_exchange()
     * @var int
     * @access private
     */
    private $kex_dh_group_size_max = 4096;
    /**
     * Server Host Key Algorithms
     *
     * @see self::getServerHostKeyAlgorithms()
     * @var array|false
     * @access private
     */
    private $server_host_key_algorithms = false;
    /**
     * Encryption Algorithms: Client to Server
     *
     * @see self::getEncryptionAlgorithmsClient2Server()
     * @var array|false
     * @access private
     */
    private $encryption_algorithms_client_to_server = false;
    /**
     * Encryption Algorithms: Server to Client
     *
     * @see self::getEncryptionAlgorithmsServer2Client()
     * @var array|false
     * @access private
     */
    private $encryption_algorithms_server_to_client = false;
    /**
     * MAC Algorithms: Client to Server
     *
     * @see self::getMACAlgorithmsClient2Server()
     * @var array|false
     * @access private
     */
    private $mac_algorithms_client_to_server = false;
    /**
     * MAC Algorithms: Server to Client
     *
     * @see self::getMACAlgorithmsServer2Client()
     * @var array|false
     * @access private
     */
    private $mac_algorithms_server_to_client = false;
    /**
     * Compression Algorithms: Client to Server
     *
     * @see self::getCompressionAlgorithmsClient2Server()
     * @var array|false
     * @access private
     */
    private $compression_algorithms_client_to_server = false;
    /**
     * Compression Algorithms: Server to Client
     *
     * @see self::getCompressionAlgorithmsServer2Client()
     * @var array|false
     * @access private
     */
    private $compression_algorithms_server_to_client = false;
    /**
     * Languages: Server to Client
     *
     * @see self::getLanguagesServer2Client()
     * @var array|false
     * @access private
     */
    private $languages_server_to_client = false;
    /**
     * Languages: Client to Server
     *
     * @see self::getLanguagesClient2Server()
     * @var array|false
     * @access private
     */
    private $languages_client_to_server = false;
    /**
     * Preferred Algorithms
     *
     * @see self::setPreferredAlgorithms()
     * @var array
     * @access private
     */
    private $preferred = [];
    /**
     * Block Size for Server to Client Encryption
     *
     * "Note that the length of the concatenation of 'packet_length',
     *  'padding_length', 'payload', and 'random padding' MUST be a multiple
     *  of the cipher block size or 8, whichever is larger.  This constraint
     *  MUST be enforced, even when using stream ciphers."
     *
     *  -- http://tools.ietf.org/html/rfc4253#section-6
     *
     * @see self::__construct()
     * @see self::_send_binary_packet()
     * @var int
     * @access private
     */
    private $encrypt_block_size = 8;
    /**
     * Block Size for Client to Server Encryption
     *
     * @see self::__construct()
     * @see self::_get_binary_packet()
     * @var int
     * @access private
     */
    private $decrypt_block_size = 8;
    /**
     * Server to Client Encryption Object
     *
     * @see self::_get_binary_packet()
     * @var object
     * @access private
     */
    private $decrypt = false;
    /**
     * Server to Client Length Encryption Object
     *
     * @see self::_get_binary_packet()
     * @var object
     * @access private
     */
    private $lengthDecrypt = false;
    /**
     * Client to Server Encryption Object
     *
     * @see self::_send_binary_packet()
     * @var object
     * @access private
     */
    private $encrypt = false;
    /**
     * Client to Server Length Encryption Object
     *
     * @see self::_send_binary_packet()
     * @var object
     * @access private
     */
    private $lengthEncrypt = false;
    /**
     * Client to Server HMAC Object
     *
     * @see self::_send_binary_packet()
     * @var object
     * @access private
     */
    private $hmac_create = false;
    /**
     * Server to Client HMAC Object
     *
     * @see self::_get_binary_packet()
     * @var object
     * @access private
     */
    private $hmac_check = false;
    /**
     * Size of server to client HMAC
     *
     * We need to know how big the HMAC will be for the server to client direction so that we know how many bytes to read.
     * For the client to server side, the HMAC object will make the HMAC as long as it needs to be.  All we need to do is
     * append it.
     *
     * @see self::_get_binary_packet()
     * @var int
     * @access private
     */
    private $hmac_size = false;
    /**
     * Server Public Host Key
     *
     * @see self::getServerPublicHostKey()
     * @var string
     * @access private
     */
    private $server_public_host_key;
    /**
     * Session identifier
     *
     * "The exchange hash H from the first key exchange is additionally
     *  used as the session identifier, which is a unique identifier for
     *  this connection."
     *
     *  -- http://tools.ietf.org/html/rfc4253#section-7.2
     *
     * @see self::_key_exchange()
     * @var string
     * @access private
     */
    private $session_id = false;
    /**
     * Exchange hash
     *
     * The current exchange hash
     *
     * @see self::_key_exchange()
     * @var string
     * @access private
     */
    private $exchange_hash = false;
    /**
     * Message Numbers
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $message_numbers = [];
    /**
     * Disconnection Message 'reason codes' defined in RFC4253
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $disconnect_reasons = [];
    /**
     * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
     *
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $channel_open_failure_reasons = [];
    /**
     * Terminal Modes
     *
     * @link http://tools.ietf.org/html/rfc4254#section-8
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $terminal_modes = [];
    /**
     * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
     *
     * @link http://tools.ietf.org/html/rfc4254#section-5.2
     * @see self::__construct()
     * @var array
     * @access private
     */
    private $channel_extended_data_type_codes = [];
    /**
     * Send Sequence Number
     *
     * See 'Section 6.4.  Data Integrity' of rfc4253 for more info.
     *
     * @see self::_send_binary_packet()
     * @var int
     * @access private
     */
    private $send_seq_no = 0;
    /**
     * Get Sequence Number
     *
     * See 'Section 6.4.  Data Integrity' of rfc4253 for more info.
     *
     * @see self::_get_binary_packet()
     * @var int
     * @access private
     */
    private $get_seq_no = 0;
    /**
     * Server Channels
     *
     * Maps client channels to server channels
     *
     * @see self::get_channel_packet()
     * @see self::exec()
     * @var array
     * @access private
     */
    protected $server_channels = [];
    /**
     * Channel Buffers
     *
     * If a client requests a packet from one channel but receives two packets from another those packets should
     * be placed in a buffer
     *
     * @see self::get_channel_packet()
     * @see self::exec()
     * @var array
     * @access private
     */
    private $channel_buffers = [];
    /**
     * Channel Status
     *
     * Contains the type of the last sent message
     *
     * @see self::get_channel_packet()
     * @var array
     * @access private
     */
    protected $channel_status = [];
    /**
     * Packet Size
     *
     * Maximum packet size indexed by channel
     *
     * @see self::send_channel_packet()
     * @var array
     * @access private
     */
    private $packet_size_client_to_server = [];
    /**
     * Message Number Log
     *
     * @see self::getLog()
     * @var array
     * @access private
     */
    private $message_number_log = [];
    /**
     * Message Log
     *
     * @see self::getLog()
     * @var array
     * @access private
     */
    private $message_log = [];
    /**
     * The Window Size
     *
     * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 2GB)
     *
     * @var int
     * @see self::send_channel_packet()
     * @see self::exec()
     * @access private
     */
    protected $window_size = 0x7fffffff;
    /**
     * What we resize the window to
     *
     * When PuTTY resizes the window it doesn't add an additional 0x7FFFFFFF bytes - it adds 0x40000000 bytes.
     * Some SFTP clients (GoAnywhere) don't support adding 0x7FFFFFFF to the window size after the fact so
     * we'll just do what PuTTY does
     *
     * @var int
     * @see self::_send_channel_packet()
     * @see self::exec()
     * @access private
     */
    private $window_resize = 0x40000000;
    /**
     * Window size, server to client
     *
     * Window size indexed by channel
     *
     * @see self::send_channel_packet()
     * @var array
     * @access private
     */
    protected $window_size_server_to_client = [];
    /**
     * Window size, client to server
     *
     * Window size indexed by channel
     *
     * @see self::get_channel_packet()
     * @var array
     * @access private
     */
    private $window_size_client_to_server = [];
    /**
     * Server signature
     *
     * Verified against $this->session_id
     *
     * @see self::getServerPublicHostKey()
     * @var string
     * @access private
     */
    private $signature = '';
    /**
     * Server signature format
     *
     * ssh-rsa or ssh-dss.
     *
     * @see self::getServerPublicHostKey()
     * @var string
     * @access private
     */
    private $signature_format = '';
    /**
     * Interactive Buffer
     *
     * @see self::read()
     * @var array
     * @access private
     */
    private $interactiveBuffer = '';
    /**
     * Current log size
     *
     * Should never exceed self::LOG_MAX_SIZE
     *
     * @see self::_send_binary_packet()
     * @see self::_get_binary_packet()
     * @var int
     * @access private
     */
    private $log_size;
    /**
     * Timeout
     *
     * @see self::setTimeout()
     * @access private
     */
    protected $timeout;
    /**
     * Current Timeout
     *
     * @see self::get_channel_packet()
     * @access private
     */
    protected $curTimeout;
    /**
     * Keep Alive Interval
     *
     * @see self::setKeepAlive()
     * @access private
     */
    private $keepAlive;
    /**
     * Real-time log file pointer
     *
     * @see self::_append_log()
     * @var resource
     * @access private
     */
    private $realtime_log_file;
    /**
     * Real-time log file size
     *
     * @see self::_append_log()
     * @var int
     * @access private
     */
    private $realtime_log_size;
    /**
     * Has the signature been validated?
     *
     * @see self::getServerPublicHostKey()
     * @var bool
     * @access private
     */
    private $signature_validated = false;
    /**
     * Real-time log file wrap boolean
     *
     * @see self::_append_log()
     * @access private
     */
    private $realtime_log_wrap;
    /**
     * Flag to suppress stderr from output
     *
     * @see self::enableQuietMode()
     * @access private
     */
    private $quiet_mode = false;
    /**
     * Time of first network activity
     *
     * @var int
     * @access private
     */
    private $last_packet;
    /**
     * Exit status returned from ssh if any
     *
     * @var int
     * @access private
     */
    private $exit_status;
    /**
     * Flag to request a PTY when using exec()
     *
     * @var bool
     * @see self::enablePTY()
     * @access private
     */
    private $request_pty = false;
    /**
     * Flag set while exec() is running when using enablePTY()
     *
     * @var bool
     * @access private
     */
    private $in_request_pty_exec = false;
    /**
     * Flag set after startSubsystem() is called
     *
     * @var bool
     * @access private
     */
    private $in_subsystem;
    /**
     * Contents of stdError
     *
     * @var string
     * @access private
     */
    private $stdErrorLog;
    /**
     * The Last Interactive Response
     *
     * @see self::_keyboard_interactive_process()
     * @var string
     * @access private
     */
    private $last_interactive_response = '';
    /**
     * Keyboard Interactive Request / Responses
     *
     * @see self::_keyboard_interactive_process()
     * @var array
     * @access private
     */
    private $keyboard_requests_responses = [];
    /**
     * Banner Message
     *
     * Quoting from the RFC, "in some jurisdictions, sending a warning message before
     * authentication may be relevant for getting legal protection."
     *
     * @see self::_filter()
     * @see self::getBannerMessage()
     * @var string
     * @access private
     */
    private $banner_message = '';
    /**
     * Did read() timeout or return normally?
     *
     * @see self::isTimeout()
     * @var bool
     * @access private
     */
    private $is_timeout = false;
    /**
     * Log Boundary
     *
     * @see self::_format_log()
     * @var string
     * @access private
     */
    private $log_boundary = ':';
    /**
     * Log Long Width
     *
     * @see self::_format_log()
     * @var int
     * @access private
     */
    private $log_long_width = 65;
    /**
     * Log Short Width
     *
     * @see self::_format_log()
     * @var int
     * @access private
     */
    private $log_short_width = 16;
    /**
     * Hostname
     *
     * @see self::__construct()
     * @see self::_connect()
     * @var string
     * @access private
     */
    private $host;
    /**
     * Port Number
     *
     * @see self::__construct()
     * @see self::_connect()
     * @var int
     * @access private
     */
    private $port;
    /**
     * Number of columns for terminal window size
     *
     * @see self::getWindowColumns()
     * @see self::setWindowColumns()
     * @see self::setWindowSize()
     * @var int
     * @access private
     */
    private $windowColumns = 80;
    /**
     * Number of columns for terminal window size
     *
     * @see self::getWindowRows()
     * @see self::setWindowRows()
     * @see self::setWindowSize()
     * @var int
     * @access private
     */
    private $windowRows = 24;
    /**
     * Crypto Engine
     *
     * @see self::setCryptoEngine()
     * @see self::_key_exchange()
     * @var int
     * @access private
     */
    private static $crypto_engine = false;
    /**
     * A System_SSH_Agent for use in the SSH2 Agent Forwarding scenario
     *
     * @var \phpseclib3\System\Ssh\Agent
     * @access private
     */
    private $agent;
    /**
     * Connection storage to replicates ssh2 extension functionality:
     * {@link http://php.net/manual/en/wrappers.ssh2.php#refsect1-wrappers.ssh2-examples}
     *
     * @var SSH2[]
     */
    private static $connections;
    /**
     * Send the identification string first?
     *
     * @var bool
     * @access private
     */
    private $send_id_string_first = true;
    /**
     * Send the key exchange initiation packet first?
     *
     * @var bool
     * @access private
     */
    private $send_kex_first = true;
    /**
     * Some versions of OpenSSH incorrectly calculate the key size
     *
     * @var bool
     * @access private
     */
    private $bad_key_size_fix = false;
    /**
     * Should we try to re-connect to re-establish keys?
     *
     * @var bool
     * @access private
     */
    private $retry_connect = false;
    /**
     * Binary Packet Buffer
     *
     * @var string|false
     * @access private
     */
    private $binary_packet_buffer = false;
    /**
     * Preferred Signature Format
     *
     * @var string|false
     * @access private
     */
    protected $preferred_signature_format = false;
    /**
     * Authentication Credentials
     *
     * @var array
     * @access private
     */
    protected $auth = [];
    /**
     * Terminal
     *
     * @var string
     * @access private
     */
    private $term = 'vt100';
    /**
     * The authentication methods that may productively continue authentication.
     * 
     * @see https://tools.ietf.org/html/rfc4252#section-5.1
     * @var array|null
     * @access private
     */
    private $auth_methods_to_continue = null;
    /**
     * Compression method
     *
     * @var int
     * @access private
     */
    private $compress = NET_SSH2_COMPRESSION_NONE;
    /**
     * Decompression method
     *
     * @var resource|object
     * @access private
     */
    private $decompress = NET_SSH2_COMPRESSION_NONE;
    /**
     * Compression context
     *
     * @var int
     * @access private
     */
    private $compress_context;
    /**
     * Decompression context
     *
     * @var resource|object
     * @access private
     */
    private $decompress_context;
    /**
     * Regenerate Compression Context
     *
     * @var bool
     * @access private
     */
    private $regenerate_compression_context = false;
    /**
     * Regenerate Decompression Context
     *
     * @var bool
     * @access private
     */
    private $regenerate_decompression_context = false;
    /**
     * Smart multi-factor authentication flag
     *
     * @var bool
     * @access private
     */
    private $smartMFA = true;
    /**
     * Default Constructor.
     *
     * $host can either be a string, representing the host, or a stream resource.
     *
     * @param mixed $host
     * @param int $port
     * @param int $timeout
     * @see self::login()
     * @return (SSH2 | void)
     * @access public
     */
    public function __construct($host, $port = 22, $timeout = 10)
    {
        $this->message_numbers = [1 => 'NET_SSH2_MSG_DISCONNECT', 2 => 'NET_SSH2_MSG_IGNORE', 3 => 'NET_SSH2_MSG_UNIMPLEMENTED', 4 => 'NET_SSH2_MSG_DEBUG', 5 => 'NET_SSH2_MSG_SERVICE_REQUEST', 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT', 20 => 'NET_SSH2_MSG_KEXINIT', 21 => 'NET_SSH2_MSG_NEWKEYS', 30 => 'NET_SSH2_MSG_KEXDH_INIT', 31 => 'NET_SSH2_MSG_KEXDH_REPLY', 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST', 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE', 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS', 53 => 'NET_SSH2_MSG_USERAUTH_BANNER', 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST', 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS', 82 => 'NET_SSH2_MSG_REQUEST_FAILURE', 90 => 'NET_SSH2_MSG_CHANNEL_OPEN', 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION', 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE', 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST', 94 => 'NET_SSH2_MSG_CHANNEL_DATA', 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA', 96 => 'NET_SSH2_MSG_CHANNEL_EOF', 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE', 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST', 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS', 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'];
        $this->disconnect_reasons = [1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT', 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR', 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED', 4 => 'NET_SSH2_DISCONNECT_RESERVED', 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR', 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR', 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE', 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED', 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE', 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST', 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION', 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS', 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER', 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE', 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'];
        $this->channel_open_failure_reasons = [1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'];
        $this->terminal_modes = [0 => 'NET_SSH2_TTY_OP_END'];
        $this->channel_extended_data_type_codes = [1 => 'NET_SSH2_EXTENDED_DATA_STDERR'];
        $this->define_array(
            $this->message_numbers,
            $this->disconnect_reasons,
            $this->channel_open_failure_reasons,
            $this->terminal_modes,
            $this->channel_extended_data_type_codes,
            [60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ'],
            [60 => 'NET_SSH2_MSG_USERAUTH_PK_OK'],
            [60 => 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST', 61 => 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE'],
            // RFC 4419 - diffie-hellman-group-exchange-sha{1,256}
            [30 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST_OLD', 31 => 'NET_SSH2_MSG_KEXDH_GEX_GROUP', 32 => 'NET_SSH2_MSG_KEXDH_GEX_INIT', 33 => 'NET_SSH2_MSG_KEXDH_GEX_REPLY', 34 => 'NET_SSH2_MSG_KEXDH_GEX_REQUEST'],
            // RFC 5656 - Elliptic Curves (for curve25519-sha256@libssh.org)
            [30 => 'NET_SSH2_MSG_KEX_ECDH_INIT', 31 => 'NET_SSH2_MSG_KEX_ECDH_REPLY']
        );
        self::$connections[$this->getResourceId()] = class_exists('WeakReference') ? \WeakReference::create($this) : $this;
        if (is_resource($host)) {
            $this->fsock = $host;
            return;
        }
        if (is_string($host)) {
            $this->host = $host;
            $this->port = $port;
            $this->timeout = $timeout;
        }
    }
    /**
    * Set Crypto Engine Mode
    *
    * Possible $engine values:
    OpenSSL, mcrypt, Eval, PHP
    *
    * @param int $engine
    * @access public
    */
    public static function setCryptoEngine($engine)
    {
        self::$crypto_engine = $engine;
    }
    /**
    * Send Identification String First
    *
    * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
    both sides MUST send an identification string". It does not say which side sends it first. In
    theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
    *
    * @access public
    */
    public function sendIdentificationStringFirst()
    {
        $this->send_id_string_first = true;
    }
    /**
    * Send Identification String Last
    *
    * https://tools.ietf.org/html/rfc4253#section-4.2 says "when the connection has been established,
    both sides MUST send an identification string". It does not say which side sends it first. In
    theory it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
    *
    * @access public
    */
    public function sendIdentificationStringLast()
    {
        $this->send_id_string_first = false;
    }
    /**
    * Send SSH_MSG_KEXINIT First
    *
    * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
    sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
    it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
    *
    * @access public
    */
    public function sendKEXINITFirst()
    {
        $this->send_kex_first = true;
    }
    /**
    * Send SSH_MSG_KEXINIT Last
    *
    * https://tools.ietf.org/html/rfc4253#section-7.1 says "key exchange begins by each sending
    sending the [SSH_MSG_KEXINIT] packet". It does not say which side sends it first. In theory
    it shouldn't matter but it is a fact of life that some SSH servers are simply buggy
    *
    * @access public
    */
    public function sendKEXINITLast()
    {
        $this->send_kex_first = false;
    }
    /**
     * Connect to an SSHv2 server
     *
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @throws \RuntimeException on other errors
     * @access private
     */
    private function connect()
    {
        if ($this->bitmap & self::MASK_CONSTRUCTOR) {
            return;
        }
        $this->bitmap |= self::MASK_CONSTRUCTOR;
        $this->curTimeout = $this->timeout;
        $this->last_packet = microtime(true);
        if (!is_resource($this->fsock)) {
            $start = microtime(true);
            // with stream_select a timeout of 0 means that no timeout takes place;
            // with fsockopen a timeout of 0 means that you instantly timeout
            // to resolve this incompatibility a timeout of 100,000 will be used for fsockopen if timeout is 0
            $this->fsock = @\Phabel\Target\Php80\Polyfill::fsockopen($this->host, $this->port, $errno, $errstr, $this->curTimeout == 0 ? 100000 : $this->curTimeout);
            if (!$this->fsock) {
                $host = $this->host . ':' . $this->port;
                throw new UnableToConnectException(rtrim("Cannot connect to {$host}. Error {$errno}. {$errstr}"));
            }
            $elapsed = microtime(true) - $start;
            if ($this->curTimeout) {
                $this->curTimeout -= $elapsed;
                if ($this->curTimeout < 0) {
                    throw new \RuntimeException('Connection timed out whilst attempting to open socket connection');
                }
            }
        }
        $this->identifier = $this->generate_identifier();
        if ($this->send_id_string_first) {
            fputs($this->fsock, $this->identifier . "\r\n");
        }
        /* According to the SSH2 specs,
        
                  "The server MAY send other lines of data before sending the version
                   string.  Each line SHOULD be terminated by a Carriage Return and Line
                   Feed.  Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
                   in ISO-10646 UTF-8 [RFC3629] (language is not specified).  Clients
                   MUST be able to process such lines." */
        $data = '';
        while (!feof($this->fsock) && !preg_match('#(.*)^(SSH-(\\d\\.\\d+).*)#ms', $data, $matches)) {
            $line = '';
            while (true) {
                if ($this->curTimeout) {
                    if ($this->curTimeout < 0) {
                        throw new \RuntimeException('Connection timed out whilst receiving server identification string');
                    }
                    $read = [$this->fsock];
                    $write = $except = null;
                    $start = microtime(true);
                    $sec = floor($this->curTimeout);
                    $usec = 1000000 * ($this->curTimeout - $sec);
                    if (@stream_select($read, $write, $except, $sec, $usec) === false) {
                        throw new \RuntimeException('Connection timed out whilst receiving server identification string');
                    }
                    $elapsed = microtime(true) - $start;
                    $this->curTimeout -= $elapsed;
                }
                $temp = stream_get_line($this->fsock, 255, "\n");
                if ($temp === false) {
                    throw new \RuntimeException('Error reading from socket');
                }
                if (strlen($temp) == 255) {
                    continue;
                }
                $line .= "{$temp}\n";
                // quoting RFC4253, "Implementers who wish to maintain
                // compatibility with older, undocumented versions of this protocol may
                // want to process the identification string without expecting the
                // presence of the carriage return character for reasons described in
                // Section 5 of this document."
                //if (substr($line, -2) == "\r\n") {
                //    break;
                //}
                break;
            }
            $data .= $line;
        }
        if (feof($this->fsock)) {
            $this->bitmap = 0;
            throw new ConnectionClosedException('Connection closed by server');
        }
        $extra = $matches[1];
        if (defined('NET_SSH2_LOGGING')) {
            $this->append_log('<-', $matches[0]);
            $this->append_log('->', $this->identifier . "\r\n");
        }
        $this->server_identifier = trim($temp, "\r\n");
        if (strlen($extra)) {
            $this->errors[] = $data;
        }
        if (version_compare($matches[3], '1.99', '<')) {
            $this->bitmap = 0;
            throw new UnableToConnectException("Cannot connect to SSH {$matches[3]} servers");
        }
        if (!$this->send_id_string_first) {
            fputs($this->fsock, $this->identifier . "\r\n");
        }
        if (!$this->send_kex_first) {
            $response = $this->get_binary_packet();
            if (!strlen($response) || ord($response[0]) != NET_SSH2_MSG_KEXINIT) {
                $this->bitmap = 0;
                throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
            }
            $this->key_exchange($response);
        }
        if ($this->send_kex_first) {
            $this->key_exchange();
        }
        $this->bitmap |= self::MASK_CONNECTED;
        return true;
    }
    /**
     * Generates the SSH identifier
     *
     * You should overwrite this method in your own class if you want to use another identifier
     *
     * @access protected
     * @return string
     */
    private function generate_identifier()
    {
        $identifier = 'SSH-2.0-phpseclib_3.0';
        $ext = [];
        if (extension_loaded('sodium')) {
            $ext[] = 'libsodium';
        }
        if (extension_loaded('openssl')) {
            $ext[] = 'openssl';
        } elseif (extension_loaded('mcrypt')) {
            $ext[] = 'mcrypt';
        }
        if (extension_loaded('gmp')) {
            $ext[] = 'gmp';
        } elseif (extension_loaded('bcmath')) {
            $ext[] = 'bcmath';
        }
        if (!empty($ext)) {
            $identifier .= ' (' . implode(', ', $ext) . ')';
        }
        return $identifier;
    }
    /**
     * Key Exchange
     *
     * @return bool
     * @param (string | bool) $kexinit_payload_server optional
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @throws \RuntimeException on other errors
     * @throws \phpseclib3\Exception\NoSupportedAlgorithmsException when none of the algorithms phpseclib has loaded are compatible
     * @access private
     */
    private function key_exchange($kexinit_payload_server = false)
    {
        $preferred = $this->preferred;
        $send_kex = true;
        $kex_algorithms = isset($preferred['kex']) ? $preferred['kex'] : SSH2::getSupportedKEXAlgorithms();
        $server_host_key_algorithms = isset($preferred['hostkey']) ? $preferred['hostkey'] : SSH2::getSupportedHostKeyAlgorithms();
        $s2c_encryption_algorithms = isset($preferred['server_to_client']['crypt']) ? $preferred['server_to_client']['crypt'] : SSH2::getSupportedEncryptionAlgorithms();
        $c2s_encryption_algorithms = isset($preferred['client_to_server']['crypt']) ? $preferred['client_to_server']['crypt'] : SSH2::getSupportedEncryptionAlgorithms();
        $s2c_mac_algorithms = isset($preferred['server_to_client']['mac']) ? $preferred['server_to_client']['mac'] : SSH2::getSupportedMACAlgorithms();
        $c2s_mac_algorithms = isset($preferred['client_to_server']['mac']) ? $preferred['client_to_server']['mac'] : SSH2::getSupportedMACAlgorithms();
        $s2c_compression_algorithms = isset($preferred['server_to_client']['comp']) ? $preferred['server_to_client']['comp'] : SSH2::getSupportedCompressionAlgorithms();
        $c2s_compression_algorithms = isset($preferred['client_to_server']['comp']) ? $preferred['client_to_server']['comp'] : SSH2::getSupportedCompressionAlgorithms();
        // some SSH servers have buggy implementations of some of the above algorithms
        switch (true) {
            case $this->server_identifier == 'SSH-2.0-SSHD':
            case \Phabel\Target\Php80\Polyfill::substr($this->server_identifier, 0, 13) == 'SSH-2.0-DLINK':
                if (!isset($preferred['server_to_client']['mac'])) {
                    $s2c_mac_algorithms = array_values(array_diff($s2c_mac_algorithms, ['hmac-sha1-96', 'hmac-md5-96']));
                }
                if (!isset($preferred['client_to_server']['mac'])) {
                    $c2s_mac_algorithms = array_values(array_diff($c2s_mac_algorithms, ['hmac-sha1-96', 'hmac-md5-96']));
                }
        }
        $client_cookie = Random::string(16);
        $kexinit_payload_client = pack('Ca*', NET_SSH2_MSG_KEXINIT, $client_cookie);
        $kexinit_payload_client .= Strings::packSSH2(
            'L10bN',
            $kex_algorithms,
            $server_host_key_algorithms,
            $c2s_encryption_algorithms,
            $s2c_encryption_algorithms,
            $c2s_mac_algorithms,
            $s2c_mac_algorithms,
            $c2s_compression_algorithms,
            $s2c_compression_algorithms,
            [],
            // language, client to server
            [],
            // language, server to client
            false,
            // first_kex_packet_follows
            0
        );
        if ($kexinit_payload_server === false) {
            $this->send_binary_packet($kexinit_payload_client);
            $kexinit_payload_server = $this->get_binary_packet();
            if (!strlen($kexinit_payload_server) || ord($kexinit_payload_server[0]) != NET_SSH2_MSG_KEXINIT) {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
                throw new \UnexpectedValueException('Expected SSH_MSG_KEXINIT');
            }
            $send_kex = false;
        }
        $response = $kexinit_payload_server;
        Strings::shift($response, 1);
        // skip past the message number (it should be SSH_MSG_KEXINIT)
        $server_cookie = Strings::shift($response, 16);
        list($this->kex_algorithms, $this->server_host_key_algorithms, $this->encryption_algorithms_client_to_server, $this->encryption_algorithms_server_to_client, $this->mac_algorithms_client_to_server, $this->mac_algorithms_server_to_client, $this->compression_algorithms_client_to_server, $this->compression_algorithms_server_to_client, $this->languages_client_to_server, $this->languages_server_to_client, $first_kex_packet_follows) = Strings::unpackSSH2('L10C', $response);
        if ($send_kex) {
            $this->send_binary_packet($kexinit_payload_client);
        }
        // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
        // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
        // diffie-hellman key exchange as fast as possible
        $decrypt = self::array_intersect_first($s2c_encryption_algorithms, $this->encryption_algorithms_server_to_client);
        $decryptKeyLength = $this->encryption_algorithm_to_key_size($decrypt);
        if ($decryptKeyLength === null) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible server to client encryption algorithms found');
        }
        $encrypt = self::array_intersect_first($c2s_encryption_algorithms, $this->encryption_algorithms_client_to_server);
        $encryptKeyLength = $this->encryption_algorithm_to_key_size($encrypt);
        if ($encryptKeyLength === null) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible client to server encryption algorithms found');
        }
        // through diffie-hellman key exchange a symmetric key is obtained
        $this->kex_algorithm = self::array_intersect_first($kex_algorithms, $this->kex_algorithms);
        if ($this->kex_algorithm === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible key exchange algorithms found');
        }
        $server_host_key_algorithm = self::array_intersect_first($server_host_key_algorithms, $this->server_host_key_algorithms);
        if ($server_host_key_algorithm === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible server host key algorithms found');
        }
        $mac_algorithm_out = self::array_intersect_first($c2s_mac_algorithms, $this->mac_algorithms_client_to_server);
        if ($mac_algorithm_out === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible client to server message authentication algorithms found');
        }
        $mac_algorithm_in = self::array_intersect_first($s2c_mac_algorithms, $this->mac_algorithms_server_to_client);
        if ($mac_algorithm_in === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible server to client message authentication algorithms found');
        }
        $compression_map = ['none' => NET_SSH2_COMPRESSION_NONE, 'zlib' => NET_SSH2_COMPRESSION_ZLIB, 'zlib@openssh.com' => NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH];
        $compression_algorithm_in = self::array_intersect_first($s2c_compression_algorithms, $this->compression_algorithms_server_to_client);
        if ($compression_algorithm_in === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible server to client compression algorithms found');
        }
        $this->decompress = $compression_map[$compression_algorithm_in];
        $compression_algorithm_out = self::array_intersect_first($c2s_compression_algorithms, $this->compression_algorithms_client_to_server);
        if ($compression_algorithm_out === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
            throw new NoSupportedAlgorithmsException('No compatible client to server compression algorithms found');
        }
        $this->compress = $compression_map[$compression_algorithm_out];
        switch ($this->kex_algorithm) {
            case 'diffie-hellman-group15-sha512':
            case 'diffie-hellman-group16-sha512':
            case 'diffie-hellman-group17-sha512':
            case 'diffie-hellman-group18-sha512':
            case 'ecdh-sha2-nistp521':
                $kexHash = new Hash('sha512');
                break;
            case 'ecdh-sha2-nistp384':
                $kexHash = new Hash('sha384');
                break;
            case 'diffie-hellman-group-exchange-sha256':
            case 'diffie-hellman-group14-sha256':
            case 'ecdh-sha2-nistp256':
            case 'curve25519-sha256@libssh.org':
            case 'curve25519-sha256':
                $kexHash = new Hash('sha256');
                break;
            default:
                $kexHash = new Hash('sha1');
        }
        // Only relevant in diffie-hellman-group-exchange-sha{1,256}, otherwise empty.
        $exchange_hash_rfc4419 = '';
        if (strpos($this->kex_algorithm, 'curve25519-sha256') === 0 || strpos($this->kex_algorithm, 'ecdh-sha2-nistp') === 0) {
            $curve = strpos($this->kex_algorithm, 'curve25519-sha256') === 0 ? 'Curve25519' : \Phabel\Target\Php80\Polyfill::substr($this->kex_algorithm, 10);
            $ourPrivate = EC::createKey($curve);
            $ourPublicBytes = $ourPrivate->getPublicKey()->getEncodedCoordinates();
            $clientKexInitMessage = 'NET_SSH2_MSG_KEX_ECDH_INIT';
            $serverKexReplyMessage = 'NET_SSH2_MSG_KEX_ECDH_REPLY';
        } else {
            if (strpos($this->kex_algorithm, 'diffie-hellman-group-exchange') === 0) {
                $dh_group_sizes_packed = pack('NNN', $this->kex_dh_group_size_min, $this->kex_dh_group_size_preferred, $this->kex_dh_group_size_max);
                $packet = pack('Ca*', NET_SSH2_MSG_KEXDH_GEX_REQUEST, $dh_group_sizes_packed);
                $this->send_binary_packet($packet);
                $this->updateLogHistory('UNKNOWN (34)', 'NET_SSH2_MSG_KEXDH_GEX_REQUEST');
                $response = $this->get_binary_packet();
                list($type, $primeBytes, $gBytes) = Strings::unpackSSH2('Css', $response);
                if ($type != NET_SSH2_MSG_KEXDH_GEX_GROUP) {
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
                    throw new \UnexpectedValueException('Expected SSH_MSG_KEX_DH_GEX_GROUP');
                }
                $this->updateLogHistory('NET_SSH2_MSG_KEXDH_REPLY', 'NET_SSH2_MSG_KEXDH_GEX_GROUP');
                $prime = new BigInteger($primeBytes, -256);
                $g = new BigInteger($gBytes, -256);
                $exchange_hash_rfc4419 = $dh_group_sizes_packed . Strings::packSSH2('ss', $primeBytes, $gBytes);
                $params = DH::createParameters($prime, $g);
                $clientKexInitMessage = 'NET_SSH2_MSG_KEXDH_GEX_INIT';
                $serverKexReplyMessage = 'NET_SSH2_MSG_KEXDH_GEX_REPLY';
            } else {
                $params = DH::createParameters($this->kex_algorithm);
                $clientKexInitMessage = 'NET_SSH2_MSG_KEXDH_INIT';
                $serverKexReplyMessage = 'NET_SSH2_MSG_KEXDH_REPLY';
            }
            $keyLength = min($kexHash->getLengthInBytes(), max($encryptKeyLength, $decryptKeyLength));
            $ourPrivate = DH::createKey($params, 16 * $keyLength);
            // 2 * 8 * $keyLength
            $ourPublic = $ourPrivate->getPublicKey()->toBigInteger();
            $ourPublicBytes = $ourPublic->toBytes(true);
        }
        $data = pack('CNa*', constant($clientKexInitMessage), strlen($ourPublicBytes), $ourPublicBytes);
        $this->send_binary_packet($data);
        switch ($clientKexInitMessage) {
            case 'NET_SSH2_MSG_KEX_ECDH_INIT':
                $this->updateLogHistory('NET_SSH2_MSG_KEXDH_INIT', 'NET_SSH2_MSG_KEX_ECDH_INIT');
                break;
            case 'NET_SSH2_MSG_KEXDH_GEX_INIT':
                $this->updateLogHistory('UNKNOWN (32)', 'NET_SSH2_MSG_KEXDH_GEX_INIT');
        }
        $response = $this->get_binary_packet();
        list($type, $server_public_host_key, $theirPublicBytes, $this->signature) = Strings::unpackSSH2('Csss', $response);
        if ($type != constant($serverKexReplyMessage)) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
            throw new \UnexpectedValueException("Expected {$serverKexReplyMessage}");
        }
        switch ($serverKexReplyMessage) {
            case 'NET_SSH2_MSG_KEX_ECDH_REPLY':
                $this->updateLogHistory('NET_SSH2_MSG_KEXDH_REPLY', 'NET_SSH2_MSG_KEX_ECDH_REPLY');
                break;
            case 'NET_SSH2_MSG_KEXDH_GEX_REPLY':
                $this->updateLogHistory('UNKNOWN (33)', 'NET_SSH2_MSG_KEXDH_GEX_REPLY');
        }
        $this->server_public_host_key = $server_public_host_key;
        list($public_key_format) = Strings::unpackSSH2('s', $server_public_host_key);
        if (strlen($this->signature) < 4) {
            throw new \LengthException('The signature needs at least four bytes');
        }
        $temp = unpack('Nlength', \Phabel\Target\Php80\Polyfill::substr($this->signature, 0, 4));
        $this->signature_format = \Phabel\Target\Php80\Polyfill::substr($this->signature, 4, $temp['length']);
        $keyBytes = DH::computeSecret($ourPrivate, $theirPublicBytes);
        if (($keyBytes & "\xff\x80") === "\x00\x00") {
            $keyBytes = \Phabel\Target\Php80\Polyfill::substr($keyBytes, 1);
        } elseif (($keyBytes[0] & "\x80") === "\x80") {
            $keyBytes = "\x00{$keyBytes}";
        }
        $this->exchange_hash = Strings::packSSH2('s5', $this->identifier, $this->server_identifier, $kexinit_payload_client, $kexinit_payload_server, $this->server_public_host_key);
        $this->exchange_hash .= $exchange_hash_rfc4419;
        $this->exchange_hash .= Strings::packSSH2('s3', $ourPublicBytes, $theirPublicBytes, $keyBytes);
        $this->exchange_hash = $kexHash->hash($this->exchange_hash);
        if ($this->session_id === false) {
            $this->session_id = $this->exchange_hash;
        }
        switch ($server_host_key_algorithm) {
            case 'rsa-sha2-256':
            case 'rsa-sha2-512':
                //case 'ssh-rsa':
                $expected_key_format = 'ssh-rsa';
                break;
            default:
                $expected_key_format = $server_host_key_algorithm;
        }
        if ($public_key_format != $expected_key_format || $this->signature_format != $server_host_key_algorithm) {
            switch (true) {
                case $this->signature_format == $server_host_key_algorithm:
                case $server_host_key_algorithm != 'rsa-sha2-256' && $server_host_key_algorithm != 'rsa-sha2-512':
                case $this->signature_format != 'ssh-rsa':
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
                    throw new \RuntimeException('Server Host Key Algorithm Mismatch (' . $this->signature_format . ' vs ' . $server_host_key_algorithm . ')');
            }
        }
        $packet = pack('C', NET_SSH2_MSG_NEWKEYS);
        $this->send_binary_packet($packet);
        $response = $this->get_binary_packet();
        if ($response === false) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST);
            throw new ConnectionClosedException('Connection closed by server');
        }
        list($type) = Strings::unpackSSH2('C', $response);
        if ($type != NET_SSH2_MSG_NEWKEYS) {
            $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
            throw new \UnexpectedValueException('Expected SSH_MSG_NEWKEYS');
        }
        $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
        $this->encrypt = self::encryption_algorithm_to_crypt_instance($encrypt);
        if ($this->encrypt) {
            if (self::$crypto_engine) {
                $this->encrypt->setPreferredEngine(self::$crypto_engine);
            }
            if ($this->encrypt->getBlockLengthInBytes()) {
                $this->encrypt_block_size = $this->encrypt->getBlockLengthInBytes();
            }
            $this->encrypt->disablePadding();
            if ($this->encrypt->usesIV()) {
                $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
                while ($this->encrypt_block_size > strlen($iv)) {
                    $iv .= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
                }
                $this->encrypt->setIV(\Phabel\Target\Php80\Polyfill::substr($iv, 0, $this->encrypt_block_size));
            }
            switch ($encrypt) {
                case 'aes128-gcm@openssh.com':
                case 'aes256-gcm@openssh.com':
                    $nonce = $kexHash->hash($keyBytes . $this->exchange_hash . 'A' . $this->session_id);
                    $this->encrypt->fixed = \Phabel\Target\Php80\Polyfill::substr($nonce, 0, 4);
                    $this->encrypt->invocation_counter = \Phabel\Target\Php80\Polyfill::substr($nonce, 4, 8);
                case 'chacha20-poly1305@openssh.com':
                    break;
                default:
                    $this->encrypt->enableContinuousBuffer();
            }
            $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'C' . $this->session_id);
            while ($encryptKeyLength > strlen($key)) {
                $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
            }
            switch ($encrypt) {
                case 'chacha20-poly1305@openssh.com':
                    $encryptKeyLength = 32;
                    $this->lengthEncrypt = self::encryption_algorithm_to_crypt_instance($encrypt);
                    $this->lengthEncrypt->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 32, 32));
            }
            $this->encrypt->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $encryptKeyLength));
            $this->encrypt->name = $encrypt;
        }
        $this->decrypt = self::encryption_algorithm_to_crypt_instance($decrypt);
        if ($this->decrypt) {
            if (self::$crypto_engine) {
                $this->decrypt->setPreferredEngine(self::$crypto_engine);
            }
            if ($this->decrypt->getBlockLengthInBytes()) {
                $this->decrypt_block_size = $this->decrypt->getBlockLengthInBytes();
            }
            $this->decrypt->disablePadding();
            if ($this->decrypt->usesIV()) {
                $iv = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
                while ($this->decrypt_block_size > strlen($iv)) {
                    $iv .= $kexHash->hash($keyBytes . $this->exchange_hash . $iv);
                }
                $this->decrypt->setIV(\Phabel\Target\Php80\Polyfill::substr($iv, 0, $this->decrypt_block_size));
            }
            switch ($decrypt) {
                case 'aes128-gcm@openssh.com':
                case 'aes256-gcm@openssh.com':
                    // see https://tools.ietf.org/html/rfc5647#section-7.1
                    $nonce = $kexHash->hash($keyBytes . $this->exchange_hash . 'B' . $this->session_id);
                    $this->decrypt->fixed = \Phabel\Target\Php80\Polyfill::substr($nonce, 0, 4);
                    $this->decrypt->invocation_counter = \Phabel\Target\Php80\Polyfill::substr($nonce, 4, 8);
                case 'chacha20-poly1305@openssh.com':
                    break;
                default:
                    $this->decrypt->enableContinuousBuffer();
            }
            $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'D' . $this->session_id);
            while ($decryptKeyLength > strlen($key)) {
                $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
            }
            switch ($decrypt) {
                case 'chacha20-poly1305@openssh.com':
                    $decryptKeyLength = 32;
                    $this->lengthDecrypt = self::encryption_algorithm_to_crypt_instance($decrypt);
                    $this->lengthDecrypt->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 32, 32));
            }
            $this->decrypt->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $decryptKeyLength));
            $this->decrypt->name = $decrypt;
        }
        /* The "arcfour128" algorithm is the RC4 cipher, as described in
                   [SCHNEIER], using a 128-bit key.  The first 1536 bytes of keystream
                   generated by the cipher MUST be discarded, and the first byte of the
                   first encrypted packet MUST be encrypted using the 1537th byte of
                   keystream.
        
                   -- http://tools.ietf.org/html/rfc4345#section-4 */
        if ($encrypt == 'arcfour128' || $encrypt == 'arcfour256') {
            $this->encrypt->encrypt(str_repeat("\x00", 1536));
        }
        if ($decrypt == 'arcfour128' || $decrypt == 'arcfour256') {
            $this->decrypt->decrypt(str_repeat("\x00", 1536));
        }
        if (!$this->encrypt->usesNonce()) {
            list($this->hmac_create, $createKeyLength) = self::mac_algorithm_to_hash_instance($mac_algorithm_out);
        } else {
            $this->hmac_create = new \stdClass();
            $this->hmac_create->name = $mac_algorithm_out;
            //$mac_algorithm_out = 'none';
            $createKeyLength = 0;
        }
        if ($this->hmac_create instanceof Hash) {
            $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'E' . $this->session_id);
            while ($createKeyLength > strlen($key)) {
                $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
            }
            $this->hmac_create->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $createKeyLength));
            $this->hmac_create->name = $mac_algorithm_out;
            $this->hmac_create->etm = preg_match('#-etm@openssh\\.com$#', $mac_algorithm_out);
        }
        if (!$this->decrypt->usesNonce()) {
            list($this->hmac_check, $checkKeyLength) = self::mac_algorithm_to_hash_instance($mac_algorithm_in);
            $this->hmac_size = $this->hmac_check->getLengthInBytes();
        } else {
            $this->hmac_check = new \stdClass();
            $this->hmac_check->name = $mac_algorithm_in;
            //$mac_algorithm_in = 'none';
            $checkKeyLength = 0;
            $this->hmac_size = 0;
        }
        if ($this->hmac_check instanceof Hash) {
            $key = $kexHash->hash($keyBytes . $this->exchange_hash . 'F' . $this->session_id);
            while ($checkKeyLength > strlen($key)) {
                $key .= $kexHash->hash($keyBytes . $this->exchange_hash . $key);
            }
            $this->hmac_check->setKey(\Phabel\Target\Php80\Polyfill::substr($key, 0, $checkKeyLength));
            $this->hmac_check->name = $mac_algorithm_in;
            $this->hmac_check->etm = preg_match('#-etm@openssh\\.com$#', $mac_algorithm_in);
        }
        $this->regenerate_compression_context = $this->regenerate_decompression_context = true;
        return true;
    }
    /**
     * Maps an encryption algorithm name to the number of key bytes.
     *
     * @param string $algorithm Name of the encryption algorithm
     * @return (int | null) Number of bytes as an integer or null for unknown
     * @access private
     */
    private function encryption_algorithm_to_key_size($algorithm)
    {
        if ($this->bad_key_size_fix && self::bad_algorithm_candidate($algorithm)) {
            return 16;
        }
        switch ($algorithm) {
            case 'none':
                return 0;
            case 'aes128-gcm@openssh.com':
            case 'aes128-cbc':
            case 'aes128-ctr':
            case 'arcfour':
            case 'arcfour128':
            case 'blowfish-cbc':
            case 'blowfish-ctr':
            case 'twofish128-cbc':
            case 'twofish128-ctr':
                return 16;
            case '3des-cbc':
            case '3des-ctr':
            case 'aes192-cbc':
            case 'aes192-ctr':
            case 'twofish192-cbc':
            case 'twofish192-ctr':
                return 24;
            case 'aes256-gcm@openssh.com':
            case 'aes256-cbc':
            case 'aes256-ctr':
            case 'arcfour256':
            case 'twofish-cbc':
            case 'twofish256-cbc':
            case 'twofish256-ctr':
                return 32;
            case 'chacha20-poly1305@openssh.com':
                return 64;
        }
        return null;
    }
    /**
    * Maps an encryption algorithm name to an instance of a subclass of
    \phpseclib3\Crypt\Common\SymmetricKey.
    *
    * @param string $algorithm Name of the encryption algorithm
    * @return mixed Instance of \phpseclib3\Crypt\Common\SymmetricKey or null for unknown
    * @access private
    */
    private static function encryption_algorithm_to_crypt_instance($algorithm)
    {
        switch ($algorithm) {
            case '3des-cbc':
                return new TripleDES('cbc');
            case '3des-ctr':
                return new TripleDES('ctr');
            case 'aes256-cbc':
            case 'aes192-cbc':
            case 'aes128-cbc':
                return new Rijndael('cbc');
            case 'aes256-ctr':
            case 'aes192-ctr':
            case 'aes128-ctr':
                return new Rijndael('ctr');
            case 'blowfish-cbc':
                return new Blowfish('cbc');
            case 'blowfish-ctr':
                return new Blowfish('ctr');
            case 'twofish128-cbc':
            case 'twofish192-cbc':
            case 'twofish256-cbc':
            case 'twofish-cbc':
                return new Twofish('cbc');
            case 'twofish128-ctr':
            case 'twofish192-ctr':
            case 'twofish256-ctr':
                return new Twofish('ctr');
            case 'arcfour':
            case 'arcfour128':
            case 'arcfour256':
                return new RC4();
            case 'aes128-gcm@openssh.com':
            case 'aes256-gcm@openssh.com':
                return new Rijndael('gcm');
            case 'chacha20-poly1305@openssh.com':
                return new ChaCha20();
        }
        return null;
    }
    /**
    * Maps an encryption algorithm name to an instance of a subclass of
    \phpseclib3\Crypt\Hash.
    *
    * @param string $algorithm Name of the encryption algorithm
    * @return mixed Instance of \phpseclib3\Crypt\Hash or null for unknown
    * @access private
    */
    private static function mac_algorithm_to_hash_instance($algorithm)
    {
        switch ($algorithm) {
            case 'umac-64@openssh.com':
            case 'umac-64-etm@openssh.com':
                return [new Hash('umac-64'), 16];
            case 'umac-128@openssh.com':
            case 'umac-128-etm@openssh.com':
                return [new Hash('umac-128'), 16];
            case 'hmac-sha2-512':
            case 'hmac-sha2-512-etm@openssh.com':
                return [new Hash('sha512'), 64];
            case 'hmac-sha2-256':
            case 'hmac-sha2-256-etm@openssh.com':
                return [new Hash('sha256'), 32];
            case 'hmac-sha1':
            case 'hmac-sha1-etm@openssh.com':
                return [new Hash('sha1'), 20];
            case 'hmac-sha1-96':
                return [new Hash('sha1-96'), 20];
            case 'hmac-md5':
                return [new Hash('md5'), 16];
            case 'hmac-md5-96':
                return [new Hash('md5-96'), 16];
        }
    }
    /*
     * Tests whether or not proposed algorithm has a potential for issues
     *
     * @link https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/ssh2-aesctr-openssh.html
     * @link https://bugzilla.mindrot.org/show_bug.cgi?id=1291
     * @param string $algorithm Name of the encryption algorithm
     * @return bool
     * @access private
     */
    /**
     *
     */
    private static function bad_algorithm_candidate($algorithm)
    {
        switch ($algorithm) {
            case 'arcfour256':
            case 'aes192-ctr':
            case 'aes256-ctr':
                return true;
        }
        return false;
    }
    /**
     * Login
     *
     * The $password parameter can be a plaintext password, a \phpseclib3\Crypt\RSA|EC|DSA object, a \phpseclib3\System\SSH\Agent object or an array
     *
     * @param string $username
     * @param (string | AsymmetricKey | array[] | Agent | null) ...$args
     * @return bool
     * @see self::_login()
     * @access public
     */
    public function login($username, ...$args)
    {
        $this->auth[] = func_get_args();
        // try logging with 'none' as an authentication method first since that's what
        // PuTTY does
        if (\Phabel\Target\Php80\Polyfill::substr($this->server_identifier, 0, 15) != 'SSH-2.0-CoreFTP' && $this->auth_methods_to_continue === null) {
            if ($this->sublogin($username)) {
                return true;
            }
            if (!count($args)) {
                return false;
            }
        }
        return $this->sublogin($username, ...$args);
    }
    /**
     * Login Helper
     *
     * @param string $username
     * @param string[] ...$args
     * @return bool
     * @see self::_login_helper()
     * @access private
     */
    protected function sublogin($username, ...$args)
    {
        if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
            $this->connect();
        }
        if (empty($args)) {
            return $this->login_helper($username);
        }
        while (count($args)) {
            if (!$this->auth_methods_to_continue || !$this->smartMFA) {
                $newargs = $args;
                $args = [];
            } else {
                $newargs = [];
                foreach ($this->auth_methods_to_continue as $method) {
                    switch ($method) {
                        case 'publickey':
                            foreach ($args as $key => $arg) {
                                if ($arg instanceof PrivateKey || $arg instanceof Agent) {
                                    $newargs[] = $arg;
                                    unset($args[$key]);
                                    break;
                                }
                            }
                            break;
                        case 'keyboard-interactive':
                            $hasArray = $hasString = false;
                            foreach ($args as $arg) {
                                if ($hasArray || is_array($arg)) {
                                    $hasArray = true;
                                    break;
                                }
                                if ($hasString || is_string($arg)) {
                                    $hasString = true;
                                    break;
                                }
                            }
                            if ($hasArray && $hasString) {
                                foreach ($args as $key => $arg) {
                                    if (is_array($arg)) {
                                        $newargs[] = $arg;
                                        break 2;
                                    }
                                }
                            }
                        case 'password':
                            foreach ($args as $key => $arg) {
                                $newargs[] = $arg;
                                unset($args[$key]);
                                break;
                            }
                    }
                }
            }
            foreach ($newargs as $arg) {
                if ($this->login_helper($username, $arg)) {
                    return true;
                }
            }
        }
        return false;
    }
    /**
    * Login Helper
    *
    * {@internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
    by sending dummy SSH_MSG_IGNORE messages.}
    *
    * @param string $username
    * @param (string | AsymmetricKey | array[] | Agent | null) ...$args
    * @return bool
    * @throws \UnexpectedValueException on receipt of unexpected packets
    * @throws \RuntimeException on other errors
    * @access private
    */
    private function login_helper($username, $password = null)
    {
        if (!($this->bitmap & self::MASK_CONNECTED)) {
            return false;
        }
        if (!($this->bitmap & self::MASK_LOGIN_REQ)) {
            $packet = Strings::packSSH2('Cs', NET_SSH2_MSG_SERVICE_REQUEST, 'ssh-userauth');
            $this->send_binary_packet($packet);
            try {
                $response = $this->get_binary_packet();
            } catch (\Exception $e) {
                if ($this->retry_connect) {
                    $this->retry_connect = false;
                    $this->connect();
                    return $this->login_helper($username, $password);
                }
                $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST);
                throw new ConnectionClosedException('Connection closed by server');
            }
            list($type, $service) = Strings::unpackSSH2('Cs', $response);
            if ($type != NET_SSH2_MSG_SERVICE_ACCEPT || $service != 'ssh-userauth') {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_PROTOCOL_ERROR);
                throw new \UnexpectedValueException('Expected SSH_MSG_SERVICE_ACCEPT');
            }
            $this->bitmap |= self::MASK_LOGIN_REQ;
        }
        if (strlen($this->last_interactive_response)) {
            return !is_string($password) && !is_array($password) ? false : $this->keyboard_interactive_process($password);
        }
        if ($password instanceof PrivateKey) {
            return $this->privatekey_login($username, $password);
        }
        if ($password instanceof Agent) {
            return $this->ssh_agent_login($username, $password);
        }
        if (is_array($password)) {
            if ($this->keyboard_interactive_login($username, $password)) {
                $this->bitmap |= self::MASK_LOGIN;
                return true;
            }
            return false;
        }
        if (!isset($password)) {
            $packet = Strings::packSSH2('Cs3', NET_SSH2_MSG_USERAUTH_REQUEST, $username, 'ssh-connection', 'none');
            $this->send_binary_packet($packet);
            $response = $this->get_binary_packet();
            list($type) = Strings::unpackSSH2('C', $response);
            switch ($type) {
                case NET_SSH2_MSG_USERAUTH_SUCCESS:
                    $this->bitmap |= self::MASK_LOGIN;
                    return true;
                case NET_SSH2_MSG_USERAUTH_FAILURE:
                    list($auth_methods) = Strings::unpackSSH2('L', $response);
                    $this->auth_methods_to_continue = $auth_methods;
                default:
                    return false;
            }
        }
        if (!is_string($password)) {
            throw new \UnexpectedValueException('$password needs to either be an instance of \\phpseclib3\\Crypt\\Common\\PrivateKey, \\System\\SSH\\Agent, an array or a string');
        }
        $packet = Strings::packSSH2('Cs3bs', NET_SSH2_MSG_USERAUTH_REQUEST, $username, 'ssh-connection', 'password', false, $password);
        // remove the username and password from the logged packet
        if (!defined('NET_SSH2_LOGGING')) {
            $logged = null;
        } else {
            $logged = Strings::packSSH2('Cs3bs', NET_SSH2_MSG_USERAUTH_REQUEST, $username, 'ssh-connection', 'password', false, 'password');
        }
        $this->send_binary_packet($packet, $logged);
        $response = $this->get_binary_packet();
        list($type) = Strings::unpackSSH2('C', $response);
        switch ($type) {
            case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ:
                // in theory, the password can be changed
                $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ');
                list($message) = Strings::unpackSSH2('s', $response);
                $this->errors[] = 'SSH_MSG_USERAUTH_PASSWD_CHANGEREQ: ' . $message;
                return $this->disconnect_helper(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
            case NET_SSH2_MSG_USERAUTH_FAILURE:
                // can we use keyboard-interactive authentication?  if not then either the login is bad or the server employees
                // multi-factor authentication
                list($auth_methods, $partial_success) = Strings::unpackSSH2('Lb', $response);
                $this->auth_methods_to_continue = $auth_methods;
                if (!$partial_success && in_array('keyboard-interactive', $auth_methods)) {
                    if ($this->keyboard_interactive_login($username, $password)) {
                        $this->bitmap |= self::MASK_LOGIN;
                        return true;
                    }
                    return false;
                }
                return false;
            case NET_SSH2_MSG_USERAUTH_SUCCESS:
                $this->bitmap |= self::MASK_LOGIN;
                return true;
        }
        return false;
    }
    /**
     * Login via keyboard-interactive authentication
     *
     * See {@link http://tools.ietf.org/html/rfc4256 RFC4256} for details.  This is not a full-featured keyboard-interactive authenticator.
     *
     * @param string $username
     * @param string $password
     * @return bool
     * @access private
     */
    private function keyboard_interactive_login($username, $password)
    {
        $packet = Strings::packSSH2(
            'Cs5',
            NET_SSH2_MSG_USERAUTH_REQUEST,
            $username,
            'ssh-connection',
            'keyboard-interactive',
            '',
            // language tag
            ''
        );
        $this->send_binary_packet($packet);
        return $this->keyboard_interactive_process($password);
    }
    /**
     * Handle the keyboard-interactive requests / responses.
     *
     * @param mixed[] ...$responses
     * @return bool
     * @throws \RuntimeException on connection error
     * @access private
     */
    private function keyboard_interactive_process(...$responses)
    {
        if (strlen($this->last_interactive_response)) {
            $response = $this->last_interactive_response;
        } else {
            $orig = $response = $this->get_binary_packet();
        }
        list($type) = Strings::unpackSSH2('C', $response);
        switch ($type) {
            case NET_SSH2_MSG_USERAUTH_INFO_REQUEST:
                list(, , , $num_prompts) = Strings::unpackSSH2('s3N', $response);
                for ($i = 0; $i < count($responses); $i++) {
                    if (is_array($responses[$i])) {
                        foreach ($responses[$i] as $key => $value) {
                            $this->keyboard_requests_responses[$key] = $value;
                        }
                        unset($responses[$i]);
                    }
                }
                $responses = array_values($responses);
                if (isset($this->keyboard_requests_responses)) {
                    for ($i = 0; $i < $num_prompts; $i++) {
                        list($prompt, ) = Strings::unpackSSH2('sC', $response);
                        foreach ($this->keyboard_requests_responses as $key => $value) {
                            if (\Phabel\Target\Php80\Polyfill::substr($prompt, 0, strlen($key)) == $key) {
                                $responses[] = $value;
                                break;
                            }
                        }
                    }
                }
                // see http://tools.ietf.org/html/rfc4256#section-3.2
                if (strlen($this->last_interactive_response)) {
                    $this->last_interactive_response = '';
                } else {
                    $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_INFO_REQUEST');
                }
                if (!count($responses) && $num_prompts) {
                    $this->last_interactive_response = $orig;
                    return false;
                }
                /*
                   After obtaining the requested information from the user, the client
                   MUST respond with an SSH_MSG_USERAUTH_INFO_RESPONSE message.
                */
                // see http://tools.ietf.org/html/rfc4256#section-3.4
                $packet = $logged = pack('CN', NET_SSH2_MSG_USERAUTH_INFO_RESPONSE, count($responses));
                for ($i = 0; $i < count($responses); $i++) {
                    $packet .= Strings::packSSH2('s', $responses[$i]);
                    $logged .= Strings::packSSH2('s', 'dummy-answer');
                }
                $this->send_binary_packet($packet, $logged);
                $this->updateLogHistory('UNKNOWN (61)', 'NET_SSH2_MSG_USERAUTH_INFO_RESPONSE');
                /*
                   After receiving the response, the server MUST send either an
                   SSH_MSG_USERAUTH_SUCCESS, SSH_MSG_USERAUTH_FAILURE, or another
                   SSH_MSG_USERAUTH_INFO_REQUEST message.
                */
                // maybe phpseclib should force close the connection after x request / responses?  unless something like that is done
                // there could be an infinite loop of request / responses.
                return $this->keyboard_interactive_process();
            case NET_SSH2_MSG_USERAUTH_SUCCESS:
                return true;
            case NET_SSH2_MSG_USERAUTH_FAILURE:
                list($auth_methods) = Strings::unpackSSH2('L', $response);
                $this->auth_methods_to_continue = $auth_methods;
                return false;
        }
        return false;
    }
    /**
     * Login with an ssh-agent provided key
     *
     * @param string $username
     * @param \phpseclib3\System\SSH\Agent $agent
     * @return bool
     * @access private
     */
    private function ssh_agent_login($username, Agent $agent)
    {
        $this->agent = $agent;
        $keys = $agent->requestIdentities();
        foreach ($keys as $key) {
            if ($this->privatekey_login($username, $key)) {
                return true;
            }
        }
        return false;
    }
    /**
    * Login with an RSA private key
    *
    * {@internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
    by sending dummy SSH_MSG_IGNORE messages.}
    *
    * @param string $username
    * @param \phpseclib3\Crypt\Common\PrivateKey $privatekey
    * @return bool
    * @throws \RuntimeException on connection error
    * @access private
    */
    private function privatekey_login($username, PrivateKey $privatekey)
    {
        $publickey = $privatekey->getPublicKey();
        if ($publickey instanceof RSA) {
            $privatekey = $privatekey->withPadding(RSA::SIGNATURE_PKCS1);
            $algos = ['rsa-sha2-256', 'rsa-sha2-512', 'ssh-rsa'];
            if (isset($this->preferred['hostkey'])) {
                $algos = array_intersect($this->preferred['hostkey'], $algos);
            }
            $algo = self::array_intersect_first($algos, $this->server_host_key_algorithms);
            switch ($algo) {
                case 'rsa-sha2-512':
                    $hash = 'sha512';
                    $signatureType = 'rsa-sha2-512';
                    break;
                case 'rsa-sha2-256':
                    $hash = 'sha256';
                    $signatureType = 'rsa-sha2-256';
                    break;
                //case 'ssh-rsa':
                default:
                    $hash = 'sha1';
                    $signatureType = 'ssh-rsa';
            }
        } else {
            if ($publickey instanceof EC) {
                $privatekey = $privatekey->withSignatureFormat('SSH2');
                $curveName = $privatekey->getCurve();
                switch ($curveName) {
                    case 'Ed25519':
                        $hash = 'sha512';
                        $signatureType = 'ssh-ed25519';
                        break;
                    case 'secp256r1':
                        // nistp256
                        $hash = 'sha256';
                        $signatureType = 'ecdsa-sha2-nistp256';
                        break;
                    case 'secp384r1':
                        // nistp384
                        $hash = 'sha384';
                        $signatureType = 'ecdsa-sha2-nistp384';
                        break;
                    case 'secp521r1':
                        // nistp521
                        $hash = 'sha512';
                        $signatureType = 'ecdsa-sha2-nistp521';
                        break;
                    default:
                        if (is_array($curveName)) {
                            throw new UnsupportedCurveException('Specified Curves are not supported by SSH2');
                        }
                        throw new UnsupportedCurveException('Named Curve of ' . $curveName . ' is not supported by phpseclib3\'s SSH2 implementation');
                }
            } else {
                if ($publickey instanceof DSA) {
                    $privatekey = $privatekey->withSignatureFormat('SSH2');
                    $hash = 'sha1';
                    $signatureType = 'ssh-dss';
                } else {
                    throw new UnsupportedAlgorithmException('Please use either an RSA key, an EC one or a DSA key');
                }
            }
        }
        $publickeyStr = $publickey->toString('OpenSSH', ['binary' => true]);
        $part1 = Strings::packSSH2('Csss', NET_SSH2_MSG_USERAUTH_REQUEST, $username, 'ssh-connection', 'publickey');
        $part2 = Strings::packSSH2('ss', $signatureType, $publickeyStr);
        $packet = $part1 . chr(0) . $part2;
        $this->send_binary_packet($packet);
        $response = $this->get_binary_packet();
        list($type) = Strings::unpackSSH2('C', $response);
        switch ($type) {
            case NET_SSH2_MSG_USERAUTH_FAILURE:
                list($auth_methods) = Strings::unpackSSH2('L', $response);
                $this->auth_methods_to_continue = $auth_methods;
                $this->errors[] = 'SSH_MSG_USERAUTH_FAILURE';
                return false;
            case NET_SSH2_MSG_USERAUTH_PK_OK:
                // we'll just take it on faith that the public key blob and the public key algorithm name are as
                // they should be
                $this->updateLogHistory('UNKNOWN (60)', 'NET_SSH2_MSG_USERAUTH_PK_OK');
                break;
            case NET_SSH2_MSG_USERAUTH_SUCCESS:
                $this->bitmap |= self::MASK_LOGIN;
                return true;
            default:
                $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                throw new ConnectionClosedException('Unexpected response to publickey authentication pt 1');
        }
        $packet = $part1 . chr(1) . $part2;
        $privatekey = $privatekey->withHash($hash);
        $signature = $privatekey->sign(Strings::packSSH2('s', $this->session_id) . $packet);
        if ($publickey instanceof RSA) {
            $signature = Strings::packSSH2('ss', $signatureType, $signature);
        }
        $packet .= Strings::packSSH2('s', $signature);
        $this->send_binary_packet($packet);
        $response = $this->get_binary_packet();
        list($type) = Strings::unpackSSH2('C', $response);
        switch ($type) {
            case NET_SSH2_MSG_USERAUTH_FAILURE:
                // either the login is bad or the server employs multi-factor authentication
                list($auth_methods) = Strings::unpackSSH2('L', $response);
                $this->auth_methods_to_continue = $auth_methods;
                return false;
            case NET_SSH2_MSG_USERAUTH_SUCCESS:
                $this->bitmap |= self::MASK_LOGIN;
                return true;
        }
        $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
        throw new ConnectionClosedException('Unexpected response to publickey authentication pt 2');
    }
    /**
    * Set Timeout
    *
    * $ssh->exec('ping 127.0.0.1'); on a Linux host will never return and will run indefinitely.  setTimeout() makes it so it'll timeout.
    Setting $timeout to false or 0 will mean there is no timeout.
    *
    * @param mixed $timeout
    * @access public
    */
    public function setTimeout($timeout)
    {
        $this->timeout = $this->curTimeout = $timeout;
    }
    /**
     * Set Keep Alive
     *
     * Sends an SSH2_MSG_IGNORE message every x seconds, if x is a positive non-zero number.
     *
     * @param int $interval
     * @access public
     */
    function setKeepAlive($interval)
    {
        $this->keepAlive = $interval;
    }
    /**
     * Get the output from stdError
     *
     * @access public
     */
    public function getStdError()
    {
        return $this->stdErrorLog;
    }
    /**
    * Execute Command
    *
    * If $callback is set to false then \phpseclib3\Net\SSH2::get_channel_packet(self::CHANNEL_EXEC) will need to be called manually.
    In all likelihood, this is not a feature you want to be taking advantage of.
    *
    * @param string $command
    * @param callback $callback
    * @return string
    * @throws \RuntimeException on connection error
    * @access public
    */
    public function exec($command, $callback = null)
    {
        $this->curTimeout = $this->timeout;
        $this->is_timeout = false;
        $this->stdErrorLog = '';
        if (!$this->isAuthenticated()) {
            return false;
        }
        if ($this->in_request_pty_exec) {
            throw new \RuntimeException('If you want to run multiple exec()\'s you will need to disable (and re-enable if appropriate) a PTY for each one.');
        }
        // RFC4254 defines the (client) window size as "bytes the other party can send before it must wait for the window to
        // be adjusted".  0x7FFFFFFF is, at 2GB, the max size.  technically, it should probably be decremented, but,
        // honestly, if you're transferring more than 2GB, you probably shouldn't be using phpseclib, anyway.
        // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
        $this->window_size_server_to_client[self::CHANNEL_EXEC] = $this->window_size;
        // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
        // uses 0x4000, that's what will be used here, as well.
        $packet_size = 0x4000;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL_EXEC, $this->window_size_server_to_client[self::CHANNEL_EXEC], $packet_size);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_OPEN;
        $this->get_channel_packet(self::CHANNEL_EXEC);
        if ($this->request_pty === true) {
            $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
            $packet = Strings::packSSH2('CNsCsN4s', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_EXEC], 'pty-req', 1, $this->term, $this->windowColumns, $this->windowRows, 0, 0, $terminal_modes);
            $this->send_binary_packet($packet);
            $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
            if (!$this->get_channel_packet(self::CHANNEL_EXEC)) {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                throw new \RuntimeException('Unable to request pseudo-terminal');
            }
            $this->in_request_pty_exec = true;
        }
        // sending a pty-req SSH_MSG_CHANNEL_REQUEST message is unnecessary and, in fact, in most cases, slows things
        // down.  the one place where it might be desirable is if you're doing something like \phpseclib3\Net\SSH2::exec('ping localhost &').
        // with a pty-req SSH_MSG_CHANNEL_REQUEST, exec() will return immediately and the ping process will then
        // then immediately terminate.  without such a request exec() will loop indefinitely.  the ping process won't end but
        // neither will your script.
        // although, in theory, the size of SSH_MSG_CHANNEL_REQUEST could exceed the maximum packet size established by
        // SSH_MSG_CHANNEL_OPEN_CONFIRMATION, RFC4254#section-5.1 states that the "maximum packet size" refers to the
        // "maximum size of an individual data packet". ie. SSH_MSG_CHANNEL_DATA.  RFC4254#section-5.2 corroborates.
        $packet = Strings::packSSH2('CNsCs', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_EXEC], 'exec', 1, $command);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_REQUEST;
        if (!$this->get_channel_packet(self::CHANNEL_EXEC)) {
            return false;
        }
        $this->channel_status[self::CHANNEL_EXEC] = NET_SSH2_MSG_CHANNEL_DATA;
        if ($callback === false || $this->in_request_pty_exec) {
            return true;
        }
        $output = '';
        while (true) {
            $temp = $this->get_channel_packet(self::CHANNEL_EXEC);
            switch (true) {
                case $temp === true:
                    return is_callable($callback) ? true : $output;
                case $temp === false:
                    return false;
                default:
                    if (is_callable($callback)) {
                        if ($callback($temp) === true) {
                            $this->close_channel(self::CHANNEL_EXEC);
                            return true;
                        }
                    } else {
                        $output .= $temp;
                    }
            }
        }
    }
    /**
     * Creates an interactive shell
     *
     * @see self::read()
     * @see self::write()
     * @return bool
     * @throws \UnexpectedValueException on receipt of unexpected packets
     * @throws \RuntimeException on other errors
     * @access private
     */
    private function initShell()
    {
        if ($this->in_request_pty_exec === true) {
            return true;
        }
        $this->window_size_server_to_client[self::CHANNEL_SHELL] = $this->window_size;
        $packet_size = 0x4000;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL_SHELL, $this->window_size_server_to_client[self::CHANNEL_SHELL], $packet_size);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_OPEN;
        $this->get_channel_packet(self::CHANNEL_SHELL);
        $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
        $packet = Strings::packSSH2(
            'CNsbsN4s',
            NET_SSH2_MSG_CHANNEL_REQUEST,
            $this->server_channels[self::CHANNEL_SHELL],
            'pty-req',
            true,
            // want reply
            $this->term,
            $this->windowColumns,
            $this->windowRows,
            0,
            0,
            $terminal_modes
        );
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_REQUEST;
        if (!$this->get_channel_packet(self::CHANNEL_SHELL)) {
            throw new \RuntimeException('Unable to request pty');
        }
        $packet = Strings::packSSH2('CNsb', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_SHELL], 'shell', true);
        $this->send_binary_packet($packet);
        $response = $this->get_channel_packet(self::CHANNEL_SHELL);
        if ($response === false) {
            throw new \RuntimeException('Unable to request shell');
        }
        $this->channel_status[self::CHANNEL_SHELL] = NET_SSH2_MSG_CHANNEL_DATA;
        $this->bitmap |= self::MASK_SHELL;
        return true;
    }
    /**
     * Return the channel to be used with read() / write()
     *
     * @see self::read()
     * @see self::write()
     * @return int
     * @access public
     */
    private function get_interactive_channel()
    {
        switch (true) {
            case $this->in_subsystem:
                return self::CHANNEL_SUBSYSTEM;
            case $this->in_request_pty_exec:
                return self::CHANNEL_EXEC;
            default:
                return self::CHANNEL_SHELL;
        }
    }
    /**
     * Return an available open channel
     *
     * @return int
     * @access public
     */
    private function get_open_channel()
    {
        $channel = self::CHANNEL_EXEC;
        do {
            if (isset($this->channel_status[$channel]) && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_OPEN) {
                return $channel;
            }
        } while ($channel++ < self::CHANNEL_SUBSYSTEM);
        return false;
    }
    /**
     * Request agent forwarding of remote server
     *
     * @return bool
     * @access public
     */
    public function requestAgentForwarding()
    {
        $request_channel = $this->get_open_channel();
        if ($request_channel === false) {
            return false;
        }
        $packet = Strings::packSSH2('CNsC', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[$request_channel], 'auth-agent-req@openssh.com', 1);
        $this->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_REQUEST;
        $this->send_binary_packet($packet);
        if (!$this->get_channel_packet($request_channel)) {
            return false;
        }
        $this->channel_status[$request_channel] = NET_SSH2_MSG_CHANNEL_OPEN;
        return true;
    }
    /**
    * Returns the output of an interactive shell
    *
    * Returns when there's a match for $expect, which can take the form of a string literal or,
    if $mode == self::READ_REGEX, a regular expression.
    *
    * @see self::write()
    * @param string $expect
    * @param int $mode
    * @return (string | bool | null)
    * @throws \RuntimeException on connection error
    * @access public
    */
    public function read($expect = '', $mode = self::READ_SIMPLE)
    {
        $this->curTimeout = $this->timeout;
        $this->is_timeout = false;
        if (!$this->isAuthenticated()) {
            throw new InsufficientSetupException('Operation disallowed prior to login()');
        }
        if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) {
            throw new \RuntimeException('Unable to initiate an interactive shell session');
        }
        $channel = $this->get_interactive_channel();
        if ($mode == self::READ_NEXT) {
            return $this->get_channel_packet($channel);
        }
        $match = $expect;
        while (true) {
            if ($mode == self::READ_REGEX) {
                preg_match($expect, \Phabel\Target\Php80\Polyfill::substr($this->interactiveBuffer, -1024), $matches);
                $match = isset($matches[0]) ? $matches[0] : '';
            }
            $pos = strlen($match) ? strpos($this->interactiveBuffer, $match) : false;
            if ($pos !== false) {
                return Strings::shift($this->interactiveBuffer, $pos + strlen($match));
            }
            $response = $this->get_channel_packet($channel);
            if ($response === true) {
                $this->in_request_pty_exec = false;
                return Strings::shift($this->interactiveBuffer, strlen($this->interactiveBuffer));
            }
            $this->interactiveBuffer .= $response;
        }
    }
    /**
     * Inputs a command into an interactive shell.
     *
     * @see self::read()
     * @param string $cmd
     * @return bool
     * @throws \RuntimeException on connection error
     * @access public
     */
    public function write($cmd)
    {
        if (!$this->isAuthenticated()) {
            throw new InsufficientSetupException('Operation disallowed prior to login()');
        }
        if (!($this->bitmap & self::MASK_SHELL) && !$this->initShell()) {
            throw new \RuntimeException('Unable to initiate an interactive shell session');
        }
        return $this->send_channel_packet($this->get_interactive_channel(), $cmd);
    }
    /**
    * Start a subsystem.
    *
    * Right now only one subsystem at a time is supported. To support multiple subsystem's stopSubsystem() could accept
    a string that contained the name of the subsystem, but at that point, only one subsystem of each type could be opened.
    To support multiple subsystem's of the same name maybe it'd be best if startSubsystem() generated a new channel id and
    returns that and then that that was passed into stopSubsystem() but that'll be saved for a future date and implemented
    if there's sufficient demand for such a feature.
    *
    * @see self::stopSubsystem()
    * @param string $subsystem
    * @return bool
    * @access public
    */
    public function startSubsystem($subsystem)
    {
        $this->window_size_server_to_client[self::CHANNEL_SUBSYSTEM] = $this->window_size;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL_SUBSYSTEM, $this->window_size, 0x4000);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_OPEN;
        $this->get_channel_packet(self::CHANNEL_SUBSYSTEM);
        $packet = Strings::packSSH2('CNsCs', NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channels[self::CHANNEL_SUBSYSTEM], 'subsystem', 1, $subsystem);
        $this->send_binary_packet($packet);
        $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_REQUEST;
        if (!$this->get_channel_packet(self::CHANNEL_SUBSYSTEM)) {
            return false;
        }
        $this->channel_status[self::CHANNEL_SUBSYSTEM] = NET_SSH2_MSG_CHANNEL_DATA;
        $this->bitmap |= self::MASK_SHELL;
        $this->in_subsystem = true;
        return true;
    }
    /**
     * Stops a subsystem.
     *
     * @see self::startSubsystem()
     * @return bool
     * @access public
     */
    public function stopSubsystem()
    {
        $this->in_subsystem = false;
        $this->close_channel(self::CHANNEL_SUBSYSTEM);
        return true;
    }
    /**
     * Closes a channel
     *
     * If read() timed out you might want to just close the channel and have it auto-restart on the next read() call
     *
     * @access public
     */
    public function reset()
    {
        $this->close_channel($this->get_interactive_channel());
    }
    /**
     * Is timeout?
     *
     * Did exec() or read() return because they timed out or because they encountered the end?
     *
     * @access public
     */
    public function isTimeout()
    {
        return $this->is_timeout;
    }
    /**
     * Disconnect
     *
     * @access public
     */
    public function disconnect()
    {
        $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
        if (isset($this->realtime_log_file) && is_resource($this->realtime_log_file)) {
            fclose($this->realtime_log_file);
        }
        unset(self::$connections[$this->getResourceId()]);
    }
    /**
    * Destructor.
    *
    * Will be called, automatically, if you're supporting just PHP5.  If you're supporting PHP4, you'll need to call
    disconnect().
    *
    * @access public
    */
    public function __destruct()
    {
        $this->disconnect();
    }
    /**
     * Is the connection still active?
     *
     * @return bool
     * @access public
     */
    public function isConnected()
    {
        return (bool) ($this->bitmap & self::MASK_CONNECTED);
    }
    /**
     * Have you successfully been logged in?
     *
     * @return bool
     * @access public
     */
    public function isAuthenticated()
    {
        return (bool) ($this->bitmap & self::MASK_LOGIN);
    }
    /**
     * Pings a server connection, or tries to reconnect if the connection has gone down
     *
     * Inspired by http://php.net/manual/en/mysqli.ping.php
     *
     * @return bool
     */
    public function ping()
    {
        if (!$this->isAuthenticated()) {
            if (!empty($this->auth)) {
                return $this->reconnect();
            }
            return false;
        }
        $this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE] = $this->window_size;
        $packet_size = 0x4000;
        $packet = Strings::packSSH2('CsN3', NET_SSH2_MSG_CHANNEL_OPEN, 'session', self::CHANNEL_KEEP_ALIVE, $this->window_size_server_to_client[self::CHANNEL_KEEP_ALIVE], $packet_size);
        try {
            $this->send_binary_packet($packet);
            $this->channel_status[self::CHANNEL_KEEP_ALIVE] = NET_SSH2_MSG_CHANNEL_OPEN;
            $response = $this->get_channel_packet(self::CHANNEL_KEEP_ALIVE);
        } catch (\RuntimeException $e) {
            return $this->reconnect();
        }
        $this->close_channel(self::CHANNEL_KEEP_ALIVE);
        return true;
    }
    /**
     * In situ reconnect method
     *
     * @return boolean
     */
    private function reconnect()
    {
        $this->reset_connection(NET_SSH2_DISCONNECT_CONNECTION_LOST);
        $this->retry_connect = true;
        $this->connect();
        foreach ($this->auth as $auth) {
            $result = $this->login(...$auth);
        }
        return $result;
    }
    /**
     * Resets a connection for re-use
     *
     * @param int $reason
     * @access private
     */
    protected function reset_connection($reason)
    {
        $this->disconnect_helper($reason);
        $this->decrypt = $this->encrypt = false;
        $this->decrypt_block_size = $this->encrypt_block_size = 8;
        $this->hmac_check = $this->hmac_create = false;
        $this->hmac_size = false;
        $this->session_id = false;
        $this->retry_connect = true;
        $this->get_seq_no = $this->send_seq_no = 0;
    }
    /**
     * Gets Binary Packets
     *
     * See '6. Binary Packet Protocol' of rfc4253 for more info.
     *
     * @see self::_send_binary_packet()
     * @param bool $skip_channel_filter
     * @return string
     * @access private
     */
    private function get_binary_packet($skip_channel_filter = false)
    {
        if ($skip_channel_filter) {
            $read = [$this->fsock];
            $write = $except = null;
            if (!$this->curTimeout) {
                if ($this->keepAlive <= 0) {
                    @stream_select($read, $write, $except, null);
                } else {
                    if (!@stream_select($read, $write, $except, $this->keepAlive)) {
                        $this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
                        return $this->get_binary_packet(true);
                    }
                }
            } else {
                if ($this->curTimeout < 0) {
                    $this->is_timeout = true;
                    return true;
                }
                $read = [$this->fsock];
                $write = $except = null;
                $start = microtime(true);
                if ($this->keepAlive > 0 && $this->keepAlive < $this->curTimeout) {
                    if (!@stream_select($read, $write, $except, $this->keepAlive)) {
                        $this->send_binary_packet(pack('CN', NET_SSH2_MSG_IGNORE, 0));
                        $elapsed = microtime(true) - $start;
                        $this->curTimeout -= $elapsed;
                        return $this->get_binary_packet(true);
                    }
                    $elapsed = microtime(true) - $start;
                    $this->curTimeout -= $elapsed;
                }
                $sec = floor($this->curTimeout);
                $usec = 1000000 * ($this->curTimeout - $sec);
                // this can return a "stream_select(): unable to select [4]: Interrupted system call" error
                if (!@stream_select($read, $write, $except, $sec, $usec)) {
                    $this->is_timeout = true;
                    return true;
                }
                $elapsed = microtime(true) - $start;
                $this->curTimeout -= $elapsed;
            }
        }
        if (!is_resource($this->fsock) || feof($this->fsock)) {
            $this->bitmap = 0;
            throw new ConnectionClosedException('Connection closed (by server) prematurely ' . $elapsed . 's');
        }
        $start = microtime(true);
        $raw = stream_get_contents($this->fsock, $this->decrypt_block_size);
        if (!strlen($raw)) {
            $this->bitmap = 0;
            throw new ConnectionClosedException('No data received from server');
        }
        if ($this->decrypt) {
            switch ($this->decrypt->name) {
                case 'aes128-gcm@openssh.com':
                case 'aes256-gcm@openssh.com':
                    $this->decrypt->setNonce($this->decrypt->fixed . $this->decrypt->invocation_counter);
                    Strings::increment_str($this->decrypt->invocation_counter);
                    $this->decrypt->setAAD($temp = Strings::shift($raw, 4));
                    extract(unpack('Npacket_length', $temp));
                    /**
                     * @var integer $packet_length
                     */
                    $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4);
                    $stop = microtime(true);
                    $tag = stream_get_contents($this->fsock, $this->decrypt_block_size);
                    $this->decrypt->setTag($tag);
                    $raw = $this->decrypt->decrypt($raw);
                    $raw = $temp . $raw;
                    $remaining_length = 0;
                    break;
                case 'chacha20-poly1305@openssh.com':
                    $nonce = pack('N2', 0, $this->get_seq_no);
                    $this->lengthDecrypt->setNonce($nonce);
                    $temp = $this->lengthDecrypt->decrypt($aad = Strings::shift($raw, 4));
                    extract(unpack('Npacket_length', $temp));
                    /**
                     * @var integer $packet_length
                     */
                    $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4);
                    $stop = microtime(true);
                    $tag = stream_get_contents($this->fsock, 16);
                    $this->decrypt->setNonce($nonce);
                    $this->decrypt->setCounter(0);
                    // this is the same approach that's implemented in Salsa20::createPoly1305Key()
                    // but we don't want to use the same AEAD construction that RFC8439 describes
                    // for ChaCha20-Poly1305 so we won't rely on it (see Salsa20::poly1305())
                    $this->decrypt->setPoly1305Key($this->decrypt->encrypt(str_repeat("\x00", 32)));
                    $this->decrypt->setAAD($aad);
                    $this->decrypt->setCounter(1);
                    $this->decrypt->setTag($tag);
                    $raw = $this->decrypt->decrypt($raw);
                    $raw = $temp . $raw;
                    $remaining_length = 0;
                    break;
                default:
                    if (!$this->hmac_check instanceof Hash || !$this->hmac_check->etm) {
                        $raw = $this->decrypt->decrypt($raw);
                        break;
                    }
                    extract(unpack('Npacket_length', $temp = Strings::shift($raw, 4)));
                    /**
                     * @var integer $packet_length
                     */
                    $raw .= $this->read_remaining_bytes($packet_length - $this->decrypt_block_size + 4);
                    $stop = microtime(true);
                    $encrypted = $temp . $raw;
                    $raw = $temp . $this->decrypt->decrypt($raw);
                    $remaining_length = 0;
            }
        }
        if (strlen($raw) < 5) {
            $this->bitmap = 0;
            throw new \RuntimeException('Plaintext is too short');
        }
        extract(unpack('Npacket_length/Cpadding_length', Strings::shift($raw, 5)));
        /**
         * @var integer $packet_length
         * @var integer $padding_length
         */
        if (!isset($remaining_length)) {
            $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
        }
        $buffer = $this->read_remaining_bytes($remaining_length);
        if (!isset($stop)) {
            $stop = microtime(true);
        }
        if (strlen($buffer)) {
            $raw .= $this->decrypt ? $this->decrypt->decrypt($buffer) : $buffer;
        }
        $payload = Strings::shift($raw, $packet_length - $padding_length - 1);
        $padding = Strings::shift($raw, $padding_length);
        // should leave $raw empty
        if ($this->hmac_check instanceof Hash) {
            $hmac = stream_get_contents($this->fsock, $this->hmac_size);
            if ($hmac === false || strlen($hmac) != $this->hmac_size) {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR);
                throw new \RuntimeException('Error reading socket');
            }
            $reconstructed = !$this->hmac_check->etm ? pack('NCa*', $packet_length, $padding_length, $payload . $padding) : $encrypted;
            if (($this->hmac_check->getHash() & "\xff\xff\xff\xff") == 'umac') {
                $this->hmac_check->setNonce("\x00\x00\x00\x00" . pack('N', $this->get_seq_no));
                if ($hmac != $this->hmac_check->hash($reconstructed)) {
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR);
                    throw new \RuntimeException('Invalid UMAC');
                }
            } else {
                if ($hmac != $this->hmac_check->hash(pack('Na*', $this->get_seq_no, $reconstructed))) {
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_MAC_ERROR);
                    throw new \RuntimeException('Invalid HMAC');
                }
            }
        }
        switch ($this->decompress) {
            case NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH:
                if (!$this->isAuthenticated()) {
                    break;
                }
            case NET_SSH2_COMPRESSION_ZLIB:
                if ($this->regenerate_decompression_context) {
                    $this->regenerate_decompression_context = false;
                    $cmf = ord($payload[0]);
                    $cm = $cmf & 0xf;
                    if ($cm != 8) {
                        // deflate
                        user_error("Only CM = 8 ('deflate') is supported ({$cm})");
                    }
                    $cinfo = ($cmf & 0xf0) >> 4;
                    if ($cinfo > 7) {
                        user_error("CINFO above 7 is not allowed ({$cinfo})");
                    }
                    $windowSize = 1 << $cinfo + 8;
                    $flg = ord($payload[1]);
                    //$fcheck = $flg && 0x0F;
                    if (($cmf << 8 | $flg) % 31) {
                        user_error('fcheck failed');
                    }
                    $fdict = boolval($flg & 0x20);
                    $flevel = ($flg & 0xc0) >> 6;
                    $this->decompress_context = inflate_init(ZLIB_ENCODING_RAW, ['window' => $cinfo + 8]);
                    $payload = \Phabel\Target\Php80\Polyfill::substr($payload, 2);
                }
                if ($this->decompress_context) {
                    $payload = inflate_add($this->decompress_context, $payload, ZLIB_PARTIAL_FLUSH);
                }
        }
        $this->get_seq_no++;
        if (defined('NET_SSH2_LOGGING')) {
            $current = microtime(true);
            $message_number = isset($this->message_numbers[ord($payload[0])]) ? $this->message_numbers[ord($payload[0])] : 'UNKNOWN (' . ord($payload[0]) . ')';
            $message_number = '<- ' . $message_number . ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
            $this->append_log($message_number, $payload);
            $this->last_packet = $current;
        }
        return $this->filter($payload, $skip_channel_filter);
    }
    /**
     * Read Remaining Bytes
     *
     * @see self::get_binary_packet()
     * @param int $remaining_length
     * @return string
     * @access private
     */
    private function read_remaining_bytes($remaining_length)
    {
        if (!$remaining_length) {
            return '';
        }
        $adjustLength = false;
        if ($this->decrypt) {
            switch (true) {
                case $this->decrypt->name == 'aes128-gcm@openssh.com':
                case $this->decrypt->name == 'aes256-gcm@openssh.com':
                case $this->decrypt->name == 'chacha20-poly1305@openssh.com':
                case $this->hmac_check instanceof Hash && $this->hmac_check->etm:
                    $remaining_length += $this->decrypt_block_size - 4;
                    $adjustLength = true;
            }
        }
        // quoting <http://tools.ietf.org/html/rfc4253#section-6.1>,
        // "implementations SHOULD check that the packet length is reasonable"
        // PuTTY uses 0x9000 as the actual max packet size and so to shall we
        // don't do this when GCM mode is used since GCM mode doesn't encrypt the length
        if ($remaining_length < -$this->decrypt_block_size || $remaining_length > 0x9000 || $remaining_length % $this->decrypt_block_size != 0) {
            if (!$this->bad_key_size_fix && self::bad_algorithm_candidate($this->decrypt ? $this->decrypt->name : '') && !($this->bitmap & SSH2::MASK_LOGIN)) {
                $this->bad_key_size_fix = true;
                $this->reset_connection(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
                return false;
            }
            throw new \RuntimeException('Invalid size');
        }
        if ($adjustLength) {
            $remaining_length -= $this->decrypt_block_size - 4;
        }
        $buffer = '';
        while ($remaining_length > 0) {
            $temp = stream_get_contents($this->fsock, $remaining_length);
            if ($temp === false || feof($this->fsock)) {
                $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST);
                throw new \RuntimeException('Error reading from socket');
            }
            $buffer .= $temp;
            $remaining_length -= strlen($temp);
        }
        return $buffer;
    }
    /**
     * Filter Binary Packets
     *
     * Because some binary packets need to be ignored...
     *
     * @see self::_get_binary_packet()
     * @param string $payload
     * @param bool $skip_channel_filter
     * @return string
     * @access private
     */
    private function filter($payload, $skip_channel_filter)
    {
        switch (ord($payload[0])) {
            case NET_SSH2_MSG_DISCONNECT:
                Strings::shift($payload, 1);
                list($reason_code, $message) = Strings::unpackSSH2('Ns', $payload);
                $this->errors[] = 'SSH_MSG_DISCONNECT: ' . $this->disconnect_reasons[$reason_code] . "\r\n{$message}";
                $this->bitmap = 0;
                return false;
            case NET_SSH2_MSG_IGNORE:
                $payload = $this->get_binary_packet($skip_channel_filter);
                break;
            case NET_SSH2_MSG_DEBUG:
                Strings::shift($payload, 2);
                // second byte is "always_display"
                list($message) = Strings::unpackSSH2('s', $payload);
                $this->errors[] = "SSH_MSG_DEBUG: {$message}";
                $payload = $this->get_binary_packet($skip_channel_filter);
                break;
            case NET_SSH2_MSG_UNIMPLEMENTED:
                return false;
            case NET_SSH2_MSG_KEXINIT:
                if ($this->session_id !== false) {
                    if (!$this->key_exchange($payload)) {
                        $this->bitmap = 0;
                        return false;
                    }
                    $payload = $this->get_binary_packet($skip_channel_filter);
                }
        }
        // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
        if ($this->bitmap & self::MASK_CONNECTED && !$this->isAuthenticated() && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER) {
            Strings::shift($payload, 1);
            list($this->banner_message) = Strings::unpackSSH2('s', $payload);
            $payload = $this->get_binary_packet();
        }
        // only called when we've already logged in
        if ($this->bitmap & self::MASK_CONNECTED && $this->isAuthenticated()) {
            if ($payload === true) {
                return true;
            }
            switch (ord($payload[0])) {
                case NET_SSH2_MSG_CHANNEL_REQUEST:
                    if (strlen($payload) == 31) {
                        extract(unpack('cpacket_type/Nchannel/Nlength', $payload));
                        if (\Phabel\Target\Php80\Polyfill::substr($payload, 9, $length) == 'keepalive@openssh.com' && isset($this->server_channels[$channel])) {
                            if (ord(\Phabel\Target\Php80\Polyfill::substr($payload, 9 + $length))) {
                                // want reply
                                $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_SUCCESS, $this->server_channels[$channel]));
                            }
                            $payload = $this->get_binary_packet($skip_channel_filter);
                        }
                    }
                    break;
                case NET_SSH2_MSG_CHANNEL_DATA:
                case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
                case NET_SSH2_MSG_CHANNEL_CLOSE:
                case NET_SSH2_MSG_CHANNEL_EOF:
                    if (!$skip_channel_filter && !empty($this->server_channels)) {
                        $this->binary_packet_buffer = $payload;
                        $this->get_channel_packet(true);
                        $payload = $this->get_binary_packet();
                    }
                    break;
                case NET_SSH2_MSG_GLOBAL_REQUEST:
                    // see http://tools.ietf.org/html/rfc4254#section-4
                    Strings::shift($payload, 1);
                    list($request_name) = Strings::unpackSSH2('s', $payload);
                    $this->errors[] = "SSH_MSG_GLOBAL_REQUEST: {$request_name}";
                    try {
                        $this->send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE));
                    } catch (\RuntimeException $e) {
                        return $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                    }
                    $payload = $this->get_binary_packet($skip_channel_filter);
                    break;
                case NET_SSH2_MSG_CHANNEL_OPEN:
                    // see http://tools.ietf.org/html/rfc4254#section-5.1
                    Strings::shift($payload, 1);
                    list($data, $server_channel) = Strings::unpackSSH2('sN', $payload);
                    switch ($data) {
                        case 'auth-agent':
                        case 'auth-agent@openssh.com':
                            if (isset($this->agent)) {
                                $new_channel = self::CHANNEL_AGENT_FORWARD;
                                list($remote_window_size, $remote_maximum_packet_size) = Strings::unpackSSH2('NN', $payload);
                                $this->packet_size_client_to_server[$new_channel] = $remote_window_size;
                                $this->window_size_server_to_client[$new_channel] = $remote_maximum_packet_size;
                                $this->window_size_client_to_server[$new_channel] = $this->window_size;
                                $packet_size = 0x4000;
                                $packet = pack('CN4', NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION, $server_channel, $new_channel, $packet_size, $packet_size);
                                $this->server_channels[$new_channel] = $server_channel;
                                $this->channel_status[$new_channel] = NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION;
                                $this->send_binary_packet($packet);
                            }
                            break;
                        default:
                            $packet = Strings::packSSH2(
                                'CN2ss',
                                NET_SSH2_MSG_CHANNEL_OPEN_FAILURE,
                                $server_channel,
                                NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED,
                                '',
                                // description
                                ''
                            );
                            try {
                                $this->send_binary_packet($packet);
                            } catch (\RuntimeException $e) {
                                return $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                            }
                    }
                    $payload = $this->get_binary_packet($skip_channel_filter);
                    break;
                case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
                    Strings::shift($payload, 1);
                    list($channel, $window_size) = Strings::unpackSSH2('NN', $payload);
                    $this->window_size_client_to_server[$channel] += $window_size;
                    $payload = $this->bitmap & self::MASK_WINDOW_ADJUST ? true : $this->get_binary_packet($skip_channel_filter);
            }
        }
        return $payload;
    }
    /**
     * Enable Quiet Mode
     *
     * Suppress stderr from output
     *
     * @access public
     */
    public function enableQuietMode()
    {
        $this->quiet_mode = true;
    }
    /**
     * Disable Quiet Mode
     *
     * Show stderr in output
     *
     * @access public
     */
    public function disableQuietMode()
    {
        $this->quiet_mode = false;
    }
    /**
     * Returns whether Quiet Mode is enabled or not
     *
     * @see self::enableQuietMode()
     * @see self::disableQuietMode()
     * @access public
     * @return bool
     */
    public function isQuietModeEnabled()
    {
        return $this->quiet_mode;
    }
    /**
     * Enable request-pty when using exec()
     *
     * @access public
     */
    public function enablePTY()
    {
        $this->request_pty = true;
    }
    /**
     * Disable request-pty when using exec()
     *
     * @access public
     */
    public function disablePTY()
    {
        if ($this->in_request_pty_exec) {
            $this->close_channel(self::CHANNEL_EXEC);
            $this->in_request_pty_exec = false;
        }
        $this->request_pty = false;
    }
    /**
     * Returns whether request-pty is enabled or not
     *
     * @see self::enablePTY()
     * @see self::disablePTY()
     * @access public
     * @return bool
     */
    public function isPTYEnabled()
    {
        return $this->request_pty;
    }
    /**
    * Gets channel data
    *
    * Returns the data as a string. bool(true) is returned if:
    *
    * - the server closes the channel
    - if the connection times out
    - if the channel status is CHANNEL_OPEN and the response was CHANNEL_OPEN_CONFIRMATION
    - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_SUCCESS
    *
    * bool(false) is returned if:
    *
    * - if the channel status is CHANNEL_REQUEST and the response was CHANNEL_FAILURE
    *
    * @param int $client_channel
    * @param bool $skip_extended
    * @return mixed
    * @throws \RuntimeException on connection error
    * @access private
    */
    protected function get_channel_packet($client_channel, $skip_extended = false)
    {
        if (!empty($this->channel_buffers[$client_channel])) {
            switch ($this->channel_status[$client_channel]) {
                case NET_SSH2_MSG_CHANNEL_REQUEST:
                    foreach ($this->channel_buffers[$client_channel] as $i => $packet) {
                        switch (ord($packet[0])) {
                            case NET_SSH2_MSG_CHANNEL_SUCCESS:
                            case NET_SSH2_MSG_CHANNEL_FAILURE:
                                unset($this->channel_buffers[$client_channel][$i]);
                                return \Phabel\Target\Php80\Polyfill::substr($packet, 1);
                        }
                    }
                    break;
                default:
                    return \Phabel\Target\Php80\Polyfill::substr(array_shift($this->channel_buffers[$client_channel]), 1);
            }
        }
        while (true) {
            if ($this->binary_packet_buffer !== false) {
                $response = $this->binary_packet_buffer;
                $this->binary_packet_buffer = false;
            } else {
                $response = $this->get_binary_packet(true);
                if ($response === true && $this->is_timeout) {
                    if ($client_channel == self::CHANNEL_EXEC && !$this->request_pty) {
                        $this->close_channel($client_channel);
                    }
                    return true;
                }
                if ($response === false) {
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_CONNECTION_LOST);
                    throw new ConnectionClosedException('Connection closed by server');
                }
            }
            if ($client_channel == -1 && $response === true) {
                return true;
            }
            list($type, $channel) = Strings::unpackSSH2('CN', $response);
            // will not be setup yet on incoming channel open request
            if (isset($channel) && isset($this->channel_status[$channel]) && isset($this->window_size_server_to_client[$channel])) {
                $this->window_size_server_to_client[$channel] -= strlen($response);
                // resize the window, if appropriate
                if ($this->window_size_server_to_client[$channel] < 0) {
                    // PuTTY does something more analogous to the following:
                    //if ($this->window_size_server_to_client[$channel] < 0x3FFFFFFF) {
                    $packet = pack('CNN', NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST, $this->server_channels[$channel], $this->window_resize);
                    $this->send_binary_packet($packet);
                    $this->window_size_server_to_client[$channel] += $this->window_resize;
                }
                switch ($type) {
                    case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
                        /*
                        if ($client_channel == self::CHANNEL_EXEC) {
                            $this->send_channel_packet($client_channel, chr(0));
                        }
                        */
                        // currently, there's only one possible value for $data_type_code: NET_SSH2_EXTENDED_DATA_STDERR
                        list($data_type_code, $data) = Strings::unpackSSH2('Ns', $response);
                        $this->stdErrorLog .= $data;
                        if ($skip_extended || $this->quiet_mode) {
                            continue 2;
                        }
                        if ($client_channel == $channel && $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA) {
                            return $data;
                        }
                        $this->channel_buffers[$channel][] = chr($type) . $data;
                        continue 2;
                    case NET_SSH2_MSG_CHANNEL_REQUEST:
                        if ($this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_CLOSE) {
                            continue 2;
                        }
                        list($value) = Strings::unpackSSH2('s', $response);
                        switch ($value) {
                            case 'exit-signal':
                                list(, $signal_name, , $error_message) = Strings::unpackSSH2('bsbs', $response);
                                $this->errors[] = "SSH_MSG_CHANNEL_REQUEST (exit-signal): {$signal_name}";
                                if (strlen($error_message)) {
                                    $this->errors[count($this->errors) - 1] .= "\r\n{$error_message}";
                                }
                                $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
                                $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
                                $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_EOF;
                                continue 3;
                            case 'exit-status':
                                list(, $this->exit_status) = Strings::unpackSSH2('CN', $response);
                                // "The client MAY ignore these messages."
                                // -- http://tools.ietf.org/html/rfc4254#section-6.10
                                continue 3;
                            default:
                                // "Some systems may not implement signals, in which case they SHOULD ignore this message."
                                //  -- http://tools.ietf.org/html/rfc4254#section-6.9
                                continue 3;
                        }
                }
                switch ($this->channel_status[$channel]) {
                    case NET_SSH2_MSG_CHANNEL_OPEN:
                        switch ($type) {
                            case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
                                list($this->server_channels[$channel], $window_size, $this->packet_size_client_to_server[$channel]) = Strings::unpackSSH2('NNN', $response);
                                if ($window_size < 0) {
                                    $window_size &= 0x7fffffff;
                                    $window_size += 0x80000000;
                                }
                                $this->window_size_client_to_server[$channel] = $window_size;
                                $result = $client_channel == $channel ? true : $this->get_channel_packet($client_channel, $skip_extended);
                                $this->on_channel_open();
                                return $result;
                            case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
                                $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                                throw new \RuntimeException('Unable to open channel');
                            default:
                                if ($client_channel == $channel) {
                                    $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                                    throw new \RuntimeException('Unexpected response to open request');
                                }
                                return $this->get_channel_packet($client_channel, $skip_extended);
                        }
                        break;
                    case NET_SSH2_MSG_CHANNEL_REQUEST:
                        switch ($type) {
                            case NET_SSH2_MSG_CHANNEL_SUCCESS:
                                return true;
                            case NET_SSH2_MSG_CHANNEL_FAILURE:
                                return false;
                            case NET_SSH2_MSG_CHANNEL_DATA:
                                list($data) = Strings::unpackSSH2('s', $response);
                                $this->channel_buffers[$channel][] = chr($type) . $data;
                                return $this->get_channel_packet($client_channel, $skip_extended);
                            default:
                                $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                                throw new \RuntimeException('Unable to fulfill channel request');
                        }
                    case NET_SSH2_MSG_CHANNEL_CLOSE:
                        return $type == NET_SSH2_MSG_CHANNEL_CLOSE ? true : $this->get_channel_packet($client_channel, $skip_extended);
                }
            }
            // ie. $this->channel_status[$channel] == NET_SSH2_MSG_CHANNEL_DATA
            switch ($type) {
                case NET_SSH2_MSG_CHANNEL_DATA:
                    /*
                    if ($channel == self::CHANNEL_EXEC) {
                        // SCP requires null packets, such as this, be sent.  further, in the case of the ssh.com SSH server
                        // this actually seems to make things twice as fast.  more to the point, the message right after
                        // SSH_MSG_CHANNEL_DATA (usually SSH_MSG_IGNORE) won't block for as long as it would have otherwise.
                        // in OpenSSH it slows things down but only by a couple thousandths of a second.
                        $this->send_channel_packet($channel, chr(0));
                    }
                    */
                    list($data) = Strings::unpackSSH2('s', $response);
                    if ($channel == self::CHANNEL_AGENT_FORWARD) {
                        $agent_response = $this->agent->forwardData($data);
                        if (!is_bool($agent_response)) {
                            $this->send_channel_packet($channel, $agent_response);
                        }
                        break;
                    }
                    if ($client_channel == $channel) {
                        return $data;
                    }
                    $this->channel_buffers[$channel][] = chr($type) . $data;
                    break;
                case NET_SSH2_MSG_CHANNEL_CLOSE:
                    $this->curTimeout = 5;
                    if ($this->bitmap & self::MASK_SHELL) {
                        $this->bitmap &= ~self::MASK_SHELL;
                    }
                    if ($this->channel_status[$channel] != NET_SSH2_MSG_CHANNEL_EOF) {
                        $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$channel]));
                    }
                    $this->channel_status[$channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
                    if ($client_channel == $channel) {
                        return true;
                    }
                case NET_SSH2_MSG_CHANNEL_EOF:
                    break;
                default:
                    $this->disconnect_helper(NET_SSH2_DISCONNECT_BY_APPLICATION);
                    throw new \RuntimeException("Error reading channel data ({$type})");
            }
        }
    }
    /**
     * Sends Binary Packets
     *
     * See '6. Binary Packet Protocol' of rfc4253 for more info.
     *
     * @param string $data
     * @param string $logged
     * @see self::_get_binary_packet()
     * @return bool
     * @access private
     */
    protected function send_binary_packet($data, $logged = null)
    {
        if (!is_resource($this->fsock) || feof($this->fsock)) {
            $this->bitmap = 0;
            throw new ConnectionClosedException('Connection closed prematurely');
        }
        if (!isset($logged)) {
            $logged = $data;
        }
        switch ($this->compress) {
            case NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH:
                if (!$this->isAuthenticated()) {
                    break;
                }
            case NET_SSH2_COMPRESSION_ZLIB:
                if (!$this->regenerate_compression_context) {
                    $header = '';
                } else {
                    $this->regenerate_compression_context = false;
                    $this->compress_context = deflate_init(ZLIB_ENCODING_RAW, ['window' => 15]);
                    $header = "x\x9c";
                }
                if ($this->compress_context) {
                    $data = $header . deflate_add($this->compress_context, $data, ZLIB_PARTIAL_FLUSH);
                }
        }
        // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
        $packet_length = strlen($data) + 9;
        if ($this->encrypt && $this->encrypt->usesNonce()) {
            $packet_length -= 4;
        }
        // round up to the nearest $this->encrypt_block_size
        $packet_length += ($this->encrypt_block_size - 1) * $packet_length % $this->encrypt_block_size;
        // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length
        $padding_length = $packet_length - strlen($data) - 5;
        switch (true) {
            case $this->encrypt && $this->encrypt->usesNonce():
            case $this->hmac_create instanceof Hash && $this->hmac_create->etm:
                $padding_length += 4;
                $packet_length += 4;
        }
        $padding = Random::string($padding_length);
        // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself
        $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding);
        $hmac = '';
        if ($this->hmac_create instanceof Hash && !$this->hmac_create->etm) {
            if (($this->hmac_create->getHash() & "\xff\xff\xff\xff") == 'umac') {
                $this->hmac_create->setNonce("\x00\x00\x00\x00" . pack('N', $this->send_seq_no));
                $hmac = $this->hmac_create->hash($packet);
            } else {
                $hmac = $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet));
            }
        }
        if ($this->encrypt) {
            switch ($this->encrypt->name) {
                case 'aes128-gcm@openssh.com':
                case 'aes256-gcm@openssh.com':
                    $this->encrypt->setNonce($this->encrypt->fixed . $this->encrypt->invocation_counter);
                    Strings::increment_str($this->encrypt->invocation_counter);
                    $this->encrypt->setAAD($temp = $packet & "\xff\xff\xff\xff");
                    $packet = $temp . $this->encrypt->encrypt(\Phabel\Target\Php80\Polyfill::substr($packet, 4));
                    break;
                case 'chacha20-poly1305@openssh.com':
                    $nonce = pack('N2', 0, $this->send_seq_no);
                    $this->encrypt->setNonce($nonce);
                    $this->lengthEncrypt->setNonce($nonce);
                    $length = $this->lengthEncrypt->encrypt($packet & "\xff\xff\xff\xff");
                    $this->encrypt->setCounter(0);
                    // this is the same approach that's implemented in Salsa20::createPoly1305Key()
                    // but we don't want to use the same AEAD construction that RFC8439 describes
                    // for ChaCha20-Poly1305 so we won't rely on it (see Salsa20::poly1305())
                    $this->encrypt->setPoly1305Key($this->encrypt->encrypt(str_repeat("\x00", 32)));
                    $this->encrypt->setAAD($length);
                    $this->encrypt->setCounter(1);
                    $packet = $length . $this->encrypt->encrypt(\Phabel\Target\Php80\Polyfill::substr($packet, 4));
                    break;
                default:
                    $packet = $this->hmac_create instanceof Hash && $this->hmac_create->etm ? ($packet & "\xff\xff\xff\xff") . $this->encrypt->encrypt(\Phabel\Target\Php80\Polyfill::substr($packet, 4)) : $this->encrypt->encrypt($packet);
            }
        }
        if ($this->hmac_create instanceof Hash && $this->hmac_create->etm) {
            if (($this->hmac_create->getHash() & "\xff\xff\xff\xff") == 'umac') {
                $this->hmac_create->setNonce("\x00\x00\x00\x00" . pack('N', $this->send_seq_no));
                $hmac = $this->hmac_create->hash($packet);
            } else {
                $hmac = $this->hmac_create->hash(pack('Na*', $this->send_seq_no, $packet));
            }
        }
        $this->send_seq_no++;
        $packet .= $this->encrypt && $this->encrypt->usesNonce() ? $this->encrypt->getTag() : $hmac;
        $start = microtime(true);
        $sent = @fputs($this->fsock, $packet);
        $stop = microtime(true);
        if (defined('NET_SSH2_LOGGING')) {
            $current = microtime(true);
            $message_number = isset($this->message_numbers[ord($logged[0])]) ? $this->message_numbers[ord($logged[0])] : 'UNKNOWN (' . ord($logged[0]) . ')';
            $message_number = '-> ' . $message_number . ' (since last: ' . round($current - $this->last_packet, 4) . ', network: ' . round($stop - $start, 4) . 's)';
            $this->append_log($message_number, $logged);
            $this->last_packet = $current;
        }
        if (strlen($packet) != $sent) {
            $this->bitmap = 0;
            throw new \RuntimeException("Only {$sent} of " . strlen($packet) . " bytes were sent");
        }
    }
    /**
     * Logs data packets
     *
     * Makes sure that only the last 1MB worth of packets will be logged
     *
     * @param string $message_number
     * @param string $message
     * @access private
     */
    private function append_log($message_number, $message)
    {
        // remove the byte identifying the message type from all but the first two messages (ie. the identification strings)
        if (strlen($message_number) > 2) {
            Strings::shift($message);
        }
        switch (NET_SSH2_LOGGING) {
            // useful for benchmarks
            case self::LOG_SIMPLE:
                $this->message_number_log[] = $message_number;
                break;
            // the most useful log for SSH2
            case self::LOG_COMPLEX:
                $this->message_number_log[] = $message_number;
                $this->log_size += strlen($message);
                $this->message_log[] = $message;
                while ($this->log_size > self::LOG_MAX_SIZE) {
                    $this->log_size -= strlen(array_shift($this->message_log));
                    array_shift($this->message_number_log);
                }
                break;
            // dump the output out realtime; packets may be interspersed with non packets,
            // passwords won't be filtered out and select other packets may not be correctly
            // identified
            case self::LOG_REALTIME:
                switch (PHP_SAPI) {
                    case 'cli':
                        $start = $stop = "\r\n";
                        break;
                    default:
                        $start = '<pre>';
                        $stop = '</pre>';
                }
                echo $start . $this->format_log([$message], [$message_number]) . $stop;
                @flush();
                @ob_flush();
                break;
            // basically the same thing as self::LOG_REALTIME with the caveat that NET_SSH2_LOG_REALTIME_FILENAME
            // needs to be defined and that the resultant log file will be capped out at self::LOG_MAX_SIZE.
            // the earliest part of the log file is denoted by the first <<< START >>> and is not going to necessarily
            // at the beginning of the file
            case self::LOG_REALTIME_FILE:
                if (!isset($this->realtime_log_file)) {
                    // PHP doesn't seem to like using constants in fopen()
                    $filename = NET_SSH2_LOG_REALTIME_FILENAME;
                    $fp = fopen($filename, 'w');
                    $this->realtime_log_file = $fp;
                }
                if (!is_resource($this->realtime_log_file)) {
                    break;
                }
                $entry = $this->format_log([$message], [$message_number]);
                if ($this->realtime_log_wrap) {
                    $temp = "<<< START >>>\r\n";
                    $entry .= $temp;
                    fseek($this->realtime_log_file, ftell($this->realtime_log_file) - strlen($temp));
                }
                $this->realtime_log_size += strlen($entry);
                if ($this->realtime_log_size > self::LOG_MAX_SIZE) {
                    fseek($this->realtime_log_file, 0);
                    $this->realtime_log_size = strlen($entry);
                    $this->realtime_log_wrap = true;
                }
                fputs($this->realtime_log_file, $entry);
        }
    }
    /**
     * Sends channel data
     *
     * Spans multiple SSH_MSG_CHANNEL_DATAs if appropriate
     *
     * @param int $client_channel
     * @param string $data
     * @return bool
     * @access private
     */
    protected function send_channel_packet($client_channel, $data)
    {
        while (strlen($data)) {
            if (!$this->window_size_client_to_server[$client_channel]) {
                $this->bitmap ^= self::MASK_WINDOW_ADJUST;
                // using an invalid channel will let the buffers be built up for the valid channels
                $this->get_channel_packet(-1);
                $this->bitmap ^= self::MASK_WINDOW_ADJUST;
            }
            /* The maximum amount of data allowed is determined by the maximum
               packet size for the channel, and the current window size, whichever
               is smaller.
                 -- http://tools.ietf.org/html/rfc4254#section-5.2 */
            $max_size = min($this->packet_size_client_to_server[$client_channel], $this->window_size_client_to_server[$client_channel]);
            $temp = Strings::shift($data, $max_size);
            $packet = Strings::packSSH2('CNs', NET_SSH2_MSG_CHANNEL_DATA, $this->server_channels[$client_channel], $temp);
            $this->window_size_client_to_server[$client_channel] -= strlen($temp);
            $this->send_binary_packet($packet);
        }
        return true;
    }
    /**
    * Closes and flushes a channel
    *
    * \phpseclib3\Net\SSH2 doesn't properly close most channels.  For exec() channels are normally closed by the server
    and for SFTP channels are presumably closed when the client disconnects.  This functions is intended
    for SCP more than anything.
    *
    * @param int $client_channel
    * @param bool $want_reply
    * @return bool
    * @access private
    */
    private function close_channel($client_channel, $want_reply = false)
    {
        // see http://tools.ietf.org/html/rfc4254#section-5.3
        $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_EOF, $this->server_channels[$client_channel]));
        if (!$want_reply) {
            $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
        }
        $this->channel_status[$client_channel] = NET_SSH2_MSG_CHANNEL_CLOSE;
        $this->curTimeout = 5;
        while (!is_bool($this->get_channel_packet($client_channel))) {
        }
        if ($this->is_timeout) {
            $this->disconnect();
        }
        if ($want_reply) {
            $this->send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $this->server_channels[$client_channel]));
        }
        if ($this->bitmap & self::MASK_SHELL) {
            $this->bitmap &= ~self::MASK_SHELL;
        }
    }
    /**
     * Disconnect
     *
     * @param int $reason
     * @return bool
     * @access protected
     */
    protected function disconnect_helper($reason)
    {
        if ($this->bitmap & self::MASK_CONNECTED) {
            $data = Strings::packSSH2('CNss', NET_SSH2_MSG_DISCONNECT, $reason, '', '');
            try {
                $this->send_binary_packet($data);
            } catch (\Exception $e) {
            }
        }
        $this->bitmap = 0;
        if (is_resource($this->fsock) && get_resource_type($this->fsock) == 'stream') {
            fclose($this->fsock);
        }
        return false;
    }
    /**
    * Define Array
    *
    * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of
    named constants from it, using the value as the name of the constant and the index as the value of the constant.
    If any of the constants that would be defined already exists, none of the constants will be defined.
    *
    * @param mixed[] ...$args
    * @access protected
    */
    protected function define_array(...$args)
    {
        foreach ($args as $arg) {
            foreach ($arg as $key => $value) {
                if (!defined($value)) {
                    define($value, $key);
                } else {
                    break 2;
                }
            }
        }
    }
    /**
     * Returns a log of the packets that have been sent and received.
     *
     * Returns a string if NET_SSH2_LOGGING == self::LOG_COMPLEX, an array if NET_SSH2_LOGGING == self::LOG_SIMPLE and false if !defined('NET_SSH2_LOGGING')
     *
     * @access public
     * @return (array | false | string)
     */
    public function getLog()
    {
        if (!defined('NET_SSH2_LOGGING')) {
            return false;
        }
        switch (NET_SSH2_LOGGING) {
            case self::LOG_SIMPLE:
                return $this->message_number_log;
            case self::LOG_COMPLEX:
                $log = $this->format_log($this->message_log, $this->message_number_log);
                return PHP_SAPI == 'cli' ? $log : '<pre>' . $log . '</pre>';
            default:
                return false;
        }
    }
    /**
     * Formats a log for printing
     *
     * @param array $message_log
     * @param array $message_number_log
     * @access private
     * @return string
     */
    protected function format_log($message_log, $message_number_log)
    {
        $output = '';
        for ($i = 0; $i < count($message_log); $i++) {
            $output .= $message_number_log[$i] . "\r\n";
            $current_log = $message_log[$i];
            $j = 0;
            do {
                if (strlen($current_log)) {
                    $output .= str_pad(dechex($j), 7, '0', STR_PAD_LEFT) . '0  ';
                }
                $fragment = Strings::shift($current_log, $this->log_short_width);
                $hex = \Phabel\Target\Php80\Polyfill::substr(preg_replace_callback('#.#s', function ($matches) {
                    return $this->log_boundary . str_pad(dechex(ord($matches[0])), 2, '0', STR_PAD_LEFT);
                }, $fragment), strlen($this->log_boundary));
                // replace non ASCII printable characters with dots
                // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
                // also replace < with a . since < messes up the output on web browsers
                $raw = preg_replace('#[^\\x20-\\x7E]|<#', '.', $fragment);
                $output .= str_pad($hex, $this->log_long_width - $this->log_short_width, ' ') . $raw . "\r\n";
                $j++;
            } while (strlen($current_log));
            $output .= "\r\n";
        }
        return $output;
    }
    /**
    * Helper function for agent->on_channel_open()
    *
    * Used when channels are created to inform agent
    of said channel opening. Must be called after
    channel open confirmation received
    *
    * @access private
    */
    private function on_channel_open()
    {
        if (isset($this->agent)) {
            $this->agent->registerChannelOpen($this);
        }
    }
    /**
    * Returns the first value of the intersection of two arrays or false if
    the intersection is empty. The order is defined by the first parameter.
    *
    * @param array $array1
    * @param array $array2
    * @return mixed False if intersection is empty, else intersected value.
    * @access private
    */
    private static function array_intersect_first($array1, $array2)
    {
        foreach ($array1 as $value) {
            if (in_array($value, $array2)) {
                return $value;
            }
        }
        return false;
    }
    /**
     * Returns all errors
     *
     * @return string[]
     * @access public
     */
    public function getErrors()
    {
        return $this->errors;
    }
    /**
     * Returns the last error
     *
     * @return string
     * @access public
     */
    public function getLastError()
    {
        $count = count($this->errors);
        if ($count > 0) {
            return $this->errors[$count - 1];
        }
    }
    /**
     * Return the server identification.
     *
     * @return string
     * @access public
     */
    public function getServerIdentification()
    {
        $this->connect();
        return $this->server_identifier;
    }
    /**
     * Returns a list of algorithms the server supports
     *
     * @return array
     * @access public
     */
    public function getServerAlgorithms()
    {
        $this->connect();
        return ['kex' => $this->kex_algorithms, 'hostkey' => $this->server_host_key_algorithms, 'client_to_server' => ['crypt' => $this->encryption_algorithms_client_to_server, 'mac' => $this->mac_algorithms_client_to_server, 'comp' => $this->compression_algorithms_client_to_server, 'lang' => $this->languages_client_to_server], 'server_to_client' => ['crypt' => $this->encryption_algorithms_server_to_client, 'mac' => $this->mac_algorithms_server_to_client, 'comp' => $this->compression_algorithms_server_to_client, 'lang' => $this->languages_server_to_client]];
    }
    /**
     * Returns a list of KEX algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedKEXAlgorithms()
    {
        $kex_algorithms = [
            // Elliptic Curve Diffie-Hellman Key Agreement (ECDH) using
            // Curve25519. See doc/curve25519-sha256@libssh.org.txt in the
            // libssh repository for more information.
            'curve25519-sha256',
            'curve25519-sha256@libssh.org',
            'ecdh-sha2-nistp256',
            // RFC 5656
            'ecdh-sha2-nistp384',
            // RFC 5656
            'ecdh-sha2-nistp521',
            // RFC 5656
            'diffie-hellman-group-exchange-sha256',
            // RFC 4419
            'diffie-hellman-group-exchange-sha1',
            // RFC 4419
            // Diffie-Hellman Key Agreement (DH) using integer modulo prime
            // groups.
            'diffie-hellman-group14-sha256',
            'diffie-hellman-group14-sha1',
            // REQUIRED
            'diffie-hellman-group15-sha512',
            'diffie-hellman-group16-sha512',
            'diffie-hellman-group17-sha512',
            'diffie-hellman-group18-sha512',
            'diffie-hellman-group1-sha1',
        ];
        return $kex_algorithms;
    }
    /**
     * Returns a list of host key algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedHostKeyAlgorithms()
    {
        return [
            'ssh-ed25519',
            // https://tools.ietf.org/html/draft-ietf-curdle-ssh-ed25519-02
            'ecdsa-sha2-nistp256',
            // RFC 5656
            'ecdsa-sha2-nistp384',
            // RFC 5656
            'ecdsa-sha2-nistp521',
            // RFC 5656
            'rsa-sha2-256',
            // RFC 8332
            'rsa-sha2-512',
            // RFC 8332
            'ssh-rsa',
            // RECOMMENDED  sign   Raw RSA Key
            'ssh-dss',
        ];
    }
    /**
     * Returns a list of symmetric key algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedEncryptionAlgorithms()
    {
        $algos = [
            // from <https://tools.ietf.org/html/rfc5647>:
            'aes128-gcm@openssh.com',
            'aes256-gcm@openssh.com',
            // from <http://tools.ietf.org/html/rfc4345#section-4>:
            'arcfour256',
            'arcfour128',
            //'arcfour',      // OPTIONAL          the ARCFOUR stream cipher with a 128-bit key
            // CTR modes from <http://tools.ietf.org/html/rfc4344#section-4>:
            'aes128-ctr',
            // RECOMMENDED       AES (Rijndael) in SDCTR mode, with 128-bit key
            'aes192-ctr',
            // RECOMMENDED       AES with 192-bit key
            'aes256-ctr',
            // RECOMMENDED       AES with 256-bit key
            // from <https://git.io/fhxOl>:
            // one of the big benefits of chacha20-poly1305 is speed. the problem is...
            // libsodium doesn't generate the poly1305 keys in the way ssh does and openssl's PHP bindings don't even
            // seem to support poly1305 currently. so even if libsodium or openssl are being used for the chacha20
            // part, pure-PHP has to be used for the poly1305 part and that's gonna cause a big slow down.
            // speed-wise it winds up being faster to use AES (when openssl or mcrypt are available) and some HMAC
            // (which is always gonna be super fast to compute thanks to the hash extension, which
            // "is bundled and compiled into PHP by default")
            'chacha20-poly1305@openssh.com',
            'twofish128-ctr',
            // OPTIONAL          Twofish in SDCTR mode, with 128-bit key
            'twofish192-ctr',
            // OPTIONAL          Twofish with 192-bit key
            'twofish256-ctr',
            // OPTIONAL          Twofish with 256-bit key
            'aes128-cbc',
            // RECOMMENDED       AES with a 128-bit key
            'aes192-cbc',
            // OPTIONAL          AES with a 192-bit key
            'aes256-cbc',
            // OPTIONAL          AES in CBC mode, with a 256-bit key
            'twofish128-cbc',
            // OPTIONAL          Twofish with a 128-bit key
            'twofish192-cbc',
            // OPTIONAL          Twofish with a 192-bit key
            'twofish256-cbc',
            'twofish-cbc',
            // OPTIONAL          alias for "twofish256-cbc"
            //                   (this is being retained for historical reasons)
            'blowfish-ctr',
            // OPTIONAL          Blowfish in SDCTR mode
            'blowfish-cbc',
            // OPTIONAL          Blowfish in CBC mode
            '3des-ctr',
            // RECOMMENDED       Three-key 3DES in SDCTR mode
            '3des-cbc',
        ];
        if (self::$crypto_engine) {
            $engines = [self::$crypto_engine];
        } else {
            $engines = ['libsodium', 'OpenSSL (GCM)', 'OpenSSL', 'mcrypt', 'Eval', 'PHP'];
        }
        $ciphers = [];
        foreach ($engines as $engine) {
            foreach ($algos as $algo) {
                $obj = self::encryption_algorithm_to_crypt_instance($algo);
                if ($obj instanceof Rijndael) {
                    $obj->setKeyLength(preg_replace('#[^\\d]#', '', $algo));
                }
                switch ($algo) {
                    case 'chacha20-poly1305@openssh.com':
                    case 'arcfour128':
                    case 'arcfour256':
                        if ($engine != 'Eval') {
                            continue 2;
                        }
                        break;
                    case 'aes128-gcm@openssh.com':
                    case 'aes256-gcm@openssh.com':
                        if ($engine == 'OpenSSL') {
                            continue 2;
                        }
                        $obj->setNonce('dummydummydu');
                }
                if ($obj->isValidEngine($engine)) {
                    $algos = array_diff($algos, [$algo]);
                    $ciphers[] = $algo;
                }
            }
        }
        return $ciphers;
    }
    /**
     * Returns a list of MAC algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedMACAlgorithms()
    {
        return [
            'hmac-sha2-256-etm@openssh.com',
            'hmac-sha2-512-etm@openssh.com',
            'umac-64-etm@openssh.com',
            'umac-128-etm@openssh.com',
            'hmac-sha1-etm@openssh.com',
            // from <http://www.ietf.org/rfc/rfc6668.txt>:
            'hmac-sha2-256',
            // RECOMMENDED     HMAC-SHA256 (digest length = key length = 32)
            'hmac-sha2-512',
            // OPTIONAL        HMAC-SHA512 (digest length = key length = 64)
            // from <https://tools.ietf.org/html/draft-miller-secsh-umac-01>:
            'umac-64@openssh.com',
            'umac-128@openssh.com',
            'hmac-sha1-96',
            // RECOMMENDED     first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
            'hmac-sha1',
            // REQUIRED        HMAC-SHA1 (digest length = key length = 20)
            'hmac-md5-96',
            // OPTIONAL        first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
            'hmac-md5',
        ];
    }
    /**
     * Returns a list of compression algorithms that phpseclib supports
     *
     * @return array
     * @access public
     */
    public static function getSupportedCompressionAlgorithms()
    {
        $algos = ['none'];
        // REQUIRED        no compression
        if (function_exists('deflate_init')) {
            $algos[] = 'zlib@openssh.com';
            // https://datatracker.ietf.org/doc/html/draft-miller-secsh-compression-delayed
            $algos[] = 'zlib';
        }
        return $algos;
    }
    /**
     * Return list of negotiated algorithms
     *
     * Uses the same format as https://www.php.net/ssh2-methods-negotiated
     *
     * @return array
     * @access public
     */
    public function getAlgorithmsNegotiated()
    {
        $this->connect();
        $compression_map = [NET_SSH2_COMPRESSION_NONE => 'none', NET_SSH2_COMPRESSION_ZLIB => 'zlib', NET_SSH2_COMPRESSION_ZLIB_AT_OPENSSH => 'zlib@openssh.com'];
        return ['kex' => $this->kex_algorithm, 'hostkey' => $this->signature_format, 'client_to_server' => ['crypt' => $this->encrypt->name, 'mac' => $this->hmac_create->name, 'comp' => $compression_map[$this->compress]], 'server_to_client' => ['crypt' => $this->decrypt->name, 'mac' => $this->hmac_check->name, 'comp' => $compression_map[$this->decompress]]];
    }
    /**
     * Allows you to set the terminal
     *
     * @param string $term
     * @access public
     */
    public function setTerminal($term)
    {
        $this->term = $term;
    }
    /**
    * Accepts an associative array with up to four parameters as described at
    <https://www.php.net/manual/en/function.ssh2-connect.php>
    *
    * @param array $methods
    * @access public
    */
    public function setPreferredAlgorithms(array $methods)
    {
        $preferred = $methods;
        if (isset($preferred['kex'])) {
            $preferred['kex'] = array_intersect($preferred['kex'], static::getSupportedKEXAlgorithms());
        }
        if (isset($preferred['hostkey'])) {
            $preferred['hostkey'] = array_intersect($preferred['hostkey'], static::getSupportedHostKeyAlgorithms());
        }
        $keys = ['client_to_server', 'server_to_client'];
        foreach ($keys as $key) {
            if (isset($preferred[$key])) {
                $a =& $preferred[$key];
                if (isset($a['crypt'])) {
                    $a['crypt'] = array_intersect($a['crypt'], static::getSupportedEncryptionAlgorithms());
                }
                if (isset($a['comp'])) {
                    $a['comp'] = array_intersect($a['comp'], static::getSupportedCompressionAlgorithms());
                }
                if (isset($a['mac'])) {
                    $a['mac'] = array_intersect($a['mac'], static::getSupportedMACAlgorithms());
                }
            }
        }
        $keys = ['kex', 'hostkey', 'client_to_server/crypt', 'client_to_server/comp', 'client_to_server/mac', 'server_to_client/crypt', 'server_to_client/comp', 'server_to_client/mac'];
        foreach ($keys as $key) {
            $p = $preferred;
            $m = $methods;
            $subkeys = explode('/', $key);
            foreach ($subkeys as $subkey) {
                if (!isset($p[$subkey])) {
                    continue 2;
                }
                $p = $p[$subkey];
                $m = $m[$subkey];
            }
            if (count($p) != count($m)) {
                $diff = array_diff($m, $p);
                $msg = count($diff) == 1 ? ' is not a supported algorithm' : ' are not supported algorithms';
                throw new UnsupportedAlgorithmException(implode(', ', $diff) . $msg);
            }
        }
        $this->preferred = $preferred;
    }
    /**
    * Returns the banner message.
    *
    * Quoting from the RFC, "in some jurisdictions, sending a warning message before
    authentication may be relevant for getting legal protection."
    *
    * @return string
    * @access public
    */
    public function getBannerMessage()
    {
        return $this->banner_message;
    }
    /**
    * Returns the server public host key.
    *
    * Caching this the first time you connect to a server and checking the result on subsequent connections
    is recommended.  Returns false if the server signature is not signed correctly with the public host key.
    *
    * @return mixed
    * @throws \RuntimeException on badly formatted keys
    * @throws \phpseclib3\Exception\NoSupportedAlgorithmsException when the key isn't in a supported format
    * @access public
    */
    public function getServerPublicHostKey()
    {
        if (!($this->bitmap & self::MASK_CONSTRUCTOR)) {
            $this->connect();
        }
        $signature = $this->signature;
        $server_public_host_key = base64_encode($this->server_public_host_key);
        if ($this->signature_validated) {
            return $this->bitmap ? $this->signature_format . ' ' . $server_public_host_key : false;
        }
        $this->signature_validated = true;
        switch ($this->signature_format) {
            case 'ssh-ed25519':
            case 'ecdsa-sha2-nistp256':
            case 'ecdsa-sha2-nistp384':
            case 'ecdsa-sha2-nistp521':
                $key = EC::loadFormat('OpenSSH', $server_public_host_key)->withSignatureFormat('SSH2');
                switch ($this->signature_format) {
                    case 'ssh-ed25519':
                        $hash = 'sha512';
                        break;
                    case 'ecdsa-sha2-nistp256':
                        $hash = 'sha256';
                        break;
                    case 'ecdsa-sha2-nistp384':
                        $hash = 'sha384';
                        break;
                    case 'ecdsa-sha2-nistp521':
                        $hash = 'sha512';
                }
                $key = $key->withHash($hash);
                break;
            case 'ssh-dss':
                $key = DSA::loadFormat('OpenSSH', $server_public_host_key)->withSignatureFormat('SSH2')->withHash('sha1');
                break;
            case 'ssh-rsa':
            case 'rsa-sha2-256':
            case 'rsa-sha2-512':
                if (strlen($signature) < 15) {
                    return false;
                }
                Strings::shift($signature, 11);
                $temp = unpack('Nlength', Strings::shift($signature, 4));
                $signature = Strings::shift($signature, $temp['length']);
                $key = RSA::loadFormat('OpenSSH', $server_public_host_key)->withPadding(RSA::SIGNATURE_PKCS1);
                switch ($this->signature_format) {
                    case 'rsa-sha2-512':
                        $hash = 'sha512';
                        break;
                    case 'rsa-sha2-256':
                        $hash = 'sha256';
                        break;
                    //case 'ssh-rsa':
                    default:
                        $hash = 'sha1';
                }
                $key = $key->withHash($hash);
                break;
            default:
                $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
                throw new NoSupportedAlgorithmsException('Unsupported signature format');
        }
        if (!$key->verify($this->exchange_hash, $signature)) {
            return $this->disconnect_helper(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
        }
        return $this->signature_format . ' ' . $server_public_host_key;
    }
    /**
     * Returns the exit status of an SSH command or false.
     *
     * @return (false | int)
     * @access public
     */
    public function getExitStatus()
    {
        if (is_null($this->exit_status)) {
            return false;
        }
        return $this->exit_status;
    }
    /**
     * Returns the number of columns for the terminal window size.
     *
     * @return int
     * @access public
     */
    public function getWindowColumns()
    {
        return $this->windowColumns;
    }
    /**
     * Returns the number of rows for the terminal window size.
     *
     * @return int
     * @access public
     */
    public function getWindowRows()
    {
        return $this->windowRows;
    }
    /**
     * Sets the number of columns for the terminal window size.
     *
     * @param int $value
     * @access public
     */
    public function setWindowColumns($value)
    {
        $this->windowColumns = $value;
    }
    /**
     * Sets the number of rows for the terminal window size.
     *
     * @param int $value
     * @access public
     */
    public function setWindowRows($value)
    {
        $this->windowRows = $value;
    }
    /**
     * Sets the number of columns and rows for the terminal window size.
     *
     * @param int $columns
     * @param int $rows
     * @access public
     */
    public function setWindowSize($columns = 80, $rows = 24)
    {
        $this->windowColumns = $columns;
        $this->windowRows = $rows;
    }
    /**
     * To String Magic Method
     *
     * @return string
     * @access public
     */
    public function __toString()
    {
        return $this->getResourceId();
    }
    /**
    * Get Resource ID
    *
    * We use {} because that symbols should not be in URL according to
    {@link http://tools.ietf.org/html/rfc3986#section-2 RFC}.
    It will safe us from any conflicts, because otherwise regexp will
    match all alphanumeric domains.
    *
    * @return string
    */
    public function getResourceId()
    {
        return '{' . spl_object_hash($this) . '}';
    }
    /**
     * Return existing connection
     *
     * @param string $id
     *
     * @return (bool | SSH2) will return false if no such connection
     */
    public static function getConnectionByResourceId($id)
    {
        if (isset(self::$connections[$id])) {
            return self::$connections[$id] instanceof \WeakReference ? self::$connections[$id]->get() : self::$connections[$id];
        }
        return false;
    }
    /**
     * Return all excising connections
     *
     * @return SSH2[]
     */
    public static function getConnections()
    {
        if (!class_exists('WeakReference')) {
            return self::$connections;
        }
        $temp = [];
        foreach (self::$connections as $key => $ref) {
            $temp[$key] = $ref->get();
        }
        return $temp;
    }
    /*
     * Update packet types in log history
     *
     * @param string $old
     * @param string $new
     * @access private
     */
    /**
     *
     */
    private function updateLogHistory($old, $new)
    {
        if (defined('NET_SSH2_LOGGING') && NET_SSH2_LOGGING == self::LOG_COMPLEX) {
            $this->message_number_log[count($this->message_number_log) - 1] = str_replace($old, $new, $this->message_number_log[count($this->message_number_log) - 1]);
        }
    }
    /**
     * Return the list of authentication methods that may productively continue authentication.
     *
     * @see https://tools.ietf.org/html/rfc4252#section-5.1
     * @return (array | null)
     */
    public function getAuthMethodsToContinue()
    {
        return $this->auth_methods_to_continue;
    }
    /**
     * Enables "smart" multi-factor authentication (MFA)
     */
    public function enableSmartMFA()
    {
        $this->smartMFA = true;
    }
    /**
     * Disables "smart" multi-factor authentication (MFA)
     */
    public function disableSmartMFA()
    {
        $this->smartMFA = false;
    }
}<?php

/**
 * SFTP Stream Wrapper
 *
 * Creates an sftp:// protocol handler that can be used with, for example, fopen(), dir(), etc.
 *
 * PHP version 5
 *
 * @category  Net
 * @package   SFTP
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2013 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Net\SFTP;

use phpseclib3\Crypt\Common\PrivateKey;
use phpseclib3\Net\SFTP;
use phpseclib3\Net\SSH2;
/**
 * SFTP Stream Wrapper
 *
 * @package SFTP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Stream
{
    /**
     * SFTP instances
     *
     * Rather than re-create the connection we re-use instances if possible
     *
     * @var array
     */
    static $instances;
    /**
     * SFTP instance
     *
     * @var object
     * @access private
     */
    private $sftp;
    /**
     * Path
     *
     * @var string
     * @access private
     */
    private $path;
    /**
     * Mode
     *
     * @var string
     * @access private
     */
    private $mode;
    /**
     * Position
     *
     * @var int
     * @access private
     */
    private $pos;
    /**
     * Size
     *
     * @var int
     * @access private
     */
    private $size;
    /**
     * Directory entries
     *
     * @var array
     * @access private
     */
    private $entries;
    /**
     * EOF flag
     *
     * @var bool
     * @access private
     */
    private $eof;
    /**
     * Context resource
     *
     * Technically this needs to be publicly accessible so PHP can set it directly
     *
     * @var resource
     * @access public
     */
    public $context;
    /**
     * Notification callback function
     *
     * @var callable
     * @access public
     */
    private $notification;
    /**
     * Registers this class as a URL wrapper.
     *
     * @param string $protocol The wrapper name to be registered.
     * @return bool True on success, false otherwise.
     * @access public
     */
    public static function register($protocol = 'sftp')
    {
        if (in_array($protocol, stream_get_wrappers(), true)) {
            return false;
        }
        return stream_wrapper_register($protocol, get_called_class());
    }
    /**
     * The Constructor
     *
     * @access public
     */
    public function __construct()
    {
        if (defined('NET_SFTP_STREAM_LOGGING')) {
            echo "__construct()\r\n";
        }
    }
    /**
    * Path Parser
    *
    * Extract a path from a URI and actually connect to an SSH server if appropriate
    *
    * If "notification" is set as a context parameter the message code for successful login is
    NET_SSH2_MSG_USERAUTH_SUCCESS. For a failed login it's NET_SSH2_MSG_USERAUTH_FAILURE.
    *
    * @param string $path
    * @return string
    * @access private
    */
    protected function parse_path($path)
    {
        $orig = $path;
        extract(parse_url($path) + ['port' => 22]);
        if (isset($query)) {
            $path .= '?' . $query;
        } elseif (preg_match('/(\\?|\\?#)$/', $orig)) {
            $path .= '?';
        }
        if (isset($fragment)) {
            $path .= '#' . $fragment;
        } elseif ($orig[strlen($orig) - 1] == '#') {
            $path .= '#';
        }
        if (!isset($host)) {
            return false;
        }
        if (isset($this->context)) {
            $context = stream_context_get_params($this->context);
            if (isset($context['notification'])) {
                $this->notification = $context['notification'];
            }
        }
        if (preg_match('/^{[a-z0-9]+}$/i', $host)) {
            $host = SSH2::getConnectionByResourceId($host);
            if ($host === false) {
                return false;
            }
            $this->sftp = $host;
        } else {
            if (isset($this->context)) {
                $context = stream_context_get_options($this->context);
            }
            if (isset($context[$scheme]['session'])) {
                $sftp = $context[$scheme]['session'];
            }
            if (isset($context[$scheme]['sftp'])) {
                $sftp = $context[$scheme]['sftp'];
            }
            if (isset($sftp) && $sftp instanceof SFTP) {
                $this->sftp = $sftp;
                return $path;
            }
            if (isset($context[$scheme]['username'])) {
                $user = $context[$scheme]['username'];
            }
            if (isset($context[$scheme]['password'])) {
                $pass = $context[$scheme]['password'];
            }
            if (isset($context[$scheme]['privkey']) && $context[$scheme]['privkey'] instanceof PrivateKey) {
                $pass = $context[$scheme]['privkey'];
            }
            if (!isset($user) || !isset($pass)) {
                return false;
            }
            // casting $pass to a string is necessary in the event that it's a \phpseclib3\Crypt\RSA object
            if (isset(self::$instances[$host][$port][$user][(string) $pass])) {
                $this->sftp = self::$instances[$host][$port][$user][(string) $pass];
            } else {
                $this->sftp = new SFTP($host, $port);
                $this->sftp->disableStatCache();
                if (isset($this->notification) && is_callable($this->notification)) {
                    /* if !is_callable($this->notification) we could do this:
                    
                                           user_error('fopen(): failed to call user notifier', E_USER_WARNING);
                    
                                           the ftp wrapper gives errors like that when the notifier isn't callable.
                                           i've opted not to do that, however, since the ftp wrapper gives the line
                                           on which the fopen occurred as the line number - not the line that the
                                           user_error is on.
                                        */
                    call_user_func($this->notification, STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
                    call_user_func($this->notification, STREAM_NOTIFY_AUTH_REQUIRED, STREAM_NOTIFY_SEVERITY_INFO, '', 0, 0, 0);
                    if (!$this->sftp->login($user, $pass)) {
                        call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_ERR, 'Login Failure', NET_SSH2_MSG_USERAUTH_FAILURE, 0, 0);
                        return false;
                    }
                    call_user_func($this->notification, STREAM_NOTIFY_AUTH_RESULT, STREAM_NOTIFY_SEVERITY_INFO, 'Login Success', NET_SSH2_MSG_USERAUTH_SUCCESS, 0, 0);
                } else {
                    if (!$this->sftp->login($user, $pass)) {
                        return false;
                    }
                }
                self::$instances[$host][$port][$user][(string) $pass] = $this->sftp;
            }
        }
        return $path;
    }
    /**
     * Opens file or URL
     *
     * @param string $path
     * @param string $mode
     * @param int $options
     * @param string $opened_path
     * @return bool
     * @access public
     */
    private function _stream_open($path, $mode, $options, &$opened_path)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        $this->path = $path;
        $this->size = $this->sftp->filesize($path);
        $this->mode = preg_replace('#[bt]$#', '', $mode);
        $this->eof = false;
        if ($this->size === false) {
            if ($this->mode[0] == 'r') {
                return false;
            } else {
                $this->sftp->touch($path);
                $this->size = 0;
            }
        } else {
            switch ($this->mode[0]) {
                case 'x':
                    return false;
                case 'w':
                    $this->sftp->truncate($path, 0);
                    $this->size = 0;
            }
        }
        $this->pos = $this->mode[0] != 'a' ? 0 : $this->size;
        return true;
    }
    /**
     * Read from stream
     *
     * @param int $count
     * @return mixed
     * @access public
     */
    private function _stream_read($count)
    {
        switch ($this->mode) {
            case 'w':
            case 'a':
            case 'x':
            case 'c':
                return false;
        }
        // commented out because some files - eg. /dev/urandom - will say their size is 0 when in fact it's kinda infinite
        //if ($this->pos >= $this->size) {
        //    $this->eof = true;
        //    return false;
        //}
        $result = $this->sftp->get($this->path, false, $this->pos, $count);
        if (isset($this->notification) && is_callable($this->notification)) {
            if ($result === false) {
                call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
                return 0;
            }
            // seems that PHP calls stream_read in 8k chunks
            call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($result), $this->size);
        }
        if (empty($result)) {
            // ie. false or empty string
            $this->eof = true;
            return false;
        }
        $this->pos += strlen($result);
        return $result;
    }
    /**
     * Write to stream
     *
     * @param string $data
     * @return mixed
     * @access public
     */
    private function _stream_write($data)
    {
        switch ($this->mode) {
            case 'r':
                return false;
        }
        $result = $this->sftp->put($this->path, $data, SFTP::SOURCE_STRING, $this->pos);
        if (isset($this->notification) && is_callable($this->notification)) {
            if (!$result) {
                call_user_func($this->notification, STREAM_NOTIFY_FAILURE, STREAM_NOTIFY_SEVERITY_ERR, $this->sftp->getLastSFTPError(), NET_SFTP_OPEN, 0, 0);
                return 0;
            }
            // seems that PHP splits up strings into 8k blocks before calling stream_write
            call_user_func($this->notification, STREAM_NOTIFY_PROGRESS, STREAM_NOTIFY_SEVERITY_INFO, '', 0, strlen($data), strlen($data));
        }
        if ($result === false) {
            return false;
        }
        $this->pos += strlen($data);
        if ($this->pos > $this->size) {
            $this->size = $this->pos;
        }
        $this->eof = false;
        return strlen($data);
    }
    /**
     * Retrieve the current position of a stream
     *
     * @return int
     * @access public
     */
    private function _stream_tell()
    {
        return $this->pos;
    }
    /**
    * Tests for end-of-file on a file pointer
    *
    * In my testing there are four classes functions that normally effect the pointer:
    fseek, fputs  / fwrite, fgets / fread and ftruncate.
    *
    * Only fgets / fread, however, results in feof() returning true. do fputs($fp, 'aaa') on a blank file and feof()
    will return false. do fread($fp, 1) and feof() will then return true. do fseek($fp, 10) on ablank file and feof()
    will return false. do fread($fp, 1) and feof() will then return true.
    *
    * @return bool
    * @access public
    */
    private function _stream_eof()
    {
        return $this->eof;
    }
    /**
     * Seeks to specific location in a stream
     *
     * @param int $offset
     * @param int $whence
     * @return bool
     * @access public
     */
    private function _stream_seek($offset, $whence)
    {
        switch ($whence) {
            case SEEK_SET:
                if ($offset < 0) {
                    return false;
                }
                break;
            case SEEK_CUR:
                $offset += $this->pos;
                break;
            case SEEK_END:
                $offset += $this->size;
        }
        $this->pos = $offset;
        $this->eof = false;
        return true;
    }
    /**
     * Change stream options
     *
     * @param string $path
     * @param int $option
     * @param mixed $var
     * @return bool
     * @access public
     */
    private function _stream_metadata($path, $option, $var)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        // stream_metadata was introduced in PHP 5.4.0 but as of 5.4.11 the constants haven't been defined
        // see http://www.php.net/streamwrapper.stream-metadata and https://bugs.php.net/64246
        //     and https://github.com/php/php-src/blob/master/main/php_streams.h#L592
        switch ($option) {
            case 1:
                // PHP_STREAM_META_TOUCH
                $time = isset($var[0]) ? $var[0] : null;
                $atime = isset($var[1]) ? $var[1] : null;
                return $this->sftp->touch($path, $time, $atime);
            case 2:
            // PHP_STREAM_OWNER_NAME
            case 3:
                // PHP_STREAM_GROUP_NAME
                return false;
            case 4:
                // PHP_STREAM_META_OWNER
                return $this->sftp->chown($path, $var);
            case 5:
                // PHP_STREAM_META_GROUP
                return $this->sftp->chgrp($path, $var);
            case 6:
                // PHP_STREAM_META_ACCESS
                return $this->sftp->chmod($path, $var) !== false;
        }
    }
    /**
     * Retrieve the underlaying resource
     *
     * @param int $cast_as
     * @return resource
     * @access public
     */
    private function _stream_cast($cast_as)
    {
        return $this->sftp->fsock;
    }
    /**
     * Advisory file locking
     *
     * @param int $operation
     * @return bool
     * @access public
     */
    private function _stream_lock($operation)
    {
        return false;
    }
    /**
    * Renames a file or directory
    *
    * Attempts to rename oldname to newname, moving it between directories if necessary.
    If newname exists, it will be overwritten.  This is a departure from what \phpseclib3\Net\SFTP
    does.
    *
    * @param string $path_from
    * @param string $path_to
    * @return bool
    * @access public
    */
    private function _rename($path_from, $path_to)
    {
        $path1 = parse_url($path_from);
        $path2 = parse_url($path_to);
        unset($path1['path'], $path2['path']);
        if ($path1 != $path2) {
            return false;
        }
        $path_from = $this->parse_path($path_from);
        $path_to = parse_url($path_to);
        if ($path_from === false) {
            return false;
        }
        $path_to = $path_to['path'];
        // the $component part of parse_url() was added in PHP 5.1.2
        // "It is an error if there already exists a file with the name specified by newpath."
        //  -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-6.5
        if (!$this->sftp->rename($path_from, $path_to)) {
            if ($this->sftp->stat($path_to)) {
                return $this->sftp->delete($path_to, true) && $this->sftp->rename($path_from, $path_to);
            }
            return false;
        }
        return true;
    }
    /**
    * Open directory handle
    *
    * The only $options is "whether or not to enforce safe_mode (0x04)". Since safe mode was deprecated in 5.3 and
    removed in 5.4 I'm just going to ignore it.
    *
    * Also, nlist() is the best that this function is realistically going to be able to do. When an SFTP client
    sends a SSH_FXP_READDIR packet you don't generally get info on just one file but on multiple files. Quoting
    the SFTP specs:
    *
    * The SSH_FXP_NAME response has the following format:
    *
    * uint32     id
    uint32     count
    repeats count times:
    string     filename
    string     longname
    ATTRS      attrs
    *
    * @param string $path
    * @param int $options
    * @return bool
    * @access public
    */
    private function _dir_opendir($path, $options)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        $this->pos = 0;
        $this->entries = $this->sftp->nlist($path);
        return $this->entries !== false;
    }
    /**
     * Read entry from directory handle
     *
     * @return mixed
     * @access public
     */
    private function _dir_readdir()
    {
        if (isset($this->entries[$this->pos])) {
            return $this->entries[$this->pos++];
        }
        return false;
    }
    /**
     * Rewind directory handle
     *
     * @return bool
     * @access public
     */
    private function _dir_rewinddir()
    {
        $this->pos = 0;
        return true;
    }
    /**
     * Close directory handle
     *
     * @return bool
     * @access public
     */
    private function _dir_closedir()
    {
        return true;
    }
    /**
     * Create a directory
     *
     * Only valid $options is STREAM_MKDIR_RECURSIVE
     *
     * @param string $path
     * @param int $mode
     * @param int $options
     * @return bool
     * @access public
     */
    private function _mkdir($path, $mode, $options)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        return $this->sftp->mkdir($path, $mode, $options & STREAM_MKDIR_RECURSIVE);
    }
    /**
    * Removes a directory
    *
    * Only valid $options is STREAM_MKDIR_RECURSIVE per <http://php.net/streamwrapper.rmdir>, however,
    <http://php.net/rmdir>  does not have a $recursive parameter as mkdir() does so I don't know how
    STREAM_MKDIR_RECURSIVE is supposed to be set. Also, when I try it out with rmdir() I get 8 as
    $options. What does 8 correspond to?
    *
    * @param string $path
    * @param int $options
    * @return bool
    * @access public
    */
    private function _rmdir($path, $options)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        return $this->sftp->rmdir($path);
    }
    /**
     * Flushes the output
     *
     * See <http://php.net/fflush>. Always returns true because \phpseclib3\Net\SFTP doesn't cache stuff before writing
     *
     * @return bool
     * @access public
     */
    private function _stream_flush()
    {
        return true;
    }
    /**
     * Retrieve information about a file resource
     *
     * @return mixed
     * @access public
     */
    private function _stream_stat()
    {
        $results = $this->sftp->stat($this->path);
        if ($results === false) {
            return false;
        }
        return $results;
    }
    /**
     * Delete a file
     *
     * @param string $path
     * @return bool
     * @access public
     */
    private function _unlink($path)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        return $this->sftp->delete($path, false);
    }
    /**
    * Retrieve information about a file
    *
    * Ignores the STREAM_URL_STAT_QUIET flag because the entirety of \phpseclib3\Net\SFTP\Stream is quiet by default
    might be worthwhile to reconstruct bits 12-16 (ie. the file type) if mode doesn't have them but we'll
    cross that bridge when and if it's reached
    *
    * @param string $path
    * @param int $flags
    * @return mixed
    * @access public
    */
    private function _url_stat($path, $flags)
    {
        $path = $this->parse_path($path);
        if ($path === false) {
            return false;
        }
        $results = $flags & STREAM_URL_STAT_LINK ? $this->sftp->lstat($path) : $this->sftp->stat($path);
        if ($results === false) {
            return false;
        }
        return $results;
    }
    /**
     * Truncate stream
     *
     * @param int $new_size
     * @return bool
     * @access public
     */
    private function _stream_truncate($new_size)
    {
        if (!$this->sftp->truncate($this->path, $new_size)) {
            return false;
        }
        $this->eof = false;
        $this->size = $new_size;
        return true;
    }
    /**
    * Change stream options
    *
    * STREAM_OPTION_WRITE_BUFFER isn't supported for the same reason stream_flush isn't.
    The other two aren't supported because of limitations in \phpseclib3\Net\SFTP.
    *
    * @param int $option
    * @param int $arg1
    * @param int $arg2
    * @return bool
    * @access public
    */
    private function _stream_set_option($option, $arg1, $arg2)
    {
        return false;
    }
    /**
     * Close an resource
     *
     * @access public
     */
    private function _stream_close()
    {
    }
    /**
    * __call Magic Method
    *
    * When you're utilizing an SFTP stream you're not calling the methods in this class directly - PHP is calling them for you.
    Which kinda begs the question... what methods is PHP calling and what parameters is it passing to them? This function
    lets you figure that out.
    *
    * If NET_SFTP_STREAM_LOGGING is defined all calls will be output on the screen and then (regardless of whether or not
    NET_SFTP_STREAM_LOGGING is enabled) the parameters will be passed through to the appropriate method.
    *
    * @param string $name
    * @param array $arguments
    * @return mixed
    * @access public
    */
    public function __call($name, $arguments)
    {
        if (defined('NET_SFTP_STREAM_LOGGING')) {
            echo $name . '(';
            $last = count($arguments) - 1;
            foreach ($arguments as $i => $argument) {
                var_export($argument);
                if ($i != $last) {
                    echo ',';
                }
            }
            echo ")\r\n";
        }
        $name = '_' . $name;
        if (!method_exists($this, $name)) {
            return false;
        }
        return $this->{$name}(...$arguments);
    }
}<?php

/**
 * Pure-PHP ssh-agent client.
 *
 * {@internal See http://api.libssh.org/rfc/PROTOCOL.agent}
 *
 * PHP version 5
 *
 * @category  System
 * @package   SSH\Agent
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2009 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\System\SSH\Agent;

use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\EC;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\System\SSH\Agent;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\Common\PrivateKey;
/**
 * Pure-PHP ssh-agent client identity object
 *
 * Instantiation should only be performed by \phpseclib3\System\SSH\Agent class.
 * This could be thought of as implementing an interface that phpseclib3\Crypt\RSA
 * implements. ie. maybe a Net_SSH_Auth_PublicKey interface or something.
 * The methods in this interface would be getPublicKey and sign since those are the
 * methods phpseclib looks for to perform public key authentication.
 *
 * @package SSH\Agent
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  internal
 */
class Identity implements PrivateKey
{
    use \phpseclib3\System\SSH\Common\Traits\ReadBytes;
    // Signature Flags
    // See https://tools.ietf.org/html/draft-miller-ssh-agent-00#section-5.3
    const SSH_AGENT_RSA2_256 = 2;
    const SSH_AGENT_RSA2_512 = 4;
    /**
     * Key Object
     *
     * @var \phpseclib3\Crypt\RSA
     * @access private
     * @see self::getPublicKey()
     */
    private $key;
    /**
     * Key Blob
     *
     * @var string
     * @access private
     * @see self::sign()
     */
    private $key_blob;
    /**
     * Socket Resource
     *
     * @var resource
     * @access private
     * @see self::sign()
     */
    private $fsock;
    /**
     * Signature flags
     *
     * @var int
     * @access private
     * @see self::sign()
     * @see self::setHash()
     */
    private $flags = 0;
    /**
     * Curve Aliases
     *
     * @var array
     * @access private
     */
    private static $curveAliases = ['secp256r1' => 'nistp256', 'secp384r1' => 'nistp384', 'secp521r1' => 'nistp521', 'Ed25519' => 'Ed25519'];
    /**
     * Default Constructor.
     *
     * @param resource $fsock
     * @return \phpseclib3\System\SSH\Agent\Identity
     * @access private
     */
    public function __construct($fsock)
    {
        $this->fsock = $fsock;
    }
    /**
     * Set Public Key
     *
     * Called by \phpseclib3\System\SSH\Agent::requestIdentities()
     *
     * @param \phpseclib3\Crypt\Common\PublicKey $key
     * @access private
     */
    public function withPublicKey($key)
    {
        if ($key instanceof EC) {
            if (is_array($key->getCurve()) || !isset(self::$curveAliases[$key->getCurve()])) {
                throw new UnsupportedAlgorithmException('The only supported curves are nistp256, nistp384, nistp512 and Ed25519');
            }
        }
        $new = clone $this;
        $new->key = $key;
        return $new;
    }
    /**
    * Set Public Key
    *
    * Called by \phpseclib3\System\SSH\Agent::requestIdentities(). The key blob could be extracted from $this->key
    but this saves a small amount of computation.
    *
    * @param string $key_blob
    * @access private
    */
    public function withPublicKeyBlob($key_blob)
    {
        $new = clone $this;
        $new->key_blob = $key_blob;
        return $new;
    }
    /**
     * Get Public Key
     *
     * Wrapper for $this->key->getPublicKey()
     *
     * @param string $type optional
     * @return mixed
     * @access public
     */
    public function getPublicKey($type = 'PKCS8')
    {
        return $this->key;
    }
    /**
     * Sets the hash
     *
     * @param string $hash
     * @access public
     */
    public function withHash($hash)
    {
        $new = clone $this;
        $hash = strtolower($hash);
        if ($this->key instanceof RSA) {
            $new->flags = 0;
            switch ($hash) {
                case 'sha1':
                    break;
                case 'sha256':
                    $new->flags = self::SSH_AGENT_RSA2_256;
                    break;
                case 'sha512':
                    $new->flags = self::SSH_AGENT_RSA2_512;
                    break;
                default:
                    throw new UnsupportedAlgorithmException('The only supported hashes for RSA are sha1, sha256 and sha512');
            }
        }
        if ($this->key instanceof EC) {
            switch ($this->key->getCurve()) {
                case 'secp256r1':
                    $expectedHash = 'sha256';
                    break;
                case 'secp384r1':
                    $expectedHash = 'sha384';
                    break;
                //case 'secp521r1':
                //case 'Ed25519':
                default:
                    $expectedHash = 'sha512';
            }
            if ($hash != $expectedHash) {
                throw new UnsupportedAlgorithmException('The only supported hash for ' . self::$curveAliases[$key->getCurve()] . ' is ' . $expectedHash);
            }
        }
        if ($this->key instanceof DSA) {
            if ($hash != 'sha1') {
                throw new UnsupportedAlgorithmException('The only supported hash for DSA is sha1');
            }
        }
        return $new;
    }
    /**
     * Sets the padding
     *
     * Only PKCS1 padding is supported
     *
     * @param string $padding
     * @access public
     */
    public function withPadding($padding)
    {
        if (!$this->key instanceof RSA) {
            throw new UnsupportedAlgorithmException('Only RSA keys support padding');
        }
        if ($padding != RSA::SIGNATURE_PKCS1 && $padding != RSA::SIGNATURE_RELAXED_PKCS1) {
            throw new UnsupportedAlgorithmException('ssh-agent can only create PKCS1 signatures');
        }
        return $this;
    }
    /**
     * Determines the signature padding mode
     *
     * Valid values are: ASN1, SSH2, Raw
     *
     * @access public
     * @param string $format
     */
    public function withSignatureFormat($format)
    {
        if ($this->key instanceof RSA) {
            throw new UnsupportedAlgorithmException('Only DSA and EC keys support signature format setting');
        }
        if ($format != 'SSH2') {
            throw new UnsupportedAlgorithmException('Only SSH2-formatted signatures are currently supported');
        }
        return $this;
    }
    /**
     * Returns the curve
     *
     * Returns a string if it's a named curve, an array if not
     *
     * @access public
     * @return (string | array)
     */
    public function getCurve()
    {
        if (!$this->key instanceof EC) {
            throw new UnsupportedAlgorithmException('Only EC keys have curves');
        }
        return $this->key->getCurve();
    }
    /**
     * Create a signature
     *
     * See "2.6.2 Protocol 2 private key signature request"
     *
     * @param string $message
     * @return string
     * @throws \RuntimeException on connection errors
     * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
     * @access public
     */
    public function sign($message)
    {
        // the last parameter (currently 0) is for flags and ssh-agent only defines one flag (for ssh-dss): SSH_AGENT_OLD_SIGNATURE
        $packet = Strings::packSSH2('CssN', Agent::SSH_AGENTC_SIGN_REQUEST, $this->key_blob, $message, $this->flags);
        $packet = Strings::packSSH2('s', $packet);
        if (strlen($packet) != fputs($this->fsock, $packet)) {
            throw new \RuntimeException('Connection closed during signing');
        }
        $length = current(unpack('N', $this->readBytes(4)));
        $packet = $this->readBytes($length);
        list($type, $signature_blob) = Strings::unpackSSH2('Cs', $packet);
        if ($type != Agent::SSH_AGENT_SIGN_RESPONSE) {
            throw new \RuntimeException('Unable to retrieve signature');
        }
        if (!$this->key instanceof RSA) {
            return $signature_blob;
        }
        list($type, $signature_blob) = Strings::unpackSSH2('ss', $signature_blob);
        return $signature_blob;
    }
    /**
     * Returns the private key
     *
     * @param string $type
     * @param array $options optional
     * @return string
     */
    public function toString($type, array $options = [])
    {
        throw new \RuntimeException('ssh-agent does not provide a mechanism to get the private key');
    }
    /**
     * Sets the password
     *
     * @access public
     * @param (string | boolean) $password
     */
    public function withPassword($password = false)
    {
        throw new \RuntimeException('ssh-agent does not provide a mechanism to get the private key');
    }
}<?php

/**
 * ReadBytes trait
 *
 * PHP version 5
 *
 * @category  System
 * @package   SSH
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\System\SSH\Common\Traits;

/**
 * ReadBytes trait
 *
 * @package SSH
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
trait ReadBytes
{
    /**
     * Read data
     *
     * @param int $length
     * @throws \RuntimeException on connection errors
     * @access public
     */
    public function readBytes($length)
    {
        $temp = fread($this->fsock, $length);
        if (strlen($temp) != $length) {
            throw new \RuntimeException("Expected {$length} bytes; got " . strlen($temp));
        }
        return $temp;
    }
}<?php

/**
 * Pure-PHP ssh-agent client.
 *
 * {@internal See http://api.libssh.org/rfc/PROTOCOL.agent}
 *
 * PHP version 5
 *
 * Here are some examples of how to use this library:
 * <code>
 * <?php
 *    include 'vendor/autoload.php';
 *
 *    $agent = new \phpseclib3\System\SSH\Agent();
 *
 *    $ssh = new \phpseclib3\Net\SSH2('www.domain.tld');
 *    if (!$ssh->login('username', $agent)) {
 *        exit('Login Failed');
 *    }
 *
 *    echo $ssh->exec('pwd');
 *    echo $ssh->exec('ls -la');
 * ?>
 * </code>
 *
 * @category  System
 * @package   SSH\Agent
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2014 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\System\SSH;

use phpseclib3\Crypt\RSA;
use phpseclib3\Exception\BadConfigurationException;
use phpseclib3\System\SSH\Agent\Identity;
use phpseclib3\Common\Functions\Strings;
use phpseclib3\Crypt\PublicKeyLoader;
/**
 * Pure-PHP ssh-agent client identity factory
 *
 * requestIdentities() method pumps out \phpseclib3\System\SSH\Agent\Identity objects
 *
 * @package SSH\Agent
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Agent
{
    use Common\Traits\ReadBytes;
    // Message numbers
    // to request SSH1 keys you have to use SSH_AGENTC_REQUEST_RSA_IDENTITIES (1)
    const SSH_AGENTC_REQUEST_IDENTITIES = 11;
    // this is the SSH2 response; the SSH1 response is SSH_AGENT_RSA_IDENTITIES_ANSWER (2).
    const SSH_AGENT_IDENTITIES_ANSWER = 12;
    // the SSH1 request is SSH_AGENTC_RSA_CHALLENGE (3)
    const SSH_AGENTC_SIGN_REQUEST = 13;
    // the SSH1 response is SSH_AGENT_RSA_RESPONSE (4)
    const SSH_AGENT_SIGN_RESPONSE = 14;
    // Agent forwarding status
    // no forwarding requested and not active
    const FORWARD_NONE = 0;
    // request agent forwarding when opportune
    const FORWARD_REQUEST = 1;
    // forwarding has been request and is active
    const FORWARD_ACTIVE = 2;
    /**
     * Unused
     */
    const SSH_AGENT_FAILURE = 5;
    /**
     * Socket Resource
     *
     * @var resource
     * @access private
     */
    private $fsock;
    /**
     * Agent forwarding status
     *
     * @var int
     * @access private
     */
    private $forward_status = self::FORWARD_NONE;
    /**
     * Buffer for accumulating forwarded authentication
     * agent data arriving on SSH data channel destined
     * for agent unix socket
     *
     * @var string
     * @access private
     */
    private $socket_buffer = '';
    /**
     * Tracking the number of bytes we are expecting
     * to arrive for the agent socket on the SSH data
     * channel
     *
     * @var int
     * @access private
     */
    private $expected_bytes = 0;
    /**
     * The current request channel
     *
     * @var int
     * @access private
     */
    private $request_channel;
    /**
     * Default Constructor
     *
     * @return \phpseclib3\System\SSH\Agent
     * @throws \phpseclib3\Exception\BadConfigurationException if SSH_AUTH_SOCK cannot be found
     * @throws \RuntimeException on connection errors
     * @access public
     */
    public function __construct($address = null)
    {
        if (!$address) {
            switch (true) {
                case isset($_SERVER['SSH_AUTH_SOCK']):
                    $address = $_SERVER['SSH_AUTH_SOCK'];
                    break;
                case isset($_ENV['SSH_AUTH_SOCK']):
                    $address = $_ENV['SSH_AUTH_SOCK'];
                    break;
                default:
                    throw new BadConfigurationException('SSH_AUTH_SOCK not found');
            }
        }
        $this->fsock = \Phabel\Target\Php80\Polyfill::fsockopen('unix://' . $address, 0, $errno, $errstr);
        if (!$this->fsock) {
            throw new \RuntimeException("Unable to connect to ssh-agent (Error {$errno}: {$errstr})");
        }
    }
    /**
    * Request Identities
    *
    * See "2.5.2 Requesting a list of protocol 2 keys"
    Returns an array containing zero or more \phpseclib3\System\SSH\Agent\Identity objects
    *
    * @return array
    * @throws \RuntimeException on receipt of unexpected packets
    * @access public
    */
    public function requestIdentities()
    {
        if (!$this->fsock) {
            return [];
        }
        $packet = pack('NC', 1, self::SSH_AGENTC_REQUEST_IDENTITIES);
        if (strlen($packet) != fputs($this->fsock, $packet)) {
            throw new \RuntimeException('Connection closed while requesting identities');
        }
        $length = current(unpack('N', $this->readBytes(4)));
        $packet = $this->readBytes($length);
        list($type, $keyCount) = Strings::unpackSSH2('CN', $packet);
        if ($type != self::SSH_AGENT_IDENTITIES_ANSWER) {
            throw new \RuntimeException('Unable to request identities');
        }
        $identities = [];
        for ($i = 0; $i < $keyCount; $i++) {
            list($key_blob, $comment) = Strings::unpackSSH2('ss', $packet);
            $temp = $key_blob;
            list($key_type) = Strings::unpackSSH2('s', $temp);
            switch ($key_type) {
                case 'ssh-rsa':
                case 'ssh-dss':
                case 'ssh-ed25519':
                case 'ecdsa-sha2-nistp256':
                case 'ecdsa-sha2-nistp384':
                case 'ecdsa-sha2-nistp521':
                    $key = PublicKeyLoader::load($key_type . ' ' . base64_encode($key_blob));
            }
            // resources are passed by reference by default
            if (isset($key)) {
                $identity = (new Identity($this->fsock))->withPublicKey($key)->withPublicKeyBlob($key_blob);
                $identities[] = $identity;
                unset($key);
            }
        }
        return $identities;
    }
    /**
    * Signal that agent forwarding should
    be requested when a channel is opened
    *
    * @param \phpseclib3\Net\SSH2 $ssh
    * @return bool
    * @access public
    */
    public function startSSHForwarding($ssh)
    {
        if ($this->forward_status == self::FORWARD_NONE) {
            $this->forward_status = self::FORWARD_REQUEST;
        }
    }
    /**
     * Request agent forwarding of remote server
     *
     * @param \phpseclib3\Net\SSH2 $ssh
     * @return bool
     * @access private
     */
    private function request_forwarding($ssh)
    {
        if (!$ssh->requestAgentForwarding()) {
            return false;
        }
        $this->forward_status = self::FORWARD_ACTIVE;
        return true;
    }
    /**
    * On successful channel open
    *
    * This method is called upon successful channel
    open to give the SSH Agent an opportunity
    to take further action. i.e. request agent forwarding
    *
    * @param \phpseclib3\Net\SSH2 $ssh
    * @access private
    */
    public function registerChannelOpen($ssh)
    {
        if ($this->forward_status == self::FORWARD_REQUEST) {
            $this->request_forwarding($ssh);
        }
    }
    /**
     * Forward data to SSH Agent and return data reply
     *
     * @param string $data
     * @return string Data from SSH Agent
     * @throws \RuntimeException on connection errors
     * @access public
     */
    public function forwardData($data)
    {
        if ($this->expected_bytes > 0) {
            $this->socket_buffer .= $data;
            $this->expected_bytes -= strlen($data);
        } else {
            $agent_data_bytes = current(unpack('N', $data));
            $current_data_bytes = strlen($data);
            $this->socket_buffer = $data;
            if ($current_data_bytes != $agent_data_bytes + 4) {
                $this->expected_bytes = $agent_data_bytes + 4 - $current_data_bytes;
                return false;
            }
        }
        if (strlen($this->socket_buffer) != fwrite($this->fsock, $this->socket_buffer)) {
            throw new \RuntimeException('Connection closed attempting to forward data to SSH agent');
        }
        $this->socket_buffer = '';
        $this->expected_bytes = 0;
        $agent_reply_bytes = current(unpack('N', $this->readBytes(4)));
        $agent_reply_data = $this->readBytes($agent_reply_bytes);
        $agent_reply_data = current(unpack('a*', $agent_reply_data));
        return pack('Na*', $agent_reply_bytes, $agent_reply_data);
    }
}<?php

/**
 * Pure-PHP ASN.1 Parser
 *
 * PHP version 5
 *
 * ASN.1 provides the semantics for data encoded using various schemes.  The most commonly
 * utilized scheme is DER or the "Distinguished Encoding Rules".  PEM's are base64 encoded
 * DER blobs.
 *
 * \phpseclib3\File\ASN1 decodes and encodes DER formatted messages and places them in a semantic context.
 *
 * Uses the 1988 ASN.1 syntax.
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2012 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File;

use ParagonIE\ConstantTime\Base64;
use phpseclib3\File\ASN1\Element;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
use DateTime;
use DateTimeZone;
/**
 * Pure-PHP ASN.1 Parser
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ASN1
{
    // Tag Classes
    // http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=12
    const CLASS_UNIVERSAL = 0;
    const CLASS_APPLICATION = 1;
    const CLASS_CONTEXT_SPECIFIC = 2;
    const CLASS_PRIVATE = 3;
    // Tag Classes
    // http://www.obj-sys.com/asn1tutorial/node124.html
    const TYPE_BOOLEAN = 1;
    const TYPE_INTEGER = 2;
    const TYPE_BIT_STRING = 3;
    const TYPE_OCTET_STRING = 4;
    const TYPE_NULL = 5;
    const TYPE_OBJECT_IDENTIFIER = 6;
    //const TYPE_OBJECT_DESCRIPTOR = 7;
    //const TYPE_INSTANCE_OF       = 8; // EXTERNAL
    const TYPE_REAL = 9;
    const TYPE_ENUMERATED = 10;
    //const TYPE_EMBEDDED          = 11;
    const TYPE_UTF8_STRING = 12;
    //const TYPE_RELATIVE_OID      = 13;
    const TYPE_SEQUENCE = 16;
    // SEQUENCE OF
    const TYPE_SET = 17;
    // SET OF
    // More Tag Classes
    // http://www.obj-sys.com/asn1tutorial/node10.html
    const TYPE_NUMERIC_STRING = 18;
    const TYPE_PRINTABLE_STRING = 19;
    const TYPE_TELETEX_STRING = 20;
    // T61String
    const TYPE_VIDEOTEX_STRING = 21;
    const TYPE_IA5_STRING = 22;
    const TYPE_UTC_TIME = 23;
    const TYPE_GENERALIZED_TIME = 24;
    const TYPE_GRAPHIC_STRING = 25;
    const TYPE_VISIBLE_STRING = 26;
    // ISO646String
    const TYPE_GENERAL_STRING = 27;
    const TYPE_UNIVERSAL_STRING = 28;
    //const TYPE_CHARACTER_STRING = 29;
    const TYPE_BMP_STRING = 30;
    // Tag Aliases
    // These tags are kinda place holders for other tags.
    const TYPE_CHOICE = -1;
    const TYPE_ANY = -2;
    /**
     * ASN.1 object identifiers
     *
     * @var array
     * @access private
     * @link http://en.wikipedia.org/wiki/Object_identifier
     */
    private static $oids = [];
    /**
     * ASN.1 object identifier reverse mapping
     *
     * @var array
     * @access private
     */
    private static $reverseOIDs = [];
    /**
     * Default date format
     *
     * @var string
     * @access private
     * @link http://php.net/class.datetime
     */
    private static $format = 'D, d M Y H:i:s O';
    /**
     * Filters
     *
     * If the mapping type is self::TYPE_ANY what do we actually encode it as?
     *
     * @var array
     * @access private
     * @see self::encode_der()
     */
    private static $filters;
    /**
     * Current Location of most recent ASN.1 encode process
     *
     * Useful for debug purposes
     *
     * @var array
     * @access private
     * @see self::encode_der()
     */
    private static $location;
    /**
     * DER Encoded String
     *
     * In case we need to create ASN1\Element object's..
     *
     * @var string
     * @access private
     * @see self::decodeDER()
     */
    private static $encoded;
    /**
     * Type mapping table for the ANY type.
     *
     * Structured or unknown types are mapped to a \phpseclib3\File\ASN1\Element.
     * Unambiguous types get the direct mapping (int/real/bool).
     * Others are mapped as a choice, with an extra indexing level.
     *
     * @var array
     * @access public
     */
    const ANY_MAP = [
        self::TYPE_BOOLEAN => true,
        self::TYPE_INTEGER => true,
        self::TYPE_BIT_STRING => 'bitString',
        self::TYPE_OCTET_STRING => 'octetString',
        self::TYPE_NULL => 'null',
        self::TYPE_OBJECT_IDENTIFIER => 'objectIdentifier',
        self::TYPE_REAL => true,
        self::TYPE_ENUMERATED => 'enumerated',
        self::TYPE_UTF8_STRING => 'utf8String',
        self::TYPE_NUMERIC_STRING => 'numericString',
        self::TYPE_PRINTABLE_STRING => 'printableString',
        self::TYPE_TELETEX_STRING => 'teletexString',
        self::TYPE_VIDEOTEX_STRING => 'videotexString',
        self::TYPE_IA5_STRING => 'ia5String',
        self::TYPE_UTC_TIME => 'utcTime',
        self::TYPE_GENERALIZED_TIME => 'generalTime',
        self::TYPE_GRAPHIC_STRING => 'graphicString',
        self::TYPE_VISIBLE_STRING => 'visibleString',
        self::TYPE_GENERAL_STRING => 'generalString',
        self::TYPE_UNIVERSAL_STRING => 'universalString',
        //self::TYPE_CHARACTER_STRING     => 'characterString',
        self::TYPE_BMP_STRING => 'bmpString',
    ];
    /**
     * String type to character size mapping table.
     *
     * Non-convertable types are absent from this table.
     * size == 0 indicates variable length encoding.
     *
     * @var array
     * @access public
     */
    const STRING_TYPE_SIZE = [self::TYPE_UTF8_STRING => 0, self::TYPE_BMP_STRING => 2, self::TYPE_UNIVERSAL_STRING => 4, self::TYPE_PRINTABLE_STRING => 1, self::TYPE_TELETEX_STRING => 1, self::TYPE_IA5_STRING => 1, self::TYPE_VISIBLE_STRING => 1];
    /**
     * Parse BER-encoding
     *
     * Serves a similar purpose to openssl's asn1parse
     *
     * @param string $encoded
     * @return array
     * @access public
     */
    public static function decodeBER($encoded)
    {
        if ($encoded instanceof Element) {
            $encoded = $encoded->element;
        }
        self::$encoded = $encoded;
        $decoded = [self::decode_ber($encoded)];
        // encapsulate in an array for BC with the old decodeBER
        return $decoded;
    }
    /**
    * Parse BER-encoding (Helper function)
    *
    * Sometimes we want to get the BER encoding of a particular tag.  $start lets us do that without having to reencode.
    $encoded is passed by reference for the recursive calls done for self::TYPE_BIT_STRING and
    self::TYPE_OCTET_STRING. In those cases, the indefinite length is used.
    *
    * @param string $encoded
    * @param int $start
    * @param int $encoded_pos
    * @return (array | bool)
    * @access private
    */
    private static function decode_ber($encoded, $start = 0, $encoded_pos = 0)
    {
        $current = ['start' => $start];
        if (!isset($encoded[$encoded_pos])) {
            return false;
        }
        $type = ord($encoded[$encoded_pos++]);
        $startOffset = 1;
        $constructed = $type >> 5 & 1;
        $tag = $type & 0x1f;
        if ($tag == 0x1f) {
            $tag = 0;
            // process septets (since the eighth bit is ignored, it's not an octet)
            do {
                if (!isset($encoded[$encoded_pos])) {
                    return false;
                }
                $temp = ord($encoded[$encoded_pos++]);
                $startOffset++;
                $loop = $temp >> 7;
                $tag <<= 7;
                $temp &= 0x7f;
                // "bits 7 to 1 of the first subsequent octet shall not all be zero"
                if ($startOffset == 2 && $temp == 0) {
                    return false;
                }
                $tag |= $temp;
            } while ($loop);
        }
        $start += $startOffset;
        // Length, as discussed in paragraph 8.1.3 of X.690-0207.pdf#page=13
        if (!isset($encoded[$encoded_pos])) {
            return false;
        }
        $length = ord($encoded[$encoded_pos++]);
        $start++;
        if ($length == 0x80) {
            // indefinite length
            // "[A sender shall] use the indefinite form (see 8.1.3.6) if the encoding is constructed and is not all
            //  immediately available." -- paragraph 8.1.3.2.c
            $length = strlen($encoded) - $encoded_pos;
        } elseif ($length & 0x80) {
            // definite length, long form
            // technically, the long form of the length can be represented by up to 126 octets (bytes), but we'll only
            // support it up to four.
            $length &= 0x7f;
            $temp = \Phabel\Target\Php80\Polyfill::substr($encoded, $encoded_pos, $length);
            $encoded_pos += $length;
            // tags of indefinte length don't really have a header length; this length includes the tag
            $current += ['headerlength' => $length + 2];
            $start += $length;
            extract(unpack('Nlength', \Phabel\Target\Php80\Polyfill::substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4)));
            /** @var integer $length */
        } else {
            $current += ['headerlength' => 2];
        }
        if ($length > strlen($encoded) - $encoded_pos) {
            return false;
        }
        $content = \Phabel\Target\Php80\Polyfill::substr($encoded, $encoded_pos, $length);
        $content_pos = 0;
        // at this point $length can be overwritten. it's only accurate for definite length things as is
        /* Class is UNIVERSAL, APPLICATION, PRIVATE, or CONTEXT-SPECIFIC. The UNIVERSAL class is restricted to the ASN.1
                   built-in types. It defines an application-independent data type that must be distinguishable from all other
                   data types. The other three classes are user defined. The APPLICATION class distinguishes data types that
                   have a wide, scattered use within a particular presentation context. PRIVATE distinguishes data types within
                   a particular organization or country. CONTEXT-SPECIFIC distinguishes members of a sequence or set, the
                   alternatives of a CHOICE, or universally tagged set members. Only the class number appears in braces for this
                   data type; the term CONTEXT-SPECIFIC does not appear.
        
                     -- http://www.obj-sys.com/asn1tutorial/node12.html */
        $class = $type >> 6 & 3;
        switch ($class) {
            case self::CLASS_APPLICATION:
            case self::CLASS_PRIVATE:
            case self::CLASS_CONTEXT_SPECIFIC:
                if (!$constructed) {
                    return ['type' => $class, 'constant' => $tag, 'content' => $content, 'length' => $length + $start - $current['start']] + $current;
                }
                $newcontent = [];
                $remainingLength = $length;
                while ($remainingLength > 0) {
                    $temp = self::decode_ber($content, $start, $content_pos);
                    if ($temp === false) {
                        break;
                    }
                    $length = $temp['length'];
                    // end-of-content octets - see paragraph 8.1.5
                    if (\Phabel\Target\Php80\Polyfill::substr($content, $content_pos + $length, 2) == "\x00\x00") {
                        $length += 2;
                        $start += $length;
                        $newcontent[] = $temp;
                        break;
                    }
                    $start += $length;
                    $remainingLength -= $length;
                    $newcontent[] = $temp;
                    $content_pos += $length;
                }
                return [
                    'type' => $class,
                    'constant' => $tag,
                    // the array encapsulation is for BC with the old format
                    'content' => $newcontent,
                    // the only time when $content['headerlength'] isn't defined is when the length is indefinite.
                    // the absence of $content['headerlength'] is how we know if something is indefinite or not.
                    // technically, it could be defined to be 2 and then another indicator could be used but whatever.
                    'length' => $start - $current['start'],
                ] + $current;
        }
        $current += ['type' => $tag];
        // decode UNIVERSAL tags
        switch ($tag) {
            case self::TYPE_BOOLEAN:
                // "The contents octets shall consist of a single octet." -- paragraph 8.2.1
                if ($constructed || strlen($content) != 1) {
                    return false;
                }
                $current['content'] = (bool) ord($content[$content_pos]);
                break;
            case self::TYPE_INTEGER:
            case self::TYPE_ENUMERATED:
                if ($constructed) {
                    return false;
                }
                $current['content'] = new BigInteger(\Phabel\Target\Php80\Polyfill::substr($content, $content_pos), -256);
                break;
            case self::TYPE_REAL:
                // not currently supported
                return false;
            case self::TYPE_BIT_STRING:
                // The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
                // the number of unused bits in the final subsequent octet. The number shall be in the range zero to
                // seven.
                if (!$constructed) {
                    $current['content'] = \Phabel\Target\Php80\Polyfill::substr($content, $content_pos);
                } else {
                    $temp = self::decode_ber($content, $start, $content_pos);
                    if ($temp === false) {
                        return false;
                    }
                    $length -= strlen($content) - $content_pos;
                    $last = count($temp) - 1;
                    for ($i = 0; $i < $last; $i++) {
                        // all subtags should be bit strings
                        if ($temp[$i]['type'] != self::TYPE_BIT_STRING) {
                            return false;
                        }
                        $current['content'] .= \Phabel\Target\Php80\Polyfill::substr($temp[$i]['content'], 1);
                    }
                    // all subtags should be bit strings
                    if ($temp[$last]['type'] != self::TYPE_BIT_STRING) {
                        return false;
                    }
                    $current['content'] = $temp[$last]['content'][0] . $current['content'] . \Phabel\Target\Php80\Polyfill::substr($temp[$i]['content'], 1);
                }
                break;
            case self::TYPE_OCTET_STRING:
                if (!$constructed) {
                    $current['content'] = \Phabel\Target\Php80\Polyfill::substr($content, $content_pos);
                } else {
                    $current['content'] = '';
                    $length = 0;
                    while (\Phabel\Target\Php80\Polyfill::substr($content, $content_pos, 2) != "\x00\x00") {
                        $temp = self::decode_ber($content, $length + $start, $content_pos);
                        if ($temp === false) {
                            return false;
                        }
                        $content_pos += $temp['length'];
                        // all subtags should be octet strings
                        if ($temp['type'] != self::TYPE_OCTET_STRING) {
                            return false;
                        }
                        $current['content'] .= $temp['content'];
                        $length += $temp['length'];
                    }
                    if (\Phabel\Target\Php80\Polyfill::substr($content, $content_pos, 2) == "\x00\x00") {
                        $length += 2;
                        // +2 for the EOC
                    }
                }
                break;
            case self::TYPE_NULL:
                // "The contents octets shall not contain any octets." -- paragraph 8.8.2
                if ($constructed || strlen($content)) {
                    return false;
                }
                break;
            case self::TYPE_SEQUENCE:
            case self::TYPE_SET:
                if (!$constructed) {
                    return false;
                }
                $offset = 0;
                $current['content'] = [];
                $content_len = strlen($content);
                while ($content_pos < $content_len) {
                    // if indefinite length construction was used and we have an end-of-content string next
                    // see paragraphs 8.1.1.3, 8.1.3.2, 8.1.3.6, 8.1.5, and (for an example) 8.6.4.2
                    if (!isset($current['headerlength']) && \Phabel\Target\Php80\Polyfill::substr($content, $content_pos, 2) == "\x00\x00") {
                        $length = $offset + 2;
                        // +2 for the EOC
                        break 2;
                    }
                    $temp = self::decode_ber($content, $start + $offset, $content_pos);
                    if ($temp === false) {
                        return false;
                    }
                    $content_pos += $temp['length'];
                    $current['content'][] = $temp;
                    $offset += $temp['length'];
                }
                break;
            case self::TYPE_OBJECT_IDENTIFIER:
                if ($constructed) {
                    return false;
                }
                $current['content'] = self::decodeOID(\Phabel\Target\Php80\Polyfill::substr($content, $content_pos));
                if ($current['content'] === false) {
                    return false;
                }
                break;
            /* Each character string type shall be encoded as if it had been declared:
                           [UNIVERSAL x] IMPLICIT OCTET STRING
            
                             -- X.690-0207.pdf#page=23 (paragraph 8.21.3)
            
                           Per that, we're not going to do any validation.  If there are any illegal characters in the string,
                           we don't really care */
            case self::TYPE_NUMERIC_STRING:
            // 0,1,2,3,4,5,6,7,8,9, and space
            case self::TYPE_PRINTABLE_STRING:
            // Upper and lower case letters, digits, space, apostrophe, left/right parenthesis, plus sign, comma,
            // hyphen, full stop, solidus, colon, equal sign, question mark
            case self::TYPE_TELETEX_STRING:
            // The Teletex character set in CCITT's T61, space, and delete
            // see http://en.wikipedia.org/wiki/Teletex#Character_sets
            case self::TYPE_VIDEOTEX_STRING:
            // The Videotex character set in CCITT's T.100 and T.101, space, and delete
            case self::TYPE_VISIBLE_STRING:
            // Printing character sets of international ASCII, and space
            case self::TYPE_IA5_STRING:
            // International Alphabet 5 (International ASCII)
            case self::TYPE_GRAPHIC_STRING:
            // All registered G sets, and space
            case self::TYPE_GENERAL_STRING:
            // All registered C and G sets, space and delete
            case self::TYPE_UTF8_STRING:
            // ????
            case self::TYPE_BMP_STRING:
                if ($constructed) {
                    return false;
                }
                $current['content'] = \Phabel\Target\Php80\Polyfill::substr($content, $content_pos);
                break;
            case self::TYPE_UTC_TIME:
            case self::TYPE_GENERALIZED_TIME:
                if ($constructed) {
                    return false;
                }
                $current['content'] = self::decodeTime(\Phabel\Target\Php80\Polyfill::substr($content, $content_pos), $tag);
                break;
            default:
                return false;
        }
        $start += $length;
        // ie. length is the length of the full TLV encoding - it's not just the length of the value
        return $current + ['length' => $start - $current['start']];
    }
    /**
     * ASN.1 Map
     *
     * Provides an ASN.1 semantic mapping ($mapping) from a parsed BER-encoding to a human readable format.
     *
     * "Special" mappings may be applied on a per tag-name basis via $special.
     *
     * @param array $decoded
     * @param array $mapping
     * @param array $special
     * @return (array | bool | Element)
     * @access public
     */
    public static function asn1map($decoded, $mapping, $special = [])
    {
        if (!is_array($decoded)) {
            return false;
        }
        if (isset($mapping['explicit']) && is_array($decoded['content'])) {
            $decoded = $decoded['content'][0];
        }
        switch (true) {
            case $mapping['type'] == self::TYPE_ANY:
                $intype = $decoded['type'];
                // !isset(self::ANY_MAP[$intype]) produces a fatal error on PHP 5.6
                if (isset($decoded['constant']) || !array_key_exists($intype, self::ANY_MAP) || ord(self::$encoded[$decoded['start']]) & 0x20) {
                    return new Element(\Phabel\Target\Php80\Polyfill::substr(self::$encoded, $decoded['start'], $decoded['length']));
                }
                $inmap = self::ANY_MAP[$intype];
                if (is_string($inmap)) {
                    return [$inmap => self::asn1map($decoded, ['type' => $intype] + $mapping, $special)];
                }
                break;
            case $mapping['type'] == self::TYPE_CHOICE:
                foreach ($mapping['children'] as $key => $option) {
                    switch (true) {
                        case isset($option['constant']) && $option['constant'] == $decoded['constant']:
                        case !isset($option['constant']) && $option['type'] == $decoded['type']:
                            $value = self::asn1map($decoded, $option, $special);
                            break;
                        case !isset($option['constant']) && $option['type'] == self::TYPE_CHOICE:
                            $v = self::asn1map($decoded, $option, $special);
                            if (isset($v)) {
                                $value = $v;
                            }
                    }
                    if (isset($value)) {
                        if (isset($special[$key])) {
                            $value = $special[$key]($value);
                        }
                        return [$key => $value];
                    }
                }
                return null;
            case isset($mapping['implicit']):
            case isset($mapping['explicit']):
            case $decoded['type'] == $mapping['type']:
                break;
            default:
                // if $decoded['type'] and $mapping['type'] are both strings, but different types of strings,
                // let it through
                switch (true) {
                    case $decoded['type'] < 18:
                    // self::TYPE_NUMERIC_STRING == 18
                    case $decoded['type'] > 30:
                    // self::TYPE_BMP_STRING == 30
                    case $mapping['type'] < 18:
                    case $mapping['type'] > 30:
                        return null;
                }
        }
        if (isset($mapping['implicit'])) {
            $decoded['type'] = $mapping['type'];
        }
        switch ($decoded['type']) {
            case self::TYPE_SEQUENCE:
                $map = [];
                // ignore the min and max
                if (isset($mapping['min']) && isset($mapping['max'])) {
                    $child = $mapping['children'];
                    foreach ($decoded['content'] as $content) {
                        if (($map[] = self::asn1map($content, $child, $special)) === null) {
                            return null;
                        }
                    }
                    return $map;
                }
                $n = count($decoded['content']);
                $i = 0;
                foreach ($mapping['children'] as $key => $child) {
                    $maymatch = $i < $n;
                    // Match only existing input.
                    if ($maymatch) {
                        $temp = $decoded['content'][$i];
                        if ($child['type'] != self::TYPE_CHOICE) {
                            // Get the mapping and input class & constant.
                            $childClass = $tempClass = self::CLASS_UNIVERSAL;
                            $constant = null;
                            if (isset($temp['constant'])) {
                                $tempClass = $temp['type'];
                            }
                            if (isset($child['class'])) {
                                $childClass = $child['class'];
                                $constant = $child['cast'];
                            } elseif (isset($child['constant'])) {
                                $childClass = self::CLASS_CONTEXT_SPECIFIC;
                                $constant = $child['constant'];
                            }
                            if (isset($constant) && isset($temp['constant'])) {
                                // Can only match if constants and class match.
                                $maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
                            } else {
                                // Can only match if no constant expected and type matches or is generic.
                                $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false;
                            }
                        }
                    }
                    if ($maymatch) {
                        // Attempt submapping.
                        $candidate = self::asn1map($temp, $child, $special);
                        $maymatch = $candidate !== null;
                    }
                    if ($maymatch) {
                        // Got the match: use it.
                        if (isset($special[$key])) {
                            $candidate = $special[$key]($candidate);
                        }
                        $map[$key] = $candidate;
                        $i++;
                    } elseif (isset($child['default'])) {
                        $map[$key] = $child['default'];
                    } elseif (!isset($child['optional'])) {
                        return null;
                        // Syntax error.
                    }
                }
                // Fail mapping if all input items have not been consumed.
                return $i < $n ? null : $map;
            // the main diff between sets and sequences is the encapsulation of the foreach in another for loop
            case self::TYPE_SET:
                $map = [];
                // ignore the min and max
                if (isset($mapping['min']) && isset($mapping['max'])) {
                    $child = $mapping['children'];
                    foreach ($decoded['content'] as $content) {
                        if (($map[] = self::asn1map($content, $child, $special)) === null) {
                            return null;
                        }
                    }
                    return $map;
                }
                for ($i = 0; $i < count($decoded['content']); $i++) {
                    $temp = $decoded['content'][$i];
                    $tempClass = self::CLASS_UNIVERSAL;
                    if (isset($temp['constant'])) {
                        $tempClass = $temp['type'];
                    }
                    foreach ($mapping['children'] as $key => $child) {
                        if (isset($map[$key])) {
                            continue;
                        }
                        $maymatch = true;
                        if ($child['type'] != self::TYPE_CHOICE) {
                            $childClass = self::CLASS_UNIVERSAL;
                            $constant = null;
                            if (isset($child['class'])) {
                                $childClass = $child['class'];
                                $constant = $child['cast'];
                            } elseif (isset($child['constant'])) {
                                $childClass = self::CLASS_CONTEXT_SPECIFIC;
                                $constant = $child['constant'];
                            }
                            if (isset($constant) && isset($temp['constant'])) {
                                // Can only match if constants and class match.
                                $maymatch = $constant == $temp['constant'] && $childClass == $tempClass;
                            } else {
                                // Can only match if no constant expected and type matches or is generic.
                                $maymatch = !isset($child['constant']) && array_search($child['type'], [$temp['type'], self::TYPE_ANY, self::TYPE_CHOICE]) !== false;
                            }
                        }
                        if ($maymatch) {
                            // Attempt submapping.
                            $candidate = self::asn1map($temp, $child, $special);
                            $maymatch = $candidate !== null;
                        }
                        if (!$maymatch) {
                            break;
                        }
                        // Got the match: use it.
                        if (isset($special[$key])) {
                            $candidate = $special[$key]($candidate);
                        }
                        $map[$key] = $candidate;
                        break;
                    }
                }
                foreach ($mapping['children'] as $key => $child) {
                    if (!isset($map[$key])) {
                        if (isset($child['default'])) {
                            $map[$key] = $child['default'];
                        } elseif (!isset($child['optional'])) {
                            return null;
                        }
                    }
                }
                return $map;
            case self::TYPE_OBJECT_IDENTIFIER:
                return isset(self::$oids[$decoded['content']]) ? self::$oids[$decoded['content']] : $decoded['content'];
            case self::TYPE_UTC_TIME:
            case self::TYPE_GENERALIZED_TIME:
                // for explicitly tagged optional stuff
                if (is_array($decoded['content'])) {
                    $decoded['content'] = $decoded['content'][0]['content'];
                }
                // for implicitly tagged optional stuff
                // in theory, doing isset($mapping['implicit']) would work but malformed certs do exist
                // in the wild that OpenSSL decodes without issue so we'll support them as well
                if (!is_object($decoded['content'])) {
                    $decoded['content'] = self::decodeTime($decoded['content'], $decoded['type']);
                }
                return $decoded['content'] ? $decoded['content']->format(self::$format) : false;
            case self::TYPE_BIT_STRING:
                if (isset($mapping['mapping'])) {
                    $offset = ord($decoded['content'][0]);
                    $size = (strlen($decoded['content']) - 1) * 8 - $offset;
                    /*
                       From X.680-0207.pdf#page=46 (21.7):
                    
                       "When a "NamedBitList" is used in defining a bitstring type ASN.1 encoding rules are free to add (or remove)
                        arbitrarily any trailing 0 bits to (or from) values that are being encoded or decoded. Application designers should
                        therefore ensure that different semantics are not associated with such values which differ only in the number of trailing
                        0 bits."
                    */
                    $bits = count($mapping['mapping']) == $size ? [] : array_fill(0, count($mapping['mapping']) - $size, false);
                    for ($i = strlen($decoded['content']) - 1; $i > 0; $i--) {
                        $current = ord($decoded['content'][$i]);
                        for ($j = $offset; $j < 8; $j++) {
                            $bits[] = (bool) ($current & 1 << $j);
                        }
                        $offset = 0;
                    }
                    $values = [];
                    $map = array_reverse($mapping['mapping']);
                    foreach ($map as $i => $value) {
                        if ($bits[$i]) {
                            $values[] = $value;
                        }
                    }
                    return $values;
                }
            case self::TYPE_OCTET_STRING:
                return $decoded['content'];
            case self::TYPE_NULL:
                return '';
            case self::TYPE_BOOLEAN:
                return $decoded['content'];
            case self::TYPE_NUMERIC_STRING:
            case self::TYPE_PRINTABLE_STRING:
            case self::TYPE_TELETEX_STRING:
            case self::TYPE_VIDEOTEX_STRING:
            case self::TYPE_IA5_STRING:
            case self::TYPE_GRAPHIC_STRING:
            case self::TYPE_VISIBLE_STRING:
            case self::TYPE_GENERAL_STRING:
            case self::TYPE_UNIVERSAL_STRING:
            case self::TYPE_UTF8_STRING:
            case self::TYPE_BMP_STRING:
                return $decoded['content'];
            case self::TYPE_INTEGER:
            case self::TYPE_ENUMERATED:
                $temp = $decoded['content'];
                if (isset($mapping['implicit'])) {
                    $temp = new BigInteger($decoded['content'], -256);
                }
                if (isset($mapping['mapping'])) {
                    $temp = (int) $temp->toString();
                    return isset($mapping['mapping'][$temp]) ? $mapping['mapping'][$temp] : false;
                }
                return $temp;
        }
    }
    /**
    * DER-decode the length
    *
    * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4.  See
    {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
    *
    * @access public
    * @param string $string
    * @return int
    */
    public static function decodeLength(&$string)
    {
        $length = ord(Strings::shift($string));
        if ($length & 0x80) {
            // definite length, long form
            $length &= 0x7f;
            $temp = Strings::shift($string, $length);
            list(, $length) = unpack('N', \Phabel\Target\Php80\Polyfill::substr(str_pad($temp, 4, chr(0), STR_PAD_LEFT), -4));
        }
        return $length;
    }
    /**
    * ASN.1 Encode
    *
    * DER-encodes an ASN.1 semantic mapping ($mapping).  Some libraries would probably call this function
    an ASN.1 compiler.
    *
    * "Special" mappings can be applied via $special.
    *
    * @param (Element | string | array) $source
    * @param array $mapping
    * @param array $special
    * @return string
    * @access public
    */
    public static function encodeDER($source, $mapping, $special = [])
    {
        self::$location = [];
        return self::encode_der($source, $mapping, null, $special);
    }
    /**
     * ASN.1 Encode (Helper function)
     *
     * @param (Element | string | array) $source
     * @param array $mapping
     * @param int $idx
     * @param array $special
     * @return string
     * @access private
     */
    private static function encode_der($source, $mapping, $idx = null, $special = [])
    {
        if ($source instanceof Element) {
            return $source->element;
        }
        // do not encode (implicitly optional) fields with value set to default
        if (isset($mapping['default']) && $source === $mapping['default']) {
            return '';
        }
        if (isset($idx)) {
            if (isset($special[$idx])) {
                $source = $special[$idx]($source);
            }
            self::$location[] = $idx;
        }
        $tag = $mapping['type'];
        switch ($tag) {
            case self::TYPE_SET:
            // Children order is not important, thus process in sequence.
            case self::TYPE_SEQUENCE:
                $tag |= 0x20;
                // set the constructed bit
                // ignore the min and max
                if (isset($mapping['min']) && isset($mapping['max'])) {
                    $value = [];
                    $child = $mapping['children'];
                    foreach ($source as $content) {
                        $temp = self::encode_der($content, $child, null, $special);
                        if ($temp === false) {
                            return false;
                        }
                        $value[] = $temp;
                    }
                    /* "The encodings of the component values of a set-of value shall appear in ascending order, the encodings being compared
                                            as octet strings with the shorter components being padded at their trailing end with 0-octets.
                                            NOTE - The padding octets are for comparison purposes only and do not appear in the encodings."
                    
                                           -- sec 11.6 of http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf  */
                    if ($mapping['type'] == self::TYPE_SET) {
                        sort($value);
                    }
                    $value = implode('', $value);
                    break;
                }
                $value = '';
                foreach ($mapping['children'] as $key => $child) {
                    if (!array_key_exists($key, $source)) {
                        if (!isset($child['optional'])) {
                            return false;
                        }
                        continue;
                    }
                    $temp = self::encode_der($source[$key], $child, $key, $special);
                    if ($temp === false) {
                        return false;
                    }
                    // An empty child encoding means it has been optimized out.
                    // Else we should have at least one tag byte.
                    if ($temp === '') {
                        continue;
                    }
                    // if isset($child['constant']) is true then isset($child['optional']) should be true as well
                    if (isset($child['constant'])) {
                        /*
                          From X.680-0207.pdf#page=58 (30.6):
                        
                          "The tagging construction specifies explicit tagging if any of the following holds:
                           ...
                           c) the "Tag Type" alternative is used and the value of "TagDefault" for the module is IMPLICIT TAGS or
                           AUTOMATIC TAGS, but the type defined by "Type" is an untagged choice type, an untagged open type, or
                           an untagged "DummyReference" (see ITU-T Rec. X.683 | ISO/IEC 8824-4, 8.3)."
                        */
                        if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
                            $subtag = chr(self::CLASS_CONTEXT_SPECIFIC << 6 | 0x20 | $child['constant']);
                            $temp = $subtag . self::encodeLength(strlen($temp)) . $temp;
                        } else {
                            $subtag = chr(self::CLASS_CONTEXT_SPECIFIC << 6 | ord($temp[0]) & 0x20 | $child['constant']);
                            $temp = $subtag . \Phabel\Target\Php80\Polyfill::substr($temp, 1);
                        }
                    }
                    $value .= $temp;
                }
                break;
            case self::TYPE_CHOICE:
                $temp = false;
                foreach ($mapping['children'] as $key => $child) {
                    if (!isset($source[$key])) {
                        continue;
                    }
                    $temp = self::encode_der($source[$key], $child, $key, $special);
                    if ($temp === false) {
                        return false;
                    }
                    // An empty child encoding means it has been optimized out.
                    // Else we should have at least one tag byte.
                    if ($temp === '') {
                        continue;
                    }
                    $tag = ord($temp[0]);
                    // if isset($child['constant']) is true then isset($child['optional']) should be true as well
                    if (isset($child['constant'])) {
                        if (isset($child['explicit']) || $child['type'] == self::TYPE_CHOICE) {
                            $subtag = chr(self::CLASS_CONTEXT_SPECIFIC << 6 | 0x20 | $child['constant']);
                            $temp = $subtag . self::encodeLength(strlen($temp)) . $temp;
                        } else {
                            $subtag = chr(self::CLASS_CONTEXT_SPECIFIC << 6 | ord($temp[0]) & 0x20 | $child['constant']);
                            $temp = $subtag . \Phabel\Target\Php80\Polyfill::substr($temp, 1);
                        }
                    }
                }
                if (isset($idx)) {
                    array_pop(self::$location);
                }
                if ($temp && isset($mapping['cast'])) {
                    $temp[0] = chr($mapping['class'] << 6 | $tag & 0x20 | $mapping['cast']);
                }
                return $temp;
            case self::TYPE_INTEGER:
            case self::TYPE_ENUMERATED:
                if (!isset($mapping['mapping'])) {
                    if (is_numeric($source)) {
                        $source = new BigInteger($source);
                    }
                    $value = $source->toBytes(true);
                } else {
                    $value = array_search($source, $mapping['mapping']);
                    if ($value === false) {
                        return false;
                    }
                    $value = new BigInteger($value);
                    $value = $value->toBytes(true);
                }
                if (!strlen($value)) {
                    $value = chr(0);
                }
                break;
            case self::TYPE_UTC_TIME:
            case self::TYPE_GENERALIZED_TIME:
                $format = $mapping['type'] == self::TYPE_UTC_TIME ? 'y' : 'Y';
                $format .= 'mdHis';
                // if $source does _not_ include timezone information within it then assume that the timezone is GMT
                $date = new DateTime($source, new DateTimeZone('GMT'));
                // if $source _does_ include timezone information within it then convert the time to GMT
                $date->setTimezone(new DateTimeZone('GMT'));
                $value = $date->format($format) . 'Z';
                break;
            case self::TYPE_BIT_STRING:
                if (isset($mapping['mapping'])) {
                    $bits = array_fill(0, count($mapping['mapping']), 0);
                    $size = 0;
                    for ($i = 0; $i < count($mapping['mapping']); $i++) {
                        if (in_array($mapping['mapping'][$i], $source)) {
                            $bits[$i] = 1;
                            $size = $i;
                        }
                    }
                    if (isset($mapping['min']) && $mapping['min'] >= 1 && $size < $mapping['min']) {
                        $size = $mapping['min'] - 1;
                    }
                    $offset = 8 - ($size + 1 & 7);
                    $offset = $offset !== 8 ? $offset : 0;
                    $value = chr($offset);
                    for ($i = $size + 1; $i < count($mapping['mapping']); $i++) {
                        unset($bits[$i]);
                    }
                    $bits = implode('', array_pad($bits, $size + $offset + 1, 0));
                    $bytes = explode(' ', rtrim(chunk_split($bits, 8, ' ')));
                    foreach ($bytes as $byte) {
                        $value .= chr(bindec($byte));
                    }
                    break;
                }
            case self::TYPE_OCTET_STRING:
                /* The initial octet shall encode, as an unsigned binary integer with bit 1 as the least significant bit,
                                   the number of unused bits in the final subsequent octet. The number shall be in the range zero to seven.
                
                                   -- http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=16 */
                $value = $source;
                break;
            case self::TYPE_OBJECT_IDENTIFIER:
                $value = self::encodeOID($source);
                break;
            case self::TYPE_ANY:
                $loc = self::$location;
                if (isset($idx)) {
                    array_pop(self::$location);
                }
                switch (true) {
                    case !isset($source):
                        return self::encode_der(null, ['type' => self::TYPE_NULL] + $mapping, null, $special);
                    case is_int($source):
                    case $source instanceof BigInteger:
                        return self::encode_der($source, ['type' => self::TYPE_INTEGER] + $mapping, null, $special);
                    case is_float($source):
                        return self::encode_der($source, ['type' => self::TYPE_REAL] + $mapping, null, $special);
                    case is_bool($source):
                        return self::encode_der($source, ['type' => self::TYPE_BOOLEAN] + $mapping, null, $special);
                    case is_array($source) && count($source) == 1:
                        $typename = implode('', array_keys($source));
                        $outtype = array_search($typename, self::ANY_MAP, true);
                        if ($outtype !== false) {
                            return self::encode_der($source[$typename], ['type' => $outtype] + $mapping, null, $special);
                        }
                }
                $filters = self::$filters;
                foreach ($loc as $part) {
                    if (!isset($filters[$part])) {
                        $filters = false;
                        break;
                    }
                    $filters = $filters[$part];
                }
                if ($filters === false) {
                    throw new \RuntimeException('No filters defined for ' . implode('/', $loc));
                }
                return self::encode_der($source, $filters + $mapping, null, $special);
            case self::TYPE_NULL:
                $value = '';
                break;
            case self::TYPE_NUMERIC_STRING:
            case self::TYPE_TELETEX_STRING:
            case self::TYPE_PRINTABLE_STRING:
            case self::TYPE_UNIVERSAL_STRING:
            case self::TYPE_UTF8_STRING:
            case self::TYPE_BMP_STRING:
            case self::TYPE_IA5_STRING:
            case self::TYPE_VISIBLE_STRING:
            case self::TYPE_VIDEOTEX_STRING:
            case self::TYPE_GRAPHIC_STRING:
            case self::TYPE_GENERAL_STRING:
                $value = $source;
                break;
            case self::TYPE_BOOLEAN:
                $value = $source ? "\xff" : "\x00";
                break;
            default:
                throw new \RuntimeException('Mapping provides no type definition for ' . implode('/', self::$location));
        }
        if (isset($idx)) {
            array_pop(self::$location);
        }
        if (isset($mapping['cast'])) {
            if (isset($mapping['explicit']) || $mapping['type'] == self::TYPE_CHOICE) {
                $value = chr($tag) . self::encodeLength(strlen($value)) . $value;
                $tag = $mapping['class'] << 6 | 0x20 | $mapping['cast'];
            } else {
                $tag = $mapping['class'] << 6 | ord($temp[0]) & 0x20 | $mapping['cast'];
            }
        }
        return chr($tag) . self::encodeLength(strlen($value)) . $value;
    }
    /**
     * BER-decode the OID
     *
     * Called by _decode_ber()
     *
     * @access public
     * @param string $content
     * @return string
     */
    public static function decodeOID($content)
    {
        static $eighty;
        if (!$eighty) {
            $eighty = new BigInteger(80);
        }
        $oid = [];
        $pos = 0;
        $len = strlen($content);
        if (ord($content[$len - 1]) & 0x80) {
            return false;
        }
        $n = new BigInteger();
        while ($pos < $len) {
            $temp = ord($content[$pos++]);
            $n = $n->bitwise_leftShift(7);
            $n = $n->bitwise_or(new BigInteger($temp & 0x7f));
            if (~$temp & 0x80) {
                $oid[] = $n;
                $n = new BigInteger();
            }
        }
        $part1 = array_shift($oid);
        $first = floor(ord($content[0]) / 40);
        /*
          "This packing of the first two object identifier components recognizes that only three values are allocated from the root
           node, and at most 39 subsequent values from nodes reached by X = 0 and X = 1."
        
          -- https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=22
        */
        if ($first <= 2) {
            // ie. 0 <= ord($content[0]) < 120 (0x78)
            array_unshift($oid, ord($content[0]) % 40);
            array_unshift($oid, $first);
        } else {
            array_unshift($oid, $part1->subtract($eighty));
            array_unshift($oid, 2);
        }
        return implode('.', $oid);
    }
    /**
     * DER-encode the OID
     *
     * Called by _encode_der()
     *
     * @access public
     * @param string $source
     * @return string
     */
    public static function encodeOID($source)
    {
        static $mask, $zero, $forty;
        if (!$mask) {
            $mask = new BigInteger(0x7f);
            $zero = new BigInteger();
            $forty = new BigInteger(40);
        }
        if (!preg_match('#(?:\\d+\\.)+#', $source)) {
            $oid = isset(self::$reverseOIDs[$source]) ? self::$reverseOIDs[$source] : false;
        } else {
            $oid = $source;
        }
        if ($oid === false) {
            throw new \RuntimeException('Invalid OID');
        }
        $parts = explode('.', $oid);
        $part1 = array_shift($parts);
        $part2 = array_shift($parts);
        $first = new BigInteger($part1);
        $first = $first->multiply($forty);
        $first = $first->add(new BigInteger($part2));
        array_unshift($parts, $first->toString());
        $value = '';
        foreach ($parts as $part) {
            if (!$part) {
                $temp = "\x00";
            } else {
                $temp = '';
                $part = new BigInteger($part);
                while (!$part->equals($zero)) {
                    $submask = $part->bitwise_and($mask);
                    $submask->setPrecision(8);
                    $temp = (chr(0x80) | $submask->toBytes()) . $temp;
                    $part = $part->bitwise_rightShift(7);
                }
                $temp[strlen($temp) - 1] = $temp[strlen($temp) - 1] & chr(0x7f);
            }
            $value .= $temp;
        }
        return $value;
    }
    /**
     * BER-decode the time
     *
     * Called by _decode_ber() and in the case of implicit tags asn1map().
     *
     * @access private
     * @param string $content
     * @param int $tag
     * @return string
     */
    private static function decodeTime($content, $tag)
    {
        /* UTCTime:
                   http://tools.ietf.org/html/rfc5280#section-4.1.2.5.1
                   http://www.obj-sys.com/asn1tutorial/node15.html
        
                   GeneralizedTime:
                   http://tools.ietf.org/html/rfc5280#section-4.1.2.5.2
                   http://www.obj-sys.com/asn1tutorial/node14.html */
        $format = 'YmdHis';
        if ($tag == self::TYPE_UTC_TIME) {
            // https://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#page=28 says "the seconds
            // element shall always be present" but none-the-less I've seen X509 certs where it isn't and if the
            // browsers parse it phpseclib ought to too
            if (preg_match('#^(\\d{10})(Z|[+-]\\d{4})$#', $content, $matches)) {
                $content = $matches[1] . '00' . $matches[2];
            }
            $prefix = \Phabel\Target\Php80\Polyfill::substr($content, 0, 2) >= 50 ? '19' : '20';
            $content = $prefix . $content;
        } elseif (strpos($content, '.') !== false) {
            $format .= '.u';
        }
        if ($content[strlen($content) - 1] == 'Z') {
            $content = \Phabel\Target\Php80\Polyfill::substr($content, 0, -1) . '+0000';
        }
        if (strpos($content, '-') !== false || strpos($content, '+') !== false) {
            $format .= 'O';
        }
        // error supression isn't necessary as of PHP 7.0:
        // http://php.net/manual/en/migration70.other-changes.php
        return @DateTime::createFromFormat($format, $content);
    }
    /**
     * Set the time format
     *
     * Sets the time / date format for asn1map().
     *
     * @access public
     * @param string $format
     */
    public static function setTimeFormat($format)
    {
        self::$format = $format;
    }
    /**
    * Load OIDs
    *
    * Load the relevant OIDs for a particular ASN.1 semantic mapping.
    Previously loaded OIDs are retained.
    *
    * @access public
    * @param array $oids
    */
    public static function loadOIDs($oids)
    {
        self::$reverseOIDs += $oids;
        self::$oids = array_flip(self::$reverseOIDs);
    }
    /**
    * Set filters
    *
    * See \phpseclib3\File\X509, etc, for an example.
    Previously loaded filters are not retained.
    *
    * @access public
    * @param array $filters
    */
    public static function setFilters($filters)
    {
        self::$filters = $filters;
    }
    /**
    * String type conversion
    *
    * This is a lazy conversion, dealing only with character size.
    No real conversion table is used.
    *
    * @param string $in
    * @param int $from
    * @param int $to
    * @return string
    * @access public
    */
    public static function convert($in, $from = self::TYPE_UTF8_STRING, $to = self::TYPE_UTF8_STRING)
    {
        // isset(self::STRING_TYPE_SIZE[$from] returns a fatal error on PHP 5.6
        if (!array_key_exists($from, self::STRING_TYPE_SIZE) || !array_key_exists($to, self::STRING_TYPE_SIZE)) {
            return false;
        }
        $insize = self::STRING_TYPE_SIZE[$from];
        $outsize = self::STRING_TYPE_SIZE[$to];
        $inlength = strlen($in);
        $out = '';
        for ($i = 0; $i < $inlength;) {
            if ($inlength - $i < $insize) {
                return false;
            }
            // Get an input character as a 32-bit value.
            $c = ord($in[$i++]);
            switch (true) {
                case $insize == 4:
                    $c = $c << 8 | ord($in[$i++]);
                    $c = $c << 8 | ord($in[$i++]);
                case $insize == 2:
                    $c = $c << 8 | ord($in[$i++]);
                case $insize == 1:
                    break;
                case ($c & 0x80) == 0x0:
                    break;
                case ($c & 0x40) == 0x0:
                    return false;
                default:
                    $bit = 6;
                    do {
                        if ($bit > 25 || $i >= $inlength || (ord($in[$i]) & 0xc0) != 0x80) {
                            return false;
                        }
                        $c = $c << 6 | ord($in[$i++]) & 0x3f;
                        $bit += 5;
                        $mask = 1 << $bit;
                    } while ($c & $bit);
                    $c &= $mask - 1;
                    break;
            }
            // Convert and append the character to output string.
            $v = '';
            switch (true) {
                case $outsize == 4:
                    $v .= chr($c & 0xff);
                    $c >>= 8;
                    $v .= chr($c & 0xff);
                    $c >>= 8;
                case $outsize == 2:
                    $v .= chr($c & 0xff);
                    $c >>= 8;
                case $outsize == 1:
                    $v .= chr($c & 0xff);
                    $c >>= 8;
                    if ($c) {
                        return false;
                    }
                    break;
                case ($c & 0x80000000) != 0:
                    return false;
                case $c >= 0x4000000:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0x4000000;
                case $c >= 0x200000:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0x200000;
                case $c >= 0x10000:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0x10000;
                case $c >= 0x800:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0x800;
                case $c >= 0x80:
                    $v .= chr(0x80 | $c & 0x3f);
                    $c = $c >> 6 | 0xc0;
                default:
                    $v .= chr($c);
                    break;
            }
            $out .= strrev($v);
        }
        return $out;
    }
    /**
     * Extract raw BER from Base64 encoding
     *
     * @access private
     * @param string $str
     * @return string
     */
    public static function extractBER($str)
    {
        /* X.509 certs are assumed to be base64 encoded but sometimes they'll have additional things in them
         * above and beyond the ceritificate.
         * ie. some may have the following preceding the -----BEGIN CERTIFICATE----- line:
         *
         * Bag Attributes
         *     localKeyID: 01 00 00 00
         * subject=/O=organization/OU=org unit/CN=common name
         * issuer=/O=organization/CN=common name
         */
        if (strlen($str) > ini_get('pcre.backtrack_limit')) {
            $temp = $str;
        } else {
            $temp = preg_replace('#.*?^-+[^-]+-+[\\r\\n ]*$#ms', '', $str, 1);
            $temp = preg_replace('#-+END.*[\\r\\n ]*.*#ms', '', $temp, 1);
        }
        // remove new lines
        $temp = str_replace(["\r", "\n", ' '], '', $temp);
        // remove the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- stuff
        $temp = preg_replace('#^-+[^-]+-+|-+[^-]+-+$#', '', $temp);
        $temp = preg_match('#^[a-zA-Z\\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false;
        return $temp != false ? $temp : $str;
    }
    /**
    * DER-encode the length
    *
    * DER supports lengths up to (2**8)**127, however, we'll only support lengths up to (2**8)**4.  See
    {@link http://itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf#p=13 X.690 paragraph 8.1.3} for more information.
    *
    * @access public
    * @param int $length
    * @return string
    */
    public static function encodeLength($length)
    {
        if ($length <= 0x7f) {
            return chr($length);
        }
        $temp = ltrim(pack('N', $length), chr(0));
        return pack('Ca*', 0x80 | strlen($temp), $temp);
    }
    /**
    * Returns the OID corresponding to a name
    *
    * What's returned in the associative array returned by loadX509() (or load*()) is either a name or an OID if
    no OID to name mapping is available. The problem with this is that what may be an unmapped OID in one version
    of phpseclib may not be unmapped in the next version, so apps that are looking at this OID may not be able
    to work from version to version.
    *
    * This method will return the OID if a name is passed to it and if no mapping is avialable it'll assume that
    what's being passed to it already is an OID and return that instead. A few examples.
    *
    * getOID('2.16.840.1.101.3.4.2.1') == '2.16.840.1.101.3.4.2.1'
    getOID('id-sha256') == '2.16.840.1.101.3.4.2.1'
    getOID('zzz') == 'zzz'
    *
    * @access public
    * @param string $name
    * @return string
    */
    public static function getOID($name)
    {
        return isset(self::$reverseOIDs[$name]) ? self::$reverseOIDs[$name] : $name;
    }
}<?php

/**
 * ASN.1 Raw Element
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2012 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1;

/**
 * ASN.1 Raw Element
 *
 * An ASN.1 ANY mapping will return an ASN1\Element object. Use of this object
 * will also bypass the normal encoding rules in ASN1::encodeDER()
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Element
{
    /**
     * Raw element value
     *
     * @var string
     * @access private
     */
    public $element;
    /**
     * Constructor
     *
     * @param string $encoded
     * @return \phpseclib3\File\ASN1\Element
     * @access public
     */
    public function __construct($encoded)
    {
        $this->element = $encoded;
    }
}<?php

/**
 * RSAPublicKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RSAPublicKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RSAPublicKey
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['modulus' => ['type' => ASN1::TYPE_INTEGER], 'publicExponent' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * DisplayText
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DisplayText
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DisplayText
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['ia5String' => ['type' => ASN1::TYPE_IA5_STRING], 'visibleString' => ['type' => ASN1::TYPE_VISIBLE_STRING], 'bmpString' => ['type' => ASN1::TYPE_BMP_STRING], 'utf8String' => ['type' => ASN1::TYPE_UTF8_STRING]]];
}<?php

/**
 * DirectoryString
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DirectoryString
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DirectoryString
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['teletexString' => ['type' => ASN1::TYPE_TELETEX_STRING], 'printableString' => ['type' => ASN1::TYPE_PRINTABLE_STRING], 'universalString' => ['type' => ASN1::TYPE_UNIVERSAL_STRING], 'utf8String' => ['type' => ASN1::TYPE_UTF8_STRING], 'bmpString' => ['type' => ASN1::TYPE_BMP_STRING]]];
}<?php

/**
 * PKCS9String 
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PKCS9String 
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PKCS9String
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['ia5String' => ['type' => ASN1::TYPE_IA5_STRING], 'directoryString' => DirectoryString::MAP]];
}<?php

/**
 * PolicyInformation
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PolicyInformation
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PolicyInformation
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['policyIdentifier' => CertPolicyId::MAP, 'policyQualifiers' => ['type' => ASN1::TYPE_SEQUENCE, 'min' => 0, 'max' => -1, 'optional' => true, 'children' => PolicyQualifierInfo::MAP]]];
}<?php

/**
 * ExtKeyUsageSyntax
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ExtKeyUsageSyntax
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ExtKeyUsageSyntax
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => KeyPurposeId::MAP];
}<?php

/**
 * BasicConstraints
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BasicConstraints
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BasicConstraints
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['cA' => ['type' => ASN1::TYPE_BOOLEAN, 'optional' => true, 'default' => false], 'pathLenConstraint' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true]]];
}<?php

/**
 * CPSuri
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CPSuri
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CPSuri
{
    const MAP = ['type' => ASN1::TYPE_IA5_STRING];
}<?php

/**
 * EncryptedPrivateKeyInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * EncryptedPrivateKeyInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EncryptedPrivateKeyInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['encryptionAlgorithm' => AlgorithmIdentifier::MAP, 'encryptedData' => EncryptedData::MAP]];
}<?php

/**
 * CRLDistributionPoints
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CRLDistributionPoints
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CRLDistributionPoints
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => DistributionPoint::MAP];
}<?php

/**
 * OtherPrimeInfos
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OtherPrimeInfos
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OtherPrimeInfos
{
    // version must be multi if otherPrimeInfos present
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => OtherPrimeInfo::MAP];
}<?php

/**
 * PBKDF2params
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PBKDF2params
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PBKDF2params
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        // technically, this is a CHOICE in RFC2898 but the other "choice" is, currently, more of a placeholder
        // in the RFC
        'salt' => ['type' => ASN1::TYPE_OCTET_STRING],
        'iterationCount' => ['type' => ASN1::TYPE_INTEGER],
        'keyLength' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true],
        'prf' => AlgorithmIdentifier::MAP + ['optional' => true],
    ]];
}<?php

/**
 * IssuerAltName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * IssuerAltName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class IssuerAltName
{
    const MAP = GeneralNames::MAP;
}<?php

/**
 * Attributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Attributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Attributes
{
    const MAP = ['type' => ASN1::TYPE_SET, 'min' => 1, 'max' => -1, 'children' => Attribute::MAP];
}<?php

/**
 * SubjectDirectoryAttributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SubjectDirectoryAttributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SubjectDirectoryAttributes
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => Attribute::MAP];
}<?php

/**
 * PublicKeyAndChallenge
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PublicKeyAndChallenge
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PublicKeyAndChallenge
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['spki' => SubjectPublicKeyInfo::MAP, 'challenge' => ['type' => ASN1::TYPE_IA5_STRING]]];
}<?php

/**
 * AccessDescription
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AccessDescription
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AccessDescription
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['accessMethod' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'accessLocation' => GeneralName::MAP]];
}<?php

/**
 * ExtensionAttribute
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ExtensionAttribute
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ExtensionAttribute
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['extension-attribute-type' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 0, 'optional' => true, 'implicit' => true], 'extension-attribute-value' => ['type' => ASN1::TYPE_ANY, 'constant' => 1, 'optional' => true, 'explicit' => true]]];
}<?php

/**
 * netscape_cert_type
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * netscape_cert_type
 *
 * mapping is from <http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html>
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class netscape_cert_type
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING, 'mapping' => ['SSLClient', 'SSLServer', 'Email', 'ObjectSigning', 'Reserved', 'SSLCA', 'EmailCA', 'ObjectSigningCA']];
}<?php

/**
 * CountryName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CountryName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CountryName
{
    const MAP = [
        'type' => ASN1::TYPE_CHOICE,
        // if class isn't present it's assumed to be \phpseclib3\File\ASN1::CLASS_UNIVERSAL or
        // (if constant is present) \phpseclib3\File\ASN1::CLASS_CONTEXT_SPECIFIC
        'class' => ASN1::CLASS_APPLICATION,
        'cast' => 1,
        'children' => ['x121-dcc-code' => ['type' => ASN1::TYPE_NUMERIC_STRING], 'iso-3166-alpha2-code' => ['type' => ASN1::TYPE_PRINTABLE_STRING]],
    ];
}<?php

/**
 * DSAPrivateKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DSAPrivateKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DSAPrivateKey
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER], 'p' => ['type' => ASN1::TYPE_INTEGER], 'q' => ['type' => ASN1::TYPE_INTEGER], 'g' => ['type' => ASN1::TYPE_INTEGER], 'y' => ['type' => ASN1::TYPE_INTEGER], 'x' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * BaseDistance
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BaseDistance
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BaseDistance
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * PrivateKeyInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PrivateKeyInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PrivateKeyInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['v1']], 'privateKeyAlgorithm' => AlgorithmIdentifier::MAP, 'privateKey' => PrivateKey::MAP, 'attributes' => ['constant' => 0, 'optional' => true, 'implicit' => true] + Attributes::MAP]];
}<?php

/**
 * Validity
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Validity
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Validity
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['notBefore' => Time::MAP, 'notAfter' => Time::MAP]];
}<?php

/**
 * BuiltInDomainDefinedAttribute
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BuiltInDomainDefinedAttribute
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BuiltInDomainDefinedAttribute
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['type' => ['type' => ASN1::TYPE_PRINTABLE_STRING], 'value' => ['type' => ASN1::TYPE_PRINTABLE_STRING]]];
}<?php

/**
 * Extension
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Extension
 *
 * A certificate using system MUST reject the certificate if it encounters
 * a critical extension it does not recognize; however, a non-critical
 * extension may be ignored if it is not recognized.
 *
 * http://tools.ietf.org/html/rfc5280#section-4.2
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Extension
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['extnId' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'critical' => ['type' => ASN1::TYPE_BOOLEAN, 'optional' => true, 'default' => false], 'extnValue' => ['type' => ASN1::TYPE_OCTET_STRING]]];
}<?php

/**
 * Curve
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Curve
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Curve
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['a' => FieldElement::MAP, 'b' => FieldElement::MAP, 'seed' => ['type' => ASN1::TYPE_BIT_STRING, 'optional' => true]]];
}<?php

/**
 * AttributeType
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AttributeType
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AttributeType
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * GeneralSubtree
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * GeneralSubtree
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class GeneralSubtree
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['base' => GeneralName::MAP, 'minimum' => ['constant' => 0, 'optional' => true, 'implicit' => true, 'default' => '0'] + BaseDistance::MAP, 'maximum' => ['constant' => 1, 'optional' => true, 'implicit' => true] + BaseDistance::MAP]];
}<?php

/**
 * RC2CBCParameter
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RC2CBCParameter
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RC2CBCParameter
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['rc2ParametersVersion' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true], 'iv' => ['type' => ASN1::TYPE_OCTET_STRING]]];
}<?php

/**
 * DSAPublicKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DSAPublicKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DSAPublicKey
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * SubjectAltName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SubjectAltName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SubjectAltName
{
    const MAP = GeneralNames::MAP;
}<?php

/**
 * NetworkAddress
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * NetworkAddress
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class NetworkAddress
{
    const MAP = ['type' => ASN1::TYPE_NUMERIC_STRING];
}<?php

/**
 * RevokedCertificate
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RevokedCertificate
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RevokedCertificate
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['userCertificate' => CertificateSerialNumber::MAP, 'revocationDate' => Time::MAP, 'crlEntryExtensions' => ['optional' => true] + Extensions::MAP]];
}<?php

/**
 * NoticeReference
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * NoticeReference
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class NoticeReference
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['organization' => DisplayText::MAP, 'noticeNumbers' => ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => 200, 'children' => ['type' => ASN1::TYPE_INTEGER]]]];
}<?php

/**
 * DistributionPointName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DistributionPointName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DistributionPointName
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['fullName' => ['constant' => 0, 'optional' => true, 'implicit' => true] + GeneralNames::MAP, 'nameRelativeToCRLIssuer' => ['constant' => 1, 'optional' => true, 'implicit' => true] + RelativeDistinguishedName::MAP]];
}<?php

/**
 * OneAsymmetricKey
 *
 * See https://tools.ietf.org/html/rfc5958
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OneAsymmetricKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OneAsymmetricKey
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['v1', 'v2']], 'privateKeyAlgorithm' => AlgorithmIdentifier::MAP, 'privateKey' => PrivateKey::MAP, 'attributes' => ['constant' => 0, 'optional' => true, 'implicit' => true] + Attributes::MAP, 'publicKey' => ['constant' => 1, 'optional' => true, 'implicit' => true] + PublicKey::MAP]];
}<?php

/**
 * OrganizationalUnitNames
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OrganizationalUnitNames
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OrganizationalUnitNames
{
    const MAP = [
        'type' => ASN1::TYPE_SEQUENCE,
        'min' => 1,
        'max' => 4,
        // ub-organizational-units
        'children' => ['type' => ASN1::TYPE_PRINTABLE_STRING],
    ];
}<?php

/**
 * DssSigValue
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DssSigValue
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DssSigValue
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['r' => ['type' => ASN1::TYPE_INTEGER], 's' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * PrivateDomainName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PrivateDomainName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PrivateDomainName
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['numeric' => ['type' => ASN1::TYPE_NUMERIC_STRING], 'printable' => ['type' => ASN1::TYPE_PRINTABLE_STRING]]];
}<?php

/**
 * Characteristic_two
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Characteristic_two
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Characteristic_two
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'm' => ['type' => ASN1::TYPE_INTEGER],
        // field size 2**m
        'basis' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER],
        'parameters' => ['type' => ASN1::TYPE_ANY, 'optional' => true],
    ]];
}<?php

/**
 * Attribute
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Attribute
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Attribute
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['type' => AttributeType::MAP, 'value' => ['type' => ASN1::TYPE_SET, 'min' => 1, 'max' => -1, 'children' => AttributeValue::MAP]]];
}<?php

/**
 * Prime_p
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Prime_p
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Prime_p
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * TBSCertList
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * TBSCertList
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class TBSCertList
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['v1', 'v2', 'v3'], 'optional' => true, 'default' => 'v2'], 'signature' => AlgorithmIdentifier::MAP, 'issuer' => Name::MAP, 'thisUpdate' => Time::MAP, 'nextUpdate' => ['optional' => true] + Time::MAP, 'revokedCertificates' => ['type' => ASN1::TYPE_SEQUENCE, 'optional' => true, 'min' => 0, 'max' => -1, 'children' => RevokedCertificate::MAP], 'crlExtensions' => ['constant' => 0, 'optional' => true, 'explicit' => true] + Extensions::MAP]];
}<?php

/**
 * PrivateKeyUsagePeriod
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PrivateKeyUsagePeriod
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PrivateKeyUsagePeriod
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['notBefore' => ['constant' => 0, 'optional' => true, 'implicit' => true, 'type' => ASN1::TYPE_GENERALIZED_TIME], 'notAfter' => ['constant' => 1, 'optional' => true, 'implicit' => true, 'type' => ASN1::TYPE_GENERALIZED_TIME]]];
}<?php

/**
 * Extensions
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Extensions
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Extensions
{
    const MAP = [
        'type' => ASN1::TYPE_SEQUENCE,
        'min' => 1,
        // technically, it's MAX, but we'll assume anything < 0 is MAX
        'max' => -1,
        // if 'children' isn't an array then 'min' and 'max' must be defined
        'children' => Extension::MAP,
    ];
}<?php

/**
 * CRLReason
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CRLReason
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CRLReason
{
    const MAP = ['type' => ASN1::TYPE_ENUMERATED, 'mapping' => [
        'unspecified',
        'keyCompromise',
        'cACompromise',
        'affiliationChanged',
        'superseded',
        'cessationOfOperation',
        'certificateHold',
        // Value 7 is not used.
        8 => 'removeFromCRL',
        'privilegeWithdrawn',
        'aACompromise',
    ]];
}<?php

/**
 * PublicKeyInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PublicKeyInfo
 *
 * this format is not formally defined anywhere but is none-the-less the form you
 * get when you do "openssl rsa -in private.pem -outform PEM -pubout"
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PublicKeyInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['publicKeyAlgorithm' => AlgorithmIdentifier::MAP, 'publicKey' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * SubjectPublicKeyInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SubjectPublicKeyInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SubjectPublicKeyInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['algorithm' => AlgorithmIdentifier::MAP, 'subjectPublicKey' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * Name
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Name
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Name
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['rdnSequence' => RDNSequence::MAP]];
}<?php

/**
 * AuthorityInfoAccessSyntax
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AuthorityInfoAccessSyntax
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AuthorityInfoAccessSyntax
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => AccessDescription::MAP];
}<?php

/**
 * KeyIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * KeyIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class KeyIdentifier
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * Trinomial
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Trinomial
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Trinomial
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * PrivateKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PrivateKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PrivateKey
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * CertificatePolicies
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificatePolicies
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificatePolicies
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => PolicyInformation::MAP];
}<?php

/**
 * KeyUsage
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * KeyUsage
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class KeyUsage
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING, 'mapping' => ['digitalSignature', 'nonRepudiation', 'keyEncipherment', 'dataEncipherment', 'keyAgreement', 'keyCertSign', 'cRLSign', 'encipherOnly', 'decipherOnly']];
}<?php

/**
 * netscape_comment
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * netscape_comment
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class netscape_comment
{
    const MAP = ['type' => ASN1::TYPE_IA5_STRING];
}<?php

/**
 * UserNotice
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * UserNotice
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class UserNotice
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['noticeRef' => ['optional' => true, 'implicit' => true] + NoticeReference::MAP, 'explicitText' => ['optional' => true, 'implicit' => true] + DisplayText::MAP]];
}<?php

/**
 * SignedPublicKeyAndChallenge
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SignedPublicKeyAndChallenge
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SignedPublicKeyAndChallenge
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['publicKeyAndChallenge' => PublicKeyAndChallenge::MAP, 'signatureAlgorithm' => AlgorithmIdentifier::MAP, 'signature' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * PersonalName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PersonalName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PersonalName
{
    const MAP = ['type' => ASN1::TYPE_SET, 'children' => ['surname' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 0, 'optional' => true, 'implicit' => true], 'given-name' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 1, 'optional' => true, 'implicit' => true], 'initials' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 2, 'optional' => true, 'implicit' => true], 'generation-qualifier' => ['type' => ASN1::TYPE_PRINTABLE_STRING, 'constant' => 3, 'optional' => true, 'implicit' => true]]];
}<?php

/**
 * ECParameters
 *
 * From: https://tools.ietf.org/html/rfc5915
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ECParameters
 *
 *  ECParameters ::= CHOICE {
 *    namedCurve         OBJECT IDENTIFIER
 *    -- implicitCurve   NULL
 *    -- specifiedCurve  SpecifiedECDomain
 *  }
 *    -- implicitCurve and specifiedCurve MUST NOT be used in PKIX.
 *    -- Details for SpecifiedECDomain can be found in [X9.62].
 *    -- Any future additions to this CHOICE should be coordinated
 *    -- with ANSI X9.
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ECParameters
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['namedCurve' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'implicitCurve' => ['type' => ASN1::TYPE_NULL], 'specifiedCurve' => SpecifiedECDomain::MAP]];
}<?php

/**
 * RSASSA_PSS_params
 *
 * As defined in https://tools.ietf.org/html/rfc4055#section-3.1
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RSASSA_PSS_params
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RSASSA_PSS_params
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['hashAlgorithm' => ['constant' => 0, 'optional' => true, 'explicit' => true] + HashAlgorithm::MAP, 'maskGenAlgorithm' => ['constant' => 1, 'optional' => true, 'explicit' => true] + MaskGenAlgorithm::MAP, 'saltLength' => ['type' => ASN1::TYPE_INTEGER, 'constant' => 2, 'optional' => true, 'explicit' => true, 'default' => 20], 'trailerField' => ['type' => ASN1::TYPE_INTEGER, 'constant' => 3, 'optional' => true, 'explicit' => true, 'default' => 1]]];
}<?php

/**
 * GeneralName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * GeneralName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class GeneralName
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['otherName' => ['constant' => 0, 'optional' => true, 'implicit' => true] + AnotherName::MAP, 'rfc822Name' => ['type' => ASN1::TYPE_IA5_STRING, 'constant' => 1, 'optional' => true, 'implicit' => true], 'dNSName' => ['type' => ASN1::TYPE_IA5_STRING, 'constant' => 2, 'optional' => true, 'implicit' => true], 'x400Address' => ['constant' => 3, 'optional' => true, 'implicit' => true] + ORAddress::MAP, 'directoryName' => ['constant' => 4, 'optional' => true, 'explicit' => true] + Name::MAP, 'ediPartyName' => ['constant' => 5, 'optional' => true, 'implicit' => true] + EDIPartyName::MAP, 'uniformResourceIdentifier' => ['type' => ASN1::TYPE_IA5_STRING, 'constant' => 6, 'optional' => true, 'implicit' => true], 'iPAddress' => ['type' => ASN1::TYPE_OCTET_STRING, 'constant' => 7, 'optional' => true, 'implicit' => true], 'registeredID' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER, 'constant' => 8, 'optional' => true, 'implicit' => true]]];
}<?php

/**
 * HoldInstructionCode
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * HoldInstructionCode
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class HoldInstructionCode
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * Pentanomial
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Pentanomial
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Pentanomial
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'k1' => ['type' => ASN1::TYPE_INTEGER],
        // k1 > 0
        'k2' => ['type' => ASN1::TYPE_INTEGER],
        // k2 > k1
        'k3' => ['type' => ASN1::TYPE_INTEGER],
    ]];
}<?php

/**
 * DistributionPoint
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DistributionPoint
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DistributionPoint
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['distributionPoint' => ['constant' => 0, 'optional' => true, 'explicit' => true] + DistributionPointName::MAP, 'reasons' => ['constant' => 1, 'optional' => true, 'implicit' => true] + ReasonFlags::MAP, 'cRLIssuer' => ['constant' => 2, 'optional' => true, 'implicit' => true] + GeneralNames::MAP]];
}<?php

/**
 * UniqueIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * UniqueIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class UniqueIdentifier
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING];
}<?php

/**
 * TerminalIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * TerminalIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class TerminalIdentifier
{
    const MAP = ['type' => ASN1::TYPE_PRINTABLE_STRING];
}<?php

/**
 * AnotherName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AnotherName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AnotherName
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['type-id' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'value' => ['type' => ASN1::TYPE_ANY, 'constant' => 0, 'optional' => true, 'explicit' => true]]];
}<?php

/**
 * CertificateSerialNumber
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificateSerialNumber
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificateSerialNumber
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * RelativeDistinguishedName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RelativeDistinguishedName
 *
 * In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare,
 * but they can be useful at times when either there is no unique attribute in the entry or you
 * want to ensure that the entry's DN contains some useful identifying information.
 *
 * - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RelativeDistinguishedName
{
    const MAP = ['type' => ASN1::TYPE_SET, 'min' => 1, 'max' => -1, 'children' => AttributeTypeAndValue::MAP];
}<?php

/**
 * OrganizationName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OrganizationName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OrganizationName
{
    const MAP = ['type' => ASN1::TYPE_PRINTABLE_STRING];
}<?php

/**
 * RSAPrivateKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RSAPrivateKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RSAPrivateKey
{
    // version must be multi if otherPrimeInfos present
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['two-prime', 'multi']],
        'modulus' => ['type' => ASN1::TYPE_INTEGER],
        // n
        'publicExponent' => ['type' => ASN1::TYPE_INTEGER],
        // e
        'privateExponent' => ['type' => ASN1::TYPE_INTEGER],
        // d
        'prime1' => ['type' => ASN1::TYPE_INTEGER],
        // p
        'prime2' => ['type' => ASN1::TYPE_INTEGER],
        // q
        'exponent1' => ['type' => ASN1::TYPE_INTEGER],
        // d mod (p-1)
        'exponent2' => ['type' => ASN1::TYPE_INTEGER],
        // d mod (q-1)
        'coefficient' => ['type' => ASN1::TYPE_INTEGER],
        // (inverse of q) mod p
        'otherPrimeInfos' => OtherPrimeInfos::MAP + ['optional' => true],
    ]];
}<?php

/**
 * AlgorithmIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AlgorithmIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AlgorithmIdentifier
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['algorithm' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'parameters' => ['type' => ASN1::TYPE_ANY, 'optional' => true]]];
}<?php

/**
 * BuiltInStandardAttributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BuiltInStandardAttributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BuiltInStandardAttributes
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['country-name' => ['optional' => true] + CountryName::MAP, 'administration-domain-name' => ['optional' => true] + AdministrationDomainName::MAP, 'network-address' => ['constant' => 0, 'optional' => true, 'implicit' => true] + NetworkAddress::MAP, 'terminal-identifier' => ['constant' => 1, 'optional' => true, 'implicit' => true] + TerminalIdentifier::MAP, 'private-domain-name' => ['constant' => 2, 'optional' => true, 'explicit' => true] + PrivateDomainName::MAP, 'organization-name' => ['constant' => 3, 'optional' => true, 'implicit' => true] + OrganizationName::MAP, 'numeric-user-identifier' => ['constant' => 4, 'optional' => true, 'implicit' => true] + NumericUserIdentifier::MAP, 'personal-name' => ['constant' => 5, 'optional' => true, 'implicit' => true] + PersonalName::MAP, 'organizational-unit-names' => ['constant' => 6, 'optional' => true, 'implicit' => true] + OrganizationalUnitNames::MAP]];
}<?php

/**
 * PublicKey
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PublicKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PublicKey
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING];
}<?php

/**
 * DSAParams
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DSAParams
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DSAParams
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['p' => ['type' => ASN1::TYPE_INTEGER], 'q' => ['type' => ASN1::TYPE_INTEGER], 'g' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * CRLNumber
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CRLNumber
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CRLNumber
{
    const MAP = ['type' => ASN1::TYPE_INTEGER];
}<?php

/**
 * ORAddress
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ORAddress
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ORAddress
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['built-in-standard-attributes' => BuiltInStandardAttributes::MAP, 'built-in-domain-defined-attributes' => ['optional' => true] + BuiltInDomainDefinedAttributes::MAP, 'extension-attributes' => ['optional' => true] + ExtensionAttributes::MAP]];
}<?php

/**
 * AdministrationDomainName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AdministrationDomainName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AdministrationDomainName
{
    const MAP = [
        'type' => ASN1::TYPE_CHOICE,
        // if class isn't present it's assumed to be \phpseclib3\File\ASN1::CLASS_UNIVERSAL or
        // (if constant is present) \phpseclib3\File\ASN1::CLASS_CONTEXT_SPECIFIC
        'class' => ASN1::CLASS_APPLICATION,
        'cast' => 2,
        'children' => ['numeric' => ['type' => ASN1::TYPE_NUMERIC_STRING], 'printable' => ['type' => ASN1::TYPE_PRINTABLE_STRING]],
    ];
}<?php

/**
 * ECPoint
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ECPoint
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ECPoint
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * ExtensionAttributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ExtensionAttributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ExtensionAttributes
{
    const MAP = [
        'type' => ASN1::TYPE_SET,
        'min' => 1,
        'max' => 256,
        // ub-extension-attributes
        'children' => ExtensionAttribute::MAP,
    ];
}<?php

/**
 * CertPolicyId
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertPolicyId
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertPolicyId
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * AuthorityKeyIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AuthorityKeyIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AuthorityKeyIdentifier
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['keyIdentifier' => ['constant' => 0, 'optional' => true, 'implicit' => true] + KeyIdentifier::MAP, 'authorityCertIssuer' => ['constant' => 1, 'optional' => true, 'implicit' => true] + GeneralNames::MAP, 'authorityCertSerialNumber' => ['constant' => 2, 'optional' => true, 'implicit' => true] + CertificateSerialNumber::MAP]];
}<?php

/**
 * SubjectInfoAccessSyntax
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SubjectInfoAccessSyntax
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SubjectInfoAccessSyntax
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => AccessDescription::MAP];
}<?php

/**
 * GeneralSubtrees
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * GeneralSubtrees
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class GeneralSubtrees
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => GeneralSubtree::MAP];
}<?php

/**
 * netscape_ca_policy_url
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * netscape_ca_policy_url
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class netscape_ca_policy_url
{
    const MAP = ['type' => ASN1::TYPE_IA5_STRING];
}<?php

/**
 * NumericUserIdentifier
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * NumericUserIdentifier
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class NumericUserIdentifier
{
    const MAP = ['type' => ASN1::TYPE_NUMERIC_STRING];
}<?php

/**
 * CertificationRequest
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificationRequest
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificationRequest
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['certificationRequestInfo' => CertificationRequestInfo::MAP, 'signatureAlgorithm' => AlgorithmIdentifier::MAP, 'signature' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * PolicyQualifierInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PolicyQualifierInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PolicyQualifierInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['policyQualifierId' => PolicyQualifierId::MAP, 'qualifier' => ['type' => ASN1::TYPE_ANY]]];
}<?php

/**
 * IssuingDistributionPoint
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * IssuingDistributionPoint
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class IssuingDistributionPoint
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['distributionPoint' => ['constant' => 0, 'optional' => true, 'explicit' => true] + DistributionPointName::MAP, 'onlyContainsUserCerts' => ['type' => ASN1::TYPE_BOOLEAN, 'constant' => 1, 'optional' => true, 'default' => false, 'implicit' => true], 'onlyContainsCACerts' => ['type' => ASN1::TYPE_BOOLEAN, 'constant' => 2, 'optional' => true, 'default' => false, 'implicit' => true], 'onlySomeReasons' => ['constant' => 3, 'optional' => true, 'implicit' => true] + ReasonFlags::MAP, 'indirectCRL' => ['type' => ASN1::TYPE_BOOLEAN, 'constant' => 4, 'optional' => true, 'default' => false, 'implicit' => true], 'onlyContainsAttributeCerts' => ['type' => ASN1::TYPE_BOOLEAN, 'constant' => 5, 'optional' => true, 'default' => false, 'implicit' => true]]];
}<?php

/**
 * CertificateIssuer
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificateIssuer
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificateIssuer
{
    const MAP = GeneralNames::MAP;
}<?php

/**
 * EncryptedData
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * EncryptedData
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EncryptedData
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * PBMAC1params
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PBMAC1params
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PBMAC1params
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['keyDerivationFunc' => AlgorithmIdentifier::MAP, 'messageAuthScheme' => AlgorithmIdentifier::MAP]];
}<?php

/**
 * DigestInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DigestInfo
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DigestInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['digestAlgorithm' => AlgorithmIdentifier::MAP, 'digest' => ['type' => ASN1::TYPE_OCTET_STRING]]];
}<?php

/**
 * KeyPurposeId
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * KeyPurposeId
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class KeyPurposeId
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * HashAglorithm
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * HashAglorithm
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class HashAlgorithm
{
    const MAP = AlgorithmIdentifier::MAP;
}<?php

/**
 * FieldID
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * FieldID
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class FieldID
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['fieldType' => ['type' => ASN1::TYPE_OBJECT_IDENTIFIER], 'parameters' => ['type' => ASN1::TYPE_ANY, 'optional' => true]]];
}<?php

/**
 * PolicyMappings
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PolicyMappings
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PolicyMappings
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['issuerDomainPolicy' => CertPolicyId::MAP, 'subjectDomainPolicy' => CertPolicyId::MAP]]];
}<?php

/**
 * RDNSequence
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * RDNSequence
 *
 * In practice, RDNs containing multiple name-value pairs (called "multivalued RDNs") are rare,
 * but they can be useful at times when either there is no unique attribute in the entry or you
 * want to ensure that the entry's DN contains some useful identifying information.
 *
 * - https://www.opends.org/wiki/page/DefinitionRelativeDistinguishedName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class RDNSequence
{
    const MAP = [
        'type' => ASN1::TYPE_SEQUENCE,
        // RDNSequence does not define a min or a max, which means it doesn't have one
        'min' => 0,
        'max' => -1,
        'children' => RelativeDistinguishedName::MAP,
    ];
}<?php

/**
 * TBSCertificate
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * TBSCertificate
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class TBSCertificate
{
    // assert($TBSCertificate['children']['signature'] == $Certificate['children']['signatureAlgorithm'])
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        // technically, default implies optional, but we'll define it as being optional, none-the-less, just to
        // reenforce that fact
        'version' => ['type' => ASN1::TYPE_INTEGER, 'constant' => 0, 'optional' => true, 'explicit' => true, 'mapping' => ['v1', 'v2', 'v3'], 'default' => 'v1'],
        'serialNumber' => CertificateSerialNumber::MAP,
        'signature' => AlgorithmIdentifier::MAP,
        'issuer' => Name::MAP,
        'validity' => Validity::MAP,
        'subject' => Name::MAP,
        'subjectPublicKeyInfo' => SubjectPublicKeyInfo::MAP,
        // implicit means that the T in the TLV structure is to be rewritten, regardless of the type
        'issuerUniqueID' => ['constant' => 1, 'optional' => true, 'implicit' => true] + UniqueIdentifier::MAP,
        'subjectUniqueID' => ['constant' => 2, 'optional' => true, 'implicit' => true] + UniqueIdentifier::MAP,
        // <http://tools.ietf.org/html/rfc2459#page-74> doesn't use the EXPLICIT keyword but if
        // it's not IMPLICIT, it's EXPLICIT
        'extensions' => ['constant' => 3, 'optional' => true, 'explicit' => true] + Extensions::MAP,
    ]];
}<?php

/**
 * CertificateList
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificateList
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificateList
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['tbsCertList' => TBSCertList::MAP, 'signatureAlgorithm' => AlgorithmIdentifier::MAP, 'signature' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * BuiltInDomainDefinedAttributes
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * BuiltInDomainDefinedAttributes
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BuiltInDomainDefinedAttributes
{
    const MAP = [
        'type' => ASN1::TYPE_SEQUENCE,
        'min' => 1,
        'max' => 4,
        // ub-domain-defined-attributes
        'children' => BuiltInDomainDefinedAttribute::MAP,
    ];
}<?php

/**
 * PolicyQualifierId
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PolicyQualifierId
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PolicyQualifierId
{
    const MAP = ['type' => ASN1::TYPE_OBJECT_IDENTIFIER];
}<?php

/**
 * FieldElement
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * FieldElement
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class FieldElement
{
    const MAP = ['type' => ASN1::TYPE_OCTET_STRING];
}<?php

/**
 * MaskGenAglorithm
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * MaskGenAglorithm
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MaskGenAlgorithm
{
    const MAP = AlgorithmIdentifier::MAP;
}<?php

/**
 * SpecifiedECDomain
 *
 * From: http://www.secg.org/sec1-v2.pdf#page=109
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * SpecifiedECDomain
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class SpecifiedECDomain
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => [1 => 'ecdpVer1', 'ecdpVer2', 'ecdpVer3']], 'fieldID' => FieldID::MAP, 'curve' => Curve::MAP, 'base' => ECPoint::MAP, 'order' => ['type' => ASN1::TYPE_INTEGER], 'cofactor' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true], 'hash' => ['optional' => true] + HashAlgorithm::MAP]];
}<?php

/**
 * GeneralNames
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * GeneralNames
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class GeneralNames
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'min' => 1, 'max' => -1, 'children' => GeneralName::MAP];
}<?php

/**
 * EDIPartyName
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * EDIPartyName
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EDIPartyName
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'nameAssigner' => ['constant' => 0, 'optional' => true, 'implicit' => true] + DirectoryString::MAP,
        // partyName is technically required but \phpseclib3\File\ASN1 doesn't currently support non-optional constants and
        // setting it to optional gets the job done in any event.
        'partyName' => ['constant' => 1, 'optional' => true, 'implicit' => true] + DirectoryString::MAP,
    ]];
}<?php

/**
 * AttributeValue
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AttributeValue
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AttributeValue
{
    const MAP = ['type' => ASN1::TYPE_ANY];
}<?php

/**
 * DHParameter
 *
 * From: https://www.teletrust.de/fileadmin/files/oid/oid_pkcs-3v1-4.pdf#page=6
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * DHParameter
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DHParameter
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['prime' => ['type' => ASN1::TYPE_INTEGER], 'base' => ['type' => ASN1::TYPE_INTEGER], 'privateValueLength' => ['type' => ASN1::TYPE_INTEGER, 'optional' => true]]];
}<?php

/**
 * NameConstraints
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * NameConstraints
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class NameConstraints
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['permittedSubtrees' => ['constant' => 0, 'optional' => true, 'implicit' => true] + GeneralSubtrees::MAP, 'excludedSubtrees' => ['constant' => 1, 'optional' => true, 'implicit' => true] + GeneralSubtrees::MAP]];
}<?php

/**
 * OtherPrimeInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * OtherPrimeInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OtherPrimeInfo
{
    // version must be multi if otherPrimeInfos present
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => [
        'prime' => ['type' => ASN1::TYPE_INTEGER],
        // ri
        'exponent' => ['type' => ASN1::TYPE_INTEGER],
        // di
        'coefficient' => ['type' => ASN1::TYPE_INTEGER],
    ]];
}<?php

/**
 * AttributeTypeAndValue
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * AttributeTypeAndValue
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class AttributeTypeAndValue
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['type' => AttributeType::MAP, 'value' => AttributeValue::MAP]];
}<?php

/**
 * ReasonFlags
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ReasonFlags
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ReasonFlags
{
    const MAP = ['type' => ASN1::TYPE_BIT_STRING, 'mapping' => ['unused', 'keyCompromise', 'cACompromise', 'affiliationChanged', 'superseded', 'cessationOfOperation', 'certificateHold', 'privilegeWithdrawn', 'aACompromise']];
}<?php

/**
 * Certificate
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Certificate
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Certificate
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['tbsCertificate' => TBSCertificate::MAP, 'signatureAlgorithm' => AlgorithmIdentifier::MAP, 'signature' => ['type' => ASN1::TYPE_BIT_STRING]]];
}<?php

/**
 * PostalAddress
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PostalAddress
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PostalAddress
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'optional' => true, 'min' => 1, 'max' => -1, 'children' => DirectoryString::MAP];
}<?php

/**
 * ECPrivateKey
 *
 * From: https://tools.ietf.org/html/rfc5915
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * ECPrivateKey
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class ECPrivateKey
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => [1 => 'ecPrivkeyVer1']], 'privateKey' => ['type' => ASN1::TYPE_OCTET_STRING], 'parameters' => ['constant' => 0, 'optional' => true, 'explicit' => true] + ECParameters::MAP, 'publicKey' => ['type' => ASN1::TYPE_BIT_STRING, 'constant' => 1, 'optional' => true, 'explicit' => true]]];
}<?php

/**
 * EcdsaSigValue
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * EcdsaSigValue
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EcdsaSigValue
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['r' => ['type' => ASN1::TYPE_INTEGER], 's' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * InvalidityDate
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * InvalidityDate
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class InvalidityDate
{
    const MAP = ['type' => ASN1::TYPE_GENERALIZED_TIME];
}<?php

/**
 * PBES2params
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PBES2params
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PBES2params
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['keyDerivationFunc' => AlgorithmIdentifier::MAP, 'encryptionScheme' => AlgorithmIdentifier::MAP]];
}<?php

/**
 * CertificationRequestInfo
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * CertificationRequestInfo
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class CertificationRequestInfo
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['version' => ['type' => ASN1::TYPE_INTEGER, 'mapping' => ['v1']], 'subject' => Name::MAP, 'subjectPKInfo' => SubjectPublicKeyInfo::MAP, 'attributes' => ['constant' => 0, 'optional' => true, 'implicit' => true] + Attributes::MAP]];
}<?php

/**
 * PBEParameter
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * PBEParameter
 *
 * from https://tools.ietf.org/html/rfc2898#appendix-A.3
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PBEParameter
{
    const MAP = ['type' => ASN1::TYPE_SEQUENCE, 'children' => ['salt' => ['type' => ASN1::TYPE_OCTET_STRING], 'iterationCount' => ['type' => ASN1::TYPE_INTEGER]]];
}<?php

/**
 * Time
 *
 * PHP version 5
 *
 * @category  File
 * @package   ASN1
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File\ASN1\Maps;

use phpseclib3\File\ASN1;
/**
 * Time
 *
 * @package ASN1
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Time
{
    const MAP = ['type' => ASN1::TYPE_CHOICE, 'children' => ['utcTime' => ['type' => ASN1::TYPE_UTC_TIME], 'generalTime' => ['type' => ASN1::TYPE_GENERALIZED_TIME]]];
}<?php

/**
 * Pure-PHP X.509 Parser
 *
 * PHP version 5
 *
 * Encode and decode X.509 certificates.
 *
 * The extensions are from {@link http://tools.ietf.org/html/rfc5280 RFC5280} and
 * {@link http://web.archive.org/web/19961027104704/http://www3.netscape.com/eng/security/cert-exts.html Netscape Certificate Extensions}.
 *
 * Note that loading an X.509 certificate and resaving it may invalidate the signature.  The reason being that the signature is based on a
 * portion of the certificate that contains optional parameters with default values.  ie. if the parameter isn't there the default value is
 * used.  Problem is, if the parameter is there and it just so happens to have the default value there are two ways that that parameter can
 * be encoded.  It can be encoded explicitly or left out all together.  This would effect the signature value and thus may invalidate the
 * the certificate all together unless the certificate is re-signed.
 *
 * @category  File
 * @package   X509
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2012 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File;

use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use ParagonIE\ConstantTime\Base64;
use ParagonIE\ConstantTime\Hex;
use phpseclib3\Crypt\Common\PrivateKey;
use phpseclib3\Crypt\Common\PublicKey;
use phpseclib3\Crypt\DSA;
use phpseclib3\Crypt\EC;
use phpseclib3\Crypt\Hash;
use phpseclib3\Crypt\Random;
use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\RSA\Formats\Keys\PSS;
use phpseclib3\Exception\UnsupportedAlgorithmException;
use phpseclib3\File\ASN1\Element;
use phpseclib3\File\ASN1\Maps;
use phpseclib3\Math\BigInteger;
use phpseclib3\Crypt\PublicKeyLoader;
/**
 * Pure-PHP X.509 Parser
 *
 * @package X509
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class X509
{
    /**
     * Flag to only accept signatures signed by certificate authorities
     *
     * Not really used anymore but retained all the same to suppress E_NOTICEs from old installs
     *
     * @access public
     */
    const VALIDATE_SIGNATURE_BY_CA = 1;
    /**
     * Return internal array representation
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_ARRAY = 0;
    /**
     * Return string
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_STRING = 1;
    /**
     * Return ASN.1 name string
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_ASN1 = 2;
    /**
     * Return OpenSSL compatible array
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_OPENSSL = 3;
    /**
     * Return canonical ASN.1 RDNs string
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_CANON = 4;
    /**
     * Return name hash for file indexing
     *
     * @access public
     * @see \phpseclib3\File\X509::getDN()
     */
    const DN_HASH = 5;
    /**
     * Save as PEM
     *
     * ie. a base64-encoded PEM with a header and a footer
     *
     * @access public
     * @see \phpseclib3\File\X509::saveX509()
     * @see \phpseclib3\File\X509::saveCSR()
     * @see \phpseclib3\File\X509::saveCRL()
     */
    const FORMAT_PEM = 0;
    /**
     * Save as DER
     *
     * @access public
     * @see \phpseclib3\File\X509::saveX509()
     * @see \phpseclib3\File\X509::saveCSR()
     * @see \phpseclib3\File\X509::saveCRL()
     */
    const FORMAT_DER = 1;
    /**
     * Save as a SPKAC
     *
     * @access public
     * @see \phpseclib3\File\X509::saveX509()
     * @see \phpseclib3\File\X509::saveCSR()
     * @see \phpseclib3\File\X509::saveCRL()
     *
     * Only works on CSRs. Not currently supported.
     */
    const FORMAT_SPKAC = 2;
    /**
     * Auto-detect the format
     *
     * Used only by the load*() functions
     *
     * @access public
     * @see \phpseclib3\File\X509::saveX509()
     * @see \phpseclib3\File\X509::saveCSR()
     * @see \phpseclib3\File\X509::saveCRL()
     */
    const FORMAT_AUTO_DETECT = 3;
    /**
     * Attribute value disposition.
     * If disposition is >= 0, this is the index of the target value.
     */
    const ATTR_ALL = -1;
    // All attribute values (array).
    const ATTR_APPEND = -2;
    // Add a value.
    const ATTR_REPLACE = -3;
    // Clear first, then add a value.
    /**
     * Distinguished Name
     *
     * @var array
     * @access private
     */
    private $dn;
    /**
     * Public key
     *
     * @var string
     * @access private
     */
    private $publicKey;
    /**
     * Private key
     *
     * @var string
     * @access private
     */
    private $privateKey;
    /**
     * Object identifiers for X.509 certificates
     *
     * @var array
     * @access private
     * @link http://en.wikipedia.org/wiki/Object_identifier
     */
    private $oids;
    /**
     * The certificate authorities
     *
     * @var array
     * @access private
     */
    private $CAs;
    /**
     * The currently loaded certificate
     *
     * @var array
     * @access private
     */
    private $currentCert;
    /**
     * The signature subject
     *
     * There's no guarantee \phpseclib3\File\X509 is going to re-encode an X.509 cert in the same way it was originally
     * encoded so we take save the portion of the original cert that the signature would have made for.
     *
     * @var string
     * @access private
     */
    private $signatureSubject;
    /**
     * Certificate Start Date
     *
     * @var string
     * @access private
     */
    private $startDate;
    /**
     * Certificate End Date
     *
     * @var string
     * @access private
     */
    private $endDate;
    /**
     * Serial Number
     *
     * @var string
     * @access private
     */
    private $serialNumber;
    /**
     * Key Identifier
     *
     * See {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.1 RFC5280#section-4.2.1.1} and
     * {@link http://tools.ietf.org/html/rfc5280#section-4.2.1.2 RFC5280#section-4.2.1.2}.
     *
     * @var string
     * @access private
     */
    private $currentKeyIdentifier;
    /**
     * CA Flag
     *
     * @var bool
     * @access private
     */
    private $caFlag = false;
    /**
     * SPKAC Challenge
     *
     * @var string
     * @access private
     */
    private $challenge;
    /**
     * @var array
     * @access private
     */
    private $extensionValues = [];
    /**
     * OIDs loaded
     *
     * @var bool
     * @access private
     */
    private static $oidsLoaded = false;
    /**
     * Recursion Limit
     *
     * @var int
     * @access private
     */
    private static $recur_limit = 5;
    /**
     * URL fetch flag
     *
     * @var bool
     * @access private
     */
    private static $disable_url_fetch = false;
    /**
     * @var array
     * @access private
     */
    private static $extensions = [];
    /**
     * @var ?array
     * @access private
     */
    private $ipAddresses = null;
    /**
     * @var ?array
     * @access private
     */
    private $domains = null;
    /**
     * Default Constructor.
     *
     * @return \phpseclib3\File\X509
     * @access public
     */
    public function __construct()
    {
        // Explicitly Tagged Module, 1988 Syntax
        // http://tools.ietf.org/html/rfc5280#appendix-A.1
        if (!self::$oidsLoaded) {
            // OIDs from RFC5280 and those RFCs mentioned in RFC5280#section-4.1.1.2
            ASN1::loadOIDs([
                //'id-pkix' => '1.3.6.1.5.5.7',
                //'id-pe' => '1.3.6.1.5.5.7.1',
                //'id-qt' => '1.3.6.1.5.5.7.2',
                //'id-kp' => '1.3.6.1.5.5.7.3',
                //'id-ad' => '1.3.6.1.5.5.7.48',
                'id-qt-cps' => '1.3.6.1.5.5.7.2.1',
                'id-qt-unotice' => '1.3.6.1.5.5.7.2.2',
                'id-ad-ocsp' => '1.3.6.1.5.5.7.48.1',
                'id-ad-caIssuers' => '1.3.6.1.5.5.7.48.2',
                'id-ad-timeStamping' => '1.3.6.1.5.5.7.48.3',
                'id-ad-caRepository' => '1.3.6.1.5.5.7.48.5',
                //'id-at' => '2.5.4',
                'id-at-name' => '2.5.4.41',
                'id-at-surname' => '2.5.4.4',
                'id-at-givenName' => '2.5.4.42',
                'id-at-initials' => '2.5.4.43',
                'id-at-generationQualifier' => '2.5.4.44',
                'id-at-commonName' => '2.5.4.3',
                'id-at-localityName' => '2.5.4.7',
                'id-at-stateOrProvinceName' => '2.5.4.8',
                'id-at-organizationName' => '2.5.4.10',
                'id-at-organizationalUnitName' => '2.5.4.11',
                'id-at-title' => '2.5.4.12',
                'id-at-description' => '2.5.4.13',
                'id-at-dnQualifier' => '2.5.4.46',
                'id-at-countryName' => '2.5.4.6',
                'id-at-serialNumber' => '2.5.4.5',
                'id-at-pseudonym' => '2.5.4.65',
                'id-at-postalCode' => '2.5.4.17',
                'id-at-streetAddress' => '2.5.4.9',
                'id-at-uniqueIdentifier' => '2.5.4.45',
                'id-at-role' => '2.5.4.72',
                'id-at-postalAddress' => '2.5.4.16',
                //'id-domainComponent' => '0.9.2342.19200300.100.1.25',
                //'pkcs-9' => '1.2.840.113549.1.9',
                'pkcs-9-at-emailAddress' => '1.2.840.113549.1.9.1',
                //'id-ce' => '2.5.29',
                'id-ce-authorityKeyIdentifier' => '2.5.29.35',
                'id-ce-subjectKeyIdentifier' => '2.5.29.14',
                'id-ce-keyUsage' => '2.5.29.15',
                'id-ce-privateKeyUsagePeriod' => '2.5.29.16',
                'id-ce-certificatePolicies' => '2.5.29.32',
                //'anyPolicy' => '2.5.29.32.0',
                'id-ce-policyMappings' => '2.5.29.33',
                'id-ce-subjectAltName' => '2.5.29.17',
                'id-ce-issuerAltName' => '2.5.29.18',
                'id-ce-subjectDirectoryAttributes' => '2.5.29.9',
                'id-ce-basicConstraints' => '2.5.29.19',
                'id-ce-nameConstraints' => '2.5.29.30',
                'id-ce-policyConstraints' => '2.5.29.36',
                'id-ce-cRLDistributionPoints' => '2.5.29.31',
                'id-ce-extKeyUsage' => '2.5.29.37',
                //'anyExtendedKeyUsage' => '2.5.29.37.0',
                'id-kp-serverAuth' => '1.3.6.1.5.5.7.3.1',
                'id-kp-clientAuth' => '1.3.6.1.5.5.7.3.2',
                'id-kp-codeSigning' => '1.3.6.1.5.5.7.3.3',
                'id-kp-emailProtection' => '1.3.6.1.5.5.7.3.4',
                'id-kp-timeStamping' => '1.3.6.1.5.5.7.3.8',
                'id-kp-OCSPSigning' => '1.3.6.1.5.5.7.3.9',
                'id-ce-inhibitAnyPolicy' => '2.5.29.54',
                'id-ce-freshestCRL' => '2.5.29.46',
                'id-pe-authorityInfoAccess' => '1.3.6.1.5.5.7.1.1',
                'id-pe-subjectInfoAccess' => '1.3.6.1.5.5.7.1.11',
                'id-ce-cRLNumber' => '2.5.29.20',
                'id-ce-issuingDistributionPoint' => '2.5.29.28',
                'id-ce-deltaCRLIndicator' => '2.5.29.27',
                'id-ce-cRLReasons' => '2.5.29.21',
                'id-ce-certificateIssuer' => '2.5.29.29',
                'id-ce-holdInstructionCode' => '2.5.29.23',
                //'holdInstruction' => '1.2.840.10040.2',
                'id-holdinstruction-none' => '1.2.840.10040.2.1',
                'id-holdinstruction-callissuer' => '1.2.840.10040.2.2',
                'id-holdinstruction-reject' => '1.2.840.10040.2.3',
                'id-ce-invalidityDate' => '2.5.29.24',
                'rsaEncryption' => '1.2.840.113549.1.1.1',
                'md2WithRSAEncryption' => '1.2.840.113549.1.1.2',
                'md5WithRSAEncryption' => '1.2.840.113549.1.1.4',
                'sha1WithRSAEncryption' => '1.2.840.113549.1.1.5',
                'sha224WithRSAEncryption' => '1.2.840.113549.1.1.14',
                'sha256WithRSAEncryption' => '1.2.840.113549.1.1.11',
                'sha384WithRSAEncryption' => '1.2.840.113549.1.1.12',
                'sha512WithRSAEncryption' => '1.2.840.113549.1.1.13',
                'id-ecPublicKey' => '1.2.840.10045.2.1',
                'ecdsa-with-SHA1' => '1.2.840.10045.4.1',
                // from https://tools.ietf.org/html/rfc5758#section-3.2
                'ecdsa-with-SHA224' => '1.2.840.10045.4.3.1',
                'ecdsa-with-SHA256' => '1.2.840.10045.4.3.2',
                'ecdsa-with-SHA384' => '1.2.840.10045.4.3.3',
                'ecdsa-with-SHA512' => '1.2.840.10045.4.3.4',
                'id-dsa' => '1.2.840.10040.4.1',
                'id-dsa-with-sha1' => '1.2.840.10040.4.3',
                // from https://tools.ietf.org/html/rfc5758#section-3.1
                'id-dsa-with-sha224' => '2.16.840.1.101.3.4.3.1',
                'id-dsa-with-sha256' => '2.16.840.1.101.3.4.3.2',
                // from https://tools.ietf.org/html/rfc8410:
                'id-Ed25519' => '1.3.101.112',
                'id-Ed448' => '1.3.101.113',
                'id-RSASSA-PSS' => '1.2.840.113549.1.1.10',
                //'id-sha224' => '2.16.840.1.101.3.4.2.4',
                //'id-sha256' => '2.16.840.1.101.3.4.2.1',
                //'id-sha384' => '2.16.840.1.101.3.4.2.2',
                //'id-sha512' => '2.16.840.1.101.3.4.2.3',
                //'id-GostR3411-94-with-GostR3410-94' => '1.2.643.2.2.4',
                //'id-GostR3411-94-with-GostR3410-2001' => '1.2.643.2.2.3',
                //'id-GostR3410-2001' => '1.2.643.2.2.20',
                //'id-GostR3410-94' => '1.2.643.2.2.19',
                // Netscape Object Identifiers from "Netscape Certificate Extensions"
                'netscape' => '2.16.840.1.113730',
                'netscape-cert-extension' => '2.16.840.1.113730.1',
                'netscape-cert-type' => '2.16.840.1.113730.1.1',
                'netscape-comment' => '2.16.840.1.113730.1.13',
                'netscape-ca-policy-url' => '2.16.840.1.113730.1.8',
                // the following are X.509 extensions not supported by phpseclib
                'id-pe-logotype' => '1.3.6.1.5.5.7.1.12',
                'entrustVersInfo' => '1.2.840.113533.7.65.0',
                'verisignPrivate' => '2.16.840.1.113733.1.6.9',
                // for Certificate Signing Requests
                // see http://tools.ietf.org/html/rfc2985
                'pkcs-9-at-unstructuredName' => '1.2.840.113549.1.9.2',
                // PKCS #9 unstructured name
                'pkcs-9-at-challengePassword' => '1.2.840.113549.1.9.7',
                // Challenge password for certificate revocations
                'pkcs-9-at-extensionRequest' => '1.2.840.113549.1.9.14',
            ]);
        }
    }
    /**
     * Load X.509 certificate
     *
     * Returns an associative array describing the X.509 cert or a false if the cert failed to load
     *
     * @param string $cert
     * @param int $mode
     * @access public
     * @return mixed
     */
    public function loadX509($cert, $mode = self::FORMAT_AUTO_DETECT)
    {
        if (is_array($cert) && isset($cert['tbsCertificate'])) {
            unset($this->currentCert);
            unset($this->currentKeyIdentifier);
            $this->dn = $cert['tbsCertificate']['subject'];
            if (!isset($this->dn)) {
                return false;
            }
            $this->currentCert = $cert;
            $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
            $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
            unset($this->signatureSubject);
            return $cert;
        }
        if ($mode != self::FORMAT_DER) {
            $newcert = ASN1::extractBER($cert);
            if ($mode == self::FORMAT_PEM && $cert == $newcert) {
                return false;
            }
            $cert = $newcert;
        }
        if ($cert === false) {
            $this->currentCert = false;
            return false;
        }
        $decoded = ASN1::decodeBER($cert);
        if (!empty($decoded)) {
            $x509 = ASN1::asn1map($decoded[0], Maps\Certificate::MAP);
        }
        if (!isset($x509) || $x509 === false) {
            $this->currentCert = false;
            return false;
        }
        $this->signatureSubject = \Phabel\Target\Php80\Polyfill::substr($cert, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
        if ($this->isSubArrayValid($x509, 'tbsCertificate/extensions')) {
            $this->mapInExtensions($x509, 'tbsCertificate/extensions');
        }
        $this->mapInDNs($x509, 'tbsCertificate/issuer/rdnSequence');
        $this->mapInDNs($x509, 'tbsCertificate/subject/rdnSequence');
        $key = $x509['tbsCertificate']['subjectPublicKeyInfo'];
        $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP);
        $x509['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'] = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($key), 64) . "-----END PUBLIC KEY-----";
        $this->currentCert = $x509;
        $this->dn = $x509['tbsCertificate']['subject'];
        $currentKeyIdentifier = $this->getExtension('id-ce-subjectKeyIdentifier');
        $this->currentKeyIdentifier = is_string($currentKeyIdentifier) ? $currentKeyIdentifier : null;
        return $x509;
    }
    /**
     * Save X.509 certificate
     *
     * @param array $cert
     * @param int $format optional
     * @access public
     * @return string
     */
    public function saveX509($cert, $format = self::FORMAT_PEM)
    {
        if (!is_array($cert) || !isset($cert['tbsCertificate'])) {
            return false;
        }
        switch (true) {
            // "case !$a: case !$b: break; default: whatever();" is the same thing as "if ($a && $b) whatever()"
            case !($algorithm = $this->subArray($cert, 'tbsCertificate/subjectPublicKeyInfo/algorithm/algorithm')):
            case is_object($cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
                break;
            default:
                $cert['tbsCertificate']['subjectPublicKeyInfo'] = new Element(base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $cert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'])));
        }
        if ($algorithm == 'rsaEncryption') {
            $cert['signatureAlgorithm']['parameters'] = null;
            $cert['tbsCertificate']['signature']['parameters'] = null;
        }
        $filters = [];
        $type_utf8_string = ['type' => ASN1::TYPE_UTF8_STRING];
        $filters['tbsCertificate']['signature']['parameters'] = $type_utf8_string;
        $filters['tbsCertificate']['signature']['issuer']['rdnSequence']['value'] = $type_utf8_string;
        $filters['tbsCertificate']['issuer']['rdnSequence']['value'] = $type_utf8_string;
        $filters['tbsCertificate']['subject']['rdnSequence']['value'] = $type_utf8_string;
        $filters['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['parameters'] = $type_utf8_string;
        $filters['signatureAlgorithm']['parameters'] = $type_utf8_string;
        $filters['authorityCertIssuer']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
        //$filters['policyQualifiers']['qualifier'] = $type_utf8_string;
        $filters['distributionPoint']['fullName']['directoryName']['rdnSequence']['value'] = $type_utf8_string;
        $filters['directoryName']['rdnSequence']['value'] = $type_utf8_string;
        foreach (self::$extensions as $extension) {
            $filters['tbsCertificate']['extensions'][] = $extension;
        }
        /* in the case of policyQualifiers/qualifier, the type has to be \phpseclib3\File\ASN1::TYPE_IA5_STRING.
             \phpseclib3\File\ASN1::TYPE_PRINTABLE_STRING will cause OpenSSL's X.509 parser to spit out random
             characters.
           */
        $filters['policyQualifiers']['qualifier'] = ['type' => ASN1::TYPE_IA5_STRING];
        ASN1::setFilters($filters);
        $this->mapOutExtensions($cert, 'tbsCertificate/extensions');
        $this->mapOutDNs($cert, 'tbsCertificate/issuer/rdnSequence');
        $this->mapOutDNs($cert, 'tbsCertificate/subject/rdnSequence');
        $cert = ASN1::encodeDER($cert, Maps\Certificate::MAP);
        switch ($format) {
            case self::FORMAT_DER:
                return $cert;
            // case self::FORMAT_PEM:
            default:
                return "-----BEGIN CERTIFICATE-----\r\n" . chunk_split(Base64::encode($cert), 64) . '-----END CERTIFICATE-----';
        }
    }
    /**
    * Map extension values from octet string to extension-specific internal
    format.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapInExtensions(&$root, $path)
    {
        $extensions =& $this->subArrayUnchecked($root, $path);
        if ($extensions) {
            for ($i = 0; $i < count($extensions); $i++) {
                $id = $extensions[$i]['extnId'];
                $value =& $extensions[$i]['extnValue'];
                /* [extnValue] contains the DER encoding of an ASN.1 value
                   corresponding to the extension type identified by extnID */
                $map = $this->getMapping($id);
                if (!is_bool($map)) {
                    $decoder = $id == 'id-ce-nameConstraints' ? [static::class, 'decodeNameConstraintIP'] : [static::class, 'decodeIP'];
                    $decoded = ASN1::decodeBER($value);
                    $mapped = ASN1::asn1map($decoded[0], $map, ['iPAddress' => $decoder]);
                    $value = $mapped === false ? $decoded[0] : $mapped;
                    if ($id == 'id-ce-certificatePolicies') {
                        for ($j = 0; $j < count($value); $j++) {
                            if (!isset($value[$j]['policyQualifiers'])) {
                                continue;
                            }
                            for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
                                $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
                                $map = $this->getMapping($subid);
                                $subvalue =& $value[$j]['policyQualifiers'][$k]['qualifier'];
                                if ($map !== false) {
                                    $decoded = ASN1::decodeBER($subvalue);
                                    $mapped = ASN1::asn1map($decoded[0], $map);
                                    $subvalue = $mapped === false ? $decoded[0] : $mapped;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    /**
    * Map extension values from extension-specific internal format to
    octet string.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapOutExtensions(&$root, $path)
    {
        $extensions =& $this->subArray($root, $path, !empty($this->extensionValues));
        foreach ($this->extensionValues as $id => $data) {
            extract($data);
            $newext = ['extnId' => $id, 'extnValue' => $value, 'critical' => $critical];
            if ($replace) {
                foreach ($extensions as $key => $value) {
                    if ($value['extnId'] == $id) {
                        $extensions[$key] = $newext;
                        continue 2;
                    }
                }
            }
            $extensions[] = $newext;
        }
        if (is_array($extensions)) {
            $size = count($extensions);
            for ($i = 0; $i < $size; $i++) {
                if ($extensions[$i] instanceof Element) {
                    continue;
                }
                $id = $extensions[$i]['extnId'];
                $value =& $extensions[$i]['extnValue'];
                switch ($id) {
                    case 'id-ce-certificatePolicies':
                        for ($j = 0; $j < count($value); $j++) {
                            if (!isset($value[$j]['policyQualifiers'])) {
                                continue;
                            }
                            for ($k = 0; $k < count($value[$j]['policyQualifiers']); $k++) {
                                $subid = $value[$j]['policyQualifiers'][$k]['policyQualifierId'];
                                $map = $this->getMapping($subid);
                                $subvalue =& $value[$j]['policyQualifiers'][$k]['qualifier'];
                                if ($map !== false) {
                                    // by default \phpseclib3\File\ASN1 will try to render qualifier as a \phpseclib3\File\ASN1::TYPE_IA5_STRING since it's
                                    // actual type is \phpseclib3\File\ASN1::TYPE_ANY
                                    $subvalue = new Element(ASN1::encodeDER($subvalue, $map));
                                }
                            }
                        }
                        break;
                    case 'id-ce-authorityKeyIdentifier':
                        // use 00 as the serial number instead of an empty string
                        if (isset($value['authorityCertSerialNumber'])) {
                            if ($value['authorityCertSerialNumber']->toBytes() == '') {
                                $temp = chr(ASN1::CLASS_CONTEXT_SPECIFIC << 6 | 2) . "\x01\x00";
                                $value['authorityCertSerialNumber'] = new Element($temp);
                            }
                        }
                }
                /* [extnValue] contains the DER encoding of an ASN.1 value
                   corresponding to the extension type identified by extnID */
                $map = $this->getMapping($id);
                if (is_bool($map)) {
                    if (!$map) {
                        //user_error($id . ' is not a currently supported extension');
                        unset($extensions[$i]);
                    }
                } else {
                    $value = ASN1::encodeDER($value, $map, ['iPAddress' => [static::class, 'encodeIP']]);
                }
            }
        }
    }
    /**
    * Map attribute values from ANY type to attribute-specific internal
    format.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapInAttributes(&$root, $path)
    {
        $attributes =& $this->subArray($root, $path);
        if (is_array($attributes)) {
            for ($i = 0; $i < count($attributes); $i++) {
                $id = $attributes[$i]['type'];
                /* $value contains the DER encoding of an ASN.1 value
                   corresponding to the attribute type identified by type */
                $map = $this->getMapping($id);
                if (is_array($attributes[$i]['value'])) {
                    $values =& $attributes[$i]['value'];
                    for ($j = 0; $j < count($values); $j++) {
                        $value = ASN1::encodeDER($values[$j], Maps\AttributeValue::MAP);
                        $decoded = ASN1::decodeBER($value);
                        if (!is_bool($map)) {
                            $mapped = ASN1::asn1map($decoded[0], $map);
                            if ($mapped !== false) {
                                $values[$j] = $mapped;
                            }
                            if ($id == 'pkcs-9-at-extensionRequest' && $this->isSubArrayValid($values, $j)) {
                                $this->mapInExtensions($values, $j);
                            }
                        } elseif ($map) {
                            $values[$j] = $value;
                        }
                    }
                }
            }
        }
    }
    /**
    * Map attribute values from attribute-specific internal format to
    ANY type.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapOutAttributes(&$root, $path)
    {
        $attributes =& $this->subArray($root, $path);
        if (is_array($attributes)) {
            $size = count($attributes);
            for ($i = 0; $i < $size; $i++) {
                /* [value] contains the DER encoding of an ASN.1 value
                   corresponding to the attribute type identified by type */
                $id = $attributes[$i]['type'];
                $map = $this->getMapping($id);
                if ($map === false) {
                    //user_error($id . ' is not a currently supported attribute', E_USER_NOTICE);
                    unset($attributes[$i]);
                } elseif (is_array($attributes[$i]['value'])) {
                    $values =& $attributes[$i]['value'];
                    for ($j = 0; $j < count($values); $j++) {
                        switch ($id) {
                            case 'pkcs-9-at-extensionRequest':
                                $this->mapOutExtensions($values, $j);
                                break;
                        }
                        if (!is_bool($map)) {
                            $temp = ASN1::encodeDER($values[$j], $map);
                            $decoded = ASN1::decodeBER($temp);
                            $values[$j] = ASN1::asn1map($decoded[0], Maps\AttributeValue::MAP);
                        }
                    }
                }
            }
        }
    }
    /**
    * Map DN values from ANY type to DN-specific internal
    format.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapInDNs(&$root, $path)
    {
        $dns =& $this->subArray($root, $path);
        if (is_array($dns)) {
            for ($i = 0; $i < count($dns); $i++) {
                for ($j = 0; $j < count($dns[$i]); $j++) {
                    $type = $dns[$i][$j]['type'];
                    $value =& $dns[$i][$j]['value'];
                    if (is_object($value) && $value instanceof Element) {
                        $map = $this->getMapping($type);
                        if (!is_bool($map)) {
                            $decoded = ASN1::decodeBER($value);
                            $value = ASN1::asn1map($decoded[0], $map);
                        }
                    }
                }
            }
        }
    }
    /**
    * Map DN values from DN-specific internal format to
    ANY type.
    *
    * @param array $root (by reference)
    * @param string $path
    * @access private
    */
    private function mapOutDNs(&$root, $path)
    {
        $dns =& $this->subArray($root, $path);
        if (is_array($dns)) {
            $size = count($dns);
            for ($i = 0; $i < $size; $i++) {
                for ($j = 0; $j < count($dns[$i]); $j++) {
                    $type = $dns[$i][$j]['type'];
                    $value =& $dns[$i][$j]['value'];
                    if (is_object($value) && $value instanceof Element) {
                        continue;
                    }
                    $map = $this->getMapping($type);
                    if (!is_bool($map)) {
                        $value = new Element(ASN1::encodeDER($value, $map));
                    }
                }
            }
        }
    }
    /**
     * Associate an extension ID to an extension mapping
     *
     * @param string $extnId
     * @access private
     * @return mixed
     */
    private function getMapping($extnId)
    {
        if (!is_string($extnId)) {
            // eg. if it's a \phpseclib3\File\ASN1\Element object
            return true;
        }
        if (isset(self::$extensions[$extnId])) {
            return self::$extensions[$extnId];
        }
        switch ($extnId) {
            case 'id-ce-keyUsage':
                return Maps\KeyUsage::MAP;
            case 'id-ce-basicConstraints':
                return Maps\BasicConstraints::MAP;
            case 'id-ce-subjectKeyIdentifier':
                return Maps\KeyIdentifier::MAP;
            case 'id-ce-cRLDistributionPoints':
                return Maps\CRLDistributionPoints::MAP;
            case 'id-ce-authorityKeyIdentifier':
                return Maps\AuthorityKeyIdentifier::MAP;
            case 'id-ce-certificatePolicies':
                return Maps\CertificatePolicies::MAP;
            case 'id-ce-extKeyUsage':
                return Maps\ExtKeyUsageSyntax::MAP;
            case 'id-pe-authorityInfoAccess':
                return Maps\AuthorityInfoAccessSyntax::MAP;
            case 'id-ce-subjectAltName':
                return Maps\SubjectAltName::MAP;
            case 'id-ce-subjectDirectoryAttributes':
                return Maps\SubjectDirectoryAttributes::MAP;
            case 'id-ce-privateKeyUsagePeriod':
                return Maps\PrivateKeyUsagePeriod::MAP;
            case 'id-ce-issuerAltName':
                return Maps\IssuerAltName::MAP;
            case 'id-ce-policyMappings':
                return Maps\PolicyMappings::MAP;
            case 'id-ce-nameConstraints':
                return Maps\NameConstraints::MAP;
            case 'netscape-cert-type':
                return Maps\netscape_cert_type::MAP;
            case 'netscape-comment':
                return Maps\netscape_comment::MAP;
            case 'netscape-ca-policy-url':
                return Maps\netscape_ca_policy_url::MAP;
            // since id-qt-cps isn't a constructed type it will have already been decoded as a string by the time it gets
            // back around to asn1map() and we don't want it decoded again.
            //case 'id-qt-cps':
            //    return Maps\CPSuri::MAP;
            case 'id-qt-unotice':
                return Maps\UserNotice::MAP;
            // the following OIDs are unsupported but we don't want them to give notices when calling saveX509().
            case 'id-pe-logotype':
            // http://www.ietf.org/rfc/rfc3709.txt
            case 'entrustVersInfo':
            // http://support.microsoft.com/kb/287547
            case '1.3.6.1.4.1.311.20.2':
            // szOID_ENROLL_CERTTYPE_EXTENSION
            case '1.3.6.1.4.1.311.21.1':
            // szOID_CERTSRV_CA_VERSION
            // "SET Secure Electronic Transaction Specification"
            // http://www.maithean.com/docs/set_bk3.pdf
            case '2.23.42.7.0':
            // id-set-hashedRootKey
            // "Certificate Transparency"
            // https://tools.ietf.org/html/rfc6962
            case '1.3.6.1.4.1.11129.2.4.2':
            // "Qualified Certificate statements"
            // https://tools.ietf.org/html/rfc3739#section-3.2.6
            case '1.3.6.1.5.5.7.1.3':
                return true;
            // CSR attributes
            case 'pkcs-9-at-unstructuredName':
                return Maps\PKCS9String::MAP;
            case 'pkcs-9-at-challengePassword':
                return Maps\DirectoryString::MAP;
            case 'pkcs-9-at-extensionRequest':
                return Maps\Extensions::MAP;
            // CRL extensions.
            case 'id-ce-cRLNumber':
                return Maps\CRLNumber::MAP;
            case 'id-ce-deltaCRLIndicator':
                return Maps\CRLNumber::MAP;
            case 'id-ce-issuingDistributionPoint':
                return Maps\IssuingDistributionPoint::MAP;
            case 'id-ce-freshestCRL':
                return Maps\CRLDistributionPoints::MAP;
            case 'id-ce-cRLReasons':
                return Maps\CRLReason::MAP;
            case 'id-ce-invalidityDate':
                return Maps\InvalidityDate::MAP;
            case 'id-ce-certificateIssuer':
                return Maps\CertificateIssuer::MAP;
            case 'id-ce-holdInstructionCode':
                return Maps\HoldInstructionCode::MAP;
            case 'id-at-postalAddress':
                return Maps\PostalAddress::MAP;
        }
        return false;
    }
    /**
     * Load an X.509 certificate as a certificate authority
     *
     * @param string $cert
     * @access public
     * @return bool
     */
    public function loadCA($cert)
    {
        $olddn = $this->dn;
        $oldcert = $this->currentCert;
        $oldsigsubj = $this->signatureSubject;
        $oldkeyid = $this->currentKeyIdentifier;
        $cert = $this->loadX509($cert);
        if (!$cert) {
            $this->dn = $olddn;
            $this->currentCert = $oldcert;
            $this->signatureSubject = $oldsigsubj;
            $this->currentKeyIdentifier = $oldkeyid;
            return false;
        }
        /* From RFC5280 "PKIX Certificate and CRL Profile":
        
                   If the keyUsage extension is present, then the subject public key
                   MUST NOT be used to verify signatures on certificates or CRLs unless
                   the corresponding keyCertSign or cRLSign bit is set. */
        //$keyUsage = $this->getExtension('id-ce-keyUsage');
        //if ($keyUsage && !in_array('keyCertSign', $keyUsage)) {
        //    return false;
        //}
        /* From RFC5280 "PKIX Certificate and CRL Profile":
        
                   The cA boolean indicates whether the certified public key may be used
                   to verify certificate signatures.  If the cA boolean is not asserted,
                   then the keyCertSign bit in the key usage extension MUST NOT be
                   asserted.  If the basic constraints extension is not present in a
                   version 3 certificate, or the extension is present but the cA boolean
                   is not asserted, then the certified public key MUST NOT be used to
                   verify certificate signatures. */
        //$basicConstraints = $this->getExtension('id-ce-basicConstraints');
        //if (!$basicConstraints || !$basicConstraints['cA']) {
        //    return false;
        //}
        $this->CAs[] = $cert;
        $this->dn = $olddn;
        $this->currentCert = $oldcert;
        $this->signatureSubject = $oldsigsubj;
        return true;
    }
    /**
    * Validate an X.509 certificate against a URL
    *
    * From RFC2818 "HTTP over TLS":
    *
    * Matching is performed using the matching rules specified by
    [RFC2459].  If more than one identity of a given type is present in
    the certificate (e.g., more than one dNSName name, a match in any one
    of the set is considered acceptable.) Names may contain the wildcard
    character * which is considered to match any single domain name
    component or component fragment. E.g., *.a.com matches foo.a.com but
    not bar.foo.a.com. f*.com matches foo.com but not bar.com.
    *
    * @param string $url
    * @access public
    * @return bool
    */
    public function validateURL($url)
    {
        if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
            return false;
        }
        $components = parse_url($url);
        if (!isset($components['host'])) {
            return false;
        }
        if ($names = $this->getExtension('id-ce-subjectAltName')) {
            foreach ($names as $name) {
                foreach ($name as $key => $value) {
                    $value = str_replace(['.', '*'], ['\\.', '[^.]*'], $value);
                    switch ($key) {
                        case 'dNSName':
                            /* From RFC2818 "HTTP over TLS":
                            
                                                           If a subjectAltName extension of type dNSName is present, that MUST
                                                           be used as the identity. Otherwise, the (most specific) Common Name
                                                           field in the Subject field of the certificate MUST be used. Although
                                                           the use of the Common Name is existing practice, it is deprecated and
                                                           Certification Authorities are encouraged to use the dNSName instead. */
                            if (preg_match('#^' . $value . '$#', $components['host'])) {
                                return true;
                            }
                            break;
                        case 'iPAddress':
                            /* From RFC2818 "HTTP over TLS":
                            
                                                           In some cases, the URI is specified as an IP address rather than a
                                                           hostname. In this case, the iPAddress subjectAltName must be present
                                                           in the certificate and must exactly match the IP in the URI. */
                            if (preg_match('#(?:\\d{1-3}\\.){4}#', $components['host'] . '.') && preg_match('#^' . $value . '$#', $components['host'])) {
                                return true;
                            }
                    }
                }
            }
            return false;
        }
        if ($value = $this->getDNProp('id-at-commonName')) {
            $value = str_replace(['.', '*'], ['\\.', '[^.]*'], $value[0]);
            return preg_match('#^' . $value . '$#', $components['host']);
        }
        return false;
    }
    /**
     * Validate a date
     *
     * If $date isn't defined it is assumed to be the current date.
     *
     * @param (DateTimeInterface | string) $date optional
     * @access public
     * @return boolean
     */
    public function validateDate($date = null)
    {
        if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
            return false;
        }
        if (!isset($date)) {
            $date = new DateTimeImmutable(null, new DateTimeZone(@date_default_timezone_get()));
        }
        $notBefore = $this->currentCert['tbsCertificate']['validity']['notBefore'];
        $notBefore = isset($notBefore['generalTime']) ? $notBefore['generalTime'] : $notBefore['utcTime'];
        $notAfter = $this->currentCert['tbsCertificate']['validity']['notAfter'];
        $notAfter = isset($notAfter['generalTime']) ? $notAfter['generalTime'] : $notAfter['utcTime'];
        if (is_string($date)) {
            $date = new DateTimeImmutable($date, new DateTimeZone(@date_default_timezone_get()));
        }
        $notBefore = new DateTimeImmutable($notBefore, new DateTimeZone(@date_default_timezone_get()));
        $notAfter = new DateTimeImmutable($notAfter, new DateTimeZone(@date_default_timezone_get()));
        return $date >= $notBefore && $date <= $notAfter;
    }
    /**
     * Fetches a URL
     *
     * @param string $url
     * @access private
     * @return (bool | string)
     */
    private static function fetchURL($url)
    {
        if (self::$disable_url_fetch) {
            return false;
        }
        $parts = parse_url($url);
        $data = '';
        switch ($parts['scheme']) {
            case 'http':
                $fsock = @\Phabel\Target\Php80\Polyfill::fsockopen($parts['host'], isset($parts['port']) ? $parts['port'] : 80);
                if (!$fsock) {
                    return false;
                }
                fputs($fsock, "GET {$parts['path']} HTTP/1.0\r\n");
                fputs($fsock, "Host: {$parts['host']}\r\n\r\n");
                $line = fgets($fsock, 1024);
                if (strlen($line) < 3) {
                    return false;
                }
                preg_match('#HTTP/1.\\d (\\d{3})#', $line, $temp);
                if ($temp[1] != '200') {
                    return false;
                }
                // skip the rest of the headers in the http response
                while (!feof($fsock) && fgets($fsock, 1024) != "\r\n") {
                }
                while (!feof($fsock)) {
                    $temp = fread($fsock, 1024);
                    if ($temp === false) {
                        return false;
                    }
                    $data .= $temp;
                }
                break;
        }
        return $data;
    }
    /**
     * Validates an intermediate cert as identified via authority info access extension
     *
     * See https://tools.ietf.org/html/rfc4325 for more info
     *
     * @param bool $caonly
     * @param int $count
     * @access private
     * @return bool
     */
    private function testForIntermediate($caonly, $count)
    {
        $opts = $this->getExtension('id-pe-authorityInfoAccess');
        if (!is_array($opts)) {
            return false;
        }
        foreach ($opts as $opt) {
            if ($opt['accessMethod'] == 'id-ad-caIssuers') {
                // accessLocation is a GeneralName. GeneralName fields support stuff like email addresses, IP addresses, LDAP,
                // etc, but we're only supporting URI's. URI's and LDAP are the only thing https://tools.ietf.org/html/rfc4325
                // discusses
                if (isset($opt['accessLocation']['uniformResourceIdentifier'])) {
                    $url = $opt['accessLocation']['uniformResourceIdentifier'];
                    break;
                }
            }
        }
        if (!isset($url)) {
            return false;
        }
        $cert = static::fetchURL($url);
        if (!is_string($cert)) {
            return false;
        }
        $parent = new static();
        $parent->CAs = $this->CAs;
        /*
         "Conforming applications that support HTTP or FTP for accessing
          certificates MUST be able to accept .cer files and SHOULD be able
          to accept .p7c files." -- https://tools.ietf.org/html/rfc4325
        
         A .p7c file is 'a "certs-only" CMS message as specified in RFC 2797"
        
         These are currently unsupported
        */
        if (!is_array($parent->loadX509($cert))) {
            return false;
        }
        if (!$parent->validateSignatureCountable($caonly, ++$count)) {
            return false;
        }
        $this->CAs[] = $parent->currentCert;
        //$this->loadCA($cert);
        return true;
    }
    /**
    * Validate a signature
    *
    * Works on X.509 certs, CSR's and CRL's.
    Returns true if the signature is verified, false if it is not correct or null on error
    *
    * By default returns false for self-signed certs. Call validateSignature(false) to make this support
    self-signed.
    *
    * The behavior of this function is inspired by {@link http://php.net/openssl-verify openssl_verify}.
    *
    * @param bool $caonly optional
    * @access public
    * @return mixed
    */
    public function validateSignature($caonly = true)
    {
        return $this->validateSignatureCountable($caonly, 0);
    }
    /**
     * Validate a signature
     *
     * Performs said validation whilst keeping track of how many times validation method is called
     *
     * @param bool $caonly
     * @param int $count
     * @access private
     * @return mixed
     */
    private function validateSignatureCountable($caonly, $count)
    {
        if (!is_array($this->currentCert) || !isset($this->signatureSubject)) {
            return null;
        }
        if ($count == self::$recur_limit) {
            return false;
        }
        /* TODO:
                   "emailAddress attribute values are not case-sensitive (e.g., "subscriber@example.com" is the same as "SUBSCRIBER@EXAMPLE.COM")."
                    -- http://tools.ietf.org/html/rfc5280#section-4.1.2.6
        
                   implement pathLenConstraint in the id-ce-basicConstraints extension */
        switch (true) {
            case isset($this->currentCert['tbsCertificate']):
                // self-signed cert
                switch (true) {
                    case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $this->currentCert['tbsCertificate']['subject']:
                    case defined('FILE_X509_IGNORE_TYPE') && $this->getIssuerDN(self::DN_STRING) === $this->getDN(self::DN_STRING):
                        $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
                        $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier');
                        switch (true) {
                            case !is_array($authorityKey):
                            case !$subjectKeyID:
                            case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
                                $signingCert = $this->currentCert;
                        }
                }
                if (!empty($this->CAs)) {
                    for ($i = 0; $i < count($this->CAs); $i++) {
                        // even if the cert is a self-signed one we still want to see if it's a CA;
                        // if not, we'll conditionally return an error
                        $ca = $this->CAs[$i];
                        switch (true) {
                            case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']:
                            case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertificate']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
                                $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
                                $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
                                switch (true) {
                                    case !is_array($authorityKey):
                                    case !$subjectKeyID:
                                    case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
                                        if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
                                            break 2;
                                            // serial mismatch - check other ca
                                        }
                                        $signingCert = $ca;
                                        // working cert
                                        break 3;
                                }
                        }
                    }
                    if (count($this->CAs) == $i && $caonly) {
                        return $this->testForIntermediate($caonly, $count) && $this->validateSignature($caonly);
                    }
                } elseif (!isset($signingCert) || $caonly) {
                    return $this->testForIntermediate($caonly, $count) && $this->validateSignature($caonly);
                }
                return $this->validateSignatureHelper($signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $this->currentCert['signatureAlgorithm']['algorithm'], \Phabel\Target\Php80\Polyfill::substr($this->currentCert['signature'], 1), $this->signatureSubject);
            case isset($this->currentCert['certificationRequestInfo']):
                return $this->validateSignatureHelper($this->currentCert['certificationRequestInfo']['subjectPKInfo']['algorithm']['algorithm'], $this->currentCert['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $this->currentCert['signatureAlgorithm']['algorithm'], \Phabel\Target\Php80\Polyfill::substr($this->currentCert['signature'], 1), $this->signatureSubject);
            case isset($this->currentCert['publicKeyAndChallenge']):
                return $this->validateSignatureHelper($this->currentCert['publicKeyAndChallenge']['spki']['algorithm']['algorithm'], $this->currentCert['publicKeyAndChallenge']['spki']['subjectPublicKey'], $this->currentCert['signatureAlgorithm']['algorithm'], \Phabel\Target\Php80\Polyfill::substr($this->currentCert['signature'], 1), $this->signatureSubject);
            case isset($this->currentCert['tbsCertList']):
                if (!empty($this->CAs)) {
                    for ($i = 0; $i < count($this->CAs); $i++) {
                        $ca = $this->CAs[$i];
                        switch (true) {
                            case !defined('FILE_X509_IGNORE_TYPE') && $this->currentCert['tbsCertList']['issuer'] === $ca['tbsCertificate']['subject']:
                            case defined('FILE_X509_IGNORE_TYPE') && $this->getDN(self::DN_STRING, $this->currentCert['tbsCertList']['issuer']) === $this->getDN(self::DN_STRING, $ca['tbsCertificate']['subject']):
                                $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier');
                                $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
                                switch (true) {
                                    case !is_array($authorityKey):
                                    case !$subjectKeyID:
                                    case isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
                                        if (is_array($authorityKey) && isset($authorityKey['authorityCertSerialNumber']) && !$authorityKey['authorityCertSerialNumber']->equals($ca['tbsCertificate']['serialNumber'])) {
                                            break 2;
                                            // serial mismatch - check other ca
                                        }
                                        $signingCert = $ca;
                                        // working cert
                                        break 3;
                                }
                        }
                    }
                }
                if (!isset($signingCert)) {
                    return false;
                }
                return $this->validateSignatureHelper($signingCert['tbsCertificate']['subjectPublicKeyInfo']['algorithm']['algorithm'], $signingCert['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $this->currentCert['signatureAlgorithm']['algorithm'], \Phabel\Target\Php80\Polyfill::substr($this->currentCert['signature'], 1), $this->signatureSubject);
            default:
                return false;
        }
    }
    /**
    * Validates a signature
    *
    * Returns true if the signature is verified and false if it is not correct.
    If the algorithms are unsupposed an exception is thrown.
    *
    * @param string $publicKeyAlgorithm
    * @param string $publicKey
    * @param string $signatureAlgorithm
    * @param string $signature
    * @param string $signatureSubject
    * @access private
    * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
    * @return bool
    */
    private function validateSignatureHelper($publicKeyAlgorithm, $publicKey, $signatureAlgorithm, $signature, $signatureSubject)
    {
        switch ($publicKeyAlgorithm) {
            case 'id-RSASSA-PSS':
                $key = RSA::loadFormat('PSS', $publicKey);
                break;
            case 'rsaEncryption':
                $key = RSA::loadFormat('PKCS8', $publicKey);
                switch ($signatureAlgorithm) {
                    case 'md2WithRSAEncryption':
                    case 'md5WithRSAEncryption':
                    case 'sha1WithRSAEncryption':
                    case 'sha224WithRSAEncryption':
                    case 'sha256WithRSAEncryption':
                    case 'sha384WithRSAEncryption':
                    case 'sha512WithRSAEncryption':
                        $key = $key->withHash(preg_replace('#WithRSAEncryption$#', '', $signatureAlgorithm))->withPadding(RSA::SIGNATURE_PKCS1);
                        break;
                    default:
                        throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
                }
                break;
            case 'id-Ed25519':
            case 'id-Ed448':
                $key = EC::loadFormat('PKCS8', $publicKey);
                break;
            case 'id-ecPublicKey':
                $key = EC::loadFormat('PKCS8', $publicKey);
                switch ($signatureAlgorithm) {
                    case 'ecdsa-with-SHA1':
                    case 'ecdsa-with-SHA224':
                    case 'ecdsa-with-SHA256':
                    case 'ecdsa-with-SHA384':
                    case 'ecdsa-with-SHA512':
                        $key = $key->withHash(preg_replace('#^ecdsa-with-#', '', strtolower($signatureAlgorithm)));
                        break;
                    default:
                        throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
                }
                break;
            case 'id-dsa':
                $key = DSA::loadFormat('PKCS8', $publicKey);
                switch ($signatureAlgorithm) {
                    case 'id-dsa-with-sha1':
                    case 'id-dsa-with-sha224':
                    case 'id-dsa-with-sha256':
                        $key = $key->withHash(preg_replace('#^id-dsa-with-#', '', strtolower($signatureAlgorithm)));
                        break;
                    default:
                        throw new UnsupportedAlgorithmException('Signature algorithm unsupported');
                }
                break;
            default:
                throw new UnsupportedAlgorithmException('Public key algorithm unsupported');
        }
        return $key->verify($signatureSubject, $signature);
    }
    /**
    * Sets the recursion limit
    *
    * When validating a signature it may be necessary to download intermediate certs from URI's.
    An intermediate cert that linked to itself would result in an infinite loop so to prevent
    that we set a recursion limit. A negative number means that there is no recursion limit.
    *
    * @param int $count
    * @access public
    */
    public static function setRecurLimit($count)
    {
        self::$recur_limit = $count;
    }
    /**
     * Prevents URIs from being automatically retrieved
     *
     * @access public
     */
    public static function disableURLFetch()
    {
        self::$disable_url_fetch = true;
    }
    /**
     * Allows URIs to be automatically retrieved
     *
     * @access public
     */
    public static function enableURLFetch()
    {
        self::$disable_url_fetch = false;
    }
    /**
     * Decodes an IP address
     *
     * Takes in a base64 encoded "blob" and returns a human readable IP address
     *
     * @param string $ip
     * @access private
     * @return string
     */
    public static function decodeIP($ip)
    {
        return inet_ntop($ip);
    }
    /**
     * Decodes an IP address in a name constraints extension
     *
     * Takes in a base64 encoded "blob" and returns a human readable IP address / mask
     *
     * @param string $ip
     * @access private
     * @return array
     */
    public static function decodeNameConstraintIP($ip)
    {
        $size = strlen($ip) >> 1;
        $mask = \Phabel\Target\Php80\Polyfill::substr($ip, $size);
        $ip = \Phabel\Target\Php80\Polyfill::substr($ip, 0, $size);
        return [inet_ntop($ip), inet_ntop($mask)];
    }
    /**
     * Encodes an IP address
     *
     * Takes a human readable IP address into a base64-encoded "blob"
     *
     * @param (string | array) $ip
     * @access private
     * @return string
     */
    public static function encodeIP($ip)
    {
        return is_string($ip) ? inet_pton($ip) : inet_pton($ip[0]) . inet_pton($ip[1]);
    }
    /**
     * "Normalizes" a Distinguished Name property
     *
     * @param string $propName
     * @access private
     * @return mixed
     */
    private function translateDNProp($propName)
    {
        switch (strtolower($propName)) {
            case 'id-at-countryname':
            case 'countryname':
            case 'c':
                return 'id-at-countryName';
            case 'id-at-organizationname':
            case 'organizationname':
            case 'o':
                return 'id-at-organizationName';
            case 'id-at-dnqualifier':
            case 'dnqualifier':
                return 'id-at-dnQualifier';
            case 'id-at-commonname':
            case 'commonname':
            case 'cn':
                return 'id-at-commonName';
            case 'id-at-stateorprovincename':
            case 'stateorprovincename':
            case 'state':
            case 'province':
            case 'provincename':
            case 'st':
                return 'id-at-stateOrProvinceName';
            case 'id-at-localityname':
            case 'localityname':
            case 'l':
                return 'id-at-localityName';
            case 'id-emailaddress':
            case 'emailaddress':
                return 'pkcs-9-at-emailAddress';
            case 'id-at-serialnumber':
            case 'serialnumber':
                return 'id-at-serialNumber';
            case 'id-at-postalcode':
            case 'postalcode':
                return 'id-at-postalCode';
            case 'id-at-streetaddress':
            case 'streetaddress':
                return 'id-at-streetAddress';
            case 'id-at-name':
            case 'name':
                return 'id-at-name';
            case 'id-at-givenname':
            case 'givenname':
                return 'id-at-givenName';
            case 'id-at-surname':
            case 'surname':
            case 'sn':
                return 'id-at-surname';
            case 'id-at-initials':
            case 'initials':
                return 'id-at-initials';
            case 'id-at-generationqualifier':
            case 'generationqualifier':
                return 'id-at-generationQualifier';
            case 'id-at-organizationalunitname':
            case 'organizationalunitname':
            case 'ou':
                return 'id-at-organizationalUnitName';
            case 'id-at-pseudonym':
            case 'pseudonym':
                return 'id-at-pseudonym';
            case 'id-at-title':
            case 'title':
                return 'id-at-title';
            case 'id-at-description':
            case 'description':
                return 'id-at-description';
            case 'id-at-role':
            case 'role':
                return 'id-at-role';
            case 'id-at-uniqueidentifier':
            case 'uniqueidentifier':
            case 'x500uniqueidentifier':
                return 'id-at-uniqueIdentifier';
            case 'postaladdress':
            case 'id-at-postaladdress':
                return 'id-at-postalAddress';
            default:
                return false;
        }
    }
    /**
     * Set a Distinguished Name property
     *
     * @param string $propName
     * @param mixed $propValue
     * @param string $type optional
     * @access public
     * @return bool
     */
    public function setDNProp($propName, $propValue, $type = 'utf8String')
    {
        if (empty($this->dn)) {
            $this->dn = ['rdnSequence' => []];
        }
        if (($propName = $this->translateDNProp($propName)) === false) {
            return false;
        }
        foreach ((array) $propValue as $v) {
            if (!is_array($v) && isset($type)) {
                $v = [$type => $v];
            }
            $this->dn['rdnSequence'][] = [['type' => $propName, 'value' => $v]];
        }
        return true;
    }
    /**
     * Remove Distinguished Name properties
     *
     * @param string $propName
     * @access public
     */
    public function removeDNProp($propName)
    {
        if (empty($this->dn)) {
            return;
        }
        if (($propName = $this->translateDNProp($propName)) === false) {
            return;
        }
        $dn =& $this->dn['rdnSequence'];
        $size = count($dn);
        for ($i = 0; $i < $size; $i++) {
            if ($dn[$i][0]['type'] == $propName) {
                unset($dn[$i]);
            }
        }
        $dn = array_values($dn);
        // fix for https://bugs.php.net/75433 affecting PHP 7.2
        if (!isset($dn[0])) {
            $dn = array_splice($dn, 0, 0);
        }
    }
    /**
     * Get Distinguished Name properties
     *
     * @param string $propName
     * @param array $dn optional
     * @param bool $withType optional
     * @return mixed
     * @access public
     */
    public function getDNProp($propName, $dn = null, $withType = false)
    {
        if (!isset($dn)) {
            $dn = $this->dn;
        }
        if (empty($dn)) {
            return false;
        }
        if (($propName = $this->translateDNProp($propName)) === false) {
            return false;
        }
        $filters = [];
        $filters['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
        ASN1::setFilters($filters);
        $this->mapOutDNs($dn, 'rdnSequence');
        $dn = $dn['rdnSequence'];
        $result = [];
        for ($i = 0; $i < count($dn); $i++) {
            if ($dn[$i][0]['type'] == $propName) {
                $v = $dn[$i][0]['value'];
                if (!$withType) {
                    if (is_array($v)) {
                        foreach ($v as $type => $s) {
                            $type = array_search($type, ASN1::ANY_MAP);
                            if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) {
                                $s = ASN1::convert($s, $type);
                                if ($s !== false) {
                                    $v = $s;
                                    break;
                                }
                            }
                        }
                        if (is_array($v)) {
                            $v = array_pop($v);
                            // Always strip data type.
                        }
                    } elseif (is_object($v) && $v instanceof Element) {
                        $map = $this->getMapping($propName);
                        if (!is_bool($map)) {
                            $decoded = ASN1::decodeBER($v);
                            $v = ASN1::asn1map($decoded[0], $map);
                        }
                    }
                }
                $result[] = $v;
            }
        }
        return $result;
    }
    /**
     * Set a Distinguished Name
     *
     * @param mixed $dn
     * @param bool $merge optional
     * @param string $type optional
     * @access public
     * @return bool
     */
    public function setDN($dn, $merge = false, $type = 'utf8String')
    {
        if (!$merge) {
            $this->dn = null;
        }
        if (is_array($dn)) {
            if (isset($dn['rdnSequence'])) {
                $this->dn = $dn;
                // No merge here.
                return true;
            }
            // handles stuff generated by openssl_x509_parse()
            foreach ($dn as $prop => $value) {
                if (!$this->setDNProp($prop, $value, $type)) {
                    return false;
                }
            }
            return true;
        }
        // handles everything else
        $results = preg_split('#((?:^|, *|/)(?:C=|O=|OU=|CN=|L=|ST=|SN=|postalCode=|streetAddress=|emailAddress=|serialNumber=|organizationalUnitName=|title=|description=|role=|x500UniqueIdentifier=|postalAddress=))#', $dn, -1, PREG_SPLIT_DELIM_CAPTURE);
        for ($i = 1; $i < count($results); $i += 2) {
            $prop = trim($results[$i], ', =/');
            $value = $results[$i + 1];
            if (!$this->setDNProp($prop, $value, $type)) {
                return false;
            }
        }
        return true;
    }
    /**
     * Get the Distinguished Name for a certificates subject
     *
     * @param mixed $format optional
     * @param array $dn optional
     * @access public
     * @return (array | bool)
     */
    public function getDN($format = self::DN_ARRAY, $dn = null)
    {
        if (!isset($dn)) {
            $dn = isset($this->currentCert['tbsCertList']) ? $this->currentCert['tbsCertList']['issuer'] : $this->dn;
        }
        switch ((int) $format) {
            case self::DN_ARRAY:
                return $dn;
            case self::DN_ASN1:
                $filters = [];
                $filters['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
                ASN1::setFilters($filters);
                $this->mapOutDNs($dn, 'rdnSequence');
                return ASN1::encodeDER($dn, Maps\Name::MAP);
            case self::DN_CANON:
                //  No SEQUENCE around RDNs and all string values normalized as
                // trimmed lowercase UTF-8 with all spacing as one blank.
                // constructed RDNs will not be canonicalized
                $filters = [];
                $filters['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
                ASN1::setFilters($filters);
                $result = '';
                $this->mapOutDNs($dn, 'rdnSequence');
                foreach ($dn['rdnSequence'] as $rdn) {
                    foreach ($rdn as $i => $attr) {
                        $attr =& $rdn[$i];
                        if (is_array($attr['value'])) {
                            foreach ($attr['value'] as $type => $v) {
                                $type = array_search($type, ASN1::ANY_MAP, true);
                                if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) {
                                    $v = ASN1::convert($v, $type);
                                    if ($v !== false) {
                                        $v = preg_replace('/\\s+/', ' ', $v);
                                        $attr['value'] = strtolower(trim($v));
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    $result .= ASN1::encodeDER($rdn, Maps\RelativeDistinguishedName::MAP);
                }
                return $result;
            case self::DN_HASH:
                $dn = $this->getDN(self::DN_CANON, $dn);
                $hash = new Hash('sha1');
                $hash = $hash->hash($dn);
                extract(unpack('Vhash', $hash));
                return strtolower(Hex::encode(pack('N', $hash)));
        }
        // Default is to return a string.
        $start = true;
        $output = '';
        $result = [];
        $filters = [];
        $filters['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
        ASN1::setFilters($filters);
        $this->mapOutDNs($dn, 'rdnSequence');
        foreach ($dn['rdnSequence'] as $field) {
            $prop = $field[0]['type'];
            $value = $field[0]['value'];
            $delim = ', ';
            switch ($prop) {
                case 'id-at-countryName':
                    $desc = 'C';
                    break;
                case 'id-at-stateOrProvinceName':
                    $desc = 'ST';
                    break;
                case 'id-at-organizationName':
                    $desc = 'O';
                    break;
                case 'id-at-organizationalUnitName':
                    $desc = 'OU';
                    break;
                case 'id-at-commonName':
                    $desc = 'CN';
                    break;
                case 'id-at-localityName':
                    $desc = 'L';
                    break;
                case 'id-at-surname':
                    $desc = 'SN';
                    break;
                case 'id-at-uniqueIdentifier':
                    $delim = '/';
                    $desc = 'x500UniqueIdentifier';
                    break;
                case 'id-at-postalAddress':
                    $delim = '/';
                    $desc = 'postalAddress';
                    break;
                default:
                    $delim = '/';
                    $desc = preg_replace('#.+-([^-]+)$#', '$1', $prop);
            }
            if (!$start) {
                $output .= $delim;
            }
            if (is_array($value)) {
                foreach ($value as $type => $v) {
                    $type = array_search($type, ASN1::ANY_MAP, true);
                    if ($type !== false && array_key_exists($type, ASN1::STRING_TYPE_SIZE)) {
                        $v = ASN1::convert($v, $type);
                        if ($v !== false) {
                            $value = $v;
                            break;
                        }
                    }
                }
                if (is_array($value)) {
                    $value = array_pop($value);
                    // Always strip data type.
                }
            } elseif (is_object($value) && $value instanceof Element) {
                $callback = function ($x) {
                    return '\\x' . bin2hex($x[0]);
                };
                $value = strtoupper(preg_replace_callback('#[^\\x20-\\x7E]#', $callback, $value->element));
            }
            $output .= $desc . '=' . $value;
            $result[$desc] = isset($result[$desc]) ? array_merge((array) $result[$desc], [$value]) : $value;
            $start = false;
        }
        return $format == self::DN_OPENSSL ? $result : $output;
    }
    /**
     * Get the Distinguished Name for a certificate/crl issuer
     *
     * @param int $format optional
     * @access public
     * @return mixed
     */
    public function getIssuerDN($format = self::DN_ARRAY)
    {
        switch (true) {
            case !isset($this->currentCert) || !is_array($this->currentCert):
                break;
            case isset($this->currentCert['tbsCertificate']):
                return $this->getDN($format, $this->currentCert['tbsCertificate']['issuer']);
            case isset($this->currentCert['tbsCertList']):
                return $this->getDN($format, $this->currentCert['tbsCertList']['issuer']);
        }
        return false;
    }
    /**
    * Get the Distinguished Name for a certificate/csr subject
    Alias of getDN()
    *
    * @param int $format optional
    * @access public
    * @return mixed
    */
    public function getSubjectDN($format = self::DN_ARRAY)
    {
        switch (true) {
            case !empty($this->dn):
                return $this->getDN($format);
            case !isset($this->currentCert) || !is_array($this->currentCert):
                break;
            case isset($this->currentCert['tbsCertificate']):
                return $this->getDN($format, $this->currentCert['tbsCertificate']['subject']);
            case isset($this->currentCert['certificationRequestInfo']):
                return $this->getDN($format, $this->currentCert['certificationRequestInfo']['subject']);
        }
        return false;
    }
    /**
     * Get an individual Distinguished Name property for a certificate/crl issuer
     *
     * @param string $propName
     * @param bool $withType optional
     * @access public
     * @return mixed
     */
    public function getIssuerDNProp($propName, $withType = false)
    {
        switch (true) {
            case !isset($this->currentCert) || !is_array($this->currentCert):
                break;
            case isset($this->currentCert['tbsCertificate']):
                return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['issuer'], $withType);
            case isset($this->currentCert['tbsCertList']):
                return $this->getDNProp($propName, $this->currentCert['tbsCertList']['issuer'], $withType);
        }
        return false;
    }
    /**
     * Get an individual Distinguished Name property for a certificate/csr subject
     *
     * @param string $propName
     * @param bool $withType optional
     * @access public
     * @return mixed
     */
    public function getSubjectDNProp($propName, $withType = false)
    {
        switch (true) {
            case !empty($this->dn):
                return $this->getDNProp($propName, null, $withType);
            case !isset($this->currentCert) || !is_array($this->currentCert):
                break;
            case isset($this->currentCert['tbsCertificate']):
                return $this->getDNProp($propName, $this->currentCert['tbsCertificate']['subject'], $withType);
            case isset($this->currentCert['certificationRequestInfo']):
                return $this->getDNProp($propName, $this->currentCert['certificationRequestInfo']['subject'], $withType);
        }
        return false;
    }
    /**
     * Get the certificate chain for the current cert
     *
     * @access public
     * @return mixed
     */
    public function getChain()
    {
        $chain = [$this->currentCert];
        if (!is_array($this->currentCert) || !isset($this->currentCert['tbsCertificate'])) {
            return false;
        }
        if (empty($this->CAs)) {
            return $chain;
        }
        while (true) {
            $currentCert = $chain[count($chain) - 1];
            for ($i = 0; $i < count($this->CAs); $i++) {
                $ca = $this->CAs[$i];
                if ($currentCert['tbsCertificate']['issuer'] === $ca['tbsCertificate']['subject']) {
                    $authorityKey = $this->getExtension('id-ce-authorityKeyIdentifier', $currentCert);
                    $subjectKeyID = $this->getExtension('id-ce-subjectKeyIdentifier', $ca);
                    switch (true) {
                        case !is_array($authorityKey):
                        case is_array($authorityKey) && isset($authorityKey['keyIdentifier']) && $authorityKey['keyIdentifier'] === $subjectKeyID:
                            if ($currentCert === $ca) {
                                break 3;
                            }
                            $chain[] = $ca;
                            break 2;
                    }
                }
            }
            if ($i == count($this->CAs)) {
                break;
            }
        }
        foreach ($chain as $key => $value) {
            $chain[$key] = new X509();
            $chain[$key]->loadX509($value);
        }
        return $chain;
    }
    /**
     * Returns the current cert
     *
     * @access public
     * @return (array | bool)
     */
    public function &getCurrentCert()
    {
        return $this->currentCert;
    }
    /**
     * Set public key
     *
     * Key needs to be a \phpseclib3\Crypt\RSA object
     *
     * @param PublicKey $key
     * @access public
     * @return bool
     */
    public function setPublicKey(PublicKey $key)
    {
        $this->publicKey = $key;
    }
    /**
     * Set private key
     *
     * Key needs to be a \phpseclib3\Crypt\RSA object
     *
     * @param PrivateKey $key
     * @access public
     */
    public function setPrivateKey(PrivateKey $key)
    {
        $this->privateKey = $key;
    }
    /**
     * Set challenge
     *
     * Used for SPKAC CSR's
     *
     * @param string $challenge
     * @access public
     */
    public function setChallenge($challenge)
    {
        $this->challenge = $challenge;
    }
    /**
     * Gets the public key
     *
     * Returns a \phpseclib3\Crypt\RSA object or a false.
     *
     * @access public
     * @return mixed
     */
    public function getPublicKey()
    {
        if (isset($this->publicKey)) {
            return $this->publicKey;
        }
        if (isset($this->currentCert) && is_array($this->currentCert)) {
            $paths = ['tbsCertificate/subjectPublicKeyInfo', 'certificationRequestInfo/subjectPKInfo', 'publicKeyAndChallenge/spki'];
            foreach ($paths as $path) {
                $keyinfo = $this->subArray($this->currentCert, $path);
                if (!empty($keyinfo)) {
                    break;
                }
            }
        }
        if (empty($keyinfo)) {
            return false;
        }
        $key = $keyinfo['subjectPublicKey'];
        switch ($keyinfo['algorithm']['algorithm']) {
            case 'id-RSASSA-PSS':
                return RSA::loadFormat('PSS', $key);
            case 'rsaEncryption':
                return RSA::loadFormat('PKCS8', $key)->withPadding(RSA::SIGNATURE_PKCS1);
            case 'id-ecPublicKey':
            case 'id-Ed25519':
            case 'id-Ed448':
                return EC::loadFormat('PKCS8', $key);
            case 'id-dsa':
                return DSA::loadFormat('PKCS8', $key);
        }
        return false;
    }
    /**
     * Load a Certificate Signing Request
     *
     * @param string $csr
     * @param int $mode
     * @return mixed
     * @access public
     */
    public function loadCSR($csr, $mode = self::FORMAT_AUTO_DETECT)
    {
        if (is_array($csr) && isset($csr['certificationRequestInfo'])) {
            unset($this->currentCert);
            unset($this->currentKeyIdentifier);
            unset($this->signatureSubject);
            $this->dn = $csr['certificationRequestInfo']['subject'];
            if (!isset($this->dn)) {
                return false;
            }
            $this->currentCert = $csr;
            return $csr;
        }
        // see http://tools.ietf.org/html/rfc2986
        if ($mode != self::FORMAT_DER) {
            $newcsr = ASN1::extractBER($csr);
            if ($mode == self::FORMAT_PEM && $csr == $newcsr) {
                return false;
            }
            $csr = $newcsr;
        }
        $orig = $csr;
        if ($csr === false) {
            $this->currentCert = false;
            return false;
        }
        $decoded = ASN1::decodeBER($csr);
        if (empty($decoded)) {
            $this->currentCert = false;
            return false;
        }
        $csr = ASN1::asn1map($decoded[0], Maps\CertificationRequest::MAP);
        if (!isset($csr) || $csr === false) {
            $this->currentCert = false;
            return false;
        }
        $this->mapInAttributes($csr, 'certificationRequestInfo/attributes');
        $this->mapInDNs($csr, 'certificationRequestInfo/subject/rdnSequence');
        $this->dn = $csr['certificationRequestInfo']['subject'];
        $this->signatureSubject = \Phabel\Target\Php80\Polyfill::substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
        $key = $csr['certificationRequestInfo']['subjectPKInfo'];
        $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP);
        $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'] = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($key), 64) . "-----END PUBLIC KEY-----";
        $this->currentKeyIdentifier = null;
        $this->currentCert = $csr;
        $this->publicKey = null;
        $this->publicKey = $this->getPublicKey();
        return $csr;
    }
    /**
     * Save CSR request
     *
     * @param array $csr
     * @param int $format optional
     * @access public
     * @return string
     */
    public function saveCSR($csr, $format = self::FORMAT_PEM)
    {
        if (!is_array($csr) || !isset($csr['certificationRequestInfo'])) {
            return false;
        }
        switch (true) {
            case !($algorithm = $this->subArray($csr, 'certificationRequestInfo/subjectPKInfo/algorithm/algorithm')):
            case is_object($csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
                break;
            default:
                $csr['certificationRequestInfo']['subjectPKInfo'] = new Element(base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $csr['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'])));
        }
        $filters = [];
        $filters['certificationRequestInfo']['subject']['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
        ASN1::setFilters($filters);
        $this->mapOutDNs($csr, 'certificationRequestInfo/subject/rdnSequence');
        $this->mapOutAttributes($csr, 'certificationRequestInfo/attributes');
        $csr = ASN1::encodeDER($csr, Maps\CertificationRequest::MAP);
        switch ($format) {
            case self::FORMAT_DER:
                return $csr;
            // case self::FORMAT_PEM:
            default:
                return "-----BEGIN CERTIFICATE REQUEST-----\r\n" . chunk_split(Base64::encode($csr), 64) . '-----END CERTIFICATE REQUEST-----';
        }
    }
    /**
     * Load a SPKAC CSR
     *
     * SPKAC's are produced by the HTML5 keygen element:
     *
     * https://developer.mozilla.org/en-US/docs/HTML/Element/keygen
     *
     * @param string $spkac
     * @access public
     * @return mixed
     */
    public function loadSPKAC($spkac)
    {
        if (is_array($spkac) && isset($spkac['publicKeyAndChallenge'])) {
            unset($this->currentCert);
            unset($this->currentKeyIdentifier);
            unset($this->signatureSubject);
            $this->currentCert = $spkac;
            return $spkac;
        }
        // see http://www.w3.org/html/wg/drafts/html/master/forms.html#signedpublickeyandchallenge
        // OpenSSL produces SPKAC's that are preceded by the string SPKAC=
        $temp = preg_replace('#(?:SPKAC=)|[ \\r\\n\\\\]#', '', $spkac);
        $temp = preg_match('#^[a-zA-Z\\d/+]*={0,2}$#', $temp) ? Base64::decode($temp) : false;
        if ($temp != false) {
            $spkac = $temp;
        }
        $orig = $spkac;
        if ($spkac === false) {
            $this->currentCert = false;
            return false;
        }
        $decoded = ASN1::decodeBER($spkac);
        if (empty($decoded)) {
            $this->currentCert = false;
            return false;
        }
        $spkac = ASN1::asn1map($decoded[0], Maps\SignedPublicKeyAndChallenge::MAP);
        if (!isset($spkac) || $spkac === false) {
            $this->currentCert = false;
            return false;
        }
        $this->signatureSubject = \Phabel\Target\Php80\Polyfill::substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
        $key = $spkac['publicKeyAndChallenge']['spki'];
        $key = ASN1::encodeDER($key, Maps\SubjectPublicKeyInfo::MAP);
        $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'] = "-----BEGIN PUBLIC KEY-----\r\n" . chunk_split(base64_encode($key), 64) . "-----END PUBLIC KEY-----";
        $this->currentKeyIdentifier = null;
        $this->currentCert = $spkac;
        $this->publicKey = null;
        $this->publicKey = $this->getPublicKey();
        return $spkac;
    }
    /**
     * Save a SPKAC CSR request
     *
     * @param array $spkac
     * @param int $format optional
     * @access public
     * @return string
     */
    public function saveSPKAC($spkac, $format = self::FORMAT_PEM)
    {
        if (!is_array($spkac) || !isset($spkac['publicKeyAndChallenge'])) {
            return false;
        }
        $algorithm = $this->subArray($spkac, 'publicKeyAndChallenge/spki/algorithm/algorithm');
        switch (true) {
            case !$algorithm:
            case is_object($spkac['publicKeyAndChallenge']['spki']['subjectPublicKey']):
                break;
            default:
                $spkac['publicKeyAndChallenge']['spki'] = new Element(base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $spkac['publicKeyAndChallenge']['spki']['subjectPublicKey'])));
        }
        $spkac = ASN1::encodeDER($spkac, Maps\SignedPublicKeyAndChallenge::MAP);
        switch ($format) {
            case self::FORMAT_DER:
                return $spkac;
            // case self::FORMAT_PEM:
            default:
                // OpenSSL's implementation of SPKAC requires the SPKAC be preceded by SPKAC= and since there are pretty much
                // no other SPKAC decoders phpseclib will use that same format
                return 'SPKAC=' . Base64::encode($spkac);
        }
    }
    /**
     * Load a Certificate Revocation List
     *
     * @param string $crl
     * @param int $mode
     * @return mixed
     * @access public
     */
    public function loadCRL($crl, $mode = self::FORMAT_AUTO_DETECT)
    {
        if (is_array($crl) && isset($crl['tbsCertList'])) {
            $this->currentCert = $crl;
            unset($this->signatureSubject);
            return $crl;
        }
        if ($mode != self::FORMAT_DER) {
            $newcrl = ASN1::extractBER($crl);
            if ($mode == self::FORMAT_PEM && $crl == $newcrl) {
                return false;
            }
            $crl = $newcrl;
        }
        $orig = $crl;
        if ($crl === false) {
            $this->currentCert = false;
            return false;
        }
        $decoded = ASN1::decodeBER($crl);
        if (empty($decoded)) {
            $this->currentCert = false;
            return false;
        }
        $crl = ASN1::asn1map($decoded[0], Maps\CertificateList::MAP);
        if (!isset($crl) || $crl === false) {
            $this->currentCert = false;
            return false;
        }
        $this->signatureSubject = \Phabel\Target\Php80\Polyfill::substr($orig, $decoded[0]['content'][0]['start'], $decoded[0]['content'][0]['length']);
        $this->mapInDNs($crl, 'tbsCertList/issuer/rdnSequence');
        if ($this->isSubArrayValid($crl, 'tbsCertList/crlExtensions')) {
            $this->mapInExtensions($crl, 'tbsCertList/crlExtensions');
        }
        if ($this->isSubArrayValid($crl, 'tbsCertList/revokedCertificates')) {
            $rclist_ref =& $this->subArrayUnchecked($crl, 'tbsCertList/revokedCertificates');
            if ($rclist_ref) {
                $rclist = $crl['tbsCertList']['revokedCertificates'];
                foreach ($rclist as $i => $extension) {
                    if ($this->isSubArrayValid($rclist, "{$i}/crlEntryExtensions")) {
                        $this->mapInExtensions($rclist_ref, "{$i}/crlEntryExtensions");
                    }
                }
            }
        }
        $this->currentKeyIdentifier = null;
        $this->currentCert = $crl;
        return $crl;
    }
    /**
     * Save Certificate Revocation List.
     *
     * @param array $crl
     * @param int $format optional
     * @access public
     * @return string
     */
    public function saveCRL($crl, $format = self::FORMAT_PEM)
    {
        if (!is_array($crl) || !isset($crl['tbsCertList'])) {
            return false;
        }
        $filters = [];
        $filters['tbsCertList']['issuer']['rdnSequence']['value'] = ['type' => ASN1::TYPE_UTF8_STRING];
        $filters['tbsCertList']['signature']['parameters'] = ['type' => ASN1::TYPE_UTF8_STRING];
        $filters['signatureAlgorithm']['parameters'] = ['type' => ASN1::TYPE_UTF8_STRING];
        if (empty($crl['tbsCertList']['signature']['parameters'])) {
            $filters['tbsCertList']['signature']['parameters'] = ['type' => ASN1::TYPE_NULL];
        }
        if (empty($crl['signatureAlgorithm']['parameters'])) {
            $filters['signatureAlgorithm']['parameters'] = ['type' => ASN1::TYPE_NULL];
        }
        ASN1::setFilters($filters);
        $this->mapOutDNs($crl, 'tbsCertList/issuer/rdnSequence');
        $this->mapOutExtensions($crl, 'tbsCertList/crlExtensions');
        $rclist =& $this->subArray($crl, 'tbsCertList/revokedCertificates');
        if (is_array($rclist)) {
            foreach ($rclist as $i => $extension) {
                $this->mapOutExtensions($rclist, "{$i}/crlEntryExtensions");
            }
        }
        $crl = ASN1::encodeDER($crl, Maps\CertificateList::MAP);
        switch ($format) {
            case self::FORMAT_DER:
                return $crl;
            // case self::FORMAT_PEM:
            default:
                return "-----BEGIN X509 CRL-----\r\n" . chunk_split(Base64::encode($crl), 64) . '-----END X509 CRL-----';
        }
    }
    /**
    * Helper function to build a time field according to RFC 3280 section
    - 4.1.2.5 Validity
    - 5.1.2.4 This Update
    - 5.1.2.5 Next Update
    - 5.1.2.6 Revoked Certificates
    by choosing utcTime iff year of date given is before 2050 and generalTime else.
    *
    * @param string $date in format date('D, d M Y H:i:s O')
    * @access private
    * @return (array | Element)
    */
    private function timeField($date)
    {
        if ($date instanceof Element) {
            return $date;
        }
        $dateObj = new DateTimeImmutable($date, new DateTimeZone('GMT'));
        $year = $dateObj->format('Y');
        // the same way ASN1.php parses this
        if ($year < 2050) {
            return ['utcTime' => $date];
        } else {
            return ['generalTime' => $date];
        }
    }
    /**
    * Sign an X.509 certificate
    *
    * $issuer's private key needs to be loaded.
    $subject can be either an existing X.509 cert (if you want to resign it),
    a CSR or something with the DN and public key explicitly set.
    *
    * @param \phpseclib3\File\X509 $issuer
    * @param \phpseclib3\File\X509 $subject
    * @access public
    * @return mixed
    */
    public function sign($issuer, $subject)
    {
        if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
            return false;
        }
        if (isset($subject->publicKey) && !($subjectPublicKey = $subject->formatSubjectPublicKey())) {
            return false;
        }
        $currentCert = isset($this->currentCert) ? $this->currentCert : null;
        $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
        $signatureAlgorithm = self::identifySignatureAlgorithm($issuer->privateKey);
        if ($signatureAlgorithm != 'id-RSASSA-PSS') {
            $signatureAlgorithm = ['algorithm' => $signatureAlgorithm];
        } else {
            $r = PSS::load($issuer->privateKey->withPassword()->toString('PSS'));
            $signatureAlgorithm = ['algorithm' => 'id-RSASSA-PSS', 'parameters' => PSS::savePSSParams($r)];
        }
        if (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertificate'])) {
            $this->currentCert = $subject->currentCert;
            $this->currentCert['tbsCertificate']['signature'] = $signatureAlgorithm;
            $this->currentCert['signatureAlgorithm'] = $signatureAlgorithm;
            if (!empty($this->startDate)) {
                $this->currentCert['tbsCertificate']['validity']['notBefore'] = $this->timeField($this->startDate);
            }
            if (!empty($this->endDate)) {
                $this->currentCert['tbsCertificate']['validity']['notAfter'] = $this->timeField($this->endDate);
            }
            if (!empty($this->serialNumber)) {
                $this->currentCert['tbsCertificate']['serialNumber'] = $this->serialNumber;
            }
            if (!empty($subject->dn)) {
                $this->currentCert['tbsCertificate']['subject'] = $subject->dn;
            }
            if (!empty($subject->publicKey)) {
                $this->currentCert['tbsCertificate']['subjectPublicKeyInfo'] = $subjectPublicKey;
            }
            $this->removeExtension('id-ce-authorityKeyIdentifier');
            if (isset($subject->domains)) {
                $this->removeExtension('id-ce-subjectAltName');
            }
        } elseif (isset($subject->currentCert) && is_array($subject->currentCert) && isset($subject->currentCert['tbsCertList'])) {
            return false;
        } else {
            if (!isset($subject->publicKey)) {
                return false;
            }
            $startDate = new DateTimeImmutable('now', new DateTimeZone(@date_default_timezone_get()));
            $startDate = !empty($this->startDate) ? $this->startDate : $startDate->format('D, d M Y H:i:s O');
            $endDate = new DateTimeImmutable('+1 year', new DateTimeZone(@date_default_timezone_get()));
            $endDate = !empty($this->endDate) ? $this->endDate : $endDate->format('D, d M Y H:i:s O');
            /* "The serial number MUST be a positive integer"
                           "Conforming CAs MUST NOT use serialNumber values longer than 20 octets."
                            -- https://tools.ietf.org/html/rfc5280#section-4.1.2.2
            
                           for the integer to be positive the leading bit needs to be 0 hence the
                           application of a bitmap
                        */
            $serialNumber = !empty($this->serialNumber) ? $this->serialNumber : new BigInteger(Random::string(20) & "" . str_repeat("\xff", 19), 256);
            $this->currentCert = ['tbsCertificate' => [
                'version' => 'v3',
                'serialNumber' => $serialNumber,
                // $this->setSerialNumber()
                'signature' => $signatureAlgorithm,
                'issuer' => false,
                // this is going to be overwritten later
                'validity' => [
                    'notBefore' => $this->timeField($startDate),
                    // $this->setStartDate()
                    'notAfter' => $this->timeField($endDate),
                ],
                'subject' => $subject->dn,
                'subjectPublicKeyInfo' => $subjectPublicKey,
            ], 'signatureAlgorithm' => $signatureAlgorithm, 'signature' => false];
            // Copy extensions from CSR.
            $csrexts = $subject->getAttribute('pkcs-9-at-extensionRequest', 0);
            if (!empty($csrexts)) {
                $this->currentCert['tbsCertificate']['extensions'] = $csrexts;
            }
        }
        $this->currentCert['tbsCertificate']['issuer'] = $issuer->dn;
        if (isset($issuer->currentKeyIdentifier)) {
            $this->setExtension('id-ce-authorityKeyIdentifier', [
                //'authorityCertIssuer' => array(
                //    array(
                //        'directoryName' => $issuer->dn
                //    )
                //),
                'keyIdentifier' => $issuer->currentKeyIdentifier,
            ]);
            //$extensions = &$this->currentCert['tbsCertificate']['extensions'];
            //if (isset($issuer->serialNumber)) {
            //    $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
            //}
            //unset($extensions);
        }
        if (isset($subject->currentKeyIdentifier)) {
            $this->setExtension('id-ce-subjectKeyIdentifier', $subject->currentKeyIdentifier);
        }
        $altName = [];
        if (isset($subject->domains) && count($subject->domains)) {
            $altName = array_map(['\\phpseclib3\\File\\X509', 'dnsName'], $subject->domains);
        }
        if (isset($subject->ipAddresses) && count($subject->ipAddresses)) {
            // should an IP address appear as the CN if no domain name is specified? idk
            //$ips = count($subject->domains) ? $subject->ipAddresses : array_slice($subject->ipAddresses, 1);
            $ipAddresses = [];
            foreach ($subject->ipAddresses as $ipAddress) {
                $encoded = $subject->ipAddress($ipAddress);
                if ($encoded !== false) {
                    $ipAddresses[] = $encoded;
                }
            }
            if (count($ipAddresses)) {
                $altName = array_merge($altName, $ipAddresses);
            }
        }
        if (!empty($altName)) {
            $this->setExtension('id-ce-subjectAltName', $altName);
        }
        if ($this->caFlag) {
            $keyUsage = $this->getExtension('id-ce-keyUsage');
            if (!$keyUsage) {
                $keyUsage = [];
            }
            $this->setExtension('id-ce-keyUsage', array_values(array_unique(array_merge($keyUsage, ['cRLSign', 'keyCertSign']))));
            $basicConstraints = $this->getExtension('id-ce-basicConstraints');
            if (!$basicConstraints) {
                $basicConstraints = [];
            }
            $this->setExtension('id-ce-basicConstraints', array_merge(['cA' => true], $basicConstraints), true);
            if (!isset($subject->currentKeyIdentifier)) {
                $this->setExtension('id-ce-subjectKeyIdentifier', $this->computeKeyIdentifier($this->currentCert), false, false);
            }
        }
        // resync $this->signatureSubject
        // save $tbsCertificate in case there are any \phpseclib3\File\ASN1\Element objects in it
        $tbsCertificate = $this->currentCert['tbsCertificate'];
        $this->loadX509($this->saveX509($this->currentCert));
        $result = $this->currentCert;
        $this->currentCert['signature'] = $result['signature'] = "\x00" . $issuer->privateKey->sign($this->signatureSubject);
        $result['tbsCertificate'] = $tbsCertificate;
        $this->currentCert = $currentCert;
        $this->signatureSubject = $signatureSubject;
        return $result;
    }
    /**
     * Sign a CSR
     *
     * @access public
     * @return mixed
     */
    public function signCSR()
    {
        if (!is_object($this->privateKey) || empty($this->dn)) {
            return false;
        }
        $origPublicKey = $this->publicKey;
        $this->publicKey = $this->privateKey->getPublicKey();
        $publicKey = $this->formatSubjectPublicKey();
        $this->publicKey = $origPublicKey;
        $currentCert = isset($this->currentCert) ? $this->currentCert : null;
        $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
        $signatureAlgorithm = self::identifySignatureAlgorithm($this->privateKey);
        if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['certificationRequestInfo'])) {
            $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
            if (!empty($this->dn)) {
                $this->currentCert['certificationRequestInfo']['subject'] = $this->dn;
            }
            $this->currentCert['certificationRequestInfo']['subjectPKInfo'] = $publicKey;
        } else {
            $this->currentCert = ['certificationRequestInfo' => ['version' => 'v1', 'subject' => $this->dn, 'subjectPKInfo' => $publicKey], 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], 'signature' => false];
        }
        // resync $this->signatureSubject
        // save $certificationRequestInfo in case there are any \phpseclib3\File\ASN1\Element objects in it
        $certificationRequestInfo = $this->currentCert['certificationRequestInfo'];
        $this->loadCSR($this->saveCSR($this->currentCert));
        $result = $this->currentCert;
        $this->currentCert['signature'] = $result['signature'] = "\x00" . $this->privateKey->sign($this->signatureSubject);
        $result['certificationRequestInfo'] = $certificationRequestInfo;
        $this->currentCert = $currentCert;
        $this->signatureSubject = $signatureSubject;
        return $result;
    }
    /**
     * Sign a SPKAC
     *
     * @access public
     * @return mixed
     */
    public function signSPKAC()
    {
        if (!is_object($this->privateKey)) {
            return false;
        }
        $origPublicKey = $this->publicKey;
        $this->publicKey = $this->privateKey->getPublicKey();
        $publicKey = $this->formatSubjectPublicKey();
        $this->publicKey = $origPublicKey;
        $currentCert = isset($this->currentCert) ? $this->currentCert : null;
        $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
        $signatureAlgorithm = self::identifySignatureAlgorithm($this->privateKey);
        // re-signing a SPKAC seems silly but since everything else supports re-signing why not?
        if (isset($this->currentCert) && is_array($this->currentCert) && isset($this->currentCert['publicKeyAndChallenge'])) {
            $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
            $this->currentCert['publicKeyAndChallenge']['spki'] = $publicKey;
            if (!empty($this->challenge)) {
                // the bitwise AND ensures that the output is a valid IA5String
                $this->currentCert['publicKeyAndChallenge']['challenge'] = $this->challenge & str_repeat("", strlen($this->challenge));
            }
        } else {
            $this->currentCert = ['publicKeyAndChallenge' => [
                'spki' => $publicKey,
                // quoting <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/keygen>,
                // "A challenge string that is submitted along with the public key. Defaults to an empty string if not specified."
                // both Firefox and OpenSSL ("openssl spkac -key private.key") behave this way
                // we could alternatively do this instead if we ignored the specs:
                // Random::string(8) & str_repeat("\x7F", 8)
                'challenge' => !empty($this->challenge) ? $this->challenge : '',
            ], 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], 'signature' => false];
        }
        // resync $this->signatureSubject
        // save $publicKeyAndChallenge in case there are any \phpseclib3\File\ASN1\Element objects in it
        $publicKeyAndChallenge = $this->currentCert['publicKeyAndChallenge'];
        $this->loadSPKAC($this->saveSPKAC($this->currentCert));
        $result = $this->currentCert;
        $this->currentCert['signature'] = $result['signature'] = "\x00" . $this->privateKey->sign($this->signatureSubject);
        $result['publicKeyAndChallenge'] = $publicKeyAndChallenge;
        $this->currentCert = $currentCert;
        $this->signatureSubject = $signatureSubject;
        return $result;
    }
    /**
     * Sign a CRL
     *
     * $issuer's private key needs to be loaded.
     *
     * @param \phpseclib3\File\X509 $issuer
     * @param \phpseclib3\File\X509 $crl
     * @access public
     * @return mixed
     */
    public function signCRL($issuer, $crl)
    {
        if (!is_object($issuer->privateKey) || empty($issuer->dn)) {
            return false;
        }
        $currentCert = isset($this->currentCert) ? $this->currentCert : null;
        $signatureSubject = isset($this->signatureSubject) ? $this->signatureSubject : null;
        $signatureAlgorithm = self::identifySignatureAlgorithm($issuer->privateKey);
        $thisUpdate = new DateTimeImmutable('now', new DateTimeZone(@date_default_timezone_get()));
        $thisUpdate = !empty($this->startDate) ? $this->startDate : $thisUpdate->format('D, d M Y H:i:s O');
        if (isset($crl->currentCert) && is_array($crl->currentCert) && isset($crl->currentCert['tbsCertList'])) {
            $this->currentCert = $crl->currentCert;
            $this->currentCert['tbsCertList']['signature']['algorithm'] = $signatureAlgorithm;
            $this->currentCert['signatureAlgorithm']['algorithm'] = $signatureAlgorithm;
        } else {
            $this->currentCert = ['tbsCertList' => [
                'version' => 'v2',
                'signature' => ['algorithm' => $signatureAlgorithm],
                'issuer' => false,
                // this is going to be overwritten later
                'thisUpdate' => $this->timeField($thisUpdate),
            ], 'signatureAlgorithm' => ['algorithm' => $signatureAlgorithm], 'signature' => false];
        }
        $tbsCertList =& $this->currentCert['tbsCertList'];
        $tbsCertList['issuer'] = $issuer->dn;
        $tbsCertList['thisUpdate'] = $this->timeField($thisUpdate);
        if (!empty($this->endDate)) {
            $tbsCertList['nextUpdate'] = $this->timeField($this->endDate);
            // $this->setEndDate()
        } else {
            unset($tbsCertList['nextUpdate']);
        }
        if (!empty($this->serialNumber)) {
            $crlNumber = $this->serialNumber;
        } else {
            $crlNumber = $this->getExtension('id-ce-cRLNumber');
            // "The CRL number is a non-critical CRL extension that conveys a
            //  monotonically increasing sequence number for a given CRL scope and
            //  CRL issuer.  This extension allows users to easily determine when a
            //  particular CRL supersedes another CRL."
            // -- https://tools.ietf.org/html/rfc5280#section-5.2.3
            $crlNumber = $crlNumber !== false ? $crlNumber->add(new BigInteger(1)) : null;
        }
        $this->removeExtension('id-ce-authorityKeyIdentifier');
        $this->removeExtension('id-ce-issuerAltName');
        // Be sure version >= v2 if some extension found.
        $version = isset($tbsCertList['version']) ? $tbsCertList['version'] : 0;
        if (!$version) {
            if (!empty($tbsCertList['crlExtensions'])) {
                $version = 1;
                // v2.
            } elseif (!empty($tbsCertList['revokedCertificates'])) {
                foreach ($tbsCertList['revokedCertificates'] as $cert) {
                    if (!empty($cert['crlEntryExtensions'])) {
                        $version = 1;
                        // v2.
                    }
                }
            }
            if ($version) {
                $tbsCertList['version'] = $version;
            }
        }
        // Store additional extensions.
        if (!empty($tbsCertList['version'])) {
            // At least v2.
            if (!empty($crlNumber)) {
                $this->setExtension('id-ce-cRLNumber', $crlNumber);
            }
            if (isset($issuer->currentKeyIdentifier)) {
                $this->setExtension('id-ce-authorityKeyIdentifier', [
                    //'authorityCertIssuer' => array(
                    //    ]
                    //        'directoryName' => $issuer->dn
                    //    ]
                    //),
                    'keyIdentifier' => $issuer->currentKeyIdentifier,
                ]);
                //$extensions = &$tbsCertList['crlExtensions'];
                //if (isset($issuer->serialNumber)) {
                //    $extensions[count($extensions) - 1]['authorityCertSerialNumber'] = $issuer->serialNumber;
                //}
                //unset($extensions);
            }
            $issuerAltName = $this->getExtension('id-ce-subjectAltName', $issuer->currentCert);
            if ($issuerAltName !== false) {
                $this->setExtension('id-ce-issuerAltName', $issuerAltName);
            }
        }
        if (empty($tbsCertList['revokedCertificates'])) {
            unset($tbsCertList['revokedCertificates']);
        }
        unset($tbsCertList);
        // resync $this->signatureSubject
        // save $tbsCertList in case there are any \phpseclib3\File\ASN1\Element objects in it
        $tbsCertList = $this->currentCert['tbsCertList'];
        $this->loadCRL($this->saveCRL($this->currentCert));
        $result = $this->currentCert;
        $this->currentCert['signature'] = $result['signature'] = "\x00" . $issuer->privateKey->sign($this->signatureSubject);
        $result['tbsCertList'] = $tbsCertList;
        $this->currentCert = $currentCert;
        $this->signatureSubject = $signatureSubject;
        return $result;
    }
    /**
     * Identify signature algorithm from key settings
     *
     * @param PrivateKey $key
     * @access private
     * @throws \phpseclib3\Exception\UnsupportedAlgorithmException if the algorithm is unsupported
     * @return string
     */
    private static function identifySignatureAlgorithm(PrivateKey $key)
    {
        if ($key instanceof RSA) {
            if ($key->getPadding() & RSA::SIGNATURE_PSS) {
                return 'id-RSASSA-PSS';
            }
            switch ($key->getHash()) {
                case 'md2':
                case 'md5':
                case 'sha1':
                case 'sha224':
                case 'sha256':
                case 'sha384':
                case 'sha512':
                    return $key->getHash() . 'WithRSAEncryption';
            }
            throw new UnsupportedAlgorithmException('The only supported hash algorithms for RSA are: md2, md5, sha1, sha224, sha256, sha384, sha512');
        }
        if ($key instanceof DSA) {
            switch ($key->getHash()) {
                case 'sha1':
                case 'sha224':
                case 'sha256':
                    return 'id-dsa-with-' . $key->getHash();
            }
            throw new UnsupportedAlgorithmException('The only supported hash algorithms for DSA are: sha1, sha224, sha256');
        }
        if ($key instanceof EC) {
            switch ($key->getCurve()) {
                case 'Ed25519':
                case 'Ed448':
                    return 'id-' . $key->getCurve();
            }
            switch ($key->getHash()) {
                case 'sha1':
                case 'sha224':
                case 'sha256':
                case 'sha384':
                case 'sha512':
                    return 'ecdsa-with-' . strtoupper($key->getHash());
            }
            throw new UnsupportedAlgorithmException('The only supported hash algorithms for EC are: sha1, sha224, sha256, sha384, sha512');
        }
        throw new UnsupportedAlgorithmException('The only supported public key classes are: RSA, DSA, EC');
    }
    /**
     * Set certificate start date
     *
     * @param (DateTimeInterface | string) $date
     * @access public
     */
    public function setStartDate($date)
    {
        if (!is_object($date) || !$date instanceof DateTimeInterface) {
            $date = new DateTimeImmutable($date, new DateTimeZone(@date_default_timezone_get()));
        }
        $this->startDate = $date->format('D, d M Y H:i:s O');
    }
    /**
     * Set certificate end date
     *
     * @param (DateTimeInterface | string) $date
     * @access public
     */
    public function setEndDate($date)
    {
        /*
          To indicate that a certificate has no well-defined expiration date,
          the notAfter SHOULD be assigned the GeneralizedTime value of
          99991231235959Z.
        
          -- http://tools.ietf.org/html/rfc5280#section-4.1.2.5
        */
        if (is_string($date) && strtolower($date) === 'lifetime') {
            $temp = '99991231235959Z';
            $temp = chr(ASN1::TYPE_GENERALIZED_TIME) . ASN1::encodeLength(strlen($temp)) . $temp;
            $this->endDate = new Element($temp);
        } else {
            if (!is_object($date) || !$date instanceof DateTimeInterface) {
                $date = new DateTimeImmutable($date, new DateTimeZone(@date_default_timezone_get()));
            }
            $this->endDate = $date->format('D, d M Y H:i:s O');
        }
    }
    /**
     * Set Serial Number
     *
     * @param string $serial
     * @param int $base optional
     * @access public
     */
    public function setSerialNumber($serial, $base = -256)
    {
        $this->serialNumber = new BigInteger($serial, $base);
    }
    /**
     * Turns the certificate into a certificate authority
     *
     * @access public
     */
    public function makeCA()
    {
        $this->caFlag = true;
    }
    /**
    * Check for validity of subarray
    *
    * This is intended for use in conjunction with _subArrayUnchecked(),
    implementing the checks included in _subArray() but without copying
    a potentially large array by passing its reference by-value to is_array().
    *
    * @param array $root
    * @param string $path
    * @return boolean
    * @access private
    */
    private function isSubArrayValid($root, $path)
    {
        if (!is_array($root)) {
            return false;
        }
        foreach (explode('/', $path) as $i) {
            if (!is_array($root)) {
                return false;
            }
            if (!isset($root[$i])) {
                return true;
            }
            $root = $root[$i];
        }
        return true;
    }
    /**
    * Get a reference to a subarray
    *
    * This variant of _subArray() does no is_array() checking,
    so $root should be checked with _isSubArrayValid() first.
    *
    * This is here for performance reasons:
    Passing a reference (i.e. $root) by-value (i.e. to is_array())
    creates a copy. If $root is an especially large array, this is expensive.
    *
    * @param array $root
    * @param string $path absolute path with / as component separator
    * @param bool $create optional
    * @access private
    * @return (array | false)
    */
    private function &subArrayUnchecked(&$root, $path, $create = false)
    {
        $false = false;
        foreach (explode('/', $path) as $i) {
            if (!isset($root[$i])) {
                if (!$create) {
                    return $false;
                }
                $root[$i] = [];
            }
            $root =& $root[$i];
        }
        return $root;
    }
    /**
     * Get a reference to a subarray
     *
     * @param array $root
     * @param string $path absolute path with / as component separator
     * @param bool $create optional
     * @access private
     * @return (array | false)
     */
    private function &subArray(&$root, $path, $create = false)
    {
        $false = false;
        if (!is_array($root)) {
            return $false;
        }
        foreach (explode('/', $path) as $i) {
            if (!is_array($root)) {
                return $false;
            }
            if (!isset($root[$i])) {
                if (!$create) {
                    return $false;
                }
                $root[$i] = [];
            }
            $root =& $root[$i];
        }
        return $root;
    }
    /**
     * Get a reference to an extension subarray
     *
     * @param array $root
     * @param string $path optional absolute path with / as component separator
     * @param bool $create optional
     * @access private
     * @return (array | false)
     */
    private function &extensions(&$root, $path = null, $create = false)
    {
        if (!isset($root)) {
            $root = $this->currentCert;
        }
        switch (true) {
            case !empty($path):
            case !is_array($root):
                break;
            case isset($root['tbsCertificate']):
                $path = 'tbsCertificate/extensions';
                break;
            case isset($root['tbsCertList']):
                $path = 'tbsCertList/crlExtensions';
                break;
            case isset($root['certificationRequestInfo']):
                $pth = 'certificationRequestInfo/attributes';
                $attributes =& $this->subArray($root, $pth, $create);
                if (is_array($attributes)) {
                    foreach ($attributes as $key => $value) {
                        if ($value['type'] == 'pkcs-9-at-extensionRequest') {
                            $path = "{$pth}/{$key}/value/0";
                            break 2;
                        }
                    }
                    if ($create) {
                        $key = count($attributes);
                        $attributes[] = ['type' => 'pkcs-9-at-extensionRequest', 'value' => []];
                        $path = "{$pth}/{$key}/value/0";
                    }
                }
                break;
        }
        $extensions =& $this->subArray($root, $path, $create);
        if (!is_array($extensions)) {
            $false = false;
            return $false;
        }
        return $extensions;
    }
    /**
     * Remove an Extension
     *
     * @param string $id
     * @param string $path optional
     * @access private
     * @return bool
     */
    private function removeExtensionHelper($id, $path = null)
    {
        $extensions =& $this->extensions($this->currentCert, $path);
        if (!is_array($extensions)) {
            return false;
        }
        $result = false;
        foreach ($extensions as $key => $value) {
            if ($value['extnId'] == $id) {
                unset($extensions[$key]);
                $result = true;
            }
        }
        $extensions = array_values($extensions);
        // fix for https://bugs.php.net/75433 affecting PHP 7.2
        if (!isset($extensions[0])) {
            $extensions = array_splice($extensions, 0, 0);
        }
        return $result;
    }
    /**
     * Get an Extension
     *
     * Returns the extension if it exists and false if not
     *
     * @param string $id
     * @param array $cert optional
     * @param string $path optional
     * @access private
     * @return mixed
     */
    private function getExtensionHelper($id, $cert = null, $path = null)
    {
        $extensions = $this->extensions($cert, $path);
        if (!is_array($extensions)) {
            return false;
        }
        foreach ($extensions as $key => $value) {
            if ($value['extnId'] == $id) {
                return $value['extnValue'];
            }
        }
        return false;
    }
    /**
     * Returns a list of all extensions in use
     *
     * @param array $cert optional
     * @param string $path optional
     * @access private
     * @return array
     */
    private function getExtensionsHelper($cert = null, $path = null)
    {
        $exts = $this->extensions($cert, $path);
        $extensions = [];
        if (is_array($exts)) {
            foreach ($exts as $extension) {
                $extensions[] = $extension['extnId'];
            }
        }
        return $extensions;
    }
    /**
     * Set an Extension
     *
     * @param string $id
     * @param mixed $value
     * @param bool $critical optional
     * @param bool $replace optional
     * @param string $path optional
     * @access private
     * @return bool
     */
    private function setExtensionHelper($id, $value, $critical = false, $replace = true, $path = null)
    {
        $extensions =& $this->extensions($this->currentCert, $path, true);
        if (!is_array($extensions)) {
            return false;
        }
        $newext = ['extnId' => $id, 'critical' => $critical, 'extnValue' => $value];
        foreach ($extensions as $key => $value) {
            if ($value['extnId'] == $id) {
                if (!$replace) {
                    return false;
                }
                $extensions[$key] = $newext;
                return true;
            }
        }
        $extensions[] = $newext;
        return true;
    }
    /**
     * Remove a certificate, CSR or CRL Extension
     *
     * @param string $id
     * @access public
     * @return bool
     */
    public function removeExtension($id)
    {
        return $this->removeExtensionHelper($id);
    }
    /**
     * Get a certificate, CSR or CRL Extension
     *
     * Returns the extension if it exists and false if not
     *
     * @param string $id
     * @param array $cert optional
     * @param string $path
     * @access public
     * @return mixed
     */
    public function getExtension($id, $cert = null, $path = null)
    {
        return $this->getExtensionHelper($id, $cert, $path);
    }
    /**
     * Returns a list of all extensions in use in certificate, CSR or CRL
     *
     * @param array $cert optional
     * @param string $path optional
     * @access public
     * @return array
     */
    public function getExtensions($cert = null, $path = null)
    {
        return $this->getExtensionsHelper($cert, $path);
    }
    /**
     * Set a certificate, CSR or CRL Extension
     *
     * @param string $id
     * @param mixed $value
     * @param bool $critical optional
     * @param bool $replace optional
     * @access public
     * @return bool
     */
    public function setExtension($id, $value, $critical = false, $replace = true)
    {
        return $this->setExtensionHelper($id, $value, $critical, $replace);
    }
    /**
     * Remove a CSR attribute.
     *
     * @param string $id
     * @param int $disposition optional
     * @access public
     * @return bool
     */
    public function removeAttribute($id, $disposition = self::ATTR_ALL)
    {
        $attributes =& $this->subArray($this->currentCert, 'certificationRequestInfo/attributes');
        if (!is_array($attributes)) {
            return false;
        }
        $result = false;
        foreach ($attributes as $key => $attribute) {
            if ($attribute['type'] == $id) {
                $n = count($attribute['value']);
                switch (true) {
                    case $disposition == self::ATTR_APPEND:
                    case $disposition == self::ATTR_REPLACE:
                        return false;
                    case $disposition >= $n:
                        $disposition -= $n;
                        break;
                    case $disposition == self::ATTR_ALL:
                    case $n == 1:
                        unset($attributes[$key]);
                        $result = true;
                        break;
                    default:
                        unset($attributes[$key]['value'][$disposition]);
                        $attributes[$key]['value'] = array_values($attributes[$key]['value']);
                        $result = true;
                        break;
                }
                if ($result && $disposition != self::ATTR_ALL) {
                    break;
                }
            }
        }
        $attributes = array_values($attributes);
        return $result;
    }
    /**
     * Get a CSR attribute
     *
     * Returns the attribute if it exists and false if not
     *
     * @param string $id
     * @param int $disposition optional
     * @param array $csr optional
     * @access public
     * @return mixed
     */
    public function getAttribute($id, $disposition = self::ATTR_ALL, $csr = null)
    {
        if (empty($csr)) {
            $csr = $this->currentCert;
        }
        $attributes = $this->subArray($csr, 'certificationRequestInfo/attributes');
        if (!is_array($attributes)) {
            return false;
        }
        foreach ($attributes as $key => $attribute) {
            if ($attribute['type'] == $id) {
                $n = count($attribute['value']);
                switch (true) {
                    case $disposition == self::ATTR_APPEND:
                    case $disposition == self::ATTR_REPLACE:
                        return false;
                    case $disposition == self::ATTR_ALL:
                        return $attribute['value'];
                    case $disposition >= $n:
                        $disposition -= $n;
                        break;
                    default:
                        return $attribute['value'][$disposition];
                }
            }
        }
        return false;
    }
    /**
     * Returns a list of all CSR attributes in use
     *
     * @param array $csr optional
     * @access public
     * @return array
     */
    public function getAttributes($csr = null)
    {
        if (empty($csr)) {
            $csr = $this->currentCert;
        }
        $attributes = $this->subArray($csr, 'certificationRequestInfo/attributes');
        $attrs = [];
        if (is_array($attributes)) {
            foreach ($attributes as $attribute) {
                $attrs[] = $attribute['type'];
            }
        }
        return $attrs;
    }
    /**
     * Set a CSR attribute
     *
     * @param string $id
     * @param mixed $value
     * @param int $disposition optional
     * @access public
     * @return bool
     */
    public function setAttribute($id, $value, $disposition = self::ATTR_ALL)
    {
        $attributes =& $this->subArray($this->currentCert, 'certificationRequestInfo/attributes', true);
        if (!is_array($attributes)) {
            return false;
        }
        switch ($disposition) {
            case self::ATTR_REPLACE:
                $disposition = self::ATTR_APPEND;
            case self::ATTR_ALL:
                $this->removeAttribute($id);
                break;
        }
        foreach ($attributes as $key => $attribute) {
            if ($attribute['type'] == $id) {
                $n = count($attribute['value']);
                switch (true) {
                    case $disposition == self::ATTR_APPEND:
                        $last = $key;
                        break;
                    case $disposition >= $n:
                        $disposition -= $n;
                        break;
                    default:
                        $attributes[$key]['value'][$disposition] = $value;
                        return true;
                }
            }
        }
        switch (true) {
            case $disposition >= 0:
                return false;
            case isset($last):
                $attributes[$last]['value'][] = $value;
                break;
            default:
                $attributes[] = ['type' => $id, 'value' => $disposition == self::ATTR_ALL ? $value : [$value]];
                break;
        }
        return true;
    }
    /**
     * Sets the subject key identifier
     *
     * This is used by the id-ce-authorityKeyIdentifier and the id-ce-subjectKeyIdentifier extensions.
     *
     * @param string $value
     * @access public
     */
    public function setKeyIdentifier($value)
    {
        if (empty($value)) {
            unset($this->currentKeyIdentifier);
        } else {
            $this->currentKeyIdentifier = $value;
        }
    }
    /**
    * Compute a public key identifier.
    *
    * Although key identifiers may be set to any unique value, this function
    computes key identifiers from public key according to the two
    recommended methods (4.2.1.2 RFC 3280).
    Highly polymorphic: try to accept all possible forms of key:
    - Key object
    - \phpseclib3\File\X509 object with public or private key defined
    - Certificate or CSR array
    - \phpseclib3\File\ASN1\Element object
    - PEM or DER string
    *
    * @param mixed $key optional
    * @param int $method optional
    * @access public
    * @return string binary key identifier
    */
    public function computeKeyIdentifier($key = null, $method = 1)
    {
        if (is_null($key)) {
            $key = $this;
        }
        switch (true) {
            case is_string($key):
                break;
            case is_array($key) && isset($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey']):
                return $this->computeKeyIdentifier($key['tbsCertificate']['subjectPublicKeyInfo']['subjectPublicKey'], $method);
            case is_array($key) && isset($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey']):
                return $this->computeKeyIdentifier($key['certificationRequestInfo']['subjectPKInfo']['subjectPublicKey'], $method);
            case !is_object($key):
                return false;
            case $key instanceof Element:
                // Assume the element is a bitstring-packed key.
                $decoded = ASN1::decodeBER($key->element);
                if (empty($decoded)) {
                    return false;
                }
                $raw = ASN1::asn1map($decoded[0], ['type' => ASN1::TYPE_BIT_STRING]);
                if (empty($raw)) {
                    return false;
                }
                // If the key is private, compute identifier from its corresponding public key.
                $key = PublicKeyLoader::load($raw);
                if ($key instanceof PrivateKey) {
                    // If private.
                    return $this->computeKeyIdentifier($key, $method);
                }
                $key = $raw;
                // Is a public key.
                break;
            case $key instanceof X509:
                if (isset($key->publicKey)) {
                    return $this->computeKeyIdentifier($key->publicKey, $method);
                }
                if (isset($key->privateKey)) {
                    return $this->computeKeyIdentifier($key->privateKey, $method);
                }
                if (isset($key->currentCert['tbsCertificate']) || isset($key->currentCert['certificationRequestInfo'])) {
                    return $this->computeKeyIdentifier($key->currentCert, $method);
                }
                return false;
            default:
                // Should be a key object (i.e.: \phpseclib3\Crypt\RSA).
                $key = $key->getPublicKey();
                break;
        }
        // If in PEM format, convert to binary.
        $key = ASN1::extractBER($key);
        // Now we have the key string: compute its sha-1 sum.
        $hash = new Hash('sha1');
        $hash = $hash->hash($key);
        if ($method == 2) {
            $hash = \Phabel\Target\Php80\Polyfill::substr($hash, -8);
            $hash[0] = chr(ord($hash[0]) & 0xf | 0x40);
        }
        return $hash;
    }
    /**
     * Format a public key as appropriate
     *
     * @access private
     * @return (array | bool)
     */
    private function formatSubjectPublicKey()
    {
        $format = $this->publicKey instanceof RSA && $this->publicKey->getPadding() & RSA::SIGNATURE_PSS ? 'PSS' : 'PKCS8';
        $publicKey = base64_decode(preg_replace('#-.+-|[\\r\\n]#', '', $this->publicKey->toString($format)));
        $decoded = ASN1::decodeBER($publicKey);
        $mapped = ASN1::asn1map($decoded[0], Maps\SubjectPublicKeyInfo::MAP);
        $mapped['subjectPublicKey'] = $this->publicKey->toString($format);
        return $mapped;
    }
    /**
     * Set the domain name's which the cert is to be valid for
     *
     * @param mixed[] ...$domains
     * @access public
     * @return array
     */
    public function setDomain(...$domains)
    {
        $this->domains = $domains;
        $this->removeDNProp('id-at-commonName');
        $this->setDNProp('id-at-commonName', $this->domains[0]);
    }
    /**
     * Set the IP Addresses's which the cert is to be valid for
     *
     * @access public
     * @param mixed[] ...$ipAddresses
     */
    public function setIPAddress(...$ipAddresses)
    {
        $this->ipAddresses = $ipAddresses;
        /*
        if (!isset($this->domains)) {
            $this->removeDNProp('id-at-commonName');
            $this->setDNProp('id-at-commonName', $this->ipAddresses[0]);
        }
        */
    }
    /**
     * Helper function to build domain array
     *
     * @access private
     * @param string $domain
     * @return array
     */
    private function dnsName($domain)
    {
        return ['dNSName' => $domain];
    }
    /**
     * Helper function to build IP Address array
     *
     * (IPv6 is not currently supported)
     *
     * @access private
     * @param string $address
     * @return array
     */
    private function iPAddress($address)
    {
        return ['iPAddress' => $address];
    }
    /**
     * Get the index of a revoked certificate.
     *
     * @param array $rclist
     * @param string $serial
     * @param bool $create optional
     * @access private
     * @return (int | false)
     */
    private function revokedCertificate(&$rclist, $serial, $create = false)
    {
        $serial = new BigInteger($serial);
        foreach ($rclist as $i => $rc) {
            if (!$serial->compare($rc['userCertificate'])) {
                return $i;
            }
        }
        if (!$create) {
            return false;
        }
        $i = count($rclist);
        $revocationDate = new DateTimeImmutable('now', new DateTimeZone(@date_default_timezone_get()));
        $rclist[] = ['userCertificate' => $serial, 'revocationDate' => $this->timeField($revocationDate->format('D, d M Y H:i:s O'))];
        return $i;
    }
    /**
     * Revoke a certificate.
     *
     * @param string $serial
     * @param string $date optional
     * @access public
     * @return bool
     */
    public function revoke($serial, $date = null)
    {
        if (isset($this->currentCert['tbsCertList'])) {
            if (is_array($rclist =& $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
                if ($this->revokedCertificate($rclist, $serial) === false) {
                    // If not yet revoked
                    if (($i = $this->revokedCertificate($rclist, $serial, true)) !== false) {
                        if (!empty($date)) {
                            $rclist[$i]['revocationDate'] = $this->timeField($date);
                        }
                        return true;
                    }
                }
            }
        }
        return false;
    }
    /**
     * Unrevoke a certificate.
     *
     * @param string $serial
     * @access public
     * @return bool
     */
    public function unrevoke($serial)
    {
        if (is_array($rclist =& $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                unset($rclist[$i]);
                $rclist = array_values($rclist);
                return true;
            }
        }
        return false;
    }
    /**
     * Get a revoked certificate.
     *
     * @param string $serial
     * @access public
     * @return mixed
     */
    public function getRevoked($serial)
    {
        if (is_array($rclist = $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                return $rclist[$i];
            }
        }
        return false;
    }
    /**
     * List revoked certificates
     *
     * @param array $crl optional
     * @access public
     * @return (array | bool)
     */
    public function listRevoked($crl = null)
    {
        if (!isset($crl)) {
            $crl = $this->currentCert;
        }
        if (!isset($crl['tbsCertList'])) {
            return false;
        }
        $result = [];
        if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) {
            foreach ($rclist as $rc) {
                $result[] = $rc['userCertificate']->toString();
            }
        }
        return $result;
    }
    /**
     * Remove a Revoked Certificate Extension
     *
     * @param string $serial
     * @param string $id
     * @access public
     * @return bool
     */
    public function removeRevokedCertificateExtension($serial, $id)
    {
        if (is_array($rclist =& $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                return $this->removeExtensionHelper($id, "tbsCertList/revokedCertificates/{$i}/crlEntryExtensions");
            }
        }
        return false;
    }
    /**
     * Get a Revoked Certificate Extension
     *
     * Returns the extension if it exists and false if not
     *
     * @param string $serial
     * @param string $id
     * @param array $crl optional
     * @access public
     * @return mixed
     */
    public function getRevokedCertificateExtension($serial, $id, $crl = null)
    {
        if (!isset($crl)) {
            $crl = $this->currentCert;
        }
        if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                return $this->getExtension($id, $crl, "tbsCertList/revokedCertificates/{$i}/crlEntryExtensions");
            }
        }
        return false;
    }
    /**
     * Returns a list of all extensions in use for a given revoked certificate
     *
     * @param string $serial
     * @param array $crl optional
     * @access public
     * @return (array | bool)
     */
    public function getRevokedCertificateExtensions($serial, $crl = null)
    {
        if (!isset($crl)) {
            $crl = $this->currentCert;
        }
        if (is_array($rclist = $this->subArray($crl, 'tbsCertList/revokedCertificates'))) {
            if (($i = $this->revokedCertificate($rclist, $serial)) !== false) {
                return $this->getExtensions($crl, "tbsCertList/revokedCertificates/{$i}/crlEntryExtensions");
            }
        }
        return false;
    }
    /**
     * Set a Revoked Certificate Extension
     *
     * @param string $serial
     * @param string $id
     * @param mixed $value
     * @param bool $critical optional
     * @param bool $replace optional
     * @access public
     * @return bool
     */
    public function setRevokedCertificateExtension($serial, $id, $value, $critical = false, $replace = true)
    {
        if (isset($this->currentCert['tbsCertList'])) {
            if (is_array($rclist =& $this->subArray($this->currentCert, 'tbsCertList/revokedCertificates', true))) {
                if (($i = $this->revokedCertificate($rclist, $serial, true)) !== false) {
                    return $this->setExtensionHelper($id, $value, $critical, $replace, "tbsCertList/revokedCertificates/{$i}/crlEntryExtensions");
                }
            }
        }
        return false;
    }
    /**
     * Register the mapping for a custom/unsupported extension.
     *
     * @param string $id
     * @param array $mapping
     */
    public static function registerExtension($id, array $mapping)
    {
        if (isset(self::$extensions[$id]) && self::$extensions[$id] !== $mapping) {
            throw new \RuntimeException('Extension ' . $id . ' has already been defined with a different mapping.');
        }
        self::$extensions[$id] = $mapping;
    }
    /**
     * Register the mapping for a custom/unsupported extension.
     *
     * @param string $id
     *
     * @return (array | null)
     */
    public static function getRegisteredExtension($id)
    {
        return isset(self::$extensions[$id]) ? self::$extensions[$id] : null;
    }
    /**
     * Register the mapping for a custom/unsupported extension.
     *
     * @param string $id
     * @param mixed $value
     * @param bool $critical
     * @param bool $replace
     */
    public function setExtensionValue($id, $value, $critical = false, $replace = false)
    {
        $this->extensionValues[$id] = compact('critical', 'replace', 'value');
    }
}<?php

/**
 * Pure-PHP ANSI Decoder
 *
 * PHP version 5
 *
 * If you call read() in \phpseclib3\Net\SSH2 you may get {@link http://en.wikipedia.org/wiki/ANSI_escape_code ANSI escape codes} back.
 * They'd look like chr(0x1B) . '[00m' or whatever (0x1B = ESC).  They tell a
 * {@link http://en.wikipedia.org/wiki/Terminal_emulator terminal emulator} how to format the characters, what
 * color to display them in, etc. \phpseclib3\File\ANSI is a {@link http://en.wikipedia.org/wiki/VT100 VT100} terminal emulator.
 *
 * @category  File
 * @package   ANSI
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2012 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\File;

/**
 * Pure-PHP ANSI Decoder
 *
 * @package ANSI
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class ANSI
{
    /**
     * Max Width
     *
     * @var int
     * @access private
     */
    private $max_x;
    /**
     * Max Height
     *
     * @var int
     * @access private
     */
    private $max_y;
    /**
     * Max History
     *
     * @var int
     * @access private
     */
    private $max_history;
    /**
     * History
     *
     * @var array
     * @access private
     */
    private $history;
    /**
     * History Attributes
     *
     * @var array
     * @access private
     */
    private $history_attrs;
    /**
     * Current Column
     *
     * @var int
     * @access private
     */
    private $x;
    /**
     * Current Row
     *
     * @var int
     * @access private
     */
    private $y;
    /**
     * Old Column
     *
     * @var int
     * @access private
     */
    private $old_x;
    /**
     * Old Row
     *
     * @var int
     * @access private
     */
    private $old_y;
    /**
     * An empty attribute cell
     *
     * @var object
     * @access private
     */
    private $base_attr_cell;
    /**
     * The current attribute cell
     *
     * @var object
     * @access private
     */
    private $attr_cell;
    /**
     * An empty attribute row
     *
     * @var array
     * @access private
     */
    private $attr_row;
    /**
     * The current screen text
     *
     * @var array
     * @access private
     */
    private $screen;
    /**
     * The current screen attributes
     *
     * @var array
     * @access private
     */
    private $attrs;
    /**
     * Current ANSI code
     *
     * @var string
     * @access private
     */
    private $ansi;
    /**
     * Tokenization
     *
     * @var array
     * @access private
     */
    private $tokenization;
    /**
     * Default Constructor.
     *
     * @return \phpseclib3\File\ANSI
     * @access public
     */
    public function __construct()
    {
        $attr_cell = new \stdClass();
        $attr_cell->bold = false;
        $attr_cell->underline = false;
        $attr_cell->blink = false;
        $attr_cell->background = 'black';
        $attr_cell->foreground = 'white';
        $attr_cell->reverse = false;
        $this->base_attr_cell = clone $attr_cell;
        $this->attr_cell = clone $attr_cell;
        $this->setHistory(200);
        $this->setDimensions(80, 24);
    }
    /**
     * Set terminal width and height
     *
     * Resets the screen as well
     *
     * @param int $x
     * @param int $y
     * @access public
     */
    public function setDimensions($x, $y)
    {
        $this->max_x = $x - 1;
        $this->max_y = $y - 1;
        $this->x = $this->y = 0;
        $this->history = $this->history_attrs = [];
        $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell);
        $this->screen = array_fill(0, $this->max_y + 1, '');
        $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row);
        $this->ansi = '';
    }
    /**
     * Set the number of lines that should be logged past the terminal height
     *
     * @param int $history
     * @access public
     */
    public function setHistory($history)
    {
        $this->max_history = $history;
    }
    /**
     * Load a string
     *
     * @param string $source
     * @access public
     */
    public function loadString($source)
    {
        $this->setDimensions($this->max_x + 1, $this->max_y + 1);
        $this->appendString($source);
    }
    /**
     * Appdend a string
     *
     * @param string $source
     * @access public
     */
    public function appendString($source)
    {
        $this->tokenization = [''];
        for ($i = 0; $i < strlen($source); $i++) {
            if (strlen($this->ansi)) {
                $this->ansi .= $source[$i];
                $chr = ord($source[$i]);
                // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements
                // single character CSI's not currently supported
                switch (true) {
                    case $this->ansi == "\x1b=":
                        $this->ansi = '';
                        continue 2;
                    case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['):
                    case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126:
                        break;
                    default:
                        continue 2;
                }
                $this->tokenization[] = $this->ansi;
                $this->tokenization[] = '';
                // http://ascii-table.com/ansi-escape-sequences-vt-100.php
                switch ($this->ansi) {
                    case "\x1b[H":
                        // Move cursor to upper left corner
                        $this->old_x = $this->x;
                        $this->old_y = $this->y;
                        $this->x = $this->y = 0;
                        break;
                    case "\x1b[J":
                        // Clear screen from cursor down
                        $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y));
                        $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, ''));
                        $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y));
                        $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row));
                        if (count($this->history) == $this->max_history) {
                            array_shift($this->history);
                            array_shift($this->history_attrs);
                        }
                    case "\x1b[K":
                        // Clear screen from cursor right
                        $this->screen[$this->y] = \Phabel\Target\Php80\Polyfill::substr($this->screen[$this->y], 0, $this->x);
                        array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - ($this->x - 1), $this->base_attr_cell));
                        break;
                    case "\x1b[2K":
                        // Clear entire line
                        $this->screen[$this->y] = str_repeat(' ', $this->x);
                        $this->attrs[$this->y] = $this->attr_row;
                        break;
                    case "\x1b[?1h":
                    // set cursor key to application
                    case "\x1b[?25h":
                    // show the cursor
                    case "\x1b(B":
                        // set united states g0 character set
                        break;
                    case "\x1bE":
                        // Move to next line
                        $this->newLine();
                        $this->x = 0;
                        break;
                    default:
                        switch (true) {
                            case preg_match('#\\x1B\\[(\\d+)B#', $this->ansi, $match):
                                // Move cursor down n lines
                                $this->old_y = $this->y;
                                $this->y += $match[1];
                                break;
                            case preg_match('#\\x1B\\[(\\d+);(\\d+)H#', $this->ansi, $match):
                                // Move cursor to screen location v,h
                                $this->old_x = $this->x;
                                $this->old_y = $this->y;
                                $this->x = $match[2] - 1;
                                $this->y = $match[1] - 1;
                                break;
                            case preg_match('#\\x1B\\[(\\d+)C#', $this->ansi, $match):
                                // Move cursor right n lines
                                $this->old_x = $this->x;
                                $this->x += $match[1];
                                break;
                            case preg_match('#\\x1B\\[(\\d+)D#', $this->ansi, $match):
                                // Move cursor left n lines
                                $this->old_x = $this->x;
                                $this->x -= $match[1];
                                if ($this->x < 0) {
                                    $this->x = 0;
                                }
                                break;
                            case preg_match('#\\x1B\\[(\\d+);(\\d+)r#', $this->ansi, $match):
                                // Set top and bottom lines of a window
                                break;
                            case preg_match('#\\x1B\\[(\\d*(?:;\\d*)*)m#', $this->ansi, $match):
                                // character attributes
                                $attr_cell =& $this->attr_cell;
                                $mods = explode(';', $match[1]);
                                foreach ($mods as $mod) {
                                    switch ($mod) {
                                        case '':
                                        case '0':
                                            // Turn off character attributes
                                            $attr_cell = clone $this->base_attr_cell;
                                            break;
                                        case '1':
                                            // Turn bold mode on
                                            $attr_cell->bold = true;
                                            break;
                                        case '4':
                                            // Turn underline mode on
                                            $attr_cell->underline = true;
                                            break;
                                        case '5':
                                            // Turn blinking mode on
                                            $attr_cell->blink = true;
                                            break;
                                        case '7':
                                            // Turn reverse video on
                                            $attr_cell->reverse = !$attr_cell->reverse;
                                            $temp = $attr_cell->background;
                                            $attr_cell->background = $attr_cell->foreground;
                                            $attr_cell->foreground = $temp;
                                            break;
                                        default:
                                            // set colors
                                            //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground;
                                            $front =& $attr_cell->{$attr_cell->reverse ? 'background' : 'foreground'};
                                            //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background;
                                            $back =& $attr_cell->{$attr_cell->reverse ? 'foreground' : 'background'};
                                            switch ($mod) {
                                                // @codingStandardsIgnoreStart
                                                case '30':
                                                    $front = 'black';
                                                    break;
                                                case '31':
                                                    $front = 'red';
                                                    break;
                                                case '32':
                                                    $front = 'green';
                                                    break;
                                                case '33':
                                                    $front = 'yellow';
                                                    break;
                                                case '34':
                                                    $front = 'blue';
                                                    break;
                                                case '35':
                                                    $front = 'magenta';
                                                    break;
                                                case '36':
                                                    $front = 'cyan';
                                                    break;
                                                case '37':
                                                    $front = 'white';
                                                    break;
                                                case '40':
                                                    $back = 'black';
                                                    break;
                                                case '41':
                                                    $back = 'red';
                                                    break;
                                                case '42':
                                                    $back = 'green';
                                                    break;
                                                case '43':
                                                    $back = 'yellow';
                                                    break;
                                                case '44':
                                                    $back = 'blue';
                                                    break;
                                                case '45':
                                                    $back = 'magenta';
                                                    break;
                                                case '46':
                                                    $back = 'cyan';
                                                    break;
                                                case '47':
                                                    $back = 'white';
                                                    break;
                                                // @codingStandardsIgnoreEnd
                                                default:
                                                    //user_error('Unsupported attribute: ' . $mod);
                                                    $this->ansi = '';
                                                    break 2;
                                            }
                                    }
                                }
                                break;
                            default:
                        }
                }
                $this->ansi = '';
                continue;
            }
            $this->tokenization[count($this->tokenization) - 1] .= $source[$i];
            switch ($source[$i]) {
                case "\r":
                    $this->x = 0;
                    break;
                case "\n":
                    $this->newLine();
                    break;
                case "\x08":
                    // backspace
                    if ($this->x) {
                        $this->x--;
                        $this->attrs[$this->y][$this->x] = clone $this->base_attr_cell;
                        $this->screen[$this->y] = \Phabel\Target\Php80\Polyfill::substr_replace($this->screen[$this->y], $source[$i], $this->x, 1);
                    }
                    break;
                case "\x0f":
                    // shift
                    break;
                case "\x1b":
                    // start ANSI escape code
                    $this->tokenization[count($this->tokenization) - 1] = \Phabel\Target\Php80\Polyfill::substr($this->tokenization[count($this->tokenization) - 1], 0, -1);
                    //if (!strlen($this->tokenization[count($this->tokenization) - 1])) {
                    //    array_pop($this->tokenization);
                    //}
                    $this->ansi .= "\x1b";
                    break;
                default:
                    $this->attrs[$this->y][$this->x] = clone $this->attr_cell;
                    if ($this->x > strlen($this->screen[$this->y])) {
                        $this->screen[$this->y] = str_repeat(' ', $this->x);
                    }
                    $this->screen[$this->y] = \Phabel\Target\Php80\Polyfill::substr_replace($this->screen[$this->y], $source[$i], $this->x, 1);
                    if ($this->x > $this->max_x) {
                        $this->x = 0;
                        $this->newLine();
                    } else {
                        $this->x++;
                    }
            }
        }
    }
    /**
     * Add a new line
     *
     * Also update the $this->screen and $this->history buffers
     *
     * @access private
     */
    private function newLine()
    {
        //if ($this->y < $this->max_y) {
        //    $this->y++;
        //}
        while ($this->y >= $this->max_y) {
            $this->history = array_merge($this->history, [array_shift($this->screen)]);
            $this->screen[] = '';
            $this->history_attrs = array_merge($this->history_attrs, [array_shift($this->attrs)]);
            $this->attrs[] = $this->attr_row;
            if (count($this->history) >= $this->max_history) {
                array_shift($this->history);
                array_shift($this->history_attrs);
            }
            $this->y--;
        }
        $this->y++;
    }
    /**
     * Returns the current coordinate without preformating
     *
     * @access private
     * @param \stdClass $last_attr
     * @param \stdClass $cur_attr
     * @param string $char
     * @return string
     */
    private function processCoordinate($last_attr, $cur_attr, $char)
    {
        $output = '';
        if ($last_attr != $cur_attr) {
            $close = $open = '';
            if ($last_attr->foreground != $cur_attr->foreground) {
                if ($cur_attr->foreground != 'white') {
                    $open .= '<span style="color: ' . $cur_attr->foreground . '">';
                }
                if ($last_attr->foreground != 'white') {
                    $close = '</span>' . $close;
                }
            }
            if ($last_attr->background != $cur_attr->background) {
                if ($cur_attr->background != 'black') {
                    $open .= '<span style="background: ' . $cur_attr->background . '">';
                }
                if ($last_attr->background != 'black') {
                    $close = '</span>' . $close;
                }
            }
            if ($last_attr->bold != $cur_attr->bold) {
                if ($cur_attr->bold) {
                    $open .= '<b>';
                } else {
                    $close = '</b>' . $close;
                }
            }
            if ($last_attr->underline != $cur_attr->underline) {
                if ($cur_attr->underline) {
                    $open .= '<u>';
                } else {
                    $close = '</u>' . $close;
                }
            }
            if ($last_attr->blink != $cur_attr->blink) {
                if ($cur_attr->blink) {
                    $open .= '<blink>';
                } else {
                    $close = '</blink>' . $close;
                }
            }
            $output .= $close . $open;
        }
        $output .= htmlspecialchars($char);
        return $output;
    }
    /**
     * Returns the current screen without preformating
     *
     * @access private
     * @return string
     */
    private function getScreenHelper()
    {
        $output = '';
        $last_attr = $this->base_attr_cell;
        for ($i = 0; $i <= $this->max_y; $i++) {
            for ($j = 0; $j <= $this->max_x; $j++) {
                $cur_attr = $this->attrs[$i][$j];
                $output .= $this->processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : '');
                $last_attr = $this->attrs[$i][$j];
            }
            $output .= "\r\n";
        }
        $output = \Phabel\Target\Php80\Polyfill::substr($output, 0, -2);
        // close any remaining open tags
        $output .= $this->processCoordinate($last_attr, $this->base_attr_cell, '');
        return rtrim($output);
    }
    /**
     * Returns the current screen
     *
     * @access public
     * @return string
     */
    public function getScreen()
    {
        return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $this->getScreenHelper() . '</pre>';
    }
    /**
     * Returns the current screen and the x previous lines
     *
     * @access public
     * @return string
     */
    public function getHistory()
    {
        $scrollback = '';
        $last_attr = $this->base_attr_cell;
        for ($i = 0; $i < count($this->history); $i++) {
            for ($j = 0; $j <= $this->max_x + 1; $j++) {
                $cur_attr = $this->history_attrs[$i][$j];
                $scrollback .= $this->processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : '');
                $last_attr = $this->history_attrs[$i][$j];
            }
            $scrollback .= "\r\n";
        }
        $base_attr_cell = $this->base_attr_cell;
        $this->base_attr_cell = $last_attr;
        $scrollback .= $this->getScreen();
        $this->base_attr_cell = $base_attr_cell;
        return '<pre width="' . ($this->max_x + 1) . '" style="color: white; background: black">' . $scrollback . '</span></pre>';
    }
}<?php

/**
 * Common String Functions
 *
 * PHP version 5
 *
 * @category  Common
 * @package   Functions\Strings
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2016 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Common\Functions;

use phpseclib3\Math\BigInteger;
use phpseclib3\Math\Common\FiniteField;
/**
 * Common String Functions
 *
 * @package Functions\Strings
 * @author  Jim Wigginton <terrafrost@php.net>
 */
abstract class Strings
{
    /**
     * String Shift
     *
     * Inspired by array_shift
     *
     * @param string $string
     * @param int $index
     * @access public
     * @return string
     */
    public static function shift(&$string, $index = 1)
    {
        $substr = \Phabel\Target\Php80\Polyfill::substr($string, 0, $index);
        $string = \Phabel\Target\Php80\Polyfill::substr($string, $index);
        return $substr;
    }
    /**
     * String Pop
     *
     * Inspired by array_pop
     *
     * @param string $string
     * @param int $index
     * @access public
     * @return string
     */
    public static function pop(&$string, $index = 1)
    {
        $substr = \Phabel\Target\Php80\Polyfill::substr($string, -$index);
        $string = \Phabel\Target\Php80\Polyfill::substr($string, 0, -$index);
        return $substr;
    }
    /**
    * Parse SSH2-style string
    *
    * Returns either an array or a boolean if $data is malformed.
    *
    * Valid characters for $format are as follows:
    *
    * C = byte
    b = boolean (true/false)
    N = uint32
    Q = uint64
    s = string
    i = mpint
    L = name-list
    *
    * uint64 is not supported.
    *
    * @param string $format
    * @param string $data
    * @return mixed
    */
    public static function unpackSSH2($format, &$data)
    {
        $format = self::formatPack($format);
        $result = [];
        for ($i = 0; $i < strlen($format); $i++) {
            switch ($format[$i]) {
                case 'C':
                case 'b':
                    if (!strlen($data)) {
                        throw new \LengthException('At least one byte needs to be present for successful C / b decodes');
                    }
                    break;
                case 'N':
                case 'i':
                case 's':
                case 'L':
                    if (strlen($data) < 4) {
                        throw new \LengthException('At least four byte needs to be present for successful N / i / s / L decodes');
                    }
                    break;
                case 'Q':
                    if (strlen($data) < 8) {
                        throw new \LengthException('At least eight byte needs to be present for successful N / i / s / L decodes');
                    }
                    break;
                default:
                    throw new \InvalidArgumentException('$format contains an invalid character');
            }
            switch ($format[$i]) {
                case 'C':
                    $result[] = ord(self::shift($data));
                    continue 2;
                case 'b':
                    $result[] = ord(self::shift($data)) != 0;
                    continue 2;
                case 'N':
                    list(, $temp) = unpack('N', self::shift($data, 4));
                    $result[] = $temp;
                    continue 2;
                case 'Q':
                    // pack() added support for Q in PHP 5.6.3 and PHP 5.6 is phpseclib 3's minimum version
                    // so in theory we could support this BUT, "64-bit format codes are not available for
                    // 32-bit versions" and phpseclib works on 32-bit installs. on 32-bit installs
                    // 64-bit floats can be used to get larger numbers then 32-bit signed ints would allow
                    // for. sure, you're not gonna get the full precision of 64-bit numbers but just because
                    // you need > 32-bit precision doesn't mean you need the full 64-bit precision
                    extract(unpack('Nupper/Nlower', self::shift($data, 8)));
                    $temp = $upper ? 4294967296 * $upper : 0;
                    $temp += $lower < 0 ? ($lower & 0x7ffffffff) + 0x80000000 : $lower;
                    // $temp = hexdec(bin2hex(self::shift($data, 8)));
                    $result[] = $temp;
                    continue 2;
            }
            list(, $length) = unpack('N', self::shift($data, 4));
            if (strlen($data) < $length) {
                throw new \LengthException("{$length} bytes needed; " . strlen($data) . ' bytes available');
            }
            $temp = self::shift($data, $length);
            switch ($format[$i]) {
                case 'i':
                    $result[] = new BigInteger($temp, -256);
                    break;
                case 's':
                    $result[] = $temp;
                    break;
                case 'L':
                    $result[] = explode(',', $temp);
            }
        }
        return $result;
    }
    /**
     * Create SSH2-style string
     *
     * @param string[] ...$elements
     * @access public
     * @return mixed
     */
    public static function packSSH2(...$elements)
    {
        $format = self::formatPack($elements[0]);
        array_shift($elements);
        if (strlen($format) != count($elements)) {
            throw new \InvalidArgumentException('There must be as many arguments as there are characters in the $format string');
        }
        $result = '';
        for ($i = 0; $i < strlen($format); $i++) {
            $element = $elements[$i];
            switch ($format[$i]) {
                case 'C':
                    if (!is_int($element)) {
                        throw new \InvalidArgumentException('Bytes must be represented as an integer between 0 and 255, inclusive.');
                    }
                    $result .= pack('C', $element);
                    break;
                case 'b':
                    if (!is_bool($element)) {
                        throw new \InvalidArgumentException('A boolean parameter was expected.');
                    }
                    $result .= $element ? "\x01" : "\x00";
                    break;
                case 'Q':
                    if (!is_int($element) && !is_float($element)) {
                        throw new \InvalidArgumentException('An integer was expected.');
                    }
                    // 4294967296 == 1 << 32
                    $result .= pack('NN', $element / 4294967296, $element);
                    break;
                case 'N':
                    if (is_float($element)) {
                        $element = (int) $element;
                    }
                    if (!is_int($element)) {
                        throw new \InvalidArgumentException('An integer was expected.');
                    }
                    $result .= pack('N', $element);
                    break;
                case 's':
                    if (!self::is_stringable($element)) {
                        throw new \InvalidArgumentException('A string was expected.');
                    }
                    $result .= pack('Na*', strlen($element), $element);
                    break;
                case 'i':
                    if (!$element instanceof BigInteger && !$element instanceof FiniteField\Integer) {
                        throw new \InvalidArgumentException('A phpseclib3\\Math\\BigInteger or phpseclib3\\Math\\Common\\FiniteField\\Integer object was expected.');
                    }
                    $element = $element->toBytes(true);
                    $result .= pack('Na*', strlen($element), $element);
                    break;
                case 'L':
                    if (!is_array($element)) {
                        throw new \InvalidArgumentException('An array was expected.');
                    }
                    $element = implode(',', $element);
                    $result .= pack('Na*', strlen($element), $element);
                    break;
                default:
                    throw new \InvalidArgumentException('$format contains an invalid character');
            }
        }
        return $result;
    }
    /**
     * Expand a pack string
     *
     * Converts C5 to CCCCC, for example.
     *
     * @access private
     * @param string $format
     * @return string
     */
    private static function formatPack($format)
    {
        $parts = preg_split('#(\\d+)#', $format, -1, PREG_SPLIT_DELIM_CAPTURE);
        $format = '';
        for ($i = 1; $i < count($parts); $i += 2) {
            $format .= \Phabel\Target\Php80\Polyfill::substr($parts[$i - 1], 0, -1) . str_repeat(\Phabel\Target\Php80\Polyfill::substr($parts[$i - 1], -1), $parts[$i]);
        }
        $format .= $parts[$i - 1];
        return $format;
    }
    /**
    * Convert binary data into bits
    *
    * bin2hex / hex2bin refer to base-256 encoded data as binary, whilst
    decbin / bindec refer to base-2 encoded data as binary. For the purposes
    of this function, bin refers to base-256 encoded data whilst bits refers
    to base-2 encoded data
    *
    * @access public
    * @param string $x
    * @return string
    */
    public static function bits2bin($x)
    {
        /*
        // the pure-PHP approach is faster than the GMP approach
        if (function_exists('gmp_export')) {
             return strlen($x) ? gmp_export(gmp_init($x, 2)) : gmp_init(0);
        }
        */
        if (preg_match('#[^01]#', $x)) {
            throw new \RuntimeException('The only valid characters are 0 and 1');
        }
        if (!defined('PHP_INT_MIN')) {
            define('PHP_INT_MIN', ~PHP_INT_MAX);
        }
        $length = strlen($x);
        if (!$length) {
            return '';
        }
        $block_size = PHP_INT_SIZE << 3;
        $pad = $block_size - $length % $block_size;
        if ($pad != $block_size) {
            $x = str_repeat('0', $pad) . $x;
        }
        $parts = str_split($x, $block_size);
        $str = '';
        foreach ($parts as $part) {
            $xor = $part[0] == '1' ? PHP_INT_MIN : 0;
            $part[0] = '0';
            $str .= pack(PHP_INT_SIZE == 4 ? 'N' : 'J', $xor ^ eval('return 0b' . $part . ';'));
        }
        return ltrim($str, "\x00");
    }
    /**
     * Convert bits to binary data
     *
     * @access public
     * @param string $x
     * @return string
     */
    public static function bin2bits($x)
    {
        /*
        // the pure-PHP approach is slower than the GMP approach BUT
        // i want to the pure-PHP version to be easily unit tested as well
        if (function_exists('gmp_import')) {
            return gmp_strval(gmp_import($x), 2);
        }
        */
        $len = strlen($x);
        $mod = $len % PHP_INT_SIZE;
        if ($mod) {
            $x = str_pad($x, $len + PHP_INT_SIZE - $mod, "\x00", STR_PAD_LEFT);
        }
        $bits = '';
        if (PHP_INT_SIZE == 4) {
            $digits = unpack('N*', $x);
            foreach ($digits as $digit) {
                $bits .= sprintf('%032b', $digit);
            }
        } else {
            $digits = unpack('J*', $x);
            foreach ($digits as $digit) {
                $bits .= sprintf('%064b', $digit);
            }
        }
        return ltrim($bits, '0');
    }
    /**
     * Switch Endianness Bit Order
     *
     * @access public
     * @param string $x
     * @return string
     */
    public static function switchEndianness($x)
    {
        $r = '';
        // from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
        for ($i = strlen($x) - 1; $i >= 0; $i--) {
            $b = ord($x[$i]);
            $p1 = $b * 0x802 & 0x22110;
            $p2 = $b * 0x8020 & 0x88440;
            $r .= chr(($p1 | $p2) * 0x10101 >> 16);
        }
        return $r;
    }
    /**
     * Increment the current string
     *
     * @param string $var
     * @return string
     * @access public
     */
    public static function increment_str(&$var)
    {
        for ($i = 4; $i <= strlen($var); $i += 4) {
            $temp = \Phabel\Target\Php80\Polyfill::substr($var, -$i, 4);
            switch ($temp) {
                case "\xff\xff\xff\xff":
                    $var = \Phabel\Target\Php80\Polyfill::substr_replace($var, "\x00\x00\x00\x00", -$i, 4);
                    break;
                case "\xff\xff\xff":
                    $var = \Phabel\Target\Php80\Polyfill::substr_replace($var, "\x80\x00\x00\x00", -$i, 4);
                    return $var;
                default:
                    $temp = unpack('Nnum', $temp);
                    $var = \Phabel\Target\Php80\Polyfill::substr_replace($var, pack('N', $temp['num'] + 1), -$i, 4);
                    return $var;
            }
        }
        $remainder = strlen($var) % 4;
        if ($remainder == 0) {
            return $var;
        }
        $temp = unpack('Nnum', str_pad(\Phabel\Target\Php80\Polyfill::substr($var, 0, $remainder), 4, "\x00", STR_PAD_LEFT));
        $temp = \Phabel\Target\Php80\Polyfill::substr(pack('N', $temp['num'] + 1), -$remainder);
        $var = \Phabel\Target\Php80\Polyfill::substr_replace($var, $temp, 0, $remainder);
        return $var;
    }
    /**
     * Find whether the type of a variable is string (or could be converted to one)
     *
     * @param (string | object) $var
     * @return boolean
     * @access public
     */
    public static function is_stringable($var)
    {
        return is_string($var) || is_object($var) && method_exists($var, '__toString');
    }
}<?php

/**
 * InconsistentSetupException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   InconsistentSetupException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * InconsistentSetupException
 *
 * @package InconsistentSetupException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class InconsistentSetupException extends \RuntimeException
{
}<?php

/**
 * UnsupportedOperationException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnsupportedOperationException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnsupportedOperationException
 *
 * @package UnsupportedOperationException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnsupportedOperationException extends \RuntimeException
{
}<?php

/**
 * BadModeException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   BadModeException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * BadModeException
 *
 * @package BadModeException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class BadModeException extends \RuntimeException
{
}<?php

/**
 * BadDecryptionException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   BadDecryptionException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * BadDecryptionException
 *
 * @package BadDecryptionException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class BadDecryptionException extends \RuntimeException
{
}<?php

/**
 * UnsupportedAlgorithmException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnsupportedAlgorithmException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnsupportedAlgorithmException
 *
 * @package UnsupportedAlgorithmException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnsupportedAlgorithmException extends \RuntimeException
{
}<?php

/**
 * NoKeyLoadedException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   NoKeyLoadedException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * NoKeyLoadedException
 *
 * @package NoKeyLoadedException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class NoKeyLoadedException extends \RuntimeException
{
}<?php

/**
 * UnsupportedCurveException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnsupportedCurveException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnsupportedCurveException
 *
 * @package UnsupportedCurveException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnsupportedCurveException extends \RuntimeException
{
}<?php

/**
 * BadConfigurationException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   BadConfigurationException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * BadConfigurationException
 *
 * @package BadConfigurationException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class BadConfigurationException extends \RuntimeException
{
}<?php

/**
 * ConnectionClosedException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   ConnectionClosedException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * ConnectionClosedException
 *
 * @package ConnectionClosedException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class ConnectionClosedException extends \RuntimeException
{
}<?php

/**
 * InsufficientSetupException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   InsufficientSetupException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * InsufficientSetupException
 *
 * @package InsufficientSetupException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class InsufficientSetupException extends \RuntimeException
{
}<?php

/**
 * UnsupportedFormatException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnsupportedFormatException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnsupportedFormatException
 *
 * @package UnsupportedFormatException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnsupportedFormatException extends \RuntimeException
{
}<?php

/**
 * UnableToConnectException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   UnableToConnectException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * UnableToConnectException
 *
 * @package UnableToConnectException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class UnableToConnectException extends \RuntimeException
{
}<?php

/**
 * NoSupportedAlgorithmsException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   NoSupportedAlgorithmsException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * NoSupportedAlgorithmsException
 *
 * @package NoSupportedAlgorithmsException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class NoSupportedAlgorithmsException extends \RuntimeException
{
}<?php

/**
 * FileNotFoundException
 *
 * PHP version 5
 *
 * @category  Exception
 * @package   FileNotFoundException
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2015 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://phpseclib.sourceforge.net
 */
namespace phpseclib3\Exception;

/**
 * FileNotFoundException
 *
 * @package FileNotFoundException
 * @author  Jim Wigginton <terrafrost@php.net>
 */
class FileNotFoundException extends \RuntimeException
{
}<?php

/**
 * Prime Finite Fields
 *
 * Utilizes the factory design pattern
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math;

use phpseclib3\Math\Common\FiniteField;
use phpseclib3\Math\PrimeField\Integer;
/**
 * Prime Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PrimeField extends FiniteField
{
    /**
     * Instance Counter
     *
     * @var int
     */
    private static $instanceCounter = 0;
    /**
     * Keeps track of current instance
     *
     * @var int
     */
    protected $instanceID;
    /**
     * Default constructor
     */
    public function __construct(BigInteger $modulo)
    {
        //if (!$modulo->isPrime()) {
        //    throw new \UnexpectedValueException('PrimeField requires a prime number be passed to the constructor');
        //}
        $this->modulo = $modulo;
        $this->instanceID = self::$instanceCounter++;
        Integer::setModulo($this->instanceID, $modulo);
        Integer::setRecurringModuloFunction($this->instanceID, $modulo->createRecurringModuloFunction());
    }
    /**
     * Use a custom defined modular reduction function
     */
    public function setReduction(callable $func)
    {
        $this->reduce = $func->bindTo($this, $this);
    }
    /**
     * Returns an instance of a dynamically generated PrimeFieldInteger class
     *
     * @return object
     */
    public function newInteger(BigInteger $num)
    {
        return new Integer($this->instanceID, $num);
    }
    /**
     * Returns an integer on the finite field between one and the prime modulo
     *
     * @return object
     */
    public function randomInteger()
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        return new Integer($this->instanceID, BigInteger::randomRange($one, Integer::getModulo($this->instanceID)));
    }
    /**
     * Returns the length of the modulo in bytes
     *
     * @return integer
     */
    public function getLengthInBytes()
    {
        return Integer::getModulo($this->instanceID)->getLengthInBytes();
    }
    /**
     * Returns the length of the modulo in bits
     *
     * @return integer
     */
    public function getLength()
    {
        return Integer::getModulo($this->instanceID)->getLength();
    }
    /**
     * Destructor
     */
    public function __destruct()
    {
        Integer::cleanupCache($this->instanceID);
    }
}<?php

/**
 * Binary Finite Fields
 *
 * In a binary finite field numbers are actually polynomial equations. If you
 * represent the number as a sequence of bits you get a sequence of 1's or 0's.
 * These 1's or 0's represent the coefficients of the x**n, where n is the
 * location of the given bit. When you add numbers over a binary finite field
 * the result should have a coefficient of 1 or 0 as well. Hence addition
 * and subtraction become the same operation as XOR.
 * eg. 1 + 1 + 1 == 3 % 2 == 1 or 0 - 1 == -1 % 2 == 1
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math\BinaryField;

use phpseclib3\Math\Common\FiniteField\Integer as Base;
use phpseclib3\Math\BigInteger;
use phpseclib3\Math\BinaryField;
use ParagonIE\ConstantTime\Hex;
/**
 * Binary Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Integer extends Base
{
    /**
     * Holds the BinaryField's value
     *
     * @var string
     */
    protected $value;
    /**
     * Keeps track of current instance
     *
     * @var int
     */
    protected $instanceID;
    /**
     * Holds the PrimeField's modulo
     *
     * @var string[]
     */
    protected static $modulo;
    /**
     * Holds a pre-generated function to perform modulo reductions
     *
     * @var callable[]
     */
    protected static $reduce;
    /**
     * Default constructor
     */
    public function __construct($instanceID, $num = '')
    {
        $this->instanceID = $instanceID;
        if (!strlen($num)) {
            $this->value = '';
        } else {
            $reduce = static::$reduce[$instanceID];
            $this->value = $reduce($num);
        }
    }
    /**
     * Set the modulo for a given instance
     */
    public static function setModulo($instanceID, $modulo)
    {
        static::$modulo[$instanceID] = $modulo;
    }
    /**
     * Set the modulo for a given instance
     */
    public static function setRecurringModuloFunction($instanceID, callable $function)
    {
        static::$reduce[$instanceID] = $function;
    }
    /**
     * Tests a parameter to see if it's of the right instance
     *
     * Throws an exception if the incorrect class is being utilized
     */
    private static function checkInstance(self $x, self $y)
    {
        if ($x->instanceID != $y->instanceID) {
            throw new \UnexpectedValueException('The instances of the two BinaryField\\Integer objects do not match');
        }
    }
    /**
     * Tests the equality of two numbers.
     *
     * @return bool
     */
    public function equals(self $x)
    {
        static::checkInstance($this, $x);
        return $this->value == $x->value;
    }
    /**
     * Compares two numbers.
     *
     * @return int
     */
    public function compare(self $x)
    {
        static::checkInstance($this, $x);
        $a = $this->value;
        $b = $x->value;
        $length = max(strlen($a), strlen($b));
        $a = str_pad($a, $length, "\x00", STR_PAD_LEFT);
        $b = str_pad($b, $length, "\x00", STR_PAD_LEFT);
        return strcmp($a, $b);
    }
    /**
     * Returns the degree of the polynomial
     *
     * @param string $x
     * @return int
     */
    private static function deg($x)
    {
        $x = ltrim($x, "\x00");
        $xbit = decbin(ord($x[0]));
        $xlen = $xbit == '0' ? 0 : strlen($xbit);
        $len = strlen($x);
        if (!$len) {
            return -1;
        }
        return 8 * strlen($x) - 9 + $xlen;
    }
    /**
     * Perform polynomial division
     *
     * @return string[]
     * @link https://en.wikipedia.org/wiki/Polynomial_greatest_common_divisor#Euclidean_division
     */
    private static function polynomialDivide($x, $y)
    {
        // in wikipedia's description of the algorithm, lc() is the leading coefficient. over a binary field that's
        // always going to be 1.
        $q = chr(0);
        $d = static::deg($y);
        $r = $x;
        while (($degr = static::deg($r)) >= $d) {
            $s = '1' . str_repeat('0', $degr - $d);
            $s = BinaryField::base2ToBase256($s);
            $length = max(strlen($s), strlen($q));
            $q = !isset($q) ? $s : str_pad($q, $length, "\x00", STR_PAD_LEFT) ^ str_pad($s, $length, "\x00", STR_PAD_LEFT);
            $s = static::polynomialMultiply($s, $y);
            $length = max(strlen($r), strlen($s));
            $r = str_pad($r, $length, "\x00", STR_PAD_LEFT) ^ str_pad($s, $length, "\x00", STR_PAD_LEFT);
        }
        return [ltrim($q, "\x00"), ltrim($r, "\x00")];
    }
    /**
     * Perform polynomial multiplation in the traditional way
     *
     * @return string
     * @link https://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplication
     */
    private static function regularPolynomialMultiply($x, $y)
    {
        $precomputed = [ltrim($x, "\x00")];
        $x = strrev(BinaryField::base256ToBase2($x));
        $y = strrev(BinaryField::base256ToBase2($y));
        if (strlen($x) == strlen($y)) {
            $length = strlen($x);
        } else {
            $length = max(strlen($x), strlen($y));
            $x = str_pad($x, $length, '0');
            $y = str_pad($y, $length, '0');
        }
        $result = str_repeat('0', 2 * $length - 1);
        $result = BinaryField::base2ToBase256($result);
        $size = strlen($result);
        $x = strrev($x);
        // precompute left shift 1 through 7
        for ($i = 1; $i < 8; $i++) {
            $precomputed[$i] = BinaryField::base2ToBase256($x . str_repeat('0', $i));
        }
        for ($i = 0; $i < strlen($y); $i++) {
            if ($y[$i] == '1') {
                $temp = $precomputed[$i & 7] . str_repeat("\x00", $i >> 3);
                $result ^= str_pad($temp, $size, "\x00", STR_PAD_LEFT);
            }
        }
        return $result;
    }
    /**
     * Perform polynomial multiplation
     *
     * Uses karatsuba multiplication to reduce x-bit multiplications to a series of 32-bit multiplications
     *
     * @return string
     * @link https://en.wikipedia.org/wiki/Karatsuba_algorithm
     */
    private static function polynomialMultiply($x, $y)
    {
        if (strlen($x) == strlen($y)) {
            $length = strlen($x);
        } else {
            $length = max(strlen($x), strlen($y));
            $x = str_pad($x, $length, "\x00", STR_PAD_LEFT);
            $y = str_pad($y, $length, "\x00", STR_PAD_LEFT);
        }
        switch (true) {
            case PHP_INT_SIZE == 8 && $length <= 4:
                return $length != 4 ? self::subMultiply(str_pad($x, 4, "\x00", STR_PAD_LEFT), str_pad($y, 4, "\x00", STR_PAD_LEFT)) : self::subMultiply($x, $y);
            case PHP_INT_SIZE == 4 || $length > 32:
                return self::regularPolynomialMultiply($x, $y);
        }
        $m = $length >> 1;
        $x1 = \Phabel\Target\Php80\Polyfill::substr($x, 0, -$m);
        $x0 = \Phabel\Target\Php80\Polyfill::substr($x, -$m);
        $y1 = \Phabel\Target\Php80\Polyfill::substr($y, 0, -$m);
        $y0 = \Phabel\Target\Php80\Polyfill::substr($y, -$m);
        $z2 = self::polynomialMultiply($x1, $y1);
        $z0 = self::polynomialMultiply($x0, $y0);
        $z1 = self::polynomialMultiply(self::subAdd2($x1, $x0), self::subAdd2($y1, $y0));
        $z1 = self::subAdd3($z1, $z2, $z0);
        $xy = self::subAdd3($z2 . str_repeat("\x00", 2 * $m), $z1 . str_repeat("\x00", $m), $z0);
        return ltrim($xy, "\x00");
    }
    /**
    * Perform polynomial multiplication on 2x 32-bit numbers, returning
    a 64-bit number
    *
    * @param string $x
    * @param string $y
    * @return string
    * @link https://www.bearssl.org/constanttime.html#ghash-for-gcm
    */
    private static function subMultiply($x, $y)
    {
        $x = unpack('N', $x)[1];
        $y = unpack('N', $y)[1];
        $x0 = $x & 0x11111111;
        $x1 = $x & 0x22222222;
        $x2 = $x & 0x44444444;
        $x3 = $x & 0x88888888;
        $y0 = $y & 0x11111111;
        $y1 = $y & 0x22222222;
        $y2 = $y & 0x44444444;
        $y3 = $y & 0x88888888;
        $z0 = $x0 * $y0 ^ $x1 * $y3 ^ $x2 * $y2 ^ $x3 * $y1;
        $z1 = $x0 * $y1 ^ $x1 * $y0 ^ $x2 * $y3 ^ $x3 * $y2;
        $z2 = $x0 * $y2 ^ $x1 * $y1 ^ $x2 * $y0 ^ $x3 * $y3;
        $z3 = $x0 * $y3 ^ $x1 * $y2 ^ $x2 * $y1 ^ $x3 * $y0;
        $z0 &= 0x1111111111111111;
        $z1 &= 0x2222222222222222;
        $z2 &= 0x4444444444444444;
        $z3 &= -8608480567731124088;
        // 0x8888888888888888 gets interpreted as a float
        $z = $z0 | $z1 | $z2 | $z3;
        return pack('J', $z);
    }
    /**
     * Adds two numbers
     *
     * @param string $x
     * @param string $y
     * @return string
     */
    private static function subAdd2($x, $y)
    {
        $length = max(strlen($x), strlen($y));
        $x = str_pad($x, $length, "\x00", STR_PAD_LEFT);
        $y = str_pad($y, $length, "\x00", STR_PAD_LEFT);
        return $x ^ $y;
    }
    /**
     * Adds three numbers
     *
     * @param string $x
     * @param string $y
     * @return string
     */
    private static function subAdd3($x, $y, $z)
    {
        $length = max(strlen($x), strlen($y), strlen($z));
        $x = str_pad($x, $length, "\x00", STR_PAD_LEFT);
        $y = str_pad($y, $length, "\x00", STR_PAD_LEFT);
        $z = str_pad($z, $length, "\x00", STR_PAD_LEFT);
        return $x ^ $y ^ $z;
    }
    /**
     * Adds two BinaryFieldIntegers.
     *
     * @return static
     */
    public function add(self $y)
    {
        static::checkInstance($this, $y);
        $length = strlen(static::$modulo[$this->instanceID]);
        $x = str_pad($this->value, $length, "\x00", STR_PAD_LEFT);
        $y = str_pad($y->value, $length, "\x00", STR_PAD_LEFT);
        return new static($this->instanceID, $x ^ $y);
    }
    /**
     * Subtracts two BinaryFieldIntegers.
     *
     * @return static
     */
    public function subtract(self $x)
    {
        return $this->add($x);
    }
    /**
     * Multiplies two BinaryFieldIntegers.
     *
     * @return static
     */
    public function multiply(self $y)
    {
        static::checkInstance($this, $y);
        return new static($this->instanceID, static::polynomialMultiply($this->value, $y->value));
    }
    /**
     * Returns the modular inverse of a BinaryFieldInteger
     *
     * @return static
     */
    public function modInverse()
    {
        $remainder0 = static::$modulo[$this->instanceID];
        $remainder1 = $this->value;
        if ($remainder1 == '') {
            return new static($this->instanceID);
        }
        $aux0 = "\x00";
        $aux1 = "\x01";
        while ($remainder1 != "\x01") {
            list($q, $r) = static::polynomialDivide($remainder0, $remainder1);
            $remainder0 = $remainder1;
            $remainder1 = $r;
            // the auxiliary in row n is given by the sum of the auxiliary in
            // row n-2 and the product of the quotient and the auxiliary in row
            // n-1
            $temp = static::polynomialMultiply($aux1, $q);
            $aux = str_pad($aux0, strlen($temp), "\x00", STR_PAD_LEFT) ^ str_pad($temp, strlen($aux0), "\x00", STR_PAD_LEFT);
            $aux0 = $aux1;
            $aux1 = $aux;
        }
        $temp = new static($this->instanceID);
        $temp->value = ltrim($aux1, "\x00");
        return $temp;
    }
    /**
     * Divides two PrimeFieldIntegers.
     *
     * @return static
     */
    public function divide(self $x)
    {
        static::checkInstance($this, $x);
        $x = $x->modInverse();
        return $this->multiply($x);
    }
    /**
    * Negate
    *
    * A negative number can be written as 0-12. With modulos, 0 is the same thing as the modulo
    so 0-12 is the same thing as modulo-12
    *
    * @return object
    */
    public function negate()
    {
        $x = str_pad($this->value, strlen(static::$modulo[$this->instanceID]), "\x00", STR_PAD_LEFT);
        return new static($this->instanceID, $x ^ static::$modulo[$this->instanceID]);
    }
    /**
     * Returns the modulo
     *
     * @return integer
     */
    public static function getModulo($instanceID)
    {
        return static::$modulo[$instanceID];
    }
    /**
     * Converts an Integer to a byte string (eg. base-256).
     *
     * @return string
     */
    public function toBytes()
    {
        return str_pad($this->value, strlen(static::$modulo[$this->instanceID]), "\x00", STR_PAD_LEFT);
    }
    /**
     * Converts an Integer to a hex string (eg. base-16).
     *
     * @return string
     */
    public function toHex()
    {
        return Hex::encode($this->toBytes());
    }
    /**
     * Converts an Integer to a bit string (eg. base-2).
     *
     * @return string
     */
    public function toBits()
    {
        //return str_pad(BinaryField::base256ToBase2($this->value), strlen(static::$modulo[$this->instanceID]), '0', STR_PAD_LEFT);
        return BinaryField::base256ToBase2($this->value);
    }
    /**
     * Converts an Integer to a BigInteger
     *
     * @return string
     */
    public function toBigInteger()
    {
        return new BigInteger($this->value, 256);
    }
    /**
     * __toString() magic method
     *
     * @access public
     */
    public function __toString()
    {
        return (string) $this->toBigInteger();
    }
    /**
     * __debugInfo() magic method
     *
     * @access public
     */
    public function __debugInfo()
    {
        return ['value' => $this->toHex()];
    }
}<?php

/**
 * Prime Finite Fields
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math\PrimeField;

use phpseclib3\Math\Common\FiniteField\Integer as Base;
use phpseclib3\Math\BigInteger;
use ParagonIE\ConstantTime\Hex;
/**
 * Prime Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class Integer extends Base
{
    /**
     * Holds the PrimeField's value
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected $value;
    /**
     * Keeps track of current instance
     *
     * @var int
     */
    protected $instanceID;
    /**
     * Holds the PrimeField's modulo
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected static $modulo;
    /**
     * Holds a pre-generated function to perform modulo reductions
     *
     * @var Callable
     */
    protected static $reduce;
    /**
     * Zero
     *
     * @var \phpseclib3\Math\BigInteger
     */
    protected static $zero;
    /**
     * Default constructor
     */
    public function __construct($instanceID, BigInteger $num = null)
    {
        $this->instanceID = $instanceID;
        if (!isset($num)) {
            $this->value = clone static::$zero;
        } else {
            $reduce = static::$reduce[$instanceID];
            $this->value = $reduce($num);
        }
    }
    /**
     * Set the modulo for a given instance
     */
    public static function setModulo($instanceID, BigInteger $modulo)
    {
        static::$modulo[$instanceID] = $modulo;
    }
    /**
     * Set the modulo for a given instance
     */
    public static function setRecurringModuloFunction($instanceID, callable $function)
    {
        static::$reduce[$instanceID] = $function;
        if (!isset(static::$zero)) {
            static::$zero = new BigInteger();
        }
    }
    /**
     * Delete the modulo for a given instance
     */
    public static function cleanupCache($instanceID)
    {
        unset(static::$modulo[$instanceID]);
        unset(static::$reduce[$instanceID]);
    }
    /**
     * Returns the modulo
     *
     * @return integer
     */
    public static function getModulo($instanceID)
    {
        return static::$modulo[$instanceID];
    }
    /**
     * Tests a parameter to see if it's of the right instance
     *
     * Throws an exception if the incorrect class is being utilized
     */
    public static function checkInstance(self $x, self $y)
    {
        if ($x->instanceID != $y->instanceID) {
            throw new \UnexpectedValueException('The instances of the two PrimeField\\Integer objects do not match');
        }
    }
    /**
     * Tests the equality of two numbers.
     *
     * @return bool
     */
    public function equals(self $x)
    {
        static::checkInstance($this, $x);
        return $this->value->equals($x->value);
    }
    /**
     * Compares two numbers.
     *
     * @return int
     */
    public function compare(self $x)
    {
        static::checkInstance($this, $x);
        return $this->value->compare($x->value);
    }
    /**
     * Adds two PrimeFieldIntegers.
     *
     * @return static
     */
    public function add(self $x)
    {
        static::checkInstance($this, $x);
        $temp = new static($this->instanceID);
        $temp->value = $this->value->add($x->value);
        if ($temp->value->compare(static::$modulo[$this->instanceID]) >= 0) {
            $temp->value = $temp->value->subtract(static::$modulo[$this->instanceID]);
        }
        return $temp;
    }
    /**
     * Subtracts two PrimeFieldIntegers.
     *
     * @return static
     */
    public function subtract(self $x)
    {
        static::checkInstance($this, $x);
        $temp = new static($this->instanceID);
        $temp->value = $this->value->subtract($x->value);
        if ($temp->value->isNegative()) {
            $temp->value = $temp->value->add(static::$modulo[$this->instanceID]);
        }
        return $temp;
    }
    /**
     * Multiplies two PrimeFieldIntegers.
     *
     * @return static
     */
    public function multiply(self $x)
    {
        static::checkInstance($this, $x);
        return new static($this->instanceID, $this->value->multiply($x->value));
    }
    /**
     * Divides two PrimeFieldIntegers.
     *
     * @return static
     */
    public function divide(self $x)
    {
        static::checkInstance($this, $x);
        $denominator = $x->value->modInverse(static::$modulo[$this->instanceID]);
        return new static($this->instanceID, $this->value->multiply($denominator));
    }
    /**
     * Performs power operation on a PrimeFieldInteger.
     *
     * @return static
     */
    public function pow(BigInteger $x)
    {
        $temp = new static($this->instanceID);
        $temp->value = $this->value->powMod($x, static::$modulo[$this->instanceID]);
        return $temp;
    }
    /**
     * Calculates the square root
     *
     * @link https://en.wikipedia.org/wiki/Tonelli%E2%80%93Shanks_algorithm
     * @return (static | false)
     */
    public function squareRoot()
    {
        static $one, $two;
        if (!isset($one)) {
            $one = new BigInteger(1);
            $two = new BigInteger(2);
        }
        $reduce = static::$reduce[$this->instanceID];
        $p_1 = static::$modulo[$this->instanceID]->subtract($one);
        $q = clone $p_1;
        $s = BigInteger::scan1divide($q);
        list($pow) = $p_1->divide($two);
        for ($z = $one; !$z->equals(static::$modulo[$this->instanceID]); $z = $z->add($one)) {
            $temp = $z->powMod($pow, static::$modulo[$this->instanceID]);
            if ($temp->equals($p_1)) {
                break;
            }
        }
        $m = new BigInteger($s);
        $c = $z->powMod($q, static::$modulo[$this->instanceID]);
        $t = $this->value->powMod($q, static::$modulo[$this->instanceID]);
        list($temp) = $q->add($one)->divide($two);
        $r = $this->value->powMod($temp, static::$modulo[$this->instanceID]);
        while (!$t->equals($one)) {
            $i = clone $one;
            while (!$t->powMod($two->pow($i), static::$modulo[$this->instanceID])->equals($one)) {
                $i = $i->add($one);
            }
            if ($i->compare($m) >= 0) {
                return false;
            }
            $b = $c->powMod($two->pow($m->subtract($i)->subtract($one)), static::$modulo[$this->instanceID]);
            $m = $i;
            $c = $reduce($b->multiply($b));
            $t = $reduce($t->multiply($c));
            $r = $reduce($r->multiply($b));
        }
        return new static($this->instanceID, $r);
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return $this->value->isOdd();
    }
    /**
    * Negate
    *
    * A negative number can be written as 0-12. With modulos, 0 is the same thing as the modulo
    so 0-12 is the same thing as modulo-12
    *
    * @return object
    */
    public function negate()
    {
        return new static($this->instanceID, static::$modulo[$this->instanceID]->subtract($this->value));
    }
    /**
     * Converts an Integer to a byte string (eg. base-256).
     *
     * @return string
     */
    public function toBytes()
    {
        $length = static::$modulo[$this->instanceID]->getLengthInBytes();
        return str_pad($this->value->toBytes(), $length, "\x00", STR_PAD_LEFT);
    }
    /**
     * Converts an Integer to a hex string (eg. base-16).
     *
     * @return string
     */
    public function toHex()
    {
        return Hex::encode($this->toBytes());
    }
    /**
     * Converts an Integer to a bit string (eg. base-2).
     *
     * @return string
     */
    public function toBits()
    {
        // return $this->value->toBits();
        static $length;
        if (!isset($length)) {
            $length = static::$modulo[$this->instanceID]->getLength();
        }
        return str_pad($this->value->toBits(), $length, '0', STR_PAD_LEFT);
    }
    /**
     * Returns the w-ary non-adjacent form (wNAF)
     *
     * @param int $w optional
     * @return int[]
     */
    public function getNAF($w = 1)
    {
        $w++;
        $mask = new BigInteger((1 << $w) - 1);
        $sub = new BigInteger(1 << $w);
        //$sub = new BigInteger(1 << ($w - 1));
        $d = $this->toBigInteger();
        $d_i = [];
        $i = 0;
        while ($d->compare(static::$zero) > 0) {
            if ($d->isOdd()) {
                // start mods
                $d_i[$i] = $d->testBit($w - 1) ? $d->bitwise_and($mask)->subtract($sub) : $d->bitwise_and($mask);
                // end mods
                $d = $d->subtract($d_i[$i]);
                $d_i[$i] = (int) $d_i[$i]->toString();
            } else {
                $d_i[$i] = 0;
            }
            $shift = !$d->equals(static::$zero) && $d->bitwise_and($mask)->equals(static::$zero) ? $w : 1;
            // $w or $w + 1?
            $d = $d->bitwise_rightShift($shift);
            while (--$shift > 0) {
                $d_i[++$i] = 0;
            }
            $i++;
        }
        return $d_i;
    }
    /**
     * Converts an Integer to a BigInteger
     *
     * @return string
     */
    public function toBigInteger()
    {
        return clone $this->value;
    }
    /**
     * __toString() magic method
     *
     * @access public
     */
    public function __toString()
    {
        return (string) $this->value;
    }
    /**
     * __debugInfo() magic method
     *
     * @access public
     */
    public function __debugInfo()
    {
        return ['value' => $this->toHex()];
    }
}<?php

/**
 * Binary Finite Fields
 *
 * Utilizes the factory design pattern
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Math\Common\FiniteField;
use phpseclib3\Math\BinaryField\Integer;
use phpseclib3\Common\Functions\Strings;
/**
 * Binary Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class BinaryField extends FiniteField
{
    /**
     * Instance Counter
     *
     * @var int
     */
    private static $instanceCounter = 0;
    /**
     * Keeps track of current instance
     *
     * @var int
     */
    protected $instanceID;
    /**
     * Default constructor
     */
    public function __construct(...$indices)
    {
        $m = array_shift($indices);
        $val = str_repeat('0', $m) . '1';
        foreach ($indices as $index) {
            $val[$index] = '1';
        }
        $modulo = static::base2ToBase256(strrev($val));
        $mStart = 2 * $m - 2;
        $t = ceil($m / 8);
        $finalMask = chr((1 << $m % 8) - 1);
        if ($finalMask == "\x00") {
            $finalMask = "\xff";
        }
        $bitLen = $mStart + 1;
        $pad = ceil($bitLen / 8);
        $h = $bitLen & 7;
        $h = $h ? 8 - $h : 0;
        $r = rtrim(\Phabel\Target\Php80\Polyfill::substr($val, 0, -1), '0');
        $u = [static::base2ToBase256(strrev($r))];
        for ($i = 1; $i < 8; $i++) {
            $u[] = static::base2ToBase256(strrev(str_repeat('0', $i) . $r));
        }
        // implements algorithm 2.40 (in section 2.3.5) in "Guide to Elliptic Curve Cryptography"
        // with W = 8
        $reduce = function ($c) use($u, $mStart, $m, $t, $finalMask, $pad, $h) {
            $c = str_pad($c, $pad, "\x00", STR_PAD_LEFT);
            for ($i = $mStart; $i >= $m;) {
                $g = $h >> 3;
                $mask = $h & 7;
                $mask = $mask ? 1 << 7 - $mask : 0x80;
                for (; $mask > 0; $mask >>= 1, $i--, $h++) {
                    if (ord($c[$g]) & $mask) {
                        $temp = $i - $m;
                        $j = $temp >> 3;
                        $k = $temp & 7;
                        $t1 = $j ? \Phabel\Target\Php80\Polyfill::substr($c, 0, -$j) : $c;
                        $length = strlen($t1);
                        if ($length) {
                            $t2 = str_pad($u[$k], $length, "\x00", STR_PAD_LEFT);
                            $temp = $t1 ^ $t2;
                            $c = $j ? \Phabel\Target\Php80\Polyfill::substr_replace($c, $temp, 0, $length) : $temp;
                        }
                    }
                }
            }
            $c = \Phabel\Target\Php80\Polyfill::substr($c, -$t);
            if (strlen($c) == $t) {
                $c[0] = $c[0] & $finalMask;
            }
            return ltrim($c, "\x00");
        };
        $this->instanceID = self::$instanceCounter++;
        Integer::setModulo($this->instanceID, $modulo);
        Integer::setRecurringModuloFunction($this->instanceID, $reduce);
        $this->randomMax = new BigInteger($modulo, 2);
    }
    /**
     * Returns an instance of a dynamically generated PrimeFieldInteger class
     *
     * @param string $num
     * @return object
     */
    public function newInteger($num)
    {
        return new Integer($this->instanceID, $num instanceof BigInteger ? $num->toBytes() : $num);
    }
    /**
     * Returns an integer on the finite field between one and the prime modulo
     *
     * @return object
     */
    public function randomInteger()
    {
        static $one;
        if (!isset($one)) {
            $one = new BigInteger(1);
        }
        return new Integer($this->instanceID, BigInteger::randomRange($one, $this->randomMax)->toBytes());
    }
    /**
     * Returns the length of the modulo in bytes
     *
     * @return integer
     */
    public function getLengthInBytes()
    {
        return strlen(Integer::getModulo($this->instanceID));
    }
    /**
     * Returns the length of the modulo in bits
     *
     * @return integer
     */
    public function getLength()
    {
        return strlen(Integer::getModulo($this->instanceID)) << 3;
    }
    /**
     * Converts a base-2 string to a base-256 string
     *
     * @param string $x
     * @param integer $size
     * @return string
     */
    public static function base2ToBase256($x, $size = null)
    {
        $str = Strings::bits2bin($x);
        $pad = strlen($x) >> 3;
        if (strlen($x) & 3) {
            $pad++;
        }
        $str = str_pad($str, $pad, "\x00", STR_PAD_LEFT);
        if (isset($size)) {
            $str = str_pad($str, $size, "\x00", STR_PAD_LEFT);
        }
        return $str;
    }
    /**
     * Converts a base-256 string to a base-2 string
     *
     * @param string $x
     * @return string
     */
    public static function base256ToBase2($x)
    {
        if (function_exists('gmp_import')) {
            return gmp_strval(gmp_import($x), 2);
        }
        return Strings::bin2bits($x);
    }
}<?php

/**
 * Finite Field Integer Base Class
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math\Common\FiniteField;

/**
 * Finite Field Integer
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Integer
{
}<?php

/**
 * Finite Fields Base Class
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math\Common;

/**
 * Finite Fields
 *
 * @package Math
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class FiniteField
{
}<?php

/**
 * Pure-PHP arbitrary precision integer arithmetic library.
 *
 * Supports base-2, base-10, base-16, and base-256 numbers.  Uses the GMP or BCMath extensions, if available,
 * and an internal implementation, otherwise.
 *
 * PHP version 5 and 7
 *
 * Here's an example of how to use this library:
 * <code>
 * <?php
 *    $a = new \phpseclib3\Math\BigInteger(2);
 *    $b = new \phpseclib3\Math\BigInteger(3);
 *
 *    $c = $a->add($b);
 *
 *    echo $c->toString(); // outputs 5
 * ?>
 * </code>
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 */
namespace phpseclib3\Math;

use phpseclib3\Exception\BadConfigurationException;
/**
 * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
 * numbers.
 *
 * @package BigInteger
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class BigInteger
{
    /**
     * Main Engine
     *
     * @var string
     */
    private static $mainEngine;
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    private static $modexpEngine;
    /**
     * Selected Engines
     *
     * @var array
     */
    private static $engines;
    /**
     * The actual BigInteger object
     *
     * @var object
     */
    private $value;
    /**
     * Mode independent value used for serialization.
     *
     * @see self::__sleep()
     * @see self::__wakeup()
     * @var string
     */
    private $hex;
    /**
     * Precision (used only for serialization)
     *
     * @see self::__sleep()
     * @see self::__wakeup()
     * @var int
     */
    private $precision;
    /**
     * Sets engine type.
     *
     * Throws an exception if the type is invalid
     *
     * @param string $main
     * @param array $modexps optional
     */
    public static function setEngine($main, $modexps = ['DefaultEngine'])
    {
        self::$engines = [];
        $fqmain = 'phpseclib3\\Math\\BigInteger\\Engines\\' . $main;
        if (!class_exists($fqmain) || !method_exists($fqmain, 'isValidEngine')) {
            throw new \InvalidArgumentException("{$main} is not a valid engine");
        }
        if (!$fqmain::isValidEngine()) {
            throw new BadConfigurationException("{$main} is not setup correctly on this system");
        }
        self::$mainEngine = $fqmain;
        if (!in_array('Default', $modexps)) {
            $modexps[] = 'DefaultEngine';
        }
        $found = false;
        foreach ($modexps as $modexp) {
            try {
                $fqmain::setModExpEngine($modexp);
                $found = true;
                break;
            } catch (\Exception $e) {
            }
        }
        if (!$found) {
            throw new BadConfigurationException("No valid modular exponentiation engine found for {$main}");
        }
        self::$modexpEngine = $modexp;
        self::$engines = [$main, $modexp];
    }
    /**
     * Returns the engine type
     *
     * @return string[]
     */
    public static function getEngine()
    {
        self::initialize_static_variables();
        return self::$engines;
    }
    /**
     * Initialize static variables
     */
    private static function initialize_static_variables()
    {
        if (!isset(self::$mainEngine)) {
            $engines = [['GMP'], ['PHP64', ['OpenSSL']], ['BCMath', ['OpenSSL']], ['PHP32', ['OpenSSL']]];
            foreach ($engines as $engine) {
                try {
                    self::setEngine($engine[0], isset($engine[1]) ? $engine[1] : []);
                    break;
                } catch (\Exception $e) {
                }
            }
        }
    }
    /**
    * Converts base-2, base-10, base-16, and binary strings (base-256) to BigIntegers.
    *
    * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
    two's compliment.  The sole exception to this is -10, which is treated the same as 10 is.
    *
    * @param (string | int | BigInteger\Engines\Engine) $x Base-10 number or base-$base number if $base set.
    * @param int $base
    * @return BigInteger
    */
    public function __construct($x = 0, $base = 10)
    {
        self::initialize_static_variables();
        if (\Phabel\Plugin\NewFixer::instanceOf($x, self::$mainEngine)) {
            $this->value = clone $x;
        } elseif ($x instanceof BigInteger\Engines\Engine) {
            $this->value = new static("{$x}");
            $this->value->setPrecision($x->getPrecision());
        } else {
            $this->value = ($phabel_3129085052483abc = self::$mainEngine) || true ? new $phabel_3129085052483abc($x, $base) : false;
        }
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function toString()
    {
        return $this->value->toString();
    }
    /**
     * __toString() magic method
     */
    public function __toString()
    {
        return (string) $this->value;
    }
    /**
     * __debugInfo() magic method
     *
     * Will be called, automatically, when print_r() or var_dump() are called
     */
    public function __debugInfo()
    {
        return $this->value->__debugInfo();
    }
    /**
     * Converts a BigInteger to a byte string (eg. base-256).
     *
     * @param bool $twos_compliment
     * @return string
     */
    public function toBytes($twos_compliment = false)
    {
        return $this->value->toBytes($twos_compliment);
    }
    /**
     * Converts a BigInteger to a hex string (eg. base-16).
     *
     * @param bool $twos_compliment
     * @return string
     */
    public function toHex($twos_compliment = false)
    {
        return $this->value->toHex($twos_compliment);
    }
    /**
    * Converts a BigInteger to a bit string (eg. base-2).
    *
    * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
    saved as two's compliment.
    *
    * @param bool $twos_compliment
    * @return string
    */
    function toBits($twos_compliment = false)
    {
        return $this->value->toBits($twos_compliment);
    }
    /**
     * Adds two BigIntegers.
     *
     * @param BigInteger $y
     * @return BigInteger
     */
    public function add(BigInteger $y)
    {
        return new static($this->value->add($y->value));
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param BigInteger $y
     * @return BigInteger
     */
    function subtract(BigInteger $y)
    {
        return new static($this->value->subtract($y->value));
    }
    /**
     * Multiplies two BigIntegers
     *
     * @param BigInteger $x
     * @return BigInteger
     */
    public function multiply(BigInteger $x)
    {
        return new static($this->value->multiply($x->value));
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * Here's an example:
    <code>
    <?php
    $a = new \phpseclib3\Math\BigInteger('10');
    $b = new \phpseclib3\Math\BigInteger('20');
    *
    * list($quotient, $remainder) = $a->divide($b);
    *
    * echo $quotient->toString(); // outputs 0
    echo "\r\n";
    echo $remainder->toString(); // outputs 10
    ?>
    </code>
    *
    * @param BigInteger $y
    * @return BigInteger[]
    */
    public function divide(BigInteger $y)
    {
        list($q, $r) = $this->value->divide($y->value);
        return [new static($q), new static($r)];
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @return BigInteger
     * @param BigInteger $n
     */
    public function modInverse(BigInteger $n)
    {
        return new static($this->value->modInverse($n->value));
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @return BigInteger[]
     * @param BigInteger $n
     */
    public function extendedGCD(BigInteger $n)
    {
        extract($this->value->extendedGCD($n->value));
        /**
         * @var BigInteger $gcd
         * @var BigInteger $x
         * @var BigInteger $y
         */
        return ['gcd' => new static($gcd), 'x' => new static($x), 'y' => new static($y)];
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param BigInteger $n
     * @return BigInteger
     */
    public function gcd(BigInteger $n)
    {
        return new static($this->value->gcd($n->value));
    }
    /**
     * Absolute value.
     *
     * @return BigInteger
     * @access public
     */
    public function abs()
    {
        return new static($this->value->abs());
    }
    /**
    * Set Precision
    *
    * Some bitwise operations give different results depending on the precision being used.  Examples include left
    shift, not, and rotates.
    *
    * @param int $bits
    */
    public function setPrecision($bits)
    {
        $this->value->setPrecision($bits);
    }
    /**
     * Get Precision
     *
     * Returns the precision if it exists, false if it doesn't
     *
     * @return (int | bool)
     */
    public function getPrecision()
    {
        return $this->value->getPrecision();
    }
    /**
    * Serialize
    *
    * Will be called, automatically, when serialize() is called on a BigInteger object.
    *
    * __sleep() / __wakeup() have been around since PHP 4.0
    *
    * \Serializable was introduced in PHP 5.1 and deprecated in PHP 8.1:
    https://wiki.php.net/rfc/phase_out_serializable
    *
    * __serialize() / __unserialize() were introduced in PHP 7.4:
    https://wiki.php.net/rfc/custom_object_serialization
    *
    * @return string
    */
    public function __sleep()
    {
        $this->hex = $this->toHex(true);
        $vars = ['hex'];
        if ($this->getPrecision() > 0) {
            $vars[] = 'precision';
        }
        return $vars;
    }
    /**
     * Serialize
     *
     * Will be called, automatically, when unserialize() is called on a BigInteger object.
     */
    public function __wakeup()
    {
        $temp = new static($this->hex, -16);
        $this->value = $temp->value;
        if ($this->precision > 0) {
            // recalculate $this->bitmask
            $this->setPrecision($this->precision);
        }
    }
    /**
     * Performs modular exponentiation.
     *
     * @param BigInteger $e
     * @param BigInteger $n
     * @return BigInteger
     */
    public function powMod(BigInteger $e, BigInteger $n)
    {
        return new static($this->value->powMod($e->value, $n->value));
    }
    /**
     * Performs modular exponentiation.
     *
     * @param BigInteger $e
     * @param BigInteger $n
     * @return BigInteger
     */
    public function modPow(BigInteger $e, BigInteger $n)
    {
        return new static($this->value->modPow($e->value, $n->value));
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param BigInteger $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @access public
    * @see self::equals()
    */
    public function compare(BigInteger $y)
    {
        return $this->value->compare($y->value);
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param BigInteger $x
     * @return bool
     */
    public function equals(BigInteger $x)
    {
        return $this->value->equals($x->value);
    }
    /**
     * Logical Not
     *
     * @return BigInteger
     */
    public function bitwise_not()
    {
        return new static($this->value->bitwise_not());
    }
    /**
     * Logical And
     *
     * @param BigInteger $x
     * @return BigInteger
     */
    public function bitwise_and(BigInteger $x)
    {
        return new static($this->value->bitwise_and($x->value));
    }
    /**
     * Logical Or
     *
     * @param BigInteger $x
     * @return BigInteger
     */
    public function bitwise_or(BigInteger $x)
    {
        return new static($this->value->bitwise_or($x->value));
    }
    /**
     * Logical Exclusive Or
     *
     * @param BigInteger $x
     * @return BigInteger
     */
    public function bitwise_xor(BigInteger $x)
    {
        return new static($this->value->bitwise_xor($x->value));
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
     *
     * @param int $shift
     * @return BigInteger
     */
    public function bitwise_rightShift($shift)
    {
        return new static($this->value->bitwise_rightShift($shift));
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
     *
     * @param int $shift
     * @return BigInteger
     */
    public function bitwise_leftShift($shift)
    {
        return new static($this->value->bitwise_leftShift($shift));
    }
    /**
     * Logical Left Rotate
     *
     * Instead of the top x bits being dropped they're appended to the shifted bit string.
     *
     * @param int $shift
     * @return BigInteger
     */
    public function bitwise_leftRotate($shift)
    {
        return new static($this->value->bitwise_leftRotate($shift));
    }
    /**
     * Logical Right Rotate
     *
     * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
     *
     * @param int $shift
     * @return BigInteger
     */
    public function bitwise_rightRotate($shift)
    {
        return new static($this->value->bitwise_rightRotate($shift));
    }
    /**
     * Returns the smallest and largest n-bit number
     *
     * @param int $bits
     * @return BigInteger[]
     */
    public static function minMaxBits($bits)
    {
        self::initialize_static_variables();
        $class = self::$mainEngine;
        extract($class::minMaxBits($bits));
        /** @var BigInteger $min
         *  @var BigInteger $max
         */
        return ['min' => new static($min), 'max' => new static($max)];
    }
    /**
     * Return the size of a BigInteger in bits
     *
     * @return int
     */
    public function getLength()
    {
        return $this->value->getLength();
    }
    /**
     * Return the size of a BigInteger in bytes
     *
     * @return int
     */
    public function getLengthInBytes()
    {
        return $this->value->getLengthInBytes();
    }
    /**
     * Generates a random number of a certain size
     *
     * Bit length is equal to $size
     *
     * @param int $size
     * @return BigInteger
     */
    public static function random($size)
    {
        self::initialize_static_variables();
        $class = self::$mainEngine;
        return new static($class::random($size));
    }
    /**
     * Generates a random prime number of a certain size
     *
     * Bit length is equal to $size
     *
     * @param int $size
     * @return BigInteger
     */
    public static function randomPrime($size)
    {
        self::initialize_static_variables();
        $class = self::$mainEngine;
        return new static($class::randomPrime($size));
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param BigInteger $min
     * @param BigInteger $max
     * @return (false | BigInteger)
     */
    public static function randomRangePrime(BigInteger $min, BigInteger $max)
    {
        $class = self::$mainEngine;
        return new static($class::randomRangePrime($min->value, $max->value));
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param BigInteger $min
    * @param BigInteger $max
    * @return BigInteger
    */
    public static function randomRange(BigInteger $min, BigInteger $max)
    {
        $class = self::$mainEngine;
        return new static($class::randomRange($min->value, $max->value));
    }
    /**
    * Checks a numer to see if it's prime
    *
    * Assuming the $t parameter is not set, this function has an error rate of 2**-80.  The main motivation for the
    $t parameter is distributability.  BigInteger::randomPrime() can be distributed across multiple pageloads
    on a website instead of just one.
    *
    * @param (int | bool) $t
    * @return bool
    */
    public function isPrime($t = false)
    {
        return $this->value->isPrime($t);
    }
    /**
     * Calculates the nth root of a biginteger.
     *
     * Returns the nth root of a positive biginteger, where n defaults to 2
     *
     * @param int $n optional
     * @return BigInteger
     */
    public function root($n = 2)
    {
        return new static($this->value->root($n));
    }
    /**
     * Performs exponentiation.
     *
     * @param BigInteger $n
     * @return BigInteger
     */
    public function pow(BigInteger $n)
    {
        return new static($this->value->pow($n->value));
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param BigInteger ...$nums
     * @return BigInteger
     */
    public static function min(BigInteger ...$nums)
    {
        $class = self::$mainEngine;
        $nums = array_map(function ($num) {
            return $num->value;
        }, $nums);
        return new static($class::min(...$nums));
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param BigInteger ...$nums
     * @return BigInteger
     */
    public static function max(BigInteger ...$nums)
    {
        $class = self::$mainEngine;
        $nums = array_map(function ($num) {
            return $num->value;
        }, $nums);
        return new static($class::max(...$nums));
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param BigInteger $min
     * @param BigInteger $max
     * @return bool
     */
    public function between(BigInteger $min, BigInteger $max)
    {
        return $this->value->between($min->value, $max->value);
    }
    /**
     * Clone
     */
    public function __clone()
    {
        $this->value = clone $this->value;
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return $this->value->isOdd();
    }
    /**
     * Tests if a bit is set
     *
     * @param int $x
     * @return boolean
     */
    public function testBit($x)
    {
        return $this->value->testBit($x);
    }
    /**
     * Is Negative?
     *
     * @return boolean
     */
    public function isNegative()
    {
        return $this->value->isNegative();
    }
    /**
     * Negate
     *
     * Given $k, returns -$k
     *
     * @return BigInteger
     */
    public function negate()
    {
        return new static($this->value->negate());
    }
    /**
     * Scan for 1 and right shift by that amount
     *
     * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
     *
     * @param BigInteger $r
     * @return int
     */
    public static function scan1divide(BigInteger $r)
    {
        $class = self::$mainEngine;
        return $class::scan1divide($r->value);
    }
    /**
    * Create Recurring Modulo Function
    *
    * Sometimes it may be desirable to do repeated modulos with the same number outside of
    modular exponentiation
    *
    * @return callable
    */
    public function createRecurringModuloFunction()
    {
        $func = $this->value->createRecurringModuloFunction();
        return function (BigInteger $x) use($func) {
            return new static($func($x->value));
        };
    }
    /**
     * Bitwise Split
     *
     * Splits BigInteger's into chunks of $split bits
     *
     * @param int $split
     * @return \phpseclib3\Math\BigInteger[]
     */
    public function bitwise_split($split)
    {
        return array_map(function ($val) {
            return new static($val);
        }, $this->value->bitwise_split($split));
    }
}<?php

/**
 * OpenSSL Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use phpseclib3\Crypt\RSA;
use phpseclib3\Crypt\RSA\Formats\Keys\PKCS8;
use phpseclib3\Math\BigInteger;
/**
 * OpenSSL Modular Exponentiation Engine
 *
 * @package Engines
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSL
{
    /**
     * Test for engine validity
     *
     * @return bool
     */
    public static function isValidEngine()
    {
        return extension_loaded('openssl') && static::class != __CLASS__;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param Engine $x
     * @param Engine $e
     * @param Engine $n
     * @return Engine
     */
    public static function powModHelper(Engine $x, Engine $e, Engine $n)
    {
        if ($n->getLengthInBytes() < 31 || $n->getLengthInBytes() > 16384) {
            throw new \OutOfRangeException('Only modulo between 31 and 16384 bits are accepted');
        }
        $key = PKCS8::savePublicKey(new BigInteger($n), new BigInteger($e));
        $plaintext = str_pad($x->toBytes(), $n->getLengthInBytes(), "\x00", STR_PAD_LEFT);
        // this is easily prone to failure. if the modulo is a multiple of 2 or 3 or whatever it
        // won't work and you'll get a "failure: error:0906D06C:PEM routines:PEM_read_bio:no start line"
        // error. i suppose, for even numbers, we could do what PHP\Montgomery.php does, but then what
        // about odd numbers divisible by 3, by 5, etc?
        if (!openssl_public_encrypt($plaintext, $result, $key, OPENSSL_NO_PADDING)) {
            throw new \UnexpectedValueException(openssl_error_string());
        }
        $class = get_class($x);
        return new $class($result, 256);
    }
}<?php

/**
 * GMP Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\GMP;

use phpseclib3\Math\BigInteger\Engines\GMP;
/**
 * GMP Modular Exponentiation Engine
 *
 * @package GMP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DefaultEngine extends GMP
{
    /**
     * Performs modular exponentiation.
     *
     * @param GMP $x
     * @param GMP $e
     * @param GMP $n
     * @return GMP
     */
    protected static function powModHelper(GMP $x, GMP $e, GMP $n)
    {
        $temp = new GMP();
        $temp->value = gmp_powm($x->value, $e->value, $n->value);
        return $x->normalize($temp);
    }
}<?php

/**
 * Pure-PHP 32-bit BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
/**
 * Pure-PHP 32-bit Engine.
 *
 * Uses 64-bit floats if int size is 4 bits
 *
 * @package PHP32
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PHP32 extends PHP
{
    // Constants used by PHP.php
    const BASE = 26;
    const BASE_FULL = 0x4000000;
    const MAX_DIGIT = 0x3ffffff;
    const MSB = 0x2000000;
    /**
     * MAX10 in greatest MAX10LEN satisfying
     * MAX10 = 10**MAX10LEN <= 2**BASE.
     */
    const MAX10 = 10000000;
    /**
     * MAX10LEN in greatest MAX10LEN satisfying
     * MAX10 = 10**MAX10LEN <= 2**BASE.
     */
    const MAX10LEN = 7;
    const MAX_DIGIT2 = 4503599627370496;
    /**#@-*/
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    protected static $modexpEngine;
    /**
     * Engine Validity Flag
     *
     * @var bool
     */
    protected static $isValidEngine;
    /**
     * Primes > 2 and < 1000
     *
     * @var array
     */
    protected static $primes;
    /**
     * BigInteger(0)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP32
     */
    protected static $zero;
    /**
     * BigInteger(1)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP32
     */
    protected static $one;
    /**
     * BigInteger(2)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP32
     */
    protected static $two;
    /**
     * Initialize a PHP32 BigInteger Engine instance
     *
     * @param int $base
     * @see parent::initialize()
     */
    protected function initialize($base)
    {
        if ($base != 256 && $base != -256) {
            return parent::initialize($base);
        }
        $val = $this->value;
        $this->value = [];
        $vals =& $this->value;
        $i = strlen($val);
        if (!$i) {
            return;
        }
        while (true) {
            $i -= 4;
            if ($i < 0) {
                if ($i == -4) {
                    break;
                }
                $val = \Phabel\Target\Php80\Polyfill::substr($val, 0, 4 + $i);
                $val = str_pad($val, 4, "\x00", STR_PAD_LEFT);
                if ($val == "\x00\x00\x00\x00") {
                    break;
                }
                $i = 0;
            }
            list(, $digit) = unpack('N', \Phabel\Target\Php80\Polyfill::substr($val, $i, 4));
            $step = count($vals) & 3;
            if ($step) {
                $digit >>= 2 * $step;
            }
            if ($step != 3) {
                $digit &= static::MAX_DIGIT;
                $i++;
            }
            $vals[] = $digit;
        }
        while (end($vals) === 0) {
            array_pop($vals);
        }
        reset($vals);
    }
    /**
     * Test for engine validity
     *
     * @see parent::__construct()
     * @return bool
     */
    public static function isValidEngine()
    {
        return PHP_INT_SIZE >= 4;
    }
    /**
     * Adds two BigIntegers.
     *
     * @param PHP32 $y
     * @return PHP32
     */
    public function add(PHP32 $y)
    {
        $temp = self::addHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param PHP32 $y
     * @return PHP32
     */
    public function subtract(PHP32 $y)
    {
        $temp = self::subtractHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
     * Multiplies two BigIntegers.
     *
     * @param PHP32 $y
     * @return PHP32
     */
    public function multiply(PHP32 $y)
    {
        $temp = self::multiplyHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param PHP32 $y
    * @return PHP32
    */
    public function divide(PHP32 $y)
    {
        return $this->divideHelper($y);
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @param PHP32 $n
     * @return (false | PHP32)
     */
    public function modInverse(PHP32 $n)
    {
        return $this->modInverseHelper($n);
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @param PHP32 $n
     * @return PHP32[]
     */
    public function extendedGCD(PHP32 $n)
    {
        return $this->extendedGCDHelper($n);
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param PHP32 $n
     * @return PHP32
     */
    public function gcd(PHP32 $n)
    {
        return $this->extendedGCD($n)['gcd'];
    }
    /**
     * Logical And
     *
     * @param PHP32 $x
     * @return PHP32
     */
    public function bitwise_and(PHP32 $x)
    {
        return $this->bitwiseAndHelper($x);
    }
    /**
     * Logical Or
     *
     * @param PHP32 $x
     * @return PHP32
     */
    public function bitwise_or(PHP32 $x)
    {
        return $this->bitwiseOrHelper($x);
    }
    /**
     * Logical Exclusive Or
     *
     * @param PHP32 $x
     * @return PHP32
     */
    public function bitwise_xor(PHP32 $x)
    {
        return $this->bitwiseXorHelper($x);
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param PHP32 $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @access public
    * @see self::equals()
    */
    public function compare(PHP32 $y)
    {
        return $this->compareHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param PHP32 $x
     * @return bool
     */
    public function equals(PHP32 $x)
    {
        return $this->value === $x->value && $this->is_negative == $x->is_negative;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param PHP32 $e
     * @param PHP32 $n
     * @return PHP32
     */
    public function modPow(PHP32 $e, PHP32 $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * Alias for modPow().
     *
     * @param PHP32 $e
     * @param PHP32 $n
     * @return PHP32
     */
    public function powMod(PHP32 $e, PHP32 $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param PHP32 $min
     * @param PHP32 $max
     * @return (false | PHP32)
     */
    public static function randomRangePrime(PHP32 $min, PHP32 $max)
    {
        return self::randomRangePrimeOuter($min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param PHP32 $min
    * @param PHP32 $max
    * @return PHP32
    */
    public static function randomRange(PHP32 $min, PHP32 $max)
    {
        return self::randomRangeHelper($min, $max);
    }
    /**
     * Performs exponentiation.
     *
     * @param PHP32 $n
     * @return PHP32
     */
    public function pow(PHP32 $n)
    {
        return $this->powHelper($n);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param PHP32 ...$nums
     * @return PHP32
     */
    public static function min(PHP32 ...$nums)
    {
        return self::minHelper($nums);
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param PHP32 ...$nums
     * @return PHP32
     */
    public static function max(PHP32 ...$nums)
    {
        return self::maxHelper($nums);
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param PHP32 $min
     * @param PHP32 $max
     * @return bool
     */
    public function between(PHP32 $min, PHP32 $max)
    {
        return $this->compare($min) >= 0 && $this->compare($max) <= 0;
    }
}<?php

/**
 * BCMath BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Exception\BadConfigurationException;
/**
 * BCMath Engine.
 *
 * @package BCMath
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class BCMath extends Engine
{
    /**
     * Can Bitwise operations be done fast?
     *
     * @see parent::bitwise_leftRotate()
     * @see parent::bitwise_rightRotate()
     * @access protected
     */
    const FAST_BITWISE = false;
    /**
     * Engine Directory
     *
     * @see parent::setModExpEngine
     * @access protected
     */
    const ENGINE_DIR = 'BCMath';
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    protected static $modexpEngine;
    /**
     * Engine Validity Flag
     *
     * @var bool
     */
    protected static $isValidEngine;
    /**
     * BigInteger(0)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    protected static $zero;
    /**
     * BigInteger(1)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    protected static $one;
    /**
     * BigInteger(2)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    protected static $two;
    /**
     * Primes > 2 and < 1000
     *
     * @var array
     */
    protected static $primes;
    /**
     * Test for engine validity
     *
     * @see parent::__construct()
     * @return bool
     */
    public static function isValidEngine()
    {
        return extension_loaded('bcmath');
    }
    /**
     * Default constructor
     *
     * @param mixed $x integer Base-10 number or base-$base number if $base set.
     * @param int $base
     * @see parent::__construct()
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    public function __construct($x = 0, $base = 10)
    {
        if (!isset(self::$isValidEngine)) {
            self::$isValidEngine = self::isValidEngine();
        }
        if (!self::$isValidEngine) {
            throw new BadConfigurationException('BCMath is not setup correctly on this system');
        }
        $this->value = '0';
        parent::__construct($x, $base);
    }
    /**
     * Initialize a BCMath BigInteger Engine instance
     *
     * @param int $base
     * @see parent::__construct()
     */
    protected function initialize($base)
    {
        switch (abs($base)) {
            case 256:
                // round $len to the nearest 4
                $len = strlen($this->value) + 3 & 0xfffffffc;
                $x = str_pad($this->value, $len, chr(0), STR_PAD_LEFT);
                $this->value = '0';
                for ($i = 0; $i < $len; $i += 4) {
                    $this->value = bcmul($this->value, '4294967296', 0);
                    // 4294967296 == 2**32
                    $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + (ord($x[$i + 1]) << 16 | ord($x[$i + 2]) << 8 | ord($x[$i + 3])), 0);
                }
                if ($this->is_negative) {
                    $this->value = '-' . $this->value;
                }
                break;
            case 16:
                $x = strlen($this->value) & 1 ? '0' . $this->value : $this->value;
                $temp = new self(Hex::decode($x), 256);
                $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
                $this->is_negative = false;
                break;
            case 10:
                // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
                // results then doing it on '-1' does (modInverse does $x[0])
                $this->value = $this->value === '-' ? '0' : (string) $this->value;
        }
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function toString()
    {
        if ($this->value === '0') {
            return '0';
        }
        return ltrim($this->value, '0');
    }
    /**
     * Converts a BigInteger to a byte string (eg. base-256).
     *
     * @param bool $twos_compliment
     * @return string
     */
    function toBytes($twos_compliment = false)
    {
        if ($twos_compliment) {
            return $this->toBytesHelper();
        }
        $value = '';
        $current = $this->value;
        if ($current[0] == '-') {
            $current = \Phabel\Target\Php80\Polyfill::substr($current, 1);
        }
        while (bccomp($current, '0', 0) > 0) {
            $temp = bcmod($current, '16777216');
            $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
            $current = bcdiv($current, '16777216', 0);
        }
        return $this->precision > 0 ? \Phabel\Target\Php80\Polyfill::substr(str_pad($value, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : ltrim($value, chr(0));
    }
    /**
     * Adds two BigIntegers.
     *
     * @param BCMath $y
     * @return BCMath
     */
    public function add(BCMath $y)
    {
        $temp = new self();
        $temp->value = bcadd($this->value, $y->value);
        return $this->normalize($temp);
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param BCMath $y
     * @return BCMath
     */
    public function subtract(BCMath $y)
    {
        $temp = new self();
        $temp->value = bcsub($this->value, $y->value);
        return $this->normalize($temp);
    }
    /**
     * Multiplies two BigIntegers.
     *
     * @param BCMath $x
     * @return BCMath
     */
    public function multiply(BCMath $x)
    {
        $temp = new self();
        $temp->value = bcmul($this->value, $x->value);
        return $this->normalize($temp);
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param BCMath $y
    * @return BCMath
    */
    public function divide(BCMath $y)
    {
        $quotient = new self();
        $remainder = new self();
        $quotient->value = bcdiv($this->value, $y->value, 0);
        $remainder->value = bcmod($this->value, $y->value);
        if ($remainder->value[0] == '-') {
            $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? \Phabel\Target\Php80\Polyfill::substr($y->value, 1) : $y->value, 0);
        }
        return [$this->normalize($quotient), $this->normalize($remainder)];
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     *
     * @return (false | BCMath)
     * @param \phpseclib3\Math\BigInteger\Engines\BCMath $n
     */
    public function modInverse(BCMath $n)
    {
        return $this->modInverseHelper($n);
    }
    /**
    * Calculates the greatest common divisor and Bezout's identity.
    *
    * Say you have 693 and 609.  The GCD is 21.  Bezout's identity states that there exist integers x and y such that
    693*x + 609*y == 21.  In point of fact, there are actually an infinite number of x and y combinations and which
    combination is returned is dependent upon which mode is in use.  See
    {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
    *
    * @param BCMath $n
    * @return BCMath
    */
    public function extendedGCD(BCMath $n)
    {
        // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
        // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway.  as is,
        // the basic extended euclidean algorithim is what we're using.
        $u = $this->value;
        $v = $n->value;
        $a = '1';
        $b = '0';
        $c = '0';
        $d = '1';
        while (bccomp($v, '0', 0) != 0) {
            $q = bcdiv($u, $v, 0);
            $temp = $u;
            $u = $v;
            $v = bcsub($temp, bcmul($v, $q, 0), 0);
            $temp = $a;
            $a = $c;
            $c = bcsub($temp, bcmul($a, $q, 0), 0);
            $temp = $b;
            $b = $d;
            $d = bcsub($temp, bcmul($b, $q, 0), 0);
        }
        return ['gcd' => $this->normalize(new static($u)), 'x' => $this->normalize(new static($a)), 'y' => $this->normalize(new static($b))];
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param BCMath $n
     * @return BCMath
     */
    public function gcd(BCMath $n)
    {
        extract($this->extendedGCD($n));
        /** @var BCMath $gcd */
        return $gcd;
    }
    /**
     * Absolute value.
     *
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    public function abs()
    {
        $temp = new static();
        $temp->value = strlen($this->value) && $this->value[0] == '-' ? \Phabel\Target\Php80\Polyfill::substr($this->value, 1) : $this->value;
        return $temp;
    }
    /**
     * Logical And
     *
     * @param BCMath $x
     * @return BCMath
     */
    public function bitwise_and(BCMath $x)
    {
        return $this->bitwiseAndHelper($x);
    }
    /**
     * Logical Or
     *
     * @param BCMath $x
     * @return BCMath
     */
    public function bitwise_or(BCMath $x)
    {
        return $this->bitwiseXorHelper($x);
    }
    /**
     * Logical Exclusive Or
     *
     * @param BCMath $x
     * @return BCMath
     */
    public function bitwise_xor(BCMath $x)
    {
        return $this->bitwiseXorHelper($x);
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    public function bitwise_rightShift($shift)
    {
        $temp = new static();
        $temp->value = bcdiv($this->value, bcpow('2', $shift, 0), 0);
        return $this->normalize($temp);
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    public function bitwise_leftShift($shift)
    {
        $temp = new static();
        $temp->value = bcmul($this->value, bcpow('2', $shift, 0), 0);
        return $this->normalize($temp);
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param BCMath $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @see self::equals()
    */
    public function compare(BCMath $y)
    {
        return bccomp($this->value, $y->value, 0);
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param BCMath $x
     * @return bool
     */
    public function equals(BCMath $x)
    {
        return $this->value == $x->value;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param BCMath $e
     * @param BCMath $n
     * @return BCMath
     */
    public function modPow(BCMath $e, BCMath $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * Alias for modPow().
     *
     * @param BCMath $e
     * @param BCMath $n
     * @return BCMath
     */
    public function powMod(BCMath $e, BCMath $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * @param BCMath $e
     * @param BCMath $n
     * @return BCMath
     */
    protected function powModInner(BCMath $e, BCMath $n)
    {
        try {
            $class = self::$modexpEngine;
            return $class::powModHelper($this, $e, $n, static::class);
        } catch (\Exception $err) {
            return BCMath\DefaultEngine::powModHelper($this, $e, $n, static::class);
        }
    }
    /**
     * Normalize
     *
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
     *
     * @param BCMath $result
     * @return BCMath
     */
    protected function normalize(BCMath $result)
    {
        $result->precision = $this->precision;
        $result->bitmask = $this->bitmask;
        if ($result->bitmask !== false) {
            $result->value = bcmod($result->value, $result->bitmask->value);
        }
        return $result;
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param BCMath $min
     * @param BCMath $max
     * @return (false | BCMath)
     */
    public static function randomRangePrime(BCMath $min, BCMath $max)
    {
        return self::randomRangePrimeOuter($min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param BCMath $min
    * @param BCMath $max
    * @return BCMath
    */
    public static function randomRange(BCMath $min, BCMath $max)
    {
        return self::randomRangeHelper($min, $max);
    }
    /**
     * Make the current number odd
     *
     * If the current number is odd it'll be unchanged.  If it's even, one will be added to it.
     *
     * @see self::randomPrime()
     */
    protected function make_odd()
    {
        if (!$this->isOdd()) {
            $this->value = bcadd($this->value, '1');
        }
    }
    /**
     * Test the number against small primes.
     *
     * @see self::isPrime()
     */
    protected function testSmallPrimes()
    {
        if ($this->value === '1') {
            return false;
        }
        if ($this->value === '2') {
            return true;
        }
        if ($this->value[strlen($this->value) - 1] % 2 == 0) {
            return false;
        }
        $value = $this->value;
        foreach (self::$primes as $prime) {
            $r = bcmod($this->value, $prime);
            if ($r == '0') {
                return $this->value == $prime;
            }
        }
        return true;
    }
    /**
     * Scan for 1 and right shift by that amount
     *
     * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
     *
     * @see self::isPrime()
     * @param BCMath $r
     * @return int
     */
    public static function scan1divide(BCMath $r)
    {
        $r_value =& $r->value;
        $s = 0;
        // if $n was 1, $r would be 0 and this would be an infinite loop, hence our $this->equals(static::$one) check earlier
        while ($r_value[strlen($r_value) - 1] % 2 == 0) {
            $r_value = bcdiv($r_value, '2', 0);
            ++$s;
        }
        return $s;
    }
    /**
     * Performs exponentiation.
     *
     * @param BCMath $n
     * @return BCMath
     */
    public function pow(BCMath $n)
    {
        $temp = new self();
        $temp->value = bcpow($this->value, $n->value);
        return $this->normalize($temp);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param BCMath ...$nums
     * @return BCMath
     */
    public static function min(BCMath ...$nums)
    {
        return self::minHelper($nums);
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param BCMath ...$nums
     * @return BCMath
     */
    public static function max(BCMath ...$nums)
    {
        return self::maxHelper($nums);
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param BCMath $min
     * @param BCMath $max
     * @return bool
     */
    public function between(BCMath $min, BCMath $max)
    {
        return $this->compare($min) >= 0 && $this->compare($max) <= 0;
    }
    /**
     * Set Bitmask
     *
     * @return Engine
     * @param int $bits
     * @see self::setPrecision()
     */
    protected static function setBitmask($bits)
    {
        $temp = parent::setBitmask($bits);
        return $temp->add(static::$one);
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return $this->value[strlen($this->value) - 1] % 2 == 1;
    }
    /**
     * Tests if a bit is set
     *
     * @return boolean
     */
    public function testBit($x)
    {
        return bccomp(bcmod($this->value, bcpow('2', $x + 1, 0), 0), bcpow('2', $x, 0), 0) >= 0;
    }
    /**
     * Is Negative?
     *
     * @return boolean
     */
    public function isNegative()
    {
        return strlen($this->value) && $this->value[0] == '-';
    }
    /**
     * Negate
     *
     * Given $k, returns -$k
     *
     * @return BCMath
     */
    public function negate()
    {
        $temp = clone $this;
        if (!strlen($temp->value)) {
            return $temp;
        }
        $temp->value = $temp->value[0] == '-' ? \Phabel\Target\Php80\Polyfill::substr($this->value, 1) : '-' . $this->value;
        return $temp;
    }
}<?php

/**
 * Base BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Exception\BadConfigurationException;
use phpseclib3\Crypt\Random;
use phpseclib3\Math\BigInteger;
use phpseclib3\Common\Functions\Strings;
/**
 * Base Engine.
 *
 * @package Engine
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Engine
{
    /**
     * Holds the BigInteger's value
     *
     * @var mixed
     */
    protected $value;
    /**
     * Holds the BigInteger's sign
     *
     * @var bool
     */
    protected $is_negative;
    /**
     * Precision
     *
     * @see static::setPrecision()
     */
    protected $precision = -1;
    /**
     * Precision Bitmask
     *
     * @see static::setPrecision()
     */
    protected $bitmask = false;
    /**
     * Recurring Modulo Function
     *
     * @var callable
     */
    protected $reduce;
    /**
     * Mode independent value used for serialization.
     *
     * @see self::__sleep()
     * @see self::__wakeup()
     * @var string
     */
    protected $hex;
    /**
     * Default constructor
     *
     * @param mixed $x integer Base-10 number or base-$base number if $base set.
     * @param int $base
     */
    public function __construct($x, $base)
    {
        if (!isset(static::$primes)) {
            static::$primes = [3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997];
            static::$zero = new static(0);
            static::$one = new static(1);
            static::$two = new static(2);
        }
        // '0' counts as empty() but when the base is 256 '0' is equal to ord('0') or 48
        // '0' is the only value like this per http://php.net/empty
        if (empty($x) && (abs($base) != 256 || $x !== '0')) {
            return;
        }
        switch ($base) {
            case -256:
            case 256:
                if ($base == -256 && ord($x[0]) & 0x80) {
                    $this->value = ~$x;
                    $this->is_negative = true;
                } else {
                    $this->value = $x;
                    $this->is_negative = false;
                }
                static::initialize($base);
                if ($this->is_negative) {
                    $temp = $this->add(new static('-1'));
                    $this->value = $temp->value;
                }
                break;
            case -16:
            case 16:
                if ($base > 0 && $x[0] == '-') {
                    $this->is_negative = true;
                    $x = \Phabel\Target\Php80\Polyfill::substr($x, 1);
                }
                $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
                $is_negative = false;
                if ($base < 0 && hexdec($x[0]) >= 8) {
                    $this->is_negative = $is_negative = true;
                    $x = Hex::encode(~Hex::decode($x));
                }
                $this->value = $x;
                static::initialize($base);
                if ($is_negative) {
                    $temp = $this->add(new static('-1'));
                    $this->value = $temp->value;
                }
                break;
            case -10:
            case 10:
                // (?<!^)(?:-).*: find any -'s that aren't at the beginning and then any characters that follow that
                // (?<=^|-)0*: find any 0's that are preceded by the start of the string or by a - (ie. octals)
                // [^-0-9].*: find any non-numeric characters and then any characters that follow that
                $this->value = preg_replace('#(?<!^)(?:-).*|(?<=^|-)0*|[^-0-9].*#', '', $x);
                if (!strlen($this->value) || $this->value == '-') {
                    $this->value = '0';
                }
                static::initialize($base);
                break;
            case -2:
            case 2:
                if ($base > 0 && $x[0] == '-') {
                    $this->is_negative = true;
                    $x = \Phabel\Target\Php80\Polyfill::substr($x, 1);
                }
                $x = preg_replace('#^([01]*).*#', '$1', $x);
                $temp = new static(Strings::bits2bin($x), 128 * $base);
                // ie. either -16 or +16
                $this->value = $temp->value;
                if ($temp->is_negative) {
                    $this->is_negative = true;
                }
                break;
            default:
        }
    }
    /**
     * Sets engine type.
     *
     * Throws an exception if the type is invalid
     *
     * @param string $engine
     */
    public static function setModExpEngine($engine)
    {
        $fqengine = '\\phpseclib3\\Math\\BigInteger\\Engines\\' . static::ENGINE_DIR . '\\' . $engine;
        if (!class_exists($fqengine) || !method_exists($fqengine, 'isValidEngine')) {
            throw new \InvalidArgumentException("{$engine} is not a valid engine");
        }
        if (!$fqengine::isValidEngine()) {
            throw new BadConfigurationException("{$engine} is not setup correctly on this system");
        }
        static::$modexpEngine = $fqengine;
    }
    /**
    * Converts a BigInteger to a byte string (eg. base-256).
    *
    * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
    saved as two's compliment.
    * @return string
    */
    protected function toBytesHelper()
    {
        $comparison = $this->compare(new static());
        if ($comparison == 0) {
            return $this->precision > 0 ? str_repeat(chr(0), $this->precision + 1 >> 3) : '';
        }
        $temp = $comparison < 0 ? $this->add(new static(1)) : $this;
        $bytes = $temp->toBytes();
        if (!strlen($bytes)) {
            // eg. if the number we're trying to convert is -1
            $bytes = chr(0);
        }
        if (ord($bytes[0]) & 0x80) {
            $bytes = chr(0) . $bytes;
        }
        return $comparison < 0 ? ~$bytes : $bytes;
    }
    /**
     * Converts a BigInteger to a hex string (eg. base-16).
     *
     * @param bool $twos_compliment
     * @return string
     */
    public function toHex($twos_compliment = false)
    {
        return Hex::encode($this->toBytes($twos_compliment));
    }
    /**
    * Converts a BigInteger to a bit string (eg. base-2).
    *
    * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
    saved as two's compliment.
    *
    * @param bool $twos_compliment
    * @return string
    */
    public function toBits($twos_compliment = false)
    {
        $hex = $this->toBytes($twos_compliment);
        $bits = Strings::bin2bits($hex);
        $result = $this->precision > 0 ? \Phabel\Target\Php80\Polyfill::substr($bits, -$this->precision) : ltrim($bits, '0');
        if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
            return '0' . $result;
        }
        return $result;
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     *
     * {@internal See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.}
     *
     * @param \phpseclib3\Math\BigInteger\Engines\Engine $n
     * @return (\phpseclib3\Math\BigInteger\Engines\Engine | false)
     */
    protected function modInverseHelper(Engine $n)
    {
        // $x mod -$n == $x mod $n.
        $n = $n->abs();
        if ($this->compare(static::$zero) < 0) {
            $temp = $this->abs();
            $temp = $temp->modInverse($n);
            return $this->normalize($n->subtract($temp));
        }
        extract($this->extendedGCD($n));
        /**
         * @var BigInteger $gcd
         * @var BigInteger $x
         */
        if (!$gcd->equals(static::$one)) {
            return false;
        }
        $x = $x->compare(static::$zero) < 0 ? $x->add($n) : $x;
        return $this->compare(static::$zero) < 0 ? $this->normalize($n->subtract($x)) : $this->normalize($x);
    }
    /**
     * Serialize
     *
     * Will be called, automatically, when serialize() is called on a BigInteger object.
     *
     * @return string
     */
    public function __sleep()
    {
        $this->hex = $this->toHex(true);
        $vars = ['hex'];
        if ($this->precision > 0) {
            $vars[] = 'precision';
        }
        return $vars;
    }
    /**
     * Serialize
     *
     * Will be called, automatically, when unserialize() is called on a BigInteger object.
     */
    public function __wakeup()
    {
        $temp = new static($this->hex, -16);
        $this->value = $temp->value;
        $this->is_negative = $temp->is_negative;
        if ($this->precision > 0) {
            // recalculate $this->bitmask
            $this->setPrecision($this->precision);
        }
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function __toString()
    {
        return $this->toString();
    }
    /**
     * __debugInfo() magic method
     *
     * Will be called, automatically, when print_r() or var_dump() are called
     */
    public function __debugInfo()
    {
        return ['value' => '0x' . $this->toHex(true), 'engine' => basename(static::class)];
    }
    /**
    * Set Precision
    *
    * Some bitwise operations give different results depending on the precision being used.  Examples include left
    shift, not, and rotates.
    *
    * @param int $bits
    */
    public function setPrecision($bits)
    {
        if ($bits < 1) {
            $this->precision = -1;
            $this->bitmask = false;
            return;
        }
        $this->precision = $bits;
        $this->bitmask = static::setBitmask($bits);
        $temp = $this->normalize($this);
        $this->value = $temp->value;
    }
    /**
     * Get Precision
     *
     * Returns the precision if it exists, -1 if it doesn't
     *
     * @return int
     */
    public function getPrecision()
    {
        return $this->precision;
    }
    /**
     * Set Bitmask
     * @return Engine
     * @param int $bits
     * @see self::setPrecision()
     */
    protected static function setBitmask($bits)
    {
        return new static(chr((1 << ($bits & 0x7)) - 1) . str_repeat(chr(0xff), $bits >> 3), 256);
    }
    /**
     * Logical Not
     *
     * @return (Engine | string)
     */
    public function bitwise_not()
    {
        // calculuate "not" without regard to $this->precision
        // (will always result in a smaller number.  ie. ~1 isn't 1111 1110 - it's 0)
        $temp = $this->toBytes();
        if ($temp == '') {
            return $this->normalize(static::$zero);
        }
        $pre_msb = decbin(ord($temp[0]));
        $temp = ~$temp;
        $msb = decbin(ord($temp[0]));
        if (strlen($msb) == 8) {
            $msb = \Phabel\Target\Php80\Polyfill::substr($msb, strpos($msb, '0'));
        }
        $temp[0] = chr(bindec($msb));
        // see if we need to add extra leading 1's
        $current_bits = strlen($pre_msb) + 8 * strlen($temp) - 8;
        $new_bits = $this->precision - $current_bits;
        if ($new_bits <= 0) {
            return $this->normalize(new static($temp, 256));
        }
        // generate as many leading 1's as we need to.
        $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xff), $new_bits >> 3);
        self::base256_lshift($leading_ones, $current_bits);
        $temp = str_pad($temp, strlen($leading_ones), chr(0), STR_PAD_LEFT);
        return $this->normalize(new static($leading_ones | $temp, 256));
    }
    /**
     * Logical Left Shift
     *
     * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
     *
     * @param string $x
     * @param int $shift
     * @return string
     */
    protected static function base256_lshift(&$x, $shift)
    {
        if ($shift == 0) {
            return;
        }
        $num_bytes = $shift >> 3;
        // eg. floor($shift/8)
        $shift &= 7;
        // eg. $shift % 8
        $carry = 0;
        for ($i = strlen($x) - 1; $i >= 0; --$i) {
            $temp = ord($x[$i]) << $shift | $carry;
            $x[$i] = chr($temp);
            $carry = $temp >> 8;
        }
        $carry = $carry != 0 ? chr($carry) : '';
        $x = $carry . $x . str_repeat(chr(0), $num_bytes);
    }
    /**
     * Logical Left Rotate
     *
     * Instead of the top x bits being dropped they're appended to the shifted bit string.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    public function bitwise_leftRotate($shift)
    {
        $bits = $this->toBytes();
        if ($this->precision > 0) {
            $precision = $this->precision;
            if (static::FAST_BITWISE) {
                $mask = $this->bitmask->toBytes();
            } else {
                $mask = $this->bitmask->subtract(new static(1));
                $mask = $mask->toBytes();
            }
        } else {
            $temp = ord($bits[0]);
            for ($i = 0; $temp >> $i; ++$i) {
            }
            $precision = 8 * strlen($bits) - 8 + $i;
            $mask = chr((1 << ($precision & 0x7)) - 1) . str_repeat(chr(0xff), $precision >> 3);
        }
        if ($shift < 0) {
            $shift += $precision;
        }
        $shift %= $precision;
        if (!$shift) {
            return clone $this;
        }
        $left = $this->bitwise_leftShift($shift);
        $left = $left->bitwise_and(new static($mask, 256));
        $right = $this->bitwise_rightShift($precision - $shift);
        $result = static::FAST_BITWISE ? $left->bitwise_or($right) : $left->add($right);
        return $this->normalize($result);
    }
    /**
     * Logical Right Rotate
     *
     * Instead of the bottom x bits being dropped they're prepended to the shifted bit string.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    public function bitwise_rightRotate($shift)
    {
        return $this->bitwise_leftRotate(-$shift);
    }
    /**
     * Returns the smallest and largest n-bit number
     *
     * @param int $bits
     * @return \phpseclib3\Math\BigInteger\Engines\Engine[]
     */
    public static function minMaxBits($bits)
    {
        $bytes = $bits >> 3;
        $min = str_repeat(chr(0), $bytes);
        $max = str_repeat(chr(0xff), $bytes);
        $msb = $bits & 7;
        if ($msb) {
            $min = chr(1 << $msb - 1) . $min;
            $max = chr((1 << $msb) - 1) . $max;
        } else {
            $min[0] = chr(0x80);
        }
        return ['min' => new static($min, 256), 'max' => new static($max, 256)];
    }
    /**
     * Return the size of a BigInteger in bits
     *
     * @return int
     */
    public function getLength()
    {
        return strlen($this->toBits());
    }
    /**
     * Return the size of a BigInteger in bytes
     *
     * @return int
     */
    public function getLengthInBytes()
    {
        return strlen($this->toBytes());
    }
    /**
     * Performs some pre-processing for powMod
     *
     * @param Engine $e
     * @param Engine $n
     * @return (bool | Engine)
     */
    protected function powModOuter(Engine $e, Engine $n)
    {
        $n = $this->bitmask !== false && $this->bitmask->compare($n) < 0 ? $this->bitmask : $n->abs();
        if ($e->compare(new static()) < 0) {
            $e = $e->abs();
            $temp = $this->modInverse($n);
            if ($temp === false) {
                return false;
            }
            return $this->normalize($temp->powModInner($e, $n));
        }
        return $this->powModInner($e, $n);
    }
    /**
    * Sliding Window k-ary Modular Exponentiation
    *
    * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}.  In a departure from those algorithims,
    however, this function performs a modular reduction after every multiplication and squaring operation.
    As such, this function has the same preconditions that the reductions being used do.
    *
    * @param \phpseclib3\Math\BigInteger\Engines\Engine $x
    * @param \phpseclib3\Math\BigInteger\Engines\Engine $e
    * @param \phpseclib3\Math\BigInteger\Engines\Engine $n
    * @param string $class
    * @return \phpseclib3\Math\BigInteger\Engines\Engine
    */
    protected static function slidingWindow(Engine $x, Engine $e, Engine $n, $class)
    {
        static $window_ranges = [7, 25, 81, 241, 673, 1793];
        // from BigInteger.java's oddModPow function
        //static $window_ranges = [0, 7, 36, 140, 450, 1303, 3529]; // from MPM 7.3.1
        $e_bits = $e->toBits();
        $e_length = strlen($e_bits);
        // calculate the appropriate window size.
        // $window_size == 3 if $window_ranges is between 25 and 81, for example.
        for ($i = 0, $window_size = 1; $i < count($window_ranges) && $e_length > $window_ranges[$i]; ++$window_size, ++$i) {
        }
        $n_value = $n->value;
        if (method_exists(static::class, 'generateCustomReduction')) {
            static::generateCustomReduction($n, $class);
        }
        // precompute $this^0 through $this^$window_size
        $powers = [];
        $powers[1] = static::prepareReduce($x->value, $n_value, $class);
        $powers[2] = static::squareReduce($powers[1], $n_value, $class);
        // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end
        // in a 1.  ie. it's supposed to be odd.
        $temp = 1 << $window_size - 1;
        for ($i = 1; $i < $temp; ++$i) {
            $i2 = $i << 1;
            $powers[$i2 + 1] = static::multiplyReduce($powers[$i2 - 1], $powers[2], $n_value, $class);
        }
        $result = new $class(1);
        $result = static::prepareReduce($result->value, $n_value, $class);
        for ($i = 0; $i < $e_length;) {
            if (!$e_bits[$i]) {
                $result = static::squareReduce($result, $n_value, $class);
                ++$i;
            } else {
                for ($j = $window_size - 1; $j > 0; --$j) {
                    if (!empty($e_bits[$i + $j])) {
                        break;
                    }
                }
                // eg. the length of substr($e_bits, $i, $j + 1)
                for ($k = 0; $k <= $j; ++$k) {
                    $result = static::squareReduce($result, $n_value, $class);
                }
                $result = static::multiplyReduce($result, $powers[bindec(\Phabel\Target\Php80\Polyfill::substr($e_bits, $i, $j + 1))], $n_value, $class);
                $i += $j + 1;
            }
        }
        $temp = new $class();
        $temp->value = static::reduce($result, $n_value, $class);
        return $temp;
    }
    /**
     * Generates a random number of a certain size
     *
     * Bit length is equal to $size
     *
     * @param int $size
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    public static function random($size)
    {
        extract(static::minMaxBits($size));
        /**
         * @var BigInteger $min
         * @var BigInteger $max
         */
        return static::randomRange($min, $max);
    }
    /**
     * Generates a random prime number of a certain size
     *
     * Bit length is equal to $size
     *
     * @param int $size
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    public static function randomPrime($size)
    {
        extract(static::minMaxBits($size));
        /**
         * @var BigInteger $min
         * @var BigInteger $max
         */
        return static::randomRangePrime($min, $max);
    }
    /**
     * Performs some pre-processing for randomRangePrime
     *
     * @param Engine $min
     * @param Engine $max
     * @return (bool | Engine)
     */
    protected static function randomRangePrimeOuter(Engine $min, Engine $max)
    {
        $compare = $max->compare($min);
        if (!$compare) {
            return $min->isPrime() ? $min : false;
        } elseif ($compare < 0) {
            // if $min is bigger then $max, swap $min and $max
            $temp = $max;
            $max = $min;
            $min = $temp;
        }
        $x = static::randomRange($min, $max);
        return static::randomRangePrimeInner($x, $min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param Engine $min
    * @param Engine $max
    * @return Engine
    */
    protected static function randomRangeHelper(Engine $min, Engine $max)
    {
        $compare = $max->compare($min);
        if (!$compare) {
            return $min;
        } elseif ($compare < 0) {
            // if $min is bigger then $max, swap $min and $max
            $temp = $max;
            $max = $min;
            $min = $temp;
        }
        if (!isset(static::$one)) {
            static::$one = new static(1);
        }
        $max = $max->subtract($min->subtract(static::$one));
        $size = strlen(ltrim($max->toBytes(), chr(0)));
        /*
            doing $random % $max doesn't work because some numbers will be more likely to occur than others.
            eg. if $max is 140 and $random's max is 255 then that'd mean both $random = 5 and $random = 145
            would produce 5 whereas the only value of random that could produce 139 would be 139. ie.
            not all numbers would be equally likely. some would be more likely than others.
        
            creating a whole new random number until you find one that is within the range doesn't work
            because, for sufficiently small ranges, the likelihood that you'd get a number within that range
            would be pretty small. eg. with $random's max being 255 and if your $max being 1 the probability
            would be pretty high that $random would be greater than $max.
        
            phpseclib works around this using the technique described here:
        
            http://crypto.stackexchange.com/questions/5708/creating-a-small-number-from-a-cryptographically-secure-random-string
        */
        $random_max = new static(chr(1) . str_repeat("\x00", $size), 256);
        $random = new static(Random::string($size), 256);
        list($max_multiple) = $random_max->divide($max);
        $max_multiple = $max_multiple->multiply($max);
        while ($random->compare($max_multiple) >= 0) {
            $random = $random->subtract($max_multiple);
            $random_max = $random_max->subtract($max_multiple);
            $random = $random->bitwise_leftShift(8);
            $random = $random->add(new static(Random::string(1), 256));
            $random_max = $random_max->bitwise_leftShift(8);
            list($max_multiple) = $random_max->divide($max);
            $max_multiple = $max_multiple->multiply($max);
        }
        list(, $random) = $random->divide($max);
        return $random->add($min);
    }
    /**
     * Performs some post-processing for randomRangePrime
     *
     * @param Engine $x
     * @param Engine $min
     * @param Engine $max
     * @return (bool | Engine)
     */
    protected static function randomRangePrimeInner(Engine $x, Engine $min, Engine $max)
    {
        if (!isset(static::$two)) {
            static::$two = new static('2');
        }
        $x->make_odd();
        if ($x->compare($max) > 0) {
            // if $x > $max then $max is even and if $min == $max then no prime number exists between the specified range
            if ($min->equals($max)) {
                return false;
            }
            $x = clone $min;
            $x->make_odd();
        }
        $initial_x = clone $x;
        while (true) {
            if ($x->isPrime()) {
                return $x;
            }
            $x = $x->add(static::$two);
            if ($x->compare($max) > 0) {
                $x = clone $min;
                if ($x->equals(static::$two)) {
                    return $x;
                }
                $x->make_odd();
            }
            if ($x->equals($initial_x)) {
                return false;
            }
        }
    }
    /**
     * Sets the $t parameter for primality testing
     *
     * @return int
     */
    protected function setupIsPrime()
    {
        $length = $this->getLengthInBytes();
        // see HAC 4.49 "Note (controlling the error probability)"
        // @codingStandardsIgnoreStart
        if ($length >= 163) {
            $t = 2;
        } else {
            if ($length >= 106) {
                $t = 3;
            } else {
                if ($length >= 81) {
                    $t = 4;
                } else {
                    if ($length >= 68) {
                        $t = 5;
                    } else {
                        if ($length >= 56) {
                            $t = 6;
                        } else {
                            if ($length >= 50) {
                                $t = 7;
                            } else {
                                if ($length >= 43) {
                                    $t = 8;
                                } else {
                                    if ($length >= 37) {
                                        $t = 9;
                                    } else {
                                        if ($length >= 31) {
                                            $t = 12;
                                        } else {
                                            if ($length >= 25) {
                                                $t = 15;
                                            } else {
                                                if ($length >= 18) {
                                                    $t = 18;
                                                } else {
                                                    $t = 27;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        // @codingStandardsIgnoreEnd
        return $t;
    }
    /**
    * Tests Primality
    *
    * Uses the {@link http://en.wikipedia.org/wiki/Miller%E2%80%93Rabin_primality_test Miller-Rabin primality test}.
    See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap4.pdf#page=8 HAC 4.24} for more info.
    *
    * @param int $t
    * @return bool
    */
    protected function testPrimality($t)
    {
        if (!$this->testSmallPrimes()) {
            return false;
        }
        $n = clone $this;
        $n_1 = $n->subtract(static::$one);
        $n_2 = $n->subtract(static::$two);
        $r = clone $n_1;
        $s = static::scan1divide($r);
        for ($i = 0; $i < $t; ++$i) {
            $a = static::randomRange(static::$two, $n_2);
            $y = $a->modPow($r, $n);
            if (!$y->equals(static::$one) && !$y->equals($n_1)) {
                for ($j = 1; $j < $s && !$y->equals($n_1); ++$j) {
                    $y = $y->modPow(static::$two, $n);
                    if ($y->equals(static::$one)) {
                        return false;
                    }
                }
                if (!$y->equals($n_1)) {
                    return false;
                }
            }
        }
        return true;
    }
    /**
    * Checks a numer to see if it's prime
    *
    * Assuming the $t parameter is not set, this function has an error rate of 2**-80.  The main motivation for the
    $t parameter is distributability.  BigInteger::randomPrime() can be distributed across multiple pageloads
    on a website instead of just one.
    *
    * @param (int | bool) $t
    * @return bool
    */
    public function isPrime($t = false)
    {
        if (!$t) {
            $t = $this->setupIsPrime();
        }
        return $this->testPrimality($t);
    }
    /**
     * Performs a few preliminary checks on root
     *
     * @param int $n
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    protected function rootHelper($n)
    {
        if ($n < 1) {
            return clone static::$zero;
        }
        // we want positive exponents
        if ($this->compare(static::$one) < 0) {
            return clone static::$zero;
        }
        // we want positive numbers
        if ($this->compare(static::$two) < 0) {
            return clone static::$one;
        }
        // n-th root of 1 or 2 is 1
        return $this->rootInner($n);
    }
    /**
     * Calculates the nth root of a biginteger.
     *
     * Returns the nth root of a positive biginteger, where n defaults to 2
     *
     * {@internal This function is based off of {@link http://mathforum.org/library/drmath/view/52605.html this page} and {@link http://stackoverflow.com/questions/11242920/calculating-nth-root-with-bcmath-in-php this stackoverflow question}.}
     *
     * @param int $n
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    protected function rootInner($n)
    {
        $n = new static($n);
        // g is our guess number
        $g = static::$two;
        // while (g^n < num) g=g*2
        while ($g->pow($n)->compare($this) < 0) {
            $g = $g->multiply(static::$two);
        }
        // if (g^n==num) num is a power of 2, we're lucky, end of job
        // == 0 bccomp(bcpow($g, $n), $n->value)==0
        if ($g->pow($n)->equals($this) > 0) {
            $root = $g;
            return $this->normalize($root);
        }
        // if we're here num wasn't a power of 2 :(
        $og = $g;
        // og means original guess and here is our upper bound
        $g = $g->divide(static::$two)[0];
        // g is set to be our lower bound
        $step = $og->subtract($g)->divide(static::$two)[0];
        // step is the half of upper bound - lower bound
        $g = $g->add($step);
        // we start at lower bound + step , basically in the middle of our interval
        // while step>1
        while ($step->compare(static::$one) == 1) {
            $guess = $g->pow($n);
            $step = $step->divide(static::$two)[0];
            $comp = $guess->compare($this);
            // compare our guess with real number
            switch ($comp) {
                case -1:
                    // if guess is lower we add the new step
                    $g = $g->add($step);
                    break;
                case 1:
                    // if guess is higher we sub the new step
                    $g = $g->subtract($step);
                    break;
                case 0:
                    // if guess is exactly the num we're done, we return the value
                    $root = $g;
                    break 2;
            }
        }
        if ($comp == 1) {
            $g = $g->subtract($step);
        }
        // whatever happened, g is the closest guess we can make so return it
        $root = $g;
        return $this->normalize($root);
    }
    /**
     * Calculates the nth root of a biginteger.
     *
     * @param int $n
     * @return Engine
     */
    public function root($n = 2)
    {
        return $this->rootHelper($n);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param array $nums
     * @return Engine
     */
    protected static function minHelper(array $nums)
    {
        if (count($nums) == 1) {
            return $nums[0];
        }
        $min = $nums[0];
        for ($i = 1; $i < count($nums); $i++) {
            $min = $min->compare($nums[$i]) > 0 ? $nums[$i] : $min;
        }
        return $min;
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param array $nums
     * @return Engine
     */
    protected static function maxHelper(array $nums)
    {
        if (count($nums) == 1) {
            return $nums[0];
        }
        $max = $nums[0];
        for ($i = 1; $i < count($nums); $i++) {
            $max = $max->compare($nums[$i]) < 0 ? $nums[$i] : $max;
        }
        return $max;
    }
    /**
    * Create Recurring Modulo Function
    *
    * Sometimes it may be desirable to do repeated modulos with the same number outside of
    modular exponentiation
    *
    * @return callable
    */
    public function createRecurringModuloFunction()
    {
        $class = static::class;
        $fqengine = !method_exists(static::$modexpEngine, 'reduce') ? '\\phpseclib3\\Math\\BigInteger\\Engines\\' . static::ENGINE_DIR . '\\DefaultEngine' : static::$modexpEngine;
        if (method_exists($fqengine, 'generateCustomReduction')) {
            $func = $fqengine::generateCustomReduction($this, static::class);
            return eval('return function(' . static::class . ' $x) use ($func, $class) {
                $r = new $class();
                $r->value = $func($x->value);
                return $r;
            };');
        }
        $n = $this->value;
        return eval('return function(' . static::class . ' $x) use ($n, $fqengine, $class) {
            $r = new $class();
            $r->value = $fqengine::reduce($x->value, $n, $class);
            return $r;
        };');
    }
    /**
     * Calculates the greatest common divisor and Bezout's identity.
     *
     * @param Engine $n
     * @param Engine $stop (optional)
     * @return Engine
     */
    protected function extendedGCDHelper(Engine $n, Engine $stop = null)
    {
        $u = clone $this;
        $v = clone $n;
        $one = new static(1);
        $zero = new static();
        $a = clone $one;
        $b = clone $zero;
        $c = clone $zero;
        $d = clone $one;
        while (!$v->equals($zero)) {
            list($q) = $u->divide($v);
            $temp = $u;
            $u = $v;
            $v = $temp->subtract($v->multiply($q));
            $temp = $a;
            $a = $c;
            $c = $temp->subtract($a->multiply($q));
            $temp = $b;
            $b = $d;
            $d = $temp->subtract($b->multiply($q));
        }
        return ['gcd' => $u, 'x' => $a, 'y' => $b];
    }
    /**
     * Bitwise Split
     *
     * Splits BigInteger's into chunks of $split bits
     *
     * @param int $split
     * @return \phpseclib3\Math\BigInteger\Engines\Engine[]
     */
    public function bitwise_split($split)
    {
        if ($split < 1) {
            throw new \RuntimeException('Offset must be greater than 1');
        }
        $mask = static::$one->bitwise_leftShift($split)->subtract(static::$one);
        $num = clone $this;
        $vals = [];
        while (!$num->equals(static::$zero)) {
            $vals[] = $num->bitwise_and($mask);
            $num = $num->bitwise_rightShift($split);
        }
        return array_reverse($vals);
    }
    /**
     * Logical And
     *
     * @param Engine $x
     * @return Engine
     */
    protected function bitwiseAndHelper(Engine $x)
    {
        $left = $this->toBytes(true);
        $right = $x->toBytes(true);
        $length = max(strlen($left), strlen($right));
        $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
        $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
        return $this->normalize(new static($left & $right, -256));
    }
    /**
     * Logical Or
     *
     * @param Engine $x
     * @return Engine
     */
    protected function bitwiseOrHelper(Engine $x)
    {
        $left = $this->toBytes(true);
        $right = $x->toBytes(true);
        $length = max(strlen($left), strlen($right));
        $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
        $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
        return $this->normalize(new static($left | $right, -256));
    }
    /**
     * Logical Exclusive Or
     *
     * @param Engine $x
     * @return Engine
     */
    protected function bitwiseXorHelper(Engine $x)
    {
        $left = $this->toBytes(true);
        $right = $x->toBytes(true);
        $length = max(strlen($left), strlen($right));
        $left = str_pad($left, $length, chr(0), STR_PAD_LEFT);
        $right = str_pad($right, $length, chr(0), STR_PAD_LEFT);
        return $this->normalize(new static($left ^ $right, -256));
    }
}<?php

/**
 * Pure-PHP 64-bit BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
/**
 * Pure-PHP 64-bit Engine.
 *
 * Uses 64-bit integers if int size is 8 bits
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class PHP64 extends PHP
{
    // Constants used by PHP.php
    const BASE = 31;
    const BASE_FULL = 0x80000000;
    const MAX_DIGIT = 0x7fffffff;
    const MSB = 0x40000000;
    /**
     * MAX10 in greatest MAX10LEN satisfying
     * MAX10 = 10**MAX10LEN <= 2**BASE.
     */
    const MAX10 = 1000000000;
    /**
     * MAX10LEN in greatest MAX10LEN satisfying
     * MAX10 = 10**MAX10LEN <= 2**BASE.
     */
    const MAX10LEN = 9;
    const MAX_DIGIT2 = 4611686018427387904;
    /**#@-*/
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    protected static $modexpEngine;
    /**
     * Engine Validity Flag
     *
     * @var bool
     */
    protected static $isValidEngine;
    /**
     * Primes > 2 and < 1000
     *
     * @var array
     */
    protected static $primes;
    /**
     * BigInteger(0)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP64
     */
    protected static $zero;
    /**
     * BigInteger(1)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP64
     */
    protected static $one;
    /**
     * BigInteger(2)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\PHP64
     */
    protected static $two;
    /**
     * Initialize a PHP64 BigInteger Engine instance
     *
     * @param int $base
     * @see parent::initialize()
     */
    protected function initialize($base)
    {
        if ($base != 256 && $base != -256) {
            return parent::initialize($base);
        }
        $val = $this->value;
        $this->value = [];
        $vals =& $this->value;
        $i = strlen($val);
        if (!$i) {
            return;
        }
        while (true) {
            $i -= 4;
            if ($i < 0) {
                if ($i == -4) {
                    break;
                }
                $val = \Phabel\Target\Php80\Polyfill::substr($val, 0, 4 + $i);
                $val = str_pad($val, 4, "\x00", STR_PAD_LEFT);
                if ($val == "\x00\x00\x00\x00") {
                    break;
                }
                $i = 0;
            }
            list(, $digit) = unpack('N', \Phabel\Target\Php80\Polyfill::substr($val, $i, 4));
            $step = count($vals) & 7;
            if (!$step) {
                $digit &= static::MAX_DIGIT;
                $i++;
            } else {
                $shift = 8 - $step;
                $digit >>= $shift;
                $shift = 32 - $shift;
                $digit &= (1 << $shift) - 1;
                $temp = $i > 0 ? ord($val[$i - 1]) : 0;
                $digit |= $temp << $shift & 0x7f000000;
            }
            $vals[] = $digit;
        }
        while (end($vals) === 0) {
            array_pop($vals);
        }
        reset($vals);
    }
    /**
     * Test for engine validity
     *
     * @see parent::__construct()
     * @return bool
     */
    public static function isValidEngine()
    {
        return PHP_INT_SIZE >= 8;
    }
    /**
     * Adds two BigIntegers.
     *
     * @param PHP64 $y
     * @return PHP64
     */
    public function add(PHP64 $y)
    {
        $temp = self::addHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param PHP64 $y
     * @return PHP64
     */
    public function subtract(PHP64 $y)
    {
        $temp = self::subtractHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
     * Multiplies two BigIntegers.
     *
     * @param PHP64 $y
     * @return PHP64
     */
    public function multiply(PHP64 $y)
    {
        $temp = self::multiplyHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
        return $this->convertToObj($temp);
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param PHP64 $y
    * @return PHP64
    */
    public function divide(PHP64 $y)
    {
        return $this->divideHelper($y);
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @param PHP64 $n
     * @return (false | PHP64)
     */
    public function modInverse(PHP64 $n)
    {
        return $this->modInverseHelper($n);
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     * @param PHP64 $n
     * @return PHP64[]
     */
    public function extendedGCD(PHP64 $n)
    {
        return $this->extendedGCDHelper($n);
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param PHP64 $n
     * @return PHP64
     */
    public function gcd(PHP64 $n)
    {
        return $this->extendedGCD($n)['gcd'];
    }
    /**
     * Logical And
     *
     * @param PHP64 $x
     * @return PHP64
     */
    public function bitwise_and(PHP64 $x)
    {
        return $this->bitwiseAndHelper($x);
    }
    /**
     * Logical Or
     *
     * @param PHP64 $x
     * @return PHP64
     */
    public function bitwise_or(PHP64 $x)
    {
        return $this->bitwiseOrHelper($x);
    }
    /**
     * Logical Exclusive Or
     *
     * @param PHP64 $x
     * @return PHP64
     */
    public function bitwise_xor(PHP64 $x)
    {
        return $this->bitwiseXorHelper($x);
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param PHP64 $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @access public
    * @see self::equals()
    */
    public function compare(PHP64 $y)
    {
        return parent::compareHelper($this->value, $this->is_negative, $y->value, $y->is_negative);
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param PHP64 $x
     * @return bool
     */
    public function equals(PHP64 $x)
    {
        return $this->value === $x->value && $this->is_negative == $x->is_negative;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param PHP64 $e
     * @param PHP64 $n
     * @return PHP64
     */
    public function modPow(PHP64 $e, PHP64 $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * Alias for modPow().
     *
     * @param PHP64 $e
     * @param PHP64 $n
     * @return PHP64
     */
    public function powMod(PHP64 $e, PHP64 $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param PHP64 $min
     * @param PHP64 $max
     * @return (false | PHP64)
     */
    public static function randomRangePrime(PHP64 $min, PHP64 $max)
    {
        return self::randomRangePrimeOuter($min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param PHP64 $min
    * @param PHP64 $max
    * @return PHP64
    */
    public static function randomRange(PHP64 $min, PHP64 $max)
    {
        return self::randomRangeHelper($min, $max);
    }
    /**
     * Performs exponentiation.
     *
     * @param PHP64 $n
     * @return PHP64
     */
    public function pow(PHP64 $n)
    {
        return $this->powHelper($n);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param PHP64 ...$nums
     * @return PHP64
     */
    public static function min(PHP64 ...$nums)
    {
        return self::minHelper($nums);
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param PHP64 ...$nums
     * @return PHP64
     */
    public static function max(PHP64 ...$nums)
    {
        return self::maxHelper($nums);
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param PHP64 $min
     * @param PHP64 $max
     * @return bool
     */
    public function between(PHP64 $min, PHP64 $max)
    {
        return $this->compare($min) >= 0 && $this->compare($max) <= 0;
    }
}<?php

/**
 * Pure-PHP BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Exception\BadConfigurationException;
/**
 * Pure-PHP Engine.
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PHP extends Engine
{
    /**#@+
     * Array constants
     *
     * Rather than create a thousands and thousands of new BigInteger objects in repeated function calls to add() and
     * multiply() or whatever, we'll just work directly on arrays, taking them in as parameters and returning them.
     *
     * @access protected
     */
    /**
     * $result[self::VALUE] contains the value.
     */
    const VALUE = 0;
    /**
     * $result[self::SIGN] contains the sign.
     */
    const SIGN = 1;
    /**#@-*/
    /**
     * Karatsuba Cutoff
     *
     * At what point do we switch between Karatsuba multiplication and schoolbook long multiplication?
     *
     * @access private
     */
    const KARATSUBA_CUTOFF = 25;
    /**
     * Can Bitwise operations be done fast?
     *
     * @see parent::bitwise_leftRotate()
     * @see parent::bitwise_rightRotate()
     * @access protected
     */
    const FAST_BITWISE = true;
    /**
     * Engine Directory
     *
     * @see parent::setModExpEngine
     * @access protected
     */
    const ENGINE_DIR = 'PHP';
    /**
     * Default constructor
     *
     * @param mixed $x integer Base-10 number or base-$base number if $base set.
     * @param int $base
     * @see parent::__construct()
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    public function __construct($x = 0, $base = 10)
    {
        if (!isset(static::$isValidEngine)) {
            static::$isValidEngine = static::isValidEngine();
        }
        if (!static::$isValidEngine) {
            throw new BadConfigurationException(static::class . ' is not setup correctly on this system');
        }
        $this->value = [];
        parent::__construct($x, $base);
    }
    /**
     * Initialize a PHP BigInteger Engine instance
     *
     * @param int $base
     * @see parent::__construct()
     */
    protected function initialize($base)
    {
        switch (abs($base)) {
            case 16:
                $x = strlen($this->value) & 1 ? '0' . $this->value : $this->value;
                $temp = new static(Hex::decode($x), 256);
                $this->value = $temp->value;
                break;
            case 10:
                $temp = new static();
                $multiplier = new static();
                $multiplier->value = [static::MAX10];
                $x = $this->value;
                if ($x[0] == '-') {
                    $this->is_negative = true;
                    $x = \Phabel\Target\Php80\Polyfill::substr($x, 1);
                }
                $x = str_pad($x, strlen($x) + (static::MAX10LEN - 1) * strlen($x) % static::MAX10LEN, 0, STR_PAD_LEFT);
                while (strlen($x)) {
                    $temp = $temp->multiply($multiplier);
                    $temp = $temp->add(new static($this->int2bytes(\Phabel\Target\Php80\Polyfill::substr($x, 0, static::MAX10LEN)), 256));
                    $x = \Phabel\Target\Php80\Polyfill::substr($x, static::MAX10LEN);
                }
                $this->value = $temp->value;
        }
    }
    /**
     * Pads strings so that unpack may be used on them
     *
     * @param string $str
     * @return string
     */
    protected function pad($str)
    {
        $length = strlen($str);
        $pad = 4 - strlen($str) % 4;
        return str_pad($str, $length + $pad, "\x00", STR_PAD_LEFT);
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function toString()
    {
        if (!count($this->value)) {
            return '0';
        }
        $temp = clone $this;
        $temp->bitmask = false;
        $temp->is_negative = false;
        $divisor = new static();
        $divisor->value = [static::MAX10];
        $result = '';
        while (count($temp->value)) {
            list($temp, $mod) = $temp->divide($divisor);
            $result = str_pad(isset($mod->value[0]) ? $mod->value[0] : '', static::MAX10LEN, '0', STR_PAD_LEFT) . $result;
        }
        $result = ltrim($result, '0');
        if (empty($result)) {
            $result = '0';
        }
        if ($this->is_negative) {
            $result = '-' . $result;
        }
        return $result;
    }
    /**
     * Converts a BigInteger to a byte string (eg. base-256).
     *
     * @param bool $twos_compliment
     * @return string
     */
    public function toBytes($twos_compliment = false)
    {
        if ($twos_compliment) {
            return $this->toBytesHelper();
        }
        if (!count($this->value)) {
            return $this->precision > 0 ? str_repeat(chr(0), $this->precision + 1 >> 3) : '';
        }
        $result = $this->bitwise_small_split(8);
        $result = implode('', array_map('chr', $result));
        return $this->precision > 0 ? str_pad(\Phabel\Target\Php80\Polyfill::substr($result, -($this->precision + 7 >> 3)), $this->precision + 7 >> 3, chr(0), STR_PAD_LEFT) : $result;
    }
    /**
     * Performs addition.
     *
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @return array
     */
    protected static function addHelper(array $x_value, $x_negative, array $y_value, $y_negative)
    {
        $x_size = count($x_value);
        $y_size = count($y_value);
        if ($x_size == 0) {
            return [self::VALUE => $y_value, self::SIGN => $y_negative];
        } elseif ($y_size == 0) {
            return [self::VALUE => $x_value, self::SIGN => $x_negative];
        }
        // subtract, if appropriate
        if ($x_negative != $y_negative) {
            if ($x_value == $y_value) {
                return [self::VALUE => [], self::SIGN => false];
            }
            $temp = self::subtractHelper($x_value, false, $y_value, false);
            $temp[self::SIGN] = self::compareHelper($x_value, false, $y_value, false) > 0 ? $x_negative : $y_negative;
            return $temp;
        }
        if ($x_size < $y_size) {
            $size = $x_size;
            $value = $y_value;
        } else {
            $size = $y_size;
            $value = $x_value;
        }
        $value[count($value)] = 0;
        // just in case the carry adds an extra digit
        $carry = 0;
        for ($i = 0, $j = 1; $j < $size; $i += 2, $j += 2) {
            //$sum = $x_value[$j] * static::BASE_FULL + $x_value[$i] + $y_value[$j] * static::BASE_FULL + $y_value[$i] + $carry;
            $sum = ($x_value[$j] + $y_value[$j]) * static::BASE_FULL + $x_value[$i] + $y_value[$i] + $carry;
            $carry = $sum >= static::MAX_DIGIT2;
            // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
            $sum = $carry ? $sum - static::MAX_DIGIT2 : $sum;
            $temp = static::BASE === 26 ? intval($sum / 0x4000000) : $sum >> 31;
            $value[$i] = (int) ($sum - static::BASE_FULL * $temp);
            // eg. a faster alternative to fmod($sum, 0x4000000)
            $value[$j] = $temp;
        }
        if ($j == $size) {
            // ie. if $y_size is odd
            $sum = $x_value[$i] + $y_value[$i] + $carry;
            $carry = $sum >= static::BASE_FULL;
            $value[$i] = $carry ? $sum - static::BASE_FULL : $sum;
            ++$i;
            // ie. let $i = $j since we've just done $value[$i]
        }
        if ($carry) {
            for (; $value[$i] == static::MAX_DIGIT; ++$i) {
                $value[$i] = 0;
            }
            ++$value[$i];
        }
        return [self::VALUE => self::trim($value), self::SIGN => $x_negative];
    }
    /**
     * Performs subtraction.
     *
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @return array
     */
    static function subtractHelper(array $x_value, $x_negative, array $y_value, $y_negative)
    {
        $x_size = count($x_value);
        $y_size = count($y_value);
        if ($x_size == 0) {
            return [self::VALUE => $y_value, self::SIGN => !$y_negative];
        } elseif ($y_size == 0) {
            return [self::VALUE => $x_value, self::SIGN => $x_negative];
        }
        // add, if appropriate (ie. -$x - +$y or +$x - -$y)
        if ($x_negative != $y_negative) {
            $temp = self::addHelper($x_value, false, $y_value, false);
            $temp[self::SIGN] = $x_negative;
            return $temp;
        }
        $diff = self::compareHelper($x_value, $x_negative, $y_value, $y_negative);
        if (!$diff) {
            return [self::VALUE => [], self::SIGN => false];
        }
        // switch $x and $y around, if appropriate.
        if (!$x_negative && $diff < 0 || $x_negative && $diff > 0) {
            $temp = $x_value;
            $x_value = $y_value;
            $y_value = $temp;
            $x_negative = !$x_negative;
            $x_size = count($x_value);
            $y_size = count($y_value);
        }
        // at this point, $x_value should be at least as big as - if not bigger than - $y_value
        $carry = 0;
        for ($i = 0, $j = 1; $j < $y_size; $i += 2, $j += 2) {
            $sum = ($x_value[$j] - $y_value[$j]) * static::BASE_FULL + $x_value[$i] - $y_value[$i] - $carry;
            $carry = $sum < 0;
            // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
            $sum = $carry ? $sum + static::MAX_DIGIT2 : $sum;
            $temp = static::BASE === 26 ? intval($sum / 0x4000000) : $sum >> 31;
            $x_value[$i] = (int) ($sum - static::BASE_FULL * $temp);
            $x_value[$j] = $temp;
        }
        if ($j == $y_size) {
            // ie. if $y_size is odd
            $sum = $x_value[$i] - $y_value[$i] - $carry;
            $carry = $sum < 0;
            $x_value[$i] = $carry ? $sum + static::BASE_FULL : $sum;
            ++$i;
        }
        if ($carry) {
            for (; !$x_value[$i]; ++$i) {
                $x_value[$i] = static::MAX_DIGIT;
            }
            --$x_value[$i];
        }
        return [self::VALUE => self::trim($x_value), self::SIGN => $x_negative];
    }
    /**
     * Performs multiplication.
     *
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @return array
     */
    protected static function multiplyHelper(array $x_value, $x_negative, array $y_value, $y_negative)
    {
        //if ( $x_value == $y_value ) {
        //    return [
        //        self::VALUE => self::square($x_value),
        //        self::SIGN => $x_sign != $y_value
        //    ];
        //}
        $x_length = count($x_value);
        $y_length = count($y_value);
        if (!$x_length || !$y_length) {
            // a 0 is being multiplied
            return [self::VALUE => [], self::SIGN => false];
        }
        return [self::VALUE => min($x_length, $y_length) < 2 * self::KARATSUBA_CUTOFF ? self::trim(self::regularMultiply($x_value, $y_value)) : self::trim(self::karatsuba($x_value, $y_value)), self::SIGN => $x_negative != $y_negative];
    }
    /**
    * Performs Karatsuba multiplication on two BigIntegers
    *
    * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=120 MPM 5.2.3}.
    *
    * @param array $x_value
    * @param array $y_value
    * @return array
    */
    private static function karatsuba(array $x_value, array $y_value)
    {
        $m = min(count($x_value) >> 1, count($y_value) >> 1);
        if ($m < self::KARATSUBA_CUTOFF) {
            return self::regularMultiply($x_value, $y_value);
        }
        $x1 = array_slice($x_value, $m);
        $x0 = array_slice($x_value, 0, $m);
        $y1 = array_slice($y_value, $m);
        $y0 = array_slice($y_value, 0, $m);
        $z2 = self::karatsuba($x1, $y1);
        $z0 = self::karatsuba($x0, $y0);
        $z1 = self::addHelper($x1, false, $x0, false);
        $temp = self::addHelper($y1, false, $y0, false);
        $z1 = self::karatsuba($z1[self::VALUE], $temp[self::VALUE]);
        $temp = self::addHelper($z2, false, $z0, false);
        $z1 = self::subtractHelper($z1, false, $temp[self::VALUE], false);
        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
        $xy = self::addHelper($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
        $xy = self::addHelper($xy[self::VALUE], $xy[self::SIGN], $z0, false);
        return $xy[self::VALUE];
    }
    /**
     * Performs long multiplication on two BigIntegers
     *
     * Modeled after 'multiply' in MutableBigInteger.java.
     *
     * @param array $x_value
     * @param array $y_value
     * @return array
     */
    protected static function regularMultiply(array $x_value, array $y_value)
    {
        $x_length = count($x_value);
        $y_length = count($y_value);
        if (!$x_length || !$y_length) {
            // a 0 is being multiplied
            return [];
        }
        $product_value = self::array_repeat(0, $x_length + $y_length);
        // the following for loop could be removed if the for loop following it
        // (the one with nested for loops) initially set $i to 0, but
        // doing so would also make the result in one set of unnecessary adds,
        // since on the outermost loops first pass, $product->value[$k] is going
        // to always be 0
        $carry = 0;
        for ($j = 0; $j < $x_length; ++$j) {
            // ie. $i = 0
            $temp = $x_value[$j] * $y_value[0] + $carry;
            // $product_value[$k] == 0
            $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
            $product_value[$j] = (int) ($temp - static::BASE_FULL * $carry);
        }
        $product_value[$j] = $carry;
        // the above for loop is what the previous comment was talking about.  the
        // following for loop is the "one with nested for loops"
        for ($i = 1; $i < $y_length; ++$i) {
            $carry = 0;
            for ($j = 0, $k = $i; $j < $x_length; ++$j, ++$k) {
                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
                $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
                $product_value[$k] = (int) ($temp - static::BASE_FULL * $carry);
            }
            $product_value[$k] = $carry;
        }
        return $product_value;
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param \phpseclib3\Math\BigInteger\engines\PHP $y
    * @return array
    * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}.
    */
    protected function divideHelper(PHP $y)
    {
        if (count($y->value) == 1) {
            list($q, $r) = $this->divide_digit($this->value, $y->value[0]);
            $quotient = new static();
            $remainder = new static();
            $quotient->value = $q;
            $remainder->value = [$r];
            $quotient->is_negative = $this->is_negative != $y->is_negative;
            return [$this->normalize($quotient), $this->normalize($remainder)];
        }
        $x = clone $this;
        $y = clone $y;
        $x_sign = $x->is_negative;
        $y_sign = $y->is_negative;
        $x->is_negative = $y->is_negative = false;
        $diff = $x->compare($y);
        if (!$diff) {
            $temp = new static();
            $temp->value = [1];
            $temp->is_negative = $x_sign != $y_sign;
            return [$this->normalize($temp), $this->normalize(static::$zero)];
        }
        if ($diff < 0) {
            // if $x is negative, "add" $y.
            if ($x_sign) {
                $x = $y->subtract($x);
            }
            return [$this->normalize(static::$zero), $this->normalize($x)];
        }
        // normalize $x and $y as described in HAC 14.23 / 14.24
        $msb = $y->value[count($y->value) - 1];
        for ($shift = 0; !($msb & static::MSB); ++$shift) {
            $msb <<= 1;
        }
        $x->lshift($shift);
        $y->lshift($shift);
        $y_value =& $y->value;
        $x_max = count($x->value) - 1;
        $y_max = count($y->value) - 1;
        $quotient = new static();
        $quotient_value =& $quotient->value;
        $quotient_value = self::array_repeat(0, $x_max - $y_max + 1);
        static $temp, $lhs, $rhs;
        if (!isset($temp)) {
            $temp = new static();
            $lhs = new static();
            $rhs = new static();
        }
        $temp_value =& $temp->value;
        $rhs_value =& $rhs->value;
        // $temp = $y << ($x_max - $y_max-1) in base 2**26
        $temp_value = array_merge(self::array_repeat(0, $x_max - $y_max), $y_value);
        while ($x->compare($temp) >= 0) {
            // calculate the "common residue"
            ++$quotient_value[$x_max - $y_max];
            $x = $x->subtract($temp);
            $x_max = count($x->value) - 1;
        }
        for ($i = $x_max; $i >= $y_max + 1; --$i) {
            $x_value =& $x->value;
            $x_window = [isset($x_value[$i]) ? $x_value[$i] : 0, isset($x_value[$i - 1]) ? $x_value[$i - 1] : 0, isset($x_value[$i - 2]) ? $x_value[$i - 2] : 0];
            $y_window = [$y_value[$y_max], $y_max > 0 ? $y_value[$y_max - 1] : 0];
            $q_index = $i - $y_max - 1;
            if ($x_window[0] == $y_window[0]) {
                $quotient_value[$q_index] = static::MAX_DIGIT;
            } else {
                $quotient_value[$q_index] = self::safe_divide($x_window[0] * static::BASE_FULL + $x_window[1], $y_window[0]);
            }
            $temp_value = [$y_window[1], $y_window[0]];
            $lhs->value = [$quotient_value[$q_index]];
            $lhs = $lhs->multiply($temp);
            $rhs_value = [$x_window[2], $x_window[1], $x_window[0]];
            while ($lhs->compare($rhs) > 0) {
                --$quotient_value[$q_index];
                $lhs->value = [$quotient_value[$q_index]];
                $lhs = $lhs->multiply($temp);
            }
            $adjust = self::array_repeat(0, $q_index);
            $temp_value = [$quotient_value[$q_index]];
            $temp = $temp->multiply($y);
            $temp_value =& $temp->value;
            if (count($temp_value)) {
                $temp_value = array_merge($adjust, $temp_value);
            }
            $x = $x->subtract($temp);
            if ($x->compare(static::$zero) < 0) {
                $temp_value = array_merge($adjust, $y_value);
                $x = $x->add($temp);
                --$quotient_value[$q_index];
            }
            $x_max = count($x_value) - 1;
        }
        // unnormalize the remainder
        $x->rshift($shift);
        $quotient->is_negative = $x_sign != $y_sign;
        // calculate the "common residue", if appropriate
        if ($x_sign) {
            $y->rshift($shift);
            $x = $y->subtract($x);
        }
        return [$this->normalize($quotient), $this->normalize($x)];
    }
    /**
     * Divides a BigInteger by a regular integer
     *
     * abc / x = a00 / x + b0 / x + c / x
     *
     * @param array $dividend
     * @param int $divisor
     * @return array
     */
    private static function divide_digit(array $dividend, $divisor)
    {
        $carry = 0;
        $result = [];
        for ($i = count($dividend) - 1; $i >= 0; --$i) {
            $temp = static::BASE_FULL * $carry + $dividend[$i];
            $result[$i] = self::safe_divide($temp, $divisor);
            $carry = (int) ($temp - $divisor * $result[$i]);
        }
        return [$result, $carry];
    }
    /**
    * Single digit division
    *
    * Even if int64 is being used the division operator will return a float64 value
    if the dividend is not evenly divisible by the divisor. Since a float64 doesn't
    have the precision of int64 this is a problem so, when int64 is being used,
    we'll guarantee that the dividend is divisible by first subtracting the remainder.
    *
    * @param int $x
    * @param int $y
    * @return int
    */
    private static function safe_divide($x, $y)
    {
        if (static::BASE === 26) {
            return (int) ($x / $y);
        }
        // static::BASE === 31
        return ($x - $x % $y) / $y;
    }
    /*
     * Convert an array / boolean to a PHP BigInteger object
     *
     * @param array $arr
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    /**
     *
     */
    protected function convertToObj(array $arr)
    {
        $result = new static();
        $result->value = $arr[self::VALUE];
        $result->is_negative = $arr[self::SIGN];
        return $this->normalize($result);
    }
    /**
     * Normalize
     *
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
     *
     * @param PHP $result
     * @return PHP
     */
    protected function normalize(PHP $result)
    {
        $result->precision = $this->precision;
        $result->bitmask = $this->bitmask;
        $value =& $result->value;
        if (!count($value)) {
            $result->is_negative = false;
            return $result;
        }
        $value = static::trim($value);
        if (!empty($result->bitmask->value)) {
            $length = min(count($value), count($result->bitmask->value));
            $value = array_slice($value, 0, $length);
            for ($i = 0; $i < $length; ++$i) {
                $value[$i] = $value[$i] & $result->bitmask->value[$i];
            }
        }
        return $result;
    }
    /*
     * Compares two numbers.
     *
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @return int
     * @see static::compare()
     */
    /**
     *
     */
    protected static function compareHelper(array $x_value, $x_negative, array $y_value, $y_negative)
    {
        if ($x_negative != $y_negative) {
            return !$x_negative && $y_negative ? 1 : -1;
        }
        $result = $x_negative ? -1 : 1;
        if (count($x_value) != count($y_value)) {
            return count($x_value) > count($y_value) ? $result : -$result;
        }
        $size = max(count($x_value), count($y_value));
        $x_value = array_pad($x_value, $size, 0);
        $y_value = array_pad($y_value, $size, 0);
        for ($i = count($x_value) - 1; $i >= 0; --$i) {
            if ($x_value[$i] != $y_value[$i]) {
                return $x_value[$i] > $y_value[$i] ? $result : -$result;
            }
        }
        return 0;
    }
    /**
     * Absolute value.
     *
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    public function abs()
    {
        $temp = new static();
        $temp->value = $this->value;
        return $temp;
    }
    /**
     * Trim
     *
     * Removes leading zeros
     *
     * @param array $value
     * @return PHP
     */
    protected static function trim(array $value)
    {
        for ($i = count($value) - 1; $i >= 0; --$i) {
            if ($value[$i]) {
                break;
            }
            unset($value[$i]);
        }
        return $value;
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    public function bitwise_rightShift($shift)
    {
        $temp = new static();
        // could just replace lshift with this, but then all lshift() calls would need to be rewritten
        // and I don't want to do that...
        $temp->value = $this->value;
        $temp->rshift($shift);
        return $this->normalize($temp);
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\PHP
     */
    public function bitwise_leftShift($shift)
    {
        $temp = new static();
        // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten
        // and I don't want to do that...
        $temp->value = $this->value;
        $temp->lshift($shift);
        return $this->normalize($temp);
    }
    /**
     * Converts 32-bit integers to bytes.
     *
     * @param int $x
     * @return string
     */
    private static function int2bytes($x)
    {
        return ltrim(pack('N', $x), chr(0));
    }
    /**
     * Array Repeat
     *
     * @param int $input
     * @param int $multiplier
     * @return array
     */
    protected static function array_repeat($input, $multiplier)
    {
        return $multiplier ? array_fill(0, $multiplier, $input) : [];
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits.
     *
     * @param int $shift
     */
    protected function lshift($shift)
    {
        if ($shift == 0) {
            return;
        }
        $num_digits = (int) ($shift / static::BASE);
        $shift %= static::BASE;
        $shift = 1 << $shift;
        $carry = 0;
        for ($i = 0; $i < count($this->value); ++$i) {
            $temp = $this->value[$i] * $shift + $carry;
            $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
            $this->value[$i] = (int) ($temp - $carry * static::BASE_FULL);
        }
        if ($carry) {
            $this->value[count($this->value)] = $carry;
        }
        while ($num_digits--) {
            array_unshift($this->value, 0);
        }
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits.
     *
     * @param int $shift
     */
    protected function rshift($shift)
    {
        if ($shift == 0) {
            return;
        }
        $num_digits = (int) ($shift / static::BASE);
        $shift %= static::BASE;
        $carry_shift = static::BASE - $shift;
        $carry_mask = (1 << $shift) - 1;
        if ($num_digits) {
            $this->value = array_slice($this->value, $num_digits);
        }
        $carry = 0;
        for ($i = count($this->value) - 1; $i >= 0; --$i) {
            $temp = $this->value[$i] >> $shift | $carry;
            $carry = ($this->value[$i] & $carry_mask) << $carry_shift;
            $this->value[$i] = $temp;
        }
        $this->value = static::trim($this->value);
    }
    /**
     * Performs modular exponentiation.
     *
     * @param PHP $e
     * @param PHP $n
     * @return PHP
     */
    protected function powModInner(PHP $e, PHP $n)
    {
        try {
            $class = static::$modexpEngine;
            return $class::powModHelper($this, $e, $n, static::class);
        } catch (\Exception $err) {
            return PHP\DefaultEngine::powModHelper($this, $e, $n, static::class);
        }
    }
    /**
     * Performs squaring
     *
     * @param array $x
     * @return array
     */
    protected static function square(array $x)
    {
        return count($x) < 2 * self::KARATSUBA_CUTOFF ? self::trim(self::baseSquare($x)) : self::trim(self::karatsubaSquare($x));
    }
    /**
    * Performs traditional squaring on two BigIntegers
    *
    * Squaring can be done faster than multiplying a number by itself can be.  See
    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
    *
    * @param array $value
    * @return array
    */
    protected static function baseSquare(array $value)
    {
        if (empty($value)) {
            return [];
        }
        $square_value = self::array_repeat(0, 2 * count($value));
        for ($i = 0, $max_index = count($value) - 1; $i <= $max_index; ++$i) {
            $i2 = $i << 1;
            $temp = $square_value[$i2] + $value[$i] * $value[$i];
            $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
            $square_value[$i2] = (int) ($temp - static::BASE_FULL * $carry);
            // note how we start from $i+1 instead of 0 as we do in multiplication.
            for ($j = $i + 1, $k = $i2 + 1; $j <= $max_index; ++$j, ++$k) {
                $temp = $square_value[$k] + 2 * $value[$j] * $value[$i] + $carry;
                $carry = static::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
                $square_value[$k] = (int) ($temp - static::BASE_FULL * $carry);
            }
            // the following line can yield values larger 2**15.  at this point, PHP should switch
            // over to floats.
            $square_value[$i + $max_index + 1] = $carry;
        }
        return $square_value;
    }
    /**
    * Performs Karatsuba "squaring" on two BigIntegers
    *
    * See {@link http://en.wikipedia.org/wiki/Karatsuba_algorithm Karatsuba algorithm} and
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=151 MPM 5.3.4}.
    *
    * @param array $value
    * @return array
    */
    protected static function karatsubaSquare(array $value)
    {
        $m = count($value) >> 1;
        if ($m < self::KARATSUBA_CUTOFF) {
            return self::baseSquare($value);
        }
        $x1 = array_slice($value, $m);
        $x0 = array_slice($value, 0, $m);
        $z2 = self::karatsubaSquare($x1);
        $z0 = self::karatsubaSquare($x0);
        $z1 = self::addHelper($x1, false, $x0, false);
        $z1 = self::karatsubaSquare($z1[self::VALUE]);
        $temp = self::addHelper($z2, false, $z0, false);
        $z1 = self::subtractHelper($z1, false, $temp[self::VALUE], false);
        $z2 = array_merge(array_fill(0, 2 * $m, 0), $z2);
        $z1[self::VALUE] = array_merge(array_fill(0, $m, 0), $z1[self::VALUE]);
        $xx = self::addHelper($z2, false, $z1[self::VALUE], $z1[self::SIGN]);
        $xx = self::addHelper($xx[self::VALUE], $xx[self::SIGN], $z0, false);
        return $xx[self::VALUE];
    }
    /**
     * Make the current number odd
     *
     * If the current number is odd it'll be unchanged.  If it's even, one will be added to it.
     *
     * @see self::randomPrime()
     */
    protected function make_odd()
    {
        $this->value[0] |= 1;
    }
    /**
     * Test the number against small primes.
     *
     * @see self::isPrime()
     */
    protected function testSmallPrimes()
    {
        if ($this->value == [1]) {
            return false;
        }
        if ($this->value == [2]) {
            return true;
        }
        if (~$this->value[0] & 1) {
            return false;
        }
        $value = $this->value;
        foreach (static::$primes as $prime) {
            list(, $r) = self::divide_digit($value, $prime);
            if (!$r) {
                return count($value) == 1 && $value[0] == $prime;
            }
        }
        return true;
    }
    /**
     * Scan for 1 and right shift by that amount
     *
     * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
     *
     * @see self::isPrime()
     * @param PHP $r
     * @return int
     */
    public static function scan1divide(PHP $r)
    {
        $r_value =& $r->value;
        for ($i = 0, $r_length = count($r_value); $i < $r_length; ++$i) {
            $temp = ~$r_value[$i] & static::MAX_DIGIT;
            for ($j = 1; $temp >> $j & 1; ++$j) {
            }
            if ($j <= static::BASE) {
                break;
            }
        }
        $s = static::BASE * $i + $j;
        $r->rshift($s);
        return $s;
    }
    /**
     * Performs exponentiation.
     *
     * @param PHP $n
     * @return PHP
     */
    protected function powHelper(PHP $n)
    {
        if ($n->compare(static::$zero) == 0) {
            return new static(1);
        }
        // n^0 = 1
        $temp = clone $this;
        while (!$n->equals(static::$one)) {
            $temp = $temp->multiply($this);
            $n = $n->subtract(static::$one);
        }
        return $temp;
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return (bool) ($this->value[0] & 1);
    }
    /**
     * Tests if a bit is set
     *
     * @return boolean
     */
    public function testBit($x)
    {
        $digit = floor($x / static::BASE);
        $bit = $x % static::BASE;
        if (!isset($this->value[$digit])) {
            return false;
        }
        return (bool) ($this->value[$digit] & 1 << $bit);
    }
    /**
     * Is Negative?
     *
     * @return boolean
     */
    public function isNegative()
    {
        return $this->is_negative;
    }
    /**
     * Negate
     *
     * Given $k, returns -$k
     *
     * @return BigInteger
     */
    public function negate()
    {
        $temp = clone $this;
        $temp->is_negative = !$temp->is_negative;
        return $temp;
    }
    /**
     * Bitwise Split
     *
     * Splits BigInteger's into chunks of $split bits
     *
     * @param int $split
     * @return \phpseclib3\Math\BigInteger\Engines\PHP[]
     */
    public function bitwise_split($split)
    {
        if ($split < 1) {
            throw new \RuntimeException('Offset must be greater than 1');
        }
        $width = (int) ($split / static::BASE);
        if (!$width) {
            $arr = $this->bitwise_small_split($split);
            return array_map(function ($digit) {
                $temp = new static();
                $temp->value = $digit != 0 ? [$digit] : [];
                return $temp;
            }, $arr);
        }
        $vals = [];
        $val = $this->value;
        $i = $overflow = 0;
        $len = count($val);
        while ($i < $len) {
            $digit = [];
            if (!$overflow) {
                $digit = array_slice($val, $i, $width);
                $i += $width;
                $overflow = $split % static::BASE;
                if ($overflow) {
                    $mask = (1 << $overflow) - 1;
                    $temp = isset($val[$i]) ? $val[$i] : 0;
                    $digit[] = $temp & $mask;
                }
            } else {
                $remaining = static::BASE - $overflow;
                $tempsplit = $split - $remaining;
                $tempwidth = (int) ($tempsplit / static::BASE + 1);
                $digit = array_slice($val, $i, $tempwidth);
                $i += $tempwidth;
                $tempoverflow = $tempsplit % static::BASE;
                if ($tempoverflow) {
                    $tempmask = (1 << $tempoverflow) - 1;
                    $temp = isset($val[$i]) ? $val[$i] : 0;
                    $digit[] = $temp & $tempmask;
                }
                $newbits = 0;
                for ($j = count($digit) - 1; $j >= 0; $j--) {
                    $temp = $digit[$j] & $mask;
                    $digit[$j] = $digit[$j] >> $overflow | $newbits << $remaining;
                    $newbits = $temp;
                }
                $overflow = $tempoverflow;
                $mask = $tempmask;
            }
            $temp = new static();
            $temp->value = static::trim($digit);
            $vals[] = $temp;
        }
        return array_reverse($vals);
    }
    /**
     * Bitwise Split where $split < static::BASE
     *
     * @param int $split
     * @return \phpseclib3\Math\BigInteger\Engines\PHP[]
     */
    private function bitwise_small_split($split)
    {
        $vals = [];
        $val = $this->value;
        $mask = (1 << $split) - 1;
        $i = $overflow = 0;
        $len = count($val);
        $val[] = 0;
        $remaining = static::BASE;
        while ($i != $len) {
            $digit = $val[$i] & $mask;
            $val[$i] >>= $split;
            if (!$overflow) {
                $remaining -= $split;
                $overflow = $split <= $remaining ? 0 : $split - $remaining;
                if (!$remaining) {
                    $i++;
                    $remaining = static::BASE;
                    $overflow = 0;
                }
            } else {
                if (++$i != $len) {
                    $tempmask = (1 << $overflow) - 1;
                    $digit |= ($val[$i] & $tempmask) << $remaining;
                    $val[$i] >>= $overflow;
                    $remaining = static::BASE - $overflow;
                    $overflow = $split <= $remaining ? 0 : $split - $remaining;
                }
            }
            $vals[] = $digit;
        }
        while ($vals[count($vals) - 1] == 0) {
            unset($vals[count($vals) - 1]);
        }
        return array_reverse($vals);
    }
}<?php

/**
 * OpenSSL Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP;

use phpseclib3\Math\BigInteger\Engines\OpenSSL as Progenitor;
/**
 * OpenSSL Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSL extends Progenitor
{
}<?php

/**
 * PHP Montgomery Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP;

use phpseclib3\Math\BigInteger\Engines\PHP\Reductions\PowerOfTwo;
use phpseclib3\Math\BigInteger\Engines\PHP;
use phpseclib3\Math\BigInteger\Engines\PHP\Base;
use phpseclib3\Math\BigInteger\Engines\Engine;
/**
 * PHP Montgomery Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Montgomery extends Base
{
    /**
     * Test for engine validity
     *
     * @return bool
     */
    public static function isValidEngine()
    {
        return static::class != __CLASS__;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param \phpseclib3\Math\BigInteger\Engines\Engine $x
     * @param \phpseclib3\Math\BigInteger\Engines\Engine $e
     * @param \phpseclib3\Math\BigInteger\Engines\Engine $n
     * @param string $class
     * @return \phpseclib3\Math\BigInteger\Engines\Engine
     */
    protected static function slidingWindow(Engine $x, Engine $e, Engine $n, $class)
    {
        // is the modulo odd?
        if ($n->value[0] & 1) {
            return parent::slidingWindow($x, $e, $n, $class);
        }
        // if it's not, it's even
        // find the lowest set bit (eg. the max pow of 2 that divides $n)
        for ($i = 0; $i < count($n->value); ++$i) {
            if ($n->value[$i]) {
                $temp = decbin($n->value[$i]);
                $j = strlen($temp) - strrpos($temp, '1') - 1;
                $j += $class::BASE * $i;
                break;
            }
        }
        // at this point, 2^$j * $n/(2^$j) == $n
        $mod1 = clone $n;
        $mod1->rshift($j);
        $mod2 = new $class();
        $mod2->value = [1];
        $mod2->lshift($j);
        $part1 = $mod1->value != [1] ? parent::slidingWindow($x, $e, $mod1, $class) : new $class();
        $part2 = PowerOfTwo::slidingWindow($x, $e, $mod2, $class);
        $y1 = $mod2->modInverse($mod1);
        $y2 = $mod1->modInverse($mod2);
        $result = $part1->multiply($mod2);
        $result = $result->multiply($y1);
        $temp = $part2->multiply($mod1);
        $temp = $temp->multiply($y2);
        $result = $result->add($temp);
        list(, $result) = $result->divide($n);
        return $result;
    }
}<?php

/**
 * PHP Power of Two Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
/**
 * PHP Power Of Two Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class PowerOfTwo extends Base
{
    /**
     * Prepare a number for use in Montgomery Modular Reductions
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @return array
     */
    protected static function prepareReduce(array $x, array $n, $class)
    {
        return self::reduce($x, $n, $class);
    }
    /**
     * Power Of Two Reduction
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @return array
     */
    protected static function reduce(array $x, array $n, $class)
    {
        $lhs = new $class();
        $lhs->value = $x;
        $rhs = new $class();
        $rhs->value = $n;
        $temp = new $class();
        $temp->value = [1];
        $result = $lhs->bitwise_and($rhs->subtract($temp));
        return $result->value;
    }
}<?php

/**
 * PHP Montgomery Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Montgomery as Progenitor;
/**
 * PHP Montgomery Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Montgomery extends Progenitor
{
    /**
     * Prepare a number for use in Montgomery Modular Reductions
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @return array
     */
    protected static function prepareReduce(array $x, array $n, $class)
    {
        $lhs = new $class();
        $lhs->value = array_merge(self::array_repeat(0, count($n)), $x);
        $rhs = new $class();
        $rhs->value = $n;
        list(, $temp) = $lhs->divide($rhs);
        return $temp->value;
    }
    /**
    * Montgomery Multiply
    *
    * Interleaves the montgomery reduction and long multiplication algorithms together as described in
    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
    *
    * @param array $x
    * @param array $n
    * @param string $class
    * @return array
    */
    protected static function reduce(array $x, array $n, $class)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $x;
            $cache[self::DATA][] = self::modInverse67108864($n, $class);
        }
        $k = count($n);
        $result = [self::VALUE => $x];
        for ($i = 0; $i < $k; ++$i) {
            $temp = $result[self::VALUE][$i] * $cache[self::DATA][$key];
            $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31);
            $temp = $class::regularMultiply([$temp], $n);
            $temp = array_merge(self::array_repeat(0, $i), $temp);
            $result = $class::addHelper($result[self::VALUE], false, $temp, false);
        }
        $result[self::VALUE] = array_slice($result[self::VALUE], $k);
        if (self::compareHelper($result, false, $n, false) >= 0) {
            $result = $class::subtractHelper($result[self::VALUE], false, $n, false);
        }
        return $result[self::VALUE];
    }
    /**
    * Modular Inverse of a number mod 2**26 (eg. 67108864)
    *
    * Based off of the bnpInvDigit function implemented and justified in the following URL:
    *
    * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
    *
    * The following URL provides more info:
    *
    * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
    *
    * As for why we do all the bitmasking...  strange things can happen when converting from floats to ints. For
    instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
    int(-2147483648).  To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
    auto-converted to floats.  The outermost bitmask is present because without it, there's no guarantee that
    the "residue" returned would be the so-called "common residue".  We use fmod, in the last step, because the
    maximum possible $x is 26 bits and the maximum $result is 16 bits.  Thus, we have to be able to handle up to
    40 bits, which only 64-bit floating points will support.
    *
    * Thanks to Pedro Gimeno Fortea for input!
    *
    * @param array $x
    * @param string $class
    * @return int
    */
    protected static function modInverse67108864(array $x, $class)
    {
        $x = -$x[0];
        $result = $x & 0x3;
        // x**-1 mod 2**2
        $result = $result * (2 - $x * $result) & 0xf;
        // x**-1 mod 2**4
        $result = $result * (2 - ($x & 0xff) * $result) & 0xff;
        // x**-1 mod 2**8
        $result = $result * (2 - ($x & 0xffff) * $result & 0xffff) & 0xffff;
        // x**-1 mod 2**16
        $result = $class::BASE == 26 ? fmod($result * (2 - fmod($x * $result, $class::BASE_FULL)), $class::BASE_FULL) : $result * (2 - $x * $result % $class::BASE_FULL) % $class::BASE_FULL;
        return $result & $class::MAX_DIGIT;
    }
}<?php

/**
 * PHP Barrett Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
/**
 * PHP Barrett Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Barrett extends Base
{
    /**
    * Barrett Modular Reduction
    *
    * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information.  Modified slightly,
    so as not to require negative numbers (initially, this script didn't support negative numbers).
    *
    * Employs "folding", as described at
    {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}.  To quote from
    it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
    *
    * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
    usable on account of (1) its not using reasonable radix points as discussed in
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
    radix points, it only works when there are an even number of digits in the denominator.  The reason for (2) is that
    (x >> 1) + (x >> 1) != x / 2 + x / 2.  If x is even, they're the same, but if x is odd, they're not.  See the in-line
    comments for details.
    *
    * @param array $n
    * @param array $m
    * @param string $class
    * @return array
    */
    protected static function reduce(array $n, array $m, $class)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        $m_length = count($m);
        // if (self::compareHelper($n, $static::square($m)) >= 0) {
        if (count($n) > 2 * $m_length) {
            $lhs = new $class();
            $rhs = new $class();
            $lhs->value = $n;
            $rhs->value = $m;
            list(, $temp) = $lhs->divide($rhs);
            return $temp->value;
        }
        // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
        if ($m_length < 5) {
            return self::regularBarrett($n, $m, $class);
        }
        // n = 2 * m.length
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $m;
            $lhs = new $class();
            $lhs_value =& $lhs->value;
            $lhs_value = self::array_repeat(0, $m_length + ($m_length >> 1));
            $lhs_value[] = 1;
            $rhs = new $class();
            $rhs->value = $m;
            list($u, $m1) = $lhs->divide($rhs);
            $u = $u->value;
            $m1 = $m1->value;
            $cache[self::DATA][] = [
                'u' => $u,
                // m.length >> 1 (technically (m.length >> 1) + 1)
                'm1' => $m1,
            ];
        } else {
            extract($cache[self::DATA][$key]);
        }
        $cutoff = $m_length + ($m_length >> 1);
        $lsd = array_slice($n, 0, $cutoff);
        // m.length + (m.length >> 1)
        $msd = array_slice($n, $cutoff);
        // m.length >> 1
        $lsd = self::trim($lsd);
        $temp = $class::multiplyHelper($msd, false, $m1, false);
        // m.length + (m.length >> 1)
        $n = $class::addHelper($lsd, false, $temp[self::VALUE], false);
        // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers)
        //if ($m_length & 1) {
        //    return self::regularBarrett($n[self::VALUE], $m, $class);
        //}
        // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
        $temp = array_slice($n[self::VALUE], $m_length - 1);
        // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
        // if odd:  ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
        $temp = $class::multiplyHelper($temp, false, $u, false);
        // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
        // if odd:  (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
        $temp = array_slice($temp[self::VALUE], ($m_length >> 1) + 1);
        // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
        // if odd:  (m.length - (m.length >> 1)) + m.length     = 2 * m.length - (m.length >> 1)
        $temp = $class::multiplyHelper($temp, false, $m, false);
        // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
        // number from a m.length + (m.length >> 1) + 1 digit number.  ie. there'd be an extra digit and the while loop
        // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
        $result = $class::subtractHelper($n[self::VALUE], false, $temp[self::VALUE], false);
        while (self::compareHelper($result[self::VALUE], $result[self::SIGN], $m, false) >= 0) {
            $result = $class::subtractHelper($result[self::VALUE], $result[self::SIGN], $m, false);
        }
        return $result[self::VALUE];
    }
    /**
    * (Regular) Barrett Modular Reduction
    *
    * For numbers with more than four digits BigInteger::_barrett() is faster.  The difference between that and this
    is that this function does not fold the denominator into a smaller form.
    *
    * @param array $x
    * @param array $n
    * @param string $class
    * @return array
    */
    private static function regularBarrett(array $x, array $n, $class)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        $n_length = count($n);
        if (count($x) > 2 * $n_length) {
            $lhs = new $class();
            $rhs = new $class();
            $lhs->value = $x;
            $rhs->value = $n;
            list(, $temp) = $lhs->divide($rhs);
            return $temp->value;
        }
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $n;
            $lhs = new $class();
            $lhs_value =& $lhs->value;
            $lhs_value = self::array_repeat(0, 2 * $n_length);
            $lhs_value[] = 1;
            $rhs = new $class();
            $rhs->value = $n;
            list($temp, ) = $lhs->divide($rhs);
            // m.length
            $cache[self::DATA][] = $temp->value;
        }
        // 2 * m.length - (m.length - 1) = m.length + 1
        $temp = array_slice($x, $n_length - 1);
        // (m.length + 1) + m.length = 2 * m.length + 1
        $temp = $class::multiplyHelper($temp, false, $cache[self::DATA][$key], false);
        // (2 * m.length + 1) - (m.length - 1) = m.length + 2
        $temp = array_slice($temp[self::VALUE], $n_length + 1);
        // m.length + 1
        $result = array_slice($x, 0, $n_length + 1);
        // m.length + 1
        $temp = self::multiplyLower($temp, false, $n, false, $n_length + 1, $class);
        // $temp == array_slice($class::regularMultiply($temp, false, $n, false)->value, 0, $n_length + 1)
        if (self::compareHelper($result, false, $temp[self::VALUE], $temp[self::SIGN]) < 0) {
            $corrector_value = self::array_repeat(0, $n_length + 1);
            $corrector_value[count($corrector_value)] = 1;
            $result = $class::addHelper($result, false, $corrector_value, false);
            $result = $result[self::VALUE];
        }
        // at this point, we're subtracting a number with m.length + 1 digits from another number with m.length + 1 digits
        $result = $class::subtractHelper($result, false, $temp[self::VALUE], $temp[self::SIGN]);
        while (self::compareHelper($result[self::VALUE], $result[self::SIGN], $n, false) > 0) {
            $result = $class::subtractHelper($result[self::VALUE], $result[self::SIGN], $n, false);
        }
        return $result[self::VALUE];
    }
    /**
     * Performs long multiplication up to $stop digits
     *
     * If you're going to be doing array_slice($product->value, 0, $stop), some cycles can be saved.
     *
     * @see self::regularBarrett()
     * @param array $x_value
     * @param bool $x_negative
     * @param array $y_value
     * @param bool $y_negative
     * @param int $stop
     * @param string $class
     * @return array
     */
    private static function multiplyLower(array $x_value, $x_negative, array $y_value, $y_negative, $stop, $class)
    {
        $x_length = count($x_value);
        $y_length = count($y_value);
        if (!$x_length || !$y_length) {
            // a 0 is being multiplied
            return [self::VALUE => [], self::SIGN => false];
        }
        if ($x_length < $y_length) {
            $temp = $x_value;
            $x_value = $y_value;
            $y_value = $temp;
            $x_length = count($x_value);
            $y_length = count($y_value);
        }
        $product_value = self::array_repeat(0, $x_length + $y_length);
        // the following for loop could be removed if the for loop following it
        // (the one with nested for loops) initially set $i to 0, but
        // doing so would also make the result in one set of unnecessary adds,
        // since on the outermost loops first pass, $product->value[$k] is going
        // to always be 0
        $carry = 0;
        for ($j = 0; $j < $x_length; ++$j) {
            // ie. $i = 0, $k = $i
            $temp = $x_value[$j] * $y_value[0] + $carry;
            // $product_value[$k] == 0
            $carry = $class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
            $product_value[$j] = (int) ($temp - $class::BASE_FULL * $carry);
        }
        if ($j < $stop) {
            $product_value[$j] = $carry;
        }
        // the above for loop is what the previous comment was talking about.  the
        // following for loop is the "one with nested for loops"
        for ($i = 1; $i < $y_length; ++$i) {
            $carry = 0;
            for ($j = 0, $k = $i; $j < $x_length && $k < $stop; ++$j, ++$k) {
                $temp = $product_value[$k] + $x_value[$j] * $y_value[$i] + $carry;
                $carry = $class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31;
                $product_value[$k] = (int) ($temp - $class::BASE_FULL * $carry);
            }
            if ($k < $stop) {
                $product_value[$k] = $carry;
            }
        }
        return [self::VALUE => self::trim($product_value), self::SIGN => $x_negative != $y_negative];
    }
}<?php

/**
 * PHP Dynamic Barrett Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
use phpseclib3\Math\BigInteger\Engines\PHP;
/**
 * PHP Dynamic Barrett Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EvalBarrett extends Base
{
    /**
     * Custom Reduction Function
     *
     * @see self::generateCustomReduction
     */
    private static $custom_reduction;
    /**
    * Barrett Modular Reduction
    *
    * This calls a dynamically generated loop unrolled function that's specific to a given modulo.
    Array lookups are avoided as are if statements testing for how many bits the host OS supports, etc.
    *
    * @param array $n
    * @param array $m
    * @param string $class
    * @return array
    */
    protected static function reduce(array $n, array $m, $class)
    {
        $inline = self::$custom_reduction;
        return $inline($n);
    }
    /**
     * Generate Custom Reduction
     *
     * @param PHP $m
     * @param string $class
     * @return callable
     */
    protected static function generateCustomReduction(PHP $m, $class)
    {
        $m_length = count($m->value);
        if ($m_length < 5) {
            $code = '
                $lhs = new ' . $class . '();
                $lhs->value = $x;
                $rhs = new ' . $class . '();
                $rhs->value = [' . implode(',', array_map('self::float2string', $m->value)) . '];
                list(, $temp) = $lhs->divide($rhs);
                return $temp->value;
            ';
            eval('$func = function ($x) { ' . $code . '};');
            self::$custom_reduction = $func;
            //self::$custom_reduction = \Closure::bind($func, $m, $class);
            return $func;
        }
        $lhs = new $class();
        $lhs_value =& $lhs->value;
        $lhs_value = self::array_repeat(0, $m_length + ($m_length >> 1));
        $lhs_value[] = 1;
        $rhs = new $class();
        list($u, $m1) = $lhs->divide($m);
        if ($class::BASE != 26) {
            $u = $u->value;
        } else {
            $lhs_value = self::array_repeat(0, 2 * $m_length);
            $lhs_value[] = 1;
            $rhs = new $class();
            list($u) = $lhs->divide($m);
            $u = $u->value;
        }
        $m = $m->value;
        $m1 = $m1->value;
        $cutoff = count($m) + (count($m) >> 1);
        $code = '
            if (count($n) > ' . 2 * count($m) . ') {
                $lhs = new ' . $class . '();
                $rhs = new ' . $class . '();
                $lhs->value = $n;
                $rhs->value = [' . implode(',', array_map('self::float2string', $m)) . '];
                list(, $temp) = $lhs->divide($rhs);
                return $temp->value;
            }

            $lsd = array_slice($n, 0, ' . $cutoff . ');
            $msd = array_slice($n, ' . $cutoff . ');';
        $code .= self::generateInlineTrim('msd');
        $code .= self::generateInlineMultiply('msd', $m1, 'temp', $class);
        $code .= self::generateInlineAdd('lsd', 'temp', 'n', $class);
        $code .= '$temp = array_slice($n, ' . (count($m) - 1) . ');';
        $code .= self::generateInlineMultiply('temp', $u, 'temp2', $class);
        $code .= self::generateInlineTrim('temp2');
        $code .= $class::BASE == 26 ? '$temp = array_slice($temp2, ' . (count($m) + 1) . ');' : '$temp = array_slice($temp2, ' . ((count($m) >> 1) + 1) . ');';
        $code .= self::generateInlineMultiply('temp', $m, 'temp2', $class);
        $code .= self::generateInlineTrim('temp2');
        /*
        if ($class::BASE == 26) {
            $code.= '$n = array_slice($n, 0, ' . (count($m) + 1) . ');
                     $temp2 = array_slice($temp2, 0, ' . (count($m) + 1) . ');';
        }
        */
        $code .= self::generateInlineSubtract2('n', 'temp2', 'temp', $class);
        $subcode = self::generateInlineSubtract1('temp', $m, 'temp2', $class);
        $subcode .= '$temp = $temp2;';
        $code .= self::generateInlineCompare($m, 'temp', $subcode);
        $code .= 'return $temp;';
        eval('$func = function ($n) { ' . $code . '};');
        self::$custom_reduction = $func;
        return $func;
        //self::$custom_reduction = \Closure::bind($func, $m, $class);
    }
    /**
     * Inline Trim
     *
     * Removes leading zeros
     *
     * @param string $name
     * @return string
     */
    private static function generateInlineTrim($name)
    {
        return '
            for ($i = count($' . $name . ') - 1; $i >= 0; --$i) {
                if ($' . $name . '[$i]) {
                    break;
                }
                unset($' . $name . '[$i]);
            }';
    }
    /**
     * Inline Multiply (unknown, known)
     *
     * @param string $input
     * @param array $arr
     * @param string $output
     * @param string $class
     * @return string
     */
    private static function generateInlineMultiply($input, array $arr, $output, $class)
    {
        if (!count($arr)) {
            return 'return [];';
        }
        $regular = '
            $length = count($' . $input . ');
            if (!$length) {
                $' . $output . ' = [];
            }else{
            $' . $output . ' = array_fill(0, $length + ' . count($arr) . ', 0);
            $carry = 0;';
        for ($i = 0; $i < count($arr); $i++) {
            $regular .= '
                $subtemp = $' . $input . '[0] * ' . $arr[$i];
            $regular .= $i ? ' + $carry;' : ';';
            $regular .= '$carry = ';
            $regular .= $class::BASE === 26 ? 'intval($subtemp / 0x4000000);' : '$subtemp >> 31;';
            $regular .= '$' . $output . '[' . $i . '] = ';
            if ($class::BASE === 26) {
                $regular .= '(int) (';
            }
            $regular .= '$subtemp - ' . $class::BASE_FULL . ' * $carry';
            $regular .= $class::BASE === 26 ? ');' : ';';
        }
        $regular .= '$' . $output . '[' . count($arr) . '] = $carry;';
        $regular .= '
            for ($i = 1; $i < $length; ++$i) {';
        for ($j = 0; $j < count($arr); $j++) {
            $regular .= $j ? '$k++;' : '$k = $i;';
            $regular .= '
                $subtemp = $' . $output . '[$k] + $' . $input . '[$i] * ' . $arr[$j];
            $regular .= $j ? ' + $carry;' : ';';
            $regular .= '$carry = ';
            $regular .= $class::BASE === 26 ? 'intval($subtemp / 0x4000000);' : '$subtemp >> 31;';
            $regular .= '$' . $output . '[$k] = ';
            if ($class::BASE === 26) {
                $regular .= '(int) (';
            }
            $regular .= '$subtemp - ' . $class::BASE_FULL . ' * $carry';
            $regular .= $class::BASE === 26 ? ');' : ';';
        }
        $regular .= '$' . $output . '[++$k] = $carry; $carry = 0;';
        $regular .= '}}';
        //if (count($arr) < 2 * self::KARATSUBA_CUTOFF) {
        //}
        return $regular;
    }
    /**
     * Inline Addition
     *
     * @param string $x
     * @param string $y
     * @param string $result
     * @param string $class
     * @return string
     */
    private static function generateInlineAdd($x, $y, $result, $class)
    {
        $code = '
            $length = max(count($' . $x . '), count($' . $y . '));
            $' . $result . ' = array_pad($' . $x . ', $length + 1, 0);
            $_' . $y . ' = array_pad($' . $y . ', $length, 0);
            $carry = 0;
            for ($i = 0, $j = 1; $j < $length; $i+=2, $j+=2) {
                $sum = ($' . $result . '[$j] + $_' . $y . '[$j]) * ' . $class::BASE_FULL . '
                           + $' . $result . '[$i] + $_' . $y . '[$i] +
                           $carry;
                $carry = $sum >= ' . self::float2string($class::MAX_DIGIT2) . ';
                $sum = $carry ? $sum - ' . self::float2string($class::MAX_DIGIT2) . ' : $sum;';
        $code .= $class::BASE === 26 ? '$upper = intval($sum / 0x4000000); $' . $result . '[$i] = (int) ($sum - ' . $class::BASE_FULL . ' * $upper);' : '$upper = $sum >> 31; $' . $result . '[$i] = $sum - ' . $class::BASE_FULL . ' * $upper;';
        $code .= '
                $' . $result . '[$j] = $upper;
            }
            if ($j == $length) {
                $sum = $' . $result . '[$i] + $_' . $y . '[$i] + $carry;
                $carry = $sum >= ' . self::float2string($class::BASE_FULL) . ';
                $' . $result . '[$i] = $carry ? $sum - ' . self::float2string($class::BASE_FULL) . ' : $sum;
            }
            if ($carry) {
                for (; $' . $result . '[$i] == ' . $class::MAX_DIGIT . '; ++$i) {
                    $' . $result . '[$i] = 0;
                }
                ++$' . $result . '[$i];
            }';
        $code .= self::generateInlineTrim($result);
        return $code;
    }
    /**
     * Inline Subtraction 2
     *
     * For when $known is more digits than $unknown. This is the harder use case to optimize for.
     *
     * @param string $known
     * @param string $unknown
     * @param string $result
     * @param string $class
     * @return string
     */
    private static function generateInlineSubtract2($known, $unknown, $result, $class)
    {
        $code = '
            $' . $result . ' = $' . $known . ';
            $carry = 0;
            $size = count($' . $unknown . ');
            for ($i = 0, $j = 1; $j < $size; $i+= 2, $j+= 2) {
                $sum = ($' . $known . '[$j] - $' . $unknown . '[$j]) * ' . $class::BASE_FULL . ' + $' . $known . '[$i]
                    - $' . $unknown . '[$i]
                    - $carry;
                $carry = $sum < 0;
                if ($carry) {
                    $sum+= ' . self::float2string($class::MAX_DIGIT2) . ';
                }
                $subtemp = ';
        $code .= $class::BASE === 26 ? 'intval($sum / 0x4000000);' : '$sum >> 31;';
        $code .= '$' . $result . '[$i] = ';
        if ($class::BASE === 26) {
            $code .= '(int) (';
        }
        $code .= '$sum - ' . $class::BASE_FULL . ' * $subtemp';
        if ($class::BASE === 26) {
            $code .= ')';
        }
        $code .= ';
                $' . $result . '[$j] = $subtemp;
            }
            if ($j == $size) {
                $sum = $' . $known . '[$i] - $' . $unknown . '[$i] - $carry;
                $carry = $sum < 0;
                $' . $result . '[$i] = $carry ? $sum + ' . $class::BASE_FULL . ' : $sum;
                ++$i;
            }

            if ($carry) {
                for (; !$' . $result . '[$i]; ++$i) {
                    $' . $result . '[$i] = ' . $class::MAX_DIGIT . ';
                }
                --$' . $result . '[$i];
            }';
        $code .= self::generateInlineTrim($result);
        return $code;
    }
    /**
     * Inline Subtraction 1
     *
     * For when $unknown is more digits than $known. This is the easier use case to optimize for.
     *
     * @param string $unknown
     * @param array $known
     * @param string $result
     * @param string $class
     * @return string
     */
    private static function generateInlineSubtract1($unknown, array $known, $result, $class)
    {
        $code = '$' . $result . ' = $' . $unknown . ';';
        for ($i = 0, $j = 1; $j < count($known); $i += 2, $j += 2) {
            $code .= '$sum = $' . $unknown . '[' . $j . '] * ' . $class::BASE_FULL . ' + $' . $unknown . '[' . $i . '] - ';
            $code .= self::float2string($known[$j] * $class::BASE_FULL + $known[$i]);
            if ($i != 0) {
                $code .= ' - $carry';
            }
            $code .= ';
                if ($carry = $sum < 0) {
                    $sum+= ' . self::float2string($class::MAX_DIGIT2) . ';
                }
                $subtemp = ';
            $code .= $class::BASE === 26 ? 'intval($sum / 0x4000000);' : '$sum >> 31;';
            $code .= '
                $' . $result . '[' . $i . '] = ';
            if ($class::BASE === 26) {
                $code .= ' (int) (';
            }
            $code .= '$sum - ' . $class::BASE_FULL . ' * $subtemp';
            if ($class::BASE === 26) {
                $code .= ')';
            }
            $code .= ';
                $' . $result . '[' . $j . '] = $subtemp;';
        }
        $code .= '$i = ' . $i . ';';
        if ($j == count($known)) {
            $code .= '
                $sum = $' . $unknown . '[' . $i . '] - ' . $known[$i] . ' - $carry;
                $carry = $sum < 0;
                $' . $result . '[' . $i . '] = $carry ? $sum + ' . $class::BASE_FULL . ' : $sum;
                ++$i;';
        }
        $code .= '
            if ($carry) {
                for (; !$' . $result . '[$i]; ++$i) {
                    $' . $result . '[$i] = ' . $class::MAX_DIGIT . ';
                }
                --$' . $result . '[$i];
            }';
        $code .= self::generateInlineTrim($result);
        return $code;
    }
    /**
     * Inline Comparison
     *
     * If $unknown >= $known then loop
     *
     * @param array $known
     * @param string $unknown
     * @param string $subcode
     * @return string
     */
    private static function generateInlineCompare(array $known, $unknown, $subcode)
    {
        $uniqid = uniqid();
        $code = 'loop_' . $uniqid . ':
            $clength = count($' . $unknown . ');
            switch (true) {
                case $clength < ' . count($known) . ':
                    goto end_' . $uniqid . ';
                case $clength > ' . count($known) . ':';
        for ($i = count($known) - 1; $i >= 0; $i--) {
            $code .= '
                case $' . $unknown . '[' . $i . '] > ' . $known[$i] . ':
                    goto subcode_' . $uniqid . ';
                case $' . $unknown . '[' . $i . '] < ' . $known[$i] . ':
                    goto end_' . $uniqid . ';';
        }
        $code .= '
                default:
                    // do subcode
            }

            subcode_' . $uniqid . ':' . $subcode . '
            goto loop_' . $uniqid . ';

            end_' . $uniqid . ':';
        return $code;
    }
    /**
    * Convert a float to a string
    *
    * If you do echo floatval(pow(2, 52)) you'll get 4.6116860184274E+18. It /can/ be displayed without a loss of
    precision but displayed in this way there will be precision loss, hence the need for this method.
    *
    * @param (int | float) $num
    * @return string
    */
    private static function float2string($num)
    {
        if (!is_float($num)) {
            return $num;
        }
        if ($num < 0) {
            return '-' . self::float2string(abs($num));
        }
        $temp = '';
        while ($num) {
            $temp = fmod($num, 10) . $temp;
            $num = floor($num / 10);
        }
        return $temp;
    }
}<?php

/**
 * PHP Montgomery Modular Exponentiation Engine with interleaved multiplication
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
/**
 * PHP Montgomery Modular Exponentiation Engine with interleaved multiplication
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class MontgomeryMult extends Montgomery
{
    /**
    * Montgomery Multiply
    *
    * Interleaves the montgomery reduction and long multiplication algorithms together as described in
    {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=13 HAC 14.36}
    *
    * @see self::_prepMontgomery()
    * @see self::_montgomery()
    * @access private
    * @param array $x
    * @param array $y
    * @param array $m
    * @param string $class
    * @return array
    */
    public static function multiplyReduce(array $x, array $y, array $m, $class)
    {
        // the following code, although not callable, can be run independently of the above code
        // although the above code performed better in my benchmarks the following could might
        // perform better under different circumstances. in lieu of deleting it it's just been
        // made uncallable
        static $cache = [self::VARIABLE => [], self::DATA => []];
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $m;
            $cache[self::DATA][] = self::modInverse67108864($m, $class);
        }
        $n = max(count($x), count($y), count($m));
        $x = array_pad($x, $n, 0);
        $y = array_pad($y, $n, 0);
        $m = array_pad($m, $n, 0);
        $a = [self::VALUE => self::array_repeat(0, $n + 1)];
        for ($i = 0; $i < $n; ++$i) {
            $temp = $a[self::VALUE][0] + $x[$i] * $y[0];
            $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31);
            $temp = $temp * $cache[self::DATA][$key];
            $temp = $temp - $class::BASE_FULL * ($class::BASE === 26 ? intval($temp / 0x4000000) : $temp >> 31);
            $temp = $class::addHelper($class::regularMultiply([$x[$i]], $y), false, $class::regularMultiply([$temp], $m), false);
            $a = $class::addHelper($a[self::VALUE], false, $temp[self::VALUE], false);
            $a[self::VALUE] = array_slice($a[self::VALUE], 1);
        }
        if (self::compareHelper($a[self::VALUE], false, $m, false) >= 0) {
            $a = $class::subtractHelper($a[self::VALUE], false, $m, false);
        }
        return $a[self::VALUE];
    }
}<?php

/**
 * PHP Classic Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP\Reductions;

use phpseclib3\Math\BigInteger\Engines\PHP\Base;
/**
 * PHP Classic Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Classic extends Base
{
    /**
     * Regular Division
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @return array
     */
    protected static function reduce(array $x, array $n, $class)
    {
        $lhs = new $class();
        $lhs->value = $x;
        $rhs = new $class();
        $rhs->value = $n;
        list(, $temp) = $lhs->divide($rhs);
        return $temp->value;
    }
}<?php

/**
 * PHP Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP;

use phpseclib3\Math\BigInteger\Engines\PHP;
/**
 * PHP Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Base extends PHP
{
    /**
     * Cache constants
     *
     * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
     *
     * @access private
     */
    const VARIABLE = 0;
    /**
     * $cache[self::DATA] contains the cached data.
     *
     * @access private
     */
    const DATA = 1;
    /**
     * Test for engine validity
     *
     * @return bool
     */
    public static function isValidEngine()
    {
        return static::class != __CLASS__;
    }
    /**
    * Performs modular exponentiation.
    *
    * The most naive approach to modular exponentiation has very unreasonable requirements, and
    and although the approach involving repeated squaring does vastly better, it, too, is impractical
    for our purposes.  The reason being that division - by far the most complicated and time-consuming
    of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
    *
    * Modular reductions resolve this issue.  Although an individual modular reduction takes more time
    then an individual division, when performed in succession (with the same modulo), they're a lot faster.
    *
    * The two most commonly used modular reductions are Barrett and Montgomery reduction.  Montgomery reduction,
    although faster, only works when the gcd of the modulo and of the base being used is 1.  In RSA, when the
    base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
    the product of two odd numbers is odd), but what about when RSA isn't used?
    *
    * In contrast, Barrett reduction has no such constraint.  As such, some bigint implementations perform a
    Barrett reduction after every operation in the modpow function.  Others perform Barrett reductions when the
    modulo is even and Montgomery reductions when the modulo is odd.  BigInteger.java's modPow method, however,
    uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
    the other, a power of two - and recombine them, later.  This is the method that this modPow function uses.
    {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
    *
    * @param \phpseclib3\Math\BigInteger\Engines\PHP $x
    * @param \phpseclib3\Math\BigInteger\Engines\PHP $e
    * @param \phpseclib3\Math\BigInteger\Engines\PHP $n
    * @param string $class
    * @return \phpseclib3\Math\BigInteger\Engines\PHP
    */
    protected static function powModHelper(PHP $x, PHP $e, PHP $n, $class)
    {
        if (empty($e->value)) {
            $temp = new $class();
            $temp->value = [1];
            return $x->normalize($temp);
        }
        if ($e->value == [1]) {
            list(, $temp) = $x->divide($n);
            return $x->normalize($temp);
        }
        if ($e->value == [2]) {
            $temp = new $class();
            $temp->value = $class::square($x->value);
            list(, $temp) = $temp->divide($n);
            return $x->normalize($temp);
        }
        return $x->normalize(static::slidingWindow($x, $e, $n, $class));
    }
    /**
     * Modular reduction preparation
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @see self::slidingWindow()
     * @return array
     */
    protected static function prepareReduce(array $x, array $n, $class)
    {
        return static::reduce($x, $n, $class);
    }
    /**
     * Modular multiply
     *
     * @param array $x
     * @param array $y
     * @param array $n
     * @param string $class
     * @see self::slidingWindow()
     * @return array
     */
    protected static function multiplyReduce(array $x, array $y, array $n, $class)
    {
        $temp = $class::multiplyHelper($x, false, $y, false);
        return static::reduce($temp[self::VALUE], $n, $class);
    }
    /**
     * Modular square
     *
     * @param array $x
     * @param array $n
     * @param string $class
     * @see self::slidingWindow()
     * @return array
     */
    protected static function squareReduce(array $x, array $n, $class)
    {
        return static::reduce($class::square($x), $n, $class);
    }
}<?php

/**
 * PHP Default Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\PHP;

use phpseclib3\Math\BigInteger\Engines\PHP\Reductions\EvalBarrett;
/**
 * PHP Default Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DefaultEngine extends EvalBarrett
{
}<?php

/**
 * OpenSSL Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath;

use phpseclib3\Math\BigInteger\Engines\OpenSSL as Progenitor;
/**
 * OpenSSL Modular Exponentiation Engine
 *
 * @package BCMath
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class OpenSSL extends Progenitor
{
}<?php

/**
 * Built-In BCMath Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath;

use phpseclib3\Math\BigInteger\Engines\BCMath;
/**
 * Built-In BCMath Modular Exponentiation Engine
 *
 * @package BCMath
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class BuiltIn extends BCMath
{
    /**
     * Performs modular exponentiation.
     *
     * @param BCMath $x
     * @param BCMath $e
     * @param BCMath $n
     * @return BCMath
     */
    protected static function powModHelper(BCMath $x, BCMath $e, BCMath $n)
    {
        $temp = new BCMath();
        $temp->value = bcpowmod($x->value, $e->value, $n->value);
        return $x->normalize($temp);
    }
}<?php

/**
 * BCMath Barrett Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath\Reductions;

use phpseclib3\Math\BigInteger\Engines\BCMath\Base;
/**
 * PHP Barrett Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Barrett extends Base
{
    /**
     * Cache constants
     *
     * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
     *
     * @access private
     */
    const VARIABLE = 0;
    /**
     * $cache[self::DATA] contains the cached data.
     *
     * @access private
     */
    const DATA = 1;
    /**
    * Barrett Modular Reduction
    *
    * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information.  Modified slightly,
    so as not to require negative numbers (initially, this script didn't support negative numbers).
    *
    * Employs "folding", as described at
    {@link http://www.cosic.esat.kuleuven.be/publications/thesis-149.pdf#page=66 thesis-149.pdf#page=66}.  To quote from
    it, "the idea [behind folding] is to find a value x' such that x (mod m) = x' (mod m), with x' being smaller than x."
    *
    * Unfortunately, the "Barrett Reduction with Folding" algorithm described in thesis-149.pdf is not, as written, all that
    usable on account of (1) its not using reasonable radix points as discussed in
    {@link http://math.libtomcrypt.com/files/tommath.pdf#page=162 MPM 6.2.2} and (2) the fact that, even with reasonable
    radix points, it only works when there are an even number of digits in the denominator.  The reason for (2) is that
    (x >> 1) + (x >> 1) != x / 2 + x / 2.  If x is even, they're the same, but if x is odd, they're not.  See the in-line
    comments for details.
    *
    * @param string $n
    * @param string $m
    * @return (array | string)
    */
    protected static function reduce($n, $m)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        $m_length = strlen($m);
        if (strlen($n) > 2 * $m_length) {
            return bcmod($n, $m);
        }
        // if (m.length >> 1) + 2 <= m.length then m is too small and n can't be reduced
        if ($m_length < 5) {
            return self::regularBarrett($n, $m);
        }
        // n = 2 * m.length
        if (($key = array_search($m, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $m;
            $lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1));
            $u = bcdiv($lhs, $m, 0);
            $m1 = bcsub($lhs, bcmul($u, $m));
            $cache[self::DATA][] = [
                'u' => $u,
                // m.length >> 1 (technically (m.length >> 1) + 1)
                'm1' => $m1,
            ];
        } else {
            extract($cache[self::DATA][$key]);
        }
        $cutoff = $m_length + ($m_length >> 1);
        $lsd = \Phabel\Target\Php80\Polyfill::substr($n, -$cutoff);
        $msd = \Phabel\Target\Php80\Polyfill::substr($n, 0, -$cutoff);
        $temp = bcmul($msd, $m1);
        // m.length + (m.length >> 1)
        $n = bcadd($lsd, $temp);
        // m.length + (m.length >> 1) + 1 (so basically we're adding two same length numbers)
        //if ($m_length & 1) {
        //    return self::regularBarrett($n, $m);
        //}
        // (m.length + (m.length >> 1) + 1) - (m.length - 1) == (m.length >> 1) + 2
        $temp = \Phabel\Target\Php80\Polyfill::substr($n, 0, -$m_length + 1);
        // if even: ((m.length >> 1) + 2) + (m.length >> 1) == m.length + 2
        // if odd:  ((m.length >> 1) + 2) + (m.length >> 1) == (m.length - 1) + 2 == m.length + 1
        $temp = bcmul($temp, $u);
        // if even: (m.length + 2) - ((m.length >> 1) + 1) = m.length - (m.length >> 1) + 1
        // if odd:  (m.length + 1) - ((m.length >> 1) + 1) = m.length - (m.length >> 1)
        $temp = \Phabel\Target\Php80\Polyfill::substr($temp, 0, -($m_length >> 1) - 1);
        // if even: (m.length - (m.length >> 1) + 1) + m.length = 2 * m.length - (m.length >> 1) + 1
        // if odd:  (m.length - (m.length >> 1)) + m.length     = 2 * m.length - (m.length >> 1)
        $temp = bcmul($temp, $m);
        // at this point, if m had an odd number of digits, we'd be subtracting a 2 * m.length - (m.length >> 1) digit
        // number from a m.length + (m.length >> 1) + 1 digit number.  ie. there'd be an extra digit and the while loop
        // following this comment would loop a lot (hence our calling _regularBarrett() in that situation).
        $result = bcsub($n, $temp);
        //if (bccomp($result, '0') < 0) {
        if ($result[0] == '-') {
            $temp = '1' . str_repeat('0', $m_length + 1);
            $result = bcadd($result, $temp);
        }
        while (bccomp($result, $m) >= 0) {
            $result = bcsub($result, $m);
        }
        return $result;
    }
    /**
    * (Regular) Barrett Modular Reduction
    *
    * For numbers with more than four digits BigInteger::_barrett() is faster.  The difference between that and this
    is that this function does not fold the denominator into a smaller form.
    *
    * @param string $x
    * @param string $n
    * @return string
    */
    private static function regularBarrett($x, $n)
    {
        static $cache = [self::VARIABLE => [], self::DATA => []];
        $n_length = strlen($n);
        if (strlen($x) > 2 * $n_length) {
            return bcmod($x, $n);
        }
        if (($key = array_search($n, $cache[self::VARIABLE])) === false) {
            $key = count($cache[self::VARIABLE]);
            $cache[self::VARIABLE][] = $n;
            $lhs = '1' . str_repeat('0', 2 * $n_length);
            $cache[self::DATA][] = bcdiv($lhs, $n, 0);
        }
        $temp = \Phabel\Target\Php80\Polyfill::substr($x, 0, -$n_length + 1);
        $temp = bcmul($temp, $cache[self::DATA][$key]);
        $temp = \Phabel\Target\Php80\Polyfill::substr($temp, 0, -$n_length - 1);
        $r1 = \Phabel\Target\Php80\Polyfill::substr($x, -$n_length - 1);
        $r2 = \Phabel\Target\Php80\Polyfill::substr(bcmul($temp, $n), -$n_length - 1);
        $result = bcsub($r1, $r2);
        //if (bccomp($result, '0') < 0) {
        if ($result[0] == '-') {
            $q = '1' . str_repeat('0', $n_length + 1);
            $result = bcadd($result, $q);
        }
        while (bccomp($result, $n) >= 0) {
            $result = bcsub($result, $n);
        }
        return $result;
    }
}<?php

/**
 * BCMath Dynamic Barrett Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath\Reductions;

use phpseclib3\Math\BigInteger\Engines\BCMath\Base;
use phpseclib3\Math\BigInteger\Engines\BCMath;
/**
 * PHP Barrett Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class EvalBarrett extends Base
{
    /**
     * Custom Reduction Function
     *
     * @see self::generateCustomReduction
     */
    private static $custom_reduction;
    /**
    * Barrett Modular Reduction
    *
    * This calls a dynamically generated loop unrolled function that's specific to a given modulo.
    Array lookups are avoided as are if statements testing for how many bits the host OS supports, etc.
    *
    * @param string $n
    * @param string $m
    * @return string
    */
    protected static function reduce($n, $m)
    {
        $inline = self::$custom_reduction;
        return $inline($n);
    }
    /**
     * Generate Custom Reduction
     *
     * @param BCMath $m
     * @param string $class
     * @return (callable | void)
     */
    protected static function generateCustomReduction(BCMath $m, $class)
    {
        $m_length = strlen($m);
        if ($m_length < 5) {
            $code = 'return bcmod($x, $n);';
            eval('$func = function ($n) { ' . $code . '};');
            self::$custom_reduction = $func;
            return;
        }
        $lhs = '1' . str_repeat('0', $m_length + ($m_length >> 1));
        $u = bcdiv($lhs, $m, 0);
        $m1 = bcsub($lhs, bcmul($u, $m));
        $cutoff = $m_length + ($m_length >> 1);
        $m = "'{$m}'";
        $u = "'{$u}'";
        $m1 = "'{$m1}'";
        $code .= '
            $lsd = substr($n, -' . $cutoff . ');
            $msd = substr($n, 0, -' . $cutoff . ');

            $temp = bcmul($msd, ' . $m1 . ');
            $n = bcadd($lsd, $temp);

            $temp = substr($n, 0, ' . (-$m_length + 1) . ');
            $temp = bcmul($temp, ' . $u . ');
            $temp = substr($temp, 0, ' . (-($m_length >> 1) - 1) . ');
            $temp = bcmul($temp, ' . $m . ');

            $result = bcsub($n, $temp);

            if ($result[0] == \'-\') {
                $temp = \'1' . str_repeat('0', $m_length + 1) . '\';
                $result = bcadd($result, $temp);
            }

            while (bccomp($result, ' . $m . ') >= 0) {
                $result = bcsub($result, ' . $m . ');
            }

            return $result;';
        eval('$func = function ($n) { ' . $code . '};');
        self::$custom_reduction = $func;
        return $func;
    }
}<?php

/**
 * Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath;

use phpseclib3\Math\BigInteger\Engines\BCMath;
/**
 * Sliding Window Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class Base extends BCMath
{
    /**
     * Cache constants
     *
     * $cache[self::VARIABLE] tells us whether or not the cached data is still valid.
     *
     * @access private
     */
    const VARIABLE = 0;
    /**
     * $cache[self::DATA] contains the cached data.
     *
     * @access private
     */
    const DATA = 1;
    /**
     * Test for engine validity
     *
     * @return bool
     */
    public static function isValidEngine()
    {
        return static::class != __CLASS__;
    }
    /**
     * Performs modular exponentiation.
     *
     * @param \phpseclib3\Math\BigInteger\Engines\BCMath $x
     * @param \phpseclib3\Math\BigInteger\Engines\BCMath $e
     * @param \phpseclib3\Math\BigInteger\Engines\BCMath $n
     * @param string $class
     * @return \phpseclib3\Math\BigInteger\Engines\BCMath
     */
    protected static function powModHelper(BCMath $x, BCMath $e, BCMath $n, $class)
    {
        if (empty($e->value)) {
            $temp = new $class();
            $temp->value = '1';
            return $x->normalize($temp);
        }
        return $x->normalize(static::slidingWindow($x, $e, $n, $class));
    }
    /**
     * Modular reduction preparation
     *
     * @param string $x
     * @param string $n
     * @param string $class
     * @see self::slidingWindow()
     * @return string
     */
    protected static function prepareReduce($x, $n, $class)
    {
        return static::reduce($x, $n);
    }
    /**
     * Modular multiply
     *
     * @param string $x
     * @param string $y
     * @param string $n
     * @param string $class
     * @see self::slidingWindow()
     * @return string
     */
    protected static function multiplyReduce($x, $y, $n, $class)
    {
        return static::reduce(bcmul($x, $y), $n);
    }
    /**
     * Modular square
     *
     * @param string $x
     * @param string $n
     * @param string $class
     * @see self::slidingWindow()
     * @return string
     */
    protected static function squareReduce($x, $n, $class)
    {
        return static::reduce(bcmul($x, $x), $n);
    }
}<?php

/**
 * BCMath Default Modular Exponentiation Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines\BCMath;

use phpseclib3\Math\BigInteger\Engines\BCMath\Reductions\Barrett;
/**
 * PHP Default Modular Exponentiation Engine
 *
 * @package PHP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
abstract class DefaultEngine extends Barrett
{
}<?php

/**
 * GMP BigInteger Engine
 *
 * PHP version 5 and 7
 *
 * @category  Math
 * @package   BigInteger
 * @author    Jim Wigginton <terrafrost@php.net>
 * @copyright 2017 Jim Wigginton
 * @license   http://www.opensource.org/licenses/mit-license.html  MIT License
 * @link      http://pear.php.net/package/Math_BigInteger
 */
namespace phpseclib3\Math\BigInteger\Engines;

use ParagonIE\ConstantTime\Hex;
use phpseclib3\Exception\BadConfigurationException;
/**
 * GMP Engine.
 *
 * @package GMP
 * @author  Jim Wigginton <terrafrost@php.net>
 * @access  public
 */
class GMP extends Engine
{
    /**
     * Can Bitwise operations be done fast?
     *
     * @see parent::bitwise_leftRotate()
     * @see parent::bitwise_rightRotate()
     * @access protected
     */
    const FAST_BITWISE = true;
    /**
     * Engine Directory
     *
     * @see parent::setModExpEngine
     * @access protected
     */
    const ENGINE_DIR = 'GMP';
    /**
     * Modular Exponentiation Engine
     *
     * @var string
     */
    protected static $modexpEngine;
    /**
     * Engine Validity Flag
     *
     * @var bool
     */
    protected static $isValidEngine;
    /**
     * BigInteger(0)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\GMP
     */
    protected static $zero;
    /**
     * BigInteger(1)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\GMP
     */
    protected static $one;
    /**
     * BigInteger(2)
     *
     * @var \phpseclib3\Math\BigInteger\Engines\GMP
     */
    protected static $two;
    /**
     * Primes > 2 and < 1000
     *
     * Unused for GMP Engine
     *
     * @var mixed
     */
    protected static $primes;
    /**
     * Test for engine validity
     *
     * @see parent::__construct()
     * @return bool
     */
    public static function isValidEngine()
    {
        return extension_loaded('gmp');
    }
    /**
     * Default constructor
     *
     * @param mixed $x integer Base-10 number or base-$base number if $base set.
     * @param int $base
     * @see parent::__construct()
     * @return \phpseclib3\Math\BigInteger\Engines\GMP
     */
    public function __construct($x = 0, $base = 10)
    {
        if (!isset(self::$isValidEngine)) {
            self::$isValidEngine = self::isValidEngine();
        }
        if (!self::$isValidEngine) {
            throw new BadConfigurationException('GMP is not setup correctly on this system');
        }
        if ($x instanceof \GMP) {
            $this->value = $x;
            return;
        }
        $this->value = gmp_init(0);
        parent::__construct($x, $base);
    }
    /**
     * Initialize a GMP BigInteger Engine instance
     *
     * @param int $base
     * @see parent::__construct()
     */
    protected function initialize($base)
    {
        switch (abs($base)) {
            case 256:
                $this->value = gmp_import($this->value);
                if ($this->is_negative) {
                    $this->value = -$this->value;
                }
                break;
            case 16:
                $temp = $this->is_negative ? '-0x' . $this->value : '0x' . $this->value;
                $this->value = gmp_init($temp);
                break;
            case 10:
                $this->value = gmp_init(isset($this->value) ? $this->value : '0');
        }
    }
    /**
     * Converts a BigInteger to a base-10 number.
     *
     * @return string
     */
    public function toString()
    {
        return (string) $this->value;
    }
    /**
    * Converts a BigInteger to a bit string (eg. base-2).
    *
    * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
    saved as two's compliment.
    *
    * @param bool $twos_compliment
    * @return string
    */
    public function toBits($twos_compliment = false)
    {
        $hex = $this->toHex($twos_compliment);
        $bits = gmp_strval(gmp_init($hex, 16), 2);
        if ($this->precision > 0) {
            $bits = \Phabel\Target\Php80\Polyfill::substr($bits, -$this->precision);
        }
        if ($twos_compliment && $this->compare(new static()) > 0 && $this->precision <= 0) {
            return '0' . $bits;
        }
        return $bits;
    }
    /**
     * Converts a BigInteger to a byte string (eg. base-256).
     *
     * @param bool $twos_compliment
     * @return string
     */
    function toBytes($twos_compliment = false)
    {
        if ($twos_compliment) {
            return $this->toBytesHelper();
        }
        if (gmp_cmp($this->value, gmp_init(0)) == 0) {
            return $this->precision > 0 ? str_repeat(chr(0), $this->precision + 1 >> 3) : '';
        }
        $temp = gmp_export($this->value);
        return $this->precision > 0 ? \Phabel\Target\Php80\Polyfill::substr(str_pad($temp, $this->precision >> 3, chr(0), STR_PAD_LEFT), -($this->precision >> 3)) : ltrim($temp, chr(0));
    }
    /**
     * Adds two BigIntegers.
     *
     * @param GMP $y
     * @return GMP
     */
    public function add(GMP $y)
    {
        $temp = new self();
        $temp->value = $this->value + $y->value;
        return $this->normalize($temp);
    }
    /**
     * Subtracts two BigIntegers.
     *
     * @param GMP $y
     * @return GMP
     */
    public function subtract(GMP $y)
    {
        $temp = new self();
        $temp->value = $this->value - $y->value;
        return $this->normalize($temp);
    }
    /**
     * Multiplies two BigIntegers.
     *
     * @param GMP $x
     * @return GMP
     */
    public function multiply(GMP $x)
    {
        $temp = new self();
        $temp->value = $this->value * $x->value;
        return $this->normalize($temp);
    }
    /**
    * Divides two BigIntegers.
    *
    * Returns an array whose first element contains the quotient and whose second element contains the
    "common residue".  If the remainder would be positive, the "common residue" and the remainder are the
    same.  If the remainder would be negative, the "common residue" is equal to the sum of the remainder
    and the divisor (basically, the "common residue" is the first positive modulo).
    *
    * @param GMP $y
    * @return GMP
    */
    public function divide(GMP $y)
    {
        $quotient = new self();
        $remainder = new self();
        list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
        if (gmp_sign($remainder->value) < 0) {
            $remainder->value = $remainder->value + gmp_abs($y->value);
        }
        return [$this->normalize($quotient), $this->normalize($remainder)];
    }
    /**
    * Compares two numbers.
    *
    * Although one might think !$x->compare($y) means $x != $y, it, in fact, means the opposite.  The reason for this is
    demonstrated thusly:
    *
    * $x  > $y: $x->compare($y)  > 0
    $x  < $y: $x->compare($y)  < 0
    $x == $y: $x->compare($y) == 0
    *
    * Note how the same comparison operator is used.  If you want to test for equality, use $x->equals($y).
    *
    * {@internal Could return $this->subtract($x), but that's not as fast as what we do do.}
    *
    * @param GMP $y
    * @return int in case < 0 if $this is less than $y; > 0 if $this is greater than $y, and 0 if they are equal.
    * @access public
    * @see self::equals()
    */
    public function compare(GMP $y)
    {
        $r = gmp_cmp($this->value, $y->value);
        if ($r < -1) {
            $r = -1;
        }
        if ($r > 1) {
            $r = 1;
        }
        return $r;
    }
    /**
     * Tests the equality of two numbers.
     *
     * If you need to see if one number is greater than or less than another number, use BigInteger::compare()
     *
     * @param GMP $x
     * @return bool
     */
    public function equals(GMP $x)
    {
        return $this->value == $x->value;
    }
    /**
     * Calculates modular inverses.
     *
     * Say you have (30 mod 17 * x mod 17) mod 17 == 1.  x can be found using modular inverses.
     *
     * @param GMP $n
     * @return (false | GMP)
     */
    public function modInverse(GMP $n)
    {
        $temp = new self();
        $temp->value = gmp_invert($this->value, $n->value);
        return $temp->value === false ? false : $this->normalize($temp);
    }
    /**
    * Calculates the greatest common divisor and Bezout's identity.
    *
    * Say you have 693 and 609.  The GCD is 21.  Bezout's identity states that there exist integers x and y such that
    693*x + 609*y == 21.  In point of fact, there are actually an infinite number of x and y combinations and which
    combination is returned is dependent upon which mode is in use.  See
    {@link http://en.wikipedia.org/wiki/B%C3%A9zout%27s_identity Bezout's identity - Wikipedia} for more information.
    *
    * @param \phpseclib3\Math\BigInteger\Engines\GMP $n
    * @return \phpseclib3\Math\BigInteger\Engines\GMP[]
    */
    public function extendedGCD(GMP $n)
    {
        extract(gmp_gcdext($this->value, $n->value));
        return ['gcd' => $this->normalize(new self($g)), 'x' => $this->normalize(new self($s)), 'y' => $this->normalize(new self($t))];
    }
    /**
     * Calculates the greatest common divisor
     *
     * Say you have 693 and 609.  The GCD is 21.
     *
     * @param GMP $n
     * @return GMP
     */
    public function gcd(GMP $n)
    {
        $r = gmp_gcd($this->value, $n->value);
        return $this->normalize(new self($r));
    }
    /**
     * Absolute value.
     *
     * @return \phpseclib3\Math\BigInteger\Engines\GMP
     * @access public
     */
    public function abs()
    {
        $temp = new self();
        $temp->value = gmp_abs($this->value);
        return $temp;
    }
    /**
     * Logical And
     *
     * @param GMP $x
     * @return GMP
     */
    public function bitwise_and(GMP $x)
    {
        $temp = new self();
        $temp->value = $this->value & $x->value;
        return $this->normalize($temp);
    }
    /**
     * Logical Or
     *
     * @param GMP $x
     * @return GMP
     */
    public function bitwise_or(GMP $x)
    {
        $temp = new self();
        $temp->value = $this->value | $x->value;
        return $this->normalize($temp);
    }
    /**
     * Logical Exclusive Or
     *
     * @param GMP $x
     * @return GMP
     */
    public function bitwise_xor(GMP $x)
    {
        $temp = new self();
        $temp->value = $this->value ^ $x->value;
        return $this->normalize($temp);
    }
    /**
     * Logical Right Shift
     *
     * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\GMP
     */
    public function bitwise_rightShift($shift)
    {
        // 0xFFFFFFFF >> 2 == -1 (on 32-bit systems)
        // gmp_init('0xFFFFFFFF') >> 2 == gmp_init('0x3FFFFFFF')
        $temp = new self();
        $temp->value = $this->value >> $shift;
        return $this->normalize($temp);
    }
    /**
     * Logical Left Shift
     *
     * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
     *
     * @param int $shift
     * @return \phpseclib3\Math\BigInteger\Engines\GMP
     */
    public function bitwise_leftShift($shift)
    {
        $temp = new self();
        $temp->value = $this->value << $shift;
        return $this->normalize($temp);
    }
    /**
     * Performs modular exponentiation.
     *
     * @param GMP $e
     * @param GMP $n
     * @return GMP
     */
    public function modPow(GMP $e, GMP $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * Alias for modPow().
     *
     * @param GMP $e
     * @param GMP $n
     * @return GMP
     */
    public function powMod(GMP $e, GMP $n)
    {
        return $this->powModOuter($e, $n);
    }
    /**
     * Performs modular exponentiation.
     *
     * @param GMP $e
     * @param GMP $n
     * @return GMP
     */
    protected function powModInner(GMP $e, GMP $n)
    {
        $class = self::$modexpEngine;
        return $class::powModHelper($this, $e, $n);
    }
    /**
     * Normalize
     *
     * Removes leading zeros and truncates (if necessary) to maintain the appropriate precision
     *
     * @param GMP $result
     * @return GMP
     */
    protected function normalize(GMP $result)
    {
        $result->precision = $this->precision;
        $result->bitmask = $this->bitmask;
        if ($result->bitmask !== false) {
            $flip = $result->value < 0;
            if ($flip) {
                $result->value = -$result->value;
            }
            $result->value = $result->value & $result->bitmask->value;
            if ($flip) {
                $result->value = -$result->value;
            }
        }
        return $result;
    }
    /**
     * Performs some post-processing for randomRangePrime
     *
     * @param Engine $x
     * @param Engine $min
     * @param Engine $max
     * @return GMP
     */
    protected static function randomRangePrimeInner(Engine $x, Engine $min, Engine $max)
    {
        $p = gmp_nextprime($x->value);
        if ($p <= $max->value) {
            return new self($p);
        }
        if ($min->value != $x->value) {
            $x = new self($x->value - 1);
        }
        return self::randomRangePrime($min, $x);
    }
    /**
     * Generate a random prime number between a range
     *
     * If there's not a prime within the given range, false will be returned.
     *
     * @param GMP $min
     * @param GMP $max
     * @return (false | GMP)
     */
    public static function randomRangePrime(GMP $min, GMP $max)
    {
        return self::randomRangePrimeOuter($min, $max);
    }
    /**
    * Generate a random number between a range
    *
    * Returns a random number between $min and $max where $min and $max
    can be defined using one of the two methods:
    *
    * BigInteger::randomRange($min, $max)
    BigInteger::randomRange($max, $min)
    *
    * @param GMP $min
    * @param GMP $max
    * @return GMP
    */
    public static function randomRange(GMP $min, GMP $max)
    {
        return self::randomRangeHelper($min, $max);
    }
    /**
     * Make the current number odd
     *
     * If the current number is odd it'll be unchanged.  If it's even, one will be added to it.
     *
     * @see self::randomPrime()
     */
    protected function make_odd()
    {
        gmp_setbit($this->value, 0);
    }
    /**
     * Tests Primality
     *
     * @param int $t
     * @return bool
     */
    protected function testPrimality($t)
    {
        return gmp_prob_prime($this->value, $t) != 0;
    }
    /**
     * Calculates the nth root of a biginteger.
     *
     * Returns the nth root of a positive biginteger, where n defaults to 2
     *
     * @param int $n
     * @return GMP
     */
    protected function rootInner($n)
    {
        $root = new self();
        $root->value = gmp_root($this->value, $n);
        return $this->normalize($root);
    }
    /**
     * Performs exponentiation.
     *
     * @param GMP $n
     * @return GMP
     */
    public function pow(GMP $n)
    {
        $temp = new self();
        $temp->value = $this->value ** $n->value;
        return $this->normalize($temp);
    }
    /**
     * Return the minimum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param GMP ...$nums
     * @return GMP
     */
    public static function min(GMP ...$nums)
    {
        return self::minHelper($nums);
    }
    /**
     * Return the maximum BigInteger between an arbitrary number of BigIntegers.
     *
     * @param GMP ...$nums
     * @return GMP
     */
    public static function max(GMP ...$nums)
    {
        return self::maxHelper($nums);
    }
    /**
     * Tests BigInteger to see if it is between two integers, inclusive
     *
     * @param GMP $min
     * @param GMP $max
     * @return bool
     */
    public function between(GMP $min, GMP $max)
    {
        return $this->compare($min) >= 0 && $this->compare($max) <= 0;
    }
    /**
    * Create Recurring Modulo Function
    *
    * Sometimes it may be desirable to do repeated modulos with the same number outside of
    modular exponentiation
    *
    * @return callable
    */
    public function createRecurringModuloFunction()
    {
        $temp = $this->value;
        return function (GMP $x) use($temp) {
            return new GMP($x->value % $temp);
        };
    }
    /**
     * Scan for 1 and right shift by that amount
     *
     * ie. $s = gmp_scan1($n, 0) and $r = gmp_div_q($n, gmp_pow(gmp_init('2'), $s));
     *
     * @param GMP $r
     * @return int
     */
    public static function scan1divide(GMP $r)
    {
        $s = gmp_scan1($r->value, 0);
        $r->value >>= $s;
        return $s;
    }
    /**
     * Is Odd?
     *
     * @return boolean
     */
    public function isOdd()
    {
        return gmp_testbit($this->value, 0);
    }
    /**
     * Tests if a bit is set
     *
     * @return boolean
     */
    public function testBit($x)
    {
        return gmp_testbit($this->value, $x);
    }
    /**
     * Is Negative?
     *
     * @return boolean
     */
    public function isNegative()
    {
        return gmp_sign($this->value) == -1;
    }
    /**
     * Negate
     *
     * Given $k, returns -$k
     *
     * @return GMP
     */
    public function negate()
    {
        $temp = clone $this;
        $temp->value = -$this->value;
        return $temp;
    }
}<?php

/**
 * Bootstrapping File for phpseclib
 *
 * composer isn't a requirement for phpseclib 2.0 but this file isn't really required
 * either. it's a bonus for those using composer but if you're not phpseclib will
 * still work
 *
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 */
if (extension_loaded('mbstring')) {
    // 2 - MB_OVERLOAD_STRING
    // mbstring.func_overload is deprecated in php 7.2 and removed in php 8.0.
    if (version_compare(PHP_VERSION, '8.0.0') < 0 && ini_get('mbstring.func_overload') & 2) {
        throw new UnexpectedValueException('Overloading of string functions using mbstring.func_overload is not supported by phpseclib.');
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\Response;
use Amp\Socket\Socket;
use Amp\Websocket\CompressionContext;
use Amp\Websocket\Options;
interface ConnectionFactory
{
    /**
     * @param Response $response
     * @param Socket $socket
     * @param Options $options
     * @param (CompressionContext | null) $compressionContext
     *
     * @return Connection
     */
    public function createConnection(Response $response, Socket $socket, Options $options, ?CompressionContext $compressionContext = null) : Connection;
}<?php

namespace Amp\Websocket\Client;

use Amp\ByteStream\InputStream;
use Amp\Http\Client\Response;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Websocket\ClientMetadata;
use Amp\Websocket\Code;
use Amp\Websocket\Options;
use Amp\Websocket\Rfc6455Client;
final class Rfc6455Connection implements Connection
{
    /** @var Rfc6455Client */
    private $client;
    /** @var Response */
    private $response;
    /**
     *
     */
    public function __construct(Rfc6455Client $client, Response $response)
    {
        $this->client = $client;
        $this->response = $response;
    }
    /**
     *
     */
    public function getResponse() : Response
    {
        return $this->response;
    }
    /**
     *
     */
    public function receive() : Promise
    {
        return $this->client->receive();
    }
    /**
     *
     */
    public function getId() : int
    {
        return $this->client->getId();
    }
    /**
     *
     */
    public function getOptions() : Options
    {
        return $this->client->getOptions();
    }
    /**
     *
     */
    public function isConnected() : bool
    {
        return $this->client->isConnected();
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->client->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->client->getRemoteAddress();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->client->getTlsInfo();
    }
    /**
     *
     */
    public function isClosedByPeer() : bool
    {
        return $this->client->isClosedByPeer();
    }
    /**
     *
     */
    public function getUnansweredPingCount() : int
    {
        return $this->client->getUnansweredPingCount();
    }
    /**
     *
     */
    public function getCloseCode() : int
    {
        return $this->client->getCloseCode();
    }
    /**
     *
     */
    public function getCloseReason() : string
    {
        return $this->client->getCloseReason();
    }
    /**
     *
     */
    public function send(string $data) : Promise
    {
        return $this->client->send($data);
    }
    /**
     *
     */
    public function sendBinary(string $data) : Promise
    {
        return $this->client->sendBinary($data);
    }
    /**
     *
     */
    public function stream(InputStream $stream) : Promise
    {
        return $this->client->stream($stream);
    }
    /**
     *
     */
    public function streamBinary(InputStream $stream) : Promise
    {
        return $this->client->streamBinary($stream);
    }
    /**
     *
     */
    public function ping() : Promise
    {
        return $this->client->ping();
    }
    /**
     *
     */
    public function getInfo() : ClientMetadata
    {
        return $this->client->getInfo();
    }
    /**
     *
     */
    public function close(int $code = Code::NORMAL_CLOSE, string $reason = '') : Promise
    {
        return $this->client->close($code, $reason);
    }
    /**
     *
     */
    public function onClose(callable $onClose) : void
    {
        $this->client->onClose($onClose);
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\Request;
use Amp\Http\Message;
use Amp\Websocket\Options;
use League\Uri;
use Psr\Http\Message\UriInterface as PsrUri;
final class Handshake extends Message
{
    /** @var PsrUri */
    private $uri;
    /** @var Options */
    private $options;
    /** @var int */
    private $tcpConnectTimeout = 10000;
    /** @var int */
    private $tlsHandshakeTimeout = 10000;
    /** @var int */
    private $headerSizeLimit = Request::DEFAULT_HEADER_SIZE_LIMIT;
    /**
    * @param (string | PsrUri) $uri target address of websocket (e.g. ws://foo.bar/bar or a
    wss://crypto.example/?secureConnection) or a PsrUri instance.
    * @param (Options | null) $options
    * @param (string[] | string[][]) $headers
    *
    * @throws \TypeError If $uri is not a string or an instance of PsrUri.
    */
    public function __construct($uri, ?Options $options = null, array $headers = [])
    {
        $this->uri = $this->makeUri($uri);
        $this->options = $this->checkOptions($options);
        $this->setHeaders($headers);
    }
    /**
     * @return PsrUri Websocket URI (scheme will be either ws or wss).
     */
    public function getUri() : PsrUri
    {
        return $this->uri;
    }
    /**
     * @param (string | PsrUri) $uri
     *
     * @return self Cloned object
     */
    public function withUri($uri) : self
    {
        $clone = clone $this;
        $clone->uri = $clone->makeUri($uri);
        return $clone;
    }
    /**
     * @return Options
     */
    public function getOptions() : Options
    {
        return $this->options;
    }
    /**
     * @param Options $options
     *
     * @return self Cloned object.
     */
    public function withOptions(Options $options) : self
    {
        $clone = clone $this;
        $clone->options = $clone->checkOptions($options);
        return $clone;
    }
    /**
     * @return int Timeout in milliseconds for the TCP connection.
     */
    public function getTcpConnectTimeout() : int
    {
        return $this->tcpConnectTimeout;
    }
    /**
     *
     */
    public function withTcpConnectTimeout(int $tcpConnectTimeout) : self
    {
        $clone = clone $this;
        $clone->tcpConnectTimeout = $tcpConnectTimeout;
        return $clone;
    }
    /**
     * @return int Timeout in milliseconds for the TLS handshake.
     */
    public function getTlsHandshakeTimeout() : int
    {
        return $this->tlsHandshakeTimeout;
    }
    /**
     *
     */
    public function withTlsHandshakeTimeout(int $tlsHandshakeTimeout) : self
    {
        $clone = clone $this;
        $clone->tlsHandshakeTimeout = $tlsHandshakeTimeout;
        return $clone;
    }
    /**
     *
     */
    public function getHeaderSizeLimit() : int
    {
        return $this->headerSizeLimit;
    }
    /**
     *
     */
    public function withHeaderSizeLimit(int $headerSizeLimit) : self
    {
        $clone = clone $this;
        $clone->headerSizeLimit = $headerSizeLimit;
        return $clone;
    }
    /**
     * Replaces all headers in the returned instance.
     *
     * @param (string[] | string[][]) $headers
     *
     * @return self Cloned object.
     */
    public function withHeaders(array $headers) : self
    {
        $clone = clone $this;
        foreach ($clone->getRawHeaders() as [$field]) {
            $clone->removeHeader($field);
        }
        $clone->setHeaders($headers);
        return $clone;
    }
    /**
     * Replaces the given header in the returned instance.
     *
     * @param string $name
     * @param (string | string[]) $value
     *
     * @return self Cloned object.
     */
    public function withHeader(string $name, $value) : self
    {
        $clone = clone $this;
        $clone->setHeader($name, $value);
        return $clone;
    }
    /**
     * Adds the given header in the returned instance.
     *
     * @param string $name
     * @param (string | string[]) $value
     *
     * @return self Cloned object.
     */
    public function withAddedHeader(string $name, $value) : self
    {
        $clone = clone $this;
        $clone->addHeader($name, $value);
        return $clone;
    }
    /**
     * Removes the given header in the returned instance.
     *
     * @param string $name
     *
     * @return self Cloned object.
     */
    public function withoutHeader(string $name) : self
    {
        $clone = clone $this;
        $clone->removeHeader($name);
        return $clone;
    }
    /**
     *
     */
    protected function setHeader(string $name, $value) : void
    {
        if (($name[0] ?? ':') === ':') {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::setHeader($name, $value);
    }
    /**
     *
     */
    protected function addHeader(string $name, $value) : void
    {
        if (($name[0] ?? ':') === ':') {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::addHeader($name, $value);
    }
    /**
     * @param (string | PsrUri) $uri
     *
     * @return PsrUri
     */
    private function makeUri($uri) : PsrUri
    {
        if (\is_string($uri)) {
            try {
                $uri = Uri\Http::createFromString($uri);
            } catch (\Exception $exception) {
                throw new \Error('Invalid Websocket URI provided', 0, $exception);
            }
        }
        /** @psalm-suppress DocblockTypeContradiction */
        if (!$uri instanceof PsrUri) {
            throw new \TypeError(\sprintf('Must provide an instance of %s or a websocket URI as a string', PsrUri::class));
        }
        switch ($uri->getScheme()) {
            case 'ws':
            case 'wss':
                break;
            default:
                throw new \Error('The URI scheme must be ws or wss: \'' . $uri->getScheme() . '\'');
        }
        return $uri;
    }
    /**
     *
     */
    private function checkOptions(?Options $options) : Options
    {
        if ($options === null) {
            return Options::createClientDefault();
        }
        return $options;
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\HttpException;
use Amp\Http\Client\Response;
final class ConnectionException extends HttpException
{
    /** @var Response */
    private $response;
    /**
     *
     */
    public function __construct(string $message, Response $response, ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->response = $response;
    }
    /**
     *
     */
    public function getResponse() : Response
    {
        return $this->response;
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Http;
use Amp\Http\Client\HttpClient;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Message;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Websocket;
use Amp\Websocket\CompressionContextFactory;
use Amp\Websocket\Rfc7692CompressionFactory;
use function Amp\call;
final class Rfc6455Connector implements Connector
{
    /** @var HttpClient */
    private $client;
    /** @var ConnectionFactory */
    private $connectionFactory;
    /** @var CompressionContextFactory */
    private $compressionFactory;
    /**
     * @param HttpClient $client
     * @param (ConnectionFactory | null) $connectionFactory Uses {@see Rfc6455ConnectionFactory} if null.
     * @param (CompressionContextFactory | null) $compressionFactory Uses {@see Rfc7692CompressionFactory} if null.
     */
    public function __construct(HttpClient $client, ?ConnectionFactory $connectionFactory = null, ?CompressionContextFactory $compressionFactory = null)
    {
        $this->client = $client;
        $this->connectionFactory = $connectionFactory ?? new Rfc6455ConnectionFactory();
        $this->compressionFactory = $compressionFactory ?? new Rfc7692CompressionFactory();
    }
    /**
     *
     */
    public function connect(Handshake $handshake, ?CancellationToken $cancellationToken = null) : Promise
    {
        return call(function () use($handshake, $cancellationToken) {
            $key = Websocket\generateKey();
            $request = $this->generateRequest($handshake, $key);
            $options = $handshake->getOptions();
            $deferred = new Deferred();
            $connectionFactory = $this->connectionFactory;
            $compressionFactory = $this->compressionFactory;
            $request->setUpgradeHandler(static function (EncryptableSocket $socket, Request $request, Response $response) use($connectionFactory, $compressionFactory, $deferred, $key, $options) : void {
                if (\strtolower((string) $response->getHeader('upgrade')) !== 'websocket') {
                    $deferred->fail(new ConnectionException('Upgrade header does not equal "websocket"', $response));
                    return;
                }
                if (!Websocket\validateAcceptForKey((string) $response->getHeader('sec-websocket-accept'), $key)) {
                    $deferred->fail(new ConnectionException('Invalid Sec-WebSocket-Accept header', $response));
                    return;
                }
                $extensions = self::splitField($response, 'sec-websocket-extensions');
                foreach ($extensions as $extension) {
                    if ($compressionContext = $compressionFactory->fromServerHeader($extension)) {
                        break;
                    }
                }
                $deferred->resolve($connectionFactory->createConnection($response, $socket, $options, $compressionContext ?? null));
            });
            /** @var Response $response */
            $response = (yield $this->client->request($request, $cancellationToken));
            if ($response->getStatus() !== Http\Status::SWITCHING_PROTOCOLS) {
                throw new ConnectionException(\sprintf('A %s (%d) response was not received; instead received response status: %s (%d)', Http\Status::getReason(Http\Status::SWITCHING_PROTOCOLS), Http\Status::SWITCHING_PROTOCOLS, $response->getReason(), $response->getStatus()), $response);
            }
            return (yield $deferred->promise());
        });
    }
    /**
     * @param Handshake $handshake
     * @param string $key
     *
     * @return Request
     */
    private function generateRequest(Handshake $handshake, string $key) : Request
    {
        $uri = $handshake->getUri();
        $uri = $uri->withScheme($uri->getScheme() === 'wss' ? 'https' : 'http');
        $request = new Request($uri, 'GET');
        $request->setHeaders($handshake->getHeaders());
        $request->setTcpConnectTimeout($handshake->getTcpConnectTimeout());
        $request->setTlsHandshakeTimeout($handshake->getTlsHandshakeTimeout());
        $request->setHeaderSizeLimit($handshake->getHeaderSizeLimit());
        if (!$request->hasHeader('origin')) {
            $origin = $uri->withUserInfo('')->withPath('')->withQuery('');
            $request->setHeader('origin', (string) $origin);
        }
        $extensions = self::splitField($request, 'sec-websocket-extensions');
        if ($handshake->getOptions()->isCompressionEnabled() && \extension_loaded('zlib')) {
            $extensions[] = $this->compressionFactory->createRequestHeader();
        }
        if (!empty($extensions)) {
            $request->setHeader('sec-websocket-extensions', \implode(', ', $extensions));
        }
        $request->setProtocolVersions(['1.1']);
        $request->setHeader('connection', 'Upgrade');
        $request->setHeader('upgrade', 'websocket');
        $request->setHeader('sec-websocket-version', '13');
        $request->setHeader('sec-websocket-key', $key);
        return $request;
    }
    /**
     *
     */
    private static function splitField(Message $message, string $headerName) : array
    {
        $header = \implode(', ', $message->getHeaderArray($headerName));
        if ($header === '') {
            return [];
        }
        \preg_match_all('(([^",]+(?:"((?:[^\\\\"]|\\\\.)*)"|([^,]*))?),?\\s*)', $header, $matches, \PREG_SET_ORDER);
        $values = [];
        foreach ($matches as $match) {
            // decode escaped characters
            $values[] = \preg_replace('(\\\\(.))', '\\1', \trim($match[1]));
        }
        return $values;
    }
}<?php

namespace Amp\Websocket\Client;

use Amp\CancellationToken;
use Amp\Http\Client\HttpException;
use Amp\Promise;
interface Connector
{
    /**
     * @param Handshake $handshake
     * @param (CancellationToken | null) $cancellationToken
     *
     * @return Promise<Connection>
     *
     * @throws HttpException Thrown if the request fails.
     * @throws ConnectionException If the response received is invalid or is not a switching protocols (101) response.
     */
    public function connect(Handshake $handshake, ?CancellationToken $cancellationToken = null) : Promise;
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\Response;
use Amp\Websocket\Client;
interface Connection extends Client
{
    /**
     * @return Response Server response originating the client connection.
     */
    public function getResponse() : Response;
}<?php

namespace Amp\Websocket\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Connection\DefaultConnectionFactory;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\HttpException;
use Amp\Promise;
use Amp\Socket\ConnectContext;
use Psr\Http\Message\UriInterface as PsrUri;
/**
 * @param (string | PsrUri | Handshake) $handshake
 * @param (ConnectContext | null) $connectContext
 * @param (CancellationToken | null) $cancellationToken
 *
 * @return Promise<Connection>
 *
 * @throws ConnectionException If the response received is invalid or is not a switching protocols (101) response.
 * @throws HttpException Thrown if the request fails.
 */
function connect($handshake, ?ConnectContext $connectContext = null, ?CancellationToken $cancellationToken = null) : Promise
{
    if (!$handshake instanceof Handshake) {
        $handshake = new Handshake($handshake);
    }
    if ($connectContext === null) {
        $connectContext = (new ConnectContext())->withTcpNoDelay();
    }
    $httpClient = (new HttpClientBuilder())->usingPool(new UnlimitedConnectionPool(new DefaultConnectionFactory(null, $connectContext)))->build();
    return (new Rfc6455Connector($httpClient))->connect($handshake, $cancellationToken);
}<?php

namespace Amp\Websocket\Client;

use Amp\Http\Client\Response;
use Amp\Socket\Socket;
use Amp\Websocket\CompressionContext;
use Amp\Websocket\Options;
use Amp\Websocket\Rfc6455Client;
final class Rfc6455ConnectionFactory implements ConnectionFactory
{
    /**
     *
     */
    public function createConnection(Response $response, Socket $socket, Options $options, ?CompressionContext $compressionContext = null) : Connection
    {
        $client = new Rfc6455Client($socket, $options, true, $compressionContext);
        return new Rfc6455Connection($client, $response);
    }
}<?php

use Amp\ByteStream\StreamException;
use Amp\Loop;
use Amp\Websocket\Client;
use Amp\Websocket\Client\Connection;
use Amp\Websocket\Client\Handshake;
use Amp\Websocket\ClosedException;
use Amp\Websocket\Message;
use Amp\Websocket\Options;
require __DIR__ . '/../vendor/autoload.php';
const AGENT = 'amphp/websocket';
Loop::run(function () {
    $errors = 0;
    $options = Options::createClientDefault()->withBytesPerSecondLimit(\PHP_INT_MAX)->withFrameSizeLimit(\PHP_INT_MAX)->withFramesPerSecondLimit(\PHP_INT_MAX)->withMessageSizeLimit(\PHP_INT_MAX)->withValidateUtf8(true);
    /** @var Connection $connection */
    $connection = (yield Client\connect('ws://127.0.0.1:9001/getCaseCount'));
    /** @var Message $message */
    $message = (yield $connection->receive());
    $cases = (int) (yield $message->buffer());
    echo "Going to run {$cases} test cases." . PHP_EOL;
    for ($i = 1; $i < $cases; $i++) {
        $connection = (yield Client\connect('ws://127.0.0.1:9001/getCaseInfo?case=' . $i . '&agent=' . AGENT));
        $message = (yield $connection->receive());
        $info = \json_decode((yield $message->buffer()), true);
        print $info['id'] . ' ' . \str_repeat('-', 80 - \strlen($info['id']) - 1) . PHP_EOL;
        print \wordwrap($info['description'], 80, PHP_EOL) . ' ';
        $handshake = new Handshake('ws://127.0.0.1:9001/runCase?case=' . $i . '&agent=' . AGENT, $options);
        $connection = (yield Client\connect($handshake));
        try {
            while ($message = (yield $connection->receive())) {
                $content = (yield $message->buffer());
                if ($message->isBinary()) {
                    (yield $connection->sendBinary($content));
                } else {
                    (yield $connection->send($content));
                }
            }
        } catch (ClosedException $e) {
            // ignore
        } catch (AssertionError $e) {
            print 'Assertion error: ' . $e->getMessage() . PHP_EOL;
            $connection->close();
        } catch (Error $e) {
            print 'Error: ' . $e->getMessage() . PHP_EOL;
            $connection->close();
        } catch (StreamException $e) {
            print 'Stream exception: ' . $e->getMessage() . PHP_EOL;
            $connection->close();
        }
        $connection = (yield Client\connect('ws://127.0.0.1:9001/getCaseStatus?case=' . $i . '&agent=' . AGENT));
        $message = (yield $connection->receive());
        print $result = \json_decode((yield $message->buffer()), true)['behavior'];
        if ($result === 'FAILED') {
            $errors++;
        }
        print PHP_EOL . PHP_EOL;
    }
    $connection = (yield Client\connect('ws://127.0.0.1:9001/updateReports?agent=' . AGENT));
    $connection->close();
    Loop::stop();
    if ($errors) {
        exit(1);
    }
});{
    "url": "ws://127.0.0.1:9001",
    "outdir": "./reports/clients",
    "cases": [
        "*"
    ],
    "exclude-cases": [
        "12.2*",
        "12.3*",
        "12.4*",
        "12.5*"
    ]
}
{
    "name": "amphp/websocket-client",
    "description": "Async WebSocket client for PHP based on Amp.",
    "license": "MIT",
    "authors": [
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "support": {
        "issues": "https://github.com/amphp/websocket-client/issues"
    },
    "keywords": [
        "async",
        "non-blocking",
        "websocket",
        "client",
        "http",
        "amp",
        "amphp"
    ],
    "require": {
        "php": ">=7.2",
        "amphp/amp": "^2.2",
        "amphp/http": "^1.3",
        "amphp/http-client": "^4",
        "amphp/socket": "^1",
        "amphp/websocket": "^1",
        "league/uri": "^6",
        "psr/http-message": "^1"
    },
    "require-dev": {
        "amphp/http-server": "^2",
        "amphp/websocket-server": "dev-master as 2.0-rc4",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^8 || ^7",
        "psr/log": "^1",
        "vimeo/psalm": "^3.11@dev"
    },
    "minimum-stability": "RC",
    "autoload": {
        "psr-4": {
            "Amp\\Websocket\\Client\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Websocket\\Client\\Test\\": "test"
        }
    }
}
<?php

/** @noinspection PhpUnusedPrivateFieldInspection */
/** @noinspection PhpDocSignatureInspection */
/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Http2;

use Amp\Http\HPack;
final class Http2Parser
{
    public const PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
    private const DEFAULT_MAX_FRAME_SIZE = 1 << 14;
    private const HEADER_NAME_REGEX = '/^[\\x21-\\x40\\x5b-\\x7e]+$/';
    public const KNOWN_RESPONSE_PSEUDO_HEADERS = [":status" => true];
    public const KNOWN_REQUEST_PSEUDO_HEADERS = [":method" => true, ":authority" => true, ":path" => true, ":scheme" => true];
    // SETTINGS Flags - https://http2.github.io/http2-spec/#rfc.section.6.5
    public const ACK = 0x1;
    // HEADERS Flags - https://http2.github.io/http2-spec/#rfc.section.6.2
    public const NO_FLAG = 0x0;
    public const END_STREAM = 0x1;
    public const END_HEADERS = 0x4;
    public const PADDED = 0x8;
    public const PRIORITY_FLAG = 0x20;
    // Frame Types - https://http2.github.io/http2-spec/#rfc.section.11.2
    public const DATA = 0x0;
    public const HEADERS = 0x1;
    public const PRIORITY = 0x2;
    public const RST_STREAM = 0x3;
    public const SETTINGS = 0x4;
    public const PUSH_PROMISE = 0x5;
    public const PING = 0x6;
    public const GOAWAY = 0x7;
    public const WINDOW_UPDATE = 0x8;
    public const CONTINUATION = 0x9;
    // Settings
    public const HEADER_TABLE_SIZE = 0x1;
    // 1 << 12
    public const ENABLE_PUSH = 0x2;
    // 1
    public const MAX_CONCURRENT_STREAMS = 0x3;
    // INF
    public const INITIAL_WINDOW_SIZE = 0x4;
    // 1 << 16 - 1
    public const MAX_FRAME_SIZE = 0x5;
    // 1 << 14
    public const MAX_HEADER_LIST_SIZE = 0x6;
    // INF
    // Error codes
    public const GRACEFUL_SHUTDOWN = 0x0;
    public const PROTOCOL_ERROR = 0x1;
    public const INTERNAL_ERROR = 0x2;
    public const FLOW_CONTROL_ERROR = 0x3;
    public const SETTINGS_TIMEOUT = 0x4;
    public const STREAM_CLOSED = 0x5;
    public const FRAME_SIZE_ERROR = 0x6;
    public const REFUSED_STREAM = 0x7;
    public const CANCEL = 0x8;
    public const COMPRESSION_ERROR = 0x9;
    public const CONNECT_ERROR = 0xa;
    public const ENHANCE_YOUR_CALM = 0xb;
    public const INADEQUATE_SECURITY = 0xc;
    public const HTTP_1_1_REQUIRED = 0xd;
    /**
     *
     */
    public static function getFrameName(int $type) : string
    {
        $names = [self::DATA => 'DATA', self::HEADERS => 'HEADERS', self::PRIORITY => 'PRIORITY', self::RST_STREAM => 'RST_STREAM', self::SETTINGS => 'SETTINGS', self::PUSH_PROMISE => 'PUSH_PROMISE', self::PING => 'PING', self::GOAWAY => 'GOAWAY', self::WINDOW_UPDATE => 'WINDOW_UPDATE', self::CONTINUATION => 'CONTINUATION'];
        return $names[$type] ?? '0x' . \bin2hex(\chr($type));
    }
    /**
     *
     */
    public static function logDebugFrame(string $action, int $frameType, int $frameFlags, int $streamId, int $frameLength) : bool
    {
        $env = \getenv("AMP_DEBUG_HTTP2_FRAMES") ?: "0";
        if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG_HTTP2_FRAMES") && \AMP_DEBUG_HTTP2_FRAMES) {
            \fwrite(\STDERR, $action . ' ' . self::getFrameName($frameType) . ' <flags = ' . \bin2hex(\chr($frameFlags)) . ', stream = ' . $streamId . ', length = ' . $frameLength . '>
');
        }
        return true;
    }
    /** @var string */
    private $buffer = '';
    /** @var int */
    private $bufferOffset = 0;
    /** @var int */
    private $headerSizeLimit = self::DEFAULT_MAX_FRAME_SIZE;
    // Should be configurable?
    /** @var bool */
    private $continuationExpected = false;
    /** @var int */
    private $headerFrameType = 0;
    /** @var string */
    private $headerBuffer = '';
    /** @var int */
    private $headerStream = 0;
    /** @var HPack */
    private $hpack;
    /** @var Http2Processor */
    private $handler;
    /**
     *
     */
    public function __construct(Http2Processor $handler)
    {
        $this->hpack = new HPack();
        $this->handler = $handler;
    }
    /**
     *
     */
    public function parse(string $settings = null) : \Generator
    {
        if ($settings !== null) {
            $this->parseSettings($settings, \strlen($settings), self::NO_FLAG, 0);
        }
        $this->buffer = yield;
        while (true) {
            $frameHeader = (yield from $this->consume(9));
            ['length' => $frameLength, 'type' => $frameType, 'flags' => $frameFlags, 'id' => $streamId] = \unpack('Nlength/ctype/cflags/Nid', "\x00" . $frameHeader);
            $streamId &= 0x7fffffff;
            $frameBuffer = $frameLength === 0 ? '' : (yield from $this->consume($frameLength));
            \assert(self::logDebugFrame('recv', $frameType, $frameFlags, $streamId, $frameLength));
            try {
                // Do we want to allow increasing the maximum frame size?
                if ($frameLength > self::DEFAULT_MAX_FRAME_SIZE) {
                    throw new Http2ConnectionException("Frame size limit exceeded", self::FRAME_SIZE_ERROR);
                }
                if ($this->continuationExpected && $frameType !== self::CONTINUATION) {
                    throw new Http2ConnectionException("Expected continuation frame", self::PROTOCOL_ERROR);
                }
                switch ($frameType) {
                    case self::DATA:
                        $this->parseDataFrame($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::PUSH_PROMISE:
                        $this->parsePushPromise($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::HEADERS:
                        $this->parseHeaders($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::PRIORITY:
                        $this->parsePriorityFrame($frameBuffer, $frameLength, $streamId);
                        break;
                    case self::RST_STREAM:
                        $this->parseStreamReset($frameBuffer, $frameLength, $streamId);
                        break;
                    case self::SETTINGS:
                        $this->parseSettings($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::PING:
                        $this->parsePing($frameBuffer, $frameLength, $frameFlags, $streamId);
                        break;
                    case self::GOAWAY:
                        $this->parseGoAway($frameBuffer, $frameLength, $streamId);
                        break;
                    case self::WINDOW_UPDATE:
                        $this->parseWindowUpdate($frameBuffer, $frameLength, $streamId);
                        break;
                    case self::CONTINUATION:
                        $this->parseContinuation($frameBuffer, $frameFlags, $streamId);
                        break;
                    default:
                        // Ignore and discard unknown frame per spec
                        break;
                }
            } catch (Http2StreamException $exception) {
                $this->handler->handleStreamException($exception);
            } catch (Http2ConnectionException $exception) {
                $this->handler->handleConnectionException($exception);
                throw $exception;
            }
        }
    }
    /**
     *
     */
    private function consume(int $bytes) : \Generator
    {
        $bufferEnd = $this->bufferOffset + $bytes;
        while (\strlen($this->buffer) < $bufferEnd) {
            $this->buffer .= yield;
        }
        $consumed = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->bufferOffset, $bytes);
        if ($bufferEnd > 2048) {
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $bufferEnd);
            $this->bufferOffset = 0;
        } else {
            $this->bufferOffset += $bytes;
        }
        return $consumed;
    }
    /**
     *
     */
    private function parseDataFrame(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        $isPadded = $frameFlags & self::PADDED;
        $headerLength = $isPadded ? 1 : 0;
        if ($frameLength < $headerLength) {
            $this->throwInvalidFrameSizeError();
        }
        $header = $headerLength === 0 ? '' : \Phabel\Target\Php80\Polyfill::substr($frameBuffer, 0, $headerLength);
        $padding = $isPadded ? \ord($header[0]) : 0;
        if ($streamId === 0) {
            $this->throwInvalidZeroStreamIdError();
        }
        if ($frameLength - $headerLength - $padding < 0) {
            $this->throwInvalidPaddingError();
        }
        $data = \Phabel\Target\Php80\Polyfill::substr($frameBuffer, $headerLength, $frameLength - $headerLength - $padding);
        $this->handler->handleData($streamId, $data);
        if ($frameFlags & self::END_STREAM) {
            $this->handler->handleStreamEnd($streamId);
        }
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.6
     */
    private function parsePushPromise(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        $isPadded = $frameFlags & self::PADDED;
        $headerLength = $isPadded ? 5 : 4;
        if ($frameLength < $headerLength) {
            $this->throwInvalidFrameSizeError();
        }
        $header = \Phabel\Target\Php80\Polyfill::substr($frameBuffer, 0, $headerLength);
        $padding = $isPadded ? \ord($header[0]) : 0;
        $pushId = \unpack("N", $header)[1] & 0x7fffffff;
        if ($frameLength - $headerLength - $padding < 0) {
            $this->throwInvalidPaddingError();
        }
        $this->headerFrameType = self::PUSH_PROMISE;
        $this->pushHeaderBlockFragment($pushId, \Phabel\Target\Php80\Polyfill::substr($frameBuffer, $headerLength, $frameLength - $headerLength - $padding));
        if ($frameFlags & self::END_HEADERS) {
            $this->continuationExpected = false;
            [$pseudo, $headers] = $this->parseHeaderBuffer();
            $this->handler->handlePushPromise($streamId, $pushId, $pseudo, $headers);
        } else {
            $this->continuationExpected = true;
        }
        if ($frameFlags & self::END_STREAM) {
            $this->handler->handleStreamEnd($streamId);
        }
    }
    /**
     *
     */
    private function parseHeaderBuffer() : array
    {
        if ($this->headerStream === 0) {
            throw new Http2ConnectionException('Invalid stream ID 0 for header block', self::PROTOCOL_ERROR);
        }
        if ($this->headerBuffer === '') {
            throw new Http2StreamException('Invalid empty header section', $this->headerStream, self::PROTOCOL_ERROR);
        }
        $decoded = $this->hpack->decode($this->headerBuffer, $this->headerSizeLimit);
        if ($decoded === null) {
            throw new Http2ConnectionException("Compression error in headers", self::COMPRESSION_ERROR);
        }
        $headers = [];
        $pseudo = [];
        foreach ($decoded as [$name, $value]) {
            if (!\preg_match(self::HEADER_NAME_REGEX, $name)) {
                throw new Http2StreamException("Invalid header field name", $this->headerStream, self::PROTOCOL_ERROR);
            }
            if ($name[0] === ':') {
                if (!empty($headers)) {
                    throw new Http2ConnectionException("Pseudo header after other headers", self::PROTOCOL_ERROR);
                }
                if (isset($pseudo[$name])) {
                    throw new Http2ConnectionException("Repeat pseudo header", self::PROTOCOL_ERROR);
                }
                $pseudo[$name] = $value;
                continue;
            }
            $headers[$name][] = $value;
        }
        $this->headerBuffer = '';
        $this->headerStream = 0;
        return [$pseudo, $headers];
    }
    /**
     *
     */
    private function pushHeaderBlockFragment(int $streamId, string $buffer) : void
    {
        if ($this->headerStream !== 0 && $this->headerStream !== $streamId) {
            throw new Http2ConnectionException("Expected CONTINUATION frame for stream ID " . $this->headerStream, self::PROTOCOL_ERROR);
        }
        $this->headerStream = $streamId;
        $this->headerBuffer .= $buffer;
    }
    /**
     * @see https://http2.github.io/http2-spec/#HEADERS
     */
    private function parseHeaders(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        if ($streamId === 0) {
            $this->throwInvalidZeroStreamIdError();
        }
        $headerLength = 0;
        $isPadded = $frameFlags & self::PADDED;
        $isPriority = $frameFlags & self::PRIORITY_FLAG;
        if ($isPadded) {
            $headerLength++;
        }
        if ($isPriority) {
            $headerLength += 5;
        }
        if ($frameLength < $headerLength) {
            $this->throwInvalidFrameSizeError();
        }
        $header = \Phabel\Target\Php80\Polyfill::substr($frameBuffer, 0, $headerLength);
        $padding = $isPadded ? \ord($header[0]) : 0;
        if ($isPriority) {
            ['parent' => $parent, 'weight' => $weight] = \unpack("Nparent/cweight", $header, $isPadded ? 1 : 0);
            $parent &= 0x7fffffff;
            if ($parent === $streamId) {
                $this->throwInvalidRecursiveDependency($streamId);
            }
            $this->handler->handlePriority($streamId, $parent, $weight + 1);
        }
        if ($frameLength - $headerLength - $padding < 0) {
            $this->throwInvalidPaddingError();
        }
        $this->headerFrameType = self::HEADERS;
        $this->pushHeaderBlockFragment($streamId, \Phabel\Target\Php80\Polyfill::substr($frameBuffer, $headerLength, $frameLength - $headerLength - $padding));
        $ended = $frameFlags & self::END_STREAM;
        if ($frameFlags & self::END_HEADERS) {
            $this->continuationExpected = false;
            $headersTooLarge = \strlen($this->headerBuffer) > $this->headerSizeLimit;
            [$pseudo, $headers] = $this->parseHeaderBuffer();
            // This must happen after the parsing, otherwise we loose the connection state and must close the whole
            // connection, which is not what we want hereâ€¦
            if ($headersTooLarge) {
                throw new Http2StreamException("Headers exceed maximum configured size of {$this->headerSizeLimit} bytes", $streamId, self::ENHANCE_YOUR_CALM);
            }
            $this->handler->handleHeaders($streamId, $pseudo, $headers, $ended);
        } else {
            $this->continuationExpected = true;
        }
        if ($ended) {
            $this->handler->handleStreamEnd($streamId);
        }
    }
    /**
     *
     */
    private function parsePriorityFrame(string $frameBuffer, int $frameLength, int $streamId) : void
    {
        if ($frameLength !== 5) {
            $this->throwInvalidFrameSizeError();
        }
        ['parent' => $parent, 'weight' => $weight] = \unpack("Nparent/cweight", $frameBuffer);
        if ($exclusive = $parent & 0x80000000) {
            $parent &= 0x7fffffff;
        }
        if ($streamId === 0) {
            $this->throwInvalidZeroStreamIdError();
        }
        if ($parent === $streamId) {
            $this->throwInvalidRecursiveDependency($streamId);
        }
        $this->handler->handlePriority($streamId, $parent, $weight + 1);
    }
    /**
     *
     */
    private function parseStreamReset(string $frameBuffer, int $frameLength, int $streamId) : void
    {
        if ($frameLength !== 4) {
            $this->throwInvalidFrameSizeError();
        }
        if ($streamId === 0) {
            $this->throwInvalidZeroStreamIdError();
        }
        $errorCode = \unpack('N', $frameBuffer)[1];
        $this->handler->handleStreamReset($streamId, $errorCode);
    }
    /**
     *
     */
    private function parseSettings(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        if ($streamId !== 0) {
            $this->throwInvalidNonZeroStreamIdError();
        }
        if ($frameFlags & self::ACK) {
            if ($frameLength) {
                $this->throwInvalidFrameSizeError();
            }
            return;
            // Got ACK, nothing to do
        }
        if ($frameLength % 6 !== 0) {
            $this->throwInvalidFrameSizeError();
        }
        if ($frameLength > 60) {
            // Even with room for a few future options, sending that a big SETTINGS frame is just about
            // wasting our processing time. We declare this a protocol error.
            throw new Http2ConnectionException("Excessive SETTINGS frame", self::PROTOCOL_ERROR);
        }
        $settings = [];
        while ($frameLength > 0) {
            ['key' => $key, 'value' => $value] = \unpack("nkey/Nvalue", $frameBuffer);
            if ($value < 0) {
                throw new Http2ConnectionException("Invalid setting: {$value}", self::PROTOCOL_ERROR);
            }
            $settings[$key] = $value;
            $frameBuffer = \Phabel\Target\Php80\Polyfill::substr($frameBuffer, 6);
            $frameLength -= 6;
        }
        $this->handler->handleSettings($settings);
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.7
     */
    private function parsePing(string $frameBuffer, int $frameLength, int $frameFlags, int $streamId) : void
    {
        if ($frameLength !== 8) {
            $this->throwInvalidFrameSizeError();
        }
        if ($streamId !== 0) {
            $this->throwInvalidNonZeroStreamIdError();
        }
        if ($frameFlags & self::ACK) {
            $this->handler->handlePong($frameBuffer);
        } else {
            $this->handler->handlePing($frameBuffer);
        }
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.8
     */
    private function parseGoAway(string $frameBuffer, int $frameLength, int $streamId) : void
    {
        if ($frameLength < 8) {
            $this->throwInvalidFrameSizeError();
        }
        if ($streamId !== 0) {
            $this->throwInvalidNonZeroStreamIdError();
        }
        ['last' => $lastId, 'error' => $error] = \unpack("Nlast/Nerror", $frameBuffer);
        $this->handler->handleShutdown($lastId & 0x7fffffff, $error);
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.9
     */
    private function parseWindowUpdate(string $frameBuffer, int $frameLength, int $streamId) : void
    {
        if ($frameLength !== 4) {
            $this->throwInvalidFrameSizeError();
        }
        $windowSize = \unpack('N', $frameBuffer)[1];
        if ($windowSize === 0) {
            if ($streamId) {
                throw new Http2StreamException("Invalid zero window update value", $streamId, self::PROTOCOL_ERROR);
            }
            throw new Http2ConnectionException("Invalid zero window update value", self::PROTOCOL_ERROR);
        }
        if ($streamId) {
            $this->handler->handleStreamWindowIncrement($streamId, $windowSize);
        } else {
            $this->handler->handleConnectionWindowIncrement($windowSize);
        }
    }
    /**
     * @see https://http2.github.io/http2-spec/#rfc.section.6.10
     */
    private function parseContinuation(string $frameBuffer, int $frameFlags, int $streamId) : void
    {
        if ($streamId !== $this->headerStream) {
            throw new Http2ConnectionException("Invalid CONTINUATION frame stream ID", self::PROTOCOL_ERROR);
        }
        if ($this->headerBuffer === '') {
            throw new Http2ConnectionException("Unexpected CONTINUATION frame for stream ID " . $this->headerStream, self::PROTOCOL_ERROR);
        }
        $this->pushHeaderBlockFragment($streamId, $frameBuffer);
        $ended = $frameFlags & self::END_STREAM;
        if ($frameFlags & self::END_HEADERS) {
            $this->continuationExpected = false;
            $isPush = $this->headerFrameType === self::PUSH_PROMISE;
            $pushId = $this->headerStream;
            [$pseudo, $headers] = $this->parseHeaderBuffer();
            if ($isPush) {
                $this->handler->handlePushPromise($streamId, $pushId, $pseudo, $headers);
            } else {
                $this->handler->handleHeaders($streamId, $pseudo, $headers, $ended);
            }
        }
        if ($ended) {
            $this->handler->handleStreamEnd($streamId);
        }
    }
    /**
     *
     */
    private function throwInvalidFrameSizeError() : void
    {
        throw new Http2ConnectionException("Invalid frame length", self::PROTOCOL_ERROR);
    }
    /**
     *
     */
    private function throwInvalidRecursiveDependency(int $streamId) : void
    {
        throw new Http2ConnectionException("Invalid recursive dependency for stream {$streamId}", self::PROTOCOL_ERROR);
    }
    /**
     *
     */
    private function throwInvalidPaddingError() : void
    {
        throw new Http2ConnectionException("Padding greater than length", self::PROTOCOL_ERROR);
    }
    /**
     *
     */
    private function throwInvalidZeroStreamIdError() : void
    {
        throw new Http2ConnectionException("Invalid zero stream ID", self::PROTOCOL_ERROR);
    }
    /**
     *
     */
    private function throwInvalidNonZeroStreamIdError() : void
    {
        throw new Http2ConnectionException("Invalid non-zero stream ID", self::PROTOCOL_ERROR);
    }
}<?php

namespace Amp\Http\Http2;

final class Http2ConnectionException extends \Exception
{
    /**
     *
     */
    public function __construct(string $message, int $code, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Http\Http2;

interface Http2Processor
{
    /**
     *
     */
    public function handlePong(string $data) : void;
    /**
     *
     */
    public function handlePing(string $data) : void;
    /**
     *
     */
    public function handleShutdown(int $lastId, int $error) : void;
    /**
     *
     */
    public function handleStreamWindowIncrement(int $streamId, int $windowSize) : void;
    /**
     *
     */
    public function handleConnectionWindowIncrement(int $windowSize) : void;
    /**
     *
     */
    public function handleHeaders(int $streamId, array $pseudo, array $headers, bool $streamEnded) : void;
    /**
     *
     */
    public function handlePushPromise(int $streamId, int $pushId, array $pseudo, array $headers) : void;
    /**
     *
     */
    public function handlePriority(int $streamId, int $parentId, int $weight) : void;
    /**
     *
     */
    public function handleStreamReset(int $streamId, int $errorCode) : void;
    /**
     *
     */
    public function handleStreamException(Http2StreamException $exception) : void;
    /**
     *
     */
    public function handleConnectionException(Http2ConnectionException $exception) : void;
    /**
     *
     */
    public function handleData(int $streamId, string $data) : void;
    /**
     *
     */
    public function handleSettings(array $settings) : void;
    /**
     *
     */
    public function handleStreamEnd(int $streamId) : void;
}<?php

namespace Amp\Http\Http2;

final class Http2StreamException extends \Exception
{
    /** @var int */
    private $streamId;
    /**
     *
     */
    public function __construct(string $message, int $streamId, int $code, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->streamId = $streamId;
    }
    /**
     *
     */
    public function getStreamId() : int
    {
        return $this->streamId;
    }
}<?php

namespace Amp\Http;

/**
 * @link https://tools.ietf.org/html/rfc7230
 * @link https://tools.ietf.org/html/rfc2616
 * @link https://tools.ietf.org/html/rfc5234
 */
final class Rfc7230
{
    // We make use of possessive modifiers, which gives a slight performance boost
    public const HEADER_NAME_REGEX = "(^([^()<>@,;:\\\"/[\\]?={}\x01- ]++)\$)";
    public const HEADER_VALUE_REGEX = "(^[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\$)";
    public const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\\]?={}\x01- ]++):[ \t]*+((?:[ \t]*+[!-~\x80-\xff]++)*+)[ \t]*+\r\n)m";
    public const HEADER_FOLD_REGEX = "(\r\n[ \t]++)";
    /**
     * Parses headers according to RFC 7230 and 2616.
     *
     * Allows empty header values, as HTTP/1.0 allows that.
     *
     * @param string $rawHeaders
     *
     * @return array Associative array mapping header names to arrays of values.
     *
     * @throws InvalidHeaderException If invalid headers have been passed.
     */
    public static function parseHeaders(string $rawHeaders) : array
    {
        $headers = [];
        foreach (self::parseRawHeaders($rawHeaders) as $header) {
            // Unfortunately, we can't avoid the \strtolower() calls due to \array_change_key_case() behavior
            // when equal headers are present with different casing, e.g. 'set-cookie' and 'Set-Cookie'.
            // Accessing headers directly instead of using foreach (... as list(...)) is slightly faster.
            $headers[\strtolower($header[0])][] = $header[1];
        }
        return $headers;
    }
    /**
     * Parses headers according to RFC 7230 and 2616.
     *
     * Allows empty header values, as HTTP/1.0 allows that.
     *
     * @param string $rawHeaders
     *
     * @return array List of [field, value] header pairs.
     *
     * @throws InvalidHeaderException If invalid headers have been passed.
     */
    public static function parseRawHeaders(string $rawHeaders) : array
    {
        // Ensure that the last line also ends with a newline, this is important.
        \assert(\Phabel\Target\Php80\Polyfill::substr($rawHeaders, -2) === "\r\n", "Argument 1 must end with CRLF: " . \bin2hex($rawHeaders));
        /** @var array[] $matches */
        $count = \preg_match_all(self::HEADER_REGEX, $rawHeaders, $matches, \PREG_SET_ORDER);
        // If these aren't the same, then one line didn't match and there's an invalid header.
        if ($count !== \Phabel\Target\Php80\Polyfill::substr_count($rawHeaders, "\n")) {
            // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4
            if (\preg_match(self::HEADER_FOLD_REGEX, $rawHeaders)) {
                throw new InvalidHeaderException("Invalid header syntax: Obsolete line folding");
            }
            throw new InvalidHeaderException("Invalid header syntax");
        }
        $headers = [];
        foreach ($matches as $match) {
            // We avoid a call to \trim() here due to the regex.
            // Accessing matches directly instead of using foreach (... as list(...)) is slightly faster.
            $headers[] = [$match[1], $match[2]];
        }
        return $headers;
    }
    /**
    * Format headers in to their on-the-wire format.
    *
    * Headers are always validated syntactically. This protects against response splitting and header injection
    attacks.
    *
    * @param array $headers Headers in a format as returned by {@see parseHeaders()}.
    *
    * @return string Formatted headers.
    *
    * @throws InvalidHeaderException If header names or values are invalid.
    */
    public static function formatHeaders(array $headers) : string
    {
        $headerList = [];
        foreach ($headers as $name => $values) {
            foreach ($values as $value) {
                // PHP casts integer-like keys to integers
                $headerList[] = [(string) $name, $value];
            }
        }
        return self::formatRawHeaders($headerList);
    }
    /**
    * Format headers in to their on-the-wire HTTP/1 format.
    *
    * Headers are always validated syntactically. This protects against response splitting and header injection
    attacks.
    *
    * @param array $headers List of headers in [field, value] format as returned by {@see Message::getRawHeaders()}.
    *
    * @return string Formatted headers.
    *
    * @throws InvalidHeaderException If header names or values are invalid.
    */
    public static function formatRawHeaders(array $headers) : string
    {
        $buffer = "";
        $lines = 0;
        foreach ($headers as [$name, $value]) {
            // Ignore any HTTP/2 pseudo headers
            if (($name[0] ?? '') === ':') {
                continue;
            }
            $buffer .= "{$name}: {$value}\r\n";
            $lines++;
        }
        $count = \preg_match_all(self::HEADER_REGEX, $buffer);
        if ($lines !== $count || $lines !== \Phabel\Target\Php80\Polyfill::substr_count($buffer, "\n")) {
            throw new InvalidHeaderException("Invalid headers");
        }
        return $buffer;
    }
}<?php

namespace Amp\Http;

/**
 * Base class for HTTP request and response messages.
 */
abstract class Message
{
    /** @var string[][] */
    private $headers = [];
    /** @var string[][] */
    private $headerCase = [];
    /**
    * Returns the headers as a string-indexed array of arrays of strings or an empty array if no headers
    have been set.
    *
    * @return string[][]
    */
    public function getHeaders() : array
    {
        return $this->headers;
    }
    /**
     * Returns the headers as list of [field, name] pairs in the original casing provided by the application or server.
     *
     * @return array
     */
    public final function getRawHeaders() : array
    {
        $headers = [];
        foreach ($this->headers as $lcName => $values) {
            $size = \count($values);
            for ($i = 0; $i < $size; $i++) {
                $headers[] = [$this->headerCase[$lcName][$i], $values[$i]];
            }
        }
        return $headers;
    }
    /**
     * Returns the array of values for the given header or an empty array if the header does not exist.
     *
     * @param string $name
     *
     * @return string[]
     */
    public function getHeaderArray(string $name) : array
    {
        return $this->headers[\strtolower($name)] ?? [];
    }
    /**
    * Returns the value of the given header. If multiple headers are present for the named header, only the first
    header value will be returned. Use getHeaderArray() to return an array of all values for the particular header.
    Returns null if the header does not exist.
    *
    * @param string $name
    *
    * @return (string | null)
    */
    public function getHeader(string $name)
    {
        return $this->headers[\strtolower($name)][0] ?? null;
    }
    /**
     * Sets the headers from the given array.
     *
     * @param (string[] | string[][]) $headers
     */
    protected function setHeaders(array $headers)
    {
        // Ensure this is an atomic operation, either all headers are set or none.
        $before = $this->headers;
        $beforeCase = $this->headerCase;
        try {
            foreach ($headers as $name => $value) {
                $this->setHeader($name, $value);
            }
        } catch (\Throwable $e) {
            $this->headers = $before;
            $this->headerCase = $beforeCase;
            throw $e;
        }
    }
    /**
     * Sets the named header to the given value.
     *
     * @param string $name
     * @param (string | string[]) $value
     *
     * @throws \Error If the header name or value is invalid.
     */
    protected function setHeader(string $name, $value)
    {
        \assert($this->isNameValid($name), "Invalid header name");
        if (\is_array($value)) {
            if (!$value) {
                $this->removeHeader($name);
                return;
            }
            $value = \array_values(\array_map("strval", $value));
        } else {
            $value = [(string) $value];
        }
        \assert($this->isValueValid($value), "Invalid header value");
        $lcName = \strtolower($name);
        $this->headers[$lcName] = $value;
        $this->headerCase[$lcName] = [];
        foreach ($value as $_) {
            $this->headerCase[$lcName][] = $name;
        }
    }
    /**
     * Adds the value to the named header, or creates the header with the given value if it did not exist.
     *
     * @param string $name
     * @param (string | string[]) $value
     *
     * @throws \Error If the header name or value is invalid.
     */
    protected function addHeader(string $name, $value)
    {
        \assert($this->isNameValid($name), "Invalid header name");
        if (\is_array($value)) {
            if (!$value) {
                return;
            }
            $value = \array_values(\array_map("strval", $value));
        } else {
            $value = [(string) $value];
        }
        \assert($this->isValueValid($value), "Invalid header value");
        $lcName = \strtolower($name);
        if (isset($this->headers[$lcName])) {
            $this->headers[$lcName] = \array_merge($this->headers[$lcName], $value);
            foreach ($value as $_) {
                $this->headerCase[$lcName][] = $name;
            }
        } else {
            $this->headers[$lcName] = $value;
            foreach ($value as $_) {
                $this->headerCase[$lcName][] = $name;
            }
        }
    }
    /**
     * Removes the given header if it exists.
     *
     * @param string $name
     */
    protected function removeHeader(string $name)
    {
        $lcName = \strtolower($name);
        unset($this->headers[$lcName], $this->headerCase[$lcName]);
    }
    /**
     * Checks if given header exists.
     *
     * @param string $name
     *
     * @return bool
     */
    public function hasHeader(string $name) : bool
    {
        return isset($this->headers[\strtolower($name)]);
    }
    /**
     * @param string $name
     *
     * @return bool
     */
    private function isNameValid(string $name) : bool
    {
        return (bool) \preg_match('/^[A-Za-z0-9`~!#$%^&_|\'\\-:]+$/', $name);
    }
    /**
    * Determines if the given value is a valid header value.
    *
    * @param string[] $values
    *
    * @return bool
    *
    * @throws \Error If the given value cannot be converted to a string and is not an array of values that can be
    converted to strings.
    */
    private function isValueValid(array $values) : bool
    {
        foreach ($values as $value) {
            if (\preg_match("/[^\t\r\n -~\x80-\xfe]|\r\n/", $value)) {
                return false;
            }
        }
        return true;
    }
}<?php

namespace Amp\Http;

/**
 * @link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
 */
final class Status
{
    const CONTINUE = 100;
    const SWITCHING_PROTOCOLS = 101;
    const PROCESSING = 102;
    const EARLY_HINTS = 103;
    const OK = 200;
    const CREATED = 201;
    const ACCEPTED = 202;
    const NON_AUTHORITATIVE_INFORMATION = 203;
    const NO_CONTENT = 204;
    const RESET_CONTENT = 205;
    const PARTIAL_CONTENT = 206;
    const MULTI_STATUS = 207;
    const ALREADY_REPORTED = 208;
    const IM_USED = 226;
    const MULTIPLE_CHOICES = 300;
    const MOVED_PERMANENTLY = 301;
    const FOUND = 302;
    const SEE_OTHER = 303;
    const NOT_MODIFIED = 304;
    const USE_PROXY = 305;
    const TEMPORARY_REDIRECT = 307;
    const PERMANENT_REDIRECT = 308;
    const BAD_REQUEST = 400;
    const UNAUTHORIZED = 401;
    const PAYMENT_REQUIRED = 402;
    const FORBIDDEN = 403;
    const NOT_FOUND = 404;
    const METHOD_NOT_ALLOWED = 405;
    const NOT_ACCEPTABLE = 406;
    const PROXY_AUTHENTICATION_REQUIRED = 407;
    const REQUEST_TIMEOUT = 408;
    const CONFLICT = 409;
    const GONE = 410;
    const LENGTH_REQUIRED = 411;
    const PRECONDITION_FAILED = 412;
    const PAYLOAD_TOO_LARGE = 413;
    const URI_TOO_LONG = 414;
    const UNSUPPORTED_MEDIA_TYPE = 415;
    const RANGE_NOT_SATISFIABLE = 416;
    const EXPECTATION_FAILED = 417;
    const MISDIRECTED_REQUEST = 421;
    const UNPROCESSABLE_ENTITY = 422;
    const LOCKED = 423;
    const FAILED_DEPENDENCY = 424;
    const UPGRADE_REQUIRED = 426;
    const PRECONDITION_REQUIRED = 428;
    const TOO_MANY_REQUESTS = 429;
    const REQUEST_HEADER_FIELDS_TOO_LARGE = 431;
    const UNAVAILABLE_FOR_LEGAL_REASONS = 451;
    const INTERNAL_SERVER_ERROR = 500;
    const NOT_IMPLEMENTED = 501;
    const BAD_GATEWAY = 502;
    const SERVICE_UNAVAILABLE = 503;
    const GATEWAY_TIMEOUT = 504;
    const HTTP_VERSION_NOT_SUPPORTED = 505;
    const VARIANT_ALSO_NEGOTIATES = 506;
    const INSUFFICIENT_STORAGE = 507;
    const LOOP_DETECTED = 508;
    const NOT_EXTENDED = 510;
    const NETWORK_AUTHENTICATION_REQUIRED = 511;
    // @codeCoverageIgnoreStart
    /**
     *
     */
    private function __construct()
    {
        // forbid instances
    }
    // @codeCoverageIgnoreEnd
    /**
     *
     */
    public static function getReason(int $code) : string
    {
        return [100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', 103 => 'Early Hints', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-Status', 208 => 'Already Reported', 226 => 'IM Used', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 308 => 'Permanent Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Timeout', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Payload Too Large', 414 => 'URI Too Long', 415 => 'Unsupported Media Type', 416 => 'Range Not Satisfiable', 417 => 'Expectation Failed', 421 => 'Misdirected Request', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons', 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Timeout', 505 => 'HTTP Version Not Supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 510 => 'Not Extended', 511 => 'Network Authentication Required'][$code] ?? '';
    }
}<?php

namespace Amp\Http\Cookie;

final class InvalidCookieException extends \Exception
{
    /**
     *
     */
    public function __construct(string $message)
    {
        parent::__construct($message);
    }
}<?php

namespace Amp\Http\Cookie;

/**
 * A cookie as sent in a response's 'set-cookie' header, so with attributes.
 *
 * This class does not deal with encoding of arbitrary names and values. If you want to use arbitrary values, please use
 * an encoding mechanism like Base64 or URL encoding.
 *
 * @link https://tools.ietf.org/html/rfc6265#section-5.2
 */
final class ResponseCookie
{
    private static $dateFormats = ['D, d M Y H:i:s T', 'D, d-M-y H:i:s T', 'D, d-M-Y H:i:s T', 'D, d-m-y H:i:s T', 'D, d-m-Y H:i:s T', 'D M j G:i:s Y', 'D M d H:i:s Y T'];
    /**
     * Parses a cookie from a 'set-cookie' header.
     *
     * @param string $string Valid 'set-cookie' header line.
     *
     * @return (self | null) Returns a `ResponseCookie` instance on success and `null` on failure.
     */
    public static function fromHeader(string $string) : ?self
    {
        $parts = \array_map("trim", \explode(";", $string));
        $nameValue = \explode("=", \array_shift($parts), 2);
        if (\count($nameValue) !== 2) {
            return null;
        }
        list($name, $value) = $nameValue;
        $name = \trim($name);
        $value = \trim($value, " \t\n\r\x00\v\"");
        if ($name === "") {
            return null;
        }
        // httpOnly must default to false for parsing
        $meta = CookieAttributes::empty();
        $unknownAttributes = [];
        foreach ($parts as $part) {
            $pieces = \array_map('trim', \explode('=', $part, 2));
            $key = \strtolower($pieces[0]);
            if (1 === \count($pieces)) {
                switch ($key) {
                    case 'secure':
                        $meta = $meta->withSecure();
                        break;
                    case 'httponly':
                        $meta = $meta->withHttpOnly();
                        break;
                    default:
                        $unknownAttributes[] = $part;
                        break;
                }
            } else {
                switch ($key) {
                    case 'expires':
                        $time = self::parseDate($pieces[1]);
                        if ($time === null) {
                            break;
                            // break is correct, see https://tools.ietf.org/html/rfc6265#section-5.2.1
                        }
                        $meta = $meta->withExpiry($time);
                        break;
                    case 'max-age':
                        $maxAge = \trim($pieces[1]);
                        // This also allows +1.42, but avoids a more complicated manual check
                        if (!\is_numeric($maxAge)) {
                            break;
                            // break is correct, see https://tools.ietf.org/html/rfc6265#section-5.2.2
                        }
                        $meta = $meta->withMaxAge($maxAge);
                        break;
                    case 'path':
                        $meta = $meta->withPath($pieces[1]);
                        break;
                    case 'domain':
                        $meta = $meta->withDomain($pieces[1]);
                        break;
                    case 'samesite':
                        $normalizedValue = \ucfirst(\strtolower($pieces[1]));
                        if (!\in_array($normalizedValue, [CookieAttributes::SAMESITE_NONE, CookieAttributes::SAMESITE_LAX, CookieAttributes::SAMESITE_STRICT], true)) {
                            $unknownAttributes[] = $part;
                        } else {
                            $meta = $meta->withSameSite($normalizedValue);
                        }
                        break;
                    default:
                        $unknownAttributes[] = $part;
                        break;
                }
            }
        }
        try {
            $cookie = new self($name, $value, $meta);
            $cookie->unknownAttributes = $unknownAttributes;
            return $cookie;
        } catch (InvalidCookieException $e) {
            return null;
        }
    }
    /**
     * @param string $date Formatted cookie date
     *
     * @return (\DateTimeImmutable | null) Parsed date.
     */
    private static function parseDate(string $date) : ?\DateTimeImmutable
    {
        foreach (self::$dateFormats as $dateFormat) {
            if ($parsedDate = \DateTimeImmutable::createFromFormat($dateFormat, $date, new \DateTimeZone('GMT'))) {
                return $parsedDate;
            }
        }
        return null;
    }
    /** @var string[] */
    private $unknownAttributes = [];
    /** @var string */
    private $name;
    /** @var string */
    private $value;
    /** @var CookieAttributes */
    private $attributes;
    /**
     * @param string $name Name of the cookie.
     * @param string $value Value of the cookie.
     * @param CookieAttributes $attributes Attributes of the cookie.
     *
     * @throws InvalidCookieException If name or value is invalid.
     */
    public function __construct(string $name, string $value = '', CookieAttributes $attributes = null)
    {
        if (!\preg_match('(^[^()<>@,;:\\\\"/[\\]?={}\\x01-\\x20\\x7F]++$)', $name)) {
            throw new InvalidCookieException("Invalid cookie name: '{$name}'");
        }
        if (!\preg_match('(^[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*+$)', $value)) {
            throw new InvalidCookieException("Invalid cookie value: '{$value}'");
        }
        $this->name = $name;
        $this->value = $value;
        $this->attributes = $attributes ?? CookieAttributes::default();
    }
    /**
     * @return string Name of the cookie.
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     *
     */
    public function withName(string $name) : self
    {
        if (!\preg_match('(^[^()<>@,;:\\\\"/[\\]?={}\\x01-\\x20\\x7F]++$)', $name)) {
            throw new InvalidCookieException("Invalid cookie name: '{$name}'");
        }
        $clone = clone $this;
        $clone->name = $name;
        return $clone;
    }
    /**
     * @return string Value of the cookie.
     */
    public function getValue() : string
    {
        return $this->value;
    }
    /**
     *
     */
    public function withValue(string $value) : self
    {
        if (!\preg_match('(^[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*+$)', $value)) {
            throw new InvalidCookieException("Invalid cookie value: '{$value}'");
        }
        $clone = clone $this;
        $clone->value = $value;
        return $clone;
    }
    /**
     * @return (\DateTimeImmutable | null) Expiry if set, otherwise `null`.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.1
     */
    public function getExpiry() : ?\DateTimeImmutable
    {
        return $this->attributes->getExpiry();
    }
    /**
     *
     */
    public function withExpiry(\DateTimeInterface $expiry) : self
    {
        return $this->withAttributes($this->attributes->withExpiry($expiry));
    }
    /**
     *
     */
    public function withoutExpiry() : self
    {
        return $this->withAttributes($this->attributes->withoutExpiry());
    }
    /**
     * @return (int | null) Max-Age if set, otherwise `null`.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function getMaxAge() : ?int
    {
        return $this->attributes->getMaxAge();
    }
    /**
     *
     */
    public function withMaxAge(int $maxAge) : self
    {
        return $this->withAttributes($this->attributes->withMaxAge($maxAge));
    }
    /**
     *
     */
    public function withoutMaxAge() : self
    {
        return $this->withAttributes($this->attributes->withoutMaxAge());
    }
    /**
     * @return string Cookie path.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.4
     */
    public function getPath() : string
    {
        return $this->attributes->getPath();
    }
    /**
     *
     */
    public function withPath(string $path) : self
    {
        return $this->withAttributes($this->attributes->withPath($path));
    }
    /**
     * @return string Cookie domain.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.3
     */
    public function getDomain() : string
    {
        return $this->attributes->getDomain();
    }
    /**
     *
     */
    public function withDomain(string $domain) : self
    {
        return $this->withAttributes($this->attributes->withDomain($domain));
    }
    /**
     * @return bool Whether the secure flag is enabled or not.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.5
     */
    public function isSecure() : bool
    {
        return $this->attributes->isSecure();
    }
    /**
     *
     */
    public function withSecure() : self
    {
        return $this->withAttributes($this->attributes->withSecure());
    }
    /**
     *
     */
    public function withoutSecure() : self
    {
        return $this->withAttributes($this->attributes->withoutSecure());
    }
    /**
     * @return bool Whether the httpOnly flag is enabled or not.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.6
     */
    public function isHttpOnly() : bool
    {
        return $this->attributes->isHttpOnly();
    }
    /**
     *
     */
    public function withHttpOnly() : self
    {
        return $this->withAttributes($this->attributes->withHttpOnly());
    }
    /**
     *
     */
    public function withoutHttpOnly() : self
    {
        return $this->withAttributes($this->attributes->withoutHttpOnly());
    }
    /**
     *
     */
    public function withSameSite(string $sameSite) : self
    {
        return $this->withAttributes($this->attributes->withSameSite($sameSite));
    }
    /**
     *
     */
    public function withoutSameSite() : self
    {
        return $this->withAttributes($this->attributes->withoutSameSite());
    }
    /**
     *
     */
    public function getSameSite() : ?string
    {
        return $this->attributes->getSameSite();
    }
    /**
     * @return CookieAttributes All cookie attributes.
     */
    public function getAttributes() : CookieAttributes
    {
        return $this->attributes;
    }
    /**
     *
     */
    public function withAttributes(CookieAttributes $attributes) : self
    {
        $clone = clone $this;
        $clone->attributes = $attributes;
        return $clone;
    }
    /**
     * @return string Representation of the cookie as in a 'set-cookie' header.
     */
    public function __toString() : string
    {
        $line = $this->name . '=' . $this->value;
        $line .= $this->attributes;
        $unknownAttributes = \implode('; ', $this->unknownAttributes);
        if ($unknownAttributes !== '') {
            $line .= '; ' . $unknownAttributes;
        }
        return $line;
    }
}<?php

namespace Amp\Http\Cookie;

/**
 * A cookie as sent in a request's 'cookie' header, so without any attributes.
 *
 * This class does not deal with encoding of arbitrary names and values. If you want to use arbitrary values, please use
 * an encoding mechanism like Base64 or URL encoding.
 *
 * @link https://tools.ietf.org/html/rfc6265#section-5.4
 */
final class RequestCookie
{
    /** @var string */
    private $name;
    /** @var string */
    private $value;
    /**
     * Parses the cookies from a 'cookie' header.
     *
     * Note: Parsing is aborted if there's an invalid value and no cookies are returned.
     *
     * @param string $string Valid 'cookie' header line.
     *
     * @return RequestCookie[]
     */
    public static function fromHeader(string $string) : array
    {
        $cookies = \explode(";", $string);
        $result = [];
        try {
            foreach ($cookies as $cookie) {
                $parts = \explode('=', $cookie, 2);
                if (2 !== \count($parts)) {
                    return [];
                }
                list($name, $value) = $parts;
                // We can safely trim quotes, as they're not allowed within cookie values
                $result[] = new self(\trim($name), \trim($value, " \t\""));
            }
        } catch (InvalidCookieException $e) {
            return [];
        }
        return $result;
    }
    /**
     * @param string $name Cookie name in its decoded form.
     * @param string $value Cookie value in its decoded form.
     *
     * @throws InvalidCookieException If name or value is invalid.
     */
    public function __construct(string $name, string $value = '')
    {
        if (!\preg_match('(^[^()<>@,;:\\\\"/[\\]?={}\\x01-\\x20\\x7F]*+$)', $name)) {
            throw new InvalidCookieException("Invalid cookie name: '{$name}'");
        }
        if (!\preg_match('(^[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*+$)', $value)) {
            throw new InvalidCookieException("Invalid cookie value: '{$value}'");
        }
        $this->name = $name;
        $this->value = $value;
    }
    /**
     * @return string Name of the cookie.
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     *
     */
    public function withName(string $name) : self
    {
        if (!\preg_match('(^[^()<>@,;:\\\\"/[\\]?={}\\x01-\\x20\\x7F]++$)', $name)) {
            throw new InvalidCookieException("Invalid cookie name: '{$name}'");
        }
        $clone = clone $this;
        $clone->name = $name;
        return $clone;
    }
    /**
     * @return string Value of the cookie.
     */
    public function getValue() : string
    {
        return $this->value;
    }
    /**
     *
     */
    public function withValue(string $value) : self
    {
        if (!\preg_match('(^[\\x21\\x23-\\x2B\\x2D-\\x3A\\x3C-\\x5B\\x5D-\\x7E]*+$)', $value)) {
            throw new InvalidCookieException("Invalid cookie value: '{$value}'");
        }
        $clone = clone $this;
        $clone->value = $value;
        return $clone;
    }
    /**
     * @return string Representation of the cookie as in a 'cookie' header.
     */
    public function __toString() : string
    {
        return $this->name . '=' . $this->value;
    }
}<?php

namespace Amp\Http\Cookie;

/**
 * Cookie attributes as defined in https://tools.ietf.org/html/rfc6265.
 *
 * @link https://tools.ietf.org/html/rfc6265
 */
final class CookieAttributes
{
    public const SAMESITE_NONE = 'None';
    public const SAMESITE_LAX = 'Lax';
    public const SAMESITE_STRICT = 'Strict';
    /**
     * @return CookieAttributes No cookie attributes.
     *
     * @see self::default()
     */
    public static function empty() : self
    {
        $new = new self();
        $new->httpOnly = false;
        return $new;
    }
    /**
     * @return CookieAttributes Default cookie attributes, which means httpOnly is enabled by default.
     *
     * @see self::empty()
     */
    public static function default() : self
    {
        return new self();
    }
    /** @var string */
    private $path = '';
    /** @var string */
    private $domain = '';
    /** @var int|null */
    private $maxAge;
    /** @var \DateTimeImmutable */
    private $expiry;
    /** @var bool */
    private $secure = false;
    /** @var bool */
    private $httpOnly = true;
    /** @var string|null */
    private $sameSite;
    /**
     *
     */
    private function __construct()
    {
        // only allow creation via named constructors
    }
    /**
    * @param string $path Cookie path.
    *
    * @return self Cloned instance with the specified operation applied. Cloned instance with the specified operation
    applied.
    *
    * @link https://tools.ietf.org/html/rfc6265#section-5.2.4
    */
    public function withPath(string $path) : self
    {
        $new = clone $this;
        $new->path = $path;
        return $new;
    }
    /**
     * @param string $domain Cookie domain.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.3
     */
    public function withDomain(string $domain) : self
    {
        $new = clone $this;
        $new->domain = $domain;
        return $new;
    }
    /**
     * @param string $sameSite Cookie SameSite attribute value.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-5.3.7
     */
    public function withSameSite(string $sameSite) : self
    {
        $normalizedValue = \ucfirst(\strtolower($sameSite));
        if (!\in_array($normalizedValue, [self::SAMESITE_NONE, self::SAMESITE_LAX, self::SAMESITE_STRICT], true)) {
            throw new \Error("Invalid SameSite attribute: " . $sameSite);
        }
        $new = clone $this;
        $new->sameSite = $normalizedValue;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-5.3.7
     */
    public function withoutSameSite() : self
    {
        $new = clone $this;
        $new->sameSite = null;
        return $new;
    }
    /**
     * Applies the given maximum age to the cookie.
     *
     * @param int $maxAge Cookie maximum age.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withoutMaxAge()
     * @see self::withExpiry()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function withMaxAge(int $maxAge) : self
    {
        $new = clone $this;
        $new->maxAge = $maxAge;
        return $new;
    }
    /**
     * Removes any max-age information.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withMaxAge()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function withoutMaxAge() : self
    {
        $new = clone $this;
        $new->maxAge = null;
        return $new;
    }
    /**
     * Applies the given expiry to the cookie.
     *
     * @param \DateTimeInterface $date
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withMaxAge()
     * @see self::withoutExpiry()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.1
     */
    public function withExpiry(\DateTimeInterface $date) : self
    {
        $new = clone $this;
        if ($date instanceof \DateTimeImmutable) {
            $new->expiry = $date;
        } elseif ($date instanceof \DateTime) {
            $new->expiry = \DateTimeImmutable::createFromMutable($date);
        } else {
            $new->expiry = new \DateTimeImmutable("@" . $date->getTimestamp());
        }
        return $new;
    }
    /**
     * Removes any expiry information.
     *
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withExpiry()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.1
     */
    public function withoutExpiry() : self
    {
        $new = clone $this;
        $new->expiry = null;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withoutSecure()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.5
     */
    public function withSecure() : self
    {
        $new = clone $this;
        $new->secure = true;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withSecure()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.5
     */
    public function withoutSecure() : self
    {
        $new = clone $this;
        $new->secure = false;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withoutHttpOnly()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.6
     */
    public function withHttpOnly() : self
    {
        $new = clone $this;
        $new->httpOnly = true;
        return $new;
    }
    /**
     * @return self Cloned instance with the specified operation applied.
     *
     * @see self::withHttpOnly()
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.6
     */
    public function withoutHttpOnly() : self
    {
        $new = clone $this;
        $new->httpOnly = false;
        return $new;
    }
    /**
     * @return string Cookie path.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.4
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     * @return string Cookie domain.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.3
     */
    public function getDomain() : string
    {
        return $this->domain;
    }
    /**
     * @return string Cookie domain.
     *
     * @link https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-03#section-5.3.7
     */
    public function getSameSite() : ?string
    {
        return $this->sameSite;
    }
    /**
     * @return (int | null) Cookie maximum age in seconds or `null` if no value is set.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function getMaxAge() : ?int
    {
        return $this->maxAge;
    }
    /**
     * @return (\DateTimeImmutable | null) Cookie expiry or `null` if no value is set.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.2
     */
    public function getExpiry() : ?\DateTimeImmutable
    {
        return $this->expiry;
    }
    /**
     * @return bool Whether the secure flag is enabled or not.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.5
     */
    public function isSecure() : bool
    {
        return $this->secure;
    }
    /**
     * @return bool Whether the httpOnly flag is enabled or not.
     *
     * @link https://tools.ietf.org/html/rfc6265#section-5.2.6
     */
    public function isHttpOnly() : bool
    {
        return $this->httpOnly;
    }
    /**
     * @return string Representation of the cookie attributes appended to key=value in a 'set-cookie' header.
     */
    public function __toString() : string
    {
        $string = '';
        if ($this->expiry) {
            $string .= '; Expires=' . \Phabel\Target\Php80\Polyfill::gmdate('D, j M Y G:i:s T', $this->expiry->getTimestamp());
        }
        if ($this->maxAge) {
            $string .= '; Max-Age=' . $this->maxAge;
        }
        if ('' !== $this->path) {
            $string .= '; Path=' . $this->path;
        }
        if ('' !== $this->domain) {
            $string .= '; Domain=' . $this->domain;
        }
        if ($this->secure) {
            $string .= '; Secure';
        }
        if ($this->httpOnly) {
            $string .= '; HttpOnly';
        }
        if ($this->sameSite !== null) {
            $string .= '; SameSite=' . $this->sameSite;
        }
        return $string;
    }
}<?php

namespace Amp\Http;

/**
 * @param Message $message
 * @param string $headerName
 *
 * @return (array | null)
 *
 * @see https://tools.ietf.org/html/rfc7230#section-3.2.6
 */
function parseFieldValueComponents(Message $message, string $headerName) : ?array
{
    $header = \implode(', ', $message->getHeaderArray($headerName));
    if ($header === '') {
        return [];
    }
    \preg_match_all('(([^"=,]+)(?:=(?:"((?:[^\\\\"]|\\\\.)*)"|([^,"]*)))?,?\\s*)', $header, $matches, \PREG_SET_ORDER);
    $totalMatchedLength = 0;
    $pairs = [];
    foreach ($matches as $match) {
        $totalMatchedLength += \strlen($match[0]);
        $key = \trim($match[1]);
        $value = ($match[2] ?? '') . \trim($match[3] ?? '');
        if (($match[2] ?? '') !== '') {
            // decode escaped characters
            $value = \preg_replace('(\\\\(.))', '\\1', $value);
        }
        $pairs[] = [$key, $value];
    }
    if ($totalMatchedLength !== \strlen($header)) {
        return null;
        // parse error
    }
    return $pairs;
}
/**
 * @param array $pairs Output of {@code parseFieldValueComponents}. Keys are handled case-insensitively.
 *
 * @return (array | null) Map of keys to values or {@code null} if incompatible duplicates are found.
 */
function createFieldValueComponentMap(?array $pairs) : ?array
{
    if ($pairs === null) {
        return null;
    }
    $map = [];
    foreach ($pairs as $pair) {
        \assert(\count($pair) === 2);
        \assert(\is_string($pair[0]));
        \assert(\is_string($pair[1]));
    }
    foreach ($pairs as [$key, $value]) {
        $key = \strtolower($key);
        if (isset($map[$key]) && $map[$key] !== $value) {
            return null;
            // incompatible duplicates
        }
        $map[$key] = $value;
    }
    return $map;
}
/**
 * Format timestamp in seconds as an HTTP date header.
 *
 * @param (int | null) $timestamp Timestamp to format, current time if `null`.
 *
 * @return string Formatted date header value.
 */
function formatDateHeader(?int $timestamp = null) : string
{
    static $cachedTimestamp, $cachedFormattedDate;
    $timestamp = $timestamp ?? \time();
    if ($cachedTimestamp === $timestamp) {
        return $cachedFormattedDate;
    }
    return $cachedFormattedDate = \Phabel\Target\Php80\Polyfill::gmdate("D, d M Y H:i:s", $cachedTimestamp = $timestamp) . " GMT";
}<?php

namespace Amp\Http;

final class InvalidHeaderException extends \Exception
{
    /**
     * Thrown on header injection attempts.
     *
     * @param string $reason Reason that can be used as HTTP response reason.
     */
    public function __construct(string $reason)
    {
        parent::__construct($reason);
    }
}{
    "name": "amphp/http",
    "description": "Basic HTTP primitives which can be shared by servers and clients.",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "Amp\\Http\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "require": {
        "php": ">=7.1",
        "amphp/hpack": "^3"
    },
    "require-dev": {
        "phpunit/phpunit": "^7 || ^6.5",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "config": {
        "platform": {
            "php": "7.1.0"
        }
    },
    "scripts": {
        "test": "php vendor/bin/phpunit",
        "code-style": "php vendor/bin/php-cs-fixer fix"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    }
}
{
    "symbol-whitelist": [
        "null",
        "true",
        "false",
        "static",
        "self",
        "parent",
        "array",
        "string",
        "int",
        "float",
        "bool",
        "iterable",
        "callable",
        "void",
        "object",
        "Amp\\File\\Driver",
        "Amp\\File\\exists",
        "Amp\\File\\get",
        "Amp\\File\\isdir",
        "Amp\\File\\mkdir",
        "Amp\\File\\open",
        "Amp\\File\\put",
        "Amp\\File\\size"
    ],
    "php-core-extensions": [
        "Core",
        "date",
        "pcre",
        "Phar",
        "Reflection",
        "SPL",
        "standard"
    ]
}
<?php

namespace Amp\Http\Client\Cookie;

use Amp\Http\Client\HttpException;
use Amp\Http\Cookie\InvalidCookieException;
use Amp\Http\Cookie\RequestCookie;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use Amp\Success;
use Psr\Http\Message\UriInterface as PsrUri;
final class InMemoryCookieJar implements CookieJar
{
    /** @var ResponseCookie[][][] */
    private $cookies = [];
    /**
     *
     */
    public function store(ResponseCookie ...$cookies) : Promise
    {
        foreach ($cookies as $cookie) {
            if ($cookie->getDomain() === '') {
                throw new HttpException("Can't store cookie without domain information.");
            }
            $this->cookies[$cookie->getDomain()][$cookie->getPath() ?: '/'][$cookie->getName()] = $cookie;
        }
        return new Success();
    }
    /**
     *
     */
    public function get(PsrUri $uri) : Promise
    {
        $this->clearExpiredCookies();
        $path = $uri->getPath() ?: '/';
        $domain = $uri->getHost();
        $isRequestSecure = $uri->getScheme() === 'https';
        $matches = [];
        foreach ($this->cookies as $cookieDomain => $domainCookies) {
            if (!$this->matchesDomain($domain, $cookieDomain)) {
                continue;
            }
            foreach ($domainCookies as $cookiePath => $pathCookies) {
                if (!$this->matchesPath($path, $cookiePath)) {
                    continue;
                }
                foreach ($pathCookies as $cookieName => $cookie) {
                    if ($isRequestSecure || !$cookie->isSecure()) {
                        try {
                            $matches[] = new RequestCookie($cookie->getName(), $cookie->getValue());
                        } catch (InvalidCookieException $e) {
                            // ignore cookie
                        }
                    }
                }
            }
        }
        return new Success($matches);
    }
    /**
     *
     */
    public function getAll() : array
    {
        $cookies = [];
        foreach ($this->cookies as $cookiesPerDomain) {
            foreach ($cookiesPerDomain as $cookiesPerPath) {
                foreach ($cookiesPerPath as $cookie) {
                    $cookies[] = $cookie;
                }
            }
        }
        return $cookies;
    }
    /**
     *
     */
    public function clear() : void
    {
        $this->cookies = [];
    }
    /**
     *
     */
    private function clearExpiredCookies() : void
    {
        foreach ($this->cookies as $domain => $domainCookies) {
            foreach ($domainCookies as $path => $pathCookies) {
                foreach ($pathCookies as $name => $cookie) {
                    /** @var ResponseCookie $cookie */
                    if ($cookie->getExpiry() && $cookie->getExpiry()->getTimestamp() < \time()) {
                        unset($this->cookies[$domain][$path][$name]);
                    }
                }
            }
        }
    }
    /**
     * @param string $requestDomain
     * @param string $cookieDomain
     *
     * @return bool
     *
     * @link http://tools.ietf.org/html/rfc6265#section-5.1.3
     */
    private function matchesDomain(string $requestDomain, string $cookieDomain) : bool
    {
        if ($requestDomain === \ltrim($cookieDomain, '.')) {
            return true;
        }
        /** @noinspection SubStrUsedAsStrPosInspection */
        $isWildcardCookieDomain = $cookieDomain[0] === '.';
        if (!$isWildcardCookieDomain) {
            return false;
        }
        if (\filter_var($requestDomain, FILTER_VALIDATE_IP)) {
            return false;
        }
        if (\Phabel\Target\Php80\Polyfill::substr($requestDomain, 0, -\strlen($cookieDomain)) . $cookieDomain === $requestDomain) {
            return true;
        }
        return false;
    }
    /**
     * @link http://tools.ietf.org/html/rfc6265#section-5.1.4
     *
     * @param string $requestPath
     * @param string $cookiePath
     *
     * @return bool
     */
    private function matchesPath(string $requestPath, string $cookiePath) : bool
    {
        if ($requestPath === $cookiePath) {
            return true;
        }
        if (\strpos($requestPath, $cookiePath) !== 0) {
            return false;
        }
        if (\Phabel\Target\Php80\Polyfill::substr($cookiePath, -1) === '/' || $requestPath[\strlen($cookiePath)] === '/') {
            return true;
        }
        return false;
    }
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use Amp\Success;
use Psr\Http\Message\UriInterface as PsrUri;
final class NullCookieJar implements CookieJar
{
    /**
     *
     */
    public function get(PsrUri $uri) : Promise
    {
        return new Success([]);
    }
    /**
     *
     */
    public function store(ResponseCookie ...$cookie) : Promise
    {
        return new Success();
        // nothing to do
    }
}<?php

namespace Amp\Http\Client\Cookie\Internal;

use Amp\Dns\InvalidNameException;
use function Amp\Dns\normalizeName;
/** @internal */
final class PublicSuffixList
{
    private static $initialized = false;
    private static $suffixPatterns;
    private static $exceptionPatterns;
    /**
     * @param string $domain
     *
     * @return bool
     *
     * @throws InvalidNameException
     */
    public static function isPublicSuffix(string $domain) : bool
    {
        if (!self::$initialized) {
            self::readList();
            self::$initialized = true;
        }
        $domain = normalizeName($domain);
        $domain = \implode('.', \array_reverse(\explode('.', \trim($domain, '.'))));
        foreach (self::$exceptionPatterns as $pattern) {
            if (\preg_match($pattern, $domain)) {
                return false;
            }
        }
        foreach (self::$suffixPatterns as $pattern) {
            if (\preg_match($pattern, $domain)) {
                return true;
            }
        }
        return false;
    }
    /**
     *
     */
    private static function readList() : void
    {
        $lines = \file(__DIR__ . '/../../res/public_suffix_list.dat', \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES);
        $exceptions = [];
        $rules = [];
        foreach ($lines as $line) {
            if (\trim($line) === '') {
                continue;
            }
            if (\Phabel\Target\Php80\Polyfill::substr($line, 0, 2) === '//') {
                continue;
            }
            $rule = \strtok($line, " \t");
            try {
                if ($rule[0] === '!') {
                    $exceptions[] = self::toRegex(\Phabel\Target\Php80\Polyfill::substr($rule, 1), true);
                } else {
                    $rules[] = self::toRegex($rule, false);
                }
            } catch (InvalidNameException $e) {
                // ignore IDN rules if no IDN support is available
                // requests with IDNs will fail anyway then
            }
        }
        self::$exceptionPatterns = \array_map(static function ($list) {
            return '(^(?:' . \implode('|', $list) . ')$)i';
        }, \array_chunk($exceptions, 256));
        self::$suffixPatterns = \array_map(static function ($list) {
            return '(^(?:' . \implode('|', $list) . ')$)i';
        }, \array_chunk($rules, 256));
    }
    /**
     * @param string $rule
     * @param bool $exception
     *
     * @return string
     *
     * @throws InvalidNameException
     */
    private static function toRegex(string $rule, bool $exception) : string
    {
        $labels = \explode('.', $rule);
        foreach ($labels as $key => $label) {
            if ($label !== '*') {
                $labels[$key] = normalizeName($label);
            }
        }
        $rule = \implode('.', $labels);
        $regexParts = [];
        foreach (\explode('.', $rule) as $part) {
            if ($part === '*') {
                $regexParts[] = '[^.]+';
            } else {
                /** @noinspection PregQuoteUsageInspection */
                // We use (), so we don't have that problem
                $regexParts[] = \preg_quote($part);
            }
        }
        $regex = \array_reduce($regexParts, static function ($carry, $item) use($exception) {
            if ($carry === '') {
                return $item;
            }
            return $item . "(?:\\." . $carry . ')' . ($exception ? '' : '?');
        }, '');
        return $regex;
    }
    /**
     *
     */
    private function __construct()
    {
        // no instances should be built
    }
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\File;
use Amp\Http\Client\HttpException;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use Amp\Sync\LocalMutex;
use Amp\Sync\Lock;
use Amp\Sync\Mutex;
use Psr\Http\Message\UriInterface as PsrUri;
use function Amp\call;
final class FileCookieJar implements CookieJar
{
    /** @var Promise<InMemoryCookieJar> */
    private $cookieJar;
    /** @var string */
    private $storagePath;
    /** @var Mutex */
    private $mutex;
    /** @var bool */
    private $persistSessionCookies = false;
    /**
     *
     */
    public function __construct(string $storagePath, ?Mutex $mutex = null)
    {
        if (!\interface_exists(File\Driver::class)) {
            throw new \Error(self::class . ' requires amphp/file to be installed. Run composer require amphp/file to install it.');
        }
        $this->storagePath = $storagePath;
        $this->mutex = $mutex ?? new LocalMutex();
    }
    /**
     *
     */
    public function enableSessionCookiePersistence()
    {
        $this->persistSessionCookies = true;
    }
    /**
     *
     */
    public function disableSessionCookiePersistence()
    {
        $this->persistSessionCookies = false;
    }
    /**
     *
     */
    public function get(PsrUri $uri) : Promise
    {
        return call(function () use($uri) {
            /** @var CookieJar $cookieJar */
            $cookieJar = (yield $this->read());
            return $cookieJar->get($uri);
        });
    }
    /**
     *
     */
    public function store(ResponseCookie ...$cookies) : Promise
    {
        return call(function () use($cookies) {
            /** @var InMemoryCookieJar $cookieJar */
            $cookieJar = (yield $this->read());
            (yield $cookieJar->store(...$cookies));
            (yield $this->write($cookieJar));
        });
    }
    /**
     *
     */
    private function read() : Promise
    {
        if ($this->cookieJar) {
            return $this->cookieJar;
        }
        return $this->cookieJar = call(function () {
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire());
            $cookieJar = new InMemoryCookieJar();
            if (!(yield File\exists($this->storagePath))) {
                return $cookieJar;
            }
            $readPromise = \function_exists('Amp\\File\\read') ? File\read($this->storagePath) : File\get($this->storagePath);
            $lines = \explode("\n", (yield $readPromise));
            foreach ($lines as $line) {
                $line = \trim($line);
                if ($line) {
                    $cookie = ResponseCookie::fromHeader($line);
                    if ($cookie === null) {
                        continue;
                    }
                    try {
                        $cookieJar->store($cookie);
                    } catch (HttpException $e) {
                        // ignore invalid cookies in storage
                    }
                }
            }
            $lock->release();
            return $cookieJar;
        });
    }
    /**
     *
     */
    private function write(InMemoryCookieJar $cookieJar) : Promise
    {
        return call(function () use($cookieJar) {
            $cookieData = '';
            foreach ($cookieJar->getAll() as $cookie) {
                /** @var $cookie ResponseCookie */
                if ($cookie->getExpiry() ? $cookie->getExpiry()->getTimestamp() > \time() : $this->persistSessionCookies) {
                    $cookieData .= $cookie . "\r\n";
                }
            }
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire());
            if (\function_exists('Amp\\File\\createDirectoryRecursively')) {
                try {
                    (yield File\createDirectoryRecursively(\dirname($this->storagePath), 0755));
                } catch (File\FilesystemException $e) {
                    throw new HttpException('Failed to create cookie storage directory: ' . $this->storagePath);
                }
                (yield File\write($this->storagePath, $cookieData));
            } else {
                if (!(yield File\isdir(\dirname($this->storagePath)))) {
                    (yield File\mkdir(\dirname($this->storagePath), 0755, true));
                    if (!(yield File\isdir(\dirname($this->storagePath)))) {
                        throw new HttpException('Failed to create cookie storage directory: ' . $this->storagePath);
                    }
                }
                (yield File\put($this->storagePath, $cookieData));
            }
            $lock->release();
        });
    }
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\Http\Client\HttpException;
use Amp\Http\Cookie\RequestCookie;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use Psr\Http\Message\UriInterface as PsrUri;
interface CookieJar
{
    /**
     * Retrieve all cookies matching the specified constraints.
     *
     * @param PsrUri $uri
     *
     * @return Promise<RequestCookie[]> Returns an array (possibly empty) of all cookie matches.
     */
    public function get(PsrUri $uri) : Promise;
    /**
     * Store a cookie.
     *
     * @param ResponseCookie ...$cookie
     *
     * @return Promise
     *
     * @throws HttpException
     */
    public function store(ResponseCookie ...$cookie) : Promise;
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\CancellationToken;
use Amp\Dns\InvalidNameException;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Cookie\Internal\PublicSuffixList;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Cookie\RequestCookie;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Promise;
use function Amp\call;
final class CookieInterceptor implements NetworkInterceptor
{
    /** @var CookieJar */
    private $cookieJar;
    /**
     *
     */
    public function __construct(CookieJar $cookieJar)
    {
        $this->cookieJar = $cookieJar;
    }
    /**
     *
     */
    public function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellation, $stream) {
            yield from $this->assignApplicableRequestCookies($request);
            $request->interceptPush(function (Response $response) {
                yield from $this->storeCookies($response);
            });
            /** @var Response $response */
            $response = (yield $stream->request($request, $cancellation));
            yield from $this->storeCookies($response);
            return $response;
        });
    }
    /**
     *
     */
    private function assignApplicableRequestCookies(Request $request) : \Generator
    {
        $applicableCookies = (yield $this->cookieJar->get($request->getUri()));
        if (!$applicableCookies) {
            return;
            // No cookies matched our request; we're finished.
        }
        $cookiePairs = [];
        /** @var RequestCookie $cookie */
        foreach ($applicableCookies as $cookie) {
            $cookiePairs[] = (string) $cookie;
        }
        if ($cookiePairs) {
            if ($request->hasHeader('cookie')) {
                \array_unshift($cookiePairs, $request->getHeader('cookie'));
            }
            $request->setHeader('cookie', \implode('; ', $cookiePairs));
        }
    }
    /**
     *
     */
    private function createResponseCookie(string $requestDomain, string $rawCookieStr) : ?ResponseCookie
    {
        try {
            $cookie = ResponseCookie::fromHeader($rawCookieStr);
            if ($cookie === null) {
                return null;
            }
            if (!$cookie->getDomain()) {
                $cookie = $cookie->withDomain($requestDomain);
            } else {
                // https://tools.ietf.org/html/rfc6265#section-4.1.2.3
                $cookieDomain = $cookie->getDomain();
                // If a domain is set, left dots are ignored and it's always a wildcard
                $cookieDomain = \ltrim($cookieDomain, '.');
                if ($cookieDomain !== $requestDomain) {
                    // ignore cookies on domains that are public suffixes
                    if (PublicSuffixList::isPublicSuffix($cookieDomain)) {
                        return null;
                    }
                    // cookie origin would not be included when sending the cookie
                    $cookieDomainLength = \strlen($cookieDomain);
                    if (\Phabel\Target\Php80\Polyfill::substr($requestDomain, 0, -$cookieDomainLength - 1) . '.' . $cookieDomain !== $requestDomain) {
                        return null;
                    }
                }
                // always add the dot, it's used internally for wildcard matching when an explicit domain is sent
                $cookie = $cookie->withDomain('.' . $cookieDomain);
            }
            return $cookie;
        } catch (InvalidNameException $e) {
            // Ignore malformed Set-Cookie headers
        }
        return null;
    }
    /**
     * @param Response $response
     *
     * @return \Generator
     * @throws \Amp\Http\Client\HttpException
     */
    private function storeCookies(Response $response) : \Generator
    {
        if ($response->hasHeader('set-cookie')) {
            $requestDomain = $response->getRequest()->getUri()->getHost();
            $rawCookies = $response->getHeaderArray('set-cookie');
            $cookies = [];
            foreach ($rawCookies as $rawCookie) {
                $cookie = $this->createResponseCookie($requestDomain, $rawCookie);
                if ($cookie !== null) {
                    $cookies[] = $cookie;
                }
            }
            if ($cookies) {
                (yield $this->cookieJar->store(...$cookies));
            }
        }
    }
}<?php

use Amp\Http\Client\Cookie\CookieInterceptor;
use Amp\Http\Client\Cookie\FileCookieJar;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Loop;
require __DIR__ . '/../vendor/autoload.php';
Loop::run(static function () {
    $cookieJar = new FileCookieJar(__DIR__ . '/basic-file.cookies');
    $httpClient = (new HttpClientBuilder())->interceptNetwork(new CookieInterceptor($cookieJar))->build();
    /** @var Response $firstResponse */
    $firstResponse = (yield $httpClient->request(new Request('https://google.com/')));
    (yield $firstResponse->getBody()->buffer());
    /** @var Response $secondResponse */
    $secondResponse = (yield $httpClient->request(new Request('https://google.com/')));
    (yield $secondResponse->getBody()->buffer());
    /** @var Response $otherDomainResponse */
    $otherDomainResponse = (yield $httpClient->request(new Request('https://amphp.org/')));
    (yield $otherDomainResponse->getBody()->buffer());
    print "== first request cookies ==\r\n";
    print \implode("\r\n", $firstResponse->getRequest()->getHeaderArray('cookie'));
    print "\r\n\r\n";
    print "== first response cookies ==\r\n";
    print \implode("\r\n", $firstResponse->getHeaderArray('set-cookie'));
    print "\r\n\r\n";
    print "== second request sends cookies back ==\r\n";
    print \implode("\r\n", $secondResponse->getRequest()->getHeaderArray('cookie'));
    print "\r\n\r\n";
    print "== other domain request (might send different cookies) ==\r\n";
    print \implode("\r\n", $otherDomainResponse->getRequest()->getHeaderArray('cookie'));
});<?php

use Amp\Http\Client\Cookie\CookieInterceptor;
use Amp\Http\Client\Cookie\InMemoryCookieJar;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Loop;
require __DIR__ . '/../vendor/autoload.php';
Loop::run(static function () {
    $cookieJar = new InMemoryCookieJar();
    $httpClient = (new HttpClientBuilder())->interceptNetwork(new CookieInterceptor($cookieJar))->build();
    /** @var Response $firstResponse */
    $firstResponse = (yield $httpClient->request(new Request('https://google.com/')));
    (yield $firstResponse->getBody()->buffer());
    /** @var Response $secondResponse */
    $secondResponse = (yield $httpClient->request(new Request('https://google.com/')));
    (yield $secondResponse->getBody()->buffer());
    /** @var Response $otherDomainResponse */
    $otherDomainResponse = (yield $httpClient->request(new Request('https://amphp.org/')));
    (yield $otherDomainResponse->getBody()->buffer());
    print "== first request cookies ==\r\n";
    print \implode("\r\n", $firstResponse->getRequest()->getHeaderArray('cookie'));
    print "\r\n\r\n";
    print "== first response cookies ==\r\n";
    print \implode("\r\n", $firstResponse->getHeaderArray('set-cookie'));
    print "\r\n\r\n";
    print "== second request sends cookies back ==\r\n";
    print \implode("\r\n", $secondResponse->getRequest()->getHeaderArray('cookie'));
    print "\r\n\r\n";
    print "== other domain request does not send cookies ==\r\n";
    print \implode("\r\n", $otherDomainResponse->getRequest()->getHeaderArray('cookie'));
});// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

// Please pull this list from, and only from https://publicsuffix.org/list/public_suffix_list.dat,
// rather than any other VCS sites. Pulling from any other URL is not guaranteed to be supported.

// Instructions on pulling and using this list can be found at https://publicsuffix.org/list/.

// ===BEGIN ICANN DOMAINS===

// ac : https://en.wikipedia.org/wiki/.ac
ac
com.ac
edu.ac
gov.ac
net.ac
mil.ac
org.ac

// ad : https://en.wikipedia.org/wiki/.ad
ad
nom.ad

// ae : https://en.wikipedia.org/wiki/.ae
// see also: "Domain Name Eligibility Policy" at http://www.aeda.ae/eng/aepolicy.php
ae
co.ae
net.ae
org.ae
sch.ae
ac.ae
gov.ae
mil.ae

// aero : see https://www.information.aero/index.php?id=66
aero
accident-investigation.aero
accident-prevention.aero
aerobatic.aero
aeroclub.aero
aerodrome.aero
agents.aero
aircraft.aero
airline.aero
airport.aero
air-surveillance.aero
airtraffic.aero
air-traffic-control.aero
ambulance.aero
amusement.aero
association.aero
author.aero
ballooning.aero
broker.aero
caa.aero
cargo.aero
catering.aero
certification.aero
championship.aero
charter.aero
civilaviation.aero
club.aero
conference.aero
consultant.aero
consulting.aero
control.aero
council.aero
crew.aero
design.aero
dgca.aero
educator.aero
emergency.aero
engine.aero
engineer.aero
entertainment.aero
equipment.aero
exchange.aero
express.aero
federation.aero
flight.aero
fuel.aero
gliding.aero
government.aero
groundhandling.aero
group.aero
hanggliding.aero
homebuilt.aero
insurance.aero
journal.aero
journalist.aero
leasing.aero
logistics.aero
magazine.aero
maintenance.aero
media.aero
microlight.aero
modelling.aero
navigation.aero
parachuting.aero
paragliding.aero
passenger-association.aero
pilot.aero
press.aero
production.aero
recreation.aero
repbody.aero
res.aero
research.aero
rotorcraft.aero
safety.aero
scientist.aero
services.aero
show.aero
skydiving.aero
software.aero
student.aero
trader.aero
trading.aero
trainer.aero
union.aero
workinggroup.aero
works.aero

// af : http://www.nic.af/help.jsp
af
gov.af
com.af
org.af
net.af
edu.af

// ag : http://www.nic.ag/prices.htm
ag
com.ag
org.ag
net.ag
co.ag
nom.ag

// ai : http://nic.com.ai/
ai
off.ai
com.ai
net.ai
org.ai

// al : http://www.ert.gov.al/ert_alb/faq_det.html?Id=31
al
com.al
edu.al
gov.al
mil.al
net.al
org.al

// am : https://www.amnic.net/policy/en/Policy_EN.pdf
am
co.am
com.am
commune.am
net.am
org.am

// ao : https://en.wikipedia.org/wiki/.ao
// http://www.dns.ao/REGISTR.DOC
ao
ed.ao
gv.ao
og.ao
co.ao
pb.ao
it.ao

// aq : https://en.wikipedia.org/wiki/.aq
aq

// ar : https://nic.ar/es/nic-argentina/normativa
ar
bet.ar
com.ar
coop.ar
edu.ar
gob.ar
gov.ar
int.ar
mil.ar
musica.ar
mutual.ar
net.ar
org.ar
senasa.ar
tur.ar

// arpa : https://en.wikipedia.org/wiki/.arpa
// Confirmed by registry <iana-questions@icann.org> 2008-06-18
arpa
e164.arpa
in-addr.arpa
ip6.arpa
iris.arpa
uri.arpa
urn.arpa

// as : https://en.wikipedia.org/wiki/.as
as
gov.as

// asia : https://en.wikipedia.org/wiki/.asia
asia

// at : https://en.wikipedia.org/wiki/.at
// Confirmed by registry <it@nic.at> 2008-06-17
at
ac.at
co.at
gv.at
or.at
sth.ac.at

// au : https://en.wikipedia.org/wiki/.au
// http://www.auda.org.au/
au
// 2LDs
com.au
net.au
org.au
edu.au
gov.au
asn.au
id.au
// Historic 2LDs (closed to new registration, but sites still exist)
info.au
conf.au
oz.au
// CGDNs - http://www.cgdn.org.au/
act.au
nsw.au
nt.au
qld.au
sa.au
tas.au
vic.au
wa.au
// 3LDs
act.edu.au
catholic.edu.au
// eq.edu.au - Removed at the request of the Queensland Department of Education
nsw.edu.au
nt.edu.au
qld.edu.au
sa.edu.au
tas.edu.au
vic.edu.au
wa.edu.au
// act.gov.au  Bug 984824 - Removed at request of Greg Tankard
// nsw.gov.au  Bug 547985 - Removed at request of <Shae.Donelan@services.nsw.gov.au>
// nt.gov.au  Bug 940478 - Removed at request of Greg Connors <Greg.Connors@nt.gov.au>
qld.gov.au
sa.gov.au
tas.gov.au
vic.gov.au
wa.gov.au
// 4LDs
// education.tas.edu.au - Removed at the request of the Department of Education Tasmania
schools.nsw.edu.au

// aw : https://en.wikipedia.org/wiki/.aw
aw
com.aw

// ax : https://en.wikipedia.org/wiki/.ax
ax

// az : https://en.wikipedia.org/wiki/.az
az
com.az
net.az
int.az
gov.az
org.az
edu.az
info.az
pp.az
mil.az
name.az
pro.az
biz.az

// ba : http://nic.ba/users_data/files/pravilnik_o_registraciji.pdf
ba
com.ba
edu.ba
gov.ba
mil.ba
net.ba
org.ba

// bb : https://en.wikipedia.org/wiki/.bb
bb
biz.bb
co.bb
com.bb
edu.bb
gov.bb
info.bb
net.bb
org.bb
store.bb
tv.bb

// bd : https://en.wikipedia.org/wiki/.bd
*.bd

// be : https://en.wikipedia.org/wiki/.be
// Confirmed by registry <tech@dns.be> 2008-06-08
be
ac.be

// bf : https://en.wikipedia.org/wiki/.bf
bf
gov.bf

// bg : https://en.wikipedia.org/wiki/.bg
// https://www.register.bg/user/static/rules/en/index.html
bg
a.bg
b.bg
c.bg
d.bg
e.bg
f.bg
g.bg
h.bg
i.bg
j.bg
k.bg
l.bg
m.bg
n.bg
o.bg
p.bg
q.bg
r.bg
s.bg
t.bg
u.bg
v.bg
w.bg
x.bg
y.bg
z.bg
0.bg
1.bg
2.bg
3.bg
4.bg
5.bg
6.bg
7.bg
8.bg
9.bg

// bh : https://en.wikipedia.org/wiki/.bh
bh
com.bh
edu.bh
net.bh
org.bh
gov.bh

// bi : https://en.wikipedia.org/wiki/.bi
// http://whois.nic.bi/
bi
co.bi
com.bi
edu.bi
or.bi
org.bi

// biz : https://en.wikipedia.org/wiki/.biz
biz

// bj : https://en.wikipedia.org/wiki/.bj
bj
asso.bj
barreau.bj
gouv.bj

// bm : http://www.bermudanic.bm/dnr-text.txt
bm
com.bm
edu.bm
gov.bm
net.bm
org.bm

// bn : http://www.bnnic.bn/faqs
bn
com.bn
edu.bn
gov.bn
net.bn
org.bn

// bo : https://nic.bo/delegacion2015.php#h-1.10
bo
com.bo
edu.bo
gob.bo
int.bo
org.bo
net.bo
mil.bo
tv.bo
web.bo
// Social Domains
academia.bo
agro.bo
arte.bo
blog.bo
bolivia.bo
ciencia.bo
cooperativa.bo
democracia.bo
deporte.bo
ecologia.bo
economia.bo
empresa.bo
indigena.bo
industria.bo
info.bo
medicina.bo
movimiento.bo
musica.bo
natural.bo
nombre.bo
noticias.bo
patria.bo
politica.bo
profesional.bo
plurinacional.bo
pueblo.bo
revista.bo
salud.bo
tecnologia.bo
tksat.bo
transporte.bo
wiki.bo

// br : http://registro.br/dominio/categoria.html
// Submitted by registry <fneves@registro.br>
br
9guacu.br
abc.br
adm.br
adv.br
agr.br
aju.br
am.br
anani.br
aparecida.br
app.br
arq.br
art.br
ato.br
b.br
barueri.br
belem.br
bhz.br
bib.br
bio.br
blog.br
bmd.br
boavista.br
bsb.br
campinagrande.br
campinas.br
caxias.br
cim.br
cng.br
cnt.br
com.br
contagem.br
coop.br
coz.br
cri.br
cuiaba.br
curitiba.br
def.br
des.br
det.br
dev.br
ecn.br
eco.br
edu.br
emp.br
enf.br
eng.br
esp.br
etc.br
eti.br
far.br
feira.br
flog.br
floripa.br
fm.br
fnd.br
fortal.br
fot.br
foz.br
fst.br
g12.br
geo.br
ggf.br
goiania.br
gov.br
// gov.br 26 states + df https://en.wikipedia.org/wiki/States_of_Brazil
ac.gov.br
al.gov.br
am.gov.br
ap.gov.br
ba.gov.br
ce.gov.br
df.gov.br
es.gov.br
go.gov.br
ma.gov.br
mg.gov.br
ms.gov.br
mt.gov.br
pa.gov.br
pb.gov.br
pe.gov.br
pi.gov.br
pr.gov.br
rj.gov.br
rn.gov.br
ro.gov.br
rr.gov.br
rs.gov.br
sc.gov.br
se.gov.br
sp.gov.br
to.gov.br
gru.br
imb.br
ind.br
inf.br
jab.br
jampa.br
jdf.br
joinville.br
jor.br
jus.br
leg.br
lel.br
log.br
londrina.br
macapa.br
maceio.br
manaus.br
maringa.br
mat.br
med.br
mil.br
morena.br
mp.br
mus.br
natal.br
net.br
niteroi.br
*.nom.br
not.br
ntr.br
odo.br
ong.br
org.br
osasco.br
palmas.br
poa.br
ppg.br
pro.br
psc.br
psi.br
pvh.br
qsl.br
radio.br
rec.br
recife.br
rep.br
ribeirao.br
rio.br
riobranco.br
riopreto.br
salvador.br
sampa.br
santamaria.br
santoandre.br
saobernardo.br
saogonca.br
seg.br
sjc.br
slg.br
slz.br
sorocaba.br
srv.br
taxi.br
tc.br
tec.br
teo.br
the.br
tmp.br
trd.br
tur.br
tv.br
udi.br
vet.br
vix.br
vlog.br
wiki.br
zlg.br

// bs : http://www.nic.bs/rules.html
bs
com.bs
net.bs
org.bs
edu.bs
gov.bs

// bt : https://en.wikipedia.org/wiki/.bt
bt
com.bt
edu.bt
gov.bt
net.bt
org.bt

// bv : No registrations at this time.
// Submitted by registry <jarle@uninett.no>
bv

// bw : https://en.wikipedia.org/wiki/.bw
// http://www.gobin.info/domainname/bw.doc
// list of other 2nd level tlds ?
bw
co.bw
org.bw

// by : https://en.wikipedia.org/wiki/.by
// http://tld.by/rules_2006_en.html
// list of other 2nd level tlds ?
by
gov.by
mil.by
// Official information does not indicate that com.by is a reserved
// second-level domain, but it's being used as one (see www.google.com.by and
// www.yahoo.com.by, for example), so we list it here for safety's sake.
com.by

// http://hoster.by/
of.by

// bz : https://en.wikipedia.org/wiki/.bz
// http://www.belizenic.bz/
bz
com.bz
net.bz
org.bz
edu.bz
gov.bz

// ca : https://en.wikipedia.org/wiki/.ca
ca
// ca geographical names
ab.ca
bc.ca
mb.ca
nb.ca
nf.ca
nl.ca
ns.ca
nt.ca
nu.ca
on.ca
pe.ca
qc.ca
sk.ca
yk.ca
// gc.ca: https://en.wikipedia.org/wiki/.gc.ca
// see also: http://registry.gc.ca/en/SubdomainFAQ
gc.ca

// cat : https://en.wikipedia.org/wiki/.cat
cat

// cc : https://en.wikipedia.org/wiki/.cc
cc

// cd : https://en.wikipedia.org/wiki/.cd
// see also: https://www.nic.cd/domain/insertDomain_2.jsp?act=1
cd
gov.cd

// cf : https://en.wikipedia.org/wiki/.cf
cf

// cg : https://en.wikipedia.org/wiki/.cg
cg

// ch : https://en.wikipedia.org/wiki/.ch
ch

// ci : https://en.wikipedia.org/wiki/.ci
// http://www.nic.ci/index.php?page=charte
ci
org.ci
or.ci
com.ci
co.ci
edu.ci
ed.ci
ac.ci
net.ci
go.ci
asso.ci
aÃ©roport.ci
int.ci
presse.ci
md.ci
gouv.ci

// ck : https://en.wikipedia.org/wiki/.ck
*.ck
!www.ck

// cl : https://www.nic.cl
// Confirmed by .CL registry <hsalgado@nic.cl>
cl
co.cl
gob.cl
gov.cl
mil.cl

// cm : https://en.wikipedia.org/wiki/.cm plus bug 981927
cm
co.cm
com.cm
gov.cm
net.cm

// cn : https://en.wikipedia.org/wiki/.cn
// Submitted by registry <tanyaling@cnnic.cn>
cn
ac.cn
com.cn
edu.cn
gov.cn
net.cn
org.cn
mil.cn
å…¬å�¸.cn
ç½‘ç»œ.cn
ç¶²çµ¡.cn
// cn geographic names
ah.cn
bj.cn
cq.cn
fj.cn
gd.cn
gs.cn
gz.cn
gx.cn
ha.cn
hb.cn
he.cn
hi.cn
hl.cn
hn.cn
jl.cn
js.cn
jx.cn
ln.cn
nm.cn
nx.cn
qh.cn
sc.cn
sd.cn
sh.cn
sn.cn
sx.cn
tj.cn
xj.cn
xz.cn
yn.cn
zj.cn
hk.cn
mo.cn
tw.cn

// co : https://en.wikipedia.org/wiki/.co
// Submitted by registry <tecnico@uniandes.edu.co>
co
arts.co
com.co
edu.co
firm.co
gov.co
info.co
int.co
mil.co
net.co
nom.co
org.co
rec.co
web.co

// com : https://en.wikipedia.org/wiki/.com
com

// coop : https://en.wikipedia.org/wiki/.coop
coop

// cr : http://www.nic.cr/niccr_publico/showRegistroDominiosScreen.do
cr
ac.cr
co.cr
ed.cr
fi.cr
go.cr
or.cr
sa.cr

// cu : https://en.wikipedia.org/wiki/.cu
cu
com.cu
edu.cu
org.cu
net.cu
gov.cu
inf.cu

// cv : https://en.wikipedia.org/wiki/.cv
// cv : http://www.dns.cv/tldcv_portal/do?com=DS;5446457100;111;+PAGE(4000018)+K-CAT-CODIGO(RDOM)+RCNT(100); <- registration rules
cv
com.cv
edu.cv
int.cv
nome.cv
org.cv

// cw : http://www.una.cw/cw_registry/
// Confirmed by registry <registry@una.net> 2013-03-26
cw
com.cw
edu.cw
net.cw
org.cw

// cx : https://en.wikipedia.org/wiki/.cx
// list of other 2nd level tlds ?
cx
gov.cx

// cy : http://www.nic.cy/
// Submitted by registry Panayiotou Fotia <cydns@ucy.ac.cy>
cy
ac.cy
biz.cy
com.cy
ekloges.cy
gov.cy
ltd.cy
name.cy
net.cy
org.cy
parliament.cy
press.cy
pro.cy
tm.cy

// cz : https://en.wikipedia.org/wiki/.cz
cz

// de : https://en.wikipedia.org/wiki/.de
// Confirmed by registry <ops@denic.de> (with technical
// reservations) 2008-07-01
de

// dj : https://en.wikipedia.org/wiki/.dj
dj

// dk : https://en.wikipedia.org/wiki/.dk
// Confirmed by registry <robert@dk-hostmaster.dk> 2008-06-17
dk

// dm : https://en.wikipedia.org/wiki/.dm
dm
com.dm
net.dm
org.dm
edu.dm
gov.dm

// do : https://en.wikipedia.org/wiki/.do
do
art.do
com.do
edu.do
gob.do
gov.do
mil.do
net.do
org.do
sld.do
web.do

// dz : http://www.nic.dz/images/pdf_nic/charte.pdf
dz
art.dz
asso.dz
com.dz
edu.dz
gov.dz
org.dz
net.dz
pol.dz
soc.dz
tm.dz

// ec : http://www.nic.ec/reg/paso1.asp
// Submitted by registry <vabboud@nic.ec>
ec
com.ec
info.ec
net.ec
fin.ec
k12.ec
med.ec
pro.ec
org.ec
edu.ec
gov.ec
gob.ec
mil.ec

// edu : https://en.wikipedia.org/wiki/.edu
edu

// ee : http://www.eenet.ee/EENet/dom_reeglid.html#lisa_B
ee
edu.ee
gov.ee
riik.ee
lib.ee
med.ee
com.ee
pri.ee
aip.ee
org.ee
fie.ee

// eg : https://en.wikipedia.org/wiki/.eg
eg
com.eg
edu.eg
eun.eg
gov.eg
mil.eg
name.eg
net.eg
org.eg
sci.eg

// er : https://en.wikipedia.org/wiki/.er
*.er

// es : https://www.nic.es/site_ingles/ingles/dominios/index.html
es
com.es
nom.es
org.es
gob.es
edu.es

// et : https://en.wikipedia.org/wiki/.et
et
com.et
gov.et
org.et
edu.et
biz.et
name.et
info.et
net.et

// eu : https://en.wikipedia.org/wiki/.eu
eu

// fi : https://en.wikipedia.org/wiki/.fi
fi
// aland.fi : https://en.wikipedia.org/wiki/.ax
// This domain is being phased out in favor of .ax. As there are still many
// domains under aland.fi, we still keep it on the list until aland.fi is
// completely removed.
// TODO: Check for updates (expected to be phased out around Q1/2009)
aland.fi

// fj : http://domains.fj/
// Submitted by registry <garth.miller@cocca.org.nz> 2020-02-11
fj
ac.fj
biz.fj
com.fj
gov.fj
info.fj
mil.fj
name.fj
net.fj
org.fj
pro.fj

// fk : https://en.wikipedia.org/wiki/.fk
*.fk

// fm : https://en.wikipedia.org/wiki/.fm
com.fm
edu.fm
net.fm
org.fm
fm

// fo : https://en.wikipedia.org/wiki/.fo
fo

// fr : http://www.afnic.fr/
// domaines descriptifs : https://www.afnic.fr/medias/documents/Cadre_legal/Afnic_Naming_Policy_12122016_VEN.pdf
fr
asso.fr
com.fr
gouv.fr
nom.fr
prd.fr
tm.fr
// domaines sectoriels : https://www.afnic.fr/en/products-and-services/the-fr-tld/sector-based-fr-domains-4.html
aeroport.fr
avocat.fr
avoues.fr
cci.fr
chambagri.fr
chirurgiens-dentistes.fr
experts-comptables.fr
geometre-expert.fr
greta.fr
huissier-justice.fr
medecin.fr
notaires.fr
pharmacien.fr
port.fr
veterinaire.fr

// ga : https://en.wikipedia.org/wiki/.ga
ga

// gb : This registry is effectively dormant
// Submitted by registry <Damien.Shaw@ja.net>
gb

// gd : https://en.wikipedia.org/wiki/.gd
edu.gd
gov.gd
gd

// ge : http://www.nic.net.ge/policy_en.pdf
ge
com.ge
edu.ge
gov.ge
org.ge
mil.ge
net.ge
pvt.ge

// gf : https://en.wikipedia.org/wiki/.gf
gf

// gg : http://www.channelisles.net/register-domains/
// Confirmed by registry <nigel@channelisles.net> 2013-11-28
gg
co.gg
net.gg
org.gg

// gh : https://en.wikipedia.org/wiki/.gh
// see also: http://www.nic.gh/reg_now.php
// Although domains directly at second level are not possible at the moment,
// they have been possible for some time and may come back.
gh
com.gh
edu.gh
gov.gh
org.gh
mil.gh

// gi : http://www.nic.gi/rules.html
gi
com.gi
ltd.gi
gov.gi
mod.gi
edu.gi
org.gi

// gl : https://en.wikipedia.org/wiki/.gl
// http://nic.gl
gl
co.gl
com.gl
edu.gl
net.gl
org.gl

// gm : http://www.nic.gm/htmlpages%5Cgm-policy.htm
gm

// gn : http://psg.com/dns/gn/gn.txt
// Submitted by registry <randy@psg.com>
gn
ac.gn
com.gn
edu.gn
gov.gn
org.gn
net.gn

// gov : https://en.wikipedia.org/wiki/.gov
gov

// gp : http://www.nic.gp/index.php?lang=en
gp
com.gp
net.gp
mobi.gp
edu.gp
org.gp
asso.gp

// gq : https://en.wikipedia.org/wiki/.gq
gq

// gr : https://grweb.ics.forth.gr/english/1617-B-2005.html
// Submitted by registry <segred@ics.forth.gr>
gr
com.gr
edu.gr
net.gr
org.gr
gov.gr

// gs : https://en.wikipedia.org/wiki/.gs
gs

// gt : https://www.gt/sitio/registration_policy.php?lang=en
gt
com.gt
edu.gt
gob.gt
ind.gt
mil.gt
net.gt
org.gt

// gu : http://gadao.gov.gu/register.html
// University of Guam : https://www.uog.edu
// Submitted by uognoc@triton.uog.edu
gu
com.gu
edu.gu
gov.gu
guam.gu
info.gu
net.gu
org.gu
web.gu

// gw : https://en.wikipedia.org/wiki/.gw
// gw : https://nic.gw/regras/
gw

// gy : https://en.wikipedia.org/wiki/.gy
// http://registry.gy/
gy
co.gy
com.gy
edu.gy
gov.gy
net.gy
org.gy

// hk : https://www.hkirc.hk
// Submitted by registry <hk.tech@hkirc.hk>
hk
com.hk
edu.hk
gov.hk
idv.hk
net.hk
org.hk
å…¬å�¸.hk
æ•™è‚².hk
æ•Žè‚².hk
æ”¿åºœ.hk
å€‹äºº.hk
ä¸ªäºº.hk
ç®‡äºº.hk
ç¶²ç»œ.hk
ç½‘ç»œ.hk
ç»„ç¹”.hk
ç¶²çµ¡.hk
ç½‘çµ¡.hk
ç»„ç»‡.hk
çµ„ç¹”.hk
çµ„ç»‡.hk

// hm : https://en.wikipedia.org/wiki/.hm
hm

// hn : http://www.nic.hn/politicas/ps02,,05.html
hn
com.hn
edu.hn
org.hn
net.hn
mil.hn
gob.hn

// hr : http://www.dns.hr/documents/pdf/HRTLD-regulations.pdf
hr
iz.hr
from.hr
name.hr
com.hr

// ht : http://www.nic.ht/info/charte.cfm
ht
com.ht
shop.ht
firm.ht
info.ht
adult.ht
net.ht
pro.ht
org.ht
med.ht
art.ht
coop.ht
pol.ht
asso.ht
edu.ht
rel.ht
gouv.ht
perso.ht

// hu : http://www.domain.hu/domain/English/sld.html
// Confirmed by registry <pasztor@iszt.hu> 2008-06-12
hu
co.hu
info.hu
org.hu
priv.hu
sport.hu
tm.hu
2000.hu
agrar.hu
bolt.hu
casino.hu
city.hu
erotica.hu
erotika.hu
film.hu
forum.hu
games.hu
hotel.hu
ingatlan.hu
jogasz.hu
konyvelo.hu
lakas.hu
media.hu
news.hu
reklam.hu
sex.hu
shop.hu
suli.hu
szex.hu
tozsde.hu
utazas.hu
video.hu

// id : https://pandi.id/en/domain/registration-requirements/
id
ac.id
biz.id
co.id
desa.id
go.id
mil.id
my.id
net.id
or.id
ponpes.id
sch.id
web.id

// ie : https://en.wikipedia.org/wiki/.ie
ie
gov.ie

// il : http://www.isoc.org.il/domains/
il
ac.il
co.il
gov.il
idf.il
k12.il
muni.il
net.il
org.il

// im : https://www.nic.im/
// Submitted by registry <info@nic.im>
im
ac.im
co.im
com.im
ltd.co.im
net.im
org.im
plc.co.im
tt.im
tv.im

// in : https://en.wikipedia.org/wiki/.in
// see also: https://registry.in/Policies
// Please note, that nic.in is not an official eTLD, but used by most
// government institutions.
in
co.in
firm.in
net.in
org.in
gen.in
ind.in
nic.in
ac.in
edu.in
res.in
gov.in
mil.in

// info : https://en.wikipedia.org/wiki/.info
info

// int : https://en.wikipedia.org/wiki/.int
// Confirmed by registry <iana-questions@icann.org> 2008-06-18
int
eu.int

// io : http://www.nic.io/rules.html
// list of other 2nd level tlds ?
io
com.io

// iq : http://www.cmc.iq/english/iq/iqregister1.htm
iq
gov.iq
edu.iq
mil.iq
com.iq
org.iq
net.iq

// ir : http://www.nic.ir/Terms_and_Conditions_ir,_Appendix_1_Domain_Rules
// Also see http://www.nic.ir/Internationalized_Domain_Names
// Two <iran>.ir entries added at request of <tech-team@nic.ir>, 2010-04-16
ir
ac.ir
co.ir
gov.ir
id.ir
net.ir
org.ir
sch.ir
// xn--mgba3a4f16a.ir (<iran>.ir, Persian YEH)
Ø§ÛŒØ±Ø§Ù†.ir
// xn--mgba3a4fra.ir (<iran>.ir, Arabic YEH)
Ø§ÙŠØ±Ø§Ù†.ir

// is : http://www.isnic.is/domain/rules.php
// Confirmed by registry <marius@isgate.is> 2008-12-06
is
net.is
com.is
edu.is
gov.is
org.is
int.is

// it : https://en.wikipedia.org/wiki/.it
it
gov.it
edu.it
// Reserved geo-names (regions and provinces):
// https://www.nic.it/sites/default/files/archivio/docs/Regulation_assignation_v7.1.pdf
// Regions
abr.it
abruzzo.it
aosta-valley.it
aostavalley.it
bas.it
basilicata.it
cal.it
calabria.it
cam.it
campania.it
emilia-romagna.it
emiliaromagna.it
emr.it
friuli-v-giulia.it
friuli-ve-giulia.it
friuli-vegiulia.it
friuli-venezia-giulia.it
friuli-veneziagiulia.it
friuli-vgiulia.it
friuliv-giulia.it
friulive-giulia.it
friulivegiulia.it
friulivenezia-giulia.it
friuliveneziagiulia.it
friulivgiulia.it
fvg.it
laz.it
lazio.it
lig.it
liguria.it
lom.it
lombardia.it
lombardy.it
lucania.it
mar.it
marche.it
mol.it
molise.it
piedmont.it
piemonte.it
pmn.it
pug.it
puglia.it
sar.it
sardegna.it
sardinia.it
sic.it
sicilia.it
sicily.it
taa.it
tos.it
toscana.it
trentin-sud-tirol.it
trentin-sÃ¼d-tirol.it
trentin-sudtirol.it
trentin-sÃ¼dtirol.it
trentin-sued-tirol.it
trentin-suedtirol.it
trentino-a-adige.it
trentino-aadige.it
trentino-alto-adige.it
trentino-altoadige.it
trentino-s-tirol.it
trentino-stirol.it
trentino-sud-tirol.it
trentino-sÃ¼d-tirol.it
trentino-sudtirol.it
trentino-sÃ¼dtirol.it
trentino-sued-tirol.it
trentino-suedtirol.it
trentino.it
trentinoa-adige.it
trentinoaadige.it
trentinoalto-adige.it
trentinoaltoadige.it
trentinos-tirol.it
trentinostirol.it
trentinosud-tirol.it
trentinosÃ¼d-tirol.it
trentinosudtirol.it
trentinosÃ¼dtirol.it
trentinosued-tirol.it
trentinosuedtirol.it
trentinsud-tirol.it
trentinsÃ¼d-tirol.it
trentinsudtirol.it
trentinsÃ¼dtirol.it
trentinsued-tirol.it
trentinsuedtirol.it
tuscany.it
umb.it
umbria.it
val-d-aosta.it
val-daosta.it
vald-aosta.it
valdaosta.it
valle-aosta.it
valle-d-aosta.it
valle-daosta.it
valleaosta.it
valled-aosta.it
valledaosta.it
vallee-aoste.it
vallÃ©e-aoste.it
vallee-d-aoste.it
vallÃ©e-d-aoste.it
valleeaoste.it
vallÃ©eaoste.it
valleedaoste.it
vallÃ©edaoste.it
vao.it
vda.it
ven.it
veneto.it
// Provinces
ag.it
agrigento.it
al.it
alessandria.it
alto-adige.it
altoadige.it
an.it
ancona.it
andria-barletta-trani.it
andria-trani-barletta.it
andriabarlettatrani.it
andriatranibarletta.it
ao.it
aosta.it
aoste.it
ap.it
aq.it
aquila.it
ar.it
arezzo.it
ascoli-piceno.it
ascolipiceno.it
asti.it
at.it
av.it
avellino.it
ba.it
balsan-sudtirol.it
balsan-sÃ¼dtirol.it
balsan-suedtirol.it
balsan.it
bari.it
barletta-trani-andria.it
barlettatraniandria.it
belluno.it
benevento.it
bergamo.it
bg.it
bi.it
biella.it
bl.it
bn.it
bo.it
bologna.it
bolzano-altoadige.it
bolzano.it
bozen-sudtirol.it
bozen-sÃ¼dtirol.it
bozen-suedtirol.it
bozen.it
br.it
brescia.it
brindisi.it
bs.it
bt.it
bulsan-sudtirol.it
bulsan-sÃ¼dtirol.it
bulsan-suedtirol.it
bulsan.it
bz.it
ca.it
cagliari.it
caltanissetta.it
campidano-medio.it
campidanomedio.it
campobasso.it
carbonia-iglesias.it
carboniaiglesias.it
carrara-massa.it
carraramassa.it
caserta.it
catania.it
catanzaro.it
cb.it
ce.it
cesena-forli.it
cesena-forlÃ¬.it
cesenaforli.it
cesenaforlÃ¬.it
ch.it
chieti.it
ci.it
cl.it
cn.it
co.it
como.it
cosenza.it
cr.it
cremona.it
crotone.it
cs.it
ct.it
cuneo.it
cz.it
dell-ogliastra.it
dellogliastra.it
en.it
enna.it
fc.it
fe.it
fermo.it
ferrara.it
fg.it
fi.it
firenze.it
florence.it
fm.it
foggia.it
forli-cesena.it
forlÃ¬-cesena.it
forlicesena.it
forlÃ¬cesena.it
fr.it
frosinone.it
ge.it
genoa.it
genova.it
go.it
gorizia.it
gr.it
grosseto.it
iglesias-carbonia.it
iglesiascarbonia.it
im.it
imperia.it
is.it
isernia.it
kr.it
la-spezia.it
laquila.it
laspezia.it
latina.it
lc.it
le.it
lecce.it
lecco.it
li.it
livorno.it
lo.it
lodi.it
lt.it
lu.it
lucca.it
macerata.it
mantova.it
massa-carrara.it
massacarrara.it
matera.it
mb.it
mc.it
me.it
medio-campidano.it
mediocampidano.it
messina.it
mi.it
milan.it
milano.it
mn.it
mo.it
modena.it
monza-brianza.it
monza-e-della-brianza.it
monza.it
monzabrianza.it
monzaebrianza.it
monzaedellabrianza.it
ms.it
mt.it
na.it
naples.it
napoli.it
no.it
novara.it
nu.it
nuoro.it
og.it
ogliastra.it
olbia-tempio.it
olbiatempio.it
or.it
oristano.it
ot.it
pa.it
padova.it
padua.it
palermo.it
parma.it
pavia.it
pc.it
pd.it
pe.it
perugia.it
pesaro-urbino.it
pesarourbino.it
pescara.it
pg.it
pi.it
piacenza.it
pisa.it
pistoia.it
pn.it
po.it
pordenone.it
potenza.it
pr.it
prato.it
pt.it
pu.it
pv.it
pz.it
ra.it
ragusa.it
ravenna.it
rc.it
re.it
reggio-calabria.it
reggio-emilia.it
reggiocalabria.it
reggioemilia.it
rg.it
ri.it
rieti.it
rimini.it
rm.it
rn.it
ro.it
roma.it
rome.it
rovigo.it
sa.it
salerno.it
sassari.it
savona.it
si.it
siena.it
siracusa.it
so.it
sondrio.it
sp.it
sr.it
ss.it
suedtirol.it
sÃ¼dtirol.it
sv.it
ta.it
taranto.it
te.it
tempio-olbia.it
tempioolbia.it
teramo.it
terni.it
tn.it
to.it
torino.it
tp.it
tr.it
trani-andria-barletta.it
trani-barletta-andria.it
traniandriabarletta.it
tranibarlettaandria.it
trapani.it
trento.it
treviso.it
trieste.it
ts.it
turin.it
tv.it
ud.it
udine.it
urbino-pesaro.it
urbinopesaro.it
va.it
varese.it
vb.it
vc.it
ve.it
venezia.it
venice.it
verbania.it
vercelli.it
verona.it
vi.it
vibo-valentia.it
vibovalentia.it
vicenza.it
viterbo.it
vr.it
vs.it
vt.it
vv.it

// je : http://www.channelisles.net/register-domains/
// Confirmed by registry <nigel@channelisles.net> 2013-11-28
je
co.je
net.je
org.je

// jm : http://www.com.jm/register.html
*.jm

// jo : http://www.dns.jo/Registration_policy.aspx
jo
com.jo
org.jo
net.jo
edu.jo
sch.jo
gov.jo
mil.jo
name.jo

// jobs : https://en.wikipedia.org/wiki/.jobs
jobs

// jp : https://en.wikipedia.org/wiki/.jp
// http://jprs.co.jp/en/jpdomain.html
// Submitted by registry <info@jprs.jp>
jp
// jp organizational type names
ac.jp
ad.jp
co.jp
ed.jp
go.jp
gr.jp
lg.jp
ne.jp
or.jp
// jp prefecture type names
aichi.jp
akita.jp
aomori.jp
chiba.jp
ehime.jp
fukui.jp
fukuoka.jp
fukushima.jp
gifu.jp
gunma.jp
hiroshima.jp
hokkaido.jp
hyogo.jp
ibaraki.jp
ishikawa.jp
iwate.jp
kagawa.jp
kagoshima.jp
kanagawa.jp
kochi.jp
kumamoto.jp
kyoto.jp
mie.jp
miyagi.jp
miyazaki.jp
nagano.jp
nagasaki.jp
nara.jp
niigata.jp
oita.jp
okayama.jp
okinawa.jp
osaka.jp
saga.jp
saitama.jp
shiga.jp
shimane.jp
shizuoka.jp
tochigi.jp
tokushima.jp
tokyo.jp
tottori.jp
toyama.jp
wakayama.jp
yamagata.jp
yamaguchi.jp
yamanashi.jp
æ ƒæœ¨.jp
æ„›çŸ¥.jp
æ„›åª›.jp
å…µåº«.jp
ç†Šæœ¬.jp
èŒ¨åŸŽ.jp
åŒ—æµ·é�“.jp
å�ƒè‘‰.jp
å’Œæ­Œå±±.jp
é•·å´Ž.jp
é•·é‡Ž.jp
æ–°æ½Ÿ.jp
é�’æ£®.jp
é�™å²¡.jp
æ�±äº¬.jp
çŸ³å·�.jp
åŸ¼çŽ‰.jp
ä¸‰é‡�.jp
äº¬éƒ½.jp
ä½�è³€.jp
å¤§åˆ†.jp
å¤§é˜ª.jp
å¥ˆè‰¯.jp
å®®åŸŽ.jp
å®®å´Ž.jp
å¯Œå±±.jp
å±±å�£.jp
å±±å½¢.jp
å±±æ¢¨.jp
å²©æ‰‹.jp
å²�é˜œ.jp
å²¡å±±.jp
å³¶æ ¹.jp
åºƒå³¶.jp
å¾³å³¶.jp
æ²–ç¸„.jp
æ»‹è³€.jp
ç¥žå¥ˆå·�.jp
ç¦�äº•.jp
ç¦�å²¡.jp
ç¦�å³¶.jp
ç§‹ç”°.jp
ç¾¤é¦¬.jp
é¦™å·�.jp
é«˜çŸ¥.jp
é³¥å�–.jp
é¹¿å…�å³¶.jp
// jp geographic type names
// http://jprs.jp/doc/rule/saisoku-1.html
*.kawasaki.jp
*.kitakyushu.jp
*.kobe.jp
*.nagoya.jp
*.sapporo.jp
*.sendai.jp
*.yokohama.jp
!city.kawasaki.jp
!city.kitakyushu.jp
!city.kobe.jp
!city.nagoya.jp
!city.sapporo.jp
!city.sendai.jp
!city.yokohama.jp
// 4th level registration
aisai.aichi.jp
ama.aichi.jp
anjo.aichi.jp
asuke.aichi.jp
chiryu.aichi.jp
chita.aichi.jp
fuso.aichi.jp
gamagori.aichi.jp
handa.aichi.jp
hazu.aichi.jp
hekinan.aichi.jp
higashiura.aichi.jp
ichinomiya.aichi.jp
inazawa.aichi.jp
inuyama.aichi.jp
isshiki.aichi.jp
iwakura.aichi.jp
kanie.aichi.jp
kariya.aichi.jp
kasugai.aichi.jp
kira.aichi.jp
kiyosu.aichi.jp
komaki.aichi.jp
konan.aichi.jp
kota.aichi.jp
mihama.aichi.jp
miyoshi.aichi.jp
nishio.aichi.jp
nisshin.aichi.jp
obu.aichi.jp
oguchi.aichi.jp
oharu.aichi.jp
okazaki.aichi.jp
owariasahi.aichi.jp
seto.aichi.jp
shikatsu.aichi.jp
shinshiro.aichi.jp
shitara.aichi.jp
tahara.aichi.jp
takahama.aichi.jp
tobishima.aichi.jp
toei.aichi.jp
togo.aichi.jp
tokai.aichi.jp
tokoname.aichi.jp
toyoake.aichi.jp
toyohashi.aichi.jp
toyokawa.aichi.jp
toyone.aichi.jp
toyota.aichi.jp
tsushima.aichi.jp
yatomi.aichi.jp
akita.akita.jp
daisen.akita.jp
fujisato.akita.jp
gojome.akita.jp
hachirogata.akita.jp
happou.akita.jp
higashinaruse.akita.jp
honjo.akita.jp
honjyo.akita.jp
ikawa.akita.jp
kamikoani.akita.jp
kamioka.akita.jp
katagami.akita.jp
kazuno.akita.jp
kitaakita.akita.jp
kosaka.akita.jp
kyowa.akita.jp
misato.akita.jp
mitane.akita.jp
moriyoshi.akita.jp
nikaho.akita.jp
noshiro.akita.jp
odate.akita.jp
oga.akita.jp
ogata.akita.jp
semboku.akita.jp
yokote.akita.jp
yurihonjo.akita.jp
aomori.aomori.jp
gonohe.aomori.jp
hachinohe.aomori.jp
hashikami.aomori.jp
hiranai.aomori.jp
hirosaki.aomori.jp
itayanagi.aomori.jp
kuroishi.aomori.jp
misawa.aomori.jp
mutsu.aomori.jp
nakadomari.aomori.jp
noheji.aomori.jp
oirase.aomori.jp
owani.aomori.jp
rokunohe.aomori.jp
sannohe.aomori.jp
shichinohe.aomori.jp
shingo.aomori.jp
takko.aomori.jp
towada.aomori.jp
tsugaru.aomori.jp
tsuruta.aomori.jp
abiko.chiba.jp
asahi.chiba.jp
chonan.chiba.jp
chosei.chiba.jp
choshi.chiba.jp
chuo.chiba.jp
funabashi.chiba.jp
futtsu.chiba.jp
hanamigawa.chiba.jp
ichihara.chiba.jp
ichikawa.chiba.jp
ichinomiya.chiba.jp
inzai.chiba.jp
isumi.chiba.jp
kamagaya.chiba.jp
kamogawa.chiba.jp
kashiwa.chiba.jp
katori.chiba.jp
katsuura.chiba.jp
kimitsu.chiba.jp
kisarazu.chiba.jp
kozaki.chiba.jp
kujukuri.chiba.jp
kyonan.chiba.jp
matsudo.chiba.jp
midori.chiba.jp
mihama.chiba.jp
minamiboso.chiba.jp
mobara.chiba.jp
mutsuzawa.chiba.jp
nagara.chiba.jp
nagareyama.chiba.jp
narashino.chiba.jp
narita.chiba.jp
noda.chiba.jp
oamishirasato.chiba.jp
omigawa.chiba.jp
onjuku.chiba.jp
otaki.chiba.jp
sakae.chiba.jp
sakura.chiba.jp
shimofusa.chiba.jp
shirako.chiba.jp
shiroi.chiba.jp
shisui.chiba.jp
sodegaura.chiba.jp
sosa.chiba.jp
tako.chiba.jp
tateyama.chiba.jp
togane.chiba.jp
tohnosho.chiba.jp
tomisato.chiba.jp
urayasu.chiba.jp
yachimata.chiba.jp
yachiyo.chiba.jp
yokaichiba.chiba.jp
yokoshibahikari.chiba.jp
yotsukaido.chiba.jp
ainan.ehime.jp
honai.ehime.jp
ikata.ehime.jp
imabari.ehime.jp
iyo.ehime.jp
kamijima.ehime.jp
kihoku.ehime.jp
kumakogen.ehime.jp
masaki.ehime.jp
matsuno.ehime.jp
matsuyama.ehime.jp
namikata.ehime.jp
niihama.ehime.jp
ozu.ehime.jp
saijo.ehime.jp
seiyo.ehime.jp
shikokuchuo.ehime.jp
tobe.ehime.jp
toon.ehime.jp
uchiko.ehime.jp
uwajima.ehime.jp
yawatahama.ehime.jp
echizen.fukui.jp
eiheiji.fukui.jp
fukui.fukui.jp
ikeda.fukui.jp
katsuyama.fukui.jp
mihama.fukui.jp
minamiechizen.fukui.jp
obama.fukui.jp
ohi.fukui.jp
ono.fukui.jp
sabae.fukui.jp
sakai.fukui.jp
takahama.fukui.jp
tsuruga.fukui.jp
wakasa.fukui.jp
ashiya.fukuoka.jp
buzen.fukuoka.jp
chikugo.fukuoka.jp
chikuho.fukuoka.jp
chikujo.fukuoka.jp
chikushino.fukuoka.jp
chikuzen.fukuoka.jp
chuo.fukuoka.jp
dazaifu.fukuoka.jp
fukuchi.fukuoka.jp
hakata.fukuoka.jp
higashi.fukuoka.jp
hirokawa.fukuoka.jp
hisayama.fukuoka.jp
iizuka.fukuoka.jp
inatsuki.fukuoka.jp
kaho.fukuoka.jp
kasuga.fukuoka.jp
kasuya.fukuoka.jp
kawara.fukuoka.jp
keisen.fukuoka.jp
koga.fukuoka.jp
kurate.fukuoka.jp
kurogi.fukuoka.jp
kurume.fukuoka.jp
minami.fukuoka.jp
miyako.fukuoka.jp
miyama.fukuoka.jp
miyawaka.fukuoka.jp
mizumaki.fukuoka.jp
munakata.fukuoka.jp
nakagawa.fukuoka.jp
nakama.fukuoka.jp
nishi.fukuoka.jp
nogata.fukuoka.jp
ogori.fukuoka.jp
okagaki.fukuoka.jp
okawa.fukuoka.jp
oki.fukuoka.jp
omuta.fukuoka.jp
onga.fukuoka.jp
onojo.fukuoka.jp
oto.fukuoka.jp
saigawa.fukuoka.jp
sasaguri.fukuoka.jp
shingu.fukuoka.jp
shinyoshitomi.fukuoka.jp
shonai.fukuoka.jp
soeda.fukuoka.jp
sue.fukuoka.jp
tachiarai.fukuoka.jp
tagawa.fukuoka.jp
takata.fukuoka.jp
toho.fukuoka.jp
toyotsu.fukuoka.jp
tsuiki.fukuoka.jp
ukiha.fukuoka.jp
umi.fukuoka.jp
usui.fukuoka.jp
yamada.fukuoka.jp
yame.fukuoka.jp
yanagawa.fukuoka.jp
yukuhashi.fukuoka.jp
aizubange.fukushima.jp
aizumisato.fukushima.jp
aizuwakamatsu.fukushima.jp
asakawa.fukushima.jp
bandai.fukushima.jp
date.fukushima.jp
fukushima.fukushima.jp
furudono.fukushima.jp
futaba.fukushima.jp
hanawa.fukushima.jp
higashi.fukushima.jp
hirata.fukushima.jp
hirono.fukushima.jp
iitate.fukushima.jp
inawashiro.fukushima.jp
ishikawa.fukushima.jp
iwaki.fukushima.jp
izumizaki.fukushima.jp
kagamiishi.fukushima.jp
kaneyama.fukushima.jp
kawamata.fukushima.jp
kitakata.fukushima.jp
kitashiobara.fukushima.jp
koori.fukushima.jp
koriyama.fukushima.jp
kunimi.fukushima.jp
miharu.fukushima.jp
mishima.fukushima.jp
namie.fukushima.jp
nango.fukushima.jp
nishiaizu.fukushima.jp
nishigo.fukushima.jp
okuma.fukushima.jp
omotego.fukushima.jp
ono.fukushima.jp
otama.fukushima.jp
samegawa.fukushima.jp
shimogo.fukushima.jp
shirakawa.fukushima.jp
showa.fukushima.jp
soma.fukushima.jp
sukagawa.fukushima.jp
taishin.fukushima.jp
tamakawa.fukushima.jp
tanagura.fukushima.jp
tenei.fukushima.jp
yabuki.fukushima.jp
yamato.fukushima.jp
yamatsuri.fukushima.jp
yanaizu.fukushima.jp
yugawa.fukushima.jp
anpachi.gifu.jp
ena.gifu.jp
gifu.gifu.jp
ginan.gifu.jp
godo.gifu.jp
gujo.gifu.jp
hashima.gifu.jp
hichiso.gifu.jp
hida.gifu.jp
higashishirakawa.gifu.jp
ibigawa.gifu.jp
ikeda.gifu.jp
kakamigahara.gifu.jp
kani.gifu.jp
kasahara.gifu.jp
kasamatsu.gifu.jp
kawaue.gifu.jp
kitagata.gifu.jp
mino.gifu.jp
minokamo.gifu.jp
mitake.gifu.jp
mizunami.gifu.jp
motosu.gifu.jp
nakatsugawa.gifu.jp
ogaki.gifu.jp
sakahogi.gifu.jp
seki.gifu.jp
sekigahara.gifu.jp
shirakawa.gifu.jp
tajimi.gifu.jp
takayama.gifu.jp
tarui.gifu.jp
toki.gifu.jp
tomika.gifu.jp
wanouchi.gifu.jp
yamagata.gifu.jp
yaotsu.gifu.jp
yoro.gifu.jp
annaka.gunma.jp
chiyoda.gunma.jp
fujioka.gunma.jp
higashiagatsuma.gunma.jp
isesaki.gunma.jp
itakura.gunma.jp
kanna.gunma.jp
kanra.gunma.jp
katashina.gunma.jp
kawaba.gunma.jp
kiryu.gunma.jp
kusatsu.gunma.jp
maebashi.gunma.jp
meiwa.gunma.jp
midori.gunma.jp
minakami.gunma.jp
naganohara.gunma.jp
nakanojo.gunma.jp
nanmoku.gunma.jp
numata.gunma.jp
oizumi.gunma.jp
ora.gunma.jp
ota.gunma.jp
shibukawa.gunma.jp
shimonita.gunma.jp
shinto.gunma.jp
showa.gunma.jp
takasaki.gunma.jp
takayama.gunma.jp
tamamura.gunma.jp
tatebayashi.gunma.jp
tomioka.gunma.jp
tsukiyono.gunma.jp
tsumagoi.gunma.jp
ueno.gunma.jp
yoshioka.gunma.jp
asaminami.hiroshima.jp
daiwa.hiroshima.jp
etajima.hiroshima.jp
fuchu.hiroshima.jp
fukuyama.hiroshima.jp
hatsukaichi.hiroshima.jp
higashihiroshima.hiroshima.jp
hongo.hiroshima.jp
jinsekikogen.hiroshima.jp
kaita.hiroshima.jp
kui.hiroshima.jp
kumano.hiroshima.jp
kure.hiroshima.jp
mihara.hiroshima.jp
miyoshi.hiroshima.jp
naka.hiroshima.jp
onomichi.hiroshima.jp
osakikamijima.hiroshima.jp
otake.hiroshima.jp
saka.hiroshima.jp
sera.hiroshima.jp
seranishi.hiroshima.jp
shinichi.hiroshima.jp
shobara.hiroshima.jp
takehara.hiroshima.jp
abashiri.hokkaido.jp
abira.hokkaido.jp
aibetsu.hokkaido.jp
akabira.hokkaido.jp
akkeshi.hokkaido.jp
asahikawa.hokkaido.jp
ashibetsu.hokkaido.jp
ashoro.hokkaido.jp
assabu.hokkaido.jp
atsuma.hokkaido.jp
bibai.hokkaido.jp
biei.hokkaido.jp
bifuka.hokkaido.jp
bihoro.hokkaido.jp
biratori.hokkaido.jp
chippubetsu.hokkaido.jp
chitose.hokkaido.jp
date.hokkaido.jp
ebetsu.hokkaido.jp
embetsu.hokkaido.jp
eniwa.hokkaido.jp
erimo.hokkaido.jp
esan.hokkaido.jp
esashi.hokkaido.jp
fukagawa.hokkaido.jp
fukushima.hokkaido.jp
furano.hokkaido.jp
furubira.hokkaido.jp
haboro.hokkaido.jp
hakodate.hokkaido.jp
hamatonbetsu.hokkaido.jp
hidaka.hokkaido.jp
higashikagura.hokkaido.jp
higashikawa.hokkaido.jp
hiroo.hokkaido.jp
hokuryu.hokkaido.jp
hokuto.hokkaido.jp
honbetsu.hokkaido.jp
horokanai.hokkaido.jp
horonobe.hokkaido.jp
ikeda.hokkaido.jp
imakane.hokkaido.jp
ishikari.hokkaido.jp
iwamizawa.hokkaido.jp
iwanai.hokkaido.jp
kamifurano.hokkaido.jp
kamikawa.hokkaido.jp
kamishihoro.hokkaido.jp
kamisunagawa.hokkaido.jp
kamoenai.hokkaido.jp
kayabe.hokkaido.jp
kembuchi.hokkaido.jp
kikonai.hokkaido.jp
kimobetsu.hokkaido.jp
kitahiroshima.hokkaido.jp
kitami.hokkaido.jp
kiyosato.hokkaido.jp
koshimizu.hokkaido.jp
kunneppu.hokkaido.jp
kuriyama.hokkaido.jp
kuromatsunai.hokkaido.jp
kushiro.hokkaido.jp
kutchan.hokkaido.jp
kyowa.hokkaido.jp
mashike.hokkaido.jp
matsumae.hokkaido.jp
mikasa.hokkaido.jp
minamifurano.hokkaido.jp
mombetsu.hokkaido.jp
moseushi.hokkaido.jp
mukawa.hokkaido.jp
muroran.hokkaido.jp
naie.hokkaido.jp
nakagawa.hokkaido.jp
nakasatsunai.hokkaido.jp
nakatombetsu.hokkaido.jp
nanae.hokkaido.jp
nanporo.hokkaido.jp
nayoro.hokkaido.jp
nemuro.hokkaido.jp
niikappu.hokkaido.jp
niki.hokkaido.jp
nishiokoppe.hokkaido.jp
noboribetsu.hokkaido.jp
numata.hokkaido.jp
obihiro.hokkaido.jp
obira.hokkaido.jp
oketo.hokkaido.jp
okoppe.hokkaido.jp
otaru.hokkaido.jp
otobe.hokkaido.jp
otofuke.hokkaido.jp
otoineppu.hokkaido.jp
oumu.hokkaido.jp
ozora.hokkaido.jp
pippu.hokkaido.jp
rankoshi.hokkaido.jp
rebun.hokkaido.jp
rikubetsu.hokkaido.jp
rishiri.hokkaido.jp
rishirifuji.hokkaido.jp
saroma.hokkaido.jp
sarufutsu.hokkaido.jp
shakotan.hokkaido.jp
shari.hokkaido.jp
shibecha.hokkaido.jp
shibetsu.hokkaido.jp
shikabe.hokkaido.jp
shikaoi.hokkaido.jp
shimamaki.hokkaido.jp
shimizu.hokkaido.jp
shimokawa.hokkaido.jp
shinshinotsu.hokkaido.jp
shintoku.hokkaido.jp
shiranuka.hokkaido.jp
shiraoi.hokkaido.jp
shiriuchi.hokkaido.jp
sobetsu.hokkaido.jp
sunagawa.hokkaido.jp
taiki.hokkaido.jp
takasu.hokkaido.jp
takikawa.hokkaido.jp
takinoue.hokkaido.jp
teshikaga.hokkaido.jp
tobetsu.hokkaido.jp
tohma.hokkaido.jp
tomakomai.hokkaido.jp
tomari.hokkaido.jp
toya.hokkaido.jp
toyako.hokkaido.jp
toyotomi.hokkaido.jp
toyoura.hokkaido.jp
tsubetsu.hokkaido.jp
tsukigata.hokkaido.jp
urakawa.hokkaido.jp
urausu.hokkaido.jp
uryu.hokkaido.jp
utashinai.hokkaido.jp
wakkanai.hokkaido.jp
wassamu.hokkaido.jp
yakumo.hokkaido.jp
yoichi.hokkaido.jp
aioi.hyogo.jp
akashi.hyogo.jp
ako.hyogo.jp
amagasaki.hyogo.jp
aogaki.hyogo.jp
asago.hyogo.jp
ashiya.hyogo.jp
awaji.hyogo.jp
fukusaki.hyogo.jp
goshiki.hyogo.jp
harima.hyogo.jp
himeji.hyogo.jp
ichikawa.hyogo.jp
inagawa.hyogo.jp
itami.hyogo.jp
kakogawa.hyogo.jp
kamigori.hyogo.jp
kamikawa.hyogo.jp
kasai.hyogo.jp
kasuga.hyogo.jp
kawanishi.hyogo.jp
miki.hyogo.jp
minamiawaji.hyogo.jp
nishinomiya.hyogo.jp
nishiwaki.hyogo.jp
ono.hyogo.jp
sanda.hyogo.jp
sannan.hyogo.jp
sasayama.hyogo.jp
sayo.hyogo.jp
shingu.hyogo.jp
shinonsen.hyogo.jp
shiso.hyogo.jp
sumoto.hyogo.jp
taishi.hyogo.jp
taka.hyogo.jp
takarazuka.hyogo.jp
takasago.hyogo.jp
takino.hyogo.jp
tamba.hyogo.jp
tatsuno.hyogo.jp
toyooka.hyogo.jp
yabu.hyogo.jp
yashiro.hyogo.jp
yoka.hyogo.jp
yokawa.hyogo.jp
ami.ibaraki.jp
asahi.ibaraki.jp
bando.ibaraki.jp
chikusei.ibaraki.jp
daigo.ibaraki.jp
fujishiro.ibaraki.jp
hitachi.ibaraki.jp
hitachinaka.ibaraki.jp
hitachiomiya.ibaraki.jp
hitachiota.ibaraki.jp
ibaraki.ibaraki.jp
ina.ibaraki.jp
inashiki.ibaraki.jp
itako.ibaraki.jp
iwama.ibaraki.jp
joso.ibaraki.jp
kamisu.ibaraki.jp
kasama.ibaraki.jp
kashima.ibaraki.jp
kasumigaura.ibaraki.jp
koga.ibaraki.jp
miho.ibaraki.jp
mito.ibaraki.jp
moriya.ibaraki.jp
naka.ibaraki.jp
namegata.ibaraki.jp
oarai.ibaraki.jp
ogawa.ibaraki.jp
omitama.ibaraki.jp
ryugasaki.ibaraki.jp
sakai.ibaraki.jp
sakuragawa.ibaraki.jp
shimodate.ibaraki.jp
shimotsuma.ibaraki.jp
shirosato.ibaraki.jp
sowa.ibaraki.jp
suifu.ibaraki.jp
takahagi.ibaraki.jp
tamatsukuri.ibaraki.jp
tokai.ibaraki.jp
tomobe.ibaraki.jp
tone.ibaraki.jp
toride.ibaraki.jp
tsuchiura.ibaraki.jp
tsukuba.ibaraki.jp
uchihara.ibaraki.jp
ushiku.ibaraki.jp
yachiyo.ibaraki.jp
yamagata.ibaraki.jp
yawara.ibaraki.jp
yuki.ibaraki.jp
anamizu.ishikawa.jp
hakui.ishikawa.jp
hakusan.ishikawa.jp
kaga.ishikawa.jp
kahoku.ishikawa.jp
kanazawa.ishikawa.jp
kawakita.ishikawa.jp
komatsu.ishikawa.jp
nakanoto.ishikawa.jp
nanao.ishikawa.jp
nomi.ishikawa.jp
nonoichi.ishikawa.jp
noto.ishikawa.jp
shika.ishikawa.jp
suzu.ishikawa.jp
tsubata.ishikawa.jp
tsurugi.ishikawa.jp
uchinada.ishikawa.jp
wajima.ishikawa.jp
fudai.iwate.jp
fujisawa.iwate.jp
hanamaki.iwate.jp
hiraizumi.iwate.jp
hirono.iwate.jp
ichinohe.iwate.jp
ichinoseki.iwate.jp
iwaizumi.iwate.jp
iwate.iwate.jp
joboji.iwate.jp
kamaishi.iwate.jp
kanegasaki.iwate.jp
karumai.iwate.jp
kawai.iwate.jp
kitakami.iwate.jp
kuji.iwate.jp
kunohe.iwate.jp
kuzumaki.iwate.jp
miyako.iwate.jp
mizusawa.iwate.jp
morioka.iwate.jp
ninohe.iwate.jp
noda.iwate.jp
ofunato.iwate.jp
oshu.iwate.jp
otsuchi.iwate.jp
rikuzentakata.iwate.jp
shiwa.iwate.jp
shizukuishi.iwate.jp
sumita.iwate.jp
tanohata.iwate.jp
tono.iwate.jp
yahaba.iwate.jp
yamada.iwate.jp
ayagawa.kagawa.jp
higashikagawa.kagawa.jp
kanonji.kagawa.jp
kotohira.kagawa.jp
manno.kagawa.jp
marugame.kagawa.jp
mitoyo.kagawa.jp
naoshima.kagawa.jp
sanuki.kagawa.jp
tadotsu.kagawa.jp
takamatsu.kagawa.jp
tonosho.kagawa.jp
uchinomi.kagawa.jp
utazu.kagawa.jp
zentsuji.kagawa.jp
akune.kagoshima.jp
amami.kagoshima.jp
hioki.kagoshima.jp
isa.kagoshima.jp
isen.kagoshima.jp
izumi.kagoshima.jp
kagoshima.kagoshima.jp
kanoya.kagoshima.jp
kawanabe.kagoshima.jp
kinko.kagoshima.jp
kouyama.kagoshima.jp
makurazaki.kagoshima.jp
matsumoto.kagoshima.jp
minamitane.kagoshima.jp
nakatane.kagoshima.jp
nishinoomote.kagoshima.jp
satsumasendai.kagoshima.jp
soo.kagoshima.jp
tarumizu.kagoshima.jp
yusui.kagoshima.jp
aikawa.kanagawa.jp
atsugi.kanagawa.jp
ayase.kanagawa.jp
chigasaki.kanagawa.jp
ebina.kanagawa.jp
fujisawa.kanagawa.jp
hadano.kanagawa.jp
hakone.kanagawa.jp
hiratsuka.kanagawa.jp
isehara.kanagawa.jp
kaisei.kanagawa.jp
kamakura.kanagawa.jp
kiyokawa.kanagawa.jp
matsuda.kanagawa.jp
minamiashigara.kanagawa.jp
miura.kanagawa.jp
nakai.kanagawa.jp
ninomiya.kanagawa.jp
odawara.kanagawa.jp
oi.kanagawa.jp
oiso.kanagawa.jp
sagamihara.kanagawa.jp
samukawa.kanagawa.jp
tsukui.kanagawa.jp
yamakita.kanagawa.jp
yamato.kanagawa.jp
yokosuka.kanagawa.jp
yugawara.kanagawa.jp
zama.kanagawa.jp
zushi.kanagawa.jp
aki.kochi.jp
geisei.kochi.jp
hidaka.kochi.jp
higashitsuno.kochi.jp
ino.kochi.jp
kagami.kochi.jp
kami.kochi.jp
kitagawa.kochi.jp
kochi.kochi.jp
mihara.kochi.jp
motoyama.kochi.jp
muroto.kochi.jp
nahari.kochi.jp
nakamura.kochi.jp
nankoku.kochi.jp
nishitosa.kochi.jp
niyodogawa.kochi.jp
ochi.kochi.jp
okawa.kochi.jp
otoyo.kochi.jp
otsuki.kochi.jp
sakawa.kochi.jp
sukumo.kochi.jp
susaki.kochi.jp
tosa.kochi.jp
tosashimizu.kochi.jp
toyo.kochi.jp
tsuno.kochi.jp
umaji.kochi.jp
yasuda.kochi.jp
yusuhara.kochi.jp
amakusa.kumamoto.jp
arao.kumamoto.jp
aso.kumamoto.jp
choyo.kumamoto.jp
gyokuto.kumamoto.jp
kamiamakusa.kumamoto.jp
kikuchi.kumamoto.jp
kumamoto.kumamoto.jp
mashiki.kumamoto.jp
mifune.kumamoto.jp
minamata.kumamoto.jp
minamioguni.kumamoto.jp
nagasu.kumamoto.jp
nishihara.kumamoto.jp
oguni.kumamoto.jp
ozu.kumamoto.jp
sumoto.kumamoto.jp
takamori.kumamoto.jp
uki.kumamoto.jp
uto.kumamoto.jp
yamaga.kumamoto.jp
yamato.kumamoto.jp
yatsushiro.kumamoto.jp
ayabe.kyoto.jp
fukuchiyama.kyoto.jp
higashiyama.kyoto.jp
ide.kyoto.jp
ine.kyoto.jp
joyo.kyoto.jp
kameoka.kyoto.jp
kamo.kyoto.jp
kita.kyoto.jp
kizu.kyoto.jp
kumiyama.kyoto.jp
kyotamba.kyoto.jp
kyotanabe.kyoto.jp
kyotango.kyoto.jp
maizuru.kyoto.jp
minami.kyoto.jp
minamiyamashiro.kyoto.jp
miyazu.kyoto.jp
muko.kyoto.jp
nagaokakyo.kyoto.jp
nakagyo.kyoto.jp
nantan.kyoto.jp
oyamazaki.kyoto.jp
sakyo.kyoto.jp
seika.kyoto.jp
tanabe.kyoto.jp
uji.kyoto.jp
ujitawara.kyoto.jp
wazuka.kyoto.jp
yamashina.kyoto.jp
yawata.kyoto.jp
asahi.mie.jp
inabe.mie.jp
ise.mie.jp
kameyama.mie.jp
kawagoe.mie.jp
kiho.mie.jp
kisosaki.mie.jp
kiwa.mie.jp
komono.mie.jp
kumano.mie.jp
kuwana.mie.jp
matsusaka.mie.jp
meiwa.mie.jp
mihama.mie.jp
minamiise.mie.jp
misugi.mie.jp
miyama.mie.jp
nabari.mie.jp
shima.mie.jp
suzuka.mie.jp
tado.mie.jp
taiki.mie.jp
taki.mie.jp
tamaki.mie.jp
toba.mie.jp
tsu.mie.jp
udono.mie.jp
ureshino.mie.jp
watarai.mie.jp
yokkaichi.mie.jp
furukawa.miyagi.jp
higashimatsushima.miyagi.jp
ishinomaki.miyagi.jp
iwanuma.miyagi.jp
kakuda.miyagi.jp
kami.miyagi.jp
kawasaki.miyagi.jp
marumori.miyagi.jp
matsushima.miyagi.jp
minamisanriku.miyagi.jp
misato.miyagi.jp
murata.miyagi.jp
natori.miyagi.jp
ogawara.miyagi.jp
ohira.miyagi.jp
onagawa.miyagi.jp
osaki.miyagi.jp
rifu.miyagi.jp
semine.miyagi.jp
shibata.miyagi.jp
shichikashuku.miyagi.jp
shikama.miyagi.jp
shiogama.miyagi.jp
shiroishi.miyagi.jp
tagajo.miyagi.jp
taiwa.miyagi.jp
tome.miyagi.jp
tomiya.miyagi.jp
wakuya.miyagi.jp
watari.miyagi.jp
yamamoto.miyagi.jp
zao.miyagi.jp
aya.miyazaki.jp
ebino.miyazaki.jp
gokase.miyazaki.jp
hyuga.miyazaki.jp
kadogawa.miyazaki.jp
kawaminami.miyazaki.jp
kijo.miyazaki.jp
kitagawa.miyazaki.jp
kitakata.miyazaki.jp
kitaura.miyazaki.jp
kobayashi.miyazaki.jp
kunitomi.miyazaki.jp
kushima.miyazaki.jp
mimata.miyazaki.jp
miyakonojo.miyazaki.jp
miyazaki.miyazaki.jp
morotsuka.miyazaki.jp
nichinan.miyazaki.jp
nishimera.miyazaki.jp
nobeoka.miyazaki.jp
saito.miyazaki.jp
shiiba.miyazaki.jp
shintomi.miyazaki.jp
takaharu.miyazaki.jp
takanabe.miyazaki.jp
takazaki.miyazaki.jp
tsuno.miyazaki.jp
achi.nagano.jp
agematsu.nagano.jp
anan.nagano.jp
aoki.nagano.jp
asahi.nagano.jp
azumino.nagano.jp
chikuhoku.nagano.jp
chikuma.nagano.jp
chino.nagano.jp
fujimi.nagano.jp
hakuba.nagano.jp
hara.nagano.jp
hiraya.nagano.jp
iida.nagano.jp
iijima.nagano.jp
iiyama.nagano.jp
iizuna.nagano.jp
ikeda.nagano.jp
ikusaka.nagano.jp
ina.nagano.jp
karuizawa.nagano.jp
kawakami.nagano.jp
kiso.nagano.jp
kisofukushima.nagano.jp
kitaaiki.nagano.jp
komagane.nagano.jp
komoro.nagano.jp
matsukawa.nagano.jp
matsumoto.nagano.jp
miasa.nagano.jp
minamiaiki.nagano.jp
minamimaki.nagano.jp
minamiminowa.nagano.jp
minowa.nagano.jp
miyada.nagano.jp
miyota.nagano.jp
mochizuki.nagano.jp
nagano.nagano.jp
nagawa.nagano.jp
nagiso.nagano.jp
nakagawa.nagano.jp
nakano.nagano.jp
nozawaonsen.nagano.jp
obuse.nagano.jp
ogawa.nagano.jp
okaya.nagano.jp
omachi.nagano.jp
omi.nagano.jp
ookuwa.nagano.jp
ooshika.nagano.jp
otaki.nagano.jp
otari.nagano.jp
sakae.nagano.jp
sakaki.nagano.jp
saku.nagano.jp
sakuho.nagano.jp
shimosuwa.nagano.jp
shinanomachi.nagano.jp
shiojiri.nagano.jp
suwa.nagano.jp
suzaka.nagano.jp
takagi.nagano.jp
takamori.nagano.jp
takayama.nagano.jp
tateshina.nagano.jp
tatsuno.nagano.jp
togakushi.nagano.jp
togura.nagano.jp
tomi.nagano.jp
ueda.nagano.jp
wada.nagano.jp
yamagata.nagano.jp
yamanouchi.nagano.jp
yasaka.nagano.jp
yasuoka.nagano.jp
chijiwa.nagasaki.jp
futsu.nagasaki.jp
goto.nagasaki.jp
hasami.nagasaki.jp
hirado.nagasaki.jp
iki.nagasaki.jp
isahaya.nagasaki.jp
kawatana.nagasaki.jp
kuchinotsu.nagasaki.jp
matsuura.nagasaki.jp
nagasaki.nagasaki.jp
obama.nagasaki.jp
omura.nagasaki.jp
oseto.nagasaki.jp
saikai.nagasaki.jp
sasebo.nagasaki.jp
seihi.nagasaki.jp
shimabara.nagasaki.jp
shinkamigoto.nagasaki.jp
togitsu.nagasaki.jp
tsushima.nagasaki.jp
unzen.nagasaki.jp
ando.nara.jp
gose.nara.jp
heguri.nara.jp
higashiyoshino.nara.jp
ikaruga.nara.jp
ikoma.nara.jp
kamikitayama.nara.jp
kanmaki.nara.jp
kashiba.nara.jp
kashihara.nara.jp
katsuragi.nara.jp
kawai.nara.jp
kawakami.nara.jp
kawanishi.nara.jp
koryo.nara.jp
kurotaki.nara.jp
mitsue.nara.jp
miyake.nara.jp
nara.nara.jp
nosegawa.nara.jp
oji.nara.jp
ouda.nara.jp
oyodo.nara.jp
sakurai.nara.jp
sango.nara.jp
shimoichi.nara.jp
shimokitayama.nara.jp
shinjo.nara.jp
soni.nara.jp
takatori.nara.jp
tawaramoto.nara.jp
tenkawa.nara.jp
tenri.nara.jp
uda.nara.jp
yamatokoriyama.nara.jp
yamatotakada.nara.jp
yamazoe.nara.jp
yoshino.nara.jp
aga.niigata.jp
agano.niigata.jp
gosen.niigata.jp
itoigawa.niigata.jp
izumozaki.niigata.jp
joetsu.niigata.jp
kamo.niigata.jp
kariwa.niigata.jp
kashiwazaki.niigata.jp
minamiuonuma.niigata.jp
mitsuke.niigata.jp
muika.niigata.jp
murakami.niigata.jp
myoko.niigata.jp
nagaoka.niigata.jp
niigata.niigata.jp
ojiya.niigata.jp
omi.niigata.jp
sado.niigata.jp
sanjo.niigata.jp
seiro.niigata.jp
seirou.niigata.jp
sekikawa.niigata.jp
shibata.niigata.jp
tagami.niigata.jp
tainai.niigata.jp
tochio.niigata.jp
tokamachi.niigata.jp
tsubame.niigata.jp
tsunan.niigata.jp
uonuma.niigata.jp
yahiko.niigata.jp
yoita.niigata.jp
yuzawa.niigata.jp
beppu.oita.jp
bungoono.oita.jp
bungotakada.oita.jp
hasama.oita.jp
hiji.oita.jp
himeshima.oita.jp
hita.oita.jp
kamitsue.oita.jp
kokonoe.oita.jp
kuju.oita.jp
kunisaki.oita.jp
kusu.oita.jp
oita.oita.jp
saiki.oita.jp
taketa.oita.jp
tsukumi.oita.jp
usa.oita.jp
usuki.oita.jp
yufu.oita.jp
akaiwa.okayama.jp
asakuchi.okayama.jp
bizen.okayama.jp
hayashima.okayama.jp
ibara.okayama.jp
kagamino.okayama.jp
kasaoka.okayama.jp
kibichuo.okayama.jp
kumenan.okayama.jp
kurashiki.okayama.jp
maniwa.okayama.jp
misaki.okayama.jp
nagi.okayama.jp
niimi.okayama.jp
nishiawakura.okayama.jp
okayama.okayama.jp
satosho.okayama.jp
setouchi.okayama.jp
shinjo.okayama.jp
shoo.okayama.jp
soja.okayama.jp
takahashi.okayama.jp
tamano.okayama.jp
tsuyama.okayama.jp
wake.okayama.jp
yakage.okayama.jp
aguni.okinawa.jp
ginowan.okinawa.jp
ginoza.okinawa.jp
gushikami.okinawa.jp
haebaru.okinawa.jp
higashi.okinawa.jp
hirara.okinawa.jp
iheya.okinawa.jp
ishigaki.okinawa.jp
ishikawa.okinawa.jp
itoman.okinawa.jp
izena.okinawa.jp
kadena.okinawa.jp
kin.okinawa.jp
kitadaito.okinawa.jp
kitanakagusuku.okinawa.jp
kumejima.okinawa.jp
kunigami.okinawa.jp
minamidaito.okinawa.jp
motobu.okinawa.jp
nago.okinawa.jp
naha.okinawa.jp
nakagusuku.okinawa.jp
nakijin.okinawa.jp
nanjo.okinawa.jp
nishihara.okinawa.jp
ogimi.okinawa.jp
okinawa.okinawa.jp
onna.okinawa.jp
shimoji.okinawa.jp
taketomi.okinawa.jp
tarama.okinawa.jp
tokashiki.okinawa.jp
tomigusuku.okinawa.jp
tonaki.okinawa.jp
urasoe.okinawa.jp
uruma.okinawa.jp
yaese.okinawa.jp
yomitan.okinawa.jp
yonabaru.okinawa.jp
yonaguni.okinawa.jp
zamami.okinawa.jp
abeno.osaka.jp
chihayaakasaka.osaka.jp
chuo.osaka.jp
daito.osaka.jp
fujiidera.osaka.jp
habikino.osaka.jp
hannan.osaka.jp
higashiosaka.osaka.jp
higashisumiyoshi.osaka.jp
higashiyodogawa.osaka.jp
hirakata.osaka.jp
ibaraki.osaka.jp
ikeda.osaka.jp
izumi.osaka.jp
izumiotsu.osaka.jp
izumisano.osaka.jp
kadoma.osaka.jp
kaizuka.osaka.jp
kanan.osaka.jp
kashiwara.osaka.jp
katano.osaka.jp
kawachinagano.osaka.jp
kishiwada.osaka.jp
kita.osaka.jp
kumatori.osaka.jp
matsubara.osaka.jp
minato.osaka.jp
minoh.osaka.jp
misaki.osaka.jp
moriguchi.osaka.jp
neyagawa.osaka.jp
nishi.osaka.jp
nose.osaka.jp
osakasayama.osaka.jp
sakai.osaka.jp
sayama.osaka.jp
sennan.osaka.jp
settsu.osaka.jp
shijonawate.osaka.jp
shimamoto.osaka.jp
suita.osaka.jp
tadaoka.osaka.jp
taishi.osaka.jp
tajiri.osaka.jp
takaishi.osaka.jp
takatsuki.osaka.jp
tondabayashi.osaka.jp
toyonaka.osaka.jp
toyono.osaka.jp
yao.osaka.jp
ariake.saga.jp
arita.saga.jp
fukudomi.saga.jp
genkai.saga.jp
hamatama.saga.jp
hizen.saga.jp
imari.saga.jp
kamimine.saga.jp
kanzaki.saga.jp
karatsu.saga.jp
kashima.saga.jp
kitagata.saga.jp
kitahata.saga.jp
kiyama.saga.jp
kouhoku.saga.jp
kyuragi.saga.jp
nishiarita.saga.jp
ogi.saga.jp
omachi.saga.jp
ouchi.saga.jp
saga.saga.jp
shiroishi.saga.jp
taku.saga.jp
tara.saga.jp
tosu.saga.jp
yoshinogari.saga.jp
arakawa.saitama.jp
asaka.saitama.jp
chichibu.saitama.jp
fujimi.saitama.jp
fujimino.saitama.jp
fukaya.saitama.jp
hanno.saitama.jp
hanyu.saitama.jp
hasuda.saitama.jp
hatogaya.saitama.jp
hatoyama.saitama.jp
hidaka.saitama.jp
higashichichibu.saitama.jp
higashimatsuyama.saitama.jp
honjo.saitama.jp
ina.saitama.jp
iruma.saitama.jp
iwatsuki.saitama.jp
kamiizumi.saitama.jp
kamikawa.saitama.jp
kamisato.saitama.jp
kasukabe.saitama.jp
kawagoe.saitama.jp
kawaguchi.saitama.jp
kawajima.saitama.jp
kazo.saitama.jp
kitamoto.saitama.jp
koshigaya.saitama.jp
kounosu.saitama.jp
kuki.saitama.jp
kumagaya.saitama.jp
matsubushi.saitama.jp
minano.saitama.jp
misato.saitama.jp
miyashiro.saitama.jp
miyoshi.saitama.jp
moroyama.saitama.jp
nagatoro.saitama.jp
namegawa.saitama.jp
niiza.saitama.jp
ogano.saitama.jp
ogawa.saitama.jp
ogose.saitama.jp
okegawa.saitama.jp
omiya.saitama.jp
otaki.saitama.jp
ranzan.saitama.jp
ryokami.saitama.jp
saitama.saitama.jp
sakado.saitama.jp
satte.saitama.jp
sayama.saitama.jp
shiki.saitama.jp
shiraoka.saitama.jp
soka.saitama.jp
sugito.saitama.jp
toda.saitama.jp
tokigawa.saitama.jp
tokorozawa.saitama.jp
tsurugashima.saitama.jp
urawa.saitama.jp
warabi.saitama.jp
yashio.saitama.jp
yokoze.saitama.jp
yono.saitama.jp
yorii.saitama.jp
yoshida.saitama.jp
yoshikawa.saitama.jp
yoshimi.saitama.jp
aisho.shiga.jp
gamo.shiga.jp
higashiomi.shiga.jp
hikone.shiga.jp
koka.shiga.jp
konan.shiga.jp
kosei.shiga.jp
koto.shiga.jp
kusatsu.shiga.jp
maibara.shiga.jp
moriyama.shiga.jp
nagahama.shiga.jp
nishiazai.shiga.jp
notogawa.shiga.jp
omihachiman.shiga.jp
otsu.shiga.jp
ritto.shiga.jp
ryuoh.shiga.jp
takashima.shiga.jp
takatsuki.shiga.jp
torahime.shiga.jp
toyosato.shiga.jp
yasu.shiga.jp
akagi.shimane.jp
ama.shimane.jp
gotsu.shimane.jp
hamada.shimane.jp
higashiizumo.shimane.jp
hikawa.shimane.jp
hikimi.shimane.jp
izumo.shimane.jp
kakinoki.shimane.jp
masuda.shimane.jp
matsue.shimane.jp
misato.shimane.jp
nishinoshima.shimane.jp
ohda.shimane.jp
okinoshima.shimane.jp
okuizumo.shimane.jp
shimane.shimane.jp
tamayu.shimane.jp
tsuwano.shimane.jp
unnan.shimane.jp
yakumo.shimane.jp
yasugi.shimane.jp
yatsuka.shimane.jp
arai.shizuoka.jp
atami.shizuoka.jp
fuji.shizuoka.jp
fujieda.shizuoka.jp
fujikawa.shizuoka.jp
fujinomiya.shizuoka.jp
fukuroi.shizuoka.jp
gotemba.shizuoka.jp
haibara.shizuoka.jp
hamamatsu.shizuoka.jp
higashiizu.shizuoka.jp
ito.shizuoka.jp
iwata.shizuoka.jp
izu.shizuoka.jp
izunokuni.shizuoka.jp
kakegawa.shizuoka.jp
kannami.shizuoka.jp
kawanehon.shizuoka.jp
kawazu.shizuoka.jp
kikugawa.shizuoka.jp
kosai.shizuoka.jp
makinohara.shizuoka.jp
matsuzaki.shizuoka.jp
minamiizu.shizuoka.jp
mishima.shizuoka.jp
morimachi.shizuoka.jp
nishiizu.shizuoka.jp
numazu.shizuoka.jp
omaezaki.shizuoka.jp
shimada.shizuoka.jp
shimizu.shizuoka.jp
shimoda.shizuoka.jp
shizuoka.shizuoka.jp
susono.shizuoka.jp
yaizu.shizuoka.jp
yoshida.shizuoka.jp
ashikaga.tochigi.jp
bato.tochigi.jp
haga.tochigi.jp
ichikai.tochigi.jp
iwafune.tochigi.jp
kaminokawa.tochigi.jp
kanuma.tochigi.jp
karasuyama.tochigi.jp
kuroiso.tochigi.jp
mashiko.tochigi.jp
mibu.tochigi.jp
moka.tochigi.jp
motegi.tochigi.jp
nasu.tochigi.jp
nasushiobara.tochigi.jp
nikko.tochigi.jp
nishikata.tochigi.jp
nogi.tochigi.jp
ohira.tochigi.jp
ohtawara.tochigi.jp
oyama.tochigi.jp
sakura.tochigi.jp
sano.tochigi.jp
shimotsuke.tochigi.jp
shioya.tochigi.jp
takanezawa.tochigi.jp
tochigi.tochigi.jp
tsuga.tochigi.jp
ujiie.tochigi.jp
utsunomiya.tochigi.jp
yaita.tochigi.jp
aizumi.tokushima.jp
anan.tokushima.jp
ichiba.tokushima.jp
itano.tokushima.jp
kainan.tokushima.jp
komatsushima.tokushima.jp
matsushige.tokushima.jp
mima.tokushima.jp
minami.tokushima.jp
miyoshi.tokushima.jp
mugi.tokushima.jp
nakagawa.tokushima.jp
naruto.tokushima.jp
sanagochi.tokushima.jp
shishikui.tokushima.jp
tokushima.tokushima.jp
wajiki.tokushima.jp
adachi.tokyo.jp
akiruno.tokyo.jp
akishima.tokyo.jp
aogashima.tokyo.jp
arakawa.tokyo.jp
bunkyo.tokyo.jp
chiyoda.tokyo.jp
chofu.tokyo.jp
chuo.tokyo.jp
edogawa.tokyo.jp
fuchu.tokyo.jp
fussa.tokyo.jp
hachijo.tokyo.jp
hachioji.tokyo.jp
hamura.tokyo.jp
higashikurume.tokyo.jp
higashimurayama.tokyo.jp
higashiyamato.tokyo.jp
hino.tokyo.jp
hinode.tokyo.jp
hinohara.tokyo.jp
inagi.tokyo.jp
itabashi.tokyo.jp
katsushika.tokyo.jp
kita.tokyo.jp
kiyose.tokyo.jp
kodaira.tokyo.jp
koganei.tokyo.jp
kokubunji.tokyo.jp
komae.tokyo.jp
koto.tokyo.jp
kouzushima.tokyo.jp
kunitachi.tokyo.jp
machida.tokyo.jp
meguro.tokyo.jp
minato.tokyo.jp
mitaka.tokyo.jp
mizuho.tokyo.jp
musashimurayama.tokyo.jp
musashino.tokyo.jp
nakano.tokyo.jp
nerima.tokyo.jp
ogasawara.tokyo.jp
okutama.tokyo.jp
ome.tokyo.jp
oshima.tokyo.jp
ota.tokyo.jp
setagaya.tokyo.jp
shibuya.tokyo.jp
shinagawa.tokyo.jp
shinjuku.tokyo.jp
suginami.tokyo.jp
sumida.tokyo.jp
tachikawa.tokyo.jp
taito.tokyo.jp
tama.tokyo.jp
toshima.tokyo.jp
chizu.tottori.jp
hino.tottori.jp
kawahara.tottori.jp
koge.tottori.jp
kotoura.tottori.jp
misasa.tottori.jp
nanbu.tottori.jp
nichinan.tottori.jp
sakaiminato.tottori.jp
tottori.tottori.jp
wakasa.tottori.jp
yazu.tottori.jp
yonago.tottori.jp
asahi.toyama.jp
fuchu.toyama.jp
fukumitsu.toyama.jp
funahashi.toyama.jp
himi.toyama.jp
imizu.toyama.jp
inami.toyama.jp
johana.toyama.jp
kamiichi.toyama.jp
kurobe.toyama.jp
nakaniikawa.toyama.jp
namerikawa.toyama.jp
nanto.toyama.jp
nyuzen.toyama.jp
oyabe.toyama.jp
taira.toyama.jp
takaoka.toyama.jp
tateyama.toyama.jp
toga.toyama.jp
tonami.toyama.jp
toyama.toyama.jp
unazuki.toyama.jp
uozu.toyama.jp
yamada.toyama.jp
arida.wakayama.jp
aridagawa.wakayama.jp
gobo.wakayama.jp
hashimoto.wakayama.jp
hidaka.wakayama.jp
hirogawa.wakayama.jp
inami.wakayama.jp
iwade.wakayama.jp
kainan.wakayama.jp
kamitonda.wakayama.jp
katsuragi.wakayama.jp
kimino.wakayama.jp
kinokawa.wakayama.jp
kitayama.wakayama.jp
koya.wakayama.jp
koza.wakayama.jp
kozagawa.wakayama.jp
kudoyama.wakayama.jp
kushimoto.wakayama.jp
mihama.wakayama.jp
misato.wakayama.jp
nachikatsuura.wakayama.jp
shingu.wakayama.jp
shirahama.wakayama.jp
taiji.wakayama.jp
tanabe.wakayama.jp
wakayama.wakayama.jp
yuasa.wakayama.jp
yura.wakayama.jp
asahi.yamagata.jp
funagata.yamagata.jp
higashine.yamagata.jp
iide.yamagata.jp
kahoku.yamagata.jp
kaminoyama.yamagata.jp
kaneyama.yamagata.jp
kawanishi.yamagata.jp
mamurogawa.yamagata.jp
mikawa.yamagata.jp
murayama.yamagata.jp
nagai.yamagata.jp
nakayama.yamagata.jp
nanyo.yamagata.jp
nishikawa.yamagata.jp
obanazawa.yamagata.jp
oe.yamagata.jp
oguni.yamagata.jp
ohkura.yamagata.jp
oishida.yamagata.jp
sagae.yamagata.jp
sakata.yamagata.jp
sakegawa.yamagata.jp
shinjo.yamagata.jp
shirataka.yamagata.jp
shonai.yamagata.jp
takahata.yamagata.jp
tendo.yamagata.jp
tozawa.yamagata.jp
tsuruoka.yamagata.jp
yamagata.yamagata.jp
yamanobe.yamagata.jp
yonezawa.yamagata.jp
yuza.yamagata.jp
abu.yamaguchi.jp
hagi.yamaguchi.jp
hikari.yamaguchi.jp
hofu.yamaguchi.jp
iwakuni.yamaguchi.jp
kudamatsu.yamaguchi.jp
mitou.yamaguchi.jp
nagato.yamaguchi.jp
oshima.yamaguchi.jp
shimonoseki.yamaguchi.jp
shunan.yamaguchi.jp
tabuse.yamaguchi.jp
tokuyama.yamaguchi.jp
toyota.yamaguchi.jp
ube.yamaguchi.jp
yuu.yamaguchi.jp
chuo.yamanashi.jp
doshi.yamanashi.jp
fuefuki.yamanashi.jp
fujikawa.yamanashi.jp
fujikawaguchiko.yamanashi.jp
fujiyoshida.yamanashi.jp
hayakawa.yamanashi.jp
hokuto.yamanashi.jp
ichikawamisato.yamanashi.jp
kai.yamanashi.jp
kofu.yamanashi.jp
koshu.yamanashi.jp
kosuge.yamanashi.jp
minami-alps.yamanashi.jp
minobu.yamanashi.jp
nakamichi.yamanashi.jp
nanbu.yamanashi.jp
narusawa.yamanashi.jp
nirasaki.yamanashi.jp
nishikatsura.yamanashi.jp
oshino.yamanashi.jp
otsuki.yamanashi.jp
showa.yamanashi.jp
tabayama.yamanashi.jp
tsuru.yamanashi.jp
uenohara.yamanashi.jp
yamanakako.yamanashi.jp
yamanashi.yamanashi.jp

// ke : http://www.kenic.or.ke/index.php/en/ke-domains/ke-domains
ke
ac.ke
co.ke
go.ke
info.ke
me.ke
mobi.ke
ne.ke
or.ke
sc.ke

// kg : http://www.domain.kg/dmn_n.html
kg
org.kg
net.kg
com.kg
edu.kg
gov.kg
mil.kg

// kh : http://www.mptc.gov.kh/dns_registration.htm
*.kh

// ki : http://www.ki/dns/index.html
ki
edu.ki
biz.ki
net.ki
org.ki
gov.ki
info.ki
com.ki

// km : https://en.wikipedia.org/wiki/.km
// http://www.domaine.km/documents/charte.doc
km
org.km
nom.km
gov.km
prd.km
tm.km
edu.km
mil.km
ass.km
com.km
// These are only mentioned as proposed suggestions at domaine.km, but
// https://en.wikipedia.org/wiki/.km says they're available for registration:
coop.km
asso.km
presse.km
medecin.km
notaires.km
pharmaciens.km
veterinaire.km
gouv.km

// kn : https://en.wikipedia.org/wiki/.kn
// http://www.dot.kn/domainRules.html
kn
net.kn
org.kn
edu.kn
gov.kn

// kp : http://www.kcce.kp/en_index.php
kp
com.kp
edu.kp
gov.kp
org.kp
rep.kp
tra.kp

// kr : https://en.wikipedia.org/wiki/.kr
// see also: http://domain.nida.or.kr/eng/registration.jsp
kr
ac.kr
co.kr
es.kr
go.kr
hs.kr
kg.kr
mil.kr
ms.kr
ne.kr
or.kr
pe.kr
re.kr
sc.kr
// kr geographical names
busan.kr
chungbuk.kr
chungnam.kr
daegu.kr
daejeon.kr
gangwon.kr
gwangju.kr
gyeongbuk.kr
gyeonggi.kr
gyeongnam.kr
incheon.kr
jeju.kr
jeonbuk.kr
jeonnam.kr
seoul.kr
ulsan.kr

// kw : https://www.nic.kw/policies/
// Confirmed by registry <nic.tech@citra.gov.kw>
kw
com.kw
edu.kw
emb.kw
gov.kw
ind.kw
net.kw
org.kw

// ky : http://www.icta.ky/da_ky_reg_dom.php
// Confirmed by registry <kysupport@perimeterusa.com> 2008-06-17
ky
edu.ky
gov.ky
com.ky
org.ky
net.ky

// kz : https://en.wikipedia.org/wiki/.kz
// see also: http://www.nic.kz/rules/index.jsp
kz
org.kz
edu.kz
net.kz
gov.kz
mil.kz
com.kz

// la : https://en.wikipedia.org/wiki/.la
// Submitted by registry <gavin.brown@nic.la>
la
int.la
net.la
info.la
edu.la
gov.la
per.la
com.la
org.la

// lb : https://en.wikipedia.org/wiki/.lb
// Submitted by registry <randy@psg.com>
lb
com.lb
edu.lb
gov.lb
net.lb
org.lb

// lc : https://en.wikipedia.org/wiki/.lc
// see also: http://www.nic.lc/rules.htm
lc
com.lc
net.lc
co.lc
org.lc
edu.lc
gov.lc

// li : https://en.wikipedia.org/wiki/.li
li

// lk : https://www.nic.lk/index.php/domain-registration/lk-domain-naming-structure
lk
gov.lk
sch.lk
net.lk
int.lk
com.lk
org.lk
edu.lk
ngo.lk
soc.lk
web.lk
ltd.lk
assn.lk
grp.lk
hotel.lk
ac.lk

// lr : http://psg.com/dns/lr/lr.txt
// Submitted by registry <randy@psg.com>
lr
com.lr
edu.lr
gov.lr
org.lr
net.lr

// ls : http://www.nic.ls/
// Confirmed by registry <lsadmin@nic.ls>
ls
ac.ls
biz.ls
co.ls
edu.ls
gov.ls
info.ls
net.ls
org.ls
sc.ls

// lt : https://en.wikipedia.org/wiki/.lt
lt
// gov.lt : http://www.gov.lt/index_en.php
gov.lt

// lu : http://www.dns.lu/en/
lu

// lv : http://www.nic.lv/DNS/En/generic.php
lv
com.lv
edu.lv
gov.lv
org.lv
mil.lv
id.lv
net.lv
asn.lv
conf.lv

// ly : http://www.nic.ly/regulations.php
ly
com.ly
net.ly
gov.ly
plc.ly
edu.ly
sch.ly
med.ly
org.ly
id.ly

// ma : https://en.wikipedia.org/wiki/.ma
// http://www.anrt.ma/fr/admin/download/upload/file_fr782.pdf
ma
co.ma
net.ma
gov.ma
org.ma
ac.ma
press.ma

// mc : http://www.nic.mc/
mc
tm.mc
asso.mc

// md : https://en.wikipedia.org/wiki/.md
md

// me : https://en.wikipedia.org/wiki/.me
me
co.me
net.me
org.me
edu.me
ac.me
gov.me
its.me
priv.me

// mg : http://nic.mg/nicmg/?page_id=39
mg
org.mg
nom.mg
gov.mg
prd.mg
tm.mg
edu.mg
mil.mg
com.mg
co.mg

// mh : https://en.wikipedia.org/wiki/.mh
mh

// mil : https://en.wikipedia.org/wiki/.mil
mil

// mk : https://en.wikipedia.org/wiki/.mk
// see also: http://dns.marnet.net.mk/postapka.php
mk
com.mk
org.mk
net.mk
edu.mk
gov.mk
inf.mk
name.mk

// ml : http://www.gobin.info/domainname/ml-template.doc
// see also: https://en.wikipedia.org/wiki/.ml
ml
com.ml
edu.ml
gouv.ml
gov.ml
net.ml
org.ml
presse.ml

// mm : https://en.wikipedia.org/wiki/.mm
*.mm

// mn : https://en.wikipedia.org/wiki/.mn
mn
gov.mn
edu.mn
org.mn

// mo : http://www.monic.net.mo/
mo
com.mo
net.mo
org.mo
edu.mo
gov.mo

// mobi : https://en.wikipedia.org/wiki/.mobi
mobi

// mp : http://www.dot.mp/
// Confirmed by registry <dcamacho@saipan.com> 2008-06-17
mp

// mq : https://en.wikipedia.org/wiki/.mq
mq

// mr : https://en.wikipedia.org/wiki/.mr
mr
gov.mr

// ms : http://www.nic.ms/pdf/MS_Domain_Name_Rules.pdf
ms
com.ms
edu.ms
gov.ms
net.ms
org.ms

// mt : https://www.nic.org.mt/go/policy
// Submitted by registry <help@nic.org.mt>
mt
com.mt
edu.mt
net.mt
org.mt

// mu : https://en.wikipedia.org/wiki/.mu
mu
com.mu
net.mu
org.mu
gov.mu
ac.mu
co.mu
or.mu

// museum : http://about.museum/naming/
// http://index.museum/
museum
academy.museum
agriculture.museum
air.museum
airguard.museum
alabama.museum
alaska.museum
amber.museum
ambulance.museum
american.museum
americana.museum
americanantiques.museum
americanart.museum
amsterdam.museum
and.museum
annefrank.museum
anthro.museum
anthropology.museum
antiques.museum
aquarium.museum
arboretum.museum
archaeological.museum
archaeology.museum
architecture.museum
art.museum
artanddesign.museum
artcenter.museum
artdeco.museum
arteducation.museum
artgallery.museum
arts.museum
artsandcrafts.museum
asmatart.museum
assassination.museum
assisi.museum
association.museum
astronomy.museum
atlanta.museum
austin.museum
australia.museum
automotive.museum
aviation.museum
axis.museum
badajoz.museum
baghdad.museum
bahn.museum
bale.museum
baltimore.museum
barcelona.museum
baseball.museum
basel.museum
baths.museum
bauern.museum
beauxarts.museum
beeldengeluid.museum
bellevue.museum
bergbau.museum
berkeley.museum
berlin.museum
bern.museum
bible.museum
bilbao.museum
bill.museum
birdart.museum
birthplace.museum
bonn.museum
boston.museum
botanical.museum
botanicalgarden.museum
botanicgarden.museum
botany.museum
brandywinevalley.museum
brasil.museum
bristol.museum
british.museum
britishcolumbia.museum
broadcast.museum
brunel.museum
brussel.museum
brussels.museum
bruxelles.museum
building.museum
burghof.museum
bus.museum
bushey.museum
cadaques.museum
california.museum
cambridge.museum
can.museum
canada.museum
capebreton.museum
carrier.museum
cartoonart.museum
casadelamoneda.museum
castle.museum
castres.museum
celtic.museum
center.museum
chattanooga.museum
cheltenham.museum
chesapeakebay.museum
chicago.museum
children.museum
childrens.museum
childrensgarden.museum
chiropractic.museum
chocolate.museum
christiansburg.museum
cincinnati.museum
cinema.museum
circus.museum
civilisation.museum
civilization.museum
civilwar.museum
clinton.museum
clock.museum
coal.museum
coastaldefence.museum
cody.museum
coldwar.museum
collection.museum
colonialwilliamsburg.museum
coloradoplateau.museum
columbia.museum
columbus.museum
communication.museum
communications.museum
community.museum
computer.museum
computerhistory.museum
comunicaÃ§Ãµes.museum
contemporary.museum
contemporaryart.museum
convent.museum
copenhagen.museum
corporation.museum
correios-e-telecomunicaÃ§Ãµes.museum
corvette.museum
costume.museum
countryestate.museum
county.museum
crafts.museum
cranbrook.museum
creation.museum
cultural.museum
culturalcenter.museum
culture.museum
cyber.museum
cymru.museum
dali.museum
dallas.museum
database.museum
ddr.museum
decorativearts.museum
delaware.museum
delmenhorst.museum
denmark.museum
depot.museum
design.museum
detroit.museum
dinosaur.museum
discovery.museum
dolls.museum
donostia.museum
durham.museum
eastafrica.museum
eastcoast.museum
education.museum
educational.museum
egyptian.museum
eisenbahn.museum
elburg.museum
elvendrell.museum
embroidery.museum
encyclopedic.museum
england.museum
entomology.museum
environment.museum
environmentalconservation.museum
epilepsy.museum
essex.museum
estate.museum
ethnology.museum
exeter.museum
exhibition.museum
family.museum
farm.museum
farmequipment.museum
farmers.museum
farmstead.museum
field.museum
figueres.museum
filatelia.museum
film.museum
fineart.museum
finearts.museum
finland.museum
flanders.museum
florida.museum
force.museum
fortmissoula.museum
fortworth.museum
foundation.museum
francaise.museum
frankfurt.museum
franziskaner.museum
freemasonry.museum
freiburg.museum
fribourg.museum
frog.museum
fundacio.museum
furniture.museum
gallery.museum
garden.museum
gateway.museum
geelvinck.museum
gemological.museum
geology.museum
georgia.museum
giessen.museum
glas.museum
glass.museum
gorge.museum
grandrapids.museum
graz.museum
guernsey.museum
halloffame.museum
hamburg.museum
handson.museum
harvestcelebration.museum
hawaii.museum
health.museum
heimatunduhren.museum
hellas.museum
helsinki.museum
hembygdsforbund.museum
heritage.museum
histoire.museum
historical.museum
historicalsociety.museum
historichouses.museum
historisch.museum
historisches.museum
history.museum
historyofscience.museum
horology.museum
house.museum
humanities.museum
illustration.museum
imageandsound.museum
indian.museum
indiana.museum
indianapolis.museum
indianmarket.museum
intelligence.museum
interactive.museum
iraq.museum
iron.museum
isleofman.museum
jamison.museum
jefferson.museum
jerusalem.museum
jewelry.museum
jewish.museum
jewishart.museum
jfk.museum
journalism.museum
judaica.museum
judygarland.museum
juedisches.museum
juif.museum
karate.museum
karikatur.museum
kids.museum
koebenhavn.museum
koeln.museum
kunst.museum
kunstsammlung.museum
kunstunddesign.museum
labor.museum
labour.museum
lajolla.museum
lancashire.museum
landes.museum
lans.museum
lÃ¤ns.museum
larsson.museum
lewismiller.museum
lincoln.museum
linz.museum
living.museum
livinghistory.museum
localhistory.museum
london.museum
losangeles.museum
louvre.museum
loyalist.museum
lucerne.museum
luxembourg.museum
luzern.museum
mad.museum
madrid.museum
mallorca.museum
manchester.museum
mansion.museum
mansions.museum
manx.museum
marburg.museum
maritime.museum
maritimo.museum
maryland.museum
marylhurst.museum
media.museum
medical.museum
medizinhistorisches.museum
meeres.museum
memorial.museum
mesaverde.museum
michigan.museum
midatlantic.museum
military.museum
mill.museum
miners.museum
mining.museum
minnesota.museum
missile.museum
missoula.museum
modern.museum
moma.museum
money.museum
monmouth.museum
monticello.museum
montreal.museum
moscow.museum
motorcycle.museum
muenchen.museum
muenster.museum
mulhouse.museum
muncie.museum
museet.museum
museumcenter.museum
museumvereniging.museum
music.museum
national.museum
nationalfirearms.museum
nationalheritage.museum
nativeamerican.museum
naturalhistory.museum
naturalhistorymuseum.museum
naturalsciences.museum
nature.museum
naturhistorisches.museum
natuurwetenschappen.museum
naumburg.museum
naval.museum
nebraska.museum
neues.museum
newhampshire.museum
newjersey.museum
newmexico.museum
newport.museum
newspaper.museum
newyork.museum
niepce.museum
norfolk.museum
north.museum
nrw.museum
nyc.museum
nyny.museum
oceanographic.museum
oceanographique.museum
omaha.museum
online.museum
ontario.museum
openair.museum
oregon.museum
oregontrail.museum
otago.museum
oxford.museum
pacific.museum
paderborn.museum
palace.museum
paleo.museum
palmsprings.museum
panama.museum
paris.museum
pasadena.museum
pharmacy.museum
philadelphia.museum
philadelphiaarea.museum
philately.museum
phoenix.museum
photography.museum
pilots.museum
pittsburgh.museum
planetarium.museum
plantation.museum
plants.museum
plaza.museum
portal.museum
portland.museum
portlligat.museum
posts-and-telecommunications.museum
preservation.museum
presidio.museum
press.museum
project.museum
public.museum
pubol.museum
quebec.museum
railroad.museum
railway.museum
research.museum
resistance.museum
riodejaneiro.museum
rochester.museum
rockart.museum
roma.museum
russia.museum
saintlouis.museum
salem.museum
salvadordali.museum
salzburg.museum
sandiego.museum
sanfrancisco.museum
santabarbara.museum
santacruz.museum
santafe.museum
saskatchewan.museum
satx.museum
savannahga.museum
schlesisches.museum
schoenbrunn.museum
schokoladen.museum
school.museum
schweiz.museum
science.museum
scienceandhistory.museum
scienceandindustry.museum
sciencecenter.museum
sciencecenters.museum
science-fiction.museum
sciencehistory.museum
sciences.museum
sciencesnaturelles.museum
scotland.museum
seaport.museum
settlement.museum
settlers.museum
shell.museum
sherbrooke.museum
sibenik.museum
silk.museum
ski.museum
skole.museum
society.museum
sologne.museum
soundandvision.museum
southcarolina.museum
southwest.museum
space.museum
spy.museum
square.museum
stadt.museum
stalbans.museum
starnberg.museum
state.museum
stateofdelaware.museum
station.museum
steam.museum
steiermark.museum
stjohn.museum
stockholm.museum
stpetersburg.museum
stuttgart.museum
suisse.museum
surgeonshall.museum
surrey.museum
svizzera.museum
sweden.museum
sydney.museum
tank.museum
tcm.museum
technology.museum
telekommunikation.museum
television.museum
texas.museum
textile.museum
theater.museum
time.museum
timekeeping.museum
topology.museum
torino.museum
touch.museum
town.museum
transport.museum
tree.museum
trolley.museum
trust.museum
trustee.museum
uhren.museum
ulm.museum
undersea.museum
university.museum
usa.museum
usantiques.museum
usarts.museum
uscountryestate.museum
usculture.museum
usdecorativearts.museum
usgarden.museum
ushistory.museum
ushuaia.museum
uslivinghistory.museum
utah.museum
uvic.museum
valley.museum
vantaa.museum
versailles.museum
viking.museum
village.museum
virginia.museum
virtual.museum
virtuel.museum
vlaanderen.museum
volkenkunde.museum
wales.museum
wallonie.museum
war.museum
washingtondc.museum
watchandclock.museum
watch-and-clock.museum
western.museum
westfalen.museum
whaling.museum
wildlife.museum
williamsburg.museum
windmill.museum
workshop.museum
york.museum
yorkshire.museum
yosemite.museum
youth.museum
zoological.museum
zoology.museum
×™×¨×•×©×œ×™×�.museum
Ð¸ÐºÐ¾Ð¼.museum

// mv : https://en.wikipedia.org/wiki/.mv
// "mv" included because, contra Wikipedia, google.mv exists.
mv
aero.mv
biz.mv
com.mv
coop.mv
edu.mv
gov.mv
info.mv
int.mv
mil.mv
museum.mv
name.mv
net.mv
org.mv
pro.mv

// mw : http://www.registrar.mw/
mw
ac.mw
biz.mw
co.mw
com.mw
coop.mw
edu.mw
gov.mw
int.mw
museum.mw
net.mw
org.mw

// mx : http://www.nic.mx/
// Submitted by registry <farias@nic.mx>
mx
com.mx
org.mx
gob.mx
edu.mx
net.mx

// my : http://www.mynic.my/
// Available strings: https://mynic.my/resources/domains/buying-a-domain/
my
biz.my
com.my
edu.my
gov.my
mil.my
name.my
net.my
org.my

// mz : http://www.uem.mz/
// Submitted by registry <antonio@uem.mz>
mz
ac.mz
adv.mz
co.mz
edu.mz
gov.mz
mil.mz
net.mz
org.mz

// na : http://www.na-nic.com.na/
// http://www.info.na/domain/
na
info.na
pro.na
name.na
school.na
or.na
dr.na
us.na
mx.na
ca.na
in.na
cc.na
tv.na
ws.na
mobi.na
co.na
com.na
org.na

// name : has 2nd-level tlds, but there's no list of them
name

// nc : http://www.cctld.nc/
nc
asso.nc
nom.nc

// ne : https://en.wikipedia.org/wiki/.ne
ne

// net : https://en.wikipedia.org/wiki/.net
net

// nf : https://en.wikipedia.org/wiki/.nf
nf
com.nf
net.nf
per.nf
rec.nf
web.nf
arts.nf
firm.nf
info.nf
other.nf
store.nf

// ng : http://www.nira.org.ng/index.php/join-us/register-ng-domain/189-nira-slds
ng
com.ng
edu.ng
gov.ng
i.ng
mil.ng
mobi.ng
name.ng
net.ng
org.ng
sch.ng

// ni : http://www.nic.ni/
ni
ac.ni
biz.ni
co.ni
com.ni
edu.ni
gob.ni
in.ni
info.ni
int.ni
mil.ni
net.ni
nom.ni
org.ni
web.ni

// nl : https://en.wikipedia.org/wiki/.nl
//      https://www.sidn.nl/
//      ccTLD for the Netherlands
nl

// no : https://www.norid.no/en/om-domenenavn/regelverk-for-no/
// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/
// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/
// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/
// RSS feed: https://teknisk.norid.no/en/feed/
no
// Norid category second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-c/
fhs.no
vgs.no
fylkesbibl.no
folkebibl.no
museum.no
idrett.no
priv.no
// Norid category second-level domains managed by parties other than Norid : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-d/
mil.no
stat.no
dep.no
kommune.no
herad.no
// Norid geographical second level domains : https://www.norid.no/en/om-domenenavn/regelverk-for-no/vedlegg-b/
// counties
aa.no
ah.no
bu.no
fm.no
hl.no
hm.no
jan-mayen.no
mr.no
nl.no
nt.no
of.no
ol.no
oslo.no
rl.no
sf.no
st.no
svalbard.no
tm.no
tr.no
va.no
vf.no
// primary and lower secondary schools per county
gs.aa.no
gs.ah.no
gs.bu.no
gs.fm.no
gs.hl.no
gs.hm.no
gs.jan-mayen.no
gs.mr.no
gs.nl.no
gs.nt.no
gs.of.no
gs.ol.no
gs.oslo.no
gs.rl.no
gs.sf.no
gs.st.no
gs.svalbard.no
gs.tm.no
gs.tr.no
gs.va.no
gs.vf.no
// cities
akrehamn.no
Ã¥krehamn.no
algard.no
Ã¥lgÃ¥rd.no
arna.no
brumunddal.no
bryne.no
bronnoysund.no
brÃ¸nnÃ¸ysund.no
drobak.no
drÃ¸bak.no
egersund.no
fetsund.no
floro.no
florÃ¸.no
fredrikstad.no
hokksund.no
honefoss.no
hÃ¸nefoss.no
jessheim.no
jorpeland.no
jÃ¸rpeland.no
kirkenes.no
kopervik.no
krokstadelva.no
langevag.no
langevÃ¥g.no
leirvik.no
mjondalen.no
mjÃ¸ndalen.no
mo-i-rana.no
mosjoen.no
mosjÃ¸en.no
nesoddtangen.no
orkanger.no
osoyro.no
osÃ¸yro.no
raholt.no
rÃ¥holt.no
sandnessjoen.no
sandnessjÃ¸en.no
skedsmokorset.no
slattum.no
spjelkavik.no
stathelle.no
stavern.no
stjordalshalsen.no
stjÃ¸rdalshalsen.no
tananger.no
tranby.no
vossevangen.no
// communities
afjord.no
Ã¥fjord.no
agdenes.no
al.no
Ã¥l.no
alesund.no
Ã¥lesund.no
alstahaug.no
alta.no
Ã¡ltÃ¡.no
alaheadju.no
Ã¡laheadju.no
alvdal.no
amli.no
Ã¥mli.no
amot.no
Ã¥mot.no
andebu.no
andoy.no
andÃ¸y.no
andasuolo.no
ardal.no
Ã¥rdal.no
aremark.no
arendal.no
Ã¥s.no
aseral.no
Ã¥seral.no
asker.no
askim.no
askvoll.no
askoy.no
askÃ¸y.no
asnes.no
Ã¥snes.no
audnedaln.no
aukra.no
aure.no
aurland.no
aurskog-holand.no
aurskog-hÃ¸land.no
austevoll.no
austrheim.no
averoy.no
averÃ¸y.no
balestrand.no
ballangen.no
balat.no
bÃ¡lÃ¡t.no
balsfjord.no
bahccavuotna.no
bÃ¡hccavuotna.no
bamble.no
bardu.no
beardu.no
beiarn.no
bajddar.no
bÃ¡jddar.no
baidar.no
bÃ¡idÃ¡r.no
berg.no
bergen.no
berlevag.no
berlevÃ¥g.no
bearalvahki.no
bearalvÃ¡hki.no
bindal.no
birkenes.no
bjarkoy.no
bjarkÃ¸y.no
bjerkreim.no
bjugn.no
bodo.no
bodÃ¸.no
badaddja.no
bÃ¥dÃ¥ddjÃ¥.no
budejju.no
bokn.no
bremanger.no
bronnoy.no
brÃ¸nnÃ¸y.no
bygland.no
bykle.no
barum.no
bÃ¦rum.no
bo.telemark.no
bÃ¸.telemark.no
bo.nordland.no
bÃ¸.nordland.no
bievat.no
bievÃ¡t.no
bomlo.no
bÃ¸mlo.no
batsfjord.no
bÃ¥tsfjord.no
bahcavuotna.no
bÃ¡hcavuotna.no
dovre.no
drammen.no
drangedal.no
dyroy.no
dyrÃ¸y.no
donna.no
dÃ¸nna.no
eid.no
eidfjord.no
eidsberg.no
eidskog.no
eidsvoll.no
eigersund.no
elverum.no
enebakk.no
engerdal.no
etne.no
etnedal.no
evenes.no
evenassi.no
evenÃ¡Å¡Å¡i.no
evje-og-hornnes.no
farsund.no
fauske.no
fuossko.no
fuoisku.no
fedje.no
fet.no
finnoy.no
finnÃ¸y.no
fitjar.no
fjaler.no
fjell.no
flakstad.no
flatanger.no
flekkefjord.no
flesberg.no
flora.no
fla.no
flÃ¥.no
folldal.no
forsand.no
fosnes.no
frei.no
frogn.no
froland.no
frosta.no
frana.no
frÃ¦na.no
froya.no
frÃ¸ya.no
fusa.no
fyresdal.no
forde.no
fÃ¸rde.no
gamvik.no
gangaviika.no
gÃ¡Å‹gaviika.no
gaular.no
gausdal.no
gildeskal.no
gildeskÃ¥l.no
giske.no
gjemnes.no
gjerdrum.no
gjerstad.no
gjesdal.no
gjovik.no
gjÃ¸vik.no
gloppen.no
gol.no
gran.no
grane.no
granvin.no
gratangen.no
grimstad.no
grong.no
kraanghke.no
krÃ¥anghke.no
grue.no
gulen.no
hadsel.no
halden.no
halsa.no
hamar.no
hamaroy.no
habmer.no
hÃ¡bmer.no
hapmir.no
hÃ¡pmir.no
hammerfest.no
hammarfeasta.no
hÃ¡mmÃ¡rfeasta.no
haram.no
hareid.no
harstad.no
hasvik.no
aknoluokta.no
Ã¡kÅ‹oluokta.no
hattfjelldal.no
aarborte.no
haugesund.no
hemne.no
hemnes.no
hemsedal.no
heroy.more-og-romsdal.no
herÃ¸y.mÃ¸re-og-romsdal.no
heroy.nordland.no
herÃ¸y.nordland.no
hitra.no
hjartdal.no
hjelmeland.no
hobol.no
hobÃ¸l.no
hof.no
hol.no
hole.no
holmestrand.no
holtalen.no
holtÃ¥len.no
hornindal.no
horten.no
hurdal.no
hurum.no
hvaler.no
hyllestad.no
hagebostad.no
hÃ¦gebostad.no
hoyanger.no
hÃ¸yanger.no
hoylandet.no
hÃ¸ylandet.no
ha.no
hÃ¥.no
ibestad.no
inderoy.no
inderÃ¸y.no
iveland.no
jevnaker.no
jondal.no
jolster.no
jÃ¸lster.no
karasjok.no
karasjohka.no
kÃ¡rÃ¡Å¡johka.no
karlsoy.no
galsa.no
gÃ¡lsÃ¡.no
karmoy.no
karmÃ¸y.no
kautokeino.no
guovdageaidnu.no
klepp.no
klabu.no
klÃ¦bu.no
kongsberg.no
kongsvinger.no
kragero.no
kragerÃ¸.no
kristiansand.no
kristiansund.no
krodsherad.no
krÃ¸dsherad.no
kvalsund.no
rahkkeravju.no
rÃ¡hkkerÃ¡vju.no
kvam.no
kvinesdal.no
kvinnherad.no
kviteseid.no
kvitsoy.no
kvitsÃ¸y.no
kvafjord.no
kvÃ¦fjord.no
giehtavuoatna.no
kvanangen.no
kvÃ¦nangen.no
navuotna.no
nÃ¡vuotna.no
kafjord.no
kÃ¥fjord.no
gaivuotna.no
gÃ¡ivuotna.no
larvik.no
lavangen.no
lavagis.no
loabat.no
loabÃ¡t.no
lebesby.no
davvesiida.no
leikanger.no
leirfjord.no
leka.no
leksvik.no
lenvik.no
leangaviika.no
leaÅ‹gaviika.no
lesja.no
levanger.no
lier.no
lierne.no
lillehammer.no
lillesand.no
lindesnes.no
lindas.no
lindÃ¥s.no
lom.no
loppa.no
lahppi.no
lÃ¡hppi.no
lund.no
lunner.no
luroy.no
lurÃ¸y.no
luster.no
lyngdal.no
lyngen.no
ivgu.no
lardal.no
lerdal.no
lÃ¦rdal.no
lodingen.no
lÃ¸dingen.no
lorenskog.no
lÃ¸renskog.no
loten.no
lÃ¸ten.no
malvik.no
masoy.no
mÃ¥sÃ¸y.no
muosat.no
muosÃ¡t.no
mandal.no
marker.no
marnardal.no
masfjorden.no
meland.no
meldal.no
melhus.no
meloy.no
melÃ¸y.no
meraker.no
merÃ¥ker.no
moareke.no
moÃ¥reke.no
midsund.no
midtre-gauldal.no
modalen.no
modum.no
molde.no
moskenes.no
moss.no
mosvik.no
malselv.no
mÃ¥lselv.no
malatvuopmi.no
mÃ¡latvuopmi.no
namdalseid.no
aejrie.no
namsos.no
namsskogan.no
naamesjevuemie.no
nÃ¥Ã¥mesjevuemie.no
laakesvuemie.no
nannestad.no
narvik.no
narviika.no
naustdal.no
nedre-eiker.no
nes.akershus.no
nes.buskerud.no
nesna.no
nesodden.no
nesseby.no
unjarga.no
unjÃ¡rga.no
nesset.no
nissedal.no
nittedal.no
nord-aurdal.no
nord-fron.no
nord-odal.no
norddal.no
nordkapp.no
davvenjarga.no
davvenjÃ¡rga.no
nordre-land.no
nordreisa.no
raisa.no
rÃ¡isa.no
nore-og-uvdal.no
notodden.no
naroy.no
nÃ¦rÃ¸y.no
notteroy.no
nÃ¸tterÃ¸y.no
odda.no
oksnes.no
Ã¸ksnes.no
oppdal.no
oppegard.no
oppegÃ¥rd.no
orkdal.no
orland.no
Ã¸rland.no
orskog.no
Ã¸rskog.no
orsta.no
Ã¸rsta.no
os.hedmark.no
os.hordaland.no
osen.no
osteroy.no
osterÃ¸y.no
ostre-toten.no
Ã¸stre-toten.no
overhalla.no
ovre-eiker.no
Ã¸vre-eiker.no
oyer.no
Ã¸yer.no
oygarden.no
Ã¸ygarden.no
oystre-slidre.no
Ã¸ystre-slidre.no
porsanger.no
porsangu.no
porsÃ¡Å‹gu.no
porsgrunn.no
radoy.no
radÃ¸y.no
rakkestad.no
rana.no
ruovat.no
randaberg.no
rauma.no
rendalen.no
rennebu.no
rennesoy.no
rennesÃ¸y.no
rindal.no
ringebu.no
ringerike.no
ringsaker.no
rissa.no
risor.no
risÃ¸r.no
roan.no
rollag.no
rygge.no
ralingen.no
rÃ¦lingen.no
rodoy.no
rÃ¸dÃ¸y.no
romskog.no
rÃ¸mskog.no
roros.no
rÃ¸ros.no
rost.no
rÃ¸st.no
royken.no
rÃ¸yken.no
royrvik.no
rÃ¸yrvik.no
rade.no
rÃ¥de.no
salangen.no
siellak.no
saltdal.no
salat.no
sÃ¡lÃ¡t.no
sÃ¡lat.no
samnanger.no
sande.more-og-romsdal.no
sande.mÃ¸re-og-romsdal.no
sande.vestfold.no
sandefjord.no
sandnes.no
sandoy.no
sandÃ¸y.no
sarpsborg.no
sauda.no
sauherad.no
sel.no
selbu.no
selje.no
seljord.no
sigdal.no
siljan.no
sirdal.no
skaun.no
skedsmo.no
ski.no
skien.no
skiptvet.no
skjervoy.no
skjervÃ¸y.no
skierva.no
skiervÃ¡.no
skjak.no
skjÃ¥k.no
skodje.no
skanland.no
skÃ¥nland.no
skanit.no
skÃ¡nit.no
smola.no
smÃ¸la.no
snillfjord.no
snasa.no
snÃ¥sa.no
snoasa.no
snaase.no
snÃ¥ase.no
sogndal.no
sokndal.no
sola.no
solund.no
songdalen.no
sortland.no
spydeberg.no
stange.no
stavanger.no
steigen.no
steinkjer.no
stjordal.no
stjÃ¸rdal.no
stokke.no
stor-elvdal.no
stord.no
stordal.no
storfjord.no
omasvuotna.no
strand.no
stranda.no
stryn.no
sula.no
suldal.no
sund.no
sunndal.no
surnadal.no
sveio.no
svelvik.no
sykkylven.no
sogne.no
sÃ¸gne.no
somna.no
sÃ¸mna.no
sondre-land.no
sÃ¸ndre-land.no
sor-aurdal.no
sÃ¸r-aurdal.no
sor-fron.no
sÃ¸r-fron.no
sor-odal.no
sÃ¸r-odal.no
sor-varanger.no
sÃ¸r-varanger.no
matta-varjjat.no
mÃ¡tta-vÃ¡rjjat.no
sorfold.no
sÃ¸rfold.no
sorreisa.no
sÃ¸rreisa.no
sorum.no
sÃ¸rum.no
tana.no
deatnu.no
time.no
tingvoll.no
tinn.no
tjeldsund.no
dielddanuorri.no
tjome.no
tjÃ¸me.no
tokke.no
tolga.no
torsken.no
tranoy.no
tranÃ¸y.no
tromso.no
tromsÃ¸.no
tromsa.no
romsa.no
trondheim.no
troandin.no
trysil.no
trana.no
trÃ¦na.no
trogstad.no
trÃ¸gstad.no
tvedestrand.no
tydal.no
tynset.no
tysfjord.no
divtasvuodna.no
divttasvuotna.no
tysnes.no
tysvar.no
tysvÃ¦r.no
tonsberg.no
tÃ¸nsberg.no
ullensaker.no
ullensvang.no
ulvik.no
utsira.no
vadso.no
vadsÃ¸.no
cahcesuolo.no
Ä�Ã¡hcesuolo.no
vaksdal.no
valle.no
vang.no
vanylven.no
vardo.no
vardÃ¸.no
varggat.no
vÃ¡rggÃ¡t.no
vefsn.no
vaapste.no
vega.no
vegarshei.no
vegÃ¥rshei.no
vennesla.no
verdal.no
verran.no
vestby.no
vestnes.no
vestre-slidre.no
vestre-toten.no
vestvagoy.no
vestvÃ¥gÃ¸y.no
vevelstad.no
vik.no
vikna.no
vindafjord.no
volda.no
voss.no
varoy.no
vÃ¦rÃ¸y.no
vagan.no
vÃ¥gan.no
voagat.no
vagsoy.no
vÃ¥gsÃ¸y.no
vaga.no
vÃ¥gÃ¥.no
valer.ostfold.no
vÃ¥ler.Ã¸stfold.no
valer.hedmark.no
vÃ¥ler.hedmark.no

// np : http://www.mos.com.np/register.html
*.np

// nr : http://cenpac.net.nr/dns/index.html
// Submitted by registry <technician@cenpac.net.nr>
nr
biz.nr
info.nr
gov.nr
edu.nr
org.nr
net.nr
com.nr

// nu : https://en.wikipedia.org/wiki/.nu
nu

// nz : https://en.wikipedia.org/wiki/.nz
// Submitted by registry <jay@nzrs.net.nz>
nz
ac.nz
co.nz
cri.nz
geek.nz
gen.nz
govt.nz
health.nz
iwi.nz
kiwi.nz
maori.nz
mil.nz
mÄ�ori.nz
net.nz
org.nz
parliament.nz
school.nz

// om : https://en.wikipedia.org/wiki/.om
om
co.om
com.om
edu.om
gov.om
med.om
museum.om
net.om
org.om
pro.om

// onion : https://tools.ietf.org/html/rfc7686
onion

// org : https://en.wikipedia.org/wiki/.org
org

// pa : http://www.nic.pa/
// Some additional second level "domains" resolve directly as hostnames, such as
// pannet.pa, so we add a rule for "pa".
pa
ac.pa
gob.pa
com.pa
org.pa
sld.pa
edu.pa
net.pa
ing.pa
abo.pa
med.pa
nom.pa

// pe : https://www.nic.pe/InformeFinalComision.pdf
pe
edu.pe
gob.pe
nom.pe
mil.pe
org.pe
com.pe
net.pe

// pf : http://www.gobin.info/domainname/formulaire-pf.pdf
pf
com.pf
org.pf
edu.pf

// pg : https://en.wikipedia.org/wiki/.pg
*.pg

// ph : http://www.domains.ph/FAQ2.asp
// Submitted by registry <jed@email.com.ph>
ph
com.ph
net.ph
org.ph
gov.ph
edu.ph
ngo.ph
mil.ph
i.ph

// pk : http://pk5.pknic.net.pk/pk5/msgNamepk.PK
pk
com.pk
net.pk
edu.pk
org.pk
fam.pk
biz.pk
web.pk
gov.pk
gob.pk
gok.pk
gon.pk
gop.pk
gos.pk
info.pk

// pl http://www.dns.pl/english/index.html
// Submitted by registry
pl
com.pl
net.pl
org.pl
// pl functional domains (http://www.dns.pl/english/index.html)
aid.pl
agro.pl
atm.pl
auto.pl
biz.pl
edu.pl
gmina.pl
gsm.pl
info.pl
mail.pl
miasta.pl
media.pl
mil.pl
nieruchomosci.pl
nom.pl
pc.pl
powiat.pl
priv.pl
realestate.pl
rel.pl
sex.pl
shop.pl
sklep.pl
sos.pl
szkola.pl
targi.pl
tm.pl
tourism.pl
travel.pl
turystyka.pl
// Government domains
gov.pl
ap.gov.pl
ic.gov.pl
is.gov.pl
us.gov.pl
kmpsp.gov.pl
kppsp.gov.pl
kwpsp.gov.pl
psp.gov.pl
wskr.gov.pl
kwp.gov.pl
mw.gov.pl
ug.gov.pl
um.gov.pl
umig.gov.pl
ugim.gov.pl
upow.gov.pl
uw.gov.pl
starostwo.gov.pl
pa.gov.pl
po.gov.pl
psse.gov.pl
pup.gov.pl
rzgw.gov.pl
sa.gov.pl
so.gov.pl
sr.gov.pl
wsa.gov.pl
sko.gov.pl
uzs.gov.pl
wiih.gov.pl
winb.gov.pl
pinb.gov.pl
wios.gov.pl
witd.gov.pl
wzmiuw.gov.pl
piw.gov.pl
wiw.gov.pl
griw.gov.pl
wif.gov.pl
oum.gov.pl
sdn.gov.pl
zp.gov.pl
uppo.gov.pl
mup.gov.pl
wuoz.gov.pl
konsulat.gov.pl
oirm.gov.pl
// pl regional domains (http://www.dns.pl/english/index.html)
augustow.pl
babia-gora.pl
bedzin.pl
beskidy.pl
bialowieza.pl
bialystok.pl
bielawa.pl
bieszczady.pl
boleslawiec.pl
bydgoszcz.pl
bytom.pl
cieszyn.pl
czeladz.pl
czest.pl
dlugoleka.pl
elblag.pl
elk.pl
glogow.pl
gniezno.pl
gorlice.pl
grajewo.pl
ilawa.pl
jaworzno.pl
jelenia-gora.pl
jgora.pl
kalisz.pl
kazimierz-dolny.pl
karpacz.pl
kartuzy.pl
kaszuby.pl
katowice.pl
kepno.pl
ketrzyn.pl
klodzko.pl
kobierzyce.pl
kolobrzeg.pl
konin.pl
konskowola.pl
kutno.pl
lapy.pl
lebork.pl
legnica.pl
lezajsk.pl
limanowa.pl
lomza.pl
lowicz.pl
lubin.pl
lukow.pl
malbork.pl
malopolska.pl
mazowsze.pl
mazury.pl
mielec.pl
mielno.pl
mragowo.pl
naklo.pl
nowaruda.pl
nysa.pl
olawa.pl
olecko.pl
olkusz.pl
olsztyn.pl
opoczno.pl
opole.pl
ostroda.pl
ostroleka.pl
ostrowiec.pl
ostrowwlkp.pl
pila.pl
pisz.pl
podhale.pl
podlasie.pl
polkowice.pl
pomorze.pl
pomorskie.pl
prochowice.pl
pruszkow.pl
przeworsk.pl
pulawy.pl
radom.pl
rawa-maz.pl
rybnik.pl
rzeszow.pl
sanok.pl
sejny.pl
slask.pl
slupsk.pl
sosnowiec.pl
stalowa-wola.pl
skoczow.pl
starachowice.pl
stargard.pl
suwalki.pl
swidnica.pl
swiebodzin.pl
swinoujscie.pl
szczecin.pl
szczytno.pl
tarnobrzeg.pl
tgory.pl
turek.pl
tychy.pl
ustka.pl
walbrzych.pl
warmia.pl
warszawa.pl
waw.pl
wegrow.pl
wielun.pl
wlocl.pl
wloclawek.pl
wodzislaw.pl
wolomin.pl
wroclaw.pl
zachpomor.pl
zagan.pl
zarow.pl
zgora.pl
zgorzelec.pl

// pm : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
pm

// pn : http://www.government.pn/PnRegistry/policies.htm
pn
gov.pn
co.pn
org.pn
edu.pn
net.pn

// post : https://en.wikipedia.org/wiki/.post
post

// pr : http://www.nic.pr/index.asp?f=1
pr
com.pr
net.pr
org.pr
gov.pr
edu.pr
isla.pr
pro.pr
biz.pr
info.pr
name.pr
// these aren't mentioned on nic.pr, but on https://en.wikipedia.org/wiki/.pr
est.pr
prof.pr
ac.pr

// pro : http://registry.pro/get-pro
pro
aaa.pro
aca.pro
acct.pro
avocat.pro
bar.pro
cpa.pro
eng.pro
jur.pro
law.pro
med.pro
recht.pro

// ps : https://en.wikipedia.org/wiki/.ps
// http://www.nic.ps/registration/policy.html#reg
ps
edu.ps
gov.ps
sec.ps
plo.ps
com.ps
org.ps
net.ps

// pt : https://www.dns.pt/en/domain/pt-terms-and-conditions-registration-rules/
pt
net.pt
gov.pt
org.pt
edu.pt
int.pt
publ.pt
com.pt
nome.pt

// pw : https://en.wikipedia.org/wiki/.pw
pw
co.pw
ne.pw
or.pw
ed.pw
go.pw
belau.pw

// py : http://www.nic.py/pautas.html#seccion_9
// Submitted by registry
py
com.py
coop.py
edu.py
gov.py
mil.py
net.py
org.py

// qa : http://domains.qa/en/
qa
com.qa
edu.qa
gov.qa
mil.qa
name.qa
net.qa
org.qa
sch.qa

// re : http://www.afnic.re/obtenir/chartes/nommage-re/annexe-descriptifs
re
asso.re
com.re
nom.re

// ro : http://www.rotld.ro/
ro
arts.ro
com.ro
firm.ro
info.ro
nom.ro
nt.ro
org.ro
rec.ro
store.ro
tm.ro
www.ro

// rs : https://www.rnids.rs/en/domains/national-domains
rs
ac.rs
co.rs
edu.rs
gov.rs
in.rs
org.rs

// ru : https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf
// Submitted by George Georgievsky <gug@cctld.ru>
ru

// rw : https://www.ricta.org.rw/sites/default/files/resources/registry_registrar_contract_0.pdf
rw
ac.rw
co.rw
coop.rw
gov.rw
mil.rw
net.rw
org.rw

// sa : http://www.nic.net.sa/
sa
com.sa
net.sa
org.sa
gov.sa
med.sa
pub.sa
edu.sa
sch.sa

// sb : http://www.sbnic.net.sb/
// Submitted by registry <lee.humphries@telekom.com.sb>
sb
com.sb
edu.sb
gov.sb
net.sb
org.sb

// sc : http://www.nic.sc/
sc
com.sc
gov.sc
net.sc
org.sc
edu.sc

// sd : http://www.isoc.sd/sudanic.isoc.sd/billing_pricing.htm
// Submitted by registry <admin@isoc.sd>
sd
com.sd
net.sd
org.sd
edu.sd
med.sd
tv.sd
gov.sd
info.sd

// se : https://en.wikipedia.org/wiki/.se
// Submitted by registry <patrik.wallstrom@iis.se>
se
a.se
ac.se
b.se
bd.se
brand.se
c.se
d.se
e.se
f.se
fh.se
fhsk.se
fhv.se
g.se
h.se
i.se
k.se
komforb.se
kommunalforbund.se
komvux.se
l.se
lanbib.se
m.se
n.se
naturbruksgymn.se
o.se
org.se
p.se
parti.se
pp.se
press.se
r.se
s.se
t.se
tm.se
u.se
w.se
x.se
y.se
z.se

// sg : http://www.nic.net.sg/page/registration-policies-procedures-and-guidelines
sg
com.sg
net.sg
org.sg
gov.sg
edu.sg
per.sg

// sh : http://www.nic.sh/registrar.html
sh
com.sh
net.sh
gov.sh
org.sh
mil.sh

// si : https://en.wikipedia.org/wiki/.si
si

// sj : No registrations at this time.
// Submitted by registry <jarle@uninett.no>
sj

// sk : https://en.wikipedia.org/wiki/.sk
// list of 2nd level domains ?
sk

// sl : http://www.nic.sl
// Submitted by registry <adam@neoip.com>
sl
com.sl
net.sl
edu.sl
gov.sl
org.sl

// sm : https://en.wikipedia.org/wiki/.sm
sm

// sn : https://en.wikipedia.org/wiki/.sn
sn
art.sn
com.sn
edu.sn
gouv.sn
org.sn
perso.sn
univ.sn

// so : http://sonic.so/policies/
so
com.so
edu.so
gov.so
me.so
net.so
org.so

// sr : https://en.wikipedia.org/wiki/.sr
sr

// ss : https://registry.nic.ss/
// Submitted by registry <technical@nic.ss>
ss
biz.ss
com.ss
edu.ss
gov.ss
me.ss
net.ss
org.ss
sch.ss

// st : http://www.nic.st/html/policyrules/
st
co.st
com.st
consulado.st
edu.st
embaixada.st
mil.st
net.st
org.st
principe.st
saotome.st
store.st

// su : https://en.wikipedia.org/wiki/.su
su

// sv : http://www.svnet.org.sv/niveldos.pdf
sv
com.sv
edu.sv
gob.sv
org.sv
red.sv

// sx : https://en.wikipedia.org/wiki/.sx
// Submitted by registry <jcvignes@openregistry.com>
sx
gov.sx

// sy : https://en.wikipedia.org/wiki/.sy
// see also: http://www.gobin.info/domainname/sy.doc
sy
edu.sy
gov.sy
net.sy
mil.sy
com.sy
org.sy

// sz : https://en.wikipedia.org/wiki/.sz
// http://www.sispa.org.sz/
sz
co.sz
ac.sz
org.sz

// tc : https://en.wikipedia.org/wiki/.tc
tc

// td : https://en.wikipedia.org/wiki/.td
td

// tel: https://en.wikipedia.org/wiki/.tel
// http://www.telnic.org/
tel

// tf : https://en.wikipedia.org/wiki/.tf
tf

// tg : https://en.wikipedia.org/wiki/.tg
// http://www.nic.tg/
tg

// th : https://en.wikipedia.org/wiki/.th
// Submitted by registry <krit@thains.co.th>
th
ac.th
co.th
go.th
in.th
mi.th
net.th
or.th

// tj : http://www.nic.tj/policy.html
tj
ac.tj
biz.tj
co.tj
com.tj
edu.tj
go.tj
gov.tj
int.tj
mil.tj
name.tj
net.tj
nic.tj
org.tj
test.tj
web.tj

// tk : https://en.wikipedia.org/wiki/.tk
tk

// tl : https://en.wikipedia.org/wiki/.tl
tl
gov.tl

// tm : http://www.nic.tm/local.html
tm
com.tm
co.tm
org.tm
net.tm
nom.tm
gov.tm
mil.tm
edu.tm

// tn : http://www.registre.tn/fr/
// https://whois.ati.tn/
tn
com.tn
ens.tn
fin.tn
gov.tn
ind.tn
info.tn
intl.tn
mincom.tn
nat.tn
net.tn
org.tn
perso.tn
tourism.tn

// to : https://en.wikipedia.org/wiki/.to
// Submitted by registry <egullich@colo.to>
to
com.to
gov.to
net.to
org.to
edu.to
mil.to

// tr : https://nic.tr/
// https://nic.tr/forms/eng/policies.pdf
// https://nic.tr/index.php?USRACTN=PRICELST
tr
av.tr
bbs.tr
bel.tr
biz.tr
com.tr
dr.tr
edu.tr
gen.tr
gov.tr
info.tr
mil.tr
k12.tr
kep.tr
name.tr
net.tr
org.tr
pol.tr
tel.tr
tsk.tr
tv.tr
web.tr
// Used by Northern Cyprus
nc.tr
// Used by government agencies of Northern Cyprus
gov.nc.tr

// tt : http://www.nic.tt/
tt
co.tt
com.tt
org.tt
net.tt
biz.tt
info.tt
pro.tt
int.tt
coop.tt
jobs.tt
mobi.tt
travel.tt
museum.tt
aero.tt
name.tt
gov.tt
edu.tt

// tv : https://en.wikipedia.org/wiki/.tv
// Not listing any 2LDs as reserved since none seem to exist in practice,
// Wikipedia notwithstanding.
tv

// tw : https://en.wikipedia.org/wiki/.tw
tw
edu.tw
gov.tw
mil.tw
com.tw
net.tw
org.tw
idv.tw
game.tw
ebiz.tw
club.tw
ç¶²è·¯.tw
çµ„ç¹”.tw
å•†æ¥­.tw

// tz : http://www.tznic.or.tz/index.php/domains
// Submitted by registry <manager@tznic.or.tz>
tz
ac.tz
co.tz
go.tz
hotel.tz
info.tz
me.tz
mil.tz
mobi.tz
ne.tz
or.tz
sc.tz
tv.tz

// ua : https://hostmaster.ua/policy/?ua
// Submitted by registry <dk@cctld.ua>
ua
// ua 2LD
com.ua
edu.ua
gov.ua
in.ua
net.ua
org.ua
// ua geographic names
// https://hostmaster.ua/2ld/
cherkassy.ua
cherkasy.ua
chernigov.ua
chernihiv.ua
chernivtsi.ua
chernovtsy.ua
ck.ua
cn.ua
cr.ua
crimea.ua
cv.ua
dn.ua
dnepropetrovsk.ua
dnipropetrovsk.ua
donetsk.ua
dp.ua
if.ua
ivano-frankivsk.ua
kh.ua
kharkiv.ua
kharkov.ua
kherson.ua
khmelnitskiy.ua
khmelnytskyi.ua
kiev.ua
kirovograd.ua
km.ua
kr.ua
krym.ua
ks.ua
kv.ua
kyiv.ua
lg.ua
lt.ua
lugansk.ua
lutsk.ua
lv.ua
lviv.ua
mk.ua
mykolaiv.ua
nikolaev.ua
od.ua
odesa.ua
odessa.ua
pl.ua
poltava.ua
rivne.ua
rovno.ua
rv.ua
sb.ua
sebastopol.ua
sevastopol.ua
sm.ua
sumy.ua
te.ua
ternopil.ua
uz.ua
uzhgorod.ua
vinnica.ua
vinnytsia.ua
vn.ua
volyn.ua
yalta.ua
zaporizhzhe.ua
zaporizhzhia.ua
zhitomir.ua
zhytomyr.ua
zp.ua
zt.ua

// ug : https://www.registry.co.ug/
ug
co.ug
or.ug
ac.ug
sc.ug
go.ug
ne.ug
com.ug
org.ug

// uk : https://en.wikipedia.org/wiki/.uk
// Submitted by registry <Michael.Daly@nominet.org.uk>
uk
ac.uk
co.uk
gov.uk
ltd.uk
me.uk
net.uk
nhs.uk
org.uk
plc.uk
police.uk
*.sch.uk

// us : https://en.wikipedia.org/wiki/.us
us
dni.us
fed.us
isa.us
kids.us
nsn.us
// us geographic names
ak.us
al.us
ar.us
as.us
az.us
ca.us
co.us
ct.us
dc.us
de.us
fl.us
ga.us
gu.us
hi.us
ia.us
id.us
il.us
in.us
ks.us
ky.us
la.us
ma.us
md.us
me.us
mi.us
mn.us
mo.us
ms.us
mt.us
nc.us
nd.us
ne.us
nh.us
nj.us
nm.us
nv.us
ny.us
oh.us
ok.us
or.us
pa.us
pr.us
ri.us
sc.us
sd.us
tn.us
tx.us
ut.us
vi.us
vt.us
va.us
wa.us
wi.us
wv.us
wy.us
// The registrar notes several more specific domains available in each state,
// such as state.*.us, dst.*.us, etc., but resolution of these is somewhat
// haphazard; in some states these domains resolve as addresses, while in others
// only subdomains are available, or even nothing at all. We include the
// most common ones where it's clear that different sites are different
// entities.
k12.ak.us
k12.al.us
k12.ar.us
k12.as.us
k12.az.us
k12.ca.us
k12.co.us
k12.ct.us
k12.dc.us
k12.de.us
k12.fl.us
k12.ga.us
k12.gu.us
// k12.hi.us  Bug 614565 - Hawaii has a state-wide DOE login
k12.ia.us
k12.id.us
k12.il.us
k12.in.us
k12.ks.us
k12.ky.us
k12.la.us
k12.ma.us
k12.md.us
k12.me.us
k12.mi.us
k12.mn.us
k12.mo.us
k12.ms.us
k12.mt.us
k12.nc.us
// k12.nd.us  Bug 1028347 - Removed at request of Travis Rosso <trossow@nd.gov>
k12.ne.us
k12.nh.us
k12.nj.us
k12.nm.us
k12.nv.us
k12.ny.us
k12.oh.us
k12.ok.us
k12.or.us
k12.pa.us
k12.pr.us
// k12.ri.us  Removed at request of Kim Cournoyer <netsupport@staff.ri.net>
k12.sc.us
// k12.sd.us  Bug 934131 - Removed at request of James Booze <James.Booze@k12.sd.us>
k12.tn.us
k12.tx.us
k12.ut.us
k12.vi.us
k12.vt.us
k12.va.us
k12.wa.us
k12.wi.us
// k12.wv.us  Bug 947705 - Removed at request of Verne Britton <verne@wvnet.edu>
k12.wy.us
cc.ak.us
cc.al.us
cc.ar.us
cc.as.us
cc.az.us
cc.ca.us
cc.co.us
cc.ct.us
cc.dc.us
cc.de.us
cc.fl.us
cc.ga.us
cc.gu.us
cc.hi.us
cc.ia.us
cc.id.us
cc.il.us
cc.in.us
cc.ks.us
cc.ky.us
cc.la.us
cc.ma.us
cc.md.us
cc.me.us
cc.mi.us
cc.mn.us
cc.mo.us
cc.ms.us
cc.mt.us
cc.nc.us
cc.nd.us
cc.ne.us
cc.nh.us
cc.nj.us
cc.nm.us
cc.nv.us
cc.ny.us
cc.oh.us
cc.ok.us
cc.or.us
cc.pa.us
cc.pr.us
cc.ri.us
cc.sc.us
cc.sd.us
cc.tn.us
cc.tx.us
cc.ut.us
cc.vi.us
cc.vt.us
cc.va.us
cc.wa.us
cc.wi.us
cc.wv.us
cc.wy.us
lib.ak.us
lib.al.us
lib.ar.us
lib.as.us
lib.az.us
lib.ca.us
lib.co.us
lib.ct.us
lib.dc.us
// lib.de.us  Issue #243 - Moved to Private section at request of Ed Moore <Ed.Moore@lib.de.us>
lib.fl.us
lib.ga.us
lib.gu.us
lib.hi.us
lib.ia.us
lib.id.us
lib.il.us
lib.in.us
lib.ks.us
lib.ky.us
lib.la.us
lib.ma.us
lib.md.us
lib.me.us
lib.mi.us
lib.mn.us
lib.mo.us
lib.ms.us
lib.mt.us
lib.nc.us
lib.nd.us
lib.ne.us
lib.nh.us
lib.nj.us
lib.nm.us
lib.nv.us
lib.ny.us
lib.oh.us
lib.ok.us
lib.or.us
lib.pa.us
lib.pr.us
lib.ri.us
lib.sc.us
lib.sd.us
lib.tn.us
lib.tx.us
lib.ut.us
lib.vi.us
lib.vt.us
lib.va.us
lib.wa.us
lib.wi.us
// lib.wv.us  Bug 941670 - Removed at request of Larry W Arnold <arnold@wvlc.lib.wv.us>
lib.wy.us
// k12.ma.us contains school districts in Massachusetts. The 4LDs are
//  managed independently except for private (PVT), charter (CHTR) and
//  parochial (PAROCH) schools.  Those are delegated directly to the
//  5LD operators.   <k12-ma-hostmaster _ at _ rsuc.gweep.net>
pvt.k12.ma.us
chtr.k12.ma.us
paroch.k12.ma.us
// Merit Network, Inc. maintains the registry for =~ /(k12|cc|lib).mi.us/ and the following
//    see also: http://domreg.merit.edu
//    see also: whois -h whois.domreg.merit.edu help
ann-arbor.mi.us
cog.mi.us
dst.mi.us
eaton.mi.us
gen.mi.us
mus.mi.us
tec.mi.us
washtenaw.mi.us

// uy : http://www.nic.org.uy/
uy
com.uy
edu.uy
gub.uy
mil.uy
net.uy
org.uy

// uz : http://www.reg.uz/
uz
co.uz
com.uz
net.uz
org.uz

// va : https://en.wikipedia.org/wiki/.va
va

// vc : https://en.wikipedia.org/wiki/.vc
// Submitted by registry <kshah@ca.afilias.info>
vc
com.vc
net.vc
org.vc
gov.vc
mil.vc
edu.vc

// ve : https://registro.nic.ve/
// Submitted by registry nic@nic.ve and nicve@conatel.gob.ve
ve
arts.ve
bib.ve
co.ve
com.ve
e12.ve
edu.ve
firm.ve
gob.ve
gov.ve
info.ve
int.ve
mil.ve
net.ve
nom.ve
org.ve
rar.ve
rec.ve
store.ve
tec.ve
web.ve

// vg : https://en.wikipedia.org/wiki/.vg
vg

// vi : http://www.nic.vi/newdomainform.htm
// http://www.nic.vi/Domain_Rules/body_domain_rules.html indicates some other
// TLDs are "reserved", such as edu.vi and gov.vi, but doesn't actually say they
// are available for registration (which they do not seem to be).
vi
co.vi
com.vi
k12.vi
net.vi
org.vi

// vn : https://www.dot.vn/vnnic/vnnic/domainregistration.jsp
vn
com.vn
net.vn
org.vn
edu.vn
gov.vn
int.vn
ac.vn
biz.vn
info.vn
name.vn
pro.vn
health.vn

// vu : https://en.wikipedia.org/wiki/.vu
// http://www.vunic.vu/
vu
com.vu
edu.vu
net.vu
org.vu

// wf : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
wf

// ws : https://en.wikipedia.org/wiki/.ws
// http://samoanic.ws/index.dhtml
ws
com.ws
net.ws
org.ws
gov.ws
edu.ws

// yt : http://www.afnic.fr/medias/documents/AFNIC-naming-policy2012.pdf
yt

// IDN ccTLDs
// When submitting patches, please maintain a sort by ISO 3166 ccTLD, then
// U-label, and follow this format:
// // A-Label ("<Latin renderings>", <language name>[, variant info]) : <ISO 3166 ccTLD>
// // [sponsoring org]
// U-Label

// xn--mgbaam7a8h ("Emerat", Arabic) : AE
// http://nic.ae/english/arabicdomain/rules.jsp
Ø§Ù…Ø§Ø±Ø§Øª

// xn--y9a3aq ("hye", Armenian) : AM
// ISOC AM (operated by .am Registry)
Õ°Õ¡Õµ

// xn--54b7fta0cc ("Bangla", Bangla) : BD
à¦¬à¦¾à¦‚à¦²à¦¾

// xn--90ae ("bg", Bulgarian) : BG
Ð±Ð³

// xn--mgbcpq6gpa1a ("albahrain", Arabic) : BH
Ø§Ù„Ø¨Ø­Ø±ÙŠÙ†

// xn--90ais ("bel", Belarusian/Russian Cyrillic) : BY
// Operated by .by registry
Ð±ÐµÐ»

// xn--fiqs8s ("Zhongguo/China", Chinese, Simplified) : CN
// CNNIC
// http://cnnic.cn/html/Dir/2005/10/11/3218.htm
ä¸­å›½

// xn--fiqz9s ("Zhongguo/China", Chinese, Traditional) : CN
// CNNIC
// http://cnnic.cn/html/Dir/2005/10/11/3218.htm
ä¸­åœ‹

// xn--lgbbat1ad8j ("Algeria/Al Jazair", Arabic) : DZ
Ø§Ù„Ø¬Ø²Ø§Ø¦Ø±

// xn--wgbh1c ("Egypt/Masr", Arabic) : EG
// http://www.dotmasr.eg/
Ù…ØµØ±

// xn--e1a4c ("eu", Cyrillic) : EU
// https://eurid.eu
ÐµÑŽ

// xn--qxa6a ("eu", Greek) : EU
// https://eurid.eu
ÎµÏ…

// xn--mgbah1a3hjkrd ("Mauritania", Arabic) : MR
Ù…ÙˆØ±ÙŠØªØ§Ù†ÙŠØ§

// xn--node ("ge", Georgian Mkhedruli) : GE
áƒ’áƒ”

// xn--qxam ("el", Greek) : GR
// Hellenic Ministry of Infrastructure, Transport, and Networks
ÎµÎ»

// xn--j6w193g ("Hong Kong", Chinese) : HK
// https://www.hkirc.hk
// Submitted by registry <hk.tech@hkirc.hk>
// https://www.hkirc.hk/content.jsp?id=30#!/34
é¦™æ¸¯
å…¬å�¸.é¦™æ¸¯
æ•™è‚².é¦™æ¸¯
æ”¿åºœ.é¦™æ¸¯
å€‹äºº.é¦™æ¸¯
ç¶²çµ¡.é¦™æ¸¯
çµ„ç¹”.é¦™æ¸¯

// xn--2scrj9c ("Bharat", Kannada) : IN
// India
à²­à²¾à²°à²¤

// xn--3hcrj9c ("Bharat", Oriya) : IN
// India
à¬­à¬¾à¬°à¬¤

// xn--45br5cyl ("Bharatam", Assamese) : IN
// India
à¦­à¦¾à§°à¦¤

// xn--h2breg3eve ("Bharatam", Sanskrit) : IN
// India
à¤­à¤¾à¤°à¤¤à¤®à¥�

// xn--h2brj9c8c ("Bharot", Santali) : IN
// India
à¤­à¤¾à¤°à¥‹à¤¤

// xn--mgbgu82a ("Bharat", Sindhi) : IN
// India
Ú€Ø§Ø±Øª

// xn--rvc1e0am3e ("Bharatam", Malayalam) : IN
// India
à´­à´¾à´°à´¤à´‚

// xn--h2brj9c ("Bharat", Devanagari) : IN
// India
à¤­à¤¾à¤°à¤¤

// xn--mgbbh1a ("Bharat", Kashmiri) : IN
// India
Ø¨Ø§Ø±Øª

// xn--mgbbh1a71e ("Bharat", Arabic) : IN
// India
Ø¨Ú¾Ø§Ø±Øª

// xn--fpcrj9c3d ("Bharat", Telugu) : IN
// India
à°­à°¾à°°à°¤à±�

// xn--gecrj9c ("Bharat", Gujarati) : IN
// India
àª­àª¾àª°àª¤

// xn--s9brj9c ("Bharat", Gurmukhi) : IN
// India
à¨­à¨¾à¨°à¨¤

// xn--45brj9c ("Bharat", Bengali) : IN
// India
à¦­à¦¾à¦°à¦¤

// xn--xkc2dl3a5ee0h ("India", Tamil) : IN
// India
à®‡à®¨à¯�à®¤à®¿à®¯à®¾

// xn--mgba3a4f16a ("Iran", Persian) : IR
Ø§ÛŒØ±Ø§Ù†

// xn--mgba3a4fra ("Iran", Arabic) : IR
Ø§ÙŠØ±Ø§Ù†

// xn--mgbtx2b ("Iraq", Arabic) : IQ
// Communications and Media Commission
Ø¹Ø±Ø§Ù‚

// xn--mgbayh7gpa ("al-Ordon", Arabic) : JO
// National Information Technology Center (NITC)
// Royal Scientific Society, Al-Jubeiha
Ø§Ù„Ø§Ø±Ø¯Ù†

// xn--3e0b707e ("Republic of Korea", Hangul) : KR
í•œêµ­

// xn--80ao21a ("Kaz", Kazakh) : KZ
Ò›Ð°Ð·

// xn--q7ce6a ("Lao", Lao) : LA
àº¥àº²àº§

// xn--fzc2c9e2c ("Lanka", Sinhalese-Sinhala) : LK
// https://nic.lk
à¶½à¶‚à¶šà·�

// xn--xkc2al3hye2a ("Ilangai", Tamil) : LK
// https://nic.lk
à®‡à®²à®™à¯�à®•à¯ˆ

// xn--mgbc0a9azcg ("Morocco/al-Maghrib", Arabic) : MA
Ø§Ù„Ù…ØºØ±Ø¨

// xn--d1alf ("mkd", Macedonian) : MK
// MARnet
Ð¼ÐºÐ´

// xn--l1acc ("mon", Mongolian) : MN
Ð¼Ð¾Ð½

// xn--mix891f ("Macao", Chinese, Traditional) : MO
// MONIC / HNET Asia (Registry Operator for .mo)
æ¾³é–€

// xn--mix082f ("Macao", Chinese, Simplified) : MO
æ¾³é—¨

// xn--mgbx4cd0ab ("Malaysia", Malay) : MY
Ù…Ù„ÙŠØ³ÙŠØ§

// xn--mgb9awbf ("Oman", Arabic) : OM
Ø¹Ù…Ø§Ù†

// xn--mgbai9azgqp6j ("Pakistan", Urdu/Arabic) : PK
Ù¾Ø§Ú©Ø³ØªØ§Ù†

// xn--mgbai9a5eva00b ("Pakistan", Urdu/Arabic, variant) : PK
Ù¾Ø§ÙƒØ³ØªØ§Ù†

// xn--ygbi2ammx ("Falasteen", Arabic) : PS
// The Palestinian National Internet Naming Authority (PNINA)
// http://www.pnina.ps
Ù�Ù„Ø³Ø·ÙŠÙ†

// xn--90a3ac ("srb", Cyrillic) : RS
// https://www.rnids.rs/en/domains/national-domains
Ñ�Ñ€Ð±
Ð¿Ñ€.Ñ�Ñ€Ð±
Ð¾Ñ€Ð³.Ñ�Ñ€Ð±
Ð¾Ð±Ñ€.Ñ�Ñ€Ð±
Ð¾Ð´.Ñ�Ñ€Ð±
ÑƒÐ¿Ñ€.Ñ�Ñ€Ð±
Ð°Ðº.Ñ�Ñ€Ð±

// xn--p1ai ("rf", Russian-Cyrillic) : RU
// https://cctld.ru/files/pdf/docs/en/rules_ru-rf.pdf
// Submitted by George Georgievsky <gug@cctld.ru>
Ñ€Ñ„

// xn--wgbl6a ("Qatar", Arabic) : QA
// http://www.ict.gov.qa/
Ù‚Ø·Ø±

// xn--mgberp4a5d4ar ("AlSaudiah", Arabic) : SA
// http://www.nic.net.sa/
Ø§Ù„Ø³Ø¹ÙˆØ¯ÙŠØ©

// xn--mgberp4a5d4a87g ("AlSaudiah", Arabic, variant)  : SA
Ø§Ù„Ø³Ø¹ÙˆØ¯ÛŒØ©

// xn--mgbqly7c0a67fbc ("AlSaudiah", Arabic, variant) : SA
Ø§Ù„Ø³Ø¹ÙˆØ¯ÛŒÛƒ

// xn--mgbqly7cvafr ("AlSaudiah", Arabic, variant) : SA
Ø§Ù„Ø³Ø¹ÙˆØ¯ÙŠÙ‡

// xn--mgbpl2fh ("sudan", Arabic) : SD
// Operated by .sd registry
Ø³ÙˆØ¯Ø§Ù†

// xn--yfro4i67o Singapore ("Singapore", Chinese) : SG
æ–°åŠ å�¡

// xn--clchc0ea0b2g2a9gcd ("Singapore", Tamil) : SG
à®šà®¿à®™à¯�à®•à®ªà¯�à®ªà¯‚à®°à¯�

// xn--ogbpf8fl ("Syria", Arabic) : SY
Ø³ÙˆØ±ÙŠØ©

// xn--mgbtf8fl ("Syria", Arabic, variant) : SY
Ø³ÙˆØ±ÙŠØ§

// xn--o3cw4h ("Thai", Thai) : TH
// http://www.thnic.co.th
à¹„à¸—à¸¢
à¸¨à¸¶à¸�à¸©à¸².à¹„à¸—à¸¢
à¸˜à¸¸à¸£à¸�à¸´à¸ˆ.à¹„à¸—à¸¢
à¸£à¸±à¸�à¸šà¸²à¸¥.à¹„à¸—à¸¢
à¸—à¸«à¸²à¸£.à¹„à¸—à¸¢
à¹€à¸™à¹‡à¸•.à¹„à¸—à¸¢
à¸­à¸‡à¸„à¹Œà¸�à¸£.à¹„à¸—à¸¢

// xn--pgbs0dh ("Tunisia", Arabic) : TN
// http://nic.tn
ØªÙˆÙ†Ø³

// xn--kpry57d ("Taiwan", Chinese, Traditional) : TW
// http://www.twnic.net/english/dn/dn_07a.htm
å�°ç�£

// xn--kprw13d ("Taiwan", Chinese, Simplified) : TW
// http://www.twnic.net/english/dn/dn_07a.htm
å�°æ¹¾

// xn--nnx388a ("Taiwan", Chinese, variant) : TW
è‡ºç�£

// xn--j1amh ("ukr", Cyrillic) : UA
ÑƒÐºÑ€

// xn--mgb2ddes ("AlYemen", Arabic) : YE
Ø§Ù„ÙŠÙ…Ù†

// xxx : http://icmregistry.com
xxx

// ye : http://www.y.net.ye/services/domain_name.htm
ye
com.ye
edu.ye
gov.ye
net.ye
mil.ye
org.ye

// za : https://www.zadna.org.za/content/page/domain-information/
ac.za
agric.za
alt.za
co.za
edu.za
gov.za
grondar.za
law.za
mil.za
net.za
ngo.za
nic.za
nis.za
nom.za
org.za
school.za
tm.za
web.za

// zm : https://zicta.zm/
// Submitted by registry <info@zicta.zm>
zm
ac.zm
biz.zm
co.zm
com.zm
edu.zm
gov.zm
info.zm
mil.zm
net.zm
org.zm
sch.zm

// zw : https://www.potraz.gov.zw/
// Confirmed by registry <bmtengwa@potraz.gov.zw> 2017-01-25
zw
ac.zw
co.zw
gov.zw
mil.zw
org.zw


// newGTLDs

// List of new gTLDs imported from https://www.icann.org/resources/registries/gtlds/v2/gtlds.json on 2021-10-08T15:12:46Z
// This list is auto-generated, don't edit it manually.
// aaa : 2015-02-26 American Automobile Association, Inc.
aaa

// aarp : 2015-05-21 AARP
aarp

// abarth : 2015-07-30 Fiat Chrysler Automobiles N.V.
abarth

// abb : 2014-10-24 ABB Ltd
abb

// abbott : 2014-07-24 Abbott Laboratories, Inc.
abbott

// abbvie : 2015-07-30 AbbVie Inc.
abbvie

// abc : 2015-07-30 Disney Enterprises, Inc.
abc

// able : 2015-06-25 Able Inc.
able

// abogado : 2014-04-24 Registry Services, LLC
abogado

// abudhabi : 2015-07-30 Abu Dhabi Systems and Information Centre
abudhabi

// academy : 2013-11-07 Binky Moon, LLC
academy

// accenture : 2014-08-15 Accenture plc
accenture

// accountant : 2014-11-20 dot Accountant Limited
accountant

// accountants : 2014-03-20 Binky Moon, LLC
accountants

// aco : 2015-01-08 ACO Severin Ahlmann GmbH & Co. KG
aco

// actor : 2013-12-12 Dog Beach, LLC
actor

// adac : 2015-07-16 Allgemeiner Deutscher Automobil-Club e.V. (ADAC)
adac

// ads : 2014-12-04 Charleston Road Registry Inc.
ads

// adult : 2014-10-16 ICM Registry AD LLC
adult

// aeg : 2015-03-19 Aktiebolaget Electrolux
aeg

// aetna : 2015-05-21 Aetna Life Insurance Company
aetna

// afamilycompany : 2015-07-23 Johnson Shareholdings, Inc.
afamilycompany

// afl : 2014-10-02 Australian Football League
afl

// africa : 2014-03-24 ZA Central Registry NPC trading as Registry.Africa
africa

// agakhan : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
agakhan

// agency : 2013-11-14 Binky Moon, LLC
agency

// aig : 2014-12-18 American International Group, Inc.
aig

// airbus : 2015-07-30 Airbus S.A.S.
airbus

// airforce : 2014-03-06 Dog Beach, LLC
airforce

// airtel : 2014-10-24 Bharti Airtel Limited
airtel

// akdn : 2015-04-23 Fondation Aga Khan (Aga Khan Foundation)
akdn

// alfaromeo : 2015-07-31 Fiat Chrysler Automobiles N.V.
alfaromeo

// alibaba : 2015-01-15 Alibaba Group Holding Limited
alibaba

// alipay : 2015-01-15 Alibaba Group Holding Limited
alipay

// allfinanz : 2014-07-03 Allfinanz Deutsche VermÃ¶gensberatung Aktiengesellschaft
allfinanz

// allstate : 2015-07-31 Allstate Fire and Casualty Insurance Company
allstate

// ally : 2015-06-18 Ally Financial Inc.
ally

// alsace : 2014-07-02 Region Grand Est
alsace

// alstom : 2015-07-30 ALSTOM
alstom

// amazon : 2019-12-19 Amazon Registry Services, Inc.
amazon

// americanexpress : 2015-07-31 American Express Travel Related Services Company, Inc.
americanexpress

// americanfamily : 2015-07-23 AmFam, Inc.
americanfamily

// amex : 2015-07-31 American Express Travel Related Services Company, Inc.
amex

// amfam : 2015-07-23 AmFam, Inc.
amfam

// amica : 2015-05-28 Amica Mutual Insurance Company
amica

// amsterdam : 2014-07-24 Gemeente Amsterdam
amsterdam

// analytics : 2014-12-18 Campus IP LLC
analytics

// android : 2014-08-07 Charleston Road Registry Inc.
android

// anquan : 2015-01-08 Beijing Qihu Keji Co., Ltd.
anquan

// anz : 2015-07-31 Australia and New Zealand Banking Group Limited
anz

// aol : 2015-09-17 Oath Inc.
aol

// apartments : 2014-12-11 Binky Moon, LLC
apartments

// app : 2015-05-14 Charleston Road Registry Inc.
app

// apple : 2015-05-14 Apple Inc.
apple

// aquarelle : 2014-07-24 Aquarelle.com
aquarelle

// arab : 2015-11-12 League of Arab States
arab

// aramco : 2014-11-20 Aramco Services Company
aramco

// archi : 2014-02-06 Afilias Limited
archi

// army : 2014-03-06 Dog Beach, LLC
army

// art : 2016-03-24 UK Creative Ideas Limited
art

// arte : 2014-12-11 Association Relative Ã  la TÃ©lÃ©vision EuropÃ©enne G.E.I.E.
arte

// asda : 2015-07-31 Wal-Mart Stores, Inc.
asda

// associates : 2014-03-06 Binky Moon, LLC
associates

// athleta : 2015-07-30 The Gap, Inc.
athleta

// attorney : 2014-03-20 Dog Beach, LLC
attorney

// auction : 2014-03-20 Dog Beach, LLC
auction

// audi : 2015-05-21 AUDI Aktiengesellschaft
audi

// audible : 2015-06-25 Amazon Registry Services, Inc.
audible

// audio : 2014-03-20 UNR Corp.
audio

// auspost : 2015-08-13 Australian Postal Corporation
auspost

// author : 2014-12-18 Amazon Registry Services, Inc.
author

// auto : 2014-11-13 XYZ.COM LLC
auto

// autos : 2014-01-09 XYZ.COM LLC
autos

// avianca : 2015-01-08 Avianca Holdings S.A.
avianca

// aws : 2015-06-25 AWS Registry LLC
aws

// axa : 2013-12-19 AXA Group Operations SAS
axa

// azure : 2014-12-18 Microsoft Corporation
azure

// baby : 2015-04-09 XYZ.COM LLC
baby

// baidu : 2015-01-08 Baidu, Inc.
baidu

// banamex : 2015-07-30 Citigroup Inc.
banamex

// bananarepublic : 2015-07-31 The Gap, Inc.
bananarepublic

// band : 2014-06-12 Dog Beach, LLC
band

// bank : 2014-09-25 fTLD Registry Services LLC
bank

// bar : 2013-12-12 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
bar

// barcelona : 2014-07-24 Municipi de Barcelona
barcelona

// barclaycard : 2014-11-20 Barclays Bank PLC
barclaycard

// barclays : 2014-11-20 Barclays Bank PLC
barclays

// barefoot : 2015-06-11 Gallo Vineyards, Inc.
barefoot

// bargains : 2013-11-14 Binky Moon, LLC
bargains

// baseball : 2015-10-29 MLB Advanced Media DH, LLC
baseball

// basketball : 2015-08-20 FÃ©dÃ©ration Internationale de Basketball (FIBA)
basketball

// bauhaus : 2014-04-17 Werkhaus GmbH
bauhaus

// bayern : 2014-01-23 Bayern Connect GmbH
bayern

// bbc : 2014-12-18 British Broadcasting Corporation
bbc

// bbt : 2015-07-23 BB&T Corporation
bbt

// bbva : 2014-10-02 BANCO BILBAO VIZCAYA ARGENTARIA, S.A.
bbva

// bcg : 2015-04-02 The Boston Consulting Group, Inc.
bcg

// bcn : 2014-07-24 Municipi de Barcelona
bcn

// beats : 2015-05-14 Beats Electronics, LLC
beats

// beauty : 2015-12-03 XYZ.COM LLC
beauty

// beer : 2014-01-09 Registry Services, LLC
beer

// bentley : 2014-12-18 Bentley Motors Limited
bentley

// berlin : 2013-10-31 dotBERLIN GmbH & Co. KG
berlin

// best : 2013-12-19 BestTLD Pty Ltd
best

// bestbuy : 2015-07-31 BBY Solutions, Inc.
bestbuy

// bet : 2015-05-07 Afilias Limited
bet

// bharti : 2014-01-09 Bharti Enterprises (Holding) Private Limited
bharti

// bible : 2014-06-19 American Bible Society
bible

// bid : 2013-12-19 dot Bid Limited
bid

// bike : 2013-08-27 Binky Moon, LLC
bike

// bing : 2014-12-18 Microsoft Corporation
bing

// bingo : 2014-12-04 Binky Moon, LLC
bingo

// bio : 2014-03-06 Afilias Limited
bio

// black : 2014-01-16 Afilias Limited
black

// blackfriday : 2014-01-16 UNR Corp.
blackfriday

// blockbuster : 2015-07-30 Dish DBS Corporation
blockbuster

// blog : 2015-05-14 Knock Knock WHOIS There, LLC
blog

// bloomberg : 2014-07-17 Bloomberg IP Holdings LLC
bloomberg

// blue : 2013-11-07 Afilias Limited
blue

// bms : 2014-10-30 Bristol-Myers Squibb Company
bms

// bmw : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
bmw

// bnpparibas : 2014-05-29 BNP Paribas
bnpparibas

// boats : 2014-12-04 XYZ.COM LLC
boats

// boehringer : 2015-07-09 Boehringer Ingelheim International GmbH
boehringer

// bofa : 2015-07-31 Bank of America Corporation
bofa

// bom : 2014-10-16 NÃºcleo de InformaÃ§Ã£o e CoordenaÃ§Ã£o do Ponto BR - NIC.br
bom

// bond : 2014-06-05 ShortDot SA
bond

// boo : 2014-01-30 Charleston Road Registry Inc.
boo

// book : 2015-08-27 Amazon Registry Services, Inc.
book

// booking : 2015-07-16 Booking.com B.V.
booking

// bosch : 2015-06-18 Robert Bosch GMBH
bosch

// bostik : 2015-05-28 Bostik SA
bostik

// boston : 2015-12-10 Boston TLD Management, LLC
boston

// bot : 2014-12-18 Amazon Registry Services, Inc.
bot

// boutique : 2013-11-14 Binky Moon, LLC
boutique

// box : 2015-11-12 Intercap Registry Inc.
box

// bradesco : 2014-12-18 Banco Bradesco S.A.
bradesco

// bridgestone : 2014-12-18 Bridgestone Corporation
bridgestone

// broadway : 2014-12-22 Celebrate Broadway, Inc.
broadway

// broker : 2014-12-11 Dog Beach, LLC
broker

// brother : 2015-01-29 Brother Industries, Ltd.
brother

// brussels : 2014-02-06 DNS.be vzw
brussels

// budapest : 2013-11-21 Minds + Machines Group Limited
budapest

// bugatti : 2015-07-23 Bugatti International SA
bugatti

// build : 2013-11-07 Plan Bee LLC
build

// builders : 2013-11-07 Binky Moon, LLC
builders

// business : 2013-11-07 Binky Moon, LLC
business

// buy : 2014-12-18 Amazon Registry Services, Inc.
buy

// buzz : 2013-10-02 DOTSTRATEGY CO.
buzz

// bzh : 2014-02-27 Association www.bzh
bzh

// cab : 2013-10-24 Binky Moon, LLC
cab

// cafe : 2015-02-11 Binky Moon, LLC
cafe

// cal : 2014-07-24 Charleston Road Registry Inc.
cal

// call : 2014-12-18 Amazon Registry Services, Inc.
call

// calvinklein : 2015-07-30 PVH gTLD Holdings LLC
calvinklein

// cam : 2016-04-21 AC Webconnecting Holding B.V.
cam

// camera : 2013-08-27 Binky Moon, LLC
camera

// camp : 2013-11-07 Binky Moon, LLC
camp

// cancerresearch : 2014-05-15 Australian Cancer Research Foundation
cancerresearch

// canon : 2014-09-12 Canon Inc.
canon

// capetown : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
capetown

// capital : 2014-03-06 Binky Moon, LLC
capital

// capitalone : 2015-08-06 Capital One Financial Corporation
capitalone

// car : 2015-01-22 XYZ.COM LLC
car

// caravan : 2013-12-12 Caravan International, Inc.
caravan

// cards : 2013-12-05 Binky Moon, LLC
cards

// care : 2014-03-06 Binky Moon, LLC
care

// career : 2013-10-09 dotCareer LLC
career

// careers : 2013-10-02 Binky Moon, LLC
careers

// cars : 2014-11-13 XYZ.COM LLC
cars

// casa : 2013-11-21 Registry Services, LLC
casa

// case : 2015-09-03 CNH Industrial N.V.
case

// cash : 2014-03-06 Binky Moon, LLC
cash

// casino : 2014-12-18 Binky Moon, LLC
casino

// catering : 2013-12-05 Binky Moon, LLC
catering

// catholic : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
catholic

// cba : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
cba

// cbn : 2014-08-22 The Christian Broadcasting Network, Inc.
cbn

// cbre : 2015-07-02 CBRE, Inc.
cbre

// cbs : 2015-08-06 CBS Domains Inc.
cbs

// center : 2013-11-07 Binky Moon, LLC
center

// ceo : 2013-11-07 CEOTLD Pty Ltd
ceo

// cern : 2014-06-05 European Organization for Nuclear Research ("CERN")
cern

// cfa : 2014-08-28 CFA Institute
cfa

// cfd : 2014-12-11 ShortDot SA
cfd

// chanel : 2015-04-09 Chanel International B.V.
chanel

// channel : 2014-05-08 Charleston Road Registry Inc.
channel

// charity : 2018-04-11 Binky Moon, LLC
charity

// chase : 2015-04-30 JPMorgan Chase Bank, National Association
chase

// chat : 2014-12-04 Binky Moon, LLC
chat

// cheap : 2013-11-14 Binky Moon, LLC
cheap

// chintai : 2015-06-11 CHINTAI Corporation
chintai

// christmas : 2013-11-21 UNR Corp.
christmas

// chrome : 2014-07-24 Charleston Road Registry Inc.
chrome

// church : 2014-02-06 Binky Moon, LLC
church

// cipriani : 2015-02-19 Hotel Cipriani Srl
cipriani

// circle : 2014-12-18 Amazon Registry Services, Inc.
circle

// cisco : 2014-12-22 Cisco Technology, Inc.
cisco

// citadel : 2015-07-23 Citadel Domain LLC
citadel

// citi : 2015-07-30 Citigroup Inc.
citi

// citic : 2014-01-09 CITIC Group Corporation
citic

// city : 2014-05-29 Binky Moon, LLC
city

// cityeats : 2014-12-11 Lifestyle Domain Holdings, Inc.
cityeats

// claims : 2014-03-20 Binky Moon, LLC
claims

// cleaning : 2013-12-05 Binky Moon, LLC
cleaning

// click : 2014-06-05 UNR Corp.
click

// clinic : 2014-03-20 Binky Moon, LLC
clinic

// clinique : 2015-10-01 The EstÃ©e Lauder Companies Inc.
clinique

// clothing : 2013-08-27 Binky Moon, LLC
clothing

// cloud : 2015-04-16 Aruba PEC S.p.A.
cloud

// club : 2013-11-08 Registry Services, LLC
club

// clubmed : 2015-06-25 Club MÃ©diterranÃ©e S.A.
clubmed

// coach : 2014-10-09 Binky Moon, LLC
coach

// codes : 2013-10-31 Binky Moon, LLC
codes

// coffee : 2013-10-17 Binky Moon, LLC
coffee

// college : 2014-01-16 XYZ.COM LLC
college

// cologne : 2014-02-05 dotKoeln GmbH
cologne

// comcast : 2015-07-23 Comcast IP Holdings I, LLC
comcast

// commbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
commbank

// community : 2013-12-05 Binky Moon, LLC
community

// company : 2013-11-07 Binky Moon, LLC
company

// compare : 2015-10-08 Registry Services, LLC
compare

// computer : 2013-10-24 Binky Moon, LLC
computer

// comsec : 2015-01-08 VeriSign, Inc.
comsec

// condos : 2013-12-05 Binky Moon, LLC
condos

// construction : 2013-09-16 Binky Moon, LLC
construction

// consulting : 2013-12-05 Dog Beach, LLC
consulting

// contact : 2015-01-08 Dog Beach, LLC
contact

// contractors : 2013-09-10 Binky Moon, LLC
contractors

// cooking : 2013-11-21 Registry Services, LLC
cooking

// cookingchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
cookingchannel

// cool : 2013-11-14 Binky Moon, LLC
cool

// corsica : 2014-09-25 CollectivitÃ© de Corse
corsica

// country : 2013-12-19 DotCountry LLC
country

// coupon : 2015-02-26 Amazon Registry Services, Inc.
coupon

// coupons : 2015-03-26 Binky Moon, LLC
coupons

// courses : 2014-12-04 OPEN UNIVERSITIES AUSTRALIA PTY LTD
courses

// cpa : 2019-06-10 American Institute of Certified Public Accountants
cpa

// credit : 2014-03-20 Binky Moon, LLC
credit

// creditcard : 2014-03-20 Binky Moon, LLC
creditcard

// creditunion : 2015-01-22 DotCooperation LLC
creditunion

// cricket : 2014-10-09 dot Cricket Limited
cricket

// crown : 2014-10-24 Crown Equipment Corporation
crown

// crs : 2014-04-03 Federated Co-operatives Limited
crs

// cruise : 2015-12-10 Viking River Cruises (Bermuda) Ltd.
cruise

// cruises : 2013-12-05 Binky Moon, LLC
cruises

// csc : 2014-09-25 Alliance-One Services, Inc.
csc

// cuisinella : 2014-04-03 SCHMIDT GROUPE S.A.S.
cuisinella

// cymru : 2014-05-08 Nominet UK
cymru

// cyou : 2015-01-22 ShortDot SA
cyou

// dabur : 2014-02-06 Dabur India Limited
dabur

// dad : 2014-01-23 Charleston Road Registry Inc.
dad

// dance : 2013-10-24 Dog Beach, LLC
dance

// data : 2016-06-02 Dish DBS Corporation
data

// date : 2014-11-20 dot Date Limited
date

// dating : 2013-12-05 Binky Moon, LLC
dating

// datsun : 2014-03-27 NISSAN MOTOR CO., LTD.
datsun

// day : 2014-01-30 Charleston Road Registry Inc.
day

// dclk : 2014-11-20 Charleston Road Registry Inc.
dclk

// dds : 2015-05-07 Registry Services, LLC
dds

// deal : 2015-06-25 Amazon Registry Services, Inc.
deal

// dealer : 2014-12-22 Intercap Registry Inc.
dealer

// deals : 2014-05-22 Binky Moon, LLC
deals

// degree : 2014-03-06 Dog Beach, LLC
degree

// delivery : 2014-09-11 Binky Moon, LLC
delivery

// dell : 2014-10-24 Dell Inc.
dell

// deloitte : 2015-07-31 Deloitte Touche Tohmatsu
deloitte

// delta : 2015-02-19 Delta Air Lines, Inc.
delta

// democrat : 2013-10-24 Dog Beach, LLC
democrat

// dental : 2014-03-20 Binky Moon, LLC
dental

// dentist : 2014-03-20 Dog Beach, LLC
dentist

// desi : 2013-11-14 Desi Networks LLC
desi

// design : 2014-11-07 Registry Services, LLC
design

// dev : 2014-10-16 Charleston Road Registry Inc.
dev

// dhl : 2015-07-23 Deutsche Post AG
dhl

// diamonds : 2013-09-22 Binky Moon, LLC
diamonds

// diet : 2014-06-26 UNR Corp.
diet

// digital : 2014-03-06 Binky Moon, LLC
digital

// direct : 2014-04-10 Binky Moon, LLC
direct

// directory : 2013-09-20 Binky Moon, LLC
directory

// discount : 2014-03-06 Binky Moon, LLC
discount

// discover : 2015-07-23 Discover Financial Services
discover

// dish : 2015-07-30 Dish DBS Corporation
dish

// diy : 2015-11-05 Lifestyle Domain Holdings, Inc.
diy

// dnp : 2013-12-13 Dai Nippon Printing Co., Ltd.
dnp

// docs : 2014-10-16 Charleston Road Registry Inc.
docs

// doctor : 2016-06-02 Binky Moon, LLC
doctor

// dog : 2014-12-04 Binky Moon, LLC
dog

// domains : 2013-10-17 Binky Moon, LLC
domains

// dot : 2015-05-21 Dish DBS Corporation
dot

// download : 2014-11-20 dot Support Limited
download

// drive : 2015-03-05 Charleston Road Registry Inc.
drive

// dtv : 2015-06-04 Dish DBS Corporation
dtv

// dubai : 2015-01-01 Dubai Smart Government Department
dubai

// duck : 2015-07-23 Johnson Shareholdings, Inc.
duck

// dunlop : 2015-07-02 The Goodyear Tire & Rubber Company
dunlop

// dupont : 2015-06-25 DuPont Specialty Products USA, LLC
dupont

// durban : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
durban

// dvag : 2014-06-23 Deutsche VermÃ¶gensberatung Aktiengesellschaft DVAG
dvag

// dvr : 2016-05-26 DISH Technologies L.L.C.
dvr

// earth : 2014-12-04 Interlink Co., Ltd.
earth

// eat : 2014-01-23 Charleston Road Registry Inc.
eat

// eco : 2016-07-08 Big Room Inc.
eco

// edeka : 2014-12-18 EDEKA Verband kaufmÃ¤nnischer Genossenschaften e.V.
edeka

// education : 2013-11-07 Binky Moon, LLC
education

// email : 2013-10-31 Binky Moon, LLC
email

// emerck : 2014-04-03 Merck KGaA
emerck

// energy : 2014-09-11 Binky Moon, LLC
energy

// engineer : 2014-03-06 Dog Beach, LLC
engineer

// engineering : 2014-03-06 Binky Moon, LLC
engineering

// enterprises : 2013-09-20 Binky Moon, LLC
enterprises

// epson : 2014-12-04 Seiko Epson Corporation
epson

// equipment : 2013-08-27 Binky Moon, LLC
equipment

// ericsson : 2015-07-09 Telefonaktiebolaget L M Ericsson
ericsson

// erni : 2014-04-03 ERNI Group Holding AG
erni

// esq : 2014-05-08 Charleston Road Registry Inc.
esq

// estate : 2013-08-27 Binky Moon, LLC
estate

// etisalat : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat)
etisalat

// eurovision : 2014-04-24 European Broadcasting Union (EBU)
eurovision

// eus : 2013-12-12 Puntueus Fundazioa
eus

// events : 2013-12-05 Binky Moon, LLC
events

// exchange : 2014-03-06 Binky Moon, LLC
exchange

// expert : 2013-11-21 Binky Moon, LLC
expert

// exposed : 2013-12-05 Binky Moon, LLC
exposed

// express : 2015-02-11 Binky Moon, LLC
express

// extraspace : 2015-05-14 Extra Space Storage LLC
extraspace

// fage : 2014-12-18 Fage International S.A.
fage

// fail : 2014-03-06 Binky Moon, LLC
fail

// fairwinds : 2014-11-13 FairWinds Partners, LLC
fairwinds

// faith : 2014-11-20 dot Faith Limited
faith

// family : 2015-04-02 Dog Beach, LLC
family

// fan : 2014-03-06 Dog Beach, LLC
fan

// fans : 2014-11-07 ZDNS International Limited
fans

// farm : 2013-11-07 Binky Moon, LLC
farm

// farmers : 2015-07-09 Farmers Insurance Exchange
farmers

// fashion : 2014-07-03 Registry Services, LLC
fashion

// fast : 2014-12-18 Amazon Registry Services, Inc.
fast

// fedex : 2015-08-06 Federal Express Corporation
fedex

// feedback : 2013-12-19 Top Level Spectrum, Inc.
feedback

// ferrari : 2015-07-31 Fiat Chrysler Automobiles N.V.
ferrari

// ferrero : 2014-12-18 Ferrero Trading Lux S.A.
ferrero

// fiat : 2015-07-31 Fiat Chrysler Automobiles N.V.
fiat

// fidelity : 2015-07-30 Fidelity Brokerage Services LLC
fidelity

// fido : 2015-08-06 Rogers Communications Canada Inc.
fido

// film : 2015-01-08 Motion Picture Domain Registry Pty Ltd
film

// final : 2014-10-16 NÃºcleo de InformaÃ§Ã£o e CoordenaÃ§Ã£o do Ponto BR - NIC.br
final

// finance : 2014-03-20 Binky Moon, LLC
finance

// financial : 2014-03-06 Binky Moon, LLC
financial

// fire : 2015-06-25 Amazon Registry Services, Inc.
fire

// firestone : 2014-12-18 Bridgestone Licensing Services, Inc
firestone

// firmdale : 2014-03-27 Firmdale Holdings Limited
firmdale

// fish : 2013-12-12 Binky Moon, LLC
fish

// fishing : 2013-11-21 Registry Services, LLC
fishing

// fit : 2014-11-07 Registry Services, LLC
fit

// fitness : 2014-03-06 Binky Moon, LLC
fitness

// flickr : 2015-04-02 Flickr, Inc.
flickr

// flights : 2013-12-05 Binky Moon, LLC
flights

// flir : 2015-07-23 FLIR Systems, Inc.
flir

// florist : 2013-11-07 Binky Moon, LLC
florist

// flowers : 2014-10-09 UNR Corp.
flowers

// fly : 2014-05-08 Charleston Road Registry Inc.
fly

// foo : 2014-01-23 Charleston Road Registry Inc.
foo

// food : 2016-04-21 Lifestyle Domain Holdings, Inc.
food

// foodnetwork : 2015-07-02 Lifestyle Domain Holdings, Inc.
foodnetwork

// football : 2014-12-18 Binky Moon, LLC
football

// ford : 2014-11-13 Ford Motor Company
ford

// forex : 2014-12-11 Dog Beach, LLC
forex

// forsale : 2014-05-22 Dog Beach, LLC
forsale

// forum : 2015-04-02 Fegistry, LLC
forum

// foundation : 2013-12-05 Binky Moon, LLC
foundation

// fox : 2015-09-11 FOX Registry, LLC
fox

// free : 2015-12-10 Amazon Registry Services, Inc.
free

// fresenius : 2015-07-30 Fresenius Immobilien-Verwaltungs-GmbH
fresenius

// frl : 2014-05-15 FRLregistry B.V.
frl

// frogans : 2013-12-19 OP3FT
frogans

// frontdoor : 2015-07-02 Lifestyle Domain Holdings, Inc.
frontdoor

// frontier : 2015-02-05 Frontier Communications Corporation
frontier

// ftr : 2015-07-16 Frontier Communications Corporation
ftr

// fujitsu : 2015-07-30 Fujitsu Limited
fujitsu

// fun : 2016-01-14 Radix FZC
fun

// fund : 2014-03-20 Binky Moon, LLC
fund

// furniture : 2014-03-20 Binky Moon, LLC
furniture

// futbol : 2013-09-20 Dog Beach, LLC
futbol

// fyi : 2015-04-02 Binky Moon, LLC
fyi

// gal : 2013-11-07 AsociaciÃ³n puntoGAL
gal

// gallery : 2013-09-13 Binky Moon, LLC
gallery

// gallo : 2015-06-11 Gallo Vineyards, Inc.
gallo

// gallup : 2015-02-19 Gallup, Inc.
gallup

// game : 2015-05-28 UNR Corp.
game

// games : 2015-05-28 Dog Beach, LLC
games

// gap : 2015-07-31 The Gap, Inc.
gap

// garden : 2014-06-26 Registry Services, LLC
garden

// gay : 2019-05-23 Top Level Design, LLC
gay

// gbiz : 2014-07-17 Charleston Road Registry Inc.
gbiz

// gdn : 2014-07-31 Joint Stock Company "Navigation-information systems"
gdn

// gea : 2014-12-04 GEA Group Aktiengesellschaft
gea

// gent : 2014-01-23 COMBELL NV
gent

// genting : 2015-03-12 Resorts World Inc Pte. Ltd.
genting

// george : 2015-07-31 Wal-Mart Stores, Inc.
george

// ggee : 2014-01-09 GMO Internet, Inc.
ggee

// gift : 2013-10-17 DotGift, LLC
gift

// gifts : 2014-07-03 Binky Moon, LLC
gifts

// gives : 2014-03-06 Dog Beach, LLC
gives

// giving : 2014-11-13 Giving Limited
giving

// glade : 2015-07-23 Johnson Shareholdings, Inc.
glade

// glass : 2013-11-07 Binky Moon, LLC
glass

// gle : 2014-07-24 Charleston Road Registry Inc.
gle

// global : 2014-04-17 Dot Global Domain Registry Limited
global

// globo : 2013-12-19 Globo ComunicaÃ§Ã£o e ParticipaÃ§Ãµes S.A
globo

// gmail : 2014-05-01 Charleston Road Registry Inc.
gmail

// gmbh : 2016-01-29 Binky Moon, LLC
gmbh

// gmo : 2014-01-09 GMO Internet, Inc.
gmo

// gmx : 2014-04-24 1&1 Mail & Media GmbH
gmx

// godaddy : 2015-07-23 Go Daddy East, LLC
godaddy

// gold : 2015-01-22 Binky Moon, LLC
gold

// goldpoint : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
goldpoint

// golf : 2014-12-18 Binky Moon, LLC
golf

// goo : 2014-12-18 NTT Resonant Inc.
goo

// goodyear : 2015-07-02 The Goodyear Tire & Rubber Company
goodyear

// goog : 2014-11-20 Charleston Road Registry Inc.
goog

// google : 2014-07-24 Charleston Road Registry Inc.
google

// gop : 2014-01-16 Republican State Leadership Committee, Inc.
gop

// got : 2014-12-18 Amazon Registry Services, Inc.
got

// grainger : 2015-05-07 Grainger Registry Services, LLC
grainger

// graphics : 2013-09-13 Binky Moon, LLC
graphics

// gratis : 2014-03-20 Binky Moon, LLC
gratis

// green : 2014-05-08 Afilias Limited
green

// gripe : 2014-03-06 Binky Moon, LLC
gripe

// grocery : 2016-06-16 Wal-Mart Stores, Inc.
grocery

// group : 2014-08-15 Binky Moon, LLC
group

// guardian : 2015-07-30 The Guardian Life Insurance Company of America
guardian

// gucci : 2014-11-13 Guccio Gucci S.p.a.
gucci

// guge : 2014-08-28 Charleston Road Registry Inc.
guge

// guide : 2013-09-13 Binky Moon, LLC
guide

// guitars : 2013-11-14 UNR Corp.
guitars

// guru : 2013-08-27 Binky Moon, LLC
guru

// hair : 2015-12-03 XYZ.COM LLC
hair

// hamburg : 2014-02-20 Hamburg Top-Level-Domain GmbH
hamburg

// hangout : 2014-11-13 Charleston Road Registry Inc.
hangout

// haus : 2013-12-05 Dog Beach, LLC
haus

// hbo : 2015-07-30 HBO Registry Services, Inc.
hbo

// hdfc : 2015-07-30 HOUSING DEVELOPMENT FINANCE CORPORATION LIMITED
hdfc

// hdfcbank : 2015-02-12 HDFC Bank Limited
hdfcbank

// health : 2015-02-11 DotHealth, LLC
health

// healthcare : 2014-06-12 Binky Moon, LLC
healthcare

// help : 2014-06-26 UNR Corp.
help

// helsinki : 2015-02-05 City of Helsinki
helsinki

// here : 2014-02-06 Charleston Road Registry Inc.
here

// hermes : 2014-07-10 HERMES INTERNATIONAL
hermes

// hgtv : 2015-07-02 Lifestyle Domain Holdings, Inc.
hgtv

// hiphop : 2014-03-06 UNR Corp.
hiphop

// hisamitsu : 2015-07-16 Hisamitsu Pharmaceutical Co.,Inc.
hisamitsu

// hitachi : 2014-10-31 Hitachi, Ltd.
hitachi

// hiv : 2014-03-13 UNR Corp.
hiv

// hkt : 2015-05-14 PCCW-HKT DataCom Services Limited
hkt

// hockey : 2015-03-19 Binky Moon, LLC
hockey

// holdings : 2013-08-27 Binky Moon, LLC
holdings

// holiday : 2013-11-07 Binky Moon, LLC
holiday

// homedepot : 2015-04-02 Home Depot Product Authority, LLC
homedepot

// homegoods : 2015-07-16 The TJX Companies, Inc.
homegoods

// homes : 2014-01-09 XYZ.COM LLC
homes

// homesense : 2015-07-16 The TJX Companies, Inc.
homesense

// honda : 2014-12-18 Honda Motor Co., Ltd.
honda

// horse : 2013-11-21 Registry Services, LLC
horse

// hospital : 2016-10-20 Binky Moon, LLC
hospital

// host : 2014-04-17 Radix FZC
host

// hosting : 2014-05-29 UNR Corp.
hosting

// hot : 2015-08-27 Amazon Registry Services, Inc.
hot

// hoteles : 2015-03-05 Travel Reservations SRL
hoteles

// hotels : 2016-04-07 Booking.com B.V.
hotels

// hotmail : 2014-12-18 Microsoft Corporation
hotmail

// house : 2013-11-07 Binky Moon, LLC
house

// how : 2014-01-23 Charleston Road Registry Inc.
how

// hsbc : 2014-10-24 HSBC Global Services (UK) Limited
hsbc

// hughes : 2015-07-30 Hughes Satellite Systems Corporation
hughes

// hyatt : 2015-07-30 Hyatt GTLD, L.L.C.
hyatt

// hyundai : 2015-07-09 Hyundai Motor Company
hyundai

// ibm : 2014-07-31 International Business Machines Corporation
ibm

// icbc : 2015-02-19 Industrial and Commercial Bank of China Limited
icbc

// ice : 2014-10-30 IntercontinentalExchange, Inc.
ice

// icu : 2015-01-08 ShortDot SA
icu

// ieee : 2015-07-23 IEEE Global LLC
ieee

// ifm : 2014-01-30 ifm electronic gmbh
ifm

// ikano : 2015-07-09 Ikano S.A.
ikano

// imamat : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation)
imamat

// imdb : 2015-06-25 Amazon Registry Services, Inc.
imdb

// immo : 2014-07-10 Binky Moon, LLC
immo

// immobilien : 2013-11-07 Dog Beach, LLC
immobilien

// inc : 2018-03-10 Intercap Registry Inc.
inc

// industries : 2013-12-05 Binky Moon, LLC
industries

// infiniti : 2014-03-27 NISSAN MOTOR CO., LTD.
infiniti

// ing : 2014-01-23 Charleston Road Registry Inc.
ing

// ink : 2013-12-05 Top Level Design, LLC
ink

// institute : 2013-11-07 Binky Moon, LLC
institute

// insurance : 2015-02-19 fTLD Registry Services LLC
insurance

// insure : 2014-03-20 Binky Moon, LLC
insure

// international : 2013-11-07 Binky Moon, LLC
international

// intuit : 2015-07-30 Intuit Administrative Services, Inc.
intuit

// investments : 2014-03-20 Binky Moon, LLC
investments

// ipiranga : 2014-08-28 Ipiranga Produtos de Petroleo S.A.
ipiranga

// irish : 2014-08-07 Binky Moon, LLC
irish

// ismaili : 2015-08-06 Fondation Aga Khan (Aga Khan Foundation)
ismaili

// ist : 2014-08-28 Istanbul Metropolitan Municipality
ist

// istanbul : 2014-08-28 Istanbul Metropolitan Municipality
istanbul

// itau : 2014-10-02 Itau Unibanco Holding S.A.
itau

// itv : 2015-07-09 ITV Services Limited
itv

// jaguar : 2014-11-13 Jaguar Land Rover Ltd
jaguar

// java : 2014-06-19 Oracle Corporation
java

// jcb : 2014-11-20 JCB Co., Ltd.
jcb

// jeep : 2015-07-30 FCA US LLC.
jeep

// jetzt : 2014-01-09 Binky Moon, LLC
jetzt

// jewelry : 2015-03-05 Binky Moon, LLC
jewelry

// jio : 2015-04-02 Reliance Industries Limited
jio

// jll : 2015-04-02 Jones Lang LaSalle Incorporated
jll

// jmp : 2015-03-26 Matrix IP LLC
jmp

// jnj : 2015-06-18 Johnson & Johnson Services, Inc.
jnj

// joburg : 2014-03-24 ZA Central Registry NPC trading as ZA Central Registry
joburg

// jot : 2014-12-18 Amazon Registry Services, Inc.
jot

// joy : 2014-12-18 Amazon Registry Services, Inc.
joy

// jpmorgan : 2015-04-30 JPMorgan Chase Bank, National Association
jpmorgan

// jprs : 2014-09-18 Japan Registry Services Co., Ltd.
jprs

// juegos : 2014-03-20 UNR Corp.
juegos

// juniper : 2015-07-30 JUNIPER NETWORKS, INC.
juniper

// kaufen : 2013-11-07 Dog Beach, LLC
kaufen

// kddi : 2014-09-12 KDDI CORPORATION
kddi

// kerryhotels : 2015-04-30 Kerry Trading Co. Limited
kerryhotels

// kerrylogistics : 2015-04-09 Kerry Trading Co. Limited
kerrylogistics

// kerryproperties : 2015-04-09 Kerry Trading Co. Limited
kerryproperties

// kfh : 2014-12-04 Kuwait Finance House
kfh

// kia : 2015-07-09 KIA MOTORS CORPORATION
kia

// kids : 2021-08-13 DotKids Foundation Limited
kids

// kim : 2013-09-23 Afilias Limited
kim

// kinder : 2014-11-07 Ferrero Trading Lux S.A.
kinder

// kindle : 2015-06-25 Amazon Registry Services, Inc.
kindle

// kitchen : 2013-09-20 Binky Moon, LLC
kitchen

// kiwi : 2013-09-20 DOT KIWI LIMITED
kiwi

// koeln : 2014-01-09 dotKoeln GmbH
koeln

// komatsu : 2015-01-08 Komatsu Ltd.
komatsu

// kosher : 2015-08-20 Kosher Marketing Assets LLC
kosher

// kpmg : 2015-04-23 KPMG International Cooperative (KPMG International Genossenschaft)
kpmg

// kpn : 2015-01-08 Koninklijke KPN N.V.
kpn

// krd : 2013-12-05 KRG Department of Information Technology
krd

// kred : 2013-12-19 KredTLD Pty Ltd
kred

// kuokgroup : 2015-04-09 Kerry Trading Co. Limited
kuokgroup

// kyoto : 2014-11-07 Academic Institution: Kyoto Jyoho Gakuen
kyoto

// lacaixa : 2014-01-09 FundaciÃ³n Bancaria Caixa dâ€™Estalvis i Pensions de Barcelona, â€œla Caixaâ€�
lacaixa

// lamborghini : 2015-06-04 Automobili Lamborghini S.p.A.
lamborghini

// lamer : 2015-10-01 The EstÃ©e Lauder Companies Inc.
lamer

// lancaster : 2015-02-12 LANCASTER
lancaster

// lancia : 2015-07-31 Fiat Chrysler Automobiles N.V.
lancia

// land : 2013-09-10 Binky Moon, LLC
land

// landrover : 2014-11-13 Jaguar Land Rover Ltd
landrover

// lanxess : 2015-07-30 LANXESS Corporation
lanxess

// lasalle : 2015-04-02 Jones Lang LaSalle Incorporated
lasalle

// lat : 2014-10-16 ECOM-LAC FederaciÃ²n de LatinoamÃ¨rica y el Caribe para Internet y el Comercio ElectrÃ²nico
lat

// latino : 2015-07-30 Dish DBS Corporation
latino

// latrobe : 2014-06-16 La Trobe University
latrobe

// law : 2015-01-22 Registry Services, LLC
law

// lawyer : 2014-03-20 Dog Beach, LLC
lawyer

// lds : 2014-03-20 IRI Domain Management, LLC
lds

// lease : 2014-03-06 Binky Moon, LLC
lease

// leclerc : 2014-08-07 A.C.D. LEC Association des Centres Distributeurs Edouard Leclerc
leclerc

// lefrak : 2015-07-16 LeFrak Organization, Inc.
lefrak

// legal : 2014-10-16 Binky Moon, LLC
legal

// lego : 2015-07-16 LEGO Juris A/S
lego

// lexus : 2015-04-23 TOYOTA MOTOR CORPORATION
lexus

// lgbt : 2014-05-08 Afilias Limited
lgbt

// lidl : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
lidl

// life : 2014-02-06 Binky Moon, LLC
life

// lifeinsurance : 2015-01-15 American Council of Life Insurers
lifeinsurance

// lifestyle : 2014-12-11 Lifestyle Domain Holdings, Inc.
lifestyle

// lighting : 2013-08-27 Binky Moon, LLC
lighting

// like : 2014-12-18 Amazon Registry Services, Inc.
like

// lilly : 2015-07-31 Eli Lilly and Company
lilly

// limited : 2014-03-06 Binky Moon, LLC
limited

// limo : 2013-10-17 Binky Moon, LLC
limo

// lincoln : 2014-11-13 Ford Motor Company
lincoln

// linde : 2014-12-04 Linde Aktiengesellschaft
linde

// link : 2013-11-14 UNR Corp.
link

// lipsy : 2015-06-25 Lipsy Ltd
lipsy

// live : 2014-12-04 Dog Beach, LLC
live

// living : 2015-07-30 Lifestyle Domain Holdings, Inc.
living

// lixil : 2015-03-19 LIXIL Group Corporation
lixil

// llc : 2017-12-14 Afilias Limited
llc

// llp : 2019-08-26 UNR Corp.
llp

// loan : 2014-11-20 dot Loan Limited
loan

// loans : 2014-03-20 Binky Moon, LLC
loans

// locker : 2015-06-04 Dish DBS Corporation
locker

// locus : 2015-06-25 Locus Analytics LLC
locus

// loft : 2015-07-30 Annco, Inc.
loft

// lol : 2015-01-30 UNR Corp.
lol

// london : 2013-11-14 Dot London Domains Limited
london

// lotte : 2014-11-07 Lotte Holdings Co., Ltd.
lotte

// lotto : 2014-04-10 Afilias Limited
lotto

// love : 2014-12-22 Merchant Law Group LLP
love

// lpl : 2015-07-30 LPL Holdings, Inc.
lpl

// lplfinancial : 2015-07-30 LPL Holdings, Inc.
lplfinancial

// ltd : 2014-09-25 Binky Moon, LLC
ltd

// ltda : 2014-04-17 InterNetX, Corp
ltda

// lundbeck : 2015-08-06 H. Lundbeck A/S
lundbeck

// luxe : 2014-01-09 Registry Services, LLC
luxe

// luxury : 2013-10-17 Luxury Partners, LLC
luxury

// macys : 2015-07-31 Macys, Inc.
macys

// madrid : 2014-05-01 Comunidad de Madrid
madrid

// maif : 2014-10-02 Mutuelle Assurance Instituteur France (MAIF)
maif

// maison : 2013-12-05 Binky Moon, LLC
maison

// makeup : 2015-01-15 XYZ.COM LLC
makeup

// man : 2014-12-04 MAN SE
man

// management : 2013-11-07 Binky Moon, LLC
management

// mango : 2013-10-24 PUNTO FA S.L.
mango

// map : 2016-06-09 Charleston Road Registry Inc.
map

// market : 2014-03-06 Dog Beach, LLC
market

// marketing : 2013-11-07 Binky Moon, LLC
marketing

// markets : 2014-12-11 Dog Beach, LLC
markets

// marriott : 2014-10-09 Marriott Worldwide Corporation
marriott

// marshalls : 2015-07-16 The TJX Companies, Inc.
marshalls

// maserati : 2015-07-31 Fiat Chrysler Automobiles N.V.
maserati

// mattel : 2015-08-06 Mattel Sites, Inc.
mattel

// mba : 2015-04-02 Binky Moon, LLC
mba

// mckinsey : 2015-07-31 McKinsey Holdings, Inc.
mckinsey

// med : 2015-08-06 Medistry LLC
med

// media : 2014-03-06 Binky Moon, LLC
media

// meet : 2014-01-16 Charleston Road Registry Inc.
meet

// melbourne : 2014-05-29 The Crown in right of the State of Victoria, represented by its Department of State Development, Business and Innovation
melbourne

// meme : 2014-01-30 Charleston Road Registry Inc.
meme

// memorial : 2014-10-16 Dog Beach, LLC
memorial

// men : 2015-02-26 Exclusive Registry Limited
men

// menu : 2013-09-11 Dot Menu Registry, LLC
menu

// merckmsd : 2016-07-14 MSD Registry Holdings, Inc.
merckmsd

// miami : 2013-12-19 Minds + Machines Group Limited
miami

// microsoft : 2014-12-18 Microsoft Corporation
microsoft

// mini : 2014-01-09 Bayerische Motoren Werke Aktiengesellschaft
mini

// mint : 2015-07-30 Intuit Administrative Services, Inc.
mint

// mit : 2015-07-02 Massachusetts Institute of Technology
mit

// mitsubishi : 2015-07-23 Mitsubishi Corporation
mitsubishi

// mlb : 2015-05-21 MLB Advanced Media DH, LLC
mlb

// mls : 2015-04-23 The Canadian Real Estate Association
mls

// mma : 2014-11-07 MMA IARD
mma

// mobile : 2016-06-02 Dish DBS Corporation
mobile

// moda : 2013-11-07 Dog Beach, LLC
moda

// moe : 2013-11-13 Interlink Co., Ltd.
moe

// moi : 2014-12-18 Amazon Registry Services, Inc.
moi

// mom : 2015-04-16 UNR Corp.
mom

// monash : 2013-09-30 Monash University
monash

// money : 2014-10-16 Binky Moon, LLC
money

// monster : 2015-09-11 XYZ.COM LLC
monster

// mormon : 2013-12-05 IRI Domain Management, LLC
mormon

// mortgage : 2014-03-20 Dog Beach, LLC
mortgage

// moscow : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
moscow

// moto : 2015-06-04 Motorola Trademark Holdings, LLC
moto

// motorcycles : 2014-01-09 XYZ.COM LLC
motorcycles

// mov : 2014-01-30 Charleston Road Registry Inc.
mov

// movie : 2015-02-05 Binky Moon, LLC
movie

// msd : 2015-07-23 MSD Registry Holdings, Inc.
msd

// mtn : 2014-12-04 MTN Dubai Limited
mtn

// mtr : 2015-03-12 MTR Corporation Limited
mtr

// music : 2021-05-04 DotMusic Limited
music

// mutual : 2015-04-02 Northwestern Mutual MU TLD Registry, LLC
mutual

// nab : 2015-08-20 National Australia Bank Limited
nab

// nagoya : 2013-10-24 GMO Registry, Inc.
nagoya

// natura : 2015-03-12 NATURA COSMÃ‰TICOS S.A.
natura

// navy : 2014-03-06 Dog Beach, LLC
navy

// nba : 2015-07-31 NBA REGISTRY, LLC
nba

// nec : 2015-01-08 NEC Corporation
nec

// netbank : 2014-06-26 COMMONWEALTH BANK OF AUSTRALIA
netbank

// netflix : 2015-06-18 Netflix, Inc.
netflix

// network : 2013-11-14 Binky Moon, LLC
network

// neustar : 2013-12-05 NeuStar, Inc.
neustar

// new : 2014-01-30 Charleston Road Registry Inc.
new

// news : 2014-12-18 Dog Beach, LLC
news

// next : 2015-06-18 Next plc
next

// nextdirect : 2015-06-18 Next plc
nextdirect

// nexus : 2014-07-24 Charleston Road Registry Inc.
nexus

// nfl : 2015-07-23 NFL Reg Ops LLC
nfl

// ngo : 2014-03-06 Public Interest Registry
ngo

// nhk : 2014-02-13 Japan Broadcasting Corporation (NHK)
nhk

// nico : 2014-12-04 DWANGO Co., Ltd.
nico

// nike : 2015-07-23 NIKE, Inc.
nike

// nikon : 2015-05-21 NIKON CORPORATION
nikon

// ninja : 2013-11-07 Dog Beach, LLC
ninja

// nissan : 2014-03-27 NISSAN MOTOR CO., LTD.
nissan

// nissay : 2015-10-29 Nippon Life Insurance Company
nissay

// nokia : 2015-01-08 Nokia Corporation
nokia

// northwesternmutual : 2015-06-18 Northwestern Mutual Registry, LLC
northwesternmutual

// norton : 2014-12-04 NortonLifeLock Inc.
norton

// now : 2015-06-25 Amazon Registry Services, Inc.
now

// nowruz : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
nowruz

// nowtv : 2015-05-14 Starbucks (HK) Limited
nowtv

// nra : 2014-05-22 NRA Holdings Company, INC.
nra

// nrw : 2013-11-21 Minds + Machines GmbH
nrw

// ntt : 2014-10-31 NIPPON TELEGRAPH AND TELEPHONE CORPORATION
ntt

// nyc : 2014-01-23 The City of New York by and through the New York City Department of Information Technology & Telecommunications
nyc

// obi : 2014-09-25 OBI Group Holding SE & Co. KGaA
obi

// observer : 2015-04-30 Dog Beach, LLC
observer

// off : 2015-07-23 Johnson Shareholdings, Inc.
off

// office : 2015-03-12 Microsoft Corporation
office

// okinawa : 2013-12-05 BRregistry, Inc.
okinawa

// olayan : 2015-05-14 Crescent Holding GmbH
olayan

// olayangroup : 2015-05-14 Crescent Holding GmbH
olayangroup

// oldnavy : 2015-07-31 The Gap, Inc.
oldnavy

// ollo : 2015-06-04 Dish DBS Corporation
ollo

// omega : 2015-01-08 The Swatch Group Ltd
omega

// one : 2014-11-07 One.com A/S
one

// ong : 2014-03-06 Public Interest Registry
ong

// onl : 2013-09-16 iRegistry GmbH
onl

// online : 2015-01-15 Radix FZC
online

// ooo : 2014-01-09 INFIBEAM AVENUES LIMITED
ooo

// open : 2015-07-31 American Express Travel Related Services Company, Inc.
open

// oracle : 2014-06-19 Oracle Corporation
oracle

// orange : 2015-03-12 Orange Brand Services Limited
orange

// organic : 2014-03-27 Afilias Limited
organic

// origins : 2015-10-01 The EstÃ©e Lauder Companies Inc.
origins

// osaka : 2014-09-04 Osaka Registry Co., Ltd.
osaka

// otsuka : 2013-10-11 Otsuka Holdings Co., Ltd.
otsuka

// ott : 2015-06-04 Dish DBS Corporation
ott

// ovh : 2014-01-16 MÃ©diaBC
ovh

// page : 2014-12-04 Charleston Road Registry Inc.
page

// panasonic : 2015-07-30 Panasonic Corporation
panasonic

// paris : 2014-01-30 City of Paris
paris

// pars : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
pars

// partners : 2013-12-05 Binky Moon, LLC
partners

// parts : 2013-12-05 Binky Moon, LLC
parts

// party : 2014-09-11 Blue Sky Registry Limited
party

// passagens : 2015-03-05 Travel Reservations SRL
passagens

// pay : 2015-08-27 Amazon Registry Services, Inc.
pay

// pccw : 2015-05-14 PCCW Enterprises Limited
pccw

// pet : 2015-05-07 Afilias Limited
pet

// pfizer : 2015-09-11 Pfizer Inc.
pfizer

// pharmacy : 2014-06-19 National Association of Boards of Pharmacy
pharmacy

// phd : 2016-07-28 Charleston Road Registry Inc.
phd

// philips : 2014-11-07 Koninklijke Philips N.V.
philips

// phone : 2016-06-02 Dish DBS Corporation
phone

// photo : 2013-11-14 UNR Corp.
photo

// photography : 2013-09-20 Binky Moon, LLC
photography

// photos : 2013-10-17 Binky Moon, LLC
photos

// physio : 2014-05-01 PhysBiz Pty Ltd
physio

// pics : 2013-11-14 UNR Corp.
pics

// pictet : 2014-06-26 Pictet Europe S.A.
pictet

// pictures : 2014-03-06 Binky Moon, LLC
pictures

// pid : 2015-01-08 Top Level Spectrum, Inc.
pid

// pin : 2014-12-18 Amazon Registry Services, Inc.
pin

// ping : 2015-06-11 Ping Registry Provider, Inc.
ping

// pink : 2013-10-01 Afilias Limited
pink

// pioneer : 2015-07-16 Pioneer Corporation
pioneer

// pizza : 2014-06-26 Binky Moon, LLC
pizza

// place : 2014-04-24 Binky Moon, LLC
place

// play : 2015-03-05 Charleston Road Registry Inc.
play

// playstation : 2015-07-02 Sony Interactive Entertainment Inc.
playstation

// plumbing : 2013-09-10 Binky Moon, LLC
plumbing

// plus : 2015-02-05 Binky Moon, LLC
plus

// pnc : 2015-07-02 PNC Domain Co., LLC
pnc

// pohl : 2014-06-23 Deutsche VermÃ¶gensberatung Aktiengesellschaft DVAG
pohl

// poker : 2014-07-03 Afilias Limited
poker

// politie : 2015-08-20 Politie Nederland
politie

// porn : 2014-10-16 ICM Registry PN LLC
porn

// pramerica : 2015-07-30 Prudential Financial, Inc.
pramerica

// praxi : 2013-12-05 Praxi S.p.A.
praxi

// press : 2014-04-03 Radix FZC
press

// prime : 2015-06-25 Amazon Registry Services, Inc.
prime

// prod : 2014-01-23 Charleston Road Registry Inc.
prod

// productions : 2013-12-05 Binky Moon, LLC
productions

// prof : 2014-07-24 Charleston Road Registry Inc.
prof

// progressive : 2015-07-23 Progressive Casualty Insurance Company
progressive

// promo : 2014-12-18 Afilias Limited
promo

// properties : 2013-12-05 Binky Moon, LLC
properties

// property : 2014-05-22 UNR Corp.
property

// protection : 2015-04-23 XYZ.COM LLC
protection

// pru : 2015-07-30 Prudential Financial, Inc.
pru

// prudential : 2015-07-30 Prudential Financial, Inc.
prudential

// pub : 2013-12-12 Dog Beach, LLC
pub

// pwc : 2015-10-29 PricewaterhouseCoopers LLP
pwc

// qpon : 2013-11-14 dotCOOL, Inc.
qpon

// quebec : 2013-12-19 PointQuÃ©bec Inc
quebec

// quest : 2015-03-26 XYZ.COM LLC
quest

// racing : 2014-12-04 Premier Registry Limited
racing

// radio : 2016-07-21 European Broadcasting Union (EBU)
radio

// raid : 2015-07-23 Johnson Shareholdings, Inc.
raid

// read : 2014-12-18 Amazon Registry Services, Inc.
read

// realestate : 2015-09-11 dotRealEstate LLC
realestate

// realtor : 2014-05-29 Real Estate Domains LLC
realtor

// realty : 2015-03-19 Dog Beach, LLC
realty

// recipes : 2013-10-17 Binky Moon, LLC
recipes

// red : 2013-11-07 Afilias Limited
red

// redstone : 2014-10-31 Redstone Haute Couture Co., Ltd.
redstone

// redumbrella : 2015-03-26 Travelers TLD, LLC
redumbrella

// rehab : 2014-03-06 Dog Beach, LLC
rehab

// reise : 2014-03-13 Binky Moon, LLC
reise

// reisen : 2014-03-06 Binky Moon, LLC
reisen

// reit : 2014-09-04 National Association of Real Estate Investment Trusts, Inc.
reit

// reliance : 2015-04-02 Reliance Industries Limited
reliance

// ren : 2013-12-12 ZDNS International Limited
ren

// rent : 2014-12-04 XYZ.COM LLC
rent

// rentals : 2013-12-05 Binky Moon, LLC
rentals

// repair : 2013-11-07 Binky Moon, LLC
repair

// report : 2013-12-05 Binky Moon, LLC
report

// republican : 2014-03-20 Dog Beach, LLC
republican

// rest : 2013-12-19 Punto 2012 Sociedad Anonima Promotora de Inversion de Capital Variable
rest

// restaurant : 2014-07-03 Binky Moon, LLC
restaurant

// review : 2014-11-20 dot Review Limited
review

// reviews : 2013-09-13 Dog Beach, LLC
reviews

// rexroth : 2015-06-18 Robert Bosch GMBH
rexroth

// rich : 2013-11-21 iRegistry GmbH
rich

// richardli : 2015-05-14 Pacific Century Asset Management (HK) Limited
richardli

// ricoh : 2014-11-20 Ricoh Company, Ltd.
ricoh

// ril : 2015-04-02 Reliance Industries Limited
ril

// rio : 2014-02-27 Empresa Municipal de InformÃ¡tica SA - IPLANRIO
rio

// rip : 2014-07-10 Dog Beach, LLC
rip

// rocher : 2014-12-18 Ferrero Trading Lux S.A.
rocher

// rocks : 2013-11-14 Dog Beach, LLC
rocks

// rodeo : 2013-12-19 Registry Services, LLC
rodeo

// rogers : 2015-08-06 Rogers Communications Canada Inc.
rogers

// room : 2014-12-18 Amazon Registry Services, Inc.
room

// rsvp : 2014-05-08 Charleston Road Registry Inc.
rsvp

// rugby : 2016-12-15 World Rugby Strategic Developments Limited
rugby

// ruhr : 2013-10-02 regiodot GmbH & Co. KG
ruhr

// run : 2015-03-19 Binky Moon, LLC
run

// rwe : 2015-04-02 RWE AG
rwe

// ryukyu : 2014-01-09 BRregistry, Inc.
ryukyu

// saarland : 2013-12-12 dotSaarland GmbH
saarland

// safe : 2014-12-18 Amazon Registry Services, Inc.
safe

// safety : 2015-01-08 Safety Registry Services, LLC.
safety

// sakura : 2014-12-18 SAKURA Internet Inc.
sakura

// sale : 2014-10-16 Dog Beach, LLC
sale

// salon : 2014-12-11 Binky Moon, LLC
salon

// samsclub : 2015-07-31 Wal-Mart Stores, Inc.
samsclub

// samsung : 2014-04-03 SAMSUNG SDS CO., LTD
samsung

// sandvik : 2014-11-13 Sandvik AB
sandvik

// sandvikcoromant : 2014-11-07 Sandvik AB
sandvikcoromant

// sanofi : 2014-10-09 Sanofi
sanofi

// sap : 2014-03-27 SAP AG
sap

// sarl : 2014-07-03 Binky Moon, LLC
sarl

// sas : 2015-04-02 Research IP LLC
sas

// save : 2015-06-25 Amazon Registry Services, Inc.
save

// saxo : 2014-10-31 Saxo Bank A/S
saxo

// sbi : 2015-03-12 STATE BANK OF INDIA
sbi

// sbs : 2014-11-07 ShortDot SA
sbs

// sca : 2014-03-13 SVENSKA CELLULOSA AKTIEBOLAGET SCA (publ)
sca

// scb : 2014-02-20 The Siam Commercial Bank Public Company Limited ("SCB")
scb

// schaeffler : 2015-08-06 Schaeffler Technologies AG & Co. KG
schaeffler

// schmidt : 2014-04-03 SCHMIDT GROUPE S.A.S.
schmidt

// scholarships : 2014-04-24 Scholarships.com, LLC
scholarships

// school : 2014-12-18 Binky Moon, LLC
school

// schule : 2014-03-06 Binky Moon, LLC
schule

// schwarz : 2014-09-18 Schwarz Domains und Services GmbH & Co. KG
schwarz

// science : 2014-09-11 dot Science Limited
science

// scjohnson : 2015-07-23 Johnson Shareholdings, Inc.
scjohnson

// scot : 2014-01-23 Dot Scot Registry Limited
scot

// search : 2016-06-09 Charleston Road Registry Inc.
search

// seat : 2014-05-22 SEAT, S.A. (Sociedad Unipersonal)
seat

// secure : 2015-08-27 Amazon Registry Services, Inc.
secure

// security : 2015-05-14 XYZ.COM LLC
security

// seek : 2014-12-04 Seek Limited
seek

// select : 2015-10-08 Registry Services, LLC
select

// sener : 2014-10-24 Sener IngenierÃ­a y Sistemas, S.A.
sener

// services : 2014-02-27 Binky Moon, LLC
services

// ses : 2015-07-23 SES
ses

// seven : 2015-08-06 Seven West Media Ltd
seven

// sew : 2014-07-17 SEW-EURODRIVE GmbH & Co KG
sew

// sex : 2014-11-13 ICM Registry SX LLC
sex

// sexy : 2013-09-11 UNR Corp.
sexy

// sfr : 2015-08-13 Societe Francaise du Radiotelephone - SFR
sfr

// shangrila : 2015-09-03 Shangriâ€�La International Hotel Management Limited
shangrila

// sharp : 2014-05-01 Sharp Corporation
sharp

// shaw : 2015-04-23 Shaw Cablesystems G.P.
shaw

// shell : 2015-07-30 Shell Information Technology International Inc
shell

// shia : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
shia

// shiksha : 2013-11-14 Afilias Limited
shiksha

// shoes : 2013-10-02 Binky Moon, LLC
shoes

// shop : 2016-04-08 GMO Registry, Inc.
shop

// shopping : 2016-03-31 Binky Moon, LLC
shopping

// shouji : 2015-01-08 Beijing Qihu Keji Co., Ltd.
shouji

// show : 2015-03-05 Binky Moon, LLC
show

// showtime : 2015-08-06 CBS Domains Inc.
showtime

// silk : 2015-06-25 Amazon Registry Services, Inc.
silk

// sina : 2015-03-12 Sina Corporation
sina

// singles : 2013-08-27 Binky Moon, LLC
singles

// site : 2015-01-15 Radix FZC
site

// ski : 2015-04-09 Afilias Limited
ski

// skin : 2015-01-15 XYZ.COM LLC
skin

// sky : 2014-06-19 Sky International AG
sky

// skype : 2014-12-18 Microsoft Corporation
skype

// sling : 2015-07-30 DISH Technologies L.L.C.
sling

// smart : 2015-07-09 Smart Communications, Inc. (SMART)
smart

// smile : 2014-12-18 Amazon Registry Services, Inc.
smile

// sncf : 2015-02-19 SociÃ©tÃ© Nationale des Chemins de fer Francais S N C F
sncf

// soccer : 2015-03-26 Binky Moon, LLC
soccer

// social : 2013-11-07 Dog Beach, LLC
social

// softbank : 2015-07-02 SoftBank Group Corp.
softbank

// software : 2014-03-20 Dog Beach, LLC
software

// sohu : 2013-12-19 Sohu.com Limited
sohu

// solar : 2013-11-07 Binky Moon, LLC
solar

// solutions : 2013-11-07 Binky Moon, LLC
solutions

// song : 2015-02-26 Amazon Registry Services, Inc.
song

// sony : 2015-01-08 Sony Corporation
sony

// soy : 2014-01-23 Charleston Road Registry Inc.
soy

// spa : 2019-09-19 Asia Spa and Wellness Promotion Council Limited
spa

// space : 2014-04-03 Radix FZC
space

// sport : 2017-11-16 Global Association of International Sports Federations (GAISF)
sport

// spot : 2015-02-26 Amazon Registry Services, Inc.
spot

// srl : 2015-05-07 InterNetX, Corp
srl

// stada : 2014-11-13 STADA Arzneimittel AG
stada

// staples : 2015-07-30 Staples, Inc.
staples

// star : 2015-01-08 Star India Private Limited
star

// statebank : 2015-03-12 STATE BANK OF INDIA
statebank

// statefarm : 2015-07-30 State Farm Mutual Automobile Insurance Company
statefarm

// stc : 2014-10-09 Saudi Telecom Company
stc

// stcgroup : 2014-10-09 Saudi Telecom Company
stcgroup

// stockholm : 2014-12-18 Stockholms kommun
stockholm

// storage : 2014-12-22 XYZ.COM LLC
storage

// store : 2015-04-09 Radix FZC
store

// stream : 2016-01-08 dot Stream Limited
stream

// studio : 2015-02-11 Dog Beach, LLC
studio

// study : 2014-12-11 OPEN UNIVERSITIES AUSTRALIA PTY LTD
study

// style : 2014-12-04 Binky Moon, LLC
style

// sucks : 2014-12-22 Vox Populi Registry Ltd.
sucks

// supplies : 2013-12-19 Binky Moon, LLC
supplies

// supply : 2013-12-19 Binky Moon, LLC
supply

// support : 2013-10-24 Binky Moon, LLC
support

// surf : 2014-01-09 Registry Services, LLC
surf

// surgery : 2014-03-20 Binky Moon, LLC
surgery

// suzuki : 2014-02-20 SUZUKI MOTOR CORPORATION
suzuki

// swatch : 2015-01-08 The Swatch Group Ltd
swatch

// swiss : 2014-10-16 Swiss Confederation
swiss

// sydney : 2014-09-18 State of New South Wales, Department of Premier and Cabinet
sydney

// systems : 2013-11-07 Binky Moon, LLC
systems

// tab : 2014-12-04 Tabcorp Holdings Limited
tab

// taipei : 2014-07-10 Taipei City Government
taipei

// talk : 2015-04-09 Amazon Registry Services, Inc.
talk

// taobao : 2015-01-15 Alibaba Group Holding Limited
taobao

// target : 2015-07-31 Target Domain Holdings, LLC
target

// tatamotors : 2015-03-12 Tata Motors Ltd
tatamotors

// tatar : 2014-04-24 Limited Liability Company "Coordination Center of Regional Domain of Tatarstan Republic"
tatar

// tattoo : 2013-08-30 UNR Corp.
tattoo

// tax : 2014-03-20 Binky Moon, LLC
tax

// taxi : 2015-03-19 Binky Moon, LLC
taxi

// tci : 2014-09-12 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
tci

// tdk : 2015-06-11 TDK Corporation
tdk

// team : 2015-03-05 Binky Moon, LLC
team

// tech : 2015-01-30 Radix FZC
tech

// technology : 2013-09-13 Binky Moon, LLC
technology

// temasek : 2014-08-07 Temasek Holdings (Private) Limited
temasek

// tennis : 2014-12-04 Binky Moon, LLC
tennis

// teva : 2015-07-02 Teva Pharmaceutical Industries Limited
teva

// thd : 2015-04-02 Home Depot Product Authority, LLC
thd

// theater : 2015-03-19 Binky Moon, LLC
theater

// theatre : 2015-05-07 XYZ.COM LLC
theatre

// tiaa : 2015-07-23 Teachers Insurance and Annuity Association of America
tiaa

// tickets : 2015-02-05 XYZ.COM LLC
tickets

// tienda : 2013-11-14 Binky Moon, LLC
tienda

// tiffany : 2015-01-30 Tiffany and Company
tiffany

// tips : 2013-09-20 Binky Moon, LLC
tips

// tires : 2014-11-07 Binky Moon, LLC
tires

// tirol : 2014-04-24 punkt Tirol GmbH
tirol

// tjmaxx : 2015-07-16 The TJX Companies, Inc.
tjmaxx

// tjx : 2015-07-16 The TJX Companies, Inc.
tjx

// tkmaxx : 2015-07-16 The TJX Companies, Inc.
tkmaxx

// tmall : 2015-01-15 Alibaba Group Holding Limited
tmall

// today : 2013-09-20 Binky Moon, LLC
today

// tokyo : 2013-11-13 GMO Registry, Inc.
tokyo

// tools : 2013-11-21 Binky Moon, LLC
tools

// top : 2014-03-20 .TOP Registry
top

// toray : 2014-12-18 Toray Industries, Inc.
toray

// toshiba : 2014-04-10 TOSHIBA Corporation
toshiba

// total : 2015-08-06 Total SA
total

// tours : 2015-01-22 Binky Moon, LLC
tours

// town : 2014-03-06 Binky Moon, LLC
town

// toyota : 2015-04-23 TOYOTA MOTOR CORPORATION
toyota

// toys : 2014-03-06 Binky Moon, LLC
toys

// trade : 2014-01-23 Elite Registry Limited
trade

// trading : 2014-12-11 Dog Beach, LLC
trading

// training : 2013-11-07 Binky Moon, LLC
training

// travel : 2015-10-09 Dog Beach, LLC
travel

// travelchannel : 2015-07-02 Lifestyle Domain Holdings, Inc.
travelchannel

// travelers : 2015-03-26 Travelers TLD, LLC
travelers

// travelersinsurance : 2015-03-26 Travelers TLD, LLC
travelersinsurance

// trust : 2014-10-16 UNR Corp.
trust

// trv : 2015-03-26 Travelers TLD, LLC
trv

// tube : 2015-06-11 Latin American Telecom LLC
tube

// tui : 2014-07-03 TUI AG
tui

// tunes : 2015-02-26 Amazon Registry Services, Inc.
tunes

// tushu : 2014-12-18 Amazon Registry Services, Inc.
tushu

// tvs : 2015-02-19 T V SUNDRAM IYENGAR  & SONS LIMITED
tvs

// ubank : 2015-08-20 National Australia Bank Limited
ubank

// ubs : 2014-12-11 UBS AG
ubs

// unicom : 2015-10-15 China United Network Communications Corporation Limited
unicom

// university : 2014-03-06 Binky Moon, LLC
university

// uno : 2013-09-11 Radix FZC
uno

// uol : 2014-05-01 UBN INTERNET LTDA.
uol

// ups : 2015-06-25 UPS Market Driver, Inc.
ups

// vacations : 2013-12-05 Binky Moon, LLC
vacations

// vana : 2014-12-11 Lifestyle Domain Holdings, Inc.
vana

// vanguard : 2015-09-03 The Vanguard Group, Inc.
vanguard

// vegas : 2014-01-16 Dot Vegas, Inc.
vegas

// ventures : 2013-08-27 Binky Moon, LLC
ventures

// verisign : 2015-08-13 VeriSign, Inc.
verisign

// versicherung : 2014-03-20 tldbox GmbH
versicherung

// vet : 2014-03-06 Dog Beach, LLC
vet

// viajes : 2013-10-17 Binky Moon, LLC
viajes

// video : 2014-10-16 Dog Beach, LLC
video

// vig : 2015-05-14 VIENNA INSURANCE GROUP AG Wiener Versicherung Gruppe
vig

// viking : 2015-04-02 Viking River Cruises (Bermuda) Ltd.
viking

// villas : 2013-12-05 Binky Moon, LLC
villas

// vin : 2015-06-18 Binky Moon, LLC
vin

// vip : 2015-01-22 Registry Services, LLC
vip

// virgin : 2014-09-25 Virgin Enterprises Limited
virgin

// visa : 2015-07-30 Visa Worldwide Pte. Limited
visa

// vision : 2013-12-05 Binky Moon, LLC
vision

// viva : 2014-11-07 Saudi Telecom Company
viva

// vivo : 2015-07-31 Telefonica Brasil S.A.
vivo

// vlaanderen : 2014-02-06 DNS.be vzw
vlaanderen

// vodka : 2013-12-19 Registry Services, LLC
vodka

// volkswagen : 2015-05-14 Volkswagen Group of America Inc.
volkswagen

// volvo : 2015-11-12 Volvo Holding Sverige Aktiebolag
volvo

// vote : 2013-11-21 Monolith Registry LLC
vote

// voting : 2013-11-13 Valuetainment Corp.
voting

// voto : 2013-11-21 Monolith Registry LLC
voto

// voyage : 2013-08-27 Binky Moon, LLC
voyage

// vuelos : 2015-03-05 Travel Reservations SRL
vuelos

// wales : 2014-05-08 Nominet UK
wales

// walmart : 2015-07-31 Wal-Mart Stores, Inc.
walmart

// walter : 2014-11-13 Sandvik AB
walter

// wang : 2013-10-24 Zodiac Wang Limited
wang

// wanggou : 2014-12-18 Amazon Registry Services, Inc.
wanggou

// watch : 2013-11-14 Binky Moon, LLC
watch

// watches : 2014-12-22 Afilias Limited
watches

// weather : 2015-01-08 International Business Machines Corporation
weather

// weatherchannel : 2015-03-12 International Business Machines Corporation
weatherchannel

// webcam : 2014-01-23 dot Webcam Limited
webcam

// weber : 2015-06-04 Saint-Gobain Weber SA
weber

// website : 2014-04-03 Radix FZC
website

// wedding : 2014-04-24 Registry Services, LLC
wedding

// weibo : 2015-03-05 Sina Corporation
weibo

// weir : 2015-01-29 Weir Group IP Limited
weir

// whoswho : 2014-02-20 Who's Who Registry
whoswho

// wien : 2013-10-28 punkt.wien GmbH
wien

// wiki : 2013-11-07 Top Level Design, LLC
wiki

// williamhill : 2014-03-13 William Hill Organization Limited
williamhill

// win : 2014-11-20 First Registry Limited
win

// windows : 2014-12-18 Microsoft Corporation
windows

// wine : 2015-06-18 Binky Moon, LLC
wine

// winners : 2015-07-16 The TJX Companies, Inc.
winners

// wme : 2014-02-13 William Morris Endeavor Entertainment, LLC
wme

// wolterskluwer : 2015-08-06 Wolters Kluwer N.V.
wolterskluwer

// woodside : 2015-07-09 Woodside Petroleum Limited
woodside

// work : 2013-12-19 Registry Services, LLC
work

// works : 2013-11-14 Binky Moon, LLC
works

// world : 2014-06-12 Binky Moon, LLC
world

// wow : 2015-10-08 Amazon Registry Services, Inc.
wow

// wtc : 2013-12-19 World Trade Centers Association, Inc.
wtc

// wtf : 2014-03-06 Binky Moon, LLC
wtf

// xbox : 2014-12-18 Microsoft Corporation
xbox

// xerox : 2014-10-24 Xerox DNHC LLC
xerox

// xfinity : 2015-07-09 Comcast IP Holdings I, LLC
xfinity

// xihuan : 2015-01-08 Beijing Qihu Keji Co., Ltd.
xihuan

// xin : 2014-12-11 Elegant Leader Limited
xin

// xn--11b4c3d : 2015-01-15 VeriSign Sarl
à¤•à¥‰à¤®

// xn--1ck2e1b : 2015-02-26 Amazon Registry Services, Inc.
ã‚»ãƒ¼ãƒ«

// xn--1qqw23a : 2014-01-09 Guangzhou YU Wei Information Technology Co., Ltd.
ä½›å±±

// xn--30rr7y : 2014-06-12 Excellent First Limited
æ…ˆå–„

// xn--3bst00m : 2013-09-13 Eagle Horizon Limited
é›†å›¢

// xn--3ds443g : 2013-09-08 TLD REGISTRY LIMITED OY
åœ¨çº¿

// xn--3oq18vl8pn36a : 2015-07-02 Volkswagen (China) Investment Co., Ltd.
å¤§ä¼—æ±½è½¦

// xn--3pxu8k : 2015-01-15 VeriSign Sarl
ç‚¹çœ‹

// xn--42c2d9a : 2015-01-15 VeriSign Sarl
à¸„à¸­à¸¡

// xn--45q11c : 2013-11-21 Zodiac Gemini Ltd
å…«å�¦

// xn--4gbrim : 2013-10-04 Helium TLDs Ltd
Ù…ÙˆÙ‚Ø¹

// xn--55qw42g : 2013-11-08 China Organizational Name Administration Center
å…¬ç›Š

// xn--55qx5d : 2013-11-14 China Internet Network Information Center (CNNIC)
å…¬å�¸

// xn--5su34j936bgsg : 2015-09-03 Shangriâ€�La International Hotel Management Limited
é¦™æ ¼é‡Œæ‹‰

// xn--5tzm5g : 2014-12-22 Global Website TLD Asia Limited
ç½‘ç«™

// xn--6frz82g : 2013-09-23 Afilias Limited
ç§»åŠ¨

// xn--6qq986b3xl : 2013-09-13 Tycoon Treasure Limited
æˆ‘çˆ±ä½ 

// xn--80adxhks : 2013-12-19 Foundation for Assistance for Internet Technologies and Infrastructure Development (FAITID)
Ð¼Ð¾Ñ�ÐºÐ²Ð°

// xn--80aqecdr1a : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
ÐºÐ°Ñ‚Ð¾Ð»Ð¸Ðº

// xn--80asehdb : 2013-07-14 CORE Association
Ð¾Ð½Ð»Ð°Ð¹Ð½

// xn--80aswg : 2013-07-14 CORE Association
Ñ�Ð°Ð¹Ñ‚

// xn--8y0a063a : 2015-03-26 China United Network Communications Corporation Limited
è�”é€š

// xn--9dbq2a : 2015-01-15 VeriSign Sarl
×§×•×�

// xn--9et52u : 2014-06-12 RISE VICTORY LIMITED
æ—¶å°š

// xn--9krt00a : 2015-03-12 Sina Corporation
å¾®å�š

// xn--b4w605ferd : 2014-08-07 Temasek Holdings (Private) Limited
æ·¡é©¬é”¡

// xn--bck1b9a5dre4c : 2015-02-26 Amazon Registry Services, Inc.
ãƒ•ã‚¡ãƒƒã‚·ãƒ§ãƒ³

// xn--c1avg : 2013-11-14 Public Interest Registry
Ð¾Ñ€Ð³

// xn--c2br7g : 2015-01-15 VeriSign Sarl
à¤¨à¥‡à¤Ÿ

// xn--cck2b3b : 2015-02-26 Amazon Registry Services, Inc.
ã‚¹ãƒˆã‚¢

// xn--cckwcxetd : 2019-12-19 Amazon Registry Services, Inc.
ã‚¢ãƒžã‚¾ãƒ³

// xn--cg4bki : 2013-09-27 SAMSUNG SDS CO., LTD
ì‚¼ì„±

// xn--czr694b : 2014-01-16 Internet DotTrademark Organisation Limited
å•†æ ‡

// xn--czrs0t : 2013-12-19 Binky Moon, LLC
å•†åº—

// xn--czru2d : 2013-11-21 Zodiac Aquarius Limited
å•†åŸŽ

// xn--d1acj3b : 2013-11-20 The Foundation for Network Initiatives â€œThe Smart Internetâ€�
Ð´ÐµÑ‚Ð¸

// xn--eckvdtc9d : 2014-12-18 Amazon Registry Services, Inc.
ãƒ�ã‚¤ãƒ³ãƒˆ

// xn--efvy88h : 2014-08-22 Guangzhou YU Wei Information Technology Co., Ltd.
æ–°é—»

// xn--fct429k : 2015-04-09 Amazon Registry Services, Inc.
å®¶é›»

// xn--fhbei : 2015-01-15 VeriSign Sarl
ÙƒÙˆÙ…

// xn--fiq228c5hs : 2013-09-08 TLD REGISTRY LIMITED OY
ä¸­æ–‡ç½‘

// xn--fiq64b : 2013-10-14 CITIC Group Corporation
ä¸­ä¿¡

// xn--fjq720a : 2014-05-22 Binky Moon, LLC
å¨±ä¹�

// xn--flw351e : 2014-07-31 Charleston Road Registry Inc.
è°·æ­Œ

// xn--fzys8d69uvgm : 2015-05-14 PCCW Enterprises Limited
é›»è¨Šç›ˆç§‘

// xn--g2xx48c : 2015-01-30 Nawang Heli(Xiamen) Network Service Co., LTD.
è´­ç‰©

// xn--gckr3f0f : 2015-02-26 Amazon Registry Services, Inc.
ã‚¯ãƒ©ã‚¦ãƒ‰

// xn--gk3at1e : 2015-10-08 Amazon Registry Services, Inc.
é€šè²©

// xn--hxt814e : 2014-05-15 Zodiac Taurus Limited
ç½‘åº—

// xn--i1b6b1a6a2e : 2013-11-14 Public Interest Registry
à¤¸à¤‚à¤—à¤ à¤¨

// xn--imr513n : 2014-12-11 Internet DotTrademark Organisation Limited
é¤�åŽ…

// xn--io0a7i : 2013-11-14 China Internet Network Information Center (CNNIC)
ç½‘ç»œ

// xn--j1aef : 2015-01-15 VeriSign Sarl
ÐºÐ¾Ð¼

// xn--jlq480n2rg : 2019-12-19 Amazon Registry Services, Inc.
äºšé©¬é€Š

// xn--jlq61u9w7b : 2015-01-08 Nokia Corporation
è¯ºåŸºäºš

// xn--jvr189m : 2015-02-26 Amazon Registry Services, Inc.
é£Ÿå“�

// xn--kcrx77d1x4a : 2014-11-07 Koninklijke Philips N.V.
é£žåˆ©æµ¦

// xn--kput3i : 2014-02-13 Beijing RITT-Net Technology Development Co., Ltd
æ‰‹æœº

// xn--mgba3a3ejt : 2014-11-20 Aramco Services Company
Ø§Ø±Ø§Ù…ÙƒÙˆ

// xn--mgba7c0bbn0a : 2015-05-14 Crescent Holding GmbH
Ø§Ù„Ø¹Ù„ÙŠØ§Ù†

// xn--mgbaakc7dvf : 2015-09-03 Emirates Telecommunications Corporation (trading as Etisalat)
Ø§ØªØµØ§Ù„Ø§Øª

// xn--mgbab2bd : 2013-10-31 CORE Association
Ø¨Ø§Ø²Ø§Ø±

// xn--mgbca7dzdo : 2015-07-30 Abu Dhabi Systems and Information Centre
Ø§Ø¨ÙˆØ¸Ø¨ÙŠ

// xn--mgbi4ecexp : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
ÙƒØ§Ø«ÙˆÙ„ÙŠÙƒ

// xn--mgbt3dhd : 2014-09-04 Asia Green IT System Bilgisayar San. ve Tic. Ltd. Sti.
Ù‡Ù…Ø±Ø§Ù‡

// xn--mk1bu44c : 2015-01-15 VeriSign Sarl
ë‹·ì»´

// xn--mxtq1m : 2014-03-06 Net-Chinese Co., Ltd.
æ”¿åºœ

// xn--ngbc5azd : 2013-07-13 International Domain Registry Pty. Ltd.
Ø´Ø¨ÙƒØ©

// xn--ngbe9e0a : 2014-12-04 Kuwait Finance House
Ø¨ÙŠØªÙƒ

// xn--ngbrx : 2015-11-12 League of Arab States
Ø¹Ø±Ø¨

// xn--nqv7f : 2013-11-14 Public Interest Registry
æœºæž„

// xn--nqv7fs00ema : 2013-11-14 Public Interest Registry
ç»„ç»‡æœºæž„

// xn--nyqy26a : 2014-11-07 Stable Tone Limited
å�¥åº·

// xn--otu796d : 2017-08-06 Jiang Yu Liang Cai Technology Company Limited
æ‹›è�˜

// xn--p1acf : 2013-12-12 Rusnames Limited
Ñ€ÑƒÑ�

// xn--pssy2u : 2015-01-15 VeriSign Sarl
å¤§æ‹¿

// xn--q9jyb4c : 2013-09-17 Charleston Road Registry Inc.
ã�¿ã‚“ã�ª

// xn--qcka1pmc : 2014-07-31 Charleston Road Registry Inc.
ã‚°ãƒ¼ã‚°ãƒ«

// xn--rhqv96g : 2013-09-11 Stable Tone Limited
ä¸–ç•Œ

// xn--rovu88b : 2015-02-26 Amazon Registry Services, Inc.
æ›¸ç±�

// xn--ses554g : 2014-01-16 KNET Co., Ltd.
ç½‘å�€

// xn--t60b56a : 2015-01-15 VeriSign Sarl
ë‹·ë„·

// xn--tckwe : 2015-01-15 VeriSign Sarl
ã‚³ãƒ 

// xn--tiq49xqyj : 2015-10-21 Pontificium Consilium de Comunicationibus Socialibus (PCCS) (Pontifical Council for Social Communication)
å¤©ä¸»æ•™

// xn--unup4y : 2013-07-14 Binky Moon, LLC
æ¸¸æˆ�

// xn--vermgensberater-ctb : 2014-06-23 Deutsche VermÃ¶gensberatung Aktiengesellschaft DVAG
vermÃ¶gensberater

// xn--vermgensberatung-pwb : 2014-06-23 Deutsche VermÃ¶gensberatung Aktiengesellschaft DVAG
vermÃ¶gensberatung

// xn--vhquv : 2013-08-27 Binky Moon, LLC
ä¼�ä¸š

// xn--vuq861b : 2014-10-16 Beijing Tele-info Network Technology Co., Ltd.
ä¿¡æ�¯

// xn--w4r85el8fhu5dnra : 2015-04-30 Kerry Trading Co. Limited
å˜‰é‡Œå¤§é…’åº—

// xn--w4rs40l : 2015-07-30 Kerry Trading Co. Limited
å˜‰é‡Œ

// xn--xhq521b : 2013-11-14 Guangzhou YU Wei Information Technology Co., Ltd.
å¹¿ä¸œ

// xn--zfr164b : 2013-11-08 China Organizational Name Administration Center
æ”¿åŠ¡

// xyz : 2013-12-05 XYZ.COM LLC
xyz

// yachts : 2014-01-09 XYZ.COM LLC
yachts

// yahoo : 2015-04-02 Oath Inc.
yahoo

// yamaxun : 2014-12-18 Amazon Registry Services, Inc.
yamaxun

// yandex : 2014-04-10 Yandex Europe B.V.
yandex

// yodobashi : 2014-11-20 YODOBASHI CAMERA CO.,LTD.
yodobashi

// yoga : 2014-05-29 Registry Services, LLC
yoga

// yokohama : 2013-12-12 GMO Registry, Inc.
yokohama

// you : 2015-04-09 Amazon Registry Services, Inc.
you

// youtube : 2014-05-01 Charleston Road Registry Inc.
youtube

// yun : 2015-01-08 Beijing Qihu Keji Co., Ltd.
yun

// zappos : 2015-06-25 Amazon Registry Services, Inc.
zappos

// zara : 2014-11-07 Industria de DiseÃ±o Textil, S.A. (INDITEX, S.A.)
zara

// zero : 2014-12-18 Amazon Registry Services, Inc.
zero

// zip : 2014-05-08 Charleston Road Registry Inc.
zip

// zone : 2013-11-14 Binky Moon, LLC
zone

// zuerich : 2014-11-07 Kanton ZÃ¼rich (Canton of Zurich)
zuerich


// ===END ICANN DOMAINS===
// ===BEGIN PRIVATE DOMAINS===
// (Note: these are in alphabetical order by company name)

// 1GB LLC : https://www.1gb.ua/
// Submitted by 1GB LLC <noc@1gb.com.ua>
cc.ua
inf.ua
ltd.ua

// 611coin : https://611project.org/
611.to

// Aaron Marais' Gitlab pages: https://lab.aaronleem.co.za
// Submitted by Aaron Marais <its_me@aaronleem.co.za>
graphox.us

// accesso Technology Group, plc. : https://accesso.com/
// Submitted by accesso Team <accessoecommerce@accesso.com>
*.devcdnaccesso.com

// Adobe : https://www.adobe.com/
// Submitted by Ian Boston <boston@adobe.com> and Lars Trieloff <trieloff@adobe.com>
adobeaemcloud.com
*.dev.adobeaemcloud.com
hlx.live
adobeaemcloud.net
hlx.page
hlx3.page

// Agnat sp. z o.o. : https://domena.pl
// Submitted by Przemyslaw Plewa <it-admin@domena.pl>
beep.pl

// alboto.ca : http://alboto.ca
// Submitted by Anton Avramov <avramov@alboto.ca>
barsy.ca

// Alces Software Ltd : http://alces-software.com
// Submitted by Mark J. Titorenko <mark.titorenko@alces-software.com>
*.compute.estate
*.alces.network

// all-inkl.com : https://all-inkl.com
// Submitted by Werner Kaltofen <wk@all-inkl.com>
kasserver.com

// Altervista: https://www.altervista.org
// Submitted by Carlo Cannas <tech_staff@altervista.it>
altervista.org

// alwaysdata : https://www.alwaysdata.com
// Submitted by Cyril <admin@alwaysdata.com>
alwaysdata.net

// Amazon CloudFront : https://aws.amazon.com/cloudfront/
// Submitted by Donavan Miller <donavanm@amazon.com>
cloudfront.net

// Amazon Elastic Compute Cloud : https://aws.amazon.com/ec2/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
*.compute.amazonaws.com
*.compute-1.amazonaws.com
*.compute.amazonaws.com.cn
us-east-1.amazonaws.com

// Amazon Elastic Beanstalk : https://aws.amazon.com/elasticbeanstalk/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
cn-north-1.eb.amazonaws.com.cn
cn-northwest-1.eb.amazonaws.com.cn
elasticbeanstalk.com
ap-northeast-1.elasticbeanstalk.com
ap-northeast-2.elasticbeanstalk.com
ap-northeast-3.elasticbeanstalk.com
ap-south-1.elasticbeanstalk.com
ap-southeast-1.elasticbeanstalk.com
ap-southeast-2.elasticbeanstalk.com
ca-central-1.elasticbeanstalk.com
eu-central-1.elasticbeanstalk.com
eu-west-1.elasticbeanstalk.com
eu-west-2.elasticbeanstalk.com
eu-west-3.elasticbeanstalk.com
sa-east-1.elasticbeanstalk.com
us-east-1.elasticbeanstalk.com
us-east-2.elasticbeanstalk.com
us-gov-west-1.elasticbeanstalk.com
us-west-1.elasticbeanstalk.com
us-west-2.elasticbeanstalk.com

// Amazon Elastic Load Balancing : https://aws.amazon.com/elasticloadbalancing/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
*.elb.amazonaws.com
*.elb.amazonaws.com.cn

// Amazon Global Accelerator : https://aws.amazon.com/global-accelerator/
// Submitted by Daniel Massaguer <psl-maintainers@amazon.com>
awsglobalaccelerator.com

// Amazon S3 : https://aws.amazon.com/s3/
// Submitted by Luke Wells <psl-maintainers@amazon.com>
s3.amazonaws.com
s3-ap-northeast-1.amazonaws.com
s3-ap-northeast-2.amazonaws.com
s3-ap-south-1.amazonaws.com
s3-ap-southeast-1.amazonaws.com
s3-ap-southeast-2.amazonaws.com
s3-ca-central-1.amazonaws.com
s3-eu-central-1.amazonaws.com
s3-eu-west-1.amazonaws.com
s3-eu-west-2.amazonaws.com
s3-eu-west-3.amazonaws.com
s3-external-1.amazonaws.com
s3-fips-us-gov-west-1.amazonaws.com
s3-sa-east-1.amazonaws.com
s3-us-gov-west-1.amazonaws.com
s3-us-east-2.amazonaws.com
s3-us-west-1.amazonaws.com
s3-us-west-2.amazonaws.com
s3.ap-northeast-2.amazonaws.com
s3.ap-south-1.amazonaws.com
s3.cn-north-1.amazonaws.com.cn
s3.ca-central-1.amazonaws.com
s3.eu-central-1.amazonaws.com
s3.eu-west-2.amazonaws.com
s3.eu-west-3.amazonaws.com
s3.us-east-2.amazonaws.com
s3.dualstack.ap-northeast-1.amazonaws.com
s3.dualstack.ap-northeast-2.amazonaws.com
s3.dualstack.ap-south-1.amazonaws.com
s3.dualstack.ap-southeast-1.amazonaws.com
s3.dualstack.ap-southeast-2.amazonaws.com
s3.dualstack.ca-central-1.amazonaws.com
s3.dualstack.eu-central-1.amazonaws.com
s3.dualstack.eu-west-1.amazonaws.com
s3.dualstack.eu-west-2.amazonaws.com
s3.dualstack.eu-west-3.amazonaws.com
s3.dualstack.sa-east-1.amazonaws.com
s3.dualstack.us-east-1.amazonaws.com
s3.dualstack.us-east-2.amazonaws.com
s3-website-us-east-1.amazonaws.com
s3-website-us-west-1.amazonaws.com
s3-website-us-west-2.amazonaws.com
s3-website-ap-northeast-1.amazonaws.com
s3-website-ap-southeast-1.amazonaws.com
s3-website-ap-southeast-2.amazonaws.com
s3-website-eu-west-1.amazonaws.com
s3-website-sa-east-1.amazonaws.com
s3-website.ap-northeast-2.amazonaws.com
s3-website.ap-south-1.amazonaws.com
s3-website.ca-central-1.amazonaws.com
s3-website.eu-central-1.amazonaws.com
s3-website.eu-west-2.amazonaws.com
s3-website.eu-west-3.amazonaws.com
s3-website.us-east-2.amazonaws.com

// Amsterdam Wireless: https://www.amsterdamwireless.nl/
// Submitted by Imre Jonk <hostmaster@amsterdamwireless.nl>
amsw.nl

// Amune : https://amune.org/
// Submitted by Team Amune <cert@amune.org>
t3l3p0rt.net
tele.amune.org

// Apigee : https://apigee.com/
// Submitted by Apigee Security Team <security@apigee.com>
apigee.io

// Apphud : https://apphud.com
// Submitted by Alexander Selivanov <alex@apphud.com>
siiites.com

// Appspace : https://www.appspace.com
// Submitted by Appspace Security Team <security@appspace.com>
appspacehosted.com
appspaceusercontent.com

// Appudo UG (haftungsbeschrÃ¤nkt) : https://www.appudo.com
// Submitted by Alexander Hochbaum <admin@appudo.com>
appudo.net

// Aptible : https://www.aptible.com/
// Submitted by Thomas Orozco <thomas@aptible.com>
on-aptible.com

// ASEINet : https://www.aseinet.com/
// Submitted by Asei SEKIGUCHI <mail@aseinet.com>
user.aseinet.ne.jp
gv.vc
d.gv.vc

// AsociaciÃ³n Amigos de la InformÃ¡tica "Euskalamiga" : http://encounter.eus/
// Submitted by Hector Martin <marcan@euskalencounter.org>
user.party.eus

// Association potager.org : https://potager.org/
// Submitted by Lunar <jardiniers@potager.org>
pimienta.org
poivron.org
potager.org
sweetpepper.org

// ASUSTOR Inc. : http://www.asustor.com
// Submitted by Vincent Tseng <vincenttseng@asustor.com>
myasustor.com

// Atlassian : https://atlassian.com
// Submitted by Sam Smyth <devloop@atlassian.com>
cdn.prod.atlassian-dev.net

// AVM : https://avm.de
// Submitted by Andreas Weise <a.weise@avm.de>
myfritz.net

// AVStack Pte. Ltd. : https://avstack.io
// Submitted by Jasper Hugo <jasper@avstack.io>
onavstack.net

// AW AdvisorWebsites.com Software Inc : https://advisorwebsites.com
// Submitted by James Kennedy <domains@advisorwebsites.com>
*.awdev.ca
*.advisor.ws

// AZ.pl sp. z.o.o: https://az.pl
// Submited by Krzysztof Wolski <krzysztof.wolski@home.eu>
ecommerce-shop.pl

// b-data GmbH : https://www.b-data.io
// Submitted by Olivier Benz <olivier.benz@b-data.ch>
b-data.io

// backplane : https://www.backplane.io
// Submitted by Anthony Voutas <anthony@backplane.io>
backplaneapp.io

// Balena : https://www.balena.io
// Submitted by Petros Angelatos <petrosagg@balena.io>
balena-devices.com

// University of Banja Luka : https://unibl.org
// Domains for Republic of Srpska administrative entity.
// Submitted by Marko Ivanovic <kormang@hotmail.rs>
rs.ba

// Banzai Cloud
// Submitted by Janos Matyas <info@banzaicloud.com>
*.banzai.cloud
app.banzaicloud.io
*.backyards.banzaicloud.io


// BetaInABox
// Submitted by Adrian <adrian@betainabox.com>
betainabox.com

// BinaryLane : http://www.binarylane.com
// Submitted by Nathan O'Sullivan <nathan@mammoth.com.au>
bnr.la

// Bitbucket : http://bitbucket.org
// Submitted by Andy Ortlieb <aortlieb@atlassian.com>
bitbucket.io

// Blackbaud, Inc. : https://www.blackbaud.com
// Submitted by Paul Crowder <paul.crowder@blackbaud.com>
blackbaudcdn.net

// Blatech : http://www.blatech.net
// Submitted by Luke Bratch <luke@bratch.co.uk>
of.je

// Blue Bite, LLC : https://bluebite.com
// Submitted by Joshua Weiss <admin.engineering@bluebite.com>
bluebite.io

// Boomla : https://boomla.com
// Submitted by Tibor Halter <thalter@boomla.com>
boomla.net

// Boutir : https://www.boutir.com
// Submitted by Eric Ng Ka Ka <ngkaka@boutir.com>
boutir.com

// Boxfuse : https://boxfuse.com
// Submitted by Axel Fontaine <axel@boxfuse.com>
boxfuse.io

// bplaced : https://www.bplaced.net/
// Submitted by Miroslav Bozic <security@bplaced.net>
square7.ch
bplaced.com
bplaced.de
square7.de
bplaced.net
square7.net

// Brendly : https://brendly.rs
// Submitted by Dusan Radovanovic <dusan.radovanovic@brendly.rs>
shop.brendly.rs

// BrowserSafetyMark
// Submitted by Dave Tharp <browsersafetymark.io@quicinc.com>
browsersafetymark.io

// Bytemark Hosting : https://www.bytemark.co.uk
// Submitted by Paul Cammish <paul.cammish@bytemark.co.uk>
uk0.bigv.io
dh.bytemark.co.uk
vm.bytemark.co.uk

// Caf.js Labs LLC : https://www.cafjs.com
// Submitted by Antonio Lain <antlai@cafjs.com>
cafjs.com

// callidomus : https://www.callidomus.com/
// Submitted by Marcus Popp <admin@callidomus.com>
mycd.eu

// Carrd : https://carrd.co
// Submitted by AJ <aj@carrd.co>
drr.ac
uwu.ai
carrd.co
crd.co
ju.mp

// CentralNic : http://www.centralnic.com/names/domains
// Submitted by registry <gavin.brown@centralnic.com>
ae.org
br.com
cn.com
com.de
com.se
de.com
eu.com
gb.net
hu.net
jp.net
jpn.com
mex.com
ru.com
sa.com
se.net
uk.com
uk.net
us.com
za.bz
za.com

// No longer operated by CentralNic, these entries should be adopted and/or removed by current operators
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
ar.com
gb.com
hu.com
kr.com
no.com
qc.com
uy.com

// Africa.com Web Solutions Ltd : https://registry.africa.com
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
africa.com

// iDOT Services Limited : http://www.domain.gr.com
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
gr.com

// Radix FZC : http://domains.in.net
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
in.net
web.in

// US REGISTRY LLC : http://us.org
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
us.org

// co.com Registry, LLC : https://registry.co.com
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
co.com

// Roar Domains LLC : https://roar.basketball/
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
aus.basketball
nz.basketball

// BRS Media : https://brsmedia.com/
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
radio.am
radio.fm

// c.la : http://www.c.la/
c.la

// certmgr.org : https://certmgr.org
// Submitted by B. Blechschmidt <hostmaster@certmgr.org>
certmgr.org

// Cityhost LLC  : https://cityhost.ua
// Submitted by Maksym Rivtin <support@cityhost.net.ua>
cx.ua

// Civilized Discourse Construction Kit, Inc. : https://www.discourse.org/
// Submitted by Rishabh Nambiar & Michael Brown <team@discourse.org>
discourse.group
discourse.team

// ClearVox : http://www.clearvox.nl/
// Submitted by Leon Rowland <leon@clearvox.nl>
virtueeldomein.nl

// Clever Cloud : https://www.clever-cloud.com/
// Submitted by Quentin Adam <noc@clever-cloud.com>
cleverapps.io

// Clerk : https://www.clerk.dev
// Submitted by Colin Sidoti <systems@clerk.dev>
clerk.app
clerkstage.app
*.lcl.dev
*.lclstage.dev
*.stg.dev
*.stgstage.dev

// ClickRising : https://clickrising.com/
// Submitted by Umut Gumeli <infrastructure-publicsuffixlist@clickrising.com>
clickrising.net

// Cloud66 : https://www.cloud66.com/
// Submitted by Khash Sajadi <khash@cloud66.com>
c66.me
cloud66.ws
cloud66.zone

// CloudAccess.net : https://www.cloudaccess.net/
// Submitted by Pawel Panek <noc@cloudaccess.net>
jdevcloud.com
wpdevcloud.com
cloudaccess.host
freesite.host
cloudaccess.net

// cloudControl : https://www.cloudcontrol.com/
// Submitted by Tobias Wilken <tw@cloudcontrol.com>
cloudcontrolled.com
cloudcontrolapp.com

// Cloudera, Inc. : https://www.cloudera.com/
// Submitted by Kedarnath Waikar <security@cloudera.com>
*.cloudera.site

// Cloudflare, Inc. : https://www.cloudflare.com/
// Submitted by Cloudflare Team <publicsuffixlist@cloudflare.com>
pages.dev
trycloudflare.com
workers.dev

// Clovyr : https://clovyr.io
// Submitted by Patrick Nielsen <patrick@clovyr.io>
wnext.app

// co.ca : http://registry.co.ca/
co.ca

// Co & Co : https://co-co.nl/
// Submitted by Govert Versluis <govert@co-co.nl>
*.otap.co

// i-registry s.r.o. : http://www.i-registry.cz/
// Submitted by Martin Semrad <semrad@i-registry.cz>
co.cz

// CDN77.com : http://www.cdn77.com
// Submitted by Jan Krpes <jan.krpes@cdn77.com>
c.cdn77.org
cdn77-ssl.net
r.cdn77.net
rsc.cdn77.org
ssl.origin.cdn77-secure.org

// Cloud DNS Ltd : http://www.cloudns.net
// Submitted by Aleksander Hristov <noc@cloudns.net>
cloudns.asia
cloudns.biz
cloudns.club
cloudns.cc
cloudns.eu
cloudns.in
cloudns.info
cloudns.org
cloudns.pro
cloudns.pw
cloudns.us

// CNPY : https://cnpy.gdn
// Submitted by Angelo Gladding <angelo@lahacker.net>
cnpy.gdn

// CoDNS B.V.
co.nl
co.no

// Combell.com : https://www.combell.com
// Submitted by Thomas Wouters <thomas.wouters@combellgroup.com>
webhosting.be
hosting-cluster.nl

// Coordination Center for TLD RU and XN--P1AI : https://cctld.ru/en/domains/domens_ru/reserved/
// Submitted by George Georgievsky <gug@cctld.ru>
ac.ru
edu.ru
gov.ru
int.ru
mil.ru
test.ru

// COSIMO GmbH : http://www.cosimo.de
// Submitted by Rene Marticke <rmarticke@cosimo.de>
dyn.cosidns.de
dynamisches-dns.de
dnsupdater.de
internet-dns.de
l-o-g-i-n.de
dynamic-dns.info
feste-ip.net
knx-server.net
static-access.net

// Craynic, s.r.o. : http://www.craynic.com/
// Submitted by Ales Krajnik <ales.krajnik@craynic.com>
realm.cz

// Cryptonomic : https://cryptonomic.net/
// Submitted by Andrew Cady <public-suffix-list@cryptonomic.net>
*.cryptonomic.net

// Cupcake : https://cupcake.io/
// Submitted by Jonathan Rudenberg <jonathan@cupcake.io>
cupcake.is

// Curv UG : https://curv-labs.de/
// Submitted by Marvin Wiesner <Marvin@curv-labs.de>
curv.dev

// Customer OCI - Oracle Dyn https://cloud.oracle.com/home https://dyn.com/dns/
// Submitted by Gregory Drake <support@dyn.com>
// Note: This is intended to also include customer-oci.com due to wildcards implicitly including the current label
*.customer-oci.com
*.oci.customer-oci.com
*.ocp.customer-oci.com
*.ocs.customer-oci.com

// cyon GmbH : https://www.cyon.ch/
// Submitted by Dominic Luechinger <dol@cyon.ch>
cyon.link
cyon.site

// Danger Science Group: https://dangerscience.com/
// Submitted by Skylar MacDonald <skylar@dangerscience.com>
fnwk.site
folionetwork.site
platform0.app

// Daplie, Inc : https://daplie.com
// Submitted by AJ ONeal <aj@daplie.com>
daplie.me
localhost.daplie.me

// Datto, Inc. : https://www.datto.com/
// Submitted by Philipp Heckel <ph@datto.com>
dattolocal.com
dattorelay.com
dattoweb.com
mydatto.com
dattolocal.net
mydatto.net

// Dansk.net : http://www.dansk.net/
// Submitted by Anani Voule <digital@digital.co.dk>
biz.dk
co.dk
firm.dk
reg.dk
store.dk

// dappnode.io : https://dappnode.io/
// Submitted by Abel Boldu / DAppNode Team <community@dappnode.io>
dyndns.dappnode.io

// dapps.earth : https://dapps.earth/
// Submitted by Daniil Burdakov <icqkill@gmail.com>
*.dapps.earth
*.bzz.dapps.earth

// Dark, Inc. : https://darklang.com
// Submitted by Paul Biggar <ops@darklang.com>
builtwithdark.com

// DataDetect, LLC. : https://datadetect.com
// Submitted by Andrew Banchich <abanchich@sceven.com>
demo.datadetect.com
instance.datadetect.com

// Datawire, Inc : https://www.datawire.io
// Submitted by Richard Li <secalert@datawire.io>
edgestack.me

// DDNS5 : https://ddns5.com
// Submitted by Cameron Elliott <cameron@cameronelliott.com>
ddns5.com

// Debian : https://www.debian.org/
// Submitted by Peter Palfrader / Debian Sysadmin Team <dsa-publicsuffixlist@debian.org>
debian.net

// Deno Land Inc : https://deno.com/
// Submitted by Luca Casonato <hostmaster@deno.com>
deno.dev
deno-staging.dev

// deSEC : https://desec.io/
// Submitted by Peter Thomassen <peter@desec.io>
dedyn.io

// Diher Solutions : https://diher.solutions
// Submitted by Didi Hermawan <mail@diher.solutions>
*.rss.my.id
*.diher.solutions

// DNS Africa Ltd https://dns.business
// Submitted by Calvin Browne <calvin@dns.business>
jozi.biz

// DNShome : https://www.dnshome.de/
// Submitted by Norbert Auler <mail@dnshome.de>
dnshome.de

// DotArai : https://www.dotarai.com/
// Submitted by Atsadawat Netcharadsang <atsadawat@dotarai.co.th>
online.th
shop.th

// DrayTek Corp. : https://www.draytek.com/
// Submitted by Paul Fang <mis@draytek.com>
drayddns.com

// DreamCommerce : https://shoper.pl/
// Submitted by Konrad Kotarba <konrad.kotarba@dreamcommerce.com>
shoparena.pl

// DreamHost : http://www.dreamhost.com/
// Submitted by Andrew Farmer <andrew.farmer@dreamhost.com>
dreamhosters.com

// Drobo : http://www.drobo.com/
// Submitted by Ricardo Padilha <rpadilha@drobo.com>
mydrobo.com

// Drud Holdings, LLC. : https://www.drud.com/
// Submitted by Kevin Bridges <kevin@drud.com>
drud.io
drud.us

// DuckDNS : http://www.duckdns.org/
// Submitted by Richard Harper <richard@duckdns.org>
duckdns.org

// Bip : https://bip.sh
// Submitted by Joel Kennedy <joel@bip.sh>
bip.sh

// bitbridge.net : Submitted by Craig Welch, abeliidev@gmail.com
bitbridge.net

// dy.fi : http://dy.fi/
// Submitted by Heikki Hannikainen <hessu@hes.iki.fi>
dy.fi
tunk.org

// DynDNS.com : http://www.dyndns.com/services/dns/dyndns/
dyndns-at-home.com
dyndns-at-work.com
dyndns-blog.com
dyndns-free.com
dyndns-home.com
dyndns-ip.com
dyndns-mail.com
dyndns-office.com
dyndns-pics.com
dyndns-remote.com
dyndns-server.com
dyndns-web.com
dyndns-wiki.com
dyndns-work.com
dyndns.biz
dyndns.info
dyndns.org
dyndns.tv
at-band-camp.net
ath.cx
barrel-of-knowledge.info
barrell-of-knowledge.info
better-than.tv
blogdns.com
blogdns.net
blogdns.org
blogsite.org
boldlygoingnowhere.org
broke-it.net
buyshouses.net
cechire.com
dnsalias.com
dnsalias.net
dnsalias.org
dnsdojo.com
dnsdojo.net
dnsdojo.org
does-it.net
doesntexist.com
doesntexist.org
dontexist.com
dontexist.net
dontexist.org
doomdns.com
doomdns.org
dvrdns.org
dyn-o-saur.com
dynalias.com
dynalias.net
dynalias.org
dynathome.net
dyndns.ws
endofinternet.net
endofinternet.org
endoftheinternet.org
est-a-la-maison.com
est-a-la-masion.com
est-le-patron.com
est-mon-blogueur.com
for-better.biz
for-more.biz
for-our.info
for-some.biz
for-the.biz
forgot.her.name
forgot.his.name
from-ak.com
from-al.com
from-ar.com
from-az.net
from-ca.com
from-co.net
from-ct.com
from-dc.com
from-de.com
from-fl.com
from-ga.com
from-hi.com
from-ia.com
from-id.com
from-il.com
from-in.com
from-ks.com
from-ky.com
from-la.net
from-ma.com
from-md.com
from-me.org
from-mi.com
from-mn.com
from-mo.com
from-ms.com
from-mt.com
from-nc.com
from-nd.com
from-ne.com
from-nh.com
from-nj.com
from-nm.com
from-nv.com
from-ny.net
from-oh.com
from-ok.com
from-or.com
from-pa.com
from-pr.com
from-ri.com
from-sc.com
from-sd.com
from-tn.com
from-tx.com
from-ut.com
from-va.com
from-vt.com
from-wa.com
from-wi.com
from-wv.com
from-wy.com
ftpaccess.cc
fuettertdasnetz.de
game-host.org
game-server.cc
getmyip.com
gets-it.net
go.dyndns.org
gotdns.com
gotdns.org
groks-the.info
groks-this.info
ham-radio-op.net
here-for-more.info
hobby-site.com
hobby-site.org
home.dyndns.org
homedns.org
homeftp.net
homeftp.org
homeip.net
homelinux.com
homelinux.net
homelinux.org
homeunix.com
homeunix.net
homeunix.org
iamallama.com
in-the-band.net
is-a-anarchist.com
is-a-blogger.com
is-a-bookkeeper.com
is-a-bruinsfan.org
is-a-bulls-fan.com
is-a-candidate.org
is-a-caterer.com
is-a-celticsfan.org
is-a-chef.com
is-a-chef.net
is-a-chef.org
is-a-conservative.com
is-a-cpa.com
is-a-cubicle-slave.com
is-a-democrat.com
is-a-designer.com
is-a-doctor.com
is-a-financialadvisor.com
is-a-geek.com
is-a-geek.net
is-a-geek.org
is-a-green.com
is-a-guru.com
is-a-hard-worker.com
is-a-hunter.com
is-a-knight.org
is-a-landscaper.com
is-a-lawyer.com
is-a-liberal.com
is-a-libertarian.com
is-a-linux-user.org
is-a-llama.com
is-a-musician.com
is-a-nascarfan.com
is-a-nurse.com
is-a-painter.com
is-a-patsfan.org
is-a-personaltrainer.com
is-a-photographer.com
is-a-player.com
is-a-republican.com
is-a-rockstar.com
is-a-socialist.com
is-a-soxfan.org
is-a-student.com
is-a-teacher.com
is-a-techie.com
is-a-therapist.com
is-an-accountant.com
is-an-actor.com
is-an-actress.com
is-an-anarchist.com
is-an-artist.com
is-an-engineer.com
is-an-entertainer.com
is-by.us
is-certified.com
is-found.org
is-gone.com
is-into-anime.com
is-into-cars.com
is-into-cartoons.com
is-into-games.com
is-leet.com
is-lost.org
is-not-certified.com
is-saved.org
is-slick.com
is-uberleet.com
is-very-bad.org
is-very-evil.org
is-very-good.org
is-very-nice.org
is-very-sweet.org
is-with-theband.com
isa-geek.com
isa-geek.net
isa-geek.org
isa-hockeynut.com
issmarterthanyou.com
isteingeek.de
istmein.de
kicks-ass.net
kicks-ass.org
knowsitall.info
land-4-sale.us
lebtimnetz.de
leitungsen.de
likes-pie.com
likescandy.com
merseine.nu
mine.nu
misconfused.org
mypets.ws
myphotos.cc
neat-url.com
office-on-the.net
on-the-web.tv
podzone.net
podzone.org
readmyblog.org
saves-the-whales.com
scrapper-site.net
scrapping.cc
selfip.biz
selfip.com
selfip.info
selfip.net
selfip.org
sells-for-less.com
sells-for-u.com
sells-it.net
sellsyourhome.org
servebbs.com
servebbs.net
servebbs.org
serveftp.net
serveftp.org
servegame.org
shacknet.nu
simple-url.com
space-to-rent.com
stuff-4-sale.org
stuff-4-sale.us
teaches-yoga.com
thruhere.net
traeumtgerade.de
webhop.biz
webhop.info
webhop.net
webhop.org
worse-than.tv
writesthisblog.com

// ddnss.de : https://www.ddnss.de/
// Submitted by Robert Niedziela <webmaster@ddnss.de>
ddnss.de
dyn.ddnss.de
dyndns.ddnss.de
dyndns1.de
dyn-ip24.de
home-webserver.de
dyn.home-webserver.de
myhome-server.de
ddnss.org

// Definima : http://www.definima.com/
// Submitted by Maxence Bitterli <maxence@definima.com>
definima.net
definima.io

// DigitalOcean App Platform : https://www.digitalocean.com/products/app-platform/
// Submitted by Braxton Huggins <psl-maintainers@digitalocean.com>
ondigitalocean.app

// DigitalOcean Spaces : https://www.digitalocean.com/products/spaces/
// Submitted by Robin H. Johnson <psl-maintainers@digitalocean.com>
*.digitaloceanspaces.com

// dnstrace.pro : https://dnstrace.pro/
// Submitted by Chris Partridge <chris@partridge.tech>
bci.dnstrace.pro

// Dynu.com : https://www.dynu.com/
// Submitted by Sue Ye <sue@dynu.com>
ddnsfree.com
ddnsgeek.com
giize.com
gleeze.com
kozow.com
loseyourip.com
ooguy.com
theworkpc.com
casacam.net
dynu.net
accesscam.org
camdvr.org
freeddns.org
mywire.org
webredirect.org
myddns.rocks
blogsite.xyz

// dynv6 : https://dynv6.com
// Submitted by Dominik Menke <dom@digineo.de>
dynv6.net

// Ellucian : https://ellucian.com
// Submitted by Josue Colon <CloudOps-Network@ellucian.com>
elluciancrmadvance.com
elluciancrmadvise.com
elluciancrmrecruit.com

// E4YOU spol. s.r.o. : https://e4you.cz/
// Submitted by Vladimir Dudr <info@e4you.cz>
e4.cz

// eero : https://eero.com/
// Submitted by Yue Kang <eero-dynamic-dns@amazon.com>
eero.online
eero-stage.online

// Elementor : Elementor Ltd.
// Submitted by Anton Barkan <antonb@elementor.com>
elementor.cloud
elementor.cool

// En rootâ€½ : https://en-root.org
// Submitted by Emmanuel Raviart <emmanuel@raviart.com>
en-root.fr

// Enalean SAS: https://www.enalean.com
// Submitted by Thomas Cottier <thomas.cottier@enalean.com>
mytuleap.com
tuleap-partners.com

// ECG Robotics, Inc: https://ecgrobotics.org
// Submitted by <frc1533@ecgrobotics.org>
onred.one
staging.onred.one

// EU.org https://eu.org/
// Submitted by Pierre Beyssac <hostmaster@eu.org>
eu.org
al.eu.org
asso.eu.org
at.eu.org
au.eu.org
be.eu.org
bg.eu.org
ca.eu.org
cd.eu.org
ch.eu.org
cn.eu.org
cy.eu.org
cz.eu.org
de.eu.org
dk.eu.org
edu.eu.org
ee.eu.org
es.eu.org
fi.eu.org
fr.eu.org
gr.eu.org
hr.eu.org
hu.eu.org
ie.eu.org
il.eu.org
in.eu.org
int.eu.org
is.eu.org
it.eu.org
jp.eu.org
kr.eu.org
lt.eu.org
lu.eu.org
lv.eu.org
mc.eu.org
me.eu.org
mk.eu.org
mt.eu.org
my.eu.org
net.eu.org
ng.eu.org
nl.eu.org
no.eu.org
nz.eu.org
paris.eu.org
pl.eu.org
pt.eu.org
q-a.eu.org
ro.eu.org
ru.eu.org
se.eu.org
si.eu.org
sk.eu.org
tr.eu.org
uk.eu.org
us.eu.org

// Eurobyte : https://eurobyte.ru
// Submitted by Evgeniy Subbotin <e.subbotin@eurobyte.ru>
eurodir.ru

// Evennode : http://www.evennode.com/
// Submitted by Michal Kralik <support@evennode.com>
eu-1.evennode.com
eu-2.evennode.com
eu-3.evennode.com
eu-4.evennode.com
us-1.evennode.com
us-2.evennode.com
us-3.evennode.com
us-4.evennode.com

// eDirect Corp. : https://hosting.url.com.tw/
// Submitted by C.S. chang <cschang@corp.url.com.tw>
twmail.cc
twmail.net
twmail.org
mymailer.com.tw
url.tw

// Fabrica Technologies, Inc. : https://www.fabrica.dev/
// Submitted by Eric Jiang <eric@fabrica.dev>
onfabrica.com

// Facebook, Inc.
// Submitted by Peter Ruibal <public-suffix@fb.com>
apps.fbsbx.com

// FAITID : https://faitid.org/
// Submitted by Maxim Alzoba <tech.contact@faitid.org>
// https://www.flexireg.net/stat_info
ru.net
adygeya.ru
bashkiria.ru
bir.ru
cbg.ru
com.ru
dagestan.ru
grozny.ru
kalmykia.ru
kustanai.ru
marine.ru
mordovia.ru
msk.ru
mytis.ru
nalchik.ru
nov.ru
pyatigorsk.ru
spb.ru
vladikavkaz.ru
vladimir.ru
abkhazia.su
adygeya.su
aktyubinsk.su
arkhangelsk.su
armenia.su
ashgabad.su
azerbaijan.su
balashov.su
bashkiria.su
bryansk.su
bukhara.su
chimkent.su
dagestan.su
east-kazakhstan.su
exnet.su
georgia.su
grozny.su
ivanovo.su
jambyl.su
kalmykia.su
kaluga.su
karacol.su
karaganda.su
karelia.su
khakassia.su
krasnodar.su
kurgan.su
kustanai.su
lenug.su
mangyshlak.su
mordovia.su
msk.su
murmansk.su
nalchik.su
navoi.su
north-kazakhstan.su
nov.su
obninsk.su
penza.su
pokrovsk.su
sochi.su
spb.su
tashkent.su
termez.su
togliatti.su
troitsk.su
tselinograd.su
tula.su
tuva.su
vladikavkaz.su
vladimir.su
vologda.su

// Fancy Bits, LLC : http://getchannels.com
// Submitted by Aman Gupta <aman@getchannels.com>
channelsdvr.net
u.channelsdvr.net

// Fastly Inc. : http://www.fastly.com/
// Submitted by Fastly Security <security@fastly.com>
edgecompute.app
fastly-terrarium.com
fastlylb.net
map.fastlylb.net
freetls.fastly.net
map.fastly.net
a.prod.fastly.net
global.prod.fastly.net
a.ssl.fastly.net
b.ssl.fastly.net
global.ssl.fastly.net

// FASTVPS EESTI OU : https://fastvps.ru/
// Submitted by Likhachev Vasiliy <lihachev@fastvps.ru>
fastvps-server.com
fastvps.host
myfast.host
fastvps.site
myfast.space

// Fedora : https://fedoraproject.org/
// submitted by Patrick Uiterwijk <puiterwijk@fedoraproject.org>
fedorainfracloud.org
fedorapeople.org
cloud.fedoraproject.org
app.os.fedoraproject.org
app.os.stg.fedoraproject.org

// FearWorks Media Ltd. : https://fearworksmedia.co.uk
// submitted by Keith Fairley <domains@fearworksmedia.co.uk>
couk.me
ukco.me
conn.uk
copro.uk
hosp.uk

// Fermax : https://fermax.com/
// submitted by Koen Van Isterdael <k.vanisterdael@fermax.be>
mydobiss.com

// FH Muenster : https://www.fh-muenster.de
// Submitted by Robin Naundorf <r.naundorf@fh-muenster.de>
fh-muenster.io

// Filegear Inc. : https://www.filegear.com
// Submitted by Jason Zhu <jason@owtware.com>
filegear.me
filegear-au.me
filegear-de.me
filegear-gb.me
filegear-ie.me
filegear-jp.me
filegear-sg.me

// Firebase, Inc.
// Submitted by Chris Raynor <chris@firebase.com>
firebaseapp.com

// Firewebkit : https://www.firewebkit.com
// Submitted by Majid Qureshi <mqureshi@amrayn.com>
fireweb.app

// FLAP : https://www.flap.cloud
// Submitted by Louis Chemineau <louis@chmn.me>
flap.id

// fly.io: https://fly.io
// Submitted by Kurt Mackey <kurt@fly.io>
fly.dev
edgeapp.net
shw.io

// Flynn : https://flynn.io
// Submitted by Jonathan Rudenberg <jonathan@flynn.io>
flynnhosting.net

// Forgerock : https://www.forgerock.com
// Submitted by Roderick Parr <roderick.parr@forgerock.com>
forgeblocks.com
id.forgerock.io

// Framer : https://www.framer.com
// Submitted by Koen Rouwhorst <koenrh@framer.com>
framer.app
framercanvas.com

// Frusky MEDIA&PR : https://www.frusky.de
// Submitted by Victor Pupynin <hallo@frusky.de>
*.frusky.de

// RavPage : https://www.ravpage.co.il
// Submitted by Roni Horowitz <roni@responder.co.il>
ravpage.co.il

// Frederik Braun https://frederik-braun.com
// Submitted by Frederik Braun <fb@frederik-braun.com>
0e.vc

// Freebox : http://www.freebox.fr
// Submitted by Romain Fliedel <rfliedel@freebox.fr>
freebox-os.com
freeboxos.com
fbx-os.fr
fbxos.fr
freebox-os.fr
freeboxos.fr

// freedesktop.org : https://www.freedesktop.org
// Submitted by Daniel Stone <daniel@fooishbar.org>
freedesktop.org

// freemyip.com : https://freemyip.com
// Submitted by Cadence <contact@freemyip.com>
freemyip.com

// FunkFeuer - Verein zur FÃ¶rderung freier Netze : https://www.funkfeuer.at
// Submitted by Daniel A. Maierhofer <vorstand@funkfeuer.at>
wien.funkfeuer.at

// Futureweb OG : http://www.futureweb.at
// Submitted by Andreas Schnederle-Wagner <schnederle@futureweb.at>
*.futurecms.at
*.ex.futurecms.at
*.in.futurecms.at
futurehosting.at
futuremailing.at
*.ex.ortsinfo.at
*.kunden.ortsinfo.at
*.statics.cloud

// GDS : https://www.gov.uk/service-manual/operations/operating-servicegovuk-subdomains
// Submitted by David Illsley <david.illsley@digital.cabinet-office.gov.uk>
service.gov.uk

// Gehirn Inc. : https://www.gehirn.co.jp/
// Submitted by Kohei YOSHIDA <tech@gehirn.co.jp>
gehirn.ne.jp
usercontent.jp

// Gentlent, Inc. : https://www.gentlent.com
// Submitted by Tom Klein <tom@gentlent.com>
gentapps.com
gentlentapis.com
lab.ms
cdn-edges.net

// Ghost Foundation : https://ghost.org
// Submitted by Matt Hanley <security@ghost.org>
ghost.io

// GignoSystemJapan: http://gsj.bz
// Submitted by GignoSystemJapan <kakutou-ec@gsj.bz>
gsj.bz

// GitHub, Inc.
// Submitted by Patrick Toomey <security@github.com>
githubusercontent.com
githubpreview.dev
github.io

// GitLab, Inc.
// Submitted by Alex Hanselka <alex@gitlab.com>
gitlab.io

// Gitplac.si - https://gitplac.si
// Submitted by AljaÅ¾ Starc <me@aljaxus.eu>
gitapp.si
gitpage.si

// Glitch, Inc : https://glitch.com
// Submitted by Mads Hartmann <mads@glitch.com>
glitch.me

// Global NOG Alliance : https://nogalliance.org/
// Submitted by Sander Steffann <sander@nogalliance.org>
nog.community

// Globe Hosting SRL : https://www.globehosting.com/
// Submitted by Gavin Brown <gavin.brown@centralnic.com>
co.ro
shop.ro

// GMO Pepabo, Inc. : https://pepabo.com/
// Submitted by dojineko <admin@pepabo.com>
lolipop.io

// GOV.UK Platform as a Service : https://www.cloud.service.gov.uk/
// Submitted by Tom Whitwell <gov-uk-paas-support@digital.cabinet-office.gov.uk>
cloudapps.digital
london.cloudapps.digital

// GOV.UK Pay : https://www.payments.service.gov.uk/
// Submitted by Richard Baker <richard.baker@digital.cabinet-office.gov.uk>
pymnt.uk

// UKHomeOffice : https://www.gov.uk/government/organisations/home-office
// Submitted by Jon Shanks <jon.shanks@digital.homeoffice.gov.uk>
homeoffice.gov.uk

// GlobeHosting, Inc.
// Submitted by Zoltan Egresi <egresi@globehosting.com>
ro.im

// GoIP DNS Services : http://www.goip.de
// Submitted by Christian Poulter <milchstrasse@goip.de>
goip.de

// Google, Inc.
// Submitted by Eduardo Vela <evn@google.com>
run.app
a.run.app
web.app
*.0emm.com
appspot.com
*.r.appspot.com
codespot.com
googleapis.com
googlecode.com
pagespeedmobilizer.com
publishproxy.com
withgoogle.com
withyoutube.com
*.gateway.dev
cloud.goog
translate.goog
*.usercontent.goog
cloudfunctions.net
blogspot.ae
blogspot.al
blogspot.am
blogspot.ba
blogspot.be
blogspot.bg
blogspot.bj
blogspot.ca
blogspot.cf
blogspot.ch
blogspot.cl
blogspot.co.at
blogspot.co.id
blogspot.co.il
blogspot.co.ke
blogspot.co.nz
blogspot.co.uk
blogspot.co.za
blogspot.com
blogspot.com.ar
blogspot.com.au
blogspot.com.br
blogspot.com.by
blogspot.com.co
blogspot.com.cy
blogspot.com.ee
blogspot.com.eg
blogspot.com.es
blogspot.com.mt
blogspot.com.ng
blogspot.com.tr
blogspot.com.uy
blogspot.cv
blogspot.cz
blogspot.de
blogspot.dk
blogspot.fi
blogspot.fr
blogspot.gr
blogspot.hk
blogspot.hr
blogspot.hu
blogspot.ie
blogspot.in
blogspot.is
blogspot.it
blogspot.jp
blogspot.kr
blogspot.li
blogspot.lt
blogspot.lu
blogspot.md
blogspot.mk
blogspot.mr
blogspot.mx
blogspot.my
blogspot.nl
blogspot.no
blogspot.pe
blogspot.pt
blogspot.qa
blogspot.re
blogspot.ro
blogspot.rs
blogspot.ru
blogspot.se
blogspot.sg
blogspot.si
blogspot.sk
blogspot.sn
blogspot.td
blogspot.tw
blogspot.ug
blogspot.vn

// Goupile : https://goupile.fr
// Submitted by Niels Martignene <hello@goupile.fr>
goupile.fr

// Group 53, LLC : https://www.group53.com
// Submitted by Tyler Todd <noc@nova53.net>
awsmppl.com

// GÃ¼nstigBestellen : https://gÃ¼nstigbestellen.de
// Submitted by Furkan Akkoc <info@hendelzon.de>
gÃ¼nstigbestellen.de
gÃ¼nstigliefern.de

// Hakaran group: http://hakaran.cz
// Submited by Arseniy Sokolov <security@hakaran.cz>
fin.ci
free.hr
caa.li
ua.rs
conf.se

// Handshake : https://handshake.org
// Submitted by Mike Damm <md@md.vc>
hs.zone
hs.run

// Hashbang : https://hashbang.sh
hashbang.sh

// Hasura : https://hasura.io
// Submitted by Shahidh K Muhammed <shahidh@hasura.io>
hasura.app
hasura-app.io

// Heilbronn University of Applied Sciences - Faculty Informatics (GitLab Pages): https://www.hs-heilbronn.de
// Submitted by Richard Zowalla <mi-admin@hs-heilbronn.de>
pages.it.hs-heilbronn.de

// Hepforge : https://www.hepforge.org
// Submitted by David Grellscheid <admin@hepforge.org>
hepforge.org

// Heroku : https://www.heroku.com/
// Submitted by Tom Maher <tmaher@heroku.com>
herokuapp.com
herokussl.com

// Hibernating Rhinos
// Submitted by Oren Eini <oren@ravendb.net>
myravendb.com
ravendb.community
ravendb.me
development.run
ravendb.run

// home.pl S.A.: https://home.pl
// Submited by Krzysztof Wolski <krzysztof.wolski@home.eu>
homesklep.pl

// Hong Kong Productivity Council: https://www.hkpc.org/
// Submitted by SECaaS Team <summchan@hkpc.org>
secaas.hk

// HOSTBIP REGISTRY : https://www.hostbip.com/
// Submitted by Atanunu Igbunuroghene <publicsuffixlist@hostbip.com>
orx.biz
biz.gl
col.ng
firm.ng
gen.ng
ltd.ng
ngo.ng
edu.scot
sch.so
org.yt

// HostyHosting (hostyhosting.com)
hostyhosting.io

// HÃ¤kkinen.fi
// Submitted by Eero HÃ¤kkinen <Eero+psl@HÃ¤kkinen.fi>
hÃ¤kkinen.fi

// Ici la Lune : http://www.icilalune.com/
// Submitted by Simon Morvan <simon@icilalune.com>
*.moonscale.io
moonscale.net

// iki.fi
// Submitted by Hannu Aronsson <haa@iki.fi>
iki.fi

// Impertrix Solutions : <https://impertrixcdn.com>
// Submitted by Zhixiang Zhao <csuite@impertrix.com>
impertrixcdn.com
impertrix.com

// Incsub, LLC: https://incsub.com/
// Submitted by Aaron Edwards <sysadmins@incsub.com>
smushcdn.com
wphostedmail.com
wpmucdn.com
tempurl.host
wpmudev.host

// Individual Network Berlin e.V. : https://www.in-berlin.de/
// Submitted by Christian Seitz <chris@in-berlin.de>
dyn-berlin.de
in-berlin.de
in-brb.de
in-butter.de
in-dsl.de
in-dsl.net
in-dsl.org
in-vpn.de
in-vpn.net
in-vpn.org

// info.at : http://www.info.at/
biz.at
info.at

// info.cx : http://info.cx
// Submitted by Jacob Slater <whois@igloo.to>
info.cx

// Interlegis : http://www.interlegis.leg.br
// Submitted by Gabriel Ferreira <registrobr@interlegis.leg.br>
ac.leg.br
al.leg.br
am.leg.br
ap.leg.br
ba.leg.br
ce.leg.br
df.leg.br
es.leg.br
go.leg.br
ma.leg.br
mg.leg.br
ms.leg.br
mt.leg.br
pa.leg.br
pb.leg.br
pe.leg.br
pi.leg.br
pr.leg.br
rj.leg.br
rn.leg.br
ro.leg.br
rr.leg.br
rs.leg.br
sc.leg.br
se.leg.br
sp.leg.br
to.leg.br

// intermetrics GmbH : https://pixolino.com/
// Submitted by Wolfgang Schwarz <admin@intermetrics.de>
pixolino.com

// Internet-Pro, LLP: https://netangels.ru/
// Submited by Vasiliy Sheredeko <piphon@gmail.com>
na4u.ru

// iopsys software solutions AB : https://iopsys.eu/
// Submitted by Roman Azarenko <roman.azarenko@iopsys.eu>
iopsys.se

// IPiFony Systems, Inc. : https://www.ipifony.com/
// Submitted by Matthew Hardeman <mhardeman@ipifony.com>
ipifony.net

// IServ GmbH : https://iserv.eu
// Submitted by Kim-Alexander Brodowski <info@iserv.eu>
mein-iserv.de
schulserver.de
test-iserv.de
iserv.dev

// I-O DATA DEVICE, INC. : http://www.iodata.com/
// Submitted by Yuji Minagawa <domains-admin@iodata.jp>
iobb.net

// Jelastic, Inc. : https://jelastic.com/
// Submited by Ihor Kolodyuk <ik@jelastic.com>
mel.cloudlets.com.au
cloud.interhostsolutions.be
users.scale.virtualcloud.com.br
mycloud.by
alp1.ae.flow.ch
appengine.flow.ch
es-1.axarnet.cloud
diadem.cloud
vip.jelastic.cloud
jele.cloud
it1.eur.aruba.jenv-aruba.cloud
it1.jenv-aruba.cloud
keliweb.cloud
cs.keliweb.cloud
oxa.cloud
tn.oxa.cloud
uk.oxa.cloud
primetel.cloud
uk.primetel.cloud
ca.reclaim.cloud
uk.reclaim.cloud
us.reclaim.cloud
ch.trendhosting.cloud
de.trendhosting.cloud
jele.club
amscompute.com
clicketcloud.com
dopaas.com
hidora.com
paas.hosted-by-previder.com
rag-cloud.hosteur.com
rag-cloud-ch.hosteur.com
jcloud.ik-server.com
jcloud-ver-jpc.ik-server.com
demo.jelastic.com
kilatiron.com
paas.massivegrid.com
jed.wafaicloud.com
lon.wafaicloud.com
ryd.wafaicloud.com
j.scaleforce.com.cy
jelastic.dogado.eu
fi.cloudplatform.fi
demo.datacenter.fi
paas.datacenter.fi
jele.host
mircloud.host
paas.beebyte.io
sekd1.beebyteapp.io
jele.io
cloud-fr1.unispace.io
jc.neen.it
cloud.jelastic.open.tim.it
jcloud.kz
upaas.kazteleport.kz
cloudjiffy.net
fra1-de.cloudjiffy.net
west1-us.cloudjiffy.net
jls-sto1.elastx.net
jls-sto2.elastx.net
jls-sto3.elastx.net
faststacks.net
fr-1.paas.massivegrid.net
lon-1.paas.massivegrid.net
lon-2.paas.massivegrid.net
ny-1.paas.massivegrid.net
ny-2.paas.massivegrid.net
sg-1.paas.massivegrid.net
jelastic.saveincloud.net
nordeste-idc.saveincloud.net
j.scaleforce.net
jelastic.tsukaeru.net
sdscloud.pl
unicloud.pl
mircloud.ru
jelastic.regruhosting.ru
enscaled.sg
jele.site
jelastic.team
orangecloud.tn
j.layershift.co.uk
phx.enscaled.us
mircloud.us

// Jino : https://www.jino.ru
// Submitted by Sergey Ulyashin <ulyashin@jino.ru>
myjino.ru
*.hosting.myjino.ru
*.landing.myjino.ru
*.spectrum.myjino.ru
*.vps.myjino.ru

// Jotelulu S.L. : https://jotelulu.com
// Submitted by Daniel FariÃ±a <ingenieria@jotelulu.com>
jotelulu.cloud

// Joyent : https://www.joyent.com/
// Submitted by Brian Bennett <brian.bennett@joyent.com>
*.triton.zone
*.cns.joyent.com

// JS.ORG : http://dns.js.org
// Submitted by Stefan Keim <admin@js.org>
js.org

// KaasHosting : http://www.kaashosting.nl/
// Submitted by Wouter Bakker <hostmaster@kaashosting.nl>
kaas.gg
khplay.nl

// Keyweb AG : https://www.keyweb.de
// Submitted by Martin Dannehl <postmaster@keymachine.de>
keymachine.de

// KingHost : https://king.host
// Submitted by Felipe Keller Braz <felipebraz@kinghost.com.br>
kinghost.net
uni5.net

// KnightPoint Systems, LLC : http://www.knightpoint.com/
// Submitted by Roy Keene <rkeene@knightpoint.com>
knightpoint.systems

// KUROKU LTD : https://kuroku.ltd/
// Submitted by DisposaBoy <security@oya.to>
oya.to

// Katholieke Universiteit Leuven: https://www.kuleuven.be
// Submitted by Abuse KU Leuven <abuse@kuleuven.be>
kuleuven.cloud
ezproxy.kuleuven.be

// .KRD : http://nic.krd/data/krd/Registration%20Policy.pdf
co.krd
edu.krd

// Krellian Ltd. : https://krellian.com
// Submitted by Ben Francis <ben@krellian.com>
krellian.net
webthings.io

// LCube - Professional hosting e.K. : https://www.lcube-webhosting.de
// Submitted by Lars Laehn <info@lcube.de>
git-repos.de
lcube-server.de
svn-repos.de

// Leadpages : https://www.leadpages.net
// Submitted by Greg Dallavalle <domains@leadpages.net>
leadpages.co
lpages.co
lpusercontent.com

// Lelux.fi : https://lelux.fi/
// Submitted by Lelux Admin <publisuffix@lelux.site>
lelux.site

// Lifetime Hosting : https://Lifetime.Hosting/
// Submitted by Mike Fillator <support@lifetime.hosting>
co.business
co.education
co.events
co.financial
co.network
co.place
co.technology

// Lightmaker Property Manager, Inc. : https://app.lmpm.com/
// Submitted by Greg Holland <greg.holland@lmpm.com>
app.lmpm.com

// linkyard ldt: https://www.linkyard.ch/
// Submitted by Mario Siegenthaler <mario.siegenthaler@linkyard.ch>
linkyard.cloud
linkyard-cloud.ch

// Linode : https://linode.com
// Submitted by <security@linode.com>
members.linode.com
*.nodebalancer.linode.com
*.linodeobjects.com
ip.linodeusercontent.com

// LiquidNet Ltd : http://www.liquidnetlimited.com/
// Submitted by Victor Velchev <admin@liquidnetlimited.com>
we.bs

// localzone.xyz
// Submitted by Kenny Niehage <hello@yahe.sh>
localzone.xyz

// Log'in Line : https://www.loginline.com/
// Submitted by RÃ©mi Mach <remi.mach@loginline.com>
loginline.app
loginline.dev
loginline.io
loginline.services
loginline.site

// Lokalized : https://lokalized.nl
// Submitted by Noah Taheij <noah@lokalized.nl>
servers.run

// LÃµhmus Family, The
// Submitted by Heiki LÃµhmus <hostmaster at lohmus dot me>
lohmus.me

// LubMAN UMCS Sp. z o.o : https://lubman.pl/
// Submitted by Ireneusz Maliszewski <ireneusz.maliszewski@lubman.pl>
krasnik.pl
leczna.pl
lubartow.pl
lublin.pl
poniatowa.pl
swidnik.pl

// Lug.org.uk : https://lug.org.uk
// Submitted by Jon Spriggs <admin@lug.org.uk>
glug.org.uk
lug.org.uk
lugs.org.uk

// Lukanet Ltd : https://lukanet.com
// Submitted by Anton Avramov <register@lukanet.com>
barsy.bg
barsy.co.uk
barsyonline.co.uk
barsycenter.com
barsyonline.com
barsy.club
barsy.de
barsy.eu
barsy.in
barsy.info
barsy.io
barsy.me
barsy.menu
barsy.mobi
barsy.net
barsy.online
barsy.org
barsy.pro
barsy.pub
barsy.ro
barsy.shop
barsy.site
barsy.support
barsy.uk

// Magento Commerce
// Submitted by Damien Tournoud <dtournoud@magento.cloud>
*.magentosite.cloud

// May First - People Link : https://mayfirst.org/
// Submitted by Jamie McClelland <info@mayfirst.org>
mayfirst.info
mayfirst.org

// Mail.Ru Group : https://hb.cldmail.ru
// Submitted by Ilya Zaretskiy <zaretskiy@corp.mail.ru>
hb.cldmail.ru

// Mail Transfer Platform : https://www.neupeer.com
// Submitted by Li Hui <lihui@neupeer.com>
cn.vu

// Maze Play: https://www.mazeplay.com
// Submitted by Adam Humpherys <adam@mws.dev>
mazeplay.com

// mcpe.me : https://mcpe.me
// Submitted by Noa Heyl <hi@noa.dev>
mcpe.me

// McHost : https://mchost.ru
// Submitted by Evgeniy Subbotin <e.subbotin@mchost.ru>
mcdir.me
mcdir.ru
mcpre.ru
vps.mcdir.ru

// Mediatech : https://mediatech.by
// Submitted by Evgeniy Kozhuhovskiy <ugenk@mediatech.by>
mediatech.by
mediatech.dev

// Medicom Health : https://medicomhealth.com
// Submitted by Michael Olson <molson@medicomhealth.com>
hra.health

// Memset hosting : https://www.memset.com
// Submitted by Tom Whitwell <domains@memset.com>
miniserver.com
memset.net

// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/
// Submitted by ZdenÄ›k Å ustr <zdenek.sustr@cesnet.cz>
*.cloud.metacentrum.cz
custom.metacentrum.cz

// MetaCentrum, CESNET z.s.p.o. : https://www.metacentrum.cz/en/
// Submitted by Radim JanÄ�a <janca@cesnet.cz>
flt.cloud.muni.cz
usr.cloud.muni.cz

// Meteor Development Group : https://www.meteor.com/hosting
// Submitted by Pierre Carrier <pierre@meteor.com>
meteorapp.com
eu.meteorapp.com

// Michau Enterprises Limited : http://www.co.pl/
co.pl

// Microsoft Corporation : http://microsoft.com
// Submitted by Mitch Webster <miwebst@microsoft.com>
*.azurecontainer.io
azurewebsites.net
azure-mobile.net
cloudapp.net
azurestaticapps.net
centralus.azurestaticapps.net
eastasia.azurestaticapps.net
eastus2.azurestaticapps.net
westeurope.azurestaticapps.net
westus2.azurestaticapps.net

// minion.systems : http://minion.systems
// Submitted by Robert BÃ¶ttinger <r@minion.systems>
csx.cc

// Mintere : https://mintere.com/
// Submitted by Ben Aubin <security@mintere.com>
mintere.site

// MobileEducation, LLC : https://joinforte.com
// Submitted by Grayson Martin <grayson.martin@mobileeducation.us>
forte.id

// Mozilla Corporation : https://mozilla.com
// Submitted by Ben Francis <bfrancis@mozilla.com>
mozilla-iot.org

// Mozilla Foundation : https://mozilla.org/
// Submitted by glob <glob@mozilla.com>
bmoattachments.org

// MSK-IX : https://www.msk-ix.ru/
// Submitted by Khannanov Roman <r.khannanov@msk-ix.ru>
net.ru
org.ru
pp.ru

// Mythic Beasts : https://www.mythic-beasts.com
// Submitted by Paul Cammish <kelduum@mythic-beasts.com>
hostedpi.com
customer.mythic-beasts.com
caracal.mythic-beasts.com
fentiger.mythic-beasts.com
lynx.mythic-beasts.com
ocelot.mythic-beasts.com
oncilla.mythic-beasts.com
onza.mythic-beasts.com
sphinx.mythic-beasts.com
vs.mythic-beasts.com
x.mythic-beasts.com
yali.mythic-beasts.com
cust.retrosnub.co.uk

// Nabu Casa : https://www.nabucasa.com
// Submitted by Paulus Schoutsen <infra@nabucasa.com>
ui.nabu.casa

// Names.of.London : https://names.of.london/
// Submitted by James Stevens <registry[at]names.of.london> or <publiclist[at]jrcs.net>
pony.club
of.fashion
in.london
of.london
from.marketing
with.marketing
for.men
repair.men
and.mom
for.mom
for.one
under.one
for.sale
that.win
from.work
to.work

// Netlify : https://www.netlify.com
// Submitted by Jessica Parsons <jessica@netlify.com>
netlify.app

// Neustar Inc.
// Submitted by Trung Tran <Trung.Tran@neustar.biz>
4u.com

// ngrok : https://ngrok.com/
// Submitted by Alan Shreve <alan@ngrok.com>
ngrok.io

// Nimbus Hosting Ltd. : https://www.nimbushosting.co.uk/
// Submitted by Nicholas Ford <nick@nimbushosting.co.uk>
nh-serv.co.uk

// NFSN, Inc. : https://www.NearlyFreeSpeech.NET/
// Submitted by Jeff Wheelhouse <support@nearlyfreespeech.net>
nfshost.com

// Noop : https://noop.app
// Submitted by Nathaniel Schweinberg <noop@rearc.io>
*.developer.app
noop.app

// Northflank Ltd. : https://northflank.com/
// Submitted by Marco Suter <marco@northflank.com>
*.northflank.app
*.code.run

// Noticeable : https://noticeable.io
// Submitted by Laurent Pellegrino <security@noticeable.io>
noticeable.news

// Now-DNS : https://now-dns.com
// Submitted by Steve Russell <steve@now-dns.com>
dnsking.ch
mypi.co
n4t.co
001www.com
ddnslive.com
myiphost.com
forumz.info
16-b.it
32-b.it
64-b.it
soundcast.me
tcp4.me
dnsup.net
hicam.net
now-dns.net
ownip.net
vpndns.net
dynserv.org
now-dns.org
x443.pw
now-dns.top
ntdll.top
freeddns.us
crafting.xyz
zapto.xyz

// nsupdate.info : https://www.nsupdate.info/
// Submitted by Thomas Waldmann <info@nsupdate.info>
nsupdate.info
nerdpol.ovh

// No-IP.com : https://noip.com/
// Submitted by Deven Reza <publicsuffixlist@noip.com>
blogsyte.com
brasilia.me
cable-modem.org
ciscofreak.com
collegefan.org
couchpotatofries.org
damnserver.com
ddns.me
ditchyourip.com
dnsfor.me
dnsiskinky.com
dvrcam.info
dynns.com
eating-organic.net
fantasyleague.cc
geekgalaxy.com
golffan.us
health-carereform.com
homesecuritymac.com
homesecuritypc.com
hopto.me
ilovecollege.info
loginto.me
mlbfan.org
mmafan.biz
myactivedirectory.com
mydissent.net
myeffect.net
mymediapc.net
mypsx.net
mysecuritycamera.com
mysecuritycamera.net
mysecuritycamera.org
net-freaks.com
nflfan.org
nhlfan.net
no-ip.ca
no-ip.co.uk
no-ip.net
noip.us
onthewifi.com
pgafan.net
point2this.com
pointto.us
privatizehealthinsurance.net
quicksytes.com
read-books.org
securitytactics.com
serveexchange.com
servehumour.com
servep2p.com
servesarcasm.com
stufftoread.com
ufcfan.org
unusualperson.com
workisboring.com
3utilities.com
bounceme.net
ddns.net
ddnsking.com
gotdns.ch
hopto.org
myftp.biz
myftp.org
myvnc.com
no-ip.biz
no-ip.info
no-ip.org
noip.me
redirectme.net
servebeer.com
serveblog.net
servecounterstrike.com
serveftp.com
servegame.com
servehalflife.com
servehttp.com
serveirc.com
serveminecraft.net
servemp3.com
servepics.com
servequake.com
sytes.net
webhop.me
zapto.org

// NodeArt : https://nodeart.io
// Submitted by Konstantin Nosov <Nosov@nodeart.io>
stage.nodeart.io

// Nodum B.V. : https://nodum.io/
// Submitted by Wietse Wind <hello+publicsuffixlist@nodum.io>
nodum.co
nodum.io

// Nucleos Inc. : https://nucleos.com
// Submitted by Piotr Zduniak <piotr@nucleos.com>
pcloud.host

// NYC.mn : http://www.information.nyc.mn
// Submitted by Matthew Brown <mattbrown@nyc.mn>
nyc.mn

// Observable, Inc. : https://observablehq.com
// Submitted by Mike Bostock <dns@observablehq.com>
static.observableusercontent.com

// Octopodal Solutions, LLC. : https://ulterius.io/
// Submitted by Andrew Sampson <andrew@ulterius.io>
cya.gg

// OMG.LOL : <https://omg.lol>
// Submitted by Adam Newbold <adam@omg.lol>
omg.lol

// Omnibond Systems, LLC. : https://www.omnibond.com
// Submitted by Cole Estep <cole@omnibond.com>
cloudycluster.net

// OmniWe Limited: https://omniwe.com
// Submitted by Vicary Archangel <vicary@omniwe.com>
omniwe.site

// One.com: https://www.one.com/
// Submitted by Jacob Bunk Nielsen <jbn@one.com>
service.one

// One Fold Media : http://www.onefoldmedia.com/
// Submitted by Eddie Jones <eddie@onefoldmedia.com>
nid.io

// Open Social : https://www.getopensocial.com/
// Submitted by Alexander Varwijk <security@getopensocial.com>
opensocial.site

// OpenCraft GmbH : http://opencraft.com/
// Submitted by Sven Marnach <sven@opencraft.com>
opencraft.hosting

// OpenResearch GmbH: https://openresearch.com/
// Submitted by Philipp Schmid <ops@openresearch.com>
orsites.com

// Opera Software, A.S.A.
// Submitted by Yngve Pettersen <yngve@opera.com>
operaunite.com

// Oursky Limited : https://authgear.com/, https://skygear.io/
// Submited by Authgear Team <hello@authgear.com>, Skygear Developer <hello@skygear.io>
authgear-staging.com
authgearapps.com
skygearapp.com

// OutSystems
// Submitted by Duarte Santos <domain-admin@outsystemscloud.com>
outsystemscloud.com

// OVHcloud: https://ovhcloud.com
// Submitted by Vincent CassÃ© <vincent.casse@ovhcloud.com>
*.webpaas.ovh.net
*.hosting.ovh.net

// OwnProvider GmbH: http://www.ownprovider.com
// Submitted by Jan Moennich <jan.moennich@ownprovider.com>
ownprovider.com
own.pm

// OwO : https://whats-th.is/
// Submitted by Dean Sheather <dean@deansheather.com>
*.owo.codes

// OX : http://www.ox.rs
// Submitted by Adam Grand <webmaster@mail.ox.rs>
ox.rs

// oy.lc
// Submitted by Charly Coste <changaco@changaco.oy.lc>
oy.lc

// Pagefog : https://pagefog.com/
// Submitted by Derek Myers <derek@pagefog.com>
pgfog.com

// Pagefront : https://www.pagefronthq.com/
// Submitted by Jason Kriss <jason@pagefronthq.com>
pagefrontapp.com

// PageXL : https://pagexl.com
// Submitted by Yann Guichard <yann@pagexl.com>
pagexl.com

// Paywhirl, Inc : https://paywhirl.com/
// Submitted by Daniel Netzer <dan@paywhirl.com>
*.paywhirl.com

// pcarrier.ca Software Inc: https://pcarrier.ca/
// Submitted by Pierre Carrier <pc@rrier.ca>
bar0.net
bar1.net
bar2.net
rdv.to

// .pl domains (grandfathered)
art.pl
gliwice.pl
krakow.pl
poznan.pl
wroc.pl
zakopane.pl

// Pantheon Systems, Inc. : https://pantheon.io/
// Submitted by Gary Dylina <gary@pantheon.io>
pantheonsite.io
gotpantheon.com

// Peplink | Pepwave : http://peplink.com/
// Submitted by Steve Leung <steveleung@peplink.com>
mypep.link

// Perspecta : https://perspecta.com/
// Submitted by Kenneth Van Alstyne <kvanalstyne@perspecta.com>
perspecta.cloud

// PE Ulyanov Kirill Sergeevich : https://airy.host
// Submitted by Kirill Ulyanov <k.ulyanov@airy.host>
lk3.ru

// Planet-Work : https://www.planet-work.com/
// Submitted by FrÃ©dÃ©ric VANNIÃˆRE <f.vanniere@planet-work.com>
on-web.fr

// Platform.sh : https://platform.sh
// Submitted by Nikola Kotur <nikola@platform.sh>
bc.platform.sh
ent.platform.sh
eu.platform.sh
us.platform.sh
*.platformsh.site
*.tst.site

// Platter: https://platter.dev
// Submitted by Patrick Flor <patrick@platter.dev>
platter-app.com
platter-app.dev
platterp.us

// Plesk : https://www.plesk.com/
// Submitted by Anton Akhtyamov <program-managers@plesk.com>
pdns.page
plesk.page
pleskns.com

// Port53 : https://port53.io/
// Submitted by Maximilian Schieder <maxi@zeug.co>
dyn53.io

// Positive Codes Technology Company : http://co.bn/faq.html
// Submitted by Zulfais <pc@co.bn>
co.bn

// Postman, Inc : https://postman.com
// Submitted by Rahul Dhawan <security@postman.com>
postman-echo.com
pstmn.io
mock.pstmn.io
httpbin.org

//prequalifyme.today : https://prequalifyme.today
//Submitted by DeepakTiwari deepak@ivylead.io
prequalifyme.today

// prgmr.com : https://prgmr.com/
// Submitted by Sarah Newman <owner@prgmr.com>
xen.prgmr.com

// priv.at : http://www.nic.priv.at/
// Submitted by registry <lendl@nic.at>
priv.at

// privacytools.io : https://www.privacytools.io/
// Submitted by Jonah Aragon <jonah@privacytools.io>
prvcy.page

// Protocol Labs : https://protocol.ai/
// Submitted by Michael Burns <noc@protocol.ai>
*.dweb.link

// Protonet GmbH : http://protonet.io
// Submitted by Martin Meier <admin@protonet.io>
protonet.io

// Publication Presse Communication SARL : https://ppcom.fr
// Submitted by Yaacov Akiba Slama <admin@chirurgiens-dentistes-en-france.fr>
chirurgiens-dentistes-en-france.fr
byen.site

// pubtls.org: https://www.pubtls.org
// Submitted by Kor Nielsen <kor@pubtls.org>
pubtls.org

// PythonAnywhere LLP: https://www.pythonanywhere.com
// Submitted by Giles Thomas <giles@pythonanywhere.com>
pythonanywhere.com
eu.pythonanywhere.com

// QOTO, Org.
// Submitted by Jeffrey Phillips Freeman <jeffrey.freeman@qoto.org>
qoto.io

// Qualifio : https://qualifio.com/
// Submitted by Xavier De Cock <xdecock@gmail.com>
qualifioapp.com

// QuickBackend: https://www.quickbackend.com
// Submitted by Dani Biro <dani@pymet.com>
qbuser.com

// Rad Web Hosting: https://radwebhosting.com
// Submitted by Scott Claeys <s.claeys@radwebhosting.com>
cloudsite.builders

// Redgate Software: https://red-gate.com
// Submitted by Andrew Farries <andrew.farries@red-gate.com>
instances.spawn.cc

// Redstar Consultants : https://www.redstarconsultants.com/
// Submitted by Jons Slemmer <jons@redstarconsultants.com>
instantcloud.cn

// Russian Academy of Sciences
// Submitted by Tech Support <support@rasnet.ru>
ras.ru

// QA2
// Submitted by Daniel Dent (https://www.danieldent.com/)
qa2.com

// QCX
// Submitted by Cassandra Beelen <cassandra@beelen.one>
qcx.io
*.sys.qcx.io

// QNAP System Inc : https://www.qnap.com
// Submitted by Nick Chang <nickchang@qnap.com>
dev-myqnapcloud.com
alpha-myqnapcloud.com
myqnapcloud.com

// Quip : https://quip.com
// Submitted by Patrick Linehan <plinehan@quip.com>
*.quipelements.com

// Qutheory LLC : http://qutheory.io
// Submitted by Jonas Schwartz <jonas@qutheory.io>
vapor.cloud
vaporcloud.io

// Rackmaze LLC : https://www.rackmaze.com
// Submitted by Kirill Pertsev <kika@rackmaze.com>
rackmaze.com
rackmaze.net

// Rakuten Games, Inc : https://dev.viberplay.io
// Submitted by Joshua Zhang <public-suffix@rgames.jp>
g.vbrplsbx.io

// Rancher Labs, Inc : https://rancher.com
// Submitted by Vincent Fiduccia <domains@rancher.com>
*.on-k3s.io
*.on-rancher.cloud
*.on-rio.io

// Read The Docs, Inc : https://www.readthedocs.org
// Submitted by David Fischer <team@readthedocs.org>
readthedocs.io

// Red Hat, Inc. OpenShift : https://openshift.redhat.com/
// Submitted by Tim Kramer <tkramer@rhcloud.com>
rhcloud.com

// Render : https://render.com
// Submitted by Anurag Goel <dev@render.com>
app.render.com
onrender.com

// Repl.it : https://repl.it
// Submitted by Mason Clayton <mason@repl.it>
repl.co
id.repl.co
repl.run

// Resin.io : https://resin.io
// Submitted by Tim Perry <tim@resin.io>
resindevice.io
devices.resinstaging.io

// RethinkDB : https://www.rethinkdb.com/
// Submitted by Chris Kastorff <info@rethinkdb.com>
hzc.io

// Revitalised Limited : http://www.revitalised.co.uk
// Submitted by Jack Price <jack@revitalised.co.uk>
wellbeingzone.eu
wellbeingzone.co.uk

// Rico Developments Limited : https://adimo.co
// Submitted by Colin Brown <hello@adimo.co>
adimo.co.uk

// Riseup Networks : https://riseup.net
// Submitted by Micah Anderson <micah@riseup.net>
itcouldbewor.se

// Rochester Institute of Technology : http://www.rit.edu/
// Submitted by Jennifer Herting <jchits@rit.edu>
git-pages.rit.edu

// Rusnames Limited: http://rusnames.ru/
// Submitted by Sergey Zotov <admin@rusnames.ru>
Ð±Ð¸Ð·.Ñ€ÑƒÑ�
ÐºÐ¾Ð¼.Ñ€ÑƒÑ�
ÐºÑ€Ñ‹Ð¼.Ñ€ÑƒÑ�
Ð¼Ð¸Ñ€.Ñ€ÑƒÑ�
Ð¼Ñ�Ðº.Ñ€ÑƒÑ�
Ð¾Ñ€Ð³.Ñ€ÑƒÑ�
Ñ�Ð°Ð¼Ð°Ñ€Ð°.Ñ€ÑƒÑ�
Ñ�Ð¾Ñ‡Ð¸.Ñ€ÑƒÑ�
Ñ�Ð¿Ð±.Ñ€ÑƒÑ�
Ñ�.Ñ€ÑƒÑ�

// Sandstorm Development Group, Inc. : https://sandcats.io/
// Submitted by Asheesh Laroia <asheesh@sandstorm.io>
sandcats.io

// SBE network solutions GmbH : https://www.sbe.de/
// Submitted by Norman Meilick <nm@sbe.de>
logoip.de
logoip.com

// schokokeks.org GbR : https://schokokeks.org/
// Submitted by Hanno BÃ¶ck <hanno@schokokeks.org>
schokokeks.net

// Scottish Government: https://www.gov.scot
// Submitted by Martin Ellis <martin.ellis@gov.scot>
gov.scot
service.gov.scot

// Scry Security : http://www.scrysec.com
// Submitted by Shante Adam <shante@skyhat.io>
scrysec.com

// Securepoint GmbH : https://www.securepoint.de
// Submitted by Erik Anders <erik.anders@securepoint.de>
firewall-gateway.com
firewall-gateway.de
my-gateway.de
my-router.de
spdns.de
spdns.eu
firewall-gateway.net
my-firewall.org
myfirewall.org
spdns.org

// Seidat : https://www.seidat.com
// Submitted by Artem Kondratev <accounts@seidat.com>
seidat.net

// Sellfy : https://sellfy.com
// Submitted by Yuriy Romadin <contact@sellfy.com>
sellfy.store

// Senseering GmbH : https://www.senseering.de
// Submitted by Felix MÃ¶nckemeyer <f.moenckemeyer@senseering.de>
senseering.net

// Sendmsg: https://www.sendmsg.co.il
// Submitted by Assaf Stern <domains@comstar.co.il>
minisite.ms

// Service Magnet : https://myservicemagnet.com
// Submitted by Dave Sanders <dave@myservicemagnet.com>
magnet.page

// Service Online LLC : http://drs.ua/
// Submitted by Serhii Bulakh <support@drs.ua>
biz.ua
co.ua
pp.ua

// Shift Crypto AG : https://shiftcrypto.ch
// Submitted by alex <alex@shiftcrypto.ch>
shiftcrypto.dev
shiftcrypto.io

// ShiftEdit : https://shiftedit.net/
// Submitted by Adam Jimenez <adam@shiftcreate.com>
shiftedit.io

// Shopblocks : http://www.shopblocks.com/
// Submitted by Alex Bowers <alex@shopblocks.com>
myshopblocks.com

// Shopify : https://www.shopify.com
// Submitted by Alex Richter <alex.richter@shopify.com>
myshopify.com

// Shopit : https://www.shopitcommerce.com/
// Submitted by Craig McMahon <craig@shopitcommerce.com>
shopitsite.com

// shopware AG : https://shopware.com
// Submitted by Jens KÃ¼per <cloud@shopware.com>
shopware.store

// Siemens Mobility GmbH
// Submitted by Oliver Graebner <security@mo-siemens.io>
mo-siemens.io

// SinaAppEngine : http://sae.sina.com.cn/
// Submitted by SinaAppEngine <saesupport@sinacloud.com>
1kapp.com
appchizi.com
applinzi.com
sinaapp.com
vipsinaapp.com

// Siteleaf : https://www.siteleaf.com/
// Submitted by Skylar Challand <support@siteleaf.com>
siteleaf.net

// Skyhat : http://www.skyhat.io
// Submitted by Shante Adam <shante@skyhat.io>
bounty-full.com
alpha.bounty-full.com
beta.bounty-full.com

// Small Technology Foundation : https://small-tech.org
// Submitted by Aral Balkan <aral@small-tech.org>
small-web.org

// Smoove.io : https://www.smoove.io/
// Submitted by Dan Kozak <dan@smoove.io>
vp4.me

// Snowplow Analytics : https://snowplowanalytics.com/
// Submitted by Ian Streeter <ian@snowplowanalytics.com>
try-snowplow.com

// SourceHut : https://sourcehut.org
// Submitted by Drew DeVault <sir@cmpwn.com>
srht.site

// Stackhero : https://www.stackhero.io
// Submitted by Adrien Gillon <adrien+public-suffix-list@stackhero.io>
stackhero-network.com

// Staclar : https://staclar.com
// Submitted by Matthias Merkel <matthias.merkel@staclar.com>
novecore.site

// staticland : https://static.land
// Submitted by Seth Vincent <sethvincent@gmail.com>
static.land
dev.static.land
sites.static.land

// Storebase : https://www.storebase.io
// Submitted by Tony Schirmer <tony@storebase.io>
storebase.store

// Strategic System Consulting (eApps Hosting): https://www.eapps.com/
// Submitted by Alex Oancea <aoancea@cloudscale365.com>
vps-host.net
atl.jelastic.vps-host.net
njs.jelastic.vps-host.net
ric.jelastic.vps-host.net

// Sony Interactive Entertainment LLC : https://sie.com/
// Submitted by David Coles <david.coles@sony.com>
playstation-cloud.com

// SourceLair PC : https://www.sourcelair.com
// Submitted by Antonis Kalipetis <akalipetis@sourcelair.com>
apps.lair.io
*.stolos.io

// SpaceKit : https://www.spacekit.io/
// Submitted by Reza Akhavan <spacekit.io@gmail.com>
spacekit.io

// SpeedPartner GmbH: https://www.speedpartner.de/
// Submitted by Stefan Neufeind <info@speedpartner.de>
customer.speedpartner.de

// Spreadshop (sprd.net AG) : https://www.spreadshop.com/
// Submitted by Martin Breest <security@spreadshop.com>
myspreadshop.at
myspreadshop.com.au
myspreadshop.be
myspreadshop.ca
myspreadshop.ch
myspreadshop.com
myspreadshop.de
myspreadshop.dk
myspreadshop.es
myspreadshop.fi
myspreadshop.fr
myspreadshop.ie
myspreadshop.it
myspreadshop.net
myspreadshop.nl
myspreadshop.no
myspreadshop.pl
myspreadshop.se
myspreadshop.co.uk

// Standard Library : https://stdlib.com
// Submitted by Jacob Lee <jacob@stdlib.com>
api.stdlib.com

// Storj Labs Inc. : https://storj.io/
// Submitted by Philip Hutchins <hostmaster@storj.io>
storj.farm

// Studenten Net Twente : http://www.snt.utwente.nl/
// Submitted by Silke Hofstra <syscom@snt.utwente.nl>
utwente.io

// Student-Run Computing Facility : https://www.srcf.net/
// Submitted by Edwin Balani <sysadmins@srcf.net>
soc.srcf.net
user.srcf.net

// Sub 6 Limited: http://www.sub6.com
// Submitted by Dan Miller <dm@sub6.com>
temp-dns.com

// Supabase : https://supabase.io
// Submitted by Inian Parameshwaran <security@supabase.io>
supabase.co
supabase.in
supabase.net
su.paba.se

// Symfony, SAS : https://symfony.com/
// Submitted by Fabien Potencier <fabien@symfony.com>
*.s5y.io
*.sensiosite.cloud

// Syncloud : https://syncloud.org
// Submitted by Boris Rybalkin <syncloud@syncloud.it>
syncloud.it

// Synology, Inc. : https://www.synology.com/
// Submitted by Rony Weng <ronyweng@synology.com>
diskstation.me
dscloud.biz
dscloud.me
dscloud.mobi
dsmynas.com
dsmynas.net
dsmynas.org
familyds.com
familyds.net
familyds.org
i234.me
myds.me
synology.me
vpnplus.to
direct.quickconnect.to

// Tabit Technologies Ltd. : https://tabit.cloud/
// Submitted by Oren Agiv <oren@tabit.cloud>
tabitorder.co.il

// TAIFUN Software AG : http://taifun-software.de
// Submitted by Bjoern Henke <dev-server@taifun-software.de>
taifun-dns.de

// Tailscale Inc. : https://www.tailscale.com
// Submitted by David Anderson <danderson@tailscale.com>
beta.tailscale.net
ts.net

// TASK geographical domains (www.task.gda.pl/uslugi/dns)
gda.pl
gdansk.pl
gdynia.pl
med.pl
sopot.pl

// Teckids e.V. : https://www.teckids.org
// Submitted by Dominik George <dominik.george@teckids.org>
edugit.org

// Telebit : https://telebit.cloud
// Submitted by AJ ONeal <aj@telebit.cloud>
telebit.app
telebit.io
*.telebit.xyz

// The Gwiddle Foundation : https://gwiddlefoundation.org.uk
// Submitted by Joshua Bayfield <joshua.bayfield@gwiddlefoundation.org.uk>
gwiddle.co.uk

// Thingdust AG : https://thingdust.com/
// Submitted by Adrian Imboden <adi@thingdust.com>
*.firenet.ch
*.svc.firenet.ch
reservd.com
thingdustdata.com
cust.dev.thingdust.io
cust.disrec.thingdust.io
cust.prod.thingdust.io
cust.testing.thingdust.io
reservd.dev.thingdust.io
reservd.disrec.thingdust.io
reservd.testing.thingdust.io

// ticket i/O GmbH : https://ticket.io
// Submitted by Christian Franke <it@ticket.io>
tickets.io

// Tlon.io : https://tlon.io
// Submitted by Mark Staarink <mark@tlon.io>
arvo.network
azimuth.network
tlon.network

// Tor Project, Inc. : https://torproject.org
// Submitted by Antoine BeauprÃ© <anarcat@torproject.org
torproject.net
pages.torproject.net

// TownNews.com : http://www.townnews.com
// Submitted by Dustin Ward <dward@townnews.com>
bloxcms.com
townnews-staging.com

// TradableBits: https://tradablebits.com
// Submitted by Dmitry Khrisanov dmitry@tradablebits.com
tbits.me

// TrafficPlex GmbH : https://www.trafficplex.de/
// Submitted by Phillipp RÃ¶ll <phillipp.roell@trafficplex.de>
12hp.at
2ix.at
4lima.at
lima-city.at
12hp.ch
2ix.ch
4lima.ch
lima-city.ch
trafficplex.cloud
de.cool
12hp.de
2ix.de
4lima.de
lima-city.de
1337.pictures
clan.rip
lima-city.rocks
webspace.rocks
lima.zone

// TransIP : https://www.transip.nl
// Submitted by Rory Breuk <rbreuk@transip.nl>
*.transurl.be
*.transurl.eu
*.transurl.nl

// TuxFamily : http://tuxfamily.org
// Submitted by TuxFamily administrators <adm@staff.tuxfamily.org>
tuxfamily.org

// TwoDNS : https://www.twodns.de/
// Submitted by TwoDNS-Support <support@two-dns.de>
dd-dns.de
diskstation.eu
diskstation.org
dray-dns.de
draydns.de
dyn-vpn.de
dynvpn.de
mein-vigor.de
my-vigor.de
my-wan.de
syno-ds.de
synology-diskstation.de
synology-ds.de

// Uberspace : https://uberspace.de
// Submitted by Moritz Werner <mwerner@jonaspasche.com>
uber.space
*.uberspace.de

// UDR Limited : http://www.udr.hk.com
// Submitted by registry <hostmaster@udr.hk.com>
hk.com
hk.org
ltd.hk
inc.hk

// United Gameserver GmbH : https://united-gameserver.de
// Submitted by Stefan Schwarz <sysadm@united-gameserver.de>
virtualuser.de
virtual-user.de

// Upli : https://upli.io
// Submitted by Lenny Bakkalian <lenny.bakkalian@gmail.com>
upli.io

// urown.net : https://urown.net
// Submitted by Hostmaster <hostmaster@urown.net>
urown.cloud
dnsupdate.info

// .US
// Submitted by Ed Moore <Ed.Moore@lib.de.us>
lib.de.us

// VeryPositive SIA : http://very.lv
// Submitted by Danko Aleksejevs <danko@very.lv>
2038.io

// Vercel, Inc : https://vercel.com/
// Submitted by Connor Davis <security@vercel.com>
vercel.app
vercel.dev
now.sh

// Viprinet Europe GmbH : http://www.viprinet.com
// Submitted by Simon Kissel <hostmaster@viprinet.com>
router.management

// Virtual-Info : https://www.virtual-info.info/
// Submitted by Adnan RIHAN <hostmaster@v-info.info>
v-info.info

// Voorloper.com: https://voorloper.com
// Submitted by Nathan van Bakel <info@voorloper.com>
voorloper.cloud

// Voxel.sh DNS : https://voxel.sh/dns/
// Submitted by Mia Rehlinger <dns@voxel.sh>
neko.am
nyaa.am
be.ax
cat.ax
es.ax
eu.ax
gg.ax
mc.ax
us.ax
xy.ax
nl.ci
xx.gl
app.gp
blog.gt
de.gt
to.gt
be.gy
cc.hn
blog.kg
io.kg
jp.kg
tv.kg
uk.kg
us.kg
de.ls
at.md
de.md
jp.md
to.md
indie.porn
vxl.sh
ch.tc
me.tc
we.tc
nyan.to
at.vg
blog.vu
dev.vu
me.vu

// V.UA Domain Administrator : https://domain.v.ua/
// Submitted by Serhii Rostilo <sergey@rostilo.kiev.ua>
v.ua

// Waffle Computer Inc., Ltd. : https://docs.waffleinfo.com
// Submitted by Masayuki Note <masa@blade.wafflecell.com>
wafflecell.com

// WapBlog.ID : https://www.wapblog.id
// Submitted by Fajar Sodik <official@wapblog.id>
idnblogger.com
indowapblog.com
bloger.id
wblog.id
wbq.me
fastblog.net

// WebHare bv: https://www.webhare.com/
// Submitted by Arnold Hendriks <info@webhare.com>
*.webhare.dev

// WebHotelier Technologies Ltd: https://www.webhotelier.net/
// Submitted by Apostolos Tsakpinis <apostolos.tsakpinis@gmail.com>
reserve-online.net
reserve-online.com
bookonline.app
hotelwithflight.com

// WeDeploy by Liferay, Inc. : https://www.wedeploy.com
// Submitted by Henrique Vicente <security@wedeploy.com>
wedeploy.io
wedeploy.me
wedeploy.sh

// Western Digital Technologies, Inc : https://www.wdc.com
// Submitted by Jung Jin <jungseok.jin@wdc.com>
remotewd.com

// WIARD Enterprises : https://wiardweb.com
// Submitted by Kidd Hustle <kiddhustle@wiardweb.com>
pages.wiardweb.com

// Wikimedia Labs : https://wikitech.wikimedia.org
// Submitted by Arturo Borrero Gonzalez <aborrero@wikimedia.org>
wmflabs.org
toolforge.org
wmcloud.org

// WISP : https://wisp.gg
// Submitted by Stepan Fedotov <stepan@wisp.gg>
panel.gg
daemon.panel.gg

// WoltLab GmbH : https://www.woltlab.com
// Submitted by Tim DÃ¼sterhus <security@woltlab.cloud>
woltlab-demo.com
myforum.community
community-pro.de
diskussionsbereich.de
community-pro.net
meinforum.net

// Woods Valldata : https://www.woodsvalldata.co.uk/
// Submitted by Chris Whittle <chris.whittle@woodsvalldata.co.uk>
affinitylottery.org.uk
raffleentry.org.uk
weeklylottery.org.uk

// WP Engine : https://wpengine.com/
// Submitted by Michael Smith <michael.smith@wpengine.com>
// Submitted by Brandon DuRette <brandon.durette@wpengine.com>
wpenginepowered.com
js.wpenginepowered.com

// Wix.com, Inc. : https://www.wix.com
// Submitted by Shahar Talmi <shahar@wix.com>
wixsite.com
editorx.io

// XenonCloud GbR: https://xenoncloud.net
// Submitted by Julian Uphoff <publicsuffixlist@xenoncloud.net>
half.host

// XnBay Technology : http://www.xnbay.com/
// Submitted by XnBay Developer <developer.xncloud@gmail.com>
xnbay.com
u2.xnbay.com
u2-local.xnbay.com

// XS4ALL Internet bv : https://www.xs4all.nl/
// Submitted by Daniel Mostertman <unixbeheer+publicsuffix@xs4all.net>
cistron.nl
demon.nl
xs4all.space

// Yandex.Cloud LLC: https://cloud.yandex.com
// Submitted by Alexander Lodin <security+psl@yandex-team.ru>
yandexcloud.net
storage.yandexcloud.net
website.yandexcloud.net

// YesCourse Pty Ltd : https://yescourse.com
// Submitted by Atul Bhouraskar <atul@yescourse.com>
official.academy

// Yola : https://www.yola.com/
// Submitted by Stefano Rivera <stefano@yola.com>
yolasite.com

// Yombo : https://yombo.net
// Submitted by Mitch Schwenk <mitch@yombo.net>
ybo.faith
yombo.me
homelink.one
ybo.party
ybo.review
ybo.science
ybo.trade

// Yunohost : https://yunohost.org
// Submitted by Valentin Grimaud <security@yunohost.org>
ynh.fr
nohost.me
noho.st

// ZaNiC : http://www.za.net/
// Submitted by registry <hostmaster@nic.za.net>
za.net
za.org

// Zine EOOD : https://zine.bg/
// Submitted by Martin Angelov <martin@zine.bg>
bss.design

// Zitcom A/S : https://www.zitcom.dk
// Submitted by Emil Stahl <esp@zitcom.dk>
basicserver.io
virtualserver.io
enterprisecloud.nu

// ===END PRIVATE DOMAINS==={
    "name": "amphp/http-client-cookies",
    "homepage": "https://github.com/amphp/http-client-cookies",
    "description": "Automatic cookie handling for Amp's HTTP client.",
    "keywords": [
        "http",
        "cookie",
        "cookies",
        "client",
        "async"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@gmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.2",
        "ext-filter": "*",
        "amphp/amp": "^2.3",
        "amphp/dns": "^1.2",
        "amphp/http": "^1.5",
        "amphp/http-client": "^4",
        "amphp/sync": "^1.3",
        "psr/http-message": "^1.0"
    },
    "require-dev": {
        "amphp/socket": "^1",
        "amphp/file": "^2",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^7 || ^8",
        "friendsofphp/php-cs-fixer": "^2.3",
        "amphp/http-server": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Http\\Client\\Cookie\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Http\\Client\\Cookie\\": "test"
        }
    },
    "conflict": {
        "amphp/file": "<1 || >=3"
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Http\Client\Cookie\Internal;

use PHPUnit\Framework\TestCase;
class PublicSuffixListTest extends TestCase
{
    /**
     * @dataProvider provideTestData
     * @requires extension intl
     *
     * @param $domain
     * @param $expectation
     *
     * @throws \Amp\Dns\InvalidNameException
     */
    public function testWithData($domain, $expectation) : void
    {
        $this->assertSame($expectation, PublicSuffixList::isPublicSuffix($domain));
    }
    /**
     *
     */
    public function provideTestData() : array
    {
        $lines = \file(__DIR__ . '/../fixture/public_suffix_list_tests.txt', \FILE_IGNORE_NEW_LINES | \FILE_SKIP_EMPTY_LINES);
        $lines = \array_filter($lines, static function ($line) {
            return \Phabel\Target\Php80\Polyfill::substr($line, 0, 2) !== '//';
        });
        return \array_map(static function ($line) {
            $parts = \explode(' ', $line);
            return [$parts[0], (bool) $parts[1]];
        }, $lines);
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Cookie;

class FileCookieJarTest extends CookieJarTest
{
    /**
     *
     */
    protected function createJar() : CookieJar
    {
        return new FileCookieJar(\tempnam(\sys_get_temp_dir(), 'amphp-http-client-cookies-test-'));
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Cookie;

use Amp\Http\Cookie\CookieAttributes;
use Amp\Http\Cookie\RequestCookie;
use Amp\Http\Cookie\ResponseCookie;
abstract class CookieJarTest extends CookieTest
{
    /** @var CookieJar */
    private $jar;
    /**
     *
     */
    public function setUp() : void
    {
        parent::setUp();
        $this->jar = $this->createJar();
    }
    /**
     * @dataProvider provideCookieDomainMatchData
     *
     * @param ResponseCookie $cookie
     * @param string $domain
     * @param bool $returned
     *
     * @return \Generator
     */
    public function testCookieDomainMatching(ResponseCookie $cookie, string $domain, bool $returned) : \Generator
    {
        $this->jar->store($cookie);
        $requestCookies = (yield $this->jar->get($this->getUri('https', $domain, '/')));
        if ($returned) {
            $requestCookie = new RequestCookie($cookie->getName(), $cookie->getValue());
            $this->assertSame((string) $requestCookie, \implode('; ', $requestCookies));
        } else {
            $this->assertSame([], $requestCookies);
        }
    }
    /**
     *
     */
    public function provideCookieDomainMatchData() : array
    {
        // See http://stackoverflow.com/a/1063760/2373138 for cases
        return [
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.foo.bar.example.com')), 'foo.bar', false],
            /* previous security issue */
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.example.com')), 'example.com', true],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.example.com')), 'www.example.com', true],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'example.com', true],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'www.example.com', false],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'anotherexample.com', false],
            [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('anotherexample.com')), 'example.com', false],
        ];
    }
    /**
     *
     */
    protected abstract function createJar() : CookieJar;
}<?php

namespace Amp\Http\Client\Cookie;

use Amp\PHPUnit\AsyncTestCase;
use Psr\Http\Message\UriInterface as PsrUri;
abstract class CookieTest extends AsyncTestCase
{
    /**
     *
     */
    protected function getUri(string $scheme, string $host, string $path) : PsrUri
    {
        $uri = $this->createMock(PsrUri::class);
        $uri->method('getScheme')->willReturn(\strtolower($scheme));
        $uri->method('getHost')->willReturn(\strtolower($host));
        $uri->method('getPath')->willReturn($path);
        return $uri;
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Cookie;

class InMemoryCookieJarTest extends CookieJarTest
{
    /**
     *
     */
    protected function createJar() : CookieJar
    {
        return new InMemoryCookieJar();
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Cookie;

use Amp\Http\Client\Connection\DefaultConnectionFactory;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\HttpClient;
use Amp\Http\Client\HttpClientBuilder;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Cookie\CookieAttributes;
use Amp\Http\Cookie\ResponseCookie;
use Amp\Http\Server\Options;
use Amp\Http\Server\RequestHandler\CallableRequestHandler;
use Amp\Http\Server\Response as ServerResponse;
use Amp\Http\Server\Server;
use Amp\Http\Status;
use Amp\Socket;
use Amp\Socket\StaticConnector;
use Psr\Log\NullLogger;
use function Amp\Promise\wait;
use function Amp\Socket\connector;
class ClientCookieTest extends CookieTest
{
    /** @var HttpClient */
    private $client;
    /** @var InMemoryCookieJar */
    private $jar;
    /** @var Server */
    private $server;
    /** @var string */
    private $address;
    /** @var string */
    private $cookieHeader;
    /**
     *
     */
    public function provideCookieDomainMatchData() : array
    {
        return [[new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.foo.bar.example.com')), 'foo.bar', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.example.com')), 'example.com', true], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.example.com')), 'www.example.com', true], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'example.com', true], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'www.example.com', true], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('example.com')), 'anotherexample.com', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('anotherexample.com')), 'example.com', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('com')), 'anotherexample.com', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('.com')), 'anotherexample.com', false], [new ResponseCookie('foo', 'bar', CookieAttributes::empty()->withDomain('')), 'example.com', true]];
    }
    /**
     *
     */
    public function setUp() : void
    {
        parent::setUp();
        $this->jar = new InMemoryCookieJar();
        $socket = Socket\Server::listen('127.0.0.1:0');
        $socket->unreference();
        $this->address = $socket->getAddress();
        $this->server = new Server([$socket], new CallableRequestHandler(function () {
            return new ServerResponse(Status::OK, ['set-cookie' => $this->cookieHeader], '');
        }), new NullLogger(), (new Options())->withHttp1Timeout(1)->withHttp2Timeout(1));
        wait($this->server->start());
        $this->client = (new HttpClientBuilder())->usingPool(new UnlimitedConnectionPool(new DefaultConnectionFactory(new StaticConnector($this->address, connector()))))->interceptNetwork(new CookieInterceptor($this->jar))->build();
    }
    /**
     * @dataProvider provideCookieDomainMatchData
     *
     * @param ResponseCookie $cookie
     * @param string $requestDomain
     * @param bool $accept
     *
     * @return \Generator
     */
    public function testCookieAccepting(ResponseCookie $cookie, string $requestDomain, bool $accept) : \Generator
    {
        $this->cookieHeader = (string) $cookie;
        /** @var Response $response */
        $response = (yield $this->client->request(new Request('http://' . $requestDomain . '/')));
        (yield $response->getBody()->buffer());
        $cookies = $this->jar->getAll();
        if ($accept) {
            $this->assertCount(1, $cookies);
        } else {
            $this->assertSame([], $cookies);
        }
        wait($this->server->stop());
    }
}{
    "name": "amphp/process",
    "homepage": "https://github.com/amphp/process",
    "description": "Asynchronous process manager.",
    "require": {
        "php": ">=7",
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.4"
    },
    "require-dev": {
        "phpunit/phpunit": "^6",
        "amphp/phpunit-util": "^1",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "license": "MIT",
    "authors": [
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "Amp\\Process\\": "lib"
        },
        "files": ["lib/functions.php"]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Process\\Test\\": "test"
        }
    },
    "config": {
        "platform": {
            "php": "7.0.33"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
MZ�       ÿÿ  ¸       @                                     º ´	Í!¸LÍ!This program cannot be run in DOS mode.
$       äíP¦ Œ>õ Œ>õ Œ>õ©ô­õ¬Œ>õ›Ò?ô¢Œ>õ›Ò=ô£Œ>õ›Ò;ô±Œ>õ›Ò:ô¬Œ>õ}sõõ¥Œ>õ Œ?õþŒ>õ
Ò6ô£Œ>õ
ÒÁõ¡Œ>õ Œ©õ¡Œ>õ
Ò<ô¡Œ>õRich Œ>õ                        PE  d† U%s\        ð "   0        „2        @                        �         `�                                           ð_  È       ¨Ü   €  H           € L   X  p                           €X  ”            @  ø                          .text   .      0                    `.rdata  H*   @   ,   4              @  @.data   €   p      `              @  À.pdata  H   €      b              @  @.gfids      �      f              @  @.rsrc   ¨Ü       Þ   h              @  @.reloc  L    €     F             @  B                                                                                                                                                                                                                        @SH�ì€   H‹ð_  H3ÄH‰D$xH‹ÙÇD$@   H‹IL�D$@º~f€ÿ11  …Àt‹H�¬4  D‹Àè”  3Àéó   H‰´$˜   3ö95-f  H‰¼$    t9·f  �~¸   f‰D$XH‹ f   ‰t$\D$`ÿî0  f‰D$ZH�T$Xë3¸   ¿   f‰D$HH‹Ìe  ‹‰L$L··e  ÿ¹0  f‰D$JH�T$HH‹KE3ÉH‰t$0D‹ÇH‰t$(H‰t$ ÿP0  H‹¼$    H‹´$˜   ƒøÿt‹H�Z4  èÅ  3Àë'ÿ;0  =3'  tD‹H�š4  ‹Èèc  3Àë¸   H‹L$xH3Ìè­  H�Ä€   [ÃÌÌÌÌ@SUVWAVAWHƒìXH‹Œ^  H3ÄH‰D$HL‹¼$°   3ÛA‹ñH‰\$0I‹èH‰\$(D‹ò‰\$ L�L$@D‹ÆH‹Õ‹ûÿÀ/  ƒøÿu!ÿ¥/  E‹ÎH�K4  ‹ÈM‹ÇèÑ  3Àév  D‹Óƒþ‚ã   ‹þWíƒçøfoåA»   @ „     E‹ÊE�CMÀA‹ÓHÒA�KÿHÉMÉAƒÂfBnLÅ E�CfnDÕ MÀfnTÍ A�SfBn\Í A�KfbØE�KfBnDÅ MÉfbÑHÒfbÚHÉfþÝAƒÃfBnLÍ foëfnTÕ fn\Í fbØfbÑfbÚfþÜfoãD;×‚]ÿÿÿfþåfoÄfsØfþàfoÄfsØfþàf~ç‹ÓD;ÖsW‹ÆA+Âƒør9A‹Â‹ÎA+ÊHÁàƒéHÅÑéÿÁD‹ÁE�J@ f„     PH�@ IƒèuñD;Ös
A‹ÂHÀ|Å �øD‹L$@D;ÏtE‹Æ‰|$ I‹×H�3  è�  3Àë¸   H‹L$HH3Ìè§  HƒÄXA_A^_^][ÃÌÌÌÌÌÌÌÌÌÌ@SH�ì�   H‹€\  H3ÄH‰„$ˆ   H‹ÙÇD$P    H‹IL�D$Pº~f€ÿ¾-  …Àt‹H�	3  D‹Àè!  3Àé«   ‹Èb  H�D$xH‰D$8‹¯Á‰L$@ÇD$0   ÆD$xHcÈH²b  H‰L$Hÿ_,  D$0‹L�D$X‹ÈˆD$|ÁéA¹   ˆL$y‹ÈÁéˆL$z‹È¶ÁéD$XˆD$}H�÷2  D$@ˆL${H‹KH‰D$ D$hèýÿÿ…À„ZÿÿÿÇC   ¸   H‹Œ$ˆ   H3Ìè  H�Ä�   [ÃÌÌÌÌÌÌH‰\$ AVH�ì€   H‹[[  H3ÄH‰D$p‹áa  H‹ÙƒÀE3ö‹ÈD‰t$d‰D$@ÿ-  H‹KL�L$hH‰D$HE�FH�D$dL‰t$0L‰t$(H�T$@H‰D$ ÿ¢,  ƒøÿu)ÿW,  D‹H�=2  ‹Èè†  H‹L$HÿÃ,  3Àé‚  D‹D$hAƒøs%D‹L$@H�m2  ‹è–  H‹L$Hÿ“,  3ÀéR  H‰¼$    H‹|$H¶<t$‹H�×2  D¾Àè^  H‹L$Hÿ[,  3Àé  ¶O„Ét@€ù}¶ÁL�õ?  M‹ÁëL�X3  ‹D¾ÁH�k3  è  H‹L$Hÿ,  3ÀéÊ   D‹L$@H�D$`H‰´$˜   A‹öH‰D$XfÇD$`ÇD$P   E;Át‹H��1  èÈ  H‹|$HëLHcn`  ‹L‹Á¯ÁH�OHcÐH|`  èq'  …Àt‹H�r3  è�  H‹|$Hë@ˆt$a¾   ÇC   H‹Ïÿt+  ‹H�³3  H‹KL�D$PA¹   H‰D$ èÊúÿÿ…ÀADö‹ÆH‹´$˜   H‹¼$    H‹L$pH3ÌèE  H‹œ$¨   H�Ä€   A^ÃÌÌÌ3ÀH‹Áƒz|HÿÀHƒø|í3ÀÃ¸   ÃÌÌH‰\$ UAVAWH�¬$€úÿÿH�ì€  H‹ðX  H3ÄH‰…p  E3ÿL‹ñA‹ßI‹ÞèÔøÿÿ…À„Ì  HÿÃHƒû|æH‰´$¨  I‹ÎH‰¼$°  è{ÿÿÿ…À„é   E‹ÇD‰|$@E‹ÏD‰½P  E‹×D‰½`  I‹Þ¿   @ „     L‹A‹C…À…‘   A‹ÏE…ÉtI‹SD  H9”ÍX  tÿÁA;ÉrïA;Éu#Aƒù@sI‹CH‰„ÍX  D‹�P  AÿÁD‰�P  A‹ÏE…ÒtI‹SH9”Íh  tÿÁA;ÊrïA;ÊuiAƒú@scI‹CH‰„Íh  D‹•`  AÿÂD‰•`  ëDƒøu?A‹ÇE…ÀtI‹S‹ÈH9TÌHtÿÀA;ÀrðA;ÀuAƒø@s‹ÈI‹CH‰DÌHD‹D$@AÿÀD‰D$@HƒÃHƒï…ÿÿÿL��`  L‰|$ L�…P  3ÉH�T$@ÿ¶(  ‹Øƒøÿ„=  …À„'  A‹÷I‹ÿ~y Hƒÿ}pI‹þH�T$@H‹Iÿ§(  I‹þ…Àtèªûÿÿ…À„¢   ÿËë;H‹IH�•P  ÿ}(  I‹þ…Àtè`úÿÿ…Àt|ÿËëH‹IH�•`  ÿW(  …ÀuÿÆHÿÇ…ÛŠI‹Îè’ýÿÿ…À…þÿÿ3ÀëIHcÆL�L$4ºÿÿ  ÇD$0   A¸  I‹ÆH�D$0H‰D$ H‹Kÿ+(  ƒøÿuE‹H�Å0  èP  ƒÈÿH‹´$¨  H‹¼$°  H‹�p  H3ÌèN  H‹œ$¸  H�Ä€  A_A^]ÃD‹H�×0  ‹L$4èÆ  ë´H�}1  èø  ë¦ÿp'  ‹ÈH�'1  è¢  ë�ƒÈÿëžÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$H‰|$AVHƒì 3ÛÇAH   H‰YPH‹ñÇAX   H‹ù�HcËL�FHHÁáE3ÉHÎH�QÿÍ%  …Àtj…ÛuH‹OëH‹E3ÀA�Pÿ�%  …ÀtCÿÃHƒÇƒû|¸ÇF`h   ¸   H‹H‰Ž°   H‹NH‰Ž¸   H‹N(�Žœ      H‰ŽÀ   ëH�i1  ëH�ð0  ‹Óè	  3ÀH‹\$0H‹t$8H‹|$@HƒÄ A^ÃÌH‰\$H‰l$H‰t$ WHƒìPH‹õT  H3ÄH‰D$HH‹ÙƒÏÿ¹   ÿ¼&  H‹KL�L$@3öH‰D$8H‹ÐÇD$0   A¸   H‰t$ ÿ°$  …ÀtZH�-í1  D  ‹D$@…Àtj‹L�D$0H‹KA¹   ‰D$0H‰l$ èÙõÿÿ…ÀtIH‹T$8L�L$@H‹KA¸   H‰t$ ÿV$  …Àu²ÿ”$  ƒømtÿ‰$  D‹H�'1  ‹ÈèÐ  ë‹þH‹Kÿr$  H‹Kÿ�%  ‹ÇH‹L$HH3Ìè	  H‹\$hH‹l$pH‹t$xHƒÄP_ÃÌÌÌÌH‰\$H‰t$WHƒìpH‹ÚS  H3ÄH‰D$`H‹Ù3ö¹   ‰t$TƒÏÿÿ›%  H‹KL�L$PH‰D$HD�FH�D$TH‰t$0H‰t$(H�T$@H‰D$ ÇD$@   ÿ"%  ;ÇtqD‹D$PE…À„Ä   H‹T$HL�L$XH‹KH‰t$ ÿo#  …À„”   D‹D$XD‹L$PE;ÁuuH‹KH�D$TH‰t$0L�L$PH‰t$(H�T$@A¸   H‰D$ ÿ²$  ƒøÿu�ÿO#  H�X0  D‹‹Èè–  H‹Kÿ<#  ‹ÇH‹L$`H3ÌèÝ  L�\$pI‹[I‹s I‹ã_Ã‹H�Â0  è�  ëÅÿý"  H�N0  ë¬‹þë²ÌÌÌÌÌÌÌÌH‰\$H‰l$H‰t$W¸P  èæ  H+àH‹|R  H3ÄH‰„$@  ‹ÿX  ¹öÿÿÿ�@Û�4@ÿh"  3íL�L$0H‹ÈH‰l$ D‹ÃH�T$@H‹øÿ8"  …Àuÿv"  ‹ÈH�µ0  èÀ  3Àéè  ‹T$0;ÓtD‹ÃH�ç0  èâ  3ÀéÊ  ‹Î‰5“X  ‹ÞÿË#  D‹ÆH�T$@H‹ÈH‰�X  èŒ  ‹Î‰5|X  ÿ¦#  H�T$@D‹ÆHÓH‰lX  H‹Èèd  L�L$0H‰l$ A¸   H�T$@H‹ÏÿŽ!  …ÀuÿÌ!  ‹ÈH�ë0  è  3Àé>  ‹T$0ƒútH�?1  è:  3Àé"  ¶D$@„Àt¾ÐH�Ð1  è  3Àé  L�L$0H‰l$ A¸   H�T$@H‹Ïÿ!  …ÀuÿT!  ‹ÈH�#2  èž  3ÀéÆ   ‹D$0=   uH�U2  èÀ  3Àé¨   ÿÈ@8l@tH�©2  è¤  3ÀéŒ   HƒÏÿ‰l$(D‹ÏH‰l$ L�D$@3Ò¹éý  ÿÓ   HcØ…ÀuH�í2  èh  3ÀëS¸   H÷ãH@ÇH‹ÈÿO"  D‹Ï‰\$(L�D$@H‰W  3ÒH‰D$ ¹éý  ÿ‚   …ÀuH�3  è  3Àë¸   H‹Œ$@  H3Ìè!  L�œ$P  I‹[I‹kI‹s I‹ã_ÃÌÌÌÌÌÌÌÌHƒìXH‹õO  H3ÄH‰D$H3ÀˆT$@‹H‹I‰D$AH�D$@H‰D$8A‹ÀÁèˆD$AA‹ÀÁèˆD$BA‹ÀÁèDˆD$DL�D$0L‰L$ A¹   ˆD$CÇD$0   èóðÿÿH‹L$HH3Ìè†  HƒÄXÃÌH‰\$H‰l$H‰t$ WAVAWHƒìPH‹aO  H3ÄH‰D$@3ÿH�t$(D‹÷‹ï‹ßL‹ù„     I‹ßH�T$ ÿq  …À„    ‹D$ =  uI‹ßAÿÆH‰HƒÆë…À…”   ÿÅHÿÃHƒû|»E…öt[AƒÉÿH�T$(A¸   A‹Îÿþ  ƒøÿuÿ  ‹ÈH�Š2  èe  H‹ßf�I‹ßH�T$ ÿñ  …Àtƒ|$  u4ÿÇHÿÃHƒû|Û¸   ë$ÿÖ  D‹Çë	ÿË  D‹ÅH�Ù1  ‹Èè  3ÀH‹L$@H3Ìèc  L�\$PI‹[(I‹k0I‹s8I‹ãA_A^_ÃÌÌÌÌÌÌÌÌÌ@USWH�¬$PÿÿÿH�ì°  H‹&N  H3ÄH‰…¨   Hƒ=ÜT   H‹ú‹Ùu"º   ‹ÊÿØ  H‰ÁT  H…Àt	H‹Èÿƒ  ¹  H�¿T  ÿ)  …Àt‹ÐH�Ü1  è§
  L‹Ç‹Óè­  …Àuè  ƒÈÿéa  èûÿÿ…Àtêƒ=,T   ¸   H‰´$Ð  H�uxL‰´$à  A¾   DEðL‰¼$è  E3ÿA‹ÿ¹   ÿ@  º   A‹ÎH‹Ø‰8D�BD‰xÿÝ  H‰CHƒøÿ„¾  H‰ÿÇHƒÆƒÿ|¾L‰|$(L�MxL�	ôÿÿD‰|$ 3Ò3Éÿb  3ÒH�M A¸È   H‹Øè,  H�M èýöÿÿ…À„z  ƒÊÿH‹Ëÿ	  ƒøÿuÿ  ‹ÈH�1  è`
  éP  H�UpH‹Ëÿî  …Àuÿì  ‹ÈH�+1  è6
  é&  D9}p…  H‹@S  H�EÐH‰D$HL�MèH�E 3ÉH‰D$@L�EèH‹õR  H‰D$8L‰|$0ÇD$(   ÇD$    ÿ¥  …Àuÿ{  ‹ÈH�Ò(  èÅ	  éµ  H‹MØÿf  H‹M ÿ\  H‹M¸ÿR  H‹MÈÿH  D‹EàL�Õ0  H‹Mxº   èßûÿÿ…À„l  H‹ExL�L$PD‰|$PL�Ò÷ÿÿL‰|$(3ÒD‰|$ H‹HH‹E¨H‰L$`3ÉH‰D$Xÿô  ÇD$h   L�L$hH‰…�   L�qöÿÿH‹…€   3ÒL‰|$(D‰|$ H‹HH‹E°H‰L$x3ÉH‰D$pÿ¬  ÇE€   L�M€H‰…˜   L�+öÿÿH‹…ˆ   3ÒL‰|$(D‰|$ H‹HH‹EÀH‰M�3ÉH‰Eˆÿh  H‹MÐƒÊÿH‰…    ÿ,  ƒøÿuÿ9  ‹ÈH�Ø/  èƒ  ëvH‹MÐH�UpÿC  …Àuÿ  ‹ÈH� 0  è[  ëND‹EpL�60  H‹Mxº   è úÿÿ…Àt1H���   èûÿÿ…Àt!H‹MxH‹Iÿö  ‹Epë‹H�X%  èK  èÆ  ƒÈÿL‹´$à  H‹´$Ð  L‹¼$è  H‹�¨   H3Ìè<
  H�Ä°  _[]ÃÌH‰\$H‰t$ WHƒì0H‹J  H3ÄH‰D$(3öH‹úH‰t$ H‹Ùÿ§  D�F
H‹ËH�T$ ‰0ÿ£  ‹ðH9\$ tÿ„  ƒ8 u	‰7¸   ë3ÀH‹L$(H3Ìè¿	  H‹\$PH‹t$XHƒÄ0_ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌH‰\$H‰t$WHƒì H‹ÙI‹ð¹   ÿ`  H‹Ö¹   L‹ÀH‹øÿü  …Àt.ƒøt	H�t/  ëtH‰{¸   ÇC    H‹\$0H‹t$8HƒÄ _ÃH‹Ïÿ  ¹   ÿ  H‹Ö¹   L‹ÀH‹øÿ¢  …Àt!ƒøu¦‰C¸   H‰{H‹\$0H‹t$8HƒÄ _ÃH�>/  èÁ  H‹ÏÿÀ  H‹\$03ÀH‹t$8HƒÄ _ÃÌÌÌÌÌÌ@SHƒì H‹ÙH‹ÑI‹Èè|þÿÿ…Àt‹ÿÈ=þÿ  w¸   HƒÄ [Ã‹H�/  èd  3ÀHƒÄ [ÃÌÌÌÌÌÌÌÌÌÌÌÌ@SHƒì H�YI‹ÈH‹Óè+þÿÿ…Àtƒ; ‹H�/  è$  ¸   HƒÄ [ÃÌÌÌÌÌÌÌÌÌL‰A¸   ÃÌÌÌÌÌÌH‰\$WHƒì ·I‹ØH‹úfƒø-uf9Bufƒz u¸   H‹\$@HƒÄ _ÃH‰t$0L‰t$8E…ÉtrI‹L�5H  E3ÒH�5gH  E‹ÚM‹Î�M‹H‹ÃL+Ã€    ·B· +ÑuHƒÀ…Éuì…ÒtAÿÃIƒÁL;Î|ÌëIcÃH�@M�ÎL‹ÇH�õM  H‹ÓAÿRéB  fƒø-…3  f9B…)  H�JH�2.  I‰ÿi  L‹L�5wG  E3ÒH�5ÍG  H‹øM‹ÎH…Àuof�M‹I‹ÃM+Ã€    ·B· +ÑuHƒÀ…Éuì…ÒtAÿÂIƒÁL;Î|Ìé}   IcÂH�@I�ÎH…ÀtmH‹@H…Àu
¸   é�   I‹ÓH�:M  ÿÐéŒ   fD‰M‹I‹ÃM+ÃfD  ·B· +ÑuHƒÀ…Éuì…ÒtAÿÂIƒÁL;Î|ÍëIcÂH�@I�ÎH…ÀuI‹ÓH�P-  è;  3Àë0H‹@I‹ÓH…ÀuH�\-  è  3ÀëL�GH�°L  ÿÐë¸   H‹t$0L‹t$8H‹\$@HƒÄ _ÃÌÌH‰\$H‰l$H‰L$VWAVHƒì 3ÿHcê3ÀH‰|$@»   ‰=bL  H‰cL  M‹ðÇ^L  ÿÿÿÿ‹÷‰=ZL  H‰=WL  H;Ý}Nff„     I‹ÞL�D$@D‹Îèýÿÿ…Àtd~ƒø~ƒøt	ƒøu	‹÷ë¾   HÿÃH;Ý|Éƒ=L  ÿ…±   ¹   ÿA  H�-  ¹   L‹ÀH‹ØÿÙ  …Àt$ƒøtH�Q+  ën3Àé¨   H‰±K  ‰=³K  ëfH‹Ëÿ   ¹   ÿí  H�Æ,  ¹   L‹ÀH‹Øÿ…  …Àt!ƒøt	H�ý*  ëH‰dK  ÇbK     ëH�!+  è¤  H‹Ëÿ£  9=IK  uH�ü+  è‡  ë9=K  uH�,  èq  ë¿   ‹ÇH‹\$HH‹l$PHƒÄ A^_^ÃÌÌÌÌÌH�áL  ÃÌÌÌÌÌÌÌÌH‰T$L‰D$L‰L$ SVWHƒì0H‹úH�t$`H‹ÙèÊÿÿÿE3ÉH‰t$ L‹ÇH‹ÓH‹ÿ  HƒÄ0_^[ÃÌÌÌÌÌÌÌÌÌÌÌH‰l$H‰t$H‰|$ ATAVAWHƒì0I‹èL‹òH‹ñèyÿÿÿH‰l$(M‹ÎE3ÀHÇD$     3ÒL‹øH‹HƒÉÿ“  IƒÌÿ‹ø…ÀAHüA;üuA‹ÄëlHcÏ¸   HÿÁH‰\$PH÷áI@ÄH‹Èÿm  H‹ØH…Àt7I‹�GLcÀM‹ÎH‰l$(H‹ÓHÇD$     ÿB  …ÀAHÄƒøÿuH‹Ëÿ6  A‹ÄëH‰H‹\$PH‹l$XH‹t$`H‹|$hHƒÄ0A_A^A\ÃÌÌÌÌÌÌÌH‰L$H‰T$L‰D$L‰L$ Hƒì8Hƒ=ÈI   u3ÀHƒÄ8Ãº   H‰\$0�Jÿ¼  H‹ØH…Àu
H‹\$0HƒÄ8ÃH‹T$@L�D$HH�L$ è®þÿÿH‹T$ ÿÈHcÈI¹ &     E3ÀH�J ·fƒù w·ÉI£És
fD‰ HƒèëäH‹EI  H‰SH‹Óÿ   H‹\$0¸   HƒÄ8ÃÌL‹ÜI‰SM‰CM‰K SHƒì`H‹EB  H3ÄH‰D$P3À‹ÙI‰CÈD‹Á‰D$(A¹   I‰Cà3ÒI�Cà¹   I‰C¸ÿ‡  H‹T$xH…Òu&L‹D$HH�Ñ)  ‹ÓèÒþÿÿH‹L$PH3Ìèå  HƒÄ`[ÃL�„$€   H�L$@è½ýÿÿL‹L$HH�©)  H‹T$@D‹Ãè”þÿÿH‹L$PH3Ìè§  HƒÄ`[ÃÌH‰l$H‰t$ AVHƒì@½€   ‹Íÿc  H‰\$PE3öH‹ðH‰|$X H‹1H  H…É„#  ÿú  H…À„î   H‹XH‹Èÿ4  H…Û„Ø   L‰t$8AƒÉÿL‰t$0L‹Ã‰l$(3Ò¹éý  H‰t$ ÿœ  …À…‡   ÿN  ƒøzu‘L‰t$8AƒÉÿL‰t$0L‹ÃD‰t$(3Ò¹éý  L‰t$ ÿa  Hcø…À„^ÿÿÿH‹×H‹Îÿ’  H…À„IÿÿÿL‰t$8AƒÉÿL‰t$0L‹Ã‰|$(3Ò¹éý  H‰D$ H‹ð‹ïÿ  …À„ÿÿÿ¹   ÿR  L‹ÆH�p(  H‹ÈèüÿÿéóþÿÿH‹$G  H…ÉtÿÑ  H‹G  ÿ4  L‰5G  H‹ÎH‹|$XH‹\$PH‹l$`H‹t$hHƒÄ@A^Hÿ%  ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌff„     H;ù?  òuHÁÁf÷ÁÿÿòuòÃHÁÉé«  ÌÌÌ@SHƒì ¹   è  è;  ‹Èè8  èc  H‹Øè  ¹   ‰èC  „ÀtlèR	  H�—	  è6  èù  ‹ÈèÔ  …ÀuVèù  è,  …ÀtH�Õ  è°  è‹  è†  èÁ  ‹Èèî  èÙ  „Àtè˜  è§  3ÀHƒÄ [Ã¹   èý  Ì¹   èò  ÌÌHƒì(è¯  3ÀHƒÄ(ÃHƒì(ès  èj  ‹ÈHƒÄ(é™  ÌÌÌH‰\$H‰t$WHƒì0¹   è+  „Àu¹   è�  Ì@2ö@ˆt$ èÓ  ŠØ‹ÇD  ƒùu
¹   èx  …ÉuJÇªD     H�Ë  H�¬  èí
  …Àt
¸ÿ   éì   H�Š  H�s  èÆ
  ÇlD     ë@¶@ˆt$ ŠËèO  è  H‹ØHƒ8 t"H‹Èè�  „ÀtH‹H‹Ëèr  E3ÀA�P3ÉÿÓèÞ  H‹ØHƒ8 tH‹Èèm  „ÀtH‹è�
  èx
  H‹øèj
  H‹Øè>
  L‹ÀH‹‹è—ïÿÿ‹Øèè  „Àu‹Ëè1
  @„öuèE
  3Ò±èÚ  ‹Ãë!‹Øè¿  „Àu‹Ëè
  Ì€|$  uè
  ‹ÃH‹\$@H‹t$HHƒÄ0_ÃÌHƒì(è/  HƒÄ(évþÿÿÌÌ@SHƒì H‹Ù3ÉÿG  H‹ËÿF  ÿ0  H‹Èº	 ÀHƒÄ [Hÿ%  H‰L$Hƒì8¹   èç	  …Àt¹   Í)H�O>  èª   H‹D$8H‰6?  H�D$8HƒÀH‰Æ>  H‹?  H‰�=  H‹D$@H‰”>  Çj=  	 ÀÇd=     Çn=     ¸   HkÀ H�f=  HÇ   ¸   HkÀ H‹Ž<  H‰L ¸   HkÀH‹�<  H‰L H�Í  è ÿÿÿHƒÄ8ÃÌÌÌ@SVWHƒì@H‹ÙÿW  H‹³ø   3ÿE3ÀH�T$`H‹ÎÿÝ  H…Àt9Hƒd$8 H�L$hH‹T$`L‹ÈH‰L$0L‹ÆH�L$pH‰L$(3ÉH‰\$ ÿþ  ÿÇƒÿ|±HƒÄ@_^[ÃÌÌÌHƒì(èÿ  …Àt!eH‹%0   H‹HëH;Èt3ÀðH±ØA  uî2ÀHƒÄ(Ã°ë÷ÌÌÌ@SHƒì ¶óA  …É»   DÃˆãA  èâ  è  „Àu2Àëè  „Àu	3Éèý  ëêŠÃHƒÄ [ÃÌÌÌH‰\$UH‹ìHƒì@‹Ùƒù‡¦   èc  …Àt+…Ûu'H�XA  èá  …Àt2ÀëzH�\A  èÍ  …À”ÀëgH‹;  IƒÈÿ‹Â¹@   ƒà?+È°IÓÈL3ÂL‰EàL‰EèEàL‰EðòMðý@  L‰EàL‰EèEàL‰Eðòõ@  òMðñ@  òù@  H‹\$PHƒÄ@]Ã¹   èl  ÌÌÌÌHƒìL‹Á¸MZ  f9…ÊÿÿuyHc¸ÊÿÿH�uÊÿÿH��9PE  u_¸  f9AuTL+Â·AH�QHÐ·AH�€L�ÊH‰$I;Ñt‹JL;Ár
‹BÁL;ÀrHƒÂ(ëß3ÒH…Òu2Àëƒz$ }2Àë
°ë2Àë2ÀHƒÄÃÌÌÌ@SHƒì ŠÙè  3Ò…Àt„ÛuH‡ö?  HƒÄ [Ã@SHƒì €=@   ŠÙt„ÒuŠËèH  ŠËèA  °HƒÄ [ÃÌ@SHƒì H‹Ÿ9  H‹Ù‹ÊH3³?  ƒá?HÓÊHƒúÿu
H‹Ëè9  ëH‹ÓH�“?  è"  3É…ÀHDËH‹ÁHƒÄ [ÃÌHƒì(è§ÿÿÿH÷ØÀ÷ØÿÈHƒÄ(ÃÌH‰\$ UH‹ìHƒì Hƒe H»2¢ß-™+  H‹!9  H;ÃuoH�MÿÒ	  H‹EH‰EÿÌ	  ‹ÀH1EÿX	  ‹ÀH�M H1Eÿ¸	  ‹E H�MHÁà H3E H3EH3ÁH¹ÿÿÿÿÿÿ  H#ÁH¹3¢ß-™+  H;ÃHDÁH‰­8  H‹\$HH÷ÐH‰¦8  HƒÄ ]Ã3ÀÃÌ¸   ÃÌÌ¸ @  ÃÌÌH�Ý>  Hÿ%	  ÌÌ°ÃÌH�Ù>  ÃHƒì(èïóÿÿHƒèæÿÿÿHƒHƒÄ(ÃÌ3À9X8  ”ÀÃH�?  ÃH�?  ÃH‰\$UH�¬$@ûÿÿH�ìÀ  ‹Ù¹   èÕ  …Àt‹ËÍ)ƒ%x>   H�Mð3ÒA¸Ð  è%  H�Mðÿí  H‹�è   H�•Ø  H‹ËE3Àÿs  H…Àt<Hƒd$8 H��à  H‹•Ø  L‹ÈH‰L$0L‹ÃH��è  H‰L$(H�MðH‰L$ 3ÉÿŠ  H‹…È  H�L$PH‰…è   3ÒH�…È  A¸˜   HƒÀH‰…ˆ   èŽ  H‹…È  H‰D$`ÇD$P  @ÇD$T   ÿî  ƒøH�D$PH‰D$@H�Eð”ÃH‰D$H3Éÿ  H�L$@ÿ  …Àu
öÛÀ!t=  H‹œ$Ð  H�ÄÀ  ]ÃÌÌÌHƒì(3ÉÿŒ  H‹ÈH…Àu2Àë7¸MZ  f9uòHcA<HÁ�8PE  uã¹  f9HuØƒ¸„   vÏƒ¸ø    •ÀHƒÄ(ÃH�	   Hÿ%v  ÌÌHƒì(H‹�8csmàuƒxu‹H ��àúlæƒøv�ù @™t3ÀHƒÄ(Ãè  ÌH‰\$H‰t$WHƒì H�N"  H�5G"  ëH‹;H…ÿt
H‹Ïèi   ÿ×HƒÃH;ÞråH‹\$0H‹t$8HƒÄ _ÃÌÌH‰\$H‰t$WHƒì H�"  H�5"  ëH‹;H…ÿt
H‹Ïè   ÿ×HƒÃH;ÞråH‹\$0H‹t$8HƒÄ _ÃÌÌHÿ%¥  ÌH‰\$H‰|$UH‹ìHƒì ƒeè 3É3ÀÇ¤5     ¢D‹ÁÇ‘5     �ñcAMDD‹ÊD‹ÒA�ñentiA�òineIA�ðntelEÐD‹ÛD‹Ç;  A�óAuthEÙ‹ÓDÙ�òGenu3É‹øDÒ¸   ¢‰EðD‹ÉD‰Mø‹È‰]ô‰UüE…ÒuRHƒ)5  ÿAƒÈ%ð?ÿD‰u;  =À t(=` t!=p t°ùüÿƒø wH»     H£ÃsAƒÈD‰;;  E…Ûu�á ð�ù ` rAƒÈD‰;  ¸   ‰UàD‰Mä;ø|$3É¢‰Eð‰]ô‰Mø‰Uü‰]èºã	sAƒÈD‰é:  AºásnÇt4     Çn4     AºásSAºásL3ÉÐHÁâ HÐH‰UH‹E$<u2‹@4  ƒÈÇ/4     öEè ‰)4  tƒÈ Ç4     ‰4  H‹\$83ÀH‹|$@HƒÄ ]ÃÌÌ3À94  •ÀÃÂ  ÌÌÌÌÌÿ%â  ÿ%ä  ÿ%F  ÿ%8  ÿ%Â  ÿ%  ÿ%Æ  ÿ%Ð  ÿ%*  ÿ%D  ÿ%.  ÿ%   ÿ%J  ÿ%ô  ÿ%Æ  ÿ%¨  ÿ%Ú  ÿ%Ä  ÿ%^  ÿ%   ÿ%  ÿ%t  ÿ%®  ÿ%€  ÿ%‚  ÿ%  Hƒì(M‹A8H‹ÊI‹Ñè   ¸   HƒÄ(ÃÌÌÌ@SE‹H‹ÚAƒãøL‹ÉAö L‹ÑtA‹@McP÷ØLÑHcÈL#ÑIcÃJ‹H‹C‹HHKöAt
¶AƒàðLÈL3ÊI‹É[é»òÿÿÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌff„     HƒìL‰$L‰\$M3ÛL�T$L+ÐMBÓeL‹%   M;ÓòsfA�â ðM�› ðÿÿAÆ M;ÓòuïL‹$L‹\$HƒÄòÃÌÿ%x  ÿ%z  ÌÌÌÌÌÌÌÌff„     ÿà@UHƒì H‹êH‹H‹Ñ‹èTþÿÿ�HƒÄ ]ÃÌ@UH‹êH‹3É�8  À”Á‹Á]ÃÌ                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        °c      ¼c      Ôc      äc      ðc      
d      d      .d      Dd      Xd      hd      vd      †d      œd      ®d      Äd      Öd      îd      e       e      6e      i       j      j      òi      Üi      Âi      ¦i      ’i      ~i      `i      Di      0i      i              ¤e      ¼e      še      4j      >j              je      s      €      €o      €
      €xe            €—      €	      €‚e            €`e            €        êe              Êg      >f      Hf      àe      Øe      þe              ´g              ²f              Þf      êg      þf      rg      "h      0h      dg      Æf      †g      h      |g      Vg      ¢f      �f      g      @g      8g      ôe      *g              Úg      Hg      tf      ,f      f      Zf              (< @   Ð= @           ð0 @                   $0 @   à0 @                                            p @   @q @   S u c c e s s   S i g n a l   n o t   e x p e c t e d   a t   t h i s   t i m e         I n v a l i d   s t r e a m   i d e n t i f i e r       I n v a l i d   p r o c e s s   i d e n t i f i e r     D u p l i c a t e   s t r e a m   i d e n t i f i e r   I n v a l i d   c l i e n t   s e c u r i t y   t o k e n       I n v a l i d   s e r v e r   s e c u r i t y   t o k e n       F a i l e d   t o   s e t   s o c k e t   # % d   t o   n o n - b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       C o n n e c t i n g   s o c k e t   # % d   u n e x p e c t e d l y   s u c c e e d e d         C o n n e c t i n g   s o c k e t   # % d   f a i l e d         F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d   F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d :   s e n t   % d   o f   % d   b y t e s         F a i l e d   t o   s e t   s o c k e t   # % d   t o   b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       h a n d s h a k e       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   U n e x p e c t e d   s i g n a l   c o d e   % d   f r o m   s e r v e r ,   e x p e c t i n g   H A N D S H A K E _ A C K   U n k n o w n   e r r o r       H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   S e r v e r   r e j e c t e d   c o n n e c t i o n :   % d :   % s           H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   I n v a l i d   s e r v e r   t o k e n       h a n d s h a k e   a c k       F a i l e d   t o   c o n n e c t   s o c k e t   # % d :   U n k n o w n   e r r o r   F a i l e d   t o   c o n n e c t   s o c k e t   # % d         F a i l e d   t o   c r e a t e   s o c k e t   # % d   s e l e c t ( )   o p e r a t i o n   f a i l e d               s e l e c t ( )   u n e x p e c t e d l y   r e t u r n e d   z e r o   s o c k e t s           F a i l e d   t o   c r e a t e   p i p e   f o r   p r o c e s s   I / O   s t r e a m   # % d                 F a i l e d   t o   s e t   h a n d l e   i n f o r m a t i o n   f o r   p r o c e s s   I / O   s t r e a m   # % d   F a i l e d   t o   c r e a t e   c h i l d   p r o c e s s             F a i l e d   t o   r e a d   f r o m   c h i l d   p r o c e s s   p i p e   # % d     d a t a         F a i l e d   t o   r e a d   f r o m   s o c k e t   # % d             F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d       F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d :   s e n t   % d   o f   % d   b y t e s             F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n                 F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s             F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n               F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   1   b y t e               F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   e x p e c t e d   0 ,   g o t   % d       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n               F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   c o m m a n d   t o o   l o n g           F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   m i s s i n g   n u l l   t e r m i n a t o r             F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   i n v a l i d   U T F - 8   s t r i n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   f a i l e d   t o   d e c o d e   U T F - 8   s t r i n g                 R e t r i e v i n g   c o p y   t h r e a d   # % d   e x i t   c o d e   f a i l e d           W a i t   o p e r a t i o n   o n   c o p y   t h r e a d s   f a i l e d       W S A S t a r t u p   f a i l e d :   % d       W a i t   o p e r a t i o n   o n   c o n n e c t   t h r e a d   f a i l e d   R e t r i e v i n g   c o n n e c t   t h r e a d   e x i t   c o d e   f a i l e d     P I D   W a i t   o p e r a t i o n   o n   c h i l d   p r o c e s s   f a i l e d     R e t r i e v i n g   p r o c e s s   e x i t   c o d e   f a i l e d   e x i t   c o d e       pC @   €C @   ÈC @    D @   8D @   pD @   °D @   a d d r e s s   p o r t         t o k e n - s i z e     c w d   E r r o r   p a r s i n g   s e r v e r   a d d r e s s         I n v a l i d   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   p o r t :   % d   I n v a l i d   t o k e n   s i z e :   % d     =       U n k n o w n   o p t i o n :   % s     O p t i o n   % s   r e q u i r e s   a   v a l u e     P r o c e s s   l a b e l   n o t   s u p p l i e d     S e r v e r   p o r t   n o t   s u p p l i e d         1 2 7 . 0 . 0 . 1       % d :   % s     % s :   % d :   % s     %s
                 U%s\       h   Y  M      U%s\          |Y  |M      U%s\       €  �Y  �M      U%s\                   ”                                                                                        p @                   øB @    C @                      RSDS3Þ¬«öÛmN¢¼H^„‘gØ   C:\Users\Dave\source\repos\windows-process-wrapper\Release\ProcessWrapper64.pdb                   GCTL   À-  .text$mn    À=     .text$mn$00 Ò=  6   .text$x  @  ø  .idata$5    øB     .00cfg  C     .CRT$XCA    C     .CRT$XCAA   C     .CRT$XCZ     C     .CRT$XIA    (C     .CRT$XIAA   0C     .CRT$XIAC   8C     .CRT$XIZ    @C     .CRT$XPA    HC     .CRT$XPZ    PC     .CRT$XTA    XC     .CRT$XTZ    `C  ´  .rdata  Y  ü  .rdata$zzzdbg   \     .rtc$IAA    \     .rtc$IZZ     \     .rtc$TAA    (\     .rtc$TZZ    0\  À  .xdata  ð_  ´   .idata$2    ¤`     .idata$3    ¸`  ø  .idata$4    °c  ˜  .idata$6     p      .data    p  à  .bss     €  H  .pdata   �     .gfids$y        À  .rsrc$01    À¡  èÚ  .rsrc$02                                     	ò0Ì<  x   ! t d    S  0\  !      S  0\   ¢	ðàp`P0  Ì<  H    	 0  Ì<  ˆ    4 òàÌ<  p   ! t �  \  ˜\  ! d \  æ  ¬\  !   \  æ  ¬\  !   �  \  ˜\  * 4× Ð 
ðàP  Ì<  p  ! tÖ dÕ ð  =  ô\  !   ð  =  ô\  !   tÖ  dÕ ð  =  ô\   t d 4 2à# d T 4 ’pÌ<  H    d 4 ÒpÌ<  `   /	 d T 4 
 p  Ì<  @   ¢  Ì<  H   '
 d T 4 ’ðàpÌ<  @   $ 6 p0P  Ì<  ¨  !& &ô= ä< d: À!  i"  è]  !   À!  i"  è]   d 4
 RpÌ<  (    d 4 2p 20@ @ä ;d 
4 
2p T
 4	 2àp` Rp`0
 t d T RðàÀ! 4
 ð+  ^,  �^  !   ð+  ^,  �^   b  ! 4 à,  -  Ì^  !   4 à,  -  Ì^  # ²0Ì<  P   -
 -t "4
 d T rà       	 d	 4 Rp0<     <1  R2  Ò=  R2   2P	 	b   rp`0	 "  0<     o5  ú5  ð=  ú5   P   4
 rP 4	 2P 4º ¸ P   t 4 2P    0   B         ¸`          Re   @   b          Že  HA  Ða          Æe  A  €b          <h  ÈA  pb          \h  ¸A  Øb          ~h   B  xc           h  ÀB  Èb          Àh  B  ¸b          àh   B                      °c      ¼c      Ôc      äc      ðc      
d      d      .d      Dd      Xd      hd      vd      †d      œd      ®d      Äd      Öd      îd      e       e      6e      i       j      j      òi      Üi      Âi      ¦i      ’i      ~i      `i      Di      0i      i              ¤e      ¼e      še      4j      >j              je      s      €      €o      €
      €xe            €—      €	      €‚e            €`e            €        êe              Êg      >f      Hf      àe      Øe      þe              ´g              ²f              Þf      êg      þf      rg      "h      0h      dg      Æf      †g      h      |g      Vg      ¢f      �f      g      @g      8g      ôe      *g              Úg      Hg      tf      ,f      f      Zf              TReadFile  SetHandleInformation  ÇGetStdHandle  ñWriteFile ¹WaitForMultipleObjects  Ô CreatePipe  »WaitForSingleObject ÔMultiByteToWideChar 4GetExitCodeThread VGetLastError   CloseHandle ç CreateThread  GetCurrentProcessId Û CreateProcessW  3GetExitCodeProcess   FormatMessageW  XInterlockedFlushSList ÝWideCharToMultiByte ZInterlockedPushEntrySList TInitializeSListHead YInterlockedPopEntrySList  KERNEL32.dll  H WSARecv   WSAConnect  M WSASend  InetPtonW WS2_32.dll  F wcsstr   __C_specific_handler  > memset  VCRUNTIME140.dll   free   malloc  n wcstol  ! _errno    _aligned_free  __stdio_common_vswprintf_s    __acrt_iob_func  realloc  _aligned_malloc  __stdio_common_vfprintf  __stdio_common_vswprintf  @ _seh_filter_exe B _set_app_type 	 __setusermatherr   _configure_wide_argv  5 _initialize_wide_environment  ) _get_initial_wide_environment 6 _initterm 7 _initterm_e U exit  # _exit T _set_fmode   __p___argc   __p___wargv  _cexit   _c_exit = _register_thread_local_exe_atexit_callback   _configthreadlocale  _set_new_mode  __p__commode  4 _initialize_onexit_table  < _register_onexit_function  _crt_atexit g terminate api-ms-win-crt-heap-l1-1-0.dll  api-ms-win-crt-convert-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll  api-ms-win-crt-locale-l1-1-0.dll  ®RtlCaptureContext µRtlLookupFunctionEntry  ¼RtlVirtualUnwind  ’UnhandledExceptionFilter  RSetUnhandledExceptionFilter GetCurrentProcess pTerminateProcess  pIsProcessorFeaturePresent 0QueryPerformanceCounter GetCurrentThreadId  ÝGetSystemTimeAsFileTime jIsDebuggerPresent mGetModuleHandleW  ; memcmp  < memcpy                                                                                                                                                                                                                                                                                                                                                                                                                                                          2¢ß-™+  Í] ÒfÔÿÿÿÿÿÿ         /                              ØU @           `& @   èU @           @' @   øU @           �' @   V @           Ð' @                                                                                                                                                                                                                                                                                                                                                                      S  0\  S    @\    \  X\  `  f  h\  p  Š  „\  �  \  ˜\  \  æ  ¬\  æ  ¦  À\  ¦  ®  Ô\  ®  Í  ä\  ð  =  ô\  =  £  ]  £  Ç  (]  Ç     8]       (]    ï  P]  ð    d]    X  €]  `  ø  ˜]         ¸]  €   ·!  È]  À!  i"  è]  i"  µ%   ^  µ%  Ï%  ^  Ð%  Q&  ,^  `&  :'  D^  @'  „'  T^  �'  Ç'  T^  à'  î)  \^  ð)  ‹+  p^   +  å+  „^  ð+  ^,  �^  ^,  ¿,  ¨^  ¿,  Ù,  ¼^  à,  -  Ì^  -  .-  Ô^  .-  Ÿ-  è^   -  _.  ü^  `.  ç/  _   0  !0  (_  $0  ß0  T^  à0  ð0  Ü_  ð0  	1  Ü_  1  ƒ2  ,_  „2  –2  Ü_  ˜2  Ì2  T^  Ì2  �3  \_   3  4  d_  4  M4  Ü_  P4  ™4  T^  œ4  e5  ˜_  h5  6  p_  6  (6  T^  (6  S6  T^  T6  £6  T^  ¤6  »6  Ü_  ¼6  h7  ¤_  ˜7  ³7  Ü_  Ð7  9  °_  9  l9  Ü_  |9  ´9  Ü_  ´9  þ9  D^   :  J:  D^  T:  <  À_  Ì<  é<  Ü_  ì<  E=  Ô_  `=  ±=  è_  Ð=  Ò=  Ð_  Ò=  ð=  T_  ð=  >  �_                                                                                                                                                                                          
         E   r   7                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            0  €   `  €   x  €   �  €                  ¨  €   À  €   Ø  €   ð  €               e    €                    €                  8 €               	  P                 	  `                 	  p                 	  €                 	  �                 	                    	  °  À¡  h          (¦  ¨          Ð¶  ¨%          xÜ  ›          �w >           Ðw X          ({ }          (                                                ­�: ©|6	º�EcÈ™OÌÍ�Q÷Ò¥^ùÕ©cäË£c¡Ò¦_GÛ�5×žC         k7Ë *N H%ŒK/G»‹=xÃ�?õ³‚4ÿ«{/ÿ»‰9ÿÏšHÿ×©aÿÓ¬oî³‘[’²…>²�Q ˆ<  n:Î s<ÖV-§‰Y9Gb˜l3ì�\!ó_C—R:dgI�›o(æ¾�Dÿ¬˜xÿ¸�sÿÛµx±ÓžKÕ¤W e/Ên9Î’o?ÇøsI»ïoH¨ÿV4‰â;wCqV'_u_<–\F%l™‰oíÄ´›ÿÕªeÿà»‚ÿÔ®r�] yIÑLŠ`Øï�yßú¢€ÒÞ¢{¡ü†a¥ÿ_:¡Ù�`>ÅÂ£qÙxoa9ÄÅÇÜÊ¯ƒÿ×¨]ÿÝ´tÿÛ¼ŒèÕ¬lF‘jÞ`¢äÀ˜wÕÈaK¾�D¹©}>ÿ’jHÿ¹�VùØ·ƒ‚YPAMÁ¿»õ·›pÿÖ©bÿÝ³rÿäÃ�ÿá½„§‘xRlš~d\ˆmyL]Idšv;%Ã˜U}È ] ÂŸg x9UhK‘­†Iÿ»�KÿÓ¦_ÿÚ°nÿâ¿‰ÿÕºŽØÇ©{ûÜ¼ŠúÒ³�è’{W�´”b¯¤†V—´ŒM«³…<Ñ†`%°ZÆÅ‘?ÿØ¨[ÿ‰mAÿ€g@ÿÞ¾ŒÿçÍ¥ùÎ±ƒûæÅ’ÿäÂŽÿ¾žkþÕ«hÿÍžUÿº‡7ÿ�e$÷[AÛ›n'üÐ›Iÿ×§[ÿ‰mAÿ€g@ÿÞ¿ŒÿçÍ¥ùÆ§vãÝ³rÿÚ°lÿÙ¬cÿÎ›Jÿ½‰9ÿ•j&ÿ[AýhJþ®}/ÿÐ™DÿÓŸMÿÙ¬eÿÚ°mÿâÁŒÿÖ»�Ø½¡t§Ú°nÿ×ªbÿÍ�Oÿ¸…3ÿ¢r(ÿZ ÿS;ÿ�\!ÿ½‡1ÿÎ•<ÿÓ OÿÚ®iÿÜ³qÿåÆ•ÿá¾†¥ª“pIÓ¯víÆ’@ÿ¿ˆ0ÿµ€-ÿ�f%ÿnNÿV=ÿ“i%ÿÂ‹2ÿÎ˜AÿÖ§\ÿØªbÿÝ¶wÿäÅ’éÚ°lC?2Æ©{’Ï£]ÿ»…1ÿšn'ÿ‹c$ÿlMÿfIÿ¬|/ÿÎ˜CÿÓ¡PÿÕ¤WÿÛ±nÿá¾‡úÜ³r|µc ¸œn §ŒbÙ¹‡±Í¥gÿŸw6ÿŠc$ÿhJÿjKÿ±„=ÿÕ¢PÿÖ§[ÿÙ®iÿÝ·zëÛ³r|Ì’9
ÑœI , êÅˆ Ô­qâ¿ˆ“Ü¹�ïÇ¢gÿ³ŽTÿ½˜]ÿ×±uòÕªg½Öªg¶×¬g‹Ñ S9ÁÈŒ1             Ù¬e Ó£Vàº~IãÀˆ äÂŠËåÃŒÀá¼‚hÂ�@®o¡M ¢Q             ð  À  €                                          €  À  à  (       @                                                                 ‚Q �\ …]«:eÃ•K¿ÉœTë¾•TðÅ�_ñÓ¨cóÐ£]ÙËœR­Â�Bi—i ®f·t                                                                 �n# •e¯�8a»ŽHÌÂ—SóÕ¦[ÿÔ£TÿÒ Qÿ×©`ÿÙ­gÿÚ¯lÿÛ²qÿÐ©løÀ�eÍÓ£W–É‘77·o¿~                                            ‚[ [9¥{9zÉšO÷ÐœIÿÊ“=ÿÇ�7ÿÃ‹3ÿÄŒ3ÿÍ–?ÿÐšDÿÒ�HÿÔ Oÿ×ªbÿÝ·zÿà»ƒÿÛ²rêÔ¡QŠÙš6Æ�A ý¿%                             m9Ì     H&†29'  ÿ ©|5t»ŒBñË•@ÿ»…1ÿ«y+ÿ¤t)ÿšm'ÿšm'ÿ­{,ÿ¼‡2ÿÇ�9ÿÏ™CÿÔ¢QÿÖ¥XÿÛ¯iÿÖ²yÿ¸›lþ™u<Ã³�26\aj Ã‚                     l8Ì p<Ð p;ÑDN)“°%—l%0»Š<åÅŽ7ÿ°},ÿ—k&ÿoOüT<ÜG3·G2³Z@ÑxUö¡r(ÿÃŒ5ÿÐ›GÿÔ¢Qÿ²ŠIÿ”…nÿ�xjÿ°˜rÿÙ°oÙÏ—>Bá¹z Æˆ(             p=Í n:Î n:Î6k9ÉÜ@"w¯  $U<�‰b'ÿ€[ÿnOÿQ:ë(
w         "OV=Ç˜l&ÿÅŒ3ÿ©=ÿœ”ˆÿ¶±«ÿº™eÿã½„ÿåÆ–ÿÛ±nÙÌ“86ÑœG ÄŠ-         n:Í n:Ín:ÎÂm9Ìÿ\0®òX-§åX.�õY0‘ÿM+{ÿ6Oÿ(¢  " :+dK#JlQ&hnZ<>'S;¹�d#ÿ�‚nÿÛÝßÿ®˜vÿÕ§^ÿÛ¯lÿá½†ÿåÆ•ÿØªaÂÍ�/Í”8     n;Ì n<Én:Î‰m9Îÿn9ÎÿuCÒÿQÕÿ†YØÿ…YÙÿQ×ÿsBÏÿ`3´ôB#}£ (jQ)_yZ(÷P:ÿ‘}]ðspkI -RF4áÊÊÉÿ×ÔÑÿ·“\ÿÚ«bÿØªbÿÜ²qÿãÁ�ÿß¾Šÿ¹ŒDvÿÓ… W8 m9Í m8Í7n:Îè}OÓÿ™tÝÿ©Šãÿ¬�äÿª‹äÿ¦†àÿ¡�ÛÿœyÜÿ�dÝÿo?ÇÿD#‚ª?3!M¡IíÄŸeÿÀ¨ƒàlcV*   †††ÈëìíÿÇ¿³ÿÀ“LÿÙ«cÿØªbÿØ«dÿà¹}ÿØ¼’ÿºžqÏÎ›J0Ì›M P»sAÏ—ŽeÙÿ§‡âÿ§‡ãÿ¡ßø¡~âÆ˜u§Èª�sÿšqXÿxY[ÿz_˜ÿ…^ÐÿT,¡ø/'­ u/ñâ½ƒÿ×¼’¼©_ (()'¬¬¬çôõöÿÀ´¢ÿÂ�=ÿØ©`ÿÙ¬fÿÚ¯jÿÞ¶xÿæÇ–ÿéÍ¡ÿØ«b—·j }OÒ(’kÛÝ£�áÿ¢áÿ£âÿ…h¹ÝK:s%¤x+3¼�FÜÉ”?ÿ¦v&ÿvT$ÿ`CEÿ[==ÿ…^(ÿÊ™LÿÞ¿�ýÁ¥zr†‰� 655C···õøøùÿ¹®�ÿ¾Œ=ÿÚ¬cÿÜ²pÿÜ²pÿÜ³rÿâÀ‰ÿéÏ¦ÿßºÞÏ˜A*•mÞ¡~â^¢á‰¢á¯£€âÐ‘rÊåJ9gdñÄù «‚@bÉœVïÌšKÿ¿Œ9ÿ³‚0ÿ¼Š7ÿÑ¡TÿÛ·þË¯�²®…E   <0®©§¤ÿêëìÿ¤œ�ÿ”n2ÿØ©`ÿÜ²qÿÜ²pÿÜ²oÿàº~ÿçË�ÿåÇ–ûÕ£Sl	 	    —sÿ­‡þ¦‚ë)bLŠ+   �g£|@KÅ�\ÂÍ¤cïÔªhüÖ¯rùÐ®yÞÈ§s�›wA¤v-"!+fIæ’q>ÿ©Œ]ÿ±‹Oÿ—o1ÿÐ¢YÿÜ²pÿÜ²pÿÜ²oÿÞ¶wÿåÆ”ÿãÉŸÿÉŸ\�zb=»Ÿ‚UÆŠpF¡t\7yZF%R6(/       Ð³o �q,®‰M5»–[O°ŽXE�o;%`H"¤z9{™n+œ 4rQë°}+ÿÌ–@ÿÔŸLÿÄ“EÿÔ£WÿÝ±lÿÜ±mÿÝ´rÿÞ¶wÿæÇ•ÿÒ¿ þ¬‘f­§ŒbòæÅ’ÿà¿ŒÿØ·„ÿÌ«yû¼�lð�xR†E7!)e<�x_7€lU1`VC%,sY1`‡j=y¢I¢¸‹EÙ©z1þƒ]!€2#^€[ ûµ�/ÿÏšGÿÔ¢RÿÖ£SÿÓ¤[ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò®”jýçÇ”ÿåÅ“ÿæÆ”ÿçÇ”ÿéÉ–ÿ¤�iéPC-ÃÒ®uþ×²vÿÆ¤mù†mFÛË¢aýÎ¡ZÿË—Fÿ´�0ÿˆ`"ßI4`_DÒ q(ÿÆŽ7ÿÕ¤Vÿ×¨]ÿÛ®eÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý°—oýçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿçÇ•ÿÁ¦|ÿ„oMÿà»€ÿß¹|ÿÛ³sÿ¿”QÿÊ”AÿÃ‹4ÿ¯|,ÿŠc#ü\B­L6Ì€[ ÿ®|,ÿÌ•=ÿÖ¦Yÿ×§\ÿÛ®dÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý®–pòçÇ•ÿåÅ“ÿåÄ‘ÿäÂŽÿãÀŠÿÛ·ÿÊ¢bÿØ¨^ÿÕ¤VÿÔ¡PÿÎ˜Cÿ¼…/ÿ§w*ÿŒd#ÿjKìC0àaEÿŽe$ÿ·‚.ÿÍ—BÿÔ OÿÔ¡PÿÕ¢SÿÓ¥\ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò¤ŽjÙá¾†ÿÞ¶xÿÜ³rÿÛ°mÿÚ®iÿÙ®hÿÖ¦YÿÓžLÿÓŸMÿÐœKÿÀ�<ÿ¢s)ÿ�e$ÿuSÿK5ùQ9þrQÿšm'ÿ»†1ÿÏšEÿÓŸLÿÓŸMÿÓŸLÿ×¨]ÿÝ²mÿÜ±mÿÝ´rÿÞ¶wÿçÉ™ÿÓÀ¢þ­’g­”^¬Û¶|ÿÙ¬eÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿØªaÿÒŸNÿÇ“Bÿµ‚3ÿ¬z,ÿ r(ÿ~Z ÿaEÿ@.ÿ^Cÿƒ]!ÿ£t)ÿÃ�7ÿÏ—?ÿÐ™BÿÒœHÿÓ OÿÚ®hÿÜ²qÿÜ²pÿÜ²oÿÞ¶xÿæÉšÿäË¤ÿÉŸ]�zgJlÕ¶†ûÚ¯iÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÔ¥[ÿ¿Œ<ÿ­z,ÿ«y+ÿ¨w*ÿŽe$ÿZ ÿR:ÿJ5ÿjKÿ�f%ÿ®|,ÿÈ�5ÿÏ–>ÿÏ—?ÿÏ—?ÿÔ¡QÿÛ°lÿÜ²pÿÜ²pÿÜ²oÿà¼‚ÿéÎ¤ÿæÈ™ûÕ£SkI9*ÃªƒÞß·yÿÙ­fÿÙ­hÿÖ©aÿË™KÿÁ‹5ÿ»„/ÿ®|,ÿ©x+ÿ’h%ÿ�\!ÿxVÿF1ÿV>ÿvTÿ–k&ÿ»…/ÿÉŽ2ÿË’7ÿÏ–>ÿÑšEÿ×§\ÿØ«dÿÚ®iÿÛ±nÿÝ´sÿäÄ�ÿëÓ¬ÿß¹~ÛÏ—@'   £�i–áÂ‘ÿØ¬fÿÎžQÿÃŽ:ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿšm'ÿ‚\!ÿ‚]!ÿiKÿB/ÿ_Dÿ€\ ÿ�p(ÿÀ‰0ÿÈŽ2ÿÈŽ2ÿÍ–?ÿÖ¦ZÿØªbÿØªbÿØªbÿÙ«dÿÞ·zÿçËŸÿèÍ£ÿ×©_� = „kC nX67Ï¶ŽéØ¯nÿ¿‰2ÿ¾†/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¬{,ÿ�e$ÿ…_"ÿ�\!ÿZ@ÿC/ÿdHÿˆa"ÿ¦v*ÿ¾‡0ÿÈ�4ÿÌ•>ÿÒŸNÿ×§]ÿØªbÿØªbÿØªaÿÚ­hÿá½…ÿèÌ¡ÿÞ·yÝÐšE+ÒžL '	    £ŠbŠßÂ“ÿÎ Vÿ¾‡1ÿ¾‡0ÿ¿‡0ÿ²~-ÿ‘h%ÿŒd$ÿŒd$ÿ‚]!ÿY@ÿL6ÿmNÿ“i%ÿµ‚1ÿÆ�9ÿÐœHÿÔ¢QÿÔ¢RÿÔ£Tÿ×¨^ÿØªbÿÙ¬fÿß¹~ÿæÈ™ÿà¼ƒ÷Ñ›HhòÐ› Ì—C     pW. [CÁ¦{ÂäÅ•ÿÏ VÿÀ‰3ÿµ�-ÿ•j&ÿ‹d$ÿŒd$ÿ�d$ÿyVÿbEÿ]Bÿ€[ ÿ­|,ÿË”>ÿÑšCÿÓžKÿÔ¢RÿÔ¢RÿÔ¢RÿÕ£TÿÙ¬eÿßºÿåÇ—ÿâÀŠüÓ¡QŽÆ‡#	Ì’7           Ç¢f Šl>6Ò¶‰ÙæÈ˜ÿÓ§bÿ§{4ÿ‹c$ÿ‹c#ÿŒd$ÿŠb#ÿmMÿcFÿ_CÿkLÿ˜m(ÿÉ”?ÿÑšCÿÒœFÿÔ¡QÿÔ¢RÿÕ£Tÿ×©_ÿÞ¶yÿåÇ—ÿà½„÷Ô¡RŽÊ�-Í“9                 + ÿÿê ª‡NBÝ¾�ÙæÉšÿÔ­pÿµ‹Hÿšq/ÿŽf&ÿ€[ ÿcFÿaDÿaDÿ`Dÿ‰f.ÿÓ¤XÿÕ£SÿÓŸMÿÖ¦ZÿÙ¬fÿÜ´tÿà»�ÿÞ¹ÿØ­hÝÑœJgÇˆ&	Ë�3                         mI ÿÿÿ Î V6à¼ƒÃçÉ›þãÁ‹ÿÕ­mÿÂ˜Uÿ¦~>ÿ�i1ÿŠg0ÿ•p6ÿ°‡FÿÏ¡Xÿß¹}ÿÛ´vÿØ®lÿÛ´vÿÞ¸}ÿÛ´uùÖ©bÙÎšG‹ÆŠ,)­V À}                                 ±p Ý²m ÐœIÛ²q‹äÄ‘ëçËžÿåÆ”ÿàº}ÿÜ³rÿÛ±oÿÝ´sÿá»~ÿãÁŒÿãÃ�ðÍŸWŠÂ‘D‰Æ•H‘Í™F{É‘9OÂ…%¬e ¶r                                                 Ì’6 Å„"Ô¤V9Ü´t—âÀŠÛäÅ”÷æÈ™ÿæÊœÿçÊ�ÿæÉ›úá¿ˆ×Ù®ifÉ�.ÐšF                                                                                 Ê‹( À~Ð›F$Ö§[WÙ®h‚Û±n”Ú°m‰Øªb`Ñ�K"ºn Å…#                                                     ÿÀÿÿ€ ÿ  ?ù  ð  à  À €  €                 À                                      €  €  À  à  ð  ø  ü  þ ÿÿ€?ÿ(   0   `           $                                                                                  ?, Ê�+ ¦t$¯|,e¶…7¨¼�A×Â“Hó§�Dß¯‰LàÍžT÷ÊšNæÇ•FÌÃ�=£¿ˆ2nº‚(6¼ƒ"   õàX                                                                                                                 ”d uE ¡q%'šo,t™u<³ËŸYûÔ©dÿ×¬gÿÙ­fÿÏ¥bÿÓ­pÿÞ·zÿÝ·zÿÜ¶zÿÚ³uÿÕ¬küÏ¢Zê¨~<¢šo*LÆŠ*(¾}Â„                                                                                                      �n# ˜i¥v,d¶‰AÛÇšTþÂ˜Uþ×¨]ÿÕ£TÿÒŸMÿÐœHÿÑ�IÿÖ¥XÿÖ§\ÿ×©_ÿØ«dÿÚ¯kÿÜ³sÿÞ·zÿ¼žnúÏ«t÷Ô¤ZâË”<�ÅŠ+.¿Â…$                                                                                         Šb! }T¨z1†Á”L÷Ô¤XÿÓžKÿÎ˜AÿÍ–?ÿÊ’8ÿÈ�4ÿÇ�2ÿÈ�4ÿÐ˜AÿÑ›DÿÒ›EÿÒœGÿÓŸLÿÕ£TÿØªbÿÝµwÿá½…ÿãÂŽÿÞ¹~ÿÒ¢WãÉ�7|Ã‡(ÇŒ/ ¼                                                             H*t <$`$    šm& ¤s%
ˆb&n©‚DæÕ£TÿÏ˜BÿÅŽ7ÿ¼†1ÿ»…/ÿ¹„.ÿ¶�-ÿ´€-ÿ¶‚.ÿÂŒ5ÿÇ�9ÿË”=ÿÏ˜AÿÑšCÿÑšCÿÔ¡Pÿ×¨]ÿÚ¯kÿÝµwÿá½…ÿãÃ�ÿÜ´týÒœGÀÐ“3;íšÙ—/                                                     o<Î žUÿK(‹^-S8_ «‚> žq)h¸ŠA÷Æ“CÿË”<ÿÀ‰3ÿ²-ÿ¦v*ÿ r)ÿ�p(ÿ–j&ÿ’h%ÿ•j&ÿ¥u)ÿ°},ÿº„/ÿÂ‹4ÿÉ’:ÿÑœGÿÔ¢RÿÔ¢QÿÔ£Sÿ×¨^ÿÝ³pÿÕ¯uÿ¹Ÿvÿ”{Tÿ‰e,ã±0_ë§;Ê‘6                                             m9Í l8Ìo:ÐtF%ƒÓ)R9 ˜k$'°‚:ÚÎšGÿÅŒ2ÿ·‚.ÿ¬z,ÿœo(ÿˆ`"ÿoNÿ\BýM7òG2éK5î_CúvTÿ’h%ÿªx+ÿ¼…/ÿÊ’9ÿÑ�JÿÔ¢RÿÕ¢RÿÓ¡Qÿ¥€Dÿ{mWÿxtpÿ`VGÿ¶Ÿ{ÿÖ«eñÎ•;rÆŠ,É�4                                     n;Í o<Ìn:Ïrh7Ãø2\Ÿ   ÄŠ0 |X³ƒ5ÿ¾ˆ4ÿ±~,ÿ¡s)ÿ‘g%ÿvSÿI3õ&
´f9   *1Q&
“F2ßrQÿ¡r)ÿ¿ˆ0ÿÉ�5ÿÐ›GÿÐŸOÿŠl;ÿ€{sÿ¿ÀÁÿ�‚oÿËªwÿçÆ”ÿèÌŸÿÙ­gôÍ”:rÈŽ2Ë“:                             m9Ì {Eç n:Í^o;Ðñ]1®ÿ,   %5L6Î€[ÿwUÿjLÿcGÿX?ÿ5&ä`   
                     )*žeHø�p(ÿ¿‡0ÿÈ�4ÿ†f4ÿˆ…‚ÿäåæÿ ˜Œÿ¸�SÿÞ´rÿà¼„ÿäÄ’ÿçËŸÿ×ªañÌ’7_ÿÿ� È�7                     q?Î m:Í n:Í<n:Îâo:Ïÿe5½ÿM)‘ïN)’çM)�êN*†üP,~ÿH)lÿ:"Pÿ&,ÿøc#         	  4(I81?1&   
!cF÷¤t)ÿ’h&ÿ{ulÿáâãÿÔÓÓÿ—}SÿÙªaÿØªbÿÜ³sÿá¼…ÿåÆ•ÿæÉ›ÿÔ£TâÊ�3<Ì’7 Ê‘8                 n;Í n;Ìn:Î¿n:Îÿn:Îÿn:Ïÿo:Ðÿn9Ðÿn8Ðÿn8Ñÿm8Ñÿm8Ðÿk7Ìÿd4½ÿO*–û6e¹%G    fM$ƒvX'ÜmP#îx[.æ…u[­AAA)   )“iJÿdWBÿÉÉÊÿ÷÷øÿ¨¢˜ÿº’SÿÚ«cÿØªbÿØ«cÿÝ¶xÿá½‡ÿçÊœÿãÁŒÿÑ›E¾Ï“6Ð—< ®{*         n<É _�  n:Í{n:Îþn:Îÿm8Îÿm9ÎÿsAÐÿQÔÿ‰_×ÿ�fÙÿ�gÙÿŠ`×ÿ�TÕÿwEÒÿp;Ñÿi7ÆÿO)“î"@x   $=“o6ódHÿ-
ÿM9ÿº§‰ÿa`]„´±¬  &Ï”“�ÿèèéÿôôöÿ”…lÿÐ£\ÿØªbÿØªbÿØªbÿÙ¬fÿß¹ÿâ¿ŠÿéÎ£ÿÐ©kù¦v*T°2 _=         n;Í n;Í.n:Îàm8Îÿq>Ïÿ…ZÖÿ¢€ßÿ³—æÿ·œçÿ´˜æÿ°“æÿ®�æÿ­Žæÿ«‹æÿ¦…ãÿ—pÝÿ}OÔÿo;ÐÿV-¡÷!?s   hBºÀ™[ÿÁ—VÿÌ§kÿº¨‹çFDAAlha    III«ÈÈÈÿñññÿççèÿ“xMÿÖ¦YÿØªbÿØªbÿØªbÿØªaÿÛ°nÿá¼„ÿáÂ‘ÿ¦”xù™zI¤Ð›G$È–H     m9Ì m:Êm9Í�n;Îÿ„XÕÿ§‡áÿ´™æÿ­Žäÿ¥ƒâÿ¢áÿ¡~áÿ�{Úÿ›yÊÿ–t¹ÿ�m°ÿŠl¸ÿ™yÒÿ£�ãÿ‰^Øÿp<ÏÿG%‡ê>:*Š©€@ÿÞµuÿäÌ¦ÿÂ§}¼g. %
    zzy×ÜÜÜÿøøøÿÚÚÚÿ˜u=ÿÕ MÿØªbÿØªbÿØªbÿØªcÿÙ­gÿà¼‚ÿäÄ“ÿçÑ­ÿáÀ‹ÿÓŸN�Ë”;ÑžL m9Ì l7Ë(r@Ïá’kÚÿ¬�äÿ§†ãÿ¢~áÿ¡~áÿ¡~ßø¢áËž{ÜŠŠikÉ²ˆWÿ²‚>ÿ˜m/ÿvU+ÿW@?ÿnU“ÿ–sØÿwIÍÿO'œÿ/ÉaEß¼ˆ6ÿÜ²pÿêÒ¬ÿÈ¨uŸ    4˜——ïãããÿüüüÿÒÑÐÿžw9ÿÒšAÿ×¨_ÿÙ«dÿÚ­hÿÛ°mÿÜ±oÿÞ·zÿäÄ‘ÿèÌ ÿëÔ®ÿØªbáÐšE(ÒžM ‡[Ø xHÐs“lÛÿ¥„âÿ¢áÿ¢áÿ¢áÿ¡~ßÿpWœÉ^I�“j ¤v)[À“KõÎ›JÿÃŒ5ÿªy*ÿ„^ÿX?ÿL5JÿH-\ÿ@(:ÿ`C!ÿ¥u*ÿÎ›Jÿá¾‡ÿÕÀ�ô²�TXÀ¢r **) $##G¥¥¥øåååÿþþþÿÏÎÌÿ y:ÿÒš@ÿØ©`ÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿâ¿‰ÿæÆ•ÿìÖ²ÿà¼‚ÿÒ�JrÕ¡N l;Ç“lÛš¢áî¢áú¢áÿ¢áÿ¢áÿ£€ãÿw\¥ï!A:+0 ¡n�l2ƒÆœZýÔ NÿÃŒ5ÿ±~-ÿ�o'ÿŠb ÿ†_ÿ—l$ÿ´�/ÿË–CÿÜ³rÿåÊ ÿ½Ÿq¯c: E2    �¥¥¥ÿæææÿþþþÿÌÌÌÿsY1ÿË˜HÿØ©^ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿß¹~ÿåÅ’ÿêÐ§ÿèÍ¡ÿÕ£U»Ï™DˆbÌ¡~ß¡~à.¡}àN¡~àt¡~à›¢~á¿¢âÜ™xÕôL;k®   oP  Ÿp&¸ŒE¹Ê ]þÒ£XÿÎ™EÿÅ�9ÿÂŒ7ÿÃ�7ÿË•?ÿÔ¢Sÿß·yÿÜ¾�þ½£xÆ±…@4·‘X %	 VA1ö›š™ÿÜÝßÿôõöÿÁÀ¾ÿeM'ÿšs6ÿØ¦XÿÜ²oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÝµuÿäÃ�ÿçÊœÿìÖ²ÿÙ­gèÐšF6                žyß štßžzß
 }ß¤�å9kS–O §x.  p$•r;|ÆžaìÕ«jÿÕ«hÿÚ®gÿÙ®jÿß¸{ÿÙ·‚þÑ´…ôÅ¢k°�h.&i žq*    +�uTÿy`7ÿ‰uTÿ–‚cÿ™~Rÿ§|7ÿ‚a+ÿÔ¢SÿÛ°mÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²qÿâ¿‰ÿæÆ–ÿí×´ÿáº~üÐœHn#Q8*d? "                                  ¤q" šg­5@ª„H„¸•^»Î¨mÜ»›iÏÉ¦nËº–^™—t=D¬u"  œt4M—m)€   - —…_"ÿ¨w)ÿ¼†0ÿÌ˜EÿÔŸLÿÆ”Dÿ•o2ÿÒ PÿÛ¯kÿÜ²qÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà»�ÿåÆ”ÿãÌ§ÿ°˜tï•o3YbN.Ëº˜dÿ«ŒZô”wJâ|b:ÆdN+¤K:}1$W5                    e9 5  œh¯{)�n#¢g­J    SA%(›w=†©|3î‡`"—    0" †_"ÿ©x*ÿÁŠ4ÿÑœIÿÓŸMÿÒžLÿÍšJÿÓ OÿÚ®iÿÜ°mÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá¼ƒÿèËŸÿàË«ÿ´¥�õ¶�T›{eAçåÄ�ÿèÇ”ÿæÅ‘ÿâÀ‹ÿÙ·�ÿË©tÿ¸˜eü£…Tò�h@¡	7*C3g5(Z%D5		''5D3KhQ,r‘rA©´‹Jã¾‹;þ•j&þwUb   C/Ì�e$ÿ«y+ÿÂ‹5ÿÑ�KÿÓŸNÿÓ NÿÔ OÿÕ£TÿÖ§]ÿ»‹?ÿ¨|6ÿº’SÿÛ¶zÿà»ÿâÀ‰ÿéÏ¥ÿîÙ¸ÿòßÁÿÚ¯iæ†oKõåÅ’ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿæÆ•ÿçÇ•ÿêÈ•ÿ¹žtõ!WUE-z¸–`ý¹–]ý­‹V÷¥„Pò{c<¢aL+¢€Iê®ŠQð¼–YùÊ ^ÿÎ�QÿÅŽ9ÿ¢s(ÿ{XÙhJ"&
ojKû¡r(ÿ¹„/ÿË”=ÿÕ¤WÿÖ¦YÿÖ¦Zÿ×¨\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö�vRþæÆ”ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿÓ¶‡ÿ0)Þ]N5éà»€ÿâ½‚ÿã½�ÿå¿‚ÿ¢‡\ú~fAöàµqÿÛ¯iÿÓ¢VÿÉ“>ÿÀˆ1ÿ¦v*ÿ‚]!ýqQx!	TU=êŒc#ÿ¬z,ÿÅ�3ÿÑœGÿ×¨]ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�yVþçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿäÄ“ÿ]O;ÿˆrNÿä¾‚ÿà»�ÿà»�ÿá¼€ÿÌ¨oÿ·�PÿÎ›KÿÆ�9ÿÄŠ1ÿ¾†/ÿ¥v*ÿ‡`"ÿsRÆ1#mK5åvSÿ™m'ÿ´.ÿÊ‘6ÿÓ¡Pÿ×¨^ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�xWõæÇ—ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ”ÿèÇ•ÿ¤Œgÿºšhÿá¹{ÿÝ´sÿÚ®iÿ×¨^ÿÕ¢SÿÈ‘:ÿÃ‰0ÿÃŠ1ÿ¸‚.ÿ r)ÿŠb#ÿuTóH4¦>,äbEÿ�\ ÿžp(ÿ¹ƒ.ÿÈ�7ÿÓ OÿÕ£UÿÕ¥WÿÖ¦Yÿ×§\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö…qRçåÇ˜ÿåÅ“ÿåÅ”ÿåÅ“ÿåÄ’ÿäÃ�ÿãÁ‹ÿá¾†ÿàºÿÖ¯pÿÓ¤YÿÕ£SÿÓ OÿÓŸMÿÓŸLÿÓŸMÿÌ–@ÿ¿ˆ0ÿ®{,ÿ›n'ÿ�e$ÿxVÿ]Cß<+çP9ÿkLÿ‰a#ÿ¥u*ÿÀˆ0ÿË•?ÿÓŸMÿÓŸMÿÓŸMÿÓŸNÿÓ OÿÕ£Tÿ×¨^ÿ»‹?ÿ¨|6ÿ»’SÿÛ¶{ÿà»ÿâ¿‰ÿéÎ¥ÿîÙ¸ÿòßÁÿÚ¯iæxeIËáÄ–ÿâ¾‡ÿà»�ÿÞ·zÿÜ´tÿÛ±nÿÚ¯jÿÙ­hÿÙ­gÿÙ¬eÿÔ¢RÿÓŸLÿÓŸMÿÓŸMÿÓŸMÿÒžLÿÄ‘?ÿ¤u*ÿ–k&ÿ‘g%ÿ{WÿkLýB/õJ5ÿ_CÿtSÿ‘g%ÿ¬z+ÿ¼†1ÿÏšEÿÓŸMÿÓŸMÿÓŸMÿÓŸMÿÓŸLÿÕ£TÿÛ°mÿÜ°lÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá½…ÿéÍ¢ÿàÌ­ÿµ¦�õ¶�T›dS8£Ø»�ÿÛ°lÿÙ­gÿÙ­fÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÖ¥YÿÓŸMÿÓŸMÿÓŸMÿË—Fÿ¹‡7ÿ­{-ÿ¤t)ÿ•j&ÿ}Y ÿsRÿT<ÿ9(ÿS;ÿlLÿZ ÿ˜l'ÿ³-ÿÃ�7ÿÏ—@ÿÐšDÿÒ�JÿÓŸMÿÓŸMÿÓŸMÿ×¨]ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿá½…ÿçÊ›ÿäÎ¬ÿ°™vï”n3YI:#nÊ±‰üÞ¶vÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿØªaÿÔ OÿÎ›Iÿ¾‹;ÿ¯}.ÿªy+ÿ«y+ÿ©x+ÿ�d$ÿuTÿlMÿ@-ÿC0ÿX?ÿvTÿŠb#ÿ¡s)ÿ±.ÿÌ•=ÿÏ—?ÿÏ—?ÿÏ˜@ÿÑ›FÿÒžKÿÔ PÿÚ®hÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿãÂŽÿçÊ�ÿîÚ¹ÿá»üÐ›Hn!6²›wèäÁŠÿÙ¬fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ®hÿØ«cÿÈ•Fÿ²€1ÿ«y+ÿ«y+ÿ«y+ÿ«y+ÿ—k&ÿ‚]!ÿ€[!ÿ`Dÿ:)ÿO8ÿbFÿxUÿ˜l'ÿ¥v*ÿ»…/ÿÌ“9ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ˜AÿÕ£UÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÞ¶wÿåÇ–ÿèÎ£ÿíØ¶ÿÙ­gèÑ›F5   �yW»åÉ�ÿÚ¯lÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­hÿÙ¬fÿÑ¢XÿÆ‘?ÿ»…0ÿ­{+ÿ«y+ÿ«y+ÿ«y+ÿœo'ÿƒ^"ÿ�\!ÿ[!ÿN7ÿ@.ÿV>ÿmNÿ~Y ÿ�p(ÿ®|,ÿÆ�2ÿÈ�3ÿÌ”:ÿÏ—?ÿÏ—?ÿÏ—?ÿÐšDÿ×§\ÿÙ¬fÿÛ°lÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà¼ƒÿæÉšÿëÔ®ÿèÍ¢ÿÔ£T¹ÎšGâ¶q cO1r×¿™ÿà»�ÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÔ¦]ÿÉ–FÿÀ‰3ÿ¾†/ÿ¾‡0ÿ¸‚.ÿ¬z+ÿ«y+ÿ r(ÿ†_"ÿ�\!ÿ‚]!ÿuTÿ?-ÿH3ÿ^CÿsRÿ‰b#ÿšn'ÿº„/ÿÉŽ2ÿÈŽ2ÿÉ�3ÿÍ•<ÿÏ—?ÿÐ˜AÿÕ¤VÿØªbÿØªbÿØªcÿÙ­gÿÛ±mÿÜ²pÿÝ´sÿäÄ‘ÿçË�ÿîÙ¹ÿßºþÑ�IlÔ N 3' '(²šuàéÍ¢ÿÚ°lÿÙ­gÿÖ©aÿÌšLÿÁ‹6ÿ¾‡/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ·‚.ÿ¥u*ÿ‰a#ÿ€\!ÿ�\!ÿ‚]!ÿeHÿ:)ÿN8ÿeHÿxUÿ‘g%ÿ�p(ÿ¿ˆ0ÿÈŽ2ÿÈŽ2ÿÈŽ2ÿÉ�4ÿÎ—?ÿÔ¢TÿØªbÿØªbÿØªbÿØªbÿØªbÿØ«dÿÚ®iÿàºÿæÈ™ÿêÑ©ÿëÓ­ÿ×¨]ØÐ›F!ÒžM     }eA�áÊ¥ÿá¾‡ÿÑ¡VÿÃŽ;ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿ•j&ÿ‚]!ÿ�\!ÿ�\!ÿ[ ÿV=ÿ;*ÿQ:ÿiKÿ~Z ÿ•j&ÿ¥v*ÿ½‡0ÿÇŽ2ÿÈŽ2ÿÈŽ2ÿÊ‘6ÿÑ�KÿØ©`ÿØªbÿØªbÿØªbÿØªbÿØªbÿØªaÿÙ­hÿá¾†ÿåÈ˜ÿíÙ¸ÿà¼‚ÿÒžK|á«R ÏœM     K8 9(.·�uáêÏ¥ÿÑ£[ÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¼†/ÿŸr)ÿŒd$ÿŠc#ÿ…_"ÿ‚]!ÿvTÿL7ÿ=+ÿT<ÿlMÿ„^!ÿ—l&ÿ®|,ÿº…/ÿÄ‹1ÿÉ�4ÿÌ–>ÿÒŸMÿÔ¢RÿÕ¥XÿØªaÿØªbÿØªbÿØªbÿØªbÿØ«dÿÞ¸{ÿâÀŠÿçÌ ÿæÈ™ÿÔ£UËÐ›GÑžL              x_8}ÙÀ—þåÅ“ÿÍœPÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ½‡0ÿ¥v*ÿ�d$ÿŒd$ÿŒd$ÿŒd$ÿŠb#ÿoOÿO8ÿ?-ÿU<ÿmNÿˆa"ÿ›o'ÿ¶‚/ÿ¾‰3ÿÈ’<ÿÑžKÿÔ¢QÿÔ¢RÿÔ¢RÿÔ¢RÿÖ¦ZÿØªbÿØªbÿØªbÿØªbÿÝµuÿâ¿‰ÿåÇ—ÿèÎ¤ÿÖ§]ðÌ“:QÐ–: Í™H             :* ! £‡Z¾èÐ©ÿá¾‡ÿÌ›Oÿ¿ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ«z+ÿŽf%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿˆa#ÿjKÿ_CÿT;ÿgIÿ‚]!ÿ r(ÿµ‚0ÿË•>ÿÏ™BÿÑ›FÿÔ¡QÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢SÿÖ§\ÿØªbÿØªcÿÜ´tÿá¿ˆÿäÅ”ÿéÐ§ÿÚ°mûÎ–=‚Ë‘7Í•=                     Žl7 ]E;À£tâìÓ­ÿà¼ƒÿÏŸTÿÀŠ4ÿ¾‡/ÿ°}-ÿ‘g%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿ�d$ÿZ ÿdGÿcFÿZ@ÿhJÿ‰b#ÿªy+ÿÀ‹5ÿÐ™CÿÑšCÿÑšCÿÓŸMÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢Sÿ×©`ÿÝ¶wÿâ¿ˆÿåÆ”ÿéÏ¦ÿÜ³sýÏ˜AšÊ‘6Í”;                          ÿÿÿ €b3_Ñ³„ñìÔ®ÿá¾†ÿÔ§_ÿ½‹;ÿ”j&ÿ‹c#ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿrQÿbFÿcFÿ_Dÿ]BÿxVÿ�p(ÿ»†2ÿÏ˜AÿÑšCÿÑšCÿÒ�IÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢QÿÔ¢RÿÖ¦[ÿÛ±oÿá¾‡ÿæÉšÿèÎ£ÿÛ±nûÏ˜AšÎ•;Î–>                                 7(    šxArÚ»‹ôìÕ°ÿãÁŒÿÔ©fÿ±‡Dÿ”l+ÿ‹c#ÿ‹c#ÿŒd$ÿŒd$ÿ†`"ÿhJÿcFÿcFÿcFÿ_Cÿ_DÿjKÿ¬€9ÿÓŸMÿÑšDÿÑšBÿÑ›DÿÓ OÿÔ¢RÿÔ£TÿÖ§[ÿÙ­hÿÜ³tÿß¹~ÿäÅ“ÿäÅ”ÿ×©`ðÎ–?�Ê‘7Ì“9 _'                                      _F ( ²‰IqÞ½ˆñëÒ¬ÿäÃ�ÿÜ³sÿË [ÿ¯…Bÿ—o.ÿ�e%ÿ‹c#ÿzWÿbEÿbEÿbEÿbEÿaEÿ_CÿtV'ÿÈ™NÿÚ­fÿÖ¦ZÿÔ OÿÔ OÿÖ¦ZÿÙ¬fÿÛ°nÿÝµwÿßº�ÿâÁŒÿáÀ‹ÿ×¬hýÎ™EÊÌ”:PÊ�6Ë’8                                                 œs1 wQÏžP_Þ¸zãéÏ¦ÿçËŸÿá½„ÿÛ²pÿÐ¥`ÿ½“Oÿ«�>ÿˆd,ÿsS"ÿoP ÿpQ!ÿwW%ÿ‰f/ÿ«‚BÿÌœPÿØ©_ÿàºÿà»‚ÿÜ´tÿÜ³rÿÞ¶xÿá¾†ÿâÀ‹ÿâÀ‹ÿÞº€ÿ×ªeüÍ™FÕÇ�2xÄ‰*ÌŽ- ¿‡/                                                         Î˜B Á~Ñ�K<Ù®iÁåÆ–ýêÒ«ÿæÉ›ÿá¾†ÿÞ¶wÿÚ¯lÿÒ¥]ÿËžVÿÇšTÿÇ›TÿÎ XÿÖ¨^ÿÚ­dÿÚ­gÿß¹}ÿçÊœÿÔ«jóËžVöÏ¤`þÐ¦dÿÕªfýÔ¥\ôÏœKÜÊ“;«Å‹/bÃ‡)½�%¿„'                                                                     µz# Ö£R Î™CÕ¤W€Þ·yåçËžÿëÓ­ÿéÎ¤ÿäÃ�ÿà»€ÿß·yÿÞ¶vÿÞ¶uÿÞ·xÿßº~ÿâ¿ˆÿäÄ‘ÿéÎ£ÿá¾†ïÎœL`¶'C¸‚,`¹ƒ-eÁˆ-YÅ‰+=Ã‡'Á„#ÈŒ) ¦g                                                                                     Í•= È�2ÐœH0Ö¦Z’ÝµváäÅ“ýèÍ¢ÿéÏ§ÿéÏ¦ÿèÎ£ÿèÍ£ÿéÏ¦ÿêÑ«ÿëÓ­ÿæÉ›ÿÞ·yåÔ¤VhÊ‘6Ð›H                                                                                                                             Î–< Ê�5Ð›F&Ó¡Qj×©`¬Û²p×ß¹~íá¿‡öâÁŒùâÀŠöà»�ëÛ²qÎÖ§[�Ñ�K2Ê�5Î—A                                                                                                                                         œ= â¶S ÉŽ4Ï˜AÑœG;ÒžLQÒžLXÑžKPÐ›G7Î–=Ä„$Ç‹,                                                                                         ÿÿÀ ÿÿ  ÿþ  ÿ  ÿü  ÿ  ÿø  ÿ  ÿ0   ÿ  þ0     ü    ?  ø      ø €   ð <    à     à     À     €     €     €              0    ø     ü       ?€                                                                                            €      €      €      À      à      à      ð      ø      ø    ?  ü      þ   ÿ  ÿ   ÿ  ÿÀ  ÿ  ÿà ÿÿ  ÿø ÿÿ  ÿÿ ÿÿ  ‰PNG

   IHDR         \r¨f  € IDATxÚì}wœå™ÿ÷�ª.moöº¬;®‚ÁØ„ÐB	Ž$€Ó+I(ù]r	wÀÝåîRH%…�5	�\$@(¡0Ýlã¾öö¦®éïï�ÑhUFÒhW[Lüý|ÖÞ�F3£yž÷y¾OŽáŽáŽáŽáŽáŽádªOàÊcÃõ÷‡˜Æ–€ÝkFOTîO©çŸ¼Cžêó<†£ÇÀcÃõ÷‡hMÝ¬P °ŒaÈ
Ý �„�v AÏ¶k­srCSƒ°t
,Öºß0èÖp4ºÝxðW»Ž)ˆc°Ã10‰Øpýý!ÒÔ¶šg¹UA7·VÑéJŽeæNÆgkºñ¥t;�¥¤gŸúâÚÎ©¾Ç0õ8¦ &–À‡<âûŠÓ8–Y5ÕçdAÓ�7‚¿‡#w?{ÕÉ[§ú|ŽajpLTº¥�ã„KÝ{CõSŽgªy|.ïÓèø�©éÆþ”¢ß¢iÊ=Ç,ƒ,S U@–Ð_:ÖU>äâpq¹9E!77ÏÂ#0à¯À‚gí¿.U§H(:Tƒ"©ˆÊÂ)IÇ`BÁHRu¤(M5t0wG¢Ñï³
þ1pLŒ®¿?œ5ç ä“ËœZÉ{¼<Z"š¼ý"¼|Qá®T�b8©¢'*ãHTÅ�á$Í(ùô�ýÃá?¦ÞÝ8¦ *Ä)?|nE0¸Æ-pç8eè›}<f×ºÑr¡5 L¨°;E_LÁ;ƒ)ìêO",iE÷S5ýÎè¡_yæÆÂS}ÎÇP}Lý“x”à¼_o½ÌéjïâÌ«saN­í5.xÒ ªN¡Šf@5L›Ý0(ô"æ;K †!àók8Ó]¨DÁ$U=Q;ûSØ3�°u8†IŠvÕƒŸXq÷$ßöc˜`S %°~Óf±ö²k.!7–×¹8K=XÚìÅŒ ˜`;$UŠf@ÖH…fPõ*°yYpó&gàáST	%ÕQW@Ñ¼ÑÇŽ¾„­‹ jú�#wÿ3Çr
Þ=8¦ l°~ÓfÑýOW}Å-°Ÿ-%øæ7x±¬Ù‹yu.pì¨�¥T=ó{R5“4HÍÙ>Ùpó,‚.6‡PÌV ,Eðfw¬À"Ðtã�X2uÁ±hÁ»Ç@,Á¯ñ
ÿ\Ê¿¹8¬žáÃÊ6?Ü<[ðzJÕ3,üT
|)dGÎÞ:ˆIžÞAgXÊÙ®éÆþX2µñ˜8úqL¤‘öñKšúóëÜXÓ@G�»à5Kè“ê¨9_‰ð«…®›«±F	´ôï¥\	 ÿŸcp„‚e™Ì6'ˆ+|ƒ:/¯ÀÚîóv_ÏíÉ±Ž)�wþáÀ©?{åô€[üv±ø=G€%Í>œ<'ˆ:Ÿóš¦ˆÈ¦àÛùðÅ€¤ê�4“ðÓt
Å¨®ÿo�·E
º8o/ÜqeÔ9‚F/¿‹+Øo ®â¡]CH(£×¤éÆ‘ƒû7‹½ø‡U º¥½Îïù�r¡ÝëV¶ú±~N�<�ˆJÂ’†¤R:–®’ª9íû+šQ•Ì½±B`Ü<¯Èf¬„¸Í5øÍ~¡À5H(:Ú9„�„šÙÆ€þñW,ûÐÔ]Õ1Œÿp
Àòó½<þÛ.M·˜à—[í³‘RõÌ*‘§'ÀdLþlò25n-1g›¢¸ÿ­Á% iúåÇB„G'þ¡À)?|nE(¼­˜¹¿´Éƒ59¦¾¦H¨ˆH¥9¥êˆ+F�ÙïtÕ7zÚ÷×©ù+§Ù¸œåû3 K8–K(Æyé�aˆÊ¼‚°#4EŽ`fPÌ±ÍÀ}Û2	Dšnì¾ë¦%váÁõ›6‹ÌyŸZÔwh_jœ+xõº®µ €¡H�ùû3‚« X–ëQ’ÑA—7Ðçóˆ½„»�ñÕÇ?„Øpýý¡š9s¿É0ÌWí^o¹pÆ‚šœÕÎ‰à[+}¬„+ é’¦gÓ0L—@Ö)4ƒBÕ�LP5`%ñ,G rÅk,`¡”"h¹G-¢pJÃïßìË(·XJýÚãŸ]õ��?ÝÒK©TM{Ç«´TlÙX¯…< Ü¨2¦”FÐCšª¼¡ËÉíõ[i_×+Ç8ˆ±ã]¯ Ò$ß/ìØý�‹Ã¦y!,möe¶•|Í�é;ZM§N©�4Šdº`g²a��…‡gr”Q¶°Ô¸ù× ÁË£Á7*�ïô'ðøÞ°ußöïÛ€åD×¬j�7ë	:Ú�Pc»¦*oð÷„ßÍ?sÌRpŽw­X¿i³XÅµÿi·ês8af ›:B™‡ÜòñâªíñŠ™øvˆËd�"&kÐ)ªºÂW~��_ä rÄV ¦kQë.Œäó~{�a	á„„¡¡¡ª�cþê_	5¶SÃx8àÿ¦ýáæg�e.Ç»R”òõ["ÎYT›óG%	µh(/œÒJ
°eæGåâ
Â.ãnªaE6a?‘Aƒ/—Ì¶Â)¿y£=C$ñ²ŸéxE^vô~
<%}ß:§KHr�ªÜ3JiÔPåûkÞ»�)ƒB¼ëÀy¿ÞzãŽ|†Ÿ#ÀÆŽNœÊlK©:úb
$–.*kHÈ¥Mö¸¬•úlLG ˜¡=Ž >‘+ªD– Ù/ä¸3ƒBÆ:xl÷0ž~»’¬d^o¯ñ èá9]Ü‹¢8–�O0÷�+")1YÇ@BEXÒNH§4GÇÊ†¥”pÿ­;ÿç’ç§úÞO¼kÀ†ëïfÍùÏ±Wä¿ÖráÜ%uv¿”Ÿ_nÅW41YÏ˜÷N1ÝÜ Ù‰=ê½<Î&`£æÕ¹ pz¢2~ýü^´´5Ô¡ÎËW”�˜�R‰K$UG_BCOTF_$itÇuFÓœ+B�ír<|g�¡üê™D|W(€´ÉÿÇ|¢ÏnÕ/fî—üJVûb(fÈª=…šˆ"ž’AÔÉÌ¿W¥DÎ¾¼Ë \.x!PÁw b�)†l`ÁêN”�|%à´×¸ hvõ'Ç|_
>ßÍUüÕ è�)8‘qd ‚ž¤3‹Ë²
‚.ö²ÒQ¯ ÎûõÖË\÷Ãüâ�/�Ž«ÏøúÅV}Í00’*^´‘tŒ$•ŠVûbHÄ"ˆŽc¤¿R¸ƒ±”èŒ<!/B¬iBSC=¼¡:„ZÚá	Ô”?'Åþº]ƒZŸÉ7°àX4û…Ìß3ƒt
tŽH(‡låªeÝP.¦ä’cþ�qÅÀ¾¡ÆŒÎ°ìè€,!OÄûÝø�äÕ
à‚Û·}×Žå_ÚäÁyKê3+UJÕÑUrV}+œgÃ×tŠˆ¤UlæçÃøD4ŒÃýÃP#�ú'/BÅ¸¼hm›ÿÌ…¨ŸÙak%S €iA5úÅ%Pïát›î”È™=¬è‰ÕÐ$¥QÈšÍ Mw|ýâh¨R`8–”­g(‡¸b`÷@o÷Dq,!OxEæ;OaõãòÅL#•
`Ãõ÷‡::þ7?�Ÿ#ÀY‹ê°ªÍŸÙÖ•VýRßPB³à«ŠŒ�á’ƒ]8Ü?C.4‹“]{@õÊ	¬ñ‚°Úfw eÁr[FCõ¥€uOí”À¬�˜£`‡*ªUÙr•6ÿEŽÀ'rf£Ô¬š§è‰*ØÑ—ÀÞÁ$ÊqÿÁQ§ :>wóÜãÖžò‡ü_ÈÅáâå“ßŽá/eî�ÕÔWƒ½ÝéïEÏÀ`Ùý•È ÔÈÀ”ÞCÎÂ‚«Ñ4yÙæ €é4ú„œmÙ®Àî�ä¸ x–�·Â.ê"GàâXø]\E®ƒ¤êx«?åÈ*`	yÂM”¯¾9‚£J´žÿ•uKO9û/¾†¶n­ZÖ�Ia�Jº£JÎ{­VÙùˆË†SzE°ªS |dŸ#¡Ï†¡iHuï™ê[	 àƒ˜¿t%‚s––Ý×Ž´¬€½åãÿNàY°d|�¤_4;UB$îêObkOýÑ2<†®}ÛüŸwSÔà¨Q /žô¾ÿyð�|á_×ÀûÔfþÎ7ù5ÃÀ@\-0÷ÍÀ`R«ˆÕOÄ"èîîÁáCAuÕñûò‘ìÙªN�|”Ä¡˜µj=:Þ™QnˆI³/7DøDû†Rã>– ~±rö¿ü"‹:ç˜;80œÂË‡£%¥4ÊRýÊW¿ºþ®ªžìáèP „|xÓ·îÿmhFGfG€óŽ«Çª6?T�BÓ‰È9&±U(�PâÝ½ýcZí‹A�‡¡÷LáEâÐ €«yÖ^òEðþâ‘ƒ|W€cLËàp¤P™Y„«jPèEB«lVGc�ÀVlþ;Ç2ºL«À	gp`8…ç÷—tÞ-nÁ´W „å>µéßî¾5ÛLuq.]ÙˆÅ @DÒp(,gºbR5Ð“ùùªN1Øu»öî·%óÆƒéäX
  Ä`=V}øjøêš‹îŸop0œÔ i$Í¬lKÖcÐÅ‚#€È³9ÅKãu	
?‡C�›ud¼Õ—ÀK†m¯‡ã8øx€eØ¯¥~ÿÃ­)ÆÓ[ríi7üî{ÙÂrqøØ	ÍhIPICwLÉtç)fò÷ÇÄ4çP·™_©þÎªÄÿÇ}½¦‚cD9	¡¶k7¢Çc»>Ð–ÊöJ(ž¡ðöæ¿¥<<7ÏB¬ÒP§î�jP¼t(Š7�„GÏ‰ãrJ¦ãÉÔv/«_~4ZÓV–¿aý?ßz}Ãâ2Û¼<>vB3êÓ)½ƒI5Ó™Æ0(FRZN§Àùª?Y‚Ÿù¼iâd[ Z®Äq}ÉvŽ ­A ³QÉÎ*d zxÆñ0«n¡Z.ƒ[`Ñä-¯Â)Ïì4:Ã2ãw‹¯³ÐÁ2ì×ÿìªïŒû¤&ÓR–¿aí—x}ëª™m­ŸZÓ’ùÒ{b
†“*†d„?¿\×‰¯o™ú;wížÁÏF¢sç¤~^6¨aZLRÿÁLÙ-ÕÔŒ»³âÂÏ#[ùf£5`æôÇôÅÇÏ‚®±%ød1�×2pjôD<{`)Õ~EIJÊžpÏÅGK¤`Ú) Âò7œð™o]?óÄ³3ÛÚC.|ì„fxyŠAÑS2	,†AÑŸP!§É?M7�PtôÆÕ²¡½žÎâã;…<Ü-žÔÏ¤†CMMF¢º]N‚=Xÿéëm#Í>:ö•Oÿ-‡Ræ%pqB.vÜ‘„ ‹C½Ï¾˜)àâÀ³IÅÀcï�~hæ‰~éÑ�I86Õ;A ,ÃÒ‹¿|ýœM—d¶Í­uá“kZàæ
…_Õ)úb2²9š„¢£§ŒðaÏëÇ¡#Ý“¾êç\/a %"“òYÔ0`(IªÐÑ{CX¬èçöƒ=`xÁÈ	xƒuÄÛÐZx,tG%tüë‡‹cÁŽ£rÐ‚fPÄQIƒf .ž3QÖŒ$5p�+K÷¹y6ó7Ï,¨w£ÎËãHDB~.Cˆ„¹|ÁyŸKíÿË-/Œûâ&ÓGríâÓÿé¿~èË™MóëÜøØê�bPtŽH™Ìµ¤b /®ÂÈ2bâ2†S:B@)E¾‘¦*2ìÜŽÝ;ßBR™ütÜ|0œ`Z tb{šCN>¨ç�uyÀð‚ù#¸Àº¼`<A†„ÐœãFïŸnæ÷G$£*Â ž*þä\+ I30’Ò`ÐôÀ”1(˜¸b–|»9~_pž„Ô{y,lð /®ÚÌ:ÅéË?ô…¹�±Ô#�¶NËöÐÓÃ äÃ­+Nþíš/ÿ(crÎ­uáãyÂo1ûQIÃH*g@zc
d=?Ùg´¥§óÀ”øùå0‘©ÁÅÌ}Îë	€duæ<SðEOÎ6c[Î{}ÁZTÕ2ÿË!äâPëáÆR9‚9µnÔ¸90E‰aP¼x(Š—:£¶¯Ç“©íû�éØ«pê aÎt¬|ää¯þ"zj¹ðéµÎ„?¥êè�+(–Ò>8<Œ½[_Á`lüÙj�‰Ê	(&ü|°¬8:ÚŒ°<„`}Žà–‡PÛ&¯'_¨®±è�± ö¿¨TX	D€é´„’ç»o0…Gß²%5ƒ³jbÓtNLê•C–_&Ö¶ü~Ý¿“þfŸêË~Ã J¨9ÂKçüÛ	¿fPŒÛ�Œ`(9õæ~10Â‹ã?Pœ
? ˆµ-9ÂÀVø=^_U…Ÿgè¤
? „%�#’ã,Ðì0cJÕ±o(…¨¤Á(’ÙØQïÆeÇ7£Î[ØÌ”cH­Î{Ÿ<õg¯œ>©]SÆN˜Iuõ¹S¿~k] ÕläÓàåñ©5-ð‹l�ð[a>‘”Š�"‚•4lëÄ`$NÃ‚uû¡'"îk�ýfè©êÔ €¡$…ß_6ÝMÈ‚XÛFpåîh ë*Lry¼à¸ê™ëÕ"ÿ*¾70sC’ªŽe QBA—iT’�˜lŽxó	,ˆ�%!rŽkòb0¡b$/•˜!ÄÍzyÝÆ+öw?öëm“~ñ6˜€ñk©¦þyõç¿Ódeùy;¡AWVøâ2‹ÿÁÁ˜ñú¾n¤¤ÑÌLVô@l¬Z»úªƒuùÆ�4M)~Fp¬òœ'P°�°<8oÀö¸¢X]+e²Wÿ|Hš�î¨Œ�„š™ÄdÁ/²¶Âo!¦80,�É³ç-©Ãê™þ‚×t°ðz½wž~Ëÿ<¥7 �)Q F2rÇâ3>¼ÂŠõ»8&“ág…úŠ	oL±íe¯h:¶ìÅÁ¾Ûkâ<ˆÓS	0&ouÌP_!×Áês? à¼¡Â{d³0C5Á3Ó§9ªå$Ò±d·ÀEµƒjPt†%D‹¸CpÊÜ6Î³/®R|{:(�IW „åo,\û�…ÿôÿ2R|éÊF´ÍÆŠóÛ	ÿ‘°dÛÁ&šHâµ}ÝN(%?›Ô�ó×a:‚óÆ}Cµ~]¡ð{¶C7˜<~À‚ÈUwµæÙé} �ÝQ1Yƒ§Âôâî¨‚¡„Z”8¾Í‡Ž«·}m:(�ÉU „|XÔ\¿áËßƒî;wq]¦ª¯§ˆðkº�#a© Ì¤Mþƒƒ™LÀrp5Îr<rj2ÁûB ìØ}lj¦?a¹3@ ¤Ý„"“xN@51Õæ¿8HÅÁá]’²1�PÑ•K’ƒ-·� Lµ˜4@X~(½eõç¾“©9_×ÀúÙ¦0&Í¼};á/ã/eò—‚«±ÝV0¦¬{ì\€ÝêÏy‚«?ayÛkgÆ8†«RL'ó?¾t
±¤Qì–—+‹Å‡#JQ%0«FÄEKë¦�˜°~Óf‘êÚ]Ïû¬ß*0™[ëÂ9‹Ms<"�VñÅ½¬ð§To,kòay¸[:ªîÛŽcuìV ö«3ŸpÕ%ùŠaº™ÿ€I@çãHÄ4í+AJÕq`X²1 m!WI%pÂ÷ž¿|²¯}RÀóOÞyK`áš‹/øœ˜	—®h„À$TÝ1S�³“|Š	4‘Ä›ûsYþ±€°ü´‹°.ï˜Ü »ÕŸÜ«?P\ÐÇ:ˆ³RL7óß+ï,<�PÑ–sf”ƒjE°Æ ¼^ï�“�'0ñ
€�óÞÀæuŸûŽg8|ôø¦L¸¯'j
rR1r’|ì„¿R¿¦cd€ó•æ‘�b«?[ÄÅ)jŒƒpŠéfþ»8¦l‹°¤¢ãHDªˆp¢Šƒ*eï9å‡Ï­˜¬{0¡
€pÂLPzËÊ+¾™i3uÖ¢ºãoÅúU�æ4ò°#üöt�Éß/>P¡¦yüªŠ…âŠ�EÂPE )Jô· ml®V>¦“ùÏS8�¤QŽÈUU³jD[%`enüé–öÉ¸¦ Ò~ÿoÖœã·âýK›<Ò¯'+Öß5çóW~Í ØÓ=Œ®‘êeÊåC¨m�6‘�JSƒíŠ›ËÙšÿŒàvrÈ	ÁT¤þƒÕH¤¨ºIVÒï°œè¨wãôù…Ç�Ú¨¤ÿeÃõ÷‡&ú^L˜xá™ßþ‹+TòºÍ_`úý.k`’~ÃI5ÓÌCK—–Äåœ8¿fP¼ÝÙ7¡Âoa:Ex¿³Š»¢äo/èÅVùrdh5\®é´úW*üÙè©,B`)�bÑ�å­>¬k/$}÷²d¨å¾‰¾¢ Ë/cþmåÇ®Ï„ü.^Þ /ÏdH?†!Ii™‡+’Rs2ü,á+Ó?†sž6‘�ñ¦3|é¸=ÕÔÜ]…¡g¼«QB=]V;Æ¿R‰(+�R!Âg°¨±pññ¸„÷Mtx°êjyý¦Íbçþ7®?áÌæ¥ç
 °±£kfú¡]5Kàc’–SØ3ÙÂoÁ*Ò¢Õéÿ?öó``¨JÙá!TW, ªk ¬ ªÊÐ¥$ôTZ"->ªëÐ’1è©(´d$ó£§â Ðâ#™=‡.%@U	†œëò‚c	Sù#cšÿSZx
 4ã_)¢²G¥æ3]¬ˆˆ³çÀÁáyõ:ÅésÎùÔß>tëþ‰¸'UWË„åoà\žëÏüÎ_ÀûkÐìãñÅ“f@`zb
Â’U§™Ñ]ÖäÞì5ÂŸ5:yàÐ”}>P¾k05èRZ2šÓÌ0ËyíX}Þ_g›lDX®ÆÒœ“PÛš‰ –‡È0œ ·K,k5MvÝ¿\ã˜ô«3‚BE.EÈÍåŒWÏFTÒp÷ë½ý4ƒPWMDC‘ªÞËô_vÉUàý5àpéÊ&ADÒ2™~é§éúãÓKø�é°K¦†CS Ë	èRòÀaè‰HASÓJCzNL|šå"P]…$+H&âÂ`/â‘a$qh6½ß­Â˜î@%Ä`8¥- 
¸8œ¿Ä>2Wð¿qþU½+ÔÐêí8žÌÞx1 `cG-~Ša†ùòI¿ÞØh3�é"ü¦Cd€uû2B¯%#Ð¥%5öñâEÌw«Ex)P­´;b)„ðP?†††�LÄAuuÊcÿ•„ûÆŠÎ‘Êòº£JÑRâ¶�ëç„
¶OPµ;CXîS ÆÉ'lþ ³³Ï)&h•÷Æ=CúÄåœpßt~î–Ž)‹šÂò¡ÏG1%0–ó%“³ÂÛA—�·T£ºš±"±"’^46‘K¸o¬8©,c°'*½'«gøÐ^ã*Ø®øvµ“„ª¢ O°–êÚ.>ã#°x~hycÆô�¥ý~+Ó/–E f’Ït~“04†¦™ä›&ƒÝEÍyRåæ¦åÜ€±FdÊb$žB×Há„4©Š@t8¸PuŠ#çsTÃäÁì"CpÎ¢:¸ùB×)¡³w­ß´¹j…UQ F2úMÞlšûÁ« ˜U~íA1cúÀPÒü_ÓôgeýŒ“ç+ËÃÕÒ1þ•@¶Ðç›Úœ¯z]xË�C9Tb …ùá”†®‘ú#É	oË^MÆß)$�æÚå�Rõ‚¶a<ƒ3ö®ðyÜË’g}úÆj�ó¸ aùe,Ç]½ì’« z<ð
,Þ¿À|híLÿÞØèêŽH’Þ[m°¢®–yU?n¶àC±¤ MÃŠlŒ¯5½!U¦¨‹YNIÕ@Tš0Eà$Ç¢•´ŠªjQ> £Þ�e-…Q›�Ïõµj¹ã>ª«ÿåjšMÚO¾À €3ÔÀË3ˆHŠžcúgûýQIÃ;Gú«q“Î¨ZdÀ‰à[`8~RRx�œ‹Q�Ò!,_¶Âp"ÁD2þN1�P+Š”j&²±#”3�ÙÍx]"BÁàmÕ8×ñÝ)Âœ	àË.¹
Ç3í!N�[“¹	Ù!¿”ªgü~EÓñÖ¡©ŸŒ[)„ÚÖq·s*øÙ¨´B°JEœ·Y•ð&ÙŠ`<Ád0þNÑuN
ªéè˜x–àýjÁ±Lz6¡ÉkP�UÕˆ
ŒïnQú?�yÇÃšâ{áR3†™Pƒ¸¢C£$'Þ¯»ŽT­¤w²ájœ5&¦ÝZõÇ»F!åXûŠÏÏ¡p;åÆÒ_ ©²°â{4‰Œ¿¨:Íô¹p‚pJ+pƒ‚g–4ypB[¡+àåñßã­» äÃ ]±âbs–ßÒ&æÖš¦ª•è ê"G0’R3ñþ½#Ó–ñwŠJ"•˜ûÅÀp<8‡9	¥&—Š÷SÃp¤Tœð ã�š„SŽ„+‹L'á·�TôŠø€|WÀïâ2dæ©!¸óš³ê„c|n×ŒçÇ® (ý�ÀÂµhX|8œ—Î`êM›üé¹ñ²F!kôÇ•I©ì›h8�š6.ÁÏçåžÃVØb½€t.€ƒPŸ aSMÓ[Õ(ð™($TÇIB–+À3!—Cdz'Ïµq	sÅxº�Mòa +.ü< à„™4ûE¤TIÕ@BÑ‘Ru¨éÿ\ƒ¶šêÁ˜J”ŠTcÕÏç	Œ»kO9wâ¢”«tBþU‚pJ+ÉLE¸¯RtG�=å®cE‹6cÇnñÛc=·±)€¼Õßjî9˜Ì�ùÆÕLnxRÑÁ³3‚X2«µÞê¶šž
Øµ«æª_øyÎÜ€bdÕµ’n€S–_O„‹¾6IS7�)˜Êp_%�4ZÒà¿ÀÀ+š–Œ%?vØ4/T°�‚¬:ï×[/Ë¹U® òVÿg9sÅ×)†“*T�BRuDÒ\@B5�­Àý"‹ùmX0£±êC'&ÙÃF&Rø�Üh 7ÆU––È¨8‘ÍEû£RÆ%˜NŒ¿sÜ<¯È‚Í*—NªFÑ¦í!:êlÂÂ„Œ)9¨ò;Hñ5ß¬ã2«ÿûš‰*ƒIjº§?`¶ü �R¨ºýªSãáqÜ¬–£Þ-p5Îaù	~ %Sƒ³Q*M¸\��R$bæEÜ€ÉH™§4„Ò¤¦ùV½ñÑ{ææY„Ü\Ñ°”ÅpêÜBK�‚Ì‹P™ Ì™ ]±øìÍ Lß?(rˆÈf®8-üá¬N?I¥tö™åßÑzÔºjt| nRzë[©Á´„°i%»û”N¸qª´s&«pJ‹�¸Õ8ºBÉIÅäÈüSÖòUÓš¶C­‡Çr›Arc¥u•Z ßpÕ4¢mõé€LÊoTÒ 4ó¿Eüå›þ¥À³óÛ°dV3Ü®ÉR1^P]…`öÛw5Ì˜ðÏtÒ/°T8¯\‡_Ç<@ž0YS.Ñ\$Rª™w4)�À".k9æ~)ô'Ô¢×·¶½pò0™[{Ù5WrNŽ€9ÚË8yþ—ƒáxfy‹õÞvõJ›þ¥àY,o¯Çì¦c:óTW¡%¢¹÷ˆ!6Ll7g+5x¬ª«¥‰@%å(€êjŽ˜àásI?M7Ð9"Aªp–ßdÃÅ\8†@3€þ
„ìrqE­€JÎÍ± ºv-ËñtöÉ  6u„ ä®þ’:šøPÎô/‡¦ ‡™®ü€�ð[`]>µ­úùXÌä.™¤k%‰@Ày¶Ÿ•TíÐŸí5sØ"ŸÑ‘§¥àYSð.—¯LjÐ.ŽCÉÊ­€J¸ G
€ñkzaûúóï¯A{È…¹µîóo%ý¥{Ê:ulú—»�3‚X6§eÚð¥„ßçU<à£8™!XÊ×/Gê«þ´¤y&zõç8î2¤ßtR<KàØ’çÜ—p^üTÊ
XbÓM„\ãôØŽ€‘Š~€nºÕ—ÅBZÌJÕ!©:b²�šWžÉ„§’p"ü„ÚVÛ1ÜÕ€•\jÕÕKX†Z†¨ èGKD'|õ/'üº"SOZ‚Ï•ÉOÈ&ÊË¡”°Æf¦ Yå´\Ø™@éç½móœ³^�Å	3™ÕßÒNÖê/M`‘O�‡ŸR~À©ð[fMXd€ó…Jæ”$ÕTÙ>€N¯u¢CŸ~we÷oªˆÁl?ß)âÎï]1+ ÁËc–Mû°` àÈ
(« ^<	@ÇÜ“Ï ¼7íwDò|kõñW)¦‚°ÌÝJ1Q‘Î Jô	7PAó'¹c�ÅøWM7*¬ñ¢˜ŸïQÙplë$ ï±©da\æ¤R°¬0TåÓ `‘'Î0³•bé“²ü™ñ• “?0»~Âù«÷þX0‘‘¾Lo‚’õÿeâýN¢V£’±*ÇRÈgü+�"¬¼¤¸âs,ãç;A©´ßl¨-šØQçFÈ�Ò	Çpœpi¹ã–T ù×ºòðþÌ¯s£ÞÃgrþGRæêŸRÌÕ
¿‚Ä	M+Öåä¸kï'*2ÀùjJ&ß”äLü-°fR¼ªý	<<S”ñwŠ”Z\`Æ‹±˜ûÅNU(‘x|k¡àØÏ–;fI@åÄ… üm'~ €9Ã0ÍëæZ¾ÿd®þv¨ñðX9·³›jªæƒP]…Qa#Ìbà¼!ðÁ†ª^3+ºÁy‹•ä”TÙ¤­DÑO~›2-©Î}*î«C	µ¢~å`	þXÌý’ç™tvŽªAs†çfÃn¶ ™[®T¸´0Œ+XŽ§�+N…‹cp\“‘ôÍ÷ý§bõ·CSÐÃßÑ:n~ Æß)ø@CÕ#B¨©èkå|órn€© í�‘?i¸T… S8	÷UŠ¾¸:nRÐ
ëU[ð-Tb©D${àX,l(ä„ü.¡dN@Q@8a&Ë²ëk�?=,mòÂÍ³H)zA³Ï©^ýóQ�²ãJ[`;Eµ#e­Š!=]N”�¨ñpÁ¶bMJõqZÕ~ã!�†õÆÍ(Îòç#*kEÚqM…‹ã²RõE ÕÕKtM%³ßcöû[•f“ªaNz1("’6­Vÿ|XeÇ•†«á÷—‚«aFÕ” Ãñj[Š¾®Jã‹Ø‘�L]�ŒýžŒ�ñwŠ±ðÕôó� ’ÖaÅÜ€Ž:·mÛ°Rõ%\ r~¶ù¿¬Ù—“øci¬é¶úÛ¡’°a5ýþb œ¡¦iüJ£œP* 'ce�ŸÍ”kQ>+`<Œ¿S%TG™‚åç—ƒ¬Óª„í¸ �c>Xl[Àx‚µ,Ë®oZzbÆüÌÖÞ–ö‰HÓË÷/§eÇeúç£š‘�rn@©h€.ÅÊ'e…A™2]¥V@5§N�|L´ŸïNC‚IÕ(ê,i*\ä4M»`Ãõ÷‡ìö·U TN\¨k*i^µ€iþ[™QIC\1 éÆ„fýMJ•O´éŸ�jEÊ¹e:ˆãk‰°ã%N­€j2þNPÌ˜?ß	*‰XÄŠX­~1W‰é„c‚³æ|Àn{ kç@ýò“Á`^�‰´ÖQuŠHJ�´¬¿‰B~Ùñd˜þvàU)*eM”s´d¤¬P‰e¤FÊ*�‰`ü�`(«Æ~²ýür¨„)±ß¼ºÂÔ`
Ø†@š1Üàm›_]3æ7¤ÙU7§ü1Y?*W;Xü@]`b
wœ@¨m7)(Ö4•L
Ò¥WårV +º¡Å†ŸO¹¼€©~	EŸ?ß	œZªA‹º
Ÿ·À�c·o�xþ©»6ð·/] XÜ8ZöWt$d“0Œ£wõ·ƒ×ÄÌŽùà¼åKm'ã�šZ2)h<V€Uî«K‰Š:³&’ñ/Žeàæ	T½ú«ÕBT6gsZbA4 ¥uvIA…. ¥§@pÉI €¥Í¾ó$¥V­ÞºÀòy–E{[+šÚçÀãšÜ‡t¬-Åt9-…¡¤JFÌ}K'³XqÔ÷WFúŸ›jc1¸DaJZy»ybFÒ³õFnS�˜âLÄ‹Dàx† Ý¦B0äßŸ¿ÍŽ8 æ-GÈÅ¡ÞÃgÌI5Ç|+ÚôÔžcAR5
†Nx]"šÛç¢©¥eÂkÝ³QIá�%øÙÃ>ÑSº6 Œ %#9+<5Œâ�jrEƒ²­€É÷åÃÍ“œ¡šRÚôµœº¥¢µ…
À ¦lg#G0ž`-ËqË½móÁûk21EËü·4Ó»iõO”Ècðúƒ˜1k6|µõ“v>¬ËW22`hj�à[ S6¿ \åžÉüÎð¢mØÏj„êÊH/€É÷(˜¦k‡éjXS´� Øó;»¶0bCAVå‡s€‘Š­Ñ5•Xþÿ‚z·Ùô3mþÇeò»HúíVÿ|ð,‹ÆúzÌž5kÒø»È€%øåºõðÁÆ’¯ë‰Hé2a%•Yá³MÿlPMv¬¨&ƒ×S“*ü–¹_ÓÙ
°¸¶rHq¼[P" ¤©muöß¹w)íÿûæ®`j+÷ÿÝhþ'*ÈbdD·ÉL’[�ÝRÌÐTÇmºÊå å¹ ->\6æ¯%ÂŽ	AIžœiÐÅÌýR˜®V@Ä¡(¥ÀæÔ’Êù<@¾š< jŸñÿUƒ"©ˆ)ÆQ•ùWªN+?mÁëbÎÜ'¶ó/ 5Í04Õñ°ŽÌûj[�Ó�ÊY€³!NÂ‚ŒËCS!ÙUc|©iº¨¥.N¥Â�3Båy€ŒX¿i³ÈrÜrÞ„¯®í5®Lø/¥êˆË¦IÓÕª`¼uâõ¡ fvÌŸP~@—S‚ Leó[XÑ6Pú¼Jå0¼z2Zv…×¥DIN�qù2ó’‰ô*gY:ñó� ,M? ëÔq8°˜%;3Xh0T_‘]˜y²þþÜ='èšJæ›ÍDçÕ¹ ¤¨}×™ÿ©*$2YüÀD„µDTWA8b“Þî¦9%­ CNÚ–
3‚;£pœäõ«‘[E‘-ü™}+´dJ^ŸC?ß	b²mNr,ÅØ¥3ç}j‘õwæš² üí‹˜SHSŠY3�˜fM?Æ‹˜CÿÊ)ª6´„ß#zÀÊ¦ëfƒuûÀ”'.Gs\Âr`¸QEFuÍ¶@>òó'ÚN.ª†0s¿¦cUkRuö}—âZ…SR#Ë­ßGU(Å2 ´u  ZüTƒBÒL+àÝdþOÔ 	‹�[�/ü8o ¼/TÑ±<m2Ó{ŠÞ¨+Àð…ÄŸžŒ–�ûk‰pfÂ‰`Äâb<î¼Ûp6&Jð3çUÅÖaÕB5x€¶À¨0°íY¼ô“«ÿàzøÖ{­mÙjz% øg.Dƒ—‡›g¡êŠ™$ëïó¬ä_%h¬¯GMMzzû*j+¦Kq[á·À*Š°n¸`#Œd(2½Çt<`�E¹->R4$˜¹¯Ñ!°3J
?`F I„àr6I˜c™ª™ú¥`‘�Ó©>ÀâœU4¼Pxî!7‡Þ—ÁÛÞŠD×ÞïôÚlÇŽF	@ 4·M>>Sû/¥Í‹w‹ù?Yã£*M+¦šìH°…`CE£¸¼³—AO•núQªk`ºJ™¸?ÕdÇaÁdÂ™PM?ß	œúÜ“	§EwrÞs�EñûßÞ…½p-^¿õ›4Ñ½÷« ½6ÿ} ¼ðÌoP]%ÞÆ™`8ž™2	@Õ ™ðß»“=?ÎëámŸ‹D,‚þ�AÛªÉŽ{ë[¤ 4Ðéh†ãái[€TßA0®ÂfŒèáxèÑþ’V€žŒAãø¢s	Y—z2
Öå+kš
EJµÜ<™0S¿ŠŽ:Ïä%,9='¯Xþ^XŠ"‹â¡_ý ÿ{÷o �ô§_%? èMvïc €ÚR ¶ÎP>ð‰fE4ùx„\x‡óÍ§&Ãü/†RiÅ•v!ª42 ¶.€Gí¢i©i*t©¸¥@ZÜ>ù‡uy3V‰uÖ()ØV­°ÞX¡êtÚE‡¡À”ªãÅîÂ•ÿt6~ñó›é¨ð ½À^r­9ëc Ëß@uõúÅg|‹?úüÛûf ö¥°µ;Ÿhß¼!¥êP4)�BÖt$}Z»
1Y¯z`,Pu=ÃèR¼¢aœÙÐQÇghZOø¥?¶°5£	L¬Mù0ï¯+ï�@XbÝè1'ð| ¬ƒ&'¯._Ë€gè”	~6¼<.nüª8¦°¾ß*¨âY’ÞÇ\�—µŒ~oC	ÑîèéïÇ›o¿ƒ÷BMÅ¡�ô á®ÿåìS/þÙ³W�¼• ªk³ÀÝ: Pïáq8"!¥êÐ))ZÁåæÍVJÙ�‘¦H©ƒšaDÝ$W¦ƒbÐ¦I#‹HÄ¼è>°gÌÇá¼Gî5†iZ¼¤t®c}µ¶Â jl„åsÂ�9ÇJ‡y_ÈVø“´ËÈ‡$+¨©!ÓÊ¢ŒËÚ´Q °Ä”¿|a·CJÑáN�u^uó`ÎüpÏ^�è;9×gRŠVàCÖ•® !Ôoú ªN“4°„‚«àâX~kÿ,JÓ$ŠnDL¨Æ¤·«FòO5¡î–yPcCf-½ò¹“È€å×{Ú—ÎÙúÔs�µ'—:¦)ÉDÁº¼J¬òjd dM+z@Xñ”‚Ÿ³^ƒ“�©zF,açX,1Ï�ÉºÿœƒlPÕ °»“v¼†‹cZ�L � ž†hòñ™ƒI…P%íÌ±‚n>3B.,lð`i³unÌŠ¨÷šÍÙ	*Ÿ*ß¿øùèH¤Ì�¼¿î–Ž¢[9ˆu­Ž"Çµ´ŸåÎèî-}¥zöiš
-1R2ñH—%–!'m§1ÎÌœo"%CÕ§Þ-ËÆD†¼9Y¯ÀÂ+°ˆBnÎt³<KÀ0LŽðK+‹%ÙU*æ›çã	ÖÉˆ ¼ÁZÔºùQß^5 pkžM–1Ùì9ÄS¹r„å!6Ì¯$!uWÌˆµ-�‡{ÊZºAÎ%,w]bßë·z;Ž/š¹hUrÞšK€ð"¨¡C‰–$#µd4ã
0Âò¶ŠjºY’F!ØxŠ¦#,é�4³ŒÜ�SPSQˆ‚�gôûðšþºµ¢È¬êŒí*^~ÅÓ¨³UQ)òŒ\x†ä$‰S·áúûC•“m Àr<åý5¤ÆÍB1(dÍ€¤é¨á'?,RÊ�H©æyUêFLÿÈ]ýóÁ¸[æAéuLð&›/ë!÷”Ü�á¸–™ç~auçý?ù¾tø­kÜsVÝW—“`W)HøÑ4_]NBK„‹v5¦š
->Wã¬’J"%Ãç¦	˜‹…e‹iERÑÑ•0œ7ÄS•d¨±8 +¯¡nŽ % bÁüy<}çÆ|>fªoy9,51àâ
æÐšºY5ô6 pÕ6 ¨ñ™@:%ùÿŽeàwqcr#¦“û¯¨åÓN…šfxf,rÜ‹­(ÊðŸi=ÿË÷IáÁç”#;Kî«Æ†33³…?s-Ñ¡¢VG%uùÑTÂ²£’†þ˜Œ¸¬9VN‰x;wíÆƒ�<†×wìªŠë©9<F©Ï
ˆ…rÌ®F†0Ì `ÓNÐÅBÓ$U#Ã<Nw¸yA7�f¿€Y5n,nòaQƒ³B.´DøEŒœp¤$gÃ*	ËÃÝ2¯¢	Bœ7àˆK`ö;ŒÛA¢ÿð>¥ï@É}ÕØ0Ãeõó­Âñ`=�ŒòrÒ=h:qªNÑWrêx–@ å­H+"C5;wíÆÿ=ú4’69•@q˜›PJøÄÂï.àš€Ì  ŸÏÌó
,’ªÉÔO'¡©–µPçá1´ûUxâ]XÕêÅ’F:êÜh¹¹IWrª®CrXåe�÷×UdðÁ†²ûBNn9õÒK	Ë0Ñµ'VJ	po¶/ÒDÄÐTh‰0Ç›�Ió>ÛÌu(�nL�À³nÎüñ‹,¼<:êÜ.#GP–£šZ�é©'£¸ïþqpïî1Ÿ£aÐV‚S~¡ðÜSªÑÊQ]ó€2- Ï ©H©ú„€“…®¯ fÏ[· ¸‘ËŒªºYñ˜Ru$U#3þ|"0Ö‡Ü²œrb]ky2‘s]wÊu÷-yæß/¼Dê;ø0 "4Í)Ø�²< kP#ýE­]NA`ù¢V‚€Ø0«ä9'Rò„‘�™8:I“rEr[j=XBÐt¡;"å¼æu‰èÝ¿Ñ=¯Aê;�©¤jšà�¹ØöÞX•’O>ù>àõ¡±¥­âsgªNáD5Ý°uW\6‰|^‘mà Ô€K4ÓÝ‹ˆlF¼Âô eÆ‹½/>ÉU‹÷~ä‹¶¯ó,AÈÍe”‚aÐ)ABÑÍYˆ²Vµøðxëá…šfpÞ ¤þÎ²Œ¿l(`8®åÀÖ'¿j|V×éG¥¾ƒ¿Až`³ÚŒÓ´Èn<Êp|Ž©_¬+±ÙÔ4®L�‚„$Ãëß”$ž%eÝu>ÃÜ‹,A½—Ç`B…F�Ã/>œ®¨+ž¸Å{ƒ·ÁåAXºœÊIó~èáGðO}ž`Í¸®¯ŠåØeòr™Ë ´ Ñ E3 èÆ´" Ç
%6Œý»v oÇ‹Ôi}5Ã0¥Ð^ãÂ’fVµz±°Ám;|±TjþÛžŸàq”7à¤fÀ$¿²”þN×µÿ—èÚËàlH<C‘ ÅGÀp<Ø<s¿\Z³]^@>œò#@¡ùn)q¯ÀBäÙŠ„ß/0óÜA¿ÈAÐ“xéû_À+?ÿç’Â j"‚�—Â¡ßý’=ûrÆª¦}êo��iª–:Î�`/Ë Á3Z)&O³˜ùxðêßŸ èšJúw½2æã0ŸÈ™!žÏ˜B5I.+o AH8¾ld€aØï  (½‰°ü�– EBwTWÍ¨€�¹_ª�˜¡©¶Ó‚²!©FÁ}âY’v;A¯TØóÁ33‚…4cC½øÓ7?Šî7Ÿ­èxj"‚®©ÿ`Á}ëê<ˆÃ;^®ø�ö,æºÚYó.Žie@i  x·®´“!iÅ’Ž>~ëÕÌï{þþhÕŽ[L!4xù‚¹lœ„ÿ*…•EX*ÎÎy%• !ää¶³?û  ºzƒ¥R�oå^³àëöƒ°<Ôè íjohjÉnÁå:Ž‡¢j‚>–UÝ)fÔ¸Y4ûG•¹N)þú_Ÿ-»ê—ÂÐÿG-…¨ËI(á~hñaüý™§*¶œ&³ìëyˆ‡hfé·@JÕ�ê@6Þxî‰ÌïÝo�Ý(K!X.ÃòfÕ¸rÈFe‚,+'.AÙð çºÎšCuõ€|?Ñµ©}¯�°\Fð³¡F‡m#¥úZ\ `
;áxð.wæ‡ã8ÄULˆ C�Û¼.GPçáÐì°íÿnÁþ];Æu\]SÉÈ+†2Ò5ÒŸábF"tî»bì¢]ŠAÛ >À¬éæYÅ �T9ú5@Oç~$úgþÞ¿kÇ¸c²NÁ§I¤Ž:7VµzÑQç†G‹Â5An2©Ä%VúRáÁ!˜½–°ü�‰þÃH¾³Åö=ÔÐŠšü–Àp|æ‡uùÀº| º–vŽ³�„S“Ó£¯ÎÃÃ•·ÚÉ0žº÷—U9¾4Ò_à
 À[Û¶Vtœñf²«èe dh^KIHw”$•Â®—Ÿ)ØvxÛß'ý<†A@d�|þ7XÛÑ„U³0«ÞgL„2jšK-ÕR,CZ[î@ÿaÄw<mM04jlØ¼Î,a74¬ËgvNÿdŽ«©PÊôJtÚw¼°Ë�{áÑ –¤Z	¤Ãolë:¸oLd`9³2‹úËñÀŠ7˜’ÎÕÆÛ/=U°íÍ-/LÉ¹Þñ2Þxéy f^öìz?3QÊ€ó‹òå"B0�l%Ýö¤9«€1Û‡³¢''L˜/ìZ	Ö¿\ƒ˜¤BŸ„î<-~.žÍi¼i÷Ü8ÅG/»O?ý4^yå|ñKW0­ ªk™C‘ �«ž’DŽ©³µ¿Tƒõ
@ÓìÛöjÁöÎ7žƒa“Nrvíx‰®=PÂ}B£±ò€‹CÀågf×û1”T1Ž¡;ê<V/ õ* ë,%`W8d‚]ßò3kÕÕ@HLéÿ¶=‰Ð{ÎáscõjlØ¬øËZéÕèPéB!M+ê f'»RÖj¢Æ#ä¸ :îÚ>¦c}ô²Ëp÷]weþ>á„  ?ýÉ Îô_´Ð?Ð�Ù˜�;@7(]Ss^Ñtš^Y�éˆðî-¶f\¢ÿ0ûzÆpÄñaï‹�  zß(¾ºÔyxÌo­ÅIš1¿¥^÷øbËÃÕ8ËÖï/Y8Ä¹®ËïJo!_•Fú1ôâaØô1´[ÕKYz²ô
8n€�`äöÓsŽOêSÛ>ûé�§/V×Ð˜ñæØ�eHÁpP¨…ñ.èüâß·}­”N’‘‘£üÆo”ÝŸcÌTÔfÕbMG#ZcWV
±] Xd€á¸–ïßüß/¤•€šˆØ*]NAÏó%&—›™0]Gw¿›À°O³ÃËD�S…oW ãññÆ‚lâ±gës½×Í³9VÁX¹±a–­°‹ä‚£/”V!hA—S Zq—F•Šgjºy‚•€]âŒ«¦qGnýÕ¯
¶Ýrëmæ/,:Ž4ð‰pÉuƒæZ Ó¬kÖ˜“4ôíx1ûjbé À¾m¯Nª²ËNF’FúîÚWñ1,«`mG–¶×£Æ_yÑL1%P,2�Of�¥Â¯=ªæ
x~±R©¶çZ7`¢{ô�$Œ¤4ô'TôDeôÇdÌ^´lLÇúÍÝwã²Ë/Ç3Ï<ƒW_}W~ùüô'?  ˆ3ÁêÀy`E8ŽGcÃØÍXP,C�Ñ55˜Àtë›7VìyóEäp„ÜBnÌÜŒDdLé˜c…Åþ[è~ù‰1ÉD�‡Çò¶VÍn¨XØ)«›P>²3�N–Fú1òÊŸct¥Î_õKùúF™™Qibózb
$UÏIµ]²nã˜�÷›»ïÆ©§žŠÕ«Wg„ßUÓÂr™Fp�¯›—?8æÏ©4ƒ1 2NÚDS�¼”ß}ë7^qóú�WÜ�Lö…U"<ÑèïéÊN'Ý”vO*AÀÅeA%<��(J
r®ë²çÉg#�1x‡4Ò�È¶'s”@v6 ¡icv&ú™ŒÊ…–àIgœÞ[=átÍ<®`[ÛìŽ	‰D+á/–HÄ ÝÐLMÅ!«füÑž˜“òKÈ¿>ÿäòóOÞ!–»Üâ<ª%„å�E8þ…pÂF ±¾/Òjvž¸8Ìo­­È"°Sœ7PÀ0×rÀåúd±ã¬ßtÅgA˜ç]{ßÿff»!'s­€+}©f!šnLh>ÀPR-˜¿ÇxBØxÉgªr|WM#\�³¶·|EEÇoT®˜"e  %ŸV}óÆ
«ü @˜ç@éï¬×¨®n×5í **Ò¬ŒpÂ¨¦!7êšJvo/¨‹`f5®òJ\l(
ÁÊ¬€çŸ¼CfÜþ ì‹îÞuà�ùÃæZ%¢åF£Mô4§‘”IÎIÅPRCoLÁò}s-×qYŽ§5«Ï…PÓ>Ø˜áYj‚A´Ï�?¡×”;÷^`HB¢ ÀÈ&G–˜¡˜HXå¿,ÇSÂ°@Öoºâ öéšJ:·üÕÑ1Ã@JÑ—5„SÓ„QOTFçˆ„}C)¼3�Ä;I¼ÝÇÛ½qlë1Ž¼òË]C5Å,J ô&æ¹#¯=…Î°„îˆùÓWÐW0”T1”T•´t{v½âyu¯Ëg;‹äwìµË,gÉÈ0Ã‹›YŽ§Ã¯?F-¿ÞPåŒPJÈË±ãÝ+ðHDÁHJGoLÉ(–œù�[àm» Ö�ô!Â§*+z „ÁùjñÞ+6ÿ9âì(-°· h’5"  Éæ%kÆQ]`¥úêšv'ÕÕ‚”®çŸ¼Ca®FÙyKÀÃ)³lOTÎõÛ½qìèKbÏP
û‡%Sh£2**Â’fŽQ×Hš�Žv ŽØ5{ŽêZN|ˆ0ì{Þ6Ýkëý	ÅË–4$TôÆUtGåŒ²ÈVåCkÐ…÷ÌiÄ¬z_Ñ�‡™'�›6ÌˆžÂhçº®Ôgªü‚Añïº¦’ØÎç3|@vrÐØy€‰}UƒâH^û/ ð×5ãƒßúZWžRÑñxomç}¹Àô',�¶öÙ˜¹tMÅçÈ:tŠõ¸´[Ø%Íèæ 2PÈa3t?Ê-€Î7ž€ã	\ccŸ©ñW€ÜñÆKÏon½À™ëchª‘Œ1zt‰ð”pfØ¢$Ë�Ãˆ§dRTS '#�Fúc„å¿Hóª«Ûc¶ßøçÏŸt=+ˆ`yÄ ãòÁç!† êá­k6Çµ…êà©oü5Ðò¾Ž "ÏÂÃ3àY\Þ
À1³ëýL­Ï�ƒ½ƒ‘
/ÖÌlGªg4<ÉyC9ÂËp\ËÂ«o¿p÷>öÇb÷è¤ùïçŸ¼ó‚D×žž¶àëf@OÅ3ÊD��õlKˆ	ÇƒêöåÊq™ Ì�F)²òìB>ËOK)qL1 p4§+PLÖ °¬»ægcn	¦F2Ê•°6žvú˜È¿ñæ$•"EB †  73¸ŽæP`¦ü—��dd¸Ô¾Œ'pM¢kÏ™áÁÞ&_]3M5¢½�Lrà=û¡�ô ÒwÑ‘!hÑH#ýk„å¿og… –°Üq™š@GööR¹q¼×,ò©›1¾æÙÍY†À¬%Ð<žŒ†wqLú‡@àF»À\–ÏnÆÁÁ˜qh0^p-Œà�PÛ
e¸Û<÷t'¡ì˜~âà¶« U iëêë ô‘ð[Ï£víy Ò‚7t9FôØ¾×�â@‘~rž†Î~Fsœb5»(PºOàPRE“Ïì(ëƒ	5óÞ9ï=ÍkÎÂ¾·K7Íæ:XÑê	dÜŸsÎ>kBûÅ…]V¥fÐýa¹ÕUè)“p:‡lº &i�4QÙÀ³�=¤Ã~Ï?yGÉ÷ÉÈ0¹ú…ï}þ·P%$ú—p–ã©®©ý éèaÓzÂº	ÃF¨¡'Nè¤†€“6|ä�bçñü“wÈ æYäÚß_ºßK•””†ÃMõ†™A=ŠV€.PÑ™êÞ×›£{_Ïé¼ém›�ÆùËQ¿x-j_]3 €#*|"�Àf,Ëx§/Z0�ˆ÷×Á�â™•ŸórúüBNN�’+®\©ñWæ9599ÕõÜmLÁÜ%] Ã0–ÉA–²È=KIØ)‡á¤9¸ÛÆ%HH2|3Á7s‘yL)•ÓâŒj*”<²Ó*†ÚpÒº1uLÕiûúbÑ;¹NÈú !,÷)ªk·òÞ ÎýùX×nja».¢S	«ew\Ö�TtÄ£À¯yéû_@÷Öç>’Íü;ÀŸ| Èø~ ;òºt3œÐI)í<é”÷§wJÁx‚µP¥ÅÔÐS]_BVƒ+˜3ÛæcÆ{6aÆ{6"8Çd²]ƒ�‹ÍXšAq wÄ¶ò0Õ³7#ô†œÌ©4¤ø³+mA˜3A�GxoµkÏa8ˆõm`8¾dCwKGÑ×jC�qw®~‘Í‰�kè�$¡ÐQËW   wç�š¬'€óNZ9î•QƒÇÑ~ËZ¼¶ÛÚ9„í½‰œm‘¤r9Gã`fÇšj$UƒñLP×'°ÆˆÇd	Õ@2Í¾óÓ-Ó=vx7º·>ÿ\…ÂÂ	_ ºöSÂro�˜#àH¦‘Nu-gULÒ+ðé ]¼EX~@×&ºö®ßÝµçÌÝÞÒämœ‰ëÎFÛº³!Íè GTÔxøL�A0 `ç‘Ü‡ØÕ8É#»  3è#cˆÞK”V Ôø+€}j"ÒaÄ‡ÁøjÍ:ø2×EuÕÑ”ãÉ@­‡Ï<{€iId1pž ÔèÇcÑ¼¹X¶xá¸‡ÏýÿRŸ“=åÈBTRúaùeTW·ÀûðV-˜ƒf¿0)åÀ1IC"=ˆ#¥šB_jŠo|¨ÑÎÝHôìGïþ]Hv½©ï Õ5•°OŠÅ|îD˜
¢ºv@Wæ�…§_Š¶Õ§Ï3–"H©:¶uæ´,WcC>€j*¤�ÎÌks—�\óÌ�„Ë|úM ½Æ7ë8x;Ž¨ëò–e.Ô¶ä4ÉÆd[ uf~Déá …@öpP»q\c�‡gÐr•ßO`2ç��[·ô=Ô;¸’#¢§‹¦ÙòTÿÄfÍD³_¨êÍtb¾gCN&=ô6½0r`†Ž@ªg_±6MÄ4Ýµ ô˜ðg!­·¸�pÂÌØ�íŸ|åç¯_¶ýžÆŽùg\ŽŽ÷_fx\"Sëá±jV=vÈD	²ù Âñà<�7ÐoB	2 @Èã ôyð¼ÇÃPe°./Æ
E30öw�CÒM[|…ãÁ*ï³ V¢YéñàåáÔ/)°«© #C‡¸´9à—ÂýKc'Çc¾G»ö!Ö¹‘î9�<mÐà•´�þ*a¸'žò‘w¦ƒo>�‘NDºÀRxðÌí÷ÜôÅ=�Þõ�%|í'_`ÔúÜÌ’ö¦^@¨m5{t5',˜:ðú(£ Öo¼ü©Ÿý-Ub(©ÌÊNµâf~±ÙƒÓÇ¢Ñ—-Œn µ¶ûj ¥}H9“Èd€c�™>äT18M*V•´‚D Y3†ž¹ñ‚pÚF!ûºBé+i‚g£Jæ;)1*+Â¼	J÷–}ž0ìNð®�£´é£S]�6¾ùQÓGÿ«Yöúmÿ~íîÇ~»ùø+¾‰™ËÖ`Ns S	–l€2ÜmþLsá—ûˆ´BÞ C�•	”Î4Ÿ“‰™8™(§,¥  £\-€bÜ�]‡e�ÁÀÌ €7¬ˆ÷`fÝ£3&Á|ßàMlÈ[„åÞ¢šrÔT(V3E¨Çùj"í"|,Ù{ð¦çþûcÿÕ°æœ¬ÛüuÌhnAwTï¯ƒ�¡¤ÀûB�‡S º>ÏáGìÐaÈIPÃú.Ç7q20Ù£�QÅ g¥=sŒ–³Ggúþq%¬¾D~C>$ÍèÒ
€°ÜAª«™lÀýÃ ©bó}øÐ®rýÔöa4ÄVh¾SóªMþ˜èd¤Á¹Co<qÒŸ_~ø§ë®¾yÅ’OEwT†X×ŠTÏ>³©%ËƒZÖoÚ,–w»Ì,SCŠƒÓÛ¼ŸŽÐ …¬QÈ™ü¡`Y<cŽL³”‚;=þKÕ)º†aÄ†ÐÓß�7ß~oíDb¨ŒCÂ]ÿËÙ§^ü3 ­ ¨¡í€H·92œGØ™ï‰®=¥Ë|…°ìÎcæûÑC•_X¿ióÚ~|Õ¿ŒìûÄõk>r  ;ŠLV +º¡%Uô,XÝ†'ïØ_æ�C Ž:…>�¦b‰\¡ù¯QM£�­85tˆÁ_~ûküäûßÅ‘Ã�6G"[ApãÜf$#Ã�÷ÿØ¼V  ·ƒê*ý‡1°óU§æ;Ž™ïcÇ†ëïõËÊRCN6ò¡Æ¹Ztp €0™t±èžWnê~àG/u|îæ¹‚Ëó~ƒ0ýZ*þfË;¯tMé™>îï<ôëÿëïÜûËs®úïu)…`8Pg* —Z2ŠTÏžF˜>þQU×1ÔuÑ×Æ‚^9Õ§ãNÝÏ ãÜËðËMçã¡_ý ÿ{÷o²¬qò}€^
ä×Ç H›sHg’Á> ;	Ë¿Fm7a¸éT×c’í­çe]`þêkA��ÃÔ•Û?²û•ž9ñðœ·†�<ÝrúÇstš¶,·�hÊß)ùØ¾_\Yuad<ÁÚºE«oY÷Éë/TDû»¡F�êÙ]×Nì~àG/•>‚™àm›ßÂup5Îï�-BrÞø€ýmq»DÔ‡J�C/…„$£¿ûú½ÉƒÛ°éÛÝ×/²hôU7>V4zyø]åó	¼<|£Ñ9ÃC~ Üò]ôôôP]×þ(½)ÿ}�)â¸Ô¸ @˜wŠ™ï‰sÌ|/�õ›6‹+6žCXîÃïüè“?4Tùõð[×2V_bzOÇ¡Öï†Ï-¢ÖE ¹ÍtÑ “"éŽ´üîß¯Ü²úóß^ÑÒZ�ž¨ŒDÜ¬Ù`8n!€…à…‹D^À¢«oß†ù+á]Øù?—<?¦“Îƒ‘Œ¼þÄÅÙúÌç~ïÏ×K5ÍP£faO*6þ˜$¨ºŽápjd ±=¯€åK'Mæ`Òrp;ÌÊõ¹û‰^?.¼ô2œpÆEøÙ¯ï";¾ã{ñCo·ôÚìýFU‹jNÿnþwÌ|¯§üð¹ý‡||¸ŒM¯ò³þéøÍ_5XqãâùsÑQëF¨¦õ¾Òi¯ú¼YøÃMßXñÅ:®�ÙAV3ÄUôô¢ �#zGb£
AW¾Ò~Á—Ùyÿ�?[­k¢ºzÃk�ÿ©ÿ¸Ó/þ©h€–ˆB=Š@$–€.'AuÒH?¼�3Kî?]¦bqŒóV`ÅÎy ¡¢yÍYh^s¶={Í¾gþÔ¾0Ôv™e¹OìÜ¥ ,¼úö	ÁW»�’�ØÑ\ãGëqg¡-uð{Ýo½‚3VÌv|L–e°ñ’Ïd„0Ã@--�6`žI¤T;õb×á>tö‡;øÖòõ›6‹��à�=óÖÔNøÑx­« hÆÆKj¥-04†œ*:ÉxºÂŽ ´ß�Mê��°ËOAÃòS.êŠ<ˆ'ï¸8¦ Æ�Å_¿w=U’ßbX.Ó6Fà8tÌiÇq³š3ùà‹>=îþ×Ü®Z²FÍÎ>:…bÐÌ¬�šÚœ%ë.ý<jNè'?5ÔÍ³8~^ŽŸ×†”ªãÛOßºîù§îz|Án>™! tå¢E×Üþlc{Ç—Ÿ½êäÊæRg¡ëá[~X°Öàu?GïÑÃÿÉÕä²½-¸¦IÀíð<JïuG#0Žn³~?¦ ÆˆŽÏÝ<—÷…¾Mtå"Âš·Qà8,]8Kf6´U8›>ÿïè�)HiÔqïE‘%¶‰ž�›g!rž�ó,”‘>\ÿË{On>nÙ²{»Á°Ü)ƒ]‡Þ\tí�?jòn(_Ìc��?üÄ/]{ç¢©¾ÿN‘ÝOÐiÒdŽ-¯àÌ(V+`¥ågƒ¥ša<ø«]ÖßÇÀ¡ö¾ó5qþš‹€Ò‚¯hÂ’†˜¬CuÕ¡;*çtê+’ª‘3<ÓÃ3¹9xx+ÏºëN6‡[|þ¬Õ88œUó•¾xô²ÅWýúº�?üÄ/ÆòÙ»nºâª×ßê~àGU¿¯Z2
e¸òP7ÔØ09C5Wî°‹�!ú!x|àÝ>x›çÀÝ8b¨ÉÑ±©ÃiPÜ4à *ñÿ‹Y ½±ÂÕß ìÖìÈÝ»N8ËP:>wó\+øÏ?ïYøåUXÐÞ‚•K”~ÆeÃ)É¼•¾\Ç5-Ë  Ža�37‚Ž §_ü1Èš1íÎ®uãóg­ÆÛ»ñÐëûÑ;«#ü|ÑWï>­ÉëûôX¬'ï±ºMA5»ëP]ƒ¡iÈVTW?¸ñ½¯Aé?P2“´Ø+¼7ˆ†ù+P·h5ZÖžUT!X}À/­�Š4`;8íÉÁZÔÿ?.ìjÄü-çýS}¡cÅúM›ÅŸ5Î_å›×¶�²ˆ¬¥+/»ù†Âò7šSkª‡…Wß~!a˜_njçò'ªkCíá·±þüÓrö‹ËfÛp©HµªSð¬ùZ2ÝMXÓ�¢3ðx–dLAž!™^"K rÄV1HÅ�a	^‘E£—Ï(‚%³[Ñ1£�½þžÞ~ ÁE}Ñð²Å_¿÷SÕ
æ‚ =-xù&xlÏ«xöž‚D³3ÛÑÖÚŠÚ:³Ò®¶Öü?TÓ€ðˆIäc÷þNÚ»›ª‰é~óYt¿ù,ÞþÃ�é‚Ó.&s?xÑE5³ZM…1UH°¡¥Ø	ÃÅMóßåÐJ,•#p$Rh„“òcÙ
àÍ‹¯ŸX8û”´ Ï¥ Ç1„Ì[úéóâ…‘ƒ pá„ÿÍôâ']{ç†ù
 xg,Äi7þns×_oÅÝƒS/»K hzãjÁŠŸI3LW *�­¿�A¡*ÈêðÊ3�…—gàØœÕ !ë8 ëðŠ,šýx†@äœ»fæÏnÇoŸz‰xla|×ó—˜ @¶ æ@Ô€®ÂÐÔL_ÀDçÛè~ä ¦ÀoØp
ÞwÚiX»v-<žÂ¦ n·��…Ã4UI&{ìÇ–-[pï}÷á‘‡&;ý-$YÆÒÍ7@ÑP]Õ5ÈiâÒß^¼˜qºä 8�ÿóÿÍÀ@¢�ó }]¯dÿ=­À›_?‡aù&ß¼¶…CÎ¦ Ç�ÒV†arªÙ}Eotã»OþÁ|={Ç8°~ÓfqðøÓïf.²¶uÌž…å3€µk±óÑß`û3AûÚ3mo¶…°¤!"é™Î¬fGá~a¥$³Z
¼ùYí¿ÞcPD$É<îŒ  ŸÈåÄ…²Ž}r
>u3÷`Q£×ž"n}àIüí�Ÿ¼³~Ófq¿?´ª|vŸs¤3Eû 4)#}`E/O TW¡Œ˜}gÌlÇÝwÝ	 ðz½¶Â_
¼KÄâÅ‹±xñb|ìcÃu×Ý€o}ëF1ëZT)‘éi�8¸� 5Ë‹o( ‘%ãöÿF<èù®Û”(€bæ»­ ;˜S¨©*þß]?´þüKþ Ž±`Ãõ÷‡úbá‚Lxïøã`Vóèè¬ùïû0¢‰¢Â–4%Ô‚fªA3ÂO)Ð55§WÎ=àxpÜè×ÄeB��+`Š‡S:†S:‚.A›ó@ÄUÄ$m!x† èbÁ| 9glð_VœZ¸öÎíºéŠ«Æ{ÿ «®€ü ›¥ÃoA¬ŸªkÐ£ÍÏÛZ[Çñ	…˜7ovæ÷„$CÖ(´ø";Í‰Ñ®šF„Ž;©èû§CÐí�ý/ÿ?8RHƒåûÿÀ$( §æûxæ‘þâ¥G°#ÖŒÎà×9g„?+¶Ÿ/ü²¦£sD‚Fpš–CJš�¾¸jÛ‹�*)š‚Þ(SLM7 é@JE¦G�›gpqhŒæ¯›V�V $�bß`
í5.¸�ö¾øný¿GN> {pÿë‡ à+Ko|øÈŽëÏþÞ¸nb„ånb®�Fú‰;ÜVô€°Ü¤tÿIÄcÐ’QJ
‘7Ì‰Ñ³Nþ`I÷«šñÂ)(Ñsðp¤Päûÿ@ÀxÌ÷ñ ‹Ñï?û€yhBn¯é¿~Óf1[øŽÃñË— ¥f´N*¡èèÌbX5j’>‘Ã@Bµ�ÛS%…”$çaÕê€›RM÷BÕuD5|Ú„Œ¤G—Õ{r­…Î	F2‚›ÿ0jBAXc0ïýŒøðw_õëøXÃ„9×­«Ûu�;lŽïÞ!ÔFJäLšªIV F0òÊC�FúÁ{ƒXpÆeEßã4ñf"Á1Î{ æçÿ[ˆ«¶ñí7?[ðy•ž`µÍ÷ñâ¦?Üžn+F¶:RiŸtåÏþˆ¤Ù÷Ò×(ºÃQLî-µüÌkYm°M¢JÍd«Yí±ÇCÍVX„åÍŸ<· 0Õ JéJé¨s³E ÝQ~‘ËiøZ[W�UBç¾w9Â*ƒ§· á…Ÿ/þú½;ª ÿ¯TS.T|÷Kð/^_v h5 F?¸/? XvÉU€'TtqÌÂpÚI˜#´h¢Ðþ¡BÿŸã¸ûíÂã%?m2Ì÷ñàí�nÜÖùŠu_oüÑµwþ0›ð;þ¸Ž„?©hè�šÇ'•HÀPŠ�Å¶VACŠ—<¯Q]>úÅ*0GO–7‡yºr­‰¡”Ž¨¬¡Ö# äbÁ0ª�Ca­!·ùÕ¥ù‹¯ùþË7,E2ÇËû@UéþŽÏÝ¼f¼¥Æé±èŸ¥¿Mtíá0.ßxéä3?¸½ÿœ kÎAÛ)•|Ït  �šÿ¥Â{m€¢²Û×ö(ë7m±rMÊï÷çÜ‘©¿=¹øÉw§OŒy.]Í8ft|îæ¹T•¿‚ôj»xþÜŸ?¡èe… 4M«ëH&ì…ÚÐTr
Z"Àâ±Â´R@2Š¸ïòBGK]Uƒ /m¶„Œ5‘tø<c® Jàô5è¼÷YôŽÄêx�ï6 ÆýeQú;Ò
J¿?ôxoù&¡ã�îG×Ÿn¢º¦’À¼ã±æ×—}�Ç!ù6Q¨ÄüQ ±ôTé|Dø‹Ýþ¶êæù'ï�å—v½¬©Ó·�ãÛÝx¸k‡yÿ/ã=Þ¾_\¹øùßÿA—Sh®ñcQûh²ˆ¬åúüò…0GiÅ†í«Î´DÊpOFø�Ñ™xºœ2Ó`Gz!�4p©ž}HõìƒÜÊp7”án³A§Ï1¡	ËA’Ä"#‚,ç*ª¤jàÐH
IE‡7½Â‰ª9óâ†j¦{¬‡gð‰3×š÷–åNY|Õ¯?W•/�Ò›Ëß h—©jAMD k*	,\‹“¿ú0e­Ù[oj—¸j˜ÿ†ŸSút±ÌÍ¢ö†aÐ{£/ïÂtEfõþb¨òÕ8æà¶g¯9ø›¢‹fŒŽ¢Öt�#Î…ß2ë³+Ït9y¨;Gð¤ãá}Hõìƒ2Ü52 ]J€jrÎ Mª«0ä¤yüØ”‘^È‡ ÷‚)8¦¥²yÕ H¨Hd…ó•@oLÉÓì¨sãkMo�æªj}oTWo !�9‹bB1çÔáä«RVø�é‘ÇŸý·k ÐåL)ú#Åö/zÕüÌº?		±·Lõ})@,£™ÕŸÿg<ÇZzãÃ_�ñÁkž­YyÚ‹T×~#u¥îü×Ï`¤ß¬yïŽ)�‘Ë	¿=]ƒ®FrÂ^†œ„2Ü©¿³@)ä£ÔD]ª«Ð“QÈ��‡ºs&ìR]ÅÐÐPÆá
ž%èŽÊIŽ†I{bJNžBvùèŽŸƒ€Áîª*!ÁÑ“£¿!7Võ˜yðÍ:íÿttÎYk¯©V •$ÿ”2ÿíÊ5M¹§Ø±Šª’•÷Ýxàµ÷~i‹Ò5´6é÷À¿j>ôÁ‰Ý8Åo>•¶ÕÈÖñ¬þ§üð¹ƒ]‡¾˜w<óŽÇêÍÿ‚V—Ž·¶mÅsÿ«ÏßŒ„šû¥¨:u$üTS¡FMW ›é×Ñ¡743UÕPe³`ÅÐ3
ƒ°/‚0,Ã€°¼Iþq"˜¬H€¡¤ t‚óÀzC`8ó3“‰8MAcý¨UÓWÁ0‚.:%èŽ*˜2¹ƒ”ªc ¡¢ÁËcçlÿMZ¿æÌŽÏþø�jõ$™È\ †Í„+™‚g(Ü<)ÿŸjÿßïpõ9RÔügÐ6ûïé§¾¸¶³ØñJ:ºnÜÄ±ì½©]fh}:(MUqÛó�XW÷m8›šd‹þÎ}?f²jùç´ÏÏ2XÛ2IEÇ¡°žÑàFoÓH<÷&—þl?�j*”<K€ê*ôTºœÃ	04J¸z"’öóMmÎºý ËCÖƒ4‚õ˜‘	†ãÁÀq£ -…–ŒšÛ½fM…rGQ
dªÝº£2\�È±PušzÀä†û{ñûïü3®úô'°Ÿm¼uk*ƒâ .žÒ`°`ÀÍ³ikhTˆ¦ƒÿt;Ë	)•ü³«ß&âDéÿ–:^Ip�7þà�R�!Äm)�º3V#õv'¦
�Ü‰A% }ë7^ñÇ±Æý^}û…Ù™~sÚ3É3†1ZH¡I‡‡g��äœ|ª©Ž„_�t£Ñâ#Ð’³HeàpÙRØlðÞ ÄúpÏ\ÂòÐapÞPFà¤ÏA†Pk¦ÚJª�Áp-u£ì{çˆ„9µnp,“‰¸x<KP×Ü‚ïÝv àPï¶Þý,‚‹:>wóÜjXÔÐã=ÆX�Ru¤€«Àiã�‰B@tî~]öçÚ•Ø–jÆÈ¡C)u¼’
àù'ï�S'é!�nÆÆS»c@ÓeïCì™©Äûçg¬hùÍXãþë7m�ÿ²þöúühªmGSr›m f^ùp8šIÄ -YÈdç¿–C‰š#¤YÑC•¡FÍ•]ï qp;Õ55³üÔ^,ô6 èñ¡‰5É«>=…Îè zå•ÔDj"+œæ[¸¾ÙË Kqð¾˜ô N]NA�A¨1{½Jª�þH�Aóu�šM#[¦ù?”Ô0¯^ Ï$U)E‡[`1«¹óZë±·{¼7ðe W�ÿ›$# Å@$>þC�ÙVAƒ—‡fÐ)³j®þ>�)šû¿³¿Ðü×ÁÜ]®oCÙ¸C ­é&­³?“A‘ÚuÝ?­Ÿ?É·MºKpî†3�g€¿öïù£1ÆnÅCË7|<ÝE °pVK¦®Þ0Äeäg=Xí¸­Œ=«Ä4j¤¸ð[¯ër4Cø­ç­P©¼8·y	6úf¡Ã[Ø_bƒÓ¼‹è2:µ(^9Œ�©!ª&"däõÇß½5'œÚ8¬è†PÛ
ÂrÐ¥8”‘ÞŒH¤d„9!¯Ù#,i¨õp¹8ƒ”ªƒO»EYÏ¦\¸j¾Ó= —­ß´ùkãMºb8>f¨2”¬Â D"�††ÛýS)gýü*…•ü“Ttð,K&· ò¯Æm/®Šf`g¡A“”»Ë³¬X~Ïu/½vâ—Bæd>°k‡þë·˜õ��˜4‰ÖÀÙó—ãìùËaÆŸÜÙuà—+ï»±¢P%ÌU–x{}~£fqXÒ¡¹Â/ËfUYæýº
52 Â‰kÀ�â0äQL—S9Â¯'cÐ£ý�#ƒˆîÞÀœ¬tEëJòå§‚¯±ÏŒSGâ@bô8AVÄ2¶ËšÑeòŠÜ‡GûÌ¦ýÏÜƒÀÂµ-ß˜^ùÍÎ8ùJ`$–‚Àsð\ƒ¤¢ga„SZ†e§4Ôyxð,ÁÊ³!<ºŠ¦Õ¬Øxž¼£äxð²ß¥� Ð7<1ù N7?ú]«:…
@Ò4¸ÒÍV&Ú*:ú˜±ÿbá¿½CR&|k�€îú«/w\GªÇ ôæüm4)ãàu·!ùÖ!4|ìt°õcŸÚ20SÃ0Ì×k–tì?øo·?¹ÿºÛ6o¸þþP¹÷-¼úö³Wÿö–†œÕ8YFQ¥\íj•³RM6_ŠCÍvª«PÂ}™¿õdòp’·e„©¿�~ä›äºË>‡Ú“–Á¿düKæÀ=Üóg€õ›fzg‚œîZÔó¹µòAVÄû<í¸®ýR/x ÑÝ[0ô÷ÿK}Ö9Hñ—%žRàX¸8’F—MkF5(¢Y³!­ßy–à½‹Í~ú„aNÁ8qÒ)îg9žª‰"‘ÑóÒ´É"ZŒT“4Š¤bYiÆ8˜æà8šú 5žâáÌ7º
S*RŠ~‹“ã:R _=ã}¿¦”ÚÚ`ý¿{ûòGº|#ü–MÈ�*B˜�,ËÞ~'¢#ÿíößï¿î¶Íë7m¶ÿ’8¸í*iàt9�ãr|§«~l^�ešN €5ÌCJ yp+â»· Ño©o_�¾ô-ÌŸ3Ÿëÿq<Žçá™ÙÖïA½èÍ¼VL Àˆ¡PÀ´*]{0øÜïM¡�åº  À»Ü0rVÐpjô÷xVÇ¡ìîÅkÚ3–Rñ’:‡xþÉ;d]Sû³½—¨RùUÝjæ¤$œgHÙì;U7ATÒ hÎ:9;EÈ¡ð•“J÷¡_:9®#ðÌ�„S*öºòÒnrðÓ?_ëGÝÕçÃ½¤½ª7ªÂ\Â²ìíw�´±ÇR–e@8af|ß'Ç¼‰è®—�ŒãpO?Âá¨ºýêŸHå>tÙÍ, 3†o1ü†¦A‰@KFAUJï>Dß|,3`µ^ðâçù*nøø—
ßRg?Ü¼˜£ Sd+�Wä>¤‰Ä}º®Ÿ –èÚƒ‘7‡.%`(æù1CIf|Î¡,¡O*æ| éÒâtßÂ,2táÓ`¦®ãs7Ïÿ—Å¼ {÷ÌlR”*MV¥²»d›ÿN i¦uT«€cœ‡þjÜlQòïÍîBÕ	ù—9§'hkºI=Ôw)Rú§taÏ~ŒÆoBã§Î„oÍBÿeË”å¤Ë“/aY\r'¢ ÿvûSGžzmèŠ�§Ð·s/À»àn��={÷‚óÕ€j‡ Kq¸\nPo\¢ †rÒiíV=9ê¨ñ0�oAêÕèÉ¤‘~°Oÿß¦‹Èæ•i~�•Øú boìMšŸåæEÔ”G]‘ g’xû¤<Ú·› „åþ‡êÚ_­Ê»èî-p·-€—á˜äš–ˆBÔ�cMÂOÒŒL\B5LÇÇ³ÉÀ¨dò‡æ?zGbàÜ¾•ït`J÷8ùà¡} Ì6æ¥\ E–Á»JÏõM+EI”îj=c ªê£�¬&­•¢’Õßjã–�˜¤a÷@¡a‰F¿ïôØŽÏbù=×½ôÚ{¿´ÀÚRûõÿîI„ŸÝŠYßü(Ú®<ñ­ûynÇ”'Âlœ¹i5žÂjÄb1ú\ïr¤-…WºßÆ®#lFÐeO „‘Ý¦Y¯É™¬;=Ý_Hççk*”Þ}P%“üÓ"ýÐ¢Ðj"‚¥þfœµé"l^¹~¿pPPÉÖ ÷ÁÊ»°PL	d¯þ'møè]Ï?y‡™jr@7GÞxÞöã2¹€)\Àü=&ë£
@Ñ3¦¦¤ê20›`Z4£½#1‹‚í ÀÞ={3›ò™²‘�%xQšk²\ CNÒR÷Ûì°<þô_I£�4<KÀ³ÎIC§¹¥Vÿ×m|út%ÓŸ*jbe–ÛÏ²êN?uWŸ�¶ÓG €ßï'gûÍÆ�Ÿi7³ß	à`x;jÂØçp¨'ŠÁtcI«�•<�+”z|z2]1Ú¦Ú –{qÜªEØ´è,iÈô»sôT°õèƒQDž¶ÿþ\œ d)€ˆ&å¬þÙ¡9Æ¸ÆHF.”FúýÉ#»áïX	¤€–Œi•´L`v³ì¶æ	EG]zŸÕ´“0mãÿ&È[ ÅÖwF‰R¡@'L¡k*¡J
D°/
T°;A%VAÈÍ9ý[ýÍÀŽ¾ÂÌ¿hJþ¯rÇÌFEwaÍ–ŸÞ÷Ú{¿´…€¬u²ÿÐã¯bø…íhûô9h¸d|+:¦•"ÈÜžÇ’†V,ihÅÙ P Ð–®AJ’èa)F à`xvÁ{çs>¨>„ùõÅà^ÒŽÔÛ�züÕ¢ûBP/z3VÀ-=¯¦W²5¿ª9Î�Ü
Ðkâ{^†oöqk†j*4Ýl\¢ªAÁ3ªN¡éK
™Zhò¥CkÄ8Á¸ý/i7éÀ�˜3ÇŒ4kšVÐñp–PmL¥EÁ×ÛO¹«« ²QÊ*àçU¥ÞèŠÛ…þÞpúËFÅwÁ©`�&eùÑÑÿ‡gÐúùóP³q%|+:�:Ø‹øË»§4­¸ìÍáyøyž,1Í÷ì½ªðoX†‘'^/ºòÛáõx^9–ã)%ÌíâÞ/üÑPåkR]ïPCÓˆ.§Àq¦Mäà1ýeYÕÁ§ÙpƒZÎ²6JÖÖ¥‹Š(œÍã*SIa€ŽW_ß–Q Š¢Ø* 'ð`9žêšJñBõ…ûDfRºÿØY!—óÕ?»}[6ÍÀ›Ý6ÕÔ”:öý-Tì­ÙòÓû(¥×+]C8xÝmØõÉïaä©7ážÝŒ†K6 åë—À¿aÙ¤çL°õø7,CßÝO8~' ¢Iøé³}¿®iw«ˆ|ïÉ—¾j	ƒÈ!4³C›ŠjRý<K QóF}ÿì…¦IHƒaêQ�çàÕ—_Ìl)E:	¶´´ PFzm_+ù7HéIÐÇ@ÓËÏ(,µúoïML’" ûüÄŠ²™ù“šÕãk•XÙHí:Œƒ×Ý†¾E3ÑtÙûP³qeæçh°
ªÿ†eÐ"8ô_¿Í°ýNqKÏ«™‚¨´¯o»_šØ C‹‡˜µ
òP7æ-^Šµµ<êjB¨­«g²gâ©:ÅðÐ ¤p±á.ŠA\Ü�9óTý>–}žêÚæ×wìÌl+E:‰´µ¶âÈáN(‘Á‚×Ü<;eµÿ!gŽ‚×œév³J­þ¯¶qŸ)-ßóÌcR k¶üô¾üôàJa)‚î¶:4^´¡óÖÁ=»îÙÍP%òî#Hí>ò®SþËÀ×úqäÇ*`ú�àÁ¾·3¦¿®ëK›Ñ%@â EbÿÆâ´s.À	ûbÉ!˜<KÐÔØ Ža°pÎL,ð×ÇÇï~qR‹ ëM |i!tÂ<
˜-¼¶¼±kW-C"‘@MM�­à$0oþ<lÙòä¡®‚×êÜSSùçâH¦æŸ!Zšo�j€cIN/ÀRÌÿ]ñª­þÀ8æŒÇ
È†Ò5„#?ú#ºn}µ'-CíßßŠð+:à[Ñ‘£”þð´"+�Ã2¸æ4càöÇK}¥°#Ü�ÿì|– º¦ý  ¡RËñô}ç^HÎýÈ'?©æôœ,³”cˆ�‡7«[ýÎ=óýàÎ9o<z¾ækðÎ[]•IÌæ² +ž~ü¬]ef“&“É£Ÿ'DàìY  yðHÎv'™…z/¦H�¦SD4gr�"NBÑñj—­ï?¦Õg£ß×Þû¥—œF*�{ÑLÔ�±ž3VÁÌ}R{!è…6™öÖ�{I;Üg€zÇ%ø p8>ŒOîú“iúæ¹õ/?½”ð1ž`­‘ŠÝÏ{ü'ã‡ÿ‹ùïY Iéè�)I*Kz&P~‘Å{fø13(¢ÁË££Î…žƒ{ñþ3ÎÄ‘Ã‡·Ž?w¼ÃXËß@uõzÞÄã= ÀœX,ØÚÔ\Ò¸ýöÛññ�ÞÆ™Xqý™íÍ~¡¢œjÁ#°hõ;ãjÜ,¿ïv¼ü‡_¢­µüŒÅXÑšæ"én@SÆ_ŸihB@ßxðãË�ó½Ï…m»ô?×©‡ú^$8ÀR¾5ážÝ\ðz¶B˜‚%ôdv”×÷£û/§ÊK»ÇuƒRªŒËvÜ‹© ØÇx‚kJ™þ„fRMyŠåø¹_»ëI2Þ<
Ëè‘ i¹”µò[D  ¼Ù:ØRsjÝàY�!XÕæÃ™k±oß>,]ý^H#ý}„åO§º:æ’PÂòË¨®n€o~ózœ~º™8cÆ[7 >TS°0dã™gžÁ©§ž
 8ñ/€nðAGÝØ[°�í5.¢;zŽÛ^zßûæÕ™ú‘,Ä@˜7Vmêš;žêxÿe/T’ø“�qKîó'é>�N.ïqœ@h«Cè”ð7¾Û®ª$Cë�I µÛ4'J1°õ�¡ŒÀ¢ˆø‹;{f;†_Ø^1¹g‡”*ã³»°f–6Ó,¿s@W|øß~Š5ï;Û{Á×t‰Dƒ±$Y)èT”s}¢.QÀq³ZÐÁ³³B"Ö´Ðêçñìã�àüóÏ(%Ø cíÚuøö·Í>„µµµ¶n  Ìš5«è�úûûÑÔdF)WþË=ðÌX0e«ƒ—wTòkPŠ¶ ˜“ êÃÿüËW°ëÅ¿ [O`Ó8ïqÆ­ Þ¼øú9ú‘á·!“®^Ý‹fÂ¿j><ÇÍ‚kN³­…��D$
f$	=b&Ò¨Ã¦?¥¯IçÌX9_kæ°A/¸æð.1‡ŸèßòU·$ÕzyÂcxñ¬²MP	¹”~oî¢¥øÄÍÁÛé>q’f «o ‰heõ÷Þ@l:_ Ù/à’å�XÔhfÖ{x|ú#Ä#?€| ×Žãr÷è €Ûn»sæÌ—0³}ŽîÄœËnDûIçMÉêïâZbQß?nžA{�«`»ªSüúGßÅc·} ä#fšwõ0n•¸ò¾¼ºîÊ›!×UóÄœ µëp“N<"\í�f)m} žãf�¯õƒÌn€70ÍÆ`åù–â�ôf"ÉÃ}ù,~Uý Ãña\µç!Ëìw&ü @éç`åY—f„?�£³·ßv"¯�2«5Çƒp"ø@„Ú–Œð GÌ¹s�A{È¯@ð¹Ï~6­ è§×oÚü�1‘‚„|”vX>ñ·¿áÓŸú‰¼^/<žÂòçráÀeË–âÈáNÄnGÓªæWã¥ˆ¿|XmÙòÁ³â)W`¡þæ†_(‘�çÇË¹d£*6ÑUžØþ(øèxÂ‚Õ MÊJ!Ä#‚¯ñ�õ{ ‡<Ôír|;)I¢l8I @�%¡ta²±#Ü�kö>2ëçÅ9~Æ¬5’‘ ÐÚO `
ÿ¡®îÌ>Z|áíÏ"¾çe¤ºÞÉéG˜–ã©wö2â[¸'¼ï<,oY ØÖGÈÅ!äöbÝºuÖîþžùí qéHÂdo»÷OÆ%_Œ`0ˆD"a« Ã#%y€ãW­Æ#?ŒÔá�SÂü×z8¸V	Ö¸Ù¢aÙ—;£Jª¨[ø¸®þu óß¹wäÍ¿�X­ó¬ÚªõòÚ/^\�°à?2(¥x°ïmügç³–`î#,ÿA§[ZÀ‡~ùwˆ¾öuõeÌþðögÐó—›K
}1°OO»ü*rî§®B�›E�‡Ç™ÍÊ;Á‚šˆ€°üòŠÉÀ´ËÂr<õ/YOÂÛž |ô²ËðéO}
@q2°”�M^vûË<“—iÊ³3ƒÎLÿlâ/QIÃí¯öæÔe0††¡®ƒ'Wcj30†TàbX³å§÷QÐ-Õ:Þ?RªŒí|
7îÿ›YàC˜çOpM%•&ˆú @M×ÃKòhƒ�¾Ç�±?`V×=vÛwá˜ô(ró¡T%†œ¤,ÇS"zº*9&á„™VÛÛq<q7ÏÍ½÷OÎ´
±}ÿH	>ã„•«Àr<€C»ßÏWS1š|ÎLƒR´Š‡ŸÜ.(Ê’5úDµ„¨¢  ¶­öÃÅZ‡Cq<=°ço½wíH?´äûë7^~úØ_ò 8²ÍÌ­¯Œvª;ñÂq�çú}’jöÉ³âÚ�<ö(tM%º¦>TéùRMù ?ïÂ3s	XO ÁåfPMDpï}æ\‚D"a[P*)Èà„÷¼‡ Ààë��ëº+A%¦�‡+:xwûòÆ|3†7Q¾ZÍó­j^ä/Þ~&ü™k\„�q7�üGÀáø0¾Ûó"n>ø’f¡N¥¸ ?ë<°uLèOðUªÊÜó¦oÖÚ÷#P×ˆ¤ªC•exf.Bpñ‰`ˆ’ÈX	¥àªiDÍ	gáÄOþN¿ð2ÈC€%M^ˆj
gŸ{.¢ÑHŒ°üGAg“M “øþ êV½œ¯B¨| É[a¨2ví;„ó?p6\.t]‡×ë-8OEÜ€ƒ�à¹çžA*ÆÒ³¯˜ðïÓÅ4x8É‹áX‚™!—ík)UÇß*h;æáÙ¯=uåÚñ5aÉCÕ3xÖoÚ,þH
<3‚ï¤T¿ê{wv¿™å�“;Ò…=ãŽó2¼x’¡Ê�xgúOû—[áªŸ�Á‘0†Ã¹CJÓíÂ•È t9	ªk ,Vô€ó†àné@pF†œÇŒ€€—5b^�ýÃaÜø™Kðêk¯Q]×>ZIx*�¨ô
€&ß¬ãà_¸|°lzŠolß|ñ~ ÀYgŸ�¯ýó? m	Áb9¯¾ú*V¯^ 8ïE}Ûì	üV�'ü”bv­«èêÿÐÎ¡‚)¿²$mw?tËêñ¦^çcBRøÒ‚ONEnÀt†%øî}Ûbø�­/|±Z#Î-¤•ÀÿñÞ`Ó²K®Â¼MæH¿Á‘0²ê8À¢±¾^-«gø°ûñ{ðïÿý$úÇÒýÿúM›ÅçŸºëqPãdÞDÝ‰‚õø!F»3‹í8xû×2£ÒÊå”Ê´ò–]z-V_øéjÞâ´Dxygu½�/ÚégwÙ•ybŒ.¯OÆ_1LHiÔÏw<yä˜+0ŠÃñaÜÙÿ&®Úó}}ä0±Ì}ÂrW¯ßxù—í{­ê3Ø©¡&œð{]NÎïyó™_ø3tMEãìEhnl@]m‚¿á÷z‰èáõzr~êkBh¨¯5ê‚~²¬ÙA�ã�§þ·~ó³øã½÷@MÆŸ#,÷!úß*9¯ÎÛ¾ÐK ö„³ÀyƒkF{‹˜–€¬¿Ñ]fÏƒí»÷áüœU5§‹b®ÉŸ”$„B!ÛÏÛà0^yù%$F±ôÌ�LÈ÷[ëátjtóLÑ˜TÒðÀÛ“cú[˜°$þtW ¥ÊØ>Œÿ4Ëw³°„ü|ýÆ+n®¶9Wikàë,ÇŸ£k*ñÍ:3­€»u>¼ÍsPÓØ*x!ð,UQHDÃˆöv"¾ÿMÈ‡¶aÿ®V§�‡@˜Ÿ‚*ó`&üü ×Â;k)„Ú–Ì(sÖåÍL/€Î{ÿñCo ¾ø¥«qñ‡Î`,fd»§Ýxf-^YÕ{[I¶ Ì­s�ùÿþÍ>‰æ¶EWõ	ñÏ?ûÀD=+Úi*Ó„§–Ð?‘ìÄ£}»óãíû@È¿¦'OŠàçƒñk©œ¸�êúz€®G:õ¶ú ¼BXîæÑ±f¡Y¼ ¿·m>ü‹×ƒÔ‚ËŠÏ‹íe ˜3öüä3T×TÂr<ýÕ­¿$¥\�b\@ÇâeØ¿kæœú!lüÂ·ªv?+‰÷—óû_îŒâ¹ƒ¹n†¨«žúâÚ	+{�ðÆh/¯ýâÅ,ÃÜ;‘ƒSJ)ÞŠô`Ÿ4‚'Föá¥XW‰$²uý¦+ÖN•ðÛÁTÉ6jèm ­!ë5Çv“†ãcà];«AJ¦«ýÐäªiDè=çøýBmk† ÆåƒPÓŒÞÇoC÷#æ”«¹‹–â×¿0§ÔÙ
¹Ýn46ö*ýÎoÆ×®þXŽ§þÕ¤ZIA3‚‚ã�_)¿¿;ªàwoölWRÉ+^ýêú»ªr²E0)R9™ƒJ)Ž$F°/5Œíò Þ‰”øB–¿‘êêS}-“‰láç½AÔ®=¬ÛŸã÷sÞø,e@8BM3Çƒj*ÞùÑ'�èÚ 7CÐ.*`—˜ˆDQÓÖ5©X	éW¬Ð0C~w¿Þ‹¨œ7Ž>½së×OÝ<A_Ëè½žè Ò|@*°sªkŠ�R
IS0('Ñ$ªÉÌîwbè–"èTãE…�åxÊˆžÌké±ß™î´ÙûQÂœ\mÆº"_økN8œ'>ØPÔïLk€G[êÙ‹Ý?øxæ^~û?ÉtÊçŠYW~ùüô'?€«¦ùÙ ;öÆ NK|�Ò©¾€½ß?Q!?;Lš]>>à�Þ·ðoUí\éñ^1]Áˆ¡T´Š[Â.x ïáÐTzV[n]‘Á
bæw5ÉV}„VW³¢k:Â
C¢„ðN„«aFÎûø`CN¢…ÁïGç}fŸ WM#~û­ƒ¶|€!xèÐ!tÌ›OuM%Çüz¬<ëÃcº®Z‡Z‡3ý€Ò¤ßSûÂÓ}0Ìª‰Mò³Ã¤:æcåžØ‹kö<<)çÈr<åý5„åÅŒ€3.ÑÞå�*%‘ß…×PePMÉì]…2t,/‚¸aÅµ'ª¹Ã´�Éöß‚tšo1ájšrH?Ëï/†wÿFÒi½s-Å¾ý­¢JÀÎÈ¶.úÁ_*.
¸8Ô{8ÇŒ{�X”ôÛÙ—ÀÃ»¿þÉðû³1éÌÜ«ë®ü†a*êp8>Œó·¥›žòU Ý•¼ Ã-ôÔ5gš'zf/‡Øº /‚ÝP¢C ÂŒúuz*%œKÎ]…<Ü°|F)P–‡–ˆÀ�“ö®«ÐS1NÈ„µÞ­J€°üÁ¿éšJ\5�®:¬è)+ü„!6Ì,ylCNbÏÍŸÍð¥ºÙ¹ÙVÀÂó>‹“.»ÚñuyÍùäw÷ÉFLÆ=[

}¤dòÛ¯ÿ¿õ_Ÿð/)“Þ#ù—G^~êòÙk–ò”,qúž ïÂûß2óå	óPz?€•ü0nÿ6WýŒ¯1¢Œèë«E`ápÞ X—´`¦<a9ªd¦ÇºüàüµàCM¦EÀ`À˜·�eYP |°|°œ¯†ª€ê*Äš&ðõ3`(x_Jd  š©ªœI8á!úÑÙê8Œ'XKUù^Pã3Ô0ˆ·m>‚ËßÖå¨/+üBM3Súq$�Àâ÷bäµG`¨2ººŽ ¯¿ëO:	©T*'IHÓ4(Š’S?
… (:yî¹gÞ·�ÎXw6ñ¤g$–‚‹#hñŽ…¿Ñ/ ¦ˆ›•4Ü³qÝ2ª  ÍIDATmrÞpUQŸxíÚ÷N8é—�)i’þÎ¼Åž©‰§�Nö'„àåÈ–Â ,·ÔxºÒÏ¤ªœò´/9“*Ò Ðå$¼íÇ™«>Ë›Âlè`Ý°¢¼7Þ_Þ_Fp�uûÀð"Ë�áEh‰0 €\àýuêZÁyC™é;„å!Öµ�uû–a0‚†ª@¬i‚¤ÔÐ›aèaxñEjèG/'@˜3©*=àxÀLòñu¼¬Ç1Ô�ì’ÂÏ9ó«ëjC˜½ò$t>ÿ ¥†AöîÙUÓðžã�G*•‚ àÓ35M+(Zûžãqço~‹Hx„Äú:1ïäsK~^¥‰>µ>{‚1¥êøÃöADåÜÊFY’¶{#}gzæi2¿6`Š@ç�­úÖ�õ7#š:�Rãä=ª®á™‘és¦·�åsëŽ¿H(=‡õÕ‚uûánš±~&X—¬ÛÂ°`8Œ ‚p¼ù· BKäúüœÇÎ—VŒà6÷åE€R°ž „PXÑÖåƒ.% j€°œièø@=Ñ"ý”†�a˜�SJã ^ËuMÌU_ù9@¿ÀÇ{ƒ¨[õ>¸šç‚÷×€÷�~µvÂ bÝÇÂrsy]pÕ4"Ð¾˜ô¼ú8¥†A¶oÛ–Q‰D"G	$%	^—l:R ¸DÌëèÀ=÷ÜƒXï!_šç/³ý¼J…ßïâÐ\$ÍWÕ)îß1€¾¸š³� ÃŽnxúŸß×çä3ª�©“³tøÊõçmÑÃñ�BÊ>^p¸§oXŽk'.ÿO¨*WÜw ÑµwŸ»¥ãkÖß†ªÀÝ2šG@a7d“=`8oZ°Ý~ðþÚŒ`›û¸!àjœ:¨an'†M€åÁ
n°./¨¡�óÕCŠC““ÀûA˜ÓË½ZQYí`ý¦ÍbçÁmWQUºÀ 0³ûÞÆ€PÓÎí½./ÄºÖ_l˜U±ð[ð·ÌF }19ò’Ioß¶-ãä+�X"žS+°páBìÝ·Û·mCÿŽ¿Ûº•
¿›g0#T¼Gá_wcÿHîo1þÏ|ù½ïLÂ×f‹)S €Y4ô©¶ÕïB>PN	X<@B•Õ”­0}ûŠ@U9åmœ±œ° ôTžÖy œ`šö‚Ô$Ó®€¹Ò‡@½àae]^0o6Ïtû3¯3‚zj4¼CXœ' šV.„aÁºü`¨ËñPcÃ è,–e?GH×õO«æ*ë7mw¾õñÎýoüÀ¥ DÞD`ñ{án›Îí¨3]¥´°sÞ„P.G8qL+>ü-³œ},K`ïž=Ø¹sN?ý}H$9œ@>°~ýzÜóû{	��#;¶`Á) ›wæXÇ>?P:Ñ þ¶g;úr	bÆÐÀ3ôüg¾tâß'÷[ÌÅ”*  ¸µë•·ÓJàâRáABv«aì‰õÃœw‡ûÇòy5«No`=Ás8_x-8_Ü-æ*/z@X L:"0z{(¨®eÌzÖãç«ÃrÝvM÷f” Ãñ`]>pî,w€!ýy,!Ô„,kàDªÊ_ H=á„�SM2ž`-Õ”/txó6Pc3€Z–ã©îJâ_´œ¯| œ7dÞ3j¤c+8on¨­RŸ¿˜ð[°,K	tuÁ³/½ŠSO>	”ÒŒÈ'½^/Þsüñ¸ëîßP92@”¾ý˜yâ9±ý@yáî@¯uÅ¶Ë’tÅß¿râŸ&û»ÌÇ”+ ÀTŸž±&F€3J)FÕñèð hY¿ióOÆÒ5gÅÌ¥ÛÂ.ï'YÑã',=ƒ»iNFØÞ]2¿0Âr`Ñl�á«ëò˜ÖÇgÂ…Œà‚¡HWÀ‚É' º
Â‰émX—º"†BÞ•q	øP8—z"L©aˆ Ndæ*jÐ9/L6QÈðâIÔ0þƒªÒ- ÎEZð½3“Àqë	l ç	B5æøö¬è.ÈíÌ8¿X×V–í·PNø-ø[f£eùzÒ³õYhR#ƒý¸ÿÑ'1á"Ô…PU^¯·@	Ìž=®@yâÑG0xä ¼F+OÚT5áñP/uên/G¾öü—×þ|¢¿?'˜
  n=òò‹å”@“àÅýÛ(5ß‘#»þ:�è<°Ut¬L1‚ûÀôÑ9_êjCx„<"·*gZïÊ‚„°¶Ã‹¶9 „ãÁºý0²,yÂpà¼A€¦âÀ¨K`YbC;á\^PM±,‚•ÔÐ?àó ia˜õ›®8<Ö¶aÅ`úöÛO7?wRCÿ2€• ÄÑÿD"Ô¶€sû!„ÁºrÛt	Ázð�Ñ¤KØYW .øÝÎÓu]5�hYszw¼56MJà‰G�ªiX¶lTU…(Š0#G	œ´nM†èÜù&8–ÇìåkÊ~^9á¹3ŠÙÿãŸ]õ�j~oãÁ´Q €©>3cà;%À³:µÙë5ctŽÿÈ¿î‘óõŒÙ
Šy³Ûá9¸x^‘Ç`¼PÐ	Ã‚ ™Pßèv„1sr¶§-Ftƒjr†`òy.Ã»Ày‚E Ô¶@ð×‚Pš”  €zYç�­_aÎ°„Ô–'ë7^qªO°– Çƒ�3@éGA˜ëº¿õKjè—™Ÿ xgÂÛñø¬&\ |ÚÜ·¢&£×ã†X—›ÃŸë
�œ Sø=Bå½ü�3ß{ÂýÝH¦“…¶oÛ†g_z‹ÌË²`,Ëæ(�sÏ>¯¾ñ:öîÙƒ}oþl%àwq%	?»Ò^ÀLôyáËko¬øÂ&Ó²F÷ÕuWþ!ä:;%�•[¿isÃX&]{ç©*Åú{Öœ9hjiË¼NièIØ¾WOF`hjÁvCNeòË„¼Ôè�í,>5: -ÎÙFºƒ–Œ‚j*9irÑ¨±‘Rõ} é!QP#¯Àœ	‚­ øíÞÌr<uÕ6¶¦bÃL–3£n?XÑÂæ¡¢œ7”+øY¯åö”‚‡gPã+ž;_	>u¶Þõ_™ûÄr<½ôÒ"—\|1Z[[QSSŽã2)Ã‰H§�q¶l1»½ÿãÿ§|ô‹9î€A)ê<ýÅ…ÿÅCüÝfåŸŠ,?'˜–
 (®(¥8ãµ_§Çd�}VZÇçnžË	â¾Ì�`9¿z-Ø¬¦ŽbHªFÁ{©¦BKFl�kÈ)èR¼@ø-hÉ(4›n¼T“¡ÆÃÐ“…¯šb†³,92CŠƒ¦¢PÑLb¥à½¦Ïºý`õàýµéûÁ›.�è1óòPJð­|«Ùaù²¤ŸS¿Ä‡zñÒ/¾‰èîÑq®šF|ò²�ââ�ŸI¶Š‡úûûqÞyçg”Àâ3>‚‹¯ùO¸86“áW¬¦°/î¦¯ðÓX À+ë®¼†!ä¦|%ð“#/â¶ÎW Â<jŒ¹ï`¾ÐÖÜˆ¶¹2¯ËªŽ½qÛ÷–R  §-;š
-6Ã¦×}1E@Œè†ª@—bfß,¥ JI“‹ÐU[®0ùŠì:â6Âò`8$]‘¿Ò[(%ø ÒaÓ@ÁûKYc5ù�âàS÷aû½?ÌQ’3f¶ãü>„‹?t>QWW‡ÆÆÆK`î¢¥¸ôúŸcþ¼yEsûûN¾Àôóùó1­ `¯²‹ƒÆ4Ž*�×ßê‹G÷RUÎt£X¼òÃïqe*‚â2ú£öš†œ„žGþ±é]—“%• PÜÈ¼žCKFaÈ)3¡ÈUØŸê¨*ÃÐÌº+$i7Ô¼_\Æ¬'Î29¶øÊfÖBøl{ôºÝàƒE_·³ªiò—ƒÁÞŽwþv_ŽûÄ{ƒ¸äƒçâ}§�†µk×¢½Õt/þÈ‡ÓCOM«ákßù–¯ÛPx\�âÁ·qp¤ð™îÂL3Ð·yùÅOµ­~;;Y((¸±#Þ‡ÃR Ôƒ1’�‡ž¹GjX{n”Rúk["#MÍ£%©^�CBR*· “åÏ&Ù¬UÎL)v¯„¹3¢„-]Hgr¿~$È!�4É	`Ò†¬ÛÖí7ßgóÃºýf“à6žÒiÌ×Ærà<3¥7Ý©×n?Kðyméðµ2#Í}Bnu~wŽË5‘ðz½xÏ)ïÃŠ÷_LâI	#‡vQjÄPelß¶<ð xðÏØþö[ðx½¸òÊ+‘’u¼òòKÐ¤žùó½èîÄÒeË!zÌ,G3· G"¹ßch�%éŠéê+…ioXH÷¸Ãj(’M2žàìñ”Õ.ºúö]TWZç‚ºA±w0i;ž
0-ª«¶«ÕUh‰(¨Vš«44†’*jX1uª«™QÞ†’²%#+�¥´XÑÂ‰`8Œè)iXû³ÞPŽÒsŸÏ7i«¾…/�PžùêÅÞ§îÇÝƒDa4™÷qüÒÅèêîÆ‘Ã£=9]5�øäµÿŠ¥›>ˆÞ,håE€ažè—>ý…Õ�OÚŽG� 2G~K™C)ÅEoÞ�© äû ½v¬Ç]üõ{×ÉÈs™›ÂrX´leŽ+�Pt´ç\¢ ª¤�’Š¹–ŒÂ�âpÓìOæpùI5Ù º
CÓ@59£J¹ Ù¥¹¥Ìz»÷–sJÁçóÁç&ÔßÏ†‹cÐè –P6:¥Úý*^zìAt¾ñœ­2°½–YÇ¡õ_Dý’ÌxôIïæSU
 H·ëþYû@ï[¸qÿß€jXy„ ÛëÇ’eËsLT;>ÀÃ�æ›'ñ’JÀ©5`A—S%]ˆjÀIˆÎ$ýÜ¯ö™{éáñŽyxfÂ- »U¿DŽ@îÂ��Ûpø­W1ØÝ‰ÃûÞ�4Ü[4ìê›uZÎüVo¸ØLdï‰ÀQ§  3cíÔÀÝnUË
X¿i³8¸bãÖlW ?* ä*Žãàwå®„²,#/½ÒWb f
-ÕTèR†’§ÙŸsì"ñ{Â‰ãzÀ|ÁåÇævÏå:aV€“Uß~‘E£_ _„“§4<¿ë0ö’}ºªüµV—>üÌ�„'ä¢&G¥°ðêº+ÿãÏý;¯³¬ Â	Ç�§Ùf~n  ,X¸¡ºúœýºFˆ«(~N”€Sk€p¢m�j*¨&C—S²RÅ@8³JÑúk0èxQLð³Qm%À ÞËÃïpDW6šýBîâïH¨øëÎ~„S6n•®MÛ¿Õ
 0ÉÁ5[~ú€ü†ñ¾5Þ{‹¯úõçCÏao—.=žÀhs‹ƒ[· nþ
#¦1EŸpM7�ÅÒ†óQNS E�—¥ò�i%™¿›Çäª4$0}|–ãK
~6ªå
„\j=Ø
›Íº­�â«> ¼Õ—À“ïl§”FYª_9™<'G½ Òg«ØC=Ÿ°HA£2/Üþm�zœö±kÐW‘J§Þ—ã,P]5}þ<×€qùÊ¾w<¯p»D°_0°Ó	ÆkxM>¾bÁÊ¯ú’ªã©}aÛD0B�í^V¿üh"ûŠá]¡ ª�õ›6‹ƒ+7>F55“e¨w£ÿ±_Aî¥þÕ$ª�aŽ”€— ºœÌTV²ú�cQ „åáu‹­öÅ0+À+°¨óðûù@y_ º"2þº³ß6\W¤;ý�Ýö™é4âm<8¦ Š`Ãõ÷‡ú¢á—%¹pèå‡††^yø/ 0çÔ7ŸsÕÿdö3ƒ	C©ÒJ@Ó(RÒ‘5`�°|Ú2Hë�N€µÒWCèót9ËG�às,ƒf¿ ŸPüÜUƒâ¥ýƒx³§0òòn1ùîËTŸÀtÅ37^îøÜÍgK�ÛÏyëù{ :�ÛùãNCRÑáÒD�~"¯¡;oÄS68–÷ÿÛ;ûØªÎ:ŽŸç9çžû~o_i+XÖÂºN ¸¦BjL†fâÌÔÄlþ�C—8ÙœgÒD3’EˆD·l¨™Fb”2§t&3å5aH#8y]K¡o—{{_ÎÛóøÇí)íí¹¯½·´ô|’þçÐÒÛþ>Ïï÷{~Ï¹¾t�Oªy{ÀØ¤¡$�wê­�#nè�Þ£’«bŸIB3r–Ó	| ¨ñÉ¨óåÎ¤zo©xû¿ƒ¶�>"xOÈÍ6üëÉÕsj‹¯œ ªV®?ÚøÙo>èó°¼½m\	ÍD_4�çYó•…œ †~{`Lã×r‚°t°QI†wLJ f$Ø³‘Y
Hð+¥5÷,
I÷Sº‰“W†mW} s¾ËŸG Ò±î1¥·©%e=EØ%Ix`Åýðz&Oèé&G_T³­íÈ&‚BÏÐO—*ÑoÕX1Bn·Dv3x]¬äÀ÷¸ø$¸åÜ¥Åù›	t_²ýYÝM�¾\8(êUßûí�(¥ã']’„em-‡'¿µç‘”9åð¹ÈÁ|€µPÊôÞD‰ Î¯ä¬ó�ô¾þ‘‹CüjD�r£"J¸¹ÛûæË�wK£/Ž Š uó®Ù<1Q Ð¾´�õuSî/¦$°PU¦¡C3sPóN
 äfð¹¼òí8(Å¯ü…~¾tŸrØC´ïßí«þDIëæ]-²ÇˆJRÛÄ¿_ØÔ€%Í‹@3fƒJÉBnÝˆ§TŒêÈz
±Ì¤ ¬•>3è'Â
žæóŒ5ó¾ÎÎ\�ãôµû'<Ý¥þBpPk;÷…oÄ"oP&Mz‘ÏÀò{ï™Ò 
ïØÇ$4šnTD•€W¦ðH~E*x¿_f>9{P†oþHOò»4œýu7�í�ÑÁæâ9pP"ëS?¾~;¥ô©ÌkíK[° ¶fJ6 ¤Ë‚�¸žõ2ß`Œn
$tUUn4æ¢œ�©€ÌXÑoGf) 1Š�›!ì‘rvõ-ÎßLàäÕûù}ÌÏtßG Ó¤mËž�„ÒßdöªX|�}6À9GLãˆ$�)A\èPŒ…n
è¦	M7 ¼h)”" +ÐeFà–(%�))ë_«(é>A®±Ýñ×‚\HàÔµHÖÀ'‚÷<ò3så�•Æ@ÈÖ €ÖÅÍXÔXo›dŠ œ'ä,1èœŒÏ
hÆd9h‚¢Ú+AfS¥#3iì·Cb•	òlÈŒ¢ÚÃpí½XÝ±&ïŠŸÒMôôÇq¦÷VVÁ{ˆà?Ÿ�u~.”‰\%�Ï@[sã”íÂ‰$’Ihj
	:3Ûù&äf
™Q„ÜBn6ð'ïÇéãÝønç‹¶õ~$i §wïhY{#NàçÆ@™ißº·C¨‰Wì²�\eA×îN|aÓ³ ž bª�HÊDÊ˜~�Ÿ�;) �ÌThº_`³ÊóD?Øð€Xºjybû„=t.peDÅÙ¾ˆí>¾…ø…á äÊ€©":õìÝö=±õà…I?Õ0SÓ•’ÁL
Àêî—Djæýú‡�ãüÑ.´Ü·ŸÚú*.Ç�³ÏÁ9ìSè‹N�_Ž *Hëæ]-²?¼�<bw½¡* _¨ÿüñ— ÏüñxÖÏe˜1Õ@ÊUe¡R`pI
#EüDâš‰¿¼þN½ö“ÿ&ís…ë·,ùÖKA¥nÑ¤û„Q®«ûBn¶c¾wõ‹ÅÀÐ¾uo‡ÐÏgÎ À‡Ý�è§ú›?¶áÉ_í/ø0Žj˜Hh&R†@Êà%gå€Ì(Ü#ž±!ŸbƒÝ"®™¸8Åå�(†ãôèÎ¾ðè¿!øêUóDô¹ûŸýýÓîÆ% ‚÷¨£‘ßÕpí•ùº�?]Ì m[öl$À6«?9w}‡v�z‚où›Z‡Ú¾Ñ‰†Új,j¬G•·ð·Æ¶P�´t“§w¸€É“gÍr	ÀjøSJ!Q2~W‘\Œ–´ªÛÑÓ0��}&Wþôü±‘Ó]«­?Éµhí/»ïsÒüéãàÐ¶eÏFBðÔ…�Oüˆëj7 Ô¬zh°ñó›Æg	˜âÁ’ú ÔÖ”$;3�%˜"mƒÄðø½^„«Òo*MØâ+G`gc$©ãÃáQÜ¸•Â`,5O=“¸úÎù�¯-ðÓ;�#€YÂÂ/=ýNxÙšOÛ]óHµÕ¨«¡.è+Û™ý÷ßzJ 
ŸøÌ+ö}é\`(®c /8à-L]û»¼«®¶fï\{Þþ\Áy"Ð,Á·xÅKä£¢9óZÒ¸Ô?„KýCé{ƒ!,)üú¼ð¹J;9øþ¹s P6Ä5‘”�áX·b£IqÛ”>\ð˜0ŒnÅëÿƒ/6xÀ©ë+�“Ì2Ú·îízêæ=l';<AUÐÅ¥ äSàRÜðz<ðÉ4g¶ð‹¯}LVð³?Éû5t. 1Õ„j
Dã	hj
#) ©iˆ«zÁ+ûD˜ËÝ#8?”ê;Xsâo'çÃüÙ„#€YL)2ÈÄ#hÌ�¾ÛY‚âR�ìEWçWo Àºmo,hjjÄ(—93’4ÅÓ‰aRÓ�4	¸¡•ÜvXïûàDC0ü¶³ÊßYÌZ7ïjq¹½Ÿ’k=óV•*‹¡ãÐßõÛM ÐôÐw^®[ýpÙÿÏÌåî1tí]SMô˜ÉÑcÎ
?ûp0GiÝ¼«EòøWJ×È¡ú6®«íÅH¡÷ÀÎñ­µª•ë�6?úÜƒ…þÛ‰pÁc²â½lèÚ»ŒI×)ÁY¯$Îðý¯œw‚}öãà.bmç¾°¨ªi¾qå­r¸¾Åˆ.¡‘ƒµ~®«íÖ}¢ùì¶¯¬¦Þ „ÉË—ÿôÍnëº™Œ»ÃuQ ÐâÑ^êrßdLº®%¢ƒn_ð†ß«ôs-u“Œ]qRø¹ÍÿÒ‡+¦Å1È®    IEND®B`‚               h          ¨   00     ¨%          ›     X4   V S _ V E R S I O N _ I N F O     ½ïþ                  ?                        ¸   S t r i n g F i l e I n f o   ”   0 8 0 9 0 4 b 0   ,   C o m p a n y N a m e     a m p h p   Ô V  F i l e D e s c r i p t i o n     E x e c u t e s   a   c o m m a n d   a n d   p a s s e s   t h e   s t d i o   s t r e a m s   o f   t h e   c r e a t e d   p r o c e s s   t o   T C P   s o c k e t s   0   F i l e V e r s i o n     1 . 0 . 0 . 0   :   I n t e r n a l N a m e   P r o c e s s W . e x e     V   L e g a l C o p y r i g h t   C o p y r i g h t   ( C )   a m p h p   2 0 1 7     B   O r i g i n a l F i l e n a m e   P r o c e s s W . e x e     @   P r o d u c t N a m e     P r o c e s s   W r a p p e r   4   P r o d u c t V e r s i o n   0 . 0 . 0 . 0   D    V a r F i l e I n f o     $    T r a n s l a t i o n     	°<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
                                                                                                                                                                                                                                                                                                                                                            @     ø¢ ££(£0£`£h£   P      ¥¨¥°¥¸¥À¥È¥Ð¥Ø¨ð¨ø¨ p     @ P X h p € ˆ ˜                                                                                                                                                                                                                                                                                                                                                                                                                                                     MZ�       ÿÿ  ¸       @                                   ø   º ´	Í!¸LÍ!This program cannot be run in DOS mode.
$       ‹ìä Ï�ŠóÏ�ŠóÏ�ŠóÆõóÃ�ŠóôÓ‹òÍ�ŠóôÓ‰òÍ�ŠóôÓ�òÝ�ŠóôÓŽòÂ�ŠórAóÊ�ŠóÏ�‹ó”�ŠóeÓ‚òÌ�ŠóeÓuóÎ�ŠóÏ�óÎ�ŠóeÓˆòÎ�ŠóRichÏ�Šó        PE  L h%s\        à   (        1-      @    @                      €         @�                           TY  È    �  ¨Ü                   p @  PU  p                           ÀU  @            @  p                          .text   ô&      (                    `.rdata  ê!   @   "   ,              @  @.data   ˜   p      N              @  À.gfids       €      P              @  @.rsrc   ¨Ü   �   Þ   R              @  @.reloc  @   p     0             @  B                                                                                                                                                                                                                                                                                                U‹ìƒì8¡p@ 3Å‰EüVW�EøÇEø   ‹ñPh~f€ÿvÿ¬@@ …Àt"Pÿ6hC@ è‚  ƒÄ3À_^‹Mü3Íè¤  ‹å]Ãƒ=Äs@  t8¸   ¿   f‰EÌ¡Às@  ·¼s@ PEÔÇEÐ    ÿ°@@ f‰EÎ�EÌë-¸   ¿   f‰Eè¡Às@ ‹ ‰Eì·¼s@ Pÿ°@@ f‰Eê�Eèj j j j WPÿvÿ´@@ ƒøÿt!ÿ6h˜C@ èÛ  ƒÄ3À_^‹Mü3Íèý  ‹å]Ãÿ¤@@ =3'  t"ÿ6hôC@ Pè,  ƒÄ3À_^‹Mü3ÍèÎ  ‹å]Ã‹Mü¸   _3Í^è¹  ‹å]ÃÌÌU‹ìƒì¡p@ 3Å‰Eü‹ES‹]V‹uWj j j ‰Eð‹ú�Eø‰}ìPSVQÇEô    ÿœ@@ ƒøÿu+Wÿuðh0D@ ÿ¤@@ Pè¨  ƒÄ3À_^[‹Mü3ÍèI  ‹å]Ã3À…Û„�   ƒû‚†   ‹Ó�NWíƒâø(å�fnQ�I@fnAÀƒÀfnI¸fnY°fbØfnAàfbÊfnQèfbÙfnIØfþëfnYÐfbØfbÊfbÙfþã;Âr®fþå(ÄfsØfþà(ÄfsØfþàf~á‰Môë3É3Ò3ÿ;Ãs,‹Ë+Èƒùr�Kÿ Æ|ÆƒÀ;Árò‹Mô;ÃsÆ�È‹Eø;Át(QPÿuìÿuðhpD@ è*  ƒÄ3À_^[‹Mü3ÍèK  ‹å]Ã‹Mü¸   _^3Í[è5  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì$¡p@ 3Å‰EüSVW�EàÇEà    ‹ÙPh~f€ÿsÿ¬@@ …Àt#Pÿ3hàD@ è±  ƒÄ3À_^[‹Mü3ÍèÒ  ‹å]Ã‹;‹5Ès@ ¯þÆEô=Ôs@ ÿ0@@ ‹‹ÈÁéˆMõ‹ÈÁéˆMö‹ÈˆEøŠˆEù�EôÁéhTE@ ‰Eè�EäˆM÷‹KjPÇEä   ‰uì‰}ðè¸ýÿÿƒÄ…Àtƒ‹Mü¸   _^ÇC   3Í[èK  ‹å]ÃÌÌÌÌU‹ìƒì$¡p@ 3Å‰Eü¡Ès@ SVƒÀÇEô    WP‹ù‰EèÿÔ@@ ƒÄ‰Eì�Eôj j P�EðPj�EèPÿwÿÀ@@ ƒøÿu5ÿ7hhE@ ÿ¤@@ Pè)  ƒÄÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè¾  ‹å]Ã‹Eðƒøs/ÿuèPÿ7hÈE@ èo  ÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè‡  ‹å]Ã‹]ìŠ€ùt¾ÁPÿ7hhF@ è6  ë‹ŠK„ÉtF€ù}¶Á‹…S@ ë¸(G@ P¾ÁPÿ7hHG@ è  ÿuìÿØ@@ ƒÄ3À_^[‹Mü3Íè  ‹å]Ã�MøfÇEø‰Mä‹MèÇEà   ÇEÜ    ;ÁtQPÿ7hÈE@ è¸  ‹]ìƒÄé†   ‹�S‹5Ès@ ¯ÎÜs@ ƒîr@ ‹;uƒÂƒÁƒîsïƒþütAŠ:u'ƒþýt6ŠB:Auƒþþt)ŠB:AuƒþÿtŠB:Atÿ7hÐG@ èA  ‹]ìƒÄëÆEù ÇG   ÇEÜ   SÿØ@@ ‹�Eà‹OƒÄh<H@ jPèˆûÿÿ‹MüƒÄ÷ØÀ3Í#EÜ_^[è$  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌ3À‹�ƒz|	@ƒø|ñ3ÀÃ¸   ÃÌÌÌÌÌÌU‹ìQƒ=Äs@  ¸   S‹Ù¹   VEÁ3öW‰EüjÿÔ@@ ƒÄ‹øjjÿuü‰7ÇG    ÿÄ@@ ‰Gƒøÿt‰<³Fƒþ|Ì¸   _^[‹å]Ãÿ7hìH@ èR  ƒÄ3À_^[‹å]ÃÌÌÌÌÌÌU‹ìƒäø�ì,  ¡p@ 3Ä‰„$(  S‹]VW‰\$3ö‹³èRùÿÿ…À„  Fƒþ|ê‹Ëèÿÿÿ…À„¯  D  3Ò3ö3ÿ‰T$3À‰´$   ‰¼$(  ‰D$f�‹ƒ‹C…Àux3É…öt‹C9„Œ$  tA;Îrò;Îuƒþ@s‹C‰„Œ$  ‹´$   F‰´$   3É…ÿt‹C@ 9„Œ,  tA;Ïrò;ÏuRƒÿ@sM‹C‰„Œ,  ‹¼$(  G‰¼$(  ë2ƒøu-3À…Òt‹K9L„t@;Ârõ;Âuƒú@s‹K‰L„‹T$B‰T$‹D$‹\$@‰D$ƒøŒ6ÿÿÿj �„$,  P�„$(  P�D$$Pj ÿ @@ ‹ðƒþÿ„'  …ö„  3ÿ…ö~uƒÿ}p�D$P‹»ÿpÿ¸@@ …Àt‹»èœûÿÿ…À„³   NëC�„$   P‹»ÿpÿ¸@@ …Àt‹»è‘úÿÿ…À„ˆ   Në�„$(  P‹»ÿpÿ¸@@ …Àu1G…ö‹‹\$‹Ëènýÿÿ…À…Vþÿÿ3À_^[‹Œ$(  3Ìèf  ‹å]Â ‹4»�D$P�D$ÇD$   Ph  hÿÿ  ÿvÿ¼@@ ÿ6ƒøÿu'hXH@ èô  ƒÄ‹Œ$4  ƒÈÿ_^[3Ìè  ‹å]Â h°H@ ÿt$èI  ƒÄëÓhXI@ èº  ƒÄëÄh$I@ ÿ¤@@ Pè$  ë®ÌÌSVW‹ù3ö�G(Ç    ÇG0   ÇG,    f�j P�÷�CPSÿ@@ …Àt_…öu‹Gë‹j jPÿ@@ …Àt1F�G(ƒþ|ÈÇG4D   ‹‰Gl‹G‰Gp‹G�O`   ‰Gt¸   _^[ÃVhJ@ è  ƒÄ3À_^[ÃVh°I@ è  ƒÄ3À_^[ÃÌÌÌÌÌÌÌÌQVW‹ù�GP�G4Pÿ5Ìs@ �W(j h   jRRÿ5às@ j ÿ4@@ …Àuh�J@ ÿ$@@ Pè,  ƒÄ3À_^YÃÿw‹5(@@ ÿÖÿ7ÿÖÿwÿÖÿwÿÖ_¸   ^YÃÌU‹ìƒäøƒì¡p@ 3Ä‰D$SV‹uƒËÿWh   ÿÔ@@ ‹= @@ �L$ƒÄ‰D$ÇD$   j Qh   Pÿvÿ×…ÀtB‹D$…Àt[‹‹Nh(K@ ‰D$�D$jPè‹öÿÿƒÄ…Àt<j �D$Ph   ÿt$ ÿvÿ×…Àu¾‹=$@@ ÿ×ƒømtÿ6hÐJ@ ÿ×PèO  ƒÄë3Ûÿvÿ(@@ ÿvÿ˜@@ ‹L$‹Ã_^[3ÌèÙ  ‹å]Â U‹ìƒäøƒì¡p@ 3Ä‰D$SV‹uWh   ÇD$     ÇD$ÿÿÿÿÿÔ@@ ‹À@@ ƒÄ‰D$�D$ÇD$   j j P�D$$Pj�D$$PÿvÿÓƒøÿtS‹=@@ �‹D$…À„“   j �L$$QPÿt$ ÿvÿ×…Àtu‹D$ ‹L$;ÁuVj j �D$$P�D$$Pj�D$$PÿvÿÓƒøÿu´ÿ6h4K@ ÿ$@@ PèQ  ƒÄÿvÿ(@@ ‹L$$‹D$_^[3Ìèæ  ‹å]Â QPÿ6hØK@ èŸ  ƒÄëÌÿ6hxK@ ë´ÇD$    ë¹ÌÌÌÌÌÌÌU‹ì¸  ès  ¡p@ 3Å‰Eü¡Ès@ SVW�4@jöö�<@ÿ@@ ‹Ø�…ôÿþÿj PV�…øÿþÿPSÿ @@ …Àu'h`L@ ÿ$@@ Pè¢  ƒÄ3À_^[‹Mü3ÍèC  ‹å]Ã‹…ôÿþÿ;Æt"VPh¨L@ èö  ƒÄ3À_^[‹Mü3Íè  ‹å]Ã‹5Ô@@ W‰=Ðs@ ÿÖƒÄ£Ôs@ ��øÿþÿWQPèé  ƒÄ‰=Øs@ WÿÖƒÄ£Üs@ ��øÿþÿÏWQPèÅ  ‹5 @@ �…ôÿþÿƒÄj Pj�…øÿþÿPSÿÖ…Àu
h0M@ é=ÿÿÿ‹…ôÿþÿƒøtPh˜M@ èU  é.ÿÿÿŠ…øÿþÿ„Àt¾ÀPh@N@ è8  éÿÿÿj �…ôÿþÿPh   �…øÿþÿPSÿÖ…Àu
hÐN@ éßþÿÿ‹…ôÿþÿ=   u hO@ èö
  ƒÄ3À_^[‹Mü3Íè  ‹å]Ã€¼÷ÿþÿ t h€O@ èÌ
  ƒÄ3À_^[‹Mü3Íèí  ‹å]Ã‹=@@ �…øÿþÿj j jÿPj héý  ÿ×‹ð…öu høO@ èŠ
  ƒÄ3À_^[‹Mü3Íè«  ‹å]Ã3Éº   ÷â�Á÷ÙÈQÿÔ@@ ƒÄ£às@ VPjÿ�…øÿþÿPj héý  ÿ×…Àu hhP@ è3
  ƒÄ3À_^[‹Mü3ÍèT  ‹å]Ã‹Mü¸   _^3Í[è>  ‹å]ÃÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüˆUô�Eô‹U‰Eð‹ÂÁèÇEõ    ˆEõ‹ÂÁèˆEö‹ÂV‹uÁèVˆE÷�EìˆUø‹‹IjPÇEì   è&òÿÿ‹MüƒÄ3Í^èË  ‹å]ÃÌÌÌÌU‹ìƒì¡p@ 3Å‰EüSVW3ÿ‹Ù3ö€    �EìPÿ4³ÿ @@ …À„�   ‹Eì=  u
‹³‰D½ðGë…Àu~Fƒþ|Í…ÿtIjÿj�EðPWÿ@@ ƒøÿuhHQ@ ÿ$@@ Pè”	  ƒÄ‹= @@ 3ö�EìPÿ4³ÿ×…Àt"ƒ}ì u1Fƒþ|ç¸   _^[‹Mü3Íè  ‹å]ÃVhðP@ ÿ$@@ PèH	  ƒÄ‹Mü3À_^3Í[èé
  ‹å]ÃÌÌU‹ìƒäø�ìÀ   ¡p@ 3Ä‰„$¼   ƒ=äs@  V‹uWujjÿè@@ ƒÄ£äs@ …ÀtPÿL@@ h t@ h  ÿ¨@@ …ÀtPh”Q@ èL  ƒÄ‹UVè@  ƒÄ…Àtxè´ûÿÿ…Àto�Œ$¬   èdõÿÿ…Àt_‹=,@@ �„$¬   j j Ph€@ j j ÿ×jx‹ð�D$4j PèG  ƒÄ�L$0èGøÿÿ…Àt"jÿVÿ@@ ƒøÿu0hÀQ@ ÿ$@@ PèD  ƒÄèÌ  ƒÈÿ_^‹Œ$¼   3ÌèÜ	  ‹å]Ã�„$¨   PVÿ @@ …Àu0hR@ ÿ$@@ Pè  ƒÄè‰  ƒÈÿ_^‹Œ$¼   3Ìè™	  ‹å]Ãƒ¼$¨    u—�L$0è_øÿÿ…ÀtŠ‹Œ$¬   º   hhR@ ÿt$Tè1ýÿÿƒÄ…À„eÿÿÿ‹„$¬   j ÇD$    j ‹@‰D$‹D$<‰D$�D$Ph @ j j ÿ×‰„$¸   ‹„$°   j ÇD$   j ‹@‰D$(‹D$@‰D$$�D$ Ph@@ j j ÿ×‰„$¼   ‹„$´   j ÇD$(   j ‹@‰D$4‹D$H‰D$0�D$,Ph@@ j j ÿ×jÿÿt$L‰„$È   ÿ@@ ƒøÿu0hpR@ ÿ$@@ PèÙ  ƒÄèa  ƒÈÿ_^‹Œ$¼   3Ìèq  ‹å]Ã�„$¨   Pÿt$Lÿ8@@ …Àu0hÀR@ ÿ$@@ Pè“  ƒÄè  ƒÈÿ_^‹Œ$¼   3Ìè+  ‹å]Ã‹Œ$¬   º   hS@ ÿ´$¬   è×ûÿÿƒÄ…À„þÿÿ�Œ$¸   è0üÿÿ…À„÷ýÿÿ‹„$¬   ÿpÿ˜@@ ‹Œ$Ä   ‹„$¨   _^3ÌèÄ  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌSVW‹Ù3ÿ¾p@ @ ‹‹Óf‹
f;uf…Étf‹Jf;HuƒÂƒÀf…ÉuÞ3ÀëÀƒÈ…ÀtƒÆG�þHp@ |Á_^3À[Ã�_^�…p@ [ÃÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìQVWjÿÔ@@ ƒÄ‹ðVÿujÿ”@@ ƒè t:ƒèthtS@ èÝ  ƒÄVÿØ@@ ƒÄ3À_^Y]Ã‹E‰pÇ@    ¸   _^Y]Ã‹=Ø@@ Vÿ×ƒÄjÿÔ@@ ƒÄ‹ðVÿujÿ”@@ ƒè t#ƒèthtS@ ë‹E‰pÇ@   ¸   _^Y]Ãh°S@ è[  ƒÄVÿ×ƒÄ3À_^Y]ÃÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüS‹]V‹uWÇEø    ÿ<A@ j
Ç     �EøPVÿÌ@@ ƒÄ‹ø9uøt/ÿ<A@ ƒ8 u$‰;…ÿ~�ÿ   }_^¸   [‹Mü3Íè  ‹å]Ãÿ3hàS@ èÂ  ‹MüƒÄ3Í3À_^[èã  ‹å]ÃÌÌÌÌÌÌÌÌÌÌÌÌU‹ìƒì¡p@ 3Å‰EüS‹]V‹uWÇEø    ÿ<A@ j
Ç     �EøPVÿÌ@@ ƒÄ‹ø9uøtÿ<A@ ƒ8 u‰{…ÿÿshT@ è>  ƒÄ‹Mü¸   _^3Í[è\  ‹å]ÃÌÌÌÌÌU‹ì‹E‹M‰H¸   ]ÃÌÌÌÌÌÌÌÌÌÌÌÌÌU‹ìVW‹ú·ƒø-uf9Gufƒ u	¸   _^]Ãƒ} t‹E‹0‹ÎèIýÿÿWVh¼s@ ‹@ÿÐƒÄ_^]Ãƒø-…£   f9G…™   ‹u�Gh@T@ P‰ÿˆ@@ ‹6‹øƒÄ‹Î…ÿu<èýüÿÿ…ÀuVhDT@ èn  ƒÄ3À_^]Ã‹@…Àu	¸   _^]ÃVh¼s@ ÿÐƒÄ_^]Ã3Àf‰è¼üÿÿ…Àt¿‹H…ÉuVhlT@ è&  ƒÄ3À_^]Ã�GPVh¼s@ ÿÑƒÄ_^]Ã_¸   ^]ÃÌU‹ìƒìS3ÛÇÄs@ ÿÿÿÿVW‹ú‰]ü�s‰¼s@ ‰Às@ ‰Ès@ ‰Ìs@ ;þ~=€    �EüSP‹E‹°è°þÿÿƒÄƒøwÿ$…˜'@ »   ë3ÛF;÷|Óƒ=Äs@ ÿuhU@ h8S@ h¼s@ èfüÿÿƒÄƒ=Ès@  uh¤T@ è`  ƒÄ3À_^[‹å]Ãƒ=¼s@  uhÜT@ èA  ƒÄ3À_^[‹å]Ã_^¸   [‹å]Ã�c'@ -'@ -'@ '@ &'@ ÌÌÌÌ¸�u@ ÃÌÌÌÌÌÌÌÌÌÌU‹ìƒäø‹E�MQj ÿuPèØÿÿÿÿpÿ0ÿXA@ ƒÄ‹å]ÃÌÌÌÌÌÌU‹ìƒäøƒìSV‹Ú‰L$W‰\$è¥ÿÿÿÿu‹øj Sj ‹j ÿwƒÉQÿTA@ ƒÉÿƒÄ…ÀHÁ;Áu	‹Á_^[‹å]Ã�X3É‹Ãº   ÷â�Á÷ÙÈQÿÔ@@ ‹ðƒÄ…öuƒÏÿ‹Ç_^[‹å]Ãÿuj ÿt$SVÿwÿ7ÿ`A@ ƒÄ¿ÿÿÿÿ…ÀHÇ;ÇuVÿØ@@ ƒÄ‹Ç_^[‹å]Ã‹L$_‰1^[‹å]ÃÌÌÌÌÌÌÌÌÌÌU‹ìƒìƒ=äs@  Vu3À^‹å]Ãjjÿè@@ ‹ðƒÄ…ötæ‹U�EP�Müè÷þÿÿ‹UüƒÄH�B·ƒø tƒø	t
ƒøtƒø
u
3Àf‰ƒéëßVÿ5äs@ ‰VÿH@@ ¸   ^‹å]ÃÌÌU‹ìƒì¡p@ 3Å‰EüV‹u�Eøj j Ph   Vj h   ÇEø    ÿ<@@ ‹U…Òu ÿuøVh$U@ è5ÿÿÿƒÄ^‹Mü3ÍèZ  ‹å]Ã�EP�MôèGþÿÿƒÄÿuøVÿuôh4U@ èÿÿÿ‹MüƒÄ3Í^è(  ‹å]ÃÌU‹ìQSVWh€   ÇEü€   ÿÔ@@ ƒÄ‹Ø‹=D@@ ¡äs@ …À„á   PÿP@@ …À„©   ‹pPÿÜ@@ ƒÄ…ö„”   j j ÿuüSjÿVj héý  ÿ×…Àu]ÿ$@@ ƒøzu¬j j j j jÿVj héý  ÿ×‹ø…ÿtŒWSÿà@@ ƒÄ…À„yÿÿÿj j WPjÿVj ‰}ü‹Ø‹=D@@ héý  ÿ×…À„ZÿÿÿShLU@ jÿ\A@ ƒÄPèýÿÿƒÄé;ÿÿÿ¡äs@ …Àt Pÿ@@@ ÿ5äs@ ÿÜ@@ ƒÄÇäs@     SÿØ@@ ƒÄ_^[‹å]Ã;p@ òuòÃòé_  Vjè  èX  PèE  èp  ‹ðè?  j‰èä  ƒÄ^„ÀtlÛâèL  h²3@ èl  è  Pèâ
  YY…ÀuJè  èc  …Àthb1@ è¾
  Yè+  è&  è   èß  Pè÷
  Yèì  „Àtè 
  èÅ  3ÀÃjè4  Ìèù  3ÀÃè…  è¨  PèÆ
  YÃjhY@ è"  jè  Y„Àujèú  2Ûˆ]çƒeü è³  ˆEÜ¡|s@ 3ÉA;ÁtÜ…ÀuI‰|s@ hŒA@ h€A@ è3
  YY…ÀtÇEüþÿÿÿ¸ÿ   éý   h|A@ htA@ è
  YYÇ|s@    ëŠÙˆ]çÿuÜèÙ  Yèq  ‹ð3ÿ9>tVè;  Y„ÀtWjW‹6‹Îè_  ÿÖèP  ‹ð9>tVè  Y„Àtÿ6èÝ	  YèÅ	  ‹øè¸	  ‹ðè�	  Pÿ7ÿ6èUóÿÿƒÄ‹ðè1  „ÀuVè�	  „Ûuè–	  j jèm  YYÇEüþÿÿÿ‹Æë=‹Mì‹‹ ‰EàQPè!	  YYÃ‹eèèì  „Àuÿuàè@	  €}ç uèS	  ÇEüþÿÿÿ‹Eàè  Ãè�  é‡þÿÿU‹ìj ÿt@@ ÿuÿx@@ h	 Àÿp@@ Pÿl@@ ]ÃU‹ì�ì$  jè=	  …ÀtjYÍ)£`q@ ‰\q@ ‰Xq@ ‰Tq@ ‰5Pq@ ‰=Lq@ fŒxq@ fŒlq@ fŒHq@ fŒDq@ fŒ%@q@ fŒ-<q@ œ�pq@ ‹E £dq@ ‹E£hq@ �E£tq@ ‹…ÜüÿÿÇ°p@   ¡hq@ £lp@ Ç`p@ 	 ÀÇdp@    Çpp@    jXkÀ Ç€tp@    jXkÀ ‹p@ ‰LøjXÁà ‹ p@ ‰Løh A@ èáþÿÿ‹å]ÃU‹ì‹EV‹H<È·A�QÐ·Akð(ò;Öt‹M;Jr
‹BB;ÈrƒÂ(;Öuê3À^]Ã‹Âëùèa  …Àu2ÀÃd¡   V¾€s@ ‹Pë;Ðt3À‹Êð±…Àuð2À^Ã°^ÃU‹ìƒ} uÆœs@ è‚  èŠ  „Àu2À]Ãè}  „Àu
j èr  Yëé°]ÃU‹ìƒìV‹u…ötƒþu|èà  …Àt*…öu&h„s@ èX  Y…Àt2ÀëWh�s@ èE  ÷ØYÀþÀëD¡p@ �uôWƒà¿„s@ j Y+ÈƒÈÿÓÈ3p@ ‰Eô‰Eø‰Eü¥¥¥¿�s@ ‰Eô‰Eø�uô‰Eü°¥¥¥_^‹å]Ãjè5  Ìjh8Y@ è=  ƒeü ¸MZ  f9  @ u]¡< @ �¸  @ PE  uL¹  f9ˆ @ u>‹E¹  @ +ÁPQèiþÿÿYY…Àt'ƒx$ |!ÇEüþÿÿÿ°ë‹Eì‹ 3É�8  À”Á‹ÁÃ‹eèÇEüþÿÿÿ2Àè  ÃU‹ìèÏ  …Àt€} u	3À¹€s@ ‡]ÃU‹ì€=œs@  t€} uÿuè  ÿuè  YY°]ÃU‹ì¡p@ ‹È3„s@ ƒáÿuÓÈƒøÿuè  ëh„s@ èô  Y÷ØYÀ÷Ð#E]ÃU‹ìÿuèºÿÿÿ÷ØYÀ÷ØH]ÃU‹ìƒìƒeô ƒeø ¡p@ VW¿Næ@»¾  ÿÿ;Çt…Æt	÷Ð£ p@ ëf�EôPÿ\@@ ‹Eø3Eô‰Eüÿ`@@ 1Eüÿ0@@ 1Eü�EìPÿd@@ ‹Mð�Eü3Mì3Mü3È;Ïu¹Oæ@»ë…Îu‹ÁG  ÁàÈ‰p@ ÷Ñ‰ p@ _^‹å]Ã3ÀÃ3À@Ã¸ @  Ãh s@ ÿL@@ Ã°Ãh   h   j è  ƒÄ…ÀuÃjè=   ÌÃ¸¨s@ Ãèöÿÿ‹Hƒ‰Hèçÿÿÿ‹Hƒ‰HÃ3À9p@ ”ÀÃ¸ìs@ Ã¸ès@ ÃU‹ì�ì$  SVjèÃ  …Àt‹MÍ)3ö�…ÜüÿÿhÌ  VP‰5°s@ è  ƒÄ‰…Œýÿÿ‰�ˆýÿÿ‰•„ýÿÿ‰�€ýÿÿ‰µ|ýÿÿ‰½xýÿÿfŒ•¤ýÿÿfŒ�˜ýÿÿfŒ�týÿÿfŒ…pýÿÿfŒ¥lýÿÿfŒ­hýÿÿœ�…œýÿÿ‹E‰…”ýÿÿ�E‰… ýÿÿÇ…Üüÿÿ  ‹@üjP‰…�ýÿÿ�E¨VPè{  ‹EƒÄÇE¨  @ÇE¬   ‰E´ÿX@@ V�Xÿ÷Û�E¨‰Eø�…ÜüÿÿÛ‰EüþÃÿt@@ �EøPÿx@@ …Àu¶Ã÷ØÀ!°s@ ^[‹å]Ãj ÿT@@ ‹È…Éu2ÀÃ¸MZ  f9uó‹A<Á�8PE  uæ¹  f9HuÛƒxtvÕƒ¸è    •ÀÃhF3@ ÿt@@ ÃU‹ì‹E‹ �8csmàu%ƒxu‹@= “t=!“t="“t= @™t3À]Â è$  ÌSV¾Y@ »Y@ ;ósW‹>…ÿt	‹Ïè8   ÿ×ƒÆ;órê_^[ÃSV¾Y@ »Y@ ;ósW‹>…ÿt	‹Ïè   ÿ×ƒÆ;órê_^[Ãÿ%pA@ ÌÌÌÌÌÌÌÌÌÌÌÌÌhK4@ dÿ5    ‹D$‰l$�l$+àSVW¡p@ 1Eü3ÅP‰eèÿuø‹EüÇEüþÿÿÿ‰Eø�Eðd£    òÃ‹Mðd‰    Y__^[‹å]QòÃU‹ìÿuÿuÿuÿuhó*@ hp@ è±  ƒÄ]ÃU‹ìƒ%´s@  ƒì(S3ÛC	p@ j
è$  …À„m  ƒeð 3Àƒp@ 3ÉVW‰´s@ �}ØS¢‹ó[‰‰w‰O‰W‹EØ‹Mä‰Eø�ñineI‹Eà5ntelÈ‹EÜj5GenuÈXj YS¢‹ó[‰‰w‰O‰WuC‹EØ%ð?ÿ=À t#=` t=p t=P t=` t=p u‹=¸s@ ƒÏ‰=¸s@ ë‹=¸s@ ƒ}ø‹Eä‰Eè‹Eà‰Eü‰Eì|2jX3ÉS¢‹ó[�]Ø‰‰s‰K‰S‹EÜ©   ‰Eð‹Eüt	ƒÏ‰=¸s@ _^©   tmƒp@ Ç´s@    ©   tU©   tN3ÉÐ‰Eô‰Uø‹Eô‹Møƒà3Éƒøu3…Éu/¡p@ ƒÈÇ´s@    öEð £p@ tƒÈ Ç´s@    £p@ 3À[‹å]Ã3À9p@ •ÀÃÿ%Œ@@ ÿ%„@@ ÿ%A@ ÿ%4A@ ÿ%ø@@ ÿ%HA@ ÿ%DA@ ÿ%@A@ ÿ%0A@ ÿ%,A@ ÿ%A@ ÿ%LA@ ÿ%dA@ ÿ%8A@ ÿ%A@ ÿ%A@ ÿ% A@ ÿ%A@ ÿ%ð@@ ÿ%ä@@ ÿ%hA@ ÿ%A@ ÿ%A@ ÿ% A@ ÿ%$A@ ÿ%(A@ ÿ%h@@ ÌÌÌÌÌÌÌÌÌÌQ�L$+ÈÀ÷Ð#È‹Ä% ðÿÿ;Èòr‹ÁY”‹ ‰$òÃ-   … ëçÌÿ%€@@                                                                                                                                                                                                                                                                             Œ[  ˜[  °[  À[  Ì[  æ[  ô[  
\   \  4\  D\  R\  b\  x\  Š\   \  ²\  Ê\  à\  ü\  ]  Ìa  ¸a  ža  ˆa  na  Ra  >a  *a  a  ð`      àa  Š]  v]  €]      ^]    €T]    €o  €s  €
  €	  €F]  —  €  €<]    €    È]      ¾]  ¶]  Ü]  ^  ¨_  &^      ’_      �^      Z_  d_  P_  _  n^  È_  ä_  B_   `  `  `  _  ü^  €^  4_  Ò]  Ü^  ¼^  ¤^  _      R^  8^  
^  ì]  &_  ¸_      Ÿ1@     °+@         +@ ¨+@                     `p@ °p@ S u c c e s s   S i g n a l   n o t   e x p e c t e d   a t   t h i s   t i m e     I n v a l i d   s t r e a m   i d e n t i f i e r   I n v a l i d   p r o c e s s   i d e n t i f i e r     D u p l i c a t e   s t r e a m   i d e n t i f i e r   I n v a l i d   c l i e n t   s e c u r i t y   t o k e n   I n v a l i d   s e r v e r   s e c u r i t y   t o k e n   F a i l e d   t o   s e t   s o c k e t   # % d   t o   n o n - b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d       C o n n e c t i n g   s o c k e t   # % d   u n e x p e c t e d l y   s u c c e e d e d     C o n n e c t i n g   s o c k e t   # % d   f a i l e d     F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d   F a i l e d   t o   s e n d   % s   t o   s o c k e t   # % d :   s e n t   % d   o f   % d   b y t e s         F a i l e d   t o   s e t   s o c k e t   # % d   t o   b l o c k i n g   m o d e ,   f a i l e d   w i t h   % d   h a n d s h a k e   F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d       F a i l e d   t o   r e a d   h a n d s h a k e   d a t a   f r o m   s o c k e t   # % d :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   U n e x p e c t e d   s i g n a l   c o d e   % d   f r o m   s e r v e r ,   e x p e c t i n g   H A N D S H A K E _ A C K   U n k n o w n   e r r o r       H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   S e r v e r   r e j e c t e d   c o n n e c t i o n :   % d :   % s   H a n d s h a k e   f a i l e d   f o r   s o c k e t   # % d :   I n v a l i d   s e r v e r   t o k e n   h a n d s h a k e   a c k   F a i l e d   t o   c o n n e c t   s o c k e t   # % d :   U n k n o w n   e r r o r   F a i l e d   t o   c o n n e c t   s o c k e t   # % d     F a i l e d   t o   c r e a t e   s o c k e t   # % d   s e l e c t ( )   o p e r a t i o n   f a i l e d   s e l e c t ( )   u n e x p e c t e d l y   r e t u r n e d   z e r o   s o c k e t s   F a i l e d   t o   c r e a t e   p i p e   f o r   p r o c e s s   I / O   s t r e a m   # % d         F a i l e d   t o   s e t   h a n d l e   i n f o r m a t i o n   f o r   p r o c e s s   I / O   s t r e a m   # % d   F a i l e d   t o   c r e a t e   c h i l d   p r o c e s s     F a i l e d   t o   r e a d   f r o m   c h i l d   p r o c e s s   p i p e   # % d     d a t a     F a i l e d   t o   r e a d   f r o m   s o c k e t   # % d         F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d       F a i l e d   t o   s e n d   d a t a   t o   c h i l d   p r o c e s s   p i p e   # % d :   s e n t   % d   o f   % d   b y t e s     F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n         F a i l e d   t o   r e a d   t o k e n s   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   % d   b y t e s     F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n       F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   r e c e i v e d   % d   o f   e x p e c t e d   1   b y t e       F a i l e d   t o   r e a d   t o k e n - c o m m a n d   s e p a r a t o r   f r o m   s t d i n :   e x p e c t e d   0 ,   g o t   % d       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n       F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   c o m m a n d   t o o   l o n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   m i s s i n g   n u l l   t e r m i n a t o r     F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   i n v a l i d   U T F - 8   s t r i n g   F a i l e d   t o   r e a d   c o m m a n d   f r o m   s t d i n :   f a i l e d   t o   d e c o d e   U T F - 8   s t r i n g         R e t r i e v i n g   c o p y   t h r e a d   # % d   e x i t   c o d e   f a i l e d   W a i t   o p e r a t i o n   o n   c o p y   t h r e a d s   f a i l e d   W S A S t a r t u p   f a i l e d :   % d   W a i t   o p e r a t i o n   o n   c o n n e c t   t h r e a d   f a i l e d   R e t r i e v i n g   c o n n e c t   t h r e a d   e x i t   c o d e   f a i l e d     P I D   W a i t   o p e r a t i o n   o n   c h i l d   p r o c e s s   f a i l e d     R e t r i e v i n g   p r o c e s s   e x i t   c o d e   f a i l e d   e x i t   c o d e   ¨A@ ¸A@ üA@ 0B@ hB@  B@ ÜB@ a d d r e s s   p o r t     t o k e n - s i z e     c w d   E r r o r   p a r s i n g   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   a d d r e s s     I n v a l i d   s e r v e r   p o r t :   % d   I n v a l i d   t o k e n   s i z e :   % d     =   U n k n o w n   o p t i o n :   % s     O p t i o n   % s   r e q u i r e s   a   v a l u e     P r o c e s s   l a b e l   n o t   s u p p l i e d     S e r v e r   p o r t   n o t   s u p p l i e d     1 2 7 . 0 . 0 . 1   % d :   % s     % s :   % d :   % s     %s
     h%s\       f   $V  $B      h%s\          ŒV  ŒB      h%s\       h   V   B      h%s\                   \                                                           p@  V@    pA@                    K4  RSDS0=|«@ÕèE�¾¿’ó œØ   C:\Users\Dave\source\repos\windows-process-wrapper\Release\ProcessWrapper.pdb       "   "         GCTL   ô&  .text$mn     @  p  .idata$5    pA     .00cfg  tA     .CRT$XCA    xA     .CRT$XCAA   |A     .CRT$XCZ    €A     .CRT$XIA    „A     .CRT$XIAA   ˆA     .CRT$XIAC   ŒA     .CRT$XIZ    �A     .CRT$XPA    ”A     .CRT$XPZ    ˜A     .CRT$XTA    œA     .CRT$XTZ     A  €  .rdata   V     .rdata$sxdata   $V  ä  .rdata$zzzdbg   Y     .rtc$IAA    Y     .rtc$IZZ    Y     .rtc$TAA    Y     .rtc$TZZ    Y  <   .xdata$x    TY  ´   .idata$2    Z     .idata$3    Z  p  .idata$4    Œ[  ^  .idata$6     p  `   .data   `p  8  .bss     €      .gfids$y     �  À  .rsrc$01    À‘  èÚ  .rsrc$02                    þÿÿÿ    Ìÿÿÿ    þÿÿÿî,@ -@     þÿÿÿ    Øÿÿÿ    þÿÿÿ0@ 0@ Z          .]   @  °Z          j]  ”@  œZ          ¤]  €@  ðZ          *`  Ô@  èZ          J`  Ì@  [          l`   A  p[          Ž`  TA  [          ®`  ø@  [          Î`  ð@                      Œ[  ˜[  °[  À[  Ì[  æ[  ô[  
\   \  4\  D\  R\  b\  x\  Š\   \  ²\  Ê\  à\  ü\  ]  Ìa  ¸a  ža  ˆa  na  Ra  >a  *a  a  ð`      àa  Š]  v]  €]      ^]    €T]    €o  €s  €
  €	  €F]  —  €  €<]    €    È]      ¾]  ¶]  Ü]  ^  ¨_  &^      ’_      �^      Z_  d_  P_  _  n^  È_  ä_  B_   `  `  `  _  ü^  €^  4_  Ò]  Ü^  ¼^  ¤^  _      R^  8^  
^  ì]  &_  ¸_      PReadFile  SetHandleInformation  ÀGetStdHandle  áWriteFile ©WaitForMultipleObjects  Ô CreatePipe  «WaitForSingleObject ÑMultiByteToWideChar -GetExitCodeThread PGetLastError   CloseHandle è CreateThread  
GetCurrentProcessId Û CreateProcessW  ,GetExitCodeProcess  šFormatMessageW  TInterlockedFlushSList ÍWideCharToMultiByte WInterlockedPushEntrySList KInitializeSListHead VInterlockedPopEntrySList  KERNEL32.dll  H WSARecv   WSAConnect  M WSASend  InetPtonW WS2_32.dll  P wcsstr  H memset  5 _except_handler4_common VCRUNTIME140.dll   free   malloc  n wcstol  # _errno    _aligned_free  __stdio_common_vswprintf_s    __acrt_iob_func  realloc  _aligned_malloc  __stdio_common_vfprintf  __stdio_common_vswprintf  B _seh_filter_exe D _set_app_type . __setusermatherr   _configure_wide_argv  7 _initialize_wide_environment  + _get_initial_wide_environment 8 _initterm 9 _initterm_e X exit  % _exit T _set_fmode   __p___argc   __p___wargv  _cexit   _c_exit ? _register_thread_local_exe_atexit_callback   _configthreadlocale  _set_new_mode  __p__commode  6 _initialize_onexit_table  > _register_onexit_function  _crt_atexit  _controlfp_s  j terminate api-ms-win-crt-heap-l1-1-0.dll  api-ms-win-crt-convert-l1-1-0.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll  api-ms-win-crt-locale-l1-1-0.dll  ‚UnhandledExceptionFilter  CSetUnhandledExceptionFilter 	GetCurrentProcess aTerminateProcess  mIsProcessorFeaturePresent -QueryPerformanceCounter GetCurrentThreadId  ÖGetSystemTimeAsFileTime gIsDebuggerPresent gGetModuleHandleW  F memcpy                        ±¿DNæ@»ÿÿÿÿ         8S@     °#@ HS@     €$@ TS@      %@ lS@      %@                                                                                                                                                                                                                                                                                                                                                                                                                                                         
         E   s   4      
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     0  €   `  €   x  €   �  €                  ¨  €   À  €   Ø  €   ð  €               e    €                    €                  8 €               	  P                 	  `                 	  p                 	  €                 	  �                 	                    	  °  À‘  h          (–  ¨          Ð¦  ¨%          xÌ  ›          �g >           Ðg X          (k }          (                                                ­�: ©|6	º�EcÈ™OÌÍ�Q÷Ò¥^ùÕ©cäË£c¡Ò¦_GÛ�5×žC         k7Ë *N H%ŒK/G»‹=xÃ�?õ³‚4ÿ«{/ÿ»‰9ÿÏšHÿ×©aÿÓ¬oî³‘[’²…>²�Q ˆ<  n:Î s<ÖV-§‰Y9Gb˜l3ì�\!ó_C—R:dgI�›o(æ¾�Dÿ¬˜xÿ¸�sÿÛµx±ÓžKÕ¤W e/Ên9Î’o?ÇøsI»ïoH¨ÿV4‰â;wCqV'_u_<–\F%l™‰oíÄ´›ÿÕªeÿà»‚ÿÔ®r�] yIÑLŠ`Øï�yßú¢€ÒÞ¢{¡ü†a¥ÿ_:¡Ù�`>ÅÂ£qÙxoa9ÄÅÇÜÊ¯ƒÿ×¨]ÿÝ´tÿÛ¼ŒèÕ¬lF‘jÞ`¢äÀ˜wÕÈaK¾�D¹©}>ÿ’jHÿ¹�VùØ·ƒ‚YPAMÁ¿»õ·›pÿÖ©bÿÝ³rÿäÃ�ÿá½„§‘xRlš~d\ˆmyL]Idšv;%Ã˜U}È ] ÂŸg x9UhK‘­†Iÿ»�KÿÓ¦_ÿÚ°nÿâ¿‰ÿÕºŽØÇ©{ûÜ¼ŠúÒ³�è’{W�´”b¯¤†V—´ŒM«³…<Ñ†`%°ZÆÅ‘?ÿØ¨[ÿ‰mAÿ€g@ÿÞ¾ŒÿçÍ¥ùÎ±ƒûæÅ’ÿäÂŽÿ¾žkþÕ«hÿÍžUÿº‡7ÿ�e$÷[AÛ›n'üÐ›Iÿ×§[ÿ‰mAÿ€g@ÿÞ¿ŒÿçÍ¥ùÆ§vãÝ³rÿÚ°lÿÙ¬cÿÎ›Jÿ½‰9ÿ•j&ÿ[AýhJþ®}/ÿÐ™DÿÓŸMÿÙ¬eÿÚ°mÿâÁŒÿÖ»�Ø½¡t§Ú°nÿ×ªbÿÍ�Oÿ¸…3ÿ¢r(ÿZ ÿS;ÿ�\!ÿ½‡1ÿÎ•<ÿÓ OÿÚ®iÿÜ³qÿåÆ•ÿá¾†¥ª“pIÓ¯víÆ’@ÿ¿ˆ0ÿµ€-ÿ�f%ÿnNÿV=ÿ“i%ÿÂ‹2ÿÎ˜AÿÖ§\ÿØªbÿÝ¶wÿäÅ’éÚ°lC?2Æ©{’Ï£]ÿ»…1ÿšn'ÿ‹c$ÿlMÿfIÿ¬|/ÿÎ˜CÿÓ¡PÿÕ¤WÿÛ±nÿá¾‡úÜ³r|µc ¸œn §ŒbÙ¹‡±Í¥gÿŸw6ÿŠc$ÿhJÿjKÿ±„=ÿÕ¢PÿÖ§[ÿÙ®iÿÝ·zëÛ³r|Ì’9
ÑœI , êÅˆ Ô­qâ¿ˆ“Ü¹�ïÇ¢gÿ³ŽTÿ½˜]ÿ×±uòÕªg½Öªg¶×¬g‹Ñ S9ÁÈŒ1             Ù¬e Ó£Vàº~IãÀˆ äÂŠËåÃŒÀá¼‚hÂ�@®o¡M ¢Q             ð  À  €                                          €  À  à  (       @                                                                 ‚Q �\ …]«:eÃ•K¿ÉœTë¾•TðÅ�_ñÓ¨cóÐ£]ÙËœR­Â�Bi—i ®f·t                                                                 �n# •e¯�8a»ŽHÌÂ—SóÕ¦[ÿÔ£TÿÒ Qÿ×©`ÿÙ­gÿÚ¯lÿÛ²qÿÐ©løÀ�eÍÓ£W–É‘77·o¿~                                            ‚[ [9¥{9zÉšO÷ÐœIÿÊ“=ÿÇ�7ÿÃ‹3ÿÄŒ3ÿÍ–?ÿÐšDÿÒ�HÿÔ Oÿ×ªbÿÝ·zÿà»ƒÿÛ²rêÔ¡QŠÙš6Æ�A ý¿%                             m9Ì     H&†29'  ÿ ©|5t»ŒBñË•@ÿ»…1ÿ«y+ÿ¤t)ÿšm'ÿšm'ÿ­{,ÿ¼‡2ÿÇ�9ÿÏ™CÿÔ¢QÿÖ¥XÿÛ¯iÿÖ²yÿ¸›lþ™u<Ã³�26\aj Ã‚                     l8Ì p<Ð p;ÑDN)“°%—l%0»Š<åÅŽ7ÿ°},ÿ—k&ÿoOüT<ÜG3·G2³Z@ÑxUö¡r(ÿÃŒ5ÿÐ›GÿÔ¢Qÿ²ŠIÿ”…nÿ�xjÿ°˜rÿÙ°oÙÏ—>Bá¹z Æˆ(             p=Í n:Î n:Î6k9ÉÜ@"w¯  $U<�‰b'ÿ€[ÿnOÿQ:ë(
w         "OV=Ç˜l&ÿÅŒ3ÿ©=ÿœ”ˆÿ¶±«ÿº™eÿã½„ÿåÆ–ÿÛ±nÙÌ“86ÑœG ÄŠ-         n:Í n:Ín:ÎÂm9Ìÿ\0®òX-§åX.�õY0‘ÿM+{ÿ6Oÿ(¢  " :+dK#JlQ&hnZ<>'S;¹�d#ÿ�‚nÿÛÝßÿ®˜vÿÕ§^ÿÛ¯lÿá½†ÿåÆ•ÿØªaÂÍ�/Í”8     n;Ì n<Én:Î‰m9Îÿn9ÎÿuCÒÿQÕÿ†YØÿ…YÙÿQ×ÿsBÏÿ`3´ôB#}£ (jQ)_yZ(÷P:ÿ‘}]ðspkI -RF4áÊÊÉÿ×ÔÑÿ·“\ÿÚ«bÿØªbÿÜ²qÿãÁ�ÿß¾Šÿ¹ŒDvÿÓ… W8 m9Í m8Í7n:Îè}OÓÿ™tÝÿ©Šãÿ¬�äÿª‹äÿ¦†àÿ¡�ÛÿœyÜÿ�dÝÿo?ÇÿD#‚ª?3!M¡IíÄŸeÿÀ¨ƒàlcV*   †††ÈëìíÿÇ¿³ÿÀ“LÿÙ«cÿØªbÿØ«dÿà¹}ÿØ¼’ÿºžqÏÎ›J0Ì›M P»sAÏ—ŽeÙÿ§‡âÿ§‡ãÿ¡ßø¡~âÆ˜u§Èª�sÿšqXÿxY[ÿz_˜ÿ…^ÐÿT,¡ø/'­ u/ñâ½ƒÿ×¼’¼©_ (()'¬¬¬çôõöÿÀ´¢ÿÂ�=ÿØ©`ÿÙ¬fÿÚ¯jÿÞ¶xÿæÇ–ÿéÍ¡ÿØ«b—·j }OÒ(’kÛÝ£�áÿ¢áÿ£âÿ…h¹ÝK:s%¤x+3¼�FÜÉ”?ÿ¦v&ÿvT$ÿ`CEÿ[==ÿ…^(ÿÊ™LÿÞ¿�ýÁ¥zr†‰� 655C···õøøùÿ¹®�ÿ¾Œ=ÿÚ¬cÿÜ²pÿÜ²pÿÜ³rÿâÀ‰ÿéÏ¦ÿßºÞÏ˜A*•mÞ¡~â^¢á‰¢á¯£€âÐ‘rÊåJ9gdñÄù «‚@bÉœVïÌšKÿ¿Œ9ÿ³‚0ÿ¼Š7ÿÑ¡TÿÛ·þË¯�²®…E   <0®©§¤ÿêëìÿ¤œ�ÿ”n2ÿØ©`ÿÜ²qÿÜ²pÿÜ²oÿàº~ÿçË�ÿåÇ–ûÕ£Sl	 	    —sÿ­‡þ¦‚ë)bLŠ+   �g£|@KÅ�\ÂÍ¤cïÔªhüÖ¯rùÐ®yÞÈ§s�›wA¤v-"!+fIæ’q>ÿ©Œ]ÿ±‹Oÿ—o1ÿÐ¢YÿÜ²pÿÜ²pÿÜ²oÿÞ¶wÿåÆ”ÿãÉŸÿÉŸ\�zb=»Ÿ‚UÆŠpF¡t\7yZF%R6(/       Ð³o �q,®‰M5»–[O°ŽXE�o;%`H"¤z9{™n+œ 4rQë°}+ÿÌ–@ÿÔŸLÿÄ“EÿÔ£WÿÝ±lÿÜ±mÿÝ´rÿÞ¶wÿæÇ•ÿÒ¿ þ¬‘f­§ŒbòæÅ’ÿà¿ŒÿØ·„ÿÌ«yû¼�lð�xR†E7!)e<�x_7€lU1`VC%,sY1`‡j=y¢I¢¸‹EÙ©z1þƒ]!€2#^€[ ûµ�/ÿÏšGÿÔ¢RÿÖ£SÿÓ¤[ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò®”jýçÇ”ÿåÅ“ÿæÆ”ÿçÇ”ÿéÉ–ÿ¤�iéPC-ÃÒ®uþ×²vÿÆ¤mù†mFÛË¢aýÎ¡ZÿË—Fÿ´�0ÿˆ`"ßI4`_DÒ q(ÿÆŽ7ÿÕ¤Vÿ×¨]ÿÛ®eÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý°—oýçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿçÇ•ÿÁ¦|ÿ„oMÿà»€ÿß¹|ÿÛ³sÿ¿”QÿÊ”AÿÃ‹4ÿ¯|,ÿŠc#ü\B­L6Ì€[ ÿ®|,ÿÌ•=ÿÖ¦Yÿ×§\ÿÛ®dÿ£Šaÿ
ÿ0-(ÿw`;ÿÙµ{ÿçÉšÿïÛ¼ÿäÄ‘ý®–pòçÇ•ÿåÅ“ÿåÄ‘ÿäÂŽÿãÀŠÿÛ·ÿÊ¢bÿØ¨^ÿÕ¤VÿÔ¡PÿÎ˜Cÿ¼…/ÿ§w*ÿŒd#ÿjKìC0àaEÿŽe$ÿ·‚.ÿÍ—BÿÔ OÿÔ¡PÿÕ¢SÿÓ¥\ÿœw<ÿ†d.ÿÁœbÿá¼�ÿçÊœÿïÛ½ÿâÁŒò¤ŽjÙá¾†ÿÞ¶xÿÜ³rÿÛ°mÿÚ®iÿÙ®hÿÖ¦YÿÓžLÿÓŸMÿÐœKÿÀ�<ÿ¢s)ÿ�e$ÿuSÿK5ùQ9þrQÿšm'ÿ»†1ÿÏšEÿÓŸLÿÓŸMÿÓŸLÿ×¨]ÿÝ²mÿÜ±mÿÝ´rÿÞ¶wÿçÉ™ÿÓÀ¢þ­’g­”^¬Û¶|ÿÙ¬eÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿØªaÿÒŸNÿÇ“Bÿµ‚3ÿ¬z,ÿ r(ÿ~Z ÿaEÿ@.ÿ^Cÿƒ]!ÿ£t)ÿÃ�7ÿÏ—?ÿÐ™BÿÒœHÿÓ OÿÚ®hÿÜ²qÿÜ²pÿÜ²oÿÞ¶xÿæÉšÿäË¤ÿÉŸ]�zgJlÕ¶†ûÚ¯iÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÔ¥[ÿ¿Œ<ÿ­z,ÿ«y+ÿ¨w*ÿŽe$ÿZ ÿR:ÿJ5ÿjKÿ�f%ÿ®|,ÿÈ�5ÿÏ–>ÿÏ—?ÿÏ—?ÿÔ¡QÿÛ°lÿÜ²pÿÜ²pÿÜ²oÿà¼‚ÿéÎ¤ÿæÈ™ûÕ£SkI9*ÃªƒÞß·yÿÙ­fÿÙ­hÿÖ©aÿË™KÿÁ‹5ÿ»„/ÿ®|,ÿ©x+ÿ’h%ÿ�\!ÿxVÿF1ÿV>ÿvTÿ–k&ÿ»…/ÿÉŽ2ÿË’7ÿÏ–>ÿÑšEÿ×§\ÿØ«dÿÚ®iÿÛ±nÿÝ´sÿäÄ�ÿëÓ¬ÿß¹~ÛÏ—@'   £�i–áÂ‘ÿØ¬fÿÎžQÿÃŽ:ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿšm'ÿ‚\!ÿ‚]!ÿiKÿB/ÿ_Dÿ€\ ÿ�p(ÿÀ‰0ÿÈŽ2ÿÈŽ2ÿÍ–?ÿÖ¦ZÿØªbÿØªbÿØªbÿÙ«dÿÞ·zÿçËŸÿèÍ£ÿ×©_� = „kC nX67Ï¶ŽéØ¯nÿ¿‰2ÿ¾†/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¬{,ÿ�e$ÿ…_"ÿ�\!ÿZ@ÿC/ÿdHÿˆa"ÿ¦v*ÿ¾‡0ÿÈ�4ÿÌ•>ÿÒŸNÿ×§]ÿØªbÿØªbÿØªaÿÚ­hÿá½…ÿèÌ¡ÿÞ·yÝÐšE+ÒžL '	    £ŠbŠßÂ“ÿÎ Vÿ¾‡1ÿ¾‡0ÿ¿‡0ÿ²~-ÿ‘h%ÿŒd$ÿŒd$ÿ‚]!ÿY@ÿL6ÿmNÿ“i%ÿµ‚1ÿÆ�9ÿÐœHÿÔ¢QÿÔ¢RÿÔ£Tÿ×¨^ÿØªbÿÙ¬fÿß¹~ÿæÈ™ÿà¼ƒ÷Ñ›HhòÐ› Ì—C     pW. [CÁ¦{ÂäÅ•ÿÏ VÿÀ‰3ÿµ�-ÿ•j&ÿ‹d$ÿŒd$ÿ�d$ÿyVÿbEÿ]Bÿ€[ ÿ­|,ÿË”>ÿÑšCÿÓžKÿÔ¢RÿÔ¢RÿÔ¢RÿÕ£TÿÙ¬eÿßºÿåÇ—ÿâÀŠüÓ¡QŽÆ‡#	Ì’7           Ç¢f Šl>6Ò¶‰ÙæÈ˜ÿÓ§bÿ§{4ÿ‹c$ÿ‹c#ÿŒd$ÿŠb#ÿmMÿcFÿ_CÿkLÿ˜m(ÿÉ”?ÿÑšCÿÒœFÿÔ¡QÿÔ¢RÿÕ£Tÿ×©_ÿÞ¶yÿåÇ—ÿà½„÷Ô¡RŽÊ�-Í“9                 + ÿÿê ª‡NBÝ¾�ÙæÉšÿÔ­pÿµ‹Hÿšq/ÿŽf&ÿ€[ ÿcFÿaDÿaDÿ`Dÿ‰f.ÿÓ¤XÿÕ£SÿÓŸMÿÖ¦ZÿÙ¬fÿÜ´tÿà»�ÿÞ¹ÿØ­hÝÑœJgÇˆ&	Ë�3                         mI ÿÿÿ Î V6à¼ƒÃçÉ›þãÁ‹ÿÕ­mÿÂ˜Uÿ¦~>ÿ�i1ÿŠg0ÿ•p6ÿ°‡FÿÏ¡Xÿß¹}ÿÛ´vÿØ®lÿÛ´vÿÞ¸}ÿÛ´uùÖ©bÙÎšG‹ÆŠ,)­V À}                                 ±p Ý²m ÐœIÛ²q‹äÄ‘ëçËžÿåÆ”ÿàº}ÿÜ³rÿÛ±oÿÝ´sÿá»~ÿãÁŒÿãÃ�ðÍŸWŠÂ‘D‰Æ•H‘Í™F{É‘9OÂ…%¬e ¶r                                                 Ì’6 Å„"Ô¤V9Ü´t—âÀŠÛäÅ”÷æÈ™ÿæÊœÿçÊ�ÿæÉ›úá¿ˆ×Ù®ifÉ�.ÐšF                                                                                 Ê‹( À~Ð›F$Ö§[WÙ®h‚Û±n”Ú°m‰Øªb`Ñ�K"ºn Å…#                                                     ÿÀÿÿ€ ÿ  ?ù  ð  à  À €  €                 À                                      €  €  À  à  ð  ø  ü  þ ÿÿ€?ÿ(   0   `           $                                                                                  ?, Ê�+ ¦t$¯|,e¶…7¨¼�A×Â“Hó§�Dß¯‰LàÍžT÷ÊšNæÇ•FÌÃ�=£¿ˆ2nº‚(6¼ƒ"   õàX                                                                                                                 ”d uE ¡q%'šo,t™u<³ËŸYûÔ©dÿ×¬gÿÙ­fÿÏ¥bÿÓ­pÿÞ·zÿÝ·zÿÜ¶zÿÚ³uÿÕ¬küÏ¢Zê¨~<¢šo*LÆŠ*(¾}Â„                                                                                                      �n# ˜i¥v,d¶‰AÛÇšTþÂ˜Uþ×¨]ÿÕ£TÿÒŸMÿÐœHÿÑ�IÿÖ¥XÿÖ§\ÿ×©_ÿØ«dÿÚ¯kÿÜ³sÿÞ·zÿ¼žnúÏ«t÷Ô¤ZâË”<�ÅŠ+.¿Â…$                                                                                         Šb! }T¨z1†Á”L÷Ô¤XÿÓžKÿÎ˜AÿÍ–?ÿÊ’8ÿÈ�4ÿÇ�2ÿÈ�4ÿÐ˜AÿÑ›DÿÒ›EÿÒœGÿÓŸLÿÕ£TÿØªbÿÝµwÿá½…ÿãÂŽÿÞ¹~ÿÒ¢WãÉ�7|Ã‡(ÇŒ/ ¼                                                             H*t <$`$    šm& ¤s%
ˆb&n©‚DæÕ£TÿÏ˜BÿÅŽ7ÿ¼†1ÿ»…/ÿ¹„.ÿ¶�-ÿ´€-ÿ¶‚.ÿÂŒ5ÿÇ�9ÿË”=ÿÏ˜AÿÑšCÿÑšCÿÔ¡Pÿ×¨]ÿÚ¯kÿÝµwÿá½…ÿãÃ�ÿÜ´týÒœGÀÐ“3;íšÙ—/                                                     o<Î žUÿK(‹^-S8_ «‚> žq)h¸ŠA÷Æ“CÿË”<ÿÀ‰3ÿ²-ÿ¦v*ÿ r)ÿ�p(ÿ–j&ÿ’h%ÿ•j&ÿ¥u)ÿ°},ÿº„/ÿÂ‹4ÿÉ’:ÿÑœGÿÔ¢RÿÔ¢QÿÔ£Sÿ×¨^ÿÝ³pÿÕ¯uÿ¹Ÿvÿ”{Tÿ‰e,ã±0_ë§;Ê‘6                                             m9Í l8Ìo:ÐtF%ƒÓ)R9 ˜k$'°‚:ÚÎšGÿÅŒ2ÿ·‚.ÿ¬z,ÿœo(ÿˆ`"ÿoNÿ\BýM7òG2éK5î_CúvTÿ’h%ÿªx+ÿ¼…/ÿÊ’9ÿÑ�JÿÔ¢RÿÕ¢RÿÓ¡Qÿ¥€Dÿ{mWÿxtpÿ`VGÿ¶Ÿ{ÿÖ«eñÎ•;rÆŠ,É�4                                     n;Í o<Ìn:Ïrh7Ãø2\Ÿ   ÄŠ0 |X³ƒ5ÿ¾ˆ4ÿ±~,ÿ¡s)ÿ‘g%ÿvSÿI3õ&
´f9   *1Q&
“F2ßrQÿ¡r)ÿ¿ˆ0ÿÉ�5ÿÐ›GÿÐŸOÿŠl;ÿ€{sÿ¿ÀÁÿ�‚oÿËªwÿçÆ”ÿèÌŸÿÙ­gôÍ”:rÈŽ2Ë“:                             m9Ì {Eç n:Í^o;Ðñ]1®ÿ,   %5L6Î€[ÿwUÿjLÿcGÿX?ÿ5&ä`   
                     )*žeHø�p(ÿ¿‡0ÿÈ�4ÿ†f4ÿˆ…‚ÿäåæÿ ˜Œÿ¸�SÿÞ´rÿà¼„ÿäÄ’ÿçËŸÿ×ªañÌ’7_ÿÿ� È�7                     q?Î m:Í n:Í<n:Îâo:Ïÿe5½ÿM)‘ïN)’çM)�êN*†üP,~ÿH)lÿ:"Pÿ&,ÿøc#         	  4(I81?1&   
!cF÷¤t)ÿ’h&ÿ{ulÿáâãÿÔÓÓÿ—}SÿÙªaÿØªbÿÜ³sÿá¼…ÿåÆ•ÿæÉ›ÿÔ£TâÊ�3<Ì’7 Ê‘8                 n;Í n;Ìn:Î¿n:Îÿn:Îÿn:Ïÿo:Ðÿn9Ðÿn8Ðÿn8Ñÿm8Ñÿm8Ðÿk7Ìÿd4½ÿO*–û6e¹%G    fM$ƒvX'ÜmP#îx[.æ…u[­AAA)   )“iJÿdWBÿÉÉÊÿ÷÷øÿ¨¢˜ÿº’SÿÚ«cÿØªbÿØ«cÿÝ¶xÿá½‡ÿçÊœÿãÁŒÿÑ›E¾Ï“6Ð—< ®{*         n<É _�  n:Í{n:Îþn:Îÿm8Îÿm9ÎÿsAÐÿQÔÿ‰_×ÿ�fÙÿ�gÙÿŠ`×ÿ�TÕÿwEÒÿp;Ñÿi7ÆÿO)“î"@x   $=“o6ódHÿ-
ÿM9ÿº§‰ÿa`]„´±¬  &Ï”“�ÿèèéÿôôöÿ”…lÿÐ£\ÿØªbÿØªbÿØªbÿÙ¬fÿß¹ÿâ¿ŠÿéÎ£ÿÐ©kù¦v*T°2 _=         n;Í n;Í.n:Îàm8Îÿq>Ïÿ…ZÖÿ¢€ßÿ³—æÿ·œçÿ´˜æÿ°“æÿ®�æÿ­Žæÿ«‹æÿ¦…ãÿ—pÝÿ}OÔÿo;ÐÿV-¡÷!?s   hBºÀ™[ÿÁ—VÿÌ§kÿº¨‹çFDAAlha    III«ÈÈÈÿñññÿççèÿ“xMÿÖ¦YÿØªbÿØªbÿØªbÿØªaÿÛ°nÿá¼„ÿáÂ‘ÿ¦”xù™zI¤Ð›G$È–H     m9Ì m:Êm9Í�n;Îÿ„XÕÿ§‡áÿ´™æÿ­Žäÿ¥ƒâÿ¢áÿ¡~áÿ�{Úÿ›yÊÿ–t¹ÿ�m°ÿŠl¸ÿ™yÒÿ£�ãÿ‰^Øÿp<ÏÿG%‡ê>:*Š©€@ÿÞµuÿäÌ¦ÿÂ§}¼g. %
    zzy×ÜÜÜÿøøøÿÚÚÚÿ˜u=ÿÕ MÿØªbÿØªbÿØªbÿØªcÿÙ­gÿà¼‚ÿäÄ“ÿçÑ­ÿáÀ‹ÿÓŸN�Ë”;ÑžL m9Ì l7Ë(r@Ïá’kÚÿ¬�äÿ§†ãÿ¢~áÿ¡~áÿ¡~ßø¢áËž{ÜŠŠikÉ²ˆWÿ²‚>ÿ˜m/ÿvU+ÿW@?ÿnU“ÿ–sØÿwIÍÿO'œÿ/ÉaEß¼ˆ6ÿÜ²pÿêÒ¬ÿÈ¨uŸ    4˜——ïãããÿüüüÿÒÑÐÿžw9ÿÒšAÿ×¨_ÿÙ«dÿÚ­hÿÛ°mÿÜ±oÿÞ·zÿäÄ‘ÿèÌ ÿëÔ®ÿØªbáÐšE(ÒžM ‡[Ø xHÐs“lÛÿ¥„âÿ¢áÿ¢áÿ¢áÿ¡~ßÿpWœÉ^I�“j ¤v)[À“KõÎ›JÿÃŒ5ÿªy*ÿ„^ÿX?ÿL5JÿH-\ÿ@(:ÿ`C!ÿ¥u*ÿÎ›Jÿá¾‡ÿÕÀ�ô²�TXÀ¢r **) $##G¥¥¥øåååÿþþþÿÏÎÌÿ y:ÿÒš@ÿØ©`ÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿâ¿‰ÿæÆ•ÿìÖ²ÿà¼‚ÿÒ�JrÕ¡N l;Ç“lÛš¢áî¢áú¢áÿ¢áÿ¢áÿ£€ãÿw\¥ï!A:+0 ¡n�l2ƒÆœZýÔ NÿÃŒ5ÿ±~-ÿ�o'ÿŠb ÿ†_ÿ—l$ÿ´�/ÿË–CÿÜ³rÿåÊ ÿ½Ÿq¯c: E2    �¥¥¥ÿæææÿþþþÿÌÌÌÿsY1ÿË˜HÿØ©^ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿß¹~ÿåÅ’ÿêÐ§ÿèÍ¡ÿÕ£U»Ï™DˆbÌ¡~ß¡~à.¡}àN¡~àt¡~à›¢~á¿¢âÜ™xÕôL;k®   oP  Ÿp&¸ŒE¹Ê ]þÒ£XÿÎ™EÿÅ�9ÿÂŒ7ÿÃ�7ÿË•?ÿÔ¢Sÿß·yÿÜ¾�þ½£xÆ±…@4·‘X %	 VA1ö›š™ÿÜÝßÿôõöÿÁÀ¾ÿeM'ÿšs6ÿØ¦XÿÜ²oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÝµuÿäÃ�ÿçÊœÿìÖ²ÿÙ­gèÐšF6                žyß štßžzß
 }ß¤�å9kS–O §x.  p$•r;|ÆžaìÕ«jÿÕ«hÿÚ®gÿÙ®jÿß¸{ÿÙ·‚þÑ´…ôÅ¢k°�h.&i žq*    +�uTÿy`7ÿ‰uTÿ–‚cÿ™~Rÿ§|7ÿ‚a+ÿÔ¢SÿÛ°mÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²qÿâ¿‰ÿæÆ–ÿí×´ÿáº~üÐœHn#Q8*d? "                                  ¤q" šg­5@ª„H„¸•^»Î¨mÜ»›iÏÉ¦nËº–^™—t=D¬u"  œt4M—m)€   - —…_"ÿ¨w)ÿ¼†0ÿÌ˜EÿÔŸLÿÆ”Dÿ•o2ÿÒ PÿÛ¯kÿÜ²qÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà»�ÿåÆ”ÿãÌ§ÿ°˜tï•o3YbN.Ëº˜dÿ«ŒZô”wJâ|b:ÆdN+¤K:}1$W5                    e9 5  œh¯{)�n#¢g­J    SA%(›w=†©|3î‡`"—    0" †_"ÿ©x*ÿÁŠ4ÿÑœIÿÓŸMÿÒžLÿÍšJÿÓ OÿÚ®iÿÜ°mÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá¼ƒÿèËŸÿàË«ÿ´¥�õ¶�T›{eAçåÄ�ÿèÇ”ÿæÅ‘ÿâÀ‹ÿÙ·�ÿË©tÿ¸˜eü£…Tò�h@¡	7*C3g5(Z%D5		''5D3KhQ,r‘rA©´‹Jã¾‹;þ•j&þwUb   C/Ì�e$ÿ«y+ÿÂ‹5ÿÑ�KÿÓŸNÿÓ NÿÔ OÿÕ£TÿÖ§]ÿ»‹?ÿ¨|6ÿº’SÿÛ¶zÿà»ÿâÀ‰ÿéÏ¥ÿîÙ¸ÿòßÁÿÚ¯iæ†oKõåÅ’ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿæÆ•ÿçÇ•ÿêÈ•ÿ¹žtõ!WUE-z¸–`ý¹–]ý­‹V÷¥„Pò{c<¢aL+¢€Iê®ŠQð¼–YùÊ ^ÿÎ�QÿÅŽ9ÿ¢s(ÿ{XÙhJ"&
ojKû¡r(ÿ¹„/ÿË”=ÿÕ¤WÿÖ¦YÿÖ¦Zÿ×¨\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö�vRþæÆ”ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿæÆ”ÿÓ¶‡ÿ0)Þ]N5éà»€ÿâ½‚ÿã½�ÿå¿‚ÿ¢‡\ú~fAöàµqÿÛ¯iÿÓ¢VÿÉ“>ÿÀˆ1ÿ¦v*ÿ‚]!ýqQx!	TU=êŒc#ÿ¬z,ÿÅ�3ÿÑœGÿ×¨]ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�yVþçÇ•ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿäÄ“ÿ]O;ÿˆrNÿä¾‚ÿà»�ÿà»�ÿá¼€ÿÌ¨oÿ·�PÿÎ›KÿÆ�9ÿÄŠ1ÿ¾†/ÿ¥v*ÿ‡`"ÿsRÆ1#mK5åvSÿ™m'ÿ´.ÿÊ‘6ÿÓ¡Pÿ×¨^ÿ×¨]ÿ×¨]ÿÚ­eÿË¯„ÿ#ÿ   ÿ-..ÿZULÿoV-ÿÚµ{ÿâ¾…ÿéÍ£ÿìÖ²ÿñáÆÿÜ³qþ�xWõæÇ—ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ“ÿåÅ”ÿèÇ•ÿ¤Œgÿºšhÿá¹{ÿÝ´sÿÚ®iÿ×¨^ÿÕ¢SÿÈ‘:ÿÃ‰0ÿÃŠ1ÿ¸‚.ÿ r)ÿŠb#ÿuTóH4¦>,äbEÿ�\ ÿžp(ÿ¹ƒ.ÿÈ�7ÿÓ OÿÕ£UÿÕ¥WÿÖ¦Yÿ×§\ÿÛ±pÿ†lBÿ#
ÿÿT<ÿ¬ŠTÿà»€ÿá¾†ÿéÎ¤ÿíÖ´ÿñàÄÿÛ±oö…qRçåÇ˜ÿåÅ“ÿåÅ”ÿåÅ“ÿåÄ’ÿäÃ�ÿãÁ‹ÿá¾†ÿàºÿÖ¯pÿÓ¤YÿÕ£SÿÓ OÿÓŸMÿÓŸLÿÓŸMÿÌ–@ÿ¿ˆ0ÿ®{,ÿ›n'ÿ�e$ÿxVÿ]Cß<+çP9ÿkLÿ‰a#ÿ¥u*ÿÀˆ0ÿË•?ÿÓŸMÿÓŸMÿÓŸMÿÓŸNÿÓ OÿÕ£Tÿ×¨^ÿ»‹?ÿ¨|6ÿ»’SÿÛ¶{ÿà»ÿâ¿‰ÿéÎ¥ÿîÙ¸ÿòßÁÿÚ¯iæxeIËáÄ–ÿâ¾‡ÿà»�ÿÞ·zÿÜ´tÿÛ±nÿÚ¯jÿÙ­hÿÙ­gÿÙ¬eÿÔ¢RÿÓŸLÿÓŸMÿÓŸMÿÓŸMÿÒžLÿÄ‘?ÿ¤u*ÿ–k&ÿ‘g%ÿ{WÿkLýB/õJ5ÿ_CÿtSÿ‘g%ÿ¬z+ÿ¼†1ÿÏšEÿÓŸMÿÓŸMÿÓŸMÿÓŸMÿÓŸLÿÕ£TÿÛ°mÿÜ°lÿÚ°lÿÝ³rÿÝ´sÿÝ´tÿá½…ÿéÍ¢ÿàÌ­ÿµ¦�õ¶�T›dS8£Ø»�ÿÛ°lÿÙ­gÿÙ­fÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÖ¥YÿÓŸMÿÓŸMÿÓŸMÿË—Fÿ¹‡7ÿ­{-ÿ¤t)ÿ•j&ÿ}Y ÿsRÿT<ÿ9(ÿS;ÿlLÿZ ÿ˜l'ÿ³-ÿÃ�7ÿÏ—@ÿÐšDÿÒ�JÿÓŸMÿÓŸMÿÓŸMÿ×¨]ÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿá½…ÿçÊ›ÿäÎ¬ÿ°™vï”n3YI:#nÊ±‰üÞ¶vÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿØªaÿÔ OÿÎ›Iÿ¾‹;ÿ¯}.ÿªy+ÿ«y+ÿ©x+ÿ�d$ÿuTÿlMÿ@-ÿC0ÿX?ÿvTÿŠb#ÿ¡s)ÿ±.ÿÌ•=ÿÏ—?ÿÏ—?ÿÏ˜@ÿÑ›FÿÒžKÿÔ PÿÚ®hÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ³qÿãÂŽÿçÊ�ÿîÚ¹ÿá»üÐ›Hn!6²›wèäÁŠÿÙ¬fÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ®hÿØ«cÿÈ•Fÿ²€1ÿ«y+ÿ«y+ÿ«y+ÿ«y+ÿ—k&ÿ‚]!ÿ€[!ÿ`Dÿ:)ÿO8ÿbFÿxUÿ˜l'ÿ¥v*ÿ»…/ÿÌ“9ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ—?ÿÏ˜AÿÕ£UÿÜ±oÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÜ²pÿÞ¶wÿåÇ–ÿèÎ£ÿíØ¶ÿÙ­gèÑ›F5   �yW»åÉ�ÿÚ¯lÿÙ­gÿÙ­gÿÙ­gÿÙ­gÿÙ­hÿÙ¬fÿÑ¢XÿÆ‘?ÿ»…0ÿ­{+ÿ«y+ÿ«y+ÿ«y+ÿœo'ÿƒ^"ÿ�\!ÿ[!ÿN7ÿ@.ÿV>ÿmNÿ~Y ÿ�p(ÿ®|,ÿÆ�2ÿÈ�3ÿÌ”:ÿÏ—?ÿÏ—?ÿÏ—?ÿÐšDÿ×§\ÿÙ¬fÿÛ°lÿÜ²pÿÜ²pÿÜ²pÿÜ²oÿà¼ƒÿæÉšÿëÔ®ÿèÍ¢ÿÔ£T¹ÎšGâ¶q cO1r×¿™ÿà»�ÿÙ­fÿÙ­gÿÙ­gÿÙ­gÿÔ¦]ÿÉ–FÿÀ‰3ÿ¾†/ÿ¾‡0ÿ¸‚.ÿ¬z+ÿ«y+ÿ r(ÿ†_"ÿ�\!ÿ‚]!ÿuTÿ?-ÿH3ÿ^CÿsRÿ‰b#ÿšn'ÿº„/ÿÉŽ2ÿÈŽ2ÿÉ�3ÿÍ•<ÿÏ—?ÿÐ˜AÿÕ¤VÿØªbÿØªbÿØªcÿÙ­gÿÛ±mÿÜ²pÿÝ´sÿäÄ‘ÿçË�ÿîÙ¹ÿßºþÑ�IlÔ N 3' '(²šuàéÍ¢ÿÚ°lÿÙ­gÿÖ©aÿÌšLÿÁ‹6ÿ¾‡/ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ·‚.ÿ¥u*ÿ‰a#ÿ€\!ÿ�\!ÿ‚]!ÿeHÿ:)ÿN8ÿeHÿxUÿ‘g%ÿ�p(ÿ¿ˆ0ÿÈŽ2ÿÈŽ2ÿÈŽ2ÿÉ�4ÿÎ—?ÿÔ¢TÿØªbÿØªbÿØªbÿØªbÿØªbÿØ«dÿÚ®iÿàºÿæÈ™ÿêÑ©ÿëÓ­ÿ×¨]ØÐ›F!ÒžM     }eA�áÊ¥ÿá¾‡ÿÑ¡VÿÃŽ;ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¹„/ÿ•j&ÿ‚]!ÿ�\!ÿ�\!ÿ[ ÿV=ÿ;*ÿQ:ÿiKÿ~Z ÿ•j&ÿ¥v*ÿ½‡0ÿÇŽ2ÿÈŽ2ÿÈŽ2ÿÊ‘6ÿÑ�KÿØ©`ÿØªbÿØªbÿØªbÿØªbÿØªbÿØªaÿÙ­hÿá¾†ÿåÈ˜ÿíÙ¸ÿà¼‚ÿÒžK|á«R ÏœM     K8 9(.·�uáêÏ¥ÿÑ£[ÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¼†/ÿŸr)ÿŒd$ÿŠc#ÿ…_"ÿ‚]!ÿvTÿL7ÿ=+ÿT<ÿlMÿ„^!ÿ—l&ÿ®|,ÿº…/ÿÄ‹1ÿÉ�4ÿÌ–>ÿÒŸMÿÔ¢RÿÕ¥XÿØªaÿØªbÿØªbÿØªbÿØªbÿØ«dÿÞ¸{ÿâÀŠÿçÌ ÿæÈ™ÿÔ£UËÐ›GÑžL              x_8}ÙÀ—þåÅ“ÿÍœPÿ¾ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ½‡0ÿ¥v*ÿ�d$ÿŒd$ÿŒd$ÿŒd$ÿŠb#ÿoOÿO8ÿ?-ÿU<ÿmNÿˆa"ÿ›o'ÿ¶‚/ÿ¾‰3ÿÈ’<ÿÑžKÿÔ¢QÿÔ¢RÿÔ¢RÿÔ¢RÿÖ¦ZÿØªbÿØªbÿØªbÿØªbÿÝµuÿâ¿‰ÿåÇ—ÿèÎ¤ÿÖ§]ðÌ“:QÐ–: Í™H             :* ! £‡Z¾èÐ©ÿá¾‡ÿÌ›Oÿ¿ˆ1ÿ¾‡0ÿ¾‡0ÿ¾‡0ÿ«z+ÿŽf%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿˆa#ÿjKÿ_CÿT;ÿgIÿ‚]!ÿ r(ÿµ‚0ÿË•>ÿÏ™BÿÑ›FÿÔ¡QÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢SÿÖ§\ÿØªbÿØªcÿÜ´tÿá¿ˆÿäÅ”ÿéÐ§ÿÚ°mûÎ–=‚Ë‘7Í•=                     Žl7 ]E;À£tâìÓ­ÿà¼ƒÿÏŸTÿÀŠ4ÿ¾‡/ÿ°}-ÿ‘g%ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿ�d$ÿZ ÿdGÿcFÿZ@ÿhJÿ‰b#ÿªy+ÿÀ‹5ÿÐ™CÿÑšCÿÑšCÿÓŸMÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢Sÿ×©`ÿÝ¶wÿâ¿ˆÿåÆ”ÿéÏ¦ÿÜ³sýÏ˜AšÊ‘6Í”;                          ÿÿÿ €b3_Ñ³„ñìÔ®ÿá¾†ÿÔ§_ÿ½‹;ÿ”j&ÿ‹c#ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿŒd$ÿrQÿbFÿcFÿ_Dÿ]BÿxVÿ�p(ÿ»†2ÿÏ˜AÿÑšCÿÑšCÿÒ�IÿÔ¢RÿÔ¢RÿÔ¢RÿÔ¢QÿÔ¢RÿÖ¦[ÿÛ±oÿá¾‡ÿæÉšÿèÎ£ÿÛ±nûÏ˜AšÎ•;Î–>                                 7(    šxArÚ»‹ôìÕ°ÿãÁŒÿÔ©fÿ±‡Dÿ”l+ÿ‹c#ÿ‹c#ÿŒd$ÿŒd$ÿ†`"ÿhJÿcFÿcFÿcFÿ_Cÿ_DÿjKÿ¬€9ÿÓŸMÿÑšDÿÑšBÿÑ›DÿÓ OÿÔ¢RÿÔ£TÿÖ§[ÿÙ­hÿÜ³tÿß¹~ÿäÅ“ÿäÅ”ÿ×©`ðÎ–?�Ê‘7Ì“9 _'                                      _F ( ²‰IqÞ½ˆñëÒ¬ÿäÃ�ÿÜ³sÿË [ÿ¯…Bÿ—o.ÿ�e%ÿ‹c#ÿzWÿbEÿbEÿbEÿbEÿaEÿ_CÿtV'ÿÈ™NÿÚ­fÿÖ¦ZÿÔ OÿÔ OÿÖ¦ZÿÙ¬fÿÛ°nÿÝµwÿßº�ÿâÁŒÿáÀ‹ÿ×¬hýÎ™EÊÌ”:PÊ�6Ë’8                                                 œs1 wQÏžP_Þ¸zãéÏ¦ÿçËŸÿá½„ÿÛ²pÿÐ¥`ÿ½“Oÿ«�>ÿˆd,ÿsS"ÿoP ÿpQ!ÿwW%ÿ‰f/ÿ«‚BÿÌœPÿØ©_ÿàºÿà»‚ÿÜ´tÿÜ³rÿÞ¶xÿá¾†ÿâÀ‹ÿâÀ‹ÿÞº€ÿ×ªeüÍ™FÕÇ�2xÄ‰*ÌŽ- ¿‡/                                                         Î˜B Á~Ñ�K<Ù®iÁåÆ–ýêÒ«ÿæÉ›ÿá¾†ÿÞ¶wÿÚ¯lÿÒ¥]ÿËžVÿÇšTÿÇ›TÿÎ XÿÖ¨^ÿÚ­dÿÚ­gÿß¹}ÿçÊœÿÔ«jóËžVöÏ¤`þÐ¦dÿÕªfýÔ¥\ôÏœKÜÊ“;«Å‹/bÃ‡)½�%¿„'                                                                     µz# Ö£R Î™CÕ¤W€Þ·yåçËžÿëÓ­ÿéÎ¤ÿäÃ�ÿà»€ÿß·yÿÞ¶vÿÞ¶uÿÞ·xÿßº~ÿâ¿ˆÿäÄ‘ÿéÎ£ÿá¾†ïÎœL`¶'C¸‚,`¹ƒ-eÁˆ-YÅ‰+=Ã‡'Á„#ÈŒ) ¦g                                                                                     Í•= È�2ÐœH0Ö¦Z’ÝµváäÅ“ýèÍ¢ÿéÏ§ÿéÏ¦ÿèÎ£ÿèÍ£ÿéÏ¦ÿêÑ«ÿëÓ­ÿæÉ›ÿÞ·yåÔ¤VhÊ‘6Ð›H                                                                                                                             Î–< Ê�5Ð›F&Ó¡Qj×©`¬Û²p×ß¹~íá¿‡öâÁŒùâÀŠöà»�ëÛ²qÎÖ§[�Ñ�K2Ê�5Î—A                                                                                                                                         œ= â¶S ÉŽ4Ï˜AÑœG;ÒžLQÒžLXÑžKPÐ›G7Î–=Ä„$Ç‹,                                                                                         ÿÿÀ ÿÿ  ÿþ  ÿ  ÿü  ÿ  ÿø  ÿ  ÿ0   ÿ  þ0     ü    ?  ø      ø €   ð <    à     à     À     €     €     €              0    ø     ü       ?€                                                                                            €      €      €      À      à      à      ð      ø      ø    ?  ü      þ   ÿ  ÿ   ÿ  ÿÀ  ÿ  ÿà ÿÿ  ÿø ÿÿ  ÿÿ ÿÿ  ‰PNG

   IHDR         \r¨f  € IDATxÚì}wœå™ÿ÷�ª.moöº¬;®‚ÁØ„ÐB	Ž$€Ó+I(ù]r	wÀÝåîRH%…�5	�\$@(¡0Ýlã¾öö¦®éïï�ÑhUFÒhW[Lüý|ÖÞ�F3£yž÷y¾OŽáŽáŽáŽáŽáŽádªOàÊcÃõ÷‡˜Æ–€ÝkFOTîO©çŸ¼Cžêó<†£ÇÀcÃõ÷‡hMÝ¬P °ŒaÈ
Ý �„�v AÏ¶k­srCSƒ°t
,Öºß0èÖp4ºÝxðW»Ž)ˆc°Ã10‰Øpýý!ÒÔ¶šg¹UA7·VÑéJŽeæNÆgkºñ¥t;�¥¤gŸúâÚÎ©¾Ç0õ8¦ &–À‡<âûŠÓ8–Y5ÕçdAÓ�7‚¿‡#w?{ÕÉ[§ú|ŽajpLTº¥�ã„KÝ{CõSŽgªy|.ïÓèø�©éÆþ”¢ß¢iÊ=Ç,ƒ,S U@–Ð_:ÖU>äâpq¹9E!77ÏÂ#0à¯À‚gí¿.U§H(:Tƒ"©ˆÊÂ)IÇ`BÁHRu¤(M5t0wG¢Ñï³
þ1pLŒ®¿?œ5ç ä“ËœZÉ{¼<Z"š¼ý"¼|Qá®T�b8©¢'*ãHTÅ�á$Í(ùô�ýÃá?¦ÞÝ8¦ *Ä)?|nE0¸Æ-pç8eè›}<f×ºÑr¡5 L¨°;E_LÁ;ƒ)ìêO",iE÷S5ýÎè¡_yæÆÂS}ÎÇP}Lý“x”à¼_o½ÌéjïâÌ«saN­í5.xÒ ªN¡Šf@5L›Ý0(ô"æ;K †!àók8Ó]¨DÁ$U=Q;ûSØ3�°u8†IŠvÕƒŸXq÷$ßöc˜`S %°~Óf±ö²k.!7–×¹8K=XÚìÅŒ ˜`;$UŠf@ÖH…fPõ*°yYpó&gàáST	%ÕQW@Ñ¼ÑÇŽ¾„­‹ jú�#wÿ3Çr
Þ=8¦ l°~ÓfÑýOW}Å-°Ÿ-%øæ7x±¬Ù‹yu.pì¨�¥T=ó{R5“4HÍÙ>Ùpó,‚.6‡PÌV ,Eðfw¬À"Ðtã�X2uÁ±hÁ»Ç@,Á¯ñ
ÿ\Ê¿¹8¬žáÃÊ6?Ü<[ðzJÕ3,üT
|)dGÎÞ:ˆIžÞAgXÊÙ®éÆþX2µñ˜8úqL¤‘öñKšúóëÜXÓ@G�»à5Kè“ê¨9_‰ð«…®›«±F	´ôï¥\	 ÿŸcp„‚e™Ì6'ˆ+|ƒ:/¯ÀÚîóv_ÏíÉ±Ž)�wþáÀ©?{åô€[üv±ø=G€%Í>œ<'ˆ:Ÿóš¦ˆÈ¦àÛùðÅ€¤ê�4“ðÓt
Å¨®ÿo�·E
º8o/ÜqeÔ9‚F/¿‹+Øo ®â¡]CH(£×¤éÆ‘ƒû7‹½ø‡U º¥½Îïù�r¡ÝëV¶ú±~N�<�ˆJÂ’†¤R:–®’ª9íû+šQ•Ì½±B`Ü<¯Èf¬„¸Í5øÍ~¡À5H(:Ú9„�„šÙÆ€þñW,ûÐÔ]Õ1Œÿp
Àòó½<þÛ.M·˜à—[í³‘RõÌ*‘§'ÀdLþlò25n-1g›¢¸ÿ­Á% iúåÇB„G'þ¡À)?|nE(¼­˜¹¿´Éƒ59¦¾¦H¨ˆH¥9¥êˆ+F�ÙïtÕ7zÚ÷×©ù+§Ù¸œåû3 K8–K(Æyé�aˆÊ¼‚°#4EŽ`fPÌ±ÍÀ}Û2	Dšnì¾ë¦%váÁõ›6‹ÌyŸZÔwh_jœ+xõº®µ €¡H�ùû3‚« X–ëQ’ÑA—7Ðçóˆ½„»�ñÕÇ?„Øpýý¡š9s¿É0ÌWí^o¹pÆ‚šœÕÎ‰à[+}¬„+ é’¦gÓ0L—@Ö)4ƒBÕ�LP5`%ñ,G rÅk,`¡”"h¹G-¢pJÃïßìË(·XJýÚãŸ]õ��?ÝÒK©TM{Ç«´TlÙX¯…< Ü¨2¦”FÐCšª¼¡ËÉíõ[i_×+Ç8ˆ±ã]¯ Ò$ß/ìØý�‹Ã¦y!,möe¶•|Í�é;ZM§N©�4Šdº`g²a��…‡gr”Q¶°Ô¸ù× ÁË£Á7*�ïô'ðøÞ°ußöïÛ€åD×¬j�7ë	:Ú�Pc»¦*oð÷„ßÍ?sÌRpŽw­X¿i³XÅµÿi·ês8af ›:B™‡ÜòñâªíñŠ™øvˆËd�"&kÐ)ªºÂW~��_ä rÄV ¦kQë.Œäó~{�a	á„„¡¡¡ª�cþê_	5¶SÃx8àÿ¦ýáæg�e.Ç»R”òõ["ÎYT›óG%	µh(/œÒJ
°eæGåâ
Â.ãnªaE6a?‘Aƒ/—Ì¶Â)¿y£=C$ñ²ŸéxE^vô~
<%}ß:§KHr�ªÜ3JiÔPåûkÞ»�)ƒB¼ëÀy¿ÞzãŽ|†Ÿ#ÀÆŽNœÊlK©:úb
$–.*kHÈ¥Mö¸¬•úlLG ˜¡=Ž >‘+ªD– Ù/ä¸3ƒBÆ:xl÷0ž~»’¬d^o¯ñ èá9]Ü‹¢8–�O0÷�+")1YÇ@BEXÒNH§4GÇÊ†¥”pÿ­;ÿç’ç§úÞO¼kÀ†ëïfÍùÏ±Wä¿ÖráÜ%uv¿”Ÿ_nÅW41YÏ˜÷N1ÝÜ Ù‰=ê½<Î&`£æÕ¹ pz¢2~ýü^´´5Ô¡ÎËW”�˜�R‰K$UG_BCOTF_$itÇuFÓœ+B�ír<|g�¡üê™D|W(€´ÉÿÇ|¢ÏnÕ/fî—üJVûb(fÈª=…šˆ"ž’AÔÉÌ¿W¥DÎ¾¼Ë \.x!PÁw b�)†l`ÁêN”�|%à´×¸ hvõ'Ç|_
>ßÍUüÕ è�)8‘qd ‚ž¤3‹Ë²
‚.ö²ÒQ¯ ÎûõÖË\÷Ãüâ�/�Ž«ÏøúÅV}Í00’*^´‘tŒ$•ŠVûbHÄ"ˆŽc¤¿R¸ƒ±”èŒ<!/B¬iBSC=¼¡:„ZÚá	Ô”?'Åþº]ƒZŸÉ7°àX4û…Ìß3ƒt
tŽH(‡låªeÝP.¦ä’cþ�qÅÀ¾¡ÆŒÎ°ìè€,!OÄûÝø�äÕ
à‚Û·}×Žå_ÚäÁyKê3+UJÕÑUrV}+œgÃ×tŠˆ¤UlæçÃøD4ŒÃýÃP#�ú'/BÅ¸¼hm›ÿÌ…¨ŸÙak%S €iA5úÅ%Pïát›î”È™=¬è‰ÕÐ$¥QÈšÍ Mw|ýâh¨R`8–”­g(‡¸b`÷@o÷Dq,!OxEæ;OaõãòÅL#•
`Ãõ÷‡::þ7?�Ÿ#ÀY‹ê°ªÍŸÙÖ•VýRßPB³à«ŠŒ�á’ƒ]8Ü?C.4‹“]{@õÊ	¬ñ‚°Úfw eÁr[FCõ¥€uOí”À¬�˜£`‡*ªUÙr•6ÿEŽÀ'rf£Ô¬š§è‰*ØÑ—ÀÞÁ$ÊqÿÁQ§ :>wóÜãÖžò‡ü_ÈÅáâå“ßŽá/eî�ÕÔWƒ½ÝéïEÏÀ`Ùý•È ÔÈÀ”ÞCÎÂ‚«Ñ4yÙæ €é4ú„œmÙ®Àî�ä¸ x–�·Â.ê"GàâXø]\E®ƒ¤êx«?åÈ*`	yÂM”¯¾9‚£J´žÿ•uKO9û/¾†¶n­ZÖ�Ia�Jº£JÎ{­VÙùˆË†SzE°ªS |dŸ#¡Ï†¡iHuï™ê[	 àƒ˜¿t%‚s––Ý×Ž´¬€½åãÿNàY°d|�¤_4;UB$îêObkOýÑ2<†®}ÛüŸwSÔà¨Q /žô¾ÿyð�|á_×ÀûÔfþÎ7ù5ÃÀ@\-0÷ÍÀ`R«ˆÕOÄ"èîîÁáCAuÕñûò‘ìÙªN�|”Ä¡˜µj=:Þ™QnˆI³/7DøDû†Rã>– ~±rö¿ü"‹:ç˜;80œÂË‡£%¥4ÊRýÊW¿ºþ®ªžìáèP „|xÓ·îÿmhFGfG€óŽ«Çª6?T�BÓ‰È9&±U(�PâÝ½ýcZí‹A�‡¡÷LáEâÐ €«yÖ^òEðþâ‘ƒ|W€cLËàp¤P™Y„«jPèEB«lVGc�ÀVlþ;Ç2ºL«À	gp`8…ç÷—tÞ-nÁ´W „å>µéßî¾5ÛLuq.]ÙˆÅ @DÒp(,gºbR5Ð“ùùªN1Øu»öî·%óÆƒéäX
  Ä`=V}øjøêš‹îŸop0œÔ i$Í¬lKÖcÐÅ‚#€È³9ÅKãu	
?‡C�›ud¼Õ—ÀK†m¯‡ã8øx€eØ¯¥~ÿÃ­)ÆÓ[ríi7üî{ÙÂrqøØ	ÍhIPICwLÉtç)fò÷ÇÄ4çP·™_©þÎªÄÿÇ}½¦‚cD9	¡¶k7¢Çc»>Ð–ÊöJ(ž¡ðöæ¿¥<<7ÏB¬ÒP§î�jP¼t(Š7�„GÏ‰ãrJ¦ãÉÔv/«_~4ZÓV–¿aý?ßz}Ãâ2Û¼<>vB3êÓ)½ƒI5Ó™Æ0(FRZN§Àùª?Y‚Ÿù¼iâd[ Z®Äq}ÉvŽ ­A ³QÉÎ*d zxÆñ0«n¡Z.ƒ[`Ñä-¯Â)Ïì4:Ã2ãw‹¯³ÐÁ2ì×ÿìªïŒû¤&ÓR–¿aí—x}ëª™m­ŸZÓ’ùÒ{b
†“*†d„?¿\×‰¯o™ú;wížÁÏF¢sç¤~^6¨aZLRÿÁLÙ-ÕÔŒ»³âÂÏ#[ùf£5`æôÇôÅÇÏ‚®±%ød1�×2pjôD<{`)Õ~EIJÊžpÏÅGK¤`Ú) Âò7œð™o]?óÄ³3ÛÚC.|ì„fxyŠAÑS2	,†AÑŸP!§É?M7�PtôÆÕ²¡½žÎâã;…<Ü-žÔÏ¤†CMMF¢º]N‚=Xÿéëm#Í>:ö•Oÿ-‡Ræ%pqB.vÜ‘„ ‹C½Ï¾˜)àâÀ³IÅÀcï�~hæ‰~éÑ�I86Õ;A ,ÃÒ‹¿|ýœM—d¶Í­uá“kZàæ
…_Õ)úb2²9š„¢£§ŒðaÏëÇ¡#Ý“¾êç\/a %"“òYÔ0`(IªÐÑ{CX¬èçöƒ=`xÁÈ	xƒuÄÛÐZx,tG%tüë‡‹cÁŽ£rÐ‚fPÄQIƒf .ž3QÖŒ$5p�+K÷¹y6ó7Ï,¨w£ÎËãHDB~.Cˆ„¹|ÁyŸKíÿË-/Œûâ&ÓGríâÓÿé¿~èË™MóëÜøØê�bPtŽH™Ìµ¤b /®ÂÈ2bâ2†S:B@)E¾‘¦*2ìÜŽÝ;ßBR™ütÜ|0œ`Z tb{šCN>¨ç�uyÀð‚ù#¸Àº¼`<A†„ÐœãFïŸnæ÷G$£*Â ž*þä\+ I30’Ò`ÐôÀ”1(˜¸b–|»9~_pž„Ô{y,lð /®ÚÌ:ÅéË?ô…¹�±Ô#�¶NËöÐÓÃ äÃ­+Nþíš/ÿ(crÎ­uáãyÂo1ûQIÃH*g@zc
d=?Ùg´¥§óÀ”øùå0‘©ÁÅÌ}Îë	€duæ<SðEOÎ6c[Î{}ÁZTÕ2ÿË!äâPëáÆR9‚9µnÔ¸90E‰aP¼x(Š—:£¶¯Ç“©íû�éØ«pê aÎt¬|ää¯þ"zj¹ðéµÎ„?¥êè�+(–Ò>8<Œ½[_Á`lüÙj�‰Ê	(&ü|°¬8:ÚŒ°<„`}Žà–‡PÛ&¯'_¨®±è�± ö¿¨TX	D€é´„’ç»o0…Gß²%5ƒ³jbÓtNLê•C–_&Ö¶ü~Ý¿“þfŸêË~Ã J¨9ÂKçüÛ	¿fPŒÛ�Œ`(9õæ~10Â‹ã?Pœ
? ˆµ-9ÂÀVø=^_U…Ÿgè¤
? „%�#’ã,Ðì0cJÕ±o(…¨¤Á(’ÙØQïÆeÇ7£Î[ØÌ”cH­Î{Ÿ<õg¯œ>©]SÆN˜Iuõ¹S¿~k] ÕläÓàåñ©5-ð‹l�ð[a>‘”Š�"‚•4lëÄ`$NÃ‚uû¡'"îk�ýfè©êÔ €¡$…ß_6ÝMÈ‚XÛFpåîh ë*Lry¼à¸ê™ëÕ"ÿ*¾70sC’ªŽe QBA—iT’�˜lŽxó	,ˆ�%!rŽkòb0¡b$/•˜!ÄÍzyÝÆ+öw?öëm“~ñ6˜€ñk©¦þyõç¿Ódeùy;¡AWVøâ2‹ÿÁÁ˜ñú¾n¤¤ÑÌLVô@l¬Z»úªƒuùÆ�4M)~Fp¬òœ'P°�°<8oÀö¸¢X]+e²Wÿ|Hš�î¨Œ�„š™ÄdÁ/²¶Âo!¦80,�É³ç-©Ãê™þ‚×t°ðz½wž~Ëÿ<¥7 �)Q F2rÇâ3>¼ÂŠõ»8&“ág…úŠ	oL±íe¯h:¶ìÅÁ¾Ûkâ<ˆÓS	0&ouÌP_!×Áês? à¼¡Â{d³0C5Á3Ó§9ªå$Ò±d·ÀEµƒjPt†%D‹¸CpÊÜ6Î³/®R|{:(�IW „åo,\û�…ÿôÿ2R|éÊF´ÍÆŠóÛ	ÿ‘°dÛÁ&šHâµ}ÝN(%?›Ô�ó×a:‚óÆ}Cµ~]¡ð{¶C7˜<~À‚ÈUwµæÙé} �ÝQ1Yƒ§Âôâî¨‚¡„Z”8¾Í‡Ž«·}m:(�ÉU „|XÔ\¿áËßƒî;wq]¦ª¯§ˆðkº�#a© Ì¤Mþƒƒ™LÀrp5Îr<rj2ÁûB ìØ}lj¦?a¹3@ ¤Ý„"“xN@51Õæ¿8HÅÁá]’²1�PÑ•K’ƒ-·� Lµ˜4@X~(½eõç¾“©9_×ÀúÙ¦0&Í¼};á/ã/eò—‚«±ÝV0¦¬{ì\€ÝêÏy‚«?ayÛkgÆ8†«RL'ó?¾t
±¤Qì–—+‹Å‡#JQ%0«FÄEKë¦�˜°~Óf‘êÚ]Ïû¬ß*0™[ëÂ9‹Ms<"�VñÅ½¬ð§To,kòay¸[:ªîÛŽcuìV ö«3ŸpÕ%ùŠaº™ÿ€I@çãHÄ4í+AJÕq`X²1 m!WI%pÂ÷ž¿|²¯}RÀóOÞyK`áš‹/øœ˜	—®h„À$TÝ1S�³“|Š	4‘Ä›ûsYþ±€°ü´‹°.ï˜Ü »ÕŸÜ«?P\ÐÇ:ˆ³RL7óß+ï,<�PÑ–sf”ƒjE°Æ ¼^ï�“�'0ñ
€�óÞÀæuŸûŽg8|ôø¦L¸¯'j
rR1r’|ì„¿R¿¦cd€ó•æ‘�b«?[ÄÅ)jŒƒpŠéfþ»8¦l‹°¤¢ãHDªˆp¢Šƒ*eï9å‡Ï­˜¬{0¡
€pÂLPzËÊ+¾™i3uÖ¢ºãoÅúU�æ4ò°#üöt�Éß/>P¡¦yüªŠ…âŠ�EÂPE )Jô· ml®V>¦“ùÏS8�¤QŽÈUU³jD[%`enüé–öÉ¸¦ Ò~ÿoÖœã·âýK›<Ò¯'+Öß5çóW~Í ØÓ=Œ®‘êeÊåC¨m�6‘�JSƒíŠ›ËÙšÿŒàvrÈ	ÁT¤þƒÕH¤¨ºIVÒï°œè¨wãôù…Ç�Ú¨¤ÿeÃõ÷‡&ú^L˜xá™ßþ‹+TòºÍ_`úý.k`’~ÃI5ÓÌCK—–Äåœ8¿fP¼ÝÙ7¡Âoa:Ex¿³Š»¢äo/èÅVùrdh5\®é´úW*üÙè©,B`)�bÑ�å­>¬k/$}÷²d¨å¾‰¾¢ Ë/cþmåÇ®Ï„ü.^Þ /ÏdH?†!Ii™‡+’Rs2ü,á+Ó?†sž6‘�ñ¦3|é¸=ÕÔÜ]…¡g¼«QB=]V;Æ¿R‰(+�R!Âg°¨±pññ¸„÷Mtx°êjyý¦Íbçþ7®?áÌæ¥ç
 °±£kfú¡]5Kàc’–SØ3ÙÂoÁ*Ò¢Õéÿ?öó``¨JÙá!TW, ªk ¬ ªÊÐ¥$ôTZ"->ªëÐ’1è©(´d$ó£§â Ðâ#™=‡.%@U	†œëò‚c	Sù#cšÿSZx
 4ã_)¢²G¥æ3]¬ˆˆ³çÀÁáyõ:ÅésÎùÔß>tëþ‰¸'UWË„åoà\žëÏüÎ_ÀûkÐìãñÅ“f@`zb
Â’U§™Ñ]ÖäÞì5ÂŸ5:yàÐ”}>P¾k05èRZ2šÓÌ0ËyíX}Þ_g›lDX®ÆÒœ“PÛš‰ –‡È0œ ·K,k5MvÝ¿\ã˜ô«3‚BE.EÈÍåŒWÏFTÒp÷ë½ý4ƒPWMDC‘ªÞËô_vÉUàý5àpéÊ&ADÒ2™~é§éúãÓKø�é°K¦†CS Ë	èRòÀaè‰HASÓJCzNL|šå"P]…$+H&âÂ`/â‘a$qh6½ß­Â˜î@%Ä`8¥- 
¸8œ¿Ä>2Wð¿qþU½+ÔÐêí8žÌÞx1 `cG-~Ša†ùòI¿ÞØh3�é"ü¦Cd€uû2B¯%#Ð¥%5öñâEÌw«Ex)P­´;b)„ðP?†††�LÄAuuÊcÿ•„ûÆŠÎ‘Êòº£JÑRâ¶�ëç„
¶OPµ;CXîS ÆÉ'lþ ³³Ï)&h•÷Æ=CúÄåœpßt~î–Ž)‹šÂò¡ÏG1%0–ó%“³ÂÛA—�·T£ºš±"±"’^46‘K¸o¬8©,c°'*½'«gøÐ^ã*Ø®øvµ“„ª¢ O°–êÚ.>ã#°x~hycÆô�¥ý~+Ó/–E f’Ït~“04†¦™ä›&ƒÝEÍyRåæ¦åÜ€±FdÊb$žB×Há„4©Š@t8¸PuŠ#çsTÃäÁì"CpÎ¢:¸ùB×)¡³w­ß´¹j…UQ F2úMÞlšûÁ« ˜U~íA1cúÀPÒü_ÓôgeýŒ“ç+ËÃÕÒ1þ•@¶Ðç›Úœ¯z]xË�C9Tb …ùá”†®‘ú#É	oË^MÆß)$�æÚå�Rõ‚¶a<ƒ3ö®ðyÜË’g}úÆj�ó¸ aùe,Ç]½ì’« z<ð
,Þ¿À|híLÿÞØèêŽH’Þ[m°¢®–yU?n¶àC±¤ MÃŠlŒ¯5½!U¦¨‹YNIÕ@Tš0Eà$Ç¢•´ŠªjQ> £Þ�e-…Q›�Ïõµj¹ã>ª«ÿåjšMÚO¾À €3ÔÀË3ˆHŠžcúgûýQIÃ;Gú«q“Î¨ZdÀ‰à[`8~RRx�œ‹Q�Ò!,_¶Âp"ÁD2þN1�P+Š”j&²±#”3�ÙÍx]"BÁàmÕ8×ñÝ)Âœ	àË.¹
Ç3í!N�[“¹	Ù!¿”ªgü~EÓñÖ¡©ŸŒ[)„ÚÖq·s*øÙ¨´B°JEœ·Y•ð&ÙŠ`<Ád0þNÑuN
ªéè˜x–àýjÁ±Lz6¡ÉkP�UÕˆ
ŒïnQú?�yÇÃšâ{áR3†™Pƒ¸¢C£$'Þ¯»ŽT­¤w²ájœ5&¦ÝZõÇ»F!åXûŠÏÏ¡p;åÆÒ_ ©²°â{4‰Œ¿¨:Íô¹p‚pJ+pƒ‚g–4ypB[¡+àåñßã­» äÃ ]±âbs–ßÒ&æÖš¦ª•è ê"G0’R3ñþ½#Ó–ñwŠJ"•˜ûÅÀp<8‡9	¥&—Š÷SÃp¤Tœð ã�š„SŽ„+‹L'á·�TôŠø€|WÀïâ2dæ©!¸óš³ê„c|n×ŒçÇ® (ý�ÀÂµhX|8œ—Î`êM›üé¹ñ²F!kôÇ•I©ì›h8�š6.ÁÏçåžÃVØb½€t.€ƒPŸ aSMÓ[Õ(ð™($TÇIB–+À3!—Cdz'Ïµq	sÅxº�Mòa +.ü< à„™4ûE¤TIÕ@BÑ‘Ru¨éÿ\ƒ¶šêÁ˜J”ŠTcÕÏç	Œ»kO9wâ¢”«tBþU‚pJ+ÉLE¸¯RtG�=å®cE‹6cÇnñÛc=·±)€¼Õßjî9˜Ì�ùÆÕLnxRÑÁ³3‚X2«µÞê¶šž
Øµ«æª_øyÎÜ€bdÕµ’n€S–_O„‹¾6IS7�)˜Êp_%�4ZÒà¿ÀÀ+š–Œ%?vØ4/T°�‚¬:ï×[/Ë¹U® òVÿg9sÅ×)†“*T�BRuDÒ\@B5�­Àý"‹ùmX0£±êC'&ÙÃF&Rø�Üh 7ÆU––È¨8‘ÍEû£RÆ%˜NŒ¿sÜ<¯È‚Í*—NªFÑ¦í!:êlÂÂ„Œ)9¨ò;Hñ5ß¬ã2«ÿûš‰*ƒIjº§?`¶ü �R¨ºýªSãáqÜ¬–£Þ-p5Îaù	~ %Sƒ³Q*M¸\��R$bæEÜ€ÉH™§4„Ò¤¦ùV½ñÑ{ææY„Ü\Ñ°”ÅpêÜBK�‚Ì‹P™ Ì™ ]±øìÍ Lß?(rˆÈf®8-üá¬N?I¥tö™åßÑzÔºjt| nRzë[©Á´„°i%»û”N¸qª´s&«pJ‹�¸Õ8ºBÉIÅäÈüSÖòUÓš¶C­‡Çr›Arc¥u•Z ßpÕ4¢mõé€LÊoTÒ 4ó¿Eüå›þ¥À³óÛ°dV3Ü®ÉR1^P]…`öÛw5Ì˜ðÏtÒ/°T8¯\‡_Ç<@ž0YS.Ñ\$Rª™w4)�À".k9æ~)ô'Ô¢×·¶½pò0™[{Ù5WrNŽ€9ÚË8yþ—ƒáxfy‹õÞvõJ›þ¥àY,o¯Çì¦c:óTW¡%¢¹÷ˆ!6Ll7g+5x¬ª«¥‰@%å(€êjŽ˜àásI?M7Ð9"Aªp–ßdÃÅ\8†@3€þ
„ìrqE­€JÎÍ± ºv-ËñtöÉ  6u„ ä®þ’:šøPÎô/‡¦ ‡™®ü€�ð[`]>µ­úùXÌä.™¤k%‰@Ày¶Ÿ•TíÐŸí5sØ"ŸÑ‘§¥àYSð.—¯LjÐ.ŽCÉÊ­€J¸ G
€ñkzaûúóï¯A{È…¹µîóo%ý¥{Ê:ulú—»�3‚X6§eÚð¥„ßçU<à£8™!XÊ×/Gê«þ´¤y&zõç8î2¤ßtR<KàØ’çÜ—p^üTÊ
XbÓM„\ãôØŽ€‘Š~€nºÕ—ÅBZÌJÕ!©:b²�šWžÉ„§’p"ü„ÚVÛ1ÜÕ€•\jÕÕKX†Z†¨ èGKD'|õ/'üº"SOZ‚Ï•ÉOÈ&ÊË¡”°Æf¦ Yå´\Ø™@éç½móœ³^�Å	3™ÕßÒNÖê/M`‘O�‡ŸR~À©ð[fMXd€ó…Jæ”$ÕTÙ>€N¯u¢CŸ~we÷oªˆÁl?ß)âÎï]1+ ÁËc–Mû°` àÈ
(« ^<	@ÇÜ“Ï ¼7íwDò|kõñW)¦‚°ÌÝJ1Q‘Î Jô	7PAó'¹c�ÅøWM7*¬ñ¢˜ŸïQÙplë$ ï±©da\æ¤R°¬0TåÓ `‘'Î0³•bé“²ü™ñ• “?0»~Âù«÷þX0‘‘¾Lo‚’õÿeâýN¢V£’±*ÇRÈgü+�"¬¼¤¸âs,ãç;A©´ßl¨-šØQçFÈ�Ò	Çpœpi¹ã–T ù×ºòðþÌ¯s£ÞÃgrþGRæêŸRÌÕ
¿‚Ä	M+Öåä¸kï'*2ÀùjJ&ß”äLü-°fR¼ªý	<<S”ñwŠ”Z\`Æ‹±˜ûÅNU(‘x|k¡àØÏ–;fI@åÄ… üm'~ €9Ã0ÍëæZ¾ÿd®þv¨ñðX9·³›jªæƒP]…Qa#Ìbà¼!ðÁ†ª^3+ºÁy‹•ä”TÙ¤­DÑO~›2-©Î}*î«C	µ¢~å`	þXÌý’ç™tvŽªAs†çfÃn¶ ™[®T¸´0Œ+XŽ§�+N…‹cp\“‘ôÍ÷ý§bõ·CSÐÃßÑ:n~ Æß)ø@CÕ#B¨©èkå|órn€© í�‘?i¸T… S8	÷UŠ¾¸:nRÐ
ëU[ð-Tb©D${àX,l(ä„ü.¡dN@Q@8a&Ë²ëk�?=,mòÂÍ³H)zA³Ï©^ýóQ�²ãJ[`;Eµ#e­Š!=]N”�¨ñpÁ¶bMJõqZÕ~ã!�†õÆÍ(Îòç#*kEÚqM…‹ã²RõE ÕÕKtM%³ßcöû[•f“ªaNz1("’6­Vÿ|XeÇ•†«á÷—‚«aFÕ” Ãñj[Š¾®Jã‹Ø‘�L]�ŒýžŒ�ñwŠ±ðÕôó� ’ÖaÅÜ€Ž:·mÛ°Rõ%\ r~¶ù¿¬Ù—“øci¬é¶úÛ¡’°a5ýþb œ¡¦iüJ£œP* 'ce�ŸÍ”kQ>+`<Œ¿S%TG™‚åç—ƒ¬Óª„í¸ �c>Xl[Àx‚µ,Ë®oZzbÆüÌÖÞ–ö‰HÓË÷/§eÇeúç£š‘�rn@©h€.ÅÊ'e…A™2]¥V@5§N�|L´ŸïNC‚IÕ(ê,i*\ä4M»`Ãõ÷‡ìö·U TN\¨k*i^µ€iþ[™QIC\1 éÆ„fýMJ•O´éŸ�jEÊ¹e:ˆãk‰°ã%N­€j2þNPÌ˜?ß	*‰XÄŠX­~1W‰é„c‚³æ|Àn{ kç@ýò“Á`^�‰´ÖQuŠHJ�´¬¿‰B~Ùñd˜þvàU)*eM”s´d¤¬P‰e¤FÊ*�‰`ü�`(«Æ~²ýür¨„)±ß¼ºÂÔ`
Ø†@š1Üàm›_]3æ7¤ÙU7§ü1Y?*W;Xü@]`b
wœ@¨m7)(Ö4•L
Ò¥WårV +º¡Å†ŸO¹¼€©~	EŸ?ß	œZªA‹º
Ÿ·À�c·o�xþ©»6ð·/] XÜ8ZöWt$d“0Œ£wõ·ƒ×ÄÌŽùà¼åKm'ã�šZ2)h<V€Uî«K‰Š:³&’ñ/Žeàæ	T½ú«ÕBT6gsZbA4 ¥uvIA…. ¥§@pÉI €¥Í¾ó$¥V­ÞºÀòy–E{[+šÚçÀãšÜ‡t¬-Åt9-…¡¤JFÌ}K'³XqÔ÷WFúŸ›jc1¸DaJZy»ybFÒ³õFnS�˜âLÄ‹Dàx† Ý¦B0äßŸ¿ÍŽ8 æ-GÈÅ¡ÞÃgÌI5Ç|+ÚôÔžcAR5
†Nx]"šÛç¢©¥eÂkÝ³QIá�%øÙÃ>ÑSº6 Œ %#9+<5Œâ�jrEƒ²­€É÷åÃÍ“œ¡šRÚôµœº¥¢µ…
À ¦lg#G0ž`-ËqË½móÁûk21EËü·4Ó»iõO”Ècðúƒ˜1k6|µõ“v>¬ËW22`hj�à[ S6¿ \åžÉüÎð¢mØÏj„êÊH/€É÷(˜¦k‡éjXS´� Øó;»¶0bCAVå‡s€‘Š­Ñ5•Xþÿ‚z·Ùô3mþÇeò»HúíVÿ|ð,‹ÆúzÌž5kÒø»È€%øåºõðÁÆ’¯ë‰Hé2a%•Yá³MÿlPMv¬¨&ƒ×S“*ü–¹_ÓÙ
°¸¶rHq¼[P" ¤©muöß¹w)íÿûæ®`j+÷ÿÝhþ'*ÈbdD·ÉL’[�ÝRÌÐTÇmºÊå å¹ ->\6æ¯%ÂŽ	AIžœiÐÅÌýR˜®V@Ä¡(¥ÀæÔ’Êù<@¾š< jŸñÿUƒ"©ˆ)ÆQ•ùWªN+?mÁëbÎÜ'¶ó/ 5Í04Õñ°ŽÌûj[�Ó�ÊY€³!NÂ‚ŒËCS!ÙUc|©iº¨¥.N¥Â�3Båy€ŒX¿i³ÈrÜrÞ„¯®í5®Lø/¥êˆË¦IÓÕª`¼uâõ¡ fvÌŸP~@—S‚ Leó[XÑ6Pú¼Jå0¼z2Zv…×¥DIN�qù2ó’‰ô*gY:ñó� ,M? ëÔq8°˜%;3Xh0T_‘]˜y²þþÜ='èšJæ›ÍDçÕ¹ ¤¨}×™ÿ©*$2YüÀD„µDTWA8b“Þî¦9%­ CNÚ–
3‚;£pœäõ«‘[E‘-ü™}+´dJ^ŸC?ß	b²mNr,ÅØ¥3ç}j‘õwæš² üí‹˜SHSŠY3�˜fM?Æ‹˜CÿÊ)ª6´„ß#zÀÊ¦ëfƒuûÀ”'.Gs\Âr`¸QEFuÍ¶@>òó'ÚN.ª†0s¿¦cUkRuö}—âZ…SR#Ë­ßGU(Å2 ´u  ZüTƒBÒL+àÝdþOÔ 	‹�[�/ü8o ¼/TÑ±<m2Ó{ŠÞ¨+Àð…ÄŸžŒ–�ûk‰pfÂ‰`Äâb<î¼Ûp6&Jð3çUÅÖaÕB5x€¶À¨0°íY¼ô“«ÿàzøÖ{­mÙjz% øg.Dƒ—‡›g¡êŠ™$ëïó¬ä_%h¬¯GMMzzû*j+¦Kq[á·À*Š°n¸`#Œd(2½Çt<`�E¹->R4$˜¹¯Ñ!°3J
?`F I„àr6I˜c™ª™ú¥`‘�Ó©>ÀâœU4¼Pxî!7‡Þ—ÁÛÞŠD×ÞïôÚlÇŽF	@ 4·M>>Sû/¥Í‹w‹ù?Yã£*M+¦šìH°…`CE£¸¼³—AO•núQªk`ºJ™¸?ÕdÇaÁdÂ™PM?ß	œúÜ“	§EwrÞs�EñûßÞ…½p-^¿õ›4Ñ½÷« ½6ÿ} ¼ðÌoP]%ÞÆ™`8ž™2	@Õ ™ðß»“=?ÎëámŸ‹D,‚þ�AÛªÉŽ{ë[¤ 4Ðéh†ãái[€TßA0®ÂfŒèáxèÑþ’V€žŒAãø¢s	Y—z2
Öå+kš
EJµÜ<™0S¿ŠŽ:Ïä%,9='¯Xþ^XŠ"‹â¡_ý ÿ{÷o �ô§_%? èMvïc €ÚR ¶ÎP>ð‰fE4ùx„\x‡óÍ§&Ãü/†RiÅ•v!ª42 ¶.€Gí¢i©i*t©¸¥@ZÜ>ù‡uy3V‰uÖ()ØV­°ÞX¡êtÚE‡¡À”ªãÅîÂ•ÿt6~ñó›é¨ð ½À^r­9ëc Ëß@uõúÅg|‹?úüÛûf ö¥°µ;Ÿhß¼!¥êP4)�BÖt$}Z»
1Y¯z`,Pu=ÃèR¼¢aœÙÐQÇghZOø¥?¶°5£	L¬Mù0ï¯+ï�@XbÝè1'ð| ¬ƒ&'¯._Ë€gè”	~6¼<.nüª8¦°¾ß*¨âY’ÞÇ\�—µŒ~oC	ÑîèéïÇ›o¿ƒ÷BMÅ¡�ô á®ÿåìS/þÙ³W�¼• ªk³ÀÝ: Pïáq8"!¥êÐ))ZÁåæÍVJÙ�‘¦H©ƒšaDÝ$W¦ƒbÐ¦I#‹HÄ¼è>°gÌÇá¼Gî5†iZ¼¤t®c}µ¶Â jl„åsÂ�9ÇJ‡y_ÈVø“´ËÈ‡$+¨©!ÓÊ¢ŒËÚ´Q °Ä”¿|a·CJÑáN�u^uó`ÎüpÏ^�è;9×gRŠVàCÖ•® !Ôoú ªN“4°„‚«àâX~kÿ,JÓ$ŠnDL¨Æ¤·«FòO5¡î–yPcCf-½ò¹“È€å×{Ú—ÎÙúÔs�µ'—:¦)ÉDÁº¼J¬òjd dM+z@Xñ”‚Ÿ³^ƒ“�©zF,açX,1Ï�ÉºÿœƒlPÕ °»“v¼†‹cZ�L � ž†hòñ™ƒI…P%íÌ±‚n>3B.,lð`i³unÌŠ¨÷šÍÙ	*Ÿ*ß¿øùèH¤Ì�¼¿î–Ž¢[9ˆu­Ž"Çµ´ŸåÎèî-}¥zöiš
-1R2ñH—%–!'m§1ÎÌœo"%CÕ§Þ-ËÆD†¼9Y¯ÀÂ+°ˆBnÎt³<KÀ0LŽðK+‹%ÙU*æ›çã	ÖÉˆ ¼ÁZÔºùQß^5 pkžM–1Ùì9ÄS¹r„å!6Ì¯$!uWÌˆµ-�‡{ÊZºAÎ%,w]bßë·z;Ž/š¹hUrÞšK€ð"¨¡C‰–$#µd4ã
0Âò¶ŠjºY’F!ØxŠ¦#,é�4³ŒÜ�SPSQˆ‚�gôûðšþºµ¢È¬êŒí*^~ÅÓ¨³UQ)òŒ\x†ä$‰S·áúûC•“m Àr<åý5¤ÆÍB1(dÍ€¤é¨á'?,RÊ�H©æyUêFLÿÈ]ýóÁ¸[æAéuLð&›/ë!÷”Ü�á¸–™ç~auçý?ù¾tø­kÜsVÝW—“`W)HøÑ4_]NBK„‹v5¦š
->Wã¬’J"%Ãç¦	˜‹…e‹iERÑÑ•0œ7ÄS•d¨±8 +¯¡nŽ % bÁüy<}çÆ|>fªoy9,51àâ
æÐšºY5ô6 pÕ6 ¨ñ™@:%ùÿŽeàwqcr#¦“û¯¨åÓN…šfxf,rÜ‹­(ÊðŸi=ÿË÷IáÁç”#;Kî«Æ†33³…?s-Ñ¡¢VG%uùÑTÂ²£’†þ˜Œ¸¬9VN‰x;wíÆƒ�<†×wìªŠë©9<F©Ï
ˆ…rÌ®F†0Ì `ÓNÐÅBÓ$U#Ã<Nw¸yA7�f¿€Y5n,nòaQƒ³B.´DøEŒœp¤$gÃ*	ËÃÝ2¯¢	Bœ7àˆK`ö;ŒÛA¢ÿð>¥ï@É}ÕØ0Ãeõó­Âñ`=�ŒòrÒ=h:qªNÑWrêx–@ å­H+"C5;wíÆÿ=ú4’69•@q˜›PJøÄÂï.àš€Ì  ŸÏÌó
,’ªÉÔO'¡©–µPçá1´ûUxâ]XÕêÅ’F:êÜh¹¹IWrª®CrXåe�÷×UdðÁ†²ûBNn9õÒK	Ë0Ñµ'VJ	po¶/ÒDÄÐTh‰0Ç›�Ió>ÛÌu(�nL�À³nÎüñ‹,¼<:êÜ.#GP–£šZ�é©'£¸ïþqpïî1Ÿ£aÐV‚S~¡ðÜSªÑÊQ]ó€2- Ï ©H©ú„€“…®¯ fÏ[· ¸‘ËŒªºYñ˜Ru$U#3þ|"0Ö‡Ü²œrb]ky2‘s]wÊu÷-yæß/¼Dê;ø0 "4Í)Ø�²< kP#ýE­]NA`ù¢V‚€Ø0«ä9'Rò„‘�™8:I“rEr[j=XBÐt¡;"å¼æu‰èÝ¿Ñ=¯Aê;�©¤jšà�¹ØöÞX•’O>ù>àõ¡±¥­âsgªNáD5Ý°uW\6‰|^‘mà Ô€K4ÓÝ‹ˆlF¼Âô eÆ‹½/>ÉU‹÷~ä‹¶¯ó,AÈÍe”‚aÐ)ABÑÍYˆ²Vµøðxëá…šfpÞ ¤þÎ²Œ¿l(`8®åÀÖ'¿j|V×éG¥¾ƒ¿Až`³ÚŒÓ´Èn<Êp|Ž©_¬+±ÙÔ4®L�‚„$Ãëß”$ž%eÝu>ÃÜ‹,A½—Ç`B…F�Ã/>œ®¨+ž¸Å{ƒ·ÁåAXºœÊIó~èáGðO}ž`Í¸®¯ŠåØeòr™Ë ´ Ñ E3 èÆ´" Ç
%6Œý»v oÇ‹Ôi}5Ã0¥Ð^ãÂ’fVµz±°Ám;|±TjþÛžŸàq”7à¤fÀ$¿²”þN×µÿ—èÚËàlH<C‘ ÅGÀp<Ø<s¿\Z³]^@>œò#@¡ùn)q¯ÀBäÙŠ„ß/0óÜA¿ÈAÐ“xéû_À+?ÿç’Â j"‚�—Â¡ßý’=ûrÆª¦}êo��iª–:Î�`/Ë Á3Z)&O³˜ùxðêßŸ èšJúw½2æã0ŸÈ™!žÏ˜B5I.+o AH8¾ld€aØï  (½‰°ü�– EBwTWÍ¨€�¹_ª�˜¡©¶Ó‚²!©FÁ}âY’v;A¯TØóÁ33‚…4cC½øÓ7?Šî7Ÿ­èxj"‚®©ÿ`Á}ëê<ˆÃ;^®ø�ö,æºÚYó.Žie@i  x·®´“!iÅ’Ž>~ëÕÌï{þþhÕŽ[L!4xù‚¹lœ„ÿ*…•EX*ÎÎy%• !ää¶³?û  ºzƒ¥R�oå^³àëöƒ°<Ôè íjohjÉnÁå:Ž‡¢j‚>–UÝ)fÔ¸Y4ûG•¹N)þú_Ÿ-»ê—ÂÐÿG-…¨ËI(á~hñaüý™§*¶œ&³ìëyˆ‡hfé·@JÕ�ê@6Þxî‰ÌïÝo�Ý(K!X.ÃòfÕ¸rÈFe‚,+'.AÙð çºÎšCuõ€|?Ñµ©}¯�°\Fð³¡F‡m#¥úZ\ `
;áxð.wæ‡ã8ÄULˆ C�Û¼.GPçáÐì°íÿnÁþ];Æu\]SÉÈ+†2Ò5ÒŸábF"tî»bì¢]ŠAÛ >À¬éæYÅ �T9ú5@Oç~$úgþÞ¿kÇ¸c²NÁ§I¤Ž:7VµzÑQç†G‹Â5An2©Ä%VúRáÁ!˜½–°ü�‰þÃH¾³Åö=ÔÐŠšü–Àp|æ‡uùÀº| º–vŽ³�„S“Ó£¯ÎÃÃ•·ÚÉ0žº÷—U9¾4Ò_à
 À[Û¶Vtœñf²«èe dh^KIHw”$•Â®—Ÿ)ØvxÛß'ý<†A@d�|þ7XÛÑ„U³0«ÞgL„2jšK-ÕR,CZ[î@ÿaÄw<mM04jlØ¼Î,a74¬ËgvNÿdŽ«©PÊôJtÚw¼°Ë�{áÑ –¤Z	¤Ãolë:¸oLd`9³2‹úËñÀŠ7˜’ÎÕÆÛ/=U°íÍ-/LÉ¹Þñ2Þxéy f^öìz?3QÊ€ó‹òå"B0�l%Ýö¤9«€1Û‡³¢''L˜/ìZ	Ö¿\ƒ˜¤BŸ„î<-~.žÍi¼i÷Ü8ÅG/»O?ý4^yå|ñKW0­ ªk™C‘ �«ž’DŽ©³µ¿Tƒõ
@ÓìÛöjÁöÎ7žƒa“Nrvíx‰®=PÂ}B£±ò€‹CÀågf×û1”T1Ž¡;ê<V/ õ* ë,%`W8d‚]ßò3kÕÕ@HLéÿ¶=‰Ð{ÎáscõjlØ¬øËZéÕèPéB!M+ê f'»RÖj¢Æ#ä¸ :îÚ>¦c}ô²Ëp÷]weþ>á„  ?ýÉ Îô_´Ð?Ð�Ù˜�;@7(]Ss^Ñtš^Y�éˆðî-¶f\¢ÿ0ûzÆpÄñaï‹�  zß(¾ºÔyxÌo­ÅIš1¿¥^÷øbËÃÕ8ËÖï/Y8Ä¹®ËïJo!_•Fú1ôâaØô1´[ÕKYz²ô
8n€�`äöÓsŽOêSÛ>ûé�§/V×Ð˜ñæØ�eHÁpP¨…ñ.èüâß·}­”N’‘‘£üÆo”ÝŸcÌTÔfÕbMG#ZcWV
±] Xd€á¸–ïßüß/¤•€šˆØ*]NAÏó%&—›™0]Gw¿›À°O³ÃËD�S…oW ãññÆ‚lâ±gës½×Í³9VÁX¹±a–­°‹ä‚£/”V!hA—S Zq—F•Šgjºy‚•€]âŒ«¦qGnýÕ¯
¶Ýrëmæ/,:Ž4ð‰pÉuƒæZ Ó¬kÖ˜“4ôíx1ûjbé À¾m¯Nª²ËNF’FúîÚWñ1,«`mG–¶×£Æ_yÑL1%P,2�Of�¥Â¯=ªæ
x~±R©¶çZ7`¢{ô�$Œ¤4ô'TôDeôÇdÌ^´lLÇúÍÝwã²Ë/Ç3Ï<ƒW_}W~ùüô'?  ˆ3ÁêÀy`E8ŽGcÃØÍXP,C�Ñ55˜Àtë›7VìyóEäp„ÜBnÌÜŒDdLé˜c…Åþ[è~ù‰1ÉD�‡Çò¶VÍn¨XØ)«›P>²3�N–Fú1òÊŸct¥Î_õKùúF™™Qibózb
$UÏIµ]²nã˜�÷›»ïÆ©§žŠÕ«Wg„ßUÓÂr™Fp�¯›—?8æÏ©4ƒ1 2NÚDS�¼”ß}ë7^qóú�WÜ�Lö…U"<ÑèïéÊN'Ý”vO*AÀÅeA%<��(J
r®ë²çÉg#�1x‡4Ò�È¶'s”@v6 ¡icv&ú™ŒÊ…–àIgœÞ[=átÍ<®`[ÛìŽ	‰D+á/–HÄ ÝÐLMÅ!«füÑž˜“òKÈ¿>ÿäòóOÞ!–»Üâ<ª%„å�E8þ…pÂF ±¾/Òjvž¸8Ìo­­È"°Sœ7PÀ0×rÀåúd±ã¬ßtÅgA˜ç]{ßÿff»!'s­€+}©f!šnLh>ÀPR-˜¿ÇxBØxÉgªr|WM#\�³¶·|EEÇoT®˜"e  %ŸV}óÆ
«ü @˜ç@éï¬×¨®n×5í **Ò¬ŒpÂ¨¦!7êšJvo/¨‹`f5®òJ\l(
ÁÊ¬€çŸ¼CfÜþ ì‹îÞuà�ùÃæZ%¢åF£Mô4§‘”IÎIÅPRCoLÁò}s-×qYŽ§5«Ï…PÓ>Ø˜áYj‚A´Ï�?¡×”;÷^`HB¢ ÀÈ&G–˜¡˜HXå¿,ÇSÂ°@Öoºâ öéšJ:·üÕÑ1Ã@JÑ—5„SÓ„QOTFçˆ„}C)¼3�Ä;I¼ÝÇÛ½qlë1Ž¼òË]C5Å,J ô&æ¹#¯=…Î°„îˆùÓWÐW0”T1”T•´t{v½âyu¯Ëg;‹äwìµË,gÉÈ0Ã‹›YŽ§Ã¯?F-¿ÞPåŒPJÈË±ãÝ+ðHDÁHJGoLÉ(–œù�[àm» Ö�ô!Â§*+z „ÁùjñÞ+6ÿ9âì(-°· h’5"  Éæ%kÆQ]`¥úêšv'ÕÕ‚”®çŸ¼Ca®FÙyKÀÃ)³lOTÎõÛ½qìèKbÏP
û‡%Sh£2**Â’fŽQ×Hš�Žv ŽØ5{ŽêZN|ˆ0ì{Þ6Ýkëý	ÅË–4$TôÆUtGåŒ²ÈVåCkÐ…÷ÌiÄ¬z_Ñ�‡™'�›6ÌˆžÂhçº®Ôgªü‚Añïº¦’ØÎç3|@vrÐØy€‰}UƒâH^û/ ð×5ãƒßúZWžRÑñxomç}¹Àô',�¶öÙ˜¹tMÅçÈ:tŠõ¸´[Ø%Íèæ 2PÈa3t?Ê-€Î7ž€ã	\ccŸ©ñW€ÜñÆKÏon½À™ëchª‘Œ1zt‰ð”pfØ¢$Ë�Ãˆ§dRTS '#�Fúc„å¿Hóª«Ûc¶ßøçÏŸt=+ˆ`yÄ ãòÁç!† êá­k6Çµ…êà©oü5Ðò¾Ž "ÏÂÃ3àY\Þ
À1³ëýL­Ï�ƒ½ƒ‘
/ÖÌlGªg4<ÉyC9ÂËp\ËÂ«o¿p÷>öÇb÷è¤ùïçŸ¼ó‚D×žž¶àëf@OÅ3ÊD��õlKˆ	ÇƒêöåÊq™ Ì�F)²òìB>ËOK)qL1 p4§+PLÖ °¬»ægcn	¦F2Ê•°6žvú˜È¿ñæ$•"EB †  73¸ŽæP`¦ü—��dd¸Ô¾Œ'pM¢kÏ™áÁÞ&_]3M5¢½�Lrà=û¡�ô ÒwÑ‘!hÑH#ýk„å¿og… –°Üq™š@GööR¹q¼×,ò©›1¾æÙÍY†À¬%Ð<žŒ†wqLú‡@àF»À\–ÏnÆÁÁ˜qh0^p-Œà�PÛ
e¸Û<÷t'¡ì˜~âà¶« U iëêë ô‘ð[Ï£víy Ò‚7t9FôØ¾×�â@‘~rž†Î~Fsœb5»(PºOàPRE“Ïì(ëƒ	5óÞ9ï=ÍkÎÂ¾·K7Íæ:XÑê	dÜŸsÎ>kBûÅ…]V¥fÐýa¹ÕUè)“p:‡lº &i�4QÙÀ³�=¤Ã~Ï?yGÉ÷ÉÈ0¹ú…ï}þ·P%$ú—p–ã©®©ý éèaÓzÂº	ÃF¨¡'Nè¤†€“6|ä�bçñü“wÈ æYäÚß_ºßK•””†ÃMõ†™A=ŠV€.PÑ™êÞ×›£{_Ïé¼ém›�ÆùËQ¿x-j_]3 €#*|"�Àf,Ëx§/Z0�ˆ÷×Á�â™•ŸórúüBNN�’+®\©ñWæ9599ÕõÜmLÁÜ%] Ã0–ÉA–²È=KIØ)‡á¤9¸ÛÆ%HH2|3Á7s‘yL)•ÓâŒj*”<²Ó*†ÚpÒº1uLÕiûúbÑ;¹NÈú !,÷)ªk·òÞ ÎýùX×nja».¢S	«ew\Ö�TtÄ£À¯yéû_@÷Öç>’Íü;ÀŸ| Èø~ ;òºt3œÐI)í<é”÷§wJÁx‚µP¥ÅÔÐS]_BVƒ+˜3ÛæcÆ{6aÆ{6"8Çd²]ƒ�‹ÍXšAq wÄ¶ò0Õ³7#ô†œÌ©4¤ø³+mA˜3A�GxoµkÏa8ˆõm`8¾dCwKGÑ×jC�qw®~‘Í‰�kè�$¡ÐQËW   wç�š¬'€óNZ9î•QƒÇÑ~ËZ¼¶ÛÚ9„í½‰œm‘¤r9Gã`fÇšj$UƒñLP×'°ÆˆÇd	Õ@2Í¾óÓ-Ó=vx7º·>ÿ\…ÂÂ	_ ºöSÂro�˜#àH¦‘Nu-gULÒ+ðé ]¼EX~@×&ºö®ßÝµçÌÝÞÒämœ‰ëÎFÛº³!Íè GTÔxøL�A0 `ç‘Ü‡ØÕ8É#»  3è#cˆÞK”V Ôø+€}j"ÒaÄ‡ÁøjÍ:ø2×EuÕÑ”ãÉ@­‡Ï<{€iId1pž ÔèÇcÑ¼¹X¶xá¸‡ÏýÿRŸ“=åÈBTRúaùeTW·ÀûðV-˜ƒf¿0)åÀ1IC"=ˆ#¥šB_jŠo|¨ÑÎÝHôìGïþ]Hv½©ï Õ5•°OŠÅ|îD˜
¢ºv@Wæ�…§_Š¶Õ§Ï3–"H©:¶uæ´,WcC>€j*¤�ÎÌks—�\óÌ�„Ë|úM ½Æ7ë8x;Ž¨ëò–e.Ô¶ä4ÉÆd[ uf~Déá …@öpP»q\c�‡gÐr•ßO`2ç��[·ô=Ô;¸’#¢§‹¦ÙòTÿÄfÍD³_¨êÍtb¾gCN&=ô6½0r`†Ž@ªg_±6MÄ4Ýµ ô˜ðg!­·¸�pÂÌØ�íŸ|åç¯_¶ýžÆŽùg\ŽŽ÷_fx\"Sëá±jV=vÈD	²ù Âñà<�7ÐoB	2 @Èã ôyð¼ÇÃPe°./Æ
E30öw�CÒM[|…ãÁ*ï³ V¢YéñàåáÔ/)°«© #C‡¸´9à—ÂýKc'Çc¾G»ö!Ö¹‘î9�<mÐà•´�þ*a¸'žò‘w¦ƒo>�‘NDºÀRxðÌí÷ÜôÅ=�Þõ�%|í'_`ÔúÜÌ’ö¦^@¨m5{t5',˜:ðú(£ Öo¼ü©Ÿý-Ub(©ÌÊNµâf~±ÙƒÓÇ¢Ñ—-Œn µ¶ûj ¥}H9“Èd€c�™>äT18M*V•´‚D Y3†ž¹ñ‚pÚF!ûºBé+i‚g£Jæ;)1*+Â¼	J÷–}ž0ìNð®�£´é£S]�6¾ùQÓGÿ«Yöúmÿ~íîÇ~»ùø+¾‰™ËÖ`Ns S	–l€2ÜmþLsá—ûˆ´BÞ C�•	”Î4Ÿ“‰™8™(§,¥  £\-€bÜ�]‡e�ÁÀÌ €7¬ˆ÷`fÝ£3&Á|ßàMlÈ[„åÞ¢šrÔT(V3E¨Çùj"í"|,Ù{ð¦çþûcÿÕ°æœ¬ÛüuÌhnAwTï¯ƒ�¡¤ÀûB�‡S º>ÏáGìÐaÈIPÃú.Ç7q20Ù£�QÅ g¥=sŒ–³Ggúþq%¬¾D~C>$ÍèÒ
€°ÜAª«™lÀýÃ ©bó}øÐ®rýÔöa4ÄVh¾SóªMþ˜èd¤Á¹Co<qÒŸ_~ø§ë®¾yÅ’OEwT†X×ŠTÏ>³©%ËƒZÖoÚ,–w»Ì,SCŠƒÓÛ¼ŸŽÐ …¬QÈ™ü¡`Y<cŽL³”‚;=þKÕ)º†aÄ†ÐÓß�7ß~oíDb¨ŒCÂ]ÿËÙ§^ü3 ­ ¨¡í€H·92œGØ™ï‰®=¥Ë|…°ìÎcæûÑC•_X¿ióÚ~|Õ¿ŒìûÄõk>r  ;ŠLV +º¡%Uô,XÝ†'ïØ_æ�C Ž:…>�¦b‰\¡ù¯QM£�­85tˆÁ_~ûküäûßÅ‘Ã�6G"[ApãÜf$#Ã�÷ÿØ¼V  ·ƒê*ý‡1°óU§æ;Ž™ïcÇ†ëïõËÊRCN6ò¡Æ¹Ztp €0™t±èžWnê~àG/u|îæ¹‚Ëó~ƒ0ýZ*þfË;¯tMé™>îï<ôëÿëïÜûËs®úïu)…`8Pg* —Z2ŠTÏžF˜>þQU×1ÔuÑ×Æ‚^9Õ§ãNÝÏ ãÜËðËMçã¡_ý ÿ{÷o²¬qò}€^
ä×Ç H›sHg’Á> ;	Ë¿Fm7a¸éT×c’í­çe]`þêkA��ÃÔ•Û?²û•ž9ñðœ·†�<ÝrúÇstš¶,·�hÊß)ùØ¾_\Yuad<ÁÚºE«oY÷Éë/TDû»¡F�êÙ]×Nì~àG/•>‚™àm›ßÂup5Îï�-BrÞø€ýmq»DÔ‡J�C/…„$£¿ûú½ÉƒÛ°éÛÝ×/²hôU7>V4zyø]åó	¼<|£Ñ9ÃC~ Üò]ôôôP]×þ(½)ÿ}�)â¸Ô¸ @˜wŠ™ï‰sÌ|/�õ›6‹+6žCXîÃïüè“?4Tùõð[×2V_bzOÇ¡Öï†Ï-¢ÖE ¹ÍtÑ “"éŽ´üîß¯Ü²úóß^ÑÒZ�ž¨ŒDÜ¬Ù`8n!€…à…‹D^À¢«oß†ù+á]Øù?—<?¦“Îƒ‘Œ¼þÄÅÙúÌç~ïÏ×K5ÍP£faO*6þ˜$¨ºŽápjd ±=¯€åK'Mæ`Òrp;ÌÊõ¹û‰^?.¼ô2œpÆEøÙ¯ï";¾ã{ñCo·ôÚìýFU‹jNÿnþwÌ|¯§üð¹ý‡||¸ŒM¯ò³þéøÍ_5XqãâùsÑQëF¨¦õ¾Òi¯ú¼YøÃMßXñÅ:®�ÙAV3ÄUôô¢ �#zGb£
AW¾Ò~Á—Ùyÿ�?[­k¢ºzÃk�ÿ©ÿ¸Ó/þ©h€–ˆB=Š@$–€.'AuÒH?¼�3Kî?]¦bqŒóV`ÅÎy ¡¢yÍYh^s¶={Í¾gþÔ¾0Ôv™e¹OìÜ¥ ,¼úö	ÁW»�’�ØÑ\ãGëqg¡-uð{Ýo½‚3VÌv|L–e°ñ’Ïd„0Ã@--�6`žI¤T;õb×á>tö‡;øÖòõ›6‹��à�=óÖÔNøÑx­« hÆÆKj¥-04†œ*:ÉxºÂŽ ´ß�Mê��°ËOAÃòS.êŠ<ˆ'ï¸8¦ Æ�Å_¿w=U’ßbX.Ó6Fà8tÌiÇq³š3ùà‹>=îþ×Ü®Z²FÍÎ>:…bÐÌ¬�šÚœ%ë.ý<jNè'?5ÔÍ³8~^ŽŸ×†”ªãÛOßºîù§îz|Án>™! tå¢E×Üþlc{Ç—Ÿ½êäÊæRg¡ëá[~X°Öàu?GïÑÃÿÉÕä²½-¸¦IÀíð<JïuG#0Žn³~?¦ ÆˆŽÏÝ<—÷…¾Mtå"Âš·Qà8,]8Kf6´U8›>ÿïè�)HiÔqïE‘%¶‰ž�›g!rž�ó,”‘>\ÿË{On>nÙ²{»Á°Ü)ƒ]‡Þ\tí�?jòn(_Ìc��?üÄ/]{ç¢©¾ÿN‘ÝOÐiÒdŽ-¯àÌ(V+`¥ågƒ¥ša<ø«]ÖßÇÀ¡ö¾ó5qþš‹€Ò‚¯hÂ’†˜¬CuÕ¡;*çtê+’ª‘3<ÓÃ3¹9xx+ÏºëN6‡[|þ¬Õ88œUó•¾xô²ÅWýúº�?üÄ/ÆòÙ»nºâª×ßê~àGU¿¯Z2
e¸òP7ÔØ09C5Wî°‹�!ú!x|àÝ>x›çÀÝ8b¨ÉÑ±©ÃiPÜ4à *ñÿ‹Y ½±ÂÕß ìÖìÈÝ»N8ËP:>wó\+øÏ?ïYøåUXÐÞ‚•K”~ÆeÃ)É¼•¾\Ç5-Ë  Ža�37‚Ž §_ü1Èš1íÎ®uãóg­ÆÛ»ñÐëûÑ;«#ü|ÑWï>­ÉëûôX¬'ï±ºMA5»ëP]ƒ¡iÈVTW?¸ñ½¯Aé?P2“´Ø+¼7ˆ†ù+P·h5ZÖžUT!X}À/­�Š4`;8íÉÁZÔÿ?.ìjÄü-çýS}¡cÅúM›ÅŸ5Î_å›×¶�²ˆ¬¥+/»ù†Âò7šSkª‡…Wß~!a˜_njçò'ªkCíá·±þüÓrö‹ËfÛp©HµªSð¬ùZ2ÝMXÓ�¢3ðx–dLAž!™^"K rÄV1HÅ�a	^‘E£—Ï(‚%³[Ñ1£�½þžÞ~ ÁE}Ñð²Å_¿÷SÕ
æ‚ =-xù&xlÏ«xöž‚D³3ÛÑÖÚŠÚ:³Ò®¶Öü?TÓ€ðˆIäc÷þNÚ»›ª‰é~óYt¿ù,ÞþÃ�é‚Ó.&s?xÑE5³ZM…1UH°¡¥Ø	ÃÅMóßåÐJ,•#p$Rh„“òcÙ
àÍ‹¯ŸX8û”´ Ï¥ Ç1„Ì[úéóâ…‘ƒ pá„ÿÍôâ']{ç†ù
 xg,Äi7þns×_oÅÝƒS/»K hzãjÁŠŸI3LW *�­¿�A¡*ÈêðÊ3�…—gàØœÕ !ë8 ëðŠ,šýx†@äœ»fæÏnÇoŸz‰xla|×ó—˜ @¶ æ@Ô€®ÂÐÔL_ÀDçÛè~ä ¦ÀoØp
ÞwÚiX»v-<žÂ¦ n·��…Ã4UI&{ìÇ–-[pï}÷á‘‡&;ý-$YÆÒÍ7@ÑP]Õ5ÈiâÒß^¼˜qºä 8�ÿóÿÍÀ@¢�ó }]¯dÿ=­À›_?‡aù&ß¼¶…CÎ¦ Ç�ÒV†arªÙ}Eotã»OþÁ|={Ç8°~ÓfqðøÓïf.²¶uÌž…å3€µk±óÑß`û3AûÚ3mo¶…°¤!"é™Î¬fGá~a¥$³Z
¼ùYí¿ÞcPD$É<îŒ  ŸÈåÄ…²Ž}r
>u3÷`Q£×ž"n}àIüí�Ÿ¼³~Ófq¿?´ª|vŸs¤3Eû 4)#}`E/O TW¡Œ˜}gÌlÇÝwÝ	 ðz½¶Â_
¼KÄâÅ‹±xñb|ìcÃu×Ý€o}ëF1ëZT)‘éi�8¸� 5Ë‹o( ‘%ãöÿF<èù®Û”(€bæ»­ ;˜S¨©*þß]?´þüKþ Ž±`Ãõ÷‡úbá‚Lxïøã`Vóèè¬ùïû0¢‰¢Â–4%Ô‚fªA3ÂO)Ð55§WÎ=àxpÜè×ÄeB��+`Š‡S:†S:‚.A›ó@ÄUÄ$m!x† èbÁ| 9glð_VœZ¸öÎíºéŠ«Æ{ÿ «®€ü ›¥ÃoA¬ŸªkÐ£ÍÏÛZ[Çñ	…˜7ovæ÷„$CÖ(´ø";Í‰Ñ®šF„Ž;©èû§CÐí�ý/ÿ?8RHƒåûÿÀ$( §æûxæ‘þâ¥G°#ÖŒÎà×9g„?+¶Ÿ/ü²¦£sD‚Fpš–CJš�¾¸jÛ‹�*)š‚Þ(SLM7 é@JE¦G�›gpqhŒæ¯›V�V $�bß`
í5.¸�ö¾øný¿GN> {pÿë‡ à+Ko|øÈŽëÏþÞ¸nb„ånb®�Fú‰;ÜVô€°Ü¤tÿIÄcÐ’QJ
‘7Ì‰Ñ³Nþ`I÷«šñÂ)(Ñsðp¤Päûÿ@ÀxÌ÷ñ ‹Ñï?û€yhBn¯é¿~Óf1[øŽÃñË— ¥f´N*¡èèÌbX5j’>‘Ã@Bµ�ÛS%…”$çaÕê€›RM÷BÕuD5|Ú„Œ¤G—Õ{r­…Î	F2‚›ÿ0jBAXc0ïýŒøðw_õëøXÃ„9×­«Ûu�;lŽïÞ!ÔFJäLšªIV F0òÊC�FúÁ{ƒXpÆeEßã4ñf"Á1Î{ æçÿ[ˆ«¶ñí7?[ðy•ž`µÍ÷ñâ¦?Üžn+F¶:RiŸtåÏþˆ¤Ù÷Ò×(ºÃQLî-µüÌkYm°M¢JÍd«Yí±ÇCÍVX„åÍŸ<· 0Õ JéJé¨s³E ÝQ~‘ËiøZ[W�UBç¾w9Â*ƒ§· á…Ÿ/þú½;ª ÿ¯TS.T|÷Kð/^_v h5 F?¸/? XvÉU€'TtqÌÂpÚI˜#´h¢Ðþ¡BÿŸã¸ûíÂã%?m2Ì÷ñàí�nÜÖùŠu_oüÑµwþ0›ð;þ¸Ž„?©hè�šÇ'•HÀPŠ�Å¶VACŠ—<¯Q]>úÅ*0GO–7‡yºr­‰¡”Ž¨¬¡Ö# äbÁ0ª�Ca­!·ùÕ¥ù‹¯ùþË7,E2ÇËû@UéþŽÏÝ¼f¼¥Æé±èŸ¥¿Mtíá0.ßxéä3?¸½ÿœ kÎAÛ)•|Ït  �šÿ¥Â{m€¢²Û×ö(ë7m±rMÊï÷çÜ‘©¿=¹øÉw§OŒy.]Í8ft|îæ¹T•¿‚ôj»xþÜŸ?¡èe… 4M«ëH&ì…ÚÐTr
Z"Àâ±Â´R@2Š¸ïòBGK]Uƒ /m¶„Œ5‘tø<c® Jàô5è¼÷YôŽÄêx�ï6 ÆýeQú;Ò
J¿?ôxoù&¡ã�îG×Ÿn¢º¦’À¼ã±æ×—}�Ç!ù6Q¨ÄüQ ±ôTé|Dø‹Ýþ¶êæù'ï�å—v½¬©Ó·�ãÛÝx¸k‡yÿ/ã=Þ¾_\¹øùßÿA—Sh®ñcQûh²ˆ¬åúüò…0GiÅ†í«Î´DÊpOFø�Ñ™xºœ2Ó`Gz!�4p©ž}HõìƒÜÊp7”án³A§Ï1¡	ËA’Ä"#‚,ç*ª¤jàÐH
IE‡7½Â‰ª9óâ†j¦{¬‡gð‰3×š÷–åNY|Õ¯?W•/�Ò›Ëß h—©jAMD k*	,\‹“¿ú0e­Ù[oj—¸j˜ÿ†ŸSút±ÌÍ¢ö†aÐ{£/ïÂtEfõþb¨òÕ8æà¶g¯9ø›¢‹fŒŽ¢Öt�#Î…ß2ë³+Ït9y¨;Gð¤ãá}Hõìƒ2Ü52 ]J€jrÎ Mª«0ä¤yüØ”‘^È‡ ÷‚)8¦¥²yÕ H¨Hd…ó•@oLÉÓì¨sãkMo�æªj}oTWo !�9‹bB1çÔáä«RVø�é‘ÇŸý·k ÐåL)ú#Åö/zÕüÌº?		±·Lõ})@,£™ÕŸÿg<ÇZzãÃ_�ñÁkž­YyÚ‹T×~#u¥îü×Ï`¤ß¬yïŽ)�‘Ë	¿=]ƒ®FrÂ^†œ„2Ü©¿³@)ä£ÔD]ª«Ð“QÈ��‡ºs&ìR]ÅÐÐPÆá
ž%èŽÊIŽ†I{bJNžBvùèŽŸƒ€Áîª*!ÁÑ“£¿!7Võ˜yðÍ:íÿttÎYk¯©V •$ÿ”2ÿíÊ5M¹§Ø±Šª’•÷Ýxàµ÷~i‹Ò5´6é÷À¿j>ôÁ‰Ý8Åo>•¶ÕÈÖñ¬þ§üð¹ƒ]‡¾˜w<óŽÇêÍÿ‚V—Ž·¶mÅsÿ«ÏßŒ„šû¥¨:u$üTS¡FMW ›é×Ñ¡743UÕPe³`ÅÐ3
ƒ°/‚0,Ã€°¼Iþq"˜¬H€¡¤ t‚óÀzC`8ó3“‰8MAcý¨UÓWÁ0‚.:%èŽ*˜2¹ƒ”ªc ¡¢ÁËcçlÿMZ¿æÌŽÏþø�jõ$™È\ †Í„+™‚g(Ü<)ÿŸjÿßïpõ9RÔügÐ6ûïé§¾¸¶³ØñJ:ºnÜÄ±ì½©]fh}:(MUqÛó�XW÷m8›šd‹þÎ}?f²jùç´ÏÏ2XÛ2IEÇ¡°žÑàFoÓH<÷&—þl?�j*”<K€ê*ôTºœÃ	04J¸z"’öóMmÎºý ËCÖƒ4‚õ˜‘	†ãÁÀq£ -…–ŒšÛ½fM…rGQ
dªÝº£2\�È±PušzÀä†û{ñûïü3®úô'°Ÿm¼uk*ƒâ .žÒ`°`ÀÍ³ikhTˆ¦ƒÿt;Ë	)•ü³«ß&âDéÿ–:^Ip�7þà�R�!Äm)�º3V#õv'¦
�Ü‰A% }ë7^ñÇ±Æý^}û…Ù™~sÚ3É3†1ZH¡I‡‡g��äœ|ª©Ž„_�t£Ñâ#Ð’³HeàpÙRØlðÞ ÄúpÏ\ÂòÐapÞPFà¤ÏA†Pk¦ÚJª�Áp-u£ì{çˆ„9µnp,“‰¸x<KP×Ü‚ïÝv àPï¶Þý,‚‹:>wóÜjXÔÐã=ÆX�Ru¤€«Àiã�‰B@tî~]öçÚ•Ø–jÆÈ¡C)u¼’
àù'ï�S'é!�nÆÆS»c@ÓeïCì™©Äûçg¬hùÍXãþë7m�ÿ²þöúühªmGSr›m f^ùp8šIÄ -YÈdç¿–C‰š#¤YÑC•¡FÍ•]ï qp;Õ55³üÔ^,ô6 èñ¡‰5É«>=…Îè zå•ÔDj"+œæ[¸¾ÙË Kqð¾˜ô N]NA�A¨1{½Jª�þH�Aóu�šM#[¦ù?”Ô0¯^ Ï$U)E‡[`1«¹óZë±·{¼7ðe W�ÿ›$# Å@$>þC�ÙVAƒ—‡fÐ)³j®þ>�)šû¿³¿Ðü×ÁÜ]®oCÙ¸C ­é&­³?“A‘ÚuÝ?­Ÿ?É·MºKpî†3�g€¿öïù£1ÆnÅCË7|<ÝE °pVK¦®Þ0Äeäg=Xí¸­Œ=«Ä4j¤¸ð[¯ër4Cø­ç­P©¼8·y	6úf¡Ã[Ø_bƒÓ¼‹è2:µ(^9Œ�©!ª&"däõÇß½5'œÚ8¬è†PÛ
ÂrÐ¥8”‘ÞŒH¤d„9!¯Ù#,i¨õp¹8ƒ”ªƒO»EYÏ¦\¸j¾Ó= —­ß´ùkãMºb8>f¨2”¬Â D"�††ÛýS)gýü*…•ü“Ttð,K&· ò¯Æm/®Šf`g¡A“”»Ë³¬X~Ïu/½vâ—Bæd>°k‡þë·˜õ��˜4‰ÖÀÙó—ãìùËaÆŸÜÙuà—+ï»±¢P%ÌU–x{}~£fqXÒ¡¹Â/ËfUYæýº
52 Â‰kÀ�â0äQL—S9Â¯'cÐ£ý�#ƒˆîÞÀœ¬tEëJòå§‚¯±ÏŒSGâ@bô8AVÄ2¶ËšÑeòŠÜ‡GûÌ¦ýÏÜƒÀÂµ-ß˜^ùÍÎ8ùJ`$–‚Àsð\ƒ¤¢ga„SZ†e§4Ôyxð,ÁÊ³!<ºŠ¦Õ¬Øxž¼£äxð²ß¥� Ð7<1ù N7?ú]«:…
@Ò4¸ÒÍV&Ú*:ú˜±ÿbá¿½CR&|k�€îú«/w\GªÇ ôæüm4)ãàu·!ùÖ!4|ìt°õcŸÚ20SÃ0Ì×k–tì?øo·?¹ÿºÛ6o¸þþP¹÷-¼úö³Wÿö–†œÕ8YFQ¥\íj•³RM6_ŠCÍvª«PÂ}™¿õdòp’·e„©¿�~ä›äºË>‡Ú“–Á¿düKæÀ=Üóg€õ›fzg‚œîZÔó¹µòAVÄû<í¸®ýR/x ÑÝ[0ô÷ÿK}Ö9Hñ—%žRàX¸8’F—MkF5(¢Y³!­ßy–à½‹Í~ú„aNÁ8qÒ)îg9žª‰"‘ÑóÒ´É"ZŒT“4Š¤bYiÆ8˜æà8šú 5žâáÌ7º
S*RŠ~‹“ã:R _=ã}¿¦”ÚÚ`ý¿{ûòGº|#ü–MÈ�*B˜�,ËÞ~'¢#ÿíößï¿î¶Íë7m¶ÿ’8¸í*iàt9�ãr|§«~l^�ešN €5ÌCJ yp+â»· Ño©o_�¾ô-ÌŸ3Ÿëÿq<Žçá™ÙÖïA½èÍ¼VL Àˆ¡PÀ´*]{0øÜïM¡�åº  À»Ü0rVÐpjô÷xVÇ¡ìîÅkÚ3–Rñ’:‡xþÉ;d]Sû³½—¨RùUÝjæ¤$œgHÙì;U7ATÒ hÎ:9;EÈ¡ð•“J÷¡_:9®#ðÌ�„S*öºòÒnrðÓ?_ëGÝÕçÃ½¤½ª7ªÂ\Â²ìíw�´±ÇR–e@8af|ß'Ç¼‰è®—�ŒãpO?Âá¨ºýêŸHå>tÙÍ, 3†o1ü†¦A‰@KFAUJï>Dß|,3`µ^ðâçù*nøø—
ßRg?Ü¼˜£ Sd+�Wä>¤‰Ä}º®Ÿ –èÚƒ‘7‡.%`(æù1CIf|Î¡,¡O*æ| éÒâtßÂ,2táÓ`¦®ãs7Ïÿ—Å¼ {÷ÌlR”*MV¥²»d›ÿN i¦uT«€cœ‡þjÜlQòïÍîBÕ	ù—9§'hkºI=Ôw)Rú§taÏ~ŒÆoBã§Î„oÍBÿeË”å¤Ë“/aY\r'¢ ÿvûSGžzmèŠ�§Ð·s/À»àn��={÷‚óÕ€j‡ Kq¸\nPo\¢ †rÒiíV=9ê¨ñ0�oAêÕèÉ¤‘~°Oÿß¦‹Èæ•i~�•Øú boìMšŸåæEÔ”G]‘ g’xû¤<Ú·› „åþ‡êÚ_­Ê»èî-p·-€—á˜äš–ˆBÔ�cMÂOÒŒL\B5LÇÇ³ÉÀ¨dò‡æ?zGbàÜ¾•ït`J÷8ùà¡} Ì6æ¥\ E–Á»JÏõM+EI”îj=c ªê£�¬&­•¢’Õßjã–�˜¤a÷@¡a‰F¿ïôØŽÏbù=×½ôÚ{¿´ÀÚRûõÿîI„ŸÝŠYßü(Ú®<ñ­ûynÇ”'Âlœ¹i5žÂjÄb1ú\ïr¤-…WºßÆ®#lFÐeO „‘Ý¦Y¯É™¬;=Ý_Hççk*”Þ}P%“üÓ"ýÐ¢Ðj"‚¥þfœµé"l^¹~¿pPPÉÖ ÷ÁÊ»°PL	d¯þ'møè]Ï?y‡™jr@7GÞxÞöã2¹€)\Àü=&ë£
@Ñ3¦¦¤ê20›`Z4£½#1‹‚í ÀÞ={3›ò™²‘�%xQšk²\ CNÒR÷Ûì°<þô_I£�4<KÀ³ÎIC§¹¥Vÿ×m|út%ÓŸ*jbe–ÛÏ²êN?uWŸ�¶ÓG €ßï'gûÍÆ�Ÿi7³ß	à`x;jÂØçp¨'ŠÁtcI«�•<�+”z|z2]1Ú¦Ú –{qÜªEØ´è,iÈô»sôT°õèƒQDž¶ÿþ\œ d)€ˆ&å¬þÙ¡9Æ¸ÆHF.”FúýÉ#»áïX	¤€–Œi•´L`v³ì¶æ	EG]zŸÕ´“0mãÿ&È[ ÅÖwF‰R¡@'L¡k*¡J
D°/
T°;A%VAÈÍ9ý[ýÍÀŽ¾ÂÌ¿hJþ¯rÇÌFEwaÍ–ŸÞ÷Ú{¿´…€¬u²ÿÐã¯bø…íhûô9h¸d|+:¦•"ÈÜžÇ’†V,ihÅÙ P Ð–®AJ’èa)F à`xvÁ{çs>¨>„ùõÅà^ÒŽÔÛ�züÕ¢ûBP/z3VÀ-=¯¦W²5¿ª9Î�Ü
Ðkâ{^†oöqk†j*4Ýl\¢ªAÁ3ªN¡éK
™Zhò¥CkÄ8Á¸ý/i7éÀ�˜3ÇŒ4kšVÐñp–PmL¥EÁ×ÛO¹«« ²QÊ*àçU¥ÞèŠÛ…þÞpúËFÅwÁ©`�&eùÑÑÿ‡gÐúùóP³q%|+:�:Ø‹øË»§4­¸ìÍáyøyž,1Í÷ì½ªðoX†‘'^/ºòÛáõx^9–ã)%ÌíâÞ/üÑPåkR]ïPCÓˆ.§Àq¦Mäà1ýeYÕÁ§ÙpƒZÎ²6JÖÖ¥‹Š(œÍã*SIa€ŽW_ß–Q Š¢Ø* 'ð`9žêšJñBõ…ûDfRºÿØY!—óÕ?»}[6ÍÀ›Ý6ÕÔ”:öý-Tì­ÙòÓû(¥×+]C8xÝmØõÉïaä©7ážÝŒ†K6 åë—À¿aÙ¤çL°õø7,CßÝO8~' ¢Iøé³}¿®iw«ˆ|ïÉ—¾j	ƒÈ!4³C›ŠjRý<K QóF}ÿì…¦IHƒaêQ�çàÕ—_Ìl)E:	¶´´ PFzm_+ù7HéIÐÇ@ÓËÏ(,µúoïML’" ûüÄŠ²™ù“šÕãk•XÙHí:Œƒ×Ý†¾E3ÑtÙûP³qeæçh°
ªÿ†eÐ"8ô_¿Í°ýNqKÏ«™‚¨´¯o»_šØ C‹‡˜µ
òP7æ-^Šµµ<êjB¨­«g²gâ©:ÅðÐ ¤p±á.ŠA\Ü�9óTý>–}žêÚæ×wìÌl+E:‰´µ¶âÈáN(‘Á‚×Ü<;eµÿ!gŽ‚×œév³J­þ¯¶qŸ)-ßóÌcR k¶üô¾üôàJa)‚î¶:4^´¡óÖÁ=»îÙÍP%òî#Hí>ò®SþËÀ×úqäÇ*`ú�àÁ¾·3¦¿®ëK›Ñ%@â EbÿÆâ´s.À	ûbÉ!˜<KÐÔØ Ža°pÎL,ð×ÇÇï~qR‹ ëM |i!tÂ<
˜-¼¶¼±kW-C"‘@MM�­à$0oþ<lÙòä¡®‚×êÜSSùçâH¦æŸ!Zšo�j€cIN/ÀRÌÿ]ñª­þÀ8æŒÇ
È†Ò5„#?ú#ºn}µ'-CíßßŠð+:à[Ñ‘£”þð´"+�Ã2¸æ4càöÇK}¥°#Ü�ÿì|– º¦ý  ¡RËñô}ç^HÎýÈ'?©æôœ,³”cˆ�‡7«[ýÎ=óýàÎ9o<z¾ækðÎ[]•IÌæ² +ž~ü¬]ef“&“É£Ÿ'DàìY  yðHÎv'™…z/¦H�¦SD4gr�"NBÑñj—­ï?¦Õg£ß×Þû¥—œF*�{ÑLÔ�±ž3VÁÌ}R{!è…6™öÖ�{I;Üg€zÇ%ø p8>ŒOîú“iúæ¹õ/?½”ð1ž`­‘ŠÝÏ{ü'ã‡ÿ‹ùïY Iéè�)I*Kz&P~‘Å{fø13(¢ÁË££Î…žƒ{ñþ3ÎÄ‘Ã‡·Ž?w¼ÃXËß@uõzÞÄã= ÀœX,ØÚÔ\Ò¸ýöÛññ�ÞÆ™Xqý™íÍ~¡¢œjÁ#°hõ;ãjÜ,¿ïv¼ü‡_¢­µüŒÅXÑšæ"én@SÆ_ŸihB@ßxðãË�ó½Ï…m»ô?×©‡ú^$8ÀR¾5ážÝ\ðz¶B˜‚%ôdv”×÷£û/§ÊK»ÇuƒRªŒËvÜ‹© ØÇx‚kJ™þ„fRMyŠåø¹_»ëI2Þ<
Ëè‘ i¹”µò[D  ¼Ù:ØRsjÝàY�!XÕæÃ™k±oß>,]ý^H#ý}„åO§º:æ’PÂòË¨®n€o~ózœ~º™8cÆ[7 >TS°0dã™gžÁ©§ž
 8ñ/€nðAGÝØ[°�í5.¢;zŽÛ^zßûæÕ™ú‘,Ä@˜7Vmêš;žêxÿe/T’ø“�qKîó'é>�N.ïqœ@h«Cè”ð7¾Û®ª$Cë�I µÛ4'J1°õ�¡ŒÀ¢ˆø‹;{f;†_Ø^1¹g‡”*ã³»°f–6Ó,¿s@W|øß~Š5ï;Û{Á×t‰Dƒ±$Y)èT”s}¢.QÀq³ZÐÁ³³B"Ö´Ðêçñìã�àüóÏ(%Ø cíÚuøö·Í>„µµµ¶n  Ìš5«è�úûûÑÔdF)WþË=ðÌX0e«ƒ—wTòkPŠ¶ ˜“ êÃÿüËW°ëÅ¿ [O`Ó8ïqÆ­ Þ¼øú9ú‘á·!“®^Ý‹fÂ¿j><ÇÍ‚kN³­…��D$
f$	=b&Ò¨Ã¦?¥¯IçÌX9_kæ°A/¸æð.1‡ŸèßòU·$ÕzyÂcxñ¬²MP	¹”~oî¢¥øÄÍÁÛé>q’f «o ‰heõ÷Þ@l:_ Ù/à’å�XÔhfÖ{x|ú#Ä#?€| ×Žãr÷è €Ûn»sæÌ—0³}ŽîÄœËnDûIçMÉêïâZbQß?nžA{�«`»ªSüúGßÅc·} ä#fšwõ0n•¸ò¾¼ºîÊ›!×UóÄœ µëp“N<"\í�f)m} žãf�¯õƒÌn€70ÍÆ`åù–â�ôf"ÉÃ}ù,~Uý Ãña\µç!Ëìw&ü @éç`åY—f„?�£³·ßv"¯�2«5Çƒp"ø@„Ú–Œð GÌ¹s�A{È¯@ð¹Ï~6­ è§×oÚü�1‘‚„|”vX>ñ·¿áÓŸú‰¼^/<žÂòçráÀeË–âÈáNÄnGÓªæWã¥ˆ¿|XmÙòÁ³â)W`¡þæ†_(‘�çÇË¹d£*6ÑUžØþ(øèxÂ‚Õ MÊJ!Ä#‚¯ñ�õ{ ‡<Ôír|;)I¢l8I @�%¡ta²±#Ü�kö>2ëçÅ9~Æ¬5’‘ ÐÚO `
ÿ¡®îÌ>Z|áíÏ"¾çe¤ºÞÉéG˜–ã©wö2â[¸'¼ï<,oY ØÖGÈÅ!äöbÝºuÖîþžùí qéHÂdo»÷OÆ%_Œ`0ˆD"a« Ã#%y€ãW­Æ#?ŒÔá�SÂü×z8¸V	Ö¸Ù¢aÙ—;£Jª¨[ø¸®þu óß¹wäÍ¿�X­ó¬ÚªõòÚ/^\�°à?2(¥x°ïmügç³–`î#,ÿA§[ZÀ‡~ùwˆ¾öuõeÌþðögÐó—›K
}1°OO»ü*rî§®B�›E�‡Ç™ÍÊ;Á‚šˆ€°üòŠÉÀ´ËÂr<õ/YOÂÛž |ô²ËðéO}
@q2°”�M^vûË<“—iÊ³3ƒÎLÿlâ/QIÃí¯öæÔe0††¡®ƒ'Wcj30†TàbX³å§÷QÐ-Õ:Þ?RªŒí|
7îÿ›YàC˜çOpM%•&ˆú @M×ÃKòhƒ�¾Ç�±?`V×=vÛwá˜ô(ró¡T%†œ¤,ÇS"zº*9&á„™VÛÛq<q7ÏÍ½÷OÎ´
±}ÿH	>ã„•«Àr<€C»ßÏWS1š|ÎLƒR´Š‡ŸÜ.(Ê’5úDµ„¨¢  ¶­öÃÅZ‡Cq<=°ço½wíH?´äûë7^~úØ_ò 8²ÍÌ­¯Œvª;ñÂq�çú}’jöÉ³âÚ�<ö(tM%º¦>TéùRMù ?ïÂ3s	XO ÁåfPMDpï}æ\‚D"a[P*)Èà„÷¼‡ Ààë��ëº+A%¦�‡+:xwûòÆ|3†7Q¾ZÍó­j^ä/Þ~&ü™k\„�q7�üGÀáø0¾Ûó"n>ø’f¡N¥¸ ?ë<°uLèOðUªÊÜó¦oÖÚ÷#P×ˆ¤ªC•exf.Bpñ‰`ˆ’ÈX	¥àªiDÍ	gáÄOþN¿ð2ÈC€%M^ˆj
gŸ{.¢ÑHŒ°üGAg“M “øþ êV½œ¯B¨| É[a¨2ví;„ó?p6\.t]‡×ë-8OEÜ€ƒ�à¹çžA*ÆÒ³¯˜ðïÓÅ4x8É‹áX‚™!—ík)UÇß*h;æáÙ¯=uåÚñ5aÉCÕ3xÖoÚ,þH
<3‚ï¤T¿ê{wv¿™å�“;Ò…=ãŽó2¼x’¡Ê�xgúOû—[áªŸ�Á‘0†Ã¹CJÓíÂ•È t9	ªk ,Vô€ó†àné@pF†œÇŒ€€—5b^�ýÃaÜø™Kðêk¯Q]×>ZIx*�¨ô
€&ß¬ãà_¸|°lzŠolß|ñ~ ÀYgŸ�¯ýó? m	Áb9¯¾ú*V¯^ 8ïE}Ûì	üV�'ü”bv­«èêÿÐÎ¡‚)¿²$mw?tËêñ¦^çcBRøÒ‚ONEnÀt†%øî}Ûbø�­/|±Z#Î-¤•ÀÿñÞ`Ó²K®Â¼MæH¿Á‘0²ê8À¢±¾^-«gø°ûñ{ðïÿý$úÇÒýÿúM›ÅçŸºëqPãdÞDÝ‰‚õø!F»3‹í8xû×2£ÒÊå”Ê´ò–]z-V_øéjÞâ´Dxygu½�/ÚégwÙ•ybŒ.¯OÆ_1LHiÔÏw<yä˜+0ŠÃñaÜÙÿ&®Úó}}ä0±Ì}ÂrW¯ßxù—í{­ê3Ø©¡&œð{]NÎïyó™_ø3tMEãìEhnl@]m‚¿á÷z‰èáõzr~êkBh¨¯5ê‚~²¬ÙA�ã�§þ·~ó³øã½÷@MÆŸ#,÷!úß*9¯ÎÛ¾ÐK ö„³ÀyƒkF{‹˜–€¬¿Ñ]fÏƒí»÷áüœU5§‹b®ÉŸ”$„B!ÛÏÛà0^yù%$F±ôÌ�LÈ÷[ëátjtóLÑ˜TÒðÀÛ“cú[˜°$þtW ¥ÊØ>Œÿ4Ëw³°„ü|ýÆ+n®¶9Wikàë,ÇŸ£k*ñÍ:3­€»u>¼ÍsPÓØ*x!ð,UQHDÃˆöv"¾ÿMÈ‡¶aÿ®V§�‡@˜Ÿ‚*ó`&üü ×Â;k)„Ú–Ì(sÖåÍL/€Î{ÿñCo ¾ø¥«qñ‡Î`,fd»§Ýxf-^YÕ{[I¶ Ì­s�ùÿþÍ>‰æ¶EWõ	ñÏ?ûÀD=+Úi*Ó„§–Ð?‘ìÄ£}»óãíû@È¿¦'OŠàçƒñk©œ¸�êúz€®G:õ¶ú ¼BXîæÑ±f¡Y¼ ¿·m>ü‹×ƒÔ‚ËŠÏ‹íe ˜3öüä3T×TÂr<ýÕ­¿$¥\�b\@ÇâeØ¿kæœú!lüÂ·ªv?+‰÷—óû_îŒâ¹ƒ¹n†¨«žúâÚ	+{�ðÆh/¯ýâÅ,ÃÜ;‘ƒSJ)ÞŠô`Ÿ4‚'Föá¥XW‰$²uý¦+ÖN•ðÛÁTÉ6jèm ­!ë5Çv“†ãcà];«AJ¦«ýÐäªiDè=çøýBmk† ÆåƒPÓŒÞÇoC÷#æ”«¹‹–â×¿0§ÔÙ
¹Ýn46ö*ýÎoÆ×®þXŽ§þÕ¤ZIA3‚‚ã�_)¿¿;ªàwoölWRÉ+^ýêú»ªr²E0)R9™ƒJ)Ž$F°/5Œíò Þ‰”øB–¿‘êêS}-“‰láç½AÔ®=¬ÛŸã÷sÞø,e@8BM3Çƒj*ÞùÑ'�èÚ 7CÐ.*`—˜ˆDQÓÖ5©X	éW¬Ð0C~w¿Þ‹¨œ7Ž>½së×OÝ<A_Ëè½žè Ò|@*°sªkŠ�R
IS0('Ñ$ªÉÌîwbè–"èTãE…�åxÊˆžÌké±ß™î´ÙûQÂœ\mÆº"_økN8œ'>ØPÔïLk€G[êÙ‹Ý?øxæ^~û?ÉtÊçŠYW~ùüô'?€«¦ùÙ ;öÆ NK|�Ò©¾€½ß?Q!?;Lš]>>à�Þ·ðoUí\éñ^1]Áˆ¡T´Š[Â.x ïáÐTzV[n]‘Á
bæw5ÉV}„VW³¢k:Â
C¢„ðN„«aFÎûø`CN¢…ÁïGç}fŸ WM#~û­ƒ¶|€!xèÐ!tÌ›OuM%Çüz¬<ëÃcº®Z‡Z‡3ý€Ò¤ßSûÂÓ}0Ìª‰Mò³Ã¤:æcåžØ‹kö<<)çÈr<åý5„åÅŒ€3.ÑÞå�*%‘ß…×PePMÉì]…2t,/‚¸aÅµ'ª¹Ã´�Éöß‚tšo1ájšrH?Ëï/†wÿFÒi½s-Å¾ý­¢JÀÎÈ¶.úÁ_*.
¸8Ô{8ÇŒ{�X”ôÛÙ—ÀÃ»¿þÉðû³1éÌÜ«ë®ü†a*êp8>Œó·¥›žòU Ý•¼ Ã-ôÔ5gš'zf/‡Øº /‚ÝP¢C ÂŒúuz*%œKÎ]…<Ü°|F)P–‡–ˆÀ�“ö®«ÐS1NÈ„µÞ­J€°üÁ¿éšJ\5�®:¬è)+ü„!6Ì,ylCNbÏÍŸÍð¥ºÙ¹ÙVÀÂó>‹“.»ÚñuyÍùäw÷ÉFLÆ=[

}¤dòÛ¯ÿ¿õ_Ÿð/)“Þ#ù—G^~êòÙk–ò”,qúž ïÂûß2óå	óPz?€•ü0nÿ6WýŒ¯1¢Œèë«E`ápÞ X—´`¦<a9ªd¦ÇºüàüµàCM¦EÀ`À˜·�eYP |°|°œ¯†ª€ê*Äš&ðõ3`(x_Jd  š©ªœI8á!úÑÙê8Œ'XKUù^Pã3Ô0ˆ·m>‚ËßÖå¨/+üBM3Súq$�Àâ÷bäµG`¨2ººŽ ¯¿ëO:	©T*'IHÓ4(Š’S?
… (:yî¹gÞ·�ÎXw6ñ¤g$–‚‹#hñŽ…¿Ñ/ ¦ˆ›•4Ü³qÝ2ª  ÍIDATmrÞpUQŸxíÚ÷N8é—�)i’þÎ¼Åž©‰§�Nö'„àåÈ–Â ,·ÔxºÒÏ¤ªœò´/9“*Ò Ðå$¼íÇ™«>Ë›Âlè`Ý°¢¼7Þ_Þ_Fp�uûÀð"Ë�áEh‰0 €\àýuêZÁyC™é;„å!Öµ�uû–a0‚†ª@¬i‚¤ÔÐ›aèaxñEjèG/'@˜3©*=àxÀLòñu¼¬Ç1Ô�ì’ÂÏ9ó«ëjC˜½ò$t>ÿ ¥†AöîÙUÓðžã�G*•‚ àÓ35M+(Zûžãqço~‹Hx„Äú:1ïäsK~^¥‰>µ>{‚1¥êøÃöADåÜÊFY’¶{#}gzæi2¿6`Š@ç�­úÖ�õ7#š:�Rãä=ª®á™‘és¦·�åsëŽ¿H(=‡õÕ‚uûánš±~&X—¬ÛÂ°`8Œ ‚p¼ù· BKäúüœÇÎ—VŒà6÷åE€R°ž „PXÑÖåƒ.% j€°œièø@=Ñ"ý”†�a˜�SJã ^ËuMÌU_ù9@¿ÀÇ{ƒ¨[õ>¸šç‚÷×€÷�~µvÂ bÝÇÂrsy]pÕ4"Ð¾˜ô¼ú8¥†A¶oÛ–Q‰D"G	$%	^—l:R ¸DÌëèÀ=÷ÜƒXï!_šç/³ý¼J…ßïâÐ\$ÍWÕ)îß1€¾¸š³� ÃŽnxúŸß×çä3ª�©“³tøÊõçmÑÃñ�BÊ>^p¸§oXŽk'.ÿO¨*WÜw ÑµwŸ»¥ãkÖß†ªÀÝ2šG@a7d“=`8oZ°Ý~ðþÚŒ`›û¸!àjœ:¨an'†M€åÁ
n°./¨¡�óÕCŠC““ÀûA˜ÓË½ZQYí`ý¦ÍbçÁmWQUºÀ 0³ûÞÆ€PÓÎí½./ÄºÖ_l˜U±ð[ð·ÌF }19ò’Ioß¶-ãä+�X"žS+°páBìÝ·Û·mCÿŽ¿Ûº•
¿›g0#T¼Gá_wcÿHîo1þÏ|ù½ïLÂ×f‹)S €Y4ô©¶ÕïB>PN	X<@B•Õ”­0}ûŠ@U9åmœ±œ° ôTžÖy œ`šö‚Ô$Ó®€¹Ò‡@½àae]^0o6Ïtû3¯3‚zj4¼CXœ' šV.„aÁºü`¨ËñPcÃ è,–e?GH×õO«æ*ë7mw¾õñÎýoüÀ¥ DÞD`ñ{án›Îí¨3]¥´°sÞ„P.G8qL+>ü-³œ},K`ïž=Ø¹sN?ý}H$9œ@>°~ýzÜóû{	��#;¶`Á) ›wæXÇ>?P:Ñ þ¶g;úr	bÆÐÀ3ôüg¾tâß'÷[ÌÅ”*  ¸µë•·ÓJàâRáABv«aì‰õÃœw‡ûÇòy5«No`=Ás8_x-8_Ü-æ*/z@X L:"0z{(¨®eÌzÖãç«ÃrÝvM÷f” Ãñ`]>pî,w€!ýy,!Ô„,kàDªÊ_ H=á„�SM2ž`-Õ”/txó6Pc3€Z–ã©îJâ_´œ¯| œ7dÞ3j¤c+8on¨­RŸ¿˜ð[°,K	tuÁ³/½ŠSO>	”ÒŒÈ'½^/Þsüñ¸ëîßP92@”¾ý˜yâ9±ý@yáî@¯uÅ¶Ë’tÅß¿râŸ&û»ÌÇ”+ ÀTŸž±&F€3J)FÕñèð hY¿ióOÆÒ5gÅÌ¥ÛÂ.ï'YÑã',=ƒ»iNFØÞ]2¿0Âr`Ñl�á«ëò˜ÖÇgÂ…Œà‚¡HWÀ‚É' º
Â‰émX—º"†BÞ•q	øP8—z"L©aˆ Ndæ*jÐ9/L6QÈðâIÔ0þƒªÒ- ÎEZð½3“Àqë	l ç	B5æøö¬è.ÈíÌ8¿X×V–í·PNø-ø[f£eùzÒ³õYhR#ƒý¸ÿÑ'1á"Ô…PU^¯·@	Ìž=®@yâÑG0xä ¼F+OÚT5áñP/uên/G¾öü—×þ|¢¿?'˜
  n=òò‹å”@“àÅýÛ(5ß‘#»þ:�è<°Ut¬L1‚ûÀôÑ9_êjCx„<"·*gZïÊ‚„°¶Ã‹¶9 „ãÁºý0²,yÂpà¼A€¦âÀ¨K`YbC;á\^PM±,‚•ÔÐ?àó ia˜õ›®8<Ö¶aÅ`úöÛO7?wRCÿ2€• ÄÑÿD"Ô¶€sû!„ÁºrÛt	Ázð�Ñ¤KØYW .øÝÎÓu]5�hYszw¼56MJà‰G�ªiX¶lTU…(Š0#G	œ´nM†èÜù&8–ÇìåkÊ~^9á¹3ŠÙÿãŸ]õ�j~oãÁ´Q €©>3cà;%À³:µÙë5ctŽÿÈ¿î‘óõŒÙ
Šy³Ûá9¸x^‘Ç`¼PÐ	Ã‚ ™Pßèv„1sr¶§-Ftƒjr†`òy.Ã»Ày‚E Ô¶@ð×‚Pš”  €zYç�­_aÎ°„Ô–'ë7^qªO°– Çƒ�3@éGA˜ëº¿õKjè—™Ÿ xgÂÛñø¬&\ |ÚÜ·¢&£×ã†X—›ÃŸë
�œ Sø=Bå½ü�3ß{ÂýÝH¦“…¶oÛ†g_z‹ÌË²`,Ëæ(�sÏ>¯¾ñ:öîÙƒ}oþl%àwq%	?»Ò^ÀLôyáËko¬øÂ&Ó²F÷ÕuWþ!ä:;%�•[¿isÃX&]{ç©*Åú{Öœ9hjiË¼NièIØ¾WOF`hjÁvCNeòË„¼Ôè�í,>5: -ÎÙFºƒ–Œ‚j*9irÑ¨±‘Rõ} é!QP#¯Àœ	‚­ øíÞÌr<uÕ6¶¦bÃL–3£n?XÑÂæ¡¢œ7”+øY¯åö”‚‡gPã+ž;_	>u¶Þõ_™ûÄr<½ôÒ"—\|1Z[[QSSŽã2)Ã‰H§�q¶l1»½ÿãÿ§|ô‹9î€A)ê<ýÅ…ÿÅCüÝfåŸŠ,?'˜–
 (®(¥8ãµ_§Çd�}VZÇçnžË	â¾Ì�`9¿z-Ø¬¦ŽbHªFÁ{©¦BKFl�kÈ)èR¼@ø-hÉ(4›n¼T“¡ÆÃÐ“…¯šb†³,92CŠƒ¦¢PÑLb¥à½¦Ïºý`õàýµéûÁ›.�è1óòPJð­|«Ùaù²¤ŸS¿Ä‡zñÒ/¾‰èîÑq®šF|ò²�ââ�ŸI¶Š‡úûûqÞyçg”Àâ3>‚‹¯ùO¸86“áW¬¦°/î¦¯ðÓX À+ë®¼†!ä¦|%ð“#/â¶ÎW Â<jŒ¹ï`¾ÐÖÜˆ¶¹2¯ËªŽ½qÛ÷–R  §-;š
-6Ã¦×}1E@Œè†ª@—bfß,¥ JI“‹ÐU[®0ùŠì:â6Âò`8$]‘¿Ò[(%ø ÒaÓ@ÁûKYc5ù�âàS÷aû½?ÌQ’3f¶ãü>„‹?t>QWW‡ÆÆÆK`î¢¥¸ôúŸcþ¼yEsûûN¾Àôóùó1­ `¯²‹ƒÆ4Ž*�×ßê‹G÷RUÎt£X¼òÃïqe*‚â2ú£öš†œ„žGþ±é]—“%• PÜÈ¼žCKFaÈ)3¡ÈUØŸê¨*ÃÐÌº+$i7Ô¼_\Æ¬'Î29¶øÊfÖBøl{ôºÝàƒE_·³ªiò—ƒÁÞŽwþv_ŽûÄ{ƒ¸äƒçâ}§�†µk×¢½Õt/þÈ‡ÓCOM«ákßù–¯ÛPx\�âÁ·qp¤ð™îÂL3Ð·yùÅOµ­~;;Y((¸±#Þ‡ÃR Ôƒ1’�‡ž¹GjX{n”Rúk["#MÍ£%©^�CBR*· “åÏ&Ù¬UÎL)v¯„¹3¢„-]Hgr¿~$È!�4É	`Ò†¬ÛÖí7ßgóÃºýf“à6žÒiÌ×Ærà<3¥7Ý©×n?Kðyméðµ2#Í}Bnu~wŽË5‘ðz½xÏ)ïÃŠ÷_LâI	#‡vQjÄPelß¶<ð xðÏØþö[ðx½¸òÊ+‘’u¼òòKÐ¤žùó½èîÄÒeË!zÌ,G3· G"¹ßch�%éŠéê+…ioXH÷¸Ãj(’M2žàìñ”Õ.ºúö]TWZç‚ºA±w0i;ž
0-ª«¶«ÕUh‰(¨Vš«44†’*jX1uª«™QÞ†’²%#+�¥´XÑÂ‰`8Œè)iXû³ÞPŽÒsŸÏ7i«¾…/�PžùêÅÞ§îÇÝƒDa4™÷qüÒÅèêîÆ‘Ã£=9]5�øäµÿŠ¥›>ˆÞ,håE€ažè—>ý…Õ�OÚŽG� 2G~K™C)ÅEoÞ�© äû ½v¬Ç]üõ{×ÉÈs™›ÂrX´leŽ+�Pt´ç\¢ ª¤�’Š¹–ŒÂ�âpÓìOæpùI5Ù º
CÓ@59£J¹ Ù¥¹¥Ìz»÷–sJÁçóÁç&ÔßÏ†‹cÐè –P6:¥Úý*^zìAt¾ñœ­2°½–YÇ¡õ_Dý’ÌxôIïæSU
 H·ëþYû@ï[¸qÿß€jXy„ ÛëÇ’eËsLT;>ÀÃ�æ›'ñ’JÀ©5`A—S%]ˆjÀIˆÎ$ýÜ¯ö™{éáñŽyxfÂ- »U¿DŽ@îÂ��Ûpø­W1ØÝ‰ÃûÞ�4Ü[4ìê›uZÎüVo¸ØLdï‰ÀQ§  3cíÔÀÝnUË
X¿i³8¸bãÖlW ?* ä*Žãàwå®„²,#/½ÒWb f
-ÕTèR†’§ÙŸsì"ñ{Â‰ãzÀ|ÁåÇævÏå:aV€“Uß~‘E£_ _„“§4<¿ë0ö’}ºªüµV—>üÌ�„'ä¢&G¥°ðêº+ÿãÏý;¯³¬ Â	Ç�§Ùf~n  ,X¸¡ºúœýºFˆ«(~N”€Sk€p¢m�j*¨&C—S²RÅ@8³JÑúk0èxQLð³Qm%À ÞËÃïpDW6šýBîâïH¨øëÎ~„S6n•®MÛ¿Õ
 0ÉÁ5[~ú€ü†ñ¾5Þ{‹¯úõçCÏao—.=žÀhs‹ƒ[· nþ
#¦1EŸpM7�ÅÒ†óQNS E�—¥ò�i%™¿›Çäª4$0}|–ãK
~6ªå
„\j=Ø
›Íº­�â«> ¼Õ—À“ïl§”FYª_9™<'G½ Òg«ØC=Ÿ°HA£2/Üþm�zœö±kÐW‘J§Þ—ã,P]5}þ<×€qùÊ¾w<¯p»D°_0°Ó	ÆkxM>¾bÁÊ¯ú’ªã©}aÛD0B�í^V¿üh"ûŠá]¡ ª�õ›6‹ƒ+7>F55“e¨w£ÿ±_Aî¥þÕ$ª�aŽ”€— ºœÌTV²ú�cQ „åáu‹­öÅ0+À+°¨óðûù@y_ º"2þº³ß6\W¤;ý�Ýö™é4âm<8¦ Š`Ãõ÷‡ú¢á—%¹pèå‡††^yø/ 0çÔ7ŸsÕÿdö3ƒ	C©ÒJ@Ó(RÒ‘5`�°|Ú2Hë�N€µÒWCèót9ËG�às,ƒf¿ ŸPüÜUƒâ¥ýƒx³§0òòn1ùîËTŸÀtÅ37^îøÜÍgK�ÛÏyëù{ :�ÛùãNCRÑáÒD�~"¯¡;oÄS68–÷ÿÛ;ûØªÎ:ŽŸç9çžû~o_i+XÖÂºN ¸¦BjL†fâÌÔÄlþ�C—8ÙœgÒD3’EˆD·l¨™Fb”2§t&3å5aH#8y]K¡o—{{_ÎÛóøÇí)íí¹¯½·´ô|’þçÐÒÛþ>Ïï÷{~Ï¹¾t�Oªy{ÀØ¤¡$�wê­�#nè�Þ£’«bŸIB3r–Ó	| ¨ñÉ¨óåÎ¤zo©xû¿ƒ¶�>"xOÈÍ6üëÉÕsj‹¯œ ªV®?ÚøÙo>èó°¼½m\	ÍD_4�çYó•…œ †~{`Lã×r‚°t°QI†wLJ f$Ø³‘Y
Hð+¥5÷,
I÷Sº‰“W†mW} s¾ËŸG Ò±î1¥·©%e=EØ%Ix`Åýðz&Oèé&G_T³­íÈ&‚BÏÐO—*ÑoÕX1Bn·Dv3x]¬äÀ÷¸ø$¸åÜ¥Åù›	t_²ýYÝM�¾\8(êUßûí�(¥ã']’„em-‡'¿µç‘”9åð¹ÈÁ|€µPÊôÞD‰ Î¯ä¬ó�ô¾þ‘‹CüjD�r£"J¸¹ÛûæË�wK£/Ž Š uó®Ù<1Q Ð¾´�õuSî/¦$°PU¦¡C3sPóN
 äfð¹¼òí8(Å¯ü…~¾tŸrØC´ïßí«þDIëæ]-²ÇˆJRÛÄ¿_ØÔ€%Í‹@3fƒJÉBnÝˆ§TŒêÈz
±Ì¤ ¬•>3è'Â
žæóŒ5ó¾ÎÎ\�ãôµû'<Ý¥þBpPk;÷…oÄ"oP&Mz‘ÏÀò{ï™Ò 
ïØÇ$4šnTD•€W¦ðH~E*x¿_f>9{P†oþHOò»4œýu7�í�ÑÁæâ9pP"ëS?¾~;¥ô©ÌkíK[° ¶fJ6 ¤Ë‚�¸žõ2ß`Œn
$tUUn4æ¢œ�©€ÌXÑoGf) 1Š�›!ì‘rvõ-ÎßLàäÕûù}ÌÏtßG Ó¤mËž�„ÒßdöªX|�}6À9GLãˆ$�)A\èPŒ…n
è¦	M7 ¼h)”" +ÐeFà–(%�))ë_«(é>A®±Ýñ×‚\HàÔµHÖÀ'‚÷<ò3så�•Æ@ÈÖ €ÖÅÍXÔXo›dŠ œ'ä,1èœŒÏ
hÆd9h‚¢Ú+AfS¥#3iì·Cb•	òlÈŒ¢ÚÃpí½XÝ±&ïŠŸÒMôôÇq¦÷VVÁ{ˆà?Ÿ�u~.”‰\%�Ï@[sã”íÂ‰$’Ihj
	:3Ûù&äf
™Q„ÜBn6ð'ïÇéãÝønç‹¶õ~$i §wïhY{#NàçÆ@™ißº·C¨‰Wì²�\eA×îN|aÓ³ ž bª�HÊDÊ˜~�Ÿ�;) �ÌThº_`³ÊóD?Øð€Xºjybû„=t.peDÅÙ¾ˆí>¾…ø…á äÊ€©":õìÝö=±õà…I?Õ0SÓ•’ÁL
Àêî—Djæýú‡�ãüÑ.´Ü·ŸÚú*.Ç�³ÏÁ9ìSè‹N�_Ž *Hëæ]-²?¼�<bw½¡* _¨ÿüñ— ÏüñxÖÏe˜1Õ@ÊUe¡R`pI
#EüDâš‰¿¼þN½ö“ÿ&ís…ë·,ùÖKA¥nÑ¤û„Q®«ûBn¶c¾wõ‹ÅÀÐ¾uo‡ÐÏgÎ À‡Ý�è§ú›?¶áÉ_í/ø0Žj˜Hh&R†@Êà%gå€Ì(Ü#ž±!ŸbƒÝ"®™¸8Åå�(†ãôèÎ¾ðè¿!øêUóDô¹ûŸýýÓîÆ% ‚÷¨£‘ßÕpí•ùº�?]Ì m[öl$À6«?9w}‡v�z‚où›Z‡Ú¾Ñ‰†Új,j¬G•·ð·Æ¶P�´t“§w¸€É“gÍr	ÀjøSJ!Q2~W‘\Œ–´ªÛÑÓ0��}&Wþôü±‘Ó]«­?Éµhí/»ïsÒüéãàÐ¶eÏFBðÔ…�Oüˆëj7 Ô¬zh°ñó›Æg	˜âÁ’ú ÔÖ”$;3�%˜"mƒÄðø½^„«Òo*MØâ+G`gc$©ãÃáQÜ¸•Â`,5O=“¸úÎù�¯-ðÓ;�#€YÂÂ/=ýNxÙšOÛ]óHµÕ¨«¡.è+Û™ý÷ßzJ 
ŸøÌ+ö}é\`(®c /8à-L]û»¼«®¶fï\{Þþ\Áy"Ð,Á·xÅKä£¢9óZÒ¸Ô?„KýCé{ƒ!,)üú¼ð¹J;9øþ¹s P6Ä5‘”�áX·b£IqÛ”>\ð˜0ŒnÅëÿƒ/6xÀ©ë+�“Ì2Ú·îízêæ=l';<AUÐÅ¥ äSàRÜðz<ðÉ4g¶ð‹¯}LVð³?Éû5t. 1Õ„j
Dã	hj
#) ©iˆ«zÁ+ûD˜ËÝ#8?”ê;Xsâo'çÃüÙ„#€YL)2ÈÄ#hÌ�¾ÛY‚âR�ìEWçWo Àºmo,hjjÄ(—93’4ÅÓ‰aRÓ�4	¸¡•ÜvXïûàDC0ü¶³ÊßYÌZ7ïjq¹½Ÿ’k=óV•*‹¡ãÐßõÛM ÐôÐw^®[ýpÙÿÏÌåî1tí]SMô˜ÉÑcÎ
?ûp0GiÝ¼«EòøWJ×È¡ú6®«íÅH¡÷ÀÎñ­µª•ë�6?úÜƒ…þÛ‰pÁc²â½lèÚ»ŒI×)ÁY¯$Îðý¯œw‚}öãà.bmç¾°¨ªi¾qå­r¸¾Åˆ.¡‘ƒµ~®«íÖ}¢ùì¶¯¬¦Þ „ÉË—ÿôÍnëº™Œ»ÃuQ ÐâÑ^êrßdLº®%¢ƒn_ð†ß«ôs-u“Œ]qRø¹ÍÿÒ‡+¦Å1È®    IEND®B`‚               h          ¨   00     ¨%          ›     X4   V S _ V E R S I O N _ I N F O     ½ïþ                  ?                        ¸   S t r i n g F i l e I n f o   ”   0 8 0 9 0 4 b 0   ,   C o m p a n y N a m e     a m p h p   Ô V  F i l e D e s c r i p t i o n     E x e c u t e s   a   c o m m a n d   a n d   p a s s e s   t h e   s t d i o   s t r e a m s   o f   t h e   c r e a t e d   p r o c e s s   t o   T C P   s o c k e t s   0   F i l e V e r s i o n     1 . 0 . 0 . 0   :   I n t e r n a l N a m e   P r o c e s s W . e x e     V   L e g a l C o p y r i g h t   C o p y r i g h t   ( C )   a m p h p   2 0 1 7     B   O r i g i n a l F i l e n a m e   P r o c e s s W . e x e     @   P r o d u c t N a m e     P r o c e s s   W r a p p e r   4   P r o d u c t V e r s i o n   0 . 0 . 0 . 0   D    V a r F i l e I n f o     $    T r a n s l a t i o n     	°<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='asInvoker' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>
                                                                                                                                                                                                                                                                                                                                                              ü   0)050U0k0u0‡0£0¯0¶0Ð0Ü0ü0
1G1z1ˆ1Ž1�2×2ú23)363<3c3·3Á3Ú3û3444H4V4�4ž4¥4±4¿4ÿ45#5v5œ5¬56&6A6e6�6Õ78/8Z8·8Ã8ê8ý899M9g9¢9¶9ß9ó9û9:
:":J:d:j:¡:×:å:ý:;*;Q;W;‹;ß;å;÷;<)<N<X<k<…<Ž<”<Á<â<é<ó<
==+=L=b==ª=Á=ë=>->_>g>„>Ç>7?Y?’?œ?¢?±?è?î?      L  0,0>0F0Q0V0a0k0¢0³0â0ì0ò0&1/151‚1Â1û142M2W2]2”2�2£2Ù23H3‰3�3º3Ë3Ú3é344/4>4\4‡4¢4µ4Å4õ4'5B5U5e5y5ú5$6-6I6m6‘6©6Ë6ß6å6ë6ñ67/777<7A7O7W7n7v7˜7œ7 7¤7¨7±7ß7"8V8�8™8È8Ý8'909G9r9‚9´9å9ð9õ9::?:f:‡:œ:¤:º:Å:Ë:Ñ:Ú:å:õ:<;e;Å;ó;<	<</<4<A<B=K=V=]=}=ƒ=‰=�=•=›=¢=©=°=·=¾=Å=Ì=Ô=Ü=ä=ð=ù=þ=>>>(>8>H>Q>¶>â>1?D?W?c?s?„?ª?¿?Æ?Ì?Þ?è?   0  ¨   F0S0z0‚0›0Õ0ð0ü011!1P1X1p1v1¡1Ç1Ð1Ö12²2Ñ2Û2ì2ú2;3A3Š3�3µ3º3ß3ñ34[4`4s4�4œ4§4/585@5‡5–5�5Ó5Ü5é5ô5ý5666"6(6.646:6@6F6L6R6X6^6d6j6p6v6|6‚6ˆ6Ž6”6š6 6¦6¬6²6ð6 @     p1x1„1ˆ1 1¤1 P  $   3 3$3(3,30343ü5 66,909L9P9 p     0 0$0,00080<0D0                                                                                                                                                                                                <?php

namespace Amp\Process\Internal;

final class ProcessStatus
{
    const STARTING = 0;
    const RUNNING = 1;
    const ENDED = 2;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}<?php

namespace Amp\Process\Internal;

use Amp\Deferred;
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
use Amp\Struct;
abstract class ProcessHandle
{
    use Struct;
    /** @var ProcessOutputStream */
    public $stdin;
    /** @var ProcessInputStream */
    public $stdout;
    /** @var ProcessInputStream */
    public $stderr;
    /** @var Deferred */
    public $pidDeferred;
    /** @var int */
    public $status = ProcessStatus::STARTING;
}<?php

namespace Amp\Process\Internal\Posix;

use Amp\Deferred;
use Amp\Process\Internal\ProcessHandle;
/** @internal */
final class Handle extends ProcessHandle
{
    /**
     *
     */
    public function __construct()
    {
        $this->pidDeferred = new Deferred();
        $this->joinDeferred = new Deferred();
        $this->originalParentPid = \getmypid();
    }
    /** @var Deferred */
    public $joinDeferred;
    /** @var resource */
    public $proc;
    /** @var resource */
    public $extraDataPipe;
    /** @var string */
    public $extraDataPipeWatcher;
    /** @var string */
    public $extraDataPipeStartWatcher;
    /** @var int */
    public $originalParentPid;
}<?php

namespace Amp\Process\Internal\Posix;

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Deferred;
use Amp\Loop;
use Amp\Process\Internal\ProcessHandle;
use Amp\Process\Internal\ProcessRunner;
use Amp\Process\Internal\ProcessStatus;
use Amp\Process\ProcessException;
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
use Amp\Promise;
/** @internal */
final class Runner implements ProcessRunner
{
    const FD_SPEC = [
        ["pipe", "r"],
        // stdin
        ["pipe", "w"],
        // stdout
        ["pipe", "w"],
        // stderr
        ["pipe", "w"],
    ];
    /** @var string|null */
    private static $fdPath;
    /**
     *
     */
    public static function onProcessEndExtraDataPipeReadable($watcher, $stream, Handle $handle)
    {
        Loop::cancel($watcher);
        $handle->extraDataPipeWatcher = null;
        $handle->status = ProcessStatus::ENDED;
        if (!\is_resource($stream) || \feof($stream)) {
            $handle->joinDeferred->fail(new ProcessException("Process ended unexpectedly"));
        } else {
            $handle->joinDeferred->resolve((int) \rtrim(@\stream_get_contents($stream)));
        }
    }
    /**
     *
     */
    public static function onProcessStartExtraDataPipeReadable($watcher, $stream, $data)
    {
        Loop::cancel($watcher);
        $pid = \rtrim(@\fgets($stream));
        /** @var $deferreds Deferred[] */
        list($handle, $pipes, $deferreds) = $data;
        if (!$pid || !\is_numeric($pid)) {
            $error = new ProcessException("Could not determine PID");
            $handle->pidDeferred->fail($error);
            foreach ($deferreds as $deferred) {
                /** @var $deferred Deferred */
                $deferred->fail($error);
            }
            if ($handle->status < ProcessStatus::ENDED) {
                $handle->status = ProcessStatus::ENDED;
                $handle->joinDeferred->fail($error);
            }
            return;
        }
        $handle->status = ProcessStatus::RUNNING;
        $handle->pidDeferred->resolve((int) $pid);
        $deferreds[0]->resolve($pipes[0]);
        $deferreds[1]->resolve($pipes[1]);
        $deferreds[2]->resolve($pipes[2]);
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::enable($handle->extraDataPipeWatcher);
        }
    }
    /**
     * @inheritdoc
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle
    {
        $command = \sprintf('{ (%s) <&3 3<&- 3>/dev/null & } 3<&0; trap "" INT TERM QUIT HUP;pid=$!; echo $pid >&3; wait $pid; RC=$?; echo $RC >&3; exit $RC', $command);
        $handle = new Handle();
        $handle->proc = @\proc_open($command, $this->generateFds(), $pipes, $cwd ?: null, $env ?: null, $options);
        if (!\is_resource($handle->proc)) {
            $message = "Could not start process";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            throw new ProcessException($message);
        }
        $status = \proc_get_status($handle->proc);
        if (!$status) {
            \proc_close($handle->proc);
            throw new ProcessException("Could not get process status");
        }
        $stdinDeferred = new Deferred();
        $handle->stdin = new ProcessOutputStream($stdinDeferred->promise());
        $stdoutDeferred = new Deferred();
        $handle->stdout = new ProcessInputStream($stdoutDeferred->promise());
        $stderrDeferred = new Deferred();
        $handle->stderr = new ProcessInputStream($stderrDeferred->promise());
        $handle->extraDataPipe = $pipes[3];
        \stream_set_blocking($pipes[3], false);
        $handle->extraDataPipeStartWatcher = Loop::onReadable($pipes[3], [self::class, 'onProcessStartExtraDataPipeReadable'], [$handle, [new ResourceOutputStream($pipes[0]), new ResourceInputStream($pipes[1]), new ResourceInputStream($pipes[2])], [$stdinDeferred, $stdoutDeferred, $stderrDeferred]]);
        $handle->extraDataPipeWatcher = Loop::onReadable($pipes[3], [self::class, 'onProcessEndExtraDataPipeReadable'], $handle);
        Loop::unreference($handle->extraDataPipeWatcher);
        Loop::disable($handle->extraDataPipeWatcher);
        return $handle;
    }
    /**
     *
     */
    private function generateFds() : array
    {
        if (self::$fdPath === null) {
            self::$fdPath = \file_exists("/dev/fd") ? "/dev/fd" : "/proc/self/fd";
        }
        $fdList = @\scandir(self::$fdPath, \SCANDIR_SORT_NONE);
        if ($fdList === false) {
            throw new ProcessException("Unable to list open file descriptors");
        }
        $fdList = \array_filter($fdList, function (string $path) : bool {
            return $path !== "." && $path !== "..";
        });
        $fds = [];
        foreach ($fdList as $id) {
            $fds[(int) $id] = ["file", "/dev/null", "r"];
        }
        return self::FD_SPEC + $fds;
    }
    /**
     * @inheritdoc
     */
    public function join(ProcessHandle $handle) : Promise
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::reference($handle->extraDataPipeWatcher);
        }
        return $handle->joinDeferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function kill(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::cancel($handle->extraDataPipeWatcher);
            $handle->extraDataPipeWatcher = null;
        }
        /** @var Handle $handle */
        if ($handle->extraDataPipeStartWatcher !== null) {
            Loop::cancel($handle->extraDataPipeStartWatcher);
            $handle->extraDataPipeStartWatcher = null;
        }
        if (!\proc_terminate($handle->proc, 9)) {
            // Forcefully kill the process using SIGKILL.
            throw new ProcessException("Terminating process failed");
        }
        $handle->pidDeferred->promise()->onResolve(function ($error, $pid) {
            // The function should not call posix_kill() if $pid is null (i.e., there was an error starting the process).
            if ($error) {
                return;
            }
            // ignore errors because process not always detached
            @\posix_kill($pid, 9);
        });
        if ($handle->status < ProcessStatus::ENDED) {
            $handle->status = ProcessStatus::ENDED;
            $handle->joinDeferred->fail(new ProcessException("The process was killed"));
        }
        $this->free($handle);
    }
    /**
     * @inheritdoc
     */
    public function signal(ProcessHandle $handle, int $signo)
    {
        $handle->pidDeferred->promise()->onResolve(function ($error, $pid) use($signo) {
            if ($error) {
                return;
            }
            @\posix_kill($pid, $signo);
        });
    }
    /**
     * @inheritdoc
     */
    public function destroy(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->status < ProcessStatus::ENDED && \getmypid() === $handle->originalParentPid) {
            try {
                $this->kill($handle);
                return;
            } catch (ProcessException $e) {
                // ignore
            }
        }
        $this->free($handle);
    }
    /**
     *
     */
    private function free(Handle $handle)
    {
        /** @var Handle $handle */
        if ($handle->extraDataPipeWatcher !== null) {
            Loop::cancel($handle->extraDataPipeWatcher);
            $handle->extraDataPipeWatcher = null;
        }
        /** @var Handle $handle */
        if ($handle->extraDataPipeStartWatcher !== null) {
            Loop::cancel($handle->extraDataPipeStartWatcher);
            $handle->extraDataPipeStartWatcher = null;
        }
        if (\is_resource($handle->extraDataPipe)) {
            \fclose($handle->extraDataPipe);
        }
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        if (\is_resource($handle->proc)) {
            \proc_close($handle->proc);
        }
    }
}<?php

namespace Amp\Process\Internal\Windows;

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Loop;
use Amp\Process\Internal\ProcessStatus;
use Amp\Process\ProcessException;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class SocketConnector
{
    const SERVER_SOCKET_URI = 'tcp://127.0.0.1:0';
    const SECURITY_TOKEN_SIZE = 16;
    const CONNECT_TIMEOUT = 1000;
    /** @var resource */
    private $server;
    /** @var PendingSocketClient[] */
    private $pendingClients = [];
    /** @var Handle[] */
    private $pendingProcesses = [];
    /** @var string */
    public $address;
    /** @var int */
    public $port;
    /**
     *
     */
    public function __construct()
    {
        $flags = \STREAM_SERVER_LISTEN | \STREAM_SERVER_BIND;
        $this->server = \stream_socket_server(self::SERVER_SOCKET_URI, $errNo, $errStr, $flags);
        if (!$this->server) {
            throw new \Error("Failed to create TCP server socket for process wrapper: {$errNo}: {$errStr}");
        }
        if (!\stream_set_blocking($this->server, false)) {
            throw new \Error("Failed to set server socket to non-blocking mode");
        }
        list($this->address, $this->port) = \explode(':', \stream_socket_get_name($this->server, false));
        $this->port = (int) $this->port;
        Loop::unreference(Loop::onReadable($this->server, [$this, 'onServerSocketReadable']));
    }
    /**
     *
     */
    private function failClientHandshake($socket, int $code)
    {
        \fwrite($socket, \chr(SignalCode::HANDSHAKE_ACK) . \chr($code));
        \fclose($socket);
        unset($this->pendingClients[(int) $socket]);
    }
    /**
     *
     */
    public function failHandleStart(Handle $handle, string $message, ...$args)
    {
        Loop::cancel($handle->connectTimeoutWatcher);
        unset($this->pendingProcesses[$handle->wrapperPid]);
        foreach ($handle->sockets as $socket) {
            \fclose($socket);
        }
        $error = new ProcessException(\vsprintf($message, $args));
        $deferreds = $handle->stdioDeferreds;
        $deferreds[] = $handle->joinDeferred;
        $handle->stdioDeferreds = [];
        foreach ($deferreds as $deferred) {
            $deferred->fail($error);
        }
    }
    /**
     * Read data from a client socket.
     *
     * This method cleans up internal state as appropriate. Returns null if the read fails or needs to be repeated.
     *
     * @param resource $socket
     * @param int $length
     * @param PendingSocketClient $state
     *
     * @return (string | null)
     */
    private function readDataFromPendingClient($socket, int $length, PendingSocketClient $state)
    {
        $data = \fread($socket, $length);
        if ($data === false || $data === '') {
            return null;
        }
        $data = $state->receivedDataBuffer . $data;
        if (\strlen($data) < $length) {
            $state->receivedDataBuffer = $data;
            return null;
        }
        $state->receivedDataBuffer = '';
        Loop::cancel($state->readWatcher);
        return $data;
    }
    /**
     *
     */
    public function onReadableHandshake($watcher, $socket)
    {
        $socketId = (int) $socket;
        $pendingClient = $this->pendingClients[$socketId];
        if (null === ($data = $this->readDataFromPendingClient($socket, self::SECURITY_TOKEN_SIZE + 6, $pendingClient))) {
            return;
        }
        $packet = \unpack('Csignal/Npid/Cstream_id/a*client_token', $data);
        // validate the client's handshake
        if ($packet['signal'] !== SignalCode::HANDSHAKE) {
            $this->failClientHandshake($socket, HandshakeStatus::SIGNAL_UNEXPECTED);
            return;
        }
        if ($packet['stream_id'] > 2) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_STREAM_ID);
            return;
        }
        if (!isset($this->pendingProcesses[$packet['pid']])) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_PROCESS_ID);
            return;
        }
        $handle = $this->pendingProcesses[$packet['pid']];
        if (isset($handle->sockets[$packet['stream_id']])) {
            $this->failClientHandshake($socket, HandshakeStatus::DUPLICATE_STREAM_ID);
            \trigger_error(\sprintf("%s: Received duplicate socket for process #%s stream #%d", self::class, $handle->pid, $packet['stream_id']), E_USER_WARNING);
            return;
        }
        if (!\hash_equals($packet['client_token'], $handle->securityTokens[$packet['stream_id']])) {
            $this->failClientHandshake($socket, HandshakeStatus::INVALID_CLIENT_TOKEN);
            $this->failHandleStart($handle, "Invalid client security token for stream #%d", $packet['stream_id']);
            return;
        }
        $ackData = \chr(SignalCode::HANDSHAKE_ACK) . \chr(HandshakeStatus::SUCCESS) . $handle->securityTokens[$packet['stream_id'] + 3];
        // Unless we set the security token size so high that it won't fit in the
        // buffer, this probably shouldn't ever happen unless something has gone wrong
        if (\fwrite($socket, $ackData) !== self::SECURITY_TOKEN_SIZE + 2) {
            unset($this->pendingClients[$socketId]);
            return;
        }
        $pendingClient->pid = $packet['pid'];
        $pendingClient->streamId = $packet['stream_id'];
        $pendingClient->readWatcher = Loop::onReadable($socket, [$this, 'onReadableHandshakeAck']);
    }
    /**
     *
     */
    public function onReadableHandshakeAck($watcher, $socket)
    {
        $socketId = (int) $socket;
        $pendingClient = $this->pendingClients[$socketId];
        // can happen if the start promise was failed
        if (!isset($this->pendingProcesses[$pendingClient->pid]) || $this->pendingProcesses[$pendingClient->pid]->status === ProcessStatus::ENDED) {
            \fclose($socket);
            Loop::cancel($watcher);
            Loop::cancel($pendingClient->timeoutWatcher);
            unset($this->pendingClients[$socketId]);
            return;
        }
        if (null === ($data = $this->readDataFromPendingClient($socket, 2, $pendingClient))) {
            return;
        }
        Loop::cancel($pendingClient->timeoutWatcher);
        unset($this->pendingClients[$socketId]);
        $handle = $this->pendingProcesses[$pendingClient->pid];
        $packet = \unpack('Csignal/Cstatus', $data);
        if ($packet['signal'] !== SignalCode::HANDSHAKE_ACK || $packet['status'] !== HandshakeStatus::SUCCESS) {
            $this->failHandleStart($handle, "Client rejected handshake with code %d for stream #%d", $packet['status'], $pendingClient->streamId);
            return;
        }
        $handle->sockets[$pendingClient->streamId] = $socket;
        if (\count($handle->sockets) === 3) {
            $handle->childPidWatcher = Loop::onReadable($handle->sockets[0], [$this, 'onReadableChildPid'], $handle);
            $deferreds = $handle->stdioDeferreds;
            $handle->stdioDeferreds = [];
            // clear, so there's no double resolution if process spawn fails
            $deferreds[0]->resolve(new ResourceOutputStream($handle->sockets[0]));
            $deferreds[1]->resolve(new ResourceInputStream($handle->sockets[1]));
            $deferreds[2]->resolve(new ResourceInputStream($handle->sockets[2]));
        }
    }
    /**
     *
     */
    public function onReadableChildPid($watcher, $socket, Handle $handle)
    {
        $data = \fread($socket, 5);
        if ($data === false || $data === '') {
            return;
        }
        Loop::cancel($handle->childPidWatcher);
        Loop::cancel($handle->connectTimeoutWatcher);
        $handle->childPidWatcher = null;
        if (\strlen($data) !== 5) {
            $this->failHandleStart($handle, 'Failed to read PID from wrapper: Received %d of 5 expected bytes', \strlen($data));
            return;
        }
        $packet = \unpack('Csignal/Npid', $data);
        if ($packet['signal'] !== SignalCode::CHILD_PID) {
            $this->failHandleStart($handle, "Failed to read PID from wrapper: Unexpected signal code %d", $packet['signal']);
            return;
        }
        // Required, because a process might be destroyed while starting
        if ($handle->status === ProcessStatus::STARTING) {
            $handle->status = ProcessStatus::RUNNING;
            $handle->exitCodeWatcher = Loop::onReadable($handle->sockets[0], [$this, 'onReadableExitCode'], $handle);
            if (!$handle->exitCodeRequested) {
                Loop::unreference($handle->exitCodeWatcher);
            }
        }
        $handle->pidDeferred->resolve($packet['pid']);
        unset($this->pendingProcesses[$handle->wrapperPid]);
    }
    /**
     *
     */
    public function onReadableExitCode($watcher, $socket, Handle $handle)
    {
        $data = \fread($socket, 5);
        if ($data === false || $data === '') {
            return;
        }
        Loop::cancel($handle->exitCodeWatcher);
        $handle->exitCodeWatcher = null;
        if (\strlen($data) !== 5) {
            $handle->status = ProcessStatus::ENDED;
            $handle->joinDeferred->fail(new ProcessException(\sprintf('Failed to read exit code from wrapper: Received %d of 5 expected bytes', \strlen($data))));
            return;
        }
        $packet = \unpack('Csignal/Ncode', $data);
        if ($packet['signal'] !== SignalCode::EXIT_CODE) {
            $this->failHandleStart($handle, "Failed to read exit code from wrapper: Unexpected signal code %d", $packet['signal']);
            return;
        }
        $handle->status = ProcessStatus::ENDED;
        $handle->joinDeferred->resolve($packet['code']);
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        // Explicitly \fclose() sockets, as resource streams shut only one side down.
        foreach ($handle->sockets as $sock) {
            // Ensure socket is still open before attempting to close.
            if (\is_resource($sock)) {
                @\fclose($sock);
            }
        }
    }
    /**
     *
     */
    public function onClientSocketConnectTimeout($watcher, $socket)
    {
        $id = (int) $socket;
        Loop::cancel($this->pendingClients[$id]->readWatcher);
        unset($this->pendingClients[$id]);
        \fclose($socket);
    }
    /**
     *
     */
    public function onServerSocketReadable()
    {
        $socket = \stream_socket_accept($this->server);
        if (!\stream_set_blocking($socket, false)) {
            throw new \Error("Failed to set client socket to non-blocking mode");
        }
        $pendingClient = new PendingSocketClient();
        $pendingClient->readWatcher = Loop::onReadable($socket, [$this, 'onReadableHandshake']);
        $pendingClient->timeoutWatcher = Loop::delay(self::CONNECT_TIMEOUT, [$this, 'onClientSocketConnectTimeout'], $socket);
        $this->pendingClients[(int) $socket] = $pendingClient;
    }
    /**
     *
     */
    public function onProcessConnectTimeout($watcher, Handle $handle)
    {
        $running = \is_resource($handle->proc) && \proc_get_status($handle->proc)['running'];
        $error = null;
        if (!$running) {
            $error = \stream_get_contents($handle->wrapperStderrPipe);
        }
        $error = $error ?: 'Process did not connect to server before timeout elapsed';
        foreach ($handle->sockets as $socket) {
            \fclose($socket);
        }
        $error = new ProcessException(\trim($error));
        foreach ($handle->stdioDeferreds as $deferred) {
            $deferred->fail($error);
        }
        \fclose($handle->wrapperStderrPipe);
        \proc_close($handle->proc);
        $handle->joinDeferred->fail($error);
    }
    /**
     *
     */
    public function registerPendingProcess(Handle $handle)
    {
        // Use Loop::defer() to start the timeout only after the loop has ticked once. This prevents issues with many
        // things started at once, see https://github.com/amphp/process/issues/21.
        $handle->connectTimeoutWatcher = Loop::defer(function () use($handle) {
            $handle->connectTimeoutWatcher = Loop::delay(self::CONNECT_TIMEOUT, [$this, 'onProcessConnectTimeout'], $handle);
        });
        $this->pendingProcesses[$handle->wrapperPid] = $handle;
    }
}<?php

namespace Amp\Process\Internal\Windows;

use Amp\Struct;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class PendingSocketClient
{
    use Struct;
    public $readWatcher;
    public $timeoutWatcher;
    public $receivedDataBuffer = '';
    public $pid;
    public $streamId;
}<?php

namespace Amp\Process\Internal\Windows;

/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class SignalCode
{
    const HANDSHAKE = 0x1;
    const HANDSHAKE_ACK = 0x2;
    const CHILD_PID = 0x3;
    const EXIT_CODE = 0x4;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}<?php

namespace Amp\Process\Internal\Windows;

use Amp\Deferred;
use Amp\Process\Internal\ProcessHandle;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class Handle extends ProcessHandle
{
    /**
     *
     */
    public function __construct()
    {
        $this->joinDeferred = new Deferred();
        $this->pidDeferred = new Deferred();
    }
    /** @var Deferred */
    public $joinDeferred;
    /** @var string */
    public $exitCodeWatcher;
    /** @var bool */
    public $exitCodeRequested = false;
    /** @var resource */
    public $proc;
    /** @var int */
    public $wrapperPid;
    /** @var resource */
    public $wrapperStderrPipe;
    /** @var resource[] */
    public $sockets = [];
    /** @var Deferred[] */
    public $stdioDeferreds;
    /** @var string */
    public $childPidWatcher;
    /** @var string */
    public $connectTimeoutWatcher;
    /** @var string[] */
    public $securityTokens;
}<?php

namespace Amp\Process\Internal\Windows;

/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class HandshakeStatus
{
    const SUCCESS = 0;
    const SIGNAL_UNEXPECTED = 0x1;
    const INVALID_STREAM_ID = 0x2;
    const INVALID_PROCESS_ID = 0x3;
    const DUPLICATE_STREAM_ID = 0x4;
    const INVALID_CLIENT_TOKEN = 0x5;
    /**
     *
     */
    private function __construct()
    {
        // empty to prevent instances of this class
    }
}<?php

namespace Amp\Process\Internal\Windows;

use Amp\Deferred;
use Amp\Loop;
use Amp\Process\Internal\ProcessHandle;
use Amp\Process\Internal\ProcessRunner;
use Amp\Process\Internal\ProcessStatus;
use Amp\Process\ProcessException;
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
use Amp\Promise;
use const Amp\Process\BIN_DIR;
/**
 * @internal
 * @codeCoverageIgnore Windows only.
 */
final class Runner implements ProcessRunner
{
    const FD_SPEC = [
        ["pipe", "r"],
        // stdin
        ["pipe", "w"],
        // stdout
        ["pipe", "w"],
        // stderr
        ["pipe", "w"],
    ];
    const WRAPPER_EXE_PATH = PHP_INT_SIZE === 8 ? BIN_DIR . '\\windows\\ProcessWrapper64.exe' : BIN_DIR . '\\windows\\ProcessWrapper.exe';
    private static $pharWrapperPath;
    private $socketConnector;
    /**
     *
     */
    private function makeCommand(string $workingDirectory) : string
    {
        $wrapperPath = self::WRAPPER_EXE_PATH;
        // We can't execute the exe from within the PHAR, so copy it out...
        if (\strncmp($wrapperPath, "phar://", 7) === 0) {
            if (self::$pharWrapperPath === null) {
                $fileHash = \hash_file('sha1', self::WRAPPER_EXE_PATH);
                self::$pharWrapperPath = \sys_get_temp_dir() . "/amphp-process-wrapper-" . $fileHash;
                if (!\file_exists(self::$pharWrapperPath) || \hash_file('sha1', self::$pharWrapperPath) !== $fileHash) {
                    \copy(self::WRAPPER_EXE_PATH, self::$pharWrapperPath);
                }
            }
            $wrapperPath = self::$pharWrapperPath;
        }
        $result = \sprintf('%s --address=%s --port=%d --token-size=%d', \escapeshellarg($wrapperPath), $this->socketConnector->address, $this->socketConnector->port, SocketConnector::SECURITY_TOKEN_SIZE);
        if ($workingDirectory !== '') {
            $result .= ' ' . \escapeshellarg('--cwd=' . \rtrim($workingDirectory, '\\'));
        }
        return $result;
    }
    /**
     *
     */
    public function __construct()
    {
        $this->socketConnector = new SocketConnector();
    }
    /**
     * @inheritdoc
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle
    {
        if (\strpos($command, "\x00") !== false) {
            throw new ProcessException("Can't execute commands that contain null bytes.");
        }
        $options['bypass_shell'] = true;
        $handle = new Handle();
        $handle->proc = @\proc_open($this->makeCommand($cwd ?? ''), self::FD_SPEC, $pipes, $cwd ?: null, $env ?: null, $options);
        if (!\is_resource($handle->proc)) {
            $message = "Could not start process";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            throw new ProcessException($message);
        }
        $status = \proc_get_status($handle->proc);
        if (!$status) {
            \proc_close($handle->proc);
            throw new ProcessException("Could not get process status");
        }
        $securityTokens = \random_bytes(SocketConnector::SECURITY_TOKEN_SIZE * 6);
        $written = \fwrite($pipes[0], $securityTokens . "\x00" . $command . "\x00");
        \fclose($pipes[0]);
        \fclose($pipes[1]);
        if ($written !== SocketConnector::SECURITY_TOKEN_SIZE * 6 + \strlen($command) + 2) {
            \fclose($pipes[2]);
            \proc_close($handle->proc);
            throw new ProcessException("Could not send security tokens / command to process wrapper");
        }
        $handle->securityTokens = \str_split($securityTokens, SocketConnector::SECURITY_TOKEN_SIZE);
        $handle->wrapperPid = $status['pid'];
        $handle->wrapperStderrPipe = $pipes[2];
        $stdinDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stdinDeferred;
        $handle->stdin = new ProcessOutputStream($stdinDeferred->promise());
        $stdoutDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stdoutDeferred;
        $handle->stdout = new ProcessInputStream($stdoutDeferred->promise());
        $stderrDeferred = new Deferred();
        $handle->stdioDeferreds[] = $stderrDeferred;
        $handle->stderr = new ProcessInputStream($stderrDeferred->promise());
        $this->socketConnector->registerPendingProcess($handle);
        return $handle;
    }
    /**
     * @inheritdoc
     */
    public function join(ProcessHandle $handle) : Promise
    {
        /** @var Handle $handle */
        $handle->exitCodeRequested = true;
        if ($handle->exitCodeWatcher !== null) {
            Loop::reference($handle->exitCodeWatcher);
        }
        return $handle->joinDeferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function kill(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        \exec('taskkill /F /T /PID ' . $handle->wrapperPid . ' 2>&1', $output, $exitCode);
        $failStart = false;
        if ($handle->childPidWatcher !== null) {
            Loop::cancel($handle->childPidWatcher);
            $handle->childPidWatcher = null;
            $handle->pidDeferred->fail(new ProcessException("The process was killed"));
            $failStart = true;
        }
        if ($handle->exitCodeWatcher !== null) {
            Loop::cancel($handle->exitCodeWatcher);
            $handle->exitCodeWatcher = null;
            $handle->joinDeferred->fail(new ProcessException("The process was killed"));
        }
        $handle->status = ProcessStatus::ENDED;
        if ($failStart || $handle->stdioDeferreds) {
            $this->socketConnector->failHandleStart($handle, "The process was killed");
        }
        $this->free($handle);
    }
    /**
     * @inheritdoc
     */
    public function signal(ProcessHandle $handle, int $signo)
    {
        throw new ProcessException('Signals are not supported on Windows');
    }
    /**
     * @inheritdoc
     */
    public function destroy(ProcessHandle $handle)
    {
        /** @var Handle $handle */
        if ($handle->status < ProcessStatus::ENDED && \is_resource($handle->proc)) {
            try {
                $this->kill($handle);
                return;
            } catch (ProcessException $e) {
                // ignore
            }
        }
        $this->free($handle);
    }
    /**
     *
     */
    private function free(Handle $handle)
    {
        if ($handle->childPidWatcher !== null) {
            Loop::cancel($handle->childPidWatcher);
            $handle->childPidWatcher = null;
        }
        if ($handle->exitCodeWatcher !== null) {
            Loop::cancel($handle->exitCodeWatcher);
            $handle->exitCodeWatcher = null;
        }
        $handle->stdin->close();
        $handle->stdout->close();
        $handle->stderr->close();
        foreach ($handle->sockets as $socket) {
            if (\is_resource($socket)) {
                @\fclose($socket);
            }
        }
        if (\is_resource($handle->wrapperStderrPipe)) {
            @\fclose($handle->wrapperStderrPipe);
        }
        if (\is_resource($handle->proc)) {
            \proc_close($handle->proc);
        }
    }
}<?php

namespace Amp\Process\Internal;

use Amp\Process\ProcessException;
use Amp\Promise;
interface ProcessRunner
{
    /**
     * Start a process using the supplied parameters.
     *
     * @param string $command The command to execute.
     * @param (string | null) $cwd The working directory for the child process.
     * @param array $env Environment variables to pass to the child process.
     * @param array $options `proc_open()` options.
     *
     * @return ProcessHandle
     *
     * @throws ProcessException If starting the process fails.
     */
    public function start(string $command, string $cwd = null, array $env = [], array $options = []) : ProcessHandle;
    /**
     * Wait for the child process to end.
     *
     * @param ProcessHandle $handle The process descriptor.
     *
     * @return Promise<int> Succeeds with exit code of the process or fails if the process is killed.
     */
    public function join(ProcessHandle $handle) : Promise;
    /**
     * Forcibly end the child process.
     *
     * @param ProcessHandle $handle The process descriptor.
     *
     * @throws ProcessException If terminating the process fails.
     */
    public function kill(ProcessHandle $handle);
    /**
     * Send a signal signal to the child process.
     *
     * @param ProcessHandle $handle The process descriptor.
     * @param int $signo Signal number to send to process.
     *
     * @throws ProcessException If sending the signal fails.
     */
    public function signal(ProcessHandle $handle, int $signo);
    /**
     * Release all resources held by the process handle.
     *
     * @param ProcessHandle $handle The process descriptor.
     */
    public function destroy(ProcessHandle $handle);
}<?php

namespace Amp\Process;

class StatusError extends \Error
{
}<?php

namespace Amp\Process;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\OutputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Failure;
use Amp\Promise;
final class ProcessOutputStream implements OutputStream
{
    /** @var \SplQueue */
    private $queuedWrites;
    /** @var bool */
    private $shouldClose = false;
    /** @var ResourceOutputStream */
    private $resourceStream;
    /** @var StreamException|null */
    private $error;
    /**
     *
     */
    public function __construct(Promise $resourceStreamPromise)
    {
        $this->queuedWrites = new \SplQueue();
        $resourceStreamPromise->onResolve(function ($error, $resourceStream) {
            if ($error) {
                $this->error = new StreamException("Failed to launch process", 0, $error);
                while (!$this->queuedWrites->isEmpty()) {
                    list(, $deferred) = $this->queuedWrites->shift();
                    $deferred->fail($this->error);
                }
                return;
            }
            while (!$this->queuedWrites->isEmpty()) {
                /**
                 * @var string $data
                 * @var \Amp\Deferred $deferred
                 */
                list($data, $deferred) = $this->queuedWrites->shift();
                $deferred->resolve($resourceStream->write($data));
            }
            $this->resourceStream = $resourceStream;
            if ($this->shouldClose) {
                $this->resourceStream->close();
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function write(string $data) : Promise
    {
        if ($this->resourceStream) {
            return $this->resourceStream->write($data);
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->shouldClose) {
            throw new ClosedException("Stream has already been closed.");
        }
        $deferred = new Deferred();
        $this->queuedWrites->push([$data, $deferred]);
        return $deferred->promise();
    }
    /**
     * @inheritdoc
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->resourceStream) {
            return $this->resourceStream->end($finalData);
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->shouldClose) {
            throw new ClosedException("Stream has already been closed.");
        }
        $deferred = new Deferred();
        $this->queuedWrites->push([$finalData, $deferred]);
        $this->shouldClose = true;
        return $deferred->promise();
    }
    /**
     *
     */
    public function close()
    {
        $this->shouldClose = true;
        if ($this->resourceStream) {
            $this->resourceStream->close();
        } elseif (!$this->queuedWrites->isEmpty()) {
            $error = new ClosedException("Stream closed.");
            do {
                list(, $deferred) = $this->queuedWrites->shift();
                $deferred->fail($error);
            } while (!$this->queuedWrites->isEmpty());
        }
    }
}<?php

namespace Amp\Process;

const BIN_DIR = __DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . 'bin';
const IS_WINDOWS = (PHP_OS & "\xdf\xdf\xdf") === 'WIN';
if (!\function_exists(__NAMESPACE__ . '\\escapeArguments')) {
    if (IS_WINDOWS) {
        /**
         * Escapes the command argument for safe inclusion into a Windows command string.
         *
         * @param string $arg
         *
         * @return string
         */
        function escapeArguments(string $arg) : string
        {
            return '"' . \preg_replace_callback('(\\\\*("|$))', function (array $m) : string {
                return \str_repeat('\\', \strlen($m[0])) . $m[0];
            }, $arg) . '"';
        }
    } else {
        /**
         * Escapes the command argument for safe inclusion into a Posix shell command string.
         *
         * @param string $arg
         *
         * @return string
         */
        function escapeArguments(string $arg) : string
        {
            return \escapeshellarg($arg);
        }
    }
}<?php

namespace Amp\Process;

use Amp\Loop;
use Amp\Process\Internal\Posix\Runner as PosixProcessRunner;
use Amp\Process\Internal\ProcessHandle;
use Amp\Process\Internal\ProcessRunner;
use Amp\Process\Internal\ProcessStatus;
use Amp\Process\Internal\Windows\Runner as WindowsProcessRunner;
use Amp\Promise;
use function Amp\call;
final class Process
{
    /** @var ProcessRunner */
    private $processRunner;
    /** @var string */
    private $command;
    /** @var string */
    private $cwd = "";
    /** @var array */
    private $env = [];
    /** @var array */
    private $options;
    /** @var ProcessHandle */
    private $handle;
    /** @var int|null */
    private $pid;
    /**
    * @param (string | string[]) $command Command to run.
    * @param (string | null) $cwd Working directory or use an empty string to use the working directory of the
    parent.
    * @param mixed[] $env Environment variables or use an empty array to inherit from the parent.
    * @param mixed[] $options Options for `proc_open()`.
    *
    * @throws \Error If the arguments are invalid.
    */
    public function __construct($command, string $cwd = null, array $env = [], array $options = [])
    {
        $command = \is_array($command) ? \implode(" ", \array_map(__NAMESPACE__ . "\\escapeArguments", $command)) : (string) $command;
        $cwd = $cwd ?? "";
        $envVars = [];
        foreach ($env as $key => $value) {
            if (\is_array($value)) {
                throw new \Error("\$env cannot accept array values");
            }
            $envVars[(string) $key] = (string) $value;
        }
        $this->command = $command;
        $this->cwd = $cwd;
        $this->env = $envVars;
        $this->options = $options;
        $this->processRunner = Loop::getState(self::class);
        if ($this->processRunner === null) {
            $this->processRunner = IS_WINDOWS ? new WindowsProcessRunner() : new PosixProcessRunner();
            Loop::setState(self::class, $this->processRunner);
        }
    }
    /**
     * Stops the process if it is still running.
     */
    public function __destruct()
    {
        if ($this->handle !== null) {
            $this->processRunner->destroy($this->handle);
        }
    }
    /**
     *
     */
    public function __clone()
    {
        throw new \Error("Cloning is not allowed!");
    }
    /**
     * Start the process.
     *
     * @return Promise<int> Resolves with the PID.
     *
     * @throws StatusError If the process has already been started.
     */
    public function start() : Promise
    {
        if ($this->handle) {
            throw new StatusError("Process has already been started.");
        }
        return call(function () {
            $this->handle = $this->processRunner->start($this->command, $this->cwd, $this->env, $this->options);
            return $this->pid = (yield $this->handle->pidDeferred->promise());
        });
    }
    /**
     * Wait for the process to end.
     *
     * @return Promise<int> Succeeds with process exit code or fails with a ProcessException if the process is killed.
     *
     * @throws StatusError If the process has already been started.
     */
    public function join() : Promise
    {
        if (!$this->handle) {
            throw new StatusError("Process has not been started.");
        }
        return $this->processRunner->join($this->handle);
    }
    /**
     * Forcibly end the process.
     *
     * @throws StatusError If the process is not running.
     * @throws ProcessException If terminating the process fails.
     */
    public function kill()
    {
        if (!$this->isRunning()) {
            throw new StatusError("Process is not running.");
        }
        $this->processRunner->kill($this->handle);
    }
    /**
     * Send a signal signal to the process.
     *
     * @param int $signo Signal number to send to process.
     *
     * @throws StatusError If the process is not running.
     * @throws ProcessException If sending the signal fails.
     */
    public function signal(int $signo)
    {
        if (!$this->isRunning()) {
            throw new StatusError("Process is not running.");
        }
        $this->processRunner->signal($this->handle, $signo);
    }
    /**
     * Returns the PID of the child process.
     *
     * @return int
     *
     * @throws StatusError If the process has not started or has not completed starting.
     */
    public function getPid() : int
    {
        if (!$this->pid) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->pid;
    }
    /**
     * Returns the command to execute.
     *
     * @return string The command to execute.
     */
    public function getCommand() : string
    {
        return $this->command;
    }
    /**
     * Gets the current working directory.
     *
     * @return string The current working directory an empty string if inherited from the current PHP process.
     */
    public function getWorkingDirectory() : string
    {
        if ($this->cwd === "") {
            return \getcwd() ?: "";
        }
        return $this->cwd;
    }
    /**
     * Gets the environment variables array.
     *
     * @return string[] Array of environment variables.
     */
    public function getEnv() : array
    {
        return $this->env;
    }
    /**
     * Gets the options to pass to proc_open().
     *
     * @return mixed[] Array of options.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * Determines if the process is still running.
     *
     * @return bool
     */
    public function isRunning() : bool
    {
        return $this->handle && $this->handle->status !== ProcessStatus::ENDED;
    }
    /**
     * Gets the process input stream (STDIN).
     *
     * @return ProcessOutputStream
     */
    public function getStdin() : ProcessOutputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stdin;
    }
    /**
     * Gets the process output stream (STDOUT).
     *
     * @return ProcessInputStream
     */
    public function getStdout() : ProcessInputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stdout;
    }
    /**
     * Gets the process error stream (STDERR).
     *
     * @return ProcessInputStream
     */
    public function getStderr() : ProcessInputStream
    {
        if (!$this->handle || $this->handle->status === ProcessStatus::STARTING) {
            throw new StatusError("Process has not been started or has not completed starting.");
        }
        return $this->handle->stderr;
    }
    /**
     *
     */
    public function __debugInfo() : array
    {
        return ['command' => $this->getCommand(), 'cwd' => $this->getWorkingDirectory(), 'env' => $this->getEnv(), 'options' => $this->getOptions(), 'pid' => $this->pid, 'status' => $this->handle ? $this->handle->status : -1];
    }
}<?php

namespace Amp\Process;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\PendingReadError;
use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Failure;
use Amp\Promise;
use Amp\Success;
final class ProcessInputStream implements InputStream
{
    /** @var Deferred */
    private $initialRead;
    /** @var bool */
    private $shouldClose = false;
    /** @var bool */
    private $referenced = true;
    /** @var ResourceInputStream */
    private $resourceStream;
    /** @var StreamException|null */
    private $error;
    /**
     *
     */
    public function __construct(Promise $resourceStreamPromise)
    {
        $resourceStreamPromise->onResolve(function ($error, $resourceStream) {
            if ($error) {
                $this->error = new StreamException("Failed to launch process", 0, $error);
                if ($this->initialRead) {
                    $initialRead = $this->initialRead;
                    $this->initialRead = null;
                    $initialRead->fail($this->error);
                }
                return;
            }
            $this->resourceStream = $resourceStream;
            if (!$this->referenced) {
                $this->resourceStream->unreference();
            }
            if ($this->shouldClose) {
                $this->resourceStream->close();
            }
            if ($this->initialRead) {
                $initialRead = $this->initialRead;
                $this->initialRead = null;
                $initialRead->resolve($this->shouldClose ? null : $this->resourceStream->read());
            }
        });
    }
    /**
     * Reads data from the stream.
     *
     * @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
     *
     * @throws PendingReadError Thrown if another read operation is still pending.
     */
    public function read() : Promise
    {
        if ($this->initialRead) {
            throw new PendingReadError();
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->resourceStream) {
            return $this->resourceStream->read();
        }
        if ($this->shouldClose) {
            return new Success();
            // Resolve reads on closed streams with null.
        }
        $this->initialRead = new Deferred();
        return $this->initialRead->promise();
    }
    /**
     *
     */
    public function reference()
    {
        $this->referenced = true;
        if ($this->resourceStream) {
            $this->resourceStream->reference();
        }
    }
    /**
     *
     */
    public function unreference()
    {
        $this->referenced = false;
        if ($this->resourceStream) {
            $this->resourceStream->unreference();
        }
    }
    /**
     *
     */
    public function close()
    {
        $this->shouldClose = true;
        if ($this->initialRead) {
            $initialRead = $this->initialRead;
            $this->initialRead = null;
            $initialRead->resolve();
        }
        if ($this->resourceStream) {
            $this->resourceStream->close();
        }
    }
}<?php

namespace Amp\Process;

class ProcessException extends \Exception
{
}{
    "name": "amphp/parallel",
    "description": "Parallel processing component for Amp.",
    "keywords": [
        "asynchronous",
        "async",
        "concurrent",
        "multi-threading",
        "multi-processing"
    ],
    "homepage": "https://github.com/amphp/parallel",
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Stephen Coakley",
            "email": "me@stephencoakley.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.6.1",
        "amphp/parser": "^1",
        "amphp/process": "^1",
        "amphp/serialization": "^1",
        "amphp/sync": "^1.0.1"
    },
    "require-dev": {
        "phpunit/phpunit": "^8 || ^7",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Parallel\\": "lib"
        },
        "files": [
            "lib/Context/functions.php",
            "lib/Sync/functions.php",
            "lib/Worker/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Parallel\\Example\\": "examples",
            "Amp\\Parallel\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\Parallel;
use Amp\Parallel\Context\Thread;
/**
 * Worker factory that includes a custom bootstrap file after initializing the worker.
 */
final class BootstrapWorkerFactory implements WorkerFactory
{
    /** @var string */
    private $bootstrapPath;
    /** @var string */
    private $className;
    /**
    * @param string $bootstrapFilePath Path to custom bootstrap file.
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate in each
    worker. Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    *
    * @throws \Error If the given class name does not exist or does not implement {@see Environment}.
    */
    public function __construct(string $bootstrapFilePath, string $envClassName = BasicEnvironment::class)
    {
        if (!\file_exists($bootstrapFilePath)) {
            throw new \Error(\sprintf("No file found at autoload path given '%s'", $bootstrapFilePath));
        }
        if (!\class_exists($envClassName)) {
            throw new \Error(\sprintf("Invalid environment class name '%s'", $envClassName));
        }
        if (!\is_subclass_of($envClassName, Environment::class)) {
            throw new \Error(\sprintf("The class '%s' does not implement '%s'", $envClassName, Environment::class));
        }
        $this->bootstrapPath = $bootstrapFilePath;
        $this->className = $envClassName;
    }
    /**
    * {@inheritdoc}
    *
    * The type of worker created depends on the extensions available. If multi-threading is enabled, a WorkerThread
    will be created. If threads are not available a WorkerProcess will be created.
    */
    public function create() : Worker
    {
        if (Parallel::isSupported()) {
            return new WorkerParallel($this->className, $this->bootstrapPath);
        }
        if (Thread::isSupported()) {
            return new WorkerThread($this->className, $this->bootstrapPath);
        }
        return new WorkerProcess($this->className, [], \getenv("AMP_PHP_BINARY") ?: (\defined("AMP_PHP_BINARY") ? \AMP_PHP_BINARY : null), $this->bootstrapPath);
    }
}<?php

namespace Amp\Parallel\Worker;

/**
 * Common interface for exceptions thrown when Task::run() throws an exception when being executed in a worker.
 */
interface TaskFailureThrowable extends \Throwable
{
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string;
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string;
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode();
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array;
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string;
}<?php

namespace Amp\Parallel\Worker;

/**
 * Interface for factories used to create new workers.
 */
interface WorkerFactory
{
    /**
     * Creates a new worker instance.
     *
     * @return Worker The newly created worker.
     */
    public function create() : Worker;
}<?php

namespace Amp\Parallel\Worker;

/**
 * Task implementation dispatching a simple callable.
 */
final class CallableTask implements Task
{
    /** @var callable */
    private $callable;
    /** @var mixed[] */
    private $args;
    /**
     * @param callable $callable Callable will be serialized.
     * @param mixed $args Arguments to pass to the function. Must be serializable.
     */
    public function __construct(callable $callable, array $args)
    {
        $this->callable = $callable;
        $this->args = $args;
    }
    /**
     *
     */
    public function run(Environment $environment)
    {
        if ($this->callable instanceof \__PHP_Incomplete_Class) {
            throw new \Error('When using a class instance as a callable, the class must be autoloadable');
        }
        if (\is_array($this->callable) && ($this->callable[0] ?? null) instanceof \__PHP_Incomplete_Class) {
            throw new \Error('When using a class instance method as a callable, the class must be autoloadable');
        }
        if (!\is_callable($this->callable)) {
            $message = 'User-defined functions must be autoloadable (that is, defined in a file autoloaded by composer)';
            if (\is_string($this->callable)) {
                $message .= \sprintf("; unable to load function '%s'", $this->callable);
            }
            throw new \Error($message);
        }
        return ($this->callable)(...$this->args);
    }
}<?php

namespace Amp\Parallel\Worker;

use function Amp\Parallel\Sync\formatFlattenedBacktrace;
final class TaskFailureException extends TaskException implements TaskFailureThrowable
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
    * @param string $className Original exception class name.
    * @param string $message Original exception message.
    * @param (int | string) $code Original exception code.
    * @param array $trace Backtrace generated by
    {@see \Amp\Parallel\Sync\flattenThrowableBacktrace()}.
    * @param (TaskFailureThrowable | null) $previous Instance representing any previous exception thrown in the Task.
    */
    public function __construct(string $className, string $message, $code, array $trace, ?TaskFailureThrowable $previous = null)
    {
        $format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the worker';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getWorkerTrace();
    }
}<?php

namespace Amp\Parallel\Worker;

use function Amp\Parallel\Sync\formatFlattenedBacktrace;
final class TaskFailureError extends TaskError implements TaskFailureThrowable
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
    * @param string $className Original exception class name.
    * @param string $message Original exception message.
    * @param (int | string) $code Original exception code.
    * @param array $trace Backtrace generated by
    {@see \Amp\Parallel\Sync\flattenThrowableBacktrace()}.
    * @param (TaskFailureThrowable | null) $previous Instance representing any previous exception thrown in the Task.
    */
    public function __construct(string $className, string $message, $code, array $trace, ?TaskFailureThrowable $previous = null)
    {
        $format = 'Uncaught %s in worker with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the worker';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Returns the original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getWorkerTrace();
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\StatusError;
use Amp\Promise;
use function Amp\asyncCall;
/**
 * Provides a pool of workers that can be used to execute multiple tasks asynchronously.
 *
 * A worker pool is a collection of worker threads that can perform multiple
 * tasks simultaneously. The load on each worker is balanced such that tasks
 * are completed as soon as possible and workers are used efficiently.
 */
final class DefaultPool implements Pool
{
    /** @var bool Indicates if the pool is currently running. */
    private $running = true;
    /** @var int The maximum number of workers the pool should spawn. */
    private $maxSize;
    /** @var WorkerFactory A worker factory to be used to create new workers. */
    private $factory;
    /** @var \SplObjectStorage A collection of all workers in the pool. */
    private $workers;
    /** @var \SplQueue A collection of idle workers. */
    private $idleWorkers;
    /** @var \SplQueue A queue of workers that have been assigned to tasks. */
    private $busyQueue;
    /** @var \Closure */
    private $push;
    /** @var Promise|null */
    private $exitStatus;
    /**
    * Creates a new worker pool.
    *
    * @param int $maxSize The maximum number of workers the pool should spawn.
    Defaults to `Pool::DEFAULT_MAX_SIZE`.
    * @param (WorkerFactory | null) $factory A worker factory to be used to create
    new workers.
    *
    * @throws \Error
    */
    public function __construct(int $maxSize = self::DEFAULT_MAX_SIZE, WorkerFactory $factory = null)
    {
        if ($maxSize < 0) {
            throw new \Error("Maximum size must be a non-negative integer");
        }
        $this->maxSize = $maxSize;
        // Use the global factory if none is given.
        $this->factory = $factory ?: factory();
        $this->workers = new \SplObjectStorage();
        $this->idleWorkers = new \SplQueue();
        $this->busyQueue = new \SplQueue();
        $workers = $this->workers;
        $idleWorkers = $this->idleWorkers;
        $busyQueue = $this->busyQueue;
        $this->push = static function (Worker $worker) use($workers, $idleWorkers, $busyQueue) : void {
            if (!$workers->contains($worker) || ($workers[$worker] -= 1) > 0) {
                return;
            }
            // Worker is completely idle, remove from busy queue and add to idle queue.
            foreach ($busyQueue as $key => $busy) {
                if ($busy === $worker) {
                    unset($busyQueue[$key]);
                    break;
                }
            }
            $idleWorkers->push($worker);
        };
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->isRunning()) {
            $this->kill();
        }
    }
    /**
     * Checks if the pool is running.
     *
     * @return bool True if the pool is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->running;
    }
    /**
     * Checks if the pool has any idle workers.
     *
     * @return bool True if the pool has at least one idle worker, otherwise false.
     */
    public function isIdle() : bool
    {
        return $this->idleWorkers->count() > 0 || $this->workers->count() === 0;
    }
    /**
     * {@inheritdoc}
     */
    public function getMaxSize() : int
    {
        return $this->maxSize;
    }
    /**
     * {@inheritdoc}
     */
    public function getWorkerCount() : int
    {
        return $this->workers->count();
    }
    /**
     * {@inheritdoc}
     */
    public function getIdleWorkerCount() : int
    {
        return $this->idleWorkers->count();
    }
    /**
     * Enqueues a {@see Task} to be executed by the worker pool.
     *
     * @param Task $task The task to enqueue.
     *
     * @return Promise<mixed> The return value of Task::run().
     *
     * @throws StatusError If the pool has been shutdown.
     * @throws TaskFailureThrowable If the task throws an exception.
     */
    public function enqueue(Task $task) : Promise
    {
        $worker = $this->pull();
        $promise = $worker->enqueue($task);
        $promise->onResolve(function () use($worker) : void {
            ($this->push)($worker);
        });
        return $promise;
    }
    /**
     * Shuts down the pool and all workers in it.
     *
     * @return Promise<int[]> Array of exit status from all workers.
     *
     * @throws StatusError If the pool has not been started.
     */
    public function shutdown() : Promise
    {
        if ($this->exitStatus) {
            return $this->exitStatus;
        }
        $this->running = false;
        $shutdowns = [];
        foreach ($this->workers as $worker) {
            if ($worker->isRunning()) {
                $shutdowns[] = $worker->shutdown();
            }
        }
        return $this->exitStatus = Promise\all($shutdowns);
    }
    /**
     * Kills all workers in the pool and halts the worker pool.
     */
    public function kill() : void
    {
        $this->running = false;
        foreach ($this->workers as $worker) {
            \assert($worker instanceof Worker);
            if ($worker->isRunning()) {
                $worker->kill();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getWorker() : Worker
    {
        return new Internal\PooledWorker($this->pull(), $this->push);
    }
    /**
     * Pulls a worker from the pool.
     *
     * @return Worker
     * @throws StatusError
     */
    private function pull() : Worker
    {
        if (!$this->isRunning()) {
            throw new StatusError("The pool was shutdown");
        }
        do {
            if ($this->idleWorkers->isEmpty()) {
                if ($this->getWorkerCount() >= $this->maxSize) {
                    // All possible workers busy, so shift from head (will be pushed back onto tail below).
                    $worker = $this->busyQueue->shift();
                } else {
                    // Max worker count has not been reached, so create another worker.
                    $worker = $this->factory->create();
                    if (!$worker->isRunning()) {
                        throw new WorkerException('Worker factory did not create a viable worker');
                    }
                    $this->workers->attach($worker, 0);
                    break;
                }
            } else {
                // Shift a worker off the idle queue.
                $worker = $this->idleWorkers->shift();
            }
            \assert($worker instanceof Worker);
            if ($worker->isRunning()) {
                break;
            }
            // Worker crashed; trigger error and remove it from the pool.
            asyncCall(function () use($worker) : \Generator {
                try {
                    $code = (yield $worker->shutdown());
                    \trigger_error('Worker in pool exited unexpectedly with code ' . $code, \E_USER_WARNING);
                } catch (\Throwable $exception) {
                    \trigger_error('Worker in pool crashed with exception on shutdown: ' . $exception->getMessage(), \E_USER_WARNING);
                }
            });
            $this->workers->detach($worker);
        } while (true);
        $this->busyQueue->push($worker);
        $this->workers[$worker] += 1;
        return $worker;
    }
}<?php

namespace Amp\Parallel\Worker;

class WorkerException extends \Exception
{
}<?php

namespace Amp\Parallel\Worker;

use Amp\Loop;
use Amp\Struct;
final class BasicEnvironment implements Environment
{
    /** @var array */
    private $data = [];
    /** @var \SplPriorityQueue */
    private $queue;
    /** @var string */
    private $timer;
    /**
     *
     */
    public function __construct()
    {
        $this->queue = $queue = new \SplPriorityQueue();
        $data =& $this->data;
        $this->timer = Loop::repeat(1000, static function (string $watcherId) use($queue, &$data) : void {
            $time = \time();
            while (!$queue->isEmpty()) {
                list($key, $expiration) = $queue->top();
                if (!isset($data[$key])) {
                    // Item removed.
                    $queue->extract();
                    continue;
                }
                $struct = $data[$key];
                if ($struct->expire === 0) {
                    // Item was set again without a TTL.
                    $queue->extract();
                    continue;
                }
                if ($struct->expire !== $expiration) {
                    // Expiration changed or TTL updated.
                    $queue->extract();
                    continue;
                }
                if ($time < $struct->expire) {
                    // Item at top has not expired, break out of loop.
                    break;
                }
                unset($data[$key]);
                $queue->extract();
            }
            if ($queue->isEmpty()) {
                Loop::disable($watcherId);
            }
        });
        Loop::disable($this->timer);
        Loop::unreference($this->timer);
    }
    /**
     * @param string $key
     *
     * @return bool
     */
    public function exists(string $key) : bool
    {
        return isset($this->data[$key]);
    }
    /**
     * @param string $key
     *
     * @return (mixed | null) Returns null if the key does not exist.
     */
    public function get(string $key)
    {
        if (!isset($this->data[$key])) {
            return null;
        }
        $struct = $this->data[$key];
        if ($struct->ttl !== null) {
            $expire = \time() + $struct->ttl;
            if ($struct->expire < $expire) {
                $struct->expire = $expire;
                $this->queue->insert([$key, $struct->expire], -$struct->expire);
            }
        }
        return $struct->data;
    }
    /**
     * @param string $key
     * @param mixed $value Using null for the value deletes the key.
     * @param int $ttl Number of seconds until data is automatically deleted. Use null for unlimited TTL.
     *
     * @throws \Error If the time-to-live is not a positive integer.
     */
    public function set(string $key, $value, int $ttl = null) : void
    {
        if ($value === null) {
            $this->delete($key);
            return;
        }
        if ($ttl !== null && $ttl <= 0) {
            throw new \Error("The time-to-live must be a positive integer or null");
        }
        $struct = new class
        {
            use Struct;
            public $data;
            public $expire = 0;
            public $ttl;
        };
        $struct->data = $value;
        if ($ttl !== null) {
            $struct->ttl = $ttl;
            $struct->expire = \time() + $ttl;
            $this->queue->insert([$key, $struct->expire], -$struct->expire);
            Loop::enable($this->timer);
        }
        $this->data[$key] = $struct;
    }
    /**
     * @param string $key
     */
    public function delete(string $key) : void
    {
        unset($this->data[$key]);
    }
    /**
     * Alias of exists().
     *
     * @param $key
     *
     * @return bool
     */
    public function offsetExists($key) : bool
    {
        return $this->exists($key);
    }
    /**
     * Alias of get().
     *
     * @param string $key
     *
     * @return mixed
     */
    #[\ReturnTypeWillChange]
    public function offsetGet($key)
    {
        return $this->get($key);
    }
    /**
     * Alias of set() with $ttl = null.
     *
     * @param string $key
     * @param mixed $value
     */
    public function offsetSet($key, $value) : void
    {
        $this->set($key, $value);
    }
    /**
     * Alias of delete().
     *
     * @param string $key
     */
    public function offsetUnset($key) : void
    {
        $this->delete($key);
    }
    /**
     * Removes all values.
     */
    public function clear() : void
    {
        $this->data = [];
        Loop::disable($this->timer);
        $this->queue = new \SplPriorityQueue();
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Parallel\Worker\Task;
/** @internal */
final class Job
{
    /** @var string */
    private $id;
    /** @var Task */
    private $task;
    /**
     *
     */
    public function __construct(Task $task)
    {
        static $id = 'a';
        $this->task = $task;
        $this->id = $id++;
    }
    /**
     *
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     *
     */
    public function getTask() : Task
    {
        // Classes that cannot be autoloaded will be unserialized as an instance of __PHP_Incomplete_Class.
        if ($this->task instanceof \__PHP_Incomplete_Class) {
            throw new \Error(\sprintf("Classes implementing %s must be autoloadable by the Composer autoloader", Task::class));
        }
        return $this->task;
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Failure;
use Amp\Parallel\Sync;
use Amp\Parallel\Worker\TaskFailureError;
use Amp\Parallel\Worker\TaskFailureException;
use Amp\Parallel\Worker\TaskFailureThrowable;
use Amp\Promise;
/** @internal */
final class TaskFailure extends TaskResult
{
    const PARENT_EXCEPTION = 0;
    const PARENT_ERROR = 1;
    /** @var string */
    private $type;
    /** @var int */
    private $parent;
    /** @var string */
    private $message;
    /** @var int|string */
    private $code;
    /** @var string[] */
    private $trace;
    /** @var self|null */
    private $previous;
    /**
     *
     */
    public function __construct(string $id, \Throwable $exception)
    {
        parent::__construct($id);
        $this->type = \get_class($exception);
        $this->parent = $exception instanceof \Error ? self::PARENT_ERROR : self::PARENT_EXCEPTION;
        $this->message = $exception->getMessage();
        $this->code = $exception->getCode();
        $this->trace = Sync\flattenThrowableBacktrace($exception);
        if ($previous = $exception->getPrevious()) {
            $this->previous = new self($id, $previous);
        }
    }
    /**
     *
     */
    public function promise() : Promise
    {
        return new Failure($this->createException());
    }
    /**
     *
     */
    private function createException() : TaskFailureThrowable
    {
        $previous = $this->previous ? $this->previous->createException() : null;
        if ($this->parent === self::PARENT_ERROR) {
            return new TaskFailureError($this->type, $this->message, $this->code, $this->trace, $previous);
        }
        return new TaskFailureException($this->type, $this->message, $this->code, $this->trace, $previous);
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Parallel\Worker\Task;
use Amp\Parallel\Worker\Worker;
use Amp\Promise;
/** @internal */
final class PooledWorker implements Worker
{
    /** @var callable */
    private $push;
    /** @var Worker */
    private $worker;
    /**
     * @param Worker $worker
     * @param callable $push Callable to push the worker back into the queue.
     */
    public function __construct(Worker $worker, callable $push)
    {
        $this->worker = $worker;
        $this->push = $push;
    }
    /**
     * Automatically pushes the worker back into the queue.
     */
    public function __destruct()
    {
        ($this->push)($this->worker);
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        return $this->worker->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function isIdle() : bool
    {
        return $this->worker->isIdle();
    }
    /**
     * {@inheritdoc}
     */
    public function enqueue(Task $task) : Promise
    {
        return $this->worker->enqueue($task);
    }
    /**
     * {@inheritdoc}
     */
    public function shutdown() : Promise
    {
        return $this->worker->shutdown();
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        $this->worker->kill();
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\ByteStream;
use Amp\Parallel\Context\Context;
use Amp\Parallel\Context\Process;
use Amp\Promise;
use function Amp\call;
class WorkerProcess implements Context
{
    /** @var Process */
    private $process;
    /**
     *
     */
    public function __construct($script, array $env = [], string $binary = null)
    {
        $this->process = new Process($script, null, $env, $binary);
    }
    /**
     *
     */
    public function receive() : Promise
    {
        return $this->process->receive();
    }
    /**
     *
     */
    public function send($data) : Promise
    {
        return $this->process->send($data);
    }
    /**
     *
     */
    public function isRunning() : bool
    {
        return $this->process->isRunning();
    }
    /**
     *
     */
    public function start() : Promise
    {
        return call(function () {
            $result = (yield $this->process->start());
            $stdout = $this->process->getStdout();
            $stdout->unreference();
            $stderr = $this->process->getStderr();
            $stderr->unreference();
            ByteStream\pipe($stdout, ByteStream\getStdout());
            ByteStream\pipe($stderr, ByteStream\getStderr());
            return $result;
        });
    }
    /**
     *
     */
    public function kill() : void
    {
        if ($this->process->isRunning()) {
            $this->process->kill();
        }
    }
    /**
     *
     */
    public function join() : Promise
    {
        return $this->process->join();
    }
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Parallel\Sync;
use Amp\Parallel\Worker;
use Amp\Promise;
return function (Sync\Channel $channel) use($argc, $argv) : Promise {
    if (!\defined("AMP_WORKER")) {
        \define("AMP_WORKER", \AMP_CONTEXT);
    }
    if (isset($argv[2])) {
        if (!\is_file($argv[2])) {
            throw new \Error(\sprintf("No file found at bootstrap file path given '%s'", $argv[2]));
        }
        // Include file within closure to protect scope.
        (function () use($argc, $argv) : void {
            require $argv[2];
        })();
    }
    if (!isset($argv[1])) {
        throw new \Error("No environment class name provided");
    }
    $className = $argv[1];
    if (!\class_exists($className)) {
        throw new \Error(\sprintf("Invalid environment class name '%s'", $className));
    }
    if (!\is_subclass_of($className, Worker\Environment::class)) {
        throw new \Error(\sprintf("The class '%s' does not implement '%s'", $className, Worker\Environment::class));
    }
    $environment = new $className();
    $runner = new Worker\TaskRunner($channel, $environment);
    return $runner->run();
};<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Promise;
/** @internal */
abstract class TaskResult
{
    /** @var string Task identifier. */
    private $id;
    /**
     * @param string $id Task identifier.
     */
    public function __construct(string $id)
    {
        $this->id = $id;
    }
    /**
     * @return string Task identifier.
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     * @return Promise<mixed> Resolved with the task result or failure reason.
     */
    public abstract function promise() : Promise;
}<?php

namespace Amp\Parallel\Worker\Internal;

use Amp\Failure;
use Amp\Parallel\Worker\Task;
use Amp\Promise;
use Amp\Success;
/** @internal */
final class TaskSuccess extends TaskResult
{
    /** @var mixed Result of task. */
    private $result;
    /**
     *
     */
    public function __construct(string $id, $result)
    {
        parent::__construct($id);
        $this->result = $result;
    }
    /**
     *
     */
    public function promise() : Promise
    {
        if ($this->result instanceof \__PHP_Incomplete_Class) {
            return new Failure(new \Error(\sprintf("Class instances returned from %s::run() must be autoloadable by the Composer autoloader", Task::class)));
        }
        return new Success($this->result);
    }
}<?php

namespace Amp\Parallel\Worker;

/**
 * An interface for worker pools.
 */
interface Pool extends Worker
{
    /** @var int The default maximum pool size. */
    const DEFAULT_MAX_SIZE = 32;
    /**
    * Gets a worker from the pool. The worker is marked as busy and will only be reused if the pool runs out of
    idle workers. The worker will be automatically marked as idle once no references to the returned worker remain.
    *
    * @return \Amp\Parallel\Worker\Worker
    *
    * @throws \Amp\Parallel\Context\StatusError If the queue is not running.
    */
    public function getWorker() : Worker;
    /**
     * Gets the number of workers currently running in the pool.
     *
     * @return int The number of workers.
     */
    public function getWorkerCount() : int;
    /**
     * Gets the number of workers that are currently idle.
     *
     * @return int The number of idle workers.
     */
    public function getIdleWorkerCount() : int;
    /**
     * Gets the maximum number of workers the pool may spawn to handle concurrent tasks.
     *
     * @return int The maximum number of workers.
     */
    public function getMaxSize() : int;
}<?php

namespace Amp\Parallel\Worker;

/**
 * @deprecated TaskFailureException will be thrown from failed Tasks instead of this class.
 */
class TaskException extends \Exception
{
    /** @var string Class name of exception thrown from task. */
    private $name;
    /** @var string Stack trace of the exception thrown from task. */
    private $trace;
    /**
     * @param string $name The exception class name.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalClassName() instead.
     *
     * Returns the class name of the exception thrown from the task.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the exception was thrown in the task.
     *
     * @return string
     */
    public function getWorkerTrace() : string
    {
        return $this->trace;
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\Thread;
use Amp\Parallel\Sync\Channel;
use Amp\Promise;
/**
 * A worker thread that executes task objects.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class WorkerThread extends TaskWorker
{
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param (string | null) $bootstrapPath Path to custom autoloader.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, string $bootstrapPath = null)
    {
        parent::__construct(new Thread(static function (Channel $channel, string $className, string $bootstrapPath = null) : Promise {
            if ($bootstrapPath !== null) {
                if (!\is_file($bootstrapPath)) {
                    throw new \Error(\sprintf("No file found at bootstrap file path given '%s'", $bootstrapPath));
                }
                // Include file within unbound closure to protect scope.
                (static function () use($bootstrapPath) : void {
                    require $bootstrapPath;
                })->bindTo(null, null)();
            }
            if (!\class_exists($className)) {
                throw new \Error(\sprintf("Invalid environment class name '%s'", $className));
            }
            if (!\is_subclass_of($className, Environment::class)) {
                throw new \Error(\sprintf("The class '%s' does not implement '%s'", $className, Environment::class));
            }
            $environment = new $className();
            if (!\defined("AMP_WORKER")) {
                \define("AMP_WORKER", \AMP_CONTEXT);
            }
            $runner = new TaskRunner($channel, $environment);
            return $runner->run();
        }, $envClassName, $bootstrapPath));
    }
}<?php

namespace Amp\Parallel\Worker;

interface Environment extends \ArrayAccess
{
    /**
     * @param string $key
     *
     * @return bool
     */
    public function exists(string $key) : bool;
    /**
     * @param string $key
     *
     * @return (mixed | null) Returns null if the key does not exist.
     */
    public function get(string $key);
    /**
     * @param string $key
     * @param mixed $value Using null for the value deletes the key.
     * @param int $ttl Number of seconds until data is automatically deleted. Use null for unlimited TTL.
     */
    public function set(string $key, $value, int $ttl = null);
    /**
     * @param string $key
     */
    public function delete(string $key);
    /**
     * Removes all values.
     */
    public function clear();
}<?php

namespace Amp\Parallel\Worker;

use Amp\Coroutine;
use Amp\Parallel\Sync\Channel;
use Amp\Parallel\Sync\SerializationException;
use Amp\Promise;
use function Amp\call;
final class TaskRunner
{
    /** @var Channel */
    private $channel;
    /** @var Environment */
    private $environment;
    /**
     *
     */
    public function __construct(Channel $channel, Environment $environment)
    {
        $this->channel = $channel;
        $this->environment = $environment;
    }
    /**
     * Runs the task runner, receiving tasks from the parent and sending the result of those tasks.
     *
     * @return \Amp\Promise
     */
    public function run() : Promise
    {
        return new Coroutine($this->execute());
    }
    /**
     * @coroutine
     *
     * @return \Generator
     */
    private function execute() : \Generator
    {
        $job = (yield $this->channel->receive());
        while ($job instanceof Internal\Job) {
            try {
                $result = (yield call([$job->getTask(), "run"], $this->environment));
                $result = new Internal\TaskSuccess($job->getId(), $result);
            } catch (\Throwable $exception) {
                $result = new Internal\TaskFailure($job->getId(), $exception);
            }
            $job = null;
            // Free memory from last job.
            try {
                (yield $this->channel->send($result));
            } catch (SerializationException $exception) {
                // Could not serialize task result.
                (yield $this->channel->send(new Internal\TaskFailure($result->getId(), $exception)));
            }
            $result = null;
            // Free memory from last result.
            $job = (yield $this->channel->receive());
        }
        return $job;
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Failure;
use Amp\Parallel\Context\Context;
use Amp\Parallel\Context\StatusError;
use Amp\Parallel\Sync\ChannelException;
use Amp\Promise;
use Amp\Success;
use Amp\TimeoutException;
use function Amp\call;
/**
 * Base class for most common types of task workers.
 */
abstract class TaskWorker implements Worker
{
    const SHUTDOWN_TIMEOUT = 1000;
    const ERROR_TIMEOUT = 250;
    /** @var Context */
    private $context;
    /** @var bool */
    private $started = false;
    /** @var Promise|null */
    private $pending;
    /** @var Promise|null */
    private $exitStatus;
    /**
     * @param Context $context A context running an instance of TaskRunner.
     */
    public function __construct(Context $context)
    {
        if ($context->isRunning()) {
            throw new \Error("The context was already running");
        }
        $this->context = $context;
        $context =& $this->context;
        $pending =& $this->pending;
        \register_shutdown_function(static function () use(&$context, &$pending) : void {
            if ($context === null || !$context->isRunning()) {
                return;
            }
            try {
                Promise\wait(Promise\timeout(call(function () use($context, $pending) : \Generator {
                    if ($pending) {
                        (yield $pending);
                    }
                    (yield $context->send(0));
                    return (yield $context->join());
                }), self::SHUTDOWN_TIMEOUT));
            } catch (\Throwable $exception) {
                if ($context !== null) {
                    $context->kill();
                }
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        // Report as running unless shutdown or crashed.
        return !$this->started || $this->exitStatus === null && $this->context !== null && $this->context->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function isIdle() : bool
    {
        return $this->pending === null;
    }
    /**
     * {@inheritdoc}
     */
    public function enqueue(Task $task) : Promise
    {
        if ($this->exitStatus) {
            throw new StatusError("The worker has been shut down");
        }
        $promise = $this->pending = call(function () use($task) : \Generator {
            if ($this->pending) {
                try {
                    (yield $this->pending);
                } catch (\Throwable $exception) {
                    // Ignore error from prior job.
                }
            }
            if ($this->exitStatus !== null || $this->context === null) {
                throw new WorkerException("The worker was shutdown");
            }
            if (!$this->context->isRunning()) {
                if ($this->started) {
                    throw new WorkerException("The worker crashed");
                }
                $this->started = true;
                (yield $this->context->start());
            }
            $job = new Internal\Job($task);
            try {
                (yield $this->context->send($job));
                $result = (yield $this->context->receive());
            } catch (ChannelException $exception) {
                try {
                    (yield Promise\timeout($this->context->join(), self::ERROR_TIMEOUT));
                } catch (TimeoutException $timeout) {
                    $this->kill();
                    throw new WorkerException("The worker failed unexpectedly", 0, $exception);
                }
                throw new WorkerException("The worker exited unexpectedly", 0, $exception);
            }
            if (!$result instanceof Internal\TaskResult) {
                $this->kill();
                throw new WorkerException("Context did not return a task result");
            }
            if ($result->getId() !== $job->getId()) {
                $this->kill();
                throw new WorkerException("Task results returned out of order");
            }
            return $result->promise();
        });
        $promise->onResolve(function () use($promise) : void {
            if ($this->pending === $promise) {
                $this->pending = null;
            }
        });
        return $promise;
    }
    /**
     * {@inheritdoc}
     */
    public function shutdown() : Promise
    {
        if ($this->exitStatus !== null) {
            return $this->exitStatus;
        }
        if ($this->context === null || !$this->context->isRunning()) {
            return $this->exitStatus = new Success(-1);
            // Context crashed?
        }
        return $this->exitStatus = call(function () : \Generator {
            if ($this->pending) {
                // If a task is currently running, wait for it to finish.
                (yield Promise\any([$this->pending]));
            }
            (yield $this->context->send(0));
            try {
                return (yield Promise\timeout($this->context->join(), self::SHUTDOWN_TIMEOUT));
            } catch (\Throwable $exception) {
                $this->context->kill();
                throw new WorkerException("Failed to gracefully shutdown worker", 0, $exception);
            } finally {
                // Null properties to free memory because the shutdown function has references to these.
                $this->context = null;
                $this->pending = null;
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        if ($this->exitStatus !== null || $this->context === null) {
            return;
        }
        if ($this->context->isRunning()) {
            $this->context->kill();
            $this->exitStatus = new Failure(new WorkerException("The worker was killed"));
            return;
        }
        $this->exitStatus = new Success(0);
        // Null properties to free memory because the shutdown function has references to these.
        $this->context = null;
        $this->pending = null;
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Loop;
use Amp\Promise;
const LOOP_POOL_IDENTIFIER = Pool::class;
const LOOP_FACTORY_IDENTIFIER = WorkerFactory::class;
/**
 * Gets or sets the global worker pool.
 *
 * @param (Pool | null) $pool A worker pool instance.
 *
 * @return Pool The global worker pool instance.
 */
function pool(Pool $pool = null) : Pool
{
    if ($pool === null) {
        $pool = Loop::getState(LOOP_POOL_IDENTIFIER);
        if ($pool) {
            return $pool;
        }
        $pool = new DefaultPool();
    }
    Loop::setState(LOOP_POOL_IDENTIFIER, $pool);
    return $pool;
}
/**
 * Enqueues a task to be executed by the global worker pool.
 *
 * @param Task $task The task to enqueue.
 *
 * @return Promise<mixed>
 */
function enqueue(Task $task) : Promise
{
    return pool()->enqueue($task);
}
/**
 * Enqueues a callable to be executed by the global worker pool.
 *
 * @param callable $callable Callable needs to be serializable.
 * @param mixed ...$args Arguments have to be serializable.
 *
 * @return Promise<mixed>
 */
function enqueueCallable(callable $callable, ...$args)
{
    return enqueue(new CallableTask($callable, $args));
}
/**
 * Gets a worker from the global worker pool.
 *
 * @return \Amp\Parallel\Worker\Worker
 */
function worker() : Worker
{
    return pool()->getWorker();
}
/**
 * Creates a worker using the global worker factory.
 *
 * @return \Amp\Parallel\Worker\Worker
 */
function create() : Worker
{
    return factory()->create();
}
/**
 * Gets or sets the global worker factory.
 *
 * @param (WorkerFactory | null) $factory
 *
 * @return WorkerFactory
 */
function factory(WorkerFactory $factory = null) : WorkerFactory
{
    if ($factory === null) {
        $factory = Loop::getState(LOOP_FACTORY_IDENTIFIER);
        if ($factory) {
            return $factory;
        }
        $factory = new DefaultWorkerFactory();
    }
    Loop::setState(LOOP_FACTORY_IDENTIFIER, $factory);
    return $factory;
}<?php

namespace Amp\Parallel\Worker;

use Amp\Promise;
/**
 * An interface for a parallel worker thread that runs a queue of tasks.
 */
interface Worker
{
    /**
     * Checks if the worker is running.
     *
     * @return bool True if the worker is running, otherwise false.
     */
    public function isRunning() : bool;
    /**
     * Checks if the worker is currently idle.
     *
     * @return bool
     */
    public function isIdle() : bool;
    /**
     * Enqueues a {@see Task} to be executed by the worker.
     *
     * @param Task $task The task to enqueue.
     *
     * @return Promise<mixed> Resolves with the return value of {@see Task::run()}.
     *
     * @throws TaskFailureThrowable Promise fails if {@see Task::run()} throws an exception.
     */
    public function enqueue(Task $task) : Promise;
    /**
     * @return Promise<int> Resolves with the worker exit code.
     */
    public function shutdown() : Promise;
    /**
     * Immediately kills the context.
     */
    public function kill();
}<?php

namespace Amp\Parallel\Worker;

/**
 * A worker process that executes task objects.
 */
final class WorkerProcess extends TaskWorker
{
    const SCRIPT_PATH = __DIR__ . "/Internal/worker-process.php";
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param mixed[] $env Array of environment variables to pass to the worker. Empty array inherits from the current
    PHP process. See the $env parameter of \Amp\Process\Process::__construct().
    * @param (string | null) $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    * @param (string | null) $bootstrapPath Path to custom bootstrap file.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, array $env = [], string $binary = null, string $bootstrapPath = null)
    {
        $script = [self::SCRIPT_PATH, $envClassName];
        if ($bootstrapPath !== null) {
            $script[] = $bootstrapPath;
        }
        parent::__construct(new Internal\WorkerProcess($script, $env, $binary));
    }
}<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\Parallel;
/**
 * A worker parallel extension thread that executes task objects.
 */
final class WorkerParallel extends TaskWorker
{
    const SCRIPT_PATH = __DIR__ . "/Internal/worker-process.php";
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate.
    Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    * @param string|null Path to custom bootstrap file.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct(string $envClassName = BasicEnvironment::class, string $bootstrapPath = null)
    {
        $script = [self::SCRIPT_PATH, $envClassName];
        if ($bootstrapPath !== null) {
            $script[] = $bootstrapPath;
        }
        parent::__construct(new Parallel($script));
    }
}<?php

namespace Amp\Parallel\Worker;

/**
 * A runnable unit of execution.
 */
interface Task
{
    /**
     * Runs the task inside the caller's context.
     *
     * Does not have to be a coroutine, can also be a regular function returning a value.
     *
     * @param \Amp\Parallel\Worker\Environment
     *
     * @return (mixed | \Amp\Promise | \Generator)
     */
    public function run(Environment $environment);
}<?php

namespace Amp\Parallel\Worker;

use Amp\Parallel\Context\Parallel;
use Amp\Parallel\Context\Thread;
/**
 * The built-in worker factory type.
 */
final class DefaultWorkerFactory implements WorkerFactory
{
    /** @var string */
    private $className;
    /**
    * @param string $envClassName Name of class implementing \Amp\Parallel\Worker\Environment to instigate in each
    worker. Defaults to \Amp\Parallel\Worker\BasicEnvironment.
    *
    * @throws \Error If the given class name does not exist or does not implement {@see Environment}.
    */
    public function __construct(string $envClassName = BasicEnvironment::class)
    {
        if (!\class_exists($envClassName)) {
            throw new \Error(\sprintf("Invalid environment class name '%s'", $envClassName));
        }
        if (!\is_subclass_of($envClassName, Environment::class)) {
            throw new \Error(\sprintf("The class '%s' does not implement '%s'", $envClassName, Environment::class));
        }
        $this->className = $envClassName;
    }
    /**
    * {@inheritdoc}
    *
    * The type of worker created depends on the extensions available. If multi-threading is enabled, a WorkerThread
    will be created. If threads are not available a WorkerProcess will be created.
    */
    public function create() : Worker
    {
        if (Parallel::isSupported()) {
            return new WorkerParallel($this->className);
        }
        if (Thread::isSupported()) {
            return new WorkerThread($this->className);
        }
        return new WorkerProcess($this->className, [], \getenv("AMP_PHP_BINARY") ?: (\defined("AMP_PHP_BINARY") ? \AMP_PHP_BINARY : null));
    }
}<?php

namespace Amp\Parallel\Worker;

/**
 * @deprecated TaskFailureError will be thrown from failed Tasks instead of this class.
 */
class TaskError extends \Error
{
    /** @var string Class name of error thrown from task. */
    private $name;
    /** @var string Stack trace of the error thrown from task. */
    private $trace;
    /**
     * @param string $name The exception class name.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalClassName() instead.
     *
     * Returns the class name of the error thrown from the task.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use TaskFailureThrowable::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the error was thrown in the task.
     *
     * @return string
     */
    public function getWorkerTrace() : string
    {
        return $this->trace;
    }
}<?php

namespace Amp\Parallel\Sync;

final class ContextPanicError extends PanicError
{
    /** @var string */
    private $originalMessage;
    /** @var int|string */
    private $originalCode;
    /** @var string[] */
    private $originalTrace;
    /**
     * @param string $className Original exception class name.
     * @param string $message Original exception message.
     * @param (int | string) $code Original exception code.
     * @param array $trace Backtrace generated by {@see formatFlattenedBacktrace()}.
     * @param (self | null) $previous Instance representing any previous exception thrown in the child process or thread.
     */
    public function __construct(string $className, string $message, $code, array $trace, ?self $previous = null)
    {
        $format = 'Uncaught %s in child process or thread with message "%s" and code "%s"; use %s::getOriginalTrace() for the stack trace in the child process or thread';
        parent::__construct($className, \sprintf($format, $className, $message, $code, self::class), formatFlattenedBacktrace($trace), $previous);
        $this->originalMessage = $message;
        $this->originalCode = $code;
        $this->originalTrace = $trace;
    }
    /**
     * @return string Original exception class name.
     */
    public function getOriginalClassName() : string
    {
        return $this->getName();
    }
    /**
     * @return string Original exception message.
     */
    public function getOriginalMessage() : string
    {
        return $this->originalMessage;
    }
    /**
     * @return (int | string) Original exception code.
     */
    public function getOriginalCode()
    {
        return $this->originalCode;
    }
    /**
     * Original exception stack trace.
     *
     * @return array Same as {@see Throwable::getTrace()}, except all function arguments are formatted as strings.
     */
    public function getOriginalTrace() : array
    {
        return $this->originalTrace;
    }
    /**
     * Original backtrace flattened to a human-readable string.
     *
     * @return string
     */
    public function getOriginalTraceAsString() : string
    {
        return $this->getPanicTrace();
    }
}<?php

namespace Amp\Parallel\Sync;

class SharedMemoryException extends ParcelException
{
}<?php

namespace Amp\Parallel\Sync;

final class ExitFailure implements ExitResult
{
    /** @var string */
    private $type;
    /** @var string */
    private $message;
    /** @var int|string */
    private $code;
    /** @var string[] */
    private $trace;
    /** @var self|null */
    private $previous;
    /**
     *
     */
    public function __construct(\Throwable $exception)
    {
        $this->type = \get_class($exception);
        $this->message = $exception->getMessage();
        $this->code = $exception->getCode();
        $this->trace = flattenThrowableBacktrace($exception);
        if ($previous = $exception->getPrevious()) {
            $this->previous = new self($previous);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getResult()
    {
        throw $this->createException();
    }
    /**
     *
     */
    private function createException() : ContextPanicError
    {
        $previous = $this->previous ? $this->previous->createException() : null;
        return new ContextPanicError($this->type, $this->message, $this->code, $this->trace, $previous);
    }
}<?php

namespace Amp\Parallel\Sync;

final class ExitSuccess implements ExitResult
{
    /** @var mixed */
    private $result;
    /**
     *
     */
    public function __construct($result)
    {
        $this->result = $result;
    }
    /**
     * {@inheritdoc}
     */
    public function getResult()
    {
        return $this->result;
    }
}<?php

namespace Amp\Parallel\Sync;

use Amp\Promise;
use Amp\Serialization\NativeSerializer;
use Amp\Serialization\Serializer;
use Amp\Sync\Lock;
use Amp\Sync\PosixSemaphore;
use Amp\Sync\SyncException;
use function Amp\call;
/**
 * A container object for sharing a value across contexts.
 *
 * A shared object is a container that stores an object inside shared memory.
 * The object can be accessed and mutated by any thread or process. The shared
 * object handle itself is serializable and can be sent to any thread or process
 * to give access to the value that is shared in the container.
 *
 * Because each shared object uses its own shared memory segment, it is much
 * more efficient to store a larger object containing many values inside a
 * single shared container than to use many small shared containers.
 *
 * Note that accessing a shared object is not atomic. Access to a shared object
 * should be protected with a mutex to preserve data integrity.
 *
 * When used with forking, the object must be created prior to forking for both
 * processes to access the synchronized object.
 *
 * @see http://php.net/manual/en/book.shmop.php The shared memory extension.
 * @see http://man7.org/linux/man-pages/man2/shmctl.2.html How shared memory works on Linux.
 * @see https://msdn.microsoft.com/en-us/library/ms810613.aspx How shared memory works on Windows.
 */
final class SharedMemoryParcel implements Parcel
{
    /** @var int The byte offset to the start of the object data in memory. */
    const MEM_DATA_OFFSET = 7;
    // A list of valid states the object can be in.
    const STATE_UNALLOCATED = 0;
    const STATE_ALLOCATED = 1;
    const STATE_MOVED = 2;
    const STATE_FREED = 3;
    /** @var string */
    private $id;
    /** @var int The shared memory segment key. */
    private $key;
    /** @var PosixSemaphore A semaphore for synchronizing on the parcel. */
    private $semaphore;
    /** @var resource|null An open handle to the shared memory segment. */
    private $handle;
    /** @var int */
    private $initializer = 0;
    /** @var Serializer */
    private $serializer;
    /**
    * @param string $id
    * @param mixed $value
    * @param int $size The initial size in bytes of the shared memory segment. It will automatically be expanded as
    necessary.
    * @param int $permissions Permissions to access the semaphore. Use file permission format specified as 0xxx.
    * @param (Serializer | null) $serializer
    *
    * @return self
    *
    * @throws SharedMemoryException
    * @throws SyncException
    * @throws \Error If the size or permissions are invalid.
    */
    public static function create(string $id, $value, int $size = 8192, int $permissions = 0600, ?Serializer $serializer = null) : self
    {
        $parcel = new self($id, $serializer);
        $parcel->init($value, $size, $permissions);
        return $parcel;
    }
    /**
     * @param string $id
     * @param (Serializer | null) $serializer
     *
     * @return self
     *
     * @throws SharedMemoryException
     */
    public static function use(string $id, ?Serializer $serializer = null) : self
    {
        $parcel = new self($id, $serializer);
        $parcel->open();
        return $parcel;
    }
    /**
     * @param string $id
     * @param (Serializer | null) $serializer
     */
    private function __construct(string $id, ?Serializer $serializer = null)
    {
        if (!\extension_loaded("shmop")) {
            throw new \Error(__CLASS__ . " requires the shmop extension");
        }
        $this->id = $id;
        $this->key = self::makeKey($this->id);
        $this->serializer = $serializer ?? new NativeSerializer();
    }
    /**
     * @param mixed $value
     * @param int $size
     * @param int $permissions
     *
     * @throws SharedMemoryException
     * @throws SyncException
     * @throws \Error If the size or permissions are invalid.
     */
    private function init($value, int $size = 8192, int $permissions = 0600) : void
    {
        if ($size <= 0) {
            throw new \Error('The memory size must be greater than 0');
        }
        if ($permissions <= 0 || $permissions > 0777) {
            throw new \Error('Invalid permissions');
        }
        $this->semaphore = PosixSemaphore::create($this->id, 1);
        $this->initializer = \getmypid();
        $this->memOpen($this->key, 'n', $permissions, $size + self::MEM_DATA_OFFSET);
        $this->setHeader(self::STATE_ALLOCATED, 0, $permissions);
        $this->wrap($value);
    }
    /**
     *
     */
    private function open() : void
    {
        $this->semaphore = PosixSemaphore::use($this->id);
        $this->memOpen($this->key, 'w', 0, 0);
    }
    /**
    * Checks if the object has been freed.
    *
    * Note that this does not check if the object has been destroyed; it only
    checks if this handle has freed its reference to the object.
    *
    * @return bool True if the object is freed, otherwise false.
    */
    private function isFreed() : bool
    {
        // If we are no longer connected to the memory segment, check if it has
        // been invalidated.
        if ($this->handle !== null) {
            $this->handleMovedMemory();
            $header = $this->getHeader();
            return $header['state'] === static::STATE_FREED;
        }
        return true;
    }
    /**
     * {@inheritdoc}
     */
    public function unwrap() : Promise
    {
        return call(function () {
            $lock = (yield $this->semaphore->acquire());
            \assert($lock instanceof Lock);
            try {
                return $this->getValue();
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * @return mixed
     *
     * @throws SharedMemoryException
     * @throws SerializationException
     */
    private function getValue()
    {
        if ($this->isFreed()) {
            throw new SharedMemoryException('The object has already been freed');
        }
        $header = $this->getHeader();
        // Make sure the header is in a valid state and format.
        if ($header['state'] !== self::STATE_ALLOCATED || $header['size'] <= 0) {
            throw new SharedMemoryException('Shared object memory is corrupt');
        }
        // Read the actual value data from memory and unserialize it.
        $data = $this->memGet(self::MEM_DATA_OFFSET, $header['size']);
        return $this->serializer->unserialize($data);
    }
    /**
    * If the value requires more memory to store than currently allocated, a
    new shared memory segment will be allocated with a larger size to store
    the value in. The previous memory segment will be cleaned up and marked
    for deletion. Other processes and threads will be notified of the new
    memory segment on the next read attempt. Once all running processes and
    threads disconnect from the old segment, it will be freed by the OS.
    */
    private function wrap($value) : void
    {
        if ($this->isFreed()) {
            throw new SharedMemoryException('The object has already been freed');
        }
        $serialized = $this->serializer->serialize($value);
        $size = \strlen($serialized);
        $header = $this->getHeader();
        /* If we run out of space, we need to allocate a new shared memory
              segment that is larger than the current one. To coordinate with other
              processes, we will leave a message in the old segment that the segment
              has moved and along with the new key. The old segment will be discarded
              automatically after all other processes notice the change and close
              the old handle.
           */
        if (\shmop_size($this->handle) < $size + self::MEM_DATA_OFFSET) {
            $this->key = $this->key < 0xffffffff ? $this->key + 1 : \random_int(0x10, 0xfffffffe);
            $this->setHeader(self::STATE_MOVED, $this->key, 0);
            $this->memDelete();
            \shmop_close($this->handle);
            $this->memOpen($this->key, 'n', $header['permissions'], $size * 2);
        }
        // Rewrite the header and the serialized value to memory.
        $this->setHeader(self::STATE_ALLOCATED, $size, $header['permissions']);
        $this->memSet(self::MEM_DATA_OFFSET, $serialized);
    }
    /**
     * {@inheritdoc}
     */
    public function synchronized(callable $callback) : Promise
    {
        return call(function () use($callback) : \Generator {
            $lock = (yield $this->semaphore->acquire());
            \assert($lock instanceof Lock);
            try {
                $result = (yield call($callback, $this->getValue()));
                if ($result !== null) {
                    $this->wrap($result);
                }
            } finally {
                $lock->release();
            }
            return $result;
        });
    }
    /**
    * Frees the shared object from memory.
    *
    * The memory containing the shared value will be invalidated. When all
    process disconnect from the object, the shared memory block will be
    destroyed by the OS.
    */
    public function __destruct()
    {
        if ($this->initializer === 0 || $this->initializer !== \getmypid()) {
            return;
        }
        if ($this->isFreed()) {
            return;
        }
        // Invalidate the memory block by setting its state to FREED.
        $this->setHeader(static::STATE_FREED, 0, 0);
        // Request the block to be deleted, then close our local handle.
        $this->memDelete();
        \shmop_close($this->handle);
        $this->handle = null;
        $this->semaphore = null;
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * Prevent serialization.
     */
    public function __sleep()
    {
        throw new \Error('A shared memory parcel cannot be serialized!');
    }
    /**
    * Updates the current memory segment handle, handling any moves made on the
    data.
    *
    * @throws SharedMemoryException
    */
    private function handleMovedMemory() : void
    {
        // Read from the memory block and handle moved blocks until we find the
        // correct block.
        while (true) {
            $header = $this->getHeader();
            // If the state is STATE_MOVED, the memory is stale and has been moved
            // to a new location. Move handle and try to read again.
            if ($header['state'] !== self::STATE_MOVED) {
                break;
            }
            \shmop_close($this->handle);
            $this->key = $header['size'];
            $this->memOpen($this->key, 'w', 0, 0);
        }
    }
    /**
     * Reads and returns the data header at the current memory segment.
     *
     * @return array An associative array of header data.
     *
     * @throws SharedMemoryException
     */
    private function getHeader() : array
    {
        $data = $this->memGet(0, self::MEM_DATA_OFFSET);
        return \unpack('Cstate/Lsize/Spermissions', $data);
    }
    /**
     * Sets the header data for the current memory segment.
     *
     * @param int $state An object state.
     * @param int $size The size of the stored data, or other value.
     * @param int $permissions The permissions mask on the memory segment.
     *
     * @throws SharedMemoryException
     */
    private function setHeader(int $state, int $size, int $permissions) : void
    {
        $header = \pack('CLS', $state, $size, $permissions);
        $this->memSet(0, $header);
    }
    /**
     * Opens a shared memory handle.
     *
     * @param int $key The shared memory key.
     * @param string $mode The mode to open the shared memory in.
     * @param int $permissions Process permissions on the shared memory.
     * @param int $size The size to crate the shared memory in bytes.
     *
     * @throws SharedMemoryException
     */
    private function memOpen(int $key, string $mode, int $permissions, int $size) : void
    {
        $handle = @\shmop_open($key, $mode, $permissions, $size);
        if ($handle === false) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to create shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
        $this->handle = $handle;
    }
    /**
     * Reads binary data from shared memory.
     *
     * @param int $offset The offset to read from.
     * @param int $size The number of bytes to read.
     *
     * @return string The binary data at the given offset.
     *
     * @throws SharedMemoryException
     */
    private function memGet(int $offset, int $size) : string
    {
        $data = \shmop_read($this->handle, $offset, $size);
        if ($data === false) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to read from shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
        return $data;
    }
    /**
     * Writes binary data to shared memory.
     *
     * @param int $offset The offset to write to.
     * @param string $data The binary data to write.
     *
     * @throws SharedMemoryException
     */
    private function memSet(int $offset, string $data) : void
    {
        if (!\shmop_write($this->handle, $data, $offset)) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to write to shared memory block: ' . ($error['message'] ?? 'unknown error'));
        }
    }
    /**
     * Requests the shared memory segment to be deleted.
     *
     * @throws SharedMemoryException
     */
    private function memDelete() : void
    {
        if (!\shmop_delete($this->handle)) {
            $error = \error_get_last();
            throw new SharedMemoryException('Failed to discard shared memory block' . ($error['message'] ?? 'unknown error'));
        }
    }
    /**
     *
     */
    private static function makeKey(string $id) : int
    {
        return \abs(\unpack("l", \md5($id, true))[1]);
    }
}<?php

namespace Amp\Parallel\Sync;

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Promise;
use Amp\Serialization\Serializer;
final class ChannelledSocket implements Channel
{
    /** @var ChannelledStream */
    private $channel;
    /** @var ResourceInputStream */
    private $read;
    /** @var ResourceOutputStream */
    private $write;
    /**
     * @param resource $read Readable stream resource.
     * @param resource $write Writable stream resource.
     * @param (Serializer | null) $serializer
     *
     * @throws \Error If a stream resource is not given for $resource.
     */
    public function __construct($read, $write, ?Serializer $serializer = null)
    {
        $this->channel = new ChannelledStream($this->read = new ResourceInputStream($read), $this->write = new ResourceOutputStream($write), $serializer);
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        return $this->channel->receive();
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        return $this->channel->send($data);
    }
    /**
     *
     */
    public function unreference() : void
    {
        $this->read->unreference();
    }
    /**
     *
     */
    public function reference() : void
    {
        $this->read->reference();
    }
    /**
     * Closes the read and write resource streams.
     */
    public function close() : void
    {
        $this->read->close();
        $this->write->close();
    }
}<?php

namespace Amp\Parallel\Sync;

class ParcelException extends \Exception
{
}<?php

namespace Amp\Parallel\Sync;

class ChannelException extends \Exception
{
}<?php

namespace Amp\Parallel\Sync;

use Amp\Promise;
/**
 * A parcel object for sharing data across execution contexts.
 *
 * A parcel is an object that stores a value in a safe way that can be shared
 * between different threads or processes. Different handles to the same parcel
 * will access the same data, and a parcel handle itself is serializable and
 * can be transported to other execution contexts.
 *
 * Wrapping and unwrapping values in the parcel are not atomic. To prevent race
 * conditions and guarantee safety, you should use the provided synchronization
 * methods to acquire a lock for exclusive access to the parcel first before
 * accessing the contained value.
 */
interface Parcel
{
    /**
    * Asynchronously invokes a callback while maintaining an exclusive lock on the parcel. The current value of the
    parcel is provided as the first argument to the callback function.
    *
    * @param callable $callback The synchronized callback to invoke. The parcel value is given as the single argument
    to the callback function. The callback may be a regular function or a coroutine.
    *
    * @return \Amp\Promise<mixed> Resolves with the return value of $callback or fails if $callback
    throws an exception.
    */
    public function synchronized(callable $callback) : Promise;
    /**
     * @return \Amp\Promise<mixed> A promise for the value inside the parcel.
     */
    public function unwrap() : Promise;
}<?php

namespace Amp\Parallel\Sync\Internal;

final class ParcelStorage extends \Threaded
{
    /** @var mixed */
    private $value;
    /**
     * @param mixed $value
     */
    public function __construct($value)
    {
        $this->value = $value;
    }
    /**
     * @return mixed
     */
    public function get()
    {
        return $this->value;
    }
    /**
     * @param mixed $value
     */
    public function set($value) : void
    {
        $this->value = $value;
    }
}<?php

namespace Amp\Parallel\Sync;

class SynchronizationError extends \Error
{
}<?php

namespace Amp\Parallel\Sync;

use Amp\Promise;
use Amp\Success;
use Amp\Sync\ThreadedMutex;
use function Amp\call;
/**
 * A thread-safe container that shares a value between multiple threads.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class ThreadedParcel implements Parcel
{
    /** @var ThreadedMutex */
    private $mutex;
    /** @var \Threaded */
    private $storage;
    /**
     * Creates a new shared object container.
     *
     * @param mixed $value The value to store in the container.
     */
    public function __construct($value)
    {
        $this->mutex = new ThreadedMutex();
        $this->storage = new Internal\ParcelStorage($value);
    }
    /**
     * {@inheritdoc}
     */
    public function unwrap() : Promise
    {
        return new Success($this->storage->get());
    }
    /**
     * @return \Amp\Promise
     */
    public function synchronized(callable $callback) : Promise
    {
        return call(function () use($callback) : \Generator {
            /** @var \Amp\Sync\Lock $lock */
            $lock = (yield $this->mutex->acquire());
            try {
                $result = (yield call($callback, $this->storage->get()));
                if ($result !== null) {
                    $this->storage->set($result);
                }
            } finally {
                $lock->release();
            }
            return $result;
        });
    }
}<?php

namespace Amp\Parallel\Sync;

use Amp\Promise;
/**
 * Interface for sending messages between execution contexts.
 */
interface Channel
{
    /**
    * @return \Amp\Promise<mixed>
    *
    * @throws \Amp\Parallel\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Parallel\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Parallel\Sync\ChannelException If receiving from the channel fails.
    * @throws \Amp\Parallel\Sync\SerializationException If unserializing the data fails.
    */
    public function receive() : Promise;
    /**
    * @param mixed $data
    *
    * @return \Amp\Promise<int> Resolves with the number of bytes sent on the channel.
    *
    * @throws \Amp\Parallel\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Parallel\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Parallel\Sync\ChannelException If sending on the channel fails.
    * @throws \Error If an ExitResult object is given.
    * @throws \Amp\Parallel\Sync\SerializationException If serializing the data fails.
    */
    public function send($data) : Promise;
}<?php

namespace Amp\Parallel\Sync;

use Amp\Serialization\SerializationException as SerializerException;
// Alias must be defined in an always-loaded file as catch blocks do not trigger the autoloader.
\class_alias(SerializerException::class, SerializationException::class);
/**
 * @param \Throwable $exception
 *
 * @return array Serializable exception backtrace, with all function arguments flattened to strings.
 */
function flattenThrowableBacktrace(\Throwable $exception) : array
{
    $trace = $exception->getTrace();
    foreach ($trace as &$call) {
        unset($call['object']);
        $call['args'] = \array_map(__NAMESPACE__ . '\\flattenArgument', $call['args'] ?? []);
    }
    return $trace;
}
/**
 * @param array $trace Backtrace produced by {@see formatFlattenedBacktrace()}.
 *
 * @return string
 */
function formatFlattenedBacktrace(array $trace) : string
{
    $output = [];
    foreach ($trace as $index => $call) {
        if (isset($call['class'])) {
            $name = $call['class'] . $call['type'] . $call['function'];
        } else {
            $name = $call['function'];
        }
        $output[] = \sprintf('#%d %s(%d): %s(%s)', $index, $call['file'] ?? '[internal function]', $call['line'] ?? 0, $name, \implode(', ', $call['args'] ?? ['...']));
    }
    return \implode("\n", $output);
}
/**
 * @param mixed $value
 *
 * @return string Serializable string representation of $value for backtraces.
 */
function flattenArgument($value) : string
{
    if ($value instanceof \Closure) {
        $closureReflection = new \ReflectionFunction($value);
        return \sprintf('Closure(%s:%s)', $closureReflection->getFileName(), $closureReflection->getStartLine());
    }
    if (\is_object($value)) {
        return \sprintf('Object(%s)', \get_class($value));
    }
    if (\is_array($value)) {
        return 'Array([' . \implode(', ', \array_map(__FUNCTION__, $value)) . '])';
    }
    if (\is_resource($value)) {
        return \sprintf('Resource(%s)', \get_resource_type($value));
    }
    if (\is_string($value)) {
        return '"' . $value . '"';
    }
    if (\is_null($value)) {
        return 'null';
    }
    if (\is_bool($value)) {
        return $value ? 'true' : 'false';
    }
    return (string) $value;
}<?php

namespace Amp\Parallel\Sync;

/**
 * @deprecated ContextPanicError will be thrown from uncaught exceptions in child processes and threads instead of
 * this class.
 */
class PanicError extends \Error
{
    /** @var string Class name of uncaught exception. */
    private $name;
    /** @var string Stack trace of the panic. */
    private $trace;
    /**
     * Creates a new panic error.
     *
     * @param string $name The uncaught exception class.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', ?\Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * @deprecated Use ContextPanicError::getOriginalClassName() instead.
     *
     * Returns the class name of the uncaught exception.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * @deprecated Use ContextPanicError::getOriginalTraceAsString() instead.
     *
     * Gets the stack trace at the point the panic occurred.
     *
     * @return string
     */
    public function getPanicTrace() : string
    {
        return $this->trace;
    }
}<?php

namespace Amp\Parallel\Sync;

use Amp\Parser\Parser;
use Amp\Serialization\NativeSerializer;
use Amp\Serialization\Serializer;
use function Amp\Serialization\encodeUnprintableChars;
final class ChannelParser extends Parser
{
    const HEADER_LENGTH = 5;
    /** @var Serializer */
    private $serializer;
    /**
     * @param callable(mixed $data) Callback invoked when data is parsed.
     * @param (Serializer | null) $serializer
     */
    public function __construct(callable $callback, ?Serializer $serializer = null)
    {
        $this->serializer = $serializer ?? new NativeSerializer();
        parent::__construct(self::parser($callback, $this->serializer));
    }
    /**
     * @param mixed $data Data to encode to send over a channel.
     *
     * @return string Encoded data that can be parsed by this class.
     *
     * @throws SerializationException
     */
    public function encode($data) : string
    {
        $data = $this->serializer->serialize($data);
        return \pack("CL", 0, \strlen($data)) . $data;
    }
    /**
     * @param callable $push
     * @param Serializer $serializer
     *
     * @return \Generator
     *
     * @throws ChannelException
     * @throws SerializationException
     */
    private static function parser(callable $push, Serializer $serializer) : \Generator
    {
        while (true) {
            $header = (yield self::HEADER_LENGTH);
            $data = \unpack("Cprefix/Llength", $header);
            if ($data["prefix"] !== 0) {
                $data = $header . yield;
                throw new ChannelException("Invalid packet received: " . encodeUnprintableChars($data));
            }
            $data = (yield $data["length"]);
            $push($serializer->unserialize($data));
        }
    }
}<?php

namespace Amp\Parallel\Sync;

interface ExitResult
{
    /**
     * @return mixed Return value of the callable given to the execution context.
     *
     * @throws \Amp\Parallel\Sync\PanicError If the context exited with an uncaught exception.
     */
    public function getResult();
}<?php

namespace Amp\Parallel\Sync;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
use Amp\ByteStream\StreamException;
use Amp\Promise;
use Amp\Serialization\Serializer;
use function Amp\call;
/**
 * An asynchronous channel for sending data between threads and processes.
 *
 * Supports full duplex read and write.
 */
final class ChannelledStream implements Channel
{
    /** @var InputStream */
    private $read;
    /** @var OutputStream */
    private $write;
    /** @var \SplQueue */
    private $received;
    /** @var ChannelParser */
    private $parser;
    /**
     * Creates a new channel from the given stream objects. Note that $read and $write can be the same object.
     *
     * @param InputStream $read
     * @param OutputStream $write
     * @param (Serializer | null) $serializer
     */
    public function __construct(InputStream $read, OutputStream $write, ?Serializer $serializer = null)
    {
        $this->read = $read;
        $this->write = $write;
        $this->received = new \SplQueue();
        $this->parser = new ChannelParser([$this->received, 'push'], $serializer);
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->write->write($this->parser->encode($data)));
            } catch (StreamException $exception) {
                throw new ChannelException("Sending on the channel failed. Did the context die?", 0, $exception);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        return call(function () : \Generator {
            while ($this->received->isEmpty()) {
                try {
                    $chunk = (yield $this->read->read());
                } catch (StreamException $exception) {
                    throw new ChannelException("Reading from the channel failed. Did the context die?", 0, $exception);
                }
                if ($chunk === null) {
                    throw new ChannelException("The channel closed unexpectedly. Did the context die?");
                }
                $this->parser->push($chunk);
            }
            return $this->received->shift();
        });
    }
}<?php

namespace Amp\Parallel\Context;

use Amp\Promise;
interface ContextFactory
{
    /**
    * Creates a new execution context.
    *
    * @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Context
    */
    public function create($script) : Context;
    /**
    * Creates and starts a new execution context.
    *
    * @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Promise<Context>
    */
    public function run($script) : Promise;
}<?php

namespace Amp\Parallel\Context;

use Amp\Failure;
use Amp\Loop;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitResult;
use Amp\Parallel\Sync\SynchronizationError;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
/**
 * Implements an execution context using native multi-threading.
 *
 * The thread context is not itself threaded. A local instance of the context is
 * maintained both in the context that creates the thread and in the thread
 * itself.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
final class Thread implements Context
{
    const EXIT_CHECK_FREQUENCY = 250;
    /** @var int */
    private static $nextId = 1;
    /** @var Internal\Thread An internal thread instance. */
    private $thread;
    /** @var ChannelledSocket A channel for communicating with the thread. */
    private $channel;
    /** @var resource */
    private $socket;
    /** @var callable */
    private $function;
    /** @var mixed[] */
    private $args;
    /** @var int|null */
    private $id;
    /** @var int */
    private $oid = 0;
    /** @var string */
    private $watcher;
    /**
     * Checks if threading is enabled.
     *
     * @return bool True if threading is enabled, otherwise false.
     */
    public static function isSupported() : bool
    {
        return \extension_loaded('pthreads');
    }
    /**
    * Creates and starts a new thread.
    *
    * @param callable $function The callable to invoke in the thread. First argument is an instance of
    \Amp\Parallel\Sync\Channel.
    * @param mixed ...$args Additional arguments to pass to the given callable.
    *
    * @return Promise<Thread> The thread object that was spawned.
    */
    public static function run(callable $function, ...$args) : Promise
    {
        $thread = new self($function, ...$args);
        return call(function () use($thread) : \Generator {
            (yield $thread->start());
            return $thread;
        });
    }
    /**
    * Creates a new thread.
    *
    * @param callable $function The callable to invoke in the thread. First argument is an instance of
    \Amp\Parallel\Sync\Channel.
    * @param mixed ...$args Additional arguments to pass to the given callable.
    *
    * @throws \Error Thrown if the pthreads extension is not available.
    */
    public function __construct(callable $function, ...$args)
    {
        if (!self::isSupported()) {
            throw new \Error("The pthreads extension is required to create threads.");
        }
        $this->function = $function;
        $this->args = $args;
    }
    /**
    * Returns the thread to the condition before starting. The new thread can be started and run independently of the
    first thread.
    */
    public function __clone()
    {
        $this->thread = null;
        $this->socket = null;
        $this->channel = null;
        $this->oid = 0;
    }
    /**
     * Kills the thread if it is still running.
     *
     * @throws \Amp\Parallel\Context\ContextException
     */
    public function __destruct()
    {
        if (\getmypid() === $this->oid) {
            $this->kill();
        }
    }
    /**
     * Checks if the context is running.
     *
     * @return bool True if the context is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->channel !== null;
    }
    /**
     * Spawns the thread and begins the thread's execution.
     *
     * @return Promise<int> Resolved once the thread has started.
     *
     * @throws \Amp\Parallel\Context\StatusError If the thread has already been started.
     * @throws \Amp\Parallel\Context\ContextException If starting the thread was unsuccessful.
     */
    public function start() : Promise
    {
        if ($this->oid !== 0) {
            throw new StatusError('The thread has already been started.');
        }
        $this->oid = \getmypid();
        $sockets = @\stream_socket_pair(\stripos(\PHP_OS, "win") === 0 ? STREAM_PF_INET : STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
        if ($sockets === false) {
            $message = "Failed to create socket pair";
            if ($error = \error_get_last()) {
                $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
            }
            return new Failure(new ContextException($message));
        }
        list($channel, $this->socket) = $sockets;
        $this->id = self::$nextId++;
        $thread = $this->thread = new Internal\Thread($this->id, $this->socket, $this->function, $this->args);
        if (!$this->thread->start(\PTHREADS_INHERIT_INI)) {
            return new Failure(new ContextException('Failed to start the thread.'));
        }
        $channel = $this->channel = new ChannelledSocket($channel, $channel);
        $this->watcher = Loop::repeat(self::EXIT_CHECK_FREQUENCY, static function ($watcher) use($thread, $channel) : void {
            if (!$thread->isRunning()) {
                // Delay closing to avoid race condition between thread exiting and data becoming available.
                Loop::delay(self::EXIT_CHECK_FREQUENCY, [$channel, "close"]);
                Loop::cancel($watcher);
            }
        });
        Loop::disable($this->watcher);
        return new Success($this->id);
    }
    /**
     * Immediately kills the context.
     *
     * @throws ContextException If killing the thread was unsuccessful.
     */
    public function kill() : void
    {
        if ($this->thread !== null) {
            try {
                if ($this->thread->isRunning() && !$this->thread->kill()) {
                    throw new ContextException('Could not kill thread.');
                }
            } finally {
                $this->close();
            }
        }
    }
    /**
     * Closes channel and socket if still open.
     */
    private function close() : void
    {
        if ($this->channel !== null) {
            $this->channel->close();
        }
        $this->channel = null;
        Loop::cancel($this->watcher);
    }
    /**
    * Gets a promise that resolves when the context ends and joins with the
    parent context.
    *
    * @return \Amp\Promise<mixed>
    *
    * @throws StatusError Thrown if the context has not been started.
    * @throws SynchronizationError Thrown if an exit status object is not received.
    * @throws ContextException If the context stops responding.
    */
    public function join() : Promise
    {
        if ($this->channel == null || $this->thread === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        return call(function () : \Generator {
            Loop::enable($this->watcher);
            try {
                $response = (yield $this->channel->receive());
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Failed to receive result from thread", 0, $exception);
            } finally {
                Loop::disable($this->watcher);
                $this->close();
            }
            if (!$response instanceof ExitResult) {
                $this->kill();
                throw new SynchronizationError('Did not receive an exit result from thread.');
            }
            return $response->getResult();
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The process has not been started.');
        }
        return call(function () : \Generator {
            Loop::enable($this->watcher);
            try {
                $data = (yield $this->channel->receive());
            } finally {
                Loop::disable($this->watcher);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Thread process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        if ($data instanceof ExitResult) {
            throw new \Error('Cannot send exit result objects.');
        }
        return call(function () use($data) : \Generator {
            Loop::enable($this->watcher);
            try {
                $result = (yield $this->channel->send($data));
            } finally {
                Loop::disable($this->watcher);
            }
            return $result;
        });
    }
    /**
     * Returns the ID of the thread. This ID will be unique to this process.
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getId() : int
    {
        if ($this->id === null) {
            throw new StatusError('The thread has not been started');
        }
        return $this->id;
    }
}<?php

namespace Amp\Parallel\Context;

class ContextException extends \Exception
{
}<?php

namespace Amp\Parallel\Context\Internal;

use Amp\Deferred;
use Amp\Loop;
use Amp\Parallel\Context\ContextException;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Promise;
use Amp\TimeoutException;
use function Amp\asyncCall;
use function Amp\call;
class ProcessHub
{
    const PROCESS_START_TIMEOUT = 5000;
    const KEY_RECEIVE_TIMEOUT = 1000;
    /** @var resource|null */
    private $server;
    /** @var string|null */
    private $uri;
    /** @var int[] */
    private $keys;
    /** @var string|null */
    private $watcher;
    /** @var Deferred[] */
    private $acceptor = [];
    /** @var string|null */
    private $toUnlink;
    /**
     *
     */
    public function __construct()
    {
        $isWindows = \strncasecmp(\PHP_OS, "WIN", 3) === 0;
        if ($isWindows) {
            $this->uri = "tcp://127.0.0.1:0";
        } else {
            $suffix = \bin2hex(\random_bytes(10));
            $path = \sys_get_temp_dir() . "/amp-parallel-ipc-" . $suffix . ".sock";
            $this->uri = "unix://" . $path;
            $this->toUnlink = $path;
        }
        $context = \stream_context_create(['socket' => ['backlog' => 128]]);
        $this->server = \stream_socket_server($this->uri, $errno, $errstr, \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN, $context);
        if (!$this->server) {
            throw new \RuntimeException(\sprintf("Could not create IPC server: (Errno: %d) %s", $errno, $errstr));
        }
        if ($isWindows) {
            $name = \stream_socket_get_name($this->server, false);
            $port = \Phabel\Target\Php80\Polyfill::substr($name, \strrpos($name, ":") + 1);
            $this->uri = "tcp://127.0.0.1:" . $port;
        }
        $keys =& $this->keys;
        $acceptor =& $this->acceptor;
        $this->watcher = Loop::onReadable($this->server, static function (string $watcher, $server) use(&$keys, &$acceptor) : void {
            // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
            while ($client = @\stream_socket_accept($server, 0)) {
                // Timeout of 0 to be non-blocking.
                asyncCall(static function () use($client, &$keys, &$acceptor) {
                    $channel = new ChannelledSocket($client, $client);
                    try {
                        $received = (yield Promise\timeout($channel->receive(), self::KEY_RECEIVE_TIMEOUT));
                    } catch (\Throwable $exception) {
                        $channel->close();
                        return;
                        // Ignore possible foreign connection attempt.
                    }
                    if (!\is_string($received) || !isset($keys[$received])) {
                        $channel->close();
                        return;
                        // Ignore possible foreign connection attempt.
                    }
                    $pid = $keys[$received];
                    $deferred = $acceptor[$pid];
                    unset($acceptor[$pid], $keys[$received]);
                    $deferred->resolve($channel);
                });
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->watcher);
        \fclose($this->server);
        if ($this->toUnlink !== null) {
            @\unlink($this->toUnlink);
        }
    }
    /**
     *
     */
    public function getUri() : string
    {
        return $this->uri;
    }
    /**
     *
     */
    public function generateKey(int $pid, int $length) : string
    {
        $key = \random_bytes($length);
        $this->keys[$key] = $pid;
        return $key;
    }
    /**
     *
     */
    public function accept(int $pid) : Promise
    {
        return call(function () use($pid) : \Generator {
            $this->acceptor[$pid] = new Deferred();
            Loop::enable($this->watcher);
            try {
                $channel = (yield Promise\timeout($this->acceptor[$pid]->promise(), self::PROCESS_START_TIMEOUT));
            } catch (TimeoutException $exception) {
                $key = \array_search($pid, $this->keys, true);
                \assert(\is_string($key), "Key for {$pid} not found");
                unset($this->acceptor[$pid], $this->keys[$key]);
                throw new ContextException("Starting the process timed out", 0, $exception);
            } finally {
                if (empty($this->acceptor)) {
                    Loop::disable($this->watcher);
                }
            }
            return $channel;
        });
    }
}<?php

namespace Amp\Parallel\Context\Internal;

use Amp\Parallel\Context\Process;
use Amp\Parallel\Sync;
use Amp\Promise;
use function Amp\call;
use function Amp\getCurrentTime;
\define("AMP_CONTEXT", "process");
\define("AMP_CONTEXT_ID", \getmypid());
// Doesn't exist in phpdbg...
if (\function_exists("cli_set_process_title")) {
    @\cli_set_process_title("amp-process");
}
(function () : void {
    $paths = [\dirname(__DIR__, 5) . "/autoload.php", \dirname(__DIR__, 3) . "/vendor/autoload.php"];
    foreach ($paths as $path) {
        if (\file_exists($path)) {
            $autoloadPath = $path;
            break;
        }
    }
    if (!isset($autoloadPath)) {
        \trigger_error("Could not locate autoload.php in any of the following files: " . \implode(", ", $paths), E_USER_ERROR);
        exit(1);
    }
    require $autoloadPath;
})();
(function () use($argc, $argv) : void {
    // Remove this scripts path from process arguments.
    --$argc;
    \array_shift($argv);
    if (!isset($argv[0])) {
        \trigger_error("No socket path provided", E_USER_ERROR);
        exit(1);
    }
    // Remove socket path from process arguments.
    --$argc;
    $uri = \array_shift($argv);
    $key = "";
    // Read random key from STDIN and send back to parent over IPC socket to authenticate.
    do {
        if (($chunk = \fread(\STDIN, Process::KEY_LENGTH)) === false || \feof(\STDIN)) {
            \trigger_error("Could not read key from parent", E_USER_ERROR);
            exit(1);
        }
        $key .= $chunk;
    } while (\strlen($key) < Process::KEY_LENGTH);
    $connectStart = getCurrentTime();
    while (!($socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT))) {
        if (getCurrentTime() < $connectStart + 5000) {
            // try for 5 seconds, after that the parent times out anyway
            \trigger_error("Could not connect to IPC socket", \E_USER_ERROR);
            exit(1);
        }
        \usleep(50 * 1000);
    }
    $channel = new Sync\ChannelledSocket($socket, $socket);
    try {
        Promise\wait($channel->send($key));
    } catch (\Throwable $exception) {
        \trigger_error("Could not send key to parent", E_USER_ERROR);
        exit(1);
    }
    try {
        if (!isset($argv[0])) {
            throw new \Error("No script path given");
        }
        if (!\is_file($argv[0])) {
            throw new \Error(\sprintf("No script found at '%s' (be sure to provide the full path to the script)", $argv[0]));
        }
        try {
            // Protect current scope by requiring script within another function.
            $callable = (function () use($argc, $argv) : callable {
                // Using $argc so it is available to the required script.
                return require $argv[0];
            })();
        } catch (\TypeError $exception) {
            throw new \Error(\sprintf("Script '%s' did not return a callable function", $argv[0]), 0, $exception);
        } catch (\ParseError $exception) {
            throw new \Error(\sprintf("Script '%s' contains a parse error: " . $exception->getMessage(), $argv[0]), 0, $exception);
        }
        $result = new Sync\ExitSuccess(Promise\wait(call($callable, $channel)));
    } catch (\Throwable $exception) {
        $result = new Sync\ExitFailure($exception);
    }
    try {
        Promise\wait(call(function () use($channel, $result) : \Generator {
            try {
                (yield $channel->send($result));
            } catch (Sync\SerializationException $exception) {
                // Serializing the result failed. Send the reason why.
                (yield $channel->send(new Sync\ExitFailure($exception)));
            }
        }));
    } catch (\Throwable $exception) {
        \trigger_error("Could not send result to parent; be sure to shutdown the child before ending the parent", E_USER_ERROR);
        exit(1);
    }
})();<?php

namespace Amp\Parallel\Context\Internal;

use Amp\Loop;
use Amp\Parallel\Sync\Channel;
use Amp\Parallel\Sync\ChannelException;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitFailure;
use Amp\Parallel\Sync\ExitSuccess;
use Amp\Parallel\Sync\SerializationException;
use function Amp\call;
/**
 * An internal thread that executes a given function concurrently.
 *
 * @internal
 */
final class Thread extends \Thread
{
    const KILL_CHECK_FREQUENCY = 250;
    private $id;
    /** @var callable The function to execute in the thread. */
    private $function;
    /** @var mixed[] Arguments to pass to the function. */
    private $args;
    /** @var resource */
    private $socket;
    /** @var bool */
    private $killed = false;
    /**
     * Creates a new thread object.
     *
     * @param int $id Thread ID.
     * @param resource $socket IPC communication socket.
     * @param callable $function The function to execute in the thread.
     * @param mixed[] $args Arguments to pass to the function.
     */
    public function __construct(int $id, $socket, callable $function, array $args = [])
    {
        $this->id = $id;
        $this->function = $function;
        $this->args = $args;
        $this->socket = $socket;
    }
    /**
     * Runs the thread code and the initialized function.
     *
     * @codeCoverageIgnore Only executed in thread.
     */
    public function run()
    {
        \define("AMP_CONTEXT", "thread");
        \define("AMP_CONTEXT_ID", $this->id);
        /* First thing we need to do is re-initialize the class autoloader. If
         * we don't do this first, any object of a class that was loaded after
         * the thread started will just be garbage data and unserializable
         * values (like resources) will be lost. This happens even with
         * thread-safe objects.
         */
        // Protect scope by using an unbound closure (protects static access as well).
        (static function () : void {
            $paths = [\dirname(__DIR__, 3) . \DIRECTORY_SEPARATOR . "vendor" . \DIRECTORY_SEPARATOR . "autoload.php", \dirname(__DIR__, 5) . \DIRECTORY_SEPARATOR . "autoload.php"];
            foreach ($paths as $path) {
                if (\file_exists($path)) {
                    $autoloadPath = $path;
                    break;
                }
            }
            if (!isset($autoloadPath)) {
                throw new \Error("Could not locate autoload.php");
            }
            require $autoloadPath;
        })->bindTo(null, null)();
        // At this point, the thread environment has been prepared so begin using the thread.
        if ($this->killed) {
            return;
            // Thread killed while requiring autoloader, simply exit.
        }
        Loop::run(function () : \Generator {
            $watcher = Loop::repeat(self::KILL_CHECK_FREQUENCY, function () : void {
                if ($this->killed) {
                    Loop::stop();
                }
            });
            Loop::unreference($watcher);
            try {
                $channel = new ChannelledSocket($this->socket, $this->socket);
                yield from $this->execute($channel);
            } catch (\Throwable $exception) {
                return;
                // Parent context exited or destroyed thread, no need to continue.
            } finally {
                Loop::cancel($watcher);
            }
        });
    }
    /**
     * Sets a local variable to true so the running event loop can check for a kill signal.
     */
    public function kill()
    {
        return $this->killed = true;
    }
    /**
     * @param \Amp\Parallel\Sync\Channel $channel
     *
     * @return \Generator
     *
     * @codeCoverageIgnore Only executed in thread.
     */
    private function execute(Channel $channel) : \Generator
    {
        try {
            $result = new ExitSuccess((yield call($this->function, $channel, ...$this->args)));
        } catch (\Throwable $exception) {
            $result = new ExitFailure($exception);
        }
        if ($this->killed) {
            return;
            // Parent is not listening for a result.
        }
        // Attempt to return the result.
        try {
            try {
                (yield $channel->send($result));
            } catch (SerializationException $exception) {
                // Serializing the result failed. Send the reason why.
                (yield $channel->send(new ExitFailure($exception)));
            }
        } catch (ChannelException $exception) {
            // The result was not sendable! The parent context must have died or killed the context.
        }
    }
}<?php

namespace Amp\Parallel\Context\Internal;

use Amp\Loop;
use Amp\Parallel\Sync\ChannelledSocket;
use parallel\Events;
use parallel\Future;
class ParallelHub extends ProcessHub
{
    const EXIT_CHECK_FREQUENCY = 250;
    /** @var ChannelledSocket[] */
    private $channels;
    /** @var string */
    private $watcher;
    /** @var Events */
    private $events;
    /**
     *
     */
    public function __construct()
    {
        parent::__construct();
        $events = $this->events = new Events();
        $this->events->setBlocking(false);
        $channels =& $this->channels;
        $this->watcher = Loop::repeat(self::EXIT_CHECK_FREQUENCY, static function () use(&$channels, $events) : void {
            while ($event = $events->poll()) {
                $id = (int) $event->source;
                \assert(isset($channels[$id]), 'Channel for context ID not found');
                $channel = $channels[$id];
                unset($channels[$id]);
                $channel->close();
            }
        });
        Loop::disable($this->watcher);
        Loop::unreference($this->watcher);
    }
    /**
     *
     */
    public function add(int $id, ChannelledSocket $channel, Future $future) : void
    {
        $this->channels[$id] = $channel;
        $this->events->addFuture((string) $id, $future);
        Loop::enable($this->watcher);
    }
    /**
     *
     */
    public function remove(int $id) : void
    {
        if (!isset($this->channels[$id])) {
            return;
        }
        unset($this->channels[$id]);
        $this->events->remove((string) $id);
        if (empty($this->channels)) {
            Loop::disable($this->watcher);
        }
    }
}<?php

namespace Amp\Parallel\Context;

class StatusError extends \Error
{
}<?php

namespace Amp\Parallel\Context;

use Amp\Promise;
class DefaultContextFactory implements ContextFactory
{
    /**
     *
     */
    public function create($script) : Context
    {
        /**
         * Creates a thread if ext-parallel is installed, otherwise creates a child process.
         *
         * @inheritdoc
         */
        if (Parallel::isSupported()) {
            return new Parallel($script);
        }
        return new Process($script);
    }
    /**
     * Creates and starts a thread if ext-parallel is installed, otherwise creates a child process.
     *
     * @inheritdoc
     */
    public function run($script) : Promise
    {
        if (Parallel::isSupported()) {
            return Parallel::run($script);
        }
        return Process::run($script);
    }
}<?php

namespace Amp\Parallel\Context;

use Amp\Loop;
use Amp\Promise;
const LOOP_FACTORY_IDENTIFIER = ContextFactory::class;
/**
* @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
*
* @return Context
*/
function create($script) : Context
{
    return factory()->create($script);
}
/**
* Creates and starts a process based on installed extensions (a thread if ext-parallel is installed, otherwise a child
process).
*
* @param (string | string[]) $script Path to PHP script or array with first element as path and following elements options
to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
*
* @return Promise<Context>
*/
function run($script) : Promise
{
    return factory()->run($script);
}
/**
 * Gets or sets the global context factory.
 *
 * @param (ContextFactory | null) $factory
 *
 * @return ContextFactory
 */
function factory(?ContextFactory $factory = null) : ContextFactory
{
    if ($factory === null) {
        $factory = Loop::getState(LOOP_FACTORY_IDENTIFIER);
        if ($factory) {
            return $factory;
        }
        $factory = new DefaultContextFactory();
    }
    Loop::setState(LOOP_FACTORY_IDENTIFIER, $factory);
    return $factory;
}<?php

namespace Amp\Parallel\Context;

use Amp\Loop;
use Amp\Parallel\Sync\ChannelException;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitResult;
use Amp\Parallel\Sync\SynchronizationError;
use Amp\Process\Process as BaseProcess;
use Amp\Process\ProcessInputStream;
use Amp\Process\ProcessOutputStream;
use Amp\Promise;
use Amp\TimeoutException;
use function Amp\call;
final class Process implements Context
{
    const SCRIPT_PATH = __DIR__ . "/Internal/process-runner.php";
    const KEY_LENGTH = 32;
    /** @var string|null External version of SCRIPT_PATH if inside a PHAR. */
    private static $pharScriptPath;
    /** @var string|null PHAR path with a '.phar' extension. */
    private static $pharCopy;
    /** @var string|null Cached path to located PHP binary. */
    private static $binaryPath;
    /** @var Internal\ProcessHub */
    private $hub;
    /** @var BaseProcess */
    private $process;
    /** @var ChannelledSocket */
    private $channel;
    /**
    * Creates and starts the process at the given path using the optional PHP binary path.
    *
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    * @param (string | null) $cwd Working directory.
    * @param mixed[] $env Array of environment variables.
    * @param string $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    *
    * @return Promise<Process>
    */
    public static function run($script, string $cwd = null, array $env = [], string $binary = null) : Promise
    {
        $process = new self($script, $cwd, $env, $binary);
        return call(function () use($process) : \Generator {
            (yield $process->start());
            return $process;
        });
    }
    /**
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    * @param (string | null) $cwd Working directory.
    * @param mixed[] $env Array of environment variables.
    * @param string $binary Path to PHP binary. Null will attempt to automatically locate the binary.
    *
    * @throws \Error If the PHP binary path given cannot be found or is not executable.
    */
    public function __construct($script, string $cwd = null, array $env = [], string $binary = null)
    {
        $this->hub = Loop::getState(self::class);
        if (!$this->hub instanceof Internal\ProcessHub) {
            $this->hub = new Internal\ProcessHub();
            Loop::setState(self::class, $this->hub);
        }
        $options = ["html_errors" => "0", "display_errors" => "0", "log_errors" => "1"];
        if ($binary === null) {
            if (\PHP_SAPI === "cli") {
                $binary = \PHP_BINARY;
            } else {
                $binary = self::$binaryPath ?? self::locateBinary();
            }
        } elseif (!\is_executable($binary)) {
            throw new \Error(\sprintf("The PHP binary path '%s' was not found or is not executable", $binary));
        }
        // Write process runner to external file if inside a PHAR,
        // because PHP can't open files inside a PHAR directly except for the stub.
        if (\strpos(self::SCRIPT_PATH, "phar://") === 0) {
            if (self::$pharScriptPath) {
                $scriptPath = self::$pharScriptPath;
            } else {
                $path = \dirname(self::SCRIPT_PATH);
                if (\Phabel\Target\Php80\Polyfill::substr(\Phar::running(false), -5) !== ".phar") {
                    self::$pharCopy = \sys_get_temp_dir() . "/phar-" . \bin2hex(\random_bytes(10)) . ".phar";
                    \copy(\Phar::running(false), self::$pharCopy);
                    \register_shutdown_function(static function () : void {
                        @\unlink(self::$pharCopy);
                    });
                    $path = "phar://" . self::$pharCopy . "/" . \Phabel\Target\Php80\Polyfill::substr($path, \strlen(\Phar::running(true)));
                }
                $contents = \file_get_contents(self::SCRIPT_PATH);
                $contents = \str_replace("__DIR__", \var_export($path, true), $contents);
                $suffix = \bin2hex(\random_bytes(10));
                self::$pharScriptPath = $scriptPath = \sys_get_temp_dir() . "/amp-process-runner-" . $suffix . ".php";
                \file_put_contents($scriptPath, $contents);
                \register_shutdown_function(static function () : void {
                    @\unlink(self::$pharScriptPath);
                });
            }
            // Monkey-patch the script path in the same way, only supported if the command is given as array.
            if (isset(self::$pharCopy) && \is_array($script) && isset($script[0])) {
                $script[0] = "phar://" . self::$pharCopy . \Phabel\Target\Php80\Polyfill::substr($script[0], \strlen(\Phar::running(true)));
            }
        } else {
            $scriptPath = self::SCRIPT_PATH;
        }
        if (\is_array($script)) {
            $script = \implode(" ", \array_map("escapeshellarg", $script));
        } else {
            $script = \escapeshellarg($script);
        }
        $command = \implode(" ", [\escapeshellarg($binary), $this->formatOptions($options), \escapeshellarg($scriptPath), $this->hub->getUri(), $script]);
        $this->process = new BaseProcess($command, $cwd, $env);
    }
    /**
     *
     */
    private static function locateBinary() : string
    {
        $executable = \strncasecmp(\PHP_OS, "WIN", 3) === 0 ? "php.exe" : "php";
        $paths = \array_filter(\explode(\PATH_SEPARATOR, \getenv("PATH")));
        $paths[] = \PHP_BINDIR;
        $paths = \array_unique($paths);
        foreach ($paths as $path) {
            $path .= \DIRECTORY_SEPARATOR . $executable;
            if (\is_executable($path)) {
                return self::$binaryPath = $path;
            }
        }
        throw new \Error("Could not locate PHP executable binary");
    }
    /**
     *
     */
    private function formatOptions(array $options) : string
    {
        $result = [];
        foreach ($options as $option => $value) {
            $result[] = \sprintf("-d%s=%s", $option, $value);
        }
        return \implode(" ", $result);
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * {@inheritdoc}
     */
    public function start() : Promise
    {
        return call(function () : \Generator {
            try {
                $pid = (yield $this->process->start());
                (yield $this->process->getStdin()->write($this->hub->generateKey($pid, self::KEY_LENGTH)));
                $this->channel = (yield $this->hub->accept($pid));
                return $pid;
            } catch (\Throwable $exception) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new ContextException("Starting the process failed", 0, $exception);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function isRunning() : bool
    {
        return $this->process->isRunning();
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (ChannelException $e) {
                throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        if ($data instanceof ExitResult) {
            throw new \Error("Cannot send exit result objects");
        }
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->channel->send($data));
            } catch (ChannelException $e) {
                if ($this->channel === null) {
                    throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                try {
                    $data = (yield Promise\timeout($this->join(), 100));
                } catch (ContextException|ChannelException|TimeoutException $ex) {
                    if ($this->isRunning()) {
                        $this->kill();
                    }
                    throw new ContextException("The process stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                throw new SynchronizationError(\sprintf('Process unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)), 0, $e);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function join() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError("The process has not been started");
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (\Throwable $exception) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new ContextException("Failed to receive result from process", 0, $exception);
            }
            if (!$data instanceof ExitResult) {
                if ($this->isRunning()) {
                    $this->kill();
                }
                throw new SynchronizationError("Did not receive an exit result from process");
            }
            $this->channel->close();
            $code = (yield $this->process->join());
            if ($code !== 0) {
                throw new ContextException(\sprintf("Process exited with code %d", $code));
            }
            return $data->getResult();
        });
    }
    /**
     * Send a signal to the process.
     *
     * @see \Amp\Process\Process::signal()
     *
     * @param int $signo
     *
     * @throws \Amp\Process\ProcessException
     * @throws \Amp\Process\StatusError
     */
    public function signal(int $signo) : void
    {
        $this->process->signal($signo);
    }
    /**
     * Returns the PID of the process.
     *
     * @see \Amp\Process\Process::getPid()
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getPid() : int
    {
        return $this->process->getPid();
    }
    /**
     * Returns the STDIN stream of the process.
     *
     * @see \Amp\Process\Process::getStdin()
     *
     * @return ProcessOutputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStdin() : ProcessOutputStream
    {
        return $this->process->getStdin();
    }
    /**
     * Returns the STDOUT stream of the process.
     *
     * @see \Amp\Process\Process::getStdout()
     *
     * @return ProcessInputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStdout() : ProcessInputStream
    {
        return $this->process->getStdout();
    }
    /**
     * Returns the STDOUT stream of the process.
     *
     * @see \Amp\Process\Process::getStderr()
     *
     * @return ProcessInputStream
     *
     * @throws \Amp\Process\StatusError
     */
    public function getStderr() : ProcessInputStream
    {
        return $this->process->getStderr();
    }
    /**
     * {@inheritdoc}
     */
    public function kill() : void
    {
        $this->process->kill();
        if ($this->channel !== null) {
            $this->channel->close();
        }
    }
}<?php

namespace Amp\Parallel\Context;

use Amp\Loop;
use Amp\Parallel\Sync\ChannelException;
use Amp\Parallel\Sync\ChannelledSocket;
use Amp\Parallel\Sync\ExitFailure;
use Amp\Parallel\Sync\ExitResult;
use Amp\Parallel\Sync\ExitSuccess;
use Amp\Parallel\Sync\SerializationException;
use Amp\Parallel\Sync\SynchronizationError;
use Amp\Promise;
use Amp\TimeoutException;
use parallel\Runtime;
use function Amp\call;
/**
 * Implements an execution context using native threads provided by the parallel extension.
 */
final class Parallel implements Context
{
    const EXIT_CHECK_FREQUENCY = 250;
    const KEY_LENGTH = 32;
    /** @var string|null */
    private static $autoloadPath;
    /** @var int Next thread ID. */
    private static $nextId = 1;
    /** @var Internal\ProcessHub */
    private $hub;
    /** @var int|null */
    private $id;
    /** @var Runtime|null */
    private $runtime;
    /** @var ChannelledSocket|null A channel for communicating with the parallel thread. */
    private $channel;
    /** @var string Script path. */
    private $script;
    /** @var string[] */
    private $args = [];
    /** @var int */
    private $oid = 0;
    /** @var bool */
    private $killed = false;
    /**
     * Checks if threading is enabled.
     *
     * @return bool True if threading is enabled, otherwise false.
     */
    public static function isSupported() : bool
    {
        return \extension_loaded('parallel');
    }
    /**
    * Creates and starts a new thread.
    *
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @return Promise<Thread> The thread object that was spawned.
    */
    public static function run($script) : Promise
    {
        $thread = new self($script);
        return call(function () use($thread) : \Generator {
            (yield $thread->start());
            return $thread;
        });
    }
    /**
    * @param (string | array) $script Path to PHP script or array with first element as path and following elements options
    to the PHP script (e.g.: ['bin/worker', 'Option1Value', 'Option2Value'].
    *
    * @throws \Error Thrown if the pthreads extension is not available.
    */
    public function __construct($script)
    {
        if (!self::isSupported()) {
            throw new \Error("The parallel extension is required to create parallel threads.");
        }
        $this->hub = Loop::getState(self::class);
        if (!$this->hub instanceof Internal\ParallelHub) {
            $this->hub = new Internal\ParallelHub();
            Loop::setState(self::class, $this->hub);
        }
        if (\is_array($script)) {
            $this->script = (string) \array_shift($script);
            $this->args = \array_values(\array_map("strval", $script));
        } else {
            $this->script = (string) $script;
        }
        if (self::$autoloadPath === null) {
            $paths = [\dirname(__DIR__, 2) . \DIRECTORY_SEPARATOR . "vendor" . \DIRECTORY_SEPARATOR . "autoload.php", \dirname(__DIR__, 4) . \DIRECTORY_SEPARATOR . "autoload.php"];
            foreach ($paths as $path) {
                if (\file_exists($path)) {
                    self::$autoloadPath = $path;
                    break;
                }
            }
            if (self::$autoloadPath === null) {
                throw new \Error("Could not locate autoload.php");
            }
        }
    }
    /**
    * Returns the thread to the condition before starting. The new thread can be started and run independently of the
    first thread.
    */
    public function __clone()
    {
        $this->runtime = null;
        $this->channel = null;
        $this->id = null;
        $this->oid = 0;
        $this->killed = false;
    }
    /**
     * Kills the thread if it is still running.
     *
     * @throws \Amp\Parallel\Context\ContextException
     */
    public function __destruct()
    {
        if (\getmypid() === $this->oid) {
            $this->kill();
        }
    }
    /**
     * Checks if the context is running.
     *
     * @return bool True if the context is running, otherwise false.
     */
    public function isRunning() : bool
    {
        return $this->channel !== null;
    }
    /**
     * Spawns the thread and begins the thread's execution.
     *
     * @return Promise<int> Resolved once the thread has started.
     *
     * @throws \Amp\Parallel\Context\StatusError If the thread has already been started.
     * @throws \Amp\Parallel\Context\ContextException If starting the thread was unsuccessful.
     */
    public function start() : Promise
    {
        if ($this->oid !== 0) {
            throw new StatusError('The thread has already been started.');
        }
        $this->oid = \getmypid();
        $this->runtime = new Runtime(self::$autoloadPath);
        $this->id = self::$nextId++;
        $future = $this->runtime->run(static function (int $id, string $uri, string $key, string $path, array $argv) : int {
            // @codeCoverageIgnoreStart
            // Only executed in thread.
            \define("AMP_CONTEXT", "parallel");
            \define("AMP_CONTEXT_ID", $id);
            if (!($socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT))) {
                \trigger_error("Could not connect to IPC socket", E_USER_ERROR);
                return 1;
            }
            $channel = new ChannelledSocket($socket, $socket);
            try {
                Promise\wait($channel->send($key));
            } catch (\Throwable $exception) {
                \trigger_error("Could not send key to parent", E_USER_ERROR);
                return 1;
            }
            try {
                Loop::unreference(Loop::repeat(self::EXIT_CHECK_FREQUENCY, function () : void {
                    // Timer to give the chance for the PHP VM to be interrupted by Runtime::kill(), since system calls such as
                    // select() will not be interrupted.
                }));
                try {
                    if (!\is_file($path)) {
                        throw new \Error(\sprintf("No script found at '%s' (be sure to provide the full path to the script)", $path));
                    }
                    $argc = \array_unshift($argv, $path);
                    try {
                        // Protect current scope by requiring script within another function.
                        $callable = (function () use($argc, $argv) : callable {
                            // Using $argc so it is available to the required script.
                            return require $argv[0];
                        })->bindTo(null, null)();
                    } catch (\TypeError $exception) {
                        throw new \Error(\sprintf("Script '%s' did not return a callable function", $path), 0, $exception);
                    } catch (\ParseError $exception) {
                        throw new \Error(\sprintf("Script '%s' contains a parse error", $path), 0, $exception);
                    }
                    $result = new ExitSuccess(Promise\wait(call($callable, $channel)));
                } catch (\Throwable $exception) {
                    $result = new ExitFailure($exception);
                }
                Promise\wait(call(function () use($channel, $result) : \Generator {
                    try {
                        (yield $channel->send($result));
                    } catch (SerializationException $exception) {
                        // Serializing the result failed. Send the reason why.
                        (yield $channel->send(new ExitFailure($exception)));
                    }
                }));
            } catch (\Throwable $exception) {
                \trigger_error("Could not send result to parent; be sure to shutdown the child before ending the parent", E_USER_ERROR);
                return 1;
            } finally {
                $channel->close();
            }
            return 0;
            // @codeCoverageIgnoreEnd
        }, [$this->id, $this->hub->getUri(), $this->hub->generateKey($this->id, self::KEY_LENGTH), $this->script, $this->args]);
        return call(function () use($future) : \Generator {
            try {
                $this->channel = (yield $this->hub->accept($this->id));
                $this->hub->add($this->id, $this->channel, $future);
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Starting the parallel runtime failed", 0, $exception);
            }
            if ($this->killed) {
                $this->kill();
            }
            return $this->id;
        });
    }
    /**
     * Immediately kills the context.
     */
    public function kill() : void
    {
        $this->killed = true;
        if ($this->runtime !== null) {
            try {
                $this->runtime->kill();
            } finally {
                $this->close();
            }
        }
    }
    /**
     * Closes channel and socket if still open.
     */
    private function close() : void
    {
        $this->runtime = null;
        if ($this->channel !== null) {
            $this->channel->close();
        }
        $this->channel = null;
        $this->hub->remove($this->id);
    }
    /**
    * Gets a promise that resolves when the context ends and joins with the
    parent context.
    *
    * @return \Amp\Promise<mixed>
    *
    * @throws StatusError Thrown if the context has not been started.
    * @throws SynchronizationError Thrown if an exit status object is not received.
    * @throws ContextException If the context stops responding.
    */
    public function join() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        return call(function () : \Generator {
            try {
                $response = (yield $this->channel->receive());
                $this->close();
            } catch (\Throwable $exception) {
                $this->kill();
                throw new ContextException("Failed to receive result from thread", 0, $exception);
            }
            if (!$response instanceof ExitResult) {
                $this->kill();
                throw new SynchronizationError('Did not receive an exit result from thread.');
            }
            return $response->getResult();
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started.');
        }
        return call(function () : \Generator {
            try {
                $data = (yield $this->channel->receive());
            } catch (ChannelException $e) {
                throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
            }
            if ($data instanceof ExitResult) {
                $data = $data->getResult();
                throw new SynchronizationError(\sprintf('Thread unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)));
            }
            return $data;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->channel === null) {
            throw new StatusError('The thread has not been started or has already finished.');
        }
        if ($data instanceof ExitResult) {
            throw new \Error('Cannot send exit result objects.');
        }
        return call(function () use($data) : \Generator {
            try {
                return (yield $this->channel->send($data));
            } catch (ChannelException $e) {
                if ($this->channel === null) {
                    throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                try {
                    $data = (yield Promise\timeout($this->join(), 100));
                } catch (ContextException|ChannelException|TimeoutException $ex) {
                    $this->kill();
                    throw new ContextException("The thread stopped responding, potentially due to a fatal error or calling exit", 0, $e);
                }
                throw new SynchronizationError(\sprintf('Thread unexpectedly exited with result of type: %s', \is_object($data) ? \get_class($data) : \gettype($data)), 0, $e);
            }
        });
    }
    /**
     * Returns the ID of the thread. This ID will be unique to this process.
     *
     * @return int
     *
     * @throws \Amp\Process\StatusError
     */
    public function getId() : int
    {
        if ($this->id === null) {
            throw new StatusError('The thread has not been started');
        }
        return $this->id;
    }
}<?php

namespace Amp\Parallel\Context;

use Amp\Parallel\Sync\Channel;
use Amp\Promise;
interface Context extends Channel
{
    /**
     * @return bool
     */
    public function isRunning() : bool;
    /**
     * Starts the execution context.
     *
     * @return Promise<null> Resolved once the context has started.
     */
    public function start() : Promise;
    /**
     * Immediately kills the context.
     */
    public function kill();
    /**
     * @return \Amp\Promise<mixed> Resolves with the returned from the context.
     *
     * @throws \Amp\Parallel\Context\ContextException If the context dies unexpectedly.
     * @throws \Amp\Parallel\Sync\PanicError If the context throws an uncaught exception.
     */
    public function join() : Promise;
}<?php

namespace Amp\Redis;

use Exception;
class RedisException extends Exception
{
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Promise;
final class RedisHyperLogLog
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param string $element
     * @param string ...$elements
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/pfadd
     */
    public function add(string $element, string ...$elements) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['pfadd', $this->key, $element], $elements), toBool);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/pfcount
     */
    public function count() : Promise
    {
        return $this->queryExecutor->execute(['pfcount', $this->key]);
    }
    /**
     * @param string $sourceKey
     * @param string ...$sourceKeys
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/pfmerge
     */
    public function storeUnion(string $sourceKey, string ...$sourceKeys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['pfmerge', $this->key, $sourceKey], $sourceKeys), toNull);
    }
}<?php

namespace Amp\Redis;

final class RespParser
{
    public const CRLF = "\r\n";
    public const TYPE_SIMPLE_STRING = '+';
    public const TYPE_ERROR = '-';
    public const TYPE_ARRAY = '*';
    public const TYPE_BULK_STRING = '$';
    public const TYPE_INTEGER = ':';
    private $responseCallback;
    private $buffer = '';
    private $currentResponse;
    private $arrayStack;
    private $currentSize;
    private $arraySizes;
    /**
     *
     */
    public function __construct(callable $responseCallback)
    {
        $this->responseCallback = $responseCallback;
    }
    /**
     *
     */
    public function reset() : void
    {
        $this->buffer = '';
        $this->currentResponse = null;
        $this->arrayStack = null;
        $this->currentSize = null;
        $this->arraySizes = null;
    }
    /**
     *
     */
    public function append(string $str) : void
    {
        $this->buffer .= $str;
        do {
            $type = $this->buffer[0];
            $pos = \strpos($this->buffer, self::CRLF);
            if ($pos === false) {
                return;
            }
            switch ($type) {
                case self::TYPE_SIMPLE_STRING:
                case self::TYPE_INTEGER:
                case self::TYPE_ARRAY:
                case self::TYPE_ERROR:
                    $payload = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 1, $pos - 1);
                    $remove = $pos + 2;
                    break;
                case self::TYPE_BULK_STRING:
                    $length = (int) \Phabel\Target\Php80\Polyfill::substr($this->buffer, 1, $pos);
                    if ($length === -1) {
                        $payload = null;
                        $remove = $pos + 2;
                    } else {
                        if (\strlen($this->buffer) < $pos + $length + 4) {
                            return;
                        }
                        $payload = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $pos + 2, $length);
                        $remove = $pos + $length + 4;
                    }
                    break;
                default:
                    throw new ParserException(\sprintf('unknown resp data type: %s', $type));
            }
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $remove);
            switch ($type) {
                case self::TYPE_INTEGER:
                case self::TYPE_ARRAY:
                    $payload = (int) $payload;
                    break;
                case self::TYPE_ERROR:
                    $payload = new QueryException($payload);
                    break;
                default:
                    break;
            }
            if ($this->currentResponse !== null) {
                // extend array response
                if ($type === self::TYPE_ARRAY) {
                    if ($payload >= 0) {
                        $this->arraySizes[] = $this->currentSize;
                        $this->arrayStack[] =& $this->currentResponse;
                        $this->currentSize = $payload + 1;
                        $this->currentResponse[] = [];
                        $this->currentResponse =& $this->currentResponse[\sizeof($this->currentResponse) - 1];
                    } else {
                        $this->currentResponse[] = null;
                    }
                } else {
                    $this->currentResponse[] = $payload;
                }
                while (--$this->currentSize === 0) {
                    if (\count($this->arrayStack) === 0) {
                        $cb = $this->responseCallback;
                        $cb($this->currentResponse);
                        $this->currentResponse = null;
                        break;
                    }
                    // index doesn't start at 0 :(
                    \end($this->arrayStack);
                    $key = \key($this->arrayStack);
                    $this->currentResponse =& $this->arrayStack[$key];
                    $this->currentSize = \array_pop($this->arraySizes);
                    unset($this->arrayStack[$key]);
                }
            } elseif ($type === self::TYPE_ARRAY) {
                // start new array response
                if ($payload > 0) {
                    $this->currentSize = $payload;
                    $this->arrayStack = $this->arraySizes = $this->currentResponse = [];
                } elseif ($payload === 0) {
                    $cb = $this->responseCallback;
                    $cb([]);
                } else {
                    $cb = $this->responseCallback;
                    $cb(null);
                }
            } else {
                // single data type response
                $cb = $this->responseCallback;
                $cb($payload);
            }
        } while (isset($this->buffer[0]));
    }
}<?php

namespace Amp\Redis;

class SocketException extends RedisException
{
}<?php

namespace Amp\Redis;

class ParserException extends RedisException
{
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use function Amp\call;
final class Redis
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string[] */
    private $evalCache = [];
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor)
    {
        $this->queryExecutor = $queryExecutor;
    }
    /**
     *
     */
    public function getHyperLogLog(string $key) : RedisHyperLogLog
    {
        return new RedisHyperLogLog($this->queryExecutor, $key);
    }
    /**
     *
     */
    public function getList(string $key) : RedisList
    {
        return new RedisList($this->queryExecutor, $key);
    }
    /**
     *
     */
    public function getMap(string $key) : RedisMap
    {
        return new RedisMap($this->queryExecutor, $key);
    }
    /**
     *
     */
    public function getSet(string $key) : RedisSet
    {
        return new RedisSet($this->queryExecutor, $key);
    }
    /**
     *
     */
    public function getSortedSet(string $key) : RedisSortedSet
    {
        return new RedisSortedSet($this->queryExecutor, $key);
    }
    /**
     * @param string $arg
     * @param string ...$args
     *
     * @return Promise
     */
    public function query(string $arg, string ...$args) : Promise
    {
        return $this->queryExecutor->execute(\array_merge([$arg], $args));
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/del
     */
    public function delete(string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['del', $key], $keys));
    }
    /**
     * @param string $key
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/dump
     */
    public function dump(string $key) : Promise
    {
        return $this->queryExecutor->execute(['dump', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/exists
     */
    public function has(string $key) : Promise
    {
        return $this->queryExecutor->execute(['exists', $key], toBool);
    }
    /**
     * @param string $key
     * @param int $seconds
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/expire
     */
    public function expireIn(string $key, int $seconds) : Promise
    {
        return $this->queryExecutor->execute(['expire', $key, $seconds], toBool);
    }
    /**
     * @param string $key
     * @param int $millis
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/pexpire
     */
    public function expireInMillis(string $key, int $millis) : Promise
    {
        return $this->queryExecutor->execute(['pexpire', $key, $millis], toBool);
    }
    /**
     * @param string $key
     * @param int $timestamp
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/expireat
     */
    public function expireAt(string $key, int $timestamp) : Promise
    {
        return $this->queryExecutor->execute(['expireat', $key, $timestamp], toBool);
    }
    /**
     * @param string $key
     * @param int $timestamp
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/pexpireat
     */
    public function expireAtMillis(string $key, int $timestamp) : Promise
    {
        return $this->queryExecutor->execute(['pexpireat', $key, $timestamp], toBool);
    }
    /**
     * @param string $pattern
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/keys
     *
     * @see Redis::scan()
     */
    public function getKeys(string $pattern = '*') : Promise
    {
        return $this->queryExecutor->execute(['keys', $pattern]);
    }
    /**
     * @param string $key
     * @param int $db
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/move
     */
    public function move(string $key, int $db) : Promise
    {
        return $this->queryExecutor->execute(['move', $key, $db], toBool);
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/object
     */
    public function getObjectRefcount(string $key) : Promise
    {
        return $this->queryExecutor->execute(['object', 'refcount', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/object
     */
    public function getObjectEncoding(string $key) : Promise
    {
        return $this->queryExecutor->execute(['object', 'encoding', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/object
     */
    public function getObjectIdletime(string $key) : Promise
    {
        return $this->queryExecutor->execute(['object', 'idletime', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/persist
     */
    public function persist(string $key) : Promise
    {
        return $this->queryExecutor->execute(['persist', $key], toBool);
    }
    /**
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/randomkey
     */
    public function getRandomKey() : Promise
    {
        return $this->queryExecutor->execute(['randomkey']);
    }
    /**
     * @param string $key
     * @param string $newKey
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/rename
     */
    public function rename(string $key, string $newKey) : Promise
    {
        return $this->queryExecutor->execute(['rename', $key, $newKey], toNull);
    }
    /**
     * @param string $key
     * @param string $newKey
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/renamenx
     */
    public function renameWithoutOverwrite(string $key, string $newKey) : Promise
    {
        return $this->queryExecutor->execute(['renamenx', $key, $newKey], toNull);
    }
    /**
     * @param string $key
     * @param string $serializedValue
     * @param int $ttl
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/restore
     */
    public function restore(string $key, string $serializedValue, int $ttl = 0) : Promise
    {
        return $this->queryExecutor->execute(['restore', $key, $ttl, $serializedValue], toNull);
    }
    /**
     * @param string $pattern
     * @param int $count
     *
     * @return Iterator<string>
     *
     * @link https://redis.io/commands/scan
     */
    public function scan(?string $pattern = null, ?int $count = null) : Iterator
    {
        return new Producer(function (callable $emit) use($pattern, $count) {
            $cursor = 0;
            do {
                $query = ['SCAN', $cursor];
                if ($pattern !== null) {
                    $query[] = 'MATCH';
                    $query[] = $pattern;
                }
                if ($count !== null) {
                    $query[] = 'COUNT';
                    $query[] = $count;
                }
                [$cursor, $keys] = (yield $this->queryExecutor->execute($query));
                foreach ($keys as $key) {
                    (yield $emit($key));
                }
            } while ($cursor !== '0');
        });
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/ttl
     */
    public function getTtl(string $key) : Promise
    {
        return $this->queryExecutor->execute(['ttl', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/pttl
     */
    public function getTtlInMillis(string $key) : Promise
    {
        return $this->queryExecutor->execute(['pttl', $key]);
    }
    /**
     * @param string $key
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/type
     */
    public function getType(string $key) : Promise
    {
        return $this->queryExecutor->execute(['type', $key]);
    }
    /**
     * @param string $key
     * @param string $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/append
     */
    public function append(string $key, string $value) : Promise
    {
        return $this->queryExecutor->execute(['append', $key, $value]);
    }
    /**
     * @param string $key
     * @param (int | null) $start
     * @param (int | null) $end
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitcount
     */
    public function countBits(string $key, ?int $start = null, ?int $end = null) : Promise
    {
        $cmd = ['bitcount', $key];
        if (isset($start, $end)) {
            $cmd[] = $start;
            $cmd[] = $end;
        } elseif (isset($start) || isset($end)) {
            throw \Error('Start and end must both be set or unset in countBits(), got start = ' . $start . ' and end = ' . $end);
        }
        return $this->queryExecutor->execute($cmd);
    }
    /**
     * @param string $destination
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitop
     */
    public function storeBitwiseAnd(string $destination, string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['bitop', 'and', $destination, $key], $keys));
    }
    /**
     * @param string $destination
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitop
     */
    public function storeBitwiseOr(string $destination, string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['bitop', 'or', $destination, $key], $keys));
    }
    /**
     * @param string $destination
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitop
     */
    public function storeBitwiseXor(string $destination, string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['bitop', 'xor', $destination, $key], $keys));
    }
    /**
     * @param string $destination
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitop
     */
    public function storeBitwiseNot(string $destination, string $key) : Promise
    {
        return $this->queryExecutor->execute(['bitop', 'not', $destination, $key]);
    }
    /**
     * @param string $key
     * @param bool $bit
     * @param int $start
     * @param int $end
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/bitpos
     */
    public function getBitPosition(string $key, bool $bit, ?int $start = null, ?int $end = null) : Promise
    {
        $payload = ['bitpos', $key, $bit ? 1 : 0];
        if ($start !== null) {
            $payload[] = $start;
            if ($end !== null) {
                $payload[] = $end;
            }
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @param string $key
     * @param int $decrement
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/decrby
     */
    public function decrement(string $key, int $decrement = 1) : Promise
    {
        if ($decrement === 1) {
            return $this->queryExecutor->execute(['decr', $key]);
        }
        return $this->queryExecutor->execute(['decrby', $key, $decrement]);
    }
    /**
     * @param string $key
     *
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/get
     */
    public function get(string $key) : Promise
    {
        return $this->queryExecutor->execute(['get', $key]);
    }
    /**
     * @param string $key
     * @param int $offset
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/getbit
     */
    public function getBit(string $key, int $offset) : Promise
    {
        return $this->queryExecutor->execute(['getbit', $key, $offset], toBool);
    }
    /**
     * @param string $key
     * @param int $start
     * @param int $end
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/getrange
     */
    public function getRange(string $key, int $start = 0, int $end = -1) : Promise
    {
        return $this->queryExecutor->execute(['getrange', $key, $start, $end]);
    }
    /**
     * @param string $key
     * @param string $value
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/getset
     */
    public function getAndSet(string $key, string $value) : Promise
    {
        return $this->queryExecutor->execute(['getset', $key, $value]);
    }
    /**
     * @param string $key
     * @param int $increment
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/incrby
     */
    public function increment(string $key, int $increment = 1) : Promise
    {
        if ($increment === 1) {
            return $this->queryExecutor->execute(['incr', $key]);
        }
        return $this->queryExecutor->execute(['incrby', $key, $increment]);
    }
    /**
     * @param string $key
     * @param float $increment
     *
     * @return Promise<float>
     *
     * @link https://redis.io/commands/incrbyfloat
     */
    public function incrementByFloat(string $key, float $increment) : Promise
    {
        return $this->queryExecutor->execute(['incrbyfloat', $key, $increment], toFloat);
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<array<(string | null)>>
     *
     * @link https://redis.io/commands/mget
     */
    public function getMultiple(string $key, string ...$keys) : Promise
    {
        \array_unshift($keys, $key);
        $query = \array_merge(['mget'], $keys);
        return $this->queryExecutor->execute($query, static function ($response) use($keys) {
            return \array_combine($keys, $response);
        });
    }
    /**
     * @param array $data
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/mset
     */
    public function setMultiple(array $data) : Promise
    {
        $payload = ['mset'];
        foreach ($data as $key => $value) {
            $payload[] = $key;
            $payload[] = $value;
        }
        return $this->queryExecutor->execute($payload, toNull);
    }
    /**
     * @param array $data
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/msetnx
     */
    public function setMultipleWithoutOverwrite(array $data) : Promise
    {
        $payload = ['msetnx'];
        foreach ($data as $key => $value) {
            $payload[] = $key;
            $payload[] = $value;
        }
        return $this->queryExecutor->execute($payload, toNull);
    }
    /**
     * @param string $key
     * @param string $value
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/setnx
     */
    public function setWithoutOverwrite(string $key, string $value) : Promise
    {
        return $this->queryExecutor->execute(['setnx', $key, $value], toBool);
    }
    /**
     * @param string $key
     * @param string $value
     *
     * @return Promise<bool>
     */
    public function set(string $key, string $value, SetOptions $options = null) : Promise
    {
        $query = ['set', $key, $value];
        if ($options !== null) {
            $query = \array_merge($query, $options->toQuery());
        }
        return $this->queryExecutor->execute($query, toBool);
    }
    /**
     * @param string $key
     * @param int $offset
     * @param bool $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/setbit
     */
    public function setBit(string $key, int $offset, bool $value) : Promise
    {
        return $this->queryExecutor->execute(['setbit', $key, $offset, (int) $value]);
    }
    /**
     * @param string $key
     * @param int $offset
     * @param mixed $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/setrange
     */
    public function setRange(string $key, int $offset, string $value) : Promise
    {
        return $this->queryExecutor->execute(['setrange', $key, $offset, $value]);
    }
    /**
     * @param string $key
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/strlen
     */
    public function getLength(string $key) : Promise
    {
        return $this->queryExecutor->execute(['strlen', $key]);
    }
    /**
     * @param string $channel
     * @param string $message
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/publish
     */
    public function publish(string $channel, string $message) : Promise
    {
        return $this->queryExecutor->execute(['publish', $channel, $message]);
    }
    /**
     * @param string $pattern
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/pubsub
     */
    public function getActiveChannels(?string $pattern = null) : Promise
    {
        $payload = ['pubsub', 'channels'];
        if ($pattern !== null) {
            $payload[] = $pattern;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @param string ...$channels
     *
     * @return Promise<int[]>
     *
     * @link https://redis.io/commands/pubsub
     */
    public function getNumberOfSubscriptions(string ...$channels) : Promise
    {
        $query = \array_merge(['pubsub', 'numsub'], $channels);
        return $this->queryExecutor->execute($query, static function ($response) {
            $result = [];
            for ($i = 0, $count = \count($response); $i < $count; $i += 2) {
                $result[$response[$i]] = $response[$i + 1];
            }
            return $result;
        });
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/pubsub
     */
    public function getNumberOfPatternSubscriptions() : Promise
    {
        return $this->queryExecutor->execute(['pubsub', 'numpat']);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/ping
     */
    public function ping() : Promise
    {
        return $this->queryExecutor->execute(['ping'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/quit
     */
    public function quit() : Promise
    {
        return $this->queryExecutor->execute(['quit'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/bgrewriteaof
     */
    public function rewriteAofAsync() : Promise
    {
        return $this->queryExecutor->execute(['bgrewriteaof'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/bgsave
     */
    public function saveAsync() : Promise
    {
        return $this->queryExecutor->execute(['bgsave'], toNull);
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/client-getname
     */
    public function getName() : Promise
    {
        return $this->queryExecutor->execute(['client', 'getname']);
    }
    /**
     * @param int $timeInMillis
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/client-pause
     */
    public function pauseMillis(int $timeInMillis) : Promise
    {
        return $this->queryExecutor->execute(['client', 'pause', $timeInMillis], toNull);
    }
    /**
     * @param string $name
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/client-setname
     */
    public function setName(string $name) : Promise
    {
        return $this->queryExecutor->execute(['client', 'setname', $name], toNull);
    }
    /**
     * @param string $parameter
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/config-get
     */
    public function getConfig(string $parameter) : Promise
    {
        return $this->queryExecutor->execute(['config', 'get', $parameter]);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/config-resetstat
     */
    public function resetStatistics() : Promise
    {
        return $this->queryExecutor->execute(['config', 'resetstat'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/config-rewrite
     */
    public function rewriteConfig() : Promise
    {
        return $this->queryExecutor->execute(['config', 'rewrite'], toNull);
    }
    /**
     * @param string $parameter
     * @param string $value
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/config-set
     */
    public function setConfig(string $parameter, string $value) : Promise
    {
        return $this->queryExecutor->execute(['config', 'set', $parameter, $value], toNull);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/dbsize
     */
    public function getDatabaseSize() : Promise
    {
        return $this->queryExecutor->execute(['dbsize']);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/flushall
     */
    public function flushAll() : Promise
    {
        return $this->queryExecutor->execute(['flushall'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/flushdb
     */
    public function flushDatabase() : Promise
    {
        return $this->queryExecutor->execute(['flushdb'], toNull);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/lastsave
     */
    public function getLastSave() : Promise
    {
        return $this->queryExecutor->execute(['lastsave']);
    }
    /**
     * @return Promise<array>
     *
     * @link https://redis.io/commands/role
     */
    public function getRole() : Promise
    {
        return $this->queryExecutor->execute(['role']);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/save
     */
    public function save() : Promise
    {
        return $this->queryExecutor->execute(['save'], toNull);
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/shutdown
     */
    public function shutdownWithSave() : Promise
    {
        return $this->queryExecutor->execute(['shutdown', 'save']);
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/shutdown
     */
    public function shutdownWithoutSave() : Promise
    {
        return $this->queryExecutor->execute(['shutdown', 'nosave']);
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/shutdown
     */
    public function shutdown() : Promise
    {
        return $this->queryExecutor->execute(['shutdown']);
    }
    /**
     * @param string $host
     * @param int $port
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/slaveof
     */
    public function enableReplication(string $host, int $port) : Promise
    {
        return $this->queryExecutor->execute(['slaveof', $host, $port], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/slaveof
     */
    public function disableReplication() : Promise
    {
        return $this->queryExecutor->execute(['slaveof', 'no', 'one'], toNull);
    }
    /**
     * @param int $count
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/slowlog
     */
    public function getSlowlog(?int $count = null) : Promise
    {
        $payload = ['slowlog', 'get'];
        if ($count !== null) {
            $payload[] = $count;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/slowlog
     */
    public function getSlowlogLength() : Promise
    {
        return $this->queryExecutor->execute(['slowlog', 'len']);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/slowlog
     */
    public function resetSlowlog() : Promise
    {
        return $this->queryExecutor->execute(['slowlog', 'reset'], toNull);
    }
    /**
     * @return Promise<array>
     *
     * @link https://redis.io/commands/time
     */
    public function getTime() : Promise
    {
        return $this->queryExecutor->execute(['time']);
    }
    /**
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/script-exists
     */
    public function hasScript(string $sha1) : Promise
    {
        return $this->queryExecutor->execute(['script', 'exists', $sha1], static function (array $array) {
            return (bool) $array[0];
        });
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/script-flush
     */
    public function flushScripts() : Promise
    {
        $this->evalCache = [];
        // same as internal redis behavior
        return $this->queryExecutor->execute(['script', 'flush'], toNull);
    }
    /**
     * @return Promise<void>
     *
     * @link https://redis.io/commands/script-kill
     */
    public function killScript() : Promise
    {
        return $this->queryExecutor->execute(['script', 'kill'], toNull);
    }
    /**
     * @param string $script
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/script-load
     */
    public function loadScript(string $script) : Promise
    {
        return $this->queryExecutor->execute(['script', 'load', $script]);
    }
    /**
     * @param string $text
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/echo
     */
    public function echo(string $text) : Promise
    {
        return $this->queryExecutor->execute(['echo', $text]);
    }
    /**
     * @param string $script
     * @param string[] $keys
     * @param string[] $args
     *
     * @return Promise<mixed>
     *
     * @link https://redis.io/commands/eval
     */
    public function eval(string $script, array $keys = [], array $args = []) : Promise
    {
        return call(function () use($script, $keys, $args) {
            try {
                $sha1 = $this->evalCache[$script] ?? ($this->evalCache[$script] = \sha1($script));
                $query = \array_merge(['evalsha', $sha1, \count($keys)], $keys, $args);
                return (yield $this->queryExecutor->execute($query));
            } catch (QueryException $e) {
                if (\strtok($e->getMessage(), ' ') === 'NOSCRIPT') {
                    $query = \array_merge(['eval', $script, \count($keys)], $keys, $args);
                    return $this->queryExecutor->execute($query);
                }
                throw $e;
            }
        });
    }
    /**
     *
     */
    public function select(int $database) : Promise
    {
        return $this->queryExecutor->execute(['select', $database], toNull);
    }
}<?php

namespace Amp\Redis;

use Amp\Iterator;
use Amp\Promise;
final class Subscription implements Iterator
{
    private $iterator;
    private $unsubscribeCallback;
    /**
     *
     */
    public function __construct(Iterator $iterator, callable $unsubscribeCallback)
    {
        $this->iterator = $iterator;
        $this->unsubscribeCallback = $unsubscribeCallback;
    }
    /**
     * @inheritdoc
     */
    public function advance() : Promise
    {
        return $this->iterator->advance();
    }
    /**
     * @inheritdoc
     */
    public function getCurrent()
    {
        return $this->iterator->getCurrent();
    }
    /**
     *
     */
    public function cancel() : void
    {
        ($this->unsubscribeCallback)();
    }
}<?php

namespace Amp\Redis\Mutex;

class ConnectionLimitException extends MutexException
{
}<?php

namespace Amp\Redis\Mutex;

class LockException extends MutexException
{
}<?php

namespace Amp\Redis\Mutex;

final class MutexOptions
{
    private $keyPrefix = '';
    private $lockRenewInterval = 1000;
    private $lockExpiration = 3000;
    private $lockTimeout = 10000;
    /**
     *
     */
    public function getKeyPrefix() : string
    {
        return $this->keyPrefix;
    }
    /**
     *
     */
    public function getLockExpiration() : int
    {
        return $this->lockExpiration;
    }
    /**
     *
     */
    public function getLockRenewInterval() : int
    {
        return $this->lockRenewInterval;
    }
    /**
     *
     */
    public function getLockTimeout() : int
    {
        return $this->lockTimeout;
    }
    /**
     *
     */
    public function withKeyPrefix(string $keyPrefix) : self
    {
        $clone = clone $this;
        $clone->keyPrefix = $keyPrefix;
        return $clone;
    }
    /**
     *
     */
    public function withLockExpiration(int $lockExpiration) : self
    {
        $clone = clone $this;
        $clone->lockExpiration = $lockExpiration;
        return $clone;
    }
    /**
     *
     */
    public function withLockRenewInterval(int $lockRenewInterval) : self
    {
        $clone = clone $this;
        $clone->lockRenewInterval = $lockRenewInterval;
        return $clone;
    }
    /**
     *
     */
    public function withLockTimeout(int $lockTimeout) : self
    {
        $clone = clone $this;
        $clone->lockTimeout = $lockTimeout;
        return $clone;
    }
}<?php

namespace Amp\Redis\Mutex;

use Amp\Redis\RedisException;
class MutexException extends RedisException
{
}<?php

namespace Amp\Redis\Mutex;

use Amp\Loop;
use Amp\Promise;
use Amp\Redis\QueryExecutorFactory;
use Amp\Redis\Redis;
use Amp\Redis\RedisException;
use Amp\Sync\KeyedMutex;
use Amp\Sync\Lock;
use Psr\Log\LoggerInterface as PsrLogger;
use Psr\Log\NullLogger;
use function Amp\call;
use function Amp\delay;
/**
 * Mutex can be used to create locks for mutual exclusion in distributed clients.
 *
 * @author Niklas Keller <me@kelunik.com>
 */
final class Mutex implements KeyedMutex
{
    private const LOCK = <<<LOCK
local lock = KEYS[1]
local queue = KEYS[2]

local token = ARGV[1]
local ttl = ARGV[2]
local queueTtl = ARGV[3]

if redis.call("exists", lock) == 0 then
    if redis.call("llen", queue) == 0 then
        redis.call("set", lock, token, "px", ttl)
        return 1
    else
        local queued_tokens = redis.call("lrange", queue, 0, -1)
        local push = 1
        local position = 0
        
        for i=1,#queued_tokens do
            if queued_tokens[i] == token then
                push = 0
                position = i
                break
            end
        end

        if push == 1 then
            redis.call("rpush", queue, token)
        end

        local queued = redis.call("lpop", queue)
        redis.call("set", lock, queued, "px", ttl)
        if queued == token then
            return 2
        else
            redis.call("pexpire", queue, queueTtl)

            return -1 - position
        end
    end
else
    if redis.call("get", lock) == token then
        redis.call("set", lock, token, "px", ttl)
        return 1
    end

    local queued_tokens = redis.call("lrange", queue, 0, -1)
    for i=1,#queued_tokens do
        if queued_tokens[i] == token then
            redis.call("pexpire", queue, queueTtl)

            return -1 - i
        end
    end

    redis.call("rpush", queue, token)
    redis.call("pexpire", queue, queueTtl)

    return -1 - redis.call("llen", queue)
end
LOCK;
    private const UNLOCK = <<<UNLOCK
local lock = KEYS[1]
local token = ARGV[1]

if redis.call("get", lock) == token then
    redis.call("del", lock)
    return 1
else
    return 2
end
UNLOCK;
    private const RENEW = <<<RENEW
for i=1,#KEYS do
    if redis.call("get", KEYS[i]) == ARGV[i + 1] then
        redis.call("pexpire", KEYS[i], ARGV[1])
    end
end
RENEW;
    /** @var MutexOptions */
    private $options;
    /** @var Redis */
    private $sharedConnection;
    /** @var array[] */
    private $locks;
    /** @var string */
    private $watcher;
    /** @var PsrLogger */
    private $logger;
    private $numberOfLocks = 0;
    private $numberOfAttempts = 0;
    /**
     * Constructs a new Mutex instance. A single instance can be used to create as many locks as you need.
     *
     * @param QueryExecutorFactory $queryExecutorFactory
     * @param (MutexOptions | null) $options
     */
    public function __construct(QueryExecutorFactory $queryExecutorFactory, ?MutexOptions $options = null, ?PsrLogger $logger = null)
    {
        $this->options = $options ?? new MutexOptions();
        $this->sharedConnection = new Redis($queryExecutorFactory->createQueryExecutor());
        $this->logger = $logger ?? new NullLogger();
    }
    /**
     *
     */
    public function __destruct()
    {
        if (isset($this->watcher)) {
            Loop::cancel($this->watcher);
        }
    }
    /**
    * Acquires a lock.
    *
    * If directly acquiring a lock fails, the client is placed in a queue and reattempts to lock the key. If a client
    crashes or doesn't free the lock while not renewing it, the lock will expire and the next client in the queue
    will be able to acquire it.
    *
    * @param string $key Lock key.
    *
    * @return Promise<Lock> Resolves to an instance of `Lock`.
    */
    public function acquire(string $key) : Promise
    {
        return call(function () use($key) {
            $this->numberOfLocks++;
            $token = \base64_encode(\random_bytes(16));
            $prefix = $this->options->getKeyPrefix();
            $timeLimit = \microtime(true) * 1000 + $this->options->getLockTimeout();
            $attempts = 0;
            do {
                $attempts++;
                $this->numberOfAttempts++;
                $result = (yield $this->sharedConnection->eval(self::LOCK, ["{$prefix}lock:{$key}", "{$prefix}lock-queue:{$key}"], [$token, $this->options->getLockExpiration(), $this->options->getLockExpiration() + $this->options->getLockTimeout()]));
                if ($result < 1) {
                    if ($attempts > 2 && \microtime(true) * 1000 > $timeLimit) {
                        // In very rare cases we might not get the lock, but are at the head of the queue and another
                        // client moves us into the lock position. Deleting the token from the queue and afterwards
                        // unlocking solves this. No yield required, because we use the same connection.
                        $this->sharedConnection->getList("{$prefix}lock-queue:{$key}")->remove($token);
                        Promise\rethrow($this->unlock($key, $token));
                        throw new LockException('Failed to acquire lock for ' . $key . ' within ' . $this->options->getLockTimeout() . ' ms');
                    }
                    // A negative integer as reply means we're still in the queue and indicates the queue position.
                    // Making the timing dependent on the queue position greatly reduces CPU usage and locking attempts.
                    (yield delay(5 + \min((-$result - 1) * 10, 300)));
                }
            } while ($result < 1);
            if (empty($this->locks)) {
                $this->createRenewWatcher();
            }
            $this->locks[$key . ' @ ' . $token] = [$key, $token];
            return new Lock(0, function () use($key, $token) {
                Promise\rethrow($this->unlock($key, $token));
            });
        });
    }
    /**
     *
     */
    public function getNumberOfAttempts() : int
    {
        return $this->numberOfAttempts;
    }
    /**
     *
     */
    public function getNumberOfLocks() : int
    {
        return $this->numberOfLocks;
    }
    /**
     *
     */
    public function resetStatistics() : void
    {
        $this->numberOfAttempts = 0;
        $this->numberOfLocks = 0;
    }
    /**
     * Unlocks a previously acquired lock.
     *
     * @param string $key Lock key.
     * @param string $token Unique token generated during {@link lock()}.
     *
     * @return Promise Fails if lock couldn't be unlocked, otherwise resolves normally.
     */
    private function unlock(string $key, string $token) : Promise
    {
        return call(function () use($key, $token) {
            // Unset before unlocking, as we don't want to renew the lock anymore
            // If something goes wrong, the lock will simply expire
            unset($this->locks[$key . ' @ ' . $token]);
            if (empty($this->locks) && $this->watcher !== null) {
                Loop::cancel($this->watcher);
                $this->watcher = null;
            }
            $prefix = $this->options->getKeyPrefix();
            for ($attempt = 0; $attempt < 2; $attempt++) {
                try {
                    $result = (yield $this->sharedConnection->eval(self::UNLOCK, ["{$prefix}lock:{$key}"], [$token]));
                    if ($result === 2) {
                        $this->logger->warning('Lock was already expired when unlocked', ['key' => $key]);
                    }
                    break;
                } catch (RedisException $e) {
                    $this->logger->error('Unlock operation failed on attempt ' . ($attempt + 1), ['exception' => $e]);
                }
            }
        });
    }
    /**
     *
     */
    private function createRenewWatcher() : void
    {
        $this->watcher = Loop::repeat($this->options->getLockRenewInterval(), function () {
            \assert(!empty($this->locks));
            $keys = [];
            $arguments = [$this->options->getLockExpiration()];
            $prefix = $this->options->getKeyPrefix();
            foreach ($this->locks as [$key, $token]) {
                $keys[] = "{$prefix}lock:{$key}";
                $arguments[] = $token;
            }
            try {
                (yield $this->sharedConnection->eval(self::RENEW, $keys, $arguments));
            } catch (RedisException $e) {
                $this->logger->error('Renew operation failed, locks might expire', ['exception' => $e]);
            }
        });
    }
}<?php

namespace Amp\Redis;

class QueryException extends RedisException
{
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
final class RedisSet
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param string $member
     * @param string ...$members
     *
     * @return Promise<int>
     */
    public function add(string $member, string ...$members) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sadd', $this->key, $member], $members));
    }
    /**
     * @return Promise<int>
     */
    public function getSize() : Promise
    {
        return $this->queryExecutor->execute(['scard', $this->key]);
    }
    /**
     * @param string ...$keys
     *
     * @return Promise<array>
     */
    public function diff(string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sdiff', $this->key], $keys));
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     */
    public function storeDiff(string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sdiffstore', $this->key, $key], $keys));
    }
    /**
     * @param string ...$keys
     *
     * @return Promise<array>
     */
    public function intersect(string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sinter', $this->key], $keys));
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     */
    public function storeIntersection(string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sinterstore', $this->key, $key], $keys));
    }
    /**
     * @param string $member
     *
     * @return Promise<bool>
     */
    public function contains(string $member) : Promise
    {
        return $this->queryExecutor->execute(['sismember', $this->key, $member], toBool);
    }
    /**
     * @return Promise<array>
     */
    public function getAll() : Promise
    {
        return $this->queryExecutor->execute(['smembers', $this->key]);
    }
    /**
     * @param string $member
     * @param string $destination
     *
     * @return Promise<bool>
     */
    public function move(string $member, string $destination) : Promise
    {
        return $this->queryExecutor->execute(['smove', $this->key, $destination, $member], toBool);
    }
    /**
     * @return Promise<string>
     */
    public function popRandomMember() : Promise
    {
        return $this->queryExecutor->execute(['spop', $this->key]);
    }
    /**
     * @return Promise<(string | null)>
     */
    public function getRandomMember() : Promise
    {
        return $this->queryExecutor->execute(['srandmember', $this->key]);
    }
    /**
     * @param int $count
     *
     * @return Promise<string[]>
     */
    public function getRandomMembers(int $count) : Promise
    {
        return $this->queryExecutor->execute(['srandmember', $this->key, $count]);
    }
    /**
     * @param string $member
     * @param string ...$members
     *
     * @return Promise<int>
     */
    public function remove(string $member, string ...$members) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['srem', $this->key, $member], $members));
    }
    /**
     * @param string ...$keys
     *
     * @return Promise<array>
     */
    public function union(string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sunion', $this->key], $keys));
    }
    /**
     * @param string $key
     * @param string ...$keys
     *
     * @return Promise<int>
     */
    public function storeUnion(string $key, string ...$keys) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['sunionstore', $this->key, $key], $keys));
    }
    /**
     * @param string $pattern
     * @param int $count
     *
     * @return Iterator
     */
    public function scan(?string $pattern = null, ?int $count = null) : Iterator
    {
        return new Producer(function (callable $emit) use($pattern, $count) {
            $cursor = 0;
            do {
                $query = ['SSCAN', $this->key, $cursor];
                if ($pattern !== null) {
                    $query[] = 'MATCH';
                    $query[] = $pattern;
                }
                if ($count !== null) {
                    $query[] = 'COUNT';
                    $query[] = $count;
                }
                [$cursor, $keys] = (yield $this->queryExecutor->execute($query));
                foreach ($keys as $key) {
                    (yield $emit($key));
                }
            } while ($cursor !== '0');
        });
    }
    /**
     * @param SortOptions $sort
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/sort
     */
    public function sort(?SortOptions $sort = null) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['SORT', $this->key], ($sort ?? new SortOptions())->toQuery()));
    }
}<?php

namespace Amp\Redis;

use Amp\Emitter;
use Amp\Promise;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\delay;
final class Subscriber
{
    /** @var Config */
    private $config;
    /** @var Promise|null */
    private $connect;
    /** @var Emitter[][] */
    private $emitters = [];
    /** @var Emitter[][] */
    private $patternEmitters = [];
    /**
     *
     */
    public function __construct(Config $config)
    {
        $this->config = $config;
    }
    /**
     * @param string $channel
     *
     * @return Promise<Subscription>
     */
    public function subscribe(string $channel) : Promise
    {
        return call(function () use($channel) {
            $emitter = new Emitter();
            $this->emitters[$channel][\spl_object_hash($emitter)] = $emitter;
            try {
                /** @var RespSocket $resp */
                $resp = (yield $this->connect());
                $resp->reference();
                (yield $resp->write('subscribe', $channel));
            } catch (\Throwable $e) {
                $this->unloadEmitter($emitter, $channel);
                throw $e;
            }
            return new Subscription($emitter->iterate(), function () use($emitter, $channel) {
                $this->unloadEmitter($emitter, $channel);
            });
        });
    }
    /**
     * @param string $pattern
     *
     * @return Promise<Subscription>
     */
    public function subscribeToPattern(string $pattern) : Promise
    {
        return call(function () use($pattern) {
            $emitter = new Emitter();
            $this->patternEmitters[$pattern][\spl_object_hash($emitter)] = $emitter;
            try {
                /** @var RespSocket $resp */
                $resp = (yield $this->connect());
                $resp->reference();
                (yield $resp->write('psubscribe', $pattern));
            } catch (\Throwable $e) {
                $this->unloadPatternEmitter($emitter, $pattern);
                throw $e;
            }
            return new Subscription($emitter->iterate(), function () use($emitter, $pattern) {
                $this->unloadPatternEmitter($emitter, $pattern);
            });
        });
    }
    /**
     *
     */
    private function connect() : Promise
    {
        if ($this->connect) {
            return $this->connect;
        }
        return $this->connect = call(function () {
            try {
                /** @var RespSocket $resp */
                $resp = (yield connect($this->config));
            } catch (\Throwable $connectException) {
                (yield delay(0));
                // ensure $this->connect is already assigned above in case of immediate failure
                $this->connect = null;
                throw $connectException;
            }
            asyncCall(function () use($resp) {
                try {
                    while ([$response] = (yield $resp->read())) {
                        switch ($response[0]) {
                            case 'message':
                                $backpressure = [];
                                foreach ($this->emitters[$response[1]] as $emitter) {
                                    $backpressure[] = $emitter->emit($response[2]);
                                }
                                (yield Promise\any($backpressure));
                                break;
                            case 'pmessage':
                                $backpressure = [];
                                foreach ($this->patternEmitters[$response[1]] as $emitter) {
                                    $backpressure[] = $emitter->emit([$response[3], $response[2]]);
                                }
                                (yield Promise\any($backpressure));
                                break;
                        }
                    }
                    throw new SocketException('Socket to redis instance (' . $this->config->getConnectUri() . ') closed unexpectedly');
                } catch (\Throwable $error) {
                    $emitters = \array_merge($this->emitters, $this->patternEmitters);
                    $this->connect = null;
                    $this->emitters = [];
                    $this->patternEmitters = [];
                    foreach ($emitters as $emitterGroup) {
                        foreach ($emitterGroup as $emitter) {
                            $emitter->fail($error);
                        }
                    }
                    throw $error;
                }
            });
            return $resp;
        });
    }
    /**
     *
     */
    private function isIdle() : bool
    {
        return !$this->emitters && !$this->patternEmitters;
    }
    /**
     *
     */
    private function unloadEmitter(Emitter $emitter, string $channel) : void
    {
        $hash = \spl_object_hash($emitter);
        if (isset($this->emitters[$channel][$hash])) {
            unset($this->emitters[$channel][$hash]);
            $emitter->complete();
            if (empty($this->emitters[$channel])) {
                unset($this->emitters[$channel]);
                asyncCall(function () use($channel) {
                    try {
                        /** @var RespSocket $resp */
                        $resp = (yield $this->connect());
                        if (empty($this->emitters[$channel])) {
                            $resp->reference();
                            (yield $resp->write('unsubscribe', $channel));
                        }
                        if ($this->isIdle()) {
                            $resp->unreference();
                        }
                    } catch (RedisException $exception) {
                        // if there's an exception, the unsubscribe is implicitly successful, because the connection broke
                    }
                });
            }
        }
    }
    /**
     *
     */
    private function unloadPatternEmitter(Emitter $emitter, string $pattern) : void
    {
        $hash = \spl_object_hash($emitter);
        if (isset($this->patternEmitters[$pattern][$hash])) {
            unset($this->patternEmitters[$pattern][$hash]);
            $emitter->complete();
            if (empty($this->patternEmitters[$pattern])) {
                unset($this->patternEmitters[$pattern]);
                asyncCall(function () use($pattern) {
                    try {
                        /** @var RespSocket $resp */
                        $resp = (yield $this->connect());
                        if (empty($this->patternEmitters[$pattern])) {
                            $resp->reference();
                            (yield $resp->write('punsubscribe', $pattern));
                        }
                        if ($this->isIdle()) {
                            $resp->unreference();
                        }
                    } catch (RedisException $exception) {
                        // if there's an exception, the unsubscribe is implicitly successful, because the connection broke
                    }
                });
            }
        }
    }
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
final class RedisMap
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param string $field
     * @param string ...$fields
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/hdel
     */
    public function remove(string $field, string ...$fields) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['hdel', $this->key, $field], $fields));
    }
    /**
     * @param string $field
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/hexists
     */
    public function hasKey(string $field) : Promise
    {
        return $this->queryExecutor->execute(['hexists', $this->key, $field], toBool);
    }
    /**
     * @param string $field
     * @param int $increment
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/hincrby
     */
    public function increment(string $field, int $increment = 1) : Promise
    {
        return $this->queryExecutor->execute(['hincrby', $this->key, $field, $increment]);
    }
    /**
     * @param string $field
     * @param float $increment
     *
     * @return Promise<float>
     *
     * @link https://redis.io/commands/hincrbyfloat
     */
    public function incrementByFloat(string $field, float $increment) : Promise
    {
        return $this->queryExecutor->execute(['hincrbyfloat', $this->key, $field, $increment], toFloat);
    }
    /**
     * @return Promise<array>
     *
     * @link https://redis.io/commands/hkeys
     */
    public function getKeys() : Promise
    {
        return $this->queryExecutor->execute(['hkeys', $this->key]);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/hlen
     */
    public function getSize() : Promise
    {
        return $this->queryExecutor->execute(['hlen', $this->key]);
    }
    /**
     * @return Promise<array>
     *
     * @link https://redis.io/commands/hvals
     * @link https://redis.io/commands/hgetall
     */
    public function getAll() : Promise
    {
        return $this->queryExecutor->execute(['hgetall', $this->key], toMap);
    }
    /**
     * @param array $data
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/hmset
     */
    public function setValues(array $data) : Promise
    {
        $array = ['hmset', $this->key];
        foreach ($data as $dataKey => $value) {
            $array[] = $dataKey;
            $array[] = $value;
        }
        return $this->queryExecutor->execute($array, toNull);
    }
    /**
     * @param string $field
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/hget
     */
    public function getValue(string $field) : Promise
    {
        return $this->queryExecutor->execute(['hget', $this->key, $field]);
    }
    /**
     * @param string $field
     * @param string ...$fields
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/hmget
     */
    public function getValues(string $field, string ...$fields) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['hmget', $this->key, $field], $fields));
    }
    /**
     * @param string $field
     * @param string $value
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/hset
     */
    public function setValue(string $field, string $value) : Promise
    {
        return $this->queryExecutor->execute(['hset', $this->key, $field, $value], toBool);
    }
    /**
     * @param string $field
     * @param string $value
     *
     * @return Promise<bool>
     *
     * @link https://redis.io/commands/hsetnx
     */
    public function setValueWithoutOverwrite(string $field, string $value) : Promise
    {
        return $this->queryExecutor->execute(['hsetnx', $this->key, $field, $value], toBool);
    }
    /**
     * @param string $field
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/hstrlen
     */
    public function getLength(string $field) : Promise
    {
        return $this->queryExecutor->execute(['hstrlen', $this->key, $field]);
    }
    /**
     * @param (string | null) $pattern
     * @param (int | null) $count
     *
     * @return Iterator<string>
     *
     * @link https://redis.io/commands/hscan
     */
    public function scan(?string $pattern = null, ?int $count = null) : Iterator
    {
        return new Producer(function (callable $emit) use($pattern, $count) {
            $cursor = 0;
            do {
                $query = ['HSCAN', $this->key, $cursor];
                if ($pattern !== null) {
                    $query[] = 'MATCH';
                    $query[] = $pattern;
                }
                if ($count !== null) {
                    $query[] = 'COUNT';
                    $query[] = $count;
                }
                [$cursor, $keys] = (yield $this->queryExecutor->execute($query));
                $count = \count($keys);
                \assert($count % 2 === 0);
                for ($i = 0; $i < $count; $i += 2) {
                    (yield $emit([$keys[$i], $keys[$i + 1]]));
                }
            } while ($cursor !== '0');
        });
    }
}<?php

namespace Amp\Redis;

use function League\Uri\parse;
final class Config
{
    public const DEFAULT_HOST = 'localhost';
    public const DEFAULT_PORT = '6379';
    /**
     * @param string $uri
     *
     * @return self
     *
     * @throws RedisException
     */
    public static function fromUri(string $uri) : self
    {
        if (\stripos($uri, 'tcp://') !== 0 && \stripos($uri, 'unix://') !== 0 && \stripos($uri, 'redis://') !== 0) {
            throw new RedisException('Invalid redis configuration URI, must start with tcp://, unix:// or redis://');
        }
        return new self($uri);
    }
    /** @var string */
    private $uri;
    /** @var string */
    private $password = '';
    /** @var int */
    private $database = 0;
    /** @var int */
    private $timeout = 5000;
    /**
     * @param string $uri
     *
     * @throws RedisException
     */
    private function __construct(string $uri)
    {
        $this->applyUri($uri);
    }
    /**
     *
     */
    public function getConnectUri() : string
    {
        return $this->uri;
    }
    /**
     *
     */
    public function getTimeout() : int
    {
        return $this->timeout;
    }
    /**
     *
     */
    public function getPassword() : string
    {
        return $this->password;
    }
    /**
     *
     */
    public function hasPassword() : bool
    {
        return $this->password !== '';
    }
    /**
     *
     */
    public function getDatabase() : int
    {
        return $this->database;
    }
    /**
     *
     */
    public function withTimeout(int $timeout) : self
    {
        $clone = clone $this;
        $clone->timeout = $timeout;
        return $clone;
    }
    /**
     *
     */
    public function withPassword(string $password) : self
    {
        $clone = clone $this;
        $clone->password = $password;
        return $clone;
    }
    /**
     *
     */
    public function withDatabase(int $database) : self
    {
        $clone = clone $this;
        $clone->database = $database;
        return $clone;
    }
    /**
    * When using the "redis" schemes the URI is parsed according to the rules defined by the provisional registration
    documents approved by IANA. If the URI has a password in its "user-information" part or a database number in the
    "path" part these values override the values of "password" / "database" if they are present in the "query" part.
    *
    * @link http://www.iana.org/assignments/uri-schemes/prov/redis
    *
    * @param string $uri URI string.
    *
    * @throws RedisException
    */
    private function applyUri(string $uri) : void
    {
        if ($uri === 'redis://') {
            $uri = 'redis://' . self::DEFAULT_HOST . ':' . self::DEFAULT_PORT;
        }
        try {
            $parsedUri = parse($uri);
        } catch (\Exception $exception) {
            throw new RedisException('Invalid redis configuration URI: ' . $uri);
        }
        \parse_str($parsedUri['query'] ?? '', $query);
        switch (\strtolower($parsedUri['scheme'])) {
            case 'tcp':
                $this->uri = 'tcp://' . \strtolower($parsedUri['host']) . ':' . (int) $parsedUri['port'];
                $this->database = (int) ($query['database'] ?? $query['db'] ?? 0);
                $this->password = $query['password'] ?? $query['pass'] ?? '';
                break;
            case 'unix':
                $this->uri = 'unix://' . $parsedUri['path'];
                $this->database = (int) ($query['database'] ?? $query['db'] ?? 0);
                $this->password = $query['password'] ?? $query['pass'] ?? '';
                break;
            case 'redis':
                $host = \strtolower($parsedUri['host'] ?? self::DEFAULT_HOST);
                $port = (int) ($parsedUri['port'] ?? self::DEFAULT_PORT);
                if ($host === '') {
                    $host = self::DEFAULT_HOST;
                }
                if ($port === 0) {
                    $port = self::DEFAULT_PORT;
                }
                $this->uri = 'tcp://' . $host . ':' . $port;
                if (\ltrim($parsedUri['path'], '/') !== '') {
                    $this->database = (int) \ltrim($parsedUri['path'], '/');
                } else {
                    $this->database = (int) ($query['db'] ?? 0);
                }
                if (isset($parsedUri['pass']) && $parsedUri['pass'] !== '') {
                    $this->password = $parsedUri['pass'];
                } else {
                    $this->password = $query['password'] ?? '';
                }
                break;
        }
        $this->timeout = (int) ($query['timeout'] ?? $this->timeout);
    }
}<?php

namespace Amp\Redis;

use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Promise;
use Amp\Socket;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\delay;
final class RemoteExecutor implements QueryExecutor
{
    /** @var Deferred[] */
    private $queue = [];
    /** @var Config */
    private $config;
    /** @var int */
    private $database;
    /** @var Promise|null */
    private $connect;
    /** @var Socket\Connector */
    private $connector;
    /**
     *
     */
    public function __construct(Config $config, ?Socket\Connector $connector = null)
    {
        $this->config = $config;
        $this->database = $config->getDatabase();
        $this->connector = $connector ?? Socket\connector();
    }
    /**
     * @param string[] $args
     * @param callable $transform
     *
     * @return Promise
     */
    public function execute(array $args, callable $transform = null) : Promise
    {
        return call(function () use($args, $transform) {
            $command = \strtolower($args[0] ?? '');
            $connectPromise = $this->connect();
            if ($command === 'quit') {
                $this->connect = null;
            }
            /** @var RespSocket $resp */
            $resp = (yield $connectPromise);
            $response = (yield $this->enqueue($resp, ...$args));
            if ($command === 'select') {
                $this->database = (int) $args[1];
            }
            return $transform ? $transform($response) : $response;
        });
    }
    /**
     *
     */
    private function enqueue(RespSocket $resp, string ...$args) : Promise
    {
        return call(function () use($resp, $args) {
            $deferred = new Deferred();
            $this->queue[] = $deferred;
            $resp->reference();
            try {
                (yield $resp->write(...$args));
            } catch (Socket\SocketException|StreamException $exception) {
                throw new SocketException($exception);
            }
            return $deferred->promise();
        });
    }
    /**
     *
     */
    private function connect() : Promise
    {
        if ($this->connect) {
            return $this->connect;
        }
        return $this->connect = call(function () {
            try {
                /** @var RespSocket $resp */
                $resp = (yield connect($this->config->withDatabase($this->database), $this->connector));
            } catch (\Throwable $connectException) {
                (yield delay(0));
                // ensure $this->connect is already assigned above in case of immediate failure
                $this->connect = null;
                throw $connectException;
            }
            asyncCall(function () use($resp) {
                try {
                    while ([$response] = (yield $resp->read())) {
                        $deferred = \array_shift($this->queue);
                        if (!$this->queue) {
                            $resp->unreference();
                        }
                        if ($response instanceof \Throwable) {
                            $deferred->fail($response);
                        } else {
                            $deferred->resolve($response);
                        }
                    }
                    throw new SocketException('Socket to redis instance (' . $this->config->getConnectUri() . ') closed unexpectedly');
                } catch (\Throwable $error) {
                    $queue = $this->queue;
                    $this->queue = [];
                    $this->connect = null;
                    while ($queue) {
                        $deferred = \array_shift($queue);
                        $deferred->fail($error);
                    }
                }
            });
            return $resp;
        });
    }
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
final class RedisSortedSet
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param array $data
     *
     * @return Promise<int>
     */
    public function add(array $data) : Promise
    {
        $payload = ['zadd', $this->key];
        foreach ($data as $member => $score) {
            $payload[] = $score;
            $payload[] = $member;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @return Promise<int>
     */
    public function getSize() : Promise
    {
        return $this->queryExecutor->execute(['zcard', $this->key]);
    }
    /**
     * @param int $min
     * @param int $max
     *
     * @return Promise<int>
     */
    public function count(int $min, int $max) : Promise
    {
        return $this->queryExecutor->execute(['zcount', $this->key, $min, $max]);
    }
    /**
     * @param string $member
     * @param float $increment
     *
     * @return Promise<float>
     */
    public function increment(string $member, float $increment = 1) : Promise
    {
        return $this->queryExecutor->execute(['zincrby', $this->key, $increment, $member], toFloat);
    }
    /**
     * @param string[] $keys
     * @param string $aggregate
     *
     * @return Promise<int>
     */
    public function storeIntersection(array $keys, string $aggregate = 'sum') : Promise
    {
        $payload = ['zinterstore', $this->key, \count($keys)];
        $weights = [];
        if (\count(\array_filter(\array_keys($keys), 'is_string'))) {
            foreach ($keys as $key => $weight) {
                $payload[] = $key;
                $weights[] = $weight;
            }
        } else {
            foreach ($keys as $key) {
                $payload[] = $key;
            }
        }
        if (\count($weights) > 0) {
            $payload[] = 'WEIGHTS';
            foreach ($weights as $weight) {
                $payload[] = $weight;
            }
        }
        if (\strtolower($aggregate) !== 'sum') {
            $payload[] = 'AGGREGATE';
            $payload[] = $aggregate;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @param string $min
     * @param string $max
     *
     * @return Promise<int>
     */
    public function countLexicographically(string $min, string $max) : Promise
    {
        return $this->queryExecutor->execute(['zlexcount', $this->key, $min, $max]);
    }
    /**
     * @param string $member
     *
     * @return Promise<(int | null)>
     */
    public function getRank(string $member) : Promise
    {
        return $this->queryExecutor->execute(['zrank', $this->key, $member]);
    }
    /**
     * @param string $member
     * @param string ...$members
     *
     * @return Promise<int>
     */
    public function remove(string $member, string ...$members) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['zrem', $this->key, $member], $members));
    }
    /**
     * @param string $min
     * @param string $max
     *
     * @return Promise<int>
     */
    public function removeLexicographicRange(string $min, string $max) : Promise
    {
        return $this->queryExecutor->execute(['zremrangebylex', $this->key, $min, $max]);
    }
    /**
     * @param int $start
     * @param int $stop
     *
     * @return Promise<int>
     */
    public function removeRankRange(int $start, int $stop) : Promise
    {
        return $this->queryExecutor->execute(['zremrangebyrank', $this->key, $start, $stop]);
    }
    /**
     * @param float $min
     * @param float $max
     *
     * @return Promise<int>
     */
    public function removeScoreRange(float $min, float $max) : Promise
    {
        return $this->queryExecutor->execute(['zremrangebyscore', $this->key, $min, $max]);
    }
    /**
     * @param string $member
     *
     * @return Promise<(int | null)>
     */
    public function getReversedRank(string $member) : Promise
    {
        return $this->queryExecutor->execute(['zrevrank', $this->key, $member]);
    }
    /**
     * @param (string | null) $pattern
     * @param (int | null) $count
     *
     * @return Iterator<string>
     */
    public function scan(?string $pattern = null, ?int $count = null) : Iterator
    {
        return new Producer(function (callable $emit) use($pattern, $count) {
            $cursor = 0;
            do {
                $query = ['ZSCAN', $this->key, $cursor];
                if ($pattern !== null) {
                    $query[] = 'MATCH';
                    $query[] = $pattern;
                }
                if ($count !== null) {
                    $query[] = 'COUNT';
                    $query[] = $count;
                }
                [$cursor, $keys] = (yield $this->queryExecutor->execute($query));
                $count = \count($keys);
                \assert($count % 2 === 0);
                for ($i = 0; $i < $count; $i += 2) {
                    (yield $emit([$keys[$i], (float) $keys[$i + 1]]));
                }
            } while ($cursor !== '0');
        });
    }
    /**
     * @param string $member
     *
     * @return Promise<(float | null)>
     */
    public function getScore(string $member) : Promise
    {
        return $this->queryExecutor->execute(['zscore', $this->key, $member], toFloat);
    }
    /**
     * @param string[] $keys
     * @param string $aggregate
     *
     * @return Promise<int>
     */
    public function storeUnion(array $keys, string $aggregate = 'sum') : Promise
    {
        $payload = ['zunionstore', $this->key, \count($keys)];
        $weights = [];
        if (\count(\array_filter(\array_keys($keys), 'is_string'))) {
            foreach ($keys as $key => $weight) {
                $payload[] = $key;
                $weights[] = $weight;
            }
        } else {
            foreach ($keys as $key) {
                $payload[] = $key;
            }
        }
        if (\count($weights) > 0) {
            $payload[] = 'WEIGHTS';
            foreach ($weights as $weight) {
                $payload[] = $weight;
            }
        }
        if (\strtolower($aggregate) !== 'sum') {
            $payload[] = 'AGGREGATE';
            $payload[] = $aggregate;
        }
        return $this->queryExecutor->execute($payload);
    }
    /**
     * @param SortOptions $sort
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/sort
     */
    public function sort(?SortOptions $sort = null) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['SORT', $this->key], ($sort ?? new SortOptions())->toQuery()));
    }
}<?php

namespace Amp\Redis;

interface QueryExecutorFactory
{
    /**
     * @return QueryExecutor New QueryExecutor instance.
     */
    public function createQueryExecutor() : QueryExecutor;
}<?php

namespace Amp\Redis;

final class SortOptions
{
    /** @var string|null */
    private $pattern;
    /** @var int|null */
    private $offset;
    /** @var int|null */
    private $count;
    /** @var bool */
    private $ascending = true;
    /** @var bool */
    private $lexicographically = false;
    /**
     *
     */
    public function hasPattern() : bool
    {
        return $this->pattern !== null;
    }
    /**
     *
     */
    public function getPattern() : ?string
    {
        return $this->pattern;
    }
    /**
     *
     */
    public function withPattern(string $pattern) : self
    {
        $clone = clone $this;
        $clone->pattern = $pattern;
        return $clone;
    }
    /**
     *
     */
    public function withoutPattern() : self
    {
        $clone = clone $this;
        $clone->pattern = null;
        return $clone;
    }
    /**
     *
     */
    public function getOffset() : ?int
    {
        return $this->offset;
    }
    /**
     *
     */
    public function getCount() : ?int
    {
        return $this->count;
    }
    /**
     *
     */
    public function hasLimit() : bool
    {
        return $this->offset !== null;
    }
    /**
     *
     */
    public function withLimit(int $offset, int $count) : self
    {
        $clone = clone $this;
        $clone->offset = $offset;
        $clone->count = $count;
        return $clone;
    }
    /**
     *
     */
    public function withoutLimit() : self
    {
        $clone = clone $this;
        $clone->offset = null;
        $clone->count = null;
        return $clone;
    }
    /**
     *
     */
    public function isAscending() : bool
    {
        return $this->ascending;
    }
    /**
     *
     */
    public function isDescending() : bool
    {
        return !$this->ascending;
    }
    /**
     *
     */
    public function withAscendingOrder() : self
    {
        $clone = clone $this;
        $clone->ascending = true;
        return $clone;
    }
    /**
     *
     */
    public function withDescendingOrder() : self
    {
        $clone = clone $this;
        $clone->ascending = false;
        return $clone;
    }
    /**
     *
     */
    public function isLexicographicSorting() : bool
    {
        return $this->lexicographically;
    }
    /**
     *
     */
    public function withLexicographicSorting() : self
    {
        $clone = clone $this;
        $clone->lexicographically = true;
        return $clone;
    }
    /**
     *
     */
    public function withNumericSorting() : self
    {
        $clone = clone $this;
        $clone->lexicographically = false;
        return $clone;
    }
    /**
     *
     */
    public function toQuery() : array
    {
        $payload = [];
        if ($this->hasPattern()) {
            $payload[] = 'BY';
            $payload[] = $this->getPattern();
        }
        if ($this->hasLimit()) {
            $payload[] = 'LIMIT';
            $payload[] = $this->getOffset();
            $payload[] = $this->getCount();
        }
        if ($this->isDescending()) {
            $payload[] = 'DESC';
        }
        if ($this->isLexicographicSorting()) {
            $payload[] = 'ALPHA';
        }
        return $payload;
    }
}<?php

namespace Amp\Redis;

use Amp\Promise;
interface QueryExecutor
{
    /**
     * @param string[] $query
     * @param (callable | null) $responseTransform
     *
     * @return Promise
     *
     * @see toBool()
     * @see toNull()
     * @see toFloat()
     * @see toMap()
     */
    public function execute(array $query, callable $responseTransform = null) : Promise;
}<?php

namespace Amp\Redis;

use Amp\Promise;
use Amp\Socket;
use Amp\Socket\ConnectContext;
use function Amp\call;
const toFloat = __NAMESPACE__ . '\\toFloat';
const toBool = __NAMESPACE__ . '\\toBool';
const toNull = __NAMESPACE__ . '\\toNull';
const toMap = __NAMESPACE__ . '\\toMap';
/**
 *
 */
function toFloat($response) : ?float
{
    if ($response === null) {
        return null;
    }
    return (float) $response;
}
/**
 *
 */
function toBool($response) : ?bool
{
    if ($response === null) {
        return null;
    }
    return (bool) $response;
}
/**
 *
 */
function toMap(?array $values) : ?array
{
    if ($values === null) {
        return null;
    }
    $size = \count($values);
    $result = [];
    for ($i = 0; $i < $size; $i += 2) {
        $result[$values[$i]] = $values[$i + 1];
    }
    return $result;
}
/**
 *
 */
function toNull($response) : void
{
    // nothing to do
}
/**
 * @param Config $config
 * @param (Socket\Connector | null) $connector
 *
 * @return Promise<RespSocket>
 *
 * @throws RedisException
 */
function connect(Config $config, ?Socket\Connector $connector = null) : Promise
{
    return call(static function () use($config, $connector) {
        try {
            $connectContext = (new ConnectContext())->withConnectTimeout($config->getTimeout());
            $resp = new RespSocket((yield ($connector ?? Socket\connector())->connect($config->getConnectUri(), $connectContext)));
        } catch (Socket\SocketException $e) {
            throw new SocketException('Failed to connect to redis instance (' . $config->getConnectUri() . ')', 0, $e);
        }
        $promises = [];
        if ($config->hasPassword()) {
            // pipeline, don't await
            $promises[] = $resp->write('AUTH', $config->getPassword());
        }
        if ($config->getDatabase() !== 0) {
            // pipeline, don't await
            $promises[] = $resp->write('SELECT', $config->getDatabase());
        }
        foreach ($promises as $promise) {
            (yield $promise);
            if ([$response] = (yield $resp->read())) {
                if ($response instanceof \Throwable) {
                    throw $response;
                }
            } else {
                throw new RedisException('Failed to connect to redis instance (' . $config->getConnectUri() . ')');
            }
        }
        return $resp;
    });
}<?php

namespace Amp\Redis;

use Amp\Socket;
final class RemoteExecutorFactory implements QueryExecutorFactory
{
    private $config;
    private $connector;
    /**
     *
     */
    public function __construct(Config $config, ?Socket\Connector $connector = null)
    {
        $this->config = $config;
        $this->connector = $connector ?? Socket\connector();
    }
    /**
     *
     */
    public function createQueryExecutor() : QueryExecutor
    {
        return new RemoteExecutor($this->config, $this->connector);
    }
}<?php

/** @noinspection DuplicatedCode */
namespace Amp\Redis;

use Amp\Promise;
final class RedisList
{
    /** @var QueryExecutor */
    private $queryExecutor;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(QueryExecutor $queryExecutor, string $key)
    {
        $this->queryExecutor = $queryExecutor;
        $this->key = $key;
    }
    /**
     * @param string $index
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/lindex
     */
    public function get(string $index) : Promise
    {
        return $this->queryExecutor->execute(['lindex', $this->key, $index]);
    }
    /**
     * @param string $pivot
     * @param string $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/linsert
     */
    public function insertBefore(string $pivot, string $value) : Promise
    {
        return $this->queryExecutor->execute(['linsert', $this->key, 'BEFORE', $pivot, $value]);
    }
    /**
     * @param string $pivot
     * @param string $value
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/linsert
     */
    public function insertAfter(string $pivot, string $value) : Promise
    {
        return $this->queryExecutor->execute(['linsert', $this->key, 'AFTER', $pivot, $value]);
    }
    /**
     * @return Promise<int>
     *
     * @link https://redis.io/commands/llen
     */
    public function getSize() : Promise
    {
        return $this->queryExecutor->execute(['llen', $this->key]);
    }
    /**
     * @param string $value
     * @param string ...$values
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/lpush
     */
    public function pushHead(string $value, string ...$values) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['lpush', $this->key, $value], $values));
    }
    /**
     * @param string $value
     * @param string ...$values
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/lpushx
     */
    public function pushHeadIfExists(string $value, string ...$values) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['lpushx', $this->key, $value], $values));
    }
    /**
     * @param string $value
     * @param string ...$values
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/rpush
     */
    public function pushTail(string $value, string ...$values) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['rpush', $this->key, $value], $values));
    }
    /**
     * @param string $value
     * @param string ...$values
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/rpushx
     */
    public function pushTailIfExists(string $value, string ...$values) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['rpushx', $this->key, $value], $values));
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/lpop
     */
    public function popHead() : Promise
    {
        return $this->queryExecutor->execute(['lpop', $this->key]);
    }
    /**
     * @param int $timeout
     *
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/blpop
     */
    public function popHeadBlocking(int $timeout = 0) : Promise
    {
        return $this->queryExecutor->execute(['blpop', $this->key, $timeout], static function ($response) {
            return $response[1] ?? null;
        });
    }
    /**
     * @return Promise<string>
     *
     * @link https://redis.io/commands/rpop
     */
    public function popTail() : Promise
    {
        return $this->queryExecutor->execute(['rpop', $this->key]);
    }
    /**
     * @param int $timeout
     *
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/brpop
     */
    public function popTailBlocking(int $timeout = 0) : Promise
    {
        return $this->queryExecutor->execute(['brpop', $this->key, $timeout], static function ($response) {
            return $response[1] ?? null;
        });
    }
    /**
     * @param string $destination
     *
     * @return Promise<string>
     *
     * @link https://redis.io/commands/rpoplpush
     */
    public function popTailPushHead(string $destination) : Promise
    {
        return $this->queryExecutor->execute(['rpoplpush', $this->key, $destination]);
    }
    /**
     * @param string $destination
     * @param int $timeout
     *
     * @return Promise<(string | null)>
     *
     * @link https://redis.io/commands/brpoplpush
     */
    public function popTailPushHeadBlocking(string $destination, int $timeout = 0) : Promise
    {
        return $this->queryExecutor->execute(['brpoplpush', $this->key, $destination, $timeout]);
    }
    /**
     * @param int $start
     * @param int $end
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/lrange
     */
    public function getRange(int $start = 0, int $end = -1) : Promise
    {
        return $this->queryExecutor->execute(['lrange', $this->key, $start, $end]);
    }
    /**
     * @param string $value
     * @param int $count
     *
     * @return Promise<int>
     *
     * @link https://redis.io/commands/lrem
     */
    public function remove(string $value, int $count = 0) : Promise
    {
        return $this->queryExecutor->execute(['lrem', $this->key, $count, $value]);
    }
    /**
     * @param int $index
     * @param string $value
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/lset
     */
    public function set(int $index, string $value) : Promise
    {
        return $this->queryExecutor->execute(['lset', $this->key, $index, $value], toNull);
    }
    /**
     * @param int $start
     * @param int $stop
     *
     * @return Promise<void>
     *
     * @link https://redis.io/commands/ltrim
     */
    public function trim(int $start = 0, int $stop = -1) : Promise
    {
        return $this->queryExecutor->execute(['ltrim', $this->key, $start, $stop], toNull);
    }
    /**
     * @param SortOptions $sort
     *
     * @return Promise<array>
     *
     * @link https://redis.io/commands/sort
     */
    public function sort(?SortOptions $sort = null) : Promise
    {
        return $this->queryExecutor->execute(\array_merge(['SORT', $this->key], ($sort ?? new SortOptions())->toQuery()));
    }
}<?php

namespace Amp\Redis;

use Amp\ByteStream\ClosedException;
use Amp\Emitter;
use Amp\Iterator;
use Amp\Promise;
use Amp\Socket\Socket;
use Amp\Success;
use function Amp\asyncCall;
use function Amp\call;
final class RespSocket
{
    /** @var RespParser */
    private $parser;
    /** @var Socket */
    private $socket;
    /** @var Iterator */
    private $iterator;
    /** @var Promise */
    private $backpressure;
    /** @var \Throwable */
    private $error;
    /**
     *
     */
    public function __construct(Socket $socket)
    {
        $emitter = new Emitter();
        $backpressure =& $this->backpressure;
        $backpressure = new Success();
        $this->socket = $socket;
        $this->iterator = $emitter->iterate();
        $this->parser = new RespParser(static function ($message) use($emitter, &$backpressure) {
            $backpressure = $emitter->emit($message);
        });
        asyncCall(function () use($socket, $emitter) {
            try {
                while (null !== ($chunk = (yield $socket->read()))) {
                    $this->parser->append($chunk);
                    (yield $this->backpressure);
                }
                $emitter->fail(new ClosedException('Socket closed'));
            } catch (\Throwable $e) {
                if ($this->error === null) {
                    $this->error = $e;
                }
                $emitter->fail($e);
            }
            $this->close();
        });
    }
    /**
     *
     */
    public function read() : Promise
    {
        return call(function () {
            if ((yield $this->iterator->advance())) {
                return [$this->iterator->getCurrent()];
            }
            return null;
        });
    }
    /**
     *
     */
    public function write(string ...$args) : Promise
    {
        return call(function () use($args) {
            if ($this->error) {
                throw $this->error;
            }
            if ($this->socket === null) {
                throw new ClosedException('Redis connection already closed');
            }
            $payload = '';
            foreach ($args as $arg) {
                $payload .= '$' . \strlen($arg) . "\r\n{$arg}\r\n";
            }
            $payload = '*' . \count($args) . "\r\n{$payload}";
            (yield $this->socket->write($payload));
        });
    }
    /**
     *
     */
    public function reference() : void
    {
        if ($this->socket) {
            $this->socket->reference();
        }
    }
    /**
     *
     */
    public function unreference() : void
    {
        if ($this->socket) {
            $this->socket->unreference();
        }
    }
    /**
     *
     */
    public function close() : void
    {
        if ($this->parser) {
            $this->parser->reset();
        }
        if ($this->socket) {
            $this->socket->close();
            $this->socket = null;
        }
    }
    /**
     *
     */
    public function isClosed() : bool
    {
        return $this->socket === null;
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
}<?php

namespace Amp\Redis;

use Amp\Cache\Cache as CacheInterface;
use Amp\Cache\CacheException;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class Cache implements CacheInterface
{
    /** @var Redis */
    private $redis;
    /**
     * @param Redis $redis
     */
    public function __construct(Redis $redis)
    {
        $this->redis = $redis;
    }
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        return call(function () use($key) {
            try {
                return (yield $this->redis->get($key));
            } catch (RedisException $e) {
                throw new CacheException("Fetching '{$key}' from cache failed", 0, $e);
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        if ($ttl !== null && $ttl < 0) {
            throw new \Error('Invalid TTL: ' . $ttl);
        }
        if ($ttl === 0) {
            return new Success();
            // expires immediately
        }
        return call(function () use($key, $value, $ttl) {
            try {
                $options = new SetOptions();
                if ($ttl !== null) {
                    $options = $options->withTtl($ttl);
                }
                return (yield $this->redis->set($key, $value, $options));
            } catch (RedisException $e) {
                throw new CacheException("Storing '{$key}' to cache failed", 0, $e);
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        return call(function () use($key) {
            try {
                return (yield $this->redis->delete($key));
            } catch (RedisException $e) {
                throw new CacheException("Deleting '{$key}' from cache failed", 0, $e);
            }
        });
    }
}<?php

namespace Amp\Redis;

final class SetOptions
{
    /** @var int|null */
    private $ttl;
    /** @var string|null */
    private $ttlUnit;
    /** @var string|null */
    private $existenceFlag;
    /**
     *
     */
    public function withTtl(int $seconds) : self
    {
        $clone = clone $this;
        $clone->ttl = $seconds;
        $clone->ttlUnit = 'EX';
        return $clone;
    }
    /**
     *
     */
    public function withTtlInMillis(int $millis) : self
    {
        $clone = clone $this;
        $clone->ttl = $millis;
        $clone->ttlUnit = 'PX';
        return $clone;
    }
    /**
     *
     */
    public function withoutOverwrite() : self
    {
        $clone = clone $this;
        $clone->existenceFlag = 'NX';
        return $clone;
    }
    /**
     *
     */
    public function withoutCreation() : self
    {
        $clone = clone $this;
        $clone->existenceFlag = 'XX';
        return $clone;
    }
    /**
     *
     */
    public function toQuery() : array
    {
        $query = [];
        if ($this->ttl !== null) {
            $query[] = $this->ttlUnit;
            $query[] = $this->ttl;
        }
        if ($this->existenceFlag !== null) {
            $query[] = $this->existenceFlag;
        }
        return $query;
    }
}{
    "name": "amphp/redis",
    "description": "A non-blocking Redis client for Amp.",
    "keywords": [
        "amp",
        "amphp",
        "async",
        "client",
        "redis"
    ],
    "license": "MIT",
    "homepage": "https://github.com/amphp/redis",
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "support": {
        "issues": "https://github.com/amphp/redis/issues"
    },
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2.2.1",
        "amphp/cache": "^1.2.1",
        "amphp/socket": "^1",
        "league/uri-parser": "^1.4",
        "amphp/sync": "^1.1"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1.1.2",
        "phpunit/phpunit": "^7 | ^8",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Redis\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Redis\\": "test",
            "Amp\\Cache\\Test\\": "vendor/amphp/cache/test"
        }
    }
}
{
    "name": "amphp/windows-registry",
    "description": "Windows Registry Reader.",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "Amp\\WindowsRegistry\\": "lib"
        }
    },
    "require": {
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.4",
        "amphp/process": "^1"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "config": {
        "platform": {
            "php": "7.0.0"
        }
    }
}
<?php

namespace Amp\WindowsRegistry;

use Amp\ByteStream;
use Amp\Process\Process;
use Amp\Promise;
use function Amp\call;
class WindowsRegistry
{
    /**
     *
     */
    public function read(string $key) : Promise
    {
        return call(function () use($key) {
            $key = \strtr($key, '/', "\\");
            $parts = \explode("\\", $key);
            $value = \array_pop($parts);
            $key = \implode("\\", $parts);
            $lines = (yield $this->query($key));
            $lines = \array_filter($lines, function ($line) {
                return '' !== $line && $line[0] === ' ';
            });
            $values = \array_map(function ($line) {
                return \preg_split("(\\s+)", \ltrim($line), 3);
            }, $lines);
            $foundValue = null;
            foreach ($values as $v) {
                if ($v[0] === $value) {
                    if (\count($v) >= 3) {
                        return $v[2];
                    }
                    $foundValue = $v;
                }
            }
            if ($foundValue) {
                throw new KeyNotFoundException("Windows registry key '{$key}\\{$value}' was found, but could not be read correctly, got " . \var_export($foundValue, true));
            }
            throw new KeyNotFoundException("Windows registry key '{$key}\\{$value}' not found.");
        });
    }
    /**
     *
     */
    public function listKeys(string $key) : Promise
    {
        return call(function () use($key) {
            $lines = (yield $this->query($key));
            $lines = \array_filter($lines, function ($line) {
                return '' !== $line && $line[0] !== ' ';
            });
            return $lines;
        });
    }
    /**
     *
     */
    private function query(string $key) : Promise
    {
        return call(function () use($key) {
            if (0 !== \stripos(\PHP_OS, 'WIN')) {
                throw new \Error('Not running on Windows.');
            }
            $key = \strtr($key, '/', "\\");
            $cmd = \sprintf('reg query %s', \escapeshellarg($key));
            $process = new Process($cmd);
            (yield $process->start());
            $stdout = (yield ByteStream\buffer($process->getStdout()));
            $code = (yield $process->join());
            if ($code !== 0) {
                throw new KeyNotFoundException("Windows registry key '{$key}' not found.");
            }
            return \explode("\n", \str_replace("\r", '', $stdout));
        });
    }
}<?php

namespace Amp\WindowsRegistry;

class KeyNotFoundException extends \Exception
{
}{
    "name": "amphp/amp",
    "homepage": "http://amphp.org/amp",
    "description": "A non-blocking concurrency framework for PHP applications.",
    "keywords": [
        "async",
        "asynchronous",
        "concurrency",
        "promise",
        "awaitable",
        "future",
        "non-blocking",
        "event",
        "event-loop"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "require-dev": {
        "ext-json": "*",
        "amphp/phpunit-util": "^1",
        "amphp/php-cs-fixer-config": "dev-master",
        "react/promise": "^2",
        "phpunit/phpunit": "^7 | ^8 | ^9",
        "psalm/phar": "^3.11@dev",
        "jetbrains/phpstorm-stubs": "^2019.3"
    },
    "autoload": {
        "psr-4": {
            "Amp\\": "lib"
        },
        "files": [
            "lib/functions.php",
            "lib/Internal/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Test\\": "test"
        }
    },
    "support": {
        "issues": "https://github.com/amphp/amp/issues",
        "irc": "irc://irc.freenode.org/amphp"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.x-dev"
        }
    },
    "scripts": {
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit",
        "code-style": "@php ./vendor/bin/php-cs-fixer fix"
    }
}
<?php

namespace Amp;

/**
 * Emitter is a container for an iterator that can emit values using the emit() method and completed using the
 * complete() and fail() methods of this object. The contained iterator may be accessed using the iterate()
 * method. This object should not be part of a public API, but used internally to create and emit values to an
 * iterator.
 *
 * @template TValue
 */
final class Emitter
{
    /** @var Iterator<TValue> Has public emit, complete, and fail methods. */
    private $emitter;
    /** @var Iterator<TValue> Hides producer methods. */
    private $iterator;
    /**
     *
     */
    public function __construct()
    {
        $this->emitter = new class implements Iterator
        {
            use Internal\Producer {
                emit as public;
                complete as public;
                fail as public;
            }
        };
        $this->iterator = new Internal\PrivateIterator($this->emitter);
    }
    /**
     * @return Iterator
     * @psalm-return Iterator<TValue>
     */
    public function iterate() : Iterator
    {
        return $this->iterator;
    }
    /**
     * Emits a value to the iterator.
     *
     * @param mixed $value
     *
     * @psalm-param TValue $value
     *
     * @return Promise
     * @psalm-return Promise<null>
     * @psalm-suppress MixedInferredReturnType
     * @psalm-suppress MixedReturnStatement
     */
    public function emit($value) : Promise
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        return $this->emitter->emit($value);
    }
    /**
     * Completes the iterator.
     *
     * @return void
     */
    public function complete()
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->emitter->complete();
    }
    /**
     * Fails the iterator with the given reason.
     *
     * @param \Throwable $reason
     *
     * @return void
     */
    public function fail(\Throwable $reason)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->emitter->fail($reason);
    }
}<?php

namespace Amp;

/**
 * A NullCancellationToken can be used to avoid conditionals to check whether a token has been provided.
 *
 * Instead of writing
 *
 * ```php
 * if ($token) {
 *     $token->throwIfRequested();
 * }
 * ```
 *
 * potentially multiple times, it allows writing
 *
 * ```php
 * $token = $token ?? new NullCancellationToken;
 *
 * // ...
 *
 * $token->throwIfRequested();
 * ```
 *
 * instead.
 */
final class NullCancellationToken implements CancellationToken
{
    /**
     * @inheritdoc
     */
    public function subscribe(callable $callback) : string
    {
        return "null-token";
    }
    /**
     * @inheritdoc
     */
    public function unsubscribe(string $id)
    {
        // nothing to do
    }
    /**
     * @inheritdoc
     */
    public function isRequested() : bool
    {
        return false;
    }
    /**
     * @inheritdoc
     */
    public function throwIfRequested()
    {
        // nothing to do
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a successful promise using the given value (which can be any value except an object implementing
 * `Amp\Promise` or `React\Promise\PromiseInterface`).
 *
 * @template-covariant TValue
 * @template-implements Promise<TValue>
 */
final class Success implements Promise
{
    /** @var mixed */
    private $value;
    /**
     * @param mixed $value Anything other than a Promise object.
     *
     * @psalm-param TValue $value
     *
     * @throws \Error If a promise is given as the value.
     */
    public function __construct($value = null)
    {
        if ($value instanceof Promise || $value instanceof ReactPromise) {
            throw new \Error("Cannot use a promise as success value");
        }
        $this->value = $value;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        try {
            $result = $onResolved(null, $this->value);
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
}<?php

namespace Amp;

use function Amp\Internal\formatStacktrace;
/**
 * A TimeoutCancellationToken automatically requests cancellation after the timeout has elapsed.
 */
final class TimeoutCancellationToken implements CancellationToken
{
    /** @var string */
    private $watcher;
    /** @var CancellationToken */
    private $token;
    /**
     * @param int $timeout Milliseconds until cancellation is requested.
     * @param string $message Message for TimeoutException. Default is "Operation timed out".
     */
    public function __construct(int $timeout, string $message = "Operation timed out")
    {
        $source = new CancellationTokenSource();
        $this->token = $source->getToken();
        $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
        $this->watcher = Loop::delay($timeout, static function () use($source, $message, $trace) {
            $trace = formatStacktrace($trace);
            $source->cancel(new TimeoutException("{$message}\r\nTimeoutCancellationToken was created here:\r\n{$trace}"));
        });
        Loop::unreference($this->watcher);
    }
    /**
     * Cancels the delay watcher.
     */
    public function __destruct()
    {
        Loop::cancel($this->watcher);
    }
    /**
     * {@inheritdoc}
     */
    public function subscribe(callable $callback) : string
    {
        return $this->token->subscribe($callback);
    }
    /**
     * {@inheritdoc}
     */
    public function unsubscribe(string $id)
    {
        $this->token->unsubscribe($id);
    }
    /**
     * {@inheritdoc}
     */
    public function isRequested() : bool
    {
        return $this->token->isRequested();
    }
    /**
     * {@inheritdoc}
     */
    public function throwIfRequested()
    {
        $this->token->throwIfRequested();
    }
}<?php

namespace Amp;

/**
 * @template-covariant TValue
 * @template-implements Iterator<TValue>
 */
final class Producer implements Iterator
{
    /**
     * @use Internal\Producer<TValue>
     */
    use CallableMaker, Internal\Producer;
    /**
     * @param callable(callable(TValue ): Promise ): \Generator $producer
     *
     * @throws \Error Thrown if the callable does not return a Generator.
     */
    public function __construct(callable $producer)
    {
        $result = $producer($this->callableFromInstanceMethod("emit"));
        if (!$result instanceof \Generator) {
            throw new \Error("The callable did not return a Generator");
        }
        $coroutine = new Coroutine($result);
        $coroutine->onResolve(function ($exception) {
            if ($this->complete) {
                return;
            }
            if ($exception) {
                $this->fail($exception);
                return;
            }
            $this->complete();
        });
    }
}<?php

namespace Amp;

/**
 * Representation of the future value of an asynchronous operation.
 *
 * @template-covariant TValue
 * @psalm-yield TValue
 */
interface Promise
{
    /**
    * Registers a callback to be invoked when the promise is resolved.
    *
    * If this method is called multiple times, additional handlers will be registered instead of replacing any already
    existing handlers.
    *
    * If the promise is already resolved, the callback MUST be executed immediately.
    *
    * Exceptions MUST NOT be thrown from this method. Any exceptions thrown from invoked callbacks MUST be
    forwarded to the event-loop error handler.
    *
    * Note: You shouldn't implement this interface yourself. Instead, provide a method that returns a promise for the
    operation you're implementing. Objects other than pure placeholders implementing it are a very bad idea.
    *
    * @param callable $onResolved The first argument shall be `null` on success, while the second shall be `null` on
    failure.
    *
    * @psalm-param (callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $onResolved
    *
    * @return void
    */
    public function onResolve(callable $onResolved);
}<?php

namespace Amp\Internal;

use Amp\Coroutine;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
/**
 * Trait used by Promise implementations. Do not use this trait in your code, instead compose your class from one of
 * the available classes implementing \Amp\Promise.
 *
 * @internal
 */
trait Placeholder
{
    /** @var bool */
    private $resolved = false;
    /** @var mixed */
    private $result;
    /** @var ResolutionQueue|null|callable(\Throwable|null, mixed): (Promise|\React\Promise\PromiseInterface|\Generator<mixed,
     *     Promise|\React\Promise\PromiseInterface|array<array-key, Promise|\React\Promise\PromiseInterface>, mixed,
     *     mixed>|null)|callable(\Throwable|null, mixed): void */
    private $onResolved;
    /** @var null|array */
    private $resolutionTrace;
    /**
     * @inheritdoc
     */
    public function onResolve(callable $onResolved)
    {
        if ($this->resolved) {
            if ($this->result instanceof Promise) {
                $this->result->onResolve($onResolved);
                return;
            }
            try {
                /** @var mixed $result */
                $result = $onResolved(null, $this->result);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    Promise\rethrow($result);
                }
            } catch (\Throwable $exception) {
                Loop::defer(static function () use($exception) {
                    throw $exception;
                });
            }
            return;
        }
        if (null === $this->onResolved) {
            $this->onResolved = $onResolved;
            return;
        }
        if (!$this->onResolved instanceof ResolutionQueue) {
            /** @psalm-suppress InternalClass */
            $this->onResolved = new ResolutionQueue($this->onResolved);
        }
        /** @psalm-suppress InternalMethod */
        $this->onResolved->push($onResolved);
    }
    /**
     *
     */
    public function __destruct()
    {
        try {
            $this->result = null;
        } catch (\Throwable $e) {
            Loop::defer(static function () use($e) {
                throw $e;
            });
        }
    }
    /**
     * @param mixed $value
     *
     * @return void
     *
     * @throws \Error Thrown if the promise has already been resolved.
     */
    private function resolve($value = null)
    {
        if ($this->resolved) {
            $message = "Promise has already been resolved";
            if (isset($this->resolutionTrace)) {
                $trace = formatStacktrace($this->resolutionTrace);
                $message .= ". Previous resolution trace:\n\n{$trace}\n\n";
            } else {
                // @codeCoverageIgnoreStart
                $message .= ', define environment variable AMP_DEBUG or const AMP_DEBUG = true and enable assertions for a stacktrace of the previous resolution.';
                // @codeCoverageIgnoreEnd
            }
            throw new \Error($message);
        }
        \assert((function () {
            $env = \getenv("AMP_DEBUG") ?: "0";
            if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG") && \AMP_DEBUG) {
                $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
                \array_shift($trace);
                // remove current closure
                $this->resolutionTrace = $trace;
            }
            return true;
        })());
        if ($value instanceof ReactPromise) {
            $value = Promise\adapt($value);
        }
        $this->resolved = true;
        $this->result = $value;
        if ($this->onResolved === null) {
            return;
        }
        $onResolved = $this->onResolved;
        $this->onResolved = null;
        if ($this->result instanceof Promise) {
            $this->result->onResolve($onResolved);
            return;
        }
        try {
            /** @var mixed $result */
            $result = $onResolved(null, $this->result);
            $onResolved = null;
            // allow garbage collection of $onResolved, to catch any exceptions from destructors
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
    /**
     * @param \Throwable $reason Failure reason.
     *
     * @return void
     */
    private function fail(\Throwable $reason)
    {
        $this->resolve(new Failure($reason));
    }
    /**
     * @return bool True if the placeholder has been resolved.
     */
    private function isResolved() : bool
    {
        return $this->resolved;
    }
}<?php

namespace Amp\Internal;

use Amp\Deferred;
use Amp\Failure;
use Amp\Promise;
use Amp\Success;
use React\Promise\PromiseInterface as ReactPromise;
/**
 * Trait used by Iterator implementations. Do not use this trait in your code, instead compose your class from one of
 * the available classes implementing \Amp\Iterator.
 * Note that it is the responsibility of the user of this trait to ensure that listeners have a chance to listen first
 * before emitting values.
 *
 * @internal
 * @template-covariant TValue
 */
trait Producer
{
    /** @var Promise|null */
    private $complete;
    /** @var mixed[] */
    private $values = [];
    /** @var Deferred[] */
    private $backPressure = [];
    /** @var int */
    private $consumePosition = -1;
    /** @var int */
    private $emitPosition = -1;
    /** @var Deferred|null */
    private $waiting;
    /** @var null|array */
    private $resolutionTrace;
    /**
     * {@inheritdoc}
     *
     * @return Promise<bool>
     */
    public function advance() : Promise
    {
        if ($this->waiting !== null) {
            throw new \Error("The prior promise returned must resolve before invoking this method again");
        }
        unset($this->values[$this->consumePosition]);
        $position = ++$this->consumePosition;
        if (\array_key_exists($position, $this->values)) {
            \assert(isset($this->backPressure[$position]));
            $deferred = $this->backPressure[$position];
            unset($this->backPressure[$position]);
            $deferred->resolve();
            return new Success(true);
        }
        if ($this->complete) {
            return $this->complete;
        }
        $this->waiting = new Deferred();
        return $this->waiting->promise();
    }
    /**
     * {@inheritdoc}
     *
     * @return TValue
     */
    public function getCurrent()
    {
        if (empty($this->values) && $this->complete) {
            throw new \Error("The iterator has completed");
        }
        if (!\array_key_exists($this->consumePosition, $this->values)) {
            throw new \Error("Promise returned from advance() must resolve before calling this method");
        }
        return $this->values[$this->consumePosition];
    }
    /**
     * Emits a value from the iterator. The returned promise is resolved once the emitted value has been consumed.
     *
     * @param mixed $value
     *
     * @return Promise
     * @psalm-return Promise<null>
     *
     * @throws \Error If the iterator has completed.
     */
    private function emit($value) : Promise
    {
        if ($this->complete) {
            throw new \Error("Iterators cannot emit values after calling complete");
        }
        if ($value instanceof ReactPromise) {
            $value = Promise\adapt($value);
        }
        if ($value instanceof Promise) {
            $deferred = new Deferred();
            $value->onResolve(function ($e, $v) use($deferred) {
                if ($this->complete) {
                    $deferred->fail(new \Error("The iterator was completed before the promise result could be emitted"));
                    return;
                }
                if ($e) {
                    $this->fail($e);
                    $deferred->fail($e);
                    return;
                }
                $deferred->resolve($this->emit($v));
            });
            return $deferred->promise();
        }
        $position = ++$this->emitPosition;
        $this->values[$position] = $value;
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve(true);
            return new Success();
            // Consumer was already waiting for a new value, so back-pressure is unnecessary.
        }
        $this->backPressure[$position] = $pressure = new Deferred();
        return $pressure->promise();
    }
    /**
     * Completes the iterator.
     *
     * @return void
     *
     * @throws \Error If the iterator has already been completed.
     */
    private function complete()
    {
        if ($this->complete) {
            $message = "Iterator has already been completed";
            if (isset($this->resolutionTrace)) {
                $trace = formatStacktrace($this->resolutionTrace);
                $message .= ". Previous completion trace:\n\n{$trace}\n\n";
            } else {
                // @codeCoverageIgnoreStart
                $message .= ', define environment variable AMP_DEBUG or const AMP_DEBUG = true and enable assertions for a stacktrace of the previous resolution.';
                // @codeCoverageIgnoreEnd
            }
            throw new \Error($message);
        }
        \assert((function () {
            $env = \getenv("AMP_DEBUG") ?: "0";
            if ($env !== "0" && $env !== "false" || \defined("AMP_DEBUG") && \AMP_DEBUG) {
                $trace = \debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS);
                \array_shift($trace);
                // remove current closure
                $this->resolutionTrace = $trace;
            }
            return true;
        })());
        $this->complete = new Success(false);
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve($this->complete);
        }
    }
    /**
     * @param \Throwable $exception
     *
     * @return void
     */
    private function fail(\Throwable $exception)
    {
        $this->complete = new Failure($exception);
        if ($this->waiting !== null) {
            $waiting = $this->waiting;
            $this->waiting = null;
            $waiting->resolve($this->complete);
        }
    }
}<?php

namespace Amp\Internal;

use Amp\Promise;
/**
 * Wraps a Promise instance that has public methods to resolve and fail the promise into an object that only allows
 * access to the public API methods.
 */
final class PrivatePromise implements Promise
{
    /** @var Promise */
    private $promise;
    /**
     *
     */
    public function __construct(Promise $promise)
    {
        $this->promise = $promise;
    }
    /**
     *
     */
    public function onResolve(callable $onResolved)
    {
        $this->promise->onResolve($onResolved);
    }
}<?php

namespace Amp\Internal;

/**
* Formats a stacktrace obtained via `debug_backtrace()`.
*
* @param array<array{file?: string, line: int, type?: string, class: string, function: string}> $trace Output of
`debug_backtrace()`.
*
* @return string Formatted stacktrace.
*
* @codeCoverageIgnore
* @internal
*/
function formatStacktrace(array $trace) : string
{
    return \implode("\n", \array_map(static function ($e, $i) {
        $line = "#{$i} ";
        if (isset($e["file"])) {
            $line .= "{$e['file']}:{$e['line']} ";
        }
        if (isset($e["type"])) {
            $line .= $e["class"] . $e["type"];
        }
        return $line . $e["function"] . "()";
    }, $trace, \array_keys($trace)));
}
/**
 * Creates a `TypeError` with a standardized error message.
 *
 * @param string[] $expected Expected types.
 * @param mixed $given Given value.
 *
 * @return \TypeError
 *
 * @internal
 */
function createTypeError(array $expected, $given) : \TypeError
{
    $givenType = \is_object($given) ? \sprintf("instance of %s", \get_class($given)) : \gettype($given);
    if (\count($expected) === 1) {
        $expectedType = "Expected the following type: " . \array_pop($expected);
    } else {
        $expectedType = "Expected one of the following types: " . \implode(", ", $expected);
    }
    return new \TypeError("{$expectedType}; {$givenType} given");
}
/**
 * Returns the current time relative to an arbitrary point in time.
 *
 * @return int Time in milliseconds.
 */
function getCurrentTime() : int
{
    /** @var int|null $startTime */
    static $startTime;
    /** @var int|null $nextWarning */
    static $nextWarning;
    if (\PHP_INT_SIZE === 4) {
        // @codeCoverageIgnoreStart
        if ($startTime === null) {
            $startTime = \PHP_VERSION_ID >= 70300 ? \hrtime(false)[0] : \time();
            $nextWarning = \PHP_INT_MAX - 86400 * 7;
        }
        if (\PHP_VERSION_ID >= 70300) {
            list($seconds, $nanoseconds) = \hrtime(false);
            $seconds -= $startTime;
            if ($seconds >= $nextWarning) {
                $timeToOverflow = (\PHP_INT_MAX - $seconds * 1000) / 1000;
                \trigger_error("getCurrentTime() will overflow in {$timeToOverflow} seconds, please restart the process before that. " . "You're using a 32 bit version of PHP, so time will overflow about every 24 days. Regular restarts are required.", \E_USER_WARNING);
                /** @psalm-suppress PossiblyNullOperand */
                $nextWarning += 600;
                // every 10 minutes
            }
            return (int) ($seconds * 1000 + $nanoseconds / 1000000);
        }
        $seconds = \microtime(true) - $startTime;
        if ($seconds >= $nextWarning) {
            $timeToOverflow = (\PHP_INT_MAX - $seconds * 1000) / 1000;
            \trigger_error("getCurrentTime() will overflow in {$timeToOverflow} seconds, please restart the process before that. " . "You're using a 32 bit version of PHP, so time will overflow about every 24 days. Regular restarts are required.", \E_USER_WARNING);
            /** @psalm-suppress PossiblyNullOperand */
            $nextWarning += 600;
            // every 10 minutes
        }
        return (int) ($seconds * 1000);
        // @codeCoverageIgnoreEnd
    }
    if (\PHP_VERSION_ID >= 70300) {
        list($seconds, $nanoseconds) = \hrtime(false);
        return (int) ($seconds * 1000 + $nanoseconds / 1000000);
    }
    return (int) (\microtime(true) * 1000);
}<?php

namespace Amp\Internal;

use Amp\Iterator;
use Amp\Promise;
/**
 * Wraps an Iterator instance that has public methods to emit, complete, and fail into an object that only allows
 * access to the public API methods.
 *
 * @template-covariant TValue
 * @template-implements Iterator<TValue>
 */
final class PrivateIterator implements Iterator
{
    /** @var Iterator<TValue> */
    private $iterator;
    /**
     * @param Iterator $iterator
     *
     * @psalm-param Iterator<TValue> $iterator
     */
    public function __construct(Iterator $iterator)
    {
        $this->iterator = $iterator;
    }
    /**
     * @return Promise<bool>
     */
    public function advance() : Promise
    {
        return $this->iterator->advance();
    }
    /**
     * @psalm-return TValue
     */
    public function getCurrent()
    {
        return $this->iterator->getCurrent();
    }
}<?php

namespace Amp\Internal;

use Amp\Coroutine;
use Amp\Loop;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
/**
 * Stores a set of functions to be invoked when a promise is resolved.
 *
 * @internal
 * @psalm-internal Amp\Internal
 */
class ResolutionQueue
{
    /** @var array<array-key, callable(\Throwable|null, mixed): (Promise|\React\Promise\PromiseInterface|\Generator<mixed,
     *     Promise|\React\Promise\PromiseInterface|array<array-key, Promise|\React\Promise\PromiseInterface>, mixed,
     *     mixed>|null) | callable(\Throwable|null, mixed): void> */
    private $queue = [];
    /**
     * @param (callable | null) $callback Initial callback to add to queue.
     *
     * @psalm-param (null | callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $callback
     */
    public function __construct(callable $callback = null)
    {
        if ($callback !== null) {
            $this->push($callback);
        }
    }
    /**
     * Unrolls instances of self to avoid blowing up the call stack on resolution.
     *
     * @param callable $callback
     *
     * @psalm-param (callable((\Throwable | null) , mixed ): (Promise | \React\Promise\PromiseInterface | \Generator<mixed, (Promise | \React\Promise\PromiseInterface | array<array-key, (Promise | \React\Promise\PromiseInterface)>), mixed, mixed> | null) | callable((\Throwable | null) , mixed ): void) $callback
     *
     * @return void
     */
    public function push(callable $callback)
    {
        if ($callback instanceof self) {
            $this->queue = \array_merge($this->queue, $callback->queue);
            return;
        }
        $this->queue[] = $callback;
    }
    /**
     * Calls each callback in the queue, passing the provided values to the function.
     *
     * @param (\Throwable | null) $exception
     * @param mixed $value
     *
     * @return void
     */
    public function __invoke($exception, $value)
    {
        foreach ($this->queue as $callback) {
            try {
                $result = $callback($exception, $value);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    Promise\rethrow($result);
                }
            } catch (\Throwable $exception) {
                Loop::defer(static function () use($exception) {
                    throw $exception;
                });
            }
        }
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Promise\rethrow;
/**
 * A cancellation token source provides a mechanism to cancel operations.
 *
 * Cancellation of operation works by creating a cancellation token source and passing the corresponding token when
 * starting the operation. To cancel the operation, invoke `CancellationTokenSource::cancel()`.
 *
 * Any operation can decide what to do on a cancellation request, it has "don't care" semantics. An operation SHOULD be
 * aborted, but MAY continue. Example: A DNS client might continue to receive and cache the response, as the query has
 * been sent anyway. An HTTP client would usually close a connection, but might not do so in case a response is close to
 * be fully received to reuse the connection.
 *
 * **Example**
 *
 * ```php
 * $tokenSource = new CancellationTokenSource;
 * $token = $tokenSource->getToken();
 *
 * $response = yield $httpClient->request("https://example.com/stream", $token);
 * $responseBody = $response->getBody();
 *
 * while (($chunk = yield $response->read()) !== null) {
 *     // consume $chunk
 *
 *     if ($noLongerInterested) {
 *         $cancellationTokenSource->cancel();
 *         break;
 *     }
 * }
 * ```
 *
 * @see CancellationToken
 * @see CancelledException
 */
final class CancellationTokenSource
{
    /** @var CancellationToken */
    private $token;
    /** @var callable|null */
    private $onCancel;
    /**
     *
     */
    public function __construct()
    {
        $onCancel = null;
        $this->token = new class($onCancel) implements CancellationToken
        {
            /** @var string */
            private $nextId = "a";
            /** @var callable[] */
            private $callbacks = [];
            /** @var \Throwable|null */
            private $exception;
            /**
             * @param mixed $onCancel
             * @param-out callable $onCancel
             */
            public function __construct(&$onCancel)
            {
                /** @psalm-suppress MissingClosureReturnType We still support PHP 7.0 */
                $onCancel = function (\Throwable $exception) {
                    $this->exception = $exception;
                    $callbacks = $this->callbacks;
                    $this->callbacks = [];
                    foreach ($callbacks as $callback) {
                        $this->invokeCallback($callback);
                    }
                };
            }
            /**
             * @param callable $callback
             *
             * @return void
             */
            private function invokeCallback(callable $callback)
            {
                // No type declaration to prevent exception outside the try!
                try {
                    /** @var mixed $result */
                    $result = $callback($this->exception);
                    if ($result instanceof \Generator) {
                        /** @psalm-var \Generator<mixed, Promise|ReactPromise|(Promise|ReactPromise)[], mixed, mixed> $result */
                        $result = new Coroutine($result);
                    }
                    if ($result instanceof Promise || $result instanceof ReactPromise) {
                        rethrow($result);
                    }
                } catch (\Throwable $exception) {
                    Loop::defer(static function () use($exception) {
                        throw $exception;
                    });
                }
            }
            /**
             *
             */
            public function subscribe(callable $callback) : string
            {
                $id = $this->nextId++;
                if ($this->exception) {
                    $this->invokeCallback($callback);
                } else {
                    $this->callbacks[$id] = $callback;
                }
                return $id;
            }
            /**
             *
             */
            public function unsubscribe(string $id)
            {
                unset($this->callbacks[$id]);
            }
            /**
             *
             */
            public function isRequested() : bool
            {
                return isset($this->exception);
            }
            /**
             *
             */
            public function throwIfRequested()
            {
                if (isset($this->exception)) {
                    throw $this->exception;
                }
            }
        };
        $this->onCancel = $onCancel;
    }
    /**
     *
     */
    public function getToken() : CancellationToken
    {
        return $this->token;
    }
    /**
     * @param (\Throwable | null) $previous Exception to be used as the previous exception to CancelledException.
     *
     * @return void
     */
    public function cancel(\Throwable $previous = null)
    {
        if ($this->onCancel === null) {
            return;
        }
        $onCancel = $this->onCancel;
        $this->onCancel = null;
        $onCancel(new CancelledException($previous));
    }
}<?php

namespace Amp\Loop;

use Amp\Struct;
/**
 * @template TValue as (int|resource|null)
 *
 * @psalm-suppress MissingConstructor
 */
class Watcher
{
    use Struct;
    const IO = 0b11;
    const READABLE = 0b1;
    const WRITABLE = 0b10;
    const DEFER = 0b100;
    const TIMER = 0b11000;
    const DELAY = 0b1000;
    const REPEAT = 0b10000;
    const SIGNAL = 0b100000;
    /** @var int */
    public $type;
    /** @var bool */
    public $enabled = true;
    /** @var bool */
    public $referenced = true;
    /** @var string */
    public $id;
    /** @var callable */
    public $callback;
    /**
     * Data provided to the watcher callback.
     *
     * @var mixed
     */
    public $data;
    /**
     * Watcher-dependent value storage. Stream for IO watchers, signal number for signal watchers, interval for timers.
     *
     * @var resource|int|null
     * @psalm-var TValue
     */
    public $value;
    /** @var int|null */
    public $expiration;
}<?php

namespace Amp\Loop;

use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
class EventDriver extends Driver
{
    /** @var \Event[]|null */
    private static $activeSignals;
    /** @var \EventBase */
    private $handle;
    /** @var \Event[] */
    private $events = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /** @var \Event[] */
    private $signals = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /**
     *
     */
    public function __construct()
    {
        $config = new \EventConfig();
        if (\DIRECTORY_SEPARATOR !== '\\') {
            $config->requireFeatures(\EventConfig::FEATURE_FDS);
        }
        $this->handle = new \EventBase($config);
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        if (self::$activeSignals === null) {
            self::$activeSignals =& $this->signals;
        }
        /**
         * @param         $resource
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->ioCallback = function ($resource, $what, Watcher $watcher) {
            \assert(\is_resource($watcher->value));
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param         $resource
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->timerCallback = function ($resource, $what, Watcher $watcher) {
            \assert(\is_int($watcher->value));
            if ($watcher->type & Watcher::DELAY) {
                $this->cancel($watcher->id);
            } else {
                $this->events[$watcher->id]->add($watcher->value / self::MILLISEC_PER_SEC);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param         $signum
         * @param         $what
         * @param Watcher $watcher
         *
         * @return void
         */
        $this->signalCallback = function ($signum, $what, Watcher $watcher) {
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        if (isset($this->events[$watcherId])) {
            $this->events[$watcherId]->free();
            unset($this->events[$watcherId]);
        }
    }
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("event");
    }
    /**
     * @codeCoverageIgnore
     */
    public function __destruct()
    {
        // Unset here, otherwise $event->del() in the loop may fail with a warning, because __destruct order isn't defined.
        // Related https://github.com/amphp/amp/issues/159.
        $events = $this->events;
        $this->events = [];
        foreach ($events as $event) {
            if ($event !== null) {
                // Events may have been nulled in extension depending on destruct order.
                $event->free();
            }
        }
        // Manually free the loop handle to fully release loop resources.
        // See https://github.com/amphp/amp/issues/177.
        if ($this->handle !== null) {
            $this->handle->free();
            $this->handle = null;
        }
    }
    /**
     * {@inheritdoc}
     */
    public function run()
    {
        $active = self::$activeSignals;
        \assert($active !== null);
        foreach ($active as $event) {
            $event->del();
        }
        self::$activeSignals =& $this->signals;
        foreach ($this->signals as $event) {
            /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
            $event->add();
        }
        try {
            parent::run();
        } finally {
            foreach ($this->signals as $event) {
                $event->del();
            }
            self::$activeSignals =& $active;
            foreach ($active as $event) {
                /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
                $event->add();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function stop()
    {
        $this->handle->stop();
        parent::stop();
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle() : \EventBase
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        $this->handle->loop($blocking ? \EventBase::LOOP_ONCE : \EventBase::LOOP_ONCE | \EventBase::LOOP_NONBLOCK);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $now = $this->now();
        foreach ($watchers as $watcher) {
            if (!isset($this->events[$id = $watcher->id])) {
                switch ($watcher->type) {
                    case Watcher::READABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::READ | \Event::PERSIST, $this->ioCallback, $watcher);
                        break;
                    case Watcher::WRITABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::WRITE | \Event::PERSIST, $this->ioCallback, $watcher);
                        break;
                    case Watcher::DELAY:
                    case Watcher::REPEAT:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = new \Event($this->handle, -1, \Event::TIMEOUT, $this->timerCallback, $watcher);
                        break;
                    case Watcher::SIGNAL:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = new \Event($this->handle, $watcher->value, \Event::SIGNAL | \Event::PERSIST, $this->signalCallback, $watcher);
                        break;
                    default:
                        // @codeCoverageIgnoreStart
                        throw new \Error("Unknown watcher type");
                }
            }
            switch ($watcher->type) {
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    $interval = \max(0, $watcher->expiration - $now);
                    $this->events[$id]->add($interval > 0 ? $interval / self::MILLISEC_PER_SEC : 0);
                    break;
                case Watcher::SIGNAL:
                    $this->signals[$id] = $this->events[$id];
                // no break
                default:
                    /** @psalm-suppress TooFewArguments https://github.com/JetBrains/phpstorm-stubs/pull/763 */
                    $this->events[$id]->add();
                    break;
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        if (isset($this->events[$id = $watcher->id])) {
            $this->events[$id]->del();
            if ($watcher->type === Watcher::SIGNAL) {
                unset($this->signals[$id]);
            }
        }
    }
}<?php

namespace Amp\Loop;

use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Promise\rethrow;
/**
 * Event loop driver which implements all basic operations to allow interoperability.
 *
 * Watchers (enabled or new watchers) MUST immediately be marked as enabled, but only be activated (i.e. callbacks can
 * be called) right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
 *
 * All registered callbacks MUST NOT be called from a file with strict types enabled (`declare(strict_types=1)`).
 */
abstract class Driver
{
    // Don't use 1e3 / 1e6, they result in a float instead of int
    const MILLISEC_PER_SEC = 1000;
    const MICROSEC_PER_SEC = 1000000;
    /** @var string */
    private $nextId = "a";
    /** @var Watcher[] */
    private $watchers = [];
    /** @var Watcher[] */
    private $enableQueue = [];
    /** @var Watcher[] */
    private $deferQueue = [];
    /** @var Watcher[] */
    private $nextTickQueue = [];
    /** @var callable(\Throwable):void|null */
    private $errorHandler;
    /** @var bool */
    private $running = false;
    /** @var array */
    private $registry = [];
    /**
    * Run the event loop.
    *
    * One iteration of the loop is called one "tick". A tick covers the following steps:
    *
    * 1. Activate watchers created / enabled in the last tick / before `run()`.
    2. Execute all enabled defer watchers.
    3. Execute all due timer, pending signal and actionable stream callbacks, each only once per tick.
    *
    * The loop MUST continue to run until it is either stopped explicitly, no referenced watchers exist anymore, or an
    exception is thrown that cannot be handled. Exceptions that cannot be handled are exceptions thrown from an
    error handler or exceptions that would be passed to an error handler but none exists to handle them.
    *
    * @return void
    */
    public function run()
    {
        $this->running = true;
        try {
            while ($this->running) {
                if ($this->isEmpty()) {
                    return;
                }
                $this->tick();
            }
        } finally {
            $this->stop();
        }
    }
    /**
     * @return bool True if no enabled and referenced watchers remain in the loop.
     */
    private function isEmpty() : bool
    {
        foreach ($this->watchers as $watcher) {
            if ($watcher->enabled && $watcher->referenced) {
                return false;
            }
        }
        return true;
    }
    /**
     * Executes a single tick of the event loop.
     *
     * @return void
     */
    private function tick()
    {
        if (empty($this->deferQueue)) {
            $this->deferQueue = $this->nextTickQueue;
        } else {
            $this->deferQueue = \array_merge($this->deferQueue, $this->nextTickQueue);
        }
        $this->nextTickQueue = [];
        $this->activate($this->enableQueue);
        $this->enableQueue = [];
        foreach ($this->deferQueue as $watcher) {
            if (!isset($this->deferQueue[$watcher->id])) {
                continue;
                // Watcher disabled by another defer watcher.
            }
            unset($this->watchers[$watcher->id], $this->deferQueue[$watcher->id]);
            try {
                /** @var mixed $result */
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
        /** @psalm-suppress RedundantCondition */
        $this->dispatch(empty($this->nextTickQueue) && empty($this->enableQueue) && $this->running && !$this->isEmpty());
    }
    /**
     * Activates (enables) all the given watchers.
     *
     * @param Watcher[] $watchers
     *
     * @return void
     */
    protected abstract function activate(array $watchers);
    /**
     * Dispatches any pending read/write, timer, and signal events.
     *
     * @param bool $blocking
     *
     * @return void
     */
    protected abstract function dispatch(bool $blocking);
    /**
    * Stop the event loop.
    *
    * When an event loop is stopped, it continues with its current tick and exits the loop afterwards. Multiple calls
    to stop MUST be ignored and MUST NOT raise an exception.
    *
    * @return void
    */
    public function stop()
    {
        $this->running = false;
    }
    /**
    * Defer the execution of a callback.
    *
    * The deferred callable MUST be executed before any other type of watcher in a tick. Order of enabling MUST be
    preserved when executing the callbacks.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param callable (string $watcherId, mixed $data) $callback The callback to defer. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function defer(callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<null> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::DEFER;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->nextTickQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Delay the execution of a callback.
    *
    * The delay is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be determined by which
    timers expire first, but timers with the same expiration time MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $delay The amount of time, in milliseconds, to delay the execution for.
    * @param callable (string $watcherId, mixed $data) $callback The callback to delay. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function delay(int $delay, callable $callback, $data = null) : string
    {
        if ($delay < 0) {
            throw new \Error("Delay must be greater than or equal to zero");
        }
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::DELAY;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $delay;
        $watcher->expiration = $this->now() + $delay;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Repeatedly execute a callback.
    *
    * The interval between executions is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be
    determined by which timers expire first, but timers with the same expiration time MAY be executed in any order.
    The first execution is scheduled after the first interval period.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $interval The time interval, in milliseconds, to wait between executions.
    * @param callable (string $watcherId, mixed $data) $callback The callback to repeat.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function repeat(int $interval, callable $callback, $data = null) : string
    {
        if ($interval < 0) {
            throw new \Error("Interval must be greater than or equal to zero");
        }
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::REPEAT;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $interval;
        $watcher->expiration = $this->now() + $interval;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a stream resource becomes readable or is closed for reading.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable (string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function onReadable($stream, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<resource> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::READABLE;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $stream;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a stream resource becomes writable or is closed for writing.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable (string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public function onWritable($stream, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<resource> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::WRITABLE;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $stream;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Execute a callback when a signal is received.
    *
    * Warning: Installing the same signal on different instances of this interface is deemed undefined behavior.
    Implementations MAY try to detect this, if possible, but are not required to. This is due to technical
    limitations of the signals being registered globally per process.
    *
    * Multiple watchers on the same signal MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $signo The signal number to monitor.
    * @param callable (string $watcherId, int $signo, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the $data parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    *
    * @throws UnsupportedFeatureException If signal handling is not supported.
    */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        /** @psalm-var Watcher<int> $watcher */
        $watcher = new Watcher();
        $watcher->type = Watcher::SIGNAL;
        $watcher->id = $this->nextId++;
        $watcher->callback = $callback;
        $watcher->value = $signo;
        $watcher->data = $data;
        $this->watchers[$watcher->id] = $watcher;
        $this->enableQueue[$watcher->id] = $watcher;
        return $watcher->id;
    }
    /**
    * Enable a watcher to be active starting in the next tick.
    *
    * Watchers MUST immediately be marked as enabled, but only be activated (i.e. callbacks can be called) right before
    the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public function enable(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            throw new InvalidWatcherError($watcherId, "Cannot enable an invalid watcher identifier: '{$watcherId}'");
        }
        $watcher = $this->watchers[$watcherId];
        if ($watcher->enabled) {
            return;
            // Watcher already enabled.
        }
        $watcher->enabled = true;
        switch ($watcher->type) {
            case Watcher::DEFER:
                $this->nextTickQueue[$watcher->id] = $watcher;
                break;
            case Watcher::REPEAT:
            case Watcher::DELAY:
                \assert(\is_int($watcher->value));
                $watcher->expiration = $this->now() + $watcher->value;
                $this->enableQueue[$watcher->id] = $watcher;
                break;
            default:
                $this->enableQueue[$watcher->id] = $watcher;
                break;
        }
    }
    /**
    * Cancel a watcher.
    *
    * This will detach the event loop from all resources that are associated to the watcher. After this operation the
    watcher is permanently invalid. Calling this function MUST NOT fail, even if passed an invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function cancel(string $watcherId)
    {
        $this->disable($watcherId);
        unset($this->watchers[$watcherId]);
    }
    /**
    * Disable a watcher immediately.
    *
    * A watcher MUST be disabled immediately, e.g. if a defer watcher disables a later defer watcher, the second defer
    watcher isn't executed in this tick.
    *
    * Disabling a watcher MUST NOT invalidate the watcher. Calling this function MUST NOT fail, even if passed an
    invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function disable(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            return;
        }
        $watcher = $this->watchers[$watcherId];
        if (!$watcher->enabled) {
            return;
            // Watcher already disabled.
        }
        $watcher->enabled = false;
        $id = $watcher->id;
        switch ($watcher->type) {
            case Watcher::DEFER:
                if (isset($this->nextTickQueue[$id])) {
                    // Watcher was only queued to be enabled.
                    unset($this->nextTickQueue[$id]);
                } else {
                    unset($this->deferQueue[$id]);
                }
                break;
            default:
                if (isset($this->enableQueue[$id])) {
                    // Watcher was only queued to be enabled.
                    unset($this->enableQueue[$id]);
                } else {
                    $this->deactivate($watcher);
                }
                break;
        }
    }
    /**
     * Deactivates (disables) the given watcher.
     *
     * @param Watcher $watcher
     *
     * @return void
     */
    protected abstract function deactivate(Watcher $watcher);
    /**
    * Reference a watcher.
    *
    * This will keep the event loop alive whilst the watcher is still being monitored. Watchers have this state by
    default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public function reference(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            throw new InvalidWatcherError($watcherId, "Cannot reference an invalid watcher identifier: '{$watcherId}'");
        }
        $this->watchers[$watcherId]->referenced = true;
    }
    /**
    * Unreference a watcher.
    *
    * The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers
    are all referenced by default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public function unreference(string $watcherId)
    {
        if (!isset($this->watchers[$watcherId])) {
            return;
        }
        $this->watchers[$watcherId]->referenced = false;
    }
    /**
    * Stores information in the loop bound registry.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    * @param mixed $value The value to be stored.
    *
    * @return void
    */
    public final function setState(string $key, $value)
    {
        if ($value === null) {
            unset($this->registry[$key]);
        } else {
            $this->registry[$key] = $value;
        }
    }
    /**
    * Gets information stored bound to the loop.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    *
    * @return mixed The previously stored value or `null` if it doesn't exist.
    */
    public final function getState(string $key)
    {
        return isset($this->registry[$key]) ? $this->registry[$key] : null;
    }
    /**
    * Set a callback to be executed when an error occurs.
    *
    * The callback receives the error as the first and only parameter. The return value of the callback gets ignored.
    If it can't handle the error, it MUST throw the error. Errors thrown by the callback or during its invocation
    MUST be thrown into the `run` loop and stop the driver.
    *
    * Subsequent calls to this method will overwrite the previous handler.
    *
    * @param (callable(\Throwable $error): void | null) $callback The callback to execute. `null` will clear the
    current handler.
    *
    * @return (callable(\Throwable $error): void | null) The previous handler, `null` if there was none.
    */
    public function setErrorHandler(callable $callback = null)
    {
        $previous = $this->errorHandler;
        $this->errorHandler = $callback;
        return $previous;
    }
    /**
     * Invokes the error handler with the given exception.
     *
     * @param \Throwable $exception The exception thrown from a watcher callback.
     *
     * @return void
     * @throws \Throwable If no error handler has been set.
     */
    protected function error(\Throwable $exception)
    {
        if ($this->errorHandler === null) {
            throw $exception;
        }
        ($this->errorHandler)($exception);
    }
    /**
    * Returns the current loop time in millisecond increments. Note this value does not necessarily correlate to
    wall-clock time, rather the value returned is meant to be used in relative comparisons to prior values returned
    by this method (intervals, expiration calculations, etc.) and is only updated once per loop tick.
    *
    * Extending classes should override this function to return a value cached once per loop tick.
    *
    * @return int
    */
    public function now() : int
    {
        return (int) (\microtime(true) * self::MILLISEC_PER_SEC);
    }
    /**
    * Get the underlying loop handle.
    *
    * Example: the `uv_loop` resource for `libuv` or the `EvLoop` object for `libev` or `null` for a native driver.
    *
    * Note: This function is *not* exposed in the `Loop` class. Users shall access it directly on the respective loop
    instance.
    *
    * @return (null | object | resource) The loop handle the event loop operates on. `null` if there is none.
    */
    public abstract function getHandle();
    /**
     * Returns the same array of data as getInfo().
     *
     * @return array
     */
    public function __debugInfo()
    {
        // @codeCoverageIgnoreStart
        return $this->getInfo();
        // @codeCoverageIgnoreEnd
    }
    /**
    * Retrieve an associative array of information about the event loop driver.
    *
    * The returned array MUST contain the following data describing the driver's currently registered watchers:
    *
    * [
    "defer"            => ["enabled" => int, "disabled" => int],
    "delay"            => ["enabled" => int, "disabled" => int],
    "repeat"           => ["enabled" => int, "disabled" => int],
    "on_readable"      => ["enabled" => int, "disabled" => int],
    "on_writable"      => ["enabled" => int, "disabled" => int],
    "on_signal"        => ["enabled" => int, "disabled" => int],
    "enabled_watchers" => ["referenced" => int, "unreferenced" => int],
    "running"          => bool
    ];
    *
    * Implementations MAY optionally add more information in the array but at minimum the above `key => value` format
    MUST always be provided.
    *
    * @return array Statistics about the loop in the described format.
    */
    public function getInfo() : array
    {
        $watchers = ["referenced" => 0, "unreferenced" => 0];
        $defer = $delay = $repeat = $onReadable = $onWritable = $onSignal = ["enabled" => 0, "disabled" => 0];
        foreach ($this->watchers as $watcher) {
            switch ($watcher->type) {
                case Watcher::READABLE:
                    $array =& $onReadable;
                    break;
                case Watcher::WRITABLE:
                    $array =& $onWritable;
                    break;
                case Watcher::SIGNAL:
                    $array =& $onSignal;
                    break;
                case Watcher::DEFER:
                    $array =& $defer;
                    break;
                case Watcher::DELAY:
                    $array =& $delay;
                    break;
                case Watcher::REPEAT:
                    $array =& $repeat;
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
            if ($watcher->enabled) {
                ++$array["enabled"];
                if ($watcher->referenced) {
                    ++$watchers["referenced"];
                } else {
                    ++$watchers["unreferenced"];
                }
            } else {
                ++$array["disabled"];
            }
        }
        return ["enabled_watchers" => $watchers, "defer" => $defer, "delay" => $delay, "repeat" => $repeat, "on_readable" => $onReadable, "on_writable" => $onWritable, "on_signal" => $onSignal, "running" => (bool) $this->running];
    }
}<?php

namespace Amp\Loop;

// @codeCoverageIgnoreStart
class DriverFactory
{
    /**
     * Creates a new loop instance and chooses the best available driver.
     *
     * @return Driver
     *
     * @throws \Error If an invalid class has been specified via AMP_LOOP_DRIVER
     */
    public function create() : Driver
    {
        $driver = (function () {
            if ($driver = $this->createDriverFromEnv()) {
                return $driver;
            }
            if (UvDriver::isSupported()) {
                return new UvDriver();
            }
            if (EvDriver::isSupported()) {
                return new EvDriver();
            }
            if (EventDriver::isSupported()) {
                return new EventDriver();
            }
            return new NativeDriver();
        })();
        if (\getenv("AMP_DEBUG_TRACE_WATCHERS")) {
            return new TracingDriver($driver);
        }
        return $driver;
    }
    /**
     * @return (Driver | null)
     */
    private function createDriverFromEnv()
    {
        $driver = \getenv("AMP_LOOP_DRIVER");
        if (!$driver) {
            return null;
        }
        if (!\class_exists($driver)) {
            throw new \Error(\sprintf("Driver '%s' does not exist.", $driver));
        }
        if (!\is_subclass_of($driver, Driver::class)) {
            throw new \Error(\sprintf("Driver '%s' is not a subclass of '%s'.", $driver, Driver::class));
        }
        return new $driver();
    }
}
// @codeCoverageIgnoreEnd<?php

namespace Amp\Loop;

use Amp\CallableMaker;
use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
class NativeDriver extends Driver
{
    use CallableMaker;
    /** @var resource[] */
    private $readStreams = [];
    /** @var Watcher[][] */
    private $readWatchers = [];
    /** @var resource[] */
    private $writeStreams = [];
    /** @var Watcher[][] */
    private $writeWatchers = [];
    /** @var Internal\TimerQueue */
    private $timerQueue;
    /** @var Watcher[][] */
    private $signalWatchers = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /** @var bool */
    private $signalHandling;
    /** @var callable */
    private $streamSelectErrorHandler;
    /** @var bool */
    private $streamSelectIgnoreResult = false;
    /**
     *
     */
    public function __construct()
    {
        $this->timerQueue = new Internal\TimerQueue();
        $this->signalHandling = \extension_loaded("pcntl");
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        $this->streamSelectErrorHandler = function ($errno, $message) {
            // Casing changed in PHP 8 from 'unable' to 'Unable'
            if (\stripos($message, "stream_select(): unable to select [4]: ") === 0) {
                // EINTR
                $this->streamSelectIgnoreResult = true;
                return;
            }
            if (\strpos($message, 'FD_SETSIZE') !== false) {
                $message = \str_replace(["\r\n", "\n", "\r"], " ", $message);
                $pattern = '(stream_select\\(\\): You MUST recompile PHP with a larger value of FD_SETSIZE. It is set to (\\d+), but you have descriptors numbered at least as high as (\\d+)\\.)';
                if (\preg_match($pattern, $message, $match)) {
                    $helpLink = 'https://amphp.org/amp/event-loop/#implementations';
                    $message = 'You have reached the limits of stream_select(). It has a FD_SETSIZE of ' . $match[1] . ', but you have file descriptors numbered at least as high as ' . $match[2] . '. ' . "You can install one of the extensions listed on {$helpLink} to support a higher number of " . 'concurrent file descriptors. If a large number of open file descriptors is unexpected, you might be leaking file descriptors that aren\'t closed correctly.';
                }
            }
            throw new \Exception($message, $errno);
        };
    }
    /**
     * {@inheritdoc}
     *
     * @throws \Amp\Loop\UnsupportedFeatureException If the pcntl extension is not available.
     */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        if (!$this->signalHandling) {
            throw new UnsupportedFeatureException("Signal handling requires the pcntl extension");
        }
        return parent::onSignal($signo, $callback, $data);
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle()
    {
        return null;
    }
    /**
     * @param bool $blocking
     *
     * @return void
     *
     * @throws \Throwable
     */
    protected function dispatch(bool $blocking)
    {
        $this->selectStreams($this->readStreams, $this->writeStreams, $blocking ? $this->getTimeout() : 0);
        $now = $this->now();
        while ($watcher = $this->timerQueue->extract($now)) {
            if ($watcher->type & Watcher::REPEAT) {
                $watcher->enabled = false;
                // Trick base class into adding to enable queue when calling enable()
                $this->enable($watcher->id);
            } else {
                $this->cancel($watcher->id);
            }
            try {
                // Execute the timer.
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
        if ($this->signalHandling) {
            \pcntl_signal_dispatch();
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        foreach ($watchers as $watcher) {
            switch ($watcher->type) {
                case Watcher::READABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    $this->readWatchers[$streamId][$watcher->id] = $watcher;
                    $this->readStreams[$streamId] = $watcher->value;
                    break;
                case Watcher::WRITABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    $this->writeWatchers[$streamId][$watcher->id] = $watcher;
                    $this->writeStreams[$streamId] = $watcher->value;
                    break;
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    $this->timerQueue->insert($watcher);
                    break;
                case Watcher::SIGNAL:
                    \assert(\is_int($watcher->value));
                    if (!isset($this->signalWatchers[$watcher->value])) {
                        if (!@\pcntl_signal($watcher->value, $this->callableFromInstanceMethod('handleSignal'))) {
                            $message = "Failed to register signal handler";
                            if ($error = \error_get_last()) {
                                $message .= \sprintf("; Errno: %d; %s", $error["type"], $error["message"]);
                            }
                            throw new \Error($message);
                        }
                    }
                    $this->signalWatchers[$watcher->value][$watcher->id] = $watcher;
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        switch ($watcher->type) {
            case Watcher::READABLE:
                $streamId = (int) $watcher->value;
                unset($this->readWatchers[$streamId][$watcher->id]);
                if (empty($this->readWatchers[$streamId])) {
                    unset($this->readWatchers[$streamId], $this->readStreams[$streamId]);
                }
                break;
            case Watcher::WRITABLE:
                $streamId = (int) $watcher->value;
                unset($this->writeWatchers[$streamId][$watcher->id]);
                if (empty($this->writeWatchers[$streamId])) {
                    unset($this->writeWatchers[$streamId], $this->writeStreams[$streamId]);
                }
                break;
            case Watcher::DELAY:
            case Watcher::REPEAT:
                $this->timerQueue->remove($watcher);
                break;
            case Watcher::SIGNAL:
                \assert(\is_int($watcher->value));
                if (isset($this->signalWatchers[$watcher->value])) {
                    unset($this->signalWatchers[$watcher->value][$watcher->id]);
                    if (empty($this->signalWatchers[$watcher->value])) {
                        unset($this->signalWatchers[$watcher->value]);
                        @\pcntl_signal($watcher->value, \SIG_DFL);
                    }
                }
                break;
            default:
                // @codeCoverageIgnoreStart
                throw new \Error("Unknown watcher type");
        }
    }
    /**
     * @param resource[] $read
     * @param resource[] $write
     * @param int $timeout
     *
     * @return void
     */
    private function selectStreams(array $read, array $write, int $timeout)
    {
        $timeout /= self::MILLISEC_PER_SEC;
        if (!empty($read) || !empty($write)) {
            // Use stream_select() if there are any streams in the loop.
            if ($timeout >= 0) {
                $seconds = (int) $timeout;
                $microseconds = (int) (($timeout - $seconds) * self::MICROSEC_PER_SEC);
            } else {
                $seconds = null;
                $microseconds = null;
            }
            // Failed connection attempts are indicated via except on Windows
            // @link https://github.com/reactphp/event-loop/blob/8bd064ce23c26c4decf186c2a5a818c9a8209eb0/src/StreamSelectLoop.php#L279-L287
            // @link https://docs.microsoft.com/de-de/windows/win32/api/winsock2/nf-winsock2-select
            $except = null;
            if (\DIRECTORY_SEPARATOR === '\\') {
                $except = $write;
            }
            \set_error_handler($this->streamSelectErrorHandler);
            try {
                $result = \stream_select($read, $write, $except, $seconds, $microseconds);
            } finally {
                \restore_error_handler();
            }
            if ($this->streamSelectIgnoreResult || $result === 0) {
                $this->streamSelectIgnoreResult = false;
                return;
            }
            if (!$result) {
                $this->error(new \Exception('Unknown error during stream_select'));
                return;
            }
            foreach ($read as $stream) {
                $streamId = (int) $stream;
                if (!isset($this->readWatchers[$streamId])) {
                    continue;
                    // All read watchers disabled.
                }
                foreach ($this->readWatchers[$streamId] as $watcher) {
                    if (!isset($this->readWatchers[$streamId][$watcher->id])) {
                        continue;
                        // Watcher disabled by another IO watcher.
                    }
                    try {
                        $result = ($watcher->callback)($watcher->id, $stream, $watcher->data);
                        if ($result === null) {
                            continue;
                        }
                        if ($result instanceof \Generator) {
                            $result = new Coroutine($result);
                        }
                        if ($result instanceof Promise || $result instanceof ReactPromise) {
                            rethrow($result);
                        }
                    } catch (\Throwable $exception) {
                        $this->error($exception);
                    }
                }
            }
            \assert(\is_array($write));
            // See https://github.com/vimeo/psalm/issues/3036
            if ($except) {
                foreach ($except as $key => $socket) {
                    $write[$key] = $socket;
                }
            }
            foreach ($write as $stream) {
                $streamId = (int) $stream;
                if (!isset($this->writeWatchers[$streamId])) {
                    continue;
                    // All write watchers disabled.
                }
                foreach ($this->writeWatchers[$streamId] as $watcher) {
                    if (!isset($this->writeWatchers[$streamId][$watcher->id])) {
                        continue;
                        // Watcher disabled by another IO watcher.
                    }
                    try {
                        $result = ($watcher->callback)($watcher->id, $stream, $watcher->data);
                        if ($result === null) {
                            continue;
                        }
                        if ($result instanceof \Generator) {
                            $result = new Coroutine($result);
                        }
                        if ($result instanceof Promise || $result instanceof ReactPromise) {
                            rethrow($result);
                        }
                    } catch (\Throwable $exception) {
                        $this->error($exception);
                    }
                }
            }
            return;
        }
        if ($timeout < 0) {
            // Only signal watchers are enabled, so sleep indefinitely.
            \usleep(\PHP_INT_MAX);
            return;
        }
        if ($timeout > 0) {
            // Sleep until next timer expires.
            \usleep((int) ($timeout * self::MICROSEC_PER_SEC));
        }
    }
    /**
     * @return int Milliseconds until next timer expires or -1 if there are no pending times.
     */
    private function getTimeout() : int
    {
        $expiration = $this->timerQueue->peek();
        if ($expiration === null) {
            return -1;
        }
        $expiration -= getCurrentTime() - $this->nowOffset;
        return $expiration > 0 ? $expiration : 0;
    }
    /**
     * @param int $signo
     *
     * @return void
     */
    private function handleSignal(int $signo)
    {
        foreach ($this->signalWatchers[$signo] as $watcher) {
            if (!isset($this->signalWatchers[$signo][$watcher->id])) {
                continue;
            }
            try {
                $result = ($watcher->callback)($watcher->id, $signo, $watcher->data);
                if ($result === null) {
                    continue;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        }
    }
}<?php

namespace Amp\Loop\Internal;

use Amp\Loop\Watcher;
/**
 * Uses a binary tree stored in an array to implement a heap.
 */
final class TimerQueue
{
    /** @var Watcher[] */
    private $data = [];
    /** @var int[] */
    private $pointers = [];
    /**
     * @param int $node Rebuild the data array from the given node upward.
     *
     * @return void
     */
    private function heapifyUp(int $node)
    {
        $entry = $this->data[$node];
        while ($node !== 0 && $entry->expiration < $this->data[$parent = $node - 1 >> 1]->expiration) {
            $this->swap($node, $parent);
            $node = $parent;
        }
    }
    /**
     * @param int $node Rebuild the data array from the given node downward.
     *
     * @return void
     */
    private function heapifyDown(int $node)
    {
        $length = \count($this->data);
        while (($child = ($node << 1) + 1) < $length) {
            if ($this->data[$child]->expiration < $this->data[$node]->expiration && ($child + 1 >= $length || $this->data[$child]->expiration < $this->data[$child + 1]->expiration)) {
                // Left child is less than parent and right child.
                $swap = $child;
            } elseif ($child + 1 < $length && $this->data[$child + 1]->expiration < $this->data[$node]->expiration) {
                // Right child is less than parent and left child.
                $swap = $child + 1;
            } else {
                // Left and right child are greater than parent.
                break;
            }
            $this->swap($node, $swap);
            $node = $swap;
        }
    }
    /**
     *
     */
    private function swap(int $left, int $right)
    {
        $temp = $this->data[$left];
        $this->data[$left] = $this->data[$right];
        $this->pointers[$this->data[$right]->id] = $left;
        $this->data[$right] = $temp;
        $this->pointers[$temp->id] = $right;
    }
    /**
     * Inserts the watcher into the queue. Time complexity: O(log(n)).
     *
     * @param Watcher $watcher
     *
     * @psalm-param Watcher<int> $watcher
     *
     * @return void
     */
    public function insert(Watcher $watcher)
    {
        \assert($watcher->expiration !== null);
        \assert(!isset($this->pointers[$watcher->id]));
        $node = \count($this->data);
        $this->data[$node] = $watcher;
        $this->pointers[$watcher->id] = $node;
        $this->heapifyUp($node);
    }
    /**
     * Removes the given watcher from the queue. Time complexity: O(log(n)).
     *
     * @param Watcher $watcher
     *
     * @psalm-param Watcher<int> $watcher
     *
     * @return void
     */
    public function remove(Watcher $watcher)
    {
        $id = $watcher->id;
        if (!isset($this->pointers[$id])) {
            return;
        }
        $this->removeAndRebuild($this->pointers[$id]);
    }
    /**
    * Deletes and returns the Watcher on top of the heap if it has expired, otherwise null is returned.
    Time complexity: O(log(n)).
    *
    * @param int $now Current loop time.
    *
    * @return (Watcher | null) Expired watcher at the top of the heap or null if the watcher has not expired.
    *
    * @psalm-return (Watcher<int> | null)
    */
    public function extract(int $now)
    {
        if (empty($this->data)) {
            return null;
        }
        $watcher = $this->data[0];
        if ($watcher->expiration > $now) {
            return null;
        }
        $this->removeAndRebuild(0);
        return $watcher;
    }
    /**
     * Returns the expiration time value at the top of the heap. Time complexity: O(1).
     *
     * @return (int | null) Expiration time of the watcher at the top of the heap or null if the heap is empty.
     */
    public function peek()
    {
        return isset($this->data[0]) ? $this->data[0]->expiration : null;
    }
    /**
     * @param int $node Remove the given node and then rebuild the data array.
     *
     * @return void
     */
    private function removeAndRebuild(int $node)
    {
        $length = \count($this->data) - 1;
        $id = $this->data[$node]->id;
        $left = $this->data[$node] = $this->data[$length];
        $this->pointers[$left->id] = $node;
        unset($this->data[$length], $this->pointers[$id]);
        if ($node < $length) {
            // don't need to do anything if we removed the last element
            $parent = $node - 1 >> 1;
            if ($parent >= 0 && $this->data[$node]->expiration < $this->data[$parent]->expiration) {
                $this->heapifyUp($node);
            } else {
                $this->heapifyDown($node);
            }
        }
    }
}<?php

namespace Amp\Loop;

/**
 * MUST be thrown if a feature is not supported by the system.
 *
 * This might happen if ext-pcntl is missing and the loop driver doesn't support another way to dispatch signals.
 */
class UnsupportedFeatureException extends \Exception
{
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\Loop;

use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Internal\getCurrentTime;
use function Amp\Promise\rethrow;
class EvDriver extends Driver
{
    /** @var \EvSignal[]|null */
    private static $activeSignals;
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("ev");
    }
    /** @var \EvLoop */
    private $handle;
    /** @var \EvWatcher[] */
    private $events = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /** @var \EvSignal[] */
    private $signals = [];
    /** @var int Internal timestamp for now. */
    private $now;
    /** @var int Loop time offset */
    private $nowOffset;
    /**
     *
     */
    public function __construct()
    {
        $this->handle = new \EvLoop();
        $this->nowOffset = getCurrentTime();
        $this->now = \random_int(0, $this->nowOffset);
        $this->nowOffset -= $this->now;
        if (self::$activeSignals === null) {
            self::$activeSignals =& $this->signals;
        }
        /**
         * @param \EvIO $event
         *
         * @return void
         */
        $this->ioCallback = function (\EvIO $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param \EvTimer $event
         *
         * @return void
         */
        $this->timerCallback = function (\EvTimer $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            if ($watcher->type & Watcher::DELAY) {
                $this->cancel($watcher->id);
            } elseif ($watcher->value === 0) {
                // Disable and re-enable so it's not executed repeatedly in the same tick
                // See https://github.com/amphp/amp/issues/131
                $this->disable($watcher->id);
                $this->enable($watcher->id);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param \EvSignal $event
         *
         * @return void
         */
        $this->signalCallback = function (\EvSignal $event) {
            /** @var Watcher $watcher */
            $watcher = $event->data;
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->value, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        unset($this->events[$watcherId]);
    }
    /**
     *
     */
    public function __destruct()
    {
        foreach ($this->events as $event) {
            /** @psalm-suppress all */
            if ($event !== null) {
                // Events may have been nulled in extension depending on destruct order.
                $event->stop();
            }
        }
        // We need to clear all references to events manually, see
        // https://bitbucket.org/osmanov/pecl-ev/issues/31/segfault-in-ev_timer_stop
        $this->events = [];
    }
    /**
     * {@inheritdoc}
     */
    public function run()
    {
        $active = self::$activeSignals;
        \assert($active !== null);
        foreach ($active as $event) {
            $event->stop();
        }
        self::$activeSignals =& $this->signals;
        foreach ($this->signals as $event) {
            $event->start();
        }
        try {
            parent::run();
        } finally {
            foreach ($this->signals as $event) {
                $event->stop();
            }
            self::$activeSignals =& $active;
            foreach ($active as $event) {
                $event->start();
            }
        }
    }
    /**
     * {@inheritdoc}
     */
    public function stop()
    {
        $this->handle->stop();
        parent::stop();
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        $this->now = getCurrentTime() - $this->nowOffset;
        return $this->now;
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle() : \EvLoop
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        $this->handle->run($blocking ? \Ev::RUN_ONCE : \Ev::RUN_ONCE | \Ev::RUN_NOWAIT);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $this->handle->nowUpdate();
        $now = $this->now();
        foreach ($watchers as $watcher) {
            if (!isset($this->events[$id = $watcher->id])) {
                switch ($watcher->type) {
                    case Watcher::READABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = $this->handle->io($watcher->value, \Ev::READ, $this->ioCallback, $watcher);
                        break;
                    case Watcher::WRITABLE:
                        \assert(\is_resource($watcher->value));
                        $this->events[$id] = $this->handle->io($watcher->value, \Ev::WRITE, $this->ioCallback, $watcher);
                        break;
                    case Watcher::DELAY:
                    case Watcher::REPEAT:
                        \assert(\is_int($watcher->value));
                        $interval = $watcher->value / self::MILLISEC_PER_SEC;
                        $this->events[$id] = $this->handle->timer(\max(0, ($watcher->expiration - $now) / self::MILLISEC_PER_SEC), $watcher->type & Watcher::REPEAT ? $interval : 0, $this->timerCallback, $watcher);
                        break;
                    case Watcher::SIGNAL:
                        \assert(\is_int($watcher->value));
                        $this->events[$id] = $this->handle->signal($watcher->value, $this->signalCallback, $watcher);
                        break;
                    default:
                        // @codeCoverageIgnoreStart
                        throw new \Error("Unknown watcher type");
                }
            } else {
                $this->events[$id]->start();
            }
            if ($watcher->type === Watcher::SIGNAL) {
                /** @psalm-suppress PropertyTypeCoercion */
                $this->signals[$id] = $this->events[$id];
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        if (isset($this->events[$id = $watcher->id])) {
            $this->events[$id]->stop();
            if ($watcher->type === Watcher::SIGNAL) {
                unset($this->signals[$id]);
            }
        }
    }
}<?php

namespace Amp\Loop;

use Amp\Coroutine;
use Amp\Promise;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\Promise\rethrow;
class UvDriver extends Driver
{
    /** @var resource A uv_loop resource created with uv_loop_new() */
    private $handle;
    /** @var resource[] */
    private $events = [];
    /** @var Watcher[][] */
    private $watchers = [];
    /** @var resource[] */
    private $streams = [];
    /** @var callable */
    private $ioCallback;
    /** @var callable */
    private $timerCallback;
    /** @var callable */
    private $signalCallback;
    /**
     *
     */
    public function __construct()
    {
        $this->handle = \uv_loop_new();
        /**
         * @param $event
         * @param $status
         * @param $events
         * @param $resource
         *
         * @return void
         */
        $this->ioCallback = function ($event, $status, $events, $resource) {
            $watchers = $this->watchers[(int) $event];
            switch ($status) {
                case 0:
                    // OK
                    break;
                default:
                    // Invoke the callback on errors, as this matches behavior with other loop back-ends.
                    // Re-enable watcher as libuv disables the watcher on non-zero status.
                    $flags = 0;
                    foreach ($watchers as $watcher) {
                        $flags |= $watcher->enabled ? $watcher->type : 0;
                    }
                    \uv_poll_start($event, $flags, $this->ioCallback);
                    break;
            }
            foreach ($watchers as $watcher) {
                // $events is OR'ed with 4 to trigger watcher if no events are indicated (0) or on UV_DISCONNECT (4).
                // http://docs.libuv.org/en/v1.x/poll.html
                if (!($watcher->enabled && ($watcher->type & $events || ($events | 4) === 4))) {
                    continue;
                }
                try {
                    $result = ($watcher->callback)($watcher->id, $resource, $watcher->data);
                    if ($result === null) {
                        continue;
                    }
                    if ($result instanceof \Generator) {
                        $result = new Coroutine($result);
                    }
                    if ($result instanceof Promise || $result instanceof ReactPromise) {
                        rethrow($result);
                    }
                } catch (\Throwable $exception) {
                    $this->error($exception);
                }
            }
        };
        /**
         * @param $event
         *
         * @return void
         */
        $this->timerCallback = function ($event) {
            $watcher = $this->watchers[(int) $event][0];
            if ($watcher->type & Watcher::DELAY) {
                unset($this->events[$watcher->id], $this->watchers[(int) $event]);
                // Avoid call to uv_is_active().
                $this->cancel($watcher->id);
                // Remove reference to watcher in parent.
            } elseif ($watcher->value === 0) {
                // Disable and re-enable so it's not executed repeatedly in the same tick
                // See https://github.com/amphp/amp/issues/131
                $this->disable($watcher->id);
                $this->enable($watcher->id);
            }
            try {
                $result = ($watcher->callback)($watcher->id, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
        /**
         * @param $event
         * @param $signo
         *
         * @return void
         */
        $this->signalCallback = function ($event, $signo) {
            $watcher = $this->watchers[(int) $event][0];
            try {
                $result = ($watcher->callback)($watcher->id, $signo, $watcher->data);
                if ($result === null) {
                    return;
                }
                if ($result instanceof \Generator) {
                    $result = new Coroutine($result);
                }
                if ($result instanceof Promise || $result instanceof ReactPromise) {
                    rethrow($result);
                }
            } catch (\Throwable $exception) {
                $this->error($exception);
            }
        };
    }
    /**
     * {@inheritdoc}
     */
    public function cancel(string $watcherId)
    {
        parent::cancel($watcherId);
        if (!isset($this->events[$watcherId])) {
            return;
        }
        $event = $this->events[$watcherId];
        $eventId = (int) $event;
        if (isset($this->watchers[$eventId][0])) {
            // All except IO watchers.
            unset($this->watchers[$eventId]);
        } elseif (isset($this->watchers[$eventId][$watcherId])) {
            $watcher = $this->watchers[$eventId][$watcherId];
            unset($this->watchers[$eventId][$watcherId]);
            if (empty($this->watchers[$eventId])) {
                unset($this->watchers[$eventId], $this->streams[(int) $watcher->value]);
            }
        }
        unset($this->events[$watcherId]);
    }
    /**
     *
     */
    public static function isSupported() : bool
    {
        return \extension_loaded("uv");
    }
    /**
     * {@inheritdoc}
     */
    public function now() : int
    {
        \uv_update_time($this->handle);
        /** @psalm-suppress TooManyArguments */
        return \uv_now($this->handle);
    }
    /**
     * {@inheritdoc}
     */
    public function getHandle()
    {
        return $this->handle;
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        /** @psalm-suppress TooManyArguments */
        \uv_run($this->handle, $blocking ? \UV::RUN_ONCE : \UV::RUN_NOWAIT);
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        $now = $this->now();
        foreach ($watchers as $watcher) {
            $id = $watcher->id;
            switch ($watcher->type) {
                case Watcher::READABLE:
                case Watcher::WRITABLE:
                    \assert(\is_resource($watcher->value));
                    $streamId = (int) $watcher->value;
                    if (isset($this->streams[$streamId])) {
                        $event = $this->streams[$streamId];
                    } elseif (isset($this->events[$id])) {
                        $event = $this->streams[$streamId] = $this->events[$id];
                    } else {
                        /** @psalm-suppress UndefinedFunction */
                        $event = $this->streams[$streamId] = \uv_poll_init_socket($this->handle, $watcher->value);
                    }
                    $eventId = (int) $event;
                    $this->events[$id] = $event;
                    $this->watchers[$eventId][$id] = $watcher;
                    $flags = 0;
                    foreach ($this->watchers[$eventId] as $w) {
                        $flags |= $w->enabled ? $w->type : 0;
                    }
                    \uv_poll_start($event, $flags, $this->ioCallback);
                    break;
                case Watcher::DELAY:
                case Watcher::REPEAT:
                    \assert(\is_int($watcher->value));
                    if (isset($this->events[$id])) {
                        $event = $this->events[$id];
                    } else {
                        $event = $this->events[$id] = \uv_timer_init($this->handle);
                    }
                    $this->watchers[(int) $event] = [$watcher];
                    \uv_timer_start($event, \max(0, $watcher->expiration - $now), $watcher->type & Watcher::REPEAT ? $watcher->value : 0, $this->timerCallback);
                    break;
                case Watcher::SIGNAL:
                    \assert(\is_int($watcher->value));
                    if (isset($this->events[$id])) {
                        $event = $this->events[$id];
                    } else {
                        /** @psalm-suppress UndefinedFunction */
                        $event = $this->events[$id] = \uv_signal_init($this->handle);
                    }
                    $this->watchers[(int) $event] = [$watcher];
                    /** @psalm-suppress UndefinedFunction */
                    \uv_signal_start($event, $this->signalCallback, $watcher->value);
                    break;
                default:
                    // @codeCoverageIgnoreStart
                    throw new \Error("Unknown watcher type");
            }
        }
    }
    /**
     * {@inheritdoc}
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        $id = $watcher->id;
        if (!isset($this->events[$id])) {
            return;
        }
        $event = $this->events[$id];
        if (!\uv_is_active($event)) {
            return;
        }
        switch ($watcher->type) {
            case Watcher::READABLE:
            case Watcher::WRITABLE:
                $flags = 0;
                foreach ($this->watchers[(int) $event] as $w) {
                    $flags |= $w->enabled ? $w->type : 0;
                }
                if ($flags) {
                    \uv_poll_start($event, $flags, $this->ioCallback);
                } else {
                    \uv_poll_stop($event);
                }
                break;
            case Watcher::DELAY:
            case Watcher::REPEAT:
                \uv_timer_stop($event);
                break;
            case Watcher::SIGNAL:
                \uv_signal_stop($event);
                break;
            default:
                // @codeCoverageIgnoreStart
                throw new \Error("Unknown watcher type");
        }
    }
}<?php

namespace Amp\Loop;

/**
 * MUST be thrown if any operation (except disable() and cancel()) is attempted with an invalid watcher identifier.
 *
 * An invalid watcher identifier is any identifier that is not yet emitted by the driver or cancelled by the user.
 */
class InvalidWatcherError extends \Error
{
    /** @var string */
    private $watcherId;
    /**
     * @param string $watcherId The watcher identifier.
     * @param string $message The exception message.
     */
    public function __construct(string $watcherId, string $message)
    {
        $this->watcherId = $watcherId;
        parent::__construct($message);
    }
    /**
     * @return string The watcher identifier.
     */
    public function getWatcherId()
    {
        return $this->watcherId;
    }
}<?php

namespace Amp\Loop;

use function Amp\Internal\formatStacktrace;
final class TracingDriver extends Driver
{
    /** @var Driver */
    private $driver;
    /** @var true[] */
    private $enabledWatchers = [];
    /** @var true[] */
    private $unreferencedWatchers = [];
    /** @var string[] */
    private $creationTraces = [];
    /** @var string[] */
    private $cancelTraces = [];
    /**
     *
     */
    public function __construct(Driver $driver)
    {
        $this->driver = $driver;
    }
    /**
     *
     */
    public function run()
    {
        $this->driver->run();
    }
    /**
     *
     */
    public function stop()
    {
        $this->driver->stop();
    }
    /**
     *
     */
    public function defer(callable $callback, $data = null) : string
    {
        $id = $this->driver->defer(function (...$args) use($callback) {
            $this->cancel($args[0]);
            return $callback(...$args);
        }, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function delay(int $delay, callable $callback, $data = null) : string
    {
        $id = $this->driver->delay($delay, function (...$args) use($callback) {
            $this->cancel($args[0]);
            return $callback(...$args);
        }, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function repeat(int $interval, callable $callback, $data = null) : string
    {
        $id = $this->driver->repeat($interval, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function onReadable($stream, callable $callback, $data = null) : string
    {
        $id = $this->driver->onReadable($stream, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function onWritable($stream, callable $callback, $data = null) : string
    {
        $id = $this->driver->onWritable($stream, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function onSignal(int $signo, callable $callback, $data = null) : string
    {
        $id = $this->driver->onSignal($signo, $callback, $data);
        $this->creationTraces[$id] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        $this->enabledWatchers[$id] = true;
        return $id;
    }
    /**
     *
     */
    public function enable(string $watcherId)
    {
        try {
            $this->driver->enable($watcherId);
            $this->enabledWatchers[$watcherId] = true;
        } catch (InvalidWatcherError $e) {
            throw new InvalidWatcherError($watcherId, $e->getMessage() . "\r\n\r\n" . $this->getTraces($watcherId));
        }
    }
    /**
     *
     */
    public function cancel(string $watcherId)
    {
        $this->driver->cancel($watcherId);
        if (!isset($this->cancelTraces[$watcherId])) {
            $this->cancelTraces[$watcherId] = formatStacktrace(\debug_backtrace(\DEBUG_BACKTRACE_IGNORE_ARGS));
        }
        unset($this->enabledWatchers[$watcherId], $this->unreferencedWatchers[$watcherId]);
    }
    /**
     *
     */
    public function disable(string $watcherId)
    {
        $this->driver->disable($watcherId);
        unset($this->enabledWatchers[$watcherId]);
    }
    /**
     *
     */
    public function reference(string $watcherId)
    {
        try {
            $this->driver->reference($watcherId);
            unset($this->unreferencedWatchers[$watcherId]);
        } catch (InvalidWatcherError $e) {
            throw new InvalidWatcherError($watcherId, $e->getMessage() . "\r\n\r\n" . $this->getTraces($watcherId));
        }
    }
    /**
     *
     */
    public function unreference(string $watcherId)
    {
        $this->driver->unreference($watcherId);
        $this->unreferencedWatchers[$watcherId] = true;
    }
    /**
     *
     */
    public function setErrorHandler(callable $callback = null)
    {
        return $this->driver->setErrorHandler($callback);
    }
    /**
     * @inheritdoc
     */
    public function getHandle()
    {
        $this->driver->getHandle();
    }
    /**
     *
     */
    public function dump() : string
    {
        $dump = "Enabled, referenced watchers keeping the loop running: ";
        foreach ($this->enabledWatchers as $watcher => $_) {
            if (isset($this->unreferencedWatchers[$watcher])) {
                continue;
            }
            $dump .= "Watcher ID: " . $watcher . "\r\n";
            $dump .= $this->getCreationTrace($watcher);
            $dump .= "\r\n\r\n";
        }
        return \rtrim($dump);
    }
    /**
     *
     */
    public function getInfo() : array
    {
        return $this->driver->getInfo();
    }
    /**
     *
     */
    public function __debugInfo()
    {
        return $this->driver->__debugInfo();
    }
    /**
     *
     */
    public function now() : int
    {
        return $this->driver->now();
    }
    /**
     *
     */
    protected function error(\Throwable $exception)
    {
        $this->driver->error($exception);
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function activate(array $watchers)
    {
        // nothing to do in a decorator
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function dispatch(bool $blocking)
    {
        // nothing to do in a decorator
    }
    /**
     * @inheritdoc
     *
     * @return void
     */
    protected function deactivate(Watcher $watcher)
    {
        // nothing to do in a decorator
    }
    /**
     *
     */
    private function getTraces(string $watcherId) : string
    {
        return "Creation Trace:\r\n" . $this->getCreationTrace($watcherId) . '

Cancellation Trace:
' . $this->getCancelTrace($watcherId);
    }
    /**
     *
     */
    private function getCreationTrace(string $watcher) : string
    {
        if (!isset($this->creationTraces[$watcher])) {
            return 'No creation trace, yet.';
        }
        return $this->creationTraces[$watcher];
    }
    /**
     *
     */
    private function getCancelTrace(string $watcher) : string
    {
        if (!isset($this->cancelTraces[$watcher])) {
            return 'No cancellation trace, yet.';
        }
        return $this->cancelTraces[$watcher];
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a promise from a generator function yielding promises.
 *
 * When a promise is yielded, execution of the generator is interrupted until the promise is resolved. A success
 * value is sent into the generator, while a failure reason is thrown into the generator. Using a coroutine,
 * asynchronous code can be written without callbacks and be structured like synchronous code.
 *
 * @template-covariant TReturn
 * @template-implements Promise<TReturn>
 */
final class Coroutine implements Promise
{
    use Internal\Placeholder;
    /**
    * Attempts to transform the non-promise yielded from the generator into a promise, otherwise returns an instance
    `Amp\Failure` failed with an instance of `Amp\InvalidYieldError`.
    *
    * @param mixed $yielded Non-promise yielded from generator.
    * @param \Generator $generator No type for performance, we already know the type.
    *
    * @return Promise
    */
    private static function transform($yielded, $generator) : Promise
    {
        $exception = null;
        // initialize here, see https://github.com/vimeo/psalm/issues/2951
        try {
            if (\is_array($yielded)) {
                return Promise\all($yielded);
            }
            if ($yielded instanceof ReactPromise) {
                return Promise\adapt($yielded);
            }
            // No match, continue to returning Failure below.
        } catch (\Throwable $exception) {
            // Conversion to promise failed, fall-through to returning Failure below.
        }
        return new Failure(new InvalidYieldError($generator, \sprintf("Unexpected yield; Expected an instance of %s or %s or an array of such instances", Promise::class, ReactPromise::class), $exception));
    }
    /**
     * @param \Generator $generator
     * @psalm-param \Generator<mixed, (Promise | ReactPromise | array<array-key, (Promise | ReactPromise)>), mixed, (Promise<TReturn> | ReactPromise | TReturn)> $generator
     */
    public function __construct(\Generator $generator)
    {
        try {
            $yielded = $generator->current();
            if (!$yielded instanceof Promise) {
                if (!$generator->valid()) {
                    $this->resolve($generator->getReturn());
                    return;
                }
                $yielded = self::transform($yielded, $generator);
            }
        } catch (\Throwable $exception) {
            $this->fail($exception);
            return;
        }
        /**
         * @param \Throwable|null $e Exception to be thrown into the generator.
         * @param mixed           $v Value to be sent into the generator.
         *
         * @return void
         *
         * @psalm-suppress MissingClosureParamType
         * @psalm-suppress MissingClosureReturnType
         */
        $onResolve = function (\Throwable $e = null, $v) use($generator, &$onResolve) {
            /** @var bool $immediate Used to control iterative coroutine continuation. */
            static $immediate = true;
            /** @var \Throwable|null $exception Promise failure reason when executing next coroutine step, null at all other times. */
            static $exception;
            /** @var mixed $value Promise success value when executing next coroutine step, null at all other times. */
            static $value;
            $exception = $e;
            /** @psalm-suppress MixedAssignment */
            $value = $v;
            if (!$immediate) {
                $immediate = true;
                return;
            }
            try {
                try {
                    do {
                        if ($exception) {
                            // Throw exception at current execution point.
                            $yielded = $generator->throw($exception);
                        } else {
                            // Send the new value and execute to next yield statement.
                            $yielded = $generator->send($value);
                        }
                        if (!$yielded instanceof Promise) {
                            if (!$generator->valid()) {
                                $this->resolve($generator->getReturn());
                                $onResolve = null;
                                return;
                            }
                            $yielded = self::transform($yielded, $generator);
                        }
                        $immediate = false;
                        $yielded->onResolve($onResolve);
                    } while ($immediate);
                    $immediate = true;
                } catch (\Throwable $exception) {
                    $this->fail($exception);
                    $onResolve = null;
                } finally {
                    $exception = null;
                    $value = null;
                }
            } catch (\Throwable $e) {
                Loop::defer(static function () use($e) {
                    throw $e;
                });
            }
        };
        try {
            $yielded->onResolve($onResolve);
            unset($generator, $yielded, $onResolve);
        } catch (\Throwable $e) {
            Loop::defer(static function () use($e) {
                throw $e;
            });
        }
    }
}<?php

namespace Amp;

/**
 * Cancellation tokens are simple objects that allow registering handlers to subscribe to cancellation requests.
 */
interface CancellationToken
{
    /**
    * Subscribes a new handler to be invoked on a cancellation request.
    *
    * This handler might be invoked immediately in case the token has already been cancelled. Returned generators will
    automatically be run as coroutines. Any unhandled exceptions will be throw into the event loop.
    *
    * @param callable(CancelledException) $callback Callback to be invoked on a cancellation request. Will receive a
    `CancelledException` as first argument that may be used to fail the operation's promise.
    *
    * @return string Identifier that can be used to cancel the subscription.
    */
    public function subscribe(callable $callback) : string;
    /**
     * Unsubscribes a previously registered handler.
     *
     * The handler will no longer be called as long as this method isn't invoked from a subscribed callback.
     *
     * @param string $id
     *
     * @return void
     */
    public function unsubscribe(string $id);
    /**
     * Returns whether cancellation has been requested yet.
     *
     * @return bool
     */
    public function isRequested() : bool;
    /**
     * Throws the `CancelledException` if cancellation has been requested, otherwise does nothing.
     *
     * @return void
     *
     * @throws CancelledException
     */
    public function throwIfRequested();
}<?php

namespace Amp;

/**
 * Deferred is a container for a promise that is resolved using the resolve() and fail() methods of this object.
 * The contained promise may be accessed using the promise() method. This object should not be part of a public
 * API, but used internally to create and resolve a promise.
 *
 * @template TValue
 */
final class Deferred
{
    /** @var Promise<TValue> Has public resolve and fail methods. */
    private $resolver;
    /** @var Promise<TValue> Hides placeholder methods */
    private $promise;
    /**
     *
     */
    public function __construct()
    {
        $this->resolver = new class implements Promise
        {
            use Internal\Placeholder {
                resolve as public;
                fail as public;
                isResolved as public;
            }
        };
        $this->promise = new Internal\PrivatePromise($this->resolver);
    }
    /**
     * @return Promise<TValue>
     */
    public function promise() : Promise
    {
        return $this->promise;
    }
    /**
     * Fulfill the promise with the given value.
     *
     * @param mixed $value
     *
     * @psalm-param (TValue | Promise<TValue>) $value
     *
     * @return void
     */
    public function resolve($value = null)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->resolver->resolve($value);
    }
    /**
     * Fails the promise the the given reason.
     *
     * @param \Throwable $reason
     *
     * @return void
     */
    public function fail(\Throwable $reason)
    {
        /** @psalm-suppress UndefinedInterfaceMethod */
        $this->resolver->fail($reason);
    }
    /**
     * @return bool True if the promise has been resolved.
     */
    public function isResolved() : bool
    {
        return $this->resolver->isResolved();
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
/**
 * Creates a failed promise using the given exception.
 *
 * @template-covariant TValue
 * @template-implements Promise<TValue>
 */
final class Failure implements Promise
{
    /** @var \Throwable $exception */
    private $exception;
    /**
     * @param \Throwable $exception Rejection reason.
     */
    public function __construct(\Throwable $exception)
    {
        $this->exception = $exception;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        try {
            /** @var mixed $result */
            $result = $onResolved($this->exception, null);
            if ($result === null) {
                return;
            }
            if ($result instanceof \Generator) {
                $result = new Coroutine($result);
            }
            if ($result instanceof Promise || $result instanceof ReactPromise) {
                Promise\rethrow($result);
            }
        } catch (\Throwable $exception) {
            Loop::defer(static function () use($exception) {
                throw $exception;
            });
        }
    }
}<?php

namespace Amp;

class MultiReasonException extends \Exception
{
    /** @var \Throwable[] */
    private $reasons;
    /**
     * @param \Throwable[] $reasons Array of exceptions rejecting the promise.
     * @param (string | null) $message
     */
    public function __construct(array $reasons, string $message = null)
    {
        parent::__construct($message ?: "Multiple errors encountered; use " . self::class . "::getReasons() to retrieve the array of exceptions thrown");
        $this->reasons = $reasons;
    }
    /**
     * @return \Throwable[]
     */
    public function getReasons() : array
    {
        return $this->reasons;
    }
}<?php

namespace Amp;

use React\Promise\PromiseInterface as ReactPromise;
/**
* Returns a new function that wraps $callback in a promise/coroutine-aware function that automatically runs
Generators as coroutines. The returned function always returns a promise when invoked. Errors have to be handled
by the callback caller or they will go unnoticed.
*
* Use this function to create a coroutine-aware callable for a promise-aware callback caller.
*
* @template TReturn
* @template TPromise
* @template TGeneratorReturn
* @template TGeneratorPromise
*
* @template TGenerator of (TGeneratorReturn | Promise<TGeneratorPromise>)
* @template T of (TReturn | Promise<TPromise> | \Generator<mixed, mixed, mixed, TGenerator>)
*
* @formatter :off
*
* @param callable(...mixed): T $callback
*
* @return callable
* @psalm-return (T is Promise ? (callable(mixed...): Promise<TPromise>) : (T is \Generator ? (TGenerator is Promise ? (callable(mixed...): Promise<TGeneratorPromise>) : (callable(mixed...): Promise<TGeneratorReturn>)) : (callable(mixed...): Promise<TReturn>)))
*
* @formatter :on
*
* @see asyncCoroutine()
*
* @psalm-suppress InvalidReturnType
*/
function coroutine(callable $callback) : callable
{
    /** @psalm-suppress InvalidReturnStatement */
    return static function (...$args) use($callback) : Promise {
        return call($callback, ...$args);
    };
}
/**
* Returns a new function that wraps $callback in a promise/coroutine-aware function that automatically runs
Generators as coroutines. The returned function always returns void when invoked. Errors are forwarded to the
loop's error handler using `Amp\Promise\rethrow()`.
*
* Use this function to create a coroutine-aware callable for a non-promise-aware callback caller.
*
* @param callable(...mixed): mixed $callback
*
* @return callable
* @psalm-return callable(mixed ...): void
*
* @see coroutine()
*/
function asyncCoroutine(callable $callback) : callable
{
    return static function (...$args) use($callback) {
        Promise\rethrow(call($callback, ...$args));
    };
}
/**
* Calls the given function, always returning a promise. If the function returns a Generator, it will be run as a
coroutine. If the function throws, a failed promise will be returned.
*
* @template TReturn
* @template TPromise
* @template TGeneratorReturn
* @template TGeneratorPromise
*
* @template TGenerator of (TGeneratorReturn | Promise<TGeneratorPromise>)
* @template T of (TReturn | Promise<TPromise> | \Generator<mixed, mixed, mixed, TGenerator>)
*
* @formatter :off
*
* @param callable(...mixed): T $callback
* @param mixed ...$args Arguments to pass to the function.
*
* @return Promise
* @psalm-return (T is Promise ? Promise<TPromise> : (T is \Generator ? (TGenerator is Promise ? Promise<TGeneratorPromise> : Promise<TGeneratorReturn>) : Promise<TReturn>))
*
* @formatter :on
*/
function call(callable $callback, ...$args) : Promise
{
    try {
        $result = $callback(...$args);
    } catch (\Throwable $exception) {
        return new Failure($exception);
    }
    if ($result instanceof \Generator) {
        return new Coroutine($result);
    }
    if ($result instanceof Promise) {
        return $result;
    }
    if ($result instanceof ReactPromise) {
        return Promise\adapt($result);
    }
    return new Success($result);
}
/**
* Calls the given function. If the function returns a Generator, it will be run as a coroutine. If the function
throws or returns a failing promise, the failure is forwarded to the loop error handler.
*
* @param callable(...mixed): mixed $callback
* @param mixed ...$args Arguments to pass to the function.
*
* @return void
*/
function asyncCall(callable $callback, ...$args)
{
    Promise\rethrow(call($callback, ...$args));
}
/**
 * Sleeps for the specified number of milliseconds.
 *
 * @param int $milliseconds
 *
 * @return Delayed
 */
function delay(int $milliseconds) : Delayed
{
    return new Delayed($milliseconds);
}
/**
 * Returns the current time relative to an arbitrary point in time.
 *
 * @return int Time in milliseconds.
 */
function getCurrentTime() : int
{
    return Internal\getCurrentTime();
}
namespace Amp\Promise;

use Amp\Deferred;
use Amp\Loop;
use Amp\MultiReasonException;
use Amp\Promise;
use Amp\Success;
use Amp\TimeoutException;
use React\Promise\PromiseInterface as ReactPromise;
use function Amp\call;
use function Amp\Internal\createTypeError;
/**
* Registers a callback that will forward the failure reason to the event loop's error handler if the promise fails.
*
* Use this function if you neither return the promise nor handle a possible error yourself to prevent errors from
going entirely unnoticed.
*
* @param (Promise | ReactPromise) $promise Promise to register the handler on.
*
* @return void
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
*
*/
function rethrow($promise)
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $promise->onResolve(static function ($exception) {
        if ($exception) {
            throw $exception;
        }
    });
}
/**
* Runs the event loop until the promise is resolved. Should not be called within a running event loop.
*
* Use this function only in synchronous contexts to wait for an asynchronous operation. Use coroutines and yield to
await promise resolution in a fully asynchronous application instead.
*
* @template TPromise
* @template T of (Promise<TPromise> | ReactPromise)
*
* @param (Promise | ReactPromise) $promise Promise to wait for.
*
* @return mixed Promise success value.
*
* @psalm-param T $promise
* @psalm-return (T is Promise ? TPromise : mixed)
*
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
* @throws \Error If the event loop stopped without the $promise being resolved.
* @throws \Throwable Promise failure reason.
*/
function wait($promise)
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $resolved = false;
    try {
        Loop::run(function () use(&$resolved, &$value, &$exception, $promise) {
            $promise->onResolve(function ($e, $v) use(&$resolved, &$value, &$exception) {
                Loop::stop();
                $resolved = true;
                $exception = $e;
                $value = $v;
            });
        });
    } catch (\Throwable $throwable) {
        throw new \Error("Loop exceptionally stopped without resolving the promise", 0, $throwable);
    }
    if (!$resolved) {
        throw new \Error("Loop stopped without resolving the promise");
    }
    if ($exception) {
        throw $exception;
    }
    return $value;
}
/**
* Creates an artificial timeout for any `Promise`.
*
* If the timeout expires before the promise is resolved, the returned promise fails with an instance of
`Amp\TimeoutException`.
*
* @template TReturn
*
* @param (Promise<TReturn> | ReactPromise) $promise Promise to which the timeout is applied.
* @param int $timeout Timeout in milliseconds.
*
* @return Promise<TReturn>
*
* @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
*/
function timeout($promise, int $timeout) : Promise
{
    if (!$promise instanceof Promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } else {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
    }
    $deferred = new Deferred();
    $watcher = Loop::delay($timeout, static function () use(&$deferred) {
        $temp = $deferred;
        // prevent double resolve
        $deferred = null;
        $temp->fail(new TimeoutException());
    });
    Loop::unreference($watcher);
    $promise->onResolve(function () use(&$deferred, $promise, $watcher) {
        if ($deferred !== null) {
            Loop::cancel($watcher);
            $deferred->resolve($promise);
        }
    });
    return $deferred->promise();
}
/**
 * Creates an artificial timeout for any `Promise`.
 *
 * If the promise is resolved before the timeout expires, the result is returned
 *
 * If the timeout expires before the promise is resolved, a default value is returned
 *
 * @template TReturn
 *
 * @param (Promise<TReturn> | ReactPromise) $promise Promise to which the timeout is applied.
 * @param int $timeout Timeout in milliseconds.
 * @param TReturn $default
 *
 * @return Promise<TReturn>
 *
 * @throws \TypeError If $promise is not an instance of \Amp\Promise or \React\Promise\PromiseInterface.
 */
function timeoutWithDefault($promise, int $timeout, $default = null) : Promise
{
    $promise = timeout($promise, $timeout);
    return call(static function () use($promise, $default) {
        try {
            return (yield $promise);
        } catch (TimeoutException $exception) {
            return $default;
        }
    });
}
/**
* Adapts any object with a done(callable $onFulfilled, callable $onRejected) or then(callable $onFulfilled,
callable $onRejected) method to a promise usable by components depending on placeholders implementing
\AsyncInterop\Promise.
*
* @param object $promise Object with a done() or then() method.
*
* @return Promise Promise resolved by the $thenable object.
*
* @throws \Error If the provided object does not have a then() method.
*/
function adapt($promise) : Promise
{
    if (!\is_object($promise)) {
        throw new \Error("Object must be provided");
    }
    $deferred = new Deferred();
    if (\method_exists($promise, 'done')) {
        $promise->done([$deferred, 'resolve'], [$deferred, 'fail']);
    } elseif (\method_exists($promise, 'then')) {
        $promise->then([$deferred, 'resolve'], [$deferred, 'fail']);
    } else {
        throw new \Error("Object must have a 'then' or 'done' method");
    }
    return $deferred->promise();
}
/**
* Returns a promise that is resolved when all promises are resolved. The returned promise will not fail.
Returned promise succeeds with a two-item array delineating successful and failed promise results,
with keys identical and corresponding to the original given array.
*
* This function is the same as some() with the notable exception that it will never fail even
if all promises in the array resolve unsuccessfully.
*
* @template TValue
*
* @param (Promise<TValue>[] | ReactPromise[]) $promises
*
* @return Promise<array{0: \Throwable[], 1: TValue[]}>
*
* @throws \Error If a non-Promise is in the array.
*/
function any(array $promises) : Promise
{
    return some($promises, 0);
}
/**
* Returns a promise that succeeds when all promises succeed, and fails if any promise fails. Returned
promise succeeds with an array of values used to succeed each contained promise, with keys corresponding to
the array of promises.
*
* @param (Promise[] | ReactPromise[]) $promises Array of only promises.
*
* @return Promise
*
* @throws \Error If a non-Promise is in the array.
*
* @template TValue
*
* @psalm-param array<array-key, (Promise<TValue> | ReactPromise)> $promises
* @psalm-assert array<array-key, Promise<TValue>|ReactPromise> $promises $promises
* @psalm-return Promise<array<array-key, TValue>>
*/
function all(array $promises) : Promise
{
    if (empty($promises)) {
        return new Success([]);
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $pending = \count($promises);
    $values = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $values[$key] = null;
        // add entry to array to preserve order
        $promise->onResolve(function ($exception, $value) use(&$deferred, &$values, &$pending, $key) {
            if ($pending === 0) {
                return;
            }
            if ($exception) {
                $pending = 0;
                $deferred->fail($exception);
                $deferred = null;
                return;
            }
            $values[$key] = $value;
            if (0 === --$pending) {
                $deferred->resolve($values);
            }
        });
    }
    return $result;
}
/**
 * Returns a promise that succeeds when the first promise succeeds, and fails only if all promises fail.
 *
 * @template TValue
 *
 * @param (Promise<TValue>[] | ReactPromise[]) $promises Array of only promises.
 *
 * @return Promise<TValue>
 *
 * @throws \Error If the array is empty or a non-Promise is in the array.
 */
function first(array $promises) : Promise
{
    if (empty($promises)) {
        throw new \Error("No promises provided");
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $pending = \count($promises);
    $exceptions = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $exceptions[$key] = null;
        // add entry to array to preserve order
        $promise->onResolve(function ($error, $value) use(&$deferred, &$exceptions, &$pending, $key) {
            if ($pending === 0) {
                return;
            }
            if (!$error) {
                $pending = 0;
                $deferred->resolve($value);
                $deferred = null;
                return;
            }
            $exceptions[$key] = $error;
            if (0 === --$pending) {
                $deferred->fail(new MultiReasonException($exceptions));
            }
        });
    }
    return $result;
}
/**
* Resolves with a two-item array delineating successful and failed Promise results.
*
* The returned promise will only fail if the given number of required promises fail.
*
* @template TValue
*
* @param (Promise<TValue>[] | ReactPromise[]) $promises Array of only promises.
* @param int $required Number of promises that must succeed for the
returned promise to succeed.
*
* @return Promise<array{0: \Throwable[], 1: TValue[]}>
*
* @throws \Error If a non-Promise is in the array.
*/
function some(array $promises, int $required = 1) : Promise
{
    if ($required < 0) {
        throw new \Error("Number of promises required must be non-negative");
    }
    $pending = \count($promises);
    if ($required > $pending) {
        throw new \Error("Too few promises provided");
    }
    if (empty($promises)) {
        return new Success([[], []]);
    }
    $deferred = new Deferred();
    $result = $deferred->promise();
    $values = [];
    $exceptions = [];
    foreach ($promises as $key => $promise) {
        if ($promise instanceof ReactPromise) {
            $promise = adapt($promise);
        } elseif (!$promise instanceof Promise) {
            throw createTypeError([Promise::class, ReactPromise::class], $promise);
        }
        $values[$key] = $exceptions[$key] = null;
        // add entry to arrays to preserve order
        $promise->onResolve(static function ($exception, $value) use(&$values, &$exceptions, &$pending, $key, $required, $deferred) {
            if ($exception) {
                $exceptions[$key] = $exception;
                unset($values[$key]);
            } else {
                $values[$key] = $value;
                unset($exceptions[$key]);
            }
            if (0 === --$pending) {
                if (\count($values) < $required) {
                    $deferred->fail(new MultiReasonException($exceptions));
                } else {
                    $deferred->resolve([$exceptions, $values]);
                }
            }
        });
    }
    return $result;
}
/**
 * Wraps a promise into another promise, altering the exception or result.
 *
 * @param (Promise | ReactPromise) $promise
 * @param callable $callback
 *
 * @return Promise
 */
function wrap($promise, callable $callback) : Promise
{
    if ($promise instanceof ReactPromise) {
        $promise = adapt($promise);
    } elseif (!$promise instanceof Promise) {
        throw createTypeError([Promise::class, ReactPromise::class], $promise);
    }
    $deferred = new Deferred();
    $promise->onResolve(static function (\Throwable $exception = null, $result) use($deferred, $callback) {
        try {
            $result = $callback($exception, $result);
        } catch (\Throwable $exception) {
            $deferred->fail($exception);
            return;
        }
        $deferred->resolve($result);
    });
    return $deferred->promise();
}
namespace Amp\Iterator;

use Amp\Delayed;
use Amp\Emitter;
use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use function Amp\call;
use function Amp\coroutine;
use function Amp\Internal\createTypeError;
/**
* Creates an iterator from the given iterable, emitting the each value. The iterable may contain promises. If any
promise fails, the iterator will fail with the same reason.
*
* @param (array | \Traversable) $iterable Elements to emit.
* @param int $delay Delay between element emissions in milliseconds.
*
* @return Iterator
*
* @throws \TypeError If the argument is not an array or instance of \Traversable.
*/
function fromIterable($iterable, int $delay = 0) : Iterator
{
    if (!$iterable instanceof \Traversable && !\is_array($iterable)) {
        throw createTypeError(["array", "Traversable"], $iterable);
    }
    if ($delay) {
        return new Producer(static function (callable $emit) use($iterable, $delay) {
            foreach ($iterable as $value) {
                (yield new Delayed($delay));
                (yield $emit($value));
            }
        });
    }
    return new Producer(static function (callable $emit) use($iterable) {
        foreach ($iterable as $value) {
            (yield $emit($value));
        }
    });
}
/**
 * @template TValue
 * @template TReturn
 *
 * @param Iterator<TValue> $iterator
 * @param callable(TValue $value): TReturn $onEmit
 *
 * @return Iterator<TReturn>
 */
function map(Iterator $iterator, callable $onEmit) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $onEmit) {
        while ((yield $iterator->advance())) {
            (yield $emit($onEmit($iterator->getCurrent())));
        }
    });
}
/**
 * @template TValue
 *
 * @param Iterator<TValue> $iterator
 * @param callable(TValue $value): bool $filter
 *
 * @return Iterator<TValue>
 */
function filter(Iterator $iterator, callable $filter) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $filter) {
        while ((yield $iterator->advance())) {
            if ($filter($iterator->getCurrent())) {
                (yield $emit($iterator->getCurrent()));
            }
        }
    });
}
/**
 * Creates an iterator that emits values emitted from any iterator in the array of iterators.
 *
 * @param Iterator[] $iterators
 *
 * @return Iterator
 */
function merge(array $iterators) : Iterator
{
    $emitter = new Emitter();
    $result = $emitter->iterate();
    $coroutine = coroutine(static function (Iterator $iterator) use(&$emitter) {
        while ((yield $iterator->advance()) && $emitter !== null) {
            (yield $emitter->emit($iterator->getCurrent()));
        }
    });
    $coroutines = [];
    foreach ($iterators as $iterator) {
        if (!$iterator instanceof Iterator) {
            throw createTypeError([Iterator::class], $iterator);
        }
        $coroutines[] = $coroutine($iterator);
    }
    Promise\all($coroutines)->onResolve(static function ($exception) use(&$emitter) {
        if ($exception) {
            $emitter->fail($exception);
            $emitter = null;
        } else {
            $emitter->complete();
        }
    });
    return $result;
}
/**
* Concatenates the given iterators into a single iterator, emitting values from a single iterator at a time. The
prior iterator must complete before values are emitted from any subsequent iterators. Iterators are concatenated
in the order given (iteration order of the array).
*
* @param Iterator[] $iterators
*
* @return Iterator
*/
function concat(array $iterators) : Iterator
{
    foreach ($iterators as $iterator) {
        if (!$iterator instanceof Iterator) {
            throw createTypeError([Iterator::class], $iterator);
        }
    }
    $emitter = new Emitter();
    $previous = [];
    $promise = Promise\all($previous);
    $coroutine = coroutine(static function (Iterator $iterator, callable $emit) {
        while ((yield $iterator->advance())) {
            (yield $emit($iterator->getCurrent()));
        }
    });
    foreach ($iterators as $iterator) {
        $emit = coroutine(static function ($value) use($emitter, $promise) {
            static $pending = true, $failed = false;
            if ($failed) {
                return;
            }
            if ($pending) {
                try {
                    (yield $promise);
                    $pending = false;
                } catch (\Throwable $exception) {
                    $failed = true;
                    return;
                    // Prior iterator failed.
                }
            }
            (yield $emitter->emit($value));
        });
        $previous[] = $coroutine($iterator, $emit);
        $promise = Promise\all($previous);
    }
    $promise->onResolve(static function ($exception) use($emitter) {
        if ($exception) {
            $emitter->fail($exception);
            return;
        }
        $emitter->complete();
    });
    return $emitter->iterate();
}
/**
 * Discards all remaining items and returns the number of discarded items.
 *
 * @template TValue
 *
 * @param Iterator $iterator
 *
 * @return Promise
 *
 * @psalm-param Iterator<TValue> $iterator
 * @psalm-return Promise<int>
 */
function discard(Iterator $iterator) : Promise
{
    return call(static function () use($iterator) : \Generator {
        $count = 0;
        while ((yield $iterator->advance())) {
            $count++;
        }
        return $count;
    });
}
/**
 * Collects all items from an iterator into an array.
 *
 * @template TValue
 *
 * @param Iterator $iterator
 *
 * @psalm-param Iterator<TValue> $iterator
 *
 * @return Promise
 * @psalm-return Promise<array<array-key, TValue>>
 */
function toArray(Iterator $iterator) : Promise
{
    return call(static function () use($iterator) {
        /** @psalm-var list $array */
        $array = [];
        while ((yield $iterator->advance())) {
            $array[] = $iterator->getCurrent();
        }
        return $array;
    });
}<?php

namespace Amp;

class InvalidYieldError extends \Error
{
    /**
     * @param \Generator $generator
     * @param string $prefix
     * @param (\Throwable | null) $previous
     */
    public function __construct(\Generator $generator, string $prefix, \Throwable $previous = null)
    {
        $yielded = $generator->current();
        $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), \var_export($generator->key(), true));
        if (!$generator->valid()) {
            parent::__construct($prefix, 0, $previous);
            return;
        }
        $reflGen = new \ReflectionGenerator($generator);
        $exeGen = $reflGen->getExecutingGenerator();
        if ($isSubgenerator = $exeGen !== $generator) {
            $reflGen = new \ReflectionGenerator($exeGen);
        }
        parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile()), 0, $previous);
    }
}<?php

namespace Amp;

final class CombinedCancellationToken implements CancellationToken
{
    /** @var array{0: CancellationToken, 1: string}[] */
    private $tokens = [];
    /** @var string */
    private $nextId = "a";
    /** @var callable[] */
    private $callbacks = [];
    /** @var CancelledException|null */
    private $exception;
    /**
     *
     */
    public function __construct(CancellationToken ...$tokens)
    {
        foreach ($tokens as $token) {
            $id = $token->subscribe(function (CancelledException $exception) {
                $this->exception = $exception;
                $callbacks = $this->callbacks;
                $this->callbacks = [];
                foreach ($callbacks as $callback) {
                    asyncCall($callback, $this->exception);
                }
            });
            $this->tokens[] = [$token, $id];
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        foreach ($this->tokens as list($token, $id)) {
            /** @var CancellationToken $token */
            $token->unsubscribe($id);
        }
    }
    /**
     * @inheritdoc
     */
    public function subscribe(callable $callback) : string
    {
        $id = $this->nextId++;
        if ($this->exception) {
            asyncCall($callback, $this->exception);
        } else {
            $this->callbacks[$id] = $callback;
        }
        return $id;
    }
    /**
     * @inheritdoc
     */
    public function unsubscribe(string $id)
    {
        unset($this->callbacks[$id]);
    }
    /**
     * @inheritdoc
     */
    public function isRequested() : bool
    {
        foreach ($this->tokens as list($token)) {
            if ($token->isRequested()) {
                return true;
            }
        }
        return false;
    }
    /**
     * @inheritdoc
     */
    public function throwIfRequested()
    {
        foreach ($this->tokens as list($token)) {
            $token->throwIfRequested();
        }
    }
}<?php

namespace Amp;

/**
 * Thrown if a promise doesn't resolve within a specified timeout.
 *
 * @see \Amp\Promise\timeout()
 */
class TimeoutException extends \Exception
{
    /**
     * @param string $message Exception message.
     */
    public function __construct(string $message = "Operation timed out")
    {
        parent::__construct($message);
    }
}<?php

namespace Amp;

use Amp\Loop\Driver;
use Amp\Loop\DriverFactory;
use Amp\Loop\InvalidWatcherError;
use Amp\Loop\UnsupportedFeatureException;
use Amp\Loop\Watcher;
/**
 * Accessor to allow global access to the event loop.
 *
 * @see \Amp\Loop\Driver
 */
final class Loop
{
    /**
     * @var Driver
     */
    private static $driver;
    /**
     * Disable construction as this is a static class.
     */
    private function __construct()
    {
        // intentionally left blank
    }
    /**
     * Sets the driver to be used for `Loop::run()`.
     *
     * @param Driver $driver
     *
     * @return void
     */
    public static function set(Driver $driver)
    {
        try {
            self::$driver = new class extends Driver
            {
                /**
                 * @return void
                 */
                protected function activate(array $watchers)
                {
                    throw new \Error("Can't activate watcher during garbage collection.");
                }
                /**
                 * @return void
                 */
                protected function dispatch(bool $blocking)
                {
                    throw new \Error("Can't dispatch during garbage collection.");
                }
                /**
                 * @return void
                 */
                protected function deactivate(Watcher $watcher)
                {
                    // do nothing
                }
                /**
                 *
                 */
                public function getHandle()
                {
                    return null;
                }
            };
            \gc_collect_cycles();
        } finally {
            self::$driver = $driver;
        }
    }
    /**
    * Run the event loop and optionally execute a callback within the scope of it.
    *
    * The loop MUST continue to run until it is either stopped explicitly, no referenced watchers exist anymore, or an
    exception is thrown that cannot be handled. Exceptions that cannot be handled are exceptions thrown from an
    error handler or exceptions that would be passed to an error handler but none exists to handle them.
    *
    * @param (callable | null) $callback The callback to execute.
    *
    * @return void
    */
    public static function run(callable $callback = null)
    {
        if ($callback) {
            self::$driver->defer($callback);
        }
        self::$driver->run();
    }
    /**
    * Stop the event loop.
    *
    * When an event loop is stopped, it continues with its current tick and exits the loop afterwards. Multiple calls
    to stop MUST be ignored and MUST NOT raise an exception.
    *
    * @return void
    */
    public static function stop()
    {
        self::$driver->stop();
    }
    /**
    * Defer the execution of a callback.
    *
    * The deferred callable MUST be executed before any other type of watcher in a tick. Order of enabling MUST be
    preserved when executing the callbacks.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param callable(string $watcherId, mixed $data) $callback The callback to defer. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function defer(callable $callback, $data = null) : string
    {
        return self::$driver->defer($callback, $data);
    }
    /**
    * Delay the execution of a callback.
    *
    * The delay is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be determined by which
    timers expire first, but timers with the same expiration time MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $delay The amount of time, in milliseconds, to delay the execution for.
    * @param callable(string $watcherId, mixed $data) $callback The callback to delay. The `$watcherId` will be
    invalidated before the callback call.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function delay(int $delay, callable $callback, $data = null) : string
    {
        return self::$driver->delay($delay, $callback, $data);
    }
    /**
    * Repeatedly execute a callback.
    *
    * The interval between executions is a minimum and approximate, accuracy is not guaranteed. Order of calls MUST be
    determined by which timers expire first, but timers with the same expiration time MAY be executed in any order.
    The first execution is scheduled after the first interval period.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $interval The time interval, in milliseconds, to wait between executions.
    * @param callable(string $watcherId, mixed $data) $callback The callback to repeat.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function repeat(int $interval, callable $callback, $data = null) : string
    {
        return self::$driver->repeat($interval, $callback, $data);
    }
    /**
    * Execute a callback when a stream resource becomes readable or is closed for reading.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable(string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function onReadable($stream, callable $callback, $data = null) : string
    {
        return self::$driver->onReadable($stream, $callback, $data);
    }
    /**
    * Execute a callback when a stream resource becomes writable or is closed for writing.
    *
    * Warning: Closing resources locally, e.g. with `fclose`, might not invoke the callback. Be sure to `cancel` the
    watcher when closing the resource locally. Drivers MAY choose to notify the user if there are watchers on invalid
    resources, but are not required to, due to the high performance impact. Watchers on closed resources are
    therefore undefined behavior.
    *
    * Multiple watchers on the same stream MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param resource $stream The stream to monitor.
    * @param callable(string $watcherId, resource $stream, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the `$data` parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    */
    public static function onWritable($stream, callable $callback, $data = null) : string
    {
        return self::$driver->onWritable($stream, $callback, $data);
    }
    /**
    * Execute a callback when a signal is received.
    *
    * Warning: Installing the same signal on different instances of this interface is deemed undefined behavior.
    Implementations MAY try to detect this, if possible, but are not required to. This is due to technical
    limitations of the signals being registered globally per process.
    *
    * Multiple watchers on the same signal MAY be executed in any order.
    *
    * The created watcher MUST immediately be marked as enabled, but only be activated (i.e. callback can be called)
    right before the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param int $signo The signal number to monitor.
    * @param callable(string $watcherId, int $signo, mixed $data) $callback The callback to execute.
    * @param mixed $data Arbitrary data given to the callback function as the $data parameter.
    *
    * @return string An unique identifier that can be used to cancel, enable or disable the watcher.
    *
    * @throws UnsupportedFeatureException If signal handling is not supported.
    */
    public static function onSignal(int $signo, callable $callback, $data = null) : string
    {
        return self::$driver->onSignal($signo, $callback, $data);
    }
    /**
    * Enable a watcher to be active starting in the next tick.
    *
    * Watchers MUST immediately be marked as enabled, but only be activated (i.e. callbacks can be called) right before
    the next tick. Callbacks of watchers MUST NOT be called in the tick they were enabled.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public static function enable(string $watcherId)
    {
        self::$driver->enable($watcherId);
    }
    /**
    * Disable a watcher immediately.
    *
    * A watcher MUST be disabled immediately, e.g. if a defer watcher disables a later defer watcher, the second defer
    watcher isn't executed in this tick.
    *
    * Disabling a watcher MUST NOT invalidate the watcher. Calling this function MUST NOT fail, even if passed an
    invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function disable(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->disable($watcherId);
    }
    /**
    * Cancel a watcher.
    *
    * This will detatch the event loop from all resources that are associated to the watcher. After this operation the
    watcher is permanently invalid. Calling this function MUST NOT fail, even if passed an invalid watcher.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function cancel(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->cancel($watcherId);
    }
    /**
    * Reference a watcher.
    *
    * This will keep the event loop alive whilst the watcher is still being monitored. Watchers have this state by
    default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    *
    * @throws InvalidWatcherError If the watcher identifier is invalid.
    */
    public static function reference(string $watcherId)
    {
        self::$driver->reference($watcherId);
    }
    /**
    * Unreference a watcher.
    *
    * The event loop should exit the run method when only unreferenced watchers are still being monitored. Watchers
    are all referenced by default.
    *
    * @param string $watcherId The watcher identifier.
    *
    * @return void
    */
    public static function unreference(string $watcherId)
    {
        if (\PHP_VERSION_ID < 70200 && !isset(self::$driver)) {
            // Prior to PHP 7.2, self::$driver may be unset during destruct.
            // See https://github.com/amphp/amp/issues/212.
            return;
        }
        self::$driver->unreference($watcherId);
    }
    /**
    * Returns the current loop time in millisecond increments. Note this value does not necessarily correlate to
    wall-clock time, rather the value returned is meant to be used in relative comparisons to prior values returned
    by this method (intervals, expiration calculations, etc.) and is only updated once per loop tick.
    *
    * @return int
    */
    public static function now() : int
    {
        return self::$driver->now();
    }
    /**
    * Stores information in the loop bound registry.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    * @param mixed $value The value to be stored.
    *
    * @return void
    */
    public static function setState(string $key, $value)
    {
        self::$driver->setState($key, $value);
    }
    /**
    * Gets information stored bound to the loop.
    *
    * Stored information is package private. Packages MUST NOT retrieve the stored state of other packages. Packages
    MUST use their namespace as prefix for keys. They may do so by using `SomeClass::class` as key.
    *
    * If packages want to expose loop bound state to consumers other than the package, they SHOULD provide a dedicated
    interface for that purpose instead of sharing the storage key.
    *
    * @param string $key The namespaced storage key.
    *
    * @return mixed The previously stored value or `null` if it doesn't exist.
    */
    public static function getState(string $key)
    {
        return self::$driver->getState($key);
    }
    /**
    * Set a callback to be executed when an error occurs.
    *
    * The callback receives the error as the first and only parameter. The return value of the callback gets ignored.
    If it can't handle the error, it MUST throw the error. Errors thrown by the callback or during its invocation
    MUST be thrown into the `run` loop and stop the driver.
    *
    * Subsequent calls to this method will overwrite the previous handler.
    *
    * @param callable(\Throwable $error)|null $callback The callback to execute. `null` will clear the
    current handler.
    *
    * @return callable (\Throwable $error)|null The previous handler, `null` if there was none.
    */
    public static function setErrorHandler(callable $callback = null)
    {
        return self::$driver->setErrorHandler($callback);
    }
    /**
    * Retrieve an associative array of information about the event loop driver.
    *
    * The returned array MUST contain the following data describing the driver's currently registered watchers:
    *
    * [
    "defer"            => ["enabled" => int, "disabled" => int],
    "delay"            => ["enabled" => int, "disabled" => int],
    "repeat"           => ["enabled" => int, "disabled" => int],
    "on_readable"      => ["enabled" => int, "disabled" => int],
    "on_writable"      => ["enabled" => int, "disabled" => int],
    "on_signal"        => ["enabled" => int, "disabled" => int],
    "enabled_watchers" => ["referenced" => int, "unreferenced" => int],
    "running"          => bool
    ];
    *
    * Implementations MAY optionally add more information in the array but at minimum the above `key => value` format
    MUST always be provided.
    *
    * @return array Statistics about the loop in the described format.
    */
    public static function getInfo() : array
    {
        return self::$driver->getInfo();
    }
    /**
     * Retrieve the event loop driver that is in scope.
     *
     * @return Driver
     */
    public static function get() : Driver
    {
        return self::$driver;
    }
}
// Default factory, don't move this to a file loaded by the composer "files" autoload mechanism, otherwise custom
// implementations might have issues setting a default loop, because it's overridden by us then.
// @codeCoverageIgnoreStart
Loop::set((new DriverFactory())->create());
// @codeCoverageIgnoreEnd<?php

namespace Amp;

/**
 * Creates a promise that resolves itself with a given value after a number of milliseconds.
 *
 * @template-covariant TReturn
 * @template-implements Promise<TReturn>
 */
final class Delayed implements Promise
{
    use Internal\Placeholder;
    /** @var string|null Event loop watcher identifier. */
    private $watcher;
    /**
     * @param int $time Milliseconds before succeeding the promise.
     * @param TReturn $value Succeed the promise with this value.
     */
    public function __construct(int $time, $value = null)
    {
        $this->watcher = Loop::delay($time, function () use($value) {
            $this->watcher = null;
            $this->resolve($value);
        });
    }
    /**
     * References the internal watcher in the event loop, keeping the loop running while this promise is pending.
     *
     * @return self
     */
    public function reference() : self
    {
        if ($this->watcher !== null) {
            Loop::reference($this->watcher);
        }
        return $this;
    }
    /**
    * Unreferences the internal watcher in the event loop, allowing the loop to stop while this promise is pending if
    no other events are pending in the loop.
    *
    * @return self
    */
    public function unreference() : self
    {
        if ($this->watcher !== null) {
            Loop::unreference($this->watcher);
        }
        return $this;
    }
}<?php

namespace Amp;

/**
 * Defines an asynchronous iterator over a set of values that is designed to be used within a coroutine.
 *
 * @template-covariant TValue
 */
interface Iterator
{
    /**
    * Succeeds with true if an emitted value is available by calling getCurrent() or false if the iterator has
    resolved. If the iterator fails, the returned promise will fail with the same exception.
    *
    * @return Promise
    * @psalm-return Promise<bool>
    *
    * @throws \Error If the prior promise returned from this method has not resolved.
    * @throws \Throwable The exception used to fail the iterator.
    */
    public function advance() : Promise;
    /**
     * Gets the last emitted value or throws an exception if the iterator has completed.
     *
     * @return mixed Value emitted from the iterator.
     * @psalm-return TValue
     *
     * @throws \Error If the iterator has resolved or advance() was not called before calling this method.
     * @throws \Throwable The exception used to fail the iterator.
     */
    public function getCurrent();
}<?php

namespace Amp;

// @codeCoverageIgnoreStart
if (\PHP_VERSION_ID < 70100) {
    /** @psalm-suppress DuplicateClass */
    trait CallableMaker
    {
        /** @var \ReflectionClass */
        private static $__reflectionClass;
        /** @var \ReflectionMethod[] */
        private static $__reflectionMethods = [];
        /**
        * Creates a callable from a protected or private instance method that may be invoked by callers requiring a
        publicly invokable callback.
        *
        * @param string $method Instance method name.
        *
        * @return callable
        *
        * @psalm-suppress MixedInferredReturnType
        */
        private function callableFromInstanceMethod(string $method) : callable
        {
            if (!isset(self::$__reflectionMethods[$method])) {
                if (self::$__reflectionClass === null) {
                    self::$__reflectionClass = new \ReflectionClass(self::class);
                }
                self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method);
            }
            return self::$__reflectionMethods[$method]->getClosure($this);
        }
        /**
        * Creates a callable from a protected or private static method that may be invoked by methods requiring a
        publicly invokable callback.
        *
        * @param string $method Static method name.
        *
        * @return callable
        *
        * @psalm-suppress MixedInferredReturnType
        */
        private static function callableFromStaticMethod(string $method) : callable
        {
            if (!isset(self::$__reflectionMethods[$method])) {
                if (self::$__reflectionClass === null) {
                    self::$__reflectionClass = new \ReflectionClass(self::class);
                }
                self::$__reflectionMethods[$method] = self::$__reflectionClass->getMethod($method);
            }
            return self::$__reflectionMethods[$method]->getClosure();
        }
    }
} else {
    /** @psalm-suppress DuplicateClass */
    trait CallableMaker
    {
        /**
         * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1.
         */
        private function callableFromInstanceMethod(string $method) : callable
        {
            return \Closure::fromCallable([$this, $method]);
        }
        /**
         * @deprecated Use \Closure::fromCallable() instead of this method in PHP 7.1.
         */
        private static function callableFromStaticMethod(string $method) : callable
        {
            return \Closure::fromCallable([self::class, $method]);
        }
    }
}
// @codeCoverageIgnoreEnd<?php

namespace Amp;

/**
 * Will be thrown in case an operation is cancelled.
 *
 * @see CancellationToken
 * @see CancellationTokenSource
 */
class CancelledException extends \Exception
{
    /**
     *
     */
    public function __construct(\Throwable $previous = null)
    {
        parent::__construct("The operation was cancelled", 0, $previous);
    }
}<?php

namespace Amp;

/**
 * Creates a promise that calls $promisor only when the result of the promise is requested (i.e. onResolve() is called
 * on the promise). $promisor can return a promise or any value. If $promisor throws an exception, the promise fails
 * with that exception. If $promisor returns a Generator, it will be run as a coroutine.
 */
final class LazyPromise implements Promise
{
    /** @var callable|null */
    private $promisor;
    /** @var Promise|null */
    private $promise;
    /**
    * @param callable $promisor Function which starts an async operation, returning a Promise (or any value).
    Generators will be run as a coroutine.
    */
    public function __construct(callable $promisor)
    {
        $this->promisor = $promisor;
    }
    /**
     * {@inheritdoc}
     */
    public function onResolve(callable $onResolved)
    {
        if ($this->promise === null) {
            \assert($this->promisor !== null);
            $provider = $this->promisor;
            $this->promisor = null;
            $this->promise = call($provider);
        }
        \assert($this->promise !== null);
        $this->promise->onResolve($onResolved);
    }
}<?php

namespace Amp;

/**
 * A "safe" struct trait for public property aggregators.
 *
 * This trait is intended to make using public properties a little safer by throwing when
 * nonexistent property names are read or written.
 */
trait Struct
{
    /**
     * The minimum percentage [0-100] at which to recommend a similar property
     * name when generating error messages.
     */
    private $__propertySuggestThreshold = 70;
    /**
     * @param string $property
     *
     * @psalm-return no-return
     */
    public function __get(string $property)
    {
        throw new \Error($this->generateStructPropertyError($property));
    }
    /**
     * @param string $property
     * @param mixed $value
     *
     * @psalm-return no-return
     */
    public function __set(string $property, $value)
    {
        throw new \Error($this->generateStructPropertyError($property));
    }
    /**
     *
     */
    private function generateStructPropertyError(string $property) : string
    {
        $suggestion = $this->suggestPropertyName($property);
        $suggestStr = $suggestion == "" ? "" : " ... did you mean \"{$suggestion}?\"";
        return \sprintf(
            "%s property \"%s\" does not exist%s",
            \str_replace("\x00", "@", \get_class($this)),
            // Handle anonymous class names.
            $property,
            $suggestStr
        );
    }
    /**
     *
     */
    private function suggestPropertyName(string $badProperty) : string
    {
        $badProperty = \strtolower($badProperty);
        $bestMatch = "";
        $bestMatchPercentage = 0;
        /** @psalm-suppress RawObjectIteration */
        foreach ($this as $property => $value) {
            // Never suggest properties that begin with an underscore
            if ($property[0] === "_") {
                continue;
            }
            \similar_text($badProperty, \strtolower($property), $byRefPercentage);
            if ($byRefPercentage > $bestMatchPercentage) {
                $bestMatchPercentage = $byRefPercentage;
                $bestMatch = $property;
            }
        }
        return $bestMatchPercentage >= $this->__propertySuggestThreshold ? $bestMatch : "";
    }
}<?php

namespace Amp\Http\Client;

final class MissingAttributeError extends \Error
{
    /**
     *
     */
    public function __construct(string $message)
    {
        parent::__construct($message);
    }
}<?php

namespace Amp\Http\Client;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\ByteStream\Payload;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Message;
use Amp\Http\Status;
use Amp\Promise;
use Amp\Success;
/**
 * An HTTP response.
 */
final class Response extends Message
{
    use ForbidSerialization;
    use ForbidCloning;
    /** @var string */
    private $protocolVersion;
    /** @var int */
    private $status;
    /** @var string */
    private $reason;
    /** @var Request */
    private $request;
    /** @var Payload */
    private $body;
    /** @var Promise<Trailers> */
    private $trailers;
    /** @var Response|null */
    private $previousResponse;
    /**
     *
     */
    public function __construct(string $protocolVersion, int $status, ?string $reason, array $headers, InputStream $body, Request $request, ?Promise $trailerPromise = null, ?Response $previousResponse = null)
    {
        $this->setProtocolVersion($protocolVersion);
        $this->setStatus($status, $reason);
        $this->setHeaders($headers);
        $this->setBody($body);
        $this->request = $request;
        /** @noinspection PhpUnhandledExceptionInspection */
        $this->trailers = $trailerPromise ?? new Success(new Trailers([]));
        $this->previousResponse = $previousResponse;
    }
    /**
     * Retrieve the requests's HTTP protocol version.
     *
     * @return string
     */
    public function getProtocolVersion() : string
    {
        return $this->protocolVersion;
    }
    /**
     *
     */
    public function setProtocolVersion(string $protocolVersion) : void
    {
        if (!\in_array($protocolVersion, ["1.0", "1.1", "2"], true)) {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \Error("Invalid HTTP protocol version: " . $protocolVersion);
        }
        $this->protocolVersion = $protocolVersion;
    }
    /**
     * Retrieve the response's three-digit HTTP status code.
     *
     * @return int
     */
    public function getStatus() : int
    {
        return $this->status;
    }
    /**
     *
     */
    public function setStatus(int $status, ?string $reason = null) : void
    {
        $this->status = $status;
        $this->reason = $reason ?? Status::getReason($status);
    }
    /**
     * Retrieve the response's (possibly empty) reason phrase.
     *
     * @return string
     */
    public function getReason() : string
    {
        return $this->reason;
    }
    /**
     * Retrieve the Request instance that resulted in this Response instance.
     *
     * @return Request
     */
    public function getRequest() : Request
    {
        return $this->request;
    }
    /**
     *
     */
    public function setRequest(Request $request) : void
    {
        $this->request = $request;
    }
    /**
    * Retrieve the original Request instance associated with this Response instance.
    *
    * A given Response may be the result of one or more redirects. This method is a shortcut to
    access information from the original Request that led to this response.
    *
    * @return Request
    */
    public function getOriginalRequest() : Request
    {
        if (empty($this->previousResponse)) {
            return $this->request;
        }
        return $this->previousResponse->getOriginalRequest();
    }
    /**
    * Retrieve the original Response instance associated with this Response instance.
    *
    * A given Response may be the result of one or more redirects. This method is a shortcut to
    access information from the original Response that led to this response.
    *
    * @return Response
    */
    public function getOriginalResponse() : Response
    {
        if (empty($this->previousResponse)) {
            return $this;
        }
        return $this->previousResponse->getOriginalResponse();
    }
    /**
     * If this Response is the result of a redirect traverse up the redirect history.
     *
     * @return (Response | null)
     */
    public function getPreviousResponse() : ?Response
    {
        return $this->previousResponse;
    }
    /**
     *
     */
    public function setPreviousResponse(?Response $previousResponse) : void
    {
        $this->previousResponse = $previousResponse;
    }
    /**
     * Assign a value for the specified header field by replacing any existing values for that field.
     *
     * @param string $name Header name.
     * @param (string | string[]) $value Header value.
     */
    public function setHeader(string $name, $value) : void
    {
        if (($name[0] ?? ":") === ":") {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::setHeader($name, $value);
    }
    /**
     * Assign a value for the specified header field by adding an additional header line.
     *
     * @param string $name Header name.
     * @param (string | string[]) $value Header value.
     */
    public function addHeader(string $name, $value) : void
    {
        if (($name[0] ?? ":") === ":") {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::addHeader($name, $value);
    }
    /**
     *
     */
    public function setHeaders(array $headers) : void
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        parent::setHeaders($headers);
    }
    /**
     * Remove the specified header field from the message.
     *
     * @param string $name Header name.
     */
    public function removeHeader(string $name) : void
    {
        parent::removeHeader($name);
    }
    /**
     * Retrieve the response body.
     *
     * Note: If you stream a Message, you can't consume the payload twice.
     *
     * @return Payload
     */
    public function getBody() : Payload
    {
        return $this->body;
    }
    /**
     * @param (Payload | InputStream | string | int | float | bool) $body
     */
    public function setBody($body) : void
    {
        if ($body instanceof Payload) {
            $this->body = $body;
        } elseif ($body === null) {
            $this->body = new Payload(new InMemoryStream());
        } elseif (\is_string($body)) {
            $this->body = new Payload(new InMemoryStream($body));
        } elseif (\is_scalar($body)) {
            $this->body = new Payload(new InMemoryStream(\var_export($body, true)));
        } elseif ($body instanceof InputStream) {
            $this->body = new Payload($body);
        } else {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \TypeError("Invalid body type: " . \gettype($body));
        }
    }
    /**
     * @return Promise<Trailers>
     */
    public function getTrailers() : Promise
    {
        return $this->trailers;
    }
    /**
     * @param Promise<Trailers> $promise
     */
    public function setTrailers(Promise $promise) : void
    {
        $this->trailers = $promise;
    }
}<?php

namespace Amp\Http\Client;

final class SocketException extends HttpException
{
}<?php

namespace Amp\Http\Client;

final class ParseException extends HttpException
{
    /**
     * @param string $message
     * @param int $code
     * @param (\Throwable | null) $previousException
     */
    public function __construct(string $message, int $code, \Throwable $previousException = null)
    {
        parent::__construct($message, $code, $previousException);
    }
}<?php

namespace Amp\Http\Client\EventListener;

use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\EventListener;
use Amp\Http\Client\Internal\HarAttributes;
use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Success;
use function Amp\getCurrentTime;
final class RecordHarAttributes implements EventListener
{
    /**
     *
     */
    public function startRequest(Request $request) : Promise
    {
        if (!$request->hasAttribute(HarAttributes::STARTED_DATE_TIME)) {
            $request->setAttribute(HarAttributes::STARTED_DATE_TIME, new \DateTimeImmutable());
        }
        return $this->addTiming(HarAttributes::TIME_START, $request);
    }
    /**
     *
     */
    public function startDnsResolution(Request $request) : Promise
    {
        return new Success();
        // not implemented
    }
    /**
     *
     */
    public function startConnectionCreation(Request $request) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_CONNECT, $request);
    }
    /**
     *
     */
    public function startTlsNegotiation(Request $request) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_SSL, $request);
    }
    /**
     *
     */
    public function startSendingRequest(Request $request, Stream $stream) : Promise
    {
        $host = $stream->getRemoteAddress()->getHost();
        if (\strrpos($host, ':')) {
            $host = '[' . $host . ']';
        }
        $request->setAttribute(HarAttributes::SERVER_IP_ADDRESS, $host);
        return $this->addTiming(HarAttributes::TIME_SEND, $request);
    }
    /**
     *
     */
    public function completeSendingRequest(Request $request, Stream $stream) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_WAIT, $request);
    }
    /**
     *
     */
    public function startReceivingResponse(Request $request, Stream $stream) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_RECEIVE, $request);
    }
    /**
     *
     */
    public function completeReceivingResponse(Request $request, Stream $stream) : Promise
    {
        return $this->addTiming(HarAttributes::TIME_COMPLETE, $request);
    }
    /**
     *
     */
    public function completeDnsResolution(Request $request) : Promise
    {
        return new Success();
        // not implemented
    }
    /**
     *
     */
    public function completeConnectionCreation(Request $request) : Promise
    {
        return new Success();
        // not implemented
    }
    /**
     *
     */
    public function completeTlsNegotiation(Request $request) : Promise
    {
        return new Success();
        // not implemented
    }
    /**
     *
     */
    private function addTiming(string $key, Request $request) : Promise
    {
        if (!$request->hasAttribute($key)) {
            $request->setAttribute($key, getCurrentTime());
        }
        return new Success();
    }
    /**
     *
     */
    public function abort(Request $request, \Throwable $cause) : Promise
    {
        return new Success();
    }
}<?php

namespace Amp\Http\Client;

use Amp\Http\Client\Body\StringBody;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Message;
use Amp\Promise;
use League\Uri;
use Psr\Http\Message\UriInterface;
use function Amp\call;
/**
 * An HTTP request.
 */
final class Request extends Message
{
    use ForbidSerialization;
    public const DEFAULT_HEADER_SIZE_LIMIT = 2 * 8192;
    public const DEFAULT_BODY_SIZE_LIMIT = 10485760;
    /**
     * @template TValue
     *
     * @param mixed $value
     * @psalm-param TValue $value
     *
     * @return mixed
     * @psalm-return TValue
     */
    private static function clone($value)
    {
        if ($value === null || \is_scalar($value)) {
            return $value;
        }
        // force deep cloning
        return \unserialize(\serialize($value), ['allowed_classes' => true]);
    }
    /** @var string[] */
    private $protocolVersions = ['1.1', '2'];
    /** @var string */
    private $method;
    /** @var UriInterface */
    private $uri;
    /** @var RequestBody */
    private $body;
    /** @var int */
    private $tcpConnectTimeout = 10000;
    /** @var int */
    private $tlsHandshakeTimeout = 10000;
    /** @var int */
    private $transferTimeout = 10000;
    /** @var int */
    private $inactivityTimeout = 10000;
    /** @var int */
    private $bodySizeLimit = self::DEFAULT_BODY_SIZE_LIMIT;
    /** @var int */
    private $headerSizeLimit = self::DEFAULT_HEADER_SIZE_LIMIT;
    /** @var callable|null */
    private $onPush;
    /** @var callable|null */
    private $onUpgrade;
    /** @var callable|null */
    private $onInformationalResponse;
    /** @var mixed[] */
    private $attributes = [];
    /** @var EventListener[] */
    private $eventListeners = [];
    /**
     * Request constructor.
     *
     * @param (string | UriInterface) $uri
     * @param string $method
     * @param string $body
     */
    public function __construct($uri, string $method = "GET", ?string $body = null)
    {
        $this->setUri($uri);
        $this->setMethod($method);
        $this->setBody($body);
    }
    /**
     *
     */
    public function addEventListener(EventListener $eventListener) : void
    {
        $this->eventListeners[] = $eventListener;
    }
    /**
     * @return EventListener[]
     */
    public function getEventListeners() : array
    {
        return $this->eventListeners;
    }
    /**
     * Retrieve the requests's acceptable HTTP protocol versions.
     *
     * @return string[]
     */
    public function getProtocolVersions() : array
    {
        return $this->protocolVersions;
    }
    /**
     * Assign the requests's acceptable HTTP protocol versions.
     *
     * The HTTP client might choose any of these.
     *
     * @param string[] $versions
     */
    public function setProtocolVersions(array $versions) : void
    {
        $versions = \array_unique($versions);
        if (empty($versions)) {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \Error("Empty array of protocol versions provided, must not be empty.");
        }
        foreach ($versions as $version) {
            if (!\in_array($version, ["1.0", "1.1", "2"], true)) {
                /** @noinspection PhpUndefinedClassInspection */
                throw new \Error("Invalid HTTP protocol version: " . $version);
            }
        }
        $this->protocolVersions = $versions;
    }
    /**
     * Retrieve the request's HTTP method verb.
     *
     * @return string
     */
    public function getMethod() : string
    {
        return $this->method;
    }
    /**
     * Specify the request's HTTP method verb.
     *
     * @param string $method
     */
    public function setMethod(string $method) : void
    {
        $this->method = $method;
    }
    /**
     * Retrieve the request's URI.
     *
     * @return UriInterface
     */
    public function getUri() : UriInterface
    {
        return $this->uri;
    }
    /**
     * Specify the request's HTTP URI.
     *
     * @param (string | UriInterface) $uri
     */
    public function setUri($uri) : void
    {
        $this->uri = $uri instanceof UriInterface ? $uri : $this->createUriFromString($uri);
    }
    /**
     * Assign a value for the specified header field by replacing any existing values for that field.
     *
     * @param string $name Header name.
     * @param (string | string[]) $value Header value.
     */
    public function setHeader(string $name, $value) : void
    {
        if (($name[0] ?? ":") === ":") {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::setHeader($name, $value);
    }
    /**
     * Assign a value for the specified header field by adding an additional header line.
     *
     * @param string $name Header name.
     * @param (string | string[]) $value Header value.
     */
    public function addHeader(string $name, $value) : void
    {
        if (($name[0] ?? ":") === ":") {
            throw new \Error("Header name cannot be empty or start with a colon (:)");
        }
        parent::addHeader($name, $value);
    }
    /**
     *
     */
    public function setHeaders(array $headers) : void
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        parent::setHeaders($headers);
    }
    /**
     * Remove the specified header field from the message.
     *
     * @param string $name Header name.
     */
    public function removeHeader(string $name) : void
    {
        parent::removeHeader($name);
    }
    /**
     * Retrieve the message entity body.
     */
    public function getBody() : RequestBody
    {
        return $this->body;
    }
    /**
     * Assign the message entity body.
     *
     * @param mixed $body
     */
    public function setBody($body) : void
    {
        if ($body === null) {
            $this->body = new StringBody("");
        } elseif (\is_string($body)) {
            $this->body = new StringBody($body);
        } elseif (\is_scalar($body)) {
            $this->body = new StringBody(\var_export($body, true));
        } elseif ($body instanceof RequestBody) {
            $this->body = $body;
        } else {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \TypeError("Invalid body type: " . \gettype($body));
        }
    }
    /**
    * Registers a callback to the request that is invoked when the server pushes an additional resource.
    The callback is given two parameters: the Request generated from the pushed resource, and a promise for the
    Response containing the pushed resource. An HttpException, StreamException, or CancelledException can be thrown
    to refuse the push. If no callback is registered, pushes are automatically rejected.
    *
    * Interceptors can mostly use {@code interceptPush} instead.
    *
    * Example:
    function (Request $request, Promise $response): \Generator {
    $uri = $request->getUri(); // URI of pushed resource.
    $response = yield $promise; // Wait for resource to arrive.
    // Use Response object from resolved promise.
    }
    *
    * @param (callable | null) $onPush
    */
    public function setPushHandler(?callable $onPush) : void
    {
        $this->onPush = $onPush;
    }
    /**
    * Allows interceptors to modify also pushed responses.
    *
    * If no push callable has been set by the application, the interceptor won't be invoked. If you want to enable
    push in an interceptor without the application setting a push handler, you need to use {@code setPushHandler}.
    *
    * @param callable $interceptor Receives the response and might modify it or return a new instance.
    */
    public function interceptPush(callable $interceptor) : void
    {
        if ($this->onPush === null) {
            return;
        }
        $onPush = $this->onPush;
        /** @psalm-suppress MissingClosureReturnType */
        $this->onPush = static function (Request $request, Promise $response) use($onPush, $interceptor) {
            $response = call(static function () use($response, $interceptor) : \Generator {
                return (yield call($interceptor, (yield $response))) ?? $response;
            });
            return $onPush($request, $response);
        };
    }
    /**
     * @return (callable | null)
     */
    public function getPushHandler() : ?callable
    {
        return $this->onPush;
    }
    /**
     * Registers a callback invoked if a 101 response is returned to the request.
     *
     * @param (callable | null) $onUpgrade
     */
    public function setUpgradeHandler(?callable $onUpgrade) : void
    {
        $this->onUpgrade = $onUpgrade;
    }
    /**
     * @return (callable | null)
     */
    public function getUpgradeHandler() : ?callable
    {
        return $this->onUpgrade;
    }
    /**
     * Registers a callback invoked when a 1xx response is returned to the request (other than a 101).
     *
     * @param (callable | null) $onInformationalResponse
     */
    public function setInformationalResponseHandler(?callable $onInformationalResponse) : void
    {
        $this->onInformationalResponse = $onInformationalResponse;
    }
    /**
     * @return (callable | null)
     */
    public function getInformationalResponseHandler() : ?callable
    {
        return $this->onInformationalResponse;
    }
    /**
     * @return int Timeout in milliseconds for the TCP connection.
     */
    public function getTcpConnectTimeout() : int
    {
        return $this->tcpConnectTimeout;
    }
    /**
     *
     */
    public function setTcpConnectTimeout(int $tcpConnectTimeout) : void
    {
        $this->tcpConnectTimeout = $tcpConnectTimeout;
    }
    /**
     * @return int Timeout in milliseconds for the TLS handshake.
     */
    public function getTlsHandshakeTimeout() : int
    {
        return $this->tlsHandshakeTimeout;
    }
    /**
     *
     */
    public function setTlsHandshakeTimeout(int $tlsHandshakeTimeout) : void
    {
        $this->tlsHandshakeTimeout = $tlsHandshakeTimeout;
    }
    /**
     * @return int Timeout in milliseconds for the HTTP transfer (not counting TCP connect and TLS handshake)
     */
    public function getTransferTimeout() : int
    {
        return $this->transferTimeout;
    }
    /**
     *
     */
    public function setTransferTimeout(int $transferTimeout) : void
    {
        $this->transferTimeout = $transferTimeout;
    }
    /**
     * @return int Timeout in milliseconds since the last data was received before the request fails due to inactivity.
     */
    public function getInactivityTimeout() : int
    {
        return $this->inactivityTimeout;
    }
    /**
     *
     */
    public function setInactivityTimeout(int $inactivityTimeout) : void
    {
        $this->inactivityTimeout = $inactivityTimeout;
    }
    /**
     *
     */
    public function getHeaderSizeLimit() : int
    {
        return $this->headerSizeLimit;
    }
    /**
     *
     */
    public function setHeaderSizeLimit(int $headerSizeLimit) : void
    {
        $this->headerSizeLimit = $headerSizeLimit;
    }
    /**
     *
     */
    public function getBodySizeLimit() : int
    {
        return $this->bodySizeLimit;
    }
    /**
     *
     */
    public function setBodySizeLimit(int $bodySizeLimit) : void
    {
        $this->bodySizeLimit = $bodySizeLimit;
    }
    /**
    * Note: This method returns a deep clone of the request's attributes, so you can't modify the request attributes
    by modifying the returned value in any way.
    *
    * @return mixed[] An array of all request attributes in the request's local storage, indexed by name.
    */
    public function getAttributes() : array
    {
        return self::clone($this->attributes);
    }
    /**
    * Check whether a variable with the given name exists in the request's local storage.
    *
    * Each request has its own local storage to which applications and interceptors may read and write data.
    Other interceptors which are aware of this data can then access it without the server being tightly coupled to
    specific implementations.
    *
    * @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
    *
    * @return bool
    */
    public function hasAttribute(string $name) : bool
    {
        return \array_key_exists($name, $this->attributes);
    }
    /**
    * Retrieve a variable from the request's local storage.
    *
    * Each request has its own local storage to which applications and interceptors may read and write data.
    Other interceptors which are aware of this data can then access it without the server being tightly coupled to
    specific implementations.
    *
    * Note: This method returns a deep clone of the request's attribute, so you can't modify the request attribute
    by modifying the returned value in any way.
    *
    * @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
    *
    * @return mixed
    *
    * @throws MissingAttributeError If an attribute with the given name does not exist.
    */
    public function getAttribute(string $name)
    {
        if (!$this->hasAttribute($name)) {
            throw new MissingAttributeError("The requested attribute '{$name}' does not exist");
        }
        return self::clone($this->attributes[$name]);
    }
    /**
    * Assign a variable to the request's local storage.
    *
    * Each request has its own local storage to which applications and interceptors may read and write data.
    Other interceptors which are aware of this data can then access it without the server being tightly coupled to
    specific implementations.
    *
    * Note: This method performs a deep clone of the value via serialization, so you can't modify the given value
    after setting it.
    *
    * **Example**
    *
    * ```php
    $request->setAttribute(Timing::class, $stopWatch);
    ```
    *
    * @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
    * @param mixed $value Value of the attribute, might be any serializable value.
    */
    public function setAttribute(string $name, $value) : void
    {
        $this->attributes[$name] = self::clone($value);
    }
    /**
     * Remove an attribute from the request's local storage.
     *
     * @param string $name Name of the attribute, should be namespaced with a vendor and package namespace like classes.
     *
     * @throws MissingAttributeError If an attribute with the given name does not exist.
     */
    public function removeAttribute(string $name) : void
    {
        if (!$this->hasAttribute($name)) {
            throw new MissingAttributeError("The requested attribute '{$name}' does not exist");
        }
        unset($this->attributes[$name]);
    }
    /**
     * Remove all attributes from the request's local storage.
     */
    public function removeAttributes() : void
    {
        $this->attributes = [];
    }
    /**
     *
     */
    public function isIdempotent() : bool
    {
        // https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
        return \in_array($this->method, ['GET', 'HEAD', 'PUT', 'DELETE'], true);
    }
    /**
     *
     */
    private function createUriFromString(string $uri) : UriInterface
    {
        return Uri\Http::createFromString($uri);
    }
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Connection\ConnectionPool;
use Amp\Http\Client\Connection\InterceptedStream;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Promise;
use function Amp\call;
final class PooledHttpClient implements DelegateHttpClient
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var ConnectionPool */
    private $connectionPool;
    /** @var NetworkInterceptor[] */
    private $networkInterceptors = [];
    /**
     *
     */
    public function __construct(?ConnectionPool $connectionPool = null)
    {
        $this->connectionPool = $connectionPool ?? new UnlimitedConnectionPool();
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise
    {
        return call(function () use($request, $cancellation) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startRequest($request));
            }
            $stream = (yield $this->connectionPool->getStream($request, $cancellation));
            \assert($stream instanceof Stream);
            foreach (\array_reverse($this->networkInterceptors) as $interceptor) {
                $stream = new InterceptedStream($stream, $interceptor);
            }
            return (yield $stream->request($request, $cancellation));
        });
    }
    /**
    * Adds a network interceptor.
    *
    * Network interceptors are only invoked if the request requires network access, i.e. there's no short-circuit by
    an application interceptor, e.g. a cache.
    *
    * Whether the given network interceptor will be respected for currently running requests is undefined.
    *
    * Any new requests have to take the new interceptor into account.
    *
    * @param NetworkInterceptor $networkInterceptor
    *
    * @return self
    */
    public function intercept(NetworkInterceptor $networkInterceptor) : self
    {
        $clone = clone $this;
        $clone->networkInterceptors[] = $networkInterceptor;
        return $clone;
    }
}<?php

namespace Amp\Http\Client;

use Amp\Http\Client\Connection\ConnectionPool;
use Amp\Http\Client\Connection\UnlimitedConnectionPool;
use Amp\Http\Client\Interceptor\DecompressResponse;
use Amp\Http\Client\Interceptor\FollowRedirects;
use Amp\Http\Client\Interceptor\ForbidUriUserInfo;
use Amp\Http\Client\Interceptor\RetryRequests;
use Amp\Http\Client\Interceptor\SetRequestHeaderIfUnset;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
/**
 * Allows building an HttpClient instance.
 *
 * The builder is the recommended way to build an HttpClient instance.
 */
final class HttpClientBuilder
{
    use ForbidCloning;
    use ForbidSerialization;
    /**
     *
     */
    public static function buildDefault() : HttpClient
    {
        return (new self())->build();
    }
    /** @var ForbidUriUserInfo|null */
    private $forbidUriUserInfo;
    /** @var RetryRequests|null */
    private $retryInterceptor;
    /** @var FollowRedirects|null */
    private $followRedirectsInterceptor;
    /** @var SetRequestHeaderIfUnset|null */
    private $defaultUserAgentInterceptor;
    /** @var SetRequestHeaderIfUnset|null */
    private $defaultAcceptInterceptor;
    /** @var NetworkInterceptor|null */
    private $defaultCompressionHandler;
    /** @var ApplicationInterceptor[] */
    private $applicationInterceptors = [];
    /** @var NetworkInterceptor[] */
    private $networkInterceptors = [];
    /** @var ConnectionPool */
    private $pool;
    /**
     *
     */
    public function __construct()
    {
        $this->pool = new UnlimitedConnectionPool();
        $this->forbidUriUserInfo = new ForbidUriUserInfo();
        $this->followRedirectsInterceptor = new FollowRedirects(10);
        $this->retryInterceptor = new RetryRequests(2);
        $this->defaultAcceptInterceptor = new SetRequestHeaderIfUnset('accept', '*/*');
        $this->defaultUserAgentInterceptor = new SetRequestHeaderIfUnset('user-agent', 'amphp/http-client @ v4.x');
        $this->defaultCompressionHandler = new DecompressResponse();
    }
    /**
     *
     */
    public function build() : HttpClient
    {
        /** @var PooledHttpClient $client */
        $client = new PooledHttpClient($this->pool);
        foreach ($this->networkInterceptors as $interceptor) {
            $client = $client->intercept($interceptor);
        }
        if ($this->defaultAcceptInterceptor) {
            $client = $client->intercept($this->defaultAcceptInterceptor);
        }
        if ($this->defaultUserAgentInterceptor) {
            $client = $client->intercept($this->defaultUserAgentInterceptor);
        }
        if ($this->defaultCompressionHandler) {
            $client = $client->intercept($this->defaultCompressionHandler);
        }
        $applicationInterceptors = $this->applicationInterceptors;
        if ($this->followRedirectsInterceptor) {
            \array_unshift($applicationInterceptors, $this->followRedirectsInterceptor);
        }
        if ($this->forbidUriUserInfo) {
            \array_unshift($applicationInterceptors, $this->forbidUriUserInfo);
        }
        if ($this->retryInterceptor) {
            $applicationInterceptors[] = $this->retryInterceptor;
        }
        foreach (\array_reverse($applicationInterceptors) as $applicationInterceptor) {
            $client = new InterceptedHttpClient($client, $applicationInterceptor);
        }
        return new HttpClient($client);
    }
    /**
     * @param ConnectionPool $pool Connection pool to use.
     *
     * @return self
     */
    public function usingPool(ConnectionPool $pool) : self
    {
        $builder = clone $this;
        $builder->pool = $pool;
        return $builder;
    }
    /**
    * @param ApplicationInterceptor $interceptor This interceptor gets added to the interceptor queue, so interceptors
    are executed in the order given to this method.
    *
    * @return self
    */
    public function intercept(ApplicationInterceptor $interceptor) : self
    {
        if ($this->followRedirectsInterceptor !== null && $interceptor instanceof FollowRedirects) {
            throw new \Error('Disable automatic redirect following or use HttpClientBuilder::followRedirects() to customize redirects');
        }
        if ($this->retryInterceptor !== null && $interceptor instanceof RetryRequests) {
            throw new \Error('Disable automatic retries or use HttpClientBuilder::retry() to customize retries');
        }
        $builder = clone $this;
        $builder->applicationInterceptors[] = $interceptor;
        return $builder;
    }
    /**
    * @param NetworkInterceptor $interceptor This interceptor gets added to the interceptor queue, so interceptors
    are executed in the order given to this method.
    *
    * @return self
    */
    public function interceptNetwork(NetworkInterceptor $interceptor) : self
    {
        $builder = clone $this;
        $builder->networkInterceptors[] = $interceptor;
        return $builder;
    }
    /**
    * @param int $retryLimit Maximum number of times a request may be retried. Only certain requests will be retried
    automatically (GET, HEAD, PUT, and DELETE requests are automatically retried, or any
    request that was indicated as unprocessed by the connection).
    *
    * @return self
    */
    public function retry(int $retryLimit) : self
    {
        $builder = clone $this;
        if ($retryLimit <= 0) {
            $builder->retryInterceptor = null;
        } else {
            $builder->retryInterceptor = new RetryRequests($retryLimit);
        }
        return $builder;
    }
    /**
    * @param int $limit Maximum number of redirects to follow. The client will automatically request the URI supplied
    by a redirect response (3xx status codes) and returns that response instead.
    *
    * @return self
    */
    public function followRedirects(int $limit = 10) : self
    {
        $builder = clone $this;
        if ($limit <= 0) {
            $builder->followRedirectsInterceptor = null;
        } else {
            $builder->followRedirectsInterceptor = new FollowRedirects($limit);
        }
        return $builder;
    }
    /**
     * Removes the default restriction of user:password in request URIs.
     *
     * @return self
     */
    public function allowDeprecatedUriUserInfo() : self
    {
        $builder = clone $this;
        $builder->forbidUriUserInfo = null;
        return $builder;
    }
    /**
     * Doesn't automatically set an 'accept' header.
     *
     * @return self
     */
    public function skipDefaultAcceptHeader() : self
    {
        $builder = clone $this;
        $builder->defaultAcceptInterceptor = null;
        return $builder;
    }
    /**
     * Doesn't automatically set a 'user-agent' header.
     *
     * @return self
     */
    public function skipDefaultUserAgent() : self
    {
        $builder = clone $this;
        $builder->defaultUserAgentInterceptor = null;
        return $builder;
    }
    /**
     * Doesn't automatically set an 'accept-encoding' header and decompress the response.
     *
     * @return self
     */
    public function skipAutomaticCompression() : self
    {
        $builder = clone $this;
        $builder->defaultCompressionHandler = null;
        return $builder;
    }
}<?php

namespace Amp\Http\Client\Internal;

/** @internal */
trait ForbidSerialization
{
    /**
     *
     */
    public final function __sleep()
    {
        throw new \Error(__CLASS__ . ' does not support serialization');
    }
}<?php

namespace Amp\Http\Client\Internal;

/** @internal */
trait ForbidCloning
{
    /**
     *
     */
    protected final function __clone()
    {
        // clone is automatically denied to all external calls
        // final protected instead of private to also force denial for all children
    }
}<?php

namespace Amp\Http\Client\Internal;

/** @internal */
final class HarAttributes
{
    use ForbidCloning;
    use ForbidSerialization;
    public const STARTED_DATE_TIME = 'amp.http.client.har.startedDateTime';
    public const SERVER_IP_ADDRESS = 'amp.http.client.har.serverIPAddress';
    public const TIME_START = 'amp.http.client.har.timings.start';
    public const TIME_SSL = 'amp.http.client.har.timings.ssl';
    public const TIME_CONNECT = 'amp.http.client.har.timings.connect';
    public const TIME_SEND = 'amp.http.client.har.timings.send';
    public const TIME_WAIT = 'amp.http.client.har.timings.wait';
    public const TIME_RECEIVE = 'amp.http.client.har.timings.receive';
    public const TIME_COMPLETE = 'amp.http.client.har.timings.complete';
}<?php

namespace Amp\Http\Client\Internal;

use Amp\ByteStream\InputStream;
use Amp\CancellationTokenSource;
use Amp\Promise;
/** @internal */
final class ResponseBodyStream implements InputStream
{
    use ForbidSerialization;
    use ForbidCloning;
    /** @var InputStream */
    private $body;
    /** @var CancellationTokenSource */
    private $bodyCancellation;
    /** @var bool */
    private $successfulEnd = false;
    /**
     *
     */
    public function __construct(InputStream $body, CancellationTokenSource $bodyCancellation)
    {
        $this->body = $body;
        $this->bodyCancellation = $bodyCancellation;
    }
    /**
     *
     */
    public function read() : Promise
    {
        $promise = $this->body->read();
        $promise->onResolve(function ($error, $value) {
            if ($value === null && $error === null) {
                $this->successfulEnd = true;
            }
        });
        return $promise;
    }
    /**
     *
     */
    public function __destruct()
    {
        if (!$this->successfulEnd) {
            $this->bodyCancellation->cancel();
        }
    }
}<?php

namespace Amp\Http\Client\Internal;

use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\Request;
/**
 * @param Request $request
 *
 * @return string
 * @throws InvalidRequestException
 *
 * @internal
 */
function normalizeRequestPathWithQuery(Request $request) : string
{
    $path = $request->getUri()->getPath();
    $query = $request->getUri()->getQuery();
    if ($path === '') {
        return '/' . ($query !== '' ? '?' . $query : '');
    }
    if ($path[0] !== '/') {
        throw new InvalidRequestException($request, 'Relative path (' . $path . ') is not allowed in the request URI');
    }
    return $path . ($query !== '' ? '?' . $query : '');
}<?php

namespace Amp\Http\Client\Internal;

use Amp\ByteStream\InputStream;
use Amp\Failure;
use Amp\Http\Client\ParseException;
use Amp\Http\Status;
use Amp\Promise;
/** @internal */
final class SizeLimitingInputStream implements InputStream
{
    use ForbidSerialization;
    use ForbidCloning;
    /** @var InputStream|null */
    private $source;
    /** @var int */
    private $bytesRead = 0;
    /** @var int */
    private $sizeLimit;
    /** @var \Throwable|null */
    private $exception;
    /**
     *
     */
    public function __construct(InputStream $source, int $sizeLimit)
    {
        $this->source = $source;
        $this->sizeLimit = $sizeLimit;
    }
    /**
     *
     */
    public function read() : Promise
    {
        if ($this->exception) {
            return new Failure($this->exception);
        }
        \assert($this->source !== null);
        $promise = $this->source->read();
        $promise->onResolve(function ($error, $value) {
            if ($value !== null) {
                $this->bytesRead += \strlen($value);
                if ($this->bytesRead > $this->sizeLimit) {
                    $this->exception = new ParseException("Configured body size exceeded: {$this->bytesRead} bytes received, while the configured limit is {$this->sizeLimit} bytes", Status::PAYLOAD_TOO_LARGE);
                    $this->source = null;
                }
            }
        });
        return $promise;
    }
}<?php

namespace Amp\Http\Client;

use Amp\ByteStream\InputStream;
use Amp\Promise;
/**
 * An interface for generating HTTP message bodies + headers.
 */
interface RequestBody
{
    /**
     * Retrieve a key-value array of headers to add to the outbound request.
     *
     * The resolved promise value must be a key-value array mapping header fields to values.
     *
     * @return Promise
     */
    public function getHeaders() : Promise;
    /**
     * Create the HTTP message body to be sent.
     *
     * Further calls MUST return a new stream to make it possible to resend bodies on redirects.
     *
     * @return InputStream
     */
    public function createBodyStream() : InputStream;
    /**
     * Retrieve the HTTP message body length. If not available, return -1.
     *
     * @return Promise
     */
    public function getBodyLength() : Promise;
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Promise;
use function Amp\call;
final class InterceptedHttpClient implements DelegateHttpClient
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var DelegateHttpClient */
    private $httpClient;
    /** @var ApplicationInterceptor */
    private $interceptor;
    /**
     *
     */
    public function __construct(DelegateHttpClient $httpClient, ApplicationInterceptor $interceptor)
    {
        $this->httpClient = $httpClient;
        $this->interceptor = $interceptor;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise
    {
        return call(function () use($request, $cancellation) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startRequest($request));
            }
            return $this->interceptor->request($request, $cancellation, $this->httpClient);
        });
    }
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Promise;
/**
 * Base HTTP client interface for use in {@see ApplicationInterceptor}.
 *
 * Applications and implementations should depend on {@see HttpClient} instead. The intent of this interface is to
 * allow static analysis tools to find interceptors that forget to pass the cancellation token down. This situation is
 * created because of the cancellation token being optional.
 *
 * Before executing or delegating the request, any client implementation must call {@see EventListener::startRequest()}
 * on all event listeners registered on the given request in the order defined by {@see Request::getEventListeners()}.
 * Before calling the next listener, the promise returned from the previous one must resolve successfully.
 *
 * @see HttpClient
 */
interface DelegateHttpClient
{
    /**
     * Request a specific resource from an HTTP server.
     *
     * @param Request $request
     * @param CancellationToken $cancellation
     *
     * @return Promise<Response>
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise;
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\NullCancellationToken;
use Amp\Promise;
/**
 * Convenient HTTP client for use in applications and libraries, providing a default for the cancellation token and
 * automatically cloning the passed request, so future application requests can re-use the same object again.
 */
final class HttpClient implements DelegateHttpClient
{
    private $httpClient;
    /**
     *
     */
    public function __construct(DelegateHttpClient $httpClient)
    {
        $this->httpClient = $httpClient;
    }
    /**
     * Request a specific resource from an HTTP server.
     *
     * @param Request $request
     * @param CancellationToken $cancellation
     *
     * @return Promise<Response>
     */
    public function request(Request $request, ?CancellationToken $cancellation = null) : Promise
    {
        return $this->httpClient->request(clone $request, $cancellation ?? new NullCancellationToken());
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Promise;
use League\Uri\Http;
use Psr\Http\Message\UriInterface;
final class MatchOrigin implements ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var ApplicationInterceptor[] */
    private $originMap = [];
    /** @var ApplicationInterceptor|null */
    private $default;
    /**
     * @param ApplicationInterceptor[] $originMap
     * @param ApplicationInterceptor $default
     *
     * @throws HttpException
     */
    public function __construct(array $originMap, ?ApplicationInterceptor $default = null)
    {
        foreach ($originMap as $origin => $interceptor) {
            if (!$interceptor instanceof ApplicationInterceptor) {
                $type = \is_object($interceptor) ? \get_class($interceptor) : \gettype($interceptor);
                throw new HttpException('Origin map must be a map from origin to ApplicationInterceptor, got ' . $type);
            }
            $this->originMap[$this->checkOrigin($origin)] = $interceptor;
        }
        $this->default = $default;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        $interceptor = $this->originMap[$this->normalizeOrigin($request->getUri())] ?? $this->default;
        if (!$interceptor) {
            return $httpClient->request($request, $cancellation);
        }
        return $interceptor->request($request, $cancellation, $httpClient);
    }
    /**
     *
     */
    private function checkOrigin(string $origin) : string
    {
        try {
            $originUri = Http::createFromString($origin);
        } catch (\Exception $e) {
            throw new HttpException("Invalid origin provided: parsing failed: " . $origin);
        }
        if (!\in_array($originUri->getScheme(), ['http', 'https'], true)) {
            throw new HttpException('Invalid origin with unsupported scheme: ' . $origin);
        }
        if ($originUri->getHost() === '') {
            throw new HttpException('Invalid origin without host: ' . $origin);
        }
        if ($originUri->getUserInfo() !== '') {
            throw new HttpException('Invalid origin with user info, which must not be present: ' . $origin);
        }
        if (!\in_array($originUri->getPath(), ['', '/'], true)) {
            throw new HttpException('Invalid origin with path, which must not be present: ' . $origin);
        }
        if ($originUri->getQuery() !== '') {
            throw new HttpException('Invalid origin with query, which must not be present: ' . $origin);
        }
        if ($originUri->getFragment() !== '') {
            throw new HttpException('Invalid origin with fragment, which must not be present: ' . $origin);
        }
        return $this->normalizeOrigin($originUri);
    }
    /**
     *
     */
    private function normalizeOrigin(UriInterface $uri) : string
    {
        $defaultPort = $uri->getScheme() === 'https' ? 443 : 80;
        return $uri->getScheme() . '://' . $uri->getHost() . ':' . ($uri->getPort() ?? $defaultPort);
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use function Amp\call;
class ModifyResponse implements NetworkInterceptor, ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var callable(Response):(\Generator<mixed, mixed, mixed, Response|null>|Promise<Response>|Response|null) */
    private $mapper;
    /**
     * @psalm-param callable(Response ): (\Generator<mixed, mixed, mixed, (Response | null)> | Promise<Response> | Response | null) $mapper
     */
    public function __construct(callable $mapper)
    {
        $this->mapper = $mapper;
    }
    /**
     *
     */
    public final function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellation, $stream) {
            $response = (yield $stream->request($request, $cancellation));
            $mappedResponse = (yield call($this->mapper, $response));
            \assert($mappedResponse instanceof Response || $mappedResponse === null);
            return $mappedResponse ?? $response;
        });
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        return call(function () use($request, $cancellation, $httpClient) {
            $request->interceptPush($this->mapper);
            $response = (yield $httpClient->request($request, $cancellation));
            $mappedResponse = (yield call($this->mapper, $response));
            \assert($mappedResponse instanceof Response || $mappedResponse === null);
            return $mappedResponse ?? $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class SetRequestHeader extends ModifyRequest
{
    /**
     *
     */
    public function __construct(string $headerName, string $headerValue, string ...$headerValues)
    {
        \array_unshift($headerValues, $headerValue);
        parent::__construct(static function (Request $request) use($headerName, $headerValues) {
            $request->setHeader($headerName, $headerValues);
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class SetRequestHeaderIfUnset extends ModifyRequest
{
    /**
     *
     */
    public function __construct(string $headerName, string $headerValue, string ...$headerValues)
    {
        \array_unshift($headerValues, $headerValue);
        parent::__construct(static function (Request $request) use($headerName, $headerValues) {
            if (!$request->hasHeader($headerName)) {
                $request->setHeader($headerName, $headerValues);
            }
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class AddRequestHeader extends ModifyRequest
{
    /**
     *
     */
    public function __construct(string $headerName, string ...$headerValues)
    {
        parent::__construct(static function (Request $request) use($headerName, $headerValues) {
            $request->addHeader($headerName, $headerValues);
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\HttpException;
use Amp\Http\Client\Response;
class TooManyRedirectsException extends HttpException
{
    /** @var Response */
    private $response;
    /**
     *
     */
    public function __construct(Response $response)
    {
        parent::__construct("There were too many redirects");
        $this->response = $response;
    }
    /**
     *
     */
    public function getResponse() : Response
    {
        return $this->response;
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\ByteStream\ZlibInputStream;
use Amp\CancellationToken;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Internal\SizeLimitingInputStream;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use function Amp\call;
final class DecompressResponse implements NetworkInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var bool */
    private $hasZlib;
    /**
     *
     */
    public function __construct()
    {
        $this->hasZlib = \extension_loaded('zlib');
    }
    /**
     *
     */
    public function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        // If a header is manually set, we won't interfere
        if ($request->hasHeader('accept-encoding')) {
            return $stream->request($request, $cancellation);
        }
        return call(function () use($request, $cancellation, $stream) {
            $this->addAcceptEncodingHeader($request);
            $request->interceptPush(function (Response $response) {
                return $this->decompressResponse($response);
            });
            return $this->decompressResponse((yield $stream->request($request, $cancellation)));
        });
    }
    /**
     *
     */
    private function addAcceptEncodingHeader(Request $request) : void
    {
        if ($this->hasZlib) {
            $request->setHeader('Accept-Encoding', 'gzip, deflate, identity');
        }
    }
    /**
     *
     */
    private function decompressResponse(Response $response) : Response
    {
        if ($encoding = $this->determineCompressionEncoding($response)) {
            $sizeLimit = $response->getRequest()->getBodySizeLimit();
            /** @noinspection PhpUnhandledExceptionInspection */
            $decompressedBody = new ZlibInputStream($response->getBody(), $encoding);
            $response->setBody(new SizeLimitingInputStream($decompressedBody, $sizeLimit));
            $response->removeHeader('content-encoding');
        }
        return $response;
    }
    /**
     *
     */
    private function determineCompressionEncoding(Response $response) : int
    {
        if (!$this->hasZlib) {
            return 0;
        }
        if (!$response->hasHeader("content-encoding")) {
            return 0;
        }
        $contentEncoding = $response->getHeader("content-encoding");
        \assert($contentEncoding !== null);
        $contentEncodingHeader = \trim($contentEncoding);
        if (\strcasecmp($contentEncodingHeader, 'gzip') === 0) {
            return \ZLIB_ENCODING_GZIP;
        }
        if (\strcasecmp($contentEncodingHeader, 'deflate') === 0) {
            return \ZLIB_ENCODING_DEFLATE;
        }
        return 0;
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\File;
use Amp\File\Driver;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\EventListener;
use Amp\Http\Client\EventListener\RecordHarAttributes;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Internal\HarAttributes;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Message;
use Amp\Promise;
use Amp\Sync\LocalMutex;
use Amp\Sync\Lock;
use function Amp\call;
use function Amp\Promise\rethrow;
final class LogHttpArchive implements ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /**
     *
     */
    private static function getTime(Request $request, string $start, string ...$ends) : int
    {
        if (!$request->hasAttribute($start)) {
            return -1;
        }
        foreach ($ends as $end) {
            if ($request->hasAttribute($end)) {
                return $request->getAttribute($end) - $request->getAttribute($start);
            }
        }
        return -1;
    }
    /**
     *
     */
    private static function formatHeaders(Message $message) : array
    {
        $headers = [];
        foreach ($message->getHeaders() as $field => $values) {
            foreach ($values as $value) {
                $headers[] = ['name' => $field, 'value' => $value];
            }
        }
        return $headers;
    }
    /**
     *
     */
    private static function formatEntry(Response $response) : array
    {
        $request = $response->getRequest();
        $data = ['startedDateTime' => $request->getAttribute(HarAttributes::STARTED_DATE_TIME)->format(\DateTimeInterface::RFC3339_EXTENDED), 'time' => self::getTime($request, HarAttributes::TIME_START, HarAttributes::TIME_COMPLETE), 'request' => ['method' => $request->getMethod(), 'url' => (string) $request->getUri()->withUserInfo(''), 'httpVersion' => 'http/' . $request->getProtocolVersions()[0], 'headers' => self::formatHeaders($request), 'queryString' => [], 'cookies' => [], 'headersSize' => -1, 'bodySize' => -1], 'response' => ['status' => $response->getStatus(), 'statusText' => $response->getReason(), 'httpVersion' => 'http/' . $response->getProtocolVersion(), 'headers' => self::formatHeaders($response), 'cookies' => [], 'redirectURL' => $response->getHeader('location') ?? '', 'headersSize' => -1, 'bodySize' => -1, 'content' => ['size' => (int) ($response->getHeader('content-length') ?? '-1'), 'mimeType' => $response->getHeader('content-type') ?? '']], 'cache' => [], 'timings' => ['blocked' => self::getTime($request, HarAttributes::TIME_START, HarAttributes::TIME_CONNECT, HarAttributes::TIME_SEND), 'dns' => -1, 'connect' => self::getTime($request, HarAttributes::TIME_CONNECT, HarAttributes::TIME_SEND), 'ssl' => self::getTime($request, HarAttributes::TIME_SSL, HarAttributes::TIME_SEND), 'send' => self::getTime($request, HarAttributes::TIME_SEND, HarAttributes::TIME_WAIT), 'wait' => self::getTime($request, HarAttributes::TIME_WAIT, HarAttributes::TIME_RECEIVE), 'receive' => self::getTime($request, HarAttributes::TIME_RECEIVE, HarAttributes::TIME_COMPLETE)]];
        if ($request->hasAttribute(HarAttributes::SERVER_IP_ADDRESS)) {
            $data['serverIPAddress'] = $request->getAttribute(HarAttributes::SERVER_IP_ADDRESS);
        }
        return $data;
    }
    /** @var LocalMutex */
    private $fileMutex;
    /** @var File\File|null */
    private $fileHandle;
    /** @var string */
    private $filePath;
    /** @var \Throwable|null */
    private $error;
    /** @var EventListener */
    private $eventListener;
    /**
     *
     */
    public function __construct(string $filePath)
    {
        $this->filePath = $filePath;
        $this->fileMutex = new LocalMutex();
        $this->eventListener = new RecordHarAttributes();
        if (!\interface_exists(Driver::class)) {
            throw new \Error(__CLASS__ . ' requires amphp/file to be installed');
        }
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        return call(function () use($request, $cancellation, $httpClient) {
            if ($this->error) {
                throw $this->error;
            }
            $this->ensureEventListenerIsRegistered($request);
            /** @var Response $response */
            $response = (yield $httpClient->request($request, $cancellation));
            rethrow($this->writeLog($response));
            return $response;
        });
    }
    /**
     *
     */
    public function reset() : Promise
    {
        return $this->rotate($this->filePath);
    }
    /**
     *
     */
    public function rotate(string $filePath) : Promise
    {
        return call(function () use($filePath) {
            /** @var Lock $lock */
            $lock = (yield $this->fileMutex->acquire());
            // Will automatically reopen and reset the file
            $this->fileHandle = null;
            $this->filePath = $filePath;
            $this->error = null;
            $lock->release();
        });
    }
    /**
     *
     */
    private function writeLog(Response $response) : Promise
    {
        return call(function () use($response) {
            try {
                (yield $response->getTrailers());
            } catch (\Throwable $e) {
                // ignore, still log the remaining response times
            }
            try {
                /** @var Lock $lock */
                $lock = (yield $this->fileMutex->acquire());
                $firstEntry = $this->fileHandle === null;
                if ($firstEntry) {
                    $this->fileHandle = (yield \function_exists('Amp\\File\\openFile') ? File\openFile($this->filePath, 'w') : File\open($this->filePath, 'w'));
                    $header = '{"log":{"version":"1.2","creator":{"name":"amphp/http-client","version":"4.x"},"pages":[],"entries":[';
                    (yield $this->fileHandle->write($header));
                } else {
                    \assert($this->fileHandle !== null);
                    (yield $this->fileHandle->seek(-3, \SEEK_CUR));
                }
                /** @noinspection PhpComposerExtensionStubsInspection */
                $json = \json_encode(self::formatEntry($response));
                (yield $this->fileHandle->write(($firstEntry ? '' : ',') . $json . ']}}'));
                $lock->release();
            } catch (HttpException $e) {
                $this->error = $e;
            } catch (\Throwable $e) {
                $this->error = new HttpException('Writing HTTP archive log failed', 0, $e);
            }
        });
    }
    /**
     *
     */
    private function ensureEventListenerIsRegistered(Request $request) : void
    {
        foreach ($request->getEventListeners() as $eventListener) {
            if ($eventListener instanceof RecordHarAttributes) {
                return;
                // user added it manually
            }
        }
        $request->addEventListener($this->eventListener);
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Response;
final class AddResponseHeader extends ModifyResponse
{
    /**
     *
     */
    public function __construct(string $headerName, string ...$headerValues)
    {
        parent::__construct(static function (Response $response) use($headerName, $headerValues) {
            $response->addHeader($headerName, $headerValues);
            return $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use League\Uri;
use Psr\Http\Message\UriInterface as PsrUri;
use function Amp\call;
final class FollowRedirects implements ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /**
    * Resolves the given path in $locationUri using $baseUri as a base URI. For example, a base URI of
    http://example.com/example/path and a location path of 'to/resolve' will return a URI of
    http://example.com/example/to/resolve.
    *
    * @param PsrUri $baseUri
    * @param PsrUri $locationUri
    *
    * @return PsrUri
    */
    public static function resolve(PsrUri $baseUri, PsrUri $locationUri) : PsrUri
    {
        if ((string) $locationUri === '') {
            return $baseUri;
        }
        if ($locationUri->getScheme() !== '' || $locationUri->getHost() !== '') {
            $resultUri = $locationUri->withPath(self::removeDotSegments($locationUri->getPath()));
            if ($locationUri->getScheme() === '') {
                $resultUri = $resultUri->withScheme($baseUri->getScheme());
            }
            return $resultUri;
        }
        $baseUri = $baseUri->withQuery($locationUri->getQuery());
        $baseUri = $baseUri->withFragment($locationUri->getFragment());
        if ($locationUri->getPath() !== '' && \Phabel\Target\Php80\Polyfill::substr($locationUri->getPath(), 0, 1) === "/") {
            $baseUri = $baseUri->withPath(self::removeDotSegments($locationUri->getPath()));
        } else {
            $baseUri = $baseUri->withPath(self::mergePaths($baseUri->getPath(), $locationUri->getPath()));
        }
        return $baseUri;
    }
    /**
     * @param string $input
     *
     * @return string
     *
     * @link http://www.apps.ietf.org/rfc/rfc3986.html#sec-5.2.4
     */
    private static function removeDotSegments(string $input) : string
    {
        $output = '';
        $patternA = ',^(\\.\\.?/),';
        $patternB1 = ',^(/\\./),';
        $patternB2 = ',^(/\\.)$,';
        $patternC = ',^(/\\.\\./|/\\.\\.),';
        // $patternD  = ',^(\.\.?)$,';
        $patternE = ',(/*[^/]*),';
        while ($input !== '') {
            if (\preg_match($patternA, $input)) {
                $input = \preg_replace($patternA, '', $input);
            } elseif (\preg_match($patternB1, $input, $match) || \preg_match($patternB2, $input, $match)) {
                $input = \preg_replace(",^" . $match[1] . ",", '/', $input);
            } elseif (\preg_match($patternC, $input, $match)) {
                $input = \preg_replace(',^' . \preg_quote($match[1], ',') . ',', '/', $input);
                $output = \preg_replace(',/([^/]+)$,', '', $output);
            } elseif ($input === '.' || $input === '..') {
                // pattern D
                $input = '';
            } elseif (\preg_match($patternE, $input, $match)) {
                $initialSegment = $match[1];
                $input = \preg_replace(',^' . \preg_quote($initialSegment, ',') . ',', '', $input, 1);
                $output .= $initialSegment;
            }
        }
        return $output;
    }
    /**
     * @param string $basePath
     * @param string $pathToMerge
     *
     * @return string
     *
     * @link http://tools.ietf.org/html/rfc3986#section-5.2.3
     */
    private static function mergePaths(string $basePath, string $pathToMerge) : string
    {
        if ($pathToMerge === '') {
            return self::removeDotSegments($basePath);
        }
        if ($basePath === '') {
            return self::removeDotSegments('/' . $pathToMerge);
        }
        $parts = \explode('/', $basePath);
        \array_pop($parts);
        $parts[] = $pathToMerge;
        return self::removeDotSegments(\implode('/', $parts));
    }
    /** @var int */
    private $maxRedirects;
    /** @var bool */
    private $autoReferrer;
    /**
     *
     */
    public function __construct(int $limit, bool $autoReferrer = true)
    {
        if ($limit < 1) {
            /** @noinspection PhpUndefinedClassInspection */
            throw new \Error("Invalid redirection limit: " . $limit);
        }
        $this->maxRedirects = $limit;
        $this->autoReferrer = $autoReferrer;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        // Don't follow redirects on pushes, just store the redirect in cache (if an interceptor is configured)
        return call(function () use($request, $cancellation, $httpClient) {
            /** @var Response $response */
            $response = (yield $httpClient->request(clone $request, $cancellation));
            $response = (yield from $this->followRedirects($request, $response, $httpClient, $cancellation));
            return $response;
        });
    }
    /**
     *
     */
    private function followRedirects(Request $request, Response $response, DelegateHttpClient $client, CancellationToken $cancellationToken) : \Generator
    {
        $previousResponse = null;
        $maxRedirects = $this->maxRedirects;
        $requestNr = 2;
        do {
            $request = (yield from $this->createRedirectRequest($request, $response));
            if ($request === null) {
                return $response;
            }
            /** @var Response $redirectResponse */
            $redirectResponse = (yield $client->request(clone $request, $cancellationToken));
            $redirectResponse->setPreviousResponse($response);
            $response = $redirectResponse;
        } while (++$requestNr <= $maxRedirects + 1);
        if ($this->getRedirectUri($response) !== null) {
            throw new TooManyRedirectsException($response);
        }
        return $response;
    }
    /**
     *
     */
    private function createRedirectRequest(Request $originalRequest, Response $response) : \Generator
    {
        $redirectUri = $this->getRedirectUri($response);
        if ($redirectUri === null) {
            return null;
        }
        $originalUri = $response->getRequest()->getUri();
        $isSameHost = $redirectUri->getAuthority() === $originalUri->getAuthority();
        $request = clone $originalRequest;
        $request->setMethod('GET');
        $request->setUri($redirectUri);
        $request->removeHeader('transfer-encoding');
        $request->removeHeader('content-length');
        $request->removeHeader('content-type');
        $request->removeAttributes();
        $request->setBody(null);
        if (!$isSameHost) {
            // Remove for security reasons, any interceptor headers will be added again,
            // but application headers will be discarded.
            foreach ($request->getRawHeaders() as [$field]) {
                $request->removeHeader($field);
            }
        }
        if ($this->autoReferrer) {
            $this->assignRedirectRefererHeader($request, $originalUri, $redirectUri);
        }
        yield from $this->discardResponseBody($response);
        return $request;
    }
    /**
    * Clients must not add a Referer header when leaving an unencrypted resource and redirecting to an encrypted
    resource.
    *
    * @param Request $request
    * @param PsrUri $referrerUri
    * @param PsrUri $followUri
    *
    * @link http://www.w3.org/Protocols/rfc2616/rfc2616-sec15.html#sec15.1.3
    */
    private function assignRedirectRefererHeader(Request $request, PsrUri $referrerUri, PsrUri $followUri) : void
    {
        $referrerIsEncrypted = $referrerUri->getScheme() === 'https';
        $destinationIsEncrypted = $followUri->getScheme() === 'https';
        if (!$referrerIsEncrypted || $destinationIsEncrypted) {
            $request->setHeader('Referer', (string) $referrerUri->withUserInfo('')->withFragment(''));
        } else {
            $request->removeHeader('Referer');
        }
    }
    /**
     *
     */
    private function getRedirectUri(Response $response) : ?PsrUri
    {
        if (\count($response->getHeaderArray('location')) !== 1) {
            return null;
        }
        $status = $response->getStatus();
        $request = $response->getRequest();
        $method = $request->getMethod();
        if ($method !== 'GET' && \in_array($status, [307, 308], true)) {
            return null;
        }
        // We don't automatically follow:
        // - 300 (Multiple Choices)
        // - 304 (Not Modified)
        // - 305 (Use Proxy)
        if (!\in_array($status, [301, 302, 303, 307, 308], true)) {
            return null;
        }
        try {
            $locationUri = Uri\Http::createFromString($response->getHeader('location'));
        } catch (\Exception $e) {
            return null;
        }
        return self::resolve($request->getUri(), $locationUri);
    }
    /**
     *
     */
    private function discardResponseBody(Response $response) : \Generator
    {
        // Discard response body of redirect responses
        $body = $response->getBody();
        try {
            /** @noinspection PhpStatementHasEmptyBodyInspection */
            /** @noinspection LoopWhichDoesNotLoopInspection */
            /** @noinspection MissingOrEmptyGroupStatementInspection */
            while (null !== (yield $body->read())) {
                // discard
            }
        } catch (HttpException|StreamException $e) {
            // ignore streaming errors on previous responses
        } finally {
            unset($body);
        }
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Response;
final class SetResponseHeader extends ModifyResponse
{
    /**
     *
     */
    public function __construct(string $headerName, string $headerValue, string ...$headerValues)
    {
        \array_unshift($headerValues, $headerValue);
        parent::__construct(static function (Response $response) use($headerName, $headerValues) {
            $response->setHeader($headerName, $headerValues);
            return $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Response;
final class RemoveResponseHeader extends ModifyResponse
{
    /**
     *
     */
    public function __construct(string $headerName)
    {
        parent::__construct(static function (Response $response) use($headerName) {
            $response->removeHeader($headerName);
            return $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class RemoveRequestHeader extends ModifyRequest
{
    /**
     *
     */
    public function __construct(string $headerName)
    {
        parent::__construct(static function (Request $request) use($headerName) {
            $request->removeHeader($headerName);
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Response;
final class SetResponseHeaderIfUnset extends ModifyResponse
{
    /**
     *
     */
    public function __construct(string $headerName, string $headerValue, string ...$headerValues)
    {
        \array_unshift($headerValues, $headerValue);
        parent::__construct(static function (Response $response) use($headerName, $headerValues) {
            if (!$response->hasHeader($headerName)) {
                $response->setHeader($headerName, $headerValues);
            }
            return $response;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use function Amp\call;
class ModifyRequest implements NetworkInterceptor, ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var callable(Request):(\Generator<mixed, mixed, mixed, Promise<Request|null>|Request|null>|Promise<Request|null>|Request|null) */
    private $mapper;
    /**
     * @psalm-param callable(Request ): (\Generator<mixed, mixed, mixed, (Promise<(Request | null)> | Request | null)> | Promise<(Request | null)> | Request | null) $mapper
     */
    public function __construct(callable $mapper)
    {
        $this->mapper = $mapper;
    }
    /**
     * @param Request $request
     * @param CancellationToken $cancellation
     * @param Stream $stream
     *
     * @return Promise<Response>
     */
    public final function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellation, $stream) {
            $mappedRequest = (yield call($this->mapper, $request));
            \assert($mappedRequest instanceof Request || $mappedRequest === null);
            return (yield $stream->request($mappedRequest ?? $request, $cancellation));
        });
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        return call(function () use($request, $cancellation, $httpClient) {
            $mappedRequest = (yield call($this->mapper, $request));
            \assert($mappedRequest instanceof Request || $mappedRequest === null);
            return $httpClient->request($mappedRequest ?? $request, $cancellation);
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\Request;
final class SetRequestTimeout extends ModifyRequest
{
    /**
     *
     */
    public function __construct(int $tcpConnectTimeout = 10000, int $tlsHandshakeTimeout = 10000, int $transferTimeout = 10000)
    {
        parent::__construct(static function (Request $request) use($tcpConnectTimeout, $tlsHandshakeTimeout, $transferTimeout) {
            $request->setTcpConnectTimeout($tcpConnectTimeout);
            $request->setTlsHandshakeTimeout($tlsHandshakeTimeout);
            $request->setTransferTimeout($transferTimeout);
            return $request;
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\Request;
final class ForbidUriUserInfo extends ModifyRequest
{
    /**
     *
     */
    public function __construct()
    {
        parent::__construct(static function (Request $request) {
            if ($request->getUri()->getUserInfo() !== '') {
                throw new InvalidRequestException($request, 'The user information (username:password) component of URIs has been deprecated (see https://tools.ietf.org/html/rfc3986#section-3.2.1 and https://tools.ietf.org/html/rfc7230#section-2.7.1); Instead, set an "Authorization" header containing "Basic " . \\base64_encode("username:password"). If you used HttpClientBuilder, you can use HttpClientBuilder::allowDeprecatedUriUserInfo() to disable this protection. Doing so is strongly discouraged and you need to be aware of any interceptor using UriInterface::__toString(), which might expose the password in headers or logs.');
            }
        });
    }
}<?php

namespace Amp\Http\Client\Interceptor;

use Amp\CancellationToken;
use Amp\Http\Client\ApplicationInterceptor;
use Amp\Http\Client\Connection\Http2ConnectionException;
use Amp\Http\Client\Connection\UnprocessedRequestException;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\SocketException;
use Amp\Promise;
use function Amp\call;
final class RetryRequests implements ApplicationInterceptor
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var int */
    private $retryLimit;
    /**
     *
     */
    public function __construct(int $retryLimit)
    {
        $this->retryLimit = $retryLimit;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise
    {
        return call(function () use($request, $cancellation, $httpClient) {
            $attempt = 1;
            do {
                try {
                    return (yield $httpClient->request(clone $request, $cancellation));
                } catch (UnprocessedRequestException $exception) {
                    // Request was deemed retryable by connection, so carry on.
                } catch (SocketException|Http2ConnectionException $exception) {
                    if (!$request->isIdempotent()) {
                        throw $exception;
                    }
                    // Request can safely be retried.
                }
            } while ($attempt++ <= $this->retryLimit);
            throw $exception;
        });
    }
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Interceptor\DecompressResponse;
use Amp\Promise;
/**
 * Allows intercepting an application request to an HTTP resource.
 */
interface ApplicationInterceptor
{
    /**
    * Intercepts an application request to an HTTP resource.
    *
    * The implementation might modify the request, delegate the request handling to the `$httpClient`, and/or modify
    the response after the promise returned from `$httpClient->request(...)` resolves.
    *
    * An interceptor might also short-circuit and not delegate to the `$httpClient` at all.
    *
    * Any retry or cloned follow-up request must be manually cloned from `$request` to ensure a properly working
    interceptor chain, e.g. the {@see DecompressResponse} interceptor only decodes a response if the
    `accept-encoding` header isn't set manually. If the request isn't cloned, the first attempt will set the header
    and the second attempt will see the header and won't decode the response, because it thinks another interceptor
    or the application itself will care about the decoding.
    *
    * @param Request $request
    * @param CancellationToken $cancellation
    * @param DelegateHttpClient $httpClient
    *
    * @return Promise<Response>
    */
    public function request(Request $request, CancellationToken $cancellation, DelegateHttpClient $httpClient) : Promise;
}<?php

namespace Amp\Http\Client\Body;

use Amp\ByteStream\InputStream;
use Amp\File\Driver;
use Amp\Http\Client\RequestBody;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
use function Amp\File\getSize;
use function Amp\File\open;
use function Amp\File\openFile;
use function Amp\File\size;
final class FileBody implements RequestBody
{
    /** @var string */
    private $path;
    /**
     * @param string $path The filesystem path for the file we wish to send
     */
    public function __construct(string $path)
    {
        if (!\interface_exists(Driver::class)) {
            throw new \Error("File request bodies require amphp/file to be installed");
        }
        $this->path = $path;
    }
    /**
     *
     */
    public function createBodyStream() : InputStream
    {
        $handlePromise = \function_exists('Amp\\File\\openFile') ? openFile($this->path, "r") : open($this->path, "r");
        return new class($handlePromise) implements InputStream
        {
            /** @var Promise<InputStream> */
            private $promise;
            /** @var InputStream|null */
            private $stream;
            /**
             *
             */
            public function __construct(Promise $promise)
            {
                $this->promise = $promise;
                $this->promise->onResolve(function ($error, $stream) {
                    if ($error) {
                        return;
                    }
                    $this->stream = $stream;
                });
            }
            /**
             *
             */
            public function read() : Promise
            {
                if (!$this->stream) {
                    return call(function () {
                        /** @var InputStream $stream */
                        $stream = (yield $this->promise);
                        return $stream->read();
                    });
                }
                return $this->stream->read();
            }
        };
    }
    /**
     *
     */
    public function getHeaders() : Promise
    {
        return new Success([]);
    }
    /**
     *
     */
    public function getBodyLength() : Promise
    {
        return \function_exists('Amp\\File\\getSize') ? getSize($this->path) : size($this->path);
    }
}<?php

namespace Amp\Http\Client\Body;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\Http\Client\RequestBody;
use Amp\Promise;
use Amp\Success;
final class StringBody implements RequestBody
{
    private $body;
    /**
     *
     */
    public function __construct(string $body)
    {
        $this->body = $body;
    }
    /**
     *
     */
    public function createBodyStream() : InputStream
    {
        return new InMemoryStream($this->body !== '' ? $this->body : null);
    }
    /**
     *
     */
    public function getHeaders() : Promise
    {
        return new Success([]);
    }
    /**
     *
     */
    public function getBodyLength() : Promise
    {
        return new Success(\strlen($this->body));
    }
}<?php

namespace Amp\Http\Client\Body;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\ByteStream\IteratorStream;
use Amp\Http\Client\RequestBody;
use Amp\Producer;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class FormBody implements RequestBody
{
    /** @var (array{0: string, 1: string, 2: string, 3: null}|array{0: string, 1: FileBody, 2: string, 3: string})[] */
    private $fields = [];
    /** @var string */
    private $boundary;
    /** @var bool */
    private $isMultipart = false;
    /** @var string|null */
    private $cachedBody;
    /** @var Promise<int>|null */
    private $cachedLength;
    /** @var list<string|FileBody>|null */
    private $cachedFields;
    /**
     * @param string $boundary An optional multipart boundary string
     */
    public function __construct(string $boundary = null)
    {
        /** @noinspection PhpUnhandledExceptionInspection */
        $this->boundary = $boundary ?? \bin2hex(\random_bytes(16));
    }
    /**
     * Add a data field to the form entity body.
     *
     * @param string $name
     * @param string $value
     * @param string $contentType
     */
    public function addField(string $name, string $value, string $contentType = 'text/plain') : void
    {
        $this->fields[] = [$name, $value, $contentType, null];
        $this->resetCache();
    }
    /**
     * Add each element of a associative array as a data field to the form entity body.
     *
     * @param array $data
     * @param string $contentType
     */
    public function addFields(array $data, string $contentType = 'text/plain') : void
    {
        foreach ($data as $key => $value) {
            $this->addField($key, $value, $contentType);
        }
    }
    /**
     * Add a file field to the form entity body.
     *
     * @param string $name
     * @param string $filePath
     * @param string $contentType
     */
    public function addFile(string $name, string $filePath, string $contentType = 'application/octet-stream') : void
    {
        $fileName = \basename($filePath);
        $this->fields[] = [$name, new FileBody($filePath), $contentType, $fileName];
        $this->isMultipart = true;
        $this->resetCache();
    }
    /**
     * Add each element of a associative array as a file field to the form entity body.
     *
     * @param array $data
     * @param string $contentType
     */
    public function addFiles(array $data, string $contentType = 'application/octet-stream') : void
    {
        foreach ($data as $key => $value) {
            $this->addFile($key, $value, $contentType);
        }
    }
    /**
     * Add a file field to the form from a string.
     *
     * @param string $name
     * @param string $fileContent
     * @param string $fileName
     * @param string $contentType
     */
    public function addFileFromString(string $name, string $fileContent, string $fileName, string $contentType = 'application/octet-stream') : void
    {
        $this->fields[] = [$name, $fileContent, $contentType, $fileName];
        $this->isMultipart = true;
        $this->resetCache();
    }
    /**
    * Returns an array of fields, each being an array of [name, value, content-type, file-name|null].
    Both fields and files are returned in the array. Files use a FileBody object as the value. The file-name is
    always null for fields.
    *
    * @return array
    */
    public function getFields() : array
    {
        return $this->fields;
    }
    /**
     *
     */
    private function resetCache() : void
    {
        $this->cachedBody = null;
        $this->cachedLength = null;
        $this->cachedFields = null;
    }
    /**
     *
     */
    public function createBodyStream() : InputStream
    {
        if ($this->isMultipart) {
            return $this->generateMultipartStreamFromFields($this->getMultipartFieldArray());
        }
        return new InMemoryStream($this->getFormEncodedBodyString());
    }
    /**
     *
     */
    private function getMultipartFieldArray() : array
    {
        if (isset($this->cachedFields)) {
            return $this->cachedFields;
        }
        $fields = [];
        foreach ($this->fields as $fieldArr) {
            [$name, $field, $contentType, $fileName] = $fieldArr;
            $fields[] = "--{$this->boundary}\r\n";
            /** @psalm-suppress PossiblyNullArgument */
            $fields[] = $fileName !== null ? $this->generateMultipartFileHeader($name, $fileName, $contentType) : $this->generateMultipartFieldHeader($name, $contentType);
            $fields[] = $field;
            $fields[] = "\r\n";
        }
        $fields[] = "--{$this->boundary}--\r\n";
        return $this->cachedFields = $fields;
    }
    /**
     *
     */
    private function generateMultipartFileHeader(string $name, string $fileName, string $contentType) : string
    {
        $header = "Content-Disposition: form-data; name=\"{$name}\"; filename=\"{$fileName}\"\r\n";
        $header .= "Content-Type: {$contentType}\r\n";
        $header .= "Content-Transfer-Encoding: binary\r\n\r\n";
        return $header;
    }
    /**
     *
     */
    private function generateMultipartFieldHeader(string $name, string $contentType) : string
    {
        $header = "Content-Disposition: form-data; name=\"{$name}\"\r\n";
        if ($contentType !== "") {
            $header .= "Content-Type: {$contentType}\r\n\r\n";
        } else {
            $header .= "\r\n";
        }
        return $header;
    }
    /**
     *
     */
    private function generateMultipartStreamFromFields(array $fields) : InputStream
    {
        foreach ($fields as $key => $field) {
            $fields[$key] = $field instanceof FileBody ? $field->createBodyStream() : new InMemoryStream($field);
        }
        return new IteratorStream(new Producer(static function (callable $emit) use($fields) {
            foreach ($fields as $key => $stream) {
                while (($chunk = (yield $stream->read())) !== null) {
                    (yield $emit($chunk));
                }
            }
        }));
    }
    /**
     *
     */
    private function getFormEncodedBodyString() : string
    {
        if ($this->cachedBody) {
            return $this->cachedBody;
        }
        $fields = [];
        foreach ($this->fields as $fieldArr) {
            [$name, $value] = $fieldArr;
            $fields[$name][] = $value;
        }
        foreach ($fields as $key => $value) {
            $fields[$key] = isset($value[1]) ? $value : $value[0];
        }
        return $this->cachedBody = \http_build_query($fields);
    }
    /**
     *
     */
    public function getHeaders() : Promise
    {
        return new Success(['Content-Type' => $this->determineContentType()]);
    }
    /**
     *
     */
    private function determineContentType() : string
    {
        return $this->isMultipart ? "multipart/form-data; boundary={$this->boundary}" : 'application/x-www-form-urlencoded';
    }
    /**
     *
     */
    public function getBodyLength() : Promise
    {
        if ($this->cachedLength) {
            return $this->cachedLength;
        }
        if (!$this->isMultipart) {
            return $this->cachedLength = new Success(\strlen($this->getFormEncodedBodyString()));
        }
        /** @var Promise<int> $lengthPromise */
        $lengthPromise = call(function () : \Generator {
            $fields = $this->getMultipartFieldArray();
            $length = 0;
            foreach ($fields as $field) {
                if (\is_string($field)) {
                    $length += \strlen($field);
                } else {
                    $length += (yield $field->getBodyLength());
                }
            }
            return $length;
        });
        return $this->cachedLength = $lengthPromise;
    }
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\Http\Client\Body;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\RequestBody;
use Amp\Promise;
use Amp\Success;
final class JsonBody implements RequestBody
{
    /** @var string */
    private $json;
    /**
     * JsonBody constructor.
     *
     * @param mixed $data
     * @param int $options
     * @param int $depth
     *
     * @throws HttpException
     */
    public function __construct($data, int $options = 0, int $depth = 512)
    {
        $this->json = \json_encode($data, $options, $depth);
        if (\json_last_error() !== \JSON_ERROR_NONE) {
            throw new HttpException('Failed to encode data to JSON');
        }
    }
    /**
     *
     */
    public function getHeaders() : Promise
    {
        return new Success(['content-type' => 'application/json; charset=utf-8']);
    }
    /**
     *
     */
    public function createBodyStream() : InputStream
    {
        return new InMemoryStream($this->json);
    }
    /**
     *
     */
    public function getBodyLength() : Promise
    {
        return new Success(\strlen($this->json));
    }
}<?php

namespace Amp\Http\Client;

use Amp\Http\Client\Connection\ConnectionPool;
use Amp\Http\Client\Connection\Stream;
use Amp\Promise;
/**
 * Allows listening to more fine granular events than interceptors are able to achieve.
 *
 * All event listener methods might be called multiple times for a single request. The implementing listener is
 * responsible to detect another call, e.g. via attributes in the request.
 */
interface EventListener
{
    /**
     * Called at the very beginning of {@see DelegateHttpClient::request()}.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startRequest(Request $request) : Promise;
    /**
     * Optionally called by {@see ConnectionPool::getStream()} before DNS resolution is started.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startDnsResolution(Request $request) : Promise;
    /**
     * Optionally called by {@see ConnectionPool::getStream()} after DNS resolution is completed.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeDnsResolution(Request $request) : Promise;
    /**
     * Called by {@see ConnectionPool::getStream()} before a new connection is initiated.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startConnectionCreation(Request $request) : Promise;
    /**
     * Called by {@see ConnectionPool::getStream()} after a new connection is established and TLS negotiated.
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeConnectionCreation(Request $request) : Promise;
    /**
     * Called by {@see ConnectionPool::getStream()} before TLS negotiation is started (only if HTTPS is used).
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startTlsNegotiation(Request $request) : Promise;
    /**
     * Called by {@see ConnectionPool::getStream()} after TLS negotiation is successful (only if HTTPS is used).
     *
     * @param Request $request
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeTlsNegotiation(Request $request) : Promise;
    /**
     * Called by {@see Stream::request()} before the request is sent.
     *
     * @param Request $request
     * @param Stream $stream
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startSendingRequest(Request $request, Stream $stream) : Promise;
    /**
     * Called by {@see Stream::request()} after the request is sent.
     *
     * @param Request $request
     * @param Stream $stream
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeSendingRequest(Request $request, Stream $stream) : Promise;
    /**
     * Called by {@see Stream::request()} after the first response byte is received.
     *
     * @param Request $request
     * @param Stream $stream
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function startReceivingResponse(Request $request, Stream $stream) : Promise;
    /**
     * Called by {@see Stream::request()} after the request is complete.
     *
     * @param Request $request
     * @param Stream $stream
     *
     * @return Promise Should resolve successfully, otherwise aborts the request.
     */
    public function completeReceivingResponse(Request $request, Stream $stream) : Promise;
    /**
     * Called if the request is aborted.
     *
     * @param Request $request
     * @param \Throwable $cause
     *
     * @return Promise Should resolve successfully.
     */
    public function abort(Request $request, \Throwable $cause) : Promise;
}<?php

namespace Amp\Http\Client;

final class TimeoutException extends HttpException
{
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Request;
use Amp\Promise;
interface ConnectionFactory
{
    /**
    * During connection establishment, the factory must call the {@see EventListener::startConnectionCreation()},
    {@see EventListener::startTlsNegotiation()}, {@see EventListener::completeTlsNegotiation()}, and
    {@see EventListener::completeConnectionCreation()} on all event listeners registered on the given request in the
    order defined by {@see Request::getEventListeners()} as appropriate (TLS events are only invoked if TLS is
    used). Before calling the next listener, the promise returned from the previous one must resolve successfully.
    *
    * Additionally, the factory may invoke {@see EventListener::startDnsResolution()} and
    {@see EventListener::completeDnsResolution()}, but is not required to implement such granular events.
    *
    * @param Request $request
    * @param CancellationToken $cancellationToken
    *
    * @return Promise
    */
    public function create(Request $request, CancellationToken $cancellationToken) : Promise;
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\EventListener;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
interface Stream extends DelegateHttpClient
{
    /**
    * Executes the request.
    *
    * This method may only be invoked once per instance.
    *
    * The stream must call {@see EventListener::startSendingRequest()},
    {@see EventListener::completeSendingRequest()}, {@see EventListener::startReceivingResponse()}, and
    {@see EventListener::completeReceivingResponse()} event listener methods on all event listeners registered on
    the given request in the order defined by {@see Request::getEventListeners()}. Before calling the next listener,
    the promise returned from the previous one must resolve successfully.
    *
    * @param Request $request
    * @param CancellationToken $cancellation
    *
    * @return Promise<Response>
    *
    * @throws \Error Thrown if this method is called more than once.
    */
    public function request(Request $request, CancellationToken $cancellation) : Promise;
    /**
     *
     */
    public function getLocalAddress() : SocketAddress;
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress;
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo;
}<?php

namespace Amp\Http\Client\Connection;

// Alias for backward compatibility.
\class_alias(StreamLimitingPool::class, LimitedConnectionPool::class);<?php

namespace Amp\Http\Client\Connection;

use Amp\Http\Client\HttpException;
/**
 * @deprecated Exception moved to amphp/http. Catch the base exception class (HttpException) instead.
 */
final class Http2ConnectionException extends HttpException
{
    /**
     *
     */
    public function __construct(string $message, int $code, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Http\Client\Connection\Internal;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Loop;
use Amp\Promise;
use Amp\Struct;
/**
 * Used in Http2Connection.
 *
 * @internal
 */
final class Http2Stream
{
    use Struct;
    use ForbidSerialization;
    use ForbidCloning;
    /** @var int */
    public $id;
    /** @var Request */
    public $request;
    /** @var Response|null */
    public $response;
    /** @var Deferred|null */
    public $pendingResponse;
    /** @var Promise|null */
    public $preResponseResolution;
    /** @var bool */
    public $responsePending = true;
    /** @var Emitter|null */
    public $body;
    /** @var Deferred|null */
    public $trailers;
    /** @var CancellationToken */
    public $originalCancellation;
    /** @var CancellationToken */
    public $cancellationToken;
    /** @var int Bytes received on the stream. */
    public $received = 0;
    /** @var int */
    public $serverWindow;
    /** @var int */
    public $clientWindow;
    /** @var int */
    public $bufferSize;
    /** @var string */
    public $requestBodyBuffer = '';
    /** @var bool */
    public $requestBodyComplete = false;
    /** @var Deferred */
    public $requestBodyCompletion;
    /** @var int Integer between 1 and 256 */
    public $weight = 16;
    /** @var int */
    public $dependency = 0;
    /** @var int|null */
    public $expectedLength;
    /** @var Stream */
    public $stream;
    /** @var Deferred|null */
    public $windowSizeIncrease;
    /** @var string|null */
    private $watcher;
    /**
     *
     */
    public function __construct(int $id, Request $request, Stream $stream, CancellationToken $cancellationToken, CancellationToken $originalCancellation, ?string $watcher, int $serverSize, int $clientSize)
    {
        $this->id = $id;
        $this->request = $request;
        $this->stream = $stream;
        $this->cancellationToken = $cancellationToken;
        $this->originalCancellation = $originalCancellation;
        $this->watcher = $watcher;
        $this->serverWindow = $serverSize;
        $this->clientWindow = $clientSize;
        $this->pendingResponse = new Deferred();
        $this->requestBodyCompletion = new Deferred();
        $this->bufferSize = 0;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->watcher !== null) {
            Loop::cancel($this->watcher);
        }
    }
    /**
     *
     */
    public function disableInactivityWatcher() : void
    {
        if ($this->watcher === null) {
            return;
        }
        Loop::disable($this->watcher);
    }
    /**
     *
     */
    public function enableInactivityWatcher() : void
    {
        if ($this->watcher === null) {
            return;
        }
        Loop::disable($this->watcher);
        Loop::enable($this->watcher);
    }
}<?php

/** @noinspection PhpUnusedPrivateFieldInspection */
namespace Amp\Http\Client\Connection\Internal;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\IteratorStream;
use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\CancellationTokenSource;
use Amp\CancelledException;
use Amp\CombinedCancellationToken;
use Amp\Coroutine;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Failure;
use Amp\Http\Client\Connection\Http2ConnectionException as ClientHttp2ConnectionException;
use Amp\Http\Client\Connection\Http2StreamException as ClientHttp2StreamException;
use Amp\Http\Client\Connection\HttpStream;
use Amp\Http\Client\Connection\Stream;
use Amp\Http\Client\Connection\UnprocessedRequestException;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ResponseBodyStream;
use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Client\SocketException;
use Amp\Http\Client\TimeoutException;
use Amp\Http\Client\Trailers;
use Amp\Http\HPack;
use Amp\Http\Http2\Http2ConnectionException;
use Amp\Http\Http2\Http2Parser;
use Amp\Http\Http2\Http2Processor;
use Amp\Http\Http2\Http2StreamException;
use Amp\Http\InvalidHeaderException;
use Amp\Http\Status;
use Amp\Iterator;
use Amp\Loop;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Success;
use Amp\TimeoutCancellationToken;
use League\Uri;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\Http\Client\Internal\normalizeRequestPathWithQuery;
/** @internal */
final class Http2ConnectionProcessor implements Http2Processor
{
    private const PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
    private const DEFAULT_MAX_FRAME_SIZE = 1 << 14;
    private const DEFAULT_WINDOW_SIZE = (1 << 16) - 1;
    private const MINIMUM_WINDOW = 512 * 1024;
    private const WINDOW_INCREMENT = 1024 * 1024;
    // Milliseconds to wait for pong (PING with ACK) frame before closing the connection.
    private const PONG_TIMEOUT = 5000;
    /** @var string 64-bit for ping. */
    private $counter = "aaaaaaaa";
    /** @var EncryptableSocket */
    private $socket;
    /** @var Http2Stream[] */
    private $streams = [];
    /** @var int */
    private $serverWindow = self::DEFAULT_WINDOW_SIZE;
    /** @var int */
    private $clientWindow = self::DEFAULT_WINDOW_SIZE;
    /** @var int */
    private $initialWindowSize = self::DEFAULT_WINDOW_SIZE;
    /** @var int */
    private $frameSizeLimit = self::DEFAULT_MAX_FRAME_SIZE;
    /** @var int Previous stream ID. */
    private $streamId = -1;
    /** @var int Maximum number of streams that may be opened. Initially unlimited. */
    private $concurrentStreamLimit = 2147483647;
    /** @var int Currently open or reserved streams. Initially unlimited. */
    private $remainingStreams = 2147483647;
    /** @var HPack */
    private $hpack;
    /** @var Deferred|null */
    private $settings;
    /** @var bool */
    private $initializeStarted = false;
    /** @var bool */
    private $initialized = false;
    /** @var string|null */
    private $pongWatcher;
    /** @var Deferred|null */
    private $pongDeferred;
    /** @var string|null */
    private $idleWatcher;
    /** @var int */
    private $idlePings = 0;
    /** @var callable[]|null */
    private $onClose = [];
    /** @var bool */
    private $hasTimeout = false;
    /** @var bool */
    private $hasWriteError = false;
    /** @var int|null */
    private $shutdown;
    /** @var Emitter */
    private $frameQueueEmitter;
    /** @var Iterator */
    private $frameQueue;
    /**
     *
     */
    public function __construct(EncryptableSocket $socket)
    {
        $this->socket = $socket;
        $this->hpack = new HPack();
        $this->frameQueueEmitter = new Emitter();
        $this->frameQueue = $this->frameQueueEmitter->iterate();
    }
    /**
     *
     */
    public function isInitialized() : bool
    {
        return $this->initialized;
    }
    /**
    * Returns a promise that is resolved once the connection has been initialized. A stream cannot be obtained from the
    connection until the promise returned by this method resolves.
    *
    * @return Promise
    */
    public function initialize() : Promise
    {
        if ($this->initializeStarted) {
            throw new \Error('Connection may only be initialized once');
        }
        $this->initializeStarted = true;
        if ($this->socket->isClosed()) {
            return new Failure(new UnprocessedRequestException(new SocketException('The socket closed before the connection could be initialized')));
        }
        $this->settings = new Deferred();
        $promise = $this->settings->promise();
        Promise\rethrow(new Coroutine($this->run()));
        return $promise;
    }
    /**
     *
     */
    public function onClose(callable $onClose) : void
    {
        if ($this->onClose === null) {
            asyncCall($onClose, $this);
            return;
        }
        $this->onClose[] = $onClose;
    }
    /**
     *
     */
    public function close() : Promise
    {
        $this->shutdown(new SocketException('Socket from \'' . $this->socket->getLocalAddress() . '\' to \'' . $this->socket->getRemoteAddress() . '\' closed'));
        $this->socket->close();
        if ($this->onClose !== null) {
            $onClose = $this->onClose;
            $this->onClose = null;
            foreach ($onClose as $callback) {
                asyncCall($callback, $this);
            }
        }
        return new Success();
    }
    /**
     *
     */
    public function handlePong(string $data) : void
    {
        if ($this->pongDeferred === null) {
            return;
        }
        if ($this->pongWatcher !== null) {
            Loop::cancel($this->pongWatcher);
            $this->pongWatcher = null;
        }
        $this->hasTimeout = false;
        $deferred = $this->pongDeferred;
        $this->pongDeferred = null;
        $deferred->resolve(true);
    }
    /**
     *
     */
    public function handlePing(string $data) : void
    {
        $this->writeFrame(Http2Parser::PING, Http2Parser::ACK, 0, $data);
    }
    /**
     *
     */
    public function handleShutdown(int $lastId, int $error) : void
    {
        $message = \sprintf("Received GOAWAY frame on '%s' from '%s' with error code %d", (string) $this->socket->getLocalAddress(), (string) $this->socket->getRemoteAddress(), $error);
        /**
         * @psalm-suppress DeprecatedClass
         * @noinspection PhpDeprecationInspection
         */
        $this->shutdown(new ClientHttp2ConnectionException($message, $error), $lastId);
    }
    /**
     *
     */
    public function handleStreamWindowIncrement(int $streamId, int $windowSize) : void
    {
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        if ($stream->clientWindow + $windowSize > 2147483647) {
            $this->handleStreamException(new Http2StreamException("Current window size plus new window exceeds maximum size", $streamId, Http2Parser::FLOW_CONTROL_ERROR));
            return;
        }
        $stream->clientWindow += $windowSize;
        $this->writeBufferedData($stream);
    }
    /**
     *
     */
    public function handleConnectionWindowIncrement(int $windowSize) : void
    {
        if ($this->clientWindow + $windowSize > 2147483647) {
            $this->handleConnectionException(new Http2ConnectionException("Current window size plus new window exceeds maximum size", Http2Parser::FLOW_CONTROL_ERROR));
            return;
        }
        $this->clientWindow += $windowSize;
        foreach ($this->streams as $stream) {
            if ($this->clientWindow <= 0) {
                return;
            }
            if ($stream->requestBodyBuffer === '' || $stream->clientWindow <= 0) {
                continue;
            }
            $this->writeBufferedData($stream);
        }
    }
    /**
     *
     */
    public function handleHeaders(int $streamId, array $pseudo, array $headers, bool $streamEnded) : void
    {
        foreach ($pseudo as $name => $value) {
            if (!isset(Http2Parser::KNOWN_RESPONSE_PSEUDO_HEADERS[$name])) {
                throw new Http2StreamException("Invalid pseudo header", $streamId, Http2Parser::PROTOCOL_ERROR);
            }
        }
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        $stream->enableInactivityWatcher();
        $this->hasTimeout = false;
        if ($stream->trailers) {
            if ($stream->expectedLength && $stream->received !== $stream->expectedLength) {
                $diff = $stream->expectedLength - $stream->received;
                $this->handleStreamException(new Http2StreamException("Content length mismatch: " . \abs($diff) . ' bytes ' . ($diff > 0 ? ' missing' : 'too much'), $streamId, Http2Parser::PROTOCOL_ERROR));
                return;
            }
            if (!empty($pseudo)) {
                $this->handleStreamException(new Http2StreamException("Trailers must not contain pseudo headers", $streamId, Http2Parser::PROTOCOL_ERROR));
                return;
            }
            try {
                // Constructor checks for any disallowed fields
                $parsedTrailers = new Trailers($headers);
            } catch (InvalidHeaderException $exception) {
                $this->handleStreamException(new Http2StreamException("Disallowed field names in trailer", $streamId, Http2Parser::PROTOCOL_ERROR, $exception));
                return;
            }
            $trailers = $stream->trailers;
            $stream->trailers = null;
            $trailers->resolve(call(function () use($stream, $streamId, $parsedTrailers) {
                try {
                    foreach ($stream->request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeReceivingResponse($stream->request, $stream->stream));
                    }
                    return $parsedTrailers;
                } catch (\Throwable $e) {
                    $this->handleStreamException(new Http2StreamException("Event listener error", $streamId, Http2Parser::CANCEL));
                    throw $e;
                }
            }));
            $this->setupPingIfIdle();
            return;
        }
        if (!isset($pseudo[":status"])) {
            $this->handleConnectionException(new Http2ConnectionException("No status pseudo header in response", Http2Parser::PROTOCOL_ERROR));
            return;
        }
        if (!\preg_match("/^[1-5]\\d\\d\$/", $pseudo[":status"])) {
            $this->handleStreamException(new Http2StreamException("Invalid response status code: " . $pseudo[':status'], $streamId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        if ($stream->response !== null) {
            $this->handleStreamException(new Http2StreamException("Stream headers already received", $streamId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $status = (int) $pseudo[":status"];
        if ($status === Status::SWITCHING_PROTOCOLS) {
            $this->handleConnectionException(new Http2ConnectionException("Switching Protocols (101) is not part of HTTP/2", Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $response = new Response('2', $status, Status::getReason($status), $headers, new InMemoryStream(), $stream->request);
        if ($status < 200) {
            $onInformationalResponse = $stream->request->getInformationalResponseHandler();
            if ($onInformationalResponse !== null) {
                $stream->preResponseResolution = call(function () use($onInformationalResponse, $response, $stream, $streamId) {
                    (yield $stream->preResponseResolution);
                    try {
                        (yield call($onInformationalResponse, $response));
                    } catch (\Throwable $e) {
                        $this->handleStreamException(new Http2StreamException('Informational response handler threw an exception', $streamId, Http2Parser::CANCEL));
                    }
                });
            }
            return;
        }
        \assert($stream->preResponseResolution === null);
        $stream->preResponseResolution = call(function () use($stream, $streamId) {
            try {
                foreach ($stream->request->getEventListeners() as $eventListener) {
                    (yield $eventListener->startReceivingResponse($stream->request, $stream->stream));
                }
            } catch (\Throwable $e) {
                $this->handleStreamException(new Http2StreamException("Event listener error", $streamId, Http2Parser::CANCEL));
            }
        });
        $stream->body = new Emitter();
        $stream->trailers = new Deferred();
        $bodyCancellation = new CancellationTokenSource();
        $cancellationToken = new CombinedCancellationToken($stream->cancellationToken, $bodyCancellation->getToken());
        $response->setBody(new ResponseBodyStream(new IteratorStream($stream->body->iterate()), $bodyCancellation));
        $response->setTrailers($stream->trailers->promise());
        \assert($stream->pendingResponse !== null);
        $stream->responsePending = false;
        $stream->pendingResponse->resolve(call(static function () use($response, $stream) {
            (yield $stream->requestBodyCompletion->promise());
            (yield $stream->preResponseResolution);
            $stream->preResponseResolution = null;
            $stream->pendingResponse = null;
            return $response;
        }));
        $this->increaseConnectionWindow();
        $this->increaseStreamWindow($stream);
        if (isset($headers["content-length"])) {
            if (\count($headers['content-length']) !== 1) {
                $this->handleStreamException(new Http2StreamException("Multiple content-length header values", $streamId, Http2Parser::PROTOCOL_ERROR));
                return;
            }
            $contentLength = $headers["content-length"][0];
            if (!\preg_match('/^(0|[1-9][0-9]*)$/', $contentLength)) {
                $this->handleStreamException(new Http2StreamException("Invalid content-length header value", $streamId, Http2Parser::PROTOCOL_ERROR));
                return;
            }
            $stream->expectedLength = (int) $contentLength;
        }
        $cancellationToken->subscribe(function (CancelledException $exception) use($streamId) : void {
            if (!isset($this->streams[$streamId])) {
                return;
            }
            $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $streamId, \pack("N", Http2Parser::CANCEL));
            if (!$this->streams[$streamId]->originalCancellation->isRequested()) {
                $this->hasTimeout = true;
                $this->ping();
                // async ping, if other requests occur, they wait for it
                $transferTimeout = $this->streams[$streamId]->request->getTransferTimeout();
                $exception = new TimeoutException('Allowed transfer timeout exceeded, took longer than ' . $transferTimeout . ' ms', 0, $exception);
            }
            $this->releaseStream($streamId, $exception);
        });
    }
    /**
     *
     */
    public function handlePushPromise(int $streamId, int $pushId, array $pseudo, array $headers) : void
    {
        if ($pushId % 2 === 1) {
            $this->handleConnectionException(new Http2ConnectionException("Invalid server initiated stream", Http2Parser::PROTOCOL_ERROR));
            return;
        }
        foreach ($pseudo as $name => $value) {
            if (!isset(Http2Parser::KNOWN_REQUEST_PSEUDO_HEADERS[$name])) {
                throw new Http2StreamException("Invalid pseudo header", $pushId, Http2Parser::PROTOCOL_ERROR);
            }
        }
        if (!isset($pseudo[":method"], $pseudo[":path"], $pseudo[":scheme"], $pseudo[":authority"]) || isset($headers["connection"]) || $pseudo[":path"] === '' || isset($headers["te"]) && \implode($headers["te"]) !== "trailers") {
            $this->handleStreamException(new Http2StreamException("Invalid header values", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $method = $pseudo[":method"];
        $target = $pseudo[":path"];
        $scheme = $pseudo[":scheme"];
        $host = $pseudo[":authority"];
        $query = null;
        if ($method !== 'GET' && $method !== 'HEAD') {
            $this->handleStreamException(new Http2StreamException("Pushed request method must be a safe method", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        if (!\preg_match("#^([A-Z\\d.\\-]+|\\[[\\d:]+])(?::([1-9]\\d*))?\$#i", $host, $matches)) {
            $this->handleStreamException(new Http2StreamException("Invalid pushed authority (host) name", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $host = $matches[1];
        $port = isset($matches[2]) ? (int) $matches[2] : $this->socket->getRemoteAddress()->getPort();
        if (!isset($this->streams[$streamId])) {
            $this->handleStreamException(new Http2StreamException("Parent stream {$streamId} is no longer open", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $parentStream = $this->streams[$streamId];
        $parentStream->enableInactivityWatcher();
        if (\strcasecmp($host, $parentStream->request->getUri()->getHost()) !== 0) {
            $this->handleStreamException(new Http2StreamException("Authority does not match original request authority", $pushId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        if ($position = \strpos($target, "#")) {
            $target = \Phabel\Target\Php80\Polyfill::substr($target, 0, $position);
        }
        if ($position = \strpos($target, "?")) {
            $query = \Phabel\Target\Php80\Polyfill::substr($target, $position + 1);
            $target = \Phabel\Target\Php80\Polyfill::substr($target, 0, $position);
        }
        try {
            $uri = Uri\Http::createFromComponents(["scheme" => $scheme, "host" => $host, "port" => $port, "path" => $target, "query" => $query]);
        } catch (\Exception $exception) {
            $this->handleConnectionException(new Http2ConnectionException("Invalid push URI", Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $request = new Request($uri, $method);
        $request->setHeaders($headers);
        $request->setProtocolVersions(['2']);
        $request->setPushHandler($parentStream->request->getPushHandler());
        $request->setHeaderSizeLimit($parentStream->request->getHeaderSizeLimit());
        $request->setBodySizeLimit($parentStream->request->getBodySizeLimit());
        $request->setInactivityTimeout($parentStream->request->getInactivityTimeout());
        $request->setTransferTimeout($parentStream->request->getTransferTimeout());
        $stream = new Http2Stream($pushId, $request, HttpStream::fromStream($parentStream->stream, static function () {
            throw new \Error('Calling Stream::request() on a pushed request is forbidden');
        }, static function () {
            // nothing to do
        }), $parentStream->cancellationToken, $parentStream->originalCancellation, $this->createStreamInactivityWatcher($pushId, $request->getInactivityTimeout()), self::DEFAULT_WINDOW_SIZE, 0);
        $stream->dependency = $streamId;
        $this->streams[$pushId] = $stream;
        $stream->requestBodyComplete = true;
        $stream->requestBodyCompletion->resolve();
        if ($parentStream->request->getPushHandler() === null) {
            $this->handleStreamException(new Http2StreamException("Push promise refused", $pushId, Http2Parser::CANCEL));
            return;
        }
        asyncCall(function () use($pushId, $stream) : \Generator {
            $tokenSource = new CancellationTokenSource();
            $cancellationToken = new CombinedCancellationToken($stream->cancellationToken, $tokenSource->getToken());
            $cancellationId = $cancellationToken->subscribe(function (CancelledException $exception) use($pushId) : void {
                if (!isset($this->streams[$pushId])) {
                    return;
                }
                $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $pushId, \pack("N", Http2Parser::CANCEL));
                $this->releaseStream($pushId, $exception);
            });
            $onPush = $stream->request->getPushHandler();
            try {
                \assert($onPush !== null);
                \assert($stream->pendingResponse !== null);
                (yield call($onPush, $stream->request, $stream->pendingResponse->promise()));
            } catch (HttpException|StreamException|CancelledException $exception) {
                $tokenSource->cancel($exception);
            } catch (\Throwable $exception) {
                $tokenSource->cancel($exception);
                throw $exception;
            } finally {
                $cancellationToken->unsubscribe($cancellationId);
            }
        });
    }
    /**
     *
     */
    public function handlePriority(int $streamId, int $parentId, int $weight) : void
    {
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        $stream->dependency = $parentId;
        $stream->weight = $weight;
    }
    /**
     *
     */
    public function handleStreamReset(int $streamId, int $errorCode) : void
    {
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $this->handleStreamException(new Http2StreamException("Stream closed by server", $streamId, $errorCode));
    }
    /**
     *
     */
    public function handleStreamException(Http2StreamException $exception) : void
    {
        $id = $exception->getStreamId();
        $code = $exception->getCode();
        /**
         * @psalm-suppress DeprecatedClass
         * @psalm-suppress InvalidScalarArgument
         * @noinspection PhpDeprecationInspection
         */
        $exception = new ClientHttp2StreamException($exception->getMessage(), $id, $code, $exception);
        if ($code === Http2Parser::REFUSED_STREAM) {
            $exception = new UnprocessedRequestException($exception);
        }
        $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $id, \pack("N", $code));
        if (isset($this->streams[$id])) {
            $this->releaseStream($id, $exception);
        }
    }
    /**
     *
     */
    public function handleConnectionException(Http2ConnectionException $exception) : void
    {
        /**
         * @psalm-suppress DeprecatedClass
         * @psalm-suppress InvalidScalarArgument
         * @noinspection PhpDeprecationInspection
         */
        $this->shutdown(new ClientHttp2ConnectionException($exception->getMessage(), $exception->getCode(), $exception));
        $this->close();
    }
    /**
     *
     */
    public function handleData(int $streamId, string $data) : void
    {
        $length = \strlen($data);
        $this->serverWindow -= $length;
        $this->increaseConnectionWindow();
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        $stream->disableInactivityWatcher();
        if (!$stream->body) {
            $this->handleStreamException(new Http2StreamException("Stream headers not complete or body already complete", $streamId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $stream->serverWindow -= $length;
        $stream->received += $length;
        $stream->bufferSize += $length;
        if ($stream->request->getBodySizeLimit() > 0 && $stream->received >= $stream->request->getBodySizeLimit()) {
            $this->handleStreamException(new Http2StreamException("Body size limit exceeded", $streamId, Http2Parser::CANCEL));
            return;
        }
        if ($stream->expectedLength !== null && $stream->received > $stream->expectedLength) {
            $this->handleStreamException(new Http2StreamException("Body size exceeded content-length in header", $streamId, Http2Parser::CANCEL));
            return;
        }
        $promise = $stream->body->emit($data);
        $promise->onResolve(function (?\Throwable $exception) use($streamId, $length) : void {
            if ($exception || !isset($this->streams[$streamId])) {
                return;
            }
            // Defer prevents sending increments for already closed streams
            Loop::defer(function () use($streamId, $length) {
                if (!isset($this->streams[$streamId])) {
                    return;
                }
                $this->streams[$streamId]->bufferSize -= $length;
                if ($this->streams[$streamId]->bufferSize === 0) {
                    $this->streams[$streamId]->enableInactivityWatcher();
                }
                $this->increaseStreamWindow($this->streams[$streamId]);
            });
        });
    }
    /**
     *
     */
    public function handleSettings(array $settings) : void
    {
        foreach ($settings as $setting => $value) {
            $this->applySetting($setting, $value);
        }
        $this->writeFrame(Http2Parser::SETTINGS, Http2Parser::ACK);
        if ($this->settings) {
            $deferred = $this->settings;
            $this->settings = null;
            $this->initialized = true;
            $deferred->resolve($this->remainingStreams);
        }
    }
    /**
     *
     */
    public function handleStreamEnd(int $streamId) : void
    {
        if (!isset($this->streams[$streamId])) {
            return;
        }
        $stream = $this->streams[$streamId];
        if ($stream->expectedLength !== null && $stream->received !== $stream->expectedLength) {
            $this->handleStreamException(new Http2StreamException("Body length does not match content-length header", $streamId, Http2Parser::PROTOCOL_ERROR));
            return;
        }
        $body = $stream->body;
        $stream->body = null;
        \assert($body !== null);
        $trailers = $stream->trailers;
        $stream->trailers = null;
        \assert($trailers !== null);
        $body->complete();
        $trailers->resolve(call(function () use($stream, $streamId) {
            try {
                foreach ($stream->request->getEventListeners() as $eventListener) {
                    (yield $eventListener->completeReceivingResponse($stream->request, $stream->stream));
                }
                return new Trailers([]);
            } catch (\Throwable $e) {
                $this->handleStreamException(new Http2StreamException("Event listener error", $streamId, Http2Parser::CANCEL));
                throw $e;
            }
        }));
        $this->setupPingIfIdle();
        // Stream might be cancelled right after body completion
        if (isset($this->streams[$streamId])) {
            $this->releaseStream($streamId);
        }
    }
    /**
     *
     */
    public function reserveStream() : void
    {
        if ($this->shutdown !== null || $this->hasWriteError || $this->hasTimeout) {
            throw new \Error("Can't reserve stream after shutdown started");
        }
        --$this->remainingStreams;
    }
    /**
     *
     */
    public function unreserveStream() : void
    {
        ++$this->remainingStreams;
        \assert($this->remainingStreams <= $this->concurrentStreamLimit);
    }
    /**
     *
     */
    public function getRemainingStreams() : int
    {
        if ($this->shutdown !== null || $this->hasWriteError || $this->hasTimeout) {
            return 0;
        }
        return $this->remainingStreams;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellationToken, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellationToken, $stream) : \Generator {
            if ($this->shutdown !== null) {
                $exception = new UnprocessedRequestException(new SocketException(\sprintf("Connection from '%s' to '%s' has already been shut down", (string) $this->socket->getLocalAddress(), (string) $this->socket->getRemoteAddress())));
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $exception));
                }
                throw $exception;
            }
            if ($this->hasTimeout && !(yield $this->ping())) {
                $exception = new UnprocessedRequestException(new SocketException(\sprintf("Socket to '%s' missed responding to PINGs", (string) $this->socket->getRemoteAddress())));
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $exception));
                }
                throw $exception;
            }
            $this->idlePings = 0;
            $this->cancelIdleWatcher();
            (yield RequestNormalizer::normalizeRequest($request));
            // Remove defunct HTTP/1.x headers.
            $request->removeHeader('host');
            $request->removeHeader('connection');
            $request->removeHeader('keep-alive');
            $request->removeHeader('transfer-encoding');
            $request->removeHeader('upgrade');
            $request->setProtocolVersions(['2']);
            if ($request->getMethod() === 'CONNECT') {
                $exception = new HttpException("CONNECT requests are currently not supported on HTTP/2");
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $exception));
                }
                throw $exception;
            }
            if ($this->socket->isClosed()) {
                $exception = new UnprocessedRequestException(new SocketException(\sprintf("Socket to '%s' closed before the request could be sent", (string) $this->socket->getRemoteAddress())));
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $exception));
                }
                throw $exception;
            }
            $originalCancellation = $cancellationToken;
            if ($request->getTransferTimeout() > 0) {
                $cancellationToken = new CombinedCancellationToken($cancellationToken, new TimeoutCancellationToken($request->getTransferTimeout()));
            }
            try {
                $headers = $this->generateHeaders($request);
                $body = $request->getBody()->createBodyStream();
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->startSendingRequest($request, $stream));
                }
                $chunk = (yield $body->read());
                $streamId = $this->streamId += 2;
                // Client streams should be odd-numbered, starting at 1.
                $this->streams[$streamId] = $http2stream = new Http2Stream($streamId, $request, $stream, $cancellationToken, $originalCancellation, $this->createStreamInactivityWatcher($streamId, $request->getInactivityTimeout()), self::DEFAULT_WINDOW_SIZE, $this->initialWindowSize);
                $this->socket->reference();
                $transferTimeout = $request->getTransferTimeout();
                $cancellationId = $cancellationToken->subscribe(function (CancelledException $exception) use($streamId, $originalCancellation, $transferTimeout) : void {
                    if (!isset($this->streams[$streamId])) {
                        return;
                    }
                    $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $streamId, \pack("N", Http2Parser::CANCEL));
                    if (!$originalCancellation->isRequested()) {
                        $this->hasTimeout = true;
                        $this->ping();
                        // async ping, if other requests occur, they wait for it
                        $exception = new TimeoutException('Allowed transfer timeout exceeded, took longer than ' . $transferTimeout . ' ms', 0, $exception);
                    }
                    $this->releaseStream($streamId, $exception);
                });
                if (!isset($this->streams[$streamId])) {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeSendingRequest($request, $stream));
                    }
                    \assert($http2stream->pendingResponse !== null);
                    return (yield $http2stream->pendingResponse->promise());
                }
                $flag = Http2Parser::END_HEADERS | ($chunk === null ? Http2Parser::END_STREAM : Http2Parser::NO_FLAG);
                $headers = $this->hpack->encode($headers);
                if (\strlen($headers) > $this->frameSizeLimit) {
                    /** @var string[] $split */
                    $split = \str_split($headers, $this->frameSizeLimit);
                    $firstChunk = \array_shift($split);
                    $lastChunk = \array_pop($split);
                    // no yield, because there must not be other frames in between
                    $this->writeFrame(Http2Parser::HEADERS, Http2Parser::NO_FLAG, $streamId, $firstChunk);
                    foreach ($split as $headerChunk) {
                        // no yield, because there must not be other frames in between
                        $this->writeFrame(Http2Parser::CONTINUATION, Http2Parser::NO_FLAG, $streamId, $headerChunk);
                    }
                    (yield $this->writeFrame(Http2Parser::CONTINUATION, $flag, $streamId, $lastChunk));
                } else {
                    (yield $this->writeFrame(Http2Parser::HEADERS, $flag, $streamId, $headers));
                }
                if ($chunk === null) {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeSendingRequest($request, $stream));
                    }
                    $http2stream->requestBodyComplete = true;
                    $http2stream->requestBodyCompletion->resolve();
                    \assert($http2stream->pendingResponse !== null);
                    return (yield $http2stream->pendingResponse->promise());
                }
                $buffer = $chunk;
                while (null !== ($chunk = (yield $body->read()))) {
                    if (!isset($this->streams[$streamId])) {
                        foreach ($request->getEventListeners() as $eventListener) {
                            (yield $eventListener->completeSendingRequest($request, $stream));
                        }
                        \assert($http2stream->pendingResponse !== null);
                        return (yield $http2stream->pendingResponse->promise());
                    }
                    (yield $this->writeData($http2stream, $buffer));
                    $buffer = $chunk;
                }
                if (!isset($this->streams[$streamId])) {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeSendingRequest($request, $stream));
                    }
                    \assert($http2stream->pendingResponse !== null);
                    return (yield $http2stream->pendingResponse->promise());
                }
                \assert($http2stream->pendingResponse !== null);
                $responsePromise = $http2stream->pendingResponse->promise();
                $http2stream->requestBodyComplete = true;
                $http2stream->requestBodyCompletion->resolve();
                (yield $this->writeData($http2stream, $buffer));
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->completeSendingRequest($request, $stream));
                }
                return (yield $responsePromise);
            } catch (\Throwable $exception) {
                if (isset($streamId) && isset($this->streams[$streamId])) {
                    \assert(isset($http2stream));
                    if (!$http2stream->requestBodyComplete) {
                        $http2stream->requestBodyCompletion->fail($exception);
                    }
                    $this->releaseStream($streamId, $exception);
                }
                if ($exception instanceof StreamException) {
                    $message = 'Failed to write request (stream ' . ($streamId ?? 'not assigned') . ') to socket: ' . $exception->getMessage();
                    $exception = new SocketException($message, 0, $exception);
                }
                throw $exception;
            } finally {
                if (isset($cancellationId)) {
                    $cancellationToken->unsubscribe($cancellationId);
                }
            }
        });
    }
    /**
     *
     */
    public function isClosed() : bool
    {
        return $this->onClose === null;
    }
    /**
     *
     */
    private function run() : \Generator
    {
        try {
            (yield $this->socket->write(Http2Parser::PREFACE));
            Promise\rethrow(new Coroutine($this->runWriteThread()));
            (yield $this->writeFrame(Http2Parser::SETTINGS, 0, 0, \pack("nNnNnNnN", Http2Parser::ENABLE_PUSH, 1, Http2Parser::MAX_CONCURRENT_STREAMS, 256, Http2Parser::INITIAL_WINDOW_SIZE, self::DEFAULT_WINDOW_SIZE, Http2Parser::MAX_FRAME_SIZE, self::DEFAULT_MAX_FRAME_SIZE)));
        } catch (\Throwable $e) {
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $this->shutdown(new ClientHttp2ConnectionException('The HTTP/2 connection closed' . ($this->shutdown !== null ? ' unexpectedly' : ''), $this->shutdown ?? Http2Parser::INTERNAL_ERROR));
            $this->close();
            return;
        }
        try {
            $parser = (new Http2Parser($this))->parse();
            while (null !== ($chunk = (yield $this->socket->read()))) {
                $return = $parser->send($chunk);
                \assert($return === null);
            }
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $this->shutdown(new ClientHttp2ConnectionException("The HTTP/2 connection from '" . $this->socket->getLocalAddress() . "' to '" . $this->socket->getRemoteAddress() . "' closed" . ($this->shutdown === null ? ' unexpectedly' : ''), $this->shutdown ?? Http2Parser::INTERNAL_ERROR));
            $this->close();
        } catch (\Throwable $exception) {
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $this->shutdown(new ClientHttp2ConnectionException("The HTTP/2 connection from '" . $this->socket->getLocalAddress() . "' to '" . $this->socket->getRemoteAddress() . "' closed unexpectedly: " . $exception->getMessage(), Http2Parser::INTERNAL_ERROR, $exception));
            $this->close();
        }
    }
    /**
     *
     */
    private function writeFrame(int $type, int $flags = Http2Parser::NO_FLAG, int $stream = 0, string $data = '') : Promise
    {
        \assert(Http2Parser::logDebugFrame('send', $type, $flags, $stream, \strlen($data)));
        return $this->frameQueueEmitter->emit(\Phabel\Target\Php80\Polyfill::substr(\pack("NccN", \strlen($data), $type, $flags, $stream), 1) . $data);
    }
    /**
     *
     */
    private function applySetting(int $setting, int $value) : void
    {
        switch ($setting) {
            case Http2Parser::INITIAL_WINDOW_SIZE:
                if ($value < 0 || $value > 2147483647) {
                    // (1 << 31) - 1
                    $this->handleConnectionException(new Http2ConnectionException("Invalid window size: {$value}", Http2Parser::FLOW_CONTROL_ERROR));
                    return;
                }
                $priorWindowSize = $this->initialWindowSize;
                $this->initialWindowSize = $value;
                $difference = $this->initialWindowSize - $priorWindowSize;
                foreach ($this->streams as $stream) {
                    $stream->clientWindow += $difference;
                }
                // Settings ACK should be sent before HEADER or DATA frames.
                if ($difference > 0) {
                    Loop::defer(function () {
                        foreach ($this->streams as $stream) {
                            if ($this->clientWindow <= 0) {
                                return;
                            }
                            if ($stream->requestBodyBuffer === '' || $stream->clientWindow <= 0) {
                                continue;
                            }
                            $this->writeBufferedData($stream);
                        }
                    });
                }
                return;
            case Http2Parser::MAX_FRAME_SIZE:
                if ($value < 1 << 14 || $value >= 1 << 24) {
                    $this->handleConnectionException(new Http2ConnectionException("Invalid maximum frame size: {$value}", Http2Parser::PROTOCOL_ERROR));
                    return;
                }
                $this->frameSizeLimit = $value;
                return;
            case Http2Parser::MAX_CONCURRENT_STREAMS:
                if ($value < 0 || $value > 2147483647) {
                    // (1 << 31) - 1
                    $this->handleConnectionException(new Http2ConnectionException("Invalid concurrent streams value: {$value}", Http2Parser::PROTOCOL_ERROR));
                    return;
                }
                $priorUsedStreams = $this->concurrentStreamLimit - $this->remainingStreams;
                $this->concurrentStreamLimit = $value;
                $this->remainingStreams = $this->concurrentStreamLimit - $priorUsedStreams;
                \assert($this->remainingStreams <= $this->concurrentStreamLimit);
                return;
            case Http2Parser::HEADER_TABLE_SIZE:
            // TODO Respect this setting from the server
            case Http2Parser::MAX_HEADER_LIST_SIZE:
            // TODO Respect this setting from the server
            case Http2Parser::ENABLE_PUSH:
            // No action needed.
            default:
                // Unknown setting, ignore (6.5.2).
                return;
        }
    }
    /**
     *
     */
    private function writeBufferedData(Http2Stream $stream) : Promise
    {
        if ($stream->requestBodyComplete && $stream->requestBodyBuffer === '') {
            return new Success();
        }
        $windowSize = \min($this->clientWindow, $stream->clientWindow);
        $length = \strlen($stream->requestBodyBuffer);
        if ($length <= $windowSize) {
            if ($stream->windowSizeIncrease) {
                $deferred = $stream->windowSizeIncrease;
                $stream->windowSizeIncrease = null;
                $deferred->resolve();
            }
            $this->clientWindow -= $length;
            $stream->clientWindow -= $length;
            if ($length > $this->frameSizeLimit) {
                /** @var string[] $chunks */
                $chunks = \str_split($stream->requestBodyBuffer, $this->frameSizeLimit);
                $stream->requestBodyBuffer = \array_pop($chunks);
                foreach ($chunks as $chunk) {
                    $this->writeFrame(Http2Parser::DATA, Http2Parser::NO_FLAG, $stream->id, $chunk);
                }
            }
            if ($stream->requestBodyComplete) {
                $promise = $this->writeFrame(Http2Parser::DATA, Http2Parser::END_STREAM, $stream->id, $stream->requestBodyBuffer);
            } else {
                $promise = $this->writeFrame(Http2Parser::DATA, Http2Parser::NO_FLAG, $stream->id, $stream->requestBodyBuffer);
            }
            $stream->requestBodyBuffer = "";
            $stream->enableInactivityWatcher();
            return $promise;
        }
        if ($windowSize > 0) {
            // Read next body chunk if less than 8192 bytes will remain in the buffer
            if ($length - 8192 < $windowSize && $stream->windowSizeIncrease) {
                $deferred = $stream->windowSizeIncrease;
                $stream->windowSizeIncrease = null;
                $deferred->resolve();
            }
            $data = $stream->requestBodyBuffer;
            $end = $windowSize - $this->frameSizeLimit;
            $stream->clientWindow -= $windowSize;
            $this->clientWindow -= $windowSize;
            for ($off = 0; $off < $end; $off += $this->frameSizeLimit) {
                $this->writeFrame(Http2Parser::DATA, Http2Parser::NO_FLAG, $stream->id, \Phabel\Target\Php80\Polyfill::substr($data, $off, $this->frameSizeLimit));
            }
            $promise = $this->writeFrame(Http2Parser::DATA, Http2Parser::NO_FLAG, $stream->id, \Phabel\Target\Php80\Polyfill::substr($data, $off, $windowSize - $off));
            $stream->requestBodyBuffer = \Phabel\Target\Php80\Polyfill::substr($data, $windowSize);
            $stream->enableInactivityWatcher();
            return $promise;
        }
        if ($stream->windowSizeIncrease === null) {
            $stream->windowSizeIncrease = new Deferred();
        }
        return $stream->windowSizeIncrease->promise();
    }
    /**
     *
     */
    private function releaseStream(int $streamId, ?\Throwable $exception = null) : void
    {
        \assert(isset($this->streams[$streamId]));
        $stream = $this->streams[$streamId];
        unset($this->streams[$streamId]);
        if ($streamId & 1) {
            // Client-initiated stream.
            $this->remainingStreams++;
            \assert($this->remainingStreams <= $this->concurrentStreamLimit);
        }
        if ($stream->responsePending || $stream->body || $stream->trailers) {
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $exception = $exception ?? new ClientHttp2StreamException(\sprintf("Stream %d closed unexpectedly", $streamId), $streamId, Http2Parser::INTERNAL_ERROR);
            if (!$exception instanceof HttpException && !$exception instanceof CancelledException) {
                $exception = new HttpException($exception->getMessage(), 0, $exception);
            }
            /** @var (Deferred|Emitter)[] $deferredAndEmitter */
            $deferredAndEmitter = [];
            if ($stream->responsePending) {
                $stream->responsePending = false;
                $deferredAndEmitter[] = $stream->pendingResponse;
                $stream->pendingResponse = null;
            }
            if ($stream->body) {
                $deferredAndEmitter[] = $stream->body;
                $stream->body = null;
            }
            if ($stream->trailers) {
                $deferredAndEmitter[] = $stream->trailers;
                $stream->trailers = null;
            }
            $request = $stream->request;
            asyncCall(static function () use($request, $deferredAndEmitter, $exception) {
                try {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->abort($request, $exception));
                    }
                } finally {
                    foreach ($deferredAndEmitter as $deferredOrEmitter) {
                        \assert($deferredOrEmitter !== null);
                        // TODO Find out why psalm reports this as nullable
                        $deferredOrEmitter->fail($exception);
                    }
                }
            });
        }
        if (!$this->streams && !$this->socket->isClosed()) {
            $this->socket->unreference();
        }
        if (!$this->streams && $this->shutdown !== null) {
            $this->close();
        }
    }
    /**
     *
     */
    private function setupPingIfIdle() : void
    {
        if ($this->idleWatcher !== null) {
            return;
        }
        $this->idleWatcher = Loop::defer(function ($watcher) {
            \assert($this->idleWatcher === null || $this->idleWatcher === $watcher);
            $this->idleWatcher = null;
            if (!empty($this->streams)) {
                return;
            }
            $this->idleWatcher = Loop::delay(300000, function ($watcher) {
                \assert($this->idleWatcher === null || $this->idleWatcher === $watcher);
                \assert(empty($this->streams));
                $this->idleWatcher = null;
                // Connection idle for 10 minutes
                if ($this->idlePings >= 1) {
                    $this->shutdown(new HttpException('Too many pending pings'));
                    $this->close();
                    return;
                }
                if ((yield $this->ping())) {
                    $this->setupPingIfIdle();
                }
            });
            Loop::unreference($this->idleWatcher);
        });
        Loop::unreference($this->idleWatcher);
    }
    /**
     *
     */
    private function cancelIdleWatcher() : void
    {
        if ($this->idleWatcher !== null) {
            Loop::cancel($this->idleWatcher);
            $this->idleWatcher = null;
        }
    }
    /**
     * @return Promise<bool> Fulfilled with true if a pong is received within the timeout, false if none is received.
     */
    private function ping() : Promise
    {
        if ($this->onClose === null) {
            return new Success(false);
        }
        if ($this->pongDeferred !== null) {
            return $this->pongDeferred->promise();
        }
        $this->pongDeferred = new Deferred();
        $this->idlePings++;
        $promise = $this->pongDeferred->promise();
        $this->pongWatcher = Loop::delay(self::PONG_TIMEOUT, function () {
            $this->hasTimeout = false;
            $deferred = $this->pongDeferred;
            $this->pongDeferred = null;
            \assert($deferred !== null);
            $deferred->resolve(false);
            // Shutdown connection to stop new requests, but keep it open, as other responses might still arrive
            $this->shutdown(new HttpException('PONG timeout of ' . self::PONG_TIMEOUT . 'ms reached'), \max(0, $this->streamId));
        });
        $this->writeFrame(Http2Parser::PING, 0, 0, $this->counter++);
        return $promise;
    }
    /**
    * @param HttpException $reason Shutdown reason.
    * @param (int | null) $lastId ID of last processed frame. Null to use the last opened frame ID or 0 if no
    streams have been opened.
    *
    * @return Promise
    */
    private function shutdown(HttpException $reason, ?int $lastId = null) : Promise
    {
        return call(function () use($lastId, $reason) {
            $code = (int) $reason->getCode();
            $this->shutdown = $code;
            if ($this->settings !== null) {
                $settings = $this->settings;
                $this->settings = null;
                $message = "Connection closed before HTTP/2 settings could be received";
                $settings->fail(new UnprocessedRequestException(new SocketException($message, 0, $reason)));
            }
            if ($this->streams) {
                $reason = $lastId !== null ? new UnprocessedRequestException($reason) : $reason;
                foreach ($this->streams as $id => $stream) {
                    if ($lastId !== null && $id <= $lastId) {
                        continue;
                    }
                    $this->releaseStream($id, $reason);
                }
            }
        });
    }
    /**
     * @param Request $request
     *
     * @return array
     * @throws InvalidRequestException
     */
    private function generateHeaders(Request $request) : array
    {
        $uri = $request->getUri();
        $path = normalizeRequestPathWithQuery($request);
        $authority = $uri->getHost();
        if ($port = $uri->getPort()) {
            $authority .= ':' . $port;
        }
        $headers = [[":authority", $authority], [":path", $path], [":scheme", $uri->getScheme()], [":method", $request->getMethod()]];
        foreach ($request->getHeaders() as $field => $values) {
            foreach ($values as $value) {
                if ($field === 'te' && $value !== 'trailers') {
                    continue;
                }
                $headers[] = [$field, $value];
            }
        }
        return $headers;
    }
    /**
     *
     */
    private function writeData(Http2Stream $stream, string $data) : Promise
    {
        $stream->requestBodyBuffer .= $data;
        return $this->writeBufferedData($stream);
    }
    /**
     *
     */
    private function increaseConnectionWindow() : void
    {
        $increase = 0;
        while ($this->serverWindow <= self::MINIMUM_WINDOW) {
            $this->serverWindow += self::WINDOW_INCREMENT;
            $increase += self::WINDOW_INCREMENT;
        }
        if ($increase > 0) {
            $this->writeFrame(Http2Parser::WINDOW_UPDATE, 0, 0, \pack("N", self::WINDOW_INCREMENT));
        }
    }
    /**
     *
     */
    private function increaseStreamWindow(Http2Stream $stream) : void
    {
        $minWindow = \min($stream->request->getBodySizeLimit(), self::MINIMUM_WINDOW);
        $increase = 0;
        while ($stream->serverWindow + $stream->bufferSize <= $minWindow) {
            $stream->serverWindow += self::WINDOW_INCREMENT;
            $increase += self::WINDOW_INCREMENT;
        }
        if ($increase > 0) {
            $this->writeFrame(Http2Parser::WINDOW_UPDATE, Http2Parser::NO_FLAG, $stream->id, \pack("N", self::WINDOW_INCREMENT));
        }
    }
    /**
     *
     */
    private function createStreamInactivityWatcher(int $streamId, int $timeout) : ?string
    {
        if ($timeout <= 0) {
            return null;
        }
        $watcher = Loop::delay($timeout, function () use($streamId, $timeout) : void {
            if (!isset($this->streams[$streamId])) {
                return;
            }
            $this->writeFrame(Http2Parser::RST_STREAM, Http2Parser::NO_FLAG, $streamId, \pack("N", Http2Parser::CANCEL));
            $this->releaseStream($streamId, new TimeoutException("Inactivity timeout exceeded, more than {$timeout} ms elapsed from last data received"));
        });
        Loop::unreference($watcher);
        return $watcher;
    }
    /**
     *
     */
    private function runWriteThread() : \Generator
    {
        try {
            while ((yield $this->frameQueue->advance())) {
                (yield $this->socket->write($this->frameQueue->getCurrent()));
            }
        } catch (\Throwable $exception) {
            $this->hasWriteError = true;
            /**
             * @psalm-suppress DeprecatedClass
             * @noinspection PhpDeprecationInspection
             */
            $this->shutdown(new ClientHttp2ConnectionException("The HTTP/2 connection closed unexpectedly: " . $exception->getMessage(), Http2Parser::INTERNAL_ERROR, $exception), \max(0, $this->streamId));
        }
    }
}<?php

namespace Amp\Http\Client\Connection\Internal;

use Amp\Http\Client\Request;
use Amp\Http\Client\RequestBody;
use Amp\Promise;
use function Amp\call;
/** @internal */
final class RequestNormalizer
{
    /**
     *
     */
    public static function normalizeRequest(Request $request) : Promise
    {
        return call(static function () use($request) {
            /** @var array $headers */
            $headers = (yield $request->getBody()->getHeaders());
            foreach ($headers as $name => $header) {
                if (!$request->hasHeader($name)) {
                    $request->setHeaders([$name => $header]);
                }
            }
            yield from self::normalizeRequestBodyHeaders($request);
            // Always normalize this as last item, because we need to strip sensitive headers
            self::normalizeTraceRequest($request);
            return $request;
        });
    }
    /**
     *
     */
    private static function normalizeRequestBodyHeaders(Request $request) : \Generator
    {
        if (!$request->hasHeader('host')) {
            // Though servers are supposed to be able to handle standard port names on the end of the
            // Host header some fail to do this correctly. Thankfully PSR-7 recommends to strip the port
            // if it is the standard port for the given scheme.
            $request->setHeader('host', $request->getUri()->withUserInfo('')->getAuthority());
        }
        if ($request->hasHeader("transfer-encoding")) {
            $request->removeHeader("content-length");
            return;
        }
        if ($request->hasHeader("content-length")) {
            return;
        }
        /** @var RequestBody $body */
        $body = $request->getBody();
        $bodyLength = (yield $body->getBodyLength());
        if ($bodyLength === 0) {
            if (\in_array($request->getMethod(), ['HEAD', 'GET', 'CONNECT'], true)) {
                $request->removeHeader('content-length');
            } else {
                $request->setHeader('content-length', '0');
            }
            $request->removeHeader('transfer-encoding');
        } elseif ($bodyLength > 0) {
            $request->setHeader("content-length", $bodyLength);
            $request->removeHeader("transfer-encoding");
        } else {
            $request->setHeader("transfer-encoding", "chunked");
        }
    }
    /**
     *
     */
    private static function normalizeTraceRequest(Request $request) : void
    {
        $method = $request->getMethod();
        if ($method !== 'TRACE') {
            return;
        }
        // https://tools.ietf.org/html/rfc7231#section-4.3.8
        $request->setBody(null);
        // Remove all body and sensitive headers
        $request->setHeaders(["transfer-encoding" => [], "content-length" => [], "authorization" => [], "proxy-authorization" => [], "cookie" => []]);
    }
}<?php

namespace Amp\Http\Client\Connection\Internal;

use Amp\ByteStream\InMemoryStream;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\ParseException;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\InvalidHeaderException;
use Amp\Http\Rfc7230;
use Amp\Http\Status;
/** @internal */
final class Http1Parser
{
    use ForbidSerialization;
    use ForbidCloning;
    private const STATUS_LINE_PATTERN = "#^\n        HTTP/(?P<protocol>\\d+\\.\\d+)[ \t]+\n        (?P<status>[1-9]\\d\\d)[ \t]*\n        (?P<reason>[^\x01-\x08\x10-\x19]*)\n    \$#ix";
    public const AWAITING_HEADERS = 0;
    public const BODY_IDENTITY = 1;
    public const BODY_IDENTITY_EOF = 2;
    public const BODY_CHUNKS = 3;
    public const TRAILERS_START = 4;
    public const TRAILERS = 5;
    /** @var int */
    private $state = self::AWAITING_HEADERS;
    /** @var string */
    private $buffer = '';
    /** @var string|null */
    private $protocol;
    /** @var int|null */
    private $statusCode;
    /** @var string|null */
    private $statusReason;
    /** @var string[][] */
    private $headers = [];
    /** @var int|null */
    private $remainingBodyBytes;
    /** @var int */
    private $bodyBytesConsumed = 0;
    /** @var bool */
    private $chunkedEncoding = false;
    /** @var int|null */
    private $chunkLengthRemaining;
    /** @var bool */
    private $complete = false;
    /** @var Request */
    private $request;
    /** @var int */
    private $maxHeaderBytes;
    /** @var int */
    private $maxBodyBytes;
    /** @var callable */
    private $bodyDataCallback;
    /** @var callable */
    private $trailersCallback;
    /**
     *
     */
    public function __construct(Request $request, callable $bodyDataCallback, callable $trailersCallback)
    {
        $this->request = $request;
        $this->bodyDataCallback = $bodyDataCallback;
        $this->trailersCallback = $trailersCallback;
        $this->maxHeaderBytes = $request->getHeaderSizeLimit();
        $this->maxBodyBytes = $request->getBodySizeLimit();
    }
    /**
     *
     */
    public function getBuffer() : string
    {
        return $this->buffer;
    }
    /**
     *
     */
    public function getState() : int
    {
        return $this->state;
    }
    /**
     *
     */
    public function buffer(string $data) : void
    {
        $this->buffer .= $data;
    }
    /**
     * @param (string | null) $data
     *
     * @return (Response | null)
     *
     * @throws ParseException
     */
    public function parse(string $data = null) : ?Response
    {
        if ($data !== null) {
            $this->buffer .= $data;
        }
        if ($this->buffer === '') {
            return null;
        }
        if ($this->complete) {
            throw new ParseException('Can\'t continue parsing, response is already complete', Status::BAD_REQUEST);
        }
        switch ($this->state) {
            case self::AWAITING_HEADERS:
                goto headers;
            case self::BODY_IDENTITY:
                goto body_identity;
            case self::BODY_IDENTITY_EOF:
                goto body_identity_eof;
            case self::BODY_CHUNKS:
                goto body_chunks;
            case self::TRAILERS_START:
                goto trailers_start;
            case self::TRAILERS:
                goto trailers;
        }
        headers:
        $startLineAndHeaders = $this->shiftHeadersFromBuffer();
        if ($startLineAndHeaders === null) {
            return null;
        }
        $startLineEndPos = \strpos($startLineAndHeaders, "\r\n");
        \assert($startLineEndPos !== false);
        $startLine = \Phabel\Target\Php80\Polyfill::substr($startLineAndHeaders, 0, $startLineEndPos);
        $rawHeaders = \Phabel\Target\Php80\Polyfill::substr($startLineAndHeaders, $startLineEndPos + 2);
        if (\preg_match(self::STATUS_LINE_PATTERN, $startLine, $match)) {
            $this->protocol = $match['protocol'];
            $this->statusCode = (int) $match['status'];
            $this->statusReason = \trim($match['reason']);
        } else {
            throw new ParseException('Invalid status line: ' . $startLine, Status::BAD_REQUEST);
        }
        if ($rawHeaders !== '') {
            $this->headers = $this->parseRawHeaders($rawHeaders);
        } else {
            $this->headers = [];
        }
        $requestMethod = $this->request->getMethod();
        $skipBody = $this->statusCode < Status::OK || $this->statusCode === Status::NOT_MODIFIED || $this->statusCode === Status::NO_CONTENT || $requestMethod === 'HEAD' || $requestMethod === 'CONNECT';
        if ($skipBody) {
            $this->complete = true;
        } elseif ($this->chunkedEncoding) {
            $this->state = self::BODY_CHUNKS;
        } elseif ($this->remainingBodyBytes === null) {
            $this->state = self::BODY_IDENTITY_EOF;
        } elseif ($this->remainingBodyBytes > 0) {
            $this->state = self::BODY_IDENTITY;
        } else {
            $this->complete = true;
        }
        $response = new Response($this->protocol, $this->statusCode, $this->statusReason, [], new InMemoryStream(), $this->request);
        foreach ($this->headers as [$key, $value]) {
            $response->addHeader($key, $value);
        }
        return $response;
        body_identity:
        $bufferDataSize = \strlen($this->buffer);
        if ($bufferDataSize <= $this->remainingBodyBytes) {
            $chunk = $this->buffer;
            $this->buffer = '';
            $this->remainingBodyBytes -= $bufferDataSize;
            $this->addToBody($chunk);
            if ($this->remainingBodyBytes === 0) {
                $this->complete = true;
            }
            return null;
        }
        $bodyData = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $this->remainingBodyBytes);
        $this->addToBody($bodyData);
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->remainingBodyBytes);
        $this->remainingBodyBytes = 0;
        goto complete;
        body_identity_eof:
        $this->addToBody($this->buffer);
        $this->buffer = '';
        return null;
        body_chunks:
        if ($this->parseChunkedBody()) {
            $this->state = self::TRAILERS_START;
            goto trailers_start;
        }
        return null;
        trailers_start:
        $firstTwoBytes = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, 2);
        if ($firstTwoBytes === "" || $firstTwoBytes === "\r") {
            return null;
        }
        if ($firstTwoBytes === "\r\n") {
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 2);
            goto complete;
        }
        $this->state = self::TRAILERS;
        goto trailers;
        trailers:
        $trailers = $this->shiftHeadersFromBuffer();
        if ($trailers === null) {
            return null;
        }
        $this->parseTrailers($trailers);
        goto complete;
        complete:
        $this->complete = true;
        return null;
    }
    /**
     *
     */
    public function isComplete() : bool
    {
        return $this->complete;
    }
    /**
     * @return (string | null)
     *
     * @throws ParseException
     */
    private function shiftHeadersFromBuffer() : ?string
    {
        $this->buffer = \ltrim($this->buffer, "\r\n");
        if ($headersSize = \strpos($this->buffer, "\r\n\r\n")) {
            $headers = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $headersSize + 2);
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $headersSize + 4);
        } else {
            $headersSize = \strlen($this->buffer);
            $headers = null;
        }
        if ($this->maxHeaderBytes > 0 && $headersSize > $this->maxHeaderBytes) {
            throw new ParseException("Configured header size exceeded: {$headersSize} bytes received, while the configured limit is {$this->maxHeaderBytes} bytes", Status::REQUEST_HEADER_FIELDS_TOO_LARGE);
        }
        return $headers;
    }
    /**
     * @param string $rawHeaders
     *
     * @return array
     *
     * @throws ParseException
     */
    private function parseRawHeaders(string $rawHeaders) : array
    {
        // Legacy support for folded headers
        if (\strpos($rawHeaders, "\r\n ") || \strpos($rawHeaders, "\r\n\t")) {
            $rawHeaders = \preg_replace("/\r\n[ \t]++/", ' ', $rawHeaders);
        }
        try {
            $headers = Rfc7230::parseRawHeaders($rawHeaders);
            $headerMap = [];
            foreach ($headers as [$key, $value]) {
                $headerMap[\strtolower($key)][] = $value;
            }
        } catch (InvalidHeaderException $e) {
            throw new ParseException('Invalid headers', Status::BAD_REQUEST, $e);
        }
        if (isset($headerMap['transfer-encoding'])) {
            $transferEncodings = \explode(',', \strtolower(\implode(',', $headerMap['transfer-encoding'])));
            $transferEncodings = \array_map('trim', $transferEncodings);
            $this->chunkedEncoding = \in_array('chunked', $transferEncodings, true);
        } elseif (isset($headerMap['content-length'])) {
            if (\count($headerMap['content-length']) > 1) {
                throw new ParseException('Can\'t determine body length, because multiple content-length headers present in the response', Status::BAD_REQUEST);
            }
            $contentLength = $headerMap['content-length'][0];
            if (!\preg_match('/^(0|[1-9][0-9]*)$/', $contentLength)) {
                throw new ParseException('Can\'t determine body length, because the content-length header value is invalid', Status::BAD_REQUEST);
            }
            $this->remainingBodyBytes = (int) $contentLength;
        }
        return $headers;
    }
    /**
     * Decodes a chunked response body.
     *
     * @return bool {@code true} if the body is complete, otherwise {@code false}.
     *
     * @throws ParseException
     */
    private function parseChunkedBody() : bool
    {
        if ($this->chunkLengthRemaining !== null) {
            goto decode_chunk;
        }
        determine_chunk_size:
        if (false === ($lineEndPos = \strpos($this->buffer, "\r\n"))) {
            return false;
        }
        if ($lineEndPos === 0) {
            throw new ParseException('Invalid line; hexadecimal chunk size expected', Status::BAD_REQUEST);
        }
        $line = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $lineEndPos);
        $hex = \strtolower(\trim(\ltrim($line, '0'))) ?: '0';
        $dec = \hexdec($hex);
        if ($hex !== \dechex($dec)) {
            throw new ParseException('Invalid hexadecimal chunk size', Status::BAD_REQUEST);
        }
        $this->chunkLengthRemaining = $dec;
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $lineEndPos + 2);
        if ($this->chunkLengthRemaining === 0) {
            return true;
        }
        decode_chunk:
        $bufferLength = \strlen($this->buffer);
        // These first two (extreme) edge cases prevent errors where the packet boundary ends after
        // the \r and before the \n at the end of a chunk.
        if ($bufferLength === $this->chunkLengthRemaining || $bufferLength === $this->chunkLengthRemaining + 1) {
            return false;
        }
        if ($bufferLength >= $this->chunkLengthRemaining + 2) {
            $chunk = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $this->chunkLengthRemaining);
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->chunkLengthRemaining + 2);
            $this->chunkLengthRemaining = null;
            $this->addToBody($chunk);
            goto determine_chunk_size;
        }
        /** @noinspection SuspiciousAssignmentsInspection */
        $chunk = $this->buffer;
        $this->buffer = '';
        $this->chunkLengthRemaining -= $bufferLength;
        $this->addToBody($chunk);
        return false;
    }
    /**
     * @param string $trailers
     *
     * @throws ParseException
     */
    private function parseTrailers(string $trailers) : void
    {
        try {
            $trailers = Rfc7230::parseHeaders($trailers);
        } catch (InvalidHeaderException $e) {
            throw new ParseException('Invalid trailers', Status::BAD_REQUEST, $e);
        }
        ($this->trailersCallback)($trailers);
    }
    /**
     * @param string $data
     *
     * @throws ParseException
     */
    private function addToBody(string $data) : void
    {
        $length = \strlen($data);
        if (!$length) {
            return;
        }
        $this->bodyBytesConsumed += $length;
        if ($this->maxBodyBytes > 0 && $this->bodyBytesConsumed > $this->maxBodyBytes) {
            throw new ParseException("Configured body size exceeded: {$this->bodyBytesConsumed} bytes received, while the configured limit is {$this->maxBodyBytes} bytes", Status::PAYLOAD_TOO_LARGE);
        }
        if ($this->bodyDataCallback) {
            ($this->bodyDataCallback)($data);
        }
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Request;
use Amp\Promise;
interface ConnectionPool
{
    /**
     * Reserve a stream for a particular request.
     *
     * @param Request $request
     * @param CancellationToken $cancellation
     *
     * @return Promise<Stream>
     */
    public function getStream(Request $request, CancellationToken $cancellation) : Promise;
}<?php

namespace Amp\Http\Client\Connection;

use Amp\Http\Client\HttpException;
final class UnprocessedRequestException extends HttpException
{
    /**
     *
     */
    public function __construct(HttpException $previous)
    {
        parent::__construct("The request was not processed and can be safely retried", 0, $previous);
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use function Amp\call;
final class HttpStream implements Stream
{
    use ForbidSerialization;
    use ForbidCloning;
    /**
     *
     */
    public static function fromConnection(Connection $connection, callable $requestCallback, callable $releaseCallback) : self
    {
        return new self($connection->getLocalAddress(), $connection->getRemoteAddress(), $connection->getTlsInfo(), $requestCallback, $releaseCallback);
    }
    /**
     *
     */
    public static function fromStream(Stream $stream, callable $requestCallback, callable $releaseCallback) : self
    {
        return new self($stream->getLocalAddress(), $stream->getRemoteAddress(), $stream->getTlsInfo(), $requestCallback, $releaseCallback);
    }
    /** @var SocketAddress */
    private $localAddress;
    /** @var SocketAddress */
    private $remoteAddress;
    /** @var TlsInfo|null */
    private $tlsInfo;
    /** @var callable */
    private $requestCallback;
    /** @var callable|null */
    private $releaseCallback;
    /**
     *
     */
    private function __construct(SocketAddress $localAddress, SocketAddress $remoteAddress, ?TlsInfo $tlsInfo, callable $requestCallback, callable $releaseCallback)
    {
        $this->localAddress = $localAddress;
        $this->remoteAddress = $remoteAddress;
        $this->tlsInfo = $tlsInfo;
        $this->requestCallback = $requestCallback;
        $this->releaseCallback = $releaseCallback;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->releaseCallback !== null) {
            ($this->releaseCallback)();
        }
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise
    {
        if ($this->releaseCallback === null) {
            throw new \Error('A stream may only be used for a single request');
        }
        $this->releaseCallback = null;
        return call(function () use($request, $cancellation) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startRequest($request));
            }
            return call($this->requestCallback, $request, $cancellation, $this);
        });
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->localAddress;
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->remoteAddress;
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->tlsInfo;
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
interface Connection
{
    /**
    * @param Request $request
    *
    * @return Promise<(Stream | null)> Returns a stream for the given request, or null if no stream is available or if
    the connection is not suited for the given request. The first request for a stream
    on a new connection MUST resolve the promise with a Stream instance.
    */
    public function getStream(Request $request) : Promise;
    /**
     * @return string[] Array of supported protocol versions.
     */
    public function getProtocolVersions() : array;
    /**
     *
     */
    public function close() : Promise;
    /**
     *
     */
    public function onClose(callable $onClose) : void;
    /**
     *
     */
    public function getLocalAddress() : SocketAddress;
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress;
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo;
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Coroutine;
use Amp\Deferred;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\MultiReasonException;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
use function Amp\coroutine;
final class ConnectionLimitingPool implements ConnectionPool
{
    use ForbidSerialization;
    /**
     * Create a connection pool that limits the number of connections per authority.
     *
     * @param int $connectionLimit Maximum number of connections allowed to a single authority.
     * @param (ConnectionFactory | null) $connectionFactory
     *
     * @return self
     */
    public static function byAuthority(int $connectionLimit, ?ConnectionFactory $connectionFactory = null) : self
    {
        return new self($connectionLimit, $connectionFactory);
    }
    /**
     *
     */
    private static function formatUri(Request $request) : string
    {
        $uri = $request->getUri();
        $scheme = $uri->getScheme();
        $isHttps = $scheme === 'https';
        $defaultPort = $isHttps ? 443 : 80;
        $host = $uri->getHost();
        $port = $uri->getPort() ?? $defaultPort;
        $authority = $host . ':' . $port;
        return $scheme . '://' . $authority;
    }
    /** @var int */
    private $connectionLimit;
    /** @var ConnectionFactory */
    private $connectionFactory;
    /** @var array<string, \ArrayObject<int, Promise<Connection>>> */
    private $connections = [];
    /** @var Connection[] */
    private $idleConnections = [];
    /** @var int[] */
    private $activeRequestCounts = [];
    /** @var Deferred[][] */
    private $waiting = [];
    /** @var bool[] */
    private $waitForPriorConnection = [];
    /** @var int */
    private $totalConnectionAttempts = 0;
    /** @var int */
    private $totalStreamRequests = 0;
    /** @var int */
    private $openConnectionCount = 0;
    /**
     *
     */
    private function __construct(int $connectionLimit, ?ConnectionFactory $connectionFactory = null)
    {
        if ($connectionLimit < 1) {
            throw new \Error('The connection limit must be greater than 0');
        }
        $this->connectionLimit = $connectionLimit;
        $this->connectionFactory = $connectionFactory ?? new DefaultConnectionFactory();
    }
    /**
     *
     */
    public function __clone()
    {
        $this->connections = [];
        $this->totalConnectionAttempts = 0;
        $this->totalStreamRequests = 0;
        $this->openConnectionCount = 0;
    }
    /**
     *
     */
    public function getTotalConnectionAttempts() : int
    {
        return $this->totalConnectionAttempts;
    }
    /**
     *
     */
    public function getTotalStreamRequests() : int
    {
        return $this->totalStreamRequests;
    }
    /**
     *
     */
    public function getOpenConnectionCount() : int
    {
        return $this->openConnectionCount;
    }
    /**
     *
     */
    public function getStream(Request $request, CancellationToken $cancellation) : Promise
    {
        return call(function () use($request, $cancellation) {
            $this->totalStreamRequests++;
            $uri = self::formatUri($request);
            // Using new Coroutine avoids a bug on PHP < 7.4, see #265
            /**
             * @var Stream $stream
             * @psalm-suppress all
             */
            [$connection, $stream] = (yield new Coroutine($this->getStreamFor($uri, $request, $cancellation)));
            $connectionId = \spl_object_id($connection);
            $this->activeRequestCounts[$connectionId] = ($this->activeRequestCounts[$connectionId] ?? 0) + 1;
            unset($this->idleConnections[$connectionId]);
            return HttpStream::fromStream($stream, coroutine(function (Request $request, CancellationToken $cancellationToken) use($connection, $stream, $uri) {
                try {
                    /** @var Response $response */
                    $response = (yield $stream->request($request, $cancellationToken));
                } catch (\Throwable $e) {
                    $this->onReadyConnection($connection, $uri);
                    throw $e;
                }
                // await response being completely received
                $response->getTrailers()->onResolve(function () use($connection, $uri) : void {
                    $this->onReadyConnection($connection, $uri);
                });
                return $response;
            }), function () use($connection, $uri) : void {
                $this->onReadyConnection($connection, $uri);
            });
        });
    }
    /**
     *
     */
    private function getStreamFor(string $uri, Request $request, CancellationToken $cancellation) : \Generator
    {
        $isHttps = $request->getUri()->getScheme() === 'https';
        $connections = $this->connections[$uri] ?? new \ArrayObject();
        do {
            foreach ($connections as $connectionPromise) {
                \assert($connectionPromise instanceof Promise);
                try {
                    if ($isHttps && ($this->waitForPriorConnection[$uri] ?? true)) {
                        // Wait for first successful connection if using a secure connection (maybe we can use HTTP/2).
                        $connection = (yield $connectionPromise);
                    } else {
                        $connection = (yield Promise\first([$connectionPromise, new Success()]));
                        if ($connection === null) {
                            continue;
                        }
                    }
                } catch (\Exception $exception) {
                    continue;
                    // Ignore cancellations and errors of other requests.
                }
                \assert($connection instanceof Connection);
                $stream = (yield $this->getStreamFromConnection($connection, $request));
                if ($stream === null) {
                    if (!$this->isAdditionalConnectionAllowed($uri) && $this->isConnectionIdle($connection)) {
                        $connection->close();
                        break;
                    }
                    continue;
                    // No stream available for the given request.
                }
                return [$connection, $stream];
            }
            $deferred = new Deferred();
            $deferredId = \spl_object_id($deferred);
            $this->waiting[$uri][$deferredId] = $deferred;
            $deferredPromise = $deferred->promise();
            $deferredPromise->onResolve(function () use($uri, $deferredId) : void {
                $this->removeWaiting($uri, $deferredId);
            });
            if ($this->isAdditionalConnectionAllowed($uri)) {
                break;
            }
            $connection = (yield $deferredPromise);
            \assert($connection instanceof Connection);
            $stream = (yield $this->getStreamFromConnection($connection, $request));
            if ($stream === null) {
                continue;
                // Wait for a different connection to become available.
            }
            return [$connection, $stream];
        } while (true);
        $this->totalConnectionAttempts++;
        $connectionPromise = $this->connectionFactory->create($request, $cancellation);
        $promiseId = \spl_object_id($connectionPromise);
        $this->connections[$uri] = $this->connections[$uri] ?? new \ArrayObject();
        $this->connections[$uri][$promiseId] = $connectionPromise;
        $connectionPromise->onResolve(function (?\Throwable $exception, ?Connection $connection) use(&$deferred, $uri, $promiseId, $isHttps) : void {
            if ($exception) {
                $this->dropConnection($uri, null, $promiseId);
                if ($deferred !== null) {
                    $deferred->fail($exception);
                    // Fail Deferred so Promise\first() below fails.
                }
                return;
            }
            \assert($connection !== null);
            $connectionId = \spl_object_id($connection);
            $this->openConnectionCount++;
            if ($isHttps) {
                $this->waitForPriorConnection[$uri] = \in_array('2', $connection->getProtocolVersions(), true);
            }
            $connection->onClose(function () use($uri, $connectionId, $promiseId) : void {
                $this->openConnectionCount--;
                $this->dropConnection($uri, $connectionId, $promiseId);
            });
        });
        try {
            $connection = (yield Promise\first([$connectionPromise, $deferredPromise]));
        } catch (MultiReasonException $exception) {
            [$exception] = $exception->getReasons();
            // The first reason is why the connection failed.
            throw $exception;
        }
        $deferred = null;
        // Null reference so connection promise handler does not double-resolve the Deferred.
        $this->removeWaiting($uri, $deferredId);
        // Deferred no longer needed for this request.
        \assert($connection instanceof Connection);
        $stream = (yield $this->getStreamFromConnection($connection, $request));
        if ($stream === null) {
            // Reused connection did not have an available stream for the given request.
            $connection = (yield $connectionPromise);
            // Wait for new connection request instead.
            $stream = (yield $this->getStreamFromConnection($connection, $request));
            if ($stream === null) {
                // Other requests used the new connection first, so we need to go around again.
                // Using new Coroutine avoids a bug on PHP < 7.4, see #265
                return (yield new Coroutine($this->getStreamFor($uri, $request, $cancellation)));
            }
        }
        return [$connection, $stream];
    }
    /**
     *
     */
    private function getStreamFromConnection(Connection $connection, Request $request) : Promise
    {
        if (!\array_intersect($request->getProtocolVersions(), $connection->getProtocolVersions())) {
            return new Success();
            // Connection does not support any of the requested protocol versions.
        }
        return $connection->getStream($request);
    }
    /**
     *
     */
    private function isAdditionalConnectionAllowed(string $uri) : bool
    {
        return \count($this->connections[$uri] ?? []) < $this->connectionLimit;
    }
    /**
     *
     */
    private function onReadyConnection(Connection $connection, string $uri) : void
    {
        $connectionId = \spl_object_id($connection);
        if (isset($this->activeRequestCounts[$connectionId])) {
            $this->activeRequestCounts[$connectionId]--;
            if ($this->activeRequestCounts[$connectionId] === 0) {
                while (\count($this->idleConnections) > 64) {
                    // not customizable for now
                    $idleConnection = \reset($this->idleConnections);
                    $key = \key($this->idleConnections);
                    unset($this->idleConnections[$key]);
                    $idleConnection->close();
                }
                $this->idleConnections[$connectionId] = $connection;
            }
        }
        if (empty($this->waiting[$uri])) {
            return;
        }
        $deferred = \reset($this->waiting[$uri]);
        // Deferred is removed from waiting list in onResolve callback attached above.
        $deferred->resolve($connection);
    }
    /**
     *
     */
    private function isConnectionIdle(Connection $connection) : bool
    {
        $connectionId = \spl_object_id($connection);
        \assert(!isset($this->activeRequestCounts[$connectionId]) || $this->activeRequestCounts[$connectionId] >= 0);
        return ($this->activeRequestCounts[$connectionId] ?? 0) === 0;
    }
    /**
     *
     */
    private function removeWaiting(string $uri, int $deferredId) : void
    {
        unset($this->waiting[$uri][$deferredId]);
        if (empty($this->waiting[$uri])) {
            unset($this->waiting[$uri]);
        }
    }
    /**
     *
     */
    private function dropConnection(string $uri, ?int $connectionId, int $promiseId) : void
    {
        unset($this->connections[$uri][$promiseId]);
        if ($connectionId !== null) {
            unset($this->activeRequestCounts[$connectionId], $this->idleConnections[$connectionId]);
        }
        if ($this->connections[$uri]->count() === 0) {
            unset($this->connections[$uri], $this->waitForPriorConnection[$uri]);
        }
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Promise;
final class UnlimitedConnectionPool implements ConnectionPool
{
    use ForbidSerialization;
    /** @var ConnectionLimitingPool */
    private $pool;
    /**
     *
     */
    public function __construct(?ConnectionFactory $connectionFactory = null)
    {
        $this->pool = ConnectionLimitingPool::byAuthority(\PHP_INT_MAX, $connectionFactory);
    }
    /**
     *
     */
    public function __clone()
    {
        $this->pool = clone $this->pool;
    }
    /**
     *
     */
    public function getTotalConnectionAttempts() : int
    {
        return $this->pool->getTotalConnectionAttempts();
    }
    /**
     *
     */
    public function getTotalStreamRequests() : int
    {
        return $this->pool->getTotalStreamRequests();
    }
    /**
     *
     */
    public function getOpenConnectionCount() : int
    {
        return $this->pool->getOpenConnectionCount();
    }
    /**
     *
     */
    public function getStream(Request $request, CancellationToken $cancellation) : Promise
    {
        return $this->pool->getStream($request, $cancellation);
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Success;
final class UpgradedSocket implements EncryptableSocket
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var EncryptableSocket */
    private $socket;
    /** @var string|null */
    private $buffer;
    /**
     * @param EncryptableSocket $socket
     * @param string $buffer Remaining buffer previously read from the socket.
     */
    public function __construct(EncryptableSocket $socket, string $buffer)
    {
        $this->socket = $socket;
        $this->buffer = $buffer !== '' ? $buffer : null;
    }
    /**
     *
     */
    public function read() : Promise
    {
        if ($this->buffer !== null) {
            $buffer = $this->buffer;
            $this->buffer = null;
            return new Success($buffer);
        }
        return $this->socket->read();
    }
    /**
     *
     */
    public function close() : void
    {
        $this->socket->close();
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        return $this->socket->write($data);
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        return $this->socket->end($finalData);
    }
    /**
     *
     */
    public function reference() : void
    {
        $this->socket->reference();
    }
    /**
     *
     */
    public function unreference() : void
    {
        $this->socket->unreference();
    }
    /**
     *
     */
    public function isClosed() : bool
    {
        return $this->socket->isClosed();
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->socket->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->socket->getRemoteAddress();
    }
    /**
     *
     */
    public function setupTls(?CancellationToken $cancellationToken = null) : Promise
    {
        return $this->socket->setupTls($cancellationToken);
    }
    /**
     *
     */
    public function shutdownTls(?CancellationToken $cancellationToken = null) : Promise
    {
        return $this->socket->shutdownTls();
    }
    /**
     *
     */
    public function getTlsState() : int
    {
        return $this->socket->getTlsState();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->socket->getTlsInfo();
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Promise;
use Amp\Sync\KeyedSemaphore;
use Amp\Sync\Lock;
use function Amp\call;
use function Amp\coroutine;
final class StreamLimitingPool implements ConnectionPool
{
    use ForbidCloning;
    use ForbidSerialization;
    /**
     *
     */
    public static function byHost(ConnectionPool $delegate, KeyedSemaphore $semaphore) : self
    {
        return new self($delegate, $semaphore, static function (Request $request) {
            return $request->getUri()->getHost();
        });
    }
    /**
     *
     */
    public static function byStaticKey(ConnectionPool $delegate, KeyedSemaphore $semaphore, string $key = '') : self
    {
        return new self($delegate, $semaphore, static function () use($key) {
            return $key;
        });
    }
    /**
     *
     */
    public static function byCustomKey(ConnectionPool $delegate, KeyedSemaphore $semaphore, callable $requestToKeyMapper) : self
    {
        return new self($delegate, $semaphore, $requestToKeyMapper);
    }
    /** @var ConnectionPool */
    private $delegate;
    /** @var KeyedSemaphore */
    private $semaphore;
    /** @var callable */
    private $requestToKeyMapper;
    /**
     *
     */
    private function __construct(ConnectionPool $delegate, KeyedSemaphore $semaphore, callable $requestToKeyMapper)
    {
        $this->delegate = $delegate;
        $this->semaphore = $semaphore;
        $this->requestToKeyMapper = $requestToKeyMapper;
    }
    /**
     *
     */
    public function getStream(Request $request, CancellationToken $cancellation) : Promise
    {
        return call(function () use($request, $cancellation) {
            /** @var Lock $lock */
            $lock = (yield $this->semaphore->acquire(($this->requestToKeyMapper)($request)));
            /** @var Stream $stream */
            $stream = (yield $this->delegate->getStream($request, $cancellation));
            return HttpStream::fromStream($stream, coroutine(static function (Request $request, CancellationToken $cancellationToken) use($stream, $lock) {
                try {
                    /** @var Response $response */
                    $response = (yield $stream->request($request, $cancellationToken));
                    // await response being completely received
                    $response->getTrailers()->onResolve(static function () use($lock) {
                        $lock->release();
                    });
                } catch (\Throwable $e) {
                    $lock->release();
                    throw $e;
                }
                return $response;
            }), static function () use($lock) {
                $lock->release();
            });
        });
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\CombinedCancellationToken;
use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\Request;
use Amp\Http\Client\SocketException;
use Amp\Http\Client\TimeoutException;
use Amp\Promise;
use Amp\Socket;
use Amp\Socket\ClientTlsContext;
use Amp\Socket\ConnectContext;
use Amp\Socket\Connector;
use Amp\Socket\EncryptableSocket;
use Amp\TimeoutCancellationToken;
use function Amp\call;
use function Amp\Socket\connector;
final class DefaultConnectionFactory implements ConnectionFactory
{
    /** @var Connector|null */
    private $connector;
    /** @var ConnectContext|null */
    private $connectContext;
    /**
     *
     */
    public function __construct(?Connector $connector = null, ?ConnectContext $connectContext = null)
    {
        $this->connector = $connector;
        $this->connectContext = $connectContext;
    }
    /**
     *
     */
    public function create(Request $request, CancellationToken $cancellationToken) : Promise
    {
        return call(function () use($request, $cancellationToken) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startConnectionCreation($request));
            }
            $connector = $this->connector ?? connector();
            $connectContext = $this->connectContext ?? new ConnectContext();
            $uri = $request->getUri();
            $scheme = $uri->getScheme();
            if (!\in_array($scheme, ['http', 'https'], true)) {
                throw new InvalidRequestException($request, 'Invalid scheme provided in the request URI: ' . $uri);
            }
            $isHttps = $scheme === 'https';
            $defaultPort = $isHttps ? 443 : 80;
            $host = $uri->getHost();
            $port = $uri->getPort() ?? $defaultPort;
            if ($host === '') {
                throw new InvalidRequestException($request, 'A host must be provided in the request URI: ' . $uri);
            }
            $authority = $host . ':' . $port;
            $protocolVersions = $request->getProtocolVersions();
            $isConnect = $request->getMethod() === 'CONNECT';
            if ($isHttps) {
                $protocols = [];
                if (!$isConnect && \in_array('2', $protocolVersions, true)) {
                    $protocols[] = 'h2';
                }
                if (\in_array('1.1', $protocolVersions, true) || \in_array('1.0', $protocolVersions, true)) {
                    $protocols[] = 'http/1.1';
                }
                if (!$protocols) {
                    throw new InvalidRequestException($request, \sprintf("None of the requested protocol versions (%s) are supported by %s (HTTP/2 is only supported on HTTPS)", \implode(', ', $protocolVersions), self::class));
                }
                $tlsContext = ($connectContext->getTlsContext() ?? new ClientTlsContext(''))->withPeerCapturing();
                // If we only have HTTP/1.1 available, don't set application layer protocols.
                // There are misbehaving sites like n11.com, see https://github.com/amphp/http-client/issues/255
                if ($protocols !== ['http/1.1'] && Socket\hasTlsAlpnSupport()) {
                    $tlsContext = $tlsContext->withApplicationLayerProtocols($protocols);
                }
                if ($tlsContext->getPeerName() === '') {
                    $tlsContext = $tlsContext->withPeerName($host);
                }
                $connectContext = $connectContext->withTlsContext($tlsContext);
            }
            try {
                /** @var EncryptableSocket $socket */
                $socket = (yield $connector->connect('tcp://' . $authority, $connectContext->withConnectTimeout($request->getTcpConnectTimeout()), $cancellationToken));
            } catch (Socket\ConnectException $e) {
                throw new UnprocessedRequestException(new SocketException(\sprintf("Connection to '%s' failed", $authority), 0, $e));
            } catch (CancelledException $e) {
                // In case of a user cancellation request, throw the expected exception
                $cancellationToken->throwIfRequested();
                // Otherwise we ran into a timeout of our TimeoutCancellationToken
                throw new UnprocessedRequestException(new TimeoutException(\sprintf("Connection to '%s' timed out, took longer than " . $request->getTcpConnectTimeout() . ' ms', $authority)));
                // don't pass $e
            }
            if ($isHttps) {
                try {
                    $tlsState = $socket->getTlsState();
                    // Error if anything enabled TLS on a new connection before we can do it
                    if ($tlsState !== EncryptableSocket::TLS_STATE_DISABLED) {
                        $socket->close();
                        throw new UnprocessedRequestException(new SocketException('Failed to setup TLS connection, connection was in an unexpected TLS state (' . $tlsState . ')'));
                    }
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->startTlsNegotiation($request));
                    }
                    $tlsCancellationToken = new CombinedCancellationToken($cancellationToken, new TimeoutCancellationToken($request->getTlsHandshakeTimeout()));
                    (yield $socket->setupTls($tlsCancellationToken));
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeTlsNegotiation($request));
                    }
                } catch (StreamException $exception) {
                    $socket->close();
                    throw new UnprocessedRequestException(new SocketException(\sprintf("Connection to '%s' @ '%s' closed during TLS handshake", $authority, $socket->getRemoteAddress()->toString()), 0, $exception));
                } catch (CancelledException $e) {
                    $socket->close();
                    // In case of a user cancellation request, throw the expected exception
                    $cancellationToken->throwIfRequested();
                    // Otherwise we ran into a timeout of our TimeoutCancellationToken
                    throw new UnprocessedRequestException(new TimeoutException(\sprintf("TLS handshake with '%s' @ '%s' timed out, took longer than " . $request->getTlsHandshakeTimeout() . ' ms', $authority, $socket->getRemoteAddress()->toString())));
                    // don't pass $e
                }
                $tlsInfo = $socket->getTlsInfo();
                if ($tlsInfo === null) {
                    throw new UnprocessedRequestException(new SocketException(\sprintf("Socket closed after TLS handshake with '%s' @ '%s'", $authority, $socket->getRemoteAddress()->toString())));
                }
                if ($tlsInfo->getApplicationLayerProtocol() === 'h2') {
                    $http2Connection = new Http2Connection($socket);
                    (yield $http2Connection->initialize());
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeConnectionCreation($request));
                    }
                    return $http2Connection;
                }
            }
            // Treat the presence of only HTTP/2 as prior knowledge, see https://http2.github.io/http2-spec/#known-http
            if ($request->getProtocolVersions() === ['2']) {
                $http2Connection = new Http2Connection($socket);
                (yield $http2Connection->initialize());
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->completeConnectionCreation($request));
                }
                return $http2Connection;
            }
            if (!\array_intersect($request->getProtocolVersions(), ['1.0', '1.1'])) {
                $socket->close();
                throw new InvalidRequestException($request, \sprintf("None of the requested protocol versions (%s) are supported by '%s' @ '%s'", \implode(', ', $protocolVersions), $authority, $socket->getRemoteAddress()->toString()));
            }
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->completeConnectionCreation($request));
            }
            return new Http1Connection($socket);
        });
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\NetworkInterceptor;
use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use function Amp\call;
final class InterceptedStream implements Stream
{
    use ForbidCloning;
    use ForbidSerialization;
    /** @var Stream */
    private $stream;
    /** @var NetworkInterceptor|null */
    private $interceptor;
    /**
     *
     */
    public function __construct(Stream $stream, NetworkInterceptor $interceptor)
    {
        $this->stream = $stream;
        $this->interceptor = $interceptor;
    }
    /**
     *
     */
    public function request(Request $request, CancellationToken $cancellation) : Promise
    {
        if (!$this->interceptor) {
            throw new \Error(__METHOD__ . ' may only be invoked once per instance. If you need to implement retries or otherwise issue multiple requests, register an ApplicationInterceptor to do so.');
        }
        $interceptor = $this->interceptor;
        $this->interceptor = null;
        return call(function () use($interceptor, $request, $cancellation) {
            foreach ($request->getEventListeners() as $eventListener) {
                (yield $eventListener->startRequest($request));
            }
            return $interceptor->requestViaNetwork($request, $cancellation, $this->stream);
        });
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->stream->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->stream->getRemoteAddress();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->stream->getTlsInfo();
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\ByteStream\IteratorStream;
use Amp\ByteStream\StreamException;
use Amp\CancellationToken;
use Amp\CancellationTokenSource;
use Amp\CancelledException;
use Amp\CombinedCancellationToken;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Http;
use Amp\Http\Client\Connection\Internal\Http1Parser;
use Amp\Http\Client\Connection\Internal\RequestNormalizer;
use Amp\Http\Client\HttpException;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Internal\ResponseBodyStream;
use Amp\Http\Client\InvalidRequestException;
use Amp\Http\Client\ParseException;
use Amp\Http\Client\Request;
use Amp\Http\Client\Response;
use Amp\Http\Client\SocketException;
use Amp\Http\Client\TimeoutException;
use Amp\Http\InvalidHeaderException;
use Amp\Http\Rfc7230;
use Amp\Loop;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Success;
use Amp\TimeoutCancellationToken;
use Amp\TimeoutException as PromiseTimeoutException;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\getCurrentTime;
use function Amp\Http\Client\Internal\normalizeRequestPathWithQuery;
/**
 * Socket client implementation.
 *
 * @see Client
 */
final class Http1Connection implements Connection
{
    use ForbidSerialization;
    use ForbidCloning;
    private const MAX_KEEP_ALIVE_TIMEOUT = 60;
    private const PROTOCOL_VERSIONS = ['1.0', '1.1'];
    /** @var EncryptableSocket|null */
    private $socket;
    /** @var bool */
    private $busy = false;
    /** @var int Number of requests made on this connection. */
    private $requestCounter = 0;
    /** @var string|null Keep alive timeout watcher ID. */
    private $timeoutWatcher;
    /** @var int Keep-Alive timeout from last response. */
    private $priorTimeout = self::MAX_KEEP_ALIVE_TIMEOUT;
    /** @var callable[]|null */
    private $onClose = [];
    /** @var int */
    private $timeoutGracePeriod;
    /** @var int */
    private $lastUsedAt;
    /** @var bool */
    private $explicitTimeout = false;
    /** @var SocketAddress */
    private $localAddress;
    /** @var SocketAddress */
    private $remoteAddress;
    /** @var TlsInfo|null */
    private $tlsInfo;
    /** @var Promise|null */
    private $idleRead;
    /**
     *
     */
    public function __construct(EncryptableSocket $socket, int $timeoutGracePeriod = 2000)
    {
        $this->socket = $socket;
        $this->localAddress = $socket->getLocalAddress();
        $this->remoteAddress = $socket->getRemoteAddress();
        $this->tlsInfo = $socket->getTlsInfo();
        $this->timeoutGracePeriod = $timeoutGracePeriod;
        $this->lastUsedAt = getCurrentTime();
        $this->watchIdleConnection();
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     *
     */
    public function onClose(callable $onClose) : void
    {
        if (!$this->socket || $this->socket->isClosed()) {
            Promise\rethrow(call($onClose, $this));
            return;
        }
        $this->onClose[] = $onClose;
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->socket) {
            $this->socket->close();
        }
        return $this->free();
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->localAddress;
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->remoteAddress;
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->tlsInfo;
    }
    /**
     *
     */
    public function getProtocolVersions() : array
    {
        return self::PROTOCOL_VERSIONS;
    }
    /**
     *
     */
    public function getStream(Request $request) : Promise
    {
        if ($this->busy || $this->requestCounter && !$this->hasStreamFor($request)) {
            return new Success();
        }
        $this->busy = true;
        return new Success(HttpStream::fromConnection($this, \Closure::fromCallable([$this, 'request']), \Closure::fromCallable([$this, 'release'])));
    }
    /**
     *
     */
    private function free() : Promise
    {
        $this->socket = null;
        $this->idleRead = null;
        $this->lastUsedAt = 0;
        if ($this->timeoutWatcher !== null) {
            Loop::cancel($this->timeoutWatcher);
        }
        if ($this->onClose !== null) {
            $onClose = $this->onClose;
            $this->onClose = null;
            foreach ($onClose as $callback) {
                asyncCall($callback, $this);
            }
        }
        return new Success();
    }
    /**
     *
     */
    private function hasStreamFor(Request $request) : bool
    {
        return !$this->busy && $this->socket && !$this->socket->isClosed() && ($this->getRemainingTime() > 0 || $request->isIdempotent());
    }
    /**
     * @inheritdoc
     */
    private function request(Request $request, CancellationToken $cancellation, Stream $stream) : Promise
    {
        return call(function () use($request, $cancellation, $stream) {
            ++$this->requestCounter;
            if ($this->socket !== null && !$this->socket->isClosed()) {
                $this->socket->reference();
            }
            if ($this->timeoutWatcher !== null) {
                Loop::cancel($this->timeoutWatcher);
                $this->timeoutWatcher = null;
            }
            (yield RequestNormalizer::normalizeRequest($request));
            $protocolVersion = $this->determineProtocolVersion($request);
            $request->setProtocolVersions([$protocolVersion]);
            if ($request->getTransferTimeout() > 0) {
                $timeoutToken = new TimeoutCancellationToken($request->getTransferTimeout());
                $combinedCancellation = new CombinedCancellationToken($cancellation, $timeoutToken);
            } else {
                $combinedCancellation = $cancellation;
            }
            $id = $combinedCancellation->subscribe([$this, 'close']);
            try {
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->startSendingRequest($request, $stream));
                }
                yield from $this->writeRequest($request, $protocolVersion, $combinedCancellation);
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->completeSendingRequest($request, $stream));
                }
                return yield from $this->readResponse($request, $cancellation, $combinedCancellation, $stream);
            } catch (\Throwable $e) {
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->abort($request, $e));
                }
                if ($this->socket !== null) {
                    $this->socket->close();
                }
                throw $e;
            } finally {
                $combinedCancellation->unsubscribe($id);
                $cancellation->throwIfRequested();
            }
        });
    }
    /**
     *
     */
    private function release() : void
    {
        $this->busy = false;
    }
    /**
     * @param Request $request
     * @param CancellationToken $originalCancellation
     * @param CancellationToken $readingCancellation
     *
     * @param Stream $stream
     *
     * @return \Generator
     * @throws CancelledException
     * @throws HttpException
     * @throws ParseException
     * @throws SocketException
     */
    private function readResponse(Request $request, CancellationToken $originalCancellation, CancellationToken $readingCancellation, Stream $stream) : \Generator
    {
        $bodyEmitter = new Emitter();
        $backpressure = new Success();
        $bodyCallback = static function ($data) use($bodyEmitter, &$backpressure) : void {
            $backpressure = $bodyEmitter->emit($data);
        };
        $trailersDeferred = new Deferred();
        $trailers = [];
        $trailersCallback = static function (array $headers) use(&$trailers) : void {
            $trailers = $headers;
        };
        $parser = new Http1Parser($request, $bodyCallback, $trailersCallback);
        $start = getCurrentTime();
        $timeout = $request->getInactivityTimeout();
        try {
            if ($this->socket === null) {
                throw new SocketException('Socket closed prior to response completion');
            }
            while (null !== ($chunk = (yield $timeout > 0 ? Promise\timeout($this->idleRead ?: $this->socket->read(), $timeout) : ($this->idleRead ?: $this->socket->read())))) {
                $this->idleRead = null;
                parseChunk:
                $response = $parser->parse($chunk);
                if ($response === null) {
                    if ($this->socket === null) {
                        throw new SocketException('Socket closed prior to response completion');
                    }
                    continue;
                }
                $this->lastUsedAt = getCurrentTime();
                $status = $response->getStatus();
                if ($status === Http\Status::SWITCHING_PROTOCOLS) {
                    $connection = Http\createFieldValueComponentMap(Http\parseFieldValueComponents($response, 'connection'));
                    if (!isset($connection['upgrade'])) {
                        throw new HttpException('Switching protocols response missing "Connection: upgrade" header');
                    }
                    if (!$response->hasHeader('upgrade')) {
                        throw new HttpException('Switching protocols response missing "Upgrade" header');
                    }
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeReceivingResponse($request, $stream));
                    }
                    $trailersDeferred->resolve($trailers);
                    return $this->handleUpgradeResponse($request, $response, $parser->getBuffer());
                }
                if ($status < 200) {
                    // 1XX responses (excluding 101, handled above)
                    $onInformationalResponse = $request->getInformationalResponseHandler();
                    if ($onInformationalResponse !== null) {
                        (yield call($onInformationalResponse, $response));
                    }
                    $chunk = $parser->getBuffer();
                    $parser = new Http1Parser($request, $bodyCallback, $trailersCallback);
                    goto parseChunk;
                }
                foreach ($request->getEventListeners() as $eventListener) {
                    (yield $eventListener->startReceivingResponse($request, $stream));
                }
                if ($status >= 200 && $status < 300 && $request->getMethod() === 'CONNECT') {
                    foreach ($request->getEventListeners() as $eventListener) {
                        (yield $eventListener->completeReceivingResponse($request, $stream));
                    }
                    $trailersDeferred->resolve($trailers);
                    return $this->handleUpgradeResponse($request, $response, $parser->getBuffer());
                }
                $bodyCancellationSource = new CancellationTokenSource();
                $bodyCancellationToken = new CombinedCancellationToken($readingCancellation, $bodyCancellationSource->getToken());
                $response->setTrailers($trailersDeferred->promise());
                $response->setBody(new ResponseBodyStream(new IteratorStream($bodyEmitter->iterate()), $bodyCancellationSource));
                // Read body async
                asyncCall(function () use($parser, $request, $response, $bodyEmitter, $trailersDeferred, $originalCancellation, $readingCancellation, $bodyCancellationToken, $stream, $timeout, &$backpressure, &$trailers) {
                    $id = $bodyCancellationToken->subscribe([$this, 'close']);
                    try {
                        // Required, otherwise responses without body hang
                        if (!$parser->isComplete()) {
                            // Directly parse again in case we already have the full body but aborted parsing
                            // to resolve promise with headers.
                            $chunk = null;
                            try {
                                /** @psalm-suppress PossiblyNullReference */
                                do {
                                    /** @noinspection CallableParameterUseCaseInTypeContextInspection */
                                    $parser->parse($chunk);
                                    /**
                                     * @noinspection NotOptimalIfConditionsInspection
                                     * @psalm-suppress TypeDoesNotContainType
                                     */
                                    if ($parser->isComplete()) {
                                        break;
                                    }
                                    if (!$backpressure instanceof Success) {
                                        (yield $this->withCancellation($backpressure, $bodyCancellationToken));
                                    }
                                    /** @psalm-suppress TypeDoesNotContainNull */
                                    if ($this->socket === null) {
                                        throw new SocketException('Socket closed prior to response completion');
                                    }
                                } while (null !== ($chunk = (yield $timeout > 0 ? Promise\timeout($this->socket->read(), $timeout) : $this->socket->read())));
                            } catch (PromiseTimeoutException $e) {
                                $this->close();
                                throw new TimeoutException('Inactivity timeout exceeded, more than ' . $timeout . ' ms elapsed from last data received', 0, $e);
                            }
                            $originalCancellation->throwIfRequested();
                            if ($readingCancellation->isRequested()) {
                                throw new TimeoutException('Allowed transfer timeout exceeded, took longer than ' . $request->getTransferTimeout() . ' ms');
                            }
                            $bodyCancellationToken->throwIfRequested();
                            // Ignore check if neither content-length nor chunked encoding are given.
                            if (!$parser->isComplete() && $parser->getState() !== Http1Parser::BODY_IDENTITY_EOF) {
                                throw new SocketException('Socket disconnected prior to response completion');
                            }
                        }
                        $timeout = $this->determineKeepAliveTimeout($response);
                        if ($timeout > 0 && $parser->getState() !== Http1Parser::BODY_IDENTITY_EOF) {
                            $this->timeoutWatcher = Loop::delay($timeout * 1000, [$this, 'close']);
                            Loop::unreference($this->timeoutWatcher);
                            $this->watchIdleConnection();
                        } else {
                            $this->close();
                        }
                        $this->busy = false;
                        foreach ($request->getEventListeners() as $eventListener) {
                            (yield $eventListener->completeReceivingResponse($request, $stream));
                        }
                        $bodyEmitter->complete();
                        $trailersDeferred->resolve($trailers);
                    } catch (\Throwable $e) {
                        $this->close();
                        try {
                            foreach ($request->getEventListeners() as $eventListener) {
                                (yield $eventListener->abort($request, $e));
                            }
                        } finally {
                            $bodyEmitter->fail($e);
                            $trailersDeferred->fail($e);
                        }
                    } finally {
                        $bodyCancellationToken->unsubscribe($id);
                    }
                });
                return $response;
            }
            $originalCancellation->throwIfRequested();
            throw new SocketException(\sprintf("Receiving the response headers for '%s' failed, because the socket to '%s' @ '%s' closed early with %d bytes received within %d milliseconds", (string) $request->getUri()->withUserInfo(''), $request->getUri()->withUserInfo('')->getAuthority(), $this->socket === null ? '???' : (string) $this->socket->getRemoteAddress(), \strlen($parser->getBuffer()), getCurrentTime() - $start));
        } catch (HttpException $e) {
            $this->close();
            throw $e;
        } catch (PromiseTimeoutException $e) {
            $this->close();
            throw new TimeoutException('Inactivity timeout exceeded, more than ' . $timeout . ' ms elapsed from last data received', 0, $e);
        } catch (\Throwable $e) {
            $this->close();
            throw new SocketException('Receiving the response headers failed: ' . $e->getMessage(), 0, $e);
        }
    }
    /**
     *
     */
    private function handleUpgradeResponse(Request $request, Response $response, string $buffer) : Response
    {
        if ($this->socket === null) {
            throw new SocketException('Socket closed while upgrading');
        }
        $socket = new UpgradedSocket($this->socket, $buffer);
        $this->free();
        // Mark this connection as unusable without closing socket.
        if (($onUpgrade = $request->getUpgradeHandler()) === null) {
            $socket->close();
            throw new HttpException('CONNECT or upgrade request made without upgrade handler callback');
        }
        asyncCall(static function () use($onUpgrade, $socket, $request, $response) : \Generator {
            try {
                (yield call($onUpgrade, $socket, $request, $response));
            } catch (\Throwable $exception) {
                $socket->close();
                throw new HttpException('Upgrade handler threw an exception', 0, $exception);
            }
        });
        return $response;
    }
    /**
     * @return int Approximate number of milliseconds remaining until the connection is closed.
     */
    private function getRemainingTime() : int
    {
        $timestamp = $this->lastUsedAt + ($this->explicitTimeout ? $this->priorTimeout * 1000 : $this->timeoutGracePeriod);
        return \max(0, $timestamp - getCurrentTime());
    }
    /**
     *
     */
    private function withCancellation(Promise $promise, CancellationToken $cancellationToken) : Promise
    {
        $deferred = new Deferred();
        $newPromise = $deferred->promise();
        $promise->onResolve(static function ($error, $value) use(&$deferred) : void {
            if ($deferred) {
                $temp = $deferred;
                $deferred = null;
                if ($error) {
                    $temp->fail($error);
                } else {
                    $temp->resolve($value);
                }
            }
        });
        $cancellationSubscription = $cancellationToken->subscribe(static function ($e) use(&$deferred) : void {
            if ($deferred) {
                $temp = $deferred;
                $deferred = null;
                $temp->fail($e);
            }
        });
        $newPromise->onResolve(static function () use($cancellationToken, $cancellationSubscription) : void {
            $cancellationToken->unsubscribe($cancellationSubscription);
        });
        return $newPromise;
    }
    /**
     *
     */
    private function determineKeepAliveTimeout(Response $response) : int
    {
        $request = $response->getRequest();
        $requestConnHeader = $request->getHeader('connection') ?? '';
        $responseConnHeader = $response->getHeader('connection') ?? '';
        if (!\strcasecmp($requestConnHeader, 'close')) {
            return 0;
        }
        if ($response->getProtocolVersion() === '1.0') {
            return 0;
        }
        if (!\strcasecmp($responseConnHeader, 'close')) {
            return 0;
        }
        $params = Http\createFieldValueComponentMap(Http\parseFieldValueComponents($response, 'keep-alive'));
        $timeout = (int) ($params['timeout'] ?? $this->priorTimeout);
        if (isset($params['timeout'])) {
            $this->explicitTimeout = true;
        }
        return $this->priorTimeout = \min(\max(0, $timeout), self::MAX_KEEP_ALIVE_TIMEOUT);
    }
    /**
     *
     */
    private function determineProtocolVersion(Request $request) : string
    {
        $protocolVersions = $request->getProtocolVersions();
        if (\in_array("1.1", $protocolVersions, true)) {
            return "1.1";
        }
        if (\in_array("1.0", $protocolVersions, true)) {
            return "1.0";
        }
        throw new InvalidRequestException($request, "None of the requested protocol versions is supported: " . \implode(", ", $protocolVersions));
    }
    /**
     *
     */
    private function writeRequest(Request $request, string $protocolVersion, CancellationToken $cancellation) : \Generator
    {
        try {
            $rawHeaders = $this->generateRawHeader($request, $protocolVersion);
            if ($this->socket === null) {
                throw new UnprocessedRequestException(new SocketException('Socket closed before request started'));
            }
            (yield $this->socket->write($rawHeaders));
            if ($request->getMethod() === 'CONNECT') {
                return;
            }
            $body = $request->getBody()->createBodyStream();
            $chunking = $request->getHeader("transfer-encoding") === "chunked";
            $remainingBytes = $request->getHeader("content-length");
            if ($remainingBytes !== null) {
                $remainingBytes = (int) $remainingBytes;
            }
            if ($chunking && $protocolVersion === "1.0") {
                throw new InvalidRequestException($request, "Can't send chunked bodies over HTTP/1.0");
            }
            // We always buffer the last chunk to make sure we don't write $contentLength bytes if the body is too long.
            $buffer = "";
            while (null !== ($chunk = (yield $body->read()))) {
                $cancellation->throwIfRequested();
                if ($chunk === "") {
                    continue;
                }
                if ($chunking) {
                    $chunk = \dechex(\strlen($chunk)) . "\r\n" . $chunk . "\r\n";
                } elseif ($remainingBytes !== null) {
                    $remainingBytes -= \strlen($chunk);
                    if ($remainingBytes < 0) {
                        throw new InvalidRequestException($request, "Body contained more bytes than specified in Content-Length, aborting request");
                    }
                }
                (yield $this->socket->write($buffer));
                $buffer = $chunk;
            }
            $cancellation->throwIfRequested();
            // Flush last buffered chunk.
            (yield $this->socket->write($buffer));
            if ($chunking) {
                (yield $this->socket->write("0\r\n\r\n"));
            } elseif ($remainingBytes !== null && $remainingBytes > 0) {
                throw new InvalidRequestException($request, "Body contained fewer bytes than specified in Content-Length, aborting request");
            }
        } catch (StreamException $exception) {
            throw new SocketException('Socket disconnected prior to response completion');
        }
    }
    /**
     * @param Request $request
     * @param string $protocolVersion
     *
     * @return string
     *
     * @throws HttpException
     */
    private function generateRawHeader(Request $request, string $protocolVersion) : string
    {
        $uri = $request->getUri();
        $requestUri = normalizeRequestPathWithQuery($request);
        $method = $request->getMethod();
        if ($method === 'CONNECT') {
            $defaultPort = $uri->getScheme() === 'https' ? 443 : 80;
            $requestUri = $uri->getHost() . ':' . ($uri->getPort() ?? $defaultPort);
        }
        $header = $method . ' ' . $requestUri . ' HTTP/' . $protocolVersion . "\r\n";
        try {
            $header .= Rfc7230::formatRawHeaders($request->getRawHeaders());
        } catch (InvalidHeaderException $e) {
            throw new HttpException($e->getMessage());
        }
        return $header . "\r\n";
    }
    /**
     *
     */
    private function watchIdleConnection() : void
    {
        if ($this->socket === null || $this->socket->isClosed()) {
            return;
        }
        $this->socket->unreference();
        $this->idleRead = $this->socket->read();
        $this->idleRead->onResolve(function ($error, $chunk) {
            if ($error || $chunk === null) {
                $this->close();
            }
        });
    }
}<?php

/** @noinspection PhpUnhandledExceptionInspection */
namespace Amp\Http\Client\Connection;

use Amp\CancellationToken;
use Amp\Http\Client\Connection\Internal\Http2ConnectionProcessor;
use Amp\Http\Client\Internal\ForbidCloning;
use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\Client\Request;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use function Amp\call;
final class Http2Connection implements Connection
{
    use ForbidSerialization;
    use ForbidCloning;
    private const PROTOCOL_VERSIONS = ['2'];
    /** @var EncryptableSocket */
    private $socket;
    /** @var Http2ConnectionProcessor */
    private $processor;
    /** @var int */
    private $requestCount = 0;
    /**
     *
     */
    public function __construct(EncryptableSocket $socket)
    {
        $this->socket = $socket;
        $this->processor = new Http2ConnectionProcessor($socket);
    }
    /**
     *
     */
    public function getProtocolVersions() : array
    {
        return self::PROTOCOL_VERSIONS;
    }
    /**
     *
     */
    public function initialize() : Promise
    {
        return $this->processor->initialize();
    }
    /**
     *
     */
    public function getStream(Request $request) : Promise
    {
        if (!$this->processor->isInitialized()) {
            throw new \Error('The promise returned from ' . __CLASS__ . '::initialize() must resolve before using the connection');
        }
        return call(function () {
            if ($this->processor->isClosed() || $this->processor->getRemainingStreams() <= 0) {
                return null;
            }
            $this->processor->reserveStream();
            return HttpStream::fromConnection($this, \Closure::fromCallable([$this, 'request']), \Closure::fromCallable([$this->processor, 'unreserveStream']));
        });
    }
    /**
     *
     */
    public function onClose(callable $onClose) : void
    {
        $this->processor->onClose($onClose);
    }
    /**
     *
     */
    public function close() : Promise
    {
        return $this->processor->close();
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->socket->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->socket->getRemoteAddress();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->socket->getTlsInfo();
    }
    /**
     *
     */
    private function request(Request $request, CancellationToken $token, Stream $applicationStream) : Promise
    {
        $this->requestCount++;
        return $this->processor->request($request, $token, $applicationStream);
    }
}<?php

namespace Amp\Http\Client\Connection;

use Amp\Http\Client\HttpException;
/**
 * @deprecated Exception moved to amphp/http. Catch the base exception class (HttpException) instead.
 */
final class Http2StreamException extends HttpException
{
    /** @var int */
    private $streamId;
    /**
     *
     */
    public function __construct(string $message, int $streamId, int $code, ?\Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->streamId = $streamId;
    }
    /**
     *
     */
    public function getStreamId() : int
    {
        return $this->streamId;
    }
}<?php

namespace Amp\Http\Client;

use Amp\CancellationToken;
use Amp\Http\Client\Connection\Stream;
use Amp\Promise;
/**
 * Allows intercepting an HTTP request after the connection to the remote server has been established.
 */
interface NetworkInterceptor
{
    /**
    * Intercepts an HTTP request after the connection to the remote server has been established.
    *
    * The implementation might modify the request and/or modify the response after the promise returned from
    `$stream->request(...)` resolved.
    *
    * A NetworkInterceptor SHOULD NOT short-circuit and SHOULD delegate to the `$stream` passed as third argument
    exactly once. The only exception to this is throwing an exception, e.g. because the TLS settings used are
    unacceptable. If you need short circuits, use an {@see ApplicationInterceptor} instead.
    *
    * @param Request $request
    * @param CancellationToken $cancellation
    * @param Stream $stream
    *
    * @return Promise<Response>
    */
    public function requestViaNetwork(Request $request, CancellationToken $cancellation, Stream $stream) : Promise;
}<?php

namespace Amp\Http\Client;

use Amp\Http\Client\Internal\ForbidSerialization;
use Amp\Http\InvalidHeaderException;
use Amp\Http\Message;
final class Trailers extends Message
{
    use ForbidSerialization;
    /** @see https://tools.ietf.org/html/rfc7230#section-4.1.2 */
    public const DISALLOWED_TRAILERS = ["authorization" => true, "content-encoding" => true, "content-length" => true, "content-range" => true, "content-type" => true, "cookie" => true, "expect" => true, "host" => true, "pragma" => true, "proxy-authenticate" => true, "proxy-authorization" => true, "range" => true, "te" => true, "trailer" => true, "transfer-encoding" => true, "www-authenticate" => true];
    /**
     * @param (string[] | string[][]) $headers
     *
     * @throws InvalidHeaderException Thrown if a disallowed field is in the header values.
     */
    public function __construct(array $headers)
    {
        if (!empty($headers)) {
            $this->setHeaders($headers);
        }
        if (\array_intersect_key($this->getHeaders(), self::DISALLOWED_TRAILERS)) {
            throw new InvalidHeaderException('Disallowed field in trailers');
        }
    }
}<?php

namespace Amp\Http\Client;

final class InvalidRequestException extends HttpException
{
    /** @var Request */
    private $request;
    /**
     *
     */
    public function __construct(Request $request, string $message, int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->request = $request;
    }
    /**
     *
     */
    public function getRequest() : Request
    {
        return $this->request;
    }
}<?php

namespace Amp\Http\Client;

class HttpException extends \Exception
{
}{
    "name": "amphp/http-client",
    "homepage": "https://github.com/amphp/http-client",
    "description": "Asynchronous concurrent HTTP/2 and HTTP/1.1 client built on the Amp concurrency framework",
    "keywords": [
        "http",
        "rest",
        "client",
        "concurrent",
        "async",
        "non-blocking"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@gmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.2",
        "amphp/amp": "^2.4",
        "amphp/byte-stream": "^1.6",
        "amphp/hpack": "^3",
        "amphp/http": "^1.6",
        "amphp/socket": "^1",
        "amphp/sync": "^1.3",
        "league/uri": "^6",
        "psr/http-message": "^1"
    },
    "require-dev": {
        "ext-json": "*",
        "amphp/file": "^0.2 || ^0.3 || ^1 || ^2",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^7 || ^8 || ^9",
        "amphp/http-server": "^2",
        "kelunik/link-header-rfc5988": "^1.0",
        "clue/socks-react": "^1.0",
        "amphp/react-adapter": "^2.1",
        "vimeo/psalm": "^4",
        "laminas/laminas-diactoros": "^2.3"
    },
    "suggest": {
        "ext-zlib": "Allows using compression for response bodies.",
        "ext-json": "Required for logging HTTP archives",
        "amphp/file": "Required for file request bodies and HTTP archive logging"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Http\\Client\\": "src"
        },
        "files": [
            "src/Internal/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Http\\Client\\": "test"
        }
    },
    "conflict": {
        "amphp/file": "<0.2 || >=3"
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "4.x-dev"
        }
    }
}
<?php

namespace Amp\Mysql;

use Amp\Socket\ConnectContext;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
final class ConnectionConfig extends SqlConnectionConfig
{
    public const DEFAULT_PORT = 3306;
    public const BIN_CHARSET = 45;
    // utf8mb4_general_ci
    public const KEY_MAP = ['hostname' => 'host', 'username' => 'user', 'pass' => 'password', 'database' => 'db', 'dbname' => 'db', 'compress' => 'compression', 'useCompression' => 'compression', 'cs' => 'charset', 'localInfile' => 'local-infile'];
    public const DEFAULT_CHARSET = "utf8mb4";
    public const DEFAULT_COLLATE = "utf8mb4_general_ci";
    /** @var bool */
    private $useCompression = false;
    /** @var bool */
    private $useLocalInfile = false;
    /** @var ConnectContext */
    private $context;
    /** @var string */
    private $charset = "utf8mb4";
    /** @var string  */
    private $collate = "utf8mb4_general_ci";
    /* @var string private key to use for sha256_password auth method */
    private $key;
    /**
     *
     */
    public static function fromString(string $connectionString, ConnectContext $context = null) : self
    {
        $parts = self::parseConnectionString($connectionString, self::KEY_MAP);
        if (!isset($parts['host'])) {
            throw new \Error('Host must be provided in connection string');
        }
        return new self($parts['host'], (int) ($parts['port'] ?? self::DEFAULT_PORT), $parts['user'] ?? null, $parts['password'] ?? null, $parts['db'] ?? null, $context, $parts['charset'] ?? self::DEFAULT_CHARSET, $parts['collate'] ?? self::DEFAULT_COLLATE, ($parts['compression'] ?? '') === 'on', ($parts['local-infile'] ?? '') === 'on');
    }
    /**
     *
     */
    public function __construct(string $host, int $port = self::DEFAULT_PORT, string $user = null, string $password = null, string $database = null, ConnectContext $context = null, string $charset = self::DEFAULT_CHARSET, string $collate = self::DEFAULT_COLLATE, bool $useCompression = false, string $key = '', bool $useLocalInfile = false)
    {
        parent::__construct($host, $port, $user, $password, $database);
        $this->context = $context ?? new ConnectContext();
        $this->charset = $charset;
        $this->collate = $collate;
        $this->useCompression = $useCompression;
        $this->key = $key;
        $this->useLocalInfile = $useLocalInfile;
    }
    /**
     *
     */
    public function getConnectionString() : string
    {
        return $this->getHost()[0] == "/" ? 'unix://' . $this->getHost() : 'tcp://' . $this->getHost() . ':' . $this->getPort();
    }
    /**
     *
     */
    public function isCompressionEnabled() : bool
    {
        return $this->useCompression;
    }
    /**
     *
     */
    public function withCompression() : self
    {
        $new = clone $this;
        $new->useCompression = true;
        return $new;
    }
    /**
     *
     */
    public function withoutCompression() : self
    {
        $new = clone $this;
        $new->useCompression = false;
        return $new;
    }
    /**
     *
     */
    public function isLocalInfileEnabled() : bool
    {
        return $this->useLocalInfile;
    }
    /**
     *
     */
    public function withLocalInfile() : self
    {
        $new = clone $this;
        $new->useLocalInfile = true;
        return $new;
    }
    /**
     *
     */
    public function withoutLocalInfile() : self
    {
        $new = clone $this;
        $new->useLocalInfile = false;
        return $new;
    }
    /**
     *
     */
    public function getConnectContext()
    {
        return $this->context;
    }
    /**
     *
     */
    public function withConnectContext(ConnectContext $context) : self
    {
        $new = clone $this;
        $new->context = $context;
        return $new;
    }
    /**
     *
     */
    public function getCharset() : string
    {
        return $this->charset;
    }
    /**
     *
     */
    public function getCollation() : string
    {
        return $this->collate;
    }
    /**
     *
     */
    public function withCharset(string $charset = self::DEFAULT_CHARSET, string $collate = self::DEFAULT_COLLATE) : self
    {
        $new = clone $this;
        $new->charset = $charset;
        $new->collate = $collate;
        return $new;
    }
    /**
     *
     */
    public function getKey() : string
    {
        return $this->key;
    }
    /**
     *
     */
    public function withKey(string $key) : self
    {
        $new = clone $this;
        $new->key = $key;
        return $new;
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Transaction as SqlTransaction;
use Amp\Sql\TransactionError;
use function Amp\call;
final class ConnectionTransaction implements SqlTransaction
{
    const SAVEPOINT_PREFIX = "amp_";
    /** @var Internal\Processor|null */
    private $processor;
    /** @var int */
    private $isolation;
    /** @var callable */
    private $release;
    /** @var int */
    private $refCount = 1;
    /**
     * @param Internal\Processor $processor
     * @param callable $release
     * @param int $isolation
     *
     * @throws \Error If the isolation level is invalid.
     */
    public function __construct(Internal\Processor $processor, callable $release, int $isolation = SqlTransaction::ISOLATION_COMMITTED)
    {
        switch ($isolation) {
            case SqlTransaction::ISOLATION_UNCOMMITTED:
            case SqlTransaction::ISOLATION_COMMITTED:
            case SqlTransaction::ISOLATION_REPEATABLE:
            case SqlTransaction::ISOLATION_SERIALIZABLE:
                $this->isolation = $isolation;
                break;
            default:
                throw new \Error("Isolation must be a valid transaction isolation level");
        }
        $this->processor = $processor;
        $refCount =& $this->refCount;
        $this->release = static function () use(&$refCount, $release) {
            if (--$refCount === 0) {
                $release();
            }
        };
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->processor && $this->processor->isAlive()) {
            $this->rollback();
            // Invokes $this->release callback.
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->processor->getLastUsedAt();
    }
    /**
     * {@inheritdoc}
     *
     * Closes and commits all changes in the transaction.
     */
    public function close() : void
    {
        if ($this->processor) {
            $this->commit();
            // Invokes $this->release callback.
        }
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->processor && $this->processor->isAlive();
    }
    /**
     * @return bool True if the transaction is active, false if it has been committed or rolled back.
     */
    public function isActive() : bool
    {
        return $this->processor !== null;
    }
    /**
     * @return int
     */
    public function getIsolationLevel() : int
    {
        return $this->isolation;
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function query(string $sql) : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            $result = (yield $this->processor->query($sql));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return new PooledResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function prepare(string $sql) : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            $statement = (yield $this->processor->prepare($sql));
            return new PooledStatement($statement, $this->release);
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql, $params) {
            $statement = (yield $this->processor->prepare($sql));
            \assert($statement instanceof Statement);
            $result = (yield $statement->execute($params));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return new PooledResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     * Commits the transaction and makes it inactive.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function commit() : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->processor->query("COMMIT");
        $this->processor = null;
        $promise->onResolve($this->release);
        return $promise;
    }
    /**
     * Rolls back the transaction and makes it inactive.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollback() : Promise
    {
        if ($this->processor === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->processor->query("ROLLBACK");
        $this->processor = null;
        $promise->onResolve($this->release);
        return $promise;
    }
    /**
     * Creates a savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function createSavepoint(string $identifier) : Promise
    {
        return $this->query(\sprintf("SAVEPOINT `%s%s`", self::SAVEPOINT_PREFIX, \sha1($identifier)));
    }
    /**
     * Rolls back to the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollbackTo(string $identifier) : Promise
    {
        return $this->query(\sprintf("ROLLBACK TO `%s%s`", self::SAVEPOINT_PREFIX, \sha1($identifier)));
    }
    /**
     * Releases the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function releaseSavepoint(string $identifier) : Promise
    {
        return $this->query(\sprintf("RELEASE SAVEPOINT `%s%s`", self::SAVEPOINT_PREFIX, \sha1($identifier)));
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Common\PooledStatement as SqlPooledStatement;
use Amp\Sql\ResultSet as SqlResultSet;
final class PooledStatement extends SqlPooledStatement implements Statement
{
    private $statement;
    /**
     *
     */
    public function __construct(Statement $statement, callable $release)
    {
        parent::__construct($statement, $release);
        $this->statement = $statement;
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    public function bind($paramId, $data) : void
    {
        $this->statement->bind($paramId, $data);
    }
    /**
     *
     */
    public function getFields() : Promise
    {
        return $this->statement->getFields();
    }
    /**
     *
     */
    public function reset() : Promise
    {
        return $this->statement->reset();
    }
}<?php

namespace Amp\Mysql;

use Amp\CancellationToken;
use Amp\Promise;
use Amp\Socket;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
use Amp\Sql\Connector;
final class CancellableConnector implements Connector
{
    /** @var Socket\Connector */
    private $connector;
    /**
     *
     */
    public function __construct(?Socket\Connector $connector = null)
    {
        $this->connector = $connector ?? Socket\connector();
    }
    /**
     *
     */
    public function connect(SqlConnectionConfig $config, ?CancellationToken $token = null) : Promise
    {
        if (!$config instanceof ConnectionConfig) {
            throw new \TypeError(\sprintf("Must provide an instance of %s to MySQL connectors", ConnectionConfig::class));
        }
        return Connection::connect($config, $token, $this->connector);
    }
}<?php

namespace Amp\Mysql;

use Amp\Deferred;
use Amp\Promise;
use Amp\Sql\ConnectionException;
use Amp\Sql\FailureException;
use Amp\Success;
use function Amp\call;
final class ConnectionStatement implements Statement
{
    private $paramCount;
    private $numParamCount;
    private $named = [];
    private $byNamed;
    private $query;
    private $stmtId;
    private $prebound = [];
    /** @var Internal\Processor|null */
    private $processor;
    /** @var Internal\ResultProxy */
    private $result;
    /** @var int */
    private $lastUsedAt;
    /**
     *
     */
    public function __construct(Internal\Processor $processor, string $query, int $stmtId, array $named, Internal\ResultProxy $result)
    {
        $this->processor = $processor;
        $this->query = $query;
        $this->stmtId = $stmtId;
        $this->result = $result;
        $this->numParamCount = $this->paramCount = $this->result->columnsToFetch;
        $this->byNamed = $named;
        foreach ($named as $name => $ids) {
            foreach ($ids as $id) {
                $this->named[$id] = $name;
                $this->numParamCount--;
            }
        }
        $this->lastUsedAt = \time();
    }
    /**
     *
     */
    private function getProcessor() : Internal\Processor
    {
        if ($this->processor === null) {
            throw new \Error("The statement has been closed");
        }
        if (!$this->processor->isAlive()) {
            throw new ConnectionException("Connection went away");
        }
        return $this->processor;
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        if ($this->processor === null) {
            return false;
        }
        return $this->processor->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public function bind($paramId, $data) : void
    {
        if (\is_int($paramId)) {
            if ($paramId >= $this->numParamCount) {
                throw new \Error("Parameter id {$paramId} is not defined for this prepared statement");
            }
            $i = $paramId;
        } elseif (\is_string($paramId)) {
            if (!isset($this->byNamed[$paramId])) {
                throw new \Error("Parameter :{$paramId} is not defined for this prepared statement");
            }
            $array = $this->byNamed[$paramId];
            $i = \reset($array);
        } else {
            throw new \TypeError("Invalid parameter ID type");
        }
        if (!\is_scalar($data) && !(\is_object($data) && \method_exists($data, '__toString'))) {
            throw new \TypeError("Data must be scalar or object that implements __toString method");
        }
        do {
            $realId = -1;
            while (isset($this->named[++$realId]) || $i-- > 0) {
                if (!\is_numeric($paramId) && isset($this->named[$realId]) && $this->named[$realId] == $paramId) {
                    break;
                }
            }
            $this->getProcessor()->bindParam($this->stmtId, $realId, $data);
        } while (isset($array) && ($i = \next($array)));
        if (isset($this->prebound[$paramId])) {
            $this->prebound[$paramId] .= (string) $data;
        } else {
            $this->prebound[$paramId] = (string) $data;
        }
    }
    /**
     * {@inheritdoc}
     */
    public function execute(array $params = []) : Promise
    {
        $this->lastUsedAt = \time();
        $prebound = $args = [];
        for ($unnamed = $i = 0; $i < $this->paramCount; $i++) {
            if (isset($this->named[$i])) {
                $name = $this->named[$i];
                if (\array_key_exists($name, $params)) {
                    $args[$i] = $params[$name];
                } elseif (!\array_key_exists($name, $this->prebound)) {
                    throw new \Error("Named parameter '{$name}' missing for executing prepared statement");
                } else {
                    $prebound[$i] = $this->prebound[$name];
                }
            } elseif (\array_key_exists($unnamed, $params)) {
                $args[$i] = $params[$unnamed];
                $unnamed++;
            } elseif (!\array_key_exists($unnamed, $this->prebound)) {
                throw new \Error("Parameter {$unnamed} for prepared statement missing");
            } else {
                $prebound[$i] = $this->prebound[$unnamed++];
            }
        }
        $promise = $this->getProcessor()->execute($this->stmtId, $this->query, $this->result->params, $prebound, $args);
        return call(function () use($promise) {
            $result = (yield $promise);
            if ($result instanceof Internal\ResultProxy) {
                $result = new ConnectionResultSet($result);
                return $result;
            }
            if ($result instanceof CommandResult) {
                return $result;
            }
            throw new FailureException("Unrecognized result type");
        });
    }
    /**
     *
     */
    public function getQuery() : string
    {
        return $this->query;
    }
    /**
     *
     */
    private function close() : void
    {
        if ($this->processor === null) {
            return;
        }
        $this->processor->closeStmt($this->stmtId);
        $this->processor->unreference();
        $this->processor = null;
    }
    /**
     *
     */
    public function reset() : Promise
    {
        return $this->getProcessor()->resetStmt($this->stmtId);
    }
    /**
     *
     */
    public function getFields() : Promise
    {
        if ($this->result->state >= Internal\ResultProxy::COLUMNS_FETCHED) {
            return new Success($this->result->columns);
        }
        if (isset($this->result->deferreds[Internal\ResultProxy::COLUMNS_FETCHED][0])) {
            return $this->result->deferreds[Internal\ResultProxy::COLUMNS_FETCHED][0][0]->promise();
        }
        $deferred = new Deferred();
        $this->result->deferreds[Internal\ResultProxy::COLUMNS_FETCHED][0] = [$deferred, &$this->result->columns, null];
        return $deferred->promise();
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
}<?php

namespace Amp\Mysql;

use Amp\Sql\FailureException;
/** @see 14.6.4.1.1.1 Column Type */
final class DataTypes
{
    public const MYSQL_TYPE_DECIMAL = 0x0;
    public const MYSQL_TYPE_TINY = 0x1;
    public const MYSQL_TYPE_SHORT = 0x2;
    public const MYSQL_TYPE_LONG = 0x3;
    public const MYSQL_TYPE_FLOAT = 0x4;
    public const MYSQL_TYPE_DOUBLE = 0x5;
    public const MYSQL_TYPE_NULL = 0x6;
    public const MYSQL_TYPE_TIMESTAMP = 0x7;
    public const MYSQL_TYPE_LONGLONG = 0x8;
    public const MYSQL_TYPE_INT24 = 0x9;
    public const MYSQL_TYPE_DATE = 0xa;
    public const MYSQL_TYPE_TIME = 0xb;
    public const MYSQL_TYPE_DATETIME = 0xc;
    public const MYSQL_TYPE_YEAR = 0xd;
    public const MYSQL_TYPE_NEWDATE = 0xe;
    public const MYSQL_TYPE_VARCHAR = 0xf;
    public const MYSQL_TYPE_BIT = 0x10;
    public const MYSQL_TYPE_TIMESTAMP2 = 0x11;
    public const MYSQL_TYPE_DATETIME2 = 0x12;
    public const MYSQL_TYPE_TIME2 = 0x13;
    public const MYSQL_TYPE_JSON = 0xf5;
    public const MYSQL_TYPE_NEWDECIMAL = 0xf6;
    public const MYSQL_TYPE_ENUM = 0xf7;
    public const MYSQL_TYPE_SET = 0xf8;
    public const MYSQL_TYPE_TINY_BLOB = 0xf9;
    public const MYSQL_TYPE_MEDIUM_BLOB = 0xfa;
    public const MYSQL_TYPE_LONG_BLOB = 0xfb;
    public const MYSQL_TYPE_BLOB = 0xfc;
    public const MYSQL_TYPE_VAR_STRING = 0xfd;
    public const MYSQL_TYPE_STRING = 0xfe;
    public const MYSQL_TYPE_GEOMETRY = 0xff;
    private const ENCODED_JSON_PREFIX = "base64:type251:";
    /**
     * @see 14.7.3 Binary Value
     */
    public static function encodeBinary($param) : array
    {
        $unsigned = 0;
        switch (\gettype($param)) {
            case "boolean":
                $type = self::MYSQL_TYPE_TINY;
                $value = $param ? "\x01" : "\x00";
                break;
            case "integer":
                if ($param >= 0) {
                    $unsigned = 1;
                }
                if ($param >= 0 && $param < 1 << 15) {
                    $value = self::encodeInt16($param);
                    $type = self::MYSQL_TYPE_SHORT;
                } else {
                    $value = self::encodeInt64($param);
                    $type = self::MYSQL_TYPE_LONGLONG;
                }
                break;
            case "double":
                $value = \pack("e", $param);
                $type = self::MYSQL_TYPE_DOUBLE;
                break;
            case "string":
                $type = self::MYSQL_TYPE_LONG_BLOB;
                $value = self::encodeInt(\strlen($param)) . $param;
                break;
            case "NULL":
                $type = self::MYSQL_TYPE_NULL;
                $value = "";
                break;
            default:
                throw new FailureException("Unexpected type for binding parameter: " . \gettype($param));
        }
        return [$unsigned, $type, $value];
    }
    /**
     * @see 14.7.3 Binary Protocol Value
     */
    public static function decodeBinary(int $type, string $str, ?int &$len = null)
    {
        $unsigned = $type & 0x80;
        switch ($type) {
            case self::MYSQL_TYPE_STRING:
            case self::MYSQL_TYPE_VARCHAR:
            case self::MYSQL_TYPE_VAR_STRING:
            case self::MYSQL_TYPE_ENUM:
            case self::MYSQL_TYPE_SET:
            case self::MYSQL_TYPE_LONG_BLOB:
            case self::MYSQL_TYPE_MEDIUM_BLOB:
            case self::MYSQL_TYPE_BLOB:
            case self::MYSQL_TYPE_TINY_BLOB:
            case self::MYSQL_TYPE_GEOMETRY:
            case self::MYSQL_TYPE_BIT:
            case self::MYSQL_TYPE_DECIMAL:
            case self::MYSQL_TYPE_NEWDECIMAL:
                $ret = self::decodeString($str, $intlen, $len);
                $len += $intlen;
                return $ret;
            case self::MYSQL_TYPE_JSON:
                $ret = self::decodeString($str, $intlen, $len);
                $len += $intlen;
                return self::decodeJson($ret);
            case self::MYSQL_TYPE_LONGLONG:
            case self::MYSQL_TYPE_LONGLONG | 0x80:
                $len = 8;
                return $unsigned ? self::decodeUnsigned64($str) : self::decodeInt64($str);
            case self::MYSQL_TYPE_LONG:
            case self::MYSQL_TYPE_LONG | 0x80:
            case self::MYSQL_TYPE_INT24:
            case self::MYSQL_TYPE_INT24 | 0x80:
                $len = 4;
                return $unsigned ? self::decodeUnsigned32($str) : self::decodeInt32($str);
            case self::MYSQL_TYPE_SHORT:
            case self::MYSQL_TYPE_SHORT | 0x80:
                $len = 2;
                return $unsigned ? self::decodeUnsigned16($str) : self::decodeInt16($str);
            case self::MYSQL_TYPE_TINY:
            case self::MYSQL_TYPE_TINY | 0x80:
                $len = 1;
                return $unsigned ? \ord($str) : self::decodeInt8($str);
            case self::MYSQL_TYPE_DOUBLE:
                $len = 8;
                return \unpack("e", $str)[1];
            case self::MYSQL_TYPE_FLOAT:
                $len = 4;
                return \unpack("g", $str)[1];
            case self::MYSQL_TYPE_DATE:
            case self::MYSQL_TYPE_DATETIME:
            case self::MYSQL_TYPE_TIMESTAMP:
                $year = $month = $day = $hour = $minute = $second = $microsecond = 0;
                switch ($len = \ord($str) + 1) {
                    case 12:
                        $microsecond = self::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($str, 8));
                    // no break
                    case 8:
                        $second = \ord($str[7]);
                        $minute = \ord($str[6]);
                        $hour = \ord($str[5]);
                    // no break
                    case 5:
                        $day = \ord($str[4]);
                        $month = \ord($str[3]);
                        $year = self::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($str, 1));
                    // no break
                    case 1:
                        break;
                    default:
                        throw new FailureException("Unexpected string length for date in binary protocol: " . ($len - 1));
                }
                return \str_pad($year, 2, "0", STR_PAD_LEFT) . "-" . \str_pad($month, 2, "0", STR_PAD_LEFT) . "-" . \str_pad($day, 2, "0", STR_PAD_LEFT) . " " . \str_pad($hour, 2, "0", STR_PAD_LEFT) . ":" . \str_pad($minute, 2, "0", STR_PAD_LEFT) . ":" . \str_pad($second, 2, "0", STR_PAD_LEFT) . "." . \str_pad($microsecond, 5, "0", STR_PAD_LEFT);
            case self::MYSQL_TYPE_TIME:
                $negative = $day = $hour = $minute = $second = $microsecond = 0;
                switch ($len = \ord($str) + 1) {
                    case 13:
                        $microsecond = self::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($str, 9));
                    // no break
                    case 9:
                        $second = \ord($str[8]);
                        $minute = \ord($str[7]);
                        $hour = \ord($str[6]);
                        $day = self::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($str, 2));
                        $negative = \ord($str[1]);
                    // no break
                    case 1:
                        break;
                    default:
                        throw new FailureException("Unexpected string length for time in binary protocol: " . ($len - 1));
                }
                return ($negative ? "" : "-") . \str_pad($day, 2, "0", STR_PAD_LEFT) . "d " . \str_pad($hour, 2, "0", STR_PAD_LEFT) . ":" . \str_pad($minute, 2, "0", STR_PAD_LEFT) . ":" . \str_pad($second, 2, "0", STR_PAD_LEFT) . "." . \str_pad($microsecond, 5, "0", STR_PAD_LEFT);
            case self::MYSQL_TYPE_NULL:
                $len = 0;
                return null;
            default:
                throw new FailureException("Invalid type for Binary Protocol: 0x" . \dechex($type));
        }
    }
    /**
     *
     */
    public static function decodeNullString(string $str, ?int &$len = null) : string
    {
        return \Phabel\Target\Php80\Polyfill::substr($str, 0, $len = \strpos($str, "\x00"));
    }
    /**
     *
     */
    public static function decodeStringOff(int $type, string $str, int &$off)
    {
        $len = self::decodeUnsignedOff($str, $off);
        $off += $len;
        $data = (string) \Phabel\Target\Php80\Polyfill::substr($str, $off - $len, $len);
        switch ($type) {
            case self::MYSQL_TYPE_LONGLONG | 0x80:
                return $type;
            // Return UNSIGNED BIGINT as a string.
            case self::MYSQL_TYPE_LONGLONG:
            case self::MYSQL_TYPE_LONG | 0x80:
                if (\PHP_INT_SIZE < 8) {
                    return $type;
                    // Return BIGINT and UNSIGNED INT as string on 32-bit.
                }
            // no break
            case self::MYSQL_TYPE_LONG:
            case self::MYSQL_TYPE_INT24:
            case self::MYSQL_TYPE_INT24 | 0x80:
            case self::MYSQL_TYPE_SHORT:
            case self::MYSQL_TYPE_SHORT | 0x80:
            case self::MYSQL_TYPE_TINY:
            case self::MYSQL_TYPE_TINY | 0x80:
                return (int) $data;
            case self::MYSQL_TYPE_DOUBLE:
            case self::MYSQL_TYPE_FLOAT:
                return (float) $data;
            case self::MYSQL_TYPE_JSON:
                return self::decodeJson($data);
            default:
                return $data;
        }
    }
    /**
     *
     */
    private static function decodeJson(string $data) : string
    {
        if (\strncmp(self::ENCODED_JSON_PREFIX, $data, \strlen(self::ENCODED_JSON_PREFIX)) !== 0) {
            return $data;
            // Data was not base-64 encoded.
        }
        $data = \Phabel\Target\Php80\Polyfill::substr($data, \strlen(self::ENCODED_JSON_PREFIX));
        return \base64_decode($data);
    }
    /**
     *
     */
    public static function decodeUnsignedOff(string $str, int &$off) : int
    {
        $int = \ord($str[$off]);
        if ($int < 0xfb) {
            $off += 1;
            return $int;
        }
        if ($int == 0xfc) {
            $off += 3;
            return self::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($str, $off - 2, 2));
        }
        if ($int == 0xfd) {
            $off += 4;
            return self::decodeUnsigned24(\Phabel\Target\Php80\Polyfill::substr($str, $off - 3, 3));
        }
        if ($int == 0xfe) {
            $off += 9;
            return self::decodeUnsigned64(\Phabel\Target\Php80\Polyfill::substr($str, $off - 8, 8));
        }
        // If that happens connection is borked...
        throw new FailureException("{$int} is not in ranges [0x00, 0xfa] or [0xfc, 0xfe]");
    }
    /**
     *
     */
    public static function decodeString(string $str, ?int &$intlen = null, ?int &$len = null) : string
    {
        $len = self::decodeUnsigned($str, $intlen);
        return \Phabel\Target\Php80\Polyfill::substr($str, $intlen, $len);
    }
    /**
     *
     */
    public static function decodeUnsigned(string $str, ?int &$len = null)
    {
        $int = \ord($str);
        if ($int < 0xfb) {
            $len = 1;
            return $int;
        }
        if ($int == 0xfc) {
            $len = 3;
            return self::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($str, 1, 2));
        }
        if ($int == 0xfd) {
            $len = 4;
            return self::decodeUnsigned24(\Phabel\Target\Php80\Polyfill::substr($str, 1, 4));
        }
        if ($int == 0xfe) {
            $len = 9;
            return self::decodeUnsigned64(\Phabel\Target\Php80\Polyfill::substr($str, 1, 8));
        }
        // If that happens connection is borked...
        throw new FailureException("{$int} is not in ranges [0x00, 0xfa] or [0xfc, 0xfe]");
    }
    /**
     *
     */
    public static function decodeIntByLen(string $str, int $len) : int
    {
        $int = 0;
        while ($len--) {
            $int = ($int << 8) + \ord($str[$len]);
        }
        return $int;
    }
    /**
     *
     */
    public static function decodeInt8(string $str) : int
    {
        $int = \ord($str);
        if ($int < 1 << 7) {
            return $int;
        }
        $shift = \PHP_INT_SIZE * 8 - 8;
        return $int << $shift >> $shift;
    }
    /**
     *
     */
    public static function decodeUnsigned8(string $str) : int
    {
        return \ord($str);
    }
    /**
     *
     */
    public static function decodeInt16(string $str) : int
    {
        $int = \unpack("v", $str)[1];
        if ($int < 1 << 15) {
            return $int;
        }
        $shift = \PHP_INT_SIZE * 8 - 16;
        return $int << $shift >> $shift;
    }
    /**
     *
     */
    public static function decodeUnsigned16(string $str)
    {
        return \unpack("v", $str)[1];
    }
    /**
     *
     */
    public static function decodeInt24(string $str) : int
    {
        $int = \unpack("V", \Phabel\Target\Php80\Polyfill::substr($str, 0, 3) . "\x00")[1];
        if ($int < 1 << 23) {
            return $int;
        }
        $shift = \PHP_INT_SIZE * 8 - 24;
        return $int << $shift >> $shift;
    }
    /**
     *
     */
    public static function decodeUnsigned24(string $str) : int
    {
        return \unpack("V", \Phabel\Target\Php80\Polyfill::substr($str, 0, 3) . "\x00")[1];
    }
    /**
     *
     */
    public static function decodeInt32($str) : int
    {
        if (\PHP_INT_SIZE > 4) {
            $int = \unpack("V", $str)[1];
            if ($int < 1 << 31) {
                return $int;
            }
            return $int << 32 >> 32;
        }
        return \unpack("V", $str)[1];
    }
    /**
     *
     */
    public static function decodeUnsigned32(string $str)
    {
        if (\PHP_INT_SIZE > 4) {
            return \unpack("V", $str)[1];
        }
        \assert(\extension_loaded("gmp"), "The GMP extension is required for UNSIGNED INT fields on 32-bit systems");
        return \gmp_strval(\gmp_import(\Phabel\Target\Php80\Polyfill::substr($str, 0, 4), 1, \GMP_LSW_FIRST));
    }
    /**
     *
     */
    public static function decodeInt64(string $str)
    {
        if (\PHP_INT_SIZE > 4) {
            return \unpack("P", $str)[1];
        }
        \assert(\extension_loaded("gmp"), "The GMP extension is required for BIGINT fields on 32-bit systems");
        return \gmp_strval(\gmp_import(\Phabel\Target\Php80\Polyfill::substr($str, 0, 8), 1, \GMP_LSW_FIRST));
    }
    /**
     *
     */
    public static function decodeUnsigned64(string $str)
    {
        \assert(\extension_loaded("gmp"), "The GMP extension is required for UNSIGNED BIGINT fields");
        return \gmp_strval(\gmp_import(\Phabel\Target\Php80\Polyfill::substr($str, 0, 8), 1, \GMP_LSW_FIRST));
    }
    /**
     *
     */
    public static function encodeInt(int $int) : string
    {
        if ($int < 0xfb) {
            return \chr($int);
        }
        if ($int < 1 << 16) {
            return "\xfc" . self::encodeInt16($int);
        }
        if ($int < 1 << 24) {
            return "\xfd" . self::encodeInt24($int);
        }
        if ($int < (1 << 62) * 4) {
            return "\xfe" . self::encodeInt64($int);
        }
        throw new FailureException("encodeInt doesn't allow integers bigger than 2^64 - 1 (current: {$int})");
    }
    /**
     *
     */
    public static function encodeInt16(int $int) : string
    {
        return \pack("v", $int);
    }
    /**
     *
     */
    public static function encodeInt24(int $int) : string
    {
        return \Phabel\Target\Php80\Polyfill::substr(\pack("V", $int), 0, 3);
    }
    /**
     *
     */
    public static function encodeInt32(int $int) : string
    {
        return \pack("V", $int);
    }
    /**
     *
     */
    public static function encodeInt64(int $int) : string
    {
        return \pack("VV", $int & 0xffffffff, $int >> 32);
    }
}<?php

namespace Amp\Mysql;

class TransactionError extends \Amp\Sql\TransactionError
{
}<?php

namespace Amp\Mysql;

use Amp\Sql\FailureException;
class InitializationException extends FailureException
{
}<?php

namespace Amp\Mysql\Internal;

use Amp\CancellationToken;
use Amp\Coroutine;
use Amp\Deferred;
use Amp\File;
use Amp\Loop;
use Amp\Mysql\CommandResult;
use Amp\Mysql\ConnectionConfig;
use Amp\Mysql\ConnectionStatement;
use Amp\Mysql\DataTypes;
use Amp\Mysql\InitializationException;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Sql\ConnectionException;
use Amp\Sql\FailureException;
use Amp\Sql\QueryError;
use Amp\Sql\TransientResource;
/* @TODO
 * 14.2.3 Auth switch request??
 * 14.2.4 COM_CHANGE_USER
 */
/** @see 14.1.3.4 Status Flags */
final class StatusFlags
{
    public const SERVER_STATUS_IN_TRANS = 0x1;
    // a transaction is active
    public const SERVER_STATUS_AUTOCOMMIT = 0x2;
    // auto-commit is enabled
    public const SERVER_MORE_RESULTS_EXISTS = 0x8;
    public const SERVER_STATUS_NO_GOOD_INDEX_USED = 0x10;
    public const SERVER_STATUS_NO_INDEX_USED = 0x20;
    public const SERVER_STATUS_CURSOR_EXISTS = 0x40;
    // Used by Binary Protocol Resultset to signal that COM_STMT_FETCH has to be used to fetch the row-data.
    public const SERVER_STATUS_LAST_ROW_SENT = 0x80;
    public const SERVER_STATUS_DB_DROPPED = 0x100;
    public const SERVER_STATUS_NO_BACKSLASH_ESCAPES = 0x200;
    public const SERVER_STATUS_METADATA_CHANGED = 0x400;
    public const SERVER_QUERY_WAS_SLOW = 0x800;
    public const SERVER_PS_OUT_PARAMS = 0x1000;
    public const SERVER_STATUS_IN_TRANS_READONLY = 0x2000;
    // in a read-only transaction
    public const SERVER_SESSION_STATE_CHANGED = 0x4000;
    // connection state information has changed
}
/** @see 13.1.3.1.1 Session State Information */
final class SessionStateTypes
{
    public const SESSION_TRACK_SYSTEM_VARIABLES = 0x0;
    public const SESSION_TRACK_SCHEMA = 0x1;
    public const SESSION_TRACK_STATE_CHANGE = 0x2;
    public const SESSION_TRACK_GTIDS = 0x3;
    public const SESSION_TRACK_TRANSACTION_CHARACTERISTICS = 0x4;
    public const SESSION_TRACK_TRANSACTION_STATE = 0x5;
}
/** @internal */
class Processor implements TransientResource
{
    const STATEMENT_PARAM_REGEX = <<<'REGEX'
~(["'`])(?:\\(?:\\|\1)|(?!\1).)*+\1(*SKIP)(*FAIL)|(\?)|:([a-zA-Z_][a-zA-Z0-9_]*)~ms
REGEX;
    /** @var \Generator[] */
    private $processors = [];
    /** @var int */
    private $protocol;
    private $seqId = -1;
    private $compressionId = -1;
    /** @var EncryptableSocket */
    private $socket;
    private $authPluginDataLen;
    private $query;
    public $named = [];
    /** @var callable|null */
    private $parseCallback = null;
    /** @var callable|null */
    private $packetCallback = null;
    /** @var \Amp\Promise|null */
    private $pendingWrite;
    /** @var \Amp\Sql\ConnectionConfig */
    public $config;
    /** @var \Amp\Deferred[] */
    private $deferreds = [];
    /** @var callable[] */
    private $onReady = [];
    /** @var ResultProxy|null */
    private $result;
    /** @var int */
    private $lastUsedAt;
    private $connectionId;
    private $authPluginData;
    private $capabilities = 0;
    private $serverCapabilities = 0;
    private $authPluginName;
    private $connInfo;
    private $refcount = 1;
    private $connectionState = self::UNCONNECTED;
    private const MAX_PACKET_SIZE = 0xffffff;
    private const MAX_UNCOMPRESSED_BUFLEN = 0xfffffb;
    private const CLIENT_LONG_FLAG = 0x4;
    private const CLIENT_CONNECT_WITH_DB = 0x8;
    private const CLIENT_COMPRESS = 0x20;
    private const CLIENT_LOCAL_INFILE = 0x80;
    private const CLIENT_PROTOCOL_41 = 0x200;
    private const CLIENT_SSL = 0x800;
    private const CLIENT_TRANSACTIONS = 0x2000;
    private const CLIENT_SECURE_CONNECTION = 0x8000;
    private const CLIENT_MULTI_STATEMENTS = 0x10000;
    private const CLIENT_MULTI_RESULTS = 0x20000;
    private const CLIENT_PS_MULTI_RESULTS = 0x40000;
    private const CLIENT_PLUGIN_AUTH = 0x80000;
    private const CLIENT_CONNECT_ATTRS = 0x100000;
    private const CLIENT_SESSION_TRACK = 0x800000;
    private const CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 0x200000;
    private const CLIENT_DEPRECATE_EOF = 0x1000000;
    private const OK_PACKET = 0x0;
    private const EXTRA_AUTH_PACKET = 0x1;
    private const LOCAL_INFILE_REQUEST = 0xfb;
    private const AUTH_SWITCH_PACKET = 0xfe;
    private const EOF_PACKET = 0xfe;
    private const ERR_PACKET = 0xff;
    private const UNCONNECTED = 0;
    private const ESTABLISHED = 1;
    private const READY = 2;
    private const CLOSING = 3;
    private const CLOSED = 4;
    /**
     *
     */
    public function __construct(EncryptableSocket $socket, ConnectionConfig $config)
    {
        $this->socket = $socket;
        $this->connInfo = new ConnectionState();
        $this->config = $config;
        $this->lastUsedAt = \time();
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return $this->connectionState <= self::READY;
    }
    /**
     *
     */
    public function isReady() : bool
    {
        return $this->connectionState === self::READY;
    }
    /**
     *
     */
    public function unreference() : void
    {
        if (!--$this->refcount) {
            $this->appendTask(function () {
                $this->close();
            });
        }
    }
    /**
     *
     */
    private function ready() : void
    {
        if (!empty($this->deferreds)) {
            return;
        }
        if (!empty($this->onReady)) {
            \array_shift($this->onReady)();
            return;
        }
        $this->resetIds();
        if ($this->socket) {
            try {
                $this->socket->unreference();
            } catch (Loop\InvalidWatcherError $exception) {
                // Undefined destruct order can cause unref of an invalid watcher if the loop is swapped.
                // Generally this will only happen during tests.
            }
        }
    }
    /**
     *
     */
    private function addDeferred(Deferred $deferred) : void
    {
        \assert($this->socket, "The connection has been closed");
        $this->deferreds[] = $deferred;
        $this->socket->reference();
    }
    /**
     *
     */
    public function connect(CancellationToken $token) : Promise
    {
        \assert(!$this->processors, self::class . "::connect() must not be called twice");
        $this->deferreds[] = $deferred = new Deferred();
        // Will be resolved in sendHandshake().
        $this->processors = [$this->parseMysql()];
        $id = $token->subscribe(function () : void {
            $this->close();
        });
        Promise\rethrow(new Coroutine($this->read()));
        $promise = $deferred->promise();
        $promise->onResolve(static function () use($id, $token) : void {
            $token->unsubscribe($id);
        });
        if ($this->config->getCharset() !== ConnectionConfig::DEFAULT_CHARSET || $this->config->getCollation() !== ConnectionConfig::DEFAULT_COLLATE) {
            $promise->onResolve(function (?\Throwable $exception) : void {
                if ($exception) {
                    return;
                }
                $charset = $this->config->getCharset();
                $collate = $this->config->getCollation();
                $this->query("SET NAMES '{$charset}'" . ($collate === "" ? "" : " COLLATE '{$collate}'"));
            });
        }
        return $promise;
    }
    /**
     *
     */
    private function read() : \Generator
    {
        try {
            while (($bytes = (yield $this->socket->read())) !== null) {
                // @codeCoverageIgnoreStart
                \assert((function () use($bytes) {
                    if (\defined("MYSQL_DEBUG")) {
                        \fwrite(STDERR, "in: ");
                        for ($i = 0; $i < \min(\strlen($bytes), 200); $i++) {
                            \fwrite(STDERR, \dechex(\ord($bytes[$i])) . " ");
                        }
                        $r = \range("\x00", "\x1f");
                        unset($r[10], $r[9]);
                        \fwrite(STDERR, "len: " . \strlen($bytes) . "\n");
                        \fwrite(STDERR, \str_replace($r, ".", \Phabel\Target\Php80\Polyfill::substr($bytes, 0, 200)) . "\n");
                    }
                    return true;
                })());
                // @codeCoverageIgnoreEnd
                $this->lastUsedAt = \time();
                $this->processData($bytes);
                $bytes = null;
                // Free last data read.
                if (!$this->socket) {
                    // Connection closed.
                    break;
                }
            }
        } catch (\Throwable $exception) {
            // $exception used as previous exception below.
        } finally {
            $this->close();
        }
        if (!empty($this->deferreds)) {
            $exception = new ConnectionException("Connection closed unexpectedly", 0, $exception ?? null);
            foreach ($this->deferreds as $deferred) {
                $deferred->fail($exception);
            }
        }
    }
    /**
     *
     */
    private function processData(string $data) : void
    {
        foreach ($this->processors as $processor) {
            if (empty($data = $processor->send($data))) {
                return;
            }
        }
        \assert(\is_array($data), "Final processor should yield an array");
        foreach ($data as $packet) {
            $this->parsePayload($packet);
        }
    }
    /**
     *
     */
    private function getDeferred() : Deferred
    {
        return \array_shift($this->deferreds);
    }
    /**
     *
     */
    private function appendTask(callable $callback) : void
    {
        if ($this->packetCallback || $this->parseCallback || !empty($this->onReady) || !empty($this->deferreds) || $this->connectionState !== self::READY) {
            $this->onReady[] = $callback;
        } else {
            $callback();
        }
    }
    /**
     *
     */
    public function getConnInfo() : ConnectionState
    {
        return clone $this->connInfo;
    }
    /**
     *
     */
    public function getConnectionId() : int
    {
        return $this->connectionId;
    }
    /**
     *
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     *
     */
    protected function startCommand(callable $callback) : Promise
    {
        if ($this->connectionState > self::READY) {
            throw new \Error("The connection has been closed");
        }
        $deferred = new Deferred();
        $this->appendTask(function () use($callback, $deferred) {
            $this->seqId = $this->compressionId = -1;
            $this->addDeferred($deferred);
            $callback();
        });
        return $deferred->promise();
    }
    /**
     *
     */
    public function setCharset(string $charset, string $collate = "") : Promise
    {
        return \Amp\call(function () use($charset, $collate) {
            if ($collate === "" && false !== ($off = \strpos($charset, "_"))) {
                $collate = $charset;
                $charset = \Phabel\Target\Php80\Polyfill::substr($collate, 0, $off);
            }
            $query = "SET NAMES '{$charset}'" . ($collate === "" ? "" : " COLLATE '{$collate}'");
            $result = (yield $this->query($query));
            $this->config = $this->config->withCharset($charset, $collate);
            return $result;
        });
    }
    /**
     * @see 14.6.3 COM_INIT_DB
     */
    public function useDb(string $db) : Promise
    {
        return $this->startCommand(function () use($db) {
            $this->config = $this->config->withDatabase($db);
            $this->sendPacket("\x02{$db}");
        });
    }
    /**
     * @see 14.6.4 COM_QUERY
     */
    public function query(string $query) : Promise
    {
        return $this->startCommand(function () use($query) {
            $this->query = $query;
            $this->parseCallback = [$this, "handleQuery"];
            $this->sendPacket("\x03{$query}");
        });
    }
    /**
     * @see 14.7.4 COM_STMT_PREPARE
     */
    public function prepare(string $query) : Promise
    {
        return $this->startCommand(function () use($query) {
            $this->query = $query;
            $this->parseCallback = [$this, "handlePrepare"];
            $query = \preg_replace_callback(self::STATEMENT_PARAM_REGEX, function ($m) {
                static $index = 0;
                if ($m[2] !== "?") {
                    $this->named[$m[3]][] = $index;
                }
                $index++;
                return "?";
            }, $query);
            $this->sendPacket("\x16{$query}");
        });
    }
    /** @see 14.6.18 COM_CHANGE_USER */
    /* @TODO broken, my test server doesn't support that command, can't test now
        public function changeUser($user, $pass, $db = null) {
            return $this->startCommand(function() use ($user, $pass, $db) {
                $this->config->user = $user;
                $this->config->pass = $pass;
                $this->config->db = $db;
                $payload = "\x11";
    
                $payload .= "$user\0";
                $auth = $this->secureAuth($this->config->pass, $this->authPluginData);
                if ($this->capabilities & self::CLIENT_SECURE_CONNECTION) {
                    $payload .= ord($auth) . $auth;
                } else {
                    $payload .= "$auth\0";
                }
                $payload .= "$db\0";
    
                $this->sendPacket($payload);
                $this->parseCallback = [$this, "authSwitchRequest"];
            });
        }
        */
    /**
     * @see 14.6.15 COM_PING
     */
    public function ping() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\x0e");
        });
    }
    /**
     * @see 14.6.19 COM_RESET_CONNECTION
     */
    public function resetConnection() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\x1f");
        });
    }
    /**
     * @see 14.7.5 COM_STMT_SEND_LONG_DATA
     */
    public function bindParam(int $stmtId, int $paramId, string $data) : void
    {
        $payload = "\x18";
        $payload .= DataTypes::encodeInt32($stmtId);
        $payload .= DataTypes::encodeInt16($paramId);
        $payload .= $data;
        $this->appendTask(function () use($payload) {
            $this->resetIds();
            $this->sendPacket($payload);
            $this->ready();
        });
    }
    /**
     * @see 14.7.6 COM_STMT_EXECUTE
     */
    // prebound params: null-bit set, type MYSQL_TYPE_LONG_BLOB, no value
    // $params is by-ref, because the actual result object might not yet have been filled completely with data upon call of this method ...
    public function execute(int $stmtId, string $query, array &$params, array $prebound, array $data = []) : Promise
    {
        $deferred = new Deferred();
        $this->appendTask(function () use($stmtId, $query, &$params, $prebound, $data, $deferred) {
            $payload = "\x17";
            $payload .= DataTypes::encodeInt32($stmtId);
            $payload .= \chr(0);
            // cursor flag // @TODO cursor types?!
            $payload .= DataTypes::encodeInt32(1);
            $paramCount = \count($params);
            $bound = !empty($data) || !empty($prebound);
            $types = "";
            $values = "";
            if ($paramCount) {
                $args = $data + \array_fill(0, $paramCount, null);
                \ksort($args);
                $args = \array_slice($args, 0, $paramCount);
                $nullOff = \strlen($payload);
                $payload .= \str_repeat("\x00", $paramCount + 7 >> 3);
                foreach ($args as $paramId => $param) {
                    if ($param === null) {
                        $off = $nullOff + ($paramId >> 3);
                        $payload[$off] = $payload[$off] | \chr(1 << $paramId % 8);
                    } else {
                        $bound = 1;
                    }
                    list($unsigned, $type, $value) = DataTypes::encodeBinary($param);
                    if (isset($prebound[$paramId])) {
                        $types .= \chr(DataTypes::MYSQL_TYPE_LONG_BLOB);
                    } else {
                        $types .= \chr($type);
                    }
                    $types .= $unsigned ? "\x80" : "\x00";
                    $values .= $value;
                }
                $payload .= \chr($bound);
                if ($bound) {
                    $payload .= $types;
                    $payload .= $values;
                }
            }
            $this->query = $query;
            $this->resetIds();
            $this->addDeferred($deferred);
            $this->sendPacket($payload);
            // apparently LOAD DATA LOCAL INFILE requests are not supported via prepared statements
            $this->packetCallback = [$this, "handleExecute"];
        });
        return $deferred->promise();
        // do not use $this->startCommand(), that might unexpectedly reset the seqId!
    }
    /**
     * @see 14.7.7 COM_STMT_CLOSE
     */
    public function closeStmt(int $stmtId) : void
    {
        $payload = "\x19" . DataTypes::encodeInt32($stmtId);
        $this->appendTask(function () use($payload) {
            if ($this->connectionState === self::READY) {
                $this->resetIds();
                $this->sendPacket($payload);
                $this->resetIds();
                // does not expect a reply - must be reset immediately
            }
            $this->ready();
        });
    }
    /**
     * @see 14.6.5 COM_FIELD_LIST
     */
    public function listFields(string $table, string $like = "%") : Promise
    {
        return $this->startCommand(static function () use($table, $like) {
            $this->sendPacket("\x04{$table}\x00{$like}");
            $this->parseCallback = [$this, "handleFieldlist"];
        });
    }
    /**
     *
     */
    public function listAllFields(string $table, string $like = "%") : Promise
    {
        $deferred = new Deferred();
        $columns = [];
        $onResolve = function ($error, $array) use(&$columns, &$onResolve, $deferred) {
            if ($error) {
                $deferred->fail($error);
                return;
            }
            if ($array === null) {
                $deferred->resolve($columns);
                return;
            }
            list($columns[], $promise) = $array;
            $promise->onResolve($onResolve);
        };
        $this->listFields($table, $like)->onResolve($onResolve);
        return $deferred->promise();
    }
    /**
     * @see 14.6.6 COM_CREATE_DB
     */
    public function createDatabase(string $db) : Promise
    {
        return $this->startCommand(function () use($db) {
            $this->sendPacket("\x05{$db}");
        });
    }
    /**
     * @see 14.6.7 COM_DROP_DB
     */
    public function dropDatabase(string $db) : Promise
    {
        return $this->startCommand(function () use($db) {
            $this->sendPacket("\x06{$db}");
        });
    }
    /**
     * @param $subcommand int one of the self::REFRESH_* constants
     * @see 14.6.8 COM_REFRESH
     */
    public function refresh(int $subcommand) : Promise
    {
        return $this->startCommand(function () use($subcommand) {
            $this->sendPacket("\x07" . \chr($subcommand));
        });
    }
    /**
     * @see 14.6.9 COM_SHUTDOWN
     */
    public function shutdown() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\x08\x00");
            /* SHUTDOWN_DEFAULT / SHUTDOWN_WAIT_ALL_BUFFERS, only one in use */
        });
    }
    /**
     * @see 14.6.10 COM_STATISTICS
     */
    public function statistics() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\t");
            $this->parseCallback = [$this, "readStatistics"];
        });
    }
    /**
     * @see 14.6.11 COM_PROCESS_INFO
     */
    public function processInfo() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\n");
            $this->query("SHOW PROCESSLIST");
        });
    }
    /**
     * @see 14.6.13 COM_PROCESS_KILL
     */
    public function killProcess(int $process) : Promise
    {
        return $this->startCommand(function () use($process) {
            $this->sendPacket("\f" . DataTypes::encodeInt32($process));
        });
    }
    /**
     * @see 14.6.14 COM_DEBUG
     */
    public function debugStdout() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\r");
        });
    }
    /**
     * @see 14.7.8 COM_STMT_RESET
     */
    public function resetStmt(int $stmtId) : Promise
    {
        $payload = "\x1a" . DataTypes::encodeInt32($stmtId);
        $deferred = new Deferred();
        $this->appendTask(function () use($payload, $deferred) {
            $this->resetIds();
            $this->addDeferred($deferred);
            $this->sendPacket($payload);
        });
        return $deferred->promise();
    }
    /**
     * @see 14.8.4 COM_STMT_FETCH
     */
    public function fetchStmt(int $stmtId) : Promise
    {
        $payload = "\x1c" . DataTypes::encodeInt32($stmtId) . DataTypes::encodeInt32(1);
        $deferred = new Deferred();
        $this->appendTask(function () use($payload, $deferred) {
            $this->resetIds();
            $this->addDeferred($deferred);
            $this->sendPacket($payload);
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function established() : void
    {
        // @TODO flags to use?
        $this->capabilities |= self::CLIENT_SESSION_TRACK | self::CLIENT_TRANSACTIONS | self::CLIENT_PROTOCOL_41 | self::CLIENT_SECURE_CONNECTION | self::CLIENT_MULTI_RESULTS | self::CLIENT_PS_MULTI_RESULTS | self::CLIENT_MULTI_STATEMENTS | self::CLIENT_PLUGIN_AUTH | self::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA;
        if (\extension_loaded("zlib") && $this->config->isCompressionEnabled()) {
            $this->capabilities |= self::CLIENT_COMPRESS;
        }
        if ($this->config->isLocalInfileEnabled()) {
            $this->capabilities |= self::CLIENT_LOCAL_INFILE;
        }
    }
    /**
     * @see 14.1.3.2 ERR-Packet
     */
    private function handleError(string $packet) : void
    {
        $off = 1;
        $this->connInfo->errorCode = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off, 2));
        $off += 2;
        if ($this->capabilities & self::CLIENT_PROTOCOL_41) {
            $this->connInfo->errorState = \Phabel\Target\Php80\Polyfill::substr($packet, $off, 6);
            $off += 6;
        }
        $this->connInfo->errorMsg = \Phabel\Target\Php80\Polyfill::substr($packet, $off);
        $this->parseCallback = null;
        if ($this->connectionState < self::READY) {
            // connection failure
            $this->close();
            $this->getDeferred()->fail(new InitializationException("Could not connect to {$this->config->getConnectionString()}: {$this->connInfo->errorState} {$this->connInfo->errorMsg}"));
            return;
        }
        if ($this->result === null && empty($this->deferreds)) {
            // connection killed without pending query or active result
            $this->close();
            return;
        }
        $deferred = $this->result ?? $this->getDeferred();
        // normal error
        $exception = new QueryError("MySQL error ({$this->connInfo->errorCode}): {$this->connInfo->errorState} {$this->connInfo->errorMsg}", $this->query);
        $this->result = null;
        $this->query = null;
        $deferred->fail($exception);
        $this->ready();
    }
    /**
     * @see 14.1.3.1 OK-Packet
     */
    private function parseOk(string $packet) : void
    {
        $off = 1;
        $this->connInfo->affectedRows = DataTypes::decodeUnsigned(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $intlen);
        $off += $intlen;
        $this->connInfo->insertId = DataTypes::decodeUnsigned(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $intlen);
        $off += $intlen;
        if ($this->capabilities & (self::CLIENT_PROTOCOL_41 | self::CLIENT_TRANSACTIONS)) {
            $this->connInfo->statusFlags = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
            $off += 2;
            $this->connInfo->warnings = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
            $off += 2;
        }
        if ($this->capabilities & self::CLIENT_SESSION_TRACK) {
            // Even though it seems required according to 14.1.3.1, there is no length encoded string, i.e. no trailing NULL byte ....???
            if (\strlen($packet) > $off) {
                $this->connInfo->statusInfo = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
                if ($this->connInfo->statusFlags & StatusFlags::SERVER_SESSION_STATE_CHANGED) {
                    $sessionState = DataTypes::decodeString(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $intlen, $sessionStateLen);
                    $len = 0;
                    while ($len < $sessionStateLen) {
                        $data = DataTypes::decodeString(\Phabel\Target\Php80\Polyfill::substr($sessionState, $len + 1), $datalen, $intlen);
                        switch ($type = DataTypes::decodeUnsigned8(\Phabel\Target\Php80\Polyfill::substr($sessionState, $len))) {
                            case SessionStateTypes::SESSION_TRACK_SYSTEM_VARIABLES:
                                $var = DataTypes::decodeString($data, $varintlen, $strlen);
                                $this->connInfo->sessionState[$type][$var] = DataTypes::decodeString(\Phabel\Target\Php80\Polyfill::substr($data, $varintlen + $strlen));
                                break;
                            case SessionStateTypes::SESSION_TRACK_SCHEMA:
                            case SessionStateTypes::SESSION_TRACK_STATE_CHANGE:
                            case SessionStateTypes::SESSION_TRACK_GTIDS:
                            case SessionStateTypes::SESSION_TRACK_TRANSACTION_CHARACTERISTICS:
                            case SessionStateTypes::SESSION_TRACK_TRANSACTION_STATE:
                                $this->connInfo->sessionState[$type] = DataTypes::decodeString($data);
                                break;
                            default:
                                throw new \Error("{$type} is not a valid mysql session state type");
                        }
                        $len += 1 + $intlen + $datalen;
                    }
                }
            } else {
                $this->connInfo->statusInfo = "";
            }
        } else {
            $this->connInfo->statusInfo = \Phabel\Target\Php80\Polyfill::substr($packet, $off);
        }
    }
    /**
     *
     */
    private function handleOk(string $packet) : void
    {
        $this->parseOk($packet);
        $this->getDeferred()->resolve(new CommandResult($this->connInfo->affectedRows, $this->connInfo->insertId));
        $this->ready();
    }
    /**
     * @see 14.1.3.3 EOF-Packet
     */
    private function parseEof(string $packet) : void
    {
        if ($this->capabilities & self::CLIENT_PROTOCOL_41) {
            $this->connInfo->warnings = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, 1));
            $this->connInfo->statusFlags = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, 3));
        }
    }
    /**
     *
     */
    private function handleEof(string $packet) : void
    {
        $this->parseEof($packet);
        $exception = new FailureException($this->connInfo->errorMsg, $this->connInfo->errorCode);
        $this->getDeferred()->fail($exception);
        $this->ready();
    }
    /**
     * @see 14.2.5 Connection Phase Packets
     */
    private function handleHandshake(string $packet) : void
    {
        $off = 1;
        $this->protocol = \ord($packet);
        if ($this->protocol !== 0xa) {
            throw new ConnectionException("Unsupported protocol version " . \ord($packet) . " (Expected: 10)");
        }
        $this->connInfo->serverVersion = DataTypes::decodeNullString(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $len);
        $off += $len + 1;
        $this->connectionId = DataTypes::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 4;
        $this->authPluginData = \Phabel\Target\Php80\Polyfill::substr($packet, $off, 8);
        $off += 8;
        $off += 1;
        // filler byte
        $this->serverCapabilities = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 2;
        if (\strlen($packet) > $off) {
            $this->connInfo->charset = \ord(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
            $off += 1;
            $this->connInfo->statusFlags = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
            $off += 2;
            $this->serverCapabilities += DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off)) << 16;
            $off += 2;
            $this->authPluginDataLen = $this->serverCapabilities & self::CLIENT_PLUGIN_AUTH ? \ord(\Phabel\Target\Php80\Polyfill::substr($packet, $off)) : 0;
            $off += 1;
            if ($this->serverCapabilities & self::CLIENT_SECURE_CONNECTION) {
                $off += 10;
                $strlen = \max(13, $this->authPluginDataLen - 8);
                $this->authPluginData .= \Phabel\Target\Php80\Polyfill::substr($packet, $off, $strlen);
                $off += $strlen;
                if ($this->serverCapabilities & self::CLIENT_PLUGIN_AUTH) {
                    $this->authPluginName = DataTypes::decodeNullString(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
                }
            }
        }
        $this->sendHandshake();
    }
    /**
     * @see 14.2.5 Connection Phase Packets
     */
    private function handleAuthSwitch($packet)
    {
        $off = 1;
        $this->authPluginName = DataTypes::decodeNullString(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += \strlen($this->authPluginName) + 1;
        $this->authPluginData = \Phabel\Target\Php80\Polyfill::substr($packet, $off);
        $this->sendAuthSwitchResponse();
    }
    /**
     *
     */
    private function sendAuthSwitchResponse()
    {
        $this->write($this->getAuthData());
    }
    /**
     * @see 14.6.4.1.2 LOCAL INFILE Request
     */
    private function handleLocalInfileRequest(string $packet) : void
    {
        \Amp\asyncCall(function () use($packet) {
            try {
                $filePath = \Phabel\Target\Php80\Polyfill::substr($packet, 1);
                /** @var \Amp\File\File $fileHandle */
                if (\function_exists("Amp\\File\\openFile")) {
                    // amphp/file 2.x
                    $fileHandle = (yield File\openFile($filePath, 'r'));
                } elseif (\function_exists("Amp\\File\\open")) {
                    // amphp/file 1.x or 0.3.x
                    $fileHandle = (yield File\open($filePath, 'r'));
                } else {
                    throw new \Error("amphp/file must be installed for LOCAL INFILE queries");
                }
                while ("" != ($chunk = (yield $fileHandle->read()))) {
                    $this->sendPacket($chunk);
                }
                $this->sendPacket("");
            } catch (\Throwable $e) {
                $this->getDeferred()->fail(new ConnectionException("Failed to transfer a file to the server", 0, $e));
            }
        });
    }
    /**
     * @see 14.6.4.1.1 Text Resultset
     */
    private function handleQuery(string $packet) : void
    {
        switch (\ord($packet)) {
            case self::OK_PACKET:
                $this->parseOk($packet);
                if ($this->connInfo->statusFlags & StatusFlags::SERVER_MORE_RESULTS_EXISTS) {
                    $this->getDeferred()->resolve($result = new ResultProxy());
                    $this->result = $result;
                    $result->updateState(ResultProxy::COLUMNS_FETCHED);
                    $this->successfulResultsetFetch();
                } else {
                    $this->parseCallback = null;
                    $this->getDeferred()->resolve(new CommandResult($this->connInfo->affectedRows, $this->connInfo->insertId));
                    $this->ready();
                }
                return;
            case self::LOCAL_INFILE_REQUEST:
                if ($this->config->isLocalInfileEnabled()) {
                    $this->handleLocalInfileRequest($packet);
                } else {
                    $this->getDeferred()->fail(new ConnectionException("Unexpected LOCAL_INFILE_REQUEST packet"));
                }
                return;
            case self::ERR_PACKET:
                $this->handleError($packet);
                return;
        }
        $this->parseCallback = [$this, "handleTextColumnDefinition"];
        $this->getDeferred()->resolve($result = new ResultProxy());
        /* we need to resolve before assigning vars, so that a onResolve() handler won't have a partial result available */
        $this->result = $result;
        $result->setColumns(DataTypes::decodeUnsigned($packet));
    }
    /**
     * @see 14.7.1 Binary Protocol Resultset
     */
    private function handleExecute(string $packet) : void
    {
        $this->parseCallback = [$this, "handleBinaryColumnDefinition"];
        $this->getDeferred()->resolve($result = new ResultProxy());
        /* we need to resolve before assigning vars, so that a onResolve() handler won't have a partial result available */
        $this->result = $result;
        $result->setColumns(\ord($packet));
    }
    /**
     *
     */
    private function handleFieldList(string $packet) : void
    {
        if (\ord($packet) === self::ERR_PACKET) {
            $this->parseCallback = null;
            $this->handleError($packet);
        } elseif (\ord($packet) === self::EOF_PACKET) {
            $this->parseCallback = null;
            $this->parseEof($packet);
            $this->getDeferred()->resolve(null);
            $this->ready();
        } else {
            $this->addDeferred($deferred = new Deferred());
            $this->getDeferred()->resolve([$this->parseColumnDefinition($packet), $deferred]);
        }
    }
    /**
     *
     */
    private function handleTextColumnDefinition(string $packet) : void
    {
        $this->handleColumnDefinition($packet, "handleTextResultSetRow");
    }
    /**
     *
     */
    private function handleBinaryColumnDefinition(string $packet) : void
    {
        $this->handleColumnDefinition($packet, "handleBinaryResultSetRow");
    }
    /**
     *
     */
    private function handleColumnDefinition(string $packet, string $cbMethod) : void
    {
        if (!$this->result->columnsToFetch--) {
            $this->result->updateState(ResultProxy::COLUMNS_FETCHED);
            if (\ord($packet) === self::ERR_PACKET) {
                $this->parseCallback = null;
                $this->handleError($packet);
            } else {
                $cb = $this->parseCallback = [$this, $cbMethod];
                if ($this->capabilities & self::CLIENT_DEPRECATE_EOF) {
                    $cb($packet);
                } else {
                    $this->parseEof($packet);
                    // we don't need the EOF packet, skip!
                }
            }
            return;
        }
        $this->result->columns[] = $this->parseColumnDefinition($packet);
    }
    /**
     *
     */
    private function prepareParams(string $packet) : void
    {
        if (!$this->result->columnsToFetch--) {
            $this->result->columnsToFetch = $this->result->columnCount;
            if (!$this->result->columnsToFetch) {
                $this->prepareFields($packet);
            } else {
                $this->parseCallback = [$this, "prepareFields"];
            }
            return;
        }
        $this->result->params[] = $this->parseColumnDefinition($packet);
    }
    /**
     *
     */
    private function prepareFields(string $packet) : void
    {
        if (!$this->result->columnsToFetch--) {
            $this->parseCallback = null;
            $this->query = null;
            $result = $this->result;
            $this->result = null;
            $this->ready();
            $result->updateState(ResultProxy::COLUMNS_FETCHED);
            return;
        }
        $this->result->columns[] = $this->parseColumnDefinition($packet);
    }
    /**
     * @see 14.6.4.1.1.2 Column Defintion
     */
    private function parseColumnDefinition(string $packet) : array
    {
        $off = 0;
        $column = [];
        if ($this->capabilities & self::CLIENT_PROTOCOL_41) {
            $column["catalog"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["schema"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["table"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["original_table"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["name"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["original_name"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $fixlen = DataTypes::decodeUnsignedOff($packet, $off);
            $len = 0;
            $column["charset"] = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off + $len));
            $len += 2;
            $column["columnlen"] = DataTypes::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($packet, $off + $len));
            $len += 4;
            $column["type"] = \ord($packet[$off + $len]);
            $len += 1;
            $column["flags"] = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off + $len));
            $len += 2;
            $column["decimals"] = \ord($packet[$off + $len]);
            //$len += 1;
            $off += $fixlen;
        } else {
            $column["table"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $column["name"] = DataTypes::decodeStringOff(DataTypes::MYSQL_TYPE_STRING, $packet, $off);
            $collen = DataTypes::decodeUnsignedOff($packet, $off);
            $column["columnlen"] = DataTypes::decodeIntByLen(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $collen);
            $off += $collen;
            $typelen = DataTypes::decodeUnsignedOff($packet, $off);
            $column["type"] = DataTypes::decodeIntByLen(\Phabel\Target\Php80\Polyfill::substr($packet, $off), $typelen);
            $off += $typelen;
            $len = 1;
            $flaglen = $this->capabilities & self::CLIENT_LONG_FLAG ? DataTypes::decodeUnsigned(\Phabel\Target\Php80\Polyfill::substr($packet, $off, 9), $len) : \ord($packet[$off]);
            $off += $len;
            if ($flaglen > 2) {
                $len = 2;
                $column["flags"] = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off, 4));
            } else {
                $len = 1;
                $column["flags"] = \ord($packet[$off]);
            }
            $column["decimals"] = \ord($packet[$off + $len]);
            $off += $flaglen;
        }
        if ($off < \strlen($packet)) {
            $column["defaults"] = DataTypes::decodeString(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        }
        return $column;
    }
    /**
     *
     */
    private function successfulResultsetFetch() : void
    {
        $result = $this->result;
        $deferred =& $result->next;
        if (!$deferred) {
            $deferred = new Deferred();
        }
        if ($this->connInfo->statusFlags & StatusFlags::SERVER_MORE_RESULTS_EXISTS) {
            $this->parseCallback = [$this, "handleQuery"];
            $this->addDeferred($deferred);
        } else {
            $this->parseCallback = null;
            $this->query = null;
            $this->result = null;
            $deferred->resolve();
            $this->ready();
        }
        $result->updateState(ResultProxy::ROWS_FETCHED);
    }
    /**
     * @see 14.6.4.1.1.3 Resultset Row
     */
    private function handleTextResultSetRow(string $packet) : void
    {
        $packettype = \ord($packet);
        if ($packettype === self::EOF_PACKET) {
            if ($this->capabilities & self::CLIENT_DEPRECATE_EOF) {
                $this->parseOk($packet);
            } else {
                $this->parseEof($packet);
            }
            $this->successfulResultsetFetch();
            return;
        } elseif ($packettype === self::ERR_PACKET) {
            $this->handleError($packet);
            return;
        }
        $off = 0;
        $columns = $this->result->columns;
        $fields = [];
        for ($i = 0; $off < \strlen($packet); ++$i) {
            if (\ord($packet[$off]) === 0xfb) {
                $fields[] = null;
                $off += 1;
            } else {
                $fields[] = DataTypes::decodeStringOff($columns[$i]["type"], $packet, $off);
            }
        }
        $this->result->rowFetched($fields);
    }
    /**
     * @see 14.7.2 Binary Protocol Resultset Row
     */
    private function handleBinaryResultSetRow(string $packet) : void
    {
        $packettype = \ord($packet);
        if ($packettype === self::EOF_PACKET) {
            $this->parseEof($packet);
            $this->successfulResultsetFetch();
            return;
        } elseif ($packettype === self::ERR_PACKET) {
            $this->handleError($packet);
            return;
        }
        $off = 1;
        // skip first byte
        $columnCount = $this->result->columnCount;
        $columns = $this->result->columns;
        $fields = [];
        for ($i = 0; $i < $columnCount; $i++) {
            if (\ord($packet[$off + ($i + 2 >> 3)]) & 1 << ($i + 2) % 8) {
                $fields[$i] = null;
            }
        }
        $off += $columnCount + 9 >> 3;
        for ($i = 0; $off < \strlen($packet); $i++) {
            while (\array_key_exists($i, $fields)) {
                $i++;
            }
            $fields[$i] = DataTypes::decodeBinary($columns[$i]["type"], \Phabel\Target\Php80\Polyfill::substr($packet, $off), $len);
            $off += $len;
        }
        \ksort($fields);
        $this->result->rowFetched($fields);
    }
    /**
     * @see 14.7.4.1 COM_STMT_PREPARE Response
     */
    private function handlePrepare(string $packet) : void
    {
        switch (\ord($packet)) {
            case self::OK_PACKET:
                break;
            case self::ERR_PACKET:
                $this->handleError($packet);
                return;
            default:
                throw new ConnectionException("Unexpected value for first byte of COM_STMT_PREPARE Response");
        }
        $off = 1;
        $stmtId = DataTypes::decodeUnsigned32(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 4;
        $columns = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 2;
        $params = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $off += 2;
        $off += 1;
        // filler
        $this->connInfo->warnings = DataTypes::decodeUnsigned16(\Phabel\Target\Php80\Polyfill::substr($packet, $off));
        $this->result = new ResultProxy();
        $this->result->columnsToFetch = $params;
        $this->result->columnCount = $columns;
        $this->refcount++;
        $this->getDeferred()->resolve(new ConnectionStatement($this, $this->query, $stmtId, $this->named, $this->result));
        $this->named = [];
        if ($params) {
            $this->parseCallback = [$this, "prepareParams"];
        } else {
            $this->prepareParams($packet);
        }
    }
    /**
     *
     */
    private function readStatistics(string $packet) : void
    {
        $this->getDeferred()->resolve($packet);
        $this->parseCallback = null;
        $this->ready();
    }
    /**
     * @see 14.6.2 COM_QUIT
     */
    public function sendClose() : Promise
    {
        return $this->startCommand(function () {
            $this->sendPacket("\x01");
            $this->connectionState = self::CLOSING;
        });
    }
    /**
     *
     */
    public function close() : void
    {
        if ($this->connectionState === self::CLOSING && $this->deferreds) {
            \array_pop($this->deferreds)->resolve();
        }
        $this->connectionState = self::CLOSED;
        if ($this->socket) {
            $this->socket->close();
            $this->socket = null;
        }
    }
    /**
     *
     */
    private function write(string $packet) : Promise
    {
        $packet = $this->compilePacket($packet);
        // @codeCoverageIgnoreStart
        \assert((function () use($packet) {
            if (\defined("MYSQL_DEBUG")) {
                \fwrite(STDERR, "out: ");
                for ($i = 0; $i < \min(\strlen($packet), 200); $i++) {
                    \fwrite(STDERR, \dechex(\ord($packet[$i])) . " ");
                }
                $r = \range("\x00", "\x1f");
                unset($r[10], $r[9]);
                \fwrite(STDERR, "len: " . \strlen($packet) . "\n");
                \fwrite(STDERR, \str_replace($r, ".", \Phabel\Target\Php80\Polyfill::substr($packet, 0, 200)) . "\n");
            }
            return true;
        })());
        // @codeCoverageIgnoreEnd
        if ($this->capabilities & self::CLIENT_COMPRESS && $this->connectionState >= self::READY) {
            $packet = $this->compressPacket($packet);
        }
        return $this->pendingWrite = $this->socket->write($packet);
    }
    /**
     *
     */
    private function resetIds() : void
    {
        if ($this->pendingWrite) {
            $this->pendingWrite->onResolve(function () {
                $this->seqId = $this->compressionId = -1;
            });
            return;
        }
        $this->seqId = $this->compressionId = -1;
    }
    /**
     *
     */
    private function compilePacket(string $pending) : string
    {
        $packet = "";
        do {
            $len = \strlen($pending);
            if ($len >= (1 << 24) - 1) {
                $out = \Phabel\Target\Php80\Polyfill::substr($pending, 0, (1 << 24) - 1);
                $pending = \Phabel\Target\Php80\Polyfill::substr($pending, (1 << 24) - 1);
                $len = (1 << 24) - 1;
            } else {
                $out = $pending;
                $pending = "";
            }
            $packet .= \Phabel\Target\Php80\Polyfill::substr_replace(\pack("V", $len), \chr(++$this->seqId), 3, 1) . $out;
            // expects $len < (1 << 24) - 1
        } while ($pending !== "");
        return $packet;
    }
    /**
     *
     */
    private function compressPacket(string $packet) : string
    {
        if ($packet === "") {
            return "";
        }
        $len = \strlen($packet);
        $deflated = \zlib_encode($packet, ZLIB_ENCODING_DEFLATE);
        if ($len < \strlen($deflated)) {
            return \Phabel\Target\Php80\Polyfill::substr_replace(\pack("V", \strlen($packet)), \chr(++$this->compressionId), 3, 1) . "\x00\x00\x00" . $packet;
        }
        return \Phabel\Target\Php80\Polyfill::substr_replace(\pack("V", \strlen($deflated)), \chr(++$this->compressionId), 3, 1) . \Phabel\Target\Php80\Polyfill::substr(\pack("V", $len), 0, 3) . $deflated;
    }
    /**
     * @see 14.4 Compression
     */
    private function parseCompression() : \Generator
    {
        $inflated = "";
        $buf = "";
        while (true) {
            while (\strlen($buf) < 7) {
                $buf .= (yield $inflated);
                $inflated = "";
            }
            $size = DataTypes::decodeUnsigned24($buf);
            $this->compressionId = \ord($buf[3]);
            $uncompressed = DataTypes::decodeUnsigned24(\Phabel\Target\Php80\Polyfill::substr($buf, 4, 3));
            $buf = \Phabel\Target\Php80\Polyfill::substr($buf, 7);
            if ($size > 0) {
                while (\strlen($buf) < $size) {
                    $buf .= (yield $inflated);
                    $inflated = "";
                }
                if ($uncompressed === 0) {
                    $inflated .= \Phabel\Target\Php80\Polyfill::substr($buf, 0, $size);
                } else {
                    $inflated .= \zlib_decode(\Phabel\Target\Php80\Polyfill::substr($buf, 0, $size), $uncompressed);
                }
                $buf = \Phabel\Target\Php80\Polyfill::substr($buf, $size);
            }
        }
    }
    /**
     * @see 14.1.2 MySQL Packet
     * @see 14.1.3 Generic Response Packets
     */
    private function parseMysql() : \Generator
    {
        $buf = "";
        $parsed = [];
        while (true) {
            $packet = "";
            do {
                while (\strlen($buf) < 4) {
                    $buf .= (yield $parsed);
                    $parsed = [];
                }
                $len = DataTypes::decodeUnsigned24($buf);
                $this->seqId = \ord($buf[3]);
                $buf = \Phabel\Target\Php80\Polyfill::substr($buf, 4);
                while (\strlen($buf) < ($len & 0xffffff)) {
                    $buf .= (yield $parsed);
                    $parsed = [];
                }
                $lastIn = $len !== 0xffffff;
                if ($lastIn) {
                    $size = $len % 0xffffff;
                } else {
                    $size = 0xffffff;
                }
                $packet .= \Phabel\Target\Php80\Polyfill::substr($buf, 0, $size);
                $buf = \Phabel\Target\Php80\Polyfill::substr($buf, $size);
            } while (!$lastIn);
            if (\strlen($packet) > 0) {
                $parsed[] = $packet;
            }
        }
    }
    /**
     *
     */
    private function parsePayload(string $packet) : void
    {
        if ($this->connectionState === self::UNCONNECTED) {
            $this->established();
            $this->connectionState = self::ESTABLISHED;
            $this->handleHandshake($packet);
            return;
        }
        if ($this->connectionState === self::ESTABLISHED) {
            switch (\ord($packet)) {
                case self::OK_PACKET:
                    if ($this->capabilities & self::CLIENT_COMPRESS) {
                        $this->processors = \array_merge([$this->parseCompression()], $this->processors);
                    }
                    $this->connectionState = self::READY;
                    $this->handleOk($packet);
                    break;
                case self::ERR_PACKET:
                    $this->handleError($packet);
                    break;
                case self::AUTH_SWITCH_PACKET:
                    $this->handleAuthSwitch($packet);
                    break;
                case self::EXTRA_AUTH_PACKET:
                    /** @see 14.2.5 Connection Phase Packets (AuthMoreData) */
                    switch ($this->authPluginName) {
                        case "sha256_password":
                            $key = \Phabel\Target\Php80\Polyfill::substr($packet, 1);
                            $this->config = $this->config->withKey($key);
                            $this->sendHandshake();
                            break;
                        case "caching_sha2_password":
                            switch (\ord(\Phabel\Target\Php80\Polyfill::substr($packet, 1, 1))) {
                                case 3:
                                    // success
                                    return;
                                // expecting OK afterwards
                                case 4:
                                    // fast auth failure
                                    if ($this->capabilities & self::CLIENT_SSL || $this->config->getHost()[0] === "/") {
                                        $this->write($this->config->getPassword() . "\x00");
                                    } else {
                                        $this->write("\x02");
                                    }
                                    break;
                                case 0x2d:
                                    // certificate
                                    $pubkey = \Phabel\Target\Php80\Polyfill::substr($packet, 1);
                                    $this->write($this->sha256Auth($this->config->getPassword(), $this->authPluginData, $pubkey));
                                    break;
                            }
                            break;
                        default:
                            throw new ConnectionException("Unexpected EXTRA_AUTH_PACKET in authentication phase for method {$this->authPluginName}");
                    }
                    break;
            }
            return;
        }
        if ($this->parseCallback) {
            ($this->parseCallback)($packet);
            return;
        }
        $cb = $this->packetCallback;
        $this->packetCallback = null;
        switch (\ord($packet)) {
            case self::OK_PACKET:
                $this->handleOk($packet);
                break;
            case self::ERR_PACKET:
                $this->handleError($packet);
                break;
            case self::EOF_PACKET:
                if (\strlen($packet) < 6) {
                    $this->handleEof($packet);
                    break;
                }
            // no break
            default:
                if (!$cb) {
                    throw new ConnectionException("Unexpected packet type: " . \ord($packet));
                }
                $cb($packet);
        }
    }
    /**
     *
     */
    private function secureAuth(string $pass, string $scramble) : string
    {
        $hash = \sha1($pass, 1);
        return $hash ^ \sha1(\Phabel\Target\Php80\Polyfill::substr($scramble, 0, 20) . \sha1($hash, 1), 1);
    }
    /**
     *
     */
    private function sha256Auth(string $pass, string $scramble, string $key) : string
    {
        \openssl_public_encrypt("{$pass}\x00" ^ \str_repeat($scramble, \ceil(\strlen($pass) / \strlen($scramble))), $auth, $key, OPENSSL_PKCS1_OAEP_PADDING);
        return $auth;
    }
    /**
     *
     */
    private function sha2Auth(string $pass, string $scramble) : string
    {
        $hash = \hash("sha256", $pass, true);
        return $hash ^ \hash("sha256", \Phabel\Target\Php80\Polyfill::substr($scramble, 0, 20) . \hash("sha256", $hash, true), true);
    }
    /**
     *
     */
    private function authSwitchRequest(string $packet) : void
    {
        $this->parseCallback = null;
        switch (\ord($packet)) {
            case self::EOF_PACKET:
                if (\strlen($packet) === 1) {
                    break;
                }
                $len = \strpos($packet, "\x00");
                $pluginName = \Phabel\Target\Php80\Polyfill::substr($packet, 0, $len);
                // @TODO mysql_native_pass only now...
                $authPluginData = \Phabel\Target\Php80\Polyfill::substr($packet, $len + 1);
                $this->sendPacket($this->secureAuth($this->config->getPassword(), $authPluginData));
                break;
            case self::ERR_PACKET:
                $this->handleError($packet);
                return;
            default:
                throw new ConnectionException("AuthSwitchRequest: Expecting 0xfe (or ERR_Packet), got 0x" . \dechex(\ord($packet)));
        }
    }
    /**
     * @see 14.2.5 Connection Phase Packets
     * @see 14.3 Authentication Method
     */
    private function sendHandshake(bool $inSSL = false) : void
    {
        if ($this->config->getDatabase() !== null) {
            $this->capabilities |= self::CLIENT_CONNECT_WITH_DB;
        }
        if ($this->config->getConnectContext()->getTlsContext() !== null) {
            $this->capabilities |= self::CLIENT_SSL;
        }
        $this->capabilities &= $this->serverCapabilities;
        $payload = "";
        $payload .= \pack("V", $this->capabilities);
        $payload .= \pack("V", 1 << 24 - 1);
        // max-packet size
        $payload .= \chr(ConnectionConfig::BIN_CHARSET);
        $payload .= \str_repeat("\x00", 23);
        // reserved
        if (!$inSSL && $this->capabilities & self::CLIENT_SSL) {
            \Amp\asyncCall(function () use($payload) {
                try {
                    (yield $this->write($payload));
                    (yield $this->socket->setupTls());
                    $this->sendHandshake(true);
                } catch (\Throwable $e) {
                    $this->close();
                    $this->getDeferred()->fail($e);
                }
            });
            return;
        }
        $payload .= $this->config->getUser() . "\x00";
        $auth = $this->getAuthData();
        if ($this->capabilities & self::CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA) {
            $payload .= DataTypes::encodeInt(\strlen($auth));
            $payload .= $auth;
        } elseif ($this->capabilities & self::CLIENT_SECURE_CONNECTION) {
            $payload .= \chr(\strlen($auth));
            $payload .= $auth;
        } else {
            $payload .= "{$auth}\x00";
        }
        if ($this->capabilities & self::CLIENT_CONNECT_WITH_DB) {
            $payload .= "{$this->config->getDatabase()}\x00";
        }
        if ($this->capabilities & self::CLIENT_PLUGIN_AUTH) {
            $payload .= "{$this->authPluginName}\x00";
        }
        if ($this->capabilities & self::CLIENT_CONNECT_ATTRS) {
            // connection attributes?! 5.6.6+ only!
        }
        $this->write($payload);
    }
    /**
     *
     */
    private function getAuthData() : string
    {
        $password = (string) $this->config->getPassword();
        if ($password === "") {
            return "";
        }
        if ($this->capabilities & self::CLIENT_PLUGIN_AUTH) {
            switch ($this->authPluginName) {
                case "mysql_native_password":
                    return $this->secureAuth($password, $this->authPluginData);
                case "mysql_clear_password":
                    return $password;
                case "sha256_password":
                    $key = $this->config->getKey();
                    if ($key !== "") {
                        return $this->sha256Auth($password, $this->authPluginData, $key);
                    }
                    return "\x01";
                case "caching_sha2_password":
                    return $this->sha2Auth($password, $this->authPluginData);
                case "mysql_old_password":
                    throw new ConnectionException("mysql_old_password is outdated and insecure. Intentionally not implemented!");
                default:
                    throw new ConnectionException("Invalid (or unimplemented?) auth method requested by server: {$this->authPluginName}");
            }
        }
        return $this->secureAuth($password, $this->authPluginData);
    }
    /**
     * @see 14.1.2 MySQL Packet
     */
    protected function sendPacket(string $payload) : Promise
    {
        if ($this->connectionState !== self::READY) {
            throw new \Error("Connection not ready, cannot send any packets");
        }
        return $this->write($payload);
    }
}<?php

namespace Amp\Mysql\Internal;

use Amp\Struct;
final class ConnectionState
{
    use Struct;
    /** @var int|null */
    public $affectedRows;
    public $insertId;
    public $statusFlags;
    public $warnings;
    public $statusInfo;
    public $sessionState = [];
    public $errorMsg;
    public $errorCode;
    public $errorState;
    // begins with "#"
    /** @var string */
    public $serverVersion;
    /** @var string */
    public $charset;
}<?php

namespace Amp\Mysql\Internal;

use Amp\Sql\FailureException;
use Amp\Struct;
final class ResultProxy
{
    use Struct;
    public $columnCount;
    public $columns = [];
    public $params = [];
    public $columnsToFetch;
    public $rows = [];
    public $fetchedRows = 0;
    public $userFetched = 0;
    public $deferreds = [self::UNFETCHED => [], self::COLUMNS_FETCHED => [], self::ROWS_FETCHED => []];
    /** @var int */
    public $state = self::UNFETCHED;
    /** @var \Amp\Deferred|null */
    public $next;
    public const UNFETCHED = 0;
    public const COLUMNS_FETCHED = 1;
    public const ROWS_FETCHED = 2;
    public const SINGLE_ROW_FETCH = 255;
    /**
     *
     */
    public function setColumns(int $columns) : void
    {
        $this->columnCount = $this->columnsToFetch = $columns;
    }
    /**
     *
     */
    public function updateState(int $state) : void
    {
        $this->state = $state;
        if ($state === self::ROWS_FETCHED) {
            $this->rowFetched(null);
        }
        if (empty($this->deferreds[$state])) {
            return;
        }
        foreach ($this->deferreds[$state] as [$deferred, $rows, $cb]) {
            $deferred->resolve($cb ? $cb($rows) : $rows);
        }
        $this->deferreds[$state] = [];
    }
    /**
     *
     */
    public function rowFetched(?array $row) : void
    {
        if ($row !== null) {
            $this->rows[$this->fetchedRows++] = $row;
        }
        [$entry, , $cb] = \current($this->deferreds[self::UNFETCHED]);
        if ($entry !== null) {
            unset($this->deferreds[self::UNFETCHED][\key($this->deferreds[self::UNFETCHED])]);
            $entry->resolve($cb && $row ? $cb($row) : $row);
        }
    }
    /**
     *
     */
    public function fail(FailureException $e) : void
    {
        foreach ($this->deferreds as $state) {
            foreach ($this->deferreds[$state] as [$deferred]) {
                $deferred->fail($e);
            }
            $this->deferreds[$state] = [];
        }
    }
    /**
     * @return array
     *
     * @codeCoverageIgnore
     */
    public function __debugInfo() : array
    {
        $tmp = clone $this;
        foreach ($tmp->deferreds as &$type) {
            foreach ($type as &$entry) {
                unset($entry[0], $entry[2]);
            }
        }
        return (array) $tmp;
    }
}<?php

namespace Amp\Mysql;

use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\Common\StatementPool as SqlStatementPool;
use Amp\Sql\Connector;
use Amp\Sql\Pool as SqlPool;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
use Amp\Sql\Transaction as SqlTransaction;
final class Pool extends ConnectionPool
{
    /**
     *
     */
    protected function createDefaultConnector() : Connector
    {
        return connector();
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    protected function createStatement(SqlStatement $statement, callable $release) : SqlStatement
    {
        \assert($statement instanceof Statement);
        return new PooledStatement($statement, $release);
    }
    /**
     *
     */
    protected function createStatementPool(SqlPool $pool, SqlStatement $statement, callable $prepare) : SqlStatementPool
    {
        \assert($statement instanceof Statement);
        return new StatementPool($pool, $statement, $prepare);
    }
    /**
     *
     */
    protected function createTransaction(SqlTransaction $transaction, callable $release) : SqlTransaction
    {
        return new PooledTransaction($transaction, $release);
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Common\StatementPool as SqlStatementPool;
use Amp\Sql\Pool;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
use Amp\Success;
use function Amp\call;
final class StatementPool extends SqlStatementPool implements Statement
{
    private $params = [];
    /**
     *
     */
    public function __construct(Pool $pool, Statement $statement, callable $prepare)
    {
        parent::__construct($pool, $statement, $prepare);
    }
    /**
     *
     */
    protected function prepare(SqlStatement $statement) : Promise
    {
        \assert($statement instanceof Statement);
        return call(function () use($statement) {
            (yield $statement->reset());
            foreach ($this->params as $paramId => $data) {
                $statement->bind($paramId, $data);
            }
            return $statement;
        });
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ConnectionResultSet || $resultSet instanceof PooledResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    public function bind($paramId, $data) : void
    {
        if (!\is_int($paramId) && !\is_string($paramId)) {
            throw new \TypeError("Invalid parameter ID type");
        }
        $this->params[$paramId] = $data;
    }
    /**
     *
     */
    public function reset() : Promise
    {
        $this->params = [];
        return new Success();
    }
    /**
     * @return Promise<array>
     */
    public function getFields() : Promise
    {
        return call(function () {
            $statement = (yield from $this->pop());
            \assert($statement instanceof Statement);
            $fields = (yield $statement->getFields());
            $this->push($statement);
            return $fields;
        });
    }
}<?php

namespace Amp\Mysql;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Socket;
use Amp\Sql\FailureException;
use Amp\Sql\Link;
use function Amp\call;
final class Connection implements Link
{
    public const REFRESH_GRANT = 0x1;
    public const REFRESH_LOG = 0x2;
    public const REFRESH_TABLES = 0x4;
    public const REFRESH_HOSTS = 0x8;
    public const REFRESH_STATUS = 0x10;
    public const REFRESH_THREADS = 0x20;
    public const REFRESH_SLAVE = 0x40;
    public const REFRESH_MASTER = 0x80;
    /** @var Internal\Processor */
    private $processor;
    /** @var Deferred|null */
    private $busy;
    /** @var callable Function used to release connection after a transaction has completed. */
    private $release;
    /**
     * @param ConnectionConfig $config
     * @param (CancellationToken | null) $token
     * @param (Socket\Connector | null) $connector
     *
     * @return Promise<self>
     */
    public static function connect(ConnectionConfig $config, ?CancellationToken $token = null, ?Socket\Connector $connector = null) : Promise
    {
        $token = $token ?? new NullCancellationToken();
        return call(function () use($config, $token, $connector) {
            $socket = (yield ($connector ?? Socket\connector())->connect($config->getConnectionString(), $config->getConnectContext(), $token));
            $processor = new Internal\Processor($socket, $config);
            (yield $processor->connect($token));
            return new self($processor);
        });
    }
    /**
     * @param Internal\Processor $processor
     */
    private function __construct(Internal\Processor $processor)
    {
        $this->processor = $processor;
        $this->release = function () {
            \assert($this->busy instanceof Deferred);
            $deferred = $this->busy;
            $this->busy = null;
            $deferred->resolve();
        };
    }
    /**
     * @return bool False if the connection has been closed.
     */
    public function isAlive() : bool
    {
        return $this->processor->isAlive();
    }
    /**
     * @return int Timestamp of the last time this connection was used.
     */
    public function getLastUsedAt() : int
    {
        return $this->processor->getLastUsedAt();
    }
    /**
     *
     */
    public function isReady() : bool
    {
        return $this->processor->isReady();
    }
    /**
     *
     */
    public function setCharset(string $charset, string $collate = "") : Promise
    {
        return $this->processor->setCharset($charset, $collate);
    }
    /**
     *
     */
    public function close()
    {
        $processor = $this->processor;
        // Send close command if connection is not already in a closed or closing state
        if ($processor->isAlive()) {
            $processor->sendClose()->onResolve(static function () use($processor) {
                $processor->close();
            });
        }
    }
    /**
     *
     */
    public function useDb(string $db) : Promise
    {
        return $this->processor->useDb($db);
    }
    /**
     * @param int $subcommand int one of the self::REFRESH_* constants
     *
     * @return Promise
     */
    public function refresh(int $subcommand) : Promise
    {
        return $this->processor->refresh($subcommand);
    }
    /**
     *
     */
    public function query(string $query) : Promise
    {
        return call(function () use($query) {
            while ($this->busy) {
                (yield $this->busy->promise());
            }
            $result = (yield $this->processor->query($query));
            if ($result instanceof Internal\ResultProxy) {
                return new ConnectionResultSet($result);
            }
            if ($result instanceof CommandResult) {
                return $result;
            }
            throw new FailureException("Unrecognized result type");
        });
    }
    /**
     *
     */
    public function beginTransaction(int $isolation = ConnectionTransaction::ISOLATION_COMMITTED) : Promise
    {
        return call(function () use($isolation) {
            switch ($isolation) {
                case ConnectionTransaction::ISOLATION_UNCOMMITTED:
                    (yield $this->query("SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"));
                    break;
                case ConnectionTransaction::ISOLATION_COMMITTED:
                    (yield $this->query("SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED"));
                    break;
                case ConnectionTransaction::ISOLATION_REPEATABLE:
                    (yield $this->query("SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ"));
                    break;
                case ConnectionTransaction::ISOLATION_SERIALIZABLE:
                    (yield $this->query("SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE"));
                    break;
                default:
                    throw new \Error("Invalid transaction type");
            }
            (yield $this->query("START TRANSACTION"));
            $this->busy = new Deferred();
            return new ConnectionTransaction($this->processor, $this->release, $isolation);
        });
    }
    /**
     *
     */
    public function ping() : Promise
    {
        return $this->processor->ping();
    }
    /**
     *
     */
    public function prepare(string $query) : Promise
    {
        return call(function () use($query) {
            while ($this->busy) {
                (yield $this->busy->promise());
            }
            return $this->processor->prepare($query);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        return call(function () use($sql, $params) {
            /** @var Statement $statment */
            $statment = (yield $this->prepare($sql));
            return (yield $statment->execute($params));
        });
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->processor->unreference();
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\ResultSet as SqlResultSet;
interface ResultSet extends SqlResultSet
{
    /**
    * @return Promise<bool> Resolves with true if another result set exists, false if all result sets have
    been consumed.
    */
    public function nextResultSet() : Promise;
    /**
     * @return Promise<mixed[][]>
     *
     * @throws \Error If nextResultSet() has been invoked and no further result sets were available.
     */
    public function getFields() : Promise;
}<?php

namespace Amp\Mysql;

use Amp\Loop;
use Amp\Promise;
use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
use Amp\Sql\Connector;
const LOOP_CONNECTOR_IDENTIFIER = Connector::class . "\\Mysql";
/**
 *
 */
function connector(?Connector $connector = null) : Connector
{
    if ($connector === null) {
        $connector = Loop::getState(LOOP_CONNECTOR_IDENTIFIER);
        if ($connector) {
            return $connector;
        }
        $connector = new CancellableConnector();
    }
    Loop::setState(LOOP_CONNECTOR_IDENTIFIER, $connector);
    return $connector;
}
/**
 * Create a connection using the global Connector instance.
 *
 * @param SqlConnectionConfig $config
 *
 * @return Promise<Connection>
 *
 * @throws \Amp\Sql\FailureException If connecting fails.
 * @throws \Error If the connection string does not contain a host, user, and password.
 */
function connect(SqlConnectionConfig $config) : Promise
{
    return connector()->connect($config);
}
/**
 * Create a pool using the global Connector instance.
 *
 * @param SqlConnectionConfig $config
 * @param int $maxConnections
 * @param int $idleTimeout
 *
 * @return Pool
 *
 * @throws \Error If the connection string does not contain a host, user, and password.
 */
function pool(SqlConnectionConfig $config, int $maxConnections = ConnectionPool::DEFAULT_MAX_CONNECTIONS, int $idleTimeout = ConnectionPool::DEFAULT_IDLE_TIMEOUT) : Pool
{
    return new Pool($config, $maxConnections, $idleTimeout, connector());
}<?php

namespace Amp\Mysql;

use Amp\Sql\Common\PooledTransaction as SqlPooledTransaction;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
final class PooledTransaction extends SqlPooledTransaction
{
    /**
     *
     */
    protected function createStatement(SqlStatement $statement, callable $release) : SqlStatement
    {
        \assert($statement instanceof Statement);
        return new PooledStatement($statement, $release);
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
}<?php

namespace Amp\Mysql;

use Amp\Deferred;
use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use Amp\Success;
use function Amp\asyncCall;
use function Amp\call;
final class ConnectionResultSet implements ResultSet
{
    /** @var Internal\ResultProxy|null */
    private $result;
    /** @var \Amp\Producer */
    private $producer;
    /** @var array|object Last emitted row. */
    private $currentRow;
    /** @var string[]|null */
    private $columnNames;
    /**
     *
     */
    public function __construct(Internal\ResultProxy $result)
    {
        $this->result = $result;
        $this->producer = self::makeIterator($result);
    }
    /**
     *
     */
    private static function makeIterator(Internal\ResultProxy $result) : Iterator
    {
        return new Producer(static function (callable $emit) use($result) {
            $row = (yield self::fetchRow($result));
            while ($row !== null) {
                $next = self::fetchRow($result);
                // Fetch next row while emitting last row.
                (yield $emit($row));
                $row = (yield $next);
            }
        });
    }
    /**
     *
     */
    public function __destruct()
    {
        if (!$this->result) {
            return;
        }
        $producer = $this->producer;
        asyncCall(static function () use($producer) {
            try {
                while ((yield $producer->advance())) {
                }
            } catch (\Throwable $exception) {
                // Ignore iterator failure when destroying.
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        $this->currentRow = null;
        return $this->producer->advance();
    }
    /**
     * {@inheritdoc}
     */
    public function getCurrent() : array
    {
        if ($this->currentRow !== null) {
            return $this->currentRow;
        }
        if (!$this->columnNames) {
            $this->columnNames = \array_column($this->result->columns, "name");
        }
        return $this->currentRow = \array_combine($this->columnNames, $this->producer->getCurrent());
    }
    /**
     *
     */
    private static function fetchRow(Internal\ResultProxy $result) : Promise
    {
        if ($result->userFetched < $result->fetchedRows) {
            $row = $result->rows[$result->userFetched];
            unset($result->rows[$result->userFetched]);
            $result->userFetched++;
            return new Success($row);
        }
        if ($result->state === Internal\ResultProxy::ROWS_FETCHED) {
            return new Success();
        }
        $deferred = new Deferred();
        /* We need to increment the internal counter, else the next time fetch is called,
         * it'll simply return the row we fetch here instead of fetching a new row
         * since callback order on promises isn't defined, we can't do this via onResolve() */
        $incRow = function ($row) use($result) {
            unset($result->rows[$result->userFetched++]);
            return $row;
        };
        $result->deferreds[Internal\ResultProxy::UNFETCHED][] = [$deferred, null, $incRow];
        return $deferred->promise();
    }
    /**
    * @return Promise<bool> Resolves with true if another result set exists, false if all result sets have
    been consumed.
    */
    public function nextResultSet() : Promise
    {
        if (!$this->result) {
            return new Success(false);
        }
        return call(function () {
            while ((yield $this->advance())) {
            }
            // Consume any values left in the current result.
            $this->columnNames = null;
            $deferred = $this->result->next ?: ($this->result->next = new Deferred());
            $this->result = (yield $deferred->promise());
            if ($this->result) {
                $this->producer = self::makeIterator($this->result);
                return true;
            }
            return false;
        });
    }
    /**
     * @return Promise<mixed[][]>
     *
     * @throws \Error If nextResultSet() has been invoked and no further result sets were available.
     */
    public function getFields() : Promise
    {
        if ($this->result === null) {
            throw new \Error("The current result set is empty; call this method before invoking ResultSet::nextResultSet()");
        }
        if ($this->result->state >= Internal\ResultProxy::COLUMNS_FETCHED) {
            return new Success($this->result->columns);
        }
        $deferred = new Deferred();
        $this->result->deferreds[Internal\ResultProxy::COLUMNS_FETCHED][] = [$deferred, &$this->result->columns, null];
        return $deferred->promise();
    }
}<?php

namespace Amp\Mysql;

use Amp\Sql\CommandResult as SqlCommandResult;
final class CommandResult implements SqlCommandResult
{
    /** @var int */
    private $affectedRows;
    /** @var int */
    private $lastInsertId;
    /**
     *
     */
    public function __construct(int $affectedRows, int $lastInsertId)
    {
        $this->affectedRows = $affectedRows;
        $this->lastInsertId = $lastInsertId;
    }
    /**
     * @return int Number of rows affected by the modification query.
     */
    public function getAffectedRowCount() : int
    {
        return $this->affectedRows;
    }
    /**
     * @return int Insert ID of the last auto increment row.
     */
    public function getLastInsertId() : int
    {
        return $this->lastInsertId;
    }
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Statement as SqlStatement;
interface Statement extends SqlStatement
{
    /**
     * @param (int | string) $paramId Parameter ID or name.
     * @param mixed $data Data to bind to parameter.
     *
     * @throws \Error If $paramId is not an int or string, or the position does not exist.
     */
    public function bind($paramId, $data) : void;
    /**
     * @return Promise<array>
     */
    public function getFields() : Promise;
    /**
     * Reset statement to state just after preparing.
     *
     * @return Promise<null>
     */
    public function reset() : Promise;
}<?php

namespace Amp\Mysql;

use Amp\Promise;
use Amp\Sql\Common\PooledResultSet as SqlPooledResultSet;
final class PooledResultSet extends SqlPooledResultSet implements ResultSet
{
    /** @var ConnectionResultSet */
    private $result;
    /** @var callable */
    private $release;
    /** @var Promise|null a*/
    private $nextResultPromise;
    /**
     * @param ResultSet $result
     * @param callable $release
     */
    public function __construct(ResultSet $result, callable $release)
    {
        $this->result = $result;
        $this->release =& $release;
        parent::__construct($this->result, static function () use(&$release) {
            if ($release !== null) {
                $release();
            }
        });
    }
    /**
     *
     */
    public function advance() : Promise
    {
        $promise = $this->result->advance();
        $promise->onResolve(function (\Throwable $exception = null, bool $moreResults = null) {
            if ($moreResults || $this->release === null) {
                return;
            }
            $this->nextResultPromise = $this->result->nextResultSet();
            $this->nextResultPromise->onResolve(function (\Throwable $exception = null, bool $moreResults = null) {
                $this->nextResultPromise = null;
                if ($moreResults || $this->release === null) {
                    return;
                }
                $release = $this->release;
                $this->release = null;
                $release();
            });
        });
        return $promise;
    }
    /**
     *
     */
    public function nextResultSet() : Promise
    {
        if ($this->nextResultPromise !== null) {
            $nextResultPromise = $this->nextResultPromise;
            $this->nextResultPromise = null;
            return $nextResultPromise;
        }
        $promise = $this->result->nextResultSet();
        $promise->onResolve(function (\Throwable $exception = null, bool $moreResults = null) {
            if ($moreResults || $this->release === null) {
                return;
            }
            $release = $this->release;
            $this->release = null;
            $release();
        });
        return $promise;
    }
    /**
     *
     */
    public function getFields() : Promise
    {
        return $this->result->getFields();
    }
}<?php

namespace Amp\Mysql;

final class RefreshTypes
{
    const REFRESH_GRANT = 0x1;
    const REFRESH_LOG = 0x2;
    const REFRESH_TABLES = 0x4;
    const REFRESH_HOSTS = 0x8;
    const REFRESH_STATUS = 0x10;
    const REFRESH_THREADS = 0x20;
    const REFRESH_SLAVE = 0x40;
    const REFRESH_MASTER = 0x80;
}<?php

namespace Amp\Mysql\Bench;

class AbstractBench
{
    /** @var string */
    protected $host = '127.0.0.1';
    /** @var string */
    protected $user = 'root';
    /** @var string */
    protected $pass = '';
}<?php

namespace Amp\Mysql\Bench;

use Amp\Mysql\CancellableConnector;
use Amp\Mysql\Connection;
use Amp\Mysql\ConnectionConfig;
use Amp\Mysql\Pool as ConnectionPool;
use Amp\Mysql\ResultSet;
use function Amp\call;
use function Amp\Promise\wait;
/**
 * @BeforeMethods({"init"})
 * @AfterMethods({"onAfterMethods"})
 * @Iterations(1)
 * @Revs(100)
 * @Warmup(1)
 * @OutputTimeUnit("milliseconds", precision=5)
 */
class QueryBench extends AbstractBench
{
    /** @var  ConnectionPool */
    protected $connectionPool;
    /** @var  Connection */
    protected $connection;
    /** @var  \PDO */
    protected $pdoConnection;
    /** @var int */
    protected $maxQueries = 10;
    /** @var int */
    protected $poolLimit = 10;
    /**
     *
     */
    public function init()
    {
        $config = ConnectionConfig::fromString("host={$this->host};user={$this->user};pass={$this->pass}");
        $connector = new CancellableConnector();
        $this->connectionPool = new ConnectionPool($config, $this->poolLimit, 10, $connector);
        $connectionPromise = $connector->connect($config);
        $this->connection = wait($connectionPromise);
        $this->pdoConnection = new \PDO("mysql:host={$this->host};port=3306", $this->user, $this->pass);
    }
    /**
     *
     */
    public function onAfterMethods()
    {
        $this->connectionPool->close();
        $this->connection->close();
    }
    /**
     *
     */
    public function benchPdoQueries()
    {
        foreach (\range(1, $this->maxQueries) as $ii) {
            $resultSet = $this->pdoConnection->query("SELECT {$ii}");
            $resultSet->fetch(\PDO::FETCH_ASSOC);
        }
    }
    /**
     *
     */
    public function benchSyncQueries()
    {
        wait(call(function () {
            $connection = $this->connection;
            foreach (\range(1, $this->maxQueries) as $i) {
                /** @var ResultSet $resultSet */
                $resultSet = (yield $connection->query("SELECT {$i}"));
                (yield $resultSet->advance());
            }
        }));
    }
    /**
     *
     */
    public function benchAsyncQueries()
    {
        wait(call(function () {
            $connection = $this->connection;
            /** @var ResultSet[] $resultSets */
            $resultSets = (yield \array_map(function ($i) use($connection) {
                return $connection->query("SELECT {$i}");
            }, \range(1, $this->maxQueries)));
            (yield \array_map(function ($resultSet) {
                /** @var ResultSet $resultSet */
                return $resultSet->advance();
            }, $resultSets));
        }));
    }
    /**
     *
     */
    public function benchAsyncQueriesUsingPool()
    {
        wait(call(function () {
            $connection = $this->connectionPool;
            /** @var ResultSet[] $resultSets */
            $resultSets = (yield \array_map(function ($i) use($connection) {
                return $connection->query("SELECT {$i}");
            }, \range(1, $this->maxQueries)));
            (yield \array_map(function ($resultSet) {
                /** @var ResultSet $resultSet */
                return $resultSet->advance();
            }, $resultSets));
        }));
    }
}<?php

require 'support/bootstrap.php';
require 'support/generic-table.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /* create same table than in 3-generic-with-yield.php */
    yield from createGenericTable($db);
    $promises = [];
    $promises[] = $db->query("SELECT a * b FROM tmp");
    $promises[] = $db->execute("SELECT POW(a, ?) AS power FROM tmp", [2]);
    /**
     * @var Mysql\ResultSet $result1
     * @var Mysql\ResultSet $result2
     */
    list($result1, $result2) = (yield $promises);
    // Both queries execute simultaneously. Wait for both to finish here.
    print "Query 1 Results:" . PHP_EOL;
    while ((yield $result1->advance())) {
        \var_dump($result1->getCurrent());
    }
    print PHP_EOL . "Query 2 Results:" . PHP_EOL;
    while ((yield $result2->advance())) {
        \var_dump($result2->getCurrent());
    }
    (yield $db->query("DROP TABLE tmp"));
    $db->close();
});<?php

/* Create table and fill in a few rows for examples; for comments see 3-generic-with-yield.php */
/**
 *
 */
function createGenericTable(\Amp\Sql\Link $db) : Generator
{
    (yield $db->query("DROP TABLE IF EXISTS tmp"));
    (yield $db->query("CREATE TABLE tmp (a INT(10), b INT(10))"));
    $statement = (yield $db->prepare("INSERT INTO tmp (a, b) VALUES (?, ? * 2)"));
    $promises = [];
    foreach (\range(1, 5) as $num) {
        $promises[] = $statement->execute([$num, $num]);
    }
    return (yield $promises);
}<?php

require __DIR__ . '/../../vendor/autoload.php';
//define('MYSQL_DEBUG', true);
/*
 * This file is not in VCS - create it if you want to set
 * the DB credentials without having them commited to VCS.
 */
@(include_once __DIR__ . "/../../mysql-config.php");
if (!\defined('DB_HOST') || !\defined('DB_USER') || !\defined('DB_PASS') || !\defined('DB_NAME')) {
    print "We couldn't find a mysql-config.php." . PHP_EOL;
    ask_whether_config_should_be_created:
    print "Do you want to create a configuration to run the examples? (yes/no): ";
    $answer = \trim(\fgets(STDIN));
    if ($answer === "no") {
        print "Can't run any examples without valid database credentials." . PHP_EOL;
        exit(1);
    } elseif ($answer === "yes") {
        print "Database host: ";
        $host = \var_export(\trim(\fgets(STDIN)), true);
        print "Database user: ";
        $user = \var_export(\trim(\fgets(STDIN)), true);
        print "Database password: ";
        $pass = \var_export(\trim(\fgets(STDIN)), true);
        print "Database name: ";
        $name = \var_export(\trim(\fgets(STDIN)), true);
        $config = <<<CONFIG
<?php

const DB_HOST = {$host};
const DB_USER = {$user};
const DB_PASS = {$pass};
const DB_NAME = {$name};

CONFIG;
        \file_put_contents(__DIR__ . "/../../mysql-config.php", $config);
        require __DIR__ . "/../../mysql-config.php";
        print "Successfully created configuration, running example now." . PHP_EOL;
        print "You can find the config in " . \realpath(__DIR__ . "/../../mysql-config.php") . PHP_EOL;
        print \str_repeat("-", 80) . PHP_EOL;
    } else {
        goto ask_whether_config_should_be_created;
    }
}<?php

require 'support/bootstrap.php';
require 'support/generic-table.php';
use Amp\Mysql;
\Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /* create same table than in 3-generic-with-yield.php */
    yield from createGenericTable($db);
    /* multi statements are enabled by default, but generally stored procedures also might return multiple resultsets anyway */
    $result = (yield $db->query("SELECT a + b FROM tmp; SELECT a - b FROM tmp;"));
    $i = 0;
    /** @var Mysql\ResultSet $result */
    do {
        print PHP_EOL . "Query " . ++$i . " Results:" . PHP_EOL;
        while ((yield $result->advance())) {
            \var_dump($result->getCurrent());
        }
    } while ((yield $result->nextResultSet()));
    // Advances to the next result set.
    (yield $db->query("DROP TABLE tmp"));
    $db->close();
});<?php

require 'support/bootstrap.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /* Create table and insert a few rows */
    /* we need to wait until table is finished, so that we can insert. */
    (yield $db->query("CREATE TABLE IF NOT EXISTS tmp (a INT(10), b INT(10))"));
    print "Table successfully created." . PHP_EOL;
    /** @var Mysql\Statement $statement */
    $statement = (yield $db->prepare("INSERT INTO tmp (a, b) VALUES (?, ? * 2)"));
    $promises = [];
    foreach (\range(1, 5) as $num) {
        $promises[] = $statement->execute([$num, $num]);
    }
    /* wait until everything is inserted */
    (yield $promises);
    print "Insertion successful (if it wasn't, an exception would have been thrown by now)" . PHP_EOL;
    /** @var Mysql\ResultSet $result */
    $result = (yield $db->query("SELECT a, b FROM tmp"));
    while ((yield $result->advance())) {
        \var_dump($result->getCurrent());
    }
    (yield $db->query("DROP TABLE tmp"));
    $db->close();
});<?php

/*
 * Generic example for establishing a connection
 */
require 'support/bootstrap.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    /* If you want ssl, pass as second argument an array with ssl options (an empty options array is valid too); if null is passed, ssl is not enabled either */
    $config = Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME);
    /* use an alternative charset... Default is utf8mb4_general_ci */
    $config = $config->withCharset("latin1_general_ci");
    /** @var Mysql\Connection $db */
    $db = (yield Mysql\connect($config));
    echo "Character set changed\n";
    /* optional, as connection will automatically close when destructed. */
    $db->close();
});<?php

require 'support/bootstrap.php';
require 'support/generic-table.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /* create same table than in 3-generic-with-yield.php */
    yield from createGenericTable($db);
    /** @var \Amp\Sql\Transaction $transaction */
    $transaction = (yield $db->beginTransaction());
    (yield $transaction->execute("INSERT INTO tmp VALUES (?, ? * 2)", [6, 6]));
    /** @var Mysql\ResultSet $result */
    $result = (yield $transaction->execute("SELECT * FROM tmp WHERE a >= ?", [5]));
    // Two rows should be returned.
    while ((yield $result->advance())) {
        \var_dump($result->getCurrent());
    }
    (yield $transaction->rollback());
    // Run same query again, should only return a single row since the other was rolled back.
    $result = (yield $db->execute("SELECT * FROM tmp WHERE a >= ?", [5]));
    while ((yield $result->advance())) {
        \var_dump($result->getCurrent());
    }
    $db->close();
});<?php

require 'support/bootstrap.php';
use Amp\Mysql;
Amp\Loop::run(function () {
    $db = Mysql\pool(Mysql\ConnectionConfig::fromString("host=" . DB_HOST . ";user=" . DB_USER . ";pass=" . DB_PASS . ";db=" . DB_NAME));
    /** @var Mysql\ResultSet $result */
    $result = (yield $db->query("SELECT 1 AS value"));
    while ((yield $result->advance())) {
        $row = $result->getCurrent();
        \var_dump($row['value']);
    }
    $db->close();
});{
    "bootstrap": "vendor/autoload.php",
    "path": "benchmarks",
    "php_binary": "php_no_xdebug"
}
{
    "name": "amphp/mysql",
    "description": "Asynchronous MySQL client for PHP based on Amp.",
    "license": "MIT",
    "authors": [
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/socket": "^1",
        "amphp/sql": "^1",
        "amphp/sql-common": "^1"
    },
    "require-dev": {
        "ext-openssl": "*",
        "amphp/process": "^1",
        "amphp/file": "^2 || ^1 || ^0.3.5",
        "phpunit/phpunit": "^9 || ^8 || ^7",
        "amphp/phpunit-util": "^1.1.2",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpbench/phpbench": "^0.13.0"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Mysql\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Mysql\\Test\\": "test",
            "Amp\\Mysql\\Bench\\": "benchmarks"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit"
    }
}
<?php

namespace Amp\File\Sync;

use Amp\Coroutine;
use Amp\Delayed;
use Amp\File\FilesystemException;
use Amp\Promise;
use Amp\Sync\Lock;
use Amp\Sync\Mutex;
use Amp\Sync\SyncException;
use function Amp\File\deleteFile;
use function Amp\File\openFile;
final class AsyncFileMutex implements Mutex
{
    private const LATENCY_TIMEOUT = 10;
    /** @var string The full path to the lock file. */
    private $fileName;
    /**
     * @param string $fileName Name of temporary file to use as a mutex.
     */
    public function __construct(string $fileName)
    {
        $this->fileName = $fileName;
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return new Coroutine($this->doAcquire());
    }
    /**
     * @coroutine
     *
     * @return \Generator
     */
    private function doAcquire() : \Generator
    {
        // Try to create the lock file. If the file already exists, someone else
        // has the lock, so set an asynchronous timer and try again.
        while (true) {
            try {
                $file = (yield openFile($this->fileName, 'x'));
                break;
            } catch (FilesystemException $exception) {
                (yield new Delayed(self::LATENCY_TIMEOUT));
            }
        }
        // Return a lock object that can be used to release the lock on the mutex.
        $lock = new Lock(0, function () : void {
            $this->release();
        });
        (yield $file->close());
        return $lock;
    }
    /**
     * Releases the lock on the mutex.
     */
    private function release() : void
    {
        deleteFile($this->fileName)->onResolve(function (?\Throwable $exception) : void {
            if ($exception !== null) {
                throw new SyncException('Failed to unlock the mutex file: ' . $this->fileName, 0, $exception);
            }
        });
    }
}<?php

namespace Amp\File;

use Amp\Promise;
interface Driver
{
    /**
     * Open a handle for the specified path.
     *
     * @param string $path
     * @param string $mode
     *
     * @return Promise<File>
     */
    public function openFile(string $path, string $mode) : Promise;
    /**
     * Get file status; also known as stat operation.
     *
     * If the requested path does not exist the resulting Promise will resolve to NULL.
     *
     * @param string $path The file system path to stat.
     *
     * @return Promise<(array | null)>
     */
    public function getStatus(string $path) : Promise;
    /**
     * Same as {@see Driver::getStatus()} except if the path is a link then the link's data is returned.
     *
     * If the requested path does not exist the resulting Promise will resolve to NULL.
     *
     * @param string $path The file system path to stat.
     *
     * @return Promise<(array | null)> A promise resolving to an associative array upon successful resolution.
     */
    public function getLinkStatus(string $path) : Promise;
    /**
     * Create a symlink $link pointing to the file/directory located at $target.
     *
     * @param string $target
     * @param string $link
     *
     * @return Promise<void>
     */
    public function createSymlink(string $target, string $link) : Promise;
    /**
     * Create a hard link $link pointing to the file/directory located at $target.
     *
     * @param string $target
     * @param string $link
     *
     * @return Promise<void>
     */
    public function createHardlink(string $target, string $link) : Promise;
    /**
     * Resolve the symlink at $path.
     *
     * @param string $target
     *
     * @return Promise<string>
     */
    public function resolveSymlink(string $target) : Promise;
    /**
     * Move / rename a file or directory.
     *
     * @param string $from
     * @param string $to
     *
     * @return Promise<void>
     */
    public function move(string $from, string $to) : Promise;
    /**
     * Delete a file.
     *
     * @param string $path
     *
     * @return Promise<void>
     */
    public function deleteFile(string $path) : Promise;
    /**
     * Create a directory.
     *
     * @param string $path
     * @param int $mode
     *
     * @return Promise<void>
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise;
    /**
     * Create a directory recursively.
     *
     * @param string $path
     * @param int $mode
     *
     * @return Promise<void>
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise;
    /**
     * Delete a directory.
     *
     * @param string $path
     *
     * @return Promise<void>
     */
    public function deleteDirectory(string $path) : Promise;
    /**
     * Retrieve an array of files and directories inside the specified path.
     *
     * Dot entries are not included in the resulting array (i.e. "." and "..").
     *
     * @param string $path
     *
     * @return Promise<list<string>>
     */
    public function listFiles(string $path) : Promise;
    /**
     * chmod a file or directory.
     *
     * @param string $path
     * @param int $mode
     *
     * @return Promise<void>
     */
    public function changePermissions(string $path, int $mode) : Promise;
    /**
     * chown a file or directory.
     *
     * @param string $path
     * @param (int | null) $uid
     * @param (int | null) $gid
     *
     * @return Promise<void>
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise;
    /**
    * Update the access and modification time of the specified path.
    *
    * If the file does not exist it will be created automatically.
    *
    * @param string $path
    * @param (int | null) $modificationTime The touch time. If $time is not supplied, the current system time is used.
    * @param (int | null) $accessTime The access time. If $atime is not supplied, value passed to the $time parameter is
    used.
    *
    * @return Promise<void>
    */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise;
    /**
     * Buffer the specified file's contents.
     *
     * @param string $path The file path from which to buffer contents.
     *
     * @return Promise<string> A promise resolving to a string upon successful resolution.
     */
    public function read(string $path) : Promise;
    /**
     * Write the contents string to the specified path.
     *
     * @param string $path The file path to which to $contents should be written.
     * @param string $contents The data to write to the specified $path.
     *
     * @return Promise<void>
     */
    public function write(string $path, string $contents) : Promise;
}<?php

namespace Amp\File\Internal;

use Amp\File\Driver\BlockingDriver;
use Amp\File\Driver\BlockingFile;
use Amp\File\FilesystemException;
use Amp\Parallel\Worker\Environment;
use Amp\Parallel\Worker\Task;
/**
 * @codeCoverageIgnore
 *
 * @internal
 */
final class FileTask implements Task
{
    private const ENV_PREFIX = "amphp/file#";
    /**
     *
     */
    private static function makeId(int $id) : string
    {
        return self::ENV_PREFIX . $id;
    }
    /** @var string */
    private $operation;
    /** @var mixed[] */
    private $args;
    /**  @var string|null */
    private $id;
    /**
     * @param string $operation
     * @param array $args
     * @param int $id File ID.
     *
     * @throws \Error
     */
    public function __construct(string $operation, array $args = [], int $id = null)
    {
        if ($operation === '') {
            throw new \Error('Operation must be a non-empty string');
        }
        $this->operation = $operation;
        $this->args = $args;
        $this->id = $id;
    }
    /**
     *
     */
    public function run(Environment $environment)
    {
        if ('f' === $this->operation[0]) {
            if ("fopen" === $this->operation) {
                $path = $this->args[0];
                $mode = \str_replace(['b', 't', 'e'], '', $this->args[1]);
                switch ($mode) {
                    case "r":
                    case "r+":
                    case "w":
                    case "w+":
                    case "a":
                    case "a+":
                    case "x":
                    case "x+":
                    case "c":
                    case "c+":
                        break;
                    default:
                        throw new \Error("Invalid file mode");
                }
                $handle = @\fopen($path, $mode . 'be');
                if (!$handle) {
                    $message = 'Could not open the file.';
                    if ($error = \error_get_last()) {
                        $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
                    }
                    throw new FilesystemException($message);
                }
                $file = new BlockingFile($handle, $path, $mode);
                $id = (int) $handle;
                $size = \fstat($handle)["size"];
                $environment->set(self::makeId($id), $file);
                return [$id, $size, $mode];
            }
            if ($this->id === null) {
                throw new FilesystemException("No file ID provided");
            }
            $id = self::makeId($this->id);
            if (!$environment->exists($id)) {
                throw new FilesystemException(\sprintf("No file handle with the ID %d has been opened on the worker", $this->id));
            }
            /** @var BlockingFile $file */
            if (!($file = $environment->get($id)) instanceof BlockingFile) {
                throw new FilesystemException("File storage found in inconsistent state");
            }
            switch ($this->operation) {
                case "fread":
                case "fwrite":
                case "fseek":
                case "ftruncate":
                    return [$file, \Phabel\Target\Php80\Polyfill::substr($this->operation, 1)](...$this->args);
                case "fclose":
                    $environment->delete($id);
                    $file->close();
                    return null;
                default:
                    throw new \Error('Invalid operation');
            }
        }
        switch ($this->operation) {
            case "getStatus":
            case "deleteFile":
            case "move":
            case "createHardlink":
            case "createSymlink":
            case "resolveSymlink":
            case "getLinkStatus":
            case "exists":
            case "createDirectory":
            case "createDirectoryRecursively":
            case "listFiles":
            case "deleteDirectory":
            case "changePermissions":
            case "changeOwner":
            case "touch":
            case "read":
            case "write":
                return [new BlockingDriver(), $this->operation](...$this->args);
            default:
                throw new \Error("Invalid operation");
        }
    }
}<?php

namespace Amp\File\Internal;

use Amp\Loop;
use Amp\Promise;
/** @internal */
final class EioPoll
{
    /** @var resource */
    private static $stream;
    /** @var string */
    private $watcher;
    /** @var int */
    private $requests = 0;
    /** @var Loop\Driver */
    private $driver;
    /**
     *
     */
    public function __construct(Loop\Driver $driver)
    {
        $this->driver = $driver;
        if (!self::$stream) {
            if (\function_exists('eio_init')) {
                \eio_init();
            }
            self::$stream = \eio_get_event_stream();
        }
        $this->watcher = $this->driver->onReadable(self::$stream, static function () : void {
            while (\eio_npending()) {
                \eio_poll();
            }
        });
        $this->driver->disable($this->watcher);
        $this->driver->setState(self::class, new class($this->watcher, $driver)
        {
            private $watcher;
            private $driver;
            /**
             *
             */
            public function __construct(string $watcher, Loop\Driver $driver)
            {
                $this->watcher = $watcher;
                $this->driver = $driver;
            }
            /**
             *
             */
            public function __destruct()
            {
                $this->driver->cancel($this->watcher);
                // Ensure there are no active operations anymore. This is a safe-guard as some operations might not be
                // finished on loop exit due to not being yielded. This also ensures a clean shutdown for these if PHP
                // exists.
                \eio_event_loop();
            }
        });
    }
    /**
     *
     */
    public function listen(Promise $promise) : void
    {
        if ($this->requests++ === 0) {
            $this->driver->enable($this->watcher);
        }
        $promise->onResolve(\Closure::fromCallable([$this, 'done']));
    }
    /**
     *
     */
    private function done() : void
    {
        if (--$this->requests === 0) {
            $this->driver->disable($this->watcher);
        }
        \assert($this->requests >= 0);
    }
}<?php

namespace Amp\File\Internal;

use Amp\Loop\UvDriver;
use Amp\Promise;
/** @internal */
final class UvPoll
{
    /** @var string */
    private $watcher;
    /** @var int */
    private $requests = 0;
    /** @var UvDriver */
    private $driver;
    /**
     *
     */
    public function __construct(UvDriver $driver)
    {
        $this->driver = $driver;
        $this->watcher = $this->driver->repeat(\PHP_INT_MAX / 2, static function () : void {
            // do nothing, it's a dummy watcher
        });
        $this->driver->disable($this->watcher);
        $this->driver->setState(self::class, new class($this->watcher, $driver)
        {
            private $watcher;
            private $driver;
            /**
             *
             */
            public function __construct(string $watcher, UvDriver $driver)
            {
                $this->watcher = $watcher;
                $this->driver = $driver;
            }
            /**
             *
             */
            public function __destruct()
            {
                $this->driver->cancel($this->watcher);
            }
        });
    }
    /**
     *
     */
    public function listen(Promise $promise) : void
    {
        if ($this->requests++ === 0) {
            $this->driver->enable($this->watcher);
        }
        $promise->onResolve(\Closure::fromCallable([$this, 'done']));
    }
    /**
     *
     */
    private function done() : void
    {
        if (--$this->requests === 0) {
            $this->driver->disable($this->watcher);
        }
        \assert($this->requests >= 0);
    }
}<?php

namespace Amp\File\Internal;

use Amp\Loop;
use Amp\Struct;
/** @internal */
final class Cache
{
    /** @var object */
    private $sharedState;
    /** @var string */
    private $ttlWatcherId;
    /** @var int|null */
    private $maxSize;
    /**
    * @param int $gcInterval The frequency in milliseconds at which expired cache entries should be garbage
    collected.
    * @param (int | null) $maxSize The maximum size of cache array (number of elements).
    */
    public function __construct(int $gcInterval = 1000, int $maxSize = null)
    {
        // By using a shared state object we're able to use `__destruct()` for "normal" garbage collection of both this
        // instance and the loop's watcher. Otherwise this object could only be GC'd when the TTL watcher was cancelled
        // at the loop layer.
        $this->sharedState = $sharedState = new class
        {
            use Struct;
            /** @var string[] */
            public $cache = [];
            /** @var int[] */
            public $cacheTimeouts = [];
            /** @var bool */
            public $isSortNeeded = false;
            /**
             *
             */
            public function collectGarbage() : void
            {
                $now = \time();
                if ($this->isSortNeeded) {
                    \asort($this->cacheTimeouts);
                    $this->isSortNeeded = false;
                }
                foreach ($this->cacheTimeouts as $key => $expiry) {
                    if ($now <= $expiry) {
                        break;
                    }
                    unset($this->cache[$key], $this->cacheTimeouts[$key]);
                }
            }
        };
        $this->ttlWatcherId = Loop::repeat($gcInterval, [$sharedState, "collectGarbage"]);
        $this->maxSize = $maxSize;
        Loop::unreference($this->ttlWatcherId);
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->sharedState->cache = [];
        $this->sharedState->cacheTimeouts = [];
        Loop::cancel($this->ttlWatcherId);
    }
    /**
     *
     */
    public function get(string $key)
    {
        if (!isset($this->sharedState->cache[$key])) {
            return null;
        }
        if (isset($this->sharedState->cacheTimeouts[$key]) && \time() > $this->sharedState->cacheTimeouts[$key]) {
            unset($this->sharedState->cache[$key], $this->sharedState->cacheTimeouts[$key]);
            return null;
        }
        return $this->sharedState->cache[$key];
    }
    /**
     *
     */
    public function set(string $key, $value, int $ttl = null) : void
    {
        if ($ttl === null) {
            unset($this->sharedState->cacheTimeouts[$key]);
        } elseif ($ttl >= 0) {
            $expiry = \time() + $ttl;
            $this->sharedState->cacheTimeouts[$key] = $expiry;
            $this->sharedState->isSortNeeded = true;
        } else {
            throw new \Error("Invalid cache TTL ({$ttl}; integer >= 0 or null required");
        }
        unset($this->sharedState->cache[$key]);
        if (\count($this->sharedState->cache) === $this->maxSize) {
            \array_shift($this->sharedState->cache);
        }
        $this->sharedState->cache[$key] = $value;
    }
    /**
     *
     */
    public function delete(string $key) : bool
    {
        $exists = isset($this->sharedState->cache[$key]);
        unset($this->sharedState->cache[$key], $this->sharedState->cacheTimeouts[$key]);
        return $exists;
    }
}<?php

namespace Amp\File\Driver;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\StreamException;
use Amp\Failure;
use Amp\File\File;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class BlockingFile implements File
{
    private $handle;
    private $path;
    private $mode;
    /**
     * @param resource $handle An open filesystem descriptor.
     * @param string $path File path.
     * @param string $mode File open mode.
     */
    public function __construct($handle, string $path, string $mode)
    {
        $this->handle = $handle;
        $this->path = $path;
        $this->mode = $mode;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->handle !== null) {
            @\fclose($this->handle);
        }
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        if ($this->handle === null) {
            return new Failure(new ClosedException("The file '{$this->path}' has been closed"));
        }
        try {
            \set_error_handler(function ($type, $message) {
                throw new StreamException("Failed reading from file '{$this->path}': {$message}");
            });
            $data = \fread($this->handle, $length);
            if ($data === false) {
                throw new StreamException("Failed reading from file '{$this->path}'");
            }
            return new Success($data !== '' ? $data : null);
        } catch (StreamException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->handle === null) {
            return new Failure(new ClosedException("The file '{$this->path}' has been closed"));
        }
        try {
            \set_error_handler(function ($type, $message) {
                throw new StreamException("Failed writing to file '{$this->path}': {$message}");
            });
            $length = \fwrite($this->handle, $data);
            if ($length === false) {
                throw new StreamException("Failed writing to file '{$this->path}'");
            }
            return new Success();
        } catch (StreamException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return call(function () use($data) {
            $promise = $this->write($data);
            // ignore any errors
            (yield Promise\any([$this->close()]));
            return $promise;
        });
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->handle === null) {
            return new Success();
        }
        $handle = $this->handle;
        $this->handle = null;
        try {
            \set_error_handler(function ($type, $message) {
                throw new StreamException("Failed closing file '{$this->path}': {$message}");
            });
            if (\fclose($handle)) {
                return new Success();
            }
            throw new StreamException("Failed closing file '{$this->path}'");
        } catch (StreamException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        if ($this->handle === null) {
            return new Failure(new ClosedException("The file '{$this->path}' has been closed"));
        }
        try {
            \set_error_handler(function ($type, $message) {
                throw new StreamException("Could not truncate file '{$this->path}': {$message}");
            });
            if (!\ftruncate($this->handle, $size)) {
                throw new StreamException("Could not truncate file '{$this->path}'");
            }
            return new Success();
        } catch (StreamException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function seek(int $position, int $whence = self::SEEK_SET) : Promise
    {
        if ($this->handle === null) {
            return new Failure(new ClosedException("The file '{$this->path}' has been closed"));
        }
        switch ($whence) {
            case self::SEEK_SET:
            case self::SEEK_CUR:
            case self::SEEK_END:
                try {
                    \set_error_handler(function ($type, $message) {
                        throw new StreamException("Could not seek in file '{$this->path}': {$message}");
                    });
                    if (\fseek($this->handle, $position, $whence) === -1) {
                        throw new StreamException("Could not seek in file '{$this->path}'");
                    }
                    return new Success($this->tell());
                } catch (StreamException $e) {
                    return new Failure($e);
                } finally {
                    \restore_error_handler();
                }
            default:
                throw new \Error("Invalid whence parameter; SEEK_SET, SEEK_CUR or SEEK_END expected");
        }
    }
    /**
     *
     */
    public function tell() : int
    {
        if ($this->handle === null) {
            throw new ClosedException("The file '{$this->path}' has been closed");
        }
        return \ftell($this->handle);
    }
    /**
     *
     */
    public function eof() : bool
    {
        if ($this->handle === null) {
            throw new ClosedException("The file '{$this->path}' has been closed");
        }
        return \feof($this->handle);
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->mode;
    }
}<?php

namespace Amp\File\Driver;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\StreamException;
use Amp\Failure;
use Amp\File\File;
use Amp\File\Internal;
use Amp\File\PendingOperationError;
use Amp\Parallel\Worker\TaskException;
use Amp\Parallel\Worker\Worker;
use Amp\Parallel\Worker\WorkerException;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class ParallelFile implements File
{
    /** @var Worker */
    private $worker;
    /** @var int|null */
    private $id;
    /** @var string */
    private $path;
    /** @var int */
    private $position;
    /** @var int */
    private $size;
    /** @var string */
    private $mode;
    /** @var bool True if an operation is pending. */
    private $busy = false;
    /** @var int Number of pending write operations. */
    private $pendingWrites = 0;
    /** @var bool */
    private $writable = true;
    /** @var Promise|null */
    private $closing;
    /**
     * @param Worker $worker
     * @param int $id
     * @param string $path
     * @param int $size
     * @param string $mode
     */
    public function __construct(Worker $worker, int $id, string $path, int $size, string $mode)
    {
        $this->worker = $worker;
        $this->id = $id;
        $this->path = $path;
        $this->size = $size;
        $this->mode = $mode;
        $this->position = $this->mode[0] === 'a' ? $this->size : 0;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->id !== null) {
            $this->close();
        }
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->closing) {
            return $this->closing;
        }
        $this->writable = false;
        if ($this->worker->isRunning()) {
            $this->closing = $this->worker->enqueue(new Internal\FileTask('fclose', [], $this->id));
            $this->id = null;
        } else {
            $this->closing = new Success();
        }
        return $this->closing;
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        if ($this->id === null) {
            return new Failure(new ClosedException("The file has been closed"));
        }
        if ($this->busy) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        return call(function () use($size) {
            ++$this->pendingWrites;
            $this->busy = true;
            try {
                (yield $this->worker->enqueue(new Internal\FileTask('ftruncate', [$size], $this->id)));
            } catch (TaskException $exception) {
                throw new StreamException("Reading from the file failed", 0, $exception);
            } catch (WorkerException $exception) {
                throw new StreamException("Sending the task to the worker failed", 0, $exception);
            } finally {
                if (--$this->pendingWrites === 0) {
                    $this->busy = false;
                }
            }
        });
    }
    /**
     *
     */
    public function eof() : bool
    {
        return $this->pendingWrites === 0 && $this->size <= $this->position;
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        if ($this->id === null) {
            return new Failure(new ClosedException("The file has been closed"));
        }
        if ($this->busy) {
            throw new PendingOperationError();
        }
        return call(function () use($length) {
            $this->busy = true;
            try {
                $data = (yield $this->worker->enqueue(new Internal\FileTask('fread', [$length], $this->id)));
                if ($data !== null) {
                    $this->position += \strlen($data);
                }
            } catch (TaskException $exception) {
                throw new StreamException("Reading from the file failed", 0, $exception);
            } catch (WorkerException $exception) {
                throw new StreamException("Sending the task to the worker failed", 0, $exception);
            } finally {
                $this->busy = false;
            }
            return $data;
        });
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->id === null) {
            return new Failure(new ClosedException("The file has been closed"));
        }
        if ($this->busy && $this->pendingWrites === 0) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        return call(function () use($data) {
            ++$this->pendingWrites;
            $this->busy = true;
            try {
                (yield $this->worker->enqueue(new Internal\FileTask('fwrite', [$data], $this->id)));
                $this->position += \strlen($data);
            } catch (TaskException $exception) {
                throw new StreamException("Writing to the file failed", 0, $exception);
            } catch (WorkerException $exception) {
                throw new StreamException("Sending the task to the worker failed", 0, $exception);
            } finally {
                if (--$this->pendingWrites === 0) {
                    $this->busy = false;
                }
            }
        });
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return call(function () use($data) {
            $promise = $this->write($data);
            $this->writable = false;
            // ignore any errors
            (yield Promise\any([$this->close()]));
            return $promise;
        });
    }
    /**
     *
     */
    public function seek(int $offset, int $whence = SEEK_SET) : Promise
    {
        if ($this->id === null) {
            return new Failure(new ClosedException("The file has been closed"));
        }
        if ($this->busy) {
            throw new PendingOperationError();
        }
        return call(function () use($offset, $whence) {
            switch ($whence) {
                case self::SEEK_SET:
                case self::SEEK_CUR:
                case self::SEEK_END:
                    try {
                        $this->position = (yield $this->worker->enqueue(new Internal\FileTask('fseek', [$offset, $whence], $this->id)));
                        if ($this->position > $this->size) {
                            $this->size = $this->position;
                        }
                        return $this->position;
                    } catch (TaskException $exception) {
                        throw new StreamException('Seeking in the file failed.', 0, $exception);
                    } catch (WorkerException $exception) {
                        throw new StreamException("Sending the task to the worker failed", 0, $exception);
                    }
                default:
                    throw new \Error('Invalid whence value. Use SEEK_SET, SEEK_CUR, or SEEK_END.');
            }
        });
    }
    /**
     *
     */
    public function tell() : int
    {
        return $this->position;
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->mode;
    }
}<?php

namespace Amp\File\Driver;

use Amp\Deferred;
use Amp\File\Driver;
use Amp\File\FilesystemException;
use Amp\File\Internal;
use Amp\Loop;
use Amp\Promise;
final class EioDriver implements Driver
{
    /**
     * @return bool Determines if this driver can be used based on the environment.
     */
    public static function isSupported() : bool
    {
        return \extension_loaded('eio');
    }
    /** @var Internal\EioPoll */
    private $poll;
    /**
     *
     */
    public function __construct(Loop\Driver $driver)
    {
        $this->poll = new Internal\EioPoll($driver);
    }
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        $flags = \EIO_O_NONBLOCK | $this->parseMode($mode);
        if (\defined('\\EIO_O_FSYNC')) {
            $flags |= \EIO_O_FSYNC;
        }
        $chmod = $flags & \EIO_O_CREAT ? 0644 : 0;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $openArr = [$mode, $path, $deferred];
        \eio_open($path, $flags, $chmod, \EIO_PRI_DEFAULT, [$this, "onOpenHandle"], $openArr);
        return $deferred->promise();
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        $data = [$deferred, $path];
        \eio_stat($path, $priority, [$this, "onStat"], $data);
        return $deferred->promise();
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_lstat($path, $priority, [$this, "onLstat"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_symlink($target, $link, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_link($target, $link, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function resolveSymlink(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_readlink($path, $priority, [$this, "onReadlink"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_rename($from, $to, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        $data = [$deferred, $path];
        $result = \eio_unlink($path, $priority, [$this, "onUnlink"], $data);
        // For a non-existent file eio_unlink immediately returns true and the callback is never called.
        if ($result === true) {
            $deferred->fail(new FilesystemException('File does not exist.'));
        }
        return $deferred->promise();
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \eio_mkdir($path, $mode, \EIO_PRI_DEFAULT, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        $path = \str_replace("/", DIRECTORY_SEPARATOR, $path);
        $arrayPath = \explode(DIRECTORY_SEPARATOR, $path);
        $tmpPath = "";
        $callback = function () use(&$callback, &$arrayPath, &$tmpPath, $mode, $priority, $deferred) : void {
            $tmpPath .= DIRECTORY_SEPARATOR . \array_shift($arrayPath);
            if (empty($arrayPath)) {
                \eio_mkdir($tmpPath, $mode, $priority, [$this, "onGenericResult"], $deferred);
            } else {
                $this->isdir($tmpPath)->onResolve(function ($error, $result) use($callback, $tmpPath, $mode, $priority) {
                    if ($result) {
                        $callback();
                    } else {
                        \eio_mkdir($tmpPath, $mode, $priority, $callback);
                    }
                });
            }
        };
        $callback();
        return $deferred->promise();
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        $data = [$deferred, $path];
        \eio_rmdir($path, $priority, [$this, "onRmdir"], $data);
        return $deferred->promise();
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $flags = \EIO_READDIR_STAT_ORDER | \EIO_READDIR_DIRS_FIRST;
        $priority = \EIO_PRI_DEFAULT;
        \eio_readdir($path, $flags, $priority, [$this, "onScandir"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_chmod($path, $mode, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_chown($path, $uid ?? -1, $gid ?? -1, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        $modificationTime = $modificationTime ?? \time();
        $accessTime = $accessTime ?? $modificationTime;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $priority = \EIO_PRI_DEFAULT;
        \eio_utime($path, $accessTime, $modificationTime, $priority, [$this, "onGenericResult"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        $flags = $flags = \EIO_O_RDONLY;
        $mode = 0;
        $priority = \EIO_PRI_DEFAULT;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \eio_open($path, $flags, $mode, $priority, [$this, "onGetOpen"], $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        $flags = \EIO_O_RDWR | \EIO_O_CREAT;
        $mode = \EIO_S_IRUSR | \EIO_S_IWUSR | \EIO_S_IXUSR;
        $priority = \EIO_PRI_DEFAULT;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $data = [$contents, $deferred];
        \eio_open($path, $flags, $mode, $priority, [$this, "onPutOpen"], $data);
        return $deferred->promise();
    }
    /**
     *
     */
    private function parseMode(string $mode) : int
    {
        $mode = \str_replace(['b', 't', 'e'], '', $mode);
        switch ($mode) {
            case 'r':
                return \EIO_O_RDONLY;
            case 'r+':
                return \EIO_O_RDWR;
            case 'w':
                return \EIO_O_WRONLY | \EIO_O_TRUNC | \EIO_O_CREAT;
            case 'w+':
                return \EIO_O_RDWR | \EIO_O_TRUNC | \EIO_O_CREAT;
            case 'a':
                return \EIO_O_WRONLY | \EIO_O_APPEND | \EIO_O_CREAT;
            case 'a+':
                return \EIO_O_RDWR | \EIO_O_APPEND | \EIO_O_CREAT;
            case 'x':
                return \EIO_O_WRONLY | \EIO_O_CREAT | \EIO_O_EXCL;
            case 'x+':
                return \EIO_O_RDWR | \EIO_O_CREAT | \EIO_O_EXCL;
            case 'c':
                return \EIO_O_WRONLY | \EIO_O_CREAT;
            case 'c+':
                return \EIO_O_RDWR | \EIO_O_CREAT;
            default:
                throw new \Error('Invalid file mode: ' . $mode);
        }
    }
    /**
     *
     */
    private function onOpenHandle(array $openArr, $result, $req) : void
    {
        [$mode, $path, $deferred] = $openArr;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } elseif ($mode[0] === "a") {
            \array_unshift($openArr, $result);
            \eio_ftruncate($result, $offset = 0, \EIO_PRI_DEFAULT, [$this, "onOpenFtruncate"], $openArr);
        } else {
            \array_unshift($openArr, $result);
            \eio_fstat($result, \EIO_PRI_DEFAULT, [$this, "onOpenFstat"], $openArr);
        }
    }
    /**
     *
     */
    private function onOpenFtruncate(array $openArr, $result, $req) : void
    {
        [$fh, $mode, $path, $deferred] = $openArr;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $handle = new EioFile($this->poll, $fh, $path, $mode, $size = 0);
            $deferred->resolve($handle);
        }
    }
    /**
     *
     */
    private function onOpenFstat(array $openArr, $result, $req) : void
    {
        [$fh, $mode, $path, $deferred] = $openArr;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $handle = new EioFile($this->poll, $fh, $path, $mode, $result["size"]);
            $deferred->resolve($handle);
        }
    }
    /**
     *
     */
    private function onStat(array $data, $result, $req) : void
    {
        [$deferred, $path] = $data;
        if ($result === -1) {
            $deferred->resolve(null);
        } else {
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onLstat(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->resolve(null);
        } else {
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onReadlink(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onGenericResult(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve();
        }
    }
    /**
     *
     */
    private function onUnlink(array $data, $result, $req) : void
    {
        [$deferred, $path] = $data;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve();
        }
    }
    /**
     *
     */
    private function isDir(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->getStatus($path)->onResolve(static function ($error, $result) use($deferred) : void {
            if ($result) {
                $deferred->resolve(($result["mode"] & 040000) === 040000);
            } else {
                $deferred->resolve(false);
            }
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function onRmdir(array $data, $result, $req) : void
    {
        [$deferred, $path] = $data;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve();
        }
    }
    /**
     *
     */
    private function onScandir(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $result = $result["names"];
            \sort($result);
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onGetOpen(Deferred $deferred, $result, $req) : void
    {
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $priority = \EIO_PRI_DEFAULT;
            \eio_fstat($result, $priority, [$this, "onGetFstat"], [$result, $deferred]);
        }
    }
    /**
     *
     */
    private function onGetFstat(array $fhAndPromisor, $result, $req) : void
    {
        [$fh, $deferred] = $fhAndPromisor;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
            return;
        }
        $offset = 0;
        $length = $result["size"];
        $priority = \EIO_PRI_DEFAULT;
        \eio_read($fh, $length, $offset, $priority, [$this, "onGetRead"], $fhAndPromisor);
    }
    /**
     *
     */
    private function onGetRead(array $fhAndPromisor, $result, $req) : void
    {
        [$fh, $deferred] = $fhAndPromisor;
        \eio_close($fh);
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve($result);
        }
    }
    /**
     *
     */
    private function onPutOpen(array $data, $result, $req) : void
    {
        [$contents, $deferred] = $data;
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $length = \strlen($contents);
            $offset = 0;
            $priority = \EIO_PRI_DEFAULT;
            $callback = [$this, "onPutWrite"];
            $fhAndPromisor = [$result, $deferred];
            \eio_write($result, $contents, $length, $offset, $priority, $callback, $fhAndPromisor);
        }
    }
    /**
     *
     */
    private function onPutWrite(array $fhAndPromisor, $result, $req) : void
    {
        [$fh, $deferred] = $fhAndPromisor;
        \eio_close($fh);
        if ($result === -1) {
            $deferred->fail(new FilesystemException(\eio_get_last_error($req)));
        } else {
            $deferred->resolve();
        }
    }
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\File\Driver;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Failure;
use Amp\File\File;
use Amp\File\Internal;
use Amp\File\PendingOperationError;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class UvFile implements File
{
    /** @var Internal\UvPoll */
    private $poll;
    /** @var \UVLoop */
    private $loop;
    /** @var resource */
    private $fh;
    /** @var string */
    private $path;
    /** @var string */
    private $mode;
    /** @var int */
    private $size;
    /** @var int */
    private $position;
    /** @var \SplQueue */
    private $queue;
    /** @var bool */
    private $isActive = false;
    /** @var bool */
    private $writable = true;
    /** @var Promise|null */
    private $closing;
    /** @var bool True if ext-uv version is < 0.3.0. */
    private $priorVersion;
    /**
     * @param \Amp\Loop\UvDriver $driver
     * @param Internal\UvPoll $poll Poll for keeping the loop active.
     * @param resource $fh File handle.
     * @param string $path
     * @param string $mode
     * @param int $size
     */
    public function __construct(Loop\UvDriver $driver, Internal\UvPoll $poll, $fh, string $path, string $mode, int $size)
    {
        $this->poll = $poll;
        $this->fh = $fh;
        $this->path = $path;
        $this->mode = $mode;
        $this->size = $size;
        $this->loop = $driver->getHandle();
        $this->position = $mode[0] === "a" ? $size : 0;
        $this->queue = new \SplQueue();
        $this->priorVersion = \version_compare(\phpversion('uv'), '0.3.0', '<');
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        if ($this->isActive) {
            throw new PendingOperationError();
        }
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $this->isActive = true;
        $onRead = function ($result, $buffer) use($deferred) : void {
            $this->isActive = false;
            if (\is_int($buffer)) {
                $error = \uv_strerror($buffer);
                if ($error === "bad file descriptor") {
                    $deferred->fail(new ClosedException("Reading from the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Reading from the file failed: " . $error));
                }
                return;
            }
            $length = \strlen($buffer);
            $this->position += $length;
            $deferred->resolve($length ? $buffer : null);
        };
        if ($this->priorVersion) {
            $onRead = static function ($fh, $result, $buffer) use($onRead) : void {
                if ($result < 0) {
                    $buffer = $result;
                    // php-uv v0.3.0 changed the callback to put an int in $buffer on error.
                }
                $onRead($result, $buffer);
            };
        }
        \uv_fs_read($this->loop, $this->fh, $this->position, $length, $onRead);
        return $deferred->promise();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->isActive && $this->queue->isEmpty()) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        $this->isActive = true;
        if ($this->queue->isEmpty()) {
            $promise = $this->push($data);
        } else {
            $promise = $this->queue->top();
            $promise = call(function () use($promise, $data) {
                (yield $promise);
                return (yield $this->push($data));
            });
        }
        $this->queue->push($promise);
        return $promise;
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return call(function () use($data) {
            $promise = $this->write($data);
            $this->writable = false;
            // ignore any errors
            (yield Promise\any([$this->close()]));
            return $promise;
        });
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        if ($this->isActive && $this->queue->isEmpty()) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        $this->isActive = true;
        if ($this->queue->isEmpty()) {
            $promise = $this->trim($size);
        } else {
            $promise = $this->queue->top();
            $promise = call(function () use($promise, $size) {
                (yield $promise);
                return (yield $this->trim($size));
            });
        }
        $this->queue->push($promise);
        return $promise;
    }
    /**
     *
     */
    public function seek(int $offset, int $whence = \SEEK_SET) : Promise
    {
        if ($this->isActive) {
            throw new PendingOperationError();
        }
        $offset = (int) $offset;
        switch ($whence) {
            case self::SEEK_SET:
                $this->position = $offset;
                break;
            case self::SEEK_CUR:
                $this->position += $offset;
                break;
            case self::SEEK_END:
                $this->position = $this->size + $offset;
                break;
            default:
                throw new \Error("Invalid whence parameter; SEEK_SET, SEEK_CUR or SEEK_END expected");
        }
        return new Success($this->position);
    }
    /**
     *
     */
    public function tell() : int
    {
        return $this->position;
    }
    /**
     *
     */
    public function eof() : bool
    {
        return !$this->queue->isEmpty() ? false : $this->size <= $this->position;
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->mode;
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->closing) {
            return $this->closing;
        }
        $deferred = new Deferred();
        $this->poll->listen($this->closing = $deferred->promise());
        \uv_fs_close($this->loop, $this->fh, static function () use($deferred) : void {
            // Ignore errors when closing file, as the handle will become invalid anyway.
            $deferred->resolve();
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function push(string $data) : Promise
    {
        $length = \strlen($data);
        if ($length === 0) {
            return new Success(0);
        }
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onWrite = function ($fh, $result) use($deferred, $length) : void {
            if ($this->queue->isEmpty()) {
                $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
            }
            $this->queue->shift();
            if ($this->queue->isEmpty()) {
                $this->isActive = false;
            }
            if ($result < 0) {
                $error = \uv_strerror($result);
                if ($error === "bad file descriptor") {
                    $deferred->fail(new ClosedException("Writing to the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Writing to the file failed: " . $error));
                }
            } else {
                $this->position += $length;
                if ($this->position > $this->size) {
                    $this->size = $this->position;
                }
                $deferred->resolve($length);
            }
        };
        \uv_fs_write($this->loop, $this->fh, $data, $this->position, $onWrite);
        return $deferred->promise();
    }
    /**
     *
     */
    private function trim(int $size) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onTruncate = function ($fh) use($deferred, $size) : void {
            if ($this->queue->isEmpty()) {
                $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
            }
            $this->queue->shift();
            if ($this->queue->isEmpty()) {
                $this->isActive = false;
            }
            $this->size = $size;
            $deferred->resolve();
        };
        \uv_fs_ftruncate($this->loop, $this->fh, $size, $onTruncate);
        return $deferred->promise();
    }
}<?php

namespace Amp\File\Driver;

use Amp\File\Driver;
use Amp\File\Internal\Cache;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class StatusCachingDriver implements Driver
{
    /** @var Driver */
    private $driver;
    /** @var Cache */
    private $statusCache;
    /**
     *
     */
    public function __construct(Driver $driver)
    {
        $this->driver = $driver;
        $this->statusCache = new Cache(1000, 1024);
    }
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        return call(function () use($path, $mode) {
            $file = (yield $this->driver->openFile($path, $mode));
            return new StatusCachingFile($file, function () use($path) {
                $this->invalidate([$path], new Success());
            });
        });
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        if ($cachedStat = $this->statusCache->get($path)) {
            return new Success($cachedStat);
        }
        return call(function () use($path) {
            $stat = (yield $this->driver->getStatus($path));
            if ($stat) {
                $this->statusCache->set($path, $stat, 1000);
            }
            return $stat;
        });
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        return $this->driver->getLinkStatus($path);
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        return $this->invalidate([$target, $link], $this->driver->createSymlink($target, $link));
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        return $this->invalidate([$target, $link], $this->driver->createHardlink($target, $link));
    }
    /**
     *
     */
    public function resolveSymlink(string $target) : Promise
    {
        return $this->driver->resolveSymlink($target);
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        return $this->invalidate([$from, $to], $this->driver->move($from, $to));
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        return $this->invalidate([$path], $this->driver->deleteFile($path));
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        return $this->invalidate([$path], $this->driver->createDirectory($path, $mode));
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        return $this->invalidate([$path], $this->driver->createDirectoryRecursively($path, $mode));
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        return $this->invalidate([$path], $this->driver->deleteDirectory($path));
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        return $this->driver->listFiles($path);
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        return $this->invalidate([$path], $this->driver->changePermissions($path, $mode));
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        return $this->invalidate([$path], $this->driver->changeOwner($path, $uid, $gid));
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        return $this->invalidate([$path], $this->driver->touch($path, $modificationTime, $accessTime));
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        return $this->driver->read($path);
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        return $this->invalidate([$path], $this->driver->write($path, $contents));
    }
    /**
     *
     */
    private function invalidate(array $paths, Promise $promise) : Promise
    {
        foreach ($paths as $path) {
            $this->statusCache->delete($path);
        }
        if (!$promise instanceof Success) {
            $promise->onResolve(function () use($paths) {
                foreach ($paths as $path) {
                    $this->statusCache->delete($path);
                }
            });
        }
        return $promise;
    }
}<?php

namespace Amp\File\Driver;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Failure;
use Amp\File\File;
use Amp\File\Internal;
use Amp\File\PendingOperationError;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class EioFile implements File
{
    /** @var Internal\EioPoll */
    private $poll;
    /** @var resource eio file handle. */
    private $fh;
    /** @var string */
    private $path;
    /** @var string */
    private $mode;
    /** @var int */
    private $size;
    /** @var int */
    private $position;
    /** @var \SplQueue */
    private $queue;
    /** @var bool */
    private $isActive = false;
    /** @var bool */
    private $writable = true;
    /** @var Promise|null */
    private $closing;
    /**
     *
     */
    public function __construct(Internal\EioPoll $poll, $fh, string $path, string $mode, int $size)
    {
        $this->poll = $poll;
        $this->fh = $fh;
        $this->path = $path;
        $this->mode = $mode;
        $this->size = $size;
        $this->position = $mode[0] === "a" ? $size : 0;
        $this->queue = new \SplQueue();
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        if ($this->isActive) {
            throw new PendingOperationError();
        }
        $this->isActive = true;
        $remaining = $this->size - $this->position;
        $length = $length > $remaining ? $remaining : $length;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onRead = function (Deferred $deferred, $result, $req) : void {
            $this->isActive = false;
            if ($result === -1) {
                $error = \eio_get_last_error($req);
                if ($error === "Bad file descriptor") {
                    $deferred->fail(new ClosedException("Reading from the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Reading from the file failed:" . $error));
                }
            } else {
                $this->position += \strlen($result);
                $deferred->resolve(\strlen($result) ? $result : null);
            }
        };
        \eio_read($this->fh, $length, $this->position, \EIO_PRI_DEFAULT, $onRead, $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->isActive && $this->queue->isEmpty()) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            throw new ClosedException("The file is no longer writable");
        }
        $this->isActive = true;
        if ($this->queue->isEmpty()) {
            $promise = $this->push($data);
        } else {
            $promise = $this->queue->top();
            $promise = call(function () use($promise, $data) {
                (yield $promise);
                return (yield $this->push($data));
            });
        }
        $this->queue->push($promise);
        return $promise;
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return call(function () use($data) {
            $promise = $this->write($data);
            $this->writable = false;
            // ignore any errors
            (yield Promise\any([$this->close()]));
            return $promise;
        });
    }
    /**
     *
     */
    public function close() : Promise
    {
        if ($this->closing) {
            return $this->closing;
        }
        $deferred = new Deferred();
        $this->poll->listen($this->closing = $deferred->promise());
        \eio_close($this->fh, \EIO_PRI_DEFAULT, static function (Deferred $deferred) : void {
            // Ignore errors when closing file, as the handle will become invalid anyway.
            $deferred->resolve();
        }, $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        if ($this->isActive && $this->queue->isEmpty()) {
            throw new PendingOperationError();
        }
        if (!$this->writable) {
            return new Failure(new ClosedException("The file is no longer writable"));
        }
        $this->isActive = true;
        if ($this->queue->isEmpty()) {
            $promise = $this->trim($size);
        } else {
            $promise = $this->queue->top();
            $promise = call(function () use($promise, $size) {
                (yield $promise);
                return (yield $this->trim($size));
            });
        }
        $this->queue->push($promise);
        return $promise;
    }
    /**
     *
     */
    public function seek(int $offset, int $whence = \SEEK_SET) : Promise
    {
        if ($this->isActive) {
            throw new PendingOperationError();
        }
        switch ($whence) {
            case self::SEEK_SET:
                $this->position = $offset;
                break;
            case self::SEEK_CUR:
                $this->position += $offset;
                break;
            case self::SEEK_END:
                $this->position = $this->size + $offset;
                break;
            default:
                throw new \Error("Invalid whence parameter; SEEK_SET, SEEK_CUR or SEEK_END expected");
        }
        return new Success($this->position);
    }
    /**
     *
     */
    public function tell() : int
    {
        return $this->position;
    }
    /**
     *
     */
    public function eof() : bool
    {
        return !$this->queue->isEmpty() ? false : $this->size <= $this->position;
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->path;
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->mode;
    }
    /**
     *
     */
    private function push(string $data) : Promise
    {
        $length = \strlen($data);
        if ($length === 0) {
            return new Success(0);
        }
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onWrite = function (Deferred $deferred, $result, $req) : void {
            if ($this->queue->isEmpty()) {
                $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
            }
            $this->queue->shift();
            if ($this->queue->isEmpty()) {
                $this->isActive = false;
            }
            if ($result === -1) {
                $error = \eio_get_last_error($req);
                if ($error === "Bad file descriptor") {
                    $deferred->fail(new ClosedException("Writing to the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Writing to the file failed: " . $error));
                }
            } else {
                $this->position += $result;
                if ($this->position > $this->size) {
                    $this->size = $this->position;
                }
                $deferred->resolve($result);
            }
        };
        \eio_write($this->fh, $data, $length, $this->position, \EIO_PRI_DEFAULT, $onWrite, $deferred);
        return $deferred->promise();
    }
    /**
     *
     */
    private function trim(int $size) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $onTruncate = function (Deferred $deferred, $result, $req) use($size) : void {
            if ($this->queue->isEmpty()) {
                $deferred->fail(new ClosedException('No pending write, the file may have been closed'));
            }
            $this->queue->shift();
            if ($this->queue->isEmpty()) {
                $this->isActive = false;
            }
            if ($result === -1) {
                $error = \eio_get_last_error($req);
                if ($error === "Bad file descriptor") {
                    $deferred->fail(new ClosedException("Truncating the file failed due to a closed handle"));
                } else {
                    $deferred->fail(new StreamException("Truncating the file failed: " . $error));
                }
            } else {
                $this->size = $size;
                $deferred->resolve();
            }
        };
        \eio_ftruncate($this->fh, $size, \EIO_PRI_DEFAULT, $onTruncate, $deferred);
        return $deferred->promise();
    }
}<?php

namespace Amp\File\Driver;

use Amp\Coroutine;
use Amp\File\Driver;
use Amp\File\FilesystemException;
use Amp\File\Internal;
use Amp\Parallel\Worker;
use Amp\Parallel\Worker\Pool;
use Amp\Parallel\Worker\TaskException;
use Amp\Parallel\Worker\WorkerException;
use Amp\Promise;
use function Amp\call;
final class ParallelDriver implements Driver
{
    /** @var Pool */
    private $pool;
    /**
     * @param (Pool | null) $pool
     */
    public function __construct(Pool $pool = null)
    {
        $this->pool = $pool ?: Worker\pool();
    }
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        return call(function () use($path, $mode) {
            $worker = $this->pool->getWorker();
            try {
                [$id, $size, $mode] = (yield $worker->enqueue(new Internal\FileTask("fopen", [$path, $mode])));
            } catch (TaskException $exception) {
                throw new FilesystemException("Could not open file", $exception);
            } catch (WorkerException $exception) {
                throw new FilesystemException("Could not send open request to worker", $exception);
            }
            return new ParallelFile($worker, $id, $path, $size, $mode);
        });
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("deleteFile", [$path])));
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("getStatus", [$path])));
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("move", [$from, $to])));
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("createHardlink", [$target, $link])));
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("createSymlink", [$target, $link])));
    }
    /**
     *
     */
    public function resolveSymlink(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("resolveSymlink", [$path])));
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("createDirectory", [$path, $mode])));
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("createDirectoryRecursively", [$path, $mode])));
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("listFiles", [$path])));
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("deleteDirectory", [$path])));
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("changePermissions", [$path, $mode])));
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("changeOwner", [$path, $uid, $gid])));
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("getLinkStatus", [$path])));
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("touch", [$path, $modificationTime, $accessTime])));
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("read", [$path])));
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        return new Coroutine($this->runFileTask(new Internal\FileTask("write", [$path, $contents])));
    }
    /**
     *
     */
    private function runFileTask(Internal\FileTask $task) : \Generator
    {
        try {
            return (yield $this->pool->enqueue($task));
        } catch (TaskException $exception) {
            throw new FilesystemException("The file operation failed", $exception);
        } catch (WorkerException $exception) {
            throw new FilesystemException("Could not send the file task to worker", $exception);
        }
    }
}<?php

namespace Amp\File\Driver;

use Amp\Failure;
use Amp\File\Driver;
use Amp\File\FilesystemException;
use Amp\Promise;
use Amp\Success;
final class BlockingDriver implements Driver
{
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        $mode = \str_replace(['b', 't', 'e'], '', $mode);
        switch ($mode) {
            case "r":
            case "r+":
            case "w":
            case "w+":
            case "a":
            case "a+":
            case "x":
            case "x+":
            case "c":
            case "c+":
                break;
            default:
                throw new \Error("Invalid file mode: {$mode}");
        }
        try {
            \set_error_handler(static function ($type, $message) use($path, $mode) {
                throw new FilesystemException("Failed to open '{$path}' in mode '{$mode}': {$message}");
            });
            if (!($handle = \fopen($path, $mode . 'be'))) {
                throw new FilesystemException("Failed to open '{$path}' in mode '{$mode}'");
            }
            return new Success(new BlockingFile($handle, $path, $mode));
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        \clearstatcache(true, $path);
        return new Success(@\stat($path) ?: null);
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        \clearstatcache(true, $path);
        return new Success(@\lstat($path) ?: null);
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($target, $link) {
                throw new FilesystemException("Could not create symbolic link '{$link}' to '{$target}': {$message}");
            });
            if (!\symlink($target, $link)) {
                throw new FilesystemException("Could not create symbolic link '{$link}' to '{$target}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($target, $link) {
                throw new FilesystemException("Could not create hard link '{$link}' to '{$target}': {$message}");
            });
            if (!\link($target, $link)) {
                throw new FilesystemException("Could not create hard link '{$link}' to '{$target}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function resolveSymlink(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Could not resolve symbolic link '{$path}': {$message}");
            });
            if (false === ($result = \readlink($path))) {
                throw new FilesystemException("Could not resolve symbolic link '{$path}'");
            }
            return new Success($result);
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($from, $to) {
                throw new FilesystemException("Could not move file from '{$from}' to '{$to}': {$message}");
            });
            if (!\rename($from, $to)) {
                throw new FilesystemException("Could not move file from '{$from}' to '{$to}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Could not delete file '{$path}': {$message}");
            });
            if (!\unlink($path)) {
                throw new FilesystemException("Could not delete file '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Could not create directory '{$path}': {$message}");
            });
            /** @noinspection MkdirRaceConditionInspection */
            if (!\mkdir($path, $mode)) {
                throw new FilesystemException("Could not create directory '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                if (!\is_dir($path)) {
                    throw new FilesystemException("Could not create directory '{$path}': {$message}");
                }
            });
            if (\is_dir($path)) {
                return new Success();
            }
            /** @noinspection MkdirRaceConditionInspection */
            if (!\mkdir($path, $mode, true)) {
                if (\is_dir($path)) {
                    return new Success();
                }
                throw new FilesystemException("Could not create directory '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Could not remove directory '{$path}': {$message}");
            });
            if (!\rmdir($path)) {
                throw new FilesystemException("Could not remove directory '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to list files in '{$path}': {$message}");
            });
            if (!\is_dir($path)) {
                throw new FilesystemException("Failed to list files; '{$path}' is not a directory");
            }
            if ($arr = \scandir($path)) {
                \clearstatcache(true, $path);
                return new Success(\array_values(\array_filter($arr, static function ($el) {
                    return $el !== "." && $el !== "..";
                })));
            }
            throw new FilesystemException("Failed to list files in '{$path}'");
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to change permissions for '{$path}': {$message}");
            });
            if (!\chmod($path, $mode)) {
                throw new FilesystemException("Failed to change permissions for '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to change owner for '{$path}': {$message}");
            });
            if (($uid ?? -1) !== -1 && !\chown($path, $uid)) {
                throw new FilesystemException("Failed to change owner for '{$path}'");
            }
            if (($gid ?? -1) !== -1 && !\chgrp($path, $gid)) {
                throw new FilesystemException("Failed to change owner for '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to touch '{$path}': {$message}");
            });
            $modificationTime = $modificationTime ?? \time();
            $accessTime = $accessTime ?? $modificationTime;
            if (!\touch($path, $modificationTime, $accessTime)) {
                throw new FilesystemException("Failed to touch '{$path}'");
            }
            return new Success();
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to read '{$path}': {$message}");
            });
            if (false === ($result = \file_get_contents($path))) {
                throw new FilesystemException("Failed to read '{$path}'");
            }
            return new Success($result);
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        try {
            \set_error_handler(static function ($type, $message) use($path) {
                throw new FilesystemException("Failed to read '{$path}': {$message}");
            });
            if (false === ($result = \file_put_contents($path, $contents))) {
                throw new FilesystemException("Failed to read '{$path}'");
            }
            return new Success($result);
        } catch (FilesystemException $e) {
            return new Failure($e);
        } finally {
            \restore_error_handler();
        }
    }
}<?php

namespace Amp\File\Driver;

use Amp\File\File;
use Amp\Promise;
final class StatusCachingFile implements File
{
    /** @var File */
    private $file;
    /** @var callable */
    private $invalidateCallback;
    /**
     * @param File $file Decorated instance.
     * @param callable $invalidateCallback Invalidation callback.
     *
     * @internal
     */
    public function __construct(File $file, callable $invalidateCallback)
    {
        $this->file = $file;
        $this->invalidateCallback = $invalidateCallback;
    }
    /**
     *
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise
    {
        return $this->file->read($length);
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        return $this->invalidate($this->file->write($data));
    }
    /**
     *
     */
    public function end(string $data = "") : Promise
    {
        return $this->invalidate($this->file->end($data));
    }
    /**
     *
     */
    public function close() : Promise
    {
        return $this->file->close();
    }
    /**
     *
     */
    public function seek(int $position, int $whence = self::SEEK_SET) : Promise
    {
        return $this->file->seek($position, $whence);
    }
    /**
     *
     */
    public function tell() : int
    {
        return $this->file->tell();
    }
    /**
     *
     */
    public function eof() : bool
    {
        return $this->file->eof();
    }
    /**
     *
     */
    public function getPath() : string
    {
        return $this->file->getPath();
    }
    /**
     *
     */
    public function getMode() : string
    {
        return $this->file->getMode();
    }
    /**
     *
     */
    public function truncate(int $size) : Promise
    {
        return $this->invalidate($this->file->truncate($size));
    }
    /**
     *
     */
    private function invalidate(Promise $promise) : Promise
    {
        $promise->onResolve(function () {
            ($this->invalidateCallback)();
        });
        return $promise;
    }
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\File\Driver;

use Amp\Coroutine;
use Amp\Deferred;
use Amp\File\Driver;
use Amp\File\FilesystemException;
use Amp\File\Internal;
use Amp\Loop;
use Amp\Promise;
use Closure;
final class UvDriver implements Driver
{
    /**
     * @param Loop\Driver $driver The currently active loop driver.
     *
     * @return bool Determines if this driver can be used based on the environment.
     */
    public static function isSupported(Loop\Driver $driver) : bool
    {
        return $driver instanceof Loop\UvDriver;
    }
    /** @var Loop\UvDriver */
    private $driver;
    /** @var \UVLoop|resource Loop resource of type uv_loop or instance of \UVLoop. */
    private $loop;
    /** @var Internal\UvPoll */
    private $poll;
    /** @var bool True if ext-uv version is < 0.3.0. */
    private $priorVersion;
    /**
     *
     */
    public function __construct(Loop\UvDriver $driver)
    {
        $this->driver = $driver;
        $this->loop = $driver->getHandle();
        $this->poll = new Internal\UvPoll($driver);
        $this->priorVersion = \version_compare(\phpversion('uv'), '0.3.0', '<');
    }
    /**
     *
     */
    public function openFile(string $path, string $mode) : Promise
    {
        $flags = $this->parseMode($mode);
        $chmod = $flags & \UV::O_CREAT ? 0644 : 0;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $openArr = [$mode, $path, $deferred];
        \uv_fs_open($this->loop, $path, $flags, $chmod, function ($fh) use($openArr) : void {
            if (\is_resource($fh)) {
                $this->onOpenHandle($fh, $openArr);
            } else {
                [, $path, $deferred] = $openArr;
                $deferred->fail(new FilesystemException("Failed opening file '{$path}'"));
            }
        });
        return $deferred->promise();
    }
    /**
     *
     */
    public function getStatus(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = static function ($stat) use($deferred, $path) : void {
            if (\is_int($stat)) {
                $deferred->resolve(null);
                return;
            }
            // link is not a valid stat type but returned by the uv extension
            // change link to nlink
            if (isset($stat['link'])) {
                $stat['nlink'] = $stat['link'];
                unset($stat['link']);
            }
            $deferred->resolve($stat);
        };
        if ($this->priorVersion) {
            $callback = static function ($fh, $stat) use($callback) : void {
                if (empty($fh)) {
                    $stat = 0;
                }
                $callback($stat);
            };
        }
        \uv_fs_stat($this->loop, $path, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function getLinkStatus(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        if ($this->priorVersion) {
            $callback = static function ($fh, $stat) use($deferred) : void {
                $deferred->resolve(empty($fh) ? null : $stat);
            };
        } else {
            $callback = static function ($stat) use($deferred) : void {
                $deferred->resolve(\is_int($stat) ? null : $stat);
            };
        }
        \uv_fs_lstat($this->loop, $path, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createSymlink(string $target, string $link) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = $this->createGenericCallback($deferred, "Could not create symbolic link");
        \uv_fs_symlink($this->loop, $target, $link, \UV::S_IRWXU | \UV::S_IRUSR, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_link($this->loop, $target, $link, $this->createGenericCallback($deferred, "Could not create hard link"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function resolveSymlink(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        if ($this->priorVersion) {
            $callback = static function ($fh, $target) use($deferred) : void {
                if (!(bool) $fh) {
                    $deferred->fail(new FilesystemException("Could not read symbolic link"));
                    return;
                }
                $deferred->resolve($target);
            };
        } else {
            $callback = static function ($target) use($deferred) : void {
                if (\is_int($target)) {
                    $deferred->fail(new FilesystemException("Could not read symbolic link"));
                    return;
                }
                $deferred->resolve($target);
            };
        }
        \uv_fs_readlink($this->loop, $path, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function move(string $from, string $to) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_rename($this->loop, $from, $to, $this->createGenericCallback($deferred, "Could not rename file"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function deleteFile(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_unlink($this->loop, $path, $this->createGenericCallback($deferred, "Could not unlink file"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_mkdir($this->loop, $path, $mode, $this->createGenericCallback($deferred, "Could not create directory"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $path = \str_replace("/", DIRECTORY_SEPARATOR, $path);
        $arrayPath = \explode(DIRECTORY_SEPARATOR, $path);
        $tmpPath = "";
        $callback = function () use(&$callback, &$arrayPath, &$tmpPath, $mode, $deferred) {
            $tmpPath .= DIRECTORY_SEPARATOR . \array_shift($arrayPath);
            if (empty($arrayPath)) {
                \uv_fs_mkdir($this->loop, $tmpPath, $mode, $this->createGenericCallback($deferred, "Could not create directory"));
            } else {
                $this->isDir($tmpPath)->onResolve(function ($error, $result) use($callback, $tmpPath, $mode) : void {
                    if ($result) {
                        $callback();
                    } else {
                        \uv_fs_mkdir($this->loop, $tmpPath, $mode, $callback);
                    }
                });
            }
        };
        $callback();
        return $deferred->promise();
    }
    /**
     *
     */
    public function deleteDirectory(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        \uv_fs_rmdir($this->loop, $path, $this->createGenericCallback($deferred, "Could not remove directory"));
        return $deferred->promise();
    }
    /**
     *
     */
    public function listFiles(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        if ($this->priorVersion) {
            \uv_fs_readdir($this->loop, $path, 0, static function ($fh, $data) use($deferred, $path) : void {
                if (empty($fh) && $data !== 0) {
                    $deferred->fail(new FilesystemException("Failed reading contents from {$path}"));
                } elseif ($data === 0) {
                    $deferred->resolve([]);
                } else {
                    $deferred->resolve($data);
                }
            });
        } else {
            /** @noinspection PhpUndefinedFunctionInspection */
            \uv_fs_scandir($this->loop, $path, static function ($data) use($deferred, $path) : void {
                if (\is_int($data) && $data !== 0) {
                    $deferred->fail(new FilesystemException("Failed reading contents from {$path}"));
                } elseif ($data === 0) {
                    $deferred->resolve([]);
                } else {
                    $deferred->resolve($data);
                }
            });
        }
        return $deferred->promise();
    }
    /**
     *
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = $this->createGenericCallback($deferred, "Could not change file permissions");
        \uv_fs_chmod($this->loop, $path, $mode, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid) : Promise
    {
        // @TODO Return a failure in windows environments
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = $this->createGenericCallback($deferred, "Could not change file owner");
        \uv_fs_chown($this->loop, $path, $uid ?? -1, $gid ?? -1, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function touch(string $path, ?int $modificationTime, ?int $accessTime) : Promise
    {
        $modificationTime = $modificationTime ?? \time();
        $accessTime = $accessTime ?? $modificationTime;
        $deferred = new Deferred();
        $this->poll->listen($deferred->promise());
        $callback = $this->createGenericCallback($deferred, "Could not touch file");
        \uv_fs_utime($this->loop, $path, $modificationTime, $accessTime, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    public function read(string $path) : Promise
    {
        $promise = new Coroutine($this->doRead($path));
        $this->poll->listen($promise);
        return $promise;
    }
    /**
     *
     */
    public function write(string $path, string $contents) : Promise
    {
        $promise = new Coroutine($this->doWrite($path, $contents));
        $this->poll->listen($promise);
        return $promise;
    }
    /**
     *
     */
    private function parseMode(string $mode) : int
    {
        $mode = \str_replace(['b', 't', 'e'], '', $mode);
        switch ($mode) {
            case "r":
                return \UV::O_RDONLY;
            case "r+":
                return \UV::O_RDWR;
            case "c":
            case "w":
                return \UV::O_WRONLY | \UV::O_CREAT;
            case "c+":
            case "w+":
                return \UV::O_RDWR | \UV::O_CREAT;
            case "a":
                return \UV::O_WRONLY | \UV::O_CREAT | \UV::O_APPEND;
            case "a+":
                return \UV::O_RDWR | \UV::O_CREAT | \UV::O_APPEND;
            case "x":
                return \UV::O_WRONLY | \UV::O_CREAT | \UV::O_EXCL;
            case "x+":
                return \UV::O_RDWR | \UV::O_CREAT | \UV::O_EXCL;
            default:
                throw new \Error('Invalid file mode');
        }
    }
    /**
     *
     */
    private function onOpenHandle($fh, array $openArr) : void
    {
        [$mode] = $openArr;
        if ($mode[0] === "w") {
            \uv_fs_ftruncate($this->loop, $fh, $length = 0, function ($fh) use($openArr) : void {
                if (\is_resource($fh)) {
                    $this->finalizeHandle($fh, $size = 0, $openArr);
                } else {
                    [, $path, $deferred] = $openArr;
                    $deferred->fail(new FilesystemException("Failed truncating file {$path}"));
                }
            });
        } else {
            \uv_fs_fstat($this->loop, $fh, function ($fh, $stat) use($openArr) : void {
                if (\is_resource($fh)) {
                    $this->finalizeHandle($fh, $stat["size"], $openArr);
                } else {
                    [, $path, $deferred] = $openArr;
                    $deferred->fail(new FilesystemException("Failed reading file size from open handle pointing to {$path}"));
                }
            });
        }
    }
    /**
     *
     */
    private function finalizeHandle($fh, $size, array $openArr) : void
    {
        [$mode, $path, $deferred] = $openArr;
        $handle = new UvFile($this->driver, $this->poll, $fh, $path, $mode, $size);
        $deferred->resolve($handle);
    }
    /**
     *
     */
    private function isDir(string $path) : Promise
    {
        $deferred = new Deferred();
        $this->getStatus($path)->onResolve(static function ($error, $result) use($deferred) : void {
            if ($result) {
                $deferred->resolve(($result["mode"] & \UV::S_IFDIR) === \UV::S_IFDIR);
            } else {
                $deferred->resolve(false);
            }
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function doRead($path) : \Generator
    {
        $promise = $this->doFsOpen($path, $flags = \UV::O_RDONLY, $mode = 0);
        if (!($fh = (yield $promise))) {
            throw new FilesystemException("Failed opening file handle: {$path}");
        }
        $deferred = new Deferred();
        $stat = (yield $this->doFsStat($fh));
        if (empty($stat)) {
            $deferred->fail(new FilesystemException("stat operation failed on open file handle"));
        } elseif (!$stat["isfile"]) {
            \uv_fs_close($this->loop, $fh, static function () use($deferred) : void {
                $deferred->fail(new FilesystemException("cannot buffer contents: path is not a file"));
            });
        } else {
            $buffer = (yield $this->doFsRead($fh, $offset = 0, $stat["size"]));
            if ($buffer === false) {
                \uv_fs_close($this->loop, $fh, static function () use($deferred) : void {
                    $deferred->fail(new FilesystemException("read operation failed on open file handle"));
                });
            } else {
                \uv_fs_close($this->loop, $fh, static function () use($deferred, $buffer) : void {
                    $deferred->resolve($buffer);
                });
            }
        }
        return (yield $deferred->promise());
    }
    /**
     *
     */
    private function doFsOpen(string $path, int $flags, int $mode) : Promise
    {
        $deferred = new Deferred();
        \uv_fs_open($this->loop, $path, $flags, $mode, static function ($fh) use($deferred) {
            $deferred->resolve($fh);
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function doFsStat($fh) : Promise
    {
        $deferred = new Deferred();
        \uv_fs_fstat($this->loop, $fh, static function ($fh, $stat) use($deferred) : void {
            if (\is_resource($fh)) {
                $stat["isdir"] = (bool) ($stat["mode"] & \UV::S_IFDIR);
                $stat["isfile"] = !$stat["isdir"];
                $deferred->resolve($stat);
            } else {
                $deferred->resolve();
            }
        });
        return $deferred->promise();
    }
    /**
     *
     */
    private function doFsRead($fh, int $offset, int $len) : Promise
    {
        $deferred = new Deferred();
        if ($this->priorVersion) {
            $callback = static function ($fh, $readBytes, $buffer) use($deferred) : void {
                $deferred->resolve($readBytes < 0 ? false : $buffer);
            };
        } else {
            $callback = static function ($readBytes, $buffer) use($deferred) : void {
                $deferred->resolve($readBytes < 0 ? false : $buffer);
            };
        }
        \uv_fs_read($this->loop, $fh, $offset, $len, $callback);
        return $deferred->promise();
    }
    /**
     *
     */
    private function doWrite(string $path, string $contents) : \Generator
    {
        $flags = \UV::O_WRONLY | \UV::O_CREAT;
        $mode = \UV::S_IRWXU | \UV::S_IRUSR;
        $promise = $this->doFsOpen($path, $flags, $mode);
        if (!($fh = (yield $promise))) {
            throw new FilesystemException("Failed opening write file handle");
        }
        $deferred = new Deferred();
        \uv_fs_write($this->loop, $fh, $contents, $offset = 0, function ($fh, $result) use($deferred) : void {
            \uv_fs_close($this->loop, $fh, static function () use($deferred, $result) : void {
                if ($result < 0) {
                    $deferred->fail(new FilesystemException(\uv_strerror($result)));
                } else {
                    $deferred->resolve();
                }
            });
        });
        return (yield $deferred->promise());
    }
    /**
     *
     */
    private function createGenericCallback(Deferred $deferred, string $error) : Closure
    {
        $callback = static function (int $result) use($deferred, $error) : void {
            if ($result !== 0) {
                $deferred->fail(new FilesystemException($error));
                return;
            }
            $deferred->resolve();
        };
        if ($this->priorVersion) {
            $callback = static function (bool $result) use($callback) : void {
                $callback($result ? 0 : -1);
            };
        }
        return $callback;
    }
}<?php

namespace Amp\File;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
use Amp\Promise;
interface File extends InputStream, OutputStream
{
    public const DEFAULT_READ_LENGTH = 8192;
    public const SEEK_SET = \SEEK_SET;
    public const SEEK_CUR = \SEEK_CUR;
    public const SEEK_END = \SEEK_END;
    /**
     * Read $length bytes from the open file handle.
     *
     * @param int $length
     *
     * @return Promise<(string | null)>
     */
    public function read(int $length = self::DEFAULT_READ_LENGTH) : Promise;
    /**
     * Write $data to the open file handle.
     *
     * @param string $data
     *
     * @return Promise<int>
     */
    public function write(string $data) : Promise;
    /**
     * Write $data to the open file handle and close the handle once the write completes.
     *
     * @param string $data
     *
     * @return Promise<int>
     */
    public function end(string $data = "") : Promise;
    /**
    * Close the file handle.
    *
    * Applications are not required to manually close handles -- they will
    be unloaded automatically when the object is garbage collected.
    *
    * @return Promise<void>
    */
    public function close() : Promise;
    /**
    * Set the handle's internal pointer position.
    *
    * $whence values:
    *
    * SEEK_SET - Set position equal to offset bytes.
    SEEK_CUR - Set position to current location plus offset.
    SEEK_END - Set position to end-of-file plus offset.
    *
    * @param int $position
    * @param int $whence
    *
    * @return Promise<int> New offset position.
    */
    public function seek(int $position, int $whence = self::SEEK_SET) : Promise;
    /**
     * Return the current internal offset position of the file handle.
     *
     * @return int
     */
    public function tell() : int;
    /**
     * Test for "end-of-file" on the file handle.
     *
     * @return bool
     */
    public function eof() : bool;
    /**
     * Retrieve the path used when opening the file handle.
     *
     * @return string
     */
    public function getPath() : string;
    /**
     * Retrieve the mode used when opening the file handle.
     *
     * @return string
     */
    public function getMode() : string;
    /**
    * Truncates the file to the given length. If $size is larger than the current file size, the file is extended
    with null bytes.
    *
    * @param int $size New file size.
    *
    * @return Promise<void>
    */
    public function truncate(int $size) : Promise;
}<?php

namespace Amp\File;

final class PendingOperationError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = "The previous file operation must complete before another can be started", int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\File;

class FilesystemException extends \Exception
{
    /**
     *
     */
    public function __construct(string $message, \Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
    }
}<?php

namespace Amp\File;

use Amp\File\Driver\BlockingDriver;
use Amp\File\Driver\EioDriver;
use Amp\File\Driver\ParallelDriver;
use Amp\File\Driver\StatusCachingDriver;
use Amp\File\Driver\UvDriver;
use Amp\Loop;
use Amp\Promise;
const LOOP_STATE_IDENTIFIER = Driver::class;
/**
 * Retrieve the application-wide filesystem instance.
 *
 * @param (Driver | null) $driver Use the specified object as the application-wide filesystem instance.
 *
 * @return Filesystem
 */
function filesystem(?Driver $driver = null) : Filesystem
{
    if ($driver === null) {
        if ($filesystem = Loop::getState(LOOP_STATE_IDENTIFIER)) {
            return $filesystem;
        }
        $defaultDriver = createDefaultDriver();
        if (!\defined("AMP_WORKER")) {
            // Prevent caching in workers, cache in parent instead.
            $defaultDriver = new StatusCachingDriver($defaultDriver);
        }
        $filesystem = new Filesystem($defaultDriver);
    } else {
        $filesystem = new Filesystem($driver);
    }
    if (\defined("AMP_WORKER") && $driver instanceof ParallelDriver) {
        throw new \Error("Cannot use the parallel driver within a worker");
    }
    Loop::setState(LOOP_STATE_IDENTIFIER, $filesystem);
    return $filesystem;
}
/**
 * Create a new filesystem driver best-suited for the current environment.
 *
 * @return Driver
 */
function createDefaultDriver() : Driver
{
    $driver = Loop::get();
    if (UvDriver::isSupported($driver)) {
        /** @var Loop\UvDriver $driver */
        return new UvDriver($driver);
    }
    if (EioDriver::isSupported()) {
        return new EioDriver($driver);
    }
    if (\defined("AMP_WORKER")) {
        // Prevent spawning infinite workers.
        return new BlockingDriver();
    }
    return new ParallelDriver();
}
/**
 * Open a handle for the specified path.
 *
 * @param string $path
 * @param string $mode
 *
 * @return Promise<File>
 */
function openFile(string $path, string $mode) : Promise
{
    return filesystem()->openFile($path, $mode);
}
/**
 * Execute a file stat operation.
 *
 * If the requested path does not exist the resulting Promise will resolve to NULL.
 *
 * @param string $path File system path.
 *
 * @return Promise<(array | null)>
 */
function getStatus(string $path) : Promise
{
    return filesystem()->getStatus($path);
}
/**
 * Same as {@see Filesystem::getStatus()} except if the path is a link then the link's data is returned.
 *
 * If the requested path does not exist the resulting Promise will resolve to NULL.
 *
 * @param string $path File system path.
 *
 * @return Promise<(array | null)>
 */
function getLinkStatus(string $path) : Promise
{
    return filesystem()->getLinkStatus($path);
}
/**
* Does the specified path exist?
*
* This function should never resolve as a failure -- only a successful bool value
indicating the existence of the specified path.
*
* @param string $path File system path.
*
* @return Promise<bool>
*/
function exists(string $path) : Promise
{
    return filesystem()->exists($path);
}
/**
* Retrieve the size in bytes of the file at the specified path.
*
* If the path does not exist or is not a regular file this
function's returned Promise WILL resolve as a failure.
*
* @param string $path File system path.
* @fails \Amp\Files\FilesystemException If the path does not exist or is not a file.
*
* @return Promise<int>
*/
function getSize(string $path) : Promise
{
    return filesystem()->getSize($path);
}
/**
 * Does the specified path exist and is it a directory?
 *
 * @param string $path File system path.
 *
 * @return Promise<bool>
 */
function isDirectory(string $path) : Promise
{
    return filesystem()->isDirectory($path);
}
/**
 * Does the specified path exist and is it a file?
 *
 * @param string $path File system path.
 *
 * @return Promise<bool>
 */
function isFile(string $path) : Promise
{
    return filesystem()->isFile($path);
}
/**
* Does the specified path exist and is it a symlink?
*
* If the path does not exist the returned Promise will resolve
to FALSE and will not reject with an error.
*
* @param string $path File system path.
*
* @return Promise<bool>
*/
function isSymlink(string $path) : Promise
{
    return filesystem()->isSymlink($path);
}
/**
 * Retrieve the path's last modification time as a unix timestamp.
 *
 * @param string $path File system path.
 * @fails \Amp\Files\FilesystemException If the path does not exist.
 *
 * @return Promise<int>
 */
function getModificationTime(string $path) : Promise
{
    return filesystem()->getModificationTime($path);
}
/**
 * Retrieve the path's last access time as a unix timestamp.
 *
 * @param string $path File system path.
 * @fails \Amp\Files\FilesystemException If the path does not exist.
 *
 * @return Promise<int>
 */
function getAccessTime(string $path) : Promise
{
    return filesystem()->getAccessTime($path);
}
/**
 * Retrieve the path's creation time as a unix timestamp.
 *
 * @param string $path File system path.
 * @fails \Amp\Files\FilesystemException If the path does not exist.
 *
 * @return Promise<int>
 */
function getCreationTime(string $path) : Promise
{
    return filesystem()->getCreationTime($path);
}
/**
 * Create a symlink $link pointing to the file/directory located at $original.
 *
 * @param string $original
 * @param string $link
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function createSymlink(string $original, string $link) : Promise
{
    return filesystem()->createSymlink($original, $link);
}
/**
 * Create a hard link $link pointing to the file/directory located at $target.
 *
 * @param string $target
 * @param string $link
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function createHardlink(string $target, string $link) : Promise
{
    return filesystem()->createHardlink($target, $link);
}
/**
 * Resolve the symlink at $path.
 *
 * @param string $path
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<string>
 */
function resolveSymlink(string $path) : Promise
{
    return filesystem()->resolveSymlink($path);
}
/**
 * Move / rename a file or directory.
 *
 * @param string $from
 * @param string $to
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function move(string $from, string $to) : Promise
{
    return filesystem()->move($from, $to);
}
/**
 * Delete a file.
 *
 * @param string $path
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function deleteFile(string $path) : Promise
{
    return filesystem()->deleteFile($path);
}
/**
 * Create a directory.
 *
 * @param string $path
 * @param int $mode
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function createDirectory(string $path, int $mode = 0777) : Promise
{
    return filesystem()->createDirectory($path, $mode);
}
/**
 * Create a directory recursively.
 *
 * @param string $path
 * @param int $mode
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
{
    return filesystem()->createDirectoryRecursively($path, $mode);
}
/**
 * Delete a directory.
 *
 * @param string $path
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function deleteDirectory(string $path) : Promise
{
    return filesystem()->deleteDirectory($path);
}
/**
 * Retrieve an array of files and directories inside the specified path.
 *
 * Dot entries are not included in the resulting array (i.e. "." and "..").
 *
 * @param string $path
 *
 * @return Promise<list<string>>
 */
function listFiles(string $path) : Promise
{
    return filesystem()->listFiles($path);
}
/**
 * Change permissions of a file or directory.
 *
 * @param string $path
 * @param int $mode
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function changePermissions(string $path, int $mode) : Promise
{
    return filesystem()->changePermissions($path, $mode);
}
/**
 * Change ownership of a file or directory.
 *
 * @param string $path
 * @param (int | null) $uid null to ignore
 * @param (int | null) $gid null to ignore
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function changeOwner(string $path, ?int $uid, ?int $gid = null) : Promise
{
    return filesystem()->changeOwner($path, $uid, $gid);
}
/**
 * Update the access and modification time of the specified path.
 *
 * If the file does not exist it will be created automatically.
 *
 * @param string $path
 * @param (int | null) $modificationTime The touch time. If $time is not supplied, the current system time is used.
 * @param (int | null) $accessTime The access time. If not supplied, the modification time is used.
 * @fails \Amp\Files\FilesystemException If the operation fails.
 *
 * @return Promise<void>
 */
function touch(string $path, ?int $modificationTime = null, ?int $accessTime = null) : Promise
{
    return filesystem()->touch($path, $modificationTime, $accessTime);
}
/**
 * Buffer the specified file's contents.
 *
 * @param string $path The file path from which to buffer contents.
 *
 * @return Promise<string>
 */
function read(string $path) : Promise
{
    return filesystem()->read($path);
}
/**
 * Write the contents string to the specified path.
 *
 * @param string $path The file path to which to $contents should be written.
 * @param string $contents The data to write to the specified $path.
 *
 * @return Promise<void>
 */
function write(string $path, string $contents) : Promise
{
    return filesystem()->write($path, $contents);
}<?php

namespace Amp\File;

use Amp\Promise;
use function Amp\call;
final class Filesystem
{
    /** @var Driver */
    private $driver;
    /**
     *
     */
    public function __construct(Driver $driver)
    {
        $this->driver = $driver;
    }
    /**
     * Open a handle for the specified path.
     *
     * @param string $path
     * @param string $mode
     *
     * @return Promise<File>
     */
    public function openFile(string $path, string $mode) : Promise
    {
        return $this->driver->openFile($path, $mode);
    }
    /**
     * Execute a file stat operation.
     *
     * If the requested path does not exist the resulting Promise will resolve to NULL.
     *
     * @param string $path File system path.
     *
     * @return Promise<(array | null)>
     */
    public function getStatus(string $path) : Promise
    {
        return $this->driver->getStatus($path);
    }
    /**
     * Same as {@see Filesystem::getStatus()} except if the path is a link then the link's data is returned.
     *
     * If the requested path does not exist the resulting Promise will resolve to NULL.
     *
     * @param string $path File system path.
     *
     * @return Promise<(array | null)>
     */
    public function getLinkStatus(string $path) : Promise
    {
        return $this->driver->getLinkStatus($path);
    }
    /**
    * Does the specified path exist?
    *
    * This function should never resolve as a failure -- only a successful bool value
    indicating the existence of the specified path.
    *
    * @param string $path File system path.
    *
    * @return Promise<bool>
    */
    public function exists(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            return $result !== null;
        });
    }
    /**
    * Retrieve the size in bytes of the file at the specified path.
    *
    * If the path does not exist or is not a regular file this
    function's returned Promise WILL resolve as a failure.
    *
    * @param string $path File system path.
    * @fails \Amp\Files\FilesystemException If the path does not exist or is not a file.
    *
    * @return Promise<int>
    */
    public function getSize(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                throw new FilesystemException("Failed to read file size for '{$path}'");
            }
            if ($result['mode'] & 0100000) {
                return $result["size"];
            }
            throw new FilesystemException("Failed to read file size for '{$path}'; specified path is not a regular file");
        });
    }
    /**
     * Does the specified path exist and is it a directory?
     *
     * @param string $path File system path.
     *
     * @return Promise<bool>
     */
    public function isDirectory(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                return false;
            }
            return (bool) ($result['mode'] & 040000);
        });
    }
    /**
     * Does the specified path exist and is it a file?
     *
     * @param string $path File system path.
     *
     * @return Promise<bool>
     */
    public function isFile(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                return false;
            }
            return (bool) ($result['mode'] & 0100000);
        });
    }
    /**
    * Does the specified path exist and is it a symlink?
    *
    * If the path does not exist the returned Promise will resolve
    to FALSE and will not reject with an error.
    *
    * @param string $path File system path.
    *
    * @return Promise<bool>
    */
    public function isSymlink(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getLinkStatus($path));
            if ($result === null) {
                return false;
            }
            return ($result['mode'] & 0120000) === 0120000;
        });
    }
    /**
     * Retrieve the path's last modification time as a unix timestamp.
     *
     * @param string $path File system path.
     * @fails \Amp\Files\FilesystemException If the path does not exist.
     *
     * @return Promise<int>
     */
    public function getModificationTime(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                throw new FilesystemException("Failed to read file modification time for '{$path}'");
            }
            return $result["mtime"];
        });
    }
    /**
     * Retrieve the path's last access time as a unix timestamp.
     *
     * @param string $path File system path.
     * @fails \Amp\Files\FilesystemException If the path does not exist.
     *
     * @return Promise<int>
     */
    public function getAccessTime(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                throw new FilesystemException("Failed to read file access time for '{$path}'");
            }
            return $result["atime"];
        });
    }
    /**
     * Retrieve the path's creation time as a unix timestamp.
     *
     * @param string $path File system path.
     * @fails \Amp\Files\FilesystemException If the path does not exist.
     *
     * @return Promise<int>
     */
    public function getCreationTime(string $path) : Promise
    {
        return call(function () use($path) {
            $result = (yield $this->getStatus($path));
            if ($result === null) {
                throw new FilesystemException("Failed to read file creation time for '{$path}'");
            }
            return $result["ctime"];
        });
    }
    /**
     * Create a symlink $link pointing to the file/directory located at $original.
     *
     * @param string $original
     * @param string $link
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function createSymlink(string $original, string $link) : Promise
    {
        return $this->driver->createSymlink($original, $link);
    }
    /**
     * Create a hard link $link pointing to the file/directory located at $target.
     *
     * @param string $target
     * @param string $link
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function createHardlink(string $target, string $link) : Promise
    {
        return $this->driver->createHardlink($target, $link);
    }
    /**
     * Resolve the symlink at $path.
     *
     * @param string $path
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<string>
     */
    public function resolveSymlink(string $path) : Promise
    {
        return $this->driver->resolveSymlink($path);
    }
    /**
     * Move / rename a file or directory.
     *
     * @param string $from
     * @param string $to
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function move(string $from, string $to) : Promise
    {
        return $this->driver->move($from, $to);
    }
    /**
     * Delete a file.
     *
     * @param string $path
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function deleteFile(string $path) : Promise
    {
        return $this->driver->deleteFile($path);
    }
    /**
     * Create a directory.
     *
     * @param string $path
     * @param int $mode
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function createDirectory(string $path, int $mode = 0777) : Promise
    {
        return $this->driver->createDirectory($path, $mode);
    }
    /**
     * Create a directory recursively.
     *
     * @param string $path
     * @param int $mode
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function createDirectoryRecursively(string $path, int $mode = 0777) : Promise
    {
        return $this->driver->createDirectoryRecursively($path, $mode);
    }
    /**
     * Delete a directory.
     *
     * @param string $path
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function deleteDirectory(string $path) : Promise
    {
        return $this->driver->deleteDirectory($path);
    }
    /**
     * Retrieve an array of files and directories inside the specified path.
     *
     * Dot entries are not included in the resulting array (i.e. "." and "..").
     *
     * @param string $path
     *
     * @return Promise<list<string>>
     */
    public function listFiles(string $path) : Promise
    {
        return $this->driver->listFiles($path);
    }
    /**
     * Change permissions of a file or directory.
     *
     * @param string $path
     * @param int $mode
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function changePermissions(string $path, int $mode) : Promise
    {
        return $this->driver->changePermissions($path, $mode);
    }
    /**
     * Change ownership of a file or directory.
     *
     * @param string $path
     * @param (int | null) $uid null to ignore
     * @param (int | null) $gid null to ignore
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function changeOwner(string $path, ?int $uid, ?int $gid = null) : Promise
    {
        return $this->driver->changeOwner($path, $uid, $gid);
    }
    /**
     * Update the access and modification time of the specified path.
     *
     * If the file does not exist it will be created automatically.
     *
     * @param string $path
     * @param (int | null) $modificationTime The touch time. If $time is not supplied, the current system time is used.
     * @param (int | null) $accessTime The access time. If not supplied, the modification time is used.
     * @fails \Amp\Files\FilesystemException If the operation fails.
     *
     * @return Promise<void>
     */
    public function touch(string $path, ?int $modificationTime = null, ?int $accessTime = null) : Promise
    {
        return $this->driver->touch($path, $modificationTime, $accessTime);
    }
    /**
     * Buffer the specified file's contents.
     *
     * @param string $path The file path from which to buffer contents.
     *
     * @return Promise<string>
     */
    public function read(string $path) : Promise
    {
        return $this->driver->read($path);
    }
    /**
     * Write the contents string to the specified path.
     *
     * @param string $path The file path to which to $contents should be written.
     * @param string $contents The data to write to the specified $path.
     *
     * @return Promise<void>
     */
    public function write(string $path, string $contents) : Promise
    {
        return $this->driver->write($path, $contents);
    }
}{
    "name": "amphp/file",
    "homepage": "https://github.com/amphp/file",
    "description": "Allows non-blocking access to the filesystem for Amp.",
    "support": {
        "issues": "https://github.com/amphp/file/issues"
    },
    "keywords": [
        "file",
        "disk",
        "static",
        "async",
        "non-blocking",
        "amp",
        "amphp",
        "io",
        "filesystem"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2.5.2",
        "amphp/byte-stream": "^1.8.1",
        "amphp/parallel": "^1.4",
        "amphp/sync": "^1.4"
    },
    "require-dev": {
        "ext-eio": "^2 || ^3",
        "ext-uv": "^0.3 || ^0.2",
        "amphp/phpunit-util": "^1.1",
        "phpunit/phpunit": "^9 || ^8 || ^7",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\File\\": "src"
        },
        "files": ["src/functions.php"]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\File\\Test\\": "test",
            "Amp\\Sync\\Test\\": "vendor/amphp/sync/test"
        }
    },
    "config": {
        "preferred-install": {
            "amphp/sync": "source"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "2.x-dev"
        }
    },
    "scripts": {
        "check": [
            "@code-style",
            "@test"
        ],
        "code-style": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

declare (strict_types=1);
namespace Amp\File\Test\Sync;

use Amp\File\Sync\AsyncFileMutex;
use Amp\Sync\Mutex;
use Amp\Sync\Test\AbstractMutexTest;
final class AsyncFileMutexTest extends AbstractMutexTest
{
    /**
     *
     */
    public function createMutex() : Mutex
    {
        return new AsyncFileMutex(\tempnam(\sys_get_temp_dir(), 'mutex-') . '.lock');
    }
}<?php

namespace Amp\File\Test;

use Amp\PHPUnit\AsyncTestCase;
abstract class FilesystemTest extends AsyncTestCase
{
    /**
     *
     */
    protected function setUp() : void
    {
        parent::setUp();
        Fixture::init();
    }
    /**
     *
     */
    protected function tearDown() : void
    {
        parent::tearDown();
        Fixture::clear();
    }
}<?php

namespace Amp\File\Test;

use Amp\File;
use Amp\File\PendingOperationError;
abstract class AsyncFileTest extends FileTest
{
    /**
     *
     */
    public function testSimultaneousReads() : \Generator
    {
        $this->expectException(PendingOperationError::class);
        /** @var File\File $handle */
        $handle = (yield File\openFile(__FILE__, "r"));
        $promise1 = $handle->read();
        $promise2 = $handle->read();
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield File\read(__FILE__)), 0, 20);
        $this->assertSame($expected, (yield $promise1));
        (yield $promise2);
    }
    /**
     *
     */
    public function testSeekWhileReading() : \Generator
    {
        $this->expectException(PendingOperationError::class);
        /** @var File\File $handle */
        $handle = (yield File\openFile(__FILE__, "r"));
        $promise1 = $handle->read(10);
        $promise2 = $handle->seek(0);
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield File\read(__FILE__)), 0, 10);
        $this->assertSame($expected, (yield $promise1));
        (yield $promise2);
    }
    /**
     *
     */
    public function testReadWhileWriting() : \Generator
    {
        $this->expectException(PendingOperationError::class);
        $path = Fixture::path() . "/temp";
        /** @var File\File $handle */
        $handle = (yield File\openFile($path, "c+"));
        $data = "test";
        $promise1 = $handle->write($data);
        $promise2 = $handle->read(10);
        $this->assertSame(\strlen($data), (yield $promise1));
        (yield $promise2);
        // Should throw.
    }
    /**
     *
     */
    public function testWriteWhileReading() : \Generator
    {
        $this->expectException(PendingOperationError::class);
        $path = Fixture::path() . "/temp";
        /** @var File\File $handle */
        $handle = (yield File\openFile($path, "c+"));
        $promise1 = $handle->read(10);
        $promise2 = $handle->write("test");
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield File\read(__FILE__)), 0, 10);
        $this->assertSame($expected, (yield $promise1));
        (yield $promise2);
        // Should throw.
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\BlockingDriver;
use Amp\File\Test\FileTest;
class StatusCachingFileTest extends FileTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        return new File\Driver\StatusCachingDriver(new BlockingDriver());
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\EioDriver;
use Amp\File\Test\AsyncFileTest;
use Amp\Loop;
class EioFileTest extends AsyncFileTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        if (!\extension_loaded("eio")) {
            $this->markTestSkipped("eio extension not loaded");
        }
        return new EioDriver(Loop::get());
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\BlockingDriver;
use Amp\File\Test\DriverTest;
class StatusCachingDriverTest extends DriverTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        return new File\Driver\StatusCachingDriver(new BlockingDriver());
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\EioDriver;
use Amp\File\Test\DriverTest;
use Amp\Loop;
class EioDriverTest extends DriverTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        if (!\extension_loaded("eio")) {
            $this->markTestSkipped("eio extension not loaded");
        }
        return new EioDriver(Loop::get());
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\ParallelDriver;
use Amp\File\Test\AsyncFileTest;
use Amp\Parallel\Worker\DefaultPool;
use Amp\Parallel\Worker\Pool;
class ParallelFileTest extends AsyncFileTest
{
    /** @var Pool */
    private $pool;
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        $this->pool = new DefaultPool();
        return new ParallelDriver($this->pool);
    }
    /**
     *
     */
    protected function tearDownAsync() : void
    {
        $this->pool->shutdown();
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\ParallelDriver;
use Amp\File\Test\DriverTest;
use Amp\Parallel\Worker\DefaultPool;
use Amp\Parallel\Worker\Pool;
class ParallelDriverTest extends DriverTest
{
    /** @var Pool */
    private $pool;
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        $this->pool = new DefaultPool();
        return new ParallelDriver($this->pool);
    }
    /**
     *
     */
    protected function tearDownAsync() : void
    {
        $this->pool->shutdown();
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\UvDriver;
use Amp\File\Test\DriverTest;
use Amp\Loop;
class UvDriverTest extends DriverTest
{
    /**
     * @dataProvider symlinkPathProvider
     *
     * @param \Closure $linkResolver
     */
    public function testResolveSymlinkError(\Closure $linkResolver) : \Generator
    {
        if (\version_compare(\phpversion('uv'), '0.3.0', '<')) {
            $this->markTestSkipped('UvDriver Test Skipped: Causes Crash');
        }
        yield from parent::testResolveSymlinkError($linkResolver);
    }
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        if (!\extension_loaded("uv")) {
            $this->markTestSkipped("php-uv extension not loaded");
        }
        $loop = new Loop\UvDriver();
        Loop::set($loop);
        return new UvDriver($loop);
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\BlockingDriver;
use Amp\File\Test\DriverTest;
class BlockingDriverTest extends DriverTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        return new BlockingDriver();
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\BlockingDriver;
use Amp\File\Test\FileTest;
class BlockingFileTest extends FileTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        return new BlockingDriver();
    }
}<?php

namespace Amp\File\Test\Driver;

use Amp\File;
use Amp\File\Driver\UvDriver;
use Amp\File\Test\AsyncFileTest;
use Amp\Loop;
class UvFileTest extends AsyncFileTest
{
    /**
     *
     */
    protected function createDriver() : File\Driver
    {
        if (!\extension_loaded("uv")) {
            $this->markTestSkipped("php-uv extension not loaded");
        }
        $loop = new Loop\UvDriver();
        Loop::set($loop);
        return new UvDriver($loop);
    }
}<?php

namespace Amp\File\Test;

use Amp\ByteStream\ClosedException;
use Amp\File;
abstract class FileTest extends FilesystemTest
{
    /** @var File\Driver */
    private $driver;
    /**
     *
     */
    public function testWrite() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        $this->assertSame(0, $handle->tell());
        $handle->write("foo");
        (yield $handle->write("bar"));
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertSame(6, $handle->tell());
        $this->assertTrue($handle->eof());
        $this->assertSame("foobar", $contents);
        (yield $handle->close());
    }
    /**
     *
     */
    public function testEmptyWrite() : \Generator
    {
        $path = Fixture::path() . "/write";
        $handle = (yield $this->driver->openFile($path, "c+"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->write(""));
        $this->assertSame(0, $handle->tell());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testWriteAfterClose() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        (yield $handle->close());
        $this->expectException(ClosedException::class);
        (yield $handle->write("bar"));
    }
    /**
     *
     */
    public function testDoubleClose() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        (yield $handle->close());
        $this->assertNull((yield $handle->close()));
    }
    /**
     *
     */
    public function testWriteAfterEnd() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->end("foo"));
        $this->expectException(ClosedException::class);
        (yield $handle->write("bar"));
    }
    /**
     *
     */
    public function testWriteInAppendMode() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "a+"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->write("bar"));
        (yield $handle->write("foo"));
        (yield $handle->write("baz"));
        $this->assertSame(9, $handle->tell());
        (yield $handle->seek(0));
        $this->assertSame(0, $handle->tell());
        $this->assertSame("barfoobaz", (yield $handle->read()));
    }
    /**
     *
     */
    public function testReadingToEof() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $contents = "";
        $position = 0;
        $stat = (yield $this->driver->getStatus(__FILE__));
        $chunkSize = (int) \floor($stat["size"] / 5);
        while (!$handle->eof()) {
            $chunk = (yield $handle->read($chunkSize));
            $contents .= $chunk;
            $position += \strlen($chunk);
            $this->assertSame($position, $handle->tell());
        }
        $this->assertNull((yield $handle->read()));
        $this->assertSame((yield $this->driver->read(__FILE__)), $contents);
        (yield $handle->close());
    }
    /**
     *
     */
    public function testSequentialReads() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $contents = "";
        $contents .= (yield $handle->read(10));
        $contents .= (yield $handle->read(10));
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield $this->driver->read(__FILE__)), 0, 20);
        $this->assertSame($expected, $contents);
        (yield $handle->close());
    }
    /**
     *
     */
    public function testReadingFromOffset() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->seek(10));
        $this->assertSame(10, $handle->tell());
        $chunk = (yield $handle->read(90));
        $this->assertSame(100, $handle->tell());
        $expected = \Phabel\Target\Php80\Polyfill::substr((yield $this->driver->read(__FILE__)), 10, 90);
        $this->assertSame($expected, $chunk);
        (yield $handle->close());
    }
    /**
     *
     */
    public function testSeekThrowsOnInvalidWhence() : \Generator
    {
        $this->expectException(\Error::class);
        try {
            /** @var File\File $handle */
            $handle = (yield $this->driver->openFile(__FILE__, "r"));
            (yield $handle->seek(0, 99999));
        } finally {
            (yield $handle->close());
        }
    }
    /**
     *
     */
    public function testSeekSetCur() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->seek(10));
        $this->assertSame(10, $handle->tell());
        (yield $handle->seek(-10, \SEEK_CUR));
        $this->assertSame(0, $handle->tell());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testSeekSetEnd() : \Generator
    {
        $size = \filesize(__FILE__);
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame(0, $handle->tell());
        (yield $handle->seek(-10, \SEEK_END));
        $this->assertSame($size - 10, $handle->tell());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testPath() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame(__FILE__, $handle->getPath());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testMode() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        $this->assertSame("r", $handle->getMode());
        (yield $handle->close());
    }
    /**
     *
     */
    public function testClose() : \Generator
    {
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile(__FILE__, "r"));
        (yield $handle->close());
        $this->expectException(ClosedException::class);
        (yield $handle->read());
    }
    /**
     * @depends testWrite
     */
    public function testTruncateToSmallerSize() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        $handle->write("foo");
        (yield $handle->write("bar"));
        (yield $handle->truncate(4));
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertTrue($handle->eof());
        $this->assertSame("foob", $contents);
        (yield $handle->write("bar"));
        $this->assertSame(7, $handle->tell());
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertSame("foobbar", $contents);
        (yield $handle->close());
    }
    /**
     * @depends testWrite
     */
    public function testTruncateToLargerSize() : \Generator
    {
        $path = Fixture::path() . "/write";
        /** @var File\File $handle */
        $handle = (yield $this->driver->openFile($path, "c+"));
        (yield $handle->write("foo"));
        (yield $handle->truncate(6));
        $this->assertSame(3, $handle->tell());
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertTrue($handle->eof());
        $this->assertSame("foo\x00\x00\x00", $contents);
        (yield $handle->write("bar"));
        $this->assertSame(9, $handle->tell());
        (yield $handle->seek(0));
        $contents = (yield $handle->read());
        $this->assertSame("foo\x00\x00\x00bar", $contents);
        (yield $handle->close());
    }
    /**
     *
     */
    protected abstract function createDriver() : File\Driver;
    /**
     *
     */
    protected function setUp() : void
    {
        parent::setUp();
        $this->driver = $this->createDriver();
    }
}<?php

namespace Amp\File\Test;

use Amp\File;
use Amp\File\FilesystemException;
abstract class DriverTest extends FilesystemTest
{
    /** @var File\Filesystem */
    protected $driver;
    /**
     *
     */
    public function testListFiles() : \Generator
    {
        $fixtureDir = Fixture::path();
        $actual = (yield $this->driver->listFiles($fixtureDir));
        $expected = ["dir", "dirlink", "fifo", "fifolink", "file", "filelink", "linkloop"];
        $this->assertSame($expected, $actual);
    }
    /**
     *
     */
    public function testListFilesThrowsIfPathNotADirectory() : \Generator
    {
        $this->expectException(FilesystemException::class);
        (yield $this->driver->listFiles(__FILE__));
    }
    /**
     *
     */
    public function testListFilesThrowsIfPathDoesntExist() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $path = Fixture::path() . "/nonexistent";
        (yield $this->driver->listFiles($path));
    }
    /**
     *
     */
    public function testCreateSymlink() : \Generator
    {
        $fixtureDir = Fixture::path();
        $original = "{$fixtureDir}/file";
        $link = "{$fixtureDir}/symlink.txt";
        $this->assertNull((yield $this->driver->createSymlink($original, $link)));
        $this->assertTrue(\is_link($link));
        (yield $this->driver->deleteFile($link));
    }
    /**
     *
     */
    public function testCreateSymlinkFailWhenLinkExists() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        (yield $this->driver->createSymlink($path, $path));
    }
    /**
     *
     */
    public function testCreateHardlink() : \Generator
    {
        $fixtureDir = Fixture::path();
        $original = "{$fixtureDir}/file";
        $link = "{$fixtureDir}/hardlink.txt";
        $this->assertNull((yield $this->driver->createHardlink($original, $link)));
        $this->assertFileExists($link);
        $this->assertFalse(\is_link($link));
        (yield $this->driver->deleteFile($link));
    }
    /**
     *
     */
    public function testCreateHardlinkFailWhenLinkExists() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        (yield $this->driver->createHardlink($path, $path));
    }
    /**
     *
     */
    public function testResolveSymlink() : \Generator
    {
        $fixtureDir = Fixture::path();
        $original = "{$fixtureDir}/file";
        $link = "{$fixtureDir}/symlink.txt";
        \symlink($original, $link);
        $this->assertSame($original, (yield $this->driver->resolveSymlink($link)));
    }
    /**
     *
     */
    public function symlinkPathProvider() : array
    {
        return ['nonExistingPath' => [static function () {
            return Fixture::path() . '/' . \uniqid('amphp-test-', true);
        }], 'notLink' => [static function () {
            return Fixture::path();
        }]];
    }
    /**
     * @dataProvider symlinkPathProvider
     *
     * @param \Closure $linkResolver
     *
     * @return \Generator
     */
    public function testResolveSymlinkError(\Closure $linkResolver) : \Generator
    {
        $this->expectException(FilesystemException::class);
        $link = $linkResolver();
        (yield $this->driver->resolveSymlink($link));
    }
    /**
     *
     */
    public function testLinkStatus() : \Generator
    {
        $fixtureDir = Fixture::path();
        $target = "{$fixtureDir}/file";
        $link = "{$fixtureDir}/symlink.txt";
        (yield $this->driver->createSymlink($target, $link));
        $this->assertIsArray((yield $this->driver->getLinkStatus($link)));
        (yield $this->driver->deleteFile($link));
    }
    /**
     *
     */
    public function testStatus() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $this->assertIsArray($stat);
        $this->assertSameStatus(\stat($path), $stat);
    }
    /**
     *
     */
    public function testDirectoryStatus() : \Generator
    {
        $fixtureDir = Fixture::path();
        $stat = (yield $this->driver->getStatus("{$fixtureDir}/dir"));
        $this->assertIsArray($stat);
        $this->assertSameStatus(\stat("{$fixtureDir}/dir"), $stat);
    }
    /**
     *
     */
    public function testNonexistentPathStatusResolvesToNull() : \Generator
    {
        $fixtureDir = Fixture::path();
        $stat = (yield $this->driver->getStatus("{$fixtureDir}/nonexistent"));
        $this->assertNull($stat);
    }
    /**
     *
     */
    public function testExists() : \Generator
    {
        $fixtureDir = Fixture::path();
        $this->assertFalse((yield $this->driver->exists("{$fixtureDir}/nonexistent")));
        $this->assertTrue((yield $this->driver->exists("{$fixtureDir}/file")));
    }
    /**
     *
     */
    public function testRead() : \Generator
    {
        $fixtureDir = Fixture::path();
        $this->assertSame("small", (yield $this->driver->read("{$fixtureDir}/file")));
    }
    /**
     *
     */
    public function testSize() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $size = $stat["size"];
        $this->assertSame($size, (yield $this->driver->getSize($path)));
    }
    /**
     *
     */
    public function testSizeFailsOnNonexistentPath() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        (yield $this->driver->getSize($path));
    }
    /**
     *
     */
    public function testSizeFailsOnDirectoryPath() : \Generator
    {
        $this->expectException(FilesystemException::class);
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/dir";
        $this->assertTrue((yield $this->driver->isDirectory($path)));
        (yield $this->driver->getSize($path));
    }
    /**
     * @dataProvider dataForDirectoryCheck
     */
    public function testIsDirectory(bool $expectedResult, string $name) : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/{$name}";
        $this->assertSame($expectedResult, (yield $this->driver->isDirectory($path)));
    }
    /**
     *
     */
    public function dataForDirectoryCheck() : \Generator
    {
        (yield 'file' => [false, 'file']);
        (yield 'filelink' => [false, 'filelink']);
        (yield 'dir' => [true, 'dir']);
        (yield 'dirlink' => [true, 'dirlink']);
        if (\extension_loaded('posix')) {
            (yield 'fifo' => [false, 'fifo']);
            (yield 'fifolink' => [false, 'fifolink']);
        }
        (yield 'linkloop' => [false, 'linkloop']);
        (yield 'nonexistent' => [false, 'nonexistent']);
    }
    /**
     * @dataProvider dataForFileCheck
     */
    public function testIsFile(bool $expectedResult, string $name) : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/{$name}";
        $this->assertSame($expectedResult, (yield $this->driver->isFile($path)));
    }
    /**
     *
     */
    public function dataForFileCheck() : \Generator
    {
        (yield 'file' => [true, 'file']);
        (yield 'filelink' => [true, 'filelink']);
        (yield 'dir' => [false, 'dir']);
        (yield 'dirlink' => [false, 'dirlink']);
        if (\extension_loaded('posix')) {
            (yield 'fifo' => [false, 'fifo']);
            (yield 'fifolink' => [false, 'fifolink']);
        }
        (yield 'linkloop' => [false, 'linkloop']);
        (yield 'nonexistent' => [false, 'nonexistent']);
    }
    /**
     * @dataProvider dataForSymlinkCheck
     */
    public function testIsSymlink(bool $expectedResult, string $name) : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/{$name}";
        $this->assertSame($expectedResult, (yield $this->driver->isSymlink($path)));
    }
    /**
     *
     */
    public function dataForSymlinkCheck() : \Generator
    {
        (yield 'file' => [false, 'file']);
        (yield 'filelink' => [true, 'filelink']);
        (yield 'dir' => [false, 'dir']);
        (yield 'dirlink' => [true, 'dirlink']);
        if (\extension_loaded('posix')) {
            (yield 'fifo' => [false, 'fifo']);
            (yield 'fifolink' => [true, 'fifolink']);
        }
        (yield 'linkloop' => [true, 'linkloop']);
        (yield 'nonexistent' => [false, 'nonexistent']);
    }
    /**
     *
     */
    public function testMove() : \Generator
    {
        $fixtureDir = Fixture::path();
        $contents1 = "rename test";
        $old = "{$fixtureDir}/rename1.txt";
        $new = "{$fixtureDir}/rename2.txt";
        (yield $this->driver->write($old, $contents1));
        $this->assertNull((yield $this->driver->move($old, $new)));
        $contents2 = (yield $this->driver->read($new));
        (yield $this->driver->deleteFile($new));
        $this->assertSame($contents1, $contents2);
    }
    /**
     *
     */
    public function testMoveFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->move($path, $path));
    }
    /**
     *
     */
    public function testDeleteFile() : \Generator
    {
        $fixtureDir = Fixture::path();
        $toUnlink = "{$fixtureDir}/unlink";
        (yield $this->driver->getStatus($toUnlink));
        (yield $this->driver->write($toUnlink, "unlink me"));
        $this->assertNull((yield $this->driver->deleteFile($toUnlink)));
        $this->assertNull((yield $this->driver->getStatus($toUnlink)));
    }
    /**
     *
     */
    public function testDeleteFileFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->deleteFile($path));
    }
    /**
     *
     */
    public function testDeleteFileFailsOnDirectory() : \Generator
    {
        $fixtureDir = Fixture::path();
        $dir = "{$fixtureDir}/newdir";
        (yield $this->driver->createDirectory($dir));
        $this->expectException(FilesystemException::class);
        (yield $this->driver->deleteFile($dir));
    }
    /**
     *
     */
    public function testCreateAndDeleteDirectory() : \Generator
    {
        $fixtureDir = Fixture::path();
        $dir = "{$fixtureDir}/newdir";
        \umask(022);
        $this->assertNull((yield $this->driver->createDirectory($dir)));
        $stat = (yield $this->driver->getStatus($dir));
        $this->assertSame('0755', $this->getPermissionsFromStatus($stat));
        $this->assertNull((yield $this->driver->deleteDirectory($dir)));
        $this->assertNull((yield $this->driver->getStatus($dir)));
        // test for 0, because previous array_filter made that not work
        $dir = "{$fixtureDir}/newdir/with/recursive/creation/0/1/2";
        $this->assertNull((yield $this->driver->createDirectoryRecursively($dir, 0764)));
        $stat = (yield $this->driver->getStatus($dir));
        $this->assertSame('0744', $this->getPermissionsFromStatus($stat));
    }
    /**
     *
     */
    public function testCreateDirectoryFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->createDirectory($path));
    }
    /**
     *
     */
    public function testDeleteDirectoryFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->deleteDirectory($path));
    }
    /**
     *
     */
    public function testDeleteDirectoryFailsOnFile() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->deleteDirectory($path));
    }
    /**
     *
     */
    public function testMtime() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $statMtime = $stat["mtime"];
        $this->assertSame($statMtime, (yield $this->driver->getModificationTime($path)));
    }
    /**
     *
     */
    public function testMtimeFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->getModificationTime($path));
    }
    /**
     *
     */
    public function testAtime() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $statAtime = $stat["atime"];
        $this->assertSame($statAtime, (yield $this->driver->getAccessTime($path)));
    }
    /**
     *
     */
    public function testAtimeFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->getAccessTime($path));
    }
    /**
     *
     */
    public function testCtime() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $statCtime = $stat["ctime"];
        $this->assertSame($statCtime, (yield $this->driver->getCreationTime($path)));
    }
    /**
     *
     */
    public function testCtimeFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->getCreationTime($path));
    }
    /**
     * @group slow
     */
    public function testTouch() : \Generator
    {
        $fixtureDir = Fixture::path();
        $touch = "{$fixtureDir}/touch";
        (yield $this->driver->write($touch, "touch me"));
        $oldStat = (yield $this->driver->getStatus($touch));
        $this->assertNull((yield $this->driver->touch($touch, \time() + 10, \time() + 20)));
        $newStat = (yield $this->driver->getStatus($touch));
        (yield $this->driver->deleteFile($touch));
        $this->assertTrue($newStat["atime"] > $oldStat["atime"]);
        $this->assertTrue($newStat["mtime"] > $oldStat["mtime"]);
    }
    /**
     *
     */
    public function testTouchFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->touch($path));
    }
    /**
     *
     */
    public function testChangePermissions() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        $stat = (yield $this->driver->getStatus($path));
        $this->assertNotSame('0777', \Phabel\Target\Php80\Polyfill::substr(\decoct($stat['mode']), -4));
        $this->assertNull((yield $this->driver->changePermissions($path, 0777)));
        $stat = (yield $this->driver->getStatus($path));
        $this->assertSame('0777', \Phabel\Target\Php80\Polyfill::substr(\decoct($stat['mode']), -4));
    }
    /**
     *
     */
    public function testChangePermissionsFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->changePermissions($path, 0777));
    }
    /**
     *
     */
    public function testChangeOwner() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/file";
        (yield $this->driver->getStatus($path));
        $user = \fileowner($path);
        $this->assertNull((yield $this->driver->changeOwner($path, $user, null)));
    }
    /**
     *
     */
    public function testChangeOwnerFailsOnNonexistentPath() : \Generator
    {
        $fixtureDir = Fixture::path();
        $path = "{$fixtureDir}/nonexistent";
        $this->expectException(FilesystemException::class);
        (yield $this->driver->changeOwner($path, 0, null));
    }
    /**
     *
     */
    protected function setUp() : void
    {
        parent::setUp();
        $this->driver = new File\Filesystem($this->createDriver());
    }
    /**
     *
     */
    protected abstract function createDriver() : File\Driver;
    /**
     *
     */
    private function assertSameStatus(array $expected, array $actual) : void
    {
        $filter = function (array $stat) {
            $filtered = \array_filter($stat, function (string $key) : bool {
                return !\is_numeric($key);
            }, ARRAY_FILTER_USE_KEY);
            \ksort($filtered);
            return $filtered;
        };
        $this->assertSame($filter($expected), $filter($actual));
    }
    /**
     * @param array $stat
     *
     * @return string
     */
    private function getPermissionsFromStatus(array $stat) : string
    {
        return \Phabel\Target\Php80\Polyfill::substr(\decoct($stat["mode"]), 1);
    }
}<?php

namespace Amp\File\Test;

final class Fixture
{
    private static $fixtureId;
    /**
     *
     */
    public static function path() : string
    {
        if (empty(self::$fixtureId)) {
            self::$fixtureId = \uniqid('amphp-test-', true);
        }
        return \sys_get_temp_dir() . "/amphp_file_fixture/" . \str_replace("\\", ".", __CLASS__) . self::$fixtureId;
    }
    /**
     *
     */
    public static function init() : void
    {
        $fixtureDir = self::path();
        self::clear();
        if (!\mkdir($fixtureDir, $mode = 0777, $recursive = true)) {
            throw new \RuntimeException("Failed creating temporary test fixture directory: {$fixtureDir}");
        }
        if (!\mkdir($fixtureDir . "/dir", $mode = 0777, $recursive = true)) {
            throw new \RuntimeException("Failed creating temporary test fixture directory");
        }
        if (!\file_put_contents($fixtureDir . "/file", "small")) {
            throw new \RuntimeException("Failed creating temporary test fixture file");
        }
        if (!\symlink($fixtureDir . "/dir", $fixtureDir . "/dirlink")) {
            throw new \RuntimeException("Failed creating temporary test fixture symlink to directory");
        }
        if (!\symlink($fixtureDir . "/file", $fixtureDir . "/filelink")) {
            throw new \RuntimeException("Failed creating temporary test fixture symlink to file");
        }
        if (!\symlink($fixtureDir . "/linkloop", $fixtureDir . "/linkloop")) {
            throw new \RuntimeException("Failed creating temporary test fixture symlink loop");
        }
        if (\extension_loaded('posix')) {
            if (!\posix_mkfifo($fixtureDir . "/fifo", 0777)) {
                throw new \RuntimeException("Failed creating temporary test fixture fifo");
            }
            if (!\symlink($fixtureDir . "/fifo", $fixtureDir . "/fifolink")) {
                throw new \RuntimeException("Failed creating temporary test fixture symlink to file");
            }
        }
    }
    /**
     *
     */
    public static function clear() : void
    {
        \clearstatcache(true);
        $fixtureDir = self::path();
        if (!\file_exists($fixtureDir)) {
            return;
        }
        if (\stripos(\PHP_OS, "win") === 0) {
            \system('rd /Q /S "' . $fixtureDir . '"');
        } else {
            \system('/bin/rm -rf ' . \escapeshellarg($fixtureDir));
        }
        \clearstatcache(true);
    }
}<?php

namespace Amp\Sql;

abstract class ConnectionConfig
{
    const KEY_MAP = ['hostname' => 'host', 'username' => 'user', 'pass' => 'password', 'database' => 'db', 'dbname' => 'db'];
    /** @var string */
    private $host;
    /** @var int */
    private $port;
    /** @var string|null */
    private $user;
    /** @var string|null */
    private $password;
    /** @var string|null */
    private $database;
    /**
     * Parses a connection string into an array of keys and values given.
     *
     * @param string $connectionString
     * @param string[] $keymap Map of alternative key names to canonical key names.
     *
     * @return string[]
     */
    protected static function parseConnectionString(string $connectionString, array $keymap = self::KEY_MAP) : array
    {
        $values = [];
        $params = \explode(";", $connectionString);
        if (\count($params) === 1) {
            // Attempt to explode on a space if no ';' are found.
            $params = \explode(" ", $connectionString);
        }
        foreach ($params as $param) {
            list($key, $value) = \array_map("trim", \explode("=", $param, 2) + [1 => null]);
            if (isset($keymap[$key])) {
                $key = $keymap[$key];
            }
            $values[$key] = $value;
        }
        if (\preg_match('/^(.+):(\\d{1,5})$/', $values["host"] ?? "", $matches)) {
            $values["host"] = $matches[1];
            $values["port"] = $matches[2];
        }
        return $values;
    }
    /**
     *
     */
    public function __construct(string $host, int $port, string $user = null, string $password = null, string $database = null)
    {
        $this->host = $host;
        $this->port = $port;
        $this->user = $user;
        $this->password = $password;
        $this->database = $database;
    }
    /**
     *
     */
    public final function getHost() : string
    {
        return $this->host;
    }
    /**
     *
     */
    public final function withHost(string $host) : self
    {
        $new = clone $this;
        $new->host = $host;
        return $new;
    }
    /**
     *
     */
    public final function getPort() : int
    {
        return $this->port;
    }
    /**
     *
     */
    public final function withPort(int $port) : self
    {
        $new = clone $this;
        $new->port = $port;
        return $new;
    }
    /**
     * @return (string | null)
     */
    public final function getUser()
    {
        return $this->user;
    }
    /**
     *
     */
    public final function withUser(string $user = null) : self
    {
        $new = clone $this;
        $new->user = $user;
        return $new;
    }
    /**
     * @return (string | null)
     */
    public final function getPassword()
    {
        return $this->password;
    }
    /**
     *
     */
    public final function withPassword(string $password = null) : self
    {
        $new = clone $this;
        $new->password = $password;
        return $new;
    }
    /**
     * @return (string | null)
     */
    public final function getDatabase()
    {
        return $this->database;
    }
    /**
     *
     */
    public final function withDatabase(string $database = null) : self
    {
        $new = clone $this;
        $new->database = $database;
        return $new;
    }
}<?php

namespace Amp\Sql;

class PoolError extends \Error
{
}<?php

namespace Amp\Sql;

class FailureException extends \Exception
{
}<?php

namespace Amp\Sql;

interface TransientResource
{
    /**
     * Indicates if the resource is still valid.
     *
     * @return bool
     */
    public function isAlive() : bool;
    /**
     * Get the timestamp of the last usage of this resource.
     *
     * @return int Unix timestamp in seconds.
     */
    public function getLastUsedAt() : int;
}<?php

namespace Amp\Sql;

class TransactionError extends \Error
{
}<?php

namespace Amp\Sql;

class QueryError extends \Error
{
    protected $query = "";
    /**
     *
     */
    public function __construct(string $message, string $query = "", \Throwable $previous = null)
    {
        if ($query !== "") {
            $this->query = $query;
        }
        parent::__construct($message, 0, $previous);
    }
    /**
     *
     */
    public final function getQuery() : string
    {
        return $this->query;
    }
    /**
     *
     */
    public function __toString() : string
    {
        if ($this->query === "") {
            return parent::__toString();
        }
        $msg = $this->message;
        $this->message .= "\nCurrent query was {$this->query}";
        $str = parent::__toString();
        $this->message = $msg;
        return $str;
    }
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Pool extends Link
{
    /**
     * @return Promise<Link>
     */
    public function extractConnection() : Promise;
    /**
     * @return int Total number of active connections in the pool.
     */
    public function getConnectionCount() : int;
    /**
     * @return int Total number of idle connections in the pool.
     */
    public function getIdleConnectionCount() : int;
    /**
     * @return int Maximum number of connections this pool will create.
     */
    public function getConnectionLimit() : int;
    /**
     * @return int Number of seconds a connection may remain idle before it is automatically closed.
     */
    public function getIdleTimeout() : int;
}<?php

namespace Amp\Sql;

class ConnectionException extends FailureException
{
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Connector
{
    /**
     * @param ConnectionConfig $config
     *
     * @return Promise<Connection>
     */
    public function connect(ConnectionConfig $config) : Promise;
}<?php

namespace Amp\Sql;

use Amp\Iterator;
interface ResultSet extends Iterator
{
    /**
     * {@inheritdoc}
     *
     * @return array Map of row names to values.
     */
    public function getCurrent() : array;
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Executor extends TransientResource
{
    /**
     * @param string $sql SQL query to execute.
     *
     * @return Promise<(CommandResult | ResultSet)>
     *
     * @throws FailureException If the operation fails due to unexpected condition.
     * @throws ConnectionException If the connection to the database is lost.
     * @throws QueryError If the operation fails due to an error in the query (such as a syntax error).
     */
    public function query(string $sql) : Promise;
    /**
     * @param string $sql SQL query to prepare.
     *
     * @return Promise<Statement>
     *
     * @throws FailureException If the operation fails due to unexpected condition.
     * @throws ConnectionException If the connection to the database is lost.
     * @throws QueryError If the operation fails due to an error in the query (such as a syntax error).
     */
    public function prepare(string $sql) : Promise;
    /**
     * @param string $sql SQL query to prepare and execute.
     * @param mixed[] $params Query parameters.
     *
     * @return Promise<(CommandResult | ResultSet)>
     *
     * @throws FailureException If the operation fails due to unexpected condition.
     * @throws ConnectionException If the connection to the database is lost.
     * @throws QueryError If the operation fails due to an error in the query (such as a syntax error).
     */
    public function execute(string $sql, array $params = []) : Promise;
    /**
     * Closes the executor. No further queries may be performed.
     */
    public function close();
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Link extends Executor
{
    /**
     * Starts a transaction on a single connection.
     *
     * @param int $isolation Transaction isolation level.
     *
     * @return Promise<Transaction>
     */
    public function beginTransaction(int $isolation = Transaction::ISOLATION_COMMITTED) : Promise;
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Transaction extends Executor
{
    const ISOLATION_UNCOMMITTED = 0;
    const ISOLATION_COMMITTED = 1;
    const ISOLATION_REPEATABLE = 2;
    const ISOLATION_SERIALIZABLE = 4;
    /**
     * @return int
     */
    public function getIsolationLevel() : int;
    /**
     * @return bool True if the transaction is active, false if it has been committed or rolled back.
     */
    public function isActive() : bool;
    /**
     * Commits the transaction and makes it inactive.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function commit() : Promise;
    /**
     * Rolls back the transaction and makes it inactive.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollback() : Promise;
    /**
     * Creates a savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function createSavepoint(string $identifier) : Promise;
    /**
     * Rolls back to the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollbackTo(string $identifier) : Promise;
    /**
     * Releases the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function releaseSavepoint(string $identifier) : Promise;
}<?php

namespace Amp\Sql;

interface CommandResult
{
    /**
     * Returns the number of rows affected by the query.
     *
     * @return int
     */
    public function getAffectedRowCount() : int;
}<?php

namespace Amp\Sql;

use Amp\Promise;
interface Statement extends TransientResource
{
    /**
     * @param mixed[] $params
     *
     * @return Promise<(CommandResult | ResultSet)>
     */
    public function execute(array $params = []) : Promise;
    /**
     * @return string The SQL string used to prepare the statement.
     */
    public function getQuery() : string;
}{
    "name": "amphp/sql",
    "description": "Asynchronous SQL client for Amp.",
    "keywords": [
        "database",
        "db",
        "sql",
        "asynchronous",
        "async"
    ],
    "homepage": "http://amphp.org",
    "license": "MIT",
    "require": {
        "php": ">=7",
        "amphp/amp": "^2"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master",
        "amphp/phpunit-util": "^1",
        "phpunit/phpunit": "^6"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Sql\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Sql\\Test\\": "test"
        }
    },
    "config": {
        "platform": {
            "php": "7.0.0"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "phpunit --coverage-text"
    }
}
<?php

namespace Amp\Sql\Test;

use Amp\PHPUnit\TestCase;
use Amp\Sql\QueryError;
class QueryErrorTest extends TestCase
{
    /**
     * @test
     */
    public function testItPassesQueryAlong()
    {
        $error = new QueryError('error', 'SELECT * FROM foo');
        $this->assertSame('SELECT * FROM foo', $error->getQuery());
        $this->assertStringStartsWith("Amp\\Sql\\QueryError: error\nCurrent query was SELECT * FROM foo", (string) $error);
    }
}<?php

namespace Amp\Websocket;

use Amp\ByteStream\InMemoryStream;
use Amp\ByteStream\InputStream;
use Amp\ByteStream\IteratorStream;
use Amp\ByteStream\StreamException;
use Amp\Coroutine;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Loop;
use Amp\Promise;
use Amp\Socket\EncryptableSocket;
use Amp\Socket\Socket;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
use Amp\Success;
use cash\LRUCache;
use function Amp\call;
use function Amp\getCurrentTime;
final class Rfc6455Client implements Client
{
    /** @var self[] */
    private static $clients = [];
    /** @var int[] */
    private static $bytesReadInLastSecond = [];
    /** @var int[] */
    private static $framesReadInLastSecond = [];
    /** @var Deferred[] */
    private static $rateDeferreds = [];
    /** @var string|null */
    private static $watcher;
    /** @var LRUCache&\IteratorAggregate Least-recently-used cache of next ping (heartbeat) times. */
    private static $heartbeatTimeouts;
    /** @var int Cached current time. */
    private static $now;
    /** @var Options */
    private $options;
    /** @var Socket */
    private $socket;
    /** @var Promise|null */
    private $lastWrite;
    /** @var Promise|null */
    private $lastEmit;
    /** @var bool */
    private $masked;
    /** @var CompressionContext|null */
    private $compressionContext;
    /** @var Emitter|null */
    private $currentMessageEmitter;
    /** @var Deferred|null */
    private $nextMessageDeferred;
    /** @var Message[] */
    private $messages = [];
    /** @var callable[]|null */
    private $onClose = [];
    /** @var ClientMetadata */
    private $metadata;
    /** @var Deferred|null */
    private $closeDeferred;
    /**
     * @param Socket $socket
     * @param Options $options
     * @param bool $masked True for client, false for server.
     * @param (CompressionContext | null) $compression
     */
    public function __construct(Socket $socket, Options $options, bool $masked, ?CompressionContext $compression = null)
    {
        $this->socket = $socket;
        $this->options = $options;
        $this->masked = $masked;
        $this->compressionContext = $compression;
        $this->closeDeferred = new Deferred();
        if (self::$watcher === null) {
            self::$now = getCurrentTime();
            self::$heartbeatTimeouts = new class(\PHP_INT_MAX) extends LRUCache implements \IteratorAggregate
            {
                /**
                 *
                 */
                public function getIterator() : \Iterator
                {
                    yield from $this->data;
                }
            };
            self::$watcher = Loop::repeat(1000, static function () : void {
                self::$now = getCurrentTime();
                self::$bytesReadInLastSecond = [];
                self::$framesReadInLastSecond = [];
                if (!empty(self::$rateDeferreds)) {
                    /** @psalm-suppress PossiblyNullArgument */
                    Loop::unreference(self::$watcher);
                    $rateDeferreds = self::$rateDeferreds;
                    self::$rateDeferreds = [];
                    foreach ($rateDeferreds as $deferred) {
                        $deferred->resolve();
                    }
                }
                foreach (self::$heartbeatTimeouts as $clientId => $expiryTime) {
                    if ($expiryTime >= self::$now) {
                        break;
                    }
                    $client = self::$clients[$clientId];
                    self::$heartbeatTimeouts->put($clientId, self::$now + $client->options->getHeartbeatPeriod() * 1000);
                    if ($client->getUnansweredPingCount() > $client->options->getQueuedPingLimit()) {
                        $client->close(Code::POLICY_VIOLATION, 'Exceeded unanswered PING limit');
                        continue;
                    }
                    $client->ping();
                }
            });
            Loop::unreference(self::$watcher);
        }
        $this->metadata = new ClientMetadata(self::$now, $compression !== null);
        self::$clients[$this->metadata->id] = $this;
        if ($this->options->isHeartbeatEnabled()) {
            self::$heartbeatTimeouts->put($this->metadata->id, self::$now + $this->options->getHeartbeatPeriod() * 1000);
        }
        Promise\rethrow(new Coroutine($this->read()));
    }
    /**
     *
     */
    public function receive() : Promise
    {
        if ($this->nextMessageDeferred) {
            throw new \Error('Await the previous promise returned from receive() before calling receive() again.');
        }
        // There might be messages already buffered and a close frame already received
        if ($this->messages) {
            $message = \reset($this->messages);
            unset($this->messages[\key($this->messages)]);
            return new Success($message);
        }
        if ($this->metadata->closedAt) {
            return new Success();
        }
        $this->nextMessageDeferred = new Deferred();
        return $this->nextMessageDeferred->promise();
    }
    /**
     *
     */
    public function getId() : int
    {
        return $this->metadata->id;
    }
    /**
     *
     */
    public function getUnansweredPingCount() : int
    {
        return $this->metadata->pingCount - $this->metadata->pongCount;
    }
    /**
     *
     */
    public function isConnected() : bool
    {
        return !$this->metadata->closedAt;
    }
    /**
     *
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->socket->getLocalAddress();
    }
    /**
     *
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->socket->getRemoteAddress();
    }
    /**
     *
     */
    public function getTlsInfo() : ?TlsInfo
    {
        return $this->socket instanceof EncryptableSocket ? $this->socket->getTlsInfo() : null;
    }
    /**
     *
     */
    public function getCloseCode() : int
    {
        if ($this->metadata->closeCode === null) {
            throw new \Error('The client has not closed');
        }
        return $this->metadata->closeCode;
    }
    /**
     *
     */
    public function getCloseReason() : string
    {
        if ($this->metadata->closeReason === null) {
            throw new \Error('The client has not closed');
        }
        return $this->metadata->closeReason;
    }
    /**
     *
     */
    public function isClosedByPeer() : bool
    {
        if (!$this->metadata->closedAt) {
            throw new \Error('The client has not closed');
        }
        return $this->metadata->closedByPeer;
    }
    /**
     *
     */
    public function getOptions() : Options
    {
        return $this->options;
    }
    /**
     *
     */
    public function getInfo() : ClientMetadata
    {
        return clone $this->metadata;
    }
    /**
     *
     */
    private function read() : \Generator
    {
        $maxFramesPerSecond = $this->options->getFramesPerSecondLimit();
        $maxBytesPerSecond = $this->options->getBytesPerSecondLimit();
        $heartbeatEnabled = $this->options->isHeartbeatEnabled();
        $heartbeatPeriod = $this->options->getHeartbeatPeriod() * 1000;
        $parser = $this->parser();
        try {
            while (($chunk = (yield $this->socket->read())) !== null) {
                if ($chunk === '') {
                    continue;
                }
                $this->metadata->lastReadAt = self::$now;
                $this->metadata->bytesRead += \strlen($chunk);
                self::$bytesReadInLastSecond[$this->metadata->id] = (self::$bytesReadInLastSecond[$this->metadata->id] ?? 0) + \strlen($chunk);
                if ($heartbeatEnabled) {
                    self::$heartbeatTimeouts->put($this->metadata->id, self::$now + $heartbeatPeriod);
                }
                $parser->send($chunk);
                $chunk = '';
                // Free memory from last chunk read.
                if ((self::$framesReadInLastSecond[$this->metadata->id] ?? 0) >= $maxFramesPerSecond || self::$bytesReadInLastSecond[$this->metadata->id] >= $maxBytesPerSecond) {
                    /** @psalm-suppress PossiblyNullArgument */
                    Loop::reference(self::$watcher);
                    // Reference watcher to keep loop running until rate limit released.
                    self::$rateDeferreds[$this->metadata->id] = $deferred = new Deferred();
                    (yield $deferred->promise());
                }
                if ($this->lastEmit && !$this->metadata->closedAt) {
                    (yield $this->lastEmit);
                }
            }
        } catch (\Throwable $exception) {
            $message = 'TCP connection closed with exception: ' . $exception->getMessage();
        }
        if ($this->closeDeferred !== null) {
            $deferred = $this->closeDeferred;
            $this->closeDeferred = null;
            $deferred->resolve();
        }
        if (!$this->metadata->closedAt) {
            $this->metadata->closedByPeer = true;
            $this->close(Code::ABNORMAL_CLOSE, $message ?? 'TCP connection closed unexpectedly');
        }
    }
    /**
     *
     */
    private function onData(int $opcode, string $data, bool $terminated) : void
    {
        // Ignore further data received after initiating close.
        if ($this->metadata->closedAt) {
            return;
        }
        $this->metadata->lastDataReadAt = self::$now;
        ++$this->metadata->framesRead;
        self::$framesReadInLastSecond[$this->metadata->id] = (self::$framesReadInLastSecond[$this->metadata->id] ?? 0) + 1;
        if (!$this->currentMessageEmitter) {
            if ($opcode === Opcode::CONT) {
                $this->onError(Code::PROTOCOL_ERROR, 'Illegal CONTINUATION opcode; initial message payload frame must be TEXT or BINARY');
                return;
            }
            if ($terminated) {
                $stream = new InMemoryStream($data);
                ++$this->metadata->messagesRead;
            } else {
                $this->currentMessageEmitter = new Emitter();
                $stream = new IteratorStream($this->currentMessageEmitter->iterate());
            }
            if ($opcode === Opcode::BIN) {
                $message = Message::fromBinary($stream);
            } else {
                $message = Message::fromText($stream);
            }
            if ($this->nextMessageDeferred) {
                $deferred = $this->nextMessageDeferred;
                $this->nextMessageDeferred = null;
                $deferred->resolve($message);
            } else {
                $this->messages[] = $message;
            }
            if ($terminated) {
                return;
            }
        } elseif ($opcode !== Opcode::CONT) {
            $this->onError(Code::PROTOCOL_ERROR, 'Illegal data type opcode after unfinished previous data type frame; opcode MUST be CONTINUATION');
            return;
        }
        $promise = $this->currentMessageEmitter->emit($data);
        $this->lastEmit = $this->nextMessageDeferred ? null : $promise;
        if ($terminated) {
            $emitter = $this->currentMessageEmitter;
            $this->currentMessageEmitter = null;
            $emitter->complete();
            ++$this->metadata->messagesRead;
        }
    }
    /**
     *
     */
    private function onControlFrame(int $opcode, string $data) : void
    {
        // Close already completed, so ignore any further data from the parser.
        if ($this->metadata->closedAt && $this->closeDeferred === null) {
            return;
        }
        ++$this->metadata->framesRead;
        self::$framesReadInLastSecond[$this->metadata->id] = (self::$framesReadInLastSecond[$this->metadata->id] ?? 0) + 1;
        switch ($opcode) {
            case Opcode::CLOSE:
                if ($this->closeDeferred) {
                    $deferred = $this->closeDeferred;
                    $this->closeDeferred = null;
                    $deferred->resolve();
                }
                if ($this->metadata->closedAt) {
                    break;
                }
                $this->metadata->closedByPeer = true;
                $length = \strlen($data);
                if ($length === 0) {
                    $code = Code::NONE;
                    $reason = '';
                } elseif ($length < 2) {
                    $code = Code::PROTOCOL_ERROR;
                    $reason = 'Close code must be two bytes';
                } else {
                    $code = \current(\unpack('n', \Phabel\Target\Php80\Polyfill::substr($data, 0, 2)));
                    $reason = \Phabel\Target\Php80\Polyfill::substr($data, 2);
                    if ($code < 1000 || $code >= 1004 && $code <= 1006 || $code >= 1014 && $code <= 1015 || $code >= 1016 && $code <= 1999 || $code >= 2000 && $code <= 2999 || $code >= 5000) {
                        $code = Code::PROTOCOL_ERROR;
                        $reason = 'Invalid close code';
                    } elseif ($this->options->isValidateUtf8() && !\preg_match('//u', $reason)) {
                        $code = Code::INCONSISTENT_FRAME_DATA_TYPE;
                        $reason = 'Close reason must be valid UTF-8';
                    }
                }
                $this->close($code, $reason);
                break;
            case Opcode::PING:
                $this->write($data, Opcode::PONG);
                break;
            case Opcode::PONG:
                if (!\preg_match('/^[1-9][0-9]*$/', $data)) {
                    // Ignore pong payload that is not an integer.
                    break;
                }
                // We need a min() here, else someone might just send a pong frame with a very high pong count and
                // leave TCP connection in open state... Then we'd accumulate connections which never are cleaned up...
                $this->metadata->pongCount = \min($this->metadata->pingCount, (int) $data);
                break;
        }
    }
    /**
     *
     */
    private function onError(int $code, string $reason) : void
    {
        $this->close($code, $reason);
    }
    /**
     *
     */
    public function send(string $data) : Promise
    {
        \assert((bool) \preg_match('//u', $data), 'Text data must be UTF-8');
        return $this->lastWrite = new Coroutine($this->sendData($data, Opcode::TEXT));
    }
    /**
     *
     */
    public function sendBinary(string $data) : Promise
    {
        return $this->lastWrite = new Coroutine($this->sendData($data, Opcode::BIN));
    }
    /**
     *
     */
    public function stream(InputStream $stream) : Promise
    {
        return $this->lastWrite = new Coroutine($this->sendStream($stream, Opcode::TEXT));
    }
    /**
     *
     */
    public function streamBinary(InputStream $stream) : Promise
    {
        return $this->lastWrite = new Coroutine($this->sendStream($stream, Opcode::BIN));
    }
    /**
     *
     */
    public function ping() : Promise
    {
        $this->metadata->lastHeartbeatAt = self::$now;
        ++$this->metadata->pingCount;
        return $this->write((string) $this->metadata->pingCount, Opcode::PING);
    }
    /**
     *
     */
    private function sendData(string $data, int $opcode) : \Generator
    {
        if ($this->lastWrite) {
            (yield $this->lastWrite);
        }
        ++$this->metadata->messagesSent;
        $this->metadata->lastDataSentAt = self::$now;
        $rsv = 0;
        $compress = false;
        if ($this->compressionContext && $opcode === Opcode::TEXT && \strlen($data) > $this->compressionContext->getCompressionThreshold()) {
            $rsv |= $this->compressionContext->getRsv();
            $compress = true;
        }
        try {
            if (\strlen($data) > $this->options->getFrameSplitThreshold()) {
                $length = \strlen($data);
                $slices = (int) \ceil($length / $this->options->getFrameSplitThreshold());
                $length = (int) \ceil($length / $slices);
                for ($i = 0; $i < $slices - 1; ++$i) {
                    $chunk = \Phabel\Target\Php80\Polyfill::substr($data, $length * $i, $length);
                    if ($compress) {
                        /** @psalm-suppress PossiblyNullReference */
                        $chunk = $this->compressionContext->compress($chunk, false);
                    }
                    (yield $this->write($chunk, $opcode, $rsv, false));
                    $opcode = Opcode::CONT;
                    $rsv = 0;
                    // RSV must be 0 in continuation frames.
                }
                $data = \Phabel\Target\Php80\Polyfill::substr($data, $length * $i, $length);
            }
            if ($compress) {
                /** @psalm-suppress PossiblyNullReference */
                $data = $this->compressionContext->compress($data, true);
            }
            (yield $this->write($data, $opcode, $rsv, true));
        } catch (StreamException $exception) {
            $code = Code::ABNORMAL_CLOSE;
            $reason = 'Writing to the client failed';
            (yield $this->close($code, $reason));
            throw new ClosedException('Client unexpectedly closed', $code, $reason);
        }
    }
    /**
     *
     */
    private function sendStream(InputStream $stream, int $opcode) : \Generator
    {
        if ($this->lastWrite) {
            (yield $this->lastWrite);
        }
        $rsv = 0;
        $compress = false;
        if ($this->compressionContext && $opcode === Opcode::TEXT) {
            $rsv |= $this->compressionContext->getRsv();
            $compress = true;
        }
        try {
            $buffer = (yield $stream->read());
            if ($buffer === null) {
                return (yield $this->write('', $opcode, 0, true));
            }
            $streamThreshold = $this->options->getStreamThreshold();
            while (($chunk = (yield $stream->read())) !== null) {
                if ($chunk === '') {
                    continue;
                }
                if (\strlen($buffer) < $streamThreshold) {
                    $buffer .= $chunk;
                    continue;
                }
                if ($compress) {
                    /** @psalm-suppress PossiblyNullReference */
                    $buffer = $this->compressionContext->compress($buffer, false);
                }
                (yield $this->write($buffer, $opcode, $rsv, false));
                $opcode = Opcode::CONT;
                $rsv = 0;
                // RSV must be 0 in continuation frames.
                $buffer = $chunk;
            }
            if ($compress) {
                /** @psalm-suppress PossiblyNullReference */
                $buffer = $this->compressionContext->compress($buffer, true);
            }
            (yield $this->write($buffer, $opcode, $rsv, true));
        } catch (StreamException $exception) {
            $code = Code::ABNORMAL_CLOSE;
            $reason = 'Writing to the client failed';
            (yield $this->close($code, $reason));
            throw new ClosedException('Client unexpectedly closed', $code, $reason);
        } catch (\Throwable $exception) {
            (yield $this->close(Code::UNEXPECTED_SERVER_ERROR, 'Error while reading message data'));
            throw $exception;
        }
    }
    /**
     *
     */
    private function write(string $data, int $opcode, int $rsv = 0, bool $isFinal = true) : Promise
    {
        if ($this->metadata->closedAt) {
            return new Success(0);
        }
        $frame = $this->compile($data, $opcode, $rsv, $isFinal);
        ++$this->metadata->framesSent;
        $this->metadata->bytesSent += \strlen($frame);
        $this->metadata->lastSentAt = self::$now;
        return $this->socket->write($frame);
    }
    /**
     *
     */
    private function compile(string $data, int $opcode, int $rsv, bool $isFinal) : string
    {
        $length = \strlen($data);
        $w = \chr((int) $isFinal << 7 | $rsv << 4 | $opcode);
        $maskFlag = $this->masked ? 0x80 : 0;
        if ($length > 0xffff) {
            $w .= \chr(0x7f | $maskFlag) . \pack('J', $length);
        } elseif ($length > 0x7d) {
            $w .= \chr(0x7e | $maskFlag) . \pack('n', $length);
        } else {
            $w .= \chr($length | $maskFlag);
        }
        if ($this->masked) {
            $mask = \random_bytes(4);
            return $w . $mask . ($data ^ \str_repeat($mask, $length + 3 >> 2));
        }
        return $w . $data;
    }
    /**
     *
     */
    public function close(int $code = Code::NORMAL_CLOSE, string $reason = '') : Promise
    {
        if ($this->metadata->closedAt) {
            return new Success([$this->metadata->closeCode, $this->metadata->closeReason]);
        }
        return call(function () use($code, $reason) {
            try {
                \assert($code !== Code::NONE || $reason === '');
                $promise = $this->write($code !== Code::NONE ? \pack('n', $code) . $reason : '', Opcode::CLOSE);
                $this->metadata->closedAt = self::$now;
                $this->metadata->closeCode = $code;
                $this->metadata->closeReason = $reason;
                if ($this->currentMessageEmitter) {
                    $emitter = $this->currentMessageEmitter;
                    $this->currentMessageEmitter = null;
                    $emitter->fail(new ClosedException('Connection closed while streaming message body', $code, $reason));
                }
                if ($this->nextMessageDeferred) {
                    $deferred = $this->nextMessageDeferred;
                    $this->nextMessageDeferred = null;
                    switch ($code) {
                        case Code::NORMAL_CLOSE:
                        case Code::NONE:
                            $deferred->resolve();
                            break;
                        default:
                            $deferred->fail(new ClosedException('Connection closed abnormally while awaiting message', $code, $reason));
                            break;
                    }
                }
                (yield $promise);
                // Wait for writing close frame to complete.
                if ($this->closeDeferred !== null) {
                    // Wait for peer close frame for configured number of seconds.
                    (yield Promise\timeout($this->closeDeferred->promise(), $this->options->getClosePeriod() * 1000));
                }
            } catch (\Throwable $exception) {
                // Failed to write close frame or to receive response frame, but we were disconnecting anyway.
            }
            $this->socket->close();
            $this->lastWrite = null;
            $this->lastEmit = null;
            $onClose = $this->onClose;
            $this->onClose = null;
            if ($onClose !== null) {
                foreach ($onClose as $callback) {
                    Promise\rethrow(call($callback, $this, $code, $reason));
                }
            }
            unset(self::$clients[$this->metadata->id]);
            self::$heartbeatTimeouts->remove($this->metadata->id);
            if (empty(self::$clients)) {
                /** @psalm-suppress PossiblyNullArgument */
                Loop::cancel(self::$watcher);
                self::$watcher = null;
                self::$heartbeatTimeouts = null;
            }
            return [$this->metadata->closeCode, $this->metadata->closeReason];
        });
    }
    /**
     *
     */
    public function onClose(callable $callback) : void
    {
        if ($this->onClose === null) {
            Promise\rethrow(call($callback, $this, $this->metadata->closeCode, $this->metadata->closeReason));
            return;
        }
        $this->onClose[] = $callback;
    }
    /**
     * A stateful generator websocket frame parser.
     *
     * @return \Generator
     */
    private function parser() : \Generator
    {
        $frameSizeLimit = $this->options->getFrameSizeLimit();
        $messageSizeLimit = $this->options->getMessageSizeLimit();
        $textOnly = $this->options->isTextOnly();
        $doUtf8Validation = $validateUtf8 = $this->options->isValidateUtf8();
        $compressionContext = $this->compressionContext;
        $compressedFlag = $compressionContext ? $compressionContext->getRsv() : 0;
        $dataMsgBytesRecd = 0;
        $savedBuffer = '';
        $compressed = false;
        $buffer = yield;
        $offset = 0;
        $bufferSize = \strlen($buffer);
        while (true) {
            $payload = '';
            // Free memory from last frame payload.
            while ($bufferSize < 2) {
                $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset);
                $offset = 0;
                $buffer .= yield;
                $bufferSize = \strlen($buffer);
            }
            $firstByte = \ord($buffer[$offset]);
            $secondByte = \ord($buffer[$offset + 1]);
            $offset += 2;
            $bufferSize -= 2;
            $final = (bool) ($firstByte & 0b10000000);
            $rsv = ($firstByte & 0b1110000) >> 4;
            $opcode = $firstByte & 0b1111;
            $isMasked = (bool) ($secondByte & 0b10000000);
            $maskingKey = '';
            $frameLength = $secondByte & 0b1111111;
            if ($opcode >= 3 && $opcode <= 7) {
                $this->onError(Code::PROTOCOL_ERROR, 'Use of reserved non-control frame opcode');
                return;
            }
            if ($opcode >= 11 && $opcode <= 15) {
                $this->onError(Code::PROTOCOL_ERROR, 'Use of reserved control frame opcode');
                return;
            }
            $isControlFrame = $opcode >= 0x8;
            if ($isControlFrame || $opcode === Opcode::CONT) {
                // Control and continuation frames
                if ($rsv !== 0) {
                    $this->onError(Code::PROTOCOL_ERROR, 'RSV must be 0 for control or continuation frames');
                    return;
                }
            } else {
                // Text and binary frames
                if ($rsv !== 0 && (!$compressionContext || $rsv & ~$compressedFlag)) {
                    $this->onError(Code::PROTOCOL_ERROR, 'Invalid RSV value for negotiated extensions');
                    return;
                }
                $doUtf8Validation = $validateUtf8 && $opcode === Opcode::TEXT;
                $compressed = (bool) ($rsv & $compressedFlag);
            }
            if ($frameLength === 0x7e) {
                while ($bufferSize < 2) {
                    $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset);
                    $offset = 0;
                    $buffer .= yield;
                    $bufferSize = \strlen($buffer);
                }
                $frameLength = \unpack('n', $buffer[$offset] . $buffer[$offset + 1])[1];
                $offset += 2;
                $bufferSize -= 2;
            } elseif ($frameLength === 0x7f) {
                while ($bufferSize < 8) {
                    $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset);
                    $offset = 0;
                    $buffer .= yield;
                    $bufferSize = \strlen($buffer);
                }
                $lengthLong32Pair = \unpack('N2', \Phabel\Target\Php80\Polyfill::substr($buffer, $offset, 8));
                $offset += 8;
                $bufferSize -= 8;
                if (\PHP_INT_MAX === 0x7fffffff) {
                    if ($lengthLong32Pair[1] !== 0 || $lengthLong32Pair[2] < 0) {
                        $this->onError(Code::MESSAGE_TOO_LARGE, 'Received payload exceeds maximum allowable size');
                        return;
                    }
                    $frameLength = $lengthLong32Pair[2];
                } else {
                    $frameLength = $lengthLong32Pair[1] << 32 | $lengthLong32Pair[2];
                    if ($frameLength < 0) {
                        $this->onError(Code::PROTOCOL_ERROR, 'Most significant bit of 64-bit length field set');
                        return;
                    }
                }
            }
            if ($frameLength > 0 && $isMasked === $this->masked) {
                $this->onError(Code::PROTOCOL_ERROR, 'Payload mask error');
                return;
            }
            if ($isControlFrame) {
                if (!$final) {
                    $this->onError(Code::PROTOCOL_ERROR, 'Illegal control frame fragmentation');
                    return;
                }
                if ($frameLength > 125) {
                    $this->onError(Code::PROTOCOL_ERROR, 'Control frame payload must be of maximum 125 bytes or less');
                    return;
                }
            }
            if ($frameSizeLimit && $frameLength > $frameSizeLimit) {
                $this->onError(Code::MESSAGE_TOO_LARGE, 'Received payload exceeds maximum allowable size');
                return;
            }
            if ($messageSizeLimit && $frameLength + $dataMsgBytesRecd > $messageSizeLimit) {
                $this->onError(Code::MESSAGE_TOO_LARGE, 'Received payload exceeds maximum allowable size');
                return;
            }
            if ($textOnly && $opcode === Opcode::BIN) {
                $this->onError(Code::UNACCEPTABLE_TYPE, 'BINARY opcodes (0x02) not accepted');
                return;
            }
            if ($isMasked) {
                while ($bufferSize < 4) {
                    $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset);
                    $offset = 0;
                    $buffer .= yield;
                    $bufferSize = \strlen($buffer);
                }
                $maskingKey = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset, 4);
                $offset += 4;
                $bufferSize -= 4;
            }
            while ($bufferSize < $frameLength) {
                $chunk = yield;
                $buffer .= $chunk;
                $bufferSize += \strlen($chunk);
            }
            $payload = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset, $frameLength);
            $buffer = \Phabel\Target\Php80\Polyfill::substr($buffer, $offset + $frameLength);
            $offset = 0;
            $bufferSize = \strlen($buffer);
            if ($isMasked) {
                // This is memory hungry but it's ~70x faster than iterating byte-by-byte
                // over the masked string. Deal with it; manual iteration is untenable.
                /** @psalm-suppress InvalidOperand String operands expected. */
                $payload ^= \str_repeat($maskingKey, $frameLength + 3 >> 2);
            }
            if ($isControlFrame) {
                $this->onControlFrame($opcode, $payload);
                continue;
            }
            $dataMsgBytesRecd += $frameLength;
            if ($savedBuffer !== '') {
                $payload = $savedBuffer . $payload;
                $savedBuffer = '';
            }
            if ($compressed) {
                /** @psalm-suppress PossiblyNullReference */
                $payload = $compressionContext->decompress($payload, $final);
                if ($payload === null) {
                    // Decompression failed.
                    $this->onError(Code::PROTOCOL_ERROR, 'Invalid compressed data');
                    return;
                }
            }
            if ($doUtf8Validation) {
                if ($final) {
                    $valid = \preg_match('//u', $payload);
                } else {
                    for ($i = 0; !($valid = \preg_match('//u', $payload)); $i++) {
                        $savedBuffer = \Phabel\Target\Php80\Polyfill::substr($payload, -1) . $savedBuffer;
                        $payload = \Phabel\Target\Php80\Polyfill::substr($payload, 0, -1);
                        if ($i === 3) {
                            // Remove a maximum of three bytes
                            break;
                        }
                    }
                }
                /** @psalm-suppress PossiblyUndefinedVariable Defined in either condition above. */
                if (!$valid) {
                    $this->onError(Code::INCONSISTENT_FRAME_DATA_TYPE, 'Invalid TEXT data; UTF-8 required');
                    return;
                }
            }
            if ($final) {
                $dataMsgBytesRecd = 0;
            }
            $this->onData($opcode, $payload, $final);
        }
    }
}<?php

namespace Amp\Websocket;

final class Rfc7692CompressionFactory implements CompressionContextFactory
{
    /**
     *
     */
    public function fromClientHeader(string $headerIn, ?string &$headerOut) : ?CompressionContext
    {
        return Rfc7692Compression::fromClientHeader($headerIn, $headerOut);
    }
    /**
     *
     */
    public function fromServerHeader(string $header) : ?CompressionContext
    {
        return Rfc7692Compression::fromServerHeader($header);
    }
    /**
     *
     */
    public function createRequestHeader() : string
    {
        return Rfc7692Compression::createRequestHeader();
    }
}<?php

namespace Amp\Websocket;

interface CompressionContextFactory
{
    /**
     * Create a compression context from a header received from a websocket client request.
     *
     * @param string $headerIn Header from request.
     * @param string $headerOut Sec-Websocket-Extension response header.
     *
     * @return (CompressionContext | null)
     */
    public function fromClientHeader(string $headerIn, ?string &$headerOut) : ?CompressionContext;
    /**
     * Create a compression context from a header received from a websocket server response.
     *
     * @param string $header Header from response.
     *
     * @return (CompressionContext | null)
     */
    public function fromServerHeader(string $header) : ?CompressionContext;
    /**
     * @return string Header value for Sec-Websocket-Extension header.
     */
    public function createRequestHeader() : string;
}<?php

namespace Amp\Websocket;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\Payload;
use Amp\Promise;
/**
 * This class allows streamed and buffered access to the websocket message.
 */
final class Message implements InputStream
{
    /** @var Payload */
    private $stream;
    /** @var bool */
    private $binary;
    /**
     * Create a Message from a UTF-8 text stream.
     *
     * @param InputStream $stream UTF-8 text stream.
     *
     * @return self
     */
    public static function fromText(InputStream $stream) : self
    {
        return new self($stream, false);
    }
    /**
     * Create a Message from a binary stream.
     *
     * @param InputStream $stream Binary stream.
     *
     * @return self
     */
    public static function fromBinary(InputStream $stream) : self
    {
        return new self($stream, true);
    }
    /**
     *
     */
    private function __construct(InputStream $stream, bool $binary)
    {
        $this->stream = new Payload($stream);
        $this->binary = $binary;
    }
    /**
     * @return bool True if the message is UTF-8 text, false if it is binary.
     *
     * @see Message::isBinary()
     */
    public function isText() : bool
    {
        return !$this->binary;
    }
    /**
     * @return bool True if the message is binary, false if it is UTF-8 text.
     *
     * @see Message::isText()
     */
    public function isBinary() : bool
    {
        return $this->binary;
    }
    /**
     *
     */
    public function read() : Promise
    {
        return $this->stream->read();
    }
    /**
     *
     */
    public function buffer() : Promise
    {
        return $this->stream->buffer();
    }
}<?php

namespace Amp\Websocket;

final class Options
{
    /** @var int */
    private $streamThreshold = 32768;
    // 32KB
    /** @var int */
    private $frameSplitThreshold = 32768;
    // 32KB
    /** @var int */
    private $bytesPerSecondLimit = 1048576;
    // 1MB
    /** @var int */
    private $framesPerSecondLimit = 100;
    /** @var int */
    private $frameSizeLimit = 2097152;
    // 2MB
    /** @var int */
    private $messageSizeLimit = 10485760;
    // 10MB
    /** @var bool */
    private $textOnly = false;
    /** @var bool */
    private $validateUtf8 = true;
    /** @var int */
    private $closePeriod = 3;
    /** @var bool */
    private $compressionEnabled = false;
    /** @var bool */
    private $heartbeatEnabled = true;
    /** @var int */
    private $heartbeatPeriod = 10;
    /** @var int */
    private $queuedPingLimit = 3;
    /**
     * Creates an Options object with values as documented on the accessor methods.
     *
     * @return self
     */
    public static function createServerDefault() : self
    {
        return new self();
        // Initial parameter values already tuned for servers.
    }
    /**
    * Creates an Options object with values as documented on the accessor methods except for the changes below.
    *
    * Compression is enabled if the zlib extension is installed.
    Bytes per second limit is set to PHP_INT_MAX (effectively removing the limit).
    Frames per second limit is set to PHP_INI_MAX (effectively removing the limit).
    Message size limit is set to 1 GB.
    Frame size limit is set to 100 MB.
    *
    * @return self
    */
    public static function createClientDefault() : self
    {
        $options = new self();
        $options->bytesPerSecondLimit = \PHP_INT_MAX;
        $options->framesPerSecondLimit = \PHP_INT_MAX;
        $options->messageSizeLimit = 2 ** 30;
        // 1 GB
        $options->frameSizeLimit = 2 ** 20 * 100;
        // 100 MB
        if (\extension_loaded('zlib')) {
            $options->compressionEnabled = true;
        }
        return $options;
    }
    /**
     *
     */
    private function __construct()
    {
        // Private constructor to require use of named constructors.
    }
    /**
    * @return int Number of bytes that will be buffered when streaming a message
    body before sending a frame.
    */
    public function getStreamThreshold() : int
    {
        return $this->streamThreshold;
    }
    /**
    * @param int $streamThreshold Number of bytes that will be buffered when
    streaming a message body before sending a frame. Default is 32768 (32KB)
    *
    * @return self
    *
    * @throws \Error if the number is less than 1.
    */
    public function withStreamThreshold(int $streamThreshold) : self
    {
        if ($streamThreshold < 1) {
            throw new \Error('$streamThreshold must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->streamThreshold = $streamThreshold;
        return $clone;
    }
    /**
    * @return int If a message exceeds this number of bytes, it is split into
    multiple frames, each no bigger than this value.
    */
    public function getFrameSplitThreshold() : int
    {
        return $this->frameSplitThreshold;
    }
    /**
    * @param int $frameSplitThreshold If a message exceeds this number of bytes,
    it is split into multiple frames, each no bigger than this value.
    Default is 32768 (32KB)
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withFrameSplitThreshold(int $frameSplitThreshold) : self
    {
        if ($frameSplitThreshold < 1) {
            throw new \Error('$frameSplitThreshold must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->frameSplitThreshold = $frameSplitThreshold;
        return $clone;
    }
    /**
    * @return int Maximum frame size that can be received from the peer. If a
    larger frame is received, the connection is ended with a POLICY_VIOLATION.
    */
    public function getFrameSizeLimit() : int
    {
        return $this->frameSizeLimit;
    }
    /**
    * @param int $frameSizeLimit Maximum frame size that can be received from the peer.
    If a larger frame is received, the connection is ended with a POLICY_VIOLATION.
    Default is 2097152 (2MB)
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withFrameSizeLimit(int $frameSizeLimit) : self
    {
        if ($frameSizeLimit < 1) {
            throw new \Error('$frameSizeLimit must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->frameSizeLimit = $frameSizeLimit;
        return $clone;
    }
    /**
     * @return int Maximum number of bytes the peer can send per second before being throttled.
     */
    public function getBytesPerSecondLimit() : int
    {
        return $this->bytesPerSecondLimit;
    }
    /**
    * @param int $bytesPerSecond Maximum number of bytes the peer can send per
    second before being throttled. Default is 1048576 (1MB)
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withBytesPerSecondLimit(int $bytesPerSecond) : self
    {
        if ($bytesPerSecond < 1) {
            throw new \Error('$bytesPerSecond must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->bytesPerSecondLimit = $bytesPerSecond;
        return $clone;
    }
    /**
     * @return int Maximum number of frames the peer can send per second before being throttled.
     */
    public function getFramesPerSecondLimit() : int
    {
        return $this->framesPerSecondLimit;
    }
    /**
    * @param int $framesPerSecond Maximum number of frames the peer can send per
    second before being throttled.
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withFramesPerSecondLimit(int $framesPerSecond) : self
    {
        if ($framesPerSecond < 1) {
            throw new \Error('$bytesPerSecond must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->framesPerSecondLimit = $framesPerSecond;
        return $clone;
    }
    /**
    * @return int Maximum message size that can be received from the remote endpoint.
    If a larger message is received, the connection is ended with a POLICY_VIOLATION.
    */
    public function getMessageSizeLimit() : int
    {
        return $this->messageSizeLimit;
    }
    /**
    * @param int $messageSizeLimit Maximum message size that can be received
    from the remote endpoint. If a larger message is received, the connection
    is ended with a POLICY_VIOLATION. Default is 10485760 (10MB)
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withMessageSizeLimit(int $messageSizeLimit) : self
    {
        if ($messageSizeLimit < 1) {
            throw new \Error('$messageSizeLimit must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->messageSizeLimit = $messageSizeLimit;
        return $clone;
    }
    /**
     * @return bool If true ends the connection if a binary frame is received.
     */
    public function isTextOnly() : bool
    {
        return $this->textOnly;
    }
    /**
     * @param bool $textOnly If true ends the connection if a binary frame is received.
     *
     * @return self
     */
    public function withTextOnly(bool $textOnly) : self
    {
        $clone = clone $this;
        $clone->textOnly = $textOnly;
        return $clone;
    }
    /**
     * @return bool If true validates that all text received and sent is UTF-8.
     */
    public function isValidateUtf8() : bool
    {
        return $this->validateUtf8;
    }
    /**
     * @param bool $validateUtf8 If true validates that all text received and sent is UTF-8.
     *
     * @return self
     */
    public function withValidateUtf8(bool $validateUtf8) : self
    {
        $clone = clone $this;
        $clone->validateUtf8 = $validateUtf8;
        return $clone;
    }
    /**
     * @return int Number of seconds to wait to receive peer close frame.
     */
    public function getClosePeriod() : int
    {
        return $this->closePeriod;
    }
    /**
    * @param int $closePeriod Number of seconds to wait to receive peer close
    frame. Default is 3.
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withClosePeriod(int $closePeriod) : self
    {
        if ($closePeriod < 1) {
            throw new \Error('$closePeriod must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->closePeriod = $closePeriod;
        return $clone;
    }
    /**
     * @return bool Whether to request or accept per-message compression.
     */
    public function isCompressionEnabled() : bool
    {
        return $this->compressionEnabled;
    }
    /**
     * @return self Enables requesting or accepting per-message compression.
     */
    public function withCompression() : self
    {
        $clone = clone $this;
        $clone->compressionEnabled = true;
        return $clone;
    }
    /**
     * @return self Disables requesting or accepting per-message compression.
     */
    public function withoutCompression() : self
    {
        $clone = clone $this;
        $clone->compressionEnabled = false;
        return $clone;
    }
    /**
    * @return bool If enabled, sends a ping frame to the peer every X seconds (determined
    by the heartbeat period) if there is no other activity on the connection.
    */
    public function isHeartbeatEnabled() : bool
    {
        return $this->heartbeatEnabled;
    }
    /**
    * @return self Enables heartbeat; If enabled, sends a ping frame to the
    peer every X seconds (determined by the heartbeat period) if there
    is no other activity on the connection.
    */
    public function withHeartbeat() : self
    {
        $clone = clone $this;
        $clone->heartbeatEnabled = true;
        return $clone;
    }
    /**
    * @return self Disables heartbeat; If disabled, will not periodically send
    a ping frame to the peer during timetrames of inactivity on the connection.
    */
    public function withoutHeartbeat() : self
    {
        $clone = clone $this;
        $clone->heartbeatEnabled = false;
        return $clone;
    }
    /**
     * @return int Duration in seconds between pings or other connection activity if the heartbeat is enabled.
     */
    public function getHeartbeatPeriod() : int
    {
        return $this->heartbeatPeriod;
    }
    /**
    * @param int $heartbeatPeriod Duration in seconds between pings or other
    connection activity if the heartbeat is enabled. Default is 10.
    *
    * @return self
    *
    * @throws \Error if number is less than 1.
    */
    public function withHeartbeatPeriod(int $heartbeatPeriod) : self
    {
        if ($heartbeatPeriod < 1) {
            throw new \Error('$heartbeatPeriod must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->heartbeatPeriod = $heartbeatPeriod;
        return $clone;
    }
    /**
     * @return int The number of unanswered pings before the connection is closed.
     */
    public function getQueuedPingLimit() : int
    {
        return $this->queuedPingLimit;
    }
    /**
     * @param int $queuedPingLimit The number of unanswered pings before the connection is closed.
     *
     * @return self
     *
     * @throws \Error if number is less than 1.
     */
    public function withQueuedPingLimit(int $queuedPingLimit) : self
    {
        if ($queuedPingLimit < 1) {
            throw new \Error('$queuedPingLimit must be a positive integer greater than 0');
        }
        $clone = clone $this;
        $clone->queuedPingLimit = $queuedPingLimit;
        return $clone;
    }
}<?php

namespace Amp\Websocket;

use Amp\Struct;
final class ClientMetadata
{
    use Struct;
    /** @var int Next sequential client ID. */
    private static $nextId = 1;
    /** @var int */
    public $id;
    /** @var bool */
    public $closedByPeer = false;
    /** @var int|null */
    public $closeCode;
    /** @var string|null */
    public $closeReason;
    /** @var int */
    public $connectedAt = 0;
    /** @var int */
    public $closedAt = 0;
    /** @var int */
    public $lastReadAt = 0;
    /** @var int */
    public $lastSentAt = 0;
    /** @var int */
    public $lastDataReadAt = 0;
    /** @var int */
    public $lastDataSentAt = 0;
    /** @var int */
    public $lastHeartbeatAt = 0;
    /** @var int */
    public $bytesRead = 0;
    /** @var int */
    public $bytesSent = 0;
    /** @var int */
    public $framesRead = 0;
    /** @var int */
    public $framesSent = 0;
    /** @var int */
    public $messagesRead = 0;
    /** @var int */
    public $messagesSent = 0;
    /** @var int */
    public $pingCount = 0;
    /** @var int */
    public $pongCount = 0;
    /** @var bool */
    public $compressionEnabled;
    /**
     * @param int $time Current timestamp.
     * @param bool $compressionEnabled
     */
    public function __construct(int $time, bool $compressionEnabled)
    {
        $this->id = self::$nextId++;
        $this->connectedAt = $time;
        $this->compressionEnabled = $compressionEnabled;
    }
}<?php

namespace Amp\Websocket;

use Amp\ByteStream\InputStream;
use Amp\Promise;
use Amp\Socket\SocketAddress;
use Amp\Socket\TlsInfo;
interface Client
{
    /**
     * Receive a message from the remote Websocket endpoint.
     *
     * @return Promise<(Message | null)> Resolves to message sent by the remote.
     *
     * @throws ClosedException Thrown if the connection is closed.
     */
    public function receive() : Promise;
    /**
     * @return int Unique identifier for the client.
     */
    public function getId() : int;
    /**
    * @return bool True if the client is still connected, false otherwise. Returns false as soon as the closing
    handshake is initiated by the server or client.
    */
    public function isConnected() : bool;
    /**
     * @return SocketAddress Local socket address.
     */
    public function getLocalAddress() : SocketAddress;
    /**
     * @return SocketAddress Remote socket address.
     */
    public function getRemoteAddress() : SocketAddress;
    /**
     * @return (TlsInfo | null) TlsInfo object if connection is secure.
     */
    public function getTlsInfo() : ?TlsInfo;
    /**
     * @return int Number of pings sent that have not been answered.
     */
    public function getUnansweredPingCount() : int;
    /**
     * @return int Client close code (generally one of those listed in Code, though not necessarily).
     *
     * @throws \Error Thrown if the client has not closed.
     */
    public function getCloseCode() : int;
    /**
     * @return string Client close reason.
     *
     * @throws \Error Thrown if the client has not closed.
     */
    public function getCloseReason() : string;
    /**
     * @return bool True if the peer initiated the websocket close.
     *
     * @throws \Error Thrown if the client has not closed.
     */
    public function isClosedByPeer() : bool;
    /**
    * Sends a text message to the endpoint. All data sent with this method must be valid UTF-8. Use `sendBinary()` if
    you want to send binary data.
    *
    * @param string $data Payload to send.
    *
    * @return Promise<void> Resolves once the message has been sent to the peer.
    *
    * @throws ClosedException Thrown if sending to the client fails.
    */
    public function send(string $data) : Promise;
    /**
     * Sends a binary message to the endpoint.
     *
     * @param string $data Payload to send.
     *
     * @return Promise<void> Resolves once the message has been sent to the peer.
     *
     * @throws ClosedException Thrown if sending to the client fails.
     */
    public function sendBinary(string $data) : Promise;
    /**
    * Streams the given UTF-8 text stream to the endpoint. This method should be used only for large payloads such as
    files. Use send() for smaller payloads.
    *
    * @param InputStream $stream
    *
    * @return Promise<void> Resolves once the message has been sent to the peer.
    *
    * @throws ClosedException Thrown if sending to the client fails.
    */
    public function stream(InputStream $stream) : Promise;
    /**
    * Streams the given binary to the endpoint. This method should be used only for large payloads such as
    files. Use sendBinary() for smaller payloads.
    *
    * @param InputStream $stream
    *
    * @return Promise<void> Resolves once the message has been sent to the peer.
    *
    * @throws ClosedException Thrown if sending to the client fails.
    */
    public function streamBinary(InputStream $stream) : Promise;
    /**
     * Sends a ping to the endpoint.
     *
     * @return Promise<int> Resolves with the number of bytes sent to the other endpoint.
     */
    public function ping() : Promise;
    /**
     * @return Options The options object associated with this client.
     */
    public function getOptions() : Options;
    /**
     * Returns connection metadata.
     *
     * @return ClientMetadata
     */
    public function getInfo() : ClientMetadata;
    /**
    * Closes the client connection.
    *
    * @param int $code
    * @param string $reason
    *
    * @return Promise<array> Resolves with an array containing the close code at key 0 and the close reason at key 1.
    These may differ from those provided if the connection was closed prior.
    */
    public function close(int $code = Code::NORMAL_CLOSE, string $reason = '') : Promise;
    /**
    * Attaches a callback invoked when the client closes. The callback is passed this object as the first parameter,
    the close code as the second parameter, and the close reason as the third parameter.
    *
    * @param callable(Client $client, int $code, string $reason) $callback
    */
    public function onClose(callable $callback) : void;
}<?php

namespace Amp\Websocket;

interface CompressionContext
{
    /**
     * @return int The RSV value for this compression extension.
     */
    public function getRsv() : int;
    /**
     * @return int Minimum number of bytes a message must be before compressing.
     */
    public function getCompressionThreshold() : int;
    /**
     * Compress the given payload data.
     *
     * @param string $data
     * @param bool $isFinal
     *
     * @return string
     */
    public function compress(string $data, bool $isFinal) : string;
    /**
     * Decompress the given payload data. Null should be returned if decompression fails.
     *
     * @param string $data
     * @param bool $isFinal
     *
     * @return (string | null)
     */
    public function decompress(string $data, bool $isFinal) : ?string;
}<?php

namespace Amp\Websocket;

// defined in https://tools.ietf.org/html/rfc6455#section-4
const GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';
/**
 * @param int $length Random bytes to use to generate the key.
 *
 * @return string
 *
 * @throws \Exception If generating a random key fails.
 */
function generateKey(int $length = 16) : string
{
    return \base64_encode(\random_bytes($length));
}
/**
 * Generates the value for the Sec-Websocket-Accept header based on the given Sec-Websocket-Key header value.
 *
 * @param string $key
 *
 * @return string
 */
function generateAcceptFromKey(string $key) : string
{
    return \base64_encode(\sha1($key . GUID, true));
}
/**
 * Determines if the Sec-Websocket-Accept value given matches the expected value for the Sec-Websocket-Key header.
 *
 * @param string $accept
 * @param string $key
 *
 * @return bool
 */
function validateAcceptForKey(string $accept, string $key) : bool
{
    return $accept === generateAcceptFromKey($key);
}<?php

namespace Amp\Websocket;

final class Code
{
    public const NORMAL_CLOSE = 1000;
    public const GOING_AWAY = 1001;
    public const PROTOCOL_ERROR = 1002;
    public const UNACCEPTABLE_TYPE = 1003;
    // 1004 reserved and unused.
    public const NONE = 1005;
    public const ABNORMAL_CLOSE = 1006;
    public const INCONSISTENT_FRAME_DATA_TYPE = 1007;
    public const POLICY_VIOLATION = 1008;
    public const MESSAGE_TOO_LARGE = 1009;
    public const EXPECTED_EXTENSION_MISSING = 1010;
    public const UNEXPECTED_SERVER_ERROR = 1011;
    public const SERVICE_RESTARTING = 1012;
    public const TRY_AGAIN_LATER = 1013;
    public const BAD_GATEWAY = 1014;
    public const TLS_HANDSHAKE_FAILURE = 1015;
    /**
     * @param int $code Close code.
     *
     * @return (string | null) Constant name corresponding to the given code or null if the code is undefined.
     */
    public static function getName(int $code) : ?string
    {
        return [self::NORMAL_CLOSE => 'NORMAL_CLOSE', self::GOING_AWAY => 'GOING_AWAY', self::PROTOCOL_ERROR => 'PROTOCOL_ERROR', self::UNACCEPTABLE_TYPE => 'UNACCEPTABLE_TYPE', self::NONE => 'NONE', self::ABNORMAL_CLOSE => 'ABNORMAL_CLOSE', self::INCONSISTENT_FRAME_DATA_TYPE => 'INCONSISTENT_FRAME_DATA_TYPE', self::POLICY_VIOLATION => 'POLICY_VIOLATION', self::MESSAGE_TOO_LARGE => 'MESSAGE_TOO_LARGE', self::EXPECTED_EXTENSION_MISSING => 'EXPECTED_EXTENSION_MISSING', self::UNEXPECTED_SERVER_ERROR => 'UNEXPECTED_SERVER_ERROR', self::SERVICE_RESTARTING => 'SERVICE_RESTARTING', self::TRY_AGAIN_LATER => 'TRY_AGAIN_LATER', self::BAD_GATEWAY => 'BAD_GATEWAY', self::TLS_HANDSHAKE_FAILURE => 'TLS_HANDSHAKE_FAILURE'][$code] ?? null;
    }
    /**
     * @codeCoverageIgnore Class cannot be instigated.
     */
    private function __construct()
    {
        // no instances allowed
    }
}<?php

namespace Amp\Websocket;

final class ClosedException extends \Exception
{
    /** @var string */
    private $reason;
    /**
     *
     */
    public function __construct(string $message, int $code, string $reason)
    {
        parent::__construct(\sprintf('%s; Code %s (%s); Reason: "%s"', $message, $code, Code::getName($code) ?? 'Unknown code', $reason), $code);
        $this->reason = $reason;
    }
    /**
     *
     */
    public function getReason() : string
    {
        return $this->reason;
    }
}<?php

namespace Amp\Websocket;

final class Opcode
{
    public const CONT = 0x0;
    public const TEXT = 0x1;
    public const BIN = 0x2;
    public const CLOSE = 0x8;
    public const PING = 0x9;
    public const PONG = 0xa;
    /**
     * @codeCoverageIgnore Class cannot be instigated.
     */
    private function __construct()
    {
        // forbid instances
    }
}<?php

/** @noinspection PhpComposerExtensionStubsInspection */
namespace Amp\Websocket;

final class Rfc7692Compression implements CompressionContext
{
    public const DEFAULT_WINDOW_SIZE = 15;
    private const RSV = 0b100;
    private const MINIMUM_LENGTH = 860;
    private const EMPTY_BLOCK = "\x00\x00\xff\xff";
    /**
     * Create a compression context from a header received from a websocket client request.
     *
     * @param string $headerIn Header from request.
     * @param string $headerOut Sec-Websocket-Extension response header.
     *
     * @return (self | null)
     */
    public static function fromClientHeader(string $headerIn, ?string &$headerOut) : ?self
    {
        return self::fromHeader(true, $headerIn, $headerOut);
    }
    /**
     * Create a compression context from a header received from a websocket server response.
     *
     * @param string $header Header from response.
     *
     * @return (self | null)
     */
    public static function fromServerHeader(string $header) : ?self
    {
        return self::fromHeader(false, $header);
    }
    /**
     * @return string Header value for Sec-Websocket-Extension header.
     */
    public static function createRequestHeader() : string
    {
        return 'permessage-deflate; server_no_context_takeover; client_no_context_takeover';
    }
    /**
     * @param bool $isServer True if creating a server context, false if creating a client context.
     * @param string $headerIn Header from request.
     * @param string $headerOut Sec-Websocket-Extension response header.
     *
     * @return (self | null)
     */
    private static function fromHeader(bool $isServer, string $headerIn, ?string &$headerOut = null) : ?self
    {
        $headerIn = \explode(';', \strtolower($headerIn));
        $headerIn = \array_map('trim', $headerIn);
        if (!\in_array('permessage-deflate', $headerIn, true)) {
            return null;
        }
        $serverWindowSize = self::DEFAULT_WINDOW_SIZE;
        $clientWindowSize = self::DEFAULT_WINDOW_SIZE;
        $serverContextTakeover = true;
        $clientContextTakeover = true;
        $headers = [];
        $headerOut = 'permessage-deflate';
        foreach ($headerIn as $param) {
            $parts = \explode('=', $param, 2);
            if (\in_array($parts[0], $headers, true)) {
                return null;
                // Repeat params in header.
            }
            $headers[] = $parts[0];
            switch ($parts[0]) {
                case 'permessage-deflate':
                    break;
                case 'client_max_window_bits':
                    if (isset($parts[1])) {
                        $value = (int) $parts[1];
                        if ($value < 8 || $value > 15) {
                            return null;
                            // Invalid option value.
                        }
                        $clientWindowSize = $value;
                    }
                    $headerOut .= '; client_max_window_bits=' . $clientWindowSize;
                    break;
                case 'client_no_context_takeover':
                    $clientContextTakeover = false;
                    $headerOut .= '; client_no_context_takeover';
                    break;
                case 'server_max_window_bits':
                    if (isset($parts[1])) {
                        $value = (int) $parts[1];
                        if ($value < 8 || $value > 15) {
                            return null;
                            // Invalid option value.
                        }
                        $serverWindowSize = $value;
                    }
                    $headerOut .= '; server_max_window_bits=' . $serverWindowSize;
                    break;
                case 'server_no_context_takeover':
                    $serverContextTakeover = false;
                    $headerOut .= '; server_no_context_takeover';
                    break;
                default:
                    return null;
            }
        }
        if ($isServer) {
            return new self($clientWindowSize, $serverWindowSize, $clientContextTakeover, $serverContextTakeover);
        }
        return new self($serverWindowSize, $clientWindowSize, $serverContextTakeover, $clientContextTakeover);
    }
    /** @var resource */
    private $deflate;
    /** @var resource */
    private $inflate;
    /** @var int */
    private $sendingFlushMode;
    /** @var int */
    private $receivingFlushMode;
    /**
     *
     */
    private function __construct(int $receivingWindowSize, int $sendingWindowSize, bool $receivingContextTakeover, bool $sendingContextTakeover)
    {
        $this->receivingFlushMode = $receivingContextTakeover ? \ZLIB_SYNC_FLUSH : \ZLIB_FULL_FLUSH;
        $this->sendingFlushMode = $sendingContextTakeover ? \ZLIB_SYNC_FLUSH : \ZLIB_FULL_FLUSH;
        if (($this->inflate = \inflate_init(\ZLIB_ENCODING_RAW, ['window' => $receivingWindowSize])) === false) {
            throw new \RuntimeException('Failed initializing inflate context');
        }
        if (($this->deflate = \deflate_init(\ZLIB_ENCODING_RAW, ['window' => $sendingWindowSize])) === false) {
            throw new \RuntimeException('Failed initializing deflate context');
        }
    }
    /**
     *
     */
    public function getRsv() : int
    {
        return self::RSV;
    }
    /**
     *
     */
    public function getCompressionThreshold() : int
    {
        return self::MINIMUM_LENGTH;
    }
    /**
     *
     */
    public function decompress(string $data, bool $isFinal) : ?string
    {
        if ($isFinal) {
            $data .= self::EMPTY_BLOCK;
        }
        $data = \inflate_add($this->inflate, $data, $this->receivingFlushMode);
        if (false === $data) {
            return null;
        }
        return $data;
    }
    /**
     *
     */
    public function compress(string $data, bool $isFinal) : string
    {
        $data = \deflate_add($this->deflate, $data, $this->sendingFlushMode);
        if ($data === false) {
            throw new \RuntimeException('Failed to compress data');
        }
        if ($isFinal && \Phabel\Target\Php80\Polyfill::substr($data, -4) === self::EMPTY_BLOCK) {
            $data = \Phabel\Target\Php80\Polyfill::substr($data, 0, -4);
        }
        return $data;
    }
}{
    "name": "amphp/websocket",
    "homepage": "https://github.com/amphp/websocket",
    "description": "Shared code for websocket servers and clients.",
    "support": {
        "issues": "https://github.com/amphp/websocket/issues"
    },
    "keywords": [
        "async",
        "non-blocking",
        "websocket",
        "http",
        "amp",
        "amphp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2.2",
        "amphp/byte-stream": "^1.6.1",
        "amphp/socket": "^1",
        "cash/lrucache": "^1"
    },
    "require-dev": {
        "phpunit/phpunit": "^8 || ^7",
        "amphp/phpunit-util": "^1.1.2",
        "amphp/php-cs-fixer-config": "dev-master",
        "vimeo/psalm": "^3.11@dev"
    },
    "suggest": {
        "ext-zlib": "Required for compression"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Websocket\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Websocket\\Test\\": "test"
        },
        "files": [
            "test/functions.php"
        ]
    }
}
<?php

namespace Amp\Serialization;

final class NativeSerializer implements Serializer
{
    /** @var string[]|null */
    private $allowedClasses;
    /**
     * @param (string[] | null) $allowedClasses List of allowed class names to be unserialized. Null for any class.
     */
    public function __construct(?array $allowedClasses = null)
    {
        $this->allowedClasses = $allowedClasses;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        try {
            return \serialize($data);
        } catch (\Throwable $exception) {
            throw new SerializationException(\sprintf('The given data could not be serialized: %s', $exception->getMessage()), 0, $exception);
        }
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        try {
            $result = \unserialize($data, ['allowed_classes' => $this->allowedClasses ?? true]);
            if ($result === false && $data !== \serialize(false)) {
                throw new SerializationException('Invalid data provided to unserialize: ' . encodeUnprintableChars($data));
            }
        } catch (\Throwable $exception) {
            throw new SerializationException('Exception thrown when unserializing data', 0, $exception);
        }
        return $result;
    }
}<?php

namespace Amp\Serialization;

final class JsonSerializer implements Serializer
{
    // Equal to JSON_THROW_ON_ERROR, only available in PHP 7.3+.
    private const THROW_ON_ERROR = 4194304;
    /** @var bool */
    private $associative;
    /** @var int */
    private $encodeOptions;
    /** @var int */
    private $decodeOptions;
    /** @var int */
    private $depth;
    /**
     * Creates a JSON serializer that decodes objects to associative arrays.
     *
     * @param int $encodeOptions @see \json_encode() options parameter.
     * @param int $decodeOptions @see \json_decode() options parameter.
     * @param int $depth Maximum recursion depth.
     *
     * @return self
     */
    public static function withAssociativeArrays(int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512) : self
    {
        return new self(true, $encodeOptions, $decodeOptions, $depth);
    }
    /**
     * Creates a JSON serializer that decodes objects to instances of stdClass.
     *
     * @param int $encodeOptions @see \json_encode() options parameter.
     * @param int $decodeOptions @see \json_decode() options parameter.
     * @param int $depth Maximum recursion depth.
     *
     * @return self
     */
    public static function withObjects(int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512) : self
    {
        return new self(false, $encodeOptions, $decodeOptions, $depth);
    }
    /**
     *
     */
    private function __construct(bool $associative, int $encodeOptions = 0, int $decodeOptions = 0, int $depth = 512)
    {
        $this->associative = $associative;
        $this->depth = $depth;
        // We don't want to throw on errors, we manually check for errors using json_last_error().
        $this->encodeOptions = $encodeOptions & ~self::THROW_ON_ERROR;
        $this->decodeOptions = $decodeOptions & ~self::THROW_ON_ERROR;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        $result = \json_encode($data, $this->encodeOptions, $this->depth);
        switch ($code = \json_last_error()) {
            case \JSON_ERROR_NONE:
                return $result;
            default:
                throw new SerializationException(\json_last_error_msg(), $code);
        }
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        $result = \json_decode($data, $this->associative, $this->depth, $this->decodeOptions);
        switch ($code = \json_last_error()) {
            case \JSON_ERROR_NONE:
                return $result;
            default:
                throw new SerializationException(\json_last_error_msg(), $code);
        }
    }
}<?php

namespace Amp\Serialization;

interface Serializer
{
    /**
     * @param mixed $data
     *
     * @return string
     *
     * @throws SerializationException
     */
    public function serialize($data) : string;
    /**
     * @param string $data
     *
     * @return mixed The unserialized data.
     *
     * @throws SerializationException
     */
    public function unserialize(string $data);
}<?php

namespace Amp\Serialization;

final class CompressingSerializer implements Serializer
{
    private const FLAG_COMPRESSED = 1;
    private const COMPRESSION_THRESHOLD = 256;
    /** @var Serializer */
    private $serializer;
    /**
     *
     */
    public function __construct(Serializer $serializer)
    {
        $this->serializer = $serializer;
    }
    /**
     *
     */
    public function serialize($data) : string
    {
        $serializedData = $this->serializer->serialize($data);
        $flags = 0;
        if (\strlen($serializedData) > self::COMPRESSION_THRESHOLD) {
            $serializedData = @\gzdeflate($serializedData, 1);
            if ($serializedData === false) {
                $error = \error_get_last();
                throw new SerializationException('Could not compress data: ' . ($error['message'] ?? 'unknown error'));
            }
            $flags |= self::FLAG_COMPRESSED;
        }
        return \chr($flags & 0xff) . $serializedData;
    }
    /**
     *
     */
    public function unserialize(string $data)
    {
        $firstByte = \ord($data[0]);
        $data = \Phabel\Target\Php80\Polyfill::substr($data, 1);
        if ($firstByte & self::FLAG_COMPRESSED) {
            $data = @\gzinflate($data);
            if ($data === false) {
                $error = \error_get_last();
                throw new SerializationException('Could not decompress data: ' . ($error['message'] ?? 'unknown error'));
            }
        }
        return $this->serializer->unserialize($data);
    }
}<?php

namespace Amp\Serialization;

final class PassthroughSerializer implements Serializer
{
    /**
     *
     */
    public function serialize($data) : string
    {
        if (!\is_string($data)) {
            throw new SerializationException('Serializer implementation only allows strings');
        }
        return $data;
    }
    /**
     *
     */
    public function unserialize(string $data) : string
    {
        return $data;
    }
}<?php

namespace Amp\Serialization;

/**
 * @param string $data Binary data.
 *
 * @return string Unprintable characters encoded as \x##.
 */
function encodeUnprintableChars(string $data) : string
{
    return \preg_replace_callback("/[^ -~]/", function (array $matches) : string {
        return "\\x" . \dechex(\ord($matches[0]));
    }, $data);
}<?php

namespace Amp\Serialization;

class SerializationException extends \Exception
{
}{
    "name": "amphp/serialization",
    "description": "Serialization tools for IPC and data storage in PHP.",
    "keywords": [
        "asynchronous",
        "async",
        "serialization",
        "serialize"
    ],
    "homepage": "https://github.com/amphp/serialization",
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "require-dev": {
        "phpunit/phpunit": "^9 || ^8 || ^7",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Serialization\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Serialization\\Test\\": "test"
        }
    }
}
{
    "name": "amphp/byte-stream",
    "homepage": "http://amphp.org/byte-stream",
    "description": "A stream abstraction to make working with non-blocking I/O simple.",
    "support": {
        "issues": "https://github.com/amphp/byte-stream/issues",
        "irc": "irc://irc.freenode.org/amphp"
    },
    "keywords": [
        "stream",
        "async",
        "non-blocking",
        "amp",
        "amphp",
        "io"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1.4",
        "phpunit/phpunit": "^6 || ^7 || ^8",
        "friendsofphp/php-cs-fixer": "^2.3",
        "amphp/php-cs-fixer-config": "dev-master",
        "psalm/phar": "^3.11.4",
        "jetbrains/phpstorm-stubs": "^2019.3"
    },
    "autoload": {
        "psr-4": {
            "Amp\\ByteStream\\": "lib"
        },
        "files": [
            "lib/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\ByteStream\\Test\\": "test"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    }
}
<?php

namespace Amp\ByteStream\Base64;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\StreamException;
use Amp\Promise;
use function Amp\call;
final class Base64DecodingInputStream implements InputStream
{
    /** @var InputStream|null */
    private $source;
    /** @var string|null */
    private $buffer = '';
    /**
     *
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    public function read() : Promise
    {
        return call(function () {
            if ($this->source === null) {
                throw new StreamException('Failed to read stream chunk due to invalid base64 data');
            }
            $chunk = (yield $this->source->read());
            if ($chunk === null) {
                if ($this->buffer === null) {
                    return null;
                }
                $chunk = \base64_decode($this->buffer, true);
                if ($chunk === false) {
                    $this->source = null;
                    $this->buffer = null;
                    throw new StreamException('Failed to read stream chunk due to invalid base64 data');
                }
                $this->buffer = null;
                return $chunk;
            }
            $this->buffer .= $chunk;
            $length = \strlen($this->buffer);
            $chunk = \base64_decode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 4), true);
            if ($chunk === false) {
                $this->source = null;
                $this->buffer = null;
                throw new StreamException('Failed to read stream chunk due to invalid base64 data');
            }
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 4);
            return $chunk;
        });
    }
}<?php

namespace Amp\ByteStream\Base64;

use Amp\ByteStream\OutputStream;
use Amp\Promise;
final class Base64EncodingOutputStream implements OutputStream
{
    /** @var OutputStream */
    private $destination;
    /** @var string */
    private $buffer = '';
    /**
     *
     */
    public function __construct(OutputStream $destination)
    {
        $this->destination = $destination;
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        $this->buffer .= $data;
        $length = \strlen($this->buffer);
        $chunk = \base64_encode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 3));
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 3);
        return $this->destination->write($chunk);
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        $chunk = \base64_encode($this->buffer . $finalData);
        $this->buffer = '';
        return $this->destination->end($chunk);
    }
}<?php

namespace Amp\ByteStream\Base64;

use Amp\ByteStream\OutputStream;
use Amp\ByteStream\StreamException;
use Amp\Failure;
use Amp\Promise;
final class Base64DecodingOutputStream implements OutputStream
{
    /** @var OutputStream */
    private $destination;
    /** @var string */
    private $buffer = '';
    /** @var int */
    private $offset = 0;
    /**
     *
     */
    public function __construct(OutputStream $destination)
    {
        $this->destination = $destination;
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        $this->buffer .= $data;
        $length = \strlen($this->buffer);
        $chunk = \base64_decode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 4), true);
        if ($chunk === false) {
            return new Failure(new StreamException('Invalid base64 near offset ' . $this->offset));
        }
        $this->offset += $length - $length % 4;
        $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 4);
        return $this->destination->write($chunk);
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        $this->offset += \strlen($this->buffer);
        $chunk = \base64_decode($this->buffer . $finalData, true);
        if ($chunk === false) {
            return new Failure(new StreamException('Invalid base64 near offset ' . $this->offset));
        }
        $this->buffer = '';
        return $this->destination->end($chunk);
    }
}<?php

namespace Amp\ByteStream\Base64;

use Amp\ByteStream\InputStream;
use Amp\Promise;
use function Amp\call;
final class Base64EncodingInputStream implements InputStream
{
    /** @var InputStream */
    private $source;
    /** @var string|null */
    private $buffer = '';
    /**
     *
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    public function read() : Promise
    {
        return call(function () {
            $chunk = (yield $this->source->read());
            if ($chunk === null) {
                if ($this->buffer === null) {
                    return null;
                }
                $chunk = \base64_encode($this->buffer);
                $this->buffer = null;
                return $chunk;
            }
            $this->buffer .= $chunk;
            $length = \strlen($this->buffer);
            $chunk = \base64_encode(\Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $length - $length % 3));
            $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $length - $length % 3);
            return $chunk;
        });
    }
}<?php

namespace Amp\ByteStream;

use Amp\Deferred;
use Amp\Failure;
use Amp\Iterator;
use Amp\Promise;
final class IteratorStream implements InputStream
{
    /** @var Iterator<string> */
    private $iterator;
    /** @var \Throwable|null */
    private $exception;
    /** @var bool */
    private $pending = false;
    /**
     * @psam-param Iterator<string> $iterator
     */
    public function __construct(Iterator $iterator)
    {
        $this->iterator = $iterator;
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        if ($this->exception) {
            return new Failure($this->exception);
        }
        if ($this->pending) {
            throw new PendingReadError();
        }
        $this->pending = true;
        /** @var Deferred<string|null> $deferred */
        $deferred = new Deferred();
        $this->iterator->advance()->onResolve(function ($error, $hasNextElement) use($deferred) {
            $this->pending = false;
            if ($error) {
                $this->exception = $error;
                $deferred->fail($error);
            } elseif ($hasNextElement) {
                $chunk = $this->iterator->getCurrent();
                if (!\is_string($chunk)) {
                    $this->exception = new StreamException(\sprintf("Unexpected iterator value of type '%s', expected string", \is_object($chunk) ? \get_class($chunk) : \gettype($chunk)));
                    $deferred->fail($this->exception);
                    return;
                }
                $deferred->resolve($chunk);
            } else {
                $deferred->resolve();
            }
        });
        return $deferred->promise();
    }
}<?php

namespace Amp\ByteStream;

use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
/**
 * Output stream abstraction for PHP's stream resources.
 */
final class ResourceOutputStream implements OutputStream
{
    const MAX_CONSECUTIVE_EMPTY_WRITES = 3;
    const LARGE_CHUNK_SIZE = 128 * 1024;
    /** @var resource|null */
    private $resource;
    /** @var string */
    private $watcher;
    /** @var \SplQueue<array> */
    private $writes;
    /** @var bool */
    private $writable = true;
    /** @var int|null */
    private $chunkSize;
    /**
     * @param resource $stream Stream resource.
     * @param (int | null) $chunkSize Chunk size per `fwrite()` operation.
     */
    public function __construct($stream, int $chunkSize = null)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== 'stream') {
            throw new \Error("Expected a valid stream");
        }
        $meta = \stream_get_meta_data($stream);
        if (\strpos($meta["mode"], "r") !== false && \strpos($meta["mode"], "+") === false) {
            throw new \Error("Expected a writable stream");
        }
        \stream_set_blocking($stream, false);
        \stream_set_write_buffer($stream, 0);
        $this->resource = $stream;
        $this->chunkSize =& $chunkSize;
        $writes = $this->writes = new \SplQueue();
        $writable =& $this->writable;
        $resource =& $this->resource;
        $this->watcher = Loop::onWritable($stream, static function ($watcher, $stream) use($writes, &$chunkSize, &$writable, &$resource) {
            static $emptyWrites = 0;
            try {
                while (!$writes->isEmpty()) {
                    /** @var Deferred $deferred */
                    list($data, $previous, $deferred) = $writes->shift();
                    $length = \strlen($data);
                    if ($length === 0) {
                        $deferred->resolve(0);
                        continue;
                    }
                    if (!\is_resource($stream) || ($metaData = @\stream_get_meta_data($stream)) && $metaData['eof']) {
                        throw new ClosedException("The stream was closed by the peer");
                    }
                    // Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full.
                    // Use conditional, because PHP doesn't like getting null passed
                    if ($chunkSize) {
                        $written = @\fwrite($stream, $data, $chunkSize);
                    } else {
                        $written = @\fwrite($stream, $data);
                    }
                    \assert(
                        $written !== false || \PHP_VERSION_ID >= 70400,
                        // PHP 7.4+ returns false on EPIPE.
                        "Trying to write on a previously fclose()'d resource. Do NOT manually fclose() resources the still referenced in the loop."
                    );
                    // PHP 7.4.0 and 7.4.1 may return false on EAGAIN.
                    if ($written === false && \PHP_VERSION_ID >= 70402) {
                        $message = "Failed to write to stream";
                        if ($error = \error_get_last()) {
                            $message .= \sprintf("; %s", $error["message"]);
                        }
                        throw new StreamException($message);
                    }
                    // Broken pipes between processes on macOS/FreeBSD do not detect EOF properly.
                    if ($written === 0 || $written === false) {
                        if ($emptyWrites++ > self::MAX_CONSECUTIVE_EMPTY_WRITES) {
                            $message = "Failed to write to stream after multiple attempts";
                            if ($error = \error_get_last()) {
                                $message .= \sprintf("; %s", $error["message"]);
                            }
                            throw new StreamException($message);
                        }
                        $writes->unshift([$data, $previous, $deferred]);
                        return;
                    }
                    $emptyWrites = 0;
                    if ($length > $written) {
                        $data = \Phabel\Target\Php80\Polyfill::substr($data, $written);
                        $writes->unshift([$data, $written + $previous, $deferred]);
                        return;
                    }
                    $deferred->resolve($written + $previous);
                }
            } catch (\Throwable $exception) {
                $resource = null;
                $writable = false;
                /** @psalm-suppress PossiblyUndefinedVariable */
                $deferred->fail($exception);
                while (!$writes->isEmpty()) {
                    list(, , $deferred) = $writes->shift();
                    $deferred->fail($exception);
                }
                Loop::cancel($watcher);
            } finally {
                if ($writes->isEmpty()) {
                    Loop::disable($watcher);
                }
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     */
    public function write(string $data) : Promise
    {
        return $this->send($data, false);
    }
    /**
     * Closes the stream after all pending writes have been completed. Optionally writes a final data chunk before.
     *
     * @param string $finalData Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     */
    public function end(string $finalData = "") : Promise
    {
        return $this->send($finalData, true);
    }
    /**
     *
     */
    private function send(string $data, bool $end = false) : Promise
    {
        if (!$this->writable) {
            return new Failure(new ClosedException("The stream is not writable"));
        }
        $length = \strlen($data);
        $written = 0;
        if ($end) {
            $this->writable = false;
        }
        if ($this->writes->isEmpty()) {
            if ($length === 0) {
                if ($end) {
                    $this->close();
                }
                return new Success(0);
            }
            if (!\is_resource($this->resource) || ($metaData = @\stream_get_meta_data($this->resource)) && $metaData['eof']) {
                return new Failure(new ClosedException("The stream was closed by the peer"));
            }
            // Error reporting suppressed since fwrite() emits E_WARNING if the pipe is broken or the buffer is full.
            // Use conditional, because PHP doesn't like getting null passed.
            if ($this->chunkSize) {
                $written = @\fwrite($this->resource, $data, $this->chunkSize);
            } else {
                $written = @\fwrite($this->resource, $data);
            }
            \assert(
                $written !== false || \PHP_VERSION_ID >= 70400,
                // PHP 7.4+ returns false on EPIPE.
                "Trying to write on a previously fclose()'d resource. Do NOT manually fclose() resources the still referenced in the loop."
            );
            // PHP 7.4.0 and 7.4.1 may return false on EAGAIN.
            if ($written === false && \PHP_VERSION_ID >= 70402) {
                $message = "Failed to write to stream";
                if ($error = \error_get_last()) {
                    $message .= \sprintf("; %s", $error["message"]);
                }
                return new Failure(new StreamException($message));
            }
            $written = (int) $written;
            // Cast potential false to 0.
            if ($length === $written) {
                if ($end) {
                    $this->close();
                }
                return new Success($written);
            }
            $data = \Phabel\Target\Php80\Polyfill::substr($data, $written);
        }
        $deferred = new Deferred();
        if ($length - $written > self::LARGE_CHUNK_SIZE) {
            $chunks = \str_split($data, self::LARGE_CHUNK_SIZE);
            $data = \array_pop($chunks);
            foreach ($chunks as $chunk) {
                $this->writes->push([$chunk, $written, new Deferred()]);
                $written += self::LARGE_CHUNK_SIZE;
            }
        }
        $this->writes->push([$data, $written, $deferred]);
        Loop::enable($this->watcher);
        $promise = $deferred->promise();
        if ($end) {
            $promise->onResolve([$this, "close"]);
        }
        return $promise;
    }
    /**
     * Closes the stream forcefully. Multiple `close()` calls are ignored.
     *
     * @return void
     */
    public function close()
    {
        if (\is_resource($this->resource)) {
            // Error suppression, as resource might already be closed
            $meta = @\stream_get_meta_data($this->resource);
            if ($meta && \strpos($meta["mode"], "+") !== false) {
                @\stream_socket_shutdown($this->resource, \STREAM_SHUT_WR);
            } else {
                /** @psalm-suppress InvalidPropertyAssignmentValue psalm reports this as closed-resource */
                @\fclose($this->resource);
            }
        }
        $this->free();
    }
    /**
     * Nulls reference to resource, marks stream unwritable, and fails any pending write.
     *
     * @return void
     */
    private function free()
    {
        $this->resource = null;
        $this->writable = false;
        if (!$this->writes->isEmpty()) {
            $exception = new ClosedException("The socket was closed before writing completed");
            do {
                /** @var Deferred $deferred */
                list(, , $deferred) = $this->writes->shift();
                $deferred->fail($exception);
            } while (!$this->writes->isEmpty());
        }
        Loop::cancel($this->watcher);
    }
    /**
     * @return (resource | null) Stream resource or null if end() has been called or the stream closed.
     */
    public function getResource()
    {
        return $this->resource;
    }
    /**
     * @return void
     */
    public function setChunkSize(int $chunkSize)
    {
        $this->chunkSize = $chunkSize;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->resource !== null) {
            $this->free();
        }
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
/**
 * An `OutputStream` allows writing data in chunks. Writers can wait on the returned promises to feel the backpressure.
 */
interface OutputStream
{
    /**
     * Writes data to the stream.
     *
     * @param string $data Bytes to write.
     *
     * @return Promise Succeeds once the data has been successfully written to the stream.
     *
     * @throws ClosedException If the stream has already been closed.
     * @throws StreamException If writing to the stream fails.
     */
    public function write(string $data) : Promise;
    /**
    * Marks the stream as no longer writable. Optionally writes a final data chunk before. Note that this is not the
    same as forcefully closing the stream. This method waits for all pending writes to complete before closing the
    stream. Socket streams implementing this interface should only close the writable side of the stream.
    *
    * @param string $finalData Bytes to write.
    *
    * @return Promise Succeeds once the data has been successfully written to the stream.
    *
    * @throws ClosedException If the stream has already been closed.
    * @throws StreamException If writing to the stream fails.
    */
    public function end(string $finalData = "") : Promise;
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class InputStreamChain implements InputStream
{
    /** @var InputStream[] */
    private $streams;
    /** @var bool */
    private $reading = false;
    /**
     *
     */
    public function __construct(InputStream ...$streams)
    {
        $this->streams = $streams;
    }
    /**
     * @inheritDoc
     */
    public function read() : Promise
    {
        if ($this->reading) {
            throw new PendingReadError();
        }
        if (!$this->streams) {
            return new Success(null);
        }
        return call(function () {
            $this->reading = true;
            try {
                while ($this->streams) {
                    $chunk = (yield $this->streams[0]->read());
                    if ($chunk === null) {
                        \array_shift($this->streams);
                        continue;
                    }
                    return $chunk;
                }
                return null;
            } finally {
                $this->reading = false;
            }
        });
    }
}<?php

namespace Amp\ByteStream;

use Amp\Coroutine;
use Amp\Deferred;
use Amp\Failure;
use Amp\Promise;
use Amp\Success;
/**
 * Creates a buffered message from an InputStream. The message can be consumed in chunks using the read() API or it may
 * be buffered and accessed in its entirety by waiting for the promise to resolve.
 *
 * Other implementations may extend this class to add custom properties such as a `isBinary()` flag for WebSocket
 * messages.
 *
 * Buffering Example:
 *
 * $stream = new Message($inputStream);
 * $content = yield $stream;
 *
 * Streaming Example:
 *
 * $stream = new Message($inputStream);
 *
 * while (($chunk = yield $stream->read()) !== null) {
 *     // Immediately use $chunk, reducing memory consumption since the entire message is never buffered.
 * }
 *
 * @deprecated Use Amp\ByteStream\Payload instead.
 */
class Message implements InputStream, Promise
{
    /** @var InputStream */
    private $source;
    /** @var string */
    private $buffer = "";
    /** @var Deferred|null */
    private $pendingRead;
    /** @var Coroutine|null */
    private $coroutine;
    /** @var bool True if onResolve() has been called. */
    private $buffering = false;
    /** @var Deferred|null */
    private $backpressure;
    /** @var bool True if the iterator has completed. */
    private $complete = false;
    /** @var \Throwable|null Used to fail future reads on failure. */
    private $error;
    /**
     * @param InputStream $source An iterator that only emits strings.
     */
    public function __construct(InputStream $source)
    {
        $this->source = $source;
    }
    /**
     *
     */
    private function consume() : \Generator
    {
        while (($chunk = (yield $this->source->read())) !== null) {
            $buffer = $this->buffer .= $chunk;
            if ($buffer === "") {
                continue;
                // Do not succeed reads with empty string.
            } elseif ($this->pendingRead) {
                $deferred = $this->pendingRead;
                $this->pendingRead = null;
                $this->buffer = "";
                $deferred->resolve($buffer);
                $buffer = "";
                // Destroy last emitted chunk to free memory.
            } elseif (!$this->buffering) {
                $buffer = "";
                // Destroy last emitted chunk to free memory.
                $this->backpressure = new Deferred();
                (yield $this->backpressure->promise());
            }
        }
        $this->complete = true;
        if ($this->pendingRead) {
            $deferred = $this->pendingRead;
            $this->pendingRead = null;
            $deferred->resolve($this->buffer !== "" ? $this->buffer : null);
            $this->buffer = "";
        }
        return $this->buffer;
    }
    /**
     * @inheritdoc
     */
    public final function read() : Promise
    {
        if ($this->pendingRead) {
            throw new PendingReadError();
        }
        if ($this->coroutine === null) {
            $this->coroutine = new Coroutine($this->consume());
            $this->coroutine->onResolve(function ($error) {
                if ($error) {
                    $this->error = $error;
                }
                if ($this->pendingRead) {
                    $deferred = $this->pendingRead;
                    $this->pendingRead = null;
                    $deferred->fail($error);
                }
            });
        }
        if ($this->error) {
            return new Failure($this->error);
        }
        if ($this->buffer !== "") {
            $buffer = $this->buffer;
            $this->buffer = "";
            if ($this->backpressure) {
                $backpressure = $this->backpressure;
                $this->backpressure = null;
                $backpressure->resolve();
            }
            return new Success($buffer);
        }
        if ($this->complete) {
            return new Success();
        }
        $this->pendingRead = new Deferred();
        return $this->pendingRead->promise();
    }
    /**
     * @inheritdoc
     */
    public final function onResolve(callable $onResolved)
    {
        $this->buffering = true;
        if ($this->coroutine === null) {
            $this->coroutine = new Coroutine($this->consume());
        }
        if ($this->backpressure) {
            $backpressure = $this->backpressure;
            $this->backpressure = null;
            $backpressure->resolve();
        }
        $this->coroutine->onResolve($onResolved);
    }
    /**
    * Exposes the source input stream.
    *
    * This might be required to resolve a promise with an InputStream, because promises in Amp can't be resolved with
    other promises.
    *
    * @return InputStream
    */
    public final function getInputStream() : InputStream
    {
        return $this->source;
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
/**
 * An `InputStream` allows reading byte streams in chunks.
 *
 * **Example**
 *
 * ```php
 * function readAll(InputStream $in): Promise {
 *     return Amp\call(function () use ($in) {
 *         $buffer = "";
 *
 *         while (($chunk = yield $in->read()) !== null) {
 *             $buffer .= $chunk;
 *         }
 *
 *         return $buffer;
 *     });
 * }
 * ```
 */
interface InputStream
{
    /**
     * Reads data from the stream.
     *
     * @return Promise Resolves with a string when new data is available or `null` if the stream has closed.
     *
     * @psalm-return Promise<(string | null)>
     *
     * @throws PendingReadError Thrown if another read operation is still pending.
     */
    public function read() : Promise;
}<?php

namespace Amp\ByteStream;

use Amp\Deferred;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
/**
 * Input stream abstraction for PHP's stream resources.
 */
final class ResourceInputStream implements InputStream
{
    const DEFAULT_CHUNK_SIZE = 8192;
    /** @var resource|null */
    private $resource;
    /** @var string */
    private $watcher;
    /** @var Deferred|null */
    private $deferred;
    /** @var bool */
    private $readable = true;
    /** @var int */
    private $chunkSize;
    /** @var bool */
    private $useSingleRead;
    /** @var callable */
    private $immediateCallable;
    /** @var string|null */
    private $immediateWatcher;
    /**
     * @param resource $stream Stream resource.
     * @param int $chunkSize Chunk size per read operation.
     *
     * @throws \Error If an invalid stream or parameter has been passed.
     */
    public function __construct($stream, int $chunkSize = self::DEFAULT_CHUNK_SIZE)
    {
        if (!\is_resource($stream) || \get_resource_type($stream) !== 'stream') {
            throw new \Error("Expected a valid stream");
        }
        $meta = \stream_get_meta_data($stream);
        $useSingleRead = $meta["stream_type"] === "udp_socket" || $meta["stream_type"] === "STDIO";
        $this->useSingleRead = $useSingleRead;
        if (\strpos($meta["mode"], "r") === false && \strpos($meta["mode"], "+") === false) {
            throw new \Error("Expected a readable stream");
        }
        \stream_set_blocking($stream, false);
        \stream_set_read_buffer($stream, 0);
        $this->resource =& $stream;
        $this->chunkSize =& $chunkSize;
        $deferred =& $this->deferred;
        $readable =& $this->readable;
        $this->watcher = Loop::onReadable($this->resource, static function ($watcher) use(&$deferred, &$readable, &$stream, &$chunkSize, $useSingleRead) {
            if ($useSingleRead) {
                $data = @\fread($stream, $chunkSize);
            } else {
                $data = @\stream_get_contents($stream, $chunkSize);
            }
            \assert($data !== false, "Trying to read from a previously fclose()'d resource. Do NOT manually fclose() resources the loop still has a reference to.");
            // Error suppression, because pthreads does crazy things with resources,
            // which might be closed during two operations.
            // See https://github.com/amphp/byte-stream/issues/32
            if ($data === '' && @\feof($stream)) {
                $readable = false;
                $stream = null;
                $data = null;
                // Stream closed, resolve read with null.
                Loop::cancel($watcher);
            } else {
                Loop::disable($watcher);
            }
            $temp = $deferred;
            $deferred = null;
            \assert($temp instanceof Deferred);
            $temp->resolve($data);
        });
        $this->immediateCallable = static function ($watcherId, $data) use(&$deferred) {
            $temp = $deferred;
            $deferred = null;
            \assert($temp instanceof Deferred);
            $temp->resolve($data);
        };
        Loop::disable($this->watcher);
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        if ($this->deferred !== null) {
            throw new PendingReadError();
        }
        if (!$this->readable) {
            return new Success();
            // Resolve with null on closed stream.
        }
        \assert($this->resource !== null);
        // Attempt a direct read, because Windows suffers from slow I/O on STDIN otherwise.
        if ($this->useSingleRead) {
            $data = @\fread($this->resource, $this->chunkSize);
        } else {
            $data = @\stream_get_contents($this->resource, $this->chunkSize);
        }
        \assert($data !== false, "Trying to read from a previously fclose()'d resource. Do NOT manually fclose() resources the loop still has a reference to.");
        if ($data === '') {
            // Error suppression, because pthreads does crazy things with resources,
            // which might be closed during two operations.
            // See https://github.com/amphp/byte-stream/issues/32
            if (@\feof($this->resource)) {
                $this->readable = false;
                $this->resource = null;
                Loop::cancel($this->watcher);
                return new Success();
                // Stream closed, resolve read with null.
            }
            $this->deferred = new Deferred();
            Loop::enable($this->watcher);
            return $this->deferred->promise();
        }
        // Prevent an immediate read â†’ write loop from blocking everything
        // See e.g. examples/benchmark-throughput.php
        $this->deferred = new Deferred();
        $this->immediateWatcher = Loop::defer($this->immediateCallable, $data);
        return $this->deferred->promise();
    }
    /**
     * Closes the stream forcefully. Multiple `close()` calls are ignored.
     *
     * @return void
     */
    public function close()
    {
        if (\is_resource($this->resource)) {
            // Error suppression, as resource might already be closed
            $meta = @\stream_get_meta_data($this->resource);
            if ($meta && \strpos($meta["mode"], "+") !== false) {
                @\stream_socket_shutdown($this->resource, \STREAM_SHUT_RD);
            } else {
                /** @psalm-suppress InvalidPropertyAssignmentValue */
                @\fclose($this->resource);
            }
        }
        $this->free();
    }
    /**
     * Nulls reference to resource, marks stream unreadable, and succeeds any pending read with null.
     *
     * @return void
     */
    private function free()
    {
        $this->readable = false;
        $this->resource = null;
        if ($this->deferred !== null) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->resolve();
        }
        Loop::cancel($this->watcher);
        if ($this->immediateWatcher !== null) {
            Loop::cancel($this->immediateWatcher);
        }
    }
    /**
     * @return (resource | null) The stream resource or null if the stream has closed.
     */
    public function getResource()
    {
        return $this->resource;
    }
    /**
     * @return void
     */
    public function setChunkSize(int $chunkSize)
    {
        $this->chunkSize = $chunkSize;
    }
    /**
     * References the read watcher, so the loop keeps running in case there's an active read.
     *
     * @return void
     *
     * @see Loop::reference()
     */
    public function reference()
    {
        if (!$this->resource) {
            throw new \Error("Resource has already been freed");
        }
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the read watcher, so the loop doesn't keep running even if there are active reads.
     *
     * @return void
     *
     * @see Loop::unreference()
     */
    public function unreference()
    {
        if (!$this->resource) {
            throw new \Error("Resource has already been freed");
        }
        Loop::unreference($this->watcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->resource !== null) {
            $this->free();
        }
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
use function Amp\call;
/**
 * Allows decompression of input streams using Zlib.
 */
final class ZlibInputStream implements InputStream
{
    /** @var InputStream|null */
    private $source;
    /** @var int */
    private $encoding;
    /** @var array */
    private $options;
    /** @var resource|null */
    private $resource;
    /**
     * @param InputStream $source Input stream to read compressed data from.
     * @param int $encoding Compression algorithm used, see `inflate_init()`.
     * @param array $options Algorithm options, see `inflate_init()`.
     *
     * @throws StreamException
     * @throws \Error
     *
     * @see http://php.net/manual/en/function.inflate-init.php
     */
    public function __construct(InputStream $source, int $encoding, array $options = [])
    {
        $this->source = $source;
        $this->encoding = $encoding;
        $this->options = $options;
        $this->resource = @\inflate_init($encoding, $options);
        if ($this->resource === false) {
            throw new StreamException("Failed initializing deflate context");
        }
    }
    /**
     * @inheritdoc
     */
    public function read() : Promise
    {
        return call(function () {
            if ($this->resource === null) {
                return null;
            }
            \assert($this->source !== null);
            $data = (yield $this->source->read());
            // Needs a double guard, as stream might have been closed while reading
            /** @psalm-suppress ParadoxicalCondition */
            if ($this->resource === null) {
                return null;
            }
            if ($data === null) {
                $decompressed = @\inflate_add($this->resource, "", \ZLIB_FINISH);
                if ($decompressed === false) {
                    throw new StreamException("Failed adding data to deflate context");
                }
                $this->close();
                return $decompressed;
            }
            $decompressed = @\inflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH);
            if ($decompressed === false) {
                throw new StreamException("Failed adding data to deflate context");
            }
            return $decompressed;
        });
    }
    /**
     * @internal
     * @return void
     */
    private function close()
    {
        $this->resource = null;
        $this->source = null;
    }
    /**
     * Gets the used compression encoding.
     *
     * @return int Encoding specified on construction time.
     */
    public function getEncoding() : int
    {
        return $this->encoding;
    }
    /**
     * Gets the used compression options.
     *
     * @return array Options array passed on construction time.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
}<?php

namespace Amp\ByteStream;

class StreamException extends \Exception
{
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
use function Amp\call;
final class LineReader
{
    /** @var string */
    private $delimiter;
    /** @var bool */
    private $lineMode;
    /** @var string */
    private $buffer = "";
    /** @var InputStream */
    private $source;
    /**
     *
     */
    public function __construct(InputStream $inputStream, string $delimiter = null)
    {
        $this->source = $inputStream;
        $this->delimiter = $delimiter === null ? "\n" : $delimiter;
        $this->lineMode = $delimiter === null;
    }
    /**
     * @return Promise<(string | null)>
     */
    public function readLine() : Promise
    {
        return call(function () {
            if (false !== \strpos($this->buffer, $this->delimiter)) {
                list($line, $this->buffer) = \explode($this->delimiter, $this->buffer, 2);
                return $this->lineMode ? \rtrim($line, "\r") : $line;
            }
            while (null !== ($chunk = (yield $this->source->read()))) {
                $this->buffer .= $chunk;
                if (false !== \strpos($this->buffer, $this->delimiter)) {
                    list($line, $this->buffer) = \explode($this->delimiter, $this->buffer, 2);
                    return $this->lineMode ? \rtrim($line, "\r") : $line;
                }
            }
            if ($this->buffer === "") {
                return null;
            }
            $line = $this->buffer;
            $this->buffer = "";
            return $this->lineMode ? \rtrim($line, "\r") : $line;
        });
    }
    /**
     *
     */
    public function getBuffer() : string
    {
        return $this->buffer;
    }
    /**
     * @return void
     */
    public function clearBuffer()
    {
        $this->buffer = "";
    }
}<?php

namespace Amp\ByteStream;

use Amp\Iterator;
use Amp\Loop;
use Amp\Producer;
use Amp\Promise;
use function Amp\call;
// @codeCoverageIgnoreStart
if (\strlen('â€¦') !== 3) {
    throw new \Error('The mbstring.func_overload ini setting is enabled. It must be disabled to use the stream package.');
}
// @codeCoverageIgnoreEnd
if (!\defined('STDOUT')) {
    \define('STDOUT', \fopen('php://stdout', 'w'));
}
if (!\defined('STDERR')) {
    \define('STDERR', \fopen('php://stderr', 'w'));
}
/**
 * @param \Amp\ByteStream\InputStream $source
 * @param \Amp\ByteStream\OutputStream $destination
 *
 * @return \Amp\Promise
 */
function pipe(InputStream $source, OutputStream $destination) : Promise
{
    return call(function () use($source, $destination) : \Generator {
        $written = 0;
        while (($chunk = (yield $source->read())) !== null) {
            $written += \strlen($chunk);
            $writePromise = $destination->write($chunk);
            $chunk = null;
            // free memory
            (yield $writePromise);
        }
        return $written;
    });
}
/**
 * @param \Amp\ByteStream\InputStream $source
 *
 * @return \Amp\Promise
 */
function buffer(InputStream $source) : Promise
{
    return call(function () use($source) : \Generator {
        $buffer = "";
        while (($chunk = (yield $source->read())) !== null) {
            $buffer .= $chunk;
            $chunk = null;
            // free memory
        }
        return $buffer;
    });
}
/**
 * The php://input input buffer stream for the process associated with the currently active event loop.
 *
 * @return ResourceInputStream
 */
function getInputBufferStream() : ResourceInputStream
{
    static $key = InputStream::class . '\\input';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceInputStream(\fopen('php://input', 'rb'));
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The php://output output buffer stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getOutputBufferStream() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\output';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\fopen('php://output', 'wb'));
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDIN stream for the process associated with the currently active event loop.
 *
 * @return ResourceInputStream
 */
function getStdin() : ResourceInputStream
{
    static $key = InputStream::class . '\\stdin';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceInputStream(\STDIN);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDOUT stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getStdout() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\stdout';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\STDOUT);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 * The STDERR stream for the process associated with the currently active event loop.
 *
 * @return ResourceOutputStream
 */
function getStderr() : ResourceOutputStream
{
    static $key = OutputStream::class . '\\stderr';
    $stream = Loop::getState($key);
    if (!$stream) {
        $stream = new ResourceOutputStream(\STDERR);
        Loop::setState($key, $stream);
    }
    return $stream;
}
/**
 *
 */
function parseLineDelimitedJson(InputStream $stream, bool $assoc = false, int $depth = 512, int $options = 0) : Iterator
{
    return new Producer(static function (callable $emit) use($stream, $assoc, $depth, $options) {
        $reader = new LineReader($stream);
        while (null !== ($line = (yield $reader->readLine()))) {
            $line = \trim($line);
            if ($line === '') {
                continue;
            }
            /** @noinspection PhpComposerExtensionStubsInspection */
            $data = \json_decode($line, $assoc, $depth, $options);
            /** @noinspection PhpComposerExtensionStubsInspection */
            $error = \json_last_error();
            /** @noinspection PhpComposerExtensionStubsInspection */
            if ($error !== \JSON_ERROR_NONE) {
                /** @noinspection PhpComposerExtensionStubsInspection */
                throw new StreamException('Failed to parse JSON: ' . \json_last_error_msg(), $error);
            }
            (yield $emit($data));
        }
    });
}<?php

namespace Amp\ByteStream;

final class ClosedException extends StreamException
{
}<?php

namespace Amp\ByteStream;

use Amp\Coroutine;
use Amp\Promise;
use function Amp\call;
/**
 * Creates a buffered message from an InputStream. The message can be consumed in chunks using the read() API or it may
 * be buffered and accessed in its entirety by calling buffer(). Once buffering is requested through buffer(), the
 * stream cannot be read in chunks. On destruct any remaining data is read from the InputStream given to this class.
 */
class Payload implements InputStream
{
    /** @var InputStream */
    private $stream;
    /** @var \Amp\Promise|null */
    private $promise;
    /** @var \Amp\Promise|null */
    private $lastRead;
    /**
     * @param \Amp\ByteStream\InputStream $stream
     */
    public function __construct(InputStream $stream)
    {
        $this->stream = $stream;
    }
    /**
     *
     */
    public function __destruct()
    {
        if (!$this->promise) {
            Promise\rethrow(new Coroutine($this->consume()));
        }
    }
    /**
     *
     */
    private function consume() : \Generator
    {
        try {
            if ($this->lastRead && null === (yield $this->lastRead)) {
                return;
            }
            while (null !== (yield $this->stream->read())) {
                // Discard unread bytes from message.
            }
        } catch (\Throwable $exception) {
            // If exception is thrown here the connection closed anyway.
        }
    }
    /**
     * @inheritdoc
     *
     * @throws \Error If a buffered message was requested by calling buffer().
     */
    public final function read() : Promise
    {
        if ($this->promise) {
            throw new \Error("Cannot stream message data once a buffered message has been requested");
        }
        return $this->lastRead = $this->stream->read();
    }
    /**
     * Buffers the entire message and resolves the returned promise then.
     *
     * @return Promise<string> Resolves with the entire message contents.
     */
    public final function buffer() : Promise
    {
        if ($this->promise) {
            return $this->promise;
        }
        return $this->promise = call(function () {
            $buffer = '';
            if ($this->lastRead && null === (yield $this->lastRead)) {
                return $buffer;
            }
            while (null !== ($chunk = (yield $this->stream->read()))) {
                $buffer .= $chunk;
            }
            return $buffer;
        });
    }
}<?php

namespace Amp\ByteStream;

/**
 * Thrown in case a second read operation is attempted while another read operation is still pending.
 */
final class PendingReadError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = "The previous read operation must complete before read can be called again", int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
/**
 * Allows compression of output streams using Zlib.
 */
final class ZlibOutputStream implements OutputStream
{
    /** @var OutputStream|null */
    private $destination;
    /** @var int */
    private $encoding;
    /** @var array */
    private $options;
    /** @var resource|null */
    private $resource;
    /**
     * @param OutputStream $destination Output stream to write the compressed data to.
     * @param int $encoding Compression encoding to use, see `deflate_init()`.
     * @param array $options Compression options to use, see `deflate_init()`.
     *
     * @throws StreamException If an invalid encoding or invalid options have been passed.
     *
     * @see http://php.net/manual/en/function.deflate-init.php
     */
    public function __construct(OutputStream $destination, int $encoding, array $options = [])
    {
        $this->destination = $destination;
        $this->encoding = $encoding;
        $this->options = $options;
        $this->resource = @\deflate_init($encoding, $options);
        if ($this->resource === false) {
            throw new StreamException("Failed initializing deflate context");
        }
    }
    /**
     * @inheritdoc
     */
    public function write(string $data) : Promise
    {
        if ($this->resource === null) {
            throw new ClosedException("The stream has already been closed");
        }
        \assert($this->destination !== null);
        $compressed = \deflate_add($this->resource, $data, \ZLIB_SYNC_FLUSH);
        if ($compressed === false) {
            throw new StreamException("Failed adding data to deflate context");
        }
        $promise = $this->destination->write($compressed);
        $promise->onResolve(function ($error) {
            if ($error) {
                $this->close();
            }
        });
        return $promise;
    }
    /**
     * @inheritdoc
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->resource === null) {
            throw new ClosedException("The stream has already been closed");
        }
        \assert($this->destination !== null);
        $compressed = \deflate_add($this->resource, $finalData, \ZLIB_FINISH);
        if ($compressed === false) {
            throw new StreamException("Failed adding data to deflate context");
        }
        $promise = $this->destination->end($compressed);
        $promise->onResolve(function () {
            $this->close();
        });
        return $promise;
    }
    /**
     * @internal
     * @return void
     */
    private function close()
    {
        $this->resource = null;
        $this->destination = null;
    }
    /**
     * Gets the used compression encoding.
     *
     * @return int Encoding specified on construction time.
     */
    public function getEncoding() : int
    {
        return $this->encoding;
    }
    /**
     * Gets the used compression options.
     *
     * @return array Options array passed on construction time.
     */
    public function getOptions() : array
    {
        return $this->options;
    }
}<?php

namespace Amp\ByteStream;

use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
class OutputBuffer implements OutputStream, Promise
{
    /** @var Deferred */
    private $deferred;
    /** @var string */
    private $contents = '';
    /** @var bool */
    private $closed = false;
    /**
     *
     */
    public function __construct()
    {
        $this->deferred = new Deferred();
    }
    /**
     *
     */
    public function write(string $data) : Promise
    {
        if ($this->closed) {
            throw new ClosedException("The stream has already been closed.");
        }
        $this->contents .= $data;
        return new Success(\strlen($data));
    }
    /**
     *
     */
    public function end(string $finalData = "") : Promise
    {
        if ($this->closed) {
            throw new ClosedException("The stream has already been closed.");
        }
        $this->contents .= $finalData;
        $this->closed = true;
        $this->deferred->resolve($this->contents);
        $this->contents = "";
        return new Success(\strlen($finalData));
    }
    /**
     *
     */
    public function onResolve(callable $onResolved)
    {
        $this->deferred->promise()->onResolve($onResolved);
    }
}<?php

namespace Amp\ByteStream;

use Amp\Promise;
use Amp\Success;
/**
 * Input stream with a single already known data chunk.
 */
final class InMemoryStream implements InputStream
{
    private $contents;
    /**
     * @param (string | null) $contents Data chunk or `null` for no data chunk.
     */
    public function __construct(string $contents = null)
    {
        $this->contents = $contents;
    }
    /**
     * Reads data from the stream.
     *
     * @return Promise<(string | null)> Resolves with the full contents or `null` if the stream has closed / already been consumed.
     */
    public function read() : Promise
    {
        if ($this->contents === null) {
            return new Success();
        }
        $promise = new Success($this->contents);
        $this->contents = null;
        return $promise;
    }
}{
    "name": "amphp/dns",
    "homepage": "https://github.com/amphp/dns",
    "description": "Async DNS resolution for Amp.",
    "keywords": [
        "dns",
        "resolve",
        "client",
        "async",
        "amp",
        "amphp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Chris Wright",
            "email": "addr@daverandom.com"
        },
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.0",
        "ext-json": "*",
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.1",
        "amphp/cache": "^1.2",
        "amphp/parser": "^1",
        "amphp/windows-registry": "^0.3",
        "daverandom/libdns": "^2.0.1",
        "ext-filter": "*"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1",
        "phpunit/phpunit": "^6 || ^7 || ^8 || ^9",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Dns\\": "lib"
        },
        "files": [
            "lib/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Dns\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Dns\Internal;

use Amp;
use Amp\Deferred;
use Amp\Dns\DnsException;
use Amp\Dns\TimeoutException;
use Amp\Loop;
use Amp\Parser\Parser;
use Amp\Promise;
use Amp\Success;
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Messages\Message;
use function Amp\call;
/** @internal */
final class TcpSocket extends Socket
{
    /** @var \LibDNS\Encoder\Encoder */
    private $encoder;
    /** @var \SplQueue */
    private $queue;
    /** @var Parser */
    private $parser;
    /** @var bool */
    private $isAlive = true;
    /**
     *
     */
    public static function connect(string $uri, int $timeout = 5000) : Promise
    {
        if (!($socket = @\stream_socket_client($uri, $errno, $errstr, 0, STREAM_CLIENT_ASYNC_CONNECT))) {
            throw new DnsException(\sprintf("Connection to %s failed: [Error #%d] %s", $uri, $errno, $errstr));
        }
        \stream_set_blocking($socket, false);
        return call(function () use($uri, $socket, $timeout) {
            $deferred = new Deferred();
            $watcher = Loop::onWritable($socket, static function () use($socket, $deferred) {
                $deferred->resolve(new self($socket));
            });
            try {
                return (yield Promise\timeout($deferred->promise(), $timeout));
            } catch (Amp\TimeoutException $e) {
                throw new TimeoutException("Name resolution timed out, could not connect to server at {$uri}");
            } finally {
                Loop::cancel($watcher);
            }
        });
    }
    /**
     *
     */
    public static function parser(callable $callback) : \Generator
    {
        $decoder = (new DecoderFactory())->create();
        while (true) {
            $length = (yield 2);
            $length = \unpack("n", $length)[1];
            $rawData = (yield $length);
            $callback($decoder->decode($rawData));
        }
    }
    /**
     *
     */
    protected function __construct($socket)
    {
        parent::__construct($socket);
        $this->encoder = (new EncoderFactory())->create();
        $this->queue = new \SplQueue();
        $this->parser = new Parser(self::parser([$this->queue, 'push']));
    }
    /**
     *
     */
    protected function send(Message $message) : Promise
    {
        $data = $this->encoder->encode($message);
        $promise = $this->write(\pack("n", \strlen($data)) . $data);
        $promise->onResolve(function ($error) {
            if ($error) {
                $this->isAlive = false;
            }
        });
        return $promise;
    }
    /**
     *
     */
    protected function receive() : Promise
    {
        if ($this->queue->isEmpty()) {
            return call(function () {
                do {
                    $chunk = (yield $this->read());
                    if ($chunk === null) {
                        $this->isAlive = false;
                        throw new DnsException("Reading from the server failed");
                    }
                    $this->parser->push($chunk);
                } while ($this->queue->isEmpty());
                return $this->queue->shift();
            });
        }
        return new Success($this->queue->shift());
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return $this->isAlive;
    }
}<?php

namespace Amp\Dns\Internal;

use Amp\Dns\DnsException;
use Amp\Promise;
use Amp\Success;
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Messages\Message;
use function Amp\call;
/** @internal */
final class UdpSocket extends Socket
{
    /** @var \LibDNS\Encoder\Encoder */
    private $encoder;
    /** @var \LibDNS\Decoder\Decoder */
    private $decoder;
    /**
     *
     */
    public static function connect(string $uri) : Promise
    {
        if (!($socket = @\stream_socket_client($uri, $errno, $errstr, 0, STREAM_CLIENT_ASYNC_CONNECT))) {
            throw new DnsException(\sprintf("Connection to %s failed: [Error #%d] %s", $uri, $errno, $errstr));
        }
        return new Success(new self($socket));
    }
    /**
     *
     */
    protected function __construct($socket)
    {
        parent::__construct($socket);
        $this->encoder = (new EncoderFactory())->create();
        $this->decoder = (new DecoderFactory())->create();
    }
    /**
     *
     */
    protected function send(Message $message) : Promise
    {
        $data = $this->encoder->encode($message);
        return $this->write($data);
    }
    /**
     *
     */
    protected function receive() : Promise
    {
        return call(function () {
            $data = (yield $this->read());
            if ($data === null) {
                throw new DnsException("Reading from the server failed");
            }
            return $this->decoder->decode($data);
        });
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return true;
    }
}<?php

namespace Amp\Dns\Internal;

use Amp;
use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Dns\DnsException;
use Amp\Dns\TimeoutException;
use Amp\Promise;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Records\Question;
use function Amp\call;
/** @internal */
abstract class Socket
{
    const MAX_CONCURRENT_REQUESTS = 500;
    /** @var ResourceInputStream */
    private $input;
    /** @var ResourceOutputStream */
    private $output;
    /** @var array Contains already sent queries with no response yet. For UDP this is exactly zero or one item. */
    private $pending = [];
    /** @var MessageFactory */
    private $messageFactory;
    /** @var callable */
    private $onResolve;
    /** @var int Used for determining whether the socket can be garbage collected, because it's inactive. */
    private $lastActivity;
    /** @var bool */
    private $receiving = false;
    /** @var array Queued requests if the number of concurrent requests is too large. */
    private $queue = [];
    /**
     * @param string $uri
     *
     * @return Promise<self>
     */
    public static abstract function connect(string $uri) : Promise;
    /**
     * @param Message $message
     *
     * @return Promise<int>
     */
    protected abstract function send(Message $message) : Promise;
    /**
     * @return Promise<Message>
     */
    protected abstract function receive() : Promise;
    /**
     * @return bool
     */
    public abstract function isAlive() : bool;
    /**
     *
     */
    public function getLastActivity() : int
    {
        return $this->lastActivity;
    }
    /**
     *
     */
    protected function __construct($socket)
    {
        $this->input = new ResourceInputStream($socket);
        $this->output = new ResourceOutputStream($socket);
        $this->messageFactory = new MessageFactory();
        $this->lastActivity = \time();
        $this->onResolve = function (\Throwable $exception = null, Message $message = null) {
            $this->lastActivity = \time();
            $this->receiving = false;
            if ($exception) {
                $this->error($exception);
                return;
            }
            \assert($message instanceof Message);
            $id = $message->getId();
            // Ignore duplicate and invalid responses.
            if (isset($this->pending[$id]) && $this->matchesQuestion($message, $this->pending[$id]->question)) {
                /** @var Deferred $deferred */
                $deferred = $this->pending[$id]->deferred;
                unset($this->pending[$id]);
                $deferred->resolve($message);
            }
            if (empty($this->pending)) {
                $this->input->unreference();
            } elseif (!$this->receiving) {
                $this->input->reference();
                $this->receiving = true;
                $this->receive()->onResolve($this->onResolve);
            }
        };
    }
    /**
     * @param \LibDNS\Records\Question $question
     * @param int $timeout
     *
     * @return \Amp\Promise<\LibDNS\Messages\Message>
     */
    public final function ask(Question $question, int $timeout) : Promise
    {
        return call(function () use($question, $timeout) {
            $this->lastActivity = \time();
            if (\count($this->pending) > self::MAX_CONCURRENT_REQUESTS) {
                $deferred = new Deferred();
                $this->queue[] = $deferred;
                (yield $deferred->promise());
            }
            do {
                $id = \random_int(0, 0xffff);
            } while (isset($this->pending[$id]));
            $deferred = new Deferred();
            $pending = new class
            {
                use Amp\Struct;
                public $deferred;
                public $question;
            };
            $pending->deferred = $deferred;
            $pending->question = $question;
            $this->pending[$id] = $pending;
            $message = $this->createMessage($question, $id);
            try {
                (yield $this->send($message));
            } catch (StreamException $exception) {
                $exception = new DnsException("Sending the request failed", 0, $exception);
                $this->error($exception);
                throw $exception;
            }
            $this->input->reference();
            if (!$this->receiving) {
                $this->receiving = true;
                $this->receive()->onResolve($this->onResolve);
            }
            try {
                // Work around an OPCache issue that returns an empty array with "return yield ...",
                // so assign to a variable first and return after the try block.
                //
                // See https://github.com/amphp/dns/issues/58.
                // See https://bugs.php.net/bug.php?id=74840.
                $result = (yield Promise\timeout($deferred->promise(), $timeout));
            } catch (Amp\TimeoutException $exception) {
                unset($this->pending[$id]);
                if (empty($this->pending)) {
                    $this->input->unreference();
                }
                throw new TimeoutException("Didn't receive a response within {$timeout} milliseconds.");
            } finally {
                if ($this->queue) {
                    $deferred = \array_shift($this->queue);
                    $deferred->resolve();
                }
            }
            return $result;
        });
    }
    /**
     *
     */
    public final function close()
    {
        $this->input->close();
        $this->output->close();
    }
    /**
     *
     */
    private function error(\Throwable $exception)
    {
        $this->close();
        if (empty($this->pending)) {
            return;
        }
        if (!$exception instanceof DnsException) {
            $message = "Unexpected error during resolution: " . $exception->getMessage();
            $exception = new DnsException($message, 0, $exception);
        }
        $pending = $this->pending;
        $this->pending = [];
        foreach ($pending as $pendingQuestion) {
            /** @var Deferred $deferred */
            $deferred = $pendingQuestion->deferred;
            $deferred->fail($exception);
        }
    }
    /**
     *
     */
    protected final function read() : Promise
    {
        return $this->input->read();
    }
    /**
     *
     */
    protected final function write(string $data) : Promise
    {
        return $this->output->write($data);
    }
    /**
     *
     */
    protected final function createMessage(Question $question, int $id) : Message
    {
        $request = $this->messageFactory->create(MessageTypes::QUERY);
        $request->getQuestionRecords()->add($question);
        $request->isRecursionDesired(true);
        $request->setID($id);
        return $request;
    }
    /**
     *
     */
    private function matchesQuestion(Message $message, Question $question) : bool
    {
        if ($message->getType() !== MessageTypes::RESPONSE) {
            return false;
        }
        $questionRecords = $message->getQuestionRecords();
        // We only ever ask one question at a time
        if (\count($questionRecords) !== 1) {
            return false;
        }
        $questionRecord = $questionRecords->getIterator()->current();
        if ($questionRecord->getClass() !== $question->getClass()) {
            return false;
        }
        if ($questionRecord->getType() !== $question->getType()) {
            return false;
        }
        if ($questionRecord->getName()->getValue() !== $question->getName()->getValue()) {
            return false;
        }
        return true;
    }
}<?php

namespace Amp\Dns;

use Amp\Failure;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
class UnixConfigLoader implements ConfigLoader
{
    const MAX_NAMESERVERS = 3;
    const MAX_DNS_SEARCH = 6;
    const MAX_TIMEOUT = 30 * 1000;
    const MAX_ATTEMPTS = 5;
    const MAX_NDOTS = 15;
    const DEFAULT_TIMEOUT = 5 * 1000;
    const DEFAULT_ATTEMPTS = 2;
    const DEFAULT_NDOTS = 1;
    const DEFAULT_OPTIONS = ["timeout" => self::DEFAULT_TIMEOUT, "attempts" => self::DEFAULT_ATTEMPTS, "ndots" => self::DEFAULT_NDOTS, "rotate" => false];
    private $path;
    private $hostLoader;
    /**
     *
     */
    public function __construct(string $path = "/etc/resolv.conf", HostLoader $hostLoader = null)
    {
        $this->path = $path;
        $this->hostLoader = $hostLoader ?? new HostLoader();
    }
    /**
     *
     */
    protected function readFile(string $path) : Promise
    {
        \set_error_handler(function (int $errno, string $message) use($path) {
            throw new ConfigException("Could not read configuration file '{$path}' ({$errno}) {$message}");
        });
        try {
            // Blocking file access, but this file should be local and usually loaded only once.
            $fileContent = \file_get_contents($path);
        } catch (ConfigException $exception) {
            return new Failure($exception);
        } finally {
            \restore_error_handler();
        }
        return new Success($fileContent);
    }
    /**
     *
     */
    public final function loadConfig() : Promise
    {
        return call(function () {
            $nameservers = [];
            $searchList = [];
            $options = self::DEFAULT_OPTIONS;
            $haveLocaldomainEnv = false;
            /* Allow user to override the local domain definition.  */
            if ($localdomain = \getenv("LOCALDOMAIN")) {
                /* Set search list to be blank-separated strings from rest of
                   env value.  Permits users of LOCALDOMAIN to still have a
                   search list, and anyone to set the one that they want to use
                   as an individual (even more important now that the rfc1535
                   stuff restricts searches).  */
                $searchList = $this->splitOnWhitespace($localdomain);
                $haveLocaldomainEnv = true;
            }
            $fileContent = (yield $this->readFile($this->path));
            $lines = \explode("\n", $fileContent);
            foreach ($lines as $line) {
                $line = \preg_split('#\\s+#', $line, 2);
                if (\count($line) !== 2) {
                    continue;
                }
                list($type, $value) = $line;
                if ($type === "nameserver") {
                    if (\count($nameservers) === self::MAX_NAMESERVERS) {
                        continue;
                    }
                    $value = \trim($value);
                    $ip = @\inet_pton($value);
                    if ($ip === false) {
                        continue;
                    }
                    if (isset($ip[15])) {
                        // IPv6
                        $nameservers[] = "[" . $value . "]:53";
                    } else {
                        // IPv4
                        $nameservers[] = $value . ":53";
                    }
                } elseif ($type === "domain" && !$haveLocaldomainEnv) {
                    // LOCALDOMAIN env overrides config
                    $searchList = $this->splitOnWhitespace($value);
                } elseif ($type === "search" && !$haveLocaldomainEnv) {
                    // LOCALDOMAIN env overrides config
                    $searchList = $this->splitOnWhitespace($value);
                } elseif ($type === "options") {
                    $option = $this->parseOption($value);
                    if (\count($option) === 2) {
                        $options[$option[0]] = $option[1];
                    }
                }
            }
            $hosts = (yield $this->hostLoader->loadHosts());
            if (\count($searchList) === 0) {
                $hostname = \gethostname();
                $dot = \strpos(".", $hostname);
                if ($dot !== false && $dot < \strlen($hostname)) {
                    $searchList = [\Phabel\Target\Php80\Polyfill::substr($hostname, $dot)];
                }
            }
            if (\count($searchList) > self::MAX_DNS_SEARCH) {
                $searchList = \array_slice($searchList, 0, self::MAX_DNS_SEARCH);
            }
            $resOptions = \getenv("RES_OPTIONS");
            if ($resOptions) {
                foreach ($this->splitOnWhitespace($resOptions) as $option) {
                    $option = $this->parseOption($option);
                    if (\count($option) === 2) {
                        $options[$option[0]] = $option[1];
                    }
                }
            }
            $config = new Config($nameservers, $hosts, $options["timeout"], $options["attempts"]);
            return $config->withSearchList($searchList)->withNdots($options["ndots"])->withRotationEnabled($options["rotate"]);
        });
    }
    /**
     *
     */
    private function splitOnWhitespace(string $names) : array
    {
        return \preg_split("#\\s+#", \trim($names));
    }
    /**
     *
     */
    private function parseOption(string $option) : array
    {
        $optline = \explode(':', $option, 2);
        list($name, $value) = $optline + [1 => null];
        switch ($name) {
            case "timeout":
                $value = (int) $value;
                if ($value < 0) {
                    return [];
                    // don't overwrite option value
                }
                // The value for this option is silently capped to 30s
                return ["timeout", (int) \min($value * 1000, self::MAX_TIMEOUT)];
            case "attempts":
                $value = (int) $value;
                if ($value < 0) {
                    return [];
                    // don't overwrite option value
                }
                // The value for this option is silently capped to 5
                return ["attempts", (int) \min($value, self::MAX_ATTEMPTS)];
            case "ndots":
                $value = (int) $value;
                if ($value < 0) {
                    return [];
                    // don't overwrite option value
                }
                // The value for this option is silently capped to 15
                return ["ndots", (int) \min($value, self::MAX_NDOTS)];
            case "rotate":
                return ["rotate", true];
        }
        return [];
    }
}<?php

namespace Amp\Dns;

final class Config
{
    /** @var array */
    private $nameservers;
    /** @var array */
    private $knownHosts;
    /** @var int */
    private $timeout;
    /** @var int */
    private $attempts;
    /** @var array */
    private $searchList = [];
    /** @var int */
    private $ndots = 1;
    /** @var bool */
    private $rotation = false;
    /**
     *
     */
    public function __construct(array $nameservers, array $knownHosts = [], int $timeout = 3000, int $attempts = 2)
    {
        if (\count($nameservers) < 1) {
            throw new ConfigException("At least one nameserver is required for a valid config");
        }
        foreach ($nameservers as $nameserver) {
            $this->validateNameserver($nameserver);
        }
        if ($timeout < 0) {
            throw new ConfigException("Invalid timeout ({$timeout}), must be 0 or greater");
        }
        if ($attempts < 1) {
            throw new ConfigException("Invalid attempt count ({$attempts}), must be 1 or greater");
        }
        // Windows does not include localhost in its host file. Fetch it from the system instead
        if (!isset($knownHosts[Record::A]["localhost"]) && !isset($knownHosts[Record::AAAA]["localhost"])) {
            // PHP currently provides no way to **resolve** IPv6 hostnames (not even with fallback)
            $local = \gethostbyname("localhost");
            if ($local !== "localhost") {
                $knownHosts[Record::A]["localhost"] = $local;
            } else {
                $knownHosts[Record::AAAA]["localhost"] = '::1';
            }
        }
        $this->nameservers = $nameservers;
        $this->knownHosts = $knownHosts;
        $this->timeout = $timeout;
        $this->attempts = $attempts;
    }
    /**
     *
     */
    public function withSearchList(array $searchList) : self
    {
        $self = clone $this;
        $self->searchList = $searchList;
        return $self;
    }
    /**
     * @throws ConfigException
     */
    public function withNdots(int $ndots) : self
    {
        if ($ndots < 0) {
            throw new ConfigException("Invalid ndots ({$ndots}), must be greater or equal to 0");
        }
        if ($ndots > 15) {
            $ndots = 15;
        }
        $self = clone $this;
        $self->ndots = $ndots;
        return $self;
    }
    /**
     *
     */
    public function withRotationEnabled(bool $enabled = true) : self
    {
        $self = clone $this;
        $self->rotation = $enabled;
        return $self;
    }
    /**
     *
     */
    private function validateNameserver($nameserver)
    {
        if (!$nameserver || !\is_string($nameserver)) {
            throw new ConfigException("Invalid nameserver: {$nameserver}");
        }
        if ($nameserver[0] === "[") {
            // IPv6
            $addr = \strstr(\Phabel\Target\Php80\Polyfill::substr($nameserver, 1), "]", true);
            $port = \Phabel\Target\Php80\Polyfill::substr($nameserver, \strrpos($nameserver, "]") + 1);
            if ($port !== "" && !\preg_match("(^:(\\d+)\$)", $port, $match)) {
                throw new ConfigException("Invalid nameserver: {$nameserver}");
            }
            $port = $port === "" ? 53 : \Phabel\Target\Php80\Polyfill::substr($port, 1);
        } else {
            // IPv4
            $arr = \explode(":", $nameserver, 2);
            if (\count($arr) === 2) {
                list($addr, $port) = $arr;
            } else {
                $addr = $arr[0];
                $port = 53;
            }
        }
        $addr = \trim($addr, "[]");
        $port = (int) $port;
        if (!($inAddr = @\inet_pton($addr))) {
            throw new ConfigException("Invalid server IP: {$addr}");
        }
        if ($port < 1 || $port > 65535) {
            throw new ConfigException("Invalid server port: {$port}");
        }
    }
    /**
     *
     */
    public function getNameservers() : array
    {
        return $this->nameservers;
    }
    /**
     *
     */
    public function getKnownHosts() : array
    {
        return $this->knownHosts;
    }
    /**
     *
     */
    public function getTimeout() : int
    {
        return $this->timeout;
    }
    /**
     *
     */
    public function getAttempts() : int
    {
        return $this->attempts;
    }
    /**
     *
     */
    public function getSearchList() : array
    {
        return $this->searchList;
    }
    /**
     *
     */
    public function getNdots() : int
    {
        return $this->ndots;
    }
    /**
     *
     */
    public function isRotationEnabled() : bool
    {
        return $this->rotation;
    }
}<?php

namespace Amp\Dns;

use Amp\Promise;
interface ConfigLoader
{
    /**
     *
     */
    public function loadConfig() : Promise;
}<?php

namespace Amp\Dns;

use Throwable;
/**
 * MUST be thrown in case the config can't be read and no fallback is available.
 */
class ConfigException extends DnsException
{
    /**
     *
     */
    public function __construct(string $message, Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
    }
}<?php

namespace Amp\Dns;

use Amp\Promise;
interface Resolver
{
    /**
     * Resolves a hostname name to an IP address [hostname as defined by RFC 3986].
     *
     * Upon success the returned promise resolves to an array of Record objects.
     *
     * A null $ttl value indicates the DNS name was resolved from the cache or the local hosts file.
     *
     * @param string $name The hostname to resolve.
     * @param int $typeRestriction Optional type restriction to `Record::A` or `Record::AAAA`, otherwise `null`.
     *
     * @return Promise
     */
    public function resolve(string $name, int $typeRestriction = null) : Promise;
    /**
     * Query specific DNS records.
     *
     * Upon success the returned promise resolves to an array of Record objects.
     *
     * @param string $name Record to question, A, AAAA and PTR queries are automatically normalized.
     * @param int $type Use constants of Amp\Dns\Record.
     *
     * @return Promise
     */
    public function query(string $name, int $type) : Promise;
}<?php

namespace Amp\Dns;

use Amp\Promise;
use Amp\WindowsRegistry\KeyNotFoundException;
use Amp\WindowsRegistry\WindowsRegistry;
use function Amp\call;
final class WindowsConfigLoader implements ConfigLoader
{
    private $hostLoader;
    /**
     *
     */
    public function __construct(HostLoader $hostLoader = null)
    {
        $this->hostLoader = $hostLoader ?? new HostLoader();
    }
    /**
     *
     */
    public function loadConfig() : Promise
    {
        return call(function () {
            $keys = ["HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\NameServer", "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\DhcpNameServer"];
            $reader = new WindowsRegistry();
            $nameserver = "";
            while ($nameserver === "" && ($key = \array_shift($keys))) {
                try {
                    $nameserver = (yield $reader->read($key));
                } catch (KeyNotFoundException $e) {
                    // retry other possible locations
                }
            }
            if ($nameserver === "") {
                $interfaces = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces";
                $subKeys = (yield $reader->listKeys($interfaces));
                foreach ($subKeys as $key) {
                    foreach (["NameServer", "DhcpNameServer"] as $property) {
                        try {
                            $nameserver = (yield $reader->read("{$key}\\{$property}"));
                            if ($nameserver !== "") {
                                break 2;
                            }
                        } catch (KeyNotFoundException $e) {
                            // retry other possible locations
                        }
                    }
                }
            }
            if ($nameserver === "") {
                throw new ConfigException("Could not find a nameserver in the Windows Registry");
            }
            $nameservers = [];
            // Microsoft documents space as delimiter, AppVeyor uses comma, we just accept both
            foreach (\explode(" ", \strtr($nameserver, ",", " ")) as $nameserver) {
                $nameserver = \trim($nameserver);
                $ip = @\inet_pton($nameserver);
                if ($ip === false) {
                    continue;
                }
                if (isset($ip[15])) {
                    // IPv6
                    $nameservers[] = "[" . $nameserver . "]:53";
                } else {
                    // IPv4
                    $nameservers[] = $nameserver . ":53";
                }
            }
            $hosts = (yield $this->hostLoader->loadHosts());
            return new Config($nameservers, $hosts);
        });
    }
}<?php

namespace Amp\Dns;

class NoRecordException extends DnsException
{
}<?php

namespace Amp\Dns;

use Amp\Failure;
use Amp\Promise;
use Amp\Success;
class BlockingFallbackResolver implements Resolver
{
    /**
     *
     */
    public function resolve(string $name, int $typeRestriction = null) : Promise
    {
        if (!\in_array($typeRestriction, [Record::A, null], true)) {
            return new Failure(new DnsException("Query for '{$name}' failed, because loading the system's DNS configuration failed and querying records other than A records isn't supported in blocking fallback mode."));
        }
        return $this->query($name, Record::A);
    }
    /**
     *
     */
    public function query(string $name, int $type) : Promise
    {
        if ($type !== Record::A) {
            return new Failure(new DnsException("Query for '{$name}' failed, because loading the system's DNS configuration failed and querying records other than A records isn't supported in blocking fallback mode."));
        }
        $result = \gethostbynamel($name);
        if ($result === false) {
            return new Failure(new DnsException("Query for '{$name}' failed, because loading the system's DNS configuration failed and blocking fallback via gethostbynamel() failed, too."));
        }
        if ($result === []) {
            return new Failure(new NoRecordException("No records returned for '{$name}' using blocking fallback mode."));
        }
        $records = [];
        foreach ($result as $record) {
            $records[] = new Record($record, Record::A, null);
        }
        return new Success($records);
    }
}<?php

namespace Amp\Dns;

use Amp\Loop;
use Amp\Promise;
const LOOP_STATE_IDENTIFIER = Resolver::class;
/**
 * Retrieve the application-wide dns resolver instance.
 *
 * @param \Amp\Dns\Resolver $resolver Optionally specify a new default dns resolver instance
 *
 * @return \Amp\Dns\Resolver Returns the application-wide dns resolver instance
 */
function resolver(Resolver $resolver = null) : Resolver
{
    if ($resolver === null) {
        $resolver = Loop::getState(LOOP_STATE_IDENTIFIER);
        if ($resolver) {
            return $resolver;
        }
        $resolver = createDefaultResolver();
    }
    Loop::setState(LOOP_STATE_IDENTIFIER, $resolver);
    return $resolver;
}
/**
 * Create a new dns resolver best-suited for the current environment.
 *
 * @return \Amp\Dns\Resolver
 */
function createDefaultResolver() : Resolver
{
    return new Rfc1035StubResolver();
}
/**
 * @see Resolver::resolve()
 */
function resolve(string $name, int $typeRestriction = null) : Promise
{
    return resolver()->resolve($name, $typeRestriction);
}
/**
 * @see Resolver::query()
 */
function query(string $name, int $type) : Promise
{
    return resolver()->query($name, $type);
}
/**
 * Checks whether a string is a valid DNS name.
 *
 * @param string $name String to check.
 *
 * @return bool
 */
function isValidName(string $name)
{
    try {
        normalizeName($name);
        return true;
    } catch (InvalidNameException $e) {
        return false;
    }
}
/**
 * Normalizes a DNS name and automatically checks it for validity.
 *
 * @param string $name DNS name.
 *
 * @return string Normalized DNS name.
 * @throws InvalidNameException If an invalid name or an IDN name without ext/intl being installed has been passed.
 */
function normalizeName(string $name) : string
{
    static $pattern = '/^(?<name>[a-z0-9]([a-z0-9-_]{0,61}[a-z0-9])?)(\\.(?&name))*\\.?$/i';
    if (\function_exists('idn_to_ascii') && \defined('INTL_IDNA_VARIANT_UTS46')) {
        if (false === ($result = \idn_to_ascii($name, 0, \INTL_IDNA_VARIANT_UTS46))) {
            throw new InvalidNameException("Name '{$name}' could not be processed for IDN.");
        }
        $name = $result;
    } elseif (\preg_match('/[\\x80-\\xff]/', $name)) {
        throw new InvalidNameException("Name '{$name}' contains non-ASCII characters and IDN support is not available. " . "Verify that ext/intl is installed for IDN support and that ICU is at least version 4.6.");
    }
    if (isset($name[253]) || !\preg_match($pattern, $name)) {
        throw new InvalidNameException("Name '{$name}' is not a valid hostname.");
    }
    if ($name[\strlen($name) - 1] === '.') {
        $name = \Phabel\Target\Php80\Polyfill::substr($name, 0, -1);
    }
    return $name;
}<?php

namespace Amp\Dns;

class DnsException extends \Exception
{
}<?php

namespace Amp\Dns;

class TimeoutException extends DnsException
{
}<?php

namespace Amp\Dns;

class InvalidNameException extends DnsException
{
}<?php

namespace Amp\Dns;

use LibDNS\Records\ResourceQTypes;
use LibDNS\Records\ResourceTypes;
final class Record
{
    const A = ResourceTypes::A;
    const AAAA = ResourceTypes::AAAA;
    const AFSDB = ResourceTypes::AFSDB;
    // const APL = ResourceTypes::APL;
    const CAA = ResourceTypes::CAA;
    const CERT = ResourceTypes::CERT;
    const CNAME = ResourceTypes::CNAME;
    const DHCID = ResourceTypes::DHCID;
    const DLV = ResourceTypes::DLV;
    const DNAME = ResourceTypes::DNAME;
    const DNSKEY = ResourceTypes::DNSKEY;
    const DS = ResourceTypes::DS;
    const HINFO = ResourceTypes::HINFO;
    // const HIP = ResourceTypes::HIP;
    // const IPSECKEY = ResourceTypes::IPSECKEY;
    const KEY = ResourceTypes::KEY;
    const KX = ResourceTypes::KX;
    const ISDN = ResourceTypes::ISDN;
    const LOC = ResourceTypes::LOC;
    const MB = ResourceTypes::MB;
    const MD = ResourceTypes::MD;
    const MF = ResourceTypes::MF;
    const MG = ResourceTypes::MG;
    const MINFO = ResourceTypes::MINFO;
    const MR = ResourceTypes::MR;
    const MX = ResourceTypes::MX;
    const NAPTR = ResourceTypes::NAPTR;
    const NS = ResourceTypes::NS;
    // const NSEC = ResourceTypes::NSEC;
    // const NSEC3 = ResourceTypes::NSEC3;
    // const NSEC3PARAM = ResourceTypes::NSEC3PARAM;
    const NULL = ResourceTypes::NULL;
    const PTR = ResourceTypes::PTR;
    const RP = ResourceTypes::RP;
    // const RRSIG = ResourceTypes::RRSIG;
    const RT = ResourceTypes::RT;
    const SIG = ResourceTypes::SIG;
    const SOA = ResourceTypes::SOA;
    const SPF = ResourceTypes::SPF;
    const SRV = ResourceTypes::SRV;
    const TXT = ResourceTypes::TXT;
    const WKS = ResourceTypes::WKS;
    const X25 = ResourceTypes::X25;
    const AXFR = ResourceQTypes::AXFR;
    const MAILB = ResourceQTypes::MAILB;
    const MAILA = ResourceQTypes::MAILA;
    const ALL = ResourceQTypes::ALL;
    private $value;
    private $type;
    private $ttl;
    /**
     *
     */
    public function __construct(string $value, int $type, int $ttl = null)
    {
        $this->value = $value;
        $this->type = $type;
        $this->ttl = $ttl;
    }
    /**
     *
     */
    public function getValue() : string
    {
        return $this->value;
    }
    /**
     *
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     *
     */
    public function getTtl()
    {
        return $this->ttl;
    }
    /**
     * Converts an record type integer back into its name as defined in this class.
     *
     * Returns "unknown (<type>)" in case a name for this record is not known.
     *
     * @param int $type Record type as integer.
     *
     * @return string Name of the constant for this record in this class.
     */
    public static function getName(int $type) : string
    {
        static $types;
        if (0 > $type || 0xffff < $type) {
            $message = \sprintf('%d does not correspond to a valid record type (must be between 0 and 65535).', $type);
            throw new \Error($message);
        }
        if ($types === null) {
            $types = \array_flip((new \ReflectionClass(self::class))->getConstants());
        }
        return $types[$type] ?? "unknown ({$type})";
    }
}<?php

namespace Amp\Dns;

use Amp\Failure;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
class HostLoader
{
    private $path;
    /**
     *
     */
    public function __construct(string $path = null)
    {
        $this->path = $path ?? $this->getDefaultPath();
    }
    /**
     *
     */
    private function getDefaultPath() : string
    {
        return \stripos(PHP_OS, "win") === 0 ? 'C:\\Windows\\system32\\drivers\\etc\\hosts' : '/etc/hosts';
    }
    /**
     *
     */
    protected function readFile(string $path) : Promise
    {
        \set_error_handler(function (int $errno, string $message) use($path) {
            throw new ConfigException("Could not read configuration file '{$path}' ({$errno}) {$message}");
        });
        try {
            // Blocking file access, but this file should be local and usually loaded only once.
            $fileContent = \file_get_contents($path);
        } catch (ConfigException $exception) {
            return new Failure($exception);
        } finally {
            \restore_error_handler();
        }
        return new Success($fileContent);
    }
    /**
     *
     */
    public function loadHosts() : Promise
    {
        return call(function () {
            try {
                $contents = (yield $this->readFile($this->path));
            } catch (ConfigException $exception) {
                return [];
            }
            $data = [];
            $lines = \array_filter(\array_map("trim", \explode("\n", $contents)));
            foreach ($lines as $line) {
                if ($line[0] === "#") {
                    // Skip comments
                    continue;
                }
                $parts = \preg_split('/\\s+/', $line);
                if (!($ip = @\inet_pton($parts[0]))) {
                    continue;
                } elseif (isset($ip[4])) {
                    $key = Record::AAAA;
                } else {
                    $key = Record::A;
                }
                for ($i = 1, $l = \count($parts); $i < $l; $i++) {
                    try {
                        $normalizedName = normalizeName($parts[$i]);
                        $data[$key][$normalizedName] = $parts[0];
                    } catch (InvalidNameException $e) {
                        // ignore invalid entries
                    }
                }
            }
            return $data;
        });
    }
}<?php

namespace Amp\Dns;

use Amp\Cache\ArrayCache;
use Amp\Cache\Cache;
use Amp\Dns\Internal\Socket;
use Amp\Dns\Internal\TcpSocket;
use Amp\Dns\Internal\UdpSocket;
use Amp\Loop;
use Amp\MultiReasonException;
use Amp\Promise;
use Amp\Success;
use LibDNS\Messages\Message;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use function Amp\call;
final class Rfc1035StubResolver implements Resolver
{
    const CACHE_PREFIX = "amphp.dns.";
    const CONFIG_NOT_LOADED = 0;
    const CONFIG_LOADED = 1;
    const CONFIG_FAILED = 2;
    /** @var ConfigLoader */
    private $configLoader;
    /** @var QuestionFactory */
    private $questionFactory;
    /** @var Config|null */
    private $config;
    /** @var int */
    private $configStatus = self::CONFIG_NOT_LOADED;
    /** @var Promise|null */
    private $pendingConfig;
    /** @var Cache */
    private $cache;
    /** @var Socket[] */
    private $sockets = [];
    /** @var Promise[] */
    private $pendingSockets = [];
    /** @var Promise[] */
    private $pendingQueries = [];
    /** @var string */
    private $gcWatcher;
    /** @var BlockingFallbackResolver */
    private $blockingFallbackResolver;
    /** @var int */
    private $nextNameserver = 0;
    /**
     *
     */
    public function __construct(Cache $cache = null, ConfigLoader $configLoader = null)
    {
        $this->cache = $cache ?? new ArrayCache(5000, 256);
        $this->configLoader = $configLoader ?? (\stripos(PHP_OS, "win") === 0 ? new WindowsConfigLoader() : new UnixConfigLoader());
        $this->questionFactory = new QuestionFactory();
        $this->blockingFallbackResolver = new BlockingFallbackResolver();
        $sockets =& $this->sockets;
        $this->gcWatcher = Loop::repeat(5000, static function () use(&$sockets) {
            if (!$sockets) {
                return;
            }
            $now = \time();
            foreach ($sockets as $key => $server) {
                if ($server->getLastActivity() < $now - 60) {
                    $server->close();
                    unset($sockets[$key]);
                }
            }
        });
        Loop::unreference($this->gcWatcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->gcWatcher);
    }
    /**
     * @inheritdoc
     */
    public function resolve(string $name, int $typeRestriction = null) : Promise
    {
        if ($typeRestriction !== null && $typeRestriction !== Record::A && $typeRestriction !== Record::AAAA) {
            throw new \Error("Invalid value for parameter 2: null|Record::A|Record::AAAA expected");
        }
        return call(function () use($name, $typeRestriction) {
            if ($this->configStatus === self::CONFIG_NOT_LOADED) {
                (yield $this->reloadConfig());
            }
            if ($this->configStatus === self::CONFIG_FAILED) {
                return $this->blockingFallbackResolver->resolve($name, $typeRestriction);
            }
            switch ($typeRestriction) {
                case Record::A:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        return [new Record($name, Record::A, null)];
                    }
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        throw new DnsException("Got an IPv6 address, but type is restricted to IPv4");
                    }
                    break;
                case Record::AAAA:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        return [new Record($name, Record::AAAA, null)];
                    }
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        throw new DnsException("Got an IPv4 address, but type is restricted to IPv6");
                    }
                    break;
                default:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        return [new Record($name, Record::A, null)];
                    }
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        return [new Record($name, Record::AAAA, null)];
                    }
                    break;
            }
            $dots = \Phabel\Target\Php80\Polyfill::substr_count($name, ".");
            // Should be replaced with $name[-1] from 7.1
            $trailingDot = \Phabel\Target\Php80\Polyfill::substr($name, -1, 1) === ".";
            $name = normalizeName($name);
            if ($records = $this->queryHosts($name, $typeRestriction)) {
                return $records;
            }
            // Follow RFC 6761 and never send queries for localhost to the caching DNS server
            // Usually, these queries are already resolved via queryHosts()
            if ($name === 'localhost') {
                return $typeRestriction === Record::AAAA ? [new Record('::1', Record::AAAA, null)] : [new Record('127.0.0.1', Record::A, null)];
            }
            $searchList = [null];
            if (!$trailingDot && $dots < $this->config->getNdots()) {
                $searchList = \array_merge($this->config->getSearchList(), $searchList);
            }
            foreach ($searchList as $searchIndex => $search) {
                for ($redirects = 0; $redirects < 5; $redirects++) {
                    $searchName = $name;
                    if ($search !== null) {
                        $searchName = $name . "." . $search;
                    }
                    try {
                        if ($typeRestriction) {
                            return (yield $this->query($searchName, $typeRestriction));
                        }
                        try {
                            list(, $records) = (yield Promise\some([$this->query($searchName, Record::A), $this->query($searchName, Record::AAAA)]));
                            return \array_merge(...$records);
                        } catch (MultiReasonException $e) {
                            $errors = [];
                            foreach ($e->getReasons() as $reason) {
                                if ($reason instanceof NoRecordException) {
                                    throw $reason;
                                }
                                if ($searchIndex < \count($searchList) - 1 && \in_array($reason->getCode(), [2, 3], true)) {
                                    continue 2;
                                }
                                $errors[] = $reason->getMessage();
                            }
                            throw new DnsException("All query attempts failed for {$searchName}: " . \implode(", ", $errors), 0, $e);
                        }
                    } catch (NoRecordException $e) {
                        try {
                            /** @var Record[] $cnameRecords */
                            $cnameRecords = (yield $this->query($searchName, Record::CNAME));
                            $name = $cnameRecords[0]->getValue();
                            continue;
                        } catch (NoRecordException $e) {
                            /** @var Record[] $dnameRecords */
                            $dnameRecords = (yield $this->query($searchName, Record::DNAME));
                            $name = $dnameRecords[0]->getValue();
                            continue;
                        }
                    } catch (DnsException $e) {
                        if ($searchIndex < \count($searchList) - 1 && \in_array($e->getCode(), [2, 3], true)) {
                            continue 2;
                        }
                        throw $e;
                    }
                }
            }
            throw new DnsException("Giving up resolution of '{$searchName}', too many redirects");
        });
    }
    /**
     * Reloads the configuration in the background.
     *
     * Once it's finished, the configuration will be used for new requests.
     *
     * @return Promise
     */
    public function reloadConfig() : Promise
    {
        if ($this->pendingConfig) {
            return $this->pendingConfig;
        }
        $promise = call(function () {
            try {
                $this->config = (yield $this->configLoader->loadConfig());
                $this->configStatus = self::CONFIG_LOADED;
            } catch (ConfigException $e) {
                $this->configStatus = self::CONFIG_FAILED;
                try {
                    \trigger_error("Could not load the system's DNS configuration, using synchronous, blocking fallback", \E_USER_WARNING);
                } catch (\Throwable $triggerException) {
                    \set_error_handler(null);
                    \trigger_error("Could not load the system's DNS configuration, using synchronous, blocking fallback", \E_USER_WARNING);
                    \restore_error_handler();
                }
            }
        });
        $this->pendingConfig = $promise;
        $promise->onResolve(function () {
            $this->pendingConfig = null;
        });
        return $promise;
    }
    /**
     * @inheritdoc
     */
    public function query(string $name, int $type) : Promise
    {
        $pendingQueryKey = $type . " " . $name;
        if (isset($this->pendingQueries[$pendingQueryKey])) {
            return $this->pendingQueries[$pendingQueryKey];
        }
        $promise = call(function () use($name, $type) {
            if ($this->configStatus === self::CONFIG_NOT_LOADED) {
                (yield $this->reloadConfig());
            }
            if ($this->configStatus === self::CONFIG_FAILED) {
                return $this->blockingFallbackResolver->query($name, $type);
            }
            $name = $this->normalizeName($name, $type);
            $question = $this->createQuestion($name, $type);
            if (null !== ($cachedValue = (yield $this->cache->get($this->getCacheKey($name, $type))))) {
                return $this->decodeCachedResult($name, $type, $cachedValue);
            }
            $nameservers = $this->selectNameservers();
            $nameserversCount = \count($nameservers);
            $attempts = $this->config->getAttempts();
            $protocol = "udp";
            $attempt = 0;
            /** @var Socket $socket */
            $uri = $protocol . "://" . $nameservers[0];
            $socket = (yield $this->getSocket($uri));
            $attemptDescription = [];
            while ($attempt < $attempts) {
                try {
                    if (!$socket->isAlive()) {
                        unset($this->sockets[$uri]);
                        $socket->close();
                        $uri = $protocol . "://" . $nameservers[$attempt % $nameserversCount];
                        $socket = (yield $this->getSocket($uri));
                    }
                    $attemptDescription[] = $uri;
                    /** @var Message $response */
                    $response = (yield $socket->ask($question, $this->config->getTimeout()));
                    $this->assertAcceptableResponse($response, $name);
                    // UDP sockets are never reused, they're not in the $this->sockets map
                    if ($protocol === "udp") {
                        // Defer call, because it interferes with the unreference() call in Internal\Socket otherwise
                        Loop::defer(static function () use($socket) {
                            $socket->close();
                        });
                    }
                    if ($response->isTruncated()) {
                        if ($protocol !== "tcp") {
                            // Retry with TCP, don't count attempt
                            $protocol = "tcp";
                            $uri = $protocol . "://" . $nameservers[$attempt % $nameserversCount];
                            $socket = (yield $this->getSocket($uri));
                            continue;
                        }
                        throw new DnsException("Server returned a truncated response for '{$name}' (" . Record::getName($type) . ")");
                    }
                    $answers = $response->getAnswerRecords();
                    $result = [];
                    $ttls = [];
                    /** @var \LibDNS\Records\Resource $record */
                    foreach ($answers as $record) {
                        $recordType = $record->getType();
                        $result[$recordType][] = (string) $record->getData();
                        // Cache for max one day
                        $ttls[$recordType] = \min($ttls[$recordType] ?? 86400, $record->getTTL());
                    }
                    foreach ($result as $recordType => $records) {
                        // We don't care here whether storing in the cache fails
                        $this->cache->set($this->getCacheKey($name, $recordType), \json_encode($records), $ttls[$recordType]);
                    }
                    if (!isset($result[$type])) {
                        // "it MUST NOT cache it for longer than five (5) minutes" per RFC 2308 section 7.1
                        $this->cache->set($this->getCacheKey($name, $type), \json_encode([]), 300);
                        throw new NoRecordException("No records returned for '{$name}' (" . Record::getName($type) . ")");
                    }
                    return \array_map(static function ($data) use($type, $ttls) {
                        return new Record($data, $type, $ttls[$type]);
                    }, $result[$type]);
                } catch (TimeoutException $e) {
                    // Defer call, because it might interfere with the unreference() call in Internal\Socket otherwise
                    Loop::defer(function () use($socket, $uri) {
                        unset($this->sockets[$uri]);
                        $socket->close();
                    });
                    $uri = $protocol . "://" . $nameservers[++$attempt % $nameserversCount];
                    $socket = (yield $this->getSocket($uri));
                    continue;
                }
            }
            throw new TimeoutException(\sprintf("No response for '%s' (%s) from any nameserver within %d ms after %d attempts, tried %s", $name, Record::getName($type), $this->config->getTimeout(), $attempts, \implode(", ", $attemptDescription)));
        });
        $this->pendingQueries[$type . " " . $name] = $promise;
        $promise->onResolve(function () use($name, $type) {
            unset($this->pendingQueries[$type . " " . $name]);
        });
        return $promise;
    }
    /**
     *
     */
    private function queryHosts(string $name, int $typeRestriction = null) : array
    {
        $hosts = $this->config->getKnownHosts();
        $records = [];
        $returnIPv4 = $typeRestriction === null || $typeRestriction === Record::A;
        $returnIPv6 = $typeRestriction === null || $typeRestriction === Record::AAAA;
        if ($returnIPv4 && isset($hosts[Record::A][$name])) {
            $records[] = new Record($hosts[Record::A][$name], Record::A, null);
        }
        if ($returnIPv6 && isset($hosts[Record::AAAA][$name])) {
            $records[] = new Record($hosts[Record::AAAA][$name], Record::AAAA, null);
        }
        return $records;
    }
    /**
     *
     */
    private function normalizeName(string $name, int $type)
    {
        if ($type === Record::PTR) {
            if (($packedIp = @\inet_pton($name)) !== false) {
                if (isset($packedIp[4])) {
                    // IPv6
                    $name = \wordwrap(\strrev(\bin2hex($packedIp)), 1, ".", true) . ".ip6.arpa";
                } else {
                    // IPv4
                    $name = \inet_ntop(\strrev($packedIp)) . ".in-addr.arpa";
                }
            }
        } elseif (\in_array($type, [Record::A, Record::AAAA], true)) {
            $name = normalizeName($name);
        }
        return $name;
    }
    /**
     * @param string $name
     * @param int $type
     *
     * @return Question
     */
    private function createQuestion(string $name, int $type) : Question
    {
        if (0 > $type || 0xffff < $type) {
            $message = \sprintf('%d does not correspond to a valid record type (must be between 0 and 65535).', $type);
            throw new \Error($message);
        }
        $question = $this->questionFactory->create($type);
        $question->setName($name);
        return $question;
    }
    /**
     *
     */
    private function getCacheKey(string $name, int $type) : string
    {
        return self::CACHE_PREFIX . $name . "#" . $type;
    }
    /**
     *
     */
    private function decodeCachedResult(string $name, int $type, string $encoded) : array
    {
        $decoded = \json_decode($encoded, true);
        if (!$decoded) {
            throw new NoRecordException("No records returned for {$name} (cached result)");
        }
        $result = [];
        foreach ($decoded as $data) {
            $result[] = new Record($data, $type);
        }
        return $result;
    }
    /**
     *
     */
    private function getSocket($uri) : Promise
    {
        // We use a new socket for each UDP request, as that increases the entropy and mitigates response forgery.
        if (\Phabel\Target\Php80\Polyfill::substr($uri, 0, 3) === "udp") {
            return UdpSocket::connect($uri);
        }
        // Over TCP we might reuse sockets if the server allows to keep them open. Sequence IDs in TCP are already
        // better than a random port. Additionally, a TCP connection is more expensive.
        if (isset($this->sockets[$uri])) {
            return new Success($this->sockets[$uri]);
        }
        if (isset($this->pendingSockets[$uri])) {
            return $this->pendingSockets[$uri];
        }
        $server = TcpSocket::connect($uri);
        $server->onResolve(function ($error, $server) use($uri) {
            unset($this->pendingSockets[$uri]);
            if (!$error) {
                $this->sockets[$uri] = $server;
            }
        });
        return $server;
    }
    /**
     * @throws DnsException
     */
    private function assertAcceptableResponse(Message $response, string $name)
    {
        if ($response->getResponseCode() !== 0) {
            // https://www.iana.org/assignments/dns-parameters/dns-parameters.xhtml
            $errors = [1 => 'FormErr', 2 => 'ServFail', 3 => 'NXDomain', 4 => 'NotImp', 5 => 'Refused', 6 => 'YXDomain', 7 => 'YXRRSet', 8 => 'NXRRSet', 9 => 'NotAuth', 10 => 'NotZone', 11 => 'DSOTYPENI', 16 => 'BADVERS', 17 => 'BADKEY', 18 => 'BADTIME', 19 => 'BADMODE', 20 => 'BADNAME', 21 => 'BADALG', 22 => 'BADTRUNC', 23 => 'BADCOOKIE'];
            throw new DnsException(\sprintf("Name resolution failed for '%s'; server returned error code: %d (%s)", $name, $response->getResponseCode(), $errors[$response->getResponseCode()] ?? 'UNKNOWN'), $response->getResponseCode());
        }
    }
    /**
     *
     */
    private function selectNameservers() : array
    {
        $nameservers = $this->config->getNameservers();
        if ($this->config->isRotationEnabled() && ($nameserversCount = \count($nameservers)) > 1) {
            $nameservers = \array_merge(\array_slice($nameservers, $this->nextNameserver), \array_slice($nameservers, 0, $this->nextNameserver));
            $this->nextNameserver = ++$this->nextNameserver % $nameserversCount;
        }
        return $nameservers;
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
final class ConnectionConfig extends SqlConnectionConfig
{
    public const DEFAULT_PORT = 5432;
    public const SSL_MODES = ['disable', 'allow', 'prefer', 'require', 'verify-ca', 'verify-full'];
    /** @var string|null */
    private $sslMode = null;
    /** @var string|null */
    private $string;
    /**
     *
     */
    public static function fromString(string $connectionString) : self
    {
        $parts = self::parseConnectionString($connectionString);
        if (!isset($parts["host"])) {
            throw new \Error("Host must be provided in connection string");
        }
        $config = new self($parts["host"], (int) ($parts["port"] ?? self::DEFAULT_PORT), $parts["user"] ?? null, $parts["password"] ?? null, $parts["db"] ?? null);
        if (isset($parts["sslmode"])) {
            $config = $config->withSslMode($parts["sslmode"]);
        }
        return $config;
    }
    /**
     *
     */
    public function __construct(string $host, int $port = self::DEFAULT_PORT, string $user = null, string $password = null, string $database = null)
    {
        parent::__construct($host, $port, $user, $password, $database);
    }
    /**
     *
     */
    public function __clone()
    {
        $this->string = null;
    }
    /**
     *
     */
    public function getSslMode() : ?string
    {
        return $this->sslMode;
    }
    /**
     *
     */
    public function withSslMode(string $mode) : self
    {
        if (!\in_array($mode, self::SSL_MODES, true)) {
            throw new \Error('Invalid SSL mode, must be one of: ' . \implode(', ', self::SSL_MODES));
        }
        $new = clone $this;
        $new->sslMode = $mode;
        return $new;
    }
    /**
     *
     */
    public function withoutSslMode() : self
    {
        $new = clone $this;
        $new->sslMode = null;
        return $new;
    }
    /**
     * @return string Connection string used with ext-pgsql and pecl-pq.
     */
    public function getConnectionString() : string
    {
        if ($this->string !== null) {
            return $this->string;
        }
        $chunks = ["host=" . $this->getHost(), "port=" . $this->getPort()];
        $user = $this->getUser();
        if ($user !== null) {
            $chunks[] = "user=" . $user;
        }
        $password = $this->getPassword();
        if ($password !== null) {
            $chunks[] = "password=" . $password;
        }
        $database = $this->getDatabase();
        if ($database !== null) {
            $chunks[] = "dbname=" . $database;
        }
        if ($this->sslMode !== null) {
            $chunks[] = "sslmode=" . $this->sslMode;
        }
        return $this->string = \implode(" ", $chunks);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Transaction as SqlTransaction;
use Amp\Sql\TransactionError;
use function Amp\call;
final class ConnectionTransaction implements Transaction
{
    /** @var Handle|null */
    private $handle;
    /** @var int */
    private $isolation;
    /** @var callable */
    private $release;
    /** @var int */
    private $refCount = 1;
    /**
     * @param Handle $handle
     * @param callable $release
     * @param int $isolation
     *
     * @throws \Error If the isolation level is invalid.
     */
    public function __construct(Handle $handle, callable $release, int $isolation = SqlTransaction::ISOLATION_COMMITTED)
    {
        switch ($isolation) {
            case SqlTransaction::ISOLATION_UNCOMMITTED:
            case SqlTransaction::ISOLATION_COMMITTED:
            case SqlTransaction::ISOLATION_REPEATABLE:
            case SqlTransaction::ISOLATION_SERIALIZABLE:
                $this->isolation = $isolation;
                break;
            default:
                throw new \Error("Isolation must be a valid transaction isolation level");
        }
        $this->handle = $handle;
        $refCount =& $this->refCount;
        $this->release = static function () use(&$refCount, $release) {
            if (--$refCount === 0) {
                $release();
            }
        };
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->handle && $this->handle->isAlive()) {
            $this->rollback();
            // Invokes $this->release callback.
        }
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->handle->getLastUsedAt();
    }
    /**
     * {@inheritdoc}
     *
     * Closes and commits all changes in the transaction.
     */
    public function close() : void
    {
        if ($this->handle) {
            $this->commit();
            // Invokes $this->release callback.
        }
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle && $this->handle->isAlive();
    }
    /**
     * @return bool True if the transaction is active, false if it has been committed or rolled back.
     */
    public function isActive() : bool
    {
        return $this->handle !== null;
    }
    /**
     * @return int
     */
    public function getIsolationLevel() : int
    {
        return $this->isolation;
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function query(string $sql) : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            ++$this->refCount;
            try {
                $result = (yield $this->handle->query($sql));
            } finally {
                ($this->release)();
            }
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return new PooledResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function prepare(string $sql) : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            ++$this->refCount;
            try {
                $statement = (yield $this->handle->prepare($sql));
            } catch (\Throwable $exception) {
                ($this->release)();
                throw $exception;
            }
            return new PooledStatement($statement, $this->release);
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql, $params) {
            ++$this->refCount;
            try {
                $result = (yield $this->handle->execute($sql, $params));
            } finally {
                ($this->release)();
            }
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return new PooledResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->handle->notify($channel, $payload);
    }
    /**
     * Commits the transaction and makes it inactive.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function commit() : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->handle->query("COMMIT");
        $this->handle = null;
        $promise->onResolve($this->release);
        return $promise;
    }
    /**
     * Rolls back the transaction and makes it inactive.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollback() : Promise
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->handle->query("ROLLBACK");
        $this->handle = null;
        $promise->onResolve($this->release);
        return $promise;
    }
    /**
     * Creates a savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function createSavepoint(string $identifier) : Promise
    {
        return $this->query("SAVEPOINT " . $this->quoteName($identifier));
    }
    /**
     * Rolls back to the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function rollbackTo(string $identifier) : Promise
    {
        return $this->query("ROLLBACK TO " . $this->quoteName($identifier));
    }
    /**
     * Releases the savepoint with the given identifier.
     *
     * @param string $identifier Savepoint identifier.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function releaseSavepoint(string $identifier) : Promise
    {
        return $this->query("RELEASE SAVEPOINT " . $this->quoteName($identifier));
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function quoteString(string $data) : string
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->handle->quoteString($data);
    }
    /**
     * {@inheritdoc}
     *
     * @throws TransactionError If the transaction has been committed or rolled back.
     */
    public function quoteName(string $name) : string
    {
        if ($this->handle === null) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->handle->quoteName($name);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Statement;
final class PqStatement implements Statement
{
    /** @var PqHandle */
    private $handle;
    /** @var string */
    private $name;
    /** @var string */
    private $sql;
    /** @var array */
    private $params;
    /** @var int */
    private $lastUsedAt;
    /**
     * @param PqHandle $handle
     * @param string $name Statement name.
     * @param string $sql Original prepared SQL query.
     * @param string[] $params Parameter indices to parameter names.
     */
    public function __construct(PqHandle $handle, string $name, string $sql, array $params)
    {
        $this->handle = $handle;
        $this->name = $name;
        $this->params = $params;
        $this->sql = $sql;
        $this->lastUsedAt = \time();
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->handle->statementDeallocate($this->name);
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public function getQuery() : string
    {
        return $this->sql;
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     * {@inheritdoc}
     */
    public function execute(array $params = []) : Promise
    {
        $this->lastUsedAt = \time();
        return $this->handle->statementExecute($this->name, Internal\replaceNamedParams($params, $this->params));
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\Common\PooledStatement as SqlPooledStatement;
use Amp\Sql\ResultSet as SqlResultSet;
final class PooledStatement extends SqlPooledStatement
{
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\FailureException;
use Amp\Success;
final class PgSqlResultSet implements ResultSet
{
    /** @var resource PostgreSQL result resource. */
    private $handle;
    /** @var array<int, array{string, string}> */
    private $types;
    /** @var int */
    private $position = 0;
    /** @var mixed Last row emitted. */
    private $currentRow;
    /** @var int[] */
    private $fieldTypes = [];
    /** @var string[] */
    private $fieldNames = [];
    /** @var Internal\ArrayParser */
    private $parser;
    /**
     * @param resource $handle PostgreSQL result resource.
     * @param array<int, array{string, string}> $types
     */
    public function __construct($handle, array $types = [])
    {
        $this->handle = $handle;
        $this->types = $types;
        $numFields = \pg_num_fields($this->handle);
        for ($i = 0; $i < $numFields; ++$i) {
            $this->fieldNames[] = \pg_field_name($this->handle, $i);
            $this->fieldTypes[] = \pg_field_type_oid($this->handle, $i);
        }
        $this->parser = new Internal\ArrayParser();
    }
    /**
     * Frees the result resource.
     */
    public function __destruct()
    {
        \pg_free_result($this->handle);
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        $this->currentRow = null;
        if (++$this->position > \pg_num_rows($this->handle)) {
            return new Success(false);
        }
        return new Success(true);
    }
    /**
     * {@inheritdoc}
     */
    public function getCurrent() : array
    {
        if ($this->currentRow !== null) {
            return $this->currentRow;
        }
        if ($this->position > \pg_num_rows($this->handle)) {
            throw new \Error("No more rows remain in the result set");
        }
        $result = \pg_fetch_array($this->handle, null, \PGSQL_NUM);
        if ($result === false) {
            $message = \pg_result_error($this->handle);
            \pg_free_result($this->handle);
            throw new FailureException($message);
        }
        $columnCount = \count($result);
        for ($column = 0; $column < $columnCount; ++$column) {
            if ($result[$column] === null) {
                continue;
            }
            $result[$column] = $this->cast($this->fieldTypes[$column], $result[$column]);
        }
        return $this->currentRow = \array_combine($this->fieldNames, $result);
    }
    /**
     * @see https://github.com/postgres/postgres/blob/REL_14_STABLE/src/include/catalog/pg_type.dat for OID types.
     * @see https://www.postgresql.org/docs/14/catalog-pg-type.html for pg_type catalog docs.
     *
     * @param int $oid
     * @param string $value
     *
     * @return (array | bool | float | int) Cast value.
     *
     * @throws ParseException
     */
    private function cast(int $oid, string $value)
    {
        [$type, $delimiter, $element] = $this->types[$oid] ?? ['S', ',', 0];
        switch ($type) {
            case 'A':
                // Arrays
                return $this->parser->parse($value, function (string $data) use($element) {
                    return $this->cast($element, $data);
                }, $delimiter);
            case 'B':
                // Binary
                return $value === 't';
            case 'N':
                // Numeric
                switch ($oid) {
                    case 700:
                    // float4
                    case 701:
                    // float8
                    case 790:
                    // money
                    case 1700:
                        // numeric
                        return (float) $value;
                    default:
                        // Cast all other numeric types to an integer.
                        return (int) $value;
                }
            default:
                // Return all other types as strings.
                return $value;
        }
    }
    /**
     * @return int Number of rows in the result set.
     */
    public function numRows() : int
    {
        return \pg_num_rows($this->handle);
    }
    /**
     * @return int Number of fields in each row.
     */
    public function getFieldCount() : int
    {
        return \pg_num_fields($this->handle);
    }
    /**
     * @param int $fieldNum
     *
     * @return string Column name at index $fieldNum
     *
     * @throws \Error If the field number does not exist in the result.
     */
    public function getFieldName(int $fieldNum) : string
    {
        if (0 > $fieldNum || $this->getFieldCount() <= $fieldNum) {
            throw new \Error(\sprintf('No field with index %d in result', $fieldNum));
        }
        return \pg_field_name($this->handle, $fieldNum);
    }
    /**
     * @param string $fieldName
     *
     * @return int Index of field with given name.
     *
     * @throws \Error If the field name does not exist in the result.
     */
    public function getFieldIndex(string $fieldName) : int
    {
        $result = \pg_field_num($this->handle, $fieldName);
        if (-1 === $result) {
            throw new \Error(\sprintf('No field with name "%s" in result', $fieldName));
        }
        return $result;
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Success;
use pq;
final class PqBufferedResultSet implements ResultSet
{
    /** @var \pq\Result */
    private $result;
    /** @var int */
    private $position = 0;
    /** @var mixed Last row emitted. */
    private $currentRow;
    /**
     * @param pq\Result $result PostgreSQL result object.
     */
    public function __construct(pq\Result $result)
    {
        $this->result = $result;
        $this->result->autoConvert = pq\Result::CONV_SCALAR | pq\Result::CONV_ARRAY;
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        $this->currentRow = null;
        if (++$this->position > $this->result->numRows) {
            return new Success(false);
        }
        return new Success(true);
    }
    /**
     * {@inheritdoc}
     */
    public function getCurrent() : array
    {
        if ($this->currentRow !== null) {
            return $this->currentRow;
        }
        if ($this->position > $this->result->numRows) {
            throw new \Error("No more rows remain in the result set");
        }
        return $this->currentRow = $this->result->fetchRow(pq\Result::FETCH_ASSOC);
    }
    /**
     *
     */
    public function getNumRows() : int
    {
        return $this->result->numRows;
    }
    /**
     *
     */
    public function getFieldCount() : int
    {
        return $this->result->numCols;
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\CommandResult;
final class PgSqlCommandResult implements CommandResult
{
    /** @var resource PostgreSQL result resource. */
    private $handle;
    /**
     * @param resource $handle PostgreSQL result resource.
     */
    public function __construct($handle)
    {
        $this->handle = $handle;
    }
    /**
     * Frees the result resource.
     */
    public function __destruct()
    {
        \pg_free_result($this->handle);
    }
    /**
     * @return int Number of rows affected by the INSERT, UPDATE, or DELETE query.
     */
    public function getAffectedRowCount() : int
    {
        return \pg_affected_rows($this->handle);
    }
    /**
    * @deprecated This is not meant to be used to get the last insertion ID. Use `INSERT ... RETURNING column_name`
    to get the last auto-increment ID.
    *
    * $sql = "INSERT INTO person (lastname, firstname) VALUES (?, ?) RETURNING id;"
    $statement = yield $pool->prepare($sql);
    $result = yield $statement->execute(['Doe', 'John']);
    if (!yield $result->advance()) {
    throw new \RuntimeException("Insertion failed");
    }
    $id = $result->getCurrent()['id'];
    *
    * @return string
    */
    public function getLastOid() : string
    {
        return (string) \pg_last_oid($this->handle);
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\FailureException;
class ParseException extends FailureException
{
    /**
     *
     */
    public function __construct(string $message = '')
    {
        $message = "Parse error while splitting array" . ($message === '' ? '' : ": " . $message);
        parent::__construct($message);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
interface Receiver extends Executor
{
    /**
     * @param string $channel Channel name.
     *
     * @return Promise<Listener>
     *
     * @throws \Amp\Sql\FailureException If the operation fails due to unexpected condition.
     * @throws \Amp\Sql\ConnectionException If the connection to the database is lost.
     * @throws \Amp\Sql\QueryError If the operation fails due to an error in the query (such as a syntax error).
     */
    public function listen(string $channel) : Promise;
}<?php

namespace Amp\Postgres;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Sql\ConnectionException;
use pq;
final class PqConnection extends Connection implements Link
{
    /** @var PqHandle */
    private $handle;
    /**
     * @param ConnectionConfig $connectionConfig
     * @param CancellationToken $token
     *
     * @return Promise<PqConnection>
     */
    public static function connect(ConnectionConfig $connectionConfig, ?CancellationToken $token = null) : Promise
    {
        try {
            $connection = new pq\Connection($connectionConfig->getConnectionString(), pq\Connection::ASYNC);
        } catch (pq\Exception $exception) {
            return new Failure(new ConnectionException("Could not connect to PostgreSQL server", 0, $exception));
        }
        $connection->nonblocking = true;
        $connection->unbuffered = true;
        $deferred = new Deferred();
        $callback = function () use($connection, $deferred) : void {
            switch ($connection->poll()) {
                case pq\Connection::POLLING_READING:
                // Connection not ready, poll again.
                case pq\Connection::POLLING_WRITING:
                    // Still writing...
                    return;
                case pq\Connection::POLLING_FAILED:
                    $deferred->fail(new ConnectionException($connection->errorMessage));
                    return;
                case pq\Connection::POLLING_OK:
                    $deferred->resolve(new self($connection));
                    return;
            }
        };
        $poll = Loop::onReadable($connection->socket, $callback);
        $await = Loop::onWritable($connection->socket, $callback);
        $promise = $deferred->promise();
        $token = $token ?? new NullCancellationToken();
        $id = $token->subscribe([$deferred, "fail"]);
        $promise->onResolve(function () use($poll, $await, $id, $token) : void {
            $token->unsubscribe($id);
            Loop::cancel($poll);
            Loop::cancel($await);
        });
        return $promise;
    }
    /**
     * @param \pq\Connection $handle
     */
    public function __construct(pq\Connection $handle)
    {
        $this->handle = new PqHandle($handle);
        parent::__construct($this->handle);
    }
    /**
     * @return bool True if result sets are buffered in memory, false if unbuffered.
     */
    public function isBufferingResults() : bool
    {
        return $this->handle->isBufferingResults();
    }
    /**
     * Sets result sets to be fully buffered in local memory.
     */
    public function shouldBufferResults() : void
    {
        $this->handle->shouldBufferResults();
    }
    /**
     * Sets result sets to be streamed from the database server.
     */
    public function shouldNotBufferResults() : void
    {
        $this->handle->shouldNotBufferResults();
    }
}<?php

namespace Amp\Postgres;

use Amp\Iterator;
use Amp\Promise;
final class ConnectionListener implements Listener
{
    /** @var \Amp\Iterator */
    private $iterator;
    /** @var string */
    private $channel;
    /** @var callable|null */
    private $unlisten;
    /**
     * @param \Amp\Iterator $iterator Iterator emitting notificatons on the channel.
     * @param string $channel Channel name.
     * @param callable(string $channel):  $unlisten Function invoked to unlisten from the channel.
     */
    public function __construct(Iterator $iterator, string $channel, callable $unlisten)
    {
        $this->iterator = $iterator;
        $this->channel = $channel;
        $this->unlisten = $unlisten;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->unlisten) {
            $this->unlisten();
            // Invokes $this->queue->complete().
        }
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        return $this->iterator->advance();
    }
    /**
     * {@inheritdoc}
     *
     * @return Notification
     */
    public function getCurrent() : Notification
    {
        return $this->iterator->getCurrent();
    }
    /**
     * @return string Channel name.
     */
    public function getChannel() : string
    {
        return $this->channel;
    }
    /**
     * @return bool
     */
    public function isListening() : bool
    {
        return $this->unlisten !== null;
    }
    /**
     * Unlistens from the channel. No more values will be emitted from this listener.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws \Error If this method was previously invoked.
     */
    public function unlisten() : Promise
    {
        if (!$this->unlisten) {
            throw new \Error("Already unlistened on this channel");
        }
        /** @var Promise $promise */
        $promise = ($this->unlisten)($this->channel);
        $this->unlisten = null;
        return $promise;
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
use Amp\Sql\Connector;
use Amp\Sql\FailureException;
use Amp\TimeoutCancellationToken;
final class TimeoutConnector implements Connector
{
    const DEFAULT_TIMEOUT = 5000;
    /** @var int */
    private $timeout;
    /**
     * @param int $timeout Milliseconds until connections attempts are cancelled.
     */
    public function __construct(int $timeout = self::DEFAULT_TIMEOUT)
    {
        $this->timeout = $timeout;
    }
    /**
     * {@inheritdoc}
     *
     * @throws FailureException If connecting fails.
     *
     * @throws \Error If neither ext-pgsql or pecl-pq is loaded.
     */
    public function connect(SqlConnectionConfig $connectionConfig) : Promise
    {
        if (!$connectionConfig instanceof ConnectionConfig) {
            throw new \TypeError(\sprintf("Must provide an instance of %s to Postgres connectors", ConnectionConfig::class));
        }
        $token = new TimeoutCancellationToken($this->timeout);
        if (\extension_loaded("pq")) {
            return PqConnection::connect($connectionConfig, $token);
        }
        if (\extension_loaded("pgsql")) {
            return PgSqlConnection::connect($connectionConfig, $token);
        }
        throw new \Error("amphp/postgres requires either pecl-pq or ext-pgsql");
    }
}<?php

namespace Amp\Postgres;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Sql\ConnectionException;
final class PgSqlConnection extends Connection implements Link
{
    /**
     * @param ConnectionConfig $connectionConfig
     * @param CancellationToken $token
     *
     * @return Promise<PgSqlConnection>
     *
     * @throws \Error If pecl-ev is used as a loop extension.
     */
    public static function connect(ConnectionConfig $connectionConfig, ?CancellationToken $token = null) : Promise
    {
        // @codeCoverageIgnoreStart
        if (Loop::get()->getHandle() instanceof \EvLoop) {
            throw new \Error('ext-pgsql is not compatible with pecl-ev; use pecl-pq or a different loop extension');
        }
        // @codeCoverageIgnoreEnd
        if (!($connection = @\pg_connect($connectionConfig->getConnectionString(), \PGSQL_CONNECT_ASYNC | \PGSQL_CONNECT_FORCE_NEW))) {
            return new Failure(new ConnectionException("Failed to create connection resource"));
        }
        if (\pg_connection_status($connection) === \PGSQL_CONNECTION_BAD) {
            return new Failure(new ConnectionException(\pg_last_error($connection)));
        }
        if (!($socket = \pg_socket($connection))) {
            return new Failure(new ConnectionException("Failed to access connection socket"));
        }
        $deferred = new Deferred();
        $id = \sha1($connectionConfig->getHost() . $connectionConfig->getPort() . $connectionConfig->getUser());
        $callback = function ($watcher, $resource) use($connection, $deferred, $id) : void {
            switch (\pg_connect_poll($connection)) {
                case \PGSQL_POLLING_READING:
                // Connection not ready, poll again.
                case \PGSQL_POLLING_WRITING:
                    // Still writing...
                    return;
                case \PGSQL_POLLING_FAILED:
                    $deferred->fail(new ConnectionException(\pg_last_error($connection)));
                    return;
                case \PGSQL_POLLING_OK:
                    $deferred->resolve(new self($connection, $resource, $id));
                    return;
            }
        };
        $poll = Loop::onReadable($socket, $callback);
        $await = Loop::onWritable($socket, $callback);
        $promise = $deferred->promise();
        $token = $token ?? new NullCancellationToken();
        $id = $token->subscribe([$deferred, "fail"]);
        $promise->onResolve(function ($exception) use($connection, $poll, $await, $id, $token) : void {
            if ($exception) {
                \pg_close($connection);
            }
            $token->unsubscribe($id);
            Loop::cancel($poll);
            Loop::cancel($await);
        });
        return $promise;
    }
    /**
     * @param resource $handle PostgreSQL connection handle.
     * @param resource $socket PostgreSQL connection stream socket.
     * @param string $id Connection identifier for determining which cached type table to use.
     */
    public function __construct($handle, $socket, string $id = '')
    {
        parent::__construct(new PgSqlHandle($handle, $socket, $id));
    }
}<?php

namespace Amp\Postgres;

use Amp\Coroutine;
use Amp\Deferred;
use Amp\Emitter;
use Amp\Loop;
use Amp\Promise;
use Amp\Sql\ConnectionException;
use Amp\Sql\FailureException;
use Amp\Sql\QueryError;
use Amp\Struct;
use Amp\Success;
use pq;
use function Amp\call;
use function Amp\coroutine;
final class PqHandle implements Handle
{
    /** @var pq\Connection PostgreSQL connection object. */
    private $handle;
    /** @var Deferred|null */
    private $deferred;
    /** @var Deferred|null */
    private $busy;
    /** @var string */
    private $poll;
    /** @var string */
    private $await;
    /** @var Emitter[] */
    private $listeners = [];
    /** @var array<string, object{refCount: int, promise: Promise<string>, statement: pq\Statement, sql: string}> */
    private $statements = [];
    /** @var int */
    private $lastUsedAt;
    /**
     * Connection constructor.
     *
     * @param pq\Connection $handle
     */
    public function __construct(pq\Connection $handle)
    {
        $this->handle = $handle;
        $this->lastUsedAt = \time();
        $handle =& $this->handle;
        $lastUsedAt =& $this->lastUsedAt;
        $deferred =& $this->deferred;
        $listeners =& $this->listeners;
        $this->poll = Loop::onReadable($this->handle->socket, static function ($watcher) use(&$deferred, &$lastUsedAt, &$listeners, &$handle) : void {
            $lastUsedAt = \time();
            if ($handle->poll() === pq\Connection::POLLING_FAILED) {
                $exception = new ConnectionException($handle->errorMessage);
                $handle = null;
                // Marks connection as dead.
                Loop::disable($watcher);
                foreach ($listeners as $listener) {
                    $listener->fail($exception);
                }
                if ($deferred !== null) {
                    $deferred->fail($exception);
                }
                return;
            }
            if ($deferred === null) {
                return;
                // No active query, only notification listeners.
            }
            if ($handle->busy) {
                return;
                // Not finished receiving data, poll again.
            }
            $deferred->resolve($handle->getResult());
            if (!$deferred && empty($listeners)) {
                Loop::unreference($watcher);
            }
        });
        $this->await = Loop::onWritable($this->handle->socket, static function ($watcher) use(&$deferred, &$listeners, &$handle) : void {
            try {
                if (!$handle->flush()) {
                    return;
                    // Not finished sending data, continue polling for writability.
                }
            } catch (pq\Exception $exception) {
                $exception = new ConnectionException("Flushing the connection failed", 0, $exception);
                $handle = null;
                // Marks connection as dead.
                foreach ($listeners as $listener) {
                    $listener->fail($exception);
                }
                if ($deferred !== null) {
                    $deferred->fail($exception);
                }
            }
            Loop::disable($watcher);
        });
        Loop::unreference($this->poll);
        Loop::disable($this->await);
    }
    /**
     * Frees Io watchers from loop.
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle !== null;
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     * {@inheritdoc}
     */
    public function close() : void
    {
        if ($this->deferred) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->fail(new ConnectionException("The connection was closed"));
        }
        $this->handle = null;
        $this->free();
    }
    /**
     *
     */
    private function free() : void
    {
        Loop::cancel($this->poll);
        Loop::cancel($this->await);
    }
    /**
     * @param string|null Query SQL or null if not related.
     * @param callable $method Method to execute.
     * @param mixed ...$args Arguments to pass to function.
     *
     * @return \Generator
     *
     * @resolve \Amp\Sql\CommandResult|\pq\Statement
     *
     * @throws FailureException
     */
    private function send(?string $sql, callable $method, ...$args) : \Generator
    {
        while ($this->busy) {
            try {
                (yield $this->busy->promise());
            } catch (\Throwable $exception) {
                // Ignore failure from another operation.
            }
        }
        if (!$this->handle) {
            throw new ConnectionException("The connection to the database has been closed");
        }
        try {
            $this->deferred = $this->busy = new Deferred();
            $handle = $method(...$args);
            Loop::reference($this->poll);
            if (!$this->handle->flush()) {
                Loop::enable($this->await);
            }
            $result = (yield $this->deferred->promise());
        } catch (pq\Exception $exception) {
            throw new FailureException($this->handle->errorMessage, 0, $exception);
        } finally {
            $this->deferred = $this->busy = null;
        }
        if (!$result instanceof pq\Result) {
            throw new FailureException("Unknown query result");
        }
        switch ($result->status) {
            case pq\Result::EMPTY_QUERY:
                throw new QueryError("Empty query string");
            case pq\Result::COMMAND_OK:
                if ($handle instanceof pq\Statement) {
                    return $handle;
                    // Will be wrapped into a PqStatement object.
                }
                return new PqCommandResult($result);
            case pq\Result::TUPLES_OK:
                return new PqBufferedResultSet($result);
            case pq\Result::SINGLE_TUPLE:
                $this->busy = new Deferred();
                return new PqUnbufferedResultSet(coroutine(\Closure::fromCallable([$this, 'fetch'])), $result, \Closure::fromCallable([$this, 'release']));
            case pq\Result::NONFATAL_ERROR:
            case pq\Result::FATAL_ERROR:
                while ($this->handle->busy && $this->handle->getResult()) {
                }
                throw new QueryExecutionError($result->errorMessage, $result->diag, null, $sql ?? '');
            case pq\Result::BAD_RESPONSE:
                $this->close();
                throw new FailureException($result->errorMessage);
            default:
                $this->close();
                throw new FailureException("Unknown result status");
        }
    }
    /**
     *
     */
    private function fetch() : \Generator
    {
        if (!$this->handle->busy) {
            // Results buffered.
            $result = $this->handle->getResult();
        } else {
            $this->deferred = new Deferred();
            Loop::reference($this->poll);
            if (!$this->handle->flush()) {
                Loop::enable($this->await);
            }
            try {
                $result = (yield $this->deferred->promise());
            } finally {
                $this->deferred = null;
            }
        }
        if (!$result) {
            throw new ConnectionException("Connection closed");
        }
        switch ($result->status) {
            case pq\Result::TUPLES_OK:
                // End of result set.
                return null;
            case pq\Result::SINGLE_TUPLE:
                return $result;
            default:
                $this->close();
                throw new FailureException($result->errorMessage);
        }
    }
    /**
     *
     */
    private function release() : void
    {
        \assert($this->busy instanceof Deferred && $this->busy !== $this->deferred, "Connection in invalid state when releasing");
        while ($this->handle->busy && $this->handle->getResult()) {
        }
        $deferred = $this->busy;
        $this->busy = null;
        $deferred->resolve();
    }
    /**
     * Executes the named statement using the given parameters.
     *
     * @param string $name
     * @param array $params
     *
     * @return Promise
     * @throws FailureException
     */
    public function statementExecute(string $name, array $params) : Promise
    {
        \assert(isset($this->statements[$name]), "Named statement not found when executing");
        $storage = $this->statements[$name];
        \assert($storage->statement instanceof pq\Statement, "Statement storage in invalid state");
        return new Coroutine($this->send($storage->sql, [$storage->statement, "execAsync"], $params));
    }
    /**
     * @param string $name
     *
     * @return Promise
     *
     * @throws FailureException
     */
    public function statementDeallocate(string $name) : Promise
    {
        if (!$this->handle) {
            return new Success();
            // Connection dead.
        }
        \assert(isset($this->statements[$name]), "Named statement not found when deallocating");
        $storage = $this->statements[$name];
        if (--$storage->refCount) {
            return new Success();
        }
        \assert($storage->statement instanceof pq\Statement, "Statement storage in invalid state");
        return $storage->promise = call(function () use($storage, $name) {
            yield from $this->send(null, [$storage->statement, "deallocateAsync"]);
            unset($this->statements[$name]);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function query(string $sql) : Promise
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return new Coroutine($this->send($sql, [$this->handle, "execAsync"], $sql));
    }
    /**
     * {@inheritdoc}
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        $sql = Internal\parseNamedParams($sql, $names);
        $params = Internal\replaceNamedParams($params, $names);
        return new Coroutine($this->send($sql, [$this->handle, "execParamsAsync"], $sql, $params));
    }
    /**
     * {@inheritdoc}
     */
    public function prepare(string $sql) : Promise
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return call(function () use($sql) {
            $modifiedSql = Internal\parseNamedParams($sql, $names);
            $name = Handle::STATEMENT_NAME_PREFIX . \sha1($modifiedSql);
            while (isset($this->statements[$name])) {
                $storage = $this->statements[$name];
                ++$storage->refCount;
                // Statement may be being allocated or deallocated. Wait to finish, then check for existence again.
                if ($storage->promise instanceof Promise) {
                    // Do not return promised prepared statement object, as the $names array may differ.
                    (yield $storage->promise);
                    --$storage->refCount;
                    continue;
                }
                return new PqStatement($this, $name, $sql, $names);
            }
            $storage = new class
            {
                use Struct;
                public $refCount = 1;
                /** @var Promise<string> */
                public $promise;
                /** @var pq\Statement */
                public $statement;
                /** @var string */
                public $sql;
            };
            $storage->sql = $sql;
            $this->statements[$name] = $storage;
            try {
                $storage->statement = (yield $storage->promise = new Coroutine($this->send($sql, [$this->handle, "prepareAsync"], $name, $modifiedSql)));
            } catch (\Throwable $exception) {
                unset($this->statements[$name]);
                throw $exception;
            } finally {
                $storage->promise = null;
            }
            return new PqStatement($this, $name, $sql, $names);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        return new Coroutine($this->send(null, [$this->handle, "notifyAsync"], $channel, $payload));
    }
    /**
     * {@inheritdoc}
     */
    public function listen(string $channel) : Promise
    {
        return call(function () use($channel) {
            if (isset($this->listeners[$channel])) {
                throw new QueryError(\sprintf("Already listening on channel '%s'", $channel));
            }
            $this->listeners[$channel] = $emitter = new Emitter();
            try {
                yield from $this->send(null, [$this->handle, "listenAsync"], $channel, static function (string $channel, string $message, int $pid) use($emitter) {
                    $notification = new Notification();
                    $notification->channel = $channel;
                    $notification->pid = $pid;
                    $notification->payload = $message;
                    $emitter->emit($notification);
                });
            } catch (\Throwable $exception) {
                unset($this->listeners[$channel]);
                throw $exception;
            }
            Loop::reference($this->poll);
            return new ConnectionListener($emitter->iterate(), $channel, \Closure::fromCallable([$this, 'unlisten']));
        });
    }
    /**
     * @param string $channel
     *
     * @return Promise
     *
     * @throws \Error
     */
    private function unlisten(string $channel) : Promise
    {
        \assert(isset($this->listeners[$channel]), "Not listening on that channel");
        $emitter = $this->listeners[$channel];
        unset($this->listeners[$channel]);
        if (!$this->handle) {
            $promise = new Success();
            // Connection already closed.
        } else {
            $promise = new Coroutine($this->send(null, [$this->handle, "unlistenAsync"], $channel));
        }
        $promise->onResolve([$emitter, "complete"]);
        return $promise;
    }
    /**
     * {@inheritdoc}
     */
    public function quoteString(string $data) : string
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return $this->handle->quote($data);
    }
    /**
     * {@inheritdoc}
     */
    public function quoteName(string $name) : string
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return $this->handle->quoteName($name);
    }
    /**
     * @return bool True if result sets are buffered in memory, false if unbuffered.
     */
    public function isBufferingResults() : bool
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        return !$this->handle->unbuffered;
    }
    /**
     * Sets result sets to be fully buffered in local memory.
     */
    public function shouldBufferResults()
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        $this->handle->unbuffered = false;
    }
    /**
     * Sets result sets to be streamed from the database server.
     */
    public function shouldNotBufferResults()
    {
        if (!$this->handle) {
            throw new \Error("The connection to the database has been closed");
        }
        $this->handle->unbuffered = true;
    }
}<?php

namespace Amp\Postgres;

interface Quoter
{
    /**
    * Quotes (escapes) the given string for use as a string literal or identifier in a query. This method wraps the
    string in single quotes, so additional quotes should not be added in the query.
    *
    * @param string $data Unquoted data.
    *
    * @return string Quoted string wrapped in single quotes.
    *
    * @throws \Error If the connection to the database has been closed.
    */
    public function quoteString(string $data) : string;
    /**
     * Quotes (escapes) the given string for use as a name or identifier in a query.
     *
     * @param string $name Unquoted identifier.
     *
     * @return string Quoted identifier.
     *
     * @throws \Error If the connection to the database has been closed.
     */
    public function quoteName(string $name) : string;
}<?php

namespace Amp\Postgres;

use Amp\Sql\CommandResult;
use pq;
final class PqCommandResult implements CommandResult
{
    /** @var \pq\Result PostgreSQL result object. */
    private $result;
    /**
     * @param \pq\Result $result PostgreSQL result object.
     */
    public function __construct(pq\Result $result)
    {
        $this->result = $result;
    }
    /**
     * @return int Number of rows affected by the INSERT, UPDATE, or DELETE query.
     */
    public function getAffectedRowCount() : int
    {
        return $this->result->affectedRows;
    }
}<?php

namespace Amp\Postgres\Internal;

use function Amp\Postgres\cast;
const STATEMENT_PARAM_REGEX = <<<'REGEX'
[
    # Skip all quoted groups.
    (['"])(?:\\(?:\\|\1)|(?!\1).)*+\1(*SKIP)(*FAIL)
    |
    # Unnamed parameters.
    (?<unnamed>
        \$(?<numbered>\d+)
        |
        # Match all question marks except those surrounded by "operator"-class characters on either side.
        (?<!(?<operators>[-+\\*/<>~!@#%^&|`?]))
        \?
        (?!\g<operators>|=)
        |
        :\?
    )
    |
    # Named parameters.
    (?<!:):(?<named>[a-zA-Z_][a-zA-Z0-9_]*)
]msxS
REGEX;
/**
 * @param string $sql SQL statement with named and unnamed placeholders.
 * @param (array | null) $names [Output] Array of parameter positions mapped to names and/or indexed locations.
 *
 * @return string SQL statement with Postgres-style placeholders
 */
function parseNamedParams(string $sql, ?array &$names) : string
{
    $names = [];
    return \preg_replace_callback(STATEMENT_PARAM_REGEX, function (array $matches) use(&$names) : string {
        static $index = 0, $unnamed = 0, $numbered = 1;
        if (isset($matches['named'])) {
            $names[$index] = $matches['named'];
        } elseif (!isset($matches['numbered'])) {
            $names[$index] = $unnamed++;
        } else {
            if ($unnamed > 0) {
                throw new \Error("Cannot mix unnamed (? placeholders) with numbered parameters");
            }
            $position = (int) $matches['numbered'];
            if ($position <= 0 || $position > $numbered + 1) {
                throw new \Error("Numbered placeholders must be sequential starting at 1");
            }
            $numbered = \max($position, $numbered);
            $names[$index] = $position - 1;
        }
        return '$' . ++$index;
    }, $sql);
}
/**
 * @param mixed[] $params User-provided array of statement parameters.
 * @param mixed[] $names Array generated by parseNamedParams.
 *
 * @return mixed[]
 *
 * @throws \Error If the $param array does not contain a key corresponding to a named parameter.
 */
function replaceNamedParams(array $params, array $names) : array
{
    $values = [];
    foreach ($names as $index => $name) {
        if (!\array_key_exists($name, $params)) {
            if (\is_int($name)) {
                $message = \sprintf("Value for unnamed parameter at position %s missing", $name);
            } else {
                $message = \sprintf("Value for named parameter '%s' missing", $name);
            }
            throw new \Error($message);
        }
        $values[$index] = cast($params[$name]);
    }
    return $values;
}<?php

namespace Amp\Postgres\Internal;

use Amp\Postgres\ParseException;
/**
 * @internal
 */
final class ArrayParser
{
    /**
     * @param string $data String representation of PostgreSQL array.
     * @param callable $cast Callback to cast parsed values.
     * @param string $delimiter Delimiter used to separate values.
     *
     * @return array Parsed column data.
     *
     * @throws ParseException
     */
    public function parse(string $data, callable $cast, string $delimiter = ',') : array
    {
        $data = \trim($data);
        $parser = $this->parser($data, $cast, $delimiter);
        $data = \iterator_to_array($parser);
        if ($parser->getReturn() !== '') {
            throw new ParseException("Data left in buffer after parsing");
        }
        return $data;
    }
    /**
     * Recursive generator parser yielding array values.
     *
     * @param string $data Remaining buffer data.
     * @param callable $cast Callback to cast parsed values.
     * @param string $delimiter Delimiter used to separate values.
     *
     * @return \Generator
     *
     * @throws ParseException
     */
    private function parser(string $data, callable $cast, string $delimiter = ',') : \Generator
    {
        if ($data === '') {
            throw new ParseException("Unexpected end of data");
        }
        if ($data[0] !== '{') {
            throw new ParseException("Missing opening bracket");
        }
        $data = \ltrim(\Phabel\Target\Php80\Polyfill::substr($data, 1));
        do {
            if ($data === '') {
                throw new ParseException("Unexpected end of data");
            }
            if ($data[0] === '}') {
                // Empty array
                return \ltrim(\Phabel\Target\Php80\Polyfill::substr($data, 1));
            }
            if ($data[0] === '{') {
                // Array
                $parser = $this->parser($data, $cast, $delimiter);
                (yield \iterator_to_array($parser));
                $data = $parser->getReturn();
                $end = $this->trim($data, 0, $delimiter);
                continue;
            }
            if ($data[0] === '"') {
                // Quoted value
                for ($position = 1; isset($data[$position]); ++$position) {
                    if ($data[$position] === '\\') {
                        ++$position;
                        // Skip next character
                        continue;
                    }
                    if ($data[$position] === '"') {
                        break;
                    }
                }
                if (!isset($data[$position])) {
                    throw new ParseException("Could not find matching quote in quoted value");
                }
                $yield = \stripslashes(\Phabel\Target\Php80\Polyfill::substr($data, 1, $position - 1));
                $end = $this->trim($data, $position + 1, $delimiter);
            } else {
                // Unquoted value
                $position = 0;
                while (isset($data[$position]) && $data[$position] !== $delimiter && $data[$position] !== '}') {
                    ++$position;
                }
                $yield = \trim(\Phabel\Target\Php80\Polyfill::substr($data, 0, $position));
                $end = $this->trim($data, $position, $delimiter);
                if (\strcasecmp($yield, "NULL") === 0) {
                    // Literal NULL is always unquoted.
                    (yield null);
                    continue;
                }
            }
            (yield $cast($yield));
        } while ($end !== '}');
        return $data;
    }
    /**
     * @param string $data Data trimmed past next delimiter and any whitespace to the right of the delimiter.
     * @param int $position Position to start search for delimiter.
     * @param string $delimiter Delimiter used to separate values.
     *
     * @return string First non-whitespace character after given position.
     *
     * @throws ParseException
     */
    private function trim(string &$data, int $position, string $delimiter) : string
    {
        $data = \ltrim(\Phabel\Target\Php80\Polyfill::substr($data, $position));
        if ($data === '') {
            throw new ParseException("Unexpected end of data");
        }
        $end = $data[0];
        if ($end !== $delimiter && $end !== '}') {
            throw new ParseException("Invalid delimiter");
        }
        $data = \ltrim(\Phabel\Target\Php80\Polyfill::substr($data, 1));
        return $end;
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Statement;
final class PgSqlStatement implements Statement
{
    /** @var PgSqlHandle */
    private $handle;
    /** @var string */
    private $name;
    /** @var string */
    private $sql;
    /** @var string[] */
    private $params;
    /** @var int */
    private $lastUsedAt;
    /**
     * @param PgSqlHandle $handle
     * @param string $name
     * @param string $sql
     * @param string[] $params
     */
    public function __construct(PgSqlHandle $handle, string $name, string $sql, array $params)
    {
        $this->handle = $handle;
        $this->name = $name;
        $this->sql = $sql;
        $this->params = $params;
        $this->lastUsedAt = \time();
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->handle->statementDeallocate($this->name);
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public function getQuery() : string
    {
        return $this->sql;
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     * {@inheritdoc}
     */
    public function execute(array $params = []) : Promise
    {
        return $this->handle->statementExecute($this->name, Internal\replaceNamedParams($params, $this->params));
    }
}<?php

namespace Amp\Postgres;

use Amp\Coroutine;
use Amp\Promise;
use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\Common\StatementPool as SqlStatementPool;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\Connector;
use Amp\Sql\Pool as SqlPool;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
use Amp\Sql\Transaction as SqlTransaction;
use function Amp\call;
final class Pool extends ConnectionPool implements Link
{
    /** @var Connection|Promise|null Connection used for notification listening. */
    private $listeningConnection;
    /** @var int Number of listeners on listening connection. */
    private $listenerCount = 0;
    /** @var bool */
    private $resetConnections;
    /**
     * @param ConnectionConfig $config
     * @param int $maxConnections
     * @param int $idleTimeout
     * @param bool $resetConnections True to automatically execute DISCARD ALL on a connection before use.
     * @param (Connector | null) $connector
     */
    public function __construct(ConnectionConfig $config, int $maxConnections = self::DEFAULT_MAX_CONNECTIONS, int $idleTimeout = self::DEFAULT_IDLE_TIMEOUT, bool $resetConnections = true, ?Connector $connector = null)
    {
        parent::__construct($config, $maxConnections, $idleTimeout, $connector);
        $this->resetConnections = $resetConnections;
    }
    /**
     * @return Connector The Connector instance defined by the connector() function.
     */
    protected function createDefaultConnector() : Connector
    {
        return connector();
    }
    /**
     *
     */
    protected function createStatement(SqlStatement $statement, callable $release) : SqlStatement
    {
        return new PooledStatement($statement, $release);
    }
    /**
     *
     */
    protected function createStatementPool(SqlPool $pool, SqlStatement $statement, callable $prepare) : SqlStatementPool
    {
        return new StatementPool($pool, $statement, $prepare);
    }
    /**
     *
     */
    protected function createTransaction(SqlTransaction $transaction, callable $release) : SqlTransaction
    {
        \assert($transaction instanceof Transaction);
        return new PooledTransaction($transaction, $release);
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    protected function pop() : \Generator
    {
        $connection = (yield from parent::pop());
        \assert($connection instanceof Connection);
        if ($this->resetConnections) {
            (yield $connection->query("DISCARD ALL"));
        }
        return $connection;
    }
    /**
     * {@inheritdoc}
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        return call(function () use($channel, $payload) {
            $connection = (yield from $this->pop());
            \assert($connection instanceof Connection);
            try {
                $result = (yield $connection->notify($channel, $payload));
            } finally {
                $this->push($connection);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function listen(string $channel) : Promise
    {
        return call(function () use($channel) {
            ++$this->listenerCount;
            if ($this->listeningConnection === null) {
                $this->listeningConnection = new Coroutine($this->pop());
            }
            if ($this->listeningConnection instanceof Promise) {
                $this->listeningConnection = (yield $this->listeningConnection);
            }
            try {
                $listener = (yield $this->listeningConnection->listen($channel));
                \assert($listener instanceof Listener);
            } catch (\Throwable $exception) {
                if (--$this->listenerCount === 0) {
                    $connection = $this->listeningConnection;
                    $this->listeningConnection = null;
                    $this->push($connection);
                }
                throw $exception;
            }
            return new PooledListener($listener, function () {
                if (--$this->listenerCount === 0) {
                    $connection = $this->listeningConnection;
                    $this->listeningConnection = null;
                    $this->push($connection);
                }
            });
        });
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Common\StatementPool as SqlStatementPool;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement;
use Amp\Success;
final class StatementPool extends SqlStatementPool
{
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     *
     */
    protected function prepare(Statement $statement) : Promise
    {
        return new Success($statement);
        // Nothing to be done.
    }
}<?php

namespace Amp\Postgres;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Promise;
use Amp\Sql\Link;
use Amp\Sql\Transaction;
use function Amp\call;
abstract class Connection implements Link, Handle
{
    /** @var Handle */
    private $handle;
    /** @var Deferred|null Used to only allow one transaction at a time. */
    private $busy;
    /**
     * @param ConnectionConfig $connectionConfig
     * @param CancellationToken $token
     *
     * @return Promise<Connection>
     */
    public static abstract function connect(ConnectionConfig $connectionConfig, ?CancellationToken $token = null) : Promise;
    /**
     * @param Handle $handle
     */
    public function __construct(Handle $handle)
    {
        $this->handle = $handle;
    }
    /**
     * {@inheritdoc}
     */
    public final function isAlive() : bool
    {
        return $this->handle->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public final function getLastUsedAt() : int
    {
        return $this->handle->getLastUsedAt();
    }
    /**
     * {@inheritdoc}
     */
    public final function close() : void
    {
        $this->handle->close();
    }
    /**
     * @param string $methodName Method to execute.
     * @param mixed ...$args Arguments to pass to function.
     *
     * @return Promise
     */
    private function send(string $methodName, ...$args) : Promise
    {
        if ($this->busy) {
            return call(function () use($methodName, $args) {
                while ($this->busy) {
                    (yield $this->busy->promise());
                }
                return (yield $this->handle->{$methodName}(...$args));
            });
        }
        return $this->handle->{$methodName}(...$args);
    }
    /**
     * Reserves the connection for a transaction.
     */
    private function reserve() : void
    {
        \assert($this->busy === null);
        $this->busy = new Deferred();
    }
    /**
     * Releases the transaction lock.
     */
    private function release() : void
    {
        \assert($this->busy !== null);
        $deferred = $this->busy;
        $this->busy = null;
        $deferred->resolve();
    }
    /**
     * {@inheritdoc}
     */
    public final function query(string $sql) : Promise
    {
        return $this->send("query", $sql);
    }
    /**
     * {@inheritdoc}
     */
    public final function execute(string $sql, array $params = []) : Promise
    {
        return $this->send("execute", $sql, $params);
    }
    /**
     * {@inheritdoc}
     */
    public final function prepare(string $sql) : Promise
    {
        return $this->send("prepare", $sql);
    }
    /**
     * {@inheritdoc}
     */
    public final function notify(string $channel, string $payload = "") : Promise
    {
        return $this->send("notify", $channel, $payload);
    }
    /**
     * {@inheritdoc}
     */
    public final function listen(string $channel) : Promise
    {
        return $this->send("listen", $channel);
    }
    /**
     * {@inheritdoc}
     */
    public final function beginTransaction(int $isolation = Transaction::ISOLATION_COMMITTED) : Promise
    {
        return call(function () use($isolation) {
            $this->reserve();
            try {
                switch ($isolation) {
                    case Transaction::ISOLATION_UNCOMMITTED:
                        (yield $this->handle->query("BEGIN TRANSACTION ISOLATION LEVEL READ UNCOMMITTED"));
                        break;
                    case Transaction::ISOLATION_COMMITTED:
                        (yield $this->handle->query("BEGIN TRANSACTION ISOLATION LEVEL READ COMMITTED"));
                        break;
                    case Transaction::ISOLATION_REPEATABLE:
                        (yield $this->handle->query("BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ"));
                        break;
                    case Transaction::ISOLATION_SERIALIZABLE:
                        (yield $this->handle->query("BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE"));
                        break;
                    default:
                        throw new \Error("Invalid transaction type");
                }
            } catch (\Throwable $exception) {
                $this->release();
                throw $exception;
            }
            return new ConnectionTransaction($this->handle, \Closure::fromCallable([$this, 'release']), $isolation);
        });
    }
    /**
     * {@inheritdoc}
     */
    public final function quoteString(string $data) : string
    {
        return $this->handle->quoteString($data);
    }
    /**
     * {@inheritdoc}
     */
    public final function quoteName(string $name) : string
    {
        return $this->handle->quoteName($name);
    }
}<?php

namespace Amp\Postgres;

use Amp\Promise;
final class PooledListener implements Listener
{
    /** @var Listener */
    private $listener;
    /** @var callable|null */
    private $release;
    /**
     *
     */
    public function __construct(Listener $listener, callable $release)
    {
        $this->listener = $listener;
        $this->release = $release;
        if (!$this->listener->isListening()) {
            ($this->release)();
            $this->release = null;
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->listener->isListening()) {
            $this->unlisten();
            // Invokes $this->release callback.
        }
    }
    /**
     *
     */
    public function advance() : Promise
    {
        return $this->listener->advance();
    }
    /**
     *
     */
    public function getCurrent() : Notification
    {
        return $this->listener->getCurrent();
    }
    /**
     *
     */
    public function getChannel() : string
    {
        return $this->listener->getChannel();
    }
    /**
     *
     */
    public function isListening() : bool
    {
        return $this->listener->isListening();
    }
    /**
     *
     */
    public function unlisten() : Promise
    {
        if (!$this->release) {
            throw new \Error("Already unlistened on this channel");
        }
        $promise = $this->listener->unlisten();
        $promise->onResolve($this->release);
        $this->release = null;
        return $promise;
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\ResultSet as SqlResultSet;
interface ResultSet extends SqlResultSet
{
    /**
     * Returns the number of fields (columns) in each row.
     *
     * @return int
     */
    public function getFieldCount() : int;
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Executor as SqlExecutor;
interface Executor extends SqlExecutor
{
    /**
     * @param string $channel Channel name.
     * @param string $payload Notification payload.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws \Amp\Sql\FailureException If the operation fails due to unexpected condition.
     * @throws \Amp\Sql\ConnectionException If the connection to the database is lost.
     */
    public function notify(string $channel, string $payload = "") : Promise;
}<?php

namespace Amp\Postgres;

use Amp\Sql\Link as SqlLink;
interface Link extends Receiver, SqlLink
{
}<?php

namespace Amp\Postgres;

use Amp\Sql\Transaction as SqlTransaction;
/**
 * Note that notifications sent during a transaction are not delivered until the transaction has been committed.
 */
interface Transaction extends Executor, Quoter, SqlTransaction
{
}<?php

namespace Amp\Postgres;

use Amp\Loop;
use Amp\Promise;
use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\ConnectionConfig as SqlConnectionConfig;
use Amp\Sql\Connector;
const LOOP_CONNECTOR_IDENTIFIER = Connector::class . "\\Postgres";
/**
 *
 */
function connector(?Connector $connector = null) : Connector
{
    if ($connector === null) {
        $connector = Loop::getState(LOOP_CONNECTOR_IDENTIFIER);
        if ($connector) {
            return $connector;
        }
        $connector = new TimeoutConnector();
    }
    Loop::setState(LOOP_CONNECTOR_IDENTIFIER, $connector);
    return $connector;
}
/**
 * Create a connection using the global Connector instance.
 *
 * @param SqlConnectionConfig $config
 *
 * @return Promise<Connection>
 *
 * @throws \Amp\Sql\FailureException If connecting fails.
 *
 * @throws \Error If neither ext-pgsql or pecl-pq is loaded.
 *
 * @codeCoverageIgnore
 */
function connect(SqlConnectionConfig $config) : Promise
{
    return connector()->connect($config);
}
/**
 * Create a pool using the global Connector instance.
 *
 * @param SqlConnectionConfig $config
 * @param int $maxConnections
 * @param int $idleTimeout
 * @param bool $resetConnections
 *
 * @return Pool
 */
function pool(SqlConnectionConfig $config, int $maxConnections = ConnectionPool::DEFAULT_MAX_CONNECTIONS, int $idleTimeout = ConnectionPool::DEFAULT_IDLE_TIMEOUT, bool $resetConnections = true) : Pool
{
    return new Pool($config, $maxConnections, $idleTimeout, $resetConnections, connector());
}
/**
 * Casts a PHP value to a representation that is understood by Postgres, including encoding arrays.
 *
 * @param mixed $value
 *
 * @return (string | int | float | null)
 *
 * @throws \Error If $value is an object without a __toString() method, a resource, or an unknown type.
 */
function cast($value)
{
    switch ($type = \gettype($value)) {
        case "NULL":
        case "integer":
        case "double":
        case "string":
            return $value;
        // No casting necessary for numerics, strings, and null.
        case "boolean":
            return $value ? 't' : 'f';
        case "array":
            return encode($value);
        case "object":
            if (!\method_exists($value, "__toString")) {
                throw new \Error("Object without a __toString() method included in parameter values");
            }
            return (string) $value;
        default:
            throw new \Error("Invalid value type '{$type}' in parameter values");
    }
}
/**
 * Encodes an array into a PostgreSQL representation of the array.
 *
 * @param array $array
 *
 * @return string The serialized representation of the array.
 *
 * @throws \Error If $array contains an object without a __toString() method, a resource, or an unknown type.
 */
function encode(array $array) : string
{
    $array = \array_map(function ($value) {
        switch (\gettype($value)) {
            case "NULL":
                return "NULL";
            case "object":
                if (!\method_exists($value, "__toString")) {
                    throw new \Error("Object without a __toString() method in array");
                }
                $value = (string) $value;
            // no break
            case "string":
                return '"' . \str_replace(['\\', '"'], ['\\\\', '\\"'], $value) . '"';
            default:
                return cast($value);
        }
    }, $array);
    return '{' . \implode(',', $array) . '}';
}<?php

namespace Amp\Postgres;

use Amp\Promise;
use Amp\Sql\Common\PooledTransaction as SqlPooledTransaction;
use Amp\Sql\ResultSet as SqlResultSet;
use Amp\Sql\Statement as SqlStatement;
final class PooledTransaction extends SqlPooledTransaction implements Transaction
{
    /** @var Transaction|null */
    private $transaction;
    /**
     *
     */
    protected function createStatement(SqlStatement $statement, callable $release) : SqlStatement
    {
        return new PooledStatement($statement, $release);
    }
    /**
     *
     */
    protected function createResultSet(SqlResultSet $resultSet, callable $release) : SqlResultSet
    {
        \assert($resultSet instanceof ResultSet);
        return new PooledResultSet($resultSet, $release);
    }
    /**
     * @param Transaction $transaction
     * @param callable $release
     */
    public function __construct(Transaction $transaction, callable $release)
    {
        parent::__construct($transaction, $release);
        $this->transaction = $transaction;
    }
    /**
     *
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        return $this->transaction->notify($channel, $payload);
    }
    /**
     *
     */
    public function quoteString(string $data) : string
    {
        return $this->transaction->quoteString($data);
    }
    /**
     *
     */
    public function quoteName(string $name) : string
    {
        return $this->transaction->quoteName($name);
    }
}<?php

namespace Amp\Postgres;

use Amp\Sql\QueryError;
class QueryExecutionError extends QueryError
{
    /** @var mixed[] */
    private $diagnostics;
    /**
     *
     */
    public function __construct(string $message, array $diagnostics, \Throwable $previous = null, string $query = '')
    {
        parent::__construct($message, $query, $previous);
        $this->diagnostics = $diagnostics;
    }
    /**
     *
     */
    public function getDiagnostics() : array
    {
        return $this->diagnostics;
    }
}<?php

namespace Amp\Postgres;

interface Handle extends Receiver, Quoter
{
    const STATEMENT_NAME_PREFIX = "amp_";
}<?php

namespace Amp\Postgres;

use Amp\Iterator;
use Amp\Promise;
interface Listener extends Iterator
{
    /**
     * @return string Channel name.
     */
    public function getChannel() : string;
    /**
     * @return bool
     */
    public function isListening() : bool;
    /**
     * Unlistens from the channel. No more values will be emitted from this listener.
     *
     * @return Promise<\Amp\Sql\CommandResult>
     *
     * @throws \Error If this method was previously invoked.
     */
    public function unlisten() : Promise;
}<?php

namespace Amp\Postgres;

use Amp\Sql\Common\PooledResultSet as SqlPooledResultSet;
final class PooledResultSet extends SqlPooledResultSet implements ResultSet
{
    /** @var ResultSet */
    private $result;
    /**
     * @param ResultSet $result
     * @param callable $release
     */
    public function __construct(ResultSet $result, callable $release)
    {
        parent::__construct($result, $release);
        $this->result = $result;
    }
    /**
     *
     */
    public function getFieldCount() : int
    {
        return $this->result->getFieldCount();
    }
}<?php

namespace Amp\Postgres;

use Amp\Producer;
use Amp\Promise;
use pq;
use function Amp\asyncCall;
final class PqUnbufferedResultSet implements ResultSet
{
    /** @var int */
    private $numCols;
    /** @var \Amp\Producer */
    private $producer;
    /** @var array|object Last row emitted. */
    private $currentRow;
    /** @var bool */
    private $destroyed = false;
    /**
     * @param callable():  $fetch Function to fetch next result row.
     * @param \pq\Result $result PostgreSQL result object.
     */
    public function __construct(callable $fetch, pq\Result $result, callable $release)
    {
        $this->numCols = $result->numCols;
        $destroyed =& $this->destroyed;
        $this->producer = new Producer(static function (callable $emit) use(&$destroyed, $release, $result, $fetch) {
            try {
                do {
                    $result->autoConvert = pq\Result::CONV_SCALAR | pq\Result::CONV_ARRAY;
                    $next = $fetch();
                    (yield $emit($result));
                    $result = (yield $next);
                } while ($result instanceof pq\Result);
            } finally {
                $destroyed = true;
                $release();
            }
        });
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->destroyed) {
            return;
        }
        $producer = $this->producer;
        asyncCall(static function () use($producer) {
            try {
                while ((yield $producer->advance())) {
                }
            } catch (\Throwable $exception) {
                // Ignore iterator failure when destroying.
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function advance() : Promise
    {
        $this->currentRow = null;
        return $this->producer->advance();
    }
    /**
     * {@inheritdoc}
     */
    public function getCurrent() : array
    {
        if ($this->currentRow !== null) {
            return $this->currentRow;
        }
        $result = $this->producer->getCurrent();
        \assert($result instanceof pq\Result);
        return $this->currentRow = $result->fetchRow(pq\Result::FETCH_ASSOC);
    }
    /**
     * @return int Number of fields (columns) in each result set.
     */
    public function getFieldCount() : int
    {
        return $this->numCols;
    }
}<?php

namespace Amp\Postgres;

use Amp\Deferred;
use Amp\Emitter;
use Amp\Loop;
use Amp\Promise;
use Amp\Sql\ConnectionException;
use Amp\Sql\FailureException;
use Amp\Sql\QueryError;
use Amp\Struct;
use Amp\Success;
use function Amp\call;
final class PgSqlHandle implements Handle
{
    const DIAGNOSTIC_CODES = [\PGSQL_DIAG_SEVERITY => "severity", \PGSQL_DIAG_SQLSTATE => "sqlstate", \PGSQL_DIAG_MESSAGE_PRIMARY => "message_primary", \PGSQL_DIAG_MESSAGE_DETAIL => "message_detail", \PGSQL_DIAG_MESSAGE_HINT => "message_hint", \PGSQL_DIAG_STATEMENT_POSITION => "statement_position", \PGSQL_DIAG_INTERNAL_POSITION => "internal_position", \PGSQL_DIAG_INTERNAL_QUERY => "internal_query", \PGSQL_DIAG_CONTEXT => "context", \PGSQL_DIAG_SOURCE_FILE => "source_file", \PGSQL_DIAG_SOURCE_LINE => "source_line", \PGSQL_DIAG_SOURCE_FUNCTION => "source_function"];
    /** @var array<string, Promise<array<int, array{string, string}>>> */
    private static $typeCache;
    /** @var resource|\PgSql\Connection|null PostgreSQL connection handle. */
    private $handle;
    /** @var Promise<array<int, array{string, string}>> */
    private $types;
    /** @var Deferred|null */
    private $deferred;
    /** @var string */
    private $poll;
    /** @var string */
    private $await;
    /** @var Emitter[] */
    private $listeners = [];
    /** @var array<string, object{refCount: int, promise: Promise<string>, sql: string}> */
    private $statements = [];
    /** @var int */
    private $lastUsedAt;
    /**
     * @param resource $handle PostgreSQL connection handle.
     * @param resource $socket PostgreSQL connection stream socket.
     * @param string $id Connection identifier for determining which cached type table to use.
     */
    public function __construct($handle, $socket, string $id = '')
    {
        $this->handle = $handle;
        $this->lastUsedAt = \time();
        $handle =& $this->handle;
        $lastUsedAt =& $this->lastUsedAt;
        $deferred =& $this->deferred;
        $listeners =& $this->listeners;
        $this->poll = Loop::onReadable($socket, static function ($watcher) use(&$deferred, &$lastUsedAt, &$listeners, &$handle) : void {
            $lastUsedAt = \time();
            if (\pg_connection_status($handle) === \PGSQL_CONNECTION_BAD) {
                $handle = null;
                if ($deferred) {
                    $deferred->fail(new ConnectionException("The connection closed during the operation"));
                }
            }
            if (!\pg_consume_input($handle)) {
                $handle = null;
                // Marks connection as dead.
                Loop::disable($watcher);
                $exception = new ConnectionException(\pg_last_error($handle));
                foreach ($listeners as $listener) {
                    $listener->fail($exception);
                }
                if ($deferred !== null) {
                    $deferred->fail($exception);
                }
                return;
            }
            while ($result = \pg_get_notify($handle, \PGSQL_ASSOC)) {
                $channel = $result["message"];
                if (!isset($listeners[$channel])) {
                    continue;
                }
                $notification = new Notification();
                $notification->channel = $channel;
                $notification->pid = $result["pid"];
                $notification->payload = $result["payload"];
                $listeners[$channel]->emit($notification);
            }
            if ($deferred === null) {
                return;
                // No active query, only notification listeners.
            }
            if (\pg_connection_busy($handle)) {
                return;
            }
            $deferred->resolve(\pg_get_result($handle));
            if (!$deferred && empty($listeners)) {
                Loop::unreference($watcher);
            }
        });
        $this->await = Loop::onWritable($socket, static function ($watcher) use(&$deferred, &$listeners, &$handle) : void {
            $flush = \pg_flush($handle);
            if ($flush === 0) {
                return;
                // Not finished sending data, listen again.
            }
            Loop::disable($watcher);
            if ($flush === false) {
                $exception = new ConnectionException(\pg_last_error($handle));
                $handle = null;
                // Marks connection as dead.
                foreach ($listeners as $listener) {
                    $listener->fail($exception);
                }
                if ($deferred !== null) {
                    $deferred->fail($exception);
                }
            }
        });
        Loop::unreference($this->poll);
        Loop::disable($this->await);
        $this->types = $this->fetchTypes($id);
    }
    /**
     * Frees Io watchers from loop.
     */
    public function __destruct()
    {
        $this->free();
    }
    /**
     *
     */
    private function fetchTypes(string $id) : Promise
    {
        if (isset(self::$typeCache[$id])) {
            return self::$typeCache[$id];
        }
        return self::$typeCache[$id] = call(function () : \Generator {
            $result = (yield from $this->send("pg_send_query", "SELECT t.oid, t.typcategory, t.typdelim, t.typelem\n                 FROM pg_catalog.pg_type t JOIN pg_catalog.pg_namespace n ON t.typnamespace=n.oid\n                 WHERE t.typisdefined AND n.nspname IN ('pg_catalog', 'public')"));
            $types = [];
            while ($row = \pg_fetch_array($result, null, \PGSQL_NUM)) {
                [$oid, $type, $delimiter, $element] = $row;
                $types[(int) $oid] = [$type, $delimiter, (int) $element];
            }
            return $types;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function close() : void
    {
        if ($this->handle instanceof \PgSql\Connection || \is_resource($this->handle)) {
            \pg_close($this->handle);
            $this->handle = null;
        }
        $this->free();
    }
    /**
     *
     */
    private function free() : void
    {
        if ($this->deferred) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->fail(new ConnectionException("The connection was closed"));
        }
        Loop::cancel($this->poll);
        Loop::cancel($this->await);
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->handle instanceof \PgSql\Connection || \is_resource($this->handle);
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
    /**
     * @param callable $function Function name to execute.
     * @param mixed ...$args Arguments to pass to function.
     *
     * @return \Generator
     *
     * @resolve resource
     *
     * @throws FailureException
     */
    private function send(callable $function, ...$args) : \Generator
    {
        while ($this->deferred) {
            try {
                (yield $this->deferred->promise());
            } catch (\Throwable $exception) {
                // Ignore failure from another operation.
            }
        }
        if (!$this->isAlive()) {
            throw new ConnectionException("The connection to the database has been closed");
        }
        while ($result = \pg_get_result($this->handle)) {
            \pg_free_result($result);
        }
        $result = $function($this->handle, ...$args);
        if ($result === false) {
            throw new FailureException(\pg_last_error($this->handle));
        }
        $this->deferred = new Deferred();
        Loop::reference($this->poll);
        if (0 === $result) {
            Loop::enable($this->await);
        }
        try {
            $result = (yield $this->deferred->promise());
        } finally {
            $this->deferred = null;
        }
        return $result;
    }
    /**
     * @param resource $result PostgreSQL result resource.
     * @param string $sql Query SQL.
     *
     * @return (\Amp\Sql\CommandResult | ResultSet)
     *
     * @throws FailureException
     * @throws QueryError
     */
    private function createResult($result, string $sql, array $types)
    {
        switch (\pg_result_status($result, \PGSQL_STATUS_LONG)) {
            case \PGSQL_EMPTY_QUERY:
                throw new QueryError("Empty query string");
            case \PGSQL_COMMAND_OK:
                return new PgSqlCommandResult($result);
            case \PGSQL_TUPLES_OK:
                return new PgSqlResultSet($result, $types);
            case \PGSQL_NONFATAL_ERROR:
            case \PGSQL_FATAL_ERROR:
                $diagnostics = [];
                foreach (self::DIAGNOSTIC_CODES as $fieldCode => $desciption) {
                    $diagnostics[$desciption] = \pg_result_error_field($result, $fieldCode);
                }
                $message = \pg_result_error($result);
                while (\pg_connection_busy($this->handle) && \pg_get_result($this->handle)) {
                }
                throw new QueryExecutionError($message, $diagnostics, null, $sql);
            case \PGSQL_BAD_RESPONSE:
                $this->close();
                throw new FailureException(\pg_result_error($result));
            default:
                // @codeCoverageIgnoreStart
                $this->close();
                throw new FailureException("Unknown result status");
        }
    }
    /**
     * @param string $name
     * @param array $params
     *
     * @return Promise
     */
    public function statementExecute(string $name, array $params) : Promise
    {
        return call(function () use($name, $params) {
            \assert(isset($this->statements[$name]), "Named statement not found when executing");
            return $this->createResult(yield from $this->send("pg_send_execute", $name, $params), $this->statements[$name]->sql, (yield $this->types));
        });
    }
    /**
     * @param string $name
     *
     * @return Promise
     *
     * @throws \Error
     */
    public function statementDeallocate(string $name) : Promise
    {
        if (!$this->isAlive()) {
            return new Success();
            // Connection closed, no need to deallocate.
        }
        \assert(isset($this->statements[$name]), "Named statement not found when deallocating");
        $storage = $this->statements[$name];
        if (--$storage->refCount) {
            return new Success();
        }
        return $storage->promise = call(function () use($storage, $name) {
            (yield $this->query(\sprintf("DEALLOCATE %s", $name)));
            unset($this->statements[$name]);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function query(string $sql) : Promise
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        return call(function () use($sql) {
            return $this->createResult(yield from $this->send("pg_send_query", $sql), $sql, (yield $this->types));
        });
    }
    /**
     * {@inheritdoc}
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        $sql = Internal\parseNamedParams($sql, $names);
        $params = Internal\replaceNamedParams($params, $names);
        return call(function () use($sql, $params) {
            return $this->createResult(yield from $this->send("pg_send_query_params", $sql, $params), $sql, (yield $this->types));
        });
    }
    /**
     * {@inheritdoc}
     */
    public function prepare(string $sql) : Promise
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        return call(function () use($sql) {
            $modifiedSql = Internal\parseNamedParams($sql, $names);
            $name = Handle::STATEMENT_NAME_PREFIX . \sha1($modifiedSql);
            while (isset($this->statements[$name])) {
                $storage = $this->statements[$name];
                ++$storage->refCount;
                // Statement may be being allocated or deallocated. Wait to finish, then check for existence again.
                if ($storage->promise instanceof Promise) {
                    // Do not return promised prepared statement object, as the $names array may differ.
                    (yield $storage->promise);
                    --$storage->refCount;
                    continue;
                }
                return new PgSqlStatement($this, $name, $sql, $names);
            }
            $storage = new class
            {
                use Struct;
                public $refCount = 1;
                /** @var Promise<string> */
                public $promise;
                /** @var string */
                public $sql;
            };
            $storage->sql = $sql;
            $this->statements[$name] = $storage;
            try {
                (yield $storage->promise = call(function () use($name, $modifiedSql, $sql) {
                    $result = (yield from $this->send("pg_send_prepare", $name, $modifiedSql));
                    switch (\pg_result_status($result, \PGSQL_STATUS_LONG)) {
                        case \PGSQL_COMMAND_OK:
                            return $name;
                        // Statement created successfully.
                        case \PGSQL_NONFATAL_ERROR:
                        case \PGSQL_FATAL_ERROR:
                            $diagnostics = [];
                            foreach (self::DIAGNOSTIC_CODES as $fieldCode => $description) {
                                $diagnostics[$description] = \pg_result_error_field($result, $fieldCode);
                            }
                            throw new QueryExecutionError(\pg_result_error($result), $diagnostics, null, $sql);
                        case \PGSQL_BAD_RESPONSE:
                            throw new FailureException(\pg_result_error($result));
                        default:
                            // @codeCoverageIgnoreStart
                            throw new FailureException("Unknown result status");
                    }
                }));
            } catch (\Throwable $exception) {
                unset($this->statements[$name]);
                throw $exception;
            } finally {
                $storage->promise = null;
            }
            return new PgSqlStatement($this, $name, $sql, $names);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function notify(string $channel, string $payload = "") : Promise
    {
        if ($payload === "") {
            return $this->query(\sprintf("NOTIFY %s", $this->quoteName($channel)));
        }
        return $this->query(\sprintf("NOTIFY %s, %s", $this->quoteName($channel), $this->quoteString($payload)));
    }
    /**
     * {@inheritdoc}
     */
    public function listen(string $channel) : Promise
    {
        return call(function () use($channel) {
            if (isset($this->listeners[$channel])) {
                throw new QueryError(\sprintf("Already listening on channel '%s'", $channel));
            }
            $this->listeners[$channel] = $emitter = new Emitter();
            try {
                (yield $this->query(\sprintf("LISTEN %s", $this->quoteName($channel))));
            } catch (\Throwable $exception) {
                unset($this->listeners[$channel]);
                throw $exception;
            }
            return new ConnectionListener($emitter->iterate(), $channel, \Closure::fromCallable([$this, 'unlisten']));
        });
    }
    /**
     * @param string $channel
     *
     * @return Promise
     *
     * @throws \Error
     */
    private function unlisten(string $channel) : Promise
    {
        \assert(isset($this->listeners[$channel]), "Not listening on that channel");
        $emitter = $this->listeners[$channel];
        unset($this->listeners[$channel]);
        if (!$this->isAlive()) {
            $promise = new Success();
            // Connection already closed.
        } else {
            $promise = $this->query(\sprintf("UNLISTEN %s", $this->quoteName($channel)));
        }
        $promise->onResolve([$emitter, "complete"]);
        return $promise;
    }
    /**
     * {@inheritdoc}
     */
    public function quoteString(string $data) : string
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        return \pg_escape_literal($this->handle, $data);
    }
    /**
     * {@inheritdoc}
     */
    public function quoteName(string $name) : string
    {
        if (!$this->isAlive()) {
            throw new \Error("The connection to the database has been closed");
        }
        return \pg_escape_identifier($this->handle, $name);
    }
}<?php

namespace Amp\Postgres;

use Amp\Struct;
final class Notification
{
    use Struct;
    /** @var string Channel name. */
    public $channel;
    /** @var int PID of message source. */
    public $pid;
    /** @var string Message payload */
    public $payload;
}#!/usr/bin/env php
<?php 
require \dirname(__DIR__) . '/vendor/autoload.php';
use Amp\Postgres;
Amp\Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');
    $pool = Postgres\pool($config);
    (yield $pool->query('DROP TABLE IF EXISTS test'));
    /** @var \Amp\Postgres\Transaction $transaction */
    $transaction = (yield $pool->beginTransaction());
    (yield $transaction->query('CREATE TABLE test (domain VARCHAR(63), tld VARCHAR(63), PRIMARY KEY (domain, tld))'));
    /** @var \Amp\Sql\Statement $statement */
    $statement = (yield $transaction->prepare('INSERT INTO test VALUES (?, ?)'));
    (yield $statement->execute(['amphp', 'org']));
    (yield $statement->execute(['google', 'com']));
    (yield $statement->execute(['github', 'com']));
    /** @var \Amp\Postgres\ResultSet $result */
    $result = (yield $transaction->execute('SELECT * FROM test WHERE tld = :tld', ['tld' => 'com']));
    $format = "%-20s | %-10s\n";
    \printf($format, 'TLD', 'Domain');
    while ((yield $result->advance())) {
        $row = $result->getCurrent();
        \printf($format, $row['domain'], $row['tld']);
    }
    (yield $transaction->rollback());
});#!/usr/bin/env php
<?php 
require \dirname(__DIR__) . '/vendor/autoload.php';
use Amp\Iterator;
use Amp\Loop;
use Amp\Postgres;
Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');
    $pool = Postgres\pool($config);
    $channel1 = "test1";
    $channel2 = "test2";
    /** @var \Amp\Postgres\Listener $listener1 */
    $listener1 = (yield $pool->listen($channel1));
    \printf("Listening on channel '%s'\n", $listener1->getChannel());
    /** @var \Amp\Postgres\Listener $listener2 */
    $listener2 = (yield $pool->listen($channel2));
    \printf("Listening on channel '%s'\n", $listener2->getChannel());
    Loop::delay(6000, function () use($listener1) {
        // Unlisten in 6 seconds.
        \printf("Unlistening from channel '%s'\n", $listener1->getChannel());
        return $listener1->unlisten();
    });
    Loop::delay(4000, function () use($listener2) {
        // Unlisten in 4 seconds.
        \printf("Unlistening from channel '%s'\n", $listener2->getChannel());
        return $listener2->unlisten();
    });
    Loop::delay(1000, function () use($pool, $channel1) {
        return $pool->notify($channel1, "Data 1.1");
    });
    Loop::delay(2000, function () use($pool, $channel2) {
        return $pool->notify($channel2, "Data 2.1");
    });
    Loop::delay(3000, function () use($pool, $channel2) {
        return $pool->notify($channel2, "Data 2.2");
    });
    Loop::delay(5000, function () use($pool, $channel1) {
        return $pool->notify($channel1, "Data 1.2");
    });
    $iterator = Iterator\merge([$listener1, $listener2]);
    // Merge both listeners into single iterator.
    while ((yield $iterator->advance())) {
        $notification = $iterator->getCurrent();
        \printf("Received notification from PID %d on channel '%s' with payload: %s\n", $notification->pid, $notification->channel, $notification->payload);
    }
});#!/usr/bin/env php
<?php 
require \dirname(__DIR__) . '/vendor/autoload.php';
use Amp\Loop;
use Amp\Postgres;
Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');
    $pool = Postgres\pool($config);
    $channel = "test";
    /** @var \Amp\Postgres\Listener $listener */
    $listener = (yield $pool->listen($channel));
    \printf("Listening on channel '%s'\n", $listener->getChannel());
    Loop::delay(3000, function () use($listener) {
        // Unlisten in 3 seconds.
        \printf("Unlistening from channel '%s'\n", $listener->getChannel());
        return $listener->unlisten();
    });
    Loop::delay(1000, function () use($pool, $channel) {
        return $pool->notify($channel, "Data 1");
        // Send first notification.
    });
    Loop::delay(2000, function () use($pool, $channel) {
        return $pool->notify($channel, "Data 2");
        // Send second notification.
    });
    while ((yield $listener->advance())) {
        $notification = $listener->getCurrent();
        \printf("Received notification from PID %d on channel '%s' with payload: %s\n", $notification->pid, $notification->channel, $notification->payload);
    }
});#!/usr/bin/env php
<?php 
require \dirname(__DIR__) . '/vendor/autoload.php';
use Amp\Postgres;
Amp\Loop::run(function () {
    $config = Postgres\ConnectionConfig::fromString('host=localhost user=postgres');
    /** @var \Amp\Postgres\Connection $connection */
    $connection = (yield Postgres\connect($config));
    /** @var \Amp\Postgres\ResultSet $result */
    $result = (yield $connection->query('SHOW ALL'));
    while ((yield $result->advance())) {
        $row = $result->getCurrent();
        \printf("%-35s = %s (%s)\n", $row['name'], $row['setting'], $row['description']);
    }
});{
    "name": "amphp/postgres",
    "description": "Asynchronous PostgreSQL client for Amp.",
    "keywords": [
        "database",
        "db",
        "postgresql",
        "postgre",
        "pgsql",
        "asynchronous",
        "async"
    ],
    "homepage": "http://amphp.org",
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/sql": "^1",
        "amphp/sql-common": "^1"
    },
    "require-dev": {
        "ext-pgsql": "*",
        "ext-pq": "*",
        "amphp/phpunit-util": "^1.1.2",
        "phpunit/phpunit": "^8 | ^7",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Postgres\\": "src"
        },
        "files": [
            "src/functions.php",
            "src/Internal/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Postgres\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Sql\Common;

use Amp\Promise;
use Amp\Sql\ResultSet;
use Amp\Sql\Statement;
use function Amp\call;
abstract class PooledStatement implements Statement
{
    /** @var Statement */
    private $statement;
    /** @var callable|null */
    private $release;
    /** @var int */
    private $refCount = 1;
    /**
    * Creates a ResultSet of the appropriate type using the ResultSet object returned by the Statement object and
    the given release callable.
    *
    * @param ResultSet $resultSet
    * @param callable $release
    *
    * @return ResultSet
    */
    protected abstract function createResultSet(ResultSet $resultSet, callable $release) : ResultSet;
    /**
     * PooledStatement constructor.
     *
     * @param Statement $statement Statement object created by pooled connection.
     * @param callable $release Callable to be invoked when the statement and any associated results are destroyed.
     */
    public function __construct(Statement $statement, callable $release)
    {
        $this->statement = $statement;
        if (!$this->statement->isAlive()) {
            $release();
        } else {
            $refCount =& $this->refCount;
            $this->release = static function () use(&$refCount, $release) {
                if (--$refCount === 0) {
                    $release();
                }
            };
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->release) {
            ($this->release)();
        }
    }
    /**
     *
     */
    public function execute(array $params = []) : Promise
    {
        return call(function () use($params) {
            $result = (yield $this->statement->execute($params));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return $this->createResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return $this->statement->isAlive();
    }
    /**
     *
     */
    public function getQuery() : string
    {
        return $this->statement->getQuery();
    }
    /**
     *
     */
    public function getLastUsedAt() : int
    {
        return $this->statement->getLastUsedAt();
    }
}<?php

namespace Amp\Sql\Common;

use Amp\MultiReasonException;
use Amp\Promise;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\ConnectionException;
use Amp\Sql\Connector;
use function Amp\call;
final class RetryConnector implements Connector
{
    /** @var Connector */
    private $connector;
    /** @var int */
    private $maxTries;
    /**
     *
     */
    public function __construct(Connector $connector, int $maxTries = 3)
    {
        if ($maxTries <= 0) {
            throw new \Error('The number of tries must be 1 or greater');
        }
        $this->connector = $connector;
        $this->maxTries = $maxTries;
    }
    /**
     *
     */
    public function connect(ConnectionConfig $config) : Promise
    {
        return call(function () use($config) {
            $tries = 0;
            $exceptions = [];
            do {
                try {
                    return (yield $this->connector->connect($config));
                } catch (\Exception $exception) {
                    $exceptions[] = $exception;
                }
            } while (++$tries < $this->maxTries);
            $name = $config->getHost() . ':' . $config->getPort();
            throw new ConnectionException("Could not connect to database server at {$name} after {$tries} tries", 0, new MultiReasonException($exceptions));
        });
    }
}<?php

namespace Amp\Sql\Common;

use Amp\CallableMaker;
use Amp\Deferred;
use Amp\Loop;
use Amp\Promise;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\Connector;
use Amp\Sql\FailureException;
use Amp\Sql\Link;
use Amp\Sql\Pool;
use Amp\Sql\ResultSet;
use Amp\Sql\Statement;
use Amp\Sql\Transaction;
use function Amp\call;
use function Amp\coroutine;
abstract class ConnectionPool implements Pool
{
    use CallableMaker;
    const DEFAULT_MAX_CONNECTIONS = 100;
    const DEFAULT_IDLE_TIMEOUT = 60;
    /** @var Connector */
    private $connector;
    /** @var ConnectionConfig */
    private $connectionConfig;
    /** @var int */
    private $maxConnections;
    /** @var \SplQueue */
    private $idle;
    /** @var \SplObjectStorage */
    private $connections;
    /** @var Promise|null */
    private $promise;
    /** @var Deferred|null */
    private $deferred;
    /** @var int */
    private $idleTimeout;
    /** @var string */
    private $timeoutWatcher;
    /** @var bool */
    private $closed = false;
    /**
     * Create a default connector object based on the library of the extending class.
     *
     * @return Connector
     */
    protected abstract function createDefaultConnector() : Connector;
    /**
    * Creates a ResultSet of the appropriate type using the ResultSet object returned by the Link object and the
    given release callable.
    *
    * @param ResultSet $resultSet
    * @param callable $release
    *
    * @return ResultSet
    */
    protected abstract function createResultSet(ResultSet $resultSet, callable $release) : ResultSet;
    /**
    * Creates a Statement of the appropriate type using the Statement object returned by the Link object and the
    given release callable.
    *
    * @param Statement $statement
    * @param callable $release
    *
    * @return Statement
    */
    protected abstract function createStatement(Statement $statement, callable $release) : Statement;
    /**
     * @param Pool $pool
     * @param Statement $statement
     * @param callable $prepare
     *
     * @return StatementPool
     */
    protected abstract function createStatementPool(Pool $pool, Statement $statement, callable $prepare) : StatementPool;
    /**
    * Creates a Transaction of the appropriate type using the Transaction object returned by the Link object and the
    given release callable.
    *
    * @param Transaction $transaction
    * @param callable $release
    *
    * @return Transaction
    */
    protected abstract function createTransaction(Transaction $transaction, callable $release) : Transaction;
    /**
     * @param ConnectionConfig $config
     * @param int $maxConnections Maximum number of active connections in the pool.
     * @param int $idleTimeout Number of seconds until idle connections are removed from the pool.
     * @param (Connector | null) $connector
     */
    public function __construct(ConnectionConfig $config, int $maxConnections = self::DEFAULT_MAX_CONNECTIONS, int $idleTimeout = self::DEFAULT_IDLE_TIMEOUT, Connector $connector = null)
    {
        $this->connector = $connector ?? $this->createDefaultConnector();
        $this->connectionConfig = $config;
        $this->idleTimeout = $idleTimeout;
        if ($this->idleTimeout < 1) {
            throw new \Error("The idle timeout must be 1 or greater");
        }
        $this->maxConnections = $maxConnections;
        if ($this->maxConnections < 1) {
            throw new \Error("Pool must contain at least one connection");
        }
        $this->connections = $connections = new \SplObjectStorage();
        $this->idle = $idle = new \SplQueue();
        $idleTimeout =& $this->idleTimeout;
        $this->timeoutWatcher = Loop::repeat(1000, static function () use(&$idleTimeout, $connections, $idle) {
            $now = \time();
            while (!$idle->isEmpty()) {
                $connection = $idle->bottom();
                \assert($connection instanceof Link);
                if ($connection->getLastUsedAt() + $idleTimeout > $now) {
                    return;
                }
                // Close connection and remove it from the pool.
                $idle->shift();
                $connections->detach($connection);
                $connection->close();
            }
        });
        Loop::unreference($this->timeoutWatcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->timeoutWatcher);
    }
    /**
     *
     */
    public function getIdleTimeout() : int
    {
        return $this->idleTimeout;
    }
    /**
     *
     */
    public function getLastUsedAt() : int
    {
        // Simple implementation... can be improved if needed.
        $time = 0;
        foreach ($this->connections as $connection) {
            \assert($connection instanceof Link);
            if (($lastUsedAt = $connection->getLastUsedAt()) > $time) {
                $time = $lastUsedAt;
            }
        }
        return $time;
    }
    /**
     * @return bool
     */
    public function isAlive() : bool
    {
        return !$this->closed;
    }
    /**
     * Close all connections in the pool. No further queries may be made after a pool is closed.
     */
    public function close()
    {
        $this->closed = true;
        foreach ($this->connections as $connection) {
            $connection->close();
        }
        $this->idle = new \SplQueue();
        if ($this->deferred instanceof Deferred) {
            $deferred = $this->deferred;
            $this->deferred = null;
            $deferred->fail(new FailureException("Connection pool closed"));
        }
    }
    /**
     * {@inheritdoc}
     */
    public function extractConnection() : Promise
    {
        return call(function () {
            $connection = (yield from $this->pop());
            $this->connections->detach($connection);
            return $connection;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function getConnectionCount() : int
    {
        return $this->connections->count();
    }
    /**
     * {@inheritdoc}
     */
    public function getIdleConnectionCount() : int
    {
        return $this->idle->count();
    }
    /**
     * {@inheritdoc}
     */
    public function getConnectionLimit() : int
    {
        return $this->maxConnections;
    }
    /**
     * @return \Generator
     *
     * @resolve Link
     *
     * @throws FailureException If creating a new connection fails.
     * @throws \Error If the pool has been closed.
     */
    protected function pop() : \Generator
    {
        if ($this->closed) {
            throw new \Error("The pool has been closed");
        }
        while ($this->promise !== null) {
            (yield $this->promise);
            // Prevent simultaneous connection creation or waiting.
        }
        do {
            // While loop to ensure an idle connection is available after promises below are resolved.
            while ($this->idle->isEmpty()) {
                if ($this->connections->count() < $this->getConnectionLimit()) {
                    // Max connection count has not been reached, so open another connection.
                    try {
                        $connection = (yield $this->promise = $this->connector->connect($this->connectionConfig));
                        if (!$connection instanceof Link) {
                            throw new \Error(\sprintf("%s::connect() must resolve to an instance of %s", \get_class($this->connector), Link::class));
                        }
                    } finally {
                        $this->promise = null;
                    }
                    $this->connections->attach($connection);
                    return $connection;
                }
                // All possible connections busy, so wait until one becomes available.
                try {
                    $this->deferred = new Deferred();
                    // Connection will be pulled from $this->idle when promise is resolved.
                    (yield $this->promise = $this->deferred->promise());
                } finally {
                    $this->deferred = null;
                    $this->promise = null;
                }
            }
            $connection = $this->idle->shift();
            \assert($connection instanceof Link);
            if ($connection->isAlive()) {
                return $connection;
            }
            $this->connections->detach($connection);
        } while (!$this->closed);
        throw new FailureException("Pool closed before an active connection could be obtained");
    }
    /**
     * @param Link $connection
     *
     * @throws \Error If the connection is not part of this pool.
     */
    protected function push(Link $connection)
    {
        \assert(isset($this->connections[$connection]), 'Connection is not part of this pool');
        if ($connection->isAlive()) {
            $this->idle->unshift($connection);
        } else {
            $this->connections->detach($connection);
        }
        if ($this->deferred instanceof Deferred) {
            $this->deferred->resolve($connection);
        }
    }
    /**
     * {@inheritdoc}
     */
    public function query(string $sql) : Promise
    {
        return call(function () use($sql) {
            $connection = (yield from $this->pop());
            \assert($connection instanceof Link);
            try {
                $result = (yield $connection->query($sql));
            } catch (\Throwable $exception) {
                $this->push($connection);
                throw $exception;
            }
            if ($result instanceof ResultSet) {
                $result = $this->createResultSet($result, function () use($connection) {
                    $this->push($connection);
                });
            } else {
                $this->push($connection);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        return call(function () use($sql, $params) {
            $connection = (yield from $this->pop());
            \assert($connection instanceof Link);
            try {
                $result = (yield $connection->execute($sql, $params));
            } catch (\Throwable $exception) {
                $this->push($connection);
                throw $exception;
            }
            if ($result instanceof ResultSet) {
                $result = $this->createResultSet($result, function () use($connection) {
                    $this->push($connection);
                });
            } else {
                $this->push($connection);
            }
            return $result;
        });
    }
    /**
     * {@inheritdoc}
     *
     * Prepared statements returned by this method will stay alive as long as the pool remains open.
     */
    public function prepare(string $sql) : Promise
    {
        return call(function () use($sql) {
            $statement = (yield from $this->prepareStatement($sql));
            return $this->createStatementPool($this, $statement, coroutine($this->callableFromInstanceMethod("prepareStatement")));
        });
    }
    /**
     * Prepares a new statement on an available connection.
     *
     * @param string $sql
     *
     * @return \Generator
     *
     * @throws FailureException
     */
    private function prepareStatement(string $sql) : \Generator
    {
        $connection = (yield from $this->pop());
        \assert($connection instanceof Link);
        try {
            $statement = (yield $connection->prepare($sql));
            \assert($statement instanceof Statement);
        } catch (\Throwable $exception) {
            $this->push($connection);
            throw $exception;
        }
        return $this->createStatement($statement, function () use($connection) {
            $this->push($connection);
        });
    }
    /**
     * {@inheritdoc}
     */
    public function beginTransaction(int $isolation = Transaction::ISOLATION_COMMITTED) : Promise
    {
        return call(function () use($isolation) {
            $connection = (yield from $this->pop());
            \assert($connection instanceof Link);
            try {
                $transaction = (yield $connection->beginTransaction($isolation));
                \assert($transaction instanceof Transaction);
            } catch (\Throwable $exception) {
                $this->push($connection);
                throw $exception;
            }
            return $this->createTransaction($transaction, function () use($connection) {
                $this->push($connection);
            });
        });
    }
}<?php

namespace Amp\Sql\Common;

use Amp\Loop;
use Amp\Promise;
use Amp\Sql\Pool;
use Amp\Sql\ResultSet;
use Amp\Sql\Statement;
use function Amp\call;
abstract class StatementPool implements Statement
{
    /** @var \Amp\Sql\Pool */
    private $pool;
    /** @var \SplQueue */
    private $statements;
    /** @var string */
    private $sql;
    /** @var int */
    private $lastUsedAt;
    /** @var string */
    private $timeoutWatcher;
    /** @var callable */
    private $prepare;
    /**
    * Performs any necessary actions to the statement to prepare it for execution, returning a promise for the same or
    a new Statement object if necessary.
    *
    * @param Statement $statement
    *
    * @return Promise<Statement>
    */
    protected abstract function prepare(Statement $statement) : Promise;
    /**
     * @param ResultSet $resultSet
     * @param callable $release
     *
     * @return ResultSet
     */
    protected abstract function createResultSet(ResultSet $resultSet, callable $release) : ResultSet;
    /**
     * @param Pool $pool Pool used to re-create the statement if the original closes.
     * @param Statement $statement Original prepared statement returned from the Link.
     * @param callable $prepare Callable that returns a new prepared statement.
     */
    public function __construct(Pool $pool, Statement $statement, callable $prepare)
    {
        $this->lastUsedAt = \time();
        $this->statements = $statements = new \SplQueue();
        $this->pool = $pool;
        $this->prepare = $prepare;
        $this->sql = $statement->getQuery();
        $this->statements->push($statement);
        $this->timeoutWatcher = Loop::repeat(1000, static function () use($pool, $statements) {
            $now = \time();
            $idleTimeout = (int) ($pool->getIdleTimeout() / 10) ?: 1;
            while (!$statements->isEmpty()) {
                $statement = $statements->bottom();
                \assert($statement instanceof Statement);
                if ($statement->getLastUsedAt() + $idleTimeout > $now) {
                    return;
                }
                $statements->shift();
            }
        });
        Loop::unreference($this->timeoutWatcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        Loop::cancel($this->timeoutWatcher);
    }
    /**
     * {@inheritdoc}
     *
     * Unlike regular statements, as long as the pool is open this statement will not die.
     */
    public function execute(array $params = []) : Promise
    {
        $this->lastUsedAt = \time();
        return call(function () use($params) {
            $statement = (yield from $this->pop());
            \assert($statement instanceof Statement);
            try {
                $statement = (yield $this->prepare($statement));
                \assert($statement instanceof Statement);
                $result = (yield $statement->execute($params));
            } catch (\Throwable $exception) {
                $this->push($statement);
                throw $exception;
            }
            if ($result instanceof ResultSet) {
                $result = $this->createResultSet($result, function () use($statement) {
                    $this->push($statement);
                });
            } else {
                $this->push($statement);
            }
            return $result;
        });
    }
    /**
    * Only retains statements if less than 10% of the pool is consumed by this statement and the pool has
    available connections.
    *
    * @param Statement $statement
    */
    protected function push(Statement $statement)
    {
        $maxConnections = $this->pool->getConnectionLimit();
        if ($this->statements->count() > $maxConnections / 10) {
            return;
        }
        if ($maxConnections === $this->pool->getConnectionCount() && $this->pool->getIdleConnectionCount() === 0) {
            return;
        }
        $this->statements->unshift($statement);
    }
    /**
     * Coroutine returning a Statement object from the pool or creating a new Statement.
     *
     * @return \Generator
     */
    protected function pop() : \Generator
    {
        while (!$this->statements->isEmpty()) {
            $statement = $this->statements->shift();
            \assert($statement instanceof Statement);
            if ($statement->isAlive()) {
                return $statement;
            }
        }
        $statement = (yield ($this->prepare)($this->sql));
        \assert($statement instanceof Statement);
        return $statement;
    }
    /**
     * {@inheritdoc}
     */
    public function isAlive() : bool
    {
        return $this->pool->isAlive();
    }
    /**
     * {@inheritdoc}
     */
    public function getQuery() : string
    {
        return $this->sql;
    }
    /**
     * {@inheritdoc}
     */
    public function getLastUsedAt() : int
    {
        return $this->lastUsedAt;
    }
}<?php

namespace Amp\Sql\Common;

use Amp\Promise;
use Amp\Sql\ResultSet;
use Amp\Sql\Statement;
use Amp\Sql\Transaction;
use Amp\Sql\TransactionError;
use function Amp\call;
abstract class PooledTransaction implements Transaction
{
    /** @var Transaction|null */
    private $transaction;
    /** @var callable|null */
    private $release;
    /** @var int */
    private $refCount = 1;
    /**
    * Creates a Statement of the appropriate type using the Statement object returned by the Transaction object and
    the given release callable.
    *
    * @param Statement $statement
    * @param callable $release
    *
    * @return Statement
    */
    protected abstract function createStatement(Statement $statement, callable $release) : Statement;
    /**
    * Creates a ResultSet of the appropriate type using the ResultSet object returned by the Transaction object and
    the given release callable.
    *
    * @param ResultSet $resultSet
    * @param callable $release
    *
    * @return ResultSet
    */
    protected abstract function createResultSet(ResultSet $resultSet, callable $release) : ResultSet;
    /**
     * @param Transaction $transaction Transaction object created by pooled connection.
     * @param callable $release Callable to be invoked when the transaction completes or is destroyed.
     */
    public function __construct(Transaction $transaction, callable $release)
    {
        $this->transaction = $transaction;
        $this->release = $release;
        if (!$this->transaction->isActive()) {
            $release();
            $this->transaction = null;
        } else {
            $refCount =& $this->refCount;
            $this->release = static function () use(&$refCount, $release) {
                if (--$refCount === 0) {
                    $release();
                }
            };
        }
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->transaction && $this->transaction->isActive()) {
            $this->close();
            // Invokes $this->release callback.
        }
    }
    /**
     *
     */
    public function query(string $sql) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            $result = (yield $this->transaction->query($sql));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return $this->createResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     *
     */
    public function prepare(string $sql) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql) {
            $statement = (yield $this->transaction->prepare($sql));
            ++$this->refCount;
            return $this->createStatement($statement, $this->release);
        });
    }
    /**
     *
     */
    public function execute(string $sql, array $params = []) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return call(function () use($sql, $params) {
            $result = (yield $this->transaction->execute($sql, $params));
            if ($result instanceof ResultSet) {
                ++$this->refCount;
                return $this->createResultSet($result, $this->release);
            }
            return $result;
        });
    }
    /**
     *
     */
    public function isAlive() : bool
    {
        return $this->transaction && $this->transaction->isAlive();
    }
    /**
     *
     */
    public function getLastUsedAt() : int
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->getLastUsedAt();
    }
    /**
     *
     */
    public function close()
    {
        if (!$this->transaction) {
            return;
        }
        $promise = $this->transaction->commit();
        $promise->onResolve($this->release);
        $this->transaction = null;
    }
    /**
     *
     */
    public function getIsolationLevel() : int
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->getIsolationLevel();
    }
    /**
     *
     */
    public function isActive() : bool
    {
        return $this->transaction && $this->transaction->isActive();
    }
    /**
     *
     */
    public function commit() : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->transaction->commit();
        $promise->onResolve($this->release);
        $this->transaction = null;
        return $promise;
    }
    /**
     *
     */
    public function rollback() : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        $promise = $this->transaction->rollback();
        $promise->onResolve($this->release);
        $this->transaction = null;
        return $promise;
    }
    /**
     *
     */
    public function createSavepoint(string $identifier) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->createSavepoint($identifier);
    }
    /**
     *
     */
    public function rollbackTo(string $identifier) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->rollbackTo($identifier);
    }
    /**
     *
     */
    public function releaseSavepoint(string $identifier) : Promise
    {
        if (!$this->transaction) {
            throw new TransactionError("The transaction has been committed or rolled back");
        }
        return $this->transaction->releaseSavepoint($identifier);
    }
}<?php

namespace Amp\Sql\Common;

use Amp\Promise;
use Amp\Sql\ResultSet;
class PooledResultSet implements ResultSet
{
    /** @var ResultSet */
    private $result;
    /** @var callable */
    private $release;
    /**
     * @param ResultSet $result ResultSet object created by pooled connection or statement.
     * @param callable $release Callable to be invoked when the result set is destroyed.
     */
    public function __construct(ResultSet $result, callable $release)
    {
        $this->result = $result;
        $this->release = $release;
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->release !== null) {
            ($this->release)();
        }
    }
    /**
     *
     */
    public function advance() : Promise
    {
        $promise = $this->result->advance();
        $promise->onResolve(function (\Throwable $exception = null, bool $moreResults = null) {
            if ($this->release === null) {
                return;
            }
            if ($exception || !$moreResults) {
                $release = $this->release;
                $this->release = null;
                $release();
            }
        });
        return $promise;
    }
    /**
     *
     */
    public function getCurrent() : array
    {
        return $this->result->getCurrent();
    }
}{
    "name": "amphp/sql-common",
    "description": "Common classes for non-blocking SQL implementations.",
    "keywords": [
        "database",
        "db",
        "sql",
        "asynchronous",
        "async"
    ],
    "homepage": "http://amphp.org",
    "license": "MIT",
    "require": {
        "php": ">=7",
        "amphp/amp": "^2",
        "amphp/sql": "^1"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master",
        "amphp/phpunit-util": "^1.3",
        "phpunit/phpunit": "^6 || ^7 || ^8 || ^9"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Sql\\Common\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Sql\\Common\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "phpunit --coverage-text"
    }
}
<?php

namespace Amp\Sql\Common\Test;

use Amp\Failure;
use Amp\PHPUnit\AsyncTestCase;
use Amp\Sql\Common\RetryConnector;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\ConnectionException;
use Amp\Sql\Connector;
use Amp\Sql\Link;
use Amp\Success;
class RetryConnectorTest extends AsyncTestCase
{
    /**
     *
     */
    public function testSuccessfulConnect() : \Generator
    {
        $connector = $this->createMock(Connector::class);
        $connector->expects($this->once())->method('connect')->willReturn(new Success($this->createMock(Link::class)));
        $retry = new RetryConnector($connector);
        $config = $this->getMockBuilder(ConnectionConfig::class)->setConstructorArgs(['localhost', 5432])->getMockForAbstractClass();
        $connection = (yield $retry->connect($config));
        $this->assertInstanceOf(Link::class, $connection);
    }
    /**
     *
     */
    public function testFirstTryFailConnect() : \Generator
    {
        $connector = $this->createMock(Connector::class);
        $connector->expects($this->exactly(2))->method('connect')->willReturnOnConsecutiveCalls(new Failure(new ConnectionException()), new Success($this->createMock(Link::class)));
        $retry = new RetryConnector($connector);
        $config = $this->getMockBuilder(ConnectionConfig::class)->setConstructorArgs(['localhost', 5432])->getMockForAbstractClass();
        $connection = (yield $retry->connect($config));
        $this->assertInstanceOf(Link::class, $connection);
    }
    /**
     *
     */
    public function testFailingConnect() : \Generator
    {
        $tries = 3;
        $connector = $this->createMock(Connector::class);
        $connector->expects($this->exactly($tries))->method('connect')->willReturn(new Failure(new ConnectionException()));
        $retry = new RetryConnector($connector, $tries);
        $config = $this->getMockBuilder(ConnectionConfig::class)->setConstructorArgs(['localhost', 5432])->getMockForAbstractClass();
        $this->expectException(ConnectionException::class);
        $this->expectExceptionMessage('Could not connect to database server');
        $connection = (yield $retry->connect($config));
    }
}<?php

namespace Amp\Sql\Common\Test;

use Amp\PHPUnit\AsyncTestCase;
use Amp\Sql\Common\PooledResultSet;
use Amp\Sql\ResultSet;
use Amp\Success;
class PooledResultSetTest extends AsyncTestCase
{
    /**
     *
     */
    public function testIdleConnectionsRemovedAfterTimeout() : \Generator
    {
        $invoked = false;
        $release = function () use(&$invoked) {
            $invoked = true;
        };
        $result = $this->createMock(ResultSet::class);
        $result->method('advance')->willReturnOnConsecutiveCalls(new Success(true), new Success(false));
        $result = new PooledResultSet($result, $release);
        $this->assertTrue((yield $result->advance()));
        $this->assertFalse($invoked);
        $this->assertFalse((yield $result->advance()));
        $this->assertTrue($invoked);
    }
}<?php

namespace Amp\Sql\Common\Test;

use Amp\Delayed;
use Amp\PHPUnit\AsyncTestCase;
use Amp\Promise;
use Amp\Sql\CommandResult;
use Amp\Sql\Common\ConnectionPool;
use Amp\Sql\ConnectionConfig;
use Amp\Sql\Connector;
use Amp\Sql\Link;
use Amp\Success;
class ConnectionPoolTest extends AsyncTestCase
{
    /**
     *
     */
    public function testInvalidMaxConnections()
    {
        $this->expectException(\Error::class);
        $this->expectExceptionMessage('Pool must contain at least one connection');
        $this->getMockBuilder(ConnectionPool::class)->setConstructorArgs([$this->createMock(ConnectionConfig::class), 0])->getMock();
    }
    /**
     *
     */
    private function createConnector() : Connector
    {
        $now = \time();
        $connector = $this->createMock(Connector::class);
        $connector->method('connect')->willReturnCallback(function () use($now) : Promise {
            $link = $this->createMock(Link::class);
            $link->method('getLastUsedAt')->willReturn($now);
            $link->method('isAlive')->willReturn(true);
            $link->method('query')->willReturnCallback(function () {
                return new Delayed(100, $this->createMock(CommandResult::class));
            });
            return new Success($link);
        });
        return $connector;
    }
    /**
     *
     */
    private function createPool(Connector $connector, int $maxConnections = 100, int $idleTimeout = 10) : ConnectionPool
    {
        return $this->getMockBuilder(ConnectionPool::class)->setConstructorArgs([$this->createMock(ConnectionConfig::class), $maxConnections, $idleTimeout, $connector])->getMockForAbstractClass();
    }
    /**
     *
     */
    public function testIdleConnectionsRemovedAfterTimeout() : \Generator
    {
        $connector = $this->createConnector();
        $pool = $this->createPool($connector, 10, 2);
        $count = 3;
        $promises = [];
        for ($i = 0; $i < $count; ++$i) {
            $promises[] = $pool->query("SELECT {$i}");
        }
        $this->assertCount($count, (yield $promises));
        $this->assertSame($count, $pool->getConnectionCount());
        (yield new Delayed(1000));
        $this->assertSame($count, $pool->getConnectionCount());
        (yield new Delayed(1000));
        $this->assertSame(0, $pool->getConnectionCount());
    }
    /**
     *
     */
    public function testMaxConnectionCount() : \Generator
    {
        $connector = $this->createConnector();
        $pool = $this->createPool($connector, $maxConnections = 3);
        $count = 10;
        $promises = [];
        for ($i = 0; $i < $count; ++$i) {
            $promises[] = $pool->query("SELECT {$i}");
        }
        $this->assertSame($maxConnections, $pool->getConnectionCount());
        $expectedRuntime = 100 * \ceil($count / $maxConnections);
        $this->setMinimumRuntime($expectedRuntime);
        $this->setTimeout($expectedRuntime + 100);
        $this->assertCount($count, (yield $promises));
    }
}<?php

namespace Amp\Sql\Common\Test;

use Amp\Delayed;
use Amp\PHPUnit\AsyncTestCase;
use Amp\Sql\Common\StatementPool;
use Amp\Sql\Pool;
use Amp\Sql\Statement;
use Amp\Success;
class StatementPoolTest extends AsyncTestCase
{
    /**
     *
     */
    public function testActiveStatementsRemainAfterTimeout() : \Generator
    {
        $pool = $this->createMock(Pool::class);
        $pool->method('isAlive')->willReturn(true);
        $pool->method('getIdleTimeout')->willReturn(60);
        $statement = $this->createMock(Statement::class);
        $statement->method('isAlive')->willReturn(true);
        $statement->method('getQuery')->willReturn('SELECT 1');
        $statement->method('getLastUsedAt')->willReturn(\time());
        $statement->expects($this->once())->method('execute');
        /** @var StatementPool $statementPool */
        $statementPool = $this->getMockBuilder(StatementPool::class)->setConstructorArgs([$pool, $statement, $this->createCallback(0)])->getMockForAbstractClass();
        $statementPool->method('prepare')->willReturnCallback(function (Statement $statement) {
            return new Success($statement);
        });
        $this->assertTrue($statementPool->isAlive());
        $this->assertSame(\time(), $statementPool->getLastUsedAt());
        (yield new Delayed(1500));
        // Give timeout watcher enough time to execute.
        $statementPool->execute();
        $this->assertTrue($statementPool->isAlive());
        $this->assertSame(\time(), $statementPool->getLastUsedAt());
    }
    /**
     *
     */
    public function testIdleStatementsRemovedAfterTimeout() : \Generator
    {
        $pool = $this->createMock(Pool::class);
        $pool->method('isAlive')->willReturn(true);
        $pool->method('getIdleTimeout')->willReturn(1);
        $statement = $this->createMock(Statement::class);
        $statement->method('isAlive')->willReturn(true);
        $statement->method('getQuery')->willReturn('SELECT 1');
        $statement->method('getLastUsedAt')->willReturn(\time());
        $statement->expects($this->once())->method('execute');
        /** @var StatementPool $statementPool */
        $statementPool = $this->getMockBuilder(StatementPool::class)->setConstructorArgs([$pool, $statement, $this->createCallback(1)])->getMockForAbstractClass();
        $statementPool->method('prepare')->willReturnCallback(function (Statement $statement) {
            return new Success($statement);
        });
        $this->assertTrue($statementPool->isAlive());
        $this->assertSame(\time(), $statementPool->getLastUsedAt());
        $statementPool->execute();
        (yield new Delayed(1500));
        // Give timeout watcher enough time to execute.
        $statementPool->execute();
        $this->assertTrue($statementPool->isAlive());
        $this->assertSame(\time(), $statementPool->getLastUsedAt());
    }
}{
    "name": "amphp/parser",
    "homepage": "https://github.com/amphp/parser",
    "description": "A generator parser to make streaming parsers simple.",
    "support": {
        "issues": "https://github.com/amphp/parser/issues"
    },
    "keywords": [
        "stream",
        "async",
        "non-blocking",
        "parser"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7"
    },
    "require-dev": {
        "phpunit/phpunit": "^6",
        "friendsofphp/php-cs-fixer": "^2.3"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Parser\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Parser\\Test\\": "test"
        }
    }
}
<?php

namespace Amp\Parser;

class InvalidDelimiterError extends \Error
{
    /**
     * @param \Generator $generator
     * @param string $prefix
     * @param (\Throwable | null) $previous
     */
    public function __construct(\Generator $generator, string $prefix, \Throwable $previous = null)
    {
        $yielded = $generator->current();
        $prefix .= \sprintf("; %s yielded at key %s", \is_object($yielded) ? \get_class($yielded) : \gettype($yielded), \var_export($generator->key(), true));
        if (!$generator->valid()) {
            parent::__construct($prefix, 0, $previous);
            return;
        }
        $reflGen = new \ReflectionGenerator($generator);
        $exeGen = $reflGen->getExecutingGenerator();
        if ($isSubgenerator = $exeGen !== $generator) {
            $reflGen = new \ReflectionGenerator($exeGen);
        }
        parent::__construct(\sprintf("%s on line %s in %s", $prefix, $reflGen->getExecutingLine(), $reflGen->getExecutingFile()), 0, $previous);
    }
}<?php

namespace Amp\Parser;

class Parser
{
    /** @var \Generator */
    private $generator;
    /** @var string */
    private $buffer = '';
    /** @var int|string|null */
    private $delimiter;
    /**
     * @param \Generator $generator
     *
     * @throws InvalidDelimiterError If the generator yields an invalid delimiter.
     * @throws \Throwable If the generator throws.
     */
    public function __construct(\Generator $generator)
    {
        $this->generator = $generator;
        $this->delimiter = $this->generator->current();
        if (!$this->generator->valid()) {
            $this->generator = null;
            return;
        }
        if ($this->delimiter !== null && (!\is_int($this->delimiter) || $this->delimiter <= 0) && (!\is_string($this->delimiter) || !\strlen($this->delimiter))) {
            throw new InvalidDelimiterError($generator, \sprintf("Invalid value yielded: Expected NULL, an int greater than 0, or a non-empty string; %s given", \is_object($this->delimiter) ? \sprintf("instance of %s", \get_class($this->delimiter)) : \gettype($this->delimiter)));
        }
    }
    /**
    * Cancels the generator parser and returns any remaining data in the internal buffer. Writing data after calling
    this method will result in an error.
    *
    * @return string
    */
    public final function cancel() : string
    {
        $this->generator = null;
        return $this->buffer;
    }
    /**
    * @return bool True if the parser can still receive more data to parse, false if it has ended and calling push
    will throw an exception.
    */
    public final function isValid() : bool
    {
        return $this->generator !== null;
    }
    /**
     * Adds data to the internal buffer and tries to continue parsing.
     *
     * @param string $data Data to append to the internal buffer.
     *
     * @throws InvalidDelimiterError If the generator yields an invalid delimiter.
     * @throws \Error If parsing has already been cancelled.
     * @throws \Throwable If the generator throws.
     */
    public final function push(string $data)
    {
        if ($this->generator === null) {
            throw new \Error("The parser is no longer writable");
        }
        $this->buffer .= $data;
        $end = false;
        try {
            while ($this->buffer !== "") {
                if (\is_int($this->delimiter)) {
                    if (\strlen($this->buffer) < $this->delimiter) {
                        break;
                        // Too few bytes in buffer.
                    }
                    $send = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $this->delimiter);
                    $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $this->delimiter);
                } elseif (\is_string($this->delimiter)) {
                    if (($position = \strpos($this->buffer, $this->delimiter)) === false) {
                        break;
                    }
                    $send = \Phabel\Target\Php80\Polyfill::substr($this->buffer, 0, $position);
                    $this->buffer = \Phabel\Target\Php80\Polyfill::substr($this->buffer, $position + \strlen($this->delimiter));
                } else {
                    $send = $this->buffer;
                    $this->buffer = "";
                }
                $this->delimiter = $this->generator->send($send);
                if (!$this->generator->valid()) {
                    $end = true;
                    break;
                }
                if ($this->delimiter !== null && (!\is_int($this->delimiter) || $this->delimiter <= 0) && (!\is_string($this->delimiter) || !\strlen($this->delimiter))) {
                    throw new InvalidDelimiterError($this->generator, \sprintf("Invalid value yielded: Expected NULL, an int greater than 0, or a non-empty string; %s given", \is_object($this->delimiter) ? \sprintf("instance of %s", \get_class($this->delimiter)) : \gettype($this->delimiter)));
                }
            }
        } catch (\Throwable $exception) {
            $end = true;
            throw $exception;
        } finally {
            if ($end) {
                $this->generator = null;
            }
        }
    }
}<?php

namespace Amp\Http\Internal;

use Amp\Http\HPackException;
/** @internal */
final class HPackNative
{
    private const HUFFMAN_CODE = [
        /* 0x00 */
        0x1ff8,
        0x7fffd8,
        0xfffffe2,
        0xfffffe3,
        0xfffffe4,
        0xfffffe5,
        0xfffffe6,
        0xfffffe7,
        /* 0x08 */
        0xfffffe8,
        0xffffea,
        0x3ffffffc,
        0xfffffe9,
        0xfffffea,
        0x3ffffffd,
        0xfffffeb,
        0xfffffec,
        /* 0x10 */
        0xfffffed,
        0xfffffee,
        0xfffffef,
        0xffffff0,
        0xffffff1,
        0xffffff2,
        0x3ffffffe,
        0xffffff3,
        /* 0x18 */
        0xffffff4,
        0xffffff5,
        0xffffff6,
        0xffffff7,
        0xffffff8,
        0xffffff9,
        0xffffffa,
        0xffffffb,
        /* 0x20 */
        0x14,
        0x3f8,
        0x3f9,
        0xffa,
        0x1ff9,
        0x15,
        0xf8,
        0x7fa,
        /* 0x28 */
        0x3fa,
        0x3fb,
        0xf9,
        0x7fb,
        0xfa,
        0x16,
        0x17,
        0x18,
        /* 0x30 */
        0x0,
        0x1,
        0x2,
        0x19,
        0x1a,
        0x1b,
        0x1c,
        0x1d,
        /* 0x38 */
        0x1e,
        0x1f,
        0x5c,
        0xfb,
        0x7ffc,
        0x20,
        0xffb,
        0x3fc,
        /* 0x40 */
        0x1ffa,
        0x21,
        0x5d,
        0x5e,
        0x5f,
        0x60,
        0x61,
        0x62,
        /* 0x48 */
        0x63,
        0x64,
        0x65,
        0x66,
        0x67,
        0x68,
        0x69,
        0x6a,
        /* 0x50 */
        0x6b,
        0x6c,
        0x6d,
        0x6e,
        0x6f,
        0x70,
        0x71,
        0x72,
        /* 0x58 */
        0xfc,
        0x73,
        0xfd,
        0x1ffb,
        0x7fff0,
        0x1ffc,
        0x3ffc,
        0x22,
        /* 0x60 */
        0x7ffd,
        0x3,
        0x23,
        0x4,
        0x24,
        0x5,
        0x25,
        0x26,
        /* 0x68 */
        0x27,
        0x6,
        0x74,
        0x75,
        0x28,
        0x29,
        0x2a,
        0x7,
        /* 0x70 */
        0x2b,
        0x76,
        0x2c,
        0x8,
        0x9,
        0x2d,
        0x77,
        0x78,
        /* 0x78 */
        0x79,
        0x7a,
        0x7b,
        0x7ffe,
        0x7fc,
        0x3ffd,
        0x1ffd,
        0xffffffc,
        /* 0x80 */
        0xfffe6,
        0x3fffd2,
        0xfffe7,
        0xfffe8,
        0x3fffd3,
        0x3fffd4,
        0x3fffd5,
        0x7fffd9,
        /* 0x88 */
        0x3fffd6,
        0x7fffda,
        0x7fffdb,
        0x7fffdc,
        0x7fffdd,
        0x7fffde,
        0xffffeb,
        0x7fffdf,
        /* 0x90 */
        0xffffec,
        0xffffed,
        0x3fffd7,
        0x7fffe0,
        0xffffee,
        0x7fffe1,
        0x7fffe2,
        0x7fffe3,
        /* 0x98 */
        0x7fffe4,
        0x1fffdc,
        0x3fffd8,
        0x7fffe5,
        0x3fffd9,
        0x7fffe6,
        0x7fffe7,
        0xffffef,
        /* 0xA0 */
        0x3fffda,
        0x1fffdd,
        0xfffe9,
        0x3fffdb,
        0x3fffdc,
        0x7fffe8,
        0x7fffe9,
        0x1fffde,
        /* 0xA8 */
        0x7fffea,
        0x3fffdd,
        0x3fffde,
        0xfffff0,
        0x1fffdf,
        0x3fffdf,
        0x7fffeb,
        0x7fffec,
        /* 0xB0 */
        0x1fffe0,
        0x1fffe1,
        0x3fffe0,
        0x1fffe2,
        0x7fffed,
        0x3fffe1,
        0x7fffee,
        0x7fffef,
        /* 0xB8 */
        0xfffea,
        0x3fffe2,
        0x3fffe3,
        0x3fffe4,
        0x7ffff0,
        0x3fffe5,
        0x3fffe6,
        0x7ffff1,
        /* 0xC0 */
        0x3ffffe0,
        0x3ffffe1,
        0xfffeb,
        0x7fff1,
        0x3fffe7,
        0x7ffff2,
        0x3fffe8,
        0x1ffffec,
        /* 0xC8 */
        0x3ffffe2,
        0x3ffffe3,
        0x3ffffe4,
        0x7ffffde,
        0x7ffffdf,
        0x3ffffe5,
        0xfffff1,
        0x1ffffed,
        /* 0xD0 */
        0x7fff2,
        0x1fffe3,
        0x3ffffe6,
        0x7ffffe0,
        0x7ffffe1,
        0x3ffffe7,
        0x7ffffe2,
        0xfffff2,
        /* 0xD8 */
        0x1fffe4,
        0x1fffe5,
        0x3ffffe8,
        0x3ffffe9,
        0xffffffd,
        0x7ffffe3,
        0x7ffffe4,
        0x7ffffe5,
        /* 0xE0 */
        0xfffec,
        0xfffff3,
        0xfffed,
        0x1fffe6,
        0x3fffe9,
        0x1fffe7,
        0x1fffe8,
        0x7ffff3,
        /* 0xE8 */
        0x3fffea,
        0x3fffeb,
        0x1ffffee,
        0x1ffffef,
        0xfffff4,
        0xfffff5,
        0x3ffffea,
        0x7ffff4,
        /* 0xF0 */
        0x3ffffeb,
        0x7ffffe6,
        0x3ffffec,
        0x3ffffed,
        0x7ffffe7,
        0x7ffffe8,
        0x7ffffe9,
        0x7ffffea,
        /* 0xF8 */
        0x7ffffeb,
        0xffffffe,
        0x7ffffec,
        0x7ffffed,
        0x7ffffee,
        0x7ffffef,
        0x7fffff0,
        0x3ffffee,
        /* end! */
        0x3fffffff,
    ];
    private const HUFFMAN_CODE_LENGTHS = [
        /* 0x00 */
        13,
        23,
        28,
        28,
        28,
        28,
        28,
        28,
        /* 0x08 */
        28,
        24,
        30,
        28,
        28,
        30,
        28,
        28,
        /* 0x10 */
        28,
        28,
        28,
        28,
        28,
        28,
        30,
        28,
        /* 0x18 */
        28,
        28,
        28,
        28,
        28,
        28,
        28,
        28,
        /* 0x20 */
        6,
        10,
        10,
        12,
        13,
        6,
        8,
        11,
        /* 0x28 */
        10,
        10,
        8,
        11,
        8,
        6,
        6,
        6,
        /* 0x30 */
        5,
        5,
        5,
        6,
        6,
        6,
        6,
        6,
        /* 0x38 */
        6,
        6,
        7,
        8,
        15,
        6,
        12,
        10,
        /* 0x40 */
        13,
        6,
        7,
        7,
        7,
        7,
        7,
        7,
        /* 0x48 */
        7,
        7,
        7,
        7,
        7,
        7,
        7,
        7,
        /* 0x50 */
        7,
        7,
        7,
        7,
        7,
        7,
        7,
        7,
        /* 0x58 */
        8,
        7,
        8,
        13,
        19,
        13,
        14,
        6,
        /* 0x60 */
        15,
        5,
        6,
        5,
        6,
        5,
        6,
        6,
        /* 0x68 */
        6,
        5,
        7,
        7,
        6,
        6,
        6,
        5,
        /* 0x70 */
        6,
        7,
        6,
        5,
        5,
        6,
        7,
        7,
        /* 0x78 */
        7,
        7,
        7,
        15,
        11,
        14,
        13,
        28,
        /* 0x80 */
        20,
        22,
        20,
        20,
        22,
        22,
        22,
        23,
        /* 0x88 */
        22,
        23,
        23,
        23,
        23,
        23,
        24,
        23,
        /* 0x90 */
        24,
        24,
        22,
        23,
        24,
        23,
        23,
        23,
        /* 0x98 */
        23,
        21,
        22,
        23,
        22,
        23,
        23,
        24,
        /* 0xA0 */
        22,
        21,
        20,
        22,
        22,
        23,
        23,
        21,
        /* 0xA8 */
        23,
        22,
        22,
        24,
        21,
        22,
        23,
        23,
        /* 0xB0 */
        21,
        21,
        22,
        21,
        23,
        22,
        23,
        23,
        /* 0xB8 */
        20,
        22,
        22,
        22,
        23,
        22,
        22,
        23,
        /* 0xC0 */
        26,
        26,
        20,
        19,
        22,
        23,
        22,
        25,
        /* 0xC8 */
        26,
        26,
        26,
        27,
        27,
        26,
        24,
        25,
        /* 0xD0 */
        19,
        21,
        26,
        27,
        27,
        26,
        27,
        24,
        /* 0xD8 */
        21,
        21,
        26,
        26,
        28,
        27,
        27,
        27,
        /* 0xE0 */
        20,
        24,
        20,
        21,
        22,
        21,
        21,
        23,
        /* 0xE8 */
        22,
        22,
        25,
        25,
        24,
        24,
        26,
        23,
        /* 0xF0 */
        26,
        27,
        26,
        26,
        27,
        27,
        27,
        27,
        /* 0xF8 */
        27,
        28,
        27,
        27,
        27,
        27,
        27,
        26,
        /* end! */
        30,
    ];
    private const DEFAULT_COMPRESSION_THRESHOLD = 1024;
    private const DEFAULT_MAX_SIZE = 4096;
    private static $huffmanLookup;
    private static $huffmanCodes;
    private static $huffmanLengths;
    private static $indexMap = [];
    /** @var string[][] */
    private $headers = [];
    /** @var int */
    private $hardMaxSize = self::DEFAULT_MAX_SIZE;
    /** @var int Max table size. */
    private $currentMaxSize = self::DEFAULT_MAX_SIZE;
    /** @var int Current table size. */
    private $size = 0;
    /**
     * Called via bindTo(), see end of file
     */
    private static function init()
    {
        self::$huffmanLookup = self::huffmanLookupInit();
        self::$huffmanCodes = self::huffmanCodesInit();
        self::$huffmanLengths = self::huffmanLengthsInit();
        foreach (\array_column(self::TABLE, 0) as $index => $name) {
            if (isset(self::$indexMap[$name])) {
                continue;
            }
            self::$indexMap[$name] = $index + 1;
        }
    }
    // (micro-)optimized decode
    /**
     *
     */
    private static function huffmanLookupInit() : array
    {
        if ('cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI || \filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
            return require __DIR__ . '/huffman-lookup.php';
        }
        \gc_disable();
        $encodingAccess = [];
        $terminals = [];
        $index = 7;
        foreach (self::HUFFMAN_CODE as $chr => $bits) {
            $len = self::HUFFMAN_CODE_LENGTHS[$chr];
            for ($bit = 0; $bit < 8; $bit++) {
                $offlen = $len + $bit;
                $next = $bit;
                for ($byte = $offlen - 1 >> 3; $byte > 0; $byte--) {
                    $cur = \str_pad(\decbin($bits >> $byte * 8 - (0x30 - $offlen & 7) & 0xff), 8, "0", STR_PAD_LEFT);
                    if (($encodingAccess[$next][$cur][0] ?? 0) !== 0) {
                        $next = $encodingAccess[$next][$cur][0];
                    } else {
                        $encodingAccess[$next][$cur] = [++$index, null];
                        $next = $index;
                    }
                }
                $key = \str_pad(\decbin($bits & (1 << ($offlen - 1 & 7) + 1) - 1), ($offlen - 1 & 7) + 1, "0", STR_PAD_LEFT);
                $encodingAccess[$next][$key] = [null, $chr > 0xff ? "" : \chr($chr)];
                if ($offlen & 7) {
                    $terminals[$offlen & 7][] = [$key, $next];
                } else {
                    $encodingAccess[$next][$key][0] = 0;
                }
            }
        }
        $memoize = [];
        for ($off = 7; $off > 0; $off--) {
            foreach ($terminals[$off] as [$key, $next]) {
                if ($encodingAccess[$next][$key][0] === null) {
                    foreach ($encodingAccess[$off] as $chr => $cur) {
                        $encodingAccess[$next][($memoize[$key] ?? ($memoize[$key] = \str_pad($key, 8, "0", STR_PAD_RIGHT))) | $chr] = [$cur[0], $encodingAccess[$next][$key][1] != "" ? $encodingAccess[$next][$key][1] . $cur[1] : ""];
                    }
                    unset($encodingAccess[$next][$key]);
                }
            }
        }
        $memoize = [];
        for ($off = 7; $off > 0; $off--) {
            foreach ($terminals[$off] as [$key, $next]) {
                foreach ($encodingAccess[$next] as $k => $v) {
                    if (\strlen($k) !== 1) {
                        $encodingAccess[$next][$memoize[$k] ?? ($memoize[$k] = \chr(\bindec($k)))] = $v;
                        unset($encodingAccess[$next][$k]);
                    }
                }
            }
            unset($encodingAccess[$off]);
        }
        \gc_enable();
        return $encodingAccess;
    }
    /**
     * @param string $input
     *
     * @return (string | null) Returns null if decoding fails.
     */
    public static function huffmanDecode(string $input)
    {
        $huffmanLookup = self::$huffmanLookup;
        $lookup = 0;
        $lengths = self::$huffmanLengths;
        $length = \strlen($input);
        $out = \str_repeat("\x00", (int) \floor($length / 5 * 8 + 1));
        // max length
        // Fail if EOS symbol is found.
        if (\strpos($input, "?\xff\xff\xff") !== false) {
            return null;
        }
        for ($bitCount = $off = $i = 0; $i < $length; $i++) {
            [$lookup, $chr] = $huffmanLookup[$lookup][$input[$i]];
            if ($chr === null) {
                continue;
            }
            if ($chr === "") {
                return null;
            }
            $out[$off++] = $chr[0];
            $bitCount += $lengths[$chr[0]];
            if (isset($chr[1])) {
                $out[$off++] = $chr[1];
                $bitCount += $lengths[$chr[1]];
            }
        }
        // Padding longer than 7-bits
        if ($i && $chr === null) {
            return null;
        }
        // Check for 0's in padding
        if ($bitCount & 7) {
            $mask = 0xff >> ($bitCount & 7);
            if ((\ord($input[$i - 1]) & $mask) !== $mask) {
                return null;
            }
        }
        return \Phabel\Target\Php80\Polyfill::substr($out, 0, $off);
    }
    /**
     *
     */
    private static function huffmanCodesInit() : array
    {
        if ('cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI || \filter_var(\ini_get('opcache.enable_cli'), \FILTER_VALIDATE_BOOLEAN)) {
            return require __DIR__ . '/huffman-codes.php';
        }
        $lookup = [];
        for ($chr = 0; $chr <= 0xff; $chr++) {
            $bits = self::HUFFMAN_CODE[$chr];
            $length = self::HUFFMAN_CODE_LENGTHS[$chr];
            for ($bit = 0; $bit < 8; $bit++) {
                $bytes = $length + $bit - 1 >> 3;
                $codes = [];
                for ($byte = $bytes; $byte >= 0; $byte--) {
                    $codes[] = \chr($byte ? $bits >> $length - ($bytes - $byte + 1) * 8 + $bit : $bits << (0x30 - $length - $bit & 7));
                }
                $lookup[$bit][\chr($chr)] = $codes;
            }
        }
        return $lookup;
    }
    /**
     *
     */
    private static function huffmanLengthsInit() : array
    {
        $lengths = [];
        for ($chr = 0; $chr <= 0xff; $chr++) {
            $lengths[\chr($chr)] = self::HUFFMAN_CODE_LENGTHS[$chr];
        }
        return $lengths;
    }
    /**
     *
     */
    public static function huffmanEncode(string $input) : string
    {
        $codes = self::$huffmanCodes;
        $lengths = self::$huffmanLengths;
        $length = \strlen($input);
        $out = \str_repeat("\x00", $length * 5 + 1);
        // max length
        for ($bitCount = $i = 0; $i < $length; $i++) {
            $chr = $input[$i];
            $byte = $bitCount >> 3;
            foreach ($codes[$bitCount & 7][$chr] as $bits) {
                // Note: |= can't be used with strings in PHP
                $out[$byte] = $out[$byte] | $bits;
                $byte++;
            }
            $bitCount += $lengths[$chr];
        }
        if ($bitCount & 7) {
            // Note: |= can't be used with strings in PHP
            $out[$byte - 1] = $out[$byte - 1] | \chr(0xff >> ($bitCount & 7));
        }
        return $i ? \Phabel\Target\Php80\Polyfill::substr($out, 0, $byte) : '';
    }
    /** @see RFC 7541 Appendix A */
    const LAST_INDEX = 61;
    const TABLE = [
        // starts at 1
        [":authority", ""],
        [":method", "GET"],
        [":method", "POST"],
        [":path", "/"],
        [":path", "/index.html"],
        [":scheme", "http"],
        [":scheme", "https"],
        [":status", "200"],
        [":status", "204"],
        [":status", "206"],
        [":status", "304"],
        [":status", "400"],
        [":status", "404"],
        [":status", "500"],
        ["accept-charset", ""],
        ["accept-encoding", "gzip, deflate"],
        ["accept-language", ""],
        ["accept-ranges", ""],
        ["accept", ""],
        ["access-control-allow-origin", ""],
        ["age", ""],
        ["allow", ""],
        ["authorization", ""],
        ["cache-control", ""],
        ["content-disposition", ""],
        ["content-encoding", ""],
        ["content-language", ""],
        ["content-length", ""],
        ["content-location", ""],
        ["content-range", ""],
        ["content-type", ""],
        ["cookie", ""],
        ["date", ""],
        ["etag", ""],
        ["expect", ""],
        ["expires", ""],
        ["from", ""],
        ["host", ""],
        ["if-match", ""],
        ["if-modified-since", ""],
        ["if-none-match", ""],
        ["if-range", ""],
        ["if-unmodified-since", ""],
        ["last-modified", ""],
        ["link", ""],
        ["location", ""],
        ["max-forwards", ""],
        ["proxy-authentication", ""],
        ["proxy-authorization", ""],
        ["range", ""],
        ["referer", ""],
        ["refresh", ""],
        ["retry-after", ""],
        ["server", ""],
        ["set-cookie", ""],
        ["strict-transport-security", ""],
        ["transfer-encoding", ""],
        ["user-agent", ""],
        ["vary", ""],
        ["via", ""],
        ["www-authenticate", ""],
    ];
    /**
     *
     */
    private static function decodeDynamicInteger(string $input, int &$off) : int
    {
        if (!isset($input[$off])) {
            throw new HPackException('Invalid input data, too short for dynamic integer');
        }
        $c = \ord($input[$off++]);
        $int = $c & 0x7f;
        $i = 0;
        while ($c & 0x80) {
            if (!isset($input[$off])) {
                return -0x80;
            }
            $c = \ord($input[$off++]);
            $int += ($c & 0x7f) << ++$i * 7;
        }
        return $int;
    }
    /**
     * @param int $maxSize Upper limit on table size.
     */
    public function __construct(int $maxSize = self::DEFAULT_MAX_SIZE)
    {
        $this->hardMaxSize = $maxSize;
    }
    /**
    * Sets the upper limit on table size. Dynamic table updates requesting a size above this size will result in a
    decoding error (i.e., returning null from decode()).
    *
    * @param int $maxSize
    */
    public function setTableSizeLimit(int $maxSize)
    {
        $this->hardMaxSize = $maxSize;
    }
    /**
     * Resizes the table to the given size, removing old entries as per section 4.4 if necessary.
     *
     * @param (int | null) $size
     */
    public function resizeTable(int $size = null)
    {
        if ($size !== null) {
            $this->currentMaxSize = \max(0, \min($size, $this->hardMaxSize));
        }
        while ($this->size > $this->currentMaxSize) {
            [$name, $value] = \array_pop($this->headers);
            $this->size -= 32 + \strlen($name) + \strlen($value);
        }
    }
    /**
     * @param string $input Encoded headers.
     * @param int $maxSize Maximum length of the decoded header string.
     *
     * @return (string[][] | null) Returns null if decoding fails or if $maxSize is exceeded.
     */
    public function decode(string $input, int $maxSize)
    {
        $headers = [];
        $off = 0;
        $inputLength = \strlen($input);
        $size = 0;
        try {
            // dynamic $table as per 2.3.2
            while ($off < $inputLength) {
                $index = \ord($input[$off++]);
                if ($index & 0x80) {
                    // range check
                    if ($index <= self::LAST_INDEX + 0x80) {
                        if ($index === 0x80) {
                            return null;
                        }
                        [$name, $value] = $headers[] = self::TABLE[$index - 0x81];
                    } else {
                        if ($index == 0xff) {
                            $index = self::decodeDynamicInteger($input, $off) + 0xff;
                        }
                        $index -= 0x81 + self::LAST_INDEX;
                        if (!isset($this->headers[$index])) {
                            return null;
                        }
                        [$name, $value] = $headers[] = $this->headers[$index];
                    }
                } elseif (($index & 0x60) !== 0x20) {
                    // (($index & 0x40) || !($index & 0x20)): bit 4: never index is ignored
                    $dynamic = (bool) ($index & 0x40);
                    if ($index & ($dynamic ? 0x3f : 0xf)) {
                        // separate length
                        if ($dynamic) {
                            if ($index === 0x7f) {
                                $index = self::decodeDynamicInteger($input, $off) + 0x3f;
                            } else {
                                $index &= 0x3f;
                            }
                        } else {
                            $index &= 0xf;
                            if ($index === 0xf) {
                                $index = self::decodeDynamicInteger($input, $off) + 0xf;
                            }
                        }
                        if ($index < 0) {
                            return null;
                        }
                        if ($index <= self::LAST_INDEX) {
                            $header = self::TABLE[$index - 1];
                        } elseif (!isset($this->headers[$index - 1 - self::LAST_INDEX])) {
                            return null;
                        } else {
                            $header = $this->headers[$index - 1 - self::LAST_INDEX];
                        }
                    } else {
                        if ($off >= $inputLength) {
                            return null;
                        }
                        $length = \ord($input[$off++]);
                        $huffman = $length & 0x80;
                        $length &= 0x7f;
                        if ($length === 0x7f) {
                            $length = self::decodeDynamicInteger($input, $off) + 0x7f;
                        }
                        if ($inputLength - $off < $length || $length <= 0) {
                            return null;
                        }
                        if ($huffman) {
                            $header = [self::huffmanDecode(\Phabel\Target\Php80\Polyfill::substr($input, $off, $length))];
                            if ($header[0] === null) {
                                return null;
                            }
                        } else {
                            $header = [\Phabel\Target\Php80\Polyfill::substr($input, $off, $length)];
                        }
                        $off += $length;
                    }
                    if ($off >= $inputLength) {
                        return null;
                    }
                    $length = \ord($input[$off++]);
                    $huffman = $length & 0x80;
                    $length &= 0x7f;
                    if ($length === 0x7f) {
                        $length = self::decodeDynamicInteger($input, $off) + 0x7f;
                    }
                    if ($inputLength - $off < $length || $length < 0) {
                        return null;
                    }
                    if ($huffman) {
                        $header[1] = self::huffmanDecode(\Phabel\Target\Php80\Polyfill::substr($input, $off, $length));
                        if ($header[1] === null) {
                            return null;
                        }
                    } else {
                        $header[1] = \Phabel\Target\Php80\Polyfill::substr($input, $off, $length);
                    }
                    $off += $length;
                    if ($dynamic) {
                        \array_unshift($this->headers, $header);
                        $this->size += 32 + \strlen($header[0]) + \strlen($header[1]);
                        if ($this->currentMaxSize < $this->size) {
                            $this->resizeTable();
                        }
                    }
                    [$name, $value] = $headers[] = $header;
                } else {
                    // if ($index & 0x20) {
                    if ($off >= $inputLength) {
                        return null;
                        // Dynamic table size update must not be the last entry in header block.
                    }
                    $index &= 0x1f;
                    if ($index === 0x1f) {
                        $index = self::decodeDynamicInteger($input, $off) + 0x1f;
                    }
                    if ($index > $this->hardMaxSize) {
                        return null;
                    }
                    $this->resizeTable($index);
                    continue;
                }
                $size += \strlen($name) + \strlen($value);
                if ($size > $maxSize) {
                    return null;
                }
            }
        } catch (HPackException $e) {
            return null;
        }
        return $headers;
    }
    /**
     *
     */
    private static function encodeDynamicInteger(int $int) : string
    {
        $out = "";
        for ($i = 0; $int >> $i > 0x80; $i += 7) {
            $out .= \chr(0x80 | $int >> $i & 0x7f);
        }
        return $out . \chr($int >> $i);
    }
    /**
     * @param string[][] $headers
     * @param int $compressionThreshold Compress strings whose length is at least the number of bytes given.
     *
     * @return string
     */
    public function encode(array $headers, int $compressionThreshold = self::DEFAULT_COMPRESSION_THRESHOLD) : string
    {
        // @TODO implementation is deliberately primitive... [doesn't use any dynamic table...]
        $output = "";
        foreach ($headers as [$name, $value]) {
            if (isset(self::$indexMap[$name])) {
                $index = self::$indexMap[$name];
                if ($index < 0x10) {
                    $output .= \chr($index);
                } else {
                    $output .= "\x0f" . \chr($index - 0xf);
                }
            } else {
                $output .= "\x00" . $this->encodeString($name, $compressionThreshold);
            }
            $output .= $this->encodeString($value, $compressionThreshold);
        }
        return $output;
    }
    /**
     *
     */
    private function encodeString(string $value, int $compressionThreshold) : string
    {
        $prefix = "\x00";
        if (\strlen($value) >= $compressionThreshold) {
            $value = self::huffmanEncode($value);
            $prefix = "\x80";
        }
        if (\strlen($value) < 0x7f) {
            return ($prefix | \chr(\strlen($value))) . $value;
        }
        return ($prefix | "") . self::encodeDynamicInteger(\strlen($value) - 0x7f) . $value;
    }
}
(function () {
    static::init();
})->bindTo(null, HPackNative::class)();<?php

/** @noinspection PhpUndefinedMethodInspection */
/** @noinspection PhpUndefinedClassInspection */
namespace Amp\Http\Internal;

use Amp\Http\HPackException;
use FFI;
/** @internal */
final class HPackNghttp2
{
    private const FLAG_NO_INDEX = 0x1;
    private const FLAG_NO_COPY_NAME = 0x2;
    private const FLAG_NO_COPY_VALUE = 0x4;
    private const FLAG_NO_COPY = self::FLAG_NO_COPY_NAME | self::FLAG_NO_COPY_VALUE;
    private const FLAG_NO_COPY_SENSITIVE = self::FLAG_NO_COPY | self::FLAG_NO_INDEX;
    private const SENSITIVE_HEADERS = ['authorization' => self::FLAG_NO_COPY_SENSITIVE, 'cookie' => self::FLAG_NO_COPY_SENSITIVE, 'proxy-authorization' => self::FLAG_NO_COPY_SENSITIVE, 'set-cookie' => self::FLAG_NO_COPY_SENSITIVE];
    private static $ffi;
    private static $deflatePtrType;
    private static $inflatePtrType;
    private static $nvType;
    private static $nvSize;
    private static $charType;
    private static $uint8Type;
    private static $uint8PtrType;
    private static $decodeNv;
    private static $decodeNvPtr;
    private static $decodeFlags;
    private static $decodeFlagsPtr;
    private static $supported;
    /**
     *
     */
    public static function isSupported() : bool
    {
        if (isset(self::$supported)) {
            return self::$supported;
        }
        if (!\extension_loaded('ffi')) {
            return self::$supported = false;
        }
        if (!\class_exists(FFI::class)) {
            return self::$supported = false;
        }
        try {
            self::init();
            return self::$supported = true;
        } catch (\Throwable $e) {
            return self::$supported = false;
        }
    }
    /**
     *
     */
    private static function init() : void
    {
        if (self::$ffi !== null) {
            return;
        }
        $header = \file_get_contents(__DIR__ . '/amp-hpack.h');
        try {
            self::$ffi = FFI::cdef($header, 'libnghttp2.so');
        } catch (\Throwable $exception) {
            self::$ffi = FFI::cdef($header, 'libnghttp2.dylib');
        }
        self::$deflatePtrType = self::$ffi->type('nghttp2_hd_deflater*');
        self::$inflatePtrType = self::$ffi->type('nghttp2_hd_inflater*');
        self::$nvType = self::$ffi->type('nghttp2_nv');
        self::$nvSize = FFI::sizeof(self::$nvType);
        self::$charType = self::$ffi->type('char');
        self::$uint8Type = self::$ffi->type('uint8_t');
        self::$uint8PtrType = self::$ffi->type('uint8_t*');
        self::$decodeNv = self::$ffi->new(self::$nvType);
        self::$decodeNvPtr = FFI::addr(self::$decodeNv);
        self::$decodeFlags = self::$ffi->new('int');
        self::$decodeFlagsPtr = FFI::addr(self::$decodeFlags);
    }
    /**
     *
     */
    private static function createBufferFromString(string $value)
    {
        $length = \strlen($value);
        $buffer = FFI::new(FFI::arrayType(self::$uint8Type, [$length]));
        FFI::memcpy($buffer, $value, $length);
        return $buffer;
    }
    private $deflatePtr;
    private $inflatePtr;
    /**
     * @param int $maxSize Upper limit on table size.
     */
    public function __construct(int $maxSize = 4096)
    {
        self::init();
        $this->deflatePtr = self::$ffi->new(self::$deflatePtrType);
        $this->inflatePtr = self::$ffi->new(self::$inflatePtrType);
        $return = self::$ffi->nghttp2_hd_deflate_new(FFI::addr($this->deflatePtr), $maxSize);
        if ($return !== 0) {
            throw new \RuntimeException('Failed to init deflate context');
        }
        $return = self::$ffi->nghttp2_hd_inflate_new(FFI::addr($this->inflatePtr));
        if ($return !== 0) {
            throw new \RuntimeException('Failed to init inflate context');
        }
    }
    /**
     * @param string $input Encoded headers.
     * @param int $maxSize Maximum length of the decoded header string.
     *
     * @return (string[][] | null) Returns null if decoding fails or if $maxSize is exceeded.
     */
    public function decode(string $input, int $maxSize) : ?array
    {
        $ffi = self::$ffi;
        $pair = self::$decodeNv;
        $pairPtr = self::$decodeNvPtr;
        $flags = self::$decodeFlags;
        $flagsPtr = self::$decodeFlagsPtr;
        $inflate = $this->inflatePtr;
        $size = 0;
        $bufferLength = \strlen($input);
        $buffer = self::createBufferFromString($input);
        $offset = 0;
        $bufferPtr = FFI::cast(self::$uint8PtrType, $buffer);
        $headers = [];
        while (true) {
            $read = $ffi->nghttp2_hd_inflate_hd2($inflate, $pairPtr, $flagsPtr, $bufferPtr, $bufferLength - $offset, 1);
            if ($read < 0) {
                return null;
            }
            $offset += $read;
            $bufferPtr += $read;
            $cFlags = $flags->cdata;
            if ($cFlags & 0x2) {
                // NGHTTP2_HD_INFLATE_EMIT
                $nameLength = $pair->namelen;
                $valueLength = $pair->valuelen;
                $headers[] = [FFI::string($pair->name, $nameLength), FFI::string($pair->value, $valueLength)];
                $size += $nameLength + $valueLength;
                if ($size > $maxSize) {
                    return null;
                }
            }
            if ($cFlags & 0x1) {
                // NGHTTP2_HD_INFLATE_FINAL
                $ffi->nghttp2_hd_inflate_end_headers($inflate);
                FFI::memset($pair, 0, self::$nvSize);
                return $headers;
            }
            if ($read === 0 || $offset > $bufferLength) {
                return null;
            }
        }
        return null;
    }
    /**
     * @param string[][] $headers
     *
     * @return string Encoded headers.
     */
    public function encode(array $headers) : string
    {
        $ffi = self::$ffi;
        // To keep memory buffers
        $buffers = [];
        $headerCount = \count($headers);
        $current = 0;
        $pairs = $ffi->new(FFI::arrayType(self::$nvType, [$headerCount]));
        foreach ($headers as $index => [$name, $value]) {
            \assert($index === $current);
            $pair = $pairs[$current];
            $nameBuffer = self::createBufferFromString($name);
            $valueBuffer = self::createBufferFromString($value);
            $pair->name = FFI::cast(self::$uint8PtrType, $nameBuffer);
            $pair->namelen = \strlen($name);
            $pair->value = FFI::cast(self::$uint8PtrType, $valueBuffer);
            $pair->valuelen = \strlen($value);
            $pair->flags = self::SENSITIVE_HEADERS[$name] ?? self::FLAG_NO_COPY;
            $buffers[] = $nameBuffer;
            $buffers[] = $valueBuffer;
            $current++;
        }
        $bufferLength = $ffi->nghttp2_hd_deflate_bound($this->deflatePtr, $pairs, $headerCount);
        $buffer = FFI::new(FFI::arrayType(self::$uint8Type, [$bufferLength]));
        $bufferLength = $ffi->nghttp2_hd_deflate_hd($this->deflatePtr, $buffer, $bufferLength, $pairs, $headerCount);
        if ($bufferLength < 0) {
            throw new HPackException('Failed to compress headers using nghttp2');
        }
        return FFI::string($buffer, $bufferLength);
    }
}<?php

return [["\x00" => [93, "0"], "\x01" => [138, "0"], "\x02" => [75, "0"], "\x03" => [91, "0"], "\x04" => [108, "0"], "\x05" => [103, "0"], "\x06" => [114, "0"], "\x07" => [14, "0"], "\x08" => [93, "1"], "\t" => [138, "1"], "\n" => [75, "1"], "\v" => [91, "1"], "\f" => [108, "1"], "\r" => [103, "1"], "\x0e" => [114, "1"], "\x0f" => [14, "1"], "\x10" => [93, "2"], "\x11" => [138, "2"], "\x12" => [75, "2"], "\x13" => [91, "2"], "\x14" => [108, "2"], "\x15" => [103, "2"], "\x16" => [114, "2"], "\x17" => [14, "2"], "\x18" => [93, "a"], "\x19" => [138, "a"], "\x1a" => [75, "a"], "\x1b" => [91, "a"], "\x1c" => [108, "a"], "\x1d" => [103, "a"], "\x1e" => [114, "a"], "\x1f" => [14, "a"], " " => [93, "c"], "!" => [138, "c"], "\"" => [75, "c"], "#" => [91, "c"], "\$" => [108, "c"], "%" => [103, "c"], "&" => [114, "c"], "'" => [14, "c"], "(" => [93, "e"], ")" => [138, "e"], "*" => [75, "e"], "+" => [91, "e"], "," => [108, "e"], "-" => [103, "e"], "." => [114, "e"], "/" => [14, "e"], [93, "i"], [138, "i"], [75, "i"], [91, "i"], [108, "i"], [103, "i"], [114, "i"], [14, "i"], [93, "o"], [138, "o"], ":" => [75, "o"], ";" => [91, "o"], "<" => [108, "o"], "=" => [103, "o"], ">" => [114, "o"], "?" => [14, "o"], "@" => [93, "s"], "A" => [138, "s"], "B" => [75, "s"], "C" => [91, "s"], "D" => [108, "s"], "E" => [103, "s"], "F" => [114, "s"], "G" => [14, "s"], "H" => [93, "t"], "I" => [138, "t"], "J" => [75, "t"], "K" => [91, "t"], "L" => [108, "t"], "M" => [103, "t"], "N" => [114, "t"], "O" => [14, "t"], "P" => [94, " "], "Q" => [76, " "], "R" => [104, " "], "S" => [16, " "], "T" => [94, "%"], "U" => [76, "%"], "V" => [104, "%"], "W" => [16, "%"], "X" => [94, "-"], "Y" => [76, "-"], "Z" => [104, "-"], "[" => [16, "-"], "\\" => [94, "."], "]" => [76, "."], "^" => [104, "."], "_" => [16, "."], "`" => [94, "/"], "a" => [76, "/"], "b" => [104, "/"], "c" => [16, "/"], "d" => [94, "3"], "e" => [76, "3"], "f" => [104, "3"], "g" => [16, "3"], "h" => [94, "4"], "i" => [76, "4"], "j" => [104, "4"], "k" => [16, "4"], "l" => [94, "5"], "m" => [76, "5"], "n" => [104, "5"], "o" => [16, "5"], "p" => [94, "6"], "q" => [76, "6"], "r" => [104, "6"], "s" => [16, "6"], "t" => [94, "7"], "u" => [76, "7"], "v" => [104, "7"], "w" => [16, "7"], "x" => [94, "8"], "y" => [76, "8"], "z" => [104, "8"], "{" => [16, "8"], "|" => [94, "9"], "}" => [76, "9"], "~" => [104, "9"], "" => [16, "9"], "\x80" => [94, "="], "\x81" => [76, "="], "\x82" => [104, "="], "\x83" => [16, "="], "\x84" => [94, "A"], "\x85" => [76, "A"], "\x86" => [104, "A"], "\x87" => [16, "A"], "\x88" => [94, "_"], "\x89" => [76, "_"], "\x8a" => [104, "_"], "\x8b" => [16, "_"], "\x8c" => [94, "b"], "\x8d" => [76, "b"], "\x8e" => [104, "b"], "\x8f" => [16, "b"], "\x90" => [94, "d"], "\x91" => [76, "d"], "\x92" => [104, "d"], "\x93" => [16, "d"], "\x94" => [94, "f"], "\x95" => [76, "f"], "\x96" => [104, "f"], "\x97" => [16, "f"], "\x98" => [94, "g"], "\x99" => [76, "g"], "\x9a" => [104, "g"], "\x9b" => [16, "g"], "\x9c" => [94, "h"], "\x9d" => [76, "h"], "\x9e" => [104, "h"], "\x9f" => [16, "h"], "\xa0" => [94, "l"], "\xa1" => [76, "l"], "\xa2" => [104, "l"], "\xa3" => [16, "l"], "\xa4" => [94, "m"], "\xa5" => [76, "m"], "\xa6" => [104, "m"], "\xa7" => [16, "m"], "\xa8" => [94, "n"], "\xa9" => [76, "n"], "\xaa" => [104, "n"], "\xab" => [16, "n"], "\xac" => [94, "p"], "\xad" => [76, "p"], "\xae" => [104, "p"], "\xaf" => [16, "p"], "\xb0" => [94, "r"], "\xb1" => [76, "r"], "\xb2" => [104, "r"], "\xb3" => [16, "r"], "\xb4" => [94, "u"], "\xb5" => [76, "u"], "\xb6" => [104, "u"], "\xb7" => [16, "u"], "\xb8" => [77, ":"], "\xb9" => [18, ":"], "\xba" => [77, "B"], "\xbb" => [18, "B"], "\xbc" => [77, "C"], "\xbd" => [18, "C"], "\xbe" => [77, "D"], "\xbf" => [18, "D"], "\xc0" => [77, "E"], "\xc1" => [18, "E"], "\xc2" => [77, "F"], "\xc3" => [18, "F"], "\xc4" => [77, "G"], "\xc5" => [18, "G"], "\xc6" => [77, "H"], "\xc7" => [18, "H"], "\xc8" => [77, "I"], "\xc9" => [18, "I"], "\xca" => [77, "J"], "\xcb" => [18, "J"], "\xcc" => [77, "K"], "\xcd" => [18, "K"], "\xce" => [77, "L"], "\xcf" => [18, "L"], "\xd0" => [77, "M"], "\xd1" => [18, "M"], "\xd2" => [77, "N"], "\xd3" => [18, "N"], "\xd4" => [77, "O"], "\xd5" => [18, "O"], "\xd6" => [77, "P"], "\xd7" => [18, "P"], "\xd8" => [77, "Q"], "\xd9" => [18, "Q"], "\xda" => [77, "R"], "\xdb" => [18, "R"], "\xdc" => [77, "S"], "\xdd" => [18, "S"], "\xde" => [77, "T"], "\xdf" => [18, "T"], "\xe0" => [77, "U"], "\xe1" => [18, "U"], "\xe2" => [77, "V"], "\xe3" => [18, "V"], "\xe4" => [77, "W"], "\xe5" => [18, "W"], "\xe6" => [77, "Y"], "\xe7" => [18, "Y"], "\xe8" => [77, "j"], "\xe9" => [18, "j"], "\xea" => [77, "k"], "\xeb" => [18, "k"], "\xec" => [77, "q"], "\xed" => [18, "q"], "\xee" => [77, "v"], "\xef" => [18, "v"], "\xf0" => [77, "w"], "\xf1" => [18, "w"], "\xf2" => [77, "x"], "\xf3" => [18, "x"], "\xf4" => [77, "y"], "\xf5" => [18, "y"], "\xf6" => [77, "z"], "\xf7" => [18, "z"], "\xf8" => [0, "&"], "\xf9" => [0, "*"], "\xfa" => [0, ","], "\xfb" => [0, ";"], "\xfc" => [0, "X"], "\xfd" => [0, "Z"], "\xfe" => [78, null], "\xff" => [8, null]], 8 => ["\x00" => [77, "?0"], "\x01" => [18, "?0"], "\x02" => [77, "?1"], "\x03" => [18, "?1"], "\x04" => [77, "?2"], "\x05" => [18, "?2"], "\x06" => [77, "?a"], "\x07" => [18, "?a"], "\x08" => [77, "?c"], "\t" => [18, "?c"], "\n" => [77, "?e"], "\v" => [18, "?e"], "\f" => [77, "?i"], "\r" => [18, "?i"], "\x0e" => [77, "?o"], "\x0f" => [18, "?o"], "\x10" => [77, "?s"], "\x11" => [18, "?s"], "\x12" => [77, "?t"], "\x13" => [18, "?t"], "\x14" => [0, "? "], "\x15" => [0, "?%"], "\x16" => [0, "?-"], "\x17" => [0, "?."], "\x18" => [0, "?/"], "\x19" => [0, "?3"], "\x1a" => [0, "?4"], "\x1b" => [0, "?5"], "\x1c" => [0, "?6"], "\x1d" => [0, "?7"], "\x1e" => [0, "?8"], "\x1f" => [0, "?9"], " " => [0, "?="], "!" => [0, "?A"], "\"" => [0, "?_"], "#" => [0, "?b"], "\$" => [0, "?d"], "%" => [0, "?f"], "&" => [0, "?g"], "'" => [0, "?h"], "(" => [0, "?l"], ")" => [0, "?m"], "*" => [0, "?n"], "+" => [0, "?p"], "," => [0, "?r"], "-" => [0, "?u"], "." => [100, "?"], "/" => [110, "?"], [111, "?"], [115, "?"], [116, "?"], [118, "?"], [119, "?"], [122, "?"], [123, "?"], [125, "?"], [126, "?"], [129, "?"], ":" => [143, "?"], ";" => [148, "?"], "<" => [151, "?"], "=" => [153, "?"], ">" => [83, "?"], "?" => [10, "?"], "@" => [0, "'0"], "A" => [0, "'1"], "B" => [0, "'2"], "C" => [0, "'a"], "D" => [0, "'c"], "E" => [0, "'e"], "F" => [0, "'i"], "G" => [0, "'o"], "H" => [0, "'s"], "I" => [0, "'t"], "J" => [73, "'"], "K" => [88, "'"], "L" => [89, "'"], "M" => [96, "'"], "N" => [97, "'"], "O" => [99, "'"], "P" => [106, "'"], "Q" => [136, "'"], "R" => [139, "'"], "S" => [141, "'"], "T" => [145, "'"], "U" => [147, "'"], "V" => [149, "'"], "W" => [101, "'"], "X" => [112, "'"], "Y" => [117, "'"], "Z" => [120, "'"], "[" => [124, "'"], "\\" => [127, "'"], "]" => [144, "'"], "^" => [152, "'"], "_" => [11, "'"], "`" => [0, "+0"], "a" => [0, "+1"], "b" => [0, "+2"], "c" => [0, "+a"], "d" => [0, "+c"], "e" => [0, "+e"], "f" => [0, "+i"], "g" => [0, "+o"], "h" => [0, "+s"], "i" => [0, "+t"], "j" => [73, "+"], "k" => [88, "+"], "l" => [89, "+"], "m" => [96, "+"], "n" => [97, "+"], "o" => [99, "+"], "p" => [106, "+"], "q" => [136, "+"], "r" => [139, "+"], "s" => [141, "+"], "t" => [145, "+"], "u" => [147, "+"], "v" => [149, "+"], "w" => [101, "+"], "x" => [112, "+"], "y" => [117, "+"], "z" => [120, "+"], "{" => [124, "+"], "|" => [127, "+"], "}" => [144, "+"], "~" => [152, "+"], "" => [11, "+"], "\x80" => [0, "|0"], "\x81" => [0, "|1"], "\x82" => [0, "|2"], "\x83" => [0, "|a"], "\x84" => [0, "|c"], "\x85" => [0, "|e"], "\x86" => [0, "|i"], "\x87" => [0, "|o"], "\x88" => [0, "|s"], "\x89" => [0, "|t"], "\x8a" => [73, "|"], "\x8b" => [88, "|"], "\x8c" => [89, "|"], "\x8d" => [96, "|"], "\x8e" => [97, "|"], "\x8f" => [99, "|"], "\x90" => [106, "|"], "\x91" => [136, "|"], "\x92" => [139, "|"], "\x93" => [141, "|"], "\x94" => [145, "|"], "\x95" => [147, "|"], "\x96" => [149, "|"], "\x97" => [101, "|"], "\x98" => [112, "|"], "\x99" => [117, "|"], "\x9a" => [120, "|"], "\x9b" => [124, "|"], "\x9c" => [127, "|"], "\x9d" => [144, "|"], "\x9e" => [152, "|"], "\x9f" => [11, "|"], "\xa0" => [92, "#"], "\xa1" => [95, "#"], "\xa2" => [137, "#"], "\xa3" => [142, "#"], "\xa4" => [150, "#"], "\xa5" => [74, "#"], "\xa6" => [90, "#"], "\xa7" => [98, "#"], "\xa8" => [107, "#"], "\xa9" => [140, "#"], "\xaa" => [146, "#"], "\xab" => [102, "#"], "\xac" => [113, "#"], "\xad" => [121, "#"], "\xae" => [128, "#"], "\xaf" => [12, "#"], "\xb0" => [92, ">"], "\xb1" => [95, ">"], "\xb2" => [137, ">"], "\xb3" => [142, ">"], "\xb4" => [150, ">"], "\xb5" => [74, ">"], "\xb6" => [90, ">"], "\xb7" => [98, ">"], "\xb8" => [107, ">"], "\xb9" => [140, ">"], "\xba" => [146, ">"], "\xbb" => [102, ">"], "\xbc" => [113, ">"], "\xbd" => [121, ">"], "\xbe" => [128, ">"], "\xbf" => [12, ">"], "\xc0" => [93, "\x00"], "\xc1" => [138, "\x00"], "\xc2" => [75, "\x00"], "\xc3" => [91, "\x00"], "\xc4" => [108, "\x00"], "\xc5" => [103, "\x00"], "\xc6" => [114, "\x00"], "\xc7" => [14, "\x00"], "\xc8" => [93, "\$"], "\xc9" => [138, "\$"], "\xca" => [75, "\$"], "\xcb" => [91, "\$"], "\xcc" => [108, "\$"], "\xcd" => [103, "\$"], "\xce" => [114, "\$"], "\xcf" => [14, "\$"], "\xd0" => [93, "@"], "\xd1" => [138, "@"], "\xd2" => [75, "@"], "\xd3" => [91, "@"], "\xd4" => [108, "@"], "\xd5" => [103, "@"], "\xd6" => [114, "@"], "\xd7" => [14, "@"], "\xd8" => [93, "["], "\xd9" => [138, "["], "\xda" => [75, "["], "\xdb" => [91, "["], "\xdc" => [108, "["], "\xdd" => [103, "["], "\xde" => [114, "["], "\xdf" => [14, "["], "\xe0" => [93, "]"], "\xe1" => [138, "]"], "\xe2" => [75, "]"], "\xe3" => [91, "]"], "\xe4" => [108, "]"], "\xe5" => [103, "]"], "\xe6" => [114, "]"], "\xe7" => [14, "]"], "\xe8" => [93, "~"], "\xe9" => [138, "~"], "\xea" => [75, "~"], "\xeb" => [91, "~"], "\xec" => [108, "~"], "\xed" => [103, "~"], "\xee" => [114, "~"], "\xef" => [14, "~"], "\xf0" => [94, "^"], "\xf1" => [76, "^"], "\xf2" => [104, "^"], "\xf3" => [16, "^"], "\xf4" => [94, "}"], "\xf5" => [76, "}"], "\xf6" => [104, "}"], "\xf7" => [16, "}"], "\xf8" => [77, "<"], "\xf9" => [18, "<"], "\xfa" => [77, "`"], "\xfb" => [18, "`"], "\xfc" => [77, "{"], "\xfd" => [18, "{"], "\xfe" => [131, null], "\xff" => [20, null]], ["\x00" => [0, "!0"], "\x01" => [0, "!1"], "\x02" => [0, "!2"], "\x03" => [0, "!a"], "\x04" => [0, "!c"], "\x05" => [0, "!e"], "\x06" => [0, "!i"], "\x07" => [0, "!o"], "\x08" => [0, "!s"], "\t" => [0, "!t"], "\n" => [73, "!"], "\v" => [88, "!"], "\f" => [89, "!"], "\r" => [96, "!"], "\x0e" => [97, "!"], "\x0f" => [99, "!"], "\x10" => [106, "!"], "\x11" => [136, "!"], "\x12" => [139, "!"], "\x13" => [141, "!"], "\x14" => [145, "!"], "\x15" => [147, "!"], "\x16" => [149, "!"], "\x17" => [101, "!"], "\x18" => [112, "!"], "\x19" => [117, "!"], "\x1a" => [120, "!"], "\x1b" => [124, "!"], "\x1c" => [127, "!"], "\x1d" => [144, "!"], "\x1e" => [152, "!"], "\x1f" => [11, "!"], " " => [0, "\"0"], "!" => [0, "\"1"], "\"" => [0, "\"2"], "#" => [0, "\"a"], "\$" => [0, "\"c"], "%" => [0, "\"e"], "&" => [0, "\"i"], "'" => [0, "\"o"], "(" => [0, "\"s"], ")" => [0, "\"t"], "*" => [73, "\""], "+" => [88, "\""], "," => [89, "\""], "-" => [96, "\""], "." => [97, "\""], "/" => [99, "\""], [106, "\""], [136, "\""], [139, "\""], [141, "\""], [145, "\""], [147, "\""], [149, "\""], [101, "\""], [112, "\""], [117, "\""], ":" => [120, "\""], ";" => [124, "\""], "<" => [127, "\""], "=" => [144, "\""], ">" => [152, "\""], "?" => [11, "\""], "@" => [0, "(0"], "A" => [0, "(1"], "B" => [0, "(2"], "C" => [0, "(a"], "D" => [0, "(c"], "E" => [0, "(e"], "F" => [0, "(i"], "G" => [0, "(o"], "H" => [0, "(s"], "I" => [0, "(t"], "J" => [73, "("], "K" => [88, "("], "L" => [89, "("], "M" => [96, "("], "N" => [97, "("], "O" => [99, "("], "P" => [106, "("], "Q" => [136, "("], "R" => [139, "("], "S" => [141, "("], "T" => [145, "("], "U" => [147, "("], "V" => [149, "("], "W" => [101, "("], "X" => [112, "("], "Y" => [117, "("], "Z" => [120, "("], "[" => [124, "("], "\\" => [127, "("], "]" => [144, "("], "^" => [152, "("], "_" => [11, "("], "`" => [0, ")0"], "a" => [0, ")1"], "b" => [0, ")2"], "c" => [0, ")a"], "d" => [0, ")c"], "e" => [0, ")e"], "f" => [0, ")i"], "g" => [0, ")o"], "h" => [0, ")s"], "i" => [0, ")t"], "j" => [73, ")"], "k" => [88, ")"], "l" => [89, ")"], "m" => [96, ")"], "n" => [97, ")"], "o" => [99, ")"], "p" => [106, ")"], "q" => [136, ")"], "r" => [139, ")"], "s" => [141, ")"], "t" => [145, ")"], "u" => [147, ")"], "v" => [149, ")"], "w" => [101, ")"], "x" => [112, ")"], "y" => [117, ")"], "z" => [120, ")"], "{" => [124, ")"], "|" => [127, ")"], "}" => [144, ")"], "~" => [152, ")"], "" => [11, ")"], "\x80" => [0, "?0"], "\x81" => [0, "?1"], "\x82" => [0, "?2"], "\x83" => [0, "?a"], "\x84" => [0, "?c"], "\x85" => [0, "?e"], "\x86" => [0, "?i"], "\x87" => [0, "?o"], "\x88" => [0, "?s"], "\x89" => [0, "?t"], "\x8a" => [73, "?"], "\x8b" => [88, "?"], "\x8c" => [89, "?"], "\x8d" => [96, "?"], "\x8e" => [97, "?"], "\x8f" => [99, "?"], "\x90" => [106, "?"], "\x91" => [136, "?"], "\x92" => [139, "?"], "\x93" => [141, "?"], "\x94" => [145, "?"], "\x95" => [147, "?"], "\x96" => [149, "?"], "\x97" => [101, "?"], "\x98" => [112, "?"], "\x99" => [117, "?"], "\x9a" => [120, "?"], "\x9b" => [124, "?"], "\x9c" => [127, "?"], "\x9d" => [144, "?"], "\x9e" => [152, "?"], "\x9f" => [11, "?"], "\xa0" => [92, "'"], "\xa1" => [95, "'"], "\xa2" => [137, "'"], "\xa3" => [142, "'"], "\xa4" => [150, "'"], "\xa5" => [74, "'"], "\xa6" => [90, "'"], "\xa7" => [98, "'"], "\xa8" => [107, "'"], "\xa9" => [140, "'"], "\xaa" => [146, "'"], "\xab" => [102, "'"], "\xac" => [113, "'"], "\xad" => [121, "'"], "\xae" => [128, "'"], "\xaf" => [12, "'"], "\xb0" => [92, "+"], "\xb1" => [95, "+"], "\xb2" => [137, "+"], "\xb3" => [142, "+"], "\xb4" => [150, "+"], "\xb5" => [74, "+"], "\xb6" => [90, "+"], "\xb7" => [98, "+"], "\xb8" => [107, "+"], "\xb9" => [140, "+"], "\xba" => [146, "+"], "\xbb" => [102, "+"], "\xbc" => [113, "+"], "\xbd" => [121, "+"], "\xbe" => [128, "+"], "\xbf" => [12, "+"], "\xc0" => [92, "|"], "\xc1" => [95, "|"], "\xc2" => [137, "|"], "\xc3" => [142, "|"], "\xc4" => [150, "|"], "\xc5" => [74, "|"], "\xc6" => [90, "|"], "\xc7" => [98, "|"], "\xc8" => [107, "|"], "\xc9" => [140, "|"], "\xca" => [146, "|"], "\xcb" => [102, "|"], "\xcc" => [113, "|"], "\xcd" => [121, "|"], "\xce" => [128, "|"], "\xcf" => [12, "|"], "\xd0" => [93, "#"], "\xd1" => [138, "#"], "\xd2" => [75, "#"], "\xd3" => [91, "#"], "\xd4" => [108, "#"], "\xd5" => [103, "#"], "\xd6" => [114, "#"], "\xd7" => [14, "#"], "\xd8" => [93, ">"], "\xd9" => [138, ">"], "\xda" => [75, ">"], "\xdb" => [91, ">"], "\xdc" => [108, ">"], "\xdd" => [103, ">"], "\xde" => [114, ">"], "\xdf" => [14, ">"], "\xe0" => [94, "\x00"], "\xe1" => [76, "\x00"], "\xe2" => [104, "\x00"], "\xe3" => [16, "\x00"], "\xe4" => [94, "\$"], "\xe5" => [76, "\$"], "\xe6" => [104, "\$"], "\xe7" => [16, "\$"], "\xe8" => [94, "@"], "\xe9" => [76, "@"], "\xea" => [104, "@"], "\xeb" => [16, "@"], "\xec" => [94, "["], "\xed" => [76, "["], "\xee" => [104, "["], "\xef" => [16, "["], "\xf0" => [94, "]"], "\xf1" => [76, "]"], "\xf2" => [104, "]"], "\xf3" => [16, "]"], "\xf4" => [94, "~"], "\xf5" => [76, "~"], "\xf6" => [104, "~"], "\xf7" => [16, "~"], "\xf8" => [77, "^"], "\xf9" => [18, "^"], "\xfa" => [77, "}"], "\xfb" => [18, "}"], "\xfc" => [0, "<"], "\xfd" => [0, "`"], "\xfe" => [0, "{"], "\xff" => [21, null]], ["\x00" => [77, "X0"], "\x01" => [18, "X0"], "\x02" => [77, "X1"], "\x03" => [18, "X1"], "\x04" => [77, "X2"], "\x05" => [18, "X2"], "\x06" => [77, "Xa"], "\x07" => [18, "Xa"], "\x08" => [77, "Xc"], "\t" => [18, "Xc"], "\n" => [77, "Xe"], "\v" => [18, "Xe"], "\f" => [77, "Xi"], "\r" => [18, "Xi"], "\x0e" => [77, "Xo"], "\x0f" => [18, "Xo"], "\x10" => [77, "Xs"], "\x11" => [18, "Xs"], "\x12" => [77, "Xt"], "\x13" => [18, "Xt"], "\x14" => [0, "X "], "\x15" => [0, "X%"], "\x16" => [0, "X-"], "\x17" => [0, "X."], "\x18" => [0, "X/"], "\x19" => [0, "X3"], "\x1a" => [0, "X4"], "\x1b" => [0, "X5"], "\x1c" => [0, "X6"], "\x1d" => [0, "X7"], "\x1e" => [0, "X8"], "\x1f" => [0, "X9"], " " => [0, "X="], "!" => [0, "XA"], "\"" => [0, "X_"], "#" => [0, "Xb"], "\$" => [0, "Xd"], "%" => [0, "Xf"], "&" => [0, "Xg"], "'" => [0, "Xh"], "(" => [0, "Xl"], ")" => [0, "Xm"], "*" => [0, "Xn"], "+" => [0, "Xp"], "," => [0, "Xr"], "-" => [0, "Xu"], "." => [100, "X"], "/" => [110, "X"], [111, "X"], [115, "X"], [116, "X"], [118, "X"], [119, "X"], [122, "X"], [123, "X"], [125, "X"], [126, "X"], [129, "X"], ":" => [143, "X"], ";" => [148, "X"], "<" => [151, "X"], "=" => [153, "X"], ">" => [83, "X"], "?" => [10, "X"], "@" => [77, "Z0"], "A" => [18, "Z0"], "B" => [77, "Z1"], "C" => [18, "Z1"], "D" => [77, "Z2"], "E" => [18, "Z2"], "F" => [77, "Za"], "G" => [18, "Za"], "H" => [77, "Zc"], "I" => [18, "Zc"], "J" => [77, "Ze"], "K" => [18, "Ze"], "L" => [77, "Zi"], "M" => [18, "Zi"], "N" => [77, "Zo"], "O" => [18, "Zo"], "P" => [77, "Zs"], "Q" => [18, "Zs"], "R" => [77, "Zt"], "S" => [18, "Zt"], "T" => [0, "Z "], "U" => [0, "Z%"], "V" => [0, "Z-"], "W" => [0, "Z."], "X" => [0, "Z/"], "Y" => [0, "Z3"], "Z" => [0, "Z4"], "[" => [0, "Z5"], "\\" => [0, "Z6"], "]" => [0, "Z7"], "^" => [0, "Z8"], "_" => [0, "Z9"], "`" => [0, "Z="], "a" => [0, "ZA"], "b" => [0, "Z_"], "c" => [0, "Zb"], "d" => [0, "Zd"], "e" => [0, "Zf"], "f" => [0, "Zg"], "g" => [0, "Zh"], "h" => [0, "Zl"], "i" => [0, "Zm"], "j" => [0, "Zn"], "k" => [0, "Zp"], "l" => [0, "Zr"], "m" => [0, "Zu"], "n" => [100, "Z"], "o" => [110, "Z"], "p" => [111, "Z"], "q" => [115, "Z"], "r" => [116, "Z"], "s" => [118, "Z"], "t" => [119, "Z"], "u" => [122, "Z"], "v" => [123, "Z"], "w" => [125, "Z"], "x" => [126, "Z"], "y" => [129, "Z"], "z" => [143, "Z"], "{" => [148, "Z"], "|" => [151, "Z"], "}" => [153, "Z"], "~" => [83, "Z"], "" => [10, "Z"], "\x80" => [92, "!"], "\x81" => [95, "!"], "\x82" => [137, "!"], "\x83" => [142, "!"], "\x84" => [150, "!"], "\x85" => [74, "!"], "\x86" => [90, "!"], "\x87" => [98, "!"], "\x88" => [107, "!"], "\x89" => [140, "!"], "\x8a" => [146, "!"], "\x8b" => [102, "!"], "\x8c" => [113, "!"], "\x8d" => [121, "!"], "\x8e" => [128, "!"], "\x8f" => [12, "!"], "\x90" => [92, "\""], "\x91" => [95, "\""], "\x92" => [137, "\""], "\x93" => [142, "\""], "\x94" => [150, "\""], "\x95" => [74, "\""], "\x96" => [90, "\""], "\x97" => [98, "\""], "\x98" => [107, "\""], "\x99" => [140, "\""], "\x9a" => [146, "\""], "\x9b" => [102, "\""], "\x9c" => [113, "\""], "\x9d" => [121, "\""], "\x9e" => [128, "\""], "\x9f" => [12, "\""], "\xa0" => [92, "("], "\xa1" => [95, "("], "\xa2" => [137, "("], "\xa3" => [142, "("], "\xa4" => [150, "("], "\xa5" => [74, "("], "\xa6" => [90, "("], "\xa7" => [98, "("], "\xa8" => [107, "("], "\xa9" => [140, "("], "\xaa" => [146, "("], "\xab" => [102, "("], "\xac" => [113, "("], "\xad" => [121, "("], "\xae" => [128, "("], "\xaf" => [12, "("], "\xb0" => [92, ")"], "\xb1" => [95, ")"], "\xb2" => [137, ")"], "\xb3" => [142, ")"], "\xb4" => [150, ")"], "\xb5" => [74, ")"], "\xb6" => [90, ")"], "\xb7" => [98, ")"], "\xb8" => [107, ")"], "\xb9" => [140, ")"], "\xba" => [146, ")"], "\xbb" => [102, ")"], "\xbc" => [113, ")"], "\xbd" => [121, ")"], "\xbe" => [128, ")"], "\xbf" => [12, ")"], "\xc0" => [92, "?"], "\xc1" => [95, "?"], "\xc2" => [137, "?"], "\xc3" => [142, "?"], "\xc4" => [150, "?"], "\xc5" => [74, "?"], "\xc6" => [90, "?"], "\xc7" => [98, "?"], "\xc8" => [107, "?"], "\xc9" => [140, "?"], "\xca" => [146, "?"], "\xcb" => [102, "?"], "\xcc" => [113, "?"], "\xcd" => [121, "?"], "\xce" => [128, "?"], "\xcf" => [12, "?"], "\xd0" => [93, "'"], "\xd1" => [138, "'"], "\xd2" => [75, "'"], "\xd3" => [91, "'"], "\xd4" => [108, "'"], "\xd5" => [103, "'"], "\xd6" => [114, "'"], "\xd7" => [14, "'"], "\xd8" => [93, "+"], "\xd9" => [138, "+"], "\xda" => [75, "+"], "\xdb" => [91, "+"], "\xdc" => [108, "+"], "\xdd" => [103, "+"], "\xde" => [114, "+"], "\xdf" => [14, "+"], "\xe0" => [93, "|"], "\xe1" => [138, "|"], "\xe2" => [75, "|"], "\xe3" => [91, "|"], "\xe4" => [108, "|"], "\xe5" => [103, "|"], "\xe6" => [114, "|"], "\xe7" => [14, "|"], "\xe8" => [94, "#"], "\xe9" => [76, "#"], "\xea" => [104, "#"], "\xeb" => [16, "#"], "\xec" => [94, ">"], "\xed" => [76, ">"], "\xee" => [104, ">"], "\xef" => [16, ">"], "\xf0" => [77, "\x00"], "\xf1" => [18, "\x00"], "\xf2" => [77, "\$"], "\xf3" => [18, "\$"], "\xf4" => [77, "@"], "\xf5" => [18, "@"], "\xf6" => [77, "["], "\xf7" => [18, "["], "\xf8" => [77, "]"], "\xf9" => [18, "]"], "\xfa" => [77, "~"], "\xfb" => [18, "~"], "\xfc" => [0, "^"], "\xfd" => [0, "}"], "\xfe" => [105, null], "\xff" => [22, null]], ["\x00" => [0, "&0"], "\x01" => [0, "&1"], "\x02" => [0, "&2"], "\x03" => [0, "&a"], "\x04" => [0, "&c"], "\x05" => [0, "&e"], "\x06" => [0, "&i"], "\x07" => [0, "&o"], "\x08" => [0, "&s"], "\t" => [0, "&t"], "\n" => [73, "&"], "\v" => [88, "&"], "\f" => [89, "&"], "\r" => [96, "&"], "\x0e" => [97, "&"], "\x0f" => [99, "&"], "\x10" => [106, "&"], "\x11" => [136, "&"], "\x12" => [139, "&"], "\x13" => [141, "&"], "\x14" => [145, "&"], "\x15" => [147, "&"], "\x16" => [149, "&"], "\x17" => [101, "&"], "\x18" => [112, "&"], "\x19" => [117, "&"], "\x1a" => [120, "&"], "\x1b" => [124, "&"], "\x1c" => [127, "&"], "\x1d" => [144, "&"], "\x1e" => [152, "&"], "\x1f" => [11, "&"], " " => [0, "*0"], "!" => [0, "*1"], "\"" => [0, "*2"], "#" => [0, "*a"], "\$" => [0, "*c"], "%" => [0, "*e"], "&" => [0, "*i"], "'" => [0, "*o"], "(" => [0, "*s"], ")" => [0, "*t"], "*" => [73, "*"], "+" => [88, "*"], "," => [89, "*"], "-" => [96, "*"], "." => [97, "*"], "/" => [99, "*"], [106, "*"], [136, "*"], [139, "*"], [141, "*"], [145, "*"], [147, "*"], [149, "*"], [101, "*"], [112, "*"], [117, "*"], ":" => [120, "*"], ";" => [124, "*"], "<" => [127, "*"], "=" => [144, "*"], ">" => [152, "*"], "?" => [11, "*"], "@" => [0, ",0"], "A" => [0, ",1"], "B" => [0, ",2"], "C" => [0, ",a"], "D" => [0, ",c"], "E" => [0, ",e"], "F" => [0, ",i"], "G" => [0, ",o"], "H" => [0, ",s"], "I" => [0, ",t"], "J" => [73, ","], "K" => [88, ","], "L" => [89, ","], "M" => [96, ","], "N" => [97, ","], "O" => [99, ","], "P" => [106, ","], "Q" => [136, ","], "R" => [139, ","], "S" => [141, ","], "T" => [145, ","], "U" => [147, ","], "V" => [149, ","], "W" => [101, ","], "X" => [112, ","], "Y" => [117, ","], "Z" => [120, ","], "[" => [124, ","], "\\" => [127, ","], "]" => [144, ","], "^" => [152, ","], "_" => [11, ","], "`" => [0, ";0"], "a" => [0, ";1"], "b" => [0, ";2"], "c" => [0, ";a"], "d" => [0, ";c"], "e" => [0, ";e"], "f" => [0, ";i"], "g" => [0, ";o"], "h" => [0, ";s"], "i" => [0, ";t"], "j" => [73, ";"], "k" => [88, ";"], "l" => [89, ";"], "m" => [96, ";"], "n" => [97, ";"], "o" => [99, ";"], "p" => [106, ";"], "q" => [136, ";"], "r" => [139, ";"], "s" => [141, ";"], "t" => [145, ";"], "u" => [147, ";"], "v" => [149, ";"], "w" => [101, ";"], "x" => [112, ";"], "y" => [117, ";"], "z" => [120, ";"], "{" => [124, ";"], "|" => [127, ";"], "}" => [144, ";"], "~" => [152, ";"], "" => [11, ";"], "\x80" => [0, "X0"], "\x81" => [0, "X1"], "\x82" => [0, "X2"], "\x83" => [0, "Xa"], "\x84" => [0, "Xc"], "\x85" => [0, "Xe"], "\x86" => [0, "Xi"], "\x87" => [0, "Xo"], "\x88" => [0, "Xs"], "\x89" => [0, "Xt"], "\x8a" => [73, "X"], "\x8b" => [88, "X"], "\x8c" => [89, "X"], "\x8d" => [96, "X"], "\x8e" => [97, "X"], "\x8f" => [99, "X"], "\x90" => [106, "X"], "\x91" => [136, "X"], "\x92" => [139, "X"], "\x93" => [141, "X"], "\x94" => [145, "X"], "\x95" => [147, "X"], "\x96" => [149, "X"], "\x97" => [101, "X"], "\x98" => [112, "X"], "\x99" => [117, "X"], "\x9a" => [120, "X"], "\x9b" => [124, "X"], "\x9c" => [127, "X"], "\x9d" => [144, "X"], "\x9e" => [152, "X"], "\x9f" => [11, "X"], "\xa0" => [0, "Z0"], "\xa1" => [0, "Z1"], "\xa2" => [0, "Z2"], "\xa3" => [0, "Za"], "\xa4" => [0, "Zc"], "\xa5" => [0, "Ze"], "\xa6" => [0, "Zi"], "\xa7" => [0, "Zo"], "\xa8" => [0, "Zs"], "\xa9" => [0, "Zt"], "\xaa" => [73, "Z"], "\xab" => [88, "Z"], "\xac" => [89, "Z"], "\xad" => [96, "Z"], "\xae" => [97, "Z"], "\xaf" => [99, "Z"], "\xb0" => [106, "Z"], "\xb1" => [136, "Z"], "\xb2" => [139, "Z"], "\xb3" => [141, "Z"], "\xb4" => [145, "Z"], "\xb5" => [147, "Z"], "\xb6" => [149, "Z"], "\xb7" => [101, "Z"], "\xb8" => [112, "Z"], "\xb9" => [117, "Z"], "\xba" => [120, "Z"], "\xbb" => [124, "Z"], "\xbc" => [127, "Z"], "\xbd" => [144, "Z"], "\xbe" => [152, "Z"], "\xbf" => [11, "Z"], "\xc0" => [93, "!"], "\xc1" => [138, "!"], "\xc2" => [75, "!"], "\xc3" => [91, "!"], "\xc4" => [108, "!"], "\xc5" => [103, "!"], "\xc6" => [114, "!"], "\xc7" => [14, "!"], "\xc8" => [93, "\""], "\xc9" => [138, "\""], "\xca" => [75, "\""], "\xcb" => [91, "\""], "\xcc" => [108, "\""], "\xcd" => [103, "\""], "\xce" => [114, "\""], "\xcf" => [14, "\""], "\xd0" => [93, "("], "\xd1" => [138, "("], "\xd2" => [75, "("], "\xd3" => [91, "("], "\xd4" => [108, "("], "\xd5" => [103, "("], "\xd6" => [114, "("], "\xd7" => [14, "("], "\xd8" => [93, ")"], "\xd9" => [138, ")"], "\xda" => [75, ")"], "\xdb" => [91, ")"], "\xdc" => [108, ")"], "\xdd" => [103, ")"], "\xde" => [114, ")"], "\xdf" => [14, ")"], "\xe0" => [93, "?"], "\xe1" => [138, "?"], "\xe2" => [75, "?"], "\xe3" => [91, "?"], "\xe4" => [108, "?"], "\xe5" => [103, "?"], "\xe6" => [114, "?"], "\xe7" => [14, "?"], "\xe8" => [94, "'"], "\xe9" => [76, "'"], "\xea" => [104, "'"], "\xeb" => [16, "'"], "\xec" => [94, "+"], "\xed" => [76, "+"], "\xee" => [104, "+"], "\xef" => [16, "+"], "\xf0" => [94, "|"], "\xf1" => [76, "|"], "\xf2" => [104, "|"], "\xf3" => [16, "|"], "\xf4" => [77, "#"], "\xf5" => [18, "#"], "\xf6" => [77, ">"], "\xf7" => [18, ">"], "\xf8" => [0, "\x00"], "\xf9" => [0, "\$"], "\xfa" => [0, "@"], "\xfb" => [0, "["], "\xfc" => [0, "]"], "\xfd" => [0, "~"], "\xfe" => [135, null], "\xff" => [24, null]], ["\x00" => [0, "w0"], "\x01" => [0, "w1"], "\x02" => [0, "w2"], "\x03" => [0, "wa"], "\x04" => [0, "wc"], "\x05" => [0, "we"], "\x06" => [0, "wi"], "\x07" => [0, "wo"], "\x08" => [0, "ws"], "\t" => [0, "wt"], "\n" => [73, "w"], "\v" => [88, "w"], "\f" => [89, "w"], "\r" => [96, "w"], "\x0e" => [97, "w"], "\x0f" => [99, "w"], "\x10" => [106, "w"], "\x11" => [136, "w"], "\x12" => [139, "w"], "\x13" => [141, "w"], "\x14" => [145, "w"], "\x15" => [147, "w"], "\x16" => [149, "w"], "\x17" => [101, "w"], "\x18" => [112, "w"], "\x19" => [117, "w"], "\x1a" => [120, "w"], "\x1b" => [124, "w"], "\x1c" => [127, "w"], "\x1d" => [144, "w"], "\x1e" => [152, "w"], "\x1f" => [11, "w"], " " => [0, "x0"], "!" => [0, "x1"], "\"" => [0, "x2"], "#" => [0, "xa"], "\$" => [0, "xc"], "%" => [0, "xe"], "&" => [0, "xi"], "'" => [0, "xo"], "(" => [0, "xs"], ")" => [0, "xt"], "*" => [73, "x"], "+" => [88, "x"], "," => [89, "x"], "-" => [96, "x"], "." => [97, "x"], "/" => [99, "x"], [106, "x"], [136, "x"], [139, "x"], [141, "x"], [145, "x"], [147, "x"], [149, "x"], [101, "x"], [112, "x"], [117, "x"], ":" => [120, "x"], ";" => [124, "x"], "<" => [127, "x"], "=" => [144, "x"], ">" => [152, "x"], "?" => [11, "x"], "@" => [0, "y0"], "A" => [0, "y1"], "B" => [0, "y2"], "C" => [0, "ya"], "D" => [0, "yc"], "E" => [0, "ye"], "F" => [0, "yi"], "G" => [0, "yo"], "H" => [0, "ys"], "I" => [0, "yt"], "J" => [73, "y"], "K" => [88, "y"], "L" => [89, "y"], "M" => [96, "y"], "N" => [97, "y"], "O" => [99, "y"], "P" => [106, "y"], "Q" => [136, "y"], "R" => [139, "y"], "S" => [141, "y"], "T" => [145, "y"], "U" => [147, "y"], "V" => [149, "y"], "W" => [101, "y"], "X" => [112, "y"], "Y" => [117, "y"], "Z" => [120, "y"], "[" => [124, "y"], "\\" => [127, "y"], "]" => [144, "y"], "^" => [152, "y"], "_" => [11, "y"], "`" => [0, "z0"], "a" => [0, "z1"], "b" => [0, "z2"], "c" => [0, "za"], "d" => [0, "zc"], "e" => [0, "ze"], "f" => [0, "zi"], "g" => [0, "zo"], "h" => [0, "zs"], "i" => [0, "zt"], "j" => [73, "z"], "k" => [88, "z"], "l" => [89, "z"], "m" => [96, "z"], "n" => [97, "z"], "o" => [99, "z"], "p" => [106, "z"], "q" => [136, "z"], "r" => [139, "z"], "s" => [141, "z"], "t" => [145, "z"], "u" => [147, "z"], "v" => [149, "z"], "w" => [101, "z"], "x" => [112, "z"], "y" => [117, "z"], "z" => [120, "z"], "{" => [124, "z"], "|" => [127, "z"], "}" => [144, "z"], "~" => [152, "z"], "" => [11, "z"], "\x80" => [92, "&"], "\x81" => [95, "&"], "\x82" => [137, "&"], "\x83" => [142, "&"], "\x84" => [150, "&"], "\x85" => [74, "&"], "\x86" => [90, "&"], "\x87" => [98, "&"], "\x88" => [107, "&"], "\x89" => [140, "&"], "\x8a" => [146, "&"], "\x8b" => [102, "&"], "\x8c" => [113, "&"], "\x8d" => [121, "&"], "\x8e" => [128, "&"], "\x8f" => [12, "&"], "\x90" => [92, "*"], "\x91" => [95, "*"], "\x92" => [137, "*"], "\x93" => [142, "*"], "\x94" => [150, "*"], "\x95" => [74, "*"], "\x96" => [90, "*"], "\x97" => [98, "*"], "\x98" => [107, "*"], "\x99" => [140, "*"], "\x9a" => [146, "*"], "\x9b" => [102, "*"], "\x9c" => [113, "*"], "\x9d" => [121, "*"], "\x9e" => [128, "*"], "\x9f" => [12, "*"], "\xa0" => [92, ","], "\xa1" => [95, ","], "\xa2" => [137, ","], "\xa3" => [142, ","], "\xa4" => [150, ","], "\xa5" => [74, ","], "\xa6" => [90, ","], "\xa7" => [98, ","], "\xa8" => [107, ","], "\xa9" => [140, ","], "\xaa" => [146, ","], "\xab" => [102, ","], "\xac" => [113, ","], "\xad" => [121, ","], "\xae" => [128, ","], "\xaf" => [12, ","], "\xb0" => [92, ";"], "\xb1" => [95, ";"], "\xb2" => [137, ";"], "\xb3" => [142, ";"], "\xb4" => [150, ";"], "\xb5" => [74, ";"], "\xb6" => [90, ";"], "\xb7" => [98, ";"], "\xb8" => [107, ";"], "\xb9" => [140, ";"], "\xba" => [146, ";"], "\xbb" => [102, ";"], "\xbc" => [113, ";"], "\xbd" => [121, ";"], "\xbe" => [128, ";"], "\xbf" => [12, ";"], "\xc0" => [92, "X"], "\xc1" => [95, "X"], "\xc2" => [137, "X"], "\xc3" => [142, "X"], "\xc4" => [150, "X"], "\xc5" => [74, "X"], "\xc6" => [90, "X"], "\xc7" => [98, "X"], "\xc8" => [107, "X"], "\xc9" => [140, "X"], "\xca" => [146, "X"], "\xcb" => [102, "X"], "\xcc" => [113, "X"], "\xcd" => [121, "X"], "\xce" => [128, "X"], "\xcf" => [12, "X"], "\xd0" => [92, "Z"], "\xd1" => [95, "Z"], "\xd2" => [137, "Z"], "\xd3" => [142, "Z"], "\xd4" => [150, "Z"], "\xd5" => [74, "Z"], "\xd6" => [90, "Z"], "\xd7" => [98, "Z"], "\xd8" => [107, "Z"], "\xd9" => [140, "Z"], "\xda" => [146, "Z"], "\xdb" => [102, "Z"], "\xdc" => [113, "Z"], "\xdd" => [121, "Z"], "\xde" => [128, "Z"], "\xdf" => [12, "Z"], "\xe0" => [94, "!"], "\xe1" => [76, "!"], "\xe2" => [104, "!"], "\xe3" => [16, "!"], "\xe4" => [94, "\""], "\xe5" => [76, "\""], "\xe6" => [104, "\""], "\xe7" => [16, "\""], "\xe8" => [94, "("], "\xe9" => [76, "("], "\xea" => [104, "("], "\xeb" => [16, "("], "\xec" => [94, ")"], "\xed" => [76, ")"], "\xee" => [104, ")"], "\xef" => [16, ")"], "\xf0" => [94, "?"], "\xf1" => [76, "?"], "\xf2" => [104, "?"], "\xf3" => [16, "?"], "\xf4" => [77, "'"], "\xf5" => [18, "'"], "\xf6" => [77, "+"], "\xf7" => [18, "+"], "\xf8" => [77, "|"], "\xf9" => [18, "|"], "\xfa" => [0, "#"], "\xfb" => [0, ">"], "\xfc" => [13, null], "\xfd" => [109, null], "\xfe" => [134, null], "\xff" => [26, null]], ["\x00" => [94, "\x000"], "\x01" => [76, "\x000"], "\x02" => [104, "\x000"], "\x03" => [16, "\x000"], "\x04" => [94, "\x001"], "\x05" => [76, "\x001"], "\x06" => [104, "\x001"], "\x07" => [16, "\x001"], "\x08" => [94, "\x002"], "\t" => [76, "\x002"], "\n" => [104, "\x002"], "\v" => [16, "\x002"], "\f" => [94, "\x00a"], "\r" => [76, "\x00a"], "\x0e" => [104, "\x00a"], "\x0f" => [16, "\x00a"], "\x10" => [94, "\x00c"], "\x11" => [76, "\x00c"], "\x12" => [104, "\x00c"], "\x13" => [16, "\x00c"], "\x14" => [94, "\x00e"], "\x15" => [76, "\x00e"], "\x16" => [104, "\x00e"], "\x17" => [16, "\x00e"], "\x18" => [94, "\x00i"], "\x19" => [76, "\x00i"], "\x1a" => [104, "\x00i"], "\x1b" => [16, "\x00i"], "\x1c" => [94, "\x00o"], "\x1d" => [76, "\x00o"], "\x1e" => [104, "\x00o"], "\x1f" => [16, "\x00o"], " " => [94, "\x00s"], "!" => [76, "\x00s"], "\"" => [104, "\x00s"], "#" => [16, "\x00s"], "\$" => [94, "\x00t"], "%" => [76, "\x00t"], "&" => [104, "\x00t"], "'" => [16, "\x00t"], "(" => [77, "\x00 "], ")" => [18, "\x00 "], "*" => [77, "\x00%"], "+" => [18, "\x00%"], "," => [77, "\x00-"], "-" => [18, "\x00-"], "." => [77, "\x00."], "/" => [18, "\x00."], [77, "\x00/"], [18, "\x00/"], [77, "\x003"], [18, "\x003"], [77, "\x004"], [18, "\x004"], [77, "\x005"], [18, "\x005"], [77, "\x006"], [18, "\x006"], ":" => [77, "\x007"], ";" => [18, "\x007"], "<" => [77, "\x008"], "=" => [18, "\x008"], ">" => [77, "\x009"], "?" => [18, "\x009"], "@" => [77, "\x00="], "A" => [18, "\x00="], "B" => [77, "\x00A"], "C" => [18, "\x00A"], "D" => [77, "\x00_"], "E" => [18, "\x00_"], "F" => [77, "\x00b"], "G" => [18, "\x00b"], "H" => [77, "\x00d"], "I" => [18, "\x00d"], "J" => [77, "\x00f"], "K" => [18, "\x00f"], "L" => [77, "\x00g"], "M" => [18, "\x00g"], "N" => [77, "\x00h"], "O" => [18, "\x00h"], "P" => [77, "\x00l"], "Q" => [18, "\x00l"], "R" => [77, "\x00m"], "S" => [18, "\x00m"], "T" => [77, "\x00n"], "U" => [18, "\x00n"], "V" => [77, "\x00p"], "W" => [18, "\x00p"], "X" => [77, "\x00r"], "Y" => [18, "\x00r"], "Z" => [77, "\x00u"], "[" => [18, "\x00u"], "\\" => [0, "\x00:"], "]" => [0, "\x00B"], "^" => [0, "\x00C"], "_" => [0, "\x00D"], "`" => [0, "\x00E"], "a" => [0, "\x00F"], "b" => [0, "\x00G"], "c" => [0, "\x00H"], "d" => [0, "\x00I"], "e" => [0, "\x00J"], "f" => [0, "\x00K"], "g" => [0, "\x00L"], "h" => [0, "\x00M"], "i" => [0, "\x00N"], "j" => [0, "\x00O"], "k" => [0, "\x00P"], "l" => [0, "\x00Q"], "m" => [0, "\x00R"], "n" => [0, "\x00S"], "o" => [0, "\x00T"], "p" => [0, "\x00U"], "q" => [0, "\x00V"], "r" => [0, "\x00W"], "s" => [0, "\x00Y"], "t" => [0, "\x00j"], "u" => [0, "\x00k"], "v" => [0, "\x00q"], "w" => [0, "\x00v"], "x" => [0, "\x00w"], "y" => [0, "\x00x"], "z" => [0, "\x00y"], "{" => [0, "\x00z"], "|" => [82, "\x00"], "}" => [87, "\x00"], "~" => [130, "\x00"], "" => [9, "\x00"], "\x80" => [94, "\$0"], "\x81" => [76, "\$0"], "\x82" => [104, "\$0"], "\x83" => [16, "\$0"], "\x84" => [94, "\$1"], "\x85" => [76, "\$1"], "\x86" => [104, "\$1"], "\x87" => [16, "\$1"], "\x88" => [94, "\$2"], "\x89" => [76, "\$2"], "\x8a" => [104, "\$2"], "\x8b" => [16, "\$2"], "\x8c" => [94, "\$a"], "\x8d" => [76, "\$a"], "\x8e" => [104, "\$a"], "\x8f" => [16, "\$a"], "\x90" => [94, "\$c"], "\x91" => [76, "\$c"], "\x92" => [104, "\$c"], "\x93" => [16, "\$c"], "\x94" => [94, "\$e"], "\x95" => [76, "\$e"], "\x96" => [104, "\$e"], "\x97" => [16, "\$e"], "\x98" => [94, "\$i"], "\x99" => [76, "\$i"], "\x9a" => [104, "\$i"], "\x9b" => [16, "\$i"], "\x9c" => [94, "\$o"], "\x9d" => [76, "\$o"], "\x9e" => [104, "\$o"], "\x9f" => [16, "\$o"], "\xa0" => [94, "\$s"], "\xa1" => [76, "\$s"], "\xa2" => [104, "\$s"], "\xa3" => [16, "\$s"], "\xa4" => [94, "\$t"], "\xa5" => [76, "\$t"], "\xa6" => [104, "\$t"], "\xa7" => [16, "\$t"], "\xa8" => [77, "\$ "], "\xa9" => [18, "\$ "], "\xaa" => [77, "\$%"], "\xab" => [18, "\$%"], "\xac" => [77, "\$-"], "\xad" => [18, "\$-"], "\xae" => [77, "\$."], "\xaf" => [18, "\$."], "\xb0" => [77, "\$/"], "\xb1" => [18, "\$/"], "\xb2" => [77, "\$3"], "\xb3" => [18, "\$3"], "\xb4" => [77, "\$4"], "\xb5" => [18, "\$4"], "\xb6" => [77, "\$5"], "\xb7" => [18, "\$5"], "\xb8" => [77, "\$6"], "\xb9" => [18, "\$6"], "\xba" => [77, "\$7"], "\xbb" => [18, "\$7"], "\xbc" => [77, "\$8"], "\xbd" => [18, "\$8"], "\xbe" => [77, "\$9"], "\xbf" => [18, "\$9"], "\xc0" => [77, "\$="], "\xc1" => [18, "\$="], "\xc2" => [77, "\$A"], "\xc3" => [18, "\$A"], "\xc4" => [77, "\$_"], "\xc5" => [18, "\$_"], "\xc6" => [77, "\$b"], "\xc7" => [18, "\$b"], "\xc8" => [77, "\$d"], "\xc9" => [18, "\$d"], "\xca" => [77, "\$f"], "\xcb" => [18, "\$f"], "\xcc" => [77, "\$g"], "\xcd" => [18, "\$g"], "\xce" => [77, "\$h"], "\xcf" => [18, "\$h"], "\xd0" => [77, "\$l"], "\xd1" => [18, "\$l"], "\xd2" => [77, "\$m"], "\xd3" => [18, "\$m"], "\xd4" => [77, "\$n"], "\xd5" => [18, "\$n"], "\xd6" => [77, "\$p"], "\xd7" => [18, "\$p"], "\xd8" => [77, "\$r"], "\xd9" => [18, "\$r"], "\xda" => [77, "\$u"], "\xdb" => [18, "\$u"], "\xdc" => [0, "\$:"], "\xdd" => [0, "\$B"], "\xde" => [0, "\$C"], "\xdf" => [0, "\$D"], "\xe0" => [0, "\$E"], "\xe1" => [0, "\$F"], "\xe2" => [0, "\$G"], "\xe3" => [0, "\$H"], "\xe4" => [0, "\$I"], "\xe5" => [0, "\$J"], "\xe6" => [0, "\$K"], "\xe7" => [0, "\$L"], "\xe8" => [0, "\$M"], "\xe9" => [0, "\$N"], "\xea" => [0, "\$O"], "\xeb" => [0, "\$P"], "\xec" => [0, "\$Q"], "\xed" => [0, "\$R"], "\xee" => [0, "\$S"], "\xef" => [0, "\$T"], "\xf0" => [0, "\$U"], "\xf1" => [0, "\$V"], "\xf2" => [0, "\$W"], "\xf3" => [0, "\$Y"], "\xf4" => [0, "\$j"], "\xf5" => [0, "\$k"], "\xf6" => [0, "\$q"], "\xf7" => [0, "\$v"], "\xf8" => [0, "\$w"], "\xf9" => [0, "\$x"], "\xfa" => [0, "\$y"], "\xfb" => [0, "\$z"], "\xfc" => [82, "\$"], "\xfd" => [87, "\$"], "\xfe" => [130, "\$"], "\xff" => [9, "\$"]], ["\x00" => [92, "U"], "\x01" => [95, "U"], "\x02" => [137, "U"], "\x03" => [142, "U"], "\x04" => [150, "U"], "\x05" => [74, "U"], "\x06" => [90, "U"], "\x07" => [98, "U"], "\x08" => [107, "U"], "\t" => [140, "U"], "\n" => [146, "U"], "\v" => [102, "U"], "\f" => [113, "U"], "\r" => [121, "U"], "\x0e" => [128, "U"], "\x0f" => [12, "U"], "\x10" => [92, "V"], "\x11" => [95, "V"], "\x12" => [137, "V"], "\x13" => [142, "V"], "\x14" => [150, "V"], "\x15" => [74, "V"], "\x16" => [90, "V"], "\x17" => [98, "V"], "\x18" => [107, "V"], "\x19" => [140, "V"], "\x1a" => [146, "V"], "\x1b" => [102, "V"], "\x1c" => [113, "V"], "\x1d" => [121, "V"], "\x1e" => [128, "V"], "\x1f" => [12, "V"], " " => [92, "W"], "!" => [95, "W"], "\"" => [137, "W"], "#" => [142, "W"], "\$" => [150, "W"], "%" => [74, "W"], "&" => [90, "W"], "'" => [98, "W"], "(" => [107, "W"], ")" => [140, "W"], "*" => [146, "W"], "+" => [102, "W"], "," => [113, "W"], "-" => [121, "W"], "." => [128, "W"], "/" => [12, "W"], [92, "Y"], [95, "Y"], [137, "Y"], [142, "Y"], [150, "Y"], [74, "Y"], [90, "Y"], [98, "Y"], [107, "Y"], [140, "Y"], ":" => [146, "Y"], ";" => [102, "Y"], "<" => [113, "Y"], "=" => [121, "Y"], ">" => [128, "Y"], "?" => [12, "Y"], "@" => [92, "j"], "A" => [95, "j"], "B" => [137, "j"], "C" => [142, "j"], "D" => [150, "j"], "E" => [74, "j"], "F" => [90, "j"], "G" => [98, "j"], "H" => [107, "j"], "I" => [140, "j"], "J" => [146, "j"], "K" => [102, "j"], "L" => [113, "j"], "M" => [121, "j"], "N" => [128, "j"], "O" => [12, "j"], "P" => [92, "k"], "Q" => [95, "k"], "R" => [137, "k"], "S" => [142, "k"], "T" => [150, "k"], "U" => [74, "k"], "V" => [90, "k"], "W" => [98, "k"], "X" => [107, "k"], "Y" => [140, "k"], "Z" => [146, "k"], "[" => [102, "k"], "\\" => [113, "k"], "]" => [121, "k"], "^" => [128, "k"], "_" => [12, "k"], "`" => [92, "q"], "a" => [95, "q"], "b" => [137, "q"], "c" => [142, "q"], "d" => [150, "q"], "e" => [74, "q"], "f" => [90, "q"], "g" => [98, "q"], "h" => [107, "q"], "i" => [140, "q"], "j" => [146, "q"], "k" => [102, "q"], "l" => [113, "q"], "m" => [121, "q"], "n" => [128, "q"], "o" => [12, "q"], "p" => [92, "v"], "q" => [95, "v"], "r" => [137, "v"], "s" => [142, "v"], "t" => [150, "v"], "u" => [74, "v"], "v" => [90, "v"], "w" => [98, "v"], "x" => [107, "v"], "y" => [140, "v"], "z" => [146, "v"], "{" => [102, "v"], "|" => [113, "v"], "}" => [121, "v"], "~" => [128, "v"], "" => [12, "v"], "\x80" => [92, "w"], "\x81" => [95, "w"], "\x82" => [137, "w"], "\x83" => [142, "w"], "\x84" => [150, "w"], "\x85" => [74, "w"], "\x86" => [90, "w"], "\x87" => [98, "w"], "\x88" => [107, "w"], "\x89" => [140, "w"], "\x8a" => [146, "w"], "\x8b" => [102, "w"], "\x8c" => [113, "w"], "\x8d" => [121, "w"], "\x8e" => [128, "w"], "\x8f" => [12, "w"], "\x90" => [92, "x"], "\x91" => [95, "x"], "\x92" => [137, "x"], "\x93" => [142, "x"], "\x94" => [150, "x"], "\x95" => [74, "x"], "\x96" => [90, "x"], "\x97" => [98, "x"], "\x98" => [107, "x"], "\x99" => [140, "x"], "\x9a" => [146, "x"], "\x9b" => [102, "x"], "\x9c" => [113, "x"], "\x9d" => [121, "x"], "\x9e" => [128, "x"], "\x9f" => [12, "x"], "\xa0" => [92, "y"], "\xa1" => [95, "y"], "\xa2" => [137, "y"], "\xa3" => [142, "y"], "\xa4" => [150, "y"], "\xa5" => [74, "y"], "\xa6" => [90, "y"], "\xa7" => [98, "y"], "\xa8" => [107, "y"], "\xa9" => [140, "y"], "\xaa" => [146, "y"], "\xab" => [102, "y"], "\xac" => [113, "y"], "\xad" => [121, "y"], "\xae" => [128, "y"], "\xaf" => [12, "y"], "\xb0" => [92, "z"], "\xb1" => [95, "z"], "\xb2" => [137, "z"], "\xb3" => [142, "z"], "\xb4" => [150, "z"], "\xb5" => [74, "z"], "\xb6" => [90, "z"], "\xb7" => [98, "z"], "\xb8" => [107, "z"], "\xb9" => [140, "z"], "\xba" => [146, "z"], "\xbb" => [102, "z"], "\xbc" => [113, "z"], "\xbd" => [121, "z"], "\xbe" => [128, "z"], "\xbf" => [12, "z"], "\xc0" => [93, "&"], "\xc1" => [138, "&"], "\xc2" => [75, "&"], "\xc3" => [91, "&"], "\xc4" => [108, "&"], "\xc5" => [103, "&"], "\xc6" => [114, "&"], "\xc7" => [14, "&"], "\xc8" => [93, "*"], "\xc9" => [138, "*"], "\xca" => [75, "*"], "\xcb" => [91, "*"], "\xcc" => [108, "*"], "\xcd" => [103, "*"], "\xce" => [114, "*"], "\xcf" => [14, "*"], "\xd0" => [93, ","], "\xd1" => [138, ","], "\xd2" => [75, ","], "\xd3" => [91, ","], "\xd4" => [108, ","], "\xd5" => [103, ","], "\xd6" => [114, ","], "\xd7" => [14, ","], "\xd8" => [93, ";"], "\xd9" => [138, ";"], "\xda" => [75, ";"], "\xdb" => [91, ";"], "\xdc" => [108, ";"], "\xdd" => [103, ";"], "\xde" => [114, ";"], "\xdf" => [14, ";"], "\xe0" => [93, "X"], "\xe1" => [138, "X"], "\xe2" => [75, "X"], "\xe3" => [91, "X"], "\xe4" => [108, "X"], "\xe5" => [103, "X"], "\xe6" => [114, "X"], "\xe7" => [14, "X"], "\xe8" => [93, "Z"], "\xe9" => [138, "Z"], "\xea" => [75, "Z"], "\xeb" => [91, "Z"], "\xec" => [108, "Z"], "\xed" => [103, "Z"], "\xee" => [114, "Z"], "\xef" => [14, "Z"], "\xf0" => [77, "!"], "\xf1" => [18, "!"], "\xf2" => [77, "\""], "\xf3" => [18, "\""], "\xf4" => [77, "("], "\xf5" => [18, "("], "\xf6" => [77, ")"], "\xf7" => [18, ")"], "\xf8" => [77, "?"], "\xf9" => [18, "?"], "\xfa" => [0, "'"], "\xfb" => [0, "+"], "\xfc" => [0, "|"], "\xfd" => [80, null], "\xfe" => [15, null], "\xff" => [28, null]], ["\x00" => [77, "\x000"], "\x01" => [18, "\x000"], "\x02" => [77, "\x001"], "\x03" => [18, "\x001"], "\x04" => [77, "\x002"], "\x05" => [18, "\x002"], "\x06" => [77, "\x00a"], "\x07" => [18, "\x00a"], "\x08" => [77, "\x00c"], "\t" => [18, "\x00c"], "\n" => [77, "\x00e"], "\v" => [18, "\x00e"], "\f" => [77, "\x00i"], "\r" => [18, "\x00i"], "\x0e" => [77, "\x00o"], "\x0f" => [18, "\x00o"], "\x10" => [77, "\x00s"], "\x11" => [18, "\x00s"], "\x12" => [77, "\x00t"], "\x13" => [18, "\x00t"], "\x14" => [0, "\x00 "], "\x15" => [0, "\x00%"], "\x16" => [0, "\x00-"], "\x17" => [0, "\x00."], "\x18" => [0, "\x00/"], "\x19" => [0, "\x003"], "\x1a" => [0, "\x004"], "\x1b" => [0, "\x005"], "\x1c" => [0, "\x006"], "\x1d" => [0, "\x007"], "\x1e" => [0, "\x008"], "\x1f" => [0, "\x009"], " " => [0, "\x00="], "!" => [0, "\x00A"], "\"" => [0, "\x00_"], "#" => [0, "\x00b"], "\$" => [0, "\x00d"], "%" => [0, "\x00f"], "&" => [0, "\x00g"], "'" => [0, "\x00h"], "(" => [0, "\x00l"], ")" => [0, "\x00m"], "*" => [0, "\x00n"], "+" => [0, "\x00p"], "," => [0, "\x00r"], "-" => [0, "\x00u"], "." => [100, "\x00"], "/" => [110, "\x00"], [111, "\x00"], [115, "\x00"], [116, "\x00"], [118, "\x00"], [119, "\x00"], [122, "\x00"], [123, "\x00"], [125, "\x00"], [126, "\x00"], [129, "\x00"], ":" => [143, "\x00"], ";" => [148, "\x00"], "<" => [151, "\x00"], "=" => [153, "\x00"], ">" => [83, "\x00"], "?" => [10, "\x00"], "@" => [77, "\$0"], "A" => [18, "\$0"], "B" => [77, "\$1"], "C" => [18, "\$1"], "D" => [77, "\$2"], "E" => [18, "\$2"], "F" => [77, "\$a"], "G" => [18, "\$a"], "H" => [77, "\$c"], "I" => [18, "\$c"], "J" => [77, "\$e"], "K" => [18, "\$e"], "L" => [77, "\$i"], "M" => [18, "\$i"], "N" => [77, "\$o"], "O" => [18, "\$o"], "P" => [77, "\$s"], "Q" => [18, "\$s"], "R" => [77, "\$t"], "S" => [18, "\$t"], "T" => [0, "\$ "], "U" => [0, "\$%"], "V" => [0, "\$-"], "W" => [0, "\$."], "X" => [0, "\$/"], "Y" => [0, "\$3"], "Z" => [0, "\$4"], "[" => [0, "\$5"], "\\" => [0, "\$6"], "]" => [0, "\$7"], "^" => [0, "\$8"], "_" => [0, "\$9"], "`" => [0, "\$="], "a" => [0, "\$A"], "b" => [0, "\$_"], "c" => [0, "\$b"], "d" => [0, "\$d"], "e" => [0, "\$f"], "f" => [0, "\$g"], "g" => [0, "\$h"], "h" => [0, "\$l"], "i" => [0, "\$m"], "j" => [0, "\$n"], "k" => [0, "\$p"], "l" => [0, "\$r"], "m" => [0, "\$u"], "n" => [100, "\$"], "o" => [110, "\$"], "p" => [111, "\$"], "q" => [115, "\$"], "r" => [116, "\$"], "s" => [118, "\$"], "t" => [119, "\$"], "u" => [122, "\$"], "v" => [123, "\$"], "w" => [125, "\$"], "x" => [126, "\$"], "y" => [129, "\$"], "z" => [143, "\$"], "{" => [148, "\$"], "|" => [151, "\$"], "}" => [153, "\$"], "~" => [83, "\$"], "" => [10, "\$"], "\x80" => [77, "@0"], "\x81" => [18, "@0"], "\x82" => [77, "@1"], "\x83" => [18, "@1"], "\x84" => [77, "@2"], "\x85" => [18, "@2"], "\x86" => [77, "@a"], "\x87" => [18, "@a"], "\x88" => [77, "@c"], "\x89" => [18, "@c"], "\x8a" => [77, "@e"], "\x8b" => [18, "@e"], "\x8c" => [77, "@i"], "\x8d" => [18, "@i"], "\x8e" => [77, "@o"], "\x8f" => [18, "@o"], "\x90" => [77, "@s"], "\x91" => [18, "@s"], "\x92" => [77, "@t"], "\x93" => [18, "@t"], "\x94" => [0, "@ "], "\x95" => [0, "@%"], "\x96" => [0, "@-"], "\x97" => [0, "@."], "\x98" => [0, "@/"], "\x99" => [0, "@3"], "\x9a" => [0, "@4"], "\x9b" => [0, "@5"], "\x9c" => [0, "@6"], "\x9d" => [0, "@7"], "\x9e" => [0, "@8"], "\x9f" => [0, "@9"], "\xa0" => [0, "@="], "\xa1" => [0, "@A"], "\xa2" => [0, "@_"], "\xa3" => [0, "@b"], "\xa4" => [0, "@d"], "\xa5" => [0, "@f"], "\xa6" => [0, "@g"], "\xa7" => [0, "@h"], "\xa8" => [0, "@l"], "\xa9" => [0, "@m"], "\xaa" => [0, "@n"], "\xab" => [0, "@p"], "\xac" => [0, "@r"], "\xad" => [0, "@u"], "\xae" => [100, "@"], "\xaf" => [110, "@"], "\xb0" => [111, "@"], "\xb1" => [115, "@"], "\xb2" => [116, "@"], "\xb3" => [118, "@"], "\xb4" => [119, "@"], "\xb5" => [122, "@"], "\xb6" => [123, "@"], "\xb7" => [125, "@"], "\xb8" => [126, "@"], "\xb9" => [129, "@"], "\xba" => [143, "@"], "\xbb" => [148, "@"], "\xbc" => [151, "@"], "\xbd" => [153, "@"], "\xbe" => [83, "@"], "\xbf" => [10, "@"], "\xc0" => [77, "[0"], "\xc1" => [18, "[0"], "\xc2" => [77, "[1"], "\xc3" => [18, "[1"], "\xc4" => [77, "[2"], "\xc5" => [18, "[2"], "\xc6" => [77, "[a"], "\xc7" => [18, "[a"], "\xc8" => [77, "[c"], "\xc9" => [18, "[c"], "\xca" => [77, "[e"], "\xcb" => [18, "[e"], "\xcc" => [77, "[i"], "\xcd" => [18, "[i"], "\xce" => [77, "[o"], "\xcf" => [18, "[o"], "\xd0" => [77, "[s"], "\xd1" => [18, "[s"], "\xd2" => [77, "[t"], "\xd3" => [18, "[t"], "\xd4" => [0, "[ "], "\xd5" => [0, "[%"], "\xd6" => [0, "[-"], "\xd7" => [0, "[."], "\xd8" => [0, "[/"], "\xd9" => [0, "[3"], "\xda" => [0, "[4"], "\xdb" => [0, "[5"], "\xdc" => [0, "[6"], "\xdd" => [0, "[7"], "\xde" => [0, "[8"], "\xdf" => [0, "[9"], "\xe0" => [0, "[="], "\xe1" => [0, "[A"], "\xe2" => [0, "[_"], "\xe3" => [0, "[b"], "\xe4" => [0, "[d"], "\xe5" => [0, "[f"], "\xe6" => [0, "[g"], "\xe7" => [0, "[h"], "\xe8" => [0, "[l"], "\xe9" => [0, "[m"], "\xea" => [0, "[n"], "\xeb" => [0, "[p"], "\xec" => [0, "[r"], "\xed" => [0, "[u"], "\xee" => [100, "["], "\xef" => [110, "["], "\xf0" => [111, "["], "\xf1" => [115, "["], "\xf2" => [116, "["], "\xf3" => [118, "["], "\xf4" => [119, "["], "\xf5" => [122, "["], "\xf6" => [123, "["], "\xf7" => [125, "["], "\xf8" => [126, "["], "\xf9" => [129, "["], "\xfa" => [143, "["], "\xfb" => [148, "["], "\xfc" => [151, "["], "\xfd" => [153, "["], "\xfe" => [83, "["], "\xff" => [10, "["]], ["\x00" => [93, "E"], "\x01" => [138, "E"], "\x02" => [75, "E"], "\x03" => [91, "E"], "\x04" => [108, "E"], "\x05" => [103, "E"], "\x06" => [114, "E"], "\x07" => [14, "E"], "\x08" => [93, "F"], "\t" => [138, "F"], "\n" => [75, "F"], "\v" => [91, "F"], "\f" => [108, "F"], "\r" => [103, "F"], "\x0e" => [114, "F"], "\x0f" => [14, "F"], "\x10" => [93, "G"], "\x11" => [138, "G"], "\x12" => [75, "G"], "\x13" => [91, "G"], "\x14" => [108, "G"], "\x15" => [103, "G"], "\x16" => [114, "G"], "\x17" => [14, "G"], "\x18" => [93, "H"], "\x19" => [138, "H"], "\x1a" => [75, "H"], "\x1b" => [91, "H"], "\x1c" => [108, "H"], "\x1d" => [103, "H"], "\x1e" => [114, "H"], "\x1f" => [14, "H"], " " => [93, "I"], "!" => [138, "I"], "\"" => [75, "I"], "#" => [91, "I"], "\$" => [108, "I"], "%" => [103, "I"], "&" => [114, "I"], "'" => [14, "I"], "(" => [93, "J"], ")" => [138, "J"], "*" => [75, "J"], "+" => [91, "J"], "," => [108, "J"], "-" => [103, "J"], "." => [114, "J"], "/" => [14, "J"], [93, "K"], [138, "K"], [75, "K"], [91, "K"], [108, "K"], [103, "K"], [114, "K"], [14, "K"], [93, "L"], [138, "L"], ":" => [75, "L"], ";" => [91, "L"], "<" => [108, "L"], "=" => [103, "L"], ">" => [114, "L"], "?" => [14, "L"], "@" => [93, "M"], "A" => [138, "M"], "B" => [75, "M"], "C" => [91, "M"], "D" => [108, "M"], "E" => [103, "M"], "F" => [114, "M"], "G" => [14, "M"], "H" => [93, "N"], "I" => [138, "N"], "J" => [75, "N"], "K" => [91, "N"], "L" => [108, "N"], "M" => [103, "N"], "N" => [114, "N"], "O" => [14, "N"], "P" => [93, "O"], "Q" => [138, "O"], "R" => [75, "O"], "S" => [91, "O"], "T" => [108, "O"], "U" => [103, "O"], "V" => [114, "O"], "W" => [14, "O"], "X" => [93, "P"], "Y" => [138, "P"], "Z" => [75, "P"], "[" => [91, "P"], "\\" => [108, "P"], "]" => [103, "P"], "^" => [114, "P"], "_" => [14, "P"], "`" => [93, "Q"], "a" => [138, "Q"], "b" => [75, "Q"], "c" => [91, "Q"], "d" => [108, "Q"], "e" => [103, "Q"], "f" => [114, "Q"], "g" => [14, "Q"], "h" => [93, "R"], "i" => [138, "R"], "j" => [75, "R"], "k" => [91, "R"], "l" => [108, "R"], "m" => [103, "R"], "n" => [114, "R"], "o" => [14, "R"], "p" => [93, "S"], "q" => [138, "S"], "r" => [75, "S"], "s" => [91, "S"], "t" => [108, "S"], "u" => [103, "S"], "v" => [114, "S"], "w" => [14, "S"], "x" => [93, "T"], "y" => [138, "T"], "z" => [75, "T"], "{" => [91, "T"], "|" => [108, "T"], "}" => [103, "T"], "~" => [114, "T"], "" => [14, "T"], "\x80" => [93, "U"], "\x81" => [138, "U"], "\x82" => [75, "U"], "\x83" => [91, "U"], "\x84" => [108, "U"], "\x85" => [103, "U"], "\x86" => [114, "U"], "\x87" => [14, "U"], "\x88" => [93, "V"], "\x89" => [138, "V"], "\x8a" => [75, "V"], "\x8b" => [91, "V"], "\x8c" => [108, "V"], "\x8d" => [103, "V"], "\x8e" => [114, "V"], "\x8f" => [14, "V"], "\x90" => [93, "W"], "\x91" => [138, "W"], "\x92" => [75, "W"], "\x93" => [91, "W"], "\x94" => [108, "W"], "\x95" => [103, "W"], "\x96" => [114, "W"], "\x97" => [14, "W"], "\x98" => [93, "Y"], "\x99" => [138, "Y"], "\x9a" => [75, "Y"], "\x9b" => [91, "Y"], "\x9c" => [108, "Y"], "\x9d" => [103, "Y"], "\x9e" => [114, "Y"], "\x9f" => [14, "Y"], "\xa0" => [93, "j"], "\xa1" => [138, "j"], "\xa2" => [75, "j"], "\xa3" => [91, "j"], "\xa4" => [108, "j"], "\xa5" => [103, "j"], "\xa6" => [114, "j"], "\xa7" => [14, "j"], "\xa8" => [93, "k"], "\xa9" => [138, "k"], "\xaa" => [75, "k"], "\xab" => [91, "k"], "\xac" => [108, "k"], "\xad" => [103, "k"], "\xae" => [114, "k"], "\xaf" => [14, "k"], "\xb0" => [93, "q"], "\xb1" => [138, "q"], "\xb2" => [75, "q"], "\xb3" => [91, "q"], "\xb4" => [108, "q"], "\xb5" => [103, "q"], "\xb6" => [114, "q"], "\xb7" => [14, "q"], "\xb8" => [93, "v"], "\xb9" => [138, "v"], "\xba" => [75, "v"], "\xbb" => [91, "v"], "\xbc" => [108, "v"], "\xbd" => [103, "v"], "\xbe" => [114, "v"], "\xbf" => [14, "v"], "\xc0" => [93, "w"], "\xc1" => [138, "w"], "\xc2" => [75, "w"], "\xc3" => [91, "w"], "\xc4" => [108, "w"], "\xc5" => [103, "w"], "\xc6" => [114, "w"], "\xc7" => [14, "w"], "\xc8" => [93, "x"], "\xc9" => [138, "x"], "\xca" => [75, "x"], "\xcb" => [91, "x"], "\xcc" => [108, "x"], "\xcd" => [103, "x"], "\xce" => [114, "x"], "\xcf" => [14, "x"], "\xd0" => [93, "y"], "\xd1" => [138, "y"], "\xd2" => [75, "y"], "\xd3" => [91, "y"], "\xd4" => [108, "y"], "\xd5" => [103, "y"], "\xd6" => [114, "y"], "\xd7" => [14, "y"], "\xd8" => [93, "z"], "\xd9" => [138, "z"], "\xda" => [75, "z"], "\xdb" => [91, "z"], "\xdc" => [108, "z"], "\xdd" => [103, "z"], "\xde" => [114, "z"], "\xdf" => [14, "z"], "\xe0" => [94, "&"], "\xe1" => [76, "&"], "\xe2" => [104, "&"], "\xe3" => [16, "&"], "\xe4" => [94, "*"], "\xe5" => [76, "*"], "\xe6" => [104, "*"], "\xe7" => [16, "*"], "\xe8" => [94, ","], "\xe9" => [76, ","], "\xea" => [104, ","], "\xeb" => [16, ","], "\xec" => [94, ";"], "\xed" => [76, ";"], "\xee" => [104, ";"], "\xef" => [16, ";"], "\xf0" => [94, "X"], "\xf1" => [76, "X"], "\xf2" => [104, "X"], "\xf3" => [16, "X"], "\xf4" => [94, "Z"], "\xf5" => [76, "Z"], "\xf6" => [104, "Z"], "\xf7" => [16, "Z"], "\xf8" => [0, "!"], "\xf9" => [0, "\""], "\xfa" => [0, "("], "\xfb" => [0, ")"], "\xfc" => [0, "?"], "\xfd" => [84, null], "\xfe" => [81, null], "\xff" => [17, null]], ["\x00" => [0, "\x000"], "\x01" => [0, "\x001"], "\x02" => [0, "\x002"], "\x03" => [0, "\x00a"], "\x04" => [0, "\x00c"], "\x05" => [0, "\x00e"], "\x06" => [0, "\x00i"], "\x07" => [0, "\x00o"], "\x08" => [0, "\x00s"], "\t" => [0, "\x00t"], "\n" => [73, "\x00"], "\v" => [88, "\x00"], "\f" => [89, "\x00"], "\r" => [96, "\x00"], "\x0e" => [97, "\x00"], "\x0f" => [99, "\x00"], "\x10" => [106, "\x00"], "\x11" => [136, "\x00"], "\x12" => [139, "\x00"], "\x13" => [141, "\x00"], "\x14" => [145, "\x00"], "\x15" => [147, "\x00"], "\x16" => [149, "\x00"], "\x17" => [101, "\x00"], "\x18" => [112, "\x00"], "\x19" => [117, "\x00"], "\x1a" => [120, "\x00"], "\x1b" => [124, "\x00"], "\x1c" => [127, "\x00"], "\x1d" => [144, "\x00"], "\x1e" => [152, "\x00"], "\x1f" => [11, "\x00"], " " => [0, "\$0"], "!" => [0, "\$1"], "\"" => [0, "\$2"], "#" => [0, "\$a"], "\$" => [0, "\$c"], "%" => [0, "\$e"], "&" => [0, "\$i"], "'" => [0, "\$o"], "(" => [0, "\$s"], ")" => [0, "\$t"], "*" => [73, "\$"], "+" => [88, "\$"], "," => [89, "\$"], "-" => [96, "\$"], "." => [97, "\$"], "/" => [99, "\$"], [106, "\$"], [136, "\$"], [139, "\$"], [141, "\$"], [145, "\$"], [147, "\$"], [149, "\$"], [101, "\$"], [112, "\$"], [117, "\$"], ":" => [120, "\$"], ";" => [124, "\$"], "<" => [127, "\$"], "=" => [144, "\$"], ">" => [152, "\$"], "?" => [11, "\$"], "@" => [0, "@0"], "A" => [0, "@1"], "B" => [0, "@2"], "C" => [0, "@a"], "D" => [0, "@c"], "E" => [0, "@e"], "F" => [0, "@i"], "G" => [0, "@o"], "H" => [0, "@s"], "I" => [0, "@t"], "J" => [73, "@"], "K" => [88, "@"], "L" => [89, "@"], "M" => [96, "@"], "N" => [97, "@"], "O" => [99, "@"], "P" => [106, "@"], "Q" => [136, "@"], "R" => [139, "@"], "S" => [141, "@"], "T" => [145, "@"], "U" => [147, "@"], "V" => [149, "@"], "W" => [101, "@"], "X" => [112, "@"], "Y" => [117, "@"], "Z" => [120, "@"], "[" => [124, "@"], "\\" => [127, "@"], "]" => [144, "@"], "^" => [152, "@"], "_" => [11, "@"], "`" => [0, "[0"], "a" => [0, "[1"], "b" => [0, "[2"], "c" => [0, "[a"], "d" => [0, "[c"], "e" => [0, "[e"], "f" => [0, "[i"], "g" => [0, "[o"], "h" => [0, "[s"], "i" => [0, "[t"], "j" => [73, "["], "k" => [88, "["], "l" => [89, "["], "m" => [96, "["], "n" => [97, "["], "o" => [99, "["], "p" => [106, "["], "q" => [136, "["], "r" => [139, "["], "s" => [141, "["], "t" => [145, "["], "u" => [147, "["], "v" => [149, "["], "w" => [101, "["], "x" => [112, "["], "y" => [117, "["], "z" => [120, "["], "{" => [124, "["], "|" => [127, "["], "}" => [144, "["], "~" => [152, "["], "" => [11, "["], "\x80" => [0, "]0"], "\x81" => [0, "]1"], "\x82" => [0, "]2"], "\x83" => [0, "]a"], "\x84" => [0, "]c"], "\x85" => [0, "]e"], "\x86" => [0, "]i"], "\x87" => [0, "]o"], "\x88" => [0, "]s"], "\x89" => [0, "]t"], "\x8a" => [73, "]"], "\x8b" => [88, "]"], "\x8c" => [89, "]"], "\x8d" => [96, "]"], "\x8e" => [97, "]"], "\x8f" => [99, "]"], "\x90" => [106, "]"], "\x91" => [136, "]"], "\x92" => [139, "]"], "\x93" => [141, "]"], "\x94" => [145, "]"], "\x95" => [147, "]"], "\x96" => [149, "]"], "\x97" => [101, "]"], "\x98" => [112, "]"], "\x99" => [117, "]"], "\x9a" => [120, "]"], "\x9b" => [124, "]"], "\x9c" => [127, "]"], "\x9d" => [144, "]"], "\x9e" => [152, "]"], "\x9f" => [11, "]"], "\xa0" => [0, "~0"], "\xa1" => [0, "~1"], "\xa2" => [0, "~2"], "\xa3" => [0, "~a"], "\xa4" => [0, "~c"], "\xa5" => [0, "~e"], "\xa6" => [0, "~i"], "\xa7" => [0, "~o"], "\xa8" => [0, "~s"], "\xa9" => [0, "~t"], "\xaa" => [73, "~"], "\xab" => [88, "~"], "\xac" => [89, "~"], "\xad" => [96, "~"], "\xae" => [97, "~"], "\xaf" => [99, "~"], "\xb0" => [106, "~"], "\xb1" => [136, "~"], "\xb2" => [139, "~"], "\xb3" => [141, "~"], "\xb4" => [145, "~"], "\xb5" => [147, "~"], "\xb6" => [149, "~"], "\xb7" => [101, "~"], "\xb8" => [112, "~"], "\xb9" => [117, "~"], "\xba" => [120, "~"], "\xbb" => [124, "~"], "\xbc" => [127, "~"], "\xbd" => [144, "~"], "\xbe" => [152, "~"], "\xbf" => [11, "~"], "\xc0" => [92, "^"], "\xc1" => [95, "^"], "\xc2" => [137, "^"], "\xc3" => [142, "^"], "\xc4" => [150, "^"], "\xc5" => [74, "^"], "\xc6" => [90, "^"], "\xc7" => [98, "^"], "\xc8" => [107, "^"], "\xc9" => [140, "^"], "\xca" => [146, "^"], "\xcb" => [102, "^"], "\xcc" => [113, "^"], "\xcd" => [121, "^"], "\xce" => [128, "^"], "\xcf" => [12, "^"], "\xd0" => [92, "}"], "\xd1" => [95, "}"], "\xd2" => [137, "}"], "\xd3" => [142, "}"], "\xd4" => [150, "}"], "\xd5" => [74, "}"], "\xd6" => [90, "}"], "\xd7" => [98, "}"], "\xd8" => [107, "}"], "\xd9" => [140, "}"], "\xda" => [146, "}"], "\xdb" => [102, "}"], "\xdc" => [113, "}"], "\xdd" => [121, "}"], "\xde" => [128, "}"], "\xdf" => [12, "}"], "\xe0" => [93, "<"], "\xe1" => [138, "<"], "\xe2" => [75, "<"], "\xe3" => [91, "<"], "\xe4" => [108, "<"], "\xe5" => [103, "<"], "\xe6" => [114, "<"], "\xe7" => [14, "<"], "\xe8" => [93, "`"], "\xe9" => [138, "`"], "\xea" => [75, "`"], "\xeb" => [91, "`"], "\xec" => [108, "`"], "\xed" => [103, "`"], "\xee" => [114, "`"], "\xef" => [14, "`"], "\xf0" => [93, "{"], "\xf1" => [138, "{"], "\xf2" => [75, "{"], "\xf3" => [91, "{"], "\xf4" => [108, "{"], "\xf5" => [103, "{"], "\xf6" => [114, "{"], "\xf7" => [14, "{"], "\xf8" => [132, null], "\xf9" => [156, null], "\xfa" => [163, null], "\xfb" => [184, null], "\xfc" => [205, null], "\xfd" => [160, null], "\xfe" => [30, null], "\xff" => [39, null]], ["\x00" => [93, "="], "\x01" => [138, "="], "\x02" => [75, "="], "\x03" => [91, "="], "\x04" => [108, "="], "\x05" => [103, "="], "\x06" => [114, "="], "\x07" => [14, "="], "\x08" => [93, "A"], "\t" => [138, "A"], "\n" => [75, "A"], "\v" => [91, "A"], "\f" => [108, "A"], "\r" => [103, "A"], "\x0e" => [114, "A"], "\x0f" => [14, "A"], "\x10" => [93, "_"], "\x11" => [138, "_"], "\x12" => [75, "_"], "\x13" => [91, "_"], "\x14" => [108, "_"], "\x15" => [103, "_"], "\x16" => [114, "_"], "\x17" => [14, "_"], "\x18" => [93, "b"], "\x19" => [138, "b"], "\x1a" => [75, "b"], "\x1b" => [91, "b"], "\x1c" => [108, "b"], "\x1d" => [103, "b"], "\x1e" => [114, "b"], "\x1f" => [14, "b"], " " => [93, "d"], "!" => [138, "d"], "\"" => [75, "d"], "#" => [91, "d"], "\$" => [108, "d"], "%" => [103, "d"], "&" => [114, "d"], "'" => [14, "d"], "(" => [93, "f"], ")" => [138, "f"], "*" => [75, "f"], "+" => [91, "f"], "," => [108, "f"], "-" => [103, "f"], "." => [114, "f"], "/" => [14, "f"], [93, "g"], [138, "g"], [75, "g"], [91, "g"], [108, "g"], [103, "g"], [114, "g"], [14, "g"], [93, "h"], [138, "h"], ":" => [75, "h"], ";" => [91, "h"], "<" => [108, "h"], "=" => [103, "h"], ">" => [114, "h"], "?" => [14, "h"], "@" => [93, "l"], "A" => [138, "l"], "B" => [75, "l"], "C" => [91, "l"], "D" => [108, "l"], "E" => [103, "l"], "F" => [114, "l"], "G" => [14, "l"], "H" => [93, "m"], "I" => [138, "m"], "J" => [75, "m"], "K" => [91, "m"], "L" => [108, "m"], "M" => [103, "m"], "N" => [114, "m"], "O" => [14, "m"], "P" => [93, "n"], "Q" => [138, "n"], "R" => [75, "n"], "S" => [91, "n"], "T" => [108, "n"], "U" => [103, "n"], "V" => [114, "n"], "W" => [14, "n"], "X" => [93, "p"], "Y" => [138, "p"], "Z" => [75, "p"], "[" => [91, "p"], "\\" => [108, "p"], "]" => [103, "p"], "^" => [114, "p"], "_" => [14, "p"], "`" => [93, "r"], "a" => [138, "r"], "b" => [75, "r"], "c" => [91, "r"], "d" => [108, "r"], "e" => [103, "r"], "f" => [114, "r"], "g" => [14, "r"], "h" => [93, "u"], "i" => [138, "u"], "j" => [75, "u"], "k" => [91, "u"], "l" => [108, "u"], "m" => [103, "u"], "n" => [114, "u"], "o" => [14, "u"], "p" => [94, ":"], "q" => [76, ":"], "r" => [104, ":"], "s" => [16, ":"], "t" => [94, "B"], "u" => [76, "B"], "v" => [104, "B"], "w" => [16, "B"], "x" => [94, "C"], "y" => [76, "C"], "z" => [104, "C"], "{" => [16, "C"], "|" => [94, "D"], "}" => [76, "D"], "~" => [104, "D"], "" => [16, "D"], "\x80" => [94, "E"], "\x81" => [76, "E"], "\x82" => [104, "E"], "\x83" => [16, "E"], "\x84" => [94, "F"], "\x85" => [76, "F"], "\x86" => [104, "F"], "\x87" => [16, "F"], "\x88" => [94, "G"], "\x89" => [76, "G"], "\x8a" => [104, "G"], "\x8b" => [16, "G"], "\x8c" => [94, "H"], "\x8d" => [76, "H"], "\x8e" => [104, "H"], "\x8f" => [16, "H"], "\x90" => [94, "I"], "\x91" => [76, "I"], "\x92" => [104, "I"], "\x93" => [16, "I"], "\x94" => [94, "J"], "\x95" => [76, "J"], "\x96" => [104, "J"], "\x97" => [16, "J"], "\x98" => [94, "K"], "\x99" => [76, "K"], "\x9a" => [104, "K"], "\x9b" => [16, "K"], "\x9c" => [94, "L"], "\x9d" => [76, "L"], "\x9e" => [104, "L"], "\x9f" => [16, "L"], "\xa0" => [94, "M"], "\xa1" => [76, "M"], "\xa2" => [104, "M"], "\xa3" => [16, "M"], "\xa4" => [94, "N"], "\xa5" => [76, "N"], "\xa6" => [104, "N"], "\xa7" => [16, "N"], "\xa8" => [94, "O"], "\xa9" => [76, "O"], "\xaa" => [104, "O"], "\xab" => [16, "O"], "\xac" => [94, "P"], "\xad" => [76, "P"], "\xae" => [104, "P"], "\xaf" => [16, "P"], "\xb0" => [94, "Q"], "\xb1" => [76, "Q"], "\xb2" => [104, "Q"], "\xb3" => [16, "Q"], "\xb4" => [94, "R"], "\xb5" => [76, "R"], "\xb6" => [104, "R"], "\xb7" => [16, "R"], "\xb8" => [94, "S"], "\xb9" => [76, "S"], "\xba" => [104, "S"], "\xbb" => [16, "S"], "\xbc" => [94, "T"], "\xbd" => [76, "T"], "\xbe" => [104, "T"], "\xbf" => [16, "T"], "\xc0" => [94, "U"], "\xc1" => [76, "U"], "\xc2" => [104, "U"], "\xc3" => [16, "U"], "\xc4" => [94, "V"], "\xc5" => [76, "V"], "\xc6" => [104, "V"], "\xc7" => [16, "V"], "\xc8" => [94, "W"], "\xc9" => [76, "W"], "\xca" => [104, "W"], "\xcb" => [16, "W"], "\xcc" => [94, "Y"], "\xcd" => [76, "Y"], "\xce" => [104, "Y"], "\xcf" => [16, "Y"], "\xd0" => [94, "j"], "\xd1" => [76, "j"], "\xd2" => [104, "j"], "\xd3" => [16, "j"], "\xd4" => [94, "k"], "\xd5" => [76, "k"], "\xd6" => [104, "k"], "\xd7" => [16, "k"], "\xd8" => [94, "q"], "\xd9" => [76, "q"], "\xda" => [104, "q"], "\xdb" => [16, "q"], "\xdc" => [94, "v"], "\xdd" => [76, "v"], "\xde" => [104, "v"], "\xdf" => [16, "v"], "\xe0" => [94, "w"], "\xe1" => [76, "w"], "\xe2" => [104, "w"], "\xe3" => [16, "w"], "\xe4" => [94, "x"], "\xe5" => [76, "x"], "\xe6" => [104, "x"], "\xe7" => [16, "x"], "\xe8" => [94, "y"], "\xe9" => [76, "y"], "\xea" => [104, "y"], "\xeb" => [16, "y"], "\xec" => [94, "z"], "\xed" => [76, "z"], "\xee" => [104, "z"], "\xef" => [16, "z"], "\xf0" => [77, "&"], "\xf1" => [18, "&"], "\xf2" => [77, "*"], "\xf3" => [18, "*"], "\xf4" => [77, ","], "\xf5" => [18, ","], "\xf6" => [77, ";"], "\xf7" => [18, ";"], "\xf8" => [77, "X"], "\xf9" => [18, "X"], "\xfa" => [77, "Z"], "\xfb" => [18, "Z"], "\xfc" => [79, null], "\xfd" => [86, null], "\xfe" => [85, null], "\xff" => [19, null]], ["\x00" => [77, "|0"], "\x01" => [18, "|0"], "\x02" => [77, "|1"], "\x03" => [18, "|1"], "\x04" => [77, "|2"], "\x05" => [18, "|2"], "\x06" => [77, "|a"], "\x07" => [18, "|a"], "\x08" => [77, "|c"], "\t" => [18, "|c"], "\n" => [77, "|e"], "\v" => [18, "|e"], "\f" => [77, "|i"], "\r" => [18, "|i"], "\x0e" => [77, "|o"], "\x0f" => [18, "|o"], "\x10" => [77, "|s"], "\x11" => [18, "|s"], "\x12" => [77, "|t"], "\x13" => [18, "|t"], "\x14" => [0, "| "], "\x15" => [0, "|%"], "\x16" => [0, "|-"], "\x17" => [0, "|."], "\x18" => [0, "|/"], "\x19" => [0, "|3"], "\x1a" => [0, "|4"], "\x1b" => [0, "|5"], "\x1c" => [0, "|6"], "\x1d" => [0, "|7"], "\x1e" => [0, "|8"], "\x1f" => [0, "|9"], " " => [0, "|="], "!" => [0, "|A"], "\"" => [0, "|_"], "#" => [0, "|b"], "\$" => [0, "|d"], "%" => [0, "|f"], "&" => [0, "|g"], "'" => [0, "|h"], "(" => [0, "|l"], ")" => [0, "|m"], "*" => [0, "|n"], "+" => [0, "|p"], "," => [0, "|r"], "-" => [0, "|u"], "." => [100, "|"], "/" => [110, "|"], [111, "|"], [115, "|"], [116, "|"], [118, "|"], [119, "|"], [122, "|"], [123, "|"], [125, "|"], [126, "|"], [129, "|"], ":" => [143, "|"], ";" => [148, "|"], "<" => [151, "|"], "=" => [153, "|"], ">" => [83, "|"], "?" => [10, "|"], "@" => [0, "#0"], "A" => [0, "#1"], "B" => [0, "#2"], "C" => [0, "#a"], "D" => [0, "#c"], "E" => [0, "#e"], "F" => [0, "#i"], "G" => [0, "#o"], "H" => [0, "#s"], "I" => [0, "#t"], "J" => [73, "#"], "K" => [88, "#"], "L" => [89, "#"], "M" => [96, "#"], "N" => [97, "#"], "O" => [99, "#"], "P" => [106, "#"], "Q" => [136, "#"], "R" => [139, "#"], "S" => [141, "#"], "T" => [145, "#"], "U" => [147, "#"], "V" => [149, "#"], "W" => [101, "#"], "X" => [112, "#"], "Y" => [117, "#"], "Z" => [120, "#"], "[" => [124, "#"], "\\" => [127, "#"], "]" => [144, "#"], "^" => [152, "#"], "_" => [11, "#"], "`" => [0, ">0"], "a" => [0, ">1"], "b" => [0, ">2"], "c" => [0, ">a"], "d" => [0, ">c"], "e" => [0, ">e"], "f" => [0, ">i"], "g" => [0, ">o"], "h" => [0, ">s"], "i" => [0, ">t"], "j" => [73, ">"], "k" => [88, ">"], "l" => [89, ">"], "m" => [96, ">"], "n" => [97, ">"], "o" => [99, ">"], "p" => [106, ">"], "q" => [136, ">"], "r" => [139, ">"], "s" => [141, ">"], "t" => [145, ">"], "u" => [147, ">"], "v" => [149, ">"], "w" => [101, ">"], "x" => [112, ">"], "y" => [117, ">"], "z" => [120, ">"], "{" => [124, ">"], "|" => [127, ">"], "}" => [144, ">"], "~" => [152, ">"], "" => [11, ">"], "\x80" => [92, "\x00"], "\x81" => [95, "\x00"], "\x82" => [137, "\x00"], "\x83" => [142, "\x00"], "\x84" => [150, "\x00"], "\x85" => [74, "\x00"], "\x86" => [90, "\x00"], "\x87" => [98, "\x00"], "\x88" => [107, "\x00"], "\x89" => [140, "\x00"], "\x8a" => [146, "\x00"], "\x8b" => [102, "\x00"], "\x8c" => [113, "\x00"], "\x8d" => [121, "\x00"], "\x8e" => [128, "\x00"], "\x8f" => [12, "\x00"], "\x90" => [92, "\$"], "\x91" => [95, "\$"], "\x92" => [137, "\$"], "\x93" => [142, "\$"], "\x94" => [150, "\$"], "\x95" => [74, "\$"], "\x96" => [90, "\$"], "\x97" => [98, "\$"], "\x98" => [107, "\$"], "\x99" => [140, "\$"], "\x9a" => [146, "\$"], "\x9b" => [102, "\$"], "\x9c" => [113, "\$"], "\x9d" => [121, "\$"], "\x9e" => [128, "\$"], "\x9f" => [12, "\$"], "\xa0" => [92, "@"], "\xa1" => [95, "@"], "\xa2" => [137, "@"], "\xa3" => [142, "@"], "\xa4" => [150, "@"], "\xa5" => [74, "@"], "\xa6" => [90, "@"], "\xa7" => [98, "@"], "\xa8" => [107, "@"], "\xa9" => [140, "@"], "\xaa" => [146, "@"], "\xab" => [102, "@"], "\xac" => [113, "@"], "\xad" => [121, "@"], "\xae" => [128, "@"], "\xaf" => [12, "@"], "\xb0" => [92, "["], "\xb1" => [95, "["], "\xb2" => [137, "["], "\xb3" => [142, "["], "\xb4" => [150, "["], "\xb5" => [74, "["], "\xb6" => [90, "["], "\xb7" => [98, "["], "\xb8" => [107, "["], "\xb9" => [140, "["], "\xba" => [146, "["], "\xbb" => [102, "["], "\xbc" => [113, "["], "\xbd" => [121, "["], "\xbe" => [128, "["], "\xbf" => [12, "["], "\xc0" => [92, "]"], "\xc1" => [95, "]"], "\xc2" => [137, "]"], "\xc3" => [142, "]"], "\xc4" => [150, "]"], "\xc5" => [74, "]"], "\xc6" => [90, "]"], "\xc7" => [98, "]"], "\xc8" => [107, "]"], "\xc9" => [140, "]"], "\xca" => [146, "]"], "\xcb" => [102, "]"], "\xcc" => [113, "]"], "\xcd" => [121, "]"], "\xce" => [128, "]"], "\xcf" => [12, "]"], "\xd0" => [92, "~"], "\xd1" => [95, "~"], "\xd2" => [137, "~"], "\xd3" => [142, "~"], "\xd4" => [150, "~"], "\xd5" => [74, "~"], "\xd6" => [90, "~"], "\xd7" => [98, "~"], "\xd8" => [107, "~"], "\xd9" => [140, "~"], "\xda" => [146, "~"], "\xdb" => [102, "~"], "\xdc" => [113, "~"], "\xdd" => [121, "~"], "\xde" => [128, "~"], "\xdf" => [12, "~"], "\xe0" => [93, "^"], "\xe1" => [138, "^"], "\xe2" => [75, "^"], "\xe3" => [91, "^"], "\xe4" => [108, "^"], "\xe5" => [103, "^"], "\xe6" => [114, "^"], "\xe7" => [14, "^"], "\xe8" => [93, "}"], "\xe9" => [138, "}"], "\xea" => [75, "}"], "\xeb" => [91, "}"], "\xec" => [108, "}"], "\xed" => [103, "}"], "\xee" => [114, "}"], "\xef" => [14, "}"], "\xf0" => [94, "<"], "\xf1" => [76, "<"], "\xf2" => [104, "<"], "\xf3" => [16, "<"], "\xf4" => [94, "`"], "\xf5" => [76, "`"], "\xf6" => [104, "`"], "\xf7" => [16, "`"], "\xf8" => [94, "{"], "\xf9" => [76, "{"], "\xfa" => [104, "{"], "\xfb" => [16, "{"], "\xfc" => [133, null], "\xfd" => [164, null], "\xfe" => [161, null], "\xff" => [31, null]], ["\x00" => [93, "\xb0"], "\x01" => [138, "\xb0"], "\x02" => [75, "\xb0"], "\x03" => [91, "\xb0"], "\x04" => [108, "\xb0"], "\x05" => [103, "\xb0"], "\x06" => [114, "\xb0"], "\x07" => [14, "\xb0"], "\x08" => [93, "\xb1"], "\t" => [138, "\xb1"], "\n" => [75, "\xb1"], "\v" => [91, "\xb1"], "\f" => [108, "\xb1"], "\r" => [103, "\xb1"], "\x0e" => [114, "\xb1"], "\x0f" => [14, "\xb1"], "\x10" => [93, "\xb3"], "\x11" => [138, "\xb3"], "\x12" => [75, "\xb3"], "\x13" => [91, "\xb3"], "\x14" => [108, "\xb3"], "\x15" => [103, "\xb3"], "\x16" => [114, "\xb3"], "\x17" => [14, "\xb3"], "\x18" => [93, "\xd1"], "\x19" => [138, "\xd1"], "\x1a" => [75, "\xd1"], "\x1b" => [91, "\xd1"], "\x1c" => [108, "\xd1"], "\x1d" => [103, "\xd1"], "\x1e" => [114, "\xd1"], "\x1f" => [14, "\xd1"], " " => [93, "\xd8"], "!" => [138, "\xd8"], "\"" => [75, "\xd8"], "#" => [91, "\xd8"], "\$" => [108, "\xd8"], "%" => [103, "\xd8"], "&" => [114, "\xd8"], "'" => [14, "\xd8"], "(" => [93, "\xd9"], ")" => [138, "\xd9"], "*" => [75, "\xd9"], "+" => [91, "\xd9"], "," => [108, "\xd9"], "-" => [103, "\xd9"], "." => [114, "\xd9"], "/" => [14, "\xd9"], [93, "\xe3"], [138, "\xe3"], [75, "\xe3"], [91, "\xe3"], [108, "\xe3"], [103, "\xe3"], [114, "\xe3"], [14, "\xe3"], [93, "\xe5"], [138, "\xe5"], ":" => [75, "\xe5"], ";" => [91, "\xe5"], "<" => [108, "\xe5"], "=" => [103, "\xe5"], ">" => [114, "\xe5"], "?" => [14, "\xe5"], "@" => [93, "\xe6"], "A" => [138, "\xe6"], "B" => [75, "\xe6"], "C" => [91, "\xe6"], "D" => [108, "\xe6"], "E" => [103, "\xe6"], "F" => [114, "\xe6"], "G" => [14, "\xe6"], "H" => [94, "\x81"], "I" => [76, "\x81"], "J" => [104, "\x81"], "K" => [16, "\x81"], "L" => [94, "\x84"], "M" => [76, "\x84"], "N" => [104, "\x84"], "O" => [16, "\x84"], "P" => [94, "\x85"], "Q" => [76, "\x85"], "R" => [104, "\x85"], "S" => [16, "\x85"], "T" => [94, "\x86"], "U" => [76, "\x86"], "V" => [104, "\x86"], "W" => [16, "\x86"], "X" => [94, "\x88"], "Y" => [76, "\x88"], "Z" => [104, "\x88"], "[" => [16, "\x88"], "\\" => [94, "\x92"], "]" => [76, "\x92"], "^" => [104, "\x92"], "_" => [16, "\x92"], "`" => [94, "\x9a"], "a" => [76, "\x9a"], "b" => [104, "\x9a"], "c" => [16, "\x9a"], "d" => [94, "\x9c"], "e" => [76, "\x9c"], "f" => [104, "\x9c"], "g" => [16, "\x9c"], "h" => [94, "\xa0"], "i" => [76, "\xa0"], "j" => [104, "\xa0"], "k" => [16, "\xa0"], "l" => [94, "\xa3"], "m" => [76, "\xa3"], "n" => [104, "\xa3"], "o" => [16, "\xa3"], "p" => [94, "\xa4"], "q" => [76, "\xa4"], "r" => [104, "\xa4"], "s" => [16, "\xa4"], "t" => [94, "\xa9"], "u" => [76, "\xa9"], "v" => [104, "\xa9"], "w" => [16, "\xa9"], "x" => [94, "\xaa"], "y" => [76, "\xaa"], "z" => [104, "\xaa"], "{" => [16, "\xaa"], "|" => [94, "\xad"], "}" => [76, "\xad"], "~" => [104, "\xad"], "" => [16, "\xad"], "\x80" => [94, "\xb2"], "\x81" => [76, "\xb2"], "\x82" => [104, "\xb2"], "\x83" => [16, "\xb2"], "\x84" => [94, "\xb5"], "\x85" => [76, "\xb5"], "\x86" => [104, "\xb5"], "\x87" => [16, "\xb5"], "\x88" => [94, "\xb9"], "\x89" => [76, "\xb9"], "\x8a" => [104, "\xb9"], "\x8b" => [16, "\xb9"], "\x8c" => [94, "\xba"], "\x8d" => [76, "\xba"], "\x8e" => [104, "\xba"], "\x8f" => [16, "\xba"], "\x90" => [94, "\xbb"], "\x91" => [76, "\xbb"], "\x92" => [104, "\xbb"], "\x93" => [16, "\xbb"], "\x94" => [94, "\xbd"], "\x95" => [76, "\xbd"], "\x96" => [104, "\xbd"], "\x97" => [16, "\xbd"], "\x98" => [94, "\xbe"], "\x99" => [76, "\xbe"], "\x9a" => [104, "\xbe"], "\x9b" => [16, "\xbe"], "\x9c" => [94, "\xc4"], "\x9d" => [76, "\xc4"], "\x9e" => [104, "\xc4"], "\x9f" => [16, "\xc4"], "\xa0" => [94, "\xc6"], "\xa1" => [76, "\xc6"], "\xa2" => [104, "\xc6"], "\xa3" => [16, "\xc6"], "\xa4" => [94, "\xe4"], "\xa5" => [76, "\xe4"], "\xa6" => [104, "\xe4"], "\xa7" => [16, "\xe4"], "\xa8" => [94, "\xe8"], "\xa9" => [76, "\xe8"], "\xaa" => [104, "\xe8"], "\xab" => [16, "\xe8"], "\xac" => [94, "\xe9"], "\xad" => [76, "\xe9"], "\xae" => [104, "\xe9"], "\xaf" => [16, "\xe9"], "\xb0" => [77, "\x01"], "\xb1" => [18, "\x01"], "\xb2" => [77, "\x87"], "\xb3" => [18, "\x87"], "\xb4" => [77, "\x89"], "\xb5" => [18, "\x89"], "\xb6" => [77, "\x8a"], "\xb7" => [18, "\x8a"], "\xb8" => [77, "\x8b"], "\xb9" => [18, "\x8b"], "\xba" => [77, "\x8c"], "\xbb" => [18, "\x8c"], "\xbc" => [77, "\x8d"], "\xbd" => [18, "\x8d"], "\xbe" => [77, "\x8f"], "\xbf" => [18, "\x8f"], "\xc0" => [77, "\x93"], "\xc1" => [18, "\x93"], "\xc2" => [77, "\x95"], "\xc3" => [18, "\x95"], "\xc4" => [77, "\x96"], "\xc5" => [18, "\x96"], "\xc6" => [77, "\x97"], "\xc7" => [18, "\x97"], "\xc8" => [77, "\x98"], "\xc9" => [18, "\x98"], "\xca" => [77, "\x9b"], "\xcb" => [18, "\x9b"], "\xcc" => [77, "\x9d"], "\xcd" => [18, "\x9d"], "\xce" => [77, "\x9e"], "\xcf" => [18, "\x9e"], "\xd0" => [77, "\xa5"], "\xd1" => [18, "\xa5"], "\xd2" => [77, "\xa6"], "\xd3" => [18, "\xa6"], "\xd4" => [77, "\xa8"], "\xd5" => [18, "\xa8"], "\xd6" => [77, "\xae"], "\xd7" => [18, "\xae"], "\xd8" => [77, "\xaf"], "\xd9" => [18, "\xaf"], "\xda" => [77, "\xb4"], "\xdb" => [18, "\xb4"], "\xdc" => [77, "\xb6"], "\xdd" => [18, "\xb6"], "\xde" => [77, "\xb7"], "\xdf" => [18, "\xb7"], "\xe0" => [77, "\xbc"], "\xe1" => [18, "\xbc"], "\xe2" => [77, "\xbf"], "\xe3" => [18, "\xbf"], "\xe4" => [77, "\xc5"], "\xe5" => [18, "\xc5"], "\xe6" => [77, "\xe7"], "\xe7" => [18, "\xe7"], "\xe8" => [77, "\xef"], "\xe9" => [18, "\xef"], "\xea" => [0, "\t"], "\xeb" => [0, "\x8e"], "\xec" => [0, "\x90"], "\xed" => [0, "\x91"], "\xee" => [0, "\x94"], "\xef" => [0, "\x9f"], "\xf0" => [0, "\xab"], "\xf1" => [0, "\xce"], "\xf2" => [0, "\xd7"], "\xf3" => [0, "\xe1"], "\xf4" => [0, "\xec"], "\xf5" => [0, "\xed"], "\xf6" => [225, null], "\xf7" => [251, null], "\xf8" => [218, null], "\xf9" => [229, null], "\xfa" => [244, null], "\xfb" => [231, null], "\xfc" => [236, null], "\xfd" => [256, null], "\xfe" => [32, null], "\xff" => [52, null]], ["\x00" => [92, "\\"], "\x01" => [95, "\\"], "\x02" => [137, "\\"], "\x03" => [142, "\\"], "\x04" => [150, "\\"], "\x05" => [74, "\\"], "\x06" => [90, "\\"], "\x07" => [98, "\\"], "\x08" => [107, "\\"], "\t" => [140, "\\"], "\n" => [146, "\\"], "\v" => [102, "\\"], "\f" => [113, "\\"], "\r" => [121, "\\"], "\x0e" => [128, "\\"], "\x0f" => [12, "\\"], "\x10" => [92, "\xc3"], "\x11" => [95, "\xc3"], "\x12" => [137, "\xc3"], "\x13" => [142, "\xc3"], "\x14" => [150, "\xc3"], "\x15" => [74, "\xc3"], "\x16" => [90, "\xc3"], "\x17" => [98, "\xc3"], "\x18" => [107, "\xc3"], "\x19" => [140, "\xc3"], "\x1a" => [146, "\xc3"], "\x1b" => [102, "\xc3"], "\x1c" => [113, "\xc3"], "\x1d" => [121, "\xc3"], "\x1e" => [128, "\xc3"], "\x1f" => [12, "\xc3"], " " => [92, "\xd0"], "!" => [95, "\xd0"], "\"" => [137, "\xd0"], "#" => [142, "\xd0"], "\$" => [150, "\xd0"], "%" => [74, "\xd0"], "&" => [90, "\xd0"], "'" => [98, "\xd0"], "(" => [107, "\xd0"], ")" => [140, "\xd0"], "*" => [146, "\xd0"], "+" => [102, "\xd0"], "," => [113, "\xd0"], "-" => [121, "\xd0"], "." => [128, "\xd0"], "/" => [12, "\xd0"], [93, "\x80"], [138, "\x80"], [75, "\x80"], [91, "\x80"], [108, "\x80"], [103, "\x80"], [114, "\x80"], [14, "\x80"], [93, "\x82"], [138, "\x82"], ":" => [75, "\x82"], ";" => [91, "\x82"], "<" => [108, "\x82"], "=" => [103, "\x82"], ">" => [114, "\x82"], "?" => [14, "\x82"], "@" => [93, "\x83"], "A" => [138, "\x83"], "B" => [75, "\x83"], "C" => [91, "\x83"], "D" => [108, "\x83"], "E" => [103, "\x83"], "F" => [114, "\x83"], "G" => [14, "\x83"], "H" => [93, "\xa2"], "I" => [138, "\xa2"], "J" => [75, "\xa2"], "K" => [91, "\xa2"], "L" => [108, "\xa2"], "M" => [103, "\xa2"], "N" => [114, "\xa2"], "O" => [14, "\xa2"], "P" => [93, "\xb8"], "Q" => [138, "\xb8"], "R" => [75, "\xb8"], "S" => [91, "\xb8"], "T" => [108, "\xb8"], "U" => [103, "\xb8"], "V" => [114, "\xb8"], "W" => [14, "\xb8"], "X" => [93, "\xc2"], "Y" => [138, "\xc2"], "Z" => [75, "\xc2"], "[" => [91, "\xc2"], "\\" => [108, "\xc2"], "]" => [103, "\xc2"], "^" => [114, "\xc2"], "_" => [14, "\xc2"], "`" => [93, "\xe0"], "a" => [138, "\xe0"], "b" => [75, "\xe0"], "c" => [91, "\xe0"], "d" => [108, "\xe0"], "e" => [103, "\xe0"], "f" => [114, "\xe0"], "g" => [14, "\xe0"], "h" => [93, "\xe2"], "i" => [138, "\xe2"], "j" => [75, "\xe2"], "k" => [91, "\xe2"], "l" => [108, "\xe2"], "m" => [103, "\xe2"], "n" => [114, "\xe2"], "o" => [14, "\xe2"], "p" => [94, "\x99"], "q" => [76, "\x99"], "r" => [104, "\x99"], "s" => [16, "\x99"], "t" => [94, "\xa1"], "u" => [76, "\xa1"], "v" => [104, "\xa1"], "w" => [16, "\xa1"], "x" => [94, "\xa7"], "y" => [76, "\xa7"], "z" => [104, "\xa7"], "{" => [16, "\xa7"], "|" => [94, "\xac"], "}" => [76, "\xac"], "~" => [104, "\xac"], "" => [16, "\xac"], "\x80" => [94, "\xb0"], "\x81" => [76, "\xb0"], "\x82" => [104, "\xb0"], "\x83" => [16, "\xb0"], "\x84" => [94, "\xb1"], "\x85" => [76, "\xb1"], "\x86" => [104, "\xb1"], "\x87" => [16, "\xb1"], "\x88" => [94, "\xb3"], "\x89" => [76, "\xb3"], "\x8a" => [104, "\xb3"], "\x8b" => [16, "\xb3"], "\x8c" => [94, "\xd1"], "\x8d" => [76, "\xd1"], "\x8e" => [104, "\xd1"], "\x8f" => [16, "\xd1"], "\x90" => [94, "\xd8"], "\x91" => [76, "\xd8"], "\x92" => [104, "\xd8"], "\x93" => [16, "\xd8"], "\x94" => [94, "\xd9"], "\x95" => [76, "\xd9"], "\x96" => [104, "\xd9"], "\x97" => [16, "\xd9"], "\x98" => [94, "\xe3"], "\x99" => [76, "\xe3"], "\x9a" => [104, "\xe3"], "\x9b" => [16, "\xe3"], "\x9c" => [94, "\xe5"], "\x9d" => [76, "\xe5"], "\x9e" => [104, "\xe5"], "\x9f" => [16, "\xe5"], "\xa0" => [94, "\xe6"], "\xa1" => [76, "\xe6"], "\xa2" => [104, "\xe6"], "\xa3" => [16, "\xe6"], "\xa4" => [77, "\x81"], "\xa5" => [18, "\x81"], "\xa6" => [77, "\x84"], "\xa7" => [18, "\x84"], "\xa8" => [77, "\x85"], "\xa9" => [18, "\x85"], "\xaa" => [77, "\x86"], "\xab" => [18, "\x86"], "\xac" => [77, "\x88"], "\xad" => [18, "\x88"], "\xae" => [77, "\x92"], "\xaf" => [18, "\x92"], "\xb0" => [77, "\x9a"], "\xb1" => [18, "\x9a"], "\xb2" => [77, "\x9c"], "\xb3" => [18, "\x9c"], "\xb4" => [77, "\xa0"], "\xb5" => [18, "\xa0"], "\xb6" => [77, "\xa3"], "\xb7" => [18, "\xa3"], "\xb8" => [77, "\xa4"], "\xb9" => [18, "\xa4"], "\xba" => [77, "\xa9"], "\xbb" => [18, "\xa9"], "\xbc" => [77, "\xaa"], "\xbd" => [18, "\xaa"], "\xbe" => [77, "\xad"], "\xbf" => [18, "\xad"], "\xc0" => [77, "\xb2"], "\xc1" => [18, "\xb2"], "\xc2" => [77, "\xb5"], "\xc3" => [18, "\xb5"], "\xc4" => [77, "\xb9"], "\xc5" => [18, "\xb9"], "\xc6" => [77, "\xba"], "\xc7" => [18, "\xba"], "\xc8" => [77, "\xbb"], "\xc9" => [18, "\xbb"], "\xca" => [77, "\xbd"], "\xcb" => [18, "\xbd"], "\xcc" => [77, "\xbe"], "\xcd" => [18, "\xbe"], "\xce" => [77, "\xc4"], "\xcf" => [18, "\xc4"], "\xd0" => [77, "\xc6"], "\xd1" => [18, "\xc6"], "\xd2" => [77, "\xe4"], "\xd3" => [18, "\xe4"], "\xd4" => [77, "\xe8"], "\xd5" => [18, "\xe8"], "\xd6" => [77, "\xe9"], "\xd7" => [18, "\xe9"], "\xd8" => [0, "\x01"], "\xd9" => [0, "\x87"], "\xda" => [0, "\x89"], "\xdb" => [0, "\x8a"], "\xdc" => [0, "\x8b"], "\xdd" => [0, "\x8c"], "\xde" => [0, "\x8d"], "\xdf" => [0, "\x8f"], "\xe0" => [0, "\x93"], "\xe1" => [0, "\x95"], "\xe2" => [0, "\x96"], "\xe3" => [0, "\x97"], "\xe4" => [0, "\x98"], "\xe5" => [0, "\x9b"], "\xe6" => [0, "\x9d"], "\xe7" => [0, "\x9e"], "\xe8" => [0, "\xa5"], "\xe9" => [0, "\xa6"], "\xea" => [0, "\xa8"], "\xeb" => [0, "\xae"], "\xec" => [0, "\xaf"], "\xed" => [0, "\xb4"], "\xee" => [0, "\xb6"], "\xef" => [0, "\xb7"], "\xf0" => [0, "\xbc"], "\xf1" => [0, "\xbf"], "\xf2" => [0, "\xc5"], "\xf3" => [0, "\xe7"], "\xf4" => [0, "\xef"], "\xf5" => [48, null], "\xf6" => [172, null], "\xf7" => [178, null], "\xf8" => [198, null], "\xf9" => [241, null], "\xfa" => [252, null], "\xfb" => [226, null], "\xfc" => [219, null], "\xfd" => [232, null], "\xfe" => [237, null], "\xff" => [33, null]], ["\x00" => [94, "{0"], "\x01" => [76, "{0"], "\x02" => [104, "{0"], "\x03" => [16, "{0"], "\x04" => [94, "{1"], "\x05" => [76, "{1"], "\x06" => [104, "{1"], "\x07" => [16, "{1"], "\x08" => [94, "{2"], "\t" => [76, "{2"], "\n" => [104, "{2"], "\v" => [16, "{2"], "\f" => [94, "{a"], "\r" => [76, "{a"], "\x0e" => [104, "{a"], "\x0f" => [16, "{a"], "\x10" => [94, "{c"], "\x11" => [76, "{c"], "\x12" => [104, "{c"], "\x13" => [16, "{c"], "\x14" => [94, "{e"], "\x15" => [76, "{e"], "\x16" => [104, "{e"], "\x17" => [16, "{e"], "\x18" => [94, "{i"], "\x19" => [76, "{i"], "\x1a" => [104, "{i"], "\x1b" => [16, "{i"], "\x1c" => [94, "{o"], "\x1d" => [76, "{o"], "\x1e" => [104, "{o"], "\x1f" => [16, "{o"], " " => [94, "{s"], "!" => [76, "{s"], "\"" => [104, "{s"], "#" => [16, "{s"], "\$" => [94, "{t"], "%" => [76, "{t"], "&" => [104, "{t"], "'" => [16, "{t"], "(" => [77, "{ "], ")" => [18, "{ "], "*" => [77, "{%"], "+" => [18, "{%"], "," => [77, "{-"], "-" => [18, "{-"], "." => [77, "{."], "/" => [18, "{."], [77, "{/"], [18, "{/"], [77, "{3"], [18, "{3"], [77, "{4"], [18, "{4"], [77, "{5"], [18, "{5"], [77, "{6"], [18, "{6"], ":" => [77, "{7"], ";" => [18, "{7"], "<" => [77, "{8"], "=" => [18, "{8"], ">" => [77, "{9"], "?" => [18, "{9"], "@" => [77, "{="], "A" => [18, "{="], "B" => [77, "{A"], "C" => [18, "{A"], "D" => [77, "{_"], "E" => [18, "{_"], "F" => [77, "{b"], "G" => [18, "{b"], "H" => [77, "{d"], "I" => [18, "{d"], "J" => [77, "{f"], "K" => [18, "{f"], "L" => [77, "{g"], "M" => [18, "{g"], "N" => [77, "{h"], "O" => [18, "{h"], "P" => [77, "{l"], "Q" => [18, "{l"], "R" => [77, "{m"], "S" => [18, "{m"], "T" => [77, "{n"], "U" => [18, "{n"], "V" => [77, "{p"], "W" => [18, "{p"], "X" => [77, "{r"], "Y" => [18, "{r"], "Z" => [77, "{u"], "[" => [18, "{u"], "\\" => [0, "{:"], "]" => [0, "{B"], "^" => [0, "{C"], "_" => [0, "{D"], "`" => [0, "{E"], "a" => [0, "{F"], "b" => [0, "{G"], "c" => [0, "{H"], "d" => [0, "{I"], "e" => [0, "{J"], "f" => [0, "{K"], "g" => [0, "{L"], "h" => [0, "{M"], "i" => [0, "{N"], "j" => [0, "{O"], "k" => [0, "{P"], "l" => [0, "{Q"], "m" => [0, "{R"], "n" => [0, "{S"], "o" => [0, "{T"], "p" => [0, "{U"], "q" => [0, "{V"], "r" => [0, "{W"], "s" => [0, "{Y"], "t" => [0, "{j"], "u" => [0, "{k"], "v" => [0, "{q"], "w" => [0, "{v"], "x" => [0, "{w"], "y" => [0, "{x"], "z" => [0, "{y"], "{" => [0, "{z"], "|" => [82, "{"], "}" => [87, "{"], "~" => [130, "{"], "" => [9, "{"], "\x80" => [93, "\\"], "\x81" => [138, "\\"], "\x82" => [75, "\\"], "\x83" => [91, "\\"], "\x84" => [108, "\\"], "\x85" => [103, "\\"], "\x86" => [114, "\\"], "\x87" => [14, "\\"], "\x88" => [93, "\xc3"], "\x89" => [138, "\xc3"], "\x8a" => [75, "\xc3"], "\x8b" => [91, "\xc3"], "\x8c" => [108, "\xc3"], "\x8d" => [103, "\xc3"], "\x8e" => [114, "\xc3"], "\x8f" => [14, "\xc3"], "\x90" => [93, "\xd0"], "\x91" => [138, "\xd0"], "\x92" => [75, "\xd0"], "\x93" => [91, "\xd0"], "\x94" => [108, "\xd0"], "\x95" => [103, "\xd0"], "\x96" => [114, "\xd0"], "\x97" => [14, "\xd0"], "\x98" => [94, "\x80"], "\x99" => [76, "\x80"], "\x9a" => [104, "\x80"], "\x9b" => [16, "\x80"], "\x9c" => [94, "\x82"], "\x9d" => [76, "\x82"], "\x9e" => [104, "\x82"], "\x9f" => [16, "\x82"], "\xa0" => [94, "\x83"], "\xa1" => [76, "\x83"], "\xa2" => [104, "\x83"], "\xa3" => [16, "\x83"], "\xa4" => [94, "\xa2"], "\xa5" => [76, "\xa2"], "\xa6" => [104, "\xa2"], "\xa7" => [16, "\xa2"], "\xa8" => [94, "\xb8"], "\xa9" => [76, "\xb8"], "\xaa" => [104, "\xb8"], "\xab" => [16, "\xb8"], "\xac" => [94, "\xc2"], "\xad" => [76, "\xc2"], "\xae" => [104, "\xc2"], "\xaf" => [16, "\xc2"], "\xb0" => [94, "\xe0"], "\xb1" => [76, "\xe0"], "\xb2" => [104, "\xe0"], "\xb3" => [16, "\xe0"], "\xb4" => [94, "\xe2"], "\xb5" => [76, "\xe2"], "\xb6" => [104, "\xe2"], "\xb7" => [16, "\xe2"], "\xb8" => [77, "\x99"], "\xb9" => [18, "\x99"], "\xba" => [77, "\xa1"], "\xbb" => [18, "\xa1"], "\xbc" => [77, "\xa7"], "\xbd" => [18, "\xa7"], "\xbe" => [77, "\xac"], "\xbf" => [18, "\xac"], "\xc0" => [77, "\xb0"], "\xc1" => [18, "\xb0"], "\xc2" => [77, "\xb1"], "\xc3" => [18, "\xb1"], "\xc4" => [77, "\xb3"], "\xc5" => [18, "\xb3"], "\xc6" => [77, "\xd1"], "\xc7" => [18, "\xd1"], "\xc8" => [77, "\xd8"], "\xc9" => [18, "\xd8"], "\xca" => [77, "\xd9"], "\xcb" => [18, "\xd9"], "\xcc" => [77, "\xe3"], "\xcd" => [18, "\xe3"], "\xce" => [77, "\xe5"], "\xcf" => [18, "\xe5"], "\xd0" => [77, "\xe6"], "\xd1" => [18, "\xe6"], "\xd2" => [0, "\x81"], "\xd3" => [0, "\x84"], "\xd4" => [0, "\x85"], "\xd5" => [0, "\x86"], "\xd6" => [0, "\x88"], "\xd7" => [0, "\x92"], "\xd8" => [0, "\x9a"], "\xd9" => [0, "\x9c"], "\xda" => [0, "\xa0"], "\xdb" => [0, "\xa3"], "\xdc" => [0, "\xa4"], "\xdd" => [0, "\xa9"], "\xde" => [0, "\xaa"], "\xdf" => [0, "\xad"], "\xe0" => [0, "\xb2"], "\xe1" => [0, "\xb5"], "\xe2" => [0, "\xb9"], "\xe3" => [0, "\xba"], "\xe4" => [0, "\xbb"], "\xe5" => [0, "\xbd"], "\xe6" => [0, "\xbe"], "\xe7" => [0, "\xc4"], "\xe8" => [0, "\xc6"], "\xe9" => [0, "\xe4"], "\xea" => [0, "\xe8"], "\xeb" => [0, "\xe9"], "\xec" => [23, null], "\xed" => [168, null], "\xee" => [169, null], "\xef" => [171, null], "\xf0" => [174, null], "\xf1" => [179, null], "\xf2" => [180, null], "\xf3" => [188, null], "\xf4" => [192, null], "\xf5" => [196, null], "\xf6" => [201, null], "\xf7" => [210, null], "\xf8" => [215, null], "\xf9" => [222, null], "\xfa" => [49, null], "\xfb" => [173, null], "\xfc" => [199, null], "\xfd" => [227, null], "\xfe" => [220, null], "\xff" => [34, null]], ["\x00" => [94, "\x010"], "\x01" => [76, "\x010"], "\x02" => [104, "\x010"], "\x03" => [16, "\x010"], "\x04" => [94, "\x011"], "\x05" => [76, "\x011"], "\x06" => [104, "\x011"], "\x07" => [16, "\x011"], "\x08" => [94, "\x012"], "\t" => [76, "\x012"], "\n" => [104, "\x012"], "\v" => [16, "\x012"], "\f" => [94, "\x01a"], "\r" => [76, "\x01a"], "\x0e" => [104, "\x01a"], "\x0f" => [16, "\x01a"], "\x10" => [94, "\x01c"], "\x11" => [76, "\x01c"], "\x12" => [104, "\x01c"], "\x13" => [16, "\x01c"], "\x14" => [94, "\x01e"], "\x15" => [76, "\x01e"], "\x16" => [104, "\x01e"], "\x17" => [16, "\x01e"], "\x18" => [94, "\x01i"], "\x19" => [76, "\x01i"], "\x1a" => [104, "\x01i"], "\x1b" => [16, "\x01i"], "\x1c" => [94, "\x01o"], "\x1d" => [76, "\x01o"], "\x1e" => [104, "\x01o"], "\x1f" => [16, "\x01o"], " " => [94, "\x01s"], "!" => [76, "\x01s"], "\"" => [104, "\x01s"], "#" => [16, "\x01s"], "\$" => [94, "\x01t"], "%" => [76, "\x01t"], "&" => [104, "\x01t"], "'" => [16, "\x01t"], "(" => [77, "\x01 "], ")" => [18, "\x01 "], "*" => [77, "\x01%"], "+" => [18, "\x01%"], "," => [77, "\x01-"], "-" => [18, "\x01-"], "." => [77, "\x01."], "/" => [18, "\x01."], [77, "\x01/"], [18, "\x01/"], [77, "\x013"], [18, "\x013"], [77, "\x014"], [18, "\x014"], [77, "\x015"], [18, "\x015"], [77, "\x016"], [18, "\x016"], ":" => [77, "\x017"], ";" => [18, "\x017"], "<" => [77, "\x018"], "=" => [18, "\x018"], ">" => [77, "\x019"], "?" => [18, "\x019"], "@" => [77, "\x01="], "A" => [18, "\x01="], "B" => [77, "\x01A"], "C" => [18, "\x01A"], "D" => [77, "\x01_"], "E" => [18, "\x01_"], "F" => [77, "\x01b"], "G" => [18, "\x01b"], "H" => [77, "\x01d"], "I" => [18, "\x01d"], "J" => [77, "\x01f"], "K" => [18, "\x01f"], "L" => [77, "\x01g"], "M" => [18, "\x01g"], "N" => [77, "\x01h"], "O" => [18, "\x01h"], "P" => [77, "\x01l"], "Q" => [18, "\x01l"], "R" => [77, "\x01m"], "S" => [18, "\x01m"], "T" => [77, "\x01n"], "U" => [18, "\x01n"], "V" => [77, "\x01p"], "W" => [18, "\x01p"], "X" => [77, "\x01r"], "Y" => [18, "\x01r"], "Z" => [77, "\x01u"], "[" => [18, "\x01u"], "\\" => [0, "\x01:"], "]" => [0, "\x01B"], "^" => [0, "\x01C"], "_" => [0, "\x01D"], "`" => [0, "\x01E"], "a" => [0, "\x01F"], "b" => [0, "\x01G"], "c" => [0, "\x01H"], "d" => [0, "\x01I"], "e" => [0, "\x01J"], "f" => [0, "\x01K"], "g" => [0, "\x01L"], "h" => [0, "\x01M"], "i" => [0, "\x01N"], "j" => [0, "\x01O"], "k" => [0, "\x01P"], "l" => [0, "\x01Q"], "m" => [0, "\x01R"], "n" => [0, "\x01S"], "o" => [0, "\x01T"], "p" => [0, "\x01U"], "q" => [0, "\x01V"], "r" => [0, "\x01W"], "s" => [0, "\x01Y"], "t" => [0, "\x01j"], "u" => [0, "\x01k"], "v" => [0, "\x01q"], "w" => [0, "\x01v"], "x" => [0, "\x01w"], "y" => [0, "\x01x"], "z" => [0, "\x01y"], "{" => [0, "\x01z"], "|" => [82, "\x01"], "}" => [87, "\x01"], "~" => [130, "\x01"], "" => [9, "\x01"], "\x80" => [94, "\x870"], "\x81" => [76, "\x870"], "\x82" => [104, "\x870"], "\x83" => [16, "\x870"], "\x84" => [94, "\x871"], "\x85" => [76, "\x871"], "\x86" => [104, "\x871"], "\x87" => [16, "\x871"], "\x88" => [94, "\x872"], "\x89" => [76, "\x872"], "\x8a" => [104, "\x872"], "\x8b" => [16, "\x872"], "\x8c" => [94, "\x87a"], "\x8d" => [76, "\x87a"], "\x8e" => [104, "\x87a"], "\x8f" => [16, "\x87a"], "\x90" => [94, "\x87c"], "\x91" => [76, "\x87c"], "\x92" => [104, "\x87c"], "\x93" => [16, "\x87c"], "\x94" => [94, "\x87e"], "\x95" => [76, "\x87e"], "\x96" => [104, "\x87e"], "\x97" => [16, "\x87e"], "\x98" => [94, "\x87i"], "\x99" => [76, "\x87i"], "\x9a" => [104, "\x87i"], "\x9b" => [16, "\x87i"], "\x9c" => [94, "\x87o"], "\x9d" => [76, "\x87o"], "\x9e" => [104, "\x87o"], "\x9f" => [16, "\x87o"], "\xa0" => [94, "\x87s"], "\xa1" => [76, "\x87s"], "\xa2" => [104, "\x87s"], "\xa3" => [16, "\x87s"], "\xa4" => [94, "\x87t"], "\xa5" => [76, "\x87t"], "\xa6" => [104, "\x87t"], "\xa7" => [16, "\x87t"], "\xa8" => [77, "\x87 "], "\xa9" => [18, "\x87 "], "\xaa" => [77, "\x87%"], "\xab" => [18, "\x87%"], "\xac" => [77, "\x87-"], "\xad" => [18, "\x87-"], "\xae" => [77, "\x87."], "\xaf" => [18, "\x87."], "\xb0" => [77, "\x87/"], "\xb1" => [18, "\x87/"], "\xb2" => [77, "\x873"], "\xb3" => [18, "\x873"], "\xb4" => [77, "\x874"], "\xb5" => [18, "\x874"], "\xb6" => [77, "\x875"], "\xb7" => [18, "\x875"], "\xb8" => [77, "\x876"], "\xb9" => [18, "\x876"], "\xba" => [77, "\x877"], "\xbb" => [18, "\x877"], "\xbc" => [77, "\x878"], "\xbd" => [18, "\x878"], "\xbe" => [77, "\x879"], "\xbf" => [18, "\x879"], "\xc0" => [77, "\x87="], "\xc1" => [18, "\x87="], "\xc2" => [77, "\x87A"], "\xc3" => [18, "\x87A"], "\xc4" => [77, "\x87_"], "\xc5" => [18, "\x87_"], "\xc6" => [77, "\x87b"], "\xc7" => [18, "\x87b"], "\xc8" => [77, "\x87d"], "\xc9" => [18, "\x87d"], "\xca" => [77, "\x87f"], "\xcb" => [18, "\x87f"], "\xcc" => [77, "\x87g"], "\xcd" => [18, "\x87g"], "\xce" => [77, "\x87h"], "\xcf" => [18, "\x87h"], "\xd0" => [77, "\x87l"], "\xd1" => [18, "\x87l"], "\xd2" => [77, "\x87m"], "\xd3" => [18, "\x87m"], "\xd4" => [77, "\x87n"], "\xd5" => [18, "\x87n"], "\xd6" => [77, "\x87p"], "\xd7" => [18, "\x87p"], "\xd8" => [77, "\x87r"], "\xd9" => [18, "\x87r"], "\xda" => [77, "\x87u"], "\xdb" => [18, "\x87u"], "\xdc" => [0, "\x87:"], "\xdd" => [0, "\x87B"], "\xde" => [0, "\x87C"], "\xdf" => [0, "\x87D"], "\xe0" => [0, "\x87E"], "\xe1" => [0, "\x87F"], "\xe2" => [0, "\x87G"], "\xe3" => [0, "\x87H"], "\xe4" => [0, "\x87I"], "\xe5" => [0, "\x87J"], "\xe6" => [0, "\x87K"], "\xe7" => [0, "\x87L"], "\xe8" => [0, "\x87M"], "\xe9" => [0, "\x87N"], "\xea" => [0, "\x87O"], "\xeb" => [0, "\x87P"], "\xec" => [0, "\x87Q"], "\xed" => [0, "\x87R"], "\xee" => [0, "\x87S"], "\xef" => [0, "\x87T"], "\xf0" => [0, "\x87U"], "\xf1" => [0, "\x87V"], "\xf2" => [0, "\x87W"], "\xf3" => [0, "\x87Y"], "\xf4" => [0, "\x87j"], "\xf5" => [0, "\x87k"], "\xf6" => [0, "\x87q"], "\xf7" => [0, "\x87v"], "\xf8" => [0, "\x87w"], "\xf9" => [0, "\x87x"], "\xfa" => [0, "\x87y"], "\xfb" => [0, "\x87z"], "\xfc" => [82, "\x87"], "\xfd" => [87, "\x87"], "\xfe" => [130, "\x87"], "\xff" => [9, "\x87"]], ["\x00" => [77, "<0"], "\x01" => [18, "<0"], "\x02" => [77, "<1"], "\x03" => [18, "<1"], "\x04" => [77, "<2"], "\x05" => [18, "<2"], "\x06" => [77, "<a"], "\x07" => [18, "<a"], "\x08" => [77, "<c"], "\t" => [18, "<c"], "\n" => [77, "<e"], "\v" => [18, "<e"], "\f" => [77, "<i"], "\r" => [18, "<i"], "\x0e" => [77, "<o"], "\x0f" => [18, "<o"], "\x10" => [77, "<s"], "\x11" => [18, "<s"], "\x12" => [77, "<t"], "\x13" => [18, "<t"], "\x14" => [0, "< "], "\x15" => [0, "<%"], "\x16" => [0, "<-"], "\x17" => [0, "<."], "\x18" => [0, "</"], "\x19" => [0, "<3"], "\x1a" => [0, "<4"], "\x1b" => [0, "<5"], "\x1c" => [0, "<6"], "\x1d" => [0, "<7"], "\x1e" => [0, "<8"], "\x1f" => [0, "<9"], " " => [0, "<="], "!" => [0, "<A"], "\"" => [0, "<_"], "#" => [0, "<b"], "\$" => [0, "<d"], "%" => [0, "<f"], "&" => [0, "<g"], "'" => [0, "<h"], "(" => [0, "<l"], ")" => [0, "<m"], "*" => [0, "<n"], "+" => [0, "<p"], "," => [0, "<r"], "-" => [0, "<u"], "." => [100, "<"], "/" => [110, "<"], [111, "<"], [115, "<"], [116, "<"], [118, "<"], [119, "<"], [122, "<"], [123, "<"], [125, "<"], [126, "<"], [129, "<"], ":" => [143, "<"], ";" => [148, "<"], "<" => [151, "<"], "=" => [153, "<"], ">" => [83, "<"], "?" => [10, "<"], "@" => [77, "`0"], "A" => [18, "`0"], "B" => [77, "`1"], "C" => [18, "`1"], "D" => [77, "`2"], "E" => [18, "`2"], "F" => [77, "`a"], "G" => [18, "`a"], "H" => [77, "`c"], "I" => [18, "`c"], "J" => [77, "`e"], "K" => [18, "`e"], "L" => [77, "`i"], "M" => [18, "`i"], "N" => [77, "`o"], "O" => [18, "`o"], "P" => [77, "`s"], "Q" => [18, "`s"], "R" => [77, "`t"], "S" => [18, "`t"], "T" => [0, "` "], "U" => [0, "`%"], "V" => [0, "`-"], "W" => [0, "`."], "X" => [0, "`/"], "Y" => [0, "`3"], "Z" => [0, "`4"], "[" => [0, "`5"], "\\" => [0, "`6"], "]" => [0, "`7"], "^" => [0, "`8"], "_" => [0, "`9"], "`" => [0, "`="], "a" => [0, "`A"], "b" => [0, "`_"], "c" => [0, "`b"], "d" => [0, "`d"], "e" => [0, "`f"], "f" => [0, "`g"], "g" => [0, "`h"], "h" => [0, "`l"], "i" => [0, "`m"], "j" => [0, "`n"], "k" => [0, "`p"], "l" => [0, "`r"], "m" => [0, "`u"], "n" => [100, "`"], "o" => [110, "`"], "p" => [111, "`"], "q" => [115, "`"], "r" => [116, "`"], "s" => [118, "`"], "t" => [119, "`"], "u" => [122, "`"], "v" => [123, "`"], "w" => [125, "`"], "x" => [126, "`"], "y" => [129, "`"], "z" => [143, "`"], "{" => [148, "`"], "|" => [151, "`"], "}" => [153, "`"], "~" => [83, "`"], "" => [10, "`"], "\x80" => [77, "{0"], "\x81" => [18, "{0"], "\x82" => [77, "{1"], "\x83" => [18, "{1"], "\x84" => [77, "{2"], "\x85" => [18, "{2"], "\x86" => [77, "{a"], "\x87" => [18, "{a"], "\x88" => [77, "{c"], "\x89" => [18, "{c"], "\x8a" => [77, "{e"], "\x8b" => [18, "{e"], "\x8c" => [77, "{i"], "\x8d" => [18, "{i"], "\x8e" => [77, "{o"], "\x8f" => [18, "{o"], "\x90" => [77, "{s"], "\x91" => [18, "{s"], "\x92" => [77, "{t"], "\x93" => [18, "{t"], "\x94" => [0, "{ "], "\x95" => [0, "{%"], "\x96" => [0, "{-"], "\x97" => [0, "{."], "\x98" => [0, "{/"], "\x99" => [0, "{3"], "\x9a" => [0, "{4"], "\x9b" => [0, "{5"], "\x9c" => [0, "{6"], "\x9d" => [0, "{7"], "\x9e" => [0, "{8"], "\x9f" => [0, "{9"], "\xa0" => [0, "{="], "\xa1" => [0, "{A"], "\xa2" => [0, "{_"], "\xa3" => [0, "{b"], "\xa4" => [0, "{d"], "\xa5" => [0, "{f"], "\xa6" => [0, "{g"], "\xa7" => [0, "{h"], "\xa8" => [0, "{l"], "\xa9" => [0, "{m"], "\xaa" => [0, "{n"], "\xab" => [0, "{p"], "\xac" => [0, "{r"], "\xad" => [0, "{u"], "\xae" => [100, "{"], "\xaf" => [110, "{"], "\xb0" => [111, "{"], "\xb1" => [115, "{"], "\xb2" => [116, "{"], "\xb3" => [118, "{"], "\xb4" => [119, "{"], "\xb5" => [122, "{"], "\xb6" => [123, "{"], "\xb7" => [125, "{"], "\xb8" => [126, "{"], "\xb9" => [129, "{"], "\xba" => [143, "{"], "\xbb" => [148, "{"], "\xbc" => [151, "{"], "\xbd" => [153, "{"], "\xbe" => [83, "{"], "\xbf" => [10, "{"], "\xc0" => [94, "\\"], "\xc1" => [76, "\\"], "\xc2" => [104, "\\"], "\xc3" => [16, "\\"], "\xc4" => [94, "\xc3"], "\xc5" => [76, "\xc3"], "\xc6" => [104, "\xc3"], "\xc7" => [16, "\xc3"], "\xc8" => [94, "\xd0"], "\xc9" => [76, "\xd0"], "\xca" => [104, "\xd0"], "\xcb" => [16, "\xd0"], "\xcc" => [77, "\x80"], "\xcd" => [18, "\x80"], "\xce" => [77, "\x82"], "\xcf" => [18, "\x82"], "\xd0" => [77, "\x83"], "\xd1" => [18, "\x83"], "\xd2" => [77, "\xa2"], "\xd3" => [18, "\xa2"], "\xd4" => [77, "\xb8"], "\xd5" => [18, "\xb8"], "\xd6" => [77, "\xc2"], "\xd7" => [18, "\xc2"], "\xd8" => [77, "\xe0"], "\xd9" => [18, "\xe0"], "\xda" => [77, "\xe2"], "\xdb" => [18, "\xe2"], "\xdc" => [0, "\x99"], "\xdd" => [0, "\xa1"], "\xde" => [0, "\xa7"], "\xdf" => [0, "\xac"], "\xe0" => [0, "\xb0"], "\xe1" => [0, "\xb1"], "\xe2" => [0, "\xb3"], "\xe3" => [0, "\xd1"], "\xe4" => [0, "\xd8"], "\xe5" => [0, "\xd9"], "\xe6" => [0, "\xe3"], "\xe7" => [0, "\xe5"], "\xe8" => [0, "\xe6"], "\xe9" => [157, null], "\xea" => [165, null], "\xeb" => [167, null], "\xec" => [185, null], "\xed" => [189, null], "\xee" => [190, null], "\xef" => [197, null], "\xf0" => [206, null], "\xf1" => [212, null], "\xf2" => [213, null], "\xf3" => [217, null], "\xf4" => [223, null], "\xf5" => [250, null], "\xf6" => [25, null], "\xf7" => [170, null], "\xf8" => [175, null], "\xf9" => [181, null], "\xfa" => [193, null], "\xfb" => [202, null], "\xfc" => [216, null], "\xfd" => [50, null], "\xfe" => [200, null], "\xff" => [35, null]], ["\x00" => [77, "\x010"], "\x01" => [18, "\x010"], "\x02" => [77, "\x011"], "\x03" => [18, "\x011"], "\x04" => [77, "\x012"], "\x05" => [18, "\x012"], "\x06" => [77, "\x01a"], "\x07" => [18, "\x01a"], "\x08" => [77, "\x01c"], "\t" => [18, "\x01c"], "\n" => [77, "\x01e"], "\v" => [18, "\x01e"], "\f" => [77, "\x01i"], "\r" => [18, "\x01i"], "\x0e" => [77, "\x01o"], "\x0f" => [18, "\x01o"], "\x10" => [77, "\x01s"], "\x11" => [18, "\x01s"], "\x12" => [77, "\x01t"], "\x13" => [18, "\x01t"], "\x14" => [0, "\x01 "], "\x15" => [0, "\x01%"], "\x16" => [0, "\x01-"], "\x17" => [0, "\x01."], "\x18" => [0, "\x01/"], "\x19" => [0, "\x013"], "\x1a" => [0, "\x014"], "\x1b" => [0, "\x015"], "\x1c" => [0, "\x016"], "\x1d" => [0, "\x017"], "\x1e" => [0, "\x018"], "\x1f" => [0, "\x019"], " " => [0, "\x01="], "!" => [0, "\x01A"], "\"" => [0, "\x01_"], "#" => [0, "\x01b"], "\$" => [0, "\x01d"], "%" => [0, "\x01f"], "&" => [0, "\x01g"], "'" => [0, "\x01h"], "(" => [0, "\x01l"], ")" => [0, "\x01m"], "*" => [0, "\x01n"], "+" => [0, "\x01p"], "," => [0, "\x01r"], "-" => [0, "\x01u"], "." => [100, "\x01"], "/" => [110, "\x01"], [111, "\x01"], [115, "\x01"], [116, "\x01"], [118, "\x01"], [119, "\x01"], [122, "\x01"], [123, "\x01"], [125, "\x01"], [126, "\x01"], [129, "\x01"], ":" => [143, "\x01"], ";" => [148, "\x01"], "<" => [151, "\x01"], "=" => [153, "\x01"], ">" => [83, "\x01"], "?" => [10, "\x01"], "@" => [77, "\x870"], "A" => [18, "\x870"], "B" => [77, "\x871"], "C" => [18, "\x871"], "D" => [77, "\x872"], "E" => [18, "\x872"], "F" => [77, "\x87a"], "G" => [18, "\x87a"], "H" => [77, "\x87c"], "I" => [18, "\x87c"], "J" => [77, "\x87e"], "K" => [18, "\x87e"], "L" => [77, "\x87i"], "M" => [18, "\x87i"], "N" => [77, "\x87o"], "O" => [18, "\x87o"], "P" => [77, "\x87s"], "Q" => [18, "\x87s"], "R" => [77, "\x87t"], "S" => [18, "\x87t"], "T" => [0, "\x87 "], "U" => [0, "\x87%"], "V" => [0, "\x87-"], "W" => [0, "\x87."], "X" => [0, "\x87/"], "Y" => [0, "\x873"], "Z" => [0, "\x874"], "[" => [0, "\x875"], "\\" => [0, "\x876"], "]" => [0, "\x877"], "^" => [0, "\x878"], "_" => [0, "\x879"], "`" => [0, "\x87="], "a" => [0, "\x87A"], "b" => [0, "\x87_"], "c" => [0, "\x87b"], "d" => [0, "\x87d"], "e" => [0, "\x87f"], "f" => [0, "\x87g"], "g" => [0, "\x87h"], "h" => [0, "\x87l"], "i" => [0, "\x87m"], "j" => [0, "\x87n"], "k" => [0, "\x87p"], "l" => [0, "\x87r"], "m" => [0, "\x87u"], "n" => [100, "\x87"], "o" => [110, "\x87"], "p" => [111, "\x87"], "q" => [115, "\x87"], "r" => [116, "\x87"], "s" => [118, "\x87"], "t" => [119, "\x87"], "u" => [122, "\x87"], "v" => [123, "\x87"], "w" => [125, "\x87"], "x" => [126, "\x87"], "y" => [129, "\x87"], "z" => [143, "\x87"], "{" => [148, "\x87"], "|" => [151, "\x87"], "}" => [153, "\x87"], "~" => [83, "\x87"], "" => [10, "\x87"], "\x80" => [77, "\x890"], "\x81" => [18, "\x890"], "\x82" => [77, "\x891"], "\x83" => [18, "\x891"], "\x84" => [77, "\x892"], "\x85" => [18, "\x892"], "\x86" => [77, "\x89a"], "\x87" => [18, "\x89a"], "\x88" => [77, "\x89c"], "\x89" => [18, "\x89c"], "\x8a" => [77, "\x89e"], "\x8b" => [18, "\x89e"], "\x8c" => [77, "\x89i"], "\x8d" => [18, "\x89i"], "\x8e" => [77, "\x89o"], "\x8f" => [18, "\x89o"], "\x90" => [77, "\x89s"], "\x91" => [18, "\x89s"], "\x92" => [77, "\x89t"], "\x93" => [18, "\x89t"], "\x94" => [0, "\x89 "], "\x95" => [0, "\x89%"], "\x96" => [0, "\x89-"], "\x97" => [0, "\x89."], "\x98" => [0, "\x89/"], "\x99" => [0, "\x893"], "\x9a" => [0, "\x894"], "\x9b" => [0, "\x895"], "\x9c" => [0, "\x896"], "\x9d" => [0, "\x897"], "\x9e" => [0, "\x898"], "\x9f" => [0, "\x899"], "\xa0" => [0, "\x89="], "\xa1" => [0, "\x89A"], "\xa2" => [0, "\x89_"], "\xa3" => [0, "\x89b"], "\xa4" => [0, "\x89d"], "\xa5" => [0, "\x89f"], "\xa6" => [0, "\x89g"], "\xa7" => [0, "\x89h"], "\xa8" => [0, "\x89l"], "\xa9" => [0, "\x89m"], "\xaa" => [0, "\x89n"], "\xab" => [0, "\x89p"], "\xac" => [0, "\x89r"], "\xad" => [0, "\x89u"], "\xae" => [100, "\x89"], "\xaf" => [110, "\x89"], "\xb0" => [111, "\x89"], "\xb1" => [115, "\x89"], "\xb2" => [116, "\x89"], "\xb3" => [118, "\x89"], "\xb4" => [119, "\x89"], "\xb5" => [122, "\x89"], "\xb6" => [123, "\x89"], "\xb7" => [125, "\x89"], "\xb8" => [126, "\x89"], "\xb9" => [129, "\x89"], "\xba" => [143, "\x89"], "\xbb" => [148, "\x89"], "\xbc" => [151, "\x89"], "\xbd" => [153, "\x89"], "\xbe" => [83, "\x89"], "\xbf" => [10, "\x89"], "\xc0" => [77, "\x8a0"], "\xc1" => [18, "\x8a0"], "\xc2" => [77, "\x8a1"], "\xc3" => [18, "\x8a1"], "\xc4" => [77, "\x8a2"], "\xc5" => [18, "\x8a2"], "\xc6" => [77, "\x8aa"], "\xc7" => [18, "\x8aa"], "\xc8" => [77, "\x8ac"], "\xc9" => [18, "\x8ac"], "\xca" => [77, "\x8ae"], "\xcb" => [18, "\x8ae"], "\xcc" => [77, "\x8ai"], "\xcd" => [18, "\x8ai"], "\xce" => [77, "\x8ao"], "\xcf" => [18, "\x8ao"], "\xd0" => [77, "\x8as"], "\xd1" => [18, "\x8as"], "\xd2" => [77, "\x8at"], "\xd3" => [18, "\x8at"], "\xd4" => [0, "\x8a "], "\xd5" => [0, "\x8a%"], "\xd6" => [0, "\x8a-"], "\xd7" => [0, "\x8a."], "\xd8" => [0, "\x8a/"], "\xd9" => [0, "\x8a3"], "\xda" => [0, "\x8a4"], "\xdb" => [0, "\x8a5"], "\xdc" => [0, "\x8a6"], "\xdd" => [0, "\x8a7"], "\xde" => [0, "\x8a8"], "\xdf" => [0, "\x8a9"], "\xe0" => [0, "\x8a="], "\xe1" => [0, "\x8aA"], "\xe2" => [0, "\x8a_"], "\xe3" => [0, "\x8ab"], "\xe4" => [0, "\x8ad"], "\xe5" => [0, "\x8af"], "\xe6" => [0, "\x8ag"], "\xe7" => [0, "\x8ah"], "\xe8" => [0, "\x8al"], "\xe9" => [0, "\x8am"], "\xea" => [0, "\x8an"], "\xeb" => [0, "\x8ap"], "\xec" => [0, "\x8ar"], "\xed" => [0, "\x8au"], "\xee" => [100, "\x8a"], "\xef" => [110, "\x8a"], "\xf0" => [111, "\x8a"], "\xf1" => [115, "\x8a"], "\xf2" => [116, "\x8a"], "\xf3" => [118, "\x8a"], "\xf4" => [119, "\x8a"], "\xf5" => [122, "\x8a"], "\xf6" => [123, "\x8a"], "\xf7" => [125, "\x8a"], "\xf8" => [126, "\x8a"], "\xf9" => [129, "\x8a"], "\xfa" => [143, "\x8a"], "\xfb" => [148, "\x8a"], "\xfc" => [151, "\x8a"], "\xfd" => [153, "\x8a"], "\xfe" => [83, "\x8a"], "\xff" => [10, "\x8a"]], ["\x00" => [77, "^0"], "\x01" => [18, "^0"], "\x02" => [77, "^1"], "\x03" => [18, "^1"], "\x04" => [77, "^2"], "\x05" => [18, "^2"], "\x06" => [77, "^a"], "\x07" => [18, "^a"], "\x08" => [77, "^c"], "\t" => [18, "^c"], "\n" => [77, "^e"], "\v" => [18, "^e"], "\f" => [77, "^i"], "\r" => [18, "^i"], "\x0e" => [77, "^o"], "\x0f" => [18, "^o"], "\x10" => [77, "^s"], "\x11" => [18, "^s"], "\x12" => [77, "^t"], "\x13" => [18, "^t"], "\x14" => [0, "^ "], "\x15" => [0, "^%"], "\x16" => [0, "^-"], "\x17" => [0, "^."], "\x18" => [0, "^/"], "\x19" => [0, "^3"], "\x1a" => [0, "^4"], "\x1b" => [0, "^5"], "\x1c" => [0, "^6"], "\x1d" => [0, "^7"], "\x1e" => [0, "^8"], "\x1f" => [0, "^9"], " " => [0, "^="], "!" => [0, "^A"], "\"" => [0, "^_"], "#" => [0, "^b"], "\$" => [0, "^d"], "%" => [0, "^f"], "&" => [0, "^g"], "'" => [0, "^h"], "(" => [0, "^l"], ")" => [0, "^m"], "*" => [0, "^n"], "+" => [0, "^p"], "," => [0, "^r"], "-" => [0, "^u"], "." => [100, "^"], "/" => [110, "^"], [111, "^"], [115, "^"], [116, "^"], [118, "^"], [119, "^"], [122, "^"], [123, "^"], [125, "^"], [126, "^"], [129, "^"], ":" => [143, "^"], ";" => [148, "^"], "<" => [151, "^"], "=" => [153, "^"], ">" => [83, "^"], "?" => [10, "^"], "@" => [77, "}0"], "A" => [18, "}0"], "B" => [77, "}1"], "C" => [18, "}1"], "D" => [77, "}2"], "E" => [18, "}2"], "F" => [77, "}a"], "G" => [18, "}a"], "H" => [77, "}c"], "I" => [18, "}c"], "J" => [77, "}e"], "K" => [18, "}e"], "L" => [77, "}i"], "M" => [18, "}i"], "N" => [77, "}o"], "O" => [18, "}o"], "P" => [77, "}s"], "Q" => [18, "}s"], "R" => [77, "}t"], "S" => [18, "}t"], "T" => [0, "} "], "U" => [0, "}%"], "V" => [0, "}-"], "W" => [0, "}."], "X" => [0, "}/"], "Y" => [0, "}3"], "Z" => [0, "}4"], "[" => [0, "}5"], "\\" => [0, "}6"], "]" => [0, "}7"], "^" => [0, "}8"], "_" => [0, "}9"], "`" => [0, "}="], "a" => [0, "}A"], "b" => [0, "}_"], "c" => [0, "}b"], "d" => [0, "}d"], "e" => [0, "}f"], "f" => [0, "}g"], "g" => [0, "}h"], "h" => [0, "}l"], "i" => [0, "}m"], "j" => [0, "}n"], "k" => [0, "}p"], "l" => [0, "}r"], "m" => [0, "}u"], "n" => [100, "}"], "o" => [110, "}"], "p" => [111, "}"], "q" => [115, "}"], "r" => [116, "}"], "s" => [118, "}"], "t" => [119, "}"], "u" => [122, "}"], "v" => [123, "}"], "w" => [125, "}"], "x" => [126, "}"], "y" => [129, "}"], "z" => [143, "}"], "{" => [148, "}"], "|" => [151, "}"], "}" => [153, "}"], "~" => [83, "}"], "" => [10, "}"], "\x80" => [0, "<0"], "\x81" => [0, "<1"], "\x82" => [0, "<2"], "\x83" => [0, "<a"], "\x84" => [0, "<c"], "\x85" => [0, "<e"], "\x86" => [0, "<i"], "\x87" => [0, "<o"], "\x88" => [0, "<s"], "\x89" => [0, "<t"], "\x8a" => [73, "<"], "\x8b" => [88, "<"], "\x8c" => [89, "<"], "\x8d" => [96, "<"], "\x8e" => [97, "<"], "\x8f" => [99, "<"], "\x90" => [106, "<"], "\x91" => [136, "<"], "\x92" => [139, "<"], "\x93" => [141, "<"], "\x94" => [145, "<"], "\x95" => [147, "<"], "\x96" => [149, "<"], "\x97" => [101, "<"], "\x98" => [112, "<"], "\x99" => [117, "<"], "\x9a" => [120, "<"], "\x9b" => [124, "<"], "\x9c" => [127, "<"], "\x9d" => [144, "<"], "\x9e" => [152, "<"], "\x9f" => [11, "<"], "\xa0" => [0, "`0"], "\xa1" => [0, "`1"], "\xa2" => [0, "`2"], "\xa3" => [0, "`a"], "\xa4" => [0, "`c"], "\xa5" => [0, "`e"], "\xa6" => [0, "`i"], "\xa7" => [0, "`o"], "\xa8" => [0, "`s"], "\xa9" => [0, "`t"], "\xaa" => [73, "`"], "\xab" => [88, "`"], "\xac" => [89, "`"], "\xad" => [96, "`"], "\xae" => [97, "`"], "\xaf" => [99, "`"], "\xb0" => [106, "`"], "\xb1" => [136, "`"], "\xb2" => [139, "`"], "\xb3" => [141, "`"], "\xb4" => [145, "`"], "\xb5" => [147, "`"], "\xb6" => [149, "`"], "\xb7" => [101, "`"], "\xb8" => [112, "`"], "\xb9" => [117, "`"], "\xba" => [120, "`"], "\xbb" => [124, "`"], "\xbc" => [127, "`"], "\xbd" => [144, "`"], "\xbe" => [152, "`"], "\xbf" => [11, "`"], "\xc0" => [0, "{0"], "\xc1" => [0, "{1"], "\xc2" => [0, "{2"], "\xc3" => [0, "{a"], "\xc4" => [0, "{c"], "\xc5" => [0, "{e"], "\xc6" => [0, "{i"], "\xc7" => [0, "{o"], "\xc8" => [0, "{s"], "\xc9" => [0, "{t"], "\xca" => [73, "{"], "\xcb" => [88, "{"], "\xcc" => [89, "{"], "\xcd" => [96, "{"], "\xce" => [97, "{"], "\xcf" => [99, "{"], "\xd0" => [106, "{"], "\xd1" => [136, "{"], "\xd2" => [139, "{"], "\xd3" => [141, "{"], "\xd4" => [145, "{"], "\xd5" => [147, "{"], "\xd6" => [149, "{"], "\xd7" => [101, "{"], "\xd8" => [112, "{"], "\xd9" => [117, "{"], "\xda" => [120, "{"], "\xdb" => [124, "{"], "\xdc" => [127, "{"], "\xdd" => [144, "{"], "\xde" => [152, "{"], "\xdf" => [11, "{"], "\xe0" => [77, "\\"], "\xe1" => [18, "\\"], "\xe2" => [77, "\xc3"], "\xe3" => [18, "\xc3"], "\xe4" => [77, "\xd0"], "\xe5" => [18, "\xd0"], "\xe6" => [0, "\x80"], "\xe7" => [0, "\x82"], "\xe8" => [0, "\x83"], "\xe9" => [0, "\xa2"], "\xea" => [0, "\xb8"], "\xeb" => [0, "\xc2"], "\xec" => [0, "\xe0"], "\xed" => [0, "\xe2"], "\xee" => [182, null], "\xef" => [195, null], "\xf0" => [203, null], "\xf1" => [209, null], "\xf2" => [242, null], "\xf3" => [249, null], "\xf4" => [158, null], "\xf5" => [166, null], "\xf6" => [186, null], "\xf7" => [191, null], "\xf8" => [207, null], "\xf9" => [214, null], "\xfa" => [224, null], "\xfb" => [27, null], "\xfc" => [176, null], "\xfd" => [194, null], "\xfe" => [51, null], "\xff" => [36, null]], ["\x00" => [0, "\x010"], "\x01" => [0, "\x011"], "\x02" => [0, "\x012"], "\x03" => [0, "\x01a"], "\x04" => [0, "\x01c"], "\x05" => [0, "\x01e"], "\x06" => [0, "\x01i"], "\x07" => [0, "\x01o"], "\x08" => [0, "\x01s"], "\t" => [0, "\x01t"], "\n" => [73, "\x01"], "\v" => [88, "\x01"], "\f" => [89, "\x01"], "\r" => [96, "\x01"], "\x0e" => [97, "\x01"], "\x0f" => [99, "\x01"], "\x10" => [106, "\x01"], "\x11" => [136, "\x01"], "\x12" => [139, "\x01"], "\x13" => [141, "\x01"], "\x14" => [145, "\x01"], "\x15" => [147, "\x01"], "\x16" => [149, "\x01"], "\x17" => [101, "\x01"], "\x18" => [112, "\x01"], "\x19" => [117, "\x01"], "\x1a" => [120, "\x01"], "\x1b" => [124, "\x01"], "\x1c" => [127, "\x01"], "\x1d" => [144, "\x01"], "\x1e" => [152, "\x01"], "\x1f" => [11, "\x01"], " " => [0, "\x870"], "!" => [0, "\x871"], "\"" => [0, "\x872"], "#" => [0, "\x87a"], "\$" => [0, "\x87c"], "%" => [0, "\x87e"], "&" => [0, "\x87i"], "'" => [0, "\x87o"], "(" => [0, "\x87s"], ")" => [0, "\x87t"], "*" => [73, "\x87"], "+" => [88, "\x87"], "," => [89, "\x87"], "-" => [96, "\x87"], "." => [97, "\x87"], "/" => [99, "\x87"], [106, "\x87"], [136, "\x87"], [139, "\x87"], [141, "\x87"], [145, "\x87"], [147, "\x87"], [149, "\x87"], [101, "\x87"], [112, "\x87"], [117, "\x87"], ":" => [120, "\x87"], ";" => [124, "\x87"], "<" => [127, "\x87"], "=" => [144, "\x87"], ">" => [152, "\x87"], "?" => [11, "\x87"], "@" => [0, "\x890"], "A" => [0, "\x891"], "B" => [0, "\x892"], "C" => [0, "\x89a"], "D" => [0, "\x89c"], "E" => [0, "\x89e"], "F" => [0, "\x89i"], "G" => [0, "\x89o"], "H" => [0, "\x89s"], "I" => [0, "\x89t"], "J" => [73, "\x89"], "K" => [88, "\x89"], "L" => [89, "\x89"], "M" => [96, "\x89"], "N" => [97, "\x89"], "O" => [99, "\x89"], "P" => [106, "\x89"], "Q" => [136, "\x89"], "R" => [139, "\x89"], "S" => [141, "\x89"], "T" => [145, "\x89"], "U" => [147, "\x89"], "V" => [149, "\x89"], "W" => [101, "\x89"], "X" => [112, "\x89"], "Y" => [117, "\x89"], "Z" => [120, "\x89"], "[" => [124, "\x89"], "\\" => [127, "\x89"], "]" => [144, "\x89"], "^" => [152, "\x89"], "_" => [11, "\x89"], "`" => [0, "\x8a0"], "a" => [0, "\x8a1"], "b" => [0, "\x8a2"], "c" => [0, "\x8aa"], "d" => [0, "\x8ac"], "e" => [0, "\x8ae"], "f" => [0, "\x8ai"], "g" => [0, "\x8ao"], "h" => [0, "\x8as"], "i" => [0, "\x8at"], "j" => [73, "\x8a"], "k" => [88, "\x8a"], "l" => [89, "\x8a"], "m" => [96, "\x8a"], "n" => [97, "\x8a"], "o" => [99, "\x8a"], "p" => [106, "\x8a"], "q" => [136, "\x8a"], "r" => [139, "\x8a"], "s" => [141, "\x8a"], "t" => [145, "\x8a"], "u" => [147, "\x8a"], "v" => [149, "\x8a"], "w" => [101, "\x8a"], "x" => [112, "\x8a"], "y" => [117, "\x8a"], "z" => [120, "\x8a"], "{" => [124, "\x8a"], "|" => [127, "\x8a"], "}" => [144, "\x8a"], "~" => [152, "\x8a"], "" => [11, "\x8a"], "\x80" => [0, "\x8b0"], "\x81" => [0, "\x8b1"], "\x82" => [0, "\x8b2"], "\x83" => [0, "\x8ba"], "\x84" => [0, "\x8bc"], "\x85" => [0, "\x8be"], "\x86" => [0, "\x8bi"], "\x87" => [0, "\x8bo"], "\x88" => [0, "\x8bs"], "\x89" => [0, "\x8bt"], "\x8a" => [73, "\x8b"], "\x8b" => [88, "\x8b"], "\x8c" => [89, "\x8b"], "\x8d" => [96, "\x8b"], "\x8e" => [97, "\x8b"], "\x8f" => [99, "\x8b"], "\x90" => [106, "\x8b"], "\x91" => [136, "\x8b"], "\x92" => [139, "\x8b"], "\x93" => [141, "\x8b"], "\x94" => [145, "\x8b"], "\x95" => [147, "\x8b"], "\x96" => [149, "\x8b"], "\x97" => [101, "\x8b"], "\x98" => [112, "\x8b"], "\x99" => [117, "\x8b"], "\x9a" => [120, "\x8b"], "\x9b" => [124, "\x8b"], "\x9c" => [127, "\x8b"], "\x9d" => [144, "\x8b"], "\x9e" => [152, "\x8b"], "\x9f" => [11, "\x8b"], "\xa0" => [0, "\x8c0"], "\xa1" => [0, "\x8c1"], "\xa2" => [0, "\x8c2"], "\xa3" => [0, "\x8ca"], "\xa4" => [0, "\x8cc"], "\xa5" => [0, "\x8ce"], "\xa6" => [0, "\x8ci"], "\xa7" => [0, "\x8co"], "\xa8" => [0, "\x8cs"], "\xa9" => [0, "\x8ct"], "\xaa" => [73, "\x8c"], "\xab" => [88, "\x8c"], "\xac" => [89, "\x8c"], "\xad" => [96, "\x8c"], "\xae" => [97, "\x8c"], "\xaf" => [99, "\x8c"], "\xb0" => [106, "\x8c"], "\xb1" => [136, "\x8c"], "\xb2" => [139, "\x8c"], "\xb3" => [141, "\x8c"], "\xb4" => [145, "\x8c"], "\xb5" => [147, "\x8c"], "\xb6" => [149, "\x8c"], "\xb7" => [101, "\x8c"], "\xb8" => [112, "\x8c"], "\xb9" => [117, "\x8c"], "\xba" => [120, "\x8c"], "\xbb" => [124, "\x8c"], "\xbc" => [127, "\x8c"], "\xbd" => [144, "\x8c"], "\xbe" => [152, "\x8c"], "\xbf" => [11, "\x8c"], "\xc0" => [0, "\x8d0"], "\xc1" => [0, "\x8d1"], "\xc2" => [0, "\x8d2"], "\xc3" => [0, "\x8da"], "\xc4" => [0, "\x8dc"], "\xc5" => [0, "\x8de"], "\xc6" => [0, "\x8di"], "\xc7" => [0, "\x8do"], "\xc8" => [0, "\x8ds"], "\xc9" => [0, "\x8dt"], "\xca" => [73, "\x8d"], "\xcb" => [88, "\x8d"], "\xcc" => [89, "\x8d"], "\xcd" => [96, "\x8d"], "\xce" => [97, "\x8d"], "\xcf" => [99, "\x8d"], "\xd0" => [106, "\x8d"], "\xd1" => [136, "\x8d"], "\xd2" => [139, "\x8d"], "\xd3" => [141, "\x8d"], "\xd4" => [145, "\x8d"], "\xd5" => [147, "\x8d"], "\xd6" => [149, "\x8d"], "\xd7" => [101, "\x8d"], "\xd8" => [112, "\x8d"], "\xd9" => [117, "\x8d"], "\xda" => [120, "\x8d"], "\xdb" => [124, "\x8d"], "\xdc" => [127, "\x8d"], "\xdd" => [144, "\x8d"], "\xde" => [152, "\x8d"], "\xdf" => [11, "\x8d"], "\xe0" => [0, "\x8f0"], "\xe1" => [0, "\x8f1"], "\xe2" => [0, "\x8f2"], "\xe3" => [0, "\x8fa"], "\xe4" => [0, "\x8fc"], "\xe5" => [0, "\x8fe"], "\xe6" => [0, "\x8fi"], "\xe7" => [0, "\x8fo"], "\xe8" => [0, "\x8fs"], "\xe9" => [0, "\x8ft"], "\xea" => [73, "\x8f"], "\xeb" => [88, "\x8f"], "\xec" => [89, "\x8f"], "\xed" => [96, "\x8f"], "\xee" => [97, "\x8f"], "\xef" => [99, "\x8f"], "\xf0" => [106, "\x8f"], "\xf1" => [136, "\x8f"], "\xf2" => [139, "\x8f"], "\xf3" => [141, "\x8f"], "\xf4" => [145, "\x8f"], "\xf5" => [147, "\x8f"], "\xf6" => [149, "\x8f"], "\xf7" => [101, "\x8f"], "\xf8" => [112, "\x8f"], "\xf9" => [117, "\x8f"], "\xfa" => [120, "\x8f"], "\xfb" => [124, "\x8f"], "\xfc" => [127, "\x8f"], "\xfd" => [144, "\x8f"], "\xfe" => [152, "\x8f"], "\xff" => [11, "\x8f"]], ["\x00" => [77, "]0"], "\x01" => [18, "]0"], "\x02" => [77, "]1"], "\x03" => [18, "]1"], "\x04" => [77, "]2"], "\x05" => [18, "]2"], "\x06" => [77, "]a"], "\x07" => [18, "]a"], "\x08" => [77, "]c"], "\t" => [18, "]c"], "\n" => [77, "]e"], "\v" => [18, "]e"], "\f" => [77, "]i"], "\r" => [18, "]i"], "\x0e" => [77, "]o"], "\x0f" => [18, "]o"], "\x10" => [77, "]s"], "\x11" => [18, "]s"], "\x12" => [77, "]t"], "\x13" => [18, "]t"], "\x14" => [0, "] "], "\x15" => [0, "]%"], "\x16" => [0, "]-"], "\x17" => [0, "]."], "\x18" => [0, "]/"], "\x19" => [0, "]3"], "\x1a" => [0, "]4"], "\x1b" => [0, "]5"], "\x1c" => [0, "]6"], "\x1d" => [0, "]7"], "\x1e" => [0, "]8"], "\x1f" => [0, "]9"], " " => [0, "]="], "!" => [0, "]A"], "\"" => [0, "]_"], "#" => [0, "]b"], "\$" => [0, "]d"], "%" => [0, "]f"], "&" => [0, "]g"], "'" => [0, "]h"], "(" => [0, "]l"], ")" => [0, "]m"], "*" => [0, "]n"], "+" => [0, "]p"], "," => [0, "]r"], "-" => [0, "]u"], "." => [100, "]"], "/" => [110, "]"], [111, "]"], [115, "]"], [116, "]"], [118, "]"], [119, "]"], [122, "]"], [123, "]"], [125, "]"], [126, "]"], [129, "]"], ":" => [143, "]"], ";" => [148, "]"], "<" => [151, "]"], "=" => [153, "]"], ">" => [83, "]"], "?" => [10, "]"], "@" => [77, "~0"], "A" => [18, "~0"], "B" => [77, "~1"], "C" => [18, "~1"], "D" => [77, "~2"], "E" => [18, "~2"], "F" => [77, "~a"], "G" => [18, "~a"], "H" => [77, "~c"], "I" => [18, "~c"], "J" => [77, "~e"], "K" => [18, "~e"], "L" => [77, "~i"], "M" => [18, "~i"], "N" => [77, "~o"], "O" => [18, "~o"], "P" => [77, "~s"], "Q" => [18, "~s"], "R" => [77, "~t"], "S" => [18, "~t"], "T" => [0, "~ "], "U" => [0, "~%"], "V" => [0, "~-"], "W" => [0, "~."], "X" => [0, "~/"], "Y" => [0, "~3"], "Z" => [0, "~4"], "[" => [0, "~5"], "\\" => [0, "~6"], "]" => [0, "~7"], "^" => [0, "~8"], "_" => [0, "~9"], "`" => [0, "~="], "a" => [0, "~A"], "b" => [0, "~_"], "c" => [0, "~b"], "d" => [0, "~d"], "e" => [0, "~f"], "f" => [0, "~g"], "g" => [0, "~h"], "h" => [0, "~l"], "i" => [0, "~m"], "j" => [0, "~n"], "k" => [0, "~p"], "l" => [0, "~r"], "m" => [0, "~u"], "n" => [100, "~"], "o" => [110, "~"], "p" => [111, "~"], "q" => [115, "~"], "r" => [116, "~"], "s" => [118, "~"], "t" => [119, "~"], "u" => [122, "~"], "v" => [123, "~"], "w" => [125, "~"], "x" => [126, "~"], "y" => [129, "~"], "z" => [143, "~"], "{" => [148, "~"], "|" => [151, "~"], "}" => [153, "~"], "~" => [83, "~"], "" => [10, "~"], "\x80" => [0, "^0"], "\x81" => [0, "^1"], "\x82" => [0, "^2"], "\x83" => [0, "^a"], "\x84" => [0, "^c"], "\x85" => [0, "^e"], "\x86" => [0, "^i"], "\x87" => [0, "^o"], "\x88" => [0, "^s"], "\x89" => [0, "^t"], "\x8a" => [73, "^"], "\x8b" => [88, "^"], "\x8c" => [89, "^"], "\x8d" => [96, "^"], "\x8e" => [97, "^"], "\x8f" => [99, "^"], "\x90" => [106, "^"], "\x91" => [136, "^"], "\x92" => [139, "^"], "\x93" => [141, "^"], "\x94" => [145, "^"], "\x95" => [147, "^"], "\x96" => [149, "^"], "\x97" => [101, "^"], "\x98" => [112, "^"], "\x99" => [117, "^"], "\x9a" => [120, "^"], "\x9b" => [124, "^"], "\x9c" => [127, "^"], "\x9d" => [144, "^"], "\x9e" => [152, "^"], "\x9f" => [11, "^"], "\xa0" => [0, "}0"], "\xa1" => [0, "}1"], "\xa2" => [0, "}2"], "\xa3" => [0, "}a"], "\xa4" => [0, "}c"], "\xa5" => [0, "}e"], "\xa6" => [0, "}i"], "\xa7" => [0, "}o"], "\xa8" => [0, "}s"], "\xa9" => [0, "}t"], "\xaa" => [73, "}"], "\xab" => [88, "}"], "\xac" => [89, "}"], "\xad" => [96, "}"], "\xae" => [97, "}"], "\xaf" => [99, "}"], "\xb0" => [106, "}"], "\xb1" => [136, "}"], "\xb2" => [139, "}"], "\xb3" => [141, "}"], "\xb4" => [145, "}"], "\xb5" => [147, "}"], "\xb6" => [149, "}"], "\xb7" => [101, "}"], "\xb8" => [112, "}"], "\xb9" => [117, "}"], "\xba" => [120, "}"], "\xbb" => [124, "}"], "\xbc" => [127, "}"], "\xbd" => [144, "}"], "\xbe" => [152, "}"], "\xbf" => [11, "}"], "\xc0" => [92, "<"], "\xc1" => [95, "<"], "\xc2" => [137, "<"], "\xc3" => [142, "<"], "\xc4" => [150, "<"], "\xc5" => [74, "<"], "\xc6" => [90, "<"], "\xc7" => [98, "<"], "\xc8" => [107, "<"], "\xc9" => [140, "<"], "\xca" => [146, "<"], "\xcb" => [102, "<"], "\xcc" => [113, "<"], "\xcd" => [121, "<"], "\xce" => [128, "<"], "\xcf" => [12, "<"], "\xd0" => [92, "`"], "\xd1" => [95, "`"], "\xd2" => [137, "`"], "\xd3" => [142, "`"], "\xd4" => [150, "`"], "\xd5" => [74, "`"], "\xd6" => [90, "`"], "\xd7" => [98, "`"], "\xd8" => [107, "`"], "\xd9" => [140, "`"], "\xda" => [146, "`"], "\xdb" => [102, "`"], "\xdc" => [113, "`"], "\xdd" => [121, "`"], "\xde" => [128, "`"], "\xdf" => [12, "`"], "\xe0" => [92, "{"], "\xe1" => [95, "{"], "\xe2" => [137, "{"], "\xe3" => [142, "{"], "\xe4" => [150, "{"], "\xe5" => [74, "{"], "\xe6" => [90, "{"], "\xe7" => [98, "{"], "\xe8" => [107, "{"], "\xe9" => [140, "{"], "\xea" => [146, "{"], "\xeb" => [102, "{"], "\xec" => [113, "{"], "\xed" => [121, "{"], "\xee" => [128, "{"], "\xef" => [12, "{"], "\xf0" => [0, "\\"], "\xf1" => [0, "\xc3"], "\xf2" => [0, "\xd0"], "\xf3" => [155, null], "\xf4" => [162, null], "\xf5" => [211, null], "\xf6" => [248, null], "\xf7" => [183, null], "\xf8" => [204, null], "\xf9" => [243, null], "\xfa" => [159, null], "\xfb" => [187, null], "\xfc" => [208, null], "\xfd" => [29, null], "\xfe" => [177, null], "\xff" => [37, null]], ["\x00" => [0, "\xc60"], "\x01" => [0, "\xc61"], "\x02" => [0, "\xc62"], "\x03" => [0, "\xc6a"], "\x04" => [0, "\xc6c"], "\x05" => [0, "\xc6e"], "\x06" => [0, "\xc6i"], "\x07" => [0, "\xc6o"], "\x08" => [0, "\xc6s"], "\t" => [0, "\xc6t"], "\n" => [73, "\xc6"], "\v" => [88, "\xc6"], "\f" => [89, "\xc6"], "\r" => [96, "\xc6"], "\x0e" => [97, "\xc6"], "\x0f" => [99, "\xc6"], "\x10" => [106, "\xc6"], "\x11" => [136, "\xc6"], "\x12" => [139, "\xc6"], "\x13" => [141, "\xc6"], "\x14" => [145, "\xc6"], "\x15" => [147, "\xc6"], "\x16" => [149, "\xc6"], "\x17" => [101, "\xc6"], "\x18" => [112, "\xc6"], "\x19" => [117, "\xc6"], "\x1a" => [120, "\xc6"], "\x1b" => [124, "\xc6"], "\x1c" => [127, "\xc6"], "\x1d" => [144, "\xc6"], "\x1e" => [152, "\xc6"], "\x1f" => [11, "\xc6"], " " => [0, "\xe40"], "!" => [0, "\xe41"], "\"" => [0, "\xe42"], "#" => [0, "\xe4a"], "\$" => [0, "\xe4c"], "%" => [0, "\xe4e"], "&" => [0, "\xe4i"], "'" => [0, "\xe4o"], "(" => [0, "\xe4s"], ")" => [0, "\xe4t"], "*" => [73, "\xe4"], "+" => [88, "\xe4"], "," => [89, "\xe4"], "-" => [96, "\xe4"], "." => [97, "\xe4"], "/" => [99, "\xe4"], [106, "\xe4"], [136, "\xe4"], [139, "\xe4"], [141, "\xe4"], [145, "\xe4"], [147, "\xe4"], [149, "\xe4"], [101, "\xe4"], [112, "\xe4"], [117, "\xe4"], ":" => [120, "\xe4"], ";" => [124, "\xe4"], "<" => [127, "\xe4"], "=" => [144, "\xe4"], ">" => [152, "\xe4"], "?" => [11, "\xe4"], "@" => [0, "\xe80"], "A" => [0, "\xe81"], "B" => [0, "\xe82"], "C" => [0, "\xe8a"], "D" => [0, "\xe8c"], "E" => [0, "\xe8e"], "F" => [0, "\xe8i"], "G" => [0, "\xe8o"], "H" => [0, "\xe8s"], "I" => [0, "\xe8t"], "J" => [73, "\xe8"], "K" => [88, "\xe8"], "L" => [89, "\xe8"], "M" => [96, "\xe8"], "N" => [97, "\xe8"], "O" => [99, "\xe8"], "P" => [106, "\xe8"], "Q" => [136, "\xe8"], "R" => [139, "\xe8"], "S" => [141, "\xe8"], "T" => [145, "\xe8"], "U" => [147, "\xe8"], "V" => [149, "\xe8"], "W" => [101, "\xe8"], "X" => [112, "\xe8"], "Y" => [117, "\xe8"], "Z" => [120, "\xe8"], "[" => [124, "\xe8"], "\\" => [127, "\xe8"], "]" => [144, "\xe8"], "^" => [152, "\xe8"], "_" => [11, "\xe8"], "`" => [0, "\xe90"], "a" => [0, "\xe91"], "b" => [0, "\xe92"], "c" => [0, "\xe9a"], "d" => [0, "\xe9c"], "e" => [0, "\xe9e"], "f" => [0, "\xe9i"], "g" => [0, "\xe9o"], "h" => [0, "\xe9s"], "i" => [0, "\xe9t"], "j" => [73, "\xe9"], "k" => [88, "\xe9"], "l" => [89, "\xe9"], "m" => [96, "\xe9"], "n" => [97, "\xe9"], "o" => [99, "\xe9"], "p" => [106, "\xe9"], "q" => [136, "\xe9"], "r" => [139, "\xe9"], "s" => [141, "\xe9"], "t" => [145, "\xe9"], "u" => [147, "\xe9"], "v" => [149, "\xe9"], "w" => [101, "\xe9"], "x" => [112, "\xe9"], "y" => [117, "\xe9"], "z" => [120, "\xe9"], "{" => [124, "\xe9"], "|" => [127, "\xe9"], "}" => [144, "\xe9"], "~" => [152, "\xe9"], "" => [11, "\xe9"], "\x80" => [92, "\x01"], "\x81" => [95, "\x01"], "\x82" => [137, "\x01"], "\x83" => [142, "\x01"], "\x84" => [150, "\x01"], "\x85" => [74, "\x01"], "\x86" => [90, "\x01"], "\x87" => [98, "\x01"], "\x88" => [107, "\x01"], "\x89" => [140, "\x01"], "\x8a" => [146, "\x01"], "\x8b" => [102, "\x01"], "\x8c" => [113, "\x01"], "\x8d" => [121, "\x01"], "\x8e" => [128, "\x01"], "\x8f" => [12, "\x01"], "\x90" => [92, "\x87"], "\x91" => [95, "\x87"], "\x92" => [137, "\x87"], "\x93" => [142, "\x87"], "\x94" => [150, "\x87"], "\x95" => [74, "\x87"], "\x96" => [90, "\x87"], "\x97" => [98, "\x87"], "\x98" => [107, "\x87"], "\x99" => [140, "\x87"], "\x9a" => [146, "\x87"], "\x9b" => [102, "\x87"], "\x9c" => [113, "\x87"], "\x9d" => [121, "\x87"], "\x9e" => [128, "\x87"], "\x9f" => [12, "\x87"], "\xa0" => [92, "\x89"], "\xa1" => [95, "\x89"], "\xa2" => [137, "\x89"], "\xa3" => [142, "\x89"], "\xa4" => [150, "\x89"], "\xa5" => [74, "\x89"], "\xa6" => [90, "\x89"], "\xa7" => [98, "\x89"], "\xa8" => [107, "\x89"], "\xa9" => [140, "\x89"], "\xaa" => [146, "\x89"], "\xab" => [102, "\x89"], "\xac" => [113, "\x89"], "\xad" => [121, "\x89"], "\xae" => [128, "\x89"], "\xaf" => [12, "\x89"], "\xb0" => [92, "\x8a"], "\xb1" => [95, "\x8a"], "\xb2" => [137, "\x8a"], "\xb3" => [142, "\x8a"], "\xb4" => [150, "\x8a"], "\xb5" => [74, "\x8a"], "\xb6" => [90, "\x8a"], "\xb7" => [98, "\x8a"], "\xb8" => [107, "\x8a"], "\xb9" => [140, "\x8a"], "\xba" => [146, "\x8a"], "\xbb" => [102, "\x8a"], "\xbc" => [113, "\x8a"], "\xbd" => [121, "\x8a"], "\xbe" => [128, "\x8a"], "\xbf" => [12, "\x8a"], "\xc0" => [92, "\x8b"], "\xc1" => [95, "\x8b"], "\xc2" => [137, "\x8b"], "\xc3" => [142, "\x8b"], "\xc4" => [150, "\x8b"], "\xc5" => [74, "\x8b"], "\xc6" => [90, "\x8b"], "\xc7" => [98, "\x8b"], "\xc8" => [107, "\x8b"], "\xc9" => [140, "\x8b"], "\xca" => [146, "\x8b"], "\xcb" => [102, "\x8b"], "\xcc" => [113, "\x8b"], "\xcd" => [121, "\x8b"], "\xce" => [128, "\x8b"], "\xcf" => [12, "\x8b"], "\xd0" => [92, "\x8c"], "\xd1" => [95, "\x8c"], "\xd2" => [137, "\x8c"], "\xd3" => [142, "\x8c"], "\xd4" => [150, "\x8c"], "\xd5" => [74, "\x8c"], "\xd6" => [90, "\x8c"], "\xd7" => [98, "\x8c"], "\xd8" => [107, "\x8c"], "\xd9" => [140, "\x8c"], "\xda" => [146, "\x8c"], "\xdb" => [102, "\x8c"], "\xdc" => [113, "\x8c"], "\xdd" => [121, "\x8c"], "\xde" => [128, "\x8c"], "\xdf" => [12, "\x8c"], "\xe0" => [92, "\x8d"], "\xe1" => [95, "\x8d"], "\xe2" => [137, "\x8d"], "\xe3" => [142, "\x8d"], "\xe4" => [150, "\x8d"], "\xe5" => [74, "\x8d"], "\xe6" => [90, "\x8d"], "\xe7" => [98, "\x8d"], "\xe8" => [107, "\x8d"], "\xe9" => [140, "\x8d"], "\xea" => [146, "\x8d"], "\xeb" => [102, "\x8d"], "\xec" => [113, "\x8d"], "\xed" => [121, "\x8d"], "\xee" => [128, "\x8d"], "\xef" => [12, "\x8d"], "\xf0" => [92, "\x8f"], "\xf1" => [95, "\x8f"], "\xf2" => [137, "\x8f"], "\xf3" => [142, "\x8f"], "\xf4" => [150, "\x8f"], "\xf5" => [74, "\x8f"], "\xf6" => [90, "\x8f"], "\xf7" => [98, "\x8f"], "\xf8" => [107, "\x8f"], "\xf9" => [140, "\x8f"], "\xfa" => [146, "\x8f"], "\xfb" => [102, "\x8f"], "\xfc" => [113, "\x8f"], "\xfd" => [121, "\x8f"], "\xfe" => [128, "\x8f"], "\xff" => [12, "\x8f"]], ["\x00" => [92, "\xb2"], "\x01" => [95, "\xb2"], "\x02" => [137, "\xb2"], "\x03" => [142, "\xb2"], "\x04" => [150, "\xb2"], "\x05" => [74, "\xb2"], "\x06" => [90, "\xb2"], "\x07" => [98, "\xb2"], "\x08" => [107, "\xb2"], "\t" => [140, "\xb2"], "\n" => [146, "\xb2"], "\v" => [102, "\xb2"], "\f" => [113, "\xb2"], "\r" => [121, "\xb2"], "\x0e" => [128, "\xb2"], "\x0f" => [12, "\xb2"], "\x10" => [92, "\xb5"], "\x11" => [95, "\xb5"], "\x12" => [137, "\xb5"], "\x13" => [142, "\xb5"], "\x14" => [150, "\xb5"], "\x15" => [74, "\xb5"], "\x16" => [90, "\xb5"], "\x17" => [98, "\xb5"], "\x18" => [107, "\xb5"], "\x19" => [140, "\xb5"], "\x1a" => [146, "\xb5"], "\x1b" => [102, "\xb5"], "\x1c" => [113, "\xb5"], "\x1d" => [121, "\xb5"], "\x1e" => [128, "\xb5"], "\x1f" => [12, "\xb5"], " " => [92, "\xb9"], "!" => [95, "\xb9"], "\"" => [137, "\xb9"], "#" => [142, "\xb9"], "\$" => [150, "\xb9"], "%" => [74, "\xb9"], "&" => [90, "\xb9"], "'" => [98, "\xb9"], "(" => [107, "\xb9"], ")" => [140, "\xb9"], "*" => [146, "\xb9"], "+" => [102, "\xb9"], "," => [113, "\xb9"], "-" => [121, "\xb9"], "." => [128, "\xb9"], "/" => [12, "\xb9"], [92, "\xba"], [95, "\xba"], [137, "\xba"], [142, "\xba"], [150, "\xba"], [74, "\xba"], [90, "\xba"], [98, "\xba"], [107, "\xba"], [140, "\xba"], ":" => [146, "\xba"], ";" => [102, "\xba"], "<" => [113, "\xba"], "=" => [121, "\xba"], ">" => [128, "\xba"], "?" => [12, "\xba"], "@" => [92, "\xbb"], "A" => [95, "\xbb"], "B" => [137, "\xbb"], "C" => [142, "\xbb"], "D" => [150, "\xbb"], "E" => [74, "\xbb"], "F" => [90, "\xbb"], "G" => [98, "\xbb"], "H" => [107, "\xbb"], "I" => [140, "\xbb"], "J" => [146, "\xbb"], "K" => [102, "\xbb"], "L" => [113, "\xbb"], "M" => [121, "\xbb"], "N" => [128, "\xbb"], "O" => [12, "\xbb"], "P" => [92, "\xbd"], "Q" => [95, "\xbd"], "R" => [137, "\xbd"], "S" => [142, "\xbd"], "T" => [150, "\xbd"], "U" => [74, "\xbd"], "V" => [90, "\xbd"], "W" => [98, "\xbd"], "X" => [107, "\xbd"], "Y" => [140, "\xbd"], "Z" => [146, "\xbd"], "[" => [102, "\xbd"], "\\" => [113, "\xbd"], "]" => [121, "\xbd"], "^" => [128, "\xbd"], "_" => [12, "\xbd"], "`" => [92, "\xbe"], "a" => [95, "\xbe"], "b" => [137, "\xbe"], "c" => [142, "\xbe"], "d" => [150, "\xbe"], "e" => [74, "\xbe"], "f" => [90, "\xbe"], "g" => [98, "\xbe"], "h" => [107, "\xbe"], "i" => [140, "\xbe"], "j" => [146, "\xbe"], "k" => [102, "\xbe"], "l" => [113, "\xbe"], "m" => [121, "\xbe"], "n" => [128, "\xbe"], "o" => [12, "\xbe"], "p" => [92, "\xc4"], "q" => [95, "\xc4"], "r" => [137, "\xc4"], "s" => [142, "\xc4"], "t" => [150, "\xc4"], "u" => [74, "\xc4"], "v" => [90, "\xc4"], "w" => [98, "\xc4"], "x" => [107, "\xc4"], "y" => [140, "\xc4"], "z" => [146, "\xc4"], "{" => [102, "\xc4"], "|" => [113, "\xc4"], "}" => [121, "\xc4"], "~" => [128, "\xc4"], "" => [12, "\xc4"], "\x80" => [92, "\xc6"], "\x81" => [95, "\xc6"], "\x82" => [137, "\xc6"], "\x83" => [142, "\xc6"], "\x84" => [150, "\xc6"], "\x85" => [74, "\xc6"], "\x86" => [90, "\xc6"], "\x87" => [98, "\xc6"], "\x88" => [107, "\xc6"], "\x89" => [140, "\xc6"], "\x8a" => [146, "\xc6"], "\x8b" => [102, "\xc6"], "\x8c" => [113, "\xc6"], "\x8d" => [121, "\xc6"], "\x8e" => [128, "\xc6"], "\x8f" => [12, "\xc6"], "\x90" => [92, "\xe4"], "\x91" => [95, "\xe4"], "\x92" => [137, "\xe4"], "\x93" => [142, "\xe4"], "\x94" => [150, "\xe4"], "\x95" => [74, "\xe4"], "\x96" => [90, "\xe4"], "\x97" => [98, "\xe4"], "\x98" => [107, "\xe4"], "\x99" => [140, "\xe4"], "\x9a" => [146, "\xe4"], "\x9b" => [102, "\xe4"], "\x9c" => [113, "\xe4"], "\x9d" => [121, "\xe4"], "\x9e" => [128, "\xe4"], "\x9f" => [12, "\xe4"], "\xa0" => [92, "\xe8"], "\xa1" => [95, "\xe8"], "\xa2" => [137, "\xe8"], "\xa3" => [142, "\xe8"], "\xa4" => [150, "\xe8"], "\xa5" => [74, "\xe8"], "\xa6" => [90, "\xe8"], "\xa7" => [98, "\xe8"], "\xa8" => [107, "\xe8"], "\xa9" => [140, "\xe8"], "\xaa" => [146, "\xe8"], "\xab" => [102, "\xe8"], "\xac" => [113, "\xe8"], "\xad" => [121, "\xe8"], "\xae" => [128, "\xe8"], "\xaf" => [12, "\xe8"], "\xb0" => [92, "\xe9"], "\xb1" => [95, "\xe9"], "\xb2" => [137, "\xe9"], "\xb3" => [142, "\xe9"], "\xb4" => [150, "\xe9"], "\xb5" => [74, "\xe9"], "\xb6" => [90, "\xe9"], "\xb7" => [98, "\xe9"], "\xb8" => [107, "\xe9"], "\xb9" => [140, "\xe9"], "\xba" => [146, "\xe9"], "\xbb" => [102, "\xe9"], "\xbc" => [113, "\xe9"], "\xbd" => [121, "\xe9"], "\xbe" => [128, "\xe9"], "\xbf" => [12, "\xe9"], "\xc0" => [93, "\x01"], "\xc1" => [138, "\x01"], "\xc2" => [75, "\x01"], "\xc3" => [91, "\x01"], "\xc4" => [108, "\x01"], "\xc5" => [103, "\x01"], "\xc6" => [114, "\x01"], "\xc7" => [14, "\x01"], "\xc8" => [93, "\x87"], "\xc9" => [138, "\x87"], "\xca" => [75, "\x87"], "\xcb" => [91, "\x87"], "\xcc" => [108, "\x87"], "\xcd" => [103, "\x87"], "\xce" => [114, "\x87"], "\xcf" => [14, "\x87"], "\xd0" => [93, "\x89"], "\xd1" => [138, "\x89"], "\xd2" => [75, "\x89"], "\xd3" => [91, "\x89"], "\xd4" => [108, "\x89"], "\xd5" => [103, "\x89"], "\xd6" => [114, "\x89"], "\xd7" => [14, "\x89"], "\xd8" => [93, "\x8a"], "\xd9" => [138, "\x8a"], "\xda" => [75, "\x8a"], "\xdb" => [91, "\x8a"], "\xdc" => [108, "\x8a"], "\xdd" => [103, "\x8a"], "\xde" => [114, "\x8a"], "\xdf" => [14, "\x8a"], "\xe0" => [93, "\x8b"], "\xe1" => [138, "\x8b"], "\xe2" => [75, "\x8b"], "\xe3" => [91, "\x8b"], "\xe4" => [108, "\x8b"], "\xe5" => [103, "\x8b"], "\xe6" => [114, "\x8b"], "\xe7" => [14, "\x8b"], "\xe8" => [93, "\x8c"], "\xe9" => [138, "\x8c"], "\xea" => [75, "\x8c"], "\xeb" => [91, "\x8c"], "\xec" => [108, "\x8c"], "\xed" => [103, "\x8c"], "\xee" => [114, "\x8c"], "\xef" => [14, "\x8c"], "\xf0" => [93, "\x8d"], "\xf1" => [138, "\x8d"], "\xf2" => [75, "\x8d"], "\xf3" => [91, "\x8d"], "\xf4" => [108, "\x8d"], "\xf5" => [103, "\x8d"], "\xf6" => [114, "\x8d"], "\xf7" => [14, "\x8d"], "\xf8" => [93, "\x8f"], "\xf9" => [138, "\x8f"], "\xfa" => [75, "\x8f"], "\xfb" => [91, "\x8f"], "\xfc" => [108, "\x8f"], "\xfd" => [103, "\x8f"], "\xfe" => [114, "\x8f"], "\xff" => [14, "\x8f"]], ["\x00" => [93, "\xb2"], "\x01" => [138, "\xb2"], "\x02" => [75, "\xb2"], "\x03" => [91, "\xb2"], "\x04" => [108, "\xb2"], "\x05" => [103, "\xb2"], "\x06" => [114, "\xb2"], "\x07" => [14, "\xb2"], "\x08" => [93, "\xb5"], "\t" => [138, "\xb5"], "\n" => [75, "\xb5"], "\v" => [91, "\xb5"], "\f" => [108, "\xb5"], "\r" => [103, "\xb5"], "\x0e" => [114, "\xb5"], "\x0f" => [14, "\xb5"], "\x10" => [93, "\xb9"], "\x11" => [138, "\xb9"], "\x12" => [75, "\xb9"], "\x13" => [91, "\xb9"], "\x14" => [108, "\xb9"], "\x15" => [103, "\xb9"], "\x16" => [114, "\xb9"], "\x17" => [14, "\xb9"], "\x18" => [93, "\xba"], "\x19" => [138, "\xba"], "\x1a" => [75, "\xba"], "\x1b" => [91, "\xba"], "\x1c" => [108, "\xba"], "\x1d" => [103, "\xba"], "\x1e" => [114, "\xba"], "\x1f" => [14, "\xba"], " " => [93, "\xbb"], "!" => [138, "\xbb"], "\"" => [75, "\xbb"], "#" => [91, "\xbb"], "\$" => [108, "\xbb"], "%" => [103, "\xbb"], "&" => [114, "\xbb"], "'" => [14, "\xbb"], "(" => [93, "\xbd"], ")" => [138, "\xbd"], "*" => [75, "\xbd"], "+" => [91, "\xbd"], "," => [108, "\xbd"], "-" => [103, "\xbd"], "." => [114, "\xbd"], "/" => [14, "\xbd"], [93, "\xbe"], [138, "\xbe"], [75, "\xbe"], [91, "\xbe"], [108, "\xbe"], [103, "\xbe"], [114, "\xbe"], [14, "\xbe"], [93, "\xc4"], [138, "\xc4"], ":" => [75, "\xc4"], ";" => [91, "\xc4"], "<" => [108, "\xc4"], "=" => [103, "\xc4"], ">" => [114, "\xc4"], "?" => [14, "\xc4"], "@" => [93, "\xc6"], "A" => [138, "\xc6"], "B" => [75, "\xc6"], "C" => [91, "\xc6"], "D" => [108, "\xc6"], "E" => [103, "\xc6"], "F" => [114, "\xc6"], "G" => [14, "\xc6"], "H" => [93, "\xe4"], "I" => [138, "\xe4"], "J" => [75, "\xe4"], "K" => [91, "\xe4"], "L" => [108, "\xe4"], "M" => [103, "\xe4"], "N" => [114, "\xe4"], "O" => [14, "\xe4"], "P" => [93, "\xe8"], "Q" => [138, "\xe8"], "R" => [75, "\xe8"], "S" => [91, "\xe8"], "T" => [108, "\xe8"], "U" => [103, "\xe8"], "V" => [114, "\xe8"], "W" => [14, "\xe8"], "X" => [93, "\xe9"], "Y" => [138, "\xe9"], "Z" => [75, "\xe9"], "[" => [91, "\xe9"], "\\" => [108, "\xe9"], "]" => [103, "\xe9"], "^" => [114, "\xe9"], "_" => [14, "\xe9"], "`" => [94, "\x01"], "a" => [76, "\x01"], "b" => [104, "\x01"], "c" => [16, "\x01"], "d" => [94, "\x87"], "e" => [76, "\x87"], "f" => [104, "\x87"], "g" => [16, "\x87"], "h" => [94, "\x89"], "i" => [76, "\x89"], "j" => [104, "\x89"], "k" => [16, "\x89"], "l" => [94, "\x8a"], "m" => [76, "\x8a"], "n" => [104, "\x8a"], "o" => [16, "\x8a"], "p" => [94, "\x8b"], "q" => [76, "\x8b"], "r" => [104, "\x8b"], "s" => [16, "\x8b"], "t" => [94, "\x8c"], "u" => [76, "\x8c"], "v" => [104, "\x8c"], "w" => [16, "\x8c"], "x" => [94, "\x8d"], "y" => [76, "\x8d"], "z" => [104, "\x8d"], "{" => [16, "\x8d"], "|" => [94, "\x8f"], "}" => [76, "\x8f"], "~" => [104, "\x8f"], "" => [16, "\x8f"], "\x80" => [94, "\x93"], "\x81" => [76, "\x93"], "\x82" => [104, "\x93"], "\x83" => [16, "\x93"], "\x84" => [94, "\x95"], "\x85" => [76, "\x95"], "\x86" => [104, "\x95"], "\x87" => [16, "\x95"], "\x88" => [94, "\x96"], "\x89" => [76, "\x96"], "\x8a" => [104, "\x96"], "\x8b" => [16, "\x96"], "\x8c" => [94, "\x97"], "\x8d" => [76, "\x97"], "\x8e" => [104, "\x97"], "\x8f" => [16, "\x97"], "\x90" => [94, "\x98"], "\x91" => [76, "\x98"], "\x92" => [104, "\x98"], "\x93" => [16, "\x98"], "\x94" => [94, "\x9b"], "\x95" => [76, "\x9b"], "\x96" => [104, "\x9b"], "\x97" => [16, "\x9b"], "\x98" => [94, "\x9d"], "\x99" => [76, "\x9d"], "\x9a" => [104, "\x9d"], "\x9b" => [16, "\x9d"], "\x9c" => [94, "\x9e"], "\x9d" => [76, "\x9e"], "\x9e" => [104, "\x9e"], "\x9f" => [16, "\x9e"], "\xa0" => [94, "\xa5"], "\xa1" => [76, "\xa5"], "\xa2" => [104, "\xa5"], "\xa3" => [16, "\xa5"], "\xa4" => [94, "\xa6"], "\xa5" => [76, "\xa6"], "\xa6" => [104, "\xa6"], "\xa7" => [16, "\xa6"], "\xa8" => [94, "\xa8"], "\xa9" => [76, "\xa8"], "\xaa" => [104, "\xa8"], "\xab" => [16, "\xa8"], "\xac" => [94, "\xae"], "\xad" => [76, "\xae"], "\xae" => [104, "\xae"], "\xaf" => [16, "\xae"], "\xb0" => [94, "\xaf"], "\xb1" => [76, "\xaf"], "\xb2" => [104, "\xaf"], "\xb3" => [16, "\xaf"], "\xb4" => [94, "\xb4"], "\xb5" => [76, "\xb4"], "\xb6" => [104, "\xb4"], "\xb7" => [16, "\xb4"], "\xb8" => [94, "\xb6"], "\xb9" => [76, "\xb6"], "\xba" => [104, "\xb6"], "\xbb" => [16, "\xb6"], "\xbc" => [94, "\xb7"], "\xbd" => [76, "\xb7"], "\xbe" => [104, "\xb7"], "\xbf" => [16, "\xb7"], "\xc0" => [94, "\xbc"], "\xc1" => [76, "\xbc"], "\xc2" => [104, "\xbc"], "\xc3" => [16, "\xbc"], "\xc4" => [94, "\xbf"], "\xc5" => [76, "\xbf"], "\xc6" => [104, "\xbf"], "\xc7" => [16, "\xbf"], "\xc8" => [94, "\xc5"], "\xc9" => [76, "\xc5"], "\xca" => [104, "\xc5"], "\xcb" => [16, "\xc5"], "\xcc" => [94, "\xe7"], "\xcd" => [76, "\xe7"], "\xce" => [104, "\xe7"], "\xcf" => [16, "\xe7"], "\xd0" => [94, "\xef"], "\xd1" => [76, "\xef"], "\xd2" => [104, "\xef"], "\xd3" => [16, "\xef"], "\xd4" => [77, "\t"], "\xd5" => [18, "\t"], "\xd6" => [77, "\x8e"], "\xd7" => [18, "\x8e"], "\xd8" => [77, "\x90"], "\xd9" => [18, "\x90"], "\xda" => [77, "\x91"], "\xdb" => [18, "\x91"], "\xdc" => [77, "\x94"], "\xdd" => [18, "\x94"], "\xde" => [77, "\x9f"], "\xdf" => [18, "\x9f"], "\xe0" => [77, "\xab"], "\xe1" => [18, "\xab"], "\xe2" => [77, "\xce"], "\xe3" => [18, "\xce"], "\xe4" => [77, "\xd7"], "\xe5" => [18, "\xd7"], "\xe6" => [77, "\xe1"], "\xe7" => [18, "\xe1"], "\xe8" => [77, "\xec"], "\xe9" => [18, "\xec"], "\xea" => [77, "\xed"], "\xeb" => [18, "\xed"], "\xec" => [0, "\xc7"], "\xed" => [0, "\xcf"], "\xee" => [0, "\xea"], "\xef" => [0, "\xeb"], "\xf0" => [221, null], "\xf1" => [228, null], "\xf2" => [230, null], "\xf3" => [235, null], "\xf4" => [245, null], "\xf5" => [253, null], "\xf6" => [255, null], "\xf7" => [234, null], "\xf8" => [239, null], "\xf9" => [247, null], "\xfa" => [258, null], "\xfb" => [261, null], "\xfc" => [41, null], "\xfd" => [47, null], "\xfe" => [64, null], "\xff" => [57, null]], ["\x00" => [0, "\xfe0"], "\x01" => [0, "\xfe1"], "\x02" => [0, "\xfe2"], "\x03" => [0, "\xfea"], "\x04" => [0, "\xfec"], "\x05" => [0, "\xfee"], "\x06" => [0, "\xfei"], "\x07" => [0, "\xfeo"], "\x08" => [0, "\xfes"], "\t" => [0, "\xfet"], "\n" => [73, "\xfe"], "\v" => [88, "\xfe"], "\f" => [89, "\xfe"], "\r" => [96, "\xfe"], "\x0e" => [97, "\xfe"], "\x0f" => [99, "\xfe"], "\x10" => [106, "\xfe"], "\x11" => [136, "\xfe"], "\x12" => [139, "\xfe"], "\x13" => [141, "\xfe"], "\x14" => [145, "\xfe"], "\x15" => [147, "\xfe"], "\x16" => [149, "\xfe"], "\x17" => [101, "\xfe"], "\x18" => [112, "\xfe"], "\x19" => [117, "\xfe"], "\x1a" => [120, "\xfe"], "\x1b" => [124, "\xfe"], "\x1c" => [127, "\xfe"], "\x1d" => [144, "\xfe"], "\x1e" => [152, "\xfe"], "\x1f" => [11, "\xfe"], " " => [92, "\x02"], "!" => [95, "\x02"], "\"" => [137, "\x02"], "#" => [142, "\x02"], "\$" => [150, "\x02"], "%" => [74, "\x02"], "&" => [90, "\x02"], "'" => [98, "\x02"], "(" => [107, "\x02"], ")" => [140, "\x02"], "*" => [146, "\x02"], "+" => [102, "\x02"], "," => [113, "\x02"], "-" => [121, "\x02"], "." => [128, "\x02"], "/" => [12, "\x02"], [92, "\x03"], [95, "\x03"], [137, "\x03"], [142, "\x03"], [150, "\x03"], [74, "\x03"], [90, "\x03"], [98, "\x03"], [107, "\x03"], [140, "\x03"], ":" => [146, "\x03"], ";" => [102, "\x03"], "<" => [113, "\x03"], "=" => [121, "\x03"], ">" => [128, "\x03"], "?" => [12, "\x03"], "@" => [92, "\x04"], "A" => [95, "\x04"], "B" => [137, "\x04"], "C" => [142, "\x04"], "D" => [150, "\x04"], "E" => [74, "\x04"], "F" => [90, "\x04"], "G" => [98, "\x04"], "H" => [107, "\x04"], "I" => [140, "\x04"], "J" => [146, "\x04"], "K" => [102, "\x04"], "L" => [113, "\x04"], "M" => [121, "\x04"], "N" => [128, "\x04"], "O" => [12, "\x04"], "P" => [92, "\x05"], "Q" => [95, "\x05"], "R" => [137, "\x05"], "S" => [142, "\x05"], "T" => [150, "\x05"], "U" => [74, "\x05"], "V" => [90, "\x05"], "W" => [98, "\x05"], "X" => [107, "\x05"], "Y" => [140, "\x05"], "Z" => [146, "\x05"], "[" => [102, "\x05"], "\\" => [113, "\x05"], "]" => [121, "\x05"], "^" => [128, "\x05"], "_" => [12, "\x05"], "`" => [92, "\x06"], "a" => [95, "\x06"], "b" => [137, "\x06"], "c" => [142, "\x06"], "d" => [150, "\x06"], "e" => [74, "\x06"], "f" => [90, "\x06"], "g" => [98, "\x06"], "h" => [107, "\x06"], "i" => [140, "\x06"], "j" => [146, "\x06"], "k" => [102, "\x06"], "l" => [113, "\x06"], "m" => [121, "\x06"], "n" => [128, "\x06"], "o" => [12, "\x06"], "p" => [92, "\x07"], "q" => [95, "\x07"], "r" => [137, "\x07"], "s" => [142, "\x07"], "t" => [150, "\x07"], "u" => [74, "\x07"], "v" => [90, "\x07"], "w" => [98, "\x07"], "x" => [107, "\x07"], "y" => [140, "\x07"], "z" => [146, "\x07"], "{" => [102, "\x07"], "|" => [113, "\x07"], "}" => [121, "\x07"], "~" => [128, "\x07"], "" => [12, "\x07"], "\x80" => [92, "\x08"], "\x81" => [95, "\x08"], "\x82" => [137, "\x08"], "\x83" => [142, "\x08"], "\x84" => [150, "\x08"], "\x85" => [74, "\x08"], "\x86" => [90, "\x08"], "\x87" => [98, "\x08"], "\x88" => [107, "\x08"], "\x89" => [140, "\x08"], "\x8a" => [146, "\x08"], "\x8b" => [102, "\x08"], "\x8c" => [113, "\x08"], "\x8d" => [121, "\x08"], "\x8e" => [128, "\x08"], "\x8f" => [12, "\x08"], "\x90" => [92, "\v"], "\x91" => [95, "\v"], "\x92" => [137, "\v"], "\x93" => [142, "\v"], "\x94" => [150, "\v"], "\x95" => [74, "\v"], "\x96" => [90, "\v"], "\x97" => [98, "\v"], "\x98" => [107, "\v"], "\x99" => [140, "\v"], "\x9a" => [146, "\v"], "\x9b" => [102, "\v"], "\x9c" => [113, "\v"], "\x9d" => [121, "\v"], "\x9e" => [128, "\v"], "\x9f" => [12, "\v"], "\xa0" => [92, "\f"], "\xa1" => [95, "\f"], "\xa2" => [137, "\f"], "\xa3" => [142, "\f"], "\xa4" => [150, "\f"], "\xa5" => [74, "\f"], "\xa6" => [90, "\f"], "\xa7" => [98, "\f"], "\xa8" => [107, "\f"], "\xa9" => [140, "\f"], "\xaa" => [146, "\f"], "\xab" => [102, "\f"], "\xac" => [113, "\f"], "\xad" => [121, "\f"], "\xae" => [128, "\f"], "\xaf" => [12, "\f"], "\xb0" => [92, "\x0e"], "\xb1" => [95, "\x0e"], "\xb2" => [137, "\x0e"], "\xb3" => [142, "\x0e"], "\xb4" => [150, "\x0e"], "\xb5" => [74, "\x0e"], "\xb6" => [90, "\x0e"], "\xb7" => [98, "\x0e"], "\xb8" => [107, "\x0e"], "\xb9" => [140, "\x0e"], "\xba" => [146, "\x0e"], "\xbb" => [102, "\x0e"], "\xbc" => [113, "\x0e"], "\xbd" => [121, "\x0e"], "\xbe" => [128, "\x0e"], "\xbf" => [12, "\x0e"], "\xc0" => [92, "\x0f"], "\xc1" => [95, "\x0f"], "\xc2" => [137, "\x0f"], "\xc3" => [142, "\x0f"], "\xc4" => [150, "\x0f"], "\xc5" => [74, "\x0f"], "\xc6" => [90, "\x0f"], "\xc7" => [98, "\x0f"], "\xc8" => [107, "\x0f"], "\xc9" => [140, "\x0f"], "\xca" => [146, "\x0f"], "\xcb" => [102, "\x0f"], "\xcc" => [113, "\x0f"], "\xcd" => [121, "\x0f"], "\xce" => [128, "\x0f"], "\xcf" => [12, "\x0f"], "\xd0" => [92, "\x10"], "\xd1" => [95, "\x10"], "\xd2" => [137, "\x10"], "\xd3" => [142, "\x10"], "\xd4" => [150, "\x10"], "\xd5" => [74, "\x10"], "\xd6" => [90, "\x10"], "\xd7" => [98, "\x10"], "\xd8" => [107, "\x10"], "\xd9" => [140, "\x10"], "\xda" => [146, "\x10"], "\xdb" => [102, "\x10"], "\xdc" => [113, "\x10"], "\xdd" => [121, "\x10"], "\xde" => [128, "\x10"], "\xdf" => [12, "\x10"], "\xe0" => [92, "\x11"], "\xe1" => [95, "\x11"], "\xe2" => [137, "\x11"], "\xe3" => [142, "\x11"], "\xe4" => [150, "\x11"], "\xe5" => [74, "\x11"], "\xe6" => [90, "\x11"], "\xe7" => [98, "\x11"], "\xe8" => [107, "\x11"], "\xe9" => [140, "\x11"], "\xea" => [146, "\x11"], "\xeb" => [102, "\x11"], "\xec" => [113, "\x11"], "\xed" => [121, "\x11"], "\xee" => [128, "\x11"], "\xef" => [12, "\x11"], "\xf0" => [92, "\x12"], "\xf1" => [95, "\x12"], "\xf2" => [137, "\x12"], "\xf3" => [142, "\x12"], "\xf4" => [150, "\x12"], "\xf5" => [74, "\x12"], "\xf6" => [90, "\x12"], "\xf7" => [98, "\x12"], "\xf8" => [107, "\x12"], "\xf9" => [140, "\x12"], "\xfa" => [146, "\x12"], "\xfb" => [102, "\x12"], "\xfc" => [113, "\x12"], "\xfd" => [121, "\x12"], "\xfe" => [128, "\x12"], "\xff" => [12, "\x12"]], ["\x00" => [92, "\xfe"], "\x01" => [95, "\xfe"], "\x02" => [137, "\xfe"], "\x03" => [142, "\xfe"], "\x04" => [150, "\xfe"], "\x05" => [74, "\xfe"], "\x06" => [90, "\xfe"], "\x07" => [98, "\xfe"], "\x08" => [107, "\xfe"], "\t" => [140, "\xfe"], "\n" => [146, "\xfe"], "\v" => [102, "\xfe"], "\f" => [113, "\xfe"], "\r" => [121, "\xfe"], "\x0e" => [128, "\xfe"], "\x0f" => [12, "\xfe"], "\x10" => [93, "\x02"], "\x11" => [138, "\x02"], "\x12" => [75, "\x02"], "\x13" => [91, "\x02"], "\x14" => [108, "\x02"], "\x15" => [103, "\x02"], "\x16" => [114, "\x02"], "\x17" => [14, "\x02"], "\x18" => [93, "\x03"], "\x19" => [138, "\x03"], "\x1a" => [75, "\x03"], "\x1b" => [91, "\x03"], "\x1c" => [108, "\x03"], "\x1d" => [103, "\x03"], "\x1e" => [114, "\x03"], "\x1f" => [14, "\x03"], " " => [93, "\x04"], "!" => [138, "\x04"], "\"" => [75, "\x04"], "#" => [91, "\x04"], "\$" => [108, "\x04"], "%" => [103, "\x04"], "&" => [114, "\x04"], "'" => [14, "\x04"], "(" => [93, "\x05"], ")" => [138, "\x05"], "*" => [75, "\x05"], "+" => [91, "\x05"], "," => [108, "\x05"], "-" => [103, "\x05"], "." => [114, "\x05"], "/" => [14, "\x05"], [93, "\x06"], [138, "\x06"], [75, "\x06"], [91, "\x06"], [108, "\x06"], [103, "\x06"], [114, "\x06"], [14, "\x06"], [93, "\x07"], [138, "\x07"], ":" => [75, "\x07"], ";" => [91, "\x07"], "<" => [108, "\x07"], "=" => [103, "\x07"], ">" => [114, "\x07"], "?" => [14, "\x07"], "@" => [93, "\x08"], "A" => [138, "\x08"], "B" => [75, "\x08"], "C" => [91, "\x08"], "D" => [108, "\x08"], "E" => [103, "\x08"], "F" => [114, "\x08"], "G" => [14, "\x08"], "H" => [93, "\v"], "I" => [138, "\v"], "J" => [75, "\v"], "K" => [91, "\v"], "L" => [108, "\v"], "M" => [103, "\v"], "N" => [114, "\v"], "O" => [14, "\v"], "P" => [93, "\f"], "Q" => [138, "\f"], "R" => [75, "\f"], "S" => [91, "\f"], "T" => [108, "\f"], "U" => [103, "\f"], "V" => [114, "\f"], "W" => [14, "\f"], "X" => [93, "\x0e"], "Y" => [138, "\x0e"], "Z" => [75, "\x0e"], "[" => [91, "\x0e"], "\\" => [108, "\x0e"], "]" => [103, "\x0e"], "^" => [114, "\x0e"], "_" => [14, "\x0e"], "`" => [93, "\x0f"], "a" => [138, "\x0f"], "b" => [75, "\x0f"], "c" => [91, "\x0f"], "d" => [108, "\x0f"], "e" => [103, "\x0f"], "f" => [114, "\x0f"], "g" => [14, "\x0f"], "h" => [93, "\x10"], "i" => [138, "\x10"], "j" => [75, "\x10"], "k" => [91, "\x10"], "l" => [108, "\x10"], "m" => [103, "\x10"], "n" => [114, "\x10"], "o" => [14, "\x10"], "p" => [93, "\x11"], "q" => [138, "\x11"], "r" => [75, "\x11"], "s" => [91, "\x11"], "t" => [108, "\x11"], "u" => [103, "\x11"], "v" => [114, "\x11"], "w" => [14, "\x11"], "x" => [93, "\x12"], "y" => [138, "\x12"], "z" => [75, "\x12"], "{" => [91, "\x12"], "|" => [108, "\x12"], "}" => [103, "\x12"], "~" => [114, "\x12"], "" => [14, "\x12"], "\x80" => [93, "\x13"], "\x81" => [138, "\x13"], "\x82" => [75, "\x13"], "\x83" => [91, "\x13"], "\x84" => [108, "\x13"], "\x85" => [103, "\x13"], "\x86" => [114, "\x13"], "\x87" => [14, "\x13"], "\x88" => [93, "\x14"], "\x89" => [138, "\x14"], "\x8a" => [75, "\x14"], "\x8b" => [91, "\x14"], "\x8c" => [108, "\x14"], "\x8d" => [103, "\x14"], "\x8e" => [114, "\x14"], "\x8f" => [14, "\x14"], "\x90" => [93, "\x15"], "\x91" => [138, "\x15"], "\x92" => [75, "\x15"], "\x93" => [91, "\x15"], "\x94" => [108, "\x15"], "\x95" => [103, "\x15"], "\x96" => [114, "\x15"], "\x97" => [14, "\x15"], "\x98" => [93, "\x17"], "\x99" => [138, "\x17"], "\x9a" => [75, "\x17"], "\x9b" => [91, "\x17"], "\x9c" => [108, "\x17"], "\x9d" => [103, "\x17"], "\x9e" => [114, "\x17"], "\x9f" => [14, "\x17"], "\xa0" => [93, "\x18"], "\xa1" => [138, "\x18"], "\xa2" => [75, "\x18"], "\xa3" => [91, "\x18"], "\xa4" => [108, "\x18"], "\xa5" => [103, "\x18"], "\xa6" => [114, "\x18"], "\xa7" => [14, "\x18"], "\xa8" => [93, "\x19"], "\xa9" => [138, "\x19"], "\xaa" => [75, "\x19"], "\xab" => [91, "\x19"], "\xac" => [108, "\x19"], "\xad" => [103, "\x19"], "\xae" => [114, "\x19"], "\xaf" => [14, "\x19"], "\xb0" => [93, "\x1a"], "\xb1" => [138, "\x1a"], "\xb2" => [75, "\x1a"], "\xb3" => [91, "\x1a"], "\xb4" => [108, "\x1a"], "\xb5" => [103, "\x1a"], "\xb6" => [114, "\x1a"], "\xb7" => [14, "\x1a"], "\xb8" => [93, "\x1b"], "\xb9" => [138, "\x1b"], "\xba" => [75, "\x1b"], "\xbb" => [91, "\x1b"], "\xbc" => [108, "\x1b"], "\xbd" => [103, "\x1b"], "\xbe" => [114, "\x1b"], "\xbf" => [14, "\x1b"], "\xc0" => [93, "\x1c"], "\xc1" => [138, "\x1c"], "\xc2" => [75, "\x1c"], "\xc3" => [91, "\x1c"], "\xc4" => [108, "\x1c"], "\xc5" => [103, "\x1c"], "\xc6" => [114, "\x1c"], "\xc7" => [14, "\x1c"], "\xc8" => [93, "\x1d"], "\xc9" => [138, "\x1d"], "\xca" => [75, "\x1d"], "\xcb" => [91, "\x1d"], "\xcc" => [108, "\x1d"], "\xcd" => [103, "\x1d"], "\xce" => [114, "\x1d"], "\xcf" => [14, "\x1d"], "\xd0" => [93, "\x1e"], "\xd1" => [138, "\x1e"], "\xd2" => [75, "\x1e"], "\xd3" => [91, "\x1e"], "\xd4" => [108, "\x1e"], "\xd5" => [103, "\x1e"], "\xd6" => [114, "\x1e"], "\xd7" => [14, "\x1e"], "\xd8" => [93, "\x1f"], "\xd9" => [138, "\x1f"], "\xda" => [75, "\x1f"], "\xdb" => [91, "\x1f"], "\xdc" => [108, "\x1f"], "\xdd" => [103, "\x1f"], "\xde" => [114, "\x1f"], "\xdf" => [14, "\x1f"], "\xe0" => [93, ""], "\xe1" => [138, ""], "\xe2" => [75, ""], "\xe3" => [91, ""], "\xe4" => [108, ""], "\xe5" => [103, ""], "\xe6" => [114, ""], "\xe7" => [14, ""], "\xe8" => [93, "\xdc"], "\xe9" => [138, "\xdc"], "\xea" => [75, "\xdc"], "\xeb" => [91, "\xdc"], "\xec" => [108, "\xdc"], "\xed" => [103, "\xdc"], "\xee" => [114, "\xdc"], "\xef" => [14, "\xdc"], "\xf0" => [93, "\xf9"], "\xf1" => [138, "\xf9"], "\xf2" => [75, "\xf9"], "\xf3" => [91, "\xf9"], "\xf4" => [108, "\xf9"], "\xf5" => [103, "\xf9"], "\xf6" => [114, "\xf9"], "\xf7" => [14, "\xf9"], "\xf8" => [77, "\n"], "\xf9" => [18, "\n"], "\xfa" => [77, "\r"], "\xfb" => [18, "\r"], "\xfc" => [77, "\x16"], "\xfd" => [18, "\x16"], "\xfe" => [77, ""], "\xff" => [18, ""]], ["\x00" => [93, "\xd3"], "\x01" => [138, "\xd3"], "\x02" => [75, "\xd3"], "\x03" => [91, "\xd3"], "\x04" => [108, "\xd3"], "\x05" => [103, "\xd3"], "\x06" => [114, "\xd3"], "\x07" => [14, "\xd3"], "\x08" => [93, "\xd4"], "\t" => [138, "\xd4"], "\n" => [75, "\xd4"], "\v" => [91, "\xd4"], "\f" => [108, "\xd4"], "\r" => [103, "\xd4"], "\x0e" => [114, "\xd4"], "\x0f" => [14, "\xd4"], "\x10" => [93, "\xd6"], "\x11" => [138, "\xd6"], "\x12" => [75, "\xd6"], "\x13" => [91, "\xd6"], "\x14" => [108, "\xd6"], "\x15" => [103, "\xd6"], "\x16" => [114, "\xd6"], "\x17" => [14, "\xd6"], "\x18" => [93, "\xdd"], "\x19" => [138, "\xdd"], "\x1a" => [75, "\xdd"], "\x1b" => [91, "\xdd"], "\x1c" => [108, "\xdd"], "\x1d" => [103, "\xdd"], "\x1e" => [114, "\xdd"], "\x1f" => [14, "\xdd"], " " => [93, "\xde"], "!" => [138, "\xde"], "\"" => [75, "\xde"], "#" => [91, "\xde"], "\$" => [108, "\xde"], "%" => [103, "\xde"], "&" => [114, "\xde"], "'" => [14, "\xde"], "(" => [93, "\xdf"], ")" => [138, "\xdf"], "*" => [75, "\xdf"], "+" => [91, "\xdf"], "," => [108, "\xdf"], "-" => [103, "\xdf"], "." => [114, "\xdf"], "/" => [14, "\xdf"], [93, "\xf1"], [138, "\xf1"], [75, "\xf1"], [91, "\xf1"], [108, "\xf1"], [103, "\xf1"], [114, "\xf1"], [14, "\xf1"], [93, "\xf4"], [138, "\xf4"], ":" => [75, "\xf4"], ";" => [91, "\xf4"], "<" => [108, "\xf4"], "=" => [103, "\xf4"], ">" => [114, "\xf4"], "?" => [14, "\xf4"], "@" => [93, "\xf5"], "A" => [138, "\xf5"], "B" => [75, "\xf5"], "C" => [91, "\xf5"], "D" => [108, "\xf5"], "E" => [103, "\xf5"], "F" => [114, "\xf5"], "G" => [14, "\xf5"], "H" => [93, "\xf6"], "I" => [138, "\xf6"], "J" => [75, "\xf6"], "K" => [91, "\xf6"], "L" => [108, "\xf6"], "M" => [103, "\xf6"], "N" => [114, "\xf6"], "O" => [14, "\xf6"], "P" => [93, "\xf7"], "Q" => [138, "\xf7"], "R" => [75, "\xf7"], "S" => [91, "\xf7"], "T" => [108, "\xf7"], "U" => [103, "\xf7"], "V" => [114, "\xf7"], "W" => [14, "\xf7"], "X" => [93, "\xf8"], "Y" => [138, "\xf8"], "Z" => [75, "\xf8"], "[" => [91, "\xf8"], "\\" => [108, "\xf8"], "]" => [103, "\xf8"], "^" => [114, "\xf8"], "_" => [14, "\xf8"], "`" => [93, "\xfa"], "a" => [138, "\xfa"], "b" => [75, "\xfa"], "c" => [91, "\xfa"], "d" => [108, "\xfa"], "e" => [103, "\xfa"], "f" => [114, "\xfa"], "g" => [14, "\xfa"], "h" => [93, "\xfb"], "i" => [138, "\xfb"], "j" => [75, "\xfb"], "k" => [91, "\xfb"], "l" => [108, "\xfb"], "m" => [103, "\xfb"], "n" => [114, "\xfb"], "o" => [14, "\xfb"], "p" => [93, "\xfc"], "q" => [138, "\xfc"], "r" => [75, "\xfc"], "s" => [91, "\xfc"], "t" => [108, "\xfc"], "u" => [103, "\xfc"], "v" => [114, "\xfc"], "w" => [14, "\xfc"], "x" => [93, "\xfd"], "y" => [138, "\xfd"], "z" => [75, "\xfd"], "{" => [91, "\xfd"], "|" => [108, "\xfd"], "}" => [103, "\xfd"], "~" => [114, "\xfd"], "" => [14, "\xfd"], "\x80" => [93, "\xfe"], "\x81" => [138, "\xfe"], "\x82" => [75, "\xfe"], "\x83" => [91, "\xfe"], "\x84" => [108, "\xfe"], "\x85" => [103, "\xfe"], "\x86" => [114, "\xfe"], "\x87" => [14, "\xfe"], "\x88" => [94, "\x02"], "\x89" => [76, "\x02"], "\x8a" => [104, "\x02"], "\x8b" => [16, "\x02"], "\x8c" => [94, "\x03"], "\x8d" => [76, "\x03"], "\x8e" => [104, "\x03"], "\x8f" => [16, "\x03"], "\x90" => [94, "\x04"], "\x91" => [76, "\x04"], "\x92" => [104, "\x04"], "\x93" => [16, "\x04"], "\x94" => [94, "\x05"], "\x95" => [76, "\x05"], "\x96" => [104, "\x05"], "\x97" => [16, "\x05"], "\x98" => [94, "\x06"], "\x99" => [76, "\x06"], "\x9a" => [104, "\x06"], "\x9b" => [16, "\x06"], "\x9c" => [94, "\x07"], "\x9d" => [76, "\x07"], "\x9e" => [104, "\x07"], "\x9f" => [16, "\x07"], "\xa0" => [94, "\x08"], "\xa1" => [76, "\x08"], "\xa2" => [104, "\x08"], "\xa3" => [16, "\x08"], "\xa4" => [94, "\v"], "\xa5" => [76, "\v"], "\xa6" => [104, "\v"], "\xa7" => [16, "\v"], "\xa8" => [94, "\f"], "\xa9" => [76, "\f"], "\xaa" => [104, "\f"], "\xab" => [16, "\f"], "\xac" => [94, "\x0e"], "\xad" => [76, "\x0e"], "\xae" => [104, "\x0e"], "\xaf" => [16, "\x0e"], "\xb0" => [94, "\x0f"], "\xb1" => [76, "\x0f"], "\xb2" => [104, "\x0f"], "\xb3" => [16, "\x0f"], "\xb4" => [94, "\x10"], "\xb5" => [76, "\x10"], "\xb6" => [104, "\x10"], "\xb7" => [16, "\x10"], "\xb8" => [94, "\x11"], "\xb9" => [76, "\x11"], "\xba" => [104, "\x11"], "\xbb" => [16, "\x11"], "\xbc" => [94, "\x12"], "\xbd" => [76, "\x12"], "\xbe" => [104, "\x12"], "\xbf" => [16, "\x12"], "\xc0" => [94, "\x13"], "\xc1" => [76, "\x13"], "\xc2" => [104, "\x13"], "\xc3" => [16, "\x13"], "\xc4" => [94, "\x14"], "\xc5" => [76, "\x14"], "\xc6" => [104, "\x14"], "\xc7" => [16, "\x14"], "\xc8" => [94, "\x15"], "\xc9" => [76, "\x15"], "\xca" => [104, "\x15"], "\xcb" => [16, "\x15"], "\xcc" => [94, "\x17"], "\xcd" => [76, "\x17"], "\xce" => [104, "\x17"], "\xcf" => [16, "\x17"], "\xd0" => [94, "\x18"], "\xd1" => [76, "\x18"], "\xd2" => [104, "\x18"], "\xd3" => [16, "\x18"], "\xd4" => [94, "\x19"], "\xd5" => [76, "\x19"], "\xd6" => [104, "\x19"], "\xd7" => [16, "\x19"], "\xd8" => [94, "\x1a"], "\xd9" => [76, "\x1a"], "\xda" => [104, "\x1a"], "\xdb" => [16, "\x1a"], "\xdc" => [94, "\x1b"], "\xdd" => [76, "\x1b"], "\xde" => [104, "\x1b"], "\xdf" => [16, "\x1b"], "\xe0" => [94, "\x1c"], "\xe1" => [76, "\x1c"], "\xe2" => [104, "\x1c"], "\xe3" => [16, "\x1c"], "\xe4" => [94, "\x1d"], "\xe5" => [76, "\x1d"], "\xe6" => [104, "\x1d"], "\xe7" => [16, "\x1d"], "\xe8" => [94, "\x1e"], "\xe9" => [76, "\x1e"], "\xea" => [104, "\x1e"], "\xeb" => [16, "\x1e"], "\xec" => [94, "\x1f"], "\xed" => [76, "\x1f"], "\xee" => [104, "\x1f"], "\xef" => [16, "\x1f"], "\xf0" => [94, ""], "\xf1" => [76, ""], "\xf2" => [104, ""], "\xf3" => [16, ""], "\xf4" => [94, "\xdc"], "\xf5" => [76, "\xdc"], "\xf6" => [104, "\xdc"], "\xf7" => [16, "\xdc"], "\xf8" => [94, "\xf9"], "\xf9" => [76, "\xf9"], "\xfa" => [104, "\xf9"], "\xfb" => [16, "\xf9"], "\xfc" => [0, "\n"], "\xfd" => [0, "\r"], "\xfe" => [0, "\x16"], "\xff" => [0, ""]], ["\x00" => [93, "\xc0"], "\x01" => [138, "\xc0"], "\x02" => [75, "\xc0"], "\x03" => [91, "\xc0"], "\x04" => [108, "\xc0"], "\x05" => [103, "\xc0"], "\x06" => [114, "\xc0"], "\x07" => [14, "\xc0"], "\x08" => [93, "\xc1"], "\t" => [138, "\xc1"], "\n" => [75, "\xc1"], "\v" => [91, "\xc1"], "\f" => [108, "\xc1"], "\r" => [103, "\xc1"], "\x0e" => [114, "\xc1"], "\x0f" => [14, "\xc1"], "\x10" => [93, "\xc8"], "\x11" => [138, "\xc8"], "\x12" => [75, "\xc8"], "\x13" => [91, "\xc8"], "\x14" => [108, "\xc8"], "\x15" => [103, "\xc8"], "\x16" => [114, "\xc8"], "\x17" => [14, "\xc8"], "\x18" => [93, "\xc9"], "\x19" => [138, "\xc9"], "\x1a" => [75, "\xc9"], "\x1b" => [91, "\xc9"], "\x1c" => [108, "\xc9"], "\x1d" => [103, "\xc9"], "\x1e" => [114, "\xc9"], "\x1f" => [14, "\xc9"], " " => [93, "\xca"], "!" => [138, "\xca"], "\"" => [75, "\xca"], "#" => [91, "\xca"], "\$" => [108, "\xca"], "%" => [103, "\xca"], "&" => [114, "\xca"], "'" => [14, "\xca"], "(" => [93, "\xcd"], ")" => [138, "\xcd"], "*" => [75, "\xcd"], "+" => [91, "\xcd"], "," => [108, "\xcd"], "-" => [103, "\xcd"], "." => [114, "\xcd"], "/" => [14, "\xcd"], [93, "\xd2"], [138, "\xd2"], [75, "\xd2"], [91, "\xd2"], [108, "\xd2"], [103, "\xd2"], [114, "\xd2"], [14, "\xd2"], [93, "\xd5"], [138, "\xd5"], ":" => [75, "\xd5"], ";" => [91, "\xd5"], "<" => [108, "\xd5"], "=" => [103, "\xd5"], ">" => [114, "\xd5"], "?" => [14, "\xd5"], "@" => [93, "\xda"], "A" => [138, "\xda"], "B" => [75, "\xda"], "C" => [91, "\xda"], "D" => [108, "\xda"], "E" => [103, "\xda"], "F" => [114, "\xda"], "G" => [14, "\xda"], "H" => [93, "\xdb"], "I" => [138, "\xdb"], "J" => [75, "\xdb"], "K" => [91, "\xdb"], "L" => [108, "\xdb"], "M" => [103, "\xdb"], "N" => [114, "\xdb"], "O" => [14, "\xdb"], "P" => [93, "\xee"], "Q" => [138, "\xee"], "R" => [75, "\xee"], "S" => [91, "\xee"], "T" => [108, "\xee"], "U" => [103, "\xee"], "V" => [114, "\xee"], "W" => [14, "\xee"], "X" => [93, "\xf0"], "Y" => [138, "\xf0"], "Z" => [75, "\xf0"], "[" => [91, "\xf0"], "\\" => [108, "\xf0"], "]" => [103, "\xf0"], "^" => [114, "\xf0"], "_" => [14, "\xf0"], "`" => [93, "\xf2"], "a" => [138, "\xf2"], "b" => [75, "\xf2"], "c" => [91, "\xf2"], "d" => [108, "\xf2"], "e" => [103, "\xf2"], "f" => [114, "\xf2"], "g" => [14, "\xf2"], "h" => [93, "\xf3"], "i" => [138, "\xf3"], "j" => [75, "\xf3"], "k" => [91, "\xf3"], "l" => [108, "\xf3"], "m" => [103, "\xf3"], "n" => [114, "\xf3"], "o" => [14, "\xf3"], "p" => [93, "\xff"], "q" => [138, "\xff"], "r" => [75, "\xff"], "s" => [91, "\xff"], "t" => [108, "\xff"], "u" => [103, "\xff"], "v" => [114, "\xff"], "w" => [14, "\xff"], "x" => [94, "\xcb"], "y" => [76, "\xcb"], "z" => [104, "\xcb"], "{" => [16, "\xcb"], "|" => [94, "\xcc"], "}" => [76, "\xcc"], "~" => [104, "\xcc"], "" => [16, "\xcc"], "\x80" => [94, "\xd3"], "\x81" => [76, "\xd3"], "\x82" => [104, "\xd3"], "\x83" => [16, "\xd3"], "\x84" => [94, "\xd4"], "\x85" => [76, "\xd4"], "\x86" => [104, "\xd4"], "\x87" => [16, "\xd4"], "\x88" => [94, "\xd6"], "\x89" => [76, "\xd6"], "\x8a" => [104, "\xd6"], "\x8b" => [16, "\xd6"], "\x8c" => [94, "\xdd"], "\x8d" => [76, "\xdd"], "\x8e" => [104, "\xdd"], "\x8f" => [16, "\xdd"], "\x90" => [94, "\xde"], "\x91" => [76, "\xde"], "\x92" => [104, "\xde"], "\x93" => [16, "\xde"], "\x94" => [94, "\xdf"], "\x95" => [76, "\xdf"], "\x96" => [104, "\xdf"], "\x97" => [16, "\xdf"], "\x98" => [94, "\xf1"], "\x99" => [76, "\xf1"], "\x9a" => [104, "\xf1"], "\x9b" => [16, "\xf1"], "\x9c" => [94, "\xf4"], "\x9d" => [76, "\xf4"], "\x9e" => [104, "\xf4"], "\x9f" => [16, "\xf4"], "\xa0" => [94, "\xf5"], "\xa1" => [76, "\xf5"], "\xa2" => [104, "\xf5"], "\xa3" => [16, "\xf5"], "\xa4" => [94, "\xf6"], "\xa5" => [76, "\xf6"], "\xa6" => [104, "\xf6"], "\xa7" => [16, "\xf6"], "\xa8" => [94, "\xf7"], "\xa9" => [76, "\xf7"], "\xaa" => [104, "\xf7"], "\xab" => [16, "\xf7"], "\xac" => [94, "\xf8"], "\xad" => [76, "\xf8"], "\xae" => [104, "\xf8"], "\xaf" => [16, "\xf8"], "\xb0" => [94, "\xfa"], "\xb1" => [76, "\xfa"], "\xb2" => [104, "\xfa"], "\xb3" => [16, "\xfa"], "\xb4" => [94, "\xfb"], "\xb5" => [76, "\xfb"], "\xb6" => [104, "\xfb"], "\xb7" => [16, "\xfb"], "\xb8" => [94, "\xfc"], "\xb9" => [76, "\xfc"], "\xba" => [104, "\xfc"], "\xbb" => [16, "\xfc"], "\xbc" => [94, "\xfd"], "\xbd" => [76, "\xfd"], "\xbe" => [104, "\xfd"], "\xbf" => [16, "\xfd"], "\xc0" => [94, "\xfe"], "\xc1" => [76, "\xfe"], "\xc2" => [104, "\xfe"], "\xc3" => [16, "\xfe"], "\xc4" => [77, "\x02"], "\xc5" => [18, "\x02"], "\xc6" => [77, "\x03"], "\xc7" => [18, "\x03"], "\xc8" => [77, "\x04"], "\xc9" => [18, "\x04"], "\xca" => [77, "\x05"], "\xcb" => [18, "\x05"], "\xcc" => [77, "\x06"], "\xcd" => [18, "\x06"], "\xce" => [77, "\x07"], "\xcf" => [18, "\x07"], "\xd0" => [77, "\x08"], "\xd1" => [18, "\x08"], "\xd2" => [77, "\v"], "\xd3" => [18, "\v"], "\xd4" => [77, "\f"], "\xd5" => [18, "\f"], "\xd6" => [77, "\x0e"], "\xd7" => [18, "\x0e"], "\xd8" => [77, "\x0f"], "\xd9" => [18, "\x0f"], "\xda" => [77, "\x10"], "\xdb" => [18, "\x10"], "\xdc" => [77, "\x11"], "\xdd" => [18, "\x11"], "\xde" => [77, "\x12"], "\xdf" => [18, "\x12"], "\xe0" => [77, "\x13"], "\xe1" => [18, "\x13"], "\xe2" => [77, "\x14"], "\xe3" => [18, "\x14"], "\xe4" => [77, "\x15"], "\xe5" => [18, "\x15"], "\xe6" => [77, "\x17"], "\xe7" => [18, "\x17"], "\xe8" => [77, "\x18"], "\xe9" => [18, "\x18"], "\xea" => [77, "\x19"], "\xeb" => [18, "\x19"], "\xec" => [77, "\x1a"], "\xed" => [18, "\x1a"], "\xee" => [77, "\x1b"], "\xef" => [18, "\x1b"], "\xf0" => [77, "\x1c"], "\xf1" => [18, "\x1c"], "\xf2" => [77, "\x1d"], "\xf3" => [18, "\x1d"], "\xf4" => [77, "\x1e"], "\xf5" => [18, "\x1e"], "\xf6" => [77, "\x1f"], "\xf7" => [18, "\x1f"], "\xf8" => [77, ""], "\xf9" => [18, ""], "\xfa" => [77, "\xdc"], "\xfb" => [18, "\xdc"], "\xfc" => [77, "\xf9"], "\xfd" => [18, "\xf9"], "\xfe" => [53, null], "\xff" => [66, null]], ["\x00" => [92, "\xab"], "\x01" => [95, "\xab"], "\x02" => [137, "\xab"], "\x03" => [142, "\xab"], "\x04" => [150, "\xab"], "\x05" => [74, "\xab"], "\x06" => [90, "\xab"], "\x07" => [98, "\xab"], "\x08" => [107, "\xab"], "\t" => [140, "\xab"], "\n" => [146, "\xab"], "\v" => [102, "\xab"], "\f" => [113, "\xab"], "\r" => [121, "\xab"], "\x0e" => [128, "\xab"], "\x0f" => [12, "\xab"], "\x10" => [92, "\xce"], "\x11" => [95, "\xce"], "\x12" => [137, "\xce"], "\x13" => [142, "\xce"], "\x14" => [150, "\xce"], "\x15" => [74, "\xce"], "\x16" => [90, "\xce"], "\x17" => [98, "\xce"], "\x18" => [107, "\xce"], "\x19" => [140, "\xce"], "\x1a" => [146, "\xce"], "\x1b" => [102, "\xce"], "\x1c" => [113, "\xce"], "\x1d" => [121, "\xce"], "\x1e" => [128, "\xce"], "\x1f" => [12, "\xce"], " " => [92, "\xd7"], "!" => [95, "\xd7"], "\"" => [137, "\xd7"], "#" => [142, "\xd7"], "\$" => [150, "\xd7"], "%" => [74, "\xd7"], "&" => [90, "\xd7"], "'" => [98, "\xd7"], "(" => [107, "\xd7"], ")" => [140, "\xd7"], "*" => [146, "\xd7"], "+" => [102, "\xd7"], "," => [113, "\xd7"], "-" => [121, "\xd7"], "." => [128, "\xd7"], "/" => [12, "\xd7"], [92, "\xe1"], [95, "\xe1"], [137, "\xe1"], [142, "\xe1"], [150, "\xe1"], [74, "\xe1"], [90, "\xe1"], [98, "\xe1"], [107, "\xe1"], [140, "\xe1"], ":" => [146, "\xe1"], ";" => [102, "\xe1"], "<" => [113, "\xe1"], "=" => [121, "\xe1"], ">" => [128, "\xe1"], "?" => [12, "\xe1"], "@" => [92, "\xec"], "A" => [95, "\xec"], "B" => [137, "\xec"], "C" => [142, "\xec"], "D" => [150, "\xec"], "E" => [74, "\xec"], "F" => [90, "\xec"], "G" => [98, "\xec"], "H" => [107, "\xec"], "I" => [140, "\xec"], "J" => [146, "\xec"], "K" => [102, "\xec"], "L" => [113, "\xec"], "M" => [121, "\xec"], "N" => [128, "\xec"], "O" => [12, "\xec"], "P" => [92, "\xed"], "Q" => [95, "\xed"], "R" => [137, "\xed"], "S" => [142, "\xed"], "T" => [150, "\xed"], "U" => [74, "\xed"], "V" => [90, "\xed"], "W" => [98, "\xed"], "X" => [107, "\xed"], "Y" => [140, "\xed"], "Z" => [146, "\xed"], "[" => [102, "\xed"], "\\" => [113, "\xed"], "]" => [121, "\xed"], "^" => [128, "\xed"], "_" => [12, "\xed"], "`" => [93, "\xc7"], "a" => [138, "\xc7"], "b" => [75, "\xc7"], "c" => [91, "\xc7"], "d" => [108, "\xc7"], "e" => [103, "\xc7"], "f" => [114, "\xc7"], "g" => [14, "\xc7"], "h" => [93, "\xcf"], "i" => [138, "\xcf"], "j" => [75, "\xcf"], "k" => [91, "\xcf"], "l" => [108, "\xcf"], "m" => [103, "\xcf"], "n" => [114, "\xcf"], "o" => [14, "\xcf"], "p" => [93, "\xea"], "q" => [138, "\xea"], "r" => [75, "\xea"], "s" => [91, "\xea"], "t" => [108, "\xea"], "u" => [103, "\xea"], "v" => [114, "\xea"], "w" => [14, "\xea"], "x" => [93, "\xeb"], "y" => [138, "\xeb"], "z" => [75, "\xeb"], "{" => [91, "\xeb"], "|" => [108, "\xeb"], "}" => [103, "\xeb"], "~" => [114, "\xeb"], "" => [14, "\xeb"], "\x80" => [94, "\xc0"], "\x81" => [76, "\xc0"], "\x82" => [104, "\xc0"], "\x83" => [16, "\xc0"], "\x84" => [94, "\xc1"], "\x85" => [76, "\xc1"], "\x86" => [104, "\xc1"], "\x87" => [16, "\xc1"], "\x88" => [94, "\xc8"], "\x89" => [76, "\xc8"], "\x8a" => [104, "\xc8"], "\x8b" => [16, "\xc8"], "\x8c" => [94, "\xc9"], "\x8d" => [76, "\xc9"], "\x8e" => [104, "\xc9"], "\x8f" => [16, "\xc9"], "\x90" => [94, "\xca"], "\x91" => [76, "\xca"], "\x92" => [104, "\xca"], "\x93" => [16, "\xca"], "\x94" => [94, "\xcd"], "\x95" => [76, "\xcd"], "\x96" => [104, "\xcd"], "\x97" => [16, "\xcd"], "\x98" => [94, "\xd2"], "\x99" => [76, "\xd2"], "\x9a" => [104, "\xd2"], "\x9b" => [16, "\xd2"], "\x9c" => [94, "\xd5"], "\x9d" => [76, "\xd5"], "\x9e" => [104, "\xd5"], "\x9f" => [16, "\xd5"], "\xa0" => [94, "\xda"], "\xa1" => [76, "\xda"], "\xa2" => [104, "\xda"], "\xa3" => [16, "\xda"], "\xa4" => [94, "\xdb"], "\xa5" => [76, "\xdb"], "\xa6" => [104, "\xdb"], "\xa7" => [16, "\xdb"], "\xa8" => [94, "\xee"], "\xa9" => [76, "\xee"], "\xaa" => [104, "\xee"], "\xab" => [16, "\xee"], "\xac" => [94, "\xf0"], "\xad" => [76, "\xf0"], "\xae" => [104, "\xf0"], "\xaf" => [16, "\xf0"], "\xb0" => [94, "\xf2"], "\xb1" => [76, "\xf2"], "\xb2" => [104, "\xf2"], "\xb3" => [16, "\xf2"], "\xb4" => [94, "\xf3"], "\xb5" => [76, "\xf3"], "\xb6" => [104, "\xf3"], "\xb7" => [16, "\xf3"], "\xb8" => [94, "\xff"], "\xb9" => [76, "\xff"], "\xba" => [104, "\xff"], "\xbb" => [16, "\xff"], "\xbc" => [77, "\xcb"], "\xbd" => [18, "\xcb"], "\xbe" => [77, "\xcc"], "\xbf" => [18, "\xcc"], "\xc0" => [77, "\xd3"], "\xc1" => [18, "\xd3"], "\xc2" => [77, "\xd4"], "\xc3" => [18, "\xd4"], "\xc4" => [77, "\xd6"], "\xc5" => [18, "\xd6"], "\xc6" => [77, "\xdd"], "\xc7" => [18, "\xdd"], "\xc8" => [77, "\xde"], "\xc9" => [18, "\xde"], "\xca" => [77, "\xdf"], "\xcb" => [18, "\xdf"], "\xcc" => [77, "\xf1"], "\xcd" => [18, "\xf1"], "\xce" => [77, "\xf4"], "\xcf" => [18, "\xf4"], "\xd0" => [77, "\xf5"], "\xd1" => [18, "\xf5"], "\xd2" => [77, "\xf6"], "\xd3" => [18, "\xf6"], "\xd4" => [77, "\xf7"], "\xd5" => [18, "\xf7"], "\xd6" => [77, "\xf8"], "\xd7" => [18, "\xf8"], "\xd8" => [77, "\xfa"], "\xd9" => [18, "\xfa"], "\xda" => [77, "\xfb"], "\xdb" => [18, "\xfb"], "\xdc" => [77, "\xfc"], "\xdd" => [18, "\xfc"], "\xde" => [77, "\xfd"], "\xdf" => [18, "\xfd"], "\xe0" => [77, "\xfe"], "\xe1" => [18, "\xfe"], "\xe2" => [0, "\x02"], "\xe3" => [0, "\x03"], "\xe4" => [0, "\x04"], "\xe5" => [0, "\x05"], "\xe6" => [0, "\x06"], "\xe7" => [0, "\x07"], "\xe8" => [0, "\x08"], "\xe9" => [0, "\v"], "\xea" => [0, "\f"], "\xeb" => [0, "\x0e"], "\xec" => [0, "\x0f"], "\xed" => [0, "\x10"], "\xee" => [0, "\x11"], "\xef" => [0, "\x12"], "\xf0" => [0, "\x13"], "\xf1" => [0, "\x14"], "\xf2" => [0, "\x15"], "\xf3" => [0, "\x17"], "\xf4" => [0, "\x18"], "\xf5" => [0, "\x19"], "\xf6" => [0, "\x1a"], "\xf7" => [0, "\x1b"], "\xf8" => [0, "\x1c"], "\xf9" => [0, "\x1d"], "\xfa" => [0, "\x1e"], "\xfb" => [0, "\x1f"], "\xfc" => [0, ""], "\xfd" => [0, "\xdc"], "\xfe" => [0, "\xf9"], "\xff" => [54, null]], ["\x00" => [92, "\xbc"], "\x01" => [95, "\xbc"], "\x02" => [137, "\xbc"], "\x03" => [142, "\xbc"], "\x04" => [150, "\xbc"], "\x05" => [74, "\xbc"], "\x06" => [90, "\xbc"], "\x07" => [98, "\xbc"], "\x08" => [107, "\xbc"], "\t" => [140, "\xbc"], "\n" => [146, "\xbc"], "\v" => [102, "\xbc"], "\f" => [113, "\xbc"], "\r" => [121, "\xbc"], "\x0e" => [128, "\xbc"], "\x0f" => [12, "\xbc"], "\x10" => [92, "\xbf"], "\x11" => [95, "\xbf"], "\x12" => [137, "\xbf"], "\x13" => [142, "\xbf"], "\x14" => [150, "\xbf"], "\x15" => [74, "\xbf"], "\x16" => [90, "\xbf"], "\x17" => [98, "\xbf"], "\x18" => [107, "\xbf"], "\x19" => [140, "\xbf"], "\x1a" => [146, "\xbf"], "\x1b" => [102, "\xbf"], "\x1c" => [113, "\xbf"], "\x1d" => [121, "\xbf"], "\x1e" => [128, "\xbf"], "\x1f" => [12, "\xbf"], " " => [92, "\xc5"], "!" => [95, "\xc5"], "\"" => [137, "\xc5"], "#" => [142, "\xc5"], "\$" => [150, "\xc5"], "%" => [74, "\xc5"], "&" => [90, "\xc5"], "'" => [98, "\xc5"], "(" => [107, "\xc5"], ")" => [140, "\xc5"], "*" => [146, "\xc5"], "+" => [102, "\xc5"], "," => [113, "\xc5"], "-" => [121, "\xc5"], "." => [128, "\xc5"], "/" => [12, "\xc5"], [92, "\xe7"], [95, "\xe7"], [137, "\xe7"], [142, "\xe7"], [150, "\xe7"], [74, "\xe7"], [90, "\xe7"], [98, "\xe7"], [107, "\xe7"], [140, "\xe7"], ":" => [146, "\xe7"], ";" => [102, "\xe7"], "<" => [113, "\xe7"], "=" => [121, "\xe7"], ">" => [128, "\xe7"], "?" => [12, "\xe7"], "@" => [92, "\xef"], "A" => [95, "\xef"], "B" => [137, "\xef"], "C" => [142, "\xef"], "D" => [150, "\xef"], "E" => [74, "\xef"], "F" => [90, "\xef"], "G" => [98, "\xef"], "H" => [107, "\xef"], "I" => [140, "\xef"], "J" => [146, "\xef"], "K" => [102, "\xef"], "L" => [113, "\xef"], "M" => [121, "\xef"], "N" => [128, "\xef"], "O" => [12, "\xef"], "P" => [93, "\t"], "Q" => [138, "\t"], "R" => [75, "\t"], "S" => [91, "\t"], "T" => [108, "\t"], "U" => [103, "\t"], "V" => [114, "\t"], "W" => [14, "\t"], "X" => [93, "\x8e"], "Y" => [138, "\x8e"], "Z" => [75, "\x8e"], "[" => [91, "\x8e"], "\\" => [108, "\x8e"], "]" => [103, "\x8e"], "^" => [114, "\x8e"], "_" => [14, "\x8e"], "`" => [93, "\x90"], "a" => [138, "\x90"], "b" => [75, "\x90"], "c" => [91, "\x90"], "d" => [108, "\x90"], "e" => [103, "\x90"], "f" => [114, "\x90"], "g" => [14, "\x90"], "h" => [93, "\x91"], "i" => [138, "\x91"], "j" => [75, "\x91"], "k" => [91, "\x91"], "l" => [108, "\x91"], "m" => [103, "\x91"], "n" => [114, "\x91"], "o" => [14, "\x91"], "p" => [93, "\x94"], "q" => [138, "\x94"], "r" => [75, "\x94"], "s" => [91, "\x94"], "t" => [108, "\x94"], "u" => [103, "\x94"], "v" => [114, "\x94"], "w" => [14, "\x94"], "x" => [93, "\x9f"], "y" => [138, "\x9f"], "z" => [75, "\x9f"], "{" => [91, "\x9f"], "|" => [108, "\x9f"], "}" => [103, "\x9f"], "~" => [114, "\x9f"], "" => [14, "\x9f"], "\x80" => [93, "\xab"], "\x81" => [138, "\xab"], "\x82" => [75, "\xab"], "\x83" => [91, "\xab"], "\x84" => [108, "\xab"], "\x85" => [103, "\xab"], "\x86" => [114, "\xab"], "\x87" => [14, "\xab"], "\x88" => [93, "\xce"], "\x89" => [138, "\xce"], "\x8a" => [75, "\xce"], "\x8b" => [91, "\xce"], "\x8c" => [108, "\xce"], "\x8d" => [103, "\xce"], "\x8e" => [114, "\xce"], "\x8f" => [14, "\xce"], "\x90" => [93, "\xd7"], "\x91" => [138, "\xd7"], "\x92" => [75, "\xd7"], "\x93" => [91, "\xd7"], "\x94" => [108, "\xd7"], "\x95" => [103, "\xd7"], "\x96" => [114, "\xd7"], "\x97" => [14, "\xd7"], "\x98" => [93, "\xe1"], "\x99" => [138, "\xe1"], "\x9a" => [75, "\xe1"], "\x9b" => [91, "\xe1"], "\x9c" => [108, "\xe1"], "\x9d" => [103, "\xe1"], "\x9e" => [114, "\xe1"], "\x9f" => [14, "\xe1"], "\xa0" => [93, "\xec"], "\xa1" => [138, "\xec"], "\xa2" => [75, "\xec"], "\xa3" => [91, "\xec"], "\xa4" => [108, "\xec"], "\xa5" => [103, "\xec"], "\xa6" => [114, "\xec"], "\xa7" => [14, "\xec"], "\xa8" => [93, "\xed"], "\xa9" => [138, "\xed"], "\xaa" => [75, "\xed"], "\xab" => [91, "\xed"], "\xac" => [108, "\xed"], "\xad" => [103, "\xed"], "\xae" => [114, "\xed"], "\xaf" => [14, "\xed"], "\xb0" => [94, "\xc7"], "\xb1" => [76, "\xc7"], "\xb2" => [104, "\xc7"], "\xb3" => [16, "\xc7"], "\xb4" => [94, "\xcf"], "\xb5" => [76, "\xcf"], "\xb6" => [104, "\xcf"], "\xb7" => [16, "\xcf"], "\xb8" => [94, "\xea"], "\xb9" => [76, "\xea"], "\xba" => [104, "\xea"], "\xbb" => [16, "\xea"], "\xbc" => [94, "\xeb"], "\xbd" => [76, "\xeb"], "\xbe" => [104, "\xeb"], "\xbf" => [16, "\xeb"], "\xc0" => [77, "\xc0"], "\xc1" => [18, "\xc0"], "\xc2" => [77, "\xc1"], "\xc3" => [18, "\xc1"], "\xc4" => [77, "\xc8"], "\xc5" => [18, "\xc8"], "\xc6" => [77, "\xc9"], "\xc7" => [18, "\xc9"], "\xc8" => [77, "\xca"], "\xc9" => [18, "\xca"], "\xca" => [77, "\xcd"], "\xcb" => [18, "\xcd"], "\xcc" => [77, "\xd2"], "\xcd" => [18, "\xd2"], "\xce" => [77, "\xd5"], "\xcf" => [18, "\xd5"], "\xd0" => [77, "\xda"], "\xd1" => [18, "\xda"], "\xd2" => [77, "\xdb"], "\xd3" => [18, "\xdb"], "\xd4" => [77, "\xee"], "\xd5" => [18, "\xee"], "\xd6" => [77, "\xf0"], "\xd7" => [18, "\xf0"], "\xd8" => [77, "\xf2"], "\xd9" => [18, "\xf2"], "\xda" => [77, "\xf3"], "\xdb" => [18, "\xf3"], "\xdc" => [77, "\xff"], "\xdd" => [18, "\xff"], "\xde" => [0, "\xcb"], "\xdf" => [0, "\xcc"], "\xe0" => [0, "\xd3"], "\xe1" => [0, "\xd4"], "\xe2" => [0, "\xd6"], "\xe3" => [0, "\xdd"], "\xe4" => [0, "\xde"], "\xe5" => [0, "\xdf"], "\xe6" => [0, "\xf1"], "\xe7" => [0, "\xf4"], "\xe8" => [0, "\xf5"], "\xe9" => [0, "\xf6"], "\xea" => [0, "\xf7"], "\xeb" => [0, "\xf8"], "\xec" => [0, "\xfa"], "\xed" => [0, "\xfb"], "\xee" => [0, "\xfc"], "\xef" => [0, "\xfd"], "\xf0" => [0, "\xfe"], "\xf1" => [38, null], "\xf2" => [42, null], "\xf3" => [44, null], "\xf4" => [45, null], "\xf5" => [58, null], "\xf6" => [59, null], "\xf7" => [61, null], "\xf8" => [62, null], "\xf9" => [65, null], "\xfa" => [67, null], "\xfb" => [69, null], "\xfc" => [70, null], "\xfd" => [72, null], "\xfe" => [154, null], "\xff" => [55, null]], ["\x00" => [94, "\x020"], "\x01" => [76, "\x020"], "\x02" => [104, "\x020"], "\x03" => [16, "\x020"], "\x04" => [94, "\x021"], "\x05" => [76, "\x021"], "\x06" => [104, "\x021"], "\x07" => [16, "\x021"], "\x08" => [94, "\x022"], "\t" => [76, "\x022"], "\n" => [104, "\x022"], "\v" => [16, "\x022"], "\f" => [94, "\x02a"], "\r" => [76, "\x02a"], "\x0e" => [104, "\x02a"], "\x0f" => [16, "\x02a"], "\x10" => [94, "\x02c"], "\x11" => [76, "\x02c"], "\x12" => [104, "\x02c"], "\x13" => [16, "\x02c"], "\x14" => [94, "\x02e"], "\x15" => [76, "\x02e"], "\x16" => [104, "\x02e"], "\x17" => [16, "\x02e"], "\x18" => [94, "\x02i"], "\x19" => [76, "\x02i"], "\x1a" => [104, "\x02i"], "\x1b" => [16, "\x02i"], "\x1c" => [94, "\x02o"], "\x1d" => [76, "\x02o"], "\x1e" => [104, "\x02o"], "\x1f" => [16, "\x02o"], " " => [94, "\x02s"], "!" => [76, "\x02s"], "\"" => [104, "\x02s"], "#" => [16, "\x02s"], "\$" => [94, "\x02t"], "%" => [76, "\x02t"], "&" => [104, "\x02t"], "'" => [16, "\x02t"], "(" => [77, "\x02 "], ")" => [18, "\x02 "], "*" => [77, "\x02%"], "+" => [18, "\x02%"], "," => [77, "\x02-"], "-" => [18, "\x02-"], "." => [77, "\x02."], "/" => [18, "\x02."], [77, "\x02/"], [18, "\x02/"], [77, "\x023"], [18, "\x023"], [77, "\x024"], [18, "\x024"], [77, "\x025"], [18, "\x025"], [77, "\x026"], [18, "\x026"], ":" => [77, "\x027"], ";" => [18, "\x027"], "<" => [77, "\x028"], "=" => [18, "\x028"], ">" => [77, "\x029"], "?" => [18, "\x029"], "@" => [77, "\x02="], "A" => [18, "\x02="], "B" => [77, "\x02A"], "C" => [18, "\x02A"], "D" => [77, "\x02_"], "E" => [18, "\x02_"], "F" => [77, "\x02b"], "G" => [18, "\x02b"], "H" => [77, "\x02d"], "I" => [18, "\x02d"], "J" => [77, "\x02f"], "K" => [18, "\x02f"], "L" => [77, "\x02g"], "M" => [18, "\x02g"], "N" => [77, "\x02h"], "O" => [18, "\x02h"], "P" => [77, "\x02l"], "Q" => [18, "\x02l"], "R" => [77, "\x02m"], "S" => [18, "\x02m"], "T" => [77, "\x02n"], "U" => [18, "\x02n"], "V" => [77, "\x02p"], "W" => [18, "\x02p"], "X" => [77, "\x02r"], "Y" => [18, "\x02r"], "Z" => [77, "\x02u"], "[" => [18, "\x02u"], "\\" => [0, "\x02:"], "]" => [0, "\x02B"], "^" => [0, "\x02C"], "_" => [0, "\x02D"], "`" => [0, "\x02E"], "a" => [0, "\x02F"], "b" => [0, "\x02G"], "c" => [0, "\x02H"], "d" => [0, "\x02I"], "e" => [0, "\x02J"], "f" => [0, "\x02K"], "g" => [0, "\x02L"], "h" => [0, "\x02M"], "i" => [0, "\x02N"], "j" => [0, "\x02O"], "k" => [0, "\x02P"], "l" => [0, "\x02Q"], "m" => [0, "\x02R"], "n" => [0, "\x02S"], "o" => [0, "\x02T"], "p" => [0, "\x02U"], "q" => [0, "\x02V"], "r" => [0, "\x02W"], "s" => [0, "\x02Y"], "t" => [0, "\x02j"], "u" => [0, "\x02k"], "v" => [0, "\x02q"], "w" => [0, "\x02v"], "x" => [0, "\x02w"], "y" => [0, "\x02x"], "z" => [0, "\x02y"], "{" => [0, "\x02z"], "|" => [82, "\x02"], "}" => [87, "\x02"], "~" => [130, "\x02"], "" => [9, "\x02"], "\x80" => [94, "\x030"], "\x81" => [76, "\x030"], "\x82" => [104, "\x030"], "\x83" => [16, "\x030"], "\x84" => [94, "\x031"], "\x85" => [76, "\x031"], "\x86" => [104, "\x031"], "\x87" => [16, "\x031"], "\x88" => [94, "\x032"], "\x89" => [76, "\x032"], "\x8a" => [104, "\x032"], "\x8b" => [16, "\x032"], "\x8c" => [94, "\x03a"], "\x8d" => [76, "\x03a"], "\x8e" => [104, "\x03a"], "\x8f" => [16, "\x03a"], "\x90" => [94, "\x03c"], "\x91" => [76, "\x03c"], "\x92" => [104, "\x03c"], "\x93" => [16, "\x03c"], "\x94" => [94, "\x03e"], "\x95" => [76, "\x03e"], "\x96" => [104, "\x03e"], "\x97" => [16, "\x03e"], "\x98" => [94, "\x03i"], "\x99" => [76, "\x03i"], "\x9a" => [104, "\x03i"], "\x9b" => [16, "\x03i"], "\x9c" => [94, "\x03o"], "\x9d" => [76, "\x03o"], "\x9e" => [104, "\x03o"], "\x9f" => [16, "\x03o"], "\xa0" => [94, "\x03s"], "\xa1" => [76, "\x03s"], "\xa2" => [104, "\x03s"], "\xa3" => [16, "\x03s"], "\xa4" => [94, "\x03t"], "\xa5" => [76, "\x03t"], "\xa6" => [104, "\x03t"], "\xa7" => [16, "\x03t"], "\xa8" => [77, "\x03 "], "\xa9" => [18, "\x03 "], "\xaa" => [77, "\x03%"], "\xab" => [18, "\x03%"], "\xac" => [77, "\x03-"], "\xad" => [18, "\x03-"], "\xae" => [77, "\x03."], "\xaf" => [18, "\x03."], "\xb0" => [77, "\x03/"], "\xb1" => [18, "\x03/"], "\xb2" => [77, "\x033"], "\xb3" => [18, "\x033"], "\xb4" => [77, "\x034"], "\xb5" => [18, "\x034"], "\xb6" => [77, "\x035"], "\xb7" => [18, "\x035"], "\xb8" => [77, "\x036"], "\xb9" => [18, "\x036"], "\xba" => [77, "\x037"], "\xbb" => [18, "\x037"], "\xbc" => [77, "\x038"], "\xbd" => [18, "\x038"], "\xbe" => [77, "\x039"], "\xbf" => [18, "\x039"], "\xc0" => [77, "\x03="], "\xc1" => [18, "\x03="], "\xc2" => [77, "\x03A"], "\xc3" => [18, "\x03A"], "\xc4" => [77, "\x03_"], "\xc5" => [18, "\x03_"], "\xc6" => [77, "\x03b"], "\xc7" => [18, "\x03b"], "\xc8" => [77, "\x03d"], "\xc9" => [18, "\x03d"], "\xca" => [77, "\x03f"], "\xcb" => [18, "\x03f"], "\xcc" => [77, "\x03g"], "\xcd" => [18, "\x03g"], "\xce" => [77, "\x03h"], "\xcf" => [18, "\x03h"], "\xd0" => [77, "\x03l"], "\xd1" => [18, "\x03l"], "\xd2" => [77, "\x03m"], "\xd3" => [18, "\x03m"], "\xd4" => [77, "\x03n"], "\xd5" => [18, "\x03n"], "\xd6" => [77, "\x03p"], "\xd7" => [18, "\x03p"], "\xd8" => [77, "\x03r"], "\xd9" => [18, "\x03r"], "\xda" => [77, "\x03u"], "\xdb" => [18, "\x03u"], "\xdc" => [0, "\x03:"], "\xdd" => [0, "\x03B"], "\xde" => [0, "\x03C"], "\xdf" => [0, "\x03D"], "\xe0" => [0, "\x03E"], "\xe1" => [0, "\x03F"], "\xe2" => [0, "\x03G"], "\xe3" => [0, "\x03H"], "\xe4" => [0, "\x03I"], "\xe5" => [0, "\x03J"], "\xe6" => [0, "\x03K"], "\xe7" => [0, "\x03L"], "\xe8" => [0, "\x03M"], "\xe9" => [0, "\x03N"], "\xea" => [0, "\x03O"], "\xeb" => [0, "\x03P"], "\xec" => [0, "\x03Q"], "\xed" => [0, "\x03R"], "\xee" => [0, "\x03S"], "\xef" => [0, "\x03T"], "\xf0" => [0, "\x03U"], "\xf1" => [0, "\x03V"], "\xf2" => [0, "\x03W"], "\xf3" => [0, "\x03Y"], "\xf4" => [0, "\x03j"], "\xf5" => [0, "\x03k"], "\xf6" => [0, "\x03q"], "\xf7" => [0, "\x03v"], "\xf8" => [0, "\x03w"], "\xf9" => [0, "\x03x"], "\xfa" => [0, "\x03y"], "\xfb" => [0, "\x03z"], "\xfc" => [82, "\x03"], "\xfd" => [87, "\x03"], "\xfe" => [130, "\x03"], "\xff" => [9, "\x03"]], ["\x00" => [93, "\x93"], "\x01" => [138, "\x93"], "\x02" => [75, "\x93"], "\x03" => [91, "\x93"], "\x04" => [108, "\x93"], "\x05" => [103, "\x93"], "\x06" => [114, "\x93"], "\x07" => [14, "\x93"], "\x08" => [93, "\x95"], "\t" => [138, "\x95"], "\n" => [75, "\x95"], "\v" => [91, "\x95"], "\f" => [108, "\x95"], "\r" => [103, "\x95"], "\x0e" => [114, "\x95"], "\x0f" => [14, "\x95"], "\x10" => [93, "\x96"], "\x11" => [138, "\x96"], "\x12" => [75, "\x96"], "\x13" => [91, "\x96"], "\x14" => [108, "\x96"], "\x15" => [103, "\x96"], "\x16" => [114, "\x96"], "\x17" => [14, "\x96"], "\x18" => [93, "\x97"], "\x19" => [138, "\x97"], "\x1a" => [75, "\x97"], "\x1b" => [91, "\x97"], "\x1c" => [108, "\x97"], "\x1d" => [103, "\x97"], "\x1e" => [114, "\x97"], "\x1f" => [14, "\x97"], " " => [93, "\x98"], "!" => [138, "\x98"], "\"" => [75, "\x98"], "#" => [91, "\x98"], "\$" => [108, "\x98"], "%" => [103, "\x98"], "&" => [114, "\x98"], "'" => [14, "\x98"], "(" => [93, "\x9b"], ")" => [138, "\x9b"], "*" => [75, "\x9b"], "+" => [91, "\x9b"], "," => [108, "\x9b"], "-" => [103, "\x9b"], "." => [114, "\x9b"], "/" => [14, "\x9b"], [93, "\x9d"], [138, "\x9d"], [75, "\x9d"], [91, "\x9d"], [108, "\x9d"], [103, "\x9d"], [114, "\x9d"], [14, "\x9d"], [93, "\x9e"], [138, "\x9e"], ":" => [75, "\x9e"], ";" => [91, "\x9e"], "<" => [108, "\x9e"], "=" => [103, "\x9e"], ">" => [114, "\x9e"], "?" => [14, "\x9e"], "@" => [93, "\xa5"], "A" => [138, "\xa5"], "B" => [75, "\xa5"], "C" => [91, "\xa5"], "D" => [108, "\xa5"], "E" => [103, "\xa5"], "F" => [114, "\xa5"], "G" => [14, "\xa5"], "H" => [93, "\xa6"], "I" => [138, "\xa6"], "J" => [75, "\xa6"], "K" => [91, "\xa6"], "L" => [108, "\xa6"], "M" => [103, "\xa6"], "N" => [114, "\xa6"], "O" => [14, "\xa6"], "P" => [93, "\xa8"], "Q" => [138, "\xa8"], "R" => [75, "\xa8"], "S" => [91, "\xa8"], "T" => [108, "\xa8"], "U" => [103, "\xa8"], "V" => [114, "\xa8"], "W" => [14, "\xa8"], "X" => [93, "\xae"], "Y" => [138, "\xae"], "Z" => [75, "\xae"], "[" => [91, "\xae"], "\\" => [108, "\xae"], "]" => [103, "\xae"], "^" => [114, "\xae"], "_" => [14, "\xae"], "`" => [93, "\xaf"], "a" => [138, "\xaf"], "b" => [75, "\xaf"], "c" => [91, "\xaf"], "d" => [108, "\xaf"], "e" => [103, "\xaf"], "f" => [114, "\xaf"], "g" => [14, "\xaf"], "h" => [93, "\xb4"], "i" => [138, "\xb4"], "j" => [75, "\xb4"], "k" => [91, "\xb4"], "l" => [108, "\xb4"], "m" => [103, "\xb4"], "n" => [114, "\xb4"], "o" => [14, "\xb4"], "p" => [93, "\xb6"], "q" => [138, "\xb6"], "r" => [75, "\xb6"], "s" => [91, "\xb6"], "t" => [108, "\xb6"], "u" => [103, "\xb6"], "v" => [114, "\xb6"], "w" => [14, "\xb6"], "x" => [93, "\xb7"], "y" => [138, "\xb7"], "z" => [75, "\xb7"], "{" => [91, "\xb7"], "|" => [108, "\xb7"], "}" => [103, "\xb7"], "~" => [114, "\xb7"], "" => [14, "\xb7"], "\x80" => [93, "\xbc"], "\x81" => [138, "\xbc"], "\x82" => [75, "\xbc"], "\x83" => [91, "\xbc"], "\x84" => [108, "\xbc"], "\x85" => [103, "\xbc"], "\x86" => [114, "\xbc"], "\x87" => [14, "\xbc"], "\x88" => [93, "\xbf"], "\x89" => [138, "\xbf"], "\x8a" => [75, "\xbf"], "\x8b" => [91, "\xbf"], "\x8c" => [108, "\xbf"], "\x8d" => [103, "\xbf"], "\x8e" => [114, "\xbf"], "\x8f" => [14, "\xbf"], "\x90" => [93, "\xc5"], "\x91" => [138, "\xc5"], "\x92" => [75, "\xc5"], "\x93" => [91, "\xc5"], "\x94" => [108, "\xc5"], "\x95" => [103, "\xc5"], "\x96" => [114, "\xc5"], "\x97" => [14, "\xc5"], "\x98" => [93, "\xe7"], "\x99" => [138, "\xe7"], "\x9a" => [75, "\xe7"], "\x9b" => [91, "\xe7"], "\x9c" => [108, "\xe7"], "\x9d" => [103, "\xe7"], "\x9e" => [114, "\xe7"], "\x9f" => [14, "\xe7"], "\xa0" => [93, "\xef"], "\xa1" => [138, "\xef"], "\xa2" => [75, "\xef"], "\xa3" => [91, "\xef"], "\xa4" => [108, "\xef"], "\xa5" => [103, "\xef"], "\xa6" => [114, "\xef"], "\xa7" => [14, "\xef"], "\xa8" => [94, "\t"], "\xa9" => [76, "\t"], "\xaa" => [104, "\t"], "\xab" => [16, "\t"], "\xac" => [94, "\x8e"], "\xad" => [76, "\x8e"], "\xae" => [104, "\x8e"], "\xaf" => [16, "\x8e"], "\xb0" => [94, "\x90"], "\xb1" => [76, "\x90"], "\xb2" => [104, "\x90"], "\xb3" => [16, "\x90"], "\xb4" => [94, "\x91"], "\xb5" => [76, "\x91"], "\xb6" => [104, "\x91"], "\xb7" => [16, "\x91"], "\xb8" => [94, "\x94"], "\xb9" => [76, "\x94"], "\xba" => [104, "\x94"], "\xbb" => [16, "\x94"], "\xbc" => [94, "\x9f"], "\xbd" => [76, "\x9f"], "\xbe" => [104, "\x9f"], "\xbf" => [16, "\x9f"], "\xc0" => [94, "\xab"], "\xc1" => [76, "\xab"], "\xc2" => [104, "\xab"], "\xc3" => [16, "\xab"], "\xc4" => [94, "\xce"], "\xc5" => [76, "\xce"], "\xc6" => [104, "\xce"], "\xc7" => [16, "\xce"], "\xc8" => [94, "\xd7"], "\xc9" => [76, "\xd7"], "\xca" => [104, "\xd7"], "\xcb" => [16, "\xd7"], "\xcc" => [94, "\xe1"], "\xcd" => [76, "\xe1"], "\xce" => [104, "\xe1"], "\xcf" => [16, "\xe1"], "\xd0" => [94, "\xec"], "\xd1" => [76, "\xec"], "\xd2" => [104, "\xec"], "\xd3" => [16, "\xec"], "\xd4" => [94, "\xed"], "\xd5" => [76, "\xed"], "\xd6" => [104, "\xed"], "\xd7" => [16, "\xed"], "\xd8" => [77, "\xc7"], "\xd9" => [18, "\xc7"], "\xda" => [77, "\xcf"], "\xdb" => [18, "\xcf"], "\xdc" => [77, "\xea"], "\xdd" => [18, "\xea"], "\xde" => [77, "\xeb"], "\xdf" => [18, "\xeb"], "\xe0" => [0, "\xc0"], "\xe1" => [0, "\xc1"], "\xe2" => [0, "\xc8"], "\xe3" => [0, "\xc9"], "\xe4" => [0, "\xca"], "\xe5" => [0, "\xcd"], "\xe6" => [0, "\xd2"], "\xe7" => [0, "\xd5"], "\xe8" => [0, "\xda"], "\xe9" => [0, "\xdb"], "\xea" => [0, "\xee"], "\xeb" => [0, "\xf0"], "\xec" => [0, "\xf2"], "\xed" => [0, "\xf3"], "\xee" => [0, "\xff"], "\xef" => [233, null], "\xf0" => [238, null], "\xf1" => [240, null], "\xf2" => [246, null], "\xf3" => [254, null], "\xf4" => [257, null], "\xf5" => [259, null], "\xf6" => [260, null], "\xf7" => [262, null], "\xf8" => [40, null], "\xf9" => [43, null], "\xfa" => [46, null], "\xfb" => [60, null], "\xfc" => [63, null], "\xfd" => [68, null], "\xfe" => [71, null], "\xff" => [56, null]], ["\x00" => [94, "\xfe0"], "\x01" => [76, "\xfe0"], "\x02" => [104, "\xfe0"], "\x03" => [16, "\xfe0"], "\x04" => [94, "\xfe1"], "\x05" => [76, "\xfe1"], "\x06" => [104, "\xfe1"], "\x07" => [16, "\xfe1"], "\x08" => [94, "\xfe2"], "\t" => [76, "\xfe2"], "\n" => [104, "\xfe2"], "\v" => [16, "\xfe2"], "\f" => [94, "\xfea"], "\r" => [76, "\xfea"], "\x0e" => [104, "\xfea"], "\x0f" => [16, "\xfea"], "\x10" => [94, "\xfec"], "\x11" => [76, "\xfec"], "\x12" => [104, "\xfec"], "\x13" => [16, "\xfec"], "\x14" => [94, "\xfee"], "\x15" => [76, "\xfee"], "\x16" => [104, "\xfee"], "\x17" => [16, "\xfee"], "\x18" => [94, "\xfei"], "\x19" => [76, "\xfei"], "\x1a" => [104, "\xfei"], "\x1b" => [16, "\xfei"], "\x1c" => [94, "\xfeo"], "\x1d" => [76, "\xfeo"], "\x1e" => [104, "\xfeo"], "\x1f" => [16, "\xfeo"], " " => [94, "\xfes"], "!" => [76, "\xfes"], "\"" => [104, "\xfes"], "#" => [16, "\xfes"], "\$" => [94, "\xfet"], "%" => [76, "\xfet"], "&" => [104, "\xfet"], "'" => [16, "\xfet"], "(" => [77, "\xfe "], ")" => [18, "\xfe "], "*" => [77, "\xfe%"], "+" => [18, "\xfe%"], "," => [77, "\xfe-"], "-" => [18, "\xfe-"], "." => [77, "\xfe."], "/" => [18, "\xfe."], [77, "\xfe/"], [18, "\xfe/"], [77, "\xfe3"], [18, "\xfe3"], [77, "\xfe4"], [18, "\xfe4"], [77, "\xfe5"], [18, "\xfe5"], [77, "\xfe6"], [18, "\xfe6"], ":" => [77, "\xfe7"], ";" => [18, "\xfe7"], "<" => [77, "\xfe8"], "=" => [18, "\xfe8"], ">" => [77, "\xfe9"], "?" => [18, "\xfe9"], "@" => [77, "\xfe="], "A" => [18, "\xfe="], "B" => [77, "\xfeA"], "C" => [18, "\xfeA"], "D" => [77, "\xfe_"], "E" => [18, "\xfe_"], "F" => [77, "\xfeb"], "G" => [18, "\xfeb"], "H" => [77, "\xfed"], "I" => [18, "\xfed"], "J" => [77, "\xfef"], "K" => [18, "\xfef"], "L" => [77, "\xfeg"], "M" => [18, "\xfeg"], "N" => [77, "\xfeh"], "O" => [18, "\xfeh"], "P" => [77, "\xfel"], "Q" => [18, "\xfel"], "R" => [77, "\xfem"], "S" => [18, "\xfem"], "T" => [77, "\xfen"], "U" => [18, "\xfen"], "V" => [77, "\xfep"], "W" => [18, "\xfep"], "X" => [77, "\xfer"], "Y" => [18, "\xfer"], "Z" => [77, "\xfeu"], "[" => [18, "\xfeu"], "\\" => [0, "\xfe:"], "]" => [0, "\xfeB"], "^" => [0, "\xfeC"], "_" => [0, "\xfeD"], "`" => [0, "\xfeE"], "a" => [0, "\xfeF"], "b" => [0, "\xfeG"], "c" => [0, "\xfeH"], "d" => [0, "\xfeI"], "e" => [0, "\xfeJ"], "f" => [0, "\xfeK"], "g" => [0, "\xfeL"], "h" => [0, "\xfeM"], "i" => [0, "\xfeN"], "j" => [0, "\xfeO"], "k" => [0, "\xfeP"], "l" => [0, "\xfeQ"], "m" => [0, "\xfeR"], "n" => [0, "\xfeS"], "o" => [0, "\xfeT"], "p" => [0, "\xfeU"], "q" => [0, "\xfeV"], "r" => [0, "\xfeW"], "s" => [0, "\xfeY"], "t" => [0, "\xfej"], "u" => [0, "\xfek"], "v" => [0, "\xfeq"], "w" => [0, "\xfev"], "x" => [0, "\xfew"], "y" => [0, "\xfex"], "z" => [0, "\xfey"], "{" => [0, "\xfez"], "|" => [82, "\xfe"], "}" => [87, "\xfe"], "~" => [130, "\xfe"], "" => [9, "\xfe"], "\x80" => [77, "\x020"], "\x81" => [18, "\x020"], "\x82" => [77, "\x021"], "\x83" => [18, "\x021"], "\x84" => [77, "\x022"], "\x85" => [18, "\x022"], "\x86" => [77, "\x02a"], "\x87" => [18, "\x02a"], "\x88" => [77, "\x02c"], "\x89" => [18, "\x02c"], "\x8a" => [77, "\x02e"], "\x8b" => [18, "\x02e"], "\x8c" => [77, "\x02i"], "\x8d" => [18, "\x02i"], "\x8e" => [77, "\x02o"], "\x8f" => [18, "\x02o"], "\x90" => [77, "\x02s"], "\x91" => [18, "\x02s"], "\x92" => [77, "\x02t"], "\x93" => [18, "\x02t"], "\x94" => [0, "\x02 "], "\x95" => [0, "\x02%"], "\x96" => [0, "\x02-"], "\x97" => [0, "\x02."], "\x98" => [0, "\x02/"], "\x99" => [0, "\x023"], "\x9a" => [0, "\x024"], "\x9b" => [0, "\x025"], "\x9c" => [0, "\x026"], "\x9d" => [0, "\x027"], "\x9e" => [0, "\x028"], "\x9f" => [0, "\x029"], "\xa0" => [0, "\x02="], "\xa1" => [0, "\x02A"], "\xa2" => [0, "\x02_"], "\xa3" => [0, "\x02b"], "\xa4" => [0, "\x02d"], "\xa5" => [0, "\x02f"], "\xa6" => [0, "\x02g"], "\xa7" => [0, "\x02h"], "\xa8" => [0, "\x02l"], "\xa9" => [0, "\x02m"], "\xaa" => [0, "\x02n"], "\xab" => [0, "\x02p"], "\xac" => [0, "\x02r"], "\xad" => [0, "\x02u"], "\xae" => [100, "\x02"], "\xaf" => [110, "\x02"], "\xb0" => [111, "\x02"], "\xb1" => [115, "\x02"], "\xb2" => [116, "\x02"], "\xb3" => [118, "\x02"], "\xb4" => [119, "\x02"], "\xb5" => [122, "\x02"], "\xb6" => [123, "\x02"], "\xb7" => [125, "\x02"], "\xb8" => [126, "\x02"], "\xb9" => [129, "\x02"], "\xba" => [143, "\x02"], "\xbb" => [148, "\x02"], "\xbc" => [151, "\x02"], "\xbd" => [153, "\x02"], "\xbe" => [83, "\x02"], "\xbf" => [10, "\x02"], "\xc0" => [77, "\x030"], "\xc1" => [18, "\x030"], "\xc2" => [77, "\x031"], "\xc3" => [18, "\x031"], "\xc4" => [77, "\x032"], "\xc5" => [18, "\x032"], "\xc6" => [77, "\x03a"], "\xc7" => [18, "\x03a"], "\xc8" => [77, "\x03c"], "\xc9" => [18, "\x03c"], "\xca" => [77, "\x03e"], "\xcb" => [18, "\x03e"], "\xcc" => [77, "\x03i"], "\xcd" => [18, "\x03i"], "\xce" => [77, "\x03o"], "\xcf" => [18, "\x03o"], "\xd0" => [77, "\x03s"], "\xd1" => [18, "\x03s"], "\xd2" => [77, "\x03t"], "\xd3" => [18, "\x03t"], "\xd4" => [0, "\x03 "], "\xd5" => [0, "\x03%"], "\xd6" => [0, "\x03-"], "\xd7" => [0, "\x03."], "\xd8" => [0, "\x03/"], "\xd9" => [0, "\x033"], "\xda" => [0, "\x034"], "\xdb" => [0, "\x035"], "\xdc" => [0, "\x036"], "\xdd" => [0, "\x037"], "\xde" => [0, "\x038"], "\xdf" => [0, "\x039"], "\xe0" => [0, "\x03="], "\xe1" => [0, "\x03A"], "\xe2" => [0, "\x03_"], "\xe3" => [0, "\x03b"], "\xe4" => [0, "\x03d"], "\xe5" => [0, "\x03f"], "\xe6" => [0, "\x03g"], "\xe7" => [0, "\x03h"], "\xe8" => [0, "\x03l"], "\xe9" => [0, "\x03m"], "\xea" => [0, "\x03n"], "\xeb" => [0, "\x03p"], "\xec" => [0, "\x03r"], "\xed" => [0, "\x03u"], "\xee" => [100, "\x03"], "\xef" => [110, "\x03"], "\xf0" => [111, "\x03"], "\xf1" => [115, "\x03"], "\xf2" => [116, "\x03"], "\xf3" => [118, "\x03"], "\xf4" => [119, "\x03"], "\xf5" => [122, "\x03"], "\xf6" => [123, "\x03"], "\xf7" => [125, "\x03"], "\xf8" => [126, "\x03"], "\xf9" => [129, "\x03"], "\xfa" => [143, "\x03"], "\xfb" => [148, "\x03"], "\xfc" => [151, "\x03"], "\xfd" => [153, "\x03"], "\xfe" => [83, "\x03"], "\xff" => [10, "\x03"]], ["\x00" => [77, "\xfe0"], "\x01" => [18, "\xfe0"], "\x02" => [77, "\xfe1"], "\x03" => [18, "\xfe1"], "\x04" => [77, "\xfe2"], "\x05" => [18, "\xfe2"], "\x06" => [77, "\xfea"], "\x07" => [18, "\xfea"], "\x08" => [77, "\xfec"], "\t" => [18, "\xfec"], "\n" => [77, "\xfee"], "\v" => [18, "\xfee"], "\f" => [77, "\xfei"], "\r" => [18, "\xfei"], "\x0e" => [77, "\xfeo"], "\x0f" => [18, "\xfeo"], "\x10" => [77, "\xfes"], "\x11" => [18, "\xfes"], "\x12" => [77, "\xfet"], "\x13" => [18, "\xfet"], "\x14" => [0, "\xfe "], "\x15" => [0, "\xfe%"], "\x16" => [0, "\xfe-"], "\x17" => [0, "\xfe."], "\x18" => [0, "\xfe/"], "\x19" => [0, "\xfe3"], "\x1a" => [0, "\xfe4"], "\x1b" => [0, "\xfe5"], "\x1c" => [0, "\xfe6"], "\x1d" => [0, "\xfe7"], "\x1e" => [0, "\xfe8"], "\x1f" => [0, "\xfe9"], " " => [0, "\xfe="], "!" => [0, "\xfeA"], "\"" => [0, "\xfe_"], "#" => [0, "\xfeb"], "\$" => [0, "\xfed"], "%" => [0, "\xfef"], "&" => [0, "\xfeg"], "'" => [0, "\xfeh"], "(" => [0, "\xfel"], ")" => [0, "\xfem"], "*" => [0, "\xfen"], "+" => [0, "\xfep"], "," => [0, "\xfer"], "-" => [0, "\xfeu"], "." => [100, "\xfe"], "/" => [110, "\xfe"], [111, "\xfe"], [115, "\xfe"], [116, "\xfe"], [118, "\xfe"], [119, "\xfe"], [122, "\xfe"], [123, "\xfe"], [125, "\xfe"], [126, "\xfe"], [129, "\xfe"], ":" => [143, "\xfe"], ";" => [148, "\xfe"], "<" => [151, "\xfe"], "=" => [153, "\xfe"], ">" => [83, "\xfe"], "?" => [10, "\xfe"], "@" => [0, "\x020"], "A" => [0, "\x021"], "B" => [0, "\x022"], "C" => [0, "\x02a"], "D" => [0, "\x02c"], "E" => [0, "\x02e"], "F" => [0, "\x02i"], "G" => [0, "\x02o"], "H" => [0, "\x02s"], "I" => [0, "\x02t"], "J" => [73, "\x02"], "K" => [88, "\x02"], "L" => [89, "\x02"], "M" => [96, "\x02"], "N" => [97, "\x02"], "O" => [99, "\x02"], "P" => [106, "\x02"], "Q" => [136, "\x02"], "R" => [139, "\x02"], "S" => [141, "\x02"], "T" => [145, "\x02"], "U" => [147, "\x02"], "V" => [149, "\x02"], "W" => [101, "\x02"], "X" => [112, "\x02"], "Y" => [117, "\x02"], "Z" => [120, "\x02"], "[" => [124, "\x02"], "\\" => [127, "\x02"], "]" => [144, "\x02"], "^" => [152, "\x02"], "_" => [11, "\x02"], "`" => [0, "\x030"], "a" => [0, "\x031"], "b" => [0, "\x032"], "c" => [0, "\x03a"], "d" => [0, "\x03c"], "e" => [0, "\x03e"], "f" => [0, "\x03i"], "g" => [0, "\x03o"], "h" => [0, "\x03s"], "i" => [0, "\x03t"], "j" => [73, "\x03"], "k" => [88, "\x03"], "l" => [89, "\x03"], "m" => [96, "\x03"], "n" => [97, "\x03"], "o" => [99, "\x03"], "p" => [106, "\x03"], "q" => [136, "\x03"], "r" => [139, "\x03"], "s" => [141, "\x03"], "t" => [145, "\x03"], "u" => [147, "\x03"], "v" => [149, "\x03"], "w" => [101, "\x03"], "x" => [112, "\x03"], "y" => [117, "\x03"], "z" => [120, "\x03"], "{" => [124, "\x03"], "|" => [127, "\x03"], "}" => [144, "\x03"], "~" => [152, "\x03"], "" => [11, "\x03"], "\x80" => [0, "\x040"], "\x81" => [0, "\x041"], "\x82" => [0, "\x042"], "\x83" => [0, "\x04a"], "\x84" => [0, "\x04c"], "\x85" => [0, "\x04e"], "\x86" => [0, "\x04i"], "\x87" => [0, "\x04o"], "\x88" => [0, "\x04s"], "\x89" => [0, "\x04t"], "\x8a" => [73, "\x04"], "\x8b" => [88, "\x04"], "\x8c" => [89, "\x04"], "\x8d" => [96, "\x04"], "\x8e" => [97, "\x04"], "\x8f" => [99, "\x04"], "\x90" => [106, "\x04"], "\x91" => [136, "\x04"], "\x92" => [139, "\x04"], "\x93" => [141, "\x04"], "\x94" => [145, "\x04"], "\x95" => [147, "\x04"], "\x96" => [149, "\x04"], "\x97" => [101, "\x04"], "\x98" => [112, "\x04"], "\x99" => [117, "\x04"], "\x9a" => [120, "\x04"], "\x9b" => [124, "\x04"], "\x9c" => [127, "\x04"], "\x9d" => [144, "\x04"], "\x9e" => [152, "\x04"], "\x9f" => [11, "\x04"], "\xa0" => [0, "\x050"], "\xa1" => [0, "\x051"], "\xa2" => [0, "\x052"], "\xa3" => [0, "\x05a"], "\xa4" => [0, "\x05c"], "\xa5" => [0, "\x05e"], "\xa6" => [0, "\x05i"], "\xa7" => [0, "\x05o"], "\xa8" => [0, "\x05s"], "\xa9" => [0, "\x05t"], "\xaa" => [73, "\x05"], "\xab" => [88, "\x05"], "\xac" => [89, "\x05"], "\xad" => [96, "\x05"], "\xae" => [97, "\x05"], "\xaf" => [99, "\x05"], "\xb0" => [106, "\x05"], "\xb1" => [136, "\x05"], "\xb2" => [139, "\x05"], "\xb3" => [141, "\x05"], "\xb4" => [145, "\x05"], "\xb5" => [147, "\x05"], "\xb6" => [149, "\x05"], "\xb7" => [101, "\x05"], "\xb8" => [112, "\x05"], "\xb9" => [117, "\x05"], "\xba" => [120, "\x05"], "\xbb" => [124, "\x05"], "\xbc" => [127, "\x05"], "\xbd" => [144, "\x05"], "\xbe" => [152, "\x05"], "\xbf" => [11, "\x05"], "\xc0" => [0, "\x060"], "\xc1" => [0, "\x061"], "\xc2" => [0, "\x062"], "\xc3" => [0, "\x06a"], "\xc4" => [0, "\x06c"], "\xc5" => [0, "\x06e"], "\xc6" => [0, "\x06i"], "\xc7" => [0, "\x06o"], "\xc8" => [0, "\x06s"], "\xc9" => [0, "\x06t"], "\xca" => [73, "\x06"], "\xcb" => [88, "\x06"], "\xcc" => [89, "\x06"], "\xcd" => [96, "\x06"], "\xce" => [97, "\x06"], "\xcf" => [99, "\x06"], "\xd0" => [106, "\x06"], "\xd1" => [136, "\x06"], "\xd2" => [139, "\x06"], "\xd3" => [141, "\x06"], "\xd4" => [145, "\x06"], "\xd5" => [147, "\x06"], "\xd6" => [149, "\x06"], "\xd7" => [101, "\x06"], "\xd8" => [112, "\x06"], "\xd9" => [117, "\x06"], "\xda" => [120, "\x06"], "\xdb" => [124, "\x06"], "\xdc" => [127, "\x06"], "\xdd" => [144, "\x06"], "\xde" => [152, "\x06"], "\xdf" => [11, "\x06"], "\xe0" => [0, "\x070"], "\xe1" => [0, "\x071"], "\xe2" => [0, "\x072"], "\xe3" => [0, "\x07a"], "\xe4" => [0, "\x07c"], "\xe5" => [0, "\x07e"], "\xe6" => [0, "\x07i"], "\xe7" => [0, "\x07o"], "\xe8" => [0, "\x07s"], "\xe9" => [0, "\x07t"], "\xea" => [73, "\x07"], "\xeb" => [88, "\x07"], "\xec" => [89, "\x07"], "\xed" => [96, "\x07"], "\xee" => [97, "\x07"], "\xef" => [99, "\x07"], "\xf0" => [106, "\x07"], "\xf1" => [136, "\x07"], "\xf2" => [139, "\x07"], "\xf3" => [141, "\x07"], "\xf4" => [145, "\x07"], "\xf5" => [147, "\x07"], "\xf6" => [149, "\x07"], "\xf7" => [101, "\x07"], "\xf8" => [112, "\x07"], "\xf9" => [117, "\x07"], "\xfa" => [120, "\x07"], "\xfb" => [124, "\x07"], "\xfc" => [127, "\x07"], "\xfd" => [144, "\x07"], "\xfe" => [152, "\x07"], "\xff" => [11, "\x07"]], ["\x00" => [94, "\x040"], "\x01" => [76, "\x040"], "\x02" => [104, "\x040"], "\x03" => [16, "\x040"], "\x04" => [94, "\x041"], "\x05" => [76, "\x041"], "\x06" => [104, "\x041"], "\x07" => [16, "\x041"], "\x08" => [94, "\x042"], "\t" => [76, "\x042"], "\n" => [104, "\x042"], "\v" => [16, "\x042"], "\f" => [94, "\x04a"], "\r" => [76, "\x04a"], "\x0e" => [104, "\x04a"], "\x0f" => [16, "\x04a"], "\x10" => [94, "\x04c"], "\x11" => [76, "\x04c"], "\x12" => [104, "\x04c"], "\x13" => [16, "\x04c"], "\x14" => [94, "\x04e"], "\x15" => [76, "\x04e"], "\x16" => [104, "\x04e"], "\x17" => [16, "\x04e"], "\x18" => [94, "\x04i"], "\x19" => [76, "\x04i"], "\x1a" => [104, "\x04i"], "\x1b" => [16, "\x04i"], "\x1c" => [94, "\x04o"], "\x1d" => [76, "\x04o"], "\x1e" => [104, "\x04o"], "\x1f" => [16, "\x04o"], " " => [94, "\x04s"], "!" => [76, "\x04s"], "\"" => [104, "\x04s"], "#" => [16, "\x04s"], "\$" => [94, "\x04t"], "%" => [76, "\x04t"], "&" => [104, "\x04t"], "'" => [16, "\x04t"], "(" => [77, "\x04 "], ")" => [18, "\x04 "], "*" => [77, "\x04%"], "+" => [18, "\x04%"], "," => [77, "\x04-"], "-" => [18, "\x04-"], "." => [77, "\x04."], "/" => [18, "\x04."], [77, "\x04/"], [18, "\x04/"], [77, "\x043"], [18, "\x043"], [77, "\x044"], [18, "\x044"], [77, "\x045"], [18, "\x045"], [77, "\x046"], [18, "\x046"], ":" => [77, "\x047"], ";" => [18, "\x047"], "<" => [77, "\x048"], "=" => [18, "\x048"], ">" => [77, "\x049"], "?" => [18, "\x049"], "@" => [77, "\x04="], "A" => [18, "\x04="], "B" => [77, "\x04A"], "C" => [18, "\x04A"], "D" => [77, "\x04_"], "E" => [18, "\x04_"], "F" => [77, "\x04b"], "G" => [18, "\x04b"], "H" => [77, "\x04d"], "I" => [18, "\x04d"], "J" => [77, "\x04f"], "K" => [18, "\x04f"], "L" => [77, "\x04g"], "M" => [18, "\x04g"], "N" => [77, "\x04h"], "O" => [18, "\x04h"], "P" => [77, "\x04l"], "Q" => [18, "\x04l"], "R" => [77, "\x04m"], "S" => [18, "\x04m"], "T" => [77, "\x04n"], "U" => [18, "\x04n"], "V" => [77, "\x04p"], "W" => [18, "\x04p"], "X" => [77, "\x04r"], "Y" => [18, "\x04r"], "Z" => [77, "\x04u"], "[" => [18, "\x04u"], "\\" => [0, "\x04:"], "]" => [0, "\x04B"], "^" => [0, "\x04C"], "_" => [0, "\x04D"], "`" => [0, "\x04E"], "a" => [0, "\x04F"], "b" => [0, "\x04G"], "c" => [0, "\x04H"], "d" => [0, "\x04I"], "e" => [0, "\x04J"], "f" => [0, "\x04K"], "g" => [0, "\x04L"], "h" => [0, "\x04M"], "i" => [0, "\x04N"], "j" => [0, "\x04O"], "k" => [0, "\x04P"], "l" => [0, "\x04Q"], "m" => [0, "\x04R"], "n" => [0, "\x04S"], "o" => [0, "\x04T"], "p" => [0, "\x04U"], "q" => [0, "\x04V"], "r" => [0, "\x04W"], "s" => [0, "\x04Y"], "t" => [0, "\x04j"], "u" => [0, "\x04k"], "v" => [0, "\x04q"], "w" => [0, "\x04v"], "x" => [0, "\x04w"], "y" => [0, "\x04x"], "z" => [0, "\x04y"], "{" => [0, "\x04z"], "|" => [82, "\x04"], "}" => [87, "\x04"], "~" => [130, "\x04"], "" => [9, "\x04"], "\x80" => [94, "\x050"], "\x81" => [76, "\x050"], "\x82" => [104, "\x050"], "\x83" => [16, "\x050"], "\x84" => [94, "\x051"], "\x85" => [76, "\x051"], "\x86" => [104, "\x051"], "\x87" => [16, "\x051"], "\x88" => [94, "\x052"], "\x89" => [76, "\x052"], "\x8a" => [104, "\x052"], "\x8b" => [16, "\x052"], "\x8c" => [94, "\x05a"], "\x8d" => [76, "\x05a"], "\x8e" => [104, "\x05a"], "\x8f" => [16, "\x05a"], "\x90" => [94, "\x05c"], "\x91" => [76, "\x05c"], "\x92" => [104, "\x05c"], "\x93" => [16, "\x05c"], "\x94" => [94, "\x05e"], "\x95" => [76, "\x05e"], "\x96" => [104, "\x05e"], "\x97" => [16, "\x05e"], "\x98" => [94, "\x05i"], "\x99" => [76, "\x05i"], "\x9a" => [104, "\x05i"], "\x9b" => [16, "\x05i"], "\x9c" => [94, "\x05o"], "\x9d" => [76, "\x05o"], "\x9e" => [104, "\x05o"], "\x9f" => [16, "\x05o"], "\xa0" => [94, "\x05s"], "\xa1" => [76, "\x05s"], "\xa2" => [104, "\x05s"], "\xa3" => [16, "\x05s"], "\xa4" => [94, "\x05t"], "\xa5" => [76, "\x05t"], "\xa6" => [104, "\x05t"], "\xa7" => [16, "\x05t"], "\xa8" => [77, "\x05 "], "\xa9" => [18, "\x05 "], "\xaa" => [77, "\x05%"], "\xab" => [18, "\x05%"], "\xac" => [77, "\x05-"], "\xad" => [18, "\x05-"], "\xae" => [77, "\x05."], "\xaf" => [18, "\x05."], "\xb0" => [77, "\x05/"], "\xb1" => [18, "\x05/"], "\xb2" => [77, "\x053"], "\xb3" => [18, "\x053"], "\xb4" => [77, "\x054"], "\xb5" => [18, "\x054"], "\xb6" => [77, "\x055"], "\xb7" => [18, "\x055"], "\xb8" => [77, "\x056"], "\xb9" => [18, "\x056"], "\xba" => [77, "\x057"], "\xbb" => [18, "\x057"], "\xbc" => [77, "\x058"], "\xbd" => [18, "\x058"], "\xbe" => [77, "\x059"], "\xbf" => [18, "\x059"], "\xc0" => [77, "\x05="], "\xc1" => [18, "\x05="], "\xc2" => [77, "\x05A"], "\xc3" => [18, "\x05A"], "\xc4" => [77, "\x05_"], "\xc5" => [18, "\x05_"], "\xc6" => [77, "\x05b"], "\xc7" => [18, "\x05b"], "\xc8" => [77, "\x05d"], "\xc9" => [18, "\x05d"], "\xca" => [77, "\x05f"], "\xcb" => [18, "\x05f"], "\xcc" => [77, "\x05g"], "\xcd" => [18, "\x05g"], "\xce" => [77, "\x05h"], "\xcf" => [18, "\x05h"], "\xd0" => [77, "\x05l"], "\xd1" => [18, "\x05l"], "\xd2" => [77, "\x05m"], "\xd3" => [18, "\x05m"], "\xd4" => [77, "\x05n"], "\xd5" => [18, "\x05n"], "\xd6" => [77, "\x05p"], "\xd7" => [18, "\x05p"], "\xd8" => [77, "\x05r"], "\xd9" => [18, "\x05r"], "\xda" => [77, "\x05u"], "\xdb" => [18, "\x05u"], "\xdc" => [0, "\x05:"], "\xdd" => [0, "\x05B"], "\xde" => [0, "\x05C"], "\xdf" => [0, "\x05D"], "\xe0" => [0, "\x05E"], "\xe1" => [0, "\x05F"], "\xe2" => [0, "\x05G"], "\xe3" => [0, "\x05H"], "\xe4" => [0, "\x05I"], "\xe5" => [0, "\x05J"], "\xe6" => [0, "\x05K"], "\xe7" => [0, "\x05L"], "\xe8" => [0, "\x05M"], "\xe9" => [0, "\x05N"], "\xea" => [0, "\x05O"], "\xeb" => [0, "\x05P"], "\xec" => [0, "\x05Q"], "\xed" => [0, "\x05R"], "\xee" => [0, "\x05S"], "\xef" => [0, "\x05T"], "\xf0" => [0, "\x05U"], "\xf1" => [0, "\x05V"], "\xf2" => [0, "\x05W"], "\xf3" => [0, "\x05Y"], "\xf4" => [0, "\x05j"], "\xf5" => [0, "\x05k"], "\xf6" => [0, "\x05q"], "\xf7" => [0, "\x05v"], "\xf8" => [0, "\x05w"], "\xf9" => [0, "\x05x"], "\xfa" => [0, "\x05y"], "\xfb" => [0, "\x05z"], "\xfc" => [82, "\x05"], "\xfd" => [87, "\x05"], "\xfe" => [130, "\x05"], "\xff" => [9, "\x05"]], ["\x00" => [77, "\x040"], "\x01" => [18, "\x040"], "\x02" => [77, "\x041"], "\x03" => [18, "\x041"], "\x04" => [77, "\x042"], "\x05" => [18, "\x042"], "\x06" => [77, "\x04a"], "\x07" => [18, "\x04a"], "\x08" => [77, "\x04c"], "\t" => [18, "\x04c"], "\n" => [77, "\x04e"], "\v" => [18, "\x04e"], "\f" => [77, "\x04i"], "\r" => [18, "\x04i"], "\x0e" => [77, "\x04o"], "\x0f" => [18, "\x04o"], "\x10" => [77, "\x04s"], "\x11" => [18, "\x04s"], "\x12" => [77, "\x04t"], "\x13" => [18, "\x04t"], "\x14" => [0, "\x04 "], "\x15" => [0, "\x04%"], "\x16" => [0, "\x04-"], "\x17" => [0, "\x04."], "\x18" => [0, "\x04/"], "\x19" => [0, "\x043"], "\x1a" => [0, "\x044"], "\x1b" => [0, "\x045"], "\x1c" => [0, "\x046"], "\x1d" => [0, "\x047"], "\x1e" => [0, "\x048"], "\x1f" => [0, "\x049"], " " => [0, "\x04="], "!" => [0, "\x04A"], "\"" => [0, "\x04_"], "#" => [0, "\x04b"], "\$" => [0, "\x04d"], "%" => [0, "\x04f"], "&" => [0, "\x04g"], "'" => [0, "\x04h"], "(" => [0, "\x04l"], ")" => [0, "\x04m"], "*" => [0, "\x04n"], "+" => [0, "\x04p"], "," => [0, "\x04r"], "-" => [0, "\x04u"], "." => [100, "\x04"], "/" => [110, "\x04"], [111, "\x04"], [115, "\x04"], [116, "\x04"], [118, "\x04"], [119, "\x04"], [122, "\x04"], [123, "\x04"], [125, "\x04"], [126, "\x04"], [129, "\x04"], ":" => [143, "\x04"], ";" => [148, "\x04"], "<" => [151, "\x04"], "=" => [153, "\x04"], ">" => [83, "\x04"], "?" => [10, "\x04"], "@" => [77, "\x050"], "A" => [18, "\x050"], "B" => [77, "\x051"], "C" => [18, "\x051"], "D" => [77, "\x052"], "E" => [18, "\x052"], "F" => [77, "\x05a"], "G" => [18, "\x05a"], "H" => [77, "\x05c"], "I" => [18, "\x05c"], "J" => [77, "\x05e"], "K" => [18, "\x05e"], "L" => [77, "\x05i"], "M" => [18, "\x05i"], "N" => [77, "\x05o"], "O" => [18, "\x05o"], "P" => [77, "\x05s"], "Q" => [18, "\x05s"], "R" => [77, "\x05t"], "S" => [18, "\x05t"], "T" => [0, "\x05 "], "U" => [0, "\x05%"], "V" => [0, "\x05-"], "W" => [0, "\x05."], "X" => [0, "\x05/"], "Y" => [0, "\x053"], "Z" => [0, "\x054"], "[" => [0, "\x055"], "\\" => [0, "\x056"], "]" => [0, "\x057"], "^" => [0, "\x058"], "_" => [0, "\x059"], "`" => [0, "\x05="], "a" => [0, "\x05A"], "b" => [0, "\x05_"], "c" => [0, "\x05b"], "d" => [0, "\x05d"], "e" => [0, "\x05f"], "f" => [0, "\x05g"], "g" => [0, "\x05h"], "h" => [0, "\x05l"], "i" => [0, "\x05m"], "j" => [0, "\x05n"], "k" => [0, "\x05p"], "l" => [0, "\x05r"], "m" => [0, "\x05u"], "n" => [100, "\x05"], "o" => [110, "\x05"], "p" => [111, "\x05"], "q" => [115, "\x05"], "r" => [116, "\x05"], "s" => [118, "\x05"], "t" => [119, "\x05"], "u" => [122, "\x05"], "v" => [123, "\x05"], "w" => [125, "\x05"], "x" => [126, "\x05"], "y" => [129, "\x05"], "z" => [143, "\x05"], "{" => [148, "\x05"], "|" => [151, "\x05"], "}" => [153, "\x05"], "~" => [83, "\x05"], "" => [10, "\x05"], "\x80" => [77, "\x060"], "\x81" => [18, "\x060"], "\x82" => [77, "\x061"], "\x83" => [18, "\x061"], "\x84" => [77, "\x062"], "\x85" => [18, "\x062"], "\x86" => [77, "\x06a"], "\x87" => [18, "\x06a"], "\x88" => [77, "\x06c"], "\x89" => [18, "\x06c"], "\x8a" => [77, "\x06e"], "\x8b" => [18, "\x06e"], "\x8c" => [77, "\x06i"], "\x8d" => [18, "\x06i"], "\x8e" => [77, "\x06o"], "\x8f" => [18, "\x06o"], "\x90" => [77, "\x06s"], "\x91" => [18, "\x06s"], "\x92" => [77, "\x06t"], "\x93" => [18, "\x06t"], "\x94" => [0, "\x06 "], "\x95" => [0, "\x06%"], "\x96" => [0, "\x06-"], "\x97" => [0, "\x06."], "\x98" => [0, "\x06/"], "\x99" => [0, "\x063"], "\x9a" => [0, "\x064"], "\x9b" => [0, "\x065"], "\x9c" => [0, "\x066"], "\x9d" => [0, "\x067"], "\x9e" => [0, "\x068"], "\x9f" => [0, "\x069"], "\xa0" => [0, "\x06="], "\xa1" => [0, "\x06A"], "\xa2" => [0, "\x06_"], "\xa3" => [0, "\x06b"], "\xa4" => [0, "\x06d"], "\xa5" => [0, "\x06f"], "\xa6" => [0, "\x06g"], "\xa7" => [0, "\x06h"], "\xa8" => [0, "\x06l"], "\xa9" => [0, "\x06m"], "\xaa" => [0, "\x06n"], "\xab" => [0, "\x06p"], "\xac" => [0, "\x06r"], "\xad" => [0, "\x06u"], "\xae" => [100, "\x06"], "\xaf" => [110, "\x06"], "\xb0" => [111, "\x06"], "\xb1" => [115, "\x06"], "\xb2" => [116, "\x06"], "\xb3" => [118, "\x06"], "\xb4" => [119, "\x06"], "\xb5" => [122, "\x06"], "\xb6" => [123, "\x06"], "\xb7" => [125, "\x06"], "\xb8" => [126, "\x06"], "\xb9" => [129, "\x06"], "\xba" => [143, "\x06"], "\xbb" => [148, "\x06"], "\xbc" => [151, "\x06"], "\xbd" => [153, "\x06"], "\xbe" => [83, "\x06"], "\xbf" => [10, "\x06"], "\xc0" => [77, "\x070"], "\xc1" => [18, "\x070"], "\xc2" => [77, "\x071"], "\xc3" => [18, "\x071"], "\xc4" => [77, "\x072"], "\xc5" => [18, "\x072"], "\xc6" => [77, "\x07a"], "\xc7" => [18, "\x07a"], "\xc8" => [77, "\x07c"], "\xc9" => [18, "\x07c"], "\xca" => [77, "\x07e"], "\xcb" => [18, "\x07e"], "\xcc" => [77, "\x07i"], "\xcd" => [18, "\x07i"], "\xce" => [77, "\x07o"], "\xcf" => [18, "\x07o"], "\xd0" => [77, "\x07s"], "\xd1" => [18, "\x07s"], "\xd2" => [77, "\x07t"], "\xd3" => [18, "\x07t"], "\xd4" => [0, "\x07 "], "\xd5" => [0, "\x07%"], "\xd6" => [0, "\x07-"], "\xd7" => [0, "\x07."], "\xd8" => [0, "\x07/"], "\xd9" => [0, "\x073"], "\xda" => [0, "\x074"], "\xdb" => [0, "\x075"], "\xdc" => [0, "\x076"], "\xdd" => [0, "\x077"], "\xde" => [0, "\x078"], "\xdf" => [0, "\x079"], "\xe0" => [0, "\x07="], "\xe1" => [0, "\x07A"], "\xe2" => [0, "\x07_"], "\xe3" => [0, "\x07b"], "\xe4" => [0, "\x07d"], "\xe5" => [0, "\x07f"], "\xe6" => [0, "\x07g"], "\xe7" => [0, "\x07h"], "\xe8" => [0, "\x07l"], "\xe9" => [0, "\x07m"], "\xea" => [0, "\x07n"], "\xeb" => [0, "\x07p"], "\xec" => [0, "\x07r"], "\xed" => [0, "\x07u"], "\xee" => [100, "\x07"], "\xef" => [110, "\x07"], "\xf0" => [111, "\x07"], "\xf1" => [115, "\x07"], "\xf2" => [116, "\x07"], "\xf3" => [118, "\x07"], "\xf4" => [119, "\x07"], "\xf5" => [122, "\x07"], "\xf6" => [123, "\x07"], "\xf7" => [125, "\x07"], "\xf8" => [126, "\x07"], "\xf9" => [129, "\x07"], "\xfa" => [143, "\x07"], "\xfb" => [148, "\x07"], "\xfc" => [151, "\x07"], "\xfd" => [153, "\x07"], "\xfe" => [83, "\x07"], "\xff" => [10, "\x07"]], ["\x00" => [94, "\x060"], "\x01" => [76, "\x060"], "\x02" => [104, "\x060"], "\x03" => [16, "\x060"], "\x04" => [94, "\x061"], "\x05" => [76, "\x061"], "\x06" => [104, "\x061"], "\x07" => [16, "\x061"], "\x08" => [94, "\x062"], "\t" => [76, "\x062"], "\n" => [104, "\x062"], "\v" => [16, "\x062"], "\f" => [94, "\x06a"], "\r" => [76, "\x06a"], "\x0e" => [104, "\x06a"], "\x0f" => [16, "\x06a"], "\x10" => [94, "\x06c"], "\x11" => [76, "\x06c"], "\x12" => [104, "\x06c"], "\x13" => [16, "\x06c"], "\x14" => [94, "\x06e"], "\x15" => [76, "\x06e"], "\x16" => [104, "\x06e"], "\x17" => [16, "\x06e"], "\x18" => [94, "\x06i"], "\x19" => [76, "\x06i"], "\x1a" => [104, "\x06i"], "\x1b" => [16, "\x06i"], "\x1c" => [94, "\x06o"], "\x1d" => [76, "\x06o"], "\x1e" => [104, "\x06o"], "\x1f" => [16, "\x06o"], " " => [94, "\x06s"], "!" => [76, "\x06s"], "\"" => [104, "\x06s"], "#" => [16, "\x06s"], "\$" => [94, "\x06t"], "%" => [76, "\x06t"], "&" => [104, "\x06t"], "'" => [16, "\x06t"], "(" => [77, "\x06 "], ")" => [18, "\x06 "], "*" => [77, "\x06%"], "+" => [18, "\x06%"], "," => [77, "\x06-"], "-" => [18, "\x06-"], "." => [77, "\x06."], "/" => [18, "\x06."], [77, "\x06/"], [18, "\x06/"], [77, "\x063"], [18, "\x063"], [77, "\x064"], [18, "\x064"], [77, "\x065"], [18, "\x065"], [77, "\x066"], [18, "\x066"], ":" => [77, "\x067"], ";" => [18, "\x067"], "<" => [77, "\x068"], "=" => [18, "\x068"], ">" => [77, "\x069"], "?" => [18, "\x069"], "@" => [77, "\x06="], "A" => [18, "\x06="], "B" => [77, "\x06A"], "C" => [18, "\x06A"], "D" => [77, "\x06_"], "E" => [18, "\x06_"], "F" => [77, "\x06b"], "G" => [18, "\x06b"], "H" => [77, "\x06d"], "I" => [18, "\x06d"], "J" => [77, "\x06f"], "K" => [18, "\x06f"], "L" => [77, "\x06g"], "M" => [18, "\x06g"], "N" => [77, "\x06h"], "O" => [18, "\x06h"], "P" => [77, "\x06l"], "Q" => [18, "\x06l"], "R" => [77, "\x06m"], "S" => [18, "\x06m"], "T" => [77, "\x06n"], "U" => [18, "\x06n"], "V" => [77, "\x06p"], "W" => [18, "\x06p"], "X" => [77, "\x06r"], "Y" => [18, "\x06r"], "Z" => [77, "\x06u"], "[" => [18, "\x06u"], "\\" => [0, "\x06:"], "]" => [0, "\x06B"], "^" => [0, "\x06C"], "_" => [0, "\x06D"], "`" => [0, "\x06E"], "a" => [0, "\x06F"], "b" => [0, "\x06G"], "c" => [0, "\x06H"], "d" => [0, "\x06I"], "e" => [0, "\x06J"], "f" => [0, "\x06K"], "g" => [0, "\x06L"], "h" => [0, "\x06M"], "i" => [0, "\x06N"], "j" => [0, "\x06O"], "k" => [0, "\x06P"], "l" => [0, "\x06Q"], "m" => [0, "\x06R"], "n" => [0, "\x06S"], "o" => [0, "\x06T"], "p" => [0, "\x06U"], "q" => [0, "\x06V"], "r" => [0, "\x06W"], "s" => [0, "\x06Y"], "t" => [0, "\x06j"], "u" => [0, "\x06k"], "v" => [0, "\x06q"], "w" => [0, "\x06v"], "x" => [0, "\x06w"], "y" => [0, "\x06x"], "z" => [0, "\x06y"], "{" => [0, "\x06z"], "|" => [82, "\x06"], "}" => [87, "\x06"], "~" => [130, "\x06"], "" => [9, "\x06"], "\x80" => [94, "\x070"], "\x81" => [76, "\x070"], "\x82" => [104, "\x070"], "\x83" => [16, "\x070"], "\x84" => [94, "\x071"], "\x85" => [76, "\x071"], "\x86" => [104, "\x071"], "\x87" => [16, "\x071"], "\x88" => [94, "\x072"], "\x89" => [76, "\x072"], "\x8a" => [104, "\x072"], "\x8b" => [16, "\x072"], "\x8c" => [94, "\x07a"], "\x8d" => [76, "\x07a"], "\x8e" => [104, "\x07a"], "\x8f" => [16, "\x07a"], "\x90" => [94, "\x07c"], "\x91" => [76, "\x07c"], "\x92" => [104, "\x07c"], "\x93" => [16, "\x07c"], "\x94" => [94, "\x07e"], "\x95" => [76, "\x07e"], "\x96" => [104, "\x07e"], "\x97" => [16, "\x07e"], "\x98" => [94, "\x07i"], "\x99" => [76, "\x07i"], "\x9a" => [104, "\x07i"], "\x9b" => [16, "\x07i"], "\x9c" => [94, "\x07o"], "\x9d" => [76, "\x07o"], "\x9e" => [104, "\x07o"], "\x9f" => [16, "\x07o"], "\xa0" => [94, "\x07s"], "\xa1" => [76, "\x07s"], "\xa2" => [104, "\x07s"], "\xa3" => [16, "\x07s"], "\xa4" => [94, "\x07t"], "\xa5" => [76, "\x07t"], "\xa6" => [104, "\x07t"], "\xa7" => [16, "\x07t"], "\xa8" => [77, "\x07 "], "\xa9" => [18, "\x07 "], "\xaa" => [77, "\x07%"], "\xab" => [18, "\x07%"], "\xac" => [77, "\x07-"], "\xad" => [18, "\x07-"], "\xae" => [77, "\x07."], "\xaf" => [18, "\x07."], "\xb0" => [77, "\x07/"], "\xb1" => [18, "\x07/"], "\xb2" => [77, "\x073"], "\xb3" => [18, "\x073"], "\xb4" => [77, "\x074"], "\xb5" => [18, "\x074"], "\xb6" => [77, "\x075"], "\xb7" => [18, "\x075"], "\xb8" => [77, "\x076"], "\xb9" => [18, "\x076"], "\xba" => [77, "\x077"], "\xbb" => [18, "\x077"], "\xbc" => [77, "\x078"], "\xbd" => [18, "\x078"], "\xbe" => [77, "\x079"], "\xbf" => [18, "\x079"], "\xc0" => [77, "\x07="], "\xc1" => [18, "\x07="], "\xc2" => [77, "\x07A"], "\xc3" => [18, "\x07A"], "\xc4" => [77, "\x07_"], "\xc5" => [18, "\x07_"], "\xc6" => [77, "\x07b"], "\xc7" => [18, "\x07b"], "\xc8" => [77, "\x07d"], "\xc9" => [18, "\x07d"], "\xca" => [77, "\x07f"], "\xcb" => [18, "\x07f"], "\xcc" => [77, "\x07g"], "\xcd" => [18, "\x07g"], "\xce" => [77, "\x07h"], "\xcf" => [18, "\x07h"], "\xd0" => [77, "\x07l"], "\xd1" => [18, "\x07l"], "\xd2" => [77, "\x07m"], "\xd3" => [18, "\x07m"], "\xd4" => [77, "\x07n"], "\xd5" => [18, "\x07n"], "\xd6" => [77, "\x07p"], "\xd7" => [18, "\x07p"], "\xd8" => [77, "\x07r"], "\xd9" => [18, "\x07r"], "\xda" => [77, "\x07u"], "\xdb" => [18, "\x07u"], "\xdc" => [0, "\x07:"], "\xdd" => [0, "\x07B"], "\xde" => [0, "\x07C"], "\xdf" => [0, "\x07D"], "\xe0" => [0, "\x07E"], "\xe1" => [0, "\x07F"], "\xe2" => [0, "\x07G"], "\xe3" => [0, "\x07H"], "\xe4" => [0, "\x07I"], "\xe5" => [0, "\x07J"], "\xe6" => [0, "\x07K"], "\xe7" => [0, "\x07L"], "\xe8" => [0, "\x07M"], "\xe9" => [0, "\x07N"], "\xea" => [0, "\x07O"], "\xeb" => [0, "\x07P"], "\xec" => [0, "\x07Q"], "\xed" => [0, "\x07R"], "\xee" => [0, "\x07S"], "\xef" => [0, "\x07T"], "\xf0" => [0, "\x07U"], "\xf1" => [0, "\x07V"], "\xf2" => [0, "\x07W"], "\xf3" => [0, "\x07Y"], "\xf4" => [0, "\x07j"], "\xf5" => [0, "\x07k"], "\xf6" => [0, "\x07q"], "\xf7" => [0, "\x07v"], "\xf8" => [0, "\x07w"], "\xf9" => [0, "\x07x"], "\xfa" => [0, "\x07y"], "\xfb" => [0, "\x07z"], "\xfc" => [82, "\x07"], "\xfd" => [87, "\x07"], "\xfe" => [130, "\x07"], "\xff" => [9, "\x07"]], ["\x00" => [94, "\x080"], "\x01" => [76, "\x080"], "\x02" => [104, "\x080"], "\x03" => [16, "\x080"], "\x04" => [94, "\x081"], "\x05" => [76, "\x081"], "\x06" => [104, "\x081"], "\x07" => [16, "\x081"], "\x08" => [94, "\x082"], "\t" => [76, "\x082"], "\n" => [104, "\x082"], "\v" => [16, "\x082"], "\f" => [94, "\x08a"], "\r" => [76, "\x08a"], "\x0e" => [104, "\x08a"], "\x0f" => [16, "\x08a"], "\x10" => [94, "\x08c"], "\x11" => [76, "\x08c"], "\x12" => [104, "\x08c"], "\x13" => [16, "\x08c"], "\x14" => [94, "\x08e"], "\x15" => [76, "\x08e"], "\x16" => [104, "\x08e"], "\x17" => [16, "\x08e"], "\x18" => [94, "\x08i"], "\x19" => [76, "\x08i"], "\x1a" => [104, "\x08i"], "\x1b" => [16, "\x08i"], "\x1c" => [94, "\x08o"], "\x1d" => [76, "\x08o"], "\x1e" => [104, "\x08o"], "\x1f" => [16, "\x08o"], " " => [94, "\x08s"], "!" => [76, "\x08s"], "\"" => [104, "\x08s"], "#" => [16, "\x08s"], "\$" => [94, "\x08t"], "%" => [76, "\x08t"], "&" => [104, "\x08t"], "'" => [16, "\x08t"], "(" => [77, "\x08 "], ")" => [18, "\x08 "], "*" => [77, "\x08%"], "+" => [18, "\x08%"], "," => [77, "\x08-"], "-" => [18, "\x08-"], "." => [77, "\x08."], "/" => [18, "\x08."], [77, "\x08/"], [18, "\x08/"], [77, "\x083"], [18, "\x083"], [77, "\x084"], [18, "\x084"], [77, "\x085"], [18, "\x085"], [77, "\x086"], [18, "\x086"], ":" => [77, "\x087"], ";" => [18, "\x087"], "<" => [77, "\x088"], "=" => [18, "\x088"], ">" => [77, "\x089"], "?" => [18, "\x089"], "@" => [77, "\x08="], "A" => [18, "\x08="], "B" => [77, "\x08A"], "C" => [18, "\x08A"], "D" => [77, "\x08_"], "E" => [18, "\x08_"], "F" => [77, "\x08b"], "G" => [18, "\x08b"], "H" => [77, "\x08d"], "I" => [18, "\x08d"], "J" => [77, "\x08f"], "K" => [18, "\x08f"], "L" => [77, "\x08g"], "M" => [18, "\x08g"], "N" => [77, "\x08h"], "O" => [18, "\x08h"], "P" => [77, "\x08l"], "Q" => [18, "\x08l"], "R" => [77, "\x08m"], "S" => [18, "\x08m"], "T" => [77, "\x08n"], "U" => [18, "\x08n"], "V" => [77, "\x08p"], "W" => [18, "\x08p"], "X" => [77, "\x08r"], "Y" => [18, "\x08r"], "Z" => [77, "\x08u"], "[" => [18, "\x08u"], "\\" => [0, "\x08:"], "]" => [0, "\x08B"], "^" => [0, "\x08C"], "_" => [0, "\x08D"], "`" => [0, "\x08E"], "a" => [0, "\x08F"], "b" => [0, "\x08G"], "c" => [0, "\x08H"], "d" => [0, "\x08I"], "e" => [0, "\x08J"], "f" => [0, "\x08K"], "g" => [0, "\x08L"], "h" => [0, "\x08M"], "i" => [0, "\x08N"], "j" => [0, "\x08O"], "k" => [0, "\x08P"], "l" => [0, "\x08Q"], "m" => [0, "\x08R"], "n" => [0, "\x08S"], "o" => [0, "\x08T"], "p" => [0, "\x08U"], "q" => [0, "\x08V"], "r" => [0, "\x08W"], "s" => [0, "\x08Y"], "t" => [0, "\x08j"], "u" => [0, "\x08k"], "v" => [0, "\x08q"], "w" => [0, "\x08v"], "x" => [0, "\x08w"], "y" => [0, "\x08x"], "z" => [0, "\x08y"], "{" => [0, "\x08z"], "|" => [82, "\x08"], "}" => [87, "\x08"], "~" => [130, "\x08"], "" => [9, "\x08"], "\x80" => [94, "\v0"], "\x81" => [76, "\v0"], "\x82" => [104, "\v0"], "\x83" => [16, "\v0"], "\x84" => [94, "\v1"], "\x85" => [76, "\v1"], "\x86" => [104, "\v1"], "\x87" => [16, "\v1"], "\x88" => [94, "\v2"], "\x89" => [76, "\v2"], "\x8a" => [104, "\v2"], "\x8b" => [16, "\v2"], "\x8c" => [94, "\va"], "\x8d" => [76, "\va"], "\x8e" => [104, "\va"], "\x8f" => [16, "\va"], "\x90" => [94, "\vc"], "\x91" => [76, "\vc"], "\x92" => [104, "\vc"], "\x93" => [16, "\vc"], "\x94" => [94, "\ve"], "\x95" => [76, "\ve"], "\x96" => [104, "\ve"], "\x97" => [16, "\ve"], "\x98" => [94, "\vi"], "\x99" => [76, "\vi"], "\x9a" => [104, "\vi"], "\x9b" => [16, "\vi"], "\x9c" => [94, "\vo"], "\x9d" => [76, "\vo"], "\x9e" => [104, "\vo"], "\x9f" => [16, "\vo"], "\xa0" => [94, "\vs"], "\xa1" => [76, "\vs"], "\xa2" => [104, "\vs"], "\xa3" => [16, "\vs"], "\xa4" => [94, "\vt"], "\xa5" => [76, "\vt"], "\xa6" => [104, "\vt"], "\xa7" => [16, "\vt"], "\xa8" => [77, "\v "], "\xa9" => [18, "\v "], "\xaa" => [77, "\v%"], "\xab" => [18, "\v%"], "\xac" => [77, "\v-"], "\xad" => [18, "\v-"], "\xae" => [77, "\v."], "\xaf" => [18, "\v."], "\xb0" => [77, "\v/"], "\xb1" => [18, "\v/"], "\xb2" => [77, "\v3"], "\xb3" => [18, "\v3"], "\xb4" => [77, "\v4"], "\xb5" => [18, "\v4"], "\xb6" => [77, "\v5"], "\xb7" => [18, "\v5"], "\xb8" => [77, "\v6"], "\xb9" => [18, "\v6"], "\xba" => [77, "\v7"], "\xbb" => [18, "\v7"], "\xbc" => [77, "\v8"], "\xbd" => [18, "\v8"], "\xbe" => [77, "\v9"], "\xbf" => [18, "\v9"], "\xc0" => [77, "\v="], "\xc1" => [18, "\v="], "\xc2" => [77, "\vA"], "\xc3" => [18, "\vA"], "\xc4" => [77, "\v_"], "\xc5" => [18, "\v_"], "\xc6" => [77, "\vb"], "\xc7" => [18, "\vb"], "\xc8" => [77, "\vd"], "\xc9" => [18, "\vd"], "\xca" => [77, "\vf"], "\xcb" => [18, "\vf"], "\xcc" => [77, "\vg"], "\xcd" => [18, "\vg"], "\xce" => [77, "\vh"], "\xcf" => [18, "\vh"], "\xd0" => [77, "\vl"], "\xd1" => [18, "\vl"], "\xd2" => [77, "\vm"], "\xd3" => [18, "\vm"], "\xd4" => [77, "\vn"], "\xd5" => [18, "\vn"], "\xd6" => [77, "\vp"], "\xd7" => [18, "\vp"], "\xd8" => [77, "\vr"], "\xd9" => [18, "\vr"], "\xda" => [77, "\vu"], "\xdb" => [18, "\vu"], "\xdc" => [0, "\v:"], "\xdd" => [0, "\vB"], "\xde" => [0, "\vC"], "\xdf" => [0, "\vD"], "\xe0" => [0, "\vE"], "\xe1" => [0, "\vF"], "\xe2" => [0, "\vG"], "\xe3" => [0, "\vH"], "\xe4" => [0, "\vI"], "\xe5" => [0, "\vJ"], "\xe6" => [0, "\vK"], "\xe7" => [0, "\vL"], "\xe8" => [0, "\vM"], "\xe9" => [0, "\vN"], "\xea" => [0, "\vO"], "\xeb" => [0, "\vP"], "\xec" => [0, "\vQ"], "\xed" => [0, "\vR"], "\xee" => [0, "\vS"], "\xef" => [0, "\vT"], "\xf0" => [0, "\vU"], "\xf1" => [0, "\vV"], "\xf2" => [0, "\vW"], "\xf3" => [0, "\vY"], "\xf4" => [0, "\vj"], "\xf5" => [0, "\vk"], "\xf6" => [0, "\vq"], "\xf7" => [0, "\vv"], "\xf8" => [0, "\vw"], "\xf9" => [0, "\vx"], "\xfa" => [0, "\vy"], "\xfb" => [0, "\vz"], "\xfc" => [82, "\v"], "\xfd" => [87, "\v"], "\xfe" => [130, "\v"], "\xff" => [9, "\v"]], ["\x00" => [77, "\x080"], "\x01" => [18, "\x080"], "\x02" => [77, "\x081"], "\x03" => [18, "\x081"], "\x04" => [77, "\x082"], "\x05" => [18, "\x082"], "\x06" => [77, "\x08a"], "\x07" => [18, "\x08a"], "\x08" => [77, "\x08c"], "\t" => [18, "\x08c"], "\n" => [77, "\x08e"], "\v" => [18, "\x08e"], "\f" => [77, "\x08i"], "\r" => [18, "\x08i"], "\x0e" => [77, "\x08o"], "\x0f" => [18, "\x08o"], "\x10" => [77, "\x08s"], "\x11" => [18, "\x08s"], "\x12" => [77, "\x08t"], "\x13" => [18, "\x08t"], "\x14" => [0, "\x08 "], "\x15" => [0, "\x08%"], "\x16" => [0, "\x08-"], "\x17" => [0, "\x08."], "\x18" => [0, "\x08/"], "\x19" => [0, "\x083"], "\x1a" => [0, "\x084"], "\x1b" => [0, "\x085"], "\x1c" => [0, "\x086"], "\x1d" => [0, "\x087"], "\x1e" => [0, "\x088"], "\x1f" => [0, "\x089"], " " => [0, "\x08="], "!" => [0, "\x08A"], "\"" => [0, "\x08_"], "#" => [0, "\x08b"], "\$" => [0, "\x08d"], "%" => [0, "\x08f"], "&" => [0, "\x08g"], "'" => [0, "\x08h"], "(" => [0, "\x08l"], ")" => [0, "\x08m"], "*" => [0, "\x08n"], "+" => [0, "\x08p"], "," => [0, "\x08r"], "-" => [0, "\x08u"], "." => [100, "\x08"], "/" => [110, "\x08"], [111, "\x08"], [115, "\x08"], [116, "\x08"], [118, "\x08"], [119, "\x08"], [122, "\x08"], [123, "\x08"], [125, "\x08"], [126, "\x08"], [129, "\x08"], ":" => [143, "\x08"], ";" => [148, "\x08"], "<" => [151, "\x08"], "=" => [153, "\x08"], ">" => [83, "\x08"], "?" => [10, "\x08"], "@" => [77, "\v0"], "A" => [18, "\v0"], "B" => [77, "\v1"], "C" => [18, "\v1"], "D" => [77, "\v2"], "E" => [18, "\v2"], "F" => [77, "\va"], "G" => [18, "\va"], "H" => [77, "\vc"], "I" => [18, "\vc"], "J" => [77, "\ve"], "K" => [18, "\ve"], "L" => [77, "\vi"], "M" => [18, "\vi"], "N" => [77, "\vo"], "O" => [18, "\vo"], "P" => [77, "\vs"], "Q" => [18, "\vs"], "R" => [77, "\vt"], "S" => [18, "\vt"], "T" => [0, "\v "], "U" => [0, "\v%"], "V" => [0, "\v-"], "W" => [0, "\v."], "X" => [0, "\v/"], "Y" => [0, "\v3"], "Z" => [0, "\v4"], "[" => [0, "\v5"], "\\" => [0, "\v6"], "]" => [0, "\v7"], "^" => [0, "\v8"], "_" => [0, "\v9"], "`" => [0, "\v="], "a" => [0, "\vA"], "b" => [0, "\v_"], "c" => [0, "\vb"], "d" => [0, "\vd"], "e" => [0, "\vf"], "f" => [0, "\vg"], "g" => [0, "\vh"], "h" => [0, "\vl"], "i" => [0, "\vm"], "j" => [0, "\vn"], "k" => [0, "\vp"], "l" => [0, "\vr"], "m" => [0, "\vu"], "n" => [100, "\v"], "o" => [110, "\v"], "p" => [111, "\v"], "q" => [115, "\v"], "r" => [116, "\v"], "s" => [118, "\v"], "t" => [119, "\v"], "u" => [122, "\v"], "v" => [123, "\v"], "w" => [125, "\v"], "x" => [126, "\v"], "y" => [129, "\v"], "z" => [143, "\v"], "{" => [148, "\v"], "|" => [151, "\v"], "}" => [153, "\v"], "~" => [83, "\v"], "" => [10, "\v"], "\x80" => [77, "\f0"], "\x81" => [18, "\f0"], "\x82" => [77, "\f1"], "\x83" => [18, "\f1"], "\x84" => [77, "\f2"], "\x85" => [18, "\f2"], "\x86" => [77, "\fa"], "\x87" => [18, "\fa"], "\x88" => [77, "\fc"], "\x89" => [18, "\fc"], "\x8a" => [77, "\fe"], "\x8b" => [18, "\fe"], "\x8c" => [77, "\fi"], "\x8d" => [18, "\fi"], "\x8e" => [77, "\fo"], "\x8f" => [18, "\fo"], "\x90" => [77, "\fs"], "\x91" => [18, "\fs"], "\x92" => [77, "\ft"], "\x93" => [18, "\ft"], "\x94" => [0, "\f "], "\x95" => [0, "\f%"], "\x96" => [0, "\f-"], "\x97" => [0, "\f."], "\x98" => [0, "\f/"], "\x99" => [0, "\f3"], "\x9a" => [0, "\f4"], "\x9b" => [0, "\f5"], "\x9c" => [0, "\f6"], "\x9d" => [0, "\f7"], "\x9e" => [0, "\f8"], "\x9f" => [0, "\f9"], "\xa0" => [0, "\f="], "\xa1" => [0, "\fA"], "\xa2" => [0, "\f_"], "\xa3" => [0, "\fb"], "\xa4" => [0, "\fd"], "\xa5" => [0, "\ff"], "\xa6" => [0, "\fg"], "\xa7" => [0, "\fh"], "\xa8" => [0, "\fl"], "\xa9" => [0, "\fm"], "\xaa" => [0, "\fn"], "\xab" => [0, "\fp"], "\xac" => [0, "\fr"], "\xad" => [0, "\fu"], "\xae" => [100, "\f"], "\xaf" => [110, "\f"], "\xb0" => [111, "\f"], "\xb1" => [115, "\f"], "\xb2" => [116, "\f"], "\xb3" => [118, "\f"], "\xb4" => [119, "\f"], "\xb5" => [122, "\f"], "\xb6" => [123, "\f"], "\xb7" => [125, "\f"], "\xb8" => [126, "\f"], "\xb9" => [129, "\f"], "\xba" => [143, "\f"], "\xbb" => [148, "\f"], "\xbc" => [151, "\f"], "\xbd" => [153, "\f"], "\xbe" => [83, "\f"], "\xbf" => [10, "\f"], "\xc0" => [77, "\x0e0"], "\xc1" => [18, "\x0e0"], "\xc2" => [77, "\x0e1"], "\xc3" => [18, "\x0e1"], "\xc4" => [77, "\x0e2"], "\xc5" => [18, "\x0e2"], "\xc6" => [77, "\x0ea"], "\xc7" => [18, "\x0ea"], "\xc8" => [77, "\x0ec"], "\xc9" => [18, "\x0ec"], "\xca" => [77, "\x0ee"], "\xcb" => [18, "\x0ee"], "\xcc" => [77, "\x0ei"], "\xcd" => [18, "\x0ei"], "\xce" => [77, "\x0eo"], "\xcf" => [18, "\x0eo"], "\xd0" => [77, "\x0es"], "\xd1" => [18, "\x0es"], "\xd2" => [77, "\x0et"], "\xd3" => [18, "\x0et"], "\xd4" => [0, "\x0e "], "\xd5" => [0, "\x0e%"], "\xd6" => [0, "\x0e-"], "\xd7" => [0, "\x0e."], "\xd8" => [0, "\x0e/"], "\xd9" => [0, "\x0e3"], "\xda" => [0, "\x0e4"], "\xdb" => [0, "\x0e5"], "\xdc" => [0, "\x0e6"], "\xdd" => [0, "\x0e7"], "\xde" => [0, "\x0e8"], "\xdf" => [0, "\x0e9"], "\xe0" => [0, "\x0e="], "\xe1" => [0, "\x0eA"], "\xe2" => [0, "\x0e_"], "\xe3" => [0, "\x0eb"], "\xe4" => [0, "\x0ed"], "\xe5" => [0, "\x0ef"], "\xe6" => [0, "\x0eg"], "\xe7" => [0, "\x0eh"], "\xe8" => [0, "\x0el"], "\xe9" => [0, "\x0em"], "\xea" => [0, "\x0en"], "\xeb" => [0, "\x0ep"], "\xec" => [0, "\x0er"], "\xed" => [0, "\x0eu"], "\xee" => [100, "\x0e"], "\xef" => [110, "\x0e"], "\xf0" => [111, "\x0e"], "\xf1" => [115, "\x0e"], "\xf2" => [116, "\x0e"], "\xf3" => [118, "\x0e"], "\xf4" => [119, "\x0e"], "\xf5" => [122, "\x0e"], "\xf6" => [123, "\x0e"], "\xf7" => [125, "\x0e"], "\xf8" => [126, "\x0e"], "\xf9" => [129, "\x0e"], "\xfa" => [143, "\x0e"], "\xfb" => [148, "\x0e"], "\xfc" => [151, "\x0e"], "\xfd" => [153, "\x0e"], "\xfe" => [83, "\x0e"], "\xff" => [10, "\x0e"]], ["\x00" => [0, "\x080"], "\x01" => [0, "\x081"], "\x02" => [0, "\x082"], "\x03" => [0, "\x08a"], "\x04" => [0, "\x08c"], "\x05" => [0, "\x08e"], "\x06" => [0, "\x08i"], "\x07" => [0, "\x08o"], "\x08" => [0, "\x08s"], "\t" => [0, "\x08t"], "\n" => [73, "\x08"], "\v" => [88, "\x08"], "\f" => [89, "\x08"], "\r" => [96, "\x08"], "\x0e" => [97, "\x08"], "\x0f" => [99, "\x08"], "\x10" => [106, "\x08"], "\x11" => [136, "\x08"], "\x12" => [139, "\x08"], "\x13" => [141, "\x08"], "\x14" => [145, "\x08"], "\x15" => [147, "\x08"], "\x16" => [149, "\x08"], "\x17" => [101, "\x08"], "\x18" => [112, "\x08"], "\x19" => [117, "\x08"], "\x1a" => [120, "\x08"], "\x1b" => [124, "\x08"], "\x1c" => [127, "\x08"], "\x1d" => [144, "\x08"], "\x1e" => [152, "\x08"], "\x1f" => [11, "\x08"], " " => [0, "\v0"], "!" => [0, "\v1"], "\"" => [0, "\v2"], "#" => [0, "\va"], "\$" => [0, "\vc"], "%" => [0, "\ve"], "&" => [0, "\vi"], "'" => [0, "\vo"], "(" => [0, "\vs"], ")" => [0, "\vt"], "*" => [73, "\v"], "+" => [88, "\v"], "," => [89, "\v"], "-" => [96, "\v"], "." => [97, "\v"], "/" => [99, "\v"], [106, "\v"], [136, "\v"], [139, "\v"], [141, "\v"], [145, "\v"], [147, "\v"], [149, "\v"], [101, "\v"], [112, "\v"], [117, "\v"], ":" => [120, "\v"], ";" => [124, "\v"], "<" => [127, "\v"], "=" => [144, "\v"], ">" => [152, "\v"], "?" => [11, "\v"], "@" => [0, "\f0"], "A" => [0, "\f1"], "B" => [0, "\f2"], "C" => [0, "\fa"], "D" => [0, "\fc"], "E" => [0, "\fe"], "F" => [0, "\fi"], "G" => [0, "\fo"], "H" => [0, "\fs"], "I" => [0, "\ft"], "J" => [73, "\f"], "K" => [88, "\f"], "L" => [89, "\f"], "M" => [96, "\f"], "N" => [97, "\f"], "O" => [99, "\f"], "P" => [106, "\f"], "Q" => [136, "\f"], "R" => [139, "\f"], "S" => [141, "\f"], "T" => [145, "\f"], "U" => [147, "\f"], "V" => [149, "\f"], "W" => [101, "\f"], "X" => [112, "\f"], "Y" => [117, "\f"], "Z" => [120, "\f"], "[" => [124, "\f"], "\\" => [127, "\f"], "]" => [144, "\f"], "^" => [152, "\f"], "_" => [11, "\f"], "`" => [0, "\x0e0"], "a" => [0, "\x0e1"], "b" => [0, "\x0e2"], "c" => [0, "\x0ea"], "d" => [0, "\x0ec"], "e" => [0, "\x0ee"], "f" => [0, "\x0ei"], "g" => [0, "\x0eo"], "h" => [0, "\x0es"], "i" => [0, "\x0et"], "j" => [73, "\x0e"], "k" => [88, "\x0e"], "l" => [89, "\x0e"], "m" => [96, "\x0e"], "n" => [97, "\x0e"], "o" => [99, "\x0e"], "p" => [106, "\x0e"], "q" => [136, "\x0e"], "r" => [139, "\x0e"], "s" => [141, "\x0e"], "t" => [145, "\x0e"], "u" => [147, "\x0e"], "v" => [149, "\x0e"], "w" => [101, "\x0e"], "x" => [112, "\x0e"], "y" => [117, "\x0e"], "z" => [120, "\x0e"], "{" => [124, "\x0e"], "|" => [127, "\x0e"], "}" => [144, "\x0e"], "~" => [152, "\x0e"], "" => [11, "\x0e"], "\x80" => [0, "\x0f0"], "\x81" => [0, "\x0f1"], "\x82" => [0, "\x0f2"], "\x83" => [0, "\x0fa"], "\x84" => [0, "\x0fc"], "\x85" => [0, "\x0fe"], "\x86" => [0, "\x0fi"], "\x87" => [0, "\x0fo"], "\x88" => [0, "\x0fs"], "\x89" => [0, "\x0ft"], "\x8a" => [73, "\x0f"], "\x8b" => [88, "\x0f"], "\x8c" => [89, "\x0f"], "\x8d" => [96, "\x0f"], "\x8e" => [97, "\x0f"], "\x8f" => [99, "\x0f"], "\x90" => [106, "\x0f"], "\x91" => [136, "\x0f"], "\x92" => [139, "\x0f"], "\x93" => [141, "\x0f"], "\x94" => [145, "\x0f"], "\x95" => [147, "\x0f"], "\x96" => [149, "\x0f"], "\x97" => [101, "\x0f"], "\x98" => [112, "\x0f"], "\x99" => [117, "\x0f"], "\x9a" => [120, "\x0f"], "\x9b" => [124, "\x0f"], "\x9c" => [127, "\x0f"], "\x9d" => [144, "\x0f"], "\x9e" => [152, "\x0f"], "\x9f" => [11, "\x0f"], "\xa0" => [0, "\x100"], "\xa1" => [0, "\x101"], "\xa2" => [0, "\x102"], "\xa3" => [0, "\x10a"], "\xa4" => [0, "\x10c"], "\xa5" => [0, "\x10e"], "\xa6" => [0, "\x10i"], "\xa7" => [0, "\x10o"], "\xa8" => [0, "\x10s"], "\xa9" => [0, "\x10t"], "\xaa" => [73, "\x10"], "\xab" => [88, "\x10"], "\xac" => [89, "\x10"], "\xad" => [96, "\x10"], "\xae" => [97, "\x10"], "\xaf" => [99, "\x10"], "\xb0" => [106, "\x10"], "\xb1" => [136, "\x10"], "\xb2" => [139, "\x10"], "\xb3" => [141, "\x10"], "\xb4" => [145, "\x10"], "\xb5" => [147, "\x10"], "\xb6" => [149, "\x10"], "\xb7" => [101, "\x10"], "\xb8" => [112, "\x10"], "\xb9" => [117, "\x10"], "\xba" => [120, "\x10"], "\xbb" => [124, "\x10"], "\xbc" => [127, "\x10"], "\xbd" => [144, "\x10"], "\xbe" => [152, "\x10"], "\xbf" => [11, "\x10"], "\xc0" => [0, "\x110"], "\xc1" => [0, "\x111"], "\xc2" => [0, "\x112"], "\xc3" => [0, "\x11a"], "\xc4" => [0, "\x11c"], "\xc5" => [0, "\x11e"], "\xc6" => [0, "\x11i"], "\xc7" => [0, "\x11o"], "\xc8" => [0, "\x11s"], "\xc9" => [0, "\x11t"], "\xca" => [73, "\x11"], "\xcb" => [88, "\x11"], "\xcc" => [89, "\x11"], "\xcd" => [96, "\x11"], "\xce" => [97, "\x11"], "\xcf" => [99, "\x11"], "\xd0" => [106, "\x11"], "\xd1" => [136, "\x11"], "\xd2" => [139, "\x11"], "\xd3" => [141, "\x11"], "\xd4" => [145, "\x11"], "\xd5" => [147, "\x11"], "\xd6" => [149, "\x11"], "\xd7" => [101, "\x11"], "\xd8" => [112, "\x11"], "\xd9" => [117, "\x11"], "\xda" => [120, "\x11"], "\xdb" => [124, "\x11"], "\xdc" => [127, "\x11"], "\xdd" => [144, "\x11"], "\xde" => [152, "\x11"], "\xdf" => [11, "\x11"], "\xe0" => [0, "\x120"], "\xe1" => [0, "\x121"], "\xe2" => [0, "\x122"], "\xe3" => [0, "\x12a"], "\xe4" => [0, "\x12c"], "\xe5" => [0, "\x12e"], "\xe6" => [0, "\x12i"], "\xe7" => [0, "\x12o"], "\xe8" => [0, "\x12s"], "\xe9" => [0, "\x12t"], "\xea" => [73, "\x12"], "\xeb" => [88, "\x12"], "\xec" => [89, "\x12"], "\xed" => [96, "\x12"], "\xee" => [97, "\x12"], "\xef" => [99, "\x12"], "\xf0" => [106, "\x12"], "\xf1" => [136, "\x12"], "\xf2" => [139, "\x12"], "\xf3" => [141, "\x12"], "\xf4" => [145, "\x12"], "\xf5" => [147, "\x12"], "\xf6" => [149, "\x12"], "\xf7" => [101, "\x12"], "\xf8" => [112, "\x12"], "\xf9" => [117, "\x12"], "\xfa" => [120, "\x12"], "\xfb" => [124, "\x12"], "\xfc" => [127, "\x12"], "\xfd" => [144, "\x12"], "\xfe" => [152, "\x12"], "\xff" => [11, "\x12"]], ["\x00" => [94, "\t0"], "\x01" => [76, "\t0"], "\x02" => [104, "\t0"], "\x03" => [16, "\t0"], "\x04" => [94, "\t1"], "\x05" => [76, "\t1"], "\x06" => [104, "\t1"], "\x07" => [16, "\t1"], "\x08" => [94, "\t2"], "\t" => [76, "\t2"], "\n" => [104, "\t2"], "\v" => [16, "\t2"], "\f" => [94, "\ta"], "\r" => [76, "\ta"], "\x0e" => [104, "\ta"], "\x0f" => [16, "\ta"], "\x10" => [94, "\tc"], "\x11" => [76, "\tc"], "\x12" => [104, "\tc"], "\x13" => [16, "\tc"], "\x14" => [94, "\te"], "\x15" => [76, "\te"], "\x16" => [104, "\te"], "\x17" => [16, "\te"], "\x18" => [94, "\ti"], "\x19" => [76, "\ti"], "\x1a" => [104, "\ti"], "\x1b" => [16, "\ti"], "\x1c" => [94, "\to"], "\x1d" => [76, "\to"], "\x1e" => [104, "\to"], "\x1f" => [16, "\to"], " " => [94, "\ts"], "!" => [76, "\ts"], "\"" => [104, "\ts"], "#" => [16, "\ts"], "\$" => [94, "\tt"], "%" => [76, "\tt"], "&" => [104, "\tt"], "'" => [16, "\tt"], "(" => [77, "\t "], ")" => [18, "\t "], "*" => [77, "\t%"], "+" => [18, "\t%"], "," => [77, "\t-"], "-" => [18, "\t-"], "." => [77, "\t."], "/" => [18, "\t."], [77, "\t/"], [18, "\t/"], [77, "\t3"], [18, "\t3"], [77, "\t4"], [18, "\t4"], [77, "\t5"], [18, "\t5"], [77, "\t6"], [18, "\t6"], ":" => [77, "\t7"], ";" => [18, "\t7"], "<" => [77, "\t8"], "=" => [18, "\t8"], ">" => [77, "\t9"], "?" => [18, "\t9"], "@" => [77, "\t="], "A" => [18, "\t="], "B" => [77, "\tA"], "C" => [18, "\tA"], "D" => [77, "\t_"], "E" => [18, "\t_"], "F" => [77, "\tb"], "G" => [18, "\tb"], "H" => [77, "\td"], "I" => [18, "\td"], "J" => [77, "\tf"], "K" => [18, "\tf"], "L" => [77, "\tg"], "M" => [18, "\tg"], "N" => [77, "\th"], "O" => [18, "\th"], "P" => [77, "\tl"], "Q" => [18, "\tl"], "R" => [77, "\tm"], "S" => [18, "\tm"], "T" => [77, "\tn"], "U" => [18, "\tn"], "V" => [77, "\tp"], "W" => [18, "\tp"], "X" => [77, "\tr"], "Y" => [18, "\tr"], "Z" => [77, "\tu"], "[" => [18, "\tu"], "\\" => [0, "\t:"], "]" => [0, "\tB"], "^" => [0, "\tC"], "_" => [0, "\tD"], "`" => [0, "\tE"], "a" => [0, "\tF"], "b" => [0, "\tG"], "c" => [0, "\tH"], "d" => [0, "\tI"], "e" => [0, "\tJ"], "f" => [0, "\tK"], "g" => [0, "\tL"], "h" => [0, "\tM"], "i" => [0, "\tN"], "j" => [0, "\tO"], "k" => [0, "\tP"], "l" => [0, "\tQ"], "m" => [0, "\tR"], "n" => [0, "\tS"], "o" => [0, "\tT"], "p" => [0, "\tU"], "q" => [0, "\tV"], "r" => [0, "\tW"], "s" => [0, "\tY"], "t" => [0, "\tj"], "u" => [0, "\tk"], "v" => [0, "\tq"], "w" => [0, "\tv"], "x" => [0, "\tw"], "y" => [0, "\tx"], "z" => [0, "\ty"], "{" => [0, "\tz"], "|" => [82, "\t"], "}" => [87, "\t"], "~" => [130, "\t"], "" => [9, "\t"], "\x80" => [94, "\x8e0"], "\x81" => [76, "\x8e0"], "\x82" => [104, "\x8e0"], "\x83" => [16, "\x8e0"], "\x84" => [94, "\x8e1"], "\x85" => [76, "\x8e1"], "\x86" => [104, "\x8e1"], "\x87" => [16, "\x8e1"], "\x88" => [94, "\x8e2"], "\x89" => [76, "\x8e2"], "\x8a" => [104, "\x8e2"], "\x8b" => [16, "\x8e2"], "\x8c" => [94, "\x8ea"], "\x8d" => [76, "\x8ea"], "\x8e" => [104, "\x8ea"], "\x8f" => [16, "\x8ea"], "\x90" => [94, "\x8ec"], "\x91" => [76, "\x8ec"], "\x92" => [104, "\x8ec"], "\x93" => [16, "\x8ec"], "\x94" => [94, "\x8ee"], "\x95" => [76, "\x8ee"], "\x96" => [104, "\x8ee"], "\x97" => [16, "\x8ee"], "\x98" => [94, "\x8ei"], "\x99" => [76, "\x8ei"], "\x9a" => [104, "\x8ei"], "\x9b" => [16, "\x8ei"], "\x9c" => [94, "\x8eo"], "\x9d" => [76, "\x8eo"], "\x9e" => [104, "\x8eo"], "\x9f" => [16, "\x8eo"], "\xa0" => [94, "\x8es"], "\xa1" => [76, "\x8es"], "\xa2" => [104, "\x8es"], "\xa3" => [16, "\x8es"], "\xa4" => [94, "\x8et"], "\xa5" => [76, "\x8et"], "\xa6" => [104, "\x8et"], "\xa7" => [16, "\x8et"], "\xa8" => [77, "\x8e "], "\xa9" => [18, "\x8e "], "\xaa" => [77, "\x8e%"], "\xab" => [18, "\x8e%"], "\xac" => [77, "\x8e-"], "\xad" => [18, "\x8e-"], "\xae" => [77, "\x8e."], "\xaf" => [18, "\x8e."], "\xb0" => [77, "\x8e/"], "\xb1" => [18, "\x8e/"], "\xb2" => [77, "\x8e3"], "\xb3" => [18, "\x8e3"], "\xb4" => [77, "\x8e4"], "\xb5" => [18, "\x8e4"], "\xb6" => [77, "\x8e5"], "\xb7" => [18, "\x8e5"], "\xb8" => [77, "\x8e6"], "\xb9" => [18, "\x8e6"], "\xba" => [77, "\x8e7"], "\xbb" => [18, "\x8e7"], "\xbc" => [77, "\x8e8"], "\xbd" => [18, "\x8e8"], "\xbe" => [77, "\x8e9"], "\xbf" => [18, "\x8e9"], "\xc0" => [77, "\x8e="], "\xc1" => [18, "\x8e="], "\xc2" => [77, "\x8eA"], "\xc3" => [18, "\x8eA"], "\xc4" => [77, "\x8e_"], "\xc5" => [18, "\x8e_"], "\xc6" => [77, "\x8eb"], "\xc7" => [18, "\x8eb"], "\xc8" => [77, "\x8ed"], "\xc9" => [18, "\x8ed"], "\xca" => [77, "\x8ef"], "\xcb" => [18, "\x8ef"], "\xcc" => [77, "\x8eg"], "\xcd" => [18, "\x8eg"], "\xce" => [77, "\x8eh"], "\xcf" => [18, "\x8eh"], "\xd0" => [77, "\x8el"], "\xd1" => [18, "\x8el"], "\xd2" => [77, "\x8em"], "\xd3" => [18, "\x8em"], "\xd4" => [77, "\x8en"], "\xd5" => [18, "\x8en"], "\xd6" => [77, "\x8ep"], "\xd7" => [18, "\x8ep"], "\xd8" => [77, "\x8er"], "\xd9" => [18, "\x8er"], "\xda" => [77, "\x8eu"], "\xdb" => [18, "\x8eu"], "\xdc" => [0, "\x8e:"], "\xdd" => [0, "\x8eB"], "\xde" => [0, "\x8eC"], "\xdf" => [0, "\x8eD"], "\xe0" => [0, "\x8eE"], "\xe1" => [0, "\x8eF"], "\xe2" => [0, "\x8eG"], "\xe3" => [0, "\x8eH"], "\xe4" => [0, "\x8eI"], "\xe5" => [0, "\x8eJ"], "\xe6" => [0, "\x8eK"], "\xe7" => [0, "\x8eL"], "\xe8" => [0, "\x8eM"], "\xe9" => [0, "\x8eN"], "\xea" => [0, "\x8eO"], "\xeb" => [0, "\x8eP"], "\xec" => [0, "\x8eQ"], "\xed" => [0, "\x8eR"], "\xee" => [0, "\x8eS"], "\xef" => [0, "\x8eT"], "\xf0" => [0, "\x8eU"], "\xf1" => [0, "\x8eV"], "\xf2" => [0, "\x8eW"], "\xf3" => [0, "\x8eY"], "\xf4" => [0, "\x8ej"], "\xf5" => [0, "\x8ek"], "\xf6" => [0, "\x8eq"], "\xf7" => [0, "\x8ev"], "\xf8" => [0, "\x8ew"], "\xf9" => [0, "\x8ex"], "\xfa" => [0, "\x8ey"], "\xfb" => [0, "\x8ez"], "\xfc" => [82, "\x8e"], "\xfd" => [87, "\x8e"], "\xfe" => [130, "\x8e"], "\xff" => [9, "\x8e"]], ["\x00" => [94, "\xef0"], "\x01" => [76, "\xef0"], "\x02" => [104, "\xef0"], "\x03" => [16, "\xef0"], "\x04" => [94, "\xef1"], "\x05" => [76, "\xef1"], "\x06" => [104, "\xef1"], "\x07" => [16, "\xef1"], "\x08" => [94, "\xef2"], "\t" => [76, "\xef2"], "\n" => [104, "\xef2"], "\v" => [16, "\xef2"], "\f" => [94, "\xefa"], "\r" => [76, "\xefa"], "\x0e" => [104, "\xefa"], "\x0f" => [16, "\xefa"], "\x10" => [94, "\xefc"], "\x11" => [76, "\xefc"], "\x12" => [104, "\xefc"], "\x13" => [16, "\xefc"], "\x14" => [94, "\xefe"], "\x15" => [76, "\xefe"], "\x16" => [104, "\xefe"], "\x17" => [16, "\xefe"], "\x18" => [94, "\xefi"], "\x19" => [76, "\xefi"], "\x1a" => [104, "\xefi"], "\x1b" => [16, "\xefi"], "\x1c" => [94, "\xefo"], "\x1d" => [76, "\xefo"], "\x1e" => [104, "\xefo"], "\x1f" => [16, "\xefo"], " " => [94, "\xefs"], "!" => [76, "\xefs"], "\"" => [104, "\xefs"], "#" => [16, "\xefs"], "\$" => [94, "\xeft"], "%" => [76, "\xeft"], "&" => [104, "\xeft"], "'" => [16, "\xeft"], "(" => [77, "\xef "], ")" => [18, "\xef "], "*" => [77, "\xef%"], "+" => [18, "\xef%"], "," => [77, "\xef-"], "-" => [18, "\xef-"], "." => [77, "\xef."], "/" => [18, "\xef."], [77, "\xef/"], [18, "\xef/"], [77, "\xef3"], [18, "\xef3"], [77, "\xef4"], [18, "\xef4"], [77, "\xef5"], [18, "\xef5"], [77, "\xef6"], [18, "\xef6"], ":" => [77, "\xef7"], ";" => [18, "\xef7"], "<" => [77, "\xef8"], "=" => [18, "\xef8"], ">" => [77, "\xef9"], "?" => [18, "\xef9"], "@" => [77, "\xef="], "A" => [18, "\xef="], "B" => [77, "\xefA"], "C" => [18, "\xefA"], "D" => [77, "\xef_"], "E" => [18, "\xef_"], "F" => [77, "\xefb"], "G" => [18, "\xefb"], "H" => [77, "\xefd"], "I" => [18, "\xefd"], "J" => [77, "\xeff"], "K" => [18, "\xeff"], "L" => [77, "\xefg"], "M" => [18, "\xefg"], "N" => [77, "\xefh"], "O" => [18, "\xefh"], "P" => [77, "\xefl"], "Q" => [18, "\xefl"], "R" => [77, "\xefm"], "S" => [18, "\xefm"], "T" => [77, "\xefn"], "U" => [18, "\xefn"], "V" => [77, "\xefp"], "W" => [18, "\xefp"], "X" => [77, "\xefr"], "Y" => [18, "\xefr"], "Z" => [77, "\xefu"], "[" => [18, "\xefu"], "\\" => [0, "\xef:"], "]" => [0, "\xefB"], "^" => [0, "\xefC"], "_" => [0, "\xefD"], "`" => [0, "\xefE"], "a" => [0, "\xefF"], "b" => [0, "\xefG"], "c" => [0, "\xefH"], "d" => [0, "\xefI"], "e" => [0, "\xefJ"], "f" => [0, "\xefK"], "g" => [0, "\xefL"], "h" => [0, "\xefM"], "i" => [0, "\xefN"], "j" => [0, "\xefO"], "k" => [0, "\xefP"], "l" => [0, "\xefQ"], "m" => [0, "\xefR"], "n" => [0, "\xefS"], "o" => [0, "\xefT"], "p" => [0, "\xefU"], "q" => [0, "\xefV"], "r" => [0, "\xefW"], "s" => [0, "\xefY"], "t" => [0, "\xefj"], "u" => [0, "\xefk"], "v" => [0, "\xefq"], "w" => [0, "\xefv"], "x" => [0, "\xefw"], "y" => [0, "\xefx"], "z" => [0, "\xefy"], "{" => [0, "\xefz"], "|" => [82, "\xef"], "}" => [87, "\xef"], "~" => [130, "\xef"], "" => [9, "\xef"], "\x80" => [77, "\t0"], "\x81" => [18, "\t0"], "\x82" => [77, "\t1"], "\x83" => [18, "\t1"], "\x84" => [77, "\t2"], "\x85" => [18, "\t2"], "\x86" => [77, "\ta"], "\x87" => [18, "\ta"], "\x88" => [77, "\tc"], "\x89" => [18, "\tc"], "\x8a" => [77, "\te"], "\x8b" => [18, "\te"], "\x8c" => [77, "\ti"], "\x8d" => [18, "\ti"], "\x8e" => [77, "\to"], "\x8f" => [18, "\to"], "\x90" => [77, "\ts"], "\x91" => [18, "\ts"], "\x92" => [77, "\tt"], "\x93" => [18, "\tt"], "\x94" => [0, "\t "], "\x95" => [0, "\t%"], "\x96" => [0, "\t-"], "\x97" => [0, "\t."], "\x98" => [0, "\t/"], "\x99" => [0, "\t3"], "\x9a" => [0, "\t4"], "\x9b" => [0, "\t5"], "\x9c" => [0, "\t6"], "\x9d" => [0, "\t7"], "\x9e" => [0, "\t8"], "\x9f" => [0, "\t9"], "\xa0" => [0, "\t="], "\xa1" => [0, "\tA"], "\xa2" => [0, "\t_"], "\xa3" => [0, "\tb"], "\xa4" => [0, "\td"], "\xa5" => [0, "\tf"], "\xa6" => [0, "\tg"], "\xa7" => [0, "\th"], "\xa8" => [0, "\tl"], "\xa9" => [0, "\tm"], "\xaa" => [0, "\tn"], "\xab" => [0, "\tp"], "\xac" => [0, "\tr"], "\xad" => [0, "\tu"], "\xae" => [100, "\t"], "\xaf" => [110, "\t"], "\xb0" => [111, "\t"], "\xb1" => [115, "\t"], "\xb2" => [116, "\t"], "\xb3" => [118, "\t"], "\xb4" => [119, "\t"], "\xb5" => [122, "\t"], "\xb6" => [123, "\t"], "\xb7" => [125, "\t"], "\xb8" => [126, "\t"], "\xb9" => [129, "\t"], "\xba" => [143, "\t"], "\xbb" => [148, "\t"], "\xbc" => [151, "\t"], "\xbd" => [153, "\t"], "\xbe" => [83, "\t"], "\xbf" => [10, "\t"], "\xc0" => [77, "\x8e0"], "\xc1" => [18, "\x8e0"], "\xc2" => [77, "\x8e1"], "\xc3" => [18, "\x8e1"], "\xc4" => [77, "\x8e2"], "\xc5" => [18, "\x8e2"], "\xc6" => [77, "\x8ea"], "\xc7" => [18, "\x8ea"], "\xc8" => [77, "\x8ec"], "\xc9" => [18, "\x8ec"], "\xca" => [77, "\x8ee"], "\xcb" => [18, "\x8ee"], "\xcc" => [77, "\x8ei"], "\xcd" => [18, "\x8ei"], "\xce" => [77, "\x8eo"], "\xcf" => [18, "\x8eo"], "\xd0" => [77, "\x8es"], "\xd1" => [18, "\x8es"], "\xd2" => [77, "\x8et"], "\xd3" => [18, "\x8et"], "\xd4" => [0, "\x8e "], "\xd5" => [0, "\x8e%"], "\xd6" => [0, "\x8e-"], "\xd7" => [0, "\x8e."], "\xd8" => [0, "\x8e/"], "\xd9" => [0, "\x8e3"], "\xda" => [0, "\x8e4"], "\xdb" => [0, "\x8e5"], "\xdc" => [0, "\x8e6"], "\xdd" => [0, "\x8e7"], "\xde" => [0, "\x8e8"], "\xdf" => [0, "\x8e9"], "\xe0" => [0, "\x8e="], "\xe1" => [0, "\x8eA"], "\xe2" => [0, "\x8e_"], "\xe3" => [0, "\x8eb"], "\xe4" => [0, "\x8ed"], "\xe5" => [0, "\x8ef"], "\xe6" => [0, "\x8eg"], "\xe7" => [0, "\x8eh"], "\xe8" => [0, "\x8el"], "\xe9" => [0, "\x8em"], "\xea" => [0, "\x8en"], "\xeb" => [0, "\x8ep"], "\xec" => [0, "\x8er"], "\xed" => [0, "\x8eu"], "\xee" => [100, "\x8e"], "\xef" => [110, "\x8e"], "\xf0" => [111, "\x8e"], "\xf1" => [115, "\x8e"], "\xf2" => [116, "\x8e"], "\xf3" => [118, "\x8e"], "\xf4" => [119, "\x8e"], "\xf5" => [122, "\x8e"], "\xf6" => [123, "\x8e"], "\xf7" => [125, "\x8e"], "\xf8" => [126, "\x8e"], "\xf9" => [129, "\x8e"], "\xfa" => [143, "\x8e"], "\xfb" => [148, "\x8e"], "\xfc" => [151, "\x8e"], "\xfd" => [153, "\x8e"], "\xfe" => [83, "\x8e"], "\xff" => [10, "\x8e"]], ["\x00" => [77, "\xef0"], "\x01" => [18, "\xef0"], "\x02" => [77, "\xef1"], "\x03" => [18, "\xef1"], "\x04" => [77, "\xef2"], "\x05" => [18, "\xef2"], "\x06" => [77, "\xefa"], "\x07" => [18, "\xefa"], "\x08" => [77, "\xefc"], "\t" => [18, "\xefc"], "\n" => [77, "\xefe"], "\v" => [18, "\xefe"], "\f" => [77, "\xefi"], "\r" => [18, "\xefi"], "\x0e" => [77, "\xefo"], "\x0f" => [18, "\xefo"], "\x10" => [77, "\xefs"], "\x11" => [18, "\xefs"], "\x12" => [77, "\xeft"], "\x13" => [18, "\xeft"], "\x14" => [0, "\xef "], "\x15" => [0, "\xef%"], "\x16" => [0, "\xef-"], "\x17" => [0, "\xef."], "\x18" => [0, "\xef/"], "\x19" => [0, "\xef3"], "\x1a" => [0, "\xef4"], "\x1b" => [0, "\xef5"], "\x1c" => [0, "\xef6"], "\x1d" => [0, "\xef7"], "\x1e" => [0, "\xef8"], "\x1f" => [0, "\xef9"], " " => [0, "\xef="], "!" => [0, "\xefA"], "\"" => [0, "\xef_"], "#" => [0, "\xefb"], "\$" => [0, "\xefd"], "%" => [0, "\xeff"], "&" => [0, "\xefg"], "'" => [0, "\xefh"], "(" => [0, "\xefl"], ")" => [0, "\xefm"], "*" => [0, "\xefn"], "+" => [0, "\xefp"], "," => [0, "\xefr"], "-" => [0, "\xefu"], "." => [100, "\xef"], "/" => [110, "\xef"], [111, "\xef"], [115, "\xef"], [116, "\xef"], [118, "\xef"], [119, "\xef"], [122, "\xef"], [123, "\xef"], [125, "\xef"], [126, "\xef"], [129, "\xef"], ":" => [143, "\xef"], ";" => [148, "\xef"], "<" => [151, "\xef"], "=" => [153, "\xef"], ">" => [83, "\xef"], "?" => [10, "\xef"], "@" => [0, "\t0"], "A" => [0, "\t1"], "B" => [0, "\t2"], "C" => [0, "\ta"], "D" => [0, "\tc"], "E" => [0, "\te"], "F" => [0, "\ti"], "G" => [0, "\to"], "H" => [0, "\ts"], "I" => [0, "\tt"], "J" => [73, "\t"], "K" => [88, "\t"], "L" => [89, "\t"], "M" => [96, "\t"], "N" => [97, "\t"], "O" => [99, "\t"], "P" => [106, "\t"], "Q" => [136, "\t"], "R" => [139, "\t"], "S" => [141, "\t"], "T" => [145, "\t"], "U" => [147, "\t"], "V" => [149, "\t"], "W" => [101, "\t"], "X" => [112, "\t"], "Y" => [117, "\t"], "Z" => [120, "\t"], "[" => [124, "\t"], "\\" => [127, "\t"], "]" => [144, "\t"], "^" => [152, "\t"], "_" => [11, "\t"], "`" => [0, "\x8e0"], "a" => [0, "\x8e1"], "b" => [0, "\x8e2"], "c" => [0, "\x8ea"], "d" => [0, "\x8ec"], "e" => [0, "\x8ee"], "f" => [0, "\x8ei"], "g" => [0, "\x8eo"], "h" => [0, "\x8es"], "i" => [0, "\x8et"], "j" => [73, "\x8e"], "k" => [88, "\x8e"], "l" => [89, "\x8e"], "m" => [96, "\x8e"], "n" => [97, "\x8e"], "o" => [99, "\x8e"], "p" => [106, "\x8e"], "q" => [136, "\x8e"], "r" => [139, "\x8e"], "s" => [141, "\x8e"], "t" => [145, "\x8e"], "u" => [147, "\x8e"], "v" => [149, "\x8e"], "w" => [101, "\x8e"], "x" => [112, "\x8e"], "y" => [117, "\x8e"], "z" => [120, "\x8e"], "{" => [124, "\x8e"], "|" => [127, "\x8e"], "}" => [144, "\x8e"], "~" => [152, "\x8e"], "" => [11, "\x8e"], "\x80" => [0, "\x900"], "\x81" => [0, "\x901"], "\x82" => [0, "\x902"], "\x83" => [0, "\x90a"], "\x84" => [0, "\x90c"], "\x85" => [0, "\x90e"], "\x86" => [0, "\x90i"], "\x87" => [0, "\x90o"], "\x88" => [0, "\x90s"], "\x89" => [0, "\x90t"], "\x8a" => [73, "\x90"], "\x8b" => [88, "\x90"], "\x8c" => [89, "\x90"], "\x8d" => [96, "\x90"], "\x8e" => [97, "\x90"], "\x8f" => [99, "\x90"], "\x90" => [106, "\x90"], "\x91" => [136, "\x90"], "\x92" => [139, "\x90"], "\x93" => [141, "\x90"], "\x94" => [145, "\x90"], "\x95" => [147, "\x90"], "\x96" => [149, "\x90"], "\x97" => [101, "\x90"], "\x98" => [112, "\x90"], "\x99" => [117, "\x90"], "\x9a" => [120, "\x90"], "\x9b" => [124, "\x90"], "\x9c" => [127, "\x90"], "\x9d" => [144, "\x90"], "\x9e" => [152, "\x90"], "\x9f" => [11, "\x90"], "\xa0" => [0, "\x910"], "\xa1" => [0, "\x911"], "\xa2" => [0, "\x912"], "\xa3" => [0, "\x91a"], "\xa4" => [0, "\x91c"], "\xa5" => [0, "\x91e"], "\xa6" => [0, "\x91i"], "\xa7" => [0, "\x91o"], "\xa8" => [0, "\x91s"], "\xa9" => [0, "\x91t"], "\xaa" => [73, "\x91"], "\xab" => [88, "\x91"], "\xac" => [89, "\x91"], "\xad" => [96, "\x91"], "\xae" => [97, "\x91"], "\xaf" => [99, "\x91"], "\xb0" => [106, "\x91"], "\xb1" => [136, "\x91"], "\xb2" => [139, "\x91"], "\xb3" => [141, "\x91"], "\xb4" => [145, "\x91"], "\xb5" => [147, "\x91"], "\xb6" => [149, "\x91"], "\xb7" => [101, "\x91"], "\xb8" => [112, "\x91"], "\xb9" => [117, "\x91"], "\xba" => [120, "\x91"], "\xbb" => [124, "\x91"], "\xbc" => [127, "\x91"], "\xbd" => [144, "\x91"], "\xbe" => [152, "\x91"], "\xbf" => [11, "\x91"], "\xc0" => [0, "\x940"], "\xc1" => [0, "\x941"], "\xc2" => [0, "\x942"], "\xc3" => [0, "\x94a"], "\xc4" => [0, "\x94c"], "\xc5" => [0, "\x94e"], "\xc6" => [0, "\x94i"], "\xc7" => [0, "\x94o"], "\xc8" => [0, "\x94s"], "\xc9" => [0, "\x94t"], "\xca" => [73, "\x94"], "\xcb" => [88, "\x94"], "\xcc" => [89, "\x94"], "\xcd" => [96, "\x94"], "\xce" => [97, "\x94"], "\xcf" => [99, "\x94"], "\xd0" => [106, "\x94"], "\xd1" => [136, "\x94"], "\xd2" => [139, "\x94"], "\xd3" => [141, "\x94"], "\xd4" => [145, "\x94"], "\xd5" => [147, "\x94"], "\xd6" => [149, "\x94"], "\xd7" => [101, "\x94"], "\xd8" => [112, "\x94"], "\xd9" => [117, "\x94"], "\xda" => [120, "\x94"], "\xdb" => [124, "\x94"], "\xdc" => [127, "\x94"], "\xdd" => [144, "\x94"], "\xde" => [152, "\x94"], "\xdf" => [11, "\x94"], "\xe0" => [0, "\x9f0"], "\xe1" => [0, "\x9f1"], "\xe2" => [0, "\x9f2"], "\xe3" => [0, "\x9fa"], "\xe4" => [0, "\x9fc"], "\xe5" => [0, "\x9fe"], "\xe6" => [0, "\x9fi"], "\xe7" => [0, "\x9fo"], "\xe8" => [0, "\x9fs"], "\xe9" => [0, "\x9ft"], "\xea" => [73, "\x9f"], "\xeb" => [88, "\x9f"], "\xec" => [89, "\x9f"], "\xed" => [96, "\x9f"], "\xee" => [97, "\x9f"], "\xef" => [99, "\x9f"], "\xf0" => [106, "\x9f"], "\xf1" => [136, "\x9f"], "\xf2" => [139, "\x9f"], "\xf3" => [141, "\x9f"], "\xf4" => [145, "\x9f"], "\xf5" => [147, "\x9f"], "\xf6" => [149, "\x9f"], "\xf7" => [101, "\x9f"], "\xf8" => [112, "\x9f"], "\xf9" => [117, "\x9f"], "\xfa" => [120, "\x9f"], "\xfb" => [124, "\x9f"], "\xfc" => [127, "\x9f"], "\xfd" => [144, "\x9f"], "\xfe" => [152, "\x9f"], "\xff" => [11, "\x9f"]], ["\x00" => [0, "\xbc0"], "\x01" => [0, "\xbc1"], "\x02" => [0, "\xbc2"], "\x03" => [0, "\xbca"], "\x04" => [0, "\xbcc"], "\x05" => [0, "\xbce"], "\x06" => [0, "\xbci"], "\x07" => [0, "\xbco"], "\x08" => [0, "\xbcs"], "\t" => [0, "\xbct"], "\n" => [73, "\xbc"], "\v" => [88, "\xbc"], "\f" => [89, "\xbc"], "\r" => [96, "\xbc"], "\x0e" => [97, "\xbc"], "\x0f" => [99, "\xbc"], "\x10" => [106, "\xbc"], "\x11" => [136, "\xbc"], "\x12" => [139, "\xbc"], "\x13" => [141, "\xbc"], "\x14" => [145, "\xbc"], "\x15" => [147, "\xbc"], "\x16" => [149, "\xbc"], "\x17" => [101, "\xbc"], "\x18" => [112, "\xbc"], "\x19" => [117, "\xbc"], "\x1a" => [120, "\xbc"], "\x1b" => [124, "\xbc"], "\x1c" => [127, "\xbc"], "\x1d" => [144, "\xbc"], "\x1e" => [152, "\xbc"], "\x1f" => [11, "\xbc"], " " => [0, "\xbf0"], "!" => [0, "\xbf1"], "\"" => [0, "\xbf2"], "#" => [0, "\xbfa"], "\$" => [0, "\xbfc"], "%" => [0, "\xbfe"], "&" => [0, "\xbfi"], "'" => [0, "\xbfo"], "(" => [0, "\xbfs"], ")" => [0, "\xbft"], "*" => [73, "\xbf"], "+" => [88, "\xbf"], "," => [89, "\xbf"], "-" => [96, "\xbf"], "." => [97, "\xbf"], "/" => [99, "\xbf"], [106, "\xbf"], [136, "\xbf"], [139, "\xbf"], [141, "\xbf"], [145, "\xbf"], [147, "\xbf"], [149, "\xbf"], [101, "\xbf"], [112, "\xbf"], [117, "\xbf"], ":" => [120, "\xbf"], ";" => [124, "\xbf"], "<" => [127, "\xbf"], "=" => [144, "\xbf"], ">" => [152, "\xbf"], "?" => [11, "\xbf"], "@" => [0, "\xc50"], "A" => [0, "\xc51"], "B" => [0, "\xc52"], "C" => [0, "\xc5a"], "D" => [0, "\xc5c"], "E" => [0, "\xc5e"], "F" => [0, "\xc5i"], "G" => [0, "\xc5o"], "H" => [0, "\xc5s"], "I" => [0, "\xc5t"], "J" => [73, "\xc5"], "K" => [88, "\xc5"], "L" => [89, "\xc5"], "M" => [96, "\xc5"], "N" => [97, "\xc5"], "O" => [99, "\xc5"], "P" => [106, "\xc5"], "Q" => [136, "\xc5"], "R" => [139, "\xc5"], "S" => [141, "\xc5"], "T" => [145, "\xc5"], "U" => [147, "\xc5"], "V" => [149, "\xc5"], "W" => [101, "\xc5"], "X" => [112, "\xc5"], "Y" => [117, "\xc5"], "Z" => [120, "\xc5"], "[" => [124, "\xc5"], "\\" => [127, "\xc5"], "]" => [144, "\xc5"], "^" => [152, "\xc5"], "_" => [11, "\xc5"], "`" => [0, "\xe70"], "a" => [0, "\xe71"], "b" => [0, "\xe72"], "c" => [0, "\xe7a"], "d" => [0, "\xe7c"], "e" => [0, "\xe7e"], "f" => [0, "\xe7i"], "g" => [0, "\xe7o"], "h" => [0, "\xe7s"], "i" => [0, "\xe7t"], "j" => [73, "\xe7"], "k" => [88, "\xe7"], "l" => [89, "\xe7"], "m" => [96, "\xe7"], "n" => [97, "\xe7"], "o" => [99, "\xe7"], "p" => [106, "\xe7"], "q" => [136, "\xe7"], "r" => [139, "\xe7"], "s" => [141, "\xe7"], "t" => [145, "\xe7"], "u" => [147, "\xe7"], "v" => [149, "\xe7"], "w" => [101, "\xe7"], "x" => [112, "\xe7"], "y" => [117, "\xe7"], "z" => [120, "\xe7"], "{" => [124, "\xe7"], "|" => [127, "\xe7"], "}" => [144, "\xe7"], "~" => [152, "\xe7"], "" => [11, "\xe7"], "\x80" => [0, "\xef0"], "\x81" => [0, "\xef1"], "\x82" => [0, "\xef2"], "\x83" => [0, "\xefa"], "\x84" => [0, "\xefc"], "\x85" => [0, "\xefe"], "\x86" => [0, "\xefi"], "\x87" => [0, "\xefo"], "\x88" => [0, "\xefs"], "\x89" => [0, "\xeft"], "\x8a" => [73, "\xef"], "\x8b" => [88, "\xef"], "\x8c" => [89, "\xef"], "\x8d" => [96, "\xef"], "\x8e" => [97, "\xef"], "\x8f" => [99, "\xef"], "\x90" => [106, "\xef"], "\x91" => [136, "\xef"], "\x92" => [139, "\xef"], "\x93" => [141, "\xef"], "\x94" => [145, "\xef"], "\x95" => [147, "\xef"], "\x96" => [149, "\xef"], "\x97" => [101, "\xef"], "\x98" => [112, "\xef"], "\x99" => [117, "\xef"], "\x9a" => [120, "\xef"], "\x9b" => [124, "\xef"], "\x9c" => [127, "\xef"], "\x9d" => [144, "\xef"], "\x9e" => [152, "\xef"], "\x9f" => [11, "\xef"], "\xa0" => [92, "\t"], "\xa1" => [95, "\t"], "\xa2" => [137, "\t"], "\xa3" => [142, "\t"], "\xa4" => [150, "\t"], "\xa5" => [74, "\t"], "\xa6" => [90, "\t"], "\xa7" => [98, "\t"], "\xa8" => [107, "\t"], "\xa9" => [140, "\t"], "\xaa" => [146, "\t"], "\xab" => [102, "\t"], "\xac" => [113, "\t"], "\xad" => [121, "\t"], "\xae" => [128, "\t"], "\xaf" => [12, "\t"], "\xb0" => [92, "\x8e"], "\xb1" => [95, "\x8e"], "\xb2" => [137, "\x8e"], "\xb3" => [142, "\x8e"], "\xb4" => [150, "\x8e"], "\xb5" => [74, "\x8e"], "\xb6" => [90, "\x8e"], "\xb7" => [98, "\x8e"], "\xb8" => [107, "\x8e"], "\xb9" => [140, "\x8e"], "\xba" => [146, "\x8e"], "\xbb" => [102, "\x8e"], "\xbc" => [113, "\x8e"], "\xbd" => [121, "\x8e"], "\xbe" => [128, "\x8e"], "\xbf" => [12, "\x8e"], "\xc0" => [92, "\x90"], "\xc1" => [95, "\x90"], "\xc2" => [137, "\x90"], "\xc3" => [142, "\x90"], "\xc4" => [150, "\x90"], "\xc5" => [74, "\x90"], "\xc6" => [90, "\x90"], "\xc7" => [98, "\x90"], "\xc8" => [107, "\x90"], "\xc9" => [140, "\x90"], "\xca" => [146, "\x90"], "\xcb" => [102, "\x90"], "\xcc" => [113, "\x90"], "\xcd" => [121, "\x90"], "\xce" => [128, "\x90"], "\xcf" => [12, "\x90"], "\xd0" => [92, "\x91"], "\xd1" => [95, "\x91"], "\xd2" => [137, "\x91"], "\xd3" => [142, "\x91"], "\xd4" => [150, "\x91"], "\xd5" => [74, "\x91"], "\xd6" => [90, "\x91"], "\xd7" => [98, "\x91"], "\xd8" => [107, "\x91"], "\xd9" => [140, "\x91"], "\xda" => [146, "\x91"], "\xdb" => [102, "\x91"], "\xdc" => [113, "\x91"], "\xdd" => [121, "\x91"], "\xde" => [128, "\x91"], "\xdf" => [12, "\x91"], "\xe0" => [92, "\x94"], "\xe1" => [95, "\x94"], "\xe2" => [137, "\x94"], "\xe3" => [142, "\x94"], "\xe4" => [150, "\x94"], "\xe5" => [74, "\x94"], "\xe6" => [90, "\x94"], "\xe7" => [98, "\x94"], "\xe8" => [107, "\x94"], "\xe9" => [140, "\x94"], "\xea" => [146, "\x94"], "\xeb" => [102, "\x94"], "\xec" => [113, "\x94"], "\xed" => [121, "\x94"], "\xee" => [128, "\x94"], "\xef" => [12, "\x94"], "\xf0" => [92, "\x9f"], "\xf1" => [95, "\x9f"], "\xf2" => [137, "\x9f"], "\xf3" => [142, "\x9f"], "\xf4" => [150, "\x9f"], "\xf5" => [74, "\x9f"], "\xf6" => [90, "\x9f"], "\xf7" => [98, "\x9f"], "\xf8" => [107, "\x9f"], "\xf9" => [140, "\x9f"], "\xfa" => [146, "\x9f"], "\xfb" => [102, "\x9f"], "\xfc" => [113, "\x9f"], "\xfd" => [121, "\x9f"], "\xfe" => [128, "\x9f"], "\xff" => [12, "\x9f"]], ["\x00" => [92, "\x13"], "\x01" => [95, "\x13"], "\x02" => [137, "\x13"], "\x03" => [142, "\x13"], "\x04" => [150, "\x13"], "\x05" => [74, "\x13"], "\x06" => [90, "\x13"], "\x07" => [98, "\x13"], "\x08" => [107, "\x13"], "\t" => [140, "\x13"], "\n" => [146, "\x13"], "\v" => [102, "\x13"], "\f" => [113, "\x13"], "\r" => [121, "\x13"], "\x0e" => [128, "\x13"], "\x0f" => [12, "\x13"], "\x10" => [92, "\x14"], "\x11" => [95, "\x14"], "\x12" => [137, "\x14"], "\x13" => [142, "\x14"], "\x14" => [150, "\x14"], "\x15" => [74, "\x14"], "\x16" => [90, "\x14"], "\x17" => [98, "\x14"], "\x18" => [107, "\x14"], "\x19" => [140, "\x14"], "\x1a" => [146, "\x14"], "\x1b" => [102, "\x14"], "\x1c" => [113, "\x14"], "\x1d" => [121, "\x14"], "\x1e" => [128, "\x14"], "\x1f" => [12, "\x14"], " " => [92, "\x15"], "!" => [95, "\x15"], "\"" => [137, "\x15"], "#" => [142, "\x15"], "\$" => [150, "\x15"], "%" => [74, "\x15"], "&" => [90, "\x15"], "'" => [98, "\x15"], "(" => [107, "\x15"], ")" => [140, "\x15"], "*" => [146, "\x15"], "+" => [102, "\x15"], "," => [113, "\x15"], "-" => [121, "\x15"], "." => [128, "\x15"], "/" => [12, "\x15"], [92, "\x17"], [95, "\x17"], [137, "\x17"], [142, "\x17"], [150, "\x17"], [74, "\x17"], [90, "\x17"], [98, "\x17"], [107, "\x17"], [140, "\x17"], ":" => [146, "\x17"], ";" => [102, "\x17"], "<" => [113, "\x17"], "=" => [121, "\x17"], ">" => [128, "\x17"], "?" => [12, "\x17"], "@" => [92, "\x18"], "A" => [95, "\x18"], "B" => [137, "\x18"], "C" => [142, "\x18"], "D" => [150, "\x18"], "E" => [74, "\x18"], "F" => [90, "\x18"], "G" => [98, "\x18"], "H" => [107, "\x18"], "I" => [140, "\x18"], "J" => [146, "\x18"], "K" => [102, "\x18"], "L" => [113, "\x18"], "M" => [121, "\x18"], "N" => [128, "\x18"], "O" => [12, "\x18"], "P" => [92, "\x19"], "Q" => [95, "\x19"], "R" => [137, "\x19"], "S" => [142, "\x19"], "T" => [150, "\x19"], "U" => [74, "\x19"], "V" => [90, "\x19"], "W" => [98, "\x19"], "X" => [107, "\x19"], "Y" => [140, "\x19"], "Z" => [146, "\x19"], "[" => [102, "\x19"], "\\" => [113, "\x19"], "]" => [121, "\x19"], "^" => [128, "\x19"], "_" => [12, "\x19"], "`" => [92, "\x1a"], "a" => [95, "\x1a"], "b" => [137, "\x1a"], "c" => [142, "\x1a"], "d" => [150, "\x1a"], "e" => [74, "\x1a"], "f" => [90, "\x1a"], "g" => [98, "\x1a"], "h" => [107, "\x1a"], "i" => [140, "\x1a"], "j" => [146, "\x1a"], "k" => [102, "\x1a"], "l" => [113, "\x1a"], "m" => [121, "\x1a"], "n" => [128, "\x1a"], "o" => [12, "\x1a"], "p" => [92, "\x1b"], "q" => [95, "\x1b"], "r" => [137, "\x1b"], "s" => [142, "\x1b"], "t" => [150, "\x1b"], "u" => [74, "\x1b"], "v" => [90, "\x1b"], "w" => [98, "\x1b"], "x" => [107, "\x1b"], "y" => [140, "\x1b"], "z" => [146, "\x1b"], "{" => [102, "\x1b"], "|" => [113, "\x1b"], "}" => [121, "\x1b"], "~" => [128, "\x1b"], "" => [12, "\x1b"], "\x80" => [92, "\x1c"], "\x81" => [95, "\x1c"], "\x82" => [137, "\x1c"], "\x83" => [142, "\x1c"], "\x84" => [150, "\x1c"], "\x85" => [74, "\x1c"], "\x86" => [90, "\x1c"], "\x87" => [98, "\x1c"], "\x88" => [107, "\x1c"], "\x89" => [140, "\x1c"], "\x8a" => [146, "\x1c"], "\x8b" => [102, "\x1c"], "\x8c" => [113, "\x1c"], "\x8d" => [121, "\x1c"], "\x8e" => [128, "\x1c"], "\x8f" => [12, "\x1c"], "\x90" => [92, "\x1d"], "\x91" => [95, "\x1d"], "\x92" => [137, "\x1d"], "\x93" => [142, "\x1d"], "\x94" => [150, "\x1d"], "\x95" => [74, "\x1d"], "\x96" => [90, "\x1d"], "\x97" => [98, "\x1d"], "\x98" => [107, "\x1d"], "\x99" => [140, "\x1d"], "\x9a" => [146, "\x1d"], "\x9b" => [102, "\x1d"], "\x9c" => [113, "\x1d"], "\x9d" => [121, "\x1d"], "\x9e" => [128, "\x1d"], "\x9f" => [12, "\x1d"], "\xa0" => [92, "\x1e"], "\xa1" => [95, "\x1e"], "\xa2" => [137, "\x1e"], "\xa3" => [142, "\x1e"], "\xa4" => [150, "\x1e"], "\xa5" => [74, "\x1e"], "\xa6" => [90, "\x1e"], "\xa7" => [98, "\x1e"], "\xa8" => [107, "\x1e"], "\xa9" => [140, "\x1e"], "\xaa" => [146, "\x1e"], "\xab" => [102, "\x1e"], "\xac" => [113, "\x1e"], "\xad" => [121, "\x1e"], "\xae" => [128, "\x1e"], "\xaf" => [12, "\x1e"], "\xb0" => [92, "\x1f"], "\xb1" => [95, "\x1f"], "\xb2" => [137, "\x1f"], "\xb3" => [142, "\x1f"], "\xb4" => [150, "\x1f"], "\xb5" => [74, "\x1f"], "\xb6" => [90, "\x1f"], "\xb7" => [98, "\x1f"], "\xb8" => [107, "\x1f"], "\xb9" => [140, "\x1f"], "\xba" => [146, "\x1f"], "\xbb" => [102, "\x1f"], "\xbc" => [113, "\x1f"], "\xbd" => [121, "\x1f"], "\xbe" => [128, "\x1f"], "\xbf" => [12, "\x1f"], "\xc0" => [92, ""], "\xc1" => [95, ""], "\xc2" => [137, ""], "\xc3" => [142, ""], "\xc4" => [150, ""], "\xc5" => [74, ""], "\xc6" => [90, ""], "\xc7" => [98, ""], "\xc8" => [107, ""], "\xc9" => [140, ""], "\xca" => [146, ""], "\xcb" => [102, ""], "\xcc" => [113, ""], "\xcd" => [121, ""], "\xce" => [128, ""], "\xcf" => [12, ""], "\xd0" => [92, "\xdc"], "\xd1" => [95, "\xdc"], "\xd2" => [137, "\xdc"], "\xd3" => [142, "\xdc"], "\xd4" => [150, "\xdc"], "\xd5" => [74, "\xdc"], "\xd6" => [90, "\xdc"], "\xd7" => [98, "\xdc"], "\xd8" => [107, "\xdc"], "\xd9" => [140, "\xdc"], "\xda" => [146, "\xdc"], "\xdb" => [102, "\xdc"], "\xdc" => [113, "\xdc"], "\xdd" => [121, "\xdc"], "\xde" => [128, "\xdc"], "\xdf" => [12, "\xdc"], "\xe0" => [92, "\xf9"], "\xe1" => [95, "\xf9"], "\xe2" => [137, "\xf9"], "\xe3" => [142, "\xf9"], "\xe4" => [150, "\xf9"], "\xe5" => [74, "\xf9"], "\xe6" => [90, "\xf9"], "\xe7" => [98, "\xf9"], "\xe8" => [107, "\xf9"], "\xe9" => [140, "\xf9"], "\xea" => [146, "\xf9"], "\xeb" => [102, "\xf9"], "\xec" => [113, "\xf9"], "\xed" => [121, "\xf9"], "\xee" => [128, "\xf9"], "\xef" => [12, "\xf9"], "\xf0" => [94, "\n"], "\xf1" => [76, "\n"], "\xf2" => [104, "\n"], "\xf3" => [16, "\n"], "\xf4" => [94, "\r"], "\xf5" => [76, "\r"], "\xf6" => [104, "\r"], "\xf7" => [16, "\r"], "\xf8" => [94, "\x16"], "\xf9" => [76, "\x16"], "\xfa" => [104, "\x16"], "\xfb" => [16, "\x16"], "\xfc" => [94, ""], "\xfd" => [76, ""], "\xfe" => [104, ""], "\xff" => [16, ""]], ["\x00" => [94, "\n0"], "\x01" => [76, "\n0"], "\x02" => [104, "\n0"], "\x03" => [16, "\n0"], "\x04" => [94, "\n1"], "\x05" => [76, "\n1"], "\x06" => [104, "\n1"], "\x07" => [16, "\n1"], "\x08" => [94, "\n2"], "\t" => [76, "\n2"], "\n" => [104, "\n2"], "\v" => [16, "\n2"], "\f" => [94, "\na"], "\r" => [76, "\na"], "\x0e" => [104, "\na"], "\x0f" => [16, "\na"], "\x10" => [94, "\nc"], "\x11" => [76, "\nc"], "\x12" => [104, "\nc"], "\x13" => [16, "\nc"], "\x14" => [94, "\ne"], "\x15" => [76, "\ne"], "\x16" => [104, "\ne"], "\x17" => [16, "\ne"], "\x18" => [94, "\ni"], "\x19" => [76, "\ni"], "\x1a" => [104, "\ni"], "\x1b" => [16, "\ni"], "\x1c" => [94, "\no"], "\x1d" => [76, "\no"], "\x1e" => [104, "\no"], "\x1f" => [16, "\no"], " " => [94, "\ns"], "!" => [76, "\ns"], "\"" => [104, "\ns"], "#" => [16, "\ns"], "\$" => [94, "\nt"], "%" => [76, "\nt"], "&" => [104, "\nt"], "'" => [16, "\nt"], "(" => [77, "\n "], ")" => [18, "\n "], "*" => [77, "\n%"], "+" => [18, "\n%"], "," => [77, "\n-"], "-" => [18, "\n-"], "." => [77, "\n."], "/" => [18, "\n."], [77, "\n/"], [18, "\n/"], [77, "\n3"], [18, "\n3"], [77, "\n4"], [18, "\n4"], [77, "\n5"], [18, "\n5"], [77, "\n6"], [18, "\n6"], ":" => [77, "\n7"], ";" => [18, "\n7"], "<" => [77, "\n8"], "=" => [18, "\n8"], ">" => [77, "\n9"], "?" => [18, "\n9"], "@" => [77, "\n="], "A" => [18, "\n="], "B" => [77, "\nA"], "C" => [18, "\nA"], "D" => [77, "\n_"], "E" => [18, "\n_"], "F" => [77, "\nb"], "G" => [18, "\nb"], "H" => [77, "\nd"], "I" => [18, "\nd"], "J" => [77, "\nf"], "K" => [18, "\nf"], "L" => [77, "\ng"], "M" => [18, "\ng"], "N" => [77, "\nh"], "O" => [18, "\nh"], "P" => [77, "\nl"], "Q" => [18, "\nl"], "R" => [77, "\nm"], "S" => [18, "\nm"], "T" => [77, "\nn"], "U" => [18, "\nn"], "V" => [77, "\np"], "W" => [18, "\np"], "X" => [77, "\nr"], "Y" => [18, "\nr"], "Z" => [77, "\nu"], "[" => [18, "\nu"], "\\" => [0, "\n:"], "]" => [0, "\nB"], "^" => [0, "\nC"], "_" => [0, "\nD"], "`" => [0, "\nE"], "a" => [0, "\nF"], "b" => [0, "\nG"], "c" => [0, "\nH"], "d" => [0, "\nI"], "e" => [0, "\nJ"], "f" => [0, "\nK"], "g" => [0, "\nL"], "h" => [0, "\nM"], "i" => [0, "\nN"], "j" => [0, "\nO"], "k" => [0, "\nP"], "l" => [0, "\nQ"], "m" => [0, "\nR"], "n" => [0, "\nS"], "o" => [0, "\nT"], "p" => [0, "\nU"], "q" => [0, "\nV"], "r" => [0, "\nW"], "s" => [0, "\nY"], "t" => [0, "\nj"], "u" => [0, "\nk"], "v" => [0, "\nq"], "w" => [0, "\nv"], "x" => [0, "\nw"], "y" => [0, "\nx"], "z" => [0, "\ny"], "{" => [0, "\nz"], "|" => [82, "\n"], "}" => [87, "\n"], "~" => [130, "\n"], "" => [9, "\n"], "\x80" => [94, "\r0"], "\x81" => [76, "\r0"], "\x82" => [104, "\r0"], "\x83" => [16, "\r0"], "\x84" => [94, "\r1"], "\x85" => [76, "\r1"], "\x86" => [104, "\r1"], "\x87" => [16, "\r1"], "\x88" => [94, "\r2"], "\x89" => [76, "\r2"], "\x8a" => [104, "\r2"], "\x8b" => [16, "\r2"], "\x8c" => [94, "\ra"], "\x8d" => [76, "\ra"], "\x8e" => [104, "\ra"], "\x8f" => [16, "\ra"], "\x90" => [94, "\rc"], "\x91" => [76, "\rc"], "\x92" => [104, "\rc"], "\x93" => [16, "\rc"], "\x94" => [94, "\re"], "\x95" => [76, "\re"], "\x96" => [104, "\re"], "\x97" => [16, "\re"], "\x98" => [94, "\ri"], "\x99" => [76, "\ri"], "\x9a" => [104, "\ri"], "\x9b" => [16, "\ri"], "\x9c" => [94, "\ro"], "\x9d" => [76, "\ro"], "\x9e" => [104, "\ro"], "\x9f" => [16, "\ro"], "\xa0" => [94, "\rs"], "\xa1" => [76, "\rs"], "\xa2" => [104, "\rs"], "\xa3" => [16, "\rs"], "\xa4" => [94, "\rt"], "\xa5" => [76, "\rt"], "\xa6" => [104, "\rt"], "\xa7" => [16, "\rt"], "\xa8" => [77, "\r "], "\xa9" => [18, "\r "], "\xaa" => [77, "\r%"], "\xab" => [18, "\r%"], "\xac" => [77, "\r-"], "\xad" => [18, "\r-"], "\xae" => [77, "\r."], "\xaf" => [18, "\r."], "\xb0" => [77, "\r/"], "\xb1" => [18, "\r/"], "\xb2" => [77, "\r3"], "\xb3" => [18, "\r3"], "\xb4" => [77, "\r4"], "\xb5" => [18, "\r4"], "\xb6" => [77, "\r5"], "\xb7" => [18, "\r5"], "\xb8" => [77, "\r6"], "\xb9" => [18, "\r6"], "\xba" => [77, "\r7"], "\xbb" => [18, "\r7"], "\xbc" => [77, "\r8"], "\xbd" => [18, "\r8"], "\xbe" => [77, "\r9"], "\xbf" => [18, "\r9"], "\xc0" => [77, "\r="], "\xc1" => [18, "\r="], "\xc2" => [77, "\rA"], "\xc3" => [18, "\rA"], "\xc4" => [77, "\r_"], "\xc5" => [18, "\r_"], "\xc6" => [77, "\rb"], "\xc7" => [18, "\rb"], "\xc8" => [77, "\rd"], "\xc9" => [18, "\rd"], "\xca" => [77, "\rf"], "\xcb" => [18, "\rf"], "\xcc" => [77, "\rg"], "\xcd" => [18, "\rg"], "\xce" => [77, "\rh"], "\xcf" => [18, "\rh"], "\xd0" => [77, "\rl"], "\xd1" => [18, "\rl"], "\xd2" => [77, "\rm"], "\xd3" => [18, "\rm"], "\xd4" => [77, "\rn"], "\xd5" => [18, "\rn"], "\xd6" => [77, "\rp"], "\xd7" => [18, "\rp"], "\xd8" => [77, "\rr"], "\xd9" => [18, "\rr"], "\xda" => [77, "\ru"], "\xdb" => [18, "\ru"], "\xdc" => [0, "\r:"], "\xdd" => [0, "\rB"], "\xde" => [0, "\rC"], "\xdf" => [0, "\rD"], "\xe0" => [0, "\rE"], "\xe1" => [0, "\rF"], "\xe2" => [0, "\rG"], "\xe3" => [0, "\rH"], "\xe4" => [0, "\rI"], "\xe5" => [0, "\rJ"], "\xe6" => [0, "\rK"], "\xe7" => [0, "\rL"], "\xe8" => [0, "\rM"], "\xe9" => [0, "\rN"], "\xea" => [0, "\rO"], "\xeb" => [0, "\rP"], "\xec" => [0, "\rQ"], "\xed" => [0, "\rR"], "\xee" => [0, "\rS"], "\xef" => [0, "\rT"], "\xf0" => [0, "\rU"], "\xf1" => [0, "\rV"], "\xf2" => [0, "\rW"], "\xf3" => [0, "\rY"], "\xf4" => [0, "\rj"], "\xf5" => [0, "\rk"], "\xf6" => [0, "\rq"], "\xf7" => [0, "\rv"], "\xf8" => [0, "\rw"], "\xf9" => [0, "\rx"], "\xfa" => [0, "\ry"], "\xfb" => [0, "\rz"], "\xfc" => [82, "\r"], "\xfd" => [87, "\r"], "\xfe" => [130, "\r"], "\xff" => [9, "\r"]], ["\x00" => [77, "\n0"], "\x01" => [18, "\n0"], "\x02" => [77, "\n1"], "\x03" => [18, "\n1"], "\x04" => [77, "\n2"], "\x05" => [18, "\n2"], "\x06" => [77, "\na"], "\x07" => [18, "\na"], "\x08" => [77, "\nc"], "\t" => [18, "\nc"], "\n" => [77, "\ne"], "\v" => [18, "\ne"], "\f" => [77, "\ni"], "\r" => [18, "\ni"], "\x0e" => [77, "\no"], "\x0f" => [18, "\no"], "\x10" => [77, "\ns"], "\x11" => [18, "\ns"], "\x12" => [77, "\nt"], "\x13" => [18, "\nt"], "\x14" => [0, "\n "], "\x15" => [0, "\n%"], "\x16" => [0, "\n-"], "\x17" => [0, "\n."], "\x18" => [0, "\n/"], "\x19" => [0, "\n3"], "\x1a" => [0, "\n4"], "\x1b" => [0, "\n5"], "\x1c" => [0, "\n6"], "\x1d" => [0, "\n7"], "\x1e" => [0, "\n8"], "\x1f" => [0, "\n9"], " " => [0, "\n="], "!" => [0, "\nA"], "\"" => [0, "\n_"], "#" => [0, "\nb"], "\$" => [0, "\nd"], "%" => [0, "\nf"], "&" => [0, "\ng"], "'" => [0, "\nh"], "(" => [0, "\nl"], ")" => [0, "\nm"], "*" => [0, "\nn"], "+" => [0, "\np"], "," => [0, "\nr"], "-" => [0, "\nu"], "." => [100, "\n"], "/" => [110, "\n"], [111, "\n"], [115, "\n"], [116, "\n"], [118, "\n"], [119, "\n"], [122, "\n"], [123, "\n"], [125, "\n"], [126, "\n"], [129, "\n"], ":" => [143, "\n"], ";" => [148, "\n"], "<" => [151, "\n"], "=" => [153, "\n"], ">" => [83, "\n"], "?" => [10, "\n"], "@" => [77, "\r0"], "A" => [18, "\r0"], "B" => [77, "\r1"], "C" => [18, "\r1"], "D" => [77, "\r2"], "E" => [18, "\r2"], "F" => [77, "\ra"], "G" => [18, "\ra"], "H" => [77, "\rc"], "I" => [18, "\rc"], "J" => [77, "\re"], "K" => [18, "\re"], "L" => [77, "\ri"], "M" => [18, "\ri"], "N" => [77, "\ro"], "O" => [18, "\ro"], "P" => [77, "\rs"], "Q" => [18, "\rs"], "R" => [77, "\rt"], "S" => [18, "\rt"], "T" => [0, "\r "], "U" => [0, "\r%"], "V" => [0, "\r-"], "W" => [0, "\r."], "X" => [0, "\r/"], "Y" => [0, "\r3"], "Z" => [0, "\r4"], "[" => [0, "\r5"], "\\" => [0, "\r6"], "]" => [0, "\r7"], "^" => [0, "\r8"], "_" => [0, "\r9"], "`" => [0, "\r="], "a" => [0, "\rA"], "b" => [0, "\r_"], "c" => [0, "\rb"], "d" => [0, "\rd"], "e" => [0, "\rf"], "f" => [0, "\rg"], "g" => [0, "\rh"], "h" => [0, "\rl"], "i" => [0, "\rm"], "j" => [0, "\rn"], "k" => [0, "\rp"], "l" => [0, "\rr"], "m" => [0, "\ru"], "n" => [100, "\r"], "o" => [110, "\r"], "p" => [111, "\r"], "q" => [115, "\r"], "r" => [116, "\r"], "s" => [118, "\r"], "t" => [119, "\r"], "u" => [122, "\r"], "v" => [123, "\r"], "w" => [125, "\r"], "x" => [126, "\r"], "y" => [129, "\r"], "z" => [143, "\r"], "{" => [148, "\r"], "|" => [151, "\r"], "}" => [153, "\r"], "~" => [83, "\r"], "" => [10, "\r"], "\x80" => [77, "\x160"], "\x81" => [18, "\x160"], "\x82" => [77, "\x161"], "\x83" => [18, "\x161"], "\x84" => [77, "\x162"], "\x85" => [18, "\x162"], "\x86" => [77, "\x16a"], "\x87" => [18, "\x16a"], "\x88" => [77, "\x16c"], "\x89" => [18, "\x16c"], "\x8a" => [77, "\x16e"], "\x8b" => [18, "\x16e"], "\x8c" => [77, "\x16i"], "\x8d" => [18, "\x16i"], "\x8e" => [77, "\x16o"], "\x8f" => [18, "\x16o"], "\x90" => [77, "\x16s"], "\x91" => [18, "\x16s"], "\x92" => [77, "\x16t"], "\x93" => [18, "\x16t"], "\x94" => [0, "\x16 "], "\x95" => [0, "\x16%"], "\x96" => [0, "\x16-"], "\x97" => [0, "\x16."], "\x98" => [0, "\x16/"], "\x99" => [0, "\x163"], "\x9a" => [0, "\x164"], "\x9b" => [0, "\x165"], "\x9c" => [0, "\x166"], "\x9d" => [0, "\x167"], "\x9e" => [0, "\x168"], "\x9f" => [0, "\x169"], "\xa0" => [0, "\x16="], "\xa1" => [0, "\x16A"], "\xa2" => [0, "\x16_"], "\xa3" => [0, "\x16b"], "\xa4" => [0, "\x16d"], "\xa5" => [0, "\x16f"], "\xa6" => [0, "\x16g"], "\xa7" => [0, "\x16h"], "\xa8" => [0, "\x16l"], "\xa9" => [0, "\x16m"], "\xaa" => [0, "\x16n"], "\xab" => [0, "\x16p"], "\xac" => [0, "\x16r"], "\xad" => [0, "\x16u"], "\xae" => [100, "\x16"], "\xaf" => [110, "\x16"], "\xb0" => [111, "\x16"], "\xb1" => [115, "\x16"], "\xb2" => [116, "\x16"], "\xb3" => [118, "\x16"], "\xb4" => [119, "\x16"], "\xb5" => [122, "\x16"], "\xb6" => [123, "\x16"], "\xb7" => [125, "\x16"], "\xb8" => [126, "\x16"], "\xb9" => [129, "\x16"], "\xba" => [143, "\x16"], "\xbb" => [148, "\x16"], "\xbc" => [151, "\x16"], "\xbd" => [153, "\x16"], "\xbe" => [83, "\x16"], "\xbf" => [10, "\x16"], "\xc0" => [77, ""], "\xc1" => [18, ""], "\xc2" => [77, ""], "\xc3" => [18, ""], "\xc4" => [77, ""], "\xc5" => [18, ""], "\xc6" => [77, ""], "\xc7" => [18, ""], "\xc8" => [77, ""], "\xc9" => [18, ""], "\xca" => [77, ""], "\xcb" => [18, ""], "\xcc" => [77, ""], "\xcd" => [18, ""], "\xce" => [77, ""], "\xcf" => [18, ""], "\xd0" => [77, ""], "\xd1" => [18, ""], "\xd2" => [77, ""], "\xd3" => [18, ""], "\xd4" => [0, ""], "\xd5" => [0, ""], "\xd6" => [0, ""], "\xd7" => [0, ""], "\xd8" => [0, ""], "\xd9" => [0, ""], "\xda" => [0, ""], "\xdb" => [0, ""], "\xdc" => [0, ""], "\xdd" => [0, ""], "\xde" => [0, ""], "\xdf" => [0, ""], "\xe0" => [0, ""], "\xe1" => [0, ""], "\xe2" => [0, ""], "\xe3" => [0, ""], "\xe4" => [0, ""], "\xe5" => [0, ""], "\xe6" => [0, ""], "\xe7" => [0, ""], "\xe8" => [0, ""], "\xe9" => [0, ""], "\xea" => [0, ""], "\xeb" => [0, ""], "\xec" => [0, ""], "\xed" => [0, ""], "\xee" => [100, ""], "\xef" => [110, ""], "\xf0" => [111, ""], "\xf1" => [115, ""], "\xf2" => [116, ""], "\xf3" => [118, ""], "\xf4" => [119, ""], "\xf5" => [122, ""], "\xf6" => [123, ""], "\xf7" => [125, ""], "\xf8" => [126, ""], "\xf9" => [129, ""], "\xfa" => [143, ""], "\xfb" => [148, ""], "\xfc" => [151, ""], "\xfd" => [153, ""], "\xfe" => [83, ""], "\xff" => [10, ""]], ["\x00" => [94, "\xf90"], "\x01" => [76, "\xf90"], "\x02" => [104, "\xf90"], "\x03" => [16, "\xf90"], "\x04" => [94, "\xf91"], "\x05" => [76, "\xf91"], "\x06" => [104, "\xf91"], "\x07" => [16, "\xf91"], "\x08" => [94, "\xf92"], "\t" => [76, "\xf92"], "\n" => [104, "\xf92"], "\v" => [16, "\xf92"], "\f" => [94, "\xf9a"], "\r" => [76, "\xf9a"], "\x0e" => [104, "\xf9a"], "\x0f" => [16, "\xf9a"], "\x10" => [94, "\xf9c"], "\x11" => [76, "\xf9c"], "\x12" => [104, "\xf9c"], "\x13" => [16, "\xf9c"], "\x14" => [94, "\xf9e"], "\x15" => [76, "\xf9e"], "\x16" => [104, "\xf9e"], "\x17" => [16, "\xf9e"], "\x18" => [94, "\xf9i"], "\x19" => [76, "\xf9i"], "\x1a" => [104, "\xf9i"], "\x1b" => [16, "\xf9i"], "\x1c" => [94, "\xf9o"], "\x1d" => [76, "\xf9o"], "\x1e" => [104, "\xf9o"], "\x1f" => [16, "\xf9o"], " " => [94, "\xf9s"], "!" => [76, "\xf9s"], "\"" => [104, "\xf9s"], "#" => [16, "\xf9s"], "\$" => [94, "\xf9t"], "%" => [76, "\xf9t"], "&" => [104, "\xf9t"], "'" => [16, "\xf9t"], "(" => [77, "\xf9 "], ")" => [18, "\xf9 "], "*" => [77, "\xf9%"], "+" => [18, "\xf9%"], "," => [77, "\xf9-"], "-" => [18, "\xf9-"], "." => [77, "\xf9."], "/" => [18, "\xf9."], [77, "\xf9/"], [18, "\xf9/"], [77, "\xf93"], [18, "\xf93"], [77, "\xf94"], [18, "\xf94"], [77, "\xf95"], [18, "\xf95"], [77, "\xf96"], [18, "\xf96"], ":" => [77, "\xf97"], ";" => [18, "\xf97"], "<" => [77, "\xf98"], "=" => [18, "\xf98"], ">" => [77, "\xf99"], "?" => [18, "\xf99"], "@" => [77, "\xf9="], "A" => [18, "\xf9="], "B" => [77, "\xf9A"], "C" => [18, "\xf9A"], "D" => [77, "\xf9_"], "E" => [18, "\xf9_"], "F" => [77, "\xf9b"], "G" => [18, "\xf9b"], "H" => [77, "\xf9d"], "I" => [18, "\xf9d"], "J" => [77, "\xf9f"], "K" => [18, "\xf9f"], "L" => [77, "\xf9g"], "M" => [18, "\xf9g"], "N" => [77, "\xf9h"], "O" => [18, "\xf9h"], "P" => [77, "\xf9l"], "Q" => [18, "\xf9l"], "R" => [77, "\xf9m"], "S" => [18, "\xf9m"], "T" => [77, "\xf9n"], "U" => [18, "\xf9n"], "V" => [77, "\xf9p"], "W" => [18, "\xf9p"], "X" => [77, "\xf9r"], "Y" => [18, "\xf9r"], "Z" => [77, "\xf9u"], "[" => [18, "\xf9u"], "\\" => [0, "\xf9:"], "]" => [0, "\xf9B"], "^" => [0, "\xf9C"], "_" => [0, "\xf9D"], "`" => [0, "\xf9E"], "a" => [0, "\xf9F"], "b" => [0, "\xf9G"], "c" => [0, "\xf9H"], "d" => [0, "\xf9I"], "e" => [0, "\xf9J"], "f" => [0, "\xf9K"], "g" => [0, "\xf9L"], "h" => [0, "\xf9M"], "i" => [0, "\xf9N"], "j" => [0, "\xf9O"], "k" => [0, "\xf9P"], "l" => [0, "\xf9Q"], "m" => [0, "\xf9R"], "n" => [0, "\xf9S"], "o" => [0, "\xf9T"], "p" => [0, "\xf9U"], "q" => [0, "\xf9V"], "r" => [0, "\xf9W"], "s" => [0, "\xf9Y"], "t" => [0, "\xf9j"], "u" => [0, "\xf9k"], "v" => [0, "\xf9q"], "w" => [0, "\xf9v"], "x" => [0, "\xf9w"], "y" => [0, "\xf9x"], "z" => [0, "\xf9y"], "{" => [0, "\xf9z"], "|" => [82, "\xf9"], "}" => [87, "\xf9"], "~" => [130, "\xf9"], "" => [9, "\xf9"], "\x80" => [0, "\n0"], "\x81" => [0, "\n1"], "\x82" => [0, "\n2"], "\x83" => [0, "\na"], "\x84" => [0, "\nc"], "\x85" => [0, "\ne"], "\x86" => [0, "\ni"], "\x87" => [0, "\no"], "\x88" => [0, "\ns"], "\x89" => [0, "\nt"], "\x8a" => [73, "\n"], "\x8b" => [88, "\n"], "\x8c" => [89, "\n"], "\x8d" => [96, "\n"], "\x8e" => [97, "\n"], "\x8f" => [99, "\n"], "\x90" => [106, "\n"], "\x91" => [136, "\n"], "\x92" => [139, "\n"], "\x93" => [141, "\n"], "\x94" => [145, "\n"], "\x95" => [147, "\n"], "\x96" => [149, "\n"], "\x97" => [101, "\n"], "\x98" => [112, "\n"], "\x99" => [117, "\n"], "\x9a" => [120, "\n"], "\x9b" => [124, "\n"], "\x9c" => [127, "\n"], "\x9d" => [144, "\n"], "\x9e" => [152, "\n"], "\x9f" => [11, "\n"], "\xa0" => [0, "\r0"], "\xa1" => [0, "\r1"], "\xa2" => [0, "\r2"], "\xa3" => [0, "\ra"], "\xa4" => [0, "\rc"], "\xa5" => [0, "\re"], "\xa6" => [0, "\ri"], "\xa7" => [0, "\ro"], "\xa8" => [0, "\rs"], "\xa9" => [0, "\rt"], "\xaa" => [73, "\r"], "\xab" => [88, "\r"], "\xac" => [89, "\r"], "\xad" => [96, "\r"], "\xae" => [97, "\r"], "\xaf" => [99, "\r"], "\xb0" => [106, "\r"], "\xb1" => [136, "\r"], "\xb2" => [139, "\r"], "\xb3" => [141, "\r"], "\xb4" => [145, "\r"], "\xb5" => [147, "\r"], "\xb6" => [149, "\r"], "\xb7" => [101, "\r"], "\xb8" => [112, "\r"], "\xb9" => [117, "\r"], "\xba" => [120, "\r"], "\xbb" => [124, "\r"], "\xbc" => [127, "\r"], "\xbd" => [144, "\r"], "\xbe" => [152, "\r"], "\xbf" => [11, "\r"], "\xc0" => [0, "\x160"], "\xc1" => [0, "\x161"], "\xc2" => [0, "\x162"], "\xc3" => [0, "\x16a"], "\xc4" => [0, "\x16c"], "\xc5" => [0, "\x16e"], "\xc6" => [0, "\x16i"], "\xc7" => [0, "\x16o"], "\xc8" => [0, "\x16s"], "\xc9" => [0, "\x16t"], "\xca" => [73, "\x16"], "\xcb" => [88, "\x16"], "\xcc" => [89, "\x16"], "\xcd" => [96, "\x16"], "\xce" => [97, "\x16"], "\xcf" => [99, "\x16"], "\xd0" => [106, "\x16"], "\xd1" => [136, "\x16"], "\xd2" => [139, "\x16"], "\xd3" => [141, "\x16"], "\xd4" => [145, "\x16"], "\xd5" => [147, "\x16"], "\xd6" => [149, "\x16"], "\xd7" => [101, "\x16"], "\xd8" => [112, "\x16"], "\xd9" => [117, "\x16"], "\xda" => [120, "\x16"], "\xdb" => [124, "\x16"], "\xdc" => [127, "\x16"], "\xdd" => [144, "\x16"], "\xde" => [152, "\x16"], "\xdf" => [11, "\x16"], "\xe0" => [0, ""], "\xe1" => [0, ""], "\xe2" => [0, ""], "\xe3" => [0, ""], "\xe4" => [0, ""], "\xe5" => [0, ""], "\xe6" => [0, ""], "\xe7" => [0, ""], "\xe8" => [0, ""], "\xe9" => [0, ""], "\xea" => [73, ""], "\xeb" => [88, ""], "\xec" => [89, ""], "\xed" => [96, ""], "\xee" => [97, ""], "\xef" => [99, ""], "\xf0" => [106, ""], "\xf1" => [136, ""], "\xf2" => [139, ""], "\xf3" => [141, ""], "\xf4" => [145, ""], "\xf5" => [147, ""], "\xf6" => [149, ""], "\xf7" => [101, ""], "\xf8" => [112, ""], "\xf9" => [117, ""], "\xfa" => [120, ""], "\xfb" => [124, ""], "\xfc" => [127, ""], "\xfd" => [144, ""], "\xfe" => [152, ""], "\xff" => [11, ""]], ["\x00" => [77, "0"], "\x01" => [18, "0"], "\x02" => [77, "1"], "\x03" => [18, "1"], "\x04" => [77, "2"], "\x05" => [18, "2"], "\x06" => [77, "a"], "\x07" => [18, "a"], "\x08" => [77, "c"], "\t" => [18, "c"], "\n" => [77, "e"], "\v" => [18, "e"], "\f" => [77, "i"], "\r" => [18, "i"], "\x0e" => [77, "o"], "\x0f" => [18, "o"], "\x10" => [77, "s"], "\x11" => [18, "s"], "\x12" => [77, "t"], "\x13" => [18, "t"], "\x14" => [0, " "], "\x15" => [0, "%"], "\x16" => [0, "-"], "\x17" => [0, "."], "\x18" => [0, "/"], "\x19" => [0, "3"], "\x1a" => [0, "4"], "\x1b" => [0, "5"], "\x1c" => [0, "6"], "\x1d" => [0, "7"], "\x1e" => [0, "8"], "\x1f" => [0, "9"], " " => [0, "="], "!" => [0, "A"], "\"" => [0, "_"], "#" => [0, "b"], "\$" => [0, "d"], "%" => [0, "f"], "&" => [0, "g"], "'" => [0, "h"], "(" => [0, "l"], ")" => [0, "m"], "*" => [0, "n"], "+" => [0, "p"], "," => [0, "r"], "-" => [0, "u"], "." => [100, ""], "/" => [110, ""], [111, ""], [115, ""], [116, ""], [118, ""], [119, ""], [122, ""], [123, ""], [125, ""], [126, ""], [129, ""], ":" => [143, ""], ";" => [148, ""], "<" => [151, ""], "=" => [153, ""], ">" => [83, ""], "?" => [10, ""], "@" => [77, "\xdc0"], "A" => [18, "\xdc0"], "B" => [77, "\xdc1"], "C" => [18, "\xdc1"], "D" => [77, "\xdc2"], "E" => [18, "\xdc2"], "F" => [77, "\xdca"], "G" => [18, "\xdca"], "H" => [77, "\xdcc"], "I" => [18, "\xdcc"], "J" => [77, "\xdce"], "K" => [18, "\xdce"], "L" => [77, "\xdci"], "M" => [18, "\xdci"], "N" => [77, "\xdco"], "O" => [18, "\xdco"], "P" => [77, "\xdcs"], "Q" => [18, "\xdcs"], "R" => [77, "\xdct"], "S" => [18, "\xdct"], "T" => [0, "\xdc "], "U" => [0, "\xdc%"], "V" => [0, "\xdc-"], "W" => [0, "\xdc."], "X" => [0, "\xdc/"], "Y" => [0, "\xdc3"], "Z" => [0, "\xdc4"], "[" => [0, "\xdc5"], "\\" => [0, "\xdc6"], "]" => [0, "\xdc7"], "^" => [0, "\xdc8"], "_" => [0, "\xdc9"], "`" => [0, "\xdc="], "a" => [0, "\xdcA"], "b" => [0, "\xdc_"], "c" => [0, "\xdcb"], "d" => [0, "\xdcd"], "e" => [0, "\xdcf"], "f" => [0, "\xdcg"], "g" => [0, "\xdch"], "h" => [0, "\xdcl"], "i" => [0, "\xdcm"], "j" => [0, "\xdcn"], "k" => [0, "\xdcp"], "l" => [0, "\xdcr"], "m" => [0, "\xdcu"], "n" => [100, "\xdc"], "o" => [110, "\xdc"], "p" => [111, "\xdc"], "q" => [115, "\xdc"], "r" => [116, "\xdc"], "s" => [118, "\xdc"], "t" => [119, "\xdc"], "u" => [122, "\xdc"], "v" => [123, "\xdc"], "w" => [125, "\xdc"], "x" => [126, "\xdc"], "y" => [129, "\xdc"], "z" => [143, "\xdc"], "{" => [148, "\xdc"], "|" => [151, "\xdc"], "}" => [153, "\xdc"], "~" => [83, "\xdc"], "" => [10, "\xdc"], "\x80" => [77, "\xf90"], "\x81" => [18, "\xf90"], "\x82" => [77, "\xf91"], "\x83" => [18, "\xf91"], "\x84" => [77, "\xf92"], "\x85" => [18, "\xf92"], "\x86" => [77, "\xf9a"], "\x87" => [18, "\xf9a"], "\x88" => [77, "\xf9c"], "\x89" => [18, "\xf9c"], "\x8a" => [77, "\xf9e"], "\x8b" => [18, "\xf9e"], "\x8c" => [77, "\xf9i"], "\x8d" => [18, "\xf9i"], "\x8e" => [77, "\xf9o"], "\x8f" => [18, "\xf9o"], "\x90" => [77, "\xf9s"], "\x91" => [18, "\xf9s"], "\x92" => [77, "\xf9t"], "\x93" => [18, "\xf9t"], "\x94" => [0, "\xf9 "], "\x95" => [0, "\xf9%"], "\x96" => [0, "\xf9-"], "\x97" => [0, "\xf9."], "\x98" => [0, "\xf9/"], "\x99" => [0, "\xf93"], "\x9a" => [0, "\xf94"], "\x9b" => [0, "\xf95"], "\x9c" => [0, "\xf96"], "\x9d" => [0, "\xf97"], "\x9e" => [0, "\xf98"], "\x9f" => [0, "\xf99"], "\xa0" => [0, "\xf9="], "\xa1" => [0, "\xf9A"], "\xa2" => [0, "\xf9_"], "\xa3" => [0, "\xf9b"], "\xa4" => [0, "\xf9d"], "\xa5" => [0, "\xf9f"], "\xa6" => [0, "\xf9g"], "\xa7" => [0, "\xf9h"], "\xa8" => [0, "\xf9l"], "\xa9" => [0, "\xf9m"], "\xaa" => [0, "\xf9n"], "\xab" => [0, "\xf9p"], "\xac" => [0, "\xf9r"], "\xad" => [0, "\xf9u"], "\xae" => [100, "\xf9"], "\xaf" => [110, "\xf9"], "\xb0" => [111, "\xf9"], "\xb1" => [115, "\xf9"], "\xb2" => [116, "\xf9"], "\xb3" => [118, "\xf9"], "\xb4" => [119, "\xf9"], "\xb5" => [122, "\xf9"], "\xb6" => [123, "\xf9"], "\xb7" => [125, "\xf9"], "\xb8" => [126, "\xf9"], "\xb9" => [129, "\xf9"], "\xba" => [143, "\xf9"], "\xbb" => [148, "\xf9"], "\xbc" => [151, "\xf9"], "\xbd" => [153, "\xf9"], "\xbe" => [83, "\xf9"], "\xbf" => [10, "\xf9"], "\xc0" => [92, "\n"], "\xc1" => [95, "\n"], "\xc2" => [137, "\n"], "\xc3" => [142, "\n"], "\xc4" => [150, "\n"], "\xc5" => [74, "\n"], "\xc6" => [90, "\n"], "\xc7" => [98, "\n"], "\xc8" => [107, "\n"], "\xc9" => [140, "\n"], "\xca" => [146, "\n"], "\xcb" => [102, "\n"], "\xcc" => [113, "\n"], "\xcd" => [121, "\n"], "\xce" => [128, "\n"], "\xcf" => [12, "\n"], "\xd0" => [92, "\r"], "\xd1" => [95, "\r"], "\xd2" => [137, "\r"], "\xd3" => [142, "\r"], "\xd4" => [150, "\r"], "\xd5" => [74, "\r"], "\xd6" => [90, "\r"], "\xd7" => [98, "\r"], "\xd8" => [107, "\r"], "\xd9" => [140, "\r"], "\xda" => [146, "\r"], "\xdb" => [102, "\r"], "\xdc" => [113, "\r"], "\xdd" => [121, "\r"], "\xde" => [128, "\r"], "\xdf" => [12, "\r"], "\xe0" => [92, "\x16"], "\xe1" => [95, "\x16"], "\xe2" => [137, "\x16"], "\xe3" => [142, "\x16"], "\xe4" => [150, "\x16"], "\xe5" => [74, "\x16"], "\xe6" => [90, "\x16"], "\xe7" => [98, "\x16"], "\xe8" => [107, "\x16"], "\xe9" => [140, "\x16"], "\xea" => [146, "\x16"], "\xeb" => [102, "\x16"], "\xec" => [113, "\x16"], "\xed" => [121, "\x16"], "\xee" => [128, "\x16"], "\xef" => [12, "\x16"], "\xf0" => [92, ""], "\xf1" => [95, ""], "\xf2" => [137, ""], "\xf3" => [142, ""], "\xf4" => [150, ""], "\xf5" => [74, ""], "\xf6" => [90, ""], "\xf7" => [98, ""], "\xf8" => [107, ""], "\xf9" => [140, ""], "\xfa" => [146, ""], "\xfb" => [102, ""], "\xfc" => [113, ""], "\xfd" => [121, ""], "\xfe" => [128, ""], "\xff" => [12, ""]], ["\x00" => [0, "\x1c0"], "\x01" => [0, "\x1c1"], "\x02" => [0, "\x1c2"], "\x03" => [0, "\x1ca"], "\x04" => [0, "\x1cc"], "\x05" => [0, "\x1ce"], "\x06" => [0, "\x1ci"], "\x07" => [0, "\x1co"], "\x08" => [0, "\x1cs"], "\t" => [0, "\x1ct"], "\n" => [73, "\x1c"], "\v" => [88, "\x1c"], "\f" => [89, "\x1c"], "\r" => [96, "\x1c"], "\x0e" => [97, "\x1c"], "\x0f" => [99, "\x1c"], "\x10" => [106, "\x1c"], "\x11" => [136, "\x1c"], "\x12" => [139, "\x1c"], "\x13" => [141, "\x1c"], "\x14" => [145, "\x1c"], "\x15" => [147, "\x1c"], "\x16" => [149, "\x1c"], "\x17" => [101, "\x1c"], "\x18" => [112, "\x1c"], "\x19" => [117, "\x1c"], "\x1a" => [120, "\x1c"], "\x1b" => [124, "\x1c"], "\x1c" => [127, "\x1c"], "\x1d" => [144, "\x1c"], "\x1e" => [152, "\x1c"], "\x1f" => [11, "\x1c"], " " => [0, "\x1d0"], "!" => [0, "\x1d1"], "\"" => [0, "\x1d2"], "#" => [0, "\x1da"], "\$" => [0, "\x1dc"], "%" => [0, "\x1de"], "&" => [0, "\x1di"], "'" => [0, "\x1do"], "(" => [0, "\x1ds"], ")" => [0, "\x1dt"], "*" => [73, "\x1d"], "+" => [88, "\x1d"], "," => [89, "\x1d"], "-" => [96, "\x1d"], "." => [97, "\x1d"], "/" => [99, "\x1d"], [106, "\x1d"], [136, "\x1d"], [139, "\x1d"], [141, "\x1d"], [145, "\x1d"], [147, "\x1d"], [149, "\x1d"], [101, "\x1d"], [112, "\x1d"], [117, "\x1d"], ":" => [120, "\x1d"], ";" => [124, "\x1d"], "<" => [127, "\x1d"], "=" => [144, "\x1d"], ">" => [152, "\x1d"], "?" => [11, "\x1d"], "@" => [0, "\x1e0"], "A" => [0, "\x1e1"], "B" => [0, "\x1e2"], "C" => [0, "\x1ea"], "D" => [0, "\x1ec"], "E" => [0, "\x1ee"], "F" => [0, "\x1ei"], "G" => [0, "\x1eo"], "H" => [0, "\x1es"], "I" => [0, "\x1et"], "J" => [73, "\x1e"], "K" => [88, "\x1e"], "L" => [89, "\x1e"], "M" => [96, "\x1e"], "N" => [97, "\x1e"], "O" => [99, "\x1e"], "P" => [106, "\x1e"], "Q" => [136, "\x1e"], "R" => [139, "\x1e"], "S" => [141, "\x1e"], "T" => [145, "\x1e"], "U" => [147, "\x1e"], "V" => [149, "\x1e"], "W" => [101, "\x1e"], "X" => [112, "\x1e"], "Y" => [117, "\x1e"], "Z" => [120, "\x1e"], "[" => [124, "\x1e"], "\\" => [127, "\x1e"], "]" => [144, "\x1e"], "^" => [152, "\x1e"], "_" => [11, "\x1e"], "`" => [0, "\x1f0"], "a" => [0, "\x1f1"], "b" => [0, "\x1f2"], "c" => [0, "\x1fa"], "d" => [0, "\x1fc"], "e" => [0, "\x1fe"], "f" => [0, "\x1fi"], "g" => [0, "\x1fo"], "h" => [0, "\x1fs"], "i" => [0, "\x1ft"], "j" => [73, "\x1f"], "k" => [88, "\x1f"], "l" => [89, "\x1f"], "m" => [96, "\x1f"], "n" => [97, "\x1f"], "o" => [99, "\x1f"], "p" => [106, "\x1f"], "q" => [136, "\x1f"], "r" => [139, "\x1f"], "s" => [141, "\x1f"], "t" => [145, "\x1f"], "u" => [147, "\x1f"], "v" => [149, "\x1f"], "w" => [101, "\x1f"], "x" => [112, "\x1f"], "y" => [117, "\x1f"], "z" => [120, "\x1f"], "{" => [124, "\x1f"], "|" => [127, "\x1f"], "}" => [144, "\x1f"], "~" => [152, "\x1f"], "" => [11, "\x1f"], "\x80" => [0, "0"], "\x81" => [0, "1"], "\x82" => [0, "2"], "\x83" => [0, "a"], "\x84" => [0, "c"], "\x85" => [0, "e"], "\x86" => [0, "i"], "\x87" => [0, "o"], "\x88" => [0, "s"], "\x89" => [0, "t"], "\x8a" => [73, ""], "\x8b" => [88, ""], "\x8c" => [89, ""], "\x8d" => [96, ""], "\x8e" => [97, ""], "\x8f" => [99, ""], "\x90" => [106, ""], "\x91" => [136, ""], "\x92" => [139, ""], "\x93" => [141, ""], "\x94" => [145, ""], "\x95" => [147, ""], "\x96" => [149, ""], "\x97" => [101, ""], "\x98" => [112, ""], "\x99" => [117, ""], "\x9a" => [120, ""], "\x9b" => [124, ""], "\x9c" => [127, ""], "\x9d" => [144, ""], "\x9e" => [152, ""], "\x9f" => [11, ""], "\xa0" => [0, "\xdc0"], "\xa1" => [0, "\xdc1"], "\xa2" => [0, "\xdc2"], "\xa3" => [0, "\xdca"], "\xa4" => [0, "\xdcc"], "\xa5" => [0, "\xdce"], "\xa6" => [0, "\xdci"], "\xa7" => [0, "\xdco"], "\xa8" => [0, "\xdcs"], "\xa9" => [0, "\xdct"], "\xaa" => [73, "\xdc"], "\xab" => [88, "\xdc"], "\xac" => [89, "\xdc"], "\xad" => [96, "\xdc"], "\xae" => [97, "\xdc"], "\xaf" => [99, "\xdc"], "\xb0" => [106, "\xdc"], "\xb1" => [136, "\xdc"], "\xb2" => [139, "\xdc"], "\xb3" => [141, "\xdc"], "\xb4" => [145, "\xdc"], "\xb5" => [147, "\xdc"], "\xb6" => [149, "\xdc"], "\xb7" => [101, "\xdc"], "\xb8" => [112, "\xdc"], "\xb9" => [117, "\xdc"], "\xba" => [120, "\xdc"], "\xbb" => [124, "\xdc"], "\xbc" => [127, "\xdc"], "\xbd" => [144, "\xdc"], "\xbe" => [152, "\xdc"], "\xbf" => [11, "\xdc"], "\xc0" => [0, "\xf90"], "\xc1" => [0, "\xf91"], "\xc2" => [0, "\xf92"], "\xc3" => [0, "\xf9a"], "\xc4" => [0, "\xf9c"], "\xc5" => [0, "\xf9e"], "\xc6" => [0, "\xf9i"], "\xc7" => [0, "\xf9o"], "\xc8" => [0, "\xf9s"], "\xc9" => [0, "\xf9t"], "\xca" => [73, "\xf9"], "\xcb" => [88, "\xf9"], "\xcc" => [89, "\xf9"], "\xcd" => [96, "\xf9"], "\xce" => [97, "\xf9"], "\xcf" => [99, "\xf9"], "\xd0" => [106, "\xf9"], "\xd1" => [136, "\xf9"], "\xd2" => [139, "\xf9"], "\xd3" => [141, "\xf9"], "\xd4" => [145, "\xf9"], "\xd5" => [147, "\xf9"], "\xd6" => [149, "\xf9"], "\xd7" => [101, "\xf9"], "\xd8" => [112, "\xf9"], "\xd9" => [117, "\xf9"], "\xda" => [120, "\xf9"], "\xdb" => [124, "\xf9"], "\xdc" => [127, "\xf9"], "\xdd" => [144, "\xf9"], "\xde" => [152, "\xf9"], "\xdf" => [11, "\xf9"], "\xe0" => [93, "\n"], "\xe1" => [138, "\n"], "\xe2" => [75, "\n"], "\xe3" => [91, "\n"], "\xe4" => [108, "\n"], "\xe5" => [103, "\n"], "\xe6" => [114, "\n"], "\xe7" => [14, "\n"], "\xe8" => [93, "\r"], "\xe9" => [138, "\r"], "\xea" => [75, "\r"], "\xeb" => [91, "\r"], "\xec" => [108, "\r"], "\xed" => [103, "\r"], "\xee" => [114, "\r"], "\xef" => [14, "\r"], "\xf0" => [93, "\x16"], "\xf1" => [138, "\x16"], "\xf2" => [75, "\x16"], "\xf3" => [91, "\x16"], "\xf4" => [108, "\x16"], "\xf5" => [103, "\x16"], "\xf6" => [114, "\x16"], "\xf7" => [14, "\x16"], "\xf8" => [93, ""], "\xf9" => [138, ""], "\xfa" => [75, ""], "\xfb" => [91, ""], "\xfc" => [108, ""], "\xfd" => [103, ""], "\xfe" => [114, ""], "\xff" => [14, ""]], ["\x00" => [94, "\f0"], "\x01" => [76, "\f0"], "\x02" => [104, "\f0"], "\x03" => [16, "\f0"], "\x04" => [94, "\f1"], "\x05" => [76, "\f1"], "\x06" => [104, "\f1"], "\x07" => [16, "\f1"], "\x08" => [94, "\f2"], "\t" => [76, "\f2"], "\n" => [104, "\f2"], "\v" => [16, "\f2"], "\f" => [94, "\fa"], "\r" => [76, "\fa"], "\x0e" => [104, "\fa"], "\x0f" => [16, "\fa"], "\x10" => [94, "\fc"], "\x11" => [76, "\fc"], "\x12" => [104, "\fc"], "\x13" => [16, "\fc"], "\x14" => [94, "\fe"], "\x15" => [76, "\fe"], "\x16" => [104, "\fe"], "\x17" => [16, "\fe"], "\x18" => [94, "\fi"], "\x19" => [76, "\fi"], "\x1a" => [104, "\fi"], "\x1b" => [16, "\fi"], "\x1c" => [94, "\fo"], "\x1d" => [76, "\fo"], "\x1e" => [104, "\fo"], "\x1f" => [16, "\fo"], " " => [94, "\fs"], "!" => [76, "\fs"], "\"" => [104, "\fs"], "#" => [16, "\fs"], "\$" => [94, "\ft"], "%" => [76, "\ft"], "&" => [104, "\ft"], "'" => [16, "\ft"], "(" => [77, "\f "], ")" => [18, "\f "], "*" => [77, "\f%"], "+" => [18, "\f%"], "," => [77, "\f-"], "-" => [18, "\f-"], "." => [77, "\f."], "/" => [18, "\f."], [77, "\f/"], [18, "\f/"], [77, "\f3"], [18, "\f3"], [77, "\f4"], [18, "\f4"], [77, "\f5"], [18, "\f5"], [77, "\f6"], [18, "\f6"], ":" => [77, "\f7"], ";" => [18, "\f7"], "<" => [77, "\f8"], "=" => [18, "\f8"], ">" => [77, "\f9"], "?" => [18, "\f9"], "@" => [77, "\f="], "A" => [18, "\f="], "B" => [77, "\fA"], "C" => [18, "\fA"], "D" => [77, "\f_"], "E" => [18, "\f_"], "F" => [77, "\fb"], "G" => [18, "\fb"], "H" => [77, "\fd"], "I" => [18, "\fd"], "J" => [77, "\ff"], "K" => [18, "\ff"], "L" => [77, "\fg"], "M" => [18, "\fg"], "N" => [77, "\fh"], "O" => [18, "\fh"], "P" => [77, "\fl"], "Q" => [18, "\fl"], "R" => [77, "\fm"], "S" => [18, "\fm"], "T" => [77, "\fn"], "U" => [18, "\fn"], "V" => [77, "\fp"], "W" => [18, "\fp"], "X" => [77, "\fr"], "Y" => [18, "\fr"], "Z" => [77, "\fu"], "[" => [18, "\fu"], "\\" => [0, "\f:"], "]" => [0, "\fB"], "^" => [0, "\fC"], "_" => [0, "\fD"], "`" => [0, "\fE"], "a" => [0, "\fF"], "b" => [0, "\fG"], "c" => [0, "\fH"], "d" => [0, "\fI"], "e" => [0, "\fJ"], "f" => [0, "\fK"], "g" => [0, "\fL"], "h" => [0, "\fM"], "i" => [0, "\fN"], "j" => [0, "\fO"], "k" => [0, "\fP"], "l" => [0, "\fQ"], "m" => [0, "\fR"], "n" => [0, "\fS"], "o" => [0, "\fT"], "p" => [0, "\fU"], "q" => [0, "\fV"], "r" => [0, "\fW"], "s" => [0, "\fY"], "t" => [0, "\fj"], "u" => [0, "\fk"], "v" => [0, "\fq"], "w" => [0, "\fv"], "x" => [0, "\fw"], "y" => [0, "\fx"], "z" => [0, "\fy"], "{" => [0, "\fz"], "|" => [82, "\f"], "}" => [87, "\f"], "~" => [130, "\f"], "" => [9, "\f"], "\x80" => [94, "\x0e0"], "\x81" => [76, "\x0e0"], "\x82" => [104, "\x0e0"], "\x83" => [16, "\x0e0"], "\x84" => [94, "\x0e1"], "\x85" => [76, "\x0e1"], "\x86" => [104, "\x0e1"], "\x87" => [16, "\x0e1"], "\x88" => [94, "\x0e2"], "\x89" => [76, "\x0e2"], "\x8a" => [104, "\x0e2"], "\x8b" => [16, "\x0e2"], "\x8c" => [94, "\x0ea"], "\x8d" => [76, "\x0ea"], "\x8e" => [104, "\x0ea"], "\x8f" => [16, "\x0ea"], "\x90" => [94, "\x0ec"], "\x91" => [76, "\x0ec"], "\x92" => [104, "\x0ec"], "\x93" => [16, "\x0ec"], "\x94" => [94, "\x0ee"], "\x95" => [76, "\x0ee"], "\x96" => [104, "\x0ee"], "\x97" => [16, "\x0ee"], "\x98" => [94, "\x0ei"], "\x99" => [76, "\x0ei"], "\x9a" => [104, "\x0ei"], "\x9b" => [16, "\x0ei"], "\x9c" => [94, "\x0eo"], "\x9d" => [76, "\x0eo"], "\x9e" => [104, "\x0eo"], "\x9f" => [16, "\x0eo"], "\xa0" => [94, "\x0es"], "\xa1" => [76, "\x0es"], "\xa2" => [104, "\x0es"], "\xa3" => [16, "\x0es"], "\xa4" => [94, "\x0et"], "\xa5" => [76, "\x0et"], "\xa6" => [104, "\x0et"], "\xa7" => [16, "\x0et"], "\xa8" => [77, "\x0e "], "\xa9" => [18, "\x0e "], "\xaa" => [77, "\x0e%"], "\xab" => [18, "\x0e%"], "\xac" => [77, "\x0e-"], "\xad" => [18, "\x0e-"], "\xae" => [77, "\x0e."], "\xaf" => [18, "\x0e."], "\xb0" => [77, "\x0e/"], "\xb1" => [18, "\x0e/"], "\xb2" => [77, "\x0e3"], "\xb3" => [18, "\x0e3"], "\xb4" => [77, "\x0e4"], "\xb5" => [18, "\x0e4"], "\xb6" => [77, "\x0e5"], "\xb7" => [18, "\x0e5"], "\xb8" => [77, "\x0e6"], "\xb9" => [18, "\x0e6"], "\xba" => [77, "\x0e7"], "\xbb" => [18, "\x0e7"], "\xbc" => [77, "\x0e8"], "\xbd" => [18, "\x0e8"], "\xbe" => [77, "\x0e9"], "\xbf" => [18, "\x0e9"], "\xc0" => [77, "\x0e="], "\xc1" => [18, "\x0e="], "\xc2" => [77, "\x0eA"], "\xc3" => [18, "\x0eA"], "\xc4" => [77, "\x0e_"], "\xc5" => [18, "\x0e_"], "\xc6" => [77, "\x0eb"], "\xc7" => [18, "\x0eb"], "\xc8" => [77, "\x0ed"], "\xc9" => [18, "\x0ed"], "\xca" => [77, "\x0ef"], "\xcb" => [18, "\x0ef"], "\xcc" => [77, "\x0eg"], "\xcd" => [18, "\x0eg"], "\xce" => [77, "\x0eh"], "\xcf" => [18, "\x0eh"], "\xd0" => [77, "\x0el"], "\xd1" => [18, "\x0el"], "\xd2" => [77, "\x0em"], "\xd3" => [18, "\x0em"], "\xd4" => [77, "\x0en"], "\xd5" => [18, "\x0en"], "\xd6" => [77, "\x0ep"], "\xd7" => [18, "\x0ep"], "\xd8" => [77, "\x0er"], "\xd9" => [18, "\x0er"], "\xda" => [77, "\x0eu"], "\xdb" => [18, "\x0eu"], "\xdc" => [0, "\x0e:"], "\xdd" => [0, "\x0eB"], "\xde" => [0, "\x0eC"], "\xdf" => [0, "\x0eD"], "\xe0" => [0, "\x0eE"], "\xe1" => [0, "\x0eF"], "\xe2" => [0, "\x0eG"], "\xe3" => [0, "\x0eH"], "\xe4" => [0, "\x0eI"], "\xe5" => [0, "\x0eJ"], "\xe6" => [0, "\x0eK"], "\xe7" => [0, "\x0eL"], "\xe8" => [0, "\x0eM"], "\xe9" => [0, "\x0eN"], "\xea" => [0, "\x0eO"], "\xeb" => [0, "\x0eP"], "\xec" => [0, "\x0eQ"], "\xed" => [0, "\x0eR"], "\xee" => [0, "\x0eS"], "\xef" => [0, "\x0eT"], "\xf0" => [0, "\x0eU"], "\xf1" => [0, "\x0eV"], "\xf2" => [0, "\x0eW"], "\xf3" => [0, "\x0eY"], "\xf4" => [0, "\x0ej"], "\xf5" => [0, "\x0ek"], "\xf6" => [0, "\x0eq"], "\xf7" => [0, "\x0ev"], "\xf8" => [0, "\x0ew"], "\xf9" => [0, "\x0ex"], "\xfa" => [0, "\x0ey"], "\xfb" => [0, "\x0ez"], "\xfc" => [82, "\x0e"], "\xfd" => [87, "\x0e"], "\xfe" => [130, "\x0e"], "\xff" => [9, "\x0e"]], ["\x00" => [94, "\x0f0"], "\x01" => [76, "\x0f0"], "\x02" => [104, "\x0f0"], "\x03" => [16, "\x0f0"], "\x04" => [94, "\x0f1"], "\x05" => [76, "\x0f1"], "\x06" => [104, "\x0f1"], "\x07" => [16, "\x0f1"], "\x08" => [94, "\x0f2"], "\t" => [76, "\x0f2"], "\n" => [104, "\x0f2"], "\v" => [16, "\x0f2"], "\f" => [94, "\x0fa"], "\r" => [76, "\x0fa"], "\x0e" => [104, "\x0fa"], "\x0f" => [16, "\x0fa"], "\x10" => [94, "\x0fc"], "\x11" => [76, "\x0fc"], "\x12" => [104, "\x0fc"], "\x13" => [16, "\x0fc"], "\x14" => [94, "\x0fe"], "\x15" => [76, "\x0fe"], "\x16" => [104, "\x0fe"], "\x17" => [16, "\x0fe"], "\x18" => [94, "\x0fi"], "\x19" => [76, "\x0fi"], "\x1a" => [104, "\x0fi"], "\x1b" => [16, "\x0fi"], "\x1c" => [94, "\x0fo"], "\x1d" => [76, "\x0fo"], "\x1e" => [104, "\x0fo"], "\x1f" => [16, "\x0fo"], " " => [94, "\x0fs"], "!" => [76, "\x0fs"], "\"" => [104, "\x0fs"], "#" => [16, "\x0fs"], "\$" => [94, "\x0ft"], "%" => [76, "\x0ft"], "&" => [104, "\x0ft"], "'" => [16, "\x0ft"], "(" => [77, "\x0f "], ")" => [18, "\x0f "], "*" => [77, "\x0f%"], "+" => [18, "\x0f%"], "," => [77, "\x0f-"], "-" => [18, "\x0f-"], "." => [77, "\x0f."], "/" => [18, "\x0f."], [77, "\x0f/"], [18, "\x0f/"], [77, "\x0f3"], [18, "\x0f3"], [77, "\x0f4"], [18, "\x0f4"], [77, "\x0f5"], [18, "\x0f5"], [77, "\x0f6"], [18, "\x0f6"], ":" => [77, "\x0f7"], ";" => [18, "\x0f7"], "<" => [77, "\x0f8"], "=" => [18, "\x0f8"], ">" => [77, "\x0f9"], "?" => [18, "\x0f9"], "@" => [77, "\x0f="], "A" => [18, "\x0f="], "B" => [77, "\x0fA"], "C" => [18, "\x0fA"], "D" => [77, "\x0f_"], "E" => [18, "\x0f_"], "F" => [77, "\x0fb"], "G" => [18, "\x0fb"], "H" => [77, "\x0fd"], "I" => [18, "\x0fd"], "J" => [77, "\x0ff"], "K" => [18, "\x0ff"], "L" => [77, "\x0fg"], "M" => [18, "\x0fg"], "N" => [77, "\x0fh"], "O" => [18, "\x0fh"], "P" => [77, "\x0fl"], "Q" => [18, "\x0fl"], "R" => [77, "\x0fm"], "S" => [18, "\x0fm"], "T" => [77, "\x0fn"], "U" => [18, "\x0fn"], "V" => [77, "\x0fp"], "W" => [18, "\x0fp"], "X" => [77, "\x0fr"], "Y" => [18, "\x0fr"], "Z" => [77, "\x0fu"], "[" => [18, "\x0fu"], "\\" => [0, "\x0f:"], "]" => [0, "\x0fB"], "^" => [0, "\x0fC"], "_" => [0, "\x0fD"], "`" => [0, "\x0fE"], "a" => [0, "\x0fF"], "b" => [0, "\x0fG"], "c" => [0, "\x0fH"], "d" => [0, "\x0fI"], "e" => [0, "\x0fJ"], "f" => [0, "\x0fK"], "g" => [0, "\x0fL"], "h" => [0, "\x0fM"], "i" => [0, "\x0fN"], "j" => [0, "\x0fO"], "k" => [0, "\x0fP"], "l" => [0, "\x0fQ"], "m" => [0, "\x0fR"], "n" => [0, "\x0fS"], "o" => [0, "\x0fT"], "p" => [0, "\x0fU"], "q" => [0, "\x0fV"], "r" => [0, "\x0fW"], "s" => [0, "\x0fY"], "t" => [0, "\x0fj"], "u" => [0, "\x0fk"], "v" => [0, "\x0fq"], "w" => [0, "\x0fv"], "x" => [0, "\x0fw"], "y" => [0, "\x0fx"], "z" => [0, "\x0fy"], "{" => [0, "\x0fz"], "|" => [82, "\x0f"], "}" => [87, "\x0f"], "~" => [130, "\x0f"], "" => [9, "\x0f"], "\x80" => [94, "\x100"], "\x81" => [76, "\x100"], "\x82" => [104, "\x100"], "\x83" => [16, "\x100"], "\x84" => [94, "\x101"], "\x85" => [76, "\x101"], "\x86" => [104, "\x101"], "\x87" => [16, "\x101"], "\x88" => [94, "\x102"], "\x89" => [76, "\x102"], "\x8a" => [104, "\x102"], "\x8b" => [16, "\x102"], "\x8c" => [94, "\x10a"], "\x8d" => [76, "\x10a"], "\x8e" => [104, "\x10a"], "\x8f" => [16, "\x10a"], "\x90" => [94, "\x10c"], "\x91" => [76, "\x10c"], "\x92" => [104, "\x10c"], "\x93" => [16, "\x10c"], "\x94" => [94, "\x10e"], "\x95" => [76, "\x10e"], "\x96" => [104, "\x10e"], "\x97" => [16, "\x10e"], "\x98" => [94, "\x10i"], "\x99" => [76, "\x10i"], "\x9a" => [104, "\x10i"], "\x9b" => [16, "\x10i"], "\x9c" => [94, "\x10o"], "\x9d" => [76, "\x10o"], "\x9e" => [104, "\x10o"], "\x9f" => [16, "\x10o"], "\xa0" => [94, "\x10s"], "\xa1" => [76, "\x10s"], "\xa2" => [104, "\x10s"], "\xa3" => [16, "\x10s"], "\xa4" => [94, "\x10t"], "\xa5" => [76, "\x10t"], "\xa6" => [104, "\x10t"], "\xa7" => [16, "\x10t"], "\xa8" => [77, "\x10 "], "\xa9" => [18, "\x10 "], "\xaa" => [77, "\x10%"], "\xab" => [18, "\x10%"], "\xac" => [77, "\x10-"], "\xad" => [18, "\x10-"], "\xae" => [77, "\x10."], "\xaf" => [18, "\x10."], "\xb0" => [77, "\x10/"], "\xb1" => [18, "\x10/"], "\xb2" => [77, "\x103"], "\xb3" => [18, "\x103"], "\xb4" => [77, "\x104"], "\xb5" => [18, "\x104"], "\xb6" => [77, "\x105"], "\xb7" => [18, "\x105"], "\xb8" => [77, "\x106"], "\xb9" => [18, "\x106"], "\xba" => [77, "\x107"], "\xbb" => [18, "\x107"], "\xbc" => [77, "\x108"], "\xbd" => [18, "\x108"], "\xbe" => [77, "\x109"], "\xbf" => [18, "\x109"], "\xc0" => [77, "\x10="], "\xc1" => [18, "\x10="], "\xc2" => [77, "\x10A"], "\xc3" => [18, "\x10A"], "\xc4" => [77, "\x10_"], "\xc5" => [18, "\x10_"], "\xc6" => [77, "\x10b"], "\xc7" => [18, "\x10b"], "\xc8" => [77, "\x10d"], "\xc9" => [18, "\x10d"], "\xca" => [77, "\x10f"], "\xcb" => [18, "\x10f"], "\xcc" => [77, "\x10g"], "\xcd" => [18, "\x10g"], "\xce" => [77, "\x10h"], "\xcf" => [18, "\x10h"], "\xd0" => [77, "\x10l"], "\xd1" => [18, "\x10l"], "\xd2" => [77, "\x10m"], "\xd3" => [18, "\x10m"], "\xd4" => [77, "\x10n"], "\xd5" => [18, "\x10n"], "\xd6" => [77, "\x10p"], "\xd7" => [18, "\x10p"], "\xd8" => [77, "\x10r"], "\xd9" => [18, "\x10r"], "\xda" => [77, "\x10u"], "\xdb" => [18, "\x10u"], "\xdc" => [0, "\x10:"], "\xdd" => [0, "\x10B"], "\xde" => [0, "\x10C"], "\xdf" => [0, "\x10D"], "\xe0" => [0, "\x10E"], "\xe1" => [0, "\x10F"], "\xe2" => [0, "\x10G"], "\xe3" => [0, "\x10H"], "\xe4" => [0, "\x10I"], "\xe5" => [0, "\x10J"], "\xe6" => [0, "\x10K"], "\xe7" => [0, "\x10L"], "\xe8" => [0, "\x10M"], "\xe9" => [0, "\x10N"], "\xea" => [0, "\x10O"], "\xeb" => [0, "\x10P"], "\xec" => [0, "\x10Q"], "\xed" => [0, "\x10R"], "\xee" => [0, "\x10S"], "\xef" => [0, "\x10T"], "\xf0" => [0, "\x10U"], "\xf1" => [0, "\x10V"], "\xf2" => [0, "\x10W"], "\xf3" => [0, "\x10Y"], "\xf4" => [0, "\x10j"], "\xf5" => [0, "\x10k"], "\xf6" => [0, "\x10q"], "\xf7" => [0, "\x10v"], "\xf8" => [0, "\x10w"], "\xf9" => [0, "\x10x"], "\xfa" => [0, "\x10y"], "\xfb" => [0, "\x10z"], "\xfc" => [82, "\x10"], "\xfd" => [87, "\x10"], "\xfe" => [130, "\x10"], "\xff" => [9, "\x10"]], ["\x00" => [77, "\x0f0"], "\x01" => [18, "\x0f0"], "\x02" => [77, "\x0f1"], "\x03" => [18, "\x0f1"], "\x04" => [77, "\x0f2"], "\x05" => [18, "\x0f2"], "\x06" => [77, "\x0fa"], "\x07" => [18, "\x0fa"], "\x08" => [77, "\x0fc"], "\t" => [18, "\x0fc"], "\n" => [77, "\x0fe"], "\v" => [18, "\x0fe"], "\f" => [77, "\x0fi"], "\r" => [18, "\x0fi"], "\x0e" => [77, "\x0fo"], "\x0f" => [18, "\x0fo"], "\x10" => [77, "\x0fs"], "\x11" => [18, "\x0fs"], "\x12" => [77, "\x0ft"], "\x13" => [18, "\x0ft"], "\x14" => [0, "\x0f "], "\x15" => [0, "\x0f%"], "\x16" => [0, "\x0f-"], "\x17" => [0, "\x0f."], "\x18" => [0, "\x0f/"], "\x19" => [0, "\x0f3"], "\x1a" => [0, "\x0f4"], "\x1b" => [0, "\x0f5"], "\x1c" => [0, "\x0f6"], "\x1d" => [0, "\x0f7"], "\x1e" => [0, "\x0f8"], "\x1f" => [0, "\x0f9"], " " => [0, "\x0f="], "!" => [0, "\x0fA"], "\"" => [0, "\x0f_"], "#" => [0, "\x0fb"], "\$" => [0, "\x0fd"], "%" => [0, "\x0ff"], "&" => [0, "\x0fg"], "'" => [0, "\x0fh"], "(" => [0, "\x0fl"], ")" => [0, "\x0fm"], "*" => [0, "\x0fn"], "+" => [0, "\x0fp"], "," => [0, "\x0fr"], "-" => [0, "\x0fu"], "." => [100, "\x0f"], "/" => [110, "\x0f"], [111, "\x0f"], [115, "\x0f"], [116, "\x0f"], [118, "\x0f"], [119, "\x0f"], [122, "\x0f"], [123, "\x0f"], [125, "\x0f"], [126, "\x0f"], [129, "\x0f"], ":" => [143, "\x0f"], ";" => [148, "\x0f"], "<" => [151, "\x0f"], "=" => [153, "\x0f"], ">" => [83, "\x0f"], "?" => [10, "\x0f"], "@" => [77, "\x100"], "A" => [18, "\x100"], "B" => [77, "\x101"], "C" => [18, "\x101"], "D" => [77, "\x102"], "E" => [18, "\x102"], "F" => [77, "\x10a"], "G" => [18, "\x10a"], "H" => [77, "\x10c"], "I" => [18, "\x10c"], "J" => [77, "\x10e"], "K" => [18, "\x10e"], "L" => [77, "\x10i"], "M" => [18, "\x10i"], "N" => [77, "\x10o"], "O" => [18, "\x10o"], "P" => [77, "\x10s"], "Q" => [18, "\x10s"], "R" => [77, "\x10t"], "S" => [18, "\x10t"], "T" => [0, "\x10 "], "U" => [0, "\x10%"], "V" => [0, "\x10-"], "W" => [0, "\x10."], "X" => [0, "\x10/"], "Y" => [0, "\x103"], "Z" => [0, "\x104"], "[" => [0, "\x105"], "\\" => [0, "\x106"], "]" => [0, "\x107"], "^" => [0, "\x108"], "_" => [0, "\x109"], "`" => [0, "\x10="], "a" => [0, "\x10A"], "b" => [0, "\x10_"], "c" => [0, "\x10b"], "d" => [0, "\x10d"], "e" => [0, "\x10f"], "f" => [0, "\x10g"], "g" => [0, "\x10h"], "h" => [0, "\x10l"], "i" => [0, "\x10m"], "j" => [0, "\x10n"], "k" => [0, "\x10p"], "l" => [0, "\x10r"], "m" => [0, "\x10u"], "n" => [100, "\x10"], "o" => [110, "\x10"], "p" => [111, "\x10"], "q" => [115, "\x10"], "r" => [116, "\x10"], "s" => [118, "\x10"], "t" => [119, "\x10"], "u" => [122, "\x10"], "v" => [123, "\x10"], "w" => [125, "\x10"], "x" => [126, "\x10"], "y" => [129, "\x10"], "z" => [143, "\x10"], "{" => [148, "\x10"], "|" => [151, "\x10"], "}" => [153, "\x10"], "~" => [83, "\x10"], "" => [10, "\x10"], "\x80" => [77, "\x110"], "\x81" => [18, "\x110"], "\x82" => [77, "\x111"], "\x83" => [18, "\x111"], "\x84" => [77, "\x112"], "\x85" => [18, "\x112"], "\x86" => [77, "\x11a"], "\x87" => [18, "\x11a"], "\x88" => [77, "\x11c"], "\x89" => [18, "\x11c"], "\x8a" => [77, "\x11e"], "\x8b" => [18, "\x11e"], "\x8c" => [77, "\x11i"], "\x8d" => [18, "\x11i"], "\x8e" => [77, "\x11o"], "\x8f" => [18, "\x11o"], "\x90" => [77, "\x11s"], "\x91" => [18, "\x11s"], "\x92" => [77, "\x11t"], "\x93" => [18, "\x11t"], "\x94" => [0, "\x11 "], "\x95" => [0, "\x11%"], "\x96" => [0, "\x11-"], "\x97" => [0, "\x11."], "\x98" => [0, "\x11/"], "\x99" => [0, "\x113"], "\x9a" => [0, "\x114"], "\x9b" => [0, "\x115"], "\x9c" => [0, "\x116"], "\x9d" => [0, "\x117"], "\x9e" => [0, "\x118"], "\x9f" => [0, "\x119"], "\xa0" => [0, "\x11="], "\xa1" => [0, "\x11A"], "\xa2" => [0, "\x11_"], "\xa3" => [0, "\x11b"], "\xa4" => [0, "\x11d"], "\xa5" => [0, "\x11f"], "\xa6" => [0, "\x11g"], "\xa7" => [0, "\x11h"], "\xa8" => [0, "\x11l"], "\xa9" => [0, "\x11m"], "\xaa" => [0, "\x11n"], "\xab" => [0, "\x11p"], "\xac" => [0, "\x11r"], "\xad" => [0, "\x11u"], "\xae" => [100, "\x11"], "\xaf" => [110, "\x11"], "\xb0" => [111, "\x11"], "\xb1" => [115, "\x11"], "\xb2" => [116, "\x11"], "\xb3" => [118, "\x11"], "\xb4" => [119, "\x11"], "\xb5" => [122, "\x11"], "\xb6" => [123, "\x11"], "\xb7" => [125, "\x11"], "\xb8" => [126, "\x11"], "\xb9" => [129, "\x11"], "\xba" => [143, "\x11"], "\xbb" => [148, "\x11"], "\xbc" => [151, "\x11"], "\xbd" => [153, "\x11"], "\xbe" => [83, "\x11"], "\xbf" => [10, "\x11"], "\xc0" => [77, "\x120"], "\xc1" => [18, "\x120"], "\xc2" => [77, "\x121"], "\xc3" => [18, "\x121"], "\xc4" => [77, "\x122"], "\xc5" => [18, "\x122"], "\xc6" => [77, "\x12a"], "\xc7" => [18, "\x12a"], "\xc8" => [77, "\x12c"], "\xc9" => [18, "\x12c"], "\xca" => [77, "\x12e"], "\xcb" => [18, "\x12e"], "\xcc" => [77, "\x12i"], "\xcd" => [18, "\x12i"], "\xce" => [77, "\x12o"], "\xcf" => [18, "\x12o"], "\xd0" => [77, "\x12s"], "\xd1" => [18, "\x12s"], "\xd2" => [77, "\x12t"], "\xd3" => [18, "\x12t"], "\xd4" => [0, "\x12 "], "\xd5" => [0, "\x12%"], "\xd6" => [0, "\x12-"], "\xd7" => [0, "\x12."], "\xd8" => [0, "\x12/"], "\xd9" => [0, "\x123"], "\xda" => [0, "\x124"], "\xdb" => [0, "\x125"], "\xdc" => [0, "\x126"], "\xdd" => [0, "\x127"], "\xde" => [0, "\x128"], "\xdf" => [0, "\x129"], "\xe0" => [0, "\x12="], "\xe1" => [0, "\x12A"], "\xe2" => [0, "\x12_"], "\xe3" => [0, "\x12b"], "\xe4" => [0, "\x12d"], "\xe5" => [0, "\x12f"], "\xe6" => [0, "\x12g"], "\xe7" => [0, "\x12h"], "\xe8" => [0, "\x12l"], "\xe9" => [0, "\x12m"], "\xea" => [0, "\x12n"], "\xeb" => [0, "\x12p"], "\xec" => [0, "\x12r"], "\xed" => [0, "\x12u"], "\xee" => [100, "\x12"], "\xef" => [110, "\x12"], "\xf0" => [111, "\x12"], "\xf1" => [115, "\x12"], "\xf2" => [116, "\x12"], "\xf3" => [118, "\x12"], "\xf4" => [119, "\x12"], "\xf5" => [122, "\x12"], "\xf6" => [123, "\x12"], "\xf7" => [125, "\x12"], "\xf8" => [126, "\x12"], "\xf9" => [129, "\x12"], "\xfa" => [143, "\x12"], "\xfb" => [148, "\x12"], "\xfc" => [151, "\x12"], "\xfd" => [153, "\x12"], "\xfe" => [83, "\x12"], "\xff" => [10, "\x12"]], ["\x00" => [94, "\x110"], "\x01" => [76, "\x110"], "\x02" => [104, "\x110"], "\x03" => [16, "\x110"], "\x04" => [94, "\x111"], "\x05" => [76, "\x111"], "\x06" => [104, "\x111"], "\x07" => [16, "\x111"], "\x08" => [94, "\x112"], "\t" => [76, "\x112"], "\n" => [104, "\x112"], "\v" => [16, "\x112"], "\f" => [94, "\x11a"], "\r" => [76, "\x11a"], "\x0e" => [104, "\x11a"], "\x0f" => [16, "\x11a"], "\x10" => [94, "\x11c"], "\x11" => [76, "\x11c"], "\x12" => [104, "\x11c"], "\x13" => [16, "\x11c"], "\x14" => [94, "\x11e"], "\x15" => [76, "\x11e"], "\x16" => [104, "\x11e"], "\x17" => [16, "\x11e"], "\x18" => [94, "\x11i"], "\x19" => [76, "\x11i"], "\x1a" => [104, "\x11i"], "\x1b" => [16, "\x11i"], "\x1c" => [94, "\x11o"], "\x1d" => [76, "\x11o"], "\x1e" => [104, "\x11o"], "\x1f" => [16, "\x11o"], " " => [94, "\x11s"], "!" => [76, "\x11s"], "\"" => [104, "\x11s"], "#" => [16, "\x11s"], "\$" => [94, "\x11t"], "%" => [76, "\x11t"], "&" => [104, "\x11t"], "'" => [16, "\x11t"], "(" => [77, "\x11 "], ")" => [18, "\x11 "], "*" => [77, "\x11%"], "+" => [18, "\x11%"], "," => [77, "\x11-"], "-" => [18, "\x11-"], "." => [77, "\x11."], "/" => [18, "\x11."], [77, "\x11/"], [18, "\x11/"], [77, "\x113"], [18, "\x113"], [77, "\x114"], [18, "\x114"], [77, "\x115"], [18, "\x115"], [77, "\x116"], [18, "\x116"], ":" => [77, "\x117"], ";" => [18, "\x117"], "<" => [77, "\x118"], "=" => [18, "\x118"], ">" => [77, "\x119"], "?" => [18, "\x119"], "@" => [77, "\x11="], "A" => [18, "\x11="], "B" => [77, "\x11A"], "C" => [18, "\x11A"], "D" => [77, "\x11_"], "E" => [18, "\x11_"], "F" => [77, "\x11b"], "G" => [18, "\x11b"], "H" => [77, "\x11d"], "I" => [18, "\x11d"], "J" => [77, "\x11f"], "K" => [18, "\x11f"], "L" => [77, "\x11g"], "M" => [18, "\x11g"], "N" => [77, "\x11h"], "O" => [18, "\x11h"], "P" => [77, "\x11l"], "Q" => [18, "\x11l"], "R" => [77, "\x11m"], "S" => [18, "\x11m"], "T" => [77, "\x11n"], "U" => [18, "\x11n"], "V" => [77, "\x11p"], "W" => [18, "\x11p"], "X" => [77, "\x11r"], "Y" => [18, "\x11r"], "Z" => [77, "\x11u"], "[" => [18, "\x11u"], "\\" => [0, "\x11:"], "]" => [0, "\x11B"], "^" => [0, "\x11C"], "_" => [0, "\x11D"], "`" => [0, "\x11E"], "a" => [0, "\x11F"], "b" => [0, "\x11G"], "c" => [0, "\x11H"], "d" => [0, "\x11I"], "e" => [0, "\x11J"], "f" => [0, "\x11K"], "g" => [0, "\x11L"], "h" => [0, "\x11M"], "i" => [0, "\x11N"], "j" => [0, "\x11O"], "k" => [0, "\x11P"], "l" => [0, "\x11Q"], "m" => [0, "\x11R"], "n" => [0, "\x11S"], "o" => [0, "\x11T"], "p" => [0, "\x11U"], "q" => [0, "\x11V"], "r" => [0, "\x11W"], "s" => [0, "\x11Y"], "t" => [0, "\x11j"], "u" => [0, "\x11k"], "v" => [0, "\x11q"], "w" => [0, "\x11v"], "x" => [0, "\x11w"], "y" => [0, "\x11x"], "z" => [0, "\x11y"], "{" => [0, "\x11z"], "|" => [82, "\x11"], "}" => [87, "\x11"], "~" => [130, "\x11"], "" => [9, "\x11"], "\x80" => [94, "\x120"], "\x81" => [76, "\x120"], "\x82" => [104, "\x120"], "\x83" => [16, "\x120"], "\x84" => [94, "\x121"], "\x85" => [76, "\x121"], "\x86" => [104, "\x121"], "\x87" => [16, "\x121"], "\x88" => [94, "\x122"], "\x89" => [76, "\x122"], "\x8a" => [104, "\x122"], "\x8b" => [16, "\x122"], "\x8c" => [94, "\x12a"], "\x8d" => [76, "\x12a"], "\x8e" => [104, "\x12a"], "\x8f" => [16, "\x12a"], "\x90" => [94, "\x12c"], "\x91" => [76, "\x12c"], "\x92" => [104, "\x12c"], "\x93" => [16, "\x12c"], "\x94" => [94, "\x12e"], "\x95" => [76, "\x12e"], "\x96" => [104, "\x12e"], "\x97" => [16, "\x12e"], "\x98" => [94, "\x12i"], "\x99" => [76, "\x12i"], "\x9a" => [104, "\x12i"], "\x9b" => [16, "\x12i"], "\x9c" => [94, "\x12o"], "\x9d" => [76, "\x12o"], "\x9e" => [104, "\x12o"], "\x9f" => [16, "\x12o"], "\xa0" => [94, "\x12s"], "\xa1" => [76, "\x12s"], "\xa2" => [104, "\x12s"], "\xa3" => [16, "\x12s"], "\xa4" => [94, "\x12t"], "\xa5" => [76, "\x12t"], "\xa6" => [104, "\x12t"], "\xa7" => [16, "\x12t"], "\xa8" => [77, "\x12 "], "\xa9" => [18, "\x12 "], "\xaa" => [77, "\x12%"], "\xab" => [18, "\x12%"], "\xac" => [77, "\x12-"], "\xad" => [18, "\x12-"], "\xae" => [77, "\x12."], "\xaf" => [18, "\x12."], "\xb0" => [77, "\x12/"], "\xb1" => [18, "\x12/"], "\xb2" => [77, "\x123"], "\xb3" => [18, "\x123"], "\xb4" => [77, "\x124"], "\xb5" => [18, "\x124"], "\xb6" => [77, "\x125"], "\xb7" => [18, "\x125"], "\xb8" => [77, "\x126"], "\xb9" => [18, "\x126"], "\xba" => [77, "\x127"], "\xbb" => [18, "\x127"], "\xbc" => [77, "\x128"], "\xbd" => [18, "\x128"], "\xbe" => [77, "\x129"], "\xbf" => [18, "\x129"], "\xc0" => [77, "\x12="], "\xc1" => [18, "\x12="], "\xc2" => [77, "\x12A"], "\xc3" => [18, "\x12A"], "\xc4" => [77, "\x12_"], "\xc5" => [18, "\x12_"], "\xc6" => [77, "\x12b"], "\xc7" => [18, "\x12b"], "\xc8" => [77, "\x12d"], "\xc9" => [18, "\x12d"], "\xca" => [77, "\x12f"], "\xcb" => [18, "\x12f"], "\xcc" => [77, "\x12g"], "\xcd" => [18, "\x12g"], "\xce" => [77, "\x12h"], "\xcf" => [18, "\x12h"], "\xd0" => [77, "\x12l"], "\xd1" => [18, "\x12l"], "\xd2" => [77, "\x12m"], "\xd3" => [18, "\x12m"], "\xd4" => [77, "\x12n"], "\xd5" => [18, "\x12n"], "\xd6" => [77, "\x12p"], "\xd7" => [18, "\x12p"], "\xd8" => [77, "\x12r"], "\xd9" => [18, "\x12r"], "\xda" => [77, "\x12u"], "\xdb" => [18, "\x12u"], "\xdc" => [0, "\x12:"], "\xdd" => [0, "\x12B"], "\xde" => [0, "\x12C"], "\xdf" => [0, "\x12D"], "\xe0" => [0, "\x12E"], "\xe1" => [0, "\x12F"], "\xe2" => [0, "\x12G"], "\xe3" => [0, "\x12H"], "\xe4" => [0, "\x12I"], "\xe5" => [0, "\x12J"], "\xe6" => [0, "\x12K"], "\xe7" => [0, "\x12L"], "\xe8" => [0, "\x12M"], "\xe9" => [0, "\x12N"], "\xea" => [0, "\x12O"], "\xeb" => [0, "\x12P"], "\xec" => [0, "\x12Q"], "\xed" => [0, "\x12R"], "\xee" => [0, "\x12S"], "\xef" => [0, "\x12T"], "\xf0" => [0, "\x12U"], "\xf1" => [0, "\x12V"], "\xf2" => [0, "\x12W"], "\xf3" => [0, "\x12Y"], "\xf4" => [0, "\x12j"], "\xf5" => [0, "\x12k"], "\xf6" => [0, "\x12q"], "\xf7" => [0, "\x12v"], "\xf8" => [0, "\x12w"], "\xf9" => [0, "\x12x"], "\xfa" => [0, "\x12y"], "\xfb" => [0, "\x12z"], "\xfc" => [82, "\x12"], "\xfd" => [87, "\x12"], "\xfe" => [130, "\x12"], "\xff" => [9, "\x12"]], ["\x00" => [94, "\x130"], "\x01" => [76, "\x130"], "\x02" => [104, "\x130"], "\x03" => [16, "\x130"], "\x04" => [94, "\x131"], "\x05" => [76, "\x131"], "\x06" => [104, "\x131"], "\x07" => [16, "\x131"], "\x08" => [94, "\x132"], "\t" => [76, "\x132"], "\n" => [104, "\x132"], "\v" => [16, "\x132"], "\f" => [94, "\x13a"], "\r" => [76, "\x13a"], "\x0e" => [104, "\x13a"], "\x0f" => [16, "\x13a"], "\x10" => [94, "\x13c"], "\x11" => [76, "\x13c"], "\x12" => [104, "\x13c"], "\x13" => [16, "\x13c"], "\x14" => [94, "\x13e"], "\x15" => [76, "\x13e"], "\x16" => [104, "\x13e"], "\x17" => [16, "\x13e"], "\x18" => [94, "\x13i"], "\x19" => [76, "\x13i"], "\x1a" => [104, "\x13i"], "\x1b" => [16, "\x13i"], "\x1c" => [94, "\x13o"], "\x1d" => [76, "\x13o"], "\x1e" => [104, "\x13o"], "\x1f" => [16, "\x13o"], " " => [94, "\x13s"], "!" => [76, "\x13s"], "\"" => [104, "\x13s"], "#" => [16, "\x13s"], "\$" => [94, "\x13t"], "%" => [76, "\x13t"], "&" => [104, "\x13t"], "'" => [16, "\x13t"], "(" => [77, "\x13 "], ")" => [18, "\x13 "], "*" => [77, "\x13%"], "+" => [18, "\x13%"], "," => [77, "\x13-"], "-" => [18, "\x13-"], "." => [77, "\x13."], "/" => [18, "\x13."], [77, "\x13/"], [18, "\x13/"], [77, "\x133"], [18, "\x133"], [77, "\x134"], [18, "\x134"], [77, "\x135"], [18, "\x135"], [77, "\x136"], [18, "\x136"], ":" => [77, "\x137"], ";" => [18, "\x137"], "<" => [77, "\x138"], "=" => [18, "\x138"], ">" => [77, "\x139"], "?" => [18, "\x139"], "@" => [77, "\x13="], "A" => [18, "\x13="], "B" => [77, "\x13A"], "C" => [18, "\x13A"], "D" => [77, "\x13_"], "E" => [18, "\x13_"], "F" => [77, "\x13b"], "G" => [18, "\x13b"], "H" => [77, "\x13d"], "I" => [18, "\x13d"], "J" => [77, "\x13f"], "K" => [18, "\x13f"], "L" => [77, "\x13g"], "M" => [18, "\x13g"], "N" => [77, "\x13h"], "O" => [18, "\x13h"], "P" => [77, "\x13l"], "Q" => [18, "\x13l"], "R" => [77, "\x13m"], "S" => [18, "\x13m"], "T" => [77, "\x13n"], "U" => [18, "\x13n"], "V" => [77, "\x13p"], "W" => [18, "\x13p"], "X" => [77, "\x13r"], "Y" => [18, "\x13r"], "Z" => [77, "\x13u"], "[" => [18, "\x13u"], "\\" => [0, "\x13:"], "]" => [0, "\x13B"], "^" => [0, "\x13C"], "_" => [0, "\x13D"], "`" => [0, "\x13E"], "a" => [0, "\x13F"], "b" => [0, "\x13G"], "c" => [0, "\x13H"], "d" => [0, "\x13I"], "e" => [0, "\x13J"], "f" => [0, "\x13K"], "g" => [0, "\x13L"], "h" => [0, "\x13M"], "i" => [0, "\x13N"], "j" => [0, "\x13O"], "k" => [0, "\x13P"], "l" => [0, "\x13Q"], "m" => [0, "\x13R"], "n" => [0, "\x13S"], "o" => [0, "\x13T"], "p" => [0, "\x13U"], "q" => [0, "\x13V"], "r" => [0, "\x13W"], "s" => [0, "\x13Y"], "t" => [0, "\x13j"], "u" => [0, "\x13k"], "v" => [0, "\x13q"], "w" => [0, "\x13v"], "x" => [0, "\x13w"], "y" => [0, "\x13x"], "z" => [0, "\x13y"], "{" => [0, "\x13z"], "|" => [82, "\x13"], "}" => [87, "\x13"], "~" => [130, "\x13"], "" => [9, "\x13"], "\x80" => [94, "\x140"], "\x81" => [76, "\x140"], "\x82" => [104, "\x140"], "\x83" => [16, "\x140"], "\x84" => [94, "\x141"], "\x85" => [76, "\x141"], "\x86" => [104, "\x141"], "\x87" => [16, "\x141"], "\x88" => [94, "\x142"], "\x89" => [76, "\x142"], "\x8a" => [104, "\x142"], "\x8b" => [16, "\x142"], "\x8c" => [94, "\x14a"], "\x8d" => [76, "\x14a"], "\x8e" => [104, "\x14a"], "\x8f" => [16, "\x14a"], "\x90" => [94, "\x14c"], "\x91" => [76, "\x14c"], "\x92" => [104, "\x14c"], "\x93" => [16, "\x14c"], "\x94" => [94, "\x14e"], "\x95" => [76, "\x14e"], "\x96" => [104, "\x14e"], "\x97" => [16, "\x14e"], "\x98" => [94, "\x14i"], "\x99" => [76, "\x14i"], "\x9a" => [104, "\x14i"], "\x9b" => [16, "\x14i"], "\x9c" => [94, "\x14o"], "\x9d" => [76, "\x14o"], "\x9e" => [104, "\x14o"], "\x9f" => [16, "\x14o"], "\xa0" => [94, "\x14s"], "\xa1" => [76, "\x14s"], "\xa2" => [104, "\x14s"], "\xa3" => [16, "\x14s"], "\xa4" => [94, "\x14t"], "\xa5" => [76, "\x14t"], "\xa6" => [104, "\x14t"], "\xa7" => [16, "\x14t"], "\xa8" => [77, "\x14 "], "\xa9" => [18, "\x14 "], "\xaa" => [77, "\x14%"], "\xab" => [18, "\x14%"], "\xac" => [77, "\x14-"], "\xad" => [18, "\x14-"], "\xae" => [77, "\x14."], "\xaf" => [18, "\x14."], "\xb0" => [77, "\x14/"], "\xb1" => [18, "\x14/"], "\xb2" => [77, "\x143"], "\xb3" => [18, "\x143"], "\xb4" => [77, "\x144"], "\xb5" => [18, "\x144"], "\xb6" => [77, "\x145"], "\xb7" => [18, "\x145"], "\xb8" => [77, "\x146"], "\xb9" => [18, "\x146"], "\xba" => [77, "\x147"], "\xbb" => [18, "\x147"], "\xbc" => [77, "\x148"], "\xbd" => [18, "\x148"], "\xbe" => [77, "\x149"], "\xbf" => [18, "\x149"], "\xc0" => [77, "\x14="], "\xc1" => [18, "\x14="], "\xc2" => [77, "\x14A"], "\xc3" => [18, "\x14A"], "\xc4" => [77, "\x14_"], "\xc5" => [18, "\x14_"], "\xc6" => [77, "\x14b"], "\xc7" => [18, "\x14b"], "\xc8" => [77, "\x14d"], "\xc9" => [18, "\x14d"], "\xca" => [77, "\x14f"], "\xcb" => [18, "\x14f"], "\xcc" => [77, "\x14g"], "\xcd" => [18, "\x14g"], "\xce" => [77, "\x14h"], "\xcf" => [18, "\x14h"], "\xd0" => [77, "\x14l"], "\xd1" => [18, "\x14l"], "\xd2" => [77, "\x14m"], "\xd3" => [18, "\x14m"], "\xd4" => [77, "\x14n"], "\xd5" => [18, "\x14n"], "\xd6" => [77, "\x14p"], "\xd7" => [18, "\x14p"], "\xd8" => [77, "\x14r"], "\xd9" => [18, "\x14r"], "\xda" => [77, "\x14u"], "\xdb" => [18, "\x14u"], "\xdc" => [0, "\x14:"], "\xdd" => [0, "\x14B"], "\xde" => [0, "\x14C"], "\xdf" => [0, "\x14D"], "\xe0" => [0, "\x14E"], "\xe1" => [0, "\x14F"], "\xe2" => [0, "\x14G"], "\xe3" => [0, "\x14H"], "\xe4" => [0, "\x14I"], "\xe5" => [0, "\x14J"], "\xe6" => [0, "\x14K"], "\xe7" => [0, "\x14L"], "\xe8" => [0, "\x14M"], "\xe9" => [0, "\x14N"], "\xea" => [0, "\x14O"], "\xeb" => [0, "\x14P"], "\xec" => [0, "\x14Q"], "\xed" => [0, "\x14R"], "\xee" => [0, "\x14S"], "\xef" => [0, "\x14T"], "\xf0" => [0, "\x14U"], "\xf1" => [0, "\x14V"], "\xf2" => [0, "\x14W"], "\xf3" => [0, "\x14Y"], "\xf4" => [0, "\x14j"], "\xf5" => [0, "\x14k"], "\xf6" => [0, "\x14q"], "\xf7" => [0, "\x14v"], "\xf8" => [0, "\x14w"], "\xf9" => [0, "\x14x"], "\xfa" => [0, "\x14y"], "\xfb" => [0, "\x14z"], "\xfc" => [82, "\x14"], "\xfd" => [87, "\x14"], "\xfe" => [130, "\x14"], "\xff" => [9, "\x14"]], ["\x00" => [77, "\x130"], "\x01" => [18, "\x130"], "\x02" => [77, "\x131"], "\x03" => [18, "\x131"], "\x04" => [77, "\x132"], "\x05" => [18, "\x132"], "\x06" => [77, "\x13a"], "\x07" => [18, "\x13a"], "\x08" => [77, "\x13c"], "\t" => [18, "\x13c"], "\n" => [77, "\x13e"], "\v" => [18, "\x13e"], "\f" => [77, "\x13i"], "\r" => [18, "\x13i"], "\x0e" => [77, "\x13o"], "\x0f" => [18, "\x13o"], "\x10" => [77, "\x13s"], "\x11" => [18, "\x13s"], "\x12" => [77, "\x13t"], "\x13" => [18, "\x13t"], "\x14" => [0, "\x13 "], "\x15" => [0, "\x13%"], "\x16" => [0, "\x13-"], "\x17" => [0, "\x13."], "\x18" => [0, "\x13/"], "\x19" => [0, "\x133"], "\x1a" => [0, "\x134"], "\x1b" => [0, "\x135"], "\x1c" => [0, "\x136"], "\x1d" => [0, "\x137"], "\x1e" => [0, "\x138"], "\x1f" => [0, "\x139"], " " => [0, "\x13="], "!" => [0, "\x13A"], "\"" => [0, "\x13_"], "#" => [0, "\x13b"], "\$" => [0, "\x13d"], "%" => [0, "\x13f"], "&" => [0, "\x13g"], "'" => [0, "\x13h"], "(" => [0, "\x13l"], ")" => [0, "\x13m"], "*" => [0, "\x13n"], "+" => [0, "\x13p"], "," => [0, "\x13r"], "-" => [0, "\x13u"], "." => [100, "\x13"], "/" => [110, "\x13"], [111, "\x13"], [115, "\x13"], [116, "\x13"], [118, "\x13"], [119, "\x13"], [122, "\x13"], [123, "\x13"], [125, "\x13"], [126, "\x13"], [129, "\x13"], ":" => [143, "\x13"], ";" => [148, "\x13"], "<" => [151, "\x13"], "=" => [153, "\x13"], ">" => [83, "\x13"], "?" => [10, "\x13"], "@" => [77, "\x140"], "A" => [18, "\x140"], "B" => [77, "\x141"], "C" => [18, "\x141"], "D" => [77, "\x142"], "E" => [18, "\x142"], "F" => [77, "\x14a"], "G" => [18, "\x14a"], "H" => [77, "\x14c"], "I" => [18, "\x14c"], "J" => [77, "\x14e"], "K" => [18, "\x14e"], "L" => [77, "\x14i"], "M" => [18, "\x14i"], "N" => [77, "\x14o"], "O" => [18, "\x14o"], "P" => [77, "\x14s"], "Q" => [18, "\x14s"], "R" => [77, "\x14t"], "S" => [18, "\x14t"], "T" => [0, "\x14 "], "U" => [0, "\x14%"], "V" => [0, "\x14-"], "W" => [0, "\x14."], "X" => [0, "\x14/"], "Y" => [0, "\x143"], "Z" => [0, "\x144"], "[" => [0, "\x145"], "\\" => [0, "\x146"], "]" => [0, "\x147"], "^" => [0, "\x148"], "_" => [0, "\x149"], "`" => [0, "\x14="], "a" => [0, "\x14A"], "b" => [0, "\x14_"], "c" => [0, "\x14b"], "d" => [0, "\x14d"], "e" => [0, "\x14f"], "f" => [0, "\x14g"], "g" => [0, "\x14h"], "h" => [0, "\x14l"], "i" => [0, "\x14m"], "j" => [0, "\x14n"], "k" => [0, "\x14p"], "l" => [0, "\x14r"], "m" => [0, "\x14u"], "n" => [100, "\x14"], "o" => [110, "\x14"], "p" => [111, "\x14"], "q" => [115, "\x14"], "r" => [116, "\x14"], "s" => [118, "\x14"], "t" => [119, "\x14"], "u" => [122, "\x14"], "v" => [123, "\x14"], "w" => [125, "\x14"], "x" => [126, "\x14"], "y" => [129, "\x14"], "z" => [143, "\x14"], "{" => [148, "\x14"], "|" => [151, "\x14"], "}" => [153, "\x14"], "~" => [83, "\x14"], "" => [10, "\x14"], "\x80" => [77, "\x150"], "\x81" => [18, "\x150"], "\x82" => [77, "\x151"], "\x83" => [18, "\x151"], "\x84" => [77, "\x152"], "\x85" => [18, "\x152"], "\x86" => [77, "\x15a"], "\x87" => [18, "\x15a"], "\x88" => [77, "\x15c"], "\x89" => [18, "\x15c"], "\x8a" => [77, "\x15e"], "\x8b" => [18, "\x15e"], "\x8c" => [77, "\x15i"], "\x8d" => [18, "\x15i"], "\x8e" => [77, "\x15o"], "\x8f" => [18, "\x15o"], "\x90" => [77, "\x15s"], "\x91" => [18, "\x15s"], "\x92" => [77, "\x15t"], "\x93" => [18, "\x15t"], "\x94" => [0, "\x15 "], "\x95" => [0, "\x15%"], "\x96" => [0, "\x15-"], "\x97" => [0, "\x15."], "\x98" => [0, "\x15/"], "\x99" => [0, "\x153"], "\x9a" => [0, "\x154"], "\x9b" => [0, "\x155"], "\x9c" => [0, "\x156"], "\x9d" => [0, "\x157"], "\x9e" => [0, "\x158"], "\x9f" => [0, "\x159"], "\xa0" => [0, "\x15="], "\xa1" => [0, "\x15A"], "\xa2" => [0, "\x15_"], "\xa3" => [0, "\x15b"], "\xa4" => [0, "\x15d"], "\xa5" => [0, "\x15f"], "\xa6" => [0, "\x15g"], "\xa7" => [0, "\x15h"], "\xa8" => [0, "\x15l"], "\xa9" => [0, "\x15m"], "\xaa" => [0, "\x15n"], "\xab" => [0, "\x15p"], "\xac" => [0, "\x15r"], "\xad" => [0, "\x15u"], "\xae" => [100, "\x15"], "\xaf" => [110, "\x15"], "\xb0" => [111, "\x15"], "\xb1" => [115, "\x15"], "\xb2" => [116, "\x15"], "\xb3" => [118, "\x15"], "\xb4" => [119, "\x15"], "\xb5" => [122, "\x15"], "\xb6" => [123, "\x15"], "\xb7" => [125, "\x15"], "\xb8" => [126, "\x15"], "\xb9" => [129, "\x15"], "\xba" => [143, "\x15"], "\xbb" => [148, "\x15"], "\xbc" => [151, "\x15"], "\xbd" => [153, "\x15"], "\xbe" => [83, "\x15"], "\xbf" => [10, "\x15"], "\xc0" => [77, "\x170"], "\xc1" => [18, "\x170"], "\xc2" => [77, "\x171"], "\xc3" => [18, "\x171"], "\xc4" => [77, "\x172"], "\xc5" => [18, "\x172"], "\xc6" => [77, "\x17a"], "\xc7" => [18, "\x17a"], "\xc8" => [77, "\x17c"], "\xc9" => [18, "\x17c"], "\xca" => [77, "\x17e"], "\xcb" => [18, "\x17e"], "\xcc" => [77, "\x17i"], "\xcd" => [18, "\x17i"], "\xce" => [77, "\x17o"], "\xcf" => [18, "\x17o"], "\xd0" => [77, "\x17s"], "\xd1" => [18, "\x17s"], "\xd2" => [77, "\x17t"], "\xd3" => [18, "\x17t"], "\xd4" => [0, "\x17 "], "\xd5" => [0, "\x17%"], "\xd6" => [0, "\x17-"], "\xd7" => [0, "\x17."], "\xd8" => [0, "\x17/"], "\xd9" => [0, "\x173"], "\xda" => [0, "\x174"], "\xdb" => [0, "\x175"], "\xdc" => [0, "\x176"], "\xdd" => [0, "\x177"], "\xde" => [0, "\x178"], "\xdf" => [0, "\x179"], "\xe0" => [0, "\x17="], "\xe1" => [0, "\x17A"], "\xe2" => [0, "\x17_"], "\xe3" => [0, "\x17b"], "\xe4" => [0, "\x17d"], "\xe5" => [0, "\x17f"], "\xe6" => [0, "\x17g"], "\xe7" => [0, "\x17h"], "\xe8" => [0, "\x17l"], "\xe9" => [0, "\x17m"], "\xea" => [0, "\x17n"], "\xeb" => [0, "\x17p"], "\xec" => [0, "\x17r"], "\xed" => [0, "\x17u"], "\xee" => [100, "\x17"], "\xef" => [110, "\x17"], "\xf0" => [111, "\x17"], "\xf1" => [115, "\x17"], "\xf2" => [116, "\x17"], "\xf3" => [118, "\x17"], "\xf4" => [119, "\x17"], "\xf5" => [122, "\x17"], "\xf6" => [123, "\x17"], "\xf7" => [125, "\x17"], "\xf8" => [126, "\x17"], "\xf9" => [129, "\x17"], "\xfa" => [143, "\x17"], "\xfb" => [148, "\x17"], "\xfc" => [151, "\x17"], "\xfd" => [153, "\x17"], "\xfe" => [83, "\x17"], "\xff" => [10, "\x17"]], ["\x00" => [0, "\x130"], "\x01" => [0, "\x131"], "\x02" => [0, "\x132"], "\x03" => [0, "\x13a"], "\x04" => [0, "\x13c"], "\x05" => [0, "\x13e"], "\x06" => [0, "\x13i"], "\x07" => [0, "\x13o"], "\x08" => [0, "\x13s"], "\t" => [0, "\x13t"], "\n" => [73, "\x13"], "\v" => [88, "\x13"], "\f" => [89, "\x13"], "\r" => [96, "\x13"], "\x0e" => [97, "\x13"], "\x0f" => [99, "\x13"], "\x10" => [106, "\x13"], "\x11" => [136, "\x13"], "\x12" => [139, "\x13"], "\x13" => [141, "\x13"], "\x14" => [145, "\x13"], "\x15" => [147, "\x13"], "\x16" => [149, "\x13"], "\x17" => [101, "\x13"], "\x18" => [112, "\x13"], "\x19" => [117, "\x13"], "\x1a" => [120, "\x13"], "\x1b" => [124, "\x13"], "\x1c" => [127, "\x13"], "\x1d" => [144, "\x13"], "\x1e" => [152, "\x13"], "\x1f" => [11, "\x13"], " " => [0, "\x140"], "!" => [0, "\x141"], "\"" => [0, "\x142"], "#" => [0, "\x14a"], "\$" => [0, "\x14c"], "%" => [0, "\x14e"], "&" => [0, "\x14i"], "'" => [0, "\x14o"], "(" => [0, "\x14s"], ")" => [0, "\x14t"], "*" => [73, "\x14"], "+" => [88, "\x14"], "," => [89, "\x14"], "-" => [96, "\x14"], "." => [97, "\x14"], "/" => [99, "\x14"], [106, "\x14"], [136, "\x14"], [139, "\x14"], [141, "\x14"], [145, "\x14"], [147, "\x14"], [149, "\x14"], [101, "\x14"], [112, "\x14"], [117, "\x14"], ":" => [120, "\x14"], ";" => [124, "\x14"], "<" => [127, "\x14"], "=" => [144, "\x14"], ">" => [152, "\x14"], "?" => [11, "\x14"], "@" => [0, "\x150"], "A" => [0, "\x151"], "B" => [0, "\x152"], "C" => [0, "\x15a"], "D" => [0, "\x15c"], "E" => [0, "\x15e"], "F" => [0, "\x15i"], "G" => [0, "\x15o"], "H" => [0, "\x15s"], "I" => [0, "\x15t"], "J" => [73, "\x15"], "K" => [88, "\x15"], "L" => [89, "\x15"], "M" => [96, "\x15"], "N" => [97, "\x15"], "O" => [99, "\x15"], "P" => [106, "\x15"], "Q" => [136, "\x15"], "R" => [139, "\x15"], "S" => [141, "\x15"], "T" => [145, "\x15"], "U" => [147, "\x15"], "V" => [149, "\x15"], "W" => [101, "\x15"], "X" => [112, "\x15"], "Y" => [117, "\x15"], "Z" => [120, "\x15"], "[" => [124, "\x15"], "\\" => [127, "\x15"], "]" => [144, "\x15"], "^" => [152, "\x15"], "_" => [11, "\x15"], "`" => [0, "\x170"], "a" => [0, "\x171"], "b" => [0, "\x172"], "c" => [0, "\x17a"], "d" => [0, "\x17c"], "e" => [0, "\x17e"], "f" => [0, "\x17i"], "g" => [0, "\x17o"], "h" => [0, "\x17s"], "i" => [0, "\x17t"], "j" => [73, "\x17"], "k" => [88, "\x17"], "l" => [89, "\x17"], "m" => [96, "\x17"], "n" => [97, "\x17"], "o" => [99, "\x17"], "p" => [106, "\x17"], "q" => [136, "\x17"], "r" => [139, "\x17"], "s" => [141, "\x17"], "t" => [145, "\x17"], "u" => [147, "\x17"], "v" => [149, "\x17"], "w" => [101, "\x17"], "x" => [112, "\x17"], "y" => [117, "\x17"], "z" => [120, "\x17"], "{" => [124, "\x17"], "|" => [127, "\x17"], "}" => [144, "\x17"], "~" => [152, "\x17"], "" => [11, "\x17"], "\x80" => [0, "\x180"], "\x81" => [0, "\x181"], "\x82" => [0, "\x182"], "\x83" => [0, "\x18a"], "\x84" => [0, "\x18c"], "\x85" => [0, "\x18e"], "\x86" => [0, "\x18i"], "\x87" => [0, "\x18o"], "\x88" => [0, "\x18s"], "\x89" => [0, "\x18t"], "\x8a" => [73, "\x18"], "\x8b" => [88, "\x18"], "\x8c" => [89, "\x18"], "\x8d" => [96, "\x18"], "\x8e" => [97, "\x18"], "\x8f" => [99, "\x18"], "\x90" => [106, "\x18"], "\x91" => [136, "\x18"], "\x92" => [139, "\x18"], "\x93" => [141, "\x18"], "\x94" => [145, "\x18"], "\x95" => [147, "\x18"], "\x96" => [149, "\x18"], "\x97" => [101, "\x18"], "\x98" => [112, "\x18"], "\x99" => [117, "\x18"], "\x9a" => [120, "\x18"], "\x9b" => [124, "\x18"], "\x9c" => [127, "\x18"], "\x9d" => [144, "\x18"], "\x9e" => [152, "\x18"], "\x9f" => [11, "\x18"], "\xa0" => [0, "\x190"], "\xa1" => [0, "\x191"], "\xa2" => [0, "\x192"], "\xa3" => [0, "\x19a"], "\xa4" => [0, "\x19c"], "\xa5" => [0, "\x19e"], "\xa6" => [0, "\x19i"], "\xa7" => [0, "\x19o"], "\xa8" => [0, "\x19s"], "\xa9" => [0, "\x19t"], "\xaa" => [73, "\x19"], "\xab" => [88, "\x19"], "\xac" => [89, "\x19"], "\xad" => [96, "\x19"], "\xae" => [97, "\x19"], "\xaf" => [99, "\x19"], "\xb0" => [106, "\x19"], "\xb1" => [136, "\x19"], "\xb2" => [139, "\x19"], "\xb3" => [141, "\x19"], "\xb4" => [145, "\x19"], "\xb5" => [147, "\x19"], "\xb6" => [149, "\x19"], "\xb7" => [101, "\x19"], "\xb8" => [112, "\x19"], "\xb9" => [117, "\x19"], "\xba" => [120, "\x19"], "\xbb" => [124, "\x19"], "\xbc" => [127, "\x19"], "\xbd" => [144, "\x19"], "\xbe" => [152, "\x19"], "\xbf" => [11, "\x19"], "\xc0" => [0, "\x1a0"], "\xc1" => [0, "\x1a1"], "\xc2" => [0, "\x1a2"], "\xc3" => [0, "\x1aa"], "\xc4" => [0, "\x1ac"], "\xc5" => [0, "\x1ae"], "\xc6" => [0, "\x1ai"], "\xc7" => [0, "\x1ao"], "\xc8" => [0, "\x1as"], "\xc9" => [0, "\x1at"], "\xca" => [73, "\x1a"], "\xcb" => [88, "\x1a"], "\xcc" => [89, "\x1a"], "\xcd" => [96, "\x1a"], "\xce" => [97, "\x1a"], "\xcf" => [99, "\x1a"], "\xd0" => [106, "\x1a"], "\xd1" => [136, "\x1a"], "\xd2" => [139, "\x1a"], "\xd3" => [141, "\x1a"], "\xd4" => [145, "\x1a"], "\xd5" => [147, "\x1a"], "\xd6" => [149, "\x1a"], "\xd7" => [101, "\x1a"], "\xd8" => [112, "\x1a"], "\xd9" => [117, "\x1a"], "\xda" => [120, "\x1a"], "\xdb" => [124, "\x1a"], "\xdc" => [127, "\x1a"], "\xdd" => [144, "\x1a"], "\xde" => [152, "\x1a"], "\xdf" => [11, "\x1a"], "\xe0" => [0, "\x1b0"], "\xe1" => [0, "\x1b1"], "\xe2" => [0, "\x1b2"], "\xe3" => [0, "\x1ba"], "\xe4" => [0, "\x1bc"], "\xe5" => [0, "\x1be"], "\xe6" => [0, "\x1bi"], "\xe7" => [0, "\x1bo"], "\xe8" => [0, "\x1bs"], "\xe9" => [0, "\x1bt"], "\xea" => [73, "\x1b"], "\xeb" => [88, "\x1b"], "\xec" => [89, "\x1b"], "\xed" => [96, "\x1b"], "\xee" => [97, "\x1b"], "\xef" => [99, "\x1b"], "\xf0" => [106, "\x1b"], "\xf1" => [136, "\x1b"], "\xf2" => [139, "\x1b"], "\xf3" => [141, "\x1b"], "\xf4" => [145, "\x1b"], "\xf5" => [147, "\x1b"], "\xf6" => [149, "\x1b"], "\xf7" => [101, "\x1b"], "\xf8" => [112, "\x1b"], "\xf9" => [117, "\x1b"], "\xfa" => [120, "\x1b"], "\xfb" => [124, "\x1b"], "\xfc" => [127, "\x1b"], "\xfd" => [144, "\x1b"], "\xfe" => [152, "\x1b"], "\xff" => [11, "\x1b"]], ["\x00" => [94, "\x150"], "\x01" => [76, "\x150"], "\x02" => [104, "\x150"], "\x03" => [16, "\x150"], "\x04" => [94, "\x151"], "\x05" => [76, "\x151"], "\x06" => [104, "\x151"], "\x07" => [16, "\x151"], "\x08" => [94, "\x152"], "\t" => [76, "\x152"], "\n" => [104, "\x152"], "\v" => [16, "\x152"], "\f" => [94, "\x15a"], "\r" => [76, "\x15a"], "\x0e" => [104, "\x15a"], "\x0f" => [16, "\x15a"], "\x10" => [94, "\x15c"], "\x11" => [76, "\x15c"], "\x12" => [104, "\x15c"], "\x13" => [16, "\x15c"], "\x14" => [94, "\x15e"], "\x15" => [76, "\x15e"], "\x16" => [104, "\x15e"], "\x17" => [16, "\x15e"], "\x18" => [94, "\x15i"], "\x19" => [76, "\x15i"], "\x1a" => [104, "\x15i"], "\x1b" => [16, "\x15i"], "\x1c" => [94, "\x15o"], "\x1d" => [76, "\x15o"], "\x1e" => [104, "\x15o"], "\x1f" => [16, "\x15o"], " " => [94, "\x15s"], "!" => [76, "\x15s"], "\"" => [104, "\x15s"], "#" => [16, "\x15s"], "\$" => [94, "\x15t"], "%" => [76, "\x15t"], "&" => [104, "\x15t"], "'" => [16, "\x15t"], "(" => [77, "\x15 "], ")" => [18, "\x15 "], "*" => [77, "\x15%"], "+" => [18, "\x15%"], "," => [77, "\x15-"], "-" => [18, "\x15-"], "." => [77, "\x15."], "/" => [18, "\x15."], [77, "\x15/"], [18, "\x15/"], [77, "\x153"], [18, "\x153"], [77, "\x154"], [18, "\x154"], [77, "\x155"], [18, "\x155"], [77, "\x156"], [18, "\x156"], ":" => [77, "\x157"], ";" => [18, "\x157"], "<" => [77, "\x158"], "=" => [18, "\x158"], ">" => [77, "\x159"], "?" => [18, "\x159"], "@" => [77, "\x15="], "A" => [18, "\x15="], "B" => [77, "\x15A"], "C" => [18, "\x15A"], "D" => [77, "\x15_"], "E" => [18, "\x15_"], "F" => [77, "\x15b"], "G" => [18, "\x15b"], "H" => [77, "\x15d"], "I" => [18, "\x15d"], "J" => [77, "\x15f"], "K" => [18, "\x15f"], "L" => [77, "\x15g"], "M" => [18, "\x15g"], "N" => [77, "\x15h"], "O" => [18, "\x15h"], "P" => [77, "\x15l"], "Q" => [18, "\x15l"], "R" => [77, "\x15m"], "S" => [18, "\x15m"], "T" => [77, "\x15n"], "U" => [18, "\x15n"], "V" => [77, "\x15p"], "W" => [18, "\x15p"], "X" => [77, "\x15r"], "Y" => [18, "\x15r"], "Z" => [77, "\x15u"], "[" => [18, "\x15u"], "\\" => [0, "\x15:"], "]" => [0, "\x15B"], "^" => [0, "\x15C"], "_" => [0, "\x15D"], "`" => [0, "\x15E"], "a" => [0, "\x15F"], "b" => [0, "\x15G"], "c" => [0, "\x15H"], "d" => [0, "\x15I"], "e" => [0, "\x15J"], "f" => [0, "\x15K"], "g" => [0, "\x15L"], "h" => [0, "\x15M"], "i" => [0, "\x15N"], "j" => [0, "\x15O"], "k" => [0, "\x15P"], "l" => [0, "\x15Q"], "m" => [0, "\x15R"], "n" => [0, "\x15S"], "o" => [0, "\x15T"], "p" => [0, "\x15U"], "q" => [0, "\x15V"], "r" => [0, "\x15W"], "s" => [0, "\x15Y"], "t" => [0, "\x15j"], "u" => [0, "\x15k"], "v" => [0, "\x15q"], "w" => [0, "\x15v"], "x" => [0, "\x15w"], "y" => [0, "\x15x"], "z" => [0, "\x15y"], "{" => [0, "\x15z"], "|" => [82, "\x15"], "}" => [87, "\x15"], "~" => [130, "\x15"], "" => [9, "\x15"], "\x80" => [94, "\x170"], "\x81" => [76, "\x170"], "\x82" => [104, "\x170"], "\x83" => [16, "\x170"], "\x84" => [94, "\x171"], "\x85" => [76, "\x171"], "\x86" => [104, "\x171"], "\x87" => [16, "\x171"], "\x88" => [94, "\x172"], "\x89" => [76, "\x172"], "\x8a" => [104, "\x172"], "\x8b" => [16, "\x172"], "\x8c" => [94, "\x17a"], "\x8d" => [76, "\x17a"], "\x8e" => [104, "\x17a"], "\x8f" => [16, "\x17a"], "\x90" => [94, "\x17c"], "\x91" => [76, "\x17c"], "\x92" => [104, "\x17c"], "\x93" => [16, "\x17c"], "\x94" => [94, "\x17e"], "\x95" => [76, "\x17e"], "\x96" => [104, "\x17e"], "\x97" => [16, "\x17e"], "\x98" => [94, "\x17i"], "\x99" => [76, "\x17i"], "\x9a" => [104, "\x17i"], "\x9b" => [16, "\x17i"], "\x9c" => [94, "\x17o"], "\x9d" => [76, "\x17o"], "\x9e" => [104, "\x17o"], "\x9f" => [16, "\x17o"], "\xa0" => [94, "\x17s"], "\xa1" => [76, "\x17s"], "\xa2" => [104, "\x17s"], "\xa3" => [16, "\x17s"], "\xa4" => [94, "\x17t"], "\xa5" => [76, "\x17t"], "\xa6" => [104, "\x17t"], "\xa7" => [16, "\x17t"], "\xa8" => [77, "\x17 "], "\xa9" => [18, "\x17 "], "\xaa" => [77, "\x17%"], "\xab" => [18, "\x17%"], "\xac" => [77, "\x17-"], "\xad" => [18, "\x17-"], "\xae" => [77, "\x17."], "\xaf" => [18, "\x17."], "\xb0" => [77, "\x17/"], "\xb1" => [18, "\x17/"], "\xb2" => [77, "\x173"], "\xb3" => [18, "\x173"], "\xb4" => [77, "\x174"], "\xb5" => [18, "\x174"], "\xb6" => [77, "\x175"], "\xb7" => [18, "\x175"], "\xb8" => [77, "\x176"], "\xb9" => [18, "\x176"], "\xba" => [77, "\x177"], "\xbb" => [18, "\x177"], "\xbc" => [77, "\x178"], "\xbd" => [18, "\x178"], "\xbe" => [77, "\x179"], "\xbf" => [18, "\x179"], "\xc0" => [77, "\x17="], "\xc1" => [18, "\x17="], "\xc2" => [77, "\x17A"], "\xc3" => [18, "\x17A"], "\xc4" => [77, "\x17_"], "\xc5" => [18, "\x17_"], "\xc6" => [77, "\x17b"], "\xc7" => [18, "\x17b"], "\xc8" => [77, "\x17d"], "\xc9" => [18, "\x17d"], "\xca" => [77, "\x17f"], "\xcb" => [18, "\x17f"], "\xcc" => [77, "\x17g"], "\xcd" => [18, "\x17g"], "\xce" => [77, "\x17h"], "\xcf" => [18, "\x17h"], "\xd0" => [77, "\x17l"], "\xd1" => [18, "\x17l"], "\xd2" => [77, "\x17m"], "\xd3" => [18, "\x17m"], "\xd4" => [77, "\x17n"], "\xd5" => [18, "\x17n"], "\xd6" => [77, "\x17p"], "\xd7" => [18, "\x17p"], "\xd8" => [77, "\x17r"], "\xd9" => [18, "\x17r"], "\xda" => [77, "\x17u"], "\xdb" => [18, "\x17u"], "\xdc" => [0, "\x17:"], "\xdd" => [0, "\x17B"], "\xde" => [0, "\x17C"], "\xdf" => [0, "\x17D"], "\xe0" => [0, "\x17E"], "\xe1" => [0, "\x17F"], "\xe2" => [0, "\x17G"], "\xe3" => [0, "\x17H"], "\xe4" => [0, "\x17I"], "\xe5" => [0, "\x17J"], "\xe6" => [0, "\x17K"], "\xe7" => [0, "\x17L"], "\xe8" => [0, "\x17M"], "\xe9" => [0, "\x17N"], "\xea" => [0, "\x17O"], "\xeb" => [0, "\x17P"], "\xec" => [0, "\x17Q"], "\xed" => [0, "\x17R"], "\xee" => [0, "\x17S"], "\xef" => [0, "\x17T"], "\xf0" => [0, "\x17U"], "\xf1" => [0, "\x17V"], "\xf2" => [0, "\x17W"], "\xf3" => [0, "\x17Y"], "\xf4" => [0, "\x17j"], "\xf5" => [0, "\x17k"], "\xf6" => [0, "\x17q"], "\xf7" => [0, "\x17v"], "\xf8" => [0, "\x17w"], "\xf9" => [0, "\x17x"], "\xfa" => [0, "\x17y"], "\xfb" => [0, "\x17z"], "\xfc" => [82, "\x17"], "\xfd" => [87, "\x17"], "\xfe" => [130, "\x17"], "\xff" => [9, "\x17"]], ["\x00" => [94, "\x160"], "\x01" => [76, "\x160"], "\x02" => [104, "\x160"], "\x03" => [16, "\x160"], "\x04" => [94, "\x161"], "\x05" => [76, "\x161"], "\x06" => [104, "\x161"], "\x07" => [16, "\x161"], "\x08" => [94, "\x162"], "\t" => [76, "\x162"], "\n" => [104, "\x162"], "\v" => [16, "\x162"], "\f" => [94, "\x16a"], "\r" => [76, "\x16a"], "\x0e" => [104, "\x16a"], "\x0f" => [16, "\x16a"], "\x10" => [94, "\x16c"], "\x11" => [76, "\x16c"], "\x12" => [104, "\x16c"], "\x13" => [16, "\x16c"], "\x14" => [94, "\x16e"], "\x15" => [76, "\x16e"], "\x16" => [104, "\x16e"], "\x17" => [16, "\x16e"], "\x18" => [94, "\x16i"], "\x19" => [76, "\x16i"], "\x1a" => [104, "\x16i"], "\x1b" => [16, "\x16i"], "\x1c" => [94, "\x16o"], "\x1d" => [76, "\x16o"], "\x1e" => [104, "\x16o"], "\x1f" => [16, "\x16o"], " " => [94, "\x16s"], "!" => [76, "\x16s"], "\"" => [104, "\x16s"], "#" => [16, "\x16s"], "\$" => [94, "\x16t"], "%" => [76, "\x16t"], "&" => [104, "\x16t"], "'" => [16, "\x16t"], "(" => [77, "\x16 "], ")" => [18, "\x16 "], "*" => [77, "\x16%"], "+" => [18, "\x16%"], "," => [77, "\x16-"], "-" => [18, "\x16-"], "." => [77, "\x16."], "/" => [18, "\x16."], [77, "\x16/"], [18, "\x16/"], [77, "\x163"], [18, "\x163"], [77, "\x164"], [18, "\x164"], [77, "\x165"], [18, "\x165"], [77, "\x166"], [18, "\x166"], ":" => [77, "\x167"], ";" => [18, "\x167"], "<" => [77, "\x168"], "=" => [18, "\x168"], ">" => [77, "\x169"], "?" => [18, "\x169"], "@" => [77, "\x16="], "A" => [18, "\x16="], "B" => [77, "\x16A"], "C" => [18, "\x16A"], "D" => [77, "\x16_"], "E" => [18, "\x16_"], "F" => [77, "\x16b"], "G" => [18, "\x16b"], "H" => [77, "\x16d"], "I" => [18, "\x16d"], "J" => [77, "\x16f"], "K" => [18, "\x16f"], "L" => [77, "\x16g"], "M" => [18, "\x16g"], "N" => [77, "\x16h"], "O" => [18, "\x16h"], "P" => [77, "\x16l"], "Q" => [18, "\x16l"], "R" => [77, "\x16m"], "S" => [18, "\x16m"], "T" => [77, "\x16n"], "U" => [18, "\x16n"], "V" => [77, "\x16p"], "W" => [18, "\x16p"], "X" => [77, "\x16r"], "Y" => [18, "\x16r"], "Z" => [77, "\x16u"], "[" => [18, "\x16u"], "\\" => [0, "\x16:"], "]" => [0, "\x16B"], "^" => [0, "\x16C"], "_" => [0, "\x16D"], "`" => [0, "\x16E"], "a" => [0, "\x16F"], "b" => [0, "\x16G"], "c" => [0, "\x16H"], "d" => [0, "\x16I"], "e" => [0, "\x16J"], "f" => [0, "\x16K"], "g" => [0, "\x16L"], "h" => [0, "\x16M"], "i" => [0, "\x16N"], "j" => [0, "\x16O"], "k" => [0, "\x16P"], "l" => [0, "\x16Q"], "m" => [0, "\x16R"], "n" => [0, "\x16S"], "o" => [0, "\x16T"], "p" => [0, "\x16U"], "q" => [0, "\x16V"], "r" => [0, "\x16W"], "s" => [0, "\x16Y"], "t" => [0, "\x16j"], "u" => [0, "\x16k"], "v" => [0, "\x16q"], "w" => [0, "\x16v"], "x" => [0, "\x16w"], "y" => [0, "\x16x"], "z" => [0, "\x16y"], "{" => [0, "\x16z"], "|" => [82, "\x16"], "}" => [87, "\x16"], "~" => [130, "\x16"], "" => [9, "\x16"], "\x80" => [94, ""], "\x81" => [76, ""], "\x82" => [104, ""], "\x83" => [16, ""], "\x84" => [94, ""], "\x85" => [76, ""], "\x86" => [104, ""], "\x87" => [16, ""], "\x88" => [94, ""], "\x89" => [76, ""], "\x8a" => [104, ""], "\x8b" => [16, ""], "\x8c" => [94, ""], "\x8d" => [76, ""], "\x8e" => [104, ""], "\x8f" => [16, ""], "\x90" => [94, ""], "\x91" => [76, ""], "\x92" => [104, ""], "\x93" => [16, ""], "\x94" => [94, ""], "\x95" => [76, ""], "\x96" => [104, ""], "\x97" => [16, ""], "\x98" => [94, ""], "\x99" => [76, ""], "\x9a" => [104, ""], "\x9b" => [16, ""], "\x9c" => [94, ""], "\x9d" => [76, ""], "\x9e" => [104, ""], "\x9f" => [16, ""], "\xa0" => [94, ""], "\xa1" => [76, ""], "\xa2" => [104, ""], "\xa3" => [16, ""], "\xa4" => [94, ""], "\xa5" => [76, ""], "\xa6" => [104, ""], "\xa7" => [16, ""], "\xa8" => [77, ""], "\xa9" => [18, ""], "\xaa" => [77, ""], "\xab" => [18, ""], "\xac" => [77, ""], "\xad" => [18, ""], "\xae" => [77, ""], "\xaf" => [18, ""], "\xb0" => [77, ""], "\xb1" => [18, ""], "\xb2" => [77, ""], "\xb3" => [18, ""], "\xb4" => [77, ""], "\xb5" => [18, ""], "\xb6" => [77, ""], "\xb7" => [18, ""], "\xb8" => [77, ""], "\xb9" => [18, ""], "\xba" => [77, ""], "\xbb" => [18, ""], "\xbc" => [77, ""], "\xbd" => [18, ""], "\xbe" => [77, ""], "\xbf" => [18, ""], "\xc0" => [77, ""], "\xc1" => [18, ""], "\xc2" => [77, ""], "\xc3" => [18, ""], "\xc4" => [77, ""], "\xc5" => [18, ""], "\xc6" => [77, ""], "\xc7" => [18, ""], "\xc8" => [77, ""], "\xc9" => [18, ""], "\xca" => [77, ""], "\xcb" => [18, ""], "\xcc" => [77, ""], "\xcd" => [18, ""], "\xce" => [77, ""], "\xcf" => [18, ""], "\xd0" => [77, ""], "\xd1" => [18, ""], "\xd2" => [77, ""], "\xd3" => [18, ""], "\xd4" => [77, ""], "\xd5" => [18, ""], "\xd6" => [77, ""], "\xd7" => [18, ""], "\xd8" => [77, ""], "\xd9" => [18, ""], "\xda" => [77, ""], "\xdb" => [18, ""], "\xdc" => [0, ""], "\xdd" => [0, ""], "\xde" => [0, ""], "\xdf" => [0, ""], "\xe0" => [0, ""], "\xe1" => [0, ""], "\xe2" => [0, ""], "\xe3" => [0, ""], "\xe4" => [0, ""], "\xe5" => [0, ""], "\xe6" => [0, ""], "\xe7" => [0, ""], "\xe8" => [0, ""], "\xe9" => [0, ""], "\xea" => [0, ""], "\xeb" => [0, ""], "\xec" => [0, ""], "\xed" => [0, ""], "\xee" => [0, ""], "\xef" => [0, ""], "\xf0" => [0, ""], "\xf1" => [0, ""], "\xf2" => [0, ""], "\xf3" => [0, ""], "\xf4" => [0, ""], "\xf5" => [0, ""], "\xf6" => [0, ""], "\xf7" => [0, ""], "\xf8" => [0, ""], "\xf9" => [0, ""], "\xfa" => [0, ""], "\xfb" => [0, ""], "\xfc" => [82, ""], "\xfd" => [87, ""], "\xfe" => [130, ""], "\xff" => [9, ""]], ["\x00" => [94, "\x180"], "\x01" => [76, "\x180"], "\x02" => [104, "\x180"], "\x03" => [16, "\x180"], "\x04" => [94, "\x181"], "\x05" => [76, "\x181"], "\x06" => [104, "\x181"], "\x07" => [16, "\x181"], "\x08" => [94, "\x182"], "\t" => [76, "\x182"], "\n" => [104, "\x182"], "\v" => [16, "\x182"], "\f" => [94, "\x18a"], "\r" => [76, "\x18a"], "\x0e" => [104, "\x18a"], "\x0f" => [16, "\x18a"], "\x10" => [94, "\x18c"], "\x11" => [76, "\x18c"], "\x12" => [104, "\x18c"], "\x13" => [16, "\x18c"], "\x14" => [94, "\x18e"], "\x15" => [76, "\x18e"], "\x16" => [104, "\x18e"], "\x17" => [16, "\x18e"], "\x18" => [94, "\x18i"], "\x19" => [76, "\x18i"], "\x1a" => [104, "\x18i"], "\x1b" => [16, "\x18i"], "\x1c" => [94, "\x18o"], "\x1d" => [76, "\x18o"], "\x1e" => [104, "\x18o"], "\x1f" => [16, "\x18o"], " " => [94, "\x18s"], "!" => [76, "\x18s"], "\"" => [104, "\x18s"], "#" => [16, "\x18s"], "\$" => [94, "\x18t"], "%" => [76, "\x18t"], "&" => [104, "\x18t"], "'" => [16, "\x18t"], "(" => [77, "\x18 "], ")" => [18, "\x18 "], "*" => [77, "\x18%"], "+" => [18, "\x18%"], "," => [77, "\x18-"], "-" => [18, "\x18-"], "." => [77, "\x18."], "/" => [18, "\x18."], [77, "\x18/"], [18, "\x18/"], [77, "\x183"], [18, "\x183"], [77, "\x184"], [18, "\x184"], [77, "\x185"], [18, "\x185"], [77, "\x186"], [18, "\x186"], ":" => [77, "\x187"], ";" => [18, "\x187"], "<" => [77, "\x188"], "=" => [18, "\x188"], ">" => [77, "\x189"], "?" => [18, "\x189"], "@" => [77, "\x18="], "A" => [18, "\x18="], "B" => [77, "\x18A"], "C" => [18, "\x18A"], "D" => [77, "\x18_"], "E" => [18, "\x18_"], "F" => [77, "\x18b"], "G" => [18, "\x18b"], "H" => [77, "\x18d"], "I" => [18, "\x18d"], "J" => [77, "\x18f"], "K" => [18, "\x18f"], "L" => [77, "\x18g"], "M" => [18, "\x18g"], "N" => [77, "\x18h"], "O" => [18, "\x18h"], "P" => [77, "\x18l"], "Q" => [18, "\x18l"], "R" => [77, "\x18m"], "S" => [18, "\x18m"], "T" => [77, "\x18n"], "U" => [18, "\x18n"], "V" => [77, "\x18p"], "W" => [18, "\x18p"], "X" => [77, "\x18r"], "Y" => [18, "\x18r"], "Z" => [77, "\x18u"], "[" => [18, "\x18u"], "\\" => [0, "\x18:"], "]" => [0, "\x18B"], "^" => [0, "\x18C"], "_" => [0, "\x18D"], "`" => [0, "\x18E"], "a" => [0, "\x18F"], "b" => [0, "\x18G"], "c" => [0, "\x18H"], "d" => [0, "\x18I"], "e" => [0, "\x18J"], "f" => [0, "\x18K"], "g" => [0, "\x18L"], "h" => [0, "\x18M"], "i" => [0, "\x18N"], "j" => [0, "\x18O"], "k" => [0, "\x18P"], "l" => [0, "\x18Q"], "m" => [0, "\x18R"], "n" => [0, "\x18S"], "o" => [0, "\x18T"], "p" => [0, "\x18U"], "q" => [0, "\x18V"], "r" => [0, "\x18W"], "s" => [0, "\x18Y"], "t" => [0, "\x18j"], "u" => [0, "\x18k"], "v" => [0, "\x18q"], "w" => [0, "\x18v"], "x" => [0, "\x18w"], "y" => [0, "\x18x"], "z" => [0, "\x18y"], "{" => [0, "\x18z"], "|" => [82, "\x18"], "}" => [87, "\x18"], "~" => [130, "\x18"], "" => [9, "\x18"], "\x80" => [94, "\x190"], "\x81" => [76, "\x190"], "\x82" => [104, "\x190"], "\x83" => [16, "\x190"], "\x84" => [94, "\x191"], "\x85" => [76, "\x191"], "\x86" => [104, "\x191"], "\x87" => [16, "\x191"], "\x88" => [94, "\x192"], "\x89" => [76, "\x192"], "\x8a" => [104, "\x192"], "\x8b" => [16, "\x192"], "\x8c" => [94, "\x19a"], "\x8d" => [76, "\x19a"], "\x8e" => [104, "\x19a"], "\x8f" => [16, "\x19a"], "\x90" => [94, "\x19c"], "\x91" => [76, "\x19c"], "\x92" => [104, "\x19c"], "\x93" => [16, "\x19c"], "\x94" => [94, "\x19e"], "\x95" => [76, "\x19e"], "\x96" => [104, "\x19e"], "\x97" => [16, "\x19e"], "\x98" => [94, "\x19i"], "\x99" => [76, "\x19i"], "\x9a" => [104, "\x19i"], "\x9b" => [16, "\x19i"], "\x9c" => [94, "\x19o"], "\x9d" => [76, "\x19o"], "\x9e" => [104, "\x19o"], "\x9f" => [16, "\x19o"], "\xa0" => [94, "\x19s"], "\xa1" => [76, "\x19s"], "\xa2" => [104, "\x19s"], "\xa3" => [16, "\x19s"], "\xa4" => [94, "\x19t"], "\xa5" => [76, "\x19t"], "\xa6" => [104, "\x19t"], "\xa7" => [16, "\x19t"], "\xa8" => [77, "\x19 "], "\xa9" => [18, "\x19 "], "\xaa" => [77, "\x19%"], "\xab" => [18, "\x19%"], "\xac" => [77, "\x19-"], "\xad" => [18, "\x19-"], "\xae" => [77, "\x19."], "\xaf" => [18, "\x19."], "\xb0" => [77, "\x19/"], "\xb1" => [18, "\x19/"], "\xb2" => [77, "\x193"], "\xb3" => [18, "\x193"], "\xb4" => [77, "\x194"], "\xb5" => [18, "\x194"], "\xb6" => [77, "\x195"], "\xb7" => [18, "\x195"], "\xb8" => [77, "\x196"], "\xb9" => [18, "\x196"], "\xba" => [77, "\x197"], "\xbb" => [18, "\x197"], "\xbc" => [77, "\x198"], "\xbd" => [18, "\x198"], "\xbe" => [77, "\x199"], "\xbf" => [18, "\x199"], "\xc0" => [77, "\x19="], "\xc1" => [18, "\x19="], "\xc2" => [77, "\x19A"], "\xc3" => [18, "\x19A"], "\xc4" => [77, "\x19_"], "\xc5" => [18, "\x19_"], "\xc6" => [77, "\x19b"], "\xc7" => [18, "\x19b"], "\xc8" => [77, "\x19d"], "\xc9" => [18, "\x19d"], "\xca" => [77, "\x19f"], "\xcb" => [18, "\x19f"], "\xcc" => [77, "\x19g"], "\xcd" => [18, "\x19g"], "\xce" => [77, "\x19h"], "\xcf" => [18, "\x19h"], "\xd0" => [77, "\x19l"], "\xd1" => [18, "\x19l"], "\xd2" => [77, "\x19m"], "\xd3" => [18, "\x19m"], "\xd4" => [77, "\x19n"], "\xd5" => [18, "\x19n"], "\xd6" => [77, "\x19p"], "\xd7" => [18, "\x19p"], "\xd8" => [77, "\x19r"], "\xd9" => [18, "\x19r"], "\xda" => [77, "\x19u"], "\xdb" => [18, "\x19u"], "\xdc" => [0, "\x19:"], "\xdd" => [0, "\x19B"], "\xde" => [0, "\x19C"], "\xdf" => [0, "\x19D"], "\xe0" => [0, "\x19E"], "\xe1" => [0, "\x19F"], "\xe2" => [0, "\x19G"], "\xe3" => [0, "\x19H"], "\xe4" => [0, "\x19I"], "\xe5" => [0, "\x19J"], "\xe6" => [0, "\x19K"], "\xe7" => [0, "\x19L"], "\xe8" => [0, "\x19M"], "\xe9" => [0, "\x19N"], "\xea" => [0, "\x19O"], "\xeb" => [0, "\x19P"], "\xec" => [0, "\x19Q"], "\xed" => [0, "\x19R"], "\xee" => [0, "\x19S"], "\xef" => [0, "\x19T"], "\xf0" => [0, "\x19U"], "\xf1" => [0, "\x19V"], "\xf2" => [0, "\x19W"], "\xf3" => [0, "\x19Y"], "\xf4" => [0, "\x19j"], "\xf5" => [0, "\x19k"], "\xf6" => [0, "\x19q"], "\xf7" => [0, "\x19v"], "\xf8" => [0, "\x19w"], "\xf9" => [0, "\x19x"], "\xfa" => [0, "\x19y"], "\xfb" => [0, "\x19z"], "\xfc" => [82, "\x19"], "\xfd" => [87, "\x19"], "\xfe" => [130, "\x19"], "\xff" => [9, "\x19"]], ["\x00" => [77, "\x180"], "\x01" => [18, "\x180"], "\x02" => [77, "\x181"], "\x03" => [18, "\x181"], "\x04" => [77, "\x182"], "\x05" => [18, "\x182"], "\x06" => [77, "\x18a"], "\x07" => [18, "\x18a"], "\x08" => [77, "\x18c"], "\t" => [18, "\x18c"], "\n" => [77, "\x18e"], "\v" => [18, "\x18e"], "\f" => [77, "\x18i"], "\r" => [18, "\x18i"], "\x0e" => [77, "\x18o"], "\x0f" => [18, "\x18o"], "\x10" => [77, "\x18s"], "\x11" => [18, "\x18s"], "\x12" => [77, "\x18t"], "\x13" => [18, "\x18t"], "\x14" => [0, "\x18 "], "\x15" => [0, "\x18%"], "\x16" => [0, "\x18-"], "\x17" => [0, "\x18."], "\x18" => [0, "\x18/"], "\x19" => [0, "\x183"], "\x1a" => [0, "\x184"], "\x1b" => [0, "\x185"], "\x1c" => [0, "\x186"], "\x1d" => [0, "\x187"], "\x1e" => [0, "\x188"], "\x1f" => [0, "\x189"], " " => [0, "\x18="], "!" => [0, "\x18A"], "\"" => [0, "\x18_"], "#" => [0, "\x18b"], "\$" => [0, "\x18d"], "%" => [0, "\x18f"], "&" => [0, "\x18g"], "'" => [0, "\x18h"], "(" => [0, "\x18l"], ")" => [0, "\x18m"], "*" => [0, "\x18n"], "+" => [0, "\x18p"], "," => [0, "\x18r"], "-" => [0, "\x18u"], "." => [100, "\x18"], "/" => [110, "\x18"], [111, "\x18"], [115, "\x18"], [116, "\x18"], [118, "\x18"], [119, "\x18"], [122, "\x18"], [123, "\x18"], [125, "\x18"], [126, "\x18"], [129, "\x18"], ":" => [143, "\x18"], ";" => [148, "\x18"], "<" => [151, "\x18"], "=" => [153, "\x18"], ">" => [83, "\x18"], "?" => [10, "\x18"], "@" => [77, "\x190"], "A" => [18, "\x190"], "B" => [77, "\x191"], "C" => [18, "\x191"], "D" => [77, "\x192"], "E" => [18, "\x192"], "F" => [77, "\x19a"], "G" => [18, "\x19a"], "H" => [77, "\x19c"], "I" => [18, "\x19c"], "J" => [77, "\x19e"], "K" => [18, "\x19e"], "L" => [77, "\x19i"], "M" => [18, "\x19i"], "N" => [77, "\x19o"], "O" => [18, "\x19o"], "P" => [77, "\x19s"], "Q" => [18, "\x19s"], "R" => [77, "\x19t"], "S" => [18, "\x19t"], "T" => [0, "\x19 "], "U" => [0, "\x19%"], "V" => [0, "\x19-"], "W" => [0, "\x19."], "X" => [0, "\x19/"], "Y" => [0, "\x193"], "Z" => [0, "\x194"], "[" => [0, "\x195"], "\\" => [0, "\x196"], "]" => [0, "\x197"], "^" => [0, "\x198"], "_" => [0, "\x199"], "`" => [0, "\x19="], "a" => [0, "\x19A"], "b" => [0, "\x19_"], "c" => [0, "\x19b"], "d" => [0, "\x19d"], "e" => [0, "\x19f"], "f" => [0, "\x19g"], "g" => [0, "\x19h"], "h" => [0, "\x19l"], "i" => [0, "\x19m"], "j" => [0, "\x19n"], "k" => [0, "\x19p"], "l" => [0, "\x19r"], "m" => [0, "\x19u"], "n" => [100, "\x19"], "o" => [110, "\x19"], "p" => [111, "\x19"], "q" => [115, "\x19"], "r" => [116, "\x19"], "s" => [118, "\x19"], "t" => [119, "\x19"], "u" => [122, "\x19"], "v" => [123, "\x19"], "w" => [125, "\x19"], "x" => [126, "\x19"], "y" => [129, "\x19"], "z" => [143, "\x19"], "{" => [148, "\x19"], "|" => [151, "\x19"], "}" => [153, "\x19"], "~" => [83, "\x19"], "" => [10, "\x19"], "\x80" => [77, "\x1a0"], "\x81" => [18, "\x1a0"], "\x82" => [77, "\x1a1"], "\x83" => [18, "\x1a1"], "\x84" => [77, "\x1a2"], "\x85" => [18, "\x1a2"], "\x86" => [77, "\x1aa"], "\x87" => [18, "\x1aa"], "\x88" => [77, "\x1ac"], "\x89" => [18, "\x1ac"], "\x8a" => [77, "\x1ae"], "\x8b" => [18, "\x1ae"], "\x8c" => [77, "\x1ai"], "\x8d" => [18, "\x1ai"], "\x8e" => [77, "\x1ao"], "\x8f" => [18, "\x1ao"], "\x90" => [77, "\x1as"], "\x91" => [18, "\x1as"], "\x92" => [77, "\x1at"], "\x93" => [18, "\x1at"], "\x94" => [0, "\x1a "], "\x95" => [0, "\x1a%"], "\x96" => [0, "\x1a-"], "\x97" => [0, "\x1a."], "\x98" => [0, "\x1a/"], "\x99" => [0, "\x1a3"], "\x9a" => [0, "\x1a4"], "\x9b" => [0, "\x1a5"], "\x9c" => [0, "\x1a6"], "\x9d" => [0, "\x1a7"], "\x9e" => [0, "\x1a8"], "\x9f" => [0, "\x1a9"], "\xa0" => [0, "\x1a="], "\xa1" => [0, "\x1aA"], "\xa2" => [0, "\x1a_"], "\xa3" => [0, "\x1ab"], "\xa4" => [0, "\x1ad"], "\xa5" => [0, "\x1af"], "\xa6" => [0, "\x1ag"], "\xa7" => [0, "\x1ah"], "\xa8" => [0, "\x1al"], "\xa9" => [0, "\x1am"], "\xaa" => [0, "\x1an"], "\xab" => [0, "\x1ap"], "\xac" => [0, "\x1ar"], "\xad" => [0, "\x1au"], "\xae" => [100, "\x1a"], "\xaf" => [110, "\x1a"], "\xb0" => [111, "\x1a"], "\xb1" => [115, "\x1a"], "\xb2" => [116, "\x1a"], "\xb3" => [118, "\x1a"], "\xb4" => [119, "\x1a"], "\xb5" => [122, "\x1a"], "\xb6" => [123, "\x1a"], "\xb7" => [125, "\x1a"], "\xb8" => [126, "\x1a"], "\xb9" => [129, "\x1a"], "\xba" => [143, "\x1a"], "\xbb" => [148, "\x1a"], "\xbc" => [151, "\x1a"], "\xbd" => [153, "\x1a"], "\xbe" => [83, "\x1a"], "\xbf" => [10, "\x1a"], "\xc0" => [77, "\x1b0"], "\xc1" => [18, "\x1b0"], "\xc2" => [77, "\x1b1"], "\xc3" => [18, "\x1b1"], "\xc4" => [77, "\x1b2"], "\xc5" => [18, "\x1b2"], "\xc6" => [77, "\x1ba"], "\xc7" => [18, "\x1ba"], "\xc8" => [77, "\x1bc"], "\xc9" => [18, "\x1bc"], "\xca" => [77, "\x1be"], "\xcb" => [18, "\x1be"], "\xcc" => [77, "\x1bi"], "\xcd" => [18, "\x1bi"], "\xce" => [77, "\x1bo"], "\xcf" => [18, "\x1bo"], "\xd0" => [77, "\x1bs"], "\xd1" => [18, "\x1bs"], "\xd2" => [77, "\x1bt"], "\xd3" => [18, "\x1bt"], "\xd4" => [0, "\x1b "], "\xd5" => [0, "\x1b%"], "\xd6" => [0, "\x1b-"], "\xd7" => [0, "\x1b."], "\xd8" => [0, "\x1b/"], "\xd9" => [0, "\x1b3"], "\xda" => [0, "\x1b4"], "\xdb" => [0, "\x1b5"], "\xdc" => [0, "\x1b6"], "\xdd" => [0, "\x1b7"], "\xde" => [0, "\x1b8"], "\xdf" => [0, "\x1b9"], "\xe0" => [0, "\x1b="], "\xe1" => [0, "\x1bA"], "\xe2" => [0, "\x1b_"], "\xe3" => [0, "\x1bb"], "\xe4" => [0, "\x1bd"], "\xe5" => [0, "\x1bf"], "\xe6" => [0, "\x1bg"], "\xe7" => [0, "\x1bh"], "\xe8" => [0, "\x1bl"], "\xe9" => [0, "\x1bm"], "\xea" => [0, "\x1bn"], "\xeb" => [0, "\x1bp"], "\xec" => [0, "\x1br"], "\xed" => [0, "\x1bu"], "\xee" => [100, "\x1b"], "\xef" => [110, "\x1b"], "\xf0" => [111, "\x1b"], "\xf1" => [115, "\x1b"], "\xf2" => [116, "\x1b"], "\xf3" => [118, "\x1b"], "\xf4" => [119, "\x1b"], "\xf5" => [122, "\x1b"], "\xf6" => [123, "\x1b"], "\xf7" => [125, "\x1b"], "\xf8" => [126, "\x1b"], "\xf9" => [129, "\x1b"], "\xfa" => [143, "\x1b"], "\xfb" => [148, "\x1b"], "\xfc" => [151, "\x1b"], "\xfd" => [153, "\x1b"], "\xfe" => [83, "\x1b"], "\xff" => [10, "\x1b"]], ["\x00" => [94, "\x1a0"], "\x01" => [76, "\x1a0"], "\x02" => [104, "\x1a0"], "\x03" => [16, "\x1a0"], "\x04" => [94, "\x1a1"], "\x05" => [76, "\x1a1"], "\x06" => [104, "\x1a1"], "\x07" => [16, "\x1a1"], "\x08" => [94, "\x1a2"], "\t" => [76, "\x1a2"], "\n" => [104, "\x1a2"], "\v" => [16, "\x1a2"], "\f" => [94, "\x1aa"], "\r" => [76, "\x1aa"], "\x0e" => [104, "\x1aa"], "\x0f" => [16, "\x1aa"], "\x10" => [94, "\x1ac"], "\x11" => [76, "\x1ac"], "\x12" => [104, "\x1ac"], "\x13" => [16, "\x1ac"], "\x14" => [94, "\x1ae"], "\x15" => [76, "\x1ae"], "\x16" => [104, "\x1ae"], "\x17" => [16, "\x1ae"], "\x18" => [94, "\x1ai"], "\x19" => [76, "\x1ai"], "\x1a" => [104, "\x1ai"], "\x1b" => [16, "\x1ai"], "\x1c" => [94, "\x1ao"], "\x1d" => [76, "\x1ao"], "\x1e" => [104, "\x1ao"], "\x1f" => [16, "\x1ao"], " " => [94, "\x1as"], "!" => [76, "\x1as"], "\"" => [104, "\x1as"], "#" => [16, "\x1as"], "\$" => [94, "\x1at"], "%" => [76, "\x1at"], "&" => [104, "\x1at"], "'" => [16, "\x1at"], "(" => [77, "\x1a "], ")" => [18, "\x1a "], "*" => [77, "\x1a%"], "+" => [18, "\x1a%"], "," => [77, "\x1a-"], "-" => [18, "\x1a-"], "." => [77, "\x1a."], "/" => [18, "\x1a."], [77, "\x1a/"], [18, "\x1a/"], [77, "\x1a3"], [18, "\x1a3"], [77, "\x1a4"], [18, "\x1a4"], [77, "\x1a5"], [18, "\x1a5"], [77, "\x1a6"], [18, "\x1a6"], ":" => [77, "\x1a7"], ";" => [18, "\x1a7"], "<" => [77, "\x1a8"], "=" => [18, "\x1a8"], ">" => [77, "\x1a9"], "?" => [18, "\x1a9"], "@" => [77, "\x1a="], "A" => [18, "\x1a="], "B" => [77, "\x1aA"], "C" => [18, "\x1aA"], "D" => [77, "\x1a_"], "E" => [18, "\x1a_"], "F" => [77, "\x1ab"], "G" => [18, "\x1ab"], "H" => [77, "\x1ad"], "I" => [18, "\x1ad"], "J" => [77, "\x1af"], "K" => [18, "\x1af"], "L" => [77, "\x1ag"], "M" => [18, "\x1ag"], "N" => [77, "\x1ah"], "O" => [18, "\x1ah"], "P" => [77, "\x1al"], "Q" => [18, "\x1al"], "R" => [77, "\x1am"], "S" => [18, "\x1am"], "T" => [77, "\x1an"], "U" => [18, "\x1an"], "V" => [77, "\x1ap"], "W" => [18, "\x1ap"], "X" => [77, "\x1ar"], "Y" => [18, "\x1ar"], "Z" => [77, "\x1au"], "[" => [18, "\x1au"], "\\" => [0, "\x1a:"], "]" => [0, "\x1aB"], "^" => [0, "\x1aC"], "_" => [0, "\x1aD"], "`" => [0, "\x1aE"], "a" => [0, "\x1aF"], "b" => [0, "\x1aG"], "c" => [0, "\x1aH"], "d" => [0, "\x1aI"], "e" => [0, "\x1aJ"], "f" => [0, "\x1aK"], "g" => [0, "\x1aL"], "h" => [0, "\x1aM"], "i" => [0, "\x1aN"], "j" => [0, "\x1aO"], "k" => [0, "\x1aP"], "l" => [0, "\x1aQ"], "m" => [0, "\x1aR"], "n" => [0, "\x1aS"], "o" => [0, "\x1aT"], "p" => [0, "\x1aU"], "q" => [0, "\x1aV"], "r" => [0, "\x1aW"], "s" => [0, "\x1aY"], "t" => [0, "\x1aj"], "u" => [0, "\x1ak"], "v" => [0, "\x1aq"], "w" => [0, "\x1av"], "x" => [0, "\x1aw"], "y" => [0, "\x1ax"], "z" => [0, "\x1ay"], "{" => [0, "\x1az"], "|" => [82, "\x1a"], "}" => [87, "\x1a"], "~" => [130, "\x1a"], "" => [9, "\x1a"], "\x80" => [94, "\x1b0"], "\x81" => [76, "\x1b0"], "\x82" => [104, "\x1b0"], "\x83" => [16, "\x1b0"], "\x84" => [94, "\x1b1"], "\x85" => [76, "\x1b1"], "\x86" => [104, "\x1b1"], "\x87" => [16, "\x1b1"], "\x88" => [94, "\x1b2"], "\x89" => [76, "\x1b2"], "\x8a" => [104, "\x1b2"], "\x8b" => [16, "\x1b2"], "\x8c" => [94, "\x1ba"], "\x8d" => [76, "\x1ba"], "\x8e" => [104, "\x1ba"], "\x8f" => [16, "\x1ba"], "\x90" => [94, "\x1bc"], "\x91" => [76, "\x1bc"], "\x92" => [104, "\x1bc"], "\x93" => [16, "\x1bc"], "\x94" => [94, "\x1be"], "\x95" => [76, "\x1be"], "\x96" => [104, "\x1be"], "\x97" => [16, "\x1be"], "\x98" => [94, "\x1bi"], "\x99" => [76, "\x1bi"], "\x9a" => [104, "\x1bi"], "\x9b" => [16, "\x1bi"], "\x9c" => [94, "\x1bo"], "\x9d" => [76, "\x1bo"], "\x9e" => [104, "\x1bo"], "\x9f" => [16, "\x1bo"], "\xa0" => [94, "\x1bs"], "\xa1" => [76, "\x1bs"], "\xa2" => [104, "\x1bs"], "\xa3" => [16, "\x1bs"], "\xa4" => [94, "\x1bt"], "\xa5" => [76, "\x1bt"], "\xa6" => [104, "\x1bt"], "\xa7" => [16, "\x1bt"], "\xa8" => [77, "\x1b "], "\xa9" => [18, "\x1b "], "\xaa" => [77, "\x1b%"], "\xab" => [18, "\x1b%"], "\xac" => [77, "\x1b-"], "\xad" => [18, "\x1b-"], "\xae" => [77, "\x1b."], "\xaf" => [18, "\x1b."], "\xb0" => [77, "\x1b/"], "\xb1" => [18, "\x1b/"], "\xb2" => [77, "\x1b3"], "\xb3" => [18, "\x1b3"], "\xb4" => [77, "\x1b4"], "\xb5" => [18, "\x1b4"], "\xb6" => [77, "\x1b5"], "\xb7" => [18, "\x1b5"], "\xb8" => [77, "\x1b6"], "\xb9" => [18, "\x1b6"], "\xba" => [77, "\x1b7"], "\xbb" => [18, "\x1b7"], "\xbc" => [77, "\x1b8"], "\xbd" => [18, "\x1b8"], "\xbe" => [77, "\x1b9"], "\xbf" => [18, "\x1b9"], "\xc0" => [77, "\x1b="], "\xc1" => [18, "\x1b="], "\xc2" => [77, "\x1bA"], "\xc3" => [18, "\x1bA"], "\xc4" => [77, "\x1b_"], "\xc5" => [18, "\x1b_"], "\xc6" => [77, "\x1bb"], "\xc7" => [18, "\x1bb"], "\xc8" => [77, "\x1bd"], "\xc9" => [18, "\x1bd"], "\xca" => [77, "\x1bf"], "\xcb" => [18, "\x1bf"], "\xcc" => [77, "\x1bg"], "\xcd" => [18, "\x1bg"], "\xce" => [77, "\x1bh"], "\xcf" => [18, "\x1bh"], "\xd0" => [77, "\x1bl"], "\xd1" => [18, "\x1bl"], "\xd2" => [77, "\x1bm"], "\xd3" => [18, "\x1bm"], "\xd4" => [77, "\x1bn"], "\xd5" => [18, "\x1bn"], "\xd6" => [77, "\x1bp"], "\xd7" => [18, "\x1bp"], "\xd8" => [77, "\x1br"], "\xd9" => [18, "\x1br"], "\xda" => [77, "\x1bu"], "\xdb" => [18, "\x1bu"], "\xdc" => [0, "\x1b:"], "\xdd" => [0, "\x1bB"], "\xde" => [0, "\x1bC"], "\xdf" => [0, "\x1bD"], "\xe0" => [0, "\x1bE"], "\xe1" => [0, "\x1bF"], "\xe2" => [0, "\x1bG"], "\xe3" => [0, "\x1bH"], "\xe4" => [0, "\x1bI"], "\xe5" => [0, "\x1bJ"], "\xe6" => [0, "\x1bK"], "\xe7" => [0, "\x1bL"], "\xe8" => [0, "\x1bM"], "\xe9" => [0, "\x1bN"], "\xea" => [0, "\x1bO"], "\xeb" => [0, "\x1bP"], "\xec" => [0, "\x1bQ"], "\xed" => [0, "\x1bR"], "\xee" => [0, "\x1bS"], "\xef" => [0, "\x1bT"], "\xf0" => [0, "\x1bU"], "\xf1" => [0, "\x1bV"], "\xf2" => [0, "\x1bW"], "\xf3" => [0, "\x1bY"], "\xf4" => [0, "\x1bj"], "\xf5" => [0, "\x1bk"], "\xf6" => [0, "\x1bq"], "\xf7" => [0, "\x1bv"], "\xf8" => [0, "\x1bw"], "\xf9" => [0, "\x1bx"], "\xfa" => [0, "\x1by"], "\xfb" => [0, "\x1bz"], "\xfc" => [82, "\x1b"], "\xfd" => [87, "\x1b"], "\xfe" => [130, "\x1b"], "\xff" => [9, "\x1b"]], ["\x00" => [94, "\x1c0"], "\x01" => [76, "\x1c0"], "\x02" => [104, "\x1c0"], "\x03" => [16, "\x1c0"], "\x04" => [94, "\x1c1"], "\x05" => [76, "\x1c1"], "\x06" => [104, "\x1c1"], "\x07" => [16, "\x1c1"], "\x08" => [94, "\x1c2"], "\t" => [76, "\x1c2"], "\n" => [104, "\x1c2"], "\v" => [16, "\x1c2"], "\f" => [94, "\x1ca"], "\r" => [76, "\x1ca"], "\x0e" => [104, "\x1ca"], "\x0f" => [16, "\x1ca"], "\x10" => [94, "\x1cc"], "\x11" => [76, "\x1cc"], "\x12" => [104, "\x1cc"], "\x13" => [16, "\x1cc"], "\x14" => [94, "\x1ce"], "\x15" => [76, "\x1ce"], "\x16" => [104, "\x1ce"], "\x17" => [16, "\x1ce"], "\x18" => [94, "\x1ci"], "\x19" => [76, "\x1ci"], "\x1a" => [104, "\x1ci"], "\x1b" => [16, "\x1ci"], "\x1c" => [94, "\x1co"], "\x1d" => [76, "\x1co"], "\x1e" => [104, "\x1co"], "\x1f" => [16, "\x1co"], " " => [94, "\x1cs"], "!" => [76, "\x1cs"], "\"" => [104, "\x1cs"], "#" => [16, "\x1cs"], "\$" => [94, "\x1ct"], "%" => [76, "\x1ct"], "&" => [104, "\x1ct"], "'" => [16, "\x1ct"], "(" => [77, "\x1c "], ")" => [18, "\x1c "], "*" => [77, "\x1c%"], "+" => [18, "\x1c%"], "," => [77, "\x1c-"], "-" => [18, "\x1c-"], "." => [77, "\x1c."], "/" => [18, "\x1c."], [77, "\x1c/"], [18, "\x1c/"], [77, "\x1c3"], [18, "\x1c3"], [77, "\x1c4"], [18, "\x1c4"], [77, "\x1c5"], [18, "\x1c5"], [77, "\x1c6"], [18, "\x1c6"], ":" => [77, "\x1c7"], ";" => [18, "\x1c7"], "<" => [77, "\x1c8"], "=" => [18, "\x1c8"], ">" => [77, "\x1c9"], "?" => [18, "\x1c9"], "@" => [77, "\x1c="], "A" => [18, "\x1c="], "B" => [77, "\x1cA"], "C" => [18, "\x1cA"], "D" => [77, "\x1c_"], "E" => [18, "\x1c_"], "F" => [77, "\x1cb"], "G" => [18, "\x1cb"], "H" => [77, "\x1cd"], "I" => [18, "\x1cd"], "J" => [77, "\x1cf"], "K" => [18, "\x1cf"], "L" => [77, "\x1cg"], "M" => [18, "\x1cg"], "N" => [77, "\x1ch"], "O" => [18, "\x1ch"], "P" => [77, "\x1cl"], "Q" => [18, "\x1cl"], "R" => [77, "\x1cm"], "S" => [18, "\x1cm"], "T" => [77, "\x1cn"], "U" => [18, "\x1cn"], "V" => [77, "\x1cp"], "W" => [18, "\x1cp"], "X" => [77, "\x1cr"], "Y" => [18, "\x1cr"], "Z" => [77, "\x1cu"], "[" => [18, "\x1cu"], "\\" => [0, "\x1c:"], "]" => [0, "\x1cB"], "^" => [0, "\x1cC"], "_" => [0, "\x1cD"], "`" => [0, "\x1cE"], "a" => [0, "\x1cF"], "b" => [0, "\x1cG"], "c" => [0, "\x1cH"], "d" => [0, "\x1cI"], "e" => [0, "\x1cJ"], "f" => [0, "\x1cK"], "g" => [0, "\x1cL"], "h" => [0, "\x1cM"], "i" => [0, "\x1cN"], "j" => [0, "\x1cO"], "k" => [0, "\x1cP"], "l" => [0, "\x1cQ"], "m" => [0, "\x1cR"], "n" => [0, "\x1cS"], "o" => [0, "\x1cT"], "p" => [0, "\x1cU"], "q" => [0, "\x1cV"], "r" => [0, "\x1cW"], "s" => [0, "\x1cY"], "t" => [0, "\x1cj"], "u" => [0, "\x1ck"], "v" => [0, "\x1cq"], "w" => [0, "\x1cv"], "x" => [0, "\x1cw"], "y" => [0, "\x1cx"], "z" => [0, "\x1cy"], "{" => [0, "\x1cz"], "|" => [82, "\x1c"], "}" => [87, "\x1c"], "~" => [130, "\x1c"], "" => [9, "\x1c"], "\x80" => [94, "\x1d0"], "\x81" => [76, "\x1d0"], "\x82" => [104, "\x1d0"], "\x83" => [16, "\x1d0"], "\x84" => [94, "\x1d1"], "\x85" => [76, "\x1d1"], "\x86" => [104, "\x1d1"], "\x87" => [16, "\x1d1"], "\x88" => [94, "\x1d2"], "\x89" => [76, "\x1d2"], "\x8a" => [104, "\x1d2"], "\x8b" => [16, "\x1d2"], "\x8c" => [94, "\x1da"], "\x8d" => [76, "\x1da"], "\x8e" => [104, "\x1da"], "\x8f" => [16, "\x1da"], "\x90" => [94, "\x1dc"], "\x91" => [76, "\x1dc"], "\x92" => [104, "\x1dc"], "\x93" => [16, "\x1dc"], "\x94" => [94, "\x1de"], "\x95" => [76, "\x1de"], "\x96" => [104, "\x1de"], "\x97" => [16, "\x1de"], "\x98" => [94, "\x1di"], "\x99" => [76, "\x1di"], "\x9a" => [104, "\x1di"], "\x9b" => [16, "\x1di"], "\x9c" => [94, "\x1do"], "\x9d" => [76, "\x1do"], "\x9e" => [104, "\x1do"], "\x9f" => [16, "\x1do"], "\xa0" => [94, "\x1ds"], "\xa1" => [76, "\x1ds"], "\xa2" => [104, "\x1ds"], "\xa3" => [16, "\x1ds"], "\xa4" => [94, "\x1dt"], "\xa5" => [76, "\x1dt"], "\xa6" => [104, "\x1dt"], "\xa7" => [16, "\x1dt"], "\xa8" => [77, "\x1d "], "\xa9" => [18, "\x1d "], "\xaa" => [77, "\x1d%"], "\xab" => [18, "\x1d%"], "\xac" => [77, "\x1d-"], "\xad" => [18, "\x1d-"], "\xae" => [77, "\x1d."], "\xaf" => [18, "\x1d."], "\xb0" => [77, "\x1d/"], "\xb1" => [18, "\x1d/"], "\xb2" => [77, "\x1d3"], "\xb3" => [18, "\x1d3"], "\xb4" => [77, "\x1d4"], "\xb5" => [18, "\x1d4"], "\xb6" => [77, "\x1d5"], "\xb7" => [18, "\x1d5"], "\xb8" => [77, "\x1d6"], "\xb9" => [18, "\x1d6"], "\xba" => [77, "\x1d7"], "\xbb" => [18, "\x1d7"], "\xbc" => [77, "\x1d8"], "\xbd" => [18, "\x1d8"], "\xbe" => [77, "\x1d9"], "\xbf" => [18, "\x1d9"], "\xc0" => [77, "\x1d="], "\xc1" => [18, "\x1d="], "\xc2" => [77, "\x1dA"], "\xc3" => [18, "\x1dA"], "\xc4" => [77, "\x1d_"], "\xc5" => [18, "\x1d_"], "\xc6" => [77, "\x1db"], "\xc7" => [18, "\x1db"], "\xc8" => [77, "\x1dd"], "\xc9" => [18, "\x1dd"], "\xca" => [77, "\x1df"], "\xcb" => [18, "\x1df"], "\xcc" => [77, "\x1dg"], "\xcd" => [18, "\x1dg"], "\xce" => [77, "\x1dh"], "\xcf" => [18, "\x1dh"], "\xd0" => [77, "\x1dl"], "\xd1" => [18, "\x1dl"], "\xd2" => [77, "\x1dm"], "\xd3" => [18, "\x1dm"], "\xd4" => [77, "\x1dn"], "\xd5" => [18, "\x1dn"], "\xd6" => [77, "\x1dp"], "\xd7" => [18, "\x1dp"], "\xd8" => [77, "\x1dr"], "\xd9" => [18, "\x1dr"], "\xda" => [77, "\x1du"], "\xdb" => [18, "\x1du"], "\xdc" => [0, "\x1d:"], "\xdd" => [0, "\x1dB"], "\xde" => [0, "\x1dC"], "\xdf" => [0, "\x1dD"], "\xe0" => [0, "\x1dE"], "\xe1" => [0, "\x1dF"], "\xe2" => [0, "\x1dG"], "\xe3" => [0, "\x1dH"], "\xe4" => [0, "\x1dI"], "\xe5" => [0, "\x1dJ"], "\xe6" => [0, "\x1dK"], "\xe7" => [0, "\x1dL"], "\xe8" => [0, "\x1dM"], "\xe9" => [0, "\x1dN"], "\xea" => [0, "\x1dO"], "\xeb" => [0, "\x1dP"], "\xec" => [0, "\x1dQ"], "\xed" => [0, "\x1dR"], "\xee" => [0, "\x1dS"], "\xef" => [0, "\x1dT"], "\xf0" => [0, "\x1dU"], "\xf1" => [0, "\x1dV"], "\xf2" => [0, "\x1dW"], "\xf3" => [0, "\x1dY"], "\xf4" => [0, "\x1dj"], "\xf5" => [0, "\x1dk"], "\xf6" => [0, "\x1dq"], "\xf7" => [0, "\x1dv"], "\xf8" => [0, "\x1dw"], "\xf9" => [0, "\x1dx"], "\xfa" => [0, "\x1dy"], "\xfb" => [0, "\x1dz"], "\xfc" => [82, "\x1d"], "\xfd" => [87, "\x1d"], "\xfe" => [130, "\x1d"], "\xff" => [9, "\x1d"]], ["\x00" => [77, "\x1c0"], "\x01" => [18, "\x1c0"], "\x02" => [77, "\x1c1"], "\x03" => [18, "\x1c1"], "\x04" => [77, "\x1c2"], "\x05" => [18, "\x1c2"], "\x06" => [77, "\x1ca"], "\x07" => [18, "\x1ca"], "\x08" => [77, "\x1cc"], "\t" => [18, "\x1cc"], "\n" => [77, "\x1ce"], "\v" => [18, "\x1ce"], "\f" => [77, "\x1ci"], "\r" => [18, "\x1ci"], "\x0e" => [77, "\x1co"], "\x0f" => [18, "\x1co"], "\x10" => [77, "\x1cs"], "\x11" => [18, "\x1cs"], "\x12" => [77, "\x1ct"], "\x13" => [18, "\x1ct"], "\x14" => [0, "\x1c "], "\x15" => [0, "\x1c%"], "\x16" => [0, "\x1c-"], "\x17" => [0, "\x1c."], "\x18" => [0, "\x1c/"], "\x19" => [0, "\x1c3"], "\x1a" => [0, "\x1c4"], "\x1b" => [0, "\x1c5"], "\x1c" => [0, "\x1c6"], "\x1d" => [0, "\x1c7"], "\x1e" => [0, "\x1c8"], "\x1f" => [0, "\x1c9"], " " => [0, "\x1c="], "!" => [0, "\x1cA"], "\"" => [0, "\x1c_"], "#" => [0, "\x1cb"], "\$" => [0, "\x1cd"], "%" => [0, "\x1cf"], "&" => [0, "\x1cg"], "'" => [0, "\x1ch"], "(" => [0, "\x1cl"], ")" => [0, "\x1cm"], "*" => [0, "\x1cn"], "+" => [0, "\x1cp"], "," => [0, "\x1cr"], "-" => [0, "\x1cu"], "." => [100, "\x1c"], "/" => [110, "\x1c"], [111, "\x1c"], [115, "\x1c"], [116, "\x1c"], [118, "\x1c"], [119, "\x1c"], [122, "\x1c"], [123, "\x1c"], [125, "\x1c"], [126, "\x1c"], [129, "\x1c"], ":" => [143, "\x1c"], ";" => [148, "\x1c"], "<" => [151, "\x1c"], "=" => [153, "\x1c"], ">" => [83, "\x1c"], "?" => [10, "\x1c"], "@" => [77, "\x1d0"], "A" => [18, "\x1d0"], "B" => [77, "\x1d1"], "C" => [18, "\x1d1"], "D" => [77, "\x1d2"], "E" => [18, "\x1d2"], "F" => [77, "\x1da"], "G" => [18, "\x1da"], "H" => [77, "\x1dc"], "I" => [18, "\x1dc"], "J" => [77, "\x1de"], "K" => [18, "\x1de"], "L" => [77, "\x1di"], "M" => [18, "\x1di"], "N" => [77, "\x1do"], "O" => [18, "\x1do"], "P" => [77, "\x1ds"], "Q" => [18, "\x1ds"], "R" => [77, "\x1dt"], "S" => [18, "\x1dt"], "T" => [0, "\x1d "], "U" => [0, "\x1d%"], "V" => [0, "\x1d-"], "W" => [0, "\x1d."], "X" => [0, "\x1d/"], "Y" => [0, "\x1d3"], "Z" => [0, "\x1d4"], "[" => [0, "\x1d5"], "\\" => [0, "\x1d6"], "]" => [0, "\x1d7"], "^" => [0, "\x1d8"], "_" => [0, "\x1d9"], "`" => [0, "\x1d="], "a" => [0, "\x1dA"], "b" => [0, "\x1d_"], "c" => [0, "\x1db"], "d" => [0, "\x1dd"], "e" => [0, "\x1df"], "f" => [0, "\x1dg"], "g" => [0, "\x1dh"], "h" => [0, "\x1dl"], "i" => [0, "\x1dm"], "j" => [0, "\x1dn"], "k" => [0, "\x1dp"], "l" => [0, "\x1dr"], "m" => [0, "\x1du"], "n" => [100, "\x1d"], "o" => [110, "\x1d"], "p" => [111, "\x1d"], "q" => [115, "\x1d"], "r" => [116, "\x1d"], "s" => [118, "\x1d"], "t" => [119, "\x1d"], "u" => [122, "\x1d"], "v" => [123, "\x1d"], "w" => [125, "\x1d"], "x" => [126, "\x1d"], "y" => [129, "\x1d"], "z" => [143, "\x1d"], "{" => [148, "\x1d"], "|" => [151, "\x1d"], "}" => [153, "\x1d"], "~" => [83, "\x1d"], "" => [10, "\x1d"], "\x80" => [77, "\x1e0"], "\x81" => [18, "\x1e0"], "\x82" => [77, "\x1e1"], "\x83" => [18, "\x1e1"], "\x84" => [77, "\x1e2"], "\x85" => [18, "\x1e2"], "\x86" => [77, "\x1ea"], "\x87" => [18, "\x1ea"], "\x88" => [77, "\x1ec"], "\x89" => [18, "\x1ec"], "\x8a" => [77, "\x1ee"], "\x8b" => [18, "\x1ee"], "\x8c" => [77, "\x1ei"], "\x8d" => [18, "\x1ei"], "\x8e" => [77, "\x1eo"], "\x8f" => [18, "\x1eo"], "\x90" => [77, "\x1es"], "\x91" => [18, "\x1es"], "\x92" => [77, "\x1et"], "\x93" => [18, "\x1et"], "\x94" => [0, "\x1e "], "\x95" => [0, "\x1e%"], "\x96" => [0, "\x1e-"], "\x97" => [0, "\x1e."], "\x98" => [0, "\x1e/"], "\x99" => [0, "\x1e3"], "\x9a" => [0, "\x1e4"], "\x9b" => [0, "\x1e5"], "\x9c" => [0, "\x1e6"], "\x9d" => [0, "\x1e7"], "\x9e" => [0, "\x1e8"], "\x9f" => [0, "\x1e9"], "\xa0" => [0, "\x1e="], "\xa1" => [0, "\x1eA"], "\xa2" => [0, "\x1e_"], "\xa3" => [0, "\x1eb"], "\xa4" => [0, "\x1ed"], "\xa5" => [0, "\x1ef"], "\xa6" => [0, "\x1eg"], "\xa7" => [0, "\x1eh"], "\xa8" => [0, "\x1el"], "\xa9" => [0, "\x1em"], "\xaa" => [0, "\x1en"], "\xab" => [0, "\x1ep"], "\xac" => [0, "\x1er"], "\xad" => [0, "\x1eu"], "\xae" => [100, "\x1e"], "\xaf" => [110, "\x1e"], "\xb0" => [111, "\x1e"], "\xb1" => [115, "\x1e"], "\xb2" => [116, "\x1e"], "\xb3" => [118, "\x1e"], "\xb4" => [119, "\x1e"], "\xb5" => [122, "\x1e"], "\xb6" => [123, "\x1e"], "\xb7" => [125, "\x1e"], "\xb8" => [126, "\x1e"], "\xb9" => [129, "\x1e"], "\xba" => [143, "\x1e"], "\xbb" => [148, "\x1e"], "\xbc" => [151, "\x1e"], "\xbd" => [153, "\x1e"], "\xbe" => [83, "\x1e"], "\xbf" => [10, "\x1e"], "\xc0" => [77, "\x1f0"], "\xc1" => [18, "\x1f0"], "\xc2" => [77, "\x1f1"], "\xc3" => [18, "\x1f1"], "\xc4" => [77, "\x1f2"], "\xc5" => [18, "\x1f2"], "\xc6" => [77, "\x1fa"], "\xc7" => [18, "\x1fa"], "\xc8" => [77, "\x1fc"], "\xc9" => [18, "\x1fc"], "\xca" => [77, "\x1fe"], "\xcb" => [18, "\x1fe"], "\xcc" => [77, "\x1fi"], "\xcd" => [18, "\x1fi"], "\xce" => [77, "\x1fo"], "\xcf" => [18, "\x1fo"], "\xd0" => [77, "\x1fs"], "\xd1" => [18, "\x1fs"], "\xd2" => [77, "\x1ft"], "\xd3" => [18, "\x1ft"], "\xd4" => [0, "\x1f "], "\xd5" => [0, "\x1f%"], "\xd6" => [0, "\x1f-"], "\xd7" => [0, "\x1f."], "\xd8" => [0, "\x1f/"], "\xd9" => [0, "\x1f3"], "\xda" => [0, "\x1f4"], "\xdb" => [0, "\x1f5"], "\xdc" => [0, "\x1f6"], "\xdd" => [0, "\x1f7"], "\xde" => [0, "\x1f8"], "\xdf" => [0, "\x1f9"], "\xe0" => [0, "\x1f="], "\xe1" => [0, "\x1fA"], "\xe2" => [0, "\x1f_"], "\xe3" => [0, "\x1fb"], "\xe4" => [0, "\x1fd"], "\xe5" => [0, "\x1ff"], "\xe6" => [0, "\x1fg"], "\xe7" => [0, "\x1fh"], "\xe8" => [0, "\x1fl"], "\xe9" => [0, "\x1fm"], "\xea" => [0, "\x1fn"], "\xeb" => [0, "\x1fp"], "\xec" => [0, "\x1fr"], "\xed" => [0, "\x1fu"], "\xee" => [100, "\x1f"], "\xef" => [110, "\x1f"], "\xf0" => [111, "\x1f"], "\xf1" => [115, "\x1f"], "\xf2" => [116, "\x1f"], "\xf3" => [118, "\x1f"], "\xf4" => [119, "\x1f"], "\xf5" => [122, "\x1f"], "\xf6" => [123, "\x1f"], "\xf7" => [125, "\x1f"], "\xf8" => [126, "\x1f"], "\xf9" => [129, "\x1f"], "\xfa" => [143, "\x1f"], "\xfb" => [148, "\x1f"], "\xfc" => [151, "\x1f"], "\xfd" => [153, "\x1f"], "\xfe" => [83, "\x1f"], "\xff" => [10, "\x1f"]], ["\x00" => [94, "\x1e0"], "\x01" => [76, "\x1e0"], "\x02" => [104, "\x1e0"], "\x03" => [16, "\x1e0"], "\x04" => [94, "\x1e1"], "\x05" => [76, "\x1e1"], "\x06" => [104, "\x1e1"], "\x07" => [16, "\x1e1"], "\x08" => [94, "\x1e2"], "\t" => [76, "\x1e2"], "\n" => [104, "\x1e2"], "\v" => [16, "\x1e2"], "\f" => [94, "\x1ea"], "\r" => [76, "\x1ea"], "\x0e" => [104, "\x1ea"], "\x0f" => [16, "\x1ea"], "\x10" => [94, "\x1ec"], "\x11" => [76, "\x1ec"], "\x12" => [104, "\x1ec"], "\x13" => [16, "\x1ec"], "\x14" => [94, "\x1ee"], "\x15" => [76, "\x1ee"], "\x16" => [104, "\x1ee"], "\x17" => [16, "\x1ee"], "\x18" => [94, "\x1ei"], "\x19" => [76, "\x1ei"], "\x1a" => [104, "\x1ei"], "\x1b" => [16, "\x1ei"], "\x1c" => [94, "\x1eo"], "\x1d" => [76, "\x1eo"], "\x1e" => [104, "\x1eo"], "\x1f" => [16, "\x1eo"], " " => [94, "\x1es"], "!" => [76, "\x1es"], "\"" => [104, "\x1es"], "#" => [16, "\x1es"], "\$" => [94, "\x1et"], "%" => [76, "\x1et"], "&" => [104, "\x1et"], "'" => [16, "\x1et"], "(" => [77, "\x1e "], ")" => [18, "\x1e "], "*" => [77, "\x1e%"], "+" => [18, "\x1e%"], "," => [77, "\x1e-"], "-" => [18, "\x1e-"], "." => [77, "\x1e."], "/" => [18, "\x1e."], [77, "\x1e/"], [18, "\x1e/"], [77, "\x1e3"], [18, "\x1e3"], [77, "\x1e4"], [18, "\x1e4"], [77, "\x1e5"], [18, "\x1e5"], [77, "\x1e6"], [18, "\x1e6"], ":" => [77, "\x1e7"], ";" => [18, "\x1e7"], "<" => [77, "\x1e8"], "=" => [18, "\x1e8"], ">" => [77, "\x1e9"], "?" => [18, "\x1e9"], "@" => [77, "\x1e="], "A" => [18, "\x1e="], "B" => [77, "\x1eA"], "C" => [18, "\x1eA"], "D" => [77, "\x1e_"], "E" => [18, "\x1e_"], "F" => [77, "\x1eb"], "G" => [18, "\x1eb"], "H" => [77, "\x1ed"], "I" => [18, "\x1ed"], "J" => [77, "\x1ef"], "K" => [18, "\x1ef"], "L" => [77, "\x1eg"], "M" => [18, "\x1eg"], "N" => [77, "\x1eh"], "O" => [18, "\x1eh"], "P" => [77, "\x1el"], "Q" => [18, "\x1el"], "R" => [77, "\x1em"], "S" => [18, "\x1em"], "T" => [77, "\x1en"], "U" => [18, "\x1en"], "V" => [77, "\x1ep"], "W" => [18, "\x1ep"], "X" => [77, "\x1er"], "Y" => [18, "\x1er"], "Z" => [77, "\x1eu"], "[" => [18, "\x1eu"], "\\" => [0, "\x1e:"], "]" => [0, "\x1eB"], "^" => [0, "\x1eC"], "_" => [0, "\x1eD"], "`" => [0, "\x1eE"], "a" => [0, "\x1eF"], "b" => [0, "\x1eG"], "c" => [0, "\x1eH"], "d" => [0, "\x1eI"], "e" => [0, "\x1eJ"], "f" => [0, "\x1eK"], "g" => [0, "\x1eL"], "h" => [0, "\x1eM"], "i" => [0, "\x1eN"], "j" => [0, "\x1eO"], "k" => [0, "\x1eP"], "l" => [0, "\x1eQ"], "m" => [0, "\x1eR"], "n" => [0, "\x1eS"], "o" => [0, "\x1eT"], "p" => [0, "\x1eU"], "q" => [0, "\x1eV"], "r" => [0, "\x1eW"], "s" => [0, "\x1eY"], "t" => [0, "\x1ej"], "u" => [0, "\x1ek"], "v" => [0, "\x1eq"], "w" => [0, "\x1ev"], "x" => [0, "\x1ew"], "y" => [0, "\x1ex"], "z" => [0, "\x1ey"], "{" => [0, "\x1ez"], "|" => [82, "\x1e"], "}" => [87, "\x1e"], "~" => [130, "\x1e"], "" => [9, "\x1e"], "\x80" => [94, "\x1f0"], "\x81" => [76, "\x1f0"], "\x82" => [104, "\x1f0"], "\x83" => [16, "\x1f0"], "\x84" => [94, "\x1f1"], "\x85" => [76, "\x1f1"], "\x86" => [104, "\x1f1"], "\x87" => [16, "\x1f1"], "\x88" => [94, "\x1f2"], "\x89" => [76, "\x1f2"], "\x8a" => [104, "\x1f2"], "\x8b" => [16, "\x1f2"], "\x8c" => [94, "\x1fa"], "\x8d" => [76, "\x1fa"], "\x8e" => [104, "\x1fa"], "\x8f" => [16, "\x1fa"], "\x90" => [94, "\x1fc"], "\x91" => [76, "\x1fc"], "\x92" => [104, "\x1fc"], "\x93" => [16, "\x1fc"], "\x94" => [94, "\x1fe"], "\x95" => [76, "\x1fe"], "\x96" => [104, "\x1fe"], "\x97" => [16, "\x1fe"], "\x98" => [94, "\x1fi"], "\x99" => [76, "\x1fi"], "\x9a" => [104, "\x1fi"], "\x9b" => [16, "\x1fi"], "\x9c" => [94, "\x1fo"], "\x9d" => [76, "\x1fo"], "\x9e" => [104, "\x1fo"], "\x9f" => [16, "\x1fo"], "\xa0" => [94, "\x1fs"], "\xa1" => [76, "\x1fs"], "\xa2" => [104, "\x1fs"], "\xa3" => [16, "\x1fs"], "\xa4" => [94, "\x1ft"], "\xa5" => [76, "\x1ft"], "\xa6" => [104, "\x1ft"], "\xa7" => [16, "\x1ft"], "\xa8" => [77, "\x1f "], "\xa9" => [18, "\x1f "], "\xaa" => [77, "\x1f%"], "\xab" => [18, "\x1f%"], "\xac" => [77, "\x1f-"], "\xad" => [18, "\x1f-"], "\xae" => [77, "\x1f."], "\xaf" => [18, "\x1f."], "\xb0" => [77, "\x1f/"], "\xb1" => [18, "\x1f/"], "\xb2" => [77, "\x1f3"], "\xb3" => [18, "\x1f3"], "\xb4" => [77, "\x1f4"], "\xb5" => [18, "\x1f4"], "\xb6" => [77, "\x1f5"], "\xb7" => [18, "\x1f5"], "\xb8" => [77, "\x1f6"], "\xb9" => [18, "\x1f6"], "\xba" => [77, "\x1f7"], "\xbb" => [18, "\x1f7"], "\xbc" => [77, "\x1f8"], "\xbd" => [18, "\x1f8"], "\xbe" => [77, "\x1f9"], "\xbf" => [18, "\x1f9"], "\xc0" => [77, "\x1f="], "\xc1" => [18, "\x1f="], "\xc2" => [77, "\x1fA"], "\xc3" => [18, "\x1fA"], "\xc4" => [77, "\x1f_"], "\xc5" => [18, "\x1f_"], "\xc6" => [77, "\x1fb"], "\xc7" => [18, "\x1fb"], "\xc8" => [77, "\x1fd"], "\xc9" => [18, "\x1fd"], "\xca" => [77, "\x1ff"], "\xcb" => [18, "\x1ff"], "\xcc" => [77, "\x1fg"], "\xcd" => [18, "\x1fg"], "\xce" => [77, "\x1fh"], "\xcf" => [18, "\x1fh"], "\xd0" => [77, "\x1fl"], "\xd1" => [18, "\x1fl"], "\xd2" => [77, "\x1fm"], "\xd3" => [18, "\x1fm"], "\xd4" => [77, "\x1fn"], "\xd5" => [18, "\x1fn"], "\xd6" => [77, "\x1fp"], "\xd7" => [18, "\x1fp"], "\xd8" => [77, "\x1fr"], "\xd9" => [18, "\x1fr"], "\xda" => [77, "\x1fu"], "\xdb" => [18, "\x1fu"], "\xdc" => [0, "\x1f:"], "\xdd" => [0, "\x1fB"], "\xde" => [0, "\x1fC"], "\xdf" => [0, "\x1fD"], "\xe0" => [0, "\x1fE"], "\xe1" => [0, "\x1fF"], "\xe2" => [0, "\x1fG"], "\xe3" => [0, "\x1fH"], "\xe4" => [0, "\x1fI"], "\xe5" => [0, "\x1fJ"], "\xe6" => [0, "\x1fK"], "\xe7" => [0, "\x1fL"], "\xe8" => [0, "\x1fM"], "\xe9" => [0, "\x1fN"], "\xea" => [0, "\x1fO"], "\xeb" => [0, "\x1fP"], "\xec" => [0, "\x1fQ"], "\xed" => [0, "\x1fR"], "\xee" => [0, "\x1fS"], "\xef" => [0, "\x1fT"], "\xf0" => [0, "\x1fU"], "\xf1" => [0, "\x1fV"], "\xf2" => [0, "\x1fW"], "\xf3" => [0, "\x1fY"], "\xf4" => [0, "\x1fj"], "\xf5" => [0, "\x1fk"], "\xf6" => [0, "\x1fq"], "\xf7" => [0, "\x1fv"], "\xf8" => [0, "\x1fw"], "\xf9" => [0, "\x1fx"], "\xfa" => [0, "\x1fy"], "\xfb" => [0, "\x1fz"], "\xfc" => [82, "\x1f"], "\xfd" => [87, "\x1f"], "\xfe" => [130, "\x1f"], "\xff" => [9, "\x1f"]], ["\x00" => [94, " 0"], "\x01" => [76, " 0"], "\x02" => [104, " 0"], "\x03" => [16, " 0"], "\x04" => [94, " 1"], "\x05" => [76, " 1"], "\x06" => [104, " 1"], "\x07" => [16, " 1"], "\x08" => [94, " 2"], "\t" => [76, " 2"], "\n" => [104, " 2"], "\v" => [16, " 2"], "\f" => [94, " a"], "\r" => [76, " a"], "\x0e" => [104, " a"], "\x0f" => [16, " a"], "\x10" => [94, " c"], "\x11" => [76, " c"], "\x12" => [104, " c"], "\x13" => [16, " c"], "\x14" => [94, " e"], "\x15" => [76, " e"], "\x16" => [104, " e"], "\x17" => [16, " e"], "\x18" => [94, " i"], "\x19" => [76, " i"], "\x1a" => [104, " i"], "\x1b" => [16, " i"], "\x1c" => [94, " o"], "\x1d" => [76, " o"], "\x1e" => [104, " o"], "\x1f" => [16, " o"], " " => [94, " s"], "!" => [76, " s"], "\"" => [104, " s"], "#" => [16, " s"], "\$" => [94, " t"], "%" => [76, " t"], "&" => [104, " t"], "'" => [16, " t"], "(" => [77, "  "], ")" => [18, "  "], "*" => [77, " %"], "+" => [18, " %"], "," => [77, " -"], "-" => [18, " -"], "." => [77, " ."], "/" => [18, " ."], [77, " /"], [18, " /"], [77, " 3"], [18, " 3"], [77, " 4"], [18, " 4"], [77, " 5"], [18, " 5"], [77, " 6"], [18, " 6"], ":" => [77, " 7"], ";" => [18, " 7"], "<" => [77, " 8"], "=" => [18, " 8"], ">" => [77, " 9"], "?" => [18, " 9"], "@" => [77, " ="], "A" => [18, " ="], "B" => [77, " A"], "C" => [18, " A"], "D" => [77, " _"], "E" => [18, " _"], "F" => [77, " b"], "G" => [18, " b"], "H" => [77, " d"], "I" => [18, " d"], "J" => [77, " f"], "K" => [18, " f"], "L" => [77, " g"], "M" => [18, " g"], "N" => [77, " h"], "O" => [18, " h"], "P" => [77, " l"], "Q" => [18, " l"], "R" => [77, " m"], "S" => [18, " m"], "T" => [77, " n"], "U" => [18, " n"], "V" => [77, " p"], "W" => [18, " p"], "X" => [77, " r"], "Y" => [18, " r"], "Z" => [77, " u"], "[" => [18, " u"], "\\" => [0, " :"], "]" => [0, " B"], "^" => [0, " C"], "_" => [0, " D"], "`" => [0, " E"], "a" => [0, " F"], "b" => [0, " G"], "c" => [0, " H"], "d" => [0, " I"], "e" => [0, " J"], "f" => [0, " K"], "g" => [0, " L"], "h" => [0, " M"], "i" => [0, " N"], "j" => [0, " O"], "k" => [0, " P"], "l" => [0, " Q"], "m" => [0, " R"], "n" => [0, " S"], "o" => [0, " T"], "p" => [0, " U"], "q" => [0, " V"], "r" => [0, " W"], "s" => [0, " Y"], "t" => [0, " j"], "u" => [0, " k"], "v" => [0, " q"], "w" => [0, " v"], "x" => [0, " w"], "y" => [0, " x"], "z" => [0, " y"], "{" => [0, " z"], "|" => [82, " "], "}" => [87, " "], "~" => [130, " "], "" => [9, " "], "\x80" => [94, "%0"], "\x81" => [76, "%0"], "\x82" => [104, "%0"], "\x83" => [16, "%0"], "\x84" => [94, "%1"], "\x85" => [76, "%1"], "\x86" => [104, "%1"], "\x87" => [16, "%1"], "\x88" => [94, "%2"], "\x89" => [76, "%2"], "\x8a" => [104, "%2"], "\x8b" => [16, "%2"], "\x8c" => [94, "%a"], "\x8d" => [76, "%a"], "\x8e" => [104, "%a"], "\x8f" => [16, "%a"], "\x90" => [94, "%c"], "\x91" => [76, "%c"], "\x92" => [104, "%c"], "\x93" => [16, "%c"], "\x94" => [94, "%e"], "\x95" => [76, "%e"], "\x96" => [104, "%e"], "\x97" => [16, "%e"], "\x98" => [94, "%i"], "\x99" => [76, "%i"], "\x9a" => [104, "%i"], "\x9b" => [16, "%i"], "\x9c" => [94, "%o"], "\x9d" => [76, "%o"], "\x9e" => [104, "%o"], "\x9f" => [16, "%o"], "\xa0" => [94, "%s"], "\xa1" => [76, "%s"], "\xa2" => [104, "%s"], "\xa3" => [16, "%s"], "\xa4" => [94, "%t"], "\xa5" => [76, "%t"], "\xa6" => [104, "%t"], "\xa7" => [16, "%t"], "\xa8" => [77, "% "], "\xa9" => [18, "% "], "\xaa" => [77, "%%"], "\xab" => [18, "%%"], "\xac" => [77, "%-"], "\xad" => [18, "%-"], "\xae" => [77, "%."], "\xaf" => [18, "%."], "\xb0" => [77, "%/"], "\xb1" => [18, "%/"], "\xb2" => [77, "%3"], "\xb3" => [18, "%3"], "\xb4" => [77, "%4"], "\xb5" => [18, "%4"], "\xb6" => [77, "%5"], "\xb7" => [18, "%5"], "\xb8" => [77, "%6"], "\xb9" => [18, "%6"], "\xba" => [77, "%7"], "\xbb" => [18, "%7"], "\xbc" => [77, "%8"], "\xbd" => [18, "%8"], "\xbe" => [77, "%9"], "\xbf" => [18, "%9"], "\xc0" => [77, "%="], "\xc1" => [18, "%="], "\xc2" => [77, "%A"], "\xc3" => [18, "%A"], "\xc4" => [77, "%_"], "\xc5" => [18, "%_"], "\xc6" => [77, "%b"], "\xc7" => [18, "%b"], "\xc8" => [77, "%d"], "\xc9" => [18, "%d"], "\xca" => [77, "%f"], "\xcb" => [18, "%f"], "\xcc" => [77, "%g"], "\xcd" => [18, "%g"], "\xce" => [77, "%h"], "\xcf" => [18, "%h"], "\xd0" => [77, "%l"], "\xd1" => [18, "%l"], "\xd2" => [77, "%m"], "\xd3" => [18, "%m"], "\xd4" => [77, "%n"], "\xd5" => [18, "%n"], "\xd6" => [77, "%p"], "\xd7" => [18, "%p"], "\xd8" => [77, "%r"], "\xd9" => [18, "%r"], "\xda" => [77, "%u"], "\xdb" => [18, "%u"], "\xdc" => [0, "%:"], "\xdd" => [0, "%B"], "\xde" => [0, "%C"], "\xdf" => [0, "%D"], "\xe0" => [0, "%E"], "\xe1" => [0, "%F"], "\xe2" => [0, "%G"], "\xe3" => [0, "%H"], "\xe4" => [0, "%I"], "\xe5" => [0, "%J"], "\xe6" => [0, "%K"], "\xe7" => [0, "%L"], "\xe8" => [0, "%M"], "\xe9" => [0, "%N"], "\xea" => [0, "%O"], "\xeb" => [0, "%P"], "\xec" => [0, "%Q"], "\xed" => [0, "%R"], "\xee" => [0, "%S"], "\xef" => [0, "%T"], "\xf0" => [0, "%U"], "\xf1" => [0, "%V"], "\xf2" => [0, "%W"], "\xf3" => [0, "%Y"], "\xf4" => [0, "%j"], "\xf5" => [0, "%k"], "\xf6" => [0, "%q"], "\xf7" => [0, "%v"], "\xf8" => [0, "%w"], "\xf9" => [0, "%x"], "\xfa" => [0, "%y"], "\xfb" => [0, "%z"], "\xfc" => [82, "%"], "\xfd" => [87, "%"], "\xfe" => [130, "%"], "\xff" => [9, "%"]], ["\x00" => [77, " 0"], "\x01" => [18, " 0"], "\x02" => [77, " 1"], "\x03" => [18, " 1"], "\x04" => [77, " 2"], "\x05" => [18, " 2"], "\x06" => [77, " a"], "\x07" => [18, " a"], "\x08" => [77, " c"], "\t" => [18, " c"], "\n" => [77, " e"], "\v" => [18, " e"], "\f" => [77, " i"], "\r" => [18, " i"], "\x0e" => [77, " o"], "\x0f" => [18, " o"], "\x10" => [77, " s"], "\x11" => [18, " s"], "\x12" => [77, " t"], "\x13" => [18, " t"], "\x14" => [0, "  "], "\x15" => [0, " %"], "\x16" => [0, " -"], "\x17" => [0, " ."], "\x18" => [0, " /"], "\x19" => [0, " 3"], "\x1a" => [0, " 4"], "\x1b" => [0, " 5"], "\x1c" => [0, " 6"], "\x1d" => [0, " 7"], "\x1e" => [0, " 8"], "\x1f" => [0, " 9"], " " => [0, " ="], "!" => [0, " A"], "\"" => [0, " _"], "#" => [0, " b"], "\$" => [0, " d"], "%" => [0, " f"], "&" => [0, " g"], "'" => [0, " h"], "(" => [0, " l"], ")" => [0, " m"], "*" => [0, " n"], "+" => [0, " p"], "," => [0, " r"], "-" => [0, " u"], "." => [100, " "], "/" => [110, " "], [111, " "], [115, " "], [116, " "], [118, " "], [119, " "], [122, " "], [123, " "], [125, " "], [126, " "], [129, " "], ":" => [143, " "], ";" => [148, " "], "<" => [151, " "], "=" => [153, " "], ">" => [83, " "], "?" => [10, " "], "@" => [77, "%0"], "A" => [18, "%0"], "B" => [77, "%1"], "C" => [18, "%1"], "D" => [77, "%2"], "E" => [18, "%2"], "F" => [77, "%a"], "G" => [18, "%a"], "H" => [77, "%c"], "I" => [18, "%c"], "J" => [77, "%e"], "K" => [18, "%e"], "L" => [77, "%i"], "M" => [18, "%i"], "N" => [77, "%o"], "O" => [18, "%o"], "P" => [77, "%s"], "Q" => [18, "%s"], "R" => [77, "%t"], "S" => [18, "%t"], "T" => [0, "% "], "U" => [0, "%%"], "V" => [0, "%-"], "W" => [0, "%."], "X" => [0, "%/"], "Y" => [0, "%3"], "Z" => [0, "%4"], "[" => [0, "%5"], "\\" => [0, "%6"], "]" => [0, "%7"], "^" => [0, "%8"], "_" => [0, "%9"], "`" => [0, "%="], "a" => [0, "%A"], "b" => [0, "%_"], "c" => [0, "%b"], "d" => [0, "%d"], "e" => [0, "%f"], "f" => [0, "%g"], "g" => [0, "%h"], "h" => [0, "%l"], "i" => [0, "%m"], "j" => [0, "%n"], "k" => [0, "%p"], "l" => [0, "%r"], "m" => [0, "%u"], "n" => [100, "%"], "o" => [110, "%"], "p" => [111, "%"], "q" => [115, "%"], "r" => [116, "%"], "s" => [118, "%"], "t" => [119, "%"], "u" => [122, "%"], "v" => [123, "%"], "w" => [125, "%"], "x" => [126, "%"], "y" => [129, "%"], "z" => [143, "%"], "{" => [148, "%"], "|" => [151, "%"], "}" => [153, "%"], "~" => [83, "%"], "" => [10, "%"], "\x80" => [77, "-0"], "\x81" => [18, "-0"], "\x82" => [77, "-1"], "\x83" => [18, "-1"], "\x84" => [77, "-2"], "\x85" => [18, "-2"], "\x86" => [77, "-a"], "\x87" => [18, "-a"], "\x88" => [77, "-c"], "\x89" => [18, "-c"], "\x8a" => [77, "-e"], "\x8b" => [18, "-e"], "\x8c" => [77, "-i"], "\x8d" => [18, "-i"], "\x8e" => [77, "-o"], "\x8f" => [18, "-o"], "\x90" => [77, "-s"], "\x91" => [18, "-s"], "\x92" => [77, "-t"], "\x93" => [18, "-t"], "\x94" => [0, "- "], "\x95" => [0, "-%"], "\x96" => [0, "--"], "\x97" => [0, "-."], "\x98" => [0, "-/"], "\x99" => [0, "-3"], "\x9a" => [0, "-4"], "\x9b" => [0, "-5"], "\x9c" => [0, "-6"], "\x9d" => [0, "-7"], "\x9e" => [0, "-8"], "\x9f" => [0, "-9"], "\xa0" => [0, "-="], "\xa1" => [0, "-A"], "\xa2" => [0, "-_"], "\xa3" => [0, "-b"], "\xa4" => [0, "-d"], "\xa5" => [0, "-f"], "\xa6" => [0, "-g"], "\xa7" => [0, "-h"], "\xa8" => [0, "-l"], "\xa9" => [0, "-m"], "\xaa" => [0, "-n"], "\xab" => [0, "-p"], "\xac" => [0, "-r"], "\xad" => [0, "-u"], "\xae" => [100, "-"], "\xaf" => [110, "-"], "\xb0" => [111, "-"], "\xb1" => [115, "-"], "\xb2" => [116, "-"], "\xb3" => [118, "-"], "\xb4" => [119, "-"], "\xb5" => [122, "-"], "\xb6" => [123, "-"], "\xb7" => [125, "-"], "\xb8" => [126, "-"], "\xb9" => [129, "-"], "\xba" => [143, "-"], "\xbb" => [148, "-"], "\xbc" => [151, "-"], "\xbd" => [153, "-"], "\xbe" => [83, "-"], "\xbf" => [10, "-"], "\xc0" => [77, ".0"], "\xc1" => [18, ".0"], "\xc2" => [77, ".1"], "\xc3" => [18, ".1"], "\xc4" => [77, ".2"], "\xc5" => [18, ".2"], "\xc6" => [77, ".a"], "\xc7" => [18, ".a"], "\xc8" => [77, ".c"], "\xc9" => [18, ".c"], "\xca" => [77, ".e"], "\xcb" => [18, ".e"], "\xcc" => [77, ".i"], "\xcd" => [18, ".i"], "\xce" => [77, ".o"], "\xcf" => [18, ".o"], "\xd0" => [77, ".s"], "\xd1" => [18, ".s"], "\xd2" => [77, ".t"], "\xd3" => [18, ".t"], "\xd4" => [0, ". "], "\xd5" => [0, ".%"], "\xd6" => [0, ".-"], "\xd7" => [0, ".."], "\xd8" => [0, "./"], "\xd9" => [0, ".3"], "\xda" => [0, ".4"], "\xdb" => [0, ".5"], "\xdc" => [0, ".6"], "\xdd" => [0, ".7"], "\xde" => [0, ".8"], "\xdf" => [0, ".9"], "\xe0" => [0, ".="], "\xe1" => [0, ".A"], "\xe2" => [0, "._"], "\xe3" => [0, ".b"], "\xe4" => [0, ".d"], "\xe5" => [0, ".f"], "\xe6" => [0, ".g"], "\xe7" => [0, ".h"], "\xe8" => [0, ".l"], "\xe9" => [0, ".m"], "\xea" => [0, ".n"], "\xeb" => [0, ".p"], "\xec" => [0, ".r"], "\xed" => [0, ".u"], "\xee" => [100, "."], "\xef" => [110, "."], "\xf0" => [111, "."], "\xf1" => [115, "."], "\xf2" => [116, "."], "\xf3" => [118, "."], "\xf4" => [119, "."], "\xf5" => [122, "."], "\xf6" => [123, "."], "\xf7" => [125, "."], "\xf8" => [126, "."], "\xf9" => [129, "."], "\xfa" => [143, "."], "\xfb" => [148, "."], "\xfc" => [151, "."], "\xfd" => [153, "."], "\xfe" => [83, "."], "\xff" => [10, "."]], ["\x00" => [77, "s0"], "\x01" => [18, "s0"], "\x02" => [77, "s1"], "\x03" => [18, "s1"], "\x04" => [77, "s2"], "\x05" => [18, "s2"], "\x06" => [77, "sa"], "\x07" => [18, "sa"], "\x08" => [77, "sc"], "\t" => [18, "sc"], "\n" => [77, "se"], "\v" => [18, "se"], "\f" => [77, "si"], "\r" => [18, "si"], "\x0e" => [77, "so"], "\x0f" => [18, "so"], "\x10" => [77, "ss"], "\x11" => [18, "ss"], "\x12" => [77, "st"], "\x13" => [18, "st"], "\x14" => [0, "s "], "\x15" => [0, "s%"], "\x16" => [0, "s-"], "\x17" => [0, "s."], "\x18" => [0, "s/"], "\x19" => [0, "s3"], "\x1a" => [0, "s4"], "\x1b" => [0, "s5"], "\x1c" => [0, "s6"], "\x1d" => [0, "s7"], "\x1e" => [0, "s8"], "\x1f" => [0, "s9"], " " => [0, "s="], "!" => [0, "sA"], "\"" => [0, "s_"], "#" => [0, "sb"], "\$" => [0, "sd"], "%" => [0, "sf"], "&" => [0, "sg"], "'" => [0, "sh"], "(" => [0, "sl"], ")" => [0, "sm"], "*" => [0, "sn"], "+" => [0, "sp"], "," => [0, "sr"], "-" => [0, "su"], "." => [100, "s"], "/" => [110, "s"], [111, "s"], [115, "s"], [116, "s"], [118, "s"], [119, "s"], [122, "s"], [123, "s"], [125, "s"], [126, "s"], [129, "s"], ":" => [143, "s"], ";" => [148, "s"], "<" => [151, "s"], "=" => [153, "s"], ">" => [83, "s"], "?" => [10, "s"], "@" => [77, "t0"], "A" => [18, "t0"], "B" => [77, "t1"], "C" => [18, "t1"], "D" => [77, "t2"], "E" => [18, "t2"], "F" => [77, "ta"], "G" => [18, "ta"], "H" => [77, "tc"], "I" => [18, "tc"], "J" => [77, "te"], "K" => [18, "te"], "L" => [77, "ti"], "M" => [18, "ti"], "N" => [77, "to"], "O" => [18, "to"], "P" => [77, "ts"], "Q" => [18, "ts"], "R" => [77, "tt"], "S" => [18, "tt"], "T" => [0, "t "], "U" => [0, "t%"], "V" => [0, "t-"], "W" => [0, "t."], "X" => [0, "t/"], "Y" => [0, "t3"], "Z" => [0, "t4"], "[" => [0, "t5"], "\\" => [0, "t6"], "]" => [0, "t7"], "^" => [0, "t8"], "_" => [0, "t9"], "`" => [0, "t="], "a" => [0, "tA"], "b" => [0, "t_"], "c" => [0, "tb"], "d" => [0, "td"], "e" => [0, "tf"], "f" => [0, "tg"], "g" => [0, "th"], "h" => [0, "tl"], "i" => [0, "tm"], "j" => [0, "tn"], "k" => [0, "tp"], "l" => [0, "tr"], "m" => [0, "tu"], "n" => [100, "t"], "o" => [110, "t"], "p" => [111, "t"], "q" => [115, "t"], "r" => [116, "t"], "s" => [118, "t"], "t" => [119, "t"], "u" => [122, "t"], "v" => [123, "t"], "w" => [125, "t"], "x" => [126, "t"], "y" => [129, "t"], "z" => [143, "t"], "{" => [148, "t"], "|" => [151, "t"], "}" => [153, "t"], "~" => [83, "t"], "" => [10, "t"], "\x80" => [0, " 0"], "\x81" => [0, " 1"], "\x82" => [0, " 2"], "\x83" => [0, " a"], "\x84" => [0, " c"], "\x85" => [0, " e"], "\x86" => [0, " i"], "\x87" => [0, " o"], "\x88" => [0, " s"], "\x89" => [0, " t"], "\x8a" => [73, " "], "\x8b" => [88, " "], "\x8c" => [89, " "], "\x8d" => [96, " "], "\x8e" => [97, " "], "\x8f" => [99, " "], "\x90" => [106, " "], "\x91" => [136, " "], "\x92" => [139, " "], "\x93" => [141, " "], "\x94" => [145, " "], "\x95" => [147, " "], "\x96" => [149, " "], "\x97" => [101, " "], "\x98" => [112, " "], "\x99" => [117, " "], "\x9a" => [120, " "], "\x9b" => [124, " "], "\x9c" => [127, " "], "\x9d" => [144, " "], "\x9e" => [152, " "], "\x9f" => [11, " "], "\xa0" => [0, "%0"], "\xa1" => [0, "%1"], "\xa2" => [0, "%2"], "\xa3" => [0, "%a"], "\xa4" => [0, "%c"], "\xa5" => [0, "%e"], "\xa6" => [0, "%i"], "\xa7" => [0, "%o"], "\xa8" => [0, "%s"], "\xa9" => [0, "%t"], "\xaa" => [73, "%"], "\xab" => [88, "%"], "\xac" => [89, "%"], "\xad" => [96, "%"], "\xae" => [97, "%"], "\xaf" => [99, "%"], "\xb0" => [106, "%"], "\xb1" => [136, "%"], "\xb2" => [139, "%"], "\xb3" => [141, "%"], "\xb4" => [145, "%"], "\xb5" => [147, "%"], "\xb6" => [149, "%"], "\xb7" => [101, "%"], "\xb8" => [112, "%"], "\xb9" => [117, "%"], "\xba" => [120, "%"], "\xbb" => [124, "%"], "\xbc" => [127, "%"], "\xbd" => [144, "%"], "\xbe" => [152, "%"], "\xbf" => [11, "%"], "\xc0" => [0, "-0"], "\xc1" => [0, "-1"], "\xc2" => [0, "-2"], "\xc3" => [0, "-a"], "\xc4" => [0, "-c"], "\xc5" => [0, "-e"], "\xc6" => [0, "-i"], "\xc7" => [0, "-o"], "\xc8" => [0, "-s"], "\xc9" => [0, "-t"], "\xca" => [73, "-"], "\xcb" => [88, "-"], "\xcc" => [89, "-"], "\xcd" => [96, "-"], "\xce" => [97, "-"], "\xcf" => [99, "-"], "\xd0" => [106, "-"], "\xd1" => [136, "-"], "\xd2" => [139, "-"], "\xd3" => [141, "-"], "\xd4" => [145, "-"], "\xd5" => [147, "-"], "\xd6" => [149, "-"], "\xd7" => [101, "-"], "\xd8" => [112, "-"], "\xd9" => [117, "-"], "\xda" => [120, "-"], "\xdb" => [124, "-"], "\xdc" => [127, "-"], "\xdd" => [144, "-"], "\xde" => [152, "-"], "\xdf" => [11, "-"], "\xe0" => [0, ".0"], "\xe1" => [0, ".1"], "\xe2" => [0, ".2"], "\xe3" => [0, ".a"], "\xe4" => [0, ".c"], "\xe5" => [0, ".e"], "\xe6" => [0, ".i"], "\xe7" => [0, ".o"], "\xe8" => [0, ".s"], "\xe9" => [0, ".t"], "\xea" => [73, "."], "\xeb" => [88, "."], "\xec" => [89, "."], "\xed" => [96, "."], "\xee" => [97, "."], "\xef" => [99, "."], "\xf0" => [106, "."], "\xf1" => [136, "."], "\xf2" => [139, "."], "\xf3" => [141, "."], "\xf4" => [145, "."], "\xf5" => [147, "."], "\xf6" => [149, "."], "\xf7" => [101, "."], "\xf8" => [112, "."], "\xf9" => [117, "."], "\xfa" => [120, "."], "\xfb" => [124, "."], "\xfc" => [127, "."], "\xfd" => [144, "."], "\xfe" => [152, "."], "\xff" => [11, "."]], ["\x00" => [0, "s0"], "\x01" => [0, "s1"], "\x02" => [0, "s2"], "\x03" => [0, "sa"], "\x04" => [0, "sc"], "\x05" => [0, "se"], "\x06" => [0, "si"], "\x07" => [0, "so"], "\x08" => [0, "ss"], "\t" => [0, "st"], "\n" => [73, "s"], "\v" => [88, "s"], "\f" => [89, "s"], "\r" => [96, "s"], "\x0e" => [97, "s"], "\x0f" => [99, "s"], "\x10" => [106, "s"], "\x11" => [136, "s"], "\x12" => [139, "s"], "\x13" => [141, "s"], "\x14" => [145, "s"], "\x15" => [147, "s"], "\x16" => [149, "s"], "\x17" => [101, "s"], "\x18" => [112, "s"], "\x19" => [117, "s"], "\x1a" => [120, "s"], "\x1b" => [124, "s"], "\x1c" => [127, "s"], "\x1d" => [144, "s"], "\x1e" => [152, "s"], "\x1f" => [11, "s"], " " => [0, "t0"], "!" => [0, "t1"], "\"" => [0, "t2"], "#" => [0, "ta"], "\$" => [0, "tc"], "%" => [0, "te"], "&" => [0, "ti"], "'" => [0, "to"], "(" => [0, "ts"], ")" => [0, "tt"], "*" => [73, "t"], "+" => [88, "t"], "," => [89, "t"], "-" => [96, "t"], "." => [97, "t"], "/" => [99, "t"], [106, "t"], [136, "t"], [139, "t"], [141, "t"], [145, "t"], [147, "t"], [149, "t"], [101, "t"], [112, "t"], [117, "t"], ":" => [120, "t"], ";" => [124, "t"], "<" => [127, "t"], "=" => [144, "t"], ">" => [152, "t"], "?" => [11, "t"], "@" => [92, " "], "A" => [95, " "], "B" => [137, " "], "C" => [142, " "], "D" => [150, " "], "E" => [74, " "], "F" => [90, " "], "G" => [98, " "], "H" => [107, " "], "I" => [140, " "], "J" => [146, " "], "K" => [102, " "], "L" => [113, " "], "M" => [121, " "], "N" => [128, " "], "O" => [12, " "], "P" => [92, "%"], "Q" => [95, "%"], "R" => [137, "%"], "S" => [142, "%"], "T" => [150, "%"], "U" => [74, "%"], "V" => [90, "%"], "W" => [98, "%"], "X" => [107, "%"], "Y" => [140, "%"], "Z" => [146, "%"], "[" => [102, "%"], "\\" => [113, "%"], "]" => [121, "%"], "^" => [128, "%"], "_" => [12, "%"], "`" => [92, "-"], "a" => [95, "-"], "b" => [137, "-"], "c" => [142, "-"], "d" => [150, "-"], "e" => [74, "-"], "f" => [90, "-"], "g" => [98, "-"], "h" => [107, "-"], "i" => [140, "-"], "j" => [146, "-"], "k" => [102, "-"], "l" => [113, "-"], "m" => [121, "-"], "n" => [128, "-"], "o" => [12, "-"], "p" => [92, "."], "q" => [95, "."], "r" => [137, "."], "s" => [142, "."], "t" => [150, "."], "u" => [74, "."], "v" => [90, "."], "w" => [98, "."], "x" => [107, "."], "y" => [140, "."], "z" => [146, "."], "{" => [102, "."], "|" => [113, "."], "}" => [121, "."], "~" => [128, "."], "" => [12, "."], "\x80" => [92, "/"], "\x81" => [95, "/"], "\x82" => [137, "/"], "\x83" => [142, "/"], "\x84" => [150, "/"], "\x85" => [74, "/"], "\x86" => [90, "/"], "\x87" => [98, "/"], "\x88" => [107, "/"], "\x89" => [140, "/"], "\x8a" => [146, "/"], "\x8b" => [102, "/"], "\x8c" => [113, "/"], "\x8d" => [121, "/"], "\x8e" => [128, "/"], "\x8f" => [12, "/"], "\x90" => [92, "3"], "\x91" => [95, "3"], "\x92" => [137, "3"], "\x93" => [142, "3"], "\x94" => [150, "3"], "\x95" => [74, "3"], "\x96" => [90, "3"], "\x97" => [98, "3"], "\x98" => [107, "3"], "\x99" => [140, "3"], "\x9a" => [146, "3"], "\x9b" => [102, "3"], "\x9c" => [113, "3"], "\x9d" => [121, "3"], "\x9e" => [128, "3"], "\x9f" => [12, "3"], "\xa0" => [92, "4"], "\xa1" => [95, "4"], "\xa2" => [137, "4"], "\xa3" => [142, "4"], "\xa4" => [150, "4"], "\xa5" => [74, "4"], "\xa6" => [90, "4"], "\xa7" => [98, "4"], "\xa8" => [107, "4"], "\xa9" => [140, "4"], "\xaa" => [146, "4"], "\xab" => [102, "4"], "\xac" => [113, "4"], "\xad" => [121, "4"], "\xae" => [128, "4"], "\xaf" => [12, "4"], "\xb0" => [92, "5"], "\xb1" => [95, "5"], "\xb2" => [137, "5"], "\xb3" => [142, "5"], "\xb4" => [150, "5"], "\xb5" => [74, "5"], "\xb6" => [90, "5"], "\xb7" => [98, "5"], "\xb8" => [107, "5"], "\xb9" => [140, "5"], "\xba" => [146, "5"], "\xbb" => [102, "5"], "\xbc" => [113, "5"], "\xbd" => [121, "5"], "\xbe" => [128, "5"], "\xbf" => [12, "5"], "\xc0" => [92, "6"], "\xc1" => [95, "6"], "\xc2" => [137, "6"], "\xc3" => [142, "6"], "\xc4" => [150, "6"], "\xc5" => [74, "6"], "\xc6" => [90, "6"], "\xc7" => [98, "6"], "\xc8" => [107, "6"], "\xc9" => [140, "6"], "\xca" => [146, "6"], "\xcb" => [102, "6"], "\xcc" => [113, "6"], "\xcd" => [121, "6"], "\xce" => [128, "6"], "\xcf" => [12, "6"], "\xd0" => [92, "7"], "\xd1" => [95, "7"], "\xd2" => [137, "7"], "\xd3" => [142, "7"], "\xd4" => [150, "7"], "\xd5" => [74, "7"], "\xd6" => [90, "7"], "\xd7" => [98, "7"], "\xd8" => [107, "7"], "\xd9" => [140, "7"], "\xda" => [146, "7"], "\xdb" => [102, "7"], "\xdc" => [113, "7"], "\xdd" => [121, "7"], "\xde" => [128, "7"], "\xdf" => [12, "7"], "\xe0" => [92, "8"], "\xe1" => [95, "8"], "\xe2" => [137, "8"], "\xe3" => [142, "8"], "\xe4" => [150, "8"], "\xe5" => [74, "8"], "\xe6" => [90, "8"], "\xe7" => [98, "8"], "\xe8" => [107, "8"], "\xe9" => [140, "8"], "\xea" => [146, "8"], "\xeb" => [102, "8"], "\xec" => [113, "8"], "\xed" => [121, "8"], "\xee" => [128, "8"], "\xef" => [12, "8"], "\xf0" => [92, "9"], "\xf1" => [95, "9"], "\xf2" => [137, "9"], "\xf3" => [142, "9"], "\xf4" => [150, "9"], "\xf5" => [74, "9"], "\xf6" => [90, "9"], "\xf7" => [98, "9"], "\xf8" => [107, "9"], "\xf9" => [140, "9"], "\xfa" => [146, "9"], "\xfb" => [102, "9"], "\xfc" => [113, "9"], "\xfd" => [121, "9"], "\xfe" => [128, "9"], "\xff" => [12, "9"]], ["\x00" => [92, "0"], "\x01" => [95, "0"], "\x02" => [137, "0"], "\x03" => [142, "0"], "\x04" => [150, "0"], "\x05" => [74, "0"], "\x06" => [90, "0"], "\x07" => [98, "0"], "\x08" => [107, "0"], "\t" => [140, "0"], "\n" => [146, "0"], "\v" => [102, "0"], "\f" => [113, "0"], "\r" => [121, "0"], "\x0e" => [128, "0"], "\x0f" => [12, "0"], "\x10" => [92, "1"], "\x11" => [95, "1"], "\x12" => [137, "1"], "\x13" => [142, "1"], "\x14" => [150, "1"], "\x15" => [74, "1"], "\x16" => [90, "1"], "\x17" => [98, "1"], "\x18" => [107, "1"], "\x19" => [140, "1"], "\x1a" => [146, "1"], "\x1b" => [102, "1"], "\x1c" => [113, "1"], "\x1d" => [121, "1"], "\x1e" => [128, "1"], "\x1f" => [12, "1"], " " => [92, "2"], "!" => [95, "2"], "\"" => [137, "2"], "#" => [142, "2"], "\$" => [150, "2"], "%" => [74, "2"], "&" => [90, "2"], "'" => [98, "2"], "(" => [107, "2"], ")" => [140, "2"], "*" => [146, "2"], "+" => [102, "2"], "," => [113, "2"], "-" => [121, "2"], "." => [128, "2"], "/" => [12, "2"], [92, "a"], [95, "a"], [137, "a"], [142, "a"], [150, "a"], [74, "a"], [90, "a"], [98, "a"], [107, "a"], [140, "a"], ":" => [146, "a"], ";" => [102, "a"], "<" => [113, "a"], "=" => [121, "a"], ">" => [128, "a"], "?" => [12, "a"], "@" => [92, "c"], "A" => [95, "c"], "B" => [137, "c"], "C" => [142, "c"], "D" => [150, "c"], "E" => [74, "c"], "F" => [90, "c"], "G" => [98, "c"], "H" => [107, "c"], "I" => [140, "c"], "J" => [146, "c"], "K" => [102, "c"], "L" => [113, "c"], "M" => [121, "c"], "N" => [128, "c"], "O" => [12, "c"], "P" => [92, "e"], "Q" => [95, "e"], "R" => [137, "e"], "S" => [142, "e"], "T" => [150, "e"], "U" => [74, "e"], "V" => [90, "e"], "W" => [98, "e"], "X" => [107, "e"], "Y" => [140, "e"], "Z" => [146, "e"], "[" => [102, "e"], "\\" => [113, "e"], "]" => [121, "e"], "^" => [128, "e"], "_" => [12, "e"], "`" => [92, "i"], "a" => [95, "i"], "b" => [137, "i"], "c" => [142, "i"], "d" => [150, "i"], "e" => [74, "i"], "f" => [90, "i"], "g" => [98, "i"], "h" => [107, "i"], "i" => [140, "i"], "j" => [146, "i"], "k" => [102, "i"], "l" => [113, "i"], "m" => [121, "i"], "n" => [128, "i"], "o" => [12, "i"], "p" => [92, "o"], "q" => [95, "o"], "r" => [137, "o"], "s" => [142, "o"], "t" => [150, "o"], "u" => [74, "o"], "v" => [90, "o"], "w" => [98, "o"], "x" => [107, "o"], "y" => [140, "o"], "z" => [146, "o"], "{" => [102, "o"], "|" => [113, "o"], "}" => [121, "o"], "~" => [128, "o"], "" => [12, "o"], "\x80" => [92, "s"], "\x81" => [95, "s"], "\x82" => [137, "s"], "\x83" => [142, "s"], "\x84" => [150, "s"], "\x85" => [74, "s"], "\x86" => [90, "s"], "\x87" => [98, "s"], "\x88" => [107, "s"], "\x89" => [140, "s"], "\x8a" => [146, "s"], "\x8b" => [102, "s"], "\x8c" => [113, "s"], "\x8d" => [121, "s"], "\x8e" => [128, "s"], "\x8f" => [12, "s"], "\x90" => [92, "t"], "\x91" => [95, "t"], "\x92" => [137, "t"], "\x93" => [142, "t"], "\x94" => [150, "t"], "\x95" => [74, "t"], "\x96" => [90, "t"], "\x97" => [98, "t"], "\x98" => [107, "t"], "\x99" => [140, "t"], "\x9a" => [146, "t"], "\x9b" => [102, "t"], "\x9c" => [113, "t"], "\x9d" => [121, "t"], "\x9e" => [128, "t"], "\x9f" => [12, "t"], "\xa0" => [93, " "], "\xa1" => [138, " "], "\xa2" => [75, " "], "\xa3" => [91, " "], "\xa4" => [108, " "], "\xa5" => [103, " "], "\xa6" => [114, " "], "\xa7" => [14, " "], "\xa8" => [93, "%"], "\xa9" => [138, "%"], "\xaa" => [75, "%"], "\xab" => [91, "%"], "\xac" => [108, "%"], "\xad" => [103, "%"], "\xae" => [114, "%"], "\xaf" => [14, "%"], "\xb0" => [93, "-"], "\xb1" => [138, "-"], "\xb2" => [75, "-"], "\xb3" => [91, "-"], "\xb4" => [108, "-"], "\xb5" => [103, "-"], "\xb6" => [114, "-"], "\xb7" => [14, "-"], "\xb8" => [93, "."], "\xb9" => [138, "."], "\xba" => [75, "."], "\xbb" => [91, "."], "\xbc" => [108, "."], "\xbd" => [103, "."], "\xbe" => [114, "."], "\xbf" => [14, "."], "\xc0" => [93, "/"], "\xc1" => [138, "/"], "\xc2" => [75, "/"], "\xc3" => [91, "/"], "\xc4" => [108, "/"], "\xc5" => [103, "/"], "\xc6" => [114, "/"], "\xc7" => [14, "/"], "\xc8" => [93, "3"], "\xc9" => [138, "3"], "\xca" => [75, "3"], "\xcb" => [91, "3"], "\xcc" => [108, "3"], "\xcd" => [103, "3"], "\xce" => [114, "3"], "\xcf" => [14, "3"], "\xd0" => [93, "4"], "\xd1" => [138, "4"], "\xd2" => [75, "4"], "\xd3" => [91, "4"], "\xd4" => [108, "4"], "\xd5" => [103, "4"], "\xd6" => [114, "4"], "\xd7" => [14, "4"], "\xd8" => [93, "5"], "\xd9" => [138, "5"], "\xda" => [75, "5"], "\xdb" => [91, "5"], "\xdc" => [108, "5"], "\xdd" => [103, "5"], "\xde" => [114, "5"], "\xdf" => [14, "5"], "\xe0" => [93, "6"], "\xe1" => [138, "6"], "\xe2" => [75, "6"], "\xe3" => [91, "6"], "\xe4" => [108, "6"], "\xe5" => [103, "6"], "\xe6" => [114, "6"], "\xe7" => [14, "6"], "\xe8" => [93, "7"], "\xe9" => [138, "7"], "\xea" => [75, "7"], "\xeb" => [91, "7"], "\xec" => [108, "7"], "\xed" => [103, "7"], "\xee" => [114, "7"], "\xef" => [14, "7"], "\xf0" => [93, "8"], "\xf1" => [138, "8"], "\xf2" => [75, "8"], "\xf3" => [91, "8"], "\xf4" => [108, "8"], "\xf5" => [103, "8"], "\xf6" => [114, "8"], "\xf7" => [14, "8"], "\xf8" => [93, "9"], "\xf9" => [138, "9"], "\xfa" => [75, "9"], "\xfb" => [91, "9"], "\xfc" => [108, "9"], "\xfd" => [103, "9"], "\xfe" => [114, "9"], "\xff" => [14, "9"]], ["\x00" => [77, "!0"], "\x01" => [18, "!0"], "\x02" => [77, "!1"], "\x03" => [18, "!1"], "\x04" => [77, "!2"], "\x05" => [18, "!2"], "\x06" => [77, "!a"], "\x07" => [18, "!a"], "\x08" => [77, "!c"], "\t" => [18, "!c"], "\n" => [77, "!e"], "\v" => [18, "!e"], "\f" => [77, "!i"], "\r" => [18, "!i"], "\x0e" => [77, "!o"], "\x0f" => [18, "!o"], "\x10" => [77, "!s"], "\x11" => [18, "!s"], "\x12" => [77, "!t"], "\x13" => [18, "!t"], "\x14" => [0, "! "], "\x15" => [0, "!%"], "\x16" => [0, "!-"], "\x17" => [0, "!."], "\x18" => [0, "!/"], "\x19" => [0, "!3"], "\x1a" => [0, "!4"], "\x1b" => [0, "!5"], "\x1c" => [0, "!6"], "\x1d" => [0, "!7"], "\x1e" => [0, "!8"], "\x1f" => [0, "!9"], " " => [0, "!="], "!" => [0, "!A"], "\"" => [0, "!_"], "#" => [0, "!b"], "\$" => [0, "!d"], "%" => [0, "!f"], "&" => [0, "!g"], "'" => [0, "!h"], "(" => [0, "!l"], ")" => [0, "!m"], "*" => [0, "!n"], "+" => [0, "!p"], "," => [0, "!r"], "-" => [0, "!u"], "." => [100, "!"], "/" => [110, "!"], [111, "!"], [115, "!"], [116, "!"], [118, "!"], [119, "!"], [122, "!"], [123, "!"], [125, "!"], [126, "!"], [129, "!"], ":" => [143, "!"], ";" => [148, "!"], "<" => [151, "!"], "=" => [153, "!"], ">" => [83, "!"], "?" => [10, "!"], "@" => [77, "\"0"], "A" => [18, "\"0"], "B" => [77, "\"1"], "C" => [18, "\"1"], "D" => [77, "\"2"], "E" => [18, "\"2"], "F" => [77, "\"a"], "G" => [18, "\"a"], "H" => [77, "\"c"], "I" => [18, "\"c"], "J" => [77, "\"e"], "K" => [18, "\"e"], "L" => [77, "\"i"], "M" => [18, "\"i"], "N" => [77, "\"o"], "O" => [18, "\"o"], "P" => [77, "\"s"], "Q" => [18, "\"s"], "R" => [77, "\"t"], "S" => [18, "\"t"], "T" => [0, "\" "], "U" => [0, "\"%"], "V" => [0, "\"-"], "W" => [0, "\"."], "X" => [0, "\"/"], "Y" => [0, "\"3"], "Z" => [0, "\"4"], "[" => [0, "\"5"], "\\" => [0, "\"6"], "]" => [0, "\"7"], "^" => [0, "\"8"], "_" => [0, "\"9"], "`" => [0, "\"="], "a" => [0, "\"A"], "b" => [0, "\"_"], "c" => [0, "\"b"], "d" => [0, "\"d"], "e" => [0, "\"f"], "f" => [0, "\"g"], "g" => [0, "\"h"], "h" => [0, "\"l"], "i" => [0, "\"m"], "j" => [0, "\"n"], "k" => [0, "\"p"], "l" => [0, "\"r"], "m" => [0, "\"u"], "n" => [100, "\""], "o" => [110, "\""], "p" => [111, "\""], "q" => [115, "\""], "r" => [116, "\""], "s" => [118, "\""], "t" => [119, "\""], "u" => [122, "\""], "v" => [123, "\""], "w" => [125, "\""], "x" => [126, "\""], "y" => [129, "\""], "z" => [143, "\""], "{" => [148, "\""], "|" => [151, "\""], "}" => [153, "\""], "~" => [83, "\""], "" => [10, "\""], "\x80" => [77, "(0"], "\x81" => [18, "(0"], "\x82" => [77, "(1"], "\x83" => [18, "(1"], "\x84" => [77, "(2"], "\x85" => [18, "(2"], "\x86" => [77, "(a"], "\x87" => [18, "(a"], "\x88" => [77, "(c"], "\x89" => [18, "(c"], "\x8a" => [77, "(e"], "\x8b" => [18, "(e"], "\x8c" => [77, "(i"], "\x8d" => [18, "(i"], "\x8e" => [77, "(o"], "\x8f" => [18, "(o"], "\x90" => [77, "(s"], "\x91" => [18, "(s"], "\x92" => [77, "(t"], "\x93" => [18, "(t"], "\x94" => [0, "( "], "\x95" => [0, "(%"], "\x96" => [0, "(-"], "\x97" => [0, "(."], "\x98" => [0, "(/"], "\x99" => [0, "(3"], "\x9a" => [0, "(4"], "\x9b" => [0, "(5"], "\x9c" => [0, "(6"], "\x9d" => [0, "(7"], "\x9e" => [0, "(8"], "\x9f" => [0, "(9"], "\xa0" => [0, "(="], "\xa1" => [0, "(A"], "\xa2" => [0, "(_"], "\xa3" => [0, "(b"], "\xa4" => [0, "(d"], "\xa5" => [0, "(f"], "\xa6" => [0, "(g"], "\xa7" => [0, "(h"], "\xa8" => [0, "(l"], "\xa9" => [0, "(m"], "\xaa" => [0, "(n"], "\xab" => [0, "(p"], "\xac" => [0, "(r"], "\xad" => [0, "(u"], "\xae" => [100, "("], "\xaf" => [110, "("], "\xb0" => [111, "("], "\xb1" => [115, "("], "\xb2" => [116, "("], "\xb3" => [118, "("], "\xb4" => [119, "("], "\xb5" => [122, "("], "\xb6" => [123, "("], "\xb7" => [125, "("], "\xb8" => [126, "("], "\xb9" => [129, "("], "\xba" => [143, "("], "\xbb" => [148, "("], "\xbc" => [151, "("], "\xbd" => [153, "("], "\xbe" => [83, "("], "\xbf" => [10, "("], "\xc0" => [77, ")0"], "\xc1" => [18, ")0"], "\xc2" => [77, ")1"], "\xc3" => [18, ")1"], "\xc4" => [77, ")2"], "\xc5" => [18, ")2"], "\xc6" => [77, ")a"], "\xc7" => [18, ")a"], "\xc8" => [77, ")c"], "\xc9" => [18, ")c"], "\xca" => [77, ")e"], "\xcb" => [18, ")e"], "\xcc" => [77, ")i"], "\xcd" => [18, ")i"], "\xce" => [77, ")o"], "\xcf" => [18, ")o"], "\xd0" => [77, ")s"], "\xd1" => [18, ")s"], "\xd2" => [77, ")t"], "\xd3" => [18, ")t"], "\xd4" => [0, ") "], "\xd5" => [0, ")%"], "\xd6" => [0, ")-"], "\xd7" => [0, ")."], "\xd8" => [0, ")/"], "\xd9" => [0, ")3"], "\xda" => [0, ")4"], "\xdb" => [0, ")5"], "\xdc" => [0, ")6"], "\xdd" => [0, ")7"], "\xde" => [0, ")8"], "\xdf" => [0, ")9"], "\xe0" => [0, ")="], "\xe1" => [0, ")A"], "\xe2" => [0, ")_"], "\xe3" => [0, ")b"], "\xe4" => [0, ")d"], "\xe5" => [0, ")f"], "\xe6" => [0, ")g"], "\xe7" => [0, ")h"], "\xe8" => [0, ")l"], "\xe9" => [0, ")m"], "\xea" => [0, ")n"], "\xeb" => [0, ")p"], "\xec" => [0, ")r"], "\xed" => [0, ")u"], "\xee" => [100, ")"], "\xef" => [110, ")"], "\xf0" => [111, ")"], "\xf1" => [115, ")"], "\xf2" => [116, ")"], "\xf3" => [118, ")"], "\xf4" => [119, ")"], "\xf5" => [122, ")"], "\xf6" => [123, ")"], "\xf7" => [125, ")"], "\xf8" => [126, ")"], "\xf9" => [129, ")"], "\xfa" => [143, ")"], "\xfb" => [148, ")"], "\xfc" => [151, ")"], "\xfd" => [153, ")"], "\xfe" => [83, ")"], "\xff" => [10, ")"]], ["\x00" => [94, "!0"], "\x01" => [76, "!0"], "\x02" => [104, "!0"], "\x03" => [16, "!0"], "\x04" => [94, "!1"], "\x05" => [76, "!1"], "\x06" => [104, "!1"], "\x07" => [16, "!1"], "\x08" => [94, "!2"], "\t" => [76, "!2"], "\n" => [104, "!2"], "\v" => [16, "!2"], "\f" => [94, "!a"], "\r" => [76, "!a"], "\x0e" => [104, "!a"], "\x0f" => [16, "!a"], "\x10" => [94, "!c"], "\x11" => [76, "!c"], "\x12" => [104, "!c"], "\x13" => [16, "!c"], "\x14" => [94, "!e"], "\x15" => [76, "!e"], "\x16" => [104, "!e"], "\x17" => [16, "!e"], "\x18" => [94, "!i"], "\x19" => [76, "!i"], "\x1a" => [104, "!i"], "\x1b" => [16, "!i"], "\x1c" => [94, "!o"], "\x1d" => [76, "!o"], "\x1e" => [104, "!o"], "\x1f" => [16, "!o"], " " => [94, "!s"], "!" => [76, "!s"], "\"" => [104, "!s"], "#" => [16, "!s"], "\$" => [94, "!t"], "%" => [76, "!t"], "&" => [104, "!t"], "'" => [16, "!t"], "(" => [77, "! "], ")" => [18, "! "], "*" => [77, "!%"], "+" => [18, "!%"], "," => [77, "!-"], "-" => [18, "!-"], "." => [77, "!."], "/" => [18, "!."], [77, "!/"], [18, "!/"], [77, "!3"], [18, "!3"], [77, "!4"], [18, "!4"], [77, "!5"], [18, "!5"], [77, "!6"], [18, "!6"], ":" => [77, "!7"], ";" => [18, "!7"], "<" => [77, "!8"], "=" => [18, "!8"], ">" => [77, "!9"], "?" => [18, "!9"], "@" => [77, "!="], "A" => [18, "!="], "B" => [77, "!A"], "C" => [18, "!A"], "D" => [77, "!_"], "E" => [18, "!_"], "F" => [77, "!b"], "G" => [18, "!b"], "H" => [77, "!d"], "I" => [18, "!d"], "J" => [77, "!f"], "K" => [18, "!f"], "L" => [77, "!g"], "M" => [18, "!g"], "N" => [77, "!h"], "O" => [18, "!h"], "P" => [77, "!l"], "Q" => [18, "!l"], "R" => [77, "!m"], "S" => [18, "!m"], "T" => [77, "!n"], "U" => [18, "!n"], "V" => [77, "!p"], "W" => [18, "!p"], "X" => [77, "!r"], "Y" => [18, "!r"], "Z" => [77, "!u"], "[" => [18, "!u"], "\\" => [0, "!:"], "]" => [0, "!B"], "^" => [0, "!C"], "_" => [0, "!D"], "`" => [0, "!E"], "a" => [0, "!F"], "b" => [0, "!G"], "c" => [0, "!H"], "d" => [0, "!I"], "e" => [0, "!J"], "f" => [0, "!K"], "g" => [0, "!L"], "h" => [0, "!M"], "i" => [0, "!N"], "j" => [0, "!O"], "k" => [0, "!P"], "l" => [0, "!Q"], "m" => [0, "!R"], "n" => [0, "!S"], "o" => [0, "!T"], "p" => [0, "!U"], "q" => [0, "!V"], "r" => [0, "!W"], "s" => [0, "!Y"], "t" => [0, "!j"], "u" => [0, "!k"], "v" => [0, "!q"], "w" => [0, "!v"], "x" => [0, "!w"], "y" => [0, "!x"], "z" => [0, "!y"], "{" => [0, "!z"], "|" => [82, "!"], "}" => [87, "!"], "~" => [130, "!"], "" => [9, "!"], "\x80" => [94, "\"0"], "\x81" => [76, "\"0"], "\x82" => [104, "\"0"], "\x83" => [16, "\"0"], "\x84" => [94, "\"1"], "\x85" => [76, "\"1"], "\x86" => [104, "\"1"], "\x87" => [16, "\"1"], "\x88" => [94, "\"2"], "\x89" => [76, "\"2"], "\x8a" => [104, "\"2"], "\x8b" => [16, "\"2"], "\x8c" => [94, "\"a"], "\x8d" => [76, "\"a"], "\x8e" => [104, "\"a"], "\x8f" => [16, "\"a"], "\x90" => [94, "\"c"], "\x91" => [76, "\"c"], "\x92" => [104, "\"c"], "\x93" => [16, "\"c"], "\x94" => [94, "\"e"], "\x95" => [76, "\"e"], "\x96" => [104, "\"e"], "\x97" => [16, "\"e"], "\x98" => [94, "\"i"], "\x99" => [76, "\"i"], "\x9a" => [104, "\"i"], "\x9b" => [16, "\"i"], "\x9c" => [94, "\"o"], "\x9d" => [76, "\"o"], "\x9e" => [104, "\"o"], "\x9f" => [16, "\"o"], "\xa0" => [94, "\"s"], "\xa1" => [76, "\"s"], "\xa2" => [104, "\"s"], "\xa3" => [16, "\"s"], "\xa4" => [94, "\"t"], "\xa5" => [76, "\"t"], "\xa6" => [104, "\"t"], "\xa7" => [16, "\"t"], "\xa8" => [77, "\" "], "\xa9" => [18, "\" "], "\xaa" => [77, "\"%"], "\xab" => [18, "\"%"], "\xac" => [77, "\"-"], "\xad" => [18, "\"-"], "\xae" => [77, "\"."], "\xaf" => [18, "\"."], "\xb0" => [77, "\"/"], "\xb1" => [18, "\"/"], "\xb2" => [77, "\"3"], "\xb3" => [18, "\"3"], "\xb4" => [77, "\"4"], "\xb5" => [18, "\"4"], "\xb6" => [77, "\"5"], "\xb7" => [18, "\"5"], "\xb8" => [77, "\"6"], "\xb9" => [18, "\"6"], "\xba" => [77, "\"7"], "\xbb" => [18, "\"7"], "\xbc" => [77, "\"8"], "\xbd" => [18, "\"8"], "\xbe" => [77, "\"9"], "\xbf" => [18, "\"9"], "\xc0" => [77, "\"="], "\xc1" => [18, "\"="], "\xc2" => [77, "\"A"], "\xc3" => [18, "\"A"], "\xc4" => [77, "\"_"], "\xc5" => [18, "\"_"], "\xc6" => [77, "\"b"], "\xc7" => [18, "\"b"], "\xc8" => [77, "\"d"], "\xc9" => [18, "\"d"], "\xca" => [77, "\"f"], "\xcb" => [18, "\"f"], "\xcc" => [77, "\"g"], "\xcd" => [18, "\"g"], "\xce" => [77, "\"h"], "\xcf" => [18, "\"h"], "\xd0" => [77, "\"l"], "\xd1" => [18, "\"l"], "\xd2" => [77, "\"m"], "\xd3" => [18, "\"m"], "\xd4" => [77, "\"n"], "\xd5" => [18, "\"n"], "\xd6" => [77, "\"p"], "\xd7" => [18, "\"p"], "\xd8" => [77, "\"r"], "\xd9" => [18, "\"r"], "\xda" => [77, "\"u"], "\xdb" => [18, "\"u"], "\xdc" => [0, "\":"], "\xdd" => [0, "\"B"], "\xde" => [0, "\"C"], "\xdf" => [0, "\"D"], "\xe0" => [0, "\"E"], "\xe1" => [0, "\"F"], "\xe2" => [0, "\"G"], "\xe3" => [0, "\"H"], "\xe4" => [0, "\"I"], "\xe5" => [0, "\"J"], "\xe6" => [0, "\"K"], "\xe7" => [0, "\"L"], "\xe8" => [0, "\"M"], "\xe9" => [0, "\"N"], "\xea" => [0, "\"O"], "\xeb" => [0, "\"P"], "\xec" => [0, "\"Q"], "\xed" => [0, "\"R"], "\xee" => [0, "\"S"], "\xef" => [0, "\"T"], "\xf0" => [0, "\"U"], "\xf1" => [0, "\"V"], "\xf2" => [0, "\"W"], "\xf3" => [0, "\"Y"], "\xf4" => [0, "\"j"], "\xf5" => [0, "\"k"], "\xf6" => [0, "\"q"], "\xf7" => [0, "\"v"], "\xf8" => [0, "\"w"], "\xf9" => [0, "\"x"], "\xfa" => [0, "\"y"], "\xfb" => [0, "\"z"], "\xfc" => [82, "\""], "\xfd" => [87, "\""], "\xfe" => [130, "\""], "\xff" => [9, "\""]], ["\x00" => [94, "#0"], "\x01" => [76, "#0"], "\x02" => [104, "#0"], "\x03" => [16, "#0"], "\x04" => [94, "#1"], "\x05" => [76, "#1"], "\x06" => [104, "#1"], "\x07" => [16, "#1"], "\x08" => [94, "#2"], "\t" => [76, "#2"], "\n" => [104, "#2"], "\v" => [16, "#2"], "\f" => [94, "#a"], "\r" => [76, "#a"], "\x0e" => [104, "#a"], "\x0f" => [16, "#a"], "\x10" => [94, "#c"], "\x11" => [76, "#c"], "\x12" => [104, "#c"], "\x13" => [16, "#c"], "\x14" => [94, "#e"], "\x15" => [76, "#e"], "\x16" => [104, "#e"], "\x17" => [16, "#e"], "\x18" => [94, "#i"], "\x19" => [76, "#i"], "\x1a" => [104, "#i"], "\x1b" => [16, "#i"], "\x1c" => [94, "#o"], "\x1d" => [76, "#o"], "\x1e" => [104, "#o"], "\x1f" => [16, "#o"], " " => [94, "#s"], "!" => [76, "#s"], "\"" => [104, "#s"], "#" => [16, "#s"], "\$" => [94, "#t"], "%" => [76, "#t"], "&" => [104, "#t"], "'" => [16, "#t"], "(" => [77, "# "], ")" => [18, "# "], "*" => [77, "#%"], "+" => [18, "#%"], "," => [77, "#-"], "-" => [18, "#-"], "." => [77, "#."], "/" => [18, "#."], [77, "#/"], [18, "#/"], [77, "#3"], [18, "#3"], [77, "#4"], [18, "#4"], [77, "#5"], [18, "#5"], [77, "#6"], [18, "#6"], ":" => [77, "#7"], ";" => [18, "#7"], "<" => [77, "#8"], "=" => [18, "#8"], ">" => [77, "#9"], "?" => [18, "#9"], "@" => [77, "#="], "A" => [18, "#="], "B" => [77, "#A"], "C" => [18, "#A"], "D" => [77, "#_"], "E" => [18, "#_"], "F" => [77, "#b"], "G" => [18, "#b"], "H" => [77, "#d"], "I" => [18, "#d"], "J" => [77, "#f"], "K" => [18, "#f"], "L" => [77, "#g"], "M" => [18, "#g"], "N" => [77, "#h"], "O" => [18, "#h"], "P" => [77, "#l"], "Q" => [18, "#l"], "R" => [77, "#m"], "S" => [18, "#m"], "T" => [77, "#n"], "U" => [18, "#n"], "V" => [77, "#p"], "W" => [18, "#p"], "X" => [77, "#r"], "Y" => [18, "#r"], "Z" => [77, "#u"], "[" => [18, "#u"], "\\" => [0, "#:"], "]" => [0, "#B"], "^" => [0, "#C"], "_" => [0, "#D"], "`" => [0, "#E"], "a" => [0, "#F"], "b" => [0, "#G"], "c" => [0, "#H"], "d" => [0, "#I"], "e" => [0, "#J"], "f" => [0, "#K"], "g" => [0, "#L"], "h" => [0, "#M"], "i" => [0, "#N"], "j" => [0, "#O"], "k" => [0, "#P"], "l" => [0, "#Q"], "m" => [0, "#R"], "n" => [0, "#S"], "o" => [0, "#T"], "p" => [0, "#U"], "q" => [0, "#V"], "r" => [0, "#W"], "s" => [0, "#Y"], "t" => [0, "#j"], "u" => [0, "#k"], "v" => [0, "#q"], "w" => [0, "#v"], "x" => [0, "#w"], "y" => [0, "#x"], "z" => [0, "#y"], "{" => [0, "#z"], "|" => [82, "#"], "}" => [87, "#"], "~" => [130, "#"], "" => [9, "#"], "\x80" => [94, ">0"], "\x81" => [76, ">0"], "\x82" => [104, ">0"], "\x83" => [16, ">0"], "\x84" => [94, ">1"], "\x85" => [76, ">1"], "\x86" => [104, ">1"], "\x87" => [16, ">1"], "\x88" => [94, ">2"], "\x89" => [76, ">2"], "\x8a" => [104, ">2"], "\x8b" => [16, ">2"], "\x8c" => [94, ">a"], "\x8d" => [76, ">a"], "\x8e" => [104, ">a"], "\x8f" => [16, ">a"], "\x90" => [94, ">c"], "\x91" => [76, ">c"], "\x92" => [104, ">c"], "\x93" => [16, ">c"], "\x94" => [94, ">e"], "\x95" => [76, ">e"], "\x96" => [104, ">e"], "\x97" => [16, ">e"], "\x98" => [94, ">i"], "\x99" => [76, ">i"], "\x9a" => [104, ">i"], "\x9b" => [16, ">i"], "\x9c" => [94, ">o"], "\x9d" => [76, ">o"], "\x9e" => [104, ">o"], "\x9f" => [16, ">o"], "\xa0" => [94, ">s"], "\xa1" => [76, ">s"], "\xa2" => [104, ">s"], "\xa3" => [16, ">s"], "\xa4" => [94, ">t"], "\xa5" => [76, ">t"], "\xa6" => [104, ">t"], "\xa7" => [16, ">t"], "\xa8" => [77, "> "], "\xa9" => [18, "> "], "\xaa" => [77, ">%"], "\xab" => [18, ">%"], "\xac" => [77, ">-"], "\xad" => [18, ">-"], "\xae" => [77, ">."], "\xaf" => [18, ">."], "\xb0" => [77, ">/"], "\xb1" => [18, ">/"], "\xb2" => [77, ">3"], "\xb3" => [18, ">3"], "\xb4" => [77, ">4"], "\xb5" => [18, ">4"], "\xb6" => [77, ">5"], "\xb7" => [18, ">5"], "\xb8" => [77, ">6"], "\xb9" => [18, ">6"], "\xba" => [77, ">7"], "\xbb" => [18, ">7"], "\xbc" => [77, ">8"], "\xbd" => [18, ">8"], "\xbe" => [77, ">9"], "\xbf" => [18, ">9"], "\xc0" => [77, ">="], "\xc1" => [18, ">="], "\xc2" => [77, ">A"], "\xc3" => [18, ">A"], "\xc4" => [77, ">_"], "\xc5" => [18, ">_"], "\xc6" => [77, ">b"], "\xc7" => [18, ">b"], "\xc8" => [77, ">d"], "\xc9" => [18, ">d"], "\xca" => [77, ">f"], "\xcb" => [18, ">f"], "\xcc" => [77, ">g"], "\xcd" => [18, ">g"], "\xce" => [77, ">h"], "\xcf" => [18, ">h"], "\xd0" => [77, ">l"], "\xd1" => [18, ">l"], "\xd2" => [77, ">m"], "\xd3" => [18, ">m"], "\xd4" => [77, ">n"], "\xd5" => [18, ">n"], "\xd6" => [77, ">p"], "\xd7" => [18, ">p"], "\xd8" => [77, ">r"], "\xd9" => [18, ">r"], "\xda" => [77, ">u"], "\xdb" => [18, ">u"], "\xdc" => [0, ">:"], "\xdd" => [0, ">B"], "\xde" => [0, ">C"], "\xdf" => [0, ">D"], "\xe0" => [0, ">E"], "\xe1" => [0, ">F"], "\xe2" => [0, ">G"], "\xe3" => [0, ">H"], "\xe4" => [0, ">I"], "\xe5" => [0, ">J"], "\xe6" => [0, ">K"], "\xe7" => [0, ">L"], "\xe8" => [0, ">M"], "\xe9" => [0, ">N"], "\xea" => [0, ">O"], "\xeb" => [0, ">P"], "\xec" => [0, ">Q"], "\xed" => [0, ">R"], "\xee" => [0, ">S"], "\xef" => [0, ">T"], "\xf0" => [0, ">U"], "\xf1" => [0, ">V"], "\xf2" => [0, ">W"], "\xf3" => [0, ">Y"], "\xf4" => [0, ">j"], "\xf5" => [0, ">k"], "\xf6" => [0, ">q"], "\xf7" => [0, ">v"], "\xf8" => [0, ">w"], "\xf9" => [0, ">x"], "\xfa" => [0, ">y"], "\xfb" => [0, ">z"], "\xfc" => [82, ">"], "\xfd" => [87, ">"], "\xfe" => [130, ">"], "\xff" => [9, ">"]], ["\x00" => [94, "|0"], "\x01" => [76, "|0"], "\x02" => [104, "|0"], "\x03" => [16, "|0"], "\x04" => [94, "|1"], "\x05" => [76, "|1"], "\x06" => [104, "|1"], "\x07" => [16, "|1"], "\x08" => [94, "|2"], "\t" => [76, "|2"], "\n" => [104, "|2"], "\v" => [16, "|2"], "\f" => [94, "|a"], "\r" => [76, "|a"], "\x0e" => [104, "|a"], "\x0f" => [16, "|a"], "\x10" => [94, "|c"], "\x11" => [76, "|c"], "\x12" => [104, "|c"], "\x13" => [16, "|c"], "\x14" => [94, "|e"], "\x15" => [76, "|e"], "\x16" => [104, "|e"], "\x17" => [16, "|e"], "\x18" => [94, "|i"], "\x19" => [76, "|i"], "\x1a" => [104, "|i"], "\x1b" => [16, "|i"], "\x1c" => [94, "|o"], "\x1d" => [76, "|o"], "\x1e" => [104, "|o"], "\x1f" => [16, "|o"], " " => [94, "|s"], "!" => [76, "|s"], "\"" => [104, "|s"], "#" => [16, "|s"], "\$" => [94, "|t"], "%" => [76, "|t"], "&" => [104, "|t"], "'" => [16, "|t"], "(" => [77, "| "], ")" => [18, "| "], "*" => [77, "|%"], "+" => [18, "|%"], "," => [77, "|-"], "-" => [18, "|-"], "." => [77, "|."], "/" => [18, "|."], [77, "|/"], [18, "|/"], [77, "|3"], [18, "|3"], [77, "|4"], [18, "|4"], [77, "|5"], [18, "|5"], [77, "|6"], [18, "|6"], ":" => [77, "|7"], ";" => [18, "|7"], "<" => [77, "|8"], "=" => [18, "|8"], ">" => [77, "|9"], "?" => [18, "|9"], "@" => [77, "|="], "A" => [18, "|="], "B" => [77, "|A"], "C" => [18, "|A"], "D" => [77, "|_"], "E" => [18, "|_"], "F" => [77, "|b"], "G" => [18, "|b"], "H" => [77, "|d"], "I" => [18, "|d"], "J" => [77, "|f"], "K" => [18, "|f"], "L" => [77, "|g"], "M" => [18, "|g"], "N" => [77, "|h"], "O" => [18, "|h"], "P" => [77, "|l"], "Q" => [18, "|l"], "R" => [77, "|m"], "S" => [18, "|m"], "T" => [77, "|n"], "U" => [18, "|n"], "V" => [77, "|p"], "W" => [18, "|p"], "X" => [77, "|r"], "Y" => [18, "|r"], "Z" => [77, "|u"], "[" => [18, "|u"], "\\" => [0, "|:"], "]" => [0, "|B"], "^" => [0, "|C"], "_" => [0, "|D"], "`" => [0, "|E"], "a" => [0, "|F"], "b" => [0, "|G"], "c" => [0, "|H"], "d" => [0, "|I"], "e" => [0, "|J"], "f" => [0, "|K"], "g" => [0, "|L"], "h" => [0, "|M"], "i" => [0, "|N"], "j" => [0, "|O"], "k" => [0, "|P"], "l" => [0, "|Q"], "m" => [0, "|R"], "n" => [0, "|S"], "o" => [0, "|T"], "p" => [0, "|U"], "q" => [0, "|V"], "r" => [0, "|W"], "s" => [0, "|Y"], "t" => [0, "|j"], "u" => [0, "|k"], "v" => [0, "|q"], "w" => [0, "|v"], "x" => [0, "|w"], "y" => [0, "|x"], "z" => [0, "|y"], "{" => [0, "|z"], "|" => [82, "|"], "}" => [87, "|"], "~" => [130, "|"], "" => [9, "|"], "\x80" => [77, "#0"], "\x81" => [18, "#0"], "\x82" => [77, "#1"], "\x83" => [18, "#1"], "\x84" => [77, "#2"], "\x85" => [18, "#2"], "\x86" => [77, "#a"], "\x87" => [18, "#a"], "\x88" => [77, "#c"], "\x89" => [18, "#c"], "\x8a" => [77, "#e"], "\x8b" => [18, "#e"], "\x8c" => [77, "#i"], "\x8d" => [18, "#i"], "\x8e" => [77, "#o"], "\x8f" => [18, "#o"], "\x90" => [77, "#s"], "\x91" => [18, "#s"], "\x92" => [77, "#t"], "\x93" => [18, "#t"], "\x94" => [0, "# "], "\x95" => [0, "#%"], "\x96" => [0, "#-"], "\x97" => [0, "#."], "\x98" => [0, "#/"], "\x99" => [0, "#3"], "\x9a" => [0, "#4"], "\x9b" => [0, "#5"], "\x9c" => [0, "#6"], "\x9d" => [0, "#7"], "\x9e" => [0, "#8"], "\x9f" => [0, "#9"], "\xa0" => [0, "#="], "\xa1" => [0, "#A"], "\xa2" => [0, "#_"], "\xa3" => [0, "#b"], "\xa4" => [0, "#d"], "\xa5" => [0, "#f"], "\xa6" => [0, "#g"], "\xa7" => [0, "#h"], "\xa8" => [0, "#l"], "\xa9" => [0, "#m"], "\xaa" => [0, "#n"], "\xab" => [0, "#p"], "\xac" => [0, "#r"], "\xad" => [0, "#u"], "\xae" => [100, "#"], "\xaf" => [110, "#"], "\xb0" => [111, "#"], "\xb1" => [115, "#"], "\xb2" => [116, "#"], "\xb3" => [118, "#"], "\xb4" => [119, "#"], "\xb5" => [122, "#"], "\xb6" => [123, "#"], "\xb7" => [125, "#"], "\xb8" => [126, "#"], "\xb9" => [129, "#"], "\xba" => [143, "#"], "\xbb" => [148, "#"], "\xbc" => [151, "#"], "\xbd" => [153, "#"], "\xbe" => [83, "#"], "\xbf" => [10, "#"], "\xc0" => [77, ">0"], "\xc1" => [18, ">0"], "\xc2" => [77, ">1"], "\xc3" => [18, ">1"], "\xc4" => [77, ">2"], "\xc5" => [18, ">2"], "\xc6" => [77, ">a"], "\xc7" => [18, ">a"], "\xc8" => [77, ">c"], "\xc9" => [18, ">c"], "\xca" => [77, ">e"], "\xcb" => [18, ">e"], "\xcc" => [77, ">i"], "\xcd" => [18, ">i"], "\xce" => [77, ">o"], "\xcf" => [18, ">o"], "\xd0" => [77, ">s"], "\xd1" => [18, ">s"], "\xd2" => [77, ">t"], "\xd3" => [18, ">t"], "\xd4" => [0, "> "], "\xd5" => [0, ">%"], "\xd6" => [0, ">-"], "\xd7" => [0, ">."], "\xd8" => [0, ">/"], "\xd9" => [0, ">3"], "\xda" => [0, ">4"], "\xdb" => [0, ">5"], "\xdc" => [0, ">6"], "\xdd" => [0, ">7"], "\xde" => [0, ">8"], "\xdf" => [0, ">9"], "\xe0" => [0, ">="], "\xe1" => [0, ">A"], "\xe2" => [0, ">_"], "\xe3" => [0, ">b"], "\xe4" => [0, ">d"], "\xe5" => [0, ">f"], "\xe6" => [0, ">g"], "\xe7" => [0, ">h"], "\xe8" => [0, ">l"], "\xe9" => [0, ">m"], "\xea" => [0, ">n"], "\xeb" => [0, ">p"], "\xec" => [0, ">r"], "\xed" => [0, ">u"], "\xee" => [100, ">"], "\xef" => [110, ">"], "\xf0" => [111, ">"], "\xf1" => [115, ">"], "\xf2" => [116, ">"], "\xf3" => [118, ">"], "\xf4" => [119, ">"], "\xf5" => [122, ">"], "\xf6" => [123, ">"], "\xf7" => [125, ">"], "\xf8" => [126, ">"], "\xf9" => [129, ">"], "\xfa" => [143, ">"], "\xfb" => [148, ">"], "\xfc" => [151, ">"], "\xfd" => [153, ">"], "\xfe" => [83, ">"], "\xff" => [10, ">"]], ["\x00" => [94, "&0"], "\x01" => [76, "&0"], "\x02" => [104, "&0"], "\x03" => [16, "&0"], "\x04" => [94, "&1"], "\x05" => [76, "&1"], "\x06" => [104, "&1"], "\x07" => [16, "&1"], "\x08" => [94, "&2"], "\t" => [76, "&2"], "\n" => [104, "&2"], "\v" => [16, "&2"], "\f" => [94, "&a"], "\r" => [76, "&a"], "\x0e" => [104, "&a"], "\x0f" => [16, "&a"], "\x10" => [94, "&c"], "\x11" => [76, "&c"], "\x12" => [104, "&c"], "\x13" => [16, "&c"], "\x14" => [94, "&e"], "\x15" => [76, "&e"], "\x16" => [104, "&e"], "\x17" => [16, "&e"], "\x18" => [94, "&i"], "\x19" => [76, "&i"], "\x1a" => [104, "&i"], "\x1b" => [16, "&i"], "\x1c" => [94, "&o"], "\x1d" => [76, "&o"], "\x1e" => [104, "&o"], "\x1f" => [16, "&o"], " " => [94, "&s"], "!" => [76, "&s"], "\"" => [104, "&s"], "#" => [16, "&s"], "\$" => [94, "&t"], "%" => [76, "&t"], "&" => [104, "&t"], "'" => [16, "&t"], "(" => [77, "& "], ")" => [18, "& "], "*" => [77, "&%"], "+" => [18, "&%"], "," => [77, "&-"], "-" => [18, "&-"], "." => [77, "&."], "/" => [18, "&."], [77, "&/"], [18, "&/"], [77, "&3"], [18, "&3"], [77, "&4"], [18, "&4"], [77, "&5"], [18, "&5"], [77, "&6"], [18, "&6"], ":" => [77, "&7"], ";" => [18, "&7"], "<" => [77, "&8"], "=" => [18, "&8"], ">" => [77, "&9"], "?" => [18, "&9"], "@" => [77, "&="], "A" => [18, "&="], "B" => [77, "&A"], "C" => [18, "&A"], "D" => [77, "&_"], "E" => [18, "&_"], "F" => [77, "&b"], "G" => [18, "&b"], "H" => [77, "&d"], "I" => [18, "&d"], "J" => [77, "&f"], "K" => [18, "&f"], "L" => [77, "&g"], "M" => [18, "&g"], "N" => [77, "&h"], "O" => [18, "&h"], "P" => [77, "&l"], "Q" => [18, "&l"], "R" => [77, "&m"], "S" => [18, "&m"], "T" => [77, "&n"], "U" => [18, "&n"], "V" => [77, "&p"], "W" => [18, "&p"], "X" => [77, "&r"], "Y" => [18, "&r"], "Z" => [77, "&u"], "[" => [18, "&u"], "\\" => [0, "&:"], "]" => [0, "&B"], "^" => [0, "&C"], "_" => [0, "&D"], "`" => [0, "&E"], "a" => [0, "&F"], "b" => [0, "&G"], "c" => [0, "&H"], "d" => [0, "&I"], "e" => [0, "&J"], "f" => [0, "&K"], "g" => [0, "&L"], "h" => [0, "&M"], "i" => [0, "&N"], "j" => [0, "&O"], "k" => [0, "&P"], "l" => [0, "&Q"], "m" => [0, "&R"], "n" => [0, "&S"], "o" => [0, "&T"], "p" => [0, "&U"], "q" => [0, "&V"], "r" => [0, "&W"], "s" => [0, "&Y"], "t" => [0, "&j"], "u" => [0, "&k"], "v" => [0, "&q"], "w" => [0, "&v"], "x" => [0, "&w"], "y" => [0, "&x"], "z" => [0, "&y"], "{" => [0, "&z"], "|" => [82, "&"], "}" => [87, "&"], "~" => [130, "&"], "" => [9, "&"], "\x80" => [94, "*0"], "\x81" => [76, "*0"], "\x82" => [104, "*0"], "\x83" => [16, "*0"], "\x84" => [94, "*1"], "\x85" => [76, "*1"], "\x86" => [104, "*1"], "\x87" => [16, "*1"], "\x88" => [94, "*2"], "\x89" => [76, "*2"], "\x8a" => [104, "*2"], "\x8b" => [16, "*2"], "\x8c" => [94, "*a"], "\x8d" => [76, "*a"], "\x8e" => [104, "*a"], "\x8f" => [16, "*a"], "\x90" => [94, "*c"], "\x91" => [76, "*c"], "\x92" => [104, "*c"], "\x93" => [16, "*c"], "\x94" => [94, "*e"], "\x95" => [76, "*e"], "\x96" => [104, "*e"], "\x97" => [16, "*e"], "\x98" => [94, "*i"], "\x99" => [76, "*i"], "\x9a" => [104, "*i"], "\x9b" => [16, "*i"], "\x9c" => [94, "*o"], "\x9d" => [76, "*o"], "\x9e" => [104, "*o"], "\x9f" => [16, "*o"], "\xa0" => [94, "*s"], "\xa1" => [76, "*s"], "\xa2" => [104, "*s"], "\xa3" => [16, "*s"], "\xa4" => [94, "*t"], "\xa5" => [76, "*t"], "\xa6" => [104, "*t"], "\xa7" => [16, "*t"], "\xa8" => [77, "* "], "\xa9" => [18, "* "], "\xaa" => [77, "*%"], "\xab" => [18, "*%"], "\xac" => [77, "*-"], "\xad" => [18, "*-"], "\xae" => [77, "*."], "\xaf" => [18, "*."], "\xb0" => [77, "*/"], "\xb1" => [18, "*/"], "\xb2" => [77, "*3"], "\xb3" => [18, "*3"], "\xb4" => [77, "*4"], "\xb5" => [18, "*4"], "\xb6" => [77, "*5"], "\xb7" => [18, "*5"], "\xb8" => [77, "*6"], "\xb9" => [18, "*6"], "\xba" => [77, "*7"], "\xbb" => [18, "*7"], "\xbc" => [77, "*8"], "\xbd" => [18, "*8"], "\xbe" => [77, "*9"], "\xbf" => [18, "*9"], "\xc0" => [77, "*="], "\xc1" => [18, "*="], "\xc2" => [77, "*A"], "\xc3" => [18, "*A"], "\xc4" => [77, "*_"], "\xc5" => [18, "*_"], "\xc6" => [77, "*b"], "\xc7" => [18, "*b"], "\xc8" => [77, "*d"], "\xc9" => [18, "*d"], "\xca" => [77, "*f"], "\xcb" => [18, "*f"], "\xcc" => [77, "*g"], "\xcd" => [18, "*g"], "\xce" => [77, "*h"], "\xcf" => [18, "*h"], "\xd0" => [77, "*l"], "\xd1" => [18, "*l"], "\xd2" => [77, "*m"], "\xd3" => [18, "*m"], "\xd4" => [77, "*n"], "\xd5" => [18, "*n"], "\xd6" => [77, "*p"], "\xd7" => [18, "*p"], "\xd8" => [77, "*r"], "\xd9" => [18, "*r"], "\xda" => [77, "*u"], "\xdb" => [18, "*u"], "\xdc" => [0, "*:"], "\xdd" => [0, "*B"], "\xde" => [0, "*C"], "\xdf" => [0, "*D"], "\xe0" => [0, "*E"], "\xe1" => [0, "*F"], "\xe2" => [0, "*G"], "\xe3" => [0, "*H"], "\xe4" => [0, "*I"], "\xe5" => [0, "*J"], "\xe6" => [0, "*K"], "\xe7" => [0, "*L"], "\xe8" => [0, "*M"], "\xe9" => [0, "*N"], "\xea" => [0, "*O"], "\xeb" => [0, "*P"], "\xec" => [0, "*Q"], "\xed" => [0, "*R"], "\xee" => [0, "*S"], "\xef" => [0, "*T"], "\xf0" => [0, "*U"], "\xf1" => [0, "*V"], "\xf2" => [0, "*W"], "\xf3" => [0, "*Y"], "\xf4" => [0, "*j"], "\xf5" => [0, "*k"], "\xf6" => [0, "*q"], "\xf7" => [0, "*v"], "\xf8" => [0, "*w"], "\xf9" => [0, "*x"], "\xfa" => [0, "*y"], "\xfb" => [0, "*z"], "\xfc" => [82, "*"], "\xfd" => [87, "*"], "\xfe" => [130, "*"], "\xff" => [9, "*"]], ["\x00" => [77, "&0"], "\x01" => [18, "&0"], "\x02" => [77, "&1"], "\x03" => [18, "&1"], "\x04" => [77, "&2"], "\x05" => [18, "&2"], "\x06" => [77, "&a"], "\x07" => [18, "&a"], "\x08" => [77, "&c"], "\t" => [18, "&c"], "\n" => [77, "&e"], "\v" => [18, "&e"], "\f" => [77, "&i"], "\r" => [18, "&i"], "\x0e" => [77, "&o"], "\x0f" => [18, "&o"], "\x10" => [77, "&s"], "\x11" => [18, "&s"], "\x12" => [77, "&t"], "\x13" => [18, "&t"], "\x14" => [0, "& "], "\x15" => [0, "&%"], "\x16" => [0, "&-"], "\x17" => [0, "&."], "\x18" => [0, "&/"], "\x19" => [0, "&3"], "\x1a" => [0, "&4"], "\x1b" => [0, "&5"], "\x1c" => [0, "&6"], "\x1d" => [0, "&7"], "\x1e" => [0, "&8"], "\x1f" => [0, "&9"], " " => [0, "&="], "!" => [0, "&A"], "\"" => [0, "&_"], "#" => [0, "&b"], "\$" => [0, "&d"], "%" => [0, "&f"], "&" => [0, "&g"], "'" => [0, "&h"], "(" => [0, "&l"], ")" => [0, "&m"], "*" => [0, "&n"], "+" => [0, "&p"], "," => [0, "&r"], "-" => [0, "&u"], "." => [100, "&"], "/" => [110, "&"], [111, "&"], [115, "&"], [116, "&"], [118, "&"], [119, "&"], [122, "&"], [123, "&"], [125, "&"], [126, "&"], [129, "&"], ":" => [143, "&"], ";" => [148, "&"], "<" => [151, "&"], "=" => [153, "&"], ">" => [83, "&"], "?" => [10, "&"], "@" => [77, "*0"], "A" => [18, "*0"], "B" => [77, "*1"], "C" => [18, "*1"], "D" => [77, "*2"], "E" => [18, "*2"], "F" => [77, "*a"], "G" => [18, "*a"], "H" => [77, "*c"], "I" => [18, "*c"], "J" => [77, "*e"], "K" => [18, "*e"], "L" => [77, "*i"], "M" => [18, "*i"], "N" => [77, "*o"], "O" => [18, "*o"], "P" => [77, "*s"], "Q" => [18, "*s"], "R" => [77, "*t"], "S" => [18, "*t"], "T" => [0, "* "], "U" => [0, "*%"], "V" => [0, "*-"], "W" => [0, "*."], "X" => [0, "*/"], "Y" => [0, "*3"], "Z" => [0, "*4"], "[" => [0, "*5"], "\\" => [0, "*6"], "]" => [0, "*7"], "^" => [0, "*8"], "_" => [0, "*9"], "`" => [0, "*="], "a" => [0, "*A"], "b" => [0, "*_"], "c" => [0, "*b"], "d" => [0, "*d"], "e" => [0, "*f"], "f" => [0, "*g"], "g" => [0, "*h"], "h" => [0, "*l"], "i" => [0, "*m"], "j" => [0, "*n"], "k" => [0, "*p"], "l" => [0, "*r"], "m" => [0, "*u"], "n" => [100, "*"], "o" => [110, "*"], "p" => [111, "*"], "q" => [115, "*"], "r" => [116, "*"], "s" => [118, "*"], "t" => [119, "*"], "u" => [122, "*"], "v" => [123, "*"], "w" => [125, "*"], "x" => [126, "*"], "y" => [129, "*"], "z" => [143, "*"], "{" => [148, "*"], "|" => [151, "*"], "}" => [153, "*"], "~" => [83, "*"], "" => [10, "*"], "\x80" => [77, ",0"], "\x81" => [18, ",0"], "\x82" => [77, ",1"], "\x83" => [18, ",1"], "\x84" => [77, ",2"], "\x85" => [18, ",2"], "\x86" => [77, ",a"], "\x87" => [18, ",a"], "\x88" => [77, ",c"], "\x89" => [18, ",c"], "\x8a" => [77, ",e"], "\x8b" => [18, ",e"], "\x8c" => [77, ",i"], "\x8d" => [18, ",i"], "\x8e" => [77, ",o"], "\x8f" => [18, ",o"], "\x90" => [77, ",s"], "\x91" => [18, ",s"], "\x92" => [77, ",t"], "\x93" => [18, ",t"], "\x94" => [0, ", "], "\x95" => [0, ",%"], "\x96" => [0, ",-"], "\x97" => [0, ",."], "\x98" => [0, ",/"], "\x99" => [0, ",3"], "\x9a" => [0, ",4"], "\x9b" => [0, ",5"], "\x9c" => [0, ",6"], "\x9d" => [0, ",7"], "\x9e" => [0, ",8"], "\x9f" => [0, ",9"], "\xa0" => [0, ",="], "\xa1" => [0, ",A"], "\xa2" => [0, ",_"], "\xa3" => [0, ",b"], "\xa4" => [0, ",d"], "\xa5" => [0, ",f"], "\xa6" => [0, ",g"], "\xa7" => [0, ",h"], "\xa8" => [0, ",l"], "\xa9" => [0, ",m"], "\xaa" => [0, ",n"], "\xab" => [0, ",p"], "\xac" => [0, ",r"], "\xad" => [0, ",u"], "\xae" => [100, ","], "\xaf" => [110, ","], "\xb0" => [111, ","], "\xb1" => [115, ","], "\xb2" => [116, ","], "\xb3" => [118, ","], "\xb4" => [119, ","], "\xb5" => [122, ","], "\xb6" => [123, ","], "\xb7" => [125, ","], "\xb8" => [126, ","], "\xb9" => [129, ","], "\xba" => [143, ","], "\xbb" => [148, ","], "\xbc" => [151, ","], "\xbd" => [153, ","], "\xbe" => [83, ","], "\xbf" => [10, ","], "\xc0" => [77, ";0"], "\xc1" => [18, ";0"], "\xc2" => [77, ";1"], "\xc3" => [18, ";1"], "\xc4" => [77, ";2"], "\xc5" => [18, ";2"], "\xc6" => [77, ";a"], "\xc7" => [18, ";a"], "\xc8" => [77, ";c"], "\xc9" => [18, ";c"], "\xca" => [77, ";e"], "\xcb" => [18, ";e"], "\xcc" => [77, ";i"], "\xcd" => [18, ";i"], "\xce" => [77, ";o"], "\xcf" => [18, ";o"], "\xd0" => [77, ";s"], "\xd1" => [18, ";s"], "\xd2" => [77, ";t"], "\xd3" => [18, ";t"], "\xd4" => [0, "; "], "\xd5" => [0, ";%"], "\xd6" => [0, ";-"], "\xd7" => [0, ";."], "\xd8" => [0, ";/"], "\xd9" => [0, ";3"], "\xda" => [0, ";4"], "\xdb" => [0, ";5"], "\xdc" => [0, ";6"], "\xdd" => [0, ";7"], "\xde" => [0, ";8"], "\xdf" => [0, ";9"], "\xe0" => [0, ";="], "\xe1" => [0, ";A"], "\xe2" => [0, ";_"], "\xe3" => [0, ";b"], "\xe4" => [0, ";d"], "\xe5" => [0, ";f"], "\xe6" => [0, ";g"], "\xe7" => [0, ";h"], "\xe8" => [0, ";l"], "\xe9" => [0, ";m"], "\xea" => [0, ";n"], "\xeb" => [0, ";p"], "\xec" => [0, ";r"], "\xed" => [0, ";u"], "\xee" => [100, ";"], "\xef" => [110, ";"], "\xf0" => [111, ";"], "\xf1" => [115, ";"], "\xf2" => [116, ";"], "\xf3" => [118, ";"], "\xf4" => [119, ";"], "\xf5" => [122, ";"], "\xf6" => [123, ";"], "\xf7" => [125, ";"], "\xf8" => [126, ";"], "\xf9" => [129, ";"], "\xfa" => [143, ";"], "\xfb" => [148, ";"], "\xfc" => [151, ";"], "\xfd" => [153, ";"], "\xfe" => [83, ";"], "\xff" => [10, ";"]], ["\x00" => [94, "'0"], "\x01" => [76, "'0"], "\x02" => [104, "'0"], "\x03" => [16, "'0"], "\x04" => [94, "'1"], "\x05" => [76, "'1"], "\x06" => [104, "'1"], "\x07" => [16, "'1"], "\x08" => [94, "'2"], "\t" => [76, "'2"], "\n" => [104, "'2"], "\v" => [16, "'2"], "\f" => [94, "'a"], "\r" => [76, "'a"], "\x0e" => [104, "'a"], "\x0f" => [16, "'a"], "\x10" => [94, "'c"], "\x11" => [76, "'c"], "\x12" => [104, "'c"], "\x13" => [16, "'c"], "\x14" => [94, "'e"], "\x15" => [76, "'e"], "\x16" => [104, "'e"], "\x17" => [16, "'e"], "\x18" => [94, "'i"], "\x19" => [76, "'i"], "\x1a" => [104, "'i"], "\x1b" => [16, "'i"], "\x1c" => [94, "'o"], "\x1d" => [76, "'o"], "\x1e" => [104, "'o"], "\x1f" => [16, "'o"], " " => [94, "'s"], "!" => [76, "'s"], "\"" => [104, "'s"], "#" => [16, "'s"], "\$" => [94, "'t"], "%" => [76, "'t"], "&" => [104, "'t"], "'" => [16, "'t"], "(" => [77, "' "], ")" => [18, "' "], "*" => [77, "'%"], "+" => [18, "'%"], "," => [77, "'-"], "-" => [18, "'-"], "." => [77, "'."], "/" => [18, "'."], [77, "'/"], [18, "'/"], [77, "'3"], [18, "'3"], [77, "'4"], [18, "'4"], [77, "'5"], [18, "'5"], [77, "'6"], [18, "'6"], ":" => [77, "'7"], ";" => [18, "'7"], "<" => [77, "'8"], "=" => [18, "'8"], ">" => [77, "'9"], "?" => [18, "'9"], "@" => [77, "'="], "A" => [18, "'="], "B" => [77, "'A"], "C" => [18, "'A"], "D" => [77, "'_"], "E" => [18, "'_"], "F" => [77, "'b"], "G" => [18, "'b"], "H" => [77, "'d"], "I" => [18, "'d"], "J" => [77, "'f"], "K" => [18, "'f"], "L" => [77, "'g"], "M" => [18, "'g"], "N" => [77, "'h"], "O" => [18, "'h"], "P" => [77, "'l"], "Q" => [18, "'l"], "R" => [77, "'m"], "S" => [18, "'m"], "T" => [77, "'n"], "U" => [18, "'n"], "V" => [77, "'p"], "W" => [18, "'p"], "X" => [77, "'r"], "Y" => [18, "'r"], "Z" => [77, "'u"], "[" => [18, "'u"], "\\" => [0, "':"], "]" => [0, "'B"], "^" => [0, "'C"], "_" => [0, "'D"], "`" => [0, "'E"], "a" => [0, "'F"], "b" => [0, "'G"], "c" => [0, "'H"], "d" => [0, "'I"], "e" => [0, "'J"], "f" => [0, "'K"], "g" => [0, "'L"], "h" => [0, "'M"], "i" => [0, "'N"], "j" => [0, "'O"], "k" => [0, "'P"], "l" => [0, "'Q"], "m" => [0, "'R"], "n" => [0, "'S"], "o" => [0, "'T"], "p" => [0, "'U"], "q" => [0, "'V"], "r" => [0, "'W"], "s" => [0, "'Y"], "t" => [0, "'j"], "u" => [0, "'k"], "v" => [0, "'q"], "w" => [0, "'v"], "x" => [0, "'w"], "y" => [0, "'x"], "z" => [0, "'y"], "{" => [0, "'z"], "|" => [82, "'"], "}" => [87, "'"], "~" => [130, "'"], "" => [9, "'"], "\x80" => [94, "+0"], "\x81" => [76, "+0"], "\x82" => [104, "+0"], "\x83" => [16, "+0"], "\x84" => [94, "+1"], "\x85" => [76, "+1"], "\x86" => [104, "+1"], "\x87" => [16, "+1"], "\x88" => [94, "+2"], "\x89" => [76, "+2"], "\x8a" => [104, "+2"], "\x8b" => [16, "+2"], "\x8c" => [94, "+a"], "\x8d" => [76, "+a"], "\x8e" => [104, "+a"], "\x8f" => [16, "+a"], "\x90" => [94, "+c"], "\x91" => [76, "+c"], "\x92" => [104, "+c"], "\x93" => [16, "+c"], "\x94" => [94, "+e"], "\x95" => [76, "+e"], "\x96" => [104, "+e"], "\x97" => [16, "+e"], "\x98" => [94, "+i"], "\x99" => [76, "+i"], "\x9a" => [104, "+i"], "\x9b" => [16, "+i"], "\x9c" => [94, "+o"], "\x9d" => [76, "+o"], "\x9e" => [104, "+o"], "\x9f" => [16, "+o"], "\xa0" => [94, "+s"], "\xa1" => [76, "+s"], "\xa2" => [104, "+s"], "\xa3" => [16, "+s"], "\xa4" => [94, "+t"], "\xa5" => [76, "+t"], "\xa6" => [104, "+t"], "\xa7" => [16, "+t"], "\xa8" => [77, "+ "], "\xa9" => [18, "+ "], "\xaa" => [77, "+%"], "\xab" => [18, "+%"], "\xac" => [77, "+-"], "\xad" => [18, "+-"], "\xae" => [77, "+."], "\xaf" => [18, "+."], "\xb0" => [77, "+/"], "\xb1" => [18, "+/"], "\xb2" => [77, "+3"], "\xb3" => [18, "+3"], "\xb4" => [77, "+4"], "\xb5" => [18, "+4"], "\xb6" => [77, "+5"], "\xb7" => [18, "+5"], "\xb8" => [77, "+6"], "\xb9" => [18, "+6"], "\xba" => [77, "+7"], "\xbb" => [18, "+7"], "\xbc" => [77, "+8"], "\xbd" => [18, "+8"], "\xbe" => [77, "+9"], "\xbf" => [18, "+9"], "\xc0" => [77, "+="], "\xc1" => [18, "+="], "\xc2" => [77, "+A"], "\xc3" => [18, "+A"], "\xc4" => [77, "+_"], "\xc5" => [18, "+_"], "\xc6" => [77, "+b"], "\xc7" => [18, "+b"], "\xc8" => [77, "+d"], "\xc9" => [18, "+d"], "\xca" => [77, "+f"], "\xcb" => [18, "+f"], "\xcc" => [77, "+g"], "\xcd" => [18, "+g"], "\xce" => [77, "+h"], "\xcf" => [18, "+h"], "\xd0" => [77, "+l"], "\xd1" => [18, "+l"], "\xd2" => [77, "+m"], "\xd3" => [18, "+m"], "\xd4" => [77, "+n"], "\xd5" => [18, "+n"], "\xd6" => [77, "+p"], "\xd7" => [18, "+p"], "\xd8" => [77, "+r"], "\xd9" => [18, "+r"], "\xda" => [77, "+u"], "\xdb" => [18, "+u"], "\xdc" => [0, "+:"], "\xdd" => [0, "+B"], "\xde" => [0, "+C"], "\xdf" => [0, "+D"], "\xe0" => [0, "+E"], "\xe1" => [0, "+F"], "\xe2" => [0, "+G"], "\xe3" => [0, "+H"], "\xe4" => [0, "+I"], "\xe5" => [0, "+J"], "\xe6" => [0, "+K"], "\xe7" => [0, "+L"], "\xe8" => [0, "+M"], "\xe9" => [0, "+N"], "\xea" => [0, "+O"], "\xeb" => [0, "+P"], "\xec" => [0, "+Q"], "\xed" => [0, "+R"], "\xee" => [0, "+S"], "\xef" => [0, "+T"], "\xf0" => [0, "+U"], "\xf1" => [0, "+V"], "\xf2" => [0, "+W"], "\xf3" => [0, "+Y"], "\xf4" => [0, "+j"], "\xf5" => [0, "+k"], "\xf6" => [0, "+q"], "\xf7" => [0, "+v"], "\xf8" => [0, "+w"], "\xf9" => [0, "+x"], "\xfa" => [0, "+y"], "\xfb" => [0, "+z"], "\xfc" => [82, "+"], "\xfd" => [87, "+"], "\xfe" => [130, "+"], "\xff" => [9, "+"]], ["\x00" => [94, "?0"], "\x01" => [76, "?0"], "\x02" => [104, "?0"], "\x03" => [16, "?0"], "\x04" => [94, "?1"], "\x05" => [76, "?1"], "\x06" => [104, "?1"], "\x07" => [16, "?1"], "\x08" => [94, "?2"], "\t" => [76, "?2"], "\n" => [104, "?2"], "\v" => [16, "?2"], "\f" => [94, "?a"], "\r" => [76, "?a"], "\x0e" => [104, "?a"], "\x0f" => [16, "?a"], "\x10" => [94, "?c"], "\x11" => [76, "?c"], "\x12" => [104, "?c"], "\x13" => [16, "?c"], "\x14" => [94, "?e"], "\x15" => [76, "?e"], "\x16" => [104, "?e"], "\x17" => [16, "?e"], "\x18" => [94, "?i"], "\x19" => [76, "?i"], "\x1a" => [104, "?i"], "\x1b" => [16, "?i"], "\x1c" => [94, "?o"], "\x1d" => [76, "?o"], "\x1e" => [104, "?o"], "\x1f" => [16, "?o"], " " => [94, "?s"], "!" => [76, "?s"], "\"" => [104, "?s"], "#" => [16, "?s"], "\$" => [94, "?t"], "%" => [76, "?t"], "&" => [104, "?t"], "'" => [16, "?t"], "(" => [77, "? "], ")" => [18, "? "], "*" => [77, "?%"], "+" => [18, "?%"], "," => [77, "?-"], "-" => [18, "?-"], "." => [77, "?."], "/" => [18, "?."], [77, "?/"], [18, "?/"], [77, "?3"], [18, "?3"], [77, "?4"], [18, "?4"], [77, "?5"], [18, "?5"], [77, "?6"], [18, "?6"], ":" => [77, "?7"], ";" => [18, "?7"], "<" => [77, "?8"], "=" => [18, "?8"], ">" => [77, "?9"], "?" => [18, "?9"], "@" => [77, "?="], "A" => [18, "?="], "B" => [77, "?A"], "C" => [18, "?A"], "D" => [77, "?_"], "E" => [18, "?_"], "F" => [77, "?b"], "G" => [18, "?b"], "H" => [77, "?d"], "I" => [18, "?d"], "J" => [77, "?f"], "K" => [18, "?f"], "L" => [77, "?g"], "M" => [18, "?g"], "N" => [77, "?h"], "O" => [18, "?h"], "P" => [77, "?l"], "Q" => [18, "?l"], "R" => [77, "?m"], "S" => [18, "?m"], "T" => [77, "?n"], "U" => [18, "?n"], "V" => [77, "?p"], "W" => [18, "?p"], "X" => [77, "?r"], "Y" => [18, "?r"], "Z" => [77, "?u"], "[" => [18, "?u"], "\\" => [0, "?:"], "]" => [0, "?B"], "^" => [0, "?C"], "_" => [0, "?D"], "`" => [0, "?E"], "a" => [0, "?F"], "b" => [0, "?G"], "c" => [0, "?H"], "d" => [0, "?I"], "e" => [0, "?J"], "f" => [0, "?K"], "g" => [0, "?L"], "h" => [0, "?M"], "i" => [0, "?N"], "j" => [0, "?O"], "k" => [0, "?P"], "l" => [0, "?Q"], "m" => [0, "?R"], "n" => [0, "?S"], "o" => [0, "?T"], "p" => [0, "?U"], "q" => [0, "?V"], "r" => [0, "?W"], "s" => [0, "?Y"], "t" => [0, "?j"], "u" => [0, "?k"], "v" => [0, "?q"], "w" => [0, "?v"], "x" => [0, "?w"], "y" => [0, "?x"], "z" => [0, "?y"], "{" => [0, "?z"], "|" => [82, "?"], "}" => [87, "?"], "~" => [130, "?"], "" => [9, "?"], "\x80" => [77, "'0"], "\x81" => [18, "'0"], "\x82" => [77, "'1"], "\x83" => [18, "'1"], "\x84" => [77, "'2"], "\x85" => [18, "'2"], "\x86" => [77, "'a"], "\x87" => [18, "'a"], "\x88" => [77, "'c"], "\x89" => [18, "'c"], "\x8a" => [77, "'e"], "\x8b" => [18, "'e"], "\x8c" => [77, "'i"], "\x8d" => [18, "'i"], "\x8e" => [77, "'o"], "\x8f" => [18, "'o"], "\x90" => [77, "'s"], "\x91" => [18, "'s"], "\x92" => [77, "'t"], "\x93" => [18, "'t"], "\x94" => [0, "' "], "\x95" => [0, "'%"], "\x96" => [0, "'-"], "\x97" => [0, "'."], "\x98" => [0, "'/"], "\x99" => [0, "'3"], "\x9a" => [0, "'4"], "\x9b" => [0, "'5"], "\x9c" => [0, "'6"], "\x9d" => [0, "'7"], "\x9e" => [0, "'8"], "\x9f" => [0, "'9"], "\xa0" => [0, "'="], "\xa1" => [0, "'A"], "\xa2" => [0, "'_"], "\xa3" => [0, "'b"], "\xa4" => [0, "'d"], "\xa5" => [0, "'f"], "\xa6" => [0, "'g"], "\xa7" => [0, "'h"], "\xa8" => [0, "'l"], "\xa9" => [0, "'m"], "\xaa" => [0, "'n"], "\xab" => [0, "'p"], "\xac" => [0, "'r"], "\xad" => [0, "'u"], "\xae" => [100, "'"], "\xaf" => [110, "'"], "\xb0" => [111, "'"], "\xb1" => [115, "'"], "\xb2" => [116, "'"], "\xb3" => [118, "'"], "\xb4" => [119, "'"], "\xb5" => [122, "'"], "\xb6" => [123, "'"], "\xb7" => [125, "'"], "\xb8" => [126, "'"], "\xb9" => [129, "'"], "\xba" => [143, "'"], "\xbb" => [148, "'"], "\xbc" => [151, "'"], "\xbd" => [153, "'"], "\xbe" => [83, "'"], "\xbf" => [10, "'"], "\xc0" => [77, "+0"], "\xc1" => [18, "+0"], "\xc2" => [77, "+1"], "\xc3" => [18, "+1"], "\xc4" => [77, "+2"], "\xc5" => [18, "+2"], "\xc6" => [77, "+a"], "\xc7" => [18, "+a"], "\xc8" => [77, "+c"], "\xc9" => [18, "+c"], "\xca" => [77, "+e"], "\xcb" => [18, "+e"], "\xcc" => [77, "+i"], "\xcd" => [18, "+i"], "\xce" => [77, "+o"], "\xcf" => [18, "+o"], "\xd0" => [77, "+s"], "\xd1" => [18, "+s"], "\xd2" => [77, "+t"], "\xd3" => [18, "+t"], "\xd4" => [0, "+ "], "\xd5" => [0, "+%"], "\xd6" => [0, "+-"], "\xd7" => [0, "+."], "\xd8" => [0, "+/"], "\xd9" => [0, "+3"], "\xda" => [0, "+4"], "\xdb" => [0, "+5"], "\xdc" => [0, "+6"], "\xdd" => [0, "+7"], "\xde" => [0, "+8"], "\xdf" => [0, "+9"], "\xe0" => [0, "+="], "\xe1" => [0, "+A"], "\xe2" => [0, "+_"], "\xe3" => [0, "+b"], "\xe4" => [0, "+d"], "\xe5" => [0, "+f"], "\xe6" => [0, "+g"], "\xe7" => [0, "+h"], "\xe8" => [0, "+l"], "\xe9" => [0, "+m"], "\xea" => [0, "+n"], "\xeb" => [0, "+p"], "\xec" => [0, "+r"], "\xed" => [0, "+u"], "\xee" => [100, "+"], "\xef" => [110, "+"], "\xf0" => [111, "+"], "\xf1" => [115, "+"], "\xf2" => [116, "+"], "\xf3" => [118, "+"], "\xf4" => [119, "+"], "\xf5" => [122, "+"], "\xf6" => [123, "+"], "\xf7" => [125, "+"], "\xf8" => [126, "+"], "\xf9" => [129, "+"], "\xfa" => [143, "+"], "\xfb" => [148, "+"], "\xfc" => [151, "+"], "\xfd" => [153, "+"], "\xfe" => [83, "+"], "\xff" => [10, "+"]], ["\x00" => [94, "(0"], "\x01" => [76, "(0"], "\x02" => [104, "(0"], "\x03" => [16, "(0"], "\x04" => [94, "(1"], "\x05" => [76, "(1"], "\x06" => [104, "(1"], "\x07" => [16, "(1"], "\x08" => [94, "(2"], "\t" => [76, "(2"], "\n" => [104, "(2"], "\v" => [16, "(2"], "\f" => [94, "(a"], "\r" => [76, "(a"], "\x0e" => [104, "(a"], "\x0f" => [16, "(a"], "\x10" => [94, "(c"], "\x11" => [76, "(c"], "\x12" => [104, "(c"], "\x13" => [16, "(c"], "\x14" => [94, "(e"], "\x15" => [76, "(e"], "\x16" => [104, "(e"], "\x17" => [16, "(e"], "\x18" => [94, "(i"], "\x19" => [76, "(i"], "\x1a" => [104, "(i"], "\x1b" => [16, "(i"], "\x1c" => [94, "(o"], "\x1d" => [76, "(o"], "\x1e" => [104, "(o"], "\x1f" => [16, "(o"], " " => [94, "(s"], "!" => [76, "(s"], "\"" => [104, "(s"], "#" => [16, "(s"], "\$" => [94, "(t"], "%" => [76, "(t"], "&" => [104, "(t"], "'" => [16, "(t"], "(" => [77, "( "], ")" => [18, "( "], "*" => [77, "(%"], "+" => [18, "(%"], "," => [77, "(-"], "-" => [18, "(-"], "." => [77, "(."], "/" => [18, "(."], [77, "(/"], [18, "(/"], [77, "(3"], [18, "(3"], [77, "(4"], [18, "(4"], [77, "(5"], [18, "(5"], [77, "(6"], [18, "(6"], ":" => [77, "(7"], ";" => [18, "(7"], "<" => [77, "(8"], "=" => [18, "(8"], ">" => [77, "(9"], "?" => [18, "(9"], "@" => [77, "(="], "A" => [18, "(="], "B" => [77, "(A"], "C" => [18, "(A"], "D" => [77, "(_"], "E" => [18, "(_"], "F" => [77, "(b"], "G" => [18, "(b"], "H" => [77, "(d"], "I" => [18, "(d"], "J" => [77, "(f"], "K" => [18, "(f"], "L" => [77, "(g"], "M" => [18, "(g"], "N" => [77, "(h"], "O" => [18, "(h"], "P" => [77, "(l"], "Q" => [18, "(l"], "R" => [77, "(m"], "S" => [18, "(m"], "T" => [77, "(n"], "U" => [18, "(n"], "V" => [77, "(p"], "W" => [18, "(p"], "X" => [77, "(r"], "Y" => [18, "(r"], "Z" => [77, "(u"], "[" => [18, "(u"], "\\" => [0, "(:"], "]" => [0, "(B"], "^" => [0, "(C"], "_" => [0, "(D"], "`" => [0, "(E"], "a" => [0, "(F"], "b" => [0, "(G"], "c" => [0, "(H"], "d" => [0, "(I"], "e" => [0, "(J"], "f" => [0, "(K"], "g" => [0, "(L"], "h" => [0, "(M"], "i" => [0, "(N"], "j" => [0, "(O"], "k" => [0, "(P"], "l" => [0, "(Q"], "m" => [0, "(R"], "n" => [0, "(S"], "o" => [0, "(T"], "p" => [0, "(U"], "q" => [0, "(V"], "r" => [0, "(W"], "s" => [0, "(Y"], "t" => [0, "(j"], "u" => [0, "(k"], "v" => [0, "(q"], "w" => [0, "(v"], "x" => [0, "(w"], "y" => [0, "(x"], "z" => [0, "(y"], "{" => [0, "(z"], "|" => [82, "("], "}" => [87, "("], "~" => [130, "("], "" => [9, "("], "\x80" => [94, ")0"], "\x81" => [76, ")0"], "\x82" => [104, ")0"], "\x83" => [16, ")0"], "\x84" => [94, ")1"], "\x85" => [76, ")1"], "\x86" => [104, ")1"], "\x87" => [16, ")1"], "\x88" => [94, ")2"], "\x89" => [76, ")2"], "\x8a" => [104, ")2"], "\x8b" => [16, ")2"], "\x8c" => [94, ")a"], "\x8d" => [76, ")a"], "\x8e" => [104, ")a"], "\x8f" => [16, ")a"], "\x90" => [94, ")c"], "\x91" => [76, ")c"], "\x92" => [104, ")c"], "\x93" => [16, ")c"], "\x94" => [94, ")e"], "\x95" => [76, ")e"], "\x96" => [104, ")e"], "\x97" => [16, ")e"], "\x98" => [94, ")i"], "\x99" => [76, ")i"], "\x9a" => [104, ")i"], "\x9b" => [16, ")i"], "\x9c" => [94, ")o"], "\x9d" => [76, ")o"], "\x9e" => [104, ")o"], "\x9f" => [16, ")o"], "\xa0" => [94, ")s"], "\xa1" => [76, ")s"], "\xa2" => [104, ")s"], "\xa3" => [16, ")s"], "\xa4" => [94, ")t"], "\xa5" => [76, ")t"], "\xa6" => [104, ")t"], "\xa7" => [16, ")t"], "\xa8" => [77, ") "], "\xa9" => [18, ") "], "\xaa" => [77, ")%"], "\xab" => [18, ")%"], "\xac" => [77, ")-"], "\xad" => [18, ")-"], "\xae" => [77, ")."], "\xaf" => [18, ")."], "\xb0" => [77, ")/"], "\xb1" => [18, ")/"], "\xb2" => [77, ")3"], "\xb3" => [18, ")3"], "\xb4" => [77, ")4"], "\xb5" => [18, ")4"], "\xb6" => [77, ")5"], "\xb7" => [18, ")5"], "\xb8" => [77, ")6"], "\xb9" => [18, ")6"], "\xba" => [77, ")7"], "\xbb" => [18, ")7"], "\xbc" => [77, ")8"], "\xbd" => [18, ")8"], "\xbe" => [77, ")9"], "\xbf" => [18, ")9"], "\xc0" => [77, ")="], "\xc1" => [18, ")="], "\xc2" => [77, ")A"], "\xc3" => [18, ")A"], "\xc4" => [77, ")_"], "\xc5" => [18, ")_"], "\xc6" => [77, ")b"], "\xc7" => [18, ")b"], "\xc8" => [77, ")d"], "\xc9" => [18, ")d"], "\xca" => [77, ")f"], "\xcb" => [18, ")f"], "\xcc" => [77, ")g"], "\xcd" => [18, ")g"], "\xce" => [77, ")h"], "\xcf" => [18, ")h"], "\xd0" => [77, ")l"], "\xd1" => [18, ")l"], "\xd2" => [77, ")m"], "\xd3" => [18, ")m"], "\xd4" => [77, ")n"], "\xd5" => [18, ")n"], "\xd6" => [77, ")p"], "\xd7" => [18, ")p"], "\xd8" => [77, ")r"], "\xd9" => [18, ")r"], "\xda" => [77, ")u"], "\xdb" => [18, ")u"], "\xdc" => [0, "):"], "\xdd" => [0, ")B"], "\xde" => [0, ")C"], "\xdf" => [0, ")D"], "\xe0" => [0, ")E"], "\xe1" => [0, ")F"], "\xe2" => [0, ")G"], "\xe3" => [0, ")H"], "\xe4" => [0, ")I"], "\xe5" => [0, ")J"], "\xe6" => [0, ")K"], "\xe7" => [0, ")L"], "\xe8" => [0, ")M"], "\xe9" => [0, ")N"], "\xea" => [0, ")O"], "\xeb" => [0, ")P"], "\xec" => [0, ")Q"], "\xed" => [0, ")R"], "\xee" => [0, ")S"], "\xef" => [0, ")T"], "\xf0" => [0, ")U"], "\xf1" => [0, ")V"], "\xf2" => [0, ")W"], "\xf3" => [0, ")Y"], "\xf4" => [0, ")j"], "\xf5" => [0, ")k"], "\xf6" => [0, ")q"], "\xf7" => [0, ")v"], "\xf8" => [0, ")w"], "\xf9" => [0, ")x"], "\xfa" => [0, ")y"], "\xfb" => [0, ")z"], "\xfc" => [82, ")"], "\xfd" => [87, ")"], "\xfe" => [130, ")"], "\xff" => [9, ")"]], ["\x00" => [94, ",0"], "\x01" => [76, ",0"], "\x02" => [104, ",0"], "\x03" => [16, ",0"], "\x04" => [94, ",1"], "\x05" => [76, ",1"], "\x06" => [104, ",1"], "\x07" => [16, ",1"], "\x08" => [94, ",2"], "\t" => [76, ",2"], "\n" => [104, ",2"], "\v" => [16, ",2"], "\f" => [94, ",a"], "\r" => [76, ",a"], "\x0e" => [104, ",a"], "\x0f" => [16, ",a"], "\x10" => [94, ",c"], "\x11" => [76, ",c"], "\x12" => [104, ",c"], "\x13" => [16, ",c"], "\x14" => [94, ",e"], "\x15" => [76, ",e"], "\x16" => [104, ",e"], "\x17" => [16, ",e"], "\x18" => [94, ",i"], "\x19" => [76, ",i"], "\x1a" => [104, ",i"], "\x1b" => [16, ",i"], "\x1c" => [94, ",o"], "\x1d" => [76, ",o"], "\x1e" => [104, ",o"], "\x1f" => [16, ",o"], " " => [94, ",s"], "!" => [76, ",s"], "\"" => [104, ",s"], "#" => [16, ",s"], "\$" => [94, ",t"], "%" => [76, ",t"], "&" => [104, ",t"], "'" => [16, ",t"], "(" => [77, ", "], ")" => [18, ", "], "*" => [77, ",%"], "+" => [18, ",%"], "," => [77, ",-"], "-" => [18, ",-"], "." => [77, ",."], "/" => [18, ",."], [77, ",/"], [18, ",/"], [77, ",3"], [18, ",3"], [77, ",4"], [18, ",4"], [77, ",5"], [18, ",5"], [77, ",6"], [18, ",6"], ":" => [77, ",7"], ";" => [18, ",7"], "<" => [77, ",8"], "=" => [18, ",8"], ">" => [77, ",9"], "?" => [18, ",9"], "@" => [77, ",="], "A" => [18, ",="], "B" => [77, ",A"], "C" => [18, ",A"], "D" => [77, ",_"], "E" => [18, ",_"], "F" => [77, ",b"], "G" => [18, ",b"], "H" => [77, ",d"], "I" => [18, ",d"], "J" => [77, ",f"], "K" => [18, ",f"], "L" => [77, ",g"], "M" => [18, ",g"], "N" => [77, ",h"], "O" => [18, ",h"], "P" => [77, ",l"], "Q" => [18, ",l"], "R" => [77, ",m"], "S" => [18, ",m"], "T" => [77, ",n"], "U" => [18, ",n"], "V" => [77, ",p"], "W" => [18, ",p"], "X" => [77, ",r"], "Y" => [18, ",r"], "Z" => [77, ",u"], "[" => [18, ",u"], "\\" => [0, ",:"], "]" => [0, ",B"], "^" => [0, ",C"], "_" => [0, ",D"], "`" => [0, ",E"], "a" => [0, ",F"], "b" => [0, ",G"], "c" => [0, ",H"], "d" => [0, ",I"], "e" => [0, ",J"], "f" => [0, ",K"], "g" => [0, ",L"], "h" => [0, ",M"], "i" => [0, ",N"], "j" => [0, ",O"], "k" => [0, ",P"], "l" => [0, ",Q"], "m" => [0, ",R"], "n" => [0, ",S"], "o" => [0, ",T"], "p" => [0, ",U"], "q" => [0, ",V"], "r" => [0, ",W"], "s" => [0, ",Y"], "t" => [0, ",j"], "u" => [0, ",k"], "v" => [0, ",q"], "w" => [0, ",v"], "x" => [0, ",w"], "y" => [0, ",x"], "z" => [0, ",y"], "{" => [0, ",z"], "|" => [82, ","], "}" => [87, ","], "~" => [130, ","], "" => [9, ","], "\x80" => [94, ";0"], "\x81" => [76, ";0"], "\x82" => [104, ";0"], "\x83" => [16, ";0"], "\x84" => [94, ";1"], "\x85" => [76, ";1"], "\x86" => [104, ";1"], "\x87" => [16, ";1"], "\x88" => [94, ";2"], "\x89" => [76, ";2"], "\x8a" => [104, ";2"], "\x8b" => [16, ";2"], "\x8c" => [94, ";a"], "\x8d" => [76, ";a"], "\x8e" => [104, ";a"], "\x8f" => [16, ";a"], "\x90" => [94, ";c"], "\x91" => [76, ";c"], "\x92" => [104, ";c"], "\x93" => [16, ";c"], "\x94" => [94, ";e"], "\x95" => [76, ";e"], "\x96" => [104, ";e"], "\x97" => [16, ";e"], "\x98" => [94, ";i"], "\x99" => [76, ";i"], "\x9a" => [104, ";i"], "\x9b" => [16, ";i"], "\x9c" => [94, ";o"], "\x9d" => [76, ";o"], "\x9e" => [104, ";o"], "\x9f" => [16, ";o"], "\xa0" => [94, ";s"], "\xa1" => [76, ";s"], "\xa2" => [104, ";s"], "\xa3" => [16, ";s"], "\xa4" => [94, ";t"], "\xa5" => [76, ";t"], "\xa6" => [104, ";t"], "\xa7" => [16, ";t"], "\xa8" => [77, "; "], "\xa9" => [18, "; "], "\xaa" => [77, ";%"], "\xab" => [18, ";%"], "\xac" => [77, ";-"], "\xad" => [18, ";-"], "\xae" => [77, ";."], "\xaf" => [18, ";."], "\xb0" => [77, ";/"], "\xb1" => [18, ";/"], "\xb2" => [77, ";3"], "\xb3" => [18, ";3"], "\xb4" => [77, ";4"], "\xb5" => [18, ";4"], "\xb6" => [77, ";5"], "\xb7" => [18, ";5"], "\xb8" => [77, ";6"], "\xb9" => [18, ";6"], "\xba" => [77, ";7"], "\xbb" => [18, ";7"], "\xbc" => [77, ";8"], "\xbd" => [18, ";8"], "\xbe" => [77, ";9"], "\xbf" => [18, ";9"], "\xc0" => [77, ";="], "\xc1" => [18, ";="], "\xc2" => [77, ";A"], "\xc3" => [18, ";A"], "\xc4" => [77, ";_"], "\xc5" => [18, ";_"], "\xc6" => [77, ";b"], "\xc7" => [18, ";b"], "\xc8" => [77, ";d"], "\xc9" => [18, ";d"], "\xca" => [77, ";f"], "\xcb" => [18, ";f"], "\xcc" => [77, ";g"], "\xcd" => [18, ";g"], "\xce" => [77, ";h"], "\xcf" => [18, ";h"], "\xd0" => [77, ";l"], "\xd1" => [18, ";l"], "\xd2" => [77, ";m"], "\xd3" => [18, ";m"], "\xd4" => [77, ";n"], "\xd5" => [18, ";n"], "\xd6" => [77, ";p"], "\xd7" => [18, ";p"], "\xd8" => [77, ";r"], "\xd9" => [18, ";r"], "\xda" => [77, ";u"], "\xdb" => [18, ";u"], "\xdc" => [0, ";:"], "\xdd" => [0, ";B"], "\xde" => [0, ";C"], "\xdf" => [0, ";D"], "\xe0" => [0, ";E"], "\xe1" => [0, ";F"], "\xe2" => [0, ";G"], "\xe3" => [0, ";H"], "\xe4" => [0, ";I"], "\xe5" => [0, ";J"], "\xe6" => [0, ";K"], "\xe7" => [0, ";L"], "\xe8" => [0, ";M"], "\xe9" => [0, ";N"], "\xea" => [0, ";O"], "\xeb" => [0, ";P"], "\xec" => [0, ";Q"], "\xed" => [0, ";R"], "\xee" => [0, ";S"], "\xef" => [0, ";T"], "\xf0" => [0, ";U"], "\xf1" => [0, ";V"], "\xf2" => [0, ";W"], "\xf3" => [0, ";Y"], "\xf4" => [0, ";j"], "\xf5" => [0, ";k"], "\xf6" => [0, ";q"], "\xf7" => [0, ";v"], "\xf8" => [0, ";w"], "\xf9" => [0, ";x"], "\xfa" => [0, ";y"], "\xfb" => [0, ";z"], "\xfc" => [82, ";"], "\xfd" => [87, ";"], "\xfe" => [130, ";"], "\xff" => [9, ";"]], ["\x00" => [94, "-0"], "\x01" => [76, "-0"], "\x02" => [104, "-0"], "\x03" => [16, "-0"], "\x04" => [94, "-1"], "\x05" => [76, "-1"], "\x06" => [104, "-1"], "\x07" => [16, "-1"], "\x08" => [94, "-2"], "\t" => [76, "-2"], "\n" => [104, "-2"], "\v" => [16, "-2"], "\f" => [94, "-a"], "\r" => [76, "-a"], "\x0e" => [104, "-a"], "\x0f" => [16, "-a"], "\x10" => [94, "-c"], "\x11" => [76, "-c"], "\x12" => [104, "-c"], "\x13" => [16, "-c"], "\x14" => [94, "-e"], "\x15" => [76, "-e"], "\x16" => [104, "-e"], "\x17" => [16, "-e"], "\x18" => [94, "-i"], "\x19" => [76, "-i"], "\x1a" => [104, "-i"], "\x1b" => [16, "-i"], "\x1c" => [94, "-o"], "\x1d" => [76, "-o"], "\x1e" => [104, "-o"], "\x1f" => [16, "-o"], " " => [94, "-s"], "!" => [76, "-s"], "\"" => [104, "-s"], "#" => [16, "-s"], "\$" => [94, "-t"], "%" => [76, "-t"], "&" => [104, "-t"], "'" => [16, "-t"], "(" => [77, "- "], ")" => [18, "- "], "*" => [77, "-%"], "+" => [18, "-%"], "," => [77, "--"], "-" => [18, "--"], "." => [77, "-."], "/" => [18, "-."], [77, "-/"], [18, "-/"], [77, "-3"], [18, "-3"], [77, "-4"], [18, "-4"], [77, "-5"], [18, "-5"], [77, "-6"], [18, "-6"], ":" => [77, "-7"], ";" => [18, "-7"], "<" => [77, "-8"], "=" => [18, "-8"], ">" => [77, "-9"], "?" => [18, "-9"], "@" => [77, "-="], "A" => [18, "-="], "B" => [77, "-A"], "C" => [18, "-A"], "D" => [77, "-_"], "E" => [18, "-_"], "F" => [77, "-b"], "G" => [18, "-b"], "H" => [77, "-d"], "I" => [18, "-d"], "J" => [77, "-f"], "K" => [18, "-f"], "L" => [77, "-g"], "M" => [18, "-g"], "N" => [77, "-h"], "O" => [18, "-h"], "P" => [77, "-l"], "Q" => [18, "-l"], "R" => [77, "-m"], "S" => [18, "-m"], "T" => [77, "-n"], "U" => [18, "-n"], "V" => [77, "-p"], "W" => [18, "-p"], "X" => [77, "-r"], "Y" => [18, "-r"], "Z" => [77, "-u"], "[" => [18, "-u"], "\\" => [0, "-:"], "]" => [0, "-B"], "^" => [0, "-C"], "_" => [0, "-D"], "`" => [0, "-E"], "a" => [0, "-F"], "b" => [0, "-G"], "c" => [0, "-H"], "d" => [0, "-I"], "e" => [0, "-J"], "f" => [0, "-K"], "g" => [0, "-L"], "h" => [0, "-M"], "i" => [0, "-N"], "j" => [0, "-O"], "k" => [0, "-P"], "l" => [0, "-Q"], "m" => [0, "-R"], "n" => [0, "-S"], "o" => [0, "-T"], "p" => [0, "-U"], "q" => [0, "-V"], "r" => [0, "-W"], "s" => [0, "-Y"], "t" => [0, "-j"], "u" => [0, "-k"], "v" => [0, "-q"], "w" => [0, "-v"], "x" => [0, "-w"], "y" => [0, "-x"], "z" => [0, "-y"], "{" => [0, "-z"], "|" => [82, "-"], "}" => [87, "-"], "~" => [130, "-"], "" => [9, "-"], "\x80" => [94, ".0"], "\x81" => [76, ".0"], "\x82" => [104, ".0"], "\x83" => [16, ".0"], "\x84" => [94, ".1"], "\x85" => [76, ".1"], "\x86" => [104, ".1"], "\x87" => [16, ".1"], "\x88" => [94, ".2"], "\x89" => [76, ".2"], "\x8a" => [104, ".2"], "\x8b" => [16, ".2"], "\x8c" => [94, ".a"], "\x8d" => [76, ".a"], "\x8e" => [104, ".a"], "\x8f" => [16, ".a"], "\x90" => [94, ".c"], "\x91" => [76, ".c"], "\x92" => [104, ".c"], "\x93" => [16, ".c"], "\x94" => [94, ".e"], "\x95" => [76, ".e"], "\x96" => [104, ".e"], "\x97" => [16, ".e"], "\x98" => [94, ".i"], "\x99" => [76, ".i"], "\x9a" => [104, ".i"], "\x9b" => [16, ".i"], "\x9c" => [94, ".o"], "\x9d" => [76, ".o"], "\x9e" => [104, ".o"], "\x9f" => [16, ".o"], "\xa0" => [94, ".s"], "\xa1" => [76, ".s"], "\xa2" => [104, ".s"], "\xa3" => [16, ".s"], "\xa4" => [94, ".t"], "\xa5" => [76, ".t"], "\xa6" => [104, ".t"], "\xa7" => [16, ".t"], "\xa8" => [77, ". "], "\xa9" => [18, ". "], "\xaa" => [77, ".%"], "\xab" => [18, ".%"], "\xac" => [77, ".-"], "\xad" => [18, ".-"], "\xae" => [77, ".."], "\xaf" => [18, ".."], "\xb0" => [77, "./"], "\xb1" => [18, "./"], "\xb2" => [77, ".3"], "\xb3" => [18, ".3"], "\xb4" => [77, ".4"], "\xb5" => [18, ".4"], "\xb6" => [77, ".5"], "\xb7" => [18, ".5"], "\xb8" => [77, ".6"], "\xb9" => [18, ".6"], "\xba" => [77, ".7"], "\xbb" => [18, ".7"], "\xbc" => [77, ".8"], "\xbd" => [18, ".8"], "\xbe" => [77, ".9"], "\xbf" => [18, ".9"], "\xc0" => [77, ".="], "\xc1" => [18, ".="], "\xc2" => [77, ".A"], "\xc3" => [18, ".A"], "\xc4" => [77, "._"], "\xc5" => [18, "._"], "\xc6" => [77, ".b"], "\xc7" => [18, ".b"], "\xc8" => [77, ".d"], "\xc9" => [18, ".d"], "\xca" => [77, ".f"], "\xcb" => [18, ".f"], "\xcc" => [77, ".g"], "\xcd" => [18, ".g"], "\xce" => [77, ".h"], "\xcf" => [18, ".h"], "\xd0" => [77, ".l"], "\xd1" => [18, ".l"], "\xd2" => [77, ".m"], "\xd3" => [18, ".m"], "\xd4" => [77, ".n"], "\xd5" => [18, ".n"], "\xd6" => [77, ".p"], "\xd7" => [18, ".p"], "\xd8" => [77, ".r"], "\xd9" => [18, ".r"], "\xda" => [77, ".u"], "\xdb" => [18, ".u"], "\xdc" => [0, ".:"], "\xdd" => [0, ".B"], "\xde" => [0, ".C"], "\xdf" => [0, ".D"], "\xe0" => [0, ".E"], "\xe1" => [0, ".F"], "\xe2" => [0, ".G"], "\xe3" => [0, ".H"], "\xe4" => [0, ".I"], "\xe5" => [0, ".J"], "\xe6" => [0, ".K"], "\xe7" => [0, ".L"], "\xe8" => [0, ".M"], "\xe9" => [0, ".N"], "\xea" => [0, ".O"], "\xeb" => [0, ".P"], "\xec" => [0, ".Q"], "\xed" => [0, ".R"], "\xee" => [0, ".S"], "\xef" => [0, ".T"], "\xf0" => [0, ".U"], "\xf1" => [0, ".V"], "\xf2" => [0, ".W"], "\xf3" => [0, ".Y"], "\xf4" => [0, ".j"], "\xf5" => [0, ".k"], "\xf6" => [0, ".q"], "\xf7" => [0, ".v"], "\xf8" => [0, ".w"], "\xf9" => [0, ".x"], "\xfa" => [0, ".y"], "\xfb" => [0, ".z"], "\xfc" => [82, "."], "\xfd" => [87, "."], "\xfe" => [130, "."], "\xff" => [9, "."]], ["\x00" => [94, "/0"], "\x01" => [76, "/0"], "\x02" => [104, "/0"], "\x03" => [16, "/0"], "\x04" => [94, "/1"], "\x05" => [76, "/1"], "\x06" => [104, "/1"], "\x07" => [16, "/1"], "\x08" => [94, "/2"], "\t" => [76, "/2"], "\n" => [104, "/2"], "\v" => [16, "/2"], "\f" => [94, "/a"], "\r" => [76, "/a"], "\x0e" => [104, "/a"], "\x0f" => [16, "/a"], "\x10" => [94, "/c"], "\x11" => [76, "/c"], "\x12" => [104, "/c"], "\x13" => [16, "/c"], "\x14" => [94, "/e"], "\x15" => [76, "/e"], "\x16" => [104, "/e"], "\x17" => [16, "/e"], "\x18" => [94, "/i"], "\x19" => [76, "/i"], "\x1a" => [104, "/i"], "\x1b" => [16, "/i"], "\x1c" => [94, "/o"], "\x1d" => [76, "/o"], "\x1e" => [104, "/o"], "\x1f" => [16, "/o"], " " => [94, "/s"], "!" => [76, "/s"], "\"" => [104, "/s"], "#" => [16, "/s"], "\$" => [94, "/t"], "%" => [76, "/t"], "&" => [104, "/t"], "'" => [16, "/t"], "(" => [77, "/ "], ")" => [18, "/ "], "*" => [77, "/%"], "+" => [18, "/%"], "," => [77, "/-"], "-" => [18, "/-"], "." => [77, "/."], "/" => [18, "/."], [77, "//"], [18, "//"], [77, "/3"], [18, "/3"], [77, "/4"], [18, "/4"], [77, "/5"], [18, "/5"], [77, "/6"], [18, "/6"], ":" => [77, "/7"], ";" => [18, "/7"], "<" => [77, "/8"], "=" => [18, "/8"], ">" => [77, "/9"], "?" => [18, "/9"], "@" => [77, "/="], "A" => [18, "/="], "B" => [77, "/A"], "C" => [18, "/A"], "D" => [77, "/_"], "E" => [18, "/_"], "F" => [77, "/b"], "G" => [18, "/b"], "H" => [77, "/d"], "I" => [18, "/d"], "J" => [77, "/f"], "K" => [18, "/f"], "L" => [77, "/g"], "M" => [18, "/g"], "N" => [77, "/h"], "O" => [18, "/h"], "P" => [77, "/l"], "Q" => [18, "/l"], "R" => [77, "/m"], "S" => [18, "/m"], "T" => [77, "/n"], "U" => [18, "/n"], "V" => [77, "/p"], "W" => [18, "/p"], "X" => [77, "/r"], "Y" => [18, "/r"], "Z" => [77, "/u"], "[" => [18, "/u"], "\\" => [0, "/:"], "]" => [0, "/B"], "^" => [0, "/C"], "_" => [0, "/D"], "`" => [0, "/E"], "a" => [0, "/F"], "b" => [0, "/G"], "c" => [0, "/H"], "d" => [0, "/I"], "e" => [0, "/J"], "f" => [0, "/K"], "g" => [0, "/L"], "h" => [0, "/M"], "i" => [0, "/N"], "j" => [0, "/O"], "k" => [0, "/P"], "l" => [0, "/Q"], "m" => [0, "/R"], "n" => [0, "/S"], "o" => [0, "/T"], "p" => [0, "/U"], "q" => [0, "/V"], "r" => [0, "/W"], "s" => [0, "/Y"], "t" => [0, "/j"], "u" => [0, "/k"], "v" => [0, "/q"], "w" => [0, "/v"], "x" => [0, "/w"], "y" => [0, "/x"], "z" => [0, "/y"], "{" => [0, "/z"], "|" => [82, "/"], "}" => [87, "/"], "~" => [130, "/"], "" => [9, "/"], "\x80" => [94, "30"], "\x81" => [76, "30"], "\x82" => [104, "30"], "\x83" => [16, "30"], "\x84" => [94, "31"], "\x85" => [76, "31"], "\x86" => [104, "31"], "\x87" => [16, "31"], "\x88" => [94, "32"], "\x89" => [76, "32"], "\x8a" => [104, "32"], "\x8b" => [16, "32"], "\x8c" => [94, "3a"], "\x8d" => [76, "3a"], "\x8e" => [104, "3a"], "\x8f" => [16, "3a"], "\x90" => [94, "3c"], "\x91" => [76, "3c"], "\x92" => [104, "3c"], "\x93" => [16, "3c"], "\x94" => [94, "3e"], "\x95" => [76, "3e"], "\x96" => [104, "3e"], "\x97" => [16, "3e"], "\x98" => [94, "3i"], "\x99" => [76, "3i"], "\x9a" => [104, "3i"], "\x9b" => [16, "3i"], "\x9c" => [94, "3o"], "\x9d" => [76, "3o"], "\x9e" => [104, "3o"], "\x9f" => [16, "3o"], "\xa0" => [94, "3s"], "\xa1" => [76, "3s"], "\xa2" => [104, "3s"], "\xa3" => [16, "3s"], "\xa4" => [94, "3t"], "\xa5" => [76, "3t"], "\xa6" => [104, "3t"], "\xa7" => [16, "3t"], "\xa8" => [77, "3 "], "\xa9" => [18, "3 "], "\xaa" => [77, "3%"], "\xab" => [18, "3%"], "\xac" => [77, "3-"], "\xad" => [18, "3-"], "\xae" => [77, "3."], "\xaf" => [18, "3."], "\xb0" => [77, "3/"], "\xb1" => [18, "3/"], "\xb2" => [77, "33"], "\xb3" => [18, "33"], "\xb4" => [77, "34"], "\xb5" => [18, "34"], "\xb6" => [77, "35"], "\xb7" => [18, "35"], "\xb8" => [77, "36"], "\xb9" => [18, "36"], "\xba" => [77, "37"], "\xbb" => [18, "37"], "\xbc" => [77, "38"], "\xbd" => [18, "38"], "\xbe" => [77, "39"], "\xbf" => [18, "39"], "\xc0" => [77, "3="], "\xc1" => [18, "3="], "\xc2" => [77, "3A"], "\xc3" => [18, "3A"], "\xc4" => [77, "3_"], "\xc5" => [18, "3_"], "\xc6" => [77, "3b"], "\xc7" => [18, "3b"], "\xc8" => [77, "3d"], "\xc9" => [18, "3d"], "\xca" => [77, "3f"], "\xcb" => [18, "3f"], "\xcc" => [77, "3g"], "\xcd" => [18, "3g"], "\xce" => [77, "3h"], "\xcf" => [18, "3h"], "\xd0" => [77, "3l"], "\xd1" => [18, "3l"], "\xd2" => [77, "3m"], "\xd3" => [18, "3m"], "\xd4" => [77, "3n"], "\xd5" => [18, "3n"], "\xd6" => [77, "3p"], "\xd7" => [18, "3p"], "\xd8" => [77, "3r"], "\xd9" => [18, "3r"], "\xda" => [77, "3u"], "\xdb" => [18, "3u"], "\xdc" => [0, "3:"], "\xdd" => [0, "3B"], "\xde" => [0, "3C"], "\xdf" => [0, "3D"], "\xe0" => [0, "3E"], "\xe1" => [0, "3F"], "\xe2" => [0, "3G"], "\xe3" => [0, "3H"], "\xe4" => [0, "3I"], "\xe5" => [0, "3J"], "\xe6" => [0, "3K"], "\xe7" => [0, "3L"], "\xe8" => [0, "3M"], "\xe9" => [0, "3N"], "\xea" => [0, "3O"], "\xeb" => [0, "3P"], "\xec" => [0, "3Q"], "\xed" => [0, "3R"], "\xee" => [0, "3S"], "\xef" => [0, "3T"], "\xf0" => [0, "3U"], "\xf1" => [0, "3V"], "\xf2" => [0, "3W"], "\xf3" => [0, "3Y"], "\xf4" => [0, "3j"], "\xf5" => [0, "3k"], "\xf6" => [0, "3q"], "\xf7" => [0, "3v"], "\xf8" => [0, "3w"], "\xf9" => [0, "3x"], "\xfa" => [0, "3y"], "\xfb" => [0, "3z"], "\xfc" => [82, "3"], "\xfd" => [87, "3"], "\xfe" => [130, "3"], "\xff" => [9, "3"]], ["\x00" => [77, "/0"], "\x01" => [18, "/0"], "\x02" => [77, "/1"], "\x03" => [18, "/1"], "\x04" => [77, "/2"], "\x05" => [18, "/2"], "\x06" => [77, "/a"], "\x07" => [18, "/a"], "\x08" => [77, "/c"], "\t" => [18, "/c"], "\n" => [77, "/e"], "\v" => [18, "/e"], "\f" => [77, "/i"], "\r" => [18, "/i"], "\x0e" => [77, "/o"], "\x0f" => [18, "/o"], "\x10" => [77, "/s"], "\x11" => [18, "/s"], "\x12" => [77, "/t"], "\x13" => [18, "/t"], "\x14" => [0, "/ "], "\x15" => [0, "/%"], "\x16" => [0, "/-"], "\x17" => [0, "/."], "\x18" => [0, "//"], "\x19" => [0, "/3"], "\x1a" => [0, "/4"], "\x1b" => [0, "/5"], "\x1c" => [0, "/6"], "\x1d" => [0, "/7"], "\x1e" => [0, "/8"], "\x1f" => [0, "/9"], " " => [0, "/="], "!" => [0, "/A"], "\"" => [0, "/_"], "#" => [0, "/b"], "\$" => [0, "/d"], "%" => [0, "/f"], "&" => [0, "/g"], "'" => [0, "/h"], "(" => [0, "/l"], ")" => [0, "/m"], "*" => [0, "/n"], "+" => [0, "/p"], "," => [0, "/r"], "-" => [0, "/u"], "." => [100, "/"], "/" => [110, "/"], [111, "/"], [115, "/"], [116, "/"], [118, "/"], [119, "/"], [122, "/"], [123, "/"], [125, "/"], [126, "/"], [129, "/"], ":" => [143, "/"], ";" => [148, "/"], "<" => [151, "/"], "=" => [153, "/"], ">" => [83, "/"], "?" => [10, "/"], "@" => [77, "30"], "A" => [18, "30"], "B" => [77, "31"], "C" => [18, "31"], "D" => [77, "32"], "E" => [18, "32"], "F" => [77, "3a"], "G" => [18, "3a"], "H" => [77, "3c"], "I" => [18, "3c"], "J" => [77, "3e"], "K" => [18, "3e"], "L" => [77, "3i"], "M" => [18, "3i"], "N" => [77, "3o"], "O" => [18, "3o"], "P" => [77, "3s"], "Q" => [18, "3s"], "R" => [77, "3t"], "S" => [18, "3t"], "T" => [0, "3 "], "U" => [0, "3%"], "V" => [0, "3-"], "W" => [0, "3."], "X" => [0, "3/"], "Y" => [0, "33"], "Z" => [0, "34"], "[" => [0, "35"], "\\" => [0, "36"], "]" => [0, "37"], "^" => [0, "38"], "_" => [0, "39"], "`" => [0, "3="], "a" => [0, "3A"], "b" => [0, "3_"], "c" => [0, "3b"], "d" => [0, "3d"], "e" => [0, "3f"], "f" => [0, "3g"], "g" => [0, "3h"], "h" => [0, "3l"], "i" => [0, "3m"], "j" => [0, "3n"], "k" => [0, "3p"], "l" => [0, "3r"], "m" => [0, "3u"], "n" => [100, "3"], "o" => [110, "3"], "p" => [111, "3"], "q" => [115, "3"], "r" => [116, "3"], "s" => [118, "3"], "t" => [119, "3"], "u" => [122, "3"], "v" => [123, "3"], "w" => [125, "3"], "x" => [126, "3"], "y" => [129, "3"], "z" => [143, "3"], "{" => [148, "3"], "|" => [151, "3"], "}" => [153, "3"], "~" => [83, "3"], "" => [10, "3"], "\x80" => [77, "40"], "\x81" => [18, "40"], "\x82" => [77, "41"], "\x83" => [18, "41"], "\x84" => [77, "42"], "\x85" => [18, "42"], "\x86" => [77, "4a"], "\x87" => [18, "4a"], "\x88" => [77, "4c"], "\x89" => [18, "4c"], "\x8a" => [77, "4e"], "\x8b" => [18, "4e"], "\x8c" => [77, "4i"], "\x8d" => [18, "4i"], "\x8e" => [77, "4o"], "\x8f" => [18, "4o"], "\x90" => [77, "4s"], "\x91" => [18, "4s"], "\x92" => [77, "4t"], "\x93" => [18, "4t"], "\x94" => [0, "4 "], "\x95" => [0, "4%"], "\x96" => [0, "4-"], "\x97" => [0, "4."], "\x98" => [0, "4/"], "\x99" => [0, "43"], "\x9a" => [0, "44"], "\x9b" => [0, "45"], "\x9c" => [0, "46"], "\x9d" => [0, "47"], "\x9e" => [0, "48"], "\x9f" => [0, "49"], "\xa0" => [0, "4="], "\xa1" => [0, "4A"], "\xa2" => [0, "4_"], "\xa3" => [0, "4b"], "\xa4" => [0, "4d"], "\xa5" => [0, "4f"], "\xa6" => [0, "4g"], "\xa7" => [0, "4h"], "\xa8" => [0, "4l"], "\xa9" => [0, "4m"], "\xaa" => [0, "4n"], "\xab" => [0, "4p"], "\xac" => [0, "4r"], "\xad" => [0, "4u"], "\xae" => [100, "4"], "\xaf" => [110, "4"], "\xb0" => [111, "4"], "\xb1" => [115, "4"], "\xb2" => [116, "4"], "\xb3" => [118, "4"], "\xb4" => [119, "4"], "\xb5" => [122, "4"], "\xb6" => [123, "4"], "\xb7" => [125, "4"], "\xb8" => [126, "4"], "\xb9" => [129, "4"], "\xba" => [143, "4"], "\xbb" => [148, "4"], "\xbc" => [151, "4"], "\xbd" => [153, "4"], "\xbe" => [83, "4"], "\xbf" => [10, "4"], "\xc0" => [77, "50"], "\xc1" => [18, "50"], "\xc2" => [77, "51"], "\xc3" => [18, "51"], "\xc4" => [77, "52"], "\xc5" => [18, "52"], "\xc6" => [77, "5a"], "\xc7" => [18, "5a"], "\xc8" => [77, "5c"], "\xc9" => [18, "5c"], "\xca" => [77, "5e"], "\xcb" => [18, "5e"], "\xcc" => [77, "5i"], "\xcd" => [18, "5i"], "\xce" => [77, "5o"], "\xcf" => [18, "5o"], "\xd0" => [77, "5s"], "\xd1" => [18, "5s"], "\xd2" => [77, "5t"], "\xd3" => [18, "5t"], "\xd4" => [0, "5 "], "\xd5" => [0, "5%"], "\xd6" => [0, "5-"], "\xd7" => [0, "5."], "\xd8" => [0, "5/"], "\xd9" => [0, "53"], "\xda" => [0, "54"], "\xdb" => [0, "55"], "\xdc" => [0, "56"], "\xdd" => [0, "57"], "\xde" => [0, "58"], "\xdf" => [0, "59"], "\xe0" => [0, "5="], "\xe1" => [0, "5A"], "\xe2" => [0, "5_"], "\xe3" => [0, "5b"], "\xe4" => [0, "5d"], "\xe5" => [0, "5f"], "\xe6" => [0, "5g"], "\xe7" => [0, "5h"], "\xe8" => [0, "5l"], "\xe9" => [0, "5m"], "\xea" => [0, "5n"], "\xeb" => [0, "5p"], "\xec" => [0, "5r"], "\xed" => [0, "5u"], "\xee" => [100, "5"], "\xef" => [110, "5"], "\xf0" => [111, "5"], "\xf1" => [115, "5"], "\xf2" => [116, "5"], "\xf3" => [118, "5"], "\xf4" => [119, "5"], "\xf5" => [122, "5"], "\xf6" => [123, "5"], "\xf7" => [125, "5"], "\xf8" => [126, "5"], "\xf9" => [129, "5"], "\xfa" => [143, "5"], "\xfb" => [148, "5"], "\xfc" => [151, "5"], "\xfd" => [153, "5"], "\xfe" => [83, "5"], "\xff" => [10, "5"]], ["\x00" => [0, "/0"], "\x01" => [0, "/1"], "\x02" => [0, "/2"], "\x03" => [0, "/a"], "\x04" => [0, "/c"], "\x05" => [0, "/e"], "\x06" => [0, "/i"], "\x07" => [0, "/o"], "\x08" => [0, "/s"], "\t" => [0, "/t"], "\n" => [73, "/"], "\v" => [88, "/"], "\f" => [89, "/"], "\r" => [96, "/"], "\x0e" => [97, "/"], "\x0f" => [99, "/"], "\x10" => [106, "/"], "\x11" => [136, "/"], "\x12" => [139, "/"], "\x13" => [141, "/"], "\x14" => [145, "/"], "\x15" => [147, "/"], "\x16" => [149, "/"], "\x17" => [101, "/"], "\x18" => [112, "/"], "\x19" => [117, "/"], "\x1a" => [120, "/"], "\x1b" => [124, "/"], "\x1c" => [127, "/"], "\x1d" => [144, "/"], "\x1e" => [152, "/"], "\x1f" => [11, "/"], " " => [0, "30"], "!" => [0, "31"], "\"" => [0, "32"], "#" => [0, "3a"], "\$" => [0, "3c"], "%" => [0, "3e"], "&" => [0, "3i"], "'" => [0, "3o"], "(" => [0, "3s"], ")" => [0, "3t"], "*" => [73, "3"], "+" => [88, "3"], "," => [89, "3"], "-" => [96, "3"], "." => [97, "3"], "/" => [99, "3"], [106, "3"], [136, "3"], [139, "3"], [141, "3"], [145, "3"], [147, "3"], [149, "3"], [101, "3"], [112, "3"], [117, "3"], ":" => [120, "3"], ";" => [124, "3"], "<" => [127, "3"], "=" => [144, "3"], ">" => [152, "3"], "?" => [11, "3"], "@" => [0, "40"], "A" => [0, "41"], "B" => [0, "42"], "C" => [0, "4a"], "D" => [0, "4c"], "E" => [0, "4e"], "F" => [0, "4i"], "G" => [0, "4o"], "H" => [0, "4s"], "I" => [0, "4t"], "J" => [73, "4"], "K" => [88, "4"], "L" => [89, "4"], "M" => [96, "4"], "N" => [97, "4"], "O" => [99, "4"], "P" => [106, "4"], "Q" => [136, "4"], "R" => [139, "4"], "S" => [141, "4"], "T" => [145, "4"], "U" => [147, "4"], "V" => [149, "4"], "W" => [101, "4"], "X" => [112, "4"], "Y" => [117, "4"], "Z" => [120, "4"], "[" => [124, "4"], "\\" => [127, "4"], "]" => [144, "4"], "^" => [152, "4"], "_" => [11, "4"], "`" => [0, "50"], "a" => [0, "51"], "b" => [0, "52"], "c" => [0, "5a"], "d" => [0, "5c"], "e" => [0, "5e"], "f" => [0, "5i"], "g" => [0, "5o"], "h" => [0, "5s"], "i" => [0, "5t"], "j" => [73, "5"], "k" => [88, "5"], "l" => [89, "5"], "m" => [96, "5"], "n" => [97, "5"], "o" => [99, "5"], "p" => [106, "5"], "q" => [136, "5"], "r" => [139, "5"], "s" => [141, "5"], "t" => [145, "5"], "u" => [147, "5"], "v" => [149, "5"], "w" => [101, "5"], "x" => [112, "5"], "y" => [117, "5"], "z" => [120, "5"], "{" => [124, "5"], "|" => [127, "5"], "}" => [144, "5"], "~" => [152, "5"], "" => [11, "5"], "\x80" => [0, "60"], "\x81" => [0, "61"], "\x82" => [0, "62"], "\x83" => [0, "6a"], "\x84" => [0, "6c"], "\x85" => [0, "6e"], "\x86" => [0, "6i"], "\x87" => [0, "6o"], "\x88" => [0, "6s"], "\x89" => [0, "6t"], "\x8a" => [73, "6"], "\x8b" => [88, "6"], "\x8c" => [89, "6"], "\x8d" => [96, "6"], "\x8e" => [97, "6"], "\x8f" => [99, "6"], "\x90" => [106, "6"], "\x91" => [136, "6"], "\x92" => [139, "6"], "\x93" => [141, "6"], "\x94" => [145, "6"], "\x95" => [147, "6"], "\x96" => [149, "6"], "\x97" => [101, "6"], "\x98" => [112, "6"], "\x99" => [117, "6"], "\x9a" => [120, "6"], "\x9b" => [124, "6"], "\x9c" => [127, "6"], "\x9d" => [144, "6"], "\x9e" => [152, "6"], "\x9f" => [11, "6"], "\xa0" => [0, "70"], "\xa1" => [0, "71"], "\xa2" => [0, "72"], "\xa3" => [0, "7a"], "\xa4" => [0, "7c"], "\xa5" => [0, "7e"], "\xa6" => [0, "7i"], "\xa7" => [0, "7o"], "\xa8" => [0, "7s"], "\xa9" => [0, "7t"], "\xaa" => [73, "7"], "\xab" => [88, "7"], "\xac" => [89, "7"], "\xad" => [96, "7"], "\xae" => [97, "7"], "\xaf" => [99, "7"], "\xb0" => [106, "7"], "\xb1" => [136, "7"], "\xb2" => [139, "7"], "\xb3" => [141, "7"], "\xb4" => [145, "7"], "\xb5" => [147, "7"], "\xb6" => [149, "7"], "\xb7" => [101, "7"], "\xb8" => [112, "7"], "\xb9" => [117, "7"], "\xba" => [120, "7"], "\xbb" => [124, "7"], "\xbc" => [127, "7"], "\xbd" => [144, "7"], "\xbe" => [152, "7"], "\xbf" => [11, "7"], "\xc0" => [0, "80"], "\xc1" => [0, "81"], "\xc2" => [0, "82"], "\xc3" => [0, "8a"], "\xc4" => [0, "8c"], "\xc5" => [0, "8e"], "\xc6" => [0, "8i"], "\xc7" => [0, "8o"], "\xc8" => [0, "8s"], "\xc9" => [0, "8t"], "\xca" => [73, "8"], "\xcb" => [88, "8"], "\xcc" => [89, "8"], "\xcd" => [96, "8"], "\xce" => [97, "8"], "\xcf" => [99, "8"], "\xd0" => [106, "8"], "\xd1" => [136, "8"], "\xd2" => [139, "8"], "\xd3" => [141, "8"], "\xd4" => [145, "8"], "\xd5" => [147, "8"], "\xd6" => [149, "8"], "\xd7" => [101, "8"], "\xd8" => [112, "8"], "\xd9" => [117, "8"], "\xda" => [120, "8"], "\xdb" => [124, "8"], "\xdc" => [127, "8"], "\xdd" => [144, "8"], "\xde" => [152, "8"], "\xdf" => [11, "8"], "\xe0" => [0, "90"], "\xe1" => [0, "91"], "\xe2" => [0, "92"], "\xe3" => [0, "9a"], "\xe4" => [0, "9c"], "\xe5" => [0, "9e"], "\xe6" => [0, "9i"], "\xe7" => [0, "9o"], "\xe8" => [0, "9s"], "\xe9" => [0, "9t"], "\xea" => [73, "9"], "\xeb" => [88, "9"], "\xec" => [89, "9"], "\xed" => [96, "9"], "\xee" => [97, "9"], "\xef" => [99, "9"], "\xf0" => [106, "9"], "\xf1" => [136, "9"], "\xf2" => [139, "9"], "\xf3" => [141, "9"], "\xf4" => [145, "9"], "\xf5" => [147, "9"], "\xf6" => [149, "9"], "\xf7" => [101, "9"], "\xf8" => [112, "9"], "\xf9" => [117, "9"], "\xfa" => [120, "9"], "\xfb" => [124, "9"], "\xfc" => [127, "9"], "\xfd" => [144, "9"], "\xfe" => [152, "9"], "\xff" => [11, "9"]], ["\x00" => [94, "00"], "\x01" => [76, "00"], "\x02" => [104, "00"], "\x03" => [16, "00"], "\x04" => [94, "01"], "\x05" => [76, "01"], "\x06" => [104, "01"], "\x07" => [16, "01"], "\x08" => [94, "02"], "\t" => [76, "02"], "\n" => [104, "02"], "\v" => [16, "02"], "\f" => [94, "0a"], "\r" => [76, "0a"], "\x0e" => [104, "0a"], "\x0f" => [16, "0a"], "\x10" => [94, "0c"], "\x11" => [76, "0c"], "\x12" => [104, "0c"], "\x13" => [16, "0c"], "\x14" => [94, "0e"], "\x15" => [76, "0e"], "\x16" => [104, "0e"], "\x17" => [16, "0e"], "\x18" => [94, "0i"], "\x19" => [76, "0i"], "\x1a" => [104, "0i"], "\x1b" => [16, "0i"], "\x1c" => [94, "0o"], "\x1d" => [76, "0o"], "\x1e" => [104, "0o"], "\x1f" => [16, "0o"], " " => [94, "0s"], "!" => [76, "0s"], "\"" => [104, "0s"], "#" => [16, "0s"], "\$" => [94, "0t"], "%" => [76, "0t"], "&" => [104, "0t"], "'" => [16, "0t"], "(" => [77, "0 "], ")" => [18, "0 "], "*" => [77, "0%"], "+" => [18, "0%"], "," => [77, "0-"], "-" => [18, "0-"], "." => [77, "0."], "/" => [18, "0."], [77, "0/"], [18, "0/"], [77, "03"], [18, "03"], [77, "04"], [18, "04"], [77, "05"], [18, "05"], [77, "06"], [18, "06"], ":" => [77, "07"], ";" => [18, "07"], "<" => [77, "08"], "=" => [18, "08"], ">" => [77, "09"], "?" => [18, "09"], "@" => [77, "0="], "A" => [18, "0="], "B" => [77, "0A"], "C" => [18, "0A"], "D" => [77, "0_"], "E" => [18, "0_"], "F" => [77, "0b"], "G" => [18, "0b"], "H" => [77, "0d"], "I" => [18, "0d"], "J" => [77, "0f"], "K" => [18, "0f"], "L" => [77, "0g"], "M" => [18, "0g"], "N" => [77, "0h"], "O" => [18, "0h"], "P" => [77, "0l"], "Q" => [18, "0l"], "R" => [77, "0m"], "S" => [18, "0m"], "T" => [77, "0n"], "U" => [18, "0n"], "V" => [77, "0p"], "W" => [18, "0p"], "X" => [77, "0r"], "Y" => [18, "0r"], "Z" => [77, "0u"], "[" => [18, "0u"], "\\" => [0, "0:"], "]" => [0, "0B"], "^" => [0, "0C"], "_" => [0, "0D"], "`" => [0, "0E"], "a" => [0, "0F"], "b" => [0, "0G"], "c" => [0, "0H"], "d" => [0, "0I"], "e" => [0, "0J"], "f" => [0, "0K"], "g" => [0, "0L"], "h" => [0, "0M"], "i" => [0, "0N"], "j" => [0, "0O"], "k" => [0, "0P"], "l" => [0, "0Q"], "m" => [0, "0R"], "n" => [0, "0S"], "o" => [0, "0T"], "p" => [0, "0U"], "q" => [0, "0V"], "r" => [0, "0W"], "s" => [0, "0Y"], "t" => [0, "0j"], "u" => [0, "0k"], "v" => [0, "0q"], "w" => [0, "0v"], "x" => [0, "0w"], "y" => [0, "0x"], "z" => [0, "0y"], "{" => [0, "0z"], "|" => [82, "0"], "}" => [87, "0"], "~" => [130, "0"], "" => [9, "0"], "\x80" => [94, "10"], "\x81" => [76, "10"], "\x82" => [104, "10"], "\x83" => [16, "10"], "\x84" => [94, "11"], "\x85" => [76, "11"], "\x86" => [104, "11"], "\x87" => [16, "11"], "\x88" => [94, "12"], "\x89" => [76, "12"], "\x8a" => [104, "12"], "\x8b" => [16, "12"], "\x8c" => [94, "1a"], "\x8d" => [76, "1a"], "\x8e" => [104, "1a"], "\x8f" => [16, "1a"], "\x90" => [94, "1c"], "\x91" => [76, "1c"], "\x92" => [104, "1c"], "\x93" => [16, "1c"], "\x94" => [94, "1e"], "\x95" => [76, "1e"], "\x96" => [104, "1e"], "\x97" => [16, "1e"], "\x98" => [94, "1i"], "\x99" => [76, "1i"], "\x9a" => [104, "1i"], "\x9b" => [16, "1i"], "\x9c" => [94, "1o"], "\x9d" => [76, "1o"], "\x9e" => [104, "1o"], "\x9f" => [16, "1o"], "\xa0" => [94, "1s"], "\xa1" => [76, "1s"], "\xa2" => [104, "1s"], "\xa3" => [16, "1s"], "\xa4" => [94, "1t"], "\xa5" => [76, "1t"], "\xa6" => [104, "1t"], "\xa7" => [16, "1t"], "\xa8" => [77, "1 "], "\xa9" => [18, "1 "], "\xaa" => [77, "1%"], "\xab" => [18, "1%"], "\xac" => [77, "1-"], "\xad" => [18, "1-"], "\xae" => [77, "1."], "\xaf" => [18, "1."], "\xb0" => [77, "1/"], "\xb1" => [18, "1/"], "\xb2" => [77, "13"], "\xb3" => [18, "13"], "\xb4" => [77, "14"], "\xb5" => [18, "14"], "\xb6" => [77, "15"], "\xb7" => [18, "15"], "\xb8" => [77, "16"], "\xb9" => [18, "16"], "\xba" => [77, "17"], "\xbb" => [18, "17"], "\xbc" => [77, "18"], "\xbd" => [18, "18"], "\xbe" => [77, "19"], "\xbf" => [18, "19"], "\xc0" => [77, "1="], "\xc1" => [18, "1="], "\xc2" => [77, "1A"], "\xc3" => [18, "1A"], "\xc4" => [77, "1_"], "\xc5" => [18, "1_"], "\xc6" => [77, "1b"], "\xc7" => [18, "1b"], "\xc8" => [77, "1d"], "\xc9" => [18, "1d"], "\xca" => [77, "1f"], "\xcb" => [18, "1f"], "\xcc" => [77, "1g"], "\xcd" => [18, "1g"], "\xce" => [77, "1h"], "\xcf" => [18, "1h"], "\xd0" => [77, "1l"], "\xd1" => [18, "1l"], "\xd2" => [77, "1m"], "\xd3" => [18, "1m"], "\xd4" => [77, "1n"], "\xd5" => [18, "1n"], "\xd6" => [77, "1p"], "\xd7" => [18, "1p"], "\xd8" => [77, "1r"], "\xd9" => [18, "1r"], "\xda" => [77, "1u"], "\xdb" => [18, "1u"], "\xdc" => [0, "1:"], "\xdd" => [0, "1B"], "\xde" => [0, "1C"], "\xdf" => [0, "1D"], "\xe0" => [0, "1E"], "\xe1" => [0, "1F"], "\xe2" => [0, "1G"], "\xe3" => [0, "1H"], "\xe4" => [0, "1I"], "\xe5" => [0, "1J"], "\xe6" => [0, "1K"], "\xe7" => [0, "1L"], "\xe8" => [0, "1M"], "\xe9" => [0, "1N"], "\xea" => [0, "1O"], "\xeb" => [0, "1P"], "\xec" => [0, "1Q"], "\xed" => [0, "1R"], "\xee" => [0, "1S"], "\xef" => [0, "1T"], "\xf0" => [0, "1U"], "\xf1" => [0, "1V"], "\xf2" => [0, "1W"], "\xf3" => [0, "1Y"], "\xf4" => [0, "1j"], "\xf5" => [0, "1k"], "\xf6" => [0, "1q"], "\xf7" => [0, "1v"], "\xf8" => [0, "1w"], "\xf9" => [0, "1x"], "\xfa" => [0, "1y"], "\xfb" => [0, "1z"], "\xfc" => [82, "1"], "\xfd" => [87, "1"], "\xfe" => [130, "1"], "\xff" => [9, "1"]], ["\x00" => [77, "00"], "\x01" => [18, "00"], "\x02" => [77, "01"], "\x03" => [18, "01"], "\x04" => [77, "02"], "\x05" => [18, "02"], "\x06" => [77, "0a"], "\x07" => [18, "0a"], "\x08" => [77, "0c"], "\t" => [18, "0c"], "\n" => [77, "0e"], "\v" => [18, "0e"], "\f" => [77, "0i"], "\r" => [18, "0i"], "\x0e" => [77, "0o"], "\x0f" => [18, "0o"], "\x10" => [77, "0s"], "\x11" => [18, "0s"], "\x12" => [77, "0t"], "\x13" => [18, "0t"], "\x14" => [0, "0 "], "\x15" => [0, "0%"], "\x16" => [0, "0-"], "\x17" => [0, "0."], "\x18" => [0, "0/"], "\x19" => [0, "03"], "\x1a" => [0, "04"], "\x1b" => [0, "05"], "\x1c" => [0, "06"], "\x1d" => [0, "07"], "\x1e" => [0, "08"], "\x1f" => [0, "09"], " " => [0, "0="], "!" => [0, "0A"], "\"" => [0, "0_"], "#" => [0, "0b"], "\$" => [0, "0d"], "%" => [0, "0f"], "&" => [0, "0g"], "'" => [0, "0h"], "(" => [0, "0l"], ")" => [0, "0m"], "*" => [0, "0n"], "+" => [0, "0p"], "," => [0, "0r"], "-" => [0, "0u"], "." => [100, "0"], "/" => [110, "0"], [111, "0"], [115, "0"], [116, "0"], [118, "0"], [119, "0"], [122, "0"], [123, "0"], [125, "0"], [126, "0"], [129, "0"], ":" => [143, "0"], ";" => [148, "0"], "<" => [151, "0"], "=" => [153, "0"], ">" => [83, "0"], "?" => [10, "0"], "@" => [77, "10"], "A" => [18, "10"], "B" => [77, "11"], "C" => [18, "11"], "D" => [77, "12"], "E" => [18, "12"], "F" => [77, "1a"], "G" => [18, "1a"], "H" => [77, "1c"], "I" => [18, "1c"], "J" => [77, "1e"], "K" => [18, "1e"], "L" => [77, "1i"], "M" => [18, "1i"], "N" => [77, "1o"], "O" => [18, "1o"], "P" => [77, "1s"], "Q" => [18, "1s"], "R" => [77, "1t"], "S" => [18, "1t"], "T" => [0, "1 "], "U" => [0, "1%"], "V" => [0, "1-"], "W" => [0, "1."], "X" => [0, "1/"], "Y" => [0, "13"], "Z" => [0, "14"], "[" => [0, "15"], "\\" => [0, "16"], "]" => [0, "17"], "^" => [0, "18"], "_" => [0, "19"], "`" => [0, "1="], "a" => [0, "1A"], "b" => [0, "1_"], "c" => [0, "1b"], "d" => [0, "1d"], "e" => [0, "1f"], "f" => [0, "1g"], "g" => [0, "1h"], "h" => [0, "1l"], "i" => [0, "1m"], "j" => [0, "1n"], "k" => [0, "1p"], "l" => [0, "1r"], "m" => [0, "1u"], "n" => [100, "1"], "o" => [110, "1"], "p" => [111, "1"], "q" => [115, "1"], "r" => [116, "1"], "s" => [118, "1"], "t" => [119, "1"], "u" => [122, "1"], "v" => [123, "1"], "w" => [125, "1"], "x" => [126, "1"], "y" => [129, "1"], "z" => [143, "1"], "{" => [148, "1"], "|" => [151, "1"], "}" => [153, "1"], "~" => [83, "1"], "" => [10, "1"], "\x80" => [77, "20"], "\x81" => [18, "20"], "\x82" => [77, "21"], "\x83" => [18, "21"], "\x84" => [77, "22"], "\x85" => [18, "22"], "\x86" => [77, "2a"], "\x87" => [18, "2a"], "\x88" => [77, "2c"], "\x89" => [18, "2c"], "\x8a" => [77, "2e"], "\x8b" => [18, "2e"], "\x8c" => [77, "2i"], "\x8d" => [18, "2i"], "\x8e" => [77, "2o"], "\x8f" => [18, "2o"], "\x90" => [77, "2s"], "\x91" => [18, "2s"], "\x92" => [77, "2t"], "\x93" => [18, "2t"], "\x94" => [0, "2 "], "\x95" => [0, "2%"], "\x96" => [0, "2-"], "\x97" => [0, "2."], "\x98" => [0, "2/"], "\x99" => [0, "23"], "\x9a" => [0, "24"], "\x9b" => [0, "25"], "\x9c" => [0, "26"], "\x9d" => [0, "27"], "\x9e" => [0, "28"], "\x9f" => [0, "29"], "\xa0" => [0, "2="], "\xa1" => [0, "2A"], "\xa2" => [0, "2_"], "\xa3" => [0, "2b"], "\xa4" => [0, "2d"], "\xa5" => [0, "2f"], "\xa6" => [0, "2g"], "\xa7" => [0, "2h"], "\xa8" => [0, "2l"], "\xa9" => [0, "2m"], "\xaa" => [0, "2n"], "\xab" => [0, "2p"], "\xac" => [0, "2r"], "\xad" => [0, "2u"], "\xae" => [100, "2"], "\xaf" => [110, "2"], "\xb0" => [111, "2"], "\xb1" => [115, "2"], "\xb2" => [116, "2"], "\xb3" => [118, "2"], "\xb4" => [119, "2"], "\xb5" => [122, "2"], "\xb6" => [123, "2"], "\xb7" => [125, "2"], "\xb8" => [126, "2"], "\xb9" => [129, "2"], "\xba" => [143, "2"], "\xbb" => [148, "2"], "\xbc" => [151, "2"], "\xbd" => [153, "2"], "\xbe" => [83, "2"], "\xbf" => [10, "2"], "\xc0" => [77, "a0"], "\xc1" => [18, "a0"], "\xc2" => [77, "a1"], "\xc3" => [18, "a1"], "\xc4" => [77, "a2"], "\xc5" => [18, "a2"], "\xc6" => [77, "aa"], "\xc7" => [18, "aa"], "\xc8" => [77, "ac"], "\xc9" => [18, "ac"], "\xca" => [77, "ae"], "\xcb" => [18, "ae"], "\xcc" => [77, "ai"], "\xcd" => [18, "ai"], "\xce" => [77, "ao"], "\xcf" => [18, "ao"], "\xd0" => [77, "as"], "\xd1" => [18, "as"], "\xd2" => [77, "at"], "\xd3" => [18, "at"], "\xd4" => [0, "a "], "\xd5" => [0, "a%"], "\xd6" => [0, "a-"], "\xd7" => [0, "a."], "\xd8" => [0, "a/"], "\xd9" => [0, "a3"], "\xda" => [0, "a4"], "\xdb" => [0, "a5"], "\xdc" => [0, "a6"], "\xdd" => [0, "a7"], "\xde" => [0, "a8"], "\xdf" => [0, "a9"], "\xe0" => [0, "a="], "\xe1" => [0, "aA"], "\xe2" => [0, "a_"], "\xe3" => [0, "ab"], "\xe4" => [0, "ad"], "\xe5" => [0, "af"], "\xe6" => [0, "ag"], "\xe7" => [0, "ah"], "\xe8" => [0, "al"], "\xe9" => [0, "am"], "\xea" => [0, "an"], "\xeb" => [0, "ap"], "\xec" => [0, "ar"], "\xed" => [0, "au"], "\xee" => [100, "a"], "\xef" => [110, "a"], "\xf0" => [111, "a"], "\xf1" => [115, "a"], "\xf2" => [116, "a"], "\xf3" => [118, "a"], "\xf4" => [119, "a"], "\xf5" => [122, "a"], "\xf6" => [123, "a"], "\xf7" => [125, "a"], "\xf8" => [126, "a"], "\xf9" => [129, "a"], "\xfa" => [143, "a"], "\xfb" => [148, "a"], "\xfc" => [151, "a"], "\xfd" => [153, "a"], "\xfe" => [83, "a"], "\xff" => [10, "a"]], ["\x00" => [0, "00"], "\x01" => [0, "01"], "\x02" => [0, "02"], "\x03" => [0, "0a"], "\x04" => [0, "0c"], "\x05" => [0, "0e"], "\x06" => [0, "0i"], "\x07" => [0, "0o"], "\x08" => [0, "0s"], "\t" => [0, "0t"], "\n" => [73, "0"], "\v" => [88, "0"], "\f" => [89, "0"], "\r" => [96, "0"], "\x0e" => [97, "0"], "\x0f" => [99, "0"], "\x10" => [106, "0"], "\x11" => [136, "0"], "\x12" => [139, "0"], "\x13" => [141, "0"], "\x14" => [145, "0"], "\x15" => [147, "0"], "\x16" => [149, "0"], "\x17" => [101, "0"], "\x18" => [112, "0"], "\x19" => [117, "0"], "\x1a" => [120, "0"], "\x1b" => [124, "0"], "\x1c" => [127, "0"], "\x1d" => [144, "0"], "\x1e" => [152, "0"], "\x1f" => [11, "0"], " " => [0, "10"], "!" => [0, "11"], "\"" => [0, "12"], "#" => [0, "1a"], "\$" => [0, "1c"], "%" => [0, "1e"], "&" => [0, "1i"], "'" => [0, "1o"], "(" => [0, "1s"], ")" => [0, "1t"], "*" => [73, "1"], "+" => [88, "1"], "," => [89, "1"], "-" => [96, "1"], "." => [97, "1"], "/" => [99, "1"], [106, "1"], [136, "1"], [139, "1"], [141, "1"], [145, "1"], [147, "1"], [149, "1"], [101, "1"], [112, "1"], [117, "1"], ":" => [120, "1"], ";" => [124, "1"], "<" => [127, "1"], "=" => [144, "1"], ">" => [152, "1"], "?" => [11, "1"], "@" => [0, "20"], "A" => [0, "21"], "B" => [0, "22"], "C" => [0, "2a"], "D" => [0, "2c"], "E" => [0, "2e"], "F" => [0, "2i"], "G" => [0, "2o"], "H" => [0, "2s"], "I" => [0, "2t"], "J" => [73, "2"], "K" => [88, "2"], "L" => [89, "2"], "M" => [96, "2"], "N" => [97, "2"], "O" => [99, "2"], "P" => [106, "2"], "Q" => [136, "2"], "R" => [139, "2"], "S" => [141, "2"], "T" => [145, "2"], "U" => [147, "2"], "V" => [149, "2"], "W" => [101, "2"], "X" => [112, "2"], "Y" => [117, "2"], "Z" => [120, "2"], "[" => [124, "2"], "\\" => [127, "2"], "]" => [144, "2"], "^" => [152, "2"], "_" => [11, "2"], "`" => [0, "a0"], "a" => [0, "a1"], "b" => [0, "a2"], "c" => [0, "aa"], "d" => [0, "ac"], "e" => [0, "ae"], "f" => [0, "ai"], "g" => [0, "ao"], "h" => [0, "as"], "i" => [0, "at"], "j" => [73, "a"], "k" => [88, "a"], "l" => [89, "a"], "m" => [96, "a"], "n" => [97, "a"], "o" => [99, "a"], "p" => [106, "a"], "q" => [136, "a"], "r" => [139, "a"], "s" => [141, "a"], "t" => [145, "a"], "u" => [147, "a"], "v" => [149, "a"], "w" => [101, "a"], "x" => [112, "a"], "y" => [117, "a"], "z" => [120, "a"], "{" => [124, "a"], "|" => [127, "a"], "}" => [144, "a"], "~" => [152, "a"], "" => [11, "a"], "\x80" => [0, "c0"], "\x81" => [0, "c1"], "\x82" => [0, "c2"], "\x83" => [0, "ca"], "\x84" => [0, "cc"], "\x85" => [0, "ce"], "\x86" => [0, "ci"], "\x87" => [0, "co"], "\x88" => [0, "cs"], "\x89" => [0, "ct"], "\x8a" => [73, "c"], "\x8b" => [88, "c"], "\x8c" => [89, "c"], "\x8d" => [96, "c"], "\x8e" => [97, "c"], "\x8f" => [99, "c"], "\x90" => [106, "c"], "\x91" => [136, "c"], "\x92" => [139, "c"], "\x93" => [141, "c"], "\x94" => [145, "c"], "\x95" => [147, "c"], "\x96" => [149, "c"], "\x97" => [101, "c"], "\x98" => [112, "c"], "\x99" => [117, "c"], "\x9a" => [120, "c"], "\x9b" => [124, "c"], "\x9c" => [127, "c"], "\x9d" => [144, "c"], "\x9e" => [152, "c"], "\x9f" => [11, "c"], "\xa0" => [0, "e0"], "\xa1" => [0, "e1"], "\xa2" => [0, "e2"], "\xa3" => [0, "ea"], "\xa4" => [0, "ec"], "\xa5" => [0, "ee"], "\xa6" => [0, "ei"], "\xa7" => [0, "eo"], "\xa8" => [0, "es"], "\xa9" => [0, "et"], "\xaa" => [73, "e"], "\xab" => [88, "e"], "\xac" => [89, "e"], "\xad" => [96, "e"], "\xae" => [97, "e"], "\xaf" => [99, "e"], "\xb0" => [106, "e"], "\xb1" => [136, "e"], "\xb2" => [139, "e"], "\xb3" => [141, "e"], "\xb4" => [145, "e"], "\xb5" => [147, "e"], "\xb6" => [149, "e"], "\xb7" => [101, "e"], "\xb8" => [112, "e"], "\xb9" => [117, "e"], "\xba" => [120, "e"], "\xbb" => [124, "e"], "\xbc" => [127, "e"], "\xbd" => [144, "e"], "\xbe" => [152, "e"], "\xbf" => [11, "e"], "\xc0" => [0, "i0"], "\xc1" => [0, "i1"], "\xc2" => [0, "i2"], "\xc3" => [0, "ia"], "\xc4" => [0, "ic"], "\xc5" => [0, "ie"], "\xc6" => [0, "ii"], "\xc7" => [0, "io"], "\xc8" => [0, "is"], "\xc9" => [0, "it"], "\xca" => [73, "i"], "\xcb" => [88, "i"], "\xcc" => [89, "i"], "\xcd" => [96, "i"], "\xce" => [97, "i"], "\xcf" => [99, "i"], "\xd0" => [106, "i"], "\xd1" => [136, "i"], "\xd2" => [139, "i"], "\xd3" => [141, "i"], "\xd4" => [145, "i"], "\xd5" => [147, "i"], "\xd6" => [149, "i"], "\xd7" => [101, "i"], "\xd8" => [112, "i"], "\xd9" => [117, "i"], "\xda" => [120, "i"], "\xdb" => [124, "i"], "\xdc" => [127, "i"], "\xdd" => [144, "i"], "\xde" => [152, "i"], "\xdf" => [11, "i"], "\xe0" => [0, "o0"], "\xe1" => [0, "o1"], "\xe2" => [0, "o2"], "\xe3" => [0, "oa"], "\xe4" => [0, "oc"], "\xe5" => [0, "oe"], "\xe6" => [0, "oi"], "\xe7" => [0, "oo"], "\xe8" => [0, "os"], "\xe9" => [0, "ot"], "\xea" => [73, "o"], "\xeb" => [88, "o"], "\xec" => [89, "o"], "\xed" => [96, "o"], "\xee" => [97, "o"], "\xef" => [99, "o"], "\xf0" => [106, "o"], "\xf1" => [136, "o"], "\xf2" => [139, "o"], "\xf3" => [141, "o"], "\xf4" => [145, "o"], "\xf5" => [147, "o"], "\xf6" => [149, "o"], "\xf7" => [101, "o"], "\xf8" => [112, "o"], "\xf9" => [117, "o"], "\xfa" => [120, "o"], "\xfb" => [124, "o"], "\xfc" => [127, "o"], "\xfd" => [144, "o"], "\xfe" => [152, "o"], "\xff" => [11, "o"]], ["\x00" => [94, "20"], "\x01" => [76, "20"], "\x02" => [104, "20"], "\x03" => [16, "20"], "\x04" => [94, "21"], "\x05" => [76, "21"], "\x06" => [104, "21"], "\x07" => [16, "21"], "\x08" => [94, "22"], "\t" => [76, "22"], "\n" => [104, "22"], "\v" => [16, "22"], "\f" => [94, "2a"], "\r" => [76, "2a"], "\x0e" => [104, "2a"], "\x0f" => [16, "2a"], "\x10" => [94, "2c"], "\x11" => [76, "2c"], "\x12" => [104, "2c"], "\x13" => [16, "2c"], "\x14" => [94, "2e"], "\x15" => [76, "2e"], "\x16" => [104, "2e"], "\x17" => [16, "2e"], "\x18" => [94, "2i"], "\x19" => [76, "2i"], "\x1a" => [104, "2i"], "\x1b" => [16, "2i"], "\x1c" => [94, "2o"], "\x1d" => [76, "2o"], "\x1e" => [104, "2o"], "\x1f" => [16, "2o"], " " => [94, "2s"], "!" => [76, "2s"], "\"" => [104, "2s"], "#" => [16, "2s"], "\$" => [94, "2t"], "%" => [76, "2t"], "&" => [104, "2t"], "'" => [16, "2t"], "(" => [77, "2 "], ")" => [18, "2 "], "*" => [77, "2%"], "+" => [18, "2%"], "," => [77, "2-"], "-" => [18, "2-"], "." => [77, "2."], "/" => [18, "2."], [77, "2/"], [18, "2/"], [77, "23"], [18, "23"], [77, "24"], [18, "24"], [77, "25"], [18, "25"], [77, "26"], [18, "26"], ":" => [77, "27"], ";" => [18, "27"], "<" => [77, "28"], "=" => [18, "28"], ">" => [77, "29"], "?" => [18, "29"], "@" => [77, "2="], "A" => [18, "2="], "B" => [77, "2A"], "C" => [18, "2A"], "D" => [77, "2_"], "E" => [18, "2_"], "F" => [77, "2b"], "G" => [18, "2b"], "H" => [77, "2d"], "I" => [18, "2d"], "J" => [77, "2f"], "K" => [18, "2f"], "L" => [77, "2g"], "M" => [18, "2g"], "N" => [77, "2h"], "O" => [18, "2h"], "P" => [77, "2l"], "Q" => [18, "2l"], "R" => [77, "2m"], "S" => [18, "2m"], "T" => [77, "2n"], "U" => [18, "2n"], "V" => [77, "2p"], "W" => [18, "2p"], "X" => [77, "2r"], "Y" => [18, "2r"], "Z" => [77, "2u"], "[" => [18, "2u"], "\\" => [0, "2:"], "]" => [0, "2B"], "^" => [0, "2C"], "_" => [0, "2D"], "`" => [0, "2E"], "a" => [0, "2F"], "b" => [0, "2G"], "c" => [0, "2H"], "d" => [0, "2I"], "e" => [0, "2J"], "f" => [0, "2K"], "g" => [0, "2L"], "h" => [0, "2M"], "i" => [0, "2N"], "j" => [0, "2O"], "k" => [0, "2P"], "l" => [0, "2Q"], "m" => [0, "2R"], "n" => [0, "2S"], "o" => [0, "2T"], "p" => [0, "2U"], "q" => [0, "2V"], "r" => [0, "2W"], "s" => [0, "2Y"], "t" => [0, "2j"], "u" => [0, "2k"], "v" => [0, "2q"], "w" => [0, "2v"], "x" => [0, "2w"], "y" => [0, "2x"], "z" => [0, "2y"], "{" => [0, "2z"], "|" => [82, "2"], "}" => [87, "2"], "~" => [130, "2"], "" => [9, "2"], "\x80" => [94, "a0"], "\x81" => [76, "a0"], "\x82" => [104, "a0"], "\x83" => [16, "a0"], "\x84" => [94, "a1"], "\x85" => [76, "a1"], "\x86" => [104, "a1"], "\x87" => [16, "a1"], "\x88" => [94, "a2"], "\x89" => [76, "a2"], "\x8a" => [104, "a2"], "\x8b" => [16, "a2"], "\x8c" => [94, "aa"], "\x8d" => [76, "aa"], "\x8e" => [104, "aa"], "\x8f" => [16, "aa"], "\x90" => [94, "ac"], "\x91" => [76, "ac"], "\x92" => [104, "ac"], "\x93" => [16, "ac"], "\x94" => [94, "ae"], "\x95" => [76, "ae"], "\x96" => [104, "ae"], "\x97" => [16, "ae"], "\x98" => [94, "ai"], "\x99" => [76, "ai"], "\x9a" => [104, "ai"], "\x9b" => [16, "ai"], "\x9c" => [94, "ao"], "\x9d" => [76, "ao"], "\x9e" => [104, "ao"], "\x9f" => [16, "ao"], "\xa0" => [94, "as"], "\xa1" => [76, "as"], "\xa2" => [104, "as"], "\xa3" => [16, "as"], "\xa4" => [94, "at"], "\xa5" => [76, "at"], "\xa6" => [104, "at"], "\xa7" => [16, "at"], "\xa8" => [77, "a "], "\xa9" => [18, "a "], "\xaa" => [77, "a%"], "\xab" => [18, "a%"], "\xac" => [77, "a-"], "\xad" => [18, "a-"], "\xae" => [77, "a."], "\xaf" => [18, "a."], "\xb0" => [77, "a/"], "\xb1" => [18, "a/"], "\xb2" => [77, "a3"], "\xb3" => [18, "a3"], "\xb4" => [77, "a4"], "\xb5" => [18, "a4"], "\xb6" => [77, "a5"], "\xb7" => [18, "a5"], "\xb8" => [77, "a6"], "\xb9" => [18, "a6"], "\xba" => [77, "a7"], "\xbb" => [18, "a7"], "\xbc" => [77, "a8"], "\xbd" => [18, "a8"], "\xbe" => [77, "a9"], "\xbf" => [18, "a9"], "\xc0" => [77, "a="], "\xc1" => [18, "a="], "\xc2" => [77, "aA"], "\xc3" => [18, "aA"], "\xc4" => [77, "a_"], "\xc5" => [18, "a_"], "\xc6" => [77, "ab"], "\xc7" => [18, "ab"], "\xc8" => [77, "ad"], "\xc9" => [18, "ad"], "\xca" => [77, "af"], "\xcb" => [18, "af"], "\xcc" => [77, "ag"], "\xcd" => [18, "ag"], "\xce" => [77, "ah"], "\xcf" => [18, "ah"], "\xd0" => [77, "al"], "\xd1" => [18, "al"], "\xd2" => [77, "am"], "\xd3" => [18, "am"], "\xd4" => [77, "an"], "\xd5" => [18, "an"], "\xd6" => [77, "ap"], "\xd7" => [18, "ap"], "\xd8" => [77, "ar"], "\xd9" => [18, "ar"], "\xda" => [77, "au"], "\xdb" => [18, "au"], "\xdc" => [0, "a:"], "\xdd" => [0, "aB"], "\xde" => [0, "aC"], "\xdf" => [0, "aD"], "\xe0" => [0, "aE"], "\xe1" => [0, "aF"], "\xe2" => [0, "aG"], "\xe3" => [0, "aH"], "\xe4" => [0, "aI"], "\xe5" => [0, "aJ"], "\xe6" => [0, "aK"], "\xe7" => [0, "aL"], "\xe8" => [0, "aM"], "\xe9" => [0, "aN"], "\xea" => [0, "aO"], "\xeb" => [0, "aP"], "\xec" => [0, "aQ"], "\xed" => [0, "aR"], "\xee" => [0, "aS"], "\xef" => [0, "aT"], "\xf0" => [0, "aU"], "\xf1" => [0, "aV"], "\xf2" => [0, "aW"], "\xf3" => [0, "aY"], "\xf4" => [0, "aj"], "\xf5" => [0, "ak"], "\xf6" => [0, "aq"], "\xf7" => [0, "av"], "\xf8" => [0, "aw"], "\xf9" => [0, "ax"], "\xfa" => [0, "ay"], "\xfb" => [0, "az"], "\xfc" => [82, "a"], "\xfd" => [87, "a"], "\xfe" => [130, "a"], "\xff" => [9, "a"]], ["\x00" => [94, "40"], "\x01" => [76, "40"], "\x02" => [104, "40"], "\x03" => [16, "40"], "\x04" => [94, "41"], "\x05" => [76, "41"], "\x06" => [104, "41"], "\x07" => [16, "41"], "\x08" => [94, "42"], "\t" => [76, "42"], "\n" => [104, "42"], "\v" => [16, "42"], "\f" => [94, "4a"], "\r" => [76, "4a"], "\x0e" => [104, "4a"], "\x0f" => [16, "4a"], "\x10" => [94, "4c"], "\x11" => [76, "4c"], "\x12" => [104, "4c"], "\x13" => [16, "4c"], "\x14" => [94, "4e"], "\x15" => [76, "4e"], "\x16" => [104, "4e"], "\x17" => [16, "4e"], "\x18" => [94, "4i"], "\x19" => [76, "4i"], "\x1a" => [104, "4i"], "\x1b" => [16, "4i"], "\x1c" => [94, "4o"], "\x1d" => [76, "4o"], "\x1e" => [104, "4o"], "\x1f" => [16, "4o"], " " => [94, "4s"], "!" => [76, "4s"], "\"" => [104, "4s"], "#" => [16, "4s"], "\$" => [94, "4t"], "%" => [76, "4t"], "&" => [104, "4t"], "'" => [16, "4t"], "(" => [77, "4 "], ")" => [18, "4 "], "*" => [77, "4%"], "+" => [18, "4%"], "," => [77, "4-"], "-" => [18, "4-"], "." => [77, "4."], "/" => [18, "4."], [77, "4/"], [18, "4/"], [77, "43"], [18, "43"], [77, "44"], [18, "44"], [77, "45"], [18, "45"], [77, "46"], [18, "46"], ":" => [77, "47"], ";" => [18, "47"], "<" => [77, "48"], "=" => [18, "48"], ">" => [77, "49"], "?" => [18, "49"], "@" => [77, "4="], "A" => [18, "4="], "B" => [77, "4A"], "C" => [18, "4A"], "D" => [77, "4_"], "E" => [18, "4_"], "F" => [77, "4b"], "G" => [18, "4b"], "H" => [77, "4d"], "I" => [18, "4d"], "J" => [77, "4f"], "K" => [18, "4f"], "L" => [77, "4g"], "M" => [18, "4g"], "N" => [77, "4h"], "O" => [18, "4h"], "P" => [77, "4l"], "Q" => [18, "4l"], "R" => [77, "4m"], "S" => [18, "4m"], "T" => [77, "4n"], "U" => [18, "4n"], "V" => [77, "4p"], "W" => [18, "4p"], "X" => [77, "4r"], "Y" => [18, "4r"], "Z" => [77, "4u"], "[" => [18, "4u"], "\\" => [0, "4:"], "]" => [0, "4B"], "^" => [0, "4C"], "_" => [0, "4D"], "`" => [0, "4E"], "a" => [0, "4F"], "b" => [0, "4G"], "c" => [0, "4H"], "d" => [0, "4I"], "e" => [0, "4J"], "f" => [0, "4K"], "g" => [0, "4L"], "h" => [0, "4M"], "i" => [0, "4N"], "j" => [0, "4O"], "k" => [0, "4P"], "l" => [0, "4Q"], "m" => [0, "4R"], "n" => [0, "4S"], "o" => [0, "4T"], "p" => [0, "4U"], "q" => [0, "4V"], "r" => [0, "4W"], "s" => [0, "4Y"], "t" => [0, "4j"], "u" => [0, "4k"], "v" => [0, "4q"], "w" => [0, "4v"], "x" => [0, "4w"], "y" => [0, "4x"], "z" => [0, "4y"], "{" => [0, "4z"], "|" => [82, "4"], "}" => [87, "4"], "~" => [130, "4"], "" => [9, "4"], "\x80" => [94, "50"], "\x81" => [76, "50"], "\x82" => [104, "50"], "\x83" => [16, "50"], "\x84" => [94, "51"], "\x85" => [76, "51"], "\x86" => [104, "51"], "\x87" => [16, "51"], "\x88" => [94, "52"], "\x89" => [76, "52"], "\x8a" => [104, "52"], "\x8b" => [16, "52"], "\x8c" => [94, "5a"], "\x8d" => [76, "5a"], "\x8e" => [104, "5a"], "\x8f" => [16, "5a"], "\x90" => [94, "5c"], "\x91" => [76, "5c"], "\x92" => [104, "5c"], "\x93" => [16, "5c"], "\x94" => [94, "5e"], "\x95" => [76, "5e"], "\x96" => [104, "5e"], "\x97" => [16, "5e"], "\x98" => [94, "5i"], "\x99" => [76, "5i"], "\x9a" => [104, "5i"], "\x9b" => [16, "5i"], "\x9c" => [94, "5o"], "\x9d" => [76, "5o"], "\x9e" => [104, "5o"], "\x9f" => [16, "5o"], "\xa0" => [94, "5s"], "\xa1" => [76, "5s"], "\xa2" => [104, "5s"], "\xa3" => [16, "5s"], "\xa4" => [94, "5t"], "\xa5" => [76, "5t"], "\xa6" => [104, "5t"], "\xa7" => [16, "5t"], "\xa8" => [77, "5 "], "\xa9" => [18, "5 "], "\xaa" => [77, "5%"], "\xab" => [18, "5%"], "\xac" => [77, "5-"], "\xad" => [18, "5-"], "\xae" => [77, "5."], "\xaf" => [18, "5."], "\xb0" => [77, "5/"], "\xb1" => [18, "5/"], "\xb2" => [77, "53"], "\xb3" => [18, "53"], "\xb4" => [77, "54"], "\xb5" => [18, "54"], "\xb6" => [77, "55"], "\xb7" => [18, "55"], "\xb8" => [77, "56"], "\xb9" => [18, "56"], "\xba" => [77, "57"], "\xbb" => [18, "57"], "\xbc" => [77, "58"], "\xbd" => [18, "58"], "\xbe" => [77, "59"], "\xbf" => [18, "59"], "\xc0" => [77, "5="], "\xc1" => [18, "5="], "\xc2" => [77, "5A"], "\xc3" => [18, "5A"], "\xc4" => [77, "5_"], "\xc5" => [18, "5_"], "\xc6" => [77, "5b"], "\xc7" => [18, "5b"], "\xc8" => [77, "5d"], "\xc9" => [18, "5d"], "\xca" => [77, "5f"], "\xcb" => [18, "5f"], "\xcc" => [77, "5g"], "\xcd" => [18, "5g"], "\xce" => [77, "5h"], "\xcf" => [18, "5h"], "\xd0" => [77, "5l"], "\xd1" => [18, "5l"], "\xd2" => [77, "5m"], "\xd3" => [18, "5m"], "\xd4" => [77, "5n"], "\xd5" => [18, "5n"], "\xd6" => [77, "5p"], "\xd7" => [18, "5p"], "\xd8" => [77, "5r"], "\xd9" => [18, "5r"], "\xda" => [77, "5u"], "\xdb" => [18, "5u"], "\xdc" => [0, "5:"], "\xdd" => [0, "5B"], "\xde" => [0, "5C"], "\xdf" => [0, "5D"], "\xe0" => [0, "5E"], "\xe1" => [0, "5F"], "\xe2" => [0, "5G"], "\xe3" => [0, "5H"], "\xe4" => [0, "5I"], "\xe5" => [0, "5J"], "\xe6" => [0, "5K"], "\xe7" => [0, "5L"], "\xe8" => [0, "5M"], "\xe9" => [0, "5N"], "\xea" => [0, "5O"], "\xeb" => [0, "5P"], "\xec" => [0, "5Q"], "\xed" => [0, "5R"], "\xee" => [0, "5S"], "\xef" => [0, "5T"], "\xf0" => [0, "5U"], "\xf1" => [0, "5V"], "\xf2" => [0, "5W"], "\xf3" => [0, "5Y"], "\xf4" => [0, "5j"], "\xf5" => [0, "5k"], "\xf6" => [0, "5q"], "\xf7" => [0, "5v"], "\xf8" => [0, "5w"], "\xf9" => [0, "5x"], "\xfa" => [0, "5y"], "\xfb" => [0, "5z"], "\xfc" => [82, "5"], "\xfd" => [87, "5"], "\xfe" => [130, "5"], "\xff" => [9, "5"]], ["\x00" => [94, "60"], "\x01" => [76, "60"], "\x02" => [104, "60"], "\x03" => [16, "60"], "\x04" => [94, "61"], "\x05" => [76, "61"], "\x06" => [104, "61"], "\x07" => [16, "61"], "\x08" => [94, "62"], "\t" => [76, "62"], "\n" => [104, "62"], "\v" => [16, "62"], "\f" => [94, "6a"], "\r" => [76, "6a"], "\x0e" => [104, "6a"], "\x0f" => [16, "6a"], "\x10" => [94, "6c"], "\x11" => [76, "6c"], "\x12" => [104, "6c"], "\x13" => [16, "6c"], "\x14" => [94, "6e"], "\x15" => [76, "6e"], "\x16" => [104, "6e"], "\x17" => [16, "6e"], "\x18" => [94, "6i"], "\x19" => [76, "6i"], "\x1a" => [104, "6i"], "\x1b" => [16, "6i"], "\x1c" => [94, "6o"], "\x1d" => [76, "6o"], "\x1e" => [104, "6o"], "\x1f" => [16, "6o"], " " => [94, "6s"], "!" => [76, "6s"], "\"" => [104, "6s"], "#" => [16, "6s"], "\$" => [94, "6t"], "%" => [76, "6t"], "&" => [104, "6t"], "'" => [16, "6t"], "(" => [77, "6 "], ")" => [18, "6 "], "*" => [77, "6%"], "+" => [18, "6%"], "," => [77, "6-"], "-" => [18, "6-"], "." => [77, "6."], "/" => [18, "6."], [77, "6/"], [18, "6/"], [77, "63"], [18, "63"], [77, "64"], [18, "64"], [77, "65"], [18, "65"], [77, "66"], [18, "66"], ":" => [77, "67"], ";" => [18, "67"], "<" => [77, "68"], "=" => [18, "68"], ">" => [77, "69"], "?" => [18, "69"], "@" => [77, "6="], "A" => [18, "6="], "B" => [77, "6A"], "C" => [18, "6A"], "D" => [77, "6_"], "E" => [18, "6_"], "F" => [77, "6b"], "G" => [18, "6b"], "H" => [77, "6d"], "I" => [18, "6d"], "J" => [77, "6f"], "K" => [18, "6f"], "L" => [77, "6g"], "M" => [18, "6g"], "N" => [77, "6h"], "O" => [18, "6h"], "P" => [77, "6l"], "Q" => [18, "6l"], "R" => [77, "6m"], "S" => [18, "6m"], "T" => [77, "6n"], "U" => [18, "6n"], "V" => [77, "6p"], "W" => [18, "6p"], "X" => [77, "6r"], "Y" => [18, "6r"], "Z" => [77, "6u"], "[" => [18, "6u"], "\\" => [0, "6:"], "]" => [0, "6B"], "^" => [0, "6C"], "_" => [0, "6D"], "`" => [0, "6E"], "a" => [0, "6F"], "b" => [0, "6G"], "c" => [0, "6H"], "d" => [0, "6I"], "e" => [0, "6J"], "f" => [0, "6K"], "g" => [0, "6L"], "h" => [0, "6M"], "i" => [0, "6N"], "j" => [0, "6O"], "k" => [0, "6P"], "l" => [0, "6Q"], "m" => [0, "6R"], "n" => [0, "6S"], "o" => [0, "6T"], "p" => [0, "6U"], "q" => [0, "6V"], "r" => [0, "6W"], "s" => [0, "6Y"], "t" => [0, "6j"], "u" => [0, "6k"], "v" => [0, "6q"], "w" => [0, "6v"], "x" => [0, "6w"], "y" => [0, "6x"], "z" => [0, "6y"], "{" => [0, "6z"], "|" => [82, "6"], "}" => [87, "6"], "~" => [130, "6"], "" => [9, "6"], "\x80" => [94, "70"], "\x81" => [76, "70"], "\x82" => [104, "70"], "\x83" => [16, "70"], "\x84" => [94, "71"], "\x85" => [76, "71"], "\x86" => [104, "71"], "\x87" => [16, "71"], "\x88" => [94, "72"], "\x89" => [76, "72"], "\x8a" => [104, "72"], "\x8b" => [16, "72"], "\x8c" => [94, "7a"], "\x8d" => [76, "7a"], "\x8e" => [104, "7a"], "\x8f" => [16, "7a"], "\x90" => [94, "7c"], "\x91" => [76, "7c"], "\x92" => [104, "7c"], "\x93" => [16, "7c"], "\x94" => [94, "7e"], "\x95" => [76, "7e"], "\x96" => [104, "7e"], "\x97" => [16, "7e"], "\x98" => [94, "7i"], "\x99" => [76, "7i"], "\x9a" => [104, "7i"], "\x9b" => [16, "7i"], "\x9c" => [94, "7o"], "\x9d" => [76, "7o"], "\x9e" => [104, "7o"], "\x9f" => [16, "7o"], "\xa0" => [94, "7s"], "\xa1" => [76, "7s"], "\xa2" => [104, "7s"], "\xa3" => [16, "7s"], "\xa4" => [94, "7t"], "\xa5" => [76, "7t"], "\xa6" => [104, "7t"], "\xa7" => [16, "7t"], "\xa8" => [77, "7 "], "\xa9" => [18, "7 "], "\xaa" => [77, "7%"], "\xab" => [18, "7%"], "\xac" => [77, "7-"], "\xad" => [18, "7-"], "\xae" => [77, "7."], "\xaf" => [18, "7."], "\xb0" => [77, "7/"], "\xb1" => [18, "7/"], "\xb2" => [77, "73"], "\xb3" => [18, "73"], "\xb4" => [77, "74"], "\xb5" => [18, "74"], "\xb6" => [77, "75"], "\xb7" => [18, "75"], "\xb8" => [77, "76"], "\xb9" => [18, "76"], "\xba" => [77, "77"], "\xbb" => [18, "77"], "\xbc" => [77, "78"], "\xbd" => [18, "78"], "\xbe" => [77, "79"], "\xbf" => [18, "79"], "\xc0" => [77, "7="], "\xc1" => [18, "7="], "\xc2" => [77, "7A"], "\xc3" => [18, "7A"], "\xc4" => [77, "7_"], "\xc5" => [18, "7_"], "\xc6" => [77, "7b"], "\xc7" => [18, "7b"], "\xc8" => [77, "7d"], "\xc9" => [18, "7d"], "\xca" => [77, "7f"], "\xcb" => [18, "7f"], "\xcc" => [77, "7g"], "\xcd" => [18, "7g"], "\xce" => [77, "7h"], "\xcf" => [18, "7h"], "\xd0" => [77, "7l"], "\xd1" => [18, "7l"], "\xd2" => [77, "7m"], "\xd3" => [18, "7m"], "\xd4" => [77, "7n"], "\xd5" => [18, "7n"], "\xd6" => [77, "7p"], "\xd7" => [18, "7p"], "\xd8" => [77, "7r"], "\xd9" => [18, "7r"], "\xda" => [77, "7u"], "\xdb" => [18, "7u"], "\xdc" => [0, "7:"], "\xdd" => [0, "7B"], "\xde" => [0, "7C"], "\xdf" => [0, "7D"], "\xe0" => [0, "7E"], "\xe1" => [0, "7F"], "\xe2" => [0, "7G"], "\xe3" => [0, "7H"], "\xe4" => [0, "7I"], "\xe5" => [0, "7J"], "\xe6" => [0, "7K"], "\xe7" => [0, "7L"], "\xe8" => [0, "7M"], "\xe9" => [0, "7N"], "\xea" => [0, "7O"], "\xeb" => [0, "7P"], "\xec" => [0, "7Q"], "\xed" => [0, "7R"], "\xee" => [0, "7S"], "\xef" => [0, "7T"], "\xf0" => [0, "7U"], "\xf1" => [0, "7V"], "\xf2" => [0, "7W"], "\xf3" => [0, "7Y"], "\xf4" => [0, "7j"], "\xf5" => [0, "7k"], "\xf6" => [0, "7q"], "\xf7" => [0, "7v"], "\xf8" => [0, "7w"], "\xf9" => [0, "7x"], "\xfa" => [0, "7y"], "\xfb" => [0, "7z"], "\xfc" => [82, "7"], "\xfd" => [87, "7"], "\xfe" => [130, "7"], "\xff" => [9, "7"]], ["\x00" => [77, "60"], "\x01" => [18, "60"], "\x02" => [77, "61"], "\x03" => [18, "61"], "\x04" => [77, "62"], "\x05" => [18, "62"], "\x06" => [77, "6a"], "\x07" => [18, "6a"], "\x08" => [77, "6c"], "\t" => [18, "6c"], "\n" => [77, "6e"], "\v" => [18, "6e"], "\f" => [77, "6i"], "\r" => [18, "6i"], "\x0e" => [77, "6o"], "\x0f" => [18, "6o"], "\x10" => [77, "6s"], "\x11" => [18, "6s"], "\x12" => [77, "6t"], "\x13" => [18, "6t"], "\x14" => [0, "6 "], "\x15" => [0, "6%"], "\x16" => [0, "6-"], "\x17" => [0, "6."], "\x18" => [0, "6/"], "\x19" => [0, "63"], "\x1a" => [0, "64"], "\x1b" => [0, "65"], "\x1c" => [0, "66"], "\x1d" => [0, "67"], "\x1e" => [0, "68"], "\x1f" => [0, "69"], " " => [0, "6="], "!" => [0, "6A"], "\"" => [0, "6_"], "#" => [0, "6b"], "\$" => [0, "6d"], "%" => [0, "6f"], "&" => [0, "6g"], "'" => [0, "6h"], "(" => [0, "6l"], ")" => [0, "6m"], "*" => [0, "6n"], "+" => [0, "6p"], "," => [0, "6r"], "-" => [0, "6u"], "." => [100, "6"], "/" => [110, "6"], [111, "6"], [115, "6"], [116, "6"], [118, "6"], [119, "6"], [122, "6"], [123, "6"], [125, "6"], [126, "6"], [129, "6"], ":" => [143, "6"], ";" => [148, "6"], "<" => [151, "6"], "=" => [153, "6"], ">" => [83, "6"], "?" => [10, "6"], "@" => [77, "70"], "A" => [18, "70"], "B" => [77, "71"], "C" => [18, "71"], "D" => [77, "72"], "E" => [18, "72"], "F" => [77, "7a"], "G" => [18, "7a"], "H" => [77, "7c"], "I" => [18, "7c"], "J" => [77, "7e"], "K" => [18, "7e"], "L" => [77, "7i"], "M" => [18, "7i"], "N" => [77, "7o"], "O" => [18, "7o"], "P" => [77, "7s"], "Q" => [18, "7s"], "R" => [77, "7t"], "S" => [18, "7t"], "T" => [0, "7 "], "U" => [0, "7%"], "V" => [0, "7-"], "W" => [0, "7."], "X" => [0, "7/"], "Y" => [0, "73"], "Z" => [0, "74"], "[" => [0, "75"], "\\" => [0, "76"], "]" => [0, "77"], "^" => [0, "78"], "_" => [0, "79"], "`" => [0, "7="], "a" => [0, "7A"], "b" => [0, "7_"], "c" => [0, "7b"], "d" => [0, "7d"], "e" => [0, "7f"], "f" => [0, "7g"], "g" => [0, "7h"], "h" => [0, "7l"], "i" => [0, "7m"], "j" => [0, "7n"], "k" => [0, "7p"], "l" => [0, "7r"], "m" => [0, "7u"], "n" => [100, "7"], "o" => [110, "7"], "p" => [111, "7"], "q" => [115, "7"], "r" => [116, "7"], "s" => [118, "7"], "t" => [119, "7"], "u" => [122, "7"], "v" => [123, "7"], "w" => [125, "7"], "x" => [126, "7"], "y" => [129, "7"], "z" => [143, "7"], "{" => [148, "7"], "|" => [151, "7"], "}" => [153, "7"], "~" => [83, "7"], "" => [10, "7"], "\x80" => [77, "80"], "\x81" => [18, "80"], "\x82" => [77, "81"], "\x83" => [18, "81"], "\x84" => [77, "82"], "\x85" => [18, "82"], "\x86" => [77, "8a"], "\x87" => [18, "8a"], "\x88" => [77, "8c"], "\x89" => [18, "8c"], "\x8a" => [77, "8e"], "\x8b" => [18, "8e"], "\x8c" => [77, "8i"], "\x8d" => [18, "8i"], "\x8e" => [77, "8o"], "\x8f" => [18, "8o"], "\x90" => [77, "8s"], "\x91" => [18, "8s"], "\x92" => [77, "8t"], "\x93" => [18, "8t"], "\x94" => [0, "8 "], "\x95" => [0, "8%"], "\x96" => [0, "8-"], "\x97" => [0, "8."], "\x98" => [0, "8/"], "\x99" => [0, "83"], "\x9a" => [0, "84"], "\x9b" => [0, "85"], "\x9c" => [0, "86"], "\x9d" => [0, "87"], "\x9e" => [0, "88"], "\x9f" => [0, "89"], "\xa0" => [0, "8="], "\xa1" => [0, "8A"], "\xa2" => [0, "8_"], "\xa3" => [0, "8b"], "\xa4" => [0, "8d"], "\xa5" => [0, "8f"], "\xa6" => [0, "8g"], "\xa7" => [0, "8h"], "\xa8" => [0, "8l"], "\xa9" => [0, "8m"], "\xaa" => [0, "8n"], "\xab" => [0, "8p"], "\xac" => [0, "8r"], "\xad" => [0, "8u"], "\xae" => [100, "8"], "\xaf" => [110, "8"], "\xb0" => [111, "8"], "\xb1" => [115, "8"], "\xb2" => [116, "8"], "\xb3" => [118, "8"], "\xb4" => [119, "8"], "\xb5" => [122, "8"], "\xb6" => [123, "8"], "\xb7" => [125, "8"], "\xb8" => [126, "8"], "\xb9" => [129, "8"], "\xba" => [143, "8"], "\xbb" => [148, "8"], "\xbc" => [151, "8"], "\xbd" => [153, "8"], "\xbe" => [83, "8"], "\xbf" => [10, "8"], "\xc0" => [77, "90"], "\xc1" => [18, "90"], "\xc2" => [77, "91"], "\xc3" => [18, "91"], "\xc4" => [77, "92"], "\xc5" => [18, "92"], "\xc6" => [77, "9a"], "\xc7" => [18, "9a"], "\xc8" => [77, "9c"], "\xc9" => [18, "9c"], "\xca" => [77, "9e"], "\xcb" => [18, "9e"], "\xcc" => [77, "9i"], "\xcd" => [18, "9i"], "\xce" => [77, "9o"], "\xcf" => [18, "9o"], "\xd0" => [77, "9s"], "\xd1" => [18, "9s"], "\xd2" => [77, "9t"], "\xd3" => [18, "9t"], "\xd4" => [0, "9 "], "\xd5" => [0, "9%"], "\xd6" => [0, "9-"], "\xd7" => [0, "9."], "\xd8" => [0, "9/"], "\xd9" => [0, "93"], "\xda" => [0, "94"], "\xdb" => [0, "95"], "\xdc" => [0, "96"], "\xdd" => [0, "97"], "\xde" => [0, "98"], "\xdf" => [0, "99"], "\xe0" => [0, "9="], "\xe1" => [0, "9A"], "\xe2" => [0, "9_"], "\xe3" => [0, "9b"], "\xe4" => [0, "9d"], "\xe5" => [0, "9f"], "\xe6" => [0, "9g"], "\xe7" => [0, "9h"], "\xe8" => [0, "9l"], "\xe9" => [0, "9m"], "\xea" => [0, "9n"], "\xeb" => [0, "9p"], "\xec" => [0, "9r"], "\xed" => [0, "9u"], "\xee" => [100, "9"], "\xef" => [110, "9"], "\xf0" => [111, "9"], "\xf1" => [115, "9"], "\xf2" => [116, "9"], "\xf3" => [118, "9"], "\xf4" => [119, "9"], "\xf5" => [122, "9"], "\xf6" => [123, "9"], "\xf7" => [125, "9"], "\xf8" => [126, "9"], "\xf9" => [129, "9"], "\xfa" => [143, "9"], "\xfb" => [148, "9"], "\xfc" => [151, "9"], "\xfd" => [153, "9"], "\xfe" => [83, "9"], "\xff" => [10, "9"]], ["\x00" => [94, "80"], "\x01" => [76, "80"], "\x02" => [104, "80"], "\x03" => [16, "80"], "\x04" => [94, "81"], "\x05" => [76, "81"], "\x06" => [104, "81"], "\x07" => [16, "81"], "\x08" => [94, "82"], "\t" => [76, "82"], "\n" => [104, "82"], "\v" => [16, "82"], "\f" => [94, "8a"], "\r" => [76, "8a"], "\x0e" => [104, "8a"], "\x0f" => [16, "8a"], "\x10" => [94, "8c"], "\x11" => [76, "8c"], "\x12" => [104, "8c"], "\x13" => [16, "8c"], "\x14" => [94, "8e"], "\x15" => [76, "8e"], "\x16" => [104, "8e"], "\x17" => [16, "8e"], "\x18" => [94, "8i"], "\x19" => [76, "8i"], "\x1a" => [104, "8i"], "\x1b" => [16, "8i"], "\x1c" => [94, "8o"], "\x1d" => [76, "8o"], "\x1e" => [104, "8o"], "\x1f" => [16, "8o"], " " => [94, "8s"], "!" => [76, "8s"], "\"" => [104, "8s"], "#" => [16, "8s"], "\$" => [94, "8t"], "%" => [76, "8t"], "&" => [104, "8t"], "'" => [16, "8t"], "(" => [77, "8 "], ")" => [18, "8 "], "*" => [77, "8%"], "+" => [18, "8%"], "," => [77, "8-"], "-" => [18, "8-"], "." => [77, "8."], "/" => [18, "8."], [77, "8/"], [18, "8/"], [77, "83"], [18, "83"], [77, "84"], [18, "84"], [77, "85"], [18, "85"], [77, "86"], [18, "86"], ":" => [77, "87"], ";" => [18, "87"], "<" => [77, "88"], "=" => [18, "88"], ">" => [77, "89"], "?" => [18, "89"], "@" => [77, "8="], "A" => [18, "8="], "B" => [77, "8A"], "C" => [18, "8A"], "D" => [77, "8_"], "E" => [18, "8_"], "F" => [77, "8b"], "G" => [18, "8b"], "H" => [77, "8d"], "I" => [18, "8d"], "J" => [77, "8f"], "K" => [18, "8f"], "L" => [77, "8g"], "M" => [18, "8g"], "N" => [77, "8h"], "O" => [18, "8h"], "P" => [77, "8l"], "Q" => [18, "8l"], "R" => [77, "8m"], "S" => [18, "8m"], "T" => [77, "8n"], "U" => [18, "8n"], "V" => [77, "8p"], "W" => [18, "8p"], "X" => [77, "8r"], "Y" => [18, "8r"], "Z" => [77, "8u"], "[" => [18, "8u"], "\\" => [0, "8:"], "]" => [0, "8B"], "^" => [0, "8C"], "_" => [0, "8D"], "`" => [0, "8E"], "a" => [0, "8F"], "b" => [0, "8G"], "c" => [0, "8H"], "d" => [0, "8I"], "e" => [0, "8J"], "f" => [0, "8K"], "g" => [0, "8L"], "h" => [0, "8M"], "i" => [0, "8N"], "j" => [0, "8O"], "k" => [0, "8P"], "l" => [0, "8Q"], "m" => [0, "8R"], "n" => [0, "8S"], "o" => [0, "8T"], "p" => [0, "8U"], "q" => [0, "8V"], "r" => [0, "8W"], "s" => [0, "8Y"], "t" => [0, "8j"], "u" => [0, "8k"], "v" => [0, "8q"], "w" => [0, "8v"], "x" => [0, "8w"], "y" => [0, "8x"], "z" => [0, "8y"], "{" => [0, "8z"], "|" => [82, "8"], "}" => [87, "8"], "~" => [130, "8"], "" => [9, "8"], "\x80" => [94, "90"], "\x81" => [76, "90"], "\x82" => [104, "90"], "\x83" => [16, "90"], "\x84" => [94, "91"], "\x85" => [76, "91"], "\x86" => [104, "91"], "\x87" => [16, "91"], "\x88" => [94, "92"], "\x89" => [76, "92"], "\x8a" => [104, "92"], "\x8b" => [16, "92"], "\x8c" => [94, "9a"], "\x8d" => [76, "9a"], "\x8e" => [104, "9a"], "\x8f" => [16, "9a"], "\x90" => [94, "9c"], "\x91" => [76, "9c"], "\x92" => [104, "9c"], "\x93" => [16, "9c"], "\x94" => [94, "9e"], "\x95" => [76, "9e"], "\x96" => [104, "9e"], "\x97" => [16, "9e"], "\x98" => [94, "9i"], "\x99" => [76, "9i"], "\x9a" => [104, "9i"], "\x9b" => [16, "9i"], "\x9c" => [94, "9o"], "\x9d" => [76, "9o"], "\x9e" => [104, "9o"], "\x9f" => [16, "9o"], "\xa0" => [94, "9s"], "\xa1" => [76, "9s"], "\xa2" => [104, "9s"], "\xa3" => [16, "9s"], "\xa4" => [94, "9t"], "\xa5" => [76, "9t"], "\xa6" => [104, "9t"], "\xa7" => [16, "9t"], "\xa8" => [77, "9 "], "\xa9" => [18, "9 "], "\xaa" => [77, "9%"], "\xab" => [18, "9%"], "\xac" => [77, "9-"], "\xad" => [18, "9-"], "\xae" => [77, "9."], "\xaf" => [18, "9."], "\xb0" => [77, "9/"], "\xb1" => [18, "9/"], "\xb2" => [77, "93"], "\xb3" => [18, "93"], "\xb4" => [77, "94"], "\xb5" => [18, "94"], "\xb6" => [77, "95"], "\xb7" => [18, "95"], "\xb8" => [77, "96"], "\xb9" => [18, "96"], "\xba" => [77, "97"], "\xbb" => [18, "97"], "\xbc" => [77, "98"], "\xbd" => [18, "98"], "\xbe" => [77, "99"], "\xbf" => [18, "99"], "\xc0" => [77, "9="], "\xc1" => [18, "9="], "\xc2" => [77, "9A"], "\xc3" => [18, "9A"], "\xc4" => [77, "9_"], "\xc5" => [18, "9_"], "\xc6" => [77, "9b"], "\xc7" => [18, "9b"], "\xc8" => [77, "9d"], "\xc9" => [18, "9d"], "\xca" => [77, "9f"], "\xcb" => [18, "9f"], "\xcc" => [77, "9g"], "\xcd" => [18, "9g"], "\xce" => [77, "9h"], "\xcf" => [18, "9h"], "\xd0" => [77, "9l"], "\xd1" => [18, "9l"], "\xd2" => [77, "9m"], "\xd3" => [18, "9m"], "\xd4" => [77, "9n"], "\xd5" => [18, "9n"], "\xd6" => [77, "9p"], "\xd7" => [18, "9p"], "\xd8" => [77, "9r"], "\xd9" => [18, "9r"], "\xda" => [77, "9u"], "\xdb" => [18, "9u"], "\xdc" => [0, "9:"], "\xdd" => [0, "9B"], "\xde" => [0, "9C"], "\xdf" => [0, "9D"], "\xe0" => [0, "9E"], "\xe1" => [0, "9F"], "\xe2" => [0, "9G"], "\xe3" => [0, "9H"], "\xe4" => [0, "9I"], "\xe5" => [0, "9J"], "\xe6" => [0, "9K"], "\xe7" => [0, "9L"], "\xe8" => [0, "9M"], "\xe9" => [0, "9N"], "\xea" => [0, "9O"], "\xeb" => [0, "9P"], "\xec" => [0, "9Q"], "\xed" => [0, "9R"], "\xee" => [0, "9S"], "\xef" => [0, "9T"], "\xf0" => [0, "9U"], "\xf1" => [0, "9V"], "\xf2" => [0, "9W"], "\xf3" => [0, "9Y"], "\xf4" => [0, "9j"], "\xf5" => [0, "9k"], "\xf6" => [0, "9q"], "\xf7" => [0, "9v"], "\xf8" => [0, "9w"], "\xf9" => [0, "9x"], "\xfa" => [0, "9y"], "\xfb" => [0, "9z"], "\xfc" => [82, "9"], "\xfd" => [87, "9"], "\xfe" => [130, "9"], "\xff" => [9, "9"]], ["\x00" => [94, ":0"], "\x01" => [76, ":0"], "\x02" => [104, ":0"], "\x03" => [16, ":0"], "\x04" => [94, ":1"], "\x05" => [76, ":1"], "\x06" => [104, ":1"], "\x07" => [16, ":1"], "\x08" => [94, ":2"], "\t" => [76, ":2"], "\n" => [104, ":2"], "\v" => [16, ":2"], "\f" => [94, ":a"], "\r" => [76, ":a"], "\x0e" => [104, ":a"], "\x0f" => [16, ":a"], "\x10" => [94, ":c"], "\x11" => [76, ":c"], "\x12" => [104, ":c"], "\x13" => [16, ":c"], "\x14" => [94, ":e"], "\x15" => [76, ":e"], "\x16" => [104, ":e"], "\x17" => [16, ":e"], "\x18" => [94, ":i"], "\x19" => [76, ":i"], "\x1a" => [104, ":i"], "\x1b" => [16, ":i"], "\x1c" => [94, ":o"], "\x1d" => [76, ":o"], "\x1e" => [104, ":o"], "\x1f" => [16, ":o"], " " => [94, ":s"], "!" => [76, ":s"], "\"" => [104, ":s"], "#" => [16, ":s"], "\$" => [94, ":t"], "%" => [76, ":t"], "&" => [104, ":t"], "'" => [16, ":t"], "(" => [77, ": "], ")" => [18, ": "], "*" => [77, ":%"], "+" => [18, ":%"], "," => [77, ":-"], "-" => [18, ":-"], "." => [77, ":."], "/" => [18, ":."], [77, ":/"], [18, ":/"], [77, ":3"], [18, ":3"], [77, ":4"], [18, ":4"], [77, ":5"], [18, ":5"], [77, ":6"], [18, ":6"], ":" => [77, ":7"], ";" => [18, ":7"], "<" => [77, ":8"], "=" => [18, ":8"], ">" => [77, ":9"], "?" => [18, ":9"], "@" => [77, ":="], "A" => [18, ":="], "B" => [77, ":A"], "C" => [18, ":A"], "D" => [77, ":_"], "E" => [18, ":_"], "F" => [77, ":b"], "G" => [18, ":b"], "H" => [77, ":d"], "I" => [18, ":d"], "J" => [77, ":f"], "K" => [18, ":f"], "L" => [77, ":g"], "M" => [18, ":g"], "N" => [77, ":h"], "O" => [18, ":h"], "P" => [77, ":l"], "Q" => [18, ":l"], "R" => [77, ":m"], "S" => [18, ":m"], "T" => [77, ":n"], "U" => [18, ":n"], "V" => [77, ":p"], "W" => [18, ":p"], "X" => [77, ":r"], "Y" => [18, ":r"], "Z" => [77, ":u"], "[" => [18, ":u"], "\\" => [0, "::"], "]" => [0, ":B"], "^" => [0, ":C"], "_" => [0, ":D"], "`" => [0, ":E"], "a" => [0, ":F"], "b" => [0, ":G"], "c" => [0, ":H"], "d" => [0, ":I"], "e" => [0, ":J"], "f" => [0, ":K"], "g" => [0, ":L"], "h" => [0, ":M"], "i" => [0, ":N"], "j" => [0, ":O"], "k" => [0, ":P"], "l" => [0, ":Q"], "m" => [0, ":R"], "n" => [0, ":S"], "o" => [0, ":T"], "p" => [0, ":U"], "q" => [0, ":V"], "r" => [0, ":W"], "s" => [0, ":Y"], "t" => [0, ":j"], "u" => [0, ":k"], "v" => [0, ":q"], "w" => [0, ":v"], "x" => [0, ":w"], "y" => [0, ":x"], "z" => [0, ":y"], "{" => [0, ":z"], "|" => [82, ":"], "}" => [87, ":"], "~" => [130, ":"], "" => [9, ":"], "\x80" => [94, "B0"], "\x81" => [76, "B0"], "\x82" => [104, "B0"], "\x83" => [16, "B0"], "\x84" => [94, "B1"], "\x85" => [76, "B1"], "\x86" => [104, "B1"], "\x87" => [16, "B1"], "\x88" => [94, "B2"], "\x89" => [76, "B2"], "\x8a" => [104, "B2"], "\x8b" => [16, "B2"], "\x8c" => [94, "Ba"], "\x8d" => [76, "Ba"], "\x8e" => [104, "Ba"], "\x8f" => [16, "Ba"], "\x90" => [94, "Bc"], "\x91" => [76, "Bc"], "\x92" => [104, "Bc"], "\x93" => [16, "Bc"], "\x94" => [94, "Be"], "\x95" => [76, "Be"], "\x96" => [104, "Be"], "\x97" => [16, "Be"], "\x98" => [94, "Bi"], "\x99" => [76, "Bi"], "\x9a" => [104, "Bi"], "\x9b" => [16, "Bi"], "\x9c" => [94, "Bo"], "\x9d" => [76, "Bo"], "\x9e" => [104, "Bo"], "\x9f" => [16, "Bo"], "\xa0" => [94, "Bs"], "\xa1" => [76, "Bs"], "\xa2" => [104, "Bs"], "\xa3" => [16, "Bs"], "\xa4" => [94, "Bt"], "\xa5" => [76, "Bt"], "\xa6" => [104, "Bt"], "\xa7" => [16, "Bt"], "\xa8" => [77, "B "], "\xa9" => [18, "B "], "\xaa" => [77, "B%"], "\xab" => [18, "B%"], "\xac" => [77, "B-"], "\xad" => [18, "B-"], "\xae" => [77, "B."], "\xaf" => [18, "B."], "\xb0" => [77, "B/"], "\xb1" => [18, "B/"], "\xb2" => [77, "B3"], "\xb3" => [18, "B3"], "\xb4" => [77, "B4"], "\xb5" => [18, "B4"], "\xb6" => [77, "B5"], "\xb7" => [18, "B5"], "\xb8" => [77, "B6"], "\xb9" => [18, "B6"], "\xba" => [77, "B7"], "\xbb" => [18, "B7"], "\xbc" => [77, "B8"], "\xbd" => [18, "B8"], "\xbe" => [77, "B9"], "\xbf" => [18, "B9"], "\xc0" => [77, "B="], "\xc1" => [18, "B="], "\xc2" => [77, "BA"], "\xc3" => [18, "BA"], "\xc4" => [77, "B_"], "\xc5" => [18, "B_"], "\xc6" => [77, "Bb"], "\xc7" => [18, "Bb"], "\xc8" => [77, "Bd"], "\xc9" => [18, "Bd"], "\xca" => [77, "Bf"], "\xcb" => [18, "Bf"], "\xcc" => [77, "Bg"], "\xcd" => [18, "Bg"], "\xce" => [77, "Bh"], "\xcf" => [18, "Bh"], "\xd0" => [77, "Bl"], "\xd1" => [18, "Bl"], "\xd2" => [77, "Bm"], "\xd3" => [18, "Bm"], "\xd4" => [77, "Bn"], "\xd5" => [18, "Bn"], "\xd6" => [77, "Bp"], "\xd7" => [18, "Bp"], "\xd8" => [77, "Br"], "\xd9" => [18, "Br"], "\xda" => [77, "Bu"], "\xdb" => [18, "Bu"], "\xdc" => [0, "B:"], "\xdd" => [0, "BB"], "\xde" => [0, "BC"], "\xdf" => [0, "BD"], "\xe0" => [0, "BE"], "\xe1" => [0, "BF"], "\xe2" => [0, "BG"], "\xe3" => [0, "BH"], "\xe4" => [0, "BI"], "\xe5" => [0, "BJ"], "\xe6" => [0, "BK"], "\xe7" => [0, "BL"], "\xe8" => [0, "BM"], "\xe9" => [0, "BN"], "\xea" => [0, "BO"], "\xeb" => [0, "BP"], "\xec" => [0, "BQ"], "\xed" => [0, "BR"], "\xee" => [0, "BS"], "\xef" => [0, "BT"], "\xf0" => [0, "BU"], "\xf1" => [0, "BV"], "\xf2" => [0, "BW"], "\xf3" => [0, "BY"], "\xf4" => [0, "Bj"], "\xf5" => [0, "Bk"], "\xf6" => [0, "Bq"], "\xf7" => [0, "Bv"], "\xf8" => [0, "Bw"], "\xf9" => [0, "Bx"], "\xfa" => [0, "By"], "\xfb" => [0, "Bz"], "\xfc" => [82, "B"], "\xfd" => [87, "B"], "\xfe" => [130, "B"], "\xff" => [9, "B"]], ["\x00" => [77, ":0"], "\x01" => [18, ":0"], "\x02" => [77, ":1"], "\x03" => [18, ":1"], "\x04" => [77, ":2"], "\x05" => [18, ":2"], "\x06" => [77, ":a"], "\x07" => [18, ":a"], "\x08" => [77, ":c"], "\t" => [18, ":c"], "\n" => [77, ":e"], "\v" => [18, ":e"], "\f" => [77, ":i"], "\r" => [18, ":i"], "\x0e" => [77, ":o"], "\x0f" => [18, ":o"], "\x10" => [77, ":s"], "\x11" => [18, ":s"], "\x12" => [77, ":t"], "\x13" => [18, ":t"], "\x14" => [0, ": "], "\x15" => [0, ":%"], "\x16" => [0, ":-"], "\x17" => [0, ":."], "\x18" => [0, ":/"], "\x19" => [0, ":3"], "\x1a" => [0, ":4"], "\x1b" => [0, ":5"], "\x1c" => [0, ":6"], "\x1d" => [0, ":7"], "\x1e" => [0, ":8"], "\x1f" => [0, ":9"], " " => [0, ":="], "!" => [0, ":A"], "\"" => [0, ":_"], "#" => [0, ":b"], "\$" => [0, ":d"], "%" => [0, ":f"], "&" => [0, ":g"], "'" => [0, ":h"], "(" => [0, ":l"], ")" => [0, ":m"], "*" => [0, ":n"], "+" => [0, ":p"], "," => [0, ":r"], "-" => [0, ":u"], "." => [100, ":"], "/" => [110, ":"], [111, ":"], [115, ":"], [116, ":"], [118, ":"], [119, ":"], [122, ":"], [123, ":"], [125, ":"], [126, ":"], [129, ":"], ":" => [143, ":"], ";" => [148, ":"], "<" => [151, ":"], "=" => [153, ":"], ">" => [83, ":"], "?" => [10, ":"], "@" => [77, "B0"], "A" => [18, "B0"], "B" => [77, "B1"], "C" => [18, "B1"], "D" => [77, "B2"], "E" => [18, "B2"], "F" => [77, "Ba"], "G" => [18, "Ba"], "H" => [77, "Bc"], "I" => [18, "Bc"], "J" => [77, "Be"], "K" => [18, "Be"], "L" => [77, "Bi"], "M" => [18, "Bi"], "N" => [77, "Bo"], "O" => [18, "Bo"], "P" => [77, "Bs"], "Q" => [18, "Bs"], "R" => [77, "Bt"], "S" => [18, "Bt"], "T" => [0, "B "], "U" => [0, "B%"], "V" => [0, "B-"], "W" => [0, "B."], "X" => [0, "B/"], "Y" => [0, "B3"], "Z" => [0, "B4"], "[" => [0, "B5"], "\\" => [0, "B6"], "]" => [0, "B7"], "^" => [0, "B8"], "_" => [0, "B9"], "`" => [0, "B="], "a" => [0, "BA"], "b" => [0, "B_"], "c" => [0, "Bb"], "d" => [0, "Bd"], "e" => [0, "Bf"], "f" => [0, "Bg"], "g" => [0, "Bh"], "h" => [0, "Bl"], "i" => [0, "Bm"], "j" => [0, "Bn"], "k" => [0, "Bp"], "l" => [0, "Br"], "m" => [0, "Bu"], "n" => [100, "B"], "o" => [110, "B"], "p" => [111, "B"], "q" => [115, "B"], "r" => [116, "B"], "s" => [118, "B"], "t" => [119, "B"], "u" => [122, "B"], "v" => [123, "B"], "w" => [125, "B"], "x" => [126, "B"], "y" => [129, "B"], "z" => [143, "B"], "{" => [148, "B"], "|" => [151, "B"], "}" => [153, "B"], "~" => [83, "B"], "" => [10, "B"], "\x80" => [77, "C0"], "\x81" => [18, "C0"], "\x82" => [77, "C1"], "\x83" => [18, "C1"], "\x84" => [77, "C2"], "\x85" => [18, "C2"], "\x86" => [77, "Ca"], "\x87" => [18, "Ca"], "\x88" => [77, "Cc"], "\x89" => [18, "Cc"], "\x8a" => [77, "Ce"], "\x8b" => [18, "Ce"], "\x8c" => [77, "Ci"], "\x8d" => [18, "Ci"], "\x8e" => [77, "Co"], "\x8f" => [18, "Co"], "\x90" => [77, "Cs"], "\x91" => [18, "Cs"], "\x92" => [77, "Ct"], "\x93" => [18, "Ct"], "\x94" => [0, "C "], "\x95" => [0, "C%"], "\x96" => [0, "C-"], "\x97" => [0, "C."], "\x98" => [0, "C/"], "\x99" => [0, "C3"], "\x9a" => [0, "C4"], "\x9b" => [0, "C5"], "\x9c" => [0, "C6"], "\x9d" => [0, "C7"], "\x9e" => [0, "C8"], "\x9f" => [0, "C9"], "\xa0" => [0, "C="], "\xa1" => [0, "CA"], "\xa2" => [0, "C_"], "\xa3" => [0, "Cb"], "\xa4" => [0, "Cd"], "\xa5" => [0, "Cf"], "\xa6" => [0, "Cg"], "\xa7" => [0, "Ch"], "\xa8" => [0, "Cl"], "\xa9" => [0, "Cm"], "\xaa" => [0, "Cn"], "\xab" => [0, "Cp"], "\xac" => [0, "Cr"], "\xad" => [0, "Cu"], "\xae" => [100, "C"], "\xaf" => [110, "C"], "\xb0" => [111, "C"], "\xb1" => [115, "C"], "\xb2" => [116, "C"], "\xb3" => [118, "C"], "\xb4" => [119, "C"], "\xb5" => [122, "C"], "\xb6" => [123, "C"], "\xb7" => [125, "C"], "\xb8" => [126, "C"], "\xb9" => [129, "C"], "\xba" => [143, "C"], "\xbb" => [148, "C"], "\xbc" => [151, "C"], "\xbd" => [153, "C"], "\xbe" => [83, "C"], "\xbf" => [10, "C"], "\xc0" => [77, "D0"], "\xc1" => [18, "D0"], "\xc2" => [77, "D1"], "\xc3" => [18, "D1"], "\xc4" => [77, "D2"], "\xc5" => [18, "D2"], "\xc6" => [77, "Da"], "\xc7" => [18, "Da"], "\xc8" => [77, "Dc"], "\xc9" => [18, "Dc"], "\xca" => [77, "De"], "\xcb" => [18, "De"], "\xcc" => [77, "Di"], "\xcd" => [18, "Di"], "\xce" => [77, "Do"], "\xcf" => [18, "Do"], "\xd0" => [77, "Ds"], "\xd1" => [18, "Ds"], "\xd2" => [77, "Dt"], "\xd3" => [18, "Dt"], "\xd4" => [0, "D "], "\xd5" => [0, "D%"], "\xd6" => [0, "D-"], "\xd7" => [0, "D."], "\xd8" => [0, "D/"], "\xd9" => [0, "D3"], "\xda" => [0, "D4"], "\xdb" => [0, "D5"], "\xdc" => [0, "D6"], "\xdd" => [0, "D7"], "\xde" => [0, "D8"], "\xdf" => [0, "D9"], "\xe0" => [0, "D="], "\xe1" => [0, "DA"], "\xe2" => [0, "D_"], "\xe3" => [0, "Db"], "\xe4" => [0, "Dd"], "\xe5" => [0, "Df"], "\xe6" => [0, "Dg"], "\xe7" => [0, "Dh"], "\xe8" => [0, "Dl"], "\xe9" => [0, "Dm"], "\xea" => [0, "Dn"], "\xeb" => [0, "Dp"], "\xec" => [0, "Dr"], "\xed" => [0, "Du"], "\xee" => [100, "D"], "\xef" => [110, "D"], "\xf0" => [111, "D"], "\xf1" => [115, "D"], "\xf2" => [116, "D"], "\xf3" => [118, "D"], "\xf4" => [119, "D"], "\xf5" => [122, "D"], "\xf6" => [123, "D"], "\xf7" => [125, "D"], "\xf8" => [126, "D"], "\xf9" => [129, "D"], "\xfa" => [143, "D"], "\xfb" => [148, "D"], "\xfc" => [151, "D"], "\xfd" => [153, "D"], "\xfe" => [83, "D"], "\xff" => [10, "D"]], ["\x00" => [77, "r0"], "\x01" => [18, "r0"], "\x02" => [77, "r1"], "\x03" => [18, "r1"], "\x04" => [77, "r2"], "\x05" => [18, "r2"], "\x06" => [77, "ra"], "\x07" => [18, "ra"], "\x08" => [77, "rc"], "\t" => [18, "rc"], "\n" => [77, "re"], "\v" => [18, "re"], "\f" => [77, "ri"], "\r" => [18, "ri"], "\x0e" => [77, "ro"], "\x0f" => [18, "ro"], "\x10" => [77, "rs"], "\x11" => [18, "rs"], "\x12" => [77, "rt"], "\x13" => [18, "rt"], "\x14" => [0, "r "], "\x15" => [0, "r%"], "\x16" => [0, "r-"], "\x17" => [0, "r."], "\x18" => [0, "r/"], "\x19" => [0, "r3"], "\x1a" => [0, "r4"], "\x1b" => [0, "r5"], "\x1c" => [0, "r6"], "\x1d" => [0, "r7"], "\x1e" => [0, "r8"], "\x1f" => [0, "r9"], " " => [0, "r="], "!" => [0, "rA"], "\"" => [0, "r_"], "#" => [0, "rb"], "\$" => [0, "rd"], "%" => [0, "rf"], "&" => [0, "rg"], "'" => [0, "rh"], "(" => [0, "rl"], ")" => [0, "rm"], "*" => [0, "rn"], "+" => [0, "rp"], "," => [0, "rr"], "-" => [0, "ru"], "." => [100, "r"], "/" => [110, "r"], [111, "r"], [115, "r"], [116, "r"], [118, "r"], [119, "r"], [122, "r"], [123, "r"], [125, "r"], [126, "r"], [129, "r"], ":" => [143, "r"], ";" => [148, "r"], "<" => [151, "r"], "=" => [153, "r"], ">" => [83, "r"], "?" => [10, "r"], "@" => [77, "u0"], "A" => [18, "u0"], "B" => [77, "u1"], "C" => [18, "u1"], "D" => [77, "u2"], "E" => [18, "u2"], "F" => [77, "ua"], "G" => [18, "ua"], "H" => [77, "uc"], "I" => [18, "uc"], "J" => [77, "ue"], "K" => [18, "ue"], "L" => [77, "ui"], "M" => [18, "ui"], "N" => [77, "uo"], "O" => [18, "uo"], "P" => [77, "us"], "Q" => [18, "us"], "R" => [77, "ut"], "S" => [18, "ut"], "T" => [0, "u "], "U" => [0, "u%"], "V" => [0, "u-"], "W" => [0, "u."], "X" => [0, "u/"], "Y" => [0, "u3"], "Z" => [0, "u4"], "[" => [0, "u5"], "\\" => [0, "u6"], "]" => [0, "u7"], "^" => [0, "u8"], "_" => [0, "u9"], "`" => [0, "u="], "a" => [0, "uA"], "b" => [0, "u_"], "c" => [0, "ub"], "d" => [0, "ud"], "e" => [0, "uf"], "f" => [0, "ug"], "g" => [0, "uh"], "h" => [0, "ul"], "i" => [0, "um"], "j" => [0, "un"], "k" => [0, "up"], "l" => [0, "ur"], "m" => [0, "uu"], "n" => [100, "u"], "o" => [110, "u"], "p" => [111, "u"], "q" => [115, "u"], "r" => [116, "u"], "s" => [118, "u"], "t" => [119, "u"], "u" => [122, "u"], "v" => [123, "u"], "w" => [125, "u"], "x" => [126, "u"], "y" => [129, "u"], "z" => [143, "u"], "{" => [148, "u"], "|" => [151, "u"], "}" => [153, "u"], "~" => [83, "u"], "" => [10, "u"], "\x80" => [0, ":0"], "\x81" => [0, ":1"], "\x82" => [0, ":2"], "\x83" => [0, ":a"], "\x84" => [0, ":c"], "\x85" => [0, ":e"], "\x86" => [0, ":i"], "\x87" => [0, ":o"], "\x88" => [0, ":s"], "\x89" => [0, ":t"], "\x8a" => [73, ":"], "\x8b" => [88, ":"], "\x8c" => [89, ":"], "\x8d" => [96, ":"], "\x8e" => [97, ":"], "\x8f" => [99, ":"], "\x90" => [106, ":"], "\x91" => [136, ":"], "\x92" => [139, ":"], "\x93" => [141, ":"], "\x94" => [145, ":"], "\x95" => [147, ":"], "\x96" => [149, ":"], "\x97" => [101, ":"], "\x98" => [112, ":"], "\x99" => [117, ":"], "\x9a" => [120, ":"], "\x9b" => [124, ":"], "\x9c" => [127, ":"], "\x9d" => [144, ":"], "\x9e" => [152, ":"], "\x9f" => [11, ":"], "\xa0" => [0, "B0"], "\xa1" => [0, "B1"], "\xa2" => [0, "B2"], "\xa3" => [0, "Ba"], "\xa4" => [0, "Bc"], "\xa5" => [0, "Be"], "\xa6" => [0, "Bi"], "\xa7" => [0, "Bo"], "\xa8" => [0, "Bs"], "\xa9" => [0, "Bt"], "\xaa" => [73, "B"], "\xab" => [88, "B"], "\xac" => [89, "B"], "\xad" => [96, "B"], "\xae" => [97, "B"], "\xaf" => [99, "B"], "\xb0" => [106, "B"], "\xb1" => [136, "B"], "\xb2" => [139, "B"], "\xb3" => [141, "B"], "\xb4" => [145, "B"], "\xb5" => [147, "B"], "\xb6" => [149, "B"], "\xb7" => [101, "B"], "\xb8" => [112, "B"], "\xb9" => [117, "B"], "\xba" => [120, "B"], "\xbb" => [124, "B"], "\xbc" => [127, "B"], "\xbd" => [144, "B"], "\xbe" => [152, "B"], "\xbf" => [11, "B"], "\xc0" => [0, "C0"], "\xc1" => [0, "C1"], "\xc2" => [0, "C2"], "\xc3" => [0, "Ca"], "\xc4" => [0, "Cc"], "\xc5" => [0, "Ce"], "\xc6" => [0, "Ci"], "\xc7" => [0, "Co"], "\xc8" => [0, "Cs"], "\xc9" => [0, "Ct"], "\xca" => [73, "C"], "\xcb" => [88, "C"], "\xcc" => [89, "C"], "\xcd" => [96, "C"], "\xce" => [97, "C"], "\xcf" => [99, "C"], "\xd0" => [106, "C"], "\xd1" => [136, "C"], "\xd2" => [139, "C"], "\xd3" => [141, "C"], "\xd4" => [145, "C"], "\xd5" => [147, "C"], "\xd6" => [149, "C"], "\xd7" => [101, "C"], "\xd8" => [112, "C"], "\xd9" => [117, "C"], "\xda" => [120, "C"], "\xdb" => [124, "C"], "\xdc" => [127, "C"], "\xdd" => [144, "C"], "\xde" => [152, "C"], "\xdf" => [11, "C"], "\xe0" => [0, "D0"], "\xe1" => [0, "D1"], "\xe2" => [0, "D2"], "\xe3" => [0, "Da"], "\xe4" => [0, "Dc"], "\xe5" => [0, "De"], "\xe6" => [0, "Di"], "\xe7" => [0, "Do"], "\xe8" => [0, "Ds"], "\xe9" => [0, "Dt"], "\xea" => [73, "D"], "\xeb" => [88, "D"], "\xec" => [89, "D"], "\xed" => [96, "D"], "\xee" => [97, "D"], "\xef" => [99, "D"], "\xf0" => [106, "D"], "\xf1" => [136, "D"], "\xf2" => [139, "D"], "\xf3" => [141, "D"], "\xf4" => [145, "D"], "\xf5" => [147, "D"], "\xf6" => [149, "D"], "\xf7" => [101, "D"], "\xf8" => [112, "D"], "\xf9" => [117, "D"], "\xfa" => [120, "D"], "\xfb" => [124, "D"], "\xfc" => [127, "D"], "\xfd" => [144, "D"], "\xfe" => [152, "D"], "\xff" => [11, "D"]], ["\x00" => [0, "l0"], "\x01" => [0, "l1"], "\x02" => [0, "l2"], "\x03" => [0, "la"], "\x04" => [0, "lc"], "\x05" => [0, "le"], "\x06" => [0, "li"], "\x07" => [0, "lo"], "\x08" => [0, "ls"], "\t" => [0, "lt"], "\n" => [73, "l"], "\v" => [88, "l"], "\f" => [89, "l"], "\r" => [96, "l"], "\x0e" => [97, "l"], "\x0f" => [99, "l"], "\x10" => [106, "l"], "\x11" => [136, "l"], "\x12" => [139, "l"], "\x13" => [141, "l"], "\x14" => [145, "l"], "\x15" => [147, "l"], "\x16" => [149, "l"], "\x17" => [101, "l"], "\x18" => [112, "l"], "\x19" => [117, "l"], "\x1a" => [120, "l"], "\x1b" => [124, "l"], "\x1c" => [127, "l"], "\x1d" => [144, "l"], "\x1e" => [152, "l"], "\x1f" => [11, "l"], " " => [0, "m0"], "!" => [0, "m1"], "\"" => [0, "m2"], "#" => [0, "ma"], "\$" => [0, "mc"], "%" => [0, "me"], "&" => [0, "mi"], "'" => [0, "mo"], "(" => [0, "ms"], ")" => [0, "mt"], "*" => [73, "m"], "+" => [88, "m"], "," => [89, "m"], "-" => [96, "m"], "." => [97, "m"], "/" => [99, "m"], [106, "m"], [136, "m"], [139, "m"], [141, "m"], [145, "m"], [147, "m"], [149, "m"], [101, "m"], [112, "m"], [117, "m"], ":" => [120, "m"], ";" => [124, "m"], "<" => [127, "m"], "=" => [144, "m"], ">" => [152, "m"], "?" => [11, "m"], "@" => [0, "n0"], "A" => [0, "n1"], "B" => [0, "n2"], "C" => [0, "na"], "D" => [0, "nc"], "E" => [0, "ne"], "F" => [0, "ni"], "G" => [0, "no"], "H" => [0, "ns"], "I" => [0, "nt"], "J" => [73, "n"], "K" => [88, "n"], "L" => [89, "n"], "M" => [96, "n"], "N" => [97, "n"], "O" => [99, "n"], "P" => [106, "n"], "Q" => [136, "n"], "R" => [139, "n"], "S" => [141, "n"], "T" => [145, "n"], "U" => [147, "n"], "V" => [149, "n"], "W" => [101, "n"], "X" => [112, "n"], "Y" => [117, "n"], "Z" => [120, "n"], "[" => [124, "n"], "\\" => [127, "n"], "]" => [144, "n"], "^" => [152, "n"], "_" => [11, "n"], "`" => [0, "p0"], "a" => [0, "p1"], "b" => [0, "p2"], "c" => [0, "pa"], "d" => [0, "pc"], "e" => [0, "pe"], "f" => [0, "pi"], "g" => [0, "po"], "h" => [0, "ps"], "i" => [0, "pt"], "j" => [73, "p"], "k" => [88, "p"], "l" => [89, "p"], "m" => [96, "p"], "n" => [97, "p"], "o" => [99, "p"], "p" => [106, "p"], "q" => [136, "p"], "r" => [139, "p"], "s" => [141, "p"], "t" => [145, "p"], "u" => [147, "p"], "v" => [149, "p"], "w" => [101, "p"], "x" => [112, "p"], "y" => [117, "p"], "z" => [120, "p"], "{" => [124, "p"], "|" => [127, "p"], "}" => [144, "p"], "~" => [152, "p"], "" => [11, "p"], "\x80" => [0, "r0"], "\x81" => [0, "r1"], "\x82" => [0, "r2"], "\x83" => [0, "ra"], "\x84" => [0, "rc"], "\x85" => [0, "re"], "\x86" => [0, "ri"], "\x87" => [0, "ro"], "\x88" => [0, "rs"], "\x89" => [0, "rt"], "\x8a" => [73, "r"], "\x8b" => [88, "r"], "\x8c" => [89, "r"], "\x8d" => [96, "r"], "\x8e" => [97, "r"], "\x8f" => [99, "r"], "\x90" => [106, "r"], "\x91" => [136, "r"], "\x92" => [139, "r"], "\x93" => [141, "r"], "\x94" => [145, "r"], "\x95" => [147, "r"], "\x96" => [149, "r"], "\x97" => [101, "r"], "\x98" => [112, "r"], "\x99" => [117, "r"], "\x9a" => [120, "r"], "\x9b" => [124, "r"], "\x9c" => [127, "r"], "\x9d" => [144, "r"], "\x9e" => [152, "r"], "\x9f" => [11, "r"], "\xa0" => [0, "u0"], "\xa1" => [0, "u1"], "\xa2" => [0, "u2"], "\xa3" => [0, "ua"], "\xa4" => [0, "uc"], "\xa5" => [0, "ue"], "\xa6" => [0, "ui"], "\xa7" => [0, "uo"], "\xa8" => [0, "us"], "\xa9" => [0, "ut"], "\xaa" => [73, "u"], "\xab" => [88, "u"], "\xac" => [89, "u"], "\xad" => [96, "u"], "\xae" => [97, "u"], "\xaf" => [99, "u"], "\xb0" => [106, "u"], "\xb1" => [136, "u"], "\xb2" => [139, "u"], "\xb3" => [141, "u"], "\xb4" => [145, "u"], "\xb5" => [147, "u"], "\xb6" => [149, "u"], "\xb7" => [101, "u"], "\xb8" => [112, "u"], "\xb9" => [117, "u"], "\xba" => [120, "u"], "\xbb" => [124, "u"], "\xbc" => [127, "u"], "\xbd" => [144, "u"], "\xbe" => [152, "u"], "\xbf" => [11, "u"], "\xc0" => [92, ":"], "\xc1" => [95, ":"], "\xc2" => [137, ":"], "\xc3" => [142, ":"], "\xc4" => [150, ":"], "\xc5" => [74, ":"], "\xc6" => [90, ":"], "\xc7" => [98, ":"], "\xc8" => [107, ":"], "\xc9" => [140, ":"], "\xca" => [146, ":"], "\xcb" => [102, ":"], "\xcc" => [113, ":"], "\xcd" => [121, ":"], "\xce" => [128, ":"], "\xcf" => [12, ":"], "\xd0" => [92, "B"], "\xd1" => [95, "B"], "\xd2" => [137, "B"], "\xd3" => [142, "B"], "\xd4" => [150, "B"], "\xd5" => [74, "B"], "\xd6" => [90, "B"], "\xd7" => [98, "B"], "\xd8" => [107, "B"], "\xd9" => [140, "B"], "\xda" => [146, "B"], "\xdb" => [102, "B"], "\xdc" => [113, "B"], "\xdd" => [121, "B"], "\xde" => [128, "B"], "\xdf" => [12, "B"], "\xe0" => [92, "C"], "\xe1" => [95, "C"], "\xe2" => [137, "C"], "\xe3" => [142, "C"], "\xe4" => [150, "C"], "\xe5" => [74, "C"], "\xe6" => [90, "C"], "\xe7" => [98, "C"], "\xe8" => [107, "C"], "\xe9" => [140, "C"], "\xea" => [146, "C"], "\xeb" => [102, "C"], "\xec" => [113, "C"], "\xed" => [121, "C"], "\xee" => [128, "C"], "\xef" => [12, "C"], "\xf0" => [92, "D"], "\xf1" => [95, "D"], "\xf2" => [137, "D"], "\xf3" => [142, "D"], "\xf4" => [150, "D"], "\xf5" => [74, "D"], "\xf6" => [90, "D"], "\xf7" => [98, "D"], "\xf8" => [107, "D"], "\xf9" => [140, "D"], "\xfa" => [146, "D"], "\xfb" => [102, "D"], "\xfc" => [113, "D"], "\xfd" => [121, "D"], "\xfe" => [128, "D"], "\xff" => [12, "D"]], ["\x00" => [92, "="], "\x01" => [95, "="], "\x02" => [137, "="], "\x03" => [142, "="], "\x04" => [150, "="], "\x05" => [74, "="], "\x06" => [90, "="], "\x07" => [98, "="], "\x08" => [107, "="], "\t" => [140, "="], "\n" => [146, "="], "\v" => [102, "="], "\f" => [113, "="], "\r" => [121, "="], "\x0e" => [128, "="], "\x0f" => [12, "="], "\x10" => [92, "A"], "\x11" => [95, "A"], "\x12" => [137, "A"], "\x13" => [142, "A"], "\x14" => [150, "A"], "\x15" => [74, "A"], "\x16" => [90, "A"], "\x17" => [98, "A"], "\x18" => [107, "A"], "\x19" => [140, "A"], "\x1a" => [146, "A"], "\x1b" => [102, "A"], "\x1c" => [113, "A"], "\x1d" => [121, "A"], "\x1e" => [128, "A"], "\x1f" => [12, "A"], " " => [92, "_"], "!" => [95, "_"], "\"" => [137, "_"], "#" => [142, "_"], "\$" => [150, "_"], "%" => [74, "_"], "&" => [90, "_"], "'" => [98, "_"], "(" => [107, "_"], ")" => [140, "_"], "*" => [146, "_"], "+" => [102, "_"], "," => [113, "_"], "-" => [121, "_"], "." => [128, "_"], "/" => [12, "_"], [92, "b"], [95, "b"], [137, "b"], [142, "b"], [150, "b"], [74, "b"], [90, "b"], [98, "b"], [107, "b"], [140, "b"], ":" => [146, "b"], ";" => [102, "b"], "<" => [113, "b"], "=" => [121, "b"], ">" => [128, "b"], "?" => [12, "b"], "@" => [92, "d"], "A" => [95, "d"], "B" => [137, "d"], "C" => [142, "d"], "D" => [150, "d"], "E" => [74, "d"], "F" => [90, "d"], "G" => [98, "d"], "H" => [107, "d"], "I" => [140, "d"], "J" => [146, "d"], "K" => [102, "d"], "L" => [113, "d"], "M" => [121, "d"], "N" => [128, "d"], "O" => [12, "d"], "P" => [92, "f"], "Q" => [95, "f"], "R" => [137, "f"], "S" => [142, "f"], "T" => [150, "f"], "U" => [74, "f"], "V" => [90, "f"], "W" => [98, "f"], "X" => [107, "f"], "Y" => [140, "f"], "Z" => [146, "f"], "[" => [102, "f"], "\\" => [113, "f"], "]" => [121, "f"], "^" => [128, "f"], "_" => [12, "f"], "`" => [92, "g"], "a" => [95, "g"], "b" => [137, "g"], "c" => [142, "g"], "d" => [150, "g"], "e" => [74, "g"], "f" => [90, "g"], "g" => [98, "g"], "h" => [107, "g"], "i" => [140, "g"], "j" => [146, "g"], "k" => [102, "g"], "l" => [113, "g"], "m" => [121, "g"], "n" => [128, "g"], "o" => [12, "g"], "p" => [92, "h"], "q" => [95, "h"], "r" => [137, "h"], "s" => [142, "h"], "t" => [150, "h"], "u" => [74, "h"], "v" => [90, "h"], "w" => [98, "h"], "x" => [107, "h"], "y" => [140, "h"], "z" => [146, "h"], "{" => [102, "h"], "|" => [113, "h"], "}" => [121, "h"], "~" => [128, "h"], "" => [12, "h"], "\x80" => [92, "l"], "\x81" => [95, "l"], "\x82" => [137, "l"], "\x83" => [142, "l"], "\x84" => [150, "l"], "\x85" => [74, "l"], "\x86" => [90, "l"], "\x87" => [98, "l"], "\x88" => [107, "l"], "\x89" => [140, "l"], "\x8a" => [146, "l"], "\x8b" => [102, "l"], "\x8c" => [113, "l"], "\x8d" => [121, "l"], "\x8e" => [128, "l"], "\x8f" => [12, "l"], "\x90" => [92, "m"], "\x91" => [95, "m"], "\x92" => [137, "m"], "\x93" => [142, "m"], "\x94" => [150, "m"], "\x95" => [74, "m"], "\x96" => [90, "m"], "\x97" => [98, "m"], "\x98" => [107, "m"], "\x99" => [140, "m"], "\x9a" => [146, "m"], "\x9b" => [102, "m"], "\x9c" => [113, "m"], "\x9d" => [121, "m"], "\x9e" => [128, "m"], "\x9f" => [12, "m"], "\xa0" => [92, "n"], "\xa1" => [95, "n"], "\xa2" => [137, "n"], "\xa3" => [142, "n"], "\xa4" => [150, "n"], "\xa5" => [74, "n"], "\xa6" => [90, "n"], "\xa7" => [98, "n"], "\xa8" => [107, "n"], "\xa9" => [140, "n"], "\xaa" => [146, "n"], "\xab" => [102, "n"], "\xac" => [113, "n"], "\xad" => [121, "n"], "\xae" => [128, "n"], "\xaf" => [12, "n"], "\xb0" => [92, "p"], "\xb1" => [95, "p"], "\xb2" => [137, "p"], "\xb3" => [142, "p"], "\xb4" => [150, "p"], "\xb5" => [74, "p"], "\xb6" => [90, "p"], "\xb7" => [98, "p"], "\xb8" => [107, "p"], "\xb9" => [140, "p"], "\xba" => [146, "p"], "\xbb" => [102, "p"], "\xbc" => [113, "p"], "\xbd" => [121, "p"], "\xbe" => [128, "p"], "\xbf" => [12, "p"], "\xc0" => [92, "r"], "\xc1" => [95, "r"], "\xc2" => [137, "r"], "\xc3" => [142, "r"], "\xc4" => [150, "r"], "\xc5" => [74, "r"], "\xc6" => [90, "r"], "\xc7" => [98, "r"], "\xc8" => [107, "r"], "\xc9" => [140, "r"], "\xca" => [146, "r"], "\xcb" => [102, "r"], "\xcc" => [113, "r"], "\xcd" => [121, "r"], "\xce" => [128, "r"], "\xcf" => [12, "r"], "\xd0" => [92, "u"], "\xd1" => [95, "u"], "\xd2" => [137, "u"], "\xd3" => [142, "u"], "\xd4" => [150, "u"], "\xd5" => [74, "u"], "\xd6" => [90, "u"], "\xd7" => [98, "u"], "\xd8" => [107, "u"], "\xd9" => [140, "u"], "\xda" => [146, "u"], "\xdb" => [102, "u"], "\xdc" => [113, "u"], "\xdd" => [121, "u"], "\xde" => [128, "u"], "\xdf" => [12, "u"], "\xe0" => [93, ":"], "\xe1" => [138, ":"], "\xe2" => [75, ":"], "\xe3" => [91, ":"], "\xe4" => [108, ":"], "\xe5" => [103, ":"], "\xe6" => [114, ":"], "\xe7" => [14, ":"], "\xe8" => [93, "B"], "\xe9" => [138, "B"], "\xea" => [75, "B"], "\xeb" => [91, "B"], "\xec" => [108, "B"], "\xed" => [103, "B"], "\xee" => [114, "B"], "\xef" => [14, "B"], "\xf0" => [93, "C"], "\xf1" => [138, "C"], "\xf2" => [75, "C"], "\xf3" => [91, "C"], "\xf4" => [108, "C"], "\xf5" => [103, "C"], "\xf6" => [114, "C"], "\xf7" => [14, "C"], "\xf8" => [93, "D"], "\xf9" => [138, "D"], "\xfa" => [75, "D"], "\xfb" => [91, "D"], "\xfc" => [108, "D"], "\xfd" => [103, "D"], "\xfe" => [114, "D"], "\xff" => [14, "D"]], ["\x00" => [94, "<0"], "\x01" => [76, "<0"], "\x02" => [104, "<0"], "\x03" => [16, "<0"], "\x04" => [94, "<1"], "\x05" => [76, "<1"], "\x06" => [104, "<1"], "\x07" => [16, "<1"], "\x08" => [94, "<2"], "\t" => [76, "<2"], "\n" => [104, "<2"], "\v" => [16, "<2"], "\f" => [94, "<a"], "\r" => [76, "<a"], "\x0e" => [104, "<a"], "\x0f" => [16, "<a"], "\x10" => [94, "<c"], "\x11" => [76, "<c"], "\x12" => [104, "<c"], "\x13" => [16, "<c"], "\x14" => [94, "<e"], "\x15" => [76, "<e"], "\x16" => [104, "<e"], "\x17" => [16, "<e"], "\x18" => [94, "<i"], "\x19" => [76, "<i"], "\x1a" => [104, "<i"], "\x1b" => [16, "<i"], "\x1c" => [94, "<o"], "\x1d" => [76, "<o"], "\x1e" => [104, "<o"], "\x1f" => [16, "<o"], " " => [94, "<s"], "!" => [76, "<s"], "\"" => [104, "<s"], "#" => [16, "<s"], "\$" => [94, "<t"], "%" => [76, "<t"], "&" => [104, "<t"], "'" => [16, "<t"], "(" => [77, "< "], ")" => [18, "< "], "*" => [77, "<%"], "+" => [18, "<%"], "," => [77, "<-"], "-" => [18, "<-"], "." => [77, "<."], "/" => [18, "<."], [77, "</"], [18, "</"], [77, "<3"], [18, "<3"], [77, "<4"], [18, "<4"], [77, "<5"], [18, "<5"], [77, "<6"], [18, "<6"], ":" => [77, "<7"], ";" => [18, "<7"], "<" => [77, "<8"], "=" => [18, "<8"], ">" => [77, "<9"], "?" => [18, "<9"], "@" => [77, "<="], "A" => [18, "<="], "B" => [77, "<A"], "C" => [18, "<A"], "D" => [77, "<_"], "E" => [18, "<_"], "F" => [77, "<b"], "G" => [18, "<b"], "H" => [77, "<d"], "I" => [18, "<d"], "J" => [77, "<f"], "K" => [18, "<f"], "L" => [77, "<g"], "M" => [18, "<g"], "N" => [77, "<h"], "O" => [18, "<h"], "P" => [77, "<l"], "Q" => [18, "<l"], "R" => [77, "<m"], "S" => [18, "<m"], "T" => [77, "<n"], "U" => [18, "<n"], "V" => [77, "<p"], "W" => [18, "<p"], "X" => [77, "<r"], "Y" => [18, "<r"], "Z" => [77, "<u"], "[" => [18, "<u"], "\\" => [0, "<:"], "]" => [0, "<B"], "^" => [0, "<C"], "_" => [0, "<D"], "`" => [0, "<E"], "a" => [0, "<F"], "b" => [0, "<G"], "c" => [0, "<H"], "d" => [0, "<I"], "e" => [0, "<J"], "f" => [0, "<K"], "g" => [0, "<L"], "h" => [0, "<M"], "i" => [0, "<N"], "j" => [0, "<O"], "k" => [0, "<P"], "l" => [0, "<Q"], "m" => [0, "<R"], "n" => [0, "<S"], "o" => [0, "<T"], "p" => [0, "<U"], "q" => [0, "<V"], "r" => [0, "<W"], "s" => [0, "<Y"], "t" => [0, "<j"], "u" => [0, "<k"], "v" => [0, "<q"], "w" => [0, "<v"], "x" => [0, "<w"], "y" => [0, "<x"], "z" => [0, "<y"], "{" => [0, "<z"], "|" => [82, "<"], "}" => [87, "<"], "~" => [130, "<"], "" => [9, "<"], "\x80" => [94, "`0"], "\x81" => [76, "`0"], "\x82" => [104, "`0"], "\x83" => [16, "`0"], "\x84" => [94, "`1"], "\x85" => [76, "`1"], "\x86" => [104, "`1"], "\x87" => [16, "`1"], "\x88" => [94, "`2"], "\x89" => [76, "`2"], "\x8a" => [104, "`2"], "\x8b" => [16, "`2"], "\x8c" => [94, "`a"], "\x8d" => [76, "`a"], "\x8e" => [104, "`a"], "\x8f" => [16, "`a"], "\x90" => [94, "`c"], "\x91" => [76, "`c"], "\x92" => [104, "`c"], "\x93" => [16, "`c"], "\x94" => [94, "`e"], "\x95" => [76, "`e"], "\x96" => [104, "`e"], "\x97" => [16, "`e"], "\x98" => [94, "`i"], "\x99" => [76, "`i"], "\x9a" => [104, "`i"], "\x9b" => [16, "`i"], "\x9c" => [94, "`o"], "\x9d" => [76, "`o"], "\x9e" => [104, "`o"], "\x9f" => [16, "`o"], "\xa0" => [94, "`s"], "\xa1" => [76, "`s"], "\xa2" => [104, "`s"], "\xa3" => [16, "`s"], "\xa4" => [94, "`t"], "\xa5" => [76, "`t"], "\xa6" => [104, "`t"], "\xa7" => [16, "`t"], "\xa8" => [77, "` "], "\xa9" => [18, "` "], "\xaa" => [77, "`%"], "\xab" => [18, "`%"], "\xac" => [77, "`-"], "\xad" => [18, "`-"], "\xae" => [77, "`."], "\xaf" => [18, "`."], "\xb0" => [77, "`/"], "\xb1" => [18, "`/"], "\xb2" => [77, "`3"], "\xb3" => [18, "`3"], "\xb4" => [77, "`4"], "\xb5" => [18, "`4"], "\xb6" => [77, "`5"], "\xb7" => [18, "`5"], "\xb8" => [77, "`6"], "\xb9" => [18, "`6"], "\xba" => [77, "`7"], "\xbb" => [18, "`7"], "\xbc" => [77, "`8"], "\xbd" => [18, "`8"], "\xbe" => [77, "`9"], "\xbf" => [18, "`9"], "\xc0" => [77, "`="], "\xc1" => [18, "`="], "\xc2" => [77, "`A"], "\xc3" => [18, "`A"], "\xc4" => [77, "`_"], "\xc5" => [18, "`_"], "\xc6" => [77, "`b"], "\xc7" => [18, "`b"], "\xc8" => [77, "`d"], "\xc9" => [18, "`d"], "\xca" => [77, "`f"], "\xcb" => [18, "`f"], "\xcc" => [77, "`g"], "\xcd" => [18, "`g"], "\xce" => [77, "`h"], "\xcf" => [18, "`h"], "\xd0" => [77, "`l"], "\xd1" => [18, "`l"], "\xd2" => [77, "`m"], "\xd3" => [18, "`m"], "\xd4" => [77, "`n"], "\xd5" => [18, "`n"], "\xd6" => [77, "`p"], "\xd7" => [18, "`p"], "\xd8" => [77, "`r"], "\xd9" => [18, "`r"], "\xda" => [77, "`u"], "\xdb" => [18, "`u"], "\xdc" => [0, "`:"], "\xdd" => [0, "`B"], "\xde" => [0, "`C"], "\xdf" => [0, "`D"], "\xe0" => [0, "`E"], "\xe1" => [0, "`F"], "\xe2" => [0, "`G"], "\xe3" => [0, "`H"], "\xe4" => [0, "`I"], "\xe5" => [0, "`J"], "\xe6" => [0, "`K"], "\xe7" => [0, "`L"], "\xe8" => [0, "`M"], "\xe9" => [0, "`N"], "\xea" => [0, "`O"], "\xeb" => [0, "`P"], "\xec" => [0, "`Q"], "\xed" => [0, "`R"], "\xee" => [0, "`S"], "\xef" => [0, "`T"], "\xf0" => [0, "`U"], "\xf1" => [0, "`V"], "\xf2" => [0, "`W"], "\xf3" => [0, "`Y"], "\xf4" => [0, "`j"], "\xf5" => [0, "`k"], "\xf6" => [0, "`q"], "\xf7" => [0, "`v"], "\xf8" => [0, "`w"], "\xf9" => [0, "`x"], "\xfa" => [0, "`y"], "\xfb" => [0, "`z"], "\xfc" => [82, "`"], "\xfd" => [87, "`"], "\xfe" => [130, "`"], "\xff" => [9, "`"]], ["\x00" => [94, "=0"], "\x01" => [76, "=0"], "\x02" => [104, "=0"], "\x03" => [16, "=0"], "\x04" => [94, "=1"], "\x05" => [76, "=1"], "\x06" => [104, "=1"], "\x07" => [16, "=1"], "\x08" => [94, "=2"], "\t" => [76, "=2"], "\n" => [104, "=2"], "\v" => [16, "=2"], "\f" => [94, "=a"], "\r" => [76, "=a"], "\x0e" => [104, "=a"], "\x0f" => [16, "=a"], "\x10" => [94, "=c"], "\x11" => [76, "=c"], "\x12" => [104, "=c"], "\x13" => [16, "=c"], "\x14" => [94, "=e"], "\x15" => [76, "=e"], "\x16" => [104, "=e"], "\x17" => [16, "=e"], "\x18" => [94, "=i"], "\x19" => [76, "=i"], "\x1a" => [104, "=i"], "\x1b" => [16, "=i"], "\x1c" => [94, "=o"], "\x1d" => [76, "=o"], "\x1e" => [104, "=o"], "\x1f" => [16, "=o"], " " => [94, "=s"], "!" => [76, "=s"], "\"" => [104, "=s"], "#" => [16, "=s"], "\$" => [94, "=t"], "%" => [76, "=t"], "&" => [104, "=t"], "'" => [16, "=t"], "(" => [77, "= "], ")" => [18, "= "], "*" => [77, "=%"], "+" => [18, "=%"], "," => [77, "=-"], "-" => [18, "=-"], "." => [77, "=."], "/" => [18, "=."], [77, "=/"], [18, "=/"], [77, "=3"], [18, "=3"], [77, "=4"], [18, "=4"], [77, "=5"], [18, "=5"], [77, "=6"], [18, "=6"], ":" => [77, "=7"], ";" => [18, "=7"], "<" => [77, "=8"], "=" => [18, "=8"], ">" => [77, "=9"], "?" => [18, "=9"], "@" => [77, "=="], "A" => [18, "=="], "B" => [77, "=A"], "C" => [18, "=A"], "D" => [77, "=_"], "E" => [18, "=_"], "F" => [77, "=b"], "G" => [18, "=b"], "H" => [77, "=d"], "I" => [18, "=d"], "J" => [77, "=f"], "K" => [18, "=f"], "L" => [77, "=g"], "M" => [18, "=g"], "N" => [77, "=h"], "O" => [18, "=h"], "P" => [77, "=l"], "Q" => [18, "=l"], "R" => [77, "=m"], "S" => [18, "=m"], "T" => [77, "=n"], "U" => [18, "=n"], "V" => [77, "=p"], "W" => [18, "=p"], "X" => [77, "=r"], "Y" => [18, "=r"], "Z" => [77, "=u"], "[" => [18, "=u"], "\\" => [0, "=:"], "]" => [0, "=B"], "^" => [0, "=C"], "_" => [0, "=D"], "`" => [0, "=E"], "a" => [0, "=F"], "b" => [0, "=G"], "c" => [0, "=H"], "d" => [0, "=I"], "e" => [0, "=J"], "f" => [0, "=K"], "g" => [0, "=L"], "h" => [0, "=M"], "i" => [0, "=N"], "j" => [0, "=O"], "k" => [0, "=P"], "l" => [0, "=Q"], "m" => [0, "=R"], "n" => [0, "=S"], "o" => [0, "=T"], "p" => [0, "=U"], "q" => [0, "=V"], "r" => [0, "=W"], "s" => [0, "=Y"], "t" => [0, "=j"], "u" => [0, "=k"], "v" => [0, "=q"], "w" => [0, "=v"], "x" => [0, "=w"], "y" => [0, "=x"], "z" => [0, "=y"], "{" => [0, "=z"], "|" => [82, "="], "}" => [87, "="], "~" => [130, "="], "" => [9, "="], "\x80" => [94, "A0"], "\x81" => [76, "A0"], "\x82" => [104, "A0"], "\x83" => [16, "A0"], "\x84" => [94, "A1"], "\x85" => [76, "A1"], "\x86" => [104, "A1"], "\x87" => [16, "A1"], "\x88" => [94, "A2"], "\x89" => [76, "A2"], "\x8a" => [104, "A2"], "\x8b" => [16, "A2"], "\x8c" => [94, "Aa"], "\x8d" => [76, "Aa"], "\x8e" => [104, "Aa"], "\x8f" => [16, "Aa"], "\x90" => [94, "Ac"], "\x91" => [76, "Ac"], "\x92" => [104, "Ac"], "\x93" => [16, "Ac"], "\x94" => [94, "Ae"], "\x95" => [76, "Ae"], "\x96" => [104, "Ae"], "\x97" => [16, "Ae"], "\x98" => [94, "Ai"], "\x99" => [76, "Ai"], "\x9a" => [104, "Ai"], "\x9b" => [16, "Ai"], "\x9c" => [94, "Ao"], "\x9d" => [76, "Ao"], "\x9e" => [104, "Ao"], "\x9f" => [16, "Ao"], "\xa0" => [94, "As"], "\xa1" => [76, "As"], "\xa2" => [104, "As"], "\xa3" => [16, "As"], "\xa4" => [94, "At"], "\xa5" => [76, "At"], "\xa6" => [104, "At"], "\xa7" => [16, "At"], "\xa8" => [77, "A "], "\xa9" => [18, "A "], "\xaa" => [77, "A%"], "\xab" => [18, "A%"], "\xac" => [77, "A-"], "\xad" => [18, "A-"], "\xae" => [77, "A."], "\xaf" => [18, "A."], "\xb0" => [77, "A/"], "\xb1" => [18, "A/"], "\xb2" => [77, "A3"], "\xb3" => [18, "A3"], "\xb4" => [77, "A4"], "\xb5" => [18, "A4"], "\xb6" => [77, "A5"], "\xb7" => [18, "A5"], "\xb8" => [77, "A6"], "\xb9" => [18, "A6"], "\xba" => [77, "A7"], "\xbb" => [18, "A7"], "\xbc" => [77, "A8"], "\xbd" => [18, "A8"], "\xbe" => [77, "A9"], "\xbf" => [18, "A9"], "\xc0" => [77, "A="], "\xc1" => [18, "A="], "\xc2" => [77, "AA"], "\xc3" => [18, "AA"], "\xc4" => [77, "A_"], "\xc5" => [18, "A_"], "\xc6" => [77, "Ab"], "\xc7" => [18, "Ab"], "\xc8" => [77, "Ad"], "\xc9" => [18, "Ad"], "\xca" => [77, "Af"], "\xcb" => [18, "Af"], "\xcc" => [77, "Ag"], "\xcd" => [18, "Ag"], "\xce" => [77, "Ah"], "\xcf" => [18, "Ah"], "\xd0" => [77, "Al"], "\xd1" => [18, "Al"], "\xd2" => [77, "Am"], "\xd3" => [18, "Am"], "\xd4" => [77, "An"], "\xd5" => [18, "An"], "\xd6" => [77, "Ap"], "\xd7" => [18, "Ap"], "\xd8" => [77, "Ar"], "\xd9" => [18, "Ar"], "\xda" => [77, "Au"], "\xdb" => [18, "Au"], "\xdc" => [0, "A:"], "\xdd" => [0, "AB"], "\xde" => [0, "AC"], "\xdf" => [0, "AD"], "\xe0" => [0, "AE"], "\xe1" => [0, "AF"], "\xe2" => [0, "AG"], "\xe3" => [0, "AH"], "\xe4" => [0, "AI"], "\xe5" => [0, "AJ"], "\xe6" => [0, "AK"], "\xe7" => [0, "AL"], "\xe8" => [0, "AM"], "\xe9" => [0, "AN"], "\xea" => [0, "AO"], "\xeb" => [0, "AP"], "\xec" => [0, "AQ"], "\xed" => [0, "AR"], "\xee" => [0, "AS"], "\xef" => [0, "AT"], "\xf0" => [0, "AU"], "\xf1" => [0, "AV"], "\xf2" => [0, "AW"], "\xf3" => [0, "AY"], "\xf4" => [0, "Aj"], "\xf5" => [0, "Ak"], "\xf6" => [0, "Aq"], "\xf7" => [0, "Av"], "\xf8" => [0, "Aw"], "\xf9" => [0, "Ax"], "\xfa" => [0, "Ay"], "\xfb" => [0, "Az"], "\xfc" => [82, "A"], "\xfd" => [87, "A"], "\xfe" => [130, "A"], "\xff" => [9, "A"]], ["\x00" => [77, "=0"], "\x01" => [18, "=0"], "\x02" => [77, "=1"], "\x03" => [18, "=1"], "\x04" => [77, "=2"], "\x05" => [18, "=2"], "\x06" => [77, "=a"], "\x07" => [18, "=a"], "\x08" => [77, "=c"], "\t" => [18, "=c"], "\n" => [77, "=e"], "\v" => [18, "=e"], "\f" => [77, "=i"], "\r" => [18, "=i"], "\x0e" => [77, "=o"], "\x0f" => [18, "=o"], "\x10" => [77, "=s"], "\x11" => [18, "=s"], "\x12" => [77, "=t"], "\x13" => [18, "=t"], "\x14" => [0, "= "], "\x15" => [0, "=%"], "\x16" => [0, "=-"], "\x17" => [0, "=."], "\x18" => [0, "=/"], "\x19" => [0, "=3"], "\x1a" => [0, "=4"], "\x1b" => [0, "=5"], "\x1c" => [0, "=6"], "\x1d" => [0, "=7"], "\x1e" => [0, "=8"], "\x1f" => [0, "=9"], " " => [0, "=="], "!" => [0, "=A"], "\"" => [0, "=_"], "#" => [0, "=b"], "\$" => [0, "=d"], "%" => [0, "=f"], "&" => [0, "=g"], "'" => [0, "=h"], "(" => [0, "=l"], ")" => [0, "=m"], "*" => [0, "=n"], "+" => [0, "=p"], "," => [0, "=r"], "-" => [0, "=u"], "." => [100, "="], "/" => [110, "="], [111, "="], [115, "="], [116, "="], [118, "="], [119, "="], [122, "="], [123, "="], [125, "="], [126, "="], [129, "="], ":" => [143, "="], ";" => [148, "="], "<" => [151, "="], "=" => [153, "="], ">" => [83, "="], "?" => [10, "="], "@" => [77, "A0"], "A" => [18, "A0"], "B" => [77, "A1"], "C" => [18, "A1"], "D" => [77, "A2"], "E" => [18, "A2"], "F" => [77, "Aa"], "G" => [18, "Aa"], "H" => [77, "Ac"], "I" => [18, "Ac"], "J" => [77, "Ae"], "K" => [18, "Ae"], "L" => [77, "Ai"], "M" => [18, "Ai"], "N" => [77, "Ao"], "O" => [18, "Ao"], "P" => [77, "As"], "Q" => [18, "As"], "R" => [77, "At"], "S" => [18, "At"], "T" => [0, "A "], "U" => [0, "A%"], "V" => [0, "A-"], "W" => [0, "A."], "X" => [0, "A/"], "Y" => [0, "A3"], "Z" => [0, "A4"], "[" => [0, "A5"], "\\" => [0, "A6"], "]" => [0, "A7"], "^" => [0, "A8"], "_" => [0, "A9"], "`" => [0, "A="], "a" => [0, "AA"], "b" => [0, "A_"], "c" => [0, "Ab"], "d" => [0, "Ad"], "e" => [0, "Af"], "f" => [0, "Ag"], "g" => [0, "Ah"], "h" => [0, "Al"], "i" => [0, "Am"], "j" => [0, "An"], "k" => [0, "Ap"], "l" => [0, "Ar"], "m" => [0, "Au"], "n" => [100, "A"], "o" => [110, "A"], "p" => [111, "A"], "q" => [115, "A"], "r" => [116, "A"], "s" => [118, "A"], "t" => [119, "A"], "u" => [122, "A"], "v" => [123, "A"], "w" => [125, "A"], "x" => [126, "A"], "y" => [129, "A"], "z" => [143, "A"], "{" => [148, "A"], "|" => [151, "A"], "}" => [153, "A"], "~" => [83, "A"], "" => [10, "A"], "\x80" => [77, "_0"], "\x81" => [18, "_0"], "\x82" => [77, "_1"], "\x83" => [18, "_1"], "\x84" => [77, "_2"], "\x85" => [18, "_2"], "\x86" => [77, "_a"], "\x87" => [18, "_a"], "\x88" => [77, "_c"], "\x89" => [18, "_c"], "\x8a" => [77, "_e"], "\x8b" => [18, "_e"], "\x8c" => [77, "_i"], "\x8d" => [18, "_i"], "\x8e" => [77, "_o"], "\x8f" => [18, "_o"], "\x90" => [77, "_s"], "\x91" => [18, "_s"], "\x92" => [77, "_t"], "\x93" => [18, "_t"], "\x94" => [0, "_ "], "\x95" => [0, "_%"], "\x96" => [0, "_-"], "\x97" => [0, "_."], "\x98" => [0, "_/"], "\x99" => [0, "_3"], "\x9a" => [0, "_4"], "\x9b" => [0, "_5"], "\x9c" => [0, "_6"], "\x9d" => [0, "_7"], "\x9e" => [0, "_8"], "\x9f" => [0, "_9"], "\xa0" => [0, "_="], "\xa1" => [0, "_A"], "\xa2" => [0, "__"], "\xa3" => [0, "_b"], "\xa4" => [0, "_d"], "\xa5" => [0, "_f"], "\xa6" => [0, "_g"], "\xa7" => [0, "_h"], "\xa8" => [0, "_l"], "\xa9" => [0, "_m"], "\xaa" => [0, "_n"], "\xab" => [0, "_p"], "\xac" => [0, "_r"], "\xad" => [0, "_u"], "\xae" => [100, "_"], "\xaf" => [110, "_"], "\xb0" => [111, "_"], "\xb1" => [115, "_"], "\xb2" => [116, "_"], "\xb3" => [118, "_"], "\xb4" => [119, "_"], "\xb5" => [122, "_"], "\xb6" => [123, "_"], "\xb7" => [125, "_"], "\xb8" => [126, "_"], "\xb9" => [129, "_"], "\xba" => [143, "_"], "\xbb" => [148, "_"], "\xbc" => [151, "_"], "\xbd" => [153, "_"], "\xbe" => [83, "_"], "\xbf" => [10, "_"], "\xc0" => [77, "b0"], "\xc1" => [18, "b0"], "\xc2" => [77, "b1"], "\xc3" => [18, "b1"], "\xc4" => [77, "b2"], "\xc5" => [18, "b2"], "\xc6" => [77, "ba"], "\xc7" => [18, "ba"], "\xc8" => [77, "bc"], "\xc9" => [18, "bc"], "\xca" => [77, "be"], "\xcb" => [18, "be"], "\xcc" => [77, "bi"], "\xcd" => [18, "bi"], "\xce" => [77, "bo"], "\xcf" => [18, "bo"], "\xd0" => [77, "bs"], "\xd1" => [18, "bs"], "\xd2" => [77, "bt"], "\xd3" => [18, "bt"], "\xd4" => [0, "b "], "\xd5" => [0, "b%"], "\xd6" => [0, "b-"], "\xd7" => [0, "b."], "\xd8" => [0, "b/"], "\xd9" => [0, "b3"], "\xda" => [0, "b4"], "\xdb" => [0, "b5"], "\xdc" => [0, "b6"], "\xdd" => [0, "b7"], "\xde" => [0, "b8"], "\xdf" => [0, "b9"], "\xe0" => [0, "b="], "\xe1" => [0, "bA"], "\xe2" => [0, "b_"], "\xe3" => [0, "bb"], "\xe4" => [0, "bd"], "\xe5" => [0, "bf"], "\xe6" => [0, "bg"], "\xe7" => [0, "bh"], "\xe8" => [0, "bl"], "\xe9" => [0, "bm"], "\xea" => [0, "bn"], "\xeb" => [0, "bp"], "\xec" => [0, "br"], "\xed" => [0, "bu"], "\xee" => [100, "b"], "\xef" => [110, "b"], "\xf0" => [111, "b"], "\xf1" => [115, "b"], "\xf2" => [116, "b"], "\xf3" => [118, "b"], "\xf4" => [119, "b"], "\xf5" => [122, "b"], "\xf6" => [123, "b"], "\xf7" => [125, "b"], "\xf8" => [126, "b"], "\xf9" => [129, "b"], "\xfa" => [143, "b"], "\xfb" => [148, "b"], "\xfc" => [151, "b"], "\xfd" => [153, "b"], "\xfe" => [83, "b"], "\xff" => [10, "b"]], ["\x00" => [0, "=0"], "\x01" => [0, "=1"], "\x02" => [0, "=2"], "\x03" => [0, "=a"], "\x04" => [0, "=c"], "\x05" => [0, "=e"], "\x06" => [0, "=i"], "\x07" => [0, "=o"], "\x08" => [0, "=s"], "\t" => [0, "=t"], "\n" => [73, "="], "\v" => [88, "="], "\f" => [89, "="], "\r" => [96, "="], "\x0e" => [97, "="], "\x0f" => [99, "="], "\x10" => [106, "="], "\x11" => [136, "="], "\x12" => [139, "="], "\x13" => [141, "="], "\x14" => [145, "="], "\x15" => [147, "="], "\x16" => [149, "="], "\x17" => [101, "="], "\x18" => [112, "="], "\x19" => [117, "="], "\x1a" => [120, "="], "\x1b" => [124, "="], "\x1c" => [127, "="], "\x1d" => [144, "="], "\x1e" => [152, "="], "\x1f" => [11, "="], " " => [0, "A0"], "!" => [0, "A1"], "\"" => [0, "A2"], "#" => [0, "Aa"], "\$" => [0, "Ac"], "%" => [0, "Ae"], "&" => [0, "Ai"], "'" => [0, "Ao"], "(" => [0, "As"], ")" => [0, "At"], "*" => [73, "A"], "+" => [88, "A"], "," => [89, "A"], "-" => [96, "A"], "." => [97, "A"], "/" => [99, "A"], [106, "A"], [136, "A"], [139, "A"], [141, "A"], [145, "A"], [147, "A"], [149, "A"], [101, "A"], [112, "A"], [117, "A"], ":" => [120, "A"], ";" => [124, "A"], "<" => [127, "A"], "=" => [144, "A"], ">" => [152, "A"], "?" => [11, "A"], "@" => [0, "_0"], "A" => [0, "_1"], "B" => [0, "_2"], "C" => [0, "_a"], "D" => [0, "_c"], "E" => [0, "_e"], "F" => [0, "_i"], "G" => [0, "_o"], "H" => [0, "_s"], "I" => [0, "_t"], "J" => [73, "_"], "K" => [88, "_"], "L" => [89, "_"], "M" => [96, "_"], "N" => [97, "_"], "O" => [99, "_"], "P" => [106, "_"], "Q" => [136, "_"], "R" => [139, "_"], "S" => [141, "_"], "T" => [145, "_"], "U" => [147, "_"], "V" => [149, "_"], "W" => [101, "_"], "X" => [112, "_"], "Y" => [117, "_"], "Z" => [120, "_"], "[" => [124, "_"], "\\" => [127, "_"], "]" => [144, "_"], "^" => [152, "_"], "_" => [11, "_"], "`" => [0, "b0"], "a" => [0, "b1"], "b" => [0, "b2"], "c" => [0, "ba"], "d" => [0, "bc"], "e" => [0, "be"], "f" => [0, "bi"], "g" => [0, "bo"], "h" => [0, "bs"], "i" => [0, "bt"], "j" => [73, "b"], "k" => [88, "b"], "l" => [89, "b"], "m" => [96, "b"], "n" => [97, "b"], "o" => [99, "b"], "p" => [106, "b"], "q" => [136, "b"], "r" => [139, "b"], "s" => [141, "b"], "t" => [145, "b"], "u" => [147, "b"], "v" => [149, "b"], "w" => [101, "b"], "x" => [112, "b"], "y" => [117, "b"], "z" => [120, "b"], "{" => [124, "b"], "|" => [127, "b"], "}" => [144, "b"], "~" => [152, "b"], "" => [11, "b"], "\x80" => [0, "d0"], "\x81" => [0, "d1"], "\x82" => [0, "d2"], "\x83" => [0, "da"], "\x84" => [0, "dc"], "\x85" => [0, "de"], "\x86" => [0, "di"], "\x87" => [0, "do"], "\x88" => [0, "ds"], "\x89" => [0, "dt"], "\x8a" => [73, "d"], "\x8b" => [88, "d"], "\x8c" => [89, "d"], "\x8d" => [96, "d"], "\x8e" => [97, "d"], "\x8f" => [99, "d"], "\x90" => [106, "d"], "\x91" => [136, "d"], "\x92" => [139, "d"], "\x93" => [141, "d"], "\x94" => [145, "d"], "\x95" => [147, "d"], "\x96" => [149, "d"], "\x97" => [101, "d"], "\x98" => [112, "d"], "\x99" => [117, "d"], "\x9a" => [120, "d"], "\x9b" => [124, "d"], "\x9c" => [127, "d"], "\x9d" => [144, "d"], "\x9e" => [152, "d"], "\x9f" => [11, "d"], "\xa0" => [0, "f0"], "\xa1" => [0, "f1"], "\xa2" => [0, "f2"], "\xa3" => [0, "fa"], "\xa4" => [0, "fc"], "\xa5" => [0, "fe"], "\xa6" => [0, "fi"], "\xa7" => [0, "fo"], "\xa8" => [0, "fs"], "\xa9" => [0, "ft"], "\xaa" => [73, "f"], "\xab" => [88, "f"], "\xac" => [89, "f"], "\xad" => [96, "f"], "\xae" => [97, "f"], "\xaf" => [99, "f"], "\xb0" => [106, "f"], "\xb1" => [136, "f"], "\xb2" => [139, "f"], "\xb3" => [141, "f"], "\xb4" => [145, "f"], "\xb5" => [147, "f"], "\xb6" => [149, "f"], "\xb7" => [101, "f"], "\xb8" => [112, "f"], "\xb9" => [117, "f"], "\xba" => [120, "f"], "\xbb" => [124, "f"], "\xbc" => [127, "f"], "\xbd" => [144, "f"], "\xbe" => [152, "f"], "\xbf" => [11, "f"], "\xc0" => [0, "g0"], "\xc1" => [0, "g1"], "\xc2" => [0, "g2"], "\xc3" => [0, "ga"], "\xc4" => [0, "gc"], "\xc5" => [0, "ge"], "\xc6" => [0, "gi"], "\xc7" => [0, "go"], "\xc8" => [0, "gs"], "\xc9" => [0, "gt"], "\xca" => [73, "g"], "\xcb" => [88, "g"], "\xcc" => [89, "g"], "\xcd" => [96, "g"], "\xce" => [97, "g"], "\xcf" => [99, "g"], "\xd0" => [106, "g"], "\xd1" => [136, "g"], "\xd2" => [139, "g"], "\xd3" => [141, "g"], "\xd4" => [145, "g"], "\xd5" => [147, "g"], "\xd6" => [149, "g"], "\xd7" => [101, "g"], "\xd8" => [112, "g"], "\xd9" => [117, "g"], "\xda" => [120, "g"], "\xdb" => [124, "g"], "\xdc" => [127, "g"], "\xdd" => [144, "g"], "\xde" => [152, "g"], "\xdf" => [11, "g"], "\xe0" => [0, "h0"], "\xe1" => [0, "h1"], "\xe2" => [0, "h2"], "\xe3" => [0, "ha"], "\xe4" => [0, "hc"], "\xe5" => [0, "he"], "\xe6" => [0, "hi"], "\xe7" => [0, "ho"], "\xe8" => [0, "hs"], "\xe9" => [0, "ht"], "\xea" => [73, "h"], "\xeb" => [88, "h"], "\xec" => [89, "h"], "\xed" => [96, "h"], "\xee" => [97, "h"], "\xef" => [99, "h"], "\xf0" => [106, "h"], "\xf1" => [136, "h"], "\xf2" => [139, "h"], "\xf3" => [141, "h"], "\xf4" => [145, "h"], "\xf5" => [147, "h"], "\xf6" => [149, "h"], "\xf7" => [101, "h"], "\xf8" => [112, "h"], "\xf9" => [117, "h"], "\xfa" => [120, "h"], "\xfb" => [124, "h"], "\xfc" => [127, "h"], "\xfd" => [144, "h"], "\xfe" => [152, "h"], "\xff" => [11, "h"]], ["\x00" => [94, "@0"], "\x01" => [76, "@0"], "\x02" => [104, "@0"], "\x03" => [16, "@0"], "\x04" => [94, "@1"], "\x05" => [76, "@1"], "\x06" => [104, "@1"], "\x07" => [16, "@1"], "\x08" => [94, "@2"], "\t" => [76, "@2"], "\n" => [104, "@2"], "\v" => [16, "@2"], "\f" => [94, "@a"], "\r" => [76, "@a"], "\x0e" => [104, "@a"], "\x0f" => [16, "@a"], "\x10" => [94, "@c"], "\x11" => [76, "@c"], "\x12" => [104, "@c"], "\x13" => [16, "@c"], "\x14" => [94, "@e"], "\x15" => [76, "@e"], "\x16" => [104, "@e"], "\x17" => [16, "@e"], "\x18" => [94, "@i"], "\x19" => [76, "@i"], "\x1a" => [104, "@i"], "\x1b" => [16, "@i"], "\x1c" => [94, "@o"], "\x1d" => [76, "@o"], "\x1e" => [104, "@o"], "\x1f" => [16, "@o"], " " => [94, "@s"], "!" => [76, "@s"], "\"" => [104, "@s"], "#" => [16, "@s"], "\$" => [94, "@t"], "%" => [76, "@t"], "&" => [104, "@t"], "'" => [16, "@t"], "(" => [77, "@ "], ")" => [18, "@ "], "*" => [77, "@%"], "+" => [18, "@%"], "," => [77, "@-"], "-" => [18, "@-"], "." => [77, "@."], "/" => [18, "@."], [77, "@/"], [18, "@/"], [77, "@3"], [18, "@3"], [77, "@4"], [18, "@4"], [77, "@5"], [18, "@5"], [77, "@6"], [18, "@6"], ":" => [77, "@7"], ";" => [18, "@7"], "<" => [77, "@8"], "=" => [18, "@8"], ">" => [77, "@9"], "?" => [18, "@9"], "@" => [77, "@="], "A" => [18, "@="], "B" => [77, "@A"], "C" => [18, "@A"], "D" => [77, "@_"], "E" => [18, "@_"], "F" => [77, "@b"], "G" => [18, "@b"], "H" => [77, "@d"], "I" => [18, "@d"], "J" => [77, "@f"], "K" => [18, "@f"], "L" => [77, "@g"], "M" => [18, "@g"], "N" => [77, "@h"], "O" => [18, "@h"], "P" => [77, "@l"], "Q" => [18, "@l"], "R" => [77, "@m"], "S" => [18, "@m"], "T" => [77, "@n"], "U" => [18, "@n"], "V" => [77, "@p"], "W" => [18, "@p"], "X" => [77, "@r"], "Y" => [18, "@r"], "Z" => [77, "@u"], "[" => [18, "@u"], "\\" => [0, "@:"], "]" => [0, "@B"], "^" => [0, "@C"], "_" => [0, "@D"], "`" => [0, "@E"], "a" => [0, "@F"], "b" => [0, "@G"], "c" => [0, "@H"], "d" => [0, "@I"], "e" => [0, "@J"], "f" => [0, "@K"], "g" => [0, "@L"], "h" => [0, "@M"], "i" => [0, "@N"], "j" => [0, "@O"], "k" => [0, "@P"], "l" => [0, "@Q"], "m" => [0, "@R"], "n" => [0, "@S"], "o" => [0, "@T"], "p" => [0, "@U"], "q" => [0, "@V"], "r" => [0, "@W"], "s" => [0, "@Y"], "t" => [0, "@j"], "u" => [0, "@k"], "v" => [0, "@q"], "w" => [0, "@v"], "x" => [0, "@w"], "y" => [0, "@x"], "z" => [0, "@y"], "{" => [0, "@z"], "|" => [82, "@"], "}" => [87, "@"], "~" => [130, "@"], "" => [9, "@"], "\x80" => [94, "[0"], "\x81" => [76, "[0"], "\x82" => [104, "[0"], "\x83" => [16, "[0"], "\x84" => [94, "[1"], "\x85" => [76, "[1"], "\x86" => [104, "[1"], "\x87" => [16, "[1"], "\x88" => [94, "[2"], "\x89" => [76, "[2"], "\x8a" => [104, "[2"], "\x8b" => [16, "[2"], "\x8c" => [94, "[a"], "\x8d" => [76, "[a"], "\x8e" => [104, "[a"], "\x8f" => [16, "[a"], "\x90" => [94, "[c"], "\x91" => [76, "[c"], "\x92" => [104, "[c"], "\x93" => [16, "[c"], "\x94" => [94, "[e"], "\x95" => [76, "[e"], "\x96" => [104, "[e"], "\x97" => [16, "[e"], "\x98" => [94, "[i"], "\x99" => [76, "[i"], "\x9a" => [104, "[i"], "\x9b" => [16, "[i"], "\x9c" => [94, "[o"], "\x9d" => [76, "[o"], "\x9e" => [104, "[o"], "\x9f" => [16, "[o"], "\xa0" => [94, "[s"], "\xa1" => [76, "[s"], "\xa2" => [104, "[s"], "\xa3" => [16, "[s"], "\xa4" => [94, "[t"], "\xa5" => [76, "[t"], "\xa6" => [104, "[t"], "\xa7" => [16, "[t"], "\xa8" => [77, "[ "], "\xa9" => [18, "[ "], "\xaa" => [77, "[%"], "\xab" => [18, "[%"], "\xac" => [77, "[-"], "\xad" => [18, "[-"], "\xae" => [77, "[."], "\xaf" => [18, "[."], "\xb0" => [77, "[/"], "\xb1" => [18, "[/"], "\xb2" => [77, "[3"], "\xb3" => [18, "[3"], "\xb4" => [77, "[4"], "\xb5" => [18, "[4"], "\xb6" => [77, "[5"], "\xb7" => [18, "[5"], "\xb8" => [77, "[6"], "\xb9" => [18, "[6"], "\xba" => [77, "[7"], "\xbb" => [18, "[7"], "\xbc" => [77, "[8"], "\xbd" => [18, "[8"], "\xbe" => [77, "[9"], "\xbf" => [18, "[9"], "\xc0" => [77, "[="], "\xc1" => [18, "[="], "\xc2" => [77, "[A"], "\xc3" => [18, "[A"], "\xc4" => [77, "[_"], "\xc5" => [18, "[_"], "\xc6" => [77, "[b"], "\xc7" => [18, "[b"], "\xc8" => [77, "[d"], "\xc9" => [18, "[d"], "\xca" => [77, "[f"], "\xcb" => [18, "[f"], "\xcc" => [77, "[g"], "\xcd" => [18, "[g"], "\xce" => [77, "[h"], "\xcf" => [18, "[h"], "\xd0" => [77, "[l"], "\xd1" => [18, "[l"], "\xd2" => [77, "[m"], "\xd3" => [18, "[m"], "\xd4" => [77, "[n"], "\xd5" => [18, "[n"], "\xd6" => [77, "[p"], "\xd7" => [18, "[p"], "\xd8" => [77, "[r"], "\xd9" => [18, "[r"], "\xda" => [77, "[u"], "\xdb" => [18, "[u"], "\xdc" => [0, "[:"], "\xdd" => [0, "[B"], "\xde" => [0, "[C"], "\xdf" => [0, "[D"], "\xe0" => [0, "[E"], "\xe1" => [0, "[F"], "\xe2" => [0, "[G"], "\xe3" => [0, "[H"], "\xe4" => [0, "[I"], "\xe5" => [0, "[J"], "\xe6" => [0, "[K"], "\xe7" => [0, "[L"], "\xe8" => [0, "[M"], "\xe9" => [0, "[N"], "\xea" => [0, "[O"], "\xeb" => [0, "[P"], "\xec" => [0, "[Q"], "\xed" => [0, "[R"], "\xee" => [0, "[S"], "\xef" => [0, "[T"], "\xf0" => [0, "[U"], "\xf1" => [0, "[V"], "\xf2" => [0, "[W"], "\xf3" => [0, "[Y"], "\xf4" => [0, "[j"], "\xf5" => [0, "[k"], "\xf6" => [0, "[q"], "\xf7" => [0, "[v"], "\xf8" => [0, "[w"], "\xf9" => [0, "[x"], "\xfa" => [0, "[y"], "\xfb" => [0, "[z"], "\xfc" => [82, "["], "\xfd" => [87, "["], "\xfe" => [130, "["], "\xff" => [9, "["]], ["\x00" => [94, "C0"], "\x01" => [76, "C0"], "\x02" => [104, "C0"], "\x03" => [16, "C0"], "\x04" => [94, "C1"], "\x05" => [76, "C1"], "\x06" => [104, "C1"], "\x07" => [16, "C1"], "\x08" => [94, "C2"], "\t" => [76, "C2"], "\n" => [104, "C2"], "\v" => [16, "C2"], "\f" => [94, "Ca"], "\r" => [76, "Ca"], "\x0e" => [104, "Ca"], "\x0f" => [16, "Ca"], "\x10" => [94, "Cc"], "\x11" => [76, "Cc"], "\x12" => [104, "Cc"], "\x13" => [16, "Cc"], "\x14" => [94, "Ce"], "\x15" => [76, "Ce"], "\x16" => [104, "Ce"], "\x17" => [16, "Ce"], "\x18" => [94, "Ci"], "\x19" => [76, "Ci"], "\x1a" => [104, "Ci"], "\x1b" => [16, "Ci"], "\x1c" => [94, "Co"], "\x1d" => [76, "Co"], "\x1e" => [104, "Co"], "\x1f" => [16, "Co"], " " => [94, "Cs"], "!" => [76, "Cs"], "\"" => [104, "Cs"], "#" => [16, "Cs"], "\$" => [94, "Ct"], "%" => [76, "Ct"], "&" => [104, "Ct"], "'" => [16, "Ct"], "(" => [77, "C "], ")" => [18, "C "], "*" => [77, "C%"], "+" => [18, "C%"], "," => [77, "C-"], "-" => [18, "C-"], "." => [77, "C."], "/" => [18, "C."], [77, "C/"], [18, "C/"], [77, "C3"], [18, "C3"], [77, "C4"], [18, "C4"], [77, "C5"], [18, "C5"], [77, "C6"], [18, "C6"], ":" => [77, "C7"], ";" => [18, "C7"], "<" => [77, "C8"], "=" => [18, "C8"], ">" => [77, "C9"], "?" => [18, "C9"], "@" => [77, "C="], "A" => [18, "C="], "B" => [77, "CA"], "C" => [18, "CA"], "D" => [77, "C_"], "E" => [18, "C_"], "F" => [77, "Cb"], "G" => [18, "Cb"], "H" => [77, "Cd"], "I" => [18, "Cd"], "J" => [77, "Cf"], "K" => [18, "Cf"], "L" => [77, "Cg"], "M" => [18, "Cg"], "N" => [77, "Ch"], "O" => [18, "Ch"], "P" => [77, "Cl"], "Q" => [18, "Cl"], "R" => [77, "Cm"], "S" => [18, "Cm"], "T" => [77, "Cn"], "U" => [18, "Cn"], "V" => [77, "Cp"], "W" => [18, "Cp"], "X" => [77, "Cr"], "Y" => [18, "Cr"], "Z" => [77, "Cu"], "[" => [18, "Cu"], "\\" => [0, "C:"], "]" => [0, "CB"], "^" => [0, "CC"], "_" => [0, "CD"], "`" => [0, "CE"], "a" => [0, "CF"], "b" => [0, "CG"], "c" => [0, "CH"], "d" => [0, "CI"], "e" => [0, "CJ"], "f" => [0, "CK"], "g" => [0, "CL"], "h" => [0, "CM"], "i" => [0, "CN"], "j" => [0, "CO"], "k" => [0, "CP"], "l" => [0, "CQ"], "m" => [0, "CR"], "n" => [0, "CS"], "o" => [0, "CT"], "p" => [0, "CU"], "q" => [0, "CV"], "r" => [0, "CW"], "s" => [0, "CY"], "t" => [0, "Cj"], "u" => [0, "Ck"], "v" => [0, "Cq"], "w" => [0, "Cv"], "x" => [0, "Cw"], "y" => [0, "Cx"], "z" => [0, "Cy"], "{" => [0, "Cz"], "|" => [82, "C"], "}" => [87, "C"], "~" => [130, "C"], "" => [9, "C"], "\x80" => [94, "D0"], "\x81" => [76, "D0"], "\x82" => [104, "D0"], "\x83" => [16, "D0"], "\x84" => [94, "D1"], "\x85" => [76, "D1"], "\x86" => [104, "D1"], "\x87" => [16, "D1"], "\x88" => [94, "D2"], "\x89" => [76, "D2"], "\x8a" => [104, "D2"], "\x8b" => [16, "D2"], "\x8c" => [94, "Da"], "\x8d" => [76, "Da"], "\x8e" => [104, "Da"], "\x8f" => [16, "Da"], "\x90" => [94, "Dc"], "\x91" => [76, "Dc"], "\x92" => [104, "Dc"], "\x93" => [16, "Dc"], "\x94" => [94, "De"], "\x95" => [76, "De"], "\x96" => [104, "De"], "\x97" => [16, "De"], "\x98" => [94, "Di"], "\x99" => [76, "Di"], "\x9a" => [104, "Di"], "\x9b" => [16, "Di"], "\x9c" => [94, "Do"], "\x9d" => [76, "Do"], "\x9e" => [104, "Do"], "\x9f" => [16, "Do"], "\xa0" => [94, "Ds"], "\xa1" => [76, "Ds"], "\xa2" => [104, "Ds"], "\xa3" => [16, "Ds"], "\xa4" => [94, "Dt"], "\xa5" => [76, "Dt"], "\xa6" => [104, "Dt"], "\xa7" => [16, "Dt"], "\xa8" => [77, "D "], "\xa9" => [18, "D "], "\xaa" => [77, "D%"], "\xab" => [18, "D%"], "\xac" => [77, "D-"], "\xad" => [18, "D-"], "\xae" => [77, "D."], "\xaf" => [18, "D."], "\xb0" => [77, "D/"], "\xb1" => [18, "D/"], "\xb2" => [77, "D3"], "\xb3" => [18, "D3"], "\xb4" => [77, "D4"], "\xb5" => [18, "D4"], "\xb6" => [77, "D5"], "\xb7" => [18, "D5"], "\xb8" => [77, "D6"], "\xb9" => [18, "D6"], "\xba" => [77, "D7"], "\xbb" => [18, "D7"], "\xbc" => [77, "D8"], "\xbd" => [18, "D8"], "\xbe" => [77, "D9"], "\xbf" => [18, "D9"], "\xc0" => [77, "D="], "\xc1" => [18, "D="], "\xc2" => [77, "DA"], "\xc3" => [18, "DA"], "\xc4" => [77, "D_"], "\xc5" => [18, "D_"], "\xc6" => [77, "Db"], "\xc7" => [18, "Db"], "\xc8" => [77, "Dd"], "\xc9" => [18, "Dd"], "\xca" => [77, "Df"], "\xcb" => [18, "Df"], "\xcc" => [77, "Dg"], "\xcd" => [18, "Dg"], "\xce" => [77, "Dh"], "\xcf" => [18, "Dh"], "\xd0" => [77, "Dl"], "\xd1" => [18, "Dl"], "\xd2" => [77, "Dm"], "\xd3" => [18, "Dm"], "\xd4" => [77, "Dn"], "\xd5" => [18, "Dn"], "\xd6" => [77, "Dp"], "\xd7" => [18, "Dp"], "\xd8" => [77, "Dr"], "\xd9" => [18, "Dr"], "\xda" => [77, "Du"], "\xdb" => [18, "Du"], "\xdc" => [0, "D:"], "\xdd" => [0, "DB"], "\xde" => [0, "DC"], "\xdf" => [0, "DD"], "\xe0" => [0, "DE"], "\xe1" => [0, "DF"], "\xe2" => [0, "DG"], "\xe3" => [0, "DH"], "\xe4" => [0, "DI"], "\xe5" => [0, "DJ"], "\xe6" => [0, "DK"], "\xe7" => [0, "DL"], "\xe8" => [0, "DM"], "\xe9" => [0, "DN"], "\xea" => [0, "DO"], "\xeb" => [0, "DP"], "\xec" => [0, "DQ"], "\xed" => [0, "DR"], "\xee" => [0, "DS"], "\xef" => [0, "DT"], "\xf0" => [0, "DU"], "\xf1" => [0, "DV"], "\xf2" => [0, "DW"], "\xf3" => [0, "DY"], "\xf4" => [0, "Dj"], "\xf5" => [0, "Dk"], "\xf6" => [0, "Dq"], "\xf7" => [0, "Dv"], "\xf8" => [0, "Dw"], "\xf9" => [0, "Dx"], "\xfa" => [0, "Dy"], "\xfb" => [0, "Dz"], "\xfc" => [82, "D"], "\xfd" => [87, "D"], "\xfe" => [130, "D"], "\xff" => [9, "D"]], ["\x00" => [94, "E0"], "\x01" => [76, "E0"], "\x02" => [104, "E0"], "\x03" => [16, "E0"], "\x04" => [94, "E1"], "\x05" => [76, "E1"], "\x06" => [104, "E1"], "\x07" => [16, "E1"], "\x08" => [94, "E2"], "\t" => [76, "E2"], "\n" => [104, "E2"], "\v" => [16, "E2"], "\f" => [94, "Ea"], "\r" => [76, "Ea"], "\x0e" => [104, "Ea"], "\x0f" => [16, "Ea"], "\x10" => [94, "Ec"], "\x11" => [76, "Ec"], "\x12" => [104, "Ec"], "\x13" => [16, "Ec"], "\x14" => [94, "Ee"], "\x15" => [76, "Ee"], "\x16" => [104, "Ee"], "\x17" => [16, "Ee"], "\x18" => [94, "Ei"], "\x19" => [76, "Ei"], "\x1a" => [104, "Ei"], "\x1b" => [16, "Ei"], "\x1c" => [94, "Eo"], "\x1d" => [76, "Eo"], "\x1e" => [104, "Eo"], "\x1f" => [16, "Eo"], " " => [94, "Es"], "!" => [76, "Es"], "\"" => [104, "Es"], "#" => [16, "Es"], "\$" => [94, "Et"], "%" => [76, "Et"], "&" => [104, "Et"], "'" => [16, "Et"], "(" => [77, "E "], ")" => [18, "E "], "*" => [77, "E%"], "+" => [18, "E%"], "," => [77, "E-"], "-" => [18, "E-"], "." => [77, "E."], "/" => [18, "E."], [77, "E/"], [18, "E/"], [77, "E3"], [18, "E3"], [77, "E4"], [18, "E4"], [77, "E5"], [18, "E5"], [77, "E6"], [18, "E6"], ":" => [77, "E7"], ";" => [18, "E7"], "<" => [77, "E8"], "=" => [18, "E8"], ">" => [77, "E9"], "?" => [18, "E9"], "@" => [77, "E="], "A" => [18, "E="], "B" => [77, "EA"], "C" => [18, "EA"], "D" => [77, "E_"], "E" => [18, "E_"], "F" => [77, "Eb"], "G" => [18, "Eb"], "H" => [77, "Ed"], "I" => [18, "Ed"], "J" => [77, "Ef"], "K" => [18, "Ef"], "L" => [77, "Eg"], "M" => [18, "Eg"], "N" => [77, "Eh"], "O" => [18, "Eh"], "P" => [77, "El"], "Q" => [18, "El"], "R" => [77, "Em"], "S" => [18, "Em"], "T" => [77, "En"], "U" => [18, "En"], "V" => [77, "Ep"], "W" => [18, "Ep"], "X" => [77, "Er"], "Y" => [18, "Er"], "Z" => [77, "Eu"], "[" => [18, "Eu"], "\\" => [0, "E:"], "]" => [0, "EB"], "^" => [0, "EC"], "_" => [0, "ED"], "`" => [0, "EE"], "a" => [0, "EF"], "b" => [0, "EG"], "c" => [0, "EH"], "d" => [0, "EI"], "e" => [0, "EJ"], "f" => [0, "EK"], "g" => [0, "EL"], "h" => [0, "EM"], "i" => [0, "EN"], "j" => [0, "EO"], "k" => [0, "EP"], "l" => [0, "EQ"], "m" => [0, "ER"], "n" => [0, "ES"], "o" => [0, "ET"], "p" => [0, "EU"], "q" => [0, "EV"], "r" => [0, "EW"], "s" => [0, "EY"], "t" => [0, "Ej"], "u" => [0, "Ek"], "v" => [0, "Eq"], "w" => [0, "Ev"], "x" => [0, "Ew"], "y" => [0, "Ex"], "z" => [0, "Ey"], "{" => [0, "Ez"], "|" => [82, "E"], "}" => [87, "E"], "~" => [130, "E"], "" => [9, "E"], "\x80" => [94, "F0"], "\x81" => [76, "F0"], "\x82" => [104, "F0"], "\x83" => [16, "F0"], "\x84" => [94, "F1"], "\x85" => [76, "F1"], "\x86" => [104, "F1"], "\x87" => [16, "F1"], "\x88" => [94, "F2"], "\x89" => [76, "F2"], "\x8a" => [104, "F2"], "\x8b" => [16, "F2"], "\x8c" => [94, "Fa"], "\x8d" => [76, "Fa"], "\x8e" => [104, "Fa"], "\x8f" => [16, "Fa"], "\x90" => [94, "Fc"], "\x91" => [76, "Fc"], "\x92" => [104, "Fc"], "\x93" => [16, "Fc"], "\x94" => [94, "Fe"], "\x95" => [76, "Fe"], "\x96" => [104, "Fe"], "\x97" => [16, "Fe"], "\x98" => [94, "Fi"], "\x99" => [76, "Fi"], "\x9a" => [104, "Fi"], "\x9b" => [16, "Fi"], "\x9c" => [94, "Fo"], "\x9d" => [76, "Fo"], "\x9e" => [104, "Fo"], "\x9f" => [16, "Fo"], "\xa0" => [94, "Fs"], "\xa1" => [76, "Fs"], "\xa2" => [104, "Fs"], "\xa3" => [16, "Fs"], "\xa4" => [94, "Ft"], "\xa5" => [76, "Ft"], "\xa6" => [104, "Ft"], "\xa7" => [16, "Ft"], "\xa8" => [77, "F "], "\xa9" => [18, "F "], "\xaa" => [77, "F%"], "\xab" => [18, "F%"], "\xac" => [77, "F-"], "\xad" => [18, "F-"], "\xae" => [77, "F."], "\xaf" => [18, "F."], "\xb0" => [77, "F/"], "\xb1" => [18, "F/"], "\xb2" => [77, "F3"], "\xb3" => [18, "F3"], "\xb4" => [77, "F4"], "\xb5" => [18, "F4"], "\xb6" => [77, "F5"], "\xb7" => [18, "F5"], "\xb8" => [77, "F6"], "\xb9" => [18, "F6"], "\xba" => [77, "F7"], "\xbb" => [18, "F7"], "\xbc" => [77, "F8"], "\xbd" => [18, "F8"], "\xbe" => [77, "F9"], "\xbf" => [18, "F9"], "\xc0" => [77, "F="], "\xc1" => [18, "F="], "\xc2" => [77, "FA"], "\xc3" => [18, "FA"], "\xc4" => [77, "F_"], "\xc5" => [18, "F_"], "\xc6" => [77, "Fb"], "\xc7" => [18, "Fb"], "\xc8" => [77, "Fd"], "\xc9" => [18, "Fd"], "\xca" => [77, "Ff"], "\xcb" => [18, "Ff"], "\xcc" => [77, "Fg"], "\xcd" => [18, "Fg"], "\xce" => [77, "Fh"], "\xcf" => [18, "Fh"], "\xd0" => [77, "Fl"], "\xd1" => [18, "Fl"], "\xd2" => [77, "Fm"], "\xd3" => [18, "Fm"], "\xd4" => [77, "Fn"], "\xd5" => [18, "Fn"], "\xd6" => [77, "Fp"], "\xd7" => [18, "Fp"], "\xd8" => [77, "Fr"], "\xd9" => [18, "Fr"], "\xda" => [77, "Fu"], "\xdb" => [18, "Fu"], "\xdc" => [0, "F:"], "\xdd" => [0, "FB"], "\xde" => [0, "FC"], "\xdf" => [0, "FD"], "\xe0" => [0, "FE"], "\xe1" => [0, "FF"], "\xe2" => [0, "FG"], "\xe3" => [0, "FH"], "\xe4" => [0, "FI"], "\xe5" => [0, "FJ"], "\xe6" => [0, "FK"], "\xe7" => [0, "FL"], "\xe8" => [0, "FM"], "\xe9" => [0, "FN"], "\xea" => [0, "FO"], "\xeb" => [0, "FP"], "\xec" => [0, "FQ"], "\xed" => [0, "FR"], "\xee" => [0, "FS"], "\xef" => [0, "FT"], "\xf0" => [0, "FU"], "\xf1" => [0, "FV"], "\xf2" => [0, "FW"], "\xf3" => [0, "FY"], "\xf4" => [0, "Fj"], "\xf5" => [0, "Fk"], "\xf6" => [0, "Fq"], "\xf7" => [0, "Fv"], "\xf8" => [0, "Fw"], "\xf9" => [0, "Fx"], "\xfa" => [0, "Fy"], "\xfb" => [0, "Fz"], "\xfc" => [82, "F"], "\xfd" => [87, "F"], "\xfe" => [130, "F"], "\xff" => [9, "F"]], ["\x00" => [77, "E0"], "\x01" => [18, "E0"], "\x02" => [77, "E1"], "\x03" => [18, "E1"], "\x04" => [77, "E2"], "\x05" => [18, "E2"], "\x06" => [77, "Ea"], "\x07" => [18, "Ea"], "\x08" => [77, "Ec"], "\t" => [18, "Ec"], "\n" => [77, "Ee"], "\v" => [18, "Ee"], "\f" => [77, "Ei"], "\r" => [18, "Ei"], "\x0e" => [77, "Eo"], "\x0f" => [18, "Eo"], "\x10" => [77, "Es"], "\x11" => [18, "Es"], "\x12" => [77, "Et"], "\x13" => [18, "Et"], "\x14" => [0, "E "], "\x15" => [0, "E%"], "\x16" => [0, "E-"], "\x17" => [0, "E."], "\x18" => [0, "E/"], "\x19" => [0, "E3"], "\x1a" => [0, "E4"], "\x1b" => [0, "E5"], "\x1c" => [0, "E6"], "\x1d" => [0, "E7"], "\x1e" => [0, "E8"], "\x1f" => [0, "E9"], " " => [0, "E="], "!" => [0, "EA"], "\"" => [0, "E_"], "#" => [0, "Eb"], "\$" => [0, "Ed"], "%" => [0, "Ef"], "&" => [0, "Eg"], "'" => [0, "Eh"], "(" => [0, "El"], ")" => [0, "Em"], "*" => [0, "En"], "+" => [0, "Ep"], "," => [0, "Er"], "-" => [0, "Eu"], "." => [100, "E"], "/" => [110, "E"], [111, "E"], [115, "E"], [116, "E"], [118, "E"], [119, "E"], [122, "E"], [123, "E"], [125, "E"], [126, "E"], [129, "E"], ":" => [143, "E"], ";" => [148, "E"], "<" => [151, "E"], "=" => [153, "E"], ">" => [83, "E"], "?" => [10, "E"], "@" => [77, "F0"], "A" => [18, "F0"], "B" => [77, "F1"], "C" => [18, "F1"], "D" => [77, "F2"], "E" => [18, "F2"], "F" => [77, "Fa"], "G" => [18, "Fa"], "H" => [77, "Fc"], "I" => [18, "Fc"], "J" => [77, "Fe"], "K" => [18, "Fe"], "L" => [77, "Fi"], "M" => [18, "Fi"], "N" => [77, "Fo"], "O" => [18, "Fo"], "P" => [77, "Fs"], "Q" => [18, "Fs"], "R" => [77, "Ft"], "S" => [18, "Ft"], "T" => [0, "F "], "U" => [0, "F%"], "V" => [0, "F-"], "W" => [0, "F."], "X" => [0, "F/"], "Y" => [0, "F3"], "Z" => [0, "F4"], "[" => [0, "F5"], "\\" => [0, "F6"], "]" => [0, "F7"], "^" => [0, "F8"], "_" => [0, "F9"], "`" => [0, "F="], "a" => [0, "FA"], "b" => [0, "F_"], "c" => [0, "Fb"], "d" => [0, "Fd"], "e" => [0, "Ff"], "f" => [0, "Fg"], "g" => [0, "Fh"], "h" => [0, "Fl"], "i" => [0, "Fm"], "j" => [0, "Fn"], "k" => [0, "Fp"], "l" => [0, "Fr"], "m" => [0, "Fu"], "n" => [100, "F"], "o" => [110, "F"], "p" => [111, "F"], "q" => [115, "F"], "r" => [116, "F"], "s" => [118, "F"], "t" => [119, "F"], "u" => [122, "F"], "v" => [123, "F"], "w" => [125, "F"], "x" => [126, "F"], "y" => [129, "F"], "z" => [143, "F"], "{" => [148, "F"], "|" => [151, "F"], "}" => [153, "F"], "~" => [83, "F"], "" => [10, "F"], "\x80" => [77, "G0"], "\x81" => [18, "G0"], "\x82" => [77, "G1"], "\x83" => [18, "G1"], "\x84" => [77, "G2"], "\x85" => [18, "G2"], "\x86" => [77, "Ga"], "\x87" => [18, "Ga"], "\x88" => [77, "Gc"], "\x89" => [18, "Gc"], "\x8a" => [77, "Ge"], "\x8b" => [18, "Ge"], "\x8c" => [77, "Gi"], "\x8d" => [18, "Gi"], "\x8e" => [77, "Go"], "\x8f" => [18, "Go"], "\x90" => [77, "Gs"], "\x91" => [18, "Gs"], "\x92" => [77, "Gt"], "\x93" => [18, "Gt"], "\x94" => [0, "G "], "\x95" => [0, "G%"], "\x96" => [0, "G-"], "\x97" => [0, "G."], "\x98" => [0, "G/"], "\x99" => [0, "G3"], "\x9a" => [0, "G4"], "\x9b" => [0, "G5"], "\x9c" => [0, "G6"], "\x9d" => [0, "G7"], "\x9e" => [0, "G8"], "\x9f" => [0, "G9"], "\xa0" => [0, "G="], "\xa1" => [0, "GA"], "\xa2" => [0, "G_"], "\xa3" => [0, "Gb"], "\xa4" => [0, "Gd"], "\xa5" => [0, "Gf"], "\xa6" => [0, "Gg"], "\xa7" => [0, "Gh"], "\xa8" => [0, "Gl"], "\xa9" => [0, "Gm"], "\xaa" => [0, "Gn"], "\xab" => [0, "Gp"], "\xac" => [0, "Gr"], "\xad" => [0, "Gu"], "\xae" => [100, "G"], "\xaf" => [110, "G"], "\xb0" => [111, "G"], "\xb1" => [115, "G"], "\xb2" => [116, "G"], "\xb3" => [118, "G"], "\xb4" => [119, "G"], "\xb5" => [122, "G"], "\xb6" => [123, "G"], "\xb7" => [125, "G"], "\xb8" => [126, "G"], "\xb9" => [129, "G"], "\xba" => [143, "G"], "\xbb" => [148, "G"], "\xbc" => [151, "G"], "\xbd" => [153, "G"], "\xbe" => [83, "G"], "\xbf" => [10, "G"], "\xc0" => [77, "H0"], "\xc1" => [18, "H0"], "\xc2" => [77, "H1"], "\xc3" => [18, "H1"], "\xc4" => [77, "H2"], "\xc5" => [18, "H2"], "\xc6" => [77, "Ha"], "\xc7" => [18, "Ha"], "\xc8" => [77, "Hc"], "\xc9" => [18, "Hc"], "\xca" => [77, "He"], "\xcb" => [18, "He"], "\xcc" => [77, "Hi"], "\xcd" => [18, "Hi"], "\xce" => [77, "Ho"], "\xcf" => [18, "Ho"], "\xd0" => [77, "Hs"], "\xd1" => [18, "Hs"], "\xd2" => [77, "Ht"], "\xd3" => [18, "Ht"], "\xd4" => [0, "H "], "\xd5" => [0, "H%"], "\xd6" => [0, "H-"], "\xd7" => [0, "H."], "\xd8" => [0, "H/"], "\xd9" => [0, "H3"], "\xda" => [0, "H4"], "\xdb" => [0, "H5"], "\xdc" => [0, "H6"], "\xdd" => [0, "H7"], "\xde" => [0, "H8"], "\xdf" => [0, "H9"], "\xe0" => [0, "H="], "\xe1" => [0, "HA"], "\xe2" => [0, "H_"], "\xe3" => [0, "Hb"], "\xe4" => [0, "Hd"], "\xe5" => [0, "Hf"], "\xe6" => [0, "Hg"], "\xe7" => [0, "Hh"], "\xe8" => [0, "Hl"], "\xe9" => [0, "Hm"], "\xea" => [0, "Hn"], "\xeb" => [0, "Hp"], "\xec" => [0, "Hr"], "\xed" => [0, "Hu"], "\xee" => [100, "H"], "\xef" => [110, "H"], "\xf0" => [111, "H"], "\xf1" => [115, "H"], "\xf2" => [116, "H"], "\xf3" => [118, "H"], "\xf4" => [119, "H"], "\xf5" => [122, "H"], "\xf6" => [123, "H"], "\xf7" => [125, "H"], "\xf8" => [126, "H"], "\xf9" => [129, "H"], "\xfa" => [143, "H"], "\xfb" => [148, "H"], "\xfc" => [151, "H"], "\xfd" => [153, "H"], "\xfe" => [83, "H"], "\xff" => [10, "H"]], ["\x00" => [0, "E0"], "\x01" => [0, "E1"], "\x02" => [0, "E2"], "\x03" => [0, "Ea"], "\x04" => [0, "Ec"], "\x05" => [0, "Ee"], "\x06" => [0, "Ei"], "\x07" => [0, "Eo"], "\x08" => [0, "Es"], "\t" => [0, "Et"], "\n" => [73, "E"], "\v" => [88, "E"], "\f" => [89, "E"], "\r" => [96, "E"], "\x0e" => [97, "E"], "\x0f" => [99, "E"], "\x10" => [106, "E"], "\x11" => [136, "E"], "\x12" => [139, "E"], "\x13" => [141, "E"], "\x14" => [145, "E"], "\x15" => [147, "E"], "\x16" => [149, "E"], "\x17" => [101, "E"], "\x18" => [112, "E"], "\x19" => [117, "E"], "\x1a" => [120, "E"], "\x1b" => [124, "E"], "\x1c" => [127, "E"], "\x1d" => [144, "E"], "\x1e" => [152, "E"], "\x1f" => [11, "E"], " " => [0, "F0"], "!" => [0, "F1"], "\"" => [0, "F2"], "#" => [0, "Fa"], "\$" => [0, "Fc"], "%" => [0, "Fe"], "&" => [0, "Fi"], "'" => [0, "Fo"], "(" => [0, "Fs"], ")" => [0, "Ft"], "*" => [73, "F"], "+" => [88, "F"], "," => [89, "F"], "-" => [96, "F"], "." => [97, "F"], "/" => [99, "F"], [106, "F"], [136, "F"], [139, "F"], [141, "F"], [145, "F"], [147, "F"], [149, "F"], [101, "F"], [112, "F"], [117, "F"], ":" => [120, "F"], ";" => [124, "F"], "<" => [127, "F"], "=" => [144, "F"], ">" => [152, "F"], "?" => [11, "F"], "@" => [0, "G0"], "A" => [0, "G1"], "B" => [0, "G2"], "C" => [0, "Ga"], "D" => [0, "Gc"], "E" => [0, "Ge"], "F" => [0, "Gi"], "G" => [0, "Go"], "H" => [0, "Gs"], "I" => [0, "Gt"], "J" => [73, "G"], "K" => [88, "G"], "L" => [89, "G"], "M" => [96, "G"], "N" => [97, "G"], "O" => [99, "G"], "P" => [106, "G"], "Q" => [136, "G"], "R" => [139, "G"], "S" => [141, "G"], "T" => [145, "G"], "U" => [147, "G"], "V" => [149, "G"], "W" => [101, "G"], "X" => [112, "G"], "Y" => [117, "G"], "Z" => [120, "G"], "[" => [124, "G"], "\\" => [127, "G"], "]" => [144, "G"], "^" => [152, "G"], "_" => [11, "G"], "`" => [0, "H0"], "a" => [0, "H1"], "b" => [0, "H2"], "c" => [0, "Ha"], "d" => [0, "Hc"], "e" => [0, "He"], "f" => [0, "Hi"], "g" => [0, "Ho"], "h" => [0, "Hs"], "i" => [0, "Ht"], "j" => [73, "H"], "k" => [88, "H"], "l" => [89, "H"], "m" => [96, "H"], "n" => [97, "H"], "o" => [99, "H"], "p" => [106, "H"], "q" => [136, "H"], "r" => [139, "H"], "s" => [141, "H"], "t" => [145, "H"], "u" => [147, "H"], "v" => [149, "H"], "w" => [101, "H"], "x" => [112, "H"], "y" => [117, "H"], "z" => [120, "H"], "{" => [124, "H"], "|" => [127, "H"], "}" => [144, "H"], "~" => [152, "H"], "" => [11, "H"], "\x80" => [0, "I0"], "\x81" => [0, "I1"], "\x82" => [0, "I2"], "\x83" => [0, "Ia"], "\x84" => [0, "Ic"], "\x85" => [0, "Ie"], "\x86" => [0, "Ii"], "\x87" => [0, "Io"], "\x88" => [0, "Is"], "\x89" => [0, "It"], "\x8a" => [73, "I"], "\x8b" => [88, "I"], "\x8c" => [89, "I"], "\x8d" => [96, "I"], "\x8e" => [97, "I"], "\x8f" => [99, "I"], "\x90" => [106, "I"], "\x91" => [136, "I"], "\x92" => [139, "I"], "\x93" => [141, "I"], "\x94" => [145, "I"], "\x95" => [147, "I"], "\x96" => [149, "I"], "\x97" => [101, "I"], "\x98" => [112, "I"], "\x99" => [117, "I"], "\x9a" => [120, "I"], "\x9b" => [124, "I"], "\x9c" => [127, "I"], "\x9d" => [144, "I"], "\x9e" => [152, "I"], "\x9f" => [11, "I"], "\xa0" => [0, "J0"], "\xa1" => [0, "J1"], "\xa2" => [0, "J2"], "\xa3" => [0, "Ja"], "\xa4" => [0, "Jc"], "\xa5" => [0, "Je"], "\xa6" => [0, "Ji"], "\xa7" => [0, "Jo"], "\xa8" => [0, "Js"], "\xa9" => [0, "Jt"], "\xaa" => [73, "J"], "\xab" => [88, "J"], "\xac" => [89, "J"], "\xad" => [96, "J"], "\xae" => [97, "J"], "\xaf" => [99, "J"], "\xb0" => [106, "J"], "\xb1" => [136, "J"], "\xb2" => [139, "J"], "\xb3" => [141, "J"], "\xb4" => [145, "J"], "\xb5" => [147, "J"], "\xb6" => [149, "J"], "\xb7" => [101, "J"], "\xb8" => [112, "J"], "\xb9" => [117, "J"], "\xba" => [120, "J"], "\xbb" => [124, "J"], "\xbc" => [127, "J"], "\xbd" => [144, "J"], "\xbe" => [152, "J"], "\xbf" => [11, "J"], "\xc0" => [0, "K0"], "\xc1" => [0, "K1"], "\xc2" => [0, "K2"], "\xc3" => [0, "Ka"], "\xc4" => [0, "Kc"], "\xc5" => [0, "Ke"], "\xc6" => [0, "Ki"], "\xc7" => [0, "Ko"], "\xc8" => [0, "Ks"], "\xc9" => [0, "Kt"], "\xca" => [73, "K"], "\xcb" => [88, "K"], "\xcc" => [89, "K"], "\xcd" => [96, "K"], "\xce" => [97, "K"], "\xcf" => [99, "K"], "\xd0" => [106, "K"], "\xd1" => [136, "K"], "\xd2" => [139, "K"], "\xd3" => [141, "K"], "\xd4" => [145, "K"], "\xd5" => [147, "K"], "\xd6" => [149, "K"], "\xd7" => [101, "K"], "\xd8" => [112, "K"], "\xd9" => [117, "K"], "\xda" => [120, "K"], "\xdb" => [124, "K"], "\xdc" => [127, "K"], "\xdd" => [144, "K"], "\xde" => [152, "K"], "\xdf" => [11, "K"], "\xe0" => [0, "L0"], "\xe1" => [0, "L1"], "\xe2" => [0, "L2"], "\xe3" => [0, "La"], "\xe4" => [0, "Lc"], "\xe5" => [0, "Le"], "\xe6" => [0, "Li"], "\xe7" => [0, "Lo"], "\xe8" => [0, "Ls"], "\xe9" => [0, "Lt"], "\xea" => [73, "L"], "\xeb" => [88, "L"], "\xec" => [89, "L"], "\xed" => [96, "L"], "\xee" => [97, "L"], "\xef" => [99, "L"], "\xf0" => [106, "L"], "\xf1" => [136, "L"], "\xf2" => [139, "L"], "\xf3" => [141, "L"], "\xf4" => [145, "L"], "\xf5" => [147, "L"], "\xf6" => [149, "L"], "\xf7" => [101, "L"], "\xf8" => [112, "L"], "\xf9" => [117, "L"], "\xfa" => [120, "L"], "\xfb" => [124, "L"], "\xfc" => [127, "L"], "\xfd" => [144, "L"], "\xfe" => [152, "L"], "\xff" => [11, "L"]], ["\x00" => [92, "E"], "\x01" => [95, "E"], "\x02" => [137, "E"], "\x03" => [142, "E"], "\x04" => [150, "E"], "\x05" => [74, "E"], "\x06" => [90, "E"], "\x07" => [98, "E"], "\x08" => [107, "E"], "\t" => [140, "E"], "\n" => [146, "E"], "\v" => [102, "E"], "\f" => [113, "E"], "\r" => [121, "E"], "\x0e" => [128, "E"], "\x0f" => [12, "E"], "\x10" => [92, "F"], "\x11" => [95, "F"], "\x12" => [137, "F"], "\x13" => [142, "F"], "\x14" => [150, "F"], "\x15" => [74, "F"], "\x16" => [90, "F"], "\x17" => [98, "F"], "\x18" => [107, "F"], "\x19" => [140, "F"], "\x1a" => [146, "F"], "\x1b" => [102, "F"], "\x1c" => [113, "F"], "\x1d" => [121, "F"], "\x1e" => [128, "F"], "\x1f" => [12, "F"], " " => [92, "G"], "!" => [95, "G"], "\"" => [137, "G"], "#" => [142, "G"], "\$" => [150, "G"], "%" => [74, "G"], "&" => [90, "G"], "'" => [98, "G"], "(" => [107, "G"], ")" => [140, "G"], "*" => [146, "G"], "+" => [102, "G"], "," => [113, "G"], "-" => [121, "G"], "." => [128, "G"], "/" => [12, "G"], [92, "H"], [95, "H"], [137, "H"], [142, "H"], [150, "H"], [74, "H"], [90, "H"], [98, "H"], [107, "H"], [140, "H"], ":" => [146, "H"], ";" => [102, "H"], "<" => [113, "H"], "=" => [121, "H"], ">" => [128, "H"], "?" => [12, "H"], "@" => [92, "I"], "A" => [95, "I"], "B" => [137, "I"], "C" => [142, "I"], "D" => [150, "I"], "E" => [74, "I"], "F" => [90, "I"], "G" => [98, "I"], "H" => [107, "I"], "I" => [140, "I"], "J" => [146, "I"], "K" => [102, "I"], "L" => [113, "I"], "M" => [121, "I"], "N" => [128, "I"], "O" => [12, "I"], "P" => [92, "J"], "Q" => [95, "J"], "R" => [137, "J"], "S" => [142, "J"], "T" => [150, "J"], "U" => [74, "J"], "V" => [90, "J"], "W" => [98, "J"], "X" => [107, "J"], "Y" => [140, "J"], "Z" => [146, "J"], "[" => [102, "J"], "\\" => [113, "J"], "]" => [121, "J"], "^" => [128, "J"], "_" => [12, "J"], "`" => [92, "K"], "a" => [95, "K"], "b" => [137, "K"], "c" => [142, "K"], "d" => [150, "K"], "e" => [74, "K"], "f" => [90, "K"], "g" => [98, "K"], "h" => [107, "K"], "i" => [140, "K"], "j" => [146, "K"], "k" => [102, "K"], "l" => [113, "K"], "m" => [121, "K"], "n" => [128, "K"], "o" => [12, "K"], "p" => [92, "L"], "q" => [95, "L"], "r" => [137, "L"], "s" => [142, "L"], "t" => [150, "L"], "u" => [74, "L"], "v" => [90, "L"], "w" => [98, "L"], "x" => [107, "L"], "y" => [140, "L"], "z" => [146, "L"], "{" => [102, "L"], "|" => [113, "L"], "}" => [121, "L"], "~" => [128, "L"], "" => [12, "L"], "\x80" => [92, "M"], "\x81" => [95, "M"], "\x82" => [137, "M"], "\x83" => [142, "M"], "\x84" => [150, "M"], "\x85" => [74, "M"], "\x86" => [90, "M"], "\x87" => [98, "M"], "\x88" => [107, "M"], "\x89" => [140, "M"], "\x8a" => [146, "M"], "\x8b" => [102, "M"], "\x8c" => [113, "M"], "\x8d" => [121, "M"], "\x8e" => [128, "M"], "\x8f" => [12, "M"], "\x90" => [92, "N"], "\x91" => [95, "N"], "\x92" => [137, "N"], "\x93" => [142, "N"], "\x94" => [150, "N"], "\x95" => [74, "N"], "\x96" => [90, "N"], "\x97" => [98, "N"], "\x98" => [107, "N"], "\x99" => [140, "N"], "\x9a" => [146, "N"], "\x9b" => [102, "N"], "\x9c" => [113, "N"], "\x9d" => [121, "N"], "\x9e" => [128, "N"], "\x9f" => [12, "N"], "\xa0" => [92, "O"], "\xa1" => [95, "O"], "\xa2" => [137, "O"], "\xa3" => [142, "O"], "\xa4" => [150, "O"], "\xa5" => [74, "O"], "\xa6" => [90, "O"], "\xa7" => [98, "O"], "\xa8" => [107, "O"], "\xa9" => [140, "O"], "\xaa" => [146, "O"], "\xab" => [102, "O"], "\xac" => [113, "O"], "\xad" => [121, "O"], "\xae" => [128, "O"], "\xaf" => [12, "O"], "\xb0" => [92, "P"], "\xb1" => [95, "P"], "\xb2" => [137, "P"], "\xb3" => [142, "P"], "\xb4" => [150, "P"], "\xb5" => [74, "P"], "\xb6" => [90, "P"], "\xb7" => [98, "P"], "\xb8" => [107, "P"], "\xb9" => [140, "P"], "\xba" => [146, "P"], "\xbb" => [102, "P"], "\xbc" => [113, "P"], "\xbd" => [121, "P"], "\xbe" => [128, "P"], "\xbf" => [12, "P"], "\xc0" => [92, "Q"], "\xc1" => [95, "Q"], "\xc2" => [137, "Q"], "\xc3" => [142, "Q"], "\xc4" => [150, "Q"], "\xc5" => [74, "Q"], "\xc6" => [90, "Q"], "\xc7" => [98, "Q"], "\xc8" => [107, "Q"], "\xc9" => [140, "Q"], "\xca" => [146, "Q"], "\xcb" => [102, "Q"], "\xcc" => [113, "Q"], "\xcd" => [121, "Q"], "\xce" => [128, "Q"], "\xcf" => [12, "Q"], "\xd0" => [92, "R"], "\xd1" => [95, "R"], "\xd2" => [137, "R"], "\xd3" => [142, "R"], "\xd4" => [150, "R"], "\xd5" => [74, "R"], "\xd6" => [90, "R"], "\xd7" => [98, "R"], "\xd8" => [107, "R"], "\xd9" => [140, "R"], "\xda" => [146, "R"], "\xdb" => [102, "R"], "\xdc" => [113, "R"], "\xdd" => [121, "R"], "\xde" => [128, "R"], "\xdf" => [12, "R"], "\xe0" => [92, "S"], "\xe1" => [95, "S"], "\xe2" => [137, "S"], "\xe3" => [142, "S"], "\xe4" => [150, "S"], "\xe5" => [74, "S"], "\xe6" => [90, "S"], "\xe7" => [98, "S"], "\xe8" => [107, "S"], "\xe9" => [140, "S"], "\xea" => [146, "S"], "\xeb" => [102, "S"], "\xec" => [113, "S"], "\xed" => [121, "S"], "\xee" => [128, "S"], "\xef" => [12, "S"], "\xf0" => [92, "T"], "\xf1" => [95, "T"], "\xf2" => [137, "T"], "\xf3" => [142, "T"], "\xf4" => [150, "T"], "\xf5" => [74, "T"], "\xf6" => [90, "T"], "\xf7" => [98, "T"], "\xf8" => [107, "T"], "\xf9" => [140, "T"], "\xfa" => [146, "T"], "\xfb" => [102, "T"], "\xfc" => [113, "T"], "\xfd" => [121, "T"], "\xfe" => [128, "T"], "\xff" => [12, "T"]], ["\x00" => [94, "G0"], "\x01" => [76, "G0"], "\x02" => [104, "G0"], "\x03" => [16, "G0"], "\x04" => [94, "G1"], "\x05" => [76, "G1"], "\x06" => [104, "G1"], "\x07" => [16, "G1"], "\x08" => [94, "G2"], "\t" => [76, "G2"], "\n" => [104, "G2"], "\v" => [16, "G2"], "\f" => [94, "Ga"], "\r" => [76, "Ga"], "\x0e" => [104, "Ga"], "\x0f" => [16, "Ga"], "\x10" => [94, "Gc"], "\x11" => [76, "Gc"], "\x12" => [104, "Gc"], "\x13" => [16, "Gc"], "\x14" => [94, "Ge"], "\x15" => [76, "Ge"], "\x16" => [104, "Ge"], "\x17" => [16, "Ge"], "\x18" => [94, "Gi"], "\x19" => [76, "Gi"], "\x1a" => [104, "Gi"], "\x1b" => [16, "Gi"], "\x1c" => [94, "Go"], "\x1d" => [76, "Go"], "\x1e" => [104, "Go"], "\x1f" => [16, "Go"], " " => [94, "Gs"], "!" => [76, "Gs"], "\"" => [104, "Gs"], "#" => [16, "Gs"], "\$" => [94, "Gt"], "%" => [76, "Gt"], "&" => [104, "Gt"], "'" => [16, "Gt"], "(" => [77, "G "], ")" => [18, "G "], "*" => [77, "G%"], "+" => [18, "G%"], "," => [77, "G-"], "-" => [18, "G-"], "." => [77, "G."], "/" => [18, "G."], [77, "G/"], [18, "G/"], [77, "G3"], [18, "G3"], [77, "G4"], [18, "G4"], [77, "G5"], [18, "G5"], [77, "G6"], [18, "G6"], ":" => [77, "G7"], ";" => [18, "G7"], "<" => [77, "G8"], "=" => [18, "G8"], ">" => [77, "G9"], "?" => [18, "G9"], "@" => [77, "G="], "A" => [18, "G="], "B" => [77, "GA"], "C" => [18, "GA"], "D" => [77, "G_"], "E" => [18, "G_"], "F" => [77, "Gb"], "G" => [18, "Gb"], "H" => [77, "Gd"], "I" => [18, "Gd"], "J" => [77, "Gf"], "K" => [18, "Gf"], "L" => [77, "Gg"], "M" => [18, "Gg"], "N" => [77, "Gh"], "O" => [18, "Gh"], "P" => [77, "Gl"], "Q" => [18, "Gl"], "R" => [77, "Gm"], "S" => [18, "Gm"], "T" => [77, "Gn"], "U" => [18, "Gn"], "V" => [77, "Gp"], "W" => [18, "Gp"], "X" => [77, "Gr"], "Y" => [18, "Gr"], "Z" => [77, "Gu"], "[" => [18, "Gu"], "\\" => [0, "G:"], "]" => [0, "GB"], "^" => [0, "GC"], "_" => [0, "GD"], "`" => [0, "GE"], "a" => [0, "GF"], "b" => [0, "GG"], "c" => [0, "GH"], "d" => [0, "GI"], "e" => [0, "GJ"], "f" => [0, "GK"], "g" => [0, "GL"], "h" => [0, "GM"], "i" => [0, "GN"], "j" => [0, "GO"], "k" => [0, "GP"], "l" => [0, "GQ"], "m" => [0, "GR"], "n" => [0, "GS"], "o" => [0, "GT"], "p" => [0, "GU"], "q" => [0, "GV"], "r" => [0, "GW"], "s" => [0, "GY"], "t" => [0, "Gj"], "u" => [0, "Gk"], "v" => [0, "Gq"], "w" => [0, "Gv"], "x" => [0, "Gw"], "y" => [0, "Gx"], "z" => [0, "Gy"], "{" => [0, "Gz"], "|" => [82, "G"], "}" => [87, "G"], "~" => [130, "G"], "" => [9, "G"], "\x80" => [94, "H0"], "\x81" => [76, "H0"], "\x82" => [104, "H0"], "\x83" => [16, "H0"], "\x84" => [94, "H1"], "\x85" => [76, "H1"], "\x86" => [104, "H1"], "\x87" => [16, "H1"], "\x88" => [94, "H2"], "\x89" => [76, "H2"], "\x8a" => [104, "H2"], "\x8b" => [16, "H2"], "\x8c" => [94, "Ha"], "\x8d" => [76, "Ha"], "\x8e" => [104, "Ha"], "\x8f" => [16, "Ha"], "\x90" => [94, "Hc"], "\x91" => [76, "Hc"], "\x92" => [104, "Hc"], "\x93" => [16, "Hc"], "\x94" => [94, "He"], "\x95" => [76, "He"], "\x96" => [104, "He"], "\x97" => [16, "He"], "\x98" => [94, "Hi"], "\x99" => [76, "Hi"], "\x9a" => [104, "Hi"], "\x9b" => [16, "Hi"], "\x9c" => [94, "Ho"], "\x9d" => [76, "Ho"], "\x9e" => [104, "Ho"], "\x9f" => [16, "Ho"], "\xa0" => [94, "Hs"], "\xa1" => [76, "Hs"], "\xa2" => [104, "Hs"], "\xa3" => [16, "Hs"], "\xa4" => [94, "Ht"], "\xa5" => [76, "Ht"], "\xa6" => [104, "Ht"], "\xa7" => [16, "Ht"], "\xa8" => [77, "H "], "\xa9" => [18, "H "], "\xaa" => [77, "H%"], "\xab" => [18, "H%"], "\xac" => [77, "H-"], "\xad" => [18, "H-"], "\xae" => [77, "H."], "\xaf" => [18, "H."], "\xb0" => [77, "H/"], "\xb1" => [18, "H/"], "\xb2" => [77, "H3"], "\xb3" => [18, "H3"], "\xb4" => [77, "H4"], "\xb5" => [18, "H4"], "\xb6" => [77, "H5"], "\xb7" => [18, "H5"], "\xb8" => [77, "H6"], "\xb9" => [18, "H6"], "\xba" => [77, "H7"], "\xbb" => [18, "H7"], "\xbc" => [77, "H8"], "\xbd" => [18, "H8"], "\xbe" => [77, "H9"], "\xbf" => [18, "H9"], "\xc0" => [77, "H="], "\xc1" => [18, "H="], "\xc2" => [77, "HA"], "\xc3" => [18, "HA"], "\xc4" => [77, "H_"], "\xc5" => [18, "H_"], "\xc6" => [77, "Hb"], "\xc7" => [18, "Hb"], "\xc8" => [77, "Hd"], "\xc9" => [18, "Hd"], "\xca" => [77, "Hf"], "\xcb" => [18, "Hf"], "\xcc" => [77, "Hg"], "\xcd" => [18, "Hg"], "\xce" => [77, "Hh"], "\xcf" => [18, "Hh"], "\xd0" => [77, "Hl"], "\xd1" => [18, "Hl"], "\xd2" => [77, "Hm"], "\xd3" => [18, "Hm"], "\xd4" => [77, "Hn"], "\xd5" => [18, "Hn"], "\xd6" => [77, "Hp"], "\xd7" => [18, "Hp"], "\xd8" => [77, "Hr"], "\xd9" => [18, "Hr"], "\xda" => [77, "Hu"], "\xdb" => [18, "Hu"], "\xdc" => [0, "H:"], "\xdd" => [0, "HB"], "\xde" => [0, "HC"], "\xdf" => [0, "HD"], "\xe0" => [0, "HE"], "\xe1" => [0, "HF"], "\xe2" => [0, "HG"], "\xe3" => [0, "HH"], "\xe4" => [0, "HI"], "\xe5" => [0, "HJ"], "\xe6" => [0, "HK"], "\xe7" => [0, "HL"], "\xe8" => [0, "HM"], "\xe9" => [0, "HN"], "\xea" => [0, "HO"], "\xeb" => [0, "HP"], "\xec" => [0, "HQ"], "\xed" => [0, "HR"], "\xee" => [0, "HS"], "\xef" => [0, "HT"], "\xf0" => [0, "HU"], "\xf1" => [0, "HV"], "\xf2" => [0, "HW"], "\xf3" => [0, "HY"], "\xf4" => [0, "Hj"], "\xf5" => [0, "Hk"], "\xf6" => [0, "Hq"], "\xf7" => [0, "Hv"], "\xf8" => [0, "Hw"], "\xf9" => [0, "Hx"], "\xfa" => [0, "Hy"], "\xfb" => [0, "Hz"], "\xfc" => [82, "H"], "\xfd" => [87, "H"], "\xfe" => [130, "H"], "\xff" => [9, "H"]], ["\x00" => [94, "I0"], "\x01" => [76, "I0"], "\x02" => [104, "I0"], "\x03" => [16, "I0"], "\x04" => [94, "I1"], "\x05" => [76, "I1"], "\x06" => [104, "I1"], "\x07" => [16, "I1"], "\x08" => [94, "I2"], "\t" => [76, "I2"], "\n" => [104, "I2"], "\v" => [16, "I2"], "\f" => [94, "Ia"], "\r" => [76, "Ia"], "\x0e" => [104, "Ia"], "\x0f" => [16, "Ia"], "\x10" => [94, "Ic"], "\x11" => [76, "Ic"], "\x12" => [104, "Ic"], "\x13" => [16, "Ic"], "\x14" => [94, "Ie"], "\x15" => [76, "Ie"], "\x16" => [104, "Ie"], "\x17" => [16, "Ie"], "\x18" => [94, "Ii"], "\x19" => [76, "Ii"], "\x1a" => [104, "Ii"], "\x1b" => [16, "Ii"], "\x1c" => [94, "Io"], "\x1d" => [76, "Io"], "\x1e" => [104, "Io"], "\x1f" => [16, "Io"], " " => [94, "Is"], "!" => [76, "Is"], "\"" => [104, "Is"], "#" => [16, "Is"], "\$" => [94, "It"], "%" => [76, "It"], "&" => [104, "It"], "'" => [16, "It"], "(" => [77, "I "], ")" => [18, "I "], "*" => [77, "I%"], "+" => [18, "I%"], "," => [77, "I-"], "-" => [18, "I-"], "." => [77, "I."], "/" => [18, "I."], [77, "I/"], [18, "I/"], [77, "I3"], [18, "I3"], [77, "I4"], [18, "I4"], [77, "I5"], [18, "I5"], [77, "I6"], [18, "I6"], ":" => [77, "I7"], ";" => [18, "I7"], "<" => [77, "I8"], "=" => [18, "I8"], ">" => [77, "I9"], "?" => [18, "I9"], "@" => [77, "I="], "A" => [18, "I="], "B" => [77, "IA"], "C" => [18, "IA"], "D" => [77, "I_"], "E" => [18, "I_"], "F" => [77, "Ib"], "G" => [18, "Ib"], "H" => [77, "Id"], "I" => [18, "Id"], "J" => [77, "If"], "K" => [18, "If"], "L" => [77, "Ig"], "M" => [18, "Ig"], "N" => [77, "Ih"], "O" => [18, "Ih"], "P" => [77, "Il"], "Q" => [18, "Il"], "R" => [77, "Im"], "S" => [18, "Im"], "T" => [77, "In"], "U" => [18, "In"], "V" => [77, "Ip"], "W" => [18, "Ip"], "X" => [77, "Ir"], "Y" => [18, "Ir"], "Z" => [77, "Iu"], "[" => [18, "Iu"], "\\" => [0, "I:"], "]" => [0, "IB"], "^" => [0, "IC"], "_" => [0, "ID"], "`" => [0, "IE"], "a" => [0, "IF"], "b" => [0, "IG"], "c" => [0, "IH"], "d" => [0, "II"], "e" => [0, "IJ"], "f" => [0, "IK"], "g" => [0, "IL"], "h" => [0, "IM"], "i" => [0, "IN"], "j" => [0, "IO"], "k" => [0, "IP"], "l" => [0, "IQ"], "m" => [0, "IR"], "n" => [0, "IS"], "o" => [0, "IT"], "p" => [0, "IU"], "q" => [0, "IV"], "r" => [0, "IW"], "s" => [0, "IY"], "t" => [0, "Ij"], "u" => [0, "Ik"], "v" => [0, "Iq"], "w" => [0, "Iv"], "x" => [0, "Iw"], "y" => [0, "Ix"], "z" => [0, "Iy"], "{" => [0, "Iz"], "|" => [82, "I"], "}" => [87, "I"], "~" => [130, "I"], "" => [9, "I"], "\x80" => [94, "J0"], "\x81" => [76, "J0"], "\x82" => [104, "J0"], "\x83" => [16, "J0"], "\x84" => [94, "J1"], "\x85" => [76, "J1"], "\x86" => [104, "J1"], "\x87" => [16, "J1"], "\x88" => [94, "J2"], "\x89" => [76, "J2"], "\x8a" => [104, "J2"], "\x8b" => [16, "J2"], "\x8c" => [94, "Ja"], "\x8d" => [76, "Ja"], "\x8e" => [104, "Ja"], "\x8f" => [16, "Ja"], "\x90" => [94, "Jc"], "\x91" => [76, "Jc"], "\x92" => [104, "Jc"], "\x93" => [16, "Jc"], "\x94" => [94, "Je"], "\x95" => [76, "Je"], "\x96" => [104, "Je"], "\x97" => [16, "Je"], "\x98" => [94, "Ji"], "\x99" => [76, "Ji"], "\x9a" => [104, "Ji"], "\x9b" => [16, "Ji"], "\x9c" => [94, "Jo"], "\x9d" => [76, "Jo"], "\x9e" => [104, "Jo"], "\x9f" => [16, "Jo"], "\xa0" => [94, "Js"], "\xa1" => [76, "Js"], "\xa2" => [104, "Js"], "\xa3" => [16, "Js"], "\xa4" => [94, "Jt"], "\xa5" => [76, "Jt"], "\xa6" => [104, "Jt"], "\xa7" => [16, "Jt"], "\xa8" => [77, "J "], "\xa9" => [18, "J "], "\xaa" => [77, "J%"], "\xab" => [18, "J%"], "\xac" => [77, "J-"], "\xad" => [18, "J-"], "\xae" => [77, "J."], "\xaf" => [18, "J."], "\xb0" => [77, "J/"], "\xb1" => [18, "J/"], "\xb2" => [77, "J3"], "\xb3" => [18, "J3"], "\xb4" => [77, "J4"], "\xb5" => [18, "J4"], "\xb6" => [77, "J5"], "\xb7" => [18, "J5"], "\xb8" => [77, "J6"], "\xb9" => [18, "J6"], "\xba" => [77, "J7"], "\xbb" => [18, "J7"], "\xbc" => [77, "J8"], "\xbd" => [18, "J8"], "\xbe" => [77, "J9"], "\xbf" => [18, "J9"], "\xc0" => [77, "J="], "\xc1" => [18, "J="], "\xc2" => [77, "JA"], "\xc3" => [18, "JA"], "\xc4" => [77, "J_"], "\xc5" => [18, "J_"], "\xc6" => [77, "Jb"], "\xc7" => [18, "Jb"], "\xc8" => [77, "Jd"], "\xc9" => [18, "Jd"], "\xca" => [77, "Jf"], "\xcb" => [18, "Jf"], "\xcc" => [77, "Jg"], "\xcd" => [18, "Jg"], "\xce" => [77, "Jh"], "\xcf" => [18, "Jh"], "\xd0" => [77, "Jl"], "\xd1" => [18, "Jl"], "\xd2" => [77, "Jm"], "\xd3" => [18, "Jm"], "\xd4" => [77, "Jn"], "\xd5" => [18, "Jn"], "\xd6" => [77, "Jp"], "\xd7" => [18, "Jp"], "\xd8" => [77, "Jr"], "\xd9" => [18, "Jr"], "\xda" => [77, "Ju"], "\xdb" => [18, "Ju"], "\xdc" => [0, "J:"], "\xdd" => [0, "JB"], "\xde" => [0, "JC"], "\xdf" => [0, "JD"], "\xe0" => [0, "JE"], "\xe1" => [0, "JF"], "\xe2" => [0, "JG"], "\xe3" => [0, "JH"], "\xe4" => [0, "JI"], "\xe5" => [0, "JJ"], "\xe6" => [0, "JK"], "\xe7" => [0, "JL"], "\xe8" => [0, "JM"], "\xe9" => [0, "JN"], "\xea" => [0, "JO"], "\xeb" => [0, "JP"], "\xec" => [0, "JQ"], "\xed" => [0, "JR"], "\xee" => [0, "JS"], "\xef" => [0, "JT"], "\xf0" => [0, "JU"], "\xf1" => [0, "JV"], "\xf2" => [0, "JW"], "\xf3" => [0, "JY"], "\xf4" => [0, "Jj"], "\xf5" => [0, "Jk"], "\xf6" => [0, "Jq"], "\xf7" => [0, "Jv"], "\xf8" => [0, "Jw"], "\xf9" => [0, "Jx"], "\xfa" => [0, "Jy"], "\xfb" => [0, "Jz"], "\xfc" => [82, "J"], "\xfd" => [87, "J"], "\xfe" => [130, "J"], "\xff" => [9, "J"]], ["\x00" => [77, "I0"], "\x01" => [18, "I0"], "\x02" => [77, "I1"], "\x03" => [18, "I1"], "\x04" => [77, "I2"], "\x05" => [18, "I2"], "\x06" => [77, "Ia"], "\x07" => [18, "Ia"], "\x08" => [77, "Ic"], "\t" => [18, "Ic"], "\n" => [77, "Ie"], "\v" => [18, "Ie"], "\f" => [77, "Ii"], "\r" => [18, "Ii"], "\x0e" => [77, "Io"], "\x0f" => [18, "Io"], "\x10" => [77, "Is"], "\x11" => [18, "Is"], "\x12" => [77, "It"], "\x13" => [18, "It"], "\x14" => [0, "I "], "\x15" => [0, "I%"], "\x16" => [0, "I-"], "\x17" => [0, "I."], "\x18" => [0, "I/"], "\x19" => [0, "I3"], "\x1a" => [0, "I4"], "\x1b" => [0, "I5"], "\x1c" => [0, "I6"], "\x1d" => [0, "I7"], "\x1e" => [0, "I8"], "\x1f" => [0, "I9"], " " => [0, "I="], "!" => [0, "IA"], "\"" => [0, "I_"], "#" => [0, "Ib"], "\$" => [0, "Id"], "%" => [0, "If"], "&" => [0, "Ig"], "'" => [0, "Ih"], "(" => [0, "Il"], ")" => [0, "Im"], "*" => [0, "In"], "+" => [0, "Ip"], "," => [0, "Ir"], "-" => [0, "Iu"], "." => [100, "I"], "/" => [110, "I"], [111, "I"], [115, "I"], [116, "I"], [118, "I"], [119, "I"], [122, "I"], [123, "I"], [125, "I"], [126, "I"], [129, "I"], ":" => [143, "I"], ";" => [148, "I"], "<" => [151, "I"], "=" => [153, "I"], ">" => [83, "I"], "?" => [10, "I"], "@" => [77, "J0"], "A" => [18, "J0"], "B" => [77, "J1"], "C" => [18, "J1"], "D" => [77, "J2"], "E" => [18, "J2"], "F" => [77, "Ja"], "G" => [18, "Ja"], "H" => [77, "Jc"], "I" => [18, "Jc"], "J" => [77, "Je"], "K" => [18, "Je"], "L" => [77, "Ji"], "M" => [18, "Ji"], "N" => [77, "Jo"], "O" => [18, "Jo"], "P" => [77, "Js"], "Q" => [18, "Js"], "R" => [77, "Jt"], "S" => [18, "Jt"], "T" => [0, "J "], "U" => [0, "J%"], "V" => [0, "J-"], "W" => [0, "J."], "X" => [0, "J/"], "Y" => [0, "J3"], "Z" => [0, "J4"], "[" => [0, "J5"], "\\" => [0, "J6"], "]" => [0, "J7"], "^" => [0, "J8"], "_" => [0, "J9"], "`" => [0, "J="], "a" => [0, "JA"], "b" => [0, "J_"], "c" => [0, "Jb"], "d" => [0, "Jd"], "e" => [0, "Jf"], "f" => [0, "Jg"], "g" => [0, "Jh"], "h" => [0, "Jl"], "i" => [0, "Jm"], "j" => [0, "Jn"], "k" => [0, "Jp"], "l" => [0, "Jr"], "m" => [0, "Ju"], "n" => [100, "J"], "o" => [110, "J"], "p" => [111, "J"], "q" => [115, "J"], "r" => [116, "J"], "s" => [118, "J"], "t" => [119, "J"], "u" => [122, "J"], "v" => [123, "J"], "w" => [125, "J"], "x" => [126, "J"], "y" => [129, "J"], "z" => [143, "J"], "{" => [148, "J"], "|" => [151, "J"], "}" => [153, "J"], "~" => [83, "J"], "" => [10, "J"], "\x80" => [77, "K0"], "\x81" => [18, "K0"], "\x82" => [77, "K1"], "\x83" => [18, "K1"], "\x84" => [77, "K2"], "\x85" => [18, "K2"], "\x86" => [77, "Ka"], "\x87" => [18, "Ka"], "\x88" => [77, "Kc"], "\x89" => [18, "Kc"], "\x8a" => [77, "Ke"], "\x8b" => [18, "Ke"], "\x8c" => [77, "Ki"], "\x8d" => [18, "Ki"], "\x8e" => [77, "Ko"], "\x8f" => [18, "Ko"], "\x90" => [77, "Ks"], "\x91" => [18, "Ks"], "\x92" => [77, "Kt"], "\x93" => [18, "Kt"], "\x94" => [0, "K "], "\x95" => [0, "K%"], "\x96" => [0, "K-"], "\x97" => [0, "K."], "\x98" => [0, "K/"], "\x99" => [0, "K3"], "\x9a" => [0, "K4"], "\x9b" => [0, "K5"], "\x9c" => [0, "K6"], "\x9d" => [0, "K7"], "\x9e" => [0, "K8"], "\x9f" => [0, "K9"], "\xa0" => [0, "K="], "\xa1" => [0, "KA"], "\xa2" => [0, "K_"], "\xa3" => [0, "Kb"], "\xa4" => [0, "Kd"], "\xa5" => [0, "Kf"], "\xa6" => [0, "Kg"], "\xa7" => [0, "Kh"], "\xa8" => [0, "Kl"], "\xa9" => [0, "Km"], "\xaa" => [0, "Kn"], "\xab" => [0, "Kp"], "\xac" => [0, "Kr"], "\xad" => [0, "Ku"], "\xae" => [100, "K"], "\xaf" => [110, "K"], "\xb0" => [111, "K"], "\xb1" => [115, "K"], "\xb2" => [116, "K"], "\xb3" => [118, "K"], "\xb4" => [119, "K"], "\xb5" => [122, "K"], "\xb6" => [123, "K"], "\xb7" => [125, "K"], "\xb8" => [126, "K"], "\xb9" => [129, "K"], "\xba" => [143, "K"], "\xbb" => [148, "K"], "\xbc" => [151, "K"], "\xbd" => [153, "K"], "\xbe" => [83, "K"], "\xbf" => [10, "K"], "\xc0" => [77, "L0"], "\xc1" => [18, "L0"], "\xc2" => [77, "L1"], "\xc3" => [18, "L1"], "\xc4" => [77, "L2"], "\xc5" => [18, "L2"], "\xc6" => [77, "La"], "\xc7" => [18, "La"], "\xc8" => [77, "Lc"], "\xc9" => [18, "Lc"], "\xca" => [77, "Le"], "\xcb" => [18, "Le"], "\xcc" => [77, "Li"], "\xcd" => [18, "Li"], "\xce" => [77, "Lo"], "\xcf" => [18, "Lo"], "\xd0" => [77, "Ls"], "\xd1" => [18, "Ls"], "\xd2" => [77, "Lt"], "\xd3" => [18, "Lt"], "\xd4" => [0, "L "], "\xd5" => [0, "L%"], "\xd6" => [0, "L-"], "\xd7" => [0, "L."], "\xd8" => [0, "L/"], "\xd9" => [0, "L3"], "\xda" => [0, "L4"], "\xdb" => [0, "L5"], "\xdc" => [0, "L6"], "\xdd" => [0, "L7"], "\xde" => [0, "L8"], "\xdf" => [0, "L9"], "\xe0" => [0, "L="], "\xe1" => [0, "LA"], "\xe2" => [0, "L_"], "\xe3" => [0, "Lb"], "\xe4" => [0, "Ld"], "\xe5" => [0, "Lf"], "\xe6" => [0, "Lg"], "\xe7" => [0, "Lh"], "\xe8" => [0, "Ll"], "\xe9" => [0, "Lm"], "\xea" => [0, "Ln"], "\xeb" => [0, "Lp"], "\xec" => [0, "Lr"], "\xed" => [0, "Lu"], "\xee" => [100, "L"], "\xef" => [110, "L"], "\xf0" => [111, "L"], "\xf1" => [115, "L"], "\xf2" => [116, "L"], "\xf3" => [118, "L"], "\xf4" => [119, "L"], "\xf5" => [122, "L"], "\xf6" => [123, "L"], "\xf7" => [125, "L"], "\xf8" => [126, "L"], "\xf9" => [129, "L"], "\xfa" => [143, "L"], "\xfb" => [148, "L"], "\xfc" => [151, "L"], "\xfd" => [153, "L"], "\xfe" => [83, "L"], "\xff" => [10, "L"]], ["\x00" => [94, "K0"], "\x01" => [76, "K0"], "\x02" => [104, "K0"], "\x03" => [16, "K0"], "\x04" => [94, "K1"], "\x05" => [76, "K1"], "\x06" => [104, "K1"], "\x07" => [16, "K1"], "\x08" => [94, "K2"], "\t" => [76, "K2"], "\n" => [104, "K2"], "\v" => [16, "K2"], "\f" => [94, "Ka"], "\r" => [76, "Ka"], "\x0e" => [104, "Ka"], "\x0f" => [16, "Ka"], "\x10" => [94, "Kc"], "\x11" => [76, "Kc"], "\x12" => [104, "Kc"], "\x13" => [16, "Kc"], "\x14" => [94, "Ke"], "\x15" => [76, "Ke"], "\x16" => [104, "Ke"], "\x17" => [16, "Ke"], "\x18" => [94, "Ki"], "\x19" => [76, "Ki"], "\x1a" => [104, "Ki"], "\x1b" => [16, "Ki"], "\x1c" => [94, "Ko"], "\x1d" => [76, "Ko"], "\x1e" => [104, "Ko"], "\x1f" => [16, "Ko"], " " => [94, "Ks"], "!" => [76, "Ks"], "\"" => [104, "Ks"], "#" => [16, "Ks"], "\$" => [94, "Kt"], "%" => [76, "Kt"], "&" => [104, "Kt"], "'" => [16, "Kt"], "(" => [77, "K "], ")" => [18, "K "], "*" => [77, "K%"], "+" => [18, "K%"], "," => [77, "K-"], "-" => [18, "K-"], "." => [77, "K."], "/" => [18, "K."], [77, "K/"], [18, "K/"], [77, "K3"], [18, "K3"], [77, "K4"], [18, "K4"], [77, "K5"], [18, "K5"], [77, "K6"], [18, "K6"], ":" => [77, "K7"], ";" => [18, "K7"], "<" => [77, "K8"], "=" => [18, "K8"], ">" => [77, "K9"], "?" => [18, "K9"], "@" => [77, "K="], "A" => [18, "K="], "B" => [77, "KA"], "C" => [18, "KA"], "D" => [77, "K_"], "E" => [18, "K_"], "F" => [77, "Kb"], "G" => [18, "Kb"], "H" => [77, "Kd"], "I" => [18, "Kd"], "J" => [77, "Kf"], "K" => [18, "Kf"], "L" => [77, "Kg"], "M" => [18, "Kg"], "N" => [77, "Kh"], "O" => [18, "Kh"], "P" => [77, "Kl"], "Q" => [18, "Kl"], "R" => [77, "Km"], "S" => [18, "Km"], "T" => [77, "Kn"], "U" => [18, "Kn"], "V" => [77, "Kp"], "W" => [18, "Kp"], "X" => [77, "Kr"], "Y" => [18, "Kr"], "Z" => [77, "Ku"], "[" => [18, "Ku"], "\\" => [0, "K:"], "]" => [0, "KB"], "^" => [0, "KC"], "_" => [0, "KD"], "`" => [0, "KE"], "a" => [0, "KF"], "b" => [0, "KG"], "c" => [0, "KH"], "d" => [0, "KI"], "e" => [0, "KJ"], "f" => [0, "KK"], "g" => [0, "KL"], "h" => [0, "KM"], "i" => [0, "KN"], "j" => [0, "KO"], "k" => [0, "KP"], "l" => [0, "KQ"], "m" => [0, "KR"], "n" => [0, "KS"], "o" => [0, "KT"], "p" => [0, "KU"], "q" => [0, "KV"], "r" => [0, "KW"], "s" => [0, "KY"], "t" => [0, "Kj"], "u" => [0, "Kk"], "v" => [0, "Kq"], "w" => [0, "Kv"], "x" => [0, "Kw"], "y" => [0, "Kx"], "z" => [0, "Ky"], "{" => [0, "Kz"], "|" => [82, "K"], "}" => [87, "K"], "~" => [130, "K"], "" => [9, "K"], "\x80" => [94, "L0"], "\x81" => [76, "L0"], "\x82" => [104, "L0"], "\x83" => [16, "L0"], "\x84" => [94, "L1"], "\x85" => [76, "L1"], "\x86" => [104, "L1"], "\x87" => [16, "L1"], "\x88" => [94, "L2"], "\x89" => [76, "L2"], "\x8a" => [104, "L2"], "\x8b" => [16, "L2"], "\x8c" => [94, "La"], "\x8d" => [76, "La"], "\x8e" => [104, "La"], "\x8f" => [16, "La"], "\x90" => [94, "Lc"], "\x91" => [76, "Lc"], "\x92" => [104, "Lc"], "\x93" => [16, "Lc"], "\x94" => [94, "Le"], "\x95" => [76, "Le"], "\x96" => [104, "Le"], "\x97" => [16, "Le"], "\x98" => [94, "Li"], "\x99" => [76, "Li"], "\x9a" => [104, "Li"], "\x9b" => [16, "Li"], "\x9c" => [94, "Lo"], "\x9d" => [76, "Lo"], "\x9e" => [104, "Lo"], "\x9f" => [16, "Lo"], "\xa0" => [94, "Ls"], "\xa1" => [76, "Ls"], "\xa2" => [104, "Ls"], "\xa3" => [16, "Ls"], "\xa4" => [94, "Lt"], "\xa5" => [76, "Lt"], "\xa6" => [104, "Lt"], "\xa7" => [16, "Lt"], "\xa8" => [77, "L "], "\xa9" => [18, "L "], "\xaa" => [77, "L%"], "\xab" => [18, "L%"], "\xac" => [77, "L-"], "\xad" => [18, "L-"], "\xae" => [77, "L."], "\xaf" => [18, "L."], "\xb0" => [77, "L/"], "\xb1" => [18, "L/"], "\xb2" => [77, "L3"], "\xb3" => [18, "L3"], "\xb4" => [77, "L4"], "\xb5" => [18, "L4"], "\xb6" => [77, "L5"], "\xb7" => [18, "L5"], "\xb8" => [77, "L6"], "\xb9" => [18, "L6"], "\xba" => [77, "L7"], "\xbb" => [18, "L7"], "\xbc" => [77, "L8"], "\xbd" => [18, "L8"], "\xbe" => [77, "L9"], "\xbf" => [18, "L9"], "\xc0" => [77, "L="], "\xc1" => [18, "L="], "\xc2" => [77, "LA"], "\xc3" => [18, "LA"], "\xc4" => [77, "L_"], "\xc5" => [18, "L_"], "\xc6" => [77, "Lb"], "\xc7" => [18, "Lb"], "\xc8" => [77, "Ld"], "\xc9" => [18, "Ld"], "\xca" => [77, "Lf"], "\xcb" => [18, "Lf"], "\xcc" => [77, "Lg"], "\xcd" => [18, "Lg"], "\xce" => [77, "Lh"], "\xcf" => [18, "Lh"], "\xd0" => [77, "Ll"], "\xd1" => [18, "Ll"], "\xd2" => [77, "Lm"], "\xd3" => [18, "Lm"], "\xd4" => [77, "Ln"], "\xd5" => [18, "Ln"], "\xd6" => [77, "Lp"], "\xd7" => [18, "Lp"], "\xd8" => [77, "Lr"], "\xd9" => [18, "Lr"], "\xda" => [77, "Lu"], "\xdb" => [18, "Lu"], "\xdc" => [0, "L:"], "\xdd" => [0, "LB"], "\xde" => [0, "LC"], "\xdf" => [0, "LD"], "\xe0" => [0, "LE"], "\xe1" => [0, "LF"], "\xe2" => [0, "LG"], "\xe3" => [0, "LH"], "\xe4" => [0, "LI"], "\xe5" => [0, "LJ"], "\xe6" => [0, "LK"], "\xe7" => [0, "LL"], "\xe8" => [0, "LM"], "\xe9" => [0, "LN"], "\xea" => [0, "LO"], "\xeb" => [0, "LP"], "\xec" => [0, "LQ"], "\xed" => [0, "LR"], "\xee" => [0, "LS"], "\xef" => [0, "LT"], "\xf0" => [0, "LU"], "\xf1" => [0, "LV"], "\xf2" => [0, "LW"], "\xf3" => [0, "LY"], "\xf4" => [0, "Lj"], "\xf5" => [0, "Lk"], "\xf6" => [0, "Lq"], "\xf7" => [0, "Lv"], "\xf8" => [0, "Lw"], "\xf9" => [0, "Lx"], "\xfa" => [0, "Ly"], "\xfb" => [0, "Lz"], "\xfc" => [82, "L"], "\xfd" => [87, "L"], "\xfe" => [130, "L"], "\xff" => [9, "L"]], ["\x00" => [94, "M0"], "\x01" => [76, "M0"], "\x02" => [104, "M0"], "\x03" => [16, "M0"], "\x04" => [94, "M1"], "\x05" => [76, "M1"], "\x06" => [104, "M1"], "\x07" => [16, "M1"], "\x08" => [94, "M2"], "\t" => [76, "M2"], "\n" => [104, "M2"], "\v" => [16, "M2"], "\f" => [94, "Ma"], "\r" => [76, "Ma"], "\x0e" => [104, "Ma"], "\x0f" => [16, "Ma"], "\x10" => [94, "Mc"], "\x11" => [76, "Mc"], "\x12" => [104, "Mc"], "\x13" => [16, "Mc"], "\x14" => [94, "Me"], "\x15" => [76, "Me"], "\x16" => [104, "Me"], "\x17" => [16, "Me"], "\x18" => [94, "Mi"], "\x19" => [76, "Mi"], "\x1a" => [104, "Mi"], "\x1b" => [16, "Mi"], "\x1c" => [94, "Mo"], "\x1d" => [76, "Mo"], "\x1e" => [104, "Mo"], "\x1f" => [16, "Mo"], " " => [94, "Ms"], "!" => [76, "Ms"], "\"" => [104, "Ms"], "#" => [16, "Ms"], "\$" => [94, "Mt"], "%" => [76, "Mt"], "&" => [104, "Mt"], "'" => [16, "Mt"], "(" => [77, "M "], ")" => [18, "M "], "*" => [77, "M%"], "+" => [18, "M%"], "," => [77, "M-"], "-" => [18, "M-"], "." => [77, "M."], "/" => [18, "M."], [77, "M/"], [18, "M/"], [77, "M3"], [18, "M3"], [77, "M4"], [18, "M4"], [77, "M5"], [18, "M5"], [77, "M6"], [18, "M6"], ":" => [77, "M7"], ";" => [18, "M7"], "<" => [77, "M8"], "=" => [18, "M8"], ">" => [77, "M9"], "?" => [18, "M9"], "@" => [77, "M="], "A" => [18, "M="], "B" => [77, "MA"], "C" => [18, "MA"], "D" => [77, "M_"], "E" => [18, "M_"], "F" => [77, "Mb"], "G" => [18, "Mb"], "H" => [77, "Md"], "I" => [18, "Md"], "J" => [77, "Mf"], "K" => [18, "Mf"], "L" => [77, "Mg"], "M" => [18, "Mg"], "N" => [77, "Mh"], "O" => [18, "Mh"], "P" => [77, "Ml"], "Q" => [18, "Ml"], "R" => [77, "Mm"], "S" => [18, "Mm"], "T" => [77, "Mn"], "U" => [18, "Mn"], "V" => [77, "Mp"], "W" => [18, "Mp"], "X" => [77, "Mr"], "Y" => [18, "Mr"], "Z" => [77, "Mu"], "[" => [18, "Mu"], "\\" => [0, "M:"], "]" => [0, "MB"], "^" => [0, "MC"], "_" => [0, "MD"], "`" => [0, "ME"], "a" => [0, "MF"], "b" => [0, "MG"], "c" => [0, "MH"], "d" => [0, "MI"], "e" => [0, "MJ"], "f" => [0, "MK"], "g" => [0, "ML"], "h" => [0, "MM"], "i" => [0, "MN"], "j" => [0, "MO"], "k" => [0, "MP"], "l" => [0, "MQ"], "m" => [0, "MR"], "n" => [0, "MS"], "o" => [0, "MT"], "p" => [0, "MU"], "q" => [0, "MV"], "r" => [0, "MW"], "s" => [0, "MY"], "t" => [0, "Mj"], "u" => [0, "Mk"], "v" => [0, "Mq"], "w" => [0, "Mv"], "x" => [0, "Mw"], "y" => [0, "Mx"], "z" => [0, "My"], "{" => [0, "Mz"], "|" => [82, "M"], "}" => [87, "M"], "~" => [130, "M"], "" => [9, "M"], "\x80" => [94, "N0"], "\x81" => [76, "N0"], "\x82" => [104, "N0"], "\x83" => [16, "N0"], "\x84" => [94, "N1"], "\x85" => [76, "N1"], "\x86" => [104, "N1"], "\x87" => [16, "N1"], "\x88" => [94, "N2"], "\x89" => [76, "N2"], "\x8a" => [104, "N2"], "\x8b" => [16, "N2"], "\x8c" => [94, "Na"], "\x8d" => [76, "Na"], "\x8e" => [104, "Na"], "\x8f" => [16, "Na"], "\x90" => [94, "Nc"], "\x91" => [76, "Nc"], "\x92" => [104, "Nc"], "\x93" => [16, "Nc"], "\x94" => [94, "Ne"], "\x95" => [76, "Ne"], "\x96" => [104, "Ne"], "\x97" => [16, "Ne"], "\x98" => [94, "Ni"], "\x99" => [76, "Ni"], "\x9a" => [104, "Ni"], "\x9b" => [16, "Ni"], "\x9c" => [94, "No"], "\x9d" => [76, "No"], "\x9e" => [104, "No"], "\x9f" => [16, "No"], "\xa0" => [94, "Ns"], "\xa1" => [76, "Ns"], "\xa2" => [104, "Ns"], "\xa3" => [16, "Ns"], "\xa4" => [94, "Nt"], "\xa5" => [76, "Nt"], "\xa6" => [104, "Nt"], "\xa7" => [16, "Nt"], "\xa8" => [77, "N "], "\xa9" => [18, "N "], "\xaa" => [77, "N%"], "\xab" => [18, "N%"], "\xac" => [77, "N-"], "\xad" => [18, "N-"], "\xae" => [77, "N."], "\xaf" => [18, "N."], "\xb0" => [77, "N/"], "\xb1" => [18, "N/"], "\xb2" => [77, "N3"], "\xb3" => [18, "N3"], "\xb4" => [77, "N4"], "\xb5" => [18, "N4"], "\xb6" => [77, "N5"], "\xb7" => [18, "N5"], "\xb8" => [77, "N6"], "\xb9" => [18, "N6"], "\xba" => [77, "N7"], "\xbb" => [18, "N7"], "\xbc" => [77, "N8"], "\xbd" => [18, "N8"], "\xbe" => [77, "N9"], "\xbf" => [18, "N9"], "\xc0" => [77, "N="], "\xc1" => [18, "N="], "\xc2" => [77, "NA"], "\xc3" => [18, "NA"], "\xc4" => [77, "N_"], "\xc5" => [18, "N_"], "\xc6" => [77, "Nb"], "\xc7" => [18, "Nb"], "\xc8" => [77, "Nd"], "\xc9" => [18, "Nd"], "\xca" => [77, "Nf"], "\xcb" => [18, "Nf"], "\xcc" => [77, "Ng"], "\xcd" => [18, "Ng"], "\xce" => [77, "Nh"], "\xcf" => [18, "Nh"], "\xd0" => [77, "Nl"], "\xd1" => [18, "Nl"], "\xd2" => [77, "Nm"], "\xd3" => [18, "Nm"], "\xd4" => [77, "Nn"], "\xd5" => [18, "Nn"], "\xd6" => [77, "Np"], "\xd7" => [18, "Np"], "\xd8" => [77, "Nr"], "\xd9" => [18, "Nr"], "\xda" => [77, "Nu"], "\xdb" => [18, "Nu"], "\xdc" => [0, "N:"], "\xdd" => [0, "NB"], "\xde" => [0, "NC"], "\xdf" => [0, "ND"], "\xe0" => [0, "NE"], "\xe1" => [0, "NF"], "\xe2" => [0, "NG"], "\xe3" => [0, "NH"], "\xe4" => [0, "NI"], "\xe5" => [0, "NJ"], "\xe6" => [0, "NK"], "\xe7" => [0, "NL"], "\xe8" => [0, "NM"], "\xe9" => [0, "NN"], "\xea" => [0, "NO"], "\xeb" => [0, "NP"], "\xec" => [0, "NQ"], "\xed" => [0, "NR"], "\xee" => [0, "NS"], "\xef" => [0, "NT"], "\xf0" => [0, "NU"], "\xf1" => [0, "NV"], "\xf2" => [0, "NW"], "\xf3" => [0, "NY"], "\xf4" => [0, "Nj"], "\xf5" => [0, "Nk"], "\xf6" => [0, "Nq"], "\xf7" => [0, "Nv"], "\xf8" => [0, "Nw"], "\xf9" => [0, "Nx"], "\xfa" => [0, "Ny"], "\xfb" => [0, "Nz"], "\xfc" => [82, "N"], "\xfd" => [87, "N"], "\xfe" => [130, "N"], "\xff" => [9, "N"]], ["\x00" => [77, "M0"], "\x01" => [18, "M0"], "\x02" => [77, "M1"], "\x03" => [18, "M1"], "\x04" => [77, "M2"], "\x05" => [18, "M2"], "\x06" => [77, "Ma"], "\x07" => [18, "Ma"], "\x08" => [77, "Mc"], "\t" => [18, "Mc"], "\n" => [77, "Me"], "\v" => [18, "Me"], "\f" => [77, "Mi"], "\r" => [18, "Mi"], "\x0e" => [77, "Mo"], "\x0f" => [18, "Mo"], "\x10" => [77, "Ms"], "\x11" => [18, "Ms"], "\x12" => [77, "Mt"], "\x13" => [18, "Mt"], "\x14" => [0, "M "], "\x15" => [0, "M%"], "\x16" => [0, "M-"], "\x17" => [0, "M."], "\x18" => [0, "M/"], "\x19" => [0, "M3"], "\x1a" => [0, "M4"], "\x1b" => [0, "M5"], "\x1c" => [0, "M6"], "\x1d" => [0, "M7"], "\x1e" => [0, "M8"], "\x1f" => [0, "M9"], " " => [0, "M="], "!" => [0, "MA"], "\"" => [0, "M_"], "#" => [0, "Mb"], "\$" => [0, "Md"], "%" => [0, "Mf"], "&" => [0, "Mg"], "'" => [0, "Mh"], "(" => [0, "Ml"], ")" => [0, "Mm"], "*" => [0, "Mn"], "+" => [0, "Mp"], "," => [0, "Mr"], "-" => [0, "Mu"], "." => [100, "M"], "/" => [110, "M"], [111, "M"], [115, "M"], [116, "M"], [118, "M"], [119, "M"], [122, "M"], [123, "M"], [125, "M"], [126, "M"], [129, "M"], ":" => [143, "M"], ";" => [148, "M"], "<" => [151, "M"], "=" => [153, "M"], ">" => [83, "M"], "?" => [10, "M"], "@" => [77, "N0"], "A" => [18, "N0"], "B" => [77, "N1"], "C" => [18, "N1"], "D" => [77, "N2"], "E" => [18, "N2"], "F" => [77, "Na"], "G" => [18, "Na"], "H" => [77, "Nc"], "I" => [18, "Nc"], "J" => [77, "Ne"], "K" => [18, "Ne"], "L" => [77, "Ni"], "M" => [18, "Ni"], "N" => [77, "No"], "O" => [18, "No"], "P" => [77, "Ns"], "Q" => [18, "Ns"], "R" => [77, "Nt"], "S" => [18, "Nt"], "T" => [0, "N "], "U" => [0, "N%"], "V" => [0, "N-"], "W" => [0, "N."], "X" => [0, "N/"], "Y" => [0, "N3"], "Z" => [0, "N4"], "[" => [0, "N5"], "\\" => [0, "N6"], "]" => [0, "N7"], "^" => [0, "N8"], "_" => [0, "N9"], "`" => [0, "N="], "a" => [0, "NA"], "b" => [0, "N_"], "c" => [0, "Nb"], "d" => [0, "Nd"], "e" => [0, "Nf"], "f" => [0, "Ng"], "g" => [0, "Nh"], "h" => [0, "Nl"], "i" => [0, "Nm"], "j" => [0, "Nn"], "k" => [0, "Np"], "l" => [0, "Nr"], "m" => [0, "Nu"], "n" => [100, "N"], "o" => [110, "N"], "p" => [111, "N"], "q" => [115, "N"], "r" => [116, "N"], "s" => [118, "N"], "t" => [119, "N"], "u" => [122, "N"], "v" => [123, "N"], "w" => [125, "N"], "x" => [126, "N"], "y" => [129, "N"], "z" => [143, "N"], "{" => [148, "N"], "|" => [151, "N"], "}" => [153, "N"], "~" => [83, "N"], "" => [10, "N"], "\x80" => [77, "O0"], "\x81" => [18, "O0"], "\x82" => [77, "O1"], "\x83" => [18, "O1"], "\x84" => [77, "O2"], "\x85" => [18, "O2"], "\x86" => [77, "Oa"], "\x87" => [18, "Oa"], "\x88" => [77, "Oc"], "\x89" => [18, "Oc"], "\x8a" => [77, "Oe"], "\x8b" => [18, "Oe"], "\x8c" => [77, "Oi"], "\x8d" => [18, "Oi"], "\x8e" => [77, "Oo"], "\x8f" => [18, "Oo"], "\x90" => [77, "Os"], "\x91" => [18, "Os"], "\x92" => [77, "Ot"], "\x93" => [18, "Ot"], "\x94" => [0, "O "], "\x95" => [0, "O%"], "\x96" => [0, "O-"], "\x97" => [0, "O."], "\x98" => [0, "O/"], "\x99" => [0, "O3"], "\x9a" => [0, "O4"], "\x9b" => [0, "O5"], "\x9c" => [0, "O6"], "\x9d" => [0, "O7"], "\x9e" => [0, "O8"], "\x9f" => [0, "O9"], "\xa0" => [0, "O="], "\xa1" => [0, "OA"], "\xa2" => [0, "O_"], "\xa3" => [0, "Ob"], "\xa4" => [0, "Od"], "\xa5" => [0, "Of"], "\xa6" => [0, "Og"], "\xa7" => [0, "Oh"], "\xa8" => [0, "Ol"], "\xa9" => [0, "Om"], "\xaa" => [0, "On"], "\xab" => [0, "Op"], "\xac" => [0, "Or"], "\xad" => [0, "Ou"], "\xae" => [100, "O"], "\xaf" => [110, "O"], "\xb0" => [111, "O"], "\xb1" => [115, "O"], "\xb2" => [116, "O"], "\xb3" => [118, "O"], "\xb4" => [119, "O"], "\xb5" => [122, "O"], "\xb6" => [123, "O"], "\xb7" => [125, "O"], "\xb8" => [126, "O"], "\xb9" => [129, "O"], "\xba" => [143, "O"], "\xbb" => [148, "O"], "\xbc" => [151, "O"], "\xbd" => [153, "O"], "\xbe" => [83, "O"], "\xbf" => [10, "O"], "\xc0" => [77, "P0"], "\xc1" => [18, "P0"], "\xc2" => [77, "P1"], "\xc3" => [18, "P1"], "\xc4" => [77, "P2"], "\xc5" => [18, "P2"], "\xc6" => [77, "Pa"], "\xc7" => [18, "Pa"], "\xc8" => [77, "Pc"], "\xc9" => [18, "Pc"], "\xca" => [77, "Pe"], "\xcb" => [18, "Pe"], "\xcc" => [77, "Pi"], "\xcd" => [18, "Pi"], "\xce" => [77, "Po"], "\xcf" => [18, "Po"], "\xd0" => [77, "Ps"], "\xd1" => [18, "Ps"], "\xd2" => [77, "Pt"], "\xd3" => [18, "Pt"], "\xd4" => [0, "P "], "\xd5" => [0, "P%"], "\xd6" => [0, "P-"], "\xd7" => [0, "P."], "\xd8" => [0, "P/"], "\xd9" => [0, "P3"], "\xda" => [0, "P4"], "\xdb" => [0, "P5"], "\xdc" => [0, "P6"], "\xdd" => [0, "P7"], "\xde" => [0, "P8"], "\xdf" => [0, "P9"], "\xe0" => [0, "P="], "\xe1" => [0, "PA"], "\xe2" => [0, "P_"], "\xe3" => [0, "Pb"], "\xe4" => [0, "Pd"], "\xe5" => [0, "Pf"], "\xe6" => [0, "Pg"], "\xe7" => [0, "Ph"], "\xe8" => [0, "Pl"], "\xe9" => [0, "Pm"], "\xea" => [0, "Pn"], "\xeb" => [0, "Pp"], "\xec" => [0, "Pr"], "\xed" => [0, "Pu"], "\xee" => [100, "P"], "\xef" => [110, "P"], "\xf0" => [111, "P"], "\xf1" => [115, "P"], "\xf2" => [116, "P"], "\xf3" => [118, "P"], "\xf4" => [119, "P"], "\xf5" => [122, "P"], "\xf6" => [123, "P"], "\xf7" => [125, "P"], "\xf8" => [126, "P"], "\xf9" => [129, "P"], "\xfa" => [143, "P"], "\xfb" => [148, "P"], "\xfc" => [151, "P"], "\xfd" => [153, "P"], "\xfe" => [83, "P"], "\xff" => [10, "P"]], ["\x00" => [0, "M0"], "\x01" => [0, "M1"], "\x02" => [0, "M2"], "\x03" => [0, "Ma"], "\x04" => [0, "Mc"], "\x05" => [0, "Me"], "\x06" => [0, "Mi"], "\x07" => [0, "Mo"], "\x08" => [0, "Ms"], "\t" => [0, "Mt"], "\n" => [73, "M"], "\v" => [88, "M"], "\f" => [89, "M"], "\r" => [96, "M"], "\x0e" => [97, "M"], "\x0f" => [99, "M"], "\x10" => [106, "M"], "\x11" => [136, "M"], "\x12" => [139, "M"], "\x13" => [141, "M"], "\x14" => [145, "M"], "\x15" => [147, "M"], "\x16" => [149, "M"], "\x17" => [101, "M"], "\x18" => [112, "M"], "\x19" => [117, "M"], "\x1a" => [120, "M"], "\x1b" => [124, "M"], "\x1c" => [127, "M"], "\x1d" => [144, "M"], "\x1e" => [152, "M"], "\x1f" => [11, "M"], " " => [0, "N0"], "!" => [0, "N1"], "\"" => [0, "N2"], "#" => [0, "Na"], "\$" => [0, "Nc"], "%" => [0, "Ne"], "&" => [0, "Ni"], "'" => [0, "No"], "(" => [0, "Ns"], ")" => [0, "Nt"], "*" => [73, "N"], "+" => [88, "N"], "," => [89, "N"], "-" => [96, "N"], "." => [97, "N"], "/" => [99, "N"], [106, "N"], [136, "N"], [139, "N"], [141, "N"], [145, "N"], [147, "N"], [149, "N"], [101, "N"], [112, "N"], [117, "N"], ":" => [120, "N"], ";" => [124, "N"], "<" => [127, "N"], "=" => [144, "N"], ">" => [152, "N"], "?" => [11, "N"], "@" => [0, "O0"], "A" => [0, "O1"], "B" => [0, "O2"], "C" => [0, "Oa"], "D" => [0, "Oc"], "E" => [0, "Oe"], "F" => [0, "Oi"], "G" => [0, "Oo"], "H" => [0, "Os"], "I" => [0, "Ot"], "J" => [73, "O"], "K" => [88, "O"], "L" => [89, "O"], "M" => [96, "O"], "N" => [97, "O"], "O" => [99, "O"], "P" => [106, "O"], "Q" => [136, "O"], "R" => [139, "O"], "S" => [141, "O"], "T" => [145, "O"], "U" => [147, "O"], "V" => [149, "O"], "W" => [101, "O"], "X" => [112, "O"], "Y" => [117, "O"], "Z" => [120, "O"], "[" => [124, "O"], "\\" => [127, "O"], "]" => [144, "O"], "^" => [152, "O"], "_" => [11, "O"], "`" => [0, "P0"], "a" => [0, "P1"], "b" => [0, "P2"], "c" => [0, "Pa"], "d" => [0, "Pc"], "e" => [0, "Pe"], "f" => [0, "Pi"], "g" => [0, "Po"], "h" => [0, "Ps"], "i" => [0, "Pt"], "j" => [73, "P"], "k" => [88, "P"], "l" => [89, "P"], "m" => [96, "P"], "n" => [97, "P"], "o" => [99, "P"], "p" => [106, "P"], "q" => [136, "P"], "r" => [139, "P"], "s" => [141, "P"], "t" => [145, "P"], "u" => [147, "P"], "v" => [149, "P"], "w" => [101, "P"], "x" => [112, "P"], "y" => [117, "P"], "z" => [120, "P"], "{" => [124, "P"], "|" => [127, "P"], "}" => [144, "P"], "~" => [152, "P"], "" => [11, "P"], "\x80" => [0, "Q0"], "\x81" => [0, "Q1"], "\x82" => [0, "Q2"], "\x83" => [0, "Qa"], "\x84" => [0, "Qc"], "\x85" => [0, "Qe"], "\x86" => [0, "Qi"], "\x87" => [0, "Qo"], "\x88" => [0, "Qs"], "\x89" => [0, "Qt"], "\x8a" => [73, "Q"], "\x8b" => [88, "Q"], "\x8c" => [89, "Q"], "\x8d" => [96, "Q"], "\x8e" => [97, "Q"], "\x8f" => [99, "Q"], "\x90" => [106, "Q"], "\x91" => [136, "Q"], "\x92" => [139, "Q"], "\x93" => [141, "Q"], "\x94" => [145, "Q"], "\x95" => [147, "Q"], "\x96" => [149, "Q"], "\x97" => [101, "Q"], "\x98" => [112, "Q"], "\x99" => [117, "Q"], "\x9a" => [120, "Q"], "\x9b" => [124, "Q"], "\x9c" => [127, "Q"], "\x9d" => [144, "Q"], "\x9e" => [152, "Q"], "\x9f" => [11, "Q"], "\xa0" => [0, "R0"], "\xa1" => [0, "R1"], "\xa2" => [0, "R2"], "\xa3" => [0, "Ra"], "\xa4" => [0, "Rc"], "\xa5" => [0, "Re"], "\xa6" => [0, "Ri"], "\xa7" => [0, "Ro"], "\xa8" => [0, "Rs"], "\xa9" => [0, "Rt"], "\xaa" => [73, "R"], "\xab" => [88, "R"], "\xac" => [89, "R"], "\xad" => [96, "R"], "\xae" => [97, "R"], "\xaf" => [99, "R"], "\xb0" => [106, "R"], "\xb1" => [136, "R"], "\xb2" => [139, "R"], "\xb3" => [141, "R"], "\xb4" => [145, "R"], "\xb5" => [147, "R"], "\xb6" => [149, "R"], "\xb7" => [101, "R"], "\xb8" => [112, "R"], "\xb9" => [117, "R"], "\xba" => [120, "R"], "\xbb" => [124, "R"], "\xbc" => [127, "R"], "\xbd" => [144, "R"], "\xbe" => [152, "R"], "\xbf" => [11, "R"], "\xc0" => [0, "S0"], "\xc1" => [0, "S1"], "\xc2" => [0, "S2"], "\xc3" => [0, "Sa"], "\xc4" => [0, "Sc"], "\xc5" => [0, "Se"], "\xc6" => [0, "Si"], "\xc7" => [0, "So"], "\xc8" => [0, "Ss"], "\xc9" => [0, "St"], "\xca" => [73, "S"], "\xcb" => [88, "S"], "\xcc" => [89, "S"], "\xcd" => [96, "S"], "\xce" => [97, "S"], "\xcf" => [99, "S"], "\xd0" => [106, "S"], "\xd1" => [136, "S"], "\xd2" => [139, "S"], "\xd3" => [141, "S"], "\xd4" => [145, "S"], "\xd5" => [147, "S"], "\xd6" => [149, "S"], "\xd7" => [101, "S"], "\xd8" => [112, "S"], "\xd9" => [117, "S"], "\xda" => [120, "S"], "\xdb" => [124, "S"], "\xdc" => [127, "S"], "\xdd" => [144, "S"], "\xde" => [152, "S"], "\xdf" => [11, "S"], "\xe0" => [0, "T0"], "\xe1" => [0, "T1"], "\xe2" => [0, "T2"], "\xe3" => [0, "Ta"], "\xe4" => [0, "Tc"], "\xe5" => [0, "Te"], "\xe6" => [0, "Ti"], "\xe7" => [0, "To"], "\xe8" => [0, "Ts"], "\xe9" => [0, "Tt"], "\xea" => [73, "T"], "\xeb" => [88, "T"], "\xec" => [89, "T"], "\xed" => [96, "T"], "\xee" => [97, "T"], "\xef" => [99, "T"], "\xf0" => [106, "T"], "\xf1" => [136, "T"], "\xf2" => [139, "T"], "\xf3" => [141, "T"], "\xf4" => [145, "T"], "\xf5" => [147, "T"], "\xf6" => [149, "T"], "\xf7" => [101, "T"], "\xf8" => [112, "T"], "\xf9" => [117, "T"], "\xfa" => [120, "T"], "\xfb" => [124, "T"], "\xfc" => [127, "T"], "\xfd" => [144, "T"], "\xfe" => [152, "T"], "\xff" => [11, "T"]], ["\x00" => [94, "O0"], "\x01" => [76, "O0"], "\x02" => [104, "O0"], "\x03" => [16, "O0"], "\x04" => [94, "O1"], "\x05" => [76, "O1"], "\x06" => [104, "O1"], "\x07" => [16, "O1"], "\x08" => [94, "O2"], "\t" => [76, "O2"], "\n" => [104, "O2"], "\v" => [16, "O2"], "\f" => [94, "Oa"], "\r" => [76, "Oa"], "\x0e" => [104, "Oa"], "\x0f" => [16, "Oa"], "\x10" => [94, "Oc"], "\x11" => [76, "Oc"], "\x12" => [104, "Oc"], "\x13" => [16, "Oc"], "\x14" => [94, "Oe"], "\x15" => [76, "Oe"], "\x16" => [104, "Oe"], "\x17" => [16, "Oe"], "\x18" => [94, "Oi"], "\x19" => [76, "Oi"], "\x1a" => [104, "Oi"], "\x1b" => [16, "Oi"], "\x1c" => [94, "Oo"], "\x1d" => [76, "Oo"], "\x1e" => [104, "Oo"], "\x1f" => [16, "Oo"], " " => [94, "Os"], "!" => [76, "Os"], "\"" => [104, "Os"], "#" => [16, "Os"], "\$" => [94, "Ot"], "%" => [76, "Ot"], "&" => [104, "Ot"], "'" => [16, "Ot"], "(" => [77, "O "], ")" => [18, "O "], "*" => [77, "O%"], "+" => [18, "O%"], "," => [77, "O-"], "-" => [18, "O-"], "." => [77, "O."], "/" => [18, "O."], [77, "O/"], [18, "O/"], [77, "O3"], [18, "O3"], [77, "O4"], [18, "O4"], [77, "O5"], [18, "O5"], [77, "O6"], [18, "O6"], ":" => [77, "O7"], ";" => [18, "O7"], "<" => [77, "O8"], "=" => [18, "O8"], ">" => [77, "O9"], "?" => [18, "O9"], "@" => [77, "O="], "A" => [18, "O="], "B" => [77, "OA"], "C" => [18, "OA"], "D" => [77, "O_"], "E" => [18, "O_"], "F" => [77, "Ob"], "G" => [18, "Ob"], "H" => [77, "Od"], "I" => [18, "Od"], "J" => [77, "Of"], "K" => [18, "Of"], "L" => [77, "Og"], "M" => [18, "Og"], "N" => [77, "Oh"], "O" => [18, "Oh"], "P" => [77, "Ol"], "Q" => [18, "Ol"], "R" => [77, "Om"], "S" => [18, "Om"], "T" => [77, "On"], "U" => [18, "On"], "V" => [77, "Op"], "W" => [18, "Op"], "X" => [77, "Or"], "Y" => [18, "Or"], "Z" => [77, "Ou"], "[" => [18, "Ou"], "\\" => [0, "O:"], "]" => [0, "OB"], "^" => [0, "OC"], "_" => [0, "OD"], "`" => [0, "OE"], "a" => [0, "OF"], "b" => [0, "OG"], "c" => [0, "OH"], "d" => [0, "OI"], "e" => [0, "OJ"], "f" => [0, "OK"], "g" => [0, "OL"], "h" => [0, "OM"], "i" => [0, "ON"], "j" => [0, "OO"], "k" => [0, "OP"], "l" => [0, "OQ"], "m" => [0, "OR"], "n" => [0, "OS"], "o" => [0, "OT"], "p" => [0, "OU"], "q" => [0, "OV"], "r" => [0, "OW"], "s" => [0, "OY"], "t" => [0, "Oj"], "u" => [0, "Ok"], "v" => [0, "Oq"], "w" => [0, "Ov"], "x" => [0, "Ow"], "y" => [0, "Ox"], "z" => [0, "Oy"], "{" => [0, "Oz"], "|" => [82, "O"], "}" => [87, "O"], "~" => [130, "O"], "" => [9, "O"], "\x80" => [94, "P0"], "\x81" => [76, "P0"], "\x82" => [104, "P0"], "\x83" => [16, "P0"], "\x84" => [94, "P1"], "\x85" => [76, "P1"], "\x86" => [104, "P1"], "\x87" => [16, "P1"], "\x88" => [94, "P2"], "\x89" => [76, "P2"], "\x8a" => [104, "P2"], "\x8b" => [16, "P2"], "\x8c" => [94, "Pa"], "\x8d" => [76, "Pa"], "\x8e" => [104, "Pa"], "\x8f" => [16, "Pa"], "\x90" => [94, "Pc"], "\x91" => [76, "Pc"], "\x92" => [104, "Pc"], "\x93" => [16, "Pc"], "\x94" => [94, "Pe"], "\x95" => [76, "Pe"], "\x96" => [104, "Pe"], "\x97" => [16, "Pe"], "\x98" => [94, "Pi"], "\x99" => [76, "Pi"], "\x9a" => [104, "Pi"], "\x9b" => [16, "Pi"], "\x9c" => [94, "Po"], "\x9d" => [76, "Po"], "\x9e" => [104, "Po"], "\x9f" => [16, "Po"], "\xa0" => [94, "Ps"], "\xa1" => [76, "Ps"], "\xa2" => [104, "Ps"], "\xa3" => [16, "Ps"], "\xa4" => [94, "Pt"], "\xa5" => [76, "Pt"], "\xa6" => [104, "Pt"], "\xa7" => [16, "Pt"], "\xa8" => [77, "P "], "\xa9" => [18, "P "], "\xaa" => [77, "P%"], "\xab" => [18, "P%"], "\xac" => [77, "P-"], "\xad" => [18, "P-"], "\xae" => [77, "P."], "\xaf" => [18, "P."], "\xb0" => [77, "P/"], "\xb1" => [18, "P/"], "\xb2" => [77, "P3"], "\xb3" => [18, "P3"], "\xb4" => [77, "P4"], "\xb5" => [18, "P4"], "\xb6" => [77, "P5"], "\xb7" => [18, "P5"], "\xb8" => [77, "P6"], "\xb9" => [18, "P6"], "\xba" => [77, "P7"], "\xbb" => [18, "P7"], "\xbc" => [77, "P8"], "\xbd" => [18, "P8"], "\xbe" => [77, "P9"], "\xbf" => [18, "P9"], "\xc0" => [77, "P="], "\xc1" => [18, "P="], "\xc2" => [77, "PA"], "\xc3" => [18, "PA"], "\xc4" => [77, "P_"], "\xc5" => [18, "P_"], "\xc6" => [77, "Pb"], "\xc7" => [18, "Pb"], "\xc8" => [77, "Pd"], "\xc9" => [18, "Pd"], "\xca" => [77, "Pf"], "\xcb" => [18, "Pf"], "\xcc" => [77, "Pg"], "\xcd" => [18, "Pg"], "\xce" => [77, "Ph"], "\xcf" => [18, "Ph"], "\xd0" => [77, "Pl"], "\xd1" => [18, "Pl"], "\xd2" => [77, "Pm"], "\xd3" => [18, "Pm"], "\xd4" => [77, "Pn"], "\xd5" => [18, "Pn"], "\xd6" => [77, "Pp"], "\xd7" => [18, "Pp"], "\xd8" => [77, "Pr"], "\xd9" => [18, "Pr"], "\xda" => [77, "Pu"], "\xdb" => [18, "Pu"], "\xdc" => [0, "P:"], "\xdd" => [0, "PB"], "\xde" => [0, "PC"], "\xdf" => [0, "PD"], "\xe0" => [0, "PE"], "\xe1" => [0, "PF"], "\xe2" => [0, "PG"], "\xe3" => [0, "PH"], "\xe4" => [0, "PI"], "\xe5" => [0, "PJ"], "\xe6" => [0, "PK"], "\xe7" => [0, "PL"], "\xe8" => [0, "PM"], "\xe9" => [0, "PN"], "\xea" => [0, "PO"], "\xeb" => [0, "PP"], "\xec" => [0, "PQ"], "\xed" => [0, "PR"], "\xee" => [0, "PS"], "\xef" => [0, "PT"], "\xf0" => [0, "PU"], "\xf1" => [0, "PV"], "\xf2" => [0, "PW"], "\xf3" => [0, "PY"], "\xf4" => [0, "Pj"], "\xf5" => [0, "Pk"], "\xf6" => [0, "Pq"], "\xf7" => [0, "Pv"], "\xf8" => [0, "Pw"], "\xf9" => [0, "Px"], "\xfa" => [0, "Py"], "\xfb" => [0, "Pz"], "\xfc" => [82, "P"], "\xfd" => [87, "P"], "\xfe" => [130, "P"], "\xff" => [9, "P"]], ["\x00" => [94, "Q0"], "\x01" => [76, "Q0"], "\x02" => [104, "Q0"], "\x03" => [16, "Q0"], "\x04" => [94, "Q1"], "\x05" => [76, "Q1"], "\x06" => [104, "Q1"], "\x07" => [16, "Q1"], "\x08" => [94, "Q2"], "\t" => [76, "Q2"], "\n" => [104, "Q2"], "\v" => [16, "Q2"], "\f" => [94, "Qa"], "\r" => [76, "Qa"], "\x0e" => [104, "Qa"], "\x0f" => [16, "Qa"], "\x10" => [94, "Qc"], "\x11" => [76, "Qc"], "\x12" => [104, "Qc"], "\x13" => [16, "Qc"], "\x14" => [94, "Qe"], "\x15" => [76, "Qe"], "\x16" => [104, "Qe"], "\x17" => [16, "Qe"], "\x18" => [94, "Qi"], "\x19" => [76, "Qi"], "\x1a" => [104, "Qi"], "\x1b" => [16, "Qi"], "\x1c" => [94, "Qo"], "\x1d" => [76, "Qo"], "\x1e" => [104, "Qo"], "\x1f" => [16, "Qo"], " " => [94, "Qs"], "!" => [76, "Qs"], "\"" => [104, "Qs"], "#" => [16, "Qs"], "\$" => [94, "Qt"], "%" => [76, "Qt"], "&" => [104, "Qt"], "'" => [16, "Qt"], "(" => [77, "Q "], ")" => [18, "Q "], "*" => [77, "Q%"], "+" => [18, "Q%"], "," => [77, "Q-"], "-" => [18, "Q-"], "." => [77, "Q."], "/" => [18, "Q."], [77, "Q/"], [18, "Q/"], [77, "Q3"], [18, "Q3"], [77, "Q4"], [18, "Q4"], [77, "Q5"], [18, "Q5"], [77, "Q6"], [18, "Q6"], ":" => [77, "Q7"], ";" => [18, "Q7"], "<" => [77, "Q8"], "=" => [18, "Q8"], ">" => [77, "Q9"], "?" => [18, "Q9"], "@" => [77, "Q="], "A" => [18, "Q="], "B" => [77, "QA"], "C" => [18, "QA"], "D" => [77, "Q_"], "E" => [18, "Q_"], "F" => [77, "Qb"], "G" => [18, "Qb"], "H" => [77, "Qd"], "I" => [18, "Qd"], "J" => [77, "Qf"], "K" => [18, "Qf"], "L" => [77, "Qg"], "M" => [18, "Qg"], "N" => [77, "Qh"], "O" => [18, "Qh"], "P" => [77, "Ql"], "Q" => [18, "Ql"], "R" => [77, "Qm"], "S" => [18, "Qm"], "T" => [77, "Qn"], "U" => [18, "Qn"], "V" => [77, "Qp"], "W" => [18, "Qp"], "X" => [77, "Qr"], "Y" => [18, "Qr"], "Z" => [77, "Qu"], "[" => [18, "Qu"], "\\" => [0, "Q:"], "]" => [0, "QB"], "^" => [0, "QC"], "_" => [0, "QD"], "`" => [0, "QE"], "a" => [0, "QF"], "b" => [0, "QG"], "c" => [0, "QH"], "d" => [0, "QI"], "e" => [0, "QJ"], "f" => [0, "QK"], "g" => [0, "QL"], "h" => [0, "QM"], "i" => [0, "QN"], "j" => [0, "QO"], "k" => [0, "QP"], "l" => [0, "QQ"], "m" => [0, "QR"], "n" => [0, "QS"], "o" => [0, "QT"], "p" => [0, "QU"], "q" => [0, "QV"], "r" => [0, "QW"], "s" => [0, "QY"], "t" => [0, "Qj"], "u" => [0, "Qk"], "v" => [0, "Qq"], "w" => [0, "Qv"], "x" => [0, "Qw"], "y" => [0, "Qx"], "z" => [0, "Qy"], "{" => [0, "Qz"], "|" => [82, "Q"], "}" => [87, "Q"], "~" => [130, "Q"], "" => [9, "Q"], "\x80" => [94, "R0"], "\x81" => [76, "R0"], "\x82" => [104, "R0"], "\x83" => [16, "R0"], "\x84" => [94, "R1"], "\x85" => [76, "R1"], "\x86" => [104, "R1"], "\x87" => [16, "R1"], "\x88" => [94, "R2"], "\x89" => [76, "R2"], "\x8a" => [104, "R2"], "\x8b" => [16, "R2"], "\x8c" => [94, "Ra"], "\x8d" => [76, "Ra"], "\x8e" => [104, "Ra"], "\x8f" => [16, "Ra"], "\x90" => [94, "Rc"], "\x91" => [76, "Rc"], "\x92" => [104, "Rc"], "\x93" => [16, "Rc"], "\x94" => [94, "Re"], "\x95" => [76, "Re"], "\x96" => [104, "Re"], "\x97" => [16, "Re"], "\x98" => [94, "Ri"], "\x99" => [76, "Ri"], "\x9a" => [104, "Ri"], "\x9b" => [16, "Ri"], "\x9c" => [94, "Ro"], "\x9d" => [76, "Ro"], "\x9e" => [104, "Ro"], "\x9f" => [16, "Ro"], "\xa0" => [94, "Rs"], "\xa1" => [76, "Rs"], "\xa2" => [104, "Rs"], "\xa3" => [16, "Rs"], "\xa4" => [94, "Rt"], "\xa5" => [76, "Rt"], "\xa6" => [104, "Rt"], "\xa7" => [16, "Rt"], "\xa8" => [77, "R "], "\xa9" => [18, "R "], "\xaa" => [77, "R%"], "\xab" => [18, "R%"], "\xac" => [77, "R-"], "\xad" => [18, "R-"], "\xae" => [77, "R."], "\xaf" => [18, "R."], "\xb0" => [77, "R/"], "\xb1" => [18, "R/"], "\xb2" => [77, "R3"], "\xb3" => [18, "R3"], "\xb4" => [77, "R4"], "\xb5" => [18, "R4"], "\xb6" => [77, "R5"], "\xb7" => [18, "R5"], "\xb8" => [77, "R6"], "\xb9" => [18, "R6"], "\xba" => [77, "R7"], "\xbb" => [18, "R7"], "\xbc" => [77, "R8"], "\xbd" => [18, "R8"], "\xbe" => [77, "R9"], "\xbf" => [18, "R9"], "\xc0" => [77, "R="], "\xc1" => [18, "R="], "\xc2" => [77, "RA"], "\xc3" => [18, "RA"], "\xc4" => [77, "R_"], "\xc5" => [18, "R_"], "\xc6" => [77, "Rb"], "\xc7" => [18, "Rb"], "\xc8" => [77, "Rd"], "\xc9" => [18, "Rd"], "\xca" => [77, "Rf"], "\xcb" => [18, "Rf"], "\xcc" => [77, "Rg"], "\xcd" => [18, "Rg"], "\xce" => [77, "Rh"], "\xcf" => [18, "Rh"], "\xd0" => [77, "Rl"], "\xd1" => [18, "Rl"], "\xd2" => [77, "Rm"], "\xd3" => [18, "Rm"], "\xd4" => [77, "Rn"], "\xd5" => [18, "Rn"], "\xd6" => [77, "Rp"], "\xd7" => [18, "Rp"], "\xd8" => [77, "Rr"], "\xd9" => [18, "Rr"], "\xda" => [77, "Ru"], "\xdb" => [18, "Ru"], "\xdc" => [0, "R:"], "\xdd" => [0, "RB"], "\xde" => [0, "RC"], "\xdf" => [0, "RD"], "\xe0" => [0, "RE"], "\xe1" => [0, "RF"], "\xe2" => [0, "RG"], "\xe3" => [0, "RH"], "\xe4" => [0, "RI"], "\xe5" => [0, "RJ"], "\xe6" => [0, "RK"], "\xe7" => [0, "RL"], "\xe8" => [0, "RM"], "\xe9" => [0, "RN"], "\xea" => [0, "RO"], "\xeb" => [0, "RP"], "\xec" => [0, "RQ"], "\xed" => [0, "RR"], "\xee" => [0, "RS"], "\xef" => [0, "RT"], "\xf0" => [0, "RU"], "\xf1" => [0, "RV"], "\xf2" => [0, "RW"], "\xf3" => [0, "RY"], "\xf4" => [0, "Rj"], "\xf5" => [0, "Rk"], "\xf6" => [0, "Rq"], "\xf7" => [0, "Rv"], "\xf8" => [0, "Rw"], "\xf9" => [0, "Rx"], "\xfa" => [0, "Ry"], "\xfb" => [0, "Rz"], "\xfc" => [82, "R"], "\xfd" => [87, "R"], "\xfe" => [130, "R"], "\xff" => [9, "R"]], ["\x00" => [77, "Q0"], "\x01" => [18, "Q0"], "\x02" => [77, "Q1"], "\x03" => [18, "Q1"], "\x04" => [77, "Q2"], "\x05" => [18, "Q2"], "\x06" => [77, "Qa"], "\x07" => [18, "Qa"], "\x08" => [77, "Qc"], "\t" => [18, "Qc"], "\n" => [77, "Qe"], "\v" => [18, "Qe"], "\f" => [77, "Qi"], "\r" => [18, "Qi"], "\x0e" => [77, "Qo"], "\x0f" => [18, "Qo"], "\x10" => [77, "Qs"], "\x11" => [18, "Qs"], "\x12" => [77, "Qt"], "\x13" => [18, "Qt"], "\x14" => [0, "Q "], "\x15" => [0, "Q%"], "\x16" => [0, "Q-"], "\x17" => [0, "Q."], "\x18" => [0, "Q/"], "\x19" => [0, "Q3"], "\x1a" => [0, "Q4"], "\x1b" => [0, "Q5"], "\x1c" => [0, "Q6"], "\x1d" => [0, "Q7"], "\x1e" => [0, "Q8"], "\x1f" => [0, "Q9"], " " => [0, "Q="], "!" => [0, "QA"], "\"" => [0, "Q_"], "#" => [0, "Qb"], "\$" => [0, "Qd"], "%" => [0, "Qf"], "&" => [0, "Qg"], "'" => [0, "Qh"], "(" => [0, "Ql"], ")" => [0, "Qm"], "*" => [0, "Qn"], "+" => [0, "Qp"], "," => [0, "Qr"], "-" => [0, "Qu"], "." => [100, "Q"], "/" => [110, "Q"], [111, "Q"], [115, "Q"], [116, "Q"], [118, "Q"], [119, "Q"], [122, "Q"], [123, "Q"], [125, "Q"], [126, "Q"], [129, "Q"], ":" => [143, "Q"], ";" => [148, "Q"], "<" => [151, "Q"], "=" => [153, "Q"], ">" => [83, "Q"], "?" => [10, "Q"], "@" => [77, "R0"], "A" => [18, "R0"], "B" => [77, "R1"], "C" => [18, "R1"], "D" => [77, "R2"], "E" => [18, "R2"], "F" => [77, "Ra"], "G" => [18, "Ra"], "H" => [77, "Rc"], "I" => [18, "Rc"], "J" => [77, "Re"], "K" => [18, "Re"], "L" => [77, "Ri"], "M" => [18, "Ri"], "N" => [77, "Ro"], "O" => [18, "Ro"], "P" => [77, "Rs"], "Q" => [18, "Rs"], "R" => [77, "Rt"], "S" => [18, "Rt"], "T" => [0, "R "], "U" => [0, "R%"], "V" => [0, "R-"], "W" => [0, "R."], "X" => [0, "R/"], "Y" => [0, "R3"], "Z" => [0, "R4"], "[" => [0, "R5"], "\\" => [0, "R6"], "]" => [0, "R7"], "^" => [0, "R8"], "_" => [0, "R9"], "`" => [0, "R="], "a" => [0, "RA"], "b" => [0, "R_"], "c" => [0, "Rb"], "d" => [0, "Rd"], "e" => [0, "Rf"], "f" => [0, "Rg"], "g" => [0, "Rh"], "h" => [0, "Rl"], "i" => [0, "Rm"], "j" => [0, "Rn"], "k" => [0, "Rp"], "l" => [0, "Rr"], "m" => [0, "Ru"], "n" => [100, "R"], "o" => [110, "R"], "p" => [111, "R"], "q" => [115, "R"], "r" => [116, "R"], "s" => [118, "R"], "t" => [119, "R"], "u" => [122, "R"], "v" => [123, "R"], "w" => [125, "R"], "x" => [126, "R"], "y" => [129, "R"], "z" => [143, "R"], "{" => [148, "R"], "|" => [151, "R"], "}" => [153, "R"], "~" => [83, "R"], "" => [10, "R"], "\x80" => [77, "S0"], "\x81" => [18, "S0"], "\x82" => [77, "S1"], "\x83" => [18, "S1"], "\x84" => [77, "S2"], "\x85" => [18, "S2"], "\x86" => [77, "Sa"], "\x87" => [18, "Sa"], "\x88" => [77, "Sc"], "\x89" => [18, "Sc"], "\x8a" => [77, "Se"], "\x8b" => [18, "Se"], "\x8c" => [77, "Si"], "\x8d" => [18, "Si"], "\x8e" => [77, "So"], "\x8f" => [18, "So"], "\x90" => [77, "Ss"], "\x91" => [18, "Ss"], "\x92" => [77, "St"], "\x93" => [18, "St"], "\x94" => [0, "S "], "\x95" => [0, "S%"], "\x96" => [0, "S-"], "\x97" => [0, "S."], "\x98" => [0, "S/"], "\x99" => [0, "S3"], "\x9a" => [0, "S4"], "\x9b" => [0, "S5"], "\x9c" => [0, "S6"], "\x9d" => [0, "S7"], "\x9e" => [0, "S8"], "\x9f" => [0, "S9"], "\xa0" => [0, "S="], "\xa1" => [0, "SA"], "\xa2" => [0, "S_"], "\xa3" => [0, "Sb"], "\xa4" => [0, "Sd"], "\xa5" => [0, "Sf"], "\xa6" => [0, "Sg"], "\xa7" => [0, "Sh"], "\xa8" => [0, "Sl"], "\xa9" => [0, "Sm"], "\xaa" => [0, "Sn"], "\xab" => [0, "Sp"], "\xac" => [0, "Sr"], "\xad" => [0, "Su"], "\xae" => [100, "S"], "\xaf" => [110, "S"], "\xb0" => [111, "S"], "\xb1" => [115, "S"], "\xb2" => [116, "S"], "\xb3" => [118, "S"], "\xb4" => [119, "S"], "\xb5" => [122, "S"], "\xb6" => [123, "S"], "\xb7" => [125, "S"], "\xb8" => [126, "S"], "\xb9" => [129, "S"], "\xba" => [143, "S"], "\xbb" => [148, "S"], "\xbc" => [151, "S"], "\xbd" => [153, "S"], "\xbe" => [83, "S"], "\xbf" => [10, "S"], "\xc0" => [77, "T0"], "\xc1" => [18, "T0"], "\xc2" => [77, "T1"], "\xc3" => [18, "T1"], "\xc4" => [77, "T2"], "\xc5" => [18, "T2"], "\xc6" => [77, "Ta"], "\xc7" => [18, "Ta"], "\xc8" => [77, "Tc"], "\xc9" => [18, "Tc"], "\xca" => [77, "Te"], "\xcb" => [18, "Te"], "\xcc" => [77, "Ti"], "\xcd" => [18, "Ti"], "\xce" => [77, "To"], "\xcf" => [18, "To"], "\xd0" => [77, "Ts"], "\xd1" => [18, "Ts"], "\xd2" => [77, "Tt"], "\xd3" => [18, "Tt"], "\xd4" => [0, "T "], "\xd5" => [0, "T%"], "\xd6" => [0, "T-"], "\xd7" => [0, "T."], "\xd8" => [0, "T/"], "\xd9" => [0, "T3"], "\xda" => [0, "T4"], "\xdb" => [0, "T5"], "\xdc" => [0, "T6"], "\xdd" => [0, "T7"], "\xde" => [0, "T8"], "\xdf" => [0, "T9"], "\xe0" => [0, "T="], "\xe1" => [0, "TA"], "\xe2" => [0, "T_"], "\xe3" => [0, "Tb"], "\xe4" => [0, "Td"], "\xe5" => [0, "Tf"], "\xe6" => [0, "Tg"], "\xe7" => [0, "Th"], "\xe8" => [0, "Tl"], "\xe9" => [0, "Tm"], "\xea" => [0, "Tn"], "\xeb" => [0, "Tp"], "\xec" => [0, "Tr"], "\xed" => [0, "Tu"], "\xee" => [100, "T"], "\xef" => [110, "T"], "\xf0" => [111, "T"], "\xf1" => [115, "T"], "\xf2" => [116, "T"], "\xf3" => [118, "T"], "\xf4" => [119, "T"], "\xf5" => [122, "T"], "\xf6" => [123, "T"], "\xf7" => [125, "T"], "\xf8" => [126, "T"], "\xf9" => [129, "T"], "\xfa" => [143, "T"], "\xfb" => [148, "T"], "\xfc" => [151, "T"], "\xfd" => [153, "T"], "\xfe" => [83, "T"], "\xff" => [10, "T"]], ["\x00" => [94, "S0"], "\x01" => [76, "S0"], "\x02" => [104, "S0"], "\x03" => [16, "S0"], "\x04" => [94, "S1"], "\x05" => [76, "S1"], "\x06" => [104, "S1"], "\x07" => [16, "S1"], "\x08" => [94, "S2"], "\t" => [76, "S2"], "\n" => [104, "S2"], "\v" => [16, "S2"], "\f" => [94, "Sa"], "\r" => [76, "Sa"], "\x0e" => [104, "Sa"], "\x0f" => [16, "Sa"], "\x10" => [94, "Sc"], "\x11" => [76, "Sc"], "\x12" => [104, "Sc"], "\x13" => [16, "Sc"], "\x14" => [94, "Se"], "\x15" => [76, "Se"], "\x16" => [104, "Se"], "\x17" => [16, "Se"], "\x18" => [94, "Si"], "\x19" => [76, "Si"], "\x1a" => [104, "Si"], "\x1b" => [16, "Si"], "\x1c" => [94, "So"], "\x1d" => [76, "So"], "\x1e" => [104, "So"], "\x1f" => [16, "So"], " " => [94, "Ss"], "!" => [76, "Ss"], "\"" => [104, "Ss"], "#" => [16, "Ss"], "\$" => [94, "St"], "%" => [76, "St"], "&" => [104, "St"], "'" => [16, "St"], "(" => [77, "S "], ")" => [18, "S "], "*" => [77, "S%"], "+" => [18, "S%"], "," => [77, "S-"], "-" => [18, "S-"], "." => [77, "S."], "/" => [18, "S."], [77, "S/"], [18, "S/"], [77, "S3"], [18, "S3"], [77, "S4"], [18, "S4"], [77, "S5"], [18, "S5"], [77, "S6"], [18, "S6"], ":" => [77, "S7"], ";" => [18, "S7"], "<" => [77, "S8"], "=" => [18, "S8"], ">" => [77, "S9"], "?" => [18, "S9"], "@" => [77, "S="], "A" => [18, "S="], "B" => [77, "SA"], "C" => [18, "SA"], "D" => [77, "S_"], "E" => [18, "S_"], "F" => [77, "Sb"], "G" => [18, "Sb"], "H" => [77, "Sd"], "I" => [18, "Sd"], "J" => [77, "Sf"], "K" => [18, "Sf"], "L" => [77, "Sg"], "M" => [18, "Sg"], "N" => [77, "Sh"], "O" => [18, "Sh"], "P" => [77, "Sl"], "Q" => [18, "Sl"], "R" => [77, "Sm"], "S" => [18, "Sm"], "T" => [77, "Sn"], "U" => [18, "Sn"], "V" => [77, "Sp"], "W" => [18, "Sp"], "X" => [77, "Sr"], "Y" => [18, "Sr"], "Z" => [77, "Su"], "[" => [18, "Su"], "\\" => [0, "S:"], "]" => [0, "SB"], "^" => [0, "SC"], "_" => [0, "SD"], "`" => [0, "SE"], "a" => [0, "SF"], "b" => [0, "SG"], "c" => [0, "SH"], "d" => [0, "SI"], "e" => [0, "SJ"], "f" => [0, "SK"], "g" => [0, "SL"], "h" => [0, "SM"], "i" => [0, "SN"], "j" => [0, "SO"], "k" => [0, "SP"], "l" => [0, "SQ"], "m" => [0, "SR"], "n" => [0, "SS"], "o" => [0, "ST"], "p" => [0, "SU"], "q" => [0, "SV"], "r" => [0, "SW"], "s" => [0, "SY"], "t" => [0, "Sj"], "u" => [0, "Sk"], "v" => [0, "Sq"], "w" => [0, "Sv"], "x" => [0, "Sw"], "y" => [0, "Sx"], "z" => [0, "Sy"], "{" => [0, "Sz"], "|" => [82, "S"], "}" => [87, "S"], "~" => [130, "S"], "" => [9, "S"], "\x80" => [94, "T0"], "\x81" => [76, "T0"], "\x82" => [104, "T0"], "\x83" => [16, "T0"], "\x84" => [94, "T1"], "\x85" => [76, "T1"], "\x86" => [104, "T1"], "\x87" => [16, "T1"], "\x88" => [94, "T2"], "\x89" => [76, "T2"], "\x8a" => [104, "T2"], "\x8b" => [16, "T2"], "\x8c" => [94, "Ta"], "\x8d" => [76, "Ta"], "\x8e" => [104, "Ta"], "\x8f" => [16, "Ta"], "\x90" => [94, "Tc"], "\x91" => [76, "Tc"], "\x92" => [104, "Tc"], "\x93" => [16, "Tc"], "\x94" => [94, "Te"], "\x95" => [76, "Te"], "\x96" => [104, "Te"], "\x97" => [16, "Te"], "\x98" => [94, "Ti"], "\x99" => [76, "Ti"], "\x9a" => [104, "Ti"], "\x9b" => [16, "Ti"], "\x9c" => [94, "To"], "\x9d" => [76, "To"], "\x9e" => [104, "To"], "\x9f" => [16, "To"], "\xa0" => [94, "Ts"], "\xa1" => [76, "Ts"], "\xa2" => [104, "Ts"], "\xa3" => [16, "Ts"], "\xa4" => [94, "Tt"], "\xa5" => [76, "Tt"], "\xa6" => [104, "Tt"], "\xa7" => [16, "Tt"], "\xa8" => [77, "T "], "\xa9" => [18, "T "], "\xaa" => [77, "T%"], "\xab" => [18, "T%"], "\xac" => [77, "T-"], "\xad" => [18, "T-"], "\xae" => [77, "T."], "\xaf" => [18, "T."], "\xb0" => [77, "T/"], "\xb1" => [18, "T/"], "\xb2" => [77, "T3"], "\xb3" => [18, "T3"], "\xb4" => [77, "T4"], "\xb5" => [18, "T4"], "\xb6" => [77, "T5"], "\xb7" => [18, "T5"], "\xb8" => [77, "T6"], "\xb9" => [18, "T6"], "\xba" => [77, "T7"], "\xbb" => [18, "T7"], "\xbc" => [77, "T8"], "\xbd" => [18, "T8"], "\xbe" => [77, "T9"], "\xbf" => [18, "T9"], "\xc0" => [77, "T="], "\xc1" => [18, "T="], "\xc2" => [77, "TA"], "\xc3" => [18, "TA"], "\xc4" => [77, "T_"], "\xc5" => [18, "T_"], "\xc6" => [77, "Tb"], "\xc7" => [18, "Tb"], "\xc8" => [77, "Td"], "\xc9" => [18, "Td"], "\xca" => [77, "Tf"], "\xcb" => [18, "Tf"], "\xcc" => [77, "Tg"], "\xcd" => [18, "Tg"], "\xce" => [77, "Th"], "\xcf" => [18, "Th"], "\xd0" => [77, "Tl"], "\xd1" => [18, "Tl"], "\xd2" => [77, "Tm"], "\xd3" => [18, "Tm"], "\xd4" => [77, "Tn"], "\xd5" => [18, "Tn"], "\xd6" => [77, "Tp"], "\xd7" => [18, "Tp"], "\xd8" => [77, "Tr"], "\xd9" => [18, "Tr"], "\xda" => [77, "Tu"], "\xdb" => [18, "Tu"], "\xdc" => [0, "T:"], "\xdd" => [0, "TB"], "\xde" => [0, "TC"], "\xdf" => [0, "TD"], "\xe0" => [0, "TE"], "\xe1" => [0, "TF"], "\xe2" => [0, "TG"], "\xe3" => [0, "TH"], "\xe4" => [0, "TI"], "\xe5" => [0, "TJ"], "\xe6" => [0, "TK"], "\xe7" => [0, "TL"], "\xe8" => [0, "TM"], "\xe9" => [0, "TN"], "\xea" => [0, "TO"], "\xeb" => [0, "TP"], "\xec" => [0, "TQ"], "\xed" => [0, "TR"], "\xee" => [0, "TS"], "\xef" => [0, "TT"], "\xf0" => [0, "TU"], "\xf1" => [0, "TV"], "\xf2" => [0, "TW"], "\xf3" => [0, "TY"], "\xf4" => [0, "Tj"], "\xf5" => [0, "Tk"], "\xf6" => [0, "Tq"], "\xf7" => [0, "Tv"], "\xf8" => [0, "Tw"], "\xf9" => [0, "Tx"], "\xfa" => [0, "Ty"], "\xfb" => [0, "Tz"], "\xfc" => [82, "T"], "\xfd" => [87, "T"], "\xfe" => [130, "T"], "\xff" => [9, "T"]], ["\x00" => [94, "U0"], "\x01" => [76, "U0"], "\x02" => [104, "U0"], "\x03" => [16, "U0"], "\x04" => [94, "U1"], "\x05" => [76, "U1"], "\x06" => [104, "U1"], "\x07" => [16, "U1"], "\x08" => [94, "U2"], "\t" => [76, "U2"], "\n" => [104, "U2"], "\v" => [16, "U2"], "\f" => [94, "Ua"], "\r" => [76, "Ua"], "\x0e" => [104, "Ua"], "\x0f" => [16, "Ua"], "\x10" => [94, "Uc"], "\x11" => [76, "Uc"], "\x12" => [104, "Uc"], "\x13" => [16, "Uc"], "\x14" => [94, "Ue"], "\x15" => [76, "Ue"], "\x16" => [104, "Ue"], "\x17" => [16, "Ue"], "\x18" => [94, "Ui"], "\x19" => [76, "Ui"], "\x1a" => [104, "Ui"], "\x1b" => [16, "Ui"], "\x1c" => [94, "Uo"], "\x1d" => [76, "Uo"], "\x1e" => [104, "Uo"], "\x1f" => [16, "Uo"], " " => [94, "Us"], "!" => [76, "Us"], "\"" => [104, "Us"], "#" => [16, "Us"], "\$" => [94, "Ut"], "%" => [76, "Ut"], "&" => [104, "Ut"], "'" => [16, "Ut"], "(" => [77, "U "], ")" => [18, "U "], "*" => [77, "U%"], "+" => [18, "U%"], "," => [77, "U-"], "-" => [18, "U-"], "." => [77, "U."], "/" => [18, "U."], [77, "U/"], [18, "U/"], [77, "U3"], [18, "U3"], [77, "U4"], [18, "U4"], [77, "U5"], [18, "U5"], [77, "U6"], [18, "U6"], ":" => [77, "U7"], ";" => [18, "U7"], "<" => [77, "U8"], "=" => [18, "U8"], ">" => [77, "U9"], "?" => [18, "U9"], "@" => [77, "U="], "A" => [18, "U="], "B" => [77, "UA"], "C" => [18, "UA"], "D" => [77, "U_"], "E" => [18, "U_"], "F" => [77, "Ub"], "G" => [18, "Ub"], "H" => [77, "Ud"], "I" => [18, "Ud"], "J" => [77, "Uf"], "K" => [18, "Uf"], "L" => [77, "Ug"], "M" => [18, "Ug"], "N" => [77, "Uh"], "O" => [18, "Uh"], "P" => [77, "Ul"], "Q" => [18, "Ul"], "R" => [77, "Um"], "S" => [18, "Um"], "T" => [77, "Un"], "U" => [18, "Un"], "V" => [77, "Up"], "W" => [18, "Up"], "X" => [77, "Ur"], "Y" => [18, "Ur"], "Z" => [77, "Uu"], "[" => [18, "Uu"], "\\" => [0, "U:"], "]" => [0, "UB"], "^" => [0, "UC"], "_" => [0, "UD"], "`" => [0, "UE"], "a" => [0, "UF"], "b" => [0, "UG"], "c" => [0, "UH"], "d" => [0, "UI"], "e" => [0, "UJ"], "f" => [0, "UK"], "g" => [0, "UL"], "h" => [0, "UM"], "i" => [0, "UN"], "j" => [0, "UO"], "k" => [0, "UP"], "l" => [0, "UQ"], "m" => [0, "UR"], "n" => [0, "US"], "o" => [0, "UT"], "p" => [0, "UU"], "q" => [0, "UV"], "r" => [0, "UW"], "s" => [0, "UY"], "t" => [0, "Uj"], "u" => [0, "Uk"], "v" => [0, "Uq"], "w" => [0, "Uv"], "x" => [0, "Uw"], "y" => [0, "Ux"], "z" => [0, "Uy"], "{" => [0, "Uz"], "|" => [82, "U"], "}" => [87, "U"], "~" => [130, "U"], "" => [9, "U"], "\x80" => [94, "V0"], "\x81" => [76, "V0"], "\x82" => [104, "V0"], "\x83" => [16, "V0"], "\x84" => [94, "V1"], "\x85" => [76, "V1"], "\x86" => [104, "V1"], "\x87" => [16, "V1"], "\x88" => [94, "V2"], "\x89" => [76, "V2"], "\x8a" => [104, "V2"], "\x8b" => [16, "V2"], "\x8c" => [94, "Va"], "\x8d" => [76, "Va"], "\x8e" => [104, "Va"], "\x8f" => [16, "Va"], "\x90" => [94, "Vc"], "\x91" => [76, "Vc"], "\x92" => [104, "Vc"], "\x93" => [16, "Vc"], "\x94" => [94, "Ve"], "\x95" => [76, "Ve"], "\x96" => [104, "Ve"], "\x97" => [16, "Ve"], "\x98" => [94, "Vi"], "\x99" => [76, "Vi"], "\x9a" => [104, "Vi"], "\x9b" => [16, "Vi"], "\x9c" => [94, "Vo"], "\x9d" => [76, "Vo"], "\x9e" => [104, "Vo"], "\x9f" => [16, "Vo"], "\xa0" => [94, "Vs"], "\xa1" => [76, "Vs"], "\xa2" => [104, "Vs"], "\xa3" => [16, "Vs"], "\xa4" => [94, "Vt"], "\xa5" => [76, "Vt"], "\xa6" => [104, "Vt"], "\xa7" => [16, "Vt"], "\xa8" => [77, "V "], "\xa9" => [18, "V "], "\xaa" => [77, "V%"], "\xab" => [18, "V%"], "\xac" => [77, "V-"], "\xad" => [18, "V-"], "\xae" => [77, "V."], "\xaf" => [18, "V."], "\xb0" => [77, "V/"], "\xb1" => [18, "V/"], "\xb2" => [77, "V3"], "\xb3" => [18, "V3"], "\xb4" => [77, "V4"], "\xb5" => [18, "V4"], "\xb6" => [77, "V5"], "\xb7" => [18, "V5"], "\xb8" => [77, "V6"], "\xb9" => [18, "V6"], "\xba" => [77, "V7"], "\xbb" => [18, "V7"], "\xbc" => [77, "V8"], "\xbd" => [18, "V8"], "\xbe" => [77, "V9"], "\xbf" => [18, "V9"], "\xc0" => [77, "V="], "\xc1" => [18, "V="], "\xc2" => [77, "VA"], "\xc3" => [18, "VA"], "\xc4" => [77, "V_"], "\xc5" => [18, "V_"], "\xc6" => [77, "Vb"], "\xc7" => [18, "Vb"], "\xc8" => [77, "Vd"], "\xc9" => [18, "Vd"], "\xca" => [77, "Vf"], "\xcb" => [18, "Vf"], "\xcc" => [77, "Vg"], "\xcd" => [18, "Vg"], "\xce" => [77, "Vh"], "\xcf" => [18, "Vh"], "\xd0" => [77, "Vl"], "\xd1" => [18, "Vl"], "\xd2" => [77, "Vm"], "\xd3" => [18, "Vm"], "\xd4" => [77, "Vn"], "\xd5" => [18, "Vn"], "\xd6" => [77, "Vp"], "\xd7" => [18, "Vp"], "\xd8" => [77, "Vr"], "\xd9" => [18, "Vr"], "\xda" => [77, "Vu"], "\xdb" => [18, "Vu"], "\xdc" => [0, "V:"], "\xdd" => [0, "VB"], "\xde" => [0, "VC"], "\xdf" => [0, "VD"], "\xe0" => [0, "VE"], "\xe1" => [0, "VF"], "\xe2" => [0, "VG"], "\xe3" => [0, "VH"], "\xe4" => [0, "VI"], "\xe5" => [0, "VJ"], "\xe6" => [0, "VK"], "\xe7" => [0, "VL"], "\xe8" => [0, "VM"], "\xe9" => [0, "VN"], "\xea" => [0, "VO"], "\xeb" => [0, "VP"], "\xec" => [0, "VQ"], "\xed" => [0, "VR"], "\xee" => [0, "VS"], "\xef" => [0, "VT"], "\xf0" => [0, "VU"], "\xf1" => [0, "VV"], "\xf2" => [0, "VW"], "\xf3" => [0, "VY"], "\xf4" => [0, "Vj"], "\xf5" => [0, "Vk"], "\xf6" => [0, "Vq"], "\xf7" => [0, "Vv"], "\xf8" => [0, "Vw"], "\xf9" => [0, "Vx"], "\xfa" => [0, "Vy"], "\xfb" => [0, "Vz"], "\xfc" => [82, "V"], "\xfd" => [87, "V"], "\xfe" => [130, "V"], "\xff" => [9, "V"]], ["\x00" => [77, "U0"], "\x01" => [18, "U0"], "\x02" => [77, "U1"], "\x03" => [18, "U1"], "\x04" => [77, "U2"], "\x05" => [18, "U2"], "\x06" => [77, "Ua"], "\x07" => [18, "Ua"], "\x08" => [77, "Uc"], "\t" => [18, "Uc"], "\n" => [77, "Ue"], "\v" => [18, "Ue"], "\f" => [77, "Ui"], "\r" => [18, "Ui"], "\x0e" => [77, "Uo"], "\x0f" => [18, "Uo"], "\x10" => [77, "Us"], "\x11" => [18, "Us"], "\x12" => [77, "Ut"], "\x13" => [18, "Ut"], "\x14" => [0, "U "], "\x15" => [0, "U%"], "\x16" => [0, "U-"], "\x17" => [0, "U."], "\x18" => [0, "U/"], "\x19" => [0, "U3"], "\x1a" => [0, "U4"], "\x1b" => [0, "U5"], "\x1c" => [0, "U6"], "\x1d" => [0, "U7"], "\x1e" => [0, "U8"], "\x1f" => [0, "U9"], " " => [0, "U="], "!" => [0, "UA"], "\"" => [0, "U_"], "#" => [0, "Ub"], "\$" => [0, "Ud"], "%" => [0, "Uf"], "&" => [0, "Ug"], "'" => [0, "Uh"], "(" => [0, "Ul"], ")" => [0, "Um"], "*" => [0, "Un"], "+" => [0, "Up"], "," => [0, "Ur"], "-" => [0, "Uu"], "." => [100, "U"], "/" => [110, "U"], [111, "U"], [115, "U"], [116, "U"], [118, "U"], [119, "U"], [122, "U"], [123, "U"], [125, "U"], [126, "U"], [129, "U"], ":" => [143, "U"], ";" => [148, "U"], "<" => [151, "U"], "=" => [153, "U"], ">" => [83, "U"], "?" => [10, "U"], "@" => [77, "V0"], "A" => [18, "V0"], "B" => [77, "V1"], "C" => [18, "V1"], "D" => [77, "V2"], "E" => [18, "V2"], "F" => [77, "Va"], "G" => [18, "Va"], "H" => [77, "Vc"], "I" => [18, "Vc"], "J" => [77, "Ve"], "K" => [18, "Ve"], "L" => [77, "Vi"], "M" => [18, "Vi"], "N" => [77, "Vo"], "O" => [18, "Vo"], "P" => [77, "Vs"], "Q" => [18, "Vs"], "R" => [77, "Vt"], "S" => [18, "Vt"], "T" => [0, "V "], "U" => [0, "V%"], "V" => [0, "V-"], "W" => [0, "V."], "X" => [0, "V/"], "Y" => [0, "V3"], "Z" => [0, "V4"], "[" => [0, "V5"], "\\" => [0, "V6"], "]" => [0, "V7"], "^" => [0, "V8"], "_" => [0, "V9"], "`" => [0, "V="], "a" => [0, "VA"], "b" => [0, "V_"], "c" => [0, "Vb"], "d" => [0, "Vd"], "e" => [0, "Vf"], "f" => [0, "Vg"], "g" => [0, "Vh"], "h" => [0, "Vl"], "i" => [0, "Vm"], "j" => [0, "Vn"], "k" => [0, "Vp"], "l" => [0, "Vr"], "m" => [0, "Vu"], "n" => [100, "V"], "o" => [110, "V"], "p" => [111, "V"], "q" => [115, "V"], "r" => [116, "V"], "s" => [118, "V"], "t" => [119, "V"], "u" => [122, "V"], "v" => [123, "V"], "w" => [125, "V"], "x" => [126, "V"], "y" => [129, "V"], "z" => [143, "V"], "{" => [148, "V"], "|" => [151, "V"], "}" => [153, "V"], "~" => [83, "V"], "" => [10, "V"], "\x80" => [77, "W0"], "\x81" => [18, "W0"], "\x82" => [77, "W1"], "\x83" => [18, "W1"], "\x84" => [77, "W2"], "\x85" => [18, "W2"], "\x86" => [77, "Wa"], "\x87" => [18, "Wa"], "\x88" => [77, "Wc"], "\x89" => [18, "Wc"], "\x8a" => [77, "We"], "\x8b" => [18, "We"], "\x8c" => [77, "Wi"], "\x8d" => [18, "Wi"], "\x8e" => [77, "Wo"], "\x8f" => [18, "Wo"], "\x90" => [77, "Ws"], "\x91" => [18, "Ws"], "\x92" => [77, "Wt"], "\x93" => [18, "Wt"], "\x94" => [0, "W "], "\x95" => [0, "W%"], "\x96" => [0, "W-"], "\x97" => [0, "W."], "\x98" => [0, "W/"], "\x99" => [0, "W3"], "\x9a" => [0, "W4"], "\x9b" => [0, "W5"], "\x9c" => [0, "W6"], "\x9d" => [0, "W7"], "\x9e" => [0, "W8"], "\x9f" => [0, "W9"], "\xa0" => [0, "W="], "\xa1" => [0, "WA"], "\xa2" => [0, "W_"], "\xa3" => [0, "Wb"], "\xa4" => [0, "Wd"], "\xa5" => [0, "Wf"], "\xa6" => [0, "Wg"], "\xa7" => [0, "Wh"], "\xa8" => [0, "Wl"], "\xa9" => [0, "Wm"], "\xaa" => [0, "Wn"], "\xab" => [0, "Wp"], "\xac" => [0, "Wr"], "\xad" => [0, "Wu"], "\xae" => [100, "W"], "\xaf" => [110, "W"], "\xb0" => [111, "W"], "\xb1" => [115, "W"], "\xb2" => [116, "W"], "\xb3" => [118, "W"], "\xb4" => [119, "W"], "\xb5" => [122, "W"], "\xb6" => [123, "W"], "\xb7" => [125, "W"], "\xb8" => [126, "W"], "\xb9" => [129, "W"], "\xba" => [143, "W"], "\xbb" => [148, "W"], "\xbc" => [151, "W"], "\xbd" => [153, "W"], "\xbe" => [83, "W"], "\xbf" => [10, "W"], "\xc0" => [77, "Y0"], "\xc1" => [18, "Y0"], "\xc2" => [77, "Y1"], "\xc3" => [18, "Y1"], "\xc4" => [77, "Y2"], "\xc5" => [18, "Y2"], "\xc6" => [77, "Ya"], "\xc7" => [18, "Ya"], "\xc8" => [77, "Yc"], "\xc9" => [18, "Yc"], "\xca" => [77, "Ye"], "\xcb" => [18, "Ye"], "\xcc" => [77, "Yi"], "\xcd" => [18, "Yi"], "\xce" => [77, "Yo"], "\xcf" => [18, "Yo"], "\xd0" => [77, "Ys"], "\xd1" => [18, "Ys"], "\xd2" => [77, "Yt"], "\xd3" => [18, "Yt"], "\xd4" => [0, "Y "], "\xd5" => [0, "Y%"], "\xd6" => [0, "Y-"], "\xd7" => [0, "Y."], "\xd8" => [0, "Y/"], "\xd9" => [0, "Y3"], "\xda" => [0, "Y4"], "\xdb" => [0, "Y5"], "\xdc" => [0, "Y6"], "\xdd" => [0, "Y7"], "\xde" => [0, "Y8"], "\xdf" => [0, "Y9"], "\xe0" => [0, "Y="], "\xe1" => [0, "YA"], "\xe2" => [0, "Y_"], "\xe3" => [0, "Yb"], "\xe4" => [0, "Yd"], "\xe5" => [0, "Yf"], "\xe6" => [0, "Yg"], "\xe7" => [0, "Yh"], "\xe8" => [0, "Yl"], "\xe9" => [0, "Ym"], "\xea" => [0, "Yn"], "\xeb" => [0, "Yp"], "\xec" => [0, "Yr"], "\xed" => [0, "Yu"], "\xee" => [100, "Y"], "\xef" => [110, "Y"], "\xf0" => [111, "Y"], "\xf1" => [115, "Y"], "\xf2" => [116, "Y"], "\xf3" => [118, "Y"], "\xf4" => [119, "Y"], "\xf5" => [122, "Y"], "\xf6" => [123, "Y"], "\xf7" => [125, "Y"], "\xf8" => [126, "Y"], "\xf9" => [129, "Y"], "\xfa" => [143, "Y"], "\xfb" => [148, "Y"], "\xfc" => [151, "Y"], "\xfd" => [153, "Y"], "\xfe" => [83, "Y"], "\xff" => [10, "Y"]], ["\x00" => [0, "U0"], "\x01" => [0, "U1"], "\x02" => [0, "U2"], "\x03" => [0, "Ua"], "\x04" => [0, "Uc"], "\x05" => [0, "Ue"], "\x06" => [0, "Ui"], "\x07" => [0, "Uo"], "\x08" => [0, "Us"], "\t" => [0, "Ut"], "\n" => [73, "U"], "\v" => [88, "U"], "\f" => [89, "U"], "\r" => [96, "U"], "\x0e" => [97, "U"], "\x0f" => [99, "U"], "\x10" => [106, "U"], "\x11" => [136, "U"], "\x12" => [139, "U"], "\x13" => [141, "U"], "\x14" => [145, "U"], "\x15" => [147, "U"], "\x16" => [149, "U"], "\x17" => [101, "U"], "\x18" => [112, "U"], "\x19" => [117, "U"], "\x1a" => [120, "U"], "\x1b" => [124, "U"], "\x1c" => [127, "U"], "\x1d" => [144, "U"], "\x1e" => [152, "U"], "\x1f" => [11, "U"], " " => [0, "V0"], "!" => [0, "V1"], "\"" => [0, "V2"], "#" => [0, "Va"], "\$" => [0, "Vc"], "%" => [0, "Ve"], "&" => [0, "Vi"], "'" => [0, "Vo"], "(" => [0, "Vs"], ")" => [0, "Vt"], "*" => [73, "V"], "+" => [88, "V"], "," => [89, "V"], "-" => [96, "V"], "." => [97, "V"], "/" => [99, "V"], [106, "V"], [136, "V"], [139, "V"], [141, "V"], [145, "V"], [147, "V"], [149, "V"], [101, "V"], [112, "V"], [117, "V"], ":" => [120, "V"], ";" => [124, "V"], "<" => [127, "V"], "=" => [144, "V"], ">" => [152, "V"], "?" => [11, "V"], "@" => [0, "W0"], "A" => [0, "W1"], "B" => [0, "W2"], "C" => [0, "Wa"], "D" => [0, "Wc"], "E" => [0, "We"], "F" => [0, "Wi"], "G" => [0, "Wo"], "H" => [0, "Ws"], "I" => [0, "Wt"], "J" => [73, "W"], "K" => [88, "W"], "L" => [89, "W"], "M" => [96, "W"], "N" => [97, "W"], "O" => [99, "W"], "P" => [106, "W"], "Q" => [136, "W"], "R" => [139, "W"], "S" => [141, "W"], "T" => [145, "W"], "U" => [147, "W"], "V" => [149, "W"], "W" => [101, "W"], "X" => [112, "W"], "Y" => [117, "W"], "Z" => [120, "W"], "[" => [124, "W"], "\\" => [127, "W"], "]" => [144, "W"], "^" => [152, "W"], "_" => [11, "W"], "`" => [0, "Y0"], "a" => [0, "Y1"], "b" => [0, "Y2"], "c" => [0, "Ya"], "d" => [0, "Yc"], "e" => [0, "Ye"], "f" => [0, "Yi"], "g" => [0, "Yo"], "h" => [0, "Ys"], "i" => [0, "Yt"], "j" => [73, "Y"], "k" => [88, "Y"], "l" => [89, "Y"], "m" => [96, "Y"], "n" => [97, "Y"], "o" => [99, "Y"], "p" => [106, "Y"], "q" => [136, "Y"], "r" => [139, "Y"], "s" => [141, "Y"], "t" => [145, "Y"], "u" => [147, "Y"], "v" => [149, "Y"], "w" => [101, "Y"], "x" => [112, "Y"], "y" => [117, "Y"], "z" => [120, "Y"], "{" => [124, "Y"], "|" => [127, "Y"], "}" => [144, "Y"], "~" => [152, "Y"], "" => [11, "Y"], "\x80" => [0, "j0"], "\x81" => [0, "j1"], "\x82" => [0, "j2"], "\x83" => [0, "ja"], "\x84" => [0, "jc"], "\x85" => [0, "je"], "\x86" => [0, "ji"], "\x87" => [0, "jo"], "\x88" => [0, "js"], "\x89" => [0, "jt"], "\x8a" => [73, "j"], "\x8b" => [88, "j"], "\x8c" => [89, "j"], "\x8d" => [96, "j"], "\x8e" => [97, "j"], "\x8f" => [99, "j"], "\x90" => [106, "j"], "\x91" => [136, "j"], "\x92" => [139, "j"], "\x93" => [141, "j"], "\x94" => [145, "j"], "\x95" => [147, "j"], "\x96" => [149, "j"], "\x97" => [101, "j"], "\x98" => [112, "j"], "\x99" => [117, "j"], "\x9a" => [120, "j"], "\x9b" => [124, "j"], "\x9c" => [127, "j"], "\x9d" => [144, "j"], "\x9e" => [152, "j"], "\x9f" => [11, "j"], "\xa0" => [0, "k0"], "\xa1" => [0, "k1"], "\xa2" => [0, "k2"], "\xa3" => [0, "ka"], "\xa4" => [0, "kc"], "\xa5" => [0, "ke"], "\xa6" => [0, "ki"], "\xa7" => [0, "ko"], "\xa8" => [0, "ks"], "\xa9" => [0, "kt"], "\xaa" => [73, "k"], "\xab" => [88, "k"], "\xac" => [89, "k"], "\xad" => [96, "k"], "\xae" => [97, "k"], "\xaf" => [99, "k"], "\xb0" => [106, "k"], "\xb1" => [136, "k"], "\xb2" => [139, "k"], "\xb3" => [141, "k"], "\xb4" => [145, "k"], "\xb5" => [147, "k"], "\xb6" => [149, "k"], "\xb7" => [101, "k"], "\xb8" => [112, "k"], "\xb9" => [117, "k"], "\xba" => [120, "k"], "\xbb" => [124, "k"], "\xbc" => [127, "k"], "\xbd" => [144, "k"], "\xbe" => [152, "k"], "\xbf" => [11, "k"], "\xc0" => [0, "q0"], "\xc1" => [0, "q1"], "\xc2" => [0, "q2"], "\xc3" => [0, "qa"], "\xc4" => [0, "qc"], "\xc5" => [0, "qe"], "\xc6" => [0, "qi"], "\xc7" => [0, "qo"], "\xc8" => [0, "qs"], "\xc9" => [0, "qt"], "\xca" => [73, "q"], "\xcb" => [88, "q"], "\xcc" => [89, "q"], "\xcd" => [96, "q"], "\xce" => [97, "q"], "\xcf" => [99, "q"], "\xd0" => [106, "q"], "\xd1" => [136, "q"], "\xd2" => [139, "q"], "\xd3" => [141, "q"], "\xd4" => [145, "q"], "\xd5" => [147, "q"], "\xd6" => [149, "q"], "\xd7" => [101, "q"], "\xd8" => [112, "q"], "\xd9" => [117, "q"], "\xda" => [120, "q"], "\xdb" => [124, "q"], "\xdc" => [127, "q"], "\xdd" => [144, "q"], "\xde" => [152, "q"], "\xdf" => [11, "q"], "\xe0" => [0, "v0"], "\xe1" => [0, "v1"], "\xe2" => [0, "v2"], "\xe3" => [0, "va"], "\xe4" => [0, "vc"], "\xe5" => [0, "ve"], "\xe6" => [0, "vi"], "\xe7" => [0, "vo"], "\xe8" => [0, "vs"], "\xe9" => [0, "vt"], "\xea" => [73, "v"], "\xeb" => [88, "v"], "\xec" => [89, "v"], "\xed" => [96, "v"], "\xee" => [97, "v"], "\xef" => [99, "v"], "\xf0" => [106, "v"], "\xf1" => [136, "v"], "\xf2" => [139, "v"], "\xf3" => [141, "v"], "\xf4" => [145, "v"], "\xf5" => [147, "v"], "\xf6" => [149, "v"], "\xf7" => [101, "v"], "\xf8" => [112, "v"], "\xf9" => [117, "v"], "\xfa" => [120, "v"], "\xfb" => [124, "v"], "\xfc" => [127, "v"], "\xfd" => [144, "v"], "\xfe" => [152, "v"], "\xff" => [11, "v"]], ["\x00" => [94, "W0"], "\x01" => [76, "W0"], "\x02" => [104, "W0"], "\x03" => [16, "W0"], "\x04" => [94, "W1"], "\x05" => [76, "W1"], "\x06" => [104, "W1"], "\x07" => [16, "W1"], "\x08" => [94, "W2"], "\t" => [76, "W2"], "\n" => [104, "W2"], "\v" => [16, "W2"], "\f" => [94, "Wa"], "\r" => [76, "Wa"], "\x0e" => [104, "Wa"], "\x0f" => [16, "Wa"], "\x10" => [94, "Wc"], "\x11" => [76, "Wc"], "\x12" => [104, "Wc"], "\x13" => [16, "Wc"], "\x14" => [94, "We"], "\x15" => [76, "We"], "\x16" => [104, "We"], "\x17" => [16, "We"], "\x18" => [94, "Wi"], "\x19" => [76, "Wi"], "\x1a" => [104, "Wi"], "\x1b" => [16, "Wi"], "\x1c" => [94, "Wo"], "\x1d" => [76, "Wo"], "\x1e" => [104, "Wo"], "\x1f" => [16, "Wo"], " " => [94, "Ws"], "!" => [76, "Ws"], "\"" => [104, "Ws"], "#" => [16, "Ws"], "\$" => [94, "Wt"], "%" => [76, "Wt"], "&" => [104, "Wt"], "'" => [16, "Wt"], "(" => [77, "W "], ")" => [18, "W "], "*" => [77, "W%"], "+" => [18, "W%"], "," => [77, "W-"], "-" => [18, "W-"], "." => [77, "W."], "/" => [18, "W."], [77, "W/"], [18, "W/"], [77, "W3"], [18, "W3"], [77, "W4"], [18, "W4"], [77, "W5"], [18, "W5"], [77, "W6"], [18, "W6"], ":" => [77, "W7"], ";" => [18, "W7"], "<" => [77, "W8"], "=" => [18, "W8"], ">" => [77, "W9"], "?" => [18, "W9"], "@" => [77, "W="], "A" => [18, "W="], "B" => [77, "WA"], "C" => [18, "WA"], "D" => [77, "W_"], "E" => [18, "W_"], "F" => [77, "Wb"], "G" => [18, "Wb"], "H" => [77, "Wd"], "I" => [18, "Wd"], "J" => [77, "Wf"], "K" => [18, "Wf"], "L" => [77, "Wg"], "M" => [18, "Wg"], "N" => [77, "Wh"], "O" => [18, "Wh"], "P" => [77, "Wl"], "Q" => [18, "Wl"], "R" => [77, "Wm"], "S" => [18, "Wm"], "T" => [77, "Wn"], "U" => [18, "Wn"], "V" => [77, "Wp"], "W" => [18, "Wp"], "X" => [77, "Wr"], "Y" => [18, "Wr"], "Z" => [77, "Wu"], "[" => [18, "Wu"], "\\" => [0, "W:"], "]" => [0, "WB"], "^" => [0, "WC"], "_" => [0, "WD"], "`" => [0, "WE"], "a" => [0, "WF"], "b" => [0, "WG"], "c" => [0, "WH"], "d" => [0, "WI"], "e" => [0, "WJ"], "f" => [0, "WK"], "g" => [0, "WL"], "h" => [0, "WM"], "i" => [0, "WN"], "j" => [0, "WO"], "k" => [0, "WP"], "l" => [0, "WQ"], "m" => [0, "WR"], "n" => [0, "WS"], "o" => [0, "WT"], "p" => [0, "WU"], "q" => [0, "WV"], "r" => [0, "WW"], "s" => [0, "WY"], "t" => [0, "Wj"], "u" => [0, "Wk"], "v" => [0, "Wq"], "w" => [0, "Wv"], "x" => [0, "Ww"], "y" => [0, "Wx"], "z" => [0, "Wy"], "{" => [0, "Wz"], "|" => [82, "W"], "}" => [87, "W"], "~" => [130, "W"], "" => [9, "W"], "\x80" => [94, "Y0"], "\x81" => [76, "Y0"], "\x82" => [104, "Y0"], "\x83" => [16, "Y0"], "\x84" => [94, "Y1"], "\x85" => [76, "Y1"], "\x86" => [104, "Y1"], "\x87" => [16, "Y1"], "\x88" => [94, "Y2"], "\x89" => [76, "Y2"], "\x8a" => [104, "Y2"], "\x8b" => [16, "Y2"], "\x8c" => [94, "Ya"], "\x8d" => [76, "Ya"], "\x8e" => [104, "Ya"], "\x8f" => [16, "Ya"], "\x90" => [94, "Yc"], "\x91" => [76, "Yc"], "\x92" => [104, "Yc"], "\x93" => [16, "Yc"], "\x94" => [94, "Ye"], "\x95" => [76, "Ye"], "\x96" => [104, "Ye"], "\x97" => [16, "Ye"], "\x98" => [94, "Yi"], "\x99" => [76, "Yi"], "\x9a" => [104, "Yi"], "\x9b" => [16, "Yi"], "\x9c" => [94, "Yo"], "\x9d" => [76, "Yo"], "\x9e" => [104, "Yo"], "\x9f" => [16, "Yo"], "\xa0" => [94, "Ys"], "\xa1" => [76, "Ys"], "\xa2" => [104, "Ys"], "\xa3" => [16, "Ys"], "\xa4" => [94, "Yt"], "\xa5" => [76, "Yt"], "\xa6" => [104, "Yt"], "\xa7" => [16, "Yt"], "\xa8" => [77, "Y "], "\xa9" => [18, "Y "], "\xaa" => [77, "Y%"], "\xab" => [18, "Y%"], "\xac" => [77, "Y-"], "\xad" => [18, "Y-"], "\xae" => [77, "Y."], "\xaf" => [18, "Y."], "\xb0" => [77, "Y/"], "\xb1" => [18, "Y/"], "\xb2" => [77, "Y3"], "\xb3" => [18, "Y3"], "\xb4" => [77, "Y4"], "\xb5" => [18, "Y4"], "\xb6" => [77, "Y5"], "\xb7" => [18, "Y5"], "\xb8" => [77, "Y6"], "\xb9" => [18, "Y6"], "\xba" => [77, "Y7"], "\xbb" => [18, "Y7"], "\xbc" => [77, "Y8"], "\xbd" => [18, "Y8"], "\xbe" => [77, "Y9"], "\xbf" => [18, "Y9"], "\xc0" => [77, "Y="], "\xc1" => [18, "Y="], "\xc2" => [77, "YA"], "\xc3" => [18, "YA"], "\xc4" => [77, "Y_"], "\xc5" => [18, "Y_"], "\xc6" => [77, "Yb"], "\xc7" => [18, "Yb"], "\xc8" => [77, "Yd"], "\xc9" => [18, "Yd"], "\xca" => [77, "Yf"], "\xcb" => [18, "Yf"], "\xcc" => [77, "Yg"], "\xcd" => [18, "Yg"], "\xce" => [77, "Yh"], "\xcf" => [18, "Yh"], "\xd0" => [77, "Yl"], "\xd1" => [18, "Yl"], "\xd2" => [77, "Ym"], "\xd3" => [18, "Ym"], "\xd4" => [77, "Yn"], "\xd5" => [18, "Yn"], "\xd6" => [77, "Yp"], "\xd7" => [18, "Yp"], "\xd8" => [77, "Yr"], "\xd9" => [18, "Yr"], "\xda" => [77, "Yu"], "\xdb" => [18, "Yu"], "\xdc" => [0, "Y:"], "\xdd" => [0, "YB"], "\xde" => [0, "YC"], "\xdf" => [0, "YD"], "\xe0" => [0, "YE"], "\xe1" => [0, "YF"], "\xe2" => [0, "YG"], "\xe3" => [0, "YH"], "\xe4" => [0, "YI"], "\xe5" => [0, "YJ"], "\xe6" => [0, "YK"], "\xe7" => [0, "YL"], "\xe8" => [0, "YM"], "\xe9" => [0, "YN"], "\xea" => [0, "YO"], "\xeb" => [0, "YP"], "\xec" => [0, "YQ"], "\xed" => [0, "YR"], "\xee" => [0, "YS"], "\xef" => [0, "YT"], "\xf0" => [0, "YU"], "\xf1" => [0, "YV"], "\xf2" => [0, "YW"], "\xf3" => [0, "YY"], "\xf4" => [0, "Yj"], "\xf5" => [0, "Yk"], "\xf6" => [0, "Yq"], "\xf7" => [0, "Yv"], "\xf8" => [0, "Yw"], "\xf9" => [0, "Yx"], "\xfa" => [0, "Yy"], "\xfb" => [0, "Yz"], "\xfc" => [82, "Y"], "\xfd" => [87, "Y"], "\xfe" => [130, "Y"], "\xff" => [9, "Y"]], ["\x00" => [94, "X0"], "\x01" => [76, "X0"], "\x02" => [104, "X0"], "\x03" => [16, "X0"], "\x04" => [94, "X1"], "\x05" => [76, "X1"], "\x06" => [104, "X1"], "\x07" => [16, "X1"], "\x08" => [94, "X2"], "\t" => [76, "X2"], "\n" => [104, "X2"], "\v" => [16, "X2"], "\f" => [94, "Xa"], "\r" => [76, "Xa"], "\x0e" => [104, "Xa"], "\x0f" => [16, "Xa"], "\x10" => [94, "Xc"], "\x11" => [76, "Xc"], "\x12" => [104, "Xc"], "\x13" => [16, "Xc"], "\x14" => [94, "Xe"], "\x15" => [76, "Xe"], "\x16" => [104, "Xe"], "\x17" => [16, "Xe"], "\x18" => [94, "Xi"], "\x19" => [76, "Xi"], "\x1a" => [104, "Xi"], "\x1b" => [16, "Xi"], "\x1c" => [94, "Xo"], "\x1d" => [76, "Xo"], "\x1e" => [104, "Xo"], "\x1f" => [16, "Xo"], " " => [94, "Xs"], "!" => [76, "Xs"], "\"" => [104, "Xs"], "#" => [16, "Xs"], "\$" => [94, "Xt"], "%" => [76, "Xt"], "&" => [104, "Xt"], "'" => [16, "Xt"], "(" => [77, "X "], ")" => [18, "X "], "*" => [77, "X%"], "+" => [18, "X%"], "," => [77, "X-"], "-" => [18, "X-"], "." => [77, "X."], "/" => [18, "X."], [77, "X/"], [18, "X/"], [77, "X3"], [18, "X3"], [77, "X4"], [18, "X4"], [77, "X5"], [18, "X5"], [77, "X6"], [18, "X6"], ":" => [77, "X7"], ";" => [18, "X7"], "<" => [77, "X8"], "=" => [18, "X8"], ">" => [77, "X9"], "?" => [18, "X9"], "@" => [77, "X="], "A" => [18, "X="], "B" => [77, "XA"], "C" => [18, "XA"], "D" => [77, "X_"], "E" => [18, "X_"], "F" => [77, "Xb"], "G" => [18, "Xb"], "H" => [77, "Xd"], "I" => [18, "Xd"], "J" => [77, "Xf"], "K" => [18, "Xf"], "L" => [77, "Xg"], "M" => [18, "Xg"], "N" => [77, "Xh"], "O" => [18, "Xh"], "P" => [77, "Xl"], "Q" => [18, "Xl"], "R" => [77, "Xm"], "S" => [18, "Xm"], "T" => [77, "Xn"], "U" => [18, "Xn"], "V" => [77, "Xp"], "W" => [18, "Xp"], "X" => [77, "Xr"], "Y" => [18, "Xr"], "Z" => [77, "Xu"], "[" => [18, "Xu"], "\\" => [0, "X:"], "]" => [0, "XB"], "^" => [0, "XC"], "_" => [0, "XD"], "`" => [0, "XE"], "a" => [0, "XF"], "b" => [0, "XG"], "c" => [0, "XH"], "d" => [0, "XI"], "e" => [0, "XJ"], "f" => [0, "XK"], "g" => [0, "XL"], "h" => [0, "XM"], "i" => [0, "XN"], "j" => [0, "XO"], "k" => [0, "XP"], "l" => [0, "XQ"], "m" => [0, "XR"], "n" => [0, "XS"], "o" => [0, "XT"], "p" => [0, "XU"], "q" => [0, "XV"], "r" => [0, "XW"], "s" => [0, "XY"], "t" => [0, "Xj"], "u" => [0, "Xk"], "v" => [0, "Xq"], "w" => [0, "Xv"], "x" => [0, "Xw"], "y" => [0, "Xx"], "z" => [0, "Xy"], "{" => [0, "Xz"], "|" => [82, "X"], "}" => [87, "X"], "~" => [130, "X"], "" => [9, "X"], "\x80" => [94, "Z0"], "\x81" => [76, "Z0"], "\x82" => [104, "Z0"], "\x83" => [16, "Z0"], "\x84" => [94, "Z1"], "\x85" => [76, "Z1"], "\x86" => [104, "Z1"], "\x87" => [16, "Z1"], "\x88" => [94, "Z2"], "\x89" => [76, "Z2"], "\x8a" => [104, "Z2"], "\x8b" => [16, "Z2"], "\x8c" => [94, "Za"], "\x8d" => [76, "Za"], "\x8e" => [104, "Za"], "\x8f" => [16, "Za"], "\x90" => [94, "Zc"], "\x91" => [76, "Zc"], "\x92" => [104, "Zc"], "\x93" => [16, "Zc"], "\x94" => [94, "Ze"], "\x95" => [76, "Ze"], "\x96" => [104, "Ze"], "\x97" => [16, "Ze"], "\x98" => [94, "Zi"], "\x99" => [76, "Zi"], "\x9a" => [104, "Zi"], "\x9b" => [16, "Zi"], "\x9c" => [94, "Zo"], "\x9d" => [76, "Zo"], "\x9e" => [104, "Zo"], "\x9f" => [16, "Zo"], "\xa0" => [94, "Zs"], "\xa1" => [76, "Zs"], "\xa2" => [104, "Zs"], "\xa3" => [16, "Zs"], "\xa4" => [94, "Zt"], "\xa5" => [76, "Zt"], "\xa6" => [104, "Zt"], "\xa7" => [16, "Zt"], "\xa8" => [77, "Z "], "\xa9" => [18, "Z "], "\xaa" => [77, "Z%"], "\xab" => [18, "Z%"], "\xac" => [77, "Z-"], "\xad" => [18, "Z-"], "\xae" => [77, "Z."], "\xaf" => [18, "Z."], "\xb0" => [77, "Z/"], "\xb1" => [18, "Z/"], "\xb2" => [77, "Z3"], "\xb3" => [18, "Z3"], "\xb4" => [77, "Z4"], "\xb5" => [18, "Z4"], "\xb6" => [77, "Z5"], "\xb7" => [18, "Z5"], "\xb8" => [77, "Z6"], "\xb9" => [18, "Z6"], "\xba" => [77, "Z7"], "\xbb" => [18, "Z7"], "\xbc" => [77, "Z8"], "\xbd" => [18, "Z8"], "\xbe" => [77, "Z9"], "\xbf" => [18, "Z9"], "\xc0" => [77, "Z="], "\xc1" => [18, "Z="], "\xc2" => [77, "ZA"], "\xc3" => [18, "ZA"], "\xc4" => [77, "Z_"], "\xc5" => [18, "Z_"], "\xc6" => [77, "Zb"], "\xc7" => [18, "Zb"], "\xc8" => [77, "Zd"], "\xc9" => [18, "Zd"], "\xca" => [77, "Zf"], "\xcb" => [18, "Zf"], "\xcc" => [77, "Zg"], "\xcd" => [18, "Zg"], "\xce" => [77, "Zh"], "\xcf" => [18, "Zh"], "\xd0" => [77, "Zl"], "\xd1" => [18, "Zl"], "\xd2" => [77, "Zm"], "\xd3" => [18, "Zm"], "\xd4" => [77, "Zn"], "\xd5" => [18, "Zn"], "\xd6" => [77, "Zp"], "\xd7" => [18, "Zp"], "\xd8" => [77, "Zr"], "\xd9" => [18, "Zr"], "\xda" => [77, "Zu"], "\xdb" => [18, "Zu"], "\xdc" => [0, "Z:"], "\xdd" => [0, "ZB"], "\xde" => [0, "ZC"], "\xdf" => [0, "ZD"], "\xe0" => [0, "ZE"], "\xe1" => [0, "ZF"], "\xe2" => [0, "ZG"], "\xe3" => [0, "ZH"], "\xe4" => [0, "ZI"], "\xe5" => [0, "ZJ"], "\xe6" => [0, "ZK"], "\xe7" => [0, "ZL"], "\xe8" => [0, "ZM"], "\xe9" => [0, "ZN"], "\xea" => [0, "ZO"], "\xeb" => [0, "ZP"], "\xec" => [0, "ZQ"], "\xed" => [0, "ZR"], "\xee" => [0, "ZS"], "\xef" => [0, "ZT"], "\xf0" => [0, "ZU"], "\xf1" => [0, "ZV"], "\xf2" => [0, "ZW"], "\xf3" => [0, "ZY"], "\xf4" => [0, "Zj"], "\xf5" => [0, "Zk"], "\xf6" => [0, "Zq"], "\xf7" => [0, "Zv"], "\xf8" => [0, "Zw"], "\xf9" => [0, "Zx"], "\xfa" => [0, "Zy"], "\xfb" => [0, "Zz"], "\xfc" => [82, "Z"], "\xfd" => [87, "Z"], "\xfe" => [130, "Z"], "\xff" => [9, "Z"]], ["\x00" => [0, "\\0"], "\x01" => [0, "\\1"], "\x02" => [0, "\\2"], "\x03" => [0, "\\a"], "\x04" => [0, "\\c"], "\x05" => [0, "\\e"], "\x06" => [0, "\\i"], "\x07" => [0, "\\o"], "\x08" => [0, "\\s"], "\t" => [0, "\\t"], "\n" => [73, "\\"], "\v" => [88, "\\"], "\f" => [89, "\\"], "\r" => [96, "\\"], "\x0e" => [97, "\\"], "\x0f" => [99, "\\"], "\x10" => [106, "\\"], "\x11" => [136, "\\"], "\x12" => [139, "\\"], "\x13" => [141, "\\"], "\x14" => [145, "\\"], "\x15" => [147, "\\"], "\x16" => [149, "\\"], "\x17" => [101, "\\"], "\x18" => [112, "\\"], "\x19" => [117, "\\"], "\x1a" => [120, "\\"], "\x1b" => [124, "\\"], "\x1c" => [127, "\\"], "\x1d" => [144, "\\"], "\x1e" => [152, "\\"], "\x1f" => [11, "\\"], " " => [0, "\xc30"], "!" => [0, "\xc31"], "\"" => [0, "\xc32"], "#" => [0, "\xc3a"], "\$" => [0, "\xc3c"], "%" => [0, "\xc3e"], "&" => [0, "\xc3i"], "'" => [0, "\xc3o"], "(" => [0, "\xc3s"], ")" => [0, "\xc3t"], "*" => [73, "\xc3"], "+" => [88, "\xc3"], "," => [89, "\xc3"], "-" => [96, "\xc3"], "." => [97, "\xc3"], "/" => [99, "\xc3"], [106, "\xc3"], [136, "\xc3"], [139, "\xc3"], [141, "\xc3"], [145, "\xc3"], [147, "\xc3"], [149, "\xc3"], [101, "\xc3"], [112, "\xc3"], [117, "\xc3"], ":" => [120, "\xc3"], ";" => [124, "\xc3"], "<" => [127, "\xc3"], "=" => [144, "\xc3"], ">" => [152, "\xc3"], "?" => [11, "\xc3"], "@" => [0, "\xd00"], "A" => [0, "\xd01"], "B" => [0, "\xd02"], "C" => [0, "\xd0a"], "D" => [0, "\xd0c"], "E" => [0, "\xd0e"], "F" => [0, "\xd0i"], "G" => [0, "\xd0o"], "H" => [0, "\xd0s"], "I" => [0, "\xd0t"], "J" => [73, "\xd0"], "K" => [88, "\xd0"], "L" => [89, "\xd0"], "M" => [96, "\xd0"], "N" => [97, "\xd0"], "O" => [99, "\xd0"], "P" => [106, "\xd0"], "Q" => [136, "\xd0"], "R" => [139, "\xd0"], "S" => [141, "\xd0"], "T" => [145, "\xd0"], "U" => [147, "\xd0"], "V" => [149, "\xd0"], "W" => [101, "\xd0"], "X" => [112, "\xd0"], "Y" => [117, "\xd0"], "Z" => [120, "\xd0"], "[" => [124, "\xd0"], "\\" => [127, "\xd0"], "]" => [144, "\xd0"], "^" => [152, "\xd0"], "_" => [11, "\xd0"], "`" => [92, "\x80"], "a" => [95, "\x80"], "b" => [137, "\x80"], "c" => [142, "\x80"], "d" => [150, "\x80"], "e" => [74, "\x80"], "f" => [90, "\x80"], "g" => [98, "\x80"], "h" => [107, "\x80"], "i" => [140, "\x80"], "j" => [146, "\x80"], "k" => [102, "\x80"], "l" => [113, "\x80"], "m" => [121, "\x80"], "n" => [128, "\x80"], "o" => [12, "\x80"], "p" => [92, "\x82"], "q" => [95, "\x82"], "r" => [137, "\x82"], "s" => [142, "\x82"], "t" => [150, "\x82"], "u" => [74, "\x82"], "v" => [90, "\x82"], "w" => [98, "\x82"], "x" => [107, "\x82"], "y" => [140, "\x82"], "z" => [146, "\x82"], "{" => [102, "\x82"], "|" => [113, "\x82"], "}" => [121, "\x82"], "~" => [128, "\x82"], "" => [12, "\x82"], "\x80" => [92, "\x83"], "\x81" => [95, "\x83"], "\x82" => [137, "\x83"], "\x83" => [142, "\x83"], "\x84" => [150, "\x83"], "\x85" => [74, "\x83"], "\x86" => [90, "\x83"], "\x87" => [98, "\x83"], "\x88" => [107, "\x83"], "\x89" => [140, "\x83"], "\x8a" => [146, "\x83"], "\x8b" => [102, "\x83"], "\x8c" => [113, "\x83"], "\x8d" => [121, "\x83"], "\x8e" => [128, "\x83"], "\x8f" => [12, "\x83"], "\x90" => [92, "\xa2"], "\x91" => [95, "\xa2"], "\x92" => [137, "\xa2"], "\x93" => [142, "\xa2"], "\x94" => [150, "\xa2"], "\x95" => [74, "\xa2"], "\x96" => [90, "\xa2"], "\x97" => [98, "\xa2"], "\x98" => [107, "\xa2"], "\x99" => [140, "\xa2"], "\x9a" => [146, "\xa2"], "\x9b" => [102, "\xa2"], "\x9c" => [113, "\xa2"], "\x9d" => [121, "\xa2"], "\x9e" => [128, "\xa2"], "\x9f" => [12, "\xa2"], "\xa0" => [92, "\xb8"], "\xa1" => [95, "\xb8"], "\xa2" => [137, "\xb8"], "\xa3" => [142, "\xb8"], "\xa4" => [150, "\xb8"], "\xa5" => [74, "\xb8"], "\xa6" => [90, "\xb8"], "\xa7" => [98, "\xb8"], "\xa8" => [107, "\xb8"], "\xa9" => [140, "\xb8"], "\xaa" => [146, "\xb8"], "\xab" => [102, "\xb8"], "\xac" => [113, "\xb8"], "\xad" => [121, "\xb8"], "\xae" => [128, "\xb8"], "\xaf" => [12, "\xb8"], "\xb0" => [92, "\xc2"], "\xb1" => [95, "\xc2"], "\xb2" => [137, "\xc2"], "\xb3" => [142, "\xc2"], "\xb4" => [150, "\xc2"], "\xb5" => [74, "\xc2"], "\xb6" => [90, "\xc2"], "\xb7" => [98, "\xc2"], "\xb8" => [107, "\xc2"], "\xb9" => [140, "\xc2"], "\xba" => [146, "\xc2"], "\xbb" => [102, "\xc2"], "\xbc" => [113, "\xc2"], "\xbd" => [121, "\xc2"], "\xbe" => [128, "\xc2"], "\xbf" => [12, "\xc2"], "\xc0" => [92, "\xe0"], "\xc1" => [95, "\xe0"], "\xc2" => [137, "\xe0"], "\xc3" => [142, "\xe0"], "\xc4" => [150, "\xe0"], "\xc5" => [74, "\xe0"], "\xc6" => [90, "\xe0"], "\xc7" => [98, "\xe0"], "\xc8" => [107, "\xe0"], "\xc9" => [140, "\xe0"], "\xca" => [146, "\xe0"], "\xcb" => [102, "\xe0"], "\xcc" => [113, "\xe0"], "\xcd" => [121, "\xe0"], "\xce" => [128, "\xe0"], "\xcf" => [12, "\xe0"], "\xd0" => [92, "\xe2"], "\xd1" => [95, "\xe2"], "\xd2" => [137, "\xe2"], "\xd3" => [142, "\xe2"], "\xd4" => [150, "\xe2"], "\xd5" => [74, "\xe2"], "\xd6" => [90, "\xe2"], "\xd7" => [98, "\xe2"], "\xd8" => [107, "\xe2"], "\xd9" => [140, "\xe2"], "\xda" => [146, "\xe2"], "\xdb" => [102, "\xe2"], "\xdc" => [113, "\xe2"], "\xdd" => [121, "\xe2"], "\xde" => [128, "\xe2"], "\xdf" => [12, "\xe2"], "\xe0" => [93, "\x99"], "\xe1" => [138, "\x99"], "\xe2" => [75, "\x99"], "\xe3" => [91, "\x99"], "\xe4" => [108, "\x99"], "\xe5" => [103, "\x99"], "\xe6" => [114, "\x99"], "\xe7" => [14, "\x99"], "\xe8" => [93, "\xa1"], "\xe9" => [138, "\xa1"], "\xea" => [75, "\xa1"], "\xeb" => [91, "\xa1"], "\xec" => [108, "\xa1"], "\xed" => [103, "\xa1"], "\xee" => [114, "\xa1"], "\xef" => [14, "\xa1"], "\xf0" => [93, "\xa7"], "\xf1" => [138, "\xa7"], "\xf2" => [75, "\xa7"], "\xf3" => [91, "\xa7"], "\xf4" => [108, "\xa7"], "\xf5" => [103, "\xa7"], "\xf6" => [114, "\xa7"], "\xf7" => [14, "\xa7"], "\xf8" => [93, "\xac"], "\xf9" => [138, "\xac"], "\xfa" => [75, "\xac"], "\xfb" => [91, "\xac"], "\xfc" => [108, "\xac"], "\xfd" => [103, "\xac"], "\xfe" => [114, "\xac"], "\xff" => [14, "\xac"]], ["\x00" => [94, "\\0"], "\x01" => [76, "\\0"], "\x02" => [104, "\\0"], "\x03" => [16, "\\0"], "\x04" => [94, "\\1"], "\x05" => [76, "\\1"], "\x06" => [104, "\\1"], "\x07" => [16, "\\1"], "\x08" => [94, "\\2"], "\t" => [76, "\\2"], "\n" => [104, "\\2"], "\v" => [16, "\\2"], "\f" => [94, "\\a"], "\r" => [76, "\\a"], "\x0e" => [104, "\\a"], "\x0f" => [16, "\\a"], "\x10" => [94, "\\c"], "\x11" => [76, "\\c"], "\x12" => [104, "\\c"], "\x13" => [16, "\\c"], "\x14" => [94, "\\e"], "\x15" => [76, "\\e"], "\x16" => [104, "\\e"], "\x17" => [16, "\\e"], "\x18" => [94, "\\i"], "\x19" => [76, "\\i"], "\x1a" => [104, "\\i"], "\x1b" => [16, "\\i"], "\x1c" => [94, "\\o"], "\x1d" => [76, "\\o"], "\x1e" => [104, "\\o"], "\x1f" => [16, "\\o"], " " => [94, "\\s"], "!" => [76, "\\s"], "\"" => [104, "\\s"], "#" => [16, "\\s"], "\$" => [94, "\\t"], "%" => [76, "\\t"], "&" => [104, "\\t"], "'" => [16, "\\t"], "(" => [77, "\\ "], ")" => [18, "\\ "], "*" => [77, "\\%"], "+" => [18, "\\%"], "," => [77, "\\-"], "-" => [18, "\\-"], "." => [77, "\\."], "/" => [18, "\\."], [77, "\\/"], [18, "\\/"], [77, "\\3"], [18, "\\3"], [77, "\\4"], [18, "\\4"], [77, "\\5"], [18, "\\5"], [77, "\\6"], [18, "\\6"], ":" => [77, "\\7"], ";" => [18, "\\7"], "<" => [77, "\\8"], "=" => [18, "\\8"], ">" => [77, "\\9"], "?" => [18, "\\9"], "@" => [77, "\\="], "A" => [18, "\\="], "B" => [77, "\\A"], "C" => [18, "\\A"], "D" => [77, "\\_"], "E" => [18, "\\_"], "F" => [77, "\\b"], "G" => [18, "\\b"], "H" => [77, "\\d"], "I" => [18, "\\d"], "J" => [77, "\\f"], "K" => [18, "\\f"], "L" => [77, "\\g"], "M" => [18, "\\g"], "N" => [77, "\\h"], "O" => [18, "\\h"], "P" => [77, "\\l"], "Q" => [18, "\\l"], "R" => [77, "\\m"], "S" => [18, "\\m"], "T" => [77, "\\n"], "U" => [18, "\\n"], "V" => [77, "\\p"], "W" => [18, "\\p"], "X" => [77, "\\r"], "Y" => [18, "\\r"], "Z" => [77, "\\u"], "[" => [18, "\\u"], "\\" => [0, "\\:"], "]" => [0, "\\B"], "^" => [0, "\\C"], "_" => [0, "\\D"], "`" => [0, "\\E"], "a" => [0, "\\F"], "b" => [0, "\\G"], "c" => [0, "\\H"], "d" => [0, "\\I"], "e" => [0, "\\J"], "f" => [0, "\\K"], "g" => [0, "\\L"], "h" => [0, "\\M"], "i" => [0, "\\N"], "j" => [0, "\\O"], "k" => [0, "\\P"], "l" => [0, "\\Q"], "m" => [0, "\\R"], "n" => [0, "\\S"], "o" => [0, "\\T"], "p" => [0, "\\U"], "q" => [0, "\\V"], "r" => [0, "\\W"], "s" => [0, "\\Y"], "t" => [0, "\\j"], "u" => [0, "\\k"], "v" => [0, "\\q"], "w" => [0, "\\v"], "x" => [0, "\\w"], "y" => [0, "\\x"], "z" => [0, "\\y"], "{" => [0, "\\z"], "|" => [82, "\\"], "}" => [87, "\\"], "~" => [130, "\\"], "" => [9, "\\"], "\x80" => [94, "\xc30"], "\x81" => [76, "\xc30"], "\x82" => [104, "\xc30"], "\x83" => [16, "\xc30"], "\x84" => [94, "\xc31"], "\x85" => [76, "\xc31"], "\x86" => [104, "\xc31"], "\x87" => [16, "\xc31"], "\x88" => [94, "\xc32"], "\x89" => [76, "\xc32"], "\x8a" => [104, "\xc32"], "\x8b" => [16, "\xc32"], "\x8c" => [94, "\xc3a"], "\x8d" => [76, "\xc3a"], "\x8e" => [104, "\xc3a"], "\x8f" => [16, "\xc3a"], "\x90" => [94, "\xc3c"], "\x91" => [76, "\xc3c"], "\x92" => [104, "\xc3c"], "\x93" => [16, "\xc3c"], "\x94" => [94, "\xc3e"], "\x95" => [76, "\xc3e"], "\x96" => [104, "\xc3e"], "\x97" => [16, "\xc3e"], "\x98" => [94, "\xc3i"], "\x99" => [76, "\xc3i"], "\x9a" => [104, "\xc3i"], "\x9b" => [16, "\xc3i"], "\x9c" => [94, "\xc3o"], "\x9d" => [76, "\xc3o"], "\x9e" => [104, "\xc3o"], "\x9f" => [16, "\xc3o"], "\xa0" => [94, "\xc3s"], "\xa1" => [76, "\xc3s"], "\xa2" => [104, "\xc3s"], "\xa3" => [16, "\xc3s"], "\xa4" => [94, "\xc3t"], "\xa5" => [76, "\xc3t"], "\xa6" => [104, "\xc3t"], "\xa7" => [16, "\xc3t"], "\xa8" => [77, "\xc3 "], "\xa9" => [18, "\xc3 "], "\xaa" => [77, "\xc3%"], "\xab" => [18, "\xc3%"], "\xac" => [77, "\xc3-"], "\xad" => [18, "\xc3-"], "\xae" => [77, "\xc3."], "\xaf" => [18, "\xc3."], "\xb0" => [77, "\xc3/"], "\xb1" => [18, "\xc3/"], "\xb2" => [77, "\xc33"], "\xb3" => [18, "\xc33"], "\xb4" => [77, "\xc34"], "\xb5" => [18, "\xc34"], "\xb6" => [77, "\xc35"], "\xb7" => [18, "\xc35"], "\xb8" => [77, "\xc36"], "\xb9" => [18, "\xc36"], "\xba" => [77, "\xc37"], "\xbb" => [18, "\xc37"], "\xbc" => [77, "\xc38"], "\xbd" => [18, "\xc38"], "\xbe" => [77, "\xc39"], "\xbf" => [18, "\xc39"], "\xc0" => [77, "\xc3="], "\xc1" => [18, "\xc3="], "\xc2" => [77, "\xc3A"], "\xc3" => [18, "\xc3A"], "\xc4" => [77, "\xc3_"], "\xc5" => [18, "\xc3_"], "\xc6" => [77, "\xc3b"], "\xc7" => [18, "\xc3b"], "\xc8" => [77, "\xc3d"], "\xc9" => [18, "\xc3d"], "\xca" => [77, "\xc3f"], "\xcb" => [18, "\xc3f"], "\xcc" => [77, "\xc3g"], "\xcd" => [18, "\xc3g"], "\xce" => [77, "\xc3h"], "\xcf" => [18, "\xc3h"], "\xd0" => [77, "\xc3l"], "\xd1" => [18, "\xc3l"], "\xd2" => [77, "\xc3m"], "\xd3" => [18, "\xc3m"], "\xd4" => [77, "\xc3n"], "\xd5" => [18, "\xc3n"], "\xd6" => [77, "\xc3p"], "\xd7" => [18, "\xc3p"], "\xd8" => [77, "\xc3r"], "\xd9" => [18, "\xc3r"], "\xda" => [77, "\xc3u"], "\xdb" => [18, "\xc3u"], "\xdc" => [0, "\xc3:"], "\xdd" => [0, "\xc3B"], "\xde" => [0, "\xc3C"], "\xdf" => [0, "\xc3D"], "\xe0" => [0, "\xc3E"], "\xe1" => [0, "\xc3F"], "\xe2" => [0, "\xc3G"], "\xe3" => [0, "\xc3H"], "\xe4" => [0, "\xc3I"], "\xe5" => [0, "\xc3J"], "\xe6" => [0, "\xc3K"], "\xe7" => [0, "\xc3L"], "\xe8" => [0, "\xc3M"], "\xe9" => [0, "\xc3N"], "\xea" => [0, "\xc3O"], "\xeb" => [0, "\xc3P"], "\xec" => [0, "\xc3Q"], "\xed" => [0, "\xc3R"], "\xee" => [0, "\xc3S"], "\xef" => [0, "\xc3T"], "\xf0" => [0, "\xc3U"], "\xf1" => [0, "\xc3V"], "\xf2" => [0, "\xc3W"], "\xf3" => [0, "\xc3Y"], "\xf4" => [0, "\xc3j"], "\xf5" => [0, "\xc3k"], "\xf6" => [0, "\xc3q"], "\xf7" => [0, "\xc3v"], "\xf8" => [0, "\xc3w"], "\xf9" => [0, "\xc3x"], "\xfa" => [0, "\xc3y"], "\xfb" => [0, "\xc3z"], "\xfc" => [82, "\xc3"], "\xfd" => [87, "\xc3"], "\xfe" => [130, "\xc3"], "\xff" => [9, "\xc3"]], ["\x00" => [77, "\\0"], "\x01" => [18, "\\0"], "\x02" => [77, "\\1"], "\x03" => [18, "\\1"], "\x04" => [77, "\\2"], "\x05" => [18, "\\2"], "\x06" => [77, "\\a"], "\x07" => [18, "\\a"], "\x08" => [77, "\\c"], "\t" => [18, "\\c"], "\n" => [77, "\\e"], "\v" => [18, "\\e"], "\f" => [77, "\\i"], "\r" => [18, "\\i"], "\x0e" => [77, "\\o"], "\x0f" => [18, "\\o"], "\x10" => [77, "\\s"], "\x11" => [18, "\\s"], "\x12" => [77, "\\t"], "\x13" => [18, "\\t"], "\x14" => [0, "\\ "], "\x15" => [0, "\\%"], "\x16" => [0, "\\-"], "\x17" => [0, "\\."], "\x18" => [0, "\\/"], "\x19" => [0, "\\3"], "\x1a" => [0, "\\4"], "\x1b" => [0, "\\5"], "\x1c" => [0, "\\6"], "\x1d" => [0, "\\7"], "\x1e" => [0, "\\8"], "\x1f" => [0, "\\9"], " " => [0, "\\="], "!" => [0, "\\A"], "\"" => [0, "\\_"], "#" => [0, "\\b"], "\$" => [0, "\\d"], "%" => [0, "\\f"], "&" => [0, "\\g"], "'" => [0, "\\h"], "(" => [0, "\\l"], ")" => [0, "\\m"], "*" => [0, "\\n"], "+" => [0, "\\p"], "," => [0, "\\r"], "-" => [0, "\\u"], "." => [100, "\\"], "/" => [110, "\\"], [111, "\\"], [115, "\\"], [116, "\\"], [118, "\\"], [119, "\\"], [122, "\\"], [123, "\\"], [125, "\\"], [126, "\\"], [129, "\\"], ":" => [143, "\\"], ";" => [148, "\\"], "<" => [151, "\\"], "=" => [153, "\\"], ">" => [83, "\\"], "?" => [10, "\\"], "@" => [77, "\xc30"], "A" => [18, "\xc30"], "B" => [77, "\xc31"], "C" => [18, "\xc31"], "D" => [77, "\xc32"], "E" => [18, "\xc32"], "F" => [77, "\xc3a"], "G" => [18, "\xc3a"], "H" => [77, "\xc3c"], "I" => [18, "\xc3c"], "J" => [77, "\xc3e"], "K" => [18, "\xc3e"], "L" => [77, "\xc3i"], "M" => [18, "\xc3i"], "N" => [77, "\xc3o"], "O" => [18, "\xc3o"], "P" => [77, "\xc3s"], "Q" => [18, "\xc3s"], "R" => [77, "\xc3t"], "S" => [18, "\xc3t"], "T" => [0, "\xc3 "], "U" => [0, "\xc3%"], "V" => [0, "\xc3-"], "W" => [0, "\xc3."], "X" => [0, "\xc3/"], "Y" => [0, "\xc33"], "Z" => [0, "\xc34"], "[" => [0, "\xc35"], "\\" => [0, "\xc36"], "]" => [0, "\xc37"], "^" => [0, "\xc38"], "_" => [0, "\xc39"], "`" => [0, "\xc3="], "a" => [0, "\xc3A"], "b" => [0, "\xc3_"], "c" => [0, "\xc3b"], "d" => [0, "\xc3d"], "e" => [0, "\xc3f"], "f" => [0, "\xc3g"], "g" => [0, "\xc3h"], "h" => [0, "\xc3l"], "i" => [0, "\xc3m"], "j" => [0, "\xc3n"], "k" => [0, "\xc3p"], "l" => [0, "\xc3r"], "m" => [0, "\xc3u"], "n" => [100, "\xc3"], "o" => [110, "\xc3"], "p" => [111, "\xc3"], "q" => [115, "\xc3"], "r" => [116, "\xc3"], "s" => [118, "\xc3"], "t" => [119, "\xc3"], "u" => [122, "\xc3"], "v" => [123, "\xc3"], "w" => [125, "\xc3"], "x" => [126, "\xc3"], "y" => [129, "\xc3"], "z" => [143, "\xc3"], "{" => [148, "\xc3"], "|" => [151, "\xc3"], "}" => [153, "\xc3"], "~" => [83, "\xc3"], "" => [10, "\xc3"], "\x80" => [77, "\xd00"], "\x81" => [18, "\xd00"], "\x82" => [77, "\xd01"], "\x83" => [18, "\xd01"], "\x84" => [77, "\xd02"], "\x85" => [18, "\xd02"], "\x86" => [77, "\xd0a"], "\x87" => [18, "\xd0a"], "\x88" => [77, "\xd0c"], "\x89" => [18, "\xd0c"], "\x8a" => [77, "\xd0e"], "\x8b" => [18, "\xd0e"], "\x8c" => [77, "\xd0i"], "\x8d" => [18, "\xd0i"], "\x8e" => [77, "\xd0o"], "\x8f" => [18, "\xd0o"], "\x90" => [77, "\xd0s"], "\x91" => [18, "\xd0s"], "\x92" => [77, "\xd0t"], "\x93" => [18, "\xd0t"], "\x94" => [0, "\xd0 "], "\x95" => [0, "\xd0%"], "\x96" => [0, "\xd0-"], "\x97" => [0, "\xd0."], "\x98" => [0, "\xd0/"], "\x99" => [0, "\xd03"], "\x9a" => [0, "\xd04"], "\x9b" => [0, "\xd05"], "\x9c" => [0, "\xd06"], "\x9d" => [0, "\xd07"], "\x9e" => [0, "\xd08"], "\x9f" => [0, "\xd09"], "\xa0" => [0, "\xd0="], "\xa1" => [0, "\xd0A"], "\xa2" => [0, "\xd0_"], "\xa3" => [0, "\xd0b"], "\xa4" => [0, "\xd0d"], "\xa5" => [0, "\xd0f"], "\xa6" => [0, "\xd0g"], "\xa7" => [0, "\xd0h"], "\xa8" => [0, "\xd0l"], "\xa9" => [0, "\xd0m"], "\xaa" => [0, "\xd0n"], "\xab" => [0, "\xd0p"], "\xac" => [0, "\xd0r"], "\xad" => [0, "\xd0u"], "\xae" => [100, "\xd0"], "\xaf" => [110, "\xd0"], "\xb0" => [111, "\xd0"], "\xb1" => [115, "\xd0"], "\xb2" => [116, "\xd0"], "\xb3" => [118, "\xd0"], "\xb4" => [119, "\xd0"], "\xb5" => [122, "\xd0"], "\xb6" => [123, "\xd0"], "\xb7" => [125, "\xd0"], "\xb8" => [126, "\xd0"], "\xb9" => [129, "\xd0"], "\xba" => [143, "\xd0"], "\xbb" => [148, "\xd0"], "\xbc" => [151, "\xd0"], "\xbd" => [153, "\xd0"], "\xbe" => [83, "\xd0"], "\xbf" => [10, "\xd0"], "\xc0" => [0, "\x800"], "\xc1" => [0, "\x801"], "\xc2" => [0, "\x802"], "\xc3" => [0, "\x80a"], "\xc4" => [0, "\x80c"], "\xc5" => [0, "\x80e"], "\xc6" => [0, "\x80i"], "\xc7" => [0, "\x80o"], "\xc8" => [0, "\x80s"], "\xc9" => [0, "\x80t"], "\xca" => [73, "\x80"], "\xcb" => [88, "\x80"], "\xcc" => [89, "\x80"], "\xcd" => [96, "\x80"], "\xce" => [97, "\x80"], "\xcf" => [99, "\x80"], "\xd0" => [106, "\x80"], "\xd1" => [136, "\x80"], "\xd2" => [139, "\x80"], "\xd3" => [141, "\x80"], "\xd4" => [145, "\x80"], "\xd5" => [147, "\x80"], "\xd6" => [149, "\x80"], "\xd7" => [101, "\x80"], "\xd8" => [112, "\x80"], "\xd9" => [117, "\x80"], "\xda" => [120, "\x80"], "\xdb" => [124, "\x80"], "\xdc" => [127, "\x80"], "\xdd" => [144, "\x80"], "\xde" => [152, "\x80"], "\xdf" => [11, "\x80"], "\xe0" => [0, "\x820"], "\xe1" => [0, "\x821"], "\xe2" => [0, "\x822"], "\xe3" => [0, "\x82a"], "\xe4" => [0, "\x82c"], "\xe5" => [0, "\x82e"], "\xe6" => [0, "\x82i"], "\xe7" => [0, "\x82o"], "\xe8" => [0, "\x82s"], "\xe9" => [0, "\x82t"], "\xea" => [73, "\x82"], "\xeb" => [88, "\x82"], "\xec" => [89, "\x82"], "\xed" => [96, "\x82"], "\xee" => [97, "\x82"], "\xef" => [99, "\x82"], "\xf0" => [106, "\x82"], "\xf1" => [136, "\x82"], "\xf2" => [139, "\x82"], "\xf3" => [141, "\x82"], "\xf4" => [145, "\x82"], "\xf5" => [147, "\x82"], "\xf6" => [149, "\x82"], "\xf7" => [101, "\x82"], "\xf8" => [112, "\x82"], "\xf9" => [117, "\x82"], "\xfa" => [120, "\x82"], "\xfb" => [124, "\x82"], "\xfc" => [127, "\x82"], "\xfd" => [144, "\x82"], "\xfe" => [152, "\x82"], "\xff" => [11, "\x82"]], ["\x00" => [94, "]0"], "\x01" => [76, "]0"], "\x02" => [104, "]0"], "\x03" => [16, "]0"], "\x04" => [94, "]1"], "\x05" => [76, "]1"], "\x06" => [104, "]1"], "\x07" => [16, "]1"], "\x08" => [94, "]2"], "\t" => [76, "]2"], "\n" => [104, "]2"], "\v" => [16, "]2"], "\f" => [94, "]a"], "\r" => [76, "]a"], "\x0e" => [104, "]a"], "\x0f" => [16, "]a"], "\x10" => [94, "]c"], "\x11" => [76, "]c"], "\x12" => [104, "]c"], "\x13" => [16, "]c"], "\x14" => [94, "]e"], "\x15" => [76, "]e"], "\x16" => [104, "]e"], "\x17" => [16, "]e"], "\x18" => [94, "]i"], "\x19" => [76, "]i"], "\x1a" => [104, "]i"], "\x1b" => [16, "]i"], "\x1c" => [94, "]o"], "\x1d" => [76, "]o"], "\x1e" => [104, "]o"], "\x1f" => [16, "]o"], " " => [94, "]s"], "!" => [76, "]s"], "\"" => [104, "]s"], "#" => [16, "]s"], "\$" => [94, "]t"], "%" => [76, "]t"], "&" => [104, "]t"], "'" => [16, "]t"], "(" => [77, "] "], ")" => [18, "] "], "*" => [77, "]%"], "+" => [18, "]%"], "," => [77, "]-"], "-" => [18, "]-"], "." => [77, "]."], "/" => [18, "]."], [77, "]/"], [18, "]/"], [77, "]3"], [18, "]3"], [77, "]4"], [18, "]4"], [77, "]5"], [18, "]5"], [77, "]6"], [18, "]6"], ":" => [77, "]7"], ";" => [18, "]7"], "<" => [77, "]8"], "=" => [18, "]8"], ">" => [77, "]9"], "?" => [18, "]9"], "@" => [77, "]="], "A" => [18, "]="], "B" => [77, "]A"], "C" => [18, "]A"], "D" => [77, "]_"], "E" => [18, "]_"], "F" => [77, "]b"], "G" => [18, "]b"], "H" => [77, "]d"], "I" => [18, "]d"], "J" => [77, "]f"], "K" => [18, "]f"], "L" => [77, "]g"], "M" => [18, "]g"], "N" => [77, "]h"], "O" => [18, "]h"], "P" => [77, "]l"], "Q" => [18, "]l"], "R" => [77, "]m"], "S" => [18, "]m"], "T" => [77, "]n"], "U" => [18, "]n"], "V" => [77, "]p"], "W" => [18, "]p"], "X" => [77, "]r"], "Y" => [18, "]r"], "Z" => [77, "]u"], "[" => [18, "]u"], "\\" => [0, "]:"], "]" => [0, "]B"], "^" => [0, "]C"], "_" => [0, "]D"], "`" => [0, "]E"], "a" => [0, "]F"], "b" => [0, "]G"], "c" => [0, "]H"], "d" => [0, "]I"], "e" => [0, "]J"], "f" => [0, "]K"], "g" => [0, "]L"], "h" => [0, "]M"], "i" => [0, "]N"], "j" => [0, "]O"], "k" => [0, "]P"], "l" => [0, "]Q"], "m" => [0, "]R"], "n" => [0, "]S"], "o" => [0, "]T"], "p" => [0, "]U"], "q" => [0, "]V"], "r" => [0, "]W"], "s" => [0, "]Y"], "t" => [0, "]j"], "u" => [0, "]k"], "v" => [0, "]q"], "w" => [0, "]v"], "x" => [0, "]w"], "y" => [0, "]x"], "z" => [0, "]y"], "{" => [0, "]z"], "|" => [82, "]"], "}" => [87, "]"], "~" => [130, "]"], "" => [9, "]"], "\x80" => [94, "~0"], "\x81" => [76, "~0"], "\x82" => [104, "~0"], "\x83" => [16, "~0"], "\x84" => [94, "~1"], "\x85" => [76, "~1"], "\x86" => [104, "~1"], "\x87" => [16, "~1"], "\x88" => [94, "~2"], "\x89" => [76, "~2"], "\x8a" => [104, "~2"], "\x8b" => [16, "~2"], "\x8c" => [94, "~a"], "\x8d" => [76, "~a"], "\x8e" => [104, "~a"], "\x8f" => [16, "~a"], "\x90" => [94, "~c"], "\x91" => [76, "~c"], "\x92" => [104, "~c"], "\x93" => [16, "~c"], "\x94" => [94, "~e"], "\x95" => [76, "~e"], "\x96" => [104, "~e"], "\x97" => [16, "~e"], "\x98" => [94, "~i"], "\x99" => [76, "~i"], "\x9a" => [104, "~i"], "\x9b" => [16, "~i"], "\x9c" => [94, "~o"], "\x9d" => [76, "~o"], "\x9e" => [104, "~o"], "\x9f" => [16, "~o"], "\xa0" => [94, "~s"], "\xa1" => [76, "~s"], "\xa2" => [104, "~s"], "\xa3" => [16, "~s"], "\xa4" => [94, "~t"], "\xa5" => [76, "~t"], "\xa6" => [104, "~t"], "\xa7" => [16, "~t"], "\xa8" => [77, "~ "], "\xa9" => [18, "~ "], "\xaa" => [77, "~%"], "\xab" => [18, "~%"], "\xac" => [77, "~-"], "\xad" => [18, "~-"], "\xae" => [77, "~."], "\xaf" => [18, "~."], "\xb0" => [77, "~/"], "\xb1" => [18, "~/"], "\xb2" => [77, "~3"], "\xb3" => [18, "~3"], "\xb4" => [77, "~4"], "\xb5" => [18, "~4"], "\xb6" => [77, "~5"], "\xb7" => [18, "~5"], "\xb8" => [77, "~6"], "\xb9" => [18, "~6"], "\xba" => [77, "~7"], "\xbb" => [18, "~7"], "\xbc" => [77, "~8"], "\xbd" => [18, "~8"], "\xbe" => [77, "~9"], "\xbf" => [18, "~9"], "\xc0" => [77, "~="], "\xc1" => [18, "~="], "\xc2" => [77, "~A"], "\xc3" => [18, "~A"], "\xc4" => [77, "~_"], "\xc5" => [18, "~_"], "\xc6" => [77, "~b"], "\xc7" => [18, "~b"], "\xc8" => [77, "~d"], "\xc9" => [18, "~d"], "\xca" => [77, "~f"], "\xcb" => [18, "~f"], "\xcc" => [77, "~g"], "\xcd" => [18, "~g"], "\xce" => [77, "~h"], "\xcf" => [18, "~h"], "\xd0" => [77, "~l"], "\xd1" => [18, "~l"], "\xd2" => [77, "~m"], "\xd3" => [18, "~m"], "\xd4" => [77, "~n"], "\xd5" => [18, "~n"], "\xd6" => [77, "~p"], "\xd7" => [18, "~p"], "\xd8" => [77, "~r"], "\xd9" => [18, "~r"], "\xda" => [77, "~u"], "\xdb" => [18, "~u"], "\xdc" => [0, "~:"], "\xdd" => [0, "~B"], "\xde" => [0, "~C"], "\xdf" => [0, "~D"], "\xe0" => [0, "~E"], "\xe1" => [0, "~F"], "\xe2" => [0, "~G"], "\xe3" => [0, "~H"], "\xe4" => [0, "~I"], "\xe5" => [0, "~J"], "\xe6" => [0, "~K"], "\xe7" => [0, "~L"], "\xe8" => [0, "~M"], "\xe9" => [0, "~N"], "\xea" => [0, "~O"], "\xeb" => [0, "~P"], "\xec" => [0, "~Q"], "\xed" => [0, "~R"], "\xee" => [0, "~S"], "\xef" => [0, "~T"], "\xf0" => [0, "~U"], "\xf1" => [0, "~V"], "\xf2" => [0, "~W"], "\xf3" => [0, "~Y"], "\xf4" => [0, "~j"], "\xf5" => [0, "~k"], "\xf6" => [0, "~q"], "\xf7" => [0, "~v"], "\xf8" => [0, "~w"], "\xf9" => [0, "~x"], "\xfa" => [0, "~y"], "\xfb" => [0, "~z"], "\xfc" => [82, "~"], "\xfd" => [87, "~"], "\xfe" => [130, "~"], "\xff" => [9, "~"]], ["\x00" => [94, "^0"], "\x01" => [76, "^0"], "\x02" => [104, "^0"], "\x03" => [16, "^0"], "\x04" => [94, "^1"], "\x05" => [76, "^1"], "\x06" => [104, "^1"], "\x07" => [16, "^1"], "\x08" => [94, "^2"], "\t" => [76, "^2"], "\n" => [104, "^2"], "\v" => [16, "^2"], "\f" => [94, "^a"], "\r" => [76, "^a"], "\x0e" => [104, "^a"], "\x0f" => [16, "^a"], "\x10" => [94, "^c"], "\x11" => [76, "^c"], "\x12" => [104, "^c"], "\x13" => [16, "^c"], "\x14" => [94, "^e"], "\x15" => [76, "^e"], "\x16" => [104, "^e"], "\x17" => [16, "^e"], "\x18" => [94, "^i"], "\x19" => [76, "^i"], "\x1a" => [104, "^i"], "\x1b" => [16, "^i"], "\x1c" => [94, "^o"], "\x1d" => [76, "^o"], "\x1e" => [104, "^o"], "\x1f" => [16, "^o"], " " => [94, "^s"], "!" => [76, "^s"], "\"" => [104, "^s"], "#" => [16, "^s"], "\$" => [94, "^t"], "%" => [76, "^t"], "&" => [104, "^t"], "'" => [16, "^t"], "(" => [77, "^ "], ")" => [18, "^ "], "*" => [77, "^%"], "+" => [18, "^%"], "," => [77, "^-"], "-" => [18, "^-"], "." => [77, "^."], "/" => [18, "^."], [77, "^/"], [18, "^/"], [77, "^3"], [18, "^3"], [77, "^4"], [18, "^4"], [77, "^5"], [18, "^5"], [77, "^6"], [18, "^6"], ":" => [77, "^7"], ";" => [18, "^7"], "<" => [77, "^8"], "=" => [18, "^8"], ">" => [77, "^9"], "?" => [18, "^9"], "@" => [77, "^="], "A" => [18, "^="], "B" => [77, "^A"], "C" => [18, "^A"], "D" => [77, "^_"], "E" => [18, "^_"], "F" => [77, "^b"], "G" => [18, "^b"], "H" => [77, "^d"], "I" => [18, "^d"], "J" => [77, "^f"], "K" => [18, "^f"], "L" => [77, "^g"], "M" => [18, "^g"], "N" => [77, "^h"], "O" => [18, "^h"], "P" => [77, "^l"], "Q" => [18, "^l"], "R" => [77, "^m"], "S" => [18, "^m"], "T" => [77, "^n"], "U" => [18, "^n"], "V" => [77, "^p"], "W" => [18, "^p"], "X" => [77, "^r"], "Y" => [18, "^r"], "Z" => [77, "^u"], "[" => [18, "^u"], "\\" => [0, "^:"], "]" => [0, "^B"], "^" => [0, "^C"], "_" => [0, "^D"], "`" => [0, "^E"], "a" => [0, "^F"], "b" => [0, "^G"], "c" => [0, "^H"], "d" => [0, "^I"], "e" => [0, "^J"], "f" => [0, "^K"], "g" => [0, "^L"], "h" => [0, "^M"], "i" => [0, "^N"], "j" => [0, "^O"], "k" => [0, "^P"], "l" => [0, "^Q"], "m" => [0, "^R"], "n" => [0, "^S"], "o" => [0, "^T"], "p" => [0, "^U"], "q" => [0, "^V"], "r" => [0, "^W"], "s" => [0, "^Y"], "t" => [0, "^j"], "u" => [0, "^k"], "v" => [0, "^q"], "w" => [0, "^v"], "x" => [0, "^w"], "y" => [0, "^x"], "z" => [0, "^y"], "{" => [0, "^z"], "|" => [82, "^"], "}" => [87, "^"], "~" => [130, "^"], "" => [9, "^"], "\x80" => [94, "}0"], "\x81" => [76, "}0"], "\x82" => [104, "}0"], "\x83" => [16, "}0"], "\x84" => [94, "}1"], "\x85" => [76, "}1"], "\x86" => [104, "}1"], "\x87" => [16, "}1"], "\x88" => [94, "}2"], "\x89" => [76, "}2"], "\x8a" => [104, "}2"], "\x8b" => [16, "}2"], "\x8c" => [94, "}a"], "\x8d" => [76, "}a"], "\x8e" => [104, "}a"], "\x8f" => [16, "}a"], "\x90" => [94, "}c"], "\x91" => [76, "}c"], "\x92" => [104, "}c"], "\x93" => [16, "}c"], "\x94" => [94, "}e"], "\x95" => [76, "}e"], "\x96" => [104, "}e"], "\x97" => [16, "}e"], "\x98" => [94, "}i"], "\x99" => [76, "}i"], "\x9a" => [104, "}i"], "\x9b" => [16, "}i"], "\x9c" => [94, "}o"], "\x9d" => [76, "}o"], "\x9e" => [104, "}o"], "\x9f" => [16, "}o"], "\xa0" => [94, "}s"], "\xa1" => [76, "}s"], "\xa2" => [104, "}s"], "\xa3" => [16, "}s"], "\xa4" => [94, "}t"], "\xa5" => [76, "}t"], "\xa6" => [104, "}t"], "\xa7" => [16, "}t"], "\xa8" => [77, "} "], "\xa9" => [18, "} "], "\xaa" => [77, "}%"], "\xab" => [18, "}%"], "\xac" => [77, "}-"], "\xad" => [18, "}-"], "\xae" => [77, "}."], "\xaf" => [18, "}."], "\xb0" => [77, "}/"], "\xb1" => [18, "}/"], "\xb2" => [77, "}3"], "\xb3" => [18, "}3"], "\xb4" => [77, "}4"], "\xb5" => [18, "}4"], "\xb6" => [77, "}5"], "\xb7" => [18, "}5"], "\xb8" => [77, "}6"], "\xb9" => [18, "}6"], "\xba" => [77, "}7"], "\xbb" => [18, "}7"], "\xbc" => [77, "}8"], "\xbd" => [18, "}8"], "\xbe" => [77, "}9"], "\xbf" => [18, "}9"], "\xc0" => [77, "}="], "\xc1" => [18, "}="], "\xc2" => [77, "}A"], "\xc3" => [18, "}A"], "\xc4" => [77, "}_"], "\xc5" => [18, "}_"], "\xc6" => [77, "}b"], "\xc7" => [18, "}b"], "\xc8" => [77, "}d"], "\xc9" => [18, "}d"], "\xca" => [77, "}f"], "\xcb" => [18, "}f"], "\xcc" => [77, "}g"], "\xcd" => [18, "}g"], "\xce" => [77, "}h"], "\xcf" => [18, "}h"], "\xd0" => [77, "}l"], "\xd1" => [18, "}l"], "\xd2" => [77, "}m"], "\xd3" => [18, "}m"], "\xd4" => [77, "}n"], "\xd5" => [18, "}n"], "\xd6" => [77, "}p"], "\xd7" => [18, "}p"], "\xd8" => [77, "}r"], "\xd9" => [18, "}r"], "\xda" => [77, "}u"], "\xdb" => [18, "}u"], "\xdc" => [0, "}:"], "\xdd" => [0, "}B"], "\xde" => [0, "}C"], "\xdf" => [0, "}D"], "\xe0" => [0, "}E"], "\xe1" => [0, "}F"], "\xe2" => [0, "}G"], "\xe3" => [0, "}H"], "\xe4" => [0, "}I"], "\xe5" => [0, "}J"], "\xe6" => [0, "}K"], "\xe7" => [0, "}L"], "\xe8" => [0, "}M"], "\xe9" => [0, "}N"], "\xea" => [0, "}O"], "\xeb" => [0, "}P"], "\xec" => [0, "}Q"], "\xed" => [0, "}R"], "\xee" => [0, "}S"], "\xef" => [0, "}T"], "\xf0" => [0, "}U"], "\xf1" => [0, "}V"], "\xf2" => [0, "}W"], "\xf3" => [0, "}Y"], "\xf4" => [0, "}j"], "\xf5" => [0, "}k"], "\xf6" => [0, "}q"], "\xf7" => [0, "}v"], "\xf8" => [0, "}w"], "\xf9" => [0, "}x"], "\xfa" => [0, "}y"], "\xfb" => [0, "}z"], "\xfc" => [82, "}"], "\xfd" => [87, "}"], "\xfe" => [130, "}"], "\xff" => [9, "}"]], ["\x00" => [94, "_0"], "\x01" => [76, "_0"], "\x02" => [104, "_0"], "\x03" => [16, "_0"], "\x04" => [94, "_1"], "\x05" => [76, "_1"], "\x06" => [104, "_1"], "\x07" => [16, "_1"], "\x08" => [94, "_2"], "\t" => [76, "_2"], "\n" => [104, "_2"], "\v" => [16, "_2"], "\f" => [94, "_a"], "\r" => [76, "_a"], "\x0e" => [104, "_a"], "\x0f" => [16, "_a"], "\x10" => [94, "_c"], "\x11" => [76, "_c"], "\x12" => [104, "_c"], "\x13" => [16, "_c"], "\x14" => [94, "_e"], "\x15" => [76, "_e"], "\x16" => [104, "_e"], "\x17" => [16, "_e"], "\x18" => [94, "_i"], "\x19" => [76, "_i"], "\x1a" => [104, "_i"], "\x1b" => [16, "_i"], "\x1c" => [94, "_o"], "\x1d" => [76, "_o"], "\x1e" => [104, "_o"], "\x1f" => [16, "_o"], " " => [94, "_s"], "!" => [76, "_s"], "\"" => [104, "_s"], "#" => [16, "_s"], "\$" => [94, "_t"], "%" => [76, "_t"], "&" => [104, "_t"], "'" => [16, "_t"], "(" => [77, "_ "], ")" => [18, "_ "], "*" => [77, "_%"], "+" => [18, "_%"], "," => [77, "_-"], "-" => [18, "_-"], "." => [77, "_."], "/" => [18, "_."], [77, "_/"], [18, "_/"], [77, "_3"], [18, "_3"], [77, "_4"], [18, "_4"], [77, "_5"], [18, "_5"], [77, "_6"], [18, "_6"], ":" => [77, "_7"], ";" => [18, "_7"], "<" => [77, "_8"], "=" => [18, "_8"], ">" => [77, "_9"], "?" => [18, "_9"], "@" => [77, "_="], "A" => [18, "_="], "B" => [77, "_A"], "C" => [18, "_A"], "D" => [77, "__"], "E" => [18, "__"], "F" => [77, "_b"], "G" => [18, "_b"], "H" => [77, "_d"], "I" => [18, "_d"], "J" => [77, "_f"], "K" => [18, "_f"], "L" => [77, "_g"], "M" => [18, "_g"], "N" => [77, "_h"], "O" => [18, "_h"], "P" => [77, "_l"], "Q" => [18, "_l"], "R" => [77, "_m"], "S" => [18, "_m"], "T" => [77, "_n"], "U" => [18, "_n"], "V" => [77, "_p"], "W" => [18, "_p"], "X" => [77, "_r"], "Y" => [18, "_r"], "Z" => [77, "_u"], "[" => [18, "_u"], "\\" => [0, "_:"], "]" => [0, "_B"], "^" => [0, "_C"], "_" => [0, "_D"], "`" => [0, "_E"], "a" => [0, "_F"], "b" => [0, "_G"], "c" => [0, "_H"], "d" => [0, "_I"], "e" => [0, "_J"], "f" => [0, "_K"], "g" => [0, "_L"], "h" => [0, "_M"], "i" => [0, "_N"], "j" => [0, "_O"], "k" => [0, "_P"], "l" => [0, "_Q"], "m" => [0, "_R"], "n" => [0, "_S"], "o" => [0, "_T"], "p" => [0, "_U"], "q" => [0, "_V"], "r" => [0, "_W"], "s" => [0, "_Y"], "t" => [0, "_j"], "u" => [0, "_k"], "v" => [0, "_q"], "w" => [0, "_v"], "x" => [0, "_w"], "y" => [0, "_x"], "z" => [0, "_y"], "{" => [0, "_z"], "|" => [82, "_"], "}" => [87, "_"], "~" => [130, "_"], "" => [9, "_"], "\x80" => [94, "b0"], "\x81" => [76, "b0"], "\x82" => [104, "b0"], "\x83" => [16, "b0"], "\x84" => [94, "b1"], "\x85" => [76, "b1"], "\x86" => [104, "b1"], "\x87" => [16, "b1"], "\x88" => [94, "b2"], "\x89" => [76, "b2"], "\x8a" => [104, "b2"], "\x8b" => [16, "b2"], "\x8c" => [94, "ba"], "\x8d" => [76, "ba"], "\x8e" => [104, "ba"], "\x8f" => [16, "ba"], "\x90" => [94, "bc"], "\x91" => [76, "bc"], "\x92" => [104, "bc"], "\x93" => [16, "bc"], "\x94" => [94, "be"], "\x95" => [76, "be"], "\x96" => [104, "be"], "\x97" => [16, "be"], "\x98" => [94, "bi"], "\x99" => [76, "bi"], "\x9a" => [104, "bi"], "\x9b" => [16, "bi"], "\x9c" => [94, "bo"], "\x9d" => [76, "bo"], "\x9e" => [104, "bo"], "\x9f" => [16, "bo"], "\xa0" => [94, "bs"], "\xa1" => [76, "bs"], "\xa2" => [104, "bs"], "\xa3" => [16, "bs"], "\xa4" => [94, "bt"], "\xa5" => [76, "bt"], "\xa6" => [104, "bt"], "\xa7" => [16, "bt"], "\xa8" => [77, "b "], "\xa9" => [18, "b "], "\xaa" => [77, "b%"], "\xab" => [18, "b%"], "\xac" => [77, "b-"], "\xad" => [18, "b-"], "\xae" => [77, "b."], "\xaf" => [18, "b."], "\xb0" => [77, "b/"], "\xb1" => [18, "b/"], "\xb2" => [77, "b3"], "\xb3" => [18, "b3"], "\xb4" => [77, "b4"], "\xb5" => [18, "b4"], "\xb6" => [77, "b5"], "\xb7" => [18, "b5"], "\xb8" => [77, "b6"], "\xb9" => [18, "b6"], "\xba" => [77, "b7"], "\xbb" => [18, "b7"], "\xbc" => [77, "b8"], "\xbd" => [18, "b8"], "\xbe" => [77, "b9"], "\xbf" => [18, "b9"], "\xc0" => [77, "b="], "\xc1" => [18, "b="], "\xc2" => [77, "bA"], "\xc3" => [18, "bA"], "\xc4" => [77, "b_"], "\xc5" => [18, "b_"], "\xc6" => [77, "bb"], "\xc7" => [18, "bb"], "\xc8" => [77, "bd"], "\xc9" => [18, "bd"], "\xca" => [77, "bf"], "\xcb" => [18, "bf"], "\xcc" => [77, "bg"], "\xcd" => [18, "bg"], "\xce" => [77, "bh"], "\xcf" => [18, "bh"], "\xd0" => [77, "bl"], "\xd1" => [18, "bl"], "\xd2" => [77, "bm"], "\xd3" => [18, "bm"], "\xd4" => [77, "bn"], "\xd5" => [18, "bn"], "\xd6" => [77, "bp"], "\xd7" => [18, "bp"], "\xd8" => [77, "br"], "\xd9" => [18, "br"], "\xda" => [77, "bu"], "\xdb" => [18, "bu"], "\xdc" => [0, "b:"], "\xdd" => [0, "bB"], "\xde" => [0, "bC"], "\xdf" => [0, "bD"], "\xe0" => [0, "bE"], "\xe1" => [0, "bF"], "\xe2" => [0, "bG"], "\xe3" => [0, "bH"], "\xe4" => [0, "bI"], "\xe5" => [0, "bJ"], "\xe6" => [0, "bK"], "\xe7" => [0, "bL"], "\xe8" => [0, "bM"], "\xe9" => [0, "bN"], "\xea" => [0, "bO"], "\xeb" => [0, "bP"], "\xec" => [0, "bQ"], "\xed" => [0, "bR"], "\xee" => [0, "bS"], "\xef" => [0, "bT"], "\xf0" => [0, "bU"], "\xf1" => [0, "bV"], "\xf2" => [0, "bW"], "\xf3" => [0, "bY"], "\xf4" => [0, "bj"], "\xf5" => [0, "bk"], "\xf6" => [0, "bq"], "\xf7" => [0, "bv"], "\xf8" => [0, "bw"], "\xf9" => [0, "bx"], "\xfa" => [0, "by"], "\xfb" => [0, "bz"], "\xfc" => [82, "b"], "\xfd" => [87, "b"], "\xfe" => [130, "b"], "\xff" => [9, "b"]], ["\x00" => [94, "c0"], "\x01" => [76, "c0"], "\x02" => [104, "c0"], "\x03" => [16, "c0"], "\x04" => [94, "c1"], "\x05" => [76, "c1"], "\x06" => [104, "c1"], "\x07" => [16, "c1"], "\x08" => [94, "c2"], "\t" => [76, "c2"], "\n" => [104, "c2"], "\v" => [16, "c2"], "\f" => [94, "ca"], "\r" => [76, "ca"], "\x0e" => [104, "ca"], "\x0f" => [16, "ca"], "\x10" => [94, "cc"], "\x11" => [76, "cc"], "\x12" => [104, "cc"], "\x13" => [16, "cc"], "\x14" => [94, "ce"], "\x15" => [76, "ce"], "\x16" => [104, "ce"], "\x17" => [16, "ce"], "\x18" => [94, "ci"], "\x19" => [76, "ci"], "\x1a" => [104, "ci"], "\x1b" => [16, "ci"], "\x1c" => [94, "co"], "\x1d" => [76, "co"], "\x1e" => [104, "co"], "\x1f" => [16, "co"], " " => [94, "cs"], "!" => [76, "cs"], "\"" => [104, "cs"], "#" => [16, "cs"], "\$" => [94, "ct"], "%" => [76, "ct"], "&" => [104, "ct"], "'" => [16, "ct"], "(" => [77, "c "], ")" => [18, "c "], "*" => [77, "c%"], "+" => [18, "c%"], "," => [77, "c-"], "-" => [18, "c-"], "." => [77, "c."], "/" => [18, "c."], [77, "c/"], [18, "c/"], [77, "c3"], [18, "c3"], [77, "c4"], [18, "c4"], [77, "c5"], [18, "c5"], [77, "c6"], [18, "c6"], ":" => [77, "c7"], ";" => [18, "c7"], "<" => [77, "c8"], "=" => [18, "c8"], ">" => [77, "c9"], "?" => [18, "c9"], "@" => [77, "c="], "A" => [18, "c="], "B" => [77, "cA"], "C" => [18, "cA"], "D" => [77, "c_"], "E" => [18, "c_"], "F" => [77, "cb"], "G" => [18, "cb"], "H" => [77, "cd"], "I" => [18, "cd"], "J" => [77, "cf"], "K" => [18, "cf"], "L" => [77, "cg"], "M" => [18, "cg"], "N" => [77, "ch"], "O" => [18, "ch"], "P" => [77, "cl"], "Q" => [18, "cl"], "R" => [77, "cm"], "S" => [18, "cm"], "T" => [77, "cn"], "U" => [18, "cn"], "V" => [77, "cp"], "W" => [18, "cp"], "X" => [77, "cr"], "Y" => [18, "cr"], "Z" => [77, "cu"], "[" => [18, "cu"], "\\" => [0, "c:"], "]" => [0, "cB"], "^" => [0, "cC"], "_" => [0, "cD"], "`" => [0, "cE"], "a" => [0, "cF"], "b" => [0, "cG"], "c" => [0, "cH"], "d" => [0, "cI"], "e" => [0, "cJ"], "f" => [0, "cK"], "g" => [0, "cL"], "h" => [0, "cM"], "i" => [0, "cN"], "j" => [0, "cO"], "k" => [0, "cP"], "l" => [0, "cQ"], "m" => [0, "cR"], "n" => [0, "cS"], "o" => [0, "cT"], "p" => [0, "cU"], "q" => [0, "cV"], "r" => [0, "cW"], "s" => [0, "cY"], "t" => [0, "cj"], "u" => [0, "ck"], "v" => [0, "cq"], "w" => [0, "cv"], "x" => [0, "cw"], "y" => [0, "cx"], "z" => [0, "cy"], "{" => [0, "cz"], "|" => [82, "c"], "}" => [87, "c"], "~" => [130, "c"], "" => [9, "c"], "\x80" => [94, "e0"], "\x81" => [76, "e0"], "\x82" => [104, "e0"], "\x83" => [16, "e0"], "\x84" => [94, "e1"], "\x85" => [76, "e1"], "\x86" => [104, "e1"], "\x87" => [16, "e1"], "\x88" => [94, "e2"], "\x89" => [76, "e2"], "\x8a" => [104, "e2"], "\x8b" => [16, "e2"], "\x8c" => [94, "ea"], "\x8d" => [76, "ea"], "\x8e" => [104, "ea"], "\x8f" => [16, "ea"], "\x90" => [94, "ec"], "\x91" => [76, "ec"], "\x92" => [104, "ec"], "\x93" => [16, "ec"], "\x94" => [94, "ee"], "\x95" => [76, "ee"], "\x96" => [104, "ee"], "\x97" => [16, "ee"], "\x98" => [94, "ei"], "\x99" => [76, "ei"], "\x9a" => [104, "ei"], "\x9b" => [16, "ei"], "\x9c" => [94, "eo"], "\x9d" => [76, "eo"], "\x9e" => [104, "eo"], "\x9f" => [16, "eo"], "\xa0" => [94, "es"], "\xa1" => [76, "es"], "\xa2" => [104, "es"], "\xa3" => [16, "es"], "\xa4" => [94, "et"], "\xa5" => [76, "et"], "\xa6" => [104, "et"], "\xa7" => [16, "et"], "\xa8" => [77, "e "], "\xa9" => [18, "e "], "\xaa" => [77, "e%"], "\xab" => [18, "e%"], "\xac" => [77, "e-"], "\xad" => [18, "e-"], "\xae" => [77, "e."], "\xaf" => [18, "e."], "\xb0" => [77, "e/"], "\xb1" => [18, "e/"], "\xb2" => [77, "e3"], "\xb3" => [18, "e3"], "\xb4" => [77, "e4"], "\xb5" => [18, "e4"], "\xb6" => [77, "e5"], "\xb7" => [18, "e5"], "\xb8" => [77, "e6"], "\xb9" => [18, "e6"], "\xba" => [77, "e7"], "\xbb" => [18, "e7"], "\xbc" => [77, "e8"], "\xbd" => [18, "e8"], "\xbe" => [77, "e9"], "\xbf" => [18, "e9"], "\xc0" => [77, "e="], "\xc1" => [18, "e="], "\xc2" => [77, "eA"], "\xc3" => [18, "eA"], "\xc4" => [77, "e_"], "\xc5" => [18, "e_"], "\xc6" => [77, "eb"], "\xc7" => [18, "eb"], "\xc8" => [77, "ed"], "\xc9" => [18, "ed"], "\xca" => [77, "ef"], "\xcb" => [18, "ef"], "\xcc" => [77, "eg"], "\xcd" => [18, "eg"], "\xce" => [77, "eh"], "\xcf" => [18, "eh"], "\xd0" => [77, "el"], "\xd1" => [18, "el"], "\xd2" => [77, "em"], "\xd3" => [18, "em"], "\xd4" => [77, "en"], "\xd5" => [18, "en"], "\xd6" => [77, "ep"], "\xd7" => [18, "ep"], "\xd8" => [77, "er"], "\xd9" => [18, "er"], "\xda" => [77, "eu"], "\xdb" => [18, "eu"], "\xdc" => [0, "e:"], "\xdd" => [0, "eB"], "\xde" => [0, "eC"], "\xdf" => [0, "eD"], "\xe0" => [0, "eE"], "\xe1" => [0, "eF"], "\xe2" => [0, "eG"], "\xe3" => [0, "eH"], "\xe4" => [0, "eI"], "\xe5" => [0, "eJ"], "\xe6" => [0, "eK"], "\xe7" => [0, "eL"], "\xe8" => [0, "eM"], "\xe9" => [0, "eN"], "\xea" => [0, "eO"], "\xeb" => [0, "eP"], "\xec" => [0, "eQ"], "\xed" => [0, "eR"], "\xee" => [0, "eS"], "\xef" => [0, "eT"], "\xf0" => [0, "eU"], "\xf1" => [0, "eV"], "\xf2" => [0, "eW"], "\xf3" => [0, "eY"], "\xf4" => [0, "ej"], "\xf5" => [0, "ek"], "\xf6" => [0, "eq"], "\xf7" => [0, "ev"], "\xf8" => [0, "ew"], "\xf9" => [0, "ex"], "\xfa" => [0, "ey"], "\xfb" => [0, "ez"], "\xfc" => [82, "e"], "\xfd" => [87, "e"], "\xfe" => [130, "e"], "\xff" => [9, "e"]], ["\x00" => [77, "c0"], "\x01" => [18, "c0"], "\x02" => [77, "c1"], "\x03" => [18, "c1"], "\x04" => [77, "c2"], "\x05" => [18, "c2"], "\x06" => [77, "ca"], "\x07" => [18, "ca"], "\x08" => [77, "cc"], "\t" => [18, "cc"], "\n" => [77, "ce"], "\v" => [18, "ce"], "\f" => [77, "ci"], "\r" => [18, "ci"], "\x0e" => [77, "co"], "\x0f" => [18, "co"], "\x10" => [77, "cs"], "\x11" => [18, "cs"], "\x12" => [77, "ct"], "\x13" => [18, "ct"], "\x14" => [0, "c "], "\x15" => [0, "c%"], "\x16" => [0, "c-"], "\x17" => [0, "c."], "\x18" => [0, "c/"], "\x19" => [0, "c3"], "\x1a" => [0, "c4"], "\x1b" => [0, "c5"], "\x1c" => [0, "c6"], "\x1d" => [0, "c7"], "\x1e" => [0, "c8"], "\x1f" => [0, "c9"], " " => [0, "c="], "!" => [0, "cA"], "\"" => [0, "c_"], "#" => [0, "cb"], "\$" => [0, "cd"], "%" => [0, "cf"], "&" => [0, "cg"], "'" => [0, "ch"], "(" => [0, "cl"], ")" => [0, "cm"], "*" => [0, "cn"], "+" => [0, "cp"], "," => [0, "cr"], "-" => [0, "cu"], "." => [100, "c"], "/" => [110, "c"], [111, "c"], [115, "c"], [116, "c"], [118, "c"], [119, "c"], [122, "c"], [123, "c"], [125, "c"], [126, "c"], [129, "c"], ":" => [143, "c"], ";" => [148, "c"], "<" => [151, "c"], "=" => [153, "c"], ">" => [83, "c"], "?" => [10, "c"], "@" => [77, "e0"], "A" => [18, "e0"], "B" => [77, "e1"], "C" => [18, "e1"], "D" => [77, "e2"], "E" => [18, "e2"], "F" => [77, "ea"], "G" => [18, "ea"], "H" => [77, "ec"], "I" => [18, "ec"], "J" => [77, "ee"], "K" => [18, "ee"], "L" => [77, "ei"], "M" => [18, "ei"], "N" => [77, "eo"], "O" => [18, "eo"], "P" => [77, "es"], "Q" => [18, "es"], "R" => [77, "et"], "S" => [18, "et"], "T" => [0, "e "], "U" => [0, "e%"], "V" => [0, "e-"], "W" => [0, "e."], "X" => [0, "e/"], "Y" => [0, "e3"], "Z" => [0, "e4"], "[" => [0, "e5"], "\\" => [0, "e6"], "]" => [0, "e7"], "^" => [0, "e8"], "_" => [0, "e9"], "`" => [0, "e="], "a" => [0, "eA"], "b" => [0, "e_"], "c" => [0, "eb"], "d" => [0, "ed"], "e" => [0, "ef"], "f" => [0, "eg"], "g" => [0, "eh"], "h" => [0, "el"], "i" => [0, "em"], "j" => [0, "en"], "k" => [0, "ep"], "l" => [0, "er"], "m" => [0, "eu"], "n" => [100, "e"], "o" => [110, "e"], "p" => [111, "e"], "q" => [115, "e"], "r" => [116, "e"], "s" => [118, "e"], "t" => [119, "e"], "u" => [122, "e"], "v" => [123, "e"], "w" => [125, "e"], "x" => [126, "e"], "y" => [129, "e"], "z" => [143, "e"], "{" => [148, "e"], "|" => [151, "e"], "}" => [153, "e"], "~" => [83, "e"], "" => [10, "e"], "\x80" => [77, "i0"], "\x81" => [18, "i0"], "\x82" => [77, "i1"], "\x83" => [18, "i1"], "\x84" => [77, "i2"], "\x85" => [18, "i2"], "\x86" => [77, "ia"], "\x87" => [18, "ia"], "\x88" => [77, "ic"], "\x89" => [18, "ic"], "\x8a" => [77, "ie"], "\x8b" => [18, "ie"], "\x8c" => [77, "ii"], "\x8d" => [18, "ii"], "\x8e" => [77, "io"], "\x8f" => [18, "io"], "\x90" => [77, "is"], "\x91" => [18, "is"], "\x92" => [77, "it"], "\x93" => [18, "it"], "\x94" => [0, "i "], "\x95" => [0, "i%"], "\x96" => [0, "i-"], "\x97" => [0, "i."], "\x98" => [0, "i/"], "\x99" => [0, "i3"], "\x9a" => [0, "i4"], "\x9b" => [0, "i5"], "\x9c" => [0, "i6"], "\x9d" => [0, "i7"], "\x9e" => [0, "i8"], "\x9f" => [0, "i9"], "\xa0" => [0, "i="], "\xa1" => [0, "iA"], "\xa2" => [0, "i_"], "\xa3" => [0, "ib"], "\xa4" => [0, "id"], "\xa5" => [0, "if"], "\xa6" => [0, "ig"], "\xa7" => [0, "ih"], "\xa8" => [0, "il"], "\xa9" => [0, "im"], "\xaa" => [0, "in"], "\xab" => [0, "ip"], "\xac" => [0, "ir"], "\xad" => [0, "iu"], "\xae" => [100, "i"], "\xaf" => [110, "i"], "\xb0" => [111, "i"], "\xb1" => [115, "i"], "\xb2" => [116, "i"], "\xb3" => [118, "i"], "\xb4" => [119, "i"], "\xb5" => [122, "i"], "\xb6" => [123, "i"], "\xb7" => [125, "i"], "\xb8" => [126, "i"], "\xb9" => [129, "i"], "\xba" => [143, "i"], "\xbb" => [148, "i"], "\xbc" => [151, "i"], "\xbd" => [153, "i"], "\xbe" => [83, "i"], "\xbf" => [10, "i"], "\xc0" => [77, "o0"], "\xc1" => [18, "o0"], "\xc2" => [77, "o1"], "\xc3" => [18, "o1"], "\xc4" => [77, "o2"], "\xc5" => [18, "o2"], "\xc6" => [77, "oa"], "\xc7" => [18, "oa"], "\xc8" => [77, "oc"], "\xc9" => [18, "oc"], "\xca" => [77, "oe"], "\xcb" => [18, "oe"], "\xcc" => [77, "oi"], "\xcd" => [18, "oi"], "\xce" => [77, "oo"], "\xcf" => [18, "oo"], "\xd0" => [77, "os"], "\xd1" => [18, "os"], "\xd2" => [77, "ot"], "\xd3" => [18, "ot"], "\xd4" => [0, "o "], "\xd5" => [0, "o%"], "\xd6" => [0, "o-"], "\xd7" => [0, "o."], "\xd8" => [0, "o/"], "\xd9" => [0, "o3"], "\xda" => [0, "o4"], "\xdb" => [0, "o5"], "\xdc" => [0, "o6"], "\xdd" => [0, "o7"], "\xde" => [0, "o8"], "\xdf" => [0, "o9"], "\xe0" => [0, "o="], "\xe1" => [0, "oA"], "\xe2" => [0, "o_"], "\xe3" => [0, "ob"], "\xe4" => [0, "od"], "\xe5" => [0, "of"], "\xe6" => [0, "og"], "\xe7" => [0, "oh"], "\xe8" => [0, "ol"], "\xe9" => [0, "om"], "\xea" => [0, "on"], "\xeb" => [0, "op"], "\xec" => [0, "or"], "\xed" => [0, "ou"], "\xee" => [100, "o"], "\xef" => [110, "o"], "\xf0" => [111, "o"], "\xf1" => [115, "o"], "\xf2" => [116, "o"], "\xf3" => [118, "o"], "\xf4" => [119, "o"], "\xf5" => [122, "o"], "\xf6" => [123, "o"], "\xf7" => [125, "o"], "\xf8" => [126, "o"], "\xf9" => [129, "o"], "\xfa" => [143, "o"], "\xfb" => [148, "o"], "\xfc" => [151, "o"], "\xfd" => [153, "o"], "\xfe" => [83, "o"], "\xff" => [10, "o"]], ["\x00" => [94, "d0"], "\x01" => [76, "d0"], "\x02" => [104, "d0"], "\x03" => [16, "d0"], "\x04" => [94, "d1"], "\x05" => [76, "d1"], "\x06" => [104, "d1"], "\x07" => [16, "d1"], "\x08" => [94, "d2"], "\t" => [76, "d2"], "\n" => [104, "d2"], "\v" => [16, "d2"], "\f" => [94, "da"], "\r" => [76, "da"], "\x0e" => [104, "da"], "\x0f" => [16, "da"], "\x10" => [94, "dc"], "\x11" => [76, "dc"], "\x12" => [104, "dc"], "\x13" => [16, "dc"], "\x14" => [94, "de"], "\x15" => [76, "de"], "\x16" => [104, "de"], "\x17" => [16, "de"], "\x18" => [94, "di"], "\x19" => [76, "di"], "\x1a" => [104, "di"], "\x1b" => [16, "di"], "\x1c" => [94, "do"], "\x1d" => [76, "do"], "\x1e" => [104, "do"], "\x1f" => [16, "do"], " " => [94, "ds"], "!" => [76, "ds"], "\"" => [104, "ds"], "#" => [16, "ds"], "\$" => [94, "dt"], "%" => [76, "dt"], "&" => [104, "dt"], "'" => [16, "dt"], "(" => [77, "d "], ")" => [18, "d "], "*" => [77, "d%"], "+" => [18, "d%"], "," => [77, "d-"], "-" => [18, "d-"], "." => [77, "d."], "/" => [18, "d."], [77, "d/"], [18, "d/"], [77, "d3"], [18, "d3"], [77, "d4"], [18, "d4"], [77, "d5"], [18, "d5"], [77, "d6"], [18, "d6"], ":" => [77, "d7"], ";" => [18, "d7"], "<" => [77, "d8"], "=" => [18, "d8"], ">" => [77, "d9"], "?" => [18, "d9"], "@" => [77, "d="], "A" => [18, "d="], "B" => [77, "dA"], "C" => [18, "dA"], "D" => [77, "d_"], "E" => [18, "d_"], "F" => [77, "db"], "G" => [18, "db"], "H" => [77, "dd"], "I" => [18, "dd"], "J" => [77, "df"], "K" => [18, "df"], "L" => [77, "dg"], "M" => [18, "dg"], "N" => [77, "dh"], "O" => [18, "dh"], "P" => [77, "dl"], "Q" => [18, "dl"], "R" => [77, "dm"], "S" => [18, "dm"], "T" => [77, "dn"], "U" => [18, "dn"], "V" => [77, "dp"], "W" => [18, "dp"], "X" => [77, "dr"], "Y" => [18, "dr"], "Z" => [77, "du"], "[" => [18, "du"], "\\" => [0, "d:"], "]" => [0, "dB"], "^" => [0, "dC"], "_" => [0, "dD"], "`" => [0, "dE"], "a" => [0, "dF"], "b" => [0, "dG"], "c" => [0, "dH"], "d" => [0, "dI"], "e" => [0, "dJ"], "f" => [0, "dK"], "g" => [0, "dL"], "h" => [0, "dM"], "i" => [0, "dN"], "j" => [0, "dO"], "k" => [0, "dP"], "l" => [0, "dQ"], "m" => [0, "dR"], "n" => [0, "dS"], "o" => [0, "dT"], "p" => [0, "dU"], "q" => [0, "dV"], "r" => [0, "dW"], "s" => [0, "dY"], "t" => [0, "dj"], "u" => [0, "dk"], "v" => [0, "dq"], "w" => [0, "dv"], "x" => [0, "dw"], "y" => [0, "dx"], "z" => [0, "dy"], "{" => [0, "dz"], "|" => [82, "d"], "}" => [87, "d"], "~" => [130, "d"], "" => [9, "d"], "\x80" => [94, "f0"], "\x81" => [76, "f0"], "\x82" => [104, "f0"], "\x83" => [16, "f0"], "\x84" => [94, "f1"], "\x85" => [76, "f1"], "\x86" => [104, "f1"], "\x87" => [16, "f1"], "\x88" => [94, "f2"], "\x89" => [76, "f2"], "\x8a" => [104, "f2"], "\x8b" => [16, "f2"], "\x8c" => [94, "fa"], "\x8d" => [76, "fa"], "\x8e" => [104, "fa"], "\x8f" => [16, "fa"], "\x90" => [94, "fc"], "\x91" => [76, "fc"], "\x92" => [104, "fc"], "\x93" => [16, "fc"], "\x94" => [94, "fe"], "\x95" => [76, "fe"], "\x96" => [104, "fe"], "\x97" => [16, "fe"], "\x98" => [94, "fi"], "\x99" => [76, "fi"], "\x9a" => [104, "fi"], "\x9b" => [16, "fi"], "\x9c" => [94, "fo"], "\x9d" => [76, "fo"], "\x9e" => [104, "fo"], "\x9f" => [16, "fo"], "\xa0" => [94, "fs"], "\xa1" => [76, "fs"], "\xa2" => [104, "fs"], "\xa3" => [16, "fs"], "\xa4" => [94, "ft"], "\xa5" => [76, "ft"], "\xa6" => [104, "ft"], "\xa7" => [16, "ft"], "\xa8" => [77, "f "], "\xa9" => [18, "f "], "\xaa" => [77, "f%"], "\xab" => [18, "f%"], "\xac" => [77, "f-"], "\xad" => [18, "f-"], "\xae" => [77, "f."], "\xaf" => [18, "f."], "\xb0" => [77, "f/"], "\xb1" => [18, "f/"], "\xb2" => [77, "f3"], "\xb3" => [18, "f3"], "\xb4" => [77, "f4"], "\xb5" => [18, "f4"], "\xb6" => [77, "f5"], "\xb7" => [18, "f5"], "\xb8" => [77, "f6"], "\xb9" => [18, "f6"], "\xba" => [77, "f7"], "\xbb" => [18, "f7"], "\xbc" => [77, "f8"], "\xbd" => [18, "f8"], "\xbe" => [77, "f9"], "\xbf" => [18, "f9"], "\xc0" => [77, "f="], "\xc1" => [18, "f="], "\xc2" => [77, "fA"], "\xc3" => [18, "fA"], "\xc4" => [77, "f_"], "\xc5" => [18, "f_"], "\xc6" => [77, "fb"], "\xc7" => [18, "fb"], "\xc8" => [77, "fd"], "\xc9" => [18, "fd"], "\xca" => [77, "ff"], "\xcb" => [18, "ff"], "\xcc" => [77, "fg"], "\xcd" => [18, "fg"], "\xce" => [77, "fh"], "\xcf" => [18, "fh"], "\xd0" => [77, "fl"], "\xd1" => [18, "fl"], "\xd2" => [77, "fm"], "\xd3" => [18, "fm"], "\xd4" => [77, "fn"], "\xd5" => [18, "fn"], "\xd6" => [77, "fp"], "\xd7" => [18, "fp"], "\xd8" => [77, "fr"], "\xd9" => [18, "fr"], "\xda" => [77, "fu"], "\xdb" => [18, "fu"], "\xdc" => [0, "f:"], "\xdd" => [0, "fB"], "\xde" => [0, "fC"], "\xdf" => [0, "fD"], "\xe0" => [0, "fE"], "\xe1" => [0, "fF"], "\xe2" => [0, "fG"], "\xe3" => [0, "fH"], "\xe4" => [0, "fI"], "\xe5" => [0, "fJ"], "\xe6" => [0, "fK"], "\xe7" => [0, "fL"], "\xe8" => [0, "fM"], "\xe9" => [0, "fN"], "\xea" => [0, "fO"], "\xeb" => [0, "fP"], "\xec" => [0, "fQ"], "\xed" => [0, "fR"], "\xee" => [0, "fS"], "\xef" => [0, "fT"], "\xf0" => [0, "fU"], "\xf1" => [0, "fV"], "\xf2" => [0, "fW"], "\xf3" => [0, "fY"], "\xf4" => [0, "fj"], "\xf5" => [0, "fk"], "\xf6" => [0, "fq"], "\xf7" => [0, "fv"], "\xf8" => [0, "fw"], "\xf9" => [0, "fx"], "\xfa" => [0, "fy"], "\xfb" => [0, "fz"], "\xfc" => [82, "f"], "\xfd" => [87, "f"], "\xfe" => [130, "f"], "\xff" => [9, "f"]], ["\x00" => [77, "d0"], "\x01" => [18, "d0"], "\x02" => [77, "d1"], "\x03" => [18, "d1"], "\x04" => [77, "d2"], "\x05" => [18, "d2"], "\x06" => [77, "da"], "\x07" => [18, "da"], "\x08" => [77, "dc"], "\t" => [18, "dc"], "\n" => [77, "de"], "\v" => [18, "de"], "\f" => [77, "di"], "\r" => [18, "di"], "\x0e" => [77, "do"], "\x0f" => [18, "do"], "\x10" => [77, "ds"], "\x11" => [18, "ds"], "\x12" => [77, "dt"], "\x13" => [18, "dt"], "\x14" => [0, "d "], "\x15" => [0, "d%"], "\x16" => [0, "d-"], "\x17" => [0, "d."], "\x18" => [0, "d/"], "\x19" => [0, "d3"], "\x1a" => [0, "d4"], "\x1b" => [0, "d5"], "\x1c" => [0, "d6"], "\x1d" => [0, "d7"], "\x1e" => [0, "d8"], "\x1f" => [0, "d9"], " " => [0, "d="], "!" => [0, "dA"], "\"" => [0, "d_"], "#" => [0, "db"], "\$" => [0, "dd"], "%" => [0, "df"], "&" => [0, "dg"], "'" => [0, "dh"], "(" => [0, "dl"], ")" => [0, "dm"], "*" => [0, "dn"], "+" => [0, "dp"], "," => [0, "dr"], "-" => [0, "du"], "." => [100, "d"], "/" => [110, "d"], [111, "d"], [115, "d"], [116, "d"], [118, "d"], [119, "d"], [122, "d"], [123, "d"], [125, "d"], [126, "d"], [129, "d"], ":" => [143, "d"], ";" => [148, "d"], "<" => [151, "d"], "=" => [153, "d"], ">" => [83, "d"], "?" => [10, "d"], "@" => [77, "f0"], "A" => [18, "f0"], "B" => [77, "f1"], "C" => [18, "f1"], "D" => [77, "f2"], "E" => [18, "f2"], "F" => [77, "fa"], "G" => [18, "fa"], "H" => [77, "fc"], "I" => [18, "fc"], "J" => [77, "fe"], "K" => [18, "fe"], "L" => [77, "fi"], "M" => [18, "fi"], "N" => [77, "fo"], "O" => [18, "fo"], "P" => [77, "fs"], "Q" => [18, "fs"], "R" => [77, "ft"], "S" => [18, "ft"], "T" => [0, "f "], "U" => [0, "f%"], "V" => [0, "f-"], "W" => [0, "f."], "X" => [0, "f/"], "Y" => [0, "f3"], "Z" => [0, "f4"], "[" => [0, "f5"], "\\" => [0, "f6"], "]" => [0, "f7"], "^" => [0, "f8"], "_" => [0, "f9"], "`" => [0, "f="], "a" => [0, "fA"], "b" => [0, "f_"], "c" => [0, "fb"], "d" => [0, "fd"], "e" => [0, "ff"], "f" => [0, "fg"], "g" => [0, "fh"], "h" => [0, "fl"], "i" => [0, "fm"], "j" => [0, "fn"], "k" => [0, "fp"], "l" => [0, "fr"], "m" => [0, "fu"], "n" => [100, "f"], "o" => [110, "f"], "p" => [111, "f"], "q" => [115, "f"], "r" => [116, "f"], "s" => [118, "f"], "t" => [119, "f"], "u" => [122, "f"], "v" => [123, "f"], "w" => [125, "f"], "x" => [126, "f"], "y" => [129, "f"], "z" => [143, "f"], "{" => [148, "f"], "|" => [151, "f"], "}" => [153, "f"], "~" => [83, "f"], "" => [10, "f"], "\x80" => [77, "g0"], "\x81" => [18, "g0"], "\x82" => [77, "g1"], "\x83" => [18, "g1"], "\x84" => [77, "g2"], "\x85" => [18, "g2"], "\x86" => [77, "ga"], "\x87" => [18, "ga"], "\x88" => [77, "gc"], "\x89" => [18, "gc"], "\x8a" => [77, "ge"], "\x8b" => [18, "ge"], "\x8c" => [77, "gi"], "\x8d" => [18, "gi"], "\x8e" => [77, "go"], "\x8f" => [18, "go"], "\x90" => [77, "gs"], "\x91" => [18, "gs"], "\x92" => [77, "gt"], "\x93" => [18, "gt"], "\x94" => [0, "g "], "\x95" => [0, "g%"], "\x96" => [0, "g-"], "\x97" => [0, "g."], "\x98" => [0, "g/"], "\x99" => [0, "g3"], "\x9a" => [0, "g4"], "\x9b" => [0, "g5"], "\x9c" => [0, "g6"], "\x9d" => [0, "g7"], "\x9e" => [0, "g8"], "\x9f" => [0, "g9"], "\xa0" => [0, "g="], "\xa1" => [0, "gA"], "\xa2" => [0, "g_"], "\xa3" => [0, "gb"], "\xa4" => [0, "gd"], "\xa5" => [0, "gf"], "\xa6" => [0, "gg"], "\xa7" => [0, "gh"], "\xa8" => [0, "gl"], "\xa9" => [0, "gm"], "\xaa" => [0, "gn"], "\xab" => [0, "gp"], "\xac" => [0, "gr"], "\xad" => [0, "gu"], "\xae" => [100, "g"], "\xaf" => [110, "g"], "\xb0" => [111, "g"], "\xb1" => [115, "g"], "\xb2" => [116, "g"], "\xb3" => [118, "g"], "\xb4" => [119, "g"], "\xb5" => [122, "g"], "\xb6" => [123, "g"], "\xb7" => [125, "g"], "\xb8" => [126, "g"], "\xb9" => [129, "g"], "\xba" => [143, "g"], "\xbb" => [148, "g"], "\xbc" => [151, "g"], "\xbd" => [153, "g"], "\xbe" => [83, "g"], "\xbf" => [10, "g"], "\xc0" => [77, "h0"], "\xc1" => [18, "h0"], "\xc2" => [77, "h1"], "\xc3" => [18, "h1"], "\xc4" => [77, "h2"], "\xc5" => [18, "h2"], "\xc6" => [77, "ha"], "\xc7" => [18, "ha"], "\xc8" => [77, "hc"], "\xc9" => [18, "hc"], "\xca" => [77, "he"], "\xcb" => [18, "he"], "\xcc" => [77, "hi"], "\xcd" => [18, "hi"], "\xce" => [77, "ho"], "\xcf" => [18, "ho"], "\xd0" => [77, "hs"], "\xd1" => [18, "hs"], "\xd2" => [77, "ht"], "\xd3" => [18, "ht"], "\xd4" => [0, "h "], "\xd5" => [0, "h%"], "\xd6" => [0, "h-"], "\xd7" => [0, "h."], "\xd8" => [0, "h/"], "\xd9" => [0, "h3"], "\xda" => [0, "h4"], "\xdb" => [0, "h5"], "\xdc" => [0, "h6"], "\xdd" => [0, "h7"], "\xde" => [0, "h8"], "\xdf" => [0, "h9"], "\xe0" => [0, "h="], "\xe1" => [0, "hA"], "\xe2" => [0, "h_"], "\xe3" => [0, "hb"], "\xe4" => [0, "hd"], "\xe5" => [0, "hf"], "\xe6" => [0, "hg"], "\xe7" => [0, "hh"], "\xe8" => [0, "hl"], "\xe9" => [0, "hm"], "\xea" => [0, "hn"], "\xeb" => [0, "hp"], "\xec" => [0, "hr"], "\xed" => [0, "hu"], "\xee" => [100, "h"], "\xef" => [110, "h"], "\xf0" => [111, "h"], "\xf1" => [115, "h"], "\xf2" => [116, "h"], "\xf3" => [118, "h"], "\xf4" => [119, "h"], "\xf5" => [122, "h"], "\xf6" => [123, "h"], "\xf7" => [125, "h"], "\xf8" => [126, "h"], "\xf9" => [129, "h"], "\xfa" => [143, "h"], "\xfb" => [148, "h"], "\xfc" => [151, "h"], "\xfd" => [153, "h"], "\xfe" => [83, "h"], "\xff" => [10, "h"]], ["\x00" => [94, "g0"], "\x01" => [76, "g0"], "\x02" => [104, "g0"], "\x03" => [16, "g0"], "\x04" => [94, "g1"], "\x05" => [76, "g1"], "\x06" => [104, "g1"], "\x07" => [16, "g1"], "\x08" => [94, "g2"], "\t" => [76, "g2"], "\n" => [104, "g2"], "\v" => [16, "g2"], "\f" => [94, "ga"], "\r" => [76, "ga"], "\x0e" => [104, "ga"], "\x0f" => [16, "ga"], "\x10" => [94, "gc"], "\x11" => [76, "gc"], "\x12" => [104, "gc"], "\x13" => [16, "gc"], "\x14" => [94, "ge"], "\x15" => [76, "ge"], "\x16" => [104, "ge"], "\x17" => [16, "ge"], "\x18" => [94, "gi"], "\x19" => [76, "gi"], "\x1a" => [104, "gi"], "\x1b" => [16, "gi"], "\x1c" => [94, "go"], "\x1d" => [76, "go"], "\x1e" => [104, "go"], "\x1f" => [16, "go"], " " => [94, "gs"], "!" => [76, "gs"], "\"" => [104, "gs"], "#" => [16, "gs"], "\$" => [94, "gt"], "%" => [76, "gt"], "&" => [104, "gt"], "'" => [16, "gt"], "(" => [77, "g "], ")" => [18, "g "], "*" => [77, "g%"], "+" => [18, "g%"], "," => [77, "g-"], "-" => [18, "g-"], "." => [77, "g."], "/" => [18, "g."], [77, "g/"], [18, "g/"], [77, "g3"], [18, "g3"], [77, "g4"], [18, "g4"], [77, "g5"], [18, "g5"], [77, "g6"], [18, "g6"], ":" => [77, "g7"], ";" => [18, "g7"], "<" => [77, "g8"], "=" => [18, "g8"], ">" => [77, "g9"], "?" => [18, "g9"], "@" => [77, "g="], "A" => [18, "g="], "B" => [77, "gA"], "C" => [18, "gA"], "D" => [77, "g_"], "E" => [18, "g_"], "F" => [77, "gb"], "G" => [18, "gb"], "H" => [77, "gd"], "I" => [18, "gd"], "J" => [77, "gf"], "K" => [18, "gf"], "L" => [77, "gg"], "M" => [18, "gg"], "N" => [77, "gh"], "O" => [18, "gh"], "P" => [77, "gl"], "Q" => [18, "gl"], "R" => [77, "gm"], "S" => [18, "gm"], "T" => [77, "gn"], "U" => [18, "gn"], "V" => [77, "gp"], "W" => [18, "gp"], "X" => [77, "gr"], "Y" => [18, "gr"], "Z" => [77, "gu"], "[" => [18, "gu"], "\\" => [0, "g:"], "]" => [0, "gB"], "^" => [0, "gC"], "_" => [0, "gD"], "`" => [0, "gE"], "a" => [0, "gF"], "b" => [0, "gG"], "c" => [0, "gH"], "d" => [0, "gI"], "e" => [0, "gJ"], "f" => [0, "gK"], "g" => [0, "gL"], "h" => [0, "gM"], "i" => [0, "gN"], "j" => [0, "gO"], "k" => [0, "gP"], "l" => [0, "gQ"], "m" => [0, "gR"], "n" => [0, "gS"], "o" => [0, "gT"], "p" => [0, "gU"], "q" => [0, "gV"], "r" => [0, "gW"], "s" => [0, "gY"], "t" => [0, "gj"], "u" => [0, "gk"], "v" => [0, "gq"], "w" => [0, "gv"], "x" => [0, "gw"], "y" => [0, "gx"], "z" => [0, "gy"], "{" => [0, "gz"], "|" => [82, "g"], "}" => [87, "g"], "~" => [130, "g"], "" => [9, "g"], "\x80" => [94, "h0"], "\x81" => [76, "h0"], "\x82" => [104, "h0"], "\x83" => [16, "h0"], "\x84" => [94, "h1"], "\x85" => [76, "h1"], "\x86" => [104, "h1"], "\x87" => [16, "h1"], "\x88" => [94, "h2"], "\x89" => [76, "h2"], "\x8a" => [104, "h2"], "\x8b" => [16, "h2"], "\x8c" => [94, "ha"], "\x8d" => [76, "ha"], "\x8e" => [104, "ha"], "\x8f" => [16, "ha"], "\x90" => [94, "hc"], "\x91" => [76, "hc"], "\x92" => [104, "hc"], "\x93" => [16, "hc"], "\x94" => [94, "he"], "\x95" => [76, "he"], "\x96" => [104, "he"], "\x97" => [16, "he"], "\x98" => [94, "hi"], "\x99" => [76, "hi"], "\x9a" => [104, "hi"], "\x9b" => [16, "hi"], "\x9c" => [94, "ho"], "\x9d" => [76, "ho"], "\x9e" => [104, "ho"], "\x9f" => [16, "ho"], "\xa0" => [94, "hs"], "\xa1" => [76, "hs"], "\xa2" => [104, "hs"], "\xa3" => [16, "hs"], "\xa4" => [94, "ht"], "\xa5" => [76, "ht"], "\xa6" => [104, "ht"], "\xa7" => [16, "ht"], "\xa8" => [77, "h "], "\xa9" => [18, "h "], "\xaa" => [77, "h%"], "\xab" => [18, "h%"], "\xac" => [77, "h-"], "\xad" => [18, "h-"], "\xae" => [77, "h."], "\xaf" => [18, "h."], "\xb0" => [77, "h/"], "\xb1" => [18, "h/"], "\xb2" => [77, "h3"], "\xb3" => [18, "h3"], "\xb4" => [77, "h4"], "\xb5" => [18, "h4"], "\xb6" => [77, "h5"], "\xb7" => [18, "h5"], "\xb8" => [77, "h6"], "\xb9" => [18, "h6"], "\xba" => [77, "h7"], "\xbb" => [18, "h7"], "\xbc" => [77, "h8"], "\xbd" => [18, "h8"], "\xbe" => [77, "h9"], "\xbf" => [18, "h9"], "\xc0" => [77, "h="], "\xc1" => [18, "h="], "\xc2" => [77, "hA"], "\xc3" => [18, "hA"], "\xc4" => [77, "h_"], "\xc5" => [18, "h_"], "\xc6" => [77, "hb"], "\xc7" => [18, "hb"], "\xc8" => [77, "hd"], "\xc9" => [18, "hd"], "\xca" => [77, "hf"], "\xcb" => [18, "hf"], "\xcc" => [77, "hg"], "\xcd" => [18, "hg"], "\xce" => [77, "hh"], "\xcf" => [18, "hh"], "\xd0" => [77, "hl"], "\xd1" => [18, "hl"], "\xd2" => [77, "hm"], "\xd3" => [18, "hm"], "\xd4" => [77, "hn"], "\xd5" => [18, "hn"], "\xd6" => [77, "hp"], "\xd7" => [18, "hp"], "\xd8" => [77, "hr"], "\xd9" => [18, "hr"], "\xda" => [77, "hu"], "\xdb" => [18, "hu"], "\xdc" => [0, "h:"], "\xdd" => [0, "hB"], "\xde" => [0, "hC"], "\xdf" => [0, "hD"], "\xe0" => [0, "hE"], "\xe1" => [0, "hF"], "\xe2" => [0, "hG"], "\xe3" => [0, "hH"], "\xe4" => [0, "hI"], "\xe5" => [0, "hJ"], "\xe6" => [0, "hK"], "\xe7" => [0, "hL"], "\xe8" => [0, "hM"], "\xe9" => [0, "hN"], "\xea" => [0, "hO"], "\xeb" => [0, "hP"], "\xec" => [0, "hQ"], "\xed" => [0, "hR"], "\xee" => [0, "hS"], "\xef" => [0, "hT"], "\xf0" => [0, "hU"], "\xf1" => [0, "hV"], "\xf2" => [0, "hW"], "\xf3" => [0, "hY"], "\xf4" => [0, "hj"], "\xf5" => [0, "hk"], "\xf6" => [0, "hq"], "\xf7" => [0, "hv"], "\xf8" => [0, "hw"], "\xf9" => [0, "hx"], "\xfa" => [0, "hy"], "\xfb" => [0, "hz"], "\xfc" => [82, "h"], "\xfd" => [87, "h"], "\xfe" => [130, "h"], "\xff" => [9, "h"]], ["\x00" => [94, "i0"], "\x01" => [76, "i0"], "\x02" => [104, "i0"], "\x03" => [16, "i0"], "\x04" => [94, "i1"], "\x05" => [76, "i1"], "\x06" => [104, "i1"], "\x07" => [16, "i1"], "\x08" => [94, "i2"], "\t" => [76, "i2"], "\n" => [104, "i2"], "\v" => [16, "i2"], "\f" => [94, "ia"], "\r" => [76, "ia"], "\x0e" => [104, "ia"], "\x0f" => [16, "ia"], "\x10" => [94, "ic"], "\x11" => [76, "ic"], "\x12" => [104, "ic"], "\x13" => [16, "ic"], "\x14" => [94, "ie"], "\x15" => [76, "ie"], "\x16" => [104, "ie"], "\x17" => [16, "ie"], "\x18" => [94, "ii"], "\x19" => [76, "ii"], "\x1a" => [104, "ii"], "\x1b" => [16, "ii"], "\x1c" => [94, "io"], "\x1d" => [76, "io"], "\x1e" => [104, "io"], "\x1f" => [16, "io"], " " => [94, "is"], "!" => [76, "is"], "\"" => [104, "is"], "#" => [16, "is"], "\$" => [94, "it"], "%" => [76, "it"], "&" => [104, "it"], "'" => [16, "it"], "(" => [77, "i "], ")" => [18, "i "], "*" => [77, "i%"], "+" => [18, "i%"], "," => [77, "i-"], "-" => [18, "i-"], "." => [77, "i."], "/" => [18, "i."], [77, "i/"], [18, "i/"], [77, "i3"], [18, "i3"], [77, "i4"], [18, "i4"], [77, "i5"], [18, "i5"], [77, "i6"], [18, "i6"], ":" => [77, "i7"], ";" => [18, "i7"], "<" => [77, "i8"], "=" => [18, "i8"], ">" => [77, "i9"], "?" => [18, "i9"], "@" => [77, "i="], "A" => [18, "i="], "B" => [77, "iA"], "C" => [18, "iA"], "D" => [77, "i_"], "E" => [18, "i_"], "F" => [77, "ib"], "G" => [18, "ib"], "H" => [77, "id"], "I" => [18, "id"], "J" => [77, "if"], "K" => [18, "if"], "L" => [77, "ig"], "M" => [18, "ig"], "N" => [77, "ih"], "O" => [18, "ih"], "P" => [77, "il"], "Q" => [18, "il"], "R" => [77, "im"], "S" => [18, "im"], "T" => [77, "in"], "U" => [18, "in"], "V" => [77, "ip"], "W" => [18, "ip"], "X" => [77, "ir"], "Y" => [18, "ir"], "Z" => [77, "iu"], "[" => [18, "iu"], "\\" => [0, "i:"], "]" => [0, "iB"], "^" => [0, "iC"], "_" => [0, "iD"], "`" => [0, "iE"], "a" => [0, "iF"], "b" => [0, "iG"], "c" => [0, "iH"], "d" => [0, "iI"], "e" => [0, "iJ"], "f" => [0, "iK"], "g" => [0, "iL"], "h" => [0, "iM"], "i" => [0, "iN"], "j" => [0, "iO"], "k" => [0, "iP"], "l" => [0, "iQ"], "m" => [0, "iR"], "n" => [0, "iS"], "o" => [0, "iT"], "p" => [0, "iU"], "q" => [0, "iV"], "r" => [0, "iW"], "s" => [0, "iY"], "t" => [0, "ij"], "u" => [0, "ik"], "v" => [0, "iq"], "w" => [0, "iv"], "x" => [0, "iw"], "y" => [0, "ix"], "z" => [0, "iy"], "{" => [0, "iz"], "|" => [82, "i"], "}" => [87, "i"], "~" => [130, "i"], "" => [9, "i"], "\x80" => [94, "o0"], "\x81" => [76, "o0"], "\x82" => [104, "o0"], "\x83" => [16, "o0"], "\x84" => [94, "o1"], "\x85" => [76, "o1"], "\x86" => [104, "o1"], "\x87" => [16, "o1"], "\x88" => [94, "o2"], "\x89" => [76, "o2"], "\x8a" => [104, "o2"], "\x8b" => [16, "o2"], "\x8c" => [94, "oa"], "\x8d" => [76, "oa"], "\x8e" => [104, "oa"], "\x8f" => [16, "oa"], "\x90" => [94, "oc"], "\x91" => [76, "oc"], "\x92" => [104, "oc"], "\x93" => [16, "oc"], "\x94" => [94, "oe"], "\x95" => [76, "oe"], "\x96" => [104, "oe"], "\x97" => [16, "oe"], "\x98" => [94, "oi"], "\x99" => [76, "oi"], "\x9a" => [104, "oi"], "\x9b" => [16, "oi"], "\x9c" => [94, "oo"], "\x9d" => [76, "oo"], "\x9e" => [104, "oo"], "\x9f" => [16, "oo"], "\xa0" => [94, "os"], "\xa1" => [76, "os"], "\xa2" => [104, "os"], "\xa3" => [16, "os"], "\xa4" => [94, "ot"], "\xa5" => [76, "ot"], "\xa6" => [104, "ot"], "\xa7" => [16, "ot"], "\xa8" => [77, "o "], "\xa9" => [18, "o "], "\xaa" => [77, "o%"], "\xab" => [18, "o%"], "\xac" => [77, "o-"], "\xad" => [18, "o-"], "\xae" => [77, "o."], "\xaf" => [18, "o."], "\xb0" => [77, "o/"], "\xb1" => [18, "o/"], "\xb2" => [77, "o3"], "\xb3" => [18, "o3"], "\xb4" => [77, "o4"], "\xb5" => [18, "o4"], "\xb6" => [77, "o5"], "\xb7" => [18, "o5"], "\xb8" => [77, "o6"], "\xb9" => [18, "o6"], "\xba" => [77, "o7"], "\xbb" => [18, "o7"], "\xbc" => [77, "o8"], "\xbd" => [18, "o8"], "\xbe" => [77, "o9"], "\xbf" => [18, "o9"], "\xc0" => [77, "o="], "\xc1" => [18, "o="], "\xc2" => [77, "oA"], "\xc3" => [18, "oA"], "\xc4" => [77, "o_"], "\xc5" => [18, "o_"], "\xc6" => [77, "ob"], "\xc7" => [18, "ob"], "\xc8" => [77, "od"], "\xc9" => [18, "od"], "\xca" => [77, "of"], "\xcb" => [18, "of"], "\xcc" => [77, "og"], "\xcd" => [18, "og"], "\xce" => [77, "oh"], "\xcf" => [18, "oh"], "\xd0" => [77, "ol"], "\xd1" => [18, "ol"], "\xd2" => [77, "om"], "\xd3" => [18, "om"], "\xd4" => [77, "on"], "\xd5" => [18, "on"], "\xd6" => [77, "op"], "\xd7" => [18, "op"], "\xd8" => [77, "or"], "\xd9" => [18, "or"], "\xda" => [77, "ou"], "\xdb" => [18, "ou"], "\xdc" => [0, "o:"], "\xdd" => [0, "oB"], "\xde" => [0, "oC"], "\xdf" => [0, "oD"], "\xe0" => [0, "oE"], "\xe1" => [0, "oF"], "\xe2" => [0, "oG"], "\xe3" => [0, "oH"], "\xe4" => [0, "oI"], "\xe5" => [0, "oJ"], "\xe6" => [0, "oK"], "\xe7" => [0, "oL"], "\xe8" => [0, "oM"], "\xe9" => [0, "oN"], "\xea" => [0, "oO"], "\xeb" => [0, "oP"], "\xec" => [0, "oQ"], "\xed" => [0, "oR"], "\xee" => [0, "oS"], "\xef" => [0, "oT"], "\xf0" => [0, "oU"], "\xf1" => [0, "oV"], "\xf2" => [0, "oW"], "\xf3" => [0, "oY"], "\xf4" => [0, "oj"], "\xf5" => [0, "ok"], "\xf6" => [0, "oq"], "\xf7" => [0, "ov"], "\xf8" => [0, "ow"], "\xf9" => [0, "ox"], "\xfa" => [0, "oy"], "\xfb" => [0, "oz"], "\xfc" => [82, "o"], "\xfd" => [87, "o"], "\xfe" => [130, "o"], "\xff" => [9, "o"]], ["\x00" => [94, "j0"], "\x01" => [76, "j0"], "\x02" => [104, "j0"], "\x03" => [16, "j0"], "\x04" => [94, "j1"], "\x05" => [76, "j1"], "\x06" => [104, "j1"], "\x07" => [16, "j1"], "\x08" => [94, "j2"], "\t" => [76, "j2"], "\n" => [104, "j2"], "\v" => [16, "j2"], "\f" => [94, "ja"], "\r" => [76, "ja"], "\x0e" => [104, "ja"], "\x0f" => [16, "ja"], "\x10" => [94, "jc"], "\x11" => [76, "jc"], "\x12" => [104, "jc"], "\x13" => [16, "jc"], "\x14" => [94, "je"], "\x15" => [76, "je"], "\x16" => [104, "je"], "\x17" => [16, "je"], "\x18" => [94, "ji"], "\x19" => [76, "ji"], "\x1a" => [104, "ji"], "\x1b" => [16, "ji"], "\x1c" => [94, "jo"], "\x1d" => [76, "jo"], "\x1e" => [104, "jo"], "\x1f" => [16, "jo"], " " => [94, "js"], "!" => [76, "js"], "\"" => [104, "js"], "#" => [16, "js"], "\$" => [94, "jt"], "%" => [76, "jt"], "&" => [104, "jt"], "'" => [16, "jt"], "(" => [77, "j "], ")" => [18, "j "], "*" => [77, "j%"], "+" => [18, "j%"], "," => [77, "j-"], "-" => [18, "j-"], "." => [77, "j."], "/" => [18, "j."], [77, "j/"], [18, "j/"], [77, "j3"], [18, "j3"], [77, "j4"], [18, "j4"], [77, "j5"], [18, "j5"], [77, "j6"], [18, "j6"], ":" => [77, "j7"], ";" => [18, "j7"], "<" => [77, "j8"], "=" => [18, "j8"], ">" => [77, "j9"], "?" => [18, "j9"], "@" => [77, "j="], "A" => [18, "j="], "B" => [77, "jA"], "C" => [18, "jA"], "D" => [77, "j_"], "E" => [18, "j_"], "F" => [77, "jb"], "G" => [18, "jb"], "H" => [77, "jd"], "I" => [18, "jd"], "J" => [77, "jf"], "K" => [18, "jf"], "L" => [77, "jg"], "M" => [18, "jg"], "N" => [77, "jh"], "O" => [18, "jh"], "P" => [77, "jl"], "Q" => [18, "jl"], "R" => [77, "jm"], "S" => [18, "jm"], "T" => [77, "jn"], "U" => [18, "jn"], "V" => [77, "jp"], "W" => [18, "jp"], "X" => [77, "jr"], "Y" => [18, "jr"], "Z" => [77, "ju"], "[" => [18, "ju"], "\\" => [0, "j:"], "]" => [0, "jB"], "^" => [0, "jC"], "_" => [0, "jD"], "`" => [0, "jE"], "a" => [0, "jF"], "b" => [0, "jG"], "c" => [0, "jH"], "d" => [0, "jI"], "e" => [0, "jJ"], "f" => [0, "jK"], "g" => [0, "jL"], "h" => [0, "jM"], "i" => [0, "jN"], "j" => [0, "jO"], "k" => [0, "jP"], "l" => [0, "jQ"], "m" => [0, "jR"], "n" => [0, "jS"], "o" => [0, "jT"], "p" => [0, "jU"], "q" => [0, "jV"], "r" => [0, "jW"], "s" => [0, "jY"], "t" => [0, "jj"], "u" => [0, "jk"], "v" => [0, "jq"], "w" => [0, "jv"], "x" => [0, "jw"], "y" => [0, "jx"], "z" => [0, "jy"], "{" => [0, "jz"], "|" => [82, "j"], "}" => [87, "j"], "~" => [130, "j"], "" => [9, "j"], "\x80" => [94, "k0"], "\x81" => [76, "k0"], "\x82" => [104, "k0"], "\x83" => [16, "k0"], "\x84" => [94, "k1"], "\x85" => [76, "k1"], "\x86" => [104, "k1"], "\x87" => [16, "k1"], "\x88" => [94, "k2"], "\x89" => [76, "k2"], "\x8a" => [104, "k2"], "\x8b" => [16, "k2"], "\x8c" => [94, "ka"], "\x8d" => [76, "ka"], "\x8e" => [104, "ka"], "\x8f" => [16, "ka"], "\x90" => [94, "kc"], "\x91" => [76, "kc"], "\x92" => [104, "kc"], "\x93" => [16, "kc"], "\x94" => [94, "ke"], "\x95" => [76, "ke"], "\x96" => [104, "ke"], "\x97" => [16, "ke"], "\x98" => [94, "ki"], "\x99" => [76, "ki"], "\x9a" => [104, "ki"], "\x9b" => [16, "ki"], "\x9c" => [94, "ko"], "\x9d" => [76, "ko"], "\x9e" => [104, "ko"], "\x9f" => [16, "ko"], "\xa0" => [94, "ks"], "\xa1" => [76, "ks"], "\xa2" => [104, "ks"], "\xa3" => [16, "ks"], "\xa4" => [94, "kt"], "\xa5" => [76, "kt"], "\xa6" => [104, "kt"], "\xa7" => [16, "kt"], "\xa8" => [77, "k "], "\xa9" => [18, "k "], "\xaa" => [77, "k%"], "\xab" => [18, "k%"], "\xac" => [77, "k-"], "\xad" => [18, "k-"], "\xae" => [77, "k."], "\xaf" => [18, "k."], "\xb0" => [77, "k/"], "\xb1" => [18, "k/"], "\xb2" => [77, "k3"], "\xb3" => [18, "k3"], "\xb4" => [77, "k4"], "\xb5" => [18, "k4"], "\xb6" => [77, "k5"], "\xb7" => [18, "k5"], "\xb8" => [77, "k6"], "\xb9" => [18, "k6"], "\xba" => [77, "k7"], "\xbb" => [18, "k7"], "\xbc" => [77, "k8"], "\xbd" => [18, "k8"], "\xbe" => [77, "k9"], "\xbf" => [18, "k9"], "\xc0" => [77, "k="], "\xc1" => [18, "k="], "\xc2" => [77, "kA"], "\xc3" => [18, "kA"], "\xc4" => [77, "k_"], "\xc5" => [18, "k_"], "\xc6" => [77, "kb"], "\xc7" => [18, "kb"], "\xc8" => [77, "kd"], "\xc9" => [18, "kd"], "\xca" => [77, "kf"], "\xcb" => [18, "kf"], "\xcc" => [77, "kg"], "\xcd" => [18, "kg"], "\xce" => [77, "kh"], "\xcf" => [18, "kh"], "\xd0" => [77, "kl"], "\xd1" => [18, "kl"], "\xd2" => [77, "km"], "\xd3" => [18, "km"], "\xd4" => [77, "kn"], "\xd5" => [18, "kn"], "\xd6" => [77, "kp"], "\xd7" => [18, "kp"], "\xd8" => [77, "kr"], "\xd9" => [18, "kr"], "\xda" => [77, "ku"], "\xdb" => [18, "ku"], "\xdc" => [0, "k:"], "\xdd" => [0, "kB"], "\xde" => [0, "kC"], "\xdf" => [0, "kD"], "\xe0" => [0, "kE"], "\xe1" => [0, "kF"], "\xe2" => [0, "kG"], "\xe3" => [0, "kH"], "\xe4" => [0, "kI"], "\xe5" => [0, "kJ"], "\xe6" => [0, "kK"], "\xe7" => [0, "kL"], "\xe8" => [0, "kM"], "\xe9" => [0, "kN"], "\xea" => [0, "kO"], "\xeb" => [0, "kP"], "\xec" => [0, "kQ"], "\xed" => [0, "kR"], "\xee" => [0, "kS"], "\xef" => [0, "kT"], "\xf0" => [0, "kU"], "\xf1" => [0, "kV"], "\xf2" => [0, "kW"], "\xf3" => [0, "kY"], "\xf4" => [0, "kj"], "\xf5" => [0, "kk"], "\xf6" => [0, "kq"], "\xf7" => [0, "kv"], "\xf8" => [0, "kw"], "\xf9" => [0, "kx"], "\xfa" => [0, "ky"], "\xfb" => [0, "kz"], "\xfc" => [82, "k"], "\xfd" => [87, "k"], "\xfe" => [130, "k"], "\xff" => [9, "k"]], ["\x00" => [77, "j0"], "\x01" => [18, "j0"], "\x02" => [77, "j1"], "\x03" => [18, "j1"], "\x04" => [77, "j2"], "\x05" => [18, "j2"], "\x06" => [77, "ja"], "\x07" => [18, "ja"], "\x08" => [77, "jc"], "\t" => [18, "jc"], "\n" => [77, "je"], "\v" => [18, "je"], "\f" => [77, "ji"], "\r" => [18, "ji"], "\x0e" => [77, "jo"], "\x0f" => [18, "jo"], "\x10" => [77, "js"], "\x11" => [18, "js"], "\x12" => [77, "jt"], "\x13" => [18, "jt"], "\x14" => [0, "j "], "\x15" => [0, "j%"], "\x16" => [0, "j-"], "\x17" => [0, "j."], "\x18" => [0, "j/"], "\x19" => [0, "j3"], "\x1a" => [0, "j4"], "\x1b" => [0, "j5"], "\x1c" => [0, "j6"], "\x1d" => [0, "j7"], "\x1e" => [0, "j8"], "\x1f" => [0, "j9"], " " => [0, "j="], "!" => [0, "jA"], "\"" => [0, "j_"], "#" => [0, "jb"], "\$" => [0, "jd"], "%" => [0, "jf"], "&" => [0, "jg"], "'" => [0, "jh"], "(" => [0, "jl"], ")" => [0, "jm"], "*" => [0, "jn"], "+" => [0, "jp"], "," => [0, "jr"], "-" => [0, "ju"], "." => [100, "j"], "/" => [110, "j"], [111, "j"], [115, "j"], [116, "j"], [118, "j"], [119, "j"], [122, "j"], [123, "j"], [125, "j"], [126, "j"], [129, "j"], ":" => [143, "j"], ";" => [148, "j"], "<" => [151, "j"], "=" => [153, "j"], ">" => [83, "j"], "?" => [10, "j"], "@" => [77, "k0"], "A" => [18, "k0"], "B" => [77, "k1"], "C" => [18, "k1"], "D" => [77, "k2"], "E" => [18, "k2"], "F" => [77, "ka"], "G" => [18, "ka"], "H" => [77, "kc"], "I" => [18, "kc"], "J" => [77, "ke"], "K" => [18, "ke"], "L" => [77, "ki"], "M" => [18, "ki"], "N" => [77, "ko"], "O" => [18, "ko"], "P" => [77, "ks"], "Q" => [18, "ks"], "R" => [77, "kt"], "S" => [18, "kt"], "T" => [0, "k "], "U" => [0, "k%"], "V" => [0, "k-"], "W" => [0, "k."], "X" => [0, "k/"], "Y" => [0, "k3"], "Z" => [0, "k4"], "[" => [0, "k5"], "\\" => [0, "k6"], "]" => [0, "k7"], "^" => [0, "k8"], "_" => [0, "k9"], "`" => [0, "k="], "a" => [0, "kA"], "b" => [0, "k_"], "c" => [0, "kb"], "d" => [0, "kd"], "e" => [0, "kf"], "f" => [0, "kg"], "g" => [0, "kh"], "h" => [0, "kl"], "i" => [0, "km"], "j" => [0, "kn"], "k" => [0, "kp"], "l" => [0, "kr"], "m" => [0, "ku"], "n" => [100, "k"], "o" => [110, "k"], "p" => [111, "k"], "q" => [115, "k"], "r" => [116, "k"], "s" => [118, "k"], "t" => [119, "k"], "u" => [122, "k"], "v" => [123, "k"], "w" => [125, "k"], "x" => [126, "k"], "y" => [129, "k"], "z" => [143, "k"], "{" => [148, "k"], "|" => [151, "k"], "}" => [153, "k"], "~" => [83, "k"], "" => [10, "k"], "\x80" => [77, "q0"], "\x81" => [18, "q0"], "\x82" => [77, "q1"], "\x83" => [18, "q1"], "\x84" => [77, "q2"], "\x85" => [18, "q2"], "\x86" => [77, "qa"], "\x87" => [18, "qa"], "\x88" => [77, "qc"], "\x89" => [18, "qc"], "\x8a" => [77, "qe"], "\x8b" => [18, "qe"], "\x8c" => [77, "qi"], "\x8d" => [18, "qi"], "\x8e" => [77, "qo"], "\x8f" => [18, "qo"], "\x90" => [77, "qs"], "\x91" => [18, "qs"], "\x92" => [77, "qt"], "\x93" => [18, "qt"], "\x94" => [0, "q "], "\x95" => [0, "q%"], "\x96" => [0, "q-"], "\x97" => [0, "q."], "\x98" => [0, "q/"], "\x99" => [0, "q3"], "\x9a" => [0, "q4"], "\x9b" => [0, "q5"], "\x9c" => [0, "q6"], "\x9d" => [0, "q7"], "\x9e" => [0, "q8"], "\x9f" => [0, "q9"], "\xa0" => [0, "q="], "\xa1" => [0, "qA"], "\xa2" => [0, "q_"], "\xa3" => [0, "qb"], "\xa4" => [0, "qd"], "\xa5" => [0, "qf"], "\xa6" => [0, "qg"], "\xa7" => [0, "qh"], "\xa8" => [0, "ql"], "\xa9" => [0, "qm"], "\xaa" => [0, "qn"], "\xab" => [0, "qp"], "\xac" => [0, "qr"], "\xad" => [0, "qu"], "\xae" => [100, "q"], "\xaf" => [110, "q"], "\xb0" => [111, "q"], "\xb1" => [115, "q"], "\xb2" => [116, "q"], "\xb3" => [118, "q"], "\xb4" => [119, "q"], "\xb5" => [122, "q"], "\xb6" => [123, "q"], "\xb7" => [125, "q"], "\xb8" => [126, "q"], "\xb9" => [129, "q"], "\xba" => [143, "q"], "\xbb" => [148, "q"], "\xbc" => [151, "q"], "\xbd" => [153, "q"], "\xbe" => [83, "q"], "\xbf" => [10, "q"], "\xc0" => [77, "v0"], "\xc1" => [18, "v0"], "\xc2" => [77, "v1"], "\xc3" => [18, "v1"], "\xc4" => [77, "v2"], "\xc5" => [18, "v2"], "\xc6" => [77, "va"], "\xc7" => [18, "va"], "\xc8" => [77, "vc"], "\xc9" => [18, "vc"], "\xca" => [77, "ve"], "\xcb" => [18, "ve"], "\xcc" => [77, "vi"], "\xcd" => [18, "vi"], "\xce" => [77, "vo"], "\xcf" => [18, "vo"], "\xd0" => [77, "vs"], "\xd1" => [18, "vs"], "\xd2" => [77, "vt"], "\xd3" => [18, "vt"], "\xd4" => [0, "v "], "\xd5" => [0, "v%"], "\xd6" => [0, "v-"], "\xd7" => [0, "v."], "\xd8" => [0, "v/"], "\xd9" => [0, "v3"], "\xda" => [0, "v4"], "\xdb" => [0, "v5"], "\xdc" => [0, "v6"], "\xdd" => [0, "v7"], "\xde" => [0, "v8"], "\xdf" => [0, "v9"], "\xe0" => [0, "v="], "\xe1" => [0, "vA"], "\xe2" => [0, "v_"], "\xe3" => [0, "vb"], "\xe4" => [0, "vd"], "\xe5" => [0, "vf"], "\xe6" => [0, "vg"], "\xe7" => [0, "vh"], "\xe8" => [0, "vl"], "\xe9" => [0, "vm"], "\xea" => [0, "vn"], "\xeb" => [0, "vp"], "\xec" => [0, "vr"], "\xed" => [0, "vu"], "\xee" => [100, "v"], "\xef" => [110, "v"], "\xf0" => [111, "v"], "\xf1" => [115, "v"], "\xf2" => [116, "v"], "\xf3" => [118, "v"], "\xf4" => [119, "v"], "\xf5" => [122, "v"], "\xf6" => [123, "v"], "\xf7" => [125, "v"], "\xf8" => [126, "v"], "\xf9" => [129, "v"], "\xfa" => [143, "v"], "\xfb" => [148, "v"], "\xfc" => [151, "v"], "\xfd" => [153, "v"], "\xfe" => [83, "v"], "\xff" => [10, "v"]], ["\x00" => [94, "l0"], "\x01" => [76, "l0"], "\x02" => [104, "l0"], "\x03" => [16, "l0"], "\x04" => [94, "l1"], "\x05" => [76, "l1"], "\x06" => [104, "l1"], "\x07" => [16, "l1"], "\x08" => [94, "l2"], "\t" => [76, "l2"], "\n" => [104, "l2"], "\v" => [16, "l2"], "\f" => [94, "la"], "\r" => [76, "la"], "\x0e" => [104, "la"], "\x0f" => [16, "la"], "\x10" => [94, "lc"], "\x11" => [76, "lc"], "\x12" => [104, "lc"], "\x13" => [16, "lc"], "\x14" => [94, "le"], "\x15" => [76, "le"], "\x16" => [104, "le"], "\x17" => [16, "le"], "\x18" => [94, "li"], "\x19" => [76, "li"], "\x1a" => [104, "li"], "\x1b" => [16, "li"], "\x1c" => [94, "lo"], "\x1d" => [76, "lo"], "\x1e" => [104, "lo"], "\x1f" => [16, "lo"], " " => [94, "ls"], "!" => [76, "ls"], "\"" => [104, "ls"], "#" => [16, "ls"], "\$" => [94, "lt"], "%" => [76, "lt"], "&" => [104, "lt"], "'" => [16, "lt"], "(" => [77, "l "], ")" => [18, "l "], "*" => [77, "l%"], "+" => [18, "l%"], "," => [77, "l-"], "-" => [18, "l-"], "." => [77, "l."], "/" => [18, "l."], [77, "l/"], [18, "l/"], [77, "l3"], [18, "l3"], [77, "l4"], [18, "l4"], [77, "l5"], [18, "l5"], [77, "l6"], [18, "l6"], ":" => [77, "l7"], ";" => [18, "l7"], "<" => [77, "l8"], "=" => [18, "l8"], ">" => [77, "l9"], "?" => [18, "l9"], "@" => [77, "l="], "A" => [18, "l="], "B" => [77, "lA"], "C" => [18, "lA"], "D" => [77, "l_"], "E" => [18, "l_"], "F" => [77, "lb"], "G" => [18, "lb"], "H" => [77, "ld"], "I" => [18, "ld"], "J" => [77, "lf"], "K" => [18, "lf"], "L" => [77, "lg"], "M" => [18, "lg"], "N" => [77, "lh"], "O" => [18, "lh"], "P" => [77, "ll"], "Q" => [18, "ll"], "R" => [77, "lm"], "S" => [18, "lm"], "T" => [77, "ln"], "U" => [18, "ln"], "V" => [77, "lp"], "W" => [18, "lp"], "X" => [77, "lr"], "Y" => [18, "lr"], "Z" => [77, "lu"], "[" => [18, "lu"], "\\" => [0, "l:"], "]" => [0, "lB"], "^" => [0, "lC"], "_" => [0, "lD"], "`" => [0, "lE"], "a" => [0, "lF"], "b" => [0, "lG"], "c" => [0, "lH"], "d" => [0, "lI"], "e" => [0, "lJ"], "f" => [0, "lK"], "g" => [0, "lL"], "h" => [0, "lM"], "i" => [0, "lN"], "j" => [0, "lO"], "k" => [0, "lP"], "l" => [0, "lQ"], "m" => [0, "lR"], "n" => [0, "lS"], "o" => [0, "lT"], "p" => [0, "lU"], "q" => [0, "lV"], "r" => [0, "lW"], "s" => [0, "lY"], "t" => [0, "lj"], "u" => [0, "lk"], "v" => [0, "lq"], "w" => [0, "lv"], "x" => [0, "lw"], "y" => [0, "lx"], "z" => [0, "ly"], "{" => [0, "lz"], "|" => [82, "l"], "}" => [87, "l"], "~" => [130, "l"], "" => [9, "l"], "\x80" => [94, "m0"], "\x81" => [76, "m0"], "\x82" => [104, "m0"], "\x83" => [16, "m0"], "\x84" => [94, "m1"], "\x85" => [76, "m1"], "\x86" => [104, "m1"], "\x87" => [16, "m1"], "\x88" => [94, "m2"], "\x89" => [76, "m2"], "\x8a" => [104, "m2"], "\x8b" => [16, "m2"], "\x8c" => [94, "ma"], "\x8d" => [76, "ma"], "\x8e" => [104, "ma"], "\x8f" => [16, "ma"], "\x90" => [94, "mc"], "\x91" => [76, "mc"], "\x92" => [104, "mc"], "\x93" => [16, "mc"], "\x94" => [94, "me"], "\x95" => [76, "me"], "\x96" => [104, "me"], "\x97" => [16, "me"], "\x98" => [94, "mi"], "\x99" => [76, "mi"], "\x9a" => [104, "mi"], "\x9b" => [16, "mi"], "\x9c" => [94, "mo"], "\x9d" => [76, "mo"], "\x9e" => [104, "mo"], "\x9f" => [16, "mo"], "\xa0" => [94, "ms"], "\xa1" => [76, "ms"], "\xa2" => [104, "ms"], "\xa3" => [16, "ms"], "\xa4" => [94, "mt"], "\xa5" => [76, "mt"], "\xa6" => [104, "mt"], "\xa7" => [16, "mt"], "\xa8" => [77, "m "], "\xa9" => [18, "m "], "\xaa" => [77, "m%"], "\xab" => [18, "m%"], "\xac" => [77, "m-"], "\xad" => [18, "m-"], "\xae" => [77, "m."], "\xaf" => [18, "m."], "\xb0" => [77, "m/"], "\xb1" => [18, "m/"], "\xb2" => [77, "m3"], "\xb3" => [18, "m3"], "\xb4" => [77, "m4"], "\xb5" => [18, "m4"], "\xb6" => [77, "m5"], "\xb7" => [18, "m5"], "\xb8" => [77, "m6"], "\xb9" => [18, "m6"], "\xba" => [77, "m7"], "\xbb" => [18, "m7"], "\xbc" => [77, "m8"], "\xbd" => [18, "m8"], "\xbe" => [77, "m9"], "\xbf" => [18, "m9"], "\xc0" => [77, "m="], "\xc1" => [18, "m="], "\xc2" => [77, "mA"], "\xc3" => [18, "mA"], "\xc4" => [77, "m_"], "\xc5" => [18, "m_"], "\xc6" => [77, "mb"], "\xc7" => [18, "mb"], "\xc8" => [77, "md"], "\xc9" => [18, "md"], "\xca" => [77, "mf"], "\xcb" => [18, "mf"], "\xcc" => [77, "mg"], "\xcd" => [18, "mg"], "\xce" => [77, "mh"], "\xcf" => [18, "mh"], "\xd0" => [77, "ml"], "\xd1" => [18, "ml"], "\xd2" => [77, "mm"], "\xd3" => [18, "mm"], "\xd4" => [77, "mn"], "\xd5" => [18, "mn"], "\xd6" => [77, "mp"], "\xd7" => [18, "mp"], "\xd8" => [77, "mr"], "\xd9" => [18, "mr"], "\xda" => [77, "mu"], "\xdb" => [18, "mu"], "\xdc" => [0, "m:"], "\xdd" => [0, "mB"], "\xde" => [0, "mC"], "\xdf" => [0, "mD"], "\xe0" => [0, "mE"], "\xe1" => [0, "mF"], "\xe2" => [0, "mG"], "\xe3" => [0, "mH"], "\xe4" => [0, "mI"], "\xe5" => [0, "mJ"], "\xe6" => [0, "mK"], "\xe7" => [0, "mL"], "\xe8" => [0, "mM"], "\xe9" => [0, "mN"], "\xea" => [0, "mO"], "\xeb" => [0, "mP"], "\xec" => [0, "mQ"], "\xed" => [0, "mR"], "\xee" => [0, "mS"], "\xef" => [0, "mT"], "\xf0" => [0, "mU"], "\xf1" => [0, "mV"], "\xf2" => [0, "mW"], "\xf3" => [0, "mY"], "\xf4" => [0, "mj"], "\xf5" => [0, "mk"], "\xf6" => [0, "mq"], "\xf7" => [0, "mv"], "\xf8" => [0, "mw"], "\xf9" => [0, "mx"], "\xfa" => [0, "my"], "\xfb" => [0, "mz"], "\xfc" => [82, "m"], "\xfd" => [87, "m"], "\xfe" => [130, "m"], "\xff" => [9, "m"]], ["\x00" => [77, "l0"], "\x01" => [18, "l0"], "\x02" => [77, "l1"], "\x03" => [18, "l1"], "\x04" => [77, "l2"], "\x05" => [18, "l2"], "\x06" => [77, "la"], "\x07" => [18, "la"], "\x08" => [77, "lc"], "\t" => [18, "lc"], "\n" => [77, "le"], "\v" => [18, "le"], "\f" => [77, "li"], "\r" => [18, "li"], "\x0e" => [77, "lo"], "\x0f" => [18, "lo"], "\x10" => [77, "ls"], "\x11" => [18, "ls"], "\x12" => [77, "lt"], "\x13" => [18, "lt"], "\x14" => [0, "l "], "\x15" => [0, "l%"], "\x16" => [0, "l-"], "\x17" => [0, "l."], "\x18" => [0, "l/"], "\x19" => [0, "l3"], "\x1a" => [0, "l4"], "\x1b" => [0, "l5"], "\x1c" => [0, "l6"], "\x1d" => [0, "l7"], "\x1e" => [0, "l8"], "\x1f" => [0, "l9"], " " => [0, "l="], "!" => [0, "lA"], "\"" => [0, "l_"], "#" => [0, "lb"], "\$" => [0, "ld"], "%" => [0, "lf"], "&" => [0, "lg"], "'" => [0, "lh"], "(" => [0, "ll"], ")" => [0, "lm"], "*" => [0, "ln"], "+" => [0, "lp"], "," => [0, "lr"], "-" => [0, "lu"], "." => [100, "l"], "/" => [110, "l"], [111, "l"], [115, "l"], [116, "l"], [118, "l"], [119, "l"], [122, "l"], [123, "l"], [125, "l"], [126, "l"], [129, "l"], ":" => [143, "l"], ";" => [148, "l"], "<" => [151, "l"], "=" => [153, "l"], ">" => [83, "l"], "?" => [10, "l"], "@" => [77, "m0"], "A" => [18, "m0"], "B" => [77, "m1"], "C" => [18, "m1"], "D" => [77, "m2"], "E" => [18, "m2"], "F" => [77, "ma"], "G" => [18, "ma"], "H" => [77, "mc"], "I" => [18, "mc"], "J" => [77, "me"], "K" => [18, "me"], "L" => [77, "mi"], "M" => [18, "mi"], "N" => [77, "mo"], "O" => [18, "mo"], "P" => [77, "ms"], "Q" => [18, "ms"], "R" => [77, "mt"], "S" => [18, "mt"], "T" => [0, "m "], "U" => [0, "m%"], "V" => [0, "m-"], "W" => [0, "m."], "X" => [0, "m/"], "Y" => [0, "m3"], "Z" => [0, "m4"], "[" => [0, "m5"], "\\" => [0, "m6"], "]" => [0, "m7"], "^" => [0, "m8"], "_" => [0, "m9"], "`" => [0, "m="], "a" => [0, "mA"], "b" => [0, "m_"], "c" => [0, "mb"], "d" => [0, "md"], "e" => [0, "mf"], "f" => [0, "mg"], "g" => [0, "mh"], "h" => [0, "ml"], "i" => [0, "mm"], "j" => [0, "mn"], "k" => [0, "mp"], "l" => [0, "mr"], "m" => [0, "mu"], "n" => [100, "m"], "o" => [110, "m"], "p" => [111, "m"], "q" => [115, "m"], "r" => [116, "m"], "s" => [118, "m"], "t" => [119, "m"], "u" => [122, "m"], "v" => [123, "m"], "w" => [125, "m"], "x" => [126, "m"], "y" => [129, "m"], "z" => [143, "m"], "{" => [148, "m"], "|" => [151, "m"], "}" => [153, "m"], "~" => [83, "m"], "" => [10, "m"], "\x80" => [77, "n0"], "\x81" => [18, "n0"], "\x82" => [77, "n1"], "\x83" => [18, "n1"], "\x84" => [77, "n2"], "\x85" => [18, "n2"], "\x86" => [77, "na"], "\x87" => [18, "na"], "\x88" => [77, "nc"], "\x89" => [18, "nc"], "\x8a" => [77, "ne"], "\x8b" => [18, "ne"], "\x8c" => [77, "ni"], "\x8d" => [18, "ni"], "\x8e" => [77, "no"], "\x8f" => [18, "no"], "\x90" => [77, "ns"], "\x91" => [18, "ns"], "\x92" => [77, "nt"], "\x93" => [18, "nt"], "\x94" => [0, "n "], "\x95" => [0, "n%"], "\x96" => [0, "n-"], "\x97" => [0, "n."], "\x98" => [0, "n/"], "\x99" => [0, "n3"], "\x9a" => [0, "n4"], "\x9b" => [0, "n5"], "\x9c" => [0, "n6"], "\x9d" => [0, "n7"], "\x9e" => [0, "n8"], "\x9f" => [0, "n9"], "\xa0" => [0, "n="], "\xa1" => [0, "nA"], "\xa2" => [0, "n_"], "\xa3" => [0, "nb"], "\xa4" => [0, "nd"], "\xa5" => [0, "nf"], "\xa6" => [0, "ng"], "\xa7" => [0, "nh"], "\xa8" => [0, "nl"], "\xa9" => [0, "nm"], "\xaa" => [0, "nn"], "\xab" => [0, "np"], "\xac" => [0, "nr"], "\xad" => [0, "nu"], "\xae" => [100, "n"], "\xaf" => [110, "n"], "\xb0" => [111, "n"], "\xb1" => [115, "n"], "\xb2" => [116, "n"], "\xb3" => [118, "n"], "\xb4" => [119, "n"], "\xb5" => [122, "n"], "\xb6" => [123, "n"], "\xb7" => [125, "n"], "\xb8" => [126, "n"], "\xb9" => [129, "n"], "\xba" => [143, "n"], "\xbb" => [148, "n"], "\xbc" => [151, "n"], "\xbd" => [153, "n"], "\xbe" => [83, "n"], "\xbf" => [10, "n"], "\xc0" => [77, "p0"], "\xc1" => [18, "p0"], "\xc2" => [77, "p1"], "\xc3" => [18, "p1"], "\xc4" => [77, "p2"], "\xc5" => [18, "p2"], "\xc6" => [77, "pa"], "\xc7" => [18, "pa"], "\xc8" => [77, "pc"], "\xc9" => [18, "pc"], "\xca" => [77, "pe"], "\xcb" => [18, "pe"], "\xcc" => [77, "pi"], "\xcd" => [18, "pi"], "\xce" => [77, "po"], "\xcf" => [18, "po"], "\xd0" => [77, "ps"], "\xd1" => [18, "ps"], "\xd2" => [77, "pt"], "\xd3" => [18, "pt"], "\xd4" => [0, "p "], "\xd5" => [0, "p%"], "\xd6" => [0, "p-"], "\xd7" => [0, "p."], "\xd8" => [0, "p/"], "\xd9" => [0, "p3"], "\xda" => [0, "p4"], "\xdb" => [0, "p5"], "\xdc" => [0, "p6"], "\xdd" => [0, "p7"], "\xde" => [0, "p8"], "\xdf" => [0, "p9"], "\xe0" => [0, "p="], "\xe1" => [0, "pA"], "\xe2" => [0, "p_"], "\xe3" => [0, "pb"], "\xe4" => [0, "pd"], "\xe5" => [0, "pf"], "\xe6" => [0, "pg"], "\xe7" => [0, "ph"], "\xe8" => [0, "pl"], "\xe9" => [0, "pm"], "\xea" => [0, "pn"], "\xeb" => [0, "pp"], "\xec" => [0, "pr"], "\xed" => [0, "pu"], "\xee" => [100, "p"], "\xef" => [110, "p"], "\xf0" => [111, "p"], "\xf1" => [115, "p"], "\xf2" => [116, "p"], "\xf3" => [118, "p"], "\xf4" => [119, "p"], "\xf5" => [122, "p"], "\xf6" => [123, "p"], "\xf7" => [125, "p"], "\xf8" => [126, "p"], "\xf9" => [129, "p"], "\xfa" => [143, "p"], "\xfb" => [148, "p"], "\xfc" => [151, "p"], "\xfd" => [153, "p"], "\xfe" => [83, "p"], "\xff" => [10, "p"]], ["\x00" => [94, "n0"], "\x01" => [76, "n0"], "\x02" => [104, "n0"], "\x03" => [16, "n0"], "\x04" => [94, "n1"], "\x05" => [76, "n1"], "\x06" => [104, "n1"], "\x07" => [16, "n1"], "\x08" => [94, "n2"], "\t" => [76, "n2"], "\n" => [104, "n2"], "\v" => [16, "n2"], "\f" => [94, "na"], "\r" => [76, "na"], "\x0e" => [104, "na"], "\x0f" => [16, "na"], "\x10" => [94, "nc"], "\x11" => [76, "nc"], "\x12" => [104, "nc"], "\x13" => [16, "nc"], "\x14" => [94, "ne"], "\x15" => [76, "ne"], "\x16" => [104, "ne"], "\x17" => [16, "ne"], "\x18" => [94, "ni"], "\x19" => [76, "ni"], "\x1a" => [104, "ni"], "\x1b" => [16, "ni"], "\x1c" => [94, "no"], "\x1d" => [76, "no"], "\x1e" => [104, "no"], "\x1f" => [16, "no"], " " => [94, "ns"], "!" => [76, "ns"], "\"" => [104, "ns"], "#" => [16, "ns"], "\$" => [94, "nt"], "%" => [76, "nt"], "&" => [104, "nt"], "'" => [16, "nt"], "(" => [77, "n "], ")" => [18, "n "], "*" => [77, "n%"], "+" => [18, "n%"], "," => [77, "n-"], "-" => [18, "n-"], "." => [77, "n."], "/" => [18, "n."], [77, "n/"], [18, "n/"], [77, "n3"], [18, "n3"], [77, "n4"], [18, "n4"], [77, "n5"], [18, "n5"], [77, "n6"], [18, "n6"], ":" => [77, "n7"], ";" => [18, "n7"], "<" => [77, "n8"], "=" => [18, "n8"], ">" => [77, "n9"], "?" => [18, "n9"], "@" => [77, "n="], "A" => [18, "n="], "B" => [77, "nA"], "C" => [18, "nA"], "D" => [77, "n_"], "E" => [18, "n_"], "F" => [77, "nb"], "G" => [18, "nb"], "H" => [77, "nd"], "I" => [18, "nd"], "J" => [77, "nf"], "K" => [18, "nf"], "L" => [77, "ng"], "M" => [18, "ng"], "N" => [77, "nh"], "O" => [18, "nh"], "P" => [77, "nl"], "Q" => [18, "nl"], "R" => [77, "nm"], "S" => [18, "nm"], "T" => [77, "nn"], "U" => [18, "nn"], "V" => [77, "np"], "W" => [18, "np"], "X" => [77, "nr"], "Y" => [18, "nr"], "Z" => [77, "nu"], "[" => [18, "nu"], "\\" => [0, "n:"], "]" => [0, "nB"], "^" => [0, "nC"], "_" => [0, "nD"], "`" => [0, "nE"], "a" => [0, "nF"], "b" => [0, "nG"], "c" => [0, "nH"], "d" => [0, "nI"], "e" => [0, "nJ"], "f" => [0, "nK"], "g" => [0, "nL"], "h" => [0, "nM"], "i" => [0, "nN"], "j" => [0, "nO"], "k" => [0, "nP"], "l" => [0, "nQ"], "m" => [0, "nR"], "n" => [0, "nS"], "o" => [0, "nT"], "p" => [0, "nU"], "q" => [0, "nV"], "r" => [0, "nW"], "s" => [0, "nY"], "t" => [0, "nj"], "u" => [0, "nk"], "v" => [0, "nq"], "w" => [0, "nv"], "x" => [0, "nw"], "y" => [0, "nx"], "z" => [0, "ny"], "{" => [0, "nz"], "|" => [82, "n"], "}" => [87, "n"], "~" => [130, "n"], "" => [9, "n"], "\x80" => [94, "p0"], "\x81" => [76, "p0"], "\x82" => [104, "p0"], "\x83" => [16, "p0"], "\x84" => [94, "p1"], "\x85" => [76, "p1"], "\x86" => [104, "p1"], "\x87" => [16, "p1"], "\x88" => [94, "p2"], "\x89" => [76, "p2"], "\x8a" => [104, "p2"], "\x8b" => [16, "p2"], "\x8c" => [94, "pa"], "\x8d" => [76, "pa"], "\x8e" => [104, "pa"], "\x8f" => [16, "pa"], "\x90" => [94, "pc"], "\x91" => [76, "pc"], "\x92" => [104, "pc"], "\x93" => [16, "pc"], "\x94" => [94, "pe"], "\x95" => [76, "pe"], "\x96" => [104, "pe"], "\x97" => [16, "pe"], "\x98" => [94, "pi"], "\x99" => [76, "pi"], "\x9a" => [104, "pi"], "\x9b" => [16, "pi"], "\x9c" => [94, "po"], "\x9d" => [76, "po"], "\x9e" => [104, "po"], "\x9f" => [16, "po"], "\xa0" => [94, "ps"], "\xa1" => [76, "ps"], "\xa2" => [104, "ps"], "\xa3" => [16, "ps"], "\xa4" => [94, "pt"], "\xa5" => [76, "pt"], "\xa6" => [104, "pt"], "\xa7" => [16, "pt"], "\xa8" => [77, "p "], "\xa9" => [18, "p "], "\xaa" => [77, "p%"], "\xab" => [18, "p%"], "\xac" => [77, "p-"], "\xad" => [18, "p-"], "\xae" => [77, "p."], "\xaf" => [18, "p."], "\xb0" => [77, "p/"], "\xb1" => [18, "p/"], "\xb2" => [77, "p3"], "\xb3" => [18, "p3"], "\xb4" => [77, "p4"], "\xb5" => [18, "p4"], "\xb6" => [77, "p5"], "\xb7" => [18, "p5"], "\xb8" => [77, "p6"], "\xb9" => [18, "p6"], "\xba" => [77, "p7"], "\xbb" => [18, "p7"], "\xbc" => [77, "p8"], "\xbd" => [18, "p8"], "\xbe" => [77, "p9"], "\xbf" => [18, "p9"], "\xc0" => [77, "p="], "\xc1" => [18, "p="], "\xc2" => [77, "pA"], "\xc3" => [18, "pA"], "\xc4" => [77, "p_"], "\xc5" => [18, "p_"], "\xc6" => [77, "pb"], "\xc7" => [18, "pb"], "\xc8" => [77, "pd"], "\xc9" => [18, "pd"], "\xca" => [77, "pf"], "\xcb" => [18, "pf"], "\xcc" => [77, "pg"], "\xcd" => [18, "pg"], "\xce" => [77, "ph"], "\xcf" => [18, "ph"], "\xd0" => [77, "pl"], "\xd1" => [18, "pl"], "\xd2" => [77, "pm"], "\xd3" => [18, "pm"], "\xd4" => [77, "pn"], "\xd5" => [18, "pn"], "\xd6" => [77, "pp"], "\xd7" => [18, "pp"], "\xd8" => [77, "pr"], "\xd9" => [18, "pr"], "\xda" => [77, "pu"], "\xdb" => [18, "pu"], "\xdc" => [0, "p:"], "\xdd" => [0, "pB"], "\xde" => [0, "pC"], "\xdf" => [0, "pD"], "\xe0" => [0, "pE"], "\xe1" => [0, "pF"], "\xe2" => [0, "pG"], "\xe3" => [0, "pH"], "\xe4" => [0, "pI"], "\xe5" => [0, "pJ"], "\xe6" => [0, "pK"], "\xe7" => [0, "pL"], "\xe8" => [0, "pM"], "\xe9" => [0, "pN"], "\xea" => [0, "pO"], "\xeb" => [0, "pP"], "\xec" => [0, "pQ"], "\xed" => [0, "pR"], "\xee" => [0, "pS"], "\xef" => [0, "pT"], "\xf0" => [0, "pU"], "\xf1" => [0, "pV"], "\xf2" => [0, "pW"], "\xf3" => [0, "pY"], "\xf4" => [0, "pj"], "\xf5" => [0, "pk"], "\xf6" => [0, "pq"], "\xf7" => [0, "pv"], "\xf8" => [0, "pw"], "\xf9" => [0, "px"], "\xfa" => [0, "py"], "\xfb" => [0, "pz"], "\xfc" => [82, "p"], "\xfd" => [87, "p"], "\xfe" => [130, "p"], "\xff" => [9, "p"]], ["\x00" => [94, "q0"], "\x01" => [76, "q0"], "\x02" => [104, "q0"], "\x03" => [16, "q0"], "\x04" => [94, "q1"], "\x05" => [76, "q1"], "\x06" => [104, "q1"], "\x07" => [16, "q1"], "\x08" => [94, "q2"], "\t" => [76, "q2"], "\n" => [104, "q2"], "\v" => [16, "q2"], "\f" => [94, "qa"], "\r" => [76, "qa"], "\x0e" => [104, "qa"], "\x0f" => [16, "qa"], "\x10" => [94, "qc"], "\x11" => [76, "qc"], "\x12" => [104, "qc"], "\x13" => [16, "qc"], "\x14" => [94, "qe"], "\x15" => [76, "qe"], "\x16" => [104, "qe"], "\x17" => [16, "qe"], "\x18" => [94, "qi"], "\x19" => [76, "qi"], "\x1a" => [104, "qi"], "\x1b" => [16, "qi"], "\x1c" => [94, "qo"], "\x1d" => [76, "qo"], "\x1e" => [104, "qo"], "\x1f" => [16, "qo"], " " => [94, "qs"], "!" => [76, "qs"], "\"" => [104, "qs"], "#" => [16, "qs"], "\$" => [94, "qt"], "%" => [76, "qt"], "&" => [104, "qt"], "'" => [16, "qt"], "(" => [77, "q "], ")" => [18, "q "], "*" => [77, "q%"], "+" => [18, "q%"], "," => [77, "q-"], "-" => [18, "q-"], "." => [77, "q."], "/" => [18, "q."], [77, "q/"], [18, "q/"], [77, "q3"], [18, "q3"], [77, "q4"], [18, "q4"], [77, "q5"], [18, "q5"], [77, "q6"], [18, "q6"], ":" => [77, "q7"], ";" => [18, "q7"], "<" => [77, "q8"], "=" => [18, "q8"], ">" => [77, "q9"], "?" => [18, "q9"], "@" => [77, "q="], "A" => [18, "q="], "B" => [77, "qA"], "C" => [18, "qA"], "D" => [77, "q_"], "E" => [18, "q_"], "F" => [77, "qb"], "G" => [18, "qb"], "H" => [77, "qd"], "I" => [18, "qd"], "J" => [77, "qf"], "K" => [18, "qf"], "L" => [77, "qg"], "M" => [18, "qg"], "N" => [77, "qh"], "O" => [18, "qh"], "P" => [77, "ql"], "Q" => [18, "ql"], "R" => [77, "qm"], "S" => [18, "qm"], "T" => [77, "qn"], "U" => [18, "qn"], "V" => [77, "qp"], "W" => [18, "qp"], "X" => [77, "qr"], "Y" => [18, "qr"], "Z" => [77, "qu"], "[" => [18, "qu"], "\\" => [0, "q:"], "]" => [0, "qB"], "^" => [0, "qC"], "_" => [0, "qD"], "`" => [0, "qE"], "a" => [0, "qF"], "b" => [0, "qG"], "c" => [0, "qH"], "d" => [0, "qI"], "e" => [0, "qJ"], "f" => [0, "qK"], "g" => [0, "qL"], "h" => [0, "qM"], "i" => [0, "qN"], "j" => [0, "qO"], "k" => [0, "qP"], "l" => [0, "qQ"], "m" => [0, "qR"], "n" => [0, "qS"], "o" => [0, "qT"], "p" => [0, "qU"], "q" => [0, "qV"], "r" => [0, "qW"], "s" => [0, "qY"], "t" => [0, "qj"], "u" => [0, "qk"], "v" => [0, "qq"], "w" => [0, "qv"], "x" => [0, "qw"], "y" => [0, "qx"], "z" => [0, "qy"], "{" => [0, "qz"], "|" => [82, "q"], "}" => [87, "q"], "~" => [130, "q"], "" => [9, "q"], "\x80" => [94, "v0"], "\x81" => [76, "v0"], "\x82" => [104, "v0"], "\x83" => [16, "v0"], "\x84" => [94, "v1"], "\x85" => [76, "v1"], "\x86" => [104, "v1"], "\x87" => [16, "v1"], "\x88" => [94, "v2"], "\x89" => [76, "v2"], "\x8a" => [104, "v2"], "\x8b" => [16, "v2"], "\x8c" => [94, "va"], "\x8d" => [76, "va"], "\x8e" => [104, "va"], "\x8f" => [16, "va"], "\x90" => [94, "vc"], "\x91" => [76, "vc"], "\x92" => [104, "vc"], "\x93" => [16, "vc"], "\x94" => [94, "ve"], "\x95" => [76, "ve"], "\x96" => [104, "ve"], "\x97" => [16, "ve"], "\x98" => [94, "vi"], "\x99" => [76, "vi"], "\x9a" => [104, "vi"], "\x9b" => [16, "vi"], "\x9c" => [94, "vo"], "\x9d" => [76, "vo"], "\x9e" => [104, "vo"], "\x9f" => [16, "vo"], "\xa0" => [94, "vs"], "\xa1" => [76, "vs"], "\xa2" => [104, "vs"], "\xa3" => [16, "vs"], "\xa4" => [94, "vt"], "\xa5" => [76, "vt"], "\xa6" => [104, "vt"], "\xa7" => [16, "vt"], "\xa8" => [77, "v "], "\xa9" => [18, "v "], "\xaa" => [77, "v%"], "\xab" => [18, "v%"], "\xac" => [77, "v-"], "\xad" => [18, "v-"], "\xae" => [77, "v."], "\xaf" => [18, "v."], "\xb0" => [77, "v/"], "\xb1" => [18, "v/"], "\xb2" => [77, "v3"], "\xb3" => [18, "v3"], "\xb4" => [77, "v4"], "\xb5" => [18, "v4"], "\xb6" => [77, "v5"], "\xb7" => [18, "v5"], "\xb8" => [77, "v6"], "\xb9" => [18, "v6"], "\xba" => [77, "v7"], "\xbb" => [18, "v7"], "\xbc" => [77, "v8"], "\xbd" => [18, "v8"], "\xbe" => [77, "v9"], "\xbf" => [18, "v9"], "\xc0" => [77, "v="], "\xc1" => [18, "v="], "\xc2" => [77, "vA"], "\xc3" => [18, "vA"], "\xc4" => [77, "v_"], "\xc5" => [18, "v_"], "\xc6" => [77, "vb"], "\xc7" => [18, "vb"], "\xc8" => [77, "vd"], "\xc9" => [18, "vd"], "\xca" => [77, "vf"], "\xcb" => [18, "vf"], "\xcc" => [77, "vg"], "\xcd" => [18, "vg"], "\xce" => [77, "vh"], "\xcf" => [18, "vh"], "\xd0" => [77, "vl"], "\xd1" => [18, "vl"], "\xd2" => [77, "vm"], "\xd3" => [18, "vm"], "\xd4" => [77, "vn"], "\xd5" => [18, "vn"], "\xd6" => [77, "vp"], "\xd7" => [18, "vp"], "\xd8" => [77, "vr"], "\xd9" => [18, "vr"], "\xda" => [77, "vu"], "\xdb" => [18, "vu"], "\xdc" => [0, "v:"], "\xdd" => [0, "vB"], "\xde" => [0, "vC"], "\xdf" => [0, "vD"], "\xe0" => [0, "vE"], "\xe1" => [0, "vF"], "\xe2" => [0, "vG"], "\xe3" => [0, "vH"], "\xe4" => [0, "vI"], "\xe5" => [0, "vJ"], "\xe6" => [0, "vK"], "\xe7" => [0, "vL"], "\xe8" => [0, "vM"], "\xe9" => [0, "vN"], "\xea" => [0, "vO"], "\xeb" => [0, "vP"], "\xec" => [0, "vQ"], "\xed" => [0, "vR"], "\xee" => [0, "vS"], "\xef" => [0, "vT"], "\xf0" => [0, "vU"], "\xf1" => [0, "vV"], "\xf2" => [0, "vW"], "\xf3" => [0, "vY"], "\xf4" => [0, "vj"], "\xf5" => [0, "vk"], "\xf6" => [0, "vq"], "\xf7" => [0, "vv"], "\xf8" => [0, "vw"], "\xf9" => [0, "vx"], "\xfa" => [0, "vy"], "\xfb" => [0, "vz"], "\xfc" => [82, "v"], "\xfd" => [87, "v"], "\xfe" => [130, "v"], "\xff" => [9, "v"]], ["\x00" => [94, "r0"], "\x01" => [76, "r0"], "\x02" => [104, "r0"], "\x03" => [16, "r0"], "\x04" => [94, "r1"], "\x05" => [76, "r1"], "\x06" => [104, "r1"], "\x07" => [16, "r1"], "\x08" => [94, "r2"], "\t" => [76, "r2"], "\n" => [104, "r2"], "\v" => [16, "r2"], "\f" => [94, "ra"], "\r" => [76, "ra"], "\x0e" => [104, "ra"], "\x0f" => [16, "ra"], "\x10" => [94, "rc"], "\x11" => [76, "rc"], "\x12" => [104, "rc"], "\x13" => [16, "rc"], "\x14" => [94, "re"], "\x15" => [76, "re"], "\x16" => [104, "re"], "\x17" => [16, "re"], "\x18" => [94, "ri"], "\x19" => [76, "ri"], "\x1a" => [104, "ri"], "\x1b" => [16, "ri"], "\x1c" => [94, "ro"], "\x1d" => [76, "ro"], "\x1e" => [104, "ro"], "\x1f" => [16, "ro"], " " => [94, "rs"], "!" => [76, "rs"], "\"" => [104, "rs"], "#" => [16, "rs"], "\$" => [94, "rt"], "%" => [76, "rt"], "&" => [104, "rt"], "'" => [16, "rt"], "(" => [77, "r "], ")" => [18, "r "], "*" => [77, "r%"], "+" => [18, "r%"], "," => [77, "r-"], "-" => [18, "r-"], "." => [77, "r."], "/" => [18, "r."], [77, "r/"], [18, "r/"], [77, "r3"], [18, "r3"], [77, "r4"], [18, "r4"], [77, "r5"], [18, "r5"], [77, "r6"], [18, "r6"], ":" => [77, "r7"], ";" => [18, "r7"], "<" => [77, "r8"], "=" => [18, "r8"], ">" => [77, "r9"], "?" => [18, "r9"], "@" => [77, "r="], "A" => [18, "r="], "B" => [77, "rA"], "C" => [18, "rA"], "D" => [77, "r_"], "E" => [18, "r_"], "F" => [77, "rb"], "G" => [18, "rb"], "H" => [77, "rd"], "I" => [18, "rd"], "J" => [77, "rf"], "K" => [18, "rf"], "L" => [77, "rg"], "M" => [18, "rg"], "N" => [77, "rh"], "O" => [18, "rh"], "P" => [77, "rl"], "Q" => [18, "rl"], "R" => [77, "rm"], "S" => [18, "rm"], "T" => [77, "rn"], "U" => [18, "rn"], "V" => [77, "rp"], "W" => [18, "rp"], "X" => [77, "rr"], "Y" => [18, "rr"], "Z" => [77, "ru"], "[" => [18, "ru"], "\\" => [0, "r:"], "]" => [0, "rB"], "^" => [0, "rC"], "_" => [0, "rD"], "`" => [0, "rE"], "a" => [0, "rF"], "b" => [0, "rG"], "c" => [0, "rH"], "d" => [0, "rI"], "e" => [0, "rJ"], "f" => [0, "rK"], "g" => [0, "rL"], "h" => [0, "rM"], "i" => [0, "rN"], "j" => [0, "rO"], "k" => [0, "rP"], "l" => [0, "rQ"], "m" => [0, "rR"], "n" => [0, "rS"], "o" => [0, "rT"], "p" => [0, "rU"], "q" => [0, "rV"], "r" => [0, "rW"], "s" => [0, "rY"], "t" => [0, "rj"], "u" => [0, "rk"], "v" => [0, "rq"], "w" => [0, "rv"], "x" => [0, "rw"], "y" => [0, "rx"], "z" => [0, "ry"], "{" => [0, "rz"], "|" => [82, "r"], "}" => [87, "r"], "~" => [130, "r"], "" => [9, "r"], "\x80" => [94, "u0"], "\x81" => [76, "u0"], "\x82" => [104, "u0"], "\x83" => [16, "u0"], "\x84" => [94, "u1"], "\x85" => [76, "u1"], "\x86" => [104, "u1"], "\x87" => [16, "u1"], "\x88" => [94, "u2"], "\x89" => [76, "u2"], "\x8a" => [104, "u2"], "\x8b" => [16, "u2"], "\x8c" => [94, "ua"], "\x8d" => [76, "ua"], "\x8e" => [104, "ua"], "\x8f" => [16, "ua"], "\x90" => [94, "uc"], "\x91" => [76, "uc"], "\x92" => [104, "uc"], "\x93" => [16, "uc"], "\x94" => [94, "ue"], "\x95" => [76, "ue"], "\x96" => [104, "ue"], "\x97" => [16, "ue"], "\x98" => [94, "ui"], "\x99" => [76, "ui"], "\x9a" => [104, "ui"], "\x9b" => [16, "ui"], "\x9c" => [94, "uo"], "\x9d" => [76, "uo"], "\x9e" => [104, "uo"], "\x9f" => [16, "uo"], "\xa0" => [94, "us"], "\xa1" => [76, "us"], "\xa2" => [104, "us"], "\xa3" => [16, "us"], "\xa4" => [94, "ut"], "\xa5" => [76, "ut"], "\xa6" => [104, "ut"], "\xa7" => [16, "ut"], "\xa8" => [77, "u "], "\xa9" => [18, "u "], "\xaa" => [77, "u%"], "\xab" => [18, "u%"], "\xac" => [77, "u-"], "\xad" => [18, "u-"], "\xae" => [77, "u."], "\xaf" => [18, "u."], "\xb0" => [77, "u/"], "\xb1" => [18, "u/"], "\xb2" => [77, "u3"], "\xb3" => [18, "u3"], "\xb4" => [77, "u4"], "\xb5" => [18, "u4"], "\xb6" => [77, "u5"], "\xb7" => [18, "u5"], "\xb8" => [77, "u6"], "\xb9" => [18, "u6"], "\xba" => [77, "u7"], "\xbb" => [18, "u7"], "\xbc" => [77, "u8"], "\xbd" => [18, "u8"], "\xbe" => [77, "u9"], "\xbf" => [18, "u9"], "\xc0" => [77, "u="], "\xc1" => [18, "u="], "\xc2" => [77, "uA"], "\xc3" => [18, "uA"], "\xc4" => [77, "u_"], "\xc5" => [18, "u_"], "\xc6" => [77, "ub"], "\xc7" => [18, "ub"], "\xc8" => [77, "ud"], "\xc9" => [18, "ud"], "\xca" => [77, "uf"], "\xcb" => [18, "uf"], "\xcc" => [77, "ug"], "\xcd" => [18, "ug"], "\xce" => [77, "uh"], "\xcf" => [18, "uh"], "\xd0" => [77, "ul"], "\xd1" => [18, "ul"], "\xd2" => [77, "um"], "\xd3" => [18, "um"], "\xd4" => [77, "un"], "\xd5" => [18, "un"], "\xd6" => [77, "up"], "\xd7" => [18, "up"], "\xd8" => [77, "ur"], "\xd9" => [18, "ur"], "\xda" => [77, "uu"], "\xdb" => [18, "uu"], "\xdc" => [0, "u:"], "\xdd" => [0, "uB"], "\xde" => [0, "uC"], "\xdf" => [0, "uD"], "\xe0" => [0, "uE"], "\xe1" => [0, "uF"], "\xe2" => [0, "uG"], "\xe3" => [0, "uH"], "\xe4" => [0, "uI"], "\xe5" => [0, "uJ"], "\xe6" => [0, "uK"], "\xe7" => [0, "uL"], "\xe8" => [0, "uM"], "\xe9" => [0, "uN"], "\xea" => [0, "uO"], "\xeb" => [0, "uP"], "\xec" => [0, "uQ"], "\xed" => [0, "uR"], "\xee" => [0, "uS"], "\xef" => [0, "uT"], "\xf0" => [0, "uU"], "\xf1" => [0, "uV"], "\xf2" => [0, "uW"], "\xf3" => [0, "uY"], "\xf4" => [0, "uj"], "\xf5" => [0, "uk"], "\xf6" => [0, "uq"], "\xf7" => [0, "uv"], "\xf8" => [0, "uw"], "\xf9" => [0, "ux"], "\xfa" => [0, "uy"], "\xfb" => [0, "uz"], "\xfc" => [82, "u"], "\xfd" => [87, "u"], "\xfe" => [130, "u"], "\xff" => [9, "u"]], ["\x00" => [94, "s0"], "\x01" => [76, "s0"], "\x02" => [104, "s0"], "\x03" => [16, "s0"], "\x04" => [94, "s1"], "\x05" => [76, "s1"], "\x06" => [104, "s1"], "\x07" => [16, "s1"], "\x08" => [94, "s2"], "\t" => [76, "s2"], "\n" => [104, "s2"], "\v" => [16, "s2"], "\f" => [94, "sa"], "\r" => [76, "sa"], "\x0e" => [104, "sa"], "\x0f" => [16, "sa"], "\x10" => [94, "sc"], "\x11" => [76, "sc"], "\x12" => [104, "sc"], "\x13" => [16, "sc"], "\x14" => [94, "se"], "\x15" => [76, "se"], "\x16" => [104, "se"], "\x17" => [16, "se"], "\x18" => [94, "si"], "\x19" => [76, "si"], "\x1a" => [104, "si"], "\x1b" => [16, "si"], "\x1c" => [94, "so"], "\x1d" => [76, "so"], "\x1e" => [104, "so"], "\x1f" => [16, "so"], " " => [94, "ss"], "!" => [76, "ss"], "\"" => [104, "ss"], "#" => [16, "ss"], "\$" => [94, "st"], "%" => [76, "st"], "&" => [104, "st"], "'" => [16, "st"], "(" => [77, "s "], ")" => [18, "s "], "*" => [77, "s%"], "+" => [18, "s%"], "," => [77, "s-"], "-" => [18, "s-"], "." => [77, "s."], "/" => [18, "s."], [77, "s/"], [18, "s/"], [77, "s3"], [18, "s3"], [77, "s4"], [18, "s4"], [77, "s5"], [18, "s5"], [77, "s6"], [18, "s6"], ":" => [77, "s7"], ";" => [18, "s7"], "<" => [77, "s8"], "=" => [18, "s8"], ">" => [77, "s9"], "?" => [18, "s9"], "@" => [77, "s="], "A" => [18, "s="], "B" => [77, "sA"], "C" => [18, "sA"], "D" => [77, "s_"], "E" => [18, "s_"], "F" => [77, "sb"], "G" => [18, "sb"], "H" => [77, "sd"], "I" => [18, "sd"], "J" => [77, "sf"], "K" => [18, "sf"], "L" => [77, "sg"], "M" => [18, "sg"], "N" => [77, "sh"], "O" => [18, "sh"], "P" => [77, "sl"], "Q" => [18, "sl"], "R" => [77, "sm"], "S" => [18, "sm"], "T" => [77, "sn"], "U" => [18, "sn"], "V" => [77, "sp"], "W" => [18, "sp"], "X" => [77, "sr"], "Y" => [18, "sr"], "Z" => [77, "su"], "[" => [18, "su"], "\\" => [0, "s:"], "]" => [0, "sB"], "^" => [0, "sC"], "_" => [0, "sD"], "`" => [0, "sE"], "a" => [0, "sF"], "b" => [0, "sG"], "c" => [0, "sH"], "d" => [0, "sI"], "e" => [0, "sJ"], "f" => [0, "sK"], "g" => [0, "sL"], "h" => [0, "sM"], "i" => [0, "sN"], "j" => [0, "sO"], "k" => [0, "sP"], "l" => [0, "sQ"], "m" => [0, "sR"], "n" => [0, "sS"], "o" => [0, "sT"], "p" => [0, "sU"], "q" => [0, "sV"], "r" => [0, "sW"], "s" => [0, "sY"], "t" => [0, "sj"], "u" => [0, "sk"], "v" => [0, "sq"], "w" => [0, "sv"], "x" => [0, "sw"], "y" => [0, "sx"], "z" => [0, "sy"], "{" => [0, "sz"], "|" => [82, "s"], "}" => [87, "s"], "~" => [130, "s"], "" => [9, "s"], "\x80" => [94, "t0"], "\x81" => [76, "t0"], "\x82" => [104, "t0"], "\x83" => [16, "t0"], "\x84" => [94, "t1"], "\x85" => [76, "t1"], "\x86" => [104, "t1"], "\x87" => [16, "t1"], "\x88" => [94, "t2"], "\x89" => [76, "t2"], "\x8a" => [104, "t2"], "\x8b" => [16, "t2"], "\x8c" => [94, "ta"], "\x8d" => [76, "ta"], "\x8e" => [104, "ta"], "\x8f" => [16, "ta"], "\x90" => [94, "tc"], "\x91" => [76, "tc"], "\x92" => [104, "tc"], "\x93" => [16, "tc"], "\x94" => [94, "te"], "\x95" => [76, "te"], "\x96" => [104, "te"], "\x97" => [16, "te"], "\x98" => [94, "ti"], "\x99" => [76, "ti"], "\x9a" => [104, "ti"], "\x9b" => [16, "ti"], "\x9c" => [94, "to"], "\x9d" => [76, "to"], "\x9e" => [104, "to"], "\x9f" => [16, "to"], "\xa0" => [94, "ts"], "\xa1" => [76, "ts"], "\xa2" => [104, "ts"], "\xa3" => [16, "ts"], "\xa4" => [94, "tt"], "\xa5" => [76, "tt"], "\xa6" => [104, "tt"], "\xa7" => [16, "tt"], "\xa8" => [77, "t "], "\xa9" => [18, "t "], "\xaa" => [77, "t%"], "\xab" => [18, "t%"], "\xac" => [77, "t-"], "\xad" => [18, "t-"], "\xae" => [77, "t."], "\xaf" => [18, "t."], "\xb0" => [77, "t/"], "\xb1" => [18, "t/"], "\xb2" => [77, "t3"], "\xb3" => [18, "t3"], "\xb4" => [77, "t4"], "\xb5" => [18, "t4"], "\xb6" => [77, "t5"], "\xb7" => [18, "t5"], "\xb8" => [77, "t6"], "\xb9" => [18, "t6"], "\xba" => [77, "t7"], "\xbb" => [18, "t7"], "\xbc" => [77, "t8"], "\xbd" => [18, "t8"], "\xbe" => [77, "t9"], "\xbf" => [18, "t9"], "\xc0" => [77, "t="], "\xc1" => [18, "t="], "\xc2" => [77, "tA"], "\xc3" => [18, "tA"], "\xc4" => [77, "t_"], "\xc5" => [18, "t_"], "\xc6" => [77, "tb"], "\xc7" => [18, "tb"], "\xc8" => [77, "td"], "\xc9" => [18, "td"], "\xca" => [77, "tf"], "\xcb" => [18, "tf"], "\xcc" => [77, "tg"], "\xcd" => [18, "tg"], "\xce" => [77, "th"], "\xcf" => [18, "th"], "\xd0" => [77, "tl"], "\xd1" => [18, "tl"], "\xd2" => [77, "tm"], "\xd3" => [18, "tm"], "\xd4" => [77, "tn"], "\xd5" => [18, "tn"], "\xd6" => [77, "tp"], "\xd7" => [18, "tp"], "\xd8" => [77, "tr"], "\xd9" => [18, "tr"], "\xda" => [77, "tu"], "\xdb" => [18, "tu"], "\xdc" => [0, "t:"], "\xdd" => [0, "tB"], "\xde" => [0, "tC"], "\xdf" => [0, "tD"], "\xe0" => [0, "tE"], "\xe1" => [0, "tF"], "\xe2" => [0, "tG"], "\xe3" => [0, "tH"], "\xe4" => [0, "tI"], "\xe5" => [0, "tJ"], "\xe6" => [0, "tK"], "\xe7" => [0, "tL"], "\xe8" => [0, "tM"], "\xe9" => [0, "tN"], "\xea" => [0, "tO"], "\xeb" => [0, "tP"], "\xec" => [0, "tQ"], "\xed" => [0, "tR"], "\xee" => [0, "tS"], "\xef" => [0, "tT"], "\xf0" => [0, "tU"], "\xf1" => [0, "tV"], "\xf2" => [0, "tW"], "\xf3" => [0, "tY"], "\xf4" => [0, "tj"], "\xf5" => [0, "tk"], "\xf6" => [0, "tq"], "\xf7" => [0, "tv"], "\xf8" => [0, "tw"], "\xf9" => [0, "tx"], "\xfa" => [0, "ty"], "\xfb" => [0, "tz"], "\xfc" => [82, "t"], "\xfd" => [87, "t"], "\xfe" => [130, "t"], "\xff" => [9, "t"]], ["\x00" => [94, "w0"], "\x01" => [76, "w0"], "\x02" => [104, "w0"], "\x03" => [16, "w0"], "\x04" => [94, "w1"], "\x05" => [76, "w1"], "\x06" => [104, "w1"], "\x07" => [16, "w1"], "\x08" => [94, "w2"], "\t" => [76, "w2"], "\n" => [104, "w2"], "\v" => [16, "w2"], "\f" => [94, "wa"], "\r" => [76, "wa"], "\x0e" => [104, "wa"], "\x0f" => [16, "wa"], "\x10" => [94, "wc"], "\x11" => [76, "wc"], "\x12" => [104, "wc"], "\x13" => [16, "wc"], "\x14" => [94, "we"], "\x15" => [76, "we"], "\x16" => [104, "we"], "\x17" => [16, "we"], "\x18" => [94, "wi"], "\x19" => [76, "wi"], "\x1a" => [104, "wi"], "\x1b" => [16, "wi"], "\x1c" => [94, "wo"], "\x1d" => [76, "wo"], "\x1e" => [104, "wo"], "\x1f" => [16, "wo"], " " => [94, "ws"], "!" => [76, "ws"], "\"" => [104, "ws"], "#" => [16, "ws"], "\$" => [94, "wt"], "%" => [76, "wt"], "&" => [104, "wt"], "'" => [16, "wt"], "(" => [77, "w "], ")" => [18, "w "], "*" => [77, "w%"], "+" => [18, "w%"], "," => [77, "w-"], "-" => [18, "w-"], "." => [77, "w."], "/" => [18, "w."], [77, "w/"], [18, "w/"], [77, "w3"], [18, "w3"], [77, "w4"], [18, "w4"], [77, "w5"], [18, "w5"], [77, "w6"], [18, "w6"], ":" => [77, "w7"], ";" => [18, "w7"], "<" => [77, "w8"], "=" => [18, "w8"], ">" => [77, "w9"], "?" => [18, "w9"], "@" => [77, "w="], "A" => [18, "w="], "B" => [77, "wA"], "C" => [18, "wA"], "D" => [77, "w_"], "E" => [18, "w_"], "F" => [77, "wb"], "G" => [18, "wb"], "H" => [77, "wd"], "I" => [18, "wd"], "J" => [77, "wf"], "K" => [18, "wf"], "L" => [77, "wg"], "M" => [18, "wg"], "N" => [77, "wh"], "O" => [18, "wh"], "P" => [77, "wl"], "Q" => [18, "wl"], "R" => [77, "wm"], "S" => [18, "wm"], "T" => [77, "wn"], "U" => [18, "wn"], "V" => [77, "wp"], "W" => [18, "wp"], "X" => [77, "wr"], "Y" => [18, "wr"], "Z" => [77, "wu"], "[" => [18, "wu"], "\\" => [0, "w:"], "]" => [0, "wB"], "^" => [0, "wC"], "_" => [0, "wD"], "`" => [0, "wE"], "a" => [0, "wF"], "b" => [0, "wG"], "c" => [0, "wH"], "d" => [0, "wI"], "e" => [0, "wJ"], "f" => [0, "wK"], "g" => [0, "wL"], "h" => [0, "wM"], "i" => [0, "wN"], "j" => [0, "wO"], "k" => [0, "wP"], "l" => [0, "wQ"], "m" => [0, "wR"], "n" => [0, "wS"], "o" => [0, "wT"], "p" => [0, "wU"], "q" => [0, "wV"], "r" => [0, "wW"], "s" => [0, "wY"], "t" => [0, "wj"], "u" => [0, "wk"], "v" => [0, "wq"], "w" => [0, "wv"], "x" => [0, "ww"], "y" => [0, "wx"], "z" => [0, "wy"], "{" => [0, "wz"], "|" => [82, "w"], "}" => [87, "w"], "~" => [130, "w"], "" => [9, "w"], "\x80" => [94, "x0"], "\x81" => [76, "x0"], "\x82" => [104, "x0"], "\x83" => [16, "x0"], "\x84" => [94, "x1"], "\x85" => [76, "x1"], "\x86" => [104, "x1"], "\x87" => [16, "x1"], "\x88" => [94, "x2"], "\x89" => [76, "x2"], "\x8a" => [104, "x2"], "\x8b" => [16, "x2"], "\x8c" => [94, "xa"], "\x8d" => [76, "xa"], "\x8e" => [104, "xa"], "\x8f" => [16, "xa"], "\x90" => [94, "xc"], "\x91" => [76, "xc"], "\x92" => [104, "xc"], "\x93" => [16, "xc"], "\x94" => [94, "xe"], "\x95" => [76, "xe"], "\x96" => [104, "xe"], "\x97" => [16, "xe"], "\x98" => [94, "xi"], "\x99" => [76, "xi"], "\x9a" => [104, "xi"], "\x9b" => [16, "xi"], "\x9c" => [94, "xo"], "\x9d" => [76, "xo"], "\x9e" => [104, "xo"], "\x9f" => [16, "xo"], "\xa0" => [94, "xs"], "\xa1" => [76, "xs"], "\xa2" => [104, "xs"], "\xa3" => [16, "xs"], "\xa4" => [94, "xt"], "\xa5" => [76, "xt"], "\xa6" => [104, "xt"], "\xa7" => [16, "xt"], "\xa8" => [77, "x "], "\xa9" => [18, "x "], "\xaa" => [77, "x%"], "\xab" => [18, "x%"], "\xac" => [77, "x-"], "\xad" => [18, "x-"], "\xae" => [77, "x."], "\xaf" => [18, "x."], "\xb0" => [77, "x/"], "\xb1" => [18, "x/"], "\xb2" => [77, "x3"], "\xb3" => [18, "x3"], "\xb4" => [77, "x4"], "\xb5" => [18, "x4"], "\xb6" => [77, "x5"], "\xb7" => [18, "x5"], "\xb8" => [77, "x6"], "\xb9" => [18, "x6"], "\xba" => [77, "x7"], "\xbb" => [18, "x7"], "\xbc" => [77, "x8"], "\xbd" => [18, "x8"], "\xbe" => [77, "x9"], "\xbf" => [18, "x9"], "\xc0" => [77, "x="], "\xc1" => [18, "x="], "\xc2" => [77, "xA"], "\xc3" => [18, "xA"], "\xc4" => [77, "x_"], "\xc5" => [18, "x_"], "\xc6" => [77, "xb"], "\xc7" => [18, "xb"], "\xc8" => [77, "xd"], "\xc9" => [18, "xd"], "\xca" => [77, "xf"], "\xcb" => [18, "xf"], "\xcc" => [77, "xg"], "\xcd" => [18, "xg"], "\xce" => [77, "xh"], "\xcf" => [18, "xh"], "\xd0" => [77, "xl"], "\xd1" => [18, "xl"], "\xd2" => [77, "xm"], "\xd3" => [18, "xm"], "\xd4" => [77, "xn"], "\xd5" => [18, "xn"], "\xd6" => [77, "xp"], "\xd7" => [18, "xp"], "\xd8" => [77, "xr"], "\xd9" => [18, "xr"], "\xda" => [77, "xu"], "\xdb" => [18, "xu"], "\xdc" => [0, "x:"], "\xdd" => [0, "xB"], "\xde" => [0, "xC"], "\xdf" => [0, "xD"], "\xe0" => [0, "xE"], "\xe1" => [0, "xF"], "\xe2" => [0, "xG"], "\xe3" => [0, "xH"], "\xe4" => [0, "xI"], "\xe5" => [0, "xJ"], "\xe6" => [0, "xK"], "\xe7" => [0, "xL"], "\xe8" => [0, "xM"], "\xe9" => [0, "xN"], "\xea" => [0, "xO"], "\xeb" => [0, "xP"], "\xec" => [0, "xQ"], "\xed" => [0, "xR"], "\xee" => [0, "xS"], "\xef" => [0, "xT"], "\xf0" => [0, "xU"], "\xf1" => [0, "xV"], "\xf2" => [0, "xW"], "\xf3" => [0, "xY"], "\xf4" => [0, "xj"], "\xf5" => [0, "xk"], "\xf6" => [0, "xq"], "\xf7" => [0, "xv"], "\xf8" => [0, "xw"], "\xf9" => [0, "xx"], "\xfa" => [0, "xy"], "\xfb" => [0, "xz"], "\xfc" => [82, "x"], "\xfd" => [87, "x"], "\xfe" => [130, "x"], "\xff" => [9, "x"]], ["\x00" => [77, "w0"], "\x01" => [18, "w0"], "\x02" => [77, "w1"], "\x03" => [18, "w1"], "\x04" => [77, "w2"], "\x05" => [18, "w2"], "\x06" => [77, "wa"], "\x07" => [18, "wa"], "\x08" => [77, "wc"], "\t" => [18, "wc"], "\n" => [77, "we"], "\v" => [18, "we"], "\f" => [77, "wi"], "\r" => [18, "wi"], "\x0e" => [77, "wo"], "\x0f" => [18, "wo"], "\x10" => [77, "ws"], "\x11" => [18, "ws"], "\x12" => [77, "wt"], "\x13" => [18, "wt"], "\x14" => [0, "w "], "\x15" => [0, "w%"], "\x16" => [0, "w-"], "\x17" => [0, "w."], "\x18" => [0, "w/"], "\x19" => [0, "w3"], "\x1a" => [0, "w4"], "\x1b" => [0, "w5"], "\x1c" => [0, "w6"], "\x1d" => [0, "w7"], "\x1e" => [0, "w8"], "\x1f" => [0, "w9"], " " => [0, "w="], "!" => [0, "wA"], "\"" => [0, "w_"], "#" => [0, "wb"], "\$" => [0, "wd"], "%" => [0, "wf"], "&" => [0, "wg"], "'" => [0, "wh"], "(" => [0, "wl"], ")" => [0, "wm"], "*" => [0, "wn"], "+" => [0, "wp"], "," => [0, "wr"], "-" => [0, "wu"], "." => [100, "w"], "/" => [110, "w"], [111, "w"], [115, "w"], [116, "w"], [118, "w"], [119, "w"], [122, "w"], [123, "w"], [125, "w"], [126, "w"], [129, "w"], ":" => [143, "w"], ";" => [148, "w"], "<" => [151, "w"], "=" => [153, "w"], ">" => [83, "w"], "?" => [10, "w"], "@" => [77, "x0"], "A" => [18, "x0"], "B" => [77, "x1"], "C" => [18, "x1"], "D" => [77, "x2"], "E" => [18, "x2"], "F" => [77, "xa"], "G" => [18, "xa"], "H" => [77, "xc"], "I" => [18, "xc"], "J" => [77, "xe"], "K" => [18, "xe"], "L" => [77, "xi"], "M" => [18, "xi"], "N" => [77, "xo"], "O" => [18, "xo"], "P" => [77, "xs"], "Q" => [18, "xs"], "R" => [77, "xt"], "S" => [18, "xt"], "T" => [0, "x "], "U" => [0, "x%"], "V" => [0, "x-"], "W" => [0, "x."], "X" => [0, "x/"], "Y" => [0, "x3"], "Z" => [0, "x4"], "[" => [0, "x5"], "\\" => [0, "x6"], "]" => [0, "x7"], "^" => [0, "x8"], "_" => [0, "x9"], "`" => [0, "x="], "a" => [0, "xA"], "b" => [0, "x_"], "c" => [0, "xb"], "d" => [0, "xd"], "e" => [0, "xf"], "f" => [0, "xg"], "g" => [0, "xh"], "h" => [0, "xl"], "i" => [0, "xm"], "j" => [0, "xn"], "k" => [0, "xp"], "l" => [0, "xr"], "m" => [0, "xu"], "n" => [100, "x"], "o" => [110, "x"], "p" => [111, "x"], "q" => [115, "x"], "r" => [116, "x"], "s" => [118, "x"], "t" => [119, "x"], "u" => [122, "x"], "v" => [123, "x"], "w" => [125, "x"], "x" => [126, "x"], "y" => [129, "x"], "z" => [143, "x"], "{" => [148, "x"], "|" => [151, "x"], "}" => [153, "x"], "~" => [83, "x"], "" => [10, "x"], "\x80" => [77, "y0"], "\x81" => [18, "y0"], "\x82" => [77, "y1"], "\x83" => [18, "y1"], "\x84" => [77, "y2"], "\x85" => [18, "y2"], "\x86" => [77, "ya"], "\x87" => [18, "ya"], "\x88" => [77, "yc"], "\x89" => [18, "yc"], "\x8a" => [77, "ye"], "\x8b" => [18, "ye"], "\x8c" => [77, "yi"], "\x8d" => [18, "yi"], "\x8e" => [77, "yo"], "\x8f" => [18, "yo"], "\x90" => [77, "ys"], "\x91" => [18, "ys"], "\x92" => [77, "yt"], "\x93" => [18, "yt"], "\x94" => [0, "y "], "\x95" => [0, "y%"], "\x96" => [0, "y-"], "\x97" => [0, "y."], "\x98" => [0, "y/"], "\x99" => [0, "y3"], "\x9a" => [0, "y4"], "\x9b" => [0, "y5"], "\x9c" => [0, "y6"], "\x9d" => [0, "y7"], "\x9e" => [0, "y8"], "\x9f" => [0, "y9"], "\xa0" => [0, "y="], "\xa1" => [0, "yA"], "\xa2" => [0, "y_"], "\xa3" => [0, "yb"], "\xa4" => [0, "yd"], "\xa5" => [0, "yf"], "\xa6" => [0, "yg"], "\xa7" => [0, "yh"], "\xa8" => [0, "yl"], "\xa9" => [0, "ym"], "\xaa" => [0, "yn"], "\xab" => [0, "yp"], "\xac" => [0, "yr"], "\xad" => [0, "yu"], "\xae" => [100, "y"], "\xaf" => [110, "y"], "\xb0" => [111, "y"], "\xb1" => [115, "y"], "\xb2" => [116, "y"], "\xb3" => [118, "y"], "\xb4" => [119, "y"], "\xb5" => [122, "y"], "\xb6" => [123, "y"], "\xb7" => [125, "y"], "\xb8" => [126, "y"], "\xb9" => [129, "y"], "\xba" => [143, "y"], "\xbb" => [148, "y"], "\xbc" => [151, "y"], "\xbd" => [153, "y"], "\xbe" => [83, "y"], "\xbf" => [10, "y"], "\xc0" => [77, "z0"], "\xc1" => [18, "z0"], "\xc2" => [77, "z1"], "\xc3" => [18, "z1"], "\xc4" => [77, "z2"], "\xc5" => [18, "z2"], "\xc6" => [77, "za"], "\xc7" => [18, "za"], "\xc8" => [77, "zc"], "\xc9" => [18, "zc"], "\xca" => [77, "ze"], "\xcb" => [18, "ze"], "\xcc" => [77, "zi"], "\xcd" => [18, "zi"], "\xce" => [77, "zo"], "\xcf" => [18, "zo"], "\xd0" => [77, "zs"], "\xd1" => [18, "zs"], "\xd2" => [77, "zt"], "\xd3" => [18, "zt"], "\xd4" => [0, "z "], "\xd5" => [0, "z%"], "\xd6" => [0, "z-"], "\xd7" => [0, "z."], "\xd8" => [0, "z/"], "\xd9" => [0, "z3"], "\xda" => [0, "z4"], "\xdb" => [0, "z5"], "\xdc" => [0, "z6"], "\xdd" => [0, "z7"], "\xde" => [0, "z8"], "\xdf" => [0, "z9"], "\xe0" => [0, "z="], "\xe1" => [0, "zA"], "\xe2" => [0, "z_"], "\xe3" => [0, "zb"], "\xe4" => [0, "zd"], "\xe5" => [0, "zf"], "\xe6" => [0, "zg"], "\xe7" => [0, "zh"], "\xe8" => [0, "zl"], "\xe9" => [0, "zm"], "\xea" => [0, "zn"], "\xeb" => [0, "zp"], "\xec" => [0, "zr"], "\xed" => [0, "zu"], "\xee" => [100, "z"], "\xef" => [110, "z"], "\xf0" => [111, "z"], "\xf1" => [115, "z"], "\xf2" => [116, "z"], "\xf3" => [118, "z"], "\xf4" => [119, "z"], "\xf5" => [122, "z"], "\xf6" => [123, "z"], "\xf7" => [125, "z"], "\xf8" => [126, "z"], "\xf9" => [129, "z"], "\xfa" => [143, "z"], "\xfb" => [148, "z"], "\xfc" => [151, "z"], "\xfd" => [153, "z"], "\xfe" => [83, "z"], "\xff" => [10, "z"]], ["\x00" => [94, "y0"], "\x01" => [76, "y0"], "\x02" => [104, "y0"], "\x03" => [16, "y0"], "\x04" => [94, "y1"], "\x05" => [76, "y1"], "\x06" => [104, "y1"], "\x07" => [16, "y1"], "\x08" => [94, "y2"], "\t" => [76, "y2"], "\n" => [104, "y2"], "\v" => [16, "y2"], "\f" => [94, "ya"], "\r" => [76, "ya"], "\x0e" => [104, "ya"], "\x0f" => [16, "ya"], "\x10" => [94, "yc"], "\x11" => [76, "yc"], "\x12" => [104, "yc"], "\x13" => [16, "yc"], "\x14" => [94, "ye"], "\x15" => [76, "ye"], "\x16" => [104, "ye"], "\x17" => [16, "ye"], "\x18" => [94, "yi"], "\x19" => [76, "yi"], "\x1a" => [104, "yi"], "\x1b" => [16, "yi"], "\x1c" => [94, "yo"], "\x1d" => [76, "yo"], "\x1e" => [104, "yo"], "\x1f" => [16, "yo"], " " => [94, "ys"], "!" => [76, "ys"], "\"" => [104, "ys"], "#" => [16, "ys"], "\$" => [94, "yt"], "%" => [76, "yt"], "&" => [104, "yt"], "'" => [16, "yt"], "(" => [77, "y "], ")" => [18, "y "], "*" => [77, "y%"], "+" => [18, "y%"], "," => [77, "y-"], "-" => [18, "y-"], "." => [77, "y."], "/" => [18, "y."], [77, "y/"], [18, "y/"], [77, "y3"], [18, "y3"], [77, "y4"], [18, "y4"], [77, "y5"], [18, "y5"], [77, "y6"], [18, "y6"], ":" => [77, "y7"], ";" => [18, "y7"], "<" => [77, "y8"], "=" => [18, "y8"], ">" => [77, "y9"], "?" => [18, "y9"], "@" => [77, "y="], "A" => [18, "y="], "B" => [77, "yA"], "C" => [18, "yA"], "D" => [77, "y_"], "E" => [18, "y_"], "F" => [77, "yb"], "G" => [18, "yb"], "H" => [77, "yd"], "I" => [18, "yd"], "J" => [77, "yf"], "K" => [18, "yf"], "L" => [77, "yg"], "M" => [18, "yg"], "N" => [77, "yh"], "O" => [18, "yh"], "P" => [77, "yl"], "Q" => [18, "yl"], "R" => [77, "ym"], "S" => [18, "ym"], "T" => [77, "yn"], "U" => [18, "yn"], "V" => [77, "yp"], "W" => [18, "yp"], "X" => [77, "yr"], "Y" => [18, "yr"], "Z" => [77, "yu"], "[" => [18, "yu"], "\\" => [0, "y:"], "]" => [0, "yB"], "^" => [0, "yC"], "_" => [0, "yD"], "`" => [0, "yE"], "a" => [0, "yF"], "b" => [0, "yG"], "c" => [0, "yH"], "d" => [0, "yI"], "e" => [0, "yJ"], "f" => [0, "yK"], "g" => [0, "yL"], "h" => [0, "yM"], "i" => [0, "yN"], "j" => [0, "yO"], "k" => [0, "yP"], "l" => [0, "yQ"], "m" => [0, "yR"], "n" => [0, "yS"], "o" => [0, "yT"], "p" => [0, "yU"], "q" => [0, "yV"], "r" => [0, "yW"], "s" => [0, "yY"], "t" => [0, "yj"], "u" => [0, "yk"], "v" => [0, "yq"], "w" => [0, "yv"], "x" => [0, "yw"], "y" => [0, "yx"], "z" => [0, "yy"], "{" => [0, "yz"], "|" => [82, "y"], "}" => [87, "y"], "~" => [130, "y"], "" => [9, "y"], "\x80" => [94, "z0"], "\x81" => [76, "z0"], "\x82" => [104, "z0"], "\x83" => [16, "z0"], "\x84" => [94, "z1"], "\x85" => [76, "z1"], "\x86" => [104, "z1"], "\x87" => [16, "z1"], "\x88" => [94, "z2"], "\x89" => [76, "z2"], "\x8a" => [104, "z2"], "\x8b" => [16, "z2"], "\x8c" => [94, "za"], "\x8d" => [76, "za"], "\x8e" => [104, "za"], "\x8f" => [16, "za"], "\x90" => [94, "zc"], "\x91" => [76, "zc"], "\x92" => [104, "zc"], "\x93" => [16, "zc"], "\x94" => [94, "ze"], "\x95" => [76, "ze"], "\x96" => [104, "ze"], "\x97" => [16, "ze"], "\x98" => [94, "zi"], "\x99" => [76, "zi"], "\x9a" => [104, "zi"], "\x9b" => [16, "zi"], "\x9c" => [94, "zo"], "\x9d" => [76, "zo"], "\x9e" => [104, "zo"], "\x9f" => [16, "zo"], "\xa0" => [94, "zs"], "\xa1" => [76, "zs"], "\xa2" => [104, "zs"], "\xa3" => [16, "zs"], "\xa4" => [94, "zt"], "\xa5" => [76, "zt"], "\xa6" => [104, "zt"], "\xa7" => [16, "zt"], "\xa8" => [77, "z "], "\xa9" => [18, "z "], "\xaa" => [77, "z%"], "\xab" => [18, "z%"], "\xac" => [77, "z-"], "\xad" => [18, "z-"], "\xae" => [77, "z."], "\xaf" => [18, "z."], "\xb0" => [77, "z/"], "\xb1" => [18, "z/"], "\xb2" => [77, "z3"], "\xb3" => [18, "z3"], "\xb4" => [77, "z4"], "\xb5" => [18, "z4"], "\xb6" => [77, "z5"], "\xb7" => [18, "z5"], "\xb8" => [77, "z6"], "\xb9" => [18, "z6"], "\xba" => [77, "z7"], "\xbb" => [18, "z7"], "\xbc" => [77, "z8"], "\xbd" => [18, "z8"], "\xbe" => [77, "z9"], "\xbf" => [18, "z9"], "\xc0" => [77, "z="], "\xc1" => [18, "z="], "\xc2" => [77, "zA"], "\xc3" => [18, "zA"], "\xc4" => [77, "z_"], "\xc5" => [18, "z_"], "\xc6" => [77, "zb"], "\xc7" => [18, "zb"], "\xc8" => [77, "zd"], "\xc9" => [18, "zd"], "\xca" => [77, "zf"], "\xcb" => [18, "zf"], "\xcc" => [77, "zg"], "\xcd" => [18, "zg"], "\xce" => [77, "zh"], "\xcf" => [18, "zh"], "\xd0" => [77, "zl"], "\xd1" => [18, "zl"], "\xd2" => [77, "zm"], "\xd3" => [18, "zm"], "\xd4" => [77, "zn"], "\xd5" => [18, "zn"], "\xd6" => [77, "zp"], "\xd7" => [18, "zp"], "\xd8" => [77, "zr"], "\xd9" => [18, "zr"], "\xda" => [77, "zu"], "\xdb" => [18, "zu"], "\xdc" => [0, "z:"], "\xdd" => [0, "zB"], "\xde" => [0, "zC"], "\xdf" => [0, "zD"], "\xe0" => [0, "zE"], "\xe1" => [0, "zF"], "\xe2" => [0, "zG"], "\xe3" => [0, "zH"], "\xe4" => [0, "zI"], "\xe5" => [0, "zJ"], "\xe6" => [0, "zK"], "\xe7" => [0, "zL"], "\xe8" => [0, "zM"], "\xe9" => [0, "zN"], "\xea" => [0, "zO"], "\xeb" => [0, "zP"], "\xec" => [0, "zQ"], "\xed" => [0, "zR"], "\xee" => [0, "zS"], "\xef" => [0, "zT"], "\xf0" => [0, "zU"], "\xf1" => [0, "zV"], "\xf2" => [0, "zW"], "\xf3" => [0, "zY"], "\xf4" => [0, "zj"], "\xf5" => [0, "zk"], "\xf6" => [0, "zq"], "\xf7" => [0, "zv"], "\xf8" => [0, "zw"], "\xf9" => [0, "zx"], "\xfa" => [0, "zy"], "\xfb" => [0, "zz"], "\xfc" => [82, "z"], "\xfd" => [87, "z"], "\xfe" => [130, "z"], "\xff" => [9, "z"]], ["\x00" => [94, "0"], "\x01" => [76, "0"], "\x02" => [104, "0"], "\x03" => [16, "0"], "\x04" => [94, "1"], "\x05" => [76, "1"], "\x06" => [104, "1"], "\x07" => [16, "1"], "\x08" => [94, "2"], "\t" => [76, "2"], "\n" => [104, "2"], "\v" => [16, "2"], "\f" => [94, "a"], "\r" => [76, "a"], "\x0e" => [104, "a"], "\x0f" => [16, "a"], "\x10" => [94, "c"], "\x11" => [76, "c"], "\x12" => [104, "c"], "\x13" => [16, "c"], "\x14" => [94, "e"], "\x15" => [76, "e"], "\x16" => [104, "e"], "\x17" => [16, "e"], "\x18" => [94, "i"], "\x19" => [76, "i"], "\x1a" => [104, "i"], "\x1b" => [16, "i"], "\x1c" => [94, "o"], "\x1d" => [76, "o"], "\x1e" => [104, "o"], "\x1f" => [16, "o"], " " => [94, "s"], "!" => [76, "s"], "\"" => [104, "s"], "#" => [16, "s"], "\$" => [94, "t"], "%" => [76, "t"], "&" => [104, "t"], "'" => [16, "t"], "(" => [77, " "], ")" => [18, " "], "*" => [77, "%"], "+" => [18, "%"], "," => [77, "-"], "-" => [18, "-"], "." => [77, "."], "/" => [18, "."], [77, "/"], [18, "/"], [77, "3"], [18, "3"], [77, "4"], [18, "4"], [77, "5"], [18, "5"], [77, "6"], [18, "6"], ":" => [77, "7"], ";" => [18, "7"], "<" => [77, "8"], "=" => [18, "8"], ">" => [77, "9"], "?" => [18, "9"], "@" => [77, "="], "A" => [18, "="], "B" => [77, "A"], "C" => [18, "A"], "D" => [77, "_"], "E" => [18, "_"], "F" => [77, "b"], "G" => [18, "b"], "H" => [77, "d"], "I" => [18, "d"], "J" => [77, "f"], "K" => [18, "f"], "L" => [77, "g"], "M" => [18, "g"], "N" => [77, "h"], "O" => [18, "h"], "P" => [77, "l"], "Q" => [18, "l"], "R" => [77, "m"], "S" => [18, "m"], "T" => [77, "n"], "U" => [18, "n"], "V" => [77, "p"], "W" => [18, "p"], "X" => [77, "r"], "Y" => [18, "r"], "Z" => [77, "u"], "[" => [18, "u"], "\\" => [0, ":"], "]" => [0, "B"], "^" => [0, "C"], "_" => [0, "D"], "`" => [0, "E"], "a" => [0, "F"], "b" => [0, "G"], "c" => [0, "H"], "d" => [0, "I"], "e" => [0, "J"], "f" => [0, "K"], "g" => [0, "L"], "h" => [0, "M"], "i" => [0, "N"], "j" => [0, "O"], "k" => [0, "P"], "l" => [0, "Q"], "m" => [0, "R"], "n" => [0, "S"], "o" => [0, "T"], "p" => [0, "U"], "q" => [0, "V"], "r" => [0, "W"], "s" => [0, "Y"], "t" => [0, "j"], "u" => [0, "k"], "v" => [0, "q"], "w" => [0, "v"], "x" => [0, "w"], "y" => [0, "x"], "z" => [0, "y"], "{" => [0, "z"], "|" => [82, ""], "}" => [87, ""], "~" => [130, ""], "" => [9, ""], "\x80" => [94, "\xdc0"], "\x81" => [76, "\xdc0"], "\x82" => [104, "\xdc0"], "\x83" => [16, "\xdc0"], "\x84" => [94, "\xdc1"], "\x85" => [76, "\xdc1"], "\x86" => [104, "\xdc1"], "\x87" => [16, "\xdc1"], "\x88" => [94, "\xdc2"], "\x89" => [76, "\xdc2"], "\x8a" => [104, "\xdc2"], "\x8b" => [16, "\xdc2"], "\x8c" => [94, "\xdca"], "\x8d" => [76, "\xdca"], "\x8e" => [104, "\xdca"], "\x8f" => [16, "\xdca"], "\x90" => [94, "\xdcc"], "\x91" => [76, "\xdcc"], "\x92" => [104, "\xdcc"], "\x93" => [16, "\xdcc"], "\x94" => [94, "\xdce"], "\x95" => [76, "\xdce"], "\x96" => [104, "\xdce"], "\x97" => [16, "\xdce"], "\x98" => [94, "\xdci"], "\x99" => [76, "\xdci"], "\x9a" => [104, "\xdci"], "\x9b" => [16, "\xdci"], "\x9c" => [94, "\xdco"], "\x9d" => [76, "\xdco"], "\x9e" => [104, "\xdco"], "\x9f" => [16, "\xdco"], "\xa0" => [94, "\xdcs"], "\xa1" => [76, "\xdcs"], "\xa2" => [104, "\xdcs"], "\xa3" => [16, "\xdcs"], "\xa4" => [94, "\xdct"], "\xa5" => [76, "\xdct"], "\xa6" => [104, "\xdct"], "\xa7" => [16, "\xdct"], "\xa8" => [77, "\xdc "], "\xa9" => [18, "\xdc "], "\xaa" => [77, "\xdc%"], "\xab" => [18, "\xdc%"], "\xac" => [77, "\xdc-"], "\xad" => [18, "\xdc-"], "\xae" => [77, "\xdc."], "\xaf" => [18, "\xdc."], "\xb0" => [77, "\xdc/"], "\xb1" => [18, "\xdc/"], "\xb2" => [77, "\xdc3"], "\xb3" => [18, "\xdc3"], "\xb4" => [77, "\xdc4"], "\xb5" => [18, "\xdc4"], "\xb6" => [77, "\xdc5"], "\xb7" => [18, "\xdc5"], "\xb8" => [77, "\xdc6"], "\xb9" => [18, "\xdc6"], "\xba" => [77, "\xdc7"], "\xbb" => [18, "\xdc7"], "\xbc" => [77, "\xdc8"], "\xbd" => [18, "\xdc8"], "\xbe" => [77, "\xdc9"], "\xbf" => [18, "\xdc9"], "\xc0" => [77, "\xdc="], "\xc1" => [18, "\xdc="], "\xc2" => [77, "\xdcA"], "\xc3" => [18, "\xdcA"], "\xc4" => [77, "\xdc_"], "\xc5" => [18, "\xdc_"], "\xc6" => [77, "\xdcb"], "\xc7" => [18, "\xdcb"], "\xc8" => [77, "\xdcd"], "\xc9" => [18, "\xdcd"], "\xca" => [77, "\xdcf"], "\xcb" => [18, "\xdcf"], "\xcc" => [77, "\xdcg"], "\xcd" => [18, "\xdcg"], "\xce" => [77, "\xdch"], "\xcf" => [18, "\xdch"], "\xd0" => [77, "\xdcl"], "\xd1" => [18, "\xdcl"], "\xd2" => [77, "\xdcm"], "\xd3" => [18, "\xdcm"], "\xd4" => [77, "\xdcn"], "\xd5" => [18, "\xdcn"], "\xd6" => [77, "\xdcp"], "\xd7" => [18, "\xdcp"], "\xd8" => [77, "\xdcr"], "\xd9" => [18, "\xdcr"], "\xda" => [77, "\xdcu"], "\xdb" => [18, "\xdcu"], "\xdc" => [0, "\xdc:"], "\xdd" => [0, "\xdcB"], "\xde" => [0, "\xdcC"], "\xdf" => [0, "\xdcD"], "\xe0" => [0, "\xdcE"], "\xe1" => [0, "\xdcF"], "\xe2" => [0, "\xdcG"], "\xe3" => [0, "\xdcH"], "\xe4" => [0, "\xdcI"], "\xe5" => [0, "\xdcJ"], "\xe6" => [0, "\xdcK"], "\xe7" => [0, "\xdcL"], "\xe8" => [0, "\xdcM"], "\xe9" => [0, "\xdcN"], "\xea" => [0, "\xdcO"], "\xeb" => [0, "\xdcP"], "\xec" => [0, "\xdcQ"], "\xed" => [0, "\xdcR"], "\xee" => [0, "\xdcS"], "\xef" => [0, "\xdcT"], "\xf0" => [0, "\xdcU"], "\xf1" => [0, "\xdcV"], "\xf2" => [0, "\xdcW"], "\xf3" => [0, "\xdcY"], "\xf4" => [0, "\xdcj"], "\xf5" => [0, "\xdck"], "\xf6" => [0, "\xdcq"], "\xf7" => [0, "\xdcv"], "\xf8" => [0, "\xdcw"], "\xf9" => [0, "\xdcx"], "\xfa" => [0, "\xdcy"], "\xfb" => [0, "\xdcz"], "\xfc" => [82, "\xdc"], "\xfd" => [87, "\xdc"], "\xfe" => [130, "\xdc"], "\xff" => [9, "\xdc"]], ["\x00" => [94, "\x800"], "\x01" => [76, "\x800"], "\x02" => [104, "\x800"], "\x03" => [16, "\x800"], "\x04" => [94, "\x801"], "\x05" => [76, "\x801"], "\x06" => [104, "\x801"], "\x07" => [16, "\x801"], "\x08" => [94, "\x802"], "\t" => [76, "\x802"], "\n" => [104, "\x802"], "\v" => [16, "\x802"], "\f" => [94, "\x80a"], "\r" => [76, "\x80a"], "\x0e" => [104, "\x80a"], "\x0f" => [16, "\x80a"], "\x10" => [94, "\x80c"], "\x11" => [76, "\x80c"], "\x12" => [104, "\x80c"], "\x13" => [16, "\x80c"], "\x14" => [94, "\x80e"], "\x15" => [76, "\x80e"], "\x16" => [104, "\x80e"], "\x17" => [16, "\x80e"], "\x18" => [94, "\x80i"], "\x19" => [76, "\x80i"], "\x1a" => [104, "\x80i"], "\x1b" => [16, "\x80i"], "\x1c" => [94, "\x80o"], "\x1d" => [76, "\x80o"], "\x1e" => [104, "\x80o"], "\x1f" => [16, "\x80o"], " " => [94, "\x80s"], "!" => [76, "\x80s"], "\"" => [104, "\x80s"], "#" => [16, "\x80s"], "\$" => [94, "\x80t"], "%" => [76, "\x80t"], "&" => [104, "\x80t"], "'" => [16, "\x80t"], "(" => [77, "\x80 "], ")" => [18, "\x80 "], "*" => [77, "\x80%"], "+" => [18, "\x80%"], "," => [77, "\x80-"], "-" => [18, "\x80-"], "." => [77, "\x80."], "/" => [18, "\x80."], [77, "\x80/"], [18, "\x80/"], [77, "\x803"], [18, "\x803"], [77, "\x804"], [18, "\x804"], [77, "\x805"], [18, "\x805"], [77, "\x806"], [18, "\x806"], ":" => [77, "\x807"], ";" => [18, "\x807"], "<" => [77, "\x808"], "=" => [18, "\x808"], ">" => [77, "\x809"], "?" => [18, "\x809"], "@" => [77, "\x80="], "A" => [18, "\x80="], "B" => [77, "\x80A"], "C" => [18, "\x80A"], "D" => [77, "\x80_"], "E" => [18, "\x80_"], "F" => [77, "\x80b"], "G" => [18, "\x80b"], "H" => [77, "\x80d"], "I" => [18, "\x80d"], "J" => [77, "\x80f"], "K" => [18, "\x80f"], "L" => [77, "\x80g"], "M" => [18, "\x80g"], "N" => [77, "\x80h"], "O" => [18, "\x80h"], "P" => [77, "\x80l"], "Q" => [18, "\x80l"], "R" => [77, "\x80m"], "S" => [18, "\x80m"], "T" => [77, "\x80n"], "U" => [18, "\x80n"], "V" => [77, "\x80p"], "W" => [18, "\x80p"], "X" => [77, "\x80r"], "Y" => [18, "\x80r"], "Z" => [77, "\x80u"], "[" => [18, "\x80u"], "\\" => [0, "\x80:"], "]" => [0, "\x80B"], "^" => [0, "\x80C"], "_" => [0, "\x80D"], "`" => [0, "\x80E"], "a" => [0, "\x80F"], "b" => [0, "\x80G"], "c" => [0, "\x80H"], "d" => [0, "\x80I"], "e" => [0, "\x80J"], "f" => [0, "\x80K"], "g" => [0, "\x80L"], "h" => [0, "\x80M"], "i" => [0, "\x80N"], "j" => [0, "\x80O"], "k" => [0, "\x80P"], "l" => [0, "\x80Q"], "m" => [0, "\x80R"], "n" => [0, "\x80S"], "o" => [0, "\x80T"], "p" => [0, "\x80U"], "q" => [0, "\x80V"], "r" => [0, "\x80W"], "s" => [0, "\x80Y"], "t" => [0, "\x80j"], "u" => [0, "\x80k"], "v" => [0, "\x80q"], "w" => [0, "\x80v"], "x" => [0, "\x80w"], "y" => [0, "\x80x"], "z" => [0, "\x80y"], "{" => [0, "\x80z"], "|" => [82, "\x80"], "}" => [87, "\x80"], "~" => [130, "\x80"], "" => [9, "\x80"], "\x80" => [94, "\x820"], "\x81" => [76, "\x820"], "\x82" => [104, "\x820"], "\x83" => [16, "\x820"], "\x84" => [94, "\x821"], "\x85" => [76, "\x821"], "\x86" => [104, "\x821"], "\x87" => [16, "\x821"], "\x88" => [94, "\x822"], "\x89" => [76, "\x822"], "\x8a" => [104, "\x822"], "\x8b" => [16, "\x822"], "\x8c" => [94, "\x82a"], "\x8d" => [76, "\x82a"], "\x8e" => [104, "\x82a"], "\x8f" => [16, "\x82a"], "\x90" => [94, "\x82c"], "\x91" => [76, "\x82c"], "\x92" => [104, "\x82c"], "\x93" => [16, "\x82c"], "\x94" => [94, "\x82e"], "\x95" => [76, "\x82e"], "\x96" => [104, "\x82e"], "\x97" => [16, "\x82e"], "\x98" => [94, "\x82i"], "\x99" => [76, "\x82i"], "\x9a" => [104, "\x82i"], "\x9b" => [16, "\x82i"], "\x9c" => [94, "\x82o"], "\x9d" => [76, "\x82o"], "\x9e" => [104, "\x82o"], "\x9f" => [16, "\x82o"], "\xa0" => [94, "\x82s"], "\xa1" => [76, "\x82s"], "\xa2" => [104, "\x82s"], "\xa3" => [16, "\x82s"], "\xa4" => [94, "\x82t"], "\xa5" => [76, "\x82t"], "\xa6" => [104, "\x82t"], "\xa7" => [16, "\x82t"], "\xa8" => [77, "\x82 "], "\xa9" => [18, "\x82 "], "\xaa" => [77, "\x82%"], "\xab" => [18, "\x82%"], "\xac" => [77, "\x82-"], "\xad" => [18, "\x82-"], "\xae" => [77, "\x82."], "\xaf" => [18, "\x82."], "\xb0" => [77, "\x82/"], "\xb1" => [18, "\x82/"], "\xb2" => [77, "\x823"], "\xb3" => [18, "\x823"], "\xb4" => [77, "\x824"], "\xb5" => [18, "\x824"], "\xb6" => [77, "\x825"], "\xb7" => [18, "\x825"], "\xb8" => [77, "\x826"], "\xb9" => [18, "\x826"], "\xba" => [77, "\x827"], "\xbb" => [18, "\x827"], "\xbc" => [77, "\x828"], "\xbd" => [18, "\x828"], "\xbe" => [77, "\x829"], "\xbf" => [18, "\x829"], "\xc0" => [77, "\x82="], "\xc1" => [18, "\x82="], "\xc2" => [77, "\x82A"], "\xc3" => [18, "\x82A"], "\xc4" => [77, "\x82_"], "\xc5" => [18, "\x82_"], "\xc6" => [77, "\x82b"], "\xc7" => [18, "\x82b"], "\xc8" => [77, "\x82d"], "\xc9" => [18, "\x82d"], "\xca" => [77, "\x82f"], "\xcb" => [18, "\x82f"], "\xcc" => [77, "\x82g"], "\xcd" => [18, "\x82g"], "\xce" => [77, "\x82h"], "\xcf" => [18, "\x82h"], "\xd0" => [77, "\x82l"], "\xd1" => [18, "\x82l"], "\xd2" => [77, "\x82m"], "\xd3" => [18, "\x82m"], "\xd4" => [77, "\x82n"], "\xd5" => [18, "\x82n"], "\xd6" => [77, "\x82p"], "\xd7" => [18, "\x82p"], "\xd8" => [77, "\x82r"], "\xd9" => [18, "\x82r"], "\xda" => [77, "\x82u"], "\xdb" => [18, "\x82u"], "\xdc" => [0, "\x82:"], "\xdd" => [0, "\x82B"], "\xde" => [0, "\x82C"], "\xdf" => [0, "\x82D"], "\xe0" => [0, "\x82E"], "\xe1" => [0, "\x82F"], "\xe2" => [0, "\x82G"], "\xe3" => [0, "\x82H"], "\xe4" => [0, "\x82I"], "\xe5" => [0, "\x82J"], "\xe6" => [0, "\x82K"], "\xe7" => [0, "\x82L"], "\xe8" => [0, "\x82M"], "\xe9" => [0, "\x82N"], "\xea" => [0, "\x82O"], "\xeb" => [0, "\x82P"], "\xec" => [0, "\x82Q"], "\xed" => [0, "\x82R"], "\xee" => [0, "\x82S"], "\xef" => [0, "\x82T"], "\xf0" => [0, "\x82U"], "\xf1" => [0, "\x82V"], "\xf2" => [0, "\x82W"], "\xf3" => [0, "\x82Y"], "\xf4" => [0, "\x82j"], "\xf5" => [0, "\x82k"], "\xf6" => [0, "\x82q"], "\xf7" => [0, "\x82v"], "\xf8" => [0, "\x82w"], "\xf9" => [0, "\x82x"], "\xfa" => [0, "\x82y"], "\xfb" => [0, "\x82z"], "\xfc" => [82, "\x82"], "\xfd" => [87, "\x82"], "\xfe" => [130, "\x82"], "\xff" => [9, "\x82"]], ["\x00" => [94, "\xd00"], "\x01" => [76, "\xd00"], "\x02" => [104, "\xd00"], "\x03" => [16, "\xd00"], "\x04" => [94, "\xd01"], "\x05" => [76, "\xd01"], "\x06" => [104, "\xd01"], "\x07" => [16, "\xd01"], "\x08" => [94, "\xd02"], "\t" => [76, "\xd02"], "\n" => [104, "\xd02"], "\v" => [16, "\xd02"], "\f" => [94, "\xd0a"], "\r" => [76, "\xd0a"], "\x0e" => [104, "\xd0a"], "\x0f" => [16, "\xd0a"], "\x10" => [94, "\xd0c"], "\x11" => [76, "\xd0c"], "\x12" => [104, "\xd0c"], "\x13" => [16, "\xd0c"], "\x14" => [94, "\xd0e"], "\x15" => [76, "\xd0e"], "\x16" => [104, "\xd0e"], "\x17" => [16, "\xd0e"], "\x18" => [94, "\xd0i"], "\x19" => [76, "\xd0i"], "\x1a" => [104, "\xd0i"], "\x1b" => [16, "\xd0i"], "\x1c" => [94, "\xd0o"], "\x1d" => [76, "\xd0o"], "\x1e" => [104, "\xd0o"], "\x1f" => [16, "\xd0o"], " " => [94, "\xd0s"], "!" => [76, "\xd0s"], "\"" => [104, "\xd0s"], "#" => [16, "\xd0s"], "\$" => [94, "\xd0t"], "%" => [76, "\xd0t"], "&" => [104, "\xd0t"], "'" => [16, "\xd0t"], "(" => [77, "\xd0 "], ")" => [18, "\xd0 "], "*" => [77, "\xd0%"], "+" => [18, "\xd0%"], "," => [77, "\xd0-"], "-" => [18, "\xd0-"], "." => [77, "\xd0."], "/" => [18, "\xd0."], [77, "\xd0/"], [18, "\xd0/"], [77, "\xd03"], [18, "\xd03"], [77, "\xd04"], [18, "\xd04"], [77, "\xd05"], [18, "\xd05"], [77, "\xd06"], [18, "\xd06"], ":" => [77, "\xd07"], ";" => [18, "\xd07"], "<" => [77, "\xd08"], "=" => [18, "\xd08"], ">" => [77, "\xd09"], "?" => [18, "\xd09"], "@" => [77, "\xd0="], "A" => [18, "\xd0="], "B" => [77, "\xd0A"], "C" => [18, "\xd0A"], "D" => [77, "\xd0_"], "E" => [18, "\xd0_"], "F" => [77, "\xd0b"], "G" => [18, "\xd0b"], "H" => [77, "\xd0d"], "I" => [18, "\xd0d"], "J" => [77, "\xd0f"], "K" => [18, "\xd0f"], "L" => [77, "\xd0g"], "M" => [18, "\xd0g"], "N" => [77, "\xd0h"], "O" => [18, "\xd0h"], "P" => [77, "\xd0l"], "Q" => [18, "\xd0l"], "R" => [77, "\xd0m"], "S" => [18, "\xd0m"], "T" => [77, "\xd0n"], "U" => [18, "\xd0n"], "V" => [77, "\xd0p"], "W" => [18, "\xd0p"], "X" => [77, "\xd0r"], "Y" => [18, "\xd0r"], "Z" => [77, "\xd0u"], "[" => [18, "\xd0u"], "\\" => [0, "\xd0:"], "]" => [0, "\xd0B"], "^" => [0, "\xd0C"], "_" => [0, "\xd0D"], "`" => [0, "\xd0E"], "a" => [0, "\xd0F"], "b" => [0, "\xd0G"], "c" => [0, "\xd0H"], "d" => [0, "\xd0I"], "e" => [0, "\xd0J"], "f" => [0, "\xd0K"], "g" => [0, "\xd0L"], "h" => [0, "\xd0M"], "i" => [0, "\xd0N"], "j" => [0, "\xd0O"], "k" => [0, "\xd0P"], "l" => [0, "\xd0Q"], "m" => [0, "\xd0R"], "n" => [0, "\xd0S"], "o" => [0, "\xd0T"], "p" => [0, "\xd0U"], "q" => [0, "\xd0V"], "r" => [0, "\xd0W"], "s" => [0, "\xd0Y"], "t" => [0, "\xd0j"], "u" => [0, "\xd0k"], "v" => [0, "\xd0q"], "w" => [0, "\xd0v"], "x" => [0, "\xd0w"], "y" => [0, "\xd0x"], "z" => [0, "\xd0y"], "{" => [0, "\xd0z"], "|" => [82, "\xd0"], "}" => [87, "\xd0"], "~" => [130, "\xd0"], "" => [9, "\xd0"], "\x80" => [77, "\x800"], "\x81" => [18, "\x800"], "\x82" => [77, "\x801"], "\x83" => [18, "\x801"], "\x84" => [77, "\x802"], "\x85" => [18, "\x802"], "\x86" => [77, "\x80a"], "\x87" => [18, "\x80a"], "\x88" => [77, "\x80c"], "\x89" => [18, "\x80c"], "\x8a" => [77, "\x80e"], "\x8b" => [18, "\x80e"], "\x8c" => [77, "\x80i"], "\x8d" => [18, "\x80i"], "\x8e" => [77, "\x80o"], "\x8f" => [18, "\x80o"], "\x90" => [77, "\x80s"], "\x91" => [18, "\x80s"], "\x92" => [77, "\x80t"], "\x93" => [18, "\x80t"], "\x94" => [0, "\x80 "], "\x95" => [0, "\x80%"], "\x96" => [0, "\x80-"], "\x97" => [0, "\x80."], "\x98" => [0, "\x80/"], "\x99" => [0, "\x803"], "\x9a" => [0, "\x804"], "\x9b" => [0, "\x805"], "\x9c" => [0, "\x806"], "\x9d" => [0, "\x807"], "\x9e" => [0, "\x808"], "\x9f" => [0, "\x809"], "\xa0" => [0, "\x80="], "\xa1" => [0, "\x80A"], "\xa2" => [0, "\x80_"], "\xa3" => [0, "\x80b"], "\xa4" => [0, "\x80d"], "\xa5" => [0, "\x80f"], "\xa6" => [0, "\x80g"], "\xa7" => [0, "\x80h"], "\xa8" => [0, "\x80l"], "\xa9" => [0, "\x80m"], "\xaa" => [0, "\x80n"], "\xab" => [0, "\x80p"], "\xac" => [0, "\x80r"], "\xad" => [0, "\x80u"], "\xae" => [100, "\x80"], "\xaf" => [110, "\x80"], "\xb0" => [111, "\x80"], "\xb1" => [115, "\x80"], "\xb2" => [116, "\x80"], "\xb3" => [118, "\x80"], "\xb4" => [119, "\x80"], "\xb5" => [122, "\x80"], "\xb6" => [123, "\x80"], "\xb7" => [125, "\x80"], "\xb8" => [126, "\x80"], "\xb9" => [129, "\x80"], "\xba" => [143, "\x80"], "\xbb" => [148, "\x80"], "\xbc" => [151, "\x80"], "\xbd" => [153, "\x80"], "\xbe" => [83, "\x80"], "\xbf" => [10, "\x80"], "\xc0" => [77, "\x820"], "\xc1" => [18, "\x820"], "\xc2" => [77, "\x821"], "\xc3" => [18, "\x821"], "\xc4" => [77, "\x822"], "\xc5" => [18, "\x822"], "\xc6" => [77, "\x82a"], "\xc7" => [18, "\x82a"], "\xc8" => [77, "\x82c"], "\xc9" => [18, "\x82c"], "\xca" => [77, "\x82e"], "\xcb" => [18, "\x82e"], "\xcc" => [77, "\x82i"], "\xcd" => [18, "\x82i"], "\xce" => [77, "\x82o"], "\xcf" => [18, "\x82o"], "\xd0" => [77, "\x82s"], "\xd1" => [18, "\x82s"], "\xd2" => [77, "\x82t"], "\xd3" => [18, "\x82t"], "\xd4" => [0, "\x82 "], "\xd5" => [0, "\x82%"], "\xd6" => [0, "\x82-"], "\xd7" => [0, "\x82."], "\xd8" => [0, "\x82/"], "\xd9" => [0, "\x823"], "\xda" => [0, "\x824"], "\xdb" => [0, "\x825"], "\xdc" => [0, "\x826"], "\xdd" => [0, "\x827"], "\xde" => [0, "\x828"], "\xdf" => [0, "\x829"], "\xe0" => [0, "\x82="], "\xe1" => [0, "\x82A"], "\xe2" => [0, "\x82_"], "\xe3" => [0, "\x82b"], "\xe4" => [0, "\x82d"], "\xe5" => [0, "\x82f"], "\xe6" => [0, "\x82g"], "\xe7" => [0, "\x82h"], "\xe8" => [0, "\x82l"], "\xe9" => [0, "\x82m"], "\xea" => [0, "\x82n"], "\xeb" => [0, "\x82p"], "\xec" => [0, "\x82r"], "\xed" => [0, "\x82u"], "\xee" => [100, "\x82"], "\xef" => [110, "\x82"], "\xf0" => [111, "\x82"], "\xf1" => [115, "\x82"], "\xf2" => [116, "\x82"], "\xf3" => [118, "\x82"], "\xf4" => [119, "\x82"], "\xf5" => [122, "\x82"], "\xf6" => [123, "\x82"], "\xf7" => [125, "\x82"], "\xf8" => [126, "\x82"], "\xf9" => [129, "\x82"], "\xfa" => [143, "\x82"], "\xfb" => [148, "\x82"], "\xfc" => [151, "\x82"], "\xfd" => [153, "\x82"], "\xfe" => [83, "\x82"], "\xff" => [10, "\x82"]], ["\x00" => [94, "\x810"], "\x01" => [76, "\x810"], "\x02" => [104, "\x810"], "\x03" => [16, "\x810"], "\x04" => [94, "\x811"], "\x05" => [76, "\x811"], "\x06" => [104, "\x811"], "\x07" => [16, "\x811"], "\x08" => [94, "\x812"], "\t" => [76, "\x812"], "\n" => [104, "\x812"], "\v" => [16, "\x812"], "\f" => [94, "\x81a"], "\r" => [76, "\x81a"], "\x0e" => [104, "\x81a"], "\x0f" => [16, "\x81a"], "\x10" => [94, "\x81c"], "\x11" => [76, "\x81c"], "\x12" => [104, "\x81c"], "\x13" => [16, "\x81c"], "\x14" => [94, "\x81e"], "\x15" => [76, "\x81e"], "\x16" => [104, "\x81e"], "\x17" => [16, "\x81e"], "\x18" => [94, "\x81i"], "\x19" => [76, "\x81i"], "\x1a" => [104, "\x81i"], "\x1b" => [16, "\x81i"], "\x1c" => [94, "\x81o"], "\x1d" => [76, "\x81o"], "\x1e" => [104, "\x81o"], "\x1f" => [16, "\x81o"], " " => [94, "\x81s"], "!" => [76, "\x81s"], "\"" => [104, "\x81s"], "#" => [16, "\x81s"], "\$" => [94, "\x81t"], "%" => [76, "\x81t"], "&" => [104, "\x81t"], "'" => [16, "\x81t"], "(" => [77, "\x81 "], ")" => [18, "\x81 "], "*" => [77, "\x81%"], "+" => [18, "\x81%"], "," => [77, "\x81-"], "-" => [18, "\x81-"], "." => [77, "\x81."], "/" => [18, "\x81."], [77, "\x81/"], [18, "\x81/"], [77, "\x813"], [18, "\x813"], [77, "\x814"], [18, "\x814"], [77, "\x815"], [18, "\x815"], [77, "\x816"], [18, "\x816"], ":" => [77, "\x817"], ";" => [18, "\x817"], "<" => [77, "\x818"], "=" => [18, "\x818"], ">" => [77, "\x819"], "?" => [18, "\x819"], "@" => [77, "\x81="], "A" => [18, "\x81="], "B" => [77, "\x81A"], "C" => [18, "\x81A"], "D" => [77, "\x81_"], "E" => [18, "\x81_"], "F" => [77, "\x81b"], "G" => [18, "\x81b"], "H" => [77, "\x81d"], "I" => [18, "\x81d"], "J" => [77, "\x81f"], "K" => [18, "\x81f"], "L" => [77, "\x81g"], "M" => [18, "\x81g"], "N" => [77, "\x81h"], "O" => [18, "\x81h"], "P" => [77, "\x81l"], "Q" => [18, "\x81l"], "R" => [77, "\x81m"], "S" => [18, "\x81m"], "T" => [77, "\x81n"], "U" => [18, "\x81n"], "V" => [77, "\x81p"], "W" => [18, "\x81p"], "X" => [77, "\x81r"], "Y" => [18, "\x81r"], "Z" => [77, "\x81u"], "[" => [18, "\x81u"], "\\" => [0, "\x81:"], "]" => [0, "\x81B"], "^" => [0, "\x81C"], "_" => [0, "\x81D"], "`" => [0, "\x81E"], "a" => [0, "\x81F"], "b" => [0, "\x81G"], "c" => [0, "\x81H"], "d" => [0, "\x81I"], "e" => [0, "\x81J"], "f" => [0, "\x81K"], "g" => [0, "\x81L"], "h" => [0, "\x81M"], "i" => [0, "\x81N"], "j" => [0, "\x81O"], "k" => [0, "\x81P"], "l" => [0, "\x81Q"], "m" => [0, "\x81R"], "n" => [0, "\x81S"], "o" => [0, "\x81T"], "p" => [0, "\x81U"], "q" => [0, "\x81V"], "r" => [0, "\x81W"], "s" => [0, "\x81Y"], "t" => [0, "\x81j"], "u" => [0, "\x81k"], "v" => [0, "\x81q"], "w" => [0, "\x81v"], "x" => [0, "\x81w"], "y" => [0, "\x81x"], "z" => [0, "\x81y"], "{" => [0, "\x81z"], "|" => [82, "\x81"], "}" => [87, "\x81"], "~" => [130, "\x81"], "" => [9, "\x81"], "\x80" => [94, "\x840"], "\x81" => [76, "\x840"], "\x82" => [104, "\x840"], "\x83" => [16, "\x840"], "\x84" => [94, "\x841"], "\x85" => [76, "\x841"], "\x86" => [104, "\x841"], "\x87" => [16, "\x841"], "\x88" => [94, "\x842"], "\x89" => [76, "\x842"], "\x8a" => [104, "\x842"], "\x8b" => [16, "\x842"], "\x8c" => [94, "\x84a"], "\x8d" => [76, "\x84a"], "\x8e" => [104, "\x84a"], "\x8f" => [16, "\x84a"], "\x90" => [94, "\x84c"], "\x91" => [76, "\x84c"], "\x92" => [104, "\x84c"], "\x93" => [16, "\x84c"], "\x94" => [94, "\x84e"], "\x95" => [76, "\x84e"], "\x96" => [104, "\x84e"], "\x97" => [16, "\x84e"], "\x98" => [94, "\x84i"], "\x99" => [76, "\x84i"], "\x9a" => [104, "\x84i"], "\x9b" => [16, "\x84i"], "\x9c" => [94, "\x84o"], "\x9d" => [76, "\x84o"], "\x9e" => [104, "\x84o"], "\x9f" => [16, "\x84o"], "\xa0" => [94, "\x84s"], "\xa1" => [76, "\x84s"], "\xa2" => [104, "\x84s"], "\xa3" => [16, "\x84s"], "\xa4" => [94, "\x84t"], "\xa5" => [76, "\x84t"], "\xa6" => [104, "\x84t"], "\xa7" => [16, "\x84t"], "\xa8" => [77, "\x84 "], "\xa9" => [18, "\x84 "], "\xaa" => [77, "\x84%"], "\xab" => [18, "\x84%"], "\xac" => [77, "\x84-"], "\xad" => [18, "\x84-"], "\xae" => [77, "\x84."], "\xaf" => [18, "\x84."], "\xb0" => [77, "\x84/"], "\xb1" => [18, "\x84/"], "\xb2" => [77, "\x843"], "\xb3" => [18, "\x843"], "\xb4" => [77, "\x844"], "\xb5" => [18, "\x844"], "\xb6" => [77, "\x845"], "\xb7" => [18, "\x845"], "\xb8" => [77, "\x846"], "\xb9" => [18, "\x846"], "\xba" => [77, "\x847"], "\xbb" => [18, "\x847"], "\xbc" => [77, "\x848"], "\xbd" => [18, "\x848"], "\xbe" => [77, "\x849"], "\xbf" => [18, "\x849"], "\xc0" => [77, "\x84="], "\xc1" => [18, "\x84="], "\xc2" => [77, "\x84A"], "\xc3" => [18, "\x84A"], "\xc4" => [77, "\x84_"], "\xc5" => [18, "\x84_"], "\xc6" => [77, "\x84b"], "\xc7" => [18, "\x84b"], "\xc8" => [77, "\x84d"], "\xc9" => [18, "\x84d"], "\xca" => [77, "\x84f"], "\xcb" => [18, "\x84f"], "\xcc" => [77, "\x84g"], "\xcd" => [18, "\x84g"], "\xce" => [77, "\x84h"], "\xcf" => [18, "\x84h"], "\xd0" => [77, "\x84l"], "\xd1" => [18, "\x84l"], "\xd2" => [77, "\x84m"], "\xd3" => [18, "\x84m"], "\xd4" => [77, "\x84n"], "\xd5" => [18, "\x84n"], "\xd6" => [77, "\x84p"], "\xd7" => [18, "\x84p"], "\xd8" => [77, "\x84r"], "\xd9" => [18, "\x84r"], "\xda" => [77, "\x84u"], "\xdb" => [18, "\x84u"], "\xdc" => [0, "\x84:"], "\xdd" => [0, "\x84B"], "\xde" => [0, "\x84C"], "\xdf" => [0, "\x84D"], "\xe0" => [0, "\x84E"], "\xe1" => [0, "\x84F"], "\xe2" => [0, "\x84G"], "\xe3" => [0, "\x84H"], "\xe4" => [0, "\x84I"], "\xe5" => [0, "\x84J"], "\xe6" => [0, "\x84K"], "\xe7" => [0, "\x84L"], "\xe8" => [0, "\x84M"], "\xe9" => [0, "\x84N"], "\xea" => [0, "\x84O"], "\xeb" => [0, "\x84P"], "\xec" => [0, "\x84Q"], "\xed" => [0, "\x84R"], "\xee" => [0, "\x84S"], "\xef" => [0, "\x84T"], "\xf0" => [0, "\x84U"], "\xf1" => [0, "\x84V"], "\xf2" => [0, "\x84W"], "\xf3" => [0, "\x84Y"], "\xf4" => [0, "\x84j"], "\xf5" => [0, "\x84k"], "\xf6" => [0, "\x84q"], "\xf7" => [0, "\x84v"], "\xf8" => [0, "\x84w"], "\xf9" => [0, "\x84x"], "\xfa" => [0, "\x84y"], "\xfb" => [0, "\x84z"], "\xfc" => [82, "\x84"], "\xfd" => [87, "\x84"], "\xfe" => [130, "\x84"], "\xff" => [9, "\x84"]], ["\x00" => [94, "\xe60"], "\x01" => [76, "\xe60"], "\x02" => [104, "\xe60"], "\x03" => [16, "\xe60"], "\x04" => [94, "\xe61"], "\x05" => [76, "\xe61"], "\x06" => [104, "\xe61"], "\x07" => [16, "\xe61"], "\x08" => [94, "\xe62"], "\t" => [76, "\xe62"], "\n" => [104, "\xe62"], "\v" => [16, "\xe62"], "\f" => [94, "\xe6a"], "\r" => [76, "\xe6a"], "\x0e" => [104, "\xe6a"], "\x0f" => [16, "\xe6a"], "\x10" => [94, "\xe6c"], "\x11" => [76, "\xe6c"], "\x12" => [104, "\xe6c"], "\x13" => [16, "\xe6c"], "\x14" => [94, "\xe6e"], "\x15" => [76, "\xe6e"], "\x16" => [104, "\xe6e"], "\x17" => [16, "\xe6e"], "\x18" => [94, "\xe6i"], "\x19" => [76, "\xe6i"], "\x1a" => [104, "\xe6i"], "\x1b" => [16, "\xe6i"], "\x1c" => [94, "\xe6o"], "\x1d" => [76, "\xe6o"], "\x1e" => [104, "\xe6o"], "\x1f" => [16, "\xe6o"], " " => [94, "\xe6s"], "!" => [76, "\xe6s"], "\"" => [104, "\xe6s"], "#" => [16, "\xe6s"], "\$" => [94, "\xe6t"], "%" => [76, "\xe6t"], "&" => [104, "\xe6t"], "'" => [16, "\xe6t"], "(" => [77, "\xe6 "], ")" => [18, "\xe6 "], "*" => [77, "\xe6%"], "+" => [18, "\xe6%"], "," => [77, "\xe6-"], "-" => [18, "\xe6-"], "." => [77, "\xe6."], "/" => [18, "\xe6."], [77, "\xe6/"], [18, "\xe6/"], [77, "\xe63"], [18, "\xe63"], [77, "\xe64"], [18, "\xe64"], [77, "\xe65"], [18, "\xe65"], [77, "\xe66"], [18, "\xe66"], ":" => [77, "\xe67"], ";" => [18, "\xe67"], "<" => [77, "\xe68"], "=" => [18, "\xe68"], ">" => [77, "\xe69"], "?" => [18, "\xe69"], "@" => [77, "\xe6="], "A" => [18, "\xe6="], "B" => [77, "\xe6A"], "C" => [18, "\xe6A"], "D" => [77, "\xe6_"], "E" => [18, "\xe6_"], "F" => [77, "\xe6b"], "G" => [18, "\xe6b"], "H" => [77, "\xe6d"], "I" => [18, "\xe6d"], "J" => [77, "\xe6f"], "K" => [18, "\xe6f"], "L" => [77, "\xe6g"], "M" => [18, "\xe6g"], "N" => [77, "\xe6h"], "O" => [18, "\xe6h"], "P" => [77, "\xe6l"], "Q" => [18, "\xe6l"], "R" => [77, "\xe6m"], "S" => [18, "\xe6m"], "T" => [77, "\xe6n"], "U" => [18, "\xe6n"], "V" => [77, "\xe6p"], "W" => [18, "\xe6p"], "X" => [77, "\xe6r"], "Y" => [18, "\xe6r"], "Z" => [77, "\xe6u"], "[" => [18, "\xe6u"], "\\" => [0, "\xe6:"], "]" => [0, "\xe6B"], "^" => [0, "\xe6C"], "_" => [0, "\xe6D"], "`" => [0, "\xe6E"], "a" => [0, "\xe6F"], "b" => [0, "\xe6G"], "c" => [0, "\xe6H"], "d" => [0, "\xe6I"], "e" => [0, "\xe6J"], "f" => [0, "\xe6K"], "g" => [0, "\xe6L"], "h" => [0, "\xe6M"], "i" => [0, "\xe6N"], "j" => [0, "\xe6O"], "k" => [0, "\xe6P"], "l" => [0, "\xe6Q"], "m" => [0, "\xe6R"], "n" => [0, "\xe6S"], "o" => [0, "\xe6T"], "p" => [0, "\xe6U"], "q" => [0, "\xe6V"], "r" => [0, "\xe6W"], "s" => [0, "\xe6Y"], "t" => [0, "\xe6j"], "u" => [0, "\xe6k"], "v" => [0, "\xe6q"], "w" => [0, "\xe6v"], "x" => [0, "\xe6w"], "y" => [0, "\xe6x"], "z" => [0, "\xe6y"], "{" => [0, "\xe6z"], "|" => [82, "\xe6"], "}" => [87, "\xe6"], "~" => [130, "\xe6"], "" => [9, "\xe6"], "\x80" => [77, "\x810"], "\x81" => [18, "\x810"], "\x82" => [77, "\x811"], "\x83" => [18, "\x811"], "\x84" => [77, "\x812"], "\x85" => [18, "\x812"], "\x86" => [77, "\x81a"], "\x87" => [18, "\x81a"], "\x88" => [77, "\x81c"], "\x89" => [18, "\x81c"], "\x8a" => [77, "\x81e"], "\x8b" => [18, "\x81e"], "\x8c" => [77, "\x81i"], "\x8d" => [18, "\x81i"], "\x8e" => [77, "\x81o"], "\x8f" => [18, "\x81o"], "\x90" => [77, "\x81s"], "\x91" => [18, "\x81s"], "\x92" => [77, "\x81t"], "\x93" => [18, "\x81t"], "\x94" => [0, "\x81 "], "\x95" => [0, "\x81%"], "\x96" => [0, "\x81-"], "\x97" => [0, "\x81."], "\x98" => [0, "\x81/"], "\x99" => [0, "\x813"], "\x9a" => [0, "\x814"], "\x9b" => [0, "\x815"], "\x9c" => [0, "\x816"], "\x9d" => [0, "\x817"], "\x9e" => [0, "\x818"], "\x9f" => [0, "\x819"], "\xa0" => [0, "\x81="], "\xa1" => [0, "\x81A"], "\xa2" => [0, "\x81_"], "\xa3" => [0, "\x81b"], "\xa4" => [0, "\x81d"], "\xa5" => [0, "\x81f"], "\xa6" => [0, "\x81g"], "\xa7" => [0, "\x81h"], "\xa8" => [0, "\x81l"], "\xa9" => [0, "\x81m"], "\xaa" => [0, "\x81n"], "\xab" => [0, "\x81p"], "\xac" => [0, "\x81r"], "\xad" => [0, "\x81u"], "\xae" => [100, "\x81"], "\xaf" => [110, "\x81"], "\xb0" => [111, "\x81"], "\xb1" => [115, "\x81"], "\xb2" => [116, "\x81"], "\xb3" => [118, "\x81"], "\xb4" => [119, "\x81"], "\xb5" => [122, "\x81"], "\xb6" => [123, "\x81"], "\xb7" => [125, "\x81"], "\xb8" => [126, "\x81"], "\xb9" => [129, "\x81"], "\xba" => [143, "\x81"], "\xbb" => [148, "\x81"], "\xbc" => [151, "\x81"], "\xbd" => [153, "\x81"], "\xbe" => [83, "\x81"], "\xbf" => [10, "\x81"], "\xc0" => [77, "\x840"], "\xc1" => [18, "\x840"], "\xc2" => [77, "\x841"], "\xc3" => [18, "\x841"], "\xc4" => [77, "\x842"], "\xc5" => [18, "\x842"], "\xc6" => [77, "\x84a"], "\xc7" => [18, "\x84a"], "\xc8" => [77, "\x84c"], "\xc9" => [18, "\x84c"], "\xca" => [77, "\x84e"], "\xcb" => [18, "\x84e"], "\xcc" => [77, "\x84i"], "\xcd" => [18, "\x84i"], "\xce" => [77, "\x84o"], "\xcf" => [18, "\x84o"], "\xd0" => [77, "\x84s"], "\xd1" => [18, "\x84s"], "\xd2" => [77, "\x84t"], "\xd3" => [18, "\x84t"], "\xd4" => [0, "\x84 "], "\xd5" => [0, "\x84%"], "\xd6" => [0, "\x84-"], "\xd7" => [0, "\x84."], "\xd8" => [0, "\x84/"], "\xd9" => [0, "\x843"], "\xda" => [0, "\x844"], "\xdb" => [0, "\x845"], "\xdc" => [0, "\x846"], "\xdd" => [0, "\x847"], "\xde" => [0, "\x848"], "\xdf" => [0, "\x849"], "\xe0" => [0, "\x84="], "\xe1" => [0, "\x84A"], "\xe2" => [0, "\x84_"], "\xe3" => [0, "\x84b"], "\xe4" => [0, "\x84d"], "\xe5" => [0, "\x84f"], "\xe6" => [0, "\x84g"], "\xe7" => [0, "\x84h"], "\xe8" => [0, "\x84l"], "\xe9" => [0, "\x84m"], "\xea" => [0, "\x84n"], "\xeb" => [0, "\x84p"], "\xec" => [0, "\x84r"], "\xed" => [0, "\x84u"], "\xee" => [100, "\x84"], "\xef" => [110, "\x84"], "\xf0" => [111, "\x84"], "\xf1" => [115, "\x84"], "\xf2" => [116, "\x84"], "\xf3" => [118, "\x84"], "\xf4" => [119, "\x84"], "\xf5" => [122, "\x84"], "\xf6" => [123, "\x84"], "\xf7" => [125, "\x84"], "\xf8" => [126, "\x84"], "\xf9" => [129, "\x84"], "\xfa" => [143, "\x84"], "\xfb" => [148, "\x84"], "\xfc" => [151, "\x84"], "\xfd" => [153, "\x84"], "\xfe" => [83, "\x84"], "\xff" => [10, "\x84"]], ["\x00" => [77, "\xe60"], "\x01" => [18, "\xe60"], "\x02" => [77, "\xe61"], "\x03" => [18, "\xe61"], "\x04" => [77, "\xe62"], "\x05" => [18, "\xe62"], "\x06" => [77, "\xe6a"], "\x07" => [18, "\xe6a"], "\x08" => [77, "\xe6c"], "\t" => [18, "\xe6c"], "\n" => [77, "\xe6e"], "\v" => [18, "\xe6e"], "\f" => [77, "\xe6i"], "\r" => [18, "\xe6i"], "\x0e" => [77, "\xe6o"], "\x0f" => [18, "\xe6o"], "\x10" => [77, "\xe6s"], "\x11" => [18, "\xe6s"], "\x12" => [77, "\xe6t"], "\x13" => [18, "\xe6t"], "\x14" => [0, "\xe6 "], "\x15" => [0, "\xe6%"], "\x16" => [0, "\xe6-"], "\x17" => [0, "\xe6."], "\x18" => [0, "\xe6/"], "\x19" => [0, "\xe63"], "\x1a" => [0, "\xe64"], "\x1b" => [0, "\xe65"], "\x1c" => [0, "\xe66"], "\x1d" => [0, "\xe67"], "\x1e" => [0, "\xe68"], "\x1f" => [0, "\xe69"], " " => [0, "\xe6="], "!" => [0, "\xe6A"], "\"" => [0, "\xe6_"], "#" => [0, "\xe6b"], "\$" => [0, "\xe6d"], "%" => [0, "\xe6f"], "&" => [0, "\xe6g"], "'" => [0, "\xe6h"], "(" => [0, "\xe6l"], ")" => [0, "\xe6m"], "*" => [0, "\xe6n"], "+" => [0, "\xe6p"], "," => [0, "\xe6r"], "-" => [0, "\xe6u"], "." => [100, "\xe6"], "/" => [110, "\xe6"], [111, "\xe6"], [115, "\xe6"], [116, "\xe6"], [118, "\xe6"], [119, "\xe6"], [122, "\xe6"], [123, "\xe6"], [125, "\xe6"], [126, "\xe6"], [129, "\xe6"], ":" => [143, "\xe6"], ";" => [148, "\xe6"], "<" => [151, "\xe6"], "=" => [153, "\xe6"], ">" => [83, "\xe6"], "?" => [10, "\xe6"], "@" => [0, "\x810"], "A" => [0, "\x811"], "B" => [0, "\x812"], "C" => [0, "\x81a"], "D" => [0, "\x81c"], "E" => [0, "\x81e"], "F" => [0, "\x81i"], "G" => [0, "\x81o"], "H" => [0, "\x81s"], "I" => [0, "\x81t"], "J" => [73, "\x81"], "K" => [88, "\x81"], "L" => [89, "\x81"], "M" => [96, "\x81"], "N" => [97, "\x81"], "O" => [99, "\x81"], "P" => [106, "\x81"], "Q" => [136, "\x81"], "R" => [139, "\x81"], "S" => [141, "\x81"], "T" => [145, "\x81"], "U" => [147, "\x81"], "V" => [149, "\x81"], "W" => [101, "\x81"], "X" => [112, "\x81"], "Y" => [117, "\x81"], "Z" => [120, "\x81"], "[" => [124, "\x81"], "\\" => [127, "\x81"], "]" => [144, "\x81"], "^" => [152, "\x81"], "_" => [11, "\x81"], "`" => [0, "\x840"], "a" => [0, "\x841"], "b" => [0, "\x842"], "c" => [0, "\x84a"], "d" => [0, "\x84c"], "e" => [0, "\x84e"], "f" => [0, "\x84i"], "g" => [0, "\x84o"], "h" => [0, "\x84s"], "i" => [0, "\x84t"], "j" => [73, "\x84"], "k" => [88, "\x84"], "l" => [89, "\x84"], "m" => [96, "\x84"], "n" => [97, "\x84"], "o" => [99, "\x84"], "p" => [106, "\x84"], "q" => [136, "\x84"], "r" => [139, "\x84"], "s" => [141, "\x84"], "t" => [145, "\x84"], "u" => [147, "\x84"], "v" => [149, "\x84"], "w" => [101, "\x84"], "x" => [112, "\x84"], "y" => [117, "\x84"], "z" => [120, "\x84"], "{" => [124, "\x84"], "|" => [127, "\x84"], "}" => [144, "\x84"], "~" => [152, "\x84"], "" => [11, "\x84"], "\x80" => [0, "\x850"], "\x81" => [0, "\x851"], "\x82" => [0, "\x852"], "\x83" => [0, "\x85a"], "\x84" => [0, "\x85c"], "\x85" => [0, "\x85e"], "\x86" => [0, "\x85i"], "\x87" => [0, "\x85o"], "\x88" => [0, "\x85s"], "\x89" => [0, "\x85t"], "\x8a" => [73, "\x85"], "\x8b" => [88, "\x85"], "\x8c" => [89, "\x85"], "\x8d" => [96, "\x85"], "\x8e" => [97, "\x85"], "\x8f" => [99, "\x85"], "\x90" => [106, "\x85"], "\x91" => [136, "\x85"], "\x92" => [139, "\x85"], "\x93" => [141, "\x85"], "\x94" => [145, "\x85"], "\x95" => [147, "\x85"], "\x96" => [149, "\x85"], "\x97" => [101, "\x85"], "\x98" => [112, "\x85"], "\x99" => [117, "\x85"], "\x9a" => [120, "\x85"], "\x9b" => [124, "\x85"], "\x9c" => [127, "\x85"], "\x9d" => [144, "\x85"], "\x9e" => [152, "\x85"], "\x9f" => [11, "\x85"], "\xa0" => [0, "\x860"], "\xa1" => [0, "\x861"], "\xa2" => [0, "\x862"], "\xa3" => [0, "\x86a"], "\xa4" => [0, "\x86c"], "\xa5" => [0, "\x86e"], "\xa6" => [0, "\x86i"], "\xa7" => [0, "\x86o"], "\xa8" => [0, "\x86s"], "\xa9" => [0, "\x86t"], "\xaa" => [73, "\x86"], "\xab" => [88, "\x86"], "\xac" => [89, "\x86"], "\xad" => [96, "\x86"], "\xae" => [97, "\x86"], "\xaf" => [99, "\x86"], "\xb0" => [106, "\x86"], "\xb1" => [136, "\x86"], "\xb2" => [139, "\x86"], "\xb3" => [141, "\x86"], "\xb4" => [145, "\x86"], "\xb5" => [147, "\x86"], "\xb6" => [149, "\x86"], "\xb7" => [101, "\x86"], "\xb8" => [112, "\x86"], "\xb9" => [117, "\x86"], "\xba" => [120, "\x86"], "\xbb" => [124, "\x86"], "\xbc" => [127, "\x86"], "\xbd" => [144, "\x86"], "\xbe" => [152, "\x86"], "\xbf" => [11, "\x86"], "\xc0" => [0, "\x880"], "\xc1" => [0, "\x881"], "\xc2" => [0, "\x882"], "\xc3" => [0, "\x88a"], "\xc4" => [0, "\x88c"], "\xc5" => [0, "\x88e"], "\xc6" => [0, "\x88i"], "\xc7" => [0, "\x88o"], "\xc8" => [0, "\x88s"], "\xc9" => [0, "\x88t"], "\xca" => [73, "\x88"], "\xcb" => [88, "\x88"], "\xcc" => [89, "\x88"], "\xcd" => [96, "\x88"], "\xce" => [97, "\x88"], "\xcf" => [99, "\x88"], "\xd0" => [106, "\x88"], "\xd1" => [136, "\x88"], "\xd2" => [139, "\x88"], "\xd3" => [141, "\x88"], "\xd4" => [145, "\x88"], "\xd5" => [147, "\x88"], "\xd6" => [149, "\x88"], "\xd7" => [101, "\x88"], "\xd8" => [112, "\x88"], "\xd9" => [117, "\x88"], "\xda" => [120, "\x88"], "\xdb" => [124, "\x88"], "\xdc" => [127, "\x88"], "\xdd" => [144, "\x88"], "\xde" => [152, "\x88"], "\xdf" => [11, "\x88"], "\xe0" => [0, "\x920"], "\xe1" => [0, "\x921"], "\xe2" => [0, "\x922"], "\xe3" => [0, "\x92a"], "\xe4" => [0, "\x92c"], "\xe5" => [0, "\x92e"], "\xe6" => [0, "\x92i"], "\xe7" => [0, "\x92o"], "\xe8" => [0, "\x92s"], "\xe9" => [0, "\x92t"], "\xea" => [73, "\x92"], "\xeb" => [88, "\x92"], "\xec" => [89, "\x92"], "\xed" => [96, "\x92"], "\xee" => [97, "\x92"], "\xef" => [99, "\x92"], "\xf0" => [106, "\x92"], "\xf1" => [136, "\x92"], "\xf2" => [139, "\x92"], "\xf3" => [141, "\x92"], "\xf4" => [145, "\x92"], "\xf5" => [147, "\x92"], "\xf6" => [149, "\x92"], "\xf7" => [101, "\x92"], "\xf8" => [112, "\x92"], "\xf9" => [117, "\x92"], "\xfa" => [120, "\x92"], "\xfb" => [124, "\x92"], "\xfc" => [127, "\x92"], "\xfd" => [144, "\x92"], "\xfe" => [152, "\x92"], "\xff" => [11, "\x92"]], ["\x00" => [0, "\xe60"], "\x01" => [0, "\xe61"], "\x02" => [0, "\xe62"], "\x03" => [0, "\xe6a"], "\x04" => [0, "\xe6c"], "\x05" => [0, "\xe6e"], "\x06" => [0, "\xe6i"], "\x07" => [0, "\xe6o"], "\x08" => [0, "\xe6s"], "\t" => [0, "\xe6t"], "\n" => [73, "\xe6"], "\v" => [88, "\xe6"], "\f" => [89, "\xe6"], "\r" => [96, "\xe6"], "\x0e" => [97, "\xe6"], "\x0f" => [99, "\xe6"], "\x10" => [106, "\xe6"], "\x11" => [136, "\xe6"], "\x12" => [139, "\xe6"], "\x13" => [141, "\xe6"], "\x14" => [145, "\xe6"], "\x15" => [147, "\xe6"], "\x16" => [149, "\xe6"], "\x17" => [101, "\xe6"], "\x18" => [112, "\xe6"], "\x19" => [117, "\xe6"], "\x1a" => [120, "\xe6"], "\x1b" => [124, "\xe6"], "\x1c" => [127, "\xe6"], "\x1d" => [144, "\xe6"], "\x1e" => [152, "\xe6"], "\x1f" => [11, "\xe6"], " " => [92, "\x81"], "!" => [95, "\x81"], "\"" => [137, "\x81"], "#" => [142, "\x81"], "\$" => [150, "\x81"], "%" => [74, "\x81"], "&" => [90, "\x81"], "'" => [98, "\x81"], "(" => [107, "\x81"], ")" => [140, "\x81"], "*" => [146, "\x81"], "+" => [102, "\x81"], "," => [113, "\x81"], "-" => [121, "\x81"], "." => [128, "\x81"], "/" => [12, "\x81"], [92, "\x84"], [95, "\x84"], [137, "\x84"], [142, "\x84"], [150, "\x84"], [74, "\x84"], [90, "\x84"], [98, "\x84"], [107, "\x84"], [140, "\x84"], ":" => [146, "\x84"], ";" => [102, "\x84"], "<" => [113, "\x84"], "=" => [121, "\x84"], ">" => [128, "\x84"], "?" => [12, "\x84"], "@" => [92, "\x85"], "A" => [95, "\x85"], "B" => [137, "\x85"], "C" => [142, "\x85"], "D" => [150, "\x85"], "E" => [74, "\x85"], "F" => [90, "\x85"], "G" => [98, "\x85"], "H" => [107, "\x85"], "I" => [140, "\x85"], "J" => [146, "\x85"], "K" => [102, "\x85"], "L" => [113, "\x85"], "M" => [121, "\x85"], "N" => [128, "\x85"], "O" => [12, "\x85"], "P" => [92, "\x86"], "Q" => [95, "\x86"], "R" => [137, "\x86"], "S" => [142, "\x86"], "T" => [150, "\x86"], "U" => [74, "\x86"], "V" => [90, "\x86"], "W" => [98, "\x86"], "X" => [107, "\x86"], "Y" => [140, "\x86"], "Z" => [146, "\x86"], "[" => [102, "\x86"], "\\" => [113, "\x86"], "]" => [121, "\x86"], "^" => [128, "\x86"], "_" => [12, "\x86"], "`" => [92, "\x88"], "a" => [95, "\x88"], "b" => [137, "\x88"], "c" => [142, "\x88"], "d" => [150, "\x88"], "e" => [74, "\x88"], "f" => [90, "\x88"], "g" => [98, "\x88"], "h" => [107, "\x88"], "i" => [140, "\x88"], "j" => [146, "\x88"], "k" => [102, "\x88"], "l" => [113, "\x88"], "m" => [121, "\x88"], "n" => [128, "\x88"], "o" => [12, "\x88"], "p" => [92, "\x92"], "q" => [95, "\x92"], "r" => [137, "\x92"], "s" => [142, "\x92"], "t" => [150, "\x92"], "u" => [74, "\x92"], "v" => [90, "\x92"], "w" => [98, "\x92"], "x" => [107, "\x92"], "y" => [140, "\x92"], "z" => [146, "\x92"], "{" => [102, "\x92"], "|" => [113, "\x92"], "}" => [121, "\x92"], "~" => [128, "\x92"], "" => [12, "\x92"], "\x80" => [92, "\x9a"], "\x81" => [95, "\x9a"], "\x82" => [137, "\x9a"], "\x83" => [142, "\x9a"], "\x84" => [150, "\x9a"], "\x85" => [74, "\x9a"], "\x86" => [90, "\x9a"], "\x87" => [98, "\x9a"], "\x88" => [107, "\x9a"], "\x89" => [140, "\x9a"], "\x8a" => [146, "\x9a"], "\x8b" => [102, "\x9a"], "\x8c" => [113, "\x9a"], "\x8d" => [121, "\x9a"], "\x8e" => [128, "\x9a"], "\x8f" => [12, "\x9a"], "\x90" => [92, "\x9c"], "\x91" => [95, "\x9c"], "\x92" => [137, "\x9c"], "\x93" => [142, "\x9c"], "\x94" => [150, "\x9c"], "\x95" => [74, "\x9c"], "\x96" => [90, "\x9c"], "\x97" => [98, "\x9c"], "\x98" => [107, "\x9c"], "\x99" => [140, "\x9c"], "\x9a" => [146, "\x9c"], "\x9b" => [102, "\x9c"], "\x9c" => [113, "\x9c"], "\x9d" => [121, "\x9c"], "\x9e" => [128, "\x9c"], "\x9f" => [12, "\x9c"], "\xa0" => [92, "\xa0"], "\xa1" => [95, "\xa0"], "\xa2" => [137, "\xa0"], "\xa3" => [142, "\xa0"], "\xa4" => [150, "\xa0"], "\xa5" => [74, "\xa0"], "\xa6" => [90, "\xa0"], "\xa7" => [98, "\xa0"], "\xa8" => [107, "\xa0"], "\xa9" => [140, "\xa0"], "\xaa" => [146, "\xa0"], "\xab" => [102, "\xa0"], "\xac" => [113, "\xa0"], "\xad" => [121, "\xa0"], "\xae" => [128, "\xa0"], "\xaf" => [12, "\xa0"], "\xb0" => [92, "\xa3"], "\xb1" => [95, "\xa3"], "\xb2" => [137, "\xa3"], "\xb3" => [142, "\xa3"], "\xb4" => [150, "\xa3"], "\xb5" => [74, "\xa3"], "\xb6" => [90, "\xa3"], "\xb7" => [98, "\xa3"], "\xb8" => [107, "\xa3"], "\xb9" => [140, "\xa3"], "\xba" => [146, "\xa3"], "\xbb" => [102, "\xa3"], "\xbc" => [113, "\xa3"], "\xbd" => [121, "\xa3"], "\xbe" => [128, "\xa3"], "\xbf" => [12, "\xa3"], "\xc0" => [92, "\xa4"], "\xc1" => [95, "\xa4"], "\xc2" => [137, "\xa4"], "\xc3" => [142, "\xa4"], "\xc4" => [150, "\xa4"], "\xc5" => [74, "\xa4"], "\xc6" => [90, "\xa4"], "\xc7" => [98, "\xa4"], "\xc8" => [107, "\xa4"], "\xc9" => [140, "\xa4"], "\xca" => [146, "\xa4"], "\xcb" => [102, "\xa4"], "\xcc" => [113, "\xa4"], "\xcd" => [121, "\xa4"], "\xce" => [128, "\xa4"], "\xcf" => [12, "\xa4"], "\xd0" => [92, "\xa9"], "\xd1" => [95, "\xa9"], "\xd2" => [137, "\xa9"], "\xd3" => [142, "\xa9"], "\xd4" => [150, "\xa9"], "\xd5" => [74, "\xa9"], "\xd6" => [90, "\xa9"], "\xd7" => [98, "\xa9"], "\xd8" => [107, "\xa9"], "\xd9" => [140, "\xa9"], "\xda" => [146, "\xa9"], "\xdb" => [102, "\xa9"], "\xdc" => [113, "\xa9"], "\xdd" => [121, "\xa9"], "\xde" => [128, "\xa9"], "\xdf" => [12, "\xa9"], "\xe0" => [92, "\xaa"], "\xe1" => [95, "\xaa"], "\xe2" => [137, "\xaa"], "\xe3" => [142, "\xaa"], "\xe4" => [150, "\xaa"], "\xe5" => [74, "\xaa"], "\xe6" => [90, "\xaa"], "\xe7" => [98, "\xaa"], "\xe8" => [107, "\xaa"], "\xe9" => [140, "\xaa"], "\xea" => [146, "\xaa"], "\xeb" => [102, "\xaa"], "\xec" => [113, "\xaa"], "\xed" => [121, "\xaa"], "\xee" => [128, "\xaa"], "\xef" => [12, "\xaa"], "\xf0" => [92, "\xad"], "\xf1" => [95, "\xad"], "\xf2" => [137, "\xad"], "\xf3" => [142, "\xad"], "\xf4" => [150, "\xad"], "\xf5" => [74, "\xad"], "\xf6" => [90, "\xad"], "\xf7" => [98, "\xad"], "\xf8" => [107, "\xad"], "\xf9" => [140, "\xad"], "\xfa" => [146, "\xad"], "\xfb" => [102, "\xad"], "\xfc" => [113, "\xad"], "\xfd" => [121, "\xad"], "\xfe" => [128, "\xad"], "\xff" => [12, "\xad"]], ["\x00" => [92, "\xb0"], "\x01" => [95, "\xb0"], "\x02" => [137, "\xb0"], "\x03" => [142, "\xb0"], "\x04" => [150, "\xb0"], "\x05" => [74, "\xb0"], "\x06" => [90, "\xb0"], "\x07" => [98, "\xb0"], "\x08" => [107, "\xb0"], "\t" => [140, "\xb0"], "\n" => [146, "\xb0"], "\v" => [102, "\xb0"], "\f" => [113, "\xb0"], "\r" => [121, "\xb0"], "\x0e" => [128, "\xb0"], "\x0f" => [12, "\xb0"], "\x10" => [92, "\xb1"], "\x11" => [95, "\xb1"], "\x12" => [137, "\xb1"], "\x13" => [142, "\xb1"], "\x14" => [150, "\xb1"], "\x15" => [74, "\xb1"], "\x16" => [90, "\xb1"], "\x17" => [98, "\xb1"], "\x18" => [107, "\xb1"], "\x19" => [140, "\xb1"], "\x1a" => [146, "\xb1"], "\x1b" => [102, "\xb1"], "\x1c" => [113, "\xb1"], "\x1d" => [121, "\xb1"], "\x1e" => [128, "\xb1"], "\x1f" => [12, "\xb1"], " " => [92, "\xb3"], "!" => [95, "\xb3"], "\"" => [137, "\xb3"], "#" => [142, "\xb3"], "\$" => [150, "\xb3"], "%" => [74, "\xb3"], "&" => [90, "\xb3"], "'" => [98, "\xb3"], "(" => [107, "\xb3"], ")" => [140, "\xb3"], "*" => [146, "\xb3"], "+" => [102, "\xb3"], "," => [113, "\xb3"], "-" => [121, "\xb3"], "." => [128, "\xb3"], "/" => [12, "\xb3"], [92, "\xd1"], [95, "\xd1"], [137, "\xd1"], [142, "\xd1"], [150, "\xd1"], [74, "\xd1"], [90, "\xd1"], [98, "\xd1"], [107, "\xd1"], [140, "\xd1"], ":" => [146, "\xd1"], ";" => [102, "\xd1"], "<" => [113, "\xd1"], "=" => [121, "\xd1"], ">" => [128, "\xd1"], "?" => [12, "\xd1"], "@" => [92, "\xd8"], "A" => [95, "\xd8"], "B" => [137, "\xd8"], "C" => [142, "\xd8"], "D" => [150, "\xd8"], "E" => [74, "\xd8"], "F" => [90, "\xd8"], "G" => [98, "\xd8"], "H" => [107, "\xd8"], "I" => [140, "\xd8"], "J" => [146, "\xd8"], "K" => [102, "\xd8"], "L" => [113, "\xd8"], "M" => [121, "\xd8"], "N" => [128, "\xd8"], "O" => [12, "\xd8"], "P" => [92, "\xd9"], "Q" => [95, "\xd9"], "R" => [137, "\xd9"], "S" => [142, "\xd9"], "T" => [150, "\xd9"], "U" => [74, "\xd9"], "V" => [90, "\xd9"], "W" => [98, "\xd9"], "X" => [107, "\xd9"], "Y" => [140, "\xd9"], "Z" => [146, "\xd9"], "[" => [102, "\xd9"], "\\" => [113, "\xd9"], "]" => [121, "\xd9"], "^" => [128, "\xd9"], "_" => [12, "\xd9"], "`" => [92, "\xe3"], "a" => [95, "\xe3"], "b" => [137, "\xe3"], "c" => [142, "\xe3"], "d" => [150, "\xe3"], "e" => [74, "\xe3"], "f" => [90, "\xe3"], "g" => [98, "\xe3"], "h" => [107, "\xe3"], "i" => [140, "\xe3"], "j" => [146, "\xe3"], "k" => [102, "\xe3"], "l" => [113, "\xe3"], "m" => [121, "\xe3"], "n" => [128, "\xe3"], "o" => [12, "\xe3"], "p" => [92, "\xe5"], "q" => [95, "\xe5"], "r" => [137, "\xe5"], "s" => [142, "\xe5"], "t" => [150, "\xe5"], "u" => [74, "\xe5"], "v" => [90, "\xe5"], "w" => [98, "\xe5"], "x" => [107, "\xe5"], "y" => [140, "\xe5"], "z" => [146, "\xe5"], "{" => [102, "\xe5"], "|" => [113, "\xe5"], "}" => [121, "\xe5"], "~" => [128, "\xe5"], "" => [12, "\xe5"], "\x80" => [92, "\xe6"], "\x81" => [95, "\xe6"], "\x82" => [137, "\xe6"], "\x83" => [142, "\xe6"], "\x84" => [150, "\xe6"], "\x85" => [74, "\xe6"], "\x86" => [90, "\xe6"], "\x87" => [98, "\xe6"], "\x88" => [107, "\xe6"], "\x89" => [140, "\xe6"], "\x8a" => [146, "\xe6"], "\x8b" => [102, "\xe6"], "\x8c" => [113, "\xe6"], "\x8d" => [121, "\xe6"], "\x8e" => [128, "\xe6"], "\x8f" => [12, "\xe6"], "\x90" => [93, "\x81"], "\x91" => [138, "\x81"], "\x92" => [75, "\x81"], "\x93" => [91, "\x81"], "\x94" => [108, "\x81"], "\x95" => [103, "\x81"], "\x96" => [114, "\x81"], "\x97" => [14, "\x81"], "\x98" => [93, "\x84"], "\x99" => [138, "\x84"], "\x9a" => [75, "\x84"], "\x9b" => [91, "\x84"], "\x9c" => [108, "\x84"], "\x9d" => [103, "\x84"], "\x9e" => [114, "\x84"], "\x9f" => [14, "\x84"], "\xa0" => [93, "\x85"], "\xa1" => [138, "\x85"], "\xa2" => [75, "\x85"], "\xa3" => [91, "\x85"], "\xa4" => [108, "\x85"], "\xa5" => [103, "\x85"], "\xa6" => [114, "\x85"], "\xa7" => [14, "\x85"], "\xa8" => [93, "\x86"], "\xa9" => [138, "\x86"], "\xaa" => [75, "\x86"], "\xab" => [91, "\x86"], "\xac" => [108, "\x86"], "\xad" => [103, "\x86"], "\xae" => [114, "\x86"], "\xaf" => [14, "\x86"], "\xb0" => [93, "\x88"], "\xb1" => [138, "\x88"], "\xb2" => [75, "\x88"], "\xb3" => [91, "\x88"], "\xb4" => [108, "\x88"], "\xb5" => [103, "\x88"], "\xb6" => [114, "\x88"], "\xb7" => [14, "\x88"], "\xb8" => [93, "\x92"], "\xb9" => [138, "\x92"], "\xba" => [75, "\x92"], "\xbb" => [91, "\x92"], "\xbc" => [108, "\x92"], "\xbd" => [103, "\x92"], "\xbe" => [114, "\x92"], "\xbf" => [14, "\x92"], "\xc0" => [93, "\x9a"], "\xc1" => [138, "\x9a"], "\xc2" => [75, "\x9a"], "\xc3" => [91, "\x9a"], "\xc4" => [108, "\x9a"], "\xc5" => [103, "\x9a"], "\xc6" => [114, "\x9a"], "\xc7" => [14, "\x9a"], "\xc8" => [93, "\x9c"], "\xc9" => [138, "\x9c"], "\xca" => [75, "\x9c"], "\xcb" => [91, "\x9c"], "\xcc" => [108, "\x9c"], "\xcd" => [103, "\x9c"], "\xce" => [114, "\x9c"], "\xcf" => [14, "\x9c"], "\xd0" => [93, "\xa0"], "\xd1" => [138, "\xa0"], "\xd2" => [75, "\xa0"], "\xd3" => [91, "\xa0"], "\xd4" => [108, "\xa0"], "\xd5" => [103, "\xa0"], "\xd6" => [114, "\xa0"], "\xd7" => [14, "\xa0"], "\xd8" => [93, "\xa3"], "\xd9" => [138, "\xa3"], "\xda" => [75, "\xa3"], "\xdb" => [91, "\xa3"], "\xdc" => [108, "\xa3"], "\xdd" => [103, "\xa3"], "\xde" => [114, "\xa3"], "\xdf" => [14, "\xa3"], "\xe0" => [93, "\xa4"], "\xe1" => [138, "\xa4"], "\xe2" => [75, "\xa4"], "\xe3" => [91, "\xa4"], "\xe4" => [108, "\xa4"], "\xe5" => [103, "\xa4"], "\xe6" => [114, "\xa4"], "\xe7" => [14, "\xa4"], "\xe8" => [93, "\xa9"], "\xe9" => [138, "\xa9"], "\xea" => [75, "\xa9"], "\xeb" => [91, "\xa9"], "\xec" => [108, "\xa9"], "\xed" => [103, "\xa9"], "\xee" => [114, "\xa9"], "\xef" => [14, "\xa9"], "\xf0" => [93, "\xaa"], "\xf1" => [138, "\xaa"], "\xf2" => [75, "\xaa"], "\xf3" => [91, "\xaa"], "\xf4" => [108, "\xaa"], "\xf5" => [103, "\xaa"], "\xf6" => [114, "\xaa"], "\xf7" => [14, "\xaa"], "\xf8" => [93, "\xad"], "\xf9" => [138, "\xad"], "\xfa" => [75, "\xad"], "\xfb" => [91, "\xad"], "\xfc" => [108, "\xad"], "\xfd" => [103, "\xad"], "\xfe" => [114, "\xad"], "\xff" => [14, "\xad"]], ["\x00" => [94, "\x830"], "\x01" => [76, "\x830"], "\x02" => [104, "\x830"], "\x03" => [16, "\x830"], "\x04" => [94, "\x831"], "\x05" => [76, "\x831"], "\x06" => [104, "\x831"], "\x07" => [16, "\x831"], "\x08" => [94, "\x832"], "\t" => [76, "\x832"], "\n" => [104, "\x832"], "\v" => [16, "\x832"], "\f" => [94, "\x83a"], "\r" => [76, "\x83a"], "\x0e" => [104, "\x83a"], "\x0f" => [16, "\x83a"], "\x10" => [94, "\x83c"], "\x11" => [76, "\x83c"], "\x12" => [104, "\x83c"], "\x13" => [16, "\x83c"], "\x14" => [94, "\x83e"], "\x15" => [76, "\x83e"], "\x16" => [104, "\x83e"], "\x17" => [16, "\x83e"], "\x18" => [94, "\x83i"], "\x19" => [76, "\x83i"], "\x1a" => [104, "\x83i"], "\x1b" => [16, "\x83i"], "\x1c" => [94, "\x83o"], "\x1d" => [76, "\x83o"], "\x1e" => [104, "\x83o"], "\x1f" => [16, "\x83o"], " " => [94, "\x83s"], "!" => [76, "\x83s"], "\"" => [104, "\x83s"], "#" => [16, "\x83s"], "\$" => [94, "\x83t"], "%" => [76, "\x83t"], "&" => [104, "\x83t"], "'" => [16, "\x83t"], "(" => [77, "\x83 "], ")" => [18, "\x83 "], "*" => [77, "\x83%"], "+" => [18, "\x83%"], "," => [77, "\x83-"], "-" => [18, "\x83-"], "." => [77, "\x83."], "/" => [18, "\x83."], [77, "\x83/"], [18, "\x83/"], [77, "\x833"], [18, "\x833"], [77, "\x834"], [18, "\x834"], [77, "\x835"], [18, "\x835"], [77, "\x836"], [18, "\x836"], ":" => [77, "\x837"], ";" => [18, "\x837"], "<" => [77, "\x838"], "=" => [18, "\x838"], ">" => [77, "\x839"], "?" => [18, "\x839"], "@" => [77, "\x83="], "A" => [18, "\x83="], "B" => [77, "\x83A"], "C" => [18, "\x83A"], "D" => [77, "\x83_"], "E" => [18, "\x83_"], "F" => [77, "\x83b"], "G" => [18, "\x83b"], "H" => [77, "\x83d"], "I" => [18, "\x83d"], "J" => [77, "\x83f"], "K" => [18, "\x83f"], "L" => [77, "\x83g"], "M" => [18, "\x83g"], "N" => [77, "\x83h"], "O" => [18, "\x83h"], "P" => [77, "\x83l"], "Q" => [18, "\x83l"], "R" => [77, "\x83m"], "S" => [18, "\x83m"], "T" => [77, "\x83n"], "U" => [18, "\x83n"], "V" => [77, "\x83p"], "W" => [18, "\x83p"], "X" => [77, "\x83r"], "Y" => [18, "\x83r"], "Z" => [77, "\x83u"], "[" => [18, "\x83u"], "\\" => [0, "\x83:"], "]" => [0, "\x83B"], "^" => [0, "\x83C"], "_" => [0, "\x83D"], "`" => [0, "\x83E"], "a" => [0, "\x83F"], "b" => [0, "\x83G"], "c" => [0, "\x83H"], "d" => [0, "\x83I"], "e" => [0, "\x83J"], "f" => [0, "\x83K"], "g" => [0, "\x83L"], "h" => [0, "\x83M"], "i" => [0, "\x83N"], "j" => [0, "\x83O"], "k" => [0, "\x83P"], "l" => [0, "\x83Q"], "m" => [0, "\x83R"], "n" => [0, "\x83S"], "o" => [0, "\x83T"], "p" => [0, "\x83U"], "q" => [0, "\x83V"], "r" => [0, "\x83W"], "s" => [0, "\x83Y"], "t" => [0, "\x83j"], "u" => [0, "\x83k"], "v" => [0, "\x83q"], "w" => [0, "\x83v"], "x" => [0, "\x83w"], "y" => [0, "\x83x"], "z" => [0, "\x83y"], "{" => [0, "\x83z"], "|" => [82, "\x83"], "}" => [87, "\x83"], "~" => [130, "\x83"], "" => [9, "\x83"], "\x80" => [94, "\xa20"], "\x81" => [76, "\xa20"], "\x82" => [104, "\xa20"], "\x83" => [16, "\xa20"], "\x84" => [94, "\xa21"], "\x85" => [76, "\xa21"], "\x86" => [104, "\xa21"], "\x87" => [16, "\xa21"], "\x88" => [94, "\xa22"], "\x89" => [76, "\xa22"], "\x8a" => [104, "\xa22"], "\x8b" => [16, "\xa22"], "\x8c" => [94, "\xa2a"], "\x8d" => [76, "\xa2a"], "\x8e" => [104, "\xa2a"], "\x8f" => [16, "\xa2a"], "\x90" => [94, "\xa2c"], "\x91" => [76, "\xa2c"], "\x92" => [104, "\xa2c"], "\x93" => [16, "\xa2c"], "\x94" => [94, "\xa2e"], "\x95" => [76, "\xa2e"], "\x96" => [104, "\xa2e"], "\x97" => [16, "\xa2e"], "\x98" => [94, "\xa2i"], "\x99" => [76, "\xa2i"], "\x9a" => [104, "\xa2i"], "\x9b" => [16, "\xa2i"], "\x9c" => [94, "\xa2o"], "\x9d" => [76, "\xa2o"], "\x9e" => [104, "\xa2o"], "\x9f" => [16, "\xa2o"], "\xa0" => [94, "\xa2s"], "\xa1" => [76, "\xa2s"], "\xa2" => [104, "\xa2s"], "\xa3" => [16, "\xa2s"], "\xa4" => [94, "\xa2t"], "\xa5" => [76, "\xa2t"], "\xa6" => [104, "\xa2t"], "\xa7" => [16, "\xa2t"], "\xa8" => [77, "\xa2 "], "\xa9" => [18, "\xa2 "], "\xaa" => [77, "\xa2%"], "\xab" => [18, "\xa2%"], "\xac" => [77, "\xa2-"], "\xad" => [18, "\xa2-"], "\xae" => [77, "\xa2."], "\xaf" => [18, "\xa2."], "\xb0" => [77, "\xa2/"], "\xb1" => [18, "\xa2/"], "\xb2" => [77, "\xa23"], "\xb3" => [18, "\xa23"], "\xb4" => [77, "\xa24"], "\xb5" => [18, "\xa24"], "\xb6" => [77, "\xa25"], "\xb7" => [18, "\xa25"], "\xb8" => [77, "\xa26"], "\xb9" => [18, "\xa26"], "\xba" => [77, "\xa27"], "\xbb" => [18, "\xa27"], "\xbc" => [77, "\xa28"], "\xbd" => [18, "\xa28"], "\xbe" => [77, "\xa29"], "\xbf" => [18, "\xa29"], "\xc0" => [77, "\xa2="], "\xc1" => [18, "\xa2="], "\xc2" => [77, "\xa2A"], "\xc3" => [18, "\xa2A"], "\xc4" => [77, "\xa2_"], "\xc5" => [18, "\xa2_"], "\xc6" => [77, "\xa2b"], "\xc7" => [18, "\xa2b"], "\xc8" => [77, "\xa2d"], "\xc9" => [18, "\xa2d"], "\xca" => [77, "\xa2f"], "\xcb" => [18, "\xa2f"], "\xcc" => [77, "\xa2g"], "\xcd" => [18, "\xa2g"], "\xce" => [77, "\xa2h"], "\xcf" => [18, "\xa2h"], "\xd0" => [77, "\xa2l"], "\xd1" => [18, "\xa2l"], "\xd2" => [77, "\xa2m"], "\xd3" => [18, "\xa2m"], "\xd4" => [77, "\xa2n"], "\xd5" => [18, "\xa2n"], "\xd6" => [77, "\xa2p"], "\xd7" => [18, "\xa2p"], "\xd8" => [77, "\xa2r"], "\xd9" => [18, "\xa2r"], "\xda" => [77, "\xa2u"], "\xdb" => [18, "\xa2u"], "\xdc" => [0, "\xa2:"], "\xdd" => [0, "\xa2B"], "\xde" => [0, "\xa2C"], "\xdf" => [0, "\xa2D"], "\xe0" => [0, "\xa2E"], "\xe1" => [0, "\xa2F"], "\xe2" => [0, "\xa2G"], "\xe3" => [0, "\xa2H"], "\xe4" => [0, "\xa2I"], "\xe5" => [0, "\xa2J"], "\xe6" => [0, "\xa2K"], "\xe7" => [0, "\xa2L"], "\xe8" => [0, "\xa2M"], "\xe9" => [0, "\xa2N"], "\xea" => [0, "\xa2O"], "\xeb" => [0, "\xa2P"], "\xec" => [0, "\xa2Q"], "\xed" => [0, "\xa2R"], "\xee" => [0, "\xa2S"], "\xef" => [0, "\xa2T"], "\xf0" => [0, "\xa2U"], "\xf1" => [0, "\xa2V"], "\xf2" => [0, "\xa2W"], "\xf3" => [0, "\xa2Y"], "\xf4" => [0, "\xa2j"], "\xf5" => [0, "\xa2k"], "\xf6" => [0, "\xa2q"], "\xf7" => [0, "\xa2v"], "\xf8" => [0, "\xa2w"], "\xf9" => [0, "\xa2x"], "\xfa" => [0, "\xa2y"], "\xfb" => [0, "\xa2z"], "\xfc" => [82, "\xa2"], "\xfd" => [87, "\xa2"], "\xfe" => [130, "\xa2"], "\xff" => [9, "\xa2"]], ["\x00" => [77, "\x830"], "\x01" => [18, "\x830"], "\x02" => [77, "\x831"], "\x03" => [18, "\x831"], "\x04" => [77, "\x832"], "\x05" => [18, "\x832"], "\x06" => [77, "\x83a"], "\x07" => [18, "\x83a"], "\x08" => [77, "\x83c"], "\t" => [18, "\x83c"], "\n" => [77, "\x83e"], "\v" => [18, "\x83e"], "\f" => [77, "\x83i"], "\r" => [18, "\x83i"], "\x0e" => [77, "\x83o"], "\x0f" => [18, "\x83o"], "\x10" => [77, "\x83s"], "\x11" => [18, "\x83s"], "\x12" => [77, "\x83t"], "\x13" => [18, "\x83t"], "\x14" => [0, "\x83 "], "\x15" => [0, "\x83%"], "\x16" => [0, "\x83-"], "\x17" => [0, "\x83."], "\x18" => [0, "\x83/"], "\x19" => [0, "\x833"], "\x1a" => [0, "\x834"], "\x1b" => [0, "\x835"], "\x1c" => [0, "\x836"], "\x1d" => [0, "\x837"], "\x1e" => [0, "\x838"], "\x1f" => [0, "\x839"], " " => [0, "\x83="], "!" => [0, "\x83A"], "\"" => [0, "\x83_"], "#" => [0, "\x83b"], "\$" => [0, "\x83d"], "%" => [0, "\x83f"], "&" => [0, "\x83g"], "'" => [0, "\x83h"], "(" => [0, "\x83l"], ")" => [0, "\x83m"], "*" => [0, "\x83n"], "+" => [0, "\x83p"], "," => [0, "\x83r"], "-" => [0, "\x83u"], "." => [100, "\x83"], "/" => [110, "\x83"], [111, "\x83"], [115, "\x83"], [116, "\x83"], [118, "\x83"], [119, "\x83"], [122, "\x83"], [123, "\x83"], [125, "\x83"], [126, "\x83"], [129, "\x83"], ":" => [143, "\x83"], ";" => [148, "\x83"], "<" => [151, "\x83"], "=" => [153, "\x83"], ">" => [83, "\x83"], "?" => [10, "\x83"], "@" => [77, "\xa20"], "A" => [18, "\xa20"], "B" => [77, "\xa21"], "C" => [18, "\xa21"], "D" => [77, "\xa22"], "E" => [18, "\xa22"], "F" => [77, "\xa2a"], "G" => [18, "\xa2a"], "H" => [77, "\xa2c"], "I" => [18, "\xa2c"], "J" => [77, "\xa2e"], "K" => [18, "\xa2e"], "L" => [77, "\xa2i"], "M" => [18, "\xa2i"], "N" => [77, "\xa2o"], "O" => [18, "\xa2o"], "P" => [77, "\xa2s"], "Q" => [18, "\xa2s"], "R" => [77, "\xa2t"], "S" => [18, "\xa2t"], "T" => [0, "\xa2 "], "U" => [0, "\xa2%"], "V" => [0, "\xa2-"], "W" => [0, "\xa2."], "X" => [0, "\xa2/"], "Y" => [0, "\xa23"], "Z" => [0, "\xa24"], "[" => [0, "\xa25"], "\\" => [0, "\xa26"], "]" => [0, "\xa27"], "^" => [0, "\xa28"], "_" => [0, "\xa29"], "`" => [0, "\xa2="], "a" => [0, "\xa2A"], "b" => [0, "\xa2_"], "c" => [0, "\xa2b"], "d" => [0, "\xa2d"], "e" => [0, "\xa2f"], "f" => [0, "\xa2g"], "g" => [0, "\xa2h"], "h" => [0, "\xa2l"], "i" => [0, "\xa2m"], "j" => [0, "\xa2n"], "k" => [0, "\xa2p"], "l" => [0, "\xa2r"], "m" => [0, "\xa2u"], "n" => [100, "\xa2"], "o" => [110, "\xa2"], "p" => [111, "\xa2"], "q" => [115, "\xa2"], "r" => [116, "\xa2"], "s" => [118, "\xa2"], "t" => [119, "\xa2"], "u" => [122, "\xa2"], "v" => [123, "\xa2"], "w" => [125, "\xa2"], "x" => [126, "\xa2"], "y" => [129, "\xa2"], "z" => [143, "\xa2"], "{" => [148, "\xa2"], "|" => [151, "\xa2"], "}" => [153, "\xa2"], "~" => [83, "\xa2"], "" => [10, "\xa2"], "\x80" => [77, "\xb80"], "\x81" => [18, "\xb80"], "\x82" => [77, "\xb81"], "\x83" => [18, "\xb81"], "\x84" => [77, "\xb82"], "\x85" => [18, "\xb82"], "\x86" => [77, "\xb8a"], "\x87" => [18, "\xb8a"], "\x88" => [77, "\xb8c"], "\x89" => [18, "\xb8c"], "\x8a" => [77, "\xb8e"], "\x8b" => [18, "\xb8e"], "\x8c" => [77, "\xb8i"], "\x8d" => [18, "\xb8i"], "\x8e" => [77, "\xb8o"], "\x8f" => [18, "\xb8o"], "\x90" => [77, "\xb8s"], "\x91" => [18, "\xb8s"], "\x92" => [77, "\xb8t"], "\x93" => [18, "\xb8t"], "\x94" => [0, "\xb8 "], "\x95" => [0, "\xb8%"], "\x96" => [0, "\xb8-"], "\x97" => [0, "\xb8."], "\x98" => [0, "\xb8/"], "\x99" => [0, "\xb83"], "\x9a" => [0, "\xb84"], "\x9b" => [0, "\xb85"], "\x9c" => [0, "\xb86"], "\x9d" => [0, "\xb87"], "\x9e" => [0, "\xb88"], "\x9f" => [0, "\xb89"], "\xa0" => [0, "\xb8="], "\xa1" => [0, "\xb8A"], "\xa2" => [0, "\xb8_"], "\xa3" => [0, "\xb8b"], "\xa4" => [0, "\xb8d"], "\xa5" => [0, "\xb8f"], "\xa6" => [0, "\xb8g"], "\xa7" => [0, "\xb8h"], "\xa8" => [0, "\xb8l"], "\xa9" => [0, "\xb8m"], "\xaa" => [0, "\xb8n"], "\xab" => [0, "\xb8p"], "\xac" => [0, "\xb8r"], "\xad" => [0, "\xb8u"], "\xae" => [100, "\xb8"], "\xaf" => [110, "\xb8"], "\xb0" => [111, "\xb8"], "\xb1" => [115, "\xb8"], "\xb2" => [116, "\xb8"], "\xb3" => [118, "\xb8"], "\xb4" => [119, "\xb8"], "\xb5" => [122, "\xb8"], "\xb6" => [123, "\xb8"], "\xb7" => [125, "\xb8"], "\xb8" => [126, "\xb8"], "\xb9" => [129, "\xb8"], "\xba" => [143, "\xb8"], "\xbb" => [148, "\xb8"], "\xbc" => [151, "\xb8"], "\xbd" => [153, "\xb8"], "\xbe" => [83, "\xb8"], "\xbf" => [10, "\xb8"], "\xc0" => [77, "\xc20"], "\xc1" => [18, "\xc20"], "\xc2" => [77, "\xc21"], "\xc3" => [18, "\xc21"], "\xc4" => [77, "\xc22"], "\xc5" => [18, "\xc22"], "\xc6" => [77, "\xc2a"], "\xc7" => [18, "\xc2a"], "\xc8" => [77, "\xc2c"], "\xc9" => [18, "\xc2c"], "\xca" => [77, "\xc2e"], "\xcb" => [18, "\xc2e"], "\xcc" => [77, "\xc2i"], "\xcd" => [18, "\xc2i"], "\xce" => [77, "\xc2o"], "\xcf" => [18, "\xc2o"], "\xd0" => [77, "\xc2s"], "\xd1" => [18, "\xc2s"], "\xd2" => [77, "\xc2t"], "\xd3" => [18, "\xc2t"], "\xd4" => [0, "\xc2 "], "\xd5" => [0, "\xc2%"], "\xd6" => [0, "\xc2-"], "\xd7" => [0, "\xc2."], "\xd8" => [0, "\xc2/"], "\xd9" => [0, "\xc23"], "\xda" => [0, "\xc24"], "\xdb" => [0, "\xc25"], "\xdc" => [0, "\xc26"], "\xdd" => [0, "\xc27"], "\xde" => [0, "\xc28"], "\xdf" => [0, "\xc29"], "\xe0" => [0, "\xc2="], "\xe1" => [0, "\xc2A"], "\xe2" => [0, "\xc2_"], "\xe3" => [0, "\xc2b"], "\xe4" => [0, "\xc2d"], "\xe5" => [0, "\xc2f"], "\xe6" => [0, "\xc2g"], "\xe7" => [0, "\xc2h"], "\xe8" => [0, "\xc2l"], "\xe9" => [0, "\xc2m"], "\xea" => [0, "\xc2n"], "\xeb" => [0, "\xc2p"], "\xec" => [0, "\xc2r"], "\xed" => [0, "\xc2u"], "\xee" => [100, "\xc2"], "\xef" => [110, "\xc2"], "\xf0" => [111, "\xc2"], "\xf1" => [115, "\xc2"], "\xf2" => [116, "\xc2"], "\xf3" => [118, "\xc2"], "\xf4" => [119, "\xc2"], "\xf5" => [122, "\xc2"], "\xf6" => [123, "\xc2"], "\xf7" => [125, "\xc2"], "\xf8" => [126, "\xc2"], "\xf9" => [129, "\xc2"], "\xfa" => [143, "\xc2"], "\xfb" => [148, "\xc2"], "\xfc" => [151, "\xc2"], "\xfd" => [153, "\xc2"], "\xfe" => [83, "\xc2"], "\xff" => [10, "\xc2"]], ["\x00" => [0, "\x830"], "\x01" => [0, "\x831"], "\x02" => [0, "\x832"], "\x03" => [0, "\x83a"], "\x04" => [0, "\x83c"], "\x05" => [0, "\x83e"], "\x06" => [0, "\x83i"], "\x07" => [0, "\x83o"], "\x08" => [0, "\x83s"], "\t" => [0, "\x83t"], "\n" => [73, "\x83"], "\v" => [88, "\x83"], "\f" => [89, "\x83"], "\r" => [96, "\x83"], "\x0e" => [97, "\x83"], "\x0f" => [99, "\x83"], "\x10" => [106, "\x83"], "\x11" => [136, "\x83"], "\x12" => [139, "\x83"], "\x13" => [141, "\x83"], "\x14" => [145, "\x83"], "\x15" => [147, "\x83"], "\x16" => [149, "\x83"], "\x17" => [101, "\x83"], "\x18" => [112, "\x83"], "\x19" => [117, "\x83"], "\x1a" => [120, "\x83"], "\x1b" => [124, "\x83"], "\x1c" => [127, "\x83"], "\x1d" => [144, "\x83"], "\x1e" => [152, "\x83"], "\x1f" => [11, "\x83"], " " => [0, "\xa20"], "!" => [0, "\xa21"], "\"" => [0, "\xa22"], "#" => [0, "\xa2a"], "\$" => [0, "\xa2c"], "%" => [0, "\xa2e"], "&" => [0, "\xa2i"], "'" => [0, "\xa2o"], "(" => [0, "\xa2s"], ")" => [0, "\xa2t"], "*" => [73, "\xa2"], "+" => [88, "\xa2"], "," => [89, "\xa2"], "-" => [96, "\xa2"], "." => [97, "\xa2"], "/" => [99, "\xa2"], [106, "\xa2"], [136, "\xa2"], [139, "\xa2"], [141, "\xa2"], [145, "\xa2"], [147, "\xa2"], [149, "\xa2"], [101, "\xa2"], [112, "\xa2"], [117, "\xa2"], ":" => [120, "\xa2"], ";" => [124, "\xa2"], "<" => [127, "\xa2"], "=" => [144, "\xa2"], ">" => [152, "\xa2"], "?" => [11, "\xa2"], "@" => [0, "\xb80"], "A" => [0, "\xb81"], "B" => [0, "\xb82"], "C" => [0, "\xb8a"], "D" => [0, "\xb8c"], "E" => [0, "\xb8e"], "F" => [0, "\xb8i"], "G" => [0, "\xb8o"], "H" => [0, "\xb8s"], "I" => [0, "\xb8t"], "J" => [73, "\xb8"], "K" => [88, "\xb8"], "L" => [89, "\xb8"], "M" => [96, "\xb8"], "N" => [97, "\xb8"], "O" => [99, "\xb8"], "P" => [106, "\xb8"], "Q" => [136, "\xb8"], "R" => [139, "\xb8"], "S" => [141, "\xb8"], "T" => [145, "\xb8"], "U" => [147, "\xb8"], "V" => [149, "\xb8"], "W" => [101, "\xb8"], "X" => [112, "\xb8"], "Y" => [117, "\xb8"], "Z" => [120, "\xb8"], "[" => [124, "\xb8"], "\\" => [127, "\xb8"], "]" => [144, "\xb8"], "^" => [152, "\xb8"], "_" => [11, "\xb8"], "`" => [0, "\xc20"], "a" => [0, "\xc21"], "b" => [0, "\xc22"], "c" => [0, "\xc2a"], "d" => [0, "\xc2c"], "e" => [0, "\xc2e"], "f" => [0, "\xc2i"], "g" => [0, "\xc2o"], "h" => [0, "\xc2s"], "i" => [0, "\xc2t"], "j" => [73, "\xc2"], "k" => [88, "\xc2"], "l" => [89, "\xc2"], "m" => [96, "\xc2"], "n" => [97, "\xc2"], "o" => [99, "\xc2"], "p" => [106, "\xc2"], "q" => [136, "\xc2"], "r" => [139, "\xc2"], "s" => [141, "\xc2"], "t" => [145, "\xc2"], "u" => [147, "\xc2"], "v" => [149, "\xc2"], "w" => [101, "\xc2"], "x" => [112, "\xc2"], "y" => [117, "\xc2"], "z" => [120, "\xc2"], "{" => [124, "\xc2"], "|" => [127, "\xc2"], "}" => [144, "\xc2"], "~" => [152, "\xc2"], "" => [11, "\xc2"], "\x80" => [0, "\xe00"], "\x81" => [0, "\xe01"], "\x82" => [0, "\xe02"], "\x83" => [0, "\xe0a"], "\x84" => [0, "\xe0c"], "\x85" => [0, "\xe0e"], "\x86" => [0, "\xe0i"], "\x87" => [0, "\xe0o"], "\x88" => [0, "\xe0s"], "\x89" => [0, "\xe0t"], "\x8a" => [73, "\xe0"], "\x8b" => [88, "\xe0"], "\x8c" => [89, "\xe0"], "\x8d" => [96, "\xe0"], "\x8e" => [97, "\xe0"], "\x8f" => [99, "\xe0"], "\x90" => [106, "\xe0"], "\x91" => [136, "\xe0"], "\x92" => [139, "\xe0"], "\x93" => [141, "\xe0"], "\x94" => [145, "\xe0"], "\x95" => [147, "\xe0"], "\x96" => [149, "\xe0"], "\x97" => [101, "\xe0"], "\x98" => [112, "\xe0"], "\x99" => [117, "\xe0"], "\x9a" => [120, "\xe0"], "\x9b" => [124, "\xe0"], "\x9c" => [127, "\xe0"], "\x9d" => [144, "\xe0"], "\x9e" => [152, "\xe0"], "\x9f" => [11, "\xe0"], "\xa0" => [0, "\xe20"], "\xa1" => [0, "\xe21"], "\xa2" => [0, "\xe22"], "\xa3" => [0, "\xe2a"], "\xa4" => [0, "\xe2c"], "\xa5" => [0, "\xe2e"], "\xa6" => [0, "\xe2i"], "\xa7" => [0, "\xe2o"], "\xa8" => [0, "\xe2s"], "\xa9" => [0, "\xe2t"], "\xaa" => [73, "\xe2"], "\xab" => [88, "\xe2"], "\xac" => [89, "\xe2"], "\xad" => [96, "\xe2"], "\xae" => [97, "\xe2"], "\xaf" => [99, "\xe2"], "\xb0" => [106, "\xe2"], "\xb1" => [136, "\xe2"], "\xb2" => [139, "\xe2"], "\xb3" => [141, "\xe2"], "\xb4" => [145, "\xe2"], "\xb5" => [147, "\xe2"], "\xb6" => [149, "\xe2"], "\xb7" => [101, "\xe2"], "\xb8" => [112, "\xe2"], "\xb9" => [117, "\xe2"], "\xba" => [120, "\xe2"], "\xbb" => [124, "\xe2"], "\xbc" => [127, "\xe2"], "\xbd" => [144, "\xe2"], "\xbe" => [152, "\xe2"], "\xbf" => [11, "\xe2"], "\xc0" => [92, "\x99"], "\xc1" => [95, "\x99"], "\xc2" => [137, "\x99"], "\xc3" => [142, "\x99"], "\xc4" => [150, "\x99"], "\xc5" => [74, "\x99"], "\xc6" => [90, "\x99"], "\xc7" => [98, "\x99"], "\xc8" => [107, "\x99"], "\xc9" => [140, "\x99"], "\xca" => [146, "\x99"], "\xcb" => [102, "\x99"], "\xcc" => [113, "\x99"], "\xcd" => [121, "\x99"], "\xce" => [128, "\x99"], "\xcf" => [12, "\x99"], "\xd0" => [92, "\xa1"], "\xd1" => [95, "\xa1"], "\xd2" => [137, "\xa1"], "\xd3" => [142, "\xa1"], "\xd4" => [150, "\xa1"], "\xd5" => [74, "\xa1"], "\xd6" => [90, "\xa1"], "\xd7" => [98, "\xa1"], "\xd8" => [107, "\xa1"], "\xd9" => [140, "\xa1"], "\xda" => [146, "\xa1"], "\xdb" => [102, "\xa1"], "\xdc" => [113, "\xa1"], "\xdd" => [121, "\xa1"], "\xde" => [128, "\xa1"], "\xdf" => [12, "\xa1"], "\xe0" => [92, "\xa7"], "\xe1" => [95, "\xa7"], "\xe2" => [137, "\xa7"], "\xe3" => [142, "\xa7"], "\xe4" => [150, "\xa7"], "\xe5" => [74, "\xa7"], "\xe6" => [90, "\xa7"], "\xe7" => [98, "\xa7"], "\xe8" => [107, "\xa7"], "\xe9" => [140, "\xa7"], "\xea" => [146, "\xa7"], "\xeb" => [102, "\xa7"], "\xec" => [113, "\xa7"], "\xed" => [121, "\xa7"], "\xee" => [128, "\xa7"], "\xef" => [12, "\xa7"], "\xf0" => [92, "\xac"], "\xf1" => [95, "\xac"], "\xf2" => [137, "\xac"], "\xf3" => [142, "\xac"], "\xf4" => [150, "\xac"], "\xf5" => [74, "\xac"], "\xf6" => [90, "\xac"], "\xf7" => [98, "\xac"], "\xf8" => [107, "\xac"], "\xf9" => [140, "\xac"], "\xfa" => [146, "\xac"], "\xfb" => [102, "\xac"], "\xfc" => [113, "\xac"], "\xfd" => [121, "\xac"], "\xfe" => [128, "\xac"], "\xff" => [12, "\xac"]], ["\x00" => [94, "\x850"], "\x01" => [76, "\x850"], "\x02" => [104, "\x850"], "\x03" => [16, "\x850"], "\x04" => [94, "\x851"], "\x05" => [76, "\x851"], "\x06" => [104, "\x851"], "\x07" => [16, "\x851"], "\x08" => [94, "\x852"], "\t" => [76, "\x852"], "\n" => [104, "\x852"], "\v" => [16, "\x852"], "\f" => [94, "\x85a"], "\r" => [76, "\x85a"], "\x0e" => [104, "\x85a"], "\x0f" => [16, "\x85a"], "\x10" => [94, "\x85c"], "\x11" => [76, "\x85c"], "\x12" => [104, "\x85c"], "\x13" => [16, "\x85c"], "\x14" => [94, "\x85e"], "\x15" => [76, "\x85e"], "\x16" => [104, "\x85e"], "\x17" => [16, "\x85e"], "\x18" => [94, "\x85i"], "\x19" => [76, "\x85i"], "\x1a" => [104, "\x85i"], "\x1b" => [16, "\x85i"], "\x1c" => [94, "\x85o"], "\x1d" => [76, "\x85o"], "\x1e" => [104, "\x85o"], "\x1f" => [16, "\x85o"], " " => [94, "\x85s"], "!" => [76, "\x85s"], "\"" => [104, "\x85s"], "#" => [16, "\x85s"], "\$" => [94, "\x85t"], "%" => [76, "\x85t"], "&" => [104, "\x85t"], "'" => [16, "\x85t"], "(" => [77, "\x85 "], ")" => [18, "\x85 "], "*" => [77, "\x85%"], "+" => [18, "\x85%"], "," => [77, "\x85-"], "-" => [18, "\x85-"], "." => [77, "\x85."], "/" => [18, "\x85."], [77, "\x85/"], [18, "\x85/"], [77, "\x853"], [18, "\x853"], [77, "\x854"], [18, "\x854"], [77, "\x855"], [18, "\x855"], [77, "\x856"], [18, "\x856"], ":" => [77, "\x857"], ";" => [18, "\x857"], "<" => [77, "\x858"], "=" => [18, "\x858"], ">" => [77, "\x859"], "?" => [18, "\x859"], "@" => [77, "\x85="], "A" => [18, "\x85="], "B" => [77, "\x85A"], "C" => [18, "\x85A"], "D" => [77, "\x85_"], "E" => [18, "\x85_"], "F" => [77, "\x85b"], "G" => [18, "\x85b"], "H" => [77, "\x85d"], "I" => [18, "\x85d"], "J" => [77, "\x85f"], "K" => [18, "\x85f"], "L" => [77, "\x85g"], "M" => [18, "\x85g"], "N" => [77, "\x85h"], "O" => [18, "\x85h"], "P" => [77, "\x85l"], "Q" => [18, "\x85l"], "R" => [77, "\x85m"], "S" => [18, "\x85m"], "T" => [77, "\x85n"], "U" => [18, "\x85n"], "V" => [77, "\x85p"], "W" => [18, "\x85p"], "X" => [77, "\x85r"], "Y" => [18, "\x85r"], "Z" => [77, "\x85u"], "[" => [18, "\x85u"], "\\" => [0, "\x85:"], "]" => [0, "\x85B"], "^" => [0, "\x85C"], "_" => [0, "\x85D"], "`" => [0, "\x85E"], "a" => [0, "\x85F"], "b" => [0, "\x85G"], "c" => [0, "\x85H"], "d" => [0, "\x85I"], "e" => [0, "\x85J"], "f" => [0, "\x85K"], "g" => [0, "\x85L"], "h" => [0, "\x85M"], "i" => [0, "\x85N"], "j" => [0, "\x85O"], "k" => [0, "\x85P"], "l" => [0, "\x85Q"], "m" => [0, "\x85R"], "n" => [0, "\x85S"], "o" => [0, "\x85T"], "p" => [0, "\x85U"], "q" => [0, "\x85V"], "r" => [0, "\x85W"], "s" => [0, "\x85Y"], "t" => [0, "\x85j"], "u" => [0, "\x85k"], "v" => [0, "\x85q"], "w" => [0, "\x85v"], "x" => [0, "\x85w"], "y" => [0, "\x85x"], "z" => [0, "\x85y"], "{" => [0, "\x85z"], "|" => [82, "\x85"], "}" => [87, "\x85"], "~" => [130, "\x85"], "" => [9, "\x85"], "\x80" => [94, "\x860"], "\x81" => [76, "\x860"], "\x82" => [104, "\x860"], "\x83" => [16, "\x860"], "\x84" => [94, "\x861"], "\x85" => [76, "\x861"], "\x86" => [104, "\x861"], "\x87" => [16, "\x861"], "\x88" => [94, "\x862"], "\x89" => [76, "\x862"], "\x8a" => [104, "\x862"], "\x8b" => [16, "\x862"], "\x8c" => [94, "\x86a"], "\x8d" => [76, "\x86a"], "\x8e" => [104, "\x86a"], "\x8f" => [16, "\x86a"], "\x90" => [94, "\x86c"], "\x91" => [76, "\x86c"], "\x92" => [104, "\x86c"], "\x93" => [16, "\x86c"], "\x94" => [94, "\x86e"], "\x95" => [76, "\x86e"], "\x96" => [104, "\x86e"], "\x97" => [16, "\x86e"], "\x98" => [94, "\x86i"], "\x99" => [76, "\x86i"], "\x9a" => [104, "\x86i"], "\x9b" => [16, "\x86i"], "\x9c" => [94, "\x86o"], "\x9d" => [76, "\x86o"], "\x9e" => [104, "\x86o"], "\x9f" => [16, "\x86o"], "\xa0" => [94, "\x86s"], "\xa1" => [76, "\x86s"], "\xa2" => [104, "\x86s"], "\xa3" => [16, "\x86s"], "\xa4" => [94, "\x86t"], "\xa5" => [76, "\x86t"], "\xa6" => [104, "\x86t"], "\xa7" => [16, "\x86t"], "\xa8" => [77, "\x86 "], "\xa9" => [18, "\x86 "], "\xaa" => [77, "\x86%"], "\xab" => [18, "\x86%"], "\xac" => [77, "\x86-"], "\xad" => [18, "\x86-"], "\xae" => [77, "\x86."], "\xaf" => [18, "\x86."], "\xb0" => [77, "\x86/"], "\xb1" => [18, "\x86/"], "\xb2" => [77, "\x863"], "\xb3" => [18, "\x863"], "\xb4" => [77, "\x864"], "\xb5" => [18, "\x864"], "\xb6" => [77, "\x865"], "\xb7" => [18, "\x865"], "\xb8" => [77, "\x866"], "\xb9" => [18, "\x866"], "\xba" => [77, "\x867"], "\xbb" => [18, "\x867"], "\xbc" => [77, "\x868"], "\xbd" => [18, "\x868"], "\xbe" => [77, "\x869"], "\xbf" => [18, "\x869"], "\xc0" => [77, "\x86="], "\xc1" => [18, "\x86="], "\xc2" => [77, "\x86A"], "\xc3" => [18, "\x86A"], "\xc4" => [77, "\x86_"], "\xc5" => [18, "\x86_"], "\xc6" => [77, "\x86b"], "\xc7" => [18, "\x86b"], "\xc8" => [77, "\x86d"], "\xc9" => [18, "\x86d"], "\xca" => [77, "\x86f"], "\xcb" => [18, "\x86f"], "\xcc" => [77, "\x86g"], "\xcd" => [18, "\x86g"], "\xce" => [77, "\x86h"], "\xcf" => [18, "\x86h"], "\xd0" => [77, "\x86l"], "\xd1" => [18, "\x86l"], "\xd2" => [77, "\x86m"], "\xd3" => [18, "\x86m"], "\xd4" => [77, "\x86n"], "\xd5" => [18, "\x86n"], "\xd6" => [77, "\x86p"], "\xd7" => [18, "\x86p"], "\xd8" => [77, "\x86r"], "\xd9" => [18, "\x86r"], "\xda" => [77, "\x86u"], "\xdb" => [18, "\x86u"], "\xdc" => [0, "\x86:"], "\xdd" => [0, "\x86B"], "\xde" => [0, "\x86C"], "\xdf" => [0, "\x86D"], "\xe0" => [0, "\x86E"], "\xe1" => [0, "\x86F"], "\xe2" => [0, "\x86G"], "\xe3" => [0, "\x86H"], "\xe4" => [0, "\x86I"], "\xe5" => [0, "\x86J"], "\xe6" => [0, "\x86K"], "\xe7" => [0, "\x86L"], "\xe8" => [0, "\x86M"], "\xe9" => [0, "\x86N"], "\xea" => [0, "\x86O"], "\xeb" => [0, "\x86P"], "\xec" => [0, "\x86Q"], "\xed" => [0, "\x86R"], "\xee" => [0, "\x86S"], "\xef" => [0, "\x86T"], "\xf0" => [0, "\x86U"], "\xf1" => [0, "\x86V"], "\xf2" => [0, "\x86W"], "\xf3" => [0, "\x86Y"], "\xf4" => [0, "\x86j"], "\xf5" => [0, "\x86k"], "\xf6" => [0, "\x86q"], "\xf7" => [0, "\x86v"], "\xf8" => [0, "\x86w"], "\xf9" => [0, "\x86x"], "\xfa" => [0, "\x86y"], "\xfb" => [0, "\x86z"], "\xfc" => [82, "\x86"], "\xfd" => [87, "\x86"], "\xfe" => [130, "\x86"], "\xff" => [9, "\x86"]], ["\x00" => [77, "\x850"], "\x01" => [18, "\x850"], "\x02" => [77, "\x851"], "\x03" => [18, "\x851"], "\x04" => [77, "\x852"], "\x05" => [18, "\x852"], "\x06" => [77, "\x85a"], "\x07" => [18, "\x85a"], "\x08" => [77, "\x85c"], "\t" => [18, "\x85c"], "\n" => [77, "\x85e"], "\v" => [18, "\x85e"], "\f" => [77, "\x85i"], "\r" => [18, "\x85i"], "\x0e" => [77, "\x85o"], "\x0f" => [18, "\x85o"], "\x10" => [77, "\x85s"], "\x11" => [18, "\x85s"], "\x12" => [77, "\x85t"], "\x13" => [18, "\x85t"], "\x14" => [0, "\x85 "], "\x15" => [0, "\x85%"], "\x16" => [0, "\x85-"], "\x17" => [0, "\x85."], "\x18" => [0, "\x85/"], "\x19" => [0, "\x853"], "\x1a" => [0, "\x854"], "\x1b" => [0, "\x855"], "\x1c" => [0, "\x856"], "\x1d" => [0, "\x857"], "\x1e" => [0, "\x858"], "\x1f" => [0, "\x859"], " " => [0, "\x85="], "!" => [0, "\x85A"], "\"" => [0, "\x85_"], "#" => [0, "\x85b"], "\$" => [0, "\x85d"], "%" => [0, "\x85f"], "&" => [0, "\x85g"], "'" => [0, "\x85h"], "(" => [0, "\x85l"], ")" => [0, "\x85m"], "*" => [0, "\x85n"], "+" => [0, "\x85p"], "," => [0, "\x85r"], "-" => [0, "\x85u"], "." => [100, "\x85"], "/" => [110, "\x85"], [111, "\x85"], [115, "\x85"], [116, "\x85"], [118, "\x85"], [119, "\x85"], [122, "\x85"], [123, "\x85"], [125, "\x85"], [126, "\x85"], [129, "\x85"], ":" => [143, "\x85"], ";" => [148, "\x85"], "<" => [151, "\x85"], "=" => [153, "\x85"], ">" => [83, "\x85"], "?" => [10, "\x85"], "@" => [77, "\x860"], "A" => [18, "\x860"], "B" => [77, "\x861"], "C" => [18, "\x861"], "D" => [77, "\x862"], "E" => [18, "\x862"], "F" => [77, "\x86a"], "G" => [18, "\x86a"], "H" => [77, "\x86c"], "I" => [18, "\x86c"], "J" => [77, "\x86e"], "K" => [18, "\x86e"], "L" => [77, "\x86i"], "M" => [18, "\x86i"], "N" => [77, "\x86o"], "O" => [18, "\x86o"], "P" => [77, "\x86s"], "Q" => [18, "\x86s"], "R" => [77, "\x86t"], "S" => [18, "\x86t"], "T" => [0, "\x86 "], "U" => [0, "\x86%"], "V" => [0, "\x86-"], "W" => [0, "\x86."], "X" => [0, "\x86/"], "Y" => [0, "\x863"], "Z" => [0, "\x864"], "[" => [0, "\x865"], "\\" => [0, "\x866"], "]" => [0, "\x867"], "^" => [0, "\x868"], "_" => [0, "\x869"], "`" => [0, "\x86="], "a" => [0, "\x86A"], "b" => [0, "\x86_"], "c" => [0, "\x86b"], "d" => [0, "\x86d"], "e" => [0, "\x86f"], "f" => [0, "\x86g"], "g" => [0, "\x86h"], "h" => [0, "\x86l"], "i" => [0, "\x86m"], "j" => [0, "\x86n"], "k" => [0, "\x86p"], "l" => [0, "\x86r"], "m" => [0, "\x86u"], "n" => [100, "\x86"], "o" => [110, "\x86"], "p" => [111, "\x86"], "q" => [115, "\x86"], "r" => [116, "\x86"], "s" => [118, "\x86"], "t" => [119, "\x86"], "u" => [122, "\x86"], "v" => [123, "\x86"], "w" => [125, "\x86"], "x" => [126, "\x86"], "y" => [129, "\x86"], "z" => [143, "\x86"], "{" => [148, "\x86"], "|" => [151, "\x86"], "}" => [153, "\x86"], "~" => [83, "\x86"], "" => [10, "\x86"], "\x80" => [77, "\x880"], "\x81" => [18, "\x880"], "\x82" => [77, "\x881"], "\x83" => [18, "\x881"], "\x84" => [77, "\x882"], "\x85" => [18, "\x882"], "\x86" => [77, "\x88a"], "\x87" => [18, "\x88a"], "\x88" => [77, "\x88c"], "\x89" => [18, "\x88c"], "\x8a" => [77, "\x88e"], "\x8b" => [18, "\x88e"], "\x8c" => [77, "\x88i"], "\x8d" => [18, "\x88i"], "\x8e" => [77, "\x88o"], "\x8f" => [18, "\x88o"], "\x90" => [77, "\x88s"], "\x91" => [18, "\x88s"], "\x92" => [77, "\x88t"], "\x93" => [18, "\x88t"], "\x94" => [0, "\x88 "], "\x95" => [0, "\x88%"], "\x96" => [0, "\x88-"], "\x97" => [0, "\x88."], "\x98" => [0, "\x88/"], "\x99" => [0, "\x883"], "\x9a" => [0, "\x884"], "\x9b" => [0, "\x885"], "\x9c" => [0, "\x886"], "\x9d" => [0, "\x887"], "\x9e" => [0, "\x888"], "\x9f" => [0, "\x889"], "\xa0" => [0, "\x88="], "\xa1" => [0, "\x88A"], "\xa2" => [0, "\x88_"], "\xa3" => [0, "\x88b"], "\xa4" => [0, "\x88d"], "\xa5" => [0, "\x88f"], "\xa6" => [0, "\x88g"], "\xa7" => [0, "\x88h"], "\xa8" => [0, "\x88l"], "\xa9" => [0, "\x88m"], "\xaa" => [0, "\x88n"], "\xab" => [0, "\x88p"], "\xac" => [0, "\x88r"], "\xad" => [0, "\x88u"], "\xae" => [100, "\x88"], "\xaf" => [110, "\x88"], "\xb0" => [111, "\x88"], "\xb1" => [115, "\x88"], "\xb2" => [116, "\x88"], "\xb3" => [118, "\x88"], "\xb4" => [119, "\x88"], "\xb5" => [122, "\x88"], "\xb6" => [123, "\x88"], "\xb7" => [125, "\x88"], "\xb8" => [126, "\x88"], "\xb9" => [129, "\x88"], "\xba" => [143, "\x88"], "\xbb" => [148, "\x88"], "\xbc" => [151, "\x88"], "\xbd" => [153, "\x88"], "\xbe" => [83, "\x88"], "\xbf" => [10, "\x88"], "\xc0" => [77, "\x920"], "\xc1" => [18, "\x920"], "\xc2" => [77, "\x921"], "\xc3" => [18, "\x921"], "\xc4" => [77, "\x922"], "\xc5" => [18, "\x922"], "\xc6" => [77, "\x92a"], "\xc7" => [18, "\x92a"], "\xc8" => [77, "\x92c"], "\xc9" => [18, "\x92c"], "\xca" => [77, "\x92e"], "\xcb" => [18, "\x92e"], "\xcc" => [77, "\x92i"], "\xcd" => [18, "\x92i"], "\xce" => [77, "\x92o"], "\xcf" => [18, "\x92o"], "\xd0" => [77, "\x92s"], "\xd1" => [18, "\x92s"], "\xd2" => [77, "\x92t"], "\xd3" => [18, "\x92t"], "\xd4" => [0, "\x92 "], "\xd5" => [0, "\x92%"], "\xd6" => [0, "\x92-"], "\xd7" => [0, "\x92."], "\xd8" => [0, "\x92/"], "\xd9" => [0, "\x923"], "\xda" => [0, "\x924"], "\xdb" => [0, "\x925"], "\xdc" => [0, "\x926"], "\xdd" => [0, "\x927"], "\xde" => [0, "\x928"], "\xdf" => [0, "\x929"], "\xe0" => [0, "\x92="], "\xe1" => [0, "\x92A"], "\xe2" => [0, "\x92_"], "\xe3" => [0, "\x92b"], "\xe4" => [0, "\x92d"], "\xe5" => [0, "\x92f"], "\xe6" => [0, "\x92g"], "\xe7" => [0, "\x92h"], "\xe8" => [0, "\x92l"], "\xe9" => [0, "\x92m"], "\xea" => [0, "\x92n"], "\xeb" => [0, "\x92p"], "\xec" => [0, "\x92r"], "\xed" => [0, "\x92u"], "\xee" => [100, "\x92"], "\xef" => [110, "\x92"], "\xf0" => [111, "\x92"], "\xf1" => [115, "\x92"], "\xf2" => [116, "\x92"], "\xf3" => [118, "\x92"], "\xf4" => [119, "\x92"], "\xf5" => [122, "\x92"], "\xf6" => [123, "\x92"], "\xf7" => [125, "\x92"], "\xf8" => [126, "\x92"], "\xf9" => [129, "\x92"], "\xfa" => [143, "\x92"], "\xfb" => [148, "\x92"], "\xfc" => [151, "\x92"], "\xfd" => [153, "\x92"], "\xfe" => [83, "\x92"], "\xff" => [10, "\x92"]], ["\x00" => [94, "\x880"], "\x01" => [76, "\x880"], "\x02" => [104, "\x880"], "\x03" => [16, "\x880"], "\x04" => [94, "\x881"], "\x05" => [76, "\x881"], "\x06" => [104, "\x881"], "\x07" => [16, "\x881"], "\x08" => [94, "\x882"], "\t" => [76, "\x882"], "\n" => [104, "\x882"], "\v" => [16, "\x882"], "\f" => [94, "\x88a"], "\r" => [76, "\x88a"], "\x0e" => [104, "\x88a"], "\x0f" => [16, "\x88a"], "\x10" => [94, "\x88c"], "\x11" => [76, "\x88c"], "\x12" => [104, "\x88c"], "\x13" => [16, "\x88c"], "\x14" => [94, "\x88e"], "\x15" => [76, "\x88e"], "\x16" => [104, "\x88e"], "\x17" => [16, "\x88e"], "\x18" => [94, "\x88i"], "\x19" => [76, "\x88i"], "\x1a" => [104, "\x88i"], "\x1b" => [16, "\x88i"], "\x1c" => [94, "\x88o"], "\x1d" => [76, "\x88o"], "\x1e" => [104, "\x88o"], "\x1f" => [16, "\x88o"], " " => [94, "\x88s"], "!" => [76, "\x88s"], "\"" => [104, "\x88s"], "#" => [16, "\x88s"], "\$" => [94, "\x88t"], "%" => [76, "\x88t"], "&" => [104, "\x88t"], "'" => [16, "\x88t"], "(" => [77, "\x88 "], ")" => [18, "\x88 "], "*" => [77, "\x88%"], "+" => [18, "\x88%"], "," => [77, "\x88-"], "-" => [18, "\x88-"], "." => [77, "\x88."], "/" => [18, "\x88."], [77, "\x88/"], [18, "\x88/"], [77, "\x883"], [18, "\x883"], [77, "\x884"], [18, "\x884"], [77, "\x885"], [18, "\x885"], [77, "\x886"], [18, "\x886"], ":" => [77, "\x887"], ";" => [18, "\x887"], "<" => [77, "\x888"], "=" => [18, "\x888"], ">" => [77, "\x889"], "?" => [18, "\x889"], "@" => [77, "\x88="], "A" => [18, "\x88="], "B" => [77, "\x88A"], "C" => [18, "\x88A"], "D" => [77, "\x88_"], "E" => [18, "\x88_"], "F" => [77, "\x88b"], "G" => [18, "\x88b"], "H" => [77, "\x88d"], "I" => [18, "\x88d"], "J" => [77, "\x88f"], "K" => [18, "\x88f"], "L" => [77, "\x88g"], "M" => [18, "\x88g"], "N" => [77, "\x88h"], "O" => [18, "\x88h"], "P" => [77, "\x88l"], "Q" => [18, "\x88l"], "R" => [77, "\x88m"], "S" => [18, "\x88m"], "T" => [77, "\x88n"], "U" => [18, "\x88n"], "V" => [77, "\x88p"], "W" => [18, "\x88p"], "X" => [77, "\x88r"], "Y" => [18, "\x88r"], "Z" => [77, "\x88u"], "[" => [18, "\x88u"], "\\" => [0, "\x88:"], "]" => [0, "\x88B"], "^" => [0, "\x88C"], "_" => [0, "\x88D"], "`" => [0, "\x88E"], "a" => [0, "\x88F"], "b" => [0, "\x88G"], "c" => [0, "\x88H"], "d" => [0, "\x88I"], "e" => [0, "\x88J"], "f" => [0, "\x88K"], "g" => [0, "\x88L"], "h" => [0, "\x88M"], "i" => [0, "\x88N"], "j" => [0, "\x88O"], "k" => [0, "\x88P"], "l" => [0, "\x88Q"], "m" => [0, "\x88R"], "n" => [0, "\x88S"], "o" => [0, "\x88T"], "p" => [0, "\x88U"], "q" => [0, "\x88V"], "r" => [0, "\x88W"], "s" => [0, "\x88Y"], "t" => [0, "\x88j"], "u" => [0, "\x88k"], "v" => [0, "\x88q"], "w" => [0, "\x88v"], "x" => [0, "\x88w"], "y" => [0, "\x88x"], "z" => [0, "\x88y"], "{" => [0, "\x88z"], "|" => [82, "\x88"], "}" => [87, "\x88"], "~" => [130, "\x88"], "" => [9, "\x88"], "\x80" => [94, "\x920"], "\x81" => [76, "\x920"], "\x82" => [104, "\x920"], "\x83" => [16, "\x920"], "\x84" => [94, "\x921"], "\x85" => [76, "\x921"], "\x86" => [104, "\x921"], "\x87" => [16, "\x921"], "\x88" => [94, "\x922"], "\x89" => [76, "\x922"], "\x8a" => [104, "\x922"], "\x8b" => [16, "\x922"], "\x8c" => [94, "\x92a"], "\x8d" => [76, "\x92a"], "\x8e" => [104, "\x92a"], "\x8f" => [16, "\x92a"], "\x90" => [94, "\x92c"], "\x91" => [76, "\x92c"], "\x92" => [104, "\x92c"], "\x93" => [16, "\x92c"], "\x94" => [94, "\x92e"], "\x95" => [76, "\x92e"], "\x96" => [104, "\x92e"], "\x97" => [16, "\x92e"], "\x98" => [94, "\x92i"], "\x99" => [76, "\x92i"], "\x9a" => [104, "\x92i"], "\x9b" => [16, "\x92i"], "\x9c" => [94, "\x92o"], "\x9d" => [76, "\x92o"], "\x9e" => [104, "\x92o"], "\x9f" => [16, "\x92o"], "\xa0" => [94, "\x92s"], "\xa1" => [76, "\x92s"], "\xa2" => [104, "\x92s"], "\xa3" => [16, "\x92s"], "\xa4" => [94, "\x92t"], "\xa5" => [76, "\x92t"], "\xa6" => [104, "\x92t"], "\xa7" => [16, "\x92t"], "\xa8" => [77, "\x92 "], "\xa9" => [18, "\x92 "], "\xaa" => [77, "\x92%"], "\xab" => [18, "\x92%"], "\xac" => [77, "\x92-"], "\xad" => [18, "\x92-"], "\xae" => [77, "\x92."], "\xaf" => [18, "\x92."], "\xb0" => [77, "\x92/"], "\xb1" => [18, "\x92/"], "\xb2" => [77, "\x923"], "\xb3" => [18, "\x923"], "\xb4" => [77, "\x924"], "\xb5" => [18, "\x924"], "\xb6" => [77, "\x925"], "\xb7" => [18, "\x925"], "\xb8" => [77, "\x926"], "\xb9" => [18, "\x926"], "\xba" => [77, "\x927"], "\xbb" => [18, "\x927"], "\xbc" => [77, "\x928"], "\xbd" => [18, "\x928"], "\xbe" => [77, "\x929"], "\xbf" => [18, "\x929"], "\xc0" => [77, "\x92="], "\xc1" => [18, "\x92="], "\xc2" => [77, "\x92A"], "\xc3" => [18, "\x92A"], "\xc4" => [77, "\x92_"], "\xc5" => [18, "\x92_"], "\xc6" => [77, "\x92b"], "\xc7" => [18, "\x92b"], "\xc8" => [77, "\x92d"], "\xc9" => [18, "\x92d"], "\xca" => [77, "\x92f"], "\xcb" => [18, "\x92f"], "\xcc" => [77, "\x92g"], "\xcd" => [18, "\x92g"], "\xce" => [77, "\x92h"], "\xcf" => [18, "\x92h"], "\xd0" => [77, "\x92l"], "\xd1" => [18, "\x92l"], "\xd2" => [77, "\x92m"], "\xd3" => [18, "\x92m"], "\xd4" => [77, "\x92n"], "\xd5" => [18, "\x92n"], "\xd6" => [77, "\x92p"], "\xd7" => [18, "\x92p"], "\xd8" => [77, "\x92r"], "\xd9" => [18, "\x92r"], "\xda" => [77, "\x92u"], "\xdb" => [18, "\x92u"], "\xdc" => [0, "\x92:"], "\xdd" => [0, "\x92B"], "\xde" => [0, "\x92C"], "\xdf" => [0, "\x92D"], "\xe0" => [0, "\x92E"], "\xe1" => [0, "\x92F"], "\xe2" => [0, "\x92G"], "\xe3" => [0, "\x92H"], "\xe4" => [0, "\x92I"], "\xe5" => [0, "\x92J"], "\xe6" => [0, "\x92K"], "\xe7" => [0, "\x92L"], "\xe8" => [0, "\x92M"], "\xe9" => [0, "\x92N"], "\xea" => [0, "\x92O"], "\xeb" => [0, "\x92P"], "\xec" => [0, "\x92Q"], "\xed" => [0, "\x92R"], "\xee" => [0, "\x92S"], "\xef" => [0, "\x92T"], "\xf0" => [0, "\x92U"], "\xf1" => [0, "\x92V"], "\xf2" => [0, "\x92W"], "\xf3" => [0, "\x92Y"], "\xf4" => [0, "\x92j"], "\xf5" => [0, "\x92k"], "\xf6" => [0, "\x92q"], "\xf7" => [0, "\x92v"], "\xf8" => [0, "\x92w"], "\xf9" => [0, "\x92x"], "\xfa" => [0, "\x92y"], "\xfb" => [0, "\x92z"], "\xfc" => [82, "\x92"], "\xfd" => [87, "\x92"], "\xfe" => [130, "\x92"], "\xff" => [9, "\x92"]], ["\x00" => [94, "\x890"], "\x01" => [76, "\x890"], "\x02" => [104, "\x890"], "\x03" => [16, "\x890"], "\x04" => [94, "\x891"], "\x05" => [76, "\x891"], "\x06" => [104, "\x891"], "\x07" => [16, "\x891"], "\x08" => [94, "\x892"], "\t" => [76, "\x892"], "\n" => [104, "\x892"], "\v" => [16, "\x892"], "\f" => [94, "\x89a"], "\r" => [76, "\x89a"], "\x0e" => [104, "\x89a"], "\x0f" => [16, "\x89a"], "\x10" => [94, "\x89c"], "\x11" => [76, "\x89c"], "\x12" => [104, "\x89c"], "\x13" => [16, "\x89c"], "\x14" => [94, "\x89e"], "\x15" => [76, "\x89e"], "\x16" => [104, "\x89e"], "\x17" => [16, "\x89e"], "\x18" => [94, "\x89i"], "\x19" => [76, "\x89i"], "\x1a" => [104, "\x89i"], "\x1b" => [16, "\x89i"], "\x1c" => [94, "\x89o"], "\x1d" => [76, "\x89o"], "\x1e" => [104, "\x89o"], "\x1f" => [16, "\x89o"], " " => [94, "\x89s"], "!" => [76, "\x89s"], "\"" => [104, "\x89s"], "#" => [16, "\x89s"], "\$" => [94, "\x89t"], "%" => [76, "\x89t"], "&" => [104, "\x89t"], "'" => [16, "\x89t"], "(" => [77, "\x89 "], ")" => [18, "\x89 "], "*" => [77, "\x89%"], "+" => [18, "\x89%"], "," => [77, "\x89-"], "-" => [18, "\x89-"], "." => [77, "\x89."], "/" => [18, "\x89."], [77, "\x89/"], [18, "\x89/"], [77, "\x893"], [18, "\x893"], [77, "\x894"], [18, "\x894"], [77, "\x895"], [18, "\x895"], [77, "\x896"], [18, "\x896"], ":" => [77, "\x897"], ";" => [18, "\x897"], "<" => [77, "\x898"], "=" => [18, "\x898"], ">" => [77, "\x899"], "?" => [18, "\x899"], "@" => [77, "\x89="], "A" => [18, "\x89="], "B" => [77, "\x89A"], "C" => [18, "\x89A"], "D" => [77, "\x89_"], "E" => [18, "\x89_"], "F" => [77, "\x89b"], "G" => [18, "\x89b"], "H" => [77, "\x89d"], "I" => [18, "\x89d"], "J" => [77, "\x89f"], "K" => [18, "\x89f"], "L" => [77, "\x89g"], "M" => [18, "\x89g"], "N" => [77, "\x89h"], "O" => [18, "\x89h"], "P" => [77, "\x89l"], "Q" => [18, "\x89l"], "R" => [77, "\x89m"], "S" => [18, "\x89m"], "T" => [77, "\x89n"], "U" => [18, "\x89n"], "V" => [77, "\x89p"], "W" => [18, "\x89p"], "X" => [77, "\x89r"], "Y" => [18, "\x89r"], "Z" => [77, "\x89u"], "[" => [18, "\x89u"], "\\" => [0, "\x89:"], "]" => [0, "\x89B"], "^" => [0, "\x89C"], "_" => [0, "\x89D"], "`" => [0, "\x89E"], "a" => [0, "\x89F"], "b" => [0, "\x89G"], "c" => [0, "\x89H"], "d" => [0, "\x89I"], "e" => [0, "\x89J"], "f" => [0, "\x89K"], "g" => [0, "\x89L"], "h" => [0, "\x89M"], "i" => [0, "\x89N"], "j" => [0, "\x89O"], "k" => [0, "\x89P"], "l" => [0, "\x89Q"], "m" => [0, "\x89R"], "n" => [0, "\x89S"], "o" => [0, "\x89T"], "p" => [0, "\x89U"], "q" => [0, "\x89V"], "r" => [0, "\x89W"], "s" => [0, "\x89Y"], "t" => [0, "\x89j"], "u" => [0, "\x89k"], "v" => [0, "\x89q"], "w" => [0, "\x89v"], "x" => [0, "\x89w"], "y" => [0, "\x89x"], "z" => [0, "\x89y"], "{" => [0, "\x89z"], "|" => [82, "\x89"], "}" => [87, "\x89"], "~" => [130, "\x89"], "" => [9, "\x89"], "\x80" => [94, "\x8a0"], "\x81" => [76, "\x8a0"], "\x82" => [104, "\x8a0"], "\x83" => [16, "\x8a0"], "\x84" => [94, "\x8a1"], "\x85" => [76, "\x8a1"], "\x86" => [104, "\x8a1"], "\x87" => [16, "\x8a1"], "\x88" => [94, "\x8a2"], "\x89" => [76, "\x8a2"], "\x8a" => [104, "\x8a2"], "\x8b" => [16, "\x8a2"], "\x8c" => [94, "\x8aa"], "\x8d" => [76, "\x8aa"], "\x8e" => [104, "\x8aa"], "\x8f" => [16, "\x8aa"], "\x90" => [94, "\x8ac"], "\x91" => [76, "\x8ac"], "\x92" => [104, "\x8ac"], "\x93" => [16, "\x8ac"], "\x94" => [94, "\x8ae"], "\x95" => [76, "\x8ae"], "\x96" => [104, "\x8ae"], "\x97" => [16, "\x8ae"], "\x98" => [94, "\x8ai"], "\x99" => [76, "\x8ai"], "\x9a" => [104, "\x8ai"], "\x9b" => [16, "\x8ai"], "\x9c" => [94, "\x8ao"], "\x9d" => [76, "\x8ao"], "\x9e" => [104, "\x8ao"], "\x9f" => [16, "\x8ao"], "\xa0" => [94, "\x8as"], "\xa1" => [76, "\x8as"], "\xa2" => [104, "\x8as"], "\xa3" => [16, "\x8as"], "\xa4" => [94, "\x8at"], "\xa5" => [76, "\x8at"], "\xa6" => [104, "\x8at"], "\xa7" => [16, "\x8at"], "\xa8" => [77, "\x8a "], "\xa9" => [18, "\x8a "], "\xaa" => [77, "\x8a%"], "\xab" => [18, "\x8a%"], "\xac" => [77, "\x8a-"], "\xad" => [18, "\x8a-"], "\xae" => [77, "\x8a."], "\xaf" => [18, "\x8a."], "\xb0" => [77, "\x8a/"], "\xb1" => [18, "\x8a/"], "\xb2" => [77, "\x8a3"], "\xb3" => [18, "\x8a3"], "\xb4" => [77, "\x8a4"], "\xb5" => [18, "\x8a4"], "\xb6" => [77, "\x8a5"], "\xb7" => [18, "\x8a5"], "\xb8" => [77, "\x8a6"], "\xb9" => [18, "\x8a6"], "\xba" => [77, "\x8a7"], "\xbb" => [18, "\x8a7"], "\xbc" => [77, "\x8a8"], "\xbd" => [18, "\x8a8"], "\xbe" => [77, "\x8a9"], "\xbf" => [18, "\x8a9"], "\xc0" => [77, "\x8a="], "\xc1" => [18, "\x8a="], "\xc2" => [77, "\x8aA"], "\xc3" => [18, "\x8aA"], "\xc4" => [77, "\x8a_"], "\xc5" => [18, "\x8a_"], "\xc6" => [77, "\x8ab"], "\xc7" => [18, "\x8ab"], "\xc8" => [77, "\x8ad"], "\xc9" => [18, "\x8ad"], "\xca" => [77, "\x8af"], "\xcb" => [18, "\x8af"], "\xcc" => [77, "\x8ag"], "\xcd" => [18, "\x8ag"], "\xce" => [77, "\x8ah"], "\xcf" => [18, "\x8ah"], "\xd0" => [77, "\x8al"], "\xd1" => [18, "\x8al"], "\xd2" => [77, "\x8am"], "\xd3" => [18, "\x8am"], "\xd4" => [77, "\x8an"], "\xd5" => [18, "\x8an"], "\xd6" => [77, "\x8ap"], "\xd7" => [18, "\x8ap"], "\xd8" => [77, "\x8ar"], "\xd9" => [18, "\x8ar"], "\xda" => [77, "\x8au"], "\xdb" => [18, "\x8au"], "\xdc" => [0, "\x8a:"], "\xdd" => [0, "\x8aB"], "\xde" => [0, "\x8aC"], "\xdf" => [0, "\x8aD"], "\xe0" => [0, "\x8aE"], "\xe1" => [0, "\x8aF"], "\xe2" => [0, "\x8aG"], "\xe3" => [0, "\x8aH"], "\xe4" => [0, "\x8aI"], "\xe5" => [0, "\x8aJ"], "\xe6" => [0, "\x8aK"], "\xe7" => [0, "\x8aL"], "\xe8" => [0, "\x8aM"], "\xe9" => [0, "\x8aN"], "\xea" => [0, "\x8aO"], "\xeb" => [0, "\x8aP"], "\xec" => [0, "\x8aQ"], "\xed" => [0, "\x8aR"], "\xee" => [0, "\x8aS"], "\xef" => [0, "\x8aT"], "\xf0" => [0, "\x8aU"], "\xf1" => [0, "\x8aV"], "\xf2" => [0, "\x8aW"], "\xf3" => [0, "\x8aY"], "\xf4" => [0, "\x8aj"], "\xf5" => [0, "\x8ak"], "\xf6" => [0, "\x8aq"], "\xf7" => [0, "\x8av"], "\xf8" => [0, "\x8aw"], "\xf9" => [0, "\x8ax"], "\xfa" => [0, "\x8ay"], "\xfb" => [0, "\x8az"], "\xfc" => [82, "\x8a"], "\xfd" => [87, "\x8a"], "\xfe" => [130, "\x8a"], "\xff" => [9, "\x8a"]], ["\x00" => [94, "\x8b0"], "\x01" => [76, "\x8b0"], "\x02" => [104, "\x8b0"], "\x03" => [16, "\x8b0"], "\x04" => [94, "\x8b1"], "\x05" => [76, "\x8b1"], "\x06" => [104, "\x8b1"], "\x07" => [16, "\x8b1"], "\x08" => [94, "\x8b2"], "\t" => [76, "\x8b2"], "\n" => [104, "\x8b2"], "\v" => [16, "\x8b2"], "\f" => [94, "\x8ba"], "\r" => [76, "\x8ba"], "\x0e" => [104, "\x8ba"], "\x0f" => [16, "\x8ba"], "\x10" => [94, "\x8bc"], "\x11" => [76, "\x8bc"], "\x12" => [104, "\x8bc"], "\x13" => [16, "\x8bc"], "\x14" => [94, "\x8be"], "\x15" => [76, "\x8be"], "\x16" => [104, "\x8be"], "\x17" => [16, "\x8be"], "\x18" => [94, "\x8bi"], "\x19" => [76, "\x8bi"], "\x1a" => [104, "\x8bi"], "\x1b" => [16, "\x8bi"], "\x1c" => [94, "\x8bo"], "\x1d" => [76, "\x8bo"], "\x1e" => [104, "\x8bo"], "\x1f" => [16, "\x8bo"], " " => [94, "\x8bs"], "!" => [76, "\x8bs"], "\"" => [104, "\x8bs"], "#" => [16, "\x8bs"], "\$" => [94, "\x8bt"], "%" => [76, "\x8bt"], "&" => [104, "\x8bt"], "'" => [16, "\x8bt"], "(" => [77, "\x8b "], ")" => [18, "\x8b "], "*" => [77, "\x8b%"], "+" => [18, "\x8b%"], "," => [77, "\x8b-"], "-" => [18, "\x8b-"], "." => [77, "\x8b."], "/" => [18, "\x8b."], [77, "\x8b/"], [18, "\x8b/"], [77, "\x8b3"], [18, "\x8b3"], [77, "\x8b4"], [18, "\x8b4"], [77, "\x8b5"], [18, "\x8b5"], [77, "\x8b6"], [18, "\x8b6"], ":" => [77, "\x8b7"], ";" => [18, "\x8b7"], "<" => [77, "\x8b8"], "=" => [18, "\x8b8"], ">" => [77, "\x8b9"], "?" => [18, "\x8b9"], "@" => [77, "\x8b="], "A" => [18, "\x8b="], "B" => [77, "\x8bA"], "C" => [18, "\x8bA"], "D" => [77, "\x8b_"], "E" => [18, "\x8b_"], "F" => [77, "\x8bb"], "G" => [18, "\x8bb"], "H" => [77, "\x8bd"], "I" => [18, "\x8bd"], "J" => [77, "\x8bf"], "K" => [18, "\x8bf"], "L" => [77, "\x8bg"], "M" => [18, "\x8bg"], "N" => [77, "\x8bh"], "O" => [18, "\x8bh"], "P" => [77, "\x8bl"], "Q" => [18, "\x8bl"], "R" => [77, "\x8bm"], "S" => [18, "\x8bm"], "T" => [77, "\x8bn"], "U" => [18, "\x8bn"], "V" => [77, "\x8bp"], "W" => [18, "\x8bp"], "X" => [77, "\x8br"], "Y" => [18, "\x8br"], "Z" => [77, "\x8bu"], "[" => [18, "\x8bu"], "\\" => [0, "\x8b:"], "]" => [0, "\x8bB"], "^" => [0, "\x8bC"], "_" => [0, "\x8bD"], "`" => [0, "\x8bE"], "a" => [0, "\x8bF"], "b" => [0, "\x8bG"], "c" => [0, "\x8bH"], "d" => [0, "\x8bI"], "e" => [0, "\x8bJ"], "f" => [0, "\x8bK"], "g" => [0, "\x8bL"], "h" => [0, "\x8bM"], "i" => [0, "\x8bN"], "j" => [0, "\x8bO"], "k" => [0, "\x8bP"], "l" => [0, "\x8bQ"], "m" => [0, "\x8bR"], "n" => [0, "\x8bS"], "o" => [0, "\x8bT"], "p" => [0, "\x8bU"], "q" => [0, "\x8bV"], "r" => [0, "\x8bW"], "s" => [0, "\x8bY"], "t" => [0, "\x8bj"], "u" => [0, "\x8bk"], "v" => [0, "\x8bq"], "w" => [0, "\x8bv"], "x" => [0, "\x8bw"], "y" => [0, "\x8bx"], "z" => [0, "\x8by"], "{" => [0, "\x8bz"], "|" => [82, "\x8b"], "}" => [87, "\x8b"], "~" => [130, "\x8b"], "" => [9, "\x8b"], "\x80" => [94, "\x8c0"], "\x81" => [76, "\x8c0"], "\x82" => [104, "\x8c0"], "\x83" => [16, "\x8c0"], "\x84" => [94, "\x8c1"], "\x85" => [76, "\x8c1"], "\x86" => [104, "\x8c1"], "\x87" => [16, "\x8c1"], "\x88" => [94, "\x8c2"], "\x89" => [76, "\x8c2"], "\x8a" => [104, "\x8c2"], "\x8b" => [16, "\x8c2"], "\x8c" => [94, "\x8ca"], "\x8d" => [76, "\x8ca"], "\x8e" => [104, "\x8ca"], "\x8f" => [16, "\x8ca"], "\x90" => [94, "\x8cc"], "\x91" => [76, "\x8cc"], "\x92" => [104, "\x8cc"], "\x93" => [16, "\x8cc"], "\x94" => [94, "\x8ce"], "\x95" => [76, "\x8ce"], "\x96" => [104, "\x8ce"], "\x97" => [16, "\x8ce"], "\x98" => [94, "\x8ci"], "\x99" => [76, "\x8ci"], "\x9a" => [104, "\x8ci"], "\x9b" => [16, "\x8ci"], "\x9c" => [94, "\x8co"], "\x9d" => [76, "\x8co"], "\x9e" => [104, "\x8co"], "\x9f" => [16, "\x8co"], "\xa0" => [94, "\x8cs"], "\xa1" => [76, "\x8cs"], "\xa2" => [104, "\x8cs"], "\xa3" => [16, "\x8cs"], "\xa4" => [94, "\x8ct"], "\xa5" => [76, "\x8ct"], "\xa6" => [104, "\x8ct"], "\xa7" => [16, "\x8ct"], "\xa8" => [77, "\x8c "], "\xa9" => [18, "\x8c "], "\xaa" => [77, "\x8c%"], "\xab" => [18, "\x8c%"], "\xac" => [77, "\x8c-"], "\xad" => [18, "\x8c-"], "\xae" => [77, "\x8c."], "\xaf" => [18, "\x8c."], "\xb0" => [77, "\x8c/"], "\xb1" => [18, "\x8c/"], "\xb2" => [77, "\x8c3"], "\xb3" => [18, "\x8c3"], "\xb4" => [77, "\x8c4"], "\xb5" => [18, "\x8c4"], "\xb6" => [77, "\x8c5"], "\xb7" => [18, "\x8c5"], "\xb8" => [77, "\x8c6"], "\xb9" => [18, "\x8c6"], "\xba" => [77, "\x8c7"], "\xbb" => [18, "\x8c7"], "\xbc" => [77, "\x8c8"], "\xbd" => [18, "\x8c8"], "\xbe" => [77, "\x8c9"], "\xbf" => [18, "\x8c9"], "\xc0" => [77, "\x8c="], "\xc1" => [18, "\x8c="], "\xc2" => [77, "\x8cA"], "\xc3" => [18, "\x8cA"], "\xc4" => [77, "\x8c_"], "\xc5" => [18, "\x8c_"], "\xc6" => [77, "\x8cb"], "\xc7" => [18, "\x8cb"], "\xc8" => [77, "\x8cd"], "\xc9" => [18, "\x8cd"], "\xca" => [77, "\x8cf"], "\xcb" => [18, "\x8cf"], "\xcc" => [77, "\x8cg"], "\xcd" => [18, "\x8cg"], "\xce" => [77, "\x8ch"], "\xcf" => [18, "\x8ch"], "\xd0" => [77, "\x8cl"], "\xd1" => [18, "\x8cl"], "\xd2" => [77, "\x8cm"], "\xd3" => [18, "\x8cm"], "\xd4" => [77, "\x8cn"], "\xd5" => [18, "\x8cn"], "\xd6" => [77, "\x8cp"], "\xd7" => [18, "\x8cp"], "\xd8" => [77, "\x8cr"], "\xd9" => [18, "\x8cr"], "\xda" => [77, "\x8cu"], "\xdb" => [18, "\x8cu"], "\xdc" => [0, "\x8c:"], "\xdd" => [0, "\x8cB"], "\xde" => [0, "\x8cC"], "\xdf" => [0, "\x8cD"], "\xe0" => [0, "\x8cE"], "\xe1" => [0, "\x8cF"], "\xe2" => [0, "\x8cG"], "\xe3" => [0, "\x8cH"], "\xe4" => [0, "\x8cI"], "\xe5" => [0, "\x8cJ"], "\xe6" => [0, "\x8cK"], "\xe7" => [0, "\x8cL"], "\xe8" => [0, "\x8cM"], "\xe9" => [0, "\x8cN"], "\xea" => [0, "\x8cO"], "\xeb" => [0, "\x8cP"], "\xec" => [0, "\x8cQ"], "\xed" => [0, "\x8cR"], "\xee" => [0, "\x8cS"], "\xef" => [0, "\x8cT"], "\xf0" => [0, "\x8cU"], "\xf1" => [0, "\x8cV"], "\xf2" => [0, "\x8cW"], "\xf3" => [0, "\x8cY"], "\xf4" => [0, "\x8cj"], "\xf5" => [0, "\x8ck"], "\xf6" => [0, "\x8cq"], "\xf7" => [0, "\x8cv"], "\xf8" => [0, "\x8cw"], "\xf9" => [0, "\x8cx"], "\xfa" => [0, "\x8cy"], "\xfb" => [0, "\x8cz"], "\xfc" => [82, "\x8c"], "\xfd" => [87, "\x8c"], "\xfe" => [130, "\x8c"], "\xff" => [9, "\x8c"]], ["\x00" => [77, "\x8b0"], "\x01" => [18, "\x8b0"], "\x02" => [77, "\x8b1"], "\x03" => [18, "\x8b1"], "\x04" => [77, "\x8b2"], "\x05" => [18, "\x8b2"], "\x06" => [77, "\x8ba"], "\x07" => [18, "\x8ba"], "\x08" => [77, "\x8bc"], "\t" => [18, "\x8bc"], "\n" => [77, "\x8be"], "\v" => [18, "\x8be"], "\f" => [77, "\x8bi"], "\r" => [18, "\x8bi"], "\x0e" => [77, "\x8bo"], "\x0f" => [18, "\x8bo"], "\x10" => [77, "\x8bs"], "\x11" => [18, "\x8bs"], "\x12" => [77, "\x8bt"], "\x13" => [18, "\x8bt"], "\x14" => [0, "\x8b "], "\x15" => [0, "\x8b%"], "\x16" => [0, "\x8b-"], "\x17" => [0, "\x8b."], "\x18" => [0, "\x8b/"], "\x19" => [0, "\x8b3"], "\x1a" => [0, "\x8b4"], "\x1b" => [0, "\x8b5"], "\x1c" => [0, "\x8b6"], "\x1d" => [0, "\x8b7"], "\x1e" => [0, "\x8b8"], "\x1f" => [0, "\x8b9"], " " => [0, "\x8b="], "!" => [0, "\x8bA"], "\"" => [0, "\x8b_"], "#" => [0, "\x8bb"], "\$" => [0, "\x8bd"], "%" => [0, "\x8bf"], "&" => [0, "\x8bg"], "'" => [0, "\x8bh"], "(" => [0, "\x8bl"], ")" => [0, "\x8bm"], "*" => [0, "\x8bn"], "+" => [0, "\x8bp"], "," => [0, "\x8br"], "-" => [0, "\x8bu"], "." => [100, "\x8b"], "/" => [110, "\x8b"], [111, "\x8b"], [115, "\x8b"], [116, "\x8b"], [118, "\x8b"], [119, "\x8b"], [122, "\x8b"], [123, "\x8b"], [125, "\x8b"], [126, "\x8b"], [129, "\x8b"], ":" => [143, "\x8b"], ";" => [148, "\x8b"], "<" => [151, "\x8b"], "=" => [153, "\x8b"], ">" => [83, "\x8b"], "?" => [10, "\x8b"], "@" => [77, "\x8c0"], "A" => [18, "\x8c0"], "B" => [77, "\x8c1"], "C" => [18, "\x8c1"], "D" => [77, "\x8c2"], "E" => [18, "\x8c2"], "F" => [77, "\x8ca"], "G" => [18, "\x8ca"], "H" => [77, "\x8cc"], "I" => [18, "\x8cc"], "J" => [77, "\x8ce"], "K" => [18, "\x8ce"], "L" => [77, "\x8ci"], "M" => [18, "\x8ci"], "N" => [77, "\x8co"], "O" => [18, "\x8co"], "P" => [77, "\x8cs"], "Q" => [18, "\x8cs"], "R" => [77, "\x8ct"], "S" => [18, "\x8ct"], "T" => [0, "\x8c "], "U" => [0, "\x8c%"], "V" => [0, "\x8c-"], "W" => [0, "\x8c."], "X" => [0, "\x8c/"], "Y" => [0, "\x8c3"], "Z" => [0, "\x8c4"], "[" => [0, "\x8c5"], "\\" => [0, "\x8c6"], "]" => [0, "\x8c7"], "^" => [0, "\x8c8"], "_" => [0, "\x8c9"], "`" => [0, "\x8c="], "a" => [0, "\x8cA"], "b" => [0, "\x8c_"], "c" => [0, "\x8cb"], "d" => [0, "\x8cd"], "e" => [0, "\x8cf"], "f" => [0, "\x8cg"], "g" => [0, "\x8ch"], "h" => [0, "\x8cl"], "i" => [0, "\x8cm"], "j" => [0, "\x8cn"], "k" => [0, "\x8cp"], "l" => [0, "\x8cr"], "m" => [0, "\x8cu"], "n" => [100, "\x8c"], "o" => [110, "\x8c"], "p" => [111, "\x8c"], "q" => [115, "\x8c"], "r" => [116, "\x8c"], "s" => [118, "\x8c"], "t" => [119, "\x8c"], "u" => [122, "\x8c"], "v" => [123, "\x8c"], "w" => [125, "\x8c"], "x" => [126, "\x8c"], "y" => [129, "\x8c"], "z" => [143, "\x8c"], "{" => [148, "\x8c"], "|" => [151, "\x8c"], "}" => [153, "\x8c"], "~" => [83, "\x8c"], "" => [10, "\x8c"], "\x80" => [77, "\x8d0"], "\x81" => [18, "\x8d0"], "\x82" => [77, "\x8d1"], "\x83" => [18, "\x8d1"], "\x84" => [77, "\x8d2"], "\x85" => [18, "\x8d2"], "\x86" => [77, "\x8da"], "\x87" => [18, "\x8da"], "\x88" => [77, "\x8dc"], "\x89" => [18, "\x8dc"], "\x8a" => [77, "\x8de"], "\x8b" => [18, "\x8de"], "\x8c" => [77, "\x8di"], "\x8d" => [18, "\x8di"], "\x8e" => [77, "\x8do"], "\x8f" => [18, "\x8do"], "\x90" => [77, "\x8ds"], "\x91" => [18, "\x8ds"], "\x92" => [77, "\x8dt"], "\x93" => [18, "\x8dt"], "\x94" => [0, "\x8d "], "\x95" => [0, "\x8d%"], "\x96" => [0, "\x8d-"], "\x97" => [0, "\x8d."], "\x98" => [0, "\x8d/"], "\x99" => [0, "\x8d3"], "\x9a" => [0, "\x8d4"], "\x9b" => [0, "\x8d5"], "\x9c" => [0, "\x8d6"], "\x9d" => [0, "\x8d7"], "\x9e" => [0, "\x8d8"], "\x9f" => [0, "\x8d9"], "\xa0" => [0, "\x8d="], "\xa1" => [0, "\x8dA"], "\xa2" => [0, "\x8d_"], "\xa3" => [0, "\x8db"], "\xa4" => [0, "\x8dd"], "\xa5" => [0, "\x8df"], "\xa6" => [0, "\x8dg"], "\xa7" => [0, "\x8dh"], "\xa8" => [0, "\x8dl"], "\xa9" => [0, "\x8dm"], "\xaa" => [0, "\x8dn"], "\xab" => [0, "\x8dp"], "\xac" => [0, "\x8dr"], "\xad" => [0, "\x8du"], "\xae" => [100, "\x8d"], "\xaf" => [110, "\x8d"], "\xb0" => [111, "\x8d"], "\xb1" => [115, "\x8d"], "\xb2" => [116, "\x8d"], "\xb3" => [118, "\x8d"], "\xb4" => [119, "\x8d"], "\xb5" => [122, "\x8d"], "\xb6" => [123, "\x8d"], "\xb7" => [125, "\x8d"], "\xb8" => [126, "\x8d"], "\xb9" => [129, "\x8d"], "\xba" => [143, "\x8d"], "\xbb" => [148, "\x8d"], "\xbc" => [151, "\x8d"], "\xbd" => [153, "\x8d"], "\xbe" => [83, "\x8d"], "\xbf" => [10, "\x8d"], "\xc0" => [77, "\x8f0"], "\xc1" => [18, "\x8f0"], "\xc2" => [77, "\x8f1"], "\xc3" => [18, "\x8f1"], "\xc4" => [77, "\x8f2"], "\xc5" => [18, "\x8f2"], "\xc6" => [77, "\x8fa"], "\xc7" => [18, "\x8fa"], "\xc8" => [77, "\x8fc"], "\xc9" => [18, "\x8fc"], "\xca" => [77, "\x8fe"], "\xcb" => [18, "\x8fe"], "\xcc" => [77, "\x8fi"], "\xcd" => [18, "\x8fi"], "\xce" => [77, "\x8fo"], "\xcf" => [18, "\x8fo"], "\xd0" => [77, "\x8fs"], "\xd1" => [18, "\x8fs"], "\xd2" => [77, "\x8ft"], "\xd3" => [18, "\x8ft"], "\xd4" => [0, "\x8f "], "\xd5" => [0, "\x8f%"], "\xd6" => [0, "\x8f-"], "\xd7" => [0, "\x8f."], "\xd8" => [0, "\x8f/"], "\xd9" => [0, "\x8f3"], "\xda" => [0, "\x8f4"], "\xdb" => [0, "\x8f5"], "\xdc" => [0, "\x8f6"], "\xdd" => [0, "\x8f7"], "\xde" => [0, "\x8f8"], "\xdf" => [0, "\x8f9"], "\xe0" => [0, "\x8f="], "\xe1" => [0, "\x8fA"], "\xe2" => [0, "\x8f_"], "\xe3" => [0, "\x8fb"], "\xe4" => [0, "\x8fd"], "\xe5" => [0, "\x8ff"], "\xe6" => [0, "\x8fg"], "\xe7" => [0, "\x8fh"], "\xe8" => [0, "\x8fl"], "\xe9" => [0, "\x8fm"], "\xea" => [0, "\x8fn"], "\xeb" => [0, "\x8fp"], "\xec" => [0, "\x8fr"], "\xed" => [0, "\x8fu"], "\xee" => [100, "\x8f"], "\xef" => [110, "\x8f"], "\xf0" => [111, "\x8f"], "\xf1" => [115, "\x8f"], "\xf2" => [116, "\x8f"], "\xf3" => [118, "\x8f"], "\xf4" => [119, "\x8f"], "\xf5" => [122, "\x8f"], "\xf6" => [123, "\x8f"], "\xf7" => [125, "\x8f"], "\xf8" => [126, "\x8f"], "\xf9" => [129, "\x8f"], "\xfa" => [143, "\x8f"], "\xfb" => [148, "\x8f"], "\xfc" => [151, "\x8f"], "\xfd" => [153, "\x8f"], "\xfe" => [83, "\x8f"], "\xff" => [10, "\x8f"]], ["\x00" => [94, "\x8d0"], "\x01" => [76, "\x8d0"], "\x02" => [104, "\x8d0"], "\x03" => [16, "\x8d0"], "\x04" => [94, "\x8d1"], "\x05" => [76, "\x8d1"], "\x06" => [104, "\x8d1"], "\x07" => [16, "\x8d1"], "\x08" => [94, "\x8d2"], "\t" => [76, "\x8d2"], "\n" => [104, "\x8d2"], "\v" => [16, "\x8d2"], "\f" => [94, "\x8da"], "\r" => [76, "\x8da"], "\x0e" => [104, "\x8da"], "\x0f" => [16, "\x8da"], "\x10" => [94, "\x8dc"], "\x11" => [76, "\x8dc"], "\x12" => [104, "\x8dc"], "\x13" => [16, "\x8dc"], "\x14" => [94, "\x8de"], "\x15" => [76, "\x8de"], "\x16" => [104, "\x8de"], "\x17" => [16, "\x8de"], "\x18" => [94, "\x8di"], "\x19" => [76, "\x8di"], "\x1a" => [104, "\x8di"], "\x1b" => [16, "\x8di"], "\x1c" => [94, "\x8do"], "\x1d" => [76, "\x8do"], "\x1e" => [104, "\x8do"], "\x1f" => [16, "\x8do"], " " => [94, "\x8ds"], "!" => [76, "\x8ds"], "\"" => [104, "\x8ds"], "#" => [16, "\x8ds"], "\$" => [94, "\x8dt"], "%" => [76, "\x8dt"], "&" => [104, "\x8dt"], "'" => [16, "\x8dt"], "(" => [77, "\x8d "], ")" => [18, "\x8d "], "*" => [77, "\x8d%"], "+" => [18, "\x8d%"], "," => [77, "\x8d-"], "-" => [18, "\x8d-"], "." => [77, "\x8d."], "/" => [18, "\x8d."], [77, "\x8d/"], [18, "\x8d/"], [77, "\x8d3"], [18, "\x8d3"], [77, "\x8d4"], [18, "\x8d4"], [77, "\x8d5"], [18, "\x8d5"], [77, "\x8d6"], [18, "\x8d6"], ":" => [77, "\x8d7"], ";" => [18, "\x8d7"], "<" => [77, "\x8d8"], "=" => [18, "\x8d8"], ">" => [77, "\x8d9"], "?" => [18, "\x8d9"], "@" => [77, "\x8d="], "A" => [18, "\x8d="], "B" => [77, "\x8dA"], "C" => [18, "\x8dA"], "D" => [77, "\x8d_"], "E" => [18, "\x8d_"], "F" => [77, "\x8db"], "G" => [18, "\x8db"], "H" => [77, "\x8dd"], "I" => [18, "\x8dd"], "J" => [77, "\x8df"], "K" => [18, "\x8df"], "L" => [77, "\x8dg"], "M" => [18, "\x8dg"], "N" => [77, "\x8dh"], "O" => [18, "\x8dh"], "P" => [77, "\x8dl"], "Q" => [18, "\x8dl"], "R" => [77, "\x8dm"], "S" => [18, "\x8dm"], "T" => [77, "\x8dn"], "U" => [18, "\x8dn"], "V" => [77, "\x8dp"], "W" => [18, "\x8dp"], "X" => [77, "\x8dr"], "Y" => [18, "\x8dr"], "Z" => [77, "\x8du"], "[" => [18, "\x8du"], "\\" => [0, "\x8d:"], "]" => [0, "\x8dB"], "^" => [0, "\x8dC"], "_" => [0, "\x8dD"], "`" => [0, "\x8dE"], "a" => [0, "\x8dF"], "b" => [0, "\x8dG"], "c" => [0, "\x8dH"], "d" => [0, "\x8dI"], "e" => [0, "\x8dJ"], "f" => [0, "\x8dK"], "g" => [0, "\x8dL"], "h" => [0, "\x8dM"], "i" => [0, "\x8dN"], "j" => [0, "\x8dO"], "k" => [0, "\x8dP"], "l" => [0, "\x8dQ"], "m" => [0, "\x8dR"], "n" => [0, "\x8dS"], "o" => [0, "\x8dT"], "p" => [0, "\x8dU"], "q" => [0, "\x8dV"], "r" => [0, "\x8dW"], "s" => [0, "\x8dY"], "t" => [0, "\x8dj"], "u" => [0, "\x8dk"], "v" => [0, "\x8dq"], "w" => [0, "\x8dv"], "x" => [0, "\x8dw"], "y" => [0, "\x8dx"], "z" => [0, "\x8dy"], "{" => [0, "\x8dz"], "|" => [82, "\x8d"], "}" => [87, "\x8d"], "~" => [130, "\x8d"], "" => [9, "\x8d"], "\x80" => [94, "\x8f0"], "\x81" => [76, "\x8f0"], "\x82" => [104, "\x8f0"], "\x83" => [16, "\x8f0"], "\x84" => [94, "\x8f1"], "\x85" => [76, "\x8f1"], "\x86" => [104, "\x8f1"], "\x87" => [16, "\x8f1"], "\x88" => [94, "\x8f2"], "\x89" => [76, "\x8f2"], "\x8a" => [104, "\x8f2"], "\x8b" => [16, "\x8f2"], "\x8c" => [94, "\x8fa"], "\x8d" => [76, "\x8fa"], "\x8e" => [104, "\x8fa"], "\x8f" => [16, "\x8fa"], "\x90" => [94, "\x8fc"], "\x91" => [76, "\x8fc"], "\x92" => [104, "\x8fc"], "\x93" => [16, "\x8fc"], "\x94" => [94, "\x8fe"], "\x95" => [76, "\x8fe"], "\x96" => [104, "\x8fe"], "\x97" => [16, "\x8fe"], "\x98" => [94, "\x8fi"], "\x99" => [76, "\x8fi"], "\x9a" => [104, "\x8fi"], "\x9b" => [16, "\x8fi"], "\x9c" => [94, "\x8fo"], "\x9d" => [76, "\x8fo"], "\x9e" => [104, "\x8fo"], "\x9f" => [16, "\x8fo"], "\xa0" => [94, "\x8fs"], "\xa1" => [76, "\x8fs"], "\xa2" => [104, "\x8fs"], "\xa3" => [16, "\x8fs"], "\xa4" => [94, "\x8ft"], "\xa5" => [76, "\x8ft"], "\xa6" => [104, "\x8ft"], "\xa7" => [16, "\x8ft"], "\xa8" => [77, "\x8f "], "\xa9" => [18, "\x8f "], "\xaa" => [77, "\x8f%"], "\xab" => [18, "\x8f%"], "\xac" => [77, "\x8f-"], "\xad" => [18, "\x8f-"], "\xae" => [77, "\x8f."], "\xaf" => [18, "\x8f."], "\xb0" => [77, "\x8f/"], "\xb1" => [18, "\x8f/"], "\xb2" => [77, "\x8f3"], "\xb3" => [18, "\x8f3"], "\xb4" => [77, "\x8f4"], "\xb5" => [18, "\x8f4"], "\xb6" => [77, "\x8f5"], "\xb7" => [18, "\x8f5"], "\xb8" => [77, "\x8f6"], "\xb9" => [18, "\x8f6"], "\xba" => [77, "\x8f7"], "\xbb" => [18, "\x8f7"], "\xbc" => [77, "\x8f8"], "\xbd" => [18, "\x8f8"], "\xbe" => [77, "\x8f9"], "\xbf" => [18, "\x8f9"], "\xc0" => [77, "\x8f="], "\xc1" => [18, "\x8f="], "\xc2" => [77, "\x8fA"], "\xc3" => [18, "\x8fA"], "\xc4" => [77, "\x8f_"], "\xc5" => [18, "\x8f_"], "\xc6" => [77, "\x8fb"], "\xc7" => [18, "\x8fb"], "\xc8" => [77, "\x8fd"], "\xc9" => [18, "\x8fd"], "\xca" => [77, "\x8ff"], "\xcb" => [18, "\x8ff"], "\xcc" => [77, "\x8fg"], "\xcd" => [18, "\x8fg"], "\xce" => [77, "\x8fh"], "\xcf" => [18, "\x8fh"], "\xd0" => [77, "\x8fl"], "\xd1" => [18, "\x8fl"], "\xd2" => [77, "\x8fm"], "\xd3" => [18, "\x8fm"], "\xd4" => [77, "\x8fn"], "\xd5" => [18, "\x8fn"], "\xd6" => [77, "\x8fp"], "\xd7" => [18, "\x8fp"], "\xd8" => [77, "\x8fr"], "\xd9" => [18, "\x8fr"], "\xda" => [77, "\x8fu"], "\xdb" => [18, "\x8fu"], "\xdc" => [0, "\x8f:"], "\xdd" => [0, "\x8fB"], "\xde" => [0, "\x8fC"], "\xdf" => [0, "\x8fD"], "\xe0" => [0, "\x8fE"], "\xe1" => [0, "\x8fF"], "\xe2" => [0, "\x8fG"], "\xe3" => [0, "\x8fH"], "\xe4" => [0, "\x8fI"], "\xe5" => [0, "\x8fJ"], "\xe6" => [0, "\x8fK"], "\xe7" => [0, "\x8fL"], "\xe8" => [0, "\x8fM"], "\xe9" => [0, "\x8fN"], "\xea" => [0, "\x8fO"], "\xeb" => [0, "\x8fP"], "\xec" => [0, "\x8fQ"], "\xed" => [0, "\x8fR"], "\xee" => [0, "\x8fS"], "\xef" => [0, "\x8fT"], "\xf0" => [0, "\x8fU"], "\xf1" => [0, "\x8fV"], "\xf2" => [0, "\x8fW"], "\xf3" => [0, "\x8fY"], "\xf4" => [0, "\x8fj"], "\xf5" => [0, "\x8fk"], "\xf6" => [0, "\x8fq"], "\xf7" => [0, "\x8fv"], "\xf8" => [0, "\x8fw"], "\xf9" => [0, "\x8fx"], "\xfa" => [0, "\x8fy"], "\xfb" => [0, "\x8fz"], "\xfc" => [82, "\x8f"], "\xfd" => [87, "\x8f"], "\xfe" => [130, "\x8f"], "\xff" => [9, "\x8f"]], ["\x00" => [94, "\x900"], "\x01" => [76, "\x900"], "\x02" => [104, "\x900"], "\x03" => [16, "\x900"], "\x04" => [94, "\x901"], "\x05" => [76, "\x901"], "\x06" => [104, "\x901"], "\x07" => [16, "\x901"], "\x08" => [94, "\x902"], "\t" => [76, "\x902"], "\n" => [104, "\x902"], "\v" => [16, "\x902"], "\f" => [94, "\x90a"], "\r" => [76, "\x90a"], "\x0e" => [104, "\x90a"], "\x0f" => [16, "\x90a"], "\x10" => [94, "\x90c"], "\x11" => [76, "\x90c"], "\x12" => [104, "\x90c"], "\x13" => [16, "\x90c"], "\x14" => [94, "\x90e"], "\x15" => [76, "\x90e"], "\x16" => [104, "\x90e"], "\x17" => [16, "\x90e"], "\x18" => [94, "\x90i"], "\x19" => [76, "\x90i"], "\x1a" => [104, "\x90i"], "\x1b" => [16, "\x90i"], "\x1c" => [94, "\x90o"], "\x1d" => [76, "\x90o"], "\x1e" => [104, "\x90o"], "\x1f" => [16, "\x90o"], " " => [94, "\x90s"], "!" => [76, "\x90s"], "\"" => [104, "\x90s"], "#" => [16, "\x90s"], "\$" => [94, "\x90t"], "%" => [76, "\x90t"], "&" => [104, "\x90t"], "'" => [16, "\x90t"], "(" => [77, "\x90 "], ")" => [18, "\x90 "], "*" => [77, "\x90%"], "+" => [18, "\x90%"], "," => [77, "\x90-"], "-" => [18, "\x90-"], "." => [77, "\x90."], "/" => [18, "\x90."], [77, "\x90/"], [18, "\x90/"], [77, "\x903"], [18, "\x903"], [77, "\x904"], [18, "\x904"], [77, "\x905"], [18, "\x905"], [77, "\x906"], [18, "\x906"], ":" => [77, "\x907"], ";" => [18, "\x907"], "<" => [77, "\x908"], "=" => [18, "\x908"], ">" => [77, "\x909"], "?" => [18, "\x909"], "@" => [77, "\x90="], "A" => [18, "\x90="], "B" => [77, "\x90A"], "C" => [18, "\x90A"], "D" => [77, "\x90_"], "E" => [18, "\x90_"], "F" => [77, "\x90b"], "G" => [18, "\x90b"], "H" => [77, "\x90d"], "I" => [18, "\x90d"], "J" => [77, "\x90f"], "K" => [18, "\x90f"], "L" => [77, "\x90g"], "M" => [18, "\x90g"], "N" => [77, "\x90h"], "O" => [18, "\x90h"], "P" => [77, "\x90l"], "Q" => [18, "\x90l"], "R" => [77, "\x90m"], "S" => [18, "\x90m"], "T" => [77, "\x90n"], "U" => [18, "\x90n"], "V" => [77, "\x90p"], "W" => [18, "\x90p"], "X" => [77, "\x90r"], "Y" => [18, "\x90r"], "Z" => [77, "\x90u"], "[" => [18, "\x90u"], "\\" => [0, "\x90:"], "]" => [0, "\x90B"], "^" => [0, "\x90C"], "_" => [0, "\x90D"], "`" => [0, "\x90E"], "a" => [0, "\x90F"], "b" => [0, "\x90G"], "c" => [0, "\x90H"], "d" => [0, "\x90I"], "e" => [0, "\x90J"], "f" => [0, "\x90K"], "g" => [0, "\x90L"], "h" => [0, "\x90M"], "i" => [0, "\x90N"], "j" => [0, "\x90O"], "k" => [0, "\x90P"], "l" => [0, "\x90Q"], "m" => [0, "\x90R"], "n" => [0, "\x90S"], "o" => [0, "\x90T"], "p" => [0, "\x90U"], "q" => [0, "\x90V"], "r" => [0, "\x90W"], "s" => [0, "\x90Y"], "t" => [0, "\x90j"], "u" => [0, "\x90k"], "v" => [0, "\x90q"], "w" => [0, "\x90v"], "x" => [0, "\x90w"], "y" => [0, "\x90x"], "z" => [0, "\x90y"], "{" => [0, "\x90z"], "|" => [82, "\x90"], "}" => [87, "\x90"], "~" => [130, "\x90"], "" => [9, "\x90"], "\x80" => [94, "\x910"], "\x81" => [76, "\x910"], "\x82" => [104, "\x910"], "\x83" => [16, "\x910"], "\x84" => [94, "\x911"], "\x85" => [76, "\x911"], "\x86" => [104, "\x911"], "\x87" => [16, "\x911"], "\x88" => [94, "\x912"], "\x89" => [76, "\x912"], "\x8a" => [104, "\x912"], "\x8b" => [16, "\x912"], "\x8c" => [94, "\x91a"], "\x8d" => [76, "\x91a"], "\x8e" => [104, "\x91a"], "\x8f" => [16, "\x91a"], "\x90" => [94, "\x91c"], "\x91" => [76, "\x91c"], "\x92" => [104, "\x91c"], "\x93" => [16, "\x91c"], "\x94" => [94, "\x91e"], "\x95" => [76, "\x91e"], "\x96" => [104, "\x91e"], "\x97" => [16, "\x91e"], "\x98" => [94, "\x91i"], "\x99" => [76, "\x91i"], "\x9a" => [104, "\x91i"], "\x9b" => [16, "\x91i"], "\x9c" => [94, "\x91o"], "\x9d" => [76, "\x91o"], "\x9e" => [104, "\x91o"], "\x9f" => [16, "\x91o"], "\xa0" => [94, "\x91s"], "\xa1" => [76, "\x91s"], "\xa2" => [104, "\x91s"], "\xa3" => [16, "\x91s"], "\xa4" => [94, "\x91t"], "\xa5" => [76, "\x91t"], "\xa6" => [104, "\x91t"], "\xa7" => [16, "\x91t"], "\xa8" => [77, "\x91 "], "\xa9" => [18, "\x91 "], "\xaa" => [77, "\x91%"], "\xab" => [18, "\x91%"], "\xac" => [77, "\x91-"], "\xad" => [18, "\x91-"], "\xae" => [77, "\x91."], "\xaf" => [18, "\x91."], "\xb0" => [77, "\x91/"], "\xb1" => [18, "\x91/"], "\xb2" => [77, "\x913"], "\xb3" => [18, "\x913"], "\xb4" => [77, "\x914"], "\xb5" => [18, "\x914"], "\xb6" => [77, "\x915"], "\xb7" => [18, "\x915"], "\xb8" => [77, "\x916"], "\xb9" => [18, "\x916"], "\xba" => [77, "\x917"], "\xbb" => [18, "\x917"], "\xbc" => [77, "\x918"], "\xbd" => [18, "\x918"], "\xbe" => [77, "\x919"], "\xbf" => [18, "\x919"], "\xc0" => [77, "\x91="], "\xc1" => [18, "\x91="], "\xc2" => [77, "\x91A"], "\xc3" => [18, "\x91A"], "\xc4" => [77, "\x91_"], "\xc5" => [18, "\x91_"], "\xc6" => [77, "\x91b"], "\xc7" => [18, "\x91b"], "\xc8" => [77, "\x91d"], "\xc9" => [18, "\x91d"], "\xca" => [77, "\x91f"], "\xcb" => [18, "\x91f"], "\xcc" => [77, "\x91g"], "\xcd" => [18, "\x91g"], "\xce" => [77, "\x91h"], "\xcf" => [18, "\x91h"], "\xd0" => [77, "\x91l"], "\xd1" => [18, "\x91l"], "\xd2" => [77, "\x91m"], "\xd3" => [18, "\x91m"], "\xd4" => [77, "\x91n"], "\xd5" => [18, "\x91n"], "\xd6" => [77, "\x91p"], "\xd7" => [18, "\x91p"], "\xd8" => [77, "\x91r"], "\xd9" => [18, "\x91r"], "\xda" => [77, "\x91u"], "\xdb" => [18, "\x91u"], "\xdc" => [0, "\x91:"], "\xdd" => [0, "\x91B"], "\xde" => [0, "\x91C"], "\xdf" => [0, "\x91D"], "\xe0" => [0, "\x91E"], "\xe1" => [0, "\x91F"], "\xe2" => [0, "\x91G"], "\xe3" => [0, "\x91H"], "\xe4" => [0, "\x91I"], "\xe5" => [0, "\x91J"], "\xe6" => [0, "\x91K"], "\xe7" => [0, "\x91L"], "\xe8" => [0, "\x91M"], "\xe9" => [0, "\x91N"], "\xea" => [0, "\x91O"], "\xeb" => [0, "\x91P"], "\xec" => [0, "\x91Q"], "\xed" => [0, "\x91R"], "\xee" => [0, "\x91S"], "\xef" => [0, "\x91T"], "\xf0" => [0, "\x91U"], "\xf1" => [0, "\x91V"], "\xf2" => [0, "\x91W"], "\xf3" => [0, "\x91Y"], "\xf4" => [0, "\x91j"], "\xf5" => [0, "\x91k"], "\xf6" => [0, "\x91q"], "\xf7" => [0, "\x91v"], "\xf8" => [0, "\x91w"], "\xf9" => [0, "\x91x"], "\xfa" => [0, "\x91y"], "\xfb" => [0, "\x91z"], "\xfc" => [82, "\x91"], "\xfd" => [87, "\x91"], "\xfe" => [130, "\x91"], "\xff" => [9, "\x91"]], ["\x00" => [77, "\x900"], "\x01" => [18, "\x900"], "\x02" => [77, "\x901"], "\x03" => [18, "\x901"], "\x04" => [77, "\x902"], "\x05" => [18, "\x902"], "\x06" => [77, "\x90a"], "\x07" => [18, "\x90a"], "\x08" => [77, "\x90c"], "\t" => [18, "\x90c"], "\n" => [77, "\x90e"], "\v" => [18, "\x90e"], "\f" => [77, "\x90i"], "\r" => [18, "\x90i"], "\x0e" => [77, "\x90o"], "\x0f" => [18, "\x90o"], "\x10" => [77, "\x90s"], "\x11" => [18, "\x90s"], "\x12" => [77, "\x90t"], "\x13" => [18, "\x90t"], "\x14" => [0, "\x90 "], "\x15" => [0, "\x90%"], "\x16" => [0, "\x90-"], "\x17" => [0, "\x90."], "\x18" => [0, "\x90/"], "\x19" => [0, "\x903"], "\x1a" => [0, "\x904"], "\x1b" => [0, "\x905"], "\x1c" => [0, "\x906"], "\x1d" => [0, "\x907"], "\x1e" => [0, "\x908"], "\x1f" => [0, "\x909"], " " => [0, "\x90="], "!" => [0, "\x90A"], "\"" => [0, "\x90_"], "#" => [0, "\x90b"], "\$" => [0, "\x90d"], "%" => [0, "\x90f"], "&" => [0, "\x90g"], "'" => [0, "\x90h"], "(" => [0, "\x90l"], ")" => [0, "\x90m"], "*" => [0, "\x90n"], "+" => [0, "\x90p"], "," => [0, "\x90r"], "-" => [0, "\x90u"], "." => [100, "\x90"], "/" => [110, "\x90"], [111, "\x90"], [115, "\x90"], [116, "\x90"], [118, "\x90"], [119, "\x90"], [122, "\x90"], [123, "\x90"], [125, "\x90"], [126, "\x90"], [129, "\x90"], ":" => [143, "\x90"], ";" => [148, "\x90"], "<" => [151, "\x90"], "=" => [153, "\x90"], ">" => [83, "\x90"], "?" => [10, "\x90"], "@" => [77, "\x910"], "A" => [18, "\x910"], "B" => [77, "\x911"], "C" => [18, "\x911"], "D" => [77, "\x912"], "E" => [18, "\x912"], "F" => [77, "\x91a"], "G" => [18, "\x91a"], "H" => [77, "\x91c"], "I" => [18, "\x91c"], "J" => [77, "\x91e"], "K" => [18, "\x91e"], "L" => [77, "\x91i"], "M" => [18, "\x91i"], "N" => [77, "\x91o"], "O" => [18, "\x91o"], "P" => [77, "\x91s"], "Q" => [18, "\x91s"], "R" => [77, "\x91t"], "S" => [18, "\x91t"], "T" => [0, "\x91 "], "U" => [0, "\x91%"], "V" => [0, "\x91-"], "W" => [0, "\x91."], "X" => [0, "\x91/"], "Y" => [0, "\x913"], "Z" => [0, "\x914"], "[" => [0, "\x915"], "\\" => [0, "\x916"], "]" => [0, "\x917"], "^" => [0, "\x918"], "_" => [0, "\x919"], "`" => [0, "\x91="], "a" => [0, "\x91A"], "b" => [0, "\x91_"], "c" => [0, "\x91b"], "d" => [0, "\x91d"], "e" => [0, "\x91f"], "f" => [0, "\x91g"], "g" => [0, "\x91h"], "h" => [0, "\x91l"], "i" => [0, "\x91m"], "j" => [0, "\x91n"], "k" => [0, "\x91p"], "l" => [0, "\x91r"], "m" => [0, "\x91u"], "n" => [100, "\x91"], "o" => [110, "\x91"], "p" => [111, "\x91"], "q" => [115, "\x91"], "r" => [116, "\x91"], "s" => [118, "\x91"], "t" => [119, "\x91"], "u" => [122, "\x91"], "v" => [123, "\x91"], "w" => [125, "\x91"], "x" => [126, "\x91"], "y" => [129, "\x91"], "z" => [143, "\x91"], "{" => [148, "\x91"], "|" => [151, "\x91"], "}" => [153, "\x91"], "~" => [83, "\x91"], "" => [10, "\x91"], "\x80" => [77, "\x940"], "\x81" => [18, "\x940"], "\x82" => [77, "\x941"], "\x83" => [18, "\x941"], "\x84" => [77, "\x942"], "\x85" => [18, "\x942"], "\x86" => [77, "\x94a"], "\x87" => [18, "\x94a"], "\x88" => [77, "\x94c"], "\x89" => [18, "\x94c"], "\x8a" => [77, "\x94e"], "\x8b" => [18, "\x94e"], "\x8c" => [77, "\x94i"], "\x8d" => [18, "\x94i"], "\x8e" => [77, "\x94o"], "\x8f" => [18, "\x94o"], "\x90" => [77, "\x94s"], "\x91" => [18, "\x94s"], "\x92" => [77, "\x94t"], "\x93" => [18, "\x94t"], "\x94" => [0, "\x94 "], "\x95" => [0, "\x94%"], "\x96" => [0, "\x94-"], "\x97" => [0, "\x94."], "\x98" => [0, "\x94/"], "\x99" => [0, "\x943"], "\x9a" => [0, "\x944"], "\x9b" => [0, "\x945"], "\x9c" => [0, "\x946"], "\x9d" => [0, "\x947"], "\x9e" => [0, "\x948"], "\x9f" => [0, "\x949"], "\xa0" => [0, "\x94="], "\xa1" => [0, "\x94A"], "\xa2" => [0, "\x94_"], "\xa3" => [0, "\x94b"], "\xa4" => [0, "\x94d"], "\xa5" => [0, "\x94f"], "\xa6" => [0, "\x94g"], "\xa7" => [0, "\x94h"], "\xa8" => [0, "\x94l"], "\xa9" => [0, "\x94m"], "\xaa" => [0, "\x94n"], "\xab" => [0, "\x94p"], "\xac" => [0, "\x94r"], "\xad" => [0, "\x94u"], "\xae" => [100, "\x94"], "\xaf" => [110, "\x94"], "\xb0" => [111, "\x94"], "\xb1" => [115, "\x94"], "\xb2" => [116, "\x94"], "\xb3" => [118, "\x94"], "\xb4" => [119, "\x94"], "\xb5" => [122, "\x94"], "\xb6" => [123, "\x94"], "\xb7" => [125, "\x94"], "\xb8" => [126, "\x94"], "\xb9" => [129, "\x94"], "\xba" => [143, "\x94"], "\xbb" => [148, "\x94"], "\xbc" => [151, "\x94"], "\xbd" => [153, "\x94"], "\xbe" => [83, "\x94"], "\xbf" => [10, "\x94"], "\xc0" => [77, "\x9f0"], "\xc1" => [18, "\x9f0"], "\xc2" => [77, "\x9f1"], "\xc3" => [18, "\x9f1"], "\xc4" => [77, "\x9f2"], "\xc5" => [18, "\x9f2"], "\xc6" => [77, "\x9fa"], "\xc7" => [18, "\x9fa"], "\xc8" => [77, "\x9fc"], "\xc9" => [18, "\x9fc"], "\xca" => [77, "\x9fe"], "\xcb" => [18, "\x9fe"], "\xcc" => [77, "\x9fi"], "\xcd" => [18, "\x9fi"], "\xce" => [77, "\x9fo"], "\xcf" => [18, "\x9fo"], "\xd0" => [77, "\x9fs"], "\xd1" => [18, "\x9fs"], "\xd2" => [77, "\x9ft"], "\xd3" => [18, "\x9ft"], "\xd4" => [0, "\x9f "], "\xd5" => [0, "\x9f%"], "\xd6" => [0, "\x9f-"], "\xd7" => [0, "\x9f."], "\xd8" => [0, "\x9f/"], "\xd9" => [0, "\x9f3"], "\xda" => [0, "\x9f4"], "\xdb" => [0, "\x9f5"], "\xdc" => [0, "\x9f6"], "\xdd" => [0, "\x9f7"], "\xde" => [0, "\x9f8"], "\xdf" => [0, "\x9f9"], "\xe0" => [0, "\x9f="], "\xe1" => [0, "\x9fA"], "\xe2" => [0, "\x9f_"], "\xe3" => [0, "\x9fb"], "\xe4" => [0, "\x9fd"], "\xe5" => [0, "\x9ff"], "\xe6" => [0, "\x9fg"], "\xe7" => [0, "\x9fh"], "\xe8" => [0, "\x9fl"], "\xe9" => [0, "\x9fm"], "\xea" => [0, "\x9fn"], "\xeb" => [0, "\x9fp"], "\xec" => [0, "\x9fr"], "\xed" => [0, "\x9fu"], "\xee" => [100, "\x9f"], "\xef" => [110, "\x9f"], "\xf0" => [111, "\x9f"], "\xf1" => [115, "\x9f"], "\xf2" => [116, "\x9f"], "\xf3" => [118, "\x9f"], "\xf4" => [119, "\x9f"], "\xf5" => [122, "\x9f"], "\xf6" => [123, "\x9f"], "\xf7" => [125, "\x9f"], "\xf8" => [126, "\x9f"], "\xf9" => [129, "\x9f"], "\xfa" => [143, "\x9f"], "\xfb" => [148, "\x9f"], "\xfc" => [151, "\x9f"], "\xfd" => [153, "\x9f"], "\xfe" => [83, "\x9f"], "\xff" => [10, "\x9f"]], ["\x00" => [94, "\x930"], "\x01" => [76, "\x930"], "\x02" => [104, "\x930"], "\x03" => [16, "\x930"], "\x04" => [94, "\x931"], "\x05" => [76, "\x931"], "\x06" => [104, "\x931"], "\x07" => [16, "\x931"], "\x08" => [94, "\x932"], "\t" => [76, "\x932"], "\n" => [104, "\x932"], "\v" => [16, "\x932"], "\f" => [94, "\x93a"], "\r" => [76, "\x93a"], "\x0e" => [104, "\x93a"], "\x0f" => [16, "\x93a"], "\x10" => [94, "\x93c"], "\x11" => [76, "\x93c"], "\x12" => [104, "\x93c"], "\x13" => [16, "\x93c"], "\x14" => [94, "\x93e"], "\x15" => [76, "\x93e"], "\x16" => [104, "\x93e"], "\x17" => [16, "\x93e"], "\x18" => [94, "\x93i"], "\x19" => [76, "\x93i"], "\x1a" => [104, "\x93i"], "\x1b" => [16, "\x93i"], "\x1c" => [94, "\x93o"], "\x1d" => [76, "\x93o"], "\x1e" => [104, "\x93o"], "\x1f" => [16, "\x93o"], " " => [94, "\x93s"], "!" => [76, "\x93s"], "\"" => [104, "\x93s"], "#" => [16, "\x93s"], "\$" => [94, "\x93t"], "%" => [76, "\x93t"], "&" => [104, "\x93t"], "'" => [16, "\x93t"], "(" => [77, "\x93 "], ")" => [18, "\x93 "], "*" => [77, "\x93%"], "+" => [18, "\x93%"], "," => [77, "\x93-"], "-" => [18, "\x93-"], "." => [77, "\x93."], "/" => [18, "\x93."], [77, "\x93/"], [18, "\x93/"], [77, "\x933"], [18, "\x933"], [77, "\x934"], [18, "\x934"], [77, "\x935"], [18, "\x935"], [77, "\x936"], [18, "\x936"], ":" => [77, "\x937"], ";" => [18, "\x937"], "<" => [77, "\x938"], "=" => [18, "\x938"], ">" => [77, "\x939"], "?" => [18, "\x939"], "@" => [77, "\x93="], "A" => [18, "\x93="], "B" => [77, "\x93A"], "C" => [18, "\x93A"], "D" => [77, "\x93_"], "E" => [18, "\x93_"], "F" => [77, "\x93b"], "G" => [18, "\x93b"], "H" => [77, "\x93d"], "I" => [18, "\x93d"], "J" => [77, "\x93f"], "K" => [18, "\x93f"], "L" => [77, "\x93g"], "M" => [18, "\x93g"], "N" => [77, "\x93h"], "O" => [18, "\x93h"], "P" => [77, "\x93l"], "Q" => [18, "\x93l"], "R" => [77, "\x93m"], "S" => [18, "\x93m"], "T" => [77, "\x93n"], "U" => [18, "\x93n"], "V" => [77, "\x93p"], "W" => [18, "\x93p"], "X" => [77, "\x93r"], "Y" => [18, "\x93r"], "Z" => [77, "\x93u"], "[" => [18, "\x93u"], "\\" => [0, "\x93:"], "]" => [0, "\x93B"], "^" => [0, "\x93C"], "_" => [0, "\x93D"], "`" => [0, "\x93E"], "a" => [0, "\x93F"], "b" => [0, "\x93G"], "c" => [0, "\x93H"], "d" => [0, "\x93I"], "e" => [0, "\x93J"], "f" => [0, "\x93K"], "g" => [0, "\x93L"], "h" => [0, "\x93M"], "i" => [0, "\x93N"], "j" => [0, "\x93O"], "k" => [0, "\x93P"], "l" => [0, "\x93Q"], "m" => [0, "\x93R"], "n" => [0, "\x93S"], "o" => [0, "\x93T"], "p" => [0, "\x93U"], "q" => [0, "\x93V"], "r" => [0, "\x93W"], "s" => [0, "\x93Y"], "t" => [0, "\x93j"], "u" => [0, "\x93k"], "v" => [0, "\x93q"], "w" => [0, "\x93v"], "x" => [0, "\x93w"], "y" => [0, "\x93x"], "z" => [0, "\x93y"], "{" => [0, "\x93z"], "|" => [82, "\x93"], "}" => [87, "\x93"], "~" => [130, "\x93"], "" => [9, "\x93"], "\x80" => [94, "\x950"], "\x81" => [76, "\x950"], "\x82" => [104, "\x950"], "\x83" => [16, "\x950"], "\x84" => [94, "\x951"], "\x85" => [76, "\x951"], "\x86" => [104, "\x951"], "\x87" => [16, "\x951"], "\x88" => [94, "\x952"], "\x89" => [76, "\x952"], "\x8a" => [104, "\x952"], "\x8b" => [16, "\x952"], "\x8c" => [94, "\x95a"], "\x8d" => [76, "\x95a"], "\x8e" => [104, "\x95a"], "\x8f" => [16, "\x95a"], "\x90" => [94, "\x95c"], "\x91" => [76, "\x95c"], "\x92" => [104, "\x95c"], "\x93" => [16, "\x95c"], "\x94" => [94, "\x95e"], "\x95" => [76, "\x95e"], "\x96" => [104, "\x95e"], "\x97" => [16, "\x95e"], "\x98" => [94, "\x95i"], "\x99" => [76, "\x95i"], "\x9a" => [104, "\x95i"], "\x9b" => [16, "\x95i"], "\x9c" => [94, "\x95o"], "\x9d" => [76, "\x95o"], "\x9e" => [104, "\x95o"], "\x9f" => [16, "\x95o"], "\xa0" => [94, "\x95s"], "\xa1" => [76, "\x95s"], "\xa2" => [104, "\x95s"], "\xa3" => [16, "\x95s"], "\xa4" => [94, "\x95t"], "\xa5" => [76, "\x95t"], "\xa6" => [104, "\x95t"], "\xa7" => [16, "\x95t"], "\xa8" => [77, "\x95 "], "\xa9" => [18, "\x95 "], "\xaa" => [77, "\x95%"], "\xab" => [18, "\x95%"], "\xac" => [77, "\x95-"], "\xad" => [18, "\x95-"], "\xae" => [77, "\x95."], "\xaf" => [18, "\x95."], "\xb0" => [77, "\x95/"], "\xb1" => [18, "\x95/"], "\xb2" => [77, "\x953"], "\xb3" => [18, "\x953"], "\xb4" => [77, "\x954"], "\xb5" => [18, "\x954"], "\xb6" => [77, "\x955"], "\xb7" => [18, "\x955"], "\xb8" => [77, "\x956"], "\xb9" => [18, "\x956"], "\xba" => [77, "\x957"], "\xbb" => [18, "\x957"], "\xbc" => [77, "\x958"], "\xbd" => [18, "\x958"], "\xbe" => [77, "\x959"], "\xbf" => [18, "\x959"], "\xc0" => [77, "\x95="], "\xc1" => [18, "\x95="], "\xc2" => [77, "\x95A"], "\xc3" => [18, "\x95A"], "\xc4" => [77, "\x95_"], "\xc5" => [18, "\x95_"], "\xc6" => [77, "\x95b"], "\xc7" => [18, "\x95b"], "\xc8" => [77, "\x95d"], "\xc9" => [18, "\x95d"], "\xca" => [77, "\x95f"], "\xcb" => [18, "\x95f"], "\xcc" => [77, "\x95g"], "\xcd" => [18, "\x95g"], "\xce" => [77, "\x95h"], "\xcf" => [18, "\x95h"], "\xd0" => [77, "\x95l"], "\xd1" => [18, "\x95l"], "\xd2" => [77, "\x95m"], "\xd3" => [18, "\x95m"], "\xd4" => [77, "\x95n"], "\xd5" => [18, "\x95n"], "\xd6" => [77, "\x95p"], "\xd7" => [18, "\x95p"], "\xd8" => [77, "\x95r"], "\xd9" => [18, "\x95r"], "\xda" => [77, "\x95u"], "\xdb" => [18, "\x95u"], "\xdc" => [0, "\x95:"], "\xdd" => [0, "\x95B"], "\xde" => [0, "\x95C"], "\xdf" => [0, "\x95D"], "\xe0" => [0, "\x95E"], "\xe1" => [0, "\x95F"], "\xe2" => [0, "\x95G"], "\xe3" => [0, "\x95H"], "\xe4" => [0, "\x95I"], "\xe5" => [0, "\x95J"], "\xe6" => [0, "\x95K"], "\xe7" => [0, "\x95L"], "\xe8" => [0, "\x95M"], "\xe9" => [0, "\x95N"], "\xea" => [0, "\x95O"], "\xeb" => [0, "\x95P"], "\xec" => [0, "\x95Q"], "\xed" => [0, "\x95R"], "\xee" => [0, "\x95S"], "\xef" => [0, "\x95T"], "\xf0" => [0, "\x95U"], "\xf1" => [0, "\x95V"], "\xf2" => [0, "\x95W"], "\xf3" => [0, "\x95Y"], "\xf4" => [0, "\x95j"], "\xf5" => [0, "\x95k"], "\xf6" => [0, "\x95q"], "\xf7" => [0, "\x95v"], "\xf8" => [0, "\x95w"], "\xf9" => [0, "\x95x"], "\xfa" => [0, "\x95y"], "\xfb" => [0, "\x95z"], "\xfc" => [82, "\x95"], "\xfd" => [87, "\x95"], "\xfe" => [130, "\x95"], "\xff" => [9, "\x95"]], ["\x00" => [77, "\x930"], "\x01" => [18, "\x930"], "\x02" => [77, "\x931"], "\x03" => [18, "\x931"], "\x04" => [77, "\x932"], "\x05" => [18, "\x932"], "\x06" => [77, "\x93a"], "\x07" => [18, "\x93a"], "\x08" => [77, "\x93c"], "\t" => [18, "\x93c"], "\n" => [77, "\x93e"], "\v" => [18, "\x93e"], "\f" => [77, "\x93i"], "\r" => [18, "\x93i"], "\x0e" => [77, "\x93o"], "\x0f" => [18, "\x93o"], "\x10" => [77, "\x93s"], "\x11" => [18, "\x93s"], "\x12" => [77, "\x93t"], "\x13" => [18, "\x93t"], "\x14" => [0, "\x93 "], "\x15" => [0, "\x93%"], "\x16" => [0, "\x93-"], "\x17" => [0, "\x93."], "\x18" => [0, "\x93/"], "\x19" => [0, "\x933"], "\x1a" => [0, "\x934"], "\x1b" => [0, "\x935"], "\x1c" => [0, "\x936"], "\x1d" => [0, "\x937"], "\x1e" => [0, "\x938"], "\x1f" => [0, "\x939"], " " => [0, "\x93="], "!" => [0, "\x93A"], "\"" => [0, "\x93_"], "#" => [0, "\x93b"], "\$" => [0, "\x93d"], "%" => [0, "\x93f"], "&" => [0, "\x93g"], "'" => [0, "\x93h"], "(" => [0, "\x93l"], ")" => [0, "\x93m"], "*" => [0, "\x93n"], "+" => [0, "\x93p"], "," => [0, "\x93r"], "-" => [0, "\x93u"], "." => [100, "\x93"], "/" => [110, "\x93"], [111, "\x93"], [115, "\x93"], [116, "\x93"], [118, "\x93"], [119, "\x93"], [122, "\x93"], [123, "\x93"], [125, "\x93"], [126, "\x93"], [129, "\x93"], ":" => [143, "\x93"], ";" => [148, "\x93"], "<" => [151, "\x93"], "=" => [153, "\x93"], ">" => [83, "\x93"], "?" => [10, "\x93"], "@" => [77, "\x950"], "A" => [18, "\x950"], "B" => [77, "\x951"], "C" => [18, "\x951"], "D" => [77, "\x952"], "E" => [18, "\x952"], "F" => [77, "\x95a"], "G" => [18, "\x95a"], "H" => [77, "\x95c"], "I" => [18, "\x95c"], "J" => [77, "\x95e"], "K" => [18, "\x95e"], "L" => [77, "\x95i"], "M" => [18, "\x95i"], "N" => [77, "\x95o"], "O" => [18, "\x95o"], "P" => [77, "\x95s"], "Q" => [18, "\x95s"], "R" => [77, "\x95t"], "S" => [18, "\x95t"], "T" => [0, "\x95 "], "U" => [0, "\x95%"], "V" => [0, "\x95-"], "W" => [0, "\x95."], "X" => [0, "\x95/"], "Y" => [0, "\x953"], "Z" => [0, "\x954"], "[" => [0, "\x955"], "\\" => [0, "\x956"], "]" => [0, "\x957"], "^" => [0, "\x958"], "_" => [0, "\x959"], "`" => [0, "\x95="], "a" => [0, "\x95A"], "b" => [0, "\x95_"], "c" => [0, "\x95b"], "d" => [0, "\x95d"], "e" => [0, "\x95f"], "f" => [0, "\x95g"], "g" => [0, "\x95h"], "h" => [0, "\x95l"], "i" => [0, "\x95m"], "j" => [0, "\x95n"], "k" => [0, "\x95p"], "l" => [0, "\x95r"], "m" => [0, "\x95u"], "n" => [100, "\x95"], "o" => [110, "\x95"], "p" => [111, "\x95"], "q" => [115, "\x95"], "r" => [116, "\x95"], "s" => [118, "\x95"], "t" => [119, "\x95"], "u" => [122, "\x95"], "v" => [123, "\x95"], "w" => [125, "\x95"], "x" => [126, "\x95"], "y" => [129, "\x95"], "z" => [143, "\x95"], "{" => [148, "\x95"], "|" => [151, "\x95"], "}" => [153, "\x95"], "~" => [83, "\x95"], "" => [10, "\x95"], "\x80" => [77, "\x960"], "\x81" => [18, "\x960"], "\x82" => [77, "\x961"], "\x83" => [18, "\x961"], "\x84" => [77, "\x962"], "\x85" => [18, "\x962"], "\x86" => [77, "\x96a"], "\x87" => [18, "\x96a"], "\x88" => [77, "\x96c"], "\x89" => [18, "\x96c"], "\x8a" => [77, "\x96e"], "\x8b" => [18, "\x96e"], "\x8c" => [77, "\x96i"], "\x8d" => [18, "\x96i"], "\x8e" => [77, "\x96o"], "\x8f" => [18, "\x96o"], "\x90" => [77, "\x96s"], "\x91" => [18, "\x96s"], "\x92" => [77, "\x96t"], "\x93" => [18, "\x96t"], "\x94" => [0, "\x96 "], "\x95" => [0, "\x96%"], "\x96" => [0, "\x96-"], "\x97" => [0, "\x96."], "\x98" => [0, "\x96/"], "\x99" => [0, "\x963"], "\x9a" => [0, "\x964"], "\x9b" => [0, "\x965"], "\x9c" => [0, "\x966"], "\x9d" => [0, "\x967"], "\x9e" => [0, "\x968"], "\x9f" => [0, "\x969"], "\xa0" => [0, "\x96="], "\xa1" => [0, "\x96A"], "\xa2" => [0, "\x96_"], "\xa3" => [0, "\x96b"], "\xa4" => [0, "\x96d"], "\xa5" => [0, "\x96f"], "\xa6" => [0, "\x96g"], "\xa7" => [0, "\x96h"], "\xa8" => [0, "\x96l"], "\xa9" => [0, "\x96m"], "\xaa" => [0, "\x96n"], "\xab" => [0, "\x96p"], "\xac" => [0, "\x96r"], "\xad" => [0, "\x96u"], "\xae" => [100, "\x96"], "\xaf" => [110, "\x96"], "\xb0" => [111, "\x96"], "\xb1" => [115, "\x96"], "\xb2" => [116, "\x96"], "\xb3" => [118, "\x96"], "\xb4" => [119, "\x96"], "\xb5" => [122, "\x96"], "\xb6" => [123, "\x96"], "\xb7" => [125, "\x96"], "\xb8" => [126, "\x96"], "\xb9" => [129, "\x96"], "\xba" => [143, "\x96"], "\xbb" => [148, "\x96"], "\xbc" => [151, "\x96"], "\xbd" => [153, "\x96"], "\xbe" => [83, "\x96"], "\xbf" => [10, "\x96"], "\xc0" => [77, "\x970"], "\xc1" => [18, "\x970"], "\xc2" => [77, "\x971"], "\xc3" => [18, "\x971"], "\xc4" => [77, "\x972"], "\xc5" => [18, "\x972"], "\xc6" => [77, "\x97a"], "\xc7" => [18, "\x97a"], "\xc8" => [77, "\x97c"], "\xc9" => [18, "\x97c"], "\xca" => [77, "\x97e"], "\xcb" => [18, "\x97e"], "\xcc" => [77, "\x97i"], "\xcd" => [18, "\x97i"], "\xce" => [77, "\x97o"], "\xcf" => [18, "\x97o"], "\xd0" => [77, "\x97s"], "\xd1" => [18, "\x97s"], "\xd2" => [77, "\x97t"], "\xd3" => [18, "\x97t"], "\xd4" => [0, "\x97 "], "\xd5" => [0, "\x97%"], "\xd6" => [0, "\x97-"], "\xd7" => [0, "\x97."], "\xd8" => [0, "\x97/"], "\xd9" => [0, "\x973"], "\xda" => [0, "\x974"], "\xdb" => [0, "\x975"], "\xdc" => [0, "\x976"], "\xdd" => [0, "\x977"], "\xde" => [0, "\x978"], "\xdf" => [0, "\x979"], "\xe0" => [0, "\x97="], "\xe1" => [0, "\x97A"], "\xe2" => [0, "\x97_"], "\xe3" => [0, "\x97b"], "\xe4" => [0, "\x97d"], "\xe5" => [0, "\x97f"], "\xe6" => [0, "\x97g"], "\xe7" => [0, "\x97h"], "\xe8" => [0, "\x97l"], "\xe9" => [0, "\x97m"], "\xea" => [0, "\x97n"], "\xeb" => [0, "\x97p"], "\xec" => [0, "\x97r"], "\xed" => [0, "\x97u"], "\xee" => [100, "\x97"], "\xef" => [110, "\x97"], "\xf0" => [111, "\x97"], "\xf1" => [115, "\x97"], "\xf2" => [116, "\x97"], "\xf3" => [118, "\x97"], "\xf4" => [119, "\x97"], "\xf5" => [122, "\x97"], "\xf6" => [123, "\x97"], "\xf7" => [125, "\x97"], "\xf8" => [126, "\x97"], "\xf9" => [129, "\x97"], "\xfa" => [143, "\x97"], "\xfb" => [148, "\x97"], "\xfc" => [151, "\x97"], "\xfd" => [153, "\x97"], "\xfe" => [83, "\x97"], "\xff" => [10, "\x97"]], ["\x00" => [0, "\x930"], "\x01" => [0, "\x931"], "\x02" => [0, "\x932"], "\x03" => [0, "\x93a"], "\x04" => [0, "\x93c"], "\x05" => [0, "\x93e"], "\x06" => [0, "\x93i"], "\x07" => [0, "\x93o"], "\x08" => [0, "\x93s"], "\t" => [0, "\x93t"], "\n" => [73, "\x93"], "\v" => [88, "\x93"], "\f" => [89, "\x93"], "\r" => [96, "\x93"], "\x0e" => [97, "\x93"], "\x0f" => [99, "\x93"], "\x10" => [106, "\x93"], "\x11" => [136, "\x93"], "\x12" => [139, "\x93"], "\x13" => [141, "\x93"], "\x14" => [145, "\x93"], "\x15" => [147, "\x93"], "\x16" => [149, "\x93"], "\x17" => [101, "\x93"], "\x18" => [112, "\x93"], "\x19" => [117, "\x93"], "\x1a" => [120, "\x93"], "\x1b" => [124, "\x93"], "\x1c" => [127, "\x93"], "\x1d" => [144, "\x93"], "\x1e" => [152, "\x93"], "\x1f" => [11, "\x93"], " " => [0, "\x950"], "!" => [0, "\x951"], "\"" => [0, "\x952"], "#" => [0, "\x95a"], "\$" => [0, "\x95c"], "%" => [0, "\x95e"], "&" => [0, "\x95i"], "'" => [0, "\x95o"], "(" => [0, "\x95s"], ")" => [0, "\x95t"], "*" => [73, "\x95"], "+" => [88, "\x95"], "," => [89, "\x95"], "-" => [96, "\x95"], "." => [97, "\x95"], "/" => [99, "\x95"], [106, "\x95"], [136, "\x95"], [139, "\x95"], [141, "\x95"], [145, "\x95"], [147, "\x95"], [149, "\x95"], [101, "\x95"], [112, "\x95"], [117, "\x95"], ":" => [120, "\x95"], ";" => [124, "\x95"], "<" => [127, "\x95"], "=" => [144, "\x95"], ">" => [152, "\x95"], "?" => [11, "\x95"], "@" => [0, "\x960"], "A" => [0, "\x961"], "B" => [0, "\x962"], "C" => [0, "\x96a"], "D" => [0, "\x96c"], "E" => [0, "\x96e"], "F" => [0, "\x96i"], "G" => [0, "\x96o"], "H" => [0, "\x96s"], "I" => [0, "\x96t"], "J" => [73, "\x96"], "K" => [88, "\x96"], "L" => [89, "\x96"], "M" => [96, "\x96"], "N" => [97, "\x96"], "O" => [99, "\x96"], "P" => [106, "\x96"], "Q" => [136, "\x96"], "R" => [139, "\x96"], "S" => [141, "\x96"], "T" => [145, "\x96"], "U" => [147, "\x96"], "V" => [149, "\x96"], "W" => [101, "\x96"], "X" => [112, "\x96"], "Y" => [117, "\x96"], "Z" => [120, "\x96"], "[" => [124, "\x96"], "\\" => [127, "\x96"], "]" => [144, "\x96"], "^" => [152, "\x96"], "_" => [11, "\x96"], "`" => [0, "\x970"], "a" => [0, "\x971"], "b" => [0, "\x972"], "c" => [0, "\x97a"], "d" => [0, "\x97c"], "e" => [0, "\x97e"], "f" => [0, "\x97i"], "g" => [0, "\x97o"], "h" => [0, "\x97s"], "i" => [0, "\x97t"], "j" => [73, "\x97"], "k" => [88, "\x97"], "l" => [89, "\x97"], "m" => [96, "\x97"], "n" => [97, "\x97"], "o" => [99, "\x97"], "p" => [106, "\x97"], "q" => [136, "\x97"], "r" => [139, "\x97"], "s" => [141, "\x97"], "t" => [145, "\x97"], "u" => [147, "\x97"], "v" => [149, "\x97"], "w" => [101, "\x97"], "x" => [112, "\x97"], "y" => [117, "\x97"], "z" => [120, "\x97"], "{" => [124, "\x97"], "|" => [127, "\x97"], "}" => [144, "\x97"], "~" => [152, "\x97"], "" => [11, "\x97"], "\x80" => [0, "\x980"], "\x81" => [0, "\x981"], "\x82" => [0, "\x982"], "\x83" => [0, "\x98a"], "\x84" => [0, "\x98c"], "\x85" => [0, "\x98e"], "\x86" => [0, "\x98i"], "\x87" => [0, "\x98o"], "\x88" => [0, "\x98s"], "\x89" => [0, "\x98t"], "\x8a" => [73, "\x98"], "\x8b" => [88, "\x98"], "\x8c" => [89, "\x98"], "\x8d" => [96, "\x98"], "\x8e" => [97, "\x98"], "\x8f" => [99, "\x98"], "\x90" => [106, "\x98"], "\x91" => [136, "\x98"], "\x92" => [139, "\x98"], "\x93" => [141, "\x98"], "\x94" => [145, "\x98"], "\x95" => [147, "\x98"], "\x96" => [149, "\x98"], "\x97" => [101, "\x98"], "\x98" => [112, "\x98"], "\x99" => [117, "\x98"], "\x9a" => [120, "\x98"], "\x9b" => [124, "\x98"], "\x9c" => [127, "\x98"], "\x9d" => [144, "\x98"], "\x9e" => [152, "\x98"], "\x9f" => [11, "\x98"], "\xa0" => [0, "\x9b0"], "\xa1" => [0, "\x9b1"], "\xa2" => [0, "\x9b2"], "\xa3" => [0, "\x9ba"], "\xa4" => [0, "\x9bc"], "\xa5" => [0, "\x9be"], "\xa6" => [0, "\x9bi"], "\xa7" => [0, "\x9bo"], "\xa8" => [0, "\x9bs"], "\xa9" => [0, "\x9bt"], "\xaa" => [73, "\x9b"], "\xab" => [88, "\x9b"], "\xac" => [89, "\x9b"], "\xad" => [96, "\x9b"], "\xae" => [97, "\x9b"], "\xaf" => [99, "\x9b"], "\xb0" => [106, "\x9b"], "\xb1" => [136, "\x9b"], "\xb2" => [139, "\x9b"], "\xb3" => [141, "\x9b"], "\xb4" => [145, "\x9b"], "\xb5" => [147, "\x9b"], "\xb6" => [149, "\x9b"], "\xb7" => [101, "\x9b"], "\xb8" => [112, "\x9b"], "\xb9" => [117, "\x9b"], "\xba" => [120, "\x9b"], "\xbb" => [124, "\x9b"], "\xbc" => [127, "\x9b"], "\xbd" => [144, "\x9b"], "\xbe" => [152, "\x9b"], "\xbf" => [11, "\x9b"], "\xc0" => [0, "\x9d0"], "\xc1" => [0, "\x9d1"], "\xc2" => [0, "\x9d2"], "\xc3" => [0, "\x9da"], "\xc4" => [0, "\x9dc"], "\xc5" => [0, "\x9de"], "\xc6" => [0, "\x9di"], "\xc7" => [0, "\x9do"], "\xc8" => [0, "\x9ds"], "\xc9" => [0, "\x9dt"], "\xca" => [73, "\x9d"], "\xcb" => [88, "\x9d"], "\xcc" => [89, "\x9d"], "\xcd" => [96, "\x9d"], "\xce" => [97, "\x9d"], "\xcf" => [99, "\x9d"], "\xd0" => [106, "\x9d"], "\xd1" => [136, "\x9d"], "\xd2" => [139, "\x9d"], "\xd3" => [141, "\x9d"], "\xd4" => [145, "\x9d"], "\xd5" => [147, "\x9d"], "\xd6" => [149, "\x9d"], "\xd7" => [101, "\x9d"], "\xd8" => [112, "\x9d"], "\xd9" => [117, "\x9d"], "\xda" => [120, "\x9d"], "\xdb" => [124, "\x9d"], "\xdc" => [127, "\x9d"], "\xdd" => [144, "\x9d"], "\xde" => [152, "\x9d"], "\xdf" => [11, "\x9d"], "\xe0" => [0, "\x9e0"], "\xe1" => [0, "\x9e1"], "\xe2" => [0, "\x9e2"], "\xe3" => [0, "\x9ea"], "\xe4" => [0, "\x9ec"], "\xe5" => [0, "\x9ee"], "\xe6" => [0, "\x9ei"], "\xe7" => [0, "\x9eo"], "\xe8" => [0, "\x9es"], "\xe9" => [0, "\x9et"], "\xea" => [73, "\x9e"], "\xeb" => [88, "\x9e"], "\xec" => [89, "\x9e"], "\xed" => [96, "\x9e"], "\xee" => [97, "\x9e"], "\xef" => [99, "\x9e"], "\xf0" => [106, "\x9e"], "\xf1" => [136, "\x9e"], "\xf2" => [139, "\x9e"], "\xf3" => [141, "\x9e"], "\xf4" => [145, "\x9e"], "\xf5" => [147, "\x9e"], "\xf6" => [149, "\x9e"], "\xf7" => [101, "\x9e"], "\xf8" => [112, "\x9e"], "\xf9" => [117, "\x9e"], "\xfa" => [120, "\x9e"], "\xfb" => [124, "\x9e"], "\xfc" => [127, "\x9e"], "\xfd" => [144, "\x9e"], "\xfe" => [152, "\x9e"], "\xff" => [11, "\x9e"]], ["\x00" => [92, "\x93"], "\x01" => [95, "\x93"], "\x02" => [137, "\x93"], "\x03" => [142, "\x93"], "\x04" => [150, "\x93"], "\x05" => [74, "\x93"], "\x06" => [90, "\x93"], "\x07" => [98, "\x93"], "\x08" => [107, "\x93"], "\t" => [140, "\x93"], "\n" => [146, "\x93"], "\v" => [102, "\x93"], "\f" => [113, "\x93"], "\r" => [121, "\x93"], "\x0e" => [128, "\x93"], "\x0f" => [12, "\x93"], "\x10" => [92, "\x95"], "\x11" => [95, "\x95"], "\x12" => [137, "\x95"], "\x13" => [142, "\x95"], "\x14" => [150, "\x95"], "\x15" => [74, "\x95"], "\x16" => [90, "\x95"], "\x17" => [98, "\x95"], "\x18" => [107, "\x95"], "\x19" => [140, "\x95"], "\x1a" => [146, "\x95"], "\x1b" => [102, "\x95"], "\x1c" => [113, "\x95"], "\x1d" => [121, "\x95"], "\x1e" => [128, "\x95"], "\x1f" => [12, "\x95"], " " => [92, "\x96"], "!" => [95, "\x96"], "\"" => [137, "\x96"], "#" => [142, "\x96"], "\$" => [150, "\x96"], "%" => [74, "\x96"], "&" => [90, "\x96"], "'" => [98, "\x96"], "(" => [107, "\x96"], ")" => [140, "\x96"], "*" => [146, "\x96"], "+" => [102, "\x96"], "," => [113, "\x96"], "-" => [121, "\x96"], "." => [128, "\x96"], "/" => [12, "\x96"], [92, "\x97"], [95, "\x97"], [137, "\x97"], [142, "\x97"], [150, "\x97"], [74, "\x97"], [90, "\x97"], [98, "\x97"], [107, "\x97"], [140, "\x97"], ":" => [146, "\x97"], ";" => [102, "\x97"], "<" => [113, "\x97"], "=" => [121, "\x97"], ">" => [128, "\x97"], "?" => [12, "\x97"], "@" => [92, "\x98"], "A" => [95, "\x98"], "B" => [137, "\x98"], "C" => [142, "\x98"], "D" => [150, "\x98"], "E" => [74, "\x98"], "F" => [90, "\x98"], "G" => [98, "\x98"], "H" => [107, "\x98"], "I" => [140, "\x98"], "J" => [146, "\x98"], "K" => [102, "\x98"], "L" => [113, "\x98"], "M" => [121, "\x98"], "N" => [128, "\x98"], "O" => [12, "\x98"], "P" => [92, "\x9b"], "Q" => [95, "\x9b"], "R" => [137, "\x9b"], "S" => [142, "\x9b"], "T" => [150, "\x9b"], "U" => [74, "\x9b"], "V" => [90, "\x9b"], "W" => [98, "\x9b"], "X" => [107, "\x9b"], "Y" => [140, "\x9b"], "Z" => [146, "\x9b"], "[" => [102, "\x9b"], "\\" => [113, "\x9b"], "]" => [121, "\x9b"], "^" => [128, "\x9b"], "_" => [12, "\x9b"], "`" => [92, "\x9d"], "a" => [95, "\x9d"], "b" => [137, "\x9d"], "c" => [142, "\x9d"], "d" => [150, "\x9d"], "e" => [74, "\x9d"], "f" => [90, "\x9d"], "g" => [98, "\x9d"], "h" => [107, "\x9d"], "i" => [140, "\x9d"], "j" => [146, "\x9d"], "k" => [102, "\x9d"], "l" => [113, "\x9d"], "m" => [121, "\x9d"], "n" => [128, "\x9d"], "o" => [12, "\x9d"], "p" => [92, "\x9e"], "q" => [95, "\x9e"], "r" => [137, "\x9e"], "s" => [142, "\x9e"], "t" => [150, "\x9e"], "u" => [74, "\x9e"], "v" => [90, "\x9e"], "w" => [98, "\x9e"], "x" => [107, "\x9e"], "y" => [140, "\x9e"], "z" => [146, "\x9e"], "{" => [102, "\x9e"], "|" => [113, "\x9e"], "}" => [121, "\x9e"], "~" => [128, "\x9e"], "" => [12, "\x9e"], "\x80" => [92, "\xa5"], "\x81" => [95, "\xa5"], "\x82" => [137, "\xa5"], "\x83" => [142, "\xa5"], "\x84" => [150, "\xa5"], "\x85" => [74, "\xa5"], "\x86" => [90, "\xa5"], "\x87" => [98, "\xa5"], "\x88" => [107, "\xa5"], "\x89" => [140, "\xa5"], "\x8a" => [146, "\xa5"], "\x8b" => [102, "\xa5"], "\x8c" => [113, "\xa5"], "\x8d" => [121, "\xa5"], "\x8e" => [128, "\xa5"], "\x8f" => [12, "\xa5"], "\x90" => [92, "\xa6"], "\x91" => [95, "\xa6"], "\x92" => [137, "\xa6"], "\x93" => [142, "\xa6"], "\x94" => [150, "\xa6"], "\x95" => [74, "\xa6"], "\x96" => [90, "\xa6"], "\x97" => [98, "\xa6"], "\x98" => [107, "\xa6"], "\x99" => [140, "\xa6"], "\x9a" => [146, "\xa6"], "\x9b" => [102, "\xa6"], "\x9c" => [113, "\xa6"], "\x9d" => [121, "\xa6"], "\x9e" => [128, "\xa6"], "\x9f" => [12, "\xa6"], "\xa0" => [92, "\xa8"], "\xa1" => [95, "\xa8"], "\xa2" => [137, "\xa8"], "\xa3" => [142, "\xa8"], "\xa4" => [150, "\xa8"], "\xa5" => [74, "\xa8"], "\xa6" => [90, "\xa8"], "\xa7" => [98, "\xa8"], "\xa8" => [107, "\xa8"], "\xa9" => [140, "\xa8"], "\xaa" => [146, "\xa8"], "\xab" => [102, "\xa8"], "\xac" => [113, "\xa8"], "\xad" => [121, "\xa8"], "\xae" => [128, "\xa8"], "\xaf" => [12, "\xa8"], "\xb0" => [92, "\xae"], "\xb1" => [95, "\xae"], "\xb2" => [137, "\xae"], "\xb3" => [142, "\xae"], "\xb4" => [150, "\xae"], "\xb5" => [74, "\xae"], "\xb6" => [90, "\xae"], "\xb7" => [98, "\xae"], "\xb8" => [107, "\xae"], "\xb9" => [140, "\xae"], "\xba" => [146, "\xae"], "\xbb" => [102, "\xae"], "\xbc" => [113, "\xae"], "\xbd" => [121, "\xae"], "\xbe" => [128, "\xae"], "\xbf" => [12, "\xae"], "\xc0" => [92, "\xaf"], "\xc1" => [95, "\xaf"], "\xc2" => [137, "\xaf"], "\xc3" => [142, "\xaf"], "\xc4" => [150, "\xaf"], "\xc5" => [74, "\xaf"], "\xc6" => [90, "\xaf"], "\xc7" => [98, "\xaf"], "\xc8" => [107, "\xaf"], "\xc9" => [140, "\xaf"], "\xca" => [146, "\xaf"], "\xcb" => [102, "\xaf"], "\xcc" => [113, "\xaf"], "\xcd" => [121, "\xaf"], "\xce" => [128, "\xaf"], "\xcf" => [12, "\xaf"], "\xd0" => [92, "\xb4"], "\xd1" => [95, "\xb4"], "\xd2" => [137, "\xb4"], "\xd3" => [142, "\xb4"], "\xd4" => [150, "\xb4"], "\xd5" => [74, "\xb4"], "\xd6" => [90, "\xb4"], "\xd7" => [98, "\xb4"], "\xd8" => [107, "\xb4"], "\xd9" => [140, "\xb4"], "\xda" => [146, "\xb4"], "\xdb" => [102, "\xb4"], "\xdc" => [113, "\xb4"], "\xdd" => [121, "\xb4"], "\xde" => [128, "\xb4"], "\xdf" => [12, "\xb4"], "\xe0" => [92, "\xb6"], "\xe1" => [95, "\xb6"], "\xe2" => [137, "\xb6"], "\xe3" => [142, "\xb6"], "\xe4" => [150, "\xb6"], "\xe5" => [74, "\xb6"], "\xe6" => [90, "\xb6"], "\xe7" => [98, "\xb6"], "\xe8" => [107, "\xb6"], "\xe9" => [140, "\xb6"], "\xea" => [146, "\xb6"], "\xeb" => [102, "\xb6"], "\xec" => [113, "\xb6"], "\xed" => [121, "\xb6"], "\xee" => [128, "\xb6"], "\xef" => [12, "\xb6"], "\xf0" => [92, "\xb7"], "\xf1" => [95, "\xb7"], "\xf2" => [137, "\xb7"], "\xf3" => [142, "\xb7"], "\xf4" => [150, "\xb7"], "\xf5" => [74, "\xb7"], "\xf6" => [90, "\xb7"], "\xf7" => [98, "\xb7"], "\xf8" => [107, "\xb7"], "\xf9" => [140, "\xb7"], "\xfa" => [146, "\xb7"], "\xfb" => [102, "\xb7"], "\xfc" => [113, "\xb7"], "\xfd" => [121, "\xb7"], "\xfe" => [128, "\xb7"], "\xff" => [12, "\xb7"]], ["\x00" => [94, "\x940"], "\x01" => [76, "\x940"], "\x02" => [104, "\x940"], "\x03" => [16, "\x940"], "\x04" => [94, "\x941"], "\x05" => [76, "\x941"], "\x06" => [104, "\x941"], "\x07" => [16, "\x941"], "\x08" => [94, "\x942"], "\t" => [76, "\x942"], "\n" => [104, "\x942"], "\v" => [16, "\x942"], "\f" => [94, "\x94a"], "\r" => [76, "\x94a"], "\x0e" => [104, "\x94a"], "\x0f" => [16, "\x94a"], "\x10" => [94, "\x94c"], "\x11" => [76, "\x94c"], "\x12" => [104, "\x94c"], "\x13" => [16, "\x94c"], "\x14" => [94, "\x94e"], "\x15" => [76, "\x94e"], "\x16" => [104, "\x94e"], "\x17" => [16, "\x94e"], "\x18" => [94, "\x94i"], "\x19" => [76, "\x94i"], "\x1a" => [104, "\x94i"], "\x1b" => [16, "\x94i"], "\x1c" => [94, "\x94o"], "\x1d" => [76, "\x94o"], "\x1e" => [104, "\x94o"], "\x1f" => [16, "\x94o"], " " => [94, "\x94s"], "!" => [76, "\x94s"], "\"" => [104, "\x94s"], "#" => [16, "\x94s"], "\$" => [94, "\x94t"], "%" => [76, "\x94t"], "&" => [104, "\x94t"], "'" => [16, "\x94t"], "(" => [77, "\x94 "], ")" => [18, "\x94 "], "*" => [77, "\x94%"], "+" => [18, "\x94%"], "," => [77, "\x94-"], "-" => [18, "\x94-"], "." => [77, "\x94."], "/" => [18, "\x94."], [77, "\x94/"], [18, "\x94/"], [77, "\x943"], [18, "\x943"], [77, "\x944"], [18, "\x944"], [77, "\x945"], [18, "\x945"], [77, "\x946"], [18, "\x946"], ":" => [77, "\x947"], ";" => [18, "\x947"], "<" => [77, "\x948"], "=" => [18, "\x948"], ">" => [77, "\x949"], "?" => [18, "\x949"], "@" => [77, "\x94="], "A" => [18, "\x94="], "B" => [77, "\x94A"], "C" => [18, "\x94A"], "D" => [77, "\x94_"], "E" => [18, "\x94_"], "F" => [77, "\x94b"], "G" => [18, "\x94b"], "H" => [77, "\x94d"], "I" => [18, "\x94d"], "J" => [77, "\x94f"], "K" => [18, "\x94f"], "L" => [77, "\x94g"], "M" => [18, "\x94g"], "N" => [77, "\x94h"], "O" => [18, "\x94h"], "P" => [77, "\x94l"], "Q" => [18, "\x94l"], "R" => [77, "\x94m"], "S" => [18, "\x94m"], "T" => [77, "\x94n"], "U" => [18, "\x94n"], "V" => [77, "\x94p"], "W" => [18, "\x94p"], "X" => [77, "\x94r"], "Y" => [18, "\x94r"], "Z" => [77, "\x94u"], "[" => [18, "\x94u"], "\\" => [0, "\x94:"], "]" => [0, "\x94B"], "^" => [0, "\x94C"], "_" => [0, "\x94D"], "`" => [0, "\x94E"], "a" => [0, "\x94F"], "b" => [0, "\x94G"], "c" => [0, "\x94H"], "d" => [0, "\x94I"], "e" => [0, "\x94J"], "f" => [0, "\x94K"], "g" => [0, "\x94L"], "h" => [0, "\x94M"], "i" => [0, "\x94N"], "j" => [0, "\x94O"], "k" => [0, "\x94P"], "l" => [0, "\x94Q"], "m" => [0, "\x94R"], "n" => [0, "\x94S"], "o" => [0, "\x94T"], "p" => [0, "\x94U"], "q" => [0, "\x94V"], "r" => [0, "\x94W"], "s" => [0, "\x94Y"], "t" => [0, "\x94j"], "u" => [0, "\x94k"], "v" => [0, "\x94q"], "w" => [0, "\x94v"], "x" => [0, "\x94w"], "y" => [0, "\x94x"], "z" => [0, "\x94y"], "{" => [0, "\x94z"], "|" => [82, "\x94"], "}" => [87, "\x94"], "~" => [130, "\x94"], "" => [9, "\x94"], "\x80" => [94, "\x9f0"], "\x81" => [76, "\x9f0"], "\x82" => [104, "\x9f0"], "\x83" => [16, "\x9f0"], "\x84" => [94, "\x9f1"], "\x85" => [76, "\x9f1"], "\x86" => [104, "\x9f1"], "\x87" => [16, "\x9f1"], "\x88" => [94, "\x9f2"], "\x89" => [76, "\x9f2"], "\x8a" => [104, "\x9f2"], "\x8b" => [16, "\x9f2"], "\x8c" => [94, "\x9fa"], "\x8d" => [76, "\x9fa"], "\x8e" => [104, "\x9fa"], "\x8f" => [16, "\x9fa"], "\x90" => [94, "\x9fc"], "\x91" => [76, "\x9fc"], "\x92" => [104, "\x9fc"], "\x93" => [16, "\x9fc"], "\x94" => [94, "\x9fe"], "\x95" => [76, "\x9fe"], "\x96" => [104, "\x9fe"], "\x97" => [16, "\x9fe"], "\x98" => [94, "\x9fi"], "\x99" => [76, "\x9fi"], "\x9a" => [104, "\x9fi"], "\x9b" => [16, "\x9fi"], "\x9c" => [94, "\x9fo"], "\x9d" => [76, "\x9fo"], "\x9e" => [104, "\x9fo"], "\x9f" => [16, "\x9fo"], "\xa0" => [94, "\x9fs"], "\xa1" => [76, "\x9fs"], "\xa2" => [104, "\x9fs"], "\xa3" => [16, "\x9fs"], "\xa4" => [94, "\x9ft"], "\xa5" => [76, "\x9ft"], "\xa6" => [104, "\x9ft"], "\xa7" => [16, "\x9ft"], "\xa8" => [77, "\x9f "], "\xa9" => [18, "\x9f "], "\xaa" => [77, "\x9f%"], "\xab" => [18, "\x9f%"], "\xac" => [77, "\x9f-"], "\xad" => [18, "\x9f-"], "\xae" => [77, "\x9f."], "\xaf" => [18, "\x9f."], "\xb0" => [77, "\x9f/"], "\xb1" => [18, "\x9f/"], "\xb2" => [77, "\x9f3"], "\xb3" => [18, "\x9f3"], "\xb4" => [77, "\x9f4"], "\xb5" => [18, "\x9f4"], "\xb6" => [77, "\x9f5"], "\xb7" => [18, "\x9f5"], "\xb8" => [77, "\x9f6"], "\xb9" => [18, "\x9f6"], "\xba" => [77, "\x9f7"], "\xbb" => [18, "\x9f7"], "\xbc" => [77, "\x9f8"], "\xbd" => [18, "\x9f8"], "\xbe" => [77, "\x9f9"], "\xbf" => [18, "\x9f9"], "\xc0" => [77, "\x9f="], "\xc1" => [18, "\x9f="], "\xc2" => [77, "\x9fA"], "\xc3" => [18, "\x9fA"], "\xc4" => [77, "\x9f_"], "\xc5" => [18, "\x9f_"], "\xc6" => [77, "\x9fb"], "\xc7" => [18, "\x9fb"], "\xc8" => [77, "\x9fd"], "\xc9" => [18, "\x9fd"], "\xca" => [77, "\x9ff"], "\xcb" => [18, "\x9ff"], "\xcc" => [77, "\x9fg"], "\xcd" => [18, "\x9fg"], "\xce" => [77, "\x9fh"], "\xcf" => [18, "\x9fh"], "\xd0" => [77, "\x9fl"], "\xd1" => [18, "\x9fl"], "\xd2" => [77, "\x9fm"], "\xd3" => [18, "\x9fm"], "\xd4" => [77, "\x9fn"], "\xd5" => [18, "\x9fn"], "\xd6" => [77, "\x9fp"], "\xd7" => [18, "\x9fp"], "\xd8" => [77, "\x9fr"], "\xd9" => [18, "\x9fr"], "\xda" => [77, "\x9fu"], "\xdb" => [18, "\x9fu"], "\xdc" => [0, "\x9f:"], "\xdd" => [0, "\x9fB"], "\xde" => [0, "\x9fC"], "\xdf" => [0, "\x9fD"], "\xe0" => [0, "\x9fE"], "\xe1" => [0, "\x9fF"], "\xe2" => [0, "\x9fG"], "\xe3" => [0, "\x9fH"], "\xe4" => [0, "\x9fI"], "\xe5" => [0, "\x9fJ"], "\xe6" => [0, "\x9fK"], "\xe7" => [0, "\x9fL"], "\xe8" => [0, "\x9fM"], "\xe9" => [0, "\x9fN"], "\xea" => [0, "\x9fO"], "\xeb" => [0, "\x9fP"], "\xec" => [0, "\x9fQ"], "\xed" => [0, "\x9fR"], "\xee" => [0, "\x9fS"], "\xef" => [0, "\x9fT"], "\xf0" => [0, "\x9fU"], "\xf1" => [0, "\x9fV"], "\xf2" => [0, "\x9fW"], "\xf3" => [0, "\x9fY"], "\xf4" => [0, "\x9fj"], "\xf5" => [0, "\x9fk"], "\xf6" => [0, "\x9fq"], "\xf7" => [0, "\x9fv"], "\xf8" => [0, "\x9fw"], "\xf9" => [0, "\x9fx"], "\xfa" => [0, "\x9fy"], "\xfb" => [0, "\x9fz"], "\xfc" => [82, "\x9f"], "\xfd" => [87, "\x9f"], "\xfe" => [130, "\x9f"], "\xff" => [9, "\x9f"]], ["\x00" => [94, "\x960"], "\x01" => [76, "\x960"], "\x02" => [104, "\x960"], "\x03" => [16, "\x960"], "\x04" => [94, "\x961"], "\x05" => [76, "\x961"], "\x06" => [104, "\x961"], "\x07" => [16, "\x961"], "\x08" => [94, "\x962"], "\t" => [76, "\x962"], "\n" => [104, "\x962"], "\v" => [16, "\x962"], "\f" => [94, "\x96a"], "\r" => [76, "\x96a"], "\x0e" => [104, "\x96a"], "\x0f" => [16, "\x96a"], "\x10" => [94, "\x96c"], "\x11" => [76, "\x96c"], "\x12" => [104, "\x96c"], "\x13" => [16, "\x96c"], "\x14" => [94, "\x96e"], "\x15" => [76, "\x96e"], "\x16" => [104, "\x96e"], "\x17" => [16, "\x96e"], "\x18" => [94, "\x96i"], "\x19" => [76, "\x96i"], "\x1a" => [104, "\x96i"], "\x1b" => [16, "\x96i"], "\x1c" => [94, "\x96o"], "\x1d" => [76, "\x96o"], "\x1e" => [104, "\x96o"], "\x1f" => [16, "\x96o"], " " => [94, "\x96s"], "!" => [76, "\x96s"], "\"" => [104, "\x96s"], "#" => [16, "\x96s"], "\$" => [94, "\x96t"], "%" => [76, "\x96t"], "&" => [104, "\x96t"], "'" => [16, "\x96t"], "(" => [77, "\x96 "], ")" => [18, "\x96 "], "*" => [77, "\x96%"], "+" => [18, "\x96%"], "," => [77, "\x96-"], "-" => [18, "\x96-"], "." => [77, "\x96."], "/" => [18, "\x96."], [77, "\x96/"], [18, "\x96/"], [77, "\x963"], [18, "\x963"], [77, "\x964"], [18, "\x964"], [77, "\x965"], [18, "\x965"], [77, "\x966"], [18, "\x966"], ":" => [77, "\x967"], ";" => [18, "\x967"], "<" => [77, "\x968"], "=" => [18, "\x968"], ">" => [77, "\x969"], "?" => [18, "\x969"], "@" => [77, "\x96="], "A" => [18, "\x96="], "B" => [77, "\x96A"], "C" => [18, "\x96A"], "D" => [77, "\x96_"], "E" => [18, "\x96_"], "F" => [77, "\x96b"], "G" => [18, "\x96b"], "H" => [77, "\x96d"], "I" => [18, "\x96d"], "J" => [77, "\x96f"], "K" => [18, "\x96f"], "L" => [77, "\x96g"], "M" => [18, "\x96g"], "N" => [77, "\x96h"], "O" => [18, "\x96h"], "P" => [77, "\x96l"], "Q" => [18, "\x96l"], "R" => [77, "\x96m"], "S" => [18, "\x96m"], "T" => [77, "\x96n"], "U" => [18, "\x96n"], "V" => [77, "\x96p"], "W" => [18, "\x96p"], "X" => [77, "\x96r"], "Y" => [18, "\x96r"], "Z" => [77, "\x96u"], "[" => [18, "\x96u"], "\\" => [0, "\x96:"], "]" => [0, "\x96B"], "^" => [0, "\x96C"], "_" => [0, "\x96D"], "`" => [0, "\x96E"], "a" => [0, "\x96F"], "b" => [0, "\x96G"], "c" => [0, "\x96H"], "d" => [0, "\x96I"], "e" => [0, "\x96J"], "f" => [0, "\x96K"], "g" => [0, "\x96L"], "h" => [0, "\x96M"], "i" => [0, "\x96N"], "j" => [0, "\x96O"], "k" => [0, "\x96P"], "l" => [0, "\x96Q"], "m" => [0, "\x96R"], "n" => [0, "\x96S"], "o" => [0, "\x96T"], "p" => [0, "\x96U"], "q" => [0, "\x96V"], "r" => [0, "\x96W"], "s" => [0, "\x96Y"], "t" => [0, "\x96j"], "u" => [0, "\x96k"], "v" => [0, "\x96q"], "w" => [0, "\x96v"], "x" => [0, "\x96w"], "y" => [0, "\x96x"], "z" => [0, "\x96y"], "{" => [0, "\x96z"], "|" => [82, "\x96"], "}" => [87, "\x96"], "~" => [130, "\x96"], "" => [9, "\x96"], "\x80" => [94, "\x970"], "\x81" => [76, "\x970"], "\x82" => [104, "\x970"], "\x83" => [16, "\x970"], "\x84" => [94, "\x971"], "\x85" => [76, "\x971"], "\x86" => [104, "\x971"], "\x87" => [16, "\x971"], "\x88" => [94, "\x972"], "\x89" => [76, "\x972"], "\x8a" => [104, "\x972"], "\x8b" => [16, "\x972"], "\x8c" => [94, "\x97a"], "\x8d" => [76, "\x97a"], "\x8e" => [104, "\x97a"], "\x8f" => [16, "\x97a"], "\x90" => [94, "\x97c"], "\x91" => [76, "\x97c"], "\x92" => [104, "\x97c"], "\x93" => [16, "\x97c"], "\x94" => [94, "\x97e"], "\x95" => [76, "\x97e"], "\x96" => [104, "\x97e"], "\x97" => [16, "\x97e"], "\x98" => [94, "\x97i"], "\x99" => [76, "\x97i"], "\x9a" => [104, "\x97i"], "\x9b" => [16, "\x97i"], "\x9c" => [94, "\x97o"], "\x9d" => [76, "\x97o"], "\x9e" => [104, "\x97o"], "\x9f" => [16, "\x97o"], "\xa0" => [94, "\x97s"], "\xa1" => [76, "\x97s"], "\xa2" => [104, "\x97s"], "\xa3" => [16, "\x97s"], "\xa4" => [94, "\x97t"], "\xa5" => [76, "\x97t"], "\xa6" => [104, "\x97t"], "\xa7" => [16, "\x97t"], "\xa8" => [77, "\x97 "], "\xa9" => [18, "\x97 "], "\xaa" => [77, "\x97%"], "\xab" => [18, "\x97%"], "\xac" => [77, "\x97-"], "\xad" => [18, "\x97-"], "\xae" => [77, "\x97."], "\xaf" => [18, "\x97."], "\xb0" => [77, "\x97/"], "\xb1" => [18, "\x97/"], "\xb2" => [77, "\x973"], "\xb3" => [18, "\x973"], "\xb4" => [77, "\x974"], "\xb5" => [18, "\x974"], "\xb6" => [77, "\x975"], "\xb7" => [18, "\x975"], "\xb8" => [77, "\x976"], "\xb9" => [18, "\x976"], "\xba" => [77, "\x977"], "\xbb" => [18, "\x977"], "\xbc" => [77, "\x978"], "\xbd" => [18, "\x978"], "\xbe" => [77, "\x979"], "\xbf" => [18, "\x979"], "\xc0" => [77, "\x97="], "\xc1" => [18, "\x97="], "\xc2" => [77, "\x97A"], "\xc3" => [18, "\x97A"], "\xc4" => [77, "\x97_"], "\xc5" => [18, "\x97_"], "\xc6" => [77, "\x97b"], "\xc7" => [18, "\x97b"], "\xc8" => [77, "\x97d"], "\xc9" => [18, "\x97d"], "\xca" => [77, "\x97f"], "\xcb" => [18, "\x97f"], "\xcc" => [77, "\x97g"], "\xcd" => [18, "\x97g"], "\xce" => [77, "\x97h"], "\xcf" => [18, "\x97h"], "\xd0" => [77, "\x97l"], "\xd1" => [18, "\x97l"], "\xd2" => [77, "\x97m"], "\xd3" => [18, "\x97m"], "\xd4" => [77, "\x97n"], "\xd5" => [18, "\x97n"], "\xd6" => [77, "\x97p"], "\xd7" => [18, "\x97p"], "\xd8" => [77, "\x97r"], "\xd9" => [18, "\x97r"], "\xda" => [77, "\x97u"], "\xdb" => [18, "\x97u"], "\xdc" => [0, "\x97:"], "\xdd" => [0, "\x97B"], "\xde" => [0, "\x97C"], "\xdf" => [0, "\x97D"], "\xe0" => [0, "\x97E"], "\xe1" => [0, "\x97F"], "\xe2" => [0, "\x97G"], "\xe3" => [0, "\x97H"], "\xe4" => [0, "\x97I"], "\xe5" => [0, "\x97J"], "\xe6" => [0, "\x97K"], "\xe7" => [0, "\x97L"], "\xe8" => [0, "\x97M"], "\xe9" => [0, "\x97N"], "\xea" => [0, "\x97O"], "\xeb" => [0, "\x97P"], "\xec" => [0, "\x97Q"], "\xed" => [0, "\x97R"], "\xee" => [0, "\x97S"], "\xef" => [0, "\x97T"], "\xf0" => [0, "\x97U"], "\xf1" => [0, "\x97V"], "\xf2" => [0, "\x97W"], "\xf3" => [0, "\x97Y"], "\xf4" => [0, "\x97j"], "\xf5" => [0, "\x97k"], "\xf6" => [0, "\x97q"], "\xf7" => [0, "\x97v"], "\xf8" => [0, "\x97w"], "\xf9" => [0, "\x97x"], "\xfa" => [0, "\x97y"], "\xfb" => [0, "\x97z"], "\xfc" => [82, "\x97"], "\xfd" => [87, "\x97"], "\xfe" => [130, "\x97"], "\xff" => [9, "\x97"]], ["\x00" => [94, "\x980"], "\x01" => [76, "\x980"], "\x02" => [104, "\x980"], "\x03" => [16, "\x980"], "\x04" => [94, "\x981"], "\x05" => [76, "\x981"], "\x06" => [104, "\x981"], "\x07" => [16, "\x981"], "\x08" => [94, "\x982"], "\t" => [76, "\x982"], "\n" => [104, "\x982"], "\v" => [16, "\x982"], "\f" => [94, "\x98a"], "\r" => [76, "\x98a"], "\x0e" => [104, "\x98a"], "\x0f" => [16, "\x98a"], "\x10" => [94, "\x98c"], "\x11" => [76, "\x98c"], "\x12" => [104, "\x98c"], "\x13" => [16, "\x98c"], "\x14" => [94, "\x98e"], "\x15" => [76, "\x98e"], "\x16" => [104, "\x98e"], "\x17" => [16, "\x98e"], "\x18" => [94, "\x98i"], "\x19" => [76, "\x98i"], "\x1a" => [104, "\x98i"], "\x1b" => [16, "\x98i"], "\x1c" => [94, "\x98o"], "\x1d" => [76, "\x98o"], "\x1e" => [104, "\x98o"], "\x1f" => [16, "\x98o"], " " => [94, "\x98s"], "!" => [76, "\x98s"], "\"" => [104, "\x98s"], "#" => [16, "\x98s"], "\$" => [94, "\x98t"], "%" => [76, "\x98t"], "&" => [104, "\x98t"], "'" => [16, "\x98t"], "(" => [77, "\x98 "], ")" => [18, "\x98 "], "*" => [77, "\x98%"], "+" => [18, "\x98%"], "," => [77, "\x98-"], "-" => [18, "\x98-"], "." => [77, "\x98."], "/" => [18, "\x98."], [77, "\x98/"], [18, "\x98/"], [77, "\x983"], [18, "\x983"], [77, "\x984"], [18, "\x984"], [77, "\x985"], [18, "\x985"], [77, "\x986"], [18, "\x986"], ":" => [77, "\x987"], ";" => [18, "\x987"], "<" => [77, "\x988"], "=" => [18, "\x988"], ">" => [77, "\x989"], "?" => [18, "\x989"], "@" => [77, "\x98="], "A" => [18, "\x98="], "B" => [77, "\x98A"], "C" => [18, "\x98A"], "D" => [77, "\x98_"], "E" => [18, "\x98_"], "F" => [77, "\x98b"], "G" => [18, "\x98b"], "H" => [77, "\x98d"], "I" => [18, "\x98d"], "J" => [77, "\x98f"], "K" => [18, "\x98f"], "L" => [77, "\x98g"], "M" => [18, "\x98g"], "N" => [77, "\x98h"], "O" => [18, "\x98h"], "P" => [77, "\x98l"], "Q" => [18, "\x98l"], "R" => [77, "\x98m"], "S" => [18, "\x98m"], "T" => [77, "\x98n"], "U" => [18, "\x98n"], "V" => [77, "\x98p"], "W" => [18, "\x98p"], "X" => [77, "\x98r"], "Y" => [18, "\x98r"], "Z" => [77, "\x98u"], "[" => [18, "\x98u"], "\\" => [0, "\x98:"], "]" => [0, "\x98B"], "^" => [0, "\x98C"], "_" => [0, "\x98D"], "`" => [0, "\x98E"], "a" => [0, "\x98F"], "b" => [0, "\x98G"], "c" => [0, "\x98H"], "d" => [0, "\x98I"], "e" => [0, "\x98J"], "f" => [0, "\x98K"], "g" => [0, "\x98L"], "h" => [0, "\x98M"], "i" => [0, "\x98N"], "j" => [0, "\x98O"], "k" => [0, "\x98P"], "l" => [0, "\x98Q"], "m" => [0, "\x98R"], "n" => [0, "\x98S"], "o" => [0, "\x98T"], "p" => [0, "\x98U"], "q" => [0, "\x98V"], "r" => [0, "\x98W"], "s" => [0, "\x98Y"], "t" => [0, "\x98j"], "u" => [0, "\x98k"], "v" => [0, "\x98q"], "w" => [0, "\x98v"], "x" => [0, "\x98w"], "y" => [0, "\x98x"], "z" => [0, "\x98y"], "{" => [0, "\x98z"], "|" => [82, "\x98"], "}" => [87, "\x98"], "~" => [130, "\x98"], "" => [9, "\x98"], "\x80" => [94, "\x9b0"], "\x81" => [76, "\x9b0"], "\x82" => [104, "\x9b0"], "\x83" => [16, "\x9b0"], "\x84" => [94, "\x9b1"], "\x85" => [76, "\x9b1"], "\x86" => [104, "\x9b1"], "\x87" => [16, "\x9b1"], "\x88" => [94, "\x9b2"], "\x89" => [76, "\x9b2"], "\x8a" => [104, "\x9b2"], "\x8b" => [16, "\x9b2"], "\x8c" => [94, "\x9ba"], "\x8d" => [76, "\x9ba"], "\x8e" => [104, "\x9ba"], "\x8f" => [16, "\x9ba"], "\x90" => [94, "\x9bc"], "\x91" => [76, "\x9bc"], "\x92" => [104, "\x9bc"], "\x93" => [16, "\x9bc"], "\x94" => [94, "\x9be"], "\x95" => [76, "\x9be"], "\x96" => [104, "\x9be"], "\x97" => [16, "\x9be"], "\x98" => [94, "\x9bi"], "\x99" => [76, "\x9bi"], "\x9a" => [104, "\x9bi"], "\x9b" => [16, "\x9bi"], "\x9c" => [94, "\x9bo"], "\x9d" => [76, "\x9bo"], "\x9e" => [104, "\x9bo"], "\x9f" => [16, "\x9bo"], "\xa0" => [94, "\x9bs"], "\xa1" => [76, "\x9bs"], "\xa2" => [104, "\x9bs"], "\xa3" => [16, "\x9bs"], "\xa4" => [94, "\x9bt"], "\xa5" => [76, "\x9bt"], "\xa6" => [104, "\x9bt"], "\xa7" => [16, "\x9bt"], "\xa8" => [77, "\x9b "], "\xa9" => [18, "\x9b "], "\xaa" => [77, "\x9b%"], "\xab" => [18, "\x9b%"], "\xac" => [77, "\x9b-"], "\xad" => [18, "\x9b-"], "\xae" => [77, "\x9b."], "\xaf" => [18, "\x9b."], "\xb0" => [77, "\x9b/"], "\xb1" => [18, "\x9b/"], "\xb2" => [77, "\x9b3"], "\xb3" => [18, "\x9b3"], "\xb4" => [77, "\x9b4"], "\xb5" => [18, "\x9b4"], "\xb6" => [77, "\x9b5"], "\xb7" => [18, "\x9b5"], "\xb8" => [77, "\x9b6"], "\xb9" => [18, "\x9b6"], "\xba" => [77, "\x9b7"], "\xbb" => [18, "\x9b7"], "\xbc" => [77, "\x9b8"], "\xbd" => [18, "\x9b8"], "\xbe" => [77, "\x9b9"], "\xbf" => [18, "\x9b9"], "\xc0" => [77, "\x9b="], "\xc1" => [18, "\x9b="], "\xc2" => [77, "\x9bA"], "\xc3" => [18, "\x9bA"], "\xc4" => [77, "\x9b_"], "\xc5" => [18, "\x9b_"], "\xc6" => [77, "\x9bb"], "\xc7" => [18, "\x9bb"], "\xc8" => [77, "\x9bd"], "\xc9" => [18, "\x9bd"], "\xca" => [77, "\x9bf"], "\xcb" => [18, "\x9bf"], "\xcc" => [77, "\x9bg"], "\xcd" => [18, "\x9bg"], "\xce" => [77, "\x9bh"], "\xcf" => [18, "\x9bh"], "\xd0" => [77, "\x9bl"], "\xd1" => [18, "\x9bl"], "\xd2" => [77, "\x9bm"], "\xd3" => [18, "\x9bm"], "\xd4" => [77, "\x9bn"], "\xd5" => [18, "\x9bn"], "\xd6" => [77, "\x9bp"], "\xd7" => [18, "\x9bp"], "\xd8" => [77, "\x9br"], "\xd9" => [18, "\x9br"], "\xda" => [77, "\x9bu"], "\xdb" => [18, "\x9bu"], "\xdc" => [0, "\x9b:"], "\xdd" => [0, "\x9bB"], "\xde" => [0, "\x9bC"], "\xdf" => [0, "\x9bD"], "\xe0" => [0, "\x9bE"], "\xe1" => [0, "\x9bF"], "\xe2" => [0, "\x9bG"], "\xe3" => [0, "\x9bH"], "\xe4" => [0, "\x9bI"], "\xe5" => [0, "\x9bJ"], "\xe6" => [0, "\x9bK"], "\xe7" => [0, "\x9bL"], "\xe8" => [0, "\x9bM"], "\xe9" => [0, "\x9bN"], "\xea" => [0, "\x9bO"], "\xeb" => [0, "\x9bP"], "\xec" => [0, "\x9bQ"], "\xed" => [0, "\x9bR"], "\xee" => [0, "\x9bS"], "\xef" => [0, "\x9bT"], "\xf0" => [0, "\x9bU"], "\xf1" => [0, "\x9bV"], "\xf2" => [0, "\x9bW"], "\xf3" => [0, "\x9bY"], "\xf4" => [0, "\x9bj"], "\xf5" => [0, "\x9bk"], "\xf6" => [0, "\x9bq"], "\xf7" => [0, "\x9bv"], "\xf8" => [0, "\x9bw"], "\xf9" => [0, "\x9bx"], "\xfa" => [0, "\x9by"], "\xfb" => [0, "\x9bz"], "\xfc" => [82, "\x9b"], "\xfd" => [87, "\x9b"], "\xfe" => [130, "\x9b"], "\xff" => [9, "\x9b"]], ["\x00" => [77, "\x980"], "\x01" => [18, "\x980"], "\x02" => [77, "\x981"], "\x03" => [18, "\x981"], "\x04" => [77, "\x982"], "\x05" => [18, "\x982"], "\x06" => [77, "\x98a"], "\x07" => [18, "\x98a"], "\x08" => [77, "\x98c"], "\t" => [18, "\x98c"], "\n" => [77, "\x98e"], "\v" => [18, "\x98e"], "\f" => [77, "\x98i"], "\r" => [18, "\x98i"], "\x0e" => [77, "\x98o"], "\x0f" => [18, "\x98o"], "\x10" => [77, "\x98s"], "\x11" => [18, "\x98s"], "\x12" => [77, "\x98t"], "\x13" => [18, "\x98t"], "\x14" => [0, "\x98 "], "\x15" => [0, "\x98%"], "\x16" => [0, "\x98-"], "\x17" => [0, "\x98."], "\x18" => [0, "\x98/"], "\x19" => [0, "\x983"], "\x1a" => [0, "\x984"], "\x1b" => [0, "\x985"], "\x1c" => [0, "\x986"], "\x1d" => [0, "\x987"], "\x1e" => [0, "\x988"], "\x1f" => [0, "\x989"], " " => [0, "\x98="], "!" => [0, "\x98A"], "\"" => [0, "\x98_"], "#" => [0, "\x98b"], "\$" => [0, "\x98d"], "%" => [0, "\x98f"], "&" => [0, "\x98g"], "'" => [0, "\x98h"], "(" => [0, "\x98l"], ")" => [0, "\x98m"], "*" => [0, "\x98n"], "+" => [0, "\x98p"], "," => [0, "\x98r"], "-" => [0, "\x98u"], "." => [100, "\x98"], "/" => [110, "\x98"], [111, "\x98"], [115, "\x98"], [116, "\x98"], [118, "\x98"], [119, "\x98"], [122, "\x98"], [123, "\x98"], [125, "\x98"], [126, "\x98"], [129, "\x98"], ":" => [143, "\x98"], ";" => [148, "\x98"], "<" => [151, "\x98"], "=" => [153, "\x98"], ">" => [83, "\x98"], "?" => [10, "\x98"], "@" => [77, "\x9b0"], "A" => [18, "\x9b0"], "B" => [77, "\x9b1"], "C" => [18, "\x9b1"], "D" => [77, "\x9b2"], "E" => [18, "\x9b2"], "F" => [77, "\x9ba"], "G" => [18, "\x9ba"], "H" => [77, "\x9bc"], "I" => [18, "\x9bc"], "J" => [77, "\x9be"], "K" => [18, "\x9be"], "L" => [77, "\x9bi"], "M" => [18, "\x9bi"], "N" => [77, "\x9bo"], "O" => [18, "\x9bo"], "P" => [77, "\x9bs"], "Q" => [18, "\x9bs"], "R" => [77, "\x9bt"], "S" => [18, "\x9bt"], "T" => [0, "\x9b "], "U" => [0, "\x9b%"], "V" => [0, "\x9b-"], "W" => [0, "\x9b."], "X" => [0, "\x9b/"], "Y" => [0, "\x9b3"], "Z" => [0, "\x9b4"], "[" => [0, "\x9b5"], "\\" => [0, "\x9b6"], "]" => [0, "\x9b7"], "^" => [0, "\x9b8"], "_" => [0, "\x9b9"], "`" => [0, "\x9b="], "a" => [0, "\x9bA"], "b" => [0, "\x9b_"], "c" => [0, "\x9bb"], "d" => [0, "\x9bd"], "e" => [0, "\x9bf"], "f" => [0, "\x9bg"], "g" => [0, "\x9bh"], "h" => [0, "\x9bl"], "i" => [0, "\x9bm"], "j" => [0, "\x9bn"], "k" => [0, "\x9bp"], "l" => [0, "\x9br"], "m" => [0, "\x9bu"], "n" => [100, "\x9b"], "o" => [110, "\x9b"], "p" => [111, "\x9b"], "q" => [115, "\x9b"], "r" => [116, "\x9b"], "s" => [118, "\x9b"], "t" => [119, "\x9b"], "u" => [122, "\x9b"], "v" => [123, "\x9b"], "w" => [125, "\x9b"], "x" => [126, "\x9b"], "y" => [129, "\x9b"], "z" => [143, "\x9b"], "{" => [148, "\x9b"], "|" => [151, "\x9b"], "}" => [153, "\x9b"], "~" => [83, "\x9b"], "" => [10, "\x9b"], "\x80" => [77, "\x9d0"], "\x81" => [18, "\x9d0"], "\x82" => [77, "\x9d1"], "\x83" => [18, "\x9d1"], "\x84" => [77, "\x9d2"], "\x85" => [18, "\x9d2"], "\x86" => [77, "\x9da"], "\x87" => [18, "\x9da"], "\x88" => [77, "\x9dc"], "\x89" => [18, "\x9dc"], "\x8a" => [77, "\x9de"], "\x8b" => [18, "\x9de"], "\x8c" => [77, "\x9di"], "\x8d" => [18, "\x9di"], "\x8e" => [77, "\x9do"], "\x8f" => [18, "\x9do"], "\x90" => [77, "\x9ds"], "\x91" => [18, "\x9ds"], "\x92" => [77, "\x9dt"], "\x93" => [18, "\x9dt"], "\x94" => [0, "\x9d "], "\x95" => [0, "\x9d%"], "\x96" => [0, "\x9d-"], "\x97" => [0, "\x9d."], "\x98" => [0, "\x9d/"], "\x99" => [0, "\x9d3"], "\x9a" => [0, "\x9d4"], "\x9b" => [0, "\x9d5"], "\x9c" => [0, "\x9d6"], "\x9d" => [0, "\x9d7"], "\x9e" => [0, "\x9d8"], "\x9f" => [0, "\x9d9"], "\xa0" => [0, "\x9d="], "\xa1" => [0, "\x9dA"], "\xa2" => [0, "\x9d_"], "\xa3" => [0, "\x9db"], "\xa4" => [0, "\x9dd"], "\xa5" => [0, "\x9df"], "\xa6" => [0, "\x9dg"], "\xa7" => [0, "\x9dh"], "\xa8" => [0, "\x9dl"], "\xa9" => [0, "\x9dm"], "\xaa" => [0, "\x9dn"], "\xab" => [0, "\x9dp"], "\xac" => [0, "\x9dr"], "\xad" => [0, "\x9du"], "\xae" => [100, "\x9d"], "\xaf" => [110, "\x9d"], "\xb0" => [111, "\x9d"], "\xb1" => [115, "\x9d"], "\xb2" => [116, "\x9d"], "\xb3" => [118, "\x9d"], "\xb4" => [119, "\x9d"], "\xb5" => [122, "\x9d"], "\xb6" => [123, "\x9d"], "\xb7" => [125, "\x9d"], "\xb8" => [126, "\x9d"], "\xb9" => [129, "\x9d"], "\xba" => [143, "\x9d"], "\xbb" => [148, "\x9d"], "\xbc" => [151, "\x9d"], "\xbd" => [153, "\x9d"], "\xbe" => [83, "\x9d"], "\xbf" => [10, "\x9d"], "\xc0" => [77, "\x9e0"], "\xc1" => [18, "\x9e0"], "\xc2" => [77, "\x9e1"], "\xc3" => [18, "\x9e1"], "\xc4" => [77, "\x9e2"], "\xc5" => [18, "\x9e2"], "\xc6" => [77, "\x9ea"], "\xc7" => [18, "\x9ea"], "\xc8" => [77, "\x9ec"], "\xc9" => [18, "\x9ec"], "\xca" => [77, "\x9ee"], "\xcb" => [18, "\x9ee"], "\xcc" => [77, "\x9ei"], "\xcd" => [18, "\x9ei"], "\xce" => [77, "\x9eo"], "\xcf" => [18, "\x9eo"], "\xd0" => [77, "\x9es"], "\xd1" => [18, "\x9es"], "\xd2" => [77, "\x9et"], "\xd3" => [18, "\x9et"], "\xd4" => [0, "\x9e "], "\xd5" => [0, "\x9e%"], "\xd6" => [0, "\x9e-"], "\xd7" => [0, "\x9e."], "\xd8" => [0, "\x9e/"], "\xd9" => [0, "\x9e3"], "\xda" => [0, "\x9e4"], "\xdb" => [0, "\x9e5"], "\xdc" => [0, "\x9e6"], "\xdd" => [0, "\x9e7"], "\xde" => [0, "\x9e8"], "\xdf" => [0, "\x9e9"], "\xe0" => [0, "\x9e="], "\xe1" => [0, "\x9eA"], "\xe2" => [0, "\x9e_"], "\xe3" => [0, "\x9eb"], "\xe4" => [0, "\x9ed"], "\xe5" => [0, "\x9ef"], "\xe6" => [0, "\x9eg"], "\xe7" => [0, "\x9eh"], "\xe8" => [0, "\x9el"], "\xe9" => [0, "\x9em"], "\xea" => [0, "\x9en"], "\xeb" => [0, "\x9ep"], "\xec" => [0, "\x9er"], "\xed" => [0, "\x9eu"], "\xee" => [100, "\x9e"], "\xef" => [110, "\x9e"], "\xf0" => [111, "\x9e"], "\xf1" => [115, "\x9e"], "\xf2" => [116, "\x9e"], "\xf3" => [118, "\x9e"], "\xf4" => [119, "\x9e"], "\xf5" => [122, "\x9e"], "\xf6" => [123, "\x9e"], "\xf7" => [125, "\x9e"], "\xf8" => [126, "\x9e"], "\xf9" => [129, "\x9e"], "\xfa" => [143, "\x9e"], "\xfb" => [148, "\x9e"], "\xfc" => [151, "\x9e"], "\xfd" => [153, "\x9e"], "\xfe" => [83, "\x9e"], "\xff" => [10, "\x9e"]], ["\x00" => [94, "\x990"], "\x01" => [76, "\x990"], "\x02" => [104, "\x990"], "\x03" => [16, "\x990"], "\x04" => [94, "\x991"], "\x05" => [76, "\x991"], "\x06" => [104, "\x991"], "\x07" => [16, "\x991"], "\x08" => [94, "\x992"], "\t" => [76, "\x992"], "\n" => [104, "\x992"], "\v" => [16, "\x992"], "\f" => [94, "\x99a"], "\r" => [76, "\x99a"], "\x0e" => [104, "\x99a"], "\x0f" => [16, "\x99a"], "\x10" => [94, "\x99c"], "\x11" => [76, "\x99c"], "\x12" => [104, "\x99c"], "\x13" => [16, "\x99c"], "\x14" => [94, "\x99e"], "\x15" => [76, "\x99e"], "\x16" => [104, "\x99e"], "\x17" => [16, "\x99e"], "\x18" => [94, "\x99i"], "\x19" => [76, "\x99i"], "\x1a" => [104, "\x99i"], "\x1b" => [16, "\x99i"], "\x1c" => [94, "\x99o"], "\x1d" => [76, "\x99o"], "\x1e" => [104, "\x99o"], "\x1f" => [16, "\x99o"], " " => [94, "\x99s"], "!" => [76, "\x99s"], "\"" => [104, "\x99s"], "#" => [16, "\x99s"], "\$" => [94, "\x99t"], "%" => [76, "\x99t"], "&" => [104, "\x99t"], "'" => [16, "\x99t"], "(" => [77, "\x99 "], ")" => [18, "\x99 "], "*" => [77, "\x99%"], "+" => [18, "\x99%"], "," => [77, "\x99-"], "-" => [18, "\x99-"], "." => [77, "\x99."], "/" => [18, "\x99."], [77, "\x99/"], [18, "\x99/"], [77, "\x993"], [18, "\x993"], [77, "\x994"], [18, "\x994"], [77, "\x995"], [18, "\x995"], [77, "\x996"], [18, "\x996"], ":" => [77, "\x997"], ";" => [18, "\x997"], "<" => [77, "\x998"], "=" => [18, "\x998"], ">" => [77, "\x999"], "?" => [18, "\x999"], "@" => [77, "\x99="], "A" => [18, "\x99="], "B" => [77, "\x99A"], "C" => [18, "\x99A"], "D" => [77, "\x99_"], "E" => [18, "\x99_"], "F" => [77, "\x99b"], "G" => [18, "\x99b"], "H" => [77, "\x99d"], "I" => [18, "\x99d"], "J" => [77, "\x99f"], "K" => [18, "\x99f"], "L" => [77, "\x99g"], "M" => [18, "\x99g"], "N" => [77, "\x99h"], "O" => [18, "\x99h"], "P" => [77, "\x99l"], "Q" => [18, "\x99l"], "R" => [77, "\x99m"], "S" => [18, "\x99m"], "T" => [77, "\x99n"], "U" => [18, "\x99n"], "V" => [77, "\x99p"], "W" => [18, "\x99p"], "X" => [77, "\x99r"], "Y" => [18, "\x99r"], "Z" => [77, "\x99u"], "[" => [18, "\x99u"], "\\" => [0, "\x99:"], "]" => [0, "\x99B"], "^" => [0, "\x99C"], "_" => [0, "\x99D"], "`" => [0, "\x99E"], "a" => [0, "\x99F"], "b" => [0, "\x99G"], "c" => [0, "\x99H"], "d" => [0, "\x99I"], "e" => [0, "\x99J"], "f" => [0, "\x99K"], "g" => [0, "\x99L"], "h" => [0, "\x99M"], "i" => [0, "\x99N"], "j" => [0, "\x99O"], "k" => [0, "\x99P"], "l" => [0, "\x99Q"], "m" => [0, "\x99R"], "n" => [0, "\x99S"], "o" => [0, "\x99T"], "p" => [0, "\x99U"], "q" => [0, "\x99V"], "r" => [0, "\x99W"], "s" => [0, "\x99Y"], "t" => [0, "\x99j"], "u" => [0, "\x99k"], "v" => [0, "\x99q"], "w" => [0, "\x99v"], "x" => [0, "\x99w"], "y" => [0, "\x99x"], "z" => [0, "\x99y"], "{" => [0, "\x99z"], "|" => [82, "\x99"], "}" => [87, "\x99"], "~" => [130, "\x99"], "" => [9, "\x99"], "\x80" => [94, "\xa10"], "\x81" => [76, "\xa10"], "\x82" => [104, "\xa10"], "\x83" => [16, "\xa10"], "\x84" => [94, "\xa11"], "\x85" => [76, "\xa11"], "\x86" => [104, "\xa11"], "\x87" => [16, "\xa11"], "\x88" => [94, "\xa12"], "\x89" => [76, "\xa12"], "\x8a" => [104, "\xa12"], "\x8b" => [16, "\xa12"], "\x8c" => [94, "\xa1a"], "\x8d" => [76, "\xa1a"], "\x8e" => [104, "\xa1a"], "\x8f" => [16, "\xa1a"], "\x90" => [94, "\xa1c"], "\x91" => [76, "\xa1c"], "\x92" => [104, "\xa1c"], "\x93" => [16, "\xa1c"], "\x94" => [94, "\xa1e"], "\x95" => [76, "\xa1e"], "\x96" => [104, "\xa1e"], "\x97" => [16, "\xa1e"], "\x98" => [94, "\xa1i"], "\x99" => [76, "\xa1i"], "\x9a" => [104, "\xa1i"], "\x9b" => [16, "\xa1i"], "\x9c" => [94, "\xa1o"], "\x9d" => [76, "\xa1o"], "\x9e" => [104, "\xa1o"], "\x9f" => [16, "\xa1o"], "\xa0" => [94, "\xa1s"], "\xa1" => [76, "\xa1s"], "\xa2" => [104, "\xa1s"], "\xa3" => [16, "\xa1s"], "\xa4" => [94, "\xa1t"], "\xa5" => [76, "\xa1t"], "\xa6" => [104, "\xa1t"], "\xa7" => [16, "\xa1t"], "\xa8" => [77, "\xa1 "], "\xa9" => [18, "\xa1 "], "\xaa" => [77, "\xa1%"], "\xab" => [18, "\xa1%"], "\xac" => [77, "\xa1-"], "\xad" => [18, "\xa1-"], "\xae" => [77, "\xa1."], "\xaf" => [18, "\xa1."], "\xb0" => [77, "\xa1/"], "\xb1" => [18, "\xa1/"], "\xb2" => [77, "\xa13"], "\xb3" => [18, "\xa13"], "\xb4" => [77, "\xa14"], "\xb5" => [18, "\xa14"], "\xb6" => [77, "\xa15"], "\xb7" => [18, "\xa15"], "\xb8" => [77, "\xa16"], "\xb9" => [18, "\xa16"], "\xba" => [77, "\xa17"], "\xbb" => [18, "\xa17"], "\xbc" => [77, "\xa18"], "\xbd" => [18, "\xa18"], "\xbe" => [77, "\xa19"], "\xbf" => [18, "\xa19"], "\xc0" => [77, "\xa1="], "\xc1" => [18, "\xa1="], "\xc2" => [77, "\xa1A"], "\xc3" => [18, "\xa1A"], "\xc4" => [77, "\xa1_"], "\xc5" => [18, "\xa1_"], "\xc6" => [77, "\xa1b"], "\xc7" => [18, "\xa1b"], "\xc8" => [77, "\xa1d"], "\xc9" => [18, "\xa1d"], "\xca" => [77, "\xa1f"], "\xcb" => [18, "\xa1f"], "\xcc" => [77, "\xa1g"], "\xcd" => [18, "\xa1g"], "\xce" => [77, "\xa1h"], "\xcf" => [18, "\xa1h"], "\xd0" => [77, "\xa1l"], "\xd1" => [18, "\xa1l"], "\xd2" => [77, "\xa1m"], "\xd3" => [18, "\xa1m"], "\xd4" => [77, "\xa1n"], "\xd5" => [18, "\xa1n"], "\xd6" => [77, "\xa1p"], "\xd7" => [18, "\xa1p"], "\xd8" => [77, "\xa1r"], "\xd9" => [18, "\xa1r"], "\xda" => [77, "\xa1u"], "\xdb" => [18, "\xa1u"], "\xdc" => [0, "\xa1:"], "\xdd" => [0, "\xa1B"], "\xde" => [0, "\xa1C"], "\xdf" => [0, "\xa1D"], "\xe0" => [0, "\xa1E"], "\xe1" => [0, "\xa1F"], "\xe2" => [0, "\xa1G"], "\xe3" => [0, "\xa1H"], "\xe4" => [0, "\xa1I"], "\xe5" => [0, "\xa1J"], "\xe6" => [0, "\xa1K"], "\xe7" => [0, "\xa1L"], "\xe8" => [0, "\xa1M"], "\xe9" => [0, "\xa1N"], "\xea" => [0, "\xa1O"], "\xeb" => [0, "\xa1P"], "\xec" => [0, "\xa1Q"], "\xed" => [0, "\xa1R"], "\xee" => [0, "\xa1S"], "\xef" => [0, "\xa1T"], "\xf0" => [0, "\xa1U"], "\xf1" => [0, "\xa1V"], "\xf2" => [0, "\xa1W"], "\xf3" => [0, "\xa1Y"], "\xf4" => [0, "\xa1j"], "\xf5" => [0, "\xa1k"], "\xf6" => [0, "\xa1q"], "\xf7" => [0, "\xa1v"], "\xf8" => [0, "\xa1w"], "\xf9" => [0, "\xa1x"], "\xfa" => [0, "\xa1y"], "\xfb" => [0, "\xa1z"], "\xfc" => [82, "\xa1"], "\xfd" => [87, "\xa1"], "\xfe" => [130, "\xa1"], "\xff" => [9, "\xa1"]], ["\x00" => [77, "\x990"], "\x01" => [18, "\x990"], "\x02" => [77, "\x991"], "\x03" => [18, "\x991"], "\x04" => [77, "\x992"], "\x05" => [18, "\x992"], "\x06" => [77, "\x99a"], "\x07" => [18, "\x99a"], "\x08" => [77, "\x99c"], "\t" => [18, "\x99c"], "\n" => [77, "\x99e"], "\v" => [18, "\x99e"], "\f" => [77, "\x99i"], "\r" => [18, "\x99i"], "\x0e" => [77, "\x99o"], "\x0f" => [18, "\x99o"], "\x10" => [77, "\x99s"], "\x11" => [18, "\x99s"], "\x12" => [77, "\x99t"], "\x13" => [18, "\x99t"], "\x14" => [0, "\x99 "], "\x15" => [0, "\x99%"], "\x16" => [0, "\x99-"], "\x17" => [0, "\x99."], "\x18" => [0, "\x99/"], "\x19" => [0, "\x993"], "\x1a" => [0, "\x994"], "\x1b" => [0, "\x995"], "\x1c" => [0, "\x996"], "\x1d" => [0, "\x997"], "\x1e" => [0, "\x998"], "\x1f" => [0, "\x999"], " " => [0, "\x99="], "!" => [0, "\x99A"], "\"" => [0, "\x99_"], "#" => [0, "\x99b"], "\$" => [0, "\x99d"], "%" => [0, "\x99f"], "&" => [0, "\x99g"], "'" => [0, "\x99h"], "(" => [0, "\x99l"], ")" => [0, "\x99m"], "*" => [0, "\x99n"], "+" => [0, "\x99p"], "," => [0, "\x99r"], "-" => [0, "\x99u"], "." => [100, "\x99"], "/" => [110, "\x99"], [111, "\x99"], [115, "\x99"], [116, "\x99"], [118, "\x99"], [119, "\x99"], [122, "\x99"], [123, "\x99"], [125, "\x99"], [126, "\x99"], [129, "\x99"], ":" => [143, "\x99"], ";" => [148, "\x99"], "<" => [151, "\x99"], "=" => [153, "\x99"], ">" => [83, "\x99"], "?" => [10, "\x99"], "@" => [77, "\xa10"], "A" => [18, "\xa10"], "B" => [77, "\xa11"], "C" => [18, "\xa11"], "D" => [77, "\xa12"], "E" => [18, "\xa12"], "F" => [77, "\xa1a"], "G" => [18, "\xa1a"], "H" => [77, "\xa1c"], "I" => [18, "\xa1c"], "J" => [77, "\xa1e"], "K" => [18, "\xa1e"], "L" => [77, "\xa1i"], "M" => [18, "\xa1i"], "N" => [77, "\xa1o"], "O" => [18, "\xa1o"], "P" => [77, "\xa1s"], "Q" => [18, "\xa1s"], "R" => [77, "\xa1t"], "S" => [18, "\xa1t"], "T" => [0, "\xa1 "], "U" => [0, "\xa1%"], "V" => [0, "\xa1-"], "W" => [0, "\xa1."], "X" => [0, "\xa1/"], "Y" => [0, "\xa13"], "Z" => [0, "\xa14"], "[" => [0, "\xa15"], "\\" => [0, "\xa16"], "]" => [0, "\xa17"], "^" => [0, "\xa18"], "_" => [0, "\xa19"], "`" => [0, "\xa1="], "a" => [0, "\xa1A"], "b" => [0, "\xa1_"], "c" => [0, "\xa1b"], "d" => [0, "\xa1d"], "e" => [0, "\xa1f"], "f" => [0, "\xa1g"], "g" => [0, "\xa1h"], "h" => [0, "\xa1l"], "i" => [0, "\xa1m"], "j" => [0, "\xa1n"], "k" => [0, "\xa1p"], "l" => [0, "\xa1r"], "m" => [0, "\xa1u"], "n" => [100, "\xa1"], "o" => [110, "\xa1"], "p" => [111, "\xa1"], "q" => [115, "\xa1"], "r" => [116, "\xa1"], "s" => [118, "\xa1"], "t" => [119, "\xa1"], "u" => [122, "\xa1"], "v" => [123, "\xa1"], "w" => [125, "\xa1"], "x" => [126, "\xa1"], "y" => [129, "\xa1"], "z" => [143, "\xa1"], "{" => [148, "\xa1"], "|" => [151, "\xa1"], "}" => [153, "\xa1"], "~" => [83, "\xa1"], "" => [10, "\xa1"], "\x80" => [77, "\xa70"], "\x81" => [18, "\xa70"], "\x82" => [77, "\xa71"], "\x83" => [18, "\xa71"], "\x84" => [77, "\xa72"], "\x85" => [18, "\xa72"], "\x86" => [77, "\xa7a"], "\x87" => [18, "\xa7a"], "\x88" => [77, "\xa7c"], "\x89" => [18, "\xa7c"], "\x8a" => [77, "\xa7e"], "\x8b" => [18, "\xa7e"], "\x8c" => [77, "\xa7i"], "\x8d" => [18, "\xa7i"], "\x8e" => [77, "\xa7o"], "\x8f" => [18, "\xa7o"], "\x90" => [77, "\xa7s"], "\x91" => [18, "\xa7s"], "\x92" => [77, "\xa7t"], "\x93" => [18, "\xa7t"], "\x94" => [0, "\xa7 "], "\x95" => [0, "\xa7%"], "\x96" => [0, "\xa7-"], "\x97" => [0, "\xa7."], "\x98" => [0, "\xa7/"], "\x99" => [0, "\xa73"], "\x9a" => [0, "\xa74"], "\x9b" => [0, "\xa75"], "\x9c" => [0, "\xa76"], "\x9d" => [0, "\xa77"], "\x9e" => [0, "\xa78"], "\x9f" => [0, "\xa79"], "\xa0" => [0, "\xa7="], "\xa1" => [0, "\xa7A"], "\xa2" => [0, "\xa7_"], "\xa3" => [0, "\xa7b"], "\xa4" => [0, "\xa7d"], "\xa5" => [0, "\xa7f"], "\xa6" => [0, "\xa7g"], "\xa7" => [0, "\xa7h"], "\xa8" => [0, "\xa7l"], "\xa9" => [0, "\xa7m"], "\xaa" => [0, "\xa7n"], "\xab" => [0, "\xa7p"], "\xac" => [0, "\xa7r"], "\xad" => [0, "\xa7u"], "\xae" => [100, "\xa7"], "\xaf" => [110, "\xa7"], "\xb0" => [111, "\xa7"], "\xb1" => [115, "\xa7"], "\xb2" => [116, "\xa7"], "\xb3" => [118, "\xa7"], "\xb4" => [119, "\xa7"], "\xb5" => [122, "\xa7"], "\xb6" => [123, "\xa7"], "\xb7" => [125, "\xa7"], "\xb8" => [126, "\xa7"], "\xb9" => [129, "\xa7"], "\xba" => [143, "\xa7"], "\xbb" => [148, "\xa7"], "\xbc" => [151, "\xa7"], "\xbd" => [153, "\xa7"], "\xbe" => [83, "\xa7"], "\xbf" => [10, "\xa7"], "\xc0" => [77, "\xac0"], "\xc1" => [18, "\xac0"], "\xc2" => [77, "\xac1"], "\xc3" => [18, "\xac1"], "\xc4" => [77, "\xac2"], "\xc5" => [18, "\xac2"], "\xc6" => [77, "\xaca"], "\xc7" => [18, "\xaca"], "\xc8" => [77, "\xacc"], "\xc9" => [18, "\xacc"], "\xca" => [77, "\xace"], "\xcb" => [18, "\xace"], "\xcc" => [77, "\xaci"], "\xcd" => [18, "\xaci"], "\xce" => [77, "\xaco"], "\xcf" => [18, "\xaco"], "\xd0" => [77, "\xacs"], "\xd1" => [18, "\xacs"], "\xd2" => [77, "\xact"], "\xd3" => [18, "\xact"], "\xd4" => [0, "\xac "], "\xd5" => [0, "\xac%"], "\xd6" => [0, "\xac-"], "\xd7" => [0, "\xac."], "\xd8" => [0, "\xac/"], "\xd9" => [0, "\xac3"], "\xda" => [0, "\xac4"], "\xdb" => [0, "\xac5"], "\xdc" => [0, "\xac6"], "\xdd" => [0, "\xac7"], "\xde" => [0, "\xac8"], "\xdf" => [0, "\xac9"], "\xe0" => [0, "\xac="], "\xe1" => [0, "\xacA"], "\xe2" => [0, "\xac_"], "\xe3" => [0, "\xacb"], "\xe4" => [0, "\xacd"], "\xe5" => [0, "\xacf"], "\xe6" => [0, "\xacg"], "\xe7" => [0, "\xach"], "\xe8" => [0, "\xacl"], "\xe9" => [0, "\xacm"], "\xea" => [0, "\xacn"], "\xeb" => [0, "\xacp"], "\xec" => [0, "\xacr"], "\xed" => [0, "\xacu"], "\xee" => [100, "\xac"], "\xef" => [110, "\xac"], "\xf0" => [111, "\xac"], "\xf1" => [115, "\xac"], "\xf2" => [116, "\xac"], "\xf3" => [118, "\xac"], "\xf4" => [119, "\xac"], "\xf5" => [122, "\xac"], "\xf6" => [123, "\xac"], "\xf7" => [125, "\xac"], "\xf8" => [126, "\xac"], "\xf9" => [129, "\xac"], "\xfa" => [143, "\xac"], "\xfb" => [148, "\xac"], "\xfc" => [151, "\xac"], "\xfd" => [153, "\xac"], "\xfe" => [83, "\xac"], "\xff" => [10, "\xac"]], ["\x00" => [77, "\xe00"], "\x01" => [18, "\xe00"], "\x02" => [77, "\xe01"], "\x03" => [18, "\xe01"], "\x04" => [77, "\xe02"], "\x05" => [18, "\xe02"], "\x06" => [77, "\xe0a"], "\x07" => [18, "\xe0a"], "\x08" => [77, "\xe0c"], "\t" => [18, "\xe0c"], "\n" => [77, "\xe0e"], "\v" => [18, "\xe0e"], "\f" => [77, "\xe0i"], "\r" => [18, "\xe0i"], "\x0e" => [77, "\xe0o"], "\x0f" => [18, "\xe0o"], "\x10" => [77, "\xe0s"], "\x11" => [18, "\xe0s"], "\x12" => [77, "\xe0t"], "\x13" => [18, "\xe0t"], "\x14" => [0, "\xe0 "], "\x15" => [0, "\xe0%"], "\x16" => [0, "\xe0-"], "\x17" => [0, "\xe0."], "\x18" => [0, "\xe0/"], "\x19" => [0, "\xe03"], "\x1a" => [0, "\xe04"], "\x1b" => [0, "\xe05"], "\x1c" => [0, "\xe06"], "\x1d" => [0, "\xe07"], "\x1e" => [0, "\xe08"], "\x1f" => [0, "\xe09"], " " => [0, "\xe0="], "!" => [0, "\xe0A"], "\"" => [0, "\xe0_"], "#" => [0, "\xe0b"], "\$" => [0, "\xe0d"], "%" => [0, "\xe0f"], "&" => [0, "\xe0g"], "'" => [0, "\xe0h"], "(" => [0, "\xe0l"], ")" => [0, "\xe0m"], "*" => [0, "\xe0n"], "+" => [0, "\xe0p"], "," => [0, "\xe0r"], "-" => [0, "\xe0u"], "." => [100, "\xe0"], "/" => [110, "\xe0"], [111, "\xe0"], [115, "\xe0"], [116, "\xe0"], [118, "\xe0"], [119, "\xe0"], [122, "\xe0"], [123, "\xe0"], [125, "\xe0"], [126, "\xe0"], [129, "\xe0"], ":" => [143, "\xe0"], ";" => [148, "\xe0"], "<" => [151, "\xe0"], "=" => [153, "\xe0"], ">" => [83, "\xe0"], "?" => [10, "\xe0"], "@" => [77, "\xe20"], "A" => [18, "\xe20"], "B" => [77, "\xe21"], "C" => [18, "\xe21"], "D" => [77, "\xe22"], "E" => [18, "\xe22"], "F" => [77, "\xe2a"], "G" => [18, "\xe2a"], "H" => [77, "\xe2c"], "I" => [18, "\xe2c"], "J" => [77, "\xe2e"], "K" => [18, "\xe2e"], "L" => [77, "\xe2i"], "M" => [18, "\xe2i"], "N" => [77, "\xe2o"], "O" => [18, "\xe2o"], "P" => [77, "\xe2s"], "Q" => [18, "\xe2s"], "R" => [77, "\xe2t"], "S" => [18, "\xe2t"], "T" => [0, "\xe2 "], "U" => [0, "\xe2%"], "V" => [0, "\xe2-"], "W" => [0, "\xe2."], "X" => [0, "\xe2/"], "Y" => [0, "\xe23"], "Z" => [0, "\xe24"], "[" => [0, "\xe25"], "\\" => [0, "\xe26"], "]" => [0, "\xe27"], "^" => [0, "\xe28"], "_" => [0, "\xe29"], "`" => [0, "\xe2="], "a" => [0, "\xe2A"], "b" => [0, "\xe2_"], "c" => [0, "\xe2b"], "d" => [0, "\xe2d"], "e" => [0, "\xe2f"], "f" => [0, "\xe2g"], "g" => [0, "\xe2h"], "h" => [0, "\xe2l"], "i" => [0, "\xe2m"], "j" => [0, "\xe2n"], "k" => [0, "\xe2p"], "l" => [0, "\xe2r"], "m" => [0, "\xe2u"], "n" => [100, "\xe2"], "o" => [110, "\xe2"], "p" => [111, "\xe2"], "q" => [115, "\xe2"], "r" => [116, "\xe2"], "s" => [118, "\xe2"], "t" => [119, "\xe2"], "u" => [122, "\xe2"], "v" => [123, "\xe2"], "w" => [125, "\xe2"], "x" => [126, "\xe2"], "y" => [129, "\xe2"], "z" => [143, "\xe2"], "{" => [148, "\xe2"], "|" => [151, "\xe2"], "}" => [153, "\xe2"], "~" => [83, "\xe2"], "" => [10, "\xe2"], "\x80" => [0, "\x990"], "\x81" => [0, "\x991"], "\x82" => [0, "\x992"], "\x83" => [0, "\x99a"], "\x84" => [0, "\x99c"], "\x85" => [0, "\x99e"], "\x86" => [0, "\x99i"], "\x87" => [0, "\x99o"], "\x88" => [0, "\x99s"], "\x89" => [0, "\x99t"], "\x8a" => [73, "\x99"], "\x8b" => [88, "\x99"], "\x8c" => [89, "\x99"], "\x8d" => [96, "\x99"], "\x8e" => [97, "\x99"], "\x8f" => [99, "\x99"], "\x90" => [106, "\x99"], "\x91" => [136, "\x99"], "\x92" => [139, "\x99"], "\x93" => [141, "\x99"], "\x94" => [145, "\x99"], "\x95" => [147, "\x99"], "\x96" => [149, "\x99"], "\x97" => [101, "\x99"], "\x98" => [112, "\x99"], "\x99" => [117, "\x99"], "\x9a" => [120, "\x99"], "\x9b" => [124, "\x99"], "\x9c" => [127, "\x99"], "\x9d" => [144, "\x99"], "\x9e" => [152, "\x99"], "\x9f" => [11, "\x99"], "\xa0" => [0, "\xa10"], "\xa1" => [0, "\xa11"], "\xa2" => [0, "\xa12"], "\xa3" => [0, "\xa1a"], "\xa4" => [0, "\xa1c"], "\xa5" => [0, "\xa1e"], "\xa6" => [0, "\xa1i"], "\xa7" => [0, "\xa1o"], "\xa8" => [0, "\xa1s"], "\xa9" => [0, "\xa1t"], "\xaa" => [73, "\xa1"], "\xab" => [88, "\xa1"], "\xac" => [89, "\xa1"], "\xad" => [96, "\xa1"], "\xae" => [97, "\xa1"], "\xaf" => [99, "\xa1"], "\xb0" => [106, "\xa1"], "\xb1" => [136, "\xa1"], "\xb2" => [139, "\xa1"], "\xb3" => [141, "\xa1"], "\xb4" => [145, "\xa1"], "\xb5" => [147, "\xa1"], "\xb6" => [149, "\xa1"], "\xb7" => [101, "\xa1"], "\xb8" => [112, "\xa1"], "\xb9" => [117, "\xa1"], "\xba" => [120, "\xa1"], "\xbb" => [124, "\xa1"], "\xbc" => [127, "\xa1"], "\xbd" => [144, "\xa1"], "\xbe" => [152, "\xa1"], "\xbf" => [11, "\xa1"], "\xc0" => [0, "\xa70"], "\xc1" => [0, "\xa71"], "\xc2" => [0, "\xa72"], "\xc3" => [0, "\xa7a"], "\xc4" => [0, "\xa7c"], "\xc5" => [0, "\xa7e"], "\xc6" => [0, "\xa7i"], "\xc7" => [0, "\xa7o"], "\xc8" => [0, "\xa7s"], "\xc9" => [0, "\xa7t"], "\xca" => [73, "\xa7"], "\xcb" => [88, "\xa7"], "\xcc" => [89, "\xa7"], "\xcd" => [96, "\xa7"], "\xce" => [97, "\xa7"], "\xcf" => [99, "\xa7"], "\xd0" => [106, "\xa7"], "\xd1" => [136, "\xa7"], "\xd2" => [139, "\xa7"], "\xd3" => [141, "\xa7"], "\xd4" => [145, "\xa7"], "\xd5" => [147, "\xa7"], "\xd6" => [149, "\xa7"], "\xd7" => [101, "\xa7"], "\xd8" => [112, "\xa7"], "\xd9" => [117, "\xa7"], "\xda" => [120, "\xa7"], "\xdb" => [124, "\xa7"], "\xdc" => [127, "\xa7"], "\xdd" => [144, "\xa7"], "\xde" => [152, "\xa7"], "\xdf" => [11, "\xa7"], "\xe0" => [0, "\xac0"], "\xe1" => [0, "\xac1"], "\xe2" => [0, "\xac2"], "\xe3" => [0, "\xaca"], "\xe4" => [0, "\xacc"], "\xe5" => [0, "\xace"], "\xe6" => [0, "\xaci"], "\xe7" => [0, "\xaco"], "\xe8" => [0, "\xacs"], "\xe9" => [0, "\xact"], "\xea" => [73, "\xac"], "\xeb" => [88, "\xac"], "\xec" => [89, "\xac"], "\xed" => [96, "\xac"], "\xee" => [97, "\xac"], "\xef" => [99, "\xac"], "\xf0" => [106, "\xac"], "\xf1" => [136, "\xac"], "\xf2" => [139, "\xac"], "\xf3" => [141, "\xac"], "\xf4" => [145, "\xac"], "\xf5" => [147, "\xac"], "\xf6" => [149, "\xac"], "\xf7" => [101, "\xac"], "\xf8" => [112, "\xac"], "\xf9" => [117, "\xac"], "\xfa" => [120, "\xac"], "\xfb" => [124, "\xac"], "\xfc" => [127, "\xac"], "\xfd" => [144, "\xac"], "\xfe" => [152, "\xac"], "\xff" => [11, "\xac"]], ["\x00" => [94, "\x9a0"], "\x01" => [76, "\x9a0"], "\x02" => [104, "\x9a0"], "\x03" => [16, "\x9a0"], "\x04" => [94, "\x9a1"], "\x05" => [76, "\x9a1"], "\x06" => [104, "\x9a1"], "\x07" => [16, "\x9a1"], "\x08" => [94, "\x9a2"], "\t" => [76, "\x9a2"], "\n" => [104, "\x9a2"], "\v" => [16, "\x9a2"], "\f" => [94, "\x9aa"], "\r" => [76, "\x9aa"], "\x0e" => [104, "\x9aa"], "\x0f" => [16, "\x9aa"], "\x10" => [94, "\x9ac"], "\x11" => [76, "\x9ac"], "\x12" => [104, "\x9ac"], "\x13" => [16, "\x9ac"], "\x14" => [94, "\x9ae"], "\x15" => [76, "\x9ae"], "\x16" => [104, "\x9ae"], "\x17" => [16, "\x9ae"], "\x18" => [94, "\x9ai"], "\x19" => [76, "\x9ai"], "\x1a" => [104, "\x9ai"], "\x1b" => [16, "\x9ai"], "\x1c" => [94, "\x9ao"], "\x1d" => [76, "\x9ao"], "\x1e" => [104, "\x9ao"], "\x1f" => [16, "\x9ao"], " " => [94, "\x9as"], "!" => [76, "\x9as"], "\"" => [104, "\x9as"], "#" => [16, "\x9as"], "\$" => [94, "\x9at"], "%" => [76, "\x9at"], "&" => [104, "\x9at"], "'" => [16, "\x9at"], "(" => [77, "\x9a "], ")" => [18, "\x9a "], "*" => [77, "\x9a%"], "+" => [18, "\x9a%"], "," => [77, "\x9a-"], "-" => [18, "\x9a-"], "." => [77, "\x9a."], "/" => [18, "\x9a."], [77, "\x9a/"], [18, "\x9a/"], [77, "\x9a3"], [18, "\x9a3"], [77, "\x9a4"], [18, "\x9a4"], [77, "\x9a5"], [18, "\x9a5"], [77, "\x9a6"], [18, "\x9a6"], ":" => [77, "\x9a7"], ";" => [18, "\x9a7"], "<" => [77, "\x9a8"], "=" => [18, "\x9a8"], ">" => [77, "\x9a9"], "?" => [18, "\x9a9"], "@" => [77, "\x9a="], "A" => [18, "\x9a="], "B" => [77, "\x9aA"], "C" => [18, "\x9aA"], "D" => [77, "\x9a_"], "E" => [18, "\x9a_"], "F" => [77, "\x9ab"], "G" => [18, "\x9ab"], "H" => [77, "\x9ad"], "I" => [18, "\x9ad"], "J" => [77, "\x9af"], "K" => [18, "\x9af"], "L" => [77, "\x9ag"], "M" => [18, "\x9ag"], "N" => [77, "\x9ah"], "O" => [18, "\x9ah"], "P" => [77, "\x9al"], "Q" => [18, "\x9al"], "R" => [77, "\x9am"], "S" => [18, "\x9am"], "T" => [77, "\x9an"], "U" => [18, "\x9an"], "V" => [77, "\x9ap"], "W" => [18, "\x9ap"], "X" => [77, "\x9ar"], "Y" => [18, "\x9ar"], "Z" => [77, "\x9au"], "[" => [18, "\x9au"], "\\" => [0, "\x9a:"], "]" => [0, "\x9aB"], "^" => [0, "\x9aC"], "_" => [0, "\x9aD"], "`" => [0, "\x9aE"], "a" => [0, "\x9aF"], "b" => [0, "\x9aG"], "c" => [0, "\x9aH"], "d" => [0, "\x9aI"], "e" => [0, "\x9aJ"], "f" => [0, "\x9aK"], "g" => [0, "\x9aL"], "h" => [0, "\x9aM"], "i" => [0, "\x9aN"], "j" => [0, "\x9aO"], "k" => [0, "\x9aP"], "l" => [0, "\x9aQ"], "m" => [0, "\x9aR"], "n" => [0, "\x9aS"], "o" => [0, "\x9aT"], "p" => [0, "\x9aU"], "q" => [0, "\x9aV"], "r" => [0, "\x9aW"], "s" => [0, "\x9aY"], "t" => [0, "\x9aj"], "u" => [0, "\x9ak"], "v" => [0, "\x9aq"], "w" => [0, "\x9av"], "x" => [0, "\x9aw"], "y" => [0, "\x9ax"], "z" => [0, "\x9ay"], "{" => [0, "\x9az"], "|" => [82, "\x9a"], "}" => [87, "\x9a"], "~" => [130, "\x9a"], "" => [9, "\x9a"], "\x80" => [94, "\x9c0"], "\x81" => [76, "\x9c0"], "\x82" => [104, "\x9c0"], "\x83" => [16, "\x9c0"], "\x84" => [94, "\x9c1"], "\x85" => [76, "\x9c1"], "\x86" => [104, "\x9c1"], "\x87" => [16, "\x9c1"], "\x88" => [94, "\x9c2"], "\x89" => [76, "\x9c2"], "\x8a" => [104, "\x9c2"], "\x8b" => [16, "\x9c2"], "\x8c" => [94, "\x9ca"], "\x8d" => [76, "\x9ca"], "\x8e" => [104, "\x9ca"], "\x8f" => [16, "\x9ca"], "\x90" => [94, "\x9cc"], "\x91" => [76, "\x9cc"], "\x92" => [104, "\x9cc"], "\x93" => [16, "\x9cc"], "\x94" => [94, "\x9ce"], "\x95" => [76, "\x9ce"], "\x96" => [104, "\x9ce"], "\x97" => [16, "\x9ce"], "\x98" => [94, "\x9ci"], "\x99" => [76, "\x9ci"], "\x9a" => [104, "\x9ci"], "\x9b" => [16, "\x9ci"], "\x9c" => [94, "\x9co"], "\x9d" => [76, "\x9co"], "\x9e" => [104, "\x9co"], "\x9f" => [16, "\x9co"], "\xa0" => [94, "\x9cs"], "\xa1" => [76, "\x9cs"], "\xa2" => [104, "\x9cs"], "\xa3" => [16, "\x9cs"], "\xa4" => [94, "\x9ct"], "\xa5" => [76, "\x9ct"], "\xa6" => [104, "\x9ct"], "\xa7" => [16, "\x9ct"], "\xa8" => [77, "\x9c "], "\xa9" => [18, "\x9c "], "\xaa" => [77, "\x9c%"], "\xab" => [18, "\x9c%"], "\xac" => [77, "\x9c-"], "\xad" => [18, "\x9c-"], "\xae" => [77, "\x9c."], "\xaf" => [18, "\x9c."], "\xb0" => [77, "\x9c/"], "\xb1" => [18, "\x9c/"], "\xb2" => [77, "\x9c3"], "\xb3" => [18, "\x9c3"], "\xb4" => [77, "\x9c4"], "\xb5" => [18, "\x9c4"], "\xb6" => [77, "\x9c5"], "\xb7" => [18, "\x9c5"], "\xb8" => [77, "\x9c6"], "\xb9" => [18, "\x9c6"], "\xba" => [77, "\x9c7"], "\xbb" => [18, "\x9c7"], "\xbc" => [77, "\x9c8"], "\xbd" => [18, "\x9c8"], "\xbe" => [77, "\x9c9"], "\xbf" => [18, "\x9c9"], "\xc0" => [77, "\x9c="], "\xc1" => [18, "\x9c="], "\xc2" => [77, "\x9cA"], "\xc3" => [18, "\x9cA"], "\xc4" => [77, "\x9c_"], "\xc5" => [18, "\x9c_"], "\xc6" => [77, "\x9cb"], "\xc7" => [18, "\x9cb"], "\xc8" => [77, "\x9cd"], "\xc9" => [18, "\x9cd"], "\xca" => [77, "\x9cf"], "\xcb" => [18, "\x9cf"], "\xcc" => [77, "\x9cg"], "\xcd" => [18, "\x9cg"], "\xce" => [77, "\x9ch"], "\xcf" => [18, "\x9ch"], "\xd0" => [77, "\x9cl"], "\xd1" => [18, "\x9cl"], "\xd2" => [77, "\x9cm"], "\xd3" => [18, "\x9cm"], "\xd4" => [77, "\x9cn"], "\xd5" => [18, "\x9cn"], "\xd6" => [77, "\x9cp"], "\xd7" => [18, "\x9cp"], "\xd8" => [77, "\x9cr"], "\xd9" => [18, "\x9cr"], "\xda" => [77, "\x9cu"], "\xdb" => [18, "\x9cu"], "\xdc" => [0, "\x9c:"], "\xdd" => [0, "\x9cB"], "\xde" => [0, "\x9cC"], "\xdf" => [0, "\x9cD"], "\xe0" => [0, "\x9cE"], "\xe1" => [0, "\x9cF"], "\xe2" => [0, "\x9cG"], "\xe3" => [0, "\x9cH"], "\xe4" => [0, "\x9cI"], "\xe5" => [0, "\x9cJ"], "\xe6" => [0, "\x9cK"], "\xe7" => [0, "\x9cL"], "\xe8" => [0, "\x9cM"], "\xe9" => [0, "\x9cN"], "\xea" => [0, "\x9cO"], "\xeb" => [0, "\x9cP"], "\xec" => [0, "\x9cQ"], "\xed" => [0, "\x9cR"], "\xee" => [0, "\x9cS"], "\xef" => [0, "\x9cT"], "\xf0" => [0, "\x9cU"], "\xf1" => [0, "\x9cV"], "\xf2" => [0, "\x9cW"], "\xf3" => [0, "\x9cY"], "\xf4" => [0, "\x9cj"], "\xf5" => [0, "\x9ck"], "\xf6" => [0, "\x9cq"], "\xf7" => [0, "\x9cv"], "\xf8" => [0, "\x9cw"], "\xf9" => [0, "\x9cx"], "\xfa" => [0, "\x9cy"], "\xfb" => [0, "\x9cz"], "\xfc" => [82, "\x9c"], "\xfd" => [87, "\x9c"], "\xfe" => [130, "\x9c"], "\xff" => [9, "\x9c"]], ["\x00" => [77, "\x9a0"], "\x01" => [18, "\x9a0"], "\x02" => [77, "\x9a1"], "\x03" => [18, "\x9a1"], "\x04" => [77, "\x9a2"], "\x05" => [18, "\x9a2"], "\x06" => [77, "\x9aa"], "\x07" => [18, "\x9aa"], "\x08" => [77, "\x9ac"], "\t" => [18, "\x9ac"], "\n" => [77, "\x9ae"], "\v" => [18, "\x9ae"], "\f" => [77, "\x9ai"], "\r" => [18, "\x9ai"], "\x0e" => [77, "\x9ao"], "\x0f" => [18, "\x9ao"], "\x10" => [77, "\x9as"], "\x11" => [18, "\x9as"], "\x12" => [77, "\x9at"], "\x13" => [18, "\x9at"], "\x14" => [0, "\x9a "], "\x15" => [0, "\x9a%"], "\x16" => [0, "\x9a-"], "\x17" => [0, "\x9a."], "\x18" => [0, "\x9a/"], "\x19" => [0, "\x9a3"], "\x1a" => [0, "\x9a4"], "\x1b" => [0, "\x9a5"], "\x1c" => [0, "\x9a6"], "\x1d" => [0, "\x9a7"], "\x1e" => [0, "\x9a8"], "\x1f" => [0, "\x9a9"], " " => [0, "\x9a="], "!" => [0, "\x9aA"], "\"" => [0, "\x9a_"], "#" => [0, "\x9ab"], "\$" => [0, "\x9ad"], "%" => [0, "\x9af"], "&" => [0, "\x9ag"], "'" => [0, "\x9ah"], "(" => [0, "\x9al"], ")" => [0, "\x9am"], "*" => [0, "\x9an"], "+" => [0, "\x9ap"], "," => [0, "\x9ar"], "-" => [0, "\x9au"], "." => [100, "\x9a"], "/" => [110, "\x9a"], [111, "\x9a"], [115, "\x9a"], [116, "\x9a"], [118, "\x9a"], [119, "\x9a"], [122, "\x9a"], [123, "\x9a"], [125, "\x9a"], [126, "\x9a"], [129, "\x9a"], ":" => [143, "\x9a"], ";" => [148, "\x9a"], "<" => [151, "\x9a"], "=" => [153, "\x9a"], ">" => [83, "\x9a"], "?" => [10, "\x9a"], "@" => [77, "\x9c0"], "A" => [18, "\x9c0"], "B" => [77, "\x9c1"], "C" => [18, "\x9c1"], "D" => [77, "\x9c2"], "E" => [18, "\x9c2"], "F" => [77, "\x9ca"], "G" => [18, "\x9ca"], "H" => [77, "\x9cc"], "I" => [18, "\x9cc"], "J" => [77, "\x9ce"], "K" => [18, "\x9ce"], "L" => [77, "\x9ci"], "M" => [18, "\x9ci"], "N" => [77, "\x9co"], "O" => [18, "\x9co"], "P" => [77, "\x9cs"], "Q" => [18, "\x9cs"], "R" => [77, "\x9ct"], "S" => [18, "\x9ct"], "T" => [0, "\x9c "], "U" => [0, "\x9c%"], "V" => [0, "\x9c-"], "W" => [0, "\x9c."], "X" => [0, "\x9c/"], "Y" => [0, "\x9c3"], "Z" => [0, "\x9c4"], "[" => [0, "\x9c5"], "\\" => [0, "\x9c6"], "]" => [0, "\x9c7"], "^" => [0, "\x9c8"], "_" => [0, "\x9c9"], "`" => [0, "\x9c="], "a" => [0, "\x9cA"], "b" => [0, "\x9c_"], "c" => [0, "\x9cb"], "d" => [0, "\x9cd"], "e" => [0, "\x9cf"], "f" => [0, "\x9cg"], "g" => [0, "\x9ch"], "h" => [0, "\x9cl"], "i" => [0, "\x9cm"], "j" => [0, "\x9cn"], "k" => [0, "\x9cp"], "l" => [0, "\x9cr"], "m" => [0, "\x9cu"], "n" => [100, "\x9c"], "o" => [110, "\x9c"], "p" => [111, "\x9c"], "q" => [115, "\x9c"], "r" => [116, "\x9c"], "s" => [118, "\x9c"], "t" => [119, "\x9c"], "u" => [122, "\x9c"], "v" => [123, "\x9c"], "w" => [125, "\x9c"], "x" => [126, "\x9c"], "y" => [129, "\x9c"], "z" => [143, "\x9c"], "{" => [148, "\x9c"], "|" => [151, "\x9c"], "}" => [153, "\x9c"], "~" => [83, "\x9c"], "" => [10, "\x9c"], "\x80" => [77, "\xa00"], "\x81" => [18, "\xa00"], "\x82" => [77, "\xa01"], "\x83" => [18, "\xa01"], "\x84" => [77, "\xa02"], "\x85" => [18, "\xa02"], "\x86" => [77, "\xa0a"], "\x87" => [18, "\xa0a"], "\x88" => [77, "\xa0c"], "\x89" => [18, "\xa0c"], "\x8a" => [77, "\xa0e"], "\x8b" => [18, "\xa0e"], "\x8c" => [77, "\xa0i"], "\x8d" => [18, "\xa0i"], "\x8e" => [77, "\xa0o"], "\x8f" => [18, "\xa0o"], "\x90" => [77, "\xa0s"], "\x91" => [18, "\xa0s"], "\x92" => [77, "\xa0t"], "\x93" => [18, "\xa0t"], "\x94" => [0, "\xa0 "], "\x95" => [0, "\xa0%"], "\x96" => [0, "\xa0-"], "\x97" => [0, "\xa0."], "\x98" => [0, "\xa0/"], "\x99" => [0, "\xa03"], "\x9a" => [0, "\xa04"], "\x9b" => [0, "\xa05"], "\x9c" => [0, "\xa06"], "\x9d" => [0, "\xa07"], "\x9e" => [0, "\xa08"], "\x9f" => [0, "\xa09"], "\xa0" => [0, "\xa0="], "\xa1" => [0, "\xa0A"], "\xa2" => [0, "\xa0_"], "\xa3" => [0, "\xa0b"], "\xa4" => [0, "\xa0d"], "\xa5" => [0, "\xa0f"], "\xa6" => [0, "\xa0g"], "\xa7" => [0, "\xa0h"], "\xa8" => [0, "\xa0l"], "\xa9" => [0, "\xa0m"], "\xaa" => [0, "\xa0n"], "\xab" => [0, "\xa0p"], "\xac" => [0, "\xa0r"], "\xad" => [0, "\xa0u"], "\xae" => [100, "\xa0"], "\xaf" => [110, "\xa0"], "\xb0" => [111, "\xa0"], "\xb1" => [115, "\xa0"], "\xb2" => [116, "\xa0"], "\xb3" => [118, "\xa0"], "\xb4" => [119, "\xa0"], "\xb5" => [122, "\xa0"], "\xb6" => [123, "\xa0"], "\xb7" => [125, "\xa0"], "\xb8" => [126, "\xa0"], "\xb9" => [129, "\xa0"], "\xba" => [143, "\xa0"], "\xbb" => [148, "\xa0"], "\xbc" => [151, "\xa0"], "\xbd" => [153, "\xa0"], "\xbe" => [83, "\xa0"], "\xbf" => [10, "\xa0"], "\xc0" => [77, "\xa30"], "\xc1" => [18, "\xa30"], "\xc2" => [77, "\xa31"], "\xc3" => [18, "\xa31"], "\xc4" => [77, "\xa32"], "\xc5" => [18, "\xa32"], "\xc6" => [77, "\xa3a"], "\xc7" => [18, "\xa3a"], "\xc8" => [77, "\xa3c"], "\xc9" => [18, "\xa3c"], "\xca" => [77, "\xa3e"], "\xcb" => [18, "\xa3e"], "\xcc" => [77, "\xa3i"], "\xcd" => [18, "\xa3i"], "\xce" => [77, "\xa3o"], "\xcf" => [18, "\xa3o"], "\xd0" => [77, "\xa3s"], "\xd1" => [18, "\xa3s"], "\xd2" => [77, "\xa3t"], "\xd3" => [18, "\xa3t"], "\xd4" => [0, "\xa3 "], "\xd5" => [0, "\xa3%"], "\xd6" => [0, "\xa3-"], "\xd7" => [0, "\xa3."], "\xd8" => [0, "\xa3/"], "\xd9" => [0, "\xa33"], "\xda" => [0, "\xa34"], "\xdb" => [0, "\xa35"], "\xdc" => [0, "\xa36"], "\xdd" => [0, "\xa37"], "\xde" => [0, "\xa38"], "\xdf" => [0, "\xa39"], "\xe0" => [0, "\xa3="], "\xe1" => [0, "\xa3A"], "\xe2" => [0, "\xa3_"], "\xe3" => [0, "\xa3b"], "\xe4" => [0, "\xa3d"], "\xe5" => [0, "\xa3f"], "\xe6" => [0, "\xa3g"], "\xe7" => [0, "\xa3h"], "\xe8" => [0, "\xa3l"], "\xe9" => [0, "\xa3m"], "\xea" => [0, "\xa3n"], "\xeb" => [0, "\xa3p"], "\xec" => [0, "\xa3r"], "\xed" => [0, "\xa3u"], "\xee" => [100, "\xa3"], "\xef" => [110, "\xa3"], "\xf0" => [111, "\xa3"], "\xf1" => [115, "\xa3"], "\xf2" => [116, "\xa3"], "\xf3" => [118, "\xa3"], "\xf4" => [119, "\xa3"], "\xf5" => [122, "\xa3"], "\xf6" => [123, "\xa3"], "\xf7" => [125, "\xa3"], "\xf8" => [126, "\xa3"], "\xf9" => [129, "\xa3"], "\xfa" => [143, "\xa3"], "\xfb" => [148, "\xa3"], "\xfc" => [151, "\xa3"], "\xfd" => [153, "\xa3"], "\xfe" => [83, "\xa3"], "\xff" => [10, "\xa3"]], ["\x00" => [0, "\x9a0"], "\x01" => [0, "\x9a1"], "\x02" => [0, "\x9a2"], "\x03" => [0, "\x9aa"], "\x04" => [0, "\x9ac"], "\x05" => [0, "\x9ae"], "\x06" => [0, "\x9ai"], "\x07" => [0, "\x9ao"], "\x08" => [0, "\x9as"], "\t" => [0, "\x9at"], "\n" => [73, "\x9a"], "\v" => [88, "\x9a"], "\f" => [89, "\x9a"], "\r" => [96, "\x9a"], "\x0e" => [97, "\x9a"], "\x0f" => [99, "\x9a"], "\x10" => [106, "\x9a"], "\x11" => [136, "\x9a"], "\x12" => [139, "\x9a"], "\x13" => [141, "\x9a"], "\x14" => [145, "\x9a"], "\x15" => [147, "\x9a"], "\x16" => [149, "\x9a"], "\x17" => [101, "\x9a"], "\x18" => [112, "\x9a"], "\x19" => [117, "\x9a"], "\x1a" => [120, "\x9a"], "\x1b" => [124, "\x9a"], "\x1c" => [127, "\x9a"], "\x1d" => [144, "\x9a"], "\x1e" => [152, "\x9a"], "\x1f" => [11, "\x9a"], " " => [0, "\x9c0"], "!" => [0, "\x9c1"], "\"" => [0, "\x9c2"], "#" => [0, "\x9ca"], "\$" => [0, "\x9cc"], "%" => [0, "\x9ce"], "&" => [0, "\x9ci"], "'" => [0, "\x9co"], "(" => [0, "\x9cs"], ")" => [0, "\x9ct"], "*" => [73, "\x9c"], "+" => [88, "\x9c"], "," => [89, "\x9c"], "-" => [96, "\x9c"], "." => [97, "\x9c"], "/" => [99, "\x9c"], [106, "\x9c"], [136, "\x9c"], [139, "\x9c"], [141, "\x9c"], [145, "\x9c"], [147, "\x9c"], [149, "\x9c"], [101, "\x9c"], [112, "\x9c"], [117, "\x9c"], ":" => [120, "\x9c"], ";" => [124, "\x9c"], "<" => [127, "\x9c"], "=" => [144, "\x9c"], ">" => [152, "\x9c"], "?" => [11, "\x9c"], "@" => [0, "\xa00"], "A" => [0, "\xa01"], "B" => [0, "\xa02"], "C" => [0, "\xa0a"], "D" => [0, "\xa0c"], "E" => [0, "\xa0e"], "F" => [0, "\xa0i"], "G" => [0, "\xa0o"], "H" => [0, "\xa0s"], "I" => [0, "\xa0t"], "J" => [73, "\xa0"], "K" => [88, "\xa0"], "L" => [89, "\xa0"], "M" => [96, "\xa0"], "N" => [97, "\xa0"], "O" => [99, "\xa0"], "P" => [106, "\xa0"], "Q" => [136, "\xa0"], "R" => [139, "\xa0"], "S" => [141, "\xa0"], "T" => [145, "\xa0"], "U" => [147, "\xa0"], "V" => [149, "\xa0"], "W" => [101, "\xa0"], "X" => [112, "\xa0"], "Y" => [117, "\xa0"], "Z" => [120, "\xa0"], "[" => [124, "\xa0"], "\\" => [127, "\xa0"], "]" => [144, "\xa0"], "^" => [152, "\xa0"], "_" => [11, "\xa0"], "`" => [0, "\xa30"], "a" => [0, "\xa31"], "b" => [0, "\xa32"], "c" => [0, "\xa3a"], "d" => [0, "\xa3c"], "e" => [0, "\xa3e"], "f" => [0, "\xa3i"], "g" => [0, "\xa3o"], "h" => [0, "\xa3s"], "i" => [0, "\xa3t"], "j" => [73, "\xa3"], "k" => [88, "\xa3"], "l" => [89, "\xa3"], "m" => [96, "\xa3"], "n" => [97, "\xa3"], "o" => [99, "\xa3"], "p" => [106, "\xa3"], "q" => [136, "\xa3"], "r" => [139, "\xa3"], "s" => [141, "\xa3"], "t" => [145, "\xa3"], "u" => [147, "\xa3"], "v" => [149, "\xa3"], "w" => [101, "\xa3"], "x" => [112, "\xa3"], "y" => [117, "\xa3"], "z" => [120, "\xa3"], "{" => [124, "\xa3"], "|" => [127, "\xa3"], "}" => [144, "\xa3"], "~" => [152, "\xa3"], "" => [11, "\xa3"], "\x80" => [0, "\xa40"], "\x81" => [0, "\xa41"], "\x82" => [0, "\xa42"], "\x83" => [0, "\xa4a"], "\x84" => [0, "\xa4c"], "\x85" => [0, "\xa4e"], "\x86" => [0, "\xa4i"], "\x87" => [0, "\xa4o"], "\x88" => [0, "\xa4s"], "\x89" => [0, "\xa4t"], "\x8a" => [73, "\xa4"], "\x8b" => [88, "\xa4"], "\x8c" => [89, "\xa4"], "\x8d" => [96, "\xa4"], "\x8e" => [97, "\xa4"], "\x8f" => [99, "\xa4"], "\x90" => [106, "\xa4"], "\x91" => [136, "\xa4"], "\x92" => [139, "\xa4"], "\x93" => [141, "\xa4"], "\x94" => [145, "\xa4"], "\x95" => [147, "\xa4"], "\x96" => [149, "\xa4"], "\x97" => [101, "\xa4"], "\x98" => [112, "\xa4"], "\x99" => [117, "\xa4"], "\x9a" => [120, "\xa4"], "\x9b" => [124, "\xa4"], "\x9c" => [127, "\xa4"], "\x9d" => [144, "\xa4"], "\x9e" => [152, "\xa4"], "\x9f" => [11, "\xa4"], "\xa0" => [0, "\xa90"], "\xa1" => [0, "\xa91"], "\xa2" => [0, "\xa92"], "\xa3" => [0, "\xa9a"], "\xa4" => [0, "\xa9c"], "\xa5" => [0, "\xa9e"], "\xa6" => [0, "\xa9i"], "\xa7" => [0, "\xa9o"], "\xa8" => [0, "\xa9s"], "\xa9" => [0, "\xa9t"], "\xaa" => [73, "\xa9"], "\xab" => [88, "\xa9"], "\xac" => [89, "\xa9"], "\xad" => [96, "\xa9"], "\xae" => [97, "\xa9"], "\xaf" => [99, "\xa9"], "\xb0" => [106, "\xa9"], "\xb1" => [136, "\xa9"], "\xb2" => [139, "\xa9"], "\xb3" => [141, "\xa9"], "\xb4" => [145, "\xa9"], "\xb5" => [147, "\xa9"], "\xb6" => [149, "\xa9"], "\xb7" => [101, "\xa9"], "\xb8" => [112, "\xa9"], "\xb9" => [117, "\xa9"], "\xba" => [120, "\xa9"], "\xbb" => [124, "\xa9"], "\xbc" => [127, "\xa9"], "\xbd" => [144, "\xa9"], "\xbe" => [152, "\xa9"], "\xbf" => [11, "\xa9"], "\xc0" => [0, "\xaa0"], "\xc1" => [0, "\xaa1"], "\xc2" => [0, "\xaa2"], "\xc3" => [0, "\xaaa"], "\xc4" => [0, "\xaac"], "\xc5" => [0, "\xaae"], "\xc6" => [0, "\xaai"], "\xc7" => [0, "\xaao"], "\xc8" => [0, "\xaas"], "\xc9" => [0, "\xaat"], "\xca" => [73, "\xaa"], "\xcb" => [88, "\xaa"], "\xcc" => [89, "\xaa"], "\xcd" => [96, "\xaa"], "\xce" => [97, "\xaa"], "\xcf" => [99, "\xaa"], "\xd0" => [106, "\xaa"], "\xd1" => [136, "\xaa"], "\xd2" => [139, "\xaa"], "\xd3" => [141, "\xaa"], "\xd4" => [145, "\xaa"], "\xd5" => [147, "\xaa"], "\xd6" => [149, "\xaa"], "\xd7" => [101, "\xaa"], "\xd8" => [112, "\xaa"], "\xd9" => [117, "\xaa"], "\xda" => [120, "\xaa"], "\xdb" => [124, "\xaa"], "\xdc" => [127, "\xaa"], "\xdd" => [144, "\xaa"], "\xde" => [152, "\xaa"], "\xdf" => [11, "\xaa"], "\xe0" => [0, "\xad0"], "\xe1" => [0, "\xad1"], "\xe2" => [0, "\xad2"], "\xe3" => [0, "\xada"], "\xe4" => [0, "\xadc"], "\xe5" => [0, "\xade"], "\xe6" => [0, "\xadi"], "\xe7" => [0, "\xado"], "\xe8" => [0, "\xads"], "\xe9" => [0, "\xadt"], "\xea" => [73, "\xad"], "\xeb" => [88, "\xad"], "\xec" => [89, "\xad"], "\xed" => [96, "\xad"], "\xee" => [97, "\xad"], "\xef" => [99, "\xad"], "\xf0" => [106, "\xad"], "\xf1" => [136, "\xad"], "\xf2" => [139, "\xad"], "\xf3" => [141, "\xad"], "\xf4" => [145, "\xad"], "\xf5" => [147, "\xad"], "\xf6" => [149, "\xad"], "\xf7" => [101, "\xad"], "\xf8" => [112, "\xad"], "\xf9" => [117, "\xad"], "\xfa" => [120, "\xad"], "\xfb" => [124, "\xad"], "\xfc" => [127, "\xad"], "\xfd" => [144, "\xad"], "\xfe" => [152, "\xad"], "\xff" => [11, "\xad"]], ["\x00" => [94, "\x9d0"], "\x01" => [76, "\x9d0"], "\x02" => [104, "\x9d0"], "\x03" => [16, "\x9d0"], "\x04" => [94, "\x9d1"], "\x05" => [76, "\x9d1"], "\x06" => [104, "\x9d1"], "\x07" => [16, "\x9d1"], "\x08" => [94, "\x9d2"], "\t" => [76, "\x9d2"], "\n" => [104, "\x9d2"], "\v" => [16, "\x9d2"], "\f" => [94, "\x9da"], "\r" => [76, "\x9da"], "\x0e" => [104, "\x9da"], "\x0f" => [16, "\x9da"], "\x10" => [94, "\x9dc"], "\x11" => [76, "\x9dc"], "\x12" => [104, "\x9dc"], "\x13" => [16, "\x9dc"], "\x14" => [94, "\x9de"], "\x15" => [76, "\x9de"], "\x16" => [104, "\x9de"], "\x17" => [16, "\x9de"], "\x18" => [94, "\x9di"], "\x19" => [76, "\x9di"], "\x1a" => [104, "\x9di"], "\x1b" => [16, "\x9di"], "\x1c" => [94, "\x9do"], "\x1d" => [76, "\x9do"], "\x1e" => [104, "\x9do"], "\x1f" => [16, "\x9do"], " " => [94, "\x9ds"], "!" => [76, "\x9ds"], "\"" => [104, "\x9ds"], "#" => [16, "\x9ds"], "\$" => [94, "\x9dt"], "%" => [76, "\x9dt"], "&" => [104, "\x9dt"], "'" => [16, "\x9dt"], "(" => [77, "\x9d "], ")" => [18, "\x9d "], "*" => [77, "\x9d%"], "+" => [18, "\x9d%"], "," => [77, "\x9d-"], "-" => [18, "\x9d-"], "." => [77, "\x9d."], "/" => [18, "\x9d."], [77, "\x9d/"], [18, "\x9d/"], [77, "\x9d3"], [18, "\x9d3"], [77, "\x9d4"], [18, "\x9d4"], [77, "\x9d5"], [18, "\x9d5"], [77, "\x9d6"], [18, "\x9d6"], ":" => [77, "\x9d7"], ";" => [18, "\x9d7"], "<" => [77, "\x9d8"], "=" => [18, "\x9d8"], ">" => [77, "\x9d9"], "?" => [18, "\x9d9"], "@" => [77, "\x9d="], "A" => [18, "\x9d="], "B" => [77, "\x9dA"], "C" => [18, "\x9dA"], "D" => [77, "\x9d_"], "E" => [18, "\x9d_"], "F" => [77, "\x9db"], "G" => [18, "\x9db"], "H" => [77, "\x9dd"], "I" => [18, "\x9dd"], "J" => [77, "\x9df"], "K" => [18, "\x9df"], "L" => [77, "\x9dg"], "M" => [18, "\x9dg"], "N" => [77, "\x9dh"], "O" => [18, "\x9dh"], "P" => [77, "\x9dl"], "Q" => [18, "\x9dl"], "R" => [77, "\x9dm"], "S" => [18, "\x9dm"], "T" => [77, "\x9dn"], "U" => [18, "\x9dn"], "V" => [77, "\x9dp"], "W" => [18, "\x9dp"], "X" => [77, "\x9dr"], "Y" => [18, "\x9dr"], "Z" => [77, "\x9du"], "[" => [18, "\x9du"], "\\" => [0, "\x9d:"], "]" => [0, "\x9dB"], "^" => [0, "\x9dC"], "_" => [0, "\x9dD"], "`" => [0, "\x9dE"], "a" => [0, "\x9dF"], "b" => [0, "\x9dG"], "c" => [0, "\x9dH"], "d" => [0, "\x9dI"], "e" => [0, "\x9dJ"], "f" => [0, "\x9dK"], "g" => [0, "\x9dL"], "h" => [0, "\x9dM"], "i" => [0, "\x9dN"], "j" => [0, "\x9dO"], "k" => [0, "\x9dP"], "l" => [0, "\x9dQ"], "m" => [0, "\x9dR"], "n" => [0, "\x9dS"], "o" => [0, "\x9dT"], "p" => [0, "\x9dU"], "q" => [0, "\x9dV"], "r" => [0, "\x9dW"], "s" => [0, "\x9dY"], "t" => [0, "\x9dj"], "u" => [0, "\x9dk"], "v" => [0, "\x9dq"], "w" => [0, "\x9dv"], "x" => [0, "\x9dw"], "y" => [0, "\x9dx"], "z" => [0, "\x9dy"], "{" => [0, "\x9dz"], "|" => [82, "\x9d"], "}" => [87, "\x9d"], "~" => [130, "\x9d"], "" => [9, "\x9d"], "\x80" => [94, "\x9e0"], "\x81" => [76, "\x9e0"], "\x82" => [104, "\x9e0"], "\x83" => [16, "\x9e0"], "\x84" => [94, "\x9e1"], "\x85" => [76, "\x9e1"], "\x86" => [104, "\x9e1"], "\x87" => [16, "\x9e1"], "\x88" => [94, "\x9e2"], "\x89" => [76, "\x9e2"], "\x8a" => [104, "\x9e2"], "\x8b" => [16, "\x9e2"], "\x8c" => [94, "\x9ea"], "\x8d" => [76, "\x9ea"], "\x8e" => [104, "\x9ea"], "\x8f" => [16, "\x9ea"], "\x90" => [94, "\x9ec"], "\x91" => [76, "\x9ec"], "\x92" => [104, "\x9ec"], "\x93" => [16, "\x9ec"], "\x94" => [94, "\x9ee"], "\x95" => [76, "\x9ee"], "\x96" => [104, "\x9ee"], "\x97" => [16, "\x9ee"], "\x98" => [94, "\x9ei"], "\x99" => [76, "\x9ei"], "\x9a" => [104, "\x9ei"], "\x9b" => [16, "\x9ei"], "\x9c" => [94, "\x9eo"], "\x9d" => [76, "\x9eo"], "\x9e" => [104, "\x9eo"], "\x9f" => [16, "\x9eo"], "\xa0" => [94, "\x9es"], "\xa1" => [76, "\x9es"], "\xa2" => [104, "\x9es"], "\xa3" => [16, "\x9es"], "\xa4" => [94, "\x9et"], "\xa5" => [76, "\x9et"], "\xa6" => [104, "\x9et"], "\xa7" => [16, "\x9et"], "\xa8" => [77, "\x9e "], "\xa9" => [18, "\x9e "], "\xaa" => [77, "\x9e%"], "\xab" => [18, "\x9e%"], "\xac" => [77, "\x9e-"], "\xad" => [18, "\x9e-"], "\xae" => [77, "\x9e."], "\xaf" => [18, "\x9e."], "\xb0" => [77, "\x9e/"], "\xb1" => [18, "\x9e/"], "\xb2" => [77, "\x9e3"], "\xb3" => [18, "\x9e3"], "\xb4" => [77, "\x9e4"], "\xb5" => [18, "\x9e4"], "\xb6" => [77, "\x9e5"], "\xb7" => [18, "\x9e5"], "\xb8" => [77, "\x9e6"], "\xb9" => [18, "\x9e6"], "\xba" => [77, "\x9e7"], "\xbb" => [18, "\x9e7"], "\xbc" => [77, "\x9e8"], "\xbd" => [18, "\x9e8"], "\xbe" => [77, "\x9e9"], "\xbf" => [18, "\x9e9"], "\xc0" => [77, "\x9e="], "\xc1" => [18, "\x9e="], "\xc2" => [77, "\x9eA"], "\xc3" => [18, "\x9eA"], "\xc4" => [77, "\x9e_"], "\xc5" => [18, "\x9e_"], "\xc6" => [77, "\x9eb"], "\xc7" => [18, "\x9eb"], "\xc8" => [77, "\x9ed"], "\xc9" => [18, "\x9ed"], "\xca" => [77, "\x9ef"], "\xcb" => [18, "\x9ef"], "\xcc" => [77, "\x9eg"], "\xcd" => [18, "\x9eg"], "\xce" => [77, "\x9eh"], "\xcf" => [18, "\x9eh"], "\xd0" => [77, "\x9el"], "\xd1" => [18, "\x9el"], "\xd2" => [77, "\x9em"], "\xd3" => [18, "\x9em"], "\xd4" => [77, "\x9en"], "\xd5" => [18, "\x9en"], "\xd6" => [77, "\x9ep"], "\xd7" => [18, "\x9ep"], "\xd8" => [77, "\x9er"], "\xd9" => [18, "\x9er"], "\xda" => [77, "\x9eu"], "\xdb" => [18, "\x9eu"], "\xdc" => [0, "\x9e:"], "\xdd" => [0, "\x9eB"], "\xde" => [0, "\x9eC"], "\xdf" => [0, "\x9eD"], "\xe0" => [0, "\x9eE"], "\xe1" => [0, "\x9eF"], "\xe2" => [0, "\x9eG"], "\xe3" => [0, "\x9eH"], "\xe4" => [0, "\x9eI"], "\xe5" => [0, "\x9eJ"], "\xe6" => [0, "\x9eK"], "\xe7" => [0, "\x9eL"], "\xe8" => [0, "\x9eM"], "\xe9" => [0, "\x9eN"], "\xea" => [0, "\x9eO"], "\xeb" => [0, "\x9eP"], "\xec" => [0, "\x9eQ"], "\xed" => [0, "\x9eR"], "\xee" => [0, "\x9eS"], "\xef" => [0, "\x9eT"], "\xf0" => [0, "\x9eU"], "\xf1" => [0, "\x9eV"], "\xf2" => [0, "\x9eW"], "\xf3" => [0, "\x9eY"], "\xf4" => [0, "\x9ej"], "\xf5" => [0, "\x9ek"], "\xf6" => [0, "\x9eq"], "\xf7" => [0, "\x9ev"], "\xf8" => [0, "\x9ew"], "\xf9" => [0, "\x9ex"], "\xfa" => [0, "\x9ey"], "\xfb" => [0, "\x9ez"], "\xfc" => [82, "\x9e"], "\xfd" => [87, "\x9e"], "\xfe" => [130, "\x9e"], "\xff" => [9, "\x9e"]], ["\x00" => [94, "\xa00"], "\x01" => [76, "\xa00"], "\x02" => [104, "\xa00"], "\x03" => [16, "\xa00"], "\x04" => [94, "\xa01"], "\x05" => [76, "\xa01"], "\x06" => [104, "\xa01"], "\x07" => [16, "\xa01"], "\x08" => [94, "\xa02"], "\t" => [76, "\xa02"], "\n" => [104, "\xa02"], "\v" => [16, "\xa02"], "\f" => [94, "\xa0a"], "\r" => [76, "\xa0a"], "\x0e" => [104, "\xa0a"], "\x0f" => [16, "\xa0a"], "\x10" => [94, "\xa0c"], "\x11" => [76, "\xa0c"], "\x12" => [104, "\xa0c"], "\x13" => [16, "\xa0c"], "\x14" => [94, "\xa0e"], "\x15" => [76, "\xa0e"], "\x16" => [104, "\xa0e"], "\x17" => [16, "\xa0e"], "\x18" => [94, "\xa0i"], "\x19" => [76, "\xa0i"], "\x1a" => [104, "\xa0i"], "\x1b" => [16, "\xa0i"], "\x1c" => [94, "\xa0o"], "\x1d" => [76, "\xa0o"], "\x1e" => [104, "\xa0o"], "\x1f" => [16, "\xa0o"], " " => [94, "\xa0s"], "!" => [76, "\xa0s"], "\"" => [104, "\xa0s"], "#" => [16, "\xa0s"], "\$" => [94, "\xa0t"], "%" => [76, "\xa0t"], "&" => [104, "\xa0t"], "'" => [16, "\xa0t"], "(" => [77, "\xa0 "], ")" => [18, "\xa0 "], "*" => [77, "\xa0%"], "+" => [18, "\xa0%"], "," => [77, "\xa0-"], "-" => [18, "\xa0-"], "." => [77, "\xa0."], "/" => [18, "\xa0."], [77, "\xa0/"], [18, "\xa0/"], [77, "\xa03"], [18, "\xa03"], [77, "\xa04"], [18, "\xa04"], [77, "\xa05"], [18, "\xa05"], [77, "\xa06"], [18, "\xa06"], ":" => [77, "\xa07"], ";" => [18, "\xa07"], "<" => [77, "\xa08"], "=" => [18, "\xa08"], ">" => [77, "\xa09"], "?" => [18, "\xa09"], "@" => [77, "\xa0="], "A" => [18, "\xa0="], "B" => [77, "\xa0A"], "C" => [18, "\xa0A"], "D" => [77, "\xa0_"], "E" => [18, "\xa0_"], "F" => [77, "\xa0b"], "G" => [18, "\xa0b"], "H" => [77, "\xa0d"], "I" => [18, "\xa0d"], "J" => [77, "\xa0f"], "K" => [18, "\xa0f"], "L" => [77, "\xa0g"], "M" => [18, "\xa0g"], "N" => [77, "\xa0h"], "O" => [18, "\xa0h"], "P" => [77, "\xa0l"], "Q" => [18, "\xa0l"], "R" => [77, "\xa0m"], "S" => [18, "\xa0m"], "T" => [77, "\xa0n"], "U" => [18, "\xa0n"], "V" => [77, "\xa0p"], "W" => [18, "\xa0p"], "X" => [77, "\xa0r"], "Y" => [18, "\xa0r"], "Z" => [77, "\xa0u"], "[" => [18, "\xa0u"], "\\" => [0, "\xa0:"], "]" => [0, "\xa0B"], "^" => [0, "\xa0C"], "_" => [0, "\xa0D"], "`" => [0, "\xa0E"], "a" => [0, "\xa0F"], "b" => [0, "\xa0G"], "c" => [0, "\xa0H"], "d" => [0, "\xa0I"], "e" => [0, "\xa0J"], "f" => [0, "\xa0K"], "g" => [0, "\xa0L"], "h" => [0, "\xa0M"], "i" => [0, "\xa0N"], "j" => [0, "\xa0O"], "k" => [0, "\xa0P"], "l" => [0, "\xa0Q"], "m" => [0, "\xa0R"], "n" => [0, "\xa0S"], "o" => [0, "\xa0T"], "p" => [0, "\xa0U"], "q" => [0, "\xa0V"], "r" => [0, "\xa0W"], "s" => [0, "\xa0Y"], "t" => [0, "\xa0j"], "u" => [0, "\xa0k"], "v" => [0, "\xa0q"], "w" => [0, "\xa0v"], "x" => [0, "\xa0w"], "y" => [0, "\xa0x"], "z" => [0, "\xa0y"], "{" => [0, "\xa0z"], "|" => [82, "\xa0"], "}" => [87, "\xa0"], "~" => [130, "\xa0"], "" => [9, "\xa0"], "\x80" => [94, "\xa30"], "\x81" => [76, "\xa30"], "\x82" => [104, "\xa30"], "\x83" => [16, "\xa30"], "\x84" => [94, "\xa31"], "\x85" => [76, "\xa31"], "\x86" => [104, "\xa31"], "\x87" => [16, "\xa31"], "\x88" => [94, "\xa32"], "\x89" => [76, "\xa32"], "\x8a" => [104, "\xa32"], "\x8b" => [16, "\xa32"], "\x8c" => [94, "\xa3a"], "\x8d" => [76, "\xa3a"], "\x8e" => [104, "\xa3a"], "\x8f" => [16, "\xa3a"], "\x90" => [94, "\xa3c"], "\x91" => [76, "\xa3c"], "\x92" => [104, "\xa3c"], "\x93" => [16, "\xa3c"], "\x94" => [94, "\xa3e"], "\x95" => [76, "\xa3e"], "\x96" => [104, "\xa3e"], "\x97" => [16, "\xa3e"], "\x98" => [94, "\xa3i"], "\x99" => [76, "\xa3i"], "\x9a" => [104, "\xa3i"], "\x9b" => [16, "\xa3i"], "\x9c" => [94, "\xa3o"], "\x9d" => [76, "\xa3o"], "\x9e" => [104, "\xa3o"], "\x9f" => [16, "\xa3o"], "\xa0" => [94, "\xa3s"], "\xa1" => [76, "\xa3s"], "\xa2" => [104, "\xa3s"], "\xa3" => [16, "\xa3s"], "\xa4" => [94, "\xa3t"], "\xa5" => [76, "\xa3t"], "\xa6" => [104, "\xa3t"], "\xa7" => [16, "\xa3t"], "\xa8" => [77, "\xa3 "], "\xa9" => [18, "\xa3 "], "\xaa" => [77, "\xa3%"], "\xab" => [18, "\xa3%"], "\xac" => [77, "\xa3-"], "\xad" => [18, "\xa3-"], "\xae" => [77, "\xa3."], "\xaf" => [18, "\xa3."], "\xb0" => [77, "\xa3/"], "\xb1" => [18, "\xa3/"], "\xb2" => [77, "\xa33"], "\xb3" => [18, "\xa33"], "\xb4" => [77, "\xa34"], "\xb5" => [18, "\xa34"], "\xb6" => [77, "\xa35"], "\xb7" => [18, "\xa35"], "\xb8" => [77, "\xa36"], "\xb9" => [18, "\xa36"], "\xba" => [77, "\xa37"], "\xbb" => [18, "\xa37"], "\xbc" => [77, "\xa38"], "\xbd" => [18, "\xa38"], "\xbe" => [77, "\xa39"], "\xbf" => [18, "\xa39"], "\xc0" => [77, "\xa3="], "\xc1" => [18, "\xa3="], "\xc2" => [77, "\xa3A"], "\xc3" => [18, "\xa3A"], "\xc4" => [77, "\xa3_"], "\xc5" => [18, "\xa3_"], "\xc6" => [77, "\xa3b"], "\xc7" => [18, "\xa3b"], "\xc8" => [77, "\xa3d"], "\xc9" => [18, "\xa3d"], "\xca" => [77, "\xa3f"], "\xcb" => [18, "\xa3f"], "\xcc" => [77, "\xa3g"], "\xcd" => [18, "\xa3g"], "\xce" => [77, "\xa3h"], "\xcf" => [18, "\xa3h"], "\xd0" => [77, "\xa3l"], "\xd1" => [18, "\xa3l"], "\xd2" => [77, "\xa3m"], "\xd3" => [18, "\xa3m"], "\xd4" => [77, "\xa3n"], "\xd5" => [18, "\xa3n"], "\xd6" => [77, "\xa3p"], "\xd7" => [18, "\xa3p"], "\xd8" => [77, "\xa3r"], "\xd9" => [18, "\xa3r"], "\xda" => [77, "\xa3u"], "\xdb" => [18, "\xa3u"], "\xdc" => [0, "\xa3:"], "\xdd" => [0, "\xa3B"], "\xde" => [0, "\xa3C"], "\xdf" => [0, "\xa3D"], "\xe0" => [0, "\xa3E"], "\xe1" => [0, "\xa3F"], "\xe2" => [0, "\xa3G"], "\xe3" => [0, "\xa3H"], "\xe4" => [0, "\xa3I"], "\xe5" => [0, "\xa3J"], "\xe6" => [0, "\xa3K"], "\xe7" => [0, "\xa3L"], "\xe8" => [0, "\xa3M"], "\xe9" => [0, "\xa3N"], "\xea" => [0, "\xa3O"], "\xeb" => [0, "\xa3P"], "\xec" => [0, "\xa3Q"], "\xed" => [0, "\xa3R"], "\xee" => [0, "\xa3S"], "\xef" => [0, "\xa3T"], "\xf0" => [0, "\xa3U"], "\xf1" => [0, "\xa3V"], "\xf2" => [0, "\xa3W"], "\xf3" => [0, "\xa3Y"], "\xf4" => [0, "\xa3j"], "\xf5" => [0, "\xa3k"], "\xf6" => [0, "\xa3q"], "\xf7" => [0, "\xa3v"], "\xf8" => [0, "\xa3w"], "\xf9" => [0, "\xa3x"], "\xfa" => [0, "\xa3y"], "\xfb" => [0, "\xa3z"], "\xfc" => [82, "\xa3"], "\xfd" => [87, "\xa3"], "\xfe" => [130, "\xa3"], "\xff" => [9, "\xa3"]], ["\x00" => [94, "\xa40"], "\x01" => [76, "\xa40"], "\x02" => [104, "\xa40"], "\x03" => [16, "\xa40"], "\x04" => [94, "\xa41"], "\x05" => [76, "\xa41"], "\x06" => [104, "\xa41"], "\x07" => [16, "\xa41"], "\x08" => [94, "\xa42"], "\t" => [76, "\xa42"], "\n" => [104, "\xa42"], "\v" => [16, "\xa42"], "\f" => [94, "\xa4a"], "\r" => [76, "\xa4a"], "\x0e" => [104, "\xa4a"], "\x0f" => [16, "\xa4a"], "\x10" => [94, "\xa4c"], "\x11" => [76, "\xa4c"], "\x12" => [104, "\xa4c"], "\x13" => [16, "\xa4c"], "\x14" => [94, "\xa4e"], "\x15" => [76, "\xa4e"], "\x16" => [104, "\xa4e"], "\x17" => [16, "\xa4e"], "\x18" => [94, "\xa4i"], "\x19" => [76, "\xa4i"], "\x1a" => [104, "\xa4i"], "\x1b" => [16, "\xa4i"], "\x1c" => [94, "\xa4o"], "\x1d" => [76, "\xa4o"], "\x1e" => [104, "\xa4o"], "\x1f" => [16, "\xa4o"], " " => [94, "\xa4s"], "!" => [76, "\xa4s"], "\"" => [104, "\xa4s"], "#" => [16, "\xa4s"], "\$" => [94, "\xa4t"], "%" => [76, "\xa4t"], "&" => [104, "\xa4t"], "'" => [16, "\xa4t"], "(" => [77, "\xa4 "], ")" => [18, "\xa4 "], "*" => [77, "\xa4%"], "+" => [18, "\xa4%"], "," => [77, "\xa4-"], "-" => [18, "\xa4-"], "." => [77, "\xa4."], "/" => [18, "\xa4."], [77, "\xa4/"], [18, "\xa4/"], [77, "\xa43"], [18, "\xa43"], [77, "\xa44"], [18, "\xa44"], [77, "\xa45"], [18, "\xa45"], [77, "\xa46"], [18, "\xa46"], ":" => [77, "\xa47"], ";" => [18, "\xa47"], "<" => [77, "\xa48"], "=" => [18, "\xa48"], ">" => [77, "\xa49"], "?" => [18, "\xa49"], "@" => [77, "\xa4="], "A" => [18, "\xa4="], "B" => [77, "\xa4A"], "C" => [18, "\xa4A"], "D" => [77, "\xa4_"], "E" => [18, "\xa4_"], "F" => [77, "\xa4b"], "G" => [18, "\xa4b"], "H" => [77, "\xa4d"], "I" => [18, "\xa4d"], "J" => [77, "\xa4f"], "K" => [18, "\xa4f"], "L" => [77, "\xa4g"], "M" => [18, "\xa4g"], "N" => [77, "\xa4h"], "O" => [18, "\xa4h"], "P" => [77, "\xa4l"], "Q" => [18, "\xa4l"], "R" => [77, "\xa4m"], "S" => [18, "\xa4m"], "T" => [77, "\xa4n"], "U" => [18, "\xa4n"], "V" => [77, "\xa4p"], "W" => [18, "\xa4p"], "X" => [77, "\xa4r"], "Y" => [18, "\xa4r"], "Z" => [77, "\xa4u"], "[" => [18, "\xa4u"], "\\" => [0, "\xa4:"], "]" => [0, "\xa4B"], "^" => [0, "\xa4C"], "_" => [0, "\xa4D"], "`" => [0, "\xa4E"], "a" => [0, "\xa4F"], "b" => [0, "\xa4G"], "c" => [0, "\xa4H"], "d" => [0, "\xa4I"], "e" => [0, "\xa4J"], "f" => [0, "\xa4K"], "g" => [0, "\xa4L"], "h" => [0, "\xa4M"], "i" => [0, "\xa4N"], "j" => [0, "\xa4O"], "k" => [0, "\xa4P"], "l" => [0, "\xa4Q"], "m" => [0, "\xa4R"], "n" => [0, "\xa4S"], "o" => [0, "\xa4T"], "p" => [0, "\xa4U"], "q" => [0, "\xa4V"], "r" => [0, "\xa4W"], "s" => [0, "\xa4Y"], "t" => [0, "\xa4j"], "u" => [0, "\xa4k"], "v" => [0, "\xa4q"], "w" => [0, "\xa4v"], "x" => [0, "\xa4w"], "y" => [0, "\xa4x"], "z" => [0, "\xa4y"], "{" => [0, "\xa4z"], "|" => [82, "\xa4"], "}" => [87, "\xa4"], "~" => [130, "\xa4"], "" => [9, "\xa4"], "\x80" => [94, "\xa90"], "\x81" => [76, "\xa90"], "\x82" => [104, "\xa90"], "\x83" => [16, "\xa90"], "\x84" => [94, "\xa91"], "\x85" => [76, "\xa91"], "\x86" => [104, "\xa91"], "\x87" => [16, "\xa91"], "\x88" => [94, "\xa92"], "\x89" => [76, "\xa92"], "\x8a" => [104, "\xa92"], "\x8b" => [16, "\xa92"], "\x8c" => [94, "\xa9a"], "\x8d" => [76, "\xa9a"], "\x8e" => [104, "\xa9a"], "\x8f" => [16, "\xa9a"], "\x90" => [94, "\xa9c"], "\x91" => [76, "\xa9c"], "\x92" => [104, "\xa9c"], "\x93" => [16, "\xa9c"], "\x94" => [94, "\xa9e"], "\x95" => [76, "\xa9e"], "\x96" => [104, "\xa9e"], "\x97" => [16, "\xa9e"], "\x98" => [94, "\xa9i"], "\x99" => [76, "\xa9i"], "\x9a" => [104, "\xa9i"], "\x9b" => [16, "\xa9i"], "\x9c" => [94, "\xa9o"], "\x9d" => [76, "\xa9o"], "\x9e" => [104, "\xa9o"], "\x9f" => [16, "\xa9o"], "\xa0" => [94, "\xa9s"], "\xa1" => [76, "\xa9s"], "\xa2" => [104, "\xa9s"], "\xa3" => [16, "\xa9s"], "\xa4" => [94, "\xa9t"], "\xa5" => [76, "\xa9t"], "\xa6" => [104, "\xa9t"], "\xa7" => [16, "\xa9t"], "\xa8" => [77, "\xa9 "], "\xa9" => [18, "\xa9 "], "\xaa" => [77, "\xa9%"], "\xab" => [18, "\xa9%"], "\xac" => [77, "\xa9-"], "\xad" => [18, "\xa9-"], "\xae" => [77, "\xa9."], "\xaf" => [18, "\xa9."], "\xb0" => [77, "\xa9/"], "\xb1" => [18, "\xa9/"], "\xb2" => [77, "\xa93"], "\xb3" => [18, "\xa93"], "\xb4" => [77, "\xa94"], "\xb5" => [18, "\xa94"], "\xb6" => [77, "\xa95"], "\xb7" => [18, "\xa95"], "\xb8" => [77, "\xa96"], "\xb9" => [18, "\xa96"], "\xba" => [77, "\xa97"], "\xbb" => [18, "\xa97"], "\xbc" => [77, "\xa98"], "\xbd" => [18, "\xa98"], "\xbe" => [77, "\xa99"], "\xbf" => [18, "\xa99"], "\xc0" => [77, "\xa9="], "\xc1" => [18, "\xa9="], "\xc2" => [77, "\xa9A"], "\xc3" => [18, "\xa9A"], "\xc4" => [77, "\xa9_"], "\xc5" => [18, "\xa9_"], "\xc6" => [77, "\xa9b"], "\xc7" => [18, "\xa9b"], "\xc8" => [77, "\xa9d"], "\xc9" => [18, "\xa9d"], "\xca" => [77, "\xa9f"], "\xcb" => [18, "\xa9f"], "\xcc" => [77, "\xa9g"], "\xcd" => [18, "\xa9g"], "\xce" => [77, "\xa9h"], "\xcf" => [18, "\xa9h"], "\xd0" => [77, "\xa9l"], "\xd1" => [18, "\xa9l"], "\xd2" => [77, "\xa9m"], "\xd3" => [18, "\xa9m"], "\xd4" => [77, "\xa9n"], "\xd5" => [18, "\xa9n"], "\xd6" => [77, "\xa9p"], "\xd7" => [18, "\xa9p"], "\xd8" => [77, "\xa9r"], "\xd9" => [18, "\xa9r"], "\xda" => [77, "\xa9u"], "\xdb" => [18, "\xa9u"], "\xdc" => [0, "\xa9:"], "\xdd" => [0, "\xa9B"], "\xde" => [0, "\xa9C"], "\xdf" => [0, "\xa9D"], "\xe0" => [0, "\xa9E"], "\xe1" => [0, "\xa9F"], "\xe2" => [0, "\xa9G"], "\xe3" => [0, "\xa9H"], "\xe4" => [0, "\xa9I"], "\xe5" => [0, "\xa9J"], "\xe6" => [0, "\xa9K"], "\xe7" => [0, "\xa9L"], "\xe8" => [0, "\xa9M"], "\xe9" => [0, "\xa9N"], "\xea" => [0, "\xa9O"], "\xeb" => [0, "\xa9P"], "\xec" => [0, "\xa9Q"], "\xed" => [0, "\xa9R"], "\xee" => [0, "\xa9S"], "\xef" => [0, "\xa9T"], "\xf0" => [0, "\xa9U"], "\xf1" => [0, "\xa9V"], "\xf2" => [0, "\xa9W"], "\xf3" => [0, "\xa9Y"], "\xf4" => [0, "\xa9j"], "\xf5" => [0, "\xa9k"], "\xf6" => [0, "\xa9q"], "\xf7" => [0, "\xa9v"], "\xf8" => [0, "\xa9w"], "\xf9" => [0, "\xa9x"], "\xfa" => [0, "\xa9y"], "\xfb" => [0, "\xa9z"], "\xfc" => [82, "\xa9"], "\xfd" => [87, "\xa9"], "\xfe" => [130, "\xa9"], "\xff" => [9, "\xa9"]], ["\x00" => [77, "\xa40"], "\x01" => [18, "\xa40"], "\x02" => [77, "\xa41"], "\x03" => [18, "\xa41"], "\x04" => [77, "\xa42"], "\x05" => [18, "\xa42"], "\x06" => [77, "\xa4a"], "\x07" => [18, "\xa4a"], "\x08" => [77, "\xa4c"], "\t" => [18, "\xa4c"], "\n" => [77, "\xa4e"], "\v" => [18, "\xa4e"], "\f" => [77, "\xa4i"], "\r" => [18, "\xa4i"], "\x0e" => [77, "\xa4o"], "\x0f" => [18, "\xa4o"], "\x10" => [77, "\xa4s"], "\x11" => [18, "\xa4s"], "\x12" => [77, "\xa4t"], "\x13" => [18, "\xa4t"], "\x14" => [0, "\xa4 "], "\x15" => [0, "\xa4%"], "\x16" => [0, "\xa4-"], "\x17" => [0, "\xa4."], "\x18" => [0, "\xa4/"], "\x19" => [0, "\xa43"], "\x1a" => [0, "\xa44"], "\x1b" => [0, "\xa45"], "\x1c" => [0, "\xa46"], "\x1d" => [0, "\xa47"], "\x1e" => [0, "\xa48"], "\x1f" => [0, "\xa49"], " " => [0, "\xa4="], "!" => [0, "\xa4A"], "\"" => [0, "\xa4_"], "#" => [0, "\xa4b"], "\$" => [0, "\xa4d"], "%" => [0, "\xa4f"], "&" => [0, "\xa4g"], "'" => [0, "\xa4h"], "(" => [0, "\xa4l"], ")" => [0, "\xa4m"], "*" => [0, "\xa4n"], "+" => [0, "\xa4p"], "," => [0, "\xa4r"], "-" => [0, "\xa4u"], "." => [100, "\xa4"], "/" => [110, "\xa4"], [111, "\xa4"], [115, "\xa4"], [116, "\xa4"], [118, "\xa4"], [119, "\xa4"], [122, "\xa4"], [123, "\xa4"], [125, "\xa4"], [126, "\xa4"], [129, "\xa4"], ":" => [143, "\xa4"], ";" => [148, "\xa4"], "<" => [151, "\xa4"], "=" => [153, "\xa4"], ">" => [83, "\xa4"], "?" => [10, "\xa4"], "@" => [77, "\xa90"], "A" => [18, "\xa90"], "B" => [77, "\xa91"], "C" => [18, "\xa91"], "D" => [77, "\xa92"], "E" => [18, "\xa92"], "F" => [77, "\xa9a"], "G" => [18, "\xa9a"], "H" => [77, "\xa9c"], "I" => [18, "\xa9c"], "J" => [77, "\xa9e"], "K" => [18, "\xa9e"], "L" => [77, "\xa9i"], "M" => [18, "\xa9i"], "N" => [77, "\xa9o"], "O" => [18, "\xa9o"], "P" => [77, "\xa9s"], "Q" => [18, "\xa9s"], "R" => [77, "\xa9t"], "S" => [18, "\xa9t"], "T" => [0, "\xa9 "], "U" => [0, "\xa9%"], "V" => [0, "\xa9-"], "W" => [0, "\xa9."], "X" => [0, "\xa9/"], "Y" => [0, "\xa93"], "Z" => [0, "\xa94"], "[" => [0, "\xa95"], "\\" => [0, "\xa96"], "]" => [0, "\xa97"], "^" => [0, "\xa98"], "_" => [0, "\xa99"], "`" => [0, "\xa9="], "a" => [0, "\xa9A"], "b" => [0, "\xa9_"], "c" => [0, "\xa9b"], "d" => [0, "\xa9d"], "e" => [0, "\xa9f"], "f" => [0, "\xa9g"], "g" => [0, "\xa9h"], "h" => [0, "\xa9l"], "i" => [0, "\xa9m"], "j" => [0, "\xa9n"], "k" => [0, "\xa9p"], "l" => [0, "\xa9r"], "m" => [0, "\xa9u"], "n" => [100, "\xa9"], "o" => [110, "\xa9"], "p" => [111, "\xa9"], "q" => [115, "\xa9"], "r" => [116, "\xa9"], "s" => [118, "\xa9"], "t" => [119, "\xa9"], "u" => [122, "\xa9"], "v" => [123, "\xa9"], "w" => [125, "\xa9"], "x" => [126, "\xa9"], "y" => [129, "\xa9"], "z" => [143, "\xa9"], "{" => [148, "\xa9"], "|" => [151, "\xa9"], "}" => [153, "\xa9"], "~" => [83, "\xa9"], "" => [10, "\xa9"], "\x80" => [77, "\xaa0"], "\x81" => [18, "\xaa0"], "\x82" => [77, "\xaa1"], "\x83" => [18, "\xaa1"], "\x84" => [77, "\xaa2"], "\x85" => [18, "\xaa2"], "\x86" => [77, "\xaaa"], "\x87" => [18, "\xaaa"], "\x88" => [77, "\xaac"], "\x89" => [18, "\xaac"], "\x8a" => [77, "\xaae"], "\x8b" => [18, "\xaae"], "\x8c" => [77, "\xaai"], "\x8d" => [18, "\xaai"], "\x8e" => [77, "\xaao"], "\x8f" => [18, "\xaao"], "\x90" => [77, "\xaas"], "\x91" => [18, "\xaas"], "\x92" => [77, "\xaat"], "\x93" => [18, "\xaat"], "\x94" => [0, "\xaa "], "\x95" => [0, "\xaa%"], "\x96" => [0, "\xaa-"], "\x97" => [0, "\xaa."], "\x98" => [0, "\xaa/"], "\x99" => [0, "\xaa3"], "\x9a" => [0, "\xaa4"], "\x9b" => [0, "\xaa5"], "\x9c" => [0, "\xaa6"], "\x9d" => [0, "\xaa7"], "\x9e" => [0, "\xaa8"], "\x9f" => [0, "\xaa9"], "\xa0" => [0, "\xaa="], "\xa1" => [0, "\xaaA"], "\xa2" => [0, "\xaa_"], "\xa3" => [0, "\xaab"], "\xa4" => [0, "\xaad"], "\xa5" => [0, "\xaaf"], "\xa6" => [0, "\xaag"], "\xa7" => [0, "\xaah"], "\xa8" => [0, "\xaal"], "\xa9" => [0, "\xaam"], "\xaa" => [0, "\xaan"], "\xab" => [0, "\xaap"], "\xac" => [0, "\xaar"], "\xad" => [0, "\xaau"], "\xae" => [100, "\xaa"], "\xaf" => [110, "\xaa"], "\xb0" => [111, "\xaa"], "\xb1" => [115, "\xaa"], "\xb2" => [116, "\xaa"], "\xb3" => [118, "\xaa"], "\xb4" => [119, "\xaa"], "\xb5" => [122, "\xaa"], "\xb6" => [123, "\xaa"], "\xb7" => [125, "\xaa"], "\xb8" => [126, "\xaa"], "\xb9" => [129, "\xaa"], "\xba" => [143, "\xaa"], "\xbb" => [148, "\xaa"], "\xbc" => [151, "\xaa"], "\xbd" => [153, "\xaa"], "\xbe" => [83, "\xaa"], "\xbf" => [10, "\xaa"], "\xc0" => [77, "\xad0"], "\xc1" => [18, "\xad0"], "\xc2" => [77, "\xad1"], "\xc3" => [18, "\xad1"], "\xc4" => [77, "\xad2"], "\xc5" => [18, "\xad2"], "\xc6" => [77, "\xada"], "\xc7" => [18, "\xada"], "\xc8" => [77, "\xadc"], "\xc9" => [18, "\xadc"], "\xca" => [77, "\xade"], "\xcb" => [18, "\xade"], "\xcc" => [77, "\xadi"], "\xcd" => [18, "\xadi"], "\xce" => [77, "\xado"], "\xcf" => [18, "\xado"], "\xd0" => [77, "\xads"], "\xd1" => [18, "\xads"], "\xd2" => [77, "\xadt"], "\xd3" => [18, "\xadt"], "\xd4" => [0, "\xad "], "\xd5" => [0, "\xad%"], "\xd6" => [0, "\xad-"], "\xd7" => [0, "\xad."], "\xd8" => [0, "\xad/"], "\xd9" => [0, "\xad3"], "\xda" => [0, "\xad4"], "\xdb" => [0, "\xad5"], "\xdc" => [0, "\xad6"], "\xdd" => [0, "\xad7"], "\xde" => [0, "\xad8"], "\xdf" => [0, "\xad9"], "\xe0" => [0, "\xad="], "\xe1" => [0, "\xadA"], "\xe2" => [0, "\xad_"], "\xe3" => [0, "\xadb"], "\xe4" => [0, "\xadd"], "\xe5" => [0, "\xadf"], "\xe6" => [0, "\xadg"], "\xe7" => [0, "\xadh"], "\xe8" => [0, "\xadl"], "\xe9" => [0, "\xadm"], "\xea" => [0, "\xadn"], "\xeb" => [0, "\xadp"], "\xec" => [0, "\xadr"], "\xed" => [0, "\xadu"], "\xee" => [100, "\xad"], "\xef" => [110, "\xad"], "\xf0" => [111, "\xad"], "\xf1" => [115, "\xad"], "\xf2" => [116, "\xad"], "\xf3" => [118, "\xad"], "\xf4" => [119, "\xad"], "\xf5" => [122, "\xad"], "\xf6" => [123, "\xad"], "\xf7" => [125, "\xad"], "\xf8" => [126, "\xad"], "\xf9" => [129, "\xad"], "\xfa" => [143, "\xad"], "\xfb" => [148, "\xad"], "\xfc" => [151, "\xad"], "\xfd" => [153, "\xad"], "\xfe" => [83, "\xad"], "\xff" => [10, "\xad"]], ["\x00" => [94, "\xa50"], "\x01" => [76, "\xa50"], "\x02" => [104, "\xa50"], "\x03" => [16, "\xa50"], "\x04" => [94, "\xa51"], "\x05" => [76, "\xa51"], "\x06" => [104, "\xa51"], "\x07" => [16, "\xa51"], "\x08" => [94, "\xa52"], "\t" => [76, "\xa52"], "\n" => [104, "\xa52"], "\v" => [16, "\xa52"], "\f" => [94, "\xa5a"], "\r" => [76, "\xa5a"], "\x0e" => [104, "\xa5a"], "\x0f" => [16, "\xa5a"], "\x10" => [94, "\xa5c"], "\x11" => [76, "\xa5c"], "\x12" => [104, "\xa5c"], "\x13" => [16, "\xa5c"], "\x14" => [94, "\xa5e"], "\x15" => [76, "\xa5e"], "\x16" => [104, "\xa5e"], "\x17" => [16, "\xa5e"], "\x18" => [94, "\xa5i"], "\x19" => [76, "\xa5i"], "\x1a" => [104, "\xa5i"], "\x1b" => [16, "\xa5i"], "\x1c" => [94, "\xa5o"], "\x1d" => [76, "\xa5o"], "\x1e" => [104, "\xa5o"], "\x1f" => [16, "\xa5o"], " " => [94, "\xa5s"], "!" => [76, "\xa5s"], "\"" => [104, "\xa5s"], "#" => [16, "\xa5s"], "\$" => [94, "\xa5t"], "%" => [76, "\xa5t"], "&" => [104, "\xa5t"], "'" => [16, "\xa5t"], "(" => [77, "\xa5 "], ")" => [18, "\xa5 "], "*" => [77, "\xa5%"], "+" => [18, "\xa5%"], "," => [77, "\xa5-"], "-" => [18, "\xa5-"], "." => [77, "\xa5."], "/" => [18, "\xa5."], [77, "\xa5/"], [18, "\xa5/"], [77, "\xa53"], [18, "\xa53"], [77, "\xa54"], [18, "\xa54"], [77, "\xa55"], [18, "\xa55"], [77, "\xa56"], [18, "\xa56"], ":" => [77, "\xa57"], ";" => [18, "\xa57"], "<" => [77, "\xa58"], "=" => [18, "\xa58"], ">" => [77, "\xa59"], "?" => [18, "\xa59"], "@" => [77, "\xa5="], "A" => [18, "\xa5="], "B" => [77, "\xa5A"], "C" => [18, "\xa5A"], "D" => [77, "\xa5_"], "E" => [18, "\xa5_"], "F" => [77, "\xa5b"], "G" => [18, "\xa5b"], "H" => [77, "\xa5d"], "I" => [18, "\xa5d"], "J" => [77, "\xa5f"], "K" => [18, "\xa5f"], "L" => [77, "\xa5g"], "M" => [18, "\xa5g"], "N" => [77, "\xa5h"], "O" => [18, "\xa5h"], "P" => [77, "\xa5l"], "Q" => [18, "\xa5l"], "R" => [77, "\xa5m"], "S" => [18, "\xa5m"], "T" => [77, "\xa5n"], "U" => [18, "\xa5n"], "V" => [77, "\xa5p"], "W" => [18, "\xa5p"], "X" => [77, "\xa5r"], "Y" => [18, "\xa5r"], "Z" => [77, "\xa5u"], "[" => [18, "\xa5u"], "\\" => [0, "\xa5:"], "]" => [0, "\xa5B"], "^" => [0, "\xa5C"], "_" => [0, "\xa5D"], "`" => [0, "\xa5E"], "a" => [0, "\xa5F"], "b" => [0, "\xa5G"], "c" => [0, "\xa5H"], "d" => [0, "\xa5I"], "e" => [0, "\xa5J"], "f" => [0, "\xa5K"], "g" => [0, "\xa5L"], "h" => [0, "\xa5M"], "i" => [0, "\xa5N"], "j" => [0, "\xa5O"], "k" => [0, "\xa5P"], "l" => [0, "\xa5Q"], "m" => [0, "\xa5R"], "n" => [0, "\xa5S"], "o" => [0, "\xa5T"], "p" => [0, "\xa5U"], "q" => [0, "\xa5V"], "r" => [0, "\xa5W"], "s" => [0, "\xa5Y"], "t" => [0, "\xa5j"], "u" => [0, "\xa5k"], "v" => [0, "\xa5q"], "w" => [0, "\xa5v"], "x" => [0, "\xa5w"], "y" => [0, "\xa5x"], "z" => [0, "\xa5y"], "{" => [0, "\xa5z"], "|" => [82, "\xa5"], "}" => [87, "\xa5"], "~" => [130, "\xa5"], "" => [9, "\xa5"], "\x80" => [94, "\xa60"], "\x81" => [76, "\xa60"], "\x82" => [104, "\xa60"], "\x83" => [16, "\xa60"], "\x84" => [94, "\xa61"], "\x85" => [76, "\xa61"], "\x86" => [104, "\xa61"], "\x87" => [16, "\xa61"], "\x88" => [94, "\xa62"], "\x89" => [76, "\xa62"], "\x8a" => [104, "\xa62"], "\x8b" => [16, "\xa62"], "\x8c" => [94, "\xa6a"], "\x8d" => [76, "\xa6a"], "\x8e" => [104, "\xa6a"], "\x8f" => [16, "\xa6a"], "\x90" => [94, "\xa6c"], "\x91" => [76, "\xa6c"], "\x92" => [104, "\xa6c"], "\x93" => [16, "\xa6c"], "\x94" => [94, "\xa6e"], "\x95" => [76, "\xa6e"], "\x96" => [104, "\xa6e"], "\x97" => [16, "\xa6e"], "\x98" => [94, "\xa6i"], "\x99" => [76, "\xa6i"], "\x9a" => [104, "\xa6i"], "\x9b" => [16, "\xa6i"], "\x9c" => [94, "\xa6o"], "\x9d" => [76, "\xa6o"], "\x9e" => [104, "\xa6o"], "\x9f" => [16, "\xa6o"], "\xa0" => [94, "\xa6s"], "\xa1" => [76, "\xa6s"], "\xa2" => [104, "\xa6s"], "\xa3" => [16, "\xa6s"], "\xa4" => [94, "\xa6t"], "\xa5" => [76, "\xa6t"], "\xa6" => [104, "\xa6t"], "\xa7" => [16, "\xa6t"], "\xa8" => [77, "\xa6 "], "\xa9" => [18, "\xa6 "], "\xaa" => [77, "\xa6%"], "\xab" => [18, "\xa6%"], "\xac" => [77, "\xa6-"], "\xad" => [18, "\xa6-"], "\xae" => [77, "\xa6."], "\xaf" => [18, "\xa6."], "\xb0" => [77, "\xa6/"], "\xb1" => [18, "\xa6/"], "\xb2" => [77, "\xa63"], "\xb3" => [18, "\xa63"], "\xb4" => [77, "\xa64"], "\xb5" => [18, "\xa64"], "\xb6" => [77, "\xa65"], "\xb7" => [18, "\xa65"], "\xb8" => [77, "\xa66"], "\xb9" => [18, "\xa66"], "\xba" => [77, "\xa67"], "\xbb" => [18, "\xa67"], "\xbc" => [77, "\xa68"], "\xbd" => [18, "\xa68"], "\xbe" => [77, "\xa69"], "\xbf" => [18, "\xa69"], "\xc0" => [77, "\xa6="], "\xc1" => [18, "\xa6="], "\xc2" => [77, "\xa6A"], "\xc3" => [18, "\xa6A"], "\xc4" => [77, "\xa6_"], "\xc5" => [18, "\xa6_"], "\xc6" => [77, "\xa6b"], "\xc7" => [18, "\xa6b"], "\xc8" => [77, "\xa6d"], "\xc9" => [18, "\xa6d"], "\xca" => [77, "\xa6f"], "\xcb" => [18, "\xa6f"], "\xcc" => [77, "\xa6g"], "\xcd" => [18, "\xa6g"], "\xce" => [77, "\xa6h"], "\xcf" => [18, "\xa6h"], "\xd0" => [77, "\xa6l"], "\xd1" => [18, "\xa6l"], "\xd2" => [77, "\xa6m"], "\xd3" => [18, "\xa6m"], "\xd4" => [77, "\xa6n"], "\xd5" => [18, "\xa6n"], "\xd6" => [77, "\xa6p"], "\xd7" => [18, "\xa6p"], "\xd8" => [77, "\xa6r"], "\xd9" => [18, "\xa6r"], "\xda" => [77, "\xa6u"], "\xdb" => [18, "\xa6u"], "\xdc" => [0, "\xa6:"], "\xdd" => [0, "\xa6B"], "\xde" => [0, "\xa6C"], "\xdf" => [0, "\xa6D"], "\xe0" => [0, "\xa6E"], "\xe1" => [0, "\xa6F"], "\xe2" => [0, "\xa6G"], "\xe3" => [0, "\xa6H"], "\xe4" => [0, "\xa6I"], "\xe5" => [0, "\xa6J"], "\xe6" => [0, "\xa6K"], "\xe7" => [0, "\xa6L"], "\xe8" => [0, "\xa6M"], "\xe9" => [0, "\xa6N"], "\xea" => [0, "\xa6O"], "\xeb" => [0, "\xa6P"], "\xec" => [0, "\xa6Q"], "\xed" => [0, "\xa6R"], "\xee" => [0, "\xa6S"], "\xef" => [0, "\xa6T"], "\xf0" => [0, "\xa6U"], "\xf1" => [0, "\xa6V"], "\xf2" => [0, "\xa6W"], "\xf3" => [0, "\xa6Y"], "\xf4" => [0, "\xa6j"], "\xf5" => [0, "\xa6k"], "\xf6" => [0, "\xa6q"], "\xf7" => [0, "\xa6v"], "\xf8" => [0, "\xa6w"], "\xf9" => [0, "\xa6x"], "\xfa" => [0, "\xa6y"], "\xfb" => [0, "\xa6z"], "\xfc" => [82, "\xa6"], "\xfd" => [87, "\xa6"], "\xfe" => [130, "\xa6"], "\xff" => [9, "\xa6"]], ["\x00" => [77, "\xa50"], "\x01" => [18, "\xa50"], "\x02" => [77, "\xa51"], "\x03" => [18, "\xa51"], "\x04" => [77, "\xa52"], "\x05" => [18, "\xa52"], "\x06" => [77, "\xa5a"], "\x07" => [18, "\xa5a"], "\x08" => [77, "\xa5c"], "\t" => [18, "\xa5c"], "\n" => [77, "\xa5e"], "\v" => [18, "\xa5e"], "\f" => [77, "\xa5i"], "\r" => [18, "\xa5i"], "\x0e" => [77, "\xa5o"], "\x0f" => [18, "\xa5o"], "\x10" => [77, "\xa5s"], "\x11" => [18, "\xa5s"], "\x12" => [77, "\xa5t"], "\x13" => [18, "\xa5t"], "\x14" => [0, "\xa5 "], "\x15" => [0, "\xa5%"], "\x16" => [0, "\xa5-"], "\x17" => [0, "\xa5."], "\x18" => [0, "\xa5/"], "\x19" => [0, "\xa53"], "\x1a" => [0, "\xa54"], "\x1b" => [0, "\xa55"], "\x1c" => [0, "\xa56"], "\x1d" => [0, "\xa57"], "\x1e" => [0, "\xa58"], "\x1f" => [0, "\xa59"], " " => [0, "\xa5="], "!" => [0, "\xa5A"], "\"" => [0, "\xa5_"], "#" => [0, "\xa5b"], "\$" => [0, "\xa5d"], "%" => [0, "\xa5f"], "&" => [0, "\xa5g"], "'" => [0, "\xa5h"], "(" => [0, "\xa5l"], ")" => [0, "\xa5m"], "*" => [0, "\xa5n"], "+" => [0, "\xa5p"], "," => [0, "\xa5r"], "-" => [0, "\xa5u"], "." => [100, "\xa5"], "/" => [110, "\xa5"], [111, "\xa5"], [115, "\xa5"], [116, "\xa5"], [118, "\xa5"], [119, "\xa5"], [122, "\xa5"], [123, "\xa5"], [125, "\xa5"], [126, "\xa5"], [129, "\xa5"], ":" => [143, "\xa5"], ";" => [148, "\xa5"], "<" => [151, "\xa5"], "=" => [153, "\xa5"], ">" => [83, "\xa5"], "?" => [10, "\xa5"], "@" => [77, "\xa60"], "A" => [18, "\xa60"], "B" => [77, "\xa61"], "C" => [18, "\xa61"], "D" => [77, "\xa62"], "E" => [18, "\xa62"], "F" => [77, "\xa6a"], "G" => [18, "\xa6a"], "H" => [77, "\xa6c"], "I" => [18, "\xa6c"], "J" => [77, "\xa6e"], "K" => [18, "\xa6e"], "L" => [77, "\xa6i"], "M" => [18, "\xa6i"], "N" => [77, "\xa6o"], "O" => [18, "\xa6o"], "P" => [77, "\xa6s"], "Q" => [18, "\xa6s"], "R" => [77, "\xa6t"], "S" => [18, "\xa6t"], "T" => [0, "\xa6 "], "U" => [0, "\xa6%"], "V" => [0, "\xa6-"], "W" => [0, "\xa6."], "X" => [0, "\xa6/"], "Y" => [0, "\xa63"], "Z" => [0, "\xa64"], "[" => [0, "\xa65"], "\\" => [0, "\xa66"], "]" => [0, "\xa67"], "^" => [0, "\xa68"], "_" => [0, "\xa69"], "`" => [0, "\xa6="], "a" => [0, "\xa6A"], "b" => [0, "\xa6_"], "c" => [0, "\xa6b"], "d" => [0, "\xa6d"], "e" => [0, "\xa6f"], "f" => [0, "\xa6g"], "g" => [0, "\xa6h"], "h" => [0, "\xa6l"], "i" => [0, "\xa6m"], "j" => [0, "\xa6n"], "k" => [0, "\xa6p"], "l" => [0, "\xa6r"], "m" => [0, "\xa6u"], "n" => [100, "\xa6"], "o" => [110, "\xa6"], "p" => [111, "\xa6"], "q" => [115, "\xa6"], "r" => [116, "\xa6"], "s" => [118, "\xa6"], "t" => [119, "\xa6"], "u" => [122, "\xa6"], "v" => [123, "\xa6"], "w" => [125, "\xa6"], "x" => [126, "\xa6"], "y" => [129, "\xa6"], "z" => [143, "\xa6"], "{" => [148, "\xa6"], "|" => [151, "\xa6"], "}" => [153, "\xa6"], "~" => [83, "\xa6"], "" => [10, "\xa6"], "\x80" => [77, "\xa80"], "\x81" => [18, "\xa80"], "\x82" => [77, "\xa81"], "\x83" => [18, "\xa81"], "\x84" => [77, "\xa82"], "\x85" => [18, "\xa82"], "\x86" => [77, "\xa8a"], "\x87" => [18, "\xa8a"], "\x88" => [77, "\xa8c"], "\x89" => [18, "\xa8c"], "\x8a" => [77, "\xa8e"], "\x8b" => [18, "\xa8e"], "\x8c" => [77, "\xa8i"], "\x8d" => [18, "\xa8i"], "\x8e" => [77, "\xa8o"], "\x8f" => [18, "\xa8o"], "\x90" => [77, "\xa8s"], "\x91" => [18, "\xa8s"], "\x92" => [77, "\xa8t"], "\x93" => [18, "\xa8t"], "\x94" => [0, "\xa8 "], "\x95" => [0, "\xa8%"], "\x96" => [0, "\xa8-"], "\x97" => [0, "\xa8."], "\x98" => [0, "\xa8/"], "\x99" => [0, "\xa83"], "\x9a" => [0, "\xa84"], "\x9b" => [0, "\xa85"], "\x9c" => [0, "\xa86"], "\x9d" => [0, "\xa87"], "\x9e" => [0, "\xa88"], "\x9f" => [0, "\xa89"], "\xa0" => [0, "\xa8="], "\xa1" => [0, "\xa8A"], "\xa2" => [0, "\xa8_"], "\xa3" => [0, "\xa8b"], "\xa4" => [0, "\xa8d"], "\xa5" => [0, "\xa8f"], "\xa6" => [0, "\xa8g"], "\xa7" => [0, "\xa8h"], "\xa8" => [0, "\xa8l"], "\xa9" => [0, "\xa8m"], "\xaa" => [0, "\xa8n"], "\xab" => [0, "\xa8p"], "\xac" => [0, "\xa8r"], "\xad" => [0, "\xa8u"], "\xae" => [100, "\xa8"], "\xaf" => [110, "\xa8"], "\xb0" => [111, "\xa8"], "\xb1" => [115, "\xa8"], "\xb2" => [116, "\xa8"], "\xb3" => [118, "\xa8"], "\xb4" => [119, "\xa8"], "\xb5" => [122, "\xa8"], "\xb6" => [123, "\xa8"], "\xb7" => [125, "\xa8"], "\xb8" => [126, "\xa8"], "\xb9" => [129, "\xa8"], "\xba" => [143, "\xa8"], "\xbb" => [148, "\xa8"], "\xbc" => [151, "\xa8"], "\xbd" => [153, "\xa8"], "\xbe" => [83, "\xa8"], "\xbf" => [10, "\xa8"], "\xc0" => [77, "\xae0"], "\xc1" => [18, "\xae0"], "\xc2" => [77, "\xae1"], "\xc3" => [18, "\xae1"], "\xc4" => [77, "\xae2"], "\xc5" => [18, "\xae2"], "\xc6" => [77, "\xaea"], "\xc7" => [18, "\xaea"], "\xc8" => [77, "\xaec"], "\xc9" => [18, "\xaec"], "\xca" => [77, "\xaee"], "\xcb" => [18, "\xaee"], "\xcc" => [77, "\xaei"], "\xcd" => [18, "\xaei"], "\xce" => [77, "\xaeo"], "\xcf" => [18, "\xaeo"], "\xd0" => [77, "\xaes"], "\xd1" => [18, "\xaes"], "\xd2" => [77, "\xaet"], "\xd3" => [18, "\xaet"], "\xd4" => [0, "\xae "], "\xd5" => [0, "\xae%"], "\xd6" => [0, "\xae-"], "\xd7" => [0, "\xae."], "\xd8" => [0, "\xae/"], "\xd9" => [0, "\xae3"], "\xda" => [0, "\xae4"], "\xdb" => [0, "\xae5"], "\xdc" => [0, "\xae6"], "\xdd" => [0, "\xae7"], "\xde" => [0, "\xae8"], "\xdf" => [0, "\xae9"], "\xe0" => [0, "\xae="], "\xe1" => [0, "\xaeA"], "\xe2" => [0, "\xae_"], "\xe3" => [0, "\xaeb"], "\xe4" => [0, "\xaed"], "\xe5" => [0, "\xaef"], "\xe6" => [0, "\xaeg"], "\xe7" => [0, "\xaeh"], "\xe8" => [0, "\xael"], "\xe9" => [0, "\xaem"], "\xea" => [0, "\xaen"], "\xeb" => [0, "\xaep"], "\xec" => [0, "\xaer"], "\xed" => [0, "\xaeu"], "\xee" => [100, "\xae"], "\xef" => [110, "\xae"], "\xf0" => [111, "\xae"], "\xf1" => [115, "\xae"], "\xf2" => [116, "\xae"], "\xf3" => [118, "\xae"], "\xf4" => [119, "\xae"], "\xf5" => [122, "\xae"], "\xf6" => [123, "\xae"], "\xf7" => [125, "\xae"], "\xf8" => [126, "\xae"], "\xf9" => [129, "\xae"], "\xfa" => [143, "\xae"], "\xfb" => [148, "\xae"], "\xfc" => [151, "\xae"], "\xfd" => [153, "\xae"], "\xfe" => [83, "\xae"], "\xff" => [10, "\xae"]], ["\x00" => [0, "\xa50"], "\x01" => [0, "\xa51"], "\x02" => [0, "\xa52"], "\x03" => [0, "\xa5a"], "\x04" => [0, "\xa5c"], "\x05" => [0, "\xa5e"], "\x06" => [0, "\xa5i"], "\x07" => [0, "\xa5o"], "\x08" => [0, "\xa5s"], "\t" => [0, "\xa5t"], "\n" => [73, "\xa5"], "\v" => [88, "\xa5"], "\f" => [89, "\xa5"], "\r" => [96, "\xa5"], "\x0e" => [97, "\xa5"], "\x0f" => [99, "\xa5"], "\x10" => [106, "\xa5"], "\x11" => [136, "\xa5"], "\x12" => [139, "\xa5"], "\x13" => [141, "\xa5"], "\x14" => [145, "\xa5"], "\x15" => [147, "\xa5"], "\x16" => [149, "\xa5"], "\x17" => [101, "\xa5"], "\x18" => [112, "\xa5"], "\x19" => [117, "\xa5"], "\x1a" => [120, "\xa5"], "\x1b" => [124, "\xa5"], "\x1c" => [127, "\xa5"], "\x1d" => [144, "\xa5"], "\x1e" => [152, "\xa5"], "\x1f" => [11, "\xa5"], " " => [0, "\xa60"], "!" => [0, "\xa61"], "\"" => [0, "\xa62"], "#" => [0, "\xa6a"], "\$" => [0, "\xa6c"], "%" => [0, "\xa6e"], "&" => [0, "\xa6i"], "'" => [0, "\xa6o"], "(" => [0, "\xa6s"], ")" => [0, "\xa6t"], "*" => [73, "\xa6"], "+" => [88, "\xa6"], "," => [89, "\xa6"], "-" => [96, "\xa6"], "." => [97, "\xa6"], "/" => [99, "\xa6"], [106, "\xa6"], [136, "\xa6"], [139, "\xa6"], [141, "\xa6"], [145, "\xa6"], [147, "\xa6"], [149, "\xa6"], [101, "\xa6"], [112, "\xa6"], [117, "\xa6"], ":" => [120, "\xa6"], ";" => [124, "\xa6"], "<" => [127, "\xa6"], "=" => [144, "\xa6"], ">" => [152, "\xa6"], "?" => [11, "\xa6"], "@" => [0, "\xa80"], "A" => [0, "\xa81"], "B" => [0, "\xa82"], "C" => [0, "\xa8a"], "D" => [0, "\xa8c"], "E" => [0, "\xa8e"], "F" => [0, "\xa8i"], "G" => [0, "\xa8o"], "H" => [0, "\xa8s"], "I" => [0, "\xa8t"], "J" => [73, "\xa8"], "K" => [88, "\xa8"], "L" => [89, "\xa8"], "M" => [96, "\xa8"], "N" => [97, "\xa8"], "O" => [99, "\xa8"], "P" => [106, "\xa8"], "Q" => [136, "\xa8"], "R" => [139, "\xa8"], "S" => [141, "\xa8"], "T" => [145, "\xa8"], "U" => [147, "\xa8"], "V" => [149, "\xa8"], "W" => [101, "\xa8"], "X" => [112, "\xa8"], "Y" => [117, "\xa8"], "Z" => [120, "\xa8"], "[" => [124, "\xa8"], "\\" => [127, "\xa8"], "]" => [144, "\xa8"], "^" => [152, "\xa8"], "_" => [11, "\xa8"], "`" => [0, "\xae0"], "a" => [0, "\xae1"], "b" => [0, "\xae2"], "c" => [0, "\xaea"], "d" => [0, "\xaec"], "e" => [0, "\xaee"], "f" => [0, "\xaei"], "g" => [0, "\xaeo"], "h" => [0, "\xaes"], "i" => [0, "\xaet"], "j" => [73, "\xae"], "k" => [88, "\xae"], "l" => [89, "\xae"], "m" => [96, "\xae"], "n" => [97, "\xae"], "o" => [99, "\xae"], "p" => [106, "\xae"], "q" => [136, "\xae"], "r" => [139, "\xae"], "s" => [141, "\xae"], "t" => [145, "\xae"], "u" => [147, "\xae"], "v" => [149, "\xae"], "w" => [101, "\xae"], "x" => [112, "\xae"], "y" => [117, "\xae"], "z" => [120, "\xae"], "{" => [124, "\xae"], "|" => [127, "\xae"], "}" => [144, "\xae"], "~" => [152, "\xae"], "" => [11, "\xae"], "\x80" => [0, "\xaf0"], "\x81" => [0, "\xaf1"], "\x82" => [0, "\xaf2"], "\x83" => [0, "\xafa"], "\x84" => [0, "\xafc"], "\x85" => [0, "\xafe"], "\x86" => [0, "\xafi"], "\x87" => [0, "\xafo"], "\x88" => [0, "\xafs"], "\x89" => [0, "\xaft"], "\x8a" => [73, "\xaf"], "\x8b" => [88, "\xaf"], "\x8c" => [89, "\xaf"], "\x8d" => [96, "\xaf"], "\x8e" => [97, "\xaf"], "\x8f" => [99, "\xaf"], "\x90" => [106, "\xaf"], "\x91" => [136, "\xaf"], "\x92" => [139, "\xaf"], "\x93" => [141, "\xaf"], "\x94" => [145, "\xaf"], "\x95" => [147, "\xaf"], "\x96" => [149, "\xaf"], "\x97" => [101, "\xaf"], "\x98" => [112, "\xaf"], "\x99" => [117, "\xaf"], "\x9a" => [120, "\xaf"], "\x9b" => [124, "\xaf"], "\x9c" => [127, "\xaf"], "\x9d" => [144, "\xaf"], "\x9e" => [152, "\xaf"], "\x9f" => [11, "\xaf"], "\xa0" => [0, "\xb40"], "\xa1" => [0, "\xb41"], "\xa2" => [0, "\xb42"], "\xa3" => [0, "\xb4a"], "\xa4" => [0, "\xb4c"], "\xa5" => [0, "\xb4e"], "\xa6" => [0, "\xb4i"], "\xa7" => [0, "\xb4o"], "\xa8" => [0, "\xb4s"], "\xa9" => [0, "\xb4t"], "\xaa" => [73, "\xb4"], "\xab" => [88, "\xb4"], "\xac" => [89, "\xb4"], "\xad" => [96, "\xb4"], "\xae" => [97, "\xb4"], "\xaf" => [99, "\xb4"], "\xb0" => [106, "\xb4"], "\xb1" => [136, "\xb4"], "\xb2" => [139, "\xb4"], "\xb3" => [141, "\xb4"], "\xb4" => [145, "\xb4"], "\xb5" => [147, "\xb4"], "\xb6" => [149, "\xb4"], "\xb7" => [101, "\xb4"], "\xb8" => [112, "\xb4"], "\xb9" => [117, "\xb4"], "\xba" => [120, "\xb4"], "\xbb" => [124, "\xb4"], "\xbc" => [127, "\xb4"], "\xbd" => [144, "\xb4"], "\xbe" => [152, "\xb4"], "\xbf" => [11, "\xb4"], "\xc0" => [0, "\xb60"], "\xc1" => [0, "\xb61"], "\xc2" => [0, "\xb62"], "\xc3" => [0, "\xb6a"], "\xc4" => [0, "\xb6c"], "\xc5" => [0, "\xb6e"], "\xc6" => [0, "\xb6i"], "\xc7" => [0, "\xb6o"], "\xc8" => [0, "\xb6s"], "\xc9" => [0, "\xb6t"], "\xca" => [73, "\xb6"], "\xcb" => [88, "\xb6"], "\xcc" => [89, "\xb6"], "\xcd" => [96, "\xb6"], "\xce" => [97, "\xb6"], "\xcf" => [99, "\xb6"], "\xd0" => [106, "\xb6"], "\xd1" => [136, "\xb6"], "\xd2" => [139, "\xb6"], "\xd3" => [141, "\xb6"], "\xd4" => [145, "\xb6"], "\xd5" => [147, "\xb6"], "\xd6" => [149, "\xb6"], "\xd7" => [101, "\xb6"], "\xd8" => [112, "\xb6"], "\xd9" => [117, "\xb6"], "\xda" => [120, "\xb6"], "\xdb" => [124, "\xb6"], "\xdc" => [127, "\xb6"], "\xdd" => [144, "\xb6"], "\xde" => [152, "\xb6"], "\xdf" => [11, "\xb6"], "\xe0" => [0, "\xb70"], "\xe1" => [0, "\xb71"], "\xe2" => [0, "\xb72"], "\xe3" => [0, "\xb7a"], "\xe4" => [0, "\xb7c"], "\xe5" => [0, "\xb7e"], "\xe6" => [0, "\xb7i"], "\xe7" => [0, "\xb7o"], "\xe8" => [0, "\xb7s"], "\xe9" => [0, "\xb7t"], "\xea" => [73, "\xb7"], "\xeb" => [88, "\xb7"], "\xec" => [89, "\xb7"], "\xed" => [96, "\xb7"], "\xee" => [97, "\xb7"], "\xef" => [99, "\xb7"], "\xf0" => [106, "\xb7"], "\xf1" => [136, "\xb7"], "\xf2" => [139, "\xb7"], "\xf3" => [141, "\xb7"], "\xf4" => [145, "\xb7"], "\xf5" => [147, "\xb7"], "\xf6" => [149, "\xb7"], "\xf7" => [101, "\xb7"], "\xf8" => [112, "\xb7"], "\xf9" => [117, "\xb7"], "\xfa" => [120, "\xb7"], "\xfb" => [124, "\xb7"], "\xfc" => [127, "\xb7"], "\xfd" => [144, "\xb7"], "\xfe" => [152, "\xb7"], "\xff" => [11, "\xb7"]], ["\x00" => [94, "\xa70"], "\x01" => [76, "\xa70"], "\x02" => [104, "\xa70"], "\x03" => [16, "\xa70"], "\x04" => [94, "\xa71"], "\x05" => [76, "\xa71"], "\x06" => [104, "\xa71"], "\x07" => [16, "\xa71"], "\x08" => [94, "\xa72"], "\t" => [76, "\xa72"], "\n" => [104, "\xa72"], "\v" => [16, "\xa72"], "\f" => [94, "\xa7a"], "\r" => [76, "\xa7a"], "\x0e" => [104, "\xa7a"], "\x0f" => [16, "\xa7a"], "\x10" => [94, "\xa7c"], "\x11" => [76, "\xa7c"], "\x12" => [104, "\xa7c"], "\x13" => [16, "\xa7c"], "\x14" => [94, "\xa7e"], "\x15" => [76, "\xa7e"], "\x16" => [104, "\xa7e"], "\x17" => [16, "\xa7e"], "\x18" => [94, "\xa7i"], "\x19" => [76, "\xa7i"], "\x1a" => [104, "\xa7i"], "\x1b" => [16, "\xa7i"], "\x1c" => [94, "\xa7o"], "\x1d" => [76, "\xa7o"], "\x1e" => [104, "\xa7o"], "\x1f" => [16, "\xa7o"], " " => [94, "\xa7s"], "!" => [76, "\xa7s"], "\"" => [104, "\xa7s"], "#" => [16, "\xa7s"], "\$" => [94, "\xa7t"], "%" => [76, "\xa7t"], "&" => [104, "\xa7t"], "'" => [16, "\xa7t"], "(" => [77, "\xa7 "], ")" => [18, "\xa7 "], "*" => [77, "\xa7%"], "+" => [18, "\xa7%"], "," => [77, "\xa7-"], "-" => [18, "\xa7-"], "." => [77, "\xa7."], "/" => [18, "\xa7."], [77, "\xa7/"], [18, "\xa7/"], [77, "\xa73"], [18, "\xa73"], [77, "\xa74"], [18, "\xa74"], [77, "\xa75"], [18, "\xa75"], [77, "\xa76"], [18, "\xa76"], ":" => [77, "\xa77"], ";" => [18, "\xa77"], "<" => [77, "\xa78"], "=" => [18, "\xa78"], ">" => [77, "\xa79"], "?" => [18, "\xa79"], "@" => [77, "\xa7="], "A" => [18, "\xa7="], "B" => [77, "\xa7A"], "C" => [18, "\xa7A"], "D" => [77, "\xa7_"], "E" => [18, "\xa7_"], "F" => [77, "\xa7b"], "G" => [18, "\xa7b"], "H" => [77, "\xa7d"], "I" => [18, "\xa7d"], "J" => [77, "\xa7f"], "K" => [18, "\xa7f"], "L" => [77, "\xa7g"], "M" => [18, "\xa7g"], "N" => [77, "\xa7h"], "O" => [18, "\xa7h"], "P" => [77, "\xa7l"], "Q" => [18, "\xa7l"], "R" => [77, "\xa7m"], "S" => [18, "\xa7m"], "T" => [77, "\xa7n"], "U" => [18, "\xa7n"], "V" => [77, "\xa7p"], "W" => [18, "\xa7p"], "X" => [77, "\xa7r"], "Y" => [18, "\xa7r"], "Z" => [77, "\xa7u"], "[" => [18, "\xa7u"], "\\" => [0, "\xa7:"], "]" => [0, "\xa7B"], "^" => [0, "\xa7C"], "_" => [0, "\xa7D"], "`" => [0, "\xa7E"], "a" => [0, "\xa7F"], "b" => [0, "\xa7G"], "c" => [0, "\xa7H"], "d" => [0, "\xa7I"], "e" => [0, "\xa7J"], "f" => [0, "\xa7K"], "g" => [0, "\xa7L"], "h" => [0, "\xa7M"], "i" => [0, "\xa7N"], "j" => [0, "\xa7O"], "k" => [0, "\xa7P"], "l" => [0, "\xa7Q"], "m" => [0, "\xa7R"], "n" => [0, "\xa7S"], "o" => [0, "\xa7T"], "p" => [0, "\xa7U"], "q" => [0, "\xa7V"], "r" => [0, "\xa7W"], "s" => [0, "\xa7Y"], "t" => [0, "\xa7j"], "u" => [0, "\xa7k"], "v" => [0, "\xa7q"], "w" => [0, "\xa7v"], "x" => [0, "\xa7w"], "y" => [0, "\xa7x"], "z" => [0, "\xa7y"], "{" => [0, "\xa7z"], "|" => [82, "\xa7"], "}" => [87, "\xa7"], "~" => [130, "\xa7"], "" => [9, "\xa7"], "\x80" => [94, "\xac0"], "\x81" => [76, "\xac0"], "\x82" => [104, "\xac0"], "\x83" => [16, "\xac0"], "\x84" => [94, "\xac1"], "\x85" => [76, "\xac1"], "\x86" => [104, "\xac1"], "\x87" => [16, "\xac1"], "\x88" => [94, "\xac2"], "\x89" => [76, "\xac2"], "\x8a" => [104, "\xac2"], "\x8b" => [16, "\xac2"], "\x8c" => [94, "\xaca"], "\x8d" => [76, "\xaca"], "\x8e" => [104, "\xaca"], "\x8f" => [16, "\xaca"], "\x90" => [94, "\xacc"], "\x91" => [76, "\xacc"], "\x92" => [104, "\xacc"], "\x93" => [16, "\xacc"], "\x94" => [94, "\xace"], "\x95" => [76, "\xace"], "\x96" => [104, "\xace"], "\x97" => [16, "\xace"], "\x98" => [94, "\xaci"], "\x99" => [76, "\xaci"], "\x9a" => [104, "\xaci"], "\x9b" => [16, "\xaci"], "\x9c" => [94, "\xaco"], "\x9d" => [76, "\xaco"], "\x9e" => [104, "\xaco"], "\x9f" => [16, "\xaco"], "\xa0" => [94, "\xacs"], "\xa1" => [76, "\xacs"], "\xa2" => [104, "\xacs"], "\xa3" => [16, "\xacs"], "\xa4" => [94, "\xact"], "\xa5" => [76, "\xact"], "\xa6" => [104, "\xact"], "\xa7" => [16, "\xact"], "\xa8" => [77, "\xac "], "\xa9" => [18, "\xac "], "\xaa" => [77, "\xac%"], "\xab" => [18, "\xac%"], "\xac" => [77, "\xac-"], "\xad" => [18, "\xac-"], "\xae" => [77, "\xac."], "\xaf" => [18, "\xac."], "\xb0" => [77, "\xac/"], "\xb1" => [18, "\xac/"], "\xb2" => [77, "\xac3"], "\xb3" => [18, "\xac3"], "\xb4" => [77, "\xac4"], "\xb5" => [18, "\xac4"], "\xb6" => [77, "\xac5"], "\xb7" => [18, "\xac5"], "\xb8" => [77, "\xac6"], "\xb9" => [18, "\xac6"], "\xba" => [77, "\xac7"], "\xbb" => [18, "\xac7"], "\xbc" => [77, "\xac8"], "\xbd" => [18, "\xac8"], "\xbe" => [77, "\xac9"], "\xbf" => [18, "\xac9"], "\xc0" => [77, "\xac="], "\xc1" => [18, "\xac="], "\xc2" => [77, "\xacA"], "\xc3" => [18, "\xacA"], "\xc4" => [77, "\xac_"], "\xc5" => [18, "\xac_"], "\xc6" => [77, "\xacb"], "\xc7" => [18, "\xacb"], "\xc8" => [77, "\xacd"], "\xc9" => [18, "\xacd"], "\xca" => [77, "\xacf"], "\xcb" => [18, "\xacf"], "\xcc" => [77, "\xacg"], "\xcd" => [18, "\xacg"], "\xce" => [77, "\xach"], "\xcf" => [18, "\xach"], "\xd0" => [77, "\xacl"], "\xd1" => [18, "\xacl"], "\xd2" => [77, "\xacm"], "\xd3" => [18, "\xacm"], "\xd4" => [77, "\xacn"], "\xd5" => [18, "\xacn"], "\xd6" => [77, "\xacp"], "\xd7" => [18, "\xacp"], "\xd8" => [77, "\xacr"], "\xd9" => [18, "\xacr"], "\xda" => [77, "\xacu"], "\xdb" => [18, "\xacu"], "\xdc" => [0, "\xac:"], "\xdd" => [0, "\xacB"], "\xde" => [0, "\xacC"], "\xdf" => [0, "\xacD"], "\xe0" => [0, "\xacE"], "\xe1" => [0, "\xacF"], "\xe2" => [0, "\xacG"], "\xe3" => [0, "\xacH"], "\xe4" => [0, "\xacI"], "\xe5" => [0, "\xacJ"], "\xe6" => [0, "\xacK"], "\xe7" => [0, "\xacL"], "\xe8" => [0, "\xacM"], "\xe9" => [0, "\xacN"], "\xea" => [0, "\xacO"], "\xeb" => [0, "\xacP"], "\xec" => [0, "\xacQ"], "\xed" => [0, "\xacR"], "\xee" => [0, "\xacS"], "\xef" => [0, "\xacT"], "\xf0" => [0, "\xacU"], "\xf1" => [0, "\xacV"], "\xf2" => [0, "\xacW"], "\xf3" => [0, "\xacY"], "\xf4" => [0, "\xacj"], "\xf5" => [0, "\xack"], "\xf6" => [0, "\xacq"], "\xf7" => [0, "\xacv"], "\xf8" => [0, "\xacw"], "\xf9" => [0, "\xacx"], "\xfa" => [0, "\xacy"], "\xfb" => [0, "\xacz"], "\xfc" => [82, "\xac"], "\xfd" => [87, "\xac"], "\xfe" => [130, "\xac"], "\xff" => [9, "\xac"]], ["\x00" => [94, "\xa80"], "\x01" => [76, "\xa80"], "\x02" => [104, "\xa80"], "\x03" => [16, "\xa80"], "\x04" => [94, "\xa81"], "\x05" => [76, "\xa81"], "\x06" => [104, "\xa81"], "\x07" => [16, "\xa81"], "\x08" => [94, "\xa82"], "\t" => [76, "\xa82"], "\n" => [104, "\xa82"], "\v" => [16, "\xa82"], "\f" => [94, "\xa8a"], "\r" => [76, "\xa8a"], "\x0e" => [104, "\xa8a"], "\x0f" => [16, "\xa8a"], "\x10" => [94, "\xa8c"], "\x11" => [76, "\xa8c"], "\x12" => [104, "\xa8c"], "\x13" => [16, "\xa8c"], "\x14" => [94, "\xa8e"], "\x15" => [76, "\xa8e"], "\x16" => [104, "\xa8e"], "\x17" => [16, "\xa8e"], "\x18" => [94, "\xa8i"], "\x19" => [76, "\xa8i"], "\x1a" => [104, "\xa8i"], "\x1b" => [16, "\xa8i"], "\x1c" => [94, "\xa8o"], "\x1d" => [76, "\xa8o"], "\x1e" => [104, "\xa8o"], "\x1f" => [16, "\xa8o"], " " => [94, "\xa8s"], "!" => [76, "\xa8s"], "\"" => [104, "\xa8s"], "#" => [16, "\xa8s"], "\$" => [94, "\xa8t"], "%" => [76, "\xa8t"], "&" => [104, "\xa8t"], "'" => [16, "\xa8t"], "(" => [77, "\xa8 "], ")" => [18, "\xa8 "], "*" => [77, "\xa8%"], "+" => [18, "\xa8%"], "," => [77, "\xa8-"], "-" => [18, "\xa8-"], "." => [77, "\xa8."], "/" => [18, "\xa8."], [77, "\xa8/"], [18, "\xa8/"], [77, "\xa83"], [18, "\xa83"], [77, "\xa84"], [18, "\xa84"], [77, "\xa85"], [18, "\xa85"], [77, "\xa86"], [18, "\xa86"], ":" => [77, "\xa87"], ";" => [18, "\xa87"], "<" => [77, "\xa88"], "=" => [18, "\xa88"], ">" => [77, "\xa89"], "?" => [18, "\xa89"], "@" => [77, "\xa8="], "A" => [18, "\xa8="], "B" => [77, "\xa8A"], "C" => [18, "\xa8A"], "D" => [77, "\xa8_"], "E" => [18, "\xa8_"], "F" => [77, "\xa8b"], "G" => [18, "\xa8b"], "H" => [77, "\xa8d"], "I" => [18, "\xa8d"], "J" => [77, "\xa8f"], "K" => [18, "\xa8f"], "L" => [77, "\xa8g"], "M" => [18, "\xa8g"], "N" => [77, "\xa8h"], "O" => [18, "\xa8h"], "P" => [77, "\xa8l"], "Q" => [18, "\xa8l"], "R" => [77, "\xa8m"], "S" => [18, "\xa8m"], "T" => [77, "\xa8n"], "U" => [18, "\xa8n"], "V" => [77, "\xa8p"], "W" => [18, "\xa8p"], "X" => [77, "\xa8r"], "Y" => [18, "\xa8r"], "Z" => [77, "\xa8u"], "[" => [18, "\xa8u"], "\\" => [0, "\xa8:"], "]" => [0, "\xa8B"], "^" => [0, "\xa8C"], "_" => [0, "\xa8D"], "`" => [0, "\xa8E"], "a" => [0, "\xa8F"], "b" => [0, "\xa8G"], "c" => [0, "\xa8H"], "d" => [0, "\xa8I"], "e" => [0, "\xa8J"], "f" => [0, "\xa8K"], "g" => [0, "\xa8L"], "h" => [0, "\xa8M"], "i" => [0, "\xa8N"], "j" => [0, "\xa8O"], "k" => [0, "\xa8P"], "l" => [0, "\xa8Q"], "m" => [0, "\xa8R"], "n" => [0, "\xa8S"], "o" => [0, "\xa8T"], "p" => [0, "\xa8U"], "q" => [0, "\xa8V"], "r" => [0, "\xa8W"], "s" => [0, "\xa8Y"], "t" => [0, "\xa8j"], "u" => [0, "\xa8k"], "v" => [0, "\xa8q"], "w" => [0, "\xa8v"], "x" => [0, "\xa8w"], "y" => [0, "\xa8x"], "z" => [0, "\xa8y"], "{" => [0, "\xa8z"], "|" => [82, "\xa8"], "}" => [87, "\xa8"], "~" => [130, "\xa8"], "" => [9, "\xa8"], "\x80" => [94, "\xae0"], "\x81" => [76, "\xae0"], "\x82" => [104, "\xae0"], "\x83" => [16, "\xae0"], "\x84" => [94, "\xae1"], "\x85" => [76, "\xae1"], "\x86" => [104, "\xae1"], "\x87" => [16, "\xae1"], "\x88" => [94, "\xae2"], "\x89" => [76, "\xae2"], "\x8a" => [104, "\xae2"], "\x8b" => [16, "\xae2"], "\x8c" => [94, "\xaea"], "\x8d" => [76, "\xaea"], "\x8e" => [104, "\xaea"], "\x8f" => [16, "\xaea"], "\x90" => [94, "\xaec"], "\x91" => [76, "\xaec"], "\x92" => [104, "\xaec"], "\x93" => [16, "\xaec"], "\x94" => [94, "\xaee"], "\x95" => [76, "\xaee"], "\x96" => [104, "\xaee"], "\x97" => [16, "\xaee"], "\x98" => [94, "\xaei"], "\x99" => [76, "\xaei"], "\x9a" => [104, "\xaei"], "\x9b" => [16, "\xaei"], "\x9c" => [94, "\xaeo"], "\x9d" => [76, "\xaeo"], "\x9e" => [104, "\xaeo"], "\x9f" => [16, "\xaeo"], "\xa0" => [94, "\xaes"], "\xa1" => [76, "\xaes"], "\xa2" => [104, "\xaes"], "\xa3" => [16, "\xaes"], "\xa4" => [94, "\xaet"], "\xa5" => [76, "\xaet"], "\xa6" => [104, "\xaet"], "\xa7" => [16, "\xaet"], "\xa8" => [77, "\xae "], "\xa9" => [18, "\xae "], "\xaa" => [77, "\xae%"], "\xab" => [18, "\xae%"], "\xac" => [77, "\xae-"], "\xad" => [18, "\xae-"], "\xae" => [77, "\xae."], "\xaf" => [18, "\xae."], "\xb0" => [77, "\xae/"], "\xb1" => [18, "\xae/"], "\xb2" => [77, "\xae3"], "\xb3" => [18, "\xae3"], "\xb4" => [77, "\xae4"], "\xb5" => [18, "\xae4"], "\xb6" => [77, "\xae5"], "\xb7" => [18, "\xae5"], "\xb8" => [77, "\xae6"], "\xb9" => [18, "\xae6"], "\xba" => [77, "\xae7"], "\xbb" => [18, "\xae7"], "\xbc" => [77, "\xae8"], "\xbd" => [18, "\xae8"], "\xbe" => [77, "\xae9"], "\xbf" => [18, "\xae9"], "\xc0" => [77, "\xae="], "\xc1" => [18, "\xae="], "\xc2" => [77, "\xaeA"], "\xc3" => [18, "\xaeA"], "\xc4" => [77, "\xae_"], "\xc5" => [18, "\xae_"], "\xc6" => [77, "\xaeb"], "\xc7" => [18, "\xaeb"], "\xc8" => [77, "\xaed"], "\xc9" => [18, "\xaed"], "\xca" => [77, "\xaef"], "\xcb" => [18, "\xaef"], "\xcc" => [77, "\xaeg"], "\xcd" => [18, "\xaeg"], "\xce" => [77, "\xaeh"], "\xcf" => [18, "\xaeh"], "\xd0" => [77, "\xael"], "\xd1" => [18, "\xael"], "\xd2" => [77, "\xaem"], "\xd3" => [18, "\xaem"], "\xd4" => [77, "\xaen"], "\xd5" => [18, "\xaen"], "\xd6" => [77, "\xaep"], "\xd7" => [18, "\xaep"], "\xd8" => [77, "\xaer"], "\xd9" => [18, "\xaer"], "\xda" => [77, "\xaeu"], "\xdb" => [18, "\xaeu"], "\xdc" => [0, "\xae:"], "\xdd" => [0, "\xaeB"], "\xde" => [0, "\xaeC"], "\xdf" => [0, "\xaeD"], "\xe0" => [0, "\xaeE"], "\xe1" => [0, "\xaeF"], "\xe2" => [0, "\xaeG"], "\xe3" => [0, "\xaeH"], "\xe4" => [0, "\xaeI"], "\xe5" => [0, "\xaeJ"], "\xe6" => [0, "\xaeK"], "\xe7" => [0, "\xaeL"], "\xe8" => [0, "\xaeM"], "\xe9" => [0, "\xaeN"], "\xea" => [0, "\xaeO"], "\xeb" => [0, "\xaeP"], "\xec" => [0, "\xaeQ"], "\xed" => [0, "\xaeR"], "\xee" => [0, "\xaeS"], "\xef" => [0, "\xaeT"], "\xf0" => [0, "\xaeU"], "\xf1" => [0, "\xaeV"], "\xf2" => [0, "\xaeW"], "\xf3" => [0, "\xaeY"], "\xf4" => [0, "\xaej"], "\xf5" => [0, "\xaek"], "\xf6" => [0, "\xaeq"], "\xf7" => [0, "\xaev"], "\xf8" => [0, "\xaew"], "\xf9" => [0, "\xaex"], "\xfa" => [0, "\xaey"], "\xfb" => [0, "\xaez"], "\xfc" => [82, "\xae"], "\xfd" => [87, "\xae"], "\xfe" => [130, "\xae"], "\xff" => [9, "\xae"]], ["\x00" => [94, "\xaa0"], "\x01" => [76, "\xaa0"], "\x02" => [104, "\xaa0"], "\x03" => [16, "\xaa0"], "\x04" => [94, "\xaa1"], "\x05" => [76, "\xaa1"], "\x06" => [104, "\xaa1"], "\x07" => [16, "\xaa1"], "\x08" => [94, "\xaa2"], "\t" => [76, "\xaa2"], "\n" => [104, "\xaa2"], "\v" => [16, "\xaa2"], "\f" => [94, "\xaaa"], "\r" => [76, "\xaaa"], "\x0e" => [104, "\xaaa"], "\x0f" => [16, "\xaaa"], "\x10" => [94, "\xaac"], "\x11" => [76, "\xaac"], "\x12" => [104, "\xaac"], "\x13" => [16, "\xaac"], "\x14" => [94, "\xaae"], "\x15" => [76, "\xaae"], "\x16" => [104, "\xaae"], "\x17" => [16, "\xaae"], "\x18" => [94, "\xaai"], "\x19" => [76, "\xaai"], "\x1a" => [104, "\xaai"], "\x1b" => [16, "\xaai"], "\x1c" => [94, "\xaao"], "\x1d" => [76, "\xaao"], "\x1e" => [104, "\xaao"], "\x1f" => [16, "\xaao"], " " => [94, "\xaas"], "!" => [76, "\xaas"], "\"" => [104, "\xaas"], "#" => [16, "\xaas"], "\$" => [94, "\xaat"], "%" => [76, "\xaat"], "&" => [104, "\xaat"], "'" => [16, "\xaat"], "(" => [77, "\xaa "], ")" => [18, "\xaa "], "*" => [77, "\xaa%"], "+" => [18, "\xaa%"], "," => [77, "\xaa-"], "-" => [18, "\xaa-"], "." => [77, "\xaa."], "/" => [18, "\xaa."], [77, "\xaa/"], [18, "\xaa/"], [77, "\xaa3"], [18, "\xaa3"], [77, "\xaa4"], [18, "\xaa4"], [77, "\xaa5"], [18, "\xaa5"], [77, "\xaa6"], [18, "\xaa6"], ":" => [77, "\xaa7"], ";" => [18, "\xaa7"], "<" => [77, "\xaa8"], "=" => [18, "\xaa8"], ">" => [77, "\xaa9"], "?" => [18, "\xaa9"], "@" => [77, "\xaa="], "A" => [18, "\xaa="], "B" => [77, "\xaaA"], "C" => [18, "\xaaA"], "D" => [77, "\xaa_"], "E" => [18, "\xaa_"], "F" => [77, "\xaab"], "G" => [18, "\xaab"], "H" => [77, "\xaad"], "I" => [18, "\xaad"], "J" => [77, "\xaaf"], "K" => [18, "\xaaf"], "L" => [77, "\xaag"], "M" => [18, "\xaag"], "N" => [77, "\xaah"], "O" => [18, "\xaah"], "P" => [77, "\xaal"], "Q" => [18, "\xaal"], "R" => [77, "\xaam"], "S" => [18, "\xaam"], "T" => [77, "\xaan"], "U" => [18, "\xaan"], "V" => [77, "\xaap"], "W" => [18, "\xaap"], "X" => [77, "\xaar"], "Y" => [18, "\xaar"], "Z" => [77, "\xaau"], "[" => [18, "\xaau"], "\\" => [0, "\xaa:"], "]" => [0, "\xaaB"], "^" => [0, "\xaaC"], "_" => [0, "\xaaD"], "`" => [0, "\xaaE"], "a" => [0, "\xaaF"], "b" => [0, "\xaaG"], "c" => [0, "\xaaH"], "d" => [0, "\xaaI"], "e" => [0, "\xaaJ"], "f" => [0, "\xaaK"], "g" => [0, "\xaaL"], "h" => [0, "\xaaM"], "i" => [0, "\xaaN"], "j" => [0, "\xaaO"], "k" => [0, "\xaaP"], "l" => [0, "\xaaQ"], "m" => [0, "\xaaR"], "n" => [0, "\xaaS"], "o" => [0, "\xaaT"], "p" => [0, "\xaaU"], "q" => [0, "\xaaV"], "r" => [0, "\xaaW"], "s" => [0, "\xaaY"], "t" => [0, "\xaaj"], "u" => [0, "\xaak"], "v" => [0, "\xaaq"], "w" => [0, "\xaav"], "x" => [0, "\xaaw"], "y" => [0, "\xaax"], "z" => [0, "\xaay"], "{" => [0, "\xaaz"], "|" => [82, "\xaa"], "}" => [87, "\xaa"], "~" => [130, "\xaa"], "" => [9, "\xaa"], "\x80" => [94, "\xad0"], "\x81" => [76, "\xad0"], "\x82" => [104, "\xad0"], "\x83" => [16, "\xad0"], "\x84" => [94, "\xad1"], "\x85" => [76, "\xad1"], "\x86" => [104, "\xad1"], "\x87" => [16, "\xad1"], "\x88" => [94, "\xad2"], "\x89" => [76, "\xad2"], "\x8a" => [104, "\xad2"], "\x8b" => [16, "\xad2"], "\x8c" => [94, "\xada"], "\x8d" => [76, "\xada"], "\x8e" => [104, "\xada"], "\x8f" => [16, "\xada"], "\x90" => [94, "\xadc"], "\x91" => [76, "\xadc"], "\x92" => [104, "\xadc"], "\x93" => [16, "\xadc"], "\x94" => [94, "\xade"], "\x95" => [76, "\xade"], "\x96" => [104, "\xade"], "\x97" => [16, "\xade"], "\x98" => [94, "\xadi"], "\x99" => [76, "\xadi"], "\x9a" => [104, "\xadi"], "\x9b" => [16, "\xadi"], "\x9c" => [94, "\xado"], "\x9d" => [76, "\xado"], "\x9e" => [104, "\xado"], "\x9f" => [16, "\xado"], "\xa0" => [94, "\xads"], "\xa1" => [76, "\xads"], "\xa2" => [104, "\xads"], "\xa3" => [16, "\xads"], "\xa4" => [94, "\xadt"], "\xa5" => [76, "\xadt"], "\xa6" => [104, "\xadt"], "\xa7" => [16, "\xadt"], "\xa8" => [77, "\xad "], "\xa9" => [18, "\xad "], "\xaa" => [77, "\xad%"], "\xab" => [18, "\xad%"], "\xac" => [77, "\xad-"], "\xad" => [18, "\xad-"], "\xae" => [77, "\xad."], "\xaf" => [18, "\xad."], "\xb0" => [77, "\xad/"], "\xb1" => [18, "\xad/"], "\xb2" => [77, "\xad3"], "\xb3" => [18, "\xad3"], "\xb4" => [77, "\xad4"], "\xb5" => [18, "\xad4"], "\xb6" => [77, "\xad5"], "\xb7" => [18, "\xad5"], "\xb8" => [77, "\xad6"], "\xb9" => [18, "\xad6"], "\xba" => [77, "\xad7"], "\xbb" => [18, "\xad7"], "\xbc" => [77, "\xad8"], "\xbd" => [18, "\xad8"], "\xbe" => [77, "\xad9"], "\xbf" => [18, "\xad9"], "\xc0" => [77, "\xad="], "\xc1" => [18, "\xad="], "\xc2" => [77, "\xadA"], "\xc3" => [18, "\xadA"], "\xc4" => [77, "\xad_"], "\xc5" => [18, "\xad_"], "\xc6" => [77, "\xadb"], "\xc7" => [18, "\xadb"], "\xc8" => [77, "\xadd"], "\xc9" => [18, "\xadd"], "\xca" => [77, "\xadf"], "\xcb" => [18, "\xadf"], "\xcc" => [77, "\xadg"], "\xcd" => [18, "\xadg"], "\xce" => [77, "\xadh"], "\xcf" => [18, "\xadh"], "\xd0" => [77, "\xadl"], "\xd1" => [18, "\xadl"], "\xd2" => [77, "\xadm"], "\xd3" => [18, "\xadm"], "\xd4" => [77, "\xadn"], "\xd5" => [18, "\xadn"], "\xd6" => [77, "\xadp"], "\xd7" => [18, "\xadp"], "\xd8" => [77, "\xadr"], "\xd9" => [18, "\xadr"], "\xda" => [77, "\xadu"], "\xdb" => [18, "\xadu"], "\xdc" => [0, "\xad:"], "\xdd" => [0, "\xadB"], "\xde" => [0, "\xadC"], "\xdf" => [0, "\xadD"], "\xe0" => [0, "\xadE"], "\xe1" => [0, "\xadF"], "\xe2" => [0, "\xadG"], "\xe3" => [0, "\xadH"], "\xe4" => [0, "\xadI"], "\xe5" => [0, "\xadJ"], "\xe6" => [0, "\xadK"], "\xe7" => [0, "\xadL"], "\xe8" => [0, "\xadM"], "\xe9" => [0, "\xadN"], "\xea" => [0, "\xadO"], "\xeb" => [0, "\xadP"], "\xec" => [0, "\xadQ"], "\xed" => [0, "\xadR"], "\xee" => [0, "\xadS"], "\xef" => [0, "\xadT"], "\xf0" => [0, "\xadU"], "\xf1" => [0, "\xadV"], "\xf2" => [0, "\xadW"], "\xf3" => [0, "\xadY"], "\xf4" => [0, "\xadj"], "\xf5" => [0, "\xadk"], "\xf6" => [0, "\xadq"], "\xf7" => [0, "\xadv"], "\xf8" => [0, "\xadw"], "\xf9" => [0, "\xadx"], "\xfa" => [0, "\xady"], "\xfb" => [0, "\xadz"], "\xfc" => [82, "\xad"], "\xfd" => [87, "\xad"], "\xfe" => [130, "\xad"], "\xff" => [9, "\xad"]], ["\x00" => [94, "\xab0"], "\x01" => [76, "\xab0"], "\x02" => [104, "\xab0"], "\x03" => [16, "\xab0"], "\x04" => [94, "\xab1"], "\x05" => [76, "\xab1"], "\x06" => [104, "\xab1"], "\x07" => [16, "\xab1"], "\x08" => [94, "\xab2"], "\t" => [76, "\xab2"], "\n" => [104, "\xab2"], "\v" => [16, "\xab2"], "\f" => [94, "\xaba"], "\r" => [76, "\xaba"], "\x0e" => [104, "\xaba"], "\x0f" => [16, "\xaba"], "\x10" => [94, "\xabc"], "\x11" => [76, "\xabc"], "\x12" => [104, "\xabc"], "\x13" => [16, "\xabc"], "\x14" => [94, "\xabe"], "\x15" => [76, "\xabe"], "\x16" => [104, "\xabe"], "\x17" => [16, "\xabe"], "\x18" => [94, "\xabi"], "\x19" => [76, "\xabi"], "\x1a" => [104, "\xabi"], "\x1b" => [16, "\xabi"], "\x1c" => [94, "\xabo"], "\x1d" => [76, "\xabo"], "\x1e" => [104, "\xabo"], "\x1f" => [16, "\xabo"], " " => [94, "\xabs"], "!" => [76, "\xabs"], "\"" => [104, "\xabs"], "#" => [16, "\xabs"], "\$" => [94, "\xabt"], "%" => [76, "\xabt"], "&" => [104, "\xabt"], "'" => [16, "\xabt"], "(" => [77, "\xab "], ")" => [18, "\xab "], "*" => [77, "\xab%"], "+" => [18, "\xab%"], "," => [77, "\xab-"], "-" => [18, "\xab-"], "." => [77, "\xab."], "/" => [18, "\xab."], [77, "\xab/"], [18, "\xab/"], [77, "\xab3"], [18, "\xab3"], [77, "\xab4"], [18, "\xab4"], [77, "\xab5"], [18, "\xab5"], [77, "\xab6"], [18, "\xab6"], ":" => [77, "\xab7"], ";" => [18, "\xab7"], "<" => [77, "\xab8"], "=" => [18, "\xab8"], ">" => [77, "\xab9"], "?" => [18, "\xab9"], "@" => [77, "\xab="], "A" => [18, "\xab="], "B" => [77, "\xabA"], "C" => [18, "\xabA"], "D" => [77, "\xab_"], "E" => [18, "\xab_"], "F" => [77, "\xabb"], "G" => [18, "\xabb"], "H" => [77, "\xabd"], "I" => [18, "\xabd"], "J" => [77, "\xabf"], "K" => [18, "\xabf"], "L" => [77, "\xabg"], "M" => [18, "\xabg"], "N" => [77, "\xabh"], "O" => [18, "\xabh"], "P" => [77, "\xabl"], "Q" => [18, "\xabl"], "R" => [77, "\xabm"], "S" => [18, "\xabm"], "T" => [77, "\xabn"], "U" => [18, "\xabn"], "V" => [77, "\xabp"], "W" => [18, "\xabp"], "X" => [77, "\xabr"], "Y" => [18, "\xabr"], "Z" => [77, "\xabu"], "[" => [18, "\xabu"], "\\" => [0, "\xab:"], "]" => [0, "\xabB"], "^" => [0, "\xabC"], "_" => [0, "\xabD"], "`" => [0, "\xabE"], "a" => [0, "\xabF"], "b" => [0, "\xabG"], "c" => [0, "\xabH"], "d" => [0, "\xabI"], "e" => [0, "\xabJ"], "f" => [0, "\xabK"], "g" => [0, "\xabL"], "h" => [0, "\xabM"], "i" => [0, "\xabN"], "j" => [0, "\xabO"], "k" => [0, "\xabP"], "l" => [0, "\xabQ"], "m" => [0, "\xabR"], "n" => [0, "\xabS"], "o" => [0, "\xabT"], "p" => [0, "\xabU"], "q" => [0, "\xabV"], "r" => [0, "\xabW"], "s" => [0, "\xabY"], "t" => [0, "\xabj"], "u" => [0, "\xabk"], "v" => [0, "\xabq"], "w" => [0, "\xabv"], "x" => [0, "\xabw"], "y" => [0, "\xabx"], "z" => [0, "\xaby"], "{" => [0, "\xabz"], "|" => [82, "\xab"], "}" => [87, "\xab"], "~" => [130, "\xab"], "" => [9, "\xab"], "\x80" => [94, "\xce0"], "\x81" => [76, "\xce0"], "\x82" => [104, "\xce0"], "\x83" => [16, "\xce0"], "\x84" => [94, "\xce1"], "\x85" => [76, "\xce1"], "\x86" => [104, "\xce1"], "\x87" => [16, "\xce1"], "\x88" => [94, "\xce2"], "\x89" => [76, "\xce2"], "\x8a" => [104, "\xce2"], "\x8b" => [16, "\xce2"], "\x8c" => [94, "\xcea"], "\x8d" => [76, "\xcea"], "\x8e" => [104, "\xcea"], "\x8f" => [16, "\xcea"], "\x90" => [94, "\xcec"], "\x91" => [76, "\xcec"], "\x92" => [104, "\xcec"], "\x93" => [16, "\xcec"], "\x94" => [94, "\xcee"], "\x95" => [76, "\xcee"], "\x96" => [104, "\xcee"], "\x97" => [16, "\xcee"], "\x98" => [94, "\xcei"], "\x99" => [76, "\xcei"], "\x9a" => [104, "\xcei"], "\x9b" => [16, "\xcei"], "\x9c" => [94, "\xceo"], "\x9d" => [76, "\xceo"], "\x9e" => [104, "\xceo"], "\x9f" => [16, "\xceo"], "\xa0" => [94, "\xces"], "\xa1" => [76, "\xces"], "\xa2" => [104, "\xces"], "\xa3" => [16, "\xces"], "\xa4" => [94, "\xcet"], "\xa5" => [76, "\xcet"], "\xa6" => [104, "\xcet"], "\xa7" => [16, "\xcet"], "\xa8" => [77, "\xce "], "\xa9" => [18, "\xce "], "\xaa" => [77, "\xce%"], "\xab" => [18, "\xce%"], "\xac" => [77, "\xce-"], "\xad" => [18, "\xce-"], "\xae" => [77, "\xce."], "\xaf" => [18, "\xce."], "\xb0" => [77, "\xce/"], "\xb1" => [18, "\xce/"], "\xb2" => [77, "\xce3"], "\xb3" => [18, "\xce3"], "\xb4" => [77, "\xce4"], "\xb5" => [18, "\xce4"], "\xb6" => [77, "\xce5"], "\xb7" => [18, "\xce5"], "\xb8" => [77, "\xce6"], "\xb9" => [18, "\xce6"], "\xba" => [77, "\xce7"], "\xbb" => [18, "\xce7"], "\xbc" => [77, "\xce8"], "\xbd" => [18, "\xce8"], "\xbe" => [77, "\xce9"], "\xbf" => [18, "\xce9"], "\xc0" => [77, "\xce="], "\xc1" => [18, "\xce="], "\xc2" => [77, "\xceA"], "\xc3" => [18, "\xceA"], "\xc4" => [77, "\xce_"], "\xc5" => [18, "\xce_"], "\xc6" => [77, "\xceb"], "\xc7" => [18, "\xceb"], "\xc8" => [77, "\xced"], "\xc9" => [18, "\xced"], "\xca" => [77, "\xcef"], "\xcb" => [18, "\xcef"], "\xcc" => [77, "\xceg"], "\xcd" => [18, "\xceg"], "\xce" => [77, "\xceh"], "\xcf" => [18, "\xceh"], "\xd0" => [77, "\xcel"], "\xd1" => [18, "\xcel"], "\xd2" => [77, "\xcem"], "\xd3" => [18, "\xcem"], "\xd4" => [77, "\xcen"], "\xd5" => [18, "\xcen"], "\xd6" => [77, "\xcep"], "\xd7" => [18, "\xcep"], "\xd8" => [77, "\xcer"], "\xd9" => [18, "\xcer"], "\xda" => [77, "\xceu"], "\xdb" => [18, "\xceu"], "\xdc" => [0, "\xce:"], "\xdd" => [0, "\xceB"], "\xde" => [0, "\xceC"], "\xdf" => [0, "\xceD"], "\xe0" => [0, "\xceE"], "\xe1" => [0, "\xceF"], "\xe2" => [0, "\xceG"], "\xe3" => [0, "\xceH"], "\xe4" => [0, "\xceI"], "\xe5" => [0, "\xceJ"], "\xe6" => [0, "\xceK"], "\xe7" => [0, "\xceL"], "\xe8" => [0, "\xceM"], "\xe9" => [0, "\xceN"], "\xea" => [0, "\xceO"], "\xeb" => [0, "\xceP"], "\xec" => [0, "\xceQ"], "\xed" => [0, "\xceR"], "\xee" => [0, "\xceS"], "\xef" => [0, "\xceT"], "\xf0" => [0, "\xceU"], "\xf1" => [0, "\xceV"], "\xf2" => [0, "\xceW"], "\xf3" => [0, "\xceY"], "\xf4" => [0, "\xcej"], "\xf5" => [0, "\xcek"], "\xf6" => [0, "\xceq"], "\xf7" => [0, "\xcev"], "\xf8" => [0, "\xcew"], "\xf9" => [0, "\xcex"], "\xfa" => [0, "\xcey"], "\xfb" => [0, "\xcez"], "\xfc" => [82, "\xce"], "\xfd" => [87, "\xce"], "\xfe" => [130, "\xce"], "\xff" => [9, "\xce"]], ["\x00" => [77, "\xab0"], "\x01" => [18, "\xab0"], "\x02" => [77, "\xab1"], "\x03" => [18, "\xab1"], "\x04" => [77, "\xab2"], "\x05" => [18, "\xab2"], "\x06" => [77, "\xaba"], "\x07" => [18, "\xaba"], "\x08" => [77, "\xabc"], "\t" => [18, "\xabc"], "\n" => [77, "\xabe"], "\v" => [18, "\xabe"], "\f" => [77, "\xabi"], "\r" => [18, "\xabi"], "\x0e" => [77, "\xabo"], "\x0f" => [18, "\xabo"], "\x10" => [77, "\xabs"], "\x11" => [18, "\xabs"], "\x12" => [77, "\xabt"], "\x13" => [18, "\xabt"], "\x14" => [0, "\xab "], "\x15" => [0, "\xab%"], "\x16" => [0, "\xab-"], "\x17" => [0, "\xab."], "\x18" => [0, "\xab/"], "\x19" => [0, "\xab3"], "\x1a" => [0, "\xab4"], "\x1b" => [0, "\xab5"], "\x1c" => [0, "\xab6"], "\x1d" => [0, "\xab7"], "\x1e" => [0, "\xab8"], "\x1f" => [0, "\xab9"], " " => [0, "\xab="], "!" => [0, "\xabA"], "\"" => [0, "\xab_"], "#" => [0, "\xabb"], "\$" => [0, "\xabd"], "%" => [0, "\xabf"], "&" => [0, "\xabg"], "'" => [0, "\xabh"], "(" => [0, "\xabl"], ")" => [0, "\xabm"], "*" => [0, "\xabn"], "+" => [0, "\xabp"], "," => [0, "\xabr"], "-" => [0, "\xabu"], "." => [100, "\xab"], "/" => [110, "\xab"], [111, "\xab"], [115, "\xab"], [116, "\xab"], [118, "\xab"], [119, "\xab"], [122, "\xab"], [123, "\xab"], [125, "\xab"], [126, "\xab"], [129, "\xab"], ":" => [143, "\xab"], ";" => [148, "\xab"], "<" => [151, "\xab"], "=" => [153, "\xab"], ">" => [83, "\xab"], "?" => [10, "\xab"], "@" => [77, "\xce0"], "A" => [18, "\xce0"], "B" => [77, "\xce1"], "C" => [18, "\xce1"], "D" => [77, "\xce2"], "E" => [18, "\xce2"], "F" => [77, "\xcea"], "G" => [18, "\xcea"], "H" => [77, "\xcec"], "I" => [18, "\xcec"], "J" => [77, "\xcee"], "K" => [18, "\xcee"], "L" => [77, "\xcei"], "M" => [18, "\xcei"], "N" => [77, "\xceo"], "O" => [18, "\xceo"], "P" => [77, "\xces"], "Q" => [18, "\xces"], "R" => [77, "\xcet"], "S" => [18, "\xcet"], "T" => [0, "\xce "], "U" => [0, "\xce%"], "V" => [0, "\xce-"], "W" => [0, "\xce."], "X" => [0, "\xce/"], "Y" => [0, "\xce3"], "Z" => [0, "\xce4"], "[" => [0, "\xce5"], "\\" => [0, "\xce6"], "]" => [0, "\xce7"], "^" => [0, "\xce8"], "_" => [0, "\xce9"], "`" => [0, "\xce="], "a" => [0, "\xceA"], "b" => [0, "\xce_"], "c" => [0, "\xceb"], "d" => [0, "\xced"], "e" => [0, "\xcef"], "f" => [0, "\xceg"], "g" => [0, "\xceh"], "h" => [0, "\xcel"], "i" => [0, "\xcem"], "j" => [0, "\xcen"], "k" => [0, "\xcep"], "l" => [0, "\xcer"], "m" => [0, "\xceu"], "n" => [100, "\xce"], "o" => [110, "\xce"], "p" => [111, "\xce"], "q" => [115, "\xce"], "r" => [116, "\xce"], "s" => [118, "\xce"], "t" => [119, "\xce"], "u" => [122, "\xce"], "v" => [123, "\xce"], "w" => [125, "\xce"], "x" => [126, "\xce"], "y" => [129, "\xce"], "z" => [143, "\xce"], "{" => [148, "\xce"], "|" => [151, "\xce"], "}" => [153, "\xce"], "~" => [83, "\xce"], "" => [10, "\xce"], "\x80" => [77, "\xd70"], "\x81" => [18, "\xd70"], "\x82" => [77, "\xd71"], "\x83" => [18, "\xd71"], "\x84" => [77, "\xd72"], "\x85" => [18, "\xd72"], "\x86" => [77, "\xd7a"], "\x87" => [18, "\xd7a"], "\x88" => [77, "\xd7c"], "\x89" => [18, "\xd7c"], "\x8a" => [77, "\xd7e"], "\x8b" => [18, "\xd7e"], "\x8c" => [77, "\xd7i"], "\x8d" => [18, "\xd7i"], "\x8e" => [77, "\xd7o"], "\x8f" => [18, "\xd7o"], "\x90" => [77, "\xd7s"], "\x91" => [18, "\xd7s"], "\x92" => [77, "\xd7t"], "\x93" => [18, "\xd7t"], "\x94" => [0, "\xd7 "], "\x95" => [0, "\xd7%"], "\x96" => [0, "\xd7-"], "\x97" => [0, "\xd7."], "\x98" => [0, "\xd7/"], "\x99" => [0, "\xd73"], "\x9a" => [0, "\xd74"], "\x9b" => [0, "\xd75"], "\x9c" => [0, "\xd76"], "\x9d" => [0, "\xd77"], "\x9e" => [0, "\xd78"], "\x9f" => [0, "\xd79"], "\xa0" => [0, "\xd7="], "\xa1" => [0, "\xd7A"], "\xa2" => [0, "\xd7_"], "\xa3" => [0, "\xd7b"], "\xa4" => [0, "\xd7d"], "\xa5" => [0, "\xd7f"], "\xa6" => [0, "\xd7g"], "\xa7" => [0, "\xd7h"], "\xa8" => [0, "\xd7l"], "\xa9" => [0, "\xd7m"], "\xaa" => [0, "\xd7n"], "\xab" => [0, "\xd7p"], "\xac" => [0, "\xd7r"], "\xad" => [0, "\xd7u"], "\xae" => [100, "\xd7"], "\xaf" => [110, "\xd7"], "\xb0" => [111, "\xd7"], "\xb1" => [115, "\xd7"], "\xb2" => [116, "\xd7"], "\xb3" => [118, "\xd7"], "\xb4" => [119, "\xd7"], "\xb5" => [122, "\xd7"], "\xb6" => [123, "\xd7"], "\xb7" => [125, "\xd7"], "\xb8" => [126, "\xd7"], "\xb9" => [129, "\xd7"], "\xba" => [143, "\xd7"], "\xbb" => [148, "\xd7"], "\xbc" => [151, "\xd7"], "\xbd" => [153, "\xd7"], "\xbe" => [83, "\xd7"], "\xbf" => [10, "\xd7"], "\xc0" => [77, "\xe10"], "\xc1" => [18, "\xe10"], "\xc2" => [77, "\xe11"], "\xc3" => [18, "\xe11"], "\xc4" => [77, "\xe12"], "\xc5" => [18, "\xe12"], "\xc6" => [77, "\xe1a"], "\xc7" => [18, "\xe1a"], "\xc8" => [77, "\xe1c"], "\xc9" => [18, "\xe1c"], "\xca" => [77, "\xe1e"], "\xcb" => [18, "\xe1e"], "\xcc" => [77, "\xe1i"], "\xcd" => [18, "\xe1i"], "\xce" => [77, "\xe1o"], "\xcf" => [18, "\xe1o"], "\xd0" => [77, "\xe1s"], "\xd1" => [18, "\xe1s"], "\xd2" => [77, "\xe1t"], "\xd3" => [18, "\xe1t"], "\xd4" => [0, "\xe1 "], "\xd5" => [0, "\xe1%"], "\xd6" => [0, "\xe1-"], "\xd7" => [0, "\xe1."], "\xd8" => [0, "\xe1/"], "\xd9" => [0, "\xe13"], "\xda" => [0, "\xe14"], "\xdb" => [0, "\xe15"], "\xdc" => [0, "\xe16"], "\xdd" => [0, "\xe17"], "\xde" => [0, "\xe18"], "\xdf" => [0, "\xe19"], "\xe0" => [0, "\xe1="], "\xe1" => [0, "\xe1A"], "\xe2" => [0, "\xe1_"], "\xe3" => [0, "\xe1b"], "\xe4" => [0, "\xe1d"], "\xe5" => [0, "\xe1f"], "\xe6" => [0, "\xe1g"], "\xe7" => [0, "\xe1h"], "\xe8" => [0, "\xe1l"], "\xe9" => [0, "\xe1m"], "\xea" => [0, "\xe1n"], "\xeb" => [0, "\xe1p"], "\xec" => [0, "\xe1r"], "\xed" => [0, "\xe1u"], "\xee" => [100, "\xe1"], "\xef" => [110, "\xe1"], "\xf0" => [111, "\xe1"], "\xf1" => [115, "\xe1"], "\xf2" => [116, "\xe1"], "\xf3" => [118, "\xe1"], "\xf4" => [119, "\xe1"], "\xf5" => [122, "\xe1"], "\xf6" => [123, "\xe1"], "\xf7" => [125, "\xe1"], "\xf8" => [126, "\xe1"], "\xf9" => [129, "\xe1"], "\xfa" => [143, "\xe1"], "\xfb" => [148, "\xe1"], "\xfc" => [151, "\xe1"], "\xfd" => [153, "\xe1"], "\xfe" => [83, "\xe1"], "\xff" => [10, "\xe1"]], ["\x00" => [0, "\xab0"], "\x01" => [0, "\xab1"], "\x02" => [0, "\xab2"], "\x03" => [0, "\xaba"], "\x04" => [0, "\xabc"], "\x05" => [0, "\xabe"], "\x06" => [0, "\xabi"], "\x07" => [0, "\xabo"], "\x08" => [0, "\xabs"], "\t" => [0, "\xabt"], "\n" => [73, "\xab"], "\v" => [88, "\xab"], "\f" => [89, "\xab"], "\r" => [96, "\xab"], "\x0e" => [97, "\xab"], "\x0f" => [99, "\xab"], "\x10" => [106, "\xab"], "\x11" => [136, "\xab"], "\x12" => [139, "\xab"], "\x13" => [141, "\xab"], "\x14" => [145, "\xab"], "\x15" => [147, "\xab"], "\x16" => [149, "\xab"], "\x17" => [101, "\xab"], "\x18" => [112, "\xab"], "\x19" => [117, "\xab"], "\x1a" => [120, "\xab"], "\x1b" => [124, "\xab"], "\x1c" => [127, "\xab"], "\x1d" => [144, "\xab"], "\x1e" => [152, "\xab"], "\x1f" => [11, "\xab"], " " => [0, "\xce0"], "!" => [0, "\xce1"], "\"" => [0, "\xce2"], "#" => [0, "\xcea"], "\$" => [0, "\xcec"], "%" => [0, "\xcee"], "&" => [0, "\xcei"], "'" => [0, "\xceo"], "(" => [0, "\xces"], ")" => [0, "\xcet"], "*" => [73, "\xce"], "+" => [88, "\xce"], "," => [89, "\xce"], "-" => [96, "\xce"], "." => [97, "\xce"], "/" => [99, "\xce"], [106, "\xce"], [136, "\xce"], [139, "\xce"], [141, "\xce"], [145, "\xce"], [147, "\xce"], [149, "\xce"], [101, "\xce"], [112, "\xce"], [117, "\xce"], ":" => [120, "\xce"], ";" => [124, "\xce"], "<" => [127, "\xce"], "=" => [144, "\xce"], ">" => [152, "\xce"], "?" => [11, "\xce"], "@" => [0, "\xd70"], "A" => [0, "\xd71"], "B" => [0, "\xd72"], "C" => [0, "\xd7a"], "D" => [0, "\xd7c"], "E" => [0, "\xd7e"], "F" => [0, "\xd7i"], "G" => [0, "\xd7o"], "H" => [0, "\xd7s"], "I" => [0, "\xd7t"], "J" => [73, "\xd7"], "K" => [88, "\xd7"], "L" => [89, "\xd7"], "M" => [96, "\xd7"], "N" => [97, "\xd7"], "O" => [99, "\xd7"], "P" => [106, "\xd7"], "Q" => [136, "\xd7"], "R" => [139, "\xd7"], "S" => [141, "\xd7"], "T" => [145, "\xd7"], "U" => [147, "\xd7"], "V" => [149, "\xd7"], "W" => [101, "\xd7"], "X" => [112, "\xd7"], "Y" => [117, "\xd7"], "Z" => [120, "\xd7"], "[" => [124, "\xd7"], "\\" => [127, "\xd7"], "]" => [144, "\xd7"], "^" => [152, "\xd7"], "_" => [11, "\xd7"], "`" => [0, "\xe10"], "a" => [0, "\xe11"], "b" => [0, "\xe12"], "c" => [0, "\xe1a"], "d" => [0, "\xe1c"], "e" => [0, "\xe1e"], "f" => [0, "\xe1i"], "g" => [0, "\xe1o"], "h" => [0, "\xe1s"], "i" => [0, "\xe1t"], "j" => [73, "\xe1"], "k" => [88, "\xe1"], "l" => [89, "\xe1"], "m" => [96, "\xe1"], "n" => [97, "\xe1"], "o" => [99, "\xe1"], "p" => [106, "\xe1"], "q" => [136, "\xe1"], "r" => [139, "\xe1"], "s" => [141, "\xe1"], "t" => [145, "\xe1"], "u" => [147, "\xe1"], "v" => [149, "\xe1"], "w" => [101, "\xe1"], "x" => [112, "\xe1"], "y" => [117, "\xe1"], "z" => [120, "\xe1"], "{" => [124, "\xe1"], "|" => [127, "\xe1"], "}" => [144, "\xe1"], "~" => [152, "\xe1"], "" => [11, "\xe1"], "\x80" => [0, "\xec0"], "\x81" => [0, "\xec1"], "\x82" => [0, "\xec2"], "\x83" => [0, "\xeca"], "\x84" => [0, "\xecc"], "\x85" => [0, "\xece"], "\x86" => [0, "\xeci"], "\x87" => [0, "\xeco"], "\x88" => [0, "\xecs"], "\x89" => [0, "\xect"], "\x8a" => [73, "\xec"], "\x8b" => [88, "\xec"], "\x8c" => [89, "\xec"], "\x8d" => [96, "\xec"], "\x8e" => [97, "\xec"], "\x8f" => [99, "\xec"], "\x90" => [106, "\xec"], "\x91" => [136, "\xec"], "\x92" => [139, "\xec"], "\x93" => [141, "\xec"], "\x94" => [145, "\xec"], "\x95" => [147, "\xec"], "\x96" => [149, "\xec"], "\x97" => [101, "\xec"], "\x98" => [112, "\xec"], "\x99" => [117, "\xec"], "\x9a" => [120, "\xec"], "\x9b" => [124, "\xec"], "\x9c" => [127, "\xec"], "\x9d" => [144, "\xec"], "\x9e" => [152, "\xec"], "\x9f" => [11, "\xec"], "\xa0" => [0, "\xed0"], "\xa1" => [0, "\xed1"], "\xa2" => [0, "\xed2"], "\xa3" => [0, "\xeda"], "\xa4" => [0, "\xedc"], "\xa5" => [0, "\xede"], "\xa6" => [0, "\xedi"], "\xa7" => [0, "\xedo"], "\xa8" => [0, "\xeds"], "\xa9" => [0, "\xedt"], "\xaa" => [73, "\xed"], "\xab" => [88, "\xed"], "\xac" => [89, "\xed"], "\xad" => [96, "\xed"], "\xae" => [97, "\xed"], "\xaf" => [99, "\xed"], "\xb0" => [106, "\xed"], "\xb1" => [136, "\xed"], "\xb2" => [139, "\xed"], "\xb3" => [141, "\xed"], "\xb4" => [145, "\xed"], "\xb5" => [147, "\xed"], "\xb6" => [149, "\xed"], "\xb7" => [101, "\xed"], "\xb8" => [112, "\xed"], "\xb9" => [117, "\xed"], "\xba" => [120, "\xed"], "\xbb" => [124, "\xed"], "\xbc" => [127, "\xed"], "\xbd" => [144, "\xed"], "\xbe" => [152, "\xed"], "\xbf" => [11, "\xed"], "\xc0" => [92, "\xc7"], "\xc1" => [95, "\xc7"], "\xc2" => [137, "\xc7"], "\xc3" => [142, "\xc7"], "\xc4" => [150, "\xc7"], "\xc5" => [74, "\xc7"], "\xc6" => [90, "\xc7"], "\xc7" => [98, "\xc7"], "\xc8" => [107, "\xc7"], "\xc9" => [140, "\xc7"], "\xca" => [146, "\xc7"], "\xcb" => [102, "\xc7"], "\xcc" => [113, "\xc7"], "\xcd" => [121, "\xc7"], "\xce" => [128, "\xc7"], "\xcf" => [12, "\xc7"], "\xd0" => [92, "\xcf"], "\xd1" => [95, "\xcf"], "\xd2" => [137, "\xcf"], "\xd3" => [142, "\xcf"], "\xd4" => [150, "\xcf"], "\xd5" => [74, "\xcf"], "\xd6" => [90, "\xcf"], "\xd7" => [98, "\xcf"], "\xd8" => [107, "\xcf"], "\xd9" => [140, "\xcf"], "\xda" => [146, "\xcf"], "\xdb" => [102, "\xcf"], "\xdc" => [113, "\xcf"], "\xdd" => [121, "\xcf"], "\xde" => [128, "\xcf"], "\xdf" => [12, "\xcf"], "\xe0" => [92, "\xea"], "\xe1" => [95, "\xea"], "\xe2" => [137, "\xea"], "\xe3" => [142, "\xea"], "\xe4" => [150, "\xea"], "\xe5" => [74, "\xea"], "\xe6" => [90, "\xea"], "\xe7" => [98, "\xea"], "\xe8" => [107, "\xea"], "\xe9" => [140, "\xea"], "\xea" => [146, "\xea"], "\xeb" => [102, "\xea"], "\xec" => [113, "\xea"], "\xed" => [121, "\xea"], "\xee" => [128, "\xea"], "\xef" => [12, "\xea"], "\xf0" => [92, "\xeb"], "\xf1" => [95, "\xeb"], "\xf2" => [137, "\xeb"], "\xf3" => [142, "\xeb"], "\xf4" => [150, "\xeb"], "\xf5" => [74, "\xeb"], "\xf6" => [90, "\xeb"], "\xf7" => [98, "\xeb"], "\xf8" => [107, "\xeb"], "\xf9" => [140, "\xeb"], "\xfa" => [146, "\xeb"], "\xfb" => [102, "\xeb"], "\xfc" => [113, "\xeb"], "\xfd" => [121, "\xeb"], "\xfe" => [128, "\xeb"], "\xff" => [12, "\xeb"]], ["\x00" => [94, "\xaf0"], "\x01" => [76, "\xaf0"], "\x02" => [104, "\xaf0"], "\x03" => [16, "\xaf0"], "\x04" => [94, "\xaf1"], "\x05" => [76, "\xaf1"], "\x06" => [104, "\xaf1"], "\x07" => [16, "\xaf1"], "\x08" => [94, "\xaf2"], "\t" => [76, "\xaf2"], "\n" => [104, "\xaf2"], "\v" => [16, "\xaf2"], "\f" => [94, "\xafa"], "\r" => [76, "\xafa"], "\x0e" => [104, "\xafa"], "\x0f" => [16, "\xafa"], "\x10" => [94, "\xafc"], "\x11" => [76, "\xafc"], "\x12" => [104, "\xafc"], "\x13" => [16, "\xafc"], "\x14" => [94, "\xafe"], "\x15" => [76, "\xafe"], "\x16" => [104, "\xafe"], "\x17" => [16, "\xafe"], "\x18" => [94, "\xafi"], "\x19" => [76, "\xafi"], "\x1a" => [104, "\xafi"], "\x1b" => [16, "\xafi"], "\x1c" => [94, "\xafo"], "\x1d" => [76, "\xafo"], "\x1e" => [104, "\xafo"], "\x1f" => [16, "\xafo"], " " => [94, "\xafs"], "!" => [76, "\xafs"], "\"" => [104, "\xafs"], "#" => [16, "\xafs"], "\$" => [94, "\xaft"], "%" => [76, "\xaft"], "&" => [104, "\xaft"], "'" => [16, "\xaft"], "(" => [77, "\xaf "], ")" => [18, "\xaf "], "*" => [77, "\xaf%"], "+" => [18, "\xaf%"], "," => [77, "\xaf-"], "-" => [18, "\xaf-"], "." => [77, "\xaf."], "/" => [18, "\xaf."], [77, "\xaf/"], [18, "\xaf/"], [77, "\xaf3"], [18, "\xaf3"], [77, "\xaf4"], [18, "\xaf4"], [77, "\xaf5"], [18, "\xaf5"], [77, "\xaf6"], [18, "\xaf6"], ":" => [77, "\xaf7"], ";" => [18, "\xaf7"], "<" => [77, "\xaf8"], "=" => [18, "\xaf8"], ">" => [77, "\xaf9"], "?" => [18, "\xaf9"], "@" => [77, "\xaf="], "A" => [18, "\xaf="], "B" => [77, "\xafA"], "C" => [18, "\xafA"], "D" => [77, "\xaf_"], "E" => [18, "\xaf_"], "F" => [77, "\xafb"], "G" => [18, "\xafb"], "H" => [77, "\xafd"], "I" => [18, "\xafd"], "J" => [77, "\xaff"], "K" => [18, "\xaff"], "L" => [77, "\xafg"], "M" => [18, "\xafg"], "N" => [77, "\xafh"], "O" => [18, "\xafh"], "P" => [77, "\xafl"], "Q" => [18, "\xafl"], "R" => [77, "\xafm"], "S" => [18, "\xafm"], "T" => [77, "\xafn"], "U" => [18, "\xafn"], "V" => [77, "\xafp"], "W" => [18, "\xafp"], "X" => [77, "\xafr"], "Y" => [18, "\xafr"], "Z" => [77, "\xafu"], "[" => [18, "\xafu"], "\\" => [0, "\xaf:"], "]" => [0, "\xafB"], "^" => [0, "\xafC"], "_" => [0, "\xafD"], "`" => [0, "\xafE"], "a" => [0, "\xafF"], "b" => [0, "\xafG"], "c" => [0, "\xafH"], "d" => [0, "\xafI"], "e" => [0, "\xafJ"], "f" => [0, "\xafK"], "g" => [0, "\xafL"], "h" => [0, "\xafM"], "i" => [0, "\xafN"], "j" => [0, "\xafO"], "k" => [0, "\xafP"], "l" => [0, "\xafQ"], "m" => [0, "\xafR"], "n" => [0, "\xafS"], "o" => [0, "\xafT"], "p" => [0, "\xafU"], "q" => [0, "\xafV"], "r" => [0, "\xafW"], "s" => [0, "\xafY"], "t" => [0, "\xafj"], "u" => [0, "\xafk"], "v" => [0, "\xafq"], "w" => [0, "\xafv"], "x" => [0, "\xafw"], "y" => [0, "\xafx"], "z" => [0, "\xafy"], "{" => [0, "\xafz"], "|" => [82, "\xaf"], "}" => [87, "\xaf"], "~" => [130, "\xaf"], "" => [9, "\xaf"], "\x80" => [94, "\xb40"], "\x81" => [76, "\xb40"], "\x82" => [104, "\xb40"], "\x83" => [16, "\xb40"], "\x84" => [94, "\xb41"], "\x85" => [76, "\xb41"], "\x86" => [104, "\xb41"], "\x87" => [16, "\xb41"], "\x88" => [94, "\xb42"], "\x89" => [76, "\xb42"], "\x8a" => [104, "\xb42"], "\x8b" => [16, "\xb42"], "\x8c" => [94, "\xb4a"], "\x8d" => [76, "\xb4a"], "\x8e" => [104, "\xb4a"], "\x8f" => [16, "\xb4a"], "\x90" => [94, "\xb4c"], "\x91" => [76, "\xb4c"], "\x92" => [104, "\xb4c"], "\x93" => [16, "\xb4c"], "\x94" => [94, "\xb4e"], "\x95" => [76, "\xb4e"], "\x96" => [104, "\xb4e"], "\x97" => [16, "\xb4e"], "\x98" => [94, "\xb4i"], "\x99" => [76, "\xb4i"], "\x9a" => [104, "\xb4i"], "\x9b" => [16, "\xb4i"], "\x9c" => [94, "\xb4o"], "\x9d" => [76, "\xb4o"], "\x9e" => [104, "\xb4o"], "\x9f" => [16, "\xb4o"], "\xa0" => [94, "\xb4s"], "\xa1" => [76, "\xb4s"], "\xa2" => [104, "\xb4s"], "\xa3" => [16, "\xb4s"], "\xa4" => [94, "\xb4t"], "\xa5" => [76, "\xb4t"], "\xa6" => [104, "\xb4t"], "\xa7" => [16, "\xb4t"], "\xa8" => [77, "\xb4 "], "\xa9" => [18, "\xb4 "], "\xaa" => [77, "\xb4%"], "\xab" => [18, "\xb4%"], "\xac" => [77, "\xb4-"], "\xad" => [18, "\xb4-"], "\xae" => [77, "\xb4."], "\xaf" => [18, "\xb4."], "\xb0" => [77, "\xb4/"], "\xb1" => [18, "\xb4/"], "\xb2" => [77, "\xb43"], "\xb3" => [18, "\xb43"], "\xb4" => [77, "\xb44"], "\xb5" => [18, "\xb44"], "\xb6" => [77, "\xb45"], "\xb7" => [18, "\xb45"], "\xb8" => [77, "\xb46"], "\xb9" => [18, "\xb46"], "\xba" => [77, "\xb47"], "\xbb" => [18, "\xb47"], "\xbc" => [77, "\xb48"], "\xbd" => [18, "\xb48"], "\xbe" => [77, "\xb49"], "\xbf" => [18, "\xb49"], "\xc0" => [77, "\xb4="], "\xc1" => [18, "\xb4="], "\xc2" => [77, "\xb4A"], "\xc3" => [18, "\xb4A"], "\xc4" => [77, "\xb4_"], "\xc5" => [18, "\xb4_"], "\xc6" => [77, "\xb4b"], "\xc7" => [18, "\xb4b"], "\xc8" => [77, "\xb4d"], "\xc9" => [18, "\xb4d"], "\xca" => [77, "\xb4f"], "\xcb" => [18, "\xb4f"], "\xcc" => [77, "\xb4g"], "\xcd" => [18, "\xb4g"], "\xce" => [77, "\xb4h"], "\xcf" => [18, "\xb4h"], "\xd0" => [77, "\xb4l"], "\xd1" => [18, "\xb4l"], "\xd2" => [77, "\xb4m"], "\xd3" => [18, "\xb4m"], "\xd4" => [77, "\xb4n"], "\xd5" => [18, "\xb4n"], "\xd6" => [77, "\xb4p"], "\xd7" => [18, "\xb4p"], "\xd8" => [77, "\xb4r"], "\xd9" => [18, "\xb4r"], "\xda" => [77, "\xb4u"], "\xdb" => [18, "\xb4u"], "\xdc" => [0, "\xb4:"], "\xdd" => [0, "\xb4B"], "\xde" => [0, "\xb4C"], "\xdf" => [0, "\xb4D"], "\xe0" => [0, "\xb4E"], "\xe1" => [0, "\xb4F"], "\xe2" => [0, "\xb4G"], "\xe3" => [0, "\xb4H"], "\xe4" => [0, "\xb4I"], "\xe5" => [0, "\xb4J"], "\xe6" => [0, "\xb4K"], "\xe7" => [0, "\xb4L"], "\xe8" => [0, "\xb4M"], "\xe9" => [0, "\xb4N"], "\xea" => [0, "\xb4O"], "\xeb" => [0, "\xb4P"], "\xec" => [0, "\xb4Q"], "\xed" => [0, "\xb4R"], "\xee" => [0, "\xb4S"], "\xef" => [0, "\xb4T"], "\xf0" => [0, "\xb4U"], "\xf1" => [0, "\xb4V"], "\xf2" => [0, "\xb4W"], "\xf3" => [0, "\xb4Y"], "\xf4" => [0, "\xb4j"], "\xf5" => [0, "\xb4k"], "\xf6" => [0, "\xb4q"], "\xf7" => [0, "\xb4v"], "\xf8" => [0, "\xb4w"], "\xf9" => [0, "\xb4x"], "\xfa" => [0, "\xb4y"], "\xfb" => [0, "\xb4z"], "\xfc" => [82, "\xb4"], "\xfd" => [87, "\xb4"], "\xfe" => [130, "\xb4"], "\xff" => [9, "\xb4"]], ["\x00" => [77, "\xaf0"], "\x01" => [18, "\xaf0"], "\x02" => [77, "\xaf1"], "\x03" => [18, "\xaf1"], "\x04" => [77, "\xaf2"], "\x05" => [18, "\xaf2"], "\x06" => [77, "\xafa"], "\x07" => [18, "\xafa"], "\x08" => [77, "\xafc"], "\t" => [18, "\xafc"], "\n" => [77, "\xafe"], "\v" => [18, "\xafe"], "\f" => [77, "\xafi"], "\r" => [18, "\xafi"], "\x0e" => [77, "\xafo"], "\x0f" => [18, "\xafo"], "\x10" => [77, "\xafs"], "\x11" => [18, "\xafs"], "\x12" => [77, "\xaft"], "\x13" => [18, "\xaft"], "\x14" => [0, "\xaf "], "\x15" => [0, "\xaf%"], "\x16" => [0, "\xaf-"], "\x17" => [0, "\xaf."], "\x18" => [0, "\xaf/"], "\x19" => [0, "\xaf3"], "\x1a" => [0, "\xaf4"], "\x1b" => [0, "\xaf5"], "\x1c" => [0, "\xaf6"], "\x1d" => [0, "\xaf7"], "\x1e" => [0, "\xaf8"], "\x1f" => [0, "\xaf9"], " " => [0, "\xaf="], "!" => [0, "\xafA"], "\"" => [0, "\xaf_"], "#" => [0, "\xafb"], "\$" => [0, "\xafd"], "%" => [0, "\xaff"], "&" => [0, "\xafg"], "'" => [0, "\xafh"], "(" => [0, "\xafl"], ")" => [0, "\xafm"], "*" => [0, "\xafn"], "+" => [0, "\xafp"], "," => [0, "\xafr"], "-" => [0, "\xafu"], "." => [100, "\xaf"], "/" => [110, "\xaf"], [111, "\xaf"], [115, "\xaf"], [116, "\xaf"], [118, "\xaf"], [119, "\xaf"], [122, "\xaf"], [123, "\xaf"], [125, "\xaf"], [126, "\xaf"], [129, "\xaf"], ":" => [143, "\xaf"], ";" => [148, "\xaf"], "<" => [151, "\xaf"], "=" => [153, "\xaf"], ">" => [83, "\xaf"], "?" => [10, "\xaf"], "@" => [77, "\xb40"], "A" => [18, "\xb40"], "B" => [77, "\xb41"], "C" => [18, "\xb41"], "D" => [77, "\xb42"], "E" => [18, "\xb42"], "F" => [77, "\xb4a"], "G" => [18, "\xb4a"], "H" => [77, "\xb4c"], "I" => [18, "\xb4c"], "J" => [77, "\xb4e"], "K" => [18, "\xb4e"], "L" => [77, "\xb4i"], "M" => [18, "\xb4i"], "N" => [77, "\xb4o"], "O" => [18, "\xb4o"], "P" => [77, "\xb4s"], "Q" => [18, "\xb4s"], "R" => [77, "\xb4t"], "S" => [18, "\xb4t"], "T" => [0, "\xb4 "], "U" => [0, "\xb4%"], "V" => [0, "\xb4-"], "W" => [0, "\xb4."], "X" => [0, "\xb4/"], "Y" => [0, "\xb43"], "Z" => [0, "\xb44"], "[" => [0, "\xb45"], "\\" => [0, "\xb46"], "]" => [0, "\xb47"], "^" => [0, "\xb48"], "_" => [0, "\xb49"], "`" => [0, "\xb4="], "a" => [0, "\xb4A"], "b" => [0, "\xb4_"], "c" => [0, "\xb4b"], "d" => [0, "\xb4d"], "e" => [0, "\xb4f"], "f" => [0, "\xb4g"], "g" => [0, "\xb4h"], "h" => [0, "\xb4l"], "i" => [0, "\xb4m"], "j" => [0, "\xb4n"], "k" => [0, "\xb4p"], "l" => [0, "\xb4r"], "m" => [0, "\xb4u"], "n" => [100, "\xb4"], "o" => [110, "\xb4"], "p" => [111, "\xb4"], "q" => [115, "\xb4"], "r" => [116, "\xb4"], "s" => [118, "\xb4"], "t" => [119, "\xb4"], "u" => [122, "\xb4"], "v" => [123, "\xb4"], "w" => [125, "\xb4"], "x" => [126, "\xb4"], "y" => [129, "\xb4"], "z" => [143, "\xb4"], "{" => [148, "\xb4"], "|" => [151, "\xb4"], "}" => [153, "\xb4"], "~" => [83, "\xb4"], "" => [10, "\xb4"], "\x80" => [77, "\xb60"], "\x81" => [18, "\xb60"], "\x82" => [77, "\xb61"], "\x83" => [18, "\xb61"], "\x84" => [77, "\xb62"], "\x85" => [18, "\xb62"], "\x86" => [77, "\xb6a"], "\x87" => [18, "\xb6a"], "\x88" => [77, "\xb6c"], "\x89" => [18, "\xb6c"], "\x8a" => [77, "\xb6e"], "\x8b" => [18, "\xb6e"], "\x8c" => [77, "\xb6i"], "\x8d" => [18, "\xb6i"], "\x8e" => [77, "\xb6o"], "\x8f" => [18, "\xb6o"], "\x90" => [77, "\xb6s"], "\x91" => [18, "\xb6s"], "\x92" => [77, "\xb6t"], "\x93" => [18, "\xb6t"], "\x94" => [0, "\xb6 "], "\x95" => [0, "\xb6%"], "\x96" => [0, "\xb6-"], "\x97" => [0, "\xb6."], "\x98" => [0, "\xb6/"], "\x99" => [0, "\xb63"], "\x9a" => [0, "\xb64"], "\x9b" => [0, "\xb65"], "\x9c" => [0, "\xb66"], "\x9d" => [0, "\xb67"], "\x9e" => [0, "\xb68"], "\x9f" => [0, "\xb69"], "\xa0" => [0, "\xb6="], "\xa1" => [0, "\xb6A"], "\xa2" => [0, "\xb6_"], "\xa3" => [0, "\xb6b"], "\xa4" => [0, "\xb6d"], "\xa5" => [0, "\xb6f"], "\xa6" => [0, "\xb6g"], "\xa7" => [0, "\xb6h"], "\xa8" => [0, "\xb6l"], "\xa9" => [0, "\xb6m"], "\xaa" => [0, "\xb6n"], "\xab" => [0, "\xb6p"], "\xac" => [0, "\xb6r"], "\xad" => [0, "\xb6u"], "\xae" => [100, "\xb6"], "\xaf" => [110, "\xb6"], "\xb0" => [111, "\xb6"], "\xb1" => [115, "\xb6"], "\xb2" => [116, "\xb6"], "\xb3" => [118, "\xb6"], "\xb4" => [119, "\xb6"], "\xb5" => [122, "\xb6"], "\xb6" => [123, "\xb6"], "\xb7" => [125, "\xb6"], "\xb8" => [126, "\xb6"], "\xb9" => [129, "\xb6"], "\xba" => [143, "\xb6"], "\xbb" => [148, "\xb6"], "\xbc" => [151, "\xb6"], "\xbd" => [153, "\xb6"], "\xbe" => [83, "\xb6"], "\xbf" => [10, "\xb6"], "\xc0" => [77, "\xb70"], "\xc1" => [18, "\xb70"], "\xc2" => [77, "\xb71"], "\xc3" => [18, "\xb71"], "\xc4" => [77, "\xb72"], "\xc5" => [18, "\xb72"], "\xc6" => [77, "\xb7a"], "\xc7" => [18, "\xb7a"], "\xc8" => [77, "\xb7c"], "\xc9" => [18, "\xb7c"], "\xca" => [77, "\xb7e"], "\xcb" => [18, "\xb7e"], "\xcc" => [77, "\xb7i"], "\xcd" => [18, "\xb7i"], "\xce" => [77, "\xb7o"], "\xcf" => [18, "\xb7o"], "\xd0" => [77, "\xb7s"], "\xd1" => [18, "\xb7s"], "\xd2" => [77, "\xb7t"], "\xd3" => [18, "\xb7t"], "\xd4" => [0, "\xb7 "], "\xd5" => [0, "\xb7%"], "\xd6" => [0, "\xb7-"], "\xd7" => [0, "\xb7."], "\xd8" => [0, "\xb7/"], "\xd9" => [0, "\xb73"], "\xda" => [0, "\xb74"], "\xdb" => [0, "\xb75"], "\xdc" => [0, "\xb76"], "\xdd" => [0, "\xb77"], "\xde" => [0, "\xb78"], "\xdf" => [0, "\xb79"], "\xe0" => [0, "\xb7="], "\xe1" => [0, "\xb7A"], "\xe2" => [0, "\xb7_"], "\xe3" => [0, "\xb7b"], "\xe4" => [0, "\xb7d"], "\xe5" => [0, "\xb7f"], "\xe6" => [0, "\xb7g"], "\xe7" => [0, "\xb7h"], "\xe8" => [0, "\xb7l"], "\xe9" => [0, "\xb7m"], "\xea" => [0, "\xb7n"], "\xeb" => [0, "\xb7p"], "\xec" => [0, "\xb7r"], "\xed" => [0, "\xb7u"], "\xee" => [100, "\xb7"], "\xef" => [110, "\xb7"], "\xf0" => [111, "\xb7"], "\xf1" => [115, "\xb7"], "\xf2" => [116, "\xb7"], "\xf3" => [118, "\xb7"], "\xf4" => [119, "\xb7"], "\xf5" => [122, "\xb7"], "\xf6" => [123, "\xb7"], "\xf7" => [125, "\xb7"], "\xf8" => [126, "\xb7"], "\xf9" => [129, "\xb7"], "\xfa" => [143, "\xb7"], "\xfb" => [148, "\xb7"], "\xfc" => [151, "\xb7"], "\xfd" => [153, "\xb7"], "\xfe" => [83, "\xb7"], "\xff" => [10, "\xb7"]], ["\x00" => [94, "\xb00"], "\x01" => [76, "\xb00"], "\x02" => [104, "\xb00"], "\x03" => [16, "\xb00"], "\x04" => [94, "\xb01"], "\x05" => [76, "\xb01"], "\x06" => [104, "\xb01"], "\x07" => [16, "\xb01"], "\x08" => [94, "\xb02"], "\t" => [76, "\xb02"], "\n" => [104, "\xb02"], "\v" => [16, "\xb02"], "\f" => [94, "\xb0a"], "\r" => [76, "\xb0a"], "\x0e" => [104, "\xb0a"], "\x0f" => [16, "\xb0a"], "\x10" => [94, "\xb0c"], "\x11" => [76, "\xb0c"], "\x12" => [104, "\xb0c"], "\x13" => [16, "\xb0c"], "\x14" => [94, "\xb0e"], "\x15" => [76, "\xb0e"], "\x16" => [104, "\xb0e"], "\x17" => [16, "\xb0e"], "\x18" => [94, "\xb0i"], "\x19" => [76, "\xb0i"], "\x1a" => [104, "\xb0i"], "\x1b" => [16, "\xb0i"], "\x1c" => [94, "\xb0o"], "\x1d" => [76, "\xb0o"], "\x1e" => [104, "\xb0o"], "\x1f" => [16, "\xb0o"], " " => [94, "\xb0s"], "!" => [76, "\xb0s"], "\"" => [104, "\xb0s"], "#" => [16, "\xb0s"], "\$" => [94, "\xb0t"], "%" => [76, "\xb0t"], "&" => [104, "\xb0t"], "'" => [16, "\xb0t"], "(" => [77, "\xb0 "], ")" => [18, "\xb0 "], "*" => [77, "\xb0%"], "+" => [18, "\xb0%"], "," => [77, "\xb0-"], "-" => [18, "\xb0-"], "." => [77, "\xb0."], "/" => [18, "\xb0."], [77, "\xb0/"], [18, "\xb0/"], [77, "\xb03"], [18, "\xb03"], [77, "\xb04"], [18, "\xb04"], [77, "\xb05"], [18, "\xb05"], [77, "\xb06"], [18, "\xb06"], ":" => [77, "\xb07"], ";" => [18, "\xb07"], "<" => [77, "\xb08"], "=" => [18, "\xb08"], ">" => [77, "\xb09"], "?" => [18, "\xb09"], "@" => [77, "\xb0="], "A" => [18, "\xb0="], "B" => [77, "\xb0A"], "C" => [18, "\xb0A"], "D" => [77, "\xb0_"], "E" => [18, "\xb0_"], "F" => [77, "\xb0b"], "G" => [18, "\xb0b"], "H" => [77, "\xb0d"], "I" => [18, "\xb0d"], "J" => [77, "\xb0f"], "K" => [18, "\xb0f"], "L" => [77, "\xb0g"], "M" => [18, "\xb0g"], "N" => [77, "\xb0h"], "O" => [18, "\xb0h"], "P" => [77, "\xb0l"], "Q" => [18, "\xb0l"], "R" => [77, "\xb0m"], "S" => [18, "\xb0m"], "T" => [77, "\xb0n"], "U" => [18, "\xb0n"], "V" => [77, "\xb0p"], "W" => [18, "\xb0p"], "X" => [77, "\xb0r"], "Y" => [18, "\xb0r"], "Z" => [77, "\xb0u"], "[" => [18, "\xb0u"], "\\" => [0, "\xb0:"], "]" => [0, "\xb0B"], "^" => [0, "\xb0C"], "_" => [0, "\xb0D"], "`" => [0, "\xb0E"], "a" => [0, "\xb0F"], "b" => [0, "\xb0G"], "c" => [0, "\xb0H"], "d" => [0, "\xb0I"], "e" => [0, "\xb0J"], "f" => [0, "\xb0K"], "g" => [0, "\xb0L"], "h" => [0, "\xb0M"], "i" => [0, "\xb0N"], "j" => [0, "\xb0O"], "k" => [0, "\xb0P"], "l" => [0, "\xb0Q"], "m" => [0, "\xb0R"], "n" => [0, "\xb0S"], "o" => [0, "\xb0T"], "p" => [0, "\xb0U"], "q" => [0, "\xb0V"], "r" => [0, "\xb0W"], "s" => [0, "\xb0Y"], "t" => [0, "\xb0j"], "u" => [0, "\xb0k"], "v" => [0, "\xb0q"], "w" => [0, "\xb0v"], "x" => [0, "\xb0w"], "y" => [0, "\xb0x"], "z" => [0, "\xb0y"], "{" => [0, "\xb0z"], "|" => [82, "\xb0"], "}" => [87, "\xb0"], "~" => [130, "\xb0"], "" => [9, "\xb0"], "\x80" => [94, "\xb10"], "\x81" => [76, "\xb10"], "\x82" => [104, "\xb10"], "\x83" => [16, "\xb10"], "\x84" => [94, "\xb11"], "\x85" => [76, "\xb11"], "\x86" => [104, "\xb11"], "\x87" => [16, "\xb11"], "\x88" => [94, "\xb12"], "\x89" => [76, "\xb12"], "\x8a" => [104, "\xb12"], "\x8b" => [16, "\xb12"], "\x8c" => [94, "\xb1a"], "\x8d" => [76, "\xb1a"], "\x8e" => [104, "\xb1a"], "\x8f" => [16, "\xb1a"], "\x90" => [94, "\xb1c"], "\x91" => [76, "\xb1c"], "\x92" => [104, "\xb1c"], "\x93" => [16, "\xb1c"], "\x94" => [94, "\xb1e"], "\x95" => [76, "\xb1e"], "\x96" => [104, "\xb1e"], "\x97" => [16, "\xb1e"], "\x98" => [94, "\xb1i"], "\x99" => [76, "\xb1i"], "\x9a" => [104, "\xb1i"], "\x9b" => [16, "\xb1i"], "\x9c" => [94, "\xb1o"], "\x9d" => [76, "\xb1o"], "\x9e" => [104, "\xb1o"], "\x9f" => [16, "\xb1o"], "\xa0" => [94, "\xb1s"], "\xa1" => [76, "\xb1s"], "\xa2" => [104, "\xb1s"], "\xa3" => [16, "\xb1s"], "\xa4" => [94, "\xb1t"], "\xa5" => [76, "\xb1t"], "\xa6" => [104, "\xb1t"], "\xa7" => [16, "\xb1t"], "\xa8" => [77, "\xb1 "], "\xa9" => [18, "\xb1 "], "\xaa" => [77, "\xb1%"], "\xab" => [18, "\xb1%"], "\xac" => [77, "\xb1-"], "\xad" => [18, "\xb1-"], "\xae" => [77, "\xb1."], "\xaf" => [18, "\xb1."], "\xb0" => [77, "\xb1/"], "\xb1" => [18, "\xb1/"], "\xb2" => [77, "\xb13"], "\xb3" => [18, "\xb13"], "\xb4" => [77, "\xb14"], "\xb5" => [18, "\xb14"], "\xb6" => [77, "\xb15"], "\xb7" => [18, "\xb15"], "\xb8" => [77, "\xb16"], "\xb9" => [18, "\xb16"], "\xba" => [77, "\xb17"], "\xbb" => [18, "\xb17"], "\xbc" => [77, "\xb18"], "\xbd" => [18, "\xb18"], "\xbe" => [77, "\xb19"], "\xbf" => [18, "\xb19"], "\xc0" => [77, "\xb1="], "\xc1" => [18, "\xb1="], "\xc2" => [77, "\xb1A"], "\xc3" => [18, "\xb1A"], "\xc4" => [77, "\xb1_"], "\xc5" => [18, "\xb1_"], "\xc6" => [77, "\xb1b"], "\xc7" => [18, "\xb1b"], "\xc8" => [77, "\xb1d"], "\xc9" => [18, "\xb1d"], "\xca" => [77, "\xb1f"], "\xcb" => [18, "\xb1f"], "\xcc" => [77, "\xb1g"], "\xcd" => [18, "\xb1g"], "\xce" => [77, "\xb1h"], "\xcf" => [18, "\xb1h"], "\xd0" => [77, "\xb1l"], "\xd1" => [18, "\xb1l"], "\xd2" => [77, "\xb1m"], "\xd3" => [18, "\xb1m"], "\xd4" => [77, "\xb1n"], "\xd5" => [18, "\xb1n"], "\xd6" => [77, "\xb1p"], "\xd7" => [18, "\xb1p"], "\xd8" => [77, "\xb1r"], "\xd9" => [18, "\xb1r"], "\xda" => [77, "\xb1u"], "\xdb" => [18, "\xb1u"], "\xdc" => [0, "\xb1:"], "\xdd" => [0, "\xb1B"], "\xde" => [0, "\xb1C"], "\xdf" => [0, "\xb1D"], "\xe0" => [0, "\xb1E"], "\xe1" => [0, "\xb1F"], "\xe2" => [0, "\xb1G"], "\xe3" => [0, "\xb1H"], "\xe4" => [0, "\xb1I"], "\xe5" => [0, "\xb1J"], "\xe6" => [0, "\xb1K"], "\xe7" => [0, "\xb1L"], "\xe8" => [0, "\xb1M"], "\xe9" => [0, "\xb1N"], "\xea" => [0, "\xb1O"], "\xeb" => [0, "\xb1P"], "\xec" => [0, "\xb1Q"], "\xed" => [0, "\xb1R"], "\xee" => [0, "\xb1S"], "\xef" => [0, "\xb1T"], "\xf0" => [0, "\xb1U"], "\xf1" => [0, "\xb1V"], "\xf2" => [0, "\xb1W"], "\xf3" => [0, "\xb1Y"], "\xf4" => [0, "\xb1j"], "\xf5" => [0, "\xb1k"], "\xf6" => [0, "\xb1q"], "\xf7" => [0, "\xb1v"], "\xf8" => [0, "\xb1w"], "\xf9" => [0, "\xb1x"], "\xfa" => [0, "\xb1y"], "\xfb" => [0, "\xb1z"], "\xfc" => [82, "\xb1"], "\xfd" => [87, "\xb1"], "\xfe" => [130, "\xb1"], "\xff" => [9, "\xb1"]], ["\x00" => [77, "\xb00"], "\x01" => [18, "\xb00"], "\x02" => [77, "\xb01"], "\x03" => [18, "\xb01"], "\x04" => [77, "\xb02"], "\x05" => [18, "\xb02"], "\x06" => [77, "\xb0a"], "\x07" => [18, "\xb0a"], "\x08" => [77, "\xb0c"], "\t" => [18, "\xb0c"], "\n" => [77, "\xb0e"], "\v" => [18, "\xb0e"], "\f" => [77, "\xb0i"], "\r" => [18, "\xb0i"], "\x0e" => [77, "\xb0o"], "\x0f" => [18, "\xb0o"], "\x10" => [77, "\xb0s"], "\x11" => [18, "\xb0s"], "\x12" => [77, "\xb0t"], "\x13" => [18, "\xb0t"], "\x14" => [0, "\xb0 "], "\x15" => [0, "\xb0%"], "\x16" => [0, "\xb0-"], "\x17" => [0, "\xb0."], "\x18" => [0, "\xb0/"], "\x19" => [0, "\xb03"], "\x1a" => [0, "\xb04"], "\x1b" => [0, "\xb05"], "\x1c" => [0, "\xb06"], "\x1d" => [0, "\xb07"], "\x1e" => [0, "\xb08"], "\x1f" => [0, "\xb09"], " " => [0, "\xb0="], "!" => [0, "\xb0A"], "\"" => [0, "\xb0_"], "#" => [0, "\xb0b"], "\$" => [0, "\xb0d"], "%" => [0, "\xb0f"], "&" => [0, "\xb0g"], "'" => [0, "\xb0h"], "(" => [0, "\xb0l"], ")" => [0, "\xb0m"], "*" => [0, "\xb0n"], "+" => [0, "\xb0p"], "," => [0, "\xb0r"], "-" => [0, "\xb0u"], "." => [100, "\xb0"], "/" => [110, "\xb0"], [111, "\xb0"], [115, "\xb0"], [116, "\xb0"], [118, "\xb0"], [119, "\xb0"], [122, "\xb0"], [123, "\xb0"], [125, "\xb0"], [126, "\xb0"], [129, "\xb0"], ":" => [143, "\xb0"], ";" => [148, "\xb0"], "<" => [151, "\xb0"], "=" => [153, "\xb0"], ">" => [83, "\xb0"], "?" => [10, "\xb0"], "@" => [77, "\xb10"], "A" => [18, "\xb10"], "B" => [77, "\xb11"], "C" => [18, "\xb11"], "D" => [77, "\xb12"], "E" => [18, "\xb12"], "F" => [77, "\xb1a"], "G" => [18, "\xb1a"], "H" => [77, "\xb1c"], "I" => [18, "\xb1c"], "J" => [77, "\xb1e"], "K" => [18, "\xb1e"], "L" => [77, "\xb1i"], "M" => [18, "\xb1i"], "N" => [77, "\xb1o"], "O" => [18, "\xb1o"], "P" => [77, "\xb1s"], "Q" => [18, "\xb1s"], "R" => [77, "\xb1t"], "S" => [18, "\xb1t"], "T" => [0, "\xb1 "], "U" => [0, "\xb1%"], "V" => [0, "\xb1-"], "W" => [0, "\xb1."], "X" => [0, "\xb1/"], "Y" => [0, "\xb13"], "Z" => [0, "\xb14"], "[" => [0, "\xb15"], "\\" => [0, "\xb16"], "]" => [0, "\xb17"], "^" => [0, "\xb18"], "_" => [0, "\xb19"], "`" => [0, "\xb1="], "a" => [0, "\xb1A"], "b" => [0, "\xb1_"], "c" => [0, "\xb1b"], "d" => [0, "\xb1d"], "e" => [0, "\xb1f"], "f" => [0, "\xb1g"], "g" => [0, "\xb1h"], "h" => [0, "\xb1l"], "i" => [0, "\xb1m"], "j" => [0, "\xb1n"], "k" => [0, "\xb1p"], "l" => [0, "\xb1r"], "m" => [0, "\xb1u"], "n" => [100, "\xb1"], "o" => [110, "\xb1"], "p" => [111, "\xb1"], "q" => [115, "\xb1"], "r" => [116, "\xb1"], "s" => [118, "\xb1"], "t" => [119, "\xb1"], "u" => [122, "\xb1"], "v" => [123, "\xb1"], "w" => [125, "\xb1"], "x" => [126, "\xb1"], "y" => [129, "\xb1"], "z" => [143, "\xb1"], "{" => [148, "\xb1"], "|" => [151, "\xb1"], "}" => [153, "\xb1"], "~" => [83, "\xb1"], "" => [10, "\xb1"], "\x80" => [77, "\xb30"], "\x81" => [18, "\xb30"], "\x82" => [77, "\xb31"], "\x83" => [18, "\xb31"], "\x84" => [77, "\xb32"], "\x85" => [18, "\xb32"], "\x86" => [77, "\xb3a"], "\x87" => [18, "\xb3a"], "\x88" => [77, "\xb3c"], "\x89" => [18, "\xb3c"], "\x8a" => [77, "\xb3e"], "\x8b" => [18, "\xb3e"], "\x8c" => [77, "\xb3i"], "\x8d" => [18, "\xb3i"], "\x8e" => [77, "\xb3o"], "\x8f" => [18, "\xb3o"], "\x90" => [77, "\xb3s"], "\x91" => [18, "\xb3s"], "\x92" => [77, "\xb3t"], "\x93" => [18, "\xb3t"], "\x94" => [0, "\xb3 "], "\x95" => [0, "\xb3%"], "\x96" => [0, "\xb3-"], "\x97" => [0, "\xb3."], "\x98" => [0, "\xb3/"], "\x99" => [0, "\xb33"], "\x9a" => [0, "\xb34"], "\x9b" => [0, "\xb35"], "\x9c" => [0, "\xb36"], "\x9d" => [0, "\xb37"], "\x9e" => [0, "\xb38"], "\x9f" => [0, "\xb39"], "\xa0" => [0, "\xb3="], "\xa1" => [0, "\xb3A"], "\xa2" => [0, "\xb3_"], "\xa3" => [0, "\xb3b"], "\xa4" => [0, "\xb3d"], "\xa5" => [0, "\xb3f"], "\xa6" => [0, "\xb3g"], "\xa7" => [0, "\xb3h"], "\xa8" => [0, "\xb3l"], "\xa9" => [0, "\xb3m"], "\xaa" => [0, "\xb3n"], "\xab" => [0, "\xb3p"], "\xac" => [0, "\xb3r"], "\xad" => [0, "\xb3u"], "\xae" => [100, "\xb3"], "\xaf" => [110, "\xb3"], "\xb0" => [111, "\xb3"], "\xb1" => [115, "\xb3"], "\xb2" => [116, "\xb3"], "\xb3" => [118, "\xb3"], "\xb4" => [119, "\xb3"], "\xb5" => [122, "\xb3"], "\xb6" => [123, "\xb3"], "\xb7" => [125, "\xb3"], "\xb8" => [126, "\xb3"], "\xb9" => [129, "\xb3"], "\xba" => [143, "\xb3"], "\xbb" => [148, "\xb3"], "\xbc" => [151, "\xb3"], "\xbd" => [153, "\xb3"], "\xbe" => [83, "\xb3"], "\xbf" => [10, "\xb3"], "\xc0" => [77, "\xd10"], "\xc1" => [18, "\xd10"], "\xc2" => [77, "\xd11"], "\xc3" => [18, "\xd11"], "\xc4" => [77, "\xd12"], "\xc5" => [18, "\xd12"], "\xc6" => [77, "\xd1a"], "\xc7" => [18, "\xd1a"], "\xc8" => [77, "\xd1c"], "\xc9" => [18, "\xd1c"], "\xca" => [77, "\xd1e"], "\xcb" => [18, "\xd1e"], "\xcc" => [77, "\xd1i"], "\xcd" => [18, "\xd1i"], "\xce" => [77, "\xd1o"], "\xcf" => [18, "\xd1o"], "\xd0" => [77, "\xd1s"], "\xd1" => [18, "\xd1s"], "\xd2" => [77, "\xd1t"], "\xd3" => [18, "\xd1t"], "\xd4" => [0, "\xd1 "], "\xd5" => [0, "\xd1%"], "\xd6" => [0, "\xd1-"], "\xd7" => [0, "\xd1."], "\xd8" => [0, "\xd1/"], "\xd9" => [0, "\xd13"], "\xda" => [0, "\xd14"], "\xdb" => [0, "\xd15"], "\xdc" => [0, "\xd16"], "\xdd" => [0, "\xd17"], "\xde" => [0, "\xd18"], "\xdf" => [0, "\xd19"], "\xe0" => [0, "\xd1="], "\xe1" => [0, "\xd1A"], "\xe2" => [0, "\xd1_"], "\xe3" => [0, "\xd1b"], "\xe4" => [0, "\xd1d"], "\xe5" => [0, "\xd1f"], "\xe6" => [0, "\xd1g"], "\xe7" => [0, "\xd1h"], "\xe8" => [0, "\xd1l"], "\xe9" => [0, "\xd1m"], "\xea" => [0, "\xd1n"], "\xeb" => [0, "\xd1p"], "\xec" => [0, "\xd1r"], "\xed" => [0, "\xd1u"], "\xee" => [100, "\xd1"], "\xef" => [110, "\xd1"], "\xf0" => [111, "\xd1"], "\xf1" => [115, "\xd1"], "\xf2" => [116, "\xd1"], "\xf3" => [118, "\xd1"], "\xf4" => [119, "\xd1"], "\xf5" => [122, "\xd1"], "\xf6" => [123, "\xd1"], "\xf7" => [125, "\xd1"], "\xf8" => [126, "\xd1"], "\xf9" => [129, "\xd1"], "\xfa" => [143, "\xd1"], "\xfb" => [148, "\xd1"], "\xfc" => [151, "\xd1"], "\xfd" => [153, "\xd1"], "\xfe" => [83, "\xd1"], "\xff" => [10, "\xd1"]], ["\x00" => [0, "\xb00"], "\x01" => [0, "\xb01"], "\x02" => [0, "\xb02"], "\x03" => [0, "\xb0a"], "\x04" => [0, "\xb0c"], "\x05" => [0, "\xb0e"], "\x06" => [0, "\xb0i"], "\x07" => [0, "\xb0o"], "\x08" => [0, "\xb0s"], "\t" => [0, "\xb0t"], "\n" => [73, "\xb0"], "\v" => [88, "\xb0"], "\f" => [89, "\xb0"], "\r" => [96, "\xb0"], "\x0e" => [97, "\xb0"], "\x0f" => [99, "\xb0"], "\x10" => [106, "\xb0"], "\x11" => [136, "\xb0"], "\x12" => [139, "\xb0"], "\x13" => [141, "\xb0"], "\x14" => [145, "\xb0"], "\x15" => [147, "\xb0"], "\x16" => [149, "\xb0"], "\x17" => [101, "\xb0"], "\x18" => [112, "\xb0"], "\x19" => [117, "\xb0"], "\x1a" => [120, "\xb0"], "\x1b" => [124, "\xb0"], "\x1c" => [127, "\xb0"], "\x1d" => [144, "\xb0"], "\x1e" => [152, "\xb0"], "\x1f" => [11, "\xb0"], " " => [0, "\xb10"], "!" => [0, "\xb11"], "\"" => [0, "\xb12"], "#" => [0, "\xb1a"], "\$" => [0, "\xb1c"], "%" => [0, "\xb1e"], "&" => [0, "\xb1i"], "'" => [0, "\xb1o"], "(" => [0, "\xb1s"], ")" => [0, "\xb1t"], "*" => [73, "\xb1"], "+" => [88, "\xb1"], "," => [89, "\xb1"], "-" => [96, "\xb1"], "." => [97, "\xb1"], "/" => [99, "\xb1"], [106, "\xb1"], [136, "\xb1"], [139, "\xb1"], [141, "\xb1"], [145, "\xb1"], [147, "\xb1"], [149, "\xb1"], [101, "\xb1"], [112, "\xb1"], [117, "\xb1"], ":" => [120, "\xb1"], ";" => [124, "\xb1"], "<" => [127, "\xb1"], "=" => [144, "\xb1"], ">" => [152, "\xb1"], "?" => [11, "\xb1"], "@" => [0, "\xb30"], "A" => [0, "\xb31"], "B" => [0, "\xb32"], "C" => [0, "\xb3a"], "D" => [0, "\xb3c"], "E" => [0, "\xb3e"], "F" => [0, "\xb3i"], "G" => [0, "\xb3o"], "H" => [0, "\xb3s"], "I" => [0, "\xb3t"], "J" => [73, "\xb3"], "K" => [88, "\xb3"], "L" => [89, "\xb3"], "M" => [96, "\xb3"], "N" => [97, "\xb3"], "O" => [99, "\xb3"], "P" => [106, "\xb3"], "Q" => [136, "\xb3"], "R" => [139, "\xb3"], "S" => [141, "\xb3"], "T" => [145, "\xb3"], "U" => [147, "\xb3"], "V" => [149, "\xb3"], "W" => [101, "\xb3"], "X" => [112, "\xb3"], "Y" => [117, "\xb3"], "Z" => [120, "\xb3"], "[" => [124, "\xb3"], "\\" => [127, "\xb3"], "]" => [144, "\xb3"], "^" => [152, "\xb3"], "_" => [11, "\xb3"], "`" => [0, "\xd10"], "a" => [0, "\xd11"], "b" => [0, "\xd12"], "c" => [0, "\xd1a"], "d" => [0, "\xd1c"], "e" => [0, "\xd1e"], "f" => [0, "\xd1i"], "g" => [0, "\xd1o"], "h" => [0, "\xd1s"], "i" => [0, "\xd1t"], "j" => [73, "\xd1"], "k" => [88, "\xd1"], "l" => [89, "\xd1"], "m" => [96, "\xd1"], "n" => [97, "\xd1"], "o" => [99, "\xd1"], "p" => [106, "\xd1"], "q" => [136, "\xd1"], "r" => [139, "\xd1"], "s" => [141, "\xd1"], "t" => [145, "\xd1"], "u" => [147, "\xd1"], "v" => [149, "\xd1"], "w" => [101, "\xd1"], "x" => [112, "\xd1"], "y" => [117, "\xd1"], "z" => [120, "\xd1"], "{" => [124, "\xd1"], "|" => [127, "\xd1"], "}" => [144, "\xd1"], "~" => [152, "\xd1"], "" => [11, "\xd1"], "\x80" => [0, "\xd80"], "\x81" => [0, "\xd81"], "\x82" => [0, "\xd82"], "\x83" => [0, "\xd8a"], "\x84" => [0, "\xd8c"], "\x85" => [0, "\xd8e"], "\x86" => [0, "\xd8i"], "\x87" => [0, "\xd8o"], "\x88" => [0, "\xd8s"], "\x89" => [0, "\xd8t"], "\x8a" => [73, "\xd8"], "\x8b" => [88, "\xd8"], "\x8c" => [89, "\xd8"], "\x8d" => [96, "\xd8"], "\x8e" => [97, "\xd8"], "\x8f" => [99, "\xd8"], "\x90" => [106, "\xd8"], "\x91" => [136, "\xd8"], "\x92" => [139, "\xd8"], "\x93" => [141, "\xd8"], "\x94" => [145, "\xd8"], "\x95" => [147, "\xd8"], "\x96" => [149, "\xd8"], "\x97" => [101, "\xd8"], "\x98" => [112, "\xd8"], "\x99" => [117, "\xd8"], "\x9a" => [120, "\xd8"], "\x9b" => [124, "\xd8"], "\x9c" => [127, "\xd8"], "\x9d" => [144, "\xd8"], "\x9e" => [152, "\xd8"], "\x9f" => [11, "\xd8"], "\xa0" => [0, "\xd90"], "\xa1" => [0, "\xd91"], "\xa2" => [0, "\xd92"], "\xa3" => [0, "\xd9a"], "\xa4" => [0, "\xd9c"], "\xa5" => [0, "\xd9e"], "\xa6" => [0, "\xd9i"], "\xa7" => [0, "\xd9o"], "\xa8" => [0, "\xd9s"], "\xa9" => [0, "\xd9t"], "\xaa" => [73, "\xd9"], "\xab" => [88, "\xd9"], "\xac" => [89, "\xd9"], "\xad" => [96, "\xd9"], "\xae" => [97, "\xd9"], "\xaf" => [99, "\xd9"], "\xb0" => [106, "\xd9"], "\xb1" => [136, "\xd9"], "\xb2" => [139, "\xd9"], "\xb3" => [141, "\xd9"], "\xb4" => [145, "\xd9"], "\xb5" => [147, "\xd9"], "\xb6" => [149, "\xd9"], "\xb7" => [101, "\xd9"], "\xb8" => [112, "\xd9"], "\xb9" => [117, "\xd9"], "\xba" => [120, "\xd9"], "\xbb" => [124, "\xd9"], "\xbc" => [127, "\xd9"], "\xbd" => [144, "\xd9"], "\xbe" => [152, "\xd9"], "\xbf" => [11, "\xd9"], "\xc0" => [0, "\xe30"], "\xc1" => [0, "\xe31"], "\xc2" => [0, "\xe32"], "\xc3" => [0, "\xe3a"], "\xc4" => [0, "\xe3c"], "\xc5" => [0, "\xe3e"], "\xc6" => [0, "\xe3i"], "\xc7" => [0, "\xe3o"], "\xc8" => [0, "\xe3s"], "\xc9" => [0, "\xe3t"], "\xca" => [73, "\xe3"], "\xcb" => [88, "\xe3"], "\xcc" => [89, "\xe3"], "\xcd" => [96, "\xe3"], "\xce" => [97, "\xe3"], "\xcf" => [99, "\xe3"], "\xd0" => [106, "\xe3"], "\xd1" => [136, "\xe3"], "\xd2" => [139, "\xe3"], "\xd3" => [141, "\xe3"], "\xd4" => [145, "\xe3"], "\xd5" => [147, "\xe3"], "\xd6" => [149, "\xe3"], "\xd7" => [101, "\xe3"], "\xd8" => [112, "\xe3"], "\xd9" => [117, "\xe3"], "\xda" => [120, "\xe3"], "\xdb" => [124, "\xe3"], "\xdc" => [127, "\xe3"], "\xdd" => [144, "\xe3"], "\xde" => [152, "\xe3"], "\xdf" => [11, "\xe3"], "\xe0" => [0, "\xe50"], "\xe1" => [0, "\xe51"], "\xe2" => [0, "\xe52"], "\xe3" => [0, "\xe5a"], "\xe4" => [0, "\xe5c"], "\xe5" => [0, "\xe5e"], "\xe6" => [0, "\xe5i"], "\xe7" => [0, "\xe5o"], "\xe8" => [0, "\xe5s"], "\xe9" => [0, "\xe5t"], "\xea" => [73, "\xe5"], "\xeb" => [88, "\xe5"], "\xec" => [89, "\xe5"], "\xed" => [96, "\xe5"], "\xee" => [97, "\xe5"], "\xef" => [99, "\xe5"], "\xf0" => [106, "\xe5"], "\xf1" => [136, "\xe5"], "\xf2" => [139, "\xe5"], "\xf3" => [141, "\xe5"], "\xf4" => [145, "\xe5"], "\xf5" => [147, "\xe5"], "\xf6" => [149, "\xe5"], "\xf7" => [101, "\xe5"], "\xf8" => [112, "\xe5"], "\xf9" => [117, "\xe5"], "\xfa" => [120, "\xe5"], "\xfb" => [124, "\xe5"], "\xfc" => [127, "\xe5"], "\xfd" => [144, "\xe5"], "\xfe" => [152, "\xe5"], "\xff" => [11, "\xe5"]], ["\x00" => [94, "\xb20"], "\x01" => [76, "\xb20"], "\x02" => [104, "\xb20"], "\x03" => [16, "\xb20"], "\x04" => [94, "\xb21"], "\x05" => [76, "\xb21"], "\x06" => [104, "\xb21"], "\x07" => [16, "\xb21"], "\x08" => [94, "\xb22"], "\t" => [76, "\xb22"], "\n" => [104, "\xb22"], "\v" => [16, "\xb22"], "\f" => [94, "\xb2a"], "\r" => [76, "\xb2a"], "\x0e" => [104, "\xb2a"], "\x0f" => [16, "\xb2a"], "\x10" => [94, "\xb2c"], "\x11" => [76, "\xb2c"], "\x12" => [104, "\xb2c"], "\x13" => [16, "\xb2c"], "\x14" => [94, "\xb2e"], "\x15" => [76, "\xb2e"], "\x16" => [104, "\xb2e"], "\x17" => [16, "\xb2e"], "\x18" => [94, "\xb2i"], "\x19" => [76, "\xb2i"], "\x1a" => [104, "\xb2i"], "\x1b" => [16, "\xb2i"], "\x1c" => [94, "\xb2o"], "\x1d" => [76, "\xb2o"], "\x1e" => [104, "\xb2o"], "\x1f" => [16, "\xb2o"], " " => [94, "\xb2s"], "!" => [76, "\xb2s"], "\"" => [104, "\xb2s"], "#" => [16, "\xb2s"], "\$" => [94, "\xb2t"], "%" => [76, "\xb2t"], "&" => [104, "\xb2t"], "'" => [16, "\xb2t"], "(" => [77, "\xb2 "], ")" => [18, "\xb2 "], "*" => [77, "\xb2%"], "+" => [18, "\xb2%"], "," => [77, "\xb2-"], "-" => [18, "\xb2-"], "." => [77, "\xb2."], "/" => [18, "\xb2."], [77, "\xb2/"], [18, "\xb2/"], [77, "\xb23"], [18, "\xb23"], [77, "\xb24"], [18, "\xb24"], [77, "\xb25"], [18, "\xb25"], [77, "\xb26"], [18, "\xb26"], ":" => [77, "\xb27"], ";" => [18, "\xb27"], "<" => [77, "\xb28"], "=" => [18, "\xb28"], ">" => [77, "\xb29"], "?" => [18, "\xb29"], "@" => [77, "\xb2="], "A" => [18, "\xb2="], "B" => [77, "\xb2A"], "C" => [18, "\xb2A"], "D" => [77, "\xb2_"], "E" => [18, "\xb2_"], "F" => [77, "\xb2b"], "G" => [18, "\xb2b"], "H" => [77, "\xb2d"], "I" => [18, "\xb2d"], "J" => [77, "\xb2f"], "K" => [18, "\xb2f"], "L" => [77, "\xb2g"], "M" => [18, "\xb2g"], "N" => [77, "\xb2h"], "O" => [18, "\xb2h"], "P" => [77, "\xb2l"], "Q" => [18, "\xb2l"], "R" => [77, "\xb2m"], "S" => [18, "\xb2m"], "T" => [77, "\xb2n"], "U" => [18, "\xb2n"], "V" => [77, "\xb2p"], "W" => [18, "\xb2p"], "X" => [77, "\xb2r"], "Y" => [18, "\xb2r"], "Z" => [77, "\xb2u"], "[" => [18, "\xb2u"], "\\" => [0, "\xb2:"], "]" => [0, "\xb2B"], "^" => [0, "\xb2C"], "_" => [0, "\xb2D"], "`" => [0, "\xb2E"], "a" => [0, "\xb2F"], "b" => [0, "\xb2G"], "c" => [0, "\xb2H"], "d" => [0, "\xb2I"], "e" => [0, "\xb2J"], "f" => [0, "\xb2K"], "g" => [0, "\xb2L"], "h" => [0, "\xb2M"], "i" => [0, "\xb2N"], "j" => [0, "\xb2O"], "k" => [0, "\xb2P"], "l" => [0, "\xb2Q"], "m" => [0, "\xb2R"], "n" => [0, "\xb2S"], "o" => [0, "\xb2T"], "p" => [0, "\xb2U"], "q" => [0, "\xb2V"], "r" => [0, "\xb2W"], "s" => [0, "\xb2Y"], "t" => [0, "\xb2j"], "u" => [0, "\xb2k"], "v" => [0, "\xb2q"], "w" => [0, "\xb2v"], "x" => [0, "\xb2w"], "y" => [0, "\xb2x"], "z" => [0, "\xb2y"], "{" => [0, "\xb2z"], "|" => [82, "\xb2"], "}" => [87, "\xb2"], "~" => [130, "\xb2"], "" => [9, "\xb2"], "\x80" => [94, "\xb50"], "\x81" => [76, "\xb50"], "\x82" => [104, "\xb50"], "\x83" => [16, "\xb50"], "\x84" => [94, "\xb51"], "\x85" => [76, "\xb51"], "\x86" => [104, "\xb51"], "\x87" => [16, "\xb51"], "\x88" => [94, "\xb52"], "\x89" => [76, "\xb52"], "\x8a" => [104, "\xb52"], "\x8b" => [16, "\xb52"], "\x8c" => [94, "\xb5a"], "\x8d" => [76, "\xb5a"], "\x8e" => [104, "\xb5a"], "\x8f" => [16, "\xb5a"], "\x90" => [94, "\xb5c"], "\x91" => [76, "\xb5c"], "\x92" => [104, "\xb5c"], "\x93" => [16, "\xb5c"], "\x94" => [94, "\xb5e"], "\x95" => [76, "\xb5e"], "\x96" => [104, "\xb5e"], "\x97" => [16, "\xb5e"], "\x98" => [94, "\xb5i"], "\x99" => [76, "\xb5i"], "\x9a" => [104, "\xb5i"], "\x9b" => [16, "\xb5i"], "\x9c" => [94, "\xb5o"], "\x9d" => [76, "\xb5o"], "\x9e" => [104, "\xb5o"], "\x9f" => [16, "\xb5o"], "\xa0" => [94, "\xb5s"], "\xa1" => [76, "\xb5s"], "\xa2" => [104, "\xb5s"], "\xa3" => [16, "\xb5s"], "\xa4" => [94, "\xb5t"], "\xa5" => [76, "\xb5t"], "\xa6" => [104, "\xb5t"], "\xa7" => [16, "\xb5t"], "\xa8" => [77, "\xb5 "], "\xa9" => [18, "\xb5 "], "\xaa" => [77, "\xb5%"], "\xab" => [18, "\xb5%"], "\xac" => [77, "\xb5-"], "\xad" => [18, "\xb5-"], "\xae" => [77, "\xb5."], "\xaf" => [18, "\xb5."], "\xb0" => [77, "\xb5/"], "\xb1" => [18, "\xb5/"], "\xb2" => [77, "\xb53"], "\xb3" => [18, "\xb53"], "\xb4" => [77, "\xb54"], "\xb5" => [18, "\xb54"], "\xb6" => [77, "\xb55"], "\xb7" => [18, "\xb55"], "\xb8" => [77, "\xb56"], "\xb9" => [18, "\xb56"], "\xba" => [77, "\xb57"], "\xbb" => [18, "\xb57"], "\xbc" => [77, "\xb58"], "\xbd" => [18, "\xb58"], "\xbe" => [77, "\xb59"], "\xbf" => [18, "\xb59"], "\xc0" => [77, "\xb5="], "\xc1" => [18, "\xb5="], "\xc2" => [77, "\xb5A"], "\xc3" => [18, "\xb5A"], "\xc4" => [77, "\xb5_"], "\xc5" => [18, "\xb5_"], "\xc6" => [77, "\xb5b"], "\xc7" => [18, "\xb5b"], "\xc8" => [77, "\xb5d"], "\xc9" => [18, "\xb5d"], "\xca" => [77, "\xb5f"], "\xcb" => [18, "\xb5f"], "\xcc" => [77, "\xb5g"], "\xcd" => [18, "\xb5g"], "\xce" => [77, "\xb5h"], "\xcf" => [18, "\xb5h"], "\xd0" => [77, "\xb5l"], "\xd1" => [18, "\xb5l"], "\xd2" => [77, "\xb5m"], "\xd3" => [18, "\xb5m"], "\xd4" => [77, "\xb5n"], "\xd5" => [18, "\xb5n"], "\xd6" => [77, "\xb5p"], "\xd7" => [18, "\xb5p"], "\xd8" => [77, "\xb5r"], "\xd9" => [18, "\xb5r"], "\xda" => [77, "\xb5u"], "\xdb" => [18, "\xb5u"], "\xdc" => [0, "\xb5:"], "\xdd" => [0, "\xb5B"], "\xde" => [0, "\xb5C"], "\xdf" => [0, "\xb5D"], "\xe0" => [0, "\xb5E"], "\xe1" => [0, "\xb5F"], "\xe2" => [0, "\xb5G"], "\xe3" => [0, "\xb5H"], "\xe4" => [0, "\xb5I"], "\xe5" => [0, "\xb5J"], "\xe6" => [0, "\xb5K"], "\xe7" => [0, "\xb5L"], "\xe8" => [0, "\xb5M"], "\xe9" => [0, "\xb5N"], "\xea" => [0, "\xb5O"], "\xeb" => [0, "\xb5P"], "\xec" => [0, "\xb5Q"], "\xed" => [0, "\xb5R"], "\xee" => [0, "\xb5S"], "\xef" => [0, "\xb5T"], "\xf0" => [0, "\xb5U"], "\xf1" => [0, "\xb5V"], "\xf2" => [0, "\xb5W"], "\xf3" => [0, "\xb5Y"], "\xf4" => [0, "\xb5j"], "\xf5" => [0, "\xb5k"], "\xf6" => [0, "\xb5q"], "\xf7" => [0, "\xb5v"], "\xf8" => [0, "\xb5w"], "\xf9" => [0, "\xb5x"], "\xfa" => [0, "\xb5y"], "\xfb" => [0, "\xb5z"], "\xfc" => [82, "\xb5"], "\xfd" => [87, "\xb5"], "\xfe" => [130, "\xb5"], "\xff" => [9, "\xb5"]], ["\x00" => [77, "\xb20"], "\x01" => [18, "\xb20"], "\x02" => [77, "\xb21"], "\x03" => [18, "\xb21"], "\x04" => [77, "\xb22"], "\x05" => [18, "\xb22"], "\x06" => [77, "\xb2a"], "\x07" => [18, "\xb2a"], "\x08" => [77, "\xb2c"], "\t" => [18, "\xb2c"], "\n" => [77, "\xb2e"], "\v" => [18, "\xb2e"], "\f" => [77, "\xb2i"], "\r" => [18, "\xb2i"], "\x0e" => [77, "\xb2o"], "\x0f" => [18, "\xb2o"], "\x10" => [77, "\xb2s"], "\x11" => [18, "\xb2s"], "\x12" => [77, "\xb2t"], "\x13" => [18, "\xb2t"], "\x14" => [0, "\xb2 "], "\x15" => [0, "\xb2%"], "\x16" => [0, "\xb2-"], "\x17" => [0, "\xb2."], "\x18" => [0, "\xb2/"], "\x19" => [0, "\xb23"], "\x1a" => [0, "\xb24"], "\x1b" => [0, "\xb25"], "\x1c" => [0, "\xb26"], "\x1d" => [0, "\xb27"], "\x1e" => [0, "\xb28"], "\x1f" => [0, "\xb29"], " " => [0, "\xb2="], "!" => [0, "\xb2A"], "\"" => [0, "\xb2_"], "#" => [0, "\xb2b"], "\$" => [0, "\xb2d"], "%" => [0, "\xb2f"], "&" => [0, "\xb2g"], "'" => [0, "\xb2h"], "(" => [0, "\xb2l"], ")" => [0, "\xb2m"], "*" => [0, "\xb2n"], "+" => [0, "\xb2p"], "," => [0, "\xb2r"], "-" => [0, "\xb2u"], "." => [100, "\xb2"], "/" => [110, "\xb2"], [111, "\xb2"], [115, "\xb2"], [116, "\xb2"], [118, "\xb2"], [119, "\xb2"], [122, "\xb2"], [123, "\xb2"], [125, "\xb2"], [126, "\xb2"], [129, "\xb2"], ":" => [143, "\xb2"], ";" => [148, "\xb2"], "<" => [151, "\xb2"], "=" => [153, "\xb2"], ">" => [83, "\xb2"], "?" => [10, "\xb2"], "@" => [77, "\xb50"], "A" => [18, "\xb50"], "B" => [77, "\xb51"], "C" => [18, "\xb51"], "D" => [77, "\xb52"], "E" => [18, "\xb52"], "F" => [77, "\xb5a"], "G" => [18, "\xb5a"], "H" => [77, "\xb5c"], "I" => [18, "\xb5c"], "J" => [77, "\xb5e"], "K" => [18, "\xb5e"], "L" => [77, "\xb5i"], "M" => [18, "\xb5i"], "N" => [77, "\xb5o"], "O" => [18, "\xb5o"], "P" => [77, "\xb5s"], "Q" => [18, "\xb5s"], "R" => [77, "\xb5t"], "S" => [18, "\xb5t"], "T" => [0, "\xb5 "], "U" => [0, "\xb5%"], "V" => [0, "\xb5-"], "W" => [0, "\xb5."], "X" => [0, "\xb5/"], "Y" => [0, "\xb53"], "Z" => [0, "\xb54"], "[" => [0, "\xb55"], "\\" => [0, "\xb56"], "]" => [0, "\xb57"], "^" => [0, "\xb58"], "_" => [0, "\xb59"], "`" => [0, "\xb5="], "a" => [0, "\xb5A"], "b" => [0, "\xb5_"], "c" => [0, "\xb5b"], "d" => [0, "\xb5d"], "e" => [0, "\xb5f"], "f" => [0, "\xb5g"], "g" => [0, "\xb5h"], "h" => [0, "\xb5l"], "i" => [0, "\xb5m"], "j" => [0, "\xb5n"], "k" => [0, "\xb5p"], "l" => [0, "\xb5r"], "m" => [0, "\xb5u"], "n" => [100, "\xb5"], "o" => [110, "\xb5"], "p" => [111, "\xb5"], "q" => [115, "\xb5"], "r" => [116, "\xb5"], "s" => [118, "\xb5"], "t" => [119, "\xb5"], "u" => [122, "\xb5"], "v" => [123, "\xb5"], "w" => [125, "\xb5"], "x" => [126, "\xb5"], "y" => [129, "\xb5"], "z" => [143, "\xb5"], "{" => [148, "\xb5"], "|" => [151, "\xb5"], "}" => [153, "\xb5"], "~" => [83, "\xb5"], "" => [10, "\xb5"], "\x80" => [77, "\xb90"], "\x81" => [18, "\xb90"], "\x82" => [77, "\xb91"], "\x83" => [18, "\xb91"], "\x84" => [77, "\xb92"], "\x85" => [18, "\xb92"], "\x86" => [77, "\xb9a"], "\x87" => [18, "\xb9a"], "\x88" => [77, "\xb9c"], "\x89" => [18, "\xb9c"], "\x8a" => [77, "\xb9e"], "\x8b" => [18, "\xb9e"], "\x8c" => [77, "\xb9i"], "\x8d" => [18, "\xb9i"], "\x8e" => [77, "\xb9o"], "\x8f" => [18, "\xb9o"], "\x90" => [77, "\xb9s"], "\x91" => [18, "\xb9s"], "\x92" => [77, "\xb9t"], "\x93" => [18, "\xb9t"], "\x94" => [0, "\xb9 "], "\x95" => [0, "\xb9%"], "\x96" => [0, "\xb9-"], "\x97" => [0, "\xb9."], "\x98" => [0, "\xb9/"], "\x99" => [0, "\xb93"], "\x9a" => [0, "\xb94"], "\x9b" => [0, "\xb95"], "\x9c" => [0, "\xb96"], "\x9d" => [0, "\xb97"], "\x9e" => [0, "\xb98"], "\x9f" => [0, "\xb99"], "\xa0" => [0, "\xb9="], "\xa1" => [0, "\xb9A"], "\xa2" => [0, "\xb9_"], "\xa3" => [0, "\xb9b"], "\xa4" => [0, "\xb9d"], "\xa5" => [0, "\xb9f"], "\xa6" => [0, "\xb9g"], "\xa7" => [0, "\xb9h"], "\xa8" => [0, "\xb9l"], "\xa9" => [0, "\xb9m"], "\xaa" => [0, "\xb9n"], "\xab" => [0, "\xb9p"], "\xac" => [0, "\xb9r"], "\xad" => [0, "\xb9u"], "\xae" => [100, "\xb9"], "\xaf" => [110, "\xb9"], "\xb0" => [111, "\xb9"], "\xb1" => [115, "\xb9"], "\xb2" => [116, "\xb9"], "\xb3" => [118, "\xb9"], "\xb4" => [119, "\xb9"], "\xb5" => [122, "\xb9"], "\xb6" => [123, "\xb9"], "\xb7" => [125, "\xb9"], "\xb8" => [126, "\xb9"], "\xb9" => [129, "\xb9"], "\xba" => [143, "\xb9"], "\xbb" => [148, "\xb9"], "\xbc" => [151, "\xb9"], "\xbd" => [153, "\xb9"], "\xbe" => [83, "\xb9"], "\xbf" => [10, "\xb9"], "\xc0" => [77, "\xba0"], "\xc1" => [18, "\xba0"], "\xc2" => [77, "\xba1"], "\xc3" => [18, "\xba1"], "\xc4" => [77, "\xba2"], "\xc5" => [18, "\xba2"], "\xc6" => [77, "\xbaa"], "\xc7" => [18, "\xbaa"], "\xc8" => [77, "\xbac"], "\xc9" => [18, "\xbac"], "\xca" => [77, "\xbae"], "\xcb" => [18, "\xbae"], "\xcc" => [77, "\xbai"], "\xcd" => [18, "\xbai"], "\xce" => [77, "\xbao"], "\xcf" => [18, "\xbao"], "\xd0" => [77, "\xbas"], "\xd1" => [18, "\xbas"], "\xd2" => [77, "\xbat"], "\xd3" => [18, "\xbat"], "\xd4" => [0, "\xba "], "\xd5" => [0, "\xba%"], "\xd6" => [0, "\xba-"], "\xd7" => [0, "\xba."], "\xd8" => [0, "\xba/"], "\xd9" => [0, "\xba3"], "\xda" => [0, "\xba4"], "\xdb" => [0, "\xba5"], "\xdc" => [0, "\xba6"], "\xdd" => [0, "\xba7"], "\xde" => [0, "\xba8"], "\xdf" => [0, "\xba9"], "\xe0" => [0, "\xba="], "\xe1" => [0, "\xbaA"], "\xe2" => [0, "\xba_"], "\xe3" => [0, "\xbab"], "\xe4" => [0, "\xbad"], "\xe5" => [0, "\xbaf"], "\xe6" => [0, "\xbag"], "\xe7" => [0, "\xbah"], "\xe8" => [0, "\xbal"], "\xe9" => [0, "\xbam"], "\xea" => [0, "\xban"], "\xeb" => [0, "\xbap"], "\xec" => [0, "\xbar"], "\xed" => [0, "\xbau"], "\xee" => [100, "\xba"], "\xef" => [110, "\xba"], "\xf0" => [111, "\xba"], "\xf1" => [115, "\xba"], "\xf2" => [116, "\xba"], "\xf3" => [118, "\xba"], "\xf4" => [119, "\xba"], "\xf5" => [122, "\xba"], "\xf6" => [123, "\xba"], "\xf7" => [125, "\xba"], "\xf8" => [126, "\xba"], "\xf9" => [129, "\xba"], "\xfa" => [143, "\xba"], "\xfb" => [148, "\xba"], "\xfc" => [151, "\xba"], "\xfd" => [153, "\xba"], "\xfe" => [83, "\xba"], "\xff" => [10, "\xba"]], ["\x00" => [0, "\xb20"], "\x01" => [0, "\xb21"], "\x02" => [0, "\xb22"], "\x03" => [0, "\xb2a"], "\x04" => [0, "\xb2c"], "\x05" => [0, "\xb2e"], "\x06" => [0, "\xb2i"], "\x07" => [0, "\xb2o"], "\x08" => [0, "\xb2s"], "\t" => [0, "\xb2t"], "\n" => [73, "\xb2"], "\v" => [88, "\xb2"], "\f" => [89, "\xb2"], "\r" => [96, "\xb2"], "\x0e" => [97, "\xb2"], "\x0f" => [99, "\xb2"], "\x10" => [106, "\xb2"], "\x11" => [136, "\xb2"], "\x12" => [139, "\xb2"], "\x13" => [141, "\xb2"], "\x14" => [145, "\xb2"], "\x15" => [147, "\xb2"], "\x16" => [149, "\xb2"], "\x17" => [101, "\xb2"], "\x18" => [112, "\xb2"], "\x19" => [117, "\xb2"], "\x1a" => [120, "\xb2"], "\x1b" => [124, "\xb2"], "\x1c" => [127, "\xb2"], "\x1d" => [144, "\xb2"], "\x1e" => [152, "\xb2"], "\x1f" => [11, "\xb2"], " " => [0, "\xb50"], "!" => [0, "\xb51"], "\"" => [0, "\xb52"], "#" => [0, "\xb5a"], "\$" => [0, "\xb5c"], "%" => [0, "\xb5e"], "&" => [0, "\xb5i"], "'" => [0, "\xb5o"], "(" => [0, "\xb5s"], ")" => [0, "\xb5t"], "*" => [73, "\xb5"], "+" => [88, "\xb5"], "," => [89, "\xb5"], "-" => [96, "\xb5"], "." => [97, "\xb5"], "/" => [99, "\xb5"], [106, "\xb5"], [136, "\xb5"], [139, "\xb5"], [141, "\xb5"], [145, "\xb5"], [147, "\xb5"], [149, "\xb5"], [101, "\xb5"], [112, "\xb5"], [117, "\xb5"], ":" => [120, "\xb5"], ";" => [124, "\xb5"], "<" => [127, "\xb5"], "=" => [144, "\xb5"], ">" => [152, "\xb5"], "?" => [11, "\xb5"], "@" => [0, "\xb90"], "A" => [0, "\xb91"], "B" => [0, "\xb92"], "C" => [0, "\xb9a"], "D" => [0, "\xb9c"], "E" => [0, "\xb9e"], "F" => [0, "\xb9i"], "G" => [0, "\xb9o"], "H" => [0, "\xb9s"], "I" => [0, "\xb9t"], "J" => [73, "\xb9"], "K" => [88, "\xb9"], "L" => [89, "\xb9"], "M" => [96, "\xb9"], "N" => [97, "\xb9"], "O" => [99, "\xb9"], "P" => [106, "\xb9"], "Q" => [136, "\xb9"], "R" => [139, "\xb9"], "S" => [141, "\xb9"], "T" => [145, "\xb9"], "U" => [147, "\xb9"], "V" => [149, "\xb9"], "W" => [101, "\xb9"], "X" => [112, "\xb9"], "Y" => [117, "\xb9"], "Z" => [120, "\xb9"], "[" => [124, "\xb9"], "\\" => [127, "\xb9"], "]" => [144, "\xb9"], "^" => [152, "\xb9"], "_" => [11, "\xb9"], "`" => [0, "\xba0"], "a" => [0, "\xba1"], "b" => [0, "\xba2"], "c" => [0, "\xbaa"], "d" => [0, "\xbac"], "e" => [0, "\xbae"], "f" => [0, "\xbai"], "g" => [0, "\xbao"], "h" => [0, "\xbas"], "i" => [0, "\xbat"], "j" => [73, "\xba"], "k" => [88, "\xba"], "l" => [89, "\xba"], "m" => [96, "\xba"], "n" => [97, "\xba"], "o" => [99, "\xba"], "p" => [106, "\xba"], "q" => [136, "\xba"], "r" => [139, "\xba"], "s" => [141, "\xba"], "t" => [145, "\xba"], "u" => [147, "\xba"], "v" => [149, "\xba"], "w" => [101, "\xba"], "x" => [112, "\xba"], "y" => [117, "\xba"], "z" => [120, "\xba"], "{" => [124, "\xba"], "|" => [127, "\xba"], "}" => [144, "\xba"], "~" => [152, "\xba"], "" => [11, "\xba"], "\x80" => [0, "\xbb0"], "\x81" => [0, "\xbb1"], "\x82" => [0, "\xbb2"], "\x83" => [0, "\xbba"], "\x84" => [0, "\xbbc"], "\x85" => [0, "\xbbe"], "\x86" => [0, "\xbbi"], "\x87" => [0, "\xbbo"], "\x88" => [0, "\xbbs"], "\x89" => [0, "\xbbt"], "\x8a" => [73, "\xbb"], "\x8b" => [88, "\xbb"], "\x8c" => [89, "\xbb"], "\x8d" => [96, "\xbb"], "\x8e" => [97, "\xbb"], "\x8f" => [99, "\xbb"], "\x90" => [106, "\xbb"], "\x91" => [136, "\xbb"], "\x92" => [139, "\xbb"], "\x93" => [141, "\xbb"], "\x94" => [145, "\xbb"], "\x95" => [147, "\xbb"], "\x96" => [149, "\xbb"], "\x97" => [101, "\xbb"], "\x98" => [112, "\xbb"], "\x99" => [117, "\xbb"], "\x9a" => [120, "\xbb"], "\x9b" => [124, "\xbb"], "\x9c" => [127, "\xbb"], "\x9d" => [144, "\xbb"], "\x9e" => [152, "\xbb"], "\x9f" => [11, "\xbb"], "\xa0" => [0, "\xbd0"], "\xa1" => [0, "\xbd1"], "\xa2" => [0, "\xbd2"], "\xa3" => [0, "\xbda"], "\xa4" => [0, "\xbdc"], "\xa5" => [0, "\xbde"], "\xa6" => [0, "\xbdi"], "\xa7" => [0, "\xbdo"], "\xa8" => [0, "\xbds"], "\xa9" => [0, "\xbdt"], "\xaa" => [73, "\xbd"], "\xab" => [88, "\xbd"], "\xac" => [89, "\xbd"], "\xad" => [96, "\xbd"], "\xae" => [97, "\xbd"], "\xaf" => [99, "\xbd"], "\xb0" => [106, "\xbd"], "\xb1" => [136, "\xbd"], "\xb2" => [139, "\xbd"], "\xb3" => [141, "\xbd"], "\xb4" => [145, "\xbd"], "\xb5" => [147, "\xbd"], "\xb6" => [149, "\xbd"], "\xb7" => [101, "\xbd"], "\xb8" => [112, "\xbd"], "\xb9" => [117, "\xbd"], "\xba" => [120, "\xbd"], "\xbb" => [124, "\xbd"], "\xbc" => [127, "\xbd"], "\xbd" => [144, "\xbd"], "\xbe" => [152, "\xbd"], "\xbf" => [11, "\xbd"], "\xc0" => [0, "\xbe0"], "\xc1" => [0, "\xbe1"], "\xc2" => [0, "\xbe2"], "\xc3" => [0, "\xbea"], "\xc4" => [0, "\xbec"], "\xc5" => [0, "\xbee"], "\xc6" => [0, "\xbei"], "\xc7" => [0, "\xbeo"], "\xc8" => [0, "\xbes"], "\xc9" => [0, "\xbet"], "\xca" => [73, "\xbe"], "\xcb" => [88, "\xbe"], "\xcc" => [89, "\xbe"], "\xcd" => [96, "\xbe"], "\xce" => [97, "\xbe"], "\xcf" => [99, "\xbe"], "\xd0" => [106, "\xbe"], "\xd1" => [136, "\xbe"], "\xd2" => [139, "\xbe"], "\xd3" => [141, "\xbe"], "\xd4" => [145, "\xbe"], "\xd5" => [147, "\xbe"], "\xd6" => [149, "\xbe"], "\xd7" => [101, "\xbe"], "\xd8" => [112, "\xbe"], "\xd9" => [117, "\xbe"], "\xda" => [120, "\xbe"], "\xdb" => [124, "\xbe"], "\xdc" => [127, "\xbe"], "\xdd" => [144, "\xbe"], "\xde" => [152, "\xbe"], "\xdf" => [11, "\xbe"], "\xe0" => [0, "\xc40"], "\xe1" => [0, "\xc41"], "\xe2" => [0, "\xc42"], "\xe3" => [0, "\xc4a"], "\xe4" => [0, "\xc4c"], "\xe5" => [0, "\xc4e"], "\xe6" => [0, "\xc4i"], "\xe7" => [0, "\xc4o"], "\xe8" => [0, "\xc4s"], "\xe9" => [0, "\xc4t"], "\xea" => [73, "\xc4"], "\xeb" => [88, "\xc4"], "\xec" => [89, "\xc4"], "\xed" => [96, "\xc4"], "\xee" => [97, "\xc4"], "\xef" => [99, "\xc4"], "\xf0" => [106, "\xc4"], "\xf1" => [136, "\xc4"], "\xf2" => [139, "\xc4"], "\xf3" => [141, "\xc4"], "\xf4" => [145, "\xc4"], "\xf5" => [147, "\xc4"], "\xf6" => [149, "\xc4"], "\xf7" => [101, "\xc4"], "\xf8" => [112, "\xc4"], "\xf9" => [117, "\xc4"], "\xfa" => [120, "\xc4"], "\xfb" => [124, "\xc4"], "\xfc" => [127, "\xc4"], "\xfd" => [144, "\xc4"], "\xfe" => [152, "\xc4"], "\xff" => [11, "\xc4"]], ["\x00" => [94, "\xb30"], "\x01" => [76, "\xb30"], "\x02" => [104, "\xb30"], "\x03" => [16, "\xb30"], "\x04" => [94, "\xb31"], "\x05" => [76, "\xb31"], "\x06" => [104, "\xb31"], "\x07" => [16, "\xb31"], "\x08" => [94, "\xb32"], "\t" => [76, "\xb32"], "\n" => [104, "\xb32"], "\v" => [16, "\xb32"], "\f" => [94, "\xb3a"], "\r" => [76, "\xb3a"], "\x0e" => [104, "\xb3a"], "\x0f" => [16, "\xb3a"], "\x10" => [94, "\xb3c"], "\x11" => [76, "\xb3c"], "\x12" => [104, "\xb3c"], "\x13" => [16, "\xb3c"], "\x14" => [94, "\xb3e"], "\x15" => [76, "\xb3e"], "\x16" => [104, "\xb3e"], "\x17" => [16, "\xb3e"], "\x18" => [94, "\xb3i"], "\x19" => [76, "\xb3i"], "\x1a" => [104, "\xb3i"], "\x1b" => [16, "\xb3i"], "\x1c" => [94, "\xb3o"], "\x1d" => [76, "\xb3o"], "\x1e" => [104, "\xb3o"], "\x1f" => [16, "\xb3o"], " " => [94, "\xb3s"], "!" => [76, "\xb3s"], "\"" => [104, "\xb3s"], "#" => [16, "\xb3s"], "\$" => [94, "\xb3t"], "%" => [76, "\xb3t"], "&" => [104, "\xb3t"], "'" => [16, "\xb3t"], "(" => [77, "\xb3 "], ")" => [18, "\xb3 "], "*" => [77, "\xb3%"], "+" => [18, "\xb3%"], "," => [77, "\xb3-"], "-" => [18, "\xb3-"], "." => [77, "\xb3."], "/" => [18, "\xb3."], [77, "\xb3/"], [18, "\xb3/"], [77, "\xb33"], [18, "\xb33"], [77, "\xb34"], [18, "\xb34"], [77, "\xb35"], [18, "\xb35"], [77, "\xb36"], [18, "\xb36"], ":" => [77, "\xb37"], ";" => [18, "\xb37"], "<" => [77, "\xb38"], "=" => [18, "\xb38"], ">" => [77, "\xb39"], "?" => [18, "\xb39"], "@" => [77, "\xb3="], "A" => [18, "\xb3="], "B" => [77, "\xb3A"], "C" => [18, "\xb3A"], "D" => [77, "\xb3_"], "E" => [18, "\xb3_"], "F" => [77, "\xb3b"], "G" => [18, "\xb3b"], "H" => [77, "\xb3d"], "I" => [18, "\xb3d"], "J" => [77, "\xb3f"], "K" => [18, "\xb3f"], "L" => [77, "\xb3g"], "M" => [18, "\xb3g"], "N" => [77, "\xb3h"], "O" => [18, "\xb3h"], "P" => [77, "\xb3l"], "Q" => [18, "\xb3l"], "R" => [77, "\xb3m"], "S" => [18, "\xb3m"], "T" => [77, "\xb3n"], "U" => [18, "\xb3n"], "V" => [77, "\xb3p"], "W" => [18, "\xb3p"], "X" => [77, "\xb3r"], "Y" => [18, "\xb3r"], "Z" => [77, "\xb3u"], "[" => [18, "\xb3u"], "\\" => [0, "\xb3:"], "]" => [0, "\xb3B"], "^" => [0, "\xb3C"], "_" => [0, "\xb3D"], "`" => [0, "\xb3E"], "a" => [0, "\xb3F"], "b" => [0, "\xb3G"], "c" => [0, "\xb3H"], "d" => [0, "\xb3I"], "e" => [0, "\xb3J"], "f" => [0, "\xb3K"], "g" => [0, "\xb3L"], "h" => [0, "\xb3M"], "i" => [0, "\xb3N"], "j" => [0, "\xb3O"], "k" => [0, "\xb3P"], "l" => [0, "\xb3Q"], "m" => [0, "\xb3R"], "n" => [0, "\xb3S"], "o" => [0, "\xb3T"], "p" => [0, "\xb3U"], "q" => [0, "\xb3V"], "r" => [0, "\xb3W"], "s" => [0, "\xb3Y"], "t" => [0, "\xb3j"], "u" => [0, "\xb3k"], "v" => [0, "\xb3q"], "w" => [0, "\xb3v"], "x" => [0, "\xb3w"], "y" => [0, "\xb3x"], "z" => [0, "\xb3y"], "{" => [0, "\xb3z"], "|" => [82, "\xb3"], "}" => [87, "\xb3"], "~" => [130, "\xb3"], "" => [9, "\xb3"], "\x80" => [94, "\xd10"], "\x81" => [76, "\xd10"], "\x82" => [104, "\xd10"], "\x83" => [16, "\xd10"], "\x84" => [94, "\xd11"], "\x85" => [76, "\xd11"], "\x86" => [104, "\xd11"], "\x87" => [16, "\xd11"], "\x88" => [94, "\xd12"], "\x89" => [76, "\xd12"], "\x8a" => [104, "\xd12"], "\x8b" => [16, "\xd12"], "\x8c" => [94, "\xd1a"], "\x8d" => [76, "\xd1a"], "\x8e" => [104, "\xd1a"], "\x8f" => [16, "\xd1a"], "\x90" => [94, "\xd1c"], "\x91" => [76, "\xd1c"], "\x92" => [104, "\xd1c"], "\x93" => [16, "\xd1c"], "\x94" => [94, "\xd1e"], "\x95" => [76, "\xd1e"], "\x96" => [104, "\xd1e"], "\x97" => [16, "\xd1e"], "\x98" => [94, "\xd1i"], "\x99" => [76, "\xd1i"], "\x9a" => [104, "\xd1i"], "\x9b" => [16, "\xd1i"], "\x9c" => [94, "\xd1o"], "\x9d" => [76, "\xd1o"], "\x9e" => [104, "\xd1o"], "\x9f" => [16, "\xd1o"], "\xa0" => [94, "\xd1s"], "\xa1" => [76, "\xd1s"], "\xa2" => [104, "\xd1s"], "\xa3" => [16, "\xd1s"], "\xa4" => [94, "\xd1t"], "\xa5" => [76, "\xd1t"], "\xa6" => [104, "\xd1t"], "\xa7" => [16, "\xd1t"], "\xa8" => [77, "\xd1 "], "\xa9" => [18, "\xd1 "], "\xaa" => [77, "\xd1%"], "\xab" => [18, "\xd1%"], "\xac" => [77, "\xd1-"], "\xad" => [18, "\xd1-"], "\xae" => [77, "\xd1."], "\xaf" => [18, "\xd1."], "\xb0" => [77, "\xd1/"], "\xb1" => [18, "\xd1/"], "\xb2" => [77, "\xd13"], "\xb3" => [18, "\xd13"], "\xb4" => [77, "\xd14"], "\xb5" => [18, "\xd14"], "\xb6" => [77, "\xd15"], "\xb7" => [18, "\xd15"], "\xb8" => [77, "\xd16"], "\xb9" => [18, "\xd16"], "\xba" => [77, "\xd17"], "\xbb" => [18, "\xd17"], "\xbc" => [77, "\xd18"], "\xbd" => [18, "\xd18"], "\xbe" => [77, "\xd19"], "\xbf" => [18, "\xd19"], "\xc0" => [77, "\xd1="], "\xc1" => [18, "\xd1="], "\xc2" => [77, "\xd1A"], "\xc3" => [18, "\xd1A"], "\xc4" => [77, "\xd1_"], "\xc5" => [18, "\xd1_"], "\xc6" => [77, "\xd1b"], "\xc7" => [18, "\xd1b"], "\xc8" => [77, "\xd1d"], "\xc9" => [18, "\xd1d"], "\xca" => [77, "\xd1f"], "\xcb" => [18, "\xd1f"], "\xcc" => [77, "\xd1g"], "\xcd" => [18, "\xd1g"], "\xce" => [77, "\xd1h"], "\xcf" => [18, "\xd1h"], "\xd0" => [77, "\xd1l"], "\xd1" => [18, "\xd1l"], "\xd2" => [77, "\xd1m"], "\xd3" => [18, "\xd1m"], "\xd4" => [77, "\xd1n"], "\xd5" => [18, "\xd1n"], "\xd6" => [77, "\xd1p"], "\xd7" => [18, "\xd1p"], "\xd8" => [77, "\xd1r"], "\xd9" => [18, "\xd1r"], "\xda" => [77, "\xd1u"], "\xdb" => [18, "\xd1u"], "\xdc" => [0, "\xd1:"], "\xdd" => [0, "\xd1B"], "\xde" => [0, "\xd1C"], "\xdf" => [0, "\xd1D"], "\xe0" => [0, "\xd1E"], "\xe1" => [0, "\xd1F"], "\xe2" => [0, "\xd1G"], "\xe3" => [0, "\xd1H"], "\xe4" => [0, "\xd1I"], "\xe5" => [0, "\xd1J"], "\xe6" => [0, "\xd1K"], "\xe7" => [0, "\xd1L"], "\xe8" => [0, "\xd1M"], "\xe9" => [0, "\xd1N"], "\xea" => [0, "\xd1O"], "\xeb" => [0, "\xd1P"], "\xec" => [0, "\xd1Q"], "\xed" => [0, "\xd1R"], "\xee" => [0, "\xd1S"], "\xef" => [0, "\xd1T"], "\xf0" => [0, "\xd1U"], "\xf1" => [0, "\xd1V"], "\xf2" => [0, "\xd1W"], "\xf3" => [0, "\xd1Y"], "\xf4" => [0, "\xd1j"], "\xf5" => [0, "\xd1k"], "\xf6" => [0, "\xd1q"], "\xf7" => [0, "\xd1v"], "\xf8" => [0, "\xd1w"], "\xf9" => [0, "\xd1x"], "\xfa" => [0, "\xd1y"], "\xfb" => [0, "\xd1z"], "\xfc" => [82, "\xd1"], "\xfd" => [87, "\xd1"], "\xfe" => [130, "\xd1"], "\xff" => [9, "\xd1"]], ["\x00" => [94, "\xb60"], "\x01" => [76, "\xb60"], "\x02" => [104, "\xb60"], "\x03" => [16, "\xb60"], "\x04" => [94, "\xb61"], "\x05" => [76, "\xb61"], "\x06" => [104, "\xb61"], "\x07" => [16, "\xb61"], "\x08" => [94, "\xb62"], "\t" => [76, "\xb62"], "\n" => [104, "\xb62"], "\v" => [16, "\xb62"], "\f" => [94, "\xb6a"], "\r" => [76, "\xb6a"], "\x0e" => [104, "\xb6a"], "\x0f" => [16, "\xb6a"], "\x10" => [94, "\xb6c"], "\x11" => [76, "\xb6c"], "\x12" => [104, "\xb6c"], "\x13" => [16, "\xb6c"], "\x14" => [94, "\xb6e"], "\x15" => [76, "\xb6e"], "\x16" => [104, "\xb6e"], "\x17" => [16, "\xb6e"], "\x18" => [94, "\xb6i"], "\x19" => [76, "\xb6i"], "\x1a" => [104, "\xb6i"], "\x1b" => [16, "\xb6i"], "\x1c" => [94, "\xb6o"], "\x1d" => [76, "\xb6o"], "\x1e" => [104, "\xb6o"], "\x1f" => [16, "\xb6o"], " " => [94, "\xb6s"], "!" => [76, "\xb6s"], "\"" => [104, "\xb6s"], "#" => [16, "\xb6s"], "\$" => [94, "\xb6t"], "%" => [76, "\xb6t"], "&" => [104, "\xb6t"], "'" => [16, "\xb6t"], "(" => [77, "\xb6 "], ")" => [18, "\xb6 "], "*" => [77, "\xb6%"], "+" => [18, "\xb6%"], "," => [77, "\xb6-"], "-" => [18, "\xb6-"], "." => [77, "\xb6."], "/" => [18, "\xb6."], [77, "\xb6/"], [18, "\xb6/"], [77, "\xb63"], [18, "\xb63"], [77, "\xb64"], [18, "\xb64"], [77, "\xb65"], [18, "\xb65"], [77, "\xb66"], [18, "\xb66"], ":" => [77, "\xb67"], ";" => [18, "\xb67"], "<" => [77, "\xb68"], "=" => [18, "\xb68"], ">" => [77, "\xb69"], "?" => [18, "\xb69"], "@" => [77, "\xb6="], "A" => [18, "\xb6="], "B" => [77, "\xb6A"], "C" => [18, "\xb6A"], "D" => [77, "\xb6_"], "E" => [18, "\xb6_"], "F" => [77, "\xb6b"], "G" => [18, "\xb6b"], "H" => [77, "\xb6d"], "I" => [18, "\xb6d"], "J" => [77, "\xb6f"], "K" => [18, "\xb6f"], "L" => [77, "\xb6g"], "M" => [18, "\xb6g"], "N" => [77, "\xb6h"], "O" => [18, "\xb6h"], "P" => [77, "\xb6l"], "Q" => [18, "\xb6l"], "R" => [77, "\xb6m"], "S" => [18, "\xb6m"], "T" => [77, "\xb6n"], "U" => [18, "\xb6n"], "V" => [77, "\xb6p"], "W" => [18, "\xb6p"], "X" => [77, "\xb6r"], "Y" => [18, "\xb6r"], "Z" => [77, "\xb6u"], "[" => [18, "\xb6u"], "\\" => [0, "\xb6:"], "]" => [0, "\xb6B"], "^" => [0, "\xb6C"], "_" => [0, "\xb6D"], "`" => [0, "\xb6E"], "a" => [0, "\xb6F"], "b" => [0, "\xb6G"], "c" => [0, "\xb6H"], "d" => [0, "\xb6I"], "e" => [0, "\xb6J"], "f" => [0, "\xb6K"], "g" => [0, "\xb6L"], "h" => [0, "\xb6M"], "i" => [0, "\xb6N"], "j" => [0, "\xb6O"], "k" => [0, "\xb6P"], "l" => [0, "\xb6Q"], "m" => [0, "\xb6R"], "n" => [0, "\xb6S"], "o" => [0, "\xb6T"], "p" => [0, "\xb6U"], "q" => [0, "\xb6V"], "r" => [0, "\xb6W"], "s" => [0, "\xb6Y"], "t" => [0, "\xb6j"], "u" => [0, "\xb6k"], "v" => [0, "\xb6q"], "w" => [0, "\xb6v"], "x" => [0, "\xb6w"], "y" => [0, "\xb6x"], "z" => [0, "\xb6y"], "{" => [0, "\xb6z"], "|" => [82, "\xb6"], "}" => [87, "\xb6"], "~" => [130, "\xb6"], "" => [9, "\xb6"], "\x80" => [94, "\xb70"], "\x81" => [76, "\xb70"], "\x82" => [104, "\xb70"], "\x83" => [16, "\xb70"], "\x84" => [94, "\xb71"], "\x85" => [76, "\xb71"], "\x86" => [104, "\xb71"], "\x87" => [16, "\xb71"], "\x88" => [94, "\xb72"], "\x89" => [76, "\xb72"], "\x8a" => [104, "\xb72"], "\x8b" => [16, "\xb72"], "\x8c" => [94, "\xb7a"], "\x8d" => [76, "\xb7a"], "\x8e" => [104, "\xb7a"], "\x8f" => [16, "\xb7a"], "\x90" => [94, "\xb7c"], "\x91" => [76, "\xb7c"], "\x92" => [104, "\xb7c"], "\x93" => [16, "\xb7c"], "\x94" => [94, "\xb7e"], "\x95" => [76, "\xb7e"], "\x96" => [104, "\xb7e"], "\x97" => [16, "\xb7e"], "\x98" => [94, "\xb7i"], "\x99" => [76, "\xb7i"], "\x9a" => [104, "\xb7i"], "\x9b" => [16, "\xb7i"], "\x9c" => [94, "\xb7o"], "\x9d" => [76, "\xb7o"], "\x9e" => [104, "\xb7o"], "\x9f" => [16, "\xb7o"], "\xa0" => [94, "\xb7s"], "\xa1" => [76, "\xb7s"], "\xa2" => [104, "\xb7s"], "\xa3" => [16, "\xb7s"], "\xa4" => [94, "\xb7t"], "\xa5" => [76, "\xb7t"], "\xa6" => [104, "\xb7t"], "\xa7" => [16, "\xb7t"], "\xa8" => [77, "\xb7 "], "\xa9" => [18, "\xb7 "], "\xaa" => [77, "\xb7%"], "\xab" => [18, "\xb7%"], "\xac" => [77, "\xb7-"], "\xad" => [18, "\xb7-"], "\xae" => [77, "\xb7."], "\xaf" => [18, "\xb7."], "\xb0" => [77, "\xb7/"], "\xb1" => [18, "\xb7/"], "\xb2" => [77, "\xb73"], "\xb3" => [18, "\xb73"], "\xb4" => [77, "\xb74"], "\xb5" => [18, "\xb74"], "\xb6" => [77, "\xb75"], "\xb7" => [18, "\xb75"], "\xb8" => [77, "\xb76"], "\xb9" => [18, "\xb76"], "\xba" => [77, "\xb77"], "\xbb" => [18, "\xb77"], "\xbc" => [77, "\xb78"], "\xbd" => [18, "\xb78"], "\xbe" => [77, "\xb79"], "\xbf" => [18, "\xb79"], "\xc0" => [77, "\xb7="], "\xc1" => [18, "\xb7="], "\xc2" => [77, "\xb7A"], "\xc3" => [18, "\xb7A"], "\xc4" => [77, "\xb7_"], "\xc5" => [18, "\xb7_"], "\xc6" => [77, "\xb7b"], "\xc7" => [18, "\xb7b"], "\xc8" => [77, "\xb7d"], "\xc9" => [18, "\xb7d"], "\xca" => [77, "\xb7f"], "\xcb" => [18, "\xb7f"], "\xcc" => [77, "\xb7g"], "\xcd" => [18, "\xb7g"], "\xce" => [77, "\xb7h"], "\xcf" => [18, "\xb7h"], "\xd0" => [77, "\xb7l"], "\xd1" => [18, "\xb7l"], "\xd2" => [77, "\xb7m"], "\xd3" => [18, "\xb7m"], "\xd4" => [77, "\xb7n"], "\xd5" => [18, "\xb7n"], "\xd6" => [77, "\xb7p"], "\xd7" => [18, "\xb7p"], "\xd8" => [77, "\xb7r"], "\xd9" => [18, "\xb7r"], "\xda" => [77, "\xb7u"], "\xdb" => [18, "\xb7u"], "\xdc" => [0, "\xb7:"], "\xdd" => [0, "\xb7B"], "\xde" => [0, "\xb7C"], "\xdf" => [0, "\xb7D"], "\xe0" => [0, "\xb7E"], "\xe1" => [0, "\xb7F"], "\xe2" => [0, "\xb7G"], "\xe3" => [0, "\xb7H"], "\xe4" => [0, "\xb7I"], "\xe5" => [0, "\xb7J"], "\xe6" => [0, "\xb7K"], "\xe7" => [0, "\xb7L"], "\xe8" => [0, "\xb7M"], "\xe9" => [0, "\xb7N"], "\xea" => [0, "\xb7O"], "\xeb" => [0, "\xb7P"], "\xec" => [0, "\xb7Q"], "\xed" => [0, "\xb7R"], "\xee" => [0, "\xb7S"], "\xef" => [0, "\xb7T"], "\xf0" => [0, "\xb7U"], "\xf1" => [0, "\xb7V"], "\xf2" => [0, "\xb7W"], "\xf3" => [0, "\xb7Y"], "\xf4" => [0, "\xb7j"], "\xf5" => [0, "\xb7k"], "\xf6" => [0, "\xb7q"], "\xf7" => [0, "\xb7v"], "\xf8" => [0, "\xb7w"], "\xf9" => [0, "\xb7x"], "\xfa" => [0, "\xb7y"], "\xfb" => [0, "\xb7z"], "\xfc" => [82, "\xb7"], "\xfd" => [87, "\xb7"], "\xfe" => [130, "\xb7"], "\xff" => [9, "\xb7"]], ["\x00" => [94, "\xb80"], "\x01" => [76, "\xb80"], "\x02" => [104, "\xb80"], "\x03" => [16, "\xb80"], "\x04" => [94, "\xb81"], "\x05" => [76, "\xb81"], "\x06" => [104, "\xb81"], "\x07" => [16, "\xb81"], "\x08" => [94, "\xb82"], "\t" => [76, "\xb82"], "\n" => [104, "\xb82"], "\v" => [16, "\xb82"], "\f" => [94, "\xb8a"], "\r" => [76, "\xb8a"], "\x0e" => [104, "\xb8a"], "\x0f" => [16, "\xb8a"], "\x10" => [94, "\xb8c"], "\x11" => [76, "\xb8c"], "\x12" => [104, "\xb8c"], "\x13" => [16, "\xb8c"], "\x14" => [94, "\xb8e"], "\x15" => [76, "\xb8e"], "\x16" => [104, "\xb8e"], "\x17" => [16, "\xb8e"], "\x18" => [94, "\xb8i"], "\x19" => [76, "\xb8i"], "\x1a" => [104, "\xb8i"], "\x1b" => [16, "\xb8i"], "\x1c" => [94, "\xb8o"], "\x1d" => [76, "\xb8o"], "\x1e" => [104, "\xb8o"], "\x1f" => [16, "\xb8o"], " " => [94, "\xb8s"], "!" => [76, "\xb8s"], "\"" => [104, "\xb8s"], "#" => [16, "\xb8s"], "\$" => [94, "\xb8t"], "%" => [76, "\xb8t"], "&" => [104, "\xb8t"], "'" => [16, "\xb8t"], "(" => [77, "\xb8 "], ")" => [18, "\xb8 "], "*" => [77, "\xb8%"], "+" => [18, "\xb8%"], "," => [77, "\xb8-"], "-" => [18, "\xb8-"], "." => [77, "\xb8."], "/" => [18, "\xb8."], [77, "\xb8/"], [18, "\xb8/"], [77, "\xb83"], [18, "\xb83"], [77, "\xb84"], [18, "\xb84"], [77, "\xb85"], [18, "\xb85"], [77, "\xb86"], [18, "\xb86"], ":" => [77, "\xb87"], ";" => [18, "\xb87"], "<" => [77, "\xb88"], "=" => [18, "\xb88"], ">" => [77, "\xb89"], "?" => [18, "\xb89"], "@" => [77, "\xb8="], "A" => [18, "\xb8="], "B" => [77, "\xb8A"], "C" => [18, "\xb8A"], "D" => [77, "\xb8_"], "E" => [18, "\xb8_"], "F" => [77, "\xb8b"], "G" => [18, "\xb8b"], "H" => [77, "\xb8d"], "I" => [18, "\xb8d"], "J" => [77, "\xb8f"], "K" => [18, "\xb8f"], "L" => [77, "\xb8g"], "M" => [18, "\xb8g"], "N" => [77, "\xb8h"], "O" => [18, "\xb8h"], "P" => [77, "\xb8l"], "Q" => [18, "\xb8l"], "R" => [77, "\xb8m"], "S" => [18, "\xb8m"], "T" => [77, "\xb8n"], "U" => [18, "\xb8n"], "V" => [77, "\xb8p"], "W" => [18, "\xb8p"], "X" => [77, "\xb8r"], "Y" => [18, "\xb8r"], "Z" => [77, "\xb8u"], "[" => [18, "\xb8u"], "\\" => [0, "\xb8:"], "]" => [0, "\xb8B"], "^" => [0, "\xb8C"], "_" => [0, "\xb8D"], "`" => [0, "\xb8E"], "a" => [0, "\xb8F"], "b" => [0, "\xb8G"], "c" => [0, "\xb8H"], "d" => [0, "\xb8I"], "e" => [0, "\xb8J"], "f" => [0, "\xb8K"], "g" => [0, "\xb8L"], "h" => [0, "\xb8M"], "i" => [0, "\xb8N"], "j" => [0, "\xb8O"], "k" => [0, "\xb8P"], "l" => [0, "\xb8Q"], "m" => [0, "\xb8R"], "n" => [0, "\xb8S"], "o" => [0, "\xb8T"], "p" => [0, "\xb8U"], "q" => [0, "\xb8V"], "r" => [0, "\xb8W"], "s" => [0, "\xb8Y"], "t" => [0, "\xb8j"], "u" => [0, "\xb8k"], "v" => [0, "\xb8q"], "w" => [0, "\xb8v"], "x" => [0, "\xb8w"], "y" => [0, "\xb8x"], "z" => [0, "\xb8y"], "{" => [0, "\xb8z"], "|" => [82, "\xb8"], "}" => [87, "\xb8"], "~" => [130, "\xb8"], "" => [9, "\xb8"], "\x80" => [94, "\xc20"], "\x81" => [76, "\xc20"], "\x82" => [104, "\xc20"], "\x83" => [16, "\xc20"], "\x84" => [94, "\xc21"], "\x85" => [76, "\xc21"], "\x86" => [104, "\xc21"], "\x87" => [16, "\xc21"], "\x88" => [94, "\xc22"], "\x89" => [76, "\xc22"], "\x8a" => [104, "\xc22"], "\x8b" => [16, "\xc22"], "\x8c" => [94, "\xc2a"], "\x8d" => [76, "\xc2a"], "\x8e" => [104, "\xc2a"], "\x8f" => [16, "\xc2a"], "\x90" => [94, "\xc2c"], "\x91" => [76, "\xc2c"], "\x92" => [104, "\xc2c"], "\x93" => [16, "\xc2c"], "\x94" => [94, "\xc2e"], "\x95" => [76, "\xc2e"], "\x96" => [104, "\xc2e"], "\x97" => [16, "\xc2e"], "\x98" => [94, "\xc2i"], "\x99" => [76, "\xc2i"], "\x9a" => [104, "\xc2i"], "\x9b" => [16, "\xc2i"], "\x9c" => [94, "\xc2o"], "\x9d" => [76, "\xc2o"], "\x9e" => [104, "\xc2o"], "\x9f" => [16, "\xc2o"], "\xa0" => [94, "\xc2s"], "\xa1" => [76, "\xc2s"], "\xa2" => [104, "\xc2s"], "\xa3" => [16, "\xc2s"], "\xa4" => [94, "\xc2t"], "\xa5" => [76, "\xc2t"], "\xa6" => [104, "\xc2t"], "\xa7" => [16, "\xc2t"], "\xa8" => [77, "\xc2 "], "\xa9" => [18, "\xc2 "], "\xaa" => [77, "\xc2%"], "\xab" => [18, "\xc2%"], "\xac" => [77, "\xc2-"], "\xad" => [18, "\xc2-"], "\xae" => [77, "\xc2."], "\xaf" => [18, "\xc2."], "\xb0" => [77, "\xc2/"], "\xb1" => [18, "\xc2/"], "\xb2" => [77, "\xc23"], "\xb3" => [18, "\xc23"], "\xb4" => [77, "\xc24"], "\xb5" => [18, "\xc24"], "\xb6" => [77, "\xc25"], "\xb7" => [18, "\xc25"], "\xb8" => [77, "\xc26"], "\xb9" => [18, "\xc26"], "\xba" => [77, "\xc27"], "\xbb" => [18, "\xc27"], "\xbc" => [77, "\xc28"], "\xbd" => [18, "\xc28"], "\xbe" => [77, "\xc29"], "\xbf" => [18, "\xc29"], "\xc0" => [77, "\xc2="], "\xc1" => [18, "\xc2="], "\xc2" => [77, "\xc2A"], "\xc3" => [18, "\xc2A"], "\xc4" => [77, "\xc2_"], "\xc5" => [18, "\xc2_"], "\xc6" => [77, "\xc2b"], "\xc7" => [18, "\xc2b"], "\xc8" => [77, "\xc2d"], "\xc9" => [18, "\xc2d"], "\xca" => [77, "\xc2f"], "\xcb" => [18, "\xc2f"], "\xcc" => [77, "\xc2g"], "\xcd" => [18, "\xc2g"], "\xce" => [77, "\xc2h"], "\xcf" => [18, "\xc2h"], "\xd0" => [77, "\xc2l"], "\xd1" => [18, "\xc2l"], "\xd2" => [77, "\xc2m"], "\xd3" => [18, "\xc2m"], "\xd4" => [77, "\xc2n"], "\xd5" => [18, "\xc2n"], "\xd6" => [77, "\xc2p"], "\xd7" => [18, "\xc2p"], "\xd8" => [77, "\xc2r"], "\xd9" => [18, "\xc2r"], "\xda" => [77, "\xc2u"], "\xdb" => [18, "\xc2u"], "\xdc" => [0, "\xc2:"], "\xdd" => [0, "\xc2B"], "\xde" => [0, "\xc2C"], "\xdf" => [0, "\xc2D"], "\xe0" => [0, "\xc2E"], "\xe1" => [0, "\xc2F"], "\xe2" => [0, "\xc2G"], "\xe3" => [0, "\xc2H"], "\xe4" => [0, "\xc2I"], "\xe5" => [0, "\xc2J"], "\xe6" => [0, "\xc2K"], "\xe7" => [0, "\xc2L"], "\xe8" => [0, "\xc2M"], "\xe9" => [0, "\xc2N"], "\xea" => [0, "\xc2O"], "\xeb" => [0, "\xc2P"], "\xec" => [0, "\xc2Q"], "\xed" => [0, "\xc2R"], "\xee" => [0, "\xc2S"], "\xef" => [0, "\xc2T"], "\xf0" => [0, "\xc2U"], "\xf1" => [0, "\xc2V"], "\xf2" => [0, "\xc2W"], "\xf3" => [0, "\xc2Y"], "\xf4" => [0, "\xc2j"], "\xf5" => [0, "\xc2k"], "\xf6" => [0, "\xc2q"], "\xf7" => [0, "\xc2v"], "\xf8" => [0, "\xc2w"], "\xf9" => [0, "\xc2x"], "\xfa" => [0, "\xc2y"], "\xfb" => [0, "\xc2z"], "\xfc" => [82, "\xc2"], "\xfd" => [87, "\xc2"], "\xfe" => [130, "\xc2"], "\xff" => [9, "\xc2"]], ["\x00" => [94, "\xb90"], "\x01" => [76, "\xb90"], "\x02" => [104, "\xb90"], "\x03" => [16, "\xb90"], "\x04" => [94, "\xb91"], "\x05" => [76, "\xb91"], "\x06" => [104, "\xb91"], "\x07" => [16, "\xb91"], "\x08" => [94, "\xb92"], "\t" => [76, "\xb92"], "\n" => [104, "\xb92"], "\v" => [16, "\xb92"], "\f" => [94, "\xb9a"], "\r" => [76, "\xb9a"], "\x0e" => [104, "\xb9a"], "\x0f" => [16, "\xb9a"], "\x10" => [94, "\xb9c"], "\x11" => [76, "\xb9c"], "\x12" => [104, "\xb9c"], "\x13" => [16, "\xb9c"], "\x14" => [94, "\xb9e"], "\x15" => [76, "\xb9e"], "\x16" => [104, "\xb9e"], "\x17" => [16, "\xb9e"], "\x18" => [94, "\xb9i"], "\x19" => [76, "\xb9i"], "\x1a" => [104, "\xb9i"], "\x1b" => [16, "\xb9i"], "\x1c" => [94, "\xb9o"], "\x1d" => [76, "\xb9o"], "\x1e" => [104, "\xb9o"], "\x1f" => [16, "\xb9o"], " " => [94, "\xb9s"], "!" => [76, "\xb9s"], "\"" => [104, "\xb9s"], "#" => [16, "\xb9s"], "\$" => [94, "\xb9t"], "%" => [76, "\xb9t"], "&" => [104, "\xb9t"], "'" => [16, "\xb9t"], "(" => [77, "\xb9 "], ")" => [18, "\xb9 "], "*" => [77, "\xb9%"], "+" => [18, "\xb9%"], "," => [77, "\xb9-"], "-" => [18, "\xb9-"], "." => [77, "\xb9."], "/" => [18, "\xb9."], [77, "\xb9/"], [18, "\xb9/"], [77, "\xb93"], [18, "\xb93"], [77, "\xb94"], [18, "\xb94"], [77, "\xb95"], [18, "\xb95"], [77, "\xb96"], [18, "\xb96"], ":" => [77, "\xb97"], ";" => [18, "\xb97"], "<" => [77, "\xb98"], "=" => [18, "\xb98"], ">" => [77, "\xb99"], "?" => [18, "\xb99"], "@" => [77, "\xb9="], "A" => [18, "\xb9="], "B" => [77, "\xb9A"], "C" => [18, "\xb9A"], "D" => [77, "\xb9_"], "E" => [18, "\xb9_"], "F" => [77, "\xb9b"], "G" => [18, "\xb9b"], "H" => [77, "\xb9d"], "I" => [18, "\xb9d"], "J" => [77, "\xb9f"], "K" => [18, "\xb9f"], "L" => [77, "\xb9g"], "M" => [18, "\xb9g"], "N" => [77, "\xb9h"], "O" => [18, "\xb9h"], "P" => [77, "\xb9l"], "Q" => [18, "\xb9l"], "R" => [77, "\xb9m"], "S" => [18, "\xb9m"], "T" => [77, "\xb9n"], "U" => [18, "\xb9n"], "V" => [77, "\xb9p"], "W" => [18, "\xb9p"], "X" => [77, "\xb9r"], "Y" => [18, "\xb9r"], "Z" => [77, "\xb9u"], "[" => [18, "\xb9u"], "\\" => [0, "\xb9:"], "]" => [0, "\xb9B"], "^" => [0, "\xb9C"], "_" => [0, "\xb9D"], "`" => [0, "\xb9E"], "a" => [0, "\xb9F"], "b" => [0, "\xb9G"], "c" => [0, "\xb9H"], "d" => [0, "\xb9I"], "e" => [0, "\xb9J"], "f" => [0, "\xb9K"], "g" => [0, "\xb9L"], "h" => [0, "\xb9M"], "i" => [0, "\xb9N"], "j" => [0, "\xb9O"], "k" => [0, "\xb9P"], "l" => [0, "\xb9Q"], "m" => [0, "\xb9R"], "n" => [0, "\xb9S"], "o" => [0, "\xb9T"], "p" => [0, "\xb9U"], "q" => [0, "\xb9V"], "r" => [0, "\xb9W"], "s" => [0, "\xb9Y"], "t" => [0, "\xb9j"], "u" => [0, "\xb9k"], "v" => [0, "\xb9q"], "w" => [0, "\xb9v"], "x" => [0, "\xb9w"], "y" => [0, "\xb9x"], "z" => [0, "\xb9y"], "{" => [0, "\xb9z"], "|" => [82, "\xb9"], "}" => [87, "\xb9"], "~" => [130, "\xb9"], "" => [9, "\xb9"], "\x80" => [94, "\xba0"], "\x81" => [76, "\xba0"], "\x82" => [104, "\xba0"], "\x83" => [16, "\xba0"], "\x84" => [94, "\xba1"], "\x85" => [76, "\xba1"], "\x86" => [104, "\xba1"], "\x87" => [16, "\xba1"], "\x88" => [94, "\xba2"], "\x89" => [76, "\xba2"], "\x8a" => [104, "\xba2"], "\x8b" => [16, "\xba2"], "\x8c" => [94, "\xbaa"], "\x8d" => [76, "\xbaa"], "\x8e" => [104, "\xbaa"], "\x8f" => [16, "\xbaa"], "\x90" => [94, "\xbac"], "\x91" => [76, "\xbac"], "\x92" => [104, "\xbac"], "\x93" => [16, "\xbac"], "\x94" => [94, "\xbae"], "\x95" => [76, "\xbae"], "\x96" => [104, "\xbae"], "\x97" => [16, "\xbae"], "\x98" => [94, "\xbai"], "\x99" => [76, "\xbai"], "\x9a" => [104, "\xbai"], "\x9b" => [16, "\xbai"], "\x9c" => [94, "\xbao"], "\x9d" => [76, "\xbao"], "\x9e" => [104, "\xbao"], "\x9f" => [16, "\xbao"], "\xa0" => [94, "\xbas"], "\xa1" => [76, "\xbas"], "\xa2" => [104, "\xbas"], "\xa3" => [16, "\xbas"], "\xa4" => [94, "\xbat"], "\xa5" => [76, "\xbat"], "\xa6" => [104, "\xbat"], "\xa7" => [16, "\xbat"], "\xa8" => [77, "\xba "], "\xa9" => [18, "\xba "], "\xaa" => [77, "\xba%"], "\xab" => [18, "\xba%"], "\xac" => [77, "\xba-"], "\xad" => [18, "\xba-"], "\xae" => [77, "\xba."], "\xaf" => [18, "\xba."], "\xb0" => [77, "\xba/"], "\xb1" => [18, "\xba/"], "\xb2" => [77, "\xba3"], "\xb3" => [18, "\xba3"], "\xb4" => [77, "\xba4"], "\xb5" => [18, "\xba4"], "\xb6" => [77, "\xba5"], "\xb7" => [18, "\xba5"], "\xb8" => [77, "\xba6"], "\xb9" => [18, "\xba6"], "\xba" => [77, "\xba7"], "\xbb" => [18, "\xba7"], "\xbc" => [77, "\xba8"], "\xbd" => [18, "\xba8"], "\xbe" => [77, "\xba9"], "\xbf" => [18, "\xba9"], "\xc0" => [77, "\xba="], "\xc1" => [18, "\xba="], "\xc2" => [77, "\xbaA"], "\xc3" => [18, "\xbaA"], "\xc4" => [77, "\xba_"], "\xc5" => [18, "\xba_"], "\xc6" => [77, "\xbab"], "\xc7" => [18, "\xbab"], "\xc8" => [77, "\xbad"], "\xc9" => [18, "\xbad"], "\xca" => [77, "\xbaf"], "\xcb" => [18, "\xbaf"], "\xcc" => [77, "\xbag"], "\xcd" => [18, "\xbag"], "\xce" => [77, "\xbah"], "\xcf" => [18, "\xbah"], "\xd0" => [77, "\xbal"], "\xd1" => [18, "\xbal"], "\xd2" => [77, "\xbam"], "\xd3" => [18, "\xbam"], "\xd4" => [77, "\xban"], "\xd5" => [18, "\xban"], "\xd6" => [77, "\xbap"], "\xd7" => [18, "\xbap"], "\xd8" => [77, "\xbar"], "\xd9" => [18, "\xbar"], "\xda" => [77, "\xbau"], "\xdb" => [18, "\xbau"], "\xdc" => [0, "\xba:"], "\xdd" => [0, "\xbaB"], "\xde" => [0, "\xbaC"], "\xdf" => [0, "\xbaD"], "\xe0" => [0, "\xbaE"], "\xe1" => [0, "\xbaF"], "\xe2" => [0, "\xbaG"], "\xe3" => [0, "\xbaH"], "\xe4" => [0, "\xbaI"], "\xe5" => [0, "\xbaJ"], "\xe6" => [0, "\xbaK"], "\xe7" => [0, "\xbaL"], "\xe8" => [0, "\xbaM"], "\xe9" => [0, "\xbaN"], "\xea" => [0, "\xbaO"], "\xeb" => [0, "\xbaP"], "\xec" => [0, "\xbaQ"], "\xed" => [0, "\xbaR"], "\xee" => [0, "\xbaS"], "\xef" => [0, "\xbaT"], "\xf0" => [0, "\xbaU"], "\xf1" => [0, "\xbaV"], "\xf2" => [0, "\xbaW"], "\xf3" => [0, "\xbaY"], "\xf4" => [0, "\xbaj"], "\xf5" => [0, "\xbak"], "\xf6" => [0, "\xbaq"], "\xf7" => [0, "\xbav"], "\xf8" => [0, "\xbaw"], "\xf9" => [0, "\xbax"], "\xfa" => [0, "\xbay"], "\xfb" => [0, "\xbaz"], "\xfc" => [82, "\xba"], "\xfd" => [87, "\xba"], "\xfe" => [130, "\xba"], "\xff" => [9, "\xba"]], ["\x00" => [94, "\xbb0"], "\x01" => [76, "\xbb0"], "\x02" => [104, "\xbb0"], "\x03" => [16, "\xbb0"], "\x04" => [94, "\xbb1"], "\x05" => [76, "\xbb1"], "\x06" => [104, "\xbb1"], "\x07" => [16, "\xbb1"], "\x08" => [94, "\xbb2"], "\t" => [76, "\xbb2"], "\n" => [104, "\xbb2"], "\v" => [16, "\xbb2"], "\f" => [94, "\xbba"], "\r" => [76, "\xbba"], "\x0e" => [104, "\xbba"], "\x0f" => [16, "\xbba"], "\x10" => [94, "\xbbc"], "\x11" => [76, "\xbbc"], "\x12" => [104, "\xbbc"], "\x13" => [16, "\xbbc"], "\x14" => [94, "\xbbe"], "\x15" => [76, "\xbbe"], "\x16" => [104, "\xbbe"], "\x17" => [16, "\xbbe"], "\x18" => [94, "\xbbi"], "\x19" => [76, "\xbbi"], "\x1a" => [104, "\xbbi"], "\x1b" => [16, "\xbbi"], "\x1c" => [94, "\xbbo"], "\x1d" => [76, "\xbbo"], "\x1e" => [104, "\xbbo"], "\x1f" => [16, "\xbbo"], " " => [94, "\xbbs"], "!" => [76, "\xbbs"], "\"" => [104, "\xbbs"], "#" => [16, "\xbbs"], "\$" => [94, "\xbbt"], "%" => [76, "\xbbt"], "&" => [104, "\xbbt"], "'" => [16, "\xbbt"], "(" => [77, "\xbb "], ")" => [18, "\xbb "], "*" => [77, "\xbb%"], "+" => [18, "\xbb%"], "," => [77, "\xbb-"], "-" => [18, "\xbb-"], "." => [77, "\xbb."], "/" => [18, "\xbb."], [77, "\xbb/"], [18, "\xbb/"], [77, "\xbb3"], [18, "\xbb3"], [77, "\xbb4"], [18, "\xbb4"], [77, "\xbb5"], [18, "\xbb5"], [77, "\xbb6"], [18, "\xbb6"], ":" => [77, "\xbb7"], ";" => [18, "\xbb7"], "<" => [77, "\xbb8"], "=" => [18, "\xbb8"], ">" => [77, "\xbb9"], "?" => [18, "\xbb9"], "@" => [77, "\xbb="], "A" => [18, "\xbb="], "B" => [77, "\xbbA"], "C" => [18, "\xbbA"], "D" => [77, "\xbb_"], "E" => [18, "\xbb_"], "F" => [77, "\xbbb"], "G" => [18, "\xbbb"], "H" => [77, "\xbbd"], "I" => [18, "\xbbd"], "J" => [77, "\xbbf"], "K" => [18, "\xbbf"], "L" => [77, "\xbbg"], "M" => [18, "\xbbg"], "N" => [77, "\xbbh"], "O" => [18, "\xbbh"], "P" => [77, "\xbbl"], "Q" => [18, "\xbbl"], "R" => [77, "\xbbm"], "S" => [18, "\xbbm"], "T" => [77, "\xbbn"], "U" => [18, "\xbbn"], "V" => [77, "\xbbp"], "W" => [18, "\xbbp"], "X" => [77, "\xbbr"], "Y" => [18, "\xbbr"], "Z" => [77, "\xbbu"], "[" => [18, "\xbbu"], "\\" => [0, "\xbb:"], "]" => [0, "\xbbB"], "^" => [0, "\xbbC"], "_" => [0, "\xbbD"], "`" => [0, "\xbbE"], "a" => [0, "\xbbF"], "b" => [0, "\xbbG"], "c" => [0, "\xbbH"], "d" => [0, "\xbbI"], "e" => [0, "\xbbJ"], "f" => [0, "\xbbK"], "g" => [0, "\xbbL"], "h" => [0, "\xbbM"], "i" => [0, "\xbbN"], "j" => [0, "\xbbO"], "k" => [0, "\xbbP"], "l" => [0, "\xbbQ"], "m" => [0, "\xbbR"], "n" => [0, "\xbbS"], "o" => [0, "\xbbT"], "p" => [0, "\xbbU"], "q" => [0, "\xbbV"], "r" => [0, "\xbbW"], "s" => [0, "\xbbY"], "t" => [0, "\xbbj"], "u" => [0, "\xbbk"], "v" => [0, "\xbbq"], "w" => [0, "\xbbv"], "x" => [0, "\xbbw"], "y" => [0, "\xbbx"], "z" => [0, "\xbby"], "{" => [0, "\xbbz"], "|" => [82, "\xbb"], "}" => [87, "\xbb"], "~" => [130, "\xbb"], "" => [9, "\xbb"], "\x80" => [94, "\xbd0"], "\x81" => [76, "\xbd0"], "\x82" => [104, "\xbd0"], "\x83" => [16, "\xbd0"], "\x84" => [94, "\xbd1"], "\x85" => [76, "\xbd1"], "\x86" => [104, "\xbd1"], "\x87" => [16, "\xbd1"], "\x88" => [94, "\xbd2"], "\x89" => [76, "\xbd2"], "\x8a" => [104, "\xbd2"], "\x8b" => [16, "\xbd2"], "\x8c" => [94, "\xbda"], "\x8d" => [76, "\xbda"], "\x8e" => [104, "\xbda"], "\x8f" => [16, "\xbda"], "\x90" => [94, "\xbdc"], "\x91" => [76, "\xbdc"], "\x92" => [104, "\xbdc"], "\x93" => [16, "\xbdc"], "\x94" => [94, "\xbde"], "\x95" => [76, "\xbde"], "\x96" => [104, "\xbde"], "\x97" => [16, "\xbde"], "\x98" => [94, "\xbdi"], "\x99" => [76, "\xbdi"], "\x9a" => [104, "\xbdi"], "\x9b" => [16, "\xbdi"], "\x9c" => [94, "\xbdo"], "\x9d" => [76, "\xbdo"], "\x9e" => [104, "\xbdo"], "\x9f" => [16, "\xbdo"], "\xa0" => [94, "\xbds"], "\xa1" => [76, "\xbds"], "\xa2" => [104, "\xbds"], "\xa3" => [16, "\xbds"], "\xa4" => [94, "\xbdt"], "\xa5" => [76, "\xbdt"], "\xa6" => [104, "\xbdt"], "\xa7" => [16, "\xbdt"], "\xa8" => [77, "\xbd "], "\xa9" => [18, "\xbd "], "\xaa" => [77, "\xbd%"], "\xab" => [18, "\xbd%"], "\xac" => [77, "\xbd-"], "\xad" => [18, "\xbd-"], "\xae" => [77, "\xbd."], "\xaf" => [18, "\xbd."], "\xb0" => [77, "\xbd/"], "\xb1" => [18, "\xbd/"], "\xb2" => [77, "\xbd3"], "\xb3" => [18, "\xbd3"], "\xb4" => [77, "\xbd4"], "\xb5" => [18, "\xbd4"], "\xb6" => [77, "\xbd5"], "\xb7" => [18, "\xbd5"], "\xb8" => [77, "\xbd6"], "\xb9" => [18, "\xbd6"], "\xba" => [77, "\xbd7"], "\xbb" => [18, "\xbd7"], "\xbc" => [77, "\xbd8"], "\xbd" => [18, "\xbd8"], "\xbe" => [77, "\xbd9"], "\xbf" => [18, "\xbd9"], "\xc0" => [77, "\xbd="], "\xc1" => [18, "\xbd="], "\xc2" => [77, "\xbdA"], "\xc3" => [18, "\xbdA"], "\xc4" => [77, "\xbd_"], "\xc5" => [18, "\xbd_"], "\xc6" => [77, "\xbdb"], "\xc7" => [18, "\xbdb"], "\xc8" => [77, "\xbdd"], "\xc9" => [18, "\xbdd"], "\xca" => [77, "\xbdf"], "\xcb" => [18, "\xbdf"], "\xcc" => [77, "\xbdg"], "\xcd" => [18, "\xbdg"], "\xce" => [77, "\xbdh"], "\xcf" => [18, "\xbdh"], "\xd0" => [77, "\xbdl"], "\xd1" => [18, "\xbdl"], "\xd2" => [77, "\xbdm"], "\xd3" => [18, "\xbdm"], "\xd4" => [77, "\xbdn"], "\xd5" => [18, "\xbdn"], "\xd6" => [77, "\xbdp"], "\xd7" => [18, "\xbdp"], "\xd8" => [77, "\xbdr"], "\xd9" => [18, "\xbdr"], "\xda" => [77, "\xbdu"], "\xdb" => [18, "\xbdu"], "\xdc" => [0, "\xbd:"], "\xdd" => [0, "\xbdB"], "\xde" => [0, "\xbdC"], "\xdf" => [0, "\xbdD"], "\xe0" => [0, "\xbdE"], "\xe1" => [0, "\xbdF"], "\xe2" => [0, "\xbdG"], "\xe3" => [0, "\xbdH"], "\xe4" => [0, "\xbdI"], "\xe5" => [0, "\xbdJ"], "\xe6" => [0, "\xbdK"], "\xe7" => [0, "\xbdL"], "\xe8" => [0, "\xbdM"], "\xe9" => [0, "\xbdN"], "\xea" => [0, "\xbdO"], "\xeb" => [0, "\xbdP"], "\xec" => [0, "\xbdQ"], "\xed" => [0, "\xbdR"], "\xee" => [0, "\xbdS"], "\xef" => [0, "\xbdT"], "\xf0" => [0, "\xbdU"], "\xf1" => [0, "\xbdV"], "\xf2" => [0, "\xbdW"], "\xf3" => [0, "\xbdY"], "\xf4" => [0, "\xbdj"], "\xf5" => [0, "\xbdk"], "\xf6" => [0, "\xbdq"], "\xf7" => [0, "\xbdv"], "\xf8" => [0, "\xbdw"], "\xf9" => [0, "\xbdx"], "\xfa" => [0, "\xbdy"], "\xfb" => [0, "\xbdz"], "\xfc" => [82, "\xbd"], "\xfd" => [87, "\xbd"], "\xfe" => [130, "\xbd"], "\xff" => [9, "\xbd"]], ["\x00" => [77, "\xbb0"], "\x01" => [18, "\xbb0"], "\x02" => [77, "\xbb1"], "\x03" => [18, "\xbb1"], "\x04" => [77, "\xbb2"], "\x05" => [18, "\xbb2"], "\x06" => [77, "\xbba"], "\x07" => [18, "\xbba"], "\x08" => [77, "\xbbc"], "\t" => [18, "\xbbc"], "\n" => [77, "\xbbe"], "\v" => [18, "\xbbe"], "\f" => [77, "\xbbi"], "\r" => [18, "\xbbi"], "\x0e" => [77, "\xbbo"], "\x0f" => [18, "\xbbo"], "\x10" => [77, "\xbbs"], "\x11" => [18, "\xbbs"], "\x12" => [77, "\xbbt"], "\x13" => [18, "\xbbt"], "\x14" => [0, "\xbb "], "\x15" => [0, "\xbb%"], "\x16" => [0, "\xbb-"], "\x17" => [0, "\xbb."], "\x18" => [0, "\xbb/"], "\x19" => [0, "\xbb3"], "\x1a" => [0, "\xbb4"], "\x1b" => [0, "\xbb5"], "\x1c" => [0, "\xbb6"], "\x1d" => [0, "\xbb7"], "\x1e" => [0, "\xbb8"], "\x1f" => [0, "\xbb9"], " " => [0, "\xbb="], "!" => [0, "\xbbA"], "\"" => [0, "\xbb_"], "#" => [0, "\xbbb"], "\$" => [0, "\xbbd"], "%" => [0, "\xbbf"], "&" => [0, "\xbbg"], "'" => [0, "\xbbh"], "(" => [0, "\xbbl"], ")" => [0, "\xbbm"], "*" => [0, "\xbbn"], "+" => [0, "\xbbp"], "," => [0, "\xbbr"], "-" => [0, "\xbbu"], "." => [100, "\xbb"], "/" => [110, "\xbb"], [111, "\xbb"], [115, "\xbb"], [116, "\xbb"], [118, "\xbb"], [119, "\xbb"], [122, "\xbb"], [123, "\xbb"], [125, "\xbb"], [126, "\xbb"], [129, "\xbb"], ":" => [143, "\xbb"], ";" => [148, "\xbb"], "<" => [151, "\xbb"], "=" => [153, "\xbb"], ">" => [83, "\xbb"], "?" => [10, "\xbb"], "@" => [77, "\xbd0"], "A" => [18, "\xbd0"], "B" => [77, "\xbd1"], "C" => [18, "\xbd1"], "D" => [77, "\xbd2"], "E" => [18, "\xbd2"], "F" => [77, "\xbda"], "G" => [18, "\xbda"], "H" => [77, "\xbdc"], "I" => [18, "\xbdc"], "J" => [77, "\xbde"], "K" => [18, "\xbde"], "L" => [77, "\xbdi"], "M" => [18, "\xbdi"], "N" => [77, "\xbdo"], "O" => [18, "\xbdo"], "P" => [77, "\xbds"], "Q" => [18, "\xbds"], "R" => [77, "\xbdt"], "S" => [18, "\xbdt"], "T" => [0, "\xbd "], "U" => [0, "\xbd%"], "V" => [0, "\xbd-"], "W" => [0, "\xbd."], "X" => [0, "\xbd/"], "Y" => [0, "\xbd3"], "Z" => [0, "\xbd4"], "[" => [0, "\xbd5"], "\\" => [0, "\xbd6"], "]" => [0, "\xbd7"], "^" => [0, "\xbd8"], "_" => [0, "\xbd9"], "`" => [0, "\xbd="], "a" => [0, "\xbdA"], "b" => [0, "\xbd_"], "c" => [0, "\xbdb"], "d" => [0, "\xbdd"], "e" => [0, "\xbdf"], "f" => [0, "\xbdg"], "g" => [0, "\xbdh"], "h" => [0, "\xbdl"], "i" => [0, "\xbdm"], "j" => [0, "\xbdn"], "k" => [0, "\xbdp"], "l" => [0, "\xbdr"], "m" => [0, "\xbdu"], "n" => [100, "\xbd"], "o" => [110, "\xbd"], "p" => [111, "\xbd"], "q" => [115, "\xbd"], "r" => [116, "\xbd"], "s" => [118, "\xbd"], "t" => [119, "\xbd"], "u" => [122, "\xbd"], "v" => [123, "\xbd"], "w" => [125, "\xbd"], "x" => [126, "\xbd"], "y" => [129, "\xbd"], "z" => [143, "\xbd"], "{" => [148, "\xbd"], "|" => [151, "\xbd"], "}" => [153, "\xbd"], "~" => [83, "\xbd"], "" => [10, "\xbd"], "\x80" => [77, "\xbe0"], "\x81" => [18, "\xbe0"], "\x82" => [77, "\xbe1"], "\x83" => [18, "\xbe1"], "\x84" => [77, "\xbe2"], "\x85" => [18, "\xbe2"], "\x86" => [77, "\xbea"], "\x87" => [18, "\xbea"], "\x88" => [77, "\xbec"], "\x89" => [18, "\xbec"], "\x8a" => [77, "\xbee"], "\x8b" => [18, "\xbee"], "\x8c" => [77, "\xbei"], "\x8d" => [18, "\xbei"], "\x8e" => [77, "\xbeo"], "\x8f" => [18, "\xbeo"], "\x90" => [77, "\xbes"], "\x91" => [18, "\xbes"], "\x92" => [77, "\xbet"], "\x93" => [18, "\xbet"], "\x94" => [0, "\xbe "], "\x95" => [0, "\xbe%"], "\x96" => [0, "\xbe-"], "\x97" => [0, "\xbe."], "\x98" => [0, "\xbe/"], "\x99" => [0, "\xbe3"], "\x9a" => [0, "\xbe4"], "\x9b" => [0, "\xbe5"], "\x9c" => [0, "\xbe6"], "\x9d" => [0, "\xbe7"], "\x9e" => [0, "\xbe8"], "\x9f" => [0, "\xbe9"], "\xa0" => [0, "\xbe="], "\xa1" => [0, "\xbeA"], "\xa2" => [0, "\xbe_"], "\xa3" => [0, "\xbeb"], "\xa4" => [0, "\xbed"], "\xa5" => [0, "\xbef"], "\xa6" => [0, "\xbeg"], "\xa7" => [0, "\xbeh"], "\xa8" => [0, "\xbel"], "\xa9" => [0, "\xbem"], "\xaa" => [0, "\xben"], "\xab" => [0, "\xbep"], "\xac" => [0, "\xber"], "\xad" => [0, "\xbeu"], "\xae" => [100, "\xbe"], "\xaf" => [110, "\xbe"], "\xb0" => [111, "\xbe"], "\xb1" => [115, "\xbe"], "\xb2" => [116, "\xbe"], "\xb3" => [118, "\xbe"], "\xb4" => [119, "\xbe"], "\xb5" => [122, "\xbe"], "\xb6" => [123, "\xbe"], "\xb7" => [125, "\xbe"], "\xb8" => [126, "\xbe"], "\xb9" => [129, "\xbe"], "\xba" => [143, "\xbe"], "\xbb" => [148, "\xbe"], "\xbc" => [151, "\xbe"], "\xbd" => [153, "\xbe"], "\xbe" => [83, "\xbe"], "\xbf" => [10, "\xbe"], "\xc0" => [77, "\xc40"], "\xc1" => [18, "\xc40"], "\xc2" => [77, "\xc41"], "\xc3" => [18, "\xc41"], "\xc4" => [77, "\xc42"], "\xc5" => [18, "\xc42"], "\xc6" => [77, "\xc4a"], "\xc7" => [18, "\xc4a"], "\xc8" => [77, "\xc4c"], "\xc9" => [18, "\xc4c"], "\xca" => [77, "\xc4e"], "\xcb" => [18, "\xc4e"], "\xcc" => [77, "\xc4i"], "\xcd" => [18, "\xc4i"], "\xce" => [77, "\xc4o"], "\xcf" => [18, "\xc4o"], "\xd0" => [77, "\xc4s"], "\xd1" => [18, "\xc4s"], "\xd2" => [77, "\xc4t"], "\xd3" => [18, "\xc4t"], "\xd4" => [0, "\xc4 "], "\xd5" => [0, "\xc4%"], "\xd6" => [0, "\xc4-"], "\xd7" => [0, "\xc4."], "\xd8" => [0, "\xc4/"], "\xd9" => [0, "\xc43"], "\xda" => [0, "\xc44"], "\xdb" => [0, "\xc45"], "\xdc" => [0, "\xc46"], "\xdd" => [0, "\xc47"], "\xde" => [0, "\xc48"], "\xdf" => [0, "\xc49"], "\xe0" => [0, "\xc4="], "\xe1" => [0, "\xc4A"], "\xe2" => [0, "\xc4_"], "\xe3" => [0, "\xc4b"], "\xe4" => [0, "\xc4d"], "\xe5" => [0, "\xc4f"], "\xe6" => [0, "\xc4g"], "\xe7" => [0, "\xc4h"], "\xe8" => [0, "\xc4l"], "\xe9" => [0, "\xc4m"], "\xea" => [0, "\xc4n"], "\xeb" => [0, "\xc4p"], "\xec" => [0, "\xc4r"], "\xed" => [0, "\xc4u"], "\xee" => [100, "\xc4"], "\xef" => [110, "\xc4"], "\xf0" => [111, "\xc4"], "\xf1" => [115, "\xc4"], "\xf2" => [116, "\xc4"], "\xf3" => [118, "\xc4"], "\xf4" => [119, "\xc4"], "\xf5" => [122, "\xc4"], "\xf6" => [123, "\xc4"], "\xf7" => [125, "\xc4"], "\xf8" => [126, "\xc4"], "\xf9" => [129, "\xc4"], "\xfa" => [143, "\xc4"], "\xfb" => [148, "\xc4"], "\xfc" => [151, "\xc4"], "\xfd" => [153, "\xc4"], "\xfe" => [83, "\xc4"], "\xff" => [10, "\xc4"]], ["\x00" => [94, "\xbc0"], "\x01" => [76, "\xbc0"], "\x02" => [104, "\xbc0"], "\x03" => [16, "\xbc0"], "\x04" => [94, "\xbc1"], "\x05" => [76, "\xbc1"], "\x06" => [104, "\xbc1"], "\x07" => [16, "\xbc1"], "\x08" => [94, "\xbc2"], "\t" => [76, "\xbc2"], "\n" => [104, "\xbc2"], "\v" => [16, "\xbc2"], "\f" => [94, "\xbca"], "\r" => [76, "\xbca"], "\x0e" => [104, "\xbca"], "\x0f" => [16, "\xbca"], "\x10" => [94, "\xbcc"], "\x11" => [76, "\xbcc"], "\x12" => [104, "\xbcc"], "\x13" => [16, "\xbcc"], "\x14" => [94, "\xbce"], "\x15" => [76, "\xbce"], "\x16" => [104, "\xbce"], "\x17" => [16, "\xbce"], "\x18" => [94, "\xbci"], "\x19" => [76, "\xbci"], "\x1a" => [104, "\xbci"], "\x1b" => [16, "\xbci"], "\x1c" => [94, "\xbco"], "\x1d" => [76, "\xbco"], "\x1e" => [104, "\xbco"], "\x1f" => [16, "\xbco"], " " => [94, "\xbcs"], "!" => [76, "\xbcs"], "\"" => [104, "\xbcs"], "#" => [16, "\xbcs"], "\$" => [94, "\xbct"], "%" => [76, "\xbct"], "&" => [104, "\xbct"], "'" => [16, "\xbct"], "(" => [77, "\xbc "], ")" => [18, "\xbc "], "*" => [77, "\xbc%"], "+" => [18, "\xbc%"], "," => [77, "\xbc-"], "-" => [18, "\xbc-"], "." => [77, "\xbc."], "/" => [18, "\xbc."], [77, "\xbc/"], [18, "\xbc/"], [77, "\xbc3"], [18, "\xbc3"], [77, "\xbc4"], [18, "\xbc4"], [77, "\xbc5"], [18, "\xbc5"], [77, "\xbc6"], [18, "\xbc6"], ":" => [77, "\xbc7"], ";" => [18, "\xbc7"], "<" => [77, "\xbc8"], "=" => [18, "\xbc8"], ">" => [77, "\xbc9"], "?" => [18, "\xbc9"], "@" => [77, "\xbc="], "A" => [18, "\xbc="], "B" => [77, "\xbcA"], "C" => [18, "\xbcA"], "D" => [77, "\xbc_"], "E" => [18, "\xbc_"], "F" => [77, "\xbcb"], "G" => [18, "\xbcb"], "H" => [77, "\xbcd"], "I" => [18, "\xbcd"], "J" => [77, "\xbcf"], "K" => [18, "\xbcf"], "L" => [77, "\xbcg"], "M" => [18, "\xbcg"], "N" => [77, "\xbch"], "O" => [18, "\xbch"], "P" => [77, "\xbcl"], "Q" => [18, "\xbcl"], "R" => [77, "\xbcm"], "S" => [18, "\xbcm"], "T" => [77, "\xbcn"], "U" => [18, "\xbcn"], "V" => [77, "\xbcp"], "W" => [18, "\xbcp"], "X" => [77, "\xbcr"], "Y" => [18, "\xbcr"], "Z" => [77, "\xbcu"], "[" => [18, "\xbcu"], "\\" => [0, "\xbc:"], "]" => [0, "\xbcB"], "^" => [0, "\xbcC"], "_" => [0, "\xbcD"], "`" => [0, "\xbcE"], "a" => [0, "\xbcF"], "b" => [0, "\xbcG"], "c" => [0, "\xbcH"], "d" => [0, "\xbcI"], "e" => [0, "\xbcJ"], "f" => [0, "\xbcK"], "g" => [0, "\xbcL"], "h" => [0, "\xbcM"], "i" => [0, "\xbcN"], "j" => [0, "\xbcO"], "k" => [0, "\xbcP"], "l" => [0, "\xbcQ"], "m" => [0, "\xbcR"], "n" => [0, "\xbcS"], "o" => [0, "\xbcT"], "p" => [0, "\xbcU"], "q" => [0, "\xbcV"], "r" => [0, "\xbcW"], "s" => [0, "\xbcY"], "t" => [0, "\xbcj"], "u" => [0, "\xbck"], "v" => [0, "\xbcq"], "w" => [0, "\xbcv"], "x" => [0, "\xbcw"], "y" => [0, "\xbcx"], "z" => [0, "\xbcy"], "{" => [0, "\xbcz"], "|" => [82, "\xbc"], "}" => [87, "\xbc"], "~" => [130, "\xbc"], "" => [9, "\xbc"], "\x80" => [94, "\xbf0"], "\x81" => [76, "\xbf0"], "\x82" => [104, "\xbf0"], "\x83" => [16, "\xbf0"], "\x84" => [94, "\xbf1"], "\x85" => [76, "\xbf1"], "\x86" => [104, "\xbf1"], "\x87" => [16, "\xbf1"], "\x88" => [94, "\xbf2"], "\x89" => [76, "\xbf2"], "\x8a" => [104, "\xbf2"], "\x8b" => [16, "\xbf2"], "\x8c" => [94, "\xbfa"], "\x8d" => [76, "\xbfa"], "\x8e" => [104, "\xbfa"], "\x8f" => [16, "\xbfa"], "\x90" => [94, "\xbfc"], "\x91" => [76, "\xbfc"], "\x92" => [104, "\xbfc"], "\x93" => [16, "\xbfc"], "\x94" => [94, "\xbfe"], "\x95" => [76, "\xbfe"], "\x96" => [104, "\xbfe"], "\x97" => [16, "\xbfe"], "\x98" => [94, "\xbfi"], "\x99" => [76, "\xbfi"], "\x9a" => [104, "\xbfi"], "\x9b" => [16, "\xbfi"], "\x9c" => [94, "\xbfo"], "\x9d" => [76, "\xbfo"], "\x9e" => [104, "\xbfo"], "\x9f" => [16, "\xbfo"], "\xa0" => [94, "\xbfs"], "\xa1" => [76, "\xbfs"], "\xa2" => [104, "\xbfs"], "\xa3" => [16, "\xbfs"], "\xa4" => [94, "\xbft"], "\xa5" => [76, "\xbft"], "\xa6" => [104, "\xbft"], "\xa7" => [16, "\xbft"], "\xa8" => [77, "\xbf "], "\xa9" => [18, "\xbf "], "\xaa" => [77, "\xbf%"], "\xab" => [18, "\xbf%"], "\xac" => [77, "\xbf-"], "\xad" => [18, "\xbf-"], "\xae" => [77, "\xbf."], "\xaf" => [18, "\xbf."], "\xb0" => [77, "\xbf/"], "\xb1" => [18, "\xbf/"], "\xb2" => [77, "\xbf3"], "\xb3" => [18, "\xbf3"], "\xb4" => [77, "\xbf4"], "\xb5" => [18, "\xbf4"], "\xb6" => [77, "\xbf5"], "\xb7" => [18, "\xbf5"], "\xb8" => [77, "\xbf6"], "\xb9" => [18, "\xbf6"], "\xba" => [77, "\xbf7"], "\xbb" => [18, "\xbf7"], "\xbc" => [77, "\xbf8"], "\xbd" => [18, "\xbf8"], "\xbe" => [77, "\xbf9"], "\xbf" => [18, "\xbf9"], "\xc0" => [77, "\xbf="], "\xc1" => [18, "\xbf="], "\xc2" => [77, "\xbfA"], "\xc3" => [18, "\xbfA"], "\xc4" => [77, "\xbf_"], "\xc5" => [18, "\xbf_"], "\xc6" => [77, "\xbfb"], "\xc7" => [18, "\xbfb"], "\xc8" => [77, "\xbfd"], "\xc9" => [18, "\xbfd"], "\xca" => [77, "\xbff"], "\xcb" => [18, "\xbff"], "\xcc" => [77, "\xbfg"], "\xcd" => [18, "\xbfg"], "\xce" => [77, "\xbfh"], "\xcf" => [18, "\xbfh"], "\xd0" => [77, "\xbfl"], "\xd1" => [18, "\xbfl"], "\xd2" => [77, "\xbfm"], "\xd3" => [18, "\xbfm"], "\xd4" => [77, "\xbfn"], "\xd5" => [18, "\xbfn"], "\xd6" => [77, "\xbfp"], "\xd7" => [18, "\xbfp"], "\xd8" => [77, "\xbfr"], "\xd9" => [18, "\xbfr"], "\xda" => [77, "\xbfu"], "\xdb" => [18, "\xbfu"], "\xdc" => [0, "\xbf:"], "\xdd" => [0, "\xbfB"], "\xde" => [0, "\xbfC"], "\xdf" => [0, "\xbfD"], "\xe0" => [0, "\xbfE"], "\xe1" => [0, "\xbfF"], "\xe2" => [0, "\xbfG"], "\xe3" => [0, "\xbfH"], "\xe4" => [0, "\xbfI"], "\xe5" => [0, "\xbfJ"], "\xe6" => [0, "\xbfK"], "\xe7" => [0, "\xbfL"], "\xe8" => [0, "\xbfM"], "\xe9" => [0, "\xbfN"], "\xea" => [0, "\xbfO"], "\xeb" => [0, "\xbfP"], "\xec" => [0, "\xbfQ"], "\xed" => [0, "\xbfR"], "\xee" => [0, "\xbfS"], "\xef" => [0, "\xbfT"], "\xf0" => [0, "\xbfU"], "\xf1" => [0, "\xbfV"], "\xf2" => [0, "\xbfW"], "\xf3" => [0, "\xbfY"], "\xf4" => [0, "\xbfj"], "\xf5" => [0, "\xbfk"], "\xf6" => [0, "\xbfq"], "\xf7" => [0, "\xbfv"], "\xf8" => [0, "\xbfw"], "\xf9" => [0, "\xbfx"], "\xfa" => [0, "\xbfy"], "\xfb" => [0, "\xbfz"], "\xfc" => [82, "\xbf"], "\xfd" => [87, "\xbf"], "\xfe" => [130, "\xbf"], "\xff" => [9, "\xbf"]], ["\x00" => [77, "\xbc0"], "\x01" => [18, "\xbc0"], "\x02" => [77, "\xbc1"], "\x03" => [18, "\xbc1"], "\x04" => [77, "\xbc2"], "\x05" => [18, "\xbc2"], "\x06" => [77, "\xbca"], "\x07" => [18, "\xbca"], "\x08" => [77, "\xbcc"], "\t" => [18, "\xbcc"], "\n" => [77, "\xbce"], "\v" => [18, "\xbce"], "\f" => [77, "\xbci"], "\r" => [18, "\xbci"], "\x0e" => [77, "\xbco"], "\x0f" => [18, "\xbco"], "\x10" => [77, "\xbcs"], "\x11" => [18, "\xbcs"], "\x12" => [77, "\xbct"], "\x13" => [18, "\xbct"], "\x14" => [0, "\xbc "], "\x15" => [0, "\xbc%"], "\x16" => [0, "\xbc-"], "\x17" => [0, "\xbc."], "\x18" => [0, "\xbc/"], "\x19" => [0, "\xbc3"], "\x1a" => [0, "\xbc4"], "\x1b" => [0, "\xbc5"], "\x1c" => [0, "\xbc6"], "\x1d" => [0, "\xbc7"], "\x1e" => [0, "\xbc8"], "\x1f" => [0, "\xbc9"], " " => [0, "\xbc="], "!" => [0, "\xbcA"], "\"" => [0, "\xbc_"], "#" => [0, "\xbcb"], "\$" => [0, "\xbcd"], "%" => [0, "\xbcf"], "&" => [0, "\xbcg"], "'" => [0, "\xbch"], "(" => [0, "\xbcl"], ")" => [0, "\xbcm"], "*" => [0, "\xbcn"], "+" => [0, "\xbcp"], "," => [0, "\xbcr"], "-" => [0, "\xbcu"], "." => [100, "\xbc"], "/" => [110, "\xbc"], [111, "\xbc"], [115, "\xbc"], [116, "\xbc"], [118, "\xbc"], [119, "\xbc"], [122, "\xbc"], [123, "\xbc"], [125, "\xbc"], [126, "\xbc"], [129, "\xbc"], ":" => [143, "\xbc"], ";" => [148, "\xbc"], "<" => [151, "\xbc"], "=" => [153, "\xbc"], ">" => [83, "\xbc"], "?" => [10, "\xbc"], "@" => [77, "\xbf0"], "A" => [18, "\xbf0"], "B" => [77, "\xbf1"], "C" => [18, "\xbf1"], "D" => [77, "\xbf2"], "E" => [18, "\xbf2"], "F" => [77, "\xbfa"], "G" => [18, "\xbfa"], "H" => [77, "\xbfc"], "I" => [18, "\xbfc"], "J" => [77, "\xbfe"], "K" => [18, "\xbfe"], "L" => [77, "\xbfi"], "M" => [18, "\xbfi"], "N" => [77, "\xbfo"], "O" => [18, "\xbfo"], "P" => [77, "\xbfs"], "Q" => [18, "\xbfs"], "R" => [77, "\xbft"], "S" => [18, "\xbft"], "T" => [0, "\xbf "], "U" => [0, "\xbf%"], "V" => [0, "\xbf-"], "W" => [0, "\xbf."], "X" => [0, "\xbf/"], "Y" => [0, "\xbf3"], "Z" => [0, "\xbf4"], "[" => [0, "\xbf5"], "\\" => [0, "\xbf6"], "]" => [0, "\xbf7"], "^" => [0, "\xbf8"], "_" => [0, "\xbf9"], "`" => [0, "\xbf="], "a" => [0, "\xbfA"], "b" => [0, "\xbf_"], "c" => [0, "\xbfb"], "d" => [0, "\xbfd"], "e" => [0, "\xbff"], "f" => [0, "\xbfg"], "g" => [0, "\xbfh"], "h" => [0, "\xbfl"], "i" => [0, "\xbfm"], "j" => [0, "\xbfn"], "k" => [0, "\xbfp"], "l" => [0, "\xbfr"], "m" => [0, "\xbfu"], "n" => [100, "\xbf"], "o" => [110, "\xbf"], "p" => [111, "\xbf"], "q" => [115, "\xbf"], "r" => [116, "\xbf"], "s" => [118, "\xbf"], "t" => [119, "\xbf"], "u" => [122, "\xbf"], "v" => [123, "\xbf"], "w" => [125, "\xbf"], "x" => [126, "\xbf"], "y" => [129, "\xbf"], "z" => [143, "\xbf"], "{" => [148, "\xbf"], "|" => [151, "\xbf"], "}" => [153, "\xbf"], "~" => [83, "\xbf"], "" => [10, "\xbf"], "\x80" => [77, "\xc50"], "\x81" => [18, "\xc50"], "\x82" => [77, "\xc51"], "\x83" => [18, "\xc51"], "\x84" => [77, "\xc52"], "\x85" => [18, "\xc52"], "\x86" => [77, "\xc5a"], "\x87" => [18, "\xc5a"], "\x88" => [77, "\xc5c"], "\x89" => [18, "\xc5c"], "\x8a" => [77, "\xc5e"], "\x8b" => [18, "\xc5e"], "\x8c" => [77, "\xc5i"], "\x8d" => [18, "\xc5i"], "\x8e" => [77, "\xc5o"], "\x8f" => [18, "\xc5o"], "\x90" => [77, "\xc5s"], "\x91" => [18, "\xc5s"], "\x92" => [77, "\xc5t"], "\x93" => [18, "\xc5t"], "\x94" => [0, "\xc5 "], "\x95" => [0, "\xc5%"], "\x96" => [0, "\xc5-"], "\x97" => [0, "\xc5."], "\x98" => [0, "\xc5/"], "\x99" => [0, "\xc53"], "\x9a" => [0, "\xc54"], "\x9b" => [0, "\xc55"], "\x9c" => [0, "\xc56"], "\x9d" => [0, "\xc57"], "\x9e" => [0, "\xc58"], "\x9f" => [0, "\xc59"], "\xa0" => [0, "\xc5="], "\xa1" => [0, "\xc5A"], "\xa2" => [0, "\xc5_"], "\xa3" => [0, "\xc5b"], "\xa4" => [0, "\xc5d"], "\xa5" => [0, "\xc5f"], "\xa6" => [0, "\xc5g"], "\xa7" => [0, "\xc5h"], "\xa8" => [0, "\xc5l"], "\xa9" => [0, "\xc5m"], "\xaa" => [0, "\xc5n"], "\xab" => [0, "\xc5p"], "\xac" => [0, "\xc5r"], "\xad" => [0, "\xc5u"], "\xae" => [100, "\xc5"], "\xaf" => [110, "\xc5"], "\xb0" => [111, "\xc5"], "\xb1" => [115, "\xc5"], "\xb2" => [116, "\xc5"], "\xb3" => [118, "\xc5"], "\xb4" => [119, "\xc5"], "\xb5" => [122, "\xc5"], "\xb6" => [123, "\xc5"], "\xb7" => [125, "\xc5"], "\xb8" => [126, "\xc5"], "\xb9" => [129, "\xc5"], "\xba" => [143, "\xc5"], "\xbb" => [148, "\xc5"], "\xbc" => [151, "\xc5"], "\xbd" => [153, "\xc5"], "\xbe" => [83, "\xc5"], "\xbf" => [10, "\xc5"], "\xc0" => [77, "\xe70"], "\xc1" => [18, "\xe70"], "\xc2" => [77, "\xe71"], "\xc3" => [18, "\xe71"], "\xc4" => [77, "\xe72"], "\xc5" => [18, "\xe72"], "\xc6" => [77, "\xe7a"], "\xc7" => [18, "\xe7a"], "\xc8" => [77, "\xe7c"], "\xc9" => [18, "\xe7c"], "\xca" => [77, "\xe7e"], "\xcb" => [18, "\xe7e"], "\xcc" => [77, "\xe7i"], "\xcd" => [18, "\xe7i"], "\xce" => [77, "\xe7o"], "\xcf" => [18, "\xe7o"], "\xd0" => [77, "\xe7s"], "\xd1" => [18, "\xe7s"], "\xd2" => [77, "\xe7t"], "\xd3" => [18, "\xe7t"], "\xd4" => [0, "\xe7 "], "\xd5" => [0, "\xe7%"], "\xd6" => [0, "\xe7-"], "\xd7" => [0, "\xe7."], "\xd8" => [0, "\xe7/"], "\xd9" => [0, "\xe73"], "\xda" => [0, "\xe74"], "\xdb" => [0, "\xe75"], "\xdc" => [0, "\xe76"], "\xdd" => [0, "\xe77"], "\xde" => [0, "\xe78"], "\xdf" => [0, "\xe79"], "\xe0" => [0, "\xe7="], "\xe1" => [0, "\xe7A"], "\xe2" => [0, "\xe7_"], "\xe3" => [0, "\xe7b"], "\xe4" => [0, "\xe7d"], "\xe5" => [0, "\xe7f"], "\xe6" => [0, "\xe7g"], "\xe7" => [0, "\xe7h"], "\xe8" => [0, "\xe7l"], "\xe9" => [0, "\xe7m"], "\xea" => [0, "\xe7n"], "\xeb" => [0, "\xe7p"], "\xec" => [0, "\xe7r"], "\xed" => [0, "\xe7u"], "\xee" => [100, "\xe7"], "\xef" => [110, "\xe7"], "\xf0" => [111, "\xe7"], "\xf1" => [115, "\xe7"], "\xf2" => [116, "\xe7"], "\xf3" => [118, "\xe7"], "\xf4" => [119, "\xe7"], "\xf5" => [122, "\xe7"], "\xf6" => [123, "\xe7"], "\xf7" => [125, "\xe7"], "\xf8" => [126, "\xe7"], "\xf9" => [129, "\xe7"], "\xfa" => [143, "\xe7"], "\xfb" => [148, "\xe7"], "\xfc" => [151, "\xe7"], "\xfd" => [153, "\xe7"], "\xfe" => [83, "\xe7"], "\xff" => [10, "\xe7"]], ["\x00" => [94, "\xbe0"], "\x01" => [76, "\xbe0"], "\x02" => [104, "\xbe0"], "\x03" => [16, "\xbe0"], "\x04" => [94, "\xbe1"], "\x05" => [76, "\xbe1"], "\x06" => [104, "\xbe1"], "\x07" => [16, "\xbe1"], "\x08" => [94, "\xbe2"], "\t" => [76, "\xbe2"], "\n" => [104, "\xbe2"], "\v" => [16, "\xbe2"], "\f" => [94, "\xbea"], "\r" => [76, "\xbea"], "\x0e" => [104, "\xbea"], "\x0f" => [16, "\xbea"], "\x10" => [94, "\xbec"], "\x11" => [76, "\xbec"], "\x12" => [104, "\xbec"], "\x13" => [16, "\xbec"], "\x14" => [94, "\xbee"], "\x15" => [76, "\xbee"], "\x16" => [104, "\xbee"], "\x17" => [16, "\xbee"], "\x18" => [94, "\xbei"], "\x19" => [76, "\xbei"], "\x1a" => [104, "\xbei"], "\x1b" => [16, "\xbei"], "\x1c" => [94, "\xbeo"], "\x1d" => [76, "\xbeo"], "\x1e" => [104, "\xbeo"], "\x1f" => [16, "\xbeo"], " " => [94, "\xbes"], "!" => [76, "\xbes"], "\"" => [104, "\xbes"], "#" => [16, "\xbes"], "\$" => [94, "\xbet"], "%" => [76, "\xbet"], "&" => [104, "\xbet"], "'" => [16, "\xbet"], "(" => [77, "\xbe "], ")" => [18, "\xbe "], "*" => [77, "\xbe%"], "+" => [18, "\xbe%"], "," => [77, "\xbe-"], "-" => [18, "\xbe-"], "." => [77, "\xbe."], "/" => [18, "\xbe."], [77, "\xbe/"], [18, "\xbe/"], [77, "\xbe3"], [18, "\xbe3"], [77, "\xbe4"], [18, "\xbe4"], [77, "\xbe5"], [18, "\xbe5"], [77, "\xbe6"], [18, "\xbe6"], ":" => [77, "\xbe7"], ";" => [18, "\xbe7"], "<" => [77, "\xbe8"], "=" => [18, "\xbe8"], ">" => [77, "\xbe9"], "?" => [18, "\xbe9"], "@" => [77, "\xbe="], "A" => [18, "\xbe="], "B" => [77, "\xbeA"], "C" => [18, "\xbeA"], "D" => [77, "\xbe_"], "E" => [18, "\xbe_"], "F" => [77, "\xbeb"], "G" => [18, "\xbeb"], "H" => [77, "\xbed"], "I" => [18, "\xbed"], "J" => [77, "\xbef"], "K" => [18, "\xbef"], "L" => [77, "\xbeg"], "M" => [18, "\xbeg"], "N" => [77, "\xbeh"], "O" => [18, "\xbeh"], "P" => [77, "\xbel"], "Q" => [18, "\xbel"], "R" => [77, "\xbem"], "S" => [18, "\xbem"], "T" => [77, "\xben"], "U" => [18, "\xben"], "V" => [77, "\xbep"], "W" => [18, "\xbep"], "X" => [77, "\xber"], "Y" => [18, "\xber"], "Z" => [77, "\xbeu"], "[" => [18, "\xbeu"], "\\" => [0, "\xbe:"], "]" => [0, "\xbeB"], "^" => [0, "\xbeC"], "_" => [0, "\xbeD"], "`" => [0, "\xbeE"], "a" => [0, "\xbeF"], "b" => [0, "\xbeG"], "c" => [0, "\xbeH"], "d" => [0, "\xbeI"], "e" => [0, "\xbeJ"], "f" => [0, "\xbeK"], "g" => [0, "\xbeL"], "h" => [0, "\xbeM"], "i" => [0, "\xbeN"], "j" => [0, "\xbeO"], "k" => [0, "\xbeP"], "l" => [0, "\xbeQ"], "m" => [0, "\xbeR"], "n" => [0, "\xbeS"], "o" => [0, "\xbeT"], "p" => [0, "\xbeU"], "q" => [0, "\xbeV"], "r" => [0, "\xbeW"], "s" => [0, "\xbeY"], "t" => [0, "\xbej"], "u" => [0, "\xbek"], "v" => [0, "\xbeq"], "w" => [0, "\xbev"], "x" => [0, "\xbew"], "y" => [0, "\xbex"], "z" => [0, "\xbey"], "{" => [0, "\xbez"], "|" => [82, "\xbe"], "}" => [87, "\xbe"], "~" => [130, "\xbe"], "" => [9, "\xbe"], "\x80" => [94, "\xc40"], "\x81" => [76, "\xc40"], "\x82" => [104, "\xc40"], "\x83" => [16, "\xc40"], "\x84" => [94, "\xc41"], "\x85" => [76, "\xc41"], "\x86" => [104, "\xc41"], "\x87" => [16, "\xc41"], "\x88" => [94, "\xc42"], "\x89" => [76, "\xc42"], "\x8a" => [104, "\xc42"], "\x8b" => [16, "\xc42"], "\x8c" => [94, "\xc4a"], "\x8d" => [76, "\xc4a"], "\x8e" => [104, "\xc4a"], "\x8f" => [16, "\xc4a"], "\x90" => [94, "\xc4c"], "\x91" => [76, "\xc4c"], "\x92" => [104, "\xc4c"], "\x93" => [16, "\xc4c"], "\x94" => [94, "\xc4e"], "\x95" => [76, "\xc4e"], "\x96" => [104, "\xc4e"], "\x97" => [16, "\xc4e"], "\x98" => [94, "\xc4i"], "\x99" => [76, "\xc4i"], "\x9a" => [104, "\xc4i"], "\x9b" => [16, "\xc4i"], "\x9c" => [94, "\xc4o"], "\x9d" => [76, "\xc4o"], "\x9e" => [104, "\xc4o"], "\x9f" => [16, "\xc4o"], "\xa0" => [94, "\xc4s"], "\xa1" => [76, "\xc4s"], "\xa2" => [104, "\xc4s"], "\xa3" => [16, "\xc4s"], "\xa4" => [94, "\xc4t"], "\xa5" => [76, "\xc4t"], "\xa6" => [104, "\xc4t"], "\xa7" => [16, "\xc4t"], "\xa8" => [77, "\xc4 "], "\xa9" => [18, "\xc4 "], "\xaa" => [77, "\xc4%"], "\xab" => [18, "\xc4%"], "\xac" => [77, "\xc4-"], "\xad" => [18, "\xc4-"], "\xae" => [77, "\xc4."], "\xaf" => [18, "\xc4."], "\xb0" => [77, "\xc4/"], "\xb1" => [18, "\xc4/"], "\xb2" => [77, "\xc43"], "\xb3" => [18, "\xc43"], "\xb4" => [77, "\xc44"], "\xb5" => [18, "\xc44"], "\xb6" => [77, "\xc45"], "\xb7" => [18, "\xc45"], "\xb8" => [77, "\xc46"], "\xb9" => [18, "\xc46"], "\xba" => [77, "\xc47"], "\xbb" => [18, "\xc47"], "\xbc" => [77, "\xc48"], "\xbd" => [18, "\xc48"], "\xbe" => [77, "\xc49"], "\xbf" => [18, "\xc49"], "\xc0" => [77, "\xc4="], "\xc1" => [18, "\xc4="], "\xc2" => [77, "\xc4A"], "\xc3" => [18, "\xc4A"], "\xc4" => [77, "\xc4_"], "\xc5" => [18, "\xc4_"], "\xc6" => [77, "\xc4b"], "\xc7" => [18, "\xc4b"], "\xc8" => [77, "\xc4d"], "\xc9" => [18, "\xc4d"], "\xca" => [77, "\xc4f"], "\xcb" => [18, "\xc4f"], "\xcc" => [77, "\xc4g"], "\xcd" => [18, "\xc4g"], "\xce" => [77, "\xc4h"], "\xcf" => [18, "\xc4h"], "\xd0" => [77, "\xc4l"], "\xd1" => [18, "\xc4l"], "\xd2" => [77, "\xc4m"], "\xd3" => [18, "\xc4m"], "\xd4" => [77, "\xc4n"], "\xd5" => [18, "\xc4n"], "\xd6" => [77, "\xc4p"], "\xd7" => [18, "\xc4p"], "\xd8" => [77, "\xc4r"], "\xd9" => [18, "\xc4r"], "\xda" => [77, "\xc4u"], "\xdb" => [18, "\xc4u"], "\xdc" => [0, "\xc4:"], "\xdd" => [0, "\xc4B"], "\xde" => [0, "\xc4C"], "\xdf" => [0, "\xc4D"], "\xe0" => [0, "\xc4E"], "\xe1" => [0, "\xc4F"], "\xe2" => [0, "\xc4G"], "\xe3" => [0, "\xc4H"], "\xe4" => [0, "\xc4I"], "\xe5" => [0, "\xc4J"], "\xe6" => [0, "\xc4K"], "\xe7" => [0, "\xc4L"], "\xe8" => [0, "\xc4M"], "\xe9" => [0, "\xc4N"], "\xea" => [0, "\xc4O"], "\xeb" => [0, "\xc4P"], "\xec" => [0, "\xc4Q"], "\xed" => [0, "\xc4R"], "\xee" => [0, "\xc4S"], "\xef" => [0, "\xc4T"], "\xf0" => [0, "\xc4U"], "\xf1" => [0, "\xc4V"], "\xf2" => [0, "\xc4W"], "\xf3" => [0, "\xc4Y"], "\xf4" => [0, "\xc4j"], "\xf5" => [0, "\xc4k"], "\xf6" => [0, "\xc4q"], "\xf7" => [0, "\xc4v"], "\xf8" => [0, "\xc4w"], "\xf9" => [0, "\xc4x"], "\xfa" => [0, "\xc4y"], "\xfb" => [0, "\xc4z"], "\xfc" => [82, "\xc4"], "\xfd" => [87, "\xc4"], "\xfe" => [130, "\xc4"], "\xff" => [9, "\xc4"]], ["\x00" => [77, "\xc00"], "\x01" => [18, "\xc00"], "\x02" => [77, "\xc01"], "\x03" => [18, "\xc01"], "\x04" => [77, "\xc02"], "\x05" => [18, "\xc02"], "\x06" => [77, "\xc0a"], "\x07" => [18, "\xc0a"], "\x08" => [77, "\xc0c"], "\t" => [18, "\xc0c"], "\n" => [77, "\xc0e"], "\v" => [18, "\xc0e"], "\f" => [77, "\xc0i"], "\r" => [18, "\xc0i"], "\x0e" => [77, "\xc0o"], "\x0f" => [18, "\xc0o"], "\x10" => [77, "\xc0s"], "\x11" => [18, "\xc0s"], "\x12" => [77, "\xc0t"], "\x13" => [18, "\xc0t"], "\x14" => [0, "\xc0 "], "\x15" => [0, "\xc0%"], "\x16" => [0, "\xc0-"], "\x17" => [0, "\xc0."], "\x18" => [0, "\xc0/"], "\x19" => [0, "\xc03"], "\x1a" => [0, "\xc04"], "\x1b" => [0, "\xc05"], "\x1c" => [0, "\xc06"], "\x1d" => [0, "\xc07"], "\x1e" => [0, "\xc08"], "\x1f" => [0, "\xc09"], " " => [0, "\xc0="], "!" => [0, "\xc0A"], "\"" => [0, "\xc0_"], "#" => [0, "\xc0b"], "\$" => [0, "\xc0d"], "%" => [0, "\xc0f"], "&" => [0, "\xc0g"], "'" => [0, "\xc0h"], "(" => [0, "\xc0l"], ")" => [0, "\xc0m"], "*" => [0, "\xc0n"], "+" => [0, "\xc0p"], "," => [0, "\xc0r"], "-" => [0, "\xc0u"], "." => [100, "\xc0"], "/" => [110, "\xc0"], [111, "\xc0"], [115, "\xc0"], [116, "\xc0"], [118, "\xc0"], [119, "\xc0"], [122, "\xc0"], [123, "\xc0"], [125, "\xc0"], [126, "\xc0"], [129, "\xc0"], ":" => [143, "\xc0"], ";" => [148, "\xc0"], "<" => [151, "\xc0"], "=" => [153, "\xc0"], ">" => [83, "\xc0"], "?" => [10, "\xc0"], "@" => [77, "\xc10"], "A" => [18, "\xc10"], "B" => [77, "\xc11"], "C" => [18, "\xc11"], "D" => [77, "\xc12"], "E" => [18, "\xc12"], "F" => [77, "\xc1a"], "G" => [18, "\xc1a"], "H" => [77, "\xc1c"], "I" => [18, "\xc1c"], "J" => [77, "\xc1e"], "K" => [18, "\xc1e"], "L" => [77, "\xc1i"], "M" => [18, "\xc1i"], "N" => [77, "\xc1o"], "O" => [18, "\xc1o"], "P" => [77, "\xc1s"], "Q" => [18, "\xc1s"], "R" => [77, "\xc1t"], "S" => [18, "\xc1t"], "T" => [0, "\xc1 "], "U" => [0, "\xc1%"], "V" => [0, "\xc1-"], "W" => [0, "\xc1."], "X" => [0, "\xc1/"], "Y" => [0, "\xc13"], "Z" => [0, "\xc14"], "[" => [0, "\xc15"], "\\" => [0, "\xc16"], "]" => [0, "\xc17"], "^" => [0, "\xc18"], "_" => [0, "\xc19"], "`" => [0, "\xc1="], "a" => [0, "\xc1A"], "b" => [0, "\xc1_"], "c" => [0, "\xc1b"], "d" => [0, "\xc1d"], "e" => [0, "\xc1f"], "f" => [0, "\xc1g"], "g" => [0, "\xc1h"], "h" => [0, "\xc1l"], "i" => [0, "\xc1m"], "j" => [0, "\xc1n"], "k" => [0, "\xc1p"], "l" => [0, "\xc1r"], "m" => [0, "\xc1u"], "n" => [100, "\xc1"], "o" => [110, "\xc1"], "p" => [111, "\xc1"], "q" => [115, "\xc1"], "r" => [116, "\xc1"], "s" => [118, "\xc1"], "t" => [119, "\xc1"], "u" => [122, "\xc1"], "v" => [123, "\xc1"], "w" => [125, "\xc1"], "x" => [126, "\xc1"], "y" => [129, "\xc1"], "z" => [143, "\xc1"], "{" => [148, "\xc1"], "|" => [151, "\xc1"], "}" => [153, "\xc1"], "~" => [83, "\xc1"], "" => [10, "\xc1"], "\x80" => [77, "\xc80"], "\x81" => [18, "\xc80"], "\x82" => [77, "\xc81"], "\x83" => [18, "\xc81"], "\x84" => [77, "\xc82"], "\x85" => [18, "\xc82"], "\x86" => [77, "\xc8a"], "\x87" => [18, "\xc8a"], "\x88" => [77, "\xc8c"], "\x89" => [18, "\xc8c"], "\x8a" => [77, "\xc8e"], "\x8b" => [18, "\xc8e"], "\x8c" => [77, "\xc8i"], "\x8d" => [18, "\xc8i"], "\x8e" => [77, "\xc8o"], "\x8f" => [18, "\xc8o"], "\x90" => [77, "\xc8s"], "\x91" => [18, "\xc8s"], "\x92" => [77, "\xc8t"], "\x93" => [18, "\xc8t"], "\x94" => [0, "\xc8 "], "\x95" => [0, "\xc8%"], "\x96" => [0, "\xc8-"], "\x97" => [0, "\xc8."], "\x98" => [0, "\xc8/"], "\x99" => [0, "\xc83"], "\x9a" => [0, "\xc84"], "\x9b" => [0, "\xc85"], "\x9c" => [0, "\xc86"], "\x9d" => [0, "\xc87"], "\x9e" => [0, "\xc88"], "\x9f" => [0, "\xc89"], "\xa0" => [0, "\xc8="], "\xa1" => [0, "\xc8A"], "\xa2" => [0, "\xc8_"], "\xa3" => [0, "\xc8b"], "\xa4" => [0, "\xc8d"], "\xa5" => [0, "\xc8f"], "\xa6" => [0, "\xc8g"], "\xa7" => [0, "\xc8h"], "\xa8" => [0, "\xc8l"], "\xa9" => [0, "\xc8m"], "\xaa" => [0, "\xc8n"], "\xab" => [0, "\xc8p"], "\xac" => [0, "\xc8r"], "\xad" => [0, "\xc8u"], "\xae" => [100, "\xc8"], "\xaf" => [110, "\xc8"], "\xb0" => [111, "\xc8"], "\xb1" => [115, "\xc8"], "\xb2" => [116, "\xc8"], "\xb3" => [118, "\xc8"], "\xb4" => [119, "\xc8"], "\xb5" => [122, "\xc8"], "\xb6" => [123, "\xc8"], "\xb7" => [125, "\xc8"], "\xb8" => [126, "\xc8"], "\xb9" => [129, "\xc8"], "\xba" => [143, "\xc8"], "\xbb" => [148, "\xc8"], "\xbc" => [151, "\xc8"], "\xbd" => [153, "\xc8"], "\xbe" => [83, "\xc8"], "\xbf" => [10, "\xc8"], "\xc0" => [77, "\xc90"], "\xc1" => [18, "\xc90"], "\xc2" => [77, "\xc91"], "\xc3" => [18, "\xc91"], "\xc4" => [77, "\xc92"], "\xc5" => [18, "\xc92"], "\xc6" => [77, "\xc9a"], "\xc7" => [18, "\xc9a"], "\xc8" => [77, "\xc9c"], "\xc9" => [18, "\xc9c"], "\xca" => [77, "\xc9e"], "\xcb" => [18, "\xc9e"], "\xcc" => [77, "\xc9i"], "\xcd" => [18, "\xc9i"], "\xce" => [77, "\xc9o"], "\xcf" => [18, "\xc9o"], "\xd0" => [77, "\xc9s"], "\xd1" => [18, "\xc9s"], "\xd2" => [77, "\xc9t"], "\xd3" => [18, "\xc9t"], "\xd4" => [0, "\xc9 "], "\xd5" => [0, "\xc9%"], "\xd6" => [0, "\xc9-"], "\xd7" => [0, "\xc9."], "\xd8" => [0, "\xc9/"], "\xd9" => [0, "\xc93"], "\xda" => [0, "\xc94"], "\xdb" => [0, "\xc95"], "\xdc" => [0, "\xc96"], "\xdd" => [0, "\xc97"], "\xde" => [0, "\xc98"], "\xdf" => [0, "\xc99"], "\xe0" => [0, "\xc9="], "\xe1" => [0, "\xc9A"], "\xe2" => [0, "\xc9_"], "\xe3" => [0, "\xc9b"], "\xe4" => [0, "\xc9d"], "\xe5" => [0, "\xc9f"], "\xe6" => [0, "\xc9g"], "\xe7" => [0, "\xc9h"], "\xe8" => [0, "\xc9l"], "\xe9" => [0, "\xc9m"], "\xea" => [0, "\xc9n"], "\xeb" => [0, "\xc9p"], "\xec" => [0, "\xc9r"], "\xed" => [0, "\xc9u"], "\xee" => [100, "\xc9"], "\xef" => [110, "\xc9"], "\xf0" => [111, "\xc9"], "\xf1" => [115, "\xc9"], "\xf2" => [116, "\xc9"], "\xf3" => [118, "\xc9"], "\xf4" => [119, "\xc9"], "\xf5" => [122, "\xc9"], "\xf6" => [123, "\xc9"], "\xf7" => [125, "\xc9"], "\xf8" => [126, "\xc9"], "\xf9" => [129, "\xc9"], "\xfa" => [143, "\xc9"], "\xfb" => [148, "\xc9"], "\xfc" => [151, "\xc9"], "\xfd" => [153, "\xc9"], "\xfe" => [83, "\xc9"], "\xff" => [10, "\xc9"]], ["\x00" => [0, "\xc00"], "\x01" => [0, "\xc01"], "\x02" => [0, "\xc02"], "\x03" => [0, "\xc0a"], "\x04" => [0, "\xc0c"], "\x05" => [0, "\xc0e"], "\x06" => [0, "\xc0i"], "\x07" => [0, "\xc0o"], "\x08" => [0, "\xc0s"], "\t" => [0, "\xc0t"], "\n" => [73, "\xc0"], "\v" => [88, "\xc0"], "\f" => [89, "\xc0"], "\r" => [96, "\xc0"], "\x0e" => [97, "\xc0"], "\x0f" => [99, "\xc0"], "\x10" => [106, "\xc0"], "\x11" => [136, "\xc0"], "\x12" => [139, "\xc0"], "\x13" => [141, "\xc0"], "\x14" => [145, "\xc0"], "\x15" => [147, "\xc0"], "\x16" => [149, "\xc0"], "\x17" => [101, "\xc0"], "\x18" => [112, "\xc0"], "\x19" => [117, "\xc0"], "\x1a" => [120, "\xc0"], "\x1b" => [124, "\xc0"], "\x1c" => [127, "\xc0"], "\x1d" => [144, "\xc0"], "\x1e" => [152, "\xc0"], "\x1f" => [11, "\xc0"], " " => [0, "\xc10"], "!" => [0, "\xc11"], "\"" => [0, "\xc12"], "#" => [0, "\xc1a"], "\$" => [0, "\xc1c"], "%" => [0, "\xc1e"], "&" => [0, "\xc1i"], "'" => [0, "\xc1o"], "(" => [0, "\xc1s"], ")" => [0, "\xc1t"], "*" => [73, "\xc1"], "+" => [88, "\xc1"], "," => [89, "\xc1"], "-" => [96, "\xc1"], "." => [97, "\xc1"], "/" => [99, "\xc1"], [106, "\xc1"], [136, "\xc1"], [139, "\xc1"], [141, "\xc1"], [145, "\xc1"], [147, "\xc1"], [149, "\xc1"], [101, "\xc1"], [112, "\xc1"], [117, "\xc1"], ":" => [120, "\xc1"], ";" => [124, "\xc1"], "<" => [127, "\xc1"], "=" => [144, "\xc1"], ">" => [152, "\xc1"], "?" => [11, "\xc1"], "@" => [0, "\xc80"], "A" => [0, "\xc81"], "B" => [0, "\xc82"], "C" => [0, "\xc8a"], "D" => [0, "\xc8c"], "E" => [0, "\xc8e"], "F" => [0, "\xc8i"], "G" => [0, "\xc8o"], "H" => [0, "\xc8s"], "I" => [0, "\xc8t"], "J" => [73, "\xc8"], "K" => [88, "\xc8"], "L" => [89, "\xc8"], "M" => [96, "\xc8"], "N" => [97, "\xc8"], "O" => [99, "\xc8"], "P" => [106, "\xc8"], "Q" => [136, "\xc8"], "R" => [139, "\xc8"], "S" => [141, "\xc8"], "T" => [145, "\xc8"], "U" => [147, "\xc8"], "V" => [149, "\xc8"], "W" => [101, "\xc8"], "X" => [112, "\xc8"], "Y" => [117, "\xc8"], "Z" => [120, "\xc8"], "[" => [124, "\xc8"], "\\" => [127, "\xc8"], "]" => [144, "\xc8"], "^" => [152, "\xc8"], "_" => [11, "\xc8"], "`" => [0, "\xc90"], "a" => [0, "\xc91"], "b" => [0, "\xc92"], "c" => [0, "\xc9a"], "d" => [0, "\xc9c"], "e" => [0, "\xc9e"], "f" => [0, "\xc9i"], "g" => [0, "\xc9o"], "h" => [0, "\xc9s"], "i" => [0, "\xc9t"], "j" => [73, "\xc9"], "k" => [88, "\xc9"], "l" => [89, "\xc9"], "m" => [96, "\xc9"], "n" => [97, "\xc9"], "o" => [99, "\xc9"], "p" => [106, "\xc9"], "q" => [136, "\xc9"], "r" => [139, "\xc9"], "s" => [141, "\xc9"], "t" => [145, "\xc9"], "u" => [147, "\xc9"], "v" => [149, "\xc9"], "w" => [101, "\xc9"], "x" => [112, "\xc9"], "y" => [117, "\xc9"], "z" => [120, "\xc9"], "{" => [124, "\xc9"], "|" => [127, "\xc9"], "}" => [144, "\xc9"], "~" => [152, "\xc9"], "" => [11, "\xc9"], "\x80" => [0, "\xca0"], "\x81" => [0, "\xca1"], "\x82" => [0, "\xca2"], "\x83" => [0, "\xcaa"], "\x84" => [0, "\xcac"], "\x85" => [0, "\xcae"], "\x86" => [0, "\xcai"], "\x87" => [0, "\xcao"], "\x88" => [0, "\xcas"], "\x89" => [0, "\xcat"], "\x8a" => [73, "\xca"], "\x8b" => [88, "\xca"], "\x8c" => [89, "\xca"], "\x8d" => [96, "\xca"], "\x8e" => [97, "\xca"], "\x8f" => [99, "\xca"], "\x90" => [106, "\xca"], "\x91" => [136, "\xca"], "\x92" => [139, "\xca"], "\x93" => [141, "\xca"], "\x94" => [145, "\xca"], "\x95" => [147, "\xca"], "\x96" => [149, "\xca"], "\x97" => [101, "\xca"], "\x98" => [112, "\xca"], "\x99" => [117, "\xca"], "\x9a" => [120, "\xca"], "\x9b" => [124, "\xca"], "\x9c" => [127, "\xca"], "\x9d" => [144, "\xca"], "\x9e" => [152, "\xca"], "\x9f" => [11, "\xca"], "\xa0" => [0, "\xcd0"], "\xa1" => [0, "\xcd1"], "\xa2" => [0, "\xcd2"], "\xa3" => [0, "\xcda"], "\xa4" => [0, "\xcdc"], "\xa5" => [0, "\xcde"], "\xa6" => [0, "\xcdi"], "\xa7" => [0, "\xcdo"], "\xa8" => [0, "\xcds"], "\xa9" => [0, "\xcdt"], "\xaa" => [73, "\xcd"], "\xab" => [88, "\xcd"], "\xac" => [89, "\xcd"], "\xad" => [96, "\xcd"], "\xae" => [97, "\xcd"], "\xaf" => [99, "\xcd"], "\xb0" => [106, "\xcd"], "\xb1" => [136, "\xcd"], "\xb2" => [139, "\xcd"], "\xb3" => [141, "\xcd"], "\xb4" => [145, "\xcd"], "\xb5" => [147, "\xcd"], "\xb6" => [149, "\xcd"], "\xb7" => [101, "\xcd"], "\xb8" => [112, "\xcd"], "\xb9" => [117, "\xcd"], "\xba" => [120, "\xcd"], "\xbb" => [124, "\xcd"], "\xbc" => [127, "\xcd"], "\xbd" => [144, "\xcd"], "\xbe" => [152, "\xcd"], "\xbf" => [11, "\xcd"], "\xc0" => [0, "\xd20"], "\xc1" => [0, "\xd21"], "\xc2" => [0, "\xd22"], "\xc3" => [0, "\xd2a"], "\xc4" => [0, "\xd2c"], "\xc5" => [0, "\xd2e"], "\xc6" => [0, "\xd2i"], "\xc7" => [0, "\xd2o"], "\xc8" => [0, "\xd2s"], "\xc9" => [0, "\xd2t"], "\xca" => [73, "\xd2"], "\xcb" => [88, "\xd2"], "\xcc" => [89, "\xd2"], "\xcd" => [96, "\xd2"], "\xce" => [97, "\xd2"], "\xcf" => [99, "\xd2"], "\xd0" => [106, "\xd2"], "\xd1" => [136, "\xd2"], "\xd2" => [139, "\xd2"], "\xd3" => [141, "\xd2"], "\xd4" => [145, "\xd2"], "\xd5" => [147, "\xd2"], "\xd6" => [149, "\xd2"], "\xd7" => [101, "\xd2"], "\xd8" => [112, "\xd2"], "\xd9" => [117, "\xd2"], "\xda" => [120, "\xd2"], "\xdb" => [124, "\xd2"], "\xdc" => [127, "\xd2"], "\xdd" => [144, "\xd2"], "\xde" => [152, "\xd2"], "\xdf" => [11, "\xd2"], "\xe0" => [0, "\xd50"], "\xe1" => [0, "\xd51"], "\xe2" => [0, "\xd52"], "\xe3" => [0, "\xd5a"], "\xe4" => [0, "\xd5c"], "\xe5" => [0, "\xd5e"], "\xe6" => [0, "\xd5i"], "\xe7" => [0, "\xd5o"], "\xe8" => [0, "\xd5s"], "\xe9" => [0, "\xd5t"], "\xea" => [73, "\xd5"], "\xeb" => [88, "\xd5"], "\xec" => [89, "\xd5"], "\xed" => [96, "\xd5"], "\xee" => [97, "\xd5"], "\xef" => [99, "\xd5"], "\xf0" => [106, "\xd5"], "\xf1" => [136, "\xd5"], "\xf2" => [139, "\xd5"], "\xf3" => [141, "\xd5"], "\xf4" => [145, "\xd5"], "\xf5" => [147, "\xd5"], "\xf6" => [149, "\xd5"], "\xf7" => [101, "\xd5"], "\xf8" => [112, "\xd5"], "\xf9" => [117, "\xd5"], "\xfa" => [120, "\xd5"], "\xfb" => [124, "\xd5"], "\xfc" => [127, "\xd5"], "\xfd" => [144, "\xd5"], "\xfe" => [152, "\xd5"], "\xff" => [11, "\xd5"]], ["\x00" => [92, "\xc0"], "\x01" => [95, "\xc0"], "\x02" => [137, "\xc0"], "\x03" => [142, "\xc0"], "\x04" => [150, "\xc0"], "\x05" => [74, "\xc0"], "\x06" => [90, "\xc0"], "\x07" => [98, "\xc0"], "\x08" => [107, "\xc0"], "\t" => [140, "\xc0"], "\n" => [146, "\xc0"], "\v" => [102, "\xc0"], "\f" => [113, "\xc0"], "\r" => [121, "\xc0"], "\x0e" => [128, "\xc0"], "\x0f" => [12, "\xc0"], "\x10" => [92, "\xc1"], "\x11" => [95, "\xc1"], "\x12" => [137, "\xc1"], "\x13" => [142, "\xc1"], "\x14" => [150, "\xc1"], "\x15" => [74, "\xc1"], "\x16" => [90, "\xc1"], "\x17" => [98, "\xc1"], "\x18" => [107, "\xc1"], "\x19" => [140, "\xc1"], "\x1a" => [146, "\xc1"], "\x1b" => [102, "\xc1"], "\x1c" => [113, "\xc1"], "\x1d" => [121, "\xc1"], "\x1e" => [128, "\xc1"], "\x1f" => [12, "\xc1"], " " => [92, "\xc8"], "!" => [95, "\xc8"], "\"" => [137, "\xc8"], "#" => [142, "\xc8"], "\$" => [150, "\xc8"], "%" => [74, "\xc8"], "&" => [90, "\xc8"], "'" => [98, "\xc8"], "(" => [107, "\xc8"], ")" => [140, "\xc8"], "*" => [146, "\xc8"], "+" => [102, "\xc8"], "," => [113, "\xc8"], "-" => [121, "\xc8"], "." => [128, "\xc8"], "/" => [12, "\xc8"], [92, "\xc9"], [95, "\xc9"], [137, "\xc9"], [142, "\xc9"], [150, "\xc9"], [74, "\xc9"], [90, "\xc9"], [98, "\xc9"], [107, "\xc9"], [140, "\xc9"], ":" => [146, "\xc9"], ";" => [102, "\xc9"], "<" => [113, "\xc9"], "=" => [121, "\xc9"], ">" => [128, "\xc9"], "?" => [12, "\xc9"], "@" => [92, "\xca"], "A" => [95, "\xca"], "B" => [137, "\xca"], "C" => [142, "\xca"], "D" => [150, "\xca"], "E" => [74, "\xca"], "F" => [90, "\xca"], "G" => [98, "\xca"], "H" => [107, "\xca"], "I" => [140, "\xca"], "J" => [146, "\xca"], "K" => [102, "\xca"], "L" => [113, "\xca"], "M" => [121, "\xca"], "N" => [128, "\xca"], "O" => [12, "\xca"], "P" => [92, "\xcd"], "Q" => [95, "\xcd"], "R" => [137, "\xcd"], "S" => [142, "\xcd"], "T" => [150, "\xcd"], "U" => [74, "\xcd"], "V" => [90, "\xcd"], "W" => [98, "\xcd"], "X" => [107, "\xcd"], "Y" => [140, "\xcd"], "Z" => [146, "\xcd"], "[" => [102, "\xcd"], "\\" => [113, "\xcd"], "]" => [121, "\xcd"], "^" => [128, "\xcd"], "_" => [12, "\xcd"], "`" => [92, "\xd2"], "a" => [95, "\xd2"], "b" => [137, "\xd2"], "c" => [142, "\xd2"], "d" => [150, "\xd2"], "e" => [74, "\xd2"], "f" => [90, "\xd2"], "g" => [98, "\xd2"], "h" => [107, "\xd2"], "i" => [140, "\xd2"], "j" => [146, "\xd2"], "k" => [102, "\xd2"], "l" => [113, "\xd2"], "m" => [121, "\xd2"], "n" => [128, "\xd2"], "o" => [12, "\xd2"], "p" => [92, "\xd5"], "q" => [95, "\xd5"], "r" => [137, "\xd5"], "s" => [142, "\xd5"], "t" => [150, "\xd5"], "u" => [74, "\xd5"], "v" => [90, "\xd5"], "w" => [98, "\xd5"], "x" => [107, "\xd5"], "y" => [140, "\xd5"], "z" => [146, "\xd5"], "{" => [102, "\xd5"], "|" => [113, "\xd5"], "}" => [121, "\xd5"], "~" => [128, "\xd5"], "" => [12, "\xd5"], "\x80" => [92, "\xda"], "\x81" => [95, "\xda"], "\x82" => [137, "\xda"], "\x83" => [142, "\xda"], "\x84" => [150, "\xda"], "\x85" => [74, "\xda"], "\x86" => [90, "\xda"], "\x87" => [98, "\xda"], "\x88" => [107, "\xda"], "\x89" => [140, "\xda"], "\x8a" => [146, "\xda"], "\x8b" => [102, "\xda"], "\x8c" => [113, "\xda"], "\x8d" => [121, "\xda"], "\x8e" => [128, "\xda"], "\x8f" => [12, "\xda"], "\x90" => [92, "\xdb"], "\x91" => [95, "\xdb"], "\x92" => [137, "\xdb"], "\x93" => [142, "\xdb"], "\x94" => [150, "\xdb"], "\x95" => [74, "\xdb"], "\x96" => [90, "\xdb"], "\x97" => [98, "\xdb"], "\x98" => [107, "\xdb"], "\x99" => [140, "\xdb"], "\x9a" => [146, "\xdb"], "\x9b" => [102, "\xdb"], "\x9c" => [113, "\xdb"], "\x9d" => [121, "\xdb"], "\x9e" => [128, "\xdb"], "\x9f" => [12, "\xdb"], "\xa0" => [92, "\xee"], "\xa1" => [95, "\xee"], "\xa2" => [137, "\xee"], "\xa3" => [142, "\xee"], "\xa4" => [150, "\xee"], "\xa5" => [74, "\xee"], "\xa6" => [90, "\xee"], "\xa7" => [98, "\xee"], "\xa8" => [107, "\xee"], "\xa9" => [140, "\xee"], "\xaa" => [146, "\xee"], "\xab" => [102, "\xee"], "\xac" => [113, "\xee"], "\xad" => [121, "\xee"], "\xae" => [128, "\xee"], "\xaf" => [12, "\xee"], "\xb0" => [92, "\xf0"], "\xb1" => [95, "\xf0"], "\xb2" => [137, "\xf0"], "\xb3" => [142, "\xf0"], "\xb4" => [150, "\xf0"], "\xb5" => [74, "\xf0"], "\xb6" => [90, "\xf0"], "\xb7" => [98, "\xf0"], "\xb8" => [107, "\xf0"], "\xb9" => [140, "\xf0"], "\xba" => [146, "\xf0"], "\xbb" => [102, "\xf0"], "\xbc" => [113, "\xf0"], "\xbd" => [121, "\xf0"], "\xbe" => [128, "\xf0"], "\xbf" => [12, "\xf0"], "\xc0" => [92, "\xf2"], "\xc1" => [95, "\xf2"], "\xc2" => [137, "\xf2"], "\xc3" => [142, "\xf2"], "\xc4" => [150, "\xf2"], "\xc5" => [74, "\xf2"], "\xc6" => [90, "\xf2"], "\xc7" => [98, "\xf2"], "\xc8" => [107, "\xf2"], "\xc9" => [140, "\xf2"], "\xca" => [146, "\xf2"], "\xcb" => [102, "\xf2"], "\xcc" => [113, "\xf2"], "\xcd" => [121, "\xf2"], "\xce" => [128, "\xf2"], "\xcf" => [12, "\xf2"], "\xd0" => [92, "\xf3"], "\xd1" => [95, "\xf3"], "\xd2" => [137, "\xf3"], "\xd3" => [142, "\xf3"], "\xd4" => [150, "\xf3"], "\xd5" => [74, "\xf3"], "\xd6" => [90, "\xf3"], "\xd7" => [98, "\xf3"], "\xd8" => [107, "\xf3"], "\xd9" => [140, "\xf3"], "\xda" => [146, "\xf3"], "\xdb" => [102, "\xf3"], "\xdc" => [113, "\xf3"], "\xdd" => [121, "\xf3"], "\xde" => [128, "\xf3"], "\xdf" => [12, "\xf3"], "\xe0" => [92, "\xff"], "\xe1" => [95, "\xff"], "\xe2" => [137, "\xff"], "\xe3" => [142, "\xff"], "\xe4" => [150, "\xff"], "\xe5" => [74, "\xff"], "\xe6" => [90, "\xff"], "\xe7" => [98, "\xff"], "\xe8" => [107, "\xff"], "\xe9" => [140, "\xff"], "\xea" => [146, "\xff"], "\xeb" => [102, "\xff"], "\xec" => [113, "\xff"], "\xed" => [121, "\xff"], "\xee" => [128, "\xff"], "\xef" => [12, "\xff"], "\xf0" => [93, "\xcb"], "\xf1" => [138, "\xcb"], "\xf2" => [75, "\xcb"], "\xf3" => [91, "\xcb"], "\xf4" => [108, "\xcb"], "\xf5" => [103, "\xcb"], "\xf6" => [114, "\xcb"], "\xf7" => [14, "\xcb"], "\xf8" => [93, "\xcc"], "\xf9" => [138, "\xcc"], "\xfa" => [75, "\xcc"], "\xfb" => [91, "\xcc"], "\xfc" => [108, "\xcc"], "\xfd" => [103, "\xcc"], "\xfe" => [114, "\xcc"], "\xff" => [14, "\xcc"]], ["\x00" => [94, "\xc00"], "\x01" => [76, "\xc00"], "\x02" => [104, "\xc00"], "\x03" => [16, "\xc00"], "\x04" => [94, "\xc01"], "\x05" => [76, "\xc01"], "\x06" => [104, "\xc01"], "\x07" => [16, "\xc01"], "\x08" => [94, "\xc02"], "\t" => [76, "\xc02"], "\n" => [104, "\xc02"], "\v" => [16, "\xc02"], "\f" => [94, "\xc0a"], "\r" => [76, "\xc0a"], "\x0e" => [104, "\xc0a"], "\x0f" => [16, "\xc0a"], "\x10" => [94, "\xc0c"], "\x11" => [76, "\xc0c"], "\x12" => [104, "\xc0c"], "\x13" => [16, "\xc0c"], "\x14" => [94, "\xc0e"], "\x15" => [76, "\xc0e"], "\x16" => [104, "\xc0e"], "\x17" => [16, "\xc0e"], "\x18" => [94, "\xc0i"], "\x19" => [76, "\xc0i"], "\x1a" => [104, "\xc0i"], "\x1b" => [16, "\xc0i"], "\x1c" => [94, "\xc0o"], "\x1d" => [76, "\xc0o"], "\x1e" => [104, "\xc0o"], "\x1f" => [16, "\xc0o"], " " => [94, "\xc0s"], "!" => [76, "\xc0s"], "\"" => [104, "\xc0s"], "#" => [16, "\xc0s"], "\$" => [94, "\xc0t"], "%" => [76, "\xc0t"], "&" => [104, "\xc0t"], "'" => [16, "\xc0t"], "(" => [77, "\xc0 "], ")" => [18, "\xc0 "], "*" => [77, "\xc0%"], "+" => [18, "\xc0%"], "," => [77, "\xc0-"], "-" => [18, "\xc0-"], "." => [77, "\xc0."], "/" => [18, "\xc0."], [77, "\xc0/"], [18, "\xc0/"], [77, "\xc03"], [18, "\xc03"], [77, "\xc04"], [18, "\xc04"], [77, "\xc05"], [18, "\xc05"], [77, "\xc06"], [18, "\xc06"], ":" => [77, "\xc07"], ";" => [18, "\xc07"], "<" => [77, "\xc08"], "=" => [18, "\xc08"], ">" => [77, "\xc09"], "?" => [18, "\xc09"], "@" => [77, "\xc0="], "A" => [18, "\xc0="], "B" => [77, "\xc0A"], "C" => [18, "\xc0A"], "D" => [77, "\xc0_"], "E" => [18, "\xc0_"], "F" => [77, "\xc0b"], "G" => [18, "\xc0b"], "H" => [77, "\xc0d"], "I" => [18, "\xc0d"], "J" => [77, "\xc0f"], "K" => [18, "\xc0f"], "L" => [77, "\xc0g"], "M" => [18, "\xc0g"], "N" => [77, "\xc0h"], "O" => [18, "\xc0h"], "P" => [77, "\xc0l"], "Q" => [18, "\xc0l"], "R" => [77, "\xc0m"], "S" => [18, "\xc0m"], "T" => [77, "\xc0n"], "U" => [18, "\xc0n"], "V" => [77, "\xc0p"], "W" => [18, "\xc0p"], "X" => [77, "\xc0r"], "Y" => [18, "\xc0r"], "Z" => [77, "\xc0u"], "[" => [18, "\xc0u"], "\\" => [0, "\xc0:"], "]" => [0, "\xc0B"], "^" => [0, "\xc0C"], "_" => [0, "\xc0D"], "`" => [0, "\xc0E"], "a" => [0, "\xc0F"], "b" => [0, "\xc0G"], "c" => [0, "\xc0H"], "d" => [0, "\xc0I"], "e" => [0, "\xc0J"], "f" => [0, "\xc0K"], "g" => [0, "\xc0L"], "h" => [0, "\xc0M"], "i" => [0, "\xc0N"], "j" => [0, "\xc0O"], "k" => [0, "\xc0P"], "l" => [0, "\xc0Q"], "m" => [0, "\xc0R"], "n" => [0, "\xc0S"], "o" => [0, "\xc0T"], "p" => [0, "\xc0U"], "q" => [0, "\xc0V"], "r" => [0, "\xc0W"], "s" => [0, "\xc0Y"], "t" => [0, "\xc0j"], "u" => [0, "\xc0k"], "v" => [0, "\xc0q"], "w" => [0, "\xc0v"], "x" => [0, "\xc0w"], "y" => [0, "\xc0x"], "z" => [0, "\xc0y"], "{" => [0, "\xc0z"], "|" => [82, "\xc0"], "}" => [87, "\xc0"], "~" => [130, "\xc0"], "" => [9, "\xc0"], "\x80" => [94, "\xc10"], "\x81" => [76, "\xc10"], "\x82" => [104, "\xc10"], "\x83" => [16, "\xc10"], "\x84" => [94, "\xc11"], "\x85" => [76, "\xc11"], "\x86" => [104, "\xc11"], "\x87" => [16, "\xc11"], "\x88" => [94, "\xc12"], "\x89" => [76, "\xc12"], "\x8a" => [104, "\xc12"], "\x8b" => [16, "\xc12"], "\x8c" => [94, "\xc1a"], "\x8d" => [76, "\xc1a"], "\x8e" => [104, "\xc1a"], "\x8f" => [16, "\xc1a"], "\x90" => [94, "\xc1c"], "\x91" => [76, "\xc1c"], "\x92" => [104, "\xc1c"], "\x93" => [16, "\xc1c"], "\x94" => [94, "\xc1e"], "\x95" => [76, "\xc1e"], "\x96" => [104, "\xc1e"], "\x97" => [16, "\xc1e"], "\x98" => [94, "\xc1i"], "\x99" => [76, "\xc1i"], "\x9a" => [104, "\xc1i"], "\x9b" => [16, "\xc1i"], "\x9c" => [94, "\xc1o"], "\x9d" => [76, "\xc1o"], "\x9e" => [104, "\xc1o"], "\x9f" => [16, "\xc1o"], "\xa0" => [94, "\xc1s"], "\xa1" => [76, "\xc1s"], "\xa2" => [104, "\xc1s"], "\xa3" => [16, "\xc1s"], "\xa4" => [94, "\xc1t"], "\xa5" => [76, "\xc1t"], "\xa6" => [104, "\xc1t"], "\xa7" => [16, "\xc1t"], "\xa8" => [77, "\xc1 "], "\xa9" => [18, "\xc1 "], "\xaa" => [77, "\xc1%"], "\xab" => [18, "\xc1%"], "\xac" => [77, "\xc1-"], "\xad" => [18, "\xc1-"], "\xae" => [77, "\xc1."], "\xaf" => [18, "\xc1."], "\xb0" => [77, "\xc1/"], "\xb1" => [18, "\xc1/"], "\xb2" => [77, "\xc13"], "\xb3" => [18, "\xc13"], "\xb4" => [77, "\xc14"], "\xb5" => [18, "\xc14"], "\xb6" => [77, "\xc15"], "\xb7" => [18, "\xc15"], "\xb8" => [77, "\xc16"], "\xb9" => [18, "\xc16"], "\xba" => [77, "\xc17"], "\xbb" => [18, "\xc17"], "\xbc" => [77, "\xc18"], "\xbd" => [18, "\xc18"], "\xbe" => [77, "\xc19"], "\xbf" => [18, "\xc19"], "\xc0" => [77, "\xc1="], "\xc1" => [18, "\xc1="], "\xc2" => [77, "\xc1A"], "\xc3" => [18, "\xc1A"], "\xc4" => [77, "\xc1_"], "\xc5" => [18, "\xc1_"], "\xc6" => [77, "\xc1b"], "\xc7" => [18, "\xc1b"], "\xc8" => [77, "\xc1d"], "\xc9" => [18, "\xc1d"], "\xca" => [77, "\xc1f"], "\xcb" => [18, "\xc1f"], "\xcc" => [77, "\xc1g"], "\xcd" => [18, "\xc1g"], "\xce" => [77, "\xc1h"], "\xcf" => [18, "\xc1h"], "\xd0" => [77, "\xc1l"], "\xd1" => [18, "\xc1l"], "\xd2" => [77, "\xc1m"], "\xd3" => [18, "\xc1m"], "\xd4" => [77, "\xc1n"], "\xd5" => [18, "\xc1n"], "\xd6" => [77, "\xc1p"], "\xd7" => [18, "\xc1p"], "\xd8" => [77, "\xc1r"], "\xd9" => [18, "\xc1r"], "\xda" => [77, "\xc1u"], "\xdb" => [18, "\xc1u"], "\xdc" => [0, "\xc1:"], "\xdd" => [0, "\xc1B"], "\xde" => [0, "\xc1C"], "\xdf" => [0, "\xc1D"], "\xe0" => [0, "\xc1E"], "\xe1" => [0, "\xc1F"], "\xe2" => [0, "\xc1G"], "\xe3" => [0, "\xc1H"], "\xe4" => [0, "\xc1I"], "\xe5" => [0, "\xc1J"], "\xe6" => [0, "\xc1K"], "\xe7" => [0, "\xc1L"], "\xe8" => [0, "\xc1M"], "\xe9" => [0, "\xc1N"], "\xea" => [0, "\xc1O"], "\xeb" => [0, "\xc1P"], "\xec" => [0, "\xc1Q"], "\xed" => [0, "\xc1R"], "\xee" => [0, "\xc1S"], "\xef" => [0, "\xc1T"], "\xf0" => [0, "\xc1U"], "\xf1" => [0, "\xc1V"], "\xf2" => [0, "\xc1W"], "\xf3" => [0, "\xc1Y"], "\xf4" => [0, "\xc1j"], "\xf5" => [0, "\xc1k"], "\xf6" => [0, "\xc1q"], "\xf7" => [0, "\xc1v"], "\xf8" => [0, "\xc1w"], "\xf9" => [0, "\xc1x"], "\xfa" => [0, "\xc1y"], "\xfb" => [0, "\xc1z"], "\xfc" => [82, "\xc1"], "\xfd" => [87, "\xc1"], "\xfe" => [130, "\xc1"], "\xff" => [9, "\xc1"]], ["\x00" => [94, "\xc50"], "\x01" => [76, "\xc50"], "\x02" => [104, "\xc50"], "\x03" => [16, "\xc50"], "\x04" => [94, "\xc51"], "\x05" => [76, "\xc51"], "\x06" => [104, "\xc51"], "\x07" => [16, "\xc51"], "\x08" => [94, "\xc52"], "\t" => [76, "\xc52"], "\n" => [104, "\xc52"], "\v" => [16, "\xc52"], "\f" => [94, "\xc5a"], "\r" => [76, "\xc5a"], "\x0e" => [104, "\xc5a"], "\x0f" => [16, "\xc5a"], "\x10" => [94, "\xc5c"], "\x11" => [76, "\xc5c"], "\x12" => [104, "\xc5c"], "\x13" => [16, "\xc5c"], "\x14" => [94, "\xc5e"], "\x15" => [76, "\xc5e"], "\x16" => [104, "\xc5e"], "\x17" => [16, "\xc5e"], "\x18" => [94, "\xc5i"], "\x19" => [76, "\xc5i"], "\x1a" => [104, "\xc5i"], "\x1b" => [16, "\xc5i"], "\x1c" => [94, "\xc5o"], "\x1d" => [76, "\xc5o"], "\x1e" => [104, "\xc5o"], "\x1f" => [16, "\xc5o"], " " => [94, "\xc5s"], "!" => [76, "\xc5s"], "\"" => [104, "\xc5s"], "#" => [16, "\xc5s"], "\$" => [94, "\xc5t"], "%" => [76, "\xc5t"], "&" => [104, "\xc5t"], "'" => [16, "\xc5t"], "(" => [77, "\xc5 "], ")" => [18, "\xc5 "], "*" => [77, "\xc5%"], "+" => [18, "\xc5%"], "," => [77, "\xc5-"], "-" => [18, "\xc5-"], "." => [77, "\xc5."], "/" => [18, "\xc5."], [77, "\xc5/"], [18, "\xc5/"], [77, "\xc53"], [18, "\xc53"], [77, "\xc54"], [18, "\xc54"], [77, "\xc55"], [18, "\xc55"], [77, "\xc56"], [18, "\xc56"], ":" => [77, "\xc57"], ";" => [18, "\xc57"], "<" => [77, "\xc58"], "=" => [18, "\xc58"], ">" => [77, "\xc59"], "?" => [18, "\xc59"], "@" => [77, "\xc5="], "A" => [18, "\xc5="], "B" => [77, "\xc5A"], "C" => [18, "\xc5A"], "D" => [77, "\xc5_"], "E" => [18, "\xc5_"], "F" => [77, "\xc5b"], "G" => [18, "\xc5b"], "H" => [77, "\xc5d"], "I" => [18, "\xc5d"], "J" => [77, "\xc5f"], "K" => [18, "\xc5f"], "L" => [77, "\xc5g"], "M" => [18, "\xc5g"], "N" => [77, "\xc5h"], "O" => [18, "\xc5h"], "P" => [77, "\xc5l"], "Q" => [18, "\xc5l"], "R" => [77, "\xc5m"], "S" => [18, "\xc5m"], "T" => [77, "\xc5n"], "U" => [18, "\xc5n"], "V" => [77, "\xc5p"], "W" => [18, "\xc5p"], "X" => [77, "\xc5r"], "Y" => [18, "\xc5r"], "Z" => [77, "\xc5u"], "[" => [18, "\xc5u"], "\\" => [0, "\xc5:"], "]" => [0, "\xc5B"], "^" => [0, "\xc5C"], "_" => [0, "\xc5D"], "`" => [0, "\xc5E"], "a" => [0, "\xc5F"], "b" => [0, "\xc5G"], "c" => [0, "\xc5H"], "d" => [0, "\xc5I"], "e" => [0, "\xc5J"], "f" => [0, "\xc5K"], "g" => [0, "\xc5L"], "h" => [0, "\xc5M"], "i" => [0, "\xc5N"], "j" => [0, "\xc5O"], "k" => [0, "\xc5P"], "l" => [0, "\xc5Q"], "m" => [0, "\xc5R"], "n" => [0, "\xc5S"], "o" => [0, "\xc5T"], "p" => [0, "\xc5U"], "q" => [0, "\xc5V"], "r" => [0, "\xc5W"], "s" => [0, "\xc5Y"], "t" => [0, "\xc5j"], "u" => [0, "\xc5k"], "v" => [0, "\xc5q"], "w" => [0, "\xc5v"], "x" => [0, "\xc5w"], "y" => [0, "\xc5x"], "z" => [0, "\xc5y"], "{" => [0, "\xc5z"], "|" => [82, "\xc5"], "}" => [87, "\xc5"], "~" => [130, "\xc5"], "" => [9, "\xc5"], "\x80" => [94, "\xe70"], "\x81" => [76, "\xe70"], "\x82" => [104, "\xe70"], "\x83" => [16, "\xe70"], "\x84" => [94, "\xe71"], "\x85" => [76, "\xe71"], "\x86" => [104, "\xe71"], "\x87" => [16, "\xe71"], "\x88" => [94, "\xe72"], "\x89" => [76, "\xe72"], "\x8a" => [104, "\xe72"], "\x8b" => [16, "\xe72"], "\x8c" => [94, "\xe7a"], "\x8d" => [76, "\xe7a"], "\x8e" => [104, "\xe7a"], "\x8f" => [16, "\xe7a"], "\x90" => [94, "\xe7c"], "\x91" => [76, "\xe7c"], "\x92" => [104, "\xe7c"], "\x93" => [16, "\xe7c"], "\x94" => [94, "\xe7e"], "\x95" => [76, "\xe7e"], "\x96" => [104, "\xe7e"], "\x97" => [16, "\xe7e"], "\x98" => [94, "\xe7i"], "\x99" => [76, "\xe7i"], "\x9a" => [104, "\xe7i"], "\x9b" => [16, "\xe7i"], "\x9c" => [94, "\xe7o"], "\x9d" => [76, "\xe7o"], "\x9e" => [104, "\xe7o"], "\x9f" => [16, "\xe7o"], "\xa0" => [94, "\xe7s"], "\xa1" => [76, "\xe7s"], "\xa2" => [104, "\xe7s"], "\xa3" => [16, "\xe7s"], "\xa4" => [94, "\xe7t"], "\xa5" => [76, "\xe7t"], "\xa6" => [104, "\xe7t"], "\xa7" => [16, "\xe7t"], "\xa8" => [77, "\xe7 "], "\xa9" => [18, "\xe7 "], "\xaa" => [77, "\xe7%"], "\xab" => [18, "\xe7%"], "\xac" => [77, "\xe7-"], "\xad" => [18, "\xe7-"], "\xae" => [77, "\xe7."], "\xaf" => [18, "\xe7."], "\xb0" => [77, "\xe7/"], "\xb1" => [18, "\xe7/"], "\xb2" => [77, "\xe73"], "\xb3" => [18, "\xe73"], "\xb4" => [77, "\xe74"], "\xb5" => [18, "\xe74"], "\xb6" => [77, "\xe75"], "\xb7" => [18, "\xe75"], "\xb8" => [77, "\xe76"], "\xb9" => [18, "\xe76"], "\xba" => [77, "\xe77"], "\xbb" => [18, "\xe77"], "\xbc" => [77, "\xe78"], "\xbd" => [18, "\xe78"], "\xbe" => [77, "\xe79"], "\xbf" => [18, "\xe79"], "\xc0" => [77, "\xe7="], "\xc1" => [18, "\xe7="], "\xc2" => [77, "\xe7A"], "\xc3" => [18, "\xe7A"], "\xc4" => [77, "\xe7_"], "\xc5" => [18, "\xe7_"], "\xc6" => [77, "\xe7b"], "\xc7" => [18, "\xe7b"], "\xc8" => [77, "\xe7d"], "\xc9" => [18, "\xe7d"], "\xca" => [77, "\xe7f"], "\xcb" => [18, "\xe7f"], "\xcc" => [77, "\xe7g"], "\xcd" => [18, "\xe7g"], "\xce" => [77, "\xe7h"], "\xcf" => [18, "\xe7h"], "\xd0" => [77, "\xe7l"], "\xd1" => [18, "\xe7l"], "\xd2" => [77, "\xe7m"], "\xd3" => [18, "\xe7m"], "\xd4" => [77, "\xe7n"], "\xd5" => [18, "\xe7n"], "\xd6" => [77, "\xe7p"], "\xd7" => [18, "\xe7p"], "\xd8" => [77, "\xe7r"], "\xd9" => [18, "\xe7r"], "\xda" => [77, "\xe7u"], "\xdb" => [18, "\xe7u"], "\xdc" => [0, "\xe7:"], "\xdd" => [0, "\xe7B"], "\xde" => [0, "\xe7C"], "\xdf" => [0, "\xe7D"], "\xe0" => [0, "\xe7E"], "\xe1" => [0, "\xe7F"], "\xe2" => [0, "\xe7G"], "\xe3" => [0, "\xe7H"], "\xe4" => [0, "\xe7I"], "\xe5" => [0, "\xe7J"], "\xe6" => [0, "\xe7K"], "\xe7" => [0, "\xe7L"], "\xe8" => [0, "\xe7M"], "\xe9" => [0, "\xe7N"], "\xea" => [0, "\xe7O"], "\xeb" => [0, "\xe7P"], "\xec" => [0, "\xe7Q"], "\xed" => [0, "\xe7R"], "\xee" => [0, "\xe7S"], "\xef" => [0, "\xe7T"], "\xf0" => [0, "\xe7U"], "\xf1" => [0, "\xe7V"], "\xf2" => [0, "\xe7W"], "\xf3" => [0, "\xe7Y"], "\xf4" => [0, "\xe7j"], "\xf5" => [0, "\xe7k"], "\xf6" => [0, "\xe7q"], "\xf7" => [0, "\xe7v"], "\xf8" => [0, "\xe7w"], "\xf9" => [0, "\xe7x"], "\xfa" => [0, "\xe7y"], "\xfb" => [0, "\xe7z"], "\xfc" => [82, "\xe7"], "\xfd" => [87, "\xe7"], "\xfe" => [130, "\xe7"], "\xff" => [9, "\xe7"]], ["\x00" => [94, "\xc60"], "\x01" => [76, "\xc60"], "\x02" => [104, "\xc60"], "\x03" => [16, "\xc60"], "\x04" => [94, "\xc61"], "\x05" => [76, "\xc61"], "\x06" => [104, "\xc61"], "\x07" => [16, "\xc61"], "\x08" => [94, "\xc62"], "\t" => [76, "\xc62"], "\n" => [104, "\xc62"], "\v" => [16, "\xc62"], "\f" => [94, "\xc6a"], "\r" => [76, "\xc6a"], "\x0e" => [104, "\xc6a"], "\x0f" => [16, "\xc6a"], "\x10" => [94, "\xc6c"], "\x11" => [76, "\xc6c"], "\x12" => [104, "\xc6c"], "\x13" => [16, "\xc6c"], "\x14" => [94, "\xc6e"], "\x15" => [76, "\xc6e"], "\x16" => [104, "\xc6e"], "\x17" => [16, "\xc6e"], "\x18" => [94, "\xc6i"], "\x19" => [76, "\xc6i"], "\x1a" => [104, "\xc6i"], "\x1b" => [16, "\xc6i"], "\x1c" => [94, "\xc6o"], "\x1d" => [76, "\xc6o"], "\x1e" => [104, "\xc6o"], "\x1f" => [16, "\xc6o"], " " => [94, "\xc6s"], "!" => [76, "\xc6s"], "\"" => [104, "\xc6s"], "#" => [16, "\xc6s"], "\$" => [94, "\xc6t"], "%" => [76, "\xc6t"], "&" => [104, "\xc6t"], "'" => [16, "\xc6t"], "(" => [77, "\xc6 "], ")" => [18, "\xc6 "], "*" => [77, "\xc6%"], "+" => [18, "\xc6%"], "," => [77, "\xc6-"], "-" => [18, "\xc6-"], "." => [77, "\xc6."], "/" => [18, "\xc6."], [77, "\xc6/"], [18, "\xc6/"], [77, "\xc63"], [18, "\xc63"], [77, "\xc64"], [18, "\xc64"], [77, "\xc65"], [18, "\xc65"], [77, "\xc66"], [18, "\xc66"], ":" => [77, "\xc67"], ";" => [18, "\xc67"], "<" => [77, "\xc68"], "=" => [18, "\xc68"], ">" => [77, "\xc69"], "?" => [18, "\xc69"], "@" => [77, "\xc6="], "A" => [18, "\xc6="], "B" => [77, "\xc6A"], "C" => [18, "\xc6A"], "D" => [77, "\xc6_"], "E" => [18, "\xc6_"], "F" => [77, "\xc6b"], "G" => [18, "\xc6b"], "H" => [77, "\xc6d"], "I" => [18, "\xc6d"], "J" => [77, "\xc6f"], "K" => [18, "\xc6f"], "L" => [77, "\xc6g"], "M" => [18, "\xc6g"], "N" => [77, "\xc6h"], "O" => [18, "\xc6h"], "P" => [77, "\xc6l"], "Q" => [18, "\xc6l"], "R" => [77, "\xc6m"], "S" => [18, "\xc6m"], "T" => [77, "\xc6n"], "U" => [18, "\xc6n"], "V" => [77, "\xc6p"], "W" => [18, "\xc6p"], "X" => [77, "\xc6r"], "Y" => [18, "\xc6r"], "Z" => [77, "\xc6u"], "[" => [18, "\xc6u"], "\\" => [0, "\xc6:"], "]" => [0, "\xc6B"], "^" => [0, "\xc6C"], "_" => [0, "\xc6D"], "`" => [0, "\xc6E"], "a" => [0, "\xc6F"], "b" => [0, "\xc6G"], "c" => [0, "\xc6H"], "d" => [0, "\xc6I"], "e" => [0, "\xc6J"], "f" => [0, "\xc6K"], "g" => [0, "\xc6L"], "h" => [0, "\xc6M"], "i" => [0, "\xc6N"], "j" => [0, "\xc6O"], "k" => [0, "\xc6P"], "l" => [0, "\xc6Q"], "m" => [0, "\xc6R"], "n" => [0, "\xc6S"], "o" => [0, "\xc6T"], "p" => [0, "\xc6U"], "q" => [0, "\xc6V"], "r" => [0, "\xc6W"], "s" => [0, "\xc6Y"], "t" => [0, "\xc6j"], "u" => [0, "\xc6k"], "v" => [0, "\xc6q"], "w" => [0, "\xc6v"], "x" => [0, "\xc6w"], "y" => [0, "\xc6x"], "z" => [0, "\xc6y"], "{" => [0, "\xc6z"], "|" => [82, "\xc6"], "}" => [87, "\xc6"], "~" => [130, "\xc6"], "" => [9, "\xc6"], "\x80" => [94, "\xe40"], "\x81" => [76, "\xe40"], "\x82" => [104, "\xe40"], "\x83" => [16, "\xe40"], "\x84" => [94, "\xe41"], "\x85" => [76, "\xe41"], "\x86" => [104, "\xe41"], "\x87" => [16, "\xe41"], "\x88" => [94, "\xe42"], "\x89" => [76, "\xe42"], "\x8a" => [104, "\xe42"], "\x8b" => [16, "\xe42"], "\x8c" => [94, "\xe4a"], "\x8d" => [76, "\xe4a"], "\x8e" => [104, "\xe4a"], "\x8f" => [16, "\xe4a"], "\x90" => [94, "\xe4c"], "\x91" => [76, "\xe4c"], "\x92" => [104, "\xe4c"], "\x93" => [16, "\xe4c"], "\x94" => [94, "\xe4e"], "\x95" => [76, "\xe4e"], "\x96" => [104, "\xe4e"], "\x97" => [16, "\xe4e"], "\x98" => [94, "\xe4i"], "\x99" => [76, "\xe4i"], "\x9a" => [104, "\xe4i"], "\x9b" => [16, "\xe4i"], "\x9c" => [94, "\xe4o"], "\x9d" => [76, "\xe4o"], "\x9e" => [104, "\xe4o"], "\x9f" => [16, "\xe4o"], "\xa0" => [94, "\xe4s"], "\xa1" => [76, "\xe4s"], "\xa2" => [104, "\xe4s"], "\xa3" => [16, "\xe4s"], "\xa4" => [94, "\xe4t"], "\xa5" => [76, "\xe4t"], "\xa6" => [104, "\xe4t"], "\xa7" => [16, "\xe4t"], "\xa8" => [77, "\xe4 "], "\xa9" => [18, "\xe4 "], "\xaa" => [77, "\xe4%"], "\xab" => [18, "\xe4%"], "\xac" => [77, "\xe4-"], "\xad" => [18, "\xe4-"], "\xae" => [77, "\xe4."], "\xaf" => [18, "\xe4."], "\xb0" => [77, "\xe4/"], "\xb1" => [18, "\xe4/"], "\xb2" => [77, "\xe43"], "\xb3" => [18, "\xe43"], "\xb4" => [77, "\xe44"], "\xb5" => [18, "\xe44"], "\xb6" => [77, "\xe45"], "\xb7" => [18, "\xe45"], "\xb8" => [77, "\xe46"], "\xb9" => [18, "\xe46"], "\xba" => [77, "\xe47"], "\xbb" => [18, "\xe47"], "\xbc" => [77, "\xe48"], "\xbd" => [18, "\xe48"], "\xbe" => [77, "\xe49"], "\xbf" => [18, "\xe49"], "\xc0" => [77, "\xe4="], "\xc1" => [18, "\xe4="], "\xc2" => [77, "\xe4A"], "\xc3" => [18, "\xe4A"], "\xc4" => [77, "\xe4_"], "\xc5" => [18, "\xe4_"], "\xc6" => [77, "\xe4b"], "\xc7" => [18, "\xe4b"], "\xc8" => [77, "\xe4d"], "\xc9" => [18, "\xe4d"], "\xca" => [77, "\xe4f"], "\xcb" => [18, "\xe4f"], "\xcc" => [77, "\xe4g"], "\xcd" => [18, "\xe4g"], "\xce" => [77, "\xe4h"], "\xcf" => [18, "\xe4h"], "\xd0" => [77, "\xe4l"], "\xd1" => [18, "\xe4l"], "\xd2" => [77, "\xe4m"], "\xd3" => [18, "\xe4m"], "\xd4" => [77, "\xe4n"], "\xd5" => [18, "\xe4n"], "\xd6" => [77, "\xe4p"], "\xd7" => [18, "\xe4p"], "\xd8" => [77, "\xe4r"], "\xd9" => [18, "\xe4r"], "\xda" => [77, "\xe4u"], "\xdb" => [18, "\xe4u"], "\xdc" => [0, "\xe4:"], "\xdd" => [0, "\xe4B"], "\xde" => [0, "\xe4C"], "\xdf" => [0, "\xe4D"], "\xe0" => [0, "\xe4E"], "\xe1" => [0, "\xe4F"], "\xe2" => [0, "\xe4G"], "\xe3" => [0, "\xe4H"], "\xe4" => [0, "\xe4I"], "\xe5" => [0, "\xe4J"], "\xe6" => [0, "\xe4K"], "\xe7" => [0, "\xe4L"], "\xe8" => [0, "\xe4M"], "\xe9" => [0, "\xe4N"], "\xea" => [0, "\xe4O"], "\xeb" => [0, "\xe4P"], "\xec" => [0, "\xe4Q"], "\xed" => [0, "\xe4R"], "\xee" => [0, "\xe4S"], "\xef" => [0, "\xe4T"], "\xf0" => [0, "\xe4U"], "\xf1" => [0, "\xe4V"], "\xf2" => [0, "\xe4W"], "\xf3" => [0, "\xe4Y"], "\xf4" => [0, "\xe4j"], "\xf5" => [0, "\xe4k"], "\xf6" => [0, "\xe4q"], "\xf7" => [0, "\xe4v"], "\xf8" => [0, "\xe4w"], "\xf9" => [0, "\xe4x"], "\xfa" => [0, "\xe4y"], "\xfb" => [0, "\xe4z"], "\xfc" => [82, "\xe4"], "\xfd" => [87, "\xe4"], "\xfe" => [130, "\xe4"], "\xff" => [9, "\xe4"]], ["\x00" => [77, "\xc60"], "\x01" => [18, "\xc60"], "\x02" => [77, "\xc61"], "\x03" => [18, "\xc61"], "\x04" => [77, "\xc62"], "\x05" => [18, "\xc62"], "\x06" => [77, "\xc6a"], "\x07" => [18, "\xc6a"], "\x08" => [77, "\xc6c"], "\t" => [18, "\xc6c"], "\n" => [77, "\xc6e"], "\v" => [18, "\xc6e"], "\f" => [77, "\xc6i"], "\r" => [18, "\xc6i"], "\x0e" => [77, "\xc6o"], "\x0f" => [18, "\xc6o"], "\x10" => [77, "\xc6s"], "\x11" => [18, "\xc6s"], "\x12" => [77, "\xc6t"], "\x13" => [18, "\xc6t"], "\x14" => [0, "\xc6 "], "\x15" => [0, "\xc6%"], "\x16" => [0, "\xc6-"], "\x17" => [0, "\xc6."], "\x18" => [0, "\xc6/"], "\x19" => [0, "\xc63"], "\x1a" => [0, "\xc64"], "\x1b" => [0, "\xc65"], "\x1c" => [0, "\xc66"], "\x1d" => [0, "\xc67"], "\x1e" => [0, "\xc68"], "\x1f" => [0, "\xc69"], " " => [0, "\xc6="], "!" => [0, "\xc6A"], "\"" => [0, "\xc6_"], "#" => [0, "\xc6b"], "\$" => [0, "\xc6d"], "%" => [0, "\xc6f"], "&" => [0, "\xc6g"], "'" => [0, "\xc6h"], "(" => [0, "\xc6l"], ")" => [0, "\xc6m"], "*" => [0, "\xc6n"], "+" => [0, "\xc6p"], "," => [0, "\xc6r"], "-" => [0, "\xc6u"], "." => [100, "\xc6"], "/" => [110, "\xc6"], [111, "\xc6"], [115, "\xc6"], [116, "\xc6"], [118, "\xc6"], [119, "\xc6"], [122, "\xc6"], [123, "\xc6"], [125, "\xc6"], [126, "\xc6"], [129, "\xc6"], ":" => [143, "\xc6"], ";" => [148, "\xc6"], "<" => [151, "\xc6"], "=" => [153, "\xc6"], ">" => [83, "\xc6"], "?" => [10, "\xc6"], "@" => [77, "\xe40"], "A" => [18, "\xe40"], "B" => [77, "\xe41"], "C" => [18, "\xe41"], "D" => [77, "\xe42"], "E" => [18, "\xe42"], "F" => [77, "\xe4a"], "G" => [18, "\xe4a"], "H" => [77, "\xe4c"], "I" => [18, "\xe4c"], "J" => [77, "\xe4e"], "K" => [18, "\xe4e"], "L" => [77, "\xe4i"], "M" => [18, "\xe4i"], "N" => [77, "\xe4o"], "O" => [18, "\xe4o"], "P" => [77, "\xe4s"], "Q" => [18, "\xe4s"], "R" => [77, "\xe4t"], "S" => [18, "\xe4t"], "T" => [0, "\xe4 "], "U" => [0, "\xe4%"], "V" => [0, "\xe4-"], "W" => [0, "\xe4."], "X" => [0, "\xe4/"], "Y" => [0, "\xe43"], "Z" => [0, "\xe44"], "[" => [0, "\xe45"], "\\" => [0, "\xe46"], "]" => [0, "\xe47"], "^" => [0, "\xe48"], "_" => [0, "\xe49"], "`" => [0, "\xe4="], "a" => [0, "\xe4A"], "b" => [0, "\xe4_"], "c" => [0, "\xe4b"], "d" => [0, "\xe4d"], "e" => [0, "\xe4f"], "f" => [0, "\xe4g"], "g" => [0, "\xe4h"], "h" => [0, "\xe4l"], "i" => [0, "\xe4m"], "j" => [0, "\xe4n"], "k" => [0, "\xe4p"], "l" => [0, "\xe4r"], "m" => [0, "\xe4u"], "n" => [100, "\xe4"], "o" => [110, "\xe4"], "p" => [111, "\xe4"], "q" => [115, "\xe4"], "r" => [116, "\xe4"], "s" => [118, "\xe4"], "t" => [119, "\xe4"], "u" => [122, "\xe4"], "v" => [123, "\xe4"], "w" => [125, "\xe4"], "x" => [126, "\xe4"], "y" => [129, "\xe4"], "z" => [143, "\xe4"], "{" => [148, "\xe4"], "|" => [151, "\xe4"], "}" => [153, "\xe4"], "~" => [83, "\xe4"], "" => [10, "\xe4"], "\x80" => [77, "\xe80"], "\x81" => [18, "\xe80"], "\x82" => [77, "\xe81"], "\x83" => [18, "\xe81"], "\x84" => [77, "\xe82"], "\x85" => [18, "\xe82"], "\x86" => [77, "\xe8a"], "\x87" => [18, "\xe8a"], "\x88" => [77, "\xe8c"], "\x89" => [18, "\xe8c"], "\x8a" => [77, "\xe8e"], "\x8b" => [18, "\xe8e"], "\x8c" => [77, "\xe8i"], "\x8d" => [18, "\xe8i"], "\x8e" => [77, "\xe8o"], "\x8f" => [18, "\xe8o"], "\x90" => [77, "\xe8s"], "\x91" => [18, "\xe8s"], "\x92" => [77, "\xe8t"], "\x93" => [18, "\xe8t"], "\x94" => [0, "\xe8 "], "\x95" => [0, "\xe8%"], "\x96" => [0, "\xe8-"], "\x97" => [0, "\xe8."], "\x98" => [0, "\xe8/"], "\x99" => [0, "\xe83"], "\x9a" => [0, "\xe84"], "\x9b" => [0, "\xe85"], "\x9c" => [0, "\xe86"], "\x9d" => [0, "\xe87"], "\x9e" => [0, "\xe88"], "\x9f" => [0, "\xe89"], "\xa0" => [0, "\xe8="], "\xa1" => [0, "\xe8A"], "\xa2" => [0, "\xe8_"], "\xa3" => [0, "\xe8b"], "\xa4" => [0, "\xe8d"], "\xa5" => [0, "\xe8f"], "\xa6" => [0, "\xe8g"], "\xa7" => [0, "\xe8h"], "\xa8" => [0, "\xe8l"], "\xa9" => [0, "\xe8m"], "\xaa" => [0, "\xe8n"], "\xab" => [0, "\xe8p"], "\xac" => [0, "\xe8r"], "\xad" => [0, "\xe8u"], "\xae" => [100, "\xe8"], "\xaf" => [110, "\xe8"], "\xb0" => [111, "\xe8"], "\xb1" => [115, "\xe8"], "\xb2" => [116, "\xe8"], "\xb3" => [118, "\xe8"], "\xb4" => [119, "\xe8"], "\xb5" => [122, "\xe8"], "\xb6" => [123, "\xe8"], "\xb7" => [125, "\xe8"], "\xb8" => [126, "\xe8"], "\xb9" => [129, "\xe8"], "\xba" => [143, "\xe8"], "\xbb" => [148, "\xe8"], "\xbc" => [151, "\xe8"], "\xbd" => [153, "\xe8"], "\xbe" => [83, "\xe8"], "\xbf" => [10, "\xe8"], "\xc0" => [77, "\xe90"], "\xc1" => [18, "\xe90"], "\xc2" => [77, "\xe91"], "\xc3" => [18, "\xe91"], "\xc4" => [77, "\xe92"], "\xc5" => [18, "\xe92"], "\xc6" => [77, "\xe9a"], "\xc7" => [18, "\xe9a"], "\xc8" => [77, "\xe9c"], "\xc9" => [18, "\xe9c"], "\xca" => [77, "\xe9e"], "\xcb" => [18, "\xe9e"], "\xcc" => [77, "\xe9i"], "\xcd" => [18, "\xe9i"], "\xce" => [77, "\xe9o"], "\xcf" => [18, "\xe9o"], "\xd0" => [77, "\xe9s"], "\xd1" => [18, "\xe9s"], "\xd2" => [77, "\xe9t"], "\xd3" => [18, "\xe9t"], "\xd4" => [0, "\xe9 "], "\xd5" => [0, "\xe9%"], "\xd6" => [0, "\xe9-"], "\xd7" => [0, "\xe9."], "\xd8" => [0, "\xe9/"], "\xd9" => [0, "\xe93"], "\xda" => [0, "\xe94"], "\xdb" => [0, "\xe95"], "\xdc" => [0, "\xe96"], "\xdd" => [0, "\xe97"], "\xde" => [0, "\xe98"], "\xdf" => [0, "\xe99"], "\xe0" => [0, "\xe9="], "\xe1" => [0, "\xe9A"], "\xe2" => [0, "\xe9_"], "\xe3" => [0, "\xe9b"], "\xe4" => [0, "\xe9d"], "\xe5" => [0, "\xe9f"], "\xe6" => [0, "\xe9g"], "\xe7" => [0, "\xe9h"], "\xe8" => [0, "\xe9l"], "\xe9" => [0, "\xe9m"], "\xea" => [0, "\xe9n"], "\xeb" => [0, "\xe9p"], "\xec" => [0, "\xe9r"], "\xed" => [0, "\xe9u"], "\xee" => [100, "\xe9"], "\xef" => [110, "\xe9"], "\xf0" => [111, "\xe9"], "\xf1" => [115, "\xe9"], "\xf2" => [116, "\xe9"], "\xf3" => [118, "\xe9"], "\xf4" => [119, "\xe9"], "\xf5" => [122, "\xe9"], "\xf6" => [123, "\xe9"], "\xf7" => [125, "\xe9"], "\xf8" => [126, "\xe9"], "\xf9" => [129, "\xe9"], "\xfa" => [143, "\xe9"], "\xfb" => [148, "\xe9"], "\xfc" => [151, "\xe9"], "\xfd" => [153, "\xe9"], "\xfe" => [83, "\xe9"], "\xff" => [10, "\xe9"]], ["\x00" => [94, "\xc70"], "\x01" => [76, "\xc70"], "\x02" => [104, "\xc70"], "\x03" => [16, "\xc70"], "\x04" => [94, "\xc71"], "\x05" => [76, "\xc71"], "\x06" => [104, "\xc71"], "\x07" => [16, "\xc71"], "\x08" => [94, "\xc72"], "\t" => [76, "\xc72"], "\n" => [104, "\xc72"], "\v" => [16, "\xc72"], "\f" => [94, "\xc7a"], "\r" => [76, "\xc7a"], "\x0e" => [104, "\xc7a"], "\x0f" => [16, "\xc7a"], "\x10" => [94, "\xc7c"], "\x11" => [76, "\xc7c"], "\x12" => [104, "\xc7c"], "\x13" => [16, "\xc7c"], "\x14" => [94, "\xc7e"], "\x15" => [76, "\xc7e"], "\x16" => [104, "\xc7e"], "\x17" => [16, "\xc7e"], "\x18" => [94, "\xc7i"], "\x19" => [76, "\xc7i"], "\x1a" => [104, "\xc7i"], "\x1b" => [16, "\xc7i"], "\x1c" => [94, "\xc7o"], "\x1d" => [76, "\xc7o"], "\x1e" => [104, "\xc7o"], "\x1f" => [16, "\xc7o"], " " => [94, "\xc7s"], "!" => [76, "\xc7s"], "\"" => [104, "\xc7s"], "#" => [16, "\xc7s"], "\$" => [94, "\xc7t"], "%" => [76, "\xc7t"], "&" => [104, "\xc7t"], "'" => [16, "\xc7t"], "(" => [77, "\xc7 "], ")" => [18, "\xc7 "], "*" => [77, "\xc7%"], "+" => [18, "\xc7%"], "," => [77, "\xc7-"], "-" => [18, "\xc7-"], "." => [77, "\xc7."], "/" => [18, "\xc7."], [77, "\xc7/"], [18, "\xc7/"], [77, "\xc73"], [18, "\xc73"], [77, "\xc74"], [18, "\xc74"], [77, "\xc75"], [18, "\xc75"], [77, "\xc76"], [18, "\xc76"], ":" => [77, "\xc77"], ";" => [18, "\xc77"], "<" => [77, "\xc78"], "=" => [18, "\xc78"], ">" => [77, "\xc79"], "?" => [18, "\xc79"], "@" => [77, "\xc7="], "A" => [18, "\xc7="], "B" => [77, "\xc7A"], "C" => [18, "\xc7A"], "D" => [77, "\xc7_"], "E" => [18, "\xc7_"], "F" => [77, "\xc7b"], "G" => [18, "\xc7b"], "H" => [77, "\xc7d"], "I" => [18, "\xc7d"], "J" => [77, "\xc7f"], "K" => [18, "\xc7f"], "L" => [77, "\xc7g"], "M" => [18, "\xc7g"], "N" => [77, "\xc7h"], "O" => [18, "\xc7h"], "P" => [77, "\xc7l"], "Q" => [18, "\xc7l"], "R" => [77, "\xc7m"], "S" => [18, "\xc7m"], "T" => [77, "\xc7n"], "U" => [18, "\xc7n"], "V" => [77, "\xc7p"], "W" => [18, "\xc7p"], "X" => [77, "\xc7r"], "Y" => [18, "\xc7r"], "Z" => [77, "\xc7u"], "[" => [18, "\xc7u"], "\\" => [0, "\xc7:"], "]" => [0, "\xc7B"], "^" => [0, "\xc7C"], "_" => [0, "\xc7D"], "`" => [0, "\xc7E"], "a" => [0, "\xc7F"], "b" => [0, "\xc7G"], "c" => [0, "\xc7H"], "d" => [0, "\xc7I"], "e" => [0, "\xc7J"], "f" => [0, "\xc7K"], "g" => [0, "\xc7L"], "h" => [0, "\xc7M"], "i" => [0, "\xc7N"], "j" => [0, "\xc7O"], "k" => [0, "\xc7P"], "l" => [0, "\xc7Q"], "m" => [0, "\xc7R"], "n" => [0, "\xc7S"], "o" => [0, "\xc7T"], "p" => [0, "\xc7U"], "q" => [0, "\xc7V"], "r" => [0, "\xc7W"], "s" => [0, "\xc7Y"], "t" => [0, "\xc7j"], "u" => [0, "\xc7k"], "v" => [0, "\xc7q"], "w" => [0, "\xc7v"], "x" => [0, "\xc7w"], "y" => [0, "\xc7x"], "z" => [0, "\xc7y"], "{" => [0, "\xc7z"], "|" => [82, "\xc7"], "}" => [87, "\xc7"], "~" => [130, "\xc7"], "" => [9, "\xc7"], "\x80" => [94, "\xcf0"], "\x81" => [76, "\xcf0"], "\x82" => [104, "\xcf0"], "\x83" => [16, "\xcf0"], "\x84" => [94, "\xcf1"], "\x85" => [76, "\xcf1"], "\x86" => [104, "\xcf1"], "\x87" => [16, "\xcf1"], "\x88" => [94, "\xcf2"], "\x89" => [76, "\xcf2"], "\x8a" => [104, "\xcf2"], "\x8b" => [16, "\xcf2"], "\x8c" => [94, "\xcfa"], "\x8d" => [76, "\xcfa"], "\x8e" => [104, "\xcfa"], "\x8f" => [16, "\xcfa"], "\x90" => [94, "\xcfc"], "\x91" => [76, "\xcfc"], "\x92" => [104, "\xcfc"], "\x93" => [16, "\xcfc"], "\x94" => [94, "\xcfe"], "\x95" => [76, "\xcfe"], "\x96" => [104, "\xcfe"], "\x97" => [16, "\xcfe"], "\x98" => [94, "\xcfi"], "\x99" => [76, "\xcfi"], "\x9a" => [104, "\xcfi"], "\x9b" => [16, "\xcfi"], "\x9c" => [94, "\xcfo"], "\x9d" => [76, "\xcfo"], "\x9e" => [104, "\xcfo"], "\x9f" => [16, "\xcfo"], "\xa0" => [94, "\xcfs"], "\xa1" => [76, "\xcfs"], "\xa2" => [104, "\xcfs"], "\xa3" => [16, "\xcfs"], "\xa4" => [94, "\xcft"], "\xa5" => [76, "\xcft"], "\xa6" => [104, "\xcft"], "\xa7" => [16, "\xcft"], "\xa8" => [77, "\xcf "], "\xa9" => [18, "\xcf "], "\xaa" => [77, "\xcf%"], "\xab" => [18, "\xcf%"], "\xac" => [77, "\xcf-"], "\xad" => [18, "\xcf-"], "\xae" => [77, "\xcf."], "\xaf" => [18, "\xcf."], "\xb0" => [77, "\xcf/"], "\xb1" => [18, "\xcf/"], "\xb2" => [77, "\xcf3"], "\xb3" => [18, "\xcf3"], "\xb4" => [77, "\xcf4"], "\xb5" => [18, "\xcf4"], "\xb6" => [77, "\xcf5"], "\xb7" => [18, "\xcf5"], "\xb8" => [77, "\xcf6"], "\xb9" => [18, "\xcf6"], "\xba" => [77, "\xcf7"], "\xbb" => [18, "\xcf7"], "\xbc" => [77, "\xcf8"], "\xbd" => [18, "\xcf8"], "\xbe" => [77, "\xcf9"], "\xbf" => [18, "\xcf9"], "\xc0" => [77, "\xcf="], "\xc1" => [18, "\xcf="], "\xc2" => [77, "\xcfA"], "\xc3" => [18, "\xcfA"], "\xc4" => [77, "\xcf_"], "\xc5" => [18, "\xcf_"], "\xc6" => [77, "\xcfb"], "\xc7" => [18, "\xcfb"], "\xc8" => [77, "\xcfd"], "\xc9" => [18, "\xcfd"], "\xca" => [77, "\xcff"], "\xcb" => [18, "\xcff"], "\xcc" => [77, "\xcfg"], "\xcd" => [18, "\xcfg"], "\xce" => [77, "\xcfh"], "\xcf" => [18, "\xcfh"], "\xd0" => [77, "\xcfl"], "\xd1" => [18, "\xcfl"], "\xd2" => [77, "\xcfm"], "\xd3" => [18, "\xcfm"], "\xd4" => [77, "\xcfn"], "\xd5" => [18, "\xcfn"], "\xd6" => [77, "\xcfp"], "\xd7" => [18, "\xcfp"], "\xd8" => [77, "\xcfr"], "\xd9" => [18, "\xcfr"], "\xda" => [77, "\xcfu"], "\xdb" => [18, "\xcfu"], "\xdc" => [0, "\xcf:"], "\xdd" => [0, "\xcfB"], "\xde" => [0, "\xcfC"], "\xdf" => [0, "\xcfD"], "\xe0" => [0, "\xcfE"], "\xe1" => [0, "\xcfF"], "\xe2" => [0, "\xcfG"], "\xe3" => [0, "\xcfH"], "\xe4" => [0, "\xcfI"], "\xe5" => [0, "\xcfJ"], "\xe6" => [0, "\xcfK"], "\xe7" => [0, "\xcfL"], "\xe8" => [0, "\xcfM"], "\xe9" => [0, "\xcfN"], "\xea" => [0, "\xcfO"], "\xeb" => [0, "\xcfP"], "\xec" => [0, "\xcfQ"], "\xed" => [0, "\xcfR"], "\xee" => [0, "\xcfS"], "\xef" => [0, "\xcfT"], "\xf0" => [0, "\xcfU"], "\xf1" => [0, "\xcfV"], "\xf2" => [0, "\xcfW"], "\xf3" => [0, "\xcfY"], "\xf4" => [0, "\xcfj"], "\xf5" => [0, "\xcfk"], "\xf6" => [0, "\xcfq"], "\xf7" => [0, "\xcfv"], "\xf8" => [0, "\xcfw"], "\xf9" => [0, "\xcfx"], "\xfa" => [0, "\xcfy"], "\xfb" => [0, "\xcfz"], "\xfc" => [82, "\xcf"], "\xfd" => [87, "\xcf"], "\xfe" => [130, "\xcf"], "\xff" => [9, "\xcf"]], ["\x00" => [77, "\xc70"], "\x01" => [18, "\xc70"], "\x02" => [77, "\xc71"], "\x03" => [18, "\xc71"], "\x04" => [77, "\xc72"], "\x05" => [18, "\xc72"], "\x06" => [77, "\xc7a"], "\x07" => [18, "\xc7a"], "\x08" => [77, "\xc7c"], "\t" => [18, "\xc7c"], "\n" => [77, "\xc7e"], "\v" => [18, "\xc7e"], "\f" => [77, "\xc7i"], "\r" => [18, "\xc7i"], "\x0e" => [77, "\xc7o"], "\x0f" => [18, "\xc7o"], "\x10" => [77, "\xc7s"], "\x11" => [18, "\xc7s"], "\x12" => [77, "\xc7t"], "\x13" => [18, "\xc7t"], "\x14" => [0, "\xc7 "], "\x15" => [0, "\xc7%"], "\x16" => [0, "\xc7-"], "\x17" => [0, "\xc7."], "\x18" => [0, "\xc7/"], "\x19" => [0, "\xc73"], "\x1a" => [0, "\xc74"], "\x1b" => [0, "\xc75"], "\x1c" => [0, "\xc76"], "\x1d" => [0, "\xc77"], "\x1e" => [0, "\xc78"], "\x1f" => [0, "\xc79"], " " => [0, "\xc7="], "!" => [0, "\xc7A"], "\"" => [0, "\xc7_"], "#" => [0, "\xc7b"], "\$" => [0, "\xc7d"], "%" => [0, "\xc7f"], "&" => [0, "\xc7g"], "'" => [0, "\xc7h"], "(" => [0, "\xc7l"], ")" => [0, "\xc7m"], "*" => [0, "\xc7n"], "+" => [0, "\xc7p"], "," => [0, "\xc7r"], "-" => [0, "\xc7u"], "." => [100, "\xc7"], "/" => [110, "\xc7"], [111, "\xc7"], [115, "\xc7"], [116, "\xc7"], [118, "\xc7"], [119, "\xc7"], [122, "\xc7"], [123, "\xc7"], [125, "\xc7"], [126, "\xc7"], [129, "\xc7"], ":" => [143, "\xc7"], ";" => [148, "\xc7"], "<" => [151, "\xc7"], "=" => [153, "\xc7"], ">" => [83, "\xc7"], "?" => [10, "\xc7"], "@" => [77, "\xcf0"], "A" => [18, "\xcf0"], "B" => [77, "\xcf1"], "C" => [18, "\xcf1"], "D" => [77, "\xcf2"], "E" => [18, "\xcf2"], "F" => [77, "\xcfa"], "G" => [18, "\xcfa"], "H" => [77, "\xcfc"], "I" => [18, "\xcfc"], "J" => [77, "\xcfe"], "K" => [18, "\xcfe"], "L" => [77, "\xcfi"], "M" => [18, "\xcfi"], "N" => [77, "\xcfo"], "O" => [18, "\xcfo"], "P" => [77, "\xcfs"], "Q" => [18, "\xcfs"], "R" => [77, "\xcft"], "S" => [18, "\xcft"], "T" => [0, "\xcf "], "U" => [0, "\xcf%"], "V" => [0, "\xcf-"], "W" => [0, "\xcf."], "X" => [0, "\xcf/"], "Y" => [0, "\xcf3"], "Z" => [0, "\xcf4"], "[" => [0, "\xcf5"], "\\" => [0, "\xcf6"], "]" => [0, "\xcf7"], "^" => [0, "\xcf8"], "_" => [0, "\xcf9"], "`" => [0, "\xcf="], "a" => [0, "\xcfA"], "b" => [0, "\xcf_"], "c" => [0, "\xcfb"], "d" => [0, "\xcfd"], "e" => [0, "\xcff"], "f" => [0, "\xcfg"], "g" => [0, "\xcfh"], "h" => [0, "\xcfl"], "i" => [0, "\xcfm"], "j" => [0, "\xcfn"], "k" => [0, "\xcfp"], "l" => [0, "\xcfr"], "m" => [0, "\xcfu"], "n" => [100, "\xcf"], "o" => [110, "\xcf"], "p" => [111, "\xcf"], "q" => [115, "\xcf"], "r" => [116, "\xcf"], "s" => [118, "\xcf"], "t" => [119, "\xcf"], "u" => [122, "\xcf"], "v" => [123, "\xcf"], "w" => [125, "\xcf"], "x" => [126, "\xcf"], "y" => [129, "\xcf"], "z" => [143, "\xcf"], "{" => [148, "\xcf"], "|" => [151, "\xcf"], "}" => [153, "\xcf"], "~" => [83, "\xcf"], "" => [10, "\xcf"], "\x80" => [77, "\xea0"], "\x81" => [18, "\xea0"], "\x82" => [77, "\xea1"], "\x83" => [18, "\xea1"], "\x84" => [77, "\xea2"], "\x85" => [18, "\xea2"], "\x86" => [77, "\xeaa"], "\x87" => [18, "\xeaa"], "\x88" => [77, "\xeac"], "\x89" => [18, "\xeac"], "\x8a" => [77, "\xeae"], "\x8b" => [18, "\xeae"], "\x8c" => [77, "\xeai"], "\x8d" => [18, "\xeai"], "\x8e" => [77, "\xeao"], "\x8f" => [18, "\xeao"], "\x90" => [77, "\xeas"], "\x91" => [18, "\xeas"], "\x92" => [77, "\xeat"], "\x93" => [18, "\xeat"], "\x94" => [0, "\xea "], "\x95" => [0, "\xea%"], "\x96" => [0, "\xea-"], "\x97" => [0, "\xea."], "\x98" => [0, "\xea/"], "\x99" => [0, "\xea3"], "\x9a" => [0, "\xea4"], "\x9b" => [0, "\xea5"], "\x9c" => [0, "\xea6"], "\x9d" => [0, "\xea7"], "\x9e" => [0, "\xea8"], "\x9f" => [0, "\xea9"], "\xa0" => [0, "\xea="], "\xa1" => [0, "\xeaA"], "\xa2" => [0, "\xea_"], "\xa3" => [0, "\xeab"], "\xa4" => [0, "\xead"], "\xa5" => [0, "\xeaf"], "\xa6" => [0, "\xeag"], "\xa7" => [0, "\xeah"], "\xa8" => [0, "\xeal"], "\xa9" => [0, "\xeam"], "\xaa" => [0, "\xean"], "\xab" => [0, "\xeap"], "\xac" => [0, "\xear"], "\xad" => [0, "\xeau"], "\xae" => [100, "\xea"], "\xaf" => [110, "\xea"], "\xb0" => [111, "\xea"], "\xb1" => [115, "\xea"], "\xb2" => [116, "\xea"], "\xb3" => [118, "\xea"], "\xb4" => [119, "\xea"], "\xb5" => [122, "\xea"], "\xb6" => [123, "\xea"], "\xb7" => [125, "\xea"], "\xb8" => [126, "\xea"], "\xb9" => [129, "\xea"], "\xba" => [143, "\xea"], "\xbb" => [148, "\xea"], "\xbc" => [151, "\xea"], "\xbd" => [153, "\xea"], "\xbe" => [83, "\xea"], "\xbf" => [10, "\xea"], "\xc0" => [77, "\xeb0"], "\xc1" => [18, "\xeb0"], "\xc2" => [77, "\xeb1"], "\xc3" => [18, "\xeb1"], "\xc4" => [77, "\xeb2"], "\xc5" => [18, "\xeb2"], "\xc6" => [77, "\xeba"], "\xc7" => [18, "\xeba"], "\xc8" => [77, "\xebc"], "\xc9" => [18, "\xebc"], "\xca" => [77, "\xebe"], "\xcb" => [18, "\xebe"], "\xcc" => [77, "\xebi"], "\xcd" => [18, "\xebi"], "\xce" => [77, "\xebo"], "\xcf" => [18, "\xebo"], "\xd0" => [77, "\xebs"], "\xd1" => [18, "\xebs"], "\xd2" => [77, "\xebt"], "\xd3" => [18, "\xebt"], "\xd4" => [0, "\xeb "], "\xd5" => [0, "\xeb%"], "\xd6" => [0, "\xeb-"], "\xd7" => [0, "\xeb."], "\xd8" => [0, "\xeb/"], "\xd9" => [0, "\xeb3"], "\xda" => [0, "\xeb4"], "\xdb" => [0, "\xeb5"], "\xdc" => [0, "\xeb6"], "\xdd" => [0, "\xeb7"], "\xde" => [0, "\xeb8"], "\xdf" => [0, "\xeb9"], "\xe0" => [0, "\xeb="], "\xe1" => [0, "\xebA"], "\xe2" => [0, "\xeb_"], "\xe3" => [0, "\xebb"], "\xe4" => [0, "\xebd"], "\xe5" => [0, "\xebf"], "\xe6" => [0, "\xebg"], "\xe7" => [0, "\xebh"], "\xe8" => [0, "\xebl"], "\xe9" => [0, "\xebm"], "\xea" => [0, "\xebn"], "\xeb" => [0, "\xebp"], "\xec" => [0, "\xebr"], "\xed" => [0, "\xebu"], "\xee" => [100, "\xeb"], "\xef" => [110, "\xeb"], "\xf0" => [111, "\xeb"], "\xf1" => [115, "\xeb"], "\xf2" => [116, "\xeb"], "\xf3" => [118, "\xeb"], "\xf4" => [119, "\xeb"], "\xf5" => [122, "\xeb"], "\xf6" => [123, "\xeb"], "\xf7" => [125, "\xeb"], "\xf8" => [126, "\xeb"], "\xf9" => [129, "\xeb"], "\xfa" => [143, "\xeb"], "\xfb" => [148, "\xeb"], "\xfc" => [151, "\xeb"], "\xfd" => [153, "\xeb"], "\xfe" => [83, "\xeb"], "\xff" => [10, "\xeb"]], ["\x00" => [77, "\xec0"], "\x01" => [18, "\xec0"], "\x02" => [77, "\xec1"], "\x03" => [18, "\xec1"], "\x04" => [77, "\xec2"], "\x05" => [18, "\xec2"], "\x06" => [77, "\xeca"], "\x07" => [18, "\xeca"], "\x08" => [77, "\xecc"], "\t" => [18, "\xecc"], "\n" => [77, "\xece"], "\v" => [18, "\xece"], "\f" => [77, "\xeci"], "\r" => [18, "\xeci"], "\x0e" => [77, "\xeco"], "\x0f" => [18, "\xeco"], "\x10" => [77, "\xecs"], "\x11" => [18, "\xecs"], "\x12" => [77, "\xect"], "\x13" => [18, "\xect"], "\x14" => [0, "\xec "], "\x15" => [0, "\xec%"], "\x16" => [0, "\xec-"], "\x17" => [0, "\xec."], "\x18" => [0, "\xec/"], "\x19" => [0, "\xec3"], "\x1a" => [0, "\xec4"], "\x1b" => [0, "\xec5"], "\x1c" => [0, "\xec6"], "\x1d" => [0, "\xec7"], "\x1e" => [0, "\xec8"], "\x1f" => [0, "\xec9"], " " => [0, "\xec="], "!" => [0, "\xecA"], "\"" => [0, "\xec_"], "#" => [0, "\xecb"], "\$" => [0, "\xecd"], "%" => [0, "\xecf"], "&" => [0, "\xecg"], "'" => [0, "\xech"], "(" => [0, "\xecl"], ")" => [0, "\xecm"], "*" => [0, "\xecn"], "+" => [0, "\xecp"], "," => [0, "\xecr"], "-" => [0, "\xecu"], "." => [100, "\xec"], "/" => [110, "\xec"], [111, "\xec"], [115, "\xec"], [116, "\xec"], [118, "\xec"], [119, "\xec"], [122, "\xec"], [123, "\xec"], [125, "\xec"], [126, "\xec"], [129, "\xec"], ":" => [143, "\xec"], ";" => [148, "\xec"], "<" => [151, "\xec"], "=" => [153, "\xec"], ">" => [83, "\xec"], "?" => [10, "\xec"], "@" => [77, "\xed0"], "A" => [18, "\xed0"], "B" => [77, "\xed1"], "C" => [18, "\xed1"], "D" => [77, "\xed2"], "E" => [18, "\xed2"], "F" => [77, "\xeda"], "G" => [18, "\xeda"], "H" => [77, "\xedc"], "I" => [18, "\xedc"], "J" => [77, "\xede"], "K" => [18, "\xede"], "L" => [77, "\xedi"], "M" => [18, "\xedi"], "N" => [77, "\xedo"], "O" => [18, "\xedo"], "P" => [77, "\xeds"], "Q" => [18, "\xeds"], "R" => [77, "\xedt"], "S" => [18, "\xedt"], "T" => [0, "\xed "], "U" => [0, "\xed%"], "V" => [0, "\xed-"], "W" => [0, "\xed."], "X" => [0, "\xed/"], "Y" => [0, "\xed3"], "Z" => [0, "\xed4"], "[" => [0, "\xed5"], "\\" => [0, "\xed6"], "]" => [0, "\xed7"], "^" => [0, "\xed8"], "_" => [0, "\xed9"], "`" => [0, "\xed="], "a" => [0, "\xedA"], "b" => [0, "\xed_"], "c" => [0, "\xedb"], "d" => [0, "\xedd"], "e" => [0, "\xedf"], "f" => [0, "\xedg"], "g" => [0, "\xedh"], "h" => [0, "\xedl"], "i" => [0, "\xedm"], "j" => [0, "\xedn"], "k" => [0, "\xedp"], "l" => [0, "\xedr"], "m" => [0, "\xedu"], "n" => [100, "\xed"], "o" => [110, "\xed"], "p" => [111, "\xed"], "q" => [115, "\xed"], "r" => [116, "\xed"], "s" => [118, "\xed"], "t" => [119, "\xed"], "u" => [122, "\xed"], "v" => [123, "\xed"], "w" => [125, "\xed"], "x" => [126, "\xed"], "y" => [129, "\xed"], "z" => [143, "\xed"], "{" => [148, "\xed"], "|" => [151, "\xed"], "}" => [153, "\xed"], "~" => [83, "\xed"], "" => [10, "\xed"], "\x80" => [0, "\xc70"], "\x81" => [0, "\xc71"], "\x82" => [0, "\xc72"], "\x83" => [0, "\xc7a"], "\x84" => [0, "\xc7c"], "\x85" => [0, "\xc7e"], "\x86" => [0, "\xc7i"], "\x87" => [0, "\xc7o"], "\x88" => [0, "\xc7s"], "\x89" => [0, "\xc7t"], "\x8a" => [73, "\xc7"], "\x8b" => [88, "\xc7"], "\x8c" => [89, "\xc7"], "\x8d" => [96, "\xc7"], "\x8e" => [97, "\xc7"], "\x8f" => [99, "\xc7"], "\x90" => [106, "\xc7"], "\x91" => [136, "\xc7"], "\x92" => [139, "\xc7"], "\x93" => [141, "\xc7"], "\x94" => [145, "\xc7"], "\x95" => [147, "\xc7"], "\x96" => [149, "\xc7"], "\x97" => [101, "\xc7"], "\x98" => [112, "\xc7"], "\x99" => [117, "\xc7"], "\x9a" => [120, "\xc7"], "\x9b" => [124, "\xc7"], "\x9c" => [127, "\xc7"], "\x9d" => [144, "\xc7"], "\x9e" => [152, "\xc7"], "\x9f" => [11, "\xc7"], "\xa0" => [0, "\xcf0"], "\xa1" => [0, "\xcf1"], "\xa2" => [0, "\xcf2"], "\xa3" => [0, "\xcfa"], "\xa4" => [0, "\xcfc"], "\xa5" => [0, "\xcfe"], "\xa6" => [0, "\xcfi"], "\xa7" => [0, "\xcfo"], "\xa8" => [0, "\xcfs"], "\xa9" => [0, "\xcft"], "\xaa" => [73, "\xcf"], "\xab" => [88, "\xcf"], "\xac" => [89, "\xcf"], "\xad" => [96, "\xcf"], "\xae" => [97, "\xcf"], "\xaf" => [99, "\xcf"], "\xb0" => [106, "\xcf"], "\xb1" => [136, "\xcf"], "\xb2" => [139, "\xcf"], "\xb3" => [141, "\xcf"], "\xb4" => [145, "\xcf"], "\xb5" => [147, "\xcf"], "\xb6" => [149, "\xcf"], "\xb7" => [101, "\xcf"], "\xb8" => [112, "\xcf"], "\xb9" => [117, "\xcf"], "\xba" => [120, "\xcf"], "\xbb" => [124, "\xcf"], "\xbc" => [127, "\xcf"], "\xbd" => [144, "\xcf"], "\xbe" => [152, "\xcf"], "\xbf" => [11, "\xcf"], "\xc0" => [0, "\xea0"], "\xc1" => [0, "\xea1"], "\xc2" => [0, "\xea2"], "\xc3" => [0, "\xeaa"], "\xc4" => [0, "\xeac"], "\xc5" => [0, "\xeae"], "\xc6" => [0, "\xeai"], "\xc7" => [0, "\xeao"], "\xc8" => [0, "\xeas"], "\xc9" => [0, "\xeat"], "\xca" => [73, "\xea"], "\xcb" => [88, "\xea"], "\xcc" => [89, "\xea"], "\xcd" => [96, "\xea"], "\xce" => [97, "\xea"], "\xcf" => [99, "\xea"], "\xd0" => [106, "\xea"], "\xd1" => [136, "\xea"], "\xd2" => [139, "\xea"], "\xd3" => [141, "\xea"], "\xd4" => [145, "\xea"], "\xd5" => [147, "\xea"], "\xd6" => [149, "\xea"], "\xd7" => [101, "\xea"], "\xd8" => [112, "\xea"], "\xd9" => [117, "\xea"], "\xda" => [120, "\xea"], "\xdb" => [124, "\xea"], "\xdc" => [127, "\xea"], "\xdd" => [144, "\xea"], "\xde" => [152, "\xea"], "\xdf" => [11, "\xea"], "\xe0" => [0, "\xeb0"], "\xe1" => [0, "\xeb1"], "\xe2" => [0, "\xeb2"], "\xe3" => [0, "\xeba"], "\xe4" => [0, "\xebc"], "\xe5" => [0, "\xebe"], "\xe6" => [0, "\xebi"], "\xe7" => [0, "\xebo"], "\xe8" => [0, "\xebs"], "\xe9" => [0, "\xebt"], "\xea" => [73, "\xeb"], "\xeb" => [88, "\xeb"], "\xec" => [89, "\xeb"], "\xed" => [96, "\xeb"], "\xee" => [97, "\xeb"], "\xef" => [99, "\xeb"], "\xf0" => [106, "\xeb"], "\xf1" => [136, "\xeb"], "\xf2" => [139, "\xeb"], "\xf3" => [141, "\xeb"], "\xf4" => [145, "\xeb"], "\xf5" => [147, "\xeb"], "\xf6" => [149, "\xeb"], "\xf7" => [101, "\xeb"], "\xf8" => [112, "\xeb"], "\xf9" => [117, "\xeb"], "\xfa" => [120, "\xeb"], "\xfb" => [124, "\xeb"], "\xfc" => [127, "\xeb"], "\xfd" => [144, "\xeb"], "\xfe" => [152, "\xeb"], "\xff" => [11, "\xeb"]], ["\x00" => [94, "\xc80"], "\x01" => [76, "\xc80"], "\x02" => [104, "\xc80"], "\x03" => [16, "\xc80"], "\x04" => [94, "\xc81"], "\x05" => [76, "\xc81"], "\x06" => [104, "\xc81"], "\x07" => [16, "\xc81"], "\x08" => [94, "\xc82"], "\t" => [76, "\xc82"], "\n" => [104, "\xc82"], "\v" => [16, "\xc82"], "\f" => [94, "\xc8a"], "\r" => [76, "\xc8a"], "\x0e" => [104, "\xc8a"], "\x0f" => [16, "\xc8a"], "\x10" => [94, "\xc8c"], "\x11" => [76, "\xc8c"], "\x12" => [104, "\xc8c"], "\x13" => [16, "\xc8c"], "\x14" => [94, "\xc8e"], "\x15" => [76, "\xc8e"], "\x16" => [104, "\xc8e"], "\x17" => [16, "\xc8e"], "\x18" => [94, "\xc8i"], "\x19" => [76, "\xc8i"], "\x1a" => [104, "\xc8i"], "\x1b" => [16, "\xc8i"], "\x1c" => [94, "\xc8o"], "\x1d" => [76, "\xc8o"], "\x1e" => [104, "\xc8o"], "\x1f" => [16, "\xc8o"], " " => [94, "\xc8s"], "!" => [76, "\xc8s"], "\"" => [104, "\xc8s"], "#" => [16, "\xc8s"], "\$" => [94, "\xc8t"], "%" => [76, "\xc8t"], "&" => [104, "\xc8t"], "'" => [16, "\xc8t"], "(" => [77, "\xc8 "], ")" => [18, "\xc8 "], "*" => [77, "\xc8%"], "+" => [18, "\xc8%"], "," => [77, "\xc8-"], "-" => [18, "\xc8-"], "." => [77, "\xc8."], "/" => [18, "\xc8."], [77, "\xc8/"], [18, "\xc8/"], [77, "\xc83"], [18, "\xc83"], [77, "\xc84"], [18, "\xc84"], [77, "\xc85"], [18, "\xc85"], [77, "\xc86"], [18, "\xc86"], ":" => [77, "\xc87"], ";" => [18, "\xc87"], "<" => [77, "\xc88"], "=" => [18, "\xc88"], ">" => [77, "\xc89"], "?" => [18, "\xc89"], "@" => [77, "\xc8="], "A" => [18, "\xc8="], "B" => [77, "\xc8A"], "C" => [18, "\xc8A"], "D" => [77, "\xc8_"], "E" => [18, "\xc8_"], "F" => [77, "\xc8b"], "G" => [18, "\xc8b"], "H" => [77, "\xc8d"], "I" => [18, "\xc8d"], "J" => [77, "\xc8f"], "K" => [18, "\xc8f"], "L" => [77, "\xc8g"], "M" => [18, "\xc8g"], "N" => [77, "\xc8h"], "O" => [18, "\xc8h"], "P" => [77, "\xc8l"], "Q" => [18, "\xc8l"], "R" => [77, "\xc8m"], "S" => [18, "\xc8m"], "T" => [77, "\xc8n"], "U" => [18, "\xc8n"], "V" => [77, "\xc8p"], "W" => [18, "\xc8p"], "X" => [77, "\xc8r"], "Y" => [18, "\xc8r"], "Z" => [77, "\xc8u"], "[" => [18, "\xc8u"], "\\" => [0, "\xc8:"], "]" => [0, "\xc8B"], "^" => [0, "\xc8C"], "_" => [0, "\xc8D"], "`" => [0, "\xc8E"], "a" => [0, "\xc8F"], "b" => [0, "\xc8G"], "c" => [0, "\xc8H"], "d" => [0, "\xc8I"], "e" => [0, "\xc8J"], "f" => [0, "\xc8K"], "g" => [0, "\xc8L"], "h" => [0, "\xc8M"], "i" => [0, "\xc8N"], "j" => [0, "\xc8O"], "k" => [0, "\xc8P"], "l" => [0, "\xc8Q"], "m" => [0, "\xc8R"], "n" => [0, "\xc8S"], "o" => [0, "\xc8T"], "p" => [0, "\xc8U"], "q" => [0, "\xc8V"], "r" => [0, "\xc8W"], "s" => [0, "\xc8Y"], "t" => [0, "\xc8j"], "u" => [0, "\xc8k"], "v" => [0, "\xc8q"], "w" => [0, "\xc8v"], "x" => [0, "\xc8w"], "y" => [0, "\xc8x"], "z" => [0, "\xc8y"], "{" => [0, "\xc8z"], "|" => [82, "\xc8"], "}" => [87, "\xc8"], "~" => [130, "\xc8"], "" => [9, "\xc8"], "\x80" => [94, "\xc90"], "\x81" => [76, "\xc90"], "\x82" => [104, "\xc90"], "\x83" => [16, "\xc90"], "\x84" => [94, "\xc91"], "\x85" => [76, "\xc91"], "\x86" => [104, "\xc91"], "\x87" => [16, "\xc91"], "\x88" => [94, "\xc92"], "\x89" => [76, "\xc92"], "\x8a" => [104, "\xc92"], "\x8b" => [16, "\xc92"], "\x8c" => [94, "\xc9a"], "\x8d" => [76, "\xc9a"], "\x8e" => [104, "\xc9a"], "\x8f" => [16, "\xc9a"], "\x90" => [94, "\xc9c"], "\x91" => [76, "\xc9c"], "\x92" => [104, "\xc9c"], "\x93" => [16, "\xc9c"], "\x94" => [94, "\xc9e"], "\x95" => [76, "\xc9e"], "\x96" => [104, "\xc9e"], "\x97" => [16, "\xc9e"], "\x98" => [94, "\xc9i"], "\x99" => [76, "\xc9i"], "\x9a" => [104, "\xc9i"], "\x9b" => [16, "\xc9i"], "\x9c" => [94, "\xc9o"], "\x9d" => [76, "\xc9o"], "\x9e" => [104, "\xc9o"], "\x9f" => [16, "\xc9o"], "\xa0" => [94, "\xc9s"], "\xa1" => [76, "\xc9s"], "\xa2" => [104, "\xc9s"], "\xa3" => [16, "\xc9s"], "\xa4" => [94, "\xc9t"], "\xa5" => [76, "\xc9t"], "\xa6" => [104, "\xc9t"], "\xa7" => [16, "\xc9t"], "\xa8" => [77, "\xc9 "], "\xa9" => [18, "\xc9 "], "\xaa" => [77, "\xc9%"], "\xab" => [18, "\xc9%"], "\xac" => [77, "\xc9-"], "\xad" => [18, "\xc9-"], "\xae" => [77, "\xc9."], "\xaf" => [18, "\xc9."], "\xb0" => [77, "\xc9/"], "\xb1" => [18, "\xc9/"], "\xb2" => [77, "\xc93"], "\xb3" => [18, "\xc93"], "\xb4" => [77, "\xc94"], "\xb5" => [18, "\xc94"], "\xb6" => [77, "\xc95"], "\xb7" => [18, "\xc95"], "\xb8" => [77, "\xc96"], "\xb9" => [18, "\xc96"], "\xba" => [77, "\xc97"], "\xbb" => [18, "\xc97"], "\xbc" => [77, "\xc98"], "\xbd" => [18, "\xc98"], "\xbe" => [77, "\xc99"], "\xbf" => [18, "\xc99"], "\xc0" => [77, "\xc9="], "\xc1" => [18, "\xc9="], "\xc2" => [77, "\xc9A"], "\xc3" => [18, "\xc9A"], "\xc4" => [77, "\xc9_"], "\xc5" => [18, "\xc9_"], "\xc6" => [77, "\xc9b"], "\xc7" => [18, "\xc9b"], "\xc8" => [77, "\xc9d"], "\xc9" => [18, "\xc9d"], "\xca" => [77, "\xc9f"], "\xcb" => [18, "\xc9f"], "\xcc" => [77, "\xc9g"], "\xcd" => [18, "\xc9g"], "\xce" => [77, "\xc9h"], "\xcf" => [18, "\xc9h"], "\xd0" => [77, "\xc9l"], "\xd1" => [18, "\xc9l"], "\xd2" => [77, "\xc9m"], "\xd3" => [18, "\xc9m"], "\xd4" => [77, "\xc9n"], "\xd5" => [18, "\xc9n"], "\xd6" => [77, "\xc9p"], "\xd7" => [18, "\xc9p"], "\xd8" => [77, "\xc9r"], "\xd9" => [18, "\xc9r"], "\xda" => [77, "\xc9u"], "\xdb" => [18, "\xc9u"], "\xdc" => [0, "\xc9:"], "\xdd" => [0, "\xc9B"], "\xde" => [0, "\xc9C"], "\xdf" => [0, "\xc9D"], "\xe0" => [0, "\xc9E"], "\xe1" => [0, "\xc9F"], "\xe2" => [0, "\xc9G"], "\xe3" => [0, "\xc9H"], "\xe4" => [0, "\xc9I"], "\xe5" => [0, "\xc9J"], "\xe6" => [0, "\xc9K"], "\xe7" => [0, "\xc9L"], "\xe8" => [0, "\xc9M"], "\xe9" => [0, "\xc9N"], "\xea" => [0, "\xc9O"], "\xeb" => [0, "\xc9P"], "\xec" => [0, "\xc9Q"], "\xed" => [0, "\xc9R"], "\xee" => [0, "\xc9S"], "\xef" => [0, "\xc9T"], "\xf0" => [0, "\xc9U"], "\xf1" => [0, "\xc9V"], "\xf2" => [0, "\xc9W"], "\xf3" => [0, "\xc9Y"], "\xf4" => [0, "\xc9j"], "\xf5" => [0, "\xc9k"], "\xf6" => [0, "\xc9q"], "\xf7" => [0, "\xc9v"], "\xf8" => [0, "\xc9w"], "\xf9" => [0, "\xc9x"], "\xfa" => [0, "\xc9y"], "\xfb" => [0, "\xc9z"], "\xfc" => [82, "\xc9"], "\xfd" => [87, "\xc9"], "\xfe" => [130, "\xc9"], "\xff" => [9, "\xc9"]], ["\x00" => [77, "\xca0"], "\x01" => [18, "\xca0"], "\x02" => [77, "\xca1"], "\x03" => [18, "\xca1"], "\x04" => [77, "\xca2"], "\x05" => [18, "\xca2"], "\x06" => [77, "\xcaa"], "\x07" => [18, "\xcaa"], "\x08" => [77, "\xcac"], "\t" => [18, "\xcac"], "\n" => [77, "\xcae"], "\v" => [18, "\xcae"], "\f" => [77, "\xcai"], "\r" => [18, "\xcai"], "\x0e" => [77, "\xcao"], "\x0f" => [18, "\xcao"], "\x10" => [77, "\xcas"], "\x11" => [18, "\xcas"], "\x12" => [77, "\xcat"], "\x13" => [18, "\xcat"], "\x14" => [0, "\xca "], "\x15" => [0, "\xca%"], "\x16" => [0, "\xca-"], "\x17" => [0, "\xca."], "\x18" => [0, "\xca/"], "\x19" => [0, "\xca3"], "\x1a" => [0, "\xca4"], "\x1b" => [0, "\xca5"], "\x1c" => [0, "\xca6"], "\x1d" => [0, "\xca7"], "\x1e" => [0, "\xca8"], "\x1f" => [0, "\xca9"], " " => [0, "\xca="], "!" => [0, "\xcaA"], "\"" => [0, "\xca_"], "#" => [0, "\xcab"], "\$" => [0, "\xcad"], "%" => [0, "\xcaf"], "&" => [0, "\xcag"], "'" => [0, "\xcah"], "(" => [0, "\xcal"], ")" => [0, "\xcam"], "*" => [0, "\xcan"], "+" => [0, "\xcap"], "," => [0, "\xcar"], "-" => [0, "\xcau"], "." => [100, "\xca"], "/" => [110, "\xca"], [111, "\xca"], [115, "\xca"], [116, "\xca"], [118, "\xca"], [119, "\xca"], [122, "\xca"], [123, "\xca"], [125, "\xca"], [126, "\xca"], [129, "\xca"], ":" => [143, "\xca"], ";" => [148, "\xca"], "<" => [151, "\xca"], "=" => [153, "\xca"], ">" => [83, "\xca"], "?" => [10, "\xca"], "@" => [77, "\xcd0"], "A" => [18, "\xcd0"], "B" => [77, "\xcd1"], "C" => [18, "\xcd1"], "D" => [77, "\xcd2"], "E" => [18, "\xcd2"], "F" => [77, "\xcda"], "G" => [18, "\xcda"], "H" => [77, "\xcdc"], "I" => [18, "\xcdc"], "J" => [77, "\xcde"], "K" => [18, "\xcde"], "L" => [77, "\xcdi"], "M" => [18, "\xcdi"], "N" => [77, "\xcdo"], "O" => [18, "\xcdo"], "P" => [77, "\xcds"], "Q" => [18, "\xcds"], "R" => [77, "\xcdt"], "S" => [18, "\xcdt"], "T" => [0, "\xcd "], "U" => [0, "\xcd%"], "V" => [0, "\xcd-"], "W" => [0, "\xcd."], "X" => [0, "\xcd/"], "Y" => [0, "\xcd3"], "Z" => [0, "\xcd4"], "[" => [0, "\xcd5"], "\\" => [0, "\xcd6"], "]" => [0, "\xcd7"], "^" => [0, "\xcd8"], "_" => [0, "\xcd9"], "`" => [0, "\xcd="], "a" => [0, "\xcdA"], "b" => [0, "\xcd_"], "c" => [0, "\xcdb"], "d" => [0, "\xcdd"], "e" => [0, "\xcdf"], "f" => [0, "\xcdg"], "g" => [0, "\xcdh"], "h" => [0, "\xcdl"], "i" => [0, "\xcdm"], "j" => [0, "\xcdn"], "k" => [0, "\xcdp"], "l" => [0, "\xcdr"], "m" => [0, "\xcdu"], "n" => [100, "\xcd"], "o" => [110, "\xcd"], "p" => [111, "\xcd"], "q" => [115, "\xcd"], "r" => [116, "\xcd"], "s" => [118, "\xcd"], "t" => [119, "\xcd"], "u" => [122, "\xcd"], "v" => [123, "\xcd"], "w" => [125, "\xcd"], "x" => [126, "\xcd"], "y" => [129, "\xcd"], "z" => [143, "\xcd"], "{" => [148, "\xcd"], "|" => [151, "\xcd"], "}" => [153, "\xcd"], "~" => [83, "\xcd"], "" => [10, "\xcd"], "\x80" => [77, "\xd20"], "\x81" => [18, "\xd20"], "\x82" => [77, "\xd21"], "\x83" => [18, "\xd21"], "\x84" => [77, "\xd22"], "\x85" => [18, "\xd22"], "\x86" => [77, "\xd2a"], "\x87" => [18, "\xd2a"], "\x88" => [77, "\xd2c"], "\x89" => [18, "\xd2c"], "\x8a" => [77, "\xd2e"], "\x8b" => [18, "\xd2e"], "\x8c" => [77, "\xd2i"], "\x8d" => [18, "\xd2i"], "\x8e" => [77, "\xd2o"], "\x8f" => [18, "\xd2o"], "\x90" => [77, "\xd2s"], "\x91" => [18, "\xd2s"], "\x92" => [77, "\xd2t"], "\x93" => [18, "\xd2t"], "\x94" => [0, "\xd2 "], "\x95" => [0, "\xd2%"], "\x96" => [0, "\xd2-"], "\x97" => [0, "\xd2."], "\x98" => [0, "\xd2/"], "\x99" => [0, "\xd23"], "\x9a" => [0, "\xd24"], "\x9b" => [0, "\xd25"], "\x9c" => [0, "\xd26"], "\x9d" => [0, "\xd27"], "\x9e" => [0, "\xd28"], "\x9f" => [0, "\xd29"], "\xa0" => [0, "\xd2="], "\xa1" => [0, "\xd2A"], "\xa2" => [0, "\xd2_"], "\xa3" => [0, "\xd2b"], "\xa4" => [0, "\xd2d"], "\xa5" => [0, "\xd2f"], "\xa6" => [0, "\xd2g"], "\xa7" => [0, "\xd2h"], "\xa8" => [0, "\xd2l"], "\xa9" => [0, "\xd2m"], "\xaa" => [0, "\xd2n"], "\xab" => [0, "\xd2p"], "\xac" => [0, "\xd2r"], "\xad" => [0, "\xd2u"], "\xae" => [100, "\xd2"], "\xaf" => [110, "\xd2"], "\xb0" => [111, "\xd2"], "\xb1" => [115, "\xd2"], "\xb2" => [116, "\xd2"], "\xb3" => [118, "\xd2"], "\xb4" => [119, "\xd2"], "\xb5" => [122, "\xd2"], "\xb6" => [123, "\xd2"], "\xb7" => [125, "\xd2"], "\xb8" => [126, "\xd2"], "\xb9" => [129, "\xd2"], "\xba" => [143, "\xd2"], "\xbb" => [148, "\xd2"], "\xbc" => [151, "\xd2"], "\xbd" => [153, "\xd2"], "\xbe" => [83, "\xd2"], "\xbf" => [10, "\xd2"], "\xc0" => [77, "\xd50"], "\xc1" => [18, "\xd50"], "\xc2" => [77, "\xd51"], "\xc3" => [18, "\xd51"], "\xc4" => [77, "\xd52"], "\xc5" => [18, "\xd52"], "\xc6" => [77, "\xd5a"], "\xc7" => [18, "\xd5a"], "\xc8" => [77, "\xd5c"], "\xc9" => [18, "\xd5c"], "\xca" => [77, "\xd5e"], "\xcb" => [18, "\xd5e"], "\xcc" => [77, "\xd5i"], "\xcd" => [18, "\xd5i"], "\xce" => [77, "\xd5o"], "\xcf" => [18, "\xd5o"], "\xd0" => [77, "\xd5s"], "\xd1" => [18, "\xd5s"], "\xd2" => [77, "\xd5t"], "\xd3" => [18, "\xd5t"], "\xd4" => [0, "\xd5 "], "\xd5" => [0, "\xd5%"], "\xd6" => [0, "\xd5-"], "\xd7" => [0, "\xd5."], "\xd8" => [0, "\xd5/"], "\xd9" => [0, "\xd53"], "\xda" => [0, "\xd54"], "\xdb" => [0, "\xd55"], "\xdc" => [0, "\xd56"], "\xdd" => [0, "\xd57"], "\xde" => [0, "\xd58"], "\xdf" => [0, "\xd59"], "\xe0" => [0, "\xd5="], "\xe1" => [0, "\xd5A"], "\xe2" => [0, "\xd5_"], "\xe3" => [0, "\xd5b"], "\xe4" => [0, "\xd5d"], "\xe5" => [0, "\xd5f"], "\xe6" => [0, "\xd5g"], "\xe7" => [0, "\xd5h"], "\xe8" => [0, "\xd5l"], "\xe9" => [0, "\xd5m"], "\xea" => [0, "\xd5n"], "\xeb" => [0, "\xd5p"], "\xec" => [0, "\xd5r"], "\xed" => [0, "\xd5u"], "\xee" => [100, "\xd5"], "\xef" => [110, "\xd5"], "\xf0" => [111, "\xd5"], "\xf1" => [115, "\xd5"], "\xf2" => [116, "\xd5"], "\xf3" => [118, "\xd5"], "\xf4" => [119, "\xd5"], "\xf5" => [122, "\xd5"], "\xf6" => [123, "\xd5"], "\xf7" => [125, "\xd5"], "\xf8" => [126, "\xd5"], "\xf9" => [129, "\xd5"], "\xfa" => [143, "\xd5"], "\xfb" => [148, "\xd5"], "\xfc" => [151, "\xd5"], "\xfd" => [153, "\xd5"], "\xfe" => [83, "\xd5"], "\xff" => [10, "\xd5"]], ["\x00" => [94, "\xca0"], "\x01" => [76, "\xca0"], "\x02" => [104, "\xca0"], "\x03" => [16, "\xca0"], "\x04" => [94, "\xca1"], "\x05" => [76, "\xca1"], "\x06" => [104, "\xca1"], "\x07" => [16, "\xca1"], "\x08" => [94, "\xca2"], "\t" => [76, "\xca2"], "\n" => [104, "\xca2"], "\v" => [16, "\xca2"], "\f" => [94, "\xcaa"], "\r" => [76, "\xcaa"], "\x0e" => [104, "\xcaa"], "\x0f" => [16, "\xcaa"], "\x10" => [94, "\xcac"], "\x11" => [76, "\xcac"], "\x12" => [104, "\xcac"], "\x13" => [16, "\xcac"], "\x14" => [94, "\xcae"], "\x15" => [76, "\xcae"], "\x16" => [104, "\xcae"], "\x17" => [16, "\xcae"], "\x18" => [94, "\xcai"], "\x19" => [76, "\xcai"], "\x1a" => [104, "\xcai"], "\x1b" => [16, "\xcai"], "\x1c" => [94, "\xcao"], "\x1d" => [76, "\xcao"], "\x1e" => [104, "\xcao"], "\x1f" => [16, "\xcao"], " " => [94, "\xcas"], "!" => [76, "\xcas"], "\"" => [104, "\xcas"], "#" => [16, "\xcas"], "\$" => [94, "\xcat"], "%" => [76, "\xcat"], "&" => [104, "\xcat"], "'" => [16, "\xcat"], "(" => [77, "\xca "], ")" => [18, "\xca "], "*" => [77, "\xca%"], "+" => [18, "\xca%"], "," => [77, "\xca-"], "-" => [18, "\xca-"], "." => [77, "\xca."], "/" => [18, "\xca."], [77, "\xca/"], [18, "\xca/"], [77, "\xca3"], [18, "\xca3"], [77, "\xca4"], [18, "\xca4"], [77, "\xca5"], [18, "\xca5"], [77, "\xca6"], [18, "\xca6"], ":" => [77, "\xca7"], ";" => [18, "\xca7"], "<" => [77, "\xca8"], "=" => [18, "\xca8"], ">" => [77, "\xca9"], "?" => [18, "\xca9"], "@" => [77, "\xca="], "A" => [18, "\xca="], "B" => [77, "\xcaA"], "C" => [18, "\xcaA"], "D" => [77, "\xca_"], "E" => [18, "\xca_"], "F" => [77, "\xcab"], "G" => [18, "\xcab"], "H" => [77, "\xcad"], "I" => [18, "\xcad"], "J" => [77, "\xcaf"], "K" => [18, "\xcaf"], "L" => [77, "\xcag"], "M" => [18, "\xcag"], "N" => [77, "\xcah"], "O" => [18, "\xcah"], "P" => [77, "\xcal"], "Q" => [18, "\xcal"], "R" => [77, "\xcam"], "S" => [18, "\xcam"], "T" => [77, "\xcan"], "U" => [18, "\xcan"], "V" => [77, "\xcap"], "W" => [18, "\xcap"], "X" => [77, "\xcar"], "Y" => [18, "\xcar"], "Z" => [77, "\xcau"], "[" => [18, "\xcau"], "\\" => [0, "\xca:"], "]" => [0, "\xcaB"], "^" => [0, "\xcaC"], "_" => [0, "\xcaD"], "`" => [0, "\xcaE"], "a" => [0, "\xcaF"], "b" => [0, "\xcaG"], "c" => [0, "\xcaH"], "d" => [0, "\xcaI"], "e" => [0, "\xcaJ"], "f" => [0, "\xcaK"], "g" => [0, "\xcaL"], "h" => [0, "\xcaM"], "i" => [0, "\xcaN"], "j" => [0, "\xcaO"], "k" => [0, "\xcaP"], "l" => [0, "\xcaQ"], "m" => [0, "\xcaR"], "n" => [0, "\xcaS"], "o" => [0, "\xcaT"], "p" => [0, "\xcaU"], "q" => [0, "\xcaV"], "r" => [0, "\xcaW"], "s" => [0, "\xcaY"], "t" => [0, "\xcaj"], "u" => [0, "\xcak"], "v" => [0, "\xcaq"], "w" => [0, "\xcav"], "x" => [0, "\xcaw"], "y" => [0, "\xcax"], "z" => [0, "\xcay"], "{" => [0, "\xcaz"], "|" => [82, "\xca"], "}" => [87, "\xca"], "~" => [130, "\xca"], "" => [9, "\xca"], "\x80" => [94, "\xcd0"], "\x81" => [76, "\xcd0"], "\x82" => [104, "\xcd0"], "\x83" => [16, "\xcd0"], "\x84" => [94, "\xcd1"], "\x85" => [76, "\xcd1"], "\x86" => [104, "\xcd1"], "\x87" => [16, "\xcd1"], "\x88" => [94, "\xcd2"], "\x89" => [76, "\xcd2"], "\x8a" => [104, "\xcd2"], "\x8b" => [16, "\xcd2"], "\x8c" => [94, "\xcda"], "\x8d" => [76, "\xcda"], "\x8e" => [104, "\xcda"], "\x8f" => [16, "\xcda"], "\x90" => [94, "\xcdc"], "\x91" => [76, "\xcdc"], "\x92" => [104, "\xcdc"], "\x93" => [16, "\xcdc"], "\x94" => [94, "\xcde"], "\x95" => [76, "\xcde"], "\x96" => [104, "\xcde"], "\x97" => [16, "\xcde"], "\x98" => [94, "\xcdi"], "\x99" => [76, "\xcdi"], "\x9a" => [104, "\xcdi"], "\x9b" => [16, "\xcdi"], "\x9c" => [94, "\xcdo"], "\x9d" => [76, "\xcdo"], "\x9e" => [104, "\xcdo"], "\x9f" => [16, "\xcdo"], "\xa0" => [94, "\xcds"], "\xa1" => [76, "\xcds"], "\xa2" => [104, "\xcds"], "\xa3" => [16, "\xcds"], "\xa4" => [94, "\xcdt"], "\xa5" => [76, "\xcdt"], "\xa6" => [104, "\xcdt"], "\xa7" => [16, "\xcdt"], "\xa8" => [77, "\xcd "], "\xa9" => [18, "\xcd "], "\xaa" => [77, "\xcd%"], "\xab" => [18, "\xcd%"], "\xac" => [77, "\xcd-"], "\xad" => [18, "\xcd-"], "\xae" => [77, "\xcd."], "\xaf" => [18, "\xcd."], "\xb0" => [77, "\xcd/"], "\xb1" => [18, "\xcd/"], "\xb2" => [77, "\xcd3"], "\xb3" => [18, "\xcd3"], "\xb4" => [77, "\xcd4"], "\xb5" => [18, "\xcd4"], "\xb6" => [77, "\xcd5"], "\xb7" => [18, "\xcd5"], "\xb8" => [77, "\xcd6"], "\xb9" => [18, "\xcd6"], "\xba" => [77, "\xcd7"], "\xbb" => [18, "\xcd7"], "\xbc" => [77, "\xcd8"], "\xbd" => [18, "\xcd8"], "\xbe" => [77, "\xcd9"], "\xbf" => [18, "\xcd9"], "\xc0" => [77, "\xcd="], "\xc1" => [18, "\xcd="], "\xc2" => [77, "\xcdA"], "\xc3" => [18, "\xcdA"], "\xc4" => [77, "\xcd_"], "\xc5" => [18, "\xcd_"], "\xc6" => [77, "\xcdb"], "\xc7" => [18, "\xcdb"], "\xc8" => [77, "\xcdd"], "\xc9" => [18, "\xcdd"], "\xca" => [77, "\xcdf"], "\xcb" => [18, "\xcdf"], "\xcc" => [77, "\xcdg"], "\xcd" => [18, "\xcdg"], "\xce" => [77, "\xcdh"], "\xcf" => [18, "\xcdh"], "\xd0" => [77, "\xcdl"], "\xd1" => [18, "\xcdl"], "\xd2" => [77, "\xcdm"], "\xd3" => [18, "\xcdm"], "\xd4" => [77, "\xcdn"], "\xd5" => [18, "\xcdn"], "\xd6" => [77, "\xcdp"], "\xd7" => [18, "\xcdp"], "\xd8" => [77, "\xcdr"], "\xd9" => [18, "\xcdr"], "\xda" => [77, "\xcdu"], "\xdb" => [18, "\xcdu"], "\xdc" => [0, "\xcd:"], "\xdd" => [0, "\xcdB"], "\xde" => [0, "\xcdC"], "\xdf" => [0, "\xcdD"], "\xe0" => [0, "\xcdE"], "\xe1" => [0, "\xcdF"], "\xe2" => [0, "\xcdG"], "\xe3" => [0, "\xcdH"], "\xe4" => [0, "\xcdI"], "\xe5" => [0, "\xcdJ"], "\xe6" => [0, "\xcdK"], "\xe7" => [0, "\xcdL"], "\xe8" => [0, "\xcdM"], "\xe9" => [0, "\xcdN"], "\xea" => [0, "\xcdO"], "\xeb" => [0, "\xcdP"], "\xec" => [0, "\xcdQ"], "\xed" => [0, "\xcdR"], "\xee" => [0, "\xcdS"], "\xef" => [0, "\xcdT"], "\xf0" => [0, "\xcdU"], "\xf1" => [0, "\xcdV"], "\xf2" => [0, "\xcdW"], "\xf3" => [0, "\xcdY"], "\xf4" => [0, "\xcdj"], "\xf5" => [0, "\xcdk"], "\xf6" => [0, "\xcdq"], "\xf7" => [0, "\xcdv"], "\xf8" => [0, "\xcdw"], "\xf9" => [0, "\xcdx"], "\xfa" => [0, "\xcdy"], "\xfb" => [0, "\xcdz"], "\xfc" => [82, "\xcd"], "\xfd" => [87, "\xcd"], "\xfe" => [130, "\xcd"], "\xff" => [9, "\xcd"]], ["\x00" => [77, "\xf20"], "\x01" => [18, "\xf20"], "\x02" => [77, "\xf21"], "\x03" => [18, "\xf21"], "\x04" => [77, "\xf22"], "\x05" => [18, "\xf22"], "\x06" => [77, "\xf2a"], "\x07" => [18, "\xf2a"], "\x08" => [77, "\xf2c"], "\t" => [18, "\xf2c"], "\n" => [77, "\xf2e"], "\v" => [18, "\xf2e"], "\f" => [77, "\xf2i"], "\r" => [18, "\xf2i"], "\x0e" => [77, "\xf2o"], "\x0f" => [18, "\xf2o"], "\x10" => [77, "\xf2s"], "\x11" => [18, "\xf2s"], "\x12" => [77, "\xf2t"], "\x13" => [18, "\xf2t"], "\x14" => [0, "\xf2 "], "\x15" => [0, "\xf2%"], "\x16" => [0, "\xf2-"], "\x17" => [0, "\xf2."], "\x18" => [0, "\xf2/"], "\x19" => [0, "\xf23"], "\x1a" => [0, "\xf24"], "\x1b" => [0, "\xf25"], "\x1c" => [0, "\xf26"], "\x1d" => [0, "\xf27"], "\x1e" => [0, "\xf28"], "\x1f" => [0, "\xf29"], " " => [0, "\xf2="], "!" => [0, "\xf2A"], "\"" => [0, "\xf2_"], "#" => [0, "\xf2b"], "\$" => [0, "\xf2d"], "%" => [0, "\xf2f"], "&" => [0, "\xf2g"], "'" => [0, "\xf2h"], "(" => [0, "\xf2l"], ")" => [0, "\xf2m"], "*" => [0, "\xf2n"], "+" => [0, "\xf2p"], "," => [0, "\xf2r"], "-" => [0, "\xf2u"], "." => [100, "\xf2"], "/" => [110, "\xf2"], [111, "\xf2"], [115, "\xf2"], [116, "\xf2"], [118, "\xf2"], [119, "\xf2"], [122, "\xf2"], [123, "\xf2"], [125, "\xf2"], [126, "\xf2"], [129, "\xf2"], ":" => [143, "\xf2"], ";" => [148, "\xf2"], "<" => [151, "\xf2"], "=" => [153, "\xf2"], ">" => [83, "\xf2"], "?" => [10, "\xf2"], "@" => [77, "\xf30"], "A" => [18, "\xf30"], "B" => [77, "\xf31"], "C" => [18, "\xf31"], "D" => [77, "\xf32"], "E" => [18, "\xf32"], "F" => [77, "\xf3a"], "G" => [18, "\xf3a"], "H" => [77, "\xf3c"], "I" => [18, "\xf3c"], "J" => [77, "\xf3e"], "K" => [18, "\xf3e"], "L" => [77, "\xf3i"], "M" => [18, "\xf3i"], "N" => [77, "\xf3o"], "O" => [18, "\xf3o"], "P" => [77, "\xf3s"], "Q" => [18, "\xf3s"], "R" => [77, "\xf3t"], "S" => [18, "\xf3t"], "T" => [0, "\xf3 "], "U" => [0, "\xf3%"], "V" => [0, "\xf3-"], "W" => [0, "\xf3."], "X" => [0, "\xf3/"], "Y" => [0, "\xf33"], "Z" => [0, "\xf34"], "[" => [0, "\xf35"], "\\" => [0, "\xf36"], "]" => [0, "\xf37"], "^" => [0, "\xf38"], "_" => [0, "\xf39"], "`" => [0, "\xf3="], "a" => [0, "\xf3A"], "b" => [0, "\xf3_"], "c" => [0, "\xf3b"], "d" => [0, "\xf3d"], "e" => [0, "\xf3f"], "f" => [0, "\xf3g"], "g" => [0, "\xf3h"], "h" => [0, "\xf3l"], "i" => [0, "\xf3m"], "j" => [0, "\xf3n"], "k" => [0, "\xf3p"], "l" => [0, "\xf3r"], "m" => [0, "\xf3u"], "n" => [100, "\xf3"], "o" => [110, "\xf3"], "p" => [111, "\xf3"], "q" => [115, "\xf3"], "r" => [116, "\xf3"], "s" => [118, "\xf3"], "t" => [119, "\xf3"], "u" => [122, "\xf3"], "v" => [123, "\xf3"], "w" => [125, "\xf3"], "x" => [126, "\xf3"], "y" => [129, "\xf3"], "z" => [143, "\xf3"], "{" => [148, "\xf3"], "|" => [151, "\xf3"], "}" => [153, "\xf3"], "~" => [83, "\xf3"], "" => [10, "\xf3"], "\x80" => [77, "\xff0"], "\x81" => [18, "\xff0"], "\x82" => [77, "\xff1"], "\x83" => [18, "\xff1"], "\x84" => [77, "\xff2"], "\x85" => [18, "\xff2"], "\x86" => [77, "\xffa"], "\x87" => [18, "\xffa"], "\x88" => [77, "\xffc"], "\x89" => [18, "\xffc"], "\x8a" => [77, "\xffe"], "\x8b" => [18, "\xffe"], "\x8c" => [77, "\xffi"], "\x8d" => [18, "\xffi"], "\x8e" => [77, "\xffo"], "\x8f" => [18, "\xffo"], "\x90" => [77, "\xffs"], "\x91" => [18, "\xffs"], "\x92" => [77, "\xfft"], "\x93" => [18, "\xfft"], "\x94" => [0, "\xff "], "\x95" => [0, "\xff%"], "\x96" => [0, "\xff-"], "\x97" => [0, "\xff."], "\x98" => [0, "\xff/"], "\x99" => [0, "\xff3"], "\x9a" => [0, "\xff4"], "\x9b" => [0, "\xff5"], "\x9c" => [0, "\xff6"], "\x9d" => [0, "\xff7"], "\x9e" => [0, "\xff8"], "\x9f" => [0, "\xff9"], "\xa0" => [0, "\xff="], "\xa1" => [0, "\xffA"], "\xa2" => [0, "\xff_"], "\xa3" => [0, "\xffb"], "\xa4" => [0, "\xffd"], "\xa5" => [0, "\xfff"], "\xa6" => [0, "\xffg"], "\xa7" => [0, "\xffh"], "\xa8" => [0, "\xffl"], "\xa9" => [0, "\xffm"], "\xaa" => [0, "\xffn"], "\xab" => [0, "\xffp"], "\xac" => [0, "\xffr"], "\xad" => [0, "\xffu"], "\xae" => [100, "\xff"], "\xaf" => [110, "\xff"], "\xb0" => [111, "\xff"], "\xb1" => [115, "\xff"], "\xb2" => [116, "\xff"], "\xb3" => [118, "\xff"], "\xb4" => [119, "\xff"], "\xb5" => [122, "\xff"], "\xb6" => [123, "\xff"], "\xb7" => [125, "\xff"], "\xb8" => [126, "\xff"], "\xb9" => [129, "\xff"], "\xba" => [143, "\xff"], "\xbb" => [148, "\xff"], "\xbc" => [151, "\xff"], "\xbd" => [153, "\xff"], "\xbe" => [83, "\xff"], "\xbf" => [10, "\xff"], "\xc0" => [0, "\xcb0"], "\xc1" => [0, "\xcb1"], "\xc2" => [0, "\xcb2"], "\xc3" => [0, "\xcba"], "\xc4" => [0, "\xcbc"], "\xc5" => [0, "\xcbe"], "\xc6" => [0, "\xcbi"], "\xc7" => [0, "\xcbo"], "\xc8" => [0, "\xcbs"], "\xc9" => [0, "\xcbt"], "\xca" => [73, "\xcb"], "\xcb" => [88, "\xcb"], "\xcc" => [89, "\xcb"], "\xcd" => [96, "\xcb"], "\xce" => [97, "\xcb"], "\xcf" => [99, "\xcb"], "\xd0" => [106, "\xcb"], "\xd1" => [136, "\xcb"], "\xd2" => [139, "\xcb"], "\xd3" => [141, "\xcb"], "\xd4" => [145, "\xcb"], "\xd5" => [147, "\xcb"], "\xd6" => [149, "\xcb"], "\xd7" => [101, "\xcb"], "\xd8" => [112, "\xcb"], "\xd9" => [117, "\xcb"], "\xda" => [120, "\xcb"], "\xdb" => [124, "\xcb"], "\xdc" => [127, "\xcb"], "\xdd" => [144, "\xcb"], "\xde" => [152, "\xcb"], "\xdf" => [11, "\xcb"], "\xe0" => [0, "\xcc0"], "\xe1" => [0, "\xcc1"], "\xe2" => [0, "\xcc2"], "\xe3" => [0, "\xcca"], "\xe4" => [0, "\xccc"], "\xe5" => [0, "\xcce"], "\xe6" => [0, "\xcci"], "\xe7" => [0, "\xcco"], "\xe8" => [0, "\xccs"], "\xe9" => [0, "\xcct"], "\xea" => [73, "\xcc"], "\xeb" => [88, "\xcc"], "\xec" => [89, "\xcc"], "\xed" => [96, "\xcc"], "\xee" => [97, "\xcc"], "\xef" => [99, "\xcc"], "\xf0" => [106, "\xcc"], "\xf1" => [136, "\xcc"], "\xf2" => [139, "\xcc"], "\xf3" => [141, "\xcc"], "\xf4" => [145, "\xcc"], "\xf5" => [147, "\xcc"], "\xf6" => [149, "\xcc"], "\xf7" => [101, "\xcc"], "\xf8" => [112, "\xcc"], "\xf9" => [117, "\xcc"], "\xfa" => [120, "\xcc"], "\xfb" => [124, "\xcc"], "\xfc" => [127, "\xcc"], "\xfd" => [144, "\xcc"], "\xfe" => [152, "\xcc"], "\xff" => [11, "\xcc"]], ["\x00" => [0, "\xda0"], "\x01" => [0, "\xda1"], "\x02" => [0, "\xda2"], "\x03" => [0, "\xdaa"], "\x04" => [0, "\xdac"], "\x05" => [0, "\xdae"], "\x06" => [0, "\xdai"], "\x07" => [0, "\xdao"], "\x08" => [0, "\xdas"], "\t" => [0, "\xdat"], "\n" => [73, "\xda"], "\v" => [88, "\xda"], "\f" => [89, "\xda"], "\r" => [96, "\xda"], "\x0e" => [97, "\xda"], "\x0f" => [99, "\xda"], "\x10" => [106, "\xda"], "\x11" => [136, "\xda"], "\x12" => [139, "\xda"], "\x13" => [141, "\xda"], "\x14" => [145, "\xda"], "\x15" => [147, "\xda"], "\x16" => [149, "\xda"], "\x17" => [101, "\xda"], "\x18" => [112, "\xda"], "\x19" => [117, "\xda"], "\x1a" => [120, "\xda"], "\x1b" => [124, "\xda"], "\x1c" => [127, "\xda"], "\x1d" => [144, "\xda"], "\x1e" => [152, "\xda"], "\x1f" => [11, "\xda"], " " => [0, "\xdb0"], "!" => [0, "\xdb1"], "\"" => [0, "\xdb2"], "#" => [0, "\xdba"], "\$" => [0, "\xdbc"], "%" => [0, "\xdbe"], "&" => [0, "\xdbi"], "'" => [0, "\xdbo"], "(" => [0, "\xdbs"], ")" => [0, "\xdbt"], "*" => [73, "\xdb"], "+" => [88, "\xdb"], "," => [89, "\xdb"], "-" => [96, "\xdb"], "." => [97, "\xdb"], "/" => [99, "\xdb"], [106, "\xdb"], [136, "\xdb"], [139, "\xdb"], [141, "\xdb"], [145, "\xdb"], [147, "\xdb"], [149, "\xdb"], [101, "\xdb"], [112, "\xdb"], [117, "\xdb"], ":" => [120, "\xdb"], ";" => [124, "\xdb"], "<" => [127, "\xdb"], "=" => [144, "\xdb"], ">" => [152, "\xdb"], "?" => [11, "\xdb"], "@" => [0, "\xee0"], "A" => [0, "\xee1"], "B" => [0, "\xee2"], "C" => [0, "\xeea"], "D" => [0, "\xeec"], "E" => [0, "\xeee"], "F" => [0, "\xeei"], "G" => [0, "\xeeo"], "H" => [0, "\xees"], "I" => [0, "\xeet"], "J" => [73, "\xee"], "K" => [88, "\xee"], "L" => [89, "\xee"], "M" => [96, "\xee"], "N" => [97, "\xee"], "O" => [99, "\xee"], "P" => [106, "\xee"], "Q" => [136, "\xee"], "R" => [139, "\xee"], "S" => [141, "\xee"], "T" => [145, "\xee"], "U" => [147, "\xee"], "V" => [149, "\xee"], "W" => [101, "\xee"], "X" => [112, "\xee"], "Y" => [117, "\xee"], "Z" => [120, "\xee"], "[" => [124, "\xee"], "\\" => [127, "\xee"], "]" => [144, "\xee"], "^" => [152, "\xee"], "_" => [11, "\xee"], "`" => [0, "\xf00"], "a" => [0, "\xf01"], "b" => [0, "\xf02"], "c" => [0, "\xf0a"], "d" => [0, "\xf0c"], "e" => [0, "\xf0e"], "f" => [0, "\xf0i"], "g" => [0, "\xf0o"], "h" => [0, "\xf0s"], "i" => [0, "\xf0t"], "j" => [73, "\xf0"], "k" => [88, "\xf0"], "l" => [89, "\xf0"], "m" => [96, "\xf0"], "n" => [97, "\xf0"], "o" => [99, "\xf0"], "p" => [106, "\xf0"], "q" => [136, "\xf0"], "r" => [139, "\xf0"], "s" => [141, "\xf0"], "t" => [145, "\xf0"], "u" => [147, "\xf0"], "v" => [149, "\xf0"], "w" => [101, "\xf0"], "x" => [112, "\xf0"], "y" => [117, "\xf0"], "z" => [120, "\xf0"], "{" => [124, "\xf0"], "|" => [127, "\xf0"], "}" => [144, "\xf0"], "~" => [152, "\xf0"], "" => [11, "\xf0"], "\x80" => [0, "\xf20"], "\x81" => [0, "\xf21"], "\x82" => [0, "\xf22"], "\x83" => [0, "\xf2a"], "\x84" => [0, "\xf2c"], "\x85" => [0, "\xf2e"], "\x86" => [0, "\xf2i"], "\x87" => [0, "\xf2o"], "\x88" => [0, "\xf2s"], "\x89" => [0, "\xf2t"], "\x8a" => [73, "\xf2"], "\x8b" => [88, "\xf2"], "\x8c" => [89, "\xf2"], "\x8d" => [96, "\xf2"], "\x8e" => [97, "\xf2"], "\x8f" => [99, "\xf2"], "\x90" => [106, "\xf2"], "\x91" => [136, "\xf2"], "\x92" => [139, "\xf2"], "\x93" => [141, "\xf2"], "\x94" => [145, "\xf2"], "\x95" => [147, "\xf2"], "\x96" => [149, "\xf2"], "\x97" => [101, "\xf2"], "\x98" => [112, "\xf2"], "\x99" => [117, "\xf2"], "\x9a" => [120, "\xf2"], "\x9b" => [124, "\xf2"], "\x9c" => [127, "\xf2"], "\x9d" => [144, "\xf2"], "\x9e" => [152, "\xf2"], "\x9f" => [11, "\xf2"], "\xa0" => [0, "\xf30"], "\xa1" => [0, "\xf31"], "\xa2" => [0, "\xf32"], "\xa3" => [0, "\xf3a"], "\xa4" => [0, "\xf3c"], "\xa5" => [0, "\xf3e"], "\xa6" => [0, "\xf3i"], "\xa7" => [0, "\xf3o"], "\xa8" => [0, "\xf3s"], "\xa9" => [0, "\xf3t"], "\xaa" => [73, "\xf3"], "\xab" => [88, "\xf3"], "\xac" => [89, "\xf3"], "\xad" => [96, "\xf3"], "\xae" => [97, "\xf3"], "\xaf" => [99, "\xf3"], "\xb0" => [106, "\xf3"], "\xb1" => [136, "\xf3"], "\xb2" => [139, "\xf3"], "\xb3" => [141, "\xf3"], "\xb4" => [145, "\xf3"], "\xb5" => [147, "\xf3"], "\xb6" => [149, "\xf3"], "\xb7" => [101, "\xf3"], "\xb8" => [112, "\xf3"], "\xb9" => [117, "\xf3"], "\xba" => [120, "\xf3"], "\xbb" => [124, "\xf3"], "\xbc" => [127, "\xf3"], "\xbd" => [144, "\xf3"], "\xbe" => [152, "\xf3"], "\xbf" => [11, "\xf3"], "\xc0" => [0, "\xff0"], "\xc1" => [0, "\xff1"], "\xc2" => [0, "\xff2"], "\xc3" => [0, "\xffa"], "\xc4" => [0, "\xffc"], "\xc5" => [0, "\xffe"], "\xc6" => [0, "\xffi"], "\xc7" => [0, "\xffo"], "\xc8" => [0, "\xffs"], "\xc9" => [0, "\xfft"], "\xca" => [73, "\xff"], "\xcb" => [88, "\xff"], "\xcc" => [89, "\xff"], "\xcd" => [96, "\xff"], "\xce" => [97, "\xff"], "\xcf" => [99, "\xff"], "\xd0" => [106, "\xff"], "\xd1" => [136, "\xff"], "\xd2" => [139, "\xff"], "\xd3" => [141, "\xff"], "\xd4" => [145, "\xff"], "\xd5" => [147, "\xff"], "\xd6" => [149, "\xff"], "\xd7" => [101, "\xff"], "\xd8" => [112, "\xff"], "\xd9" => [117, "\xff"], "\xda" => [120, "\xff"], "\xdb" => [124, "\xff"], "\xdc" => [127, "\xff"], "\xdd" => [144, "\xff"], "\xde" => [152, "\xff"], "\xdf" => [11, "\xff"], "\xe0" => [92, "\xcb"], "\xe1" => [95, "\xcb"], "\xe2" => [137, "\xcb"], "\xe3" => [142, "\xcb"], "\xe4" => [150, "\xcb"], "\xe5" => [74, "\xcb"], "\xe6" => [90, "\xcb"], "\xe7" => [98, "\xcb"], "\xe8" => [107, "\xcb"], "\xe9" => [140, "\xcb"], "\xea" => [146, "\xcb"], "\xeb" => [102, "\xcb"], "\xec" => [113, "\xcb"], "\xed" => [121, "\xcb"], "\xee" => [128, "\xcb"], "\xef" => [12, "\xcb"], "\xf0" => [92, "\xcc"], "\xf1" => [95, "\xcc"], "\xf2" => [137, "\xcc"], "\xf3" => [142, "\xcc"], "\xf4" => [150, "\xcc"], "\xf5" => [74, "\xcc"], "\xf6" => [90, "\xcc"], "\xf7" => [98, "\xcc"], "\xf8" => [107, "\xcc"], "\xf9" => [140, "\xcc"], "\xfa" => [146, "\xcc"], "\xfb" => [102, "\xcc"], "\xfc" => [113, "\xcc"], "\xfd" => [121, "\xcc"], "\xfe" => [128, "\xcc"], "\xff" => [12, "\xcc"]], ["\x00" => [94, "\xcb0"], "\x01" => [76, "\xcb0"], "\x02" => [104, "\xcb0"], "\x03" => [16, "\xcb0"], "\x04" => [94, "\xcb1"], "\x05" => [76, "\xcb1"], "\x06" => [104, "\xcb1"], "\x07" => [16, "\xcb1"], "\x08" => [94, "\xcb2"], "\t" => [76, "\xcb2"], "\n" => [104, "\xcb2"], "\v" => [16, "\xcb2"], "\f" => [94, "\xcba"], "\r" => [76, "\xcba"], "\x0e" => [104, "\xcba"], "\x0f" => [16, "\xcba"], "\x10" => [94, "\xcbc"], "\x11" => [76, "\xcbc"], "\x12" => [104, "\xcbc"], "\x13" => [16, "\xcbc"], "\x14" => [94, "\xcbe"], "\x15" => [76, "\xcbe"], "\x16" => [104, "\xcbe"], "\x17" => [16, "\xcbe"], "\x18" => [94, "\xcbi"], "\x19" => [76, "\xcbi"], "\x1a" => [104, "\xcbi"], "\x1b" => [16, "\xcbi"], "\x1c" => [94, "\xcbo"], "\x1d" => [76, "\xcbo"], "\x1e" => [104, "\xcbo"], "\x1f" => [16, "\xcbo"], " " => [94, "\xcbs"], "!" => [76, "\xcbs"], "\"" => [104, "\xcbs"], "#" => [16, "\xcbs"], "\$" => [94, "\xcbt"], "%" => [76, "\xcbt"], "&" => [104, "\xcbt"], "'" => [16, "\xcbt"], "(" => [77, "\xcb "], ")" => [18, "\xcb "], "*" => [77, "\xcb%"], "+" => [18, "\xcb%"], "," => [77, "\xcb-"], "-" => [18, "\xcb-"], "." => [77, "\xcb."], "/" => [18, "\xcb."], [77, "\xcb/"], [18, "\xcb/"], [77, "\xcb3"], [18, "\xcb3"], [77, "\xcb4"], [18, "\xcb4"], [77, "\xcb5"], [18, "\xcb5"], [77, "\xcb6"], [18, "\xcb6"], ":" => [77, "\xcb7"], ";" => [18, "\xcb7"], "<" => [77, "\xcb8"], "=" => [18, "\xcb8"], ">" => [77, "\xcb9"], "?" => [18, "\xcb9"], "@" => [77, "\xcb="], "A" => [18, "\xcb="], "B" => [77, "\xcbA"], "C" => [18, "\xcbA"], "D" => [77, "\xcb_"], "E" => [18, "\xcb_"], "F" => [77, "\xcbb"], "G" => [18, "\xcbb"], "H" => [77, "\xcbd"], "I" => [18, "\xcbd"], "J" => [77, "\xcbf"], "K" => [18, "\xcbf"], "L" => [77, "\xcbg"], "M" => [18, "\xcbg"], "N" => [77, "\xcbh"], "O" => [18, "\xcbh"], "P" => [77, "\xcbl"], "Q" => [18, "\xcbl"], "R" => [77, "\xcbm"], "S" => [18, "\xcbm"], "T" => [77, "\xcbn"], "U" => [18, "\xcbn"], "V" => [77, "\xcbp"], "W" => [18, "\xcbp"], "X" => [77, "\xcbr"], "Y" => [18, "\xcbr"], "Z" => [77, "\xcbu"], "[" => [18, "\xcbu"], "\\" => [0, "\xcb:"], "]" => [0, "\xcbB"], "^" => [0, "\xcbC"], "_" => [0, "\xcbD"], "`" => [0, "\xcbE"], "a" => [0, "\xcbF"], "b" => [0, "\xcbG"], "c" => [0, "\xcbH"], "d" => [0, "\xcbI"], "e" => [0, "\xcbJ"], "f" => [0, "\xcbK"], "g" => [0, "\xcbL"], "h" => [0, "\xcbM"], "i" => [0, "\xcbN"], "j" => [0, "\xcbO"], "k" => [0, "\xcbP"], "l" => [0, "\xcbQ"], "m" => [0, "\xcbR"], "n" => [0, "\xcbS"], "o" => [0, "\xcbT"], "p" => [0, "\xcbU"], "q" => [0, "\xcbV"], "r" => [0, "\xcbW"], "s" => [0, "\xcbY"], "t" => [0, "\xcbj"], "u" => [0, "\xcbk"], "v" => [0, "\xcbq"], "w" => [0, "\xcbv"], "x" => [0, "\xcbw"], "y" => [0, "\xcbx"], "z" => [0, "\xcby"], "{" => [0, "\xcbz"], "|" => [82, "\xcb"], "}" => [87, "\xcb"], "~" => [130, "\xcb"], "" => [9, "\xcb"], "\x80" => [94, "\xcc0"], "\x81" => [76, "\xcc0"], "\x82" => [104, "\xcc0"], "\x83" => [16, "\xcc0"], "\x84" => [94, "\xcc1"], "\x85" => [76, "\xcc1"], "\x86" => [104, "\xcc1"], "\x87" => [16, "\xcc1"], "\x88" => [94, "\xcc2"], "\x89" => [76, "\xcc2"], "\x8a" => [104, "\xcc2"], "\x8b" => [16, "\xcc2"], "\x8c" => [94, "\xcca"], "\x8d" => [76, "\xcca"], "\x8e" => [104, "\xcca"], "\x8f" => [16, "\xcca"], "\x90" => [94, "\xccc"], "\x91" => [76, "\xccc"], "\x92" => [104, "\xccc"], "\x93" => [16, "\xccc"], "\x94" => [94, "\xcce"], "\x95" => [76, "\xcce"], "\x96" => [104, "\xcce"], "\x97" => [16, "\xcce"], "\x98" => [94, "\xcci"], "\x99" => [76, "\xcci"], "\x9a" => [104, "\xcci"], "\x9b" => [16, "\xcci"], "\x9c" => [94, "\xcco"], "\x9d" => [76, "\xcco"], "\x9e" => [104, "\xcco"], "\x9f" => [16, "\xcco"], "\xa0" => [94, "\xccs"], "\xa1" => [76, "\xccs"], "\xa2" => [104, "\xccs"], "\xa3" => [16, "\xccs"], "\xa4" => [94, "\xcct"], "\xa5" => [76, "\xcct"], "\xa6" => [104, "\xcct"], "\xa7" => [16, "\xcct"], "\xa8" => [77, "\xcc "], "\xa9" => [18, "\xcc "], "\xaa" => [77, "\xcc%"], "\xab" => [18, "\xcc%"], "\xac" => [77, "\xcc-"], "\xad" => [18, "\xcc-"], "\xae" => [77, "\xcc."], "\xaf" => [18, "\xcc."], "\xb0" => [77, "\xcc/"], "\xb1" => [18, "\xcc/"], "\xb2" => [77, "\xcc3"], "\xb3" => [18, "\xcc3"], "\xb4" => [77, "\xcc4"], "\xb5" => [18, "\xcc4"], "\xb6" => [77, "\xcc5"], "\xb7" => [18, "\xcc5"], "\xb8" => [77, "\xcc6"], "\xb9" => [18, "\xcc6"], "\xba" => [77, "\xcc7"], "\xbb" => [18, "\xcc7"], "\xbc" => [77, "\xcc8"], "\xbd" => [18, "\xcc8"], "\xbe" => [77, "\xcc9"], "\xbf" => [18, "\xcc9"], "\xc0" => [77, "\xcc="], "\xc1" => [18, "\xcc="], "\xc2" => [77, "\xccA"], "\xc3" => [18, "\xccA"], "\xc4" => [77, "\xcc_"], "\xc5" => [18, "\xcc_"], "\xc6" => [77, "\xccb"], "\xc7" => [18, "\xccb"], "\xc8" => [77, "\xccd"], "\xc9" => [18, "\xccd"], "\xca" => [77, "\xccf"], "\xcb" => [18, "\xccf"], "\xcc" => [77, "\xccg"], "\xcd" => [18, "\xccg"], "\xce" => [77, "\xcch"], "\xcf" => [18, "\xcch"], "\xd0" => [77, "\xccl"], "\xd1" => [18, "\xccl"], "\xd2" => [77, "\xccm"], "\xd3" => [18, "\xccm"], "\xd4" => [77, "\xccn"], "\xd5" => [18, "\xccn"], "\xd6" => [77, "\xccp"], "\xd7" => [18, "\xccp"], "\xd8" => [77, "\xccr"], "\xd9" => [18, "\xccr"], "\xda" => [77, "\xccu"], "\xdb" => [18, "\xccu"], "\xdc" => [0, "\xcc:"], "\xdd" => [0, "\xccB"], "\xde" => [0, "\xccC"], "\xdf" => [0, "\xccD"], "\xe0" => [0, "\xccE"], "\xe1" => [0, "\xccF"], "\xe2" => [0, "\xccG"], "\xe3" => [0, "\xccH"], "\xe4" => [0, "\xccI"], "\xe5" => [0, "\xccJ"], "\xe6" => [0, "\xccK"], "\xe7" => [0, "\xccL"], "\xe8" => [0, "\xccM"], "\xe9" => [0, "\xccN"], "\xea" => [0, "\xccO"], "\xeb" => [0, "\xccP"], "\xec" => [0, "\xccQ"], "\xed" => [0, "\xccR"], "\xee" => [0, "\xccS"], "\xef" => [0, "\xccT"], "\xf0" => [0, "\xccU"], "\xf1" => [0, "\xccV"], "\xf2" => [0, "\xccW"], "\xf3" => [0, "\xccY"], "\xf4" => [0, "\xccj"], "\xf5" => [0, "\xcck"], "\xf6" => [0, "\xccq"], "\xf7" => [0, "\xccv"], "\xf8" => [0, "\xccw"], "\xf9" => [0, "\xccx"], "\xfa" => [0, "\xccy"], "\xfb" => [0, "\xccz"], "\xfc" => [82, "\xcc"], "\xfd" => [87, "\xcc"], "\xfe" => [130, "\xcc"], "\xff" => [9, "\xcc"]], ["\x00" => [94, "\xff0"], "\x01" => [76, "\xff0"], "\x02" => [104, "\xff0"], "\x03" => [16, "\xff0"], "\x04" => [94, "\xff1"], "\x05" => [76, "\xff1"], "\x06" => [104, "\xff1"], "\x07" => [16, "\xff1"], "\x08" => [94, "\xff2"], "\t" => [76, "\xff2"], "\n" => [104, "\xff2"], "\v" => [16, "\xff2"], "\f" => [94, "\xffa"], "\r" => [76, "\xffa"], "\x0e" => [104, "\xffa"], "\x0f" => [16, "\xffa"], "\x10" => [94, "\xffc"], "\x11" => [76, "\xffc"], "\x12" => [104, "\xffc"], "\x13" => [16, "\xffc"], "\x14" => [94, "\xffe"], "\x15" => [76, "\xffe"], "\x16" => [104, "\xffe"], "\x17" => [16, "\xffe"], "\x18" => [94, "\xffi"], "\x19" => [76, "\xffi"], "\x1a" => [104, "\xffi"], "\x1b" => [16, "\xffi"], "\x1c" => [94, "\xffo"], "\x1d" => [76, "\xffo"], "\x1e" => [104, "\xffo"], "\x1f" => [16, "\xffo"], " " => [94, "\xffs"], "!" => [76, "\xffs"], "\"" => [104, "\xffs"], "#" => [16, "\xffs"], "\$" => [94, "\xfft"], "%" => [76, "\xfft"], "&" => [104, "\xfft"], "'" => [16, "\xfft"], "(" => [77, "\xff "], ")" => [18, "\xff "], "*" => [77, "\xff%"], "+" => [18, "\xff%"], "," => [77, "\xff-"], "-" => [18, "\xff-"], "." => [77, "\xff."], "/" => [18, "\xff."], [77, "\xff/"], [18, "\xff/"], [77, "\xff3"], [18, "\xff3"], [77, "\xff4"], [18, "\xff4"], [77, "\xff5"], [18, "\xff5"], [77, "\xff6"], [18, "\xff6"], ":" => [77, "\xff7"], ";" => [18, "\xff7"], "<" => [77, "\xff8"], "=" => [18, "\xff8"], ">" => [77, "\xff9"], "?" => [18, "\xff9"], "@" => [77, "\xff="], "A" => [18, "\xff="], "B" => [77, "\xffA"], "C" => [18, "\xffA"], "D" => [77, "\xff_"], "E" => [18, "\xff_"], "F" => [77, "\xffb"], "G" => [18, "\xffb"], "H" => [77, "\xffd"], "I" => [18, "\xffd"], "J" => [77, "\xfff"], "K" => [18, "\xfff"], "L" => [77, "\xffg"], "M" => [18, "\xffg"], "N" => [77, "\xffh"], "O" => [18, "\xffh"], "P" => [77, "\xffl"], "Q" => [18, "\xffl"], "R" => [77, "\xffm"], "S" => [18, "\xffm"], "T" => [77, "\xffn"], "U" => [18, "\xffn"], "V" => [77, "\xffp"], "W" => [18, "\xffp"], "X" => [77, "\xffr"], "Y" => [18, "\xffr"], "Z" => [77, "\xffu"], "[" => [18, "\xffu"], "\\" => [0, "\xff:"], "]" => [0, "\xffB"], "^" => [0, "\xffC"], "_" => [0, "\xffD"], "`" => [0, "\xffE"], "a" => [0, "\xffF"], "b" => [0, "\xffG"], "c" => [0, "\xffH"], "d" => [0, "\xffI"], "e" => [0, "\xffJ"], "f" => [0, "\xffK"], "g" => [0, "\xffL"], "h" => [0, "\xffM"], "i" => [0, "\xffN"], "j" => [0, "\xffO"], "k" => [0, "\xffP"], "l" => [0, "\xffQ"], "m" => [0, "\xffR"], "n" => [0, "\xffS"], "o" => [0, "\xffT"], "p" => [0, "\xffU"], "q" => [0, "\xffV"], "r" => [0, "\xffW"], "s" => [0, "\xffY"], "t" => [0, "\xffj"], "u" => [0, "\xffk"], "v" => [0, "\xffq"], "w" => [0, "\xffv"], "x" => [0, "\xffw"], "y" => [0, "\xffx"], "z" => [0, "\xffy"], "{" => [0, "\xffz"], "|" => [82, "\xff"], "}" => [87, "\xff"], "~" => [130, "\xff"], "" => [9, "\xff"], "\x80" => [77, "\xcb0"], "\x81" => [18, "\xcb0"], "\x82" => [77, "\xcb1"], "\x83" => [18, "\xcb1"], "\x84" => [77, "\xcb2"], "\x85" => [18, "\xcb2"], "\x86" => [77, "\xcba"], "\x87" => [18, "\xcba"], "\x88" => [77, "\xcbc"], "\x89" => [18, "\xcbc"], "\x8a" => [77, "\xcbe"], "\x8b" => [18, "\xcbe"], "\x8c" => [77, "\xcbi"], "\x8d" => [18, "\xcbi"], "\x8e" => [77, "\xcbo"], "\x8f" => [18, "\xcbo"], "\x90" => [77, "\xcbs"], "\x91" => [18, "\xcbs"], "\x92" => [77, "\xcbt"], "\x93" => [18, "\xcbt"], "\x94" => [0, "\xcb "], "\x95" => [0, "\xcb%"], "\x96" => [0, "\xcb-"], "\x97" => [0, "\xcb."], "\x98" => [0, "\xcb/"], "\x99" => [0, "\xcb3"], "\x9a" => [0, "\xcb4"], "\x9b" => [0, "\xcb5"], "\x9c" => [0, "\xcb6"], "\x9d" => [0, "\xcb7"], "\x9e" => [0, "\xcb8"], "\x9f" => [0, "\xcb9"], "\xa0" => [0, "\xcb="], "\xa1" => [0, "\xcbA"], "\xa2" => [0, "\xcb_"], "\xa3" => [0, "\xcbb"], "\xa4" => [0, "\xcbd"], "\xa5" => [0, "\xcbf"], "\xa6" => [0, "\xcbg"], "\xa7" => [0, "\xcbh"], "\xa8" => [0, "\xcbl"], "\xa9" => [0, "\xcbm"], "\xaa" => [0, "\xcbn"], "\xab" => [0, "\xcbp"], "\xac" => [0, "\xcbr"], "\xad" => [0, "\xcbu"], "\xae" => [100, "\xcb"], "\xaf" => [110, "\xcb"], "\xb0" => [111, "\xcb"], "\xb1" => [115, "\xcb"], "\xb2" => [116, "\xcb"], "\xb3" => [118, "\xcb"], "\xb4" => [119, "\xcb"], "\xb5" => [122, "\xcb"], "\xb6" => [123, "\xcb"], "\xb7" => [125, "\xcb"], "\xb8" => [126, "\xcb"], "\xb9" => [129, "\xcb"], "\xba" => [143, "\xcb"], "\xbb" => [148, "\xcb"], "\xbc" => [151, "\xcb"], "\xbd" => [153, "\xcb"], "\xbe" => [83, "\xcb"], "\xbf" => [10, "\xcb"], "\xc0" => [77, "\xcc0"], "\xc1" => [18, "\xcc0"], "\xc2" => [77, "\xcc1"], "\xc3" => [18, "\xcc1"], "\xc4" => [77, "\xcc2"], "\xc5" => [18, "\xcc2"], "\xc6" => [77, "\xcca"], "\xc7" => [18, "\xcca"], "\xc8" => [77, "\xccc"], "\xc9" => [18, "\xccc"], "\xca" => [77, "\xcce"], "\xcb" => [18, "\xcce"], "\xcc" => [77, "\xcci"], "\xcd" => [18, "\xcci"], "\xce" => [77, "\xcco"], "\xcf" => [18, "\xcco"], "\xd0" => [77, "\xccs"], "\xd1" => [18, "\xccs"], "\xd2" => [77, "\xcct"], "\xd3" => [18, "\xcct"], "\xd4" => [0, "\xcc "], "\xd5" => [0, "\xcc%"], "\xd6" => [0, "\xcc-"], "\xd7" => [0, "\xcc."], "\xd8" => [0, "\xcc/"], "\xd9" => [0, "\xcc3"], "\xda" => [0, "\xcc4"], "\xdb" => [0, "\xcc5"], "\xdc" => [0, "\xcc6"], "\xdd" => [0, "\xcc7"], "\xde" => [0, "\xcc8"], "\xdf" => [0, "\xcc9"], "\xe0" => [0, "\xcc="], "\xe1" => [0, "\xccA"], "\xe2" => [0, "\xcc_"], "\xe3" => [0, "\xccb"], "\xe4" => [0, "\xccd"], "\xe5" => [0, "\xccf"], "\xe6" => [0, "\xccg"], "\xe7" => [0, "\xcch"], "\xe8" => [0, "\xccl"], "\xe9" => [0, "\xccm"], "\xea" => [0, "\xccn"], "\xeb" => [0, "\xccp"], "\xec" => [0, "\xccr"], "\xed" => [0, "\xccu"], "\xee" => [100, "\xcc"], "\xef" => [110, "\xcc"], "\xf0" => [111, "\xcc"], "\xf1" => [115, "\xcc"], "\xf2" => [116, "\xcc"], "\xf3" => [118, "\xcc"], "\xf4" => [119, "\xcc"], "\xf5" => [122, "\xcc"], "\xf6" => [123, "\xcc"], "\xf7" => [125, "\xcc"], "\xf8" => [126, "\xcc"], "\xf9" => [129, "\xcc"], "\xfa" => [143, "\xcc"], "\xfb" => [148, "\xcc"], "\xfc" => [151, "\xcc"], "\xfd" => [153, "\xcc"], "\xfe" => [83, "\xcc"], "\xff" => [10, "\xcc"]], ["\x00" => [94, "\xd20"], "\x01" => [76, "\xd20"], "\x02" => [104, "\xd20"], "\x03" => [16, "\xd20"], "\x04" => [94, "\xd21"], "\x05" => [76, "\xd21"], "\x06" => [104, "\xd21"], "\x07" => [16, "\xd21"], "\x08" => [94, "\xd22"], "\t" => [76, "\xd22"], "\n" => [104, "\xd22"], "\v" => [16, "\xd22"], "\f" => [94, "\xd2a"], "\r" => [76, "\xd2a"], "\x0e" => [104, "\xd2a"], "\x0f" => [16, "\xd2a"], "\x10" => [94, "\xd2c"], "\x11" => [76, "\xd2c"], "\x12" => [104, "\xd2c"], "\x13" => [16, "\xd2c"], "\x14" => [94, "\xd2e"], "\x15" => [76, "\xd2e"], "\x16" => [104, "\xd2e"], "\x17" => [16, "\xd2e"], "\x18" => [94, "\xd2i"], "\x19" => [76, "\xd2i"], "\x1a" => [104, "\xd2i"], "\x1b" => [16, "\xd2i"], "\x1c" => [94, "\xd2o"], "\x1d" => [76, "\xd2o"], "\x1e" => [104, "\xd2o"], "\x1f" => [16, "\xd2o"], " " => [94, "\xd2s"], "!" => [76, "\xd2s"], "\"" => [104, "\xd2s"], "#" => [16, "\xd2s"], "\$" => [94, "\xd2t"], "%" => [76, "\xd2t"], "&" => [104, "\xd2t"], "'" => [16, "\xd2t"], "(" => [77, "\xd2 "], ")" => [18, "\xd2 "], "*" => [77, "\xd2%"], "+" => [18, "\xd2%"], "," => [77, "\xd2-"], "-" => [18, "\xd2-"], "." => [77, "\xd2."], "/" => [18, "\xd2."], [77, "\xd2/"], [18, "\xd2/"], [77, "\xd23"], [18, "\xd23"], [77, "\xd24"], [18, "\xd24"], [77, "\xd25"], [18, "\xd25"], [77, "\xd26"], [18, "\xd26"], ":" => [77, "\xd27"], ";" => [18, "\xd27"], "<" => [77, "\xd28"], "=" => [18, "\xd28"], ">" => [77, "\xd29"], "?" => [18, "\xd29"], "@" => [77, "\xd2="], "A" => [18, "\xd2="], "B" => [77, "\xd2A"], "C" => [18, "\xd2A"], "D" => [77, "\xd2_"], "E" => [18, "\xd2_"], "F" => [77, "\xd2b"], "G" => [18, "\xd2b"], "H" => [77, "\xd2d"], "I" => [18, "\xd2d"], "J" => [77, "\xd2f"], "K" => [18, "\xd2f"], "L" => [77, "\xd2g"], "M" => [18, "\xd2g"], "N" => [77, "\xd2h"], "O" => [18, "\xd2h"], "P" => [77, "\xd2l"], "Q" => [18, "\xd2l"], "R" => [77, "\xd2m"], "S" => [18, "\xd2m"], "T" => [77, "\xd2n"], "U" => [18, "\xd2n"], "V" => [77, "\xd2p"], "W" => [18, "\xd2p"], "X" => [77, "\xd2r"], "Y" => [18, "\xd2r"], "Z" => [77, "\xd2u"], "[" => [18, "\xd2u"], "\\" => [0, "\xd2:"], "]" => [0, "\xd2B"], "^" => [0, "\xd2C"], "_" => [0, "\xd2D"], "`" => [0, "\xd2E"], "a" => [0, "\xd2F"], "b" => [0, "\xd2G"], "c" => [0, "\xd2H"], "d" => [0, "\xd2I"], "e" => [0, "\xd2J"], "f" => [0, "\xd2K"], "g" => [0, "\xd2L"], "h" => [0, "\xd2M"], "i" => [0, "\xd2N"], "j" => [0, "\xd2O"], "k" => [0, "\xd2P"], "l" => [0, "\xd2Q"], "m" => [0, "\xd2R"], "n" => [0, "\xd2S"], "o" => [0, "\xd2T"], "p" => [0, "\xd2U"], "q" => [0, "\xd2V"], "r" => [0, "\xd2W"], "s" => [0, "\xd2Y"], "t" => [0, "\xd2j"], "u" => [0, "\xd2k"], "v" => [0, "\xd2q"], "w" => [0, "\xd2v"], "x" => [0, "\xd2w"], "y" => [0, "\xd2x"], "z" => [0, "\xd2y"], "{" => [0, "\xd2z"], "|" => [82, "\xd2"], "}" => [87, "\xd2"], "~" => [130, "\xd2"], "" => [9, "\xd2"], "\x80" => [94, "\xd50"], "\x81" => [76, "\xd50"], "\x82" => [104, "\xd50"], "\x83" => [16, "\xd50"], "\x84" => [94, "\xd51"], "\x85" => [76, "\xd51"], "\x86" => [104, "\xd51"], "\x87" => [16, "\xd51"], "\x88" => [94, "\xd52"], "\x89" => [76, "\xd52"], "\x8a" => [104, "\xd52"], "\x8b" => [16, "\xd52"], "\x8c" => [94, "\xd5a"], "\x8d" => [76, "\xd5a"], "\x8e" => [104, "\xd5a"], "\x8f" => [16, "\xd5a"], "\x90" => [94, "\xd5c"], "\x91" => [76, "\xd5c"], "\x92" => [104, "\xd5c"], "\x93" => [16, "\xd5c"], "\x94" => [94, "\xd5e"], "\x95" => [76, "\xd5e"], "\x96" => [104, "\xd5e"], "\x97" => [16, "\xd5e"], "\x98" => [94, "\xd5i"], "\x99" => [76, "\xd5i"], "\x9a" => [104, "\xd5i"], "\x9b" => [16, "\xd5i"], "\x9c" => [94, "\xd5o"], "\x9d" => [76, "\xd5o"], "\x9e" => [104, "\xd5o"], "\x9f" => [16, "\xd5o"], "\xa0" => [94, "\xd5s"], "\xa1" => [76, "\xd5s"], "\xa2" => [104, "\xd5s"], "\xa3" => [16, "\xd5s"], "\xa4" => [94, "\xd5t"], "\xa5" => [76, "\xd5t"], "\xa6" => [104, "\xd5t"], "\xa7" => [16, "\xd5t"], "\xa8" => [77, "\xd5 "], "\xa9" => [18, "\xd5 "], "\xaa" => [77, "\xd5%"], "\xab" => [18, "\xd5%"], "\xac" => [77, "\xd5-"], "\xad" => [18, "\xd5-"], "\xae" => [77, "\xd5."], "\xaf" => [18, "\xd5."], "\xb0" => [77, "\xd5/"], "\xb1" => [18, "\xd5/"], "\xb2" => [77, "\xd53"], "\xb3" => [18, "\xd53"], "\xb4" => [77, "\xd54"], "\xb5" => [18, "\xd54"], "\xb6" => [77, "\xd55"], "\xb7" => [18, "\xd55"], "\xb8" => [77, "\xd56"], "\xb9" => [18, "\xd56"], "\xba" => [77, "\xd57"], "\xbb" => [18, "\xd57"], "\xbc" => [77, "\xd58"], "\xbd" => [18, "\xd58"], "\xbe" => [77, "\xd59"], "\xbf" => [18, "\xd59"], "\xc0" => [77, "\xd5="], "\xc1" => [18, "\xd5="], "\xc2" => [77, "\xd5A"], "\xc3" => [18, "\xd5A"], "\xc4" => [77, "\xd5_"], "\xc5" => [18, "\xd5_"], "\xc6" => [77, "\xd5b"], "\xc7" => [18, "\xd5b"], "\xc8" => [77, "\xd5d"], "\xc9" => [18, "\xd5d"], "\xca" => [77, "\xd5f"], "\xcb" => [18, "\xd5f"], "\xcc" => [77, "\xd5g"], "\xcd" => [18, "\xd5g"], "\xce" => [77, "\xd5h"], "\xcf" => [18, "\xd5h"], "\xd0" => [77, "\xd5l"], "\xd1" => [18, "\xd5l"], "\xd2" => [77, "\xd5m"], "\xd3" => [18, "\xd5m"], "\xd4" => [77, "\xd5n"], "\xd5" => [18, "\xd5n"], "\xd6" => [77, "\xd5p"], "\xd7" => [18, "\xd5p"], "\xd8" => [77, "\xd5r"], "\xd9" => [18, "\xd5r"], "\xda" => [77, "\xd5u"], "\xdb" => [18, "\xd5u"], "\xdc" => [0, "\xd5:"], "\xdd" => [0, "\xd5B"], "\xde" => [0, "\xd5C"], "\xdf" => [0, "\xd5D"], "\xe0" => [0, "\xd5E"], "\xe1" => [0, "\xd5F"], "\xe2" => [0, "\xd5G"], "\xe3" => [0, "\xd5H"], "\xe4" => [0, "\xd5I"], "\xe5" => [0, "\xd5J"], "\xe6" => [0, "\xd5K"], "\xe7" => [0, "\xd5L"], "\xe8" => [0, "\xd5M"], "\xe9" => [0, "\xd5N"], "\xea" => [0, "\xd5O"], "\xeb" => [0, "\xd5P"], "\xec" => [0, "\xd5Q"], "\xed" => [0, "\xd5R"], "\xee" => [0, "\xd5S"], "\xef" => [0, "\xd5T"], "\xf0" => [0, "\xd5U"], "\xf1" => [0, "\xd5V"], "\xf2" => [0, "\xd5W"], "\xf3" => [0, "\xd5Y"], "\xf4" => [0, "\xd5j"], "\xf5" => [0, "\xd5k"], "\xf6" => [0, "\xd5q"], "\xf7" => [0, "\xd5v"], "\xf8" => [0, "\xd5w"], "\xf9" => [0, "\xd5x"], "\xfa" => [0, "\xd5y"], "\xfb" => [0, "\xd5z"], "\xfc" => [82, "\xd5"], "\xfd" => [87, "\xd5"], "\xfe" => [130, "\xd5"], "\xff" => [9, "\xd5"]], ["\x00" => [0, "\xd30"], "\x01" => [0, "\xd31"], "\x02" => [0, "\xd32"], "\x03" => [0, "\xd3a"], "\x04" => [0, "\xd3c"], "\x05" => [0, "\xd3e"], "\x06" => [0, "\xd3i"], "\x07" => [0, "\xd3o"], "\x08" => [0, "\xd3s"], "\t" => [0, "\xd3t"], "\n" => [73, "\xd3"], "\v" => [88, "\xd3"], "\f" => [89, "\xd3"], "\r" => [96, "\xd3"], "\x0e" => [97, "\xd3"], "\x0f" => [99, "\xd3"], "\x10" => [106, "\xd3"], "\x11" => [136, "\xd3"], "\x12" => [139, "\xd3"], "\x13" => [141, "\xd3"], "\x14" => [145, "\xd3"], "\x15" => [147, "\xd3"], "\x16" => [149, "\xd3"], "\x17" => [101, "\xd3"], "\x18" => [112, "\xd3"], "\x19" => [117, "\xd3"], "\x1a" => [120, "\xd3"], "\x1b" => [124, "\xd3"], "\x1c" => [127, "\xd3"], "\x1d" => [144, "\xd3"], "\x1e" => [152, "\xd3"], "\x1f" => [11, "\xd3"], " " => [0, "\xd40"], "!" => [0, "\xd41"], "\"" => [0, "\xd42"], "#" => [0, "\xd4a"], "\$" => [0, "\xd4c"], "%" => [0, "\xd4e"], "&" => [0, "\xd4i"], "'" => [0, "\xd4o"], "(" => [0, "\xd4s"], ")" => [0, "\xd4t"], "*" => [73, "\xd4"], "+" => [88, "\xd4"], "," => [89, "\xd4"], "-" => [96, "\xd4"], "." => [97, "\xd4"], "/" => [99, "\xd4"], [106, "\xd4"], [136, "\xd4"], [139, "\xd4"], [141, "\xd4"], [145, "\xd4"], [147, "\xd4"], [149, "\xd4"], [101, "\xd4"], [112, "\xd4"], [117, "\xd4"], ":" => [120, "\xd4"], ";" => [124, "\xd4"], "<" => [127, "\xd4"], "=" => [144, "\xd4"], ">" => [152, "\xd4"], "?" => [11, "\xd4"], "@" => [0, "\xd60"], "A" => [0, "\xd61"], "B" => [0, "\xd62"], "C" => [0, "\xd6a"], "D" => [0, "\xd6c"], "E" => [0, "\xd6e"], "F" => [0, "\xd6i"], "G" => [0, "\xd6o"], "H" => [0, "\xd6s"], "I" => [0, "\xd6t"], "J" => [73, "\xd6"], "K" => [88, "\xd6"], "L" => [89, "\xd6"], "M" => [96, "\xd6"], "N" => [97, "\xd6"], "O" => [99, "\xd6"], "P" => [106, "\xd6"], "Q" => [136, "\xd6"], "R" => [139, "\xd6"], "S" => [141, "\xd6"], "T" => [145, "\xd6"], "U" => [147, "\xd6"], "V" => [149, "\xd6"], "W" => [101, "\xd6"], "X" => [112, "\xd6"], "Y" => [117, "\xd6"], "Z" => [120, "\xd6"], "[" => [124, "\xd6"], "\\" => [127, "\xd6"], "]" => [144, "\xd6"], "^" => [152, "\xd6"], "_" => [11, "\xd6"], "`" => [0, "\xdd0"], "a" => [0, "\xdd1"], "b" => [0, "\xdd2"], "c" => [0, "\xdda"], "d" => [0, "\xddc"], "e" => [0, "\xdde"], "f" => [0, "\xddi"], "g" => [0, "\xddo"], "h" => [0, "\xdds"], "i" => [0, "\xddt"], "j" => [73, "\xdd"], "k" => [88, "\xdd"], "l" => [89, "\xdd"], "m" => [96, "\xdd"], "n" => [97, "\xdd"], "o" => [99, "\xdd"], "p" => [106, "\xdd"], "q" => [136, "\xdd"], "r" => [139, "\xdd"], "s" => [141, "\xdd"], "t" => [145, "\xdd"], "u" => [147, "\xdd"], "v" => [149, "\xdd"], "w" => [101, "\xdd"], "x" => [112, "\xdd"], "y" => [117, "\xdd"], "z" => [120, "\xdd"], "{" => [124, "\xdd"], "|" => [127, "\xdd"], "}" => [144, "\xdd"], "~" => [152, "\xdd"], "" => [11, "\xdd"], "\x80" => [0, "\xde0"], "\x81" => [0, "\xde1"], "\x82" => [0, "\xde2"], "\x83" => [0, "\xdea"], "\x84" => [0, "\xdec"], "\x85" => [0, "\xdee"], "\x86" => [0, "\xdei"], "\x87" => [0, "\xdeo"], "\x88" => [0, "\xdes"], "\x89" => [0, "\xdet"], "\x8a" => [73, "\xde"], "\x8b" => [88, "\xde"], "\x8c" => [89, "\xde"], "\x8d" => [96, "\xde"], "\x8e" => [97, "\xde"], "\x8f" => [99, "\xde"], "\x90" => [106, "\xde"], "\x91" => [136, "\xde"], "\x92" => [139, "\xde"], "\x93" => [141, "\xde"], "\x94" => [145, "\xde"], "\x95" => [147, "\xde"], "\x96" => [149, "\xde"], "\x97" => [101, "\xde"], "\x98" => [112, "\xde"], "\x99" => [117, "\xde"], "\x9a" => [120, "\xde"], "\x9b" => [124, "\xde"], "\x9c" => [127, "\xde"], "\x9d" => [144, "\xde"], "\x9e" => [152, "\xde"], "\x9f" => [11, "\xde"], "\xa0" => [0, "\xdf0"], "\xa1" => [0, "\xdf1"], "\xa2" => [0, "\xdf2"], "\xa3" => [0, "\xdfa"], "\xa4" => [0, "\xdfc"], "\xa5" => [0, "\xdfe"], "\xa6" => [0, "\xdfi"], "\xa7" => [0, "\xdfo"], "\xa8" => [0, "\xdfs"], "\xa9" => [0, "\xdft"], "\xaa" => [73, "\xdf"], "\xab" => [88, "\xdf"], "\xac" => [89, "\xdf"], "\xad" => [96, "\xdf"], "\xae" => [97, "\xdf"], "\xaf" => [99, "\xdf"], "\xb0" => [106, "\xdf"], "\xb1" => [136, "\xdf"], "\xb2" => [139, "\xdf"], "\xb3" => [141, "\xdf"], "\xb4" => [145, "\xdf"], "\xb5" => [147, "\xdf"], "\xb6" => [149, "\xdf"], "\xb7" => [101, "\xdf"], "\xb8" => [112, "\xdf"], "\xb9" => [117, "\xdf"], "\xba" => [120, "\xdf"], "\xbb" => [124, "\xdf"], "\xbc" => [127, "\xdf"], "\xbd" => [144, "\xdf"], "\xbe" => [152, "\xdf"], "\xbf" => [11, "\xdf"], "\xc0" => [0, "\xf10"], "\xc1" => [0, "\xf11"], "\xc2" => [0, "\xf12"], "\xc3" => [0, "\xf1a"], "\xc4" => [0, "\xf1c"], "\xc5" => [0, "\xf1e"], "\xc6" => [0, "\xf1i"], "\xc7" => [0, "\xf1o"], "\xc8" => [0, "\xf1s"], "\xc9" => [0, "\xf1t"], "\xca" => [73, "\xf1"], "\xcb" => [88, "\xf1"], "\xcc" => [89, "\xf1"], "\xcd" => [96, "\xf1"], "\xce" => [97, "\xf1"], "\xcf" => [99, "\xf1"], "\xd0" => [106, "\xf1"], "\xd1" => [136, "\xf1"], "\xd2" => [139, "\xf1"], "\xd3" => [141, "\xf1"], "\xd4" => [145, "\xf1"], "\xd5" => [147, "\xf1"], "\xd6" => [149, "\xf1"], "\xd7" => [101, "\xf1"], "\xd8" => [112, "\xf1"], "\xd9" => [117, "\xf1"], "\xda" => [120, "\xf1"], "\xdb" => [124, "\xf1"], "\xdc" => [127, "\xf1"], "\xdd" => [144, "\xf1"], "\xde" => [152, "\xf1"], "\xdf" => [11, "\xf1"], "\xe0" => [0, "\xf40"], "\xe1" => [0, "\xf41"], "\xe2" => [0, "\xf42"], "\xe3" => [0, "\xf4a"], "\xe4" => [0, "\xf4c"], "\xe5" => [0, "\xf4e"], "\xe6" => [0, "\xf4i"], "\xe7" => [0, "\xf4o"], "\xe8" => [0, "\xf4s"], "\xe9" => [0, "\xf4t"], "\xea" => [73, "\xf4"], "\xeb" => [88, "\xf4"], "\xec" => [89, "\xf4"], "\xed" => [96, "\xf4"], "\xee" => [97, "\xf4"], "\xef" => [99, "\xf4"], "\xf0" => [106, "\xf4"], "\xf1" => [136, "\xf4"], "\xf2" => [139, "\xf4"], "\xf3" => [141, "\xf4"], "\xf4" => [145, "\xf4"], "\xf5" => [147, "\xf4"], "\xf6" => [149, "\xf4"], "\xf7" => [101, "\xf4"], "\xf8" => [112, "\xf4"], "\xf9" => [117, "\xf4"], "\xfa" => [120, "\xf4"], "\xfb" => [124, "\xf4"], "\xfc" => [127, "\xf4"], "\xfd" => [144, "\xf4"], "\xfe" => [152, "\xf4"], "\xff" => [11, "\xf4"]], ["\x00" => [92, "\xd3"], "\x01" => [95, "\xd3"], "\x02" => [137, "\xd3"], "\x03" => [142, "\xd3"], "\x04" => [150, "\xd3"], "\x05" => [74, "\xd3"], "\x06" => [90, "\xd3"], "\x07" => [98, "\xd3"], "\x08" => [107, "\xd3"], "\t" => [140, "\xd3"], "\n" => [146, "\xd3"], "\v" => [102, "\xd3"], "\f" => [113, "\xd3"], "\r" => [121, "\xd3"], "\x0e" => [128, "\xd3"], "\x0f" => [12, "\xd3"], "\x10" => [92, "\xd4"], "\x11" => [95, "\xd4"], "\x12" => [137, "\xd4"], "\x13" => [142, "\xd4"], "\x14" => [150, "\xd4"], "\x15" => [74, "\xd4"], "\x16" => [90, "\xd4"], "\x17" => [98, "\xd4"], "\x18" => [107, "\xd4"], "\x19" => [140, "\xd4"], "\x1a" => [146, "\xd4"], "\x1b" => [102, "\xd4"], "\x1c" => [113, "\xd4"], "\x1d" => [121, "\xd4"], "\x1e" => [128, "\xd4"], "\x1f" => [12, "\xd4"], " " => [92, "\xd6"], "!" => [95, "\xd6"], "\"" => [137, "\xd6"], "#" => [142, "\xd6"], "\$" => [150, "\xd6"], "%" => [74, "\xd6"], "&" => [90, "\xd6"], "'" => [98, "\xd6"], "(" => [107, "\xd6"], ")" => [140, "\xd6"], "*" => [146, "\xd6"], "+" => [102, "\xd6"], "," => [113, "\xd6"], "-" => [121, "\xd6"], "." => [128, "\xd6"], "/" => [12, "\xd6"], [92, "\xdd"], [95, "\xdd"], [137, "\xdd"], [142, "\xdd"], [150, "\xdd"], [74, "\xdd"], [90, "\xdd"], [98, "\xdd"], [107, "\xdd"], [140, "\xdd"], ":" => [146, "\xdd"], ";" => [102, "\xdd"], "<" => [113, "\xdd"], "=" => [121, "\xdd"], ">" => [128, "\xdd"], "?" => [12, "\xdd"], "@" => [92, "\xde"], "A" => [95, "\xde"], "B" => [137, "\xde"], "C" => [142, "\xde"], "D" => [150, "\xde"], "E" => [74, "\xde"], "F" => [90, "\xde"], "G" => [98, "\xde"], "H" => [107, "\xde"], "I" => [140, "\xde"], "J" => [146, "\xde"], "K" => [102, "\xde"], "L" => [113, "\xde"], "M" => [121, "\xde"], "N" => [128, "\xde"], "O" => [12, "\xde"], "P" => [92, "\xdf"], "Q" => [95, "\xdf"], "R" => [137, "\xdf"], "S" => [142, "\xdf"], "T" => [150, "\xdf"], "U" => [74, "\xdf"], "V" => [90, "\xdf"], "W" => [98, "\xdf"], "X" => [107, "\xdf"], "Y" => [140, "\xdf"], "Z" => [146, "\xdf"], "[" => [102, "\xdf"], "\\" => [113, "\xdf"], "]" => [121, "\xdf"], "^" => [128, "\xdf"], "_" => [12, "\xdf"], "`" => [92, "\xf1"], "a" => [95, "\xf1"], "b" => [137, "\xf1"], "c" => [142, "\xf1"], "d" => [150, "\xf1"], "e" => [74, "\xf1"], "f" => [90, "\xf1"], "g" => [98, "\xf1"], "h" => [107, "\xf1"], "i" => [140, "\xf1"], "j" => [146, "\xf1"], "k" => [102, "\xf1"], "l" => [113, "\xf1"], "m" => [121, "\xf1"], "n" => [128, "\xf1"], "o" => [12, "\xf1"], "p" => [92, "\xf4"], "q" => [95, "\xf4"], "r" => [137, "\xf4"], "s" => [142, "\xf4"], "t" => [150, "\xf4"], "u" => [74, "\xf4"], "v" => [90, "\xf4"], "w" => [98, "\xf4"], "x" => [107, "\xf4"], "y" => [140, "\xf4"], "z" => [146, "\xf4"], "{" => [102, "\xf4"], "|" => [113, "\xf4"], "}" => [121, "\xf4"], "~" => [128, "\xf4"], "" => [12, "\xf4"], "\x80" => [92, "\xf5"], "\x81" => [95, "\xf5"], "\x82" => [137, "\xf5"], "\x83" => [142, "\xf5"], "\x84" => [150, "\xf5"], "\x85" => [74, "\xf5"], "\x86" => [90, "\xf5"], "\x87" => [98, "\xf5"], "\x88" => [107, "\xf5"], "\x89" => [140, "\xf5"], "\x8a" => [146, "\xf5"], "\x8b" => [102, "\xf5"], "\x8c" => [113, "\xf5"], "\x8d" => [121, "\xf5"], "\x8e" => [128, "\xf5"], "\x8f" => [12, "\xf5"], "\x90" => [92, "\xf6"], "\x91" => [95, "\xf6"], "\x92" => [137, "\xf6"], "\x93" => [142, "\xf6"], "\x94" => [150, "\xf6"], "\x95" => [74, "\xf6"], "\x96" => [90, "\xf6"], "\x97" => [98, "\xf6"], "\x98" => [107, "\xf6"], "\x99" => [140, "\xf6"], "\x9a" => [146, "\xf6"], "\x9b" => [102, "\xf6"], "\x9c" => [113, "\xf6"], "\x9d" => [121, "\xf6"], "\x9e" => [128, "\xf6"], "\x9f" => [12, "\xf6"], "\xa0" => [92, "\xf7"], "\xa1" => [95, "\xf7"], "\xa2" => [137, "\xf7"], "\xa3" => [142, "\xf7"], "\xa4" => [150, "\xf7"], "\xa5" => [74, "\xf7"], "\xa6" => [90, "\xf7"], "\xa7" => [98, "\xf7"], "\xa8" => [107, "\xf7"], "\xa9" => [140, "\xf7"], "\xaa" => [146, "\xf7"], "\xab" => [102, "\xf7"], "\xac" => [113, "\xf7"], "\xad" => [121, "\xf7"], "\xae" => [128, "\xf7"], "\xaf" => [12, "\xf7"], "\xb0" => [92, "\xf8"], "\xb1" => [95, "\xf8"], "\xb2" => [137, "\xf8"], "\xb3" => [142, "\xf8"], "\xb4" => [150, "\xf8"], "\xb5" => [74, "\xf8"], "\xb6" => [90, "\xf8"], "\xb7" => [98, "\xf8"], "\xb8" => [107, "\xf8"], "\xb9" => [140, "\xf8"], "\xba" => [146, "\xf8"], "\xbb" => [102, "\xf8"], "\xbc" => [113, "\xf8"], "\xbd" => [121, "\xf8"], "\xbe" => [128, "\xf8"], "\xbf" => [12, "\xf8"], "\xc0" => [92, "\xfa"], "\xc1" => [95, "\xfa"], "\xc2" => [137, "\xfa"], "\xc3" => [142, "\xfa"], "\xc4" => [150, "\xfa"], "\xc5" => [74, "\xfa"], "\xc6" => [90, "\xfa"], "\xc7" => [98, "\xfa"], "\xc8" => [107, "\xfa"], "\xc9" => [140, "\xfa"], "\xca" => [146, "\xfa"], "\xcb" => [102, "\xfa"], "\xcc" => [113, "\xfa"], "\xcd" => [121, "\xfa"], "\xce" => [128, "\xfa"], "\xcf" => [12, "\xfa"], "\xd0" => [92, "\xfb"], "\xd1" => [95, "\xfb"], "\xd2" => [137, "\xfb"], "\xd3" => [142, "\xfb"], "\xd4" => [150, "\xfb"], "\xd5" => [74, "\xfb"], "\xd6" => [90, "\xfb"], "\xd7" => [98, "\xfb"], "\xd8" => [107, "\xfb"], "\xd9" => [140, "\xfb"], "\xda" => [146, "\xfb"], "\xdb" => [102, "\xfb"], "\xdc" => [113, "\xfb"], "\xdd" => [121, "\xfb"], "\xde" => [128, "\xfb"], "\xdf" => [12, "\xfb"], "\xe0" => [92, "\xfc"], "\xe1" => [95, "\xfc"], "\xe2" => [137, "\xfc"], "\xe3" => [142, "\xfc"], "\xe4" => [150, "\xfc"], "\xe5" => [74, "\xfc"], "\xe6" => [90, "\xfc"], "\xe7" => [98, "\xfc"], "\xe8" => [107, "\xfc"], "\xe9" => [140, "\xfc"], "\xea" => [146, "\xfc"], "\xeb" => [102, "\xfc"], "\xec" => [113, "\xfc"], "\xed" => [121, "\xfc"], "\xee" => [128, "\xfc"], "\xef" => [12, "\xfc"], "\xf0" => [92, "\xfd"], "\xf1" => [95, "\xfd"], "\xf2" => [137, "\xfd"], "\xf3" => [142, "\xfd"], "\xf4" => [150, "\xfd"], "\xf5" => [74, "\xfd"], "\xf6" => [90, "\xfd"], "\xf7" => [98, "\xfd"], "\xf8" => [107, "\xfd"], "\xf9" => [140, "\xfd"], "\xfa" => [146, "\xfd"], "\xfb" => [102, "\xfd"], "\xfc" => [113, "\xfd"], "\xfd" => [121, "\xfd"], "\xfe" => [128, "\xfd"], "\xff" => [12, "\xfd"]], ["\x00" => [94, "\xd30"], "\x01" => [76, "\xd30"], "\x02" => [104, "\xd30"], "\x03" => [16, "\xd30"], "\x04" => [94, "\xd31"], "\x05" => [76, "\xd31"], "\x06" => [104, "\xd31"], "\x07" => [16, "\xd31"], "\x08" => [94, "\xd32"], "\t" => [76, "\xd32"], "\n" => [104, "\xd32"], "\v" => [16, "\xd32"], "\f" => [94, "\xd3a"], "\r" => [76, "\xd3a"], "\x0e" => [104, "\xd3a"], "\x0f" => [16, "\xd3a"], "\x10" => [94, "\xd3c"], "\x11" => [76, "\xd3c"], "\x12" => [104, "\xd3c"], "\x13" => [16, "\xd3c"], "\x14" => [94, "\xd3e"], "\x15" => [76, "\xd3e"], "\x16" => [104, "\xd3e"], "\x17" => [16, "\xd3e"], "\x18" => [94, "\xd3i"], "\x19" => [76, "\xd3i"], "\x1a" => [104, "\xd3i"], "\x1b" => [16, "\xd3i"], "\x1c" => [94, "\xd3o"], "\x1d" => [76, "\xd3o"], "\x1e" => [104, "\xd3o"], "\x1f" => [16, "\xd3o"], " " => [94, "\xd3s"], "!" => [76, "\xd3s"], "\"" => [104, "\xd3s"], "#" => [16, "\xd3s"], "\$" => [94, "\xd3t"], "%" => [76, "\xd3t"], "&" => [104, "\xd3t"], "'" => [16, "\xd3t"], "(" => [77, "\xd3 "], ")" => [18, "\xd3 "], "*" => [77, "\xd3%"], "+" => [18, "\xd3%"], "," => [77, "\xd3-"], "-" => [18, "\xd3-"], "." => [77, "\xd3."], "/" => [18, "\xd3."], [77, "\xd3/"], [18, "\xd3/"], [77, "\xd33"], [18, "\xd33"], [77, "\xd34"], [18, "\xd34"], [77, "\xd35"], [18, "\xd35"], [77, "\xd36"], [18, "\xd36"], ":" => [77, "\xd37"], ";" => [18, "\xd37"], "<" => [77, "\xd38"], "=" => [18, "\xd38"], ">" => [77, "\xd39"], "?" => [18, "\xd39"], "@" => [77, "\xd3="], "A" => [18, "\xd3="], "B" => [77, "\xd3A"], "C" => [18, "\xd3A"], "D" => [77, "\xd3_"], "E" => [18, "\xd3_"], "F" => [77, "\xd3b"], "G" => [18, "\xd3b"], "H" => [77, "\xd3d"], "I" => [18, "\xd3d"], "J" => [77, "\xd3f"], "K" => [18, "\xd3f"], "L" => [77, "\xd3g"], "M" => [18, "\xd3g"], "N" => [77, "\xd3h"], "O" => [18, "\xd3h"], "P" => [77, "\xd3l"], "Q" => [18, "\xd3l"], "R" => [77, "\xd3m"], "S" => [18, "\xd3m"], "T" => [77, "\xd3n"], "U" => [18, "\xd3n"], "V" => [77, "\xd3p"], "W" => [18, "\xd3p"], "X" => [77, "\xd3r"], "Y" => [18, "\xd3r"], "Z" => [77, "\xd3u"], "[" => [18, "\xd3u"], "\\" => [0, "\xd3:"], "]" => [0, "\xd3B"], "^" => [0, "\xd3C"], "_" => [0, "\xd3D"], "`" => [0, "\xd3E"], "a" => [0, "\xd3F"], "b" => [0, "\xd3G"], "c" => [0, "\xd3H"], "d" => [0, "\xd3I"], "e" => [0, "\xd3J"], "f" => [0, "\xd3K"], "g" => [0, "\xd3L"], "h" => [0, "\xd3M"], "i" => [0, "\xd3N"], "j" => [0, "\xd3O"], "k" => [0, "\xd3P"], "l" => [0, "\xd3Q"], "m" => [0, "\xd3R"], "n" => [0, "\xd3S"], "o" => [0, "\xd3T"], "p" => [0, "\xd3U"], "q" => [0, "\xd3V"], "r" => [0, "\xd3W"], "s" => [0, "\xd3Y"], "t" => [0, "\xd3j"], "u" => [0, "\xd3k"], "v" => [0, "\xd3q"], "w" => [0, "\xd3v"], "x" => [0, "\xd3w"], "y" => [0, "\xd3x"], "z" => [0, "\xd3y"], "{" => [0, "\xd3z"], "|" => [82, "\xd3"], "}" => [87, "\xd3"], "~" => [130, "\xd3"], "" => [9, "\xd3"], "\x80" => [94, "\xd40"], "\x81" => [76, "\xd40"], "\x82" => [104, "\xd40"], "\x83" => [16, "\xd40"], "\x84" => [94, "\xd41"], "\x85" => [76, "\xd41"], "\x86" => [104, "\xd41"], "\x87" => [16, "\xd41"], "\x88" => [94, "\xd42"], "\x89" => [76, "\xd42"], "\x8a" => [104, "\xd42"], "\x8b" => [16, "\xd42"], "\x8c" => [94, "\xd4a"], "\x8d" => [76, "\xd4a"], "\x8e" => [104, "\xd4a"], "\x8f" => [16, "\xd4a"], "\x90" => [94, "\xd4c"], "\x91" => [76, "\xd4c"], "\x92" => [104, "\xd4c"], "\x93" => [16, "\xd4c"], "\x94" => [94, "\xd4e"], "\x95" => [76, "\xd4e"], "\x96" => [104, "\xd4e"], "\x97" => [16, "\xd4e"], "\x98" => [94, "\xd4i"], "\x99" => [76, "\xd4i"], "\x9a" => [104, "\xd4i"], "\x9b" => [16, "\xd4i"], "\x9c" => [94, "\xd4o"], "\x9d" => [76, "\xd4o"], "\x9e" => [104, "\xd4o"], "\x9f" => [16, "\xd4o"], "\xa0" => [94, "\xd4s"], "\xa1" => [76, "\xd4s"], "\xa2" => [104, "\xd4s"], "\xa3" => [16, "\xd4s"], "\xa4" => [94, "\xd4t"], "\xa5" => [76, "\xd4t"], "\xa6" => [104, "\xd4t"], "\xa7" => [16, "\xd4t"], "\xa8" => [77, "\xd4 "], "\xa9" => [18, "\xd4 "], "\xaa" => [77, "\xd4%"], "\xab" => [18, "\xd4%"], "\xac" => [77, "\xd4-"], "\xad" => [18, "\xd4-"], "\xae" => [77, "\xd4."], "\xaf" => [18, "\xd4."], "\xb0" => [77, "\xd4/"], "\xb1" => [18, "\xd4/"], "\xb2" => [77, "\xd43"], "\xb3" => [18, "\xd43"], "\xb4" => [77, "\xd44"], "\xb5" => [18, "\xd44"], "\xb6" => [77, "\xd45"], "\xb7" => [18, "\xd45"], "\xb8" => [77, "\xd46"], "\xb9" => [18, "\xd46"], "\xba" => [77, "\xd47"], "\xbb" => [18, "\xd47"], "\xbc" => [77, "\xd48"], "\xbd" => [18, "\xd48"], "\xbe" => [77, "\xd49"], "\xbf" => [18, "\xd49"], "\xc0" => [77, "\xd4="], "\xc1" => [18, "\xd4="], "\xc2" => [77, "\xd4A"], "\xc3" => [18, "\xd4A"], "\xc4" => [77, "\xd4_"], "\xc5" => [18, "\xd4_"], "\xc6" => [77, "\xd4b"], "\xc7" => [18, "\xd4b"], "\xc8" => [77, "\xd4d"], "\xc9" => [18, "\xd4d"], "\xca" => [77, "\xd4f"], "\xcb" => [18, "\xd4f"], "\xcc" => [77, "\xd4g"], "\xcd" => [18, "\xd4g"], "\xce" => [77, "\xd4h"], "\xcf" => [18, "\xd4h"], "\xd0" => [77, "\xd4l"], "\xd1" => [18, "\xd4l"], "\xd2" => [77, "\xd4m"], "\xd3" => [18, "\xd4m"], "\xd4" => [77, "\xd4n"], "\xd5" => [18, "\xd4n"], "\xd6" => [77, "\xd4p"], "\xd7" => [18, "\xd4p"], "\xd8" => [77, "\xd4r"], "\xd9" => [18, "\xd4r"], "\xda" => [77, "\xd4u"], "\xdb" => [18, "\xd4u"], "\xdc" => [0, "\xd4:"], "\xdd" => [0, "\xd4B"], "\xde" => [0, "\xd4C"], "\xdf" => [0, "\xd4D"], "\xe0" => [0, "\xd4E"], "\xe1" => [0, "\xd4F"], "\xe2" => [0, "\xd4G"], "\xe3" => [0, "\xd4H"], "\xe4" => [0, "\xd4I"], "\xe5" => [0, "\xd4J"], "\xe6" => [0, "\xd4K"], "\xe7" => [0, "\xd4L"], "\xe8" => [0, "\xd4M"], "\xe9" => [0, "\xd4N"], "\xea" => [0, "\xd4O"], "\xeb" => [0, "\xd4P"], "\xec" => [0, "\xd4Q"], "\xed" => [0, "\xd4R"], "\xee" => [0, "\xd4S"], "\xef" => [0, "\xd4T"], "\xf0" => [0, "\xd4U"], "\xf1" => [0, "\xd4V"], "\xf2" => [0, "\xd4W"], "\xf3" => [0, "\xd4Y"], "\xf4" => [0, "\xd4j"], "\xf5" => [0, "\xd4k"], "\xf6" => [0, "\xd4q"], "\xf7" => [0, "\xd4v"], "\xf8" => [0, "\xd4w"], "\xf9" => [0, "\xd4x"], "\xfa" => [0, "\xd4y"], "\xfb" => [0, "\xd4z"], "\xfc" => [82, "\xd4"], "\xfd" => [87, "\xd4"], "\xfe" => [130, "\xd4"], "\xff" => [9, "\xd4"]], ["\x00" => [77, "\xd30"], "\x01" => [18, "\xd30"], "\x02" => [77, "\xd31"], "\x03" => [18, "\xd31"], "\x04" => [77, "\xd32"], "\x05" => [18, "\xd32"], "\x06" => [77, "\xd3a"], "\x07" => [18, "\xd3a"], "\x08" => [77, "\xd3c"], "\t" => [18, "\xd3c"], "\n" => [77, "\xd3e"], "\v" => [18, "\xd3e"], "\f" => [77, "\xd3i"], "\r" => [18, "\xd3i"], "\x0e" => [77, "\xd3o"], "\x0f" => [18, "\xd3o"], "\x10" => [77, "\xd3s"], "\x11" => [18, "\xd3s"], "\x12" => [77, "\xd3t"], "\x13" => [18, "\xd3t"], "\x14" => [0, "\xd3 "], "\x15" => [0, "\xd3%"], "\x16" => [0, "\xd3-"], "\x17" => [0, "\xd3."], "\x18" => [0, "\xd3/"], "\x19" => [0, "\xd33"], "\x1a" => [0, "\xd34"], "\x1b" => [0, "\xd35"], "\x1c" => [0, "\xd36"], "\x1d" => [0, "\xd37"], "\x1e" => [0, "\xd38"], "\x1f" => [0, "\xd39"], " " => [0, "\xd3="], "!" => [0, "\xd3A"], "\"" => [0, "\xd3_"], "#" => [0, "\xd3b"], "\$" => [0, "\xd3d"], "%" => [0, "\xd3f"], "&" => [0, "\xd3g"], "'" => [0, "\xd3h"], "(" => [0, "\xd3l"], ")" => [0, "\xd3m"], "*" => [0, "\xd3n"], "+" => [0, "\xd3p"], "," => [0, "\xd3r"], "-" => [0, "\xd3u"], "." => [100, "\xd3"], "/" => [110, "\xd3"], [111, "\xd3"], [115, "\xd3"], [116, "\xd3"], [118, "\xd3"], [119, "\xd3"], [122, "\xd3"], [123, "\xd3"], [125, "\xd3"], [126, "\xd3"], [129, "\xd3"], ":" => [143, "\xd3"], ";" => [148, "\xd3"], "<" => [151, "\xd3"], "=" => [153, "\xd3"], ">" => [83, "\xd3"], "?" => [10, "\xd3"], "@" => [77, "\xd40"], "A" => [18, "\xd40"], "B" => [77, "\xd41"], "C" => [18, "\xd41"], "D" => [77, "\xd42"], "E" => [18, "\xd42"], "F" => [77, "\xd4a"], "G" => [18, "\xd4a"], "H" => [77, "\xd4c"], "I" => [18, "\xd4c"], "J" => [77, "\xd4e"], "K" => [18, "\xd4e"], "L" => [77, "\xd4i"], "M" => [18, "\xd4i"], "N" => [77, "\xd4o"], "O" => [18, "\xd4o"], "P" => [77, "\xd4s"], "Q" => [18, "\xd4s"], "R" => [77, "\xd4t"], "S" => [18, "\xd4t"], "T" => [0, "\xd4 "], "U" => [0, "\xd4%"], "V" => [0, "\xd4-"], "W" => [0, "\xd4."], "X" => [0, "\xd4/"], "Y" => [0, "\xd43"], "Z" => [0, "\xd44"], "[" => [0, "\xd45"], "\\" => [0, "\xd46"], "]" => [0, "\xd47"], "^" => [0, "\xd48"], "_" => [0, "\xd49"], "`" => [0, "\xd4="], "a" => [0, "\xd4A"], "b" => [0, "\xd4_"], "c" => [0, "\xd4b"], "d" => [0, "\xd4d"], "e" => [0, "\xd4f"], "f" => [0, "\xd4g"], "g" => [0, "\xd4h"], "h" => [0, "\xd4l"], "i" => [0, "\xd4m"], "j" => [0, "\xd4n"], "k" => [0, "\xd4p"], "l" => [0, "\xd4r"], "m" => [0, "\xd4u"], "n" => [100, "\xd4"], "o" => [110, "\xd4"], "p" => [111, "\xd4"], "q" => [115, "\xd4"], "r" => [116, "\xd4"], "s" => [118, "\xd4"], "t" => [119, "\xd4"], "u" => [122, "\xd4"], "v" => [123, "\xd4"], "w" => [125, "\xd4"], "x" => [126, "\xd4"], "y" => [129, "\xd4"], "z" => [143, "\xd4"], "{" => [148, "\xd4"], "|" => [151, "\xd4"], "}" => [153, "\xd4"], "~" => [83, "\xd4"], "" => [10, "\xd4"], "\x80" => [77, "\xd60"], "\x81" => [18, "\xd60"], "\x82" => [77, "\xd61"], "\x83" => [18, "\xd61"], "\x84" => [77, "\xd62"], "\x85" => [18, "\xd62"], "\x86" => [77, "\xd6a"], "\x87" => [18, "\xd6a"], "\x88" => [77, "\xd6c"], "\x89" => [18, "\xd6c"], "\x8a" => [77, "\xd6e"], "\x8b" => [18, "\xd6e"], "\x8c" => [77, "\xd6i"], "\x8d" => [18, "\xd6i"], "\x8e" => [77, "\xd6o"], "\x8f" => [18, "\xd6o"], "\x90" => [77, "\xd6s"], "\x91" => [18, "\xd6s"], "\x92" => [77, "\xd6t"], "\x93" => [18, "\xd6t"], "\x94" => [0, "\xd6 "], "\x95" => [0, "\xd6%"], "\x96" => [0, "\xd6-"], "\x97" => [0, "\xd6."], "\x98" => [0, "\xd6/"], "\x99" => [0, "\xd63"], "\x9a" => [0, "\xd64"], "\x9b" => [0, "\xd65"], "\x9c" => [0, "\xd66"], "\x9d" => [0, "\xd67"], "\x9e" => [0, "\xd68"], "\x9f" => [0, "\xd69"], "\xa0" => [0, "\xd6="], "\xa1" => [0, "\xd6A"], "\xa2" => [0, "\xd6_"], "\xa3" => [0, "\xd6b"], "\xa4" => [0, "\xd6d"], "\xa5" => [0, "\xd6f"], "\xa6" => [0, "\xd6g"], "\xa7" => [0, "\xd6h"], "\xa8" => [0, "\xd6l"], "\xa9" => [0, "\xd6m"], "\xaa" => [0, "\xd6n"], "\xab" => [0, "\xd6p"], "\xac" => [0, "\xd6r"], "\xad" => [0, "\xd6u"], "\xae" => [100, "\xd6"], "\xaf" => [110, "\xd6"], "\xb0" => [111, "\xd6"], "\xb1" => [115, "\xd6"], "\xb2" => [116, "\xd6"], "\xb3" => [118, "\xd6"], "\xb4" => [119, "\xd6"], "\xb5" => [122, "\xd6"], "\xb6" => [123, "\xd6"], "\xb7" => [125, "\xd6"], "\xb8" => [126, "\xd6"], "\xb9" => [129, "\xd6"], "\xba" => [143, "\xd6"], "\xbb" => [148, "\xd6"], "\xbc" => [151, "\xd6"], "\xbd" => [153, "\xd6"], "\xbe" => [83, "\xd6"], "\xbf" => [10, "\xd6"], "\xc0" => [77, "\xdd0"], "\xc1" => [18, "\xdd0"], "\xc2" => [77, "\xdd1"], "\xc3" => [18, "\xdd1"], "\xc4" => [77, "\xdd2"], "\xc5" => [18, "\xdd2"], "\xc6" => [77, "\xdda"], "\xc7" => [18, "\xdda"], "\xc8" => [77, "\xddc"], "\xc9" => [18, "\xddc"], "\xca" => [77, "\xdde"], "\xcb" => [18, "\xdde"], "\xcc" => [77, "\xddi"], "\xcd" => [18, "\xddi"], "\xce" => [77, "\xddo"], "\xcf" => [18, "\xddo"], "\xd0" => [77, "\xdds"], "\xd1" => [18, "\xdds"], "\xd2" => [77, "\xddt"], "\xd3" => [18, "\xddt"], "\xd4" => [0, "\xdd "], "\xd5" => [0, "\xdd%"], "\xd6" => [0, "\xdd-"], "\xd7" => [0, "\xdd."], "\xd8" => [0, "\xdd/"], "\xd9" => [0, "\xdd3"], "\xda" => [0, "\xdd4"], "\xdb" => [0, "\xdd5"], "\xdc" => [0, "\xdd6"], "\xdd" => [0, "\xdd7"], "\xde" => [0, "\xdd8"], "\xdf" => [0, "\xdd9"], "\xe0" => [0, "\xdd="], "\xe1" => [0, "\xddA"], "\xe2" => [0, "\xdd_"], "\xe3" => [0, "\xddb"], "\xe4" => [0, "\xddd"], "\xe5" => [0, "\xddf"], "\xe6" => [0, "\xddg"], "\xe7" => [0, "\xddh"], "\xe8" => [0, "\xddl"], "\xe9" => [0, "\xddm"], "\xea" => [0, "\xddn"], "\xeb" => [0, "\xddp"], "\xec" => [0, "\xddr"], "\xed" => [0, "\xddu"], "\xee" => [100, "\xdd"], "\xef" => [110, "\xdd"], "\xf0" => [111, "\xdd"], "\xf1" => [115, "\xdd"], "\xf2" => [116, "\xdd"], "\xf3" => [118, "\xdd"], "\xf4" => [119, "\xdd"], "\xf5" => [122, "\xdd"], "\xf6" => [123, "\xdd"], "\xf7" => [125, "\xdd"], "\xf8" => [126, "\xdd"], "\xf9" => [129, "\xdd"], "\xfa" => [143, "\xdd"], "\xfb" => [148, "\xdd"], "\xfc" => [151, "\xdd"], "\xfd" => [153, "\xdd"], "\xfe" => [83, "\xdd"], "\xff" => [10, "\xdd"]], ["\x00" => [94, "\xd60"], "\x01" => [76, "\xd60"], "\x02" => [104, "\xd60"], "\x03" => [16, "\xd60"], "\x04" => [94, "\xd61"], "\x05" => [76, "\xd61"], "\x06" => [104, "\xd61"], "\x07" => [16, "\xd61"], "\x08" => [94, "\xd62"], "\t" => [76, "\xd62"], "\n" => [104, "\xd62"], "\v" => [16, "\xd62"], "\f" => [94, "\xd6a"], "\r" => [76, "\xd6a"], "\x0e" => [104, "\xd6a"], "\x0f" => [16, "\xd6a"], "\x10" => [94, "\xd6c"], "\x11" => [76, "\xd6c"], "\x12" => [104, "\xd6c"], "\x13" => [16, "\xd6c"], "\x14" => [94, "\xd6e"], "\x15" => [76, "\xd6e"], "\x16" => [104, "\xd6e"], "\x17" => [16, "\xd6e"], "\x18" => [94, "\xd6i"], "\x19" => [76, "\xd6i"], "\x1a" => [104, "\xd6i"], "\x1b" => [16, "\xd6i"], "\x1c" => [94, "\xd6o"], "\x1d" => [76, "\xd6o"], "\x1e" => [104, "\xd6o"], "\x1f" => [16, "\xd6o"], " " => [94, "\xd6s"], "!" => [76, "\xd6s"], "\"" => [104, "\xd6s"], "#" => [16, "\xd6s"], "\$" => [94, "\xd6t"], "%" => [76, "\xd6t"], "&" => [104, "\xd6t"], "'" => [16, "\xd6t"], "(" => [77, "\xd6 "], ")" => [18, "\xd6 "], "*" => [77, "\xd6%"], "+" => [18, "\xd6%"], "," => [77, "\xd6-"], "-" => [18, "\xd6-"], "." => [77, "\xd6."], "/" => [18, "\xd6."], [77, "\xd6/"], [18, "\xd6/"], [77, "\xd63"], [18, "\xd63"], [77, "\xd64"], [18, "\xd64"], [77, "\xd65"], [18, "\xd65"], [77, "\xd66"], [18, "\xd66"], ":" => [77, "\xd67"], ";" => [18, "\xd67"], "<" => [77, "\xd68"], "=" => [18, "\xd68"], ">" => [77, "\xd69"], "?" => [18, "\xd69"], "@" => [77, "\xd6="], "A" => [18, "\xd6="], "B" => [77, "\xd6A"], "C" => [18, "\xd6A"], "D" => [77, "\xd6_"], "E" => [18, "\xd6_"], "F" => [77, "\xd6b"], "G" => [18, "\xd6b"], "H" => [77, "\xd6d"], "I" => [18, "\xd6d"], "J" => [77, "\xd6f"], "K" => [18, "\xd6f"], "L" => [77, "\xd6g"], "M" => [18, "\xd6g"], "N" => [77, "\xd6h"], "O" => [18, "\xd6h"], "P" => [77, "\xd6l"], "Q" => [18, "\xd6l"], "R" => [77, "\xd6m"], "S" => [18, "\xd6m"], "T" => [77, "\xd6n"], "U" => [18, "\xd6n"], "V" => [77, "\xd6p"], "W" => [18, "\xd6p"], "X" => [77, "\xd6r"], "Y" => [18, "\xd6r"], "Z" => [77, "\xd6u"], "[" => [18, "\xd6u"], "\\" => [0, "\xd6:"], "]" => [0, "\xd6B"], "^" => [0, "\xd6C"], "_" => [0, "\xd6D"], "`" => [0, "\xd6E"], "a" => [0, "\xd6F"], "b" => [0, "\xd6G"], "c" => [0, "\xd6H"], "d" => [0, "\xd6I"], "e" => [0, "\xd6J"], "f" => [0, "\xd6K"], "g" => [0, "\xd6L"], "h" => [0, "\xd6M"], "i" => [0, "\xd6N"], "j" => [0, "\xd6O"], "k" => [0, "\xd6P"], "l" => [0, "\xd6Q"], "m" => [0, "\xd6R"], "n" => [0, "\xd6S"], "o" => [0, "\xd6T"], "p" => [0, "\xd6U"], "q" => [0, "\xd6V"], "r" => [0, "\xd6W"], "s" => [0, "\xd6Y"], "t" => [0, "\xd6j"], "u" => [0, "\xd6k"], "v" => [0, "\xd6q"], "w" => [0, "\xd6v"], "x" => [0, "\xd6w"], "y" => [0, "\xd6x"], "z" => [0, "\xd6y"], "{" => [0, "\xd6z"], "|" => [82, "\xd6"], "}" => [87, "\xd6"], "~" => [130, "\xd6"], "" => [9, "\xd6"], "\x80" => [94, "\xdd0"], "\x81" => [76, "\xdd0"], "\x82" => [104, "\xdd0"], "\x83" => [16, "\xdd0"], "\x84" => [94, "\xdd1"], "\x85" => [76, "\xdd1"], "\x86" => [104, "\xdd1"], "\x87" => [16, "\xdd1"], "\x88" => [94, "\xdd2"], "\x89" => [76, "\xdd2"], "\x8a" => [104, "\xdd2"], "\x8b" => [16, "\xdd2"], "\x8c" => [94, "\xdda"], "\x8d" => [76, "\xdda"], "\x8e" => [104, "\xdda"], "\x8f" => [16, "\xdda"], "\x90" => [94, "\xddc"], "\x91" => [76, "\xddc"], "\x92" => [104, "\xddc"], "\x93" => [16, "\xddc"], "\x94" => [94, "\xdde"], "\x95" => [76, "\xdde"], "\x96" => [104, "\xdde"], "\x97" => [16, "\xdde"], "\x98" => [94, "\xddi"], "\x99" => [76, "\xddi"], "\x9a" => [104, "\xddi"], "\x9b" => [16, "\xddi"], "\x9c" => [94, "\xddo"], "\x9d" => [76, "\xddo"], "\x9e" => [104, "\xddo"], "\x9f" => [16, "\xddo"], "\xa0" => [94, "\xdds"], "\xa1" => [76, "\xdds"], "\xa2" => [104, "\xdds"], "\xa3" => [16, "\xdds"], "\xa4" => [94, "\xddt"], "\xa5" => [76, "\xddt"], "\xa6" => [104, "\xddt"], "\xa7" => [16, "\xddt"], "\xa8" => [77, "\xdd "], "\xa9" => [18, "\xdd "], "\xaa" => [77, "\xdd%"], "\xab" => [18, "\xdd%"], "\xac" => [77, "\xdd-"], "\xad" => [18, "\xdd-"], "\xae" => [77, "\xdd."], "\xaf" => [18, "\xdd."], "\xb0" => [77, "\xdd/"], "\xb1" => [18, "\xdd/"], "\xb2" => [77, "\xdd3"], "\xb3" => [18, "\xdd3"], "\xb4" => [77, "\xdd4"], "\xb5" => [18, "\xdd4"], "\xb6" => [77, "\xdd5"], "\xb7" => [18, "\xdd5"], "\xb8" => [77, "\xdd6"], "\xb9" => [18, "\xdd6"], "\xba" => [77, "\xdd7"], "\xbb" => [18, "\xdd7"], "\xbc" => [77, "\xdd8"], "\xbd" => [18, "\xdd8"], "\xbe" => [77, "\xdd9"], "\xbf" => [18, "\xdd9"], "\xc0" => [77, "\xdd="], "\xc1" => [18, "\xdd="], "\xc2" => [77, "\xddA"], "\xc3" => [18, "\xddA"], "\xc4" => [77, "\xdd_"], "\xc5" => [18, "\xdd_"], "\xc6" => [77, "\xddb"], "\xc7" => [18, "\xddb"], "\xc8" => [77, "\xddd"], "\xc9" => [18, "\xddd"], "\xca" => [77, "\xddf"], "\xcb" => [18, "\xddf"], "\xcc" => [77, "\xddg"], "\xcd" => [18, "\xddg"], "\xce" => [77, "\xddh"], "\xcf" => [18, "\xddh"], "\xd0" => [77, "\xddl"], "\xd1" => [18, "\xddl"], "\xd2" => [77, "\xddm"], "\xd3" => [18, "\xddm"], "\xd4" => [77, "\xddn"], "\xd5" => [18, "\xddn"], "\xd6" => [77, "\xddp"], "\xd7" => [18, "\xddp"], "\xd8" => [77, "\xddr"], "\xd9" => [18, "\xddr"], "\xda" => [77, "\xddu"], "\xdb" => [18, "\xddu"], "\xdc" => [0, "\xdd:"], "\xdd" => [0, "\xddB"], "\xde" => [0, "\xddC"], "\xdf" => [0, "\xddD"], "\xe0" => [0, "\xddE"], "\xe1" => [0, "\xddF"], "\xe2" => [0, "\xddG"], "\xe3" => [0, "\xddH"], "\xe4" => [0, "\xddI"], "\xe5" => [0, "\xddJ"], "\xe6" => [0, "\xddK"], "\xe7" => [0, "\xddL"], "\xe8" => [0, "\xddM"], "\xe9" => [0, "\xddN"], "\xea" => [0, "\xddO"], "\xeb" => [0, "\xddP"], "\xec" => [0, "\xddQ"], "\xed" => [0, "\xddR"], "\xee" => [0, "\xddS"], "\xef" => [0, "\xddT"], "\xf0" => [0, "\xddU"], "\xf1" => [0, "\xddV"], "\xf2" => [0, "\xddW"], "\xf3" => [0, "\xddY"], "\xf4" => [0, "\xddj"], "\xf5" => [0, "\xddk"], "\xf6" => [0, "\xddq"], "\xf7" => [0, "\xddv"], "\xf8" => [0, "\xddw"], "\xf9" => [0, "\xddx"], "\xfa" => [0, "\xddy"], "\xfb" => [0, "\xddz"], "\xfc" => [82, "\xdd"], "\xfd" => [87, "\xdd"], "\xfe" => [130, "\xdd"], "\xff" => [9, "\xdd"]], ["\x00" => [94, "\xd70"], "\x01" => [76, "\xd70"], "\x02" => [104, "\xd70"], "\x03" => [16, "\xd70"], "\x04" => [94, "\xd71"], "\x05" => [76, "\xd71"], "\x06" => [104, "\xd71"], "\x07" => [16, "\xd71"], "\x08" => [94, "\xd72"], "\t" => [76, "\xd72"], "\n" => [104, "\xd72"], "\v" => [16, "\xd72"], "\f" => [94, "\xd7a"], "\r" => [76, "\xd7a"], "\x0e" => [104, "\xd7a"], "\x0f" => [16, "\xd7a"], "\x10" => [94, "\xd7c"], "\x11" => [76, "\xd7c"], "\x12" => [104, "\xd7c"], "\x13" => [16, "\xd7c"], "\x14" => [94, "\xd7e"], "\x15" => [76, "\xd7e"], "\x16" => [104, "\xd7e"], "\x17" => [16, "\xd7e"], "\x18" => [94, "\xd7i"], "\x19" => [76, "\xd7i"], "\x1a" => [104, "\xd7i"], "\x1b" => [16, "\xd7i"], "\x1c" => [94, "\xd7o"], "\x1d" => [76, "\xd7o"], "\x1e" => [104, "\xd7o"], "\x1f" => [16, "\xd7o"], " " => [94, "\xd7s"], "!" => [76, "\xd7s"], "\"" => [104, "\xd7s"], "#" => [16, "\xd7s"], "\$" => [94, "\xd7t"], "%" => [76, "\xd7t"], "&" => [104, "\xd7t"], "'" => [16, "\xd7t"], "(" => [77, "\xd7 "], ")" => [18, "\xd7 "], "*" => [77, "\xd7%"], "+" => [18, "\xd7%"], "," => [77, "\xd7-"], "-" => [18, "\xd7-"], "." => [77, "\xd7."], "/" => [18, "\xd7."], [77, "\xd7/"], [18, "\xd7/"], [77, "\xd73"], [18, "\xd73"], [77, "\xd74"], [18, "\xd74"], [77, "\xd75"], [18, "\xd75"], [77, "\xd76"], [18, "\xd76"], ":" => [77, "\xd77"], ";" => [18, "\xd77"], "<" => [77, "\xd78"], "=" => [18, "\xd78"], ">" => [77, "\xd79"], "?" => [18, "\xd79"], "@" => [77, "\xd7="], "A" => [18, "\xd7="], "B" => [77, "\xd7A"], "C" => [18, "\xd7A"], "D" => [77, "\xd7_"], "E" => [18, "\xd7_"], "F" => [77, "\xd7b"], "G" => [18, "\xd7b"], "H" => [77, "\xd7d"], "I" => [18, "\xd7d"], "J" => [77, "\xd7f"], "K" => [18, "\xd7f"], "L" => [77, "\xd7g"], "M" => [18, "\xd7g"], "N" => [77, "\xd7h"], "O" => [18, "\xd7h"], "P" => [77, "\xd7l"], "Q" => [18, "\xd7l"], "R" => [77, "\xd7m"], "S" => [18, "\xd7m"], "T" => [77, "\xd7n"], "U" => [18, "\xd7n"], "V" => [77, "\xd7p"], "W" => [18, "\xd7p"], "X" => [77, "\xd7r"], "Y" => [18, "\xd7r"], "Z" => [77, "\xd7u"], "[" => [18, "\xd7u"], "\\" => [0, "\xd7:"], "]" => [0, "\xd7B"], "^" => [0, "\xd7C"], "_" => [0, "\xd7D"], "`" => [0, "\xd7E"], "a" => [0, "\xd7F"], "b" => [0, "\xd7G"], "c" => [0, "\xd7H"], "d" => [0, "\xd7I"], "e" => [0, "\xd7J"], "f" => [0, "\xd7K"], "g" => [0, "\xd7L"], "h" => [0, "\xd7M"], "i" => [0, "\xd7N"], "j" => [0, "\xd7O"], "k" => [0, "\xd7P"], "l" => [0, "\xd7Q"], "m" => [0, "\xd7R"], "n" => [0, "\xd7S"], "o" => [0, "\xd7T"], "p" => [0, "\xd7U"], "q" => [0, "\xd7V"], "r" => [0, "\xd7W"], "s" => [0, "\xd7Y"], "t" => [0, "\xd7j"], "u" => [0, "\xd7k"], "v" => [0, "\xd7q"], "w" => [0, "\xd7v"], "x" => [0, "\xd7w"], "y" => [0, "\xd7x"], "z" => [0, "\xd7y"], "{" => [0, "\xd7z"], "|" => [82, "\xd7"], "}" => [87, "\xd7"], "~" => [130, "\xd7"], "" => [9, "\xd7"], "\x80" => [94, "\xe10"], "\x81" => [76, "\xe10"], "\x82" => [104, "\xe10"], "\x83" => [16, "\xe10"], "\x84" => [94, "\xe11"], "\x85" => [76, "\xe11"], "\x86" => [104, "\xe11"], "\x87" => [16, "\xe11"], "\x88" => [94, "\xe12"], "\x89" => [76, "\xe12"], "\x8a" => [104, "\xe12"], "\x8b" => [16, "\xe12"], "\x8c" => [94, "\xe1a"], "\x8d" => [76, "\xe1a"], "\x8e" => [104, "\xe1a"], "\x8f" => [16, "\xe1a"], "\x90" => [94, "\xe1c"], "\x91" => [76, "\xe1c"], "\x92" => [104, "\xe1c"], "\x93" => [16, "\xe1c"], "\x94" => [94, "\xe1e"], "\x95" => [76, "\xe1e"], "\x96" => [104, "\xe1e"], "\x97" => [16, "\xe1e"], "\x98" => [94, "\xe1i"], "\x99" => [76, "\xe1i"], "\x9a" => [104, "\xe1i"], "\x9b" => [16, "\xe1i"], "\x9c" => [94, "\xe1o"], "\x9d" => [76, "\xe1o"], "\x9e" => [104, "\xe1o"], "\x9f" => [16, "\xe1o"], "\xa0" => [94, "\xe1s"], "\xa1" => [76, "\xe1s"], "\xa2" => [104, "\xe1s"], "\xa3" => [16, "\xe1s"], "\xa4" => [94, "\xe1t"], "\xa5" => [76, "\xe1t"], "\xa6" => [104, "\xe1t"], "\xa7" => [16, "\xe1t"], "\xa8" => [77, "\xe1 "], "\xa9" => [18, "\xe1 "], "\xaa" => [77, "\xe1%"], "\xab" => [18, "\xe1%"], "\xac" => [77, "\xe1-"], "\xad" => [18, "\xe1-"], "\xae" => [77, "\xe1."], "\xaf" => [18, "\xe1."], "\xb0" => [77, "\xe1/"], "\xb1" => [18, "\xe1/"], "\xb2" => [77, "\xe13"], "\xb3" => [18, "\xe13"], "\xb4" => [77, "\xe14"], "\xb5" => [18, "\xe14"], "\xb6" => [77, "\xe15"], "\xb7" => [18, "\xe15"], "\xb8" => [77, "\xe16"], "\xb9" => [18, "\xe16"], "\xba" => [77, "\xe17"], "\xbb" => [18, "\xe17"], "\xbc" => [77, "\xe18"], "\xbd" => [18, "\xe18"], "\xbe" => [77, "\xe19"], "\xbf" => [18, "\xe19"], "\xc0" => [77, "\xe1="], "\xc1" => [18, "\xe1="], "\xc2" => [77, "\xe1A"], "\xc3" => [18, "\xe1A"], "\xc4" => [77, "\xe1_"], "\xc5" => [18, "\xe1_"], "\xc6" => [77, "\xe1b"], "\xc7" => [18, "\xe1b"], "\xc8" => [77, "\xe1d"], "\xc9" => [18, "\xe1d"], "\xca" => [77, "\xe1f"], "\xcb" => [18, "\xe1f"], "\xcc" => [77, "\xe1g"], "\xcd" => [18, "\xe1g"], "\xce" => [77, "\xe1h"], "\xcf" => [18, "\xe1h"], "\xd0" => [77, "\xe1l"], "\xd1" => [18, "\xe1l"], "\xd2" => [77, "\xe1m"], "\xd3" => [18, "\xe1m"], "\xd4" => [77, "\xe1n"], "\xd5" => [18, "\xe1n"], "\xd6" => [77, "\xe1p"], "\xd7" => [18, "\xe1p"], "\xd8" => [77, "\xe1r"], "\xd9" => [18, "\xe1r"], "\xda" => [77, "\xe1u"], "\xdb" => [18, "\xe1u"], "\xdc" => [0, "\xe1:"], "\xdd" => [0, "\xe1B"], "\xde" => [0, "\xe1C"], "\xdf" => [0, "\xe1D"], "\xe0" => [0, "\xe1E"], "\xe1" => [0, "\xe1F"], "\xe2" => [0, "\xe1G"], "\xe3" => [0, "\xe1H"], "\xe4" => [0, "\xe1I"], "\xe5" => [0, "\xe1J"], "\xe6" => [0, "\xe1K"], "\xe7" => [0, "\xe1L"], "\xe8" => [0, "\xe1M"], "\xe9" => [0, "\xe1N"], "\xea" => [0, "\xe1O"], "\xeb" => [0, "\xe1P"], "\xec" => [0, "\xe1Q"], "\xed" => [0, "\xe1R"], "\xee" => [0, "\xe1S"], "\xef" => [0, "\xe1T"], "\xf0" => [0, "\xe1U"], "\xf1" => [0, "\xe1V"], "\xf2" => [0, "\xe1W"], "\xf3" => [0, "\xe1Y"], "\xf4" => [0, "\xe1j"], "\xf5" => [0, "\xe1k"], "\xf6" => [0, "\xe1q"], "\xf7" => [0, "\xe1v"], "\xf8" => [0, "\xe1w"], "\xf9" => [0, "\xe1x"], "\xfa" => [0, "\xe1y"], "\xfb" => [0, "\xe1z"], "\xfc" => [82, "\xe1"], "\xfd" => [87, "\xe1"], "\xfe" => [130, "\xe1"], "\xff" => [9, "\xe1"]], ["\x00" => [94, "\xd80"], "\x01" => [76, "\xd80"], "\x02" => [104, "\xd80"], "\x03" => [16, "\xd80"], "\x04" => [94, "\xd81"], "\x05" => [76, "\xd81"], "\x06" => [104, "\xd81"], "\x07" => [16, "\xd81"], "\x08" => [94, "\xd82"], "\t" => [76, "\xd82"], "\n" => [104, "\xd82"], "\v" => [16, "\xd82"], "\f" => [94, "\xd8a"], "\r" => [76, "\xd8a"], "\x0e" => [104, "\xd8a"], "\x0f" => [16, "\xd8a"], "\x10" => [94, "\xd8c"], "\x11" => [76, "\xd8c"], "\x12" => [104, "\xd8c"], "\x13" => [16, "\xd8c"], "\x14" => [94, "\xd8e"], "\x15" => [76, "\xd8e"], "\x16" => [104, "\xd8e"], "\x17" => [16, "\xd8e"], "\x18" => [94, "\xd8i"], "\x19" => [76, "\xd8i"], "\x1a" => [104, "\xd8i"], "\x1b" => [16, "\xd8i"], "\x1c" => [94, "\xd8o"], "\x1d" => [76, "\xd8o"], "\x1e" => [104, "\xd8o"], "\x1f" => [16, "\xd8o"], " " => [94, "\xd8s"], "!" => [76, "\xd8s"], "\"" => [104, "\xd8s"], "#" => [16, "\xd8s"], "\$" => [94, "\xd8t"], "%" => [76, "\xd8t"], "&" => [104, "\xd8t"], "'" => [16, "\xd8t"], "(" => [77, "\xd8 "], ")" => [18, "\xd8 "], "*" => [77, "\xd8%"], "+" => [18, "\xd8%"], "," => [77, "\xd8-"], "-" => [18, "\xd8-"], "." => [77, "\xd8."], "/" => [18, "\xd8."], [77, "\xd8/"], [18, "\xd8/"], [77, "\xd83"], [18, "\xd83"], [77, "\xd84"], [18, "\xd84"], [77, "\xd85"], [18, "\xd85"], [77, "\xd86"], [18, "\xd86"], ":" => [77, "\xd87"], ";" => [18, "\xd87"], "<" => [77, "\xd88"], "=" => [18, "\xd88"], ">" => [77, "\xd89"], "?" => [18, "\xd89"], "@" => [77, "\xd8="], "A" => [18, "\xd8="], "B" => [77, "\xd8A"], "C" => [18, "\xd8A"], "D" => [77, "\xd8_"], "E" => [18, "\xd8_"], "F" => [77, "\xd8b"], "G" => [18, "\xd8b"], "H" => [77, "\xd8d"], "I" => [18, "\xd8d"], "J" => [77, "\xd8f"], "K" => [18, "\xd8f"], "L" => [77, "\xd8g"], "M" => [18, "\xd8g"], "N" => [77, "\xd8h"], "O" => [18, "\xd8h"], "P" => [77, "\xd8l"], "Q" => [18, "\xd8l"], "R" => [77, "\xd8m"], "S" => [18, "\xd8m"], "T" => [77, "\xd8n"], "U" => [18, "\xd8n"], "V" => [77, "\xd8p"], "W" => [18, "\xd8p"], "X" => [77, "\xd8r"], "Y" => [18, "\xd8r"], "Z" => [77, "\xd8u"], "[" => [18, "\xd8u"], "\\" => [0, "\xd8:"], "]" => [0, "\xd8B"], "^" => [0, "\xd8C"], "_" => [0, "\xd8D"], "`" => [0, "\xd8E"], "a" => [0, "\xd8F"], "b" => [0, "\xd8G"], "c" => [0, "\xd8H"], "d" => [0, "\xd8I"], "e" => [0, "\xd8J"], "f" => [0, "\xd8K"], "g" => [0, "\xd8L"], "h" => [0, "\xd8M"], "i" => [0, "\xd8N"], "j" => [0, "\xd8O"], "k" => [0, "\xd8P"], "l" => [0, "\xd8Q"], "m" => [0, "\xd8R"], "n" => [0, "\xd8S"], "o" => [0, "\xd8T"], "p" => [0, "\xd8U"], "q" => [0, "\xd8V"], "r" => [0, "\xd8W"], "s" => [0, "\xd8Y"], "t" => [0, "\xd8j"], "u" => [0, "\xd8k"], "v" => [0, "\xd8q"], "w" => [0, "\xd8v"], "x" => [0, "\xd8w"], "y" => [0, "\xd8x"], "z" => [0, "\xd8y"], "{" => [0, "\xd8z"], "|" => [82, "\xd8"], "}" => [87, "\xd8"], "~" => [130, "\xd8"], "" => [9, "\xd8"], "\x80" => [94, "\xd90"], "\x81" => [76, "\xd90"], "\x82" => [104, "\xd90"], "\x83" => [16, "\xd90"], "\x84" => [94, "\xd91"], "\x85" => [76, "\xd91"], "\x86" => [104, "\xd91"], "\x87" => [16, "\xd91"], "\x88" => [94, "\xd92"], "\x89" => [76, "\xd92"], "\x8a" => [104, "\xd92"], "\x8b" => [16, "\xd92"], "\x8c" => [94, "\xd9a"], "\x8d" => [76, "\xd9a"], "\x8e" => [104, "\xd9a"], "\x8f" => [16, "\xd9a"], "\x90" => [94, "\xd9c"], "\x91" => [76, "\xd9c"], "\x92" => [104, "\xd9c"], "\x93" => [16, "\xd9c"], "\x94" => [94, "\xd9e"], "\x95" => [76, "\xd9e"], "\x96" => [104, "\xd9e"], "\x97" => [16, "\xd9e"], "\x98" => [94, "\xd9i"], "\x99" => [76, "\xd9i"], "\x9a" => [104, "\xd9i"], "\x9b" => [16, "\xd9i"], "\x9c" => [94, "\xd9o"], "\x9d" => [76, "\xd9o"], "\x9e" => [104, "\xd9o"], "\x9f" => [16, "\xd9o"], "\xa0" => [94, "\xd9s"], "\xa1" => [76, "\xd9s"], "\xa2" => [104, "\xd9s"], "\xa3" => [16, "\xd9s"], "\xa4" => [94, "\xd9t"], "\xa5" => [76, "\xd9t"], "\xa6" => [104, "\xd9t"], "\xa7" => [16, "\xd9t"], "\xa8" => [77, "\xd9 "], "\xa9" => [18, "\xd9 "], "\xaa" => [77, "\xd9%"], "\xab" => [18, "\xd9%"], "\xac" => [77, "\xd9-"], "\xad" => [18, "\xd9-"], "\xae" => [77, "\xd9."], "\xaf" => [18, "\xd9."], "\xb0" => [77, "\xd9/"], "\xb1" => [18, "\xd9/"], "\xb2" => [77, "\xd93"], "\xb3" => [18, "\xd93"], "\xb4" => [77, "\xd94"], "\xb5" => [18, "\xd94"], "\xb6" => [77, "\xd95"], "\xb7" => [18, "\xd95"], "\xb8" => [77, "\xd96"], "\xb9" => [18, "\xd96"], "\xba" => [77, "\xd97"], "\xbb" => [18, "\xd97"], "\xbc" => [77, "\xd98"], "\xbd" => [18, "\xd98"], "\xbe" => [77, "\xd99"], "\xbf" => [18, "\xd99"], "\xc0" => [77, "\xd9="], "\xc1" => [18, "\xd9="], "\xc2" => [77, "\xd9A"], "\xc3" => [18, "\xd9A"], "\xc4" => [77, "\xd9_"], "\xc5" => [18, "\xd9_"], "\xc6" => [77, "\xd9b"], "\xc7" => [18, "\xd9b"], "\xc8" => [77, "\xd9d"], "\xc9" => [18, "\xd9d"], "\xca" => [77, "\xd9f"], "\xcb" => [18, "\xd9f"], "\xcc" => [77, "\xd9g"], "\xcd" => [18, "\xd9g"], "\xce" => [77, "\xd9h"], "\xcf" => [18, "\xd9h"], "\xd0" => [77, "\xd9l"], "\xd1" => [18, "\xd9l"], "\xd2" => [77, "\xd9m"], "\xd3" => [18, "\xd9m"], "\xd4" => [77, "\xd9n"], "\xd5" => [18, "\xd9n"], "\xd6" => [77, "\xd9p"], "\xd7" => [18, "\xd9p"], "\xd8" => [77, "\xd9r"], "\xd9" => [18, "\xd9r"], "\xda" => [77, "\xd9u"], "\xdb" => [18, "\xd9u"], "\xdc" => [0, "\xd9:"], "\xdd" => [0, "\xd9B"], "\xde" => [0, "\xd9C"], "\xdf" => [0, "\xd9D"], "\xe0" => [0, "\xd9E"], "\xe1" => [0, "\xd9F"], "\xe2" => [0, "\xd9G"], "\xe3" => [0, "\xd9H"], "\xe4" => [0, "\xd9I"], "\xe5" => [0, "\xd9J"], "\xe6" => [0, "\xd9K"], "\xe7" => [0, "\xd9L"], "\xe8" => [0, "\xd9M"], "\xe9" => [0, "\xd9N"], "\xea" => [0, "\xd9O"], "\xeb" => [0, "\xd9P"], "\xec" => [0, "\xd9Q"], "\xed" => [0, "\xd9R"], "\xee" => [0, "\xd9S"], "\xef" => [0, "\xd9T"], "\xf0" => [0, "\xd9U"], "\xf1" => [0, "\xd9V"], "\xf2" => [0, "\xd9W"], "\xf3" => [0, "\xd9Y"], "\xf4" => [0, "\xd9j"], "\xf5" => [0, "\xd9k"], "\xf6" => [0, "\xd9q"], "\xf7" => [0, "\xd9v"], "\xf8" => [0, "\xd9w"], "\xf9" => [0, "\xd9x"], "\xfa" => [0, "\xd9y"], "\xfb" => [0, "\xd9z"], "\xfc" => [82, "\xd9"], "\xfd" => [87, "\xd9"], "\xfe" => [130, "\xd9"], "\xff" => [9, "\xd9"]], ["\x00" => [77, "\xd80"], "\x01" => [18, "\xd80"], "\x02" => [77, "\xd81"], "\x03" => [18, "\xd81"], "\x04" => [77, "\xd82"], "\x05" => [18, "\xd82"], "\x06" => [77, "\xd8a"], "\x07" => [18, "\xd8a"], "\x08" => [77, "\xd8c"], "\t" => [18, "\xd8c"], "\n" => [77, "\xd8e"], "\v" => [18, "\xd8e"], "\f" => [77, "\xd8i"], "\r" => [18, "\xd8i"], "\x0e" => [77, "\xd8o"], "\x0f" => [18, "\xd8o"], "\x10" => [77, "\xd8s"], "\x11" => [18, "\xd8s"], "\x12" => [77, "\xd8t"], "\x13" => [18, "\xd8t"], "\x14" => [0, "\xd8 "], "\x15" => [0, "\xd8%"], "\x16" => [0, "\xd8-"], "\x17" => [0, "\xd8."], "\x18" => [0, "\xd8/"], "\x19" => [0, "\xd83"], "\x1a" => [0, "\xd84"], "\x1b" => [0, "\xd85"], "\x1c" => [0, "\xd86"], "\x1d" => [0, "\xd87"], "\x1e" => [0, "\xd88"], "\x1f" => [0, "\xd89"], " " => [0, "\xd8="], "!" => [0, "\xd8A"], "\"" => [0, "\xd8_"], "#" => [0, "\xd8b"], "\$" => [0, "\xd8d"], "%" => [0, "\xd8f"], "&" => [0, "\xd8g"], "'" => [0, "\xd8h"], "(" => [0, "\xd8l"], ")" => [0, "\xd8m"], "*" => [0, "\xd8n"], "+" => [0, "\xd8p"], "," => [0, "\xd8r"], "-" => [0, "\xd8u"], "." => [100, "\xd8"], "/" => [110, "\xd8"], [111, "\xd8"], [115, "\xd8"], [116, "\xd8"], [118, "\xd8"], [119, "\xd8"], [122, "\xd8"], [123, "\xd8"], [125, "\xd8"], [126, "\xd8"], [129, "\xd8"], ":" => [143, "\xd8"], ";" => [148, "\xd8"], "<" => [151, "\xd8"], "=" => [153, "\xd8"], ">" => [83, "\xd8"], "?" => [10, "\xd8"], "@" => [77, "\xd90"], "A" => [18, "\xd90"], "B" => [77, "\xd91"], "C" => [18, "\xd91"], "D" => [77, "\xd92"], "E" => [18, "\xd92"], "F" => [77, "\xd9a"], "G" => [18, "\xd9a"], "H" => [77, "\xd9c"], "I" => [18, "\xd9c"], "J" => [77, "\xd9e"], "K" => [18, "\xd9e"], "L" => [77, "\xd9i"], "M" => [18, "\xd9i"], "N" => [77, "\xd9o"], "O" => [18, "\xd9o"], "P" => [77, "\xd9s"], "Q" => [18, "\xd9s"], "R" => [77, "\xd9t"], "S" => [18, "\xd9t"], "T" => [0, "\xd9 "], "U" => [0, "\xd9%"], "V" => [0, "\xd9-"], "W" => [0, "\xd9."], "X" => [0, "\xd9/"], "Y" => [0, "\xd93"], "Z" => [0, "\xd94"], "[" => [0, "\xd95"], "\\" => [0, "\xd96"], "]" => [0, "\xd97"], "^" => [0, "\xd98"], "_" => [0, "\xd99"], "`" => [0, "\xd9="], "a" => [0, "\xd9A"], "b" => [0, "\xd9_"], "c" => [0, "\xd9b"], "d" => [0, "\xd9d"], "e" => [0, "\xd9f"], "f" => [0, "\xd9g"], "g" => [0, "\xd9h"], "h" => [0, "\xd9l"], "i" => [0, "\xd9m"], "j" => [0, "\xd9n"], "k" => [0, "\xd9p"], "l" => [0, "\xd9r"], "m" => [0, "\xd9u"], "n" => [100, "\xd9"], "o" => [110, "\xd9"], "p" => [111, "\xd9"], "q" => [115, "\xd9"], "r" => [116, "\xd9"], "s" => [118, "\xd9"], "t" => [119, "\xd9"], "u" => [122, "\xd9"], "v" => [123, "\xd9"], "w" => [125, "\xd9"], "x" => [126, "\xd9"], "y" => [129, "\xd9"], "z" => [143, "\xd9"], "{" => [148, "\xd9"], "|" => [151, "\xd9"], "}" => [153, "\xd9"], "~" => [83, "\xd9"], "" => [10, "\xd9"], "\x80" => [77, "\xe30"], "\x81" => [18, "\xe30"], "\x82" => [77, "\xe31"], "\x83" => [18, "\xe31"], "\x84" => [77, "\xe32"], "\x85" => [18, "\xe32"], "\x86" => [77, "\xe3a"], "\x87" => [18, "\xe3a"], "\x88" => [77, "\xe3c"], "\x89" => [18, "\xe3c"], "\x8a" => [77, "\xe3e"], "\x8b" => [18, "\xe3e"], "\x8c" => [77, "\xe3i"], "\x8d" => [18, "\xe3i"], "\x8e" => [77, "\xe3o"], "\x8f" => [18, "\xe3o"], "\x90" => [77, "\xe3s"], "\x91" => [18, "\xe3s"], "\x92" => [77, "\xe3t"], "\x93" => [18, "\xe3t"], "\x94" => [0, "\xe3 "], "\x95" => [0, "\xe3%"], "\x96" => [0, "\xe3-"], "\x97" => [0, "\xe3."], "\x98" => [0, "\xe3/"], "\x99" => [0, "\xe33"], "\x9a" => [0, "\xe34"], "\x9b" => [0, "\xe35"], "\x9c" => [0, "\xe36"], "\x9d" => [0, "\xe37"], "\x9e" => [0, "\xe38"], "\x9f" => [0, "\xe39"], "\xa0" => [0, "\xe3="], "\xa1" => [0, "\xe3A"], "\xa2" => [0, "\xe3_"], "\xa3" => [0, "\xe3b"], "\xa4" => [0, "\xe3d"], "\xa5" => [0, "\xe3f"], "\xa6" => [0, "\xe3g"], "\xa7" => [0, "\xe3h"], "\xa8" => [0, "\xe3l"], "\xa9" => [0, "\xe3m"], "\xaa" => [0, "\xe3n"], "\xab" => [0, "\xe3p"], "\xac" => [0, "\xe3r"], "\xad" => [0, "\xe3u"], "\xae" => [100, "\xe3"], "\xaf" => [110, "\xe3"], "\xb0" => [111, "\xe3"], "\xb1" => [115, "\xe3"], "\xb2" => [116, "\xe3"], "\xb3" => [118, "\xe3"], "\xb4" => [119, "\xe3"], "\xb5" => [122, "\xe3"], "\xb6" => [123, "\xe3"], "\xb7" => [125, "\xe3"], "\xb8" => [126, "\xe3"], "\xb9" => [129, "\xe3"], "\xba" => [143, "\xe3"], "\xbb" => [148, "\xe3"], "\xbc" => [151, "\xe3"], "\xbd" => [153, "\xe3"], "\xbe" => [83, "\xe3"], "\xbf" => [10, "\xe3"], "\xc0" => [77, "\xe50"], "\xc1" => [18, "\xe50"], "\xc2" => [77, "\xe51"], "\xc3" => [18, "\xe51"], "\xc4" => [77, "\xe52"], "\xc5" => [18, "\xe52"], "\xc6" => [77, "\xe5a"], "\xc7" => [18, "\xe5a"], "\xc8" => [77, "\xe5c"], "\xc9" => [18, "\xe5c"], "\xca" => [77, "\xe5e"], "\xcb" => [18, "\xe5e"], "\xcc" => [77, "\xe5i"], "\xcd" => [18, "\xe5i"], "\xce" => [77, "\xe5o"], "\xcf" => [18, "\xe5o"], "\xd0" => [77, "\xe5s"], "\xd1" => [18, "\xe5s"], "\xd2" => [77, "\xe5t"], "\xd3" => [18, "\xe5t"], "\xd4" => [0, "\xe5 "], "\xd5" => [0, "\xe5%"], "\xd6" => [0, "\xe5-"], "\xd7" => [0, "\xe5."], "\xd8" => [0, "\xe5/"], "\xd9" => [0, "\xe53"], "\xda" => [0, "\xe54"], "\xdb" => [0, "\xe55"], "\xdc" => [0, "\xe56"], "\xdd" => [0, "\xe57"], "\xde" => [0, "\xe58"], "\xdf" => [0, "\xe59"], "\xe0" => [0, "\xe5="], "\xe1" => [0, "\xe5A"], "\xe2" => [0, "\xe5_"], "\xe3" => [0, "\xe5b"], "\xe4" => [0, "\xe5d"], "\xe5" => [0, "\xe5f"], "\xe6" => [0, "\xe5g"], "\xe7" => [0, "\xe5h"], "\xe8" => [0, "\xe5l"], "\xe9" => [0, "\xe5m"], "\xea" => [0, "\xe5n"], "\xeb" => [0, "\xe5p"], "\xec" => [0, "\xe5r"], "\xed" => [0, "\xe5u"], "\xee" => [100, "\xe5"], "\xef" => [110, "\xe5"], "\xf0" => [111, "\xe5"], "\xf1" => [115, "\xe5"], "\xf2" => [116, "\xe5"], "\xf3" => [118, "\xe5"], "\xf4" => [119, "\xe5"], "\xf5" => [122, "\xe5"], "\xf6" => [123, "\xe5"], "\xf7" => [125, "\xe5"], "\xf8" => [126, "\xe5"], "\xf9" => [129, "\xe5"], "\xfa" => [143, "\xe5"], "\xfb" => [148, "\xe5"], "\xfc" => [151, "\xe5"], "\xfd" => [153, "\xe5"], "\xfe" => [83, "\xe5"], "\xff" => [10, "\xe5"]], ["\x00" => [77, "\xda0"], "\x01" => [18, "\xda0"], "\x02" => [77, "\xda1"], "\x03" => [18, "\xda1"], "\x04" => [77, "\xda2"], "\x05" => [18, "\xda2"], "\x06" => [77, "\xdaa"], "\x07" => [18, "\xdaa"], "\x08" => [77, "\xdac"], "\t" => [18, "\xdac"], "\n" => [77, "\xdae"], "\v" => [18, "\xdae"], "\f" => [77, "\xdai"], "\r" => [18, "\xdai"], "\x0e" => [77, "\xdao"], "\x0f" => [18, "\xdao"], "\x10" => [77, "\xdas"], "\x11" => [18, "\xdas"], "\x12" => [77, "\xdat"], "\x13" => [18, "\xdat"], "\x14" => [0, "\xda "], "\x15" => [0, "\xda%"], "\x16" => [0, "\xda-"], "\x17" => [0, "\xda."], "\x18" => [0, "\xda/"], "\x19" => [0, "\xda3"], "\x1a" => [0, "\xda4"], "\x1b" => [0, "\xda5"], "\x1c" => [0, "\xda6"], "\x1d" => [0, "\xda7"], "\x1e" => [0, "\xda8"], "\x1f" => [0, "\xda9"], " " => [0, "\xda="], "!" => [0, "\xdaA"], "\"" => [0, "\xda_"], "#" => [0, "\xdab"], "\$" => [0, "\xdad"], "%" => [0, "\xdaf"], "&" => [0, "\xdag"], "'" => [0, "\xdah"], "(" => [0, "\xdal"], ")" => [0, "\xdam"], "*" => [0, "\xdan"], "+" => [0, "\xdap"], "," => [0, "\xdar"], "-" => [0, "\xdau"], "." => [100, "\xda"], "/" => [110, "\xda"], [111, "\xda"], [115, "\xda"], [116, "\xda"], [118, "\xda"], [119, "\xda"], [122, "\xda"], [123, "\xda"], [125, "\xda"], [126, "\xda"], [129, "\xda"], ":" => [143, "\xda"], ";" => [148, "\xda"], "<" => [151, "\xda"], "=" => [153, "\xda"], ">" => [83, "\xda"], "?" => [10, "\xda"], "@" => [77, "\xdb0"], "A" => [18, "\xdb0"], "B" => [77, "\xdb1"], "C" => [18, "\xdb1"], "D" => [77, "\xdb2"], "E" => [18, "\xdb2"], "F" => [77, "\xdba"], "G" => [18, "\xdba"], "H" => [77, "\xdbc"], "I" => [18, "\xdbc"], "J" => [77, "\xdbe"], "K" => [18, "\xdbe"], "L" => [77, "\xdbi"], "M" => [18, "\xdbi"], "N" => [77, "\xdbo"], "O" => [18, "\xdbo"], "P" => [77, "\xdbs"], "Q" => [18, "\xdbs"], "R" => [77, "\xdbt"], "S" => [18, "\xdbt"], "T" => [0, "\xdb "], "U" => [0, "\xdb%"], "V" => [0, "\xdb-"], "W" => [0, "\xdb."], "X" => [0, "\xdb/"], "Y" => [0, "\xdb3"], "Z" => [0, "\xdb4"], "[" => [0, "\xdb5"], "\\" => [0, "\xdb6"], "]" => [0, "\xdb7"], "^" => [0, "\xdb8"], "_" => [0, "\xdb9"], "`" => [0, "\xdb="], "a" => [0, "\xdbA"], "b" => [0, "\xdb_"], "c" => [0, "\xdbb"], "d" => [0, "\xdbd"], "e" => [0, "\xdbf"], "f" => [0, "\xdbg"], "g" => [0, "\xdbh"], "h" => [0, "\xdbl"], "i" => [0, "\xdbm"], "j" => [0, "\xdbn"], "k" => [0, "\xdbp"], "l" => [0, "\xdbr"], "m" => [0, "\xdbu"], "n" => [100, "\xdb"], "o" => [110, "\xdb"], "p" => [111, "\xdb"], "q" => [115, "\xdb"], "r" => [116, "\xdb"], "s" => [118, "\xdb"], "t" => [119, "\xdb"], "u" => [122, "\xdb"], "v" => [123, "\xdb"], "w" => [125, "\xdb"], "x" => [126, "\xdb"], "y" => [129, "\xdb"], "z" => [143, "\xdb"], "{" => [148, "\xdb"], "|" => [151, "\xdb"], "}" => [153, "\xdb"], "~" => [83, "\xdb"], "" => [10, "\xdb"], "\x80" => [77, "\xee0"], "\x81" => [18, "\xee0"], "\x82" => [77, "\xee1"], "\x83" => [18, "\xee1"], "\x84" => [77, "\xee2"], "\x85" => [18, "\xee2"], "\x86" => [77, "\xeea"], "\x87" => [18, "\xeea"], "\x88" => [77, "\xeec"], "\x89" => [18, "\xeec"], "\x8a" => [77, "\xeee"], "\x8b" => [18, "\xeee"], "\x8c" => [77, "\xeei"], "\x8d" => [18, "\xeei"], "\x8e" => [77, "\xeeo"], "\x8f" => [18, "\xeeo"], "\x90" => [77, "\xees"], "\x91" => [18, "\xees"], "\x92" => [77, "\xeet"], "\x93" => [18, "\xeet"], "\x94" => [0, "\xee "], "\x95" => [0, "\xee%"], "\x96" => [0, "\xee-"], "\x97" => [0, "\xee."], "\x98" => [0, "\xee/"], "\x99" => [0, "\xee3"], "\x9a" => [0, "\xee4"], "\x9b" => [0, "\xee5"], "\x9c" => [0, "\xee6"], "\x9d" => [0, "\xee7"], "\x9e" => [0, "\xee8"], "\x9f" => [0, "\xee9"], "\xa0" => [0, "\xee="], "\xa1" => [0, "\xeeA"], "\xa2" => [0, "\xee_"], "\xa3" => [0, "\xeeb"], "\xa4" => [0, "\xeed"], "\xa5" => [0, "\xeef"], "\xa6" => [0, "\xeeg"], "\xa7" => [0, "\xeeh"], "\xa8" => [0, "\xeel"], "\xa9" => [0, "\xeem"], "\xaa" => [0, "\xeen"], "\xab" => [0, "\xeep"], "\xac" => [0, "\xeer"], "\xad" => [0, "\xeeu"], "\xae" => [100, "\xee"], "\xaf" => [110, "\xee"], "\xb0" => [111, "\xee"], "\xb1" => [115, "\xee"], "\xb2" => [116, "\xee"], "\xb3" => [118, "\xee"], "\xb4" => [119, "\xee"], "\xb5" => [122, "\xee"], "\xb6" => [123, "\xee"], "\xb7" => [125, "\xee"], "\xb8" => [126, "\xee"], "\xb9" => [129, "\xee"], "\xba" => [143, "\xee"], "\xbb" => [148, "\xee"], "\xbc" => [151, "\xee"], "\xbd" => [153, "\xee"], "\xbe" => [83, "\xee"], "\xbf" => [10, "\xee"], "\xc0" => [77, "\xf00"], "\xc1" => [18, "\xf00"], "\xc2" => [77, "\xf01"], "\xc3" => [18, "\xf01"], "\xc4" => [77, "\xf02"], "\xc5" => [18, "\xf02"], "\xc6" => [77, "\xf0a"], "\xc7" => [18, "\xf0a"], "\xc8" => [77, "\xf0c"], "\xc9" => [18, "\xf0c"], "\xca" => [77, "\xf0e"], "\xcb" => [18, "\xf0e"], "\xcc" => [77, "\xf0i"], "\xcd" => [18, "\xf0i"], "\xce" => [77, "\xf0o"], "\xcf" => [18, "\xf0o"], "\xd0" => [77, "\xf0s"], "\xd1" => [18, "\xf0s"], "\xd2" => [77, "\xf0t"], "\xd3" => [18, "\xf0t"], "\xd4" => [0, "\xf0 "], "\xd5" => [0, "\xf0%"], "\xd6" => [0, "\xf0-"], "\xd7" => [0, "\xf0."], "\xd8" => [0, "\xf0/"], "\xd9" => [0, "\xf03"], "\xda" => [0, "\xf04"], "\xdb" => [0, "\xf05"], "\xdc" => [0, "\xf06"], "\xdd" => [0, "\xf07"], "\xde" => [0, "\xf08"], "\xdf" => [0, "\xf09"], "\xe0" => [0, "\xf0="], "\xe1" => [0, "\xf0A"], "\xe2" => [0, "\xf0_"], "\xe3" => [0, "\xf0b"], "\xe4" => [0, "\xf0d"], "\xe5" => [0, "\xf0f"], "\xe6" => [0, "\xf0g"], "\xe7" => [0, "\xf0h"], "\xe8" => [0, "\xf0l"], "\xe9" => [0, "\xf0m"], "\xea" => [0, "\xf0n"], "\xeb" => [0, "\xf0p"], "\xec" => [0, "\xf0r"], "\xed" => [0, "\xf0u"], "\xee" => [100, "\xf0"], "\xef" => [110, "\xf0"], "\xf0" => [111, "\xf0"], "\xf1" => [115, "\xf0"], "\xf2" => [116, "\xf0"], "\xf3" => [118, "\xf0"], "\xf4" => [119, "\xf0"], "\xf5" => [122, "\xf0"], "\xf6" => [123, "\xf0"], "\xf7" => [125, "\xf0"], "\xf8" => [126, "\xf0"], "\xf9" => [129, "\xf0"], "\xfa" => [143, "\xf0"], "\xfb" => [148, "\xf0"], "\xfc" => [151, "\xf0"], "\xfd" => [153, "\xf0"], "\xfe" => [83, "\xf0"], "\xff" => [10, "\xf0"]], ["\x00" => [94, "\xda0"], "\x01" => [76, "\xda0"], "\x02" => [104, "\xda0"], "\x03" => [16, "\xda0"], "\x04" => [94, "\xda1"], "\x05" => [76, "\xda1"], "\x06" => [104, "\xda1"], "\x07" => [16, "\xda1"], "\x08" => [94, "\xda2"], "\t" => [76, "\xda2"], "\n" => [104, "\xda2"], "\v" => [16, "\xda2"], "\f" => [94, "\xdaa"], "\r" => [76, "\xdaa"], "\x0e" => [104, "\xdaa"], "\x0f" => [16, "\xdaa"], "\x10" => [94, "\xdac"], "\x11" => [76, "\xdac"], "\x12" => [104, "\xdac"], "\x13" => [16, "\xdac"], "\x14" => [94, "\xdae"], "\x15" => [76, "\xdae"], "\x16" => [104, "\xdae"], "\x17" => [16, "\xdae"], "\x18" => [94, "\xdai"], "\x19" => [76, "\xdai"], "\x1a" => [104, "\xdai"], "\x1b" => [16, "\xdai"], "\x1c" => [94, "\xdao"], "\x1d" => [76, "\xdao"], "\x1e" => [104, "\xdao"], "\x1f" => [16, "\xdao"], " " => [94, "\xdas"], "!" => [76, "\xdas"], "\"" => [104, "\xdas"], "#" => [16, "\xdas"], "\$" => [94, "\xdat"], "%" => [76, "\xdat"], "&" => [104, "\xdat"], "'" => [16, "\xdat"], "(" => [77, "\xda "], ")" => [18, "\xda "], "*" => [77, "\xda%"], "+" => [18, "\xda%"], "," => [77, "\xda-"], "-" => [18, "\xda-"], "." => [77, "\xda."], "/" => [18, "\xda."], [77, "\xda/"], [18, "\xda/"], [77, "\xda3"], [18, "\xda3"], [77, "\xda4"], [18, "\xda4"], [77, "\xda5"], [18, "\xda5"], [77, "\xda6"], [18, "\xda6"], ":" => [77, "\xda7"], ";" => [18, "\xda7"], "<" => [77, "\xda8"], "=" => [18, "\xda8"], ">" => [77, "\xda9"], "?" => [18, "\xda9"], "@" => [77, "\xda="], "A" => [18, "\xda="], "B" => [77, "\xdaA"], "C" => [18, "\xdaA"], "D" => [77, "\xda_"], "E" => [18, "\xda_"], "F" => [77, "\xdab"], "G" => [18, "\xdab"], "H" => [77, "\xdad"], "I" => [18, "\xdad"], "J" => [77, "\xdaf"], "K" => [18, "\xdaf"], "L" => [77, "\xdag"], "M" => [18, "\xdag"], "N" => [77, "\xdah"], "O" => [18, "\xdah"], "P" => [77, "\xdal"], "Q" => [18, "\xdal"], "R" => [77, "\xdam"], "S" => [18, "\xdam"], "T" => [77, "\xdan"], "U" => [18, "\xdan"], "V" => [77, "\xdap"], "W" => [18, "\xdap"], "X" => [77, "\xdar"], "Y" => [18, "\xdar"], "Z" => [77, "\xdau"], "[" => [18, "\xdau"], "\\" => [0, "\xda:"], "]" => [0, "\xdaB"], "^" => [0, "\xdaC"], "_" => [0, "\xdaD"], "`" => [0, "\xdaE"], "a" => [0, "\xdaF"], "b" => [0, "\xdaG"], "c" => [0, "\xdaH"], "d" => [0, "\xdaI"], "e" => [0, "\xdaJ"], "f" => [0, "\xdaK"], "g" => [0, "\xdaL"], "h" => [0, "\xdaM"], "i" => [0, "\xdaN"], "j" => [0, "\xdaO"], "k" => [0, "\xdaP"], "l" => [0, "\xdaQ"], "m" => [0, "\xdaR"], "n" => [0, "\xdaS"], "o" => [0, "\xdaT"], "p" => [0, "\xdaU"], "q" => [0, "\xdaV"], "r" => [0, "\xdaW"], "s" => [0, "\xdaY"], "t" => [0, "\xdaj"], "u" => [0, "\xdak"], "v" => [0, "\xdaq"], "w" => [0, "\xdav"], "x" => [0, "\xdaw"], "y" => [0, "\xdax"], "z" => [0, "\xday"], "{" => [0, "\xdaz"], "|" => [82, "\xda"], "}" => [87, "\xda"], "~" => [130, "\xda"], "" => [9, "\xda"], "\x80" => [94, "\xdb0"], "\x81" => [76, "\xdb0"], "\x82" => [104, "\xdb0"], "\x83" => [16, "\xdb0"], "\x84" => [94, "\xdb1"], "\x85" => [76, "\xdb1"], "\x86" => [104, "\xdb1"], "\x87" => [16, "\xdb1"], "\x88" => [94, "\xdb2"], "\x89" => [76, "\xdb2"], "\x8a" => [104, "\xdb2"], "\x8b" => [16, "\xdb2"], "\x8c" => [94, "\xdba"], "\x8d" => [76, "\xdba"], "\x8e" => [104, "\xdba"], "\x8f" => [16, "\xdba"], "\x90" => [94, "\xdbc"], "\x91" => [76, "\xdbc"], "\x92" => [104, "\xdbc"], "\x93" => [16, "\xdbc"], "\x94" => [94, "\xdbe"], "\x95" => [76, "\xdbe"], "\x96" => [104, "\xdbe"], "\x97" => [16, "\xdbe"], "\x98" => [94, "\xdbi"], "\x99" => [76, "\xdbi"], "\x9a" => [104, "\xdbi"], "\x9b" => [16, "\xdbi"], "\x9c" => [94, "\xdbo"], "\x9d" => [76, "\xdbo"], "\x9e" => [104, "\xdbo"], "\x9f" => [16, "\xdbo"], "\xa0" => [94, "\xdbs"], "\xa1" => [76, "\xdbs"], "\xa2" => [104, "\xdbs"], "\xa3" => [16, "\xdbs"], "\xa4" => [94, "\xdbt"], "\xa5" => [76, "\xdbt"], "\xa6" => [104, "\xdbt"], "\xa7" => [16, "\xdbt"], "\xa8" => [77, "\xdb "], "\xa9" => [18, "\xdb "], "\xaa" => [77, "\xdb%"], "\xab" => [18, "\xdb%"], "\xac" => [77, "\xdb-"], "\xad" => [18, "\xdb-"], "\xae" => [77, "\xdb."], "\xaf" => [18, "\xdb."], "\xb0" => [77, "\xdb/"], "\xb1" => [18, "\xdb/"], "\xb2" => [77, "\xdb3"], "\xb3" => [18, "\xdb3"], "\xb4" => [77, "\xdb4"], "\xb5" => [18, "\xdb4"], "\xb6" => [77, "\xdb5"], "\xb7" => [18, "\xdb5"], "\xb8" => [77, "\xdb6"], "\xb9" => [18, "\xdb6"], "\xba" => [77, "\xdb7"], "\xbb" => [18, "\xdb7"], "\xbc" => [77, "\xdb8"], "\xbd" => [18, "\xdb8"], "\xbe" => [77, "\xdb9"], "\xbf" => [18, "\xdb9"], "\xc0" => [77, "\xdb="], "\xc1" => [18, "\xdb="], "\xc2" => [77, "\xdbA"], "\xc3" => [18, "\xdbA"], "\xc4" => [77, "\xdb_"], "\xc5" => [18, "\xdb_"], "\xc6" => [77, "\xdbb"], "\xc7" => [18, "\xdbb"], "\xc8" => [77, "\xdbd"], "\xc9" => [18, "\xdbd"], "\xca" => [77, "\xdbf"], "\xcb" => [18, "\xdbf"], "\xcc" => [77, "\xdbg"], "\xcd" => [18, "\xdbg"], "\xce" => [77, "\xdbh"], "\xcf" => [18, "\xdbh"], "\xd0" => [77, "\xdbl"], "\xd1" => [18, "\xdbl"], "\xd2" => [77, "\xdbm"], "\xd3" => [18, "\xdbm"], "\xd4" => [77, "\xdbn"], "\xd5" => [18, "\xdbn"], "\xd6" => [77, "\xdbp"], "\xd7" => [18, "\xdbp"], "\xd8" => [77, "\xdbr"], "\xd9" => [18, "\xdbr"], "\xda" => [77, "\xdbu"], "\xdb" => [18, "\xdbu"], "\xdc" => [0, "\xdb:"], "\xdd" => [0, "\xdbB"], "\xde" => [0, "\xdbC"], "\xdf" => [0, "\xdbD"], "\xe0" => [0, "\xdbE"], "\xe1" => [0, "\xdbF"], "\xe2" => [0, "\xdbG"], "\xe3" => [0, "\xdbH"], "\xe4" => [0, "\xdbI"], "\xe5" => [0, "\xdbJ"], "\xe6" => [0, "\xdbK"], "\xe7" => [0, "\xdbL"], "\xe8" => [0, "\xdbM"], "\xe9" => [0, "\xdbN"], "\xea" => [0, "\xdbO"], "\xeb" => [0, "\xdbP"], "\xec" => [0, "\xdbQ"], "\xed" => [0, "\xdbR"], "\xee" => [0, "\xdbS"], "\xef" => [0, "\xdbT"], "\xf0" => [0, "\xdbU"], "\xf1" => [0, "\xdbV"], "\xf2" => [0, "\xdbW"], "\xf3" => [0, "\xdbY"], "\xf4" => [0, "\xdbj"], "\xf5" => [0, "\xdbk"], "\xf6" => [0, "\xdbq"], "\xf7" => [0, "\xdbv"], "\xf8" => [0, "\xdbw"], "\xf9" => [0, "\xdbx"], "\xfa" => [0, "\xdby"], "\xfb" => [0, "\xdbz"], "\xfc" => [82, "\xdb"], "\xfd" => [87, "\xdb"], "\xfe" => [130, "\xdb"], "\xff" => [9, "\xdb"]], ["\x00" => [94, "\xde0"], "\x01" => [76, "\xde0"], "\x02" => [104, "\xde0"], "\x03" => [16, "\xde0"], "\x04" => [94, "\xde1"], "\x05" => [76, "\xde1"], "\x06" => [104, "\xde1"], "\x07" => [16, "\xde1"], "\x08" => [94, "\xde2"], "\t" => [76, "\xde2"], "\n" => [104, "\xde2"], "\v" => [16, "\xde2"], "\f" => [94, "\xdea"], "\r" => [76, "\xdea"], "\x0e" => [104, "\xdea"], "\x0f" => [16, "\xdea"], "\x10" => [94, "\xdec"], "\x11" => [76, "\xdec"], "\x12" => [104, "\xdec"], "\x13" => [16, "\xdec"], "\x14" => [94, "\xdee"], "\x15" => [76, "\xdee"], "\x16" => [104, "\xdee"], "\x17" => [16, "\xdee"], "\x18" => [94, "\xdei"], "\x19" => [76, "\xdei"], "\x1a" => [104, "\xdei"], "\x1b" => [16, "\xdei"], "\x1c" => [94, "\xdeo"], "\x1d" => [76, "\xdeo"], "\x1e" => [104, "\xdeo"], "\x1f" => [16, "\xdeo"], " " => [94, "\xdes"], "!" => [76, "\xdes"], "\"" => [104, "\xdes"], "#" => [16, "\xdes"], "\$" => [94, "\xdet"], "%" => [76, "\xdet"], "&" => [104, "\xdet"], "'" => [16, "\xdet"], "(" => [77, "\xde "], ")" => [18, "\xde "], "*" => [77, "\xde%"], "+" => [18, "\xde%"], "," => [77, "\xde-"], "-" => [18, "\xde-"], "." => [77, "\xde."], "/" => [18, "\xde."], [77, "\xde/"], [18, "\xde/"], [77, "\xde3"], [18, "\xde3"], [77, "\xde4"], [18, "\xde4"], [77, "\xde5"], [18, "\xde5"], [77, "\xde6"], [18, "\xde6"], ":" => [77, "\xde7"], ";" => [18, "\xde7"], "<" => [77, "\xde8"], "=" => [18, "\xde8"], ">" => [77, "\xde9"], "?" => [18, "\xde9"], "@" => [77, "\xde="], "A" => [18, "\xde="], "B" => [77, "\xdeA"], "C" => [18, "\xdeA"], "D" => [77, "\xde_"], "E" => [18, "\xde_"], "F" => [77, "\xdeb"], "G" => [18, "\xdeb"], "H" => [77, "\xded"], "I" => [18, "\xded"], "J" => [77, "\xdef"], "K" => [18, "\xdef"], "L" => [77, "\xdeg"], "M" => [18, "\xdeg"], "N" => [77, "\xdeh"], "O" => [18, "\xdeh"], "P" => [77, "\xdel"], "Q" => [18, "\xdel"], "R" => [77, "\xdem"], "S" => [18, "\xdem"], "T" => [77, "\xden"], "U" => [18, "\xden"], "V" => [77, "\xdep"], "W" => [18, "\xdep"], "X" => [77, "\xder"], "Y" => [18, "\xder"], "Z" => [77, "\xdeu"], "[" => [18, "\xdeu"], "\\" => [0, "\xde:"], "]" => [0, "\xdeB"], "^" => [0, "\xdeC"], "_" => [0, "\xdeD"], "`" => [0, "\xdeE"], "a" => [0, "\xdeF"], "b" => [0, "\xdeG"], "c" => [0, "\xdeH"], "d" => [0, "\xdeI"], "e" => [0, "\xdeJ"], "f" => [0, "\xdeK"], "g" => [0, "\xdeL"], "h" => [0, "\xdeM"], "i" => [0, "\xdeN"], "j" => [0, "\xdeO"], "k" => [0, "\xdeP"], "l" => [0, "\xdeQ"], "m" => [0, "\xdeR"], "n" => [0, "\xdeS"], "o" => [0, "\xdeT"], "p" => [0, "\xdeU"], "q" => [0, "\xdeV"], "r" => [0, "\xdeW"], "s" => [0, "\xdeY"], "t" => [0, "\xdej"], "u" => [0, "\xdek"], "v" => [0, "\xdeq"], "w" => [0, "\xdev"], "x" => [0, "\xdew"], "y" => [0, "\xdex"], "z" => [0, "\xdey"], "{" => [0, "\xdez"], "|" => [82, "\xde"], "}" => [87, "\xde"], "~" => [130, "\xde"], "" => [9, "\xde"], "\x80" => [94, "\xdf0"], "\x81" => [76, "\xdf0"], "\x82" => [104, "\xdf0"], "\x83" => [16, "\xdf0"], "\x84" => [94, "\xdf1"], "\x85" => [76, "\xdf1"], "\x86" => [104, "\xdf1"], "\x87" => [16, "\xdf1"], "\x88" => [94, "\xdf2"], "\x89" => [76, "\xdf2"], "\x8a" => [104, "\xdf2"], "\x8b" => [16, "\xdf2"], "\x8c" => [94, "\xdfa"], "\x8d" => [76, "\xdfa"], "\x8e" => [104, "\xdfa"], "\x8f" => [16, "\xdfa"], "\x90" => [94, "\xdfc"], "\x91" => [76, "\xdfc"], "\x92" => [104, "\xdfc"], "\x93" => [16, "\xdfc"], "\x94" => [94, "\xdfe"], "\x95" => [76, "\xdfe"], "\x96" => [104, "\xdfe"], "\x97" => [16, "\xdfe"], "\x98" => [94, "\xdfi"], "\x99" => [76, "\xdfi"], "\x9a" => [104, "\xdfi"], "\x9b" => [16, "\xdfi"], "\x9c" => [94, "\xdfo"], "\x9d" => [76, "\xdfo"], "\x9e" => [104, "\xdfo"], "\x9f" => [16, "\xdfo"], "\xa0" => [94, "\xdfs"], "\xa1" => [76, "\xdfs"], "\xa2" => [104, "\xdfs"], "\xa3" => [16, "\xdfs"], "\xa4" => [94, "\xdft"], "\xa5" => [76, "\xdft"], "\xa6" => [104, "\xdft"], "\xa7" => [16, "\xdft"], "\xa8" => [77, "\xdf "], "\xa9" => [18, "\xdf "], "\xaa" => [77, "\xdf%"], "\xab" => [18, "\xdf%"], "\xac" => [77, "\xdf-"], "\xad" => [18, "\xdf-"], "\xae" => [77, "\xdf."], "\xaf" => [18, "\xdf."], "\xb0" => [77, "\xdf/"], "\xb1" => [18, "\xdf/"], "\xb2" => [77, "\xdf3"], "\xb3" => [18, "\xdf3"], "\xb4" => [77, "\xdf4"], "\xb5" => [18, "\xdf4"], "\xb6" => [77, "\xdf5"], "\xb7" => [18, "\xdf5"], "\xb8" => [77, "\xdf6"], "\xb9" => [18, "\xdf6"], "\xba" => [77, "\xdf7"], "\xbb" => [18, "\xdf7"], "\xbc" => [77, "\xdf8"], "\xbd" => [18, "\xdf8"], "\xbe" => [77, "\xdf9"], "\xbf" => [18, "\xdf9"], "\xc0" => [77, "\xdf="], "\xc1" => [18, "\xdf="], "\xc2" => [77, "\xdfA"], "\xc3" => [18, "\xdfA"], "\xc4" => [77, "\xdf_"], "\xc5" => [18, "\xdf_"], "\xc6" => [77, "\xdfb"], "\xc7" => [18, "\xdfb"], "\xc8" => [77, "\xdfd"], "\xc9" => [18, "\xdfd"], "\xca" => [77, "\xdff"], "\xcb" => [18, "\xdff"], "\xcc" => [77, "\xdfg"], "\xcd" => [18, "\xdfg"], "\xce" => [77, "\xdfh"], "\xcf" => [18, "\xdfh"], "\xd0" => [77, "\xdfl"], "\xd1" => [18, "\xdfl"], "\xd2" => [77, "\xdfm"], "\xd3" => [18, "\xdfm"], "\xd4" => [77, "\xdfn"], "\xd5" => [18, "\xdfn"], "\xd6" => [77, "\xdfp"], "\xd7" => [18, "\xdfp"], "\xd8" => [77, "\xdfr"], "\xd9" => [18, "\xdfr"], "\xda" => [77, "\xdfu"], "\xdb" => [18, "\xdfu"], "\xdc" => [0, "\xdf:"], "\xdd" => [0, "\xdfB"], "\xde" => [0, "\xdfC"], "\xdf" => [0, "\xdfD"], "\xe0" => [0, "\xdfE"], "\xe1" => [0, "\xdfF"], "\xe2" => [0, "\xdfG"], "\xe3" => [0, "\xdfH"], "\xe4" => [0, "\xdfI"], "\xe5" => [0, "\xdfJ"], "\xe6" => [0, "\xdfK"], "\xe7" => [0, "\xdfL"], "\xe8" => [0, "\xdfM"], "\xe9" => [0, "\xdfN"], "\xea" => [0, "\xdfO"], "\xeb" => [0, "\xdfP"], "\xec" => [0, "\xdfQ"], "\xed" => [0, "\xdfR"], "\xee" => [0, "\xdfS"], "\xef" => [0, "\xdfT"], "\xf0" => [0, "\xdfU"], "\xf1" => [0, "\xdfV"], "\xf2" => [0, "\xdfW"], "\xf3" => [0, "\xdfY"], "\xf4" => [0, "\xdfj"], "\xf5" => [0, "\xdfk"], "\xf6" => [0, "\xdfq"], "\xf7" => [0, "\xdfv"], "\xf8" => [0, "\xdfw"], "\xf9" => [0, "\xdfx"], "\xfa" => [0, "\xdfy"], "\xfb" => [0, "\xdfz"], "\xfc" => [82, "\xdf"], "\xfd" => [87, "\xdf"], "\xfe" => [130, "\xdf"], "\xff" => [9, "\xdf"]], ["\x00" => [77, "\xde0"], "\x01" => [18, "\xde0"], "\x02" => [77, "\xde1"], "\x03" => [18, "\xde1"], "\x04" => [77, "\xde2"], "\x05" => [18, "\xde2"], "\x06" => [77, "\xdea"], "\x07" => [18, "\xdea"], "\x08" => [77, "\xdec"], "\t" => [18, "\xdec"], "\n" => [77, "\xdee"], "\v" => [18, "\xdee"], "\f" => [77, "\xdei"], "\r" => [18, "\xdei"], "\x0e" => [77, "\xdeo"], "\x0f" => [18, "\xdeo"], "\x10" => [77, "\xdes"], "\x11" => [18, "\xdes"], "\x12" => [77, "\xdet"], "\x13" => [18, "\xdet"], "\x14" => [0, "\xde "], "\x15" => [0, "\xde%"], "\x16" => [0, "\xde-"], "\x17" => [0, "\xde."], "\x18" => [0, "\xde/"], "\x19" => [0, "\xde3"], "\x1a" => [0, "\xde4"], "\x1b" => [0, "\xde5"], "\x1c" => [0, "\xde6"], "\x1d" => [0, "\xde7"], "\x1e" => [0, "\xde8"], "\x1f" => [0, "\xde9"], " " => [0, "\xde="], "!" => [0, "\xdeA"], "\"" => [0, "\xde_"], "#" => [0, "\xdeb"], "\$" => [0, "\xded"], "%" => [0, "\xdef"], "&" => [0, "\xdeg"], "'" => [0, "\xdeh"], "(" => [0, "\xdel"], ")" => [0, "\xdem"], "*" => [0, "\xden"], "+" => [0, "\xdep"], "," => [0, "\xder"], "-" => [0, "\xdeu"], "." => [100, "\xde"], "/" => [110, "\xde"], [111, "\xde"], [115, "\xde"], [116, "\xde"], [118, "\xde"], [119, "\xde"], [122, "\xde"], [123, "\xde"], [125, "\xde"], [126, "\xde"], [129, "\xde"], ":" => [143, "\xde"], ";" => [148, "\xde"], "<" => [151, "\xde"], "=" => [153, "\xde"], ">" => [83, "\xde"], "?" => [10, "\xde"], "@" => [77, "\xdf0"], "A" => [18, "\xdf0"], "B" => [77, "\xdf1"], "C" => [18, "\xdf1"], "D" => [77, "\xdf2"], "E" => [18, "\xdf2"], "F" => [77, "\xdfa"], "G" => [18, "\xdfa"], "H" => [77, "\xdfc"], "I" => [18, "\xdfc"], "J" => [77, "\xdfe"], "K" => [18, "\xdfe"], "L" => [77, "\xdfi"], "M" => [18, "\xdfi"], "N" => [77, "\xdfo"], "O" => [18, "\xdfo"], "P" => [77, "\xdfs"], "Q" => [18, "\xdfs"], "R" => [77, "\xdft"], "S" => [18, "\xdft"], "T" => [0, "\xdf "], "U" => [0, "\xdf%"], "V" => [0, "\xdf-"], "W" => [0, "\xdf."], "X" => [0, "\xdf/"], "Y" => [0, "\xdf3"], "Z" => [0, "\xdf4"], "[" => [0, "\xdf5"], "\\" => [0, "\xdf6"], "]" => [0, "\xdf7"], "^" => [0, "\xdf8"], "_" => [0, "\xdf9"], "`" => [0, "\xdf="], "a" => [0, "\xdfA"], "b" => [0, "\xdf_"], "c" => [0, "\xdfb"], "d" => [0, "\xdfd"], "e" => [0, "\xdff"], "f" => [0, "\xdfg"], "g" => [0, "\xdfh"], "h" => [0, "\xdfl"], "i" => [0, "\xdfm"], "j" => [0, "\xdfn"], "k" => [0, "\xdfp"], "l" => [0, "\xdfr"], "m" => [0, "\xdfu"], "n" => [100, "\xdf"], "o" => [110, "\xdf"], "p" => [111, "\xdf"], "q" => [115, "\xdf"], "r" => [116, "\xdf"], "s" => [118, "\xdf"], "t" => [119, "\xdf"], "u" => [122, "\xdf"], "v" => [123, "\xdf"], "w" => [125, "\xdf"], "x" => [126, "\xdf"], "y" => [129, "\xdf"], "z" => [143, "\xdf"], "{" => [148, "\xdf"], "|" => [151, "\xdf"], "}" => [153, "\xdf"], "~" => [83, "\xdf"], "" => [10, "\xdf"], "\x80" => [77, "\xf10"], "\x81" => [18, "\xf10"], "\x82" => [77, "\xf11"], "\x83" => [18, "\xf11"], "\x84" => [77, "\xf12"], "\x85" => [18, "\xf12"], "\x86" => [77, "\xf1a"], "\x87" => [18, "\xf1a"], "\x88" => [77, "\xf1c"], "\x89" => [18, "\xf1c"], "\x8a" => [77, "\xf1e"], "\x8b" => [18, "\xf1e"], "\x8c" => [77, "\xf1i"], "\x8d" => [18, "\xf1i"], "\x8e" => [77, "\xf1o"], "\x8f" => [18, "\xf1o"], "\x90" => [77, "\xf1s"], "\x91" => [18, "\xf1s"], "\x92" => [77, "\xf1t"], "\x93" => [18, "\xf1t"], "\x94" => [0, "\xf1 "], "\x95" => [0, "\xf1%"], "\x96" => [0, "\xf1-"], "\x97" => [0, "\xf1."], "\x98" => [0, "\xf1/"], "\x99" => [0, "\xf13"], "\x9a" => [0, "\xf14"], "\x9b" => [0, "\xf15"], "\x9c" => [0, "\xf16"], "\x9d" => [0, "\xf17"], "\x9e" => [0, "\xf18"], "\x9f" => [0, "\xf19"], "\xa0" => [0, "\xf1="], "\xa1" => [0, "\xf1A"], "\xa2" => [0, "\xf1_"], "\xa3" => [0, "\xf1b"], "\xa4" => [0, "\xf1d"], "\xa5" => [0, "\xf1f"], "\xa6" => [0, "\xf1g"], "\xa7" => [0, "\xf1h"], "\xa8" => [0, "\xf1l"], "\xa9" => [0, "\xf1m"], "\xaa" => [0, "\xf1n"], "\xab" => [0, "\xf1p"], "\xac" => [0, "\xf1r"], "\xad" => [0, "\xf1u"], "\xae" => [100, "\xf1"], "\xaf" => [110, "\xf1"], "\xb0" => [111, "\xf1"], "\xb1" => [115, "\xf1"], "\xb2" => [116, "\xf1"], "\xb3" => [118, "\xf1"], "\xb4" => [119, "\xf1"], "\xb5" => [122, "\xf1"], "\xb6" => [123, "\xf1"], "\xb7" => [125, "\xf1"], "\xb8" => [126, "\xf1"], "\xb9" => [129, "\xf1"], "\xba" => [143, "\xf1"], "\xbb" => [148, "\xf1"], "\xbc" => [151, "\xf1"], "\xbd" => [153, "\xf1"], "\xbe" => [83, "\xf1"], "\xbf" => [10, "\xf1"], "\xc0" => [77, "\xf40"], "\xc1" => [18, "\xf40"], "\xc2" => [77, "\xf41"], "\xc3" => [18, "\xf41"], "\xc4" => [77, "\xf42"], "\xc5" => [18, "\xf42"], "\xc6" => [77, "\xf4a"], "\xc7" => [18, "\xf4a"], "\xc8" => [77, "\xf4c"], "\xc9" => [18, "\xf4c"], "\xca" => [77, "\xf4e"], "\xcb" => [18, "\xf4e"], "\xcc" => [77, "\xf4i"], "\xcd" => [18, "\xf4i"], "\xce" => [77, "\xf4o"], "\xcf" => [18, "\xf4o"], "\xd0" => [77, "\xf4s"], "\xd1" => [18, "\xf4s"], "\xd2" => [77, "\xf4t"], "\xd3" => [18, "\xf4t"], "\xd4" => [0, "\xf4 "], "\xd5" => [0, "\xf4%"], "\xd6" => [0, "\xf4-"], "\xd7" => [0, "\xf4."], "\xd8" => [0, "\xf4/"], "\xd9" => [0, "\xf43"], "\xda" => [0, "\xf44"], "\xdb" => [0, "\xf45"], "\xdc" => [0, "\xf46"], "\xdd" => [0, "\xf47"], "\xde" => [0, "\xf48"], "\xdf" => [0, "\xf49"], "\xe0" => [0, "\xf4="], "\xe1" => [0, "\xf4A"], "\xe2" => [0, "\xf4_"], "\xe3" => [0, "\xf4b"], "\xe4" => [0, "\xf4d"], "\xe5" => [0, "\xf4f"], "\xe6" => [0, "\xf4g"], "\xe7" => [0, "\xf4h"], "\xe8" => [0, "\xf4l"], "\xe9" => [0, "\xf4m"], "\xea" => [0, "\xf4n"], "\xeb" => [0, "\xf4p"], "\xec" => [0, "\xf4r"], "\xed" => [0, "\xf4u"], "\xee" => [100, "\xf4"], "\xef" => [110, "\xf4"], "\xf0" => [111, "\xf4"], "\xf1" => [115, "\xf4"], "\xf2" => [116, "\xf4"], "\xf3" => [118, "\xf4"], "\xf4" => [119, "\xf4"], "\xf5" => [122, "\xf4"], "\xf6" => [123, "\xf4"], "\xf7" => [125, "\xf4"], "\xf8" => [126, "\xf4"], "\xf9" => [129, "\xf4"], "\xfa" => [143, "\xf4"], "\xfb" => [148, "\xf4"], "\xfc" => [151, "\xf4"], "\xfd" => [153, "\xf4"], "\xfe" => [83, "\xf4"], "\xff" => [10, "\xf4"]], ["\x00" => [94, "\xe00"], "\x01" => [76, "\xe00"], "\x02" => [104, "\xe00"], "\x03" => [16, "\xe00"], "\x04" => [94, "\xe01"], "\x05" => [76, "\xe01"], "\x06" => [104, "\xe01"], "\x07" => [16, "\xe01"], "\x08" => [94, "\xe02"], "\t" => [76, "\xe02"], "\n" => [104, "\xe02"], "\v" => [16, "\xe02"], "\f" => [94, "\xe0a"], "\r" => [76, "\xe0a"], "\x0e" => [104, "\xe0a"], "\x0f" => [16, "\xe0a"], "\x10" => [94, "\xe0c"], "\x11" => [76, "\xe0c"], "\x12" => [104, "\xe0c"], "\x13" => [16, "\xe0c"], "\x14" => [94, "\xe0e"], "\x15" => [76, "\xe0e"], "\x16" => [104, "\xe0e"], "\x17" => [16, "\xe0e"], "\x18" => [94, "\xe0i"], "\x19" => [76, "\xe0i"], "\x1a" => [104, "\xe0i"], "\x1b" => [16, "\xe0i"], "\x1c" => [94, "\xe0o"], "\x1d" => [76, "\xe0o"], "\x1e" => [104, "\xe0o"], "\x1f" => [16, "\xe0o"], " " => [94, "\xe0s"], "!" => [76, "\xe0s"], "\"" => [104, "\xe0s"], "#" => [16, "\xe0s"], "\$" => [94, "\xe0t"], "%" => [76, "\xe0t"], "&" => [104, "\xe0t"], "'" => [16, "\xe0t"], "(" => [77, "\xe0 "], ")" => [18, "\xe0 "], "*" => [77, "\xe0%"], "+" => [18, "\xe0%"], "," => [77, "\xe0-"], "-" => [18, "\xe0-"], "." => [77, "\xe0."], "/" => [18, "\xe0."], [77, "\xe0/"], [18, "\xe0/"], [77, "\xe03"], [18, "\xe03"], [77, "\xe04"], [18, "\xe04"], [77, "\xe05"], [18, "\xe05"], [77, "\xe06"], [18, "\xe06"], ":" => [77, "\xe07"], ";" => [18, "\xe07"], "<" => [77, "\xe08"], "=" => [18, "\xe08"], ">" => [77, "\xe09"], "?" => [18, "\xe09"], "@" => [77, "\xe0="], "A" => [18, "\xe0="], "B" => [77, "\xe0A"], "C" => [18, "\xe0A"], "D" => [77, "\xe0_"], "E" => [18, "\xe0_"], "F" => [77, "\xe0b"], "G" => [18, "\xe0b"], "H" => [77, "\xe0d"], "I" => [18, "\xe0d"], "J" => [77, "\xe0f"], "K" => [18, "\xe0f"], "L" => [77, "\xe0g"], "M" => [18, "\xe0g"], "N" => [77, "\xe0h"], "O" => [18, "\xe0h"], "P" => [77, "\xe0l"], "Q" => [18, "\xe0l"], "R" => [77, "\xe0m"], "S" => [18, "\xe0m"], "T" => [77, "\xe0n"], "U" => [18, "\xe0n"], "V" => [77, "\xe0p"], "W" => [18, "\xe0p"], "X" => [77, "\xe0r"], "Y" => [18, "\xe0r"], "Z" => [77, "\xe0u"], "[" => [18, "\xe0u"], "\\" => [0, "\xe0:"], "]" => [0, "\xe0B"], "^" => [0, "\xe0C"], "_" => [0, "\xe0D"], "`" => [0, "\xe0E"], "a" => [0, "\xe0F"], "b" => [0, "\xe0G"], "c" => [0, "\xe0H"], "d" => [0, "\xe0I"], "e" => [0, "\xe0J"], "f" => [0, "\xe0K"], "g" => [0, "\xe0L"], "h" => [0, "\xe0M"], "i" => [0, "\xe0N"], "j" => [0, "\xe0O"], "k" => [0, "\xe0P"], "l" => [0, "\xe0Q"], "m" => [0, "\xe0R"], "n" => [0, "\xe0S"], "o" => [0, "\xe0T"], "p" => [0, "\xe0U"], "q" => [0, "\xe0V"], "r" => [0, "\xe0W"], "s" => [0, "\xe0Y"], "t" => [0, "\xe0j"], "u" => [0, "\xe0k"], "v" => [0, "\xe0q"], "w" => [0, "\xe0v"], "x" => [0, "\xe0w"], "y" => [0, "\xe0x"], "z" => [0, "\xe0y"], "{" => [0, "\xe0z"], "|" => [82, "\xe0"], "}" => [87, "\xe0"], "~" => [130, "\xe0"], "" => [9, "\xe0"], "\x80" => [94, "\xe20"], "\x81" => [76, "\xe20"], "\x82" => [104, "\xe20"], "\x83" => [16, "\xe20"], "\x84" => [94, "\xe21"], "\x85" => [76, "\xe21"], "\x86" => [104, "\xe21"], "\x87" => [16, "\xe21"], "\x88" => [94, "\xe22"], "\x89" => [76, "\xe22"], "\x8a" => [104, "\xe22"], "\x8b" => [16, "\xe22"], "\x8c" => [94, "\xe2a"], "\x8d" => [76, "\xe2a"], "\x8e" => [104, "\xe2a"], "\x8f" => [16, "\xe2a"], "\x90" => [94, "\xe2c"], "\x91" => [76, "\xe2c"], "\x92" => [104, "\xe2c"], "\x93" => [16, "\xe2c"], "\x94" => [94, "\xe2e"], "\x95" => [76, "\xe2e"], "\x96" => [104, "\xe2e"], "\x97" => [16, "\xe2e"], "\x98" => [94, "\xe2i"], "\x99" => [76, "\xe2i"], "\x9a" => [104, "\xe2i"], "\x9b" => [16, "\xe2i"], "\x9c" => [94, "\xe2o"], "\x9d" => [76, "\xe2o"], "\x9e" => [104, "\xe2o"], "\x9f" => [16, "\xe2o"], "\xa0" => [94, "\xe2s"], "\xa1" => [76, "\xe2s"], "\xa2" => [104, "\xe2s"], "\xa3" => [16, "\xe2s"], "\xa4" => [94, "\xe2t"], "\xa5" => [76, "\xe2t"], "\xa6" => [104, "\xe2t"], "\xa7" => [16, "\xe2t"], "\xa8" => [77, "\xe2 "], "\xa9" => [18, "\xe2 "], "\xaa" => [77, "\xe2%"], "\xab" => [18, "\xe2%"], "\xac" => [77, "\xe2-"], "\xad" => [18, "\xe2-"], "\xae" => [77, "\xe2."], "\xaf" => [18, "\xe2."], "\xb0" => [77, "\xe2/"], "\xb1" => [18, "\xe2/"], "\xb2" => [77, "\xe23"], "\xb3" => [18, "\xe23"], "\xb4" => [77, "\xe24"], "\xb5" => [18, "\xe24"], "\xb6" => [77, "\xe25"], "\xb7" => [18, "\xe25"], "\xb8" => [77, "\xe26"], "\xb9" => [18, "\xe26"], "\xba" => [77, "\xe27"], "\xbb" => [18, "\xe27"], "\xbc" => [77, "\xe28"], "\xbd" => [18, "\xe28"], "\xbe" => [77, "\xe29"], "\xbf" => [18, "\xe29"], "\xc0" => [77, "\xe2="], "\xc1" => [18, "\xe2="], "\xc2" => [77, "\xe2A"], "\xc3" => [18, "\xe2A"], "\xc4" => [77, "\xe2_"], "\xc5" => [18, "\xe2_"], "\xc6" => [77, "\xe2b"], "\xc7" => [18, "\xe2b"], "\xc8" => [77, "\xe2d"], "\xc9" => [18, "\xe2d"], "\xca" => [77, "\xe2f"], "\xcb" => [18, "\xe2f"], "\xcc" => [77, "\xe2g"], "\xcd" => [18, "\xe2g"], "\xce" => [77, "\xe2h"], "\xcf" => [18, "\xe2h"], "\xd0" => [77, "\xe2l"], "\xd1" => [18, "\xe2l"], "\xd2" => [77, "\xe2m"], "\xd3" => [18, "\xe2m"], "\xd4" => [77, "\xe2n"], "\xd5" => [18, "\xe2n"], "\xd6" => [77, "\xe2p"], "\xd7" => [18, "\xe2p"], "\xd8" => [77, "\xe2r"], "\xd9" => [18, "\xe2r"], "\xda" => [77, "\xe2u"], "\xdb" => [18, "\xe2u"], "\xdc" => [0, "\xe2:"], "\xdd" => [0, "\xe2B"], "\xde" => [0, "\xe2C"], "\xdf" => [0, "\xe2D"], "\xe0" => [0, "\xe2E"], "\xe1" => [0, "\xe2F"], "\xe2" => [0, "\xe2G"], "\xe3" => [0, "\xe2H"], "\xe4" => [0, "\xe2I"], "\xe5" => [0, "\xe2J"], "\xe6" => [0, "\xe2K"], "\xe7" => [0, "\xe2L"], "\xe8" => [0, "\xe2M"], "\xe9" => [0, "\xe2N"], "\xea" => [0, "\xe2O"], "\xeb" => [0, "\xe2P"], "\xec" => [0, "\xe2Q"], "\xed" => [0, "\xe2R"], "\xee" => [0, "\xe2S"], "\xef" => [0, "\xe2T"], "\xf0" => [0, "\xe2U"], "\xf1" => [0, "\xe2V"], "\xf2" => [0, "\xe2W"], "\xf3" => [0, "\xe2Y"], "\xf4" => [0, "\xe2j"], "\xf5" => [0, "\xe2k"], "\xf6" => [0, "\xe2q"], "\xf7" => [0, "\xe2v"], "\xf8" => [0, "\xe2w"], "\xf9" => [0, "\xe2x"], "\xfa" => [0, "\xe2y"], "\xfb" => [0, "\xe2z"], "\xfc" => [82, "\xe2"], "\xfd" => [87, "\xe2"], "\xfe" => [130, "\xe2"], "\xff" => [9, "\xe2"]], ["\x00" => [94, "\xe30"], "\x01" => [76, "\xe30"], "\x02" => [104, "\xe30"], "\x03" => [16, "\xe30"], "\x04" => [94, "\xe31"], "\x05" => [76, "\xe31"], "\x06" => [104, "\xe31"], "\x07" => [16, "\xe31"], "\x08" => [94, "\xe32"], "\t" => [76, "\xe32"], "\n" => [104, "\xe32"], "\v" => [16, "\xe32"], "\f" => [94, "\xe3a"], "\r" => [76, "\xe3a"], "\x0e" => [104, "\xe3a"], "\x0f" => [16, "\xe3a"], "\x10" => [94, "\xe3c"], "\x11" => [76, "\xe3c"], "\x12" => [104, "\xe3c"], "\x13" => [16, "\xe3c"], "\x14" => [94, "\xe3e"], "\x15" => [76, "\xe3e"], "\x16" => [104, "\xe3e"], "\x17" => [16, "\xe3e"], "\x18" => [94, "\xe3i"], "\x19" => [76, "\xe3i"], "\x1a" => [104, "\xe3i"], "\x1b" => [16, "\xe3i"], "\x1c" => [94, "\xe3o"], "\x1d" => [76, "\xe3o"], "\x1e" => [104, "\xe3o"], "\x1f" => [16, "\xe3o"], " " => [94, "\xe3s"], "!" => [76, "\xe3s"], "\"" => [104, "\xe3s"], "#" => [16, "\xe3s"], "\$" => [94, "\xe3t"], "%" => [76, "\xe3t"], "&" => [104, "\xe3t"], "'" => [16, "\xe3t"], "(" => [77, "\xe3 "], ")" => [18, "\xe3 "], "*" => [77, "\xe3%"], "+" => [18, "\xe3%"], "," => [77, "\xe3-"], "-" => [18, "\xe3-"], "." => [77, "\xe3."], "/" => [18, "\xe3."], [77, "\xe3/"], [18, "\xe3/"], [77, "\xe33"], [18, "\xe33"], [77, "\xe34"], [18, "\xe34"], [77, "\xe35"], [18, "\xe35"], [77, "\xe36"], [18, "\xe36"], ":" => [77, "\xe37"], ";" => [18, "\xe37"], "<" => [77, "\xe38"], "=" => [18, "\xe38"], ">" => [77, "\xe39"], "?" => [18, "\xe39"], "@" => [77, "\xe3="], "A" => [18, "\xe3="], "B" => [77, "\xe3A"], "C" => [18, "\xe3A"], "D" => [77, "\xe3_"], "E" => [18, "\xe3_"], "F" => [77, "\xe3b"], "G" => [18, "\xe3b"], "H" => [77, "\xe3d"], "I" => [18, "\xe3d"], "J" => [77, "\xe3f"], "K" => [18, "\xe3f"], "L" => [77, "\xe3g"], "M" => [18, "\xe3g"], "N" => [77, "\xe3h"], "O" => [18, "\xe3h"], "P" => [77, "\xe3l"], "Q" => [18, "\xe3l"], "R" => [77, "\xe3m"], "S" => [18, "\xe3m"], "T" => [77, "\xe3n"], "U" => [18, "\xe3n"], "V" => [77, "\xe3p"], "W" => [18, "\xe3p"], "X" => [77, "\xe3r"], "Y" => [18, "\xe3r"], "Z" => [77, "\xe3u"], "[" => [18, "\xe3u"], "\\" => [0, "\xe3:"], "]" => [0, "\xe3B"], "^" => [0, "\xe3C"], "_" => [0, "\xe3D"], "`" => [0, "\xe3E"], "a" => [0, "\xe3F"], "b" => [0, "\xe3G"], "c" => [0, "\xe3H"], "d" => [0, "\xe3I"], "e" => [0, "\xe3J"], "f" => [0, "\xe3K"], "g" => [0, "\xe3L"], "h" => [0, "\xe3M"], "i" => [0, "\xe3N"], "j" => [0, "\xe3O"], "k" => [0, "\xe3P"], "l" => [0, "\xe3Q"], "m" => [0, "\xe3R"], "n" => [0, "\xe3S"], "o" => [0, "\xe3T"], "p" => [0, "\xe3U"], "q" => [0, "\xe3V"], "r" => [0, "\xe3W"], "s" => [0, "\xe3Y"], "t" => [0, "\xe3j"], "u" => [0, "\xe3k"], "v" => [0, "\xe3q"], "w" => [0, "\xe3v"], "x" => [0, "\xe3w"], "y" => [0, "\xe3x"], "z" => [0, "\xe3y"], "{" => [0, "\xe3z"], "|" => [82, "\xe3"], "}" => [87, "\xe3"], "~" => [130, "\xe3"], "" => [9, "\xe3"], "\x80" => [94, "\xe50"], "\x81" => [76, "\xe50"], "\x82" => [104, "\xe50"], "\x83" => [16, "\xe50"], "\x84" => [94, "\xe51"], "\x85" => [76, "\xe51"], "\x86" => [104, "\xe51"], "\x87" => [16, "\xe51"], "\x88" => [94, "\xe52"], "\x89" => [76, "\xe52"], "\x8a" => [104, "\xe52"], "\x8b" => [16, "\xe52"], "\x8c" => [94, "\xe5a"], "\x8d" => [76, "\xe5a"], "\x8e" => [104, "\xe5a"], "\x8f" => [16, "\xe5a"], "\x90" => [94, "\xe5c"], "\x91" => [76, "\xe5c"], "\x92" => [104, "\xe5c"], "\x93" => [16, "\xe5c"], "\x94" => [94, "\xe5e"], "\x95" => [76, "\xe5e"], "\x96" => [104, "\xe5e"], "\x97" => [16, "\xe5e"], "\x98" => [94, "\xe5i"], "\x99" => [76, "\xe5i"], "\x9a" => [104, "\xe5i"], "\x9b" => [16, "\xe5i"], "\x9c" => [94, "\xe5o"], "\x9d" => [76, "\xe5o"], "\x9e" => [104, "\xe5o"], "\x9f" => [16, "\xe5o"], "\xa0" => [94, "\xe5s"], "\xa1" => [76, "\xe5s"], "\xa2" => [104, "\xe5s"], "\xa3" => [16, "\xe5s"], "\xa4" => [94, "\xe5t"], "\xa5" => [76, "\xe5t"], "\xa6" => [104, "\xe5t"], "\xa7" => [16, "\xe5t"], "\xa8" => [77, "\xe5 "], "\xa9" => [18, "\xe5 "], "\xaa" => [77, "\xe5%"], "\xab" => [18, "\xe5%"], "\xac" => [77, "\xe5-"], "\xad" => [18, "\xe5-"], "\xae" => [77, "\xe5."], "\xaf" => [18, "\xe5."], "\xb0" => [77, "\xe5/"], "\xb1" => [18, "\xe5/"], "\xb2" => [77, "\xe53"], "\xb3" => [18, "\xe53"], "\xb4" => [77, "\xe54"], "\xb5" => [18, "\xe54"], "\xb6" => [77, "\xe55"], "\xb7" => [18, "\xe55"], "\xb8" => [77, "\xe56"], "\xb9" => [18, "\xe56"], "\xba" => [77, "\xe57"], "\xbb" => [18, "\xe57"], "\xbc" => [77, "\xe58"], "\xbd" => [18, "\xe58"], "\xbe" => [77, "\xe59"], "\xbf" => [18, "\xe59"], "\xc0" => [77, "\xe5="], "\xc1" => [18, "\xe5="], "\xc2" => [77, "\xe5A"], "\xc3" => [18, "\xe5A"], "\xc4" => [77, "\xe5_"], "\xc5" => [18, "\xe5_"], "\xc6" => [77, "\xe5b"], "\xc7" => [18, "\xe5b"], "\xc8" => [77, "\xe5d"], "\xc9" => [18, "\xe5d"], "\xca" => [77, "\xe5f"], "\xcb" => [18, "\xe5f"], "\xcc" => [77, "\xe5g"], "\xcd" => [18, "\xe5g"], "\xce" => [77, "\xe5h"], "\xcf" => [18, "\xe5h"], "\xd0" => [77, "\xe5l"], "\xd1" => [18, "\xe5l"], "\xd2" => [77, "\xe5m"], "\xd3" => [18, "\xe5m"], "\xd4" => [77, "\xe5n"], "\xd5" => [18, "\xe5n"], "\xd6" => [77, "\xe5p"], "\xd7" => [18, "\xe5p"], "\xd8" => [77, "\xe5r"], "\xd9" => [18, "\xe5r"], "\xda" => [77, "\xe5u"], "\xdb" => [18, "\xe5u"], "\xdc" => [0, "\xe5:"], "\xdd" => [0, "\xe5B"], "\xde" => [0, "\xe5C"], "\xdf" => [0, "\xe5D"], "\xe0" => [0, "\xe5E"], "\xe1" => [0, "\xe5F"], "\xe2" => [0, "\xe5G"], "\xe3" => [0, "\xe5H"], "\xe4" => [0, "\xe5I"], "\xe5" => [0, "\xe5J"], "\xe6" => [0, "\xe5K"], "\xe7" => [0, "\xe5L"], "\xe8" => [0, "\xe5M"], "\xe9" => [0, "\xe5N"], "\xea" => [0, "\xe5O"], "\xeb" => [0, "\xe5P"], "\xec" => [0, "\xe5Q"], "\xed" => [0, "\xe5R"], "\xee" => [0, "\xe5S"], "\xef" => [0, "\xe5T"], "\xf0" => [0, "\xe5U"], "\xf1" => [0, "\xe5V"], "\xf2" => [0, "\xe5W"], "\xf3" => [0, "\xe5Y"], "\xf4" => [0, "\xe5j"], "\xf5" => [0, "\xe5k"], "\xf6" => [0, "\xe5q"], "\xf7" => [0, "\xe5v"], "\xf8" => [0, "\xe5w"], "\xf9" => [0, "\xe5x"], "\xfa" => [0, "\xe5y"], "\xfb" => [0, "\xe5z"], "\xfc" => [82, "\xe5"], "\xfd" => [87, "\xe5"], "\xfe" => [130, "\xe5"], "\xff" => [9, "\xe5"]], ["\x00" => [94, "\xe80"], "\x01" => [76, "\xe80"], "\x02" => [104, "\xe80"], "\x03" => [16, "\xe80"], "\x04" => [94, "\xe81"], "\x05" => [76, "\xe81"], "\x06" => [104, "\xe81"], "\x07" => [16, "\xe81"], "\x08" => [94, "\xe82"], "\t" => [76, "\xe82"], "\n" => [104, "\xe82"], "\v" => [16, "\xe82"], "\f" => [94, "\xe8a"], "\r" => [76, "\xe8a"], "\x0e" => [104, "\xe8a"], "\x0f" => [16, "\xe8a"], "\x10" => [94, "\xe8c"], "\x11" => [76, "\xe8c"], "\x12" => [104, "\xe8c"], "\x13" => [16, "\xe8c"], "\x14" => [94, "\xe8e"], "\x15" => [76, "\xe8e"], "\x16" => [104, "\xe8e"], "\x17" => [16, "\xe8e"], "\x18" => [94, "\xe8i"], "\x19" => [76, "\xe8i"], "\x1a" => [104, "\xe8i"], "\x1b" => [16, "\xe8i"], "\x1c" => [94, "\xe8o"], "\x1d" => [76, "\xe8o"], "\x1e" => [104, "\xe8o"], "\x1f" => [16, "\xe8o"], " " => [94, "\xe8s"], "!" => [76, "\xe8s"], "\"" => [104, "\xe8s"], "#" => [16, "\xe8s"], "\$" => [94, "\xe8t"], "%" => [76, "\xe8t"], "&" => [104, "\xe8t"], "'" => [16, "\xe8t"], "(" => [77, "\xe8 "], ")" => [18, "\xe8 "], "*" => [77, "\xe8%"], "+" => [18, "\xe8%"], "," => [77, "\xe8-"], "-" => [18, "\xe8-"], "." => [77, "\xe8."], "/" => [18, "\xe8."], [77, "\xe8/"], [18, "\xe8/"], [77, "\xe83"], [18, "\xe83"], [77, "\xe84"], [18, "\xe84"], [77, "\xe85"], [18, "\xe85"], [77, "\xe86"], [18, "\xe86"], ":" => [77, "\xe87"], ";" => [18, "\xe87"], "<" => [77, "\xe88"], "=" => [18, "\xe88"], ">" => [77, "\xe89"], "?" => [18, "\xe89"], "@" => [77, "\xe8="], "A" => [18, "\xe8="], "B" => [77, "\xe8A"], "C" => [18, "\xe8A"], "D" => [77, "\xe8_"], "E" => [18, "\xe8_"], "F" => [77, "\xe8b"], "G" => [18, "\xe8b"], "H" => [77, "\xe8d"], "I" => [18, "\xe8d"], "J" => [77, "\xe8f"], "K" => [18, "\xe8f"], "L" => [77, "\xe8g"], "M" => [18, "\xe8g"], "N" => [77, "\xe8h"], "O" => [18, "\xe8h"], "P" => [77, "\xe8l"], "Q" => [18, "\xe8l"], "R" => [77, "\xe8m"], "S" => [18, "\xe8m"], "T" => [77, "\xe8n"], "U" => [18, "\xe8n"], "V" => [77, "\xe8p"], "W" => [18, "\xe8p"], "X" => [77, "\xe8r"], "Y" => [18, "\xe8r"], "Z" => [77, "\xe8u"], "[" => [18, "\xe8u"], "\\" => [0, "\xe8:"], "]" => [0, "\xe8B"], "^" => [0, "\xe8C"], "_" => [0, "\xe8D"], "`" => [0, "\xe8E"], "a" => [0, "\xe8F"], "b" => [0, "\xe8G"], "c" => [0, "\xe8H"], "d" => [0, "\xe8I"], "e" => [0, "\xe8J"], "f" => [0, "\xe8K"], "g" => [0, "\xe8L"], "h" => [0, "\xe8M"], "i" => [0, "\xe8N"], "j" => [0, "\xe8O"], "k" => [0, "\xe8P"], "l" => [0, "\xe8Q"], "m" => [0, "\xe8R"], "n" => [0, "\xe8S"], "o" => [0, "\xe8T"], "p" => [0, "\xe8U"], "q" => [0, "\xe8V"], "r" => [0, "\xe8W"], "s" => [0, "\xe8Y"], "t" => [0, "\xe8j"], "u" => [0, "\xe8k"], "v" => [0, "\xe8q"], "w" => [0, "\xe8v"], "x" => [0, "\xe8w"], "y" => [0, "\xe8x"], "z" => [0, "\xe8y"], "{" => [0, "\xe8z"], "|" => [82, "\xe8"], "}" => [87, "\xe8"], "~" => [130, "\xe8"], "" => [9, "\xe8"], "\x80" => [94, "\xe90"], "\x81" => [76, "\xe90"], "\x82" => [104, "\xe90"], "\x83" => [16, "\xe90"], "\x84" => [94, "\xe91"], "\x85" => [76, "\xe91"], "\x86" => [104, "\xe91"], "\x87" => [16, "\xe91"], "\x88" => [94, "\xe92"], "\x89" => [76, "\xe92"], "\x8a" => [104, "\xe92"], "\x8b" => [16, "\xe92"], "\x8c" => [94, "\xe9a"], "\x8d" => [76, "\xe9a"], "\x8e" => [104, "\xe9a"], "\x8f" => [16, "\xe9a"], "\x90" => [94, "\xe9c"], "\x91" => [76, "\xe9c"], "\x92" => [104, "\xe9c"], "\x93" => [16, "\xe9c"], "\x94" => [94, "\xe9e"], "\x95" => [76, "\xe9e"], "\x96" => [104, "\xe9e"], "\x97" => [16, "\xe9e"], "\x98" => [94, "\xe9i"], "\x99" => [76, "\xe9i"], "\x9a" => [104, "\xe9i"], "\x9b" => [16, "\xe9i"], "\x9c" => [94, "\xe9o"], "\x9d" => [76, "\xe9o"], "\x9e" => [104, "\xe9o"], "\x9f" => [16, "\xe9o"], "\xa0" => [94, "\xe9s"], "\xa1" => [76, "\xe9s"], "\xa2" => [104, "\xe9s"], "\xa3" => [16, "\xe9s"], "\xa4" => [94, "\xe9t"], "\xa5" => [76, "\xe9t"], "\xa6" => [104, "\xe9t"], "\xa7" => [16, "\xe9t"], "\xa8" => [77, "\xe9 "], "\xa9" => [18, "\xe9 "], "\xaa" => [77, "\xe9%"], "\xab" => [18, "\xe9%"], "\xac" => [77, "\xe9-"], "\xad" => [18, "\xe9-"], "\xae" => [77, "\xe9."], "\xaf" => [18, "\xe9."], "\xb0" => [77, "\xe9/"], "\xb1" => [18, "\xe9/"], "\xb2" => [77, "\xe93"], "\xb3" => [18, "\xe93"], "\xb4" => [77, "\xe94"], "\xb5" => [18, "\xe94"], "\xb6" => [77, "\xe95"], "\xb7" => [18, "\xe95"], "\xb8" => [77, "\xe96"], "\xb9" => [18, "\xe96"], "\xba" => [77, "\xe97"], "\xbb" => [18, "\xe97"], "\xbc" => [77, "\xe98"], "\xbd" => [18, "\xe98"], "\xbe" => [77, "\xe99"], "\xbf" => [18, "\xe99"], "\xc0" => [77, "\xe9="], "\xc1" => [18, "\xe9="], "\xc2" => [77, "\xe9A"], "\xc3" => [18, "\xe9A"], "\xc4" => [77, "\xe9_"], "\xc5" => [18, "\xe9_"], "\xc6" => [77, "\xe9b"], "\xc7" => [18, "\xe9b"], "\xc8" => [77, "\xe9d"], "\xc9" => [18, "\xe9d"], "\xca" => [77, "\xe9f"], "\xcb" => [18, "\xe9f"], "\xcc" => [77, "\xe9g"], "\xcd" => [18, "\xe9g"], "\xce" => [77, "\xe9h"], "\xcf" => [18, "\xe9h"], "\xd0" => [77, "\xe9l"], "\xd1" => [18, "\xe9l"], "\xd2" => [77, "\xe9m"], "\xd3" => [18, "\xe9m"], "\xd4" => [77, "\xe9n"], "\xd5" => [18, "\xe9n"], "\xd6" => [77, "\xe9p"], "\xd7" => [18, "\xe9p"], "\xd8" => [77, "\xe9r"], "\xd9" => [18, "\xe9r"], "\xda" => [77, "\xe9u"], "\xdb" => [18, "\xe9u"], "\xdc" => [0, "\xe9:"], "\xdd" => [0, "\xe9B"], "\xde" => [0, "\xe9C"], "\xdf" => [0, "\xe9D"], "\xe0" => [0, "\xe9E"], "\xe1" => [0, "\xe9F"], "\xe2" => [0, "\xe9G"], "\xe3" => [0, "\xe9H"], "\xe4" => [0, "\xe9I"], "\xe5" => [0, "\xe9J"], "\xe6" => [0, "\xe9K"], "\xe7" => [0, "\xe9L"], "\xe8" => [0, "\xe9M"], "\xe9" => [0, "\xe9N"], "\xea" => [0, "\xe9O"], "\xeb" => [0, "\xe9P"], "\xec" => [0, "\xe9Q"], "\xed" => [0, "\xe9R"], "\xee" => [0, "\xe9S"], "\xef" => [0, "\xe9T"], "\xf0" => [0, "\xe9U"], "\xf1" => [0, "\xe9V"], "\xf2" => [0, "\xe9W"], "\xf3" => [0, "\xe9Y"], "\xf4" => [0, "\xe9j"], "\xf5" => [0, "\xe9k"], "\xf6" => [0, "\xe9q"], "\xf7" => [0, "\xe9v"], "\xf8" => [0, "\xe9w"], "\xf9" => [0, "\xe9x"], "\xfa" => [0, "\xe9y"], "\xfb" => [0, "\xe9z"], "\xfc" => [82, "\xe9"], "\xfd" => [87, "\xe9"], "\xfe" => [130, "\xe9"], "\xff" => [9, "\xe9"]], ["\x00" => [94, "\xea0"], "\x01" => [76, "\xea0"], "\x02" => [104, "\xea0"], "\x03" => [16, "\xea0"], "\x04" => [94, "\xea1"], "\x05" => [76, "\xea1"], "\x06" => [104, "\xea1"], "\x07" => [16, "\xea1"], "\x08" => [94, "\xea2"], "\t" => [76, "\xea2"], "\n" => [104, "\xea2"], "\v" => [16, "\xea2"], "\f" => [94, "\xeaa"], "\r" => [76, "\xeaa"], "\x0e" => [104, "\xeaa"], "\x0f" => [16, "\xeaa"], "\x10" => [94, "\xeac"], "\x11" => [76, "\xeac"], "\x12" => [104, "\xeac"], "\x13" => [16, "\xeac"], "\x14" => [94, "\xeae"], "\x15" => [76, "\xeae"], "\x16" => [104, "\xeae"], "\x17" => [16, "\xeae"], "\x18" => [94, "\xeai"], "\x19" => [76, "\xeai"], "\x1a" => [104, "\xeai"], "\x1b" => [16, "\xeai"], "\x1c" => [94, "\xeao"], "\x1d" => [76, "\xeao"], "\x1e" => [104, "\xeao"], "\x1f" => [16, "\xeao"], " " => [94, "\xeas"], "!" => [76, "\xeas"], "\"" => [104, "\xeas"], "#" => [16, "\xeas"], "\$" => [94, "\xeat"], "%" => [76, "\xeat"], "&" => [104, "\xeat"], "'" => [16, "\xeat"], "(" => [77, "\xea "], ")" => [18, "\xea "], "*" => [77, "\xea%"], "+" => [18, "\xea%"], "," => [77, "\xea-"], "-" => [18, "\xea-"], "." => [77, "\xea."], "/" => [18, "\xea."], [77, "\xea/"], [18, "\xea/"], [77, "\xea3"], [18, "\xea3"], [77, "\xea4"], [18, "\xea4"], [77, "\xea5"], [18, "\xea5"], [77, "\xea6"], [18, "\xea6"], ":" => [77, "\xea7"], ";" => [18, "\xea7"], "<" => [77, "\xea8"], "=" => [18, "\xea8"], ">" => [77, "\xea9"], "?" => [18, "\xea9"], "@" => [77, "\xea="], "A" => [18, "\xea="], "B" => [77, "\xeaA"], "C" => [18, "\xeaA"], "D" => [77, "\xea_"], "E" => [18, "\xea_"], "F" => [77, "\xeab"], "G" => [18, "\xeab"], "H" => [77, "\xead"], "I" => [18, "\xead"], "J" => [77, "\xeaf"], "K" => [18, "\xeaf"], "L" => [77, "\xeag"], "M" => [18, "\xeag"], "N" => [77, "\xeah"], "O" => [18, "\xeah"], "P" => [77, "\xeal"], "Q" => [18, "\xeal"], "R" => [77, "\xeam"], "S" => [18, "\xeam"], "T" => [77, "\xean"], "U" => [18, "\xean"], "V" => [77, "\xeap"], "W" => [18, "\xeap"], "X" => [77, "\xear"], "Y" => [18, "\xear"], "Z" => [77, "\xeau"], "[" => [18, "\xeau"], "\\" => [0, "\xea:"], "]" => [0, "\xeaB"], "^" => [0, "\xeaC"], "_" => [0, "\xeaD"], "`" => [0, "\xeaE"], "a" => [0, "\xeaF"], "b" => [0, "\xeaG"], "c" => [0, "\xeaH"], "d" => [0, "\xeaI"], "e" => [0, "\xeaJ"], "f" => [0, "\xeaK"], "g" => [0, "\xeaL"], "h" => [0, "\xeaM"], "i" => [0, "\xeaN"], "j" => [0, "\xeaO"], "k" => [0, "\xeaP"], "l" => [0, "\xeaQ"], "m" => [0, "\xeaR"], "n" => [0, "\xeaS"], "o" => [0, "\xeaT"], "p" => [0, "\xeaU"], "q" => [0, "\xeaV"], "r" => [0, "\xeaW"], "s" => [0, "\xeaY"], "t" => [0, "\xeaj"], "u" => [0, "\xeak"], "v" => [0, "\xeaq"], "w" => [0, "\xeav"], "x" => [0, "\xeaw"], "y" => [0, "\xeax"], "z" => [0, "\xeay"], "{" => [0, "\xeaz"], "|" => [82, "\xea"], "}" => [87, "\xea"], "~" => [130, "\xea"], "" => [9, "\xea"], "\x80" => [94, "\xeb0"], "\x81" => [76, "\xeb0"], "\x82" => [104, "\xeb0"], "\x83" => [16, "\xeb0"], "\x84" => [94, "\xeb1"], "\x85" => [76, "\xeb1"], "\x86" => [104, "\xeb1"], "\x87" => [16, "\xeb1"], "\x88" => [94, "\xeb2"], "\x89" => [76, "\xeb2"], "\x8a" => [104, "\xeb2"], "\x8b" => [16, "\xeb2"], "\x8c" => [94, "\xeba"], "\x8d" => [76, "\xeba"], "\x8e" => [104, "\xeba"], "\x8f" => [16, "\xeba"], "\x90" => [94, "\xebc"], "\x91" => [76, "\xebc"], "\x92" => [104, "\xebc"], "\x93" => [16, "\xebc"], "\x94" => [94, "\xebe"], "\x95" => [76, "\xebe"], "\x96" => [104, "\xebe"], "\x97" => [16, "\xebe"], "\x98" => [94, "\xebi"], "\x99" => [76, "\xebi"], "\x9a" => [104, "\xebi"], "\x9b" => [16, "\xebi"], "\x9c" => [94, "\xebo"], "\x9d" => [76, "\xebo"], "\x9e" => [104, "\xebo"], "\x9f" => [16, "\xebo"], "\xa0" => [94, "\xebs"], "\xa1" => [76, "\xebs"], "\xa2" => [104, "\xebs"], "\xa3" => [16, "\xebs"], "\xa4" => [94, "\xebt"], "\xa5" => [76, "\xebt"], "\xa6" => [104, "\xebt"], "\xa7" => [16, "\xebt"], "\xa8" => [77, "\xeb "], "\xa9" => [18, "\xeb "], "\xaa" => [77, "\xeb%"], "\xab" => [18, "\xeb%"], "\xac" => [77, "\xeb-"], "\xad" => [18, "\xeb-"], "\xae" => [77, "\xeb."], "\xaf" => [18, "\xeb."], "\xb0" => [77, "\xeb/"], "\xb1" => [18, "\xeb/"], "\xb2" => [77, "\xeb3"], "\xb3" => [18, "\xeb3"], "\xb4" => [77, "\xeb4"], "\xb5" => [18, "\xeb4"], "\xb6" => [77, "\xeb5"], "\xb7" => [18, "\xeb5"], "\xb8" => [77, "\xeb6"], "\xb9" => [18, "\xeb6"], "\xba" => [77, "\xeb7"], "\xbb" => [18, "\xeb7"], "\xbc" => [77, "\xeb8"], "\xbd" => [18, "\xeb8"], "\xbe" => [77, "\xeb9"], "\xbf" => [18, "\xeb9"], "\xc0" => [77, "\xeb="], "\xc1" => [18, "\xeb="], "\xc2" => [77, "\xebA"], "\xc3" => [18, "\xebA"], "\xc4" => [77, "\xeb_"], "\xc5" => [18, "\xeb_"], "\xc6" => [77, "\xebb"], "\xc7" => [18, "\xebb"], "\xc8" => [77, "\xebd"], "\xc9" => [18, "\xebd"], "\xca" => [77, "\xebf"], "\xcb" => [18, "\xebf"], "\xcc" => [77, "\xebg"], "\xcd" => [18, "\xebg"], "\xce" => [77, "\xebh"], "\xcf" => [18, "\xebh"], "\xd0" => [77, "\xebl"], "\xd1" => [18, "\xebl"], "\xd2" => [77, "\xebm"], "\xd3" => [18, "\xebm"], "\xd4" => [77, "\xebn"], "\xd5" => [18, "\xebn"], "\xd6" => [77, "\xebp"], "\xd7" => [18, "\xebp"], "\xd8" => [77, "\xebr"], "\xd9" => [18, "\xebr"], "\xda" => [77, "\xebu"], "\xdb" => [18, "\xebu"], "\xdc" => [0, "\xeb:"], "\xdd" => [0, "\xebB"], "\xde" => [0, "\xebC"], "\xdf" => [0, "\xebD"], "\xe0" => [0, "\xebE"], "\xe1" => [0, "\xebF"], "\xe2" => [0, "\xebG"], "\xe3" => [0, "\xebH"], "\xe4" => [0, "\xebI"], "\xe5" => [0, "\xebJ"], "\xe6" => [0, "\xebK"], "\xe7" => [0, "\xebL"], "\xe8" => [0, "\xebM"], "\xe9" => [0, "\xebN"], "\xea" => [0, "\xebO"], "\xeb" => [0, "\xebP"], "\xec" => [0, "\xebQ"], "\xed" => [0, "\xebR"], "\xee" => [0, "\xebS"], "\xef" => [0, "\xebT"], "\xf0" => [0, "\xebU"], "\xf1" => [0, "\xebV"], "\xf2" => [0, "\xebW"], "\xf3" => [0, "\xebY"], "\xf4" => [0, "\xebj"], "\xf5" => [0, "\xebk"], "\xf6" => [0, "\xebq"], "\xf7" => [0, "\xebv"], "\xf8" => [0, "\xebw"], "\xf9" => [0, "\xebx"], "\xfa" => [0, "\xeby"], "\xfb" => [0, "\xebz"], "\xfc" => [82, "\xeb"], "\xfd" => [87, "\xeb"], "\xfe" => [130, "\xeb"], "\xff" => [9, "\xeb"]], ["\x00" => [94, "\xec0"], "\x01" => [76, "\xec0"], "\x02" => [104, "\xec0"], "\x03" => [16, "\xec0"], "\x04" => [94, "\xec1"], "\x05" => [76, "\xec1"], "\x06" => [104, "\xec1"], "\x07" => [16, "\xec1"], "\x08" => [94, "\xec2"], "\t" => [76, "\xec2"], "\n" => [104, "\xec2"], "\v" => [16, "\xec2"], "\f" => [94, "\xeca"], "\r" => [76, "\xeca"], "\x0e" => [104, "\xeca"], "\x0f" => [16, "\xeca"], "\x10" => [94, "\xecc"], "\x11" => [76, "\xecc"], "\x12" => [104, "\xecc"], "\x13" => [16, "\xecc"], "\x14" => [94, "\xece"], "\x15" => [76, "\xece"], "\x16" => [104, "\xece"], "\x17" => [16, "\xece"], "\x18" => [94, "\xeci"], "\x19" => [76, "\xeci"], "\x1a" => [104, "\xeci"], "\x1b" => [16, "\xeci"], "\x1c" => [94, "\xeco"], "\x1d" => [76, "\xeco"], "\x1e" => [104, "\xeco"], "\x1f" => [16, "\xeco"], " " => [94, "\xecs"], "!" => [76, "\xecs"], "\"" => [104, "\xecs"], "#" => [16, "\xecs"], "\$" => [94, "\xect"], "%" => [76, "\xect"], "&" => [104, "\xect"], "'" => [16, "\xect"], "(" => [77, "\xec "], ")" => [18, "\xec "], "*" => [77, "\xec%"], "+" => [18, "\xec%"], "," => [77, "\xec-"], "-" => [18, "\xec-"], "." => [77, "\xec."], "/" => [18, "\xec."], [77, "\xec/"], [18, "\xec/"], [77, "\xec3"], [18, "\xec3"], [77, "\xec4"], [18, "\xec4"], [77, "\xec5"], [18, "\xec5"], [77, "\xec6"], [18, "\xec6"], ":" => [77, "\xec7"], ";" => [18, "\xec7"], "<" => [77, "\xec8"], "=" => [18, "\xec8"], ">" => [77, "\xec9"], "?" => [18, "\xec9"], "@" => [77, "\xec="], "A" => [18, "\xec="], "B" => [77, "\xecA"], "C" => [18, "\xecA"], "D" => [77, "\xec_"], "E" => [18, "\xec_"], "F" => [77, "\xecb"], "G" => [18, "\xecb"], "H" => [77, "\xecd"], "I" => [18, "\xecd"], "J" => [77, "\xecf"], "K" => [18, "\xecf"], "L" => [77, "\xecg"], "M" => [18, "\xecg"], "N" => [77, "\xech"], "O" => [18, "\xech"], "P" => [77, "\xecl"], "Q" => [18, "\xecl"], "R" => [77, "\xecm"], "S" => [18, "\xecm"], "T" => [77, "\xecn"], "U" => [18, "\xecn"], "V" => [77, "\xecp"], "W" => [18, "\xecp"], "X" => [77, "\xecr"], "Y" => [18, "\xecr"], "Z" => [77, "\xecu"], "[" => [18, "\xecu"], "\\" => [0, "\xec:"], "]" => [0, "\xecB"], "^" => [0, "\xecC"], "_" => [0, "\xecD"], "`" => [0, "\xecE"], "a" => [0, "\xecF"], "b" => [0, "\xecG"], "c" => [0, "\xecH"], "d" => [0, "\xecI"], "e" => [0, "\xecJ"], "f" => [0, "\xecK"], "g" => [0, "\xecL"], "h" => [0, "\xecM"], "i" => [0, "\xecN"], "j" => [0, "\xecO"], "k" => [0, "\xecP"], "l" => [0, "\xecQ"], "m" => [0, "\xecR"], "n" => [0, "\xecS"], "o" => [0, "\xecT"], "p" => [0, "\xecU"], "q" => [0, "\xecV"], "r" => [0, "\xecW"], "s" => [0, "\xecY"], "t" => [0, "\xecj"], "u" => [0, "\xeck"], "v" => [0, "\xecq"], "w" => [0, "\xecv"], "x" => [0, "\xecw"], "y" => [0, "\xecx"], "z" => [0, "\xecy"], "{" => [0, "\xecz"], "|" => [82, "\xec"], "}" => [87, "\xec"], "~" => [130, "\xec"], "" => [9, "\xec"], "\x80" => [94, "\xed0"], "\x81" => [76, "\xed0"], "\x82" => [104, "\xed0"], "\x83" => [16, "\xed0"], "\x84" => [94, "\xed1"], "\x85" => [76, "\xed1"], "\x86" => [104, "\xed1"], "\x87" => [16, "\xed1"], "\x88" => [94, "\xed2"], "\x89" => [76, "\xed2"], "\x8a" => [104, "\xed2"], "\x8b" => [16, "\xed2"], "\x8c" => [94, "\xeda"], "\x8d" => [76, "\xeda"], "\x8e" => [104, "\xeda"], "\x8f" => [16, "\xeda"], "\x90" => [94, "\xedc"], "\x91" => [76, "\xedc"], "\x92" => [104, "\xedc"], "\x93" => [16, "\xedc"], "\x94" => [94, "\xede"], "\x95" => [76, "\xede"], "\x96" => [104, "\xede"], "\x97" => [16, "\xede"], "\x98" => [94, "\xedi"], "\x99" => [76, "\xedi"], "\x9a" => [104, "\xedi"], "\x9b" => [16, "\xedi"], "\x9c" => [94, "\xedo"], "\x9d" => [76, "\xedo"], "\x9e" => [104, "\xedo"], "\x9f" => [16, "\xedo"], "\xa0" => [94, "\xeds"], "\xa1" => [76, "\xeds"], "\xa2" => [104, "\xeds"], "\xa3" => [16, "\xeds"], "\xa4" => [94, "\xedt"], "\xa5" => [76, "\xedt"], "\xa6" => [104, "\xedt"], "\xa7" => [16, "\xedt"], "\xa8" => [77, "\xed "], "\xa9" => [18, "\xed "], "\xaa" => [77, "\xed%"], "\xab" => [18, "\xed%"], "\xac" => [77, "\xed-"], "\xad" => [18, "\xed-"], "\xae" => [77, "\xed."], "\xaf" => [18, "\xed."], "\xb0" => [77, "\xed/"], "\xb1" => [18, "\xed/"], "\xb2" => [77, "\xed3"], "\xb3" => [18, "\xed3"], "\xb4" => [77, "\xed4"], "\xb5" => [18, "\xed4"], "\xb6" => [77, "\xed5"], "\xb7" => [18, "\xed5"], "\xb8" => [77, "\xed6"], "\xb9" => [18, "\xed6"], "\xba" => [77, "\xed7"], "\xbb" => [18, "\xed7"], "\xbc" => [77, "\xed8"], "\xbd" => [18, "\xed8"], "\xbe" => [77, "\xed9"], "\xbf" => [18, "\xed9"], "\xc0" => [77, "\xed="], "\xc1" => [18, "\xed="], "\xc2" => [77, "\xedA"], "\xc3" => [18, "\xedA"], "\xc4" => [77, "\xed_"], "\xc5" => [18, "\xed_"], "\xc6" => [77, "\xedb"], "\xc7" => [18, "\xedb"], "\xc8" => [77, "\xedd"], "\xc9" => [18, "\xedd"], "\xca" => [77, "\xedf"], "\xcb" => [18, "\xedf"], "\xcc" => [77, "\xedg"], "\xcd" => [18, "\xedg"], "\xce" => [77, "\xedh"], "\xcf" => [18, "\xedh"], "\xd0" => [77, "\xedl"], "\xd1" => [18, "\xedl"], "\xd2" => [77, "\xedm"], "\xd3" => [18, "\xedm"], "\xd4" => [77, "\xedn"], "\xd5" => [18, "\xedn"], "\xd6" => [77, "\xedp"], "\xd7" => [18, "\xedp"], "\xd8" => [77, "\xedr"], "\xd9" => [18, "\xedr"], "\xda" => [77, "\xedu"], "\xdb" => [18, "\xedu"], "\xdc" => [0, "\xed:"], "\xdd" => [0, "\xedB"], "\xde" => [0, "\xedC"], "\xdf" => [0, "\xedD"], "\xe0" => [0, "\xedE"], "\xe1" => [0, "\xedF"], "\xe2" => [0, "\xedG"], "\xe3" => [0, "\xedH"], "\xe4" => [0, "\xedI"], "\xe5" => [0, "\xedJ"], "\xe6" => [0, "\xedK"], "\xe7" => [0, "\xedL"], "\xe8" => [0, "\xedM"], "\xe9" => [0, "\xedN"], "\xea" => [0, "\xedO"], "\xeb" => [0, "\xedP"], "\xec" => [0, "\xedQ"], "\xed" => [0, "\xedR"], "\xee" => [0, "\xedS"], "\xef" => [0, "\xedT"], "\xf0" => [0, "\xedU"], "\xf1" => [0, "\xedV"], "\xf2" => [0, "\xedW"], "\xf3" => [0, "\xedY"], "\xf4" => [0, "\xedj"], "\xf5" => [0, "\xedk"], "\xf6" => [0, "\xedq"], "\xf7" => [0, "\xedv"], "\xf8" => [0, "\xedw"], "\xf9" => [0, "\xedx"], "\xfa" => [0, "\xedy"], "\xfb" => [0, "\xedz"], "\xfc" => [82, "\xed"], "\xfd" => [87, "\xed"], "\xfe" => [130, "\xed"], "\xff" => [9, "\xed"]], ["\x00" => [94, "\xee0"], "\x01" => [76, "\xee0"], "\x02" => [104, "\xee0"], "\x03" => [16, "\xee0"], "\x04" => [94, "\xee1"], "\x05" => [76, "\xee1"], "\x06" => [104, "\xee1"], "\x07" => [16, "\xee1"], "\x08" => [94, "\xee2"], "\t" => [76, "\xee2"], "\n" => [104, "\xee2"], "\v" => [16, "\xee2"], "\f" => [94, "\xeea"], "\r" => [76, "\xeea"], "\x0e" => [104, "\xeea"], "\x0f" => [16, "\xeea"], "\x10" => [94, "\xeec"], "\x11" => [76, "\xeec"], "\x12" => [104, "\xeec"], "\x13" => [16, "\xeec"], "\x14" => [94, "\xeee"], "\x15" => [76, "\xeee"], "\x16" => [104, "\xeee"], "\x17" => [16, "\xeee"], "\x18" => [94, "\xeei"], "\x19" => [76, "\xeei"], "\x1a" => [104, "\xeei"], "\x1b" => [16, "\xeei"], "\x1c" => [94, "\xeeo"], "\x1d" => [76, "\xeeo"], "\x1e" => [104, "\xeeo"], "\x1f" => [16, "\xeeo"], " " => [94, "\xees"], "!" => [76, "\xees"], "\"" => [104, "\xees"], "#" => [16, "\xees"], "\$" => [94, "\xeet"], "%" => [76, "\xeet"], "&" => [104, "\xeet"], "'" => [16, "\xeet"], "(" => [77, "\xee "], ")" => [18, "\xee "], "*" => [77, "\xee%"], "+" => [18, "\xee%"], "," => [77, "\xee-"], "-" => [18, "\xee-"], "." => [77, "\xee."], "/" => [18, "\xee."], [77, "\xee/"], [18, "\xee/"], [77, "\xee3"], [18, "\xee3"], [77, "\xee4"], [18, "\xee4"], [77, "\xee5"], [18, "\xee5"], [77, "\xee6"], [18, "\xee6"], ":" => [77, "\xee7"], ";" => [18, "\xee7"], "<" => [77, "\xee8"], "=" => [18, "\xee8"], ">" => [77, "\xee9"], "?" => [18, "\xee9"], "@" => [77, "\xee="], "A" => [18, "\xee="], "B" => [77, "\xeeA"], "C" => [18, "\xeeA"], "D" => [77, "\xee_"], "E" => [18, "\xee_"], "F" => [77, "\xeeb"], "G" => [18, "\xeeb"], "H" => [77, "\xeed"], "I" => [18, "\xeed"], "J" => [77, "\xeef"], "K" => [18, "\xeef"], "L" => [77, "\xeeg"], "M" => [18, "\xeeg"], "N" => [77, "\xeeh"], "O" => [18, "\xeeh"], "P" => [77, "\xeel"], "Q" => [18, "\xeel"], "R" => [77, "\xeem"], "S" => [18, "\xeem"], "T" => [77, "\xeen"], "U" => [18, "\xeen"], "V" => [77, "\xeep"], "W" => [18, "\xeep"], "X" => [77, "\xeer"], "Y" => [18, "\xeer"], "Z" => [77, "\xeeu"], "[" => [18, "\xeeu"], "\\" => [0, "\xee:"], "]" => [0, "\xeeB"], "^" => [0, "\xeeC"], "_" => [0, "\xeeD"], "`" => [0, "\xeeE"], "a" => [0, "\xeeF"], "b" => [0, "\xeeG"], "c" => [0, "\xeeH"], "d" => [0, "\xeeI"], "e" => [0, "\xeeJ"], "f" => [0, "\xeeK"], "g" => [0, "\xeeL"], "h" => [0, "\xeeM"], "i" => [0, "\xeeN"], "j" => [0, "\xeeO"], "k" => [0, "\xeeP"], "l" => [0, "\xeeQ"], "m" => [0, "\xeeR"], "n" => [0, "\xeeS"], "o" => [0, "\xeeT"], "p" => [0, "\xeeU"], "q" => [0, "\xeeV"], "r" => [0, "\xeeW"], "s" => [0, "\xeeY"], "t" => [0, "\xeej"], "u" => [0, "\xeek"], "v" => [0, "\xeeq"], "w" => [0, "\xeev"], "x" => [0, "\xeew"], "y" => [0, "\xeex"], "z" => [0, "\xeey"], "{" => [0, "\xeez"], "|" => [82, "\xee"], "}" => [87, "\xee"], "~" => [130, "\xee"], "" => [9, "\xee"], "\x80" => [94, "\xf00"], "\x81" => [76, "\xf00"], "\x82" => [104, "\xf00"], "\x83" => [16, "\xf00"], "\x84" => [94, "\xf01"], "\x85" => [76, "\xf01"], "\x86" => [104, "\xf01"], "\x87" => [16, "\xf01"], "\x88" => [94, "\xf02"], "\x89" => [76, "\xf02"], "\x8a" => [104, "\xf02"], "\x8b" => [16, "\xf02"], "\x8c" => [94, "\xf0a"], "\x8d" => [76, "\xf0a"], "\x8e" => [104, "\xf0a"], "\x8f" => [16, "\xf0a"], "\x90" => [94, "\xf0c"], "\x91" => [76, "\xf0c"], "\x92" => [104, "\xf0c"], "\x93" => [16, "\xf0c"], "\x94" => [94, "\xf0e"], "\x95" => [76, "\xf0e"], "\x96" => [104, "\xf0e"], "\x97" => [16, "\xf0e"], "\x98" => [94, "\xf0i"], "\x99" => [76, "\xf0i"], "\x9a" => [104, "\xf0i"], "\x9b" => [16, "\xf0i"], "\x9c" => [94, "\xf0o"], "\x9d" => [76, "\xf0o"], "\x9e" => [104, "\xf0o"], "\x9f" => [16, "\xf0o"], "\xa0" => [94, "\xf0s"], "\xa1" => [76, "\xf0s"], "\xa2" => [104, "\xf0s"], "\xa3" => [16, "\xf0s"], "\xa4" => [94, "\xf0t"], "\xa5" => [76, "\xf0t"], "\xa6" => [104, "\xf0t"], "\xa7" => [16, "\xf0t"], "\xa8" => [77, "\xf0 "], "\xa9" => [18, "\xf0 "], "\xaa" => [77, "\xf0%"], "\xab" => [18, "\xf0%"], "\xac" => [77, "\xf0-"], "\xad" => [18, "\xf0-"], "\xae" => [77, "\xf0."], "\xaf" => [18, "\xf0."], "\xb0" => [77, "\xf0/"], "\xb1" => [18, "\xf0/"], "\xb2" => [77, "\xf03"], "\xb3" => [18, "\xf03"], "\xb4" => [77, "\xf04"], "\xb5" => [18, "\xf04"], "\xb6" => [77, "\xf05"], "\xb7" => [18, "\xf05"], "\xb8" => [77, "\xf06"], "\xb9" => [18, "\xf06"], "\xba" => [77, "\xf07"], "\xbb" => [18, "\xf07"], "\xbc" => [77, "\xf08"], "\xbd" => [18, "\xf08"], "\xbe" => [77, "\xf09"], "\xbf" => [18, "\xf09"], "\xc0" => [77, "\xf0="], "\xc1" => [18, "\xf0="], "\xc2" => [77, "\xf0A"], "\xc3" => [18, "\xf0A"], "\xc4" => [77, "\xf0_"], "\xc5" => [18, "\xf0_"], "\xc6" => [77, "\xf0b"], "\xc7" => [18, "\xf0b"], "\xc8" => [77, "\xf0d"], "\xc9" => [18, "\xf0d"], "\xca" => [77, "\xf0f"], "\xcb" => [18, "\xf0f"], "\xcc" => [77, "\xf0g"], "\xcd" => [18, "\xf0g"], "\xce" => [77, "\xf0h"], "\xcf" => [18, "\xf0h"], "\xd0" => [77, "\xf0l"], "\xd1" => [18, "\xf0l"], "\xd2" => [77, "\xf0m"], "\xd3" => [18, "\xf0m"], "\xd4" => [77, "\xf0n"], "\xd5" => [18, "\xf0n"], "\xd6" => [77, "\xf0p"], "\xd7" => [18, "\xf0p"], "\xd8" => [77, "\xf0r"], "\xd9" => [18, "\xf0r"], "\xda" => [77, "\xf0u"], "\xdb" => [18, "\xf0u"], "\xdc" => [0, "\xf0:"], "\xdd" => [0, "\xf0B"], "\xde" => [0, "\xf0C"], "\xdf" => [0, "\xf0D"], "\xe0" => [0, "\xf0E"], "\xe1" => [0, "\xf0F"], "\xe2" => [0, "\xf0G"], "\xe3" => [0, "\xf0H"], "\xe4" => [0, "\xf0I"], "\xe5" => [0, "\xf0J"], "\xe6" => [0, "\xf0K"], "\xe7" => [0, "\xf0L"], "\xe8" => [0, "\xf0M"], "\xe9" => [0, "\xf0N"], "\xea" => [0, "\xf0O"], "\xeb" => [0, "\xf0P"], "\xec" => [0, "\xf0Q"], "\xed" => [0, "\xf0R"], "\xee" => [0, "\xf0S"], "\xef" => [0, "\xf0T"], "\xf0" => [0, "\xf0U"], "\xf1" => [0, "\xf0V"], "\xf2" => [0, "\xf0W"], "\xf3" => [0, "\xf0Y"], "\xf4" => [0, "\xf0j"], "\xf5" => [0, "\xf0k"], "\xf6" => [0, "\xf0q"], "\xf7" => [0, "\xf0v"], "\xf8" => [0, "\xf0w"], "\xf9" => [0, "\xf0x"], "\xfa" => [0, "\xf0y"], "\xfb" => [0, "\xf0z"], "\xfc" => [82, "\xf0"], "\xfd" => [87, "\xf0"], "\xfe" => [130, "\xf0"], "\xff" => [9, "\xf0"]], ["\x00" => [94, "\xf10"], "\x01" => [76, "\xf10"], "\x02" => [104, "\xf10"], "\x03" => [16, "\xf10"], "\x04" => [94, "\xf11"], "\x05" => [76, "\xf11"], "\x06" => [104, "\xf11"], "\x07" => [16, "\xf11"], "\x08" => [94, "\xf12"], "\t" => [76, "\xf12"], "\n" => [104, "\xf12"], "\v" => [16, "\xf12"], "\f" => [94, "\xf1a"], "\r" => [76, "\xf1a"], "\x0e" => [104, "\xf1a"], "\x0f" => [16, "\xf1a"], "\x10" => [94, "\xf1c"], "\x11" => [76, "\xf1c"], "\x12" => [104, "\xf1c"], "\x13" => [16, "\xf1c"], "\x14" => [94, "\xf1e"], "\x15" => [76, "\xf1e"], "\x16" => [104, "\xf1e"], "\x17" => [16, "\xf1e"], "\x18" => [94, "\xf1i"], "\x19" => [76, "\xf1i"], "\x1a" => [104, "\xf1i"], "\x1b" => [16, "\xf1i"], "\x1c" => [94, "\xf1o"], "\x1d" => [76, "\xf1o"], "\x1e" => [104, "\xf1o"], "\x1f" => [16, "\xf1o"], " " => [94, "\xf1s"], "!" => [76, "\xf1s"], "\"" => [104, "\xf1s"], "#" => [16, "\xf1s"], "\$" => [94, "\xf1t"], "%" => [76, "\xf1t"], "&" => [104, "\xf1t"], "'" => [16, "\xf1t"], "(" => [77, "\xf1 "], ")" => [18, "\xf1 "], "*" => [77, "\xf1%"], "+" => [18, "\xf1%"], "," => [77, "\xf1-"], "-" => [18, "\xf1-"], "." => [77, "\xf1."], "/" => [18, "\xf1."], [77, "\xf1/"], [18, "\xf1/"], [77, "\xf13"], [18, "\xf13"], [77, "\xf14"], [18, "\xf14"], [77, "\xf15"], [18, "\xf15"], [77, "\xf16"], [18, "\xf16"], ":" => [77, "\xf17"], ";" => [18, "\xf17"], "<" => [77, "\xf18"], "=" => [18, "\xf18"], ">" => [77, "\xf19"], "?" => [18, "\xf19"], "@" => [77, "\xf1="], "A" => [18, "\xf1="], "B" => [77, "\xf1A"], "C" => [18, "\xf1A"], "D" => [77, "\xf1_"], "E" => [18, "\xf1_"], "F" => [77, "\xf1b"], "G" => [18, "\xf1b"], "H" => [77, "\xf1d"], "I" => [18, "\xf1d"], "J" => [77, "\xf1f"], "K" => [18, "\xf1f"], "L" => [77, "\xf1g"], "M" => [18, "\xf1g"], "N" => [77, "\xf1h"], "O" => [18, "\xf1h"], "P" => [77, "\xf1l"], "Q" => [18, "\xf1l"], "R" => [77, "\xf1m"], "S" => [18, "\xf1m"], "T" => [77, "\xf1n"], "U" => [18, "\xf1n"], "V" => [77, "\xf1p"], "W" => [18, "\xf1p"], "X" => [77, "\xf1r"], "Y" => [18, "\xf1r"], "Z" => [77, "\xf1u"], "[" => [18, "\xf1u"], "\\" => [0, "\xf1:"], "]" => [0, "\xf1B"], "^" => [0, "\xf1C"], "_" => [0, "\xf1D"], "`" => [0, "\xf1E"], "a" => [0, "\xf1F"], "b" => [0, "\xf1G"], "c" => [0, "\xf1H"], "d" => [0, "\xf1I"], "e" => [0, "\xf1J"], "f" => [0, "\xf1K"], "g" => [0, "\xf1L"], "h" => [0, "\xf1M"], "i" => [0, "\xf1N"], "j" => [0, "\xf1O"], "k" => [0, "\xf1P"], "l" => [0, "\xf1Q"], "m" => [0, "\xf1R"], "n" => [0, "\xf1S"], "o" => [0, "\xf1T"], "p" => [0, "\xf1U"], "q" => [0, "\xf1V"], "r" => [0, "\xf1W"], "s" => [0, "\xf1Y"], "t" => [0, "\xf1j"], "u" => [0, "\xf1k"], "v" => [0, "\xf1q"], "w" => [0, "\xf1v"], "x" => [0, "\xf1w"], "y" => [0, "\xf1x"], "z" => [0, "\xf1y"], "{" => [0, "\xf1z"], "|" => [82, "\xf1"], "}" => [87, "\xf1"], "~" => [130, "\xf1"], "" => [9, "\xf1"], "\x80" => [94, "\xf40"], "\x81" => [76, "\xf40"], "\x82" => [104, "\xf40"], "\x83" => [16, "\xf40"], "\x84" => [94, "\xf41"], "\x85" => [76, "\xf41"], "\x86" => [104, "\xf41"], "\x87" => [16, "\xf41"], "\x88" => [94, "\xf42"], "\x89" => [76, "\xf42"], "\x8a" => [104, "\xf42"], "\x8b" => [16, "\xf42"], "\x8c" => [94, "\xf4a"], "\x8d" => [76, "\xf4a"], "\x8e" => [104, "\xf4a"], "\x8f" => [16, "\xf4a"], "\x90" => [94, "\xf4c"], "\x91" => [76, "\xf4c"], "\x92" => [104, "\xf4c"], "\x93" => [16, "\xf4c"], "\x94" => [94, "\xf4e"], "\x95" => [76, "\xf4e"], "\x96" => [104, "\xf4e"], "\x97" => [16, "\xf4e"], "\x98" => [94, "\xf4i"], "\x99" => [76, "\xf4i"], "\x9a" => [104, "\xf4i"], "\x9b" => [16, "\xf4i"], "\x9c" => [94, "\xf4o"], "\x9d" => [76, "\xf4o"], "\x9e" => [104, "\xf4o"], "\x9f" => [16, "\xf4o"], "\xa0" => [94, "\xf4s"], "\xa1" => [76, "\xf4s"], "\xa2" => [104, "\xf4s"], "\xa3" => [16, "\xf4s"], "\xa4" => [94, "\xf4t"], "\xa5" => [76, "\xf4t"], "\xa6" => [104, "\xf4t"], "\xa7" => [16, "\xf4t"], "\xa8" => [77, "\xf4 "], "\xa9" => [18, "\xf4 "], "\xaa" => [77, "\xf4%"], "\xab" => [18, "\xf4%"], "\xac" => [77, "\xf4-"], "\xad" => [18, "\xf4-"], "\xae" => [77, "\xf4."], "\xaf" => [18, "\xf4."], "\xb0" => [77, "\xf4/"], "\xb1" => [18, "\xf4/"], "\xb2" => [77, "\xf43"], "\xb3" => [18, "\xf43"], "\xb4" => [77, "\xf44"], "\xb5" => [18, "\xf44"], "\xb6" => [77, "\xf45"], "\xb7" => [18, "\xf45"], "\xb8" => [77, "\xf46"], "\xb9" => [18, "\xf46"], "\xba" => [77, "\xf47"], "\xbb" => [18, "\xf47"], "\xbc" => [77, "\xf48"], "\xbd" => [18, "\xf48"], "\xbe" => [77, "\xf49"], "\xbf" => [18, "\xf49"], "\xc0" => [77, "\xf4="], "\xc1" => [18, "\xf4="], "\xc2" => [77, "\xf4A"], "\xc3" => [18, "\xf4A"], "\xc4" => [77, "\xf4_"], "\xc5" => [18, "\xf4_"], "\xc6" => [77, "\xf4b"], "\xc7" => [18, "\xf4b"], "\xc8" => [77, "\xf4d"], "\xc9" => [18, "\xf4d"], "\xca" => [77, "\xf4f"], "\xcb" => [18, "\xf4f"], "\xcc" => [77, "\xf4g"], "\xcd" => [18, "\xf4g"], "\xce" => [77, "\xf4h"], "\xcf" => [18, "\xf4h"], "\xd0" => [77, "\xf4l"], "\xd1" => [18, "\xf4l"], "\xd2" => [77, "\xf4m"], "\xd3" => [18, "\xf4m"], "\xd4" => [77, "\xf4n"], "\xd5" => [18, "\xf4n"], "\xd6" => [77, "\xf4p"], "\xd7" => [18, "\xf4p"], "\xd8" => [77, "\xf4r"], "\xd9" => [18, "\xf4r"], "\xda" => [77, "\xf4u"], "\xdb" => [18, "\xf4u"], "\xdc" => [0, "\xf4:"], "\xdd" => [0, "\xf4B"], "\xde" => [0, "\xf4C"], "\xdf" => [0, "\xf4D"], "\xe0" => [0, "\xf4E"], "\xe1" => [0, "\xf4F"], "\xe2" => [0, "\xf4G"], "\xe3" => [0, "\xf4H"], "\xe4" => [0, "\xf4I"], "\xe5" => [0, "\xf4J"], "\xe6" => [0, "\xf4K"], "\xe7" => [0, "\xf4L"], "\xe8" => [0, "\xf4M"], "\xe9" => [0, "\xf4N"], "\xea" => [0, "\xf4O"], "\xeb" => [0, "\xf4P"], "\xec" => [0, "\xf4Q"], "\xed" => [0, "\xf4R"], "\xee" => [0, "\xf4S"], "\xef" => [0, "\xf4T"], "\xf0" => [0, "\xf4U"], "\xf1" => [0, "\xf4V"], "\xf2" => [0, "\xf4W"], "\xf3" => [0, "\xf4Y"], "\xf4" => [0, "\xf4j"], "\xf5" => [0, "\xf4k"], "\xf6" => [0, "\xf4q"], "\xf7" => [0, "\xf4v"], "\xf8" => [0, "\xf4w"], "\xf9" => [0, "\xf4x"], "\xfa" => [0, "\xf4y"], "\xfb" => [0, "\xf4z"], "\xfc" => [82, "\xf4"], "\xfd" => [87, "\xf4"], "\xfe" => [130, "\xf4"], "\xff" => [9, "\xf4"]], ["\x00" => [94, "\xf20"], "\x01" => [76, "\xf20"], "\x02" => [104, "\xf20"], "\x03" => [16, "\xf20"], "\x04" => [94, "\xf21"], "\x05" => [76, "\xf21"], "\x06" => [104, "\xf21"], "\x07" => [16, "\xf21"], "\x08" => [94, "\xf22"], "\t" => [76, "\xf22"], "\n" => [104, "\xf22"], "\v" => [16, "\xf22"], "\f" => [94, "\xf2a"], "\r" => [76, "\xf2a"], "\x0e" => [104, "\xf2a"], "\x0f" => [16, "\xf2a"], "\x10" => [94, "\xf2c"], "\x11" => [76, "\xf2c"], "\x12" => [104, "\xf2c"], "\x13" => [16, "\xf2c"], "\x14" => [94, "\xf2e"], "\x15" => [76, "\xf2e"], "\x16" => [104, "\xf2e"], "\x17" => [16, "\xf2e"], "\x18" => [94, "\xf2i"], "\x19" => [76, "\xf2i"], "\x1a" => [104, "\xf2i"], "\x1b" => [16, "\xf2i"], "\x1c" => [94, "\xf2o"], "\x1d" => [76, "\xf2o"], "\x1e" => [104, "\xf2o"], "\x1f" => [16, "\xf2o"], " " => [94, "\xf2s"], "!" => [76, "\xf2s"], "\"" => [104, "\xf2s"], "#" => [16, "\xf2s"], "\$" => [94, "\xf2t"], "%" => [76, "\xf2t"], "&" => [104, "\xf2t"], "'" => [16, "\xf2t"], "(" => [77, "\xf2 "], ")" => [18, "\xf2 "], "*" => [77, "\xf2%"], "+" => [18, "\xf2%"], "," => [77, "\xf2-"], "-" => [18, "\xf2-"], "." => [77, "\xf2."], "/" => [18, "\xf2."], [77, "\xf2/"], [18, "\xf2/"], [77, "\xf23"], [18, "\xf23"], [77, "\xf24"], [18, "\xf24"], [77, "\xf25"], [18, "\xf25"], [77, "\xf26"], [18, "\xf26"], ":" => [77, "\xf27"], ";" => [18, "\xf27"], "<" => [77, "\xf28"], "=" => [18, "\xf28"], ">" => [77, "\xf29"], "?" => [18, "\xf29"], "@" => [77, "\xf2="], "A" => [18, "\xf2="], "B" => [77, "\xf2A"], "C" => [18, "\xf2A"], "D" => [77, "\xf2_"], "E" => [18, "\xf2_"], "F" => [77, "\xf2b"], "G" => [18, "\xf2b"], "H" => [77, "\xf2d"], "I" => [18, "\xf2d"], "J" => [77, "\xf2f"], "K" => [18, "\xf2f"], "L" => [77, "\xf2g"], "M" => [18, "\xf2g"], "N" => [77, "\xf2h"], "O" => [18, "\xf2h"], "P" => [77, "\xf2l"], "Q" => [18, "\xf2l"], "R" => [77, "\xf2m"], "S" => [18, "\xf2m"], "T" => [77, "\xf2n"], "U" => [18, "\xf2n"], "V" => [77, "\xf2p"], "W" => [18, "\xf2p"], "X" => [77, "\xf2r"], "Y" => [18, "\xf2r"], "Z" => [77, "\xf2u"], "[" => [18, "\xf2u"], "\\" => [0, "\xf2:"], "]" => [0, "\xf2B"], "^" => [0, "\xf2C"], "_" => [0, "\xf2D"], "`" => [0, "\xf2E"], "a" => [0, "\xf2F"], "b" => [0, "\xf2G"], "c" => [0, "\xf2H"], "d" => [0, "\xf2I"], "e" => [0, "\xf2J"], "f" => [0, "\xf2K"], "g" => [0, "\xf2L"], "h" => [0, "\xf2M"], "i" => [0, "\xf2N"], "j" => [0, "\xf2O"], "k" => [0, "\xf2P"], "l" => [0, "\xf2Q"], "m" => [0, "\xf2R"], "n" => [0, "\xf2S"], "o" => [0, "\xf2T"], "p" => [0, "\xf2U"], "q" => [0, "\xf2V"], "r" => [0, "\xf2W"], "s" => [0, "\xf2Y"], "t" => [0, "\xf2j"], "u" => [0, "\xf2k"], "v" => [0, "\xf2q"], "w" => [0, "\xf2v"], "x" => [0, "\xf2w"], "y" => [0, "\xf2x"], "z" => [0, "\xf2y"], "{" => [0, "\xf2z"], "|" => [82, "\xf2"], "}" => [87, "\xf2"], "~" => [130, "\xf2"], "" => [9, "\xf2"], "\x80" => [94, "\xf30"], "\x81" => [76, "\xf30"], "\x82" => [104, "\xf30"], "\x83" => [16, "\xf30"], "\x84" => [94, "\xf31"], "\x85" => [76, "\xf31"], "\x86" => [104, "\xf31"], "\x87" => [16, "\xf31"], "\x88" => [94, "\xf32"], "\x89" => [76, "\xf32"], "\x8a" => [104, "\xf32"], "\x8b" => [16, "\xf32"], "\x8c" => [94, "\xf3a"], "\x8d" => [76, "\xf3a"], "\x8e" => [104, "\xf3a"], "\x8f" => [16, "\xf3a"], "\x90" => [94, "\xf3c"], "\x91" => [76, "\xf3c"], "\x92" => [104, "\xf3c"], "\x93" => [16, "\xf3c"], "\x94" => [94, "\xf3e"], "\x95" => [76, "\xf3e"], "\x96" => [104, "\xf3e"], "\x97" => [16, "\xf3e"], "\x98" => [94, "\xf3i"], "\x99" => [76, "\xf3i"], "\x9a" => [104, "\xf3i"], "\x9b" => [16, "\xf3i"], "\x9c" => [94, "\xf3o"], "\x9d" => [76, "\xf3o"], "\x9e" => [104, "\xf3o"], "\x9f" => [16, "\xf3o"], "\xa0" => [94, "\xf3s"], "\xa1" => [76, "\xf3s"], "\xa2" => [104, "\xf3s"], "\xa3" => [16, "\xf3s"], "\xa4" => [94, "\xf3t"], "\xa5" => [76, "\xf3t"], "\xa6" => [104, "\xf3t"], "\xa7" => [16, "\xf3t"], "\xa8" => [77, "\xf3 "], "\xa9" => [18, "\xf3 "], "\xaa" => [77, "\xf3%"], "\xab" => [18, "\xf3%"], "\xac" => [77, "\xf3-"], "\xad" => [18, "\xf3-"], "\xae" => [77, "\xf3."], "\xaf" => [18, "\xf3."], "\xb0" => [77, "\xf3/"], "\xb1" => [18, "\xf3/"], "\xb2" => [77, "\xf33"], "\xb3" => [18, "\xf33"], "\xb4" => [77, "\xf34"], "\xb5" => [18, "\xf34"], "\xb6" => [77, "\xf35"], "\xb7" => [18, "\xf35"], "\xb8" => [77, "\xf36"], "\xb9" => [18, "\xf36"], "\xba" => [77, "\xf37"], "\xbb" => [18, "\xf37"], "\xbc" => [77, "\xf38"], "\xbd" => [18, "\xf38"], "\xbe" => [77, "\xf39"], "\xbf" => [18, "\xf39"], "\xc0" => [77, "\xf3="], "\xc1" => [18, "\xf3="], "\xc2" => [77, "\xf3A"], "\xc3" => [18, "\xf3A"], "\xc4" => [77, "\xf3_"], "\xc5" => [18, "\xf3_"], "\xc6" => [77, "\xf3b"], "\xc7" => [18, "\xf3b"], "\xc8" => [77, "\xf3d"], "\xc9" => [18, "\xf3d"], "\xca" => [77, "\xf3f"], "\xcb" => [18, "\xf3f"], "\xcc" => [77, "\xf3g"], "\xcd" => [18, "\xf3g"], "\xce" => [77, "\xf3h"], "\xcf" => [18, "\xf3h"], "\xd0" => [77, "\xf3l"], "\xd1" => [18, "\xf3l"], "\xd2" => [77, "\xf3m"], "\xd3" => [18, "\xf3m"], "\xd4" => [77, "\xf3n"], "\xd5" => [18, "\xf3n"], "\xd6" => [77, "\xf3p"], "\xd7" => [18, "\xf3p"], "\xd8" => [77, "\xf3r"], "\xd9" => [18, "\xf3r"], "\xda" => [77, "\xf3u"], "\xdb" => [18, "\xf3u"], "\xdc" => [0, "\xf3:"], "\xdd" => [0, "\xf3B"], "\xde" => [0, "\xf3C"], "\xdf" => [0, "\xf3D"], "\xe0" => [0, "\xf3E"], "\xe1" => [0, "\xf3F"], "\xe2" => [0, "\xf3G"], "\xe3" => [0, "\xf3H"], "\xe4" => [0, "\xf3I"], "\xe5" => [0, "\xf3J"], "\xe6" => [0, "\xf3K"], "\xe7" => [0, "\xf3L"], "\xe8" => [0, "\xf3M"], "\xe9" => [0, "\xf3N"], "\xea" => [0, "\xf3O"], "\xeb" => [0, "\xf3P"], "\xec" => [0, "\xf3Q"], "\xed" => [0, "\xf3R"], "\xee" => [0, "\xf3S"], "\xef" => [0, "\xf3T"], "\xf0" => [0, "\xf3U"], "\xf1" => [0, "\xf3V"], "\xf2" => [0, "\xf3W"], "\xf3" => [0, "\xf3Y"], "\xf4" => [0, "\xf3j"], "\xf5" => [0, "\xf3k"], "\xf6" => [0, "\xf3q"], "\xf7" => [0, "\xf3v"], "\xf8" => [0, "\xf3w"], "\xf9" => [0, "\xf3x"], "\xfa" => [0, "\xf3y"], "\xfb" => [0, "\xf3z"], "\xfc" => [82, "\xf3"], "\xfd" => [87, "\xf3"], "\xfe" => [130, "\xf3"], "\xff" => [9, "\xf3"]], ["\x00" => [0, "\xf50"], "\x01" => [0, "\xf51"], "\x02" => [0, "\xf52"], "\x03" => [0, "\xf5a"], "\x04" => [0, "\xf5c"], "\x05" => [0, "\xf5e"], "\x06" => [0, "\xf5i"], "\x07" => [0, "\xf5o"], "\x08" => [0, "\xf5s"], "\t" => [0, "\xf5t"], "\n" => [73, "\xf5"], "\v" => [88, "\xf5"], "\f" => [89, "\xf5"], "\r" => [96, "\xf5"], "\x0e" => [97, "\xf5"], "\x0f" => [99, "\xf5"], "\x10" => [106, "\xf5"], "\x11" => [136, "\xf5"], "\x12" => [139, "\xf5"], "\x13" => [141, "\xf5"], "\x14" => [145, "\xf5"], "\x15" => [147, "\xf5"], "\x16" => [149, "\xf5"], "\x17" => [101, "\xf5"], "\x18" => [112, "\xf5"], "\x19" => [117, "\xf5"], "\x1a" => [120, "\xf5"], "\x1b" => [124, "\xf5"], "\x1c" => [127, "\xf5"], "\x1d" => [144, "\xf5"], "\x1e" => [152, "\xf5"], "\x1f" => [11, "\xf5"], " " => [0, "\xf60"], "!" => [0, "\xf61"], "\"" => [0, "\xf62"], "#" => [0, "\xf6a"], "\$" => [0, "\xf6c"], "%" => [0, "\xf6e"], "&" => [0, "\xf6i"], "'" => [0, "\xf6o"], "(" => [0, "\xf6s"], ")" => [0, "\xf6t"], "*" => [73, "\xf6"], "+" => [88, "\xf6"], "," => [89, "\xf6"], "-" => [96, "\xf6"], "." => [97, "\xf6"], "/" => [99, "\xf6"], [106, "\xf6"], [136, "\xf6"], [139, "\xf6"], [141, "\xf6"], [145, "\xf6"], [147, "\xf6"], [149, "\xf6"], [101, "\xf6"], [112, "\xf6"], [117, "\xf6"], ":" => [120, "\xf6"], ";" => [124, "\xf6"], "<" => [127, "\xf6"], "=" => [144, "\xf6"], ">" => [152, "\xf6"], "?" => [11, "\xf6"], "@" => [0, "\xf70"], "A" => [0, "\xf71"], "B" => [0, "\xf72"], "C" => [0, "\xf7a"], "D" => [0, "\xf7c"], "E" => [0, "\xf7e"], "F" => [0, "\xf7i"], "G" => [0, "\xf7o"], "H" => [0, "\xf7s"], "I" => [0, "\xf7t"], "J" => [73, "\xf7"], "K" => [88, "\xf7"], "L" => [89, "\xf7"], "M" => [96, "\xf7"], "N" => [97, "\xf7"], "O" => [99, "\xf7"], "P" => [106, "\xf7"], "Q" => [136, "\xf7"], "R" => [139, "\xf7"], "S" => [141, "\xf7"], "T" => [145, "\xf7"], "U" => [147, "\xf7"], "V" => [149, "\xf7"], "W" => [101, "\xf7"], "X" => [112, "\xf7"], "Y" => [117, "\xf7"], "Z" => [120, "\xf7"], "[" => [124, "\xf7"], "\\" => [127, "\xf7"], "]" => [144, "\xf7"], "^" => [152, "\xf7"], "_" => [11, "\xf7"], "`" => [0, "\xf80"], "a" => [0, "\xf81"], "b" => [0, "\xf82"], "c" => [0, "\xf8a"], "d" => [0, "\xf8c"], "e" => [0, "\xf8e"], "f" => [0, "\xf8i"], "g" => [0, "\xf8o"], "h" => [0, "\xf8s"], "i" => [0, "\xf8t"], "j" => [73, "\xf8"], "k" => [88, "\xf8"], "l" => [89, "\xf8"], "m" => [96, "\xf8"], "n" => [97, "\xf8"], "o" => [99, "\xf8"], "p" => [106, "\xf8"], "q" => [136, "\xf8"], "r" => [139, "\xf8"], "s" => [141, "\xf8"], "t" => [145, "\xf8"], "u" => [147, "\xf8"], "v" => [149, "\xf8"], "w" => [101, "\xf8"], "x" => [112, "\xf8"], "y" => [117, "\xf8"], "z" => [120, "\xf8"], "{" => [124, "\xf8"], "|" => [127, "\xf8"], "}" => [144, "\xf8"], "~" => [152, "\xf8"], "" => [11, "\xf8"], "\x80" => [0, "\xfa0"], "\x81" => [0, "\xfa1"], "\x82" => [0, "\xfa2"], "\x83" => [0, "\xfaa"], "\x84" => [0, "\xfac"], "\x85" => [0, "\xfae"], "\x86" => [0, "\xfai"], "\x87" => [0, "\xfao"], "\x88" => [0, "\xfas"], "\x89" => [0, "\xfat"], "\x8a" => [73, "\xfa"], "\x8b" => [88, "\xfa"], "\x8c" => [89, "\xfa"], "\x8d" => [96, "\xfa"], "\x8e" => [97, "\xfa"], "\x8f" => [99, "\xfa"], "\x90" => [106, "\xfa"], "\x91" => [136, "\xfa"], "\x92" => [139, "\xfa"], "\x93" => [141, "\xfa"], "\x94" => [145, "\xfa"], "\x95" => [147, "\xfa"], "\x96" => [149, "\xfa"], "\x97" => [101, "\xfa"], "\x98" => [112, "\xfa"], "\x99" => [117, "\xfa"], "\x9a" => [120, "\xfa"], "\x9b" => [124, "\xfa"], "\x9c" => [127, "\xfa"], "\x9d" => [144, "\xfa"], "\x9e" => [152, "\xfa"], "\x9f" => [11, "\xfa"], "\xa0" => [0, "\xfb0"], "\xa1" => [0, "\xfb1"], "\xa2" => [0, "\xfb2"], "\xa3" => [0, "\xfba"], "\xa4" => [0, "\xfbc"], "\xa5" => [0, "\xfbe"], "\xa6" => [0, "\xfbi"], "\xa7" => [0, "\xfbo"], "\xa8" => [0, "\xfbs"], "\xa9" => [0, "\xfbt"], "\xaa" => [73, "\xfb"], "\xab" => [88, "\xfb"], "\xac" => [89, "\xfb"], "\xad" => [96, "\xfb"], "\xae" => [97, "\xfb"], "\xaf" => [99, "\xfb"], "\xb0" => [106, "\xfb"], "\xb1" => [136, "\xfb"], "\xb2" => [139, "\xfb"], "\xb3" => [141, "\xfb"], "\xb4" => [145, "\xfb"], "\xb5" => [147, "\xfb"], "\xb6" => [149, "\xfb"], "\xb7" => [101, "\xfb"], "\xb8" => [112, "\xfb"], "\xb9" => [117, "\xfb"], "\xba" => [120, "\xfb"], "\xbb" => [124, "\xfb"], "\xbc" => [127, "\xfb"], "\xbd" => [144, "\xfb"], "\xbe" => [152, "\xfb"], "\xbf" => [11, "\xfb"], "\xc0" => [0, "\xfc0"], "\xc1" => [0, "\xfc1"], "\xc2" => [0, "\xfc2"], "\xc3" => [0, "\xfca"], "\xc4" => [0, "\xfcc"], "\xc5" => [0, "\xfce"], "\xc6" => [0, "\xfci"], "\xc7" => [0, "\xfco"], "\xc8" => [0, "\xfcs"], "\xc9" => [0, "\xfct"], "\xca" => [73, "\xfc"], "\xcb" => [88, "\xfc"], "\xcc" => [89, "\xfc"], "\xcd" => [96, "\xfc"], "\xce" => [97, "\xfc"], "\xcf" => [99, "\xfc"], "\xd0" => [106, "\xfc"], "\xd1" => [136, "\xfc"], "\xd2" => [139, "\xfc"], "\xd3" => [141, "\xfc"], "\xd4" => [145, "\xfc"], "\xd5" => [147, "\xfc"], "\xd6" => [149, "\xfc"], "\xd7" => [101, "\xfc"], "\xd8" => [112, "\xfc"], "\xd9" => [117, "\xfc"], "\xda" => [120, "\xfc"], "\xdb" => [124, "\xfc"], "\xdc" => [127, "\xfc"], "\xdd" => [144, "\xfc"], "\xde" => [152, "\xfc"], "\xdf" => [11, "\xfc"], "\xe0" => [0, "\xfd0"], "\xe1" => [0, "\xfd1"], "\xe2" => [0, "\xfd2"], "\xe3" => [0, "\xfda"], "\xe4" => [0, "\xfdc"], "\xe5" => [0, "\xfde"], "\xe6" => [0, "\xfdi"], "\xe7" => [0, "\xfdo"], "\xe8" => [0, "\xfds"], "\xe9" => [0, "\xfdt"], "\xea" => [73, "\xfd"], "\xeb" => [88, "\xfd"], "\xec" => [89, "\xfd"], "\xed" => [96, "\xfd"], "\xee" => [97, "\xfd"], "\xef" => [99, "\xfd"], "\xf0" => [106, "\xfd"], "\xf1" => [136, "\xfd"], "\xf2" => [139, "\xfd"], "\xf3" => [141, "\xfd"], "\xf4" => [145, "\xfd"], "\xf5" => [147, "\xfd"], "\xf6" => [149, "\xfd"], "\xf7" => [101, "\xfd"], "\xf8" => [112, "\xfd"], "\xf9" => [117, "\xfd"], "\xfa" => [120, "\xfd"], "\xfb" => [124, "\xfd"], "\xfc" => [127, "\xfd"], "\xfd" => [144, "\xfd"], "\xfe" => [152, "\xfd"], "\xff" => [11, "\xfd"]], ["\x00" => [94, "\xf50"], "\x01" => [76, "\xf50"], "\x02" => [104, "\xf50"], "\x03" => [16, "\xf50"], "\x04" => [94, "\xf51"], "\x05" => [76, "\xf51"], "\x06" => [104, "\xf51"], "\x07" => [16, "\xf51"], "\x08" => [94, "\xf52"], "\t" => [76, "\xf52"], "\n" => [104, "\xf52"], "\v" => [16, "\xf52"], "\f" => [94, "\xf5a"], "\r" => [76, "\xf5a"], "\x0e" => [104, "\xf5a"], "\x0f" => [16, "\xf5a"], "\x10" => [94, "\xf5c"], "\x11" => [76, "\xf5c"], "\x12" => [104, "\xf5c"], "\x13" => [16, "\xf5c"], "\x14" => [94, "\xf5e"], "\x15" => [76, "\xf5e"], "\x16" => [104, "\xf5e"], "\x17" => [16, "\xf5e"], "\x18" => [94, "\xf5i"], "\x19" => [76, "\xf5i"], "\x1a" => [104, "\xf5i"], "\x1b" => [16, "\xf5i"], "\x1c" => [94, "\xf5o"], "\x1d" => [76, "\xf5o"], "\x1e" => [104, "\xf5o"], "\x1f" => [16, "\xf5o"], " " => [94, "\xf5s"], "!" => [76, "\xf5s"], "\"" => [104, "\xf5s"], "#" => [16, "\xf5s"], "\$" => [94, "\xf5t"], "%" => [76, "\xf5t"], "&" => [104, "\xf5t"], "'" => [16, "\xf5t"], "(" => [77, "\xf5 "], ")" => [18, "\xf5 "], "*" => [77, "\xf5%"], "+" => [18, "\xf5%"], "," => [77, "\xf5-"], "-" => [18, "\xf5-"], "." => [77, "\xf5."], "/" => [18, "\xf5."], [77, "\xf5/"], [18, "\xf5/"], [77, "\xf53"], [18, "\xf53"], [77, "\xf54"], [18, "\xf54"], [77, "\xf55"], [18, "\xf55"], [77, "\xf56"], [18, "\xf56"], ":" => [77, "\xf57"], ";" => [18, "\xf57"], "<" => [77, "\xf58"], "=" => [18, "\xf58"], ">" => [77, "\xf59"], "?" => [18, "\xf59"], "@" => [77, "\xf5="], "A" => [18, "\xf5="], "B" => [77, "\xf5A"], "C" => [18, "\xf5A"], "D" => [77, "\xf5_"], "E" => [18, "\xf5_"], "F" => [77, "\xf5b"], "G" => [18, "\xf5b"], "H" => [77, "\xf5d"], "I" => [18, "\xf5d"], "J" => [77, "\xf5f"], "K" => [18, "\xf5f"], "L" => [77, "\xf5g"], "M" => [18, "\xf5g"], "N" => [77, "\xf5h"], "O" => [18, "\xf5h"], "P" => [77, "\xf5l"], "Q" => [18, "\xf5l"], "R" => [77, "\xf5m"], "S" => [18, "\xf5m"], "T" => [77, "\xf5n"], "U" => [18, "\xf5n"], "V" => [77, "\xf5p"], "W" => [18, "\xf5p"], "X" => [77, "\xf5r"], "Y" => [18, "\xf5r"], "Z" => [77, "\xf5u"], "[" => [18, "\xf5u"], "\\" => [0, "\xf5:"], "]" => [0, "\xf5B"], "^" => [0, "\xf5C"], "_" => [0, "\xf5D"], "`" => [0, "\xf5E"], "a" => [0, "\xf5F"], "b" => [0, "\xf5G"], "c" => [0, "\xf5H"], "d" => [0, "\xf5I"], "e" => [0, "\xf5J"], "f" => [0, "\xf5K"], "g" => [0, "\xf5L"], "h" => [0, "\xf5M"], "i" => [0, "\xf5N"], "j" => [0, "\xf5O"], "k" => [0, "\xf5P"], "l" => [0, "\xf5Q"], "m" => [0, "\xf5R"], "n" => [0, "\xf5S"], "o" => [0, "\xf5T"], "p" => [0, "\xf5U"], "q" => [0, "\xf5V"], "r" => [0, "\xf5W"], "s" => [0, "\xf5Y"], "t" => [0, "\xf5j"], "u" => [0, "\xf5k"], "v" => [0, "\xf5q"], "w" => [0, "\xf5v"], "x" => [0, "\xf5w"], "y" => [0, "\xf5x"], "z" => [0, "\xf5y"], "{" => [0, "\xf5z"], "|" => [82, "\xf5"], "}" => [87, "\xf5"], "~" => [130, "\xf5"], "" => [9, "\xf5"], "\x80" => [94, "\xf60"], "\x81" => [76, "\xf60"], "\x82" => [104, "\xf60"], "\x83" => [16, "\xf60"], "\x84" => [94, "\xf61"], "\x85" => [76, "\xf61"], "\x86" => [104, "\xf61"], "\x87" => [16, "\xf61"], "\x88" => [94, "\xf62"], "\x89" => [76, "\xf62"], "\x8a" => [104, "\xf62"], "\x8b" => [16, "\xf62"], "\x8c" => [94, "\xf6a"], "\x8d" => [76, "\xf6a"], "\x8e" => [104, "\xf6a"], "\x8f" => [16, "\xf6a"], "\x90" => [94, "\xf6c"], "\x91" => [76, "\xf6c"], "\x92" => [104, "\xf6c"], "\x93" => [16, "\xf6c"], "\x94" => [94, "\xf6e"], "\x95" => [76, "\xf6e"], "\x96" => [104, "\xf6e"], "\x97" => [16, "\xf6e"], "\x98" => [94, "\xf6i"], "\x99" => [76, "\xf6i"], "\x9a" => [104, "\xf6i"], "\x9b" => [16, "\xf6i"], "\x9c" => [94, "\xf6o"], "\x9d" => [76, "\xf6o"], "\x9e" => [104, "\xf6o"], "\x9f" => [16, "\xf6o"], "\xa0" => [94, "\xf6s"], "\xa1" => [76, "\xf6s"], "\xa2" => [104, "\xf6s"], "\xa3" => [16, "\xf6s"], "\xa4" => [94, "\xf6t"], "\xa5" => [76, "\xf6t"], "\xa6" => [104, "\xf6t"], "\xa7" => [16, "\xf6t"], "\xa8" => [77, "\xf6 "], "\xa9" => [18, "\xf6 "], "\xaa" => [77, "\xf6%"], "\xab" => [18, "\xf6%"], "\xac" => [77, "\xf6-"], "\xad" => [18, "\xf6-"], "\xae" => [77, "\xf6."], "\xaf" => [18, "\xf6."], "\xb0" => [77, "\xf6/"], "\xb1" => [18, "\xf6/"], "\xb2" => [77, "\xf63"], "\xb3" => [18, "\xf63"], "\xb4" => [77, "\xf64"], "\xb5" => [18, "\xf64"], "\xb6" => [77, "\xf65"], "\xb7" => [18, "\xf65"], "\xb8" => [77, "\xf66"], "\xb9" => [18, "\xf66"], "\xba" => [77, "\xf67"], "\xbb" => [18, "\xf67"], "\xbc" => [77, "\xf68"], "\xbd" => [18, "\xf68"], "\xbe" => [77, "\xf69"], "\xbf" => [18, "\xf69"], "\xc0" => [77, "\xf6="], "\xc1" => [18, "\xf6="], "\xc2" => [77, "\xf6A"], "\xc3" => [18, "\xf6A"], "\xc4" => [77, "\xf6_"], "\xc5" => [18, "\xf6_"], "\xc6" => [77, "\xf6b"], "\xc7" => [18, "\xf6b"], "\xc8" => [77, "\xf6d"], "\xc9" => [18, "\xf6d"], "\xca" => [77, "\xf6f"], "\xcb" => [18, "\xf6f"], "\xcc" => [77, "\xf6g"], "\xcd" => [18, "\xf6g"], "\xce" => [77, "\xf6h"], "\xcf" => [18, "\xf6h"], "\xd0" => [77, "\xf6l"], "\xd1" => [18, "\xf6l"], "\xd2" => [77, "\xf6m"], "\xd3" => [18, "\xf6m"], "\xd4" => [77, "\xf6n"], "\xd5" => [18, "\xf6n"], "\xd6" => [77, "\xf6p"], "\xd7" => [18, "\xf6p"], "\xd8" => [77, "\xf6r"], "\xd9" => [18, "\xf6r"], "\xda" => [77, "\xf6u"], "\xdb" => [18, "\xf6u"], "\xdc" => [0, "\xf6:"], "\xdd" => [0, "\xf6B"], "\xde" => [0, "\xf6C"], "\xdf" => [0, "\xf6D"], "\xe0" => [0, "\xf6E"], "\xe1" => [0, "\xf6F"], "\xe2" => [0, "\xf6G"], "\xe3" => [0, "\xf6H"], "\xe4" => [0, "\xf6I"], "\xe5" => [0, "\xf6J"], "\xe6" => [0, "\xf6K"], "\xe7" => [0, "\xf6L"], "\xe8" => [0, "\xf6M"], "\xe9" => [0, "\xf6N"], "\xea" => [0, "\xf6O"], "\xeb" => [0, "\xf6P"], "\xec" => [0, "\xf6Q"], "\xed" => [0, "\xf6R"], "\xee" => [0, "\xf6S"], "\xef" => [0, "\xf6T"], "\xf0" => [0, "\xf6U"], "\xf1" => [0, "\xf6V"], "\xf2" => [0, "\xf6W"], "\xf3" => [0, "\xf6Y"], "\xf4" => [0, "\xf6j"], "\xf5" => [0, "\xf6k"], "\xf6" => [0, "\xf6q"], "\xf7" => [0, "\xf6v"], "\xf8" => [0, "\xf6w"], "\xf9" => [0, "\xf6x"], "\xfa" => [0, "\xf6y"], "\xfb" => [0, "\xf6z"], "\xfc" => [82, "\xf6"], "\xfd" => [87, "\xf6"], "\xfe" => [130, "\xf6"], "\xff" => [9, "\xf6"]], ["\x00" => [77, "\xf50"], "\x01" => [18, "\xf50"], "\x02" => [77, "\xf51"], "\x03" => [18, "\xf51"], "\x04" => [77, "\xf52"], "\x05" => [18, "\xf52"], "\x06" => [77, "\xf5a"], "\x07" => [18, "\xf5a"], "\x08" => [77, "\xf5c"], "\t" => [18, "\xf5c"], "\n" => [77, "\xf5e"], "\v" => [18, "\xf5e"], "\f" => [77, "\xf5i"], "\r" => [18, "\xf5i"], "\x0e" => [77, "\xf5o"], "\x0f" => [18, "\xf5o"], "\x10" => [77, "\xf5s"], "\x11" => [18, "\xf5s"], "\x12" => [77, "\xf5t"], "\x13" => [18, "\xf5t"], "\x14" => [0, "\xf5 "], "\x15" => [0, "\xf5%"], "\x16" => [0, "\xf5-"], "\x17" => [0, "\xf5."], "\x18" => [0, "\xf5/"], "\x19" => [0, "\xf53"], "\x1a" => [0, "\xf54"], "\x1b" => [0, "\xf55"], "\x1c" => [0, "\xf56"], "\x1d" => [0, "\xf57"], "\x1e" => [0, "\xf58"], "\x1f" => [0, "\xf59"], " " => [0, "\xf5="], "!" => [0, "\xf5A"], "\"" => [0, "\xf5_"], "#" => [0, "\xf5b"], "\$" => [0, "\xf5d"], "%" => [0, "\xf5f"], "&" => [0, "\xf5g"], "'" => [0, "\xf5h"], "(" => [0, "\xf5l"], ")" => [0, "\xf5m"], "*" => [0, "\xf5n"], "+" => [0, "\xf5p"], "," => [0, "\xf5r"], "-" => [0, "\xf5u"], "." => [100, "\xf5"], "/" => [110, "\xf5"], [111, "\xf5"], [115, "\xf5"], [116, "\xf5"], [118, "\xf5"], [119, "\xf5"], [122, "\xf5"], [123, "\xf5"], [125, "\xf5"], [126, "\xf5"], [129, "\xf5"], ":" => [143, "\xf5"], ";" => [148, "\xf5"], "<" => [151, "\xf5"], "=" => [153, "\xf5"], ">" => [83, "\xf5"], "?" => [10, "\xf5"], "@" => [77, "\xf60"], "A" => [18, "\xf60"], "B" => [77, "\xf61"], "C" => [18, "\xf61"], "D" => [77, "\xf62"], "E" => [18, "\xf62"], "F" => [77, "\xf6a"], "G" => [18, "\xf6a"], "H" => [77, "\xf6c"], "I" => [18, "\xf6c"], "J" => [77, "\xf6e"], "K" => [18, "\xf6e"], "L" => [77, "\xf6i"], "M" => [18, "\xf6i"], "N" => [77, "\xf6o"], "O" => [18, "\xf6o"], "P" => [77, "\xf6s"], "Q" => [18, "\xf6s"], "R" => [77, "\xf6t"], "S" => [18, "\xf6t"], "T" => [0, "\xf6 "], "U" => [0, "\xf6%"], "V" => [0, "\xf6-"], "W" => [0, "\xf6."], "X" => [0, "\xf6/"], "Y" => [0, "\xf63"], "Z" => [0, "\xf64"], "[" => [0, "\xf65"], "\\" => [0, "\xf66"], "]" => [0, "\xf67"], "^" => [0, "\xf68"], "_" => [0, "\xf69"], "`" => [0, "\xf6="], "a" => [0, "\xf6A"], "b" => [0, "\xf6_"], "c" => [0, "\xf6b"], "d" => [0, "\xf6d"], "e" => [0, "\xf6f"], "f" => [0, "\xf6g"], "g" => [0, "\xf6h"], "h" => [0, "\xf6l"], "i" => [0, "\xf6m"], "j" => [0, "\xf6n"], "k" => [0, "\xf6p"], "l" => [0, "\xf6r"], "m" => [0, "\xf6u"], "n" => [100, "\xf6"], "o" => [110, "\xf6"], "p" => [111, "\xf6"], "q" => [115, "\xf6"], "r" => [116, "\xf6"], "s" => [118, "\xf6"], "t" => [119, "\xf6"], "u" => [122, "\xf6"], "v" => [123, "\xf6"], "w" => [125, "\xf6"], "x" => [126, "\xf6"], "y" => [129, "\xf6"], "z" => [143, "\xf6"], "{" => [148, "\xf6"], "|" => [151, "\xf6"], "}" => [153, "\xf6"], "~" => [83, "\xf6"], "" => [10, "\xf6"], "\x80" => [77, "\xf70"], "\x81" => [18, "\xf70"], "\x82" => [77, "\xf71"], "\x83" => [18, "\xf71"], "\x84" => [77, "\xf72"], "\x85" => [18, "\xf72"], "\x86" => [77, "\xf7a"], "\x87" => [18, "\xf7a"], "\x88" => [77, "\xf7c"], "\x89" => [18, "\xf7c"], "\x8a" => [77, "\xf7e"], "\x8b" => [18, "\xf7e"], "\x8c" => [77, "\xf7i"], "\x8d" => [18, "\xf7i"], "\x8e" => [77, "\xf7o"], "\x8f" => [18, "\xf7o"], "\x90" => [77, "\xf7s"], "\x91" => [18, "\xf7s"], "\x92" => [77, "\xf7t"], "\x93" => [18, "\xf7t"], "\x94" => [0, "\xf7 "], "\x95" => [0, "\xf7%"], "\x96" => [0, "\xf7-"], "\x97" => [0, "\xf7."], "\x98" => [0, "\xf7/"], "\x99" => [0, "\xf73"], "\x9a" => [0, "\xf74"], "\x9b" => [0, "\xf75"], "\x9c" => [0, "\xf76"], "\x9d" => [0, "\xf77"], "\x9e" => [0, "\xf78"], "\x9f" => [0, "\xf79"], "\xa0" => [0, "\xf7="], "\xa1" => [0, "\xf7A"], "\xa2" => [0, "\xf7_"], "\xa3" => [0, "\xf7b"], "\xa4" => [0, "\xf7d"], "\xa5" => [0, "\xf7f"], "\xa6" => [0, "\xf7g"], "\xa7" => [0, "\xf7h"], "\xa8" => [0, "\xf7l"], "\xa9" => [0, "\xf7m"], "\xaa" => [0, "\xf7n"], "\xab" => [0, "\xf7p"], "\xac" => [0, "\xf7r"], "\xad" => [0, "\xf7u"], "\xae" => [100, "\xf7"], "\xaf" => [110, "\xf7"], "\xb0" => [111, "\xf7"], "\xb1" => [115, "\xf7"], "\xb2" => [116, "\xf7"], "\xb3" => [118, "\xf7"], "\xb4" => [119, "\xf7"], "\xb5" => [122, "\xf7"], "\xb6" => [123, "\xf7"], "\xb7" => [125, "\xf7"], "\xb8" => [126, "\xf7"], "\xb9" => [129, "\xf7"], "\xba" => [143, "\xf7"], "\xbb" => [148, "\xf7"], "\xbc" => [151, "\xf7"], "\xbd" => [153, "\xf7"], "\xbe" => [83, "\xf7"], "\xbf" => [10, "\xf7"], "\xc0" => [77, "\xf80"], "\xc1" => [18, "\xf80"], "\xc2" => [77, "\xf81"], "\xc3" => [18, "\xf81"], "\xc4" => [77, "\xf82"], "\xc5" => [18, "\xf82"], "\xc6" => [77, "\xf8a"], "\xc7" => [18, "\xf8a"], "\xc8" => [77, "\xf8c"], "\xc9" => [18, "\xf8c"], "\xca" => [77, "\xf8e"], "\xcb" => [18, "\xf8e"], "\xcc" => [77, "\xf8i"], "\xcd" => [18, "\xf8i"], "\xce" => [77, "\xf8o"], "\xcf" => [18, "\xf8o"], "\xd0" => [77, "\xf8s"], "\xd1" => [18, "\xf8s"], "\xd2" => [77, "\xf8t"], "\xd3" => [18, "\xf8t"], "\xd4" => [0, "\xf8 "], "\xd5" => [0, "\xf8%"], "\xd6" => [0, "\xf8-"], "\xd7" => [0, "\xf8."], "\xd8" => [0, "\xf8/"], "\xd9" => [0, "\xf83"], "\xda" => [0, "\xf84"], "\xdb" => [0, "\xf85"], "\xdc" => [0, "\xf86"], "\xdd" => [0, "\xf87"], "\xde" => [0, "\xf88"], "\xdf" => [0, "\xf89"], "\xe0" => [0, "\xf8="], "\xe1" => [0, "\xf8A"], "\xe2" => [0, "\xf8_"], "\xe3" => [0, "\xf8b"], "\xe4" => [0, "\xf8d"], "\xe5" => [0, "\xf8f"], "\xe6" => [0, "\xf8g"], "\xe7" => [0, "\xf8h"], "\xe8" => [0, "\xf8l"], "\xe9" => [0, "\xf8m"], "\xea" => [0, "\xf8n"], "\xeb" => [0, "\xf8p"], "\xec" => [0, "\xf8r"], "\xed" => [0, "\xf8u"], "\xee" => [100, "\xf8"], "\xef" => [110, "\xf8"], "\xf0" => [111, "\xf8"], "\xf1" => [115, "\xf8"], "\xf2" => [116, "\xf8"], "\xf3" => [118, "\xf8"], "\xf4" => [119, "\xf8"], "\xf5" => [122, "\xf8"], "\xf6" => [123, "\xf8"], "\xf7" => [125, "\xf8"], "\xf8" => [126, "\xf8"], "\xf9" => [129, "\xf8"], "\xfa" => [143, "\xf8"], "\xfb" => [148, "\xf8"], "\xfc" => [151, "\xf8"], "\xfd" => [153, "\xf8"], "\xfe" => [83, "\xf8"], "\xff" => [10, "\xf8"]], ["\x00" => [94, "\xf70"], "\x01" => [76, "\xf70"], "\x02" => [104, "\xf70"], "\x03" => [16, "\xf70"], "\x04" => [94, "\xf71"], "\x05" => [76, "\xf71"], "\x06" => [104, "\xf71"], "\x07" => [16, "\xf71"], "\x08" => [94, "\xf72"], "\t" => [76, "\xf72"], "\n" => [104, "\xf72"], "\v" => [16, "\xf72"], "\f" => [94, "\xf7a"], "\r" => [76, "\xf7a"], "\x0e" => [104, "\xf7a"], "\x0f" => [16, "\xf7a"], "\x10" => [94, "\xf7c"], "\x11" => [76, "\xf7c"], "\x12" => [104, "\xf7c"], "\x13" => [16, "\xf7c"], "\x14" => [94, "\xf7e"], "\x15" => [76, "\xf7e"], "\x16" => [104, "\xf7e"], "\x17" => [16, "\xf7e"], "\x18" => [94, "\xf7i"], "\x19" => [76, "\xf7i"], "\x1a" => [104, "\xf7i"], "\x1b" => [16, "\xf7i"], "\x1c" => [94, "\xf7o"], "\x1d" => [76, "\xf7o"], "\x1e" => [104, "\xf7o"], "\x1f" => [16, "\xf7o"], " " => [94, "\xf7s"], "!" => [76, "\xf7s"], "\"" => [104, "\xf7s"], "#" => [16, "\xf7s"], "\$" => [94, "\xf7t"], "%" => [76, "\xf7t"], "&" => [104, "\xf7t"], "'" => [16, "\xf7t"], "(" => [77, "\xf7 "], ")" => [18, "\xf7 "], "*" => [77, "\xf7%"], "+" => [18, "\xf7%"], "," => [77, "\xf7-"], "-" => [18, "\xf7-"], "." => [77, "\xf7."], "/" => [18, "\xf7."], [77, "\xf7/"], [18, "\xf7/"], [77, "\xf73"], [18, "\xf73"], [77, "\xf74"], [18, "\xf74"], [77, "\xf75"], [18, "\xf75"], [77, "\xf76"], [18, "\xf76"], ":" => [77, "\xf77"], ";" => [18, "\xf77"], "<" => [77, "\xf78"], "=" => [18, "\xf78"], ">" => [77, "\xf79"], "?" => [18, "\xf79"], "@" => [77, "\xf7="], "A" => [18, "\xf7="], "B" => [77, "\xf7A"], "C" => [18, "\xf7A"], "D" => [77, "\xf7_"], "E" => [18, "\xf7_"], "F" => [77, "\xf7b"], "G" => [18, "\xf7b"], "H" => [77, "\xf7d"], "I" => [18, "\xf7d"], "J" => [77, "\xf7f"], "K" => [18, "\xf7f"], "L" => [77, "\xf7g"], "M" => [18, "\xf7g"], "N" => [77, "\xf7h"], "O" => [18, "\xf7h"], "P" => [77, "\xf7l"], "Q" => [18, "\xf7l"], "R" => [77, "\xf7m"], "S" => [18, "\xf7m"], "T" => [77, "\xf7n"], "U" => [18, "\xf7n"], "V" => [77, "\xf7p"], "W" => [18, "\xf7p"], "X" => [77, "\xf7r"], "Y" => [18, "\xf7r"], "Z" => [77, "\xf7u"], "[" => [18, "\xf7u"], "\\" => [0, "\xf7:"], "]" => [0, "\xf7B"], "^" => [0, "\xf7C"], "_" => [0, "\xf7D"], "`" => [0, "\xf7E"], "a" => [0, "\xf7F"], "b" => [0, "\xf7G"], "c" => [0, "\xf7H"], "d" => [0, "\xf7I"], "e" => [0, "\xf7J"], "f" => [0, "\xf7K"], "g" => [0, "\xf7L"], "h" => [0, "\xf7M"], "i" => [0, "\xf7N"], "j" => [0, "\xf7O"], "k" => [0, "\xf7P"], "l" => [0, "\xf7Q"], "m" => [0, "\xf7R"], "n" => [0, "\xf7S"], "o" => [0, "\xf7T"], "p" => [0, "\xf7U"], "q" => [0, "\xf7V"], "r" => [0, "\xf7W"], "s" => [0, "\xf7Y"], "t" => [0, "\xf7j"], "u" => [0, "\xf7k"], "v" => [0, "\xf7q"], "w" => [0, "\xf7v"], "x" => [0, "\xf7w"], "y" => [0, "\xf7x"], "z" => [0, "\xf7y"], "{" => [0, "\xf7z"], "|" => [82, "\xf7"], "}" => [87, "\xf7"], "~" => [130, "\xf7"], "" => [9, "\xf7"], "\x80" => [94, "\xf80"], "\x81" => [76, "\xf80"], "\x82" => [104, "\xf80"], "\x83" => [16, "\xf80"], "\x84" => [94, "\xf81"], "\x85" => [76, "\xf81"], "\x86" => [104, "\xf81"], "\x87" => [16, "\xf81"], "\x88" => [94, "\xf82"], "\x89" => [76, "\xf82"], "\x8a" => [104, "\xf82"], "\x8b" => [16, "\xf82"], "\x8c" => [94, "\xf8a"], "\x8d" => [76, "\xf8a"], "\x8e" => [104, "\xf8a"], "\x8f" => [16, "\xf8a"], "\x90" => [94, "\xf8c"], "\x91" => [76, "\xf8c"], "\x92" => [104, "\xf8c"], "\x93" => [16, "\xf8c"], "\x94" => [94, "\xf8e"], "\x95" => [76, "\xf8e"], "\x96" => [104, "\xf8e"], "\x97" => [16, "\xf8e"], "\x98" => [94, "\xf8i"], "\x99" => [76, "\xf8i"], "\x9a" => [104, "\xf8i"], "\x9b" => [16, "\xf8i"], "\x9c" => [94, "\xf8o"], "\x9d" => [76, "\xf8o"], "\x9e" => [104, "\xf8o"], "\x9f" => [16, "\xf8o"], "\xa0" => [94, "\xf8s"], "\xa1" => [76, "\xf8s"], "\xa2" => [104, "\xf8s"], "\xa3" => [16, "\xf8s"], "\xa4" => [94, "\xf8t"], "\xa5" => [76, "\xf8t"], "\xa6" => [104, "\xf8t"], "\xa7" => [16, "\xf8t"], "\xa8" => [77, "\xf8 "], "\xa9" => [18, "\xf8 "], "\xaa" => [77, "\xf8%"], "\xab" => [18, "\xf8%"], "\xac" => [77, "\xf8-"], "\xad" => [18, "\xf8-"], "\xae" => [77, "\xf8."], "\xaf" => [18, "\xf8."], "\xb0" => [77, "\xf8/"], "\xb1" => [18, "\xf8/"], "\xb2" => [77, "\xf83"], "\xb3" => [18, "\xf83"], "\xb4" => [77, "\xf84"], "\xb5" => [18, "\xf84"], "\xb6" => [77, "\xf85"], "\xb7" => [18, "\xf85"], "\xb8" => [77, "\xf86"], "\xb9" => [18, "\xf86"], "\xba" => [77, "\xf87"], "\xbb" => [18, "\xf87"], "\xbc" => [77, "\xf88"], "\xbd" => [18, "\xf88"], "\xbe" => [77, "\xf89"], "\xbf" => [18, "\xf89"], "\xc0" => [77, "\xf8="], "\xc1" => [18, "\xf8="], "\xc2" => [77, "\xf8A"], "\xc3" => [18, "\xf8A"], "\xc4" => [77, "\xf8_"], "\xc5" => [18, "\xf8_"], "\xc6" => [77, "\xf8b"], "\xc7" => [18, "\xf8b"], "\xc8" => [77, "\xf8d"], "\xc9" => [18, "\xf8d"], "\xca" => [77, "\xf8f"], "\xcb" => [18, "\xf8f"], "\xcc" => [77, "\xf8g"], "\xcd" => [18, "\xf8g"], "\xce" => [77, "\xf8h"], "\xcf" => [18, "\xf8h"], "\xd0" => [77, "\xf8l"], "\xd1" => [18, "\xf8l"], "\xd2" => [77, "\xf8m"], "\xd3" => [18, "\xf8m"], "\xd4" => [77, "\xf8n"], "\xd5" => [18, "\xf8n"], "\xd6" => [77, "\xf8p"], "\xd7" => [18, "\xf8p"], "\xd8" => [77, "\xf8r"], "\xd9" => [18, "\xf8r"], "\xda" => [77, "\xf8u"], "\xdb" => [18, "\xf8u"], "\xdc" => [0, "\xf8:"], "\xdd" => [0, "\xf8B"], "\xde" => [0, "\xf8C"], "\xdf" => [0, "\xf8D"], "\xe0" => [0, "\xf8E"], "\xe1" => [0, "\xf8F"], "\xe2" => [0, "\xf8G"], "\xe3" => [0, "\xf8H"], "\xe4" => [0, "\xf8I"], "\xe5" => [0, "\xf8J"], "\xe6" => [0, "\xf8K"], "\xe7" => [0, "\xf8L"], "\xe8" => [0, "\xf8M"], "\xe9" => [0, "\xf8N"], "\xea" => [0, "\xf8O"], "\xeb" => [0, "\xf8P"], "\xec" => [0, "\xf8Q"], "\xed" => [0, "\xf8R"], "\xee" => [0, "\xf8S"], "\xef" => [0, "\xf8T"], "\xf0" => [0, "\xf8U"], "\xf1" => [0, "\xf8V"], "\xf2" => [0, "\xf8W"], "\xf3" => [0, "\xf8Y"], "\xf4" => [0, "\xf8j"], "\xf5" => [0, "\xf8k"], "\xf6" => [0, "\xf8q"], "\xf7" => [0, "\xf8v"], "\xf8" => [0, "\xf8w"], "\xf9" => [0, "\xf8x"], "\xfa" => [0, "\xf8y"], "\xfb" => [0, "\xf8z"], "\xfc" => [82, "\xf8"], "\xfd" => [87, "\xf8"], "\xfe" => [130, "\xf8"], "\xff" => [9, "\xf8"]], ["\x00" => [94, "\xfa0"], "\x01" => [76, "\xfa0"], "\x02" => [104, "\xfa0"], "\x03" => [16, "\xfa0"], "\x04" => [94, "\xfa1"], "\x05" => [76, "\xfa1"], "\x06" => [104, "\xfa1"], "\x07" => [16, "\xfa1"], "\x08" => [94, "\xfa2"], "\t" => [76, "\xfa2"], "\n" => [104, "\xfa2"], "\v" => [16, "\xfa2"], "\f" => [94, "\xfaa"], "\r" => [76, "\xfaa"], "\x0e" => [104, "\xfaa"], "\x0f" => [16, "\xfaa"], "\x10" => [94, "\xfac"], "\x11" => [76, "\xfac"], "\x12" => [104, "\xfac"], "\x13" => [16, "\xfac"], "\x14" => [94, "\xfae"], "\x15" => [76, "\xfae"], "\x16" => [104, "\xfae"], "\x17" => [16, "\xfae"], "\x18" => [94, "\xfai"], "\x19" => [76, "\xfai"], "\x1a" => [104, "\xfai"], "\x1b" => [16, "\xfai"], "\x1c" => [94, "\xfao"], "\x1d" => [76, "\xfao"], "\x1e" => [104, "\xfao"], "\x1f" => [16, "\xfao"], " " => [94, "\xfas"], "!" => [76, "\xfas"], "\"" => [104, "\xfas"], "#" => [16, "\xfas"], "\$" => [94, "\xfat"], "%" => [76, "\xfat"], "&" => [104, "\xfat"], "'" => [16, "\xfat"], "(" => [77, "\xfa "], ")" => [18, "\xfa "], "*" => [77, "\xfa%"], "+" => [18, "\xfa%"], "," => [77, "\xfa-"], "-" => [18, "\xfa-"], "." => [77, "\xfa."], "/" => [18, "\xfa."], [77, "\xfa/"], [18, "\xfa/"], [77, "\xfa3"], [18, "\xfa3"], [77, "\xfa4"], [18, "\xfa4"], [77, "\xfa5"], [18, "\xfa5"], [77, "\xfa6"], [18, "\xfa6"], ":" => [77, "\xfa7"], ";" => [18, "\xfa7"], "<" => [77, "\xfa8"], "=" => [18, "\xfa8"], ">" => [77, "\xfa9"], "?" => [18, "\xfa9"], "@" => [77, "\xfa="], "A" => [18, "\xfa="], "B" => [77, "\xfaA"], "C" => [18, "\xfaA"], "D" => [77, "\xfa_"], "E" => [18, "\xfa_"], "F" => [77, "\xfab"], "G" => [18, "\xfab"], "H" => [77, "\xfad"], "I" => [18, "\xfad"], "J" => [77, "\xfaf"], "K" => [18, "\xfaf"], "L" => [77, "\xfag"], "M" => [18, "\xfag"], "N" => [77, "\xfah"], "O" => [18, "\xfah"], "P" => [77, "\xfal"], "Q" => [18, "\xfal"], "R" => [77, "\xfam"], "S" => [18, "\xfam"], "T" => [77, "\xfan"], "U" => [18, "\xfan"], "V" => [77, "\xfap"], "W" => [18, "\xfap"], "X" => [77, "\xfar"], "Y" => [18, "\xfar"], "Z" => [77, "\xfau"], "[" => [18, "\xfau"], "\\" => [0, "\xfa:"], "]" => [0, "\xfaB"], "^" => [0, "\xfaC"], "_" => [0, "\xfaD"], "`" => [0, "\xfaE"], "a" => [0, "\xfaF"], "b" => [0, "\xfaG"], "c" => [0, "\xfaH"], "d" => [0, "\xfaI"], "e" => [0, "\xfaJ"], "f" => [0, "\xfaK"], "g" => [0, "\xfaL"], "h" => [0, "\xfaM"], "i" => [0, "\xfaN"], "j" => [0, "\xfaO"], "k" => [0, "\xfaP"], "l" => [0, "\xfaQ"], "m" => [0, "\xfaR"], "n" => [0, "\xfaS"], "o" => [0, "\xfaT"], "p" => [0, "\xfaU"], "q" => [0, "\xfaV"], "r" => [0, "\xfaW"], "s" => [0, "\xfaY"], "t" => [0, "\xfaj"], "u" => [0, "\xfak"], "v" => [0, "\xfaq"], "w" => [0, "\xfav"], "x" => [0, "\xfaw"], "y" => [0, "\xfax"], "z" => [0, "\xfay"], "{" => [0, "\xfaz"], "|" => [82, "\xfa"], "}" => [87, "\xfa"], "~" => [130, "\xfa"], "" => [9, "\xfa"], "\x80" => [94, "\xfb0"], "\x81" => [76, "\xfb0"], "\x82" => [104, "\xfb0"], "\x83" => [16, "\xfb0"], "\x84" => [94, "\xfb1"], "\x85" => [76, "\xfb1"], "\x86" => [104, "\xfb1"], "\x87" => [16, "\xfb1"], "\x88" => [94, "\xfb2"], "\x89" => [76, "\xfb2"], "\x8a" => [104, "\xfb2"], "\x8b" => [16, "\xfb2"], "\x8c" => [94, "\xfba"], "\x8d" => [76, "\xfba"], "\x8e" => [104, "\xfba"], "\x8f" => [16, "\xfba"], "\x90" => [94, "\xfbc"], "\x91" => [76, "\xfbc"], "\x92" => [104, "\xfbc"], "\x93" => [16, "\xfbc"], "\x94" => [94, "\xfbe"], "\x95" => [76, "\xfbe"], "\x96" => [104, "\xfbe"], "\x97" => [16, "\xfbe"], "\x98" => [94, "\xfbi"], "\x99" => [76, "\xfbi"], "\x9a" => [104, "\xfbi"], "\x9b" => [16, "\xfbi"], "\x9c" => [94, "\xfbo"], "\x9d" => [76, "\xfbo"], "\x9e" => [104, "\xfbo"], "\x9f" => [16, "\xfbo"], "\xa0" => [94, "\xfbs"], "\xa1" => [76, "\xfbs"], "\xa2" => [104, "\xfbs"], "\xa3" => [16, "\xfbs"], "\xa4" => [94, "\xfbt"], "\xa5" => [76, "\xfbt"], "\xa6" => [104, "\xfbt"], "\xa7" => [16, "\xfbt"], "\xa8" => [77, "\xfb "], "\xa9" => [18, "\xfb "], "\xaa" => [77, "\xfb%"], "\xab" => [18, "\xfb%"], "\xac" => [77, "\xfb-"], "\xad" => [18, "\xfb-"], "\xae" => [77, "\xfb."], "\xaf" => [18, "\xfb."], "\xb0" => [77, "\xfb/"], "\xb1" => [18, "\xfb/"], "\xb2" => [77, "\xfb3"], "\xb3" => [18, "\xfb3"], "\xb4" => [77, "\xfb4"], "\xb5" => [18, "\xfb4"], "\xb6" => [77, "\xfb5"], "\xb7" => [18, "\xfb5"], "\xb8" => [77, "\xfb6"], "\xb9" => [18, "\xfb6"], "\xba" => [77, "\xfb7"], "\xbb" => [18, "\xfb7"], "\xbc" => [77, "\xfb8"], "\xbd" => [18, "\xfb8"], "\xbe" => [77, "\xfb9"], "\xbf" => [18, "\xfb9"], "\xc0" => [77, "\xfb="], "\xc1" => [18, "\xfb="], "\xc2" => [77, "\xfbA"], "\xc3" => [18, "\xfbA"], "\xc4" => [77, "\xfb_"], "\xc5" => [18, "\xfb_"], "\xc6" => [77, "\xfbb"], "\xc7" => [18, "\xfbb"], "\xc8" => [77, "\xfbd"], "\xc9" => [18, "\xfbd"], "\xca" => [77, "\xfbf"], "\xcb" => [18, "\xfbf"], "\xcc" => [77, "\xfbg"], "\xcd" => [18, "\xfbg"], "\xce" => [77, "\xfbh"], "\xcf" => [18, "\xfbh"], "\xd0" => [77, "\xfbl"], "\xd1" => [18, "\xfbl"], "\xd2" => [77, "\xfbm"], "\xd3" => [18, "\xfbm"], "\xd4" => [77, "\xfbn"], "\xd5" => [18, "\xfbn"], "\xd6" => [77, "\xfbp"], "\xd7" => [18, "\xfbp"], "\xd8" => [77, "\xfbr"], "\xd9" => [18, "\xfbr"], "\xda" => [77, "\xfbu"], "\xdb" => [18, "\xfbu"], "\xdc" => [0, "\xfb:"], "\xdd" => [0, "\xfbB"], "\xde" => [0, "\xfbC"], "\xdf" => [0, "\xfbD"], "\xe0" => [0, "\xfbE"], "\xe1" => [0, "\xfbF"], "\xe2" => [0, "\xfbG"], "\xe3" => [0, "\xfbH"], "\xe4" => [0, "\xfbI"], "\xe5" => [0, "\xfbJ"], "\xe6" => [0, "\xfbK"], "\xe7" => [0, "\xfbL"], "\xe8" => [0, "\xfbM"], "\xe9" => [0, "\xfbN"], "\xea" => [0, "\xfbO"], "\xeb" => [0, "\xfbP"], "\xec" => [0, "\xfbQ"], "\xed" => [0, "\xfbR"], "\xee" => [0, "\xfbS"], "\xef" => [0, "\xfbT"], "\xf0" => [0, "\xfbU"], "\xf1" => [0, "\xfbV"], "\xf2" => [0, "\xfbW"], "\xf3" => [0, "\xfbY"], "\xf4" => [0, "\xfbj"], "\xf5" => [0, "\xfbk"], "\xf6" => [0, "\xfbq"], "\xf7" => [0, "\xfbv"], "\xf8" => [0, "\xfbw"], "\xf9" => [0, "\xfbx"], "\xfa" => [0, "\xfby"], "\xfb" => [0, "\xfbz"], "\xfc" => [82, "\xfb"], "\xfd" => [87, "\xfb"], "\xfe" => [130, "\xfb"], "\xff" => [9, "\xfb"]], ["\x00" => [77, "\xfa0"], "\x01" => [18, "\xfa0"], "\x02" => [77, "\xfa1"], "\x03" => [18, "\xfa1"], "\x04" => [77, "\xfa2"], "\x05" => [18, "\xfa2"], "\x06" => [77, "\xfaa"], "\x07" => [18, "\xfaa"], "\x08" => [77, "\xfac"], "\t" => [18, "\xfac"], "\n" => [77, "\xfae"], "\v" => [18, "\xfae"], "\f" => [77, "\xfai"], "\r" => [18, "\xfai"], "\x0e" => [77, "\xfao"], "\x0f" => [18, "\xfao"], "\x10" => [77, "\xfas"], "\x11" => [18, "\xfas"], "\x12" => [77, "\xfat"], "\x13" => [18, "\xfat"], "\x14" => [0, "\xfa "], "\x15" => [0, "\xfa%"], "\x16" => [0, "\xfa-"], "\x17" => [0, "\xfa."], "\x18" => [0, "\xfa/"], "\x19" => [0, "\xfa3"], "\x1a" => [0, "\xfa4"], "\x1b" => [0, "\xfa5"], "\x1c" => [0, "\xfa6"], "\x1d" => [0, "\xfa7"], "\x1e" => [0, "\xfa8"], "\x1f" => [0, "\xfa9"], " " => [0, "\xfa="], "!" => [0, "\xfaA"], "\"" => [0, "\xfa_"], "#" => [0, "\xfab"], "\$" => [0, "\xfad"], "%" => [0, "\xfaf"], "&" => [0, "\xfag"], "'" => [0, "\xfah"], "(" => [0, "\xfal"], ")" => [0, "\xfam"], "*" => [0, "\xfan"], "+" => [0, "\xfap"], "," => [0, "\xfar"], "-" => [0, "\xfau"], "." => [100, "\xfa"], "/" => [110, "\xfa"], [111, "\xfa"], [115, "\xfa"], [116, "\xfa"], [118, "\xfa"], [119, "\xfa"], [122, "\xfa"], [123, "\xfa"], [125, "\xfa"], [126, "\xfa"], [129, "\xfa"], ":" => [143, "\xfa"], ";" => [148, "\xfa"], "<" => [151, "\xfa"], "=" => [153, "\xfa"], ">" => [83, "\xfa"], "?" => [10, "\xfa"], "@" => [77, "\xfb0"], "A" => [18, "\xfb0"], "B" => [77, "\xfb1"], "C" => [18, "\xfb1"], "D" => [77, "\xfb2"], "E" => [18, "\xfb2"], "F" => [77, "\xfba"], "G" => [18, "\xfba"], "H" => [77, "\xfbc"], "I" => [18, "\xfbc"], "J" => [77, "\xfbe"], "K" => [18, "\xfbe"], "L" => [77, "\xfbi"], "M" => [18, "\xfbi"], "N" => [77, "\xfbo"], "O" => [18, "\xfbo"], "P" => [77, "\xfbs"], "Q" => [18, "\xfbs"], "R" => [77, "\xfbt"], "S" => [18, "\xfbt"], "T" => [0, "\xfb "], "U" => [0, "\xfb%"], "V" => [0, "\xfb-"], "W" => [0, "\xfb."], "X" => [0, "\xfb/"], "Y" => [0, "\xfb3"], "Z" => [0, "\xfb4"], "[" => [0, "\xfb5"], "\\" => [0, "\xfb6"], "]" => [0, "\xfb7"], "^" => [0, "\xfb8"], "_" => [0, "\xfb9"], "`" => [0, "\xfb="], "a" => [0, "\xfbA"], "b" => [0, "\xfb_"], "c" => [0, "\xfbb"], "d" => [0, "\xfbd"], "e" => [0, "\xfbf"], "f" => [0, "\xfbg"], "g" => [0, "\xfbh"], "h" => [0, "\xfbl"], "i" => [0, "\xfbm"], "j" => [0, "\xfbn"], "k" => [0, "\xfbp"], "l" => [0, "\xfbr"], "m" => [0, "\xfbu"], "n" => [100, "\xfb"], "o" => [110, "\xfb"], "p" => [111, "\xfb"], "q" => [115, "\xfb"], "r" => [116, "\xfb"], "s" => [118, "\xfb"], "t" => [119, "\xfb"], "u" => [122, "\xfb"], "v" => [123, "\xfb"], "w" => [125, "\xfb"], "x" => [126, "\xfb"], "y" => [129, "\xfb"], "z" => [143, "\xfb"], "{" => [148, "\xfb"], "|" => [151, "\xfb"], "}" => [153, "\xfb"], "~" => [83, "\xfb"], "" => [10, "\xfb"], "\x80" => [77, "\xfc0"], "\x81" => [18, "\xfc0"], "\x82" => [77, "\xfc1"], "\x83" => [18, "\xfc1"], "\x84" => [77, "\xfc2"], "\x85" => [18, "\xfc2"], "\x86" => [77, "\xfca"], "\x87" => [18, "\xfca"], "\x88" => [77, "\xfcc"], "\x89" => [18, "\xfcc"], "\x8a" => [77, "\xfce"], "\x8b" => [18, "\xfce"], "\x8c" => [77, "\xfci"], "\x8d" => [18, "\xfci"], "\x8e" => [77, "\xfco"], "\x8f" => [18, "\xfco"], "\x90" => [77, "\xfcs"], "\x91" => [18, "\xfcs"], "\x92" => [77, "\xfct"], "\x93" => [18, "\xfct"], "\x94" => [0, "\xfc "], "\x95" => [0, "\xfc%"], "\x96" => [0, "\xfc-"], "\x97" => [0, "\xfc."], "\x98" => [0, "\xfc/"], "\x99" => [0, "\xfc3"], "\x9a" => [0, "\xfc4"], "\x9b" => [0, "\xfc5"], "\x9c" => [0, "\xfc6"], "\x9d" => [0, "\xfc7"], "\x9e" => [0, "\xfc8"], "\x9f" => [0, "\xfc9"], "\xa0" => [0, "\xfc="], "\xa1" => [0, "\xfcA"], "\xa2" => [0, "\xfc_"], "\xa3" => [0, "\xfcb"], "\xa4" => [0, "\xfcd"], "\xa5" => [0, "\xfcf"], "\xa6" => [0, "\xfcg"], "\xa7" => [0, "\xfch"], "\xa8" => [0, "\xfcl"], "\xa9" => [0, "\xfcm"], "\xaa" => [0, "\xfcn"], "\xab" => [0, "\xfcp"], "\xac" => [0, "\xfcr"], "\xad" => [0, "\xfcu"], "\xae" => [100, "\xfc"], "\xaf" => [110, "\xfc"], "\xb0" => [111, "\xfc"], "\xb1" => [115, "\xfc"], "\xb2" => [116, "\xfc"], "\xb3" => [118, "\xfc"], "\xb4" => [119, "\xfc"], "\xb5" => [122, "\xfc"], "\xb6" => [123, "\xfc"], "\xb7" => [125, "\xfc"], "\xb8" => [126, "\xfc"], "\xb9" => [129, "\xfc"], "\xba" => [143, "\xfc"], "\xbb" => [148, "\xfc"], "\xbc" => [151, "\xfc"], "\xbd" => [153, "\xfc"], "\xbe" => [83, "\xfc"], "\xbf" => [10, "\xfc"], "\xc0" => [77, "\xfd0"], "\xc1" => [18, "\xfd0"], "\xc2" => [77, "\xfd1"], "\xc3" => [18, "\xfd1"], "\xc4" => [77, "\xfd2"], "\xc5" => [18, "\xfd2"], "\xc6" => [77, "\xfda"], "\xc7" => [18, "\xfda"], "\xc8" => [77, "\xfdc"], "\xc9" => [18, "\xfdc"], "\xca" => [77, "\xfde"], "\xcb" => [18, "\xfde"], "\xcc" => [77, "\xfdi"], "\xcd" => [18, "\xfdi"], "\xce" => [77, "\xfdo"], "\xcf" => [18, "\xfdo"], "\xd0" => [77, "\xfds"], "\xd1" => [18, "\xfds"], "\xd2" => [77, "\xfdt"], "\xd3" => [18, "\xfdt"], "\xd4" => [0, "\xfd "], "\xd5" => [0, "\xfd%"], "\xd6" => [0, "\xfd-"], "\xd7" => [0, "\xfd."], "\xd8" => [0, "\xfd/"], "\xd9" => [0, "\xfd3"], "\xda" => [0, "\xfd4"], "\xdb" => [0, "\xfd5"], "\xdc" => [0, "\xfd6"], "\xdd" => [0, "\xfd7"], "\xde" => [0, "\xfd8"], "\xdf" => [0, "\xfd9"], "\xe0" => [0, "\xfd="], "\xe1" => [0, "\xfdA"], "\xe2" => [0, "\xfd_"], "\xe3" => [0, "\xfdb"], "\xe4" => [0, "\xfdd"], "\xe5" => [0, "\xfdf"], "\xe6" => [0, "\xfdg"], "\xe7" => [0, "\xfdh"], "\xe8" => [0, "\xfdl"], "\xe9" => [0, "\xfdm"], "\xea" => [0, "\xfdn"], "\xeb" => [0, "\xfdp"], "\xec" => [0, "\xfdr"], "\xed" => [0, "\xfdu"], "\xee" => [100, "\xfd"], "\xef" => [110, "\xfd"], "\xf0" => [111, "\xfd"], "\xf1" => [115, "\xfd"], "\xf2" => [116, "\xfd"], "\xf3" => [118, "\xfd"], "\xf4" => [119, "\xfd"], "\xf5" => [122, "\xfd"], "\xf6" => [123, "\xfd"], "\xf7" => [125, "\xfd"], "\xf8" => [126, "\xfd"], "\xf9" => [129, "\xfd"], "\xfa" => [143, "\xfd"], "\xfb" => [148, "\xfd"], "\xfc" => [151, "\xfd"], "\xfd" => [153, "\xfd"], "\xfe" => [83, "\xfd"], "\xff" => [10, "\xfd"]], ["\x00" => [94, "\xfc0"], "\x01" => [76, "\xfc0"], "\x02" => [104, "\xfc0"], "\x03" => [16, "\xfc0"], "\x04" => [94, "\xfc1"], "\x05" => [76, "\xfc1"], "\x06" => [104, "\xfc1"], "\x07" => [16, "\xfc1"], "\x08" => [94, "\xfc2"], "\t" => [76, "\xfc2"], "\n" => [104, "\xfc2"], "\v" => [16, "\xfc2"], "\f" => [94, "\xfca"], "\r" => [76, "\xfca"], "\x0e" => [104, "\xfca"], "\x0f" => [16, "\xfca"], "\x10" => [94, "\xfcc"], "\x11" => [76, "\xfcc"], "\x12" => [104, "\xfcc"], "\x13" => [16, "\xfcc"], "\x14" => [94, "\xfce"], "\x15" => [76, "\xfce"], "\x16" => [104, "\xfce"], "\x17" => [16, "\xfce"], "\x18" => [94, "\xfci"], "\x19" => [76, "\xfci"], "\x1a" => [104, "\xfci"], "\x1b" => [16, "\xfci"], "\x1c" => [94, "\xfco"], "\x1d" => [76, "\xfco"], "\x1e" => [104, "\xfco"], "\x1f" => [16, "\xfco"], " " => [94, "\xfcs"], "!" => [76, "\xfcs"], "\"" => [104, "\xfcs"], "#" => [16, "\xfcs"], "\$" => [94, "\xfct"], "%" => [76, "\xfct"], "&" => [104, "\xfct"], "'" => [16, "\xfct"], "(" => [77, "\xfc "], ")" => [18, "\xfc "], "*" => [77, "\xfc%"], "+" => [18, "\xfc%"], "," => [77, "\xfc-"], "-" => [18, "\xfc-"], "." => [77, "\xfc."], "/" => [18, "\xfc."], [77, "\xfc/"], [18, "\xfc/"], [77, "\xfc3"], [18, "\xfc3"], [77, "\xfc4"], [18, "\xfc4"], [77, "\xfc5"], [18, "\xfc5"], [77, "\xfc6"], [18, "\xfc6"], ":" => [77, "\xfc7"], ";" => [18, "\xfc7"], "<" => [77, "\xfc8"], "=" => [18, "\xfc8"], ">" => [77, "\xfc9"], "?" => [18, "\xfc9"], "@" => [77, "\xfc="], "A" => [18, "\xfc="], "B" => [77, "\xfcA"], "C" => [18, "\xfcA"], "D" => [77, "\xfc_"], "E" => [18, "\xfc_"], "F" => [77, "\xfcb"], "G" => [18, "\xfcb"], "H" => [77, "\xfcd"], "I" => [18, "\xfcd"], "J" => [77, "\xfcf"], "K" => [18, "\xfcf"], "L" => [77, "\xfcg"], "M" => [18, "\xfcg"], "N" => [77, "\xfch"], "O" => [18, "\xfch"], "P" => [77, "\xfcl"], "Q" => [18, "\xfcl"], "R" => [77, "\xfcm"], "S" => [18, "\xfcm"], "T" => [77, "\xfcn"], "U" => [18, "\xfcn"], "V" => [77, "\xfcp"], "W" => [18, "\xfcp"], "X" => [77, "\xfcr"], "Y" => [18, "\xfcr"], "Z" => [77, "\xfcu"], "[" => [18, "\xfcu"], "\\" => [0, "\xfc:"], "]" => [0, "\xfcB"], "^" => [0, "\xfcC"], "_" => [0, "\xfcD"], "`" => [0, "\xfcE"], "a" => [0, "\xfcF"], "b" => [0, "\xfcG"], "c" => [0, "\xfcH"], "d" => [0, "\xfcI"], "e" => [0, "\xfcJ"], "f" => [0, "\xfcK"], "g" => [0, "\xfcL"], "h" => [0, "\xfcM"], "i" => [0, "\xfcN"], "j" => [0, "\xfcO"], "k" => [0, "\xfcP"], "l" => [0, "\xfcQ"], "m" => [0, "\xfcR"], "n" => [0, "\xfcS"], "o" => [0, "\xfcT"], "p" => [0, "\xfcU"], "q" => [0, "\xfcV"], "r" => [0, "\xfcW"], "s" => [0, "\xfcY"], "t" => [0, "\xfcj"], "u" => [0, "\xfck"], "v" => [0, "\xfcq"], "w" => [0, "\xfcv"], "x" => [0, "\xfcw"], "y" => [0, "\xfcx"], "z" => [0, "\xfcy"], "{" => [0, "\xfcz"], "|" => [82, "\xfc"], "}" => [87, "\xfc"], "~" => [130, "\xfc"], "" => [9, "\xfc"], "\x80" => [94, "\xfd0"], "\x81" => [76, "\xfd0"], "\x82" => [104, "\xfd0"], "\x83" => [16, "\xfd0"], "\x84" => [94, "\xfd1"], "\x85" => [76, "\xfd1"], "\x86" => [104, "\xfd1"], "\x87" => [16, "\xfd1"], "\x88" => [94, "\xfd2"], "\x89" => [76, "\xfd2"], "\x8a" => [104, "\xfd2"], "\x8b" => [16, "\xfd2"], "\x8c" => [94, "\xfda"], "\x8d" => [76, "\xfda"], "\x8e" => [104, "\xfda"], "\x8f" => [16, "\xfda"], "\x90" => [94, "\xfdc"], "\x91" => [76, "\xfdc"], "\x92" => [104, "\xfdc"], "\x93" => [16, "\xfdc"], "\x94" => [94, "\xfde"], "\x95" => [76, "\xfde"], "\x96" => [104, "\xfde"], "\x97" => [16, "\xfde"], "\x98" => [94, "\xfdi"], "\x99" => [76, "\xfdi"], "\x9a" => [104, "\xfdi"], "\x9b" => [16, "\xfdi"], "\x9c" => [94, "\xfdo"], "\x9d" => [76, "\xfdo"], "\x9e" => [104, "\xfdo"], "\x9f" => [16, "\xfdo"], "\xa0" => [94, "\xfds"], "\xa1" => [76, "\xfds"], "\xa2" => [104, "\xfds"], "\xa3" => [16, "\xfds"], "\xa4" => [94, "\xfdt"], "\xa5" => [76, "\xfdt"], "\xa6" => [104, "\xfdt"], "\xa7" => [16, "\xfdt"], "\xa8" => [77, "\xfd "], "\xa9" => [18, "\xfd "], "\xaa" => [77, "\xfd%"], "\xab" => [18, "\xfd%"], "\xac" => [77, "\xfd-"], "\xad" => [18, "\xfd-"], "\xae" => [77, "\xfd."], "\xaf" => [18, "\xfd."], "\xb0" => [77, "\xfd/"], "\xb1" => [18, "\xfd/"], "\xb2" => [77, "\xfd3"], "\xb3" => [18, "\xfd3"], "\xb4" => [77, "\xfd4"], "\xb5" => [18, "\xfd4"], "\xb6" => [77, "\xfd5"], "\xb7" => [18, "\xfd5"], "\xb8" => [77, "\xfd6"], "\xb9" => [18, "\xfd6"], "\xba" => [77, "\xfd7"], "\xbb" => [18, "\xfd7"], "\xbc" => [77, "\xfd8"], "\xbd" => [18, "\xfd8"], "\xbe" => [77, "\xfd9"], "\xbf" => [18, "\xfd9"], "\xc0" => [77, "\xfd="], "\xc1" => [18, "\xfd="], "\xc2" => [77, "\xfdA"], "\xc3" => [18, "\xfdA"], "\xc4" => [77, "\xfd_"], "\xc5" => [18, "\xfd_"], "\xc6" => [77, "\xfdb"], "\xc7" => [18, "\xfdb"], "\xc8" => [77, "\xfdd"], "\xc9" => [18, "\xfdd"], "\xca" => [77, "\xfdf"], "\xcb" => [18, "\xfdf"], "\xcc" => [77, "\xfdg"], "\xcd" => [18, "\xfdg"], "\xce" => [77, "\xfdh"], "\xcf" => [18, "\xfdh"], "\xd0" => [77, "\xfdl"], "\xd1" => [18, "\xfdl"], "\xd2" => [77, "\xfdm"], "\xd3" => [18, "\xfdm"], "\xd4" => [77, "\xfdn"], "\xd5" => [18, "\xfdn"], "\xd6" => [77, "\xfdp"], "\xd7" => [18, "\xfdp"], "\xd8" => [77, "\xfdr"], "\xd9" => [18, "\xfdr"], "\xda" => [77, "\xfdu"], "\xdb" => [18, "\xfdu"], "\xdc" => [0, "\xfd:"], "\xdd" => [0, "\xfdB"], "\xde" => [0, "\xfdC"], "\xdf" => [0, "\xfdD"], "\xe0" => [0, "\xfdE"], "\xe1" => [0, "\xfdF"], "\xe2" => [0, "\xfdG"], "\xe3" => [0, "\xfdH"], "\xe4" => [0, "\xfdI"], "\xe5" => [0, "\xfdJ"], "\xe6" => [0, "\xfdK"], "\xe7" => [0, "\xfdL"], "\xe8" => [0, "\xfdM"], "\xe9" => [0, "\xfdN"], "\xea" => [0, "\xfdO"], "\xeb" => [0, "\xfdP"], "\xec" => [0, "\xfdQ"], "\xed" => [0, "\xfdR"], "\xee" => [0, "\xfdS"], "\xef" => [0, "\xfdT"], "\xf0" => [0, "\xfdU"], "\xf1" => [0, "\xfdV"], "\xf2" => [0, "\xfdW"], "\xf3" => [0, "\xfdY"], "\xf4" => [0, "\xfdj"], "\xf5" => [0, "\xfdk"], "\xf6" => [0, "\xfdq"], "\xf7" => [0, "\xfdv"], "\xf8" => [0, "\xfdw"], "\xf9" => [0, "\xfdx"], "\xfa" => [0, "\xfdy"], "\xfb" => [0, "\xfdz"], "\xfc" => [82, "\xfd"], "\xfd" => [87, "\xfd"], "\xfe" => [130, "\xfd"], "\xff" => [9, "\xfd"]]];
#define FFI_SCOPE "amphp-hpack-nghttp2"
#define FFI_LIB "libnghttp2.so"

typedef struct nghttp2_hd_deflater nghttp2_hd_deflater;

typedef struct nghttp2_hd_inflater nghttp2_hd_inflater;

typedef struct {
  uint8_t *name;
  uint8_t *value;

  size_t namelen;
  size_t valuelen;

  uint8_t flags;
} nghttp2_nv;

int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max);

ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, size_t buflen, const nghttp2_nv *nva, size_t nvlen);

size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, const nghttp2_nv *nva, size_t nvlen);

int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);

ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, int *inflate_flags, const uint8_t *in, size_t inlen, int in_final);

int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
<?php

return [["\x00" => ["\xff", "\xc0"], "\x01" => ["\xff", "\xff", "\xb0"], "\x02" => ["\xff", "\xff", "\xfe", " "], "\x03" => ["\xff", "\xff", "\xfe", "0"], "\x04" => ["\xff", "\xff", "\xfe", "@"], "\x05" => ["\xff", "\xff", "\xfe", "P"], "\x06" => ["\xff", "\xff", "\xfe", "`"], "\x07" => ["\xff", "\xff", "\xfe", "p"], "\x08" => ["\xff", "\xff", "\xfe", "\x80"], "\t" => ["\xff", "\xff", "\xea"], "\n" => ["\xff", "\xff", "\xff", "\xf0"], "\v" => ["\xff", "\xff", "\xfe", "\x90"], "\f" => ["\xff", "\xff", "\xfe", "\xa0"], "\r" => ["\xff", "\xff", "\xff", "\xf4"], "\x0e" => ["\xff", "\xff", "\xfe", "\xb0"], "\x0f" => ["\xff", "\xff", "\xfe", "\xc0"], "\x10" => ["\xff", "\xff", "\xfe", "\xd0"], "\x11" => ["\xff", "\xff", "\xfe", "\xe0"], "\x12" => ["\xff", "\xff", "\xfe", "\xf0"], "\x13" => ["\xff", "\xff", "\xff", "\x00"], "\x14" => ["\xff", "\xff", "\xff", "\x10"], "\x15" => ["\xff", "\xff", "\xff", " "], "\x16" => ["\xff", "\xff", "\xff", "\xf8"], "\x17" => ["\xff", "\xff", "\xff", "0"], "\x18" => ["\xff", "\xff", "\xff", "@"], "\x19" => ["\xff", "\xff", "\xff", "P"], "\x1a" => ["\xff", "\xff", "\xff", "`"], "\x1b" => ["\xff", "\xff", "\xff", "p"], "\x1c" => ["\xff", "\xff", "\xff", "\x80"], "\x1d" => ["\xff", "\xff", "\xff", "\x90"], "\x1e" => ["\xff", "\xff", "\xff", "\xa0"], "\x1f" => ["\xff", "\xff", "\xff", "\xb0"], " " => ["P"], "!" => ["\xfe", "\x00"], "\"" => ["\xfe", "@"], "#" => ["\xff", "\xa0"], "\$" => ["\xff", "\xc8"], "%" => ["T"], "&" => ["\xf8"], "'" => ["\xff", "@"], "(" => ["\xfe", "\x80"], ")" => ["\xfe", "\xc0"], "*" => ["\xf9"], "+" => ["\xff", "`"], "," => ["\xfa"], "-" => ["X"], "." => ["\\"], "/" => ["`"], ["\x00"], ["\x08"], ["\x10"], ["d"], ["h"], ["l"], ["p"], ["t"], ["x"], ["|"], ":" => ["\xb8"], ";" => ["\xfb"], "<" => ["\xff", "\xf8"], "=" => ["\x80"], ">" => ["\xff", "\xb0"], "?" => ["\xff", "\x00"], "@" => ["\xff", "\xd0"], "A" => ["\x84"], "B" => ["\xba"], "C" => ["\xbc"], "D" => ["\xbe"], "E" => ["\xc0"], "F" => ["\xc2"], "G" => ["\xc4"], "H" => ["\xc6"], "I" => ["\xc8"], "J" => ["\xca"], "K" => ["\xcc"], "L" => ["\xce"], "M" => ["\xd0"], "N" => ["\xd2"], "O" => ["\xd4"], "P" => ["\xd6"], "Q" => ["\xd8"], "R" => ["\xda"], "S" => ["\xdc"], "T" => ["\xde"], "U" => ["\xe0"], "V" => ["\xe2"], "W" => ["\xe4"], "X" => ["\xfc"], "Y" => ["\xe6"], "Z" => ["\xfd"], "[" => ["\xff", "\xd8"], "\\" => ["\xff", "\xfe", "\x00"], "]" => ["\xff", "\xe0"], "^" => ["\xff", "\xf0"], "_" => ["\x88"], "`" => ["\xff", "\xfa"], "a" => ["\x18"], "b" => ["\x8c"], "c" => [" "], "d" => ["\x90"], "e" => ["("], "f" => ["\x94"], "g" => ["\x98"], "h" => ["\x9c"], "i" => ["0"], "j" => ["\xe8"], "k" => ["\xea"], "l" => ["\xa0"], "m" => ["\xa4"], "n" => ["\xa8"], "o" => ["8"], "p" => ["\xac"], "q" => ["\xec"], "r" => ["\xb0"], "s" => ["@"], "t" => ["H"], "u" => ["\xb4"], "v" => ["\xee"], "w" => ["\xf0"], "x" => ["\xf2"], "y" => ["\xf4"], "z" => ["\xf6"], "{" => ["\xff", "\xfc"], "|" => ["\xff", "\x80"], "}" => ["\xff", "\xf4"], "~" => ["\xff", "\xe8"], "" => ["\xff", "\xff", "\xff", "\xc0"], "\x80" => ["\xff", "\xfe", "`"], "\x81" => ["\xff", "\xff", "H"], "\x82" => ["\xff", "\xfe", "p"], "\x83" => ["\xff", "\xfe", "\x80"], "\x84" => ["\xff", "\xff", "L"], "\x85" => ["\xff", "\xff", "P"], "\x86" => ["\xff", "\xff", "T"], "\x87" => ["\xff", "\xff", "\xb2"], "\x88" => ["\xff", "\xff", "X"], "\x89" => ["\xff", "\xff", "\xb4"], "\x8a" => ["\xff", "\xff", "\xb6"], "\x8b" => ["\xff", "\xff", "\xb8"], "\x8c" => ["\xff", "\xff", "\xba"], "\x8d" => ["\xff", "\xff", "\xbc"], "\x8e" => ["\xff", "\xff", "\xeb"], "\x8f" => ["\xff", "\xff", "\xbe"], "\x90" => ["\xff", "\xff", "\xec"], "\x91" => ["\xff", "\xff", "\xed"], "\x92" => ["\xff", "\xff", "\\"], "\x93" => ["\xff", "\xff", "\xc0"], "\x94" => ["\xff", "\xff", "\xee"], "\x95" => ["\xff", "\xff", "\xc2"], "\x96" => ["\xff", "\xff", "\xc4"], "\x97" => ["\xff", "\xff", "\xc6"], "\x98" => ["\xff", "\xff", "\xc8"], "\x99" => ["\xff", "\xfe", "\xe0"], "\x9a" => ["\xff", "\xff", "`"], "\x9b" => ["\xff", "\xff", "\xca"], "\x9c" => ["\xff", "\xff", "d"], "\x9d" => ["\xff", "\xff", "\xcc"], "\x9e" => ["\xff", "\xff", "\xce"], "\x9f" => ["\xff", "\xff", "\xef"], "\xa0" => ["\xff", "\xff", "h"], "\xa1" => ["\xff", "\xfe", "\xe8"], "\xa2" => ["\xff", "\xfe", "\x90"], "\xa3" => ["\xff", "\xff", "l"], "\xa4" => ["\xff", "\xff", "p"], "\xa5" => ["\xff", "\xff", "\xd0"], "\xa6" => ["\xff", "\xff", "\xd2"], "\xa7" => ["\xff", "\xfe", "\xf0"], "\xa8" => ["\xff", "\xff", "\xd4"], "\xa9" => ["\xff", "\xff", "t"], "\xaa" => ["\xff", "\xff", "x"], "\xab" => ["\xff", "\xff", "\xf0"], "\xac" => ["\xff", "\xfe", "\xf8"], "\xad" => ["\xff", "\xff", "|"], "\xae" => ["\xff", "\xff", "\xd6"], "\xaf" => ["\xff", "\xff", "\xd8"], "\xb0" => ["\xff", "\xff", "\x00"], "\xb1" => ["\xff", "\xff", "\x08"], "\xb2" => ["\xff", "\xff", "\x80"], "\xb3" => ["\xff", "\xff", "\x10"], "\xb4" => ["\xff", "\xff", "\xda"], "\xb5" => ["\xff", "\xff", "\x84"], "\xb6" => ["\xff", "\xff", "\xdc"], "\xb7" => ["\xff", "\xff", "\xde"], "\xb8" => ["\xff", "\xfe", "\xa0"], "\xb9" => ["\xff", "\xff", "\x88"], "\xba" => ["\xff", "\xff", "\x8c"], "\xbb" => ["\xff", "\xff", "\x90"], "\xbc" => ["\xff", "\xff", "\xe0"], "\xbd" => ["\xff", "\xff", "\x94"], "\xbe" => ["\xff", "\xff", "\x98"], "\xbf" => ["\xff", "\xff", "\xe2"], "\xc0" => ["\xff", "\xff", "\xf8", "\x00"], "\xc1" => ["\xff", "\xff", "\xf8", "@"], "\xc2" => ["\xff", "\xfe", "\xb0"], "\xc3" => ["\xff", "\xfe", " "], "\xc4" => ["\xff", "\xff", "\x9c"], "\xc5" => ["\xff", "\xff", "\xe4"], "\xc6" => ["\xff", "\xff", "\xa0"], "\xc7" => ["\xff", "\xff", "\xf6", "\x00"], "\xc8" => ["\xff", "\xff", "\xf8", "\x80"], "\xc9" => ["\xff", "\xff", "\xf8", "\xc0"], "\xca" => ["\xff", "\xff", "\xf9", "\x00"], "\xcb" => ["\xff", "\xff", "\xfb", "\xc0"], "\xcc" => ["\xff", "\xff", "\xfb", "\xe0"], "\xcd" => ["\xff", "\xff", "\xf9", "@"], "\xce" => ["\xff", "\xff", "\xf1"], "\xcf" => ["\xff", "\xff", "\xf6", "\x80"], "\xd0" => ["\xff", "\xfe", "@"], "\xd1" => ["\xff", "\xff", "\x18"], "\xd2" => ["\xff", "\xff", "\xf9", "\x80"], "\xd3" => ["\xff", "\xff", "\xfc", "\x00"], "\xd4" => ["\xff", "\xff", "\xfc", " "], "\xd5" => ["\xff", "\xff", "\xf9", "\xc0"], "\xd6" => ["\xff", "\xff", "\xfc", "@"], "\xd7" => ["\xff", "\xff", "\xf2"], "\xd8" => ["\xff", "\xff", " "], "\xd9" => ["\xff", "\xff", "("], "\xda" => ["\xff", "\xff", "\xfa", "\x00"], "\xdb" => ["\xff", "\xff", "\xfa", "@"], "\xdc" => ["\xff", "\xff", "\xff", "\xd0"], "\xdd" => ["\xff", "\xff", "\xfc", "`"], "\xde" => ["\xff", "\xff", "\xfc", "\x80"], "\xdf" => ["\xff", "\xff", "\xfc", "\xa0"], "\xe0" => ["\xff", "\xfe", "\xc0"], "\xe1" => ["\xff", "\xff", "\xf3"], "\xe2" => ["\xff", "\xfe", "\xd0"], "\xe3" => ["\xff", "\xff", "0"], "\xe4" => ["\xff", "\xff", "\xa4"], "\xe5" => ["\xff", "\xff", "8"], "\xe6" => ["\xff", "\xff", "@"], "\xe7" => ["\xff", "\xff", "\xe6"], "\xe8" => ["\xff", "\xff", "\xa8"], "\xe9" => ["\xff", "\xff", "\xac"], "\xea" => ["\xff", "\xff", "\xf7", "\x00"], "\xeb" => ["\xff", "\xff", "\xf7", "\x80"], "\xec" => ["\xff", "\xff", "\xf4"], "\xed" => ["\xff", "\xff", "\xf5"], "\xee" => ["\xff", "\xff", "\xfa", "\x80"], "\xef" => ["\xff", "\xff", "\xe8"], "\xf0" => ["\xff", "\xff", "\xfa", "\xc0"], "\xf1" => ["\xff", "\xff", "\xfc", "\xc0"], "\xf2" => ["\xff", "\xff", "\xfb", "\x00"], "\xf3" => ["\xff", "\xff", "\xfb", "@"], "\xf4" => ["\xff", "\xff", "\xfc", "\xe0"], "\xf5" => ["\xff", "\xff", "\xfd", "\x00"], "\xf6" => ["\xff", "\xff", "\xfd", " "], "\xf7" => ["\xff", "\xff", "\xfd", "@"], "\xf8" => ["\xff", "\xff", "\xfd", "`"], "\xf9" => ["\xff", "\xff", "\xff", "\xe0"], "\xfa" => ["\xff", "\xff", "\xfd", "\x80"], "\xfb" => ["\xff", "\xff", "\xfd", "\xa0"], "\xfc" => ["\xff", "\xff", "\xfd", "\xc0"], "\xfd" => ["\xff", "\xff", "\xfd", "\xe0"], "\xfe" => ["\xff", "\xff", "\xfe", "\x00"], "\xff" => ["\xff", "\xff", "\xfb", "\x80"]], ["\x00" => ["", "\xe0"], "\x01" => ["", "\xff", "\xd8"], "\x02" => ["", "\xff", "\xff", "\x10"], "\x03" => ["", "\xff", "\xff", "\x18"], "\x04" => ["", "\xff", "\xff", " "], "\x05" => ["", "\xff", "\xff", "("], "\x06" => ["", "\xff", "\xff", "0"], "\x07" => ["", "\xff", "\xff", "8"], "\x08" => ["", "\xff", "\xff", "@"], "\t" => ["", "\xff", "\xf5", "\x00"], "\n" => ["", "\xff", "\xff", "\xf8"], "\v" => ["", "\xff", "\xff", "H"], "\f" => ["", "\xff", "\xff", "P"], "\r" => ["", "\xff", "\xff", "\xfa"], "\x0e" => ["", "\xff", "\xff", "X"], "\x0f" => ["", "\xff", "\xff", "`"], "\x10" => ["", "\xff", "\xff", "h"], "\x11" => ["", "\xff", "\xff", "p"], "\x12" => ["", "\xff", "\xff", "x"], "\x13" => ["", "\xff", "\xff", "\x80"], "\x14" => ["", "\xff", "\xff", "\x88"], "\x15" => ["", "\xff", "\xff", "\x90"], "\x16" => ["", "\xff", "\xff", "\xfc"], "\x17" => ["", "\xff", "\xff", "\x98"], "\x18" => ["", "\xff", "\xff", "\xa0"], "\x19" => ["", "\xff", "\xff", "\xa8"], "\x1a" => ["", "\xff", "\xff", "\xb0"], "\x1b" => ["", "\xff", "\xff", "\xb8"], "\x1c" => ["", "\xff", "\xff", "\xc0"], "\x1d" => ["", "\xff", "\xff", "\xc8"], "\x1e" => ["", "\xff", "\xff", "\xd0"], "\x1f" => ["", "\xff", "\xff", "\xd8"], " " => ["("], "!" => ["", "\x00"], "\"" => ["", " "], "#" => ["", "\xd0"], "\$" => ["", "\xe4"], "%" => ["*"], "&" => ["|", "\x00"], "'" => ["", "\xa0"], "(" => ["", "@"], ")" => ["", "`"], "*" => ["|", "\x80"], "+" => ["", "\xb0"], "," => ["}", "\x00"], "-" => [","], "." => ["."], "/" => ["0"], ["\x00"], ["\x04"], ["\x08"], ["2"], ["4"], ["6"], ["8"], [":"], ["<"], [">"], ":" => ["\\"], ";" => ["}", "\x80"], "<" => ["", "\xfc"], "=" => ["@"], ">" => ["", "\xd8"], "?" => ["", "\x80"], "@" => ["", "\xe8"], "A" => ["B"], "B" => ["]"], "C" => ["^"], "D" => ["_"], "E" => ["`"], "F" => ["a"], "G" => ["b"], "H" => ["c"], "I" => ["d"], "J" => ["e"], "K" => ["f"], "L" => ["g"], "M" => ["h"], "N" => ["i"], "O" => ["j"], "P" => ["k"], "Q" => ["l"], "R" => ["m"], "S" => ["n"], "T" => ["o"], "U" => ["p"], "V" => ["q"], "W" => ["r"], "X" => ["~", "\x00"], "Y" => ["s"], "Z" => ["~", "\x80"], "[" => ["", "\xec"], "\\" => ["", "\xff", "\x00"], "]" => ["", "\xf0"], "^" => ["", "\xf8"], "_" => ["D"], "`" => ["", "\xfd"], "a" => ["\f"], "b" => ["F"], "c" => ["\x10"], "d" => ["H"], "e" => ["\x14"], "f" => ["J"], "g" => ["L"], "h" => ["N"], "i" => ["\x18"], "j" => ["t"], "k" => ["u"], "l" => ["P"], "m" => ["R"], "n" => ["T"], "o" => ["\x1c"], "p" => ["V"], "q" => ["v"], "r" => ["X"], "s" => [" "], "t" => ["\$"], "u" => ["Z"], "v" => ["w"], "w" => ["x"], "x" => ["y"], "y" => ["z"], "z" => ["{"], "{" => ["", "\xfe"], "|" => ["", "\xc0"], "}" => ["", "\xfa"], "~" => ["", "\xf4"], "" => ["", "\xff", "\xff", "\xe0"], "\x80" => ["", "\xff", "0"], "\x81" => ["", "\xff", "\xa4"], "\x82" => ["", "\xff", "8"], "\x83" => ["", "\xff", "@"], "\x84" => ["", "\xff", "\xa6"], "\x85" => ["", "\xff", "\xa8"], "\x86" => ["", "\xff", "\xaa"], "\x87" => ["", "\xff", "\xd9"], "\x88" => ["", "\xff", "\xac"], "\x89" => ["", "\xff", "\xda"], "\x8a" => ["", "\xff", "\xdb"], "\x8b" => ["", "\xff", "\xdc"], "\x8c" => ["", "\xff", "\xdd"], "\x8d" => ["", "\xff", "\xde"], "\x8e" => ["", "\xff", "\xf5", "\x80"], "\x8f" => ["", "\xff", "\xdf"], "\x90" => ["", "\xff", "\xf6", "\x00"], "\x91" => ["", "\xff", "\xf6", "\x80"], "\x92" => ["", "\xff", "\xae"], "\x93" => ["", "\xff", "\xe0"], "\x94" => ["", "\xff", "\xf7", "\x00"], "\x95" => ["", "\xff", "\xe1"], "\x96" => ["", "\xff", "\xe2"], "\x97" => ["", "\xff", "\xe3"], "\x98" => ["", "\xff", "\xe4"], "\x99" => ["", "\xff", "p"], "\x9a" => ["", "\xff", "\xb0"], "\x9b" => ["", "\xff", "\xe5"], "\x9c" => ["", "\xff", "\xb2"], "\x9d" => ["", "\xff", "\xe6"], "\x9e" => ["", "\xff", "\xe7"], "\x9f" => ["", "\xff", "\xf7", "\x80"], "\xa0" => ["", "\xff", "\xb4"], "\xa1" => ["", "\xff", "t"], "\xa2" => ["", "\xff", "H"], "\xa3" => ["", "\xff", "\xb6"], "\xa4" => ["", "\xff", "\xb8"], "\xa5" => ["", "\xff", "\xe8"], "\xa6" => ["", "\xff", "\xe9"], "\xa7" => ["", "\xff", "x"], "\xa8" => ["", "\xff", "\xea"], "\xa9" => ["", "\xff", "\xba"], "\xaa" => ["", "\xff", "\xbc"], "\xab" => ["", "\xff", "\xf8", "\x00"], "\xac" => ["", "\xff", "|"], "\xad" => ["", "\xff", "\xbe"], "\xae" => ["", "\xff", "\xeb"], "\xaf" => ["", "\xff", "\xec"], "\xb0" => ["", "\xff", "\x80"], "\xb1" => ["", "\xff", "\x84"], "\xb2" => ["", "\xff", "\xc0"], "\xb3" => ["", "\xff", "\x88"], "\xb4" => ["", "\xff", "\xed"], "\xb5" => ["", "\xff", "\xc2"], "\xb6" => ["", "\xff", "\xee"], "\xb7" => ["", "\xff", "\xef"], "\xb8" => ["", "\xff", "P"], "\xb9" => ["", "\xff", "\xc4"], "\xba" => ["", "\xff", "\xc6"], "\xbb" => ["", "\xff", "\xc8"], "\xbc" => ["", "\xff", "\xf0"], "\xbd" => ["", "\xff", "\xca"], "\xbe" => ["", "\xff", "\xcc"], "\xbf" => ["", "\xff", "\xf1"], "\xc0" => ["", "\xff", "\xfc", "\x00"], "\xc1" => ["", "\xff", "\xfc", " "], "\xc2" => ["", "\xff", "X"], "\xc3" => ["", "\xff", "\x10"], "\xc4" => ["", "\xff", "\xce"], "\xc5" => ["", "\xff", "\xf2"], "\xc6" => ["", "\xff", "\xd0"], "\xc7" => ["", "\xff", "\xfb", "\x00"], "\xc8" => ["", "\xff", "\xfc", "@"], "\xc9" => ["", "\xff", "\xfc", "`"], "\xca" => ["", "\xff", "\xfc", "\x80"], "\xcb" => ["", "\xff", "\xfd", "\xe0"], "\xcc" => ["", "\xff", "\xfd", "\xf0"], "\xcd" => ["", "\xff", "\xfc", "\xa0"], "\xce" => ["", "\xff", "\xf8", "\x80"], "\xcf" => ["", "\xff", "\xfb", "@"], "\xd0" => ["", "\xff", " "], "\xd1" => ["", "\xff", "\x8c"], "\xd2" => ["", "\xff", "\xfc", "\xc0"], "\xd3" => ["", "\xff", "\xfe", "\x00"], "\xd4" => ["", "\xff", "\xfe", "\x10"], "\xd5" => ["", "\xff", "\xfc", "\xe0"], "\xd6" => ["", "\xff", "\xfe", " "], "\xd7" => ["", "\xff", "\xf9", "\x00"], "\xd8" => ["", "\xff", "\x90"], "\xd9" => ["", "\xff", "\x94"], "\xda" => ["", "\xff", "\xfd", "\x00"], "\xdb" => ["", "\xff", "\xfd", " "], "\xdc" => ["", "\xff", "\xff", "\xe8"], "\xdd" => ["", "\xff", "\xfe", "0"], "\xde" => ["", "\xff", "\xfe", "@"], "\xdf" => ["", "\xff", "\xfe", "P"], "\xe0" => ["", "\xff", "`"], "\xe1" => ["", "\xff", "\xf9", "\x80"], "\xe2" => ["", "\xff", "h"], "\xe3" => ["", "\xff", "\x98"], "\xe4" => ["", "\xff", "\xd2"], "\xe5" => ["", "\xff", "\x9c"], "\xe6" => ["", "\xff", "\xa0"], "\xe7" => ["", "\xff", "\xf3"], "\xe8" => ["", "\xff", "\xd4"], "\xe9" => ["", "\xff", "\xd6"], "\xea" => ["", "\xff", "\xfb", "\x80"], "\xeb" => ["", "\xff", "\xfb", "\xc0"], "\xec" => ["", "\xff", "\xfa", "\x00"], "\xed" => ["", "\xff", "\xfa", "\x80"], "\xee" => ["", "\xff", "\xfd", "@"], "\xef" => ["", "\xff", "\xf4"], "\xf0" => ["", "\xff", "\xfd", "`"], "\xf1" => ["", "\xff", "\xfe", "`"], "\xf2" => ["", "\xff", "\xfd", "\x80"], "\xf3" => ["", "\xff", "\xfd", "\xa0"], "\xf4" => ["", "\xff", "\xfe", "p"], "\xf5" => ["", "\xff", "\xfe", "\x80"], "\xf6" => ["", "\xff", "\xfe", "\x90"], "\xf7" => ["", "\xff", "\xfe", "\xa0"], "\xf8" => ["", "\xff", "\xfe", "\xb0"], "\xf9" => ["", "\xff", "\xff", "\xf0"], "\xfa" => ["", "\xff", "\xfe", "\xc0"], "\xfb" => ["", "\xff", "\xfe", "\xd0"], "\xfc" => ["", "\xff", "\xfe", "\xe0"], "\xfd" => ["", "\xff", "\xfe", "\xf0"], "\xfe" => ["", "\xff", "\xff", "\x00"], "\xff" => ["", "\xff", "\xfd", "\xc0"]], ["\x00" => ["?", "\xf0"], "\x01" => ["?", "\xff", "\xec", "\x00"], "\x02" => ["?", "\xff", "\xff", "\x88"], "\x03" => ["?", "\xff", "\xff", "\x8c"], "\x04" => ["?", "\xff", "\xff", "\x90"], "\x05" => ["?", "\xff", "\xff", "\x94"], "\x06" => ["?", "\xff", "\xff", "\x98"], "\x07" => ["?", "\xff", "\xff", "\x9c"], "\x08" => ["?", "\xff", "\xff", "\xa0"], "\t" => ["?", "\xff", "\xfa", "\x80"], "\n" => ["?", "\xff", "\xff", "\xfc"], "\v" => ["?", "\xff", "\xff", "\xa4"], "\f" => ["?", "\xff", "\xff", "\xa8"], "\r" => ["?", "\xff", "\xff", "\xfd"], "\x0e" => ["?", "\xff", "\xff", "\xac"], "\x0f" => ["?", "\xff", "\xff", "\xb0"], "\x10" => ["?", "\xff", "\xff", "\xb4"], "\x11" => ["?", "\xff", "\xff", "\xb8"], "\x12" => ["?", "\xff", "\xff", "\xbc"], "\x13" => ["?", "\xff", "\xff", "\xc0"], "\x14" => ["?", "\xff", "\xff", "\xc4"], "\x15" => ["?", "\xff", "\xff", "\xc8"], "\x16" => ["?", "\xff", "\xff", "\xfe"], "\x17" => ["?", "\xff", "\xff", "\xcc"], "\x18" => ["?", "\xff", "\xff", "\xd0"], "\x19" => ["?", "\xff", "\xff", "\xd4"], "\x1a" => ["?", "\xff", "\xff", "\xd8"], "\x1b" => ["?", "\xff", "\xff", "\xdc"], "\x1c" => ["?", "\xff", "\xff", "\xe0"], "\x1d" => ["?", "\xff", "\xff", "\xe4"], "\x1e" => ["?", "\xff", "\xff", "\xe8"], "\x1f" => ["?", "\xff", "\xff", "\xec"], " " => ["\x14"], "!" => ["?", "\x80"], "\"" => ["?", "\x90"], "#" => ["?", "\xe8"], "\$" => ["?", "\xf2"], "%" => ["\x15"], "&" => [">", "\x00"], "'" => ["?", "\xd0"], "(" => ["?", "\xa0"], ")" => ["?", "\xb0"], "*" => [">", "@"], "+" => ["?", "\xd8"], "," => [">", "\x80"], "-" => ["\x16"], "." => ["\x17"], "/" => ["\x18"], ["\x00"], ["\x02"], ["\x04"], ["\x19"], ["\x1a"], ["\x1b"], ["\x1c"], ["\x1d"], ["\x1e"], ["\x1f"], ":" => [".", "\x00"], ";" => [">", "\xc0"], "<" => ["?", "\xfe", "\x00"], "=" => [" "], ">" => ["?", "\xec"], "?" => ["?", "\xc0"], "@" => ["?", "\xf4"], "A" => ["!"], "B" => [".", "\x80"], "C" => ["/", "\x00"], "D" => ["/", "\x80"], "E" => ["0", "\x00"], "F" => ["0", "\x80"], "G" => ["1", "\x00"], "H" => ["1", "\x80"], "I" => ["2", "\x00"], "J" => ["2", "\x80"], "K" => ["3", "\x00"], "L" => ["3", "\x80"], "M" => ["4", "\x00"], "N" => ["4", "\x80"], "O" => ["5", "\x00"], "P" => ["5", "\x80"], "Q" => ["6", "\x00"], "R" => ["6", "\x80"], "S" => ["7", "\x00"], "T" => ["7", "\x80"], "U" => ["8", "\x00"], "V" => ["8", "\x80"], "W" => ["9", "\x00"], "X" => ["?", "\x00"], "Y" => ["9", "\x80"], "Z" => ["?", "@"], "[" => ["?", "\xf6"], "\\" => ["?", "\xff", "\x80"], "]" => ["?", "\xf8"], "^" => ["?", "\xfc"], "_" => ["\""], "`" => ["?", "\xfe", "\x80"], "a" => ["\x06"], "b" => ["#"], "c" => ["\x08"], "d" => ["\$"], "e" => ["\n"], "f" => ["%"], "g" => ["&"], "h" => ["'"], "i" => ["\f"], "j" => [":", "\x00"], "k" => [":", "\x80"], "l" => ["("], "m" => [")"], "n" => ["*"], "o" => ["\x0e"], "p" => ["+"], "q" => [";", "\x00"], "r" => [","], "s" => ["\x10"], "t" => ["\x12"], "u" => ["-"], "v" => [";", "\x80"], "w" => ["<", "\x00"], "x" => ["<", "\x80"], "y" => ["=", "\x00"], "z" => ["=", "\x80"], "{" => ["?", "\xff", "\x00"], "|" => ["?", "\xe0"], "}" => ["?", "\xfd"], "~" => ["?", "\xfa"], "" => ["?", "\xff", "\xff", "\xf0"], "\x80" => ["?", "\xff", "\x98"], "\x81" => ["?", "\xff", "\xd2"], "\x82" => ["?", "\xff", "\x9c"], "\x83" => ["?", "\xff", "\xa0"], "\x84" => ["?", "\xff", "\xd3"], "\x85" => ["?", "\xff", "\xd4"], "\x86" => ["?", "\xff", "\xd5"], "\x87" => ["?", "\xff", "\xec", "\x80"], "\x88" => ["?", "\xff", "\xd6"], "\x89" => ["?", "\xff", "\xed", "\x00"], "\x8a" => ["?", "\xff", "\xed", "\x80"], "\x8b" => ["?", "\xff", "\xee", "\x00"], "\x8c" => ["?", "\xff", "\xee", "\x80"], "\x8d" => ["?", "\xff", "\xef", "\x00"], "\x8e" => ["?", "\xff", "\xfa", "\xc0"], "\x8f" => ["?", "\xff", "\xef", "\x80"], "\x90" => ["?", "\xff", "\xfb", "\x00"], "\x91" => ["?", "\xff", "\xfb", "@"], "\x92" => ["?", "\xff", "\xd7"], "\x93" => ["?", "\xff", "\xf0", "\x00"], "\x94" => ["?", "\xff", "\xfb", "\x80"], "\x95" => ["?", "\xff", "\xf0", "\x80"], "\x96" => ["?", "\xff", "\xf1", "\x00"], "\x97" => ["?", "\xff", "\xf1", "\x80"], "\x98" => ["?", "\xff", "\xf2", "\x00"], "\x99" => ["?", "\xff", "\xb8"], "\x9a" => ["?", "\xff", "\xd8"], "\x9b" => ["?", "\xff", "\xf2", "\x80"], "\x9c" => ["?", "\xff", "\xd9"], "\x9d" => ["?", "\xff", "\xf3", "\x00"], "\x9e" => ["?", "\xff", "\xf3", "\x80"], "\x9f" => ["?", "\xff", "\xfb", "\xc0"], "\xa0" => ["?", "\xff", "\xda"], "\xa1" => ["?", "\xff", "\xba"], "\xa2" => ["?", "\xff", "\xa4"], "\xa3" => ["?", "\xff", "\xdb"], "\xa4" => ["?", "\xff", "\xdc"], "\xa5" => ["?", "\xff", "\xf4", "\x00"], "\xa6" => ["?", "\xff", "\xf4", "\x80"], "\xa7" => ["?", "\xff", "\xbc"], "\xa8" => ["?", "\xff", "\xf5", "\x00"], "\xa9" => ["?", "\xff", "\xdd"], "\xaa" => ["?", "\xff", "\xde"], "\xab" => ["?", "\xff", "\xfc", "\x00"], "\xac" => ["?", "\xff", "\xbe"], "\xad" => ["?", "\xff", "\xdf"], "\xae" => ["?", "\xff", "\xf5", "\x80"], "\xaf" => ["?", "\xff", "\xf6", "\x00"], "\xb0" => ["?", "\xff", "\xc0"], "\xb1" => ["?", "\xff", "\xc2"], "\xb2" => ["?", "\xff", "\xe0"], "\xb3" => ["?", "\xff", "\xc4"], "\xb4" => ["?", "\xff", "\xf6", "\x80"], "\xb5" => ["?", "\xff", "\xe1"], "\xb6" => ["?", "\xff", "\xf7", "\x00"], "\xb7" => ["?", "\xff", "\xf7", "\x80"], "\xb8" => ["?", "\xff", "\xa8"], "\xb9" => ["?", "\xff", "\xe2"], "\xba" => ["?", "\xff", "\xe3"], "\xbb" => ["?", "\xff", "\xe4"], "\xbc" => ["?", "\xff", "\xf8", "\x00"], "\xbd" => ["?", "\xff", "\xe5"], "\xbe" => ["?", "\xff", "\xe6"], "\xbf" => ["?", "\xff", "\xf8", "\x80"], "\xc0" => ["?", "\xff", "\xfe", "\x00"], "\xc1" => ["?", "\xff", "\xfe", "\x10"], "\xc2" => ["?", "\xff", "\xac"], "\xc3" => ["?", "\xff", "\x88"], "\xc4" => ["?", "\xff", "\xe7"], "\xc5" => ["?", "\xff", "\xf9", "\x00"], "\xc6" => ["?", "\xff", "\xe8"], "\xc7" => ["?", "\xff", "\xfd", "\x80"], "\xc8" => ["?", "\xff", "\xfe", " "], "\xc9" => ["?", "\xff", "\xfe", "0"], "\xca" => ["?", "\xff", "\xfe", "@"], "\xcb" => ["?", "\xff", "\xfe", "\xf0"], "\xcc" => ["?", "\xff", "\xfe", "\xf8"], "\xcd" => ["?", "\xff", "\xfe", "P"], "\xce" => ["?", "\xff", "\xfc", "@"], "\xcf" => ["?", "\xff", "\xfd", "\xa0"], "\xd0" => ["?", "\xff", "\x90"], "\xd1" => ["?", "\xff", "\xc6"], "\xd2" => ["?", "\xff", "\xfe", "`"], "\xd3" => ["?", "\xff", "\xff", "\x00"], "\xd4" => ["?", "\xff", "\xff", "\x08"], "\xd5" => ["?", "\xff", "\xfe", "p"], "\xd6" => ["?", "\xff", "\xff", "\x10"], "\xd7" => ["?", "\xff", "\xfc", "\x80"], "\xd8" => ["?", "\xff", "\xc8"], "\xd9" => ["?", "\xff", "\xca"], "\xda" => ["?", "\xff", "\xfe", "\x80"], "\xdb" => ["?", "\xff", "\xfe", "\x90"], "\xdc" => ["?", "\xff", "\xff", "\xf4"], "\xdd" => ["?", "\xff", "\xff", "\x18"], "\xde" => ["?", "\xff", "\xff", " "], "\xdf" => ["?", "\xff", "\xff", "("], "\xe0" => ["?", "\xff", "\xb0"], "\xe1" => ["?", "\xff", "\xfc", "\xc0"], "\xe2" => ["?", "\xff", "\xb4"], "\xe3" => ["?", "\xff", "\xcc"], "\xe4" => ["?", "\xff", "\xe9"], "\xe5" => ["?", "\xff", "\xce"], "\xe6" => ["?", "\xff", "\xd0"], "\xe7" => ["?", "\xff", "\xf9", "\x80"], "\xe8" => ["?", "\xff", "\xea"], "\xe9" => ["?", "\xff", "\xeb"], "\xea" => ["?", "\xff", "\xfd", "\xc0"], "\xeb" => ["?", "\xff", "\xfd", "\xe0"], "\xec" => ["?", "\xff", "\xfd", "\x00"], "\xed" => ["?", "\xff", "\xfd", "@"], "\xee" => ["?", "\xff", "\xfe", "\xa0"], "\xef" => ["?", "\xff", "\xfa", "\x00"], "\xf0" => ["?", "\xff", "\xfe", "\xb0"], "\xf1" => ["?", "\xff", "\xff", "0"], "\xf2" => ["?", "\xff", "\xfe", "\xc0"], "\xf3" => ["?", "\xff", "\xfe", "\xd0"], "\xf4" => ["?", "\xff", "\xff", "8"], "\xf5" => ["?", "\xff", "\xff", "@"], "\xf6" => ["?", "\xff", "\xff", "H"], "\xf7" => ["?", "\xff", "\xff", "P"], "\xf8" => ["?", "\xff", "\xff", "X"], "\xf9" => ["?", "\xff", "\xff", "\xf8"], "\xfa" => ["?", "\xff", "\xff", "`"], "\xfb" => ["?", "\xff", "\xff", "h"], "\xfc" => ["?", "\xff", "\xff", "p"], "\xfd" => ["?", "\xff", "\xff", "x"], "\xfe" => ["?", "\xff", "\xff", "\x80"], "\xff" => ["?", "\xff", "\xfe", "\xe0"]], ["\x00" => ["\x1f", "\xf8"], "\x01" => ["\x1f", "\xff", "\xf6", "\x00"], "\x02" => ["\x1f", "\xff", "\xff", "\xc4"], "\x03" => ["\x1f", "\xff", "\xff", "\xc6"], "\x04" => ["\x1f", "\xff", "\xff", "\xc8"], "\x05" => ["\x1f", "\xff", "\xff", "\xca"], "\x06" => ["\x1f", "\xff", "\xff", "\xcc"], "\x07" => ["\x1f", "\xff", "\xff", "\xce"], "\x08" => ["\x1f", "\xff", "\xff", "\xd0"], "\t" => ["\x1f", "\xff", "\xfd", "@"], "\n" => ["\x1f", "\xff", "\xff", "\xfe", "\x00"], "\v" => ["\x1f", "\xff", "\xff", "\xd2"], "\f" => ["\x1f", "\xff", "\xff", "\xd4"], "\r" => ["\x1f", "\xff", "\xff", "\xfe", "\x80"], "\x0e" => ["\x1f", "\xff", "\xff", "\xd6"], "\x0f" => ["\x1f", "\xff", "\xff", "\xd8"], "\x10" => ["\x1f", "\xff", "\xff", "\xda"], "\x11" => ["\x1f", "\xff", "\xff", "\xdc"], "\x12" => ["\x1f", "\xff", "\xff", "\xde"], "\x13" => ["\x1f", "\xff", "\xff", "\xe0"], "\x14" => ["\x1f", "\xff", "\xff", "\xe2"], "\x15" => ["\x1f", "\xff", "\xff", "\xe4"], "\x16" => ["\x1f", "\xff", "\xff", "\xff", "\x00"], "\x17" => ["\x1f", "\xff", "\xff", "\xe6"], "\x18" => ["\x1f", "\xff", "\xff", "\xe8"], "\x19" => ["\x1f", "\xff", "\xff", "\xea"], "\x1a" => ["\x1f", "\xff", "\xff", "\xec"], "\x1b" => ["\x1f", "\xff", "\xff", "\xee"], "\x1c" => ["\x1f", "\xff", "\xff", "\xf0"], "\x1d" => ["\x1f", "\xff", "\xff", "\xf2"], "\x1e" => ["\x1f", "\xff", "\xff", "\xf4"], "\x1f" => ["\x1f", "\xff", "\xff", "\xf6"], " " => ["\n", "\x00"], "!" => ["\x1f", "\xc0"], "\"" => ["\x1f", "\xc8"], "#" => ["\x1f", "\xf4"], "\$" => ["\x1f", "\xf9"], "%" => ["\n", "\x80"], "&" => ["\x1f", "\x00"], "'" => ["\x1f", "\xe8"], "(" => ["\x1f", "\xd0"], ")" => ["\x1f", "\xd8"], "*" => ["\x1f", " "], "+" => ["\x1f", "\xec"], "," => ["\x1f", "@"], "-" => ["\v", "\x00"], "." => ["\v", "\x80"], "/" => ["\f", "\x00"], ["\x00"], ["\x01"], ["\x02"], ["\f", "\x80"], ["\r", "\x00"], ["\r", "\x80"], ["\x0e", "\x00"], ["\x0e", "\x80"], ["\x0f", "\x00"], ["\x0f", "\x80"], ":" => ["\x17", "\x00"], ";" => ["\x1f", "`"], "<" => ["\x1f", "\xff", "\x00"], "=" => ["\x10", "\x00"], ">" => ["\x1f", "\xf6"], "?" => ["\x1f", "\xe0"], "@" => ["\x1f", "\xfa"], "A" => ["\x10", "\x80"], "B" => ["\x17", "@"], "C" => ["\x17", "\x80"], "D" => ["\x17", "\xc0"], "E" => ["\x18", "\x00"], "F" => ["\x18", "@"], "G" => ["\x18", "\x80"], "H" => ["\x18", "\xc0"], "I" => ["\x19", "\x00"], "J" => ["\x19", "@"], "K" => ["\x19", "\x80"], "L" => ["\x19", "\xc0"], "M" => ["\x1a", "\x00"], "N" => ["\x1a", "@"], "O" => ["\x1a", "\x80"], "P" => ["\x1a", "\xc0"], "Q" => ["\x1b", "\x00"], "R" => ["\x1b", "@"], "S" => ["\x1b", "\x80"], "T" => ["\x1b", "\xc0"], "U" => ["\x1c", "\x00"], "V" => ["\x1c", "@"], "W" => ["\x1c", "\x80"], "X" => ["\x1f", "\x80"], "Y" => ["\x1c", "\xc0"], "Z" => ["\x1f", "\xa0"], "[" => ["\x1f", "\xfb"], "\\" => ["\x1f", "\xff", "\xc0"], "]" => ["\x1f", "\xfc"], "^" => ["\x1f", "\xfe", "\x00"], "_" => ["\x11", "\x00"], "`" => ["\x1f", "\xff", "@"], "a" => ["\x03"], "b" => ["\x11", "\x80"], "c" => ["\x04"], "d" => ["\x12", "\x00"], "e" => ["\x05"], "f" => ["\x12", "\x80"], "g" => ["\x13", "\x00"], "h" => ["\x13", "\x80"], "i" => ["\x06"], "j" => ["\x1d", "\x00"], "k" => ["\x1d", "@"], "l" => ["\x14", "\x00"], "m" => ["\x14", "\x80"], "n" => ["\x15", "\x00"], "o" => ["\x07"], "p" => ["\x15", "\x80"], "q" => ["\x1d", "\x80"], "r" => ["\x16", "\x00"], "s" => ["\x08"], "t" => ["\t"], "u" => ["\x16", "\x80"], "v" => ["\x1d", "\xc0"], "w" => ["\x1e", "\x00"], "x" => ["\x1e", "@"], "y" => ["\x1e", "\x80"], "z" => ["\x1e", "\xc0"], "{" => ["\x1f", "\xff", "\x80"], "|" => ["\x1f", "\xf0"], "}" => ["\x1f", "\xfe", "\x80"], "~" => ["\x1f", "\xfd"], "" => ["\x1f", "\xff", "\xff", "\xf8"], "\x80" => ["\x1f", "\xff", "\xcc"], "\x81" => ["\x1f", "\xff", "\xe9", "\x00"], "\x82" => ["\x1f", "\xff", "\xce"], "\x83" => ["\x1f", "\xff", "\xd0"], "\x84" => ["\x1f", "\xff", "\xe9", "\x80"], "\x85" => ["\x1f", "\xff", "\xea", "\x00"], "\x86" => ["\x1f", "\xff", "\xea", "\x80"], "\x87" => ["\x1f", "\xff", "\xf6", "@"], "\x88" => ["\x1f", "\xff", "\xeb", "\x00"], "\x89" => ["\x1f", "\xff", "\xf6", "\x80"], "\x8a" => ["\x1f", "\xff", "\xf6", "\xc0"], "\x8b" => ["\x1f", "\xff", "\xf7", "\x00"], "\x8c" => ["\x1f", "\xff", "\xf7", "@"], "\x8d" => ["\x1f", "\xff", "\xf7", "\x80"], "\x8e" => ["\x1f", "\xff", "\xfd", "`"], "\x8f" => ["\x1f", "\xff", "\xf7", "\xc0"], "\x90" => ["\x1f", "\xff", "\xfd", "\x80"], "\x91" => ["\x1f", "\xff", "\xfd", "\xa0"], "\x92" => ["\x1f", "\xff", "\xeb", "\x80"], "\x93" => ["\x1f", "\xff", "\xf8", "\x00"], "\x94" => ["\x1f", "\xff", "\xfd", "\xc0"], "\x95" => ["\x1f", "\xff", "\xf8", "@"], "\x96" => ["\x1f", "\xff", "\xf8", "\x80"], "\x97" => ["\x1f", "\xff", "\xf8", "\xc0"], "\x98" => ["\x1f", "\xff", "\xf9", "\x00"], "\x99" => ["\x1f", "\xff", "\xdc"], "\x9a" => ["\x1f", "\xff", "\xec", "\x00"], "\x9b" => ["\x1f", "\xff", "\xf9", "@"], "\x9c" => ["\x1f", "\xff", "\xec", "\x80"], "\x9d" => ["\x1f", "\xff", "\xf9", "\x80"], "\x9e" => ["\x1f", "\xff", "\xf9", "\xc0"], "\x9f" => ["\x1f", "\xff", "\xfd", "\xe0"], "\xa0" => ["\x1f", "\xff", "\xed", "\x00"], "\xa1" => ["\x1f", "\xff", "\xdd"], "\xa2" => ["\x1f", "\xff", "\xd2"], "\xa3" => ["\x1f", "\xff", "\xed", "\x80"], "\xa4" => ["\x1f", "\xff", "\xee", "\x00"], "\xa5" => ["\x1f", "\xff", "\xfa", "\x00"], "\xa6" => ["\x1f", "\xff", "\xfa", "@"], "\xa7" => ["\x1f", "\xff", "\xde"], "\xa8" => ["\x1f", "\xff", "\xfa", "\x80"], "\xa9" => ["\x1f", "\xff", "\xee", "\x80"], "\xaa" => ["\x1f", "\xff", "\xef", "\x00"], "\xab" => ["\x1f", "\xff", "\xfe", "\x00"], "\xac" => ["\x1f", "\xff", "\xdf"], "\xad" => ["\x1f", "\xff", "\xef", "\x80"], "\xae" => ["\x1f", "\xff", "\xfa", "\xc0"], "\xaf" => ["\x1f", "\xff", "\xfb", "\x00"], "\xb0" => ["\x1f", "\xff", "\xe0"], "\xb1" => ["\x1f", "\xff", "\xe1"], "\xb2" => ["\x1f", "\xff", "\xf0", "\x00"], "\xb3" => ["\x1f", "\xff", "\xe2"], "\xb4" => ["\x1f", "\xff", "\xfb", "@"], "\xb5" => ["\x1f", "\xff", "\xf0", "\x80"], "\xb6" => ["\x1f", "\xff", "\xfb", "\x80"], "\xb7" => ["\x1f", "\xff", "\xfb", "\xc0"], "\xb8" => ["\x1f", "\xff", "\xd4"], "\xb9" => ["\x1f", "\xff", "\xf1", "\x00"], "\xba" => ["\x1f", "\xff", "\xf1", "\x80"], "\xbb" => ["\x1f", "\xff", "\xf2", "\x00"], "\xbc" => ["\x1f", "\xff", "\xfc", "\x00"], "\xbd" => ["\x1f", "\xff", "\xf2", "\x80"], "\xbe" => ["\x1f", "\xff", "\xf3", "\x00"], "\xbf" => ["\x1f", "\xff", "\xfc", "@"], "\xc0" => ["\x1f", "\xff", "\xff", "\x00"], "\xc1" => ["\x1f", "\xff", "\xff", "\x08"], "\xc2" => ["\x1f", "\xff", "\xd6"], "\xc3" => ["\x1f", "\xff", "\xc4"], "\xc4" => ["\x1f", "\xff", "\xf3", "\x80"], "\xc5" => ["\x1f", "\xff", "\xfc", "\x80"], "\xc6" => ["\x1f", "\xff", "\xf4", "\x00"], "\xc7" => ["\x1f", "\xff", "\xfe", "\xc0"], "\xc8" => ["\x1f", "\xff", "\xff", "\x10"], "\xc9" => ["\x1f", "\xff", "\xff", "\x18"], "\xca" => ["\x1f", "\xff", "\xff", " "], "\xcb" => ["\x1f", "\xff", "\xff", "x"], "\xcc" => ["\x1f", "\xff", "\xff", "|"], "\xcd" => ["\x1f", "\xff", "\xff", "("], "\xce" => ["\x1f", "\xff", "\xfe", " "], "\xcf" => ["\x1f", "\xff", "\xfe", "\xd0"], "\xd0" => ["\x1f", "\xff", "\xc8"], "\xd1" => ["\x1f", "\xff", "\xe3"], "\xd2" => ["\x1f", "\xff", "\xff", "0"], "\xd3" => ["\x1f", "\xff", "\xff", "\x80"], "\xd4" => ["\x1f", "\xff", "\xff", "\x84"], "\xd5" => ["\x1f", "\xff", "\xff", "8"], "\xd6" => ["\x1f", "\xff", "\xff", "\x88"], "\xd7" => ["\x1f", "\xff", "\xfe", "@"], "\xd8" => ["\x1f", "\xff", "\xe4"], "\xd9" => ["\x1f", "\xff", "\xe5"], "\xda" => ["\x1f", "\xff", "\xff", "@"], "\xdb" => ["\x1f", "\xff", "\xff", "H"], "\xdc" => ["\x1f", "\xff", "\xff", "\xfa"], "\xdd" => ["\x1f", "\xff", "\xff", "\x8c"], "\xde" => ["\x1f", "\xff", "\xff", "\x90"], "\xdf" => ["\x1f", "\xff", "\xff", "\x94"], "\xe0" => ["\x1f", "\xff", "\xd8"], "\xe1" => ["\x1f", "\xff", "\xfe", "`"], "\xe2" => ["\x1f", "\xff", "\xda"], "\xe3" => ["\x1f", "\xff", "\xe6"], "\xe4" => ["\x1f", "\xff", "\xf4", "\x80"], "\xe5" => ["\x1f", "\xff", "\xe7"], "\xe6" => ["\x1f", "\xff", "\xe8"], "\xe7" => ["\x1f", "\xff", "\xfc", "\xc0"], "\xe8" => ["\x1f", "\xff", "\xf5", "\x00"], "\xe9" => ["\x1f", "\xff", "\xf5", "\x80"], "\xea" => ["\x1f", "\xff", "\xfe", "\xe0"], "\xeb" => ["\x1f", "\xff", "\xfe", "\xf0"], "\xec" => ["\x1f", "\xff", "\xfe", "\x80"], "\xed" => ["\x1f", "\xff", "\xfe", "\xa0"], "\xee" => ["\x1f", "\xff", "\xff", "P"], "\xef" => ["\x1f", "\xff", "\xfd", "\x00"], "\xf0" => ["\x1f", "\xff", "\xff", "X"], "\xf1" => ["\x1f", "\xff", "\xff", "\x98"], "\xf2" => ["\x1f", "\xff", "\xff", "`"], "\xf3" => ["\x1f", "\xff", "\xff", "h"], "\xf4" => ["\x1f", "\xff", "\xff", "\x9c"], "\xf5" => ["\x1f", "\xff", "\xff", "\xa0"], "\xf6" => ["\x1f", "\xff", "\xff", "\xa4"], "\xf7" => ["\x1f", "\xff", "\xff", "\xa8"], "\xf8" => ["\x1f", "\xff", "\xff", "\xac"], "\xf9" => ["\x1f", "\xff", "\xff", "\xfc"], "\xfa" => ["\x1f", "\xff", "\xff", "\xb0"], "\xfb" => ["\x1f", "\xff", "\xff", "\xb4"], "\xfc" => ["\x1f", "\xff", "\xff", "\xb8"], "\xfd" => ["\x1f", "\xff", "\xff", "\xbc"], "\xfe" => ["\x1f", "\xff", "\xff", "\xc0"], "\xff" => ["\x1f", "\xff", "\xff", "p"]], ["\x00" => ["\x0f", "\xfc", "\x00"], "\x01" => ["\x0f", "\xff", "\xfb", "\x00"], "\x02" => ["\x0f", "\xff", "\xff", "\xe2"], "\x03" => ["\x0f", "\xff", "\xff", "\xe3"], "\x04" => ["\x0f", "\xff", "\xff", "\xe4"], "\x05" => ["\x0f", "\xff", "\xff", "\xe5"], "\x06" => ["\x0f", "\xff", "\xff", "\xe6"], "\x07" => ["\x0f", "\xff", "\xff", "\xe7"], "\x08" => ["\x0f", "\xff", "\xff", "\xe8"], "\t" => ["\x0f", "\xff", "\xfe", "\xa0"], "\n" => ["\x0f", "\xff", "\xff", "\xff", "\x00"], "\v" => ["\x0f", "\xff", "\xff", "\xe9"], "\f" => ["\x0f", "\xff", "\xff", "\xea"], "\r" => ["\x0f", "\xff", "\xff", "\xff", "@"], "\x0e" => ["\x0f", "\xff", "\xff", "\xeb"], "\x0f" => ["\x0f", "\xff", "\xff", "\xec"], "\x10" => ["\x0f", "\xff", "\xff", "\xed"], "\x11" => ["\x0f", "\xff", "\xff", "\xee"], "\x12" => ["\x0f", "\xff", "\xff", "\xef"], "\x13" => ["\x0f", "\xff", "\xff", "\xf0"], "\x14" => ["\x0f", "\xff", "\xff", "\xf1"], "\x15" => ["\x0f", "\xff", "\xff", "\xf2"], "\x16" => ["\x0f", "\xff", "\xff", "\xff", "\x80"], "\x17" => ["\x0f", "\xff", "\xff", "\xf3"], "\x18" => ["\x0f", "\xff", "\xff", "\xf4"], "\x19" => ["\x0f", "\xff", "\xff", "\xf5"], "\x1a" => ["\x0f", "\xff", "\xff", "\xf6"], "\x1b" => ["\x0f", "\xff", "\xff", "\xf7"], "\x1c" => ["\x0f", "\xff", "\xff", "\xf8"], "\x1d" => ["\x0f", "\xff", "\xff", "\xf9"], "\x1e" => ["\x0f", "\xff", "\xff", "\xfa"], "\x1f" => ["\x0f", "\xff", "\xff", "\xfb"], " " => ["\x05", "\x00"], "!" => ["\x0f", "\xe0"], "\"" => ["\x0f", "\xe4"], "#" => ["\x0f", "\xfa"], "\$" => ["\x0f", "\xfc", "\x80"], "%" => ["\x05", "@"], "&" => ["\x0f", "\x80"], "'" => ["\x0f", "\xf4"], "(" => ["\x0f", "\xe8"], ")" => ["\x0f", "\xec"], "*" => ["\x0f", "\x90"], "+" => ["\x0f", "\xf6"], "," => ["\x0f", "\xa0"], "-" => ["\x05", "\x80"], "." => ["\x05", "\xc0"], "/" => ["\x06", "\x00"], ["\x00", "\x00"], ["\x00", "\x80"], ["\x01", "\x00"], ["\x06", "@"], ["\x06", "\x80"], ["\x06", "\xc0"], ["\x07", "\x00"], ["\x07", "@"], ["\x07", "\x80"], ["\x07", "\xc0"], ":" => ["\v", "\x80"], ";" => ["\x0f", "\xb0"], "<" => ["\x0f", "\xff", "\x80"], "=" => ["\x08", "\x00"], ">" => ["\x0f", "\xfb"], "?" => ["\x0f", "\xf0"], "@" => ["\x0f", "\xfd", "\x00"], "A" => ["\x08", "@"], "B" => ["\v", "\xa0"], "C" => ["\v", "\xc0"], "D" => ["\v", "\xe0"], "E" => ["\f", "\x00"], "F" => ["\f", " "], "G" => ["\f", "@"], "H" => ["\f", "`"], "I" => ["\f", "\x80"], "J" => ["\f", "\xa0"], "K" => ["\f", "\xc0"], "L" => ["\f", "\xe0"], "M" => ["\r", "\x00"], "N" => ["\r", " "], "O" => ["\r", "@"], "P" => ["\r", "`"], "Q" => ["\r", "\x80"], "R" => ["\r", "\xa0"], "S" => ["\r", "\xc0"], "T" => ["\r", "\xe0"], "U" => ["\x0e", "\x00"], "V" => ["\x0e", " "], "W" => ["\x0e", "@"], "X" => ["\x0f", "\xc0"], "Y" => ["\x0e", "`"], "Z" => ["\x0f", "\xd0"], "[" => ["\x0f", "\xfd", "\x80"], "\\" => ["\x0f", "\xff", "\xe0"], "]" => ["\x0f", "\xfe", "\x00"], "^" => ["\x0f", "\xff", "\x00"], "_" => ["\x08", "\x80"], "`" => ["\x0f", "\xff", "\xa0"], "a" => ["\x01", "\x80"], "b" => ["\x08", "\xc0"], "c" => ["\x02", "\x00"], "d" => ["\t", "\x00"], "e" => ["\x02", "\x80"], "f" => ["\t", "@"], "g" => ["\t", "\x80"], "h" => ["\t", "\xc0"], "i" => ["\x03", "\x00"], "j" => ["\x0e", "\x80"], "k" => ["\x0e", "\xa0"], "l" => ["\n", "\x00"], "m" => ["\n", "@"], "n" => ["\n", "\x80"], "o" => ["\x03", "\x80"], "p" => ["\n", "\xc0"], "q" => ["\x0e", "\xc0"], "r" => ["\v", "\x00"], "s" => ["\x04", "\x00"], "t" => ["\x04", "\x80"], "u" => ["\v", "@"], "v" => ["\x0e", "\xe0"], "w" => ["\x0f", "\x00"], "x" => ["\x0f", " "], "y" => ["\x0f", "@"], "z" => ["\x0f", "`"], "{" => ["\x0f", "\xff", "\xc0"], "|" => ["\x0f", "\xf8"], "}" => ["\x0f", "\xff", "@"], "~" => ["\x0f", "\xfe", "\x80"], "" => ["\x0f", "\xff", "\xff", "\xfc"], "\x80" => ["\x0f", "\xff", "\xe6"], "\x81" => ["\x0f", "\xff", "\xf4", "\x80"], "\x82" => ["\x0f", "\xff", "\xe7"], "\x83" => ["\x0f", "\xff", "\xe8"], "\x84" => ["\x0f", "\xff", "\xf4", "\xc0"], "\x85" => ["\x0f", "\xff", "\xf5", "\x00"], "\x86" => ["\x0f", "\xff", "\xf5", "@"], "\x87" => ["\x0f", "\xff", "\xfb", " "], "\x88" => ["\x0f", "\xff", "\xf5", "\x80"], "\x89" => ["\x0f", "\xff", "\xfb", "@"], "\x8a" => ["\x0f", "\xff", "\xfb", "`"], "\x8b" => ["\x0f", "\xff", "\xfb", "\x80"], "\x8c" => ["\x0f", "\xff", "\xfb", "\xa0"], "\x8d" => ["\x0f", "\xff", "\xfb", "\xc0"], "\x8e" => ["\x0f", "\xff", "\xfe", "\xb0"], "\x8f" => ["\x0f", "\xff", "\xfb", "\xe0"], "\x90" => ["\x0f", "\xff", "\xfe", "\xc0"], "\x91" => ["\x0f", "\xff", "\xfe", "\xd0"], "\x92" => ["\x0f", "\xff", "\xf5", "\xc0"], "\x93" => ["\x0f", "\xff", "\xfc", "\x00"], "\x94" => ["\x0f", "\xff", "\xfe", "\xe0"], "\x95" => ["\x0f", "\xff", "\xfc", " "], "\x96" => ["\x0f", "\xff", "\xfc", "@"], "\x97" => ["\x0f", "\xff", "\xfc", "`"], "\x98" => ["\x0f", "\xff", "\xfc", "\x80"], "\x99" => ["\x0f", "\xff", "\xee", "\x00"], "\x9a" => ["\x0f", "\xff", "\xf6", "\x00"], "\x9b" => ["\x0f", "\xff", "\xfc", "\xa0"], "\x9c" => ["\x0f", "\xff", "\xf6", "@"], "\x9d" => ["\x0f", "\xff", "\xfc", "\xc0"], "\x9e" => ["\x0f", "\xff", "\xfc", "\xe0"], "\x9f" => ["\x0f", "\xff", "\xfe", "\xf0"], "\xa0" => ["\x0f", "\xff", "\xf6", "\x80"], "\xa1" => ["\x0f", "\xff", "\xee", "\x80"], "\xa2" => ["\x0f", "\xff", "\xe9"], "\xa3" => ["\x0f", "\xff", "\xf6", "\xc0"], "\xa4" => ["\x0f", "\xff", "\xf7", "\x00"], "\xa5" => ["\x0f", "\xff", "\xfd", "\x00"], "\xa6" => ["\x0f", "\xff", "\xfd", " "], "\xa7" => ["\x0f", "\xff", "\xef", "\x00"], "\xa8" => ["\x0f", "\xff", "\xfd", "@"], "\xa9" => ["\x0f", "\xff", "\xf7", "@"], "\xaa" => ["\x0f", "\xff", "\xf7", "\x80"], "\xab" => ["\x0f", "\xff", "\xff", "\x00"], "\xac" => ["\x0f", "\xff", "\xef", "\x80"], "\xad" => ["\x0f", "\xff", "\xf7", "\xc0"], "\xae" => ["\x0f", "\xff", "\xfd", "`"], "\xaf" => ["\x0f", "\xff", "\xfd", "\x80"], "\xb0" => ["\x0f", "\xff", "\xf0", "\x00"], "\xb1" => ["\x0f", "\xff", "\xf0", "\x80"], "\xb2" => ["\x0f", "\xff", "\xf8", "\x00"], "\xb3" => ["\x0f", "\xff", "\xf1", "\x00"], "\xb4" => ["\x0f", "\xff", "\xfd", "\xa0"], "\xb5" => ["\x0f", "\xff", "\xf8", "@"], "\xb6" => ["\x0f", "\xff", "\xfd", "\xc0"], "\xb7" => ["\x0f", "\xff", "\xfd", "\xe0"], "\xb8" => ["\x0f", "\xff", "\xea"], "\xb9" => ["\x0f", "\xff", "\xf8", "\x80"], "\xba" => ["\x0f", "\xff", "\xf8", "\xc0"], "\xbb" => ["\x0f", "\xff", "\xf9", "\x00"], "\xbc" => ["\x0f", "\xff", "\xfe", "\x00"], "\xbd" => ["\x0f", "\xff", "\xf9", "@"], "\xbe" => ["\x0f", "\xff", "\xf9", "\x80"], "\xbf" => ["\x0f", "\xff", "\xfe", " "], "\xc0" => ["\x0f", "\xff", "\xff", "\x80"], "\xc1" => ["\x0f", "\xff", "\xff", "\x84"], "\xc2" => ["\x0f", "\xff", "\xeb"], "\xc3" => ["\x0f", "\xff", "\xe2"], "\xc4" => ["\x0f", "\xff", "\xf9", "\xc0"], "\xc5" => ["\x0f", "\xff", "\xfe", "@"], "\xc6" => ["\x0f", "\xff", "\xfa", "\x00"], "\xc7" => ["\x0f", "\xff", "\xff", "`"], "\xc8" => ["\x0f", "\xff", "\xff", "\x88"], "\xc9" => ["\x0f", "\xff", "\xff", "\x8c"], "\xca" => ["\x0f", "\xff", "\xff", "\x90"], "\xcb" => ["\x0f", "\xff", "\xff", "\xbc"], "\xcc" => ["\x0f", "\xff", "\xff", "\xbe"], "\xcd" => ["\x0f", "\xff", "\xff", "\x94"], "\xce" => ["\x0f", "\xff", "\xff", "\x10"], "\xcf" => ["\x0f", "\xff", "\xff", "h"], "\xd0" => ["\x0f", "\xff", "\xe4"], "\xd1" => ["\x0f", "\xff", "\xf1", "\x80"], "\xd2" => ["\x0f", "\xff", "\xff", "\x98"], "\xd3" => ["\x0f", "\xff", "\xff", "\xc0"], "\xd4" => ["\x0f", "\xff", "\xff", "\xc2"], "\xd5" => ["\x0f", "\xff", "\xff", "\x9c"], "\xd6" => ["\x0f", "\xff", "\xff", "\xc4"], "\xd7" => ["\x0f", "\xff", "\xff", " "], "\xd8" => ["\x0f", "\xff", "\xf2", "\x00"], "\xd9" => ["\x0f", "\xff", "\xf2", "\x80"], "\xda" => ["\x0f", "\xff", "\xff", "\xa0"], "\xdb" => ["\x0f", "\xff", "\xff", "\xa4"], "\xdc" => ["\x0f", "\xff", "\xff", "\xfd"], "\xdd" => ["\x0f", "\xff", "\xff", "\xc6"], "\xde" => ["\x0f", "\xff", "\xff", "\xc8"], "\xdf" => ["\x0f", "\xff", "\xff", "\xca"], "\xe0" => ["\x0f", "\xff", "\xec"], "\xe1" => ["\x0f", "\xff", "\xff", "0"], "\xe2" => ["\x0f", "\xff", "\xed"], "\xe3" => ["\x0f", "\xff", "\xf3", "\x00"], "\xe4" => ["\x0f", "\xff", "\xfa", "@"], "\xe5" => ["\x0f", "\xff", "\xf3", "\x80"], "\xe6" => ["\x0f", "\xff", "\xf4", "\x00"], "\xe7" => ["\x0f", "\xff", "\xfe", "`"], "\xe8" => ["\x0f", "\xff", "\xfa", "\x80"], "\xe9" => ["\x0f", "\xff", "\xfa", "\xc0"], "\xea" => ["\x0f", "\xff", "\xff", "p"], "\xeb" => ["\x0f", "\xff", "\xff", "x"], "\xec" => ["\x0f", "\xff", "\xff", "@"], "\xed" => ["\x0f", "\xff", "\xff", "P"], "\xee" => ["\x0f", "\xff", "\xff", "\xa8"], "\xef" => ["\x0f", "\xff", "\xfe", "\x80"], "\xf0" => ["\x0f", "\xff", "\xff", "\xac"], "\xf1" => ["\x0f", "\xff", "\xff", "\xcc"], "\xf2" => ["\x0f", "\xff", "\xff", "\xb0"], "\xf3" => ["\x0f", "\xff", "\xff", "\xb4"], "\xf4" => ["\x0f", "\xff", "\xff", "\xce"], "\xf5" => ["\x0f", "\xff", "\xff", "\xd0"], "\xf6" => ["\x0f", "\xff", "\xff", "\xd2"], "\xf7" => ["\x0f", "\xff", "\xff", "\xd4"], "\xf8" => ["\x0f", "\xff", "\xff", "\xd6"], "\xf9" => ["\x0f", "\xff", "\xff", "\xfe"], "\xfa" => ["\x0f", "\xff", "\xff", "\xd8"], "\xfb" => ["\x0f", "\xff", "\xff", "\xda"], "\xfc" => ["\x0f", "\xff", "\xff", "\xdc"], "\xfd" => ["\x0f", "\xff", "\xff", "\xde"], "\xfe" => ["\x0f", "\xff", "\xff", "\xe0"], "\xff" => ["\x0f", "\xff", "\xff", "\xb8"]], ["\x00" => ["\x07", "\xfe", "\x00"], "\x01" => ["\x07", "\xff", "\xfd", "\x80"], "\x02" => ["\x07", "\xff", "\xff", "\xf1", "\x00"], "\x03" => ["\x07", "\xff", "\xff", "\xf1", "\x80"], "\x04" => ["\x07", "\xff", "\xff", "\xf2", "\x00"], "\x05" => ["\x07", "\xff", "\xff", "\xf2", "\x80"], "\x06" => ["\x07", "\xff", "\xff", "\xf3", "\x00"], "\x07" => ["\x07", "\xff", "\xff", "\xf3", "\x80"], "\x08" => ["\x07", "\xff", "\xff", "\xf4", "\x00"], "\t" => ["\x07", "\xff", "\xff", "P"], "\n" => ["\x07", "\xff", "\xff", "\xff", "\x80"], "\v" => ["\x07", "\xff", "\xff", "\xf4", "\x80"], "\f" => ["\x07", "\xff", "\xff", "\xf5", "\x00"], "\r" => ["\x07", "\xff", "\xff", "\xff", "\xa0"], "\x0e" => ["\x07", "\xff", "\xff", "\xf5", "\x80"], "\x0f" => ["\x07", "\xff", "\xff", "\xf6", "\x00"], "\x10" => ["\x07", "\xff", "\xff", "\xf6", "\x80"], "\x11" => ["\x07", "\xff", "\xff", "\xf7", "\x00"], "\x12" => ["\x07", "\xff", "\xff", "\xf7", "\x80"], "\x13" => ["\x07", "\xff", "\xff", "\xf8", "\x00"], "\x14" => ["\x07", "\xff", "\xff", "\xf8", "\x80"], "\x15" => ["\x07", "\xff", "\xff", "\xf9", "\x00"], "\x16" => ["\x07", "\xff", "\xff", "\xff", "\xc0"], "\x17" => ["\x07", "\xff", "\xff", "\xf9", "\x80"], "\x18" => ["\x07", "\xff", "\xff", "\xfa", "\x00"], "\x19" => ["\x07", "\xff", "\xff", "\xfa", "\x80"], "\x1a" => ["\x07", "\xff", "\xff", "\xfb", "\x00"], "\x1b" => ["\x07", "\xff", "\xff", "\xfb", "\x80"], "\x1c" => ["\x07", "\xff", "\xff", "\xfc", "\x00"], "\x1d" => ["\x07", "\xff", "\xff", "\xfc", "\x80"], "\x1e" => ["\x07", "\xff", "\xff", "\xfd", "\x00"], "\x1f" => ["\x07", "\xff", "\xff", "\xfd", "\x80"], " " => ["\x02", "\x80"], "!" => ["\x07", "\xf0"], "\"" => ["\x07", "\xf2"], "#" => ["\x07", "\xfd", "\x00"], "\$" => ["\x07", "\xfe", "@"], "%" => ["\x02", "\xa0"], "&" => ["\x07", "\xc0"], "'" => ["\x07", "\xfa"], "(" => ["\x07", "\xf4"], ")" => ["\x07", "\xf6"], "*" => ["\x07", "\xc8"], "+" => ["\x07", "\xfb"], "," => ["\x07", "\xd0"], "-" => ["\x02", "\xc0"], "." => ["\x02", "\xe0"], "/" => ["\x03", "\x00"], ["\x00", "\x00"], ["\x00", "@"], ["\x00", "\x80"], ["\x03", " "], ["\x03", "@"], ["\x03", "`"], ["\x03", "\x80"], ["\x03", "\xa0"], ["\x03", "\xc0"], ["\x03", "\xe0"], ":" => ["\x05", "\xc0"], ";" => ["\x07", "\xd8"], "<" => ["\x07", "\xff", "\xc0"], "=" => ["\x04", "\x00"], ">" => ["\x07", "\xfd", "\x80"], "?" => ["\x07", "\xf8"], "@" => ["\x07", "\xfe", "\x80"], "A" => ["\x04", " "], "B" => ["\x05", "\xd0"], "C" => ["\x05", "\xe0"], "D" => ["\x05", "\xf0"], "E" => ["\x06", "\x00"], "F" => ["\x06", "\x10"], "G" => ["\x06", " "], "H" => ["\x06", "0"], "I" => ["\x06", "@"], "J" => ["\x06", "P"], "K" => ["\x06", "`"], "L" => ["\x06", "p"], "M" => ["\x06", "\x80"], "N" => ["\x06", "\x90"], "O" => ["\x06", "\xa0"], "P" => ["\x06", "\xb0"], "Q" => ["\x06", "\xc0"], "R" => ["\x06", "\xd0"], "S" => ["\x06", "\xe0"], "T" => ["\x06", "\xf0"], "U" => ["\x07", "\x00"], "V" => ["\x07", "\x10"], "W" => ["\x07", " "], "X" => ["\x07", "\xe0"], "Y" => ["\x07", "0"], "Z" => ["\x07", "\xe8"], "[" => ["\x07", "\xfe", "\xc0"], "\\" => ["\x07", "\xff", "\xf0"], "]" => ["\x07", "\xff", "\x00"], "^" => ["\x07", "\xff", "\x80"], "_" => ["\x04", "@"], "`" => ["\x07", "\xff", "\xd0"], "a" => ["\x00", "\xc0"], "b" => ["\x04", "`"], "c" => ["\x01", "\x00"], "d" => ["\x04", "\x80"], "e" => ["\x01", "@"], "f" => ["\x04", "\xa0"], "g" => ["\x04", "\xc0"], "h" => ["\x04", "\xe0"], "i" => ["\x01", "\x80"], "j" => ["\x07", "@"], "k" => ["\x07", "P"], "l" => ["\x05", "\x00"], "m" => ["\x05", " "], "n" => ["\x05", "@"], "o" => ["\x01", "\xc0"], "p" => ["\x05", "`"], "q" => ["\x07", "`"], "r" => ["\x05", "\x80"], "s" => ["\x02", "\x00"], "t" => ["\x02", "@"], "u" => ["\x05", "\xa0"], "v" => ["\x07", "p"], "w" => ["\x07", "\x80"], "x" => ["\x07", "\x90"], "y" => ["\x07", "\xa0"], "z" => ["\x07", "\xb0"], "{" => ["\x07", "\xff", "\xe0"], "|" => ["\x07", "\xfc"], "}" => ["\x07", "\xff", "\xa0"], "~" => ["\x07", "\xff", "@"], "" => ["\x07", "\xff", "\xff", "\xfe", "\x00"], "\x80" => ["\x07", "\xff", "\xf3", "\x00"], "\x81" => ["\x07", "\xff", "\xfa", "@"], "\x82" => ["\x07", "\xff", "\xf3", "\x80"], "\x83" => ["\x07", "\xff", "\xf4", "\x00"], "\x84" => ["\x07", "\xff", "\xfa", "`"], "\x85" => ["\x07", "\xff", "\xfa", "\x80"], "\x86" => ["\x07", "\xff", "\xfa", "\xa0"], "\x87" => ["\x07", "\xff", "\xfd", "\x90"], "\x88" => ["\x07", "\xff", "\xfa", "\xc0"], "\x89" => ["\x07", "\xff", "\xfd", "\xa0"], "\x8a" => ["\x07", "\xff", "\xfd", "\xb0"], "\x8b" => ["\x07", "\xff", "\xfd", "\xc0"], "\x8c" => ["\x07", "\xff", "\xfd", "\xd0"], "\x8d" => ["\x07", "\xff", "\xfd", "\xe0"], "\x8e" => ["\x07", "\xff", "\xff", "X"], "\x8f" => ["\x07", "\xff", "\xfd", "\xf0"], "\x90" => ["\x07", "\xff", "\xff", "`"], "\x91" => ["\x07", "\xff", "\xff", "h"], "\x92" => ["\x07", "\xff", "\xfa", "\xe0"], "\x93" => ["\x07", "\xff", "\xfe", "\x00"], "\x94" => ["\x07", "\xff", "\xff", "p"], "\x95" => ["\x07", "\xff", "\xfe", "\x10"], "\x96" => ["\x07", "\xff", "\xfe", " "], "\x97" => ["\x07", "\xff", "\xfe", "0"], "\x98" => ["\x07", "\xff", "\xfe", "@"], "\x99" => ["\x07", "\xff", "\xf7", "\x00"], "\x9a" => ["\x07", "\xff", "\xfb", "\x00"], "\x9b" => ["\x07", "\xff", "\xfe", "P"], "\x9c" => ["\x07", "\xff", "\xfb", " "], "\x9d" => ["\x07", "\xff", "\xfe", "`"], "\x9e" => ["\x07", "\xff", "\xfe", "p"], "\x9f" => ["\x07", "\xff", "\xff", "x"], "\xa0" => ["\x07", "\xff", "\xfb", "@"], "\xa1" => ["\x07", "\xff", "\xf7", "@"], "\xa2" => ["\x07", "\xff", "\xf4", "\x80"], "\xa3" => ["\x07", "\xff", "\xfb", "`"], "\xa4" => ["\x07", "\xff", "\xfb", "\x80"], "\xa5" => ["\x07", "\xff", "\xfe", "\x80"], "\xa6" => ["\x07", "\xff", "\xfe", "\x90"], "\xa7" => ["\x07", "\xff", "\xf7", "\x80"], "\xa8" => ["\x07", "\xff", "\xfe", "\xa0"], "\xa9" => ["\x07", "\xff", "\xfb", "\xa0"], "\xaa" => ["\x07", "\xff", "\xfb", "\xc0"], "\xab" => ["\x07", "\xff", "\xff", "\x80"], "\xac" => ["\x07", "\xff", "\xf7", "\xc0"], "\xad" => ["\x07", "\xff", "\xfb", "\xe0"], "\xae" => ["\x07", "\xff", "\xfe", "\xb0"], "\xaf" => ["\x07", "\xff", "\xfe", "\xc0"], "\xb0" => ["\x07", "\xff", "\xf8", "\x00"], "\xb1" => ["\x07", "\xff", "\xf8", "@"], "\xb2" => ["\x07", "\xff", "\xfc", "\x00"], "\xb3" => ["\x07", "\xff", "\xf8", "\x80"], "\xb4" => ["\x07", "\xff", "\xfe", "\xd0"], "\xb5" => ["\x07", "\xff", "\xfc", " "], "\xb6" => ["\x07", "\xff", "\xfe", "\xe0"], "\xb7" => ["\x07", "\xff", "\xfe", "\xf0"], "\xb8" => ["\x07", "\xff", "\xf5", "\x00"], "\xb9" => ["\x07", "\xff", "\xfc", "@"], "\xba" => ["\x07", "\xff", "\xfc", "`"], "\xbb" => ["\x07", "\xff", "\xfc", "\x80"], "\xbc" => ["\x07", "\xff", "\xff", "\x00"], "\xbd" => ["\x07", "\xff", "\xfc", "\xa0"], "\xbe" => ["\x07", "\xff", "\xfc", "\xc0"], "\xbf" => ["\x07", "\xff", "\xff", "\x10"], "\xc0" => ["\x07", "\xff", "\xff", "\xc0"], "\xc1" => ["\x07", "\xff", "\xff", "\xc2"], "\xc2" => ["\x07", "\xff", "\xf5", "\x80"], "\xc3" => ["\x07", "\xff", "\xf1"], "\xc4" => ["\x07", "\xff", "\xfc", "\xe0"], "\xc5" => ["\x07", "\xff", "\xff", " "], "\xc6" => ["\x07", "\xff", "\xfd", "\x00"], "\xc7" => ["\x07", "\xff", "\xff", "\xb0"], "\xc8" => ["\x07", "\xff", "\xff", "\xc4"], "\xc9" => ["\x07", "\xff", "\xff", "\xc6"], "\xca" => ["\x07", "\xff", "\xff", "\xc8"], "\xcb" => ["\x07", "\xff", "\xff", "\xde"], "\xcc" => ["\x07", "\xff", "\xff", "\xdf"], "\xcd" => ["\x07", "\xff", "\xff", "\xca"], "\xce" => ["\x07", "\xff", "\xff", "\x88"], "\xcf" => ["\x07", "\xff", "\xff", "\xb4"], "\xd0" => ["\x07", "\xff", "\xf2"], "\xd1" => ["\x07", "\xff", "\xf8", "\xc0"], "\xd2" => ["\x07", "\xff", "\xff", "\xcc"], "\xd3" => ["\x07", "\xff", "\xff", "\xe0"], "\xd4" => ["\x07", "\xff", "\xff", "\xe1"], "\xd5" => ["\x07", "\xff", "\xff", "\xce"], "\xd6" => ["\x07", "\xff", "\xff", "\xe2"], "\xd7" => ["\x07", "\xff", "\xff", "\x90"], "\xd8" => ["\x07", "\xff", "\xf9", "\x00"], "\xd9" => ["\x07", "\xff", "\xf9", "@"], "\xda" => ["\x07", "\xff", "\xff", "\xd0"], "\xdb" => ["\x07", "\xff", "\xff", "\xd2"], "\xdc" => ["\x07", "\xff", "\xff", "\xfe", "\x80"], "\xdd" => ["\x07", "\xff", "\xff", "\xe3"], "\xde" => ["\x07", "\xff", "\xff", "\xe4"], "\xdf" => ["\x07", "\xff", "\xff", "\xe5"], "\xe0" => ["\x07", "\xff", "\xf6", "\x00"], "\xe1" => ["\x07", "\xff", "\xff", "\x98"], "\xe2" => ["\x07", "\xff", "\xf6", "\x80"], "\xe3" => ["\x07", "\xff", "\xf9", "\x80"], "\xe4" => ["\x07", "\xff", "\xfd", " "], "\xe5" => ["\x07", "\xff", "\xf9", "\xc0"], "\xe6" => ["\x07", "\xff", "\xfa", "\x00"], "\xe7" => ["\x07", "\xff", "\xff", "0"], "\xe8" => ["\x07", "\xff", "\xfd", "@"], "\xe9" => ["\x07", "\xff", "\xfd", "`"], "\xea" => ["\x07", "\xff", "\xff", "\xb8"], "\xeb" => ["\x07", "\xff", "\xff", "\xbc"], "\xec" => ["\x07", "\xff", "\xff", "\xa0"], "\xed" => ["\x07", "\xff", "\xff", "\xa8"], "\xee" => ["\x07", "\xff", "\xff", "\xd4"], "\xef" => ["\x07", "\xff", "\xff", "@"], "\xf0" => ["\x07", "\xff", "\xff", "\xd6"], "\xf1" => ["\x07", "\xff", "\xff", "\xe6"], "\xf2" => ["\x07", "\xff", "\xff", "\xd8"], "\xf3" => ["\x07", "\xff", "\xff", "\xda"], "\xf4" => ["\x07", "\xff", "\xff", "\xe7"], "\xf5" => ["\x07", "\xff", "\xff", "\xe8"], "\xf6" => ["\x07", "\xff", "\xff", "\xe9"], "\xf7" => ["\x07", "\xff", "\xff", "\xea"], "\xf8" => ["\x07", "\xff", "\xff", "\xeb"], "\xf9" => ["\x07", "\xff", "\xff", "\xff", "\x00"], "\xfa" => ["\x07", "\xff", "\xff", "\xec"], "\xfb" => ["\x07", "\xff", "\xff", "\xed"], "\xfc" => ["\x07", "\xff", "\xff", "\xee"], "\xfd" => ["\x07", "\xff", "\xff", "\xef"], "\xfe" => ["\x07", "\xff", "\xff", "\xf0"], "\xff" => ["\x07", "\xff", "\xff", "\xdc"]], ["\x00" => ["\x03", "\xff", "\x00"], "\x01" => ["\x03", "\xff", "\xfe", "\xc0"], "\x02" => ["\x03", "\xff", "\xff", "\xf8", "\x80"], "\x03" => ["\x03", "\xff", "\xff", "\xf8", "\xc0"], "\x04" => ["\x03", "\xff", "\xff", "\xf9", "\x00"], "\x05" => ["\x03", "\xff", "\xff", "\xf9", "@"], "\x06" => ["\x03", "\xff", "\xff", "\xf9", "\x80"], "\x07" => ["\x03", "\xff", "\xff", "\xf9", "\xc0"], "\x08" => ["\x03", "\xff", "\xff", "\xfa", "\x00"], "\t" => ["\x03", "\xff", "\xff", "\xa8"], "\n" => ["\x03", "\xff", "\xff", "\xff", "\xc0"], "\v" => ["\x03", "\xff", "\xff", "\xfa", "@"], "\f" => ["\x03", "\xff", "\xff", "\xfa", "\x80"], "\r" => ["\x03", "\xff", "\xff", "\xff", "\xd0"], "\x0e" => ["\x03", "\xff", "\xff", "\xfa", "\xc0"], "\x0f" => ["\x03", "\xff", "\xff", "\xfb", "\x00"], "\x10" => ["\x03", "\xff", "\xff", "\xfb", "@"], "\x11" => ["\x03", "\xff", "\xff", "\xfb", "\x80"], "\x12" => ["\x03", "\xff", "\xff", "\xfb", "\xc0"], "\x13" => ["\x03", "\xff", "\xff", "\xfc", "\x00"], "\x14" => ["\x03", "\xff", "\xff", "\xfc", "@"], "\x15" => ["\x03", "\xff", "\xff", "\xfc", "\x80"], "\x16" => ["\x03", "\xff", "\xff", "\xff", "\xe0"], "\x17" => ["\x03", "\xff", "\xff", "\xfc", "\xc0"], "\x18" => ["\x03", "\xff", "\xff", "\xfd", "\x00"], "\x19" => ["\x03", "\xff", "\xff", "\xfd", "@"], "\x1a" => ["\x03", "\xff", "\xff", "\xfd", "\x80"], "\x1b" => ["\x03", "\xff", "\xff", "\xfd", "\xc0"], "\x1c" => ["\x03", "\xff", "\xff", "\xfe", "\x00"], "\x1d" => ["\x03", "\xff", "\xff", "\xfe", "@"], "\x1e" => ["\x03", "\xff", "\xff", "\xfe", "\x80"], "\x1f" => ["\x03", "\xff", "\xff", "\xfe", "\xc0"], " " => ["\x01", "@"], "!" => ["\x03", "\xf8"], "\"" => ["\x03", "\xf9"], "#" => ["\x03", "\xfe", "\x80"], "\$" => ["\x03", "\xff", " "], "%" => ["\x01", "P"], "&" => ["\x03", "\xe0"], "'" => ["\x03", "\xfd", "\x00"], "(" => ["\x03", "\xfa"], ")" => ["\x03", "\xfb"], "*" => ["\x03", "\xe4"], "+" => ["\x03", "\xfd", "\x80"], "," => ["\x03", "\xe8"], "-" => ["\x01", "`"], "." => ["\x01", "p"], "/" => ["\x01", "\x80"], ["\x00", "\x00"], ["\x00", " "], ["\x00", "@"], ["\x01", "\x90"], ["\x01", "\xa0"], ["\x01", "\xb0"], ["\x01", "\xc0"], ["\x01", "\xd0"], ["\x01", "\xe0"], ["\x01", "\xf0"], ":" => ["\x02", "\xe0"], ";" => ["\x03", "\xec"], "<" => ["\x03", "\xff", "\xe0"], "=" => ["\x02", "\x00"], ">" => ["\x03", "\xfe", "\xc0"], "?" => ["\x03", "\xfc"], "@" => ["\x03", "\xff", "@"], "A" => ["\x02", "\x10"], "B" => ["\x02", "\xe8"], "C" => ["\x02", "\xf0"], "D" => ["\x02", "\xf8"], "E" => ["\x03", "\x00"], "F" => ["\x03", "\x08"], "G" => ["\x03", "\x10"], "H" => ["\x03", "\x18"], "I" => ["\x03", " "], "J" => ["\x03", "("], "K" => ["\x03", "0"], "L" => ["\x03", "8"], "M" => ["\x03", "@"], "N" => ["\x03", "H"], "O" => ["\x03", "P"], "P" => ["\x03", "X"], "Q" => ["\x03", "`"], "R" => ["\x03", "h"], "S" => ["\x03", "p"], "T" => ["\x03", "x"], "U" => ["\x03", "\x80"], "V" => ["\x03", "\x88"], "W" => ["\x03", "\x90"], "X" => ["\x03", "\xf0"], "Y" => ["\x03", "\x98"], "Z" => ["\x03", "\xf4"], "[" => ["\x03", "\xff", "`"], "\\" => ["\x03", "\xff", "\xf8", "\x00"], "]" => ["\x03", "\xff", "\x80"], "^" => ["\x03", "\xff", "\xc0"], "_" => ["\x02", " "], "`" => ["\x03", "\xff", "\xe8"], "a" => ["\x00", "`"], "b" => ["\x02", "0"], "c" => ["\x00", "\x80"], "d" => ["\x02", "@"], "e" => ["\x00", "\xa0"], "f" => ["\x02", "P"], "g" => ["\x02", "`"], "h" => ["\x02", "p"], "i" => ["\x00", "\xc0"], "j" => ["\x03", "\xa0"], "k" => ["\x03", "\xa8"], "l" => ["\x02", "\x80"], "m" => ["\x02", "\x90"], "n" => ["\x02", "\xa0"], "o" => ["\x00", "\xe0"], "p" => ["\x02", "\xb0"], "q" => ["\x03", "\xb0"], "r" => ["\x02", "\xc0"], "s" => ["\x01", "\x00"], "t" => ["\x01", " "], "u" => ["\x02", "\xd0"], "v" => ["\x03", "\xb8"], "w" => ["\x03", "\xc0"], "x" => ["\x03", "\xc8"], "y" => ["\x03", "\xd0"], "z" => ["\x03", "\xd8"], "{" => ["\x03", "\xff", "\xf0"], "|" => ["\x03", "\xfe", "\x00"], "}" => ["\x03", "\xff", "\xd0"], "~" => ["\x03", "\xff", "\xa0"], "" => ["\x03", "\xff", "\xff", "\xff", "\x00"], "\x80" => ["\x03", "\xff", "\xf9", "\x80"], "\x81" => ["\x03", "\xff", "\xfd", " "], "\x82" => ["\x03", "\xff", "\xf9", "\xc0"], "\x83" => ["\x03", "\xff", "\xfa", "\x00"], "\x84" => ["\x03", "\xff", "\xfd", "0"], "\x85" => ["\x03", "\xff", "\xfd", "@"], "\x86" => ["\x03", "\xff", "\xfd", "P"], "\x87" => ["\x03", "\xff", "\xfe", "\xc8"], "\x88" => ["\x03", "\xff", "\xfd", "`"], "\x89" => ["\x03", "\xff", "\xfe", "\xd0"], "\x8a" => ["\x03", "\xff", "\xfe", "\xd8"], "\x8b" => ["\x03", "\xff", "\xfe", "\xe0"], "\x8c" => ["\x03", "\xff", "\xfe", "\xe8"], "\x8d" => ["\x03", "\xff", "\xfe", "\xf0"], "\x8e" => ["\x03", "\xff", "\xff", "\xac"], "\x8f" => ["\x03", "\xff", "\xfe", "\xf8"], "\x90" => ["\x03", "\xff", "\xff", "\xb0"], "\x91" => ["\x03", "\xff", "\xff", "\xb4"], "\x92" => ["\x03", "\xff", "\xfd", "p"], "\x93" => ["\x03", "\xff", "\xff", "\x00"], "\x94" => ["\x03", "\xff", "\xff", "\xb8"], "\x95" => ["\x03", "\xff", "\xff", "\x08"], "\x96" => ["\x03", "\xff", "\xff", "\x10"], "\x97" => ["\x03", "\xff", "\xff", "\x18"], "\x98" => ["\x03", "\xff", "\xff", " "], "\x99" => ["\x03", "\xff", "\xfb", "\x80"], "\x9a" => ["\x03", "\xff", "\xfd", "\x80"], "\x9b" => ["\x03", "\xff", "\xff", "("], "\x9c" => ["\x03", "\xff", "\xfd", "\x90"], "\x9d" => ["\x03", "\xff", "\xff", "0"], "\x9e" => ["\x03", "\xff", "\xff", "8"], "\x9f" => ["\x03", "\xff", "\xff", "\xbc"], "\xa0" => ["\x03", "\xff", "\xfd", "\xa0"], "\xa1" => ["\x03", "\xff", "\xfb", "\xa0"], "\xa2" => ["\x03", "\xff", "\xfa", "@"], "\xa3" => ["\x03", "\xff", "\xfd", "\xb0"], "\xa4" => ["\x03", "\xff", "\xfd", "\xc0"], "\xa5" => ["\x03", "\xff", "\xff", "@"], "\xa6" => ["\x03", "\xff", "\xff", "H"], "\xa7" => ["\x03", "\xff", "\xfb", "\xc0"], "\xa8" => ["\x03", "\xff", "\xff", "P"], "\xa9" => ["\x03", "\xff", "\xfd", "\xd0"], "\xaa" => ["\x03", "\xff", "\xfd", "\xe0"], "\xab" => ["\x03", "\xff", "\xff", "\xc0"], "\xac" => ["\x03", "\xff", "\xfb", "\xe0"], "\xad" => ["\x03", "\xff", "\xfd", "\xf0"], "\xae" => ["\x03", "\xff", "\xff", "X"], "\xaf" => ["\x03", "\xff", "\xff", "`"], "\xb0" => ["\x03", "\xff", "\xfc", "\x00"], "\xb1" => ["\x03", "\xff", "\xfc", " "], "\xb2" => ["\x03", "\xff", "\xfe", "\x00"], "\xb3" => ["\x03", "\xff", "\xfc", "@"], "\xb4" => ["\x03", "\xff", "\xff", "h"], "\xb5" => ["\x03", "\xff", "\xfe", "\x10"], "\xb6" => ["\x03", "\xff", "\xff", "p"], "\xb7" => ["\x03", "\xff", "\xff", "x"], "\xb8" => ["\x03", "\xff", "\xfa", "\x80"], "\xb9" => ["\x03", "\xff", "\xfe", " "], "\xba" => ["\x03", "\xff", "\xfe", "0"], "\xbb" => ["\x03", "\xff", "\xfe", "@"], "\xbc" => ["\x03", "\xff", "\xff", "\x80"], "\xbd" => ["\x03", "\xff", "\xfe", "P"], "\xbe" => ["\x03", "\xff", "\xfe", "`"], "\xbf" => ["\x03", "\xff", "\xff", "\x88"], "\xc0" => ["\x03", "\xff", "\xff", "\xe0"], "\xc1" => ["\x03", "\xff", "\xff", "\xe1"], "\xc2" => ["\x03", "\xff", "\xfa", "\xc0"], "\xc3" => ["\x03", "\xff", "\xf8", "\x80"], "\xc4" => ["\x03", "\xff", "\xfe", "p"], "\xc5" => ["\x03", "\xff", "\xff", "\x90"], "\xc6" => ["\x03", "\xff", "\xfe", "\x80"], "\xc7" => ["\x03", "\xff", "\xff", "\xd8"], "\xc8" => ["\x03", "\xff", "\xff", "\xe2"], "\xc9" => ["\x03", "\xff", "\xff", "\xe3"], "\xca" => ["\x03", "\xff", "\xff", "\xe4"], "\xcb" => ["\x03", "\xff", "\xff", "\xef", "\x00"], "\xcc" => ["\x03", "\xff", "\xff", "\xef", "\x80"], "\xcd" => ["\x03", "\xff", "\xff", "\xe5"], "\xce" => ["\x03", "\xff", "\xff", "\xc4"], "\xcf" => ["\x03", "\xff", "\xff", "\xda"], "\xd0" => ["\x03", "\xff", "\xf9", "\x00"], "\xd1" => ["\x03", "\xff", "\xfc", "`"], "\xd2" => ["\x03", "\xff", "\xff", "\xe6"], "\xd3" => ["\x03", "\xff", "\xff", "\xf0", "\x00"], "\xd4" => ["\x03", "\xff", "\xff", "\xf0", "\x80"], "\xd5" => ["\x03", "\xff", "\xff", "\xe7"], "\xd6" => ["\x03", "\xff", "\xff", "\xf1", "\x00"], "\xd7" => ["\x03", "\xff", "\xff", "\xc8"], "\xd8" => ["\x03", "\xff", "\xfc", "\x80"], "\xd9" => ["\x03", "\xff", "\xfc", "\xa0"], "\xda" => ["\x03", "\xff", "\xff", "\xe8"], "\xdb" => ["\x03", "\xff", "\xff", "\xe9"], "\xdc" => ["\x03", "\xff", "\xff", "\xff", "@"], "\xdd" => ["\x03", "\xff", "\xff", "\xf1", "\x80"], "\xde" => ["\x03", "\xff", "\xff", "\xf2", "\x00"], "\xdf" => ["\x03", "\xff", "\xff", "\xf2", "\x80"], "\xe0" => ["\x03", "\xff", "\xfb", "\x00"], "\xe1" => ["\x03", "\xff", "\xff", "\xcc"], "\xe2" => ["\x03", "\xff", "\xfb", "@"], "\xe3" => ["\x03", "\xff", "\xfc", "\xc0"], "\xe4" => ["\x03", "\xff", "\xfe", "\x90"], "\xe5" => ["\x03", "\xff", "\xfc", "\xe0"], "\xe6" => ["\x03", "\xff", "\xfd", "\x00"], "\xe7" => ["\x03", "\xff", "\xff", "\x98"], "\xe8" => ["\x03", "\xff", "\xfe", "\xa0"], "\xe9" => ["\x03", "\xff", "\xfe", "\xb0"], "\xea" => ["\x03", "\xff", "\xff", "\xdc"], "\xeb" => ["\x03", "\xff", "\xff", "\xde"], "\xec" => ["\x03", "\xff", "\xff", "\xd0"], "\xed" => ["\x03", "\xff", "\xff", "\xd4"], "\xee" => ["\x03", "\xff", "\xff", "\xea"], "\xef" => ["\x03", "\xff", "\xff", "\xa0"], "\xf0" => ["\x03", "\xff", "\xff", "\xeb"], "\xf1" => ["\x03", "\xff", "\xff", "\xf3", "\x00"], "\xf2" => ["\x03", "\xff", "\xff", "\xec"], "\xf3" => ["\x03", "\xff", "\xff", "\xed"], "\xf4" => ["\x03", "\xff", "\xff", "\xf3", "\x80"], "\xf5" => ["\x03", "\xff", "\xff", "\xf4", "\x00"], "\xf6" => ["\x03", "\xff", "\xff", "\xf4", "\x80"], "\xf7" => ["\x03", "\xff", "\xff", "\xf5", "\x00"], "\xf8" => ["\x03", "\xff", "\xff", "\xf5", "\x80"], "\xf9" => ["\x03", "\xff", "\xff", "\xff", "\x80"], "\xfa" => ["\x03", "\xff", "\xff", "\xf6", "\x00"], "\xfb" => ["\x03", "\xff", "\xff", "\xf6", "\x80"], "\xfc" => ["\x03", "\xff", "\xff", "\xf7", "\x00"], "\xfd" => ["\x03", "\xff", "\xff", "\xf7", "\x80"], "\xfe" => ["\x03", "\xff", "\xff", "\xf8", "\x00"], "\xff" => ["\x03", "\xff", "\xff", "\xee"]], ["\x00" => ["\x01", "\xff", "\x80"], "\x01" => ["\x01", "\xff", "\xff", "`"], "\x02" => ["\x01", "\xff", "\xff", "\xfc", "@"], "\x03" => ["\x01", "\xff", "\xff", "\xfc", "`"], "\x04" => ["\x01", "\xff", "\xff", "\xfc", "\x80"], "\x05" => ["\x01", "\xff", "\xff", "\xfc", "\xa0"], "\x06" => ["\x01", "\xff", "\xff", "\xfc", "\xc0"], "\x07" => ["\x01", "\xff", "\xff", "\xfc", "\xe0"], "\x08" => ["\x01", "\xff", "\xff", "\xfd", "\x00"], "\t" => ["\x01", "\xff", "\xff", "\xd4"], "\n" => ["\x01", "\xff", "\xff", "\xff", "\xe0"], "\v" => ["\x01", "\xff", "\xff", "\xfd", " "], "\f" => ["\x01", "\xff", "\xff", "\xfd", "@"], "\r" => ["\x01", "\xff", "\xff", "\xff", "\xe8"], "\x0e" => ["\x01", "\xff", "\xff", "\xfd", "`"], "\x0f" => ["\x01", "\xff", "\xff", "\xfd", "\x80"], "\x10" => ["\x01", "\xff", "\xff", "\xfd", "\xa0"], "\x11" => ["\x01", "\xff", "\xff", "\xfd", "\xc0"], "\x12" => ["\x01", "\xff", "\xff", "\xfd", "\xe0"], "\x13" => ["\x01", "\xff", "\xff", "\xfe", "\x00"], "\x14" => ["\x01", "\xff", "\xff", "\xfe", " "], "\x15" => ["\x01", "\xff", "\xff", "\xfe", "@"], "\x16" => ["\x01", "\xff", "\xff", "\xff", "\xf0"], "\x17" => ["\x01", "\xff", "\xff", "\xfe", "`"], "\x18" => ["\x01", "\xff", "\xff", "\xfe", "\x80"], "\x19" => ["\x01", "\xff", "\xff", "\xfe", "\xa0"], "\x1a" => ["\x01", "\xff", "\xff", "\xfe", "\xc0"], "\x1b" => ["\x01", "\xff", "\xff", "\xfe", "\xe0"], "\x1c" => ["\x01", "\xff", "\xff", "\xff", "\x00"], "\x1d" => ["\x01", "\xff", "\xff", "\xff", " "], "\x1e" => ["\x01", "\xff", "\xff", "\xff", "@"], "\x1f" => ["\x01", "\xff", "\xff", "\xff", "`"], " " => ["\x00", "\xa0"], "!" => ["\x01", "\xfc", "\x00"], "\"" => ["\x01", "\xfc", "\x80"], "#" => ["\x01", "\xff", "@"], "\$" => ["\x01", "\xff", "\x90"], "%" => ["\x00", "\xa8"], "&" => ["\x01", "\xf0"], "'" => ["\x01", "\xfe", "\x80"], "(" => ["\x01", "\xfd", "\x00"], ")" => ["\x01", "\xfd", "\x80"], "*" => ["\x01", "\xf2"], "+" => ["\x01", "\xfe", "\xc0"], "," => ["\x01", "\xf4"], "-" => ["\x00", "\xb0"], "." => ["\x00", "\xb8"], "/" => ["\x00", "\xc0"], ["\x00", "\x00"], ["\x00", "\x10"], ["\x00", " "], ["\x00", "\xc8"], ["\x00", "\xd0"], ["\x00", "\xd8"], ["\x00", "\xe0"], ["\x00", "\xe8"], ["\x00", "\xf0"], ["\x00", "\xf8"], ":" => ["\x01", "p"], ";" => ["\x01", "\xf6"], "<" => ["\x01", "\xff", "\xf0"], "=" => ["\x01", "\x00"], ">" => ["\x01", "\xff", "`"], "?" => ["\x01", "\xfe", "\x00"], "@" => ["\x01", "\xff", "\xa0"], "A" => ["\x01", "\x08"], "B" => ["\x01", "t"], "C" => ["\x01", "x"], "D" => ["\x01", "|"], "E" => ["\x01", "\x80"], "F" => ["\x01", "\x84"], "G" => ["\x01", "\x88"], "H" => ["\x01", "\x8c"], "I" => ["\x01", "\x90"], "J" => ["\x01", "\x94"], "K" => ["\x01", "\x98"], "L" => ["\x01", "\x9c"], "M" => ["\x01", "\xa0"], "N" => ["\x01", "\xa4"], "O" => ["\x01", "\xa8"], "P" => ["\x01", "\xac"], "Q" => ["\x01", "\xb0"], "R" => ["\x01", "\xb4"], "S" => ["\x01", "\xb8"], "T" => ["\x01", "\xbc"], "U" => ["\x01", "\xc0"], "V" => ["\x01", "\xc4"], "W" => ["\x01", "\xc8"], "X" => ["\x01", "\xf8"], "Y" => ["\x01", "\xcc"], "Z" => ["\x01", "\xfa"], "[" => ["\x01", "\xff", "\xb0"], "\\" => ["\x01", "\xff", "\xfc", "\x00"], "]" => ["\x01", "\xff", "\xc0"], "^" => ["\x01", "\xff", "\xe0"], "_" => ["\x01", "\x10"], "`" => ["\x01", "\xff", "\xf4"], "a" => ["\x00", "0"], "b" => ["\x01", "\x18"], "c" => ["\x00", "@"], "d" => ["\x01", " "], "e" => ["\x00", "P"], "f" => ["\x01", "("], "g" => ["\x01", "0"], "h" => ["\x01", "8"], "i" => ["\x00", "`"], "j" => ["\x01", "\xd0"], "k" => ["\x01", "\xd4"], "l" => ["\x01", "@"], "m" => ["\x01", "H"], "n" => ["\x01", "P"], "o" => ["\x00", "p"], "p" => ["\x01", "X"], "q" => ["\x01", "\xd8"], "r" => ["\x01", "`"], "s" => ["\x00", "\x80"], "t" => ["\x00", "\x90"], "u" => ["\x01", "h"], "v" => ["\x01", "\xdc"], "w" => ["\x01", "\xe0"], "x" => ["\x01", "\xe4"], "y" => ["\x01", "\xe8"], "z" => ["\x01", "\xec"], "{" => ["\x01", "\xff", "\xf8"], "|" => ["\x01", "\xff", "\x00"], "}" => ["\x01", "\xff", "\xe8"], "~" => ["\x01", "\xff", "\xd0"], "" => ["\x01", "\xff", "\xff", "\xff", "\x80"], "\x80" => ["\x01", "\xff", "\xfc", "\xc0"], "\x81" => ["\x01", "\xff", "\xfe", "\x90"], "\x82" => ["\x01", "\xff", "\xfc", "\xe0"], "\x83" => ["\x01", "\xff", "\xfd", "\x00"], "\x84" => ["\x01", "\xff", "\xfe", "\x98"], "\x85" => ["\x01", "\xff", "\xfe", "\xa0"], "\x86" => ["\x01", "\xff", "\xfe", "\xa8"], "\x87" => ["\x01", "\xff", "\xff", "d"], "\x88" => ["\x01", "\xff", "\xfe", "\xb0"], "\x89" => ["\x01", "\xff", "\xff", "h"], "\x8a" => ["\x01", "\xff", "\xff", "l"], "\x8b" => ["\x01", "\xff", "\xff", "p"], "\x8c" => ["\x01", "\xff", "\xff", "t"], "\x8d" => ["\x01", "\xff", "\xff", "x"], "\x8e" => ["\x01", "\xff", "\xff", "\xd6"], "\x8f" => ["\x01", "\xff", "\xff", "|"], "\x90" => ["\x01", "\xff", "\xff", "\xd8"], "\x91" => ["\x01", "\xff", "\xff", "\xda"], "\x92" => ["\x01", "\xff", "\xfe", "\xb8"], "\x93" => ["\x01", "\xff", "\xff", "\x80"], "\x94" => ["\x01", "\xff", "\xff", "\xdc"], "\x95" => ["\x01", "\xff", "\xff", "\x84"], "\x96" => ["\x01", "\xff", "\xff", "\x88"], "\x97" => ["\x01", "\xff", "\xff", "\x8c"], "\x98" => ["\x01", "\xff", "\xff", "\x90"], "\x99" => ["\x01", "\xff", "\xfd", "\xc0"], "\x9a" => ["\x01", "\xff", "\xfe", "\xc0"], "\x9b" => ["\x01", "\xff", "\xff", "\x94"], "\x9c" => ["\x01", "\xff", "\xfe", "\xc8"], "\x9d" => ["\x01", "\xff", "\xff", "\x98"], "\x9e" => ["\x01", "\xff", "\xff", "\x9c"], "\x9f" => ["\x01", "\xff", "\xff", "\xde"], "\xa0" => ["\x01", "\xff", "\xfe", "\xd0"], "\xa1" => ["\x01", "\xff", "\xfd", "\xd0"], "\xa2" => ["\x01", "\xff", "\xfd", " "], "\xa3" => ["\x01", "\xff", "\xfe", "\xd8"], "\xa4" => ["\x01", "\xff", "\xfe", "\xe0"], "\xa5" => ["\x01", "\xff", "\xff", "\xa0"], "\xa6" => ["\x01", "\xff", "\xff", "\xa4"], "\xa7" => ["\x01", "\xff", "\xfd", "\xe0"], "\xa8" => ["\x01", "\xff", "\xff", "\xa8"], "\xa9" => ["\x01", "\xff", "\xfe", "\xe8"], "\xaa" => ["\x01", "\xff", "\xfe", "\xf0"], "\xab" => ["\x01", "\xff", "\xff", "\xe0"], "\xac" => ["\x01", "\xff", "\xfd", "\xf0"], "\xad" => ["\x01", "\xff", "\xfe", "\xf8"], "\xae" => ["\x01", "\xff", "\xff", "\xac"], "\xaf" => ["\x01", "\xff", "\xff", "\xb0"], "\xb0" => ["\x01", "\xff", "\xfe", "\x00"], "\xb1" => ["\x01", "\xff", "\xfe", "\x10"], "\xb2" => ["\x01", "\xff", "\xff", "\x00"], "\xb3" => ["\x01", "\xff", "\xfe", " "], "\xb4" => ["\x01", "\xff", "\xff", "\xb4"], "\xb5" => ["\x01", "\xff", "\xff", "\x08"], "\xb6" => ["\x01", "\xff", "\xff", "\xb8"], "\xb7" => ["\x01", "\xff", "\xff", "\xbc"], "\xb8" => ["\x01", "\xff", "\xfd", "@"], "\xb9" => ["\x01", "\xff", "\xff", "\x10"], "\xba" => ["\x01", "\xff", "\xff", "\x18"], "\xbb" => ["\x01", "\xff", "\xff", " "], "\xbc" => ["\x01", "\xff", "\xff", "\xc0"], "\xbd" => ["\x01", "\xff", "\xff", "("], "\xbe" => ["\x01", "\xff", "\xff", "0"], "\xbf" => ["\x01", "\xff", "\xff", "\xc4"], "\xc0" => ["\x01", "\xff", "\xff", "\xf0", "\x00"], "\xc1" => ["\x01", "\xff", "\xff", "\xf0", "\x80"], "\xc2" => ["\x01", "\xff", "\xfd", "`"], "\xc3" => ["\x01", "\xff", "\xfc", "@"], "\xc4" => ["\x01", "\xff", "\xff", "8"], "\xc5" => ["\x01", "\xff", "\xff", "\xc8"], "\xc6" => ["\x01", "\xff", "\xff", "@"], "\xc7" => ["\x01", "\xff", "\xff", "\xec"], "\xc8" => ["\x01", "\xff", "\xff", "\xf1", "\x00"], "\xc9" => ["\x01", "\xff", "\xff", "\xf1", "\x80"], "\xca" => ["\x01", "\xff", "\xff", "\xf2", "\x00"], "\xcb" => ["\x01", "\xff", "\xff", "\xf7", "\x80"], "\xcc" => ["\x01", "\xff", "\xff", "\xf7", "\xc0"], "\xcd" => ["\x01", "\xff", "\xff", "\xf2", "\x80"], "\xce" => ["\x01", "\xff", "\xff", "\xe2"], "\xcf" => ["\x01", "\xff", "\xff", "\xed"], "\xd0" => ["\x01", "\xff", "\xfc", "\x80"], "\xd1" => ["\x01", "\xff", "\xfe", "0"], "\xd2" => ["\x01", "\xff", "\xff", "\xf3", "\x00"], "\xd3" => ["\x01", "\xff", "\xff", "\xf8", "\x00"], "\xd4" => ["\x01", "\xff", "\xff", "\xf8", "@"], "\xd5" => ["\x01", "\xff", "\xff", "\xf3", "\x80"], "\xd6" => ["\x01", "\xff", "\xff", "\xf8", "\x80"], "\xd7" => ["\x01", "\xff", "\xff", "\xe4"], "\xd8" => ["\x01", "\xff", "\xfe", "@"], "\xd9" => ["\x01", "\xff", "\xfe", "P"], "\xda" => ["\x01", "\xff", "\xff", "\xf4", "\x00"], "\xdb" => ["\x01", "\xff", "\xff", "\xf4", "\x80"], "\xdc" => ["\x01", "\xff", "\xff", "\xff", "\xa0"], "\xdd" => ["\x01", "\xff", "\xff", "\xf8", "\xc0"], "\xde" => ["\x01", "\xff", "\xff", "\xf9", "\x00"], "\xdf" => ["\x01", "\xff", "\xff", "\xf9", "@"], "\xe0" => ["\x01", "\xff", "\xfd", "\x80"], "\xe1" => ["\x01", "\xff", "\xff", "\xe6"], "\xe2" => ["\x01", "\xff", "\xfd", "\xa0"], "\xe3" => ["\x01", "\xff", "\xfe", "`"], "\xe4" => ["\x01", "\xff", "\xff", "H"], "\xe5" => ["\x01", "\xff", "\xfe", "p"], "\xe6" => ["\x01", "\xff", "\xfe", "\x80"], "\xe7" => ["\x01", "\xff", "\xff", "\xcc"], "\xe8" => ["\x01", "\xff", "\xff", "P"], "\xe9" => ["\x01", "\xff", "\xff", "X"], "\xea" => ["\x01", "\xff", "\xff", "\xee"], "\xeb" => ["\x01", "\xff", "\xff", "\xef"], "\xec" => ["\x01", "\xff", "\xff", "\xe8"], "\xed" => ["\x01", "\xff", "\xff", "\xea"], "\xee" => ["\x01", "\xff", "\xff", "\xf5", "\x00"], "\xef" => ["\x01", "\xff", "\xff", "\xd0"], "\xf0" => ["\x01", "\xff", "\xff", "\xf5", "\x80"], "\xf1" => ["\x01", "\xff", "\xff", "\xf9", "\x80"], "\xf2" => ["\x01", "\xff", "\xff", "\xf6", "\x00"], "\xf3" => ["\x01", "\xff", "\xff", "\xf6", "\x80"], "\xf4" => ["\x01", "\xff", "\xff", "\xf9", "\xc0"], "\xf5" => ["\x01", "\xff", "\xff", "\xfa", "\x00"], "\xf6" => ["\x01", "\xff", "\xff", "\xfa", "@"], "\xf7" => ["\x01", "\xff", "\xff", "\xfa", "\x80"], "\xf8" => ["\x01", "\xff", "\xff", "\xfa", "\xc0"], "\xf9" => ["\x01", "\xff", "\xff", "\xff", "\xc0"], "\xfa" => ["\x01", "\xff", "\xff", "\xfb", "\x00"], "\xfb" => ["\x01", "\xff", "\xff", "\xfb", "@"], "\xfc" => ["\x01", "\xff", "\xff", "\xfb", "\x80"], "\xfd" => ["\x01", "\xff", "\xff", "\xfb", "\xc0"], "\xfe" => ["\x01", "\xff", "\xff", "\xfc", "\x00"], "\xff" => ["\x01", "\xff", "\xff", "\xf7", "\x00"]]];<?php

namespace Amp\Http;

final class HPackException extends \Exception
{
}<?php

namespace Amp\Http;

use Amp\Http\Internal\HPackNative;
use Amp\Http\Internal\HPackNghttp2;
final class HPack
{
    /** @var HPackNative|HPackNghttp2 */
    private $implementation;
    /**
     *
     */
    public function __construct(int $tableSizeLimit = 4096)
    {
        if (HPackNghttp2::isSupported()) {
            $this->implementation = new HPackNghttp2($tableSizeLimit);
        } else {
            $this->implementation = new HPackNative($tableSizeLimit);
        }
    }
    /**
     * @param string $input Input to decode.
     * @param int $maxSize Maximum deflated size.
     *
     * @return (array | null) Decoded headers.
     */
    public function decode(string $input, int $maxSize) : ?array
    {
        return $this->implementation->decode($input, $maxSize);
    }
    /**
     * @param array $headers Headers to encode.
     *
     * @return string Encoded headers.
     *
     * @throws HPackException If encoding fails.
     */
    public function encode(array $headers) : string
    {
        return $this->implementation->encode($headers);
    }
}<?php

require __DIR__ . '/../vendor/autoload.php';
$root = __DIR__ . "/../vendor/http2jp/hpack-test-case";
$paths = \glob("{$root}/*/*.json");
foreach ($paths as $path) {
    if (\basename(\dirname($path)) === "raw-data") {
        continue;
    }
    $data = \json_decode(\file_get_contents($path));
    $cases = [];
    foreach ($data->cases as $case) {
        foreach ($case->headers as &$header) {
            $header = (array) $header;
            $header = [\key($header), \current($header)];
        }
        $cases[$case->seqno] = [\hex2bin($case->wire), $case->headers];
    }
    $tests[] = $cases;
}
$minDuration = \PHP_INT_MAX;
$minOps = \PHP_INT_MAX;
for ($i = 0; $i < 10; $i++) {
    $start = \microtime(true);
    $ops = 0;
    foreach ($tests as $test) {
        $hpack = new Amp\Http\Internal\HPackNative();
        foreach ($cases as [$input, $output]) {
            $headers = $hpack->decode($input, 4096);
            $hpack->encode($headers);
            if ($headers !== $output) {
                print 'Invalid headers' . \PHP_EOL;
                exit(1);
            }
            $ops++;
        }
    }
    $duration = \microtime(true) - $start;
    $minDuration = \min($minDuration, $duration);
    $minOps = \min($ops, $minOps);
}
print "{$minOps} in {$minDuration} seconds" . \PHP_EOL;<?php

require __DIR__ . '/../../vendor/autoload.php';
use Amp\Http\HPack;
$fuzzer->setTarget(function (string $input) {
    (new HPack())->decode($input, 8192);
});
$fuzzer->setMaxLen(1024);<?php

require __DIR__ . '/../../vendor/autoload.php';
use Amp\Http\HPack;
(new HPack())->decode(\file_get_contents($argv[1]), 8192);<?php

/**
 * The MIT License (MIT).
 *
 * Copyright (c) 2017 Christian LÃ¼ck
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished
 * to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
// Taken from https://github.com/leproxy/leproxy/blob/e2ca7917c17ac8b853800f5b390297a2a1525cf7/compile.php
$small = '';
$all = \token_get_all(\file_get_contents($argv[1]));
// search next non-whitespace/non-comment token
$next = function ($i) use(&$all) {
    for ($i = $i + 1; !isset($all[$i]) || \is_array($all[$i]) && ($all[$i][0] === T_COMMENT || $all[$i][0] === T_DOC_COMMENT || $all[$i][0] === T_WHITESPACE); ++$i) {
    }
    return $i;
};
// search previous non-whitespace/non-comment token
$prev = function ($i) use(&$all) {
    for ($i = $i - 1; $i >= 0 && (!isset($all[$i]) || \is_array($all[$i]) && ($all[$i][0] === T_COMMENT || $all[$i][0] === T_DOC_COMMENT || $all[$i][0] === T_WHITESPACE)); --$i) {
    }
    return $i;
};
$first = true;
foreach ($all as $i => $token) {
    if (\is_array($token) && ($token[0] === T_COMMENT || $token[0] === T_DOC_COMMENT)) {
        // remove all comments except first
        if ($first === true) {
            $first = false;
            continue;
        }
        unset($all[$i]);
    } elseif (\is_array($token) && $token[0] === T_PUBLIC) {
        // get next non-whitespace token after `public` visibility
        $token = $all[$next($i)];
        if (\is_array($token) && $token[0] === T_VARIABLE) {
            // use shorter variable notation `public $a` => `var $a`
            $all[$i] = [T_VAR, 'var'];
        } else {
            // remove unneeded public identifier `public static function a()` => `static function a()`
            unset($all[$i]);
        }
    } elseif (\is_array($token) && $token[0] === T_LNUMBER) {
        // Use shorter integer notation `0x0F` => `15` and `011` => `9`.
        // Technically, hex codes may be shorter for very large ints, but adding
        // another 2 leading chars is rarely worth it.
        // Optimizing floats is not really worth it, as they have many special
        // cases, such as e-notation and we would lose types for `0.0` => `0`.
        $all[$i][1] = (string) \intval($token[1], 0);
    } elseif (\is_array($token) && $token[0] === T_NEW) {
        // remove unneeded parenthesis for constructors without args `new a();` => `new a;`
        // jump over next token (class name), then next must be open parenthesis, followed by closing
        $open = $next($next($i));
        $close = $next($open);
        if ($all[$open] === '(' && $all[$close] === ')') {
            unset($all[$open], $all[$close]);
        }
    } elseif (\is_array($token) && $token[0] === T_STRING) {
        // replace certain functions with their shorter alias function name
        // http://php.net/manual/en/aliases.php
        static $replace = ['implode' => 'join', 'fwrite' => 'fputs', 'array_key_exists' => 'key_exists', 'current' => 'pos'];
        // check this has a replacement and "looks like" a function call
        // this works on a number of assumptions, such as not being aliased/namespaced
        if (isset($replace[$token[1]])) {
            $p = $all[$prev($i)];
            if ($all[$next($i)] === '(' && (!\is_array($p) || !\in_array($p[0], [T_FUNCTION, T_OBJECT_OPERATOR, T_DOUBLE_COLON, T_NEW]))) {
                $all[$i][1] = $replace[$all[$i][1]];
            }
        }
    } elseif (\is_array($token) && $token[0] === T_EXIT) {
        // replace `exit` with shorter alias `die`
        // it's a language construct, not a function (see above)
        $all[$i][1] = 'die';
    } elseif (\is_array($token) && $token[0] === T_RETURN) {
        // replace `return null;` with `return;`
        $t = $next($i);
        if (\is_array($all[$t]) && $all[$t][0] === T_STRING && $all[$t][1] === 'null' && $all[$next($t)] === ';') {
            unset($all[$t]);
        }
    }
}
$all = \array_values($all);
foreach ($all as $i => $token) {
    if (\is_array($token) && $token[0] === T_WHITESPACE) {
        if (\strpos($token[1], "\n") !== false) {
            $token = \strpos("()[]<>=+-*/%|,.:?!'\"\n", \Phabel\Target\Php80\Polyfill::substr($small, -1)) === false ? "\n" : '';
        } else {
            $last = \Phabel\Target\Php80\Polyfill::substr($small, -1);
            $next = isset($all[$i + 1]) ? \Phabel\Target\Php80\Polyfill::substr(\is_array($all[$i + 1]) ? $all[$i + 1][1] : $all[$i + 1], 0, 1) : ' ';
            $token = \strpos('()[]{}<>;=+-*/%&|,.:?!@\'"
', $last) !== false || \strpos('()[]{}<>;=+-*/%&|,.:?!@\'"\\$', $next) !== false ? '' : ' ';
        }
    }
    $small .= isset($token[1]) ? $token[1] : $token;
}
\file_put_contents($argv[1], $small);{
    "name": "amphp/hpack",
    "homepage": "https://github.com/amphp/hpack",
    "description": "HTTP/2 HPack implementation.",
    "keywords": [
        "http-2",
        "hpack",
        "headers"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Bob Weinand"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.1"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master",
        "http2jp/hpack-test-case": "^1",
        "phpunit/phpunit": "^6 | ^7"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Http\\": "src"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Http\\": "test"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "3.x-dev"
        }
    },
    "repositories": [
        {
            "type": "package",
            "package": {
                "name": "http2jp/hpack-test-case",
                "version": "1.0",
                "source": {
                    "url": "https://github.com/http2jp/hpack-test-case",
                    "type": "git",
                    "reference": "origin/master"
                }
            }
        }
    ]
}
<?php

namespace Amp\Socket;

use Amp\ByteStream\StreamException;
class SocketException extends StreamException
{
}<?php

namespace Amp\Socket;

use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
final class DatagramSocket
{
    public const DEFAULT_CHUNK_SIZE = 8192;
    /**
     * Create a new Datagram (UDP server) on the specified server address.
     *
     * @param string $uri URI in scheme://host:port format. UDP is assumed if no scheme is present.
     * @param (BindContext | null) $context Context options for listening.
     *
     * @return DatagramSocket
     *
     * @throws SocketException If binding to the specified URI failed.
     * @throws \Error If an invalid scheme is given.
     */
    public static function bind(string $uri, ?BindContext $context = null) : self
    {
        $context = $context ?? new BindContext();
        $scheme = \strstr($uri, '://', true);
        if ($scheme === false) {
            $uri = 'udp://' . $uri;
        } elseif ($scheme !== 'udp') {
            throw new \Error('Only udp scheme allowed for datagram creation');
        }
        $streamContext = \stream_context_create($context->toStreamContextArray());
        // Error reporting suppressed since stream_socket_server() emits an E_WARNING on failure (checked below).
        $server = @\stream_socket_server($uri, $errno, $errstr, STREAM_SERVER_BIND, $streamContext);
        if (!$server || $errno) {
            throw new SocketException(\sprintf('Could not create datagram %s: [Error: #%d] %s', $uri, $errno, $errstr), $errno);
        }
        return new self($server, $context->getChunkSize());
    }
    /** @var resource|null UDP socket resource. */
    private $socket;
    /** @var string Watcher ID. */
    private $watcher;
    /** @var SocketAddress */
    private $address;
    /** @var Deferred|null */
    private $reader;
    /** @var int */
    private $chunkSize;
    /**
     * @param resource $socket A bound udp socket resource
     * @param int $chunkSize Maximum chunk size for the
     *
     * @throws \Error If a stream resource is not given for $socket.
     */
    public function __construct($socket, int $chunkSize = self::DEFAULT_CHUNK_SIZE)
    {
        if (!\is_resource($socket) || \get_resource_type($socket) !== 'stream') {
            throw new \Error('Invalid resource given to constructor!');
        }
        $this->socket = $socket;
        $this->address = SocketAddress::fromLocalResource($socket);
        $this->chunkSize =& $chunkSize;
        \stream_set_blocking($this->socket, false);
        $reader =& $this->reader;
        $this->watcher = Loop::onReadable($this->socket, static function ($watcher, $socket) use(&$reader, &$chunkSize) {
            $deferred = $reader;
            $reader = null;
            \assert($deferred !== null);
            $data = @\stream_socket_recvfrom($socket, $chunkSize, 0, $address);
            /** @psalm-suppress TypeDoesNotContainType */
            if ($data === false) {
                Loop::cancel($watcher);
                $deferred->resolve();
                return;
            }
            $deferred->resolve([SocketAddress::fromSocketName($address), $data]);
            /** @psalm-suppress RedundantCondition Resolution of the deferred above might read immediately again */
            if (!$reader) {
                Loop::disable($watcher);
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     * Automatically cancels the loop watcher.
     */
    public function __destruct()
    {
        if (!$this->socket) {
            return;
        }
        $this->free();
    }
    /**
     * @return Promise<(array{0: SocketAddress, 1: string} | null)> Resolves with null if the socket is closed.
     *
     * @throws PendingReceiveError If a receive request is already pending.
     */
    public function receive() : Promise
    {
        if ($this->reader) {
            throw new PendingReceiveError();
        }
        if (!$this->socket) {
            return new Success();
            // Resolve with null when endpoint is closed.
        }
        $this->reader = new Deferred();
        Loop::enable($this->watcher);
        return $this->reader->promise();
    }
    /**
     * @param SocketAddress $address
     * @param string $data
     *
     * @return Promise<int> Resolves with the number of bytes written to the socket.
     *
     * @throws SocketException If the UDP socket closes before the data can be sent.
     */
    public function send(SocketAddress $address, string $data) : Promise
    {
        if (!$this->socket) {
            return new Failure(new SocketException('The endpoint is not writable'));
        }
        try {
            try {
                \set_error_handler(static function (int $errno, string $errstr) {
                    throw new SocketException(\sprintf('Could not send packet on endpoint: %s', $errstr));
                });
                $result = \stream_socket_sendto($this->socket, $data, 0, $address->toString());
                /** @psalm-suppress TypeDoesNotContainType */
                if ($result < 0 || $result === false) {
                    throw new SocketException('Could not send packet on endpoint: Unknown error');
                }
            } finally {
                \restore_error_handler();
            }
        } catch (SocketException $e) {
            return new Failure($e);
        }
        return new Success($result);
    }
    /**
     * Raw stream socket resource.
     *
     * @return (resource | null)
     */
    public final function getResource()
    {
        return $this->socket;
    }
    /**
     * References the receive watcher.
     *
     * @see Loop::reference()
     */
    public final function reference() : void
    {
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the receive watcher.
     *
     * @see Loop::unreference()
     */
    public final function unreference() : void
    {
        Loop::unreference($this->watcher);
    }
    /**
     * Closes the datagram socket and stops receiving data. Any pending read is resolved with null.
     */
    public function close() : void
    {
        if ($this->socket) {
            /** @psalm-suppress InvalidPropertyAssignmentValue */
            \fclose($this->socket);
        }
        $this->free();
    }
    /**
     * @return bool
     */
    public function isClosed() : bool
    {
        return $this->socket === null;
    }
    /**
     * @return SocketAddress
     */
    public function getAddress() : SocketAddress
    {
        return $this->address;
    }
    /**
     * @param int $chunkSize The new maximum packet size to receive.
     */
    public function setChunkSize(int $chunkSize) : void
    {
        $this->chunkSize = $chunkSize;
    }
    /**
     *
     */
    private function free() : void
    {
        Loop::cancel($this->watcher);
        $this->socket = null;
        if ($this->reader) {
            $this->reader->resolve();
            $this->reader = null;
        }
    }
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\Failure;
use Amp\Loop;
use Amp\Promise;
use Amp\Struct;
use Amp\Success;
use League\Uri;
use function Amp\call;
/**
 * SocketPool implementation that doesn't impose any limits on concurrent open connections.
 */
final class UnlimitedSocketPool implements SocketPool
{
    private const ALLOWED_SCHEMES = ['tcp' => null, 'unix' => null];
    /** @var object[][] */
    private $sockets = [];
    /** @var string[] */
    private $objectIdCacheKeyMap = [];
    /** @var int[] */
    private $pendingCount = [];
    /** @var int */
    private $idleTimeout;
    /** @var Connector */
    private $connector;
    /**
     *
     */
    public function __construct(int $idleTimeout = 10000, ?Connector $connector = null)
    {
        $this->idleTimeout = $idleTimeout;
        $this->connector = $connector ?? connector();
    }
    /**
     * @inheritdoc
     */
    public function checkout(string $uri, ConnectContext $context = null, CancellationToken $token = null) : Promise
    {
        // A request might already be cancelled before we reach the checkout, so do not even attempt to checkout in that
        // case. The weird logic is required to throw the token's exception instead of creating a new one.
        if ($token && $token->isRequested()) {
            try {
                $token->throwIfRequested();
            } catch (CancelledException $e) {
                return new Failure($e);
            }
        }
        [$uri, $fragment] = $this->normalizeUri($uri);
        $cacheKey = $uri;
        if ($context && ($tlsContext = $context->getTlsContext())) {
            $cacheKey .= ' + ' . \serialize($tlsContext->toStreamContextArray());
        }
        if ($fragment !== null) {
            $cacheKey .= ' # ' . $fragment;
        }
        if (empty($this->sockets[$cacheKey])) {
            return $this->checkoutNewSocket($uri, $cacheKey, $context, $token);
        }
        foreach ($this->sockets[$cacheKey] as $socketId => $socket) {
            if (!$socket->isAvailable) {
                continue;
            }
            if ($socket->object instanceof ResourceSocket) {
                $resource = $socket->object->getResource();
                if (!$resource || !\is_resource($resource) || \feof($resource)) {
                    $this->clearFromId(\spl_object_hash($socket->object));
                    continue;
                }
            } elseif ($socket->object->isClosed()) {
                $this->clearFromId(\spl_object_hash($socket->object));
                continue;
            }
            $socket->isAvailable = false;
            if ($socket->idleWatcher !== null) {
                Loop::disable($socket->idleWatcher);
            }
            return new Success($socket->object);
        }
        return $this->checkoutNewSocket($uri, $cacheKey, $context, $token);
    }
    /**
     * @inheritdoc
     */
    public function clear(EncryptableSocket $socket) : void
    {
        $this->clearFromId(\spl_object_hash($socket));
    }
    /**
     * @inheritdoc
     */
    public function checkin(EncryptableSocket $socket) : void
    {
        $objectId = \spl_object_hash($socket);
        if (!isset($this->objectIdCacheKeyMap[$objectId])) {
            throw new \Error(\sprintf('Unknown socket: %d', $objectId));
        }
        $cacheKey = $this->objectIdCacheKeyMap[$objectId];
        if ($socket instanceof ResourceSocket) {
            $resource = $socket->getResource();
            if (!$resource || !\is_resource($resource) || \feof($resource)) {
                $this->clearFromId(\spl_object_hash($socket));
                return;
            }
        } elseif ($socket->isClosed()) {
            $this->clearFromId(\spl_object_hash($socket));
            return;
        }
        $socket = $this->sockets[$cacheKey][$objectId];
        $socket->isAvailable = true;
        if (isset($socket->idleWatcher)) {
            Loop::enable($socket->idleWatcher);
        } else {
            $socket->idleWatcher = Loop::delay($this->idleTimeout, function () use($socket) {
                $this->clearFromId(\spl_object_hash($socket->object));
            });
            Loop::unreference($socket->idleWatcher);
        }
    }
    /**
     * @param string $uri
     *
     * @return array
     *
     * @throws SocketException
     */
    private function normalizeUri(string $uri) : array
    {
        if (\stripos($uri, 'unix://') === 0) {
            return \explode('#', $uri) + [null, null];
        }
        try {
            $parts = Uri\parse($uri);
        } catch (\Exception $exception) {
            throw new SocketException('Could not parse URI', 0, $exception);
        }
        if ($parts['scheme'] === null) {
            throw new SocketException('Invalid URI for socket pool; no scheme given');
        }
        $port = $parts['port'] ?? 0;
        if ($port === 0 || $parts['host'] === null) {
            throw new SocketException('Invalid URI for socket pool; missing host or port');
        }
        $scheme = \strtolower($parts['scheme']);
        $host = \strtolower($parts['host']);
        if (!\array_key_exists($scheme, self::ALLOWED_SCHEMES)) {
            throw new SocketException(\sprintf("Invalid URI for socket pool; '%s' scheme not allowed - scheme must be one of %s", $scheme, \implode(', ', \array_keys(self::ALLOWED_SCHEMES))));
        }
        if ($parts['query'] !== null) {
            throw new SocketException('Invalid URI for socket pool; query component not allowed');
        }
        if ($parts['path'] !== '') {
            throw new SocketException('Invalid URI for socket pool; path component must be empty');
        }
        if ($parts['user'] !== null) {
            throw new SocketException('Invalid URI for socket pool; user component not allowed');
        }
        return [$scheme . '://' . $host . ':' . $port, $parts['fragment']];
    }
    /**
     *
     */
    private function checkoutNewSocket(string $uri, string $cacheKey, ConnectContext $connectContext = null, CancellationToken $token = null) : Promise
    {
        return call(function () use($uri, $cacheKey, $connectContext, $token) {
            $this->pendingCount[$uri] = ($this->pendingCount[$uri] ?? 0) + 1;
            try {
                /** @var EncryptableSocket $socket */
                $socket = (yield $this->connector->connect($uri, $connectContext, $token));
            } finally {
                if (--$this->pendingCount[$uri] === 0) {
                    unset($this->pendingCount[$uri]);
                }
            }
            /** @psalm-suppress MissingConstructor */
            $socketEntry = new class
            {
                use Struct;
                /** @var string */
                public $uri;
                /** @var EncryptableSocket */
                public $object;
                /** @var bool */
                public $isAvailable;
                /** @var string|null */
                public $idleWatcher;
            };
            $socketEntry->uri = $uri;
            $socketEntry->isAvailable = false;
            $socketEntry->object = $socket;
            $objectId = \spl_object_hash($socket);
            $this->sockets[$cacheKey][$objectId] = $socketEntry;
            $this->objectIdCacheKeyMap[$objectId] = $cacheKey;
            return $socket;
        });
    }
    /**
     *
     */
    private function clearFromId(string $objectId) : void
    {
        if (!isset($this->objectIdCacheKeyMap[$objectId])) {
            throw new \Error(\sprintf('Unknown socket: %d', $objectId));
        }
        $cacheKey = $this->objectIdCacheKeyMap[$objectId];
        $socket = $this->sockets[$cacheKey][$objectId];
        if ($socket->idleWatcher) {
            Loop::cancel($socket->idleWatcher);
        }
        unset($this->sockets[$cacheKey][$objectId], $this->objectIdCacheKeyMap[$objectId]);
        if (empty($this->sockets[$cacheKey])) {
            unset($this->sockets[$cacheKey]);
        }
    }
}<?php

namespace Amp\Socket\Internal;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Failure;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\Socket\TlsException;
use Amp\Success;
use League\Uri;
use function Amp\call;
/**
 * Parse an URI into [scheme, host, port].
 *
 * @param string $uri
 *
 * @return array
 *
 * @throws \Error If an invalid URI has been passed.
 *
 * @internal
 */
function parseUri(string $uri) : array
{
    if (\stripos($uri, 'unix://') === 0 || \stripos($uri, 'udg://') === 0) {
        [$scheme, $path] = \explode('://', $uri, 2);
        return [$scheme, \ltrim($path, '/'), 0];
    }
    if (\strpos($uri, '://') === false) {
        // Set a default scheme of tcp if none was given.
        $uri = 'tcp://' . $uri;
    }
    try {
        $uriParts = Uri\parse($uri);
    } catch (\Exception $exception) {
        throw new \Error("Invalid URI: {$uri}", 0, $exception);
    }
    $scheme = $uriParts['scheme'];
    $host = $uriParts['host'] ?? '';
    $port = $uriParts['port'] ?? 0;
    if (!\in_array($scheme, ['tcp', 'udp', 'unix', 'udg'], true)) {
        throw new \Error("Invalid URI scheme ({$scheme}); tcp, udp, unix or udg scheme expected");
    }
    if ($host === '' || $port === 0) {
        throw new \Error("Invalid URI: {$uri}; host and port components required");
    }
    if (\strpos($host, ':') !== false) {
        // IPv6 address
        $host = \sprintf('[%s]', \trim($host, '[]'));
    }
    return [$scheme, $host, $port];
}
/**
 * Enable encryption on an existing socket stream.
 *
 * @param resource $socket
 * @param array $options
 * @param CancellationToken $cancellationToken
 *
 * @return Promise<void>
 *
 * @internal
 */
function setupTls($socket, array $options, ?CancellationToken $cancellationToken) : Promise
{
    $cancellationToken = $cancellationToken ?? new NullCancellationToken();
    if (isset(\stream_get_meta_data($socket)['crypto'])) {
        return new Failure(new TlsException("Can't setup TLS, because it has already been set up"));
    }
    \error_clear_last();
    \stream_context_set_option($socket, $options);
    try {
        \set_error_handler(static function (int $errno, string $errstr) {
            new TlsException('TLS negotiation failed: ' . $errstr);
        });
        $result = \stream_socket_enable_crypto($socket, $enable = true);
        if ($result === false) {
            throw new TlsException('TLS negotiation failed: Unknown error');
        }
    } catch (TlsException $e) {
        return new Failure($e);
    } finally {
        \restore_error_handler();
    }
    // Yes, that function can return true / false / 0, don't use weak comparisons.
    if ($result === true) {
        /** @psalm-suppress InvalidReturnStatement */
        return new Success();
    }
    return call(static function () use($socket, $cancellationToken) {
        $cancellationToken->throwIfRequested();
        $deferred = new Deferred();
        // Watcher is guaranteed to be created, because we throw above if cancellation has already been requested
        $id = $cancellationToken->subscribe(static function ($e) use($deferred, &$watcher) {
            Loop::cancel($watcher);
            $deferred->fail($e);
        });
        $watcher = Loop::onReadable($socket, static function (string $watcher, $socket, Deferred $deferred) use($cancellationToken, $id) {
            try {
                try {
                    \set_error_handler(static function (int $errno, string $errstr) use($socket) {
                        if (\feof($socket)) {
                            $errstr = 'Connection reset by peer';
                        }
                        throw new TlsException('TLS negotiation failed: ' . $errstr);
                    });
                    $result = \stream_socket_enable_crypto($socket, true);
                    if ($result === false) {
                        $message = \feof($socket) ? 'Connection reset by peer' : 'Unknown error';
                        throw new TlsException('TLS negotiation failed: ' . $message);
                    }
                } finally {
                    \restore_error_handler();
                }
            } catch (TlsException $e) {
                Loop::cancel($watcher);
                $cancellationToken->unsubscribe($id);
                $deferred->fail($e);
                return;
            }
            // If $result is 0, just wait for the next invocation
            if ($result === true) {
                Loop::cancel($watcher);
                $cancellationToken->unsubscribe($id);
                $deferred->resolve();
            }
        }, $deferred);
        return $deferred->promise();
    });
}
/**
 * Disable encryption on an existing socket stream.
 *
 * @param resource $socket
 *
 * @return Promise<void>
 *
 * @internal
 * @psalm-suppress InvalidReturnType
 */
function shutdownTls($socket) : Promise
{
    // note that disabling crypto *ALWAYS* returns false, immediately
    // don't set _enabled to false, TLS can be setup only once
    @\stream_socket_enable_crypto($socket, false);
    /** @psalm-suppress InvalidReturnStatement */
    return new Success();
}
/**
 * Normalizes "bindto" options to add a ":0" in case no port is present, otherwise PHP will silently ignore those.
 *
 * @param (string | null) $bindTo
 *
 * @return (string | null)
 *
 * @throws \Error If an invalid option has been passed.
 */
function normalizeBindToOption(string $bindTo = null)
{
    if ($bindTo === null) {
        return null;
    }
    if (\preg_match("/\\[(?P<ip>[0-9a-f:]+)\\](:(?P<port>\\d+))?\$/", $bindTo, $match)) {
        $ip = $match['ip'];
        $port = $match['port'] ?? 0;
        if (@\inet_pton($ip) === false) {
            throw new \Error("Invalid IPv6 address: {$ip}");
        }
        if ($port < 0 || $port > 65535) {
            throw new \Error("Invalid port: {$port}");
        }
        return "[{$ip}]:{$port}";
    }
    if (\preg_match("/(?P<ip>\\d+\\.\\d+\\.\\d+\\.\\d+)(:(?P<port>\\d+))?\$/", $bindTo, $match)) {
        $ip = $match['ip'];
        $port = $match['port'] ?? 0;
        if (@\inet_pton($ip) === false) {
            throw new \Error("Invalid IPv4 address: {$ip}");
        }
        if ($port < 0 || $port > 65535) {
            throw new \Error("Invalid port: {$port}");
        }
        return "{$ip}:{$port}";
    }
    throw new \Error("Invalid bindTo value: {$bindTo}");
}
/**
 * Cleans up return values of stream_socket_get_name.
 *
 * @param (string | false) $address
 *
 * @return (string | null)
 */
function cleanupSocketName($address)
{
    // https://3v4l.org/5C1lo
    if ($address === false || $address === "\x00") {
        return null;
    }
    // Check if this is an IPv6 address which includes multiple colons but no square brackets
    // @see https://github.com/reactphp/socket/blob/v0.8.10/src/TcpServer.php#L179-L184
    // @license https://github.com/reactphp/socket/blob/v0.8.10/LICENSE
    $pos = \strrpos($address, ':');
    if ($pos !== false && \strpos($address, ':') < $pos && $address[0] !== '[') {
        $port = \Phabel\Target\Php80\Polyfill::substr($address, $pos + 1);
        $address = '[' . \Phabel\Target\Php80\Polyfill::substr($address, 0, $pos) . ']:' . $port;
    }
    // -- End of imported code ----- //
    return $address;
}<?php

namespace Amp\Socket;

use Kelunik\Certificate\Certificate;
/**
 * Exposes a connection's negotiated TLS parameters.
 */
final class TlsInfo
{
    /** @var string */
    private $version;
    /** @var string */
    private $cipherName;
    /** @var int */
    private $cipherBits;
    /** @var string */
    private $cipherVersion;
    /** @var string|null */
    private $alpnProtocol;
    /** @var array|null */
    private $certificates;
    /** @var Certificate[]|null */
    private $parsedCertificates;
    /**
     * Constructs a new instance from a stream socket resource.
     *
     * @param resource $resource Stream socket resource.
     *
     * @return (self | null) Returns null if TLS is not enabled on the stream socket.
     */
    public static function fromStreamResource($resource) : ?self
    {
        if (!\is_resource($resource) || \get_resource_type($resource) !== 'stream') {
            throw new \Error("Expected a valid stream resource");
        }
        $metadata = \stream_get_meta_data($resource)['crypto'] ?? [];
        $tlsContext = \stream_context_get_options($resource)['ssl'] ?? [];
        return empty($metadata) ? null : self::fromMetaData($metadata, $tlsContext);
    }
    /**
     * Constructs a new instance from PHP's internal info.
     *
     * Always pass the info as obtained from PHP as this method might extract additional fields in the future.
     *
     * @param array $cryptoInfo Crypto info obtained via `stream_get_meta_data($socket->getResource())["crypto"]`.
     * @param array $tlsContext Context obtained via `stream_context_get_options($socket->getResource())["ssl"])`.
     *
     * @return self
     */
    public static function fromMetaData(array $cryptoInfo, array $tlsContext) : self
    {
        if (isset($tlsContext["peer_certificate"])) {
            $certificates = \array_merge([$tlsContext["peer_certificate"]], $tlsContext["peer_certificate_chain"] ?? []);
        } else {
            $certificates = $tlsContext["peer_certificate_chain"] ?? [];
        }
        return new self($cryptoInfo["protocol"], $cryptoInfo["cipher_name"], $cryptoInfo["cipher_bits"], $cryptoInfo["cipher_version"], $cryptoInfo["alpn_protocol"] ?? null, empty($certificates) ? null : $certificates);
    }
    /**
     *
     */
    private function __construct(string $version, string $cipherName, int $cipherBits, string $cipherVersion, ?string $alpnProtocol, ?array $certificates)
    {
        $this->version = $version;
        $this->cipherName = $cipherName;
        $this->cipherBits = $cipherBits;
        $this->cipherVersion = $cipherVersion;
        $this->alpnProtocol = $alpnProtocol;
        $this->certificates = $certificates;
    }
    /**
     *
     */
    public function getVersion() : string
    {
        return $this->version;
    }
    /**
     *
     */
    public function getCipherName() : string
    {
        return $this->cipherName;
    }
    /**
     *
     */
    public function getCipherBits() : int
    {
        return $this->cipherBits;
    }
    /**
     *
     */
    public function getCipherVersion() : string
    {
        return $this->cipherVersion;
    }
    /**
     *
     */
    public function getApplicationLayerProtocol() : ?string
    {
        return $this->alpnProtocol;
    }
    /**
     * @return Certificate[]
     *
     * @throws SocketException If peer certificates were not captured.
     */
    public function getPeerCertificates() : array
    {
        if ($this->certificates === null) {
            throw new SocketException("Peer certificates not captured; use ClientTlsContext::withPeerCapturing() to capture peer certificates");
        }
        if ($this->parsedCertificates === null) {
            $this->parsedCertificates = \array_map(static function ($resource) {
                return new Certificate($resource);
            }, $this->certificates);
        }
        return $this->parsedCertificates;
    }
}<?php

namespace Amp\Socket;

use Amp\Dns\Record;
use function Amp\Socket\Internal\normalizeBindToOption;
final class ConnectContext
{
    /** @var string|null */
    private $bindTo;
    /** @var int */
    private $connectTimeout = 10000;
    /** @var int */
    private $maxAttempts = 2;
    /** @var null|int */
    private $typeRestriction;
    /** @var bool */
    private $tcpNoDelay = false;
    /** @var ClientTlsContext|null */
    private $tlsContext;
    /**
     *
     */
    public function withoutBindTo() : self
    {
        return $this->withBindTo(null);
    }
    /**
     *
     */
    public function withBindTo(?string $bindTo) : self
    {
        $bindTo = normalizeBindToOption($bindTo);
        $clone = clone $this;
        $clone->bindTo = $bindTo;
        return $clone;
    }
    /**
     *
     */
    public function getBindTo() : ?string
    {
        return $this->bindTo;
    }
    /**
     *
     */
    public function withConnectTimeout(int $timeout) : self
    {
        if ($timeout <= 0) {
            throw new \Error("Invalid connect timeout ({$timeout}), must be greater than 0");
        }
        $clone = clone $this;
        $clone->connectTimeout = $timeout;
        return $clone;
    }
    /**
     *
     */
    public function getConnectTimeout() : int
    {
        return $this->connectTimeout;
    }
    /**
     *
     */
    public function withMaxAttempts(int $maxAttempts) : self
    {
        if ($maxAttempts <= 0) {
            throw new \Error("Invalid max attempts ({$maxAttempts}), must be greater than 0");
        }
        $clone = clone $this;
        $clone->maxAttempts = $maxAttempts;
        return $clone;
    }
    /**
     *
     */
    public function getMaxAttempts() : int
    {
        return $this->maxAttempts;
    }
    /**
     *
     */
    public function withoutDnsTypeRestriction() : self
    {
        return $this->withDnsTypeRestriction(null);
    }
    /**
     *
     */
    public function withDnsTypeRestriction(?int $type) : self
    {
        if ($type !== null && $type !== Record::AAAA && $type !== Record::A) {
            throw new \Error('Invalid resolver type restriction');
        }
        $clone = clone $this;
        $clone->typeRestriction = $type;
        return $clone;
    }
    /**
     *
     */
    public function getDnsTypeRestriction() : ?int
    {
        return $this->typeRestriction;
    }
    /**
     *
     */
    public function hasTcpNoDelay() : bool
    {
        return $this->tcpNoDelay;
    }
    /**
     *
     */
    public function withTcpNoDelay() : self
    {
        $clone = clone $this;
        $clone->tcpNoDelay = true;
        return $clone;
    }
    /**
     *
     */
    public function withoutTcpNoDelay() : self
    {
        $clone = clone $this;
        $clone->tcpNoDelay = false;
        return $clone;
    }
    /**
     *
     */
    public function withoutTlsContext() : self
    {
        return $this->withTlsContext(null);
    }
    /**
     *
     */
    public function withTlsContext(?ClientTlsContext $tlsContext) : self
    {
        $clone = clone $this;
        $clone->tlsContext = $tlsContext;
        return $clone;
    }
    /**
     *
     */
    public function getTlsContext() : ?ClientTlsContext
    {
        return $this->tlsContext;
    }
    /**
     *
     */
    public function toStreamContextArray() : array
    {
        $options = ['tcp_nodelay' => $this->tcpNoDelay];
        if ($this->bindTo !== null) {
            $options['bindto'] = $this->bindTo;
        }
        $array = ['socket' => $options];
        if ($this->tlsContext) {
            $array = \array_merge($array, $this->tlsContext->toStreamContextArray());
        }
        return $array;
    }
}<?php

namespace Amp\Socket;

/**
 * Thrown if TLS can't be properly negotiated or is not supported on the given socket.
 */
class TlsException extends SocketException
{
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\Promise;
interface Connector
{
    /**
     * Asynchronously establish a socket connection to the specified URI.
     *
     * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
     * @param ConnectContext $context Socket connect context to use when connecting.
     * @param (CancellationToken | null) $token
     *
     * @return Promise<EncryptableSocket>
     *
     * @throws ConnectException
     * @throws CancelledException
     */
    public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null) : Promise;
}<?php

namespace Amp\Socket;

/**
 * Thrown in case a second read operation is attempted while another receive operation is still pending.
 */
final class PendingReceiveError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = 'The previous receive operation must complete before receive can be called again', int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Socket;

final class ServerTlsContext
{
    public const TLSv1_0 = \STREAM_CRYPTO_METHOD_TLSv1_0_SERVER;
    public const TLSv1_1 = \STREAM_CRYPTO_METHOD_TLSv1_1_SERVER;
    public const TLSv1_2 = \STREAM_CRYPTO_METHOD_TLSv1_2_SERVER;
    public const TLSv1_3 = \PHP_VERSION_ID >= 70400 ? \STREAM_CRYPTO_METHOD_TLSv1_3_SERVER : 0;
    private const TLS_VERSIONS = \PHP_VERSION_ID >= 70400 ? ['TLSv1.0' => self::TLSv1_0, 'TLSv1.1' => self::TLSv1_1, 'TLSv1.2' => self::TLSv1_2, 'TLSv1.3' => self::TLSv1_3] : ['TLSv1.0' => self::TLSv1_0, 'TLSv1.1' => self::TLSv1_1, 'TLSv1.2' => self::TLSv1_2];
    /** @var int */
    private $minVersion = self::TLSv1_0;
    /** @var null|string */
    private $peerName;
    /** @var bool */
    private $verifyPeer = false;
    /** @var int */
    private $verifyDepth = 10;
    /** @var null|string */
    private $ciphers;
    /** @var null|string */
    private $caFile;
    /** @var null|string */
    private $caPath;
    /** @var bool */
    private $capturePeer = false;
    /** @var null|Certificate */
    private $defaultCertificate;
    /** @var Certificate[] */
    private $certificates = [];
    /** @var int */
    private $securityLevel = 2;
    /** @var string[] */
    private $alpnProtocols = [];
    /**
     * Minimum TLS version to negotiate.
     *
     * Defaults to TLS 1.0.
     *
     * @param int $version One of the `ServerTlsContext::TLSv*` constants.
     *
     * @return self Cloned, modified instance.
     * @throws \Error If an invalid minimum version is given.
     */
    public function withMinimumVersion(int $version) : self
    {
        if (!\in_array($version, self::TLS_VERSIONS, true)) {
            throw new \Error(\sprintf('Invalid minimum version, only %s allowed', implode(', ', \array_keys(self::TLS_VERSIONS))));
        }
        $clone = clone $this;
        $clone->minVersion = $version;
        return $clone;
    }
    /**
     * Returns the minimum TLS version to negotiate.
     *
     * @return int
     */
    public function getMinimumVersion() : int
    {
        return $this->minVersion;
    }
    /**
     * Expected name of the peer.
     *
     * @param (string | null) $peerName
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerName(string $peerName = null) : self
    {
        $clone = clone $this;
        $clone->peerName = $peerName;
        return $clone;
    }
    /**
     * @return (null | string) Expected name of the peer or `null` if such an expectation doesn't exist.
     */
    public function getPeerName() : ?string
    {
        return $this->peerName;
    }
    /**
     * Enable peer verification.
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerVerification() : self
    {
        $clone = clone $this;
        $clone->verifyPeer = true;
        return $clone;
    }
    /**
     * Disable peer verification, this is the default for servers.
     *
     * @return self Cloned, modified instance.
     */
    public function withoutPeerVerification() : self
    {
        $clone = clone $this;
        $clone->verifyPeer = false;
        return $clone;
    }
    /**
     * @return bool Whether peer verification is enabled.
     */
    public function hasPeerVerification() : bool
    {
        return $this->verifyPeer;
    }
    /**
     * Maximum chain length the peer might present including the certificates in the local trust store.
     *
     * @param int $verifyDepth Maximum length of the certificate chain.
     *
     * @return self Cloned, modified instance.
     */
    public function withVerificationDepth(int $verifyDepth) : self
    {
        if ($verifyDepth < 0) {
            throw new \Error("Invalid verification depth ({$verifyDepth}), must be greater than or equal to 0");
        }
        $clone = clone $this;
        $clone->verifyDepth = $verifyDepth;
        return $clone;
    }
    /**
     * @return int Maximum length of the certificate chain.
     */
    public function getVerificationDepth() : int
    {
        return $this->verifyDepth;
    }
    /**
     * List of ciphers to negotiate, the server's order is always preferred.
     *
     * @param (string | null) $ciphers List of ciphers in OpenSSL's format (colon separated).
     *
     * @return self Cloned, modified instance.
     */
    public function withCiphers(string $ciphers = null) : self
    {
        $clone = clone $this;
        $clone->ciphers = $ciphers;
        return $clone;
    }
    /**
     * @return string List of ciphers in OpenSSL's format (colon separated).
     */
    public function getCiphers() : string
    {
        return $this->ciphers ?? \OPENSSL_DEFAULT_STREAM_CIPHERS;
    }
    /**
     * CAFile to check for trusted certificates.
     *
     * @param (string | null) $cafile Path to the file or `null` to unset.
     *
     * @return self Cloned, modified instance.
     */
    public function withCaFile(string $cafile = null) : self
    {
        $clone = clone $this;
        $clone->caFile = $cafile;
        return $clone;
    }
    /**
     * @return (null | string) Path to the file if one is set, otherwise `null`.
     */
    public function getCaFile() : ?string
    {
        return $this->caFile;
    }
    /**
     * CAPath to check for trusted certificates.
     *
     * @param (string | null) $capath Path to the file or `null` to unset.
     *
     * @return self Cloned, modified instance.
     */
    public function withCaPath(string $capath = null) : self
    {
        $clone = clone $this;
        $clone->caPath = $capath;
        return $clone;
    }
    /**
     * @return (null | string) Path to the file if one is set, otherwise `null`.
     */
    public function getCaPath() : ?string
    {
        return $this->caPath;
    }
    /**
     * Capture the certificates sent by the peer.
     *
     * Note: This is the chain as sent by the peer, NOT the verified chain.
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerCapturing() : self
    {
        $clone = clone $this;
        $clone->capturePeer = true;
        return $clone;
    }
    /**
     * Don't capture the certificates sent by the peer.
     *
     * @return self Cloned, modified instance.
     */
    public function withoutPeerCapturing() : self
    {
        $clone = clone $this;
        $clone->capturePeer = false;
        return $clone;
    }
    /**
     * @return bool Whether to capture the certificates sent by the peer.
     */
    public function hasPeerCapturing() : bool
    {
        return $this->capturePeer;
    }
    /**
     * Default certificate to use in case no SNI certificate matches.
     *
     * @param (Certificate | null) $defaultCertificate
     *
     * @return self Cloned, modified instance.
     */
    public function withDefaultCertificate(Certificate $defaultCertificate = null) : self
    {
        $clone = clone $this;
        $clone->defaultCertificate = $defaultCertificate;
        return $clone;
    }
    /**
     * @return (Certificate | null) Default certificate to use in case no SNI certificate matches, or `null` if unset.
     */
    public function getDefaultCertificate() : ?Certificate
    {
        return $this->defaultCertificate;
    }
    /**
     * Certificates to use for the given host names.
     *
     * @param array $certificates Must be a associative array mapping hostnames to certificate instances.
     *
     * @return self Cloned, modified instance.
     */
    public function withCertificates(array $certificates) : self
    {
        foreach ($certificates as $key => $certificate) {
            if (!\is_string($key)) {
                throw new \TypeError('Expected an array mapping domain names to Certificate instances');
            }
            if (!$certificate instanceof Certificate) {
                throw new \TypeError('Expected an array of Certificate instances');
            }
            if (\PHP_VERSION_ID < 70200 && $certificate->getCertFile() !== $certificate->getKeyFile()) {
                throw new \Error('Different files for cert and key are not supported on this version of PHP. Please upgrade to PHP 7.2 or later.');
            }
        }
        $clone = clone $this;
        $clone->certificates = $certificates;
        return $clone;
    }
    /**
     * @return array Associative array mapping hostnames to certificate instances.
     */
    public function getCertificates() : array
    {
        return $this->certificates;
    }
    /**
     * Security level to use.
     *
     * Requires OpenSSL 1.1.0 or higher.
     *
     * @param int $level Must be between 0 and 5.
     *
     * @return self Cloned, modified instance.
     */
    public function withSecurityLevel(int $level) : self
    {
        // See https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_security_level.html
        // Level 2 is not recommended, because of SHA-1 by that document,
        // but SHA-1 should be phased out now on general internet use.
        // We therefore default to level 2.
        if ($level < 0 || $level > 5) {
            throw new \Error("Invalid security level ({$level}), must be between 0 and 5.");
        }
        if (!hasTlsSecurityLevelSupport()) {
            throw new \Error("Can't set a security level, as PHP is compiled with OpenSSL < 1.1.0.");
        }
        $clone = clone $this;
        $clone->securityLevel = $level;
        return $clone;
    }
    /**
     * @return int Security level between 0 and 5. Always 0 for OpenSSL < 1.1.0.
     */
    public function getSecurityLevel() : int
    {
        // 0 is equivalent to previous versions of OpenSSL and just does nothing
        if (!hasTlsSecurityLevelSupport()) {
            return 0;
        }
        return $this->securityLevel;
    }
    /**
     * @param string[] $protocols
     *
     * @return self Cloned, modified instance.
     */
    public function withApplicationLayerProtocols(array $protocols) : self
    {
        if (!hasTlsAlpnSupport()) {
            throw new \Error("Can't set an application layer protocol list, as PHP is compiled with OpenSSL < 1.0.2.");
        }
        foreach ($protocols as $protocol) {
            if (!\is_string($protocol)) {
                throw new \TypeError("Protocol names must be strings");
            }
        }
        $clone = clone $this;
        $clone->alpnProtocols = $protocols;
        return $clone;
    }
    /**
     * @return string[]
     */
    public function getApplicationLayerProtocols() : array
    {
        return $this->alpnProtocols;
    }
    /**
     * Converts this TLS context into PHP's equivalent stream context array.
     *
     * @return array Stream context array compatible with PHP's streams.
     */
    public function toStreamContextArray() : array
    {
        $options = ['crypto_method' => $this->toStreamCryptoMethod(), 'peer_name' => $this->peerName, 'verify_peer' => $this->verifyPeer, 'verify_peer_name' => $this->verifyPeer, 'verify_depth' => $this->verifyDepth, 'ciphers' => $this->ciphers ?? \OPENSSL_DEFAULT_STREAM_CIPHERS, 'honor_cipher_order' => true, 'single_dh_use' => true, 'no_ticket' => true, 'capture_peer_cert' => $this->capturePeer, 'capture_peer_chain' => $this->capturePeer];
        if (!empty($this->alpnProtocols)) {
            $options['alpn_protocols'] = \implode(',', $this->alpnProtocols);
        }
        if ($this->defaultCertificate !== null) {
            $options['local_cert'] = $this->defaultCertificate->getCertFile();
            if ($this->defaultCertificate->getCertFile() !== $this->defaultCertificate->getKeyFile()) {
                $options['local_pk'] = $this->defaultCertificate->getKeyFile();
            }
        }
        if ($this->certificates) {
            $options['SNI_server_certs'] = \array_map(static function (Certificate $certificate) {
                if ($certificate->getCertFile() === $certificate->getKeyFile()) {
                    return $certificate->getCertFile();
                }
                return ['local_cert' => $certificate->getCertFile(), 'local_pk' => $certificate->getKeyFile()];
            }, $this->certificates);
        }
        if ($this->caFile !== null) {
            $options['cafile'] = $this->caFile;
        }
        if ($this->caPath !== null) {
            $options['capath'] = $this->caPath;
        }
        if (\OPENSSL_VERSION_NUMBER >= 0x10100000) {
            $options['security_level'] = $this->securityLevel;
        }
        return ['ssl' => $options];
    }
    /**
     * @return int Crypto method compatible with PHP's streams.
     */
    public function toStreamCryptoMethod() : int
    {
        switch ($this->minVersion) {
            case self::TLSv1_0:
                return self::TLSv1_0 | self::TLSv1_1 | self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_1:
                return self::TLSv1_1 | self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_2:
                return self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_3:
                return self::TLSv1_3;
            default:
                throw new \RuntimeException('Unknown minimum TLS version: ' . $this->minVersion);
        }
    }
}<?php

namespace Amp\Socket;

use function Amp\Socket\Internal\normalizeBindToOption;
final class BindContext
{
    /** @var string|null */
    private $bindTo;
    /** @var int */
    private $backlog = 128;
    /** @var bool */
    private $reusePort = false;
    /** @var bool */
    private $broadcast = false;
    /** @var bool */
    private $tcpNoDelay = false;
    /** @var int */
    private $chunkSize = 8192;
    /** @var ServerTlsContext|null */
    private $tlsContext;
    /**
     *
     */
    public function withoutBindTo() : self
    {
        return $this->withBindTo(null);
    }
    /**
     *
     */
    public function withBindTo(?string $bindTo) : self
    {
        $bindTo = normalizeBindToOption($bindTo);
        $clone = clone $this;
        $clone->bindTo = $bindTo;
        return $clone;
    }
    /**
     *
     */
    public function getBindTo() : ?string
    {
        return $this->bindTo;
    }
    /**
     *
     */
    public function getBacklog() : int
    {
        return $this->backlog;
    }
    /**
     *
     */
    public function withBacklog(int $backlog) : self
    {
        $clone = clone $this;
        $clone->backlog = $backlog;
        return $clone;
    }
    /**
     *
     */
    public function hasReusePort() : bool
    {
        return $this->reusePort;
    }
    /**
     *
     */
    public function withReusePort() : self
    {
        $clone = clone $this;
        $clone->reusePort = true;
        return $clone;
    }
    /**
     *
     */
    public function withoutReusePort() : self
    {
        $clone = clone $this;
        $clone->reusePort = false;
        return $clone;
    }
    /**
     *
     */
    public function hasBroadcast() : bool
    {
        return $this->broadcast;
    }
    /**
     *
     */
    public function withBroadcast() : self
    {
        $clone = clone $this;
        $clone->broadcast = true;
        return $clone;
    }
    /**
     *
     */
    public function withoutBroadcast() : self
    {
        $clone = clone $this;
        $clone->broadcast = false;
        return $clone;
    }
    /**
     *
     */
    public function hasTcpNoDelay() : bool
    {
        return $this->tcpNoDelay;
    }
    /**
     *
     */
    public function withTcpNoDelay() : self
    {
        $clone = clone $this;
        $clone->tcpNoDelay = true;
        return $clone;
    }
    /**
     *
     */
    public function withoutTcpNoDelay() : self
    {
        $clone = clone $this;
        $clone->tcpNoDelay = false;
        return $clone;
    }
    /**
     *
     */
    public function getTlsContext() : ?ServerTlsContext
    {
        return $this->tlsContext;
    }
    /**
     *
     */
    public function withoutTlsContext() : self
    {
        return $this->withTlsContext(null);
    }
    /**
     *
     */
    public function withTlsContext(?ServerTlsContext $tlsContext) : self
    {
        $clone = clone $this;
        $clone->tlsContext = $tlsContext;
        return $clone;
    }
    /**
     *
     */
    public function getChunkSize() : int
    {
        return $this->chunkSize;
    }
    /**
     *
     */
    public function withChunkSize(int $chunkSize) : self
    {
        $clone = clone $this;
        $clone->chunkSize = $chunkSize;
        return $clone;
    }
    /**
     *
     */
    public function toStreamContextArray() : array
    {
        $array = ['socket' => [
            'bindto' => $this->bindTo,
            'backlog' => $this->backlog,
            'ipv6_v6only' => true,
            // SO_REUSEADDR has SO_REUSEPORT semantics on Windows
            'so_reuseaddr' => $this->reusePort && \stripos(\PHP_OS, 'WIN') === 0,
            'so_reuseport' => $this->reusePort,
            'so_broadcast' => $this->broadcast,
            'tcp_nodelay' => $this->tcpNoDelay,
        ]];
        if ($this->tlsContext) {
            $array = \array_merge($array, $this->tlsContext->toStreamContextArray());
        }
        return $array;
    }
}<?php

namespace Amp\Socket;

/**
 * Thrown in case a second read operation is attempted while another read operation is still pending.
 */
final class PendingAcceptError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = 'The previous accept operation must complete before accept can be called again', int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Socket;

/**
 * Thrown if connecting fails.
 */
class ConnectException extends SocketException
{
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\Promise;
/**
 * Connector that connects to a statically defined URI instead of the URI passed to the connect() call.
 */
final class StaticConnector implements Connector
{
    private $uri;
    private $connector;
    /**
     *
     */
    public function __construct(string $uri, Connector $connector)
    {
        $this->uri = $uri;
        $this->connector = $connector;
    }
    /**
     *
     */
    public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null) : Promise
    {
        return $this->connector->connect($this->uri, $context, $token);
    }
}<?php

namespace Amp\Socket;

use Amp\ByteStream\ClosedException;
use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\CancellationToken;
use Amp\Failure;
use Amp\Promise;
use function Amp\call;
final class ResourceSocket implements EncryptableSocket
{
    public const DEFAULT_CHUNK_SIZE = ResourceInputStream::DEFAULT_CHUNK_SIZE;
    /**
     * @param resource $resource Stream resource.
     * @param int $chunkSize Read and write chunk size.
     *
     * @return self
     */
    public static function fromServerSocket($resource, int $chunkSize = self::DEFAULT_CHUNK_SIZE) : self
    {
        return new self($resource, $chunkSize);
    }
    /**
     * @param resource $resource Stream resource.
     * @param int $chunkSize Read and write chunk size.
     * @param (ClientTlsContext | null) $tlsContext
     *
     * @return self
     */
    public static function fromClientSocket($resource, ?ClientTlsContext $tlsContext = null, int $chunkSize = self::DEFAULT_CHUNK_SIZE) : self
    {
        return new self($resource, $chunkSize, $tlsContext);
    }
    /** @var ClientTlsContext|null */
    private $tlsContext;
    /** @var int */
    private $tlsState;
    /** @var ResourceInputStream */
    private $reader;
    /** @var ResourceOutputStream */
    private $writer;
    /** @var SocketAddress */
    private $localAddress;
    /** @var SocketAddress */
    private $remoteAddress;
    /** @var TlsInfo|null */
    private $tlsInfo;
    /**
     * @param resource $resource Stream resource.
     * @param int $chunkSize Read and write chunk size.
     * @param (ClientTlsContext | null) $tlsContext
     */
    private function __construct($resource, int $chunkSize = self::DEFAULT_CHUNK_SIZE, ?ClientTlsContext $tlsContext = null)
    {
        $this->tlsContext = $tlsContext;
        $this->reader = new ResourceInputStream($resource, $chunkSize);
        $this->writer = new ResourceOutputStream($resource, $chunkSize);
        $this->remoteAddress = SocketAddress::fromPeerResource($resource);
        $this->localAddress = SocketAddress::fromLocalResource($resource);
        $this->tlsState = self::TLS_STATE_DISABLED;
    }
    /**
     * @inheritDoc
     */
    public function setupTls(?CancellationToken $cancellationToken = null) : Promise
    {
        $resource = $this->getResource();
        if ($resource === null) {
            return new Failure(new ClosedException("Can't setup TLS, because the socket has already been closed"));
        }
        $this->tlsState = self::TLS_STATE_SETUP_PENDING;
        if ($this->tlsContext) {
            $promise = Internal\setupTls($resource, $this->tlsContext->toStreamContextArray(), $cancellationToken);
        } else {
            $context = @\stream_context_get_options($resource);
            if (empty($context['ssl'])) {
                return new Failure(new TlsException('Can\'t enable TLS without configuration. If you used Amp\\Socket\\listen(), be sure to pass a ServerTlsContext within the BindContext in the second argument, otherwise set the \'ssl\' context option to the PHP stream resource.'));
            }
            $promise = Internal\setupTls($resource, $context, $cancellationToken);
        }
        return call(function () use($promise) {
            try {
                (yield $promise);
                $this->tlsState = self::TLS_STATE_ENABLED;
            } catch (\Throwable $exception) {
                $this->close();
                throw $exception;
            }
        });
    }
    /**
     * @inheritDoc
     */
    public function shutdownTls(?CancellationToken $cancellationToken = null) : Promise
    {
        if (($resource = $this->reader->getResource()) === null) {
            return new Failure(new ClosedException("Can't shutdown TLS, because the socket has already been closed"));
        }
        $this->tlsState = self::TLS_STATE_SHUTDOWN_PENDING;
        return call(function () use($resource) {
            try {
                (yield Internal\shutdownTls($resource));
            } finally {
                $this->tlsState = self::TLS_STATE_DISABLED;
            }
        });
    }
    /**
     * @inheritDoc
     */
    public function read() : Promise
    {
        return $this->reader->read();
    }
    /**
     * @inheritDoc
     */
    public function write(string $data) : Promise
    {
        return $this->writer->write($data);
    }
    /**
     * @inheritDoc
     */
    public function end(string $data = '') : Promise
    {
        $promise = $this->writer->end($data);
        $promise->onResolve(function () {
            $this->close();
        });
        return $promise;
    }
    /**
     * @inheritDoc
     */
    public function close() : void
    {
        $this->reader->close();
        $this->writer->close();
    }
    /**
     * @inheritDoc
     */
    public function reference() : void
    {
        $this->reader->reference();
    }
    /**
     * @inheritDoc
     */
    public function unreference() : void
    {
        $this->reader->unreference();
    }
    /**
     * @inheritDoc
     */
    public function getLocalAddress() : SocketAddress
    {
        return $this->localAddress;
    }
    /**
     * @inheritDoc
     *
     * @return (resource | null)
     */
    public function getResource()
    {
        return $this->reader->getResource();
    }
    /**
     * @inheritDoc
     */
    public function getRemoteAddress() : SocketAddress
    {
        return $this->remoteAddress;
    }
    /**
     * @inheritDoc
     */
    public function getTlsState() : int
    {
        return $this->tlsState;
    }
    /**
     * @inheritDoc
     */
    public function getTlsInfo() : ?TlsInfo
    {
        if (null !== $this->tlsInfo) {
            return $this->tlsInfo;
        }
        $resource = $this->getResource();
        if ($resource === null || !\is_resource($resource)) {
            return null;
        }
        return $this->tlsInfo = TlsInfo::fromStreamResource($resource);
    }
    /**
     * @inheritDoc
     */
    public function isClosed() : bool
    {
        return $this->getResource() === null;
    }
    /**
     * @param int $chunkSize New chunk size for reading and writing.
     */
    public function setChunkSize(int $chunkSize) : void
    {
        $this->reader->setChunkSize($chunkSize);
        $this->writer->setChunkSize($chunkSize);
    }
}<?php

namespace Amp\Socket;

final class SocketAddress
{
    /** @var string */
    private $host;
    /** @var int|null */
    private $port;
    /**
     * @param resource $resource
     *
     * @return self
     */
    public static function fromPeerResource($resource) : self
    {
        $name = @\stream_socket_get_name($resource, true);
        /** @psalm-suppress TypeDoesNotContainType */
        if ($name === false || $name === "\x00") {
            return self::fromLocalResource($resource);
        }
        return self::fromSocketName($name);
    }
    /**
     * @param resource $resource
     *
     * @return self
     */
    public static function fromLocalResource($resource) : self
    {
        $wantPeer = false;
        do {
            $name = @\stream_socket_get_name($resource, $wantPeer);
            /** @psalm-suppress RedundantCondition */
            if ($name !== false && $name !== "\x00") {
                return self::fromSocketName($name);
            }
        } while ($wantPeer = !$wantPeer);
        return new self('');
    }
    /**
     * @param string $name
     *
     * @return self
     */
    public static function fromSocketName(string $name) : self
    {
        if ($portStartPos = \strrpos($name, ':')) {
            $host = \Phabel\Target\Php80\Polyfill::substr($name, 0, $portStartPos);
            $port = (int) \Phabel\Target\Php80\Polyfill::substr($name, $portStartPos + 1);
            return new self($host, $port);
        }
        return new self($name);
    }
    /**
     * @param string $host
     * @param (int | null) $port
     */
    public function __construct(string $host, ?int $port = null)
    {
        if ($port !== null && ($port < 1 || $port > 65535)) {
            throw new \Error('Port number must be null or an integer between 1 and 65535');
        }
        if (\strrpos($host, ':')) {
            $host = \trim($host, '[]');
        }
        $this->host = $host;
        $this->port = $port;
    }
    /**
     * @return string
     */
    public function getHost() : string
    {
        return $this->host;
    }
    /**
     * @return int
     */
    public function getPort() : ?int
    {
        return $this->port;
    }
    /**
     * @return string host:port formatted string.
     */
    public function toString() : string
    {
        $host = $this->host;
        if (\strrpos($host, ':')) {
            $host = '[' . $host . ']';
        }
        if ($this->port === null) {
            return $host;
        }
        return $host . ':' . $this->port;
    }
    /**
     * @see toString
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->toString();
    }
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\Loop;
use Amp\Promise;
const LOOP_CONNECTOR_IDENTIFIER = Connector::class;
/**
 * Listen for client connections on the specified server address.
 *
 * If you want to accept TLS connections, you have to use `yield $socket->setupTls()` after accepting new clients.
 *
 * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
 * @param (BindContext | null) $context Context options for listening.
 *
 * @return Server
 *
 * @throws SocketException If binding to the specified URI failed.
 * @throws \Error If an invalid scheme is given.
 * @see Server::listen()
 *
 * @deprecated Use Server::listen() instead.
 */
function listen(string $uri, ?BindContext $context = null) : Server
{
    return Server::listen($uri, $context);
}
/**
 * Set or access the global socket Connector instance.
 *
 * @param (Connector | null) $connector
 *
 * @return Connector
 */
function connector(Connector $connector = null) : Connector
{
    if ($connector === null) {
        if ($connector = Loop::getState(LOOP_CONNECTOR_IDENTIFIER)) {
            return $connector;
        }
        $connector = new DnsConnector();
    }
    Loop::setState(LOOP_CONNECTOR_IDENTIFIER, $connector);
    return $connector;
}
/**
 * Asynchronously establish a socket connection to the specified URI.
 *
 * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
 * @param ConnectContext $context Socket connect context to use when connecting.
 * @param (CancellationToken | null) $token
 *
 * @return Promise<EncryptableSocket>
 *
 * @throws ConnectException
 * @throws CancelledException
 */
function connect(string $uri, ConnectContext $context = null, CancellationToken $token = null) : Promise
{
    return connector()->connect($uri, $context, $token);
}
/**
 * Returns a pair of connected stream socket resources.
 *
 * @return ResourceSocket[] Pair of socket resources.
 *
 * @throws SocketException If creating the sockets fails.
 */
function createPair() : array
{
    try {
        \set_error_handler(static function (int $errno, string $errstr) {
            throw new SocketException(\sprintf('Failed to create socket pair.  Errno: %d; %s', $errno, $errstr));
        });
        $sockets = \stream_socket_pair(\stripos(PHP_OS, 'win') === 0 ? STREAM_PF_INET : STREAM_PF_UNIX, STREAM_SOCK_STREAM, STREAM_IPPROTO_IP);
        if ($sockets === false) {
            throw new SocketException('Failed to create socket pair.');
        }
    } finally {
        \restore_error_handler();
    }
    return [ResourceSocket::fromClientSocket($sockets[0]), ResourceSocket::fromClientSocket($sockets[1])];
}
/**
 * @see https://wiki.openssl.org/index.php/Manual:OPENSSL_VERSION_NUMBER(3)
 * @return bool
 */
function hasTlsAlpnSupport() : bool
{
    return \defined('OPENSSL_VERSION_NUMBER') && \OPENSSL_VERSION_NUMBER >= 0x10002000;
}
/**
 *
 */
function hasTlsSecurityLevelSupport() : bool
{
    return \defined('OPENSSL_VERSION_NUMBER') && \OPENSSL_VERSION_NUMBER >= 0x10100000;
}<?php

namespace Amp\Socket;

final class ClientTlsContext
{
    public const TLSv1_0 = \STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
    public const TLSv1_1 = \STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
    public const TLSv1_2 = \STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
    public const TLSv1_3 = \PHP_VERSION_ID >= 70400 ? \STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT : 0;
    private const TLS_VERSIONS = \PHP_VERSION_ID >= 70400 ? ['TLSv1.0' => self::TLSv1_0, 'TLSv1.1' => self::TLSv1_1, 'TLSv1.2' => self::TLSv1_2, 'TLSv1.3' => self::TLSv1_3] : ['TLSv1.0' => self::TLSv1_0, 'TLSv1.1' => self::TLSv1_1, 'TLSv1.2' => self::TLSv1_2];
    /** @var int */
    private $minVersion = self::TLSv1_0;
    /** @var string|null */
    private $peerName;
    /** @var bool */
    private $verifyPeer = true;
    /** @var int */
    private $verifyDepth = 10;
    /** @var string|null */
    private $ciphers;
    /** @var string|null */
    private $caFile;
    /** @var string|null */
    private $caPath;
    /** @var bool */
    private $capturePeer = false;
    /** @var bool */
    private $sniEnabled = true;
    /** @var int */
    private $securityLevel = 2;
    /** @var Certificate|null */
    private $certificate;
    /** @var string[] */
    private $alpnProtocols = [];
    /**
     *
     */
    public function __construct(string $peerName)
    {
        $this->peerName = $peerName;
    }
    /**
     * Minimum TLS version to negotiate.
     *
     * Defaults to TLS 1.0.
     *
     * @param int $version One of the `ClientTlsContext::TLSv*` constants.
     *
     * @return self Cloned, modified instance.
     * @throws \Error If an invalid minimum version is given.
     */
    public function withMinimumVersion(int $version) : self
    {
        if (!\in_array($version, self::TLS_VERSIONS, true)) {
            throw new \Error(\sprintf('Invalid minimum version, only %s allowed', implode(', ', \array_keys(self::TLS_VERSIONS))));
        }
        $clone = clone $this;
        $clone->minVersion = $version;
        return $clone;
    }
    /**
     * Returns the minimum TLS version to negotiate.
     *
     * @return int
     */
    public function getMinimumVersion() : int
    {
        return $this->minVersion;
    }
    /**
     * Expected name of the peer.
     *
     * @param string $peerName
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerName(string $peerName) : self
    {
        $clone = clone $this;
        $clone->peerName = $peerName;
        return $clone;
    }
    /**
     * @return (null | string) Expected name of the peer or `null` if such an expectation doesn't exist.
     */
    public function getPeerName() : ?string
    {
        return $this->peerName;
    }
    /**
     * Enable peer verification.
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerVerification() : self
    {
        $clone = clone $this;
        $clone->verifyPeer = true;
        return $clone;
    }
    /**
    * Disable peer verification, this is the default for servers.
    *
    * Warning: You usually shouldn't disable this setting for clients, because it allows active MitM attackers to
    intercept the communication and change it without anyone noticing.
    *
    * @return self Cloned, modified instance.
    */
    public function withoutPeerVerification() : self
    {
        $clone = clone $this;
        $clone->verifyPeer = false;
        return $clone;
    }
    /**
     * @return bool Whether peer verification is enabled.
     */
    public function hasPeerVerification() : bool
    {
        return $this->verifyPeer;
    }
    /**
     * Maximum chain length the peer might present including the certificates in the local trust store.
     *
     * @param int $verifyDepth Maximum length of the certificate chain.
     *
     * @return self Cloned, modified instance.
     */
    public function withVerificationDepth(int $verifyDepth) : self
    {
        if ($verifyDepth < 0) {
            throw new \Error("Invalid verification depth ({$verifyDepth}), must be greater than or equal to 0");
        }
        $clone = clone $this;
        $clone->verifyDepth = $verifyDepth;
        return $clone;
    }
    /**
     * @return int Maximum length of the certificate chain.
     */
    public function getVerificationDepth() : int
    {
        return $this->verifyDepth;
    }
    /**
     * List of ciphers to negotiate, the server's order is always preferred.
     *
     * @param (string | null) $ciphers List of ciphers in OpenSSL's format (colon separated).
     *
     * @return self Cloned, modified instance.
     */
    public function withCiphers(string $ciphers = null) : self
    {
        $clone = clone $this;
        $clone->ciphers = $ciphers;
        return $clone;
    }
    /**
     * @return string List of ciphers in OpenSSL's format (colon separated).
     */
    public function getCiphers() : string
    {
        return $this->ciphers ?? \OPENSSL_DEFAULT_STREAM_CIPHERS;
    }
    /**
     * CAFile to check for trusted certificates.
     *
     * @param (string | null) $cafile Path to the file or `null` to unset.
     *
     * @return self Cloned, modified instance.
     */
    public function withCaFile(string $cafile = null) : self
    {
        $clone = clone $this;
        $clone->caFile = $cafile;
        return $clone;
    }
    /**
     * @return (null | string) Path to the file if one is set, otherwise `null`.
     */
    public function getCaFile() : ?string
    {
        return $this->caFile;
    }
    /**
     * CAPath to check for trusted certificates.
     *
     * @param (string | null) $capath Path to the file or `null` to unset.
     *
     * @return self Cloned, modified instance.
     */
    public function withCaPath(string $capath = null) : self
    {
        $clone = clone $this;
        $clone->caPath = $capath;
        return $clone;
    }
    /**
     * @return (null | string) Path to the file if one is set, otherwise `null`.
     */
    public function getCaPath() : ?string
    {
        return $this->caPath;
    }
    /**
     * Capture the certificates sent by the peer.
     *
     * Note: This is the chain as sent by the peer, NOT the verified chain.
     *
     * @return self Cloned, modified instance.
     */
    public function withPeerCapturing() : self
    {
        $clone = clone $this;
        $clone->capturePeer = true;
        return $clone;
    }
    /**
     * Don't capture the certificates sent by the peer.
     *
     * @return self Cloned, modified instance.
     */
    public function withoutPeerCapturing() : self
    {
        $clone = clone $this;
        $clone->capturePeer = false;
        return $clone;
    }
    /**
     * @return bool Whether to capture the certificates sent by the peer.
     */
    public function hasPeerCapturing() : bool
    {
        return $this->capturePeer;
    }
    /**
     * Enable SNI.
     *
     * @return self Cloned, modified instance.
     */
    public function withSni() : self
    {
        $clone = clone $this;
        $clone->sniEnabled = true;
        return $clone;
    }
    /**
     * Disable SNI.
     *
     * @return self Cloned, modified instance.
     */
    public function withoutSni() : self
    {
        $clone = clone $this;
        $clone->sniEnabled = false;
        return $clone;
    }
    /**
     * @return bool Whether SNI is enabled or not.
     */
    public function hasSni() : bool
    {
        return $this->sniEnabled;
    }
    /**
     * Security level to use.
     *
     * Requires OpenSSL 1.1.0 or higher.
     *
     * @param int $level Must be between 0 and 5.
     *
     * @return self Cloned, modified instance.
     */
    public function withSecurityLevel(int $level) : self
    {
        // See https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set_security_level.html
        // Level 2 is not recommended, because of SHA-1 by that document,
        // but SHA-1 should be phased out now on general internet use.
        // We therefore default to level 2.
        if ($level < 0 || $level > 5) {
            throw new \Error("Invalid security level ({$level}), must be between 0 and 5.");
        }
        if (!hasTlsSecurityLevelSupport()) {
            throw new \Error("Can't set a security level, as PHP is compiled with OpenSSL < 1.1.0.");
        }
        $clone = clone $this;
        $clone->securityLevel = $level;
        return $clone;
    }
    /**
     * @return int Security level between 0 and 5. Always 0 for OpenSSL < 1.1.0.
     */
    public function getSecurityLevel() : int
    {
        // 0 is equivalent to previous versions of OpenSSL and just does nothing
        if (!hasTlsSecurityLevelSupport()) {
            return 0;
        }
        return $this->securityLevel;
    }
    /**
     * Client certificate to use, if key is no present it assumes it is present in the same file as the certificate.
     *
     * @param Certificate $certificate Certificate and private key info
     *
     * @return self Cloned, modified instance.
     */
    public function withCertificate(Certificate $certificate = null) : self
    {
        $clone = clone $this;
        $clone->certificate = $certificate;
        return $clone;
    }
    /**
     *
     */
    public function getCertificate() : ?Certificate
    {
        return $this->certificate;
    }
    /**
     * @param string[] $protocols
     *
     * @return self Cloned, modified instance.
     */
    public function withApplicationLayerProtocols(array $protocols) : self
    {
        if (!hasTlsAlpnSupport()) {
            throw new \Error("Can't set an application layer protocol list, as PHP is compiled with OpenSSL < 1.0.2.");
        }
        foreach ($protocols as $protocol) {
            if (!\is_string($protocol)) {
                throw new \TypeError("Protocol names must be strings");
            }
        }
        $clone = clone $this;
        $clone->alpnProtocols = $protocols;
        return $clone;
    }
    /**
     * @return string[]
     */
    public function getApplicationLayerProtocols() : array
    {
        return $this->alpnProtocols;
    }
    /**
     * Converts this TLS context into PHP's equivalent stream context array.
     *
     * @return array Stream context array compatible with PHP's streams.
     */
    public function toStreamContextArray() : array
    {
        $options = ['crypto_method' => $this->toStreamCryptoMethod(), 'peer_name' => $this->peerName, 'verify_peer' => $this->verifyPeer, 'verify_peer_name' => $this->verifyPeer, 'verify_depth' => $this->verifyDepth, 'ciphers' => $this->ciphers ?? \OPENSSL_DEFAULT_STREAM_CIPHERS, 'capture_peer_cert' => $this->capturePeer, 'capture_peer_cert_chain' => $this->capturePeer, 'SNI_enabled' => $this->sniEnabled];
        if ($this->certificate !== null) {
            $options['local_cert'] = $this->certificate->getCertFile();
            if ($this->certificate->getCertFile() !== $this->certificate->getKeyFile()) {
                $options['local_pk'] = $this->certificate->getKeyFile();
            }
        }
        if ($this->caFile !== null) {
            $options['cafile'] = $this->caFile;
        }
        if ($this->caPath !== null) {
            $options['capath'] = $this->caPath;
        }
        if (hasTlsSecurityLevelSupport()) {
            $options['security_level'] = $this->securityLevel;
        }
        if (!empty($this->alpnProtocols)) {
            $options['alpn_protocols'] = \implode(',', $this->alpnProtocols);
        }
        return ['ssl' => $options];
    }
    /**
     * @return int Crypto method compatible with PHP's streams.
     */
    public function toStreamCryptoMethod() : int
    {
        switch ($this->minVersion) {
            case self::TLSv1_0:
                return self::TLSv1_0 | self::TLSv1_1 | self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_1:
                return self::TLSv1_1 | self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_2:
                return self::TLSv1_2 | self::TLSv1_3;
            case self::TLSv1_3:
                return self::TLSv1_3;
            default:
                throw new \RuntimeException('Unknown minimum TLS version: ' . $this->minVersion);
        }
    }
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\Promise;
interface EncryptableSocket extends Socket
{
    public const TLS_STATE_DISABLED = 0;
    public const TLS_STATE_SETUP_PENDING = 1;
    public const TLS_STATE_ENABLED = 2;
    public const TLS_STATE_SHUTDOWN_PENDING = 3;
    /**
     * @param (CancellationToken | null) $cancellationToken
     *
     * @return Promise<void> Resolved when TLS is successfully set up on the socket.
     *
     * @throws SocketException Promise fails and the socket is closed if setting up TLS fails.
     */
    public function setupTls(?CancellationToken $cancellationToken = null) : Promise;
    /**
     * @param (CancellationToken | null) $cancellationToken
     *
     * @return Promise<void> Resolved when TLS is successfully shutdown.
     *
     * @throws SocketException Promise fails and the socket is closed if shutting down TLS fails.
     */
    public function shutdownTls(?CancellationToken $cancellationToken = null) : Promise;
    /**
     * @return int One of the TLS_STATE_* constants defined in this interface.
     */
    public function getTlsState() : int;
    /**
     * @return (TlsInfo | null) The TLS (crypto) context info if TLS is enabled on the socket or null otherwise.
     */
    public function getTlsInfo() : ?TlsInfo;
}<?php

namespace Amp\Socket;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
interface Socket extends InputStream, OutputStream
{
    /**
     * References the read watcher, so the loop keeps running in case there's an active read.
     *
     * @see Loop::reference()
     */
    public function reference() : void;
    /**
     * Unreferences the read watcher, so the loop doesn't keep running even if there are active reads.
     *
     * @see Loop::unreference()
     */
    public function unreference() : void;
    /**
     * Force closes the socket, failing any pending reads or writes.
     */
    public function close() : void;
    /**
     * Returns whether the socket has been closed.
     *
     * @return bool {@code true} if closed, otherwise {@code false}
     */
    public function isClosed() : bool;
    /**
     * @return SocketAddress
     */
    public function getLocalAddress() : SocketAddress;
    /**
     * @return SocketAddress
     */
    public function getRemoteAddress() : SocketAddress;
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\Deferred;
use Amp\Dns;
use Amp\Loop;
use Amp\NullCancellationToken;
use Amp\Promise;
use Amp\TimeoutException;
use function Amp\call;
final class DnsConnector implements Connector
{
    private $resolver;
    /**
     *
     */
    public function __construct(?Dns\Resolver $resolver = null)
    {
        $this->resolver = $resolver;
    }
    /**
     *
     */
    public function connect(string $uri, ?ConnectContext $context = null, ?CancellationToken $token = null) : Promise
    {
        $resolver = $this->resolver;
        return call(static function () use($uri, $context, $token, $resolver) {
            $context = $context ?? new ConnectContext();
            $token = $token ?? new NullCancellationToken();
            $attempt = 0;
            $uris = [];
            $failures = [];
            [$scheme, $host, $port] = Internal\parseUri($uri);
            if ($host[0] === '[') {
                $host = \Phabel\Target\Php80\Polyfill::substr($host, 1, -1);
            }
            if ($port === 0 || @\inet_pton($host)) {
                // Host is already an IP address or file path.
                $uris = [$uri];
            } else {
                // Host is not an IP address, so resolve the domain name.
                $records = (yield ($resolver ?? Dns\resolver())->resolve($host, $context->getDnsTypeRestriction()));
                // Usually the faster response should be preferred, but we don't have a reliable way of determining IPv6
                // support, so we always prefer IPv4 here.
                \usort($records, static function (Dns\Record $a, Dns\Record $b) {
                    return $a->getType() - $b->getType();
                });
                foreach ($records as $record) {
                    /** @var Dns\Record $record */
                    if ($record->getType() === Dns\Record::AAAA) {
                        $uris[] = \sprintf('%s://[%s]:%d', $scheme, $record->getValue(), $port);
                    } else {
                        $uris[] = \sprintf('%s://%s:%d', $scheme, $record->getValue(), $port);
                    }
                }
            }
            $flags = \STREAM_CLIENT_CONNECT | \STREAM_CLIENT_ASYNC_CONNECT;
            $timeout = $context->getConnectTimeout();
            foreach ($uris as $builtUri) {
                try {
                    $streamContext = \stream_context_create($context->withoutTlsContext()->toStreamContextArray());
                    /** @psalm-suppress NullArgument */
                    if (!($socket = @\stream_socket_client($builtUri, $errno, $errstr, null, $flags, $streamContext))) {
                        throw new ConnectException(\sprintf('Connection to %s failed: [Error #%d] %s%s', $uri, $errno, $errstr, $failures ? '; previous attempts: ' . \implode($failures) : ''), $errno);
                    }
                    \stream_set_blocking($socket, false);
                    $deferred = new Deferred();
                    $watcher = Loop::onWritable($socket, static function () use($deferred) {
                        $deferred->resolve();
                    });
                    $id = $token->subscribe([$deferred, 'fail']);
                    try {
                        (yield Promise\timeout($deferred->promise(), $timeout));
                    } catch (TimeoutException $e) {
                        throw new ConnectException(\sprintf('Connecting to %s failed: timeout exceeded (%d ms)%s', $uri, $timeout, $failures ? '; previous attempts: ' . \implode($failures) : ''), 110);
                        // See ETIMEDOUT in http://www.virtsync.com/c-error-codes-include-errno
                    } finally {
                        Loop::cancel($watcher);
                        $token->unsubscribe($id);
                    }
                    // The following hack looks like the only way to detect connection refused errors with PHP's stream sockets.
                    /** @psalm-suppress TypeDoesNotContainType */
                    if (\stream_socket_get_name($socket, true) === false) {
                        \fclose($socket);
                        throw new ConnectException(\sprintf('Connection to %s refused%s', $uri, $failures ? '; previous attempts: ' . \implode($failures) : ''), 111);
                        // See ECONNREFUSED in http://www.virtsync.com/c-error-codes-include-errno
                    }
                } catch (ConnectException $e) {
                    // Includes only error codes used in this file, as error codes on other OS families might be different.
                    // In fact, this might show a confusing error message on OS families that return 110 or 111 by itself.
                    $knownReasons = [110 => 'connection timeout', 111 => 'connection refused'];
                    $code = $e->getCode();
                    $reason = $knownReasons[$code] ?? 'Error #' . $code;
                    if (++$attempt === $context->getMaxAttempts()) {
                        break;
                    }
                    $failures[] = "{$uri} ({$reason})";
                    continue;
                    // Could not connect to host, try next host in the list.
                }
                return ResourceSocket::fromClientSocket($socket, $context->getTlsContext());
            }
            /**
             * This is reached if either all URIs failed or the maximum number of attempts is reached.
             *
             * @noinspection PhpUndefinedVariableInspection
             * @psalm-suppress PossiblyUndefinedVariable
             */
            throw $e;
        });
    }
}<?php

namespace Amp\Socket;

/**
 * @see ServerTlsContext::withDefaultCertificate()
 * @see ServerTlsContext::withCertificates()
 */
final class Certificate
{
    /** @var string */
    private $certFile;
    /** @var string */
    private $keyFile;
    /**
     * @param string $certFile Certificate file with the certificate + intermediaries.
     * @param (string | null) $keyFile Key file with the corresponding private key or `null` if the key is in $certFile.
     */
    public function __construct(string $certFile, string $keyFile = null)
    {
        $this->certFile = $certFile;
        $this->keyFile = $keyFile ?? $certFile;
    }
    /**
     * @return string
     */
    public function getCertFile() : string
    {
        return $this->certFile;
    }
    /**
     * @return string
     */
    public function getKeyFile() : string
    {
        return $this->keyFile;
    }
}<?php

namespace Amp\Socket;

use Amp\CancellationToken;
use Amp\CancelledException;
use Amp\Promise;
/**
 * Allows pooling of connections for stateless protocols.
 */
interface SocketPool
{
    /**
    * Checkout a socket from the specified URI authority.
    *
    * The resulting socket resource should be checked back in via `SocketPool::checkin()` once the calling code is
    finished with the stream (even if the socket has been closed). Failure to checkin sockets will result in memory
    leaks and socket queue blockage. Instead of checking the socket in again, it can also be cleared to prevent
    re-use.
    *
    * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present. An
    optional fragment component can be used to differentiate different socket groups connected to the same URI.
    Connections to the same host with a different ConnectContext must use separate socket groups internally to
    prevent TLS negotiation with the wrong peer name or other TLS settings.
    * @param ConnectContext $context Socket connect context to use when connecting.
    * @param (CancellationToken | null) $token Optional cancellation token to cancel the checkout request.
    *
    * @return Promise<EncryptableSocket> Resolves to an EncryptableSocket instance once a connection is available.
    *
    * @throws SocketException
    * @throws CancelledException
    */
    public function checkout(string $uri, ConnectContext $context = null, CancellationToken $token = null) : Promise;
    /**
     * Return a previously checked-out socket to the pool so it can be reused.
     *
     * @param EncryptableSocket $socket Socket instance.
     *
     * @throws \Error If the provided resource is unknown to the pool.
     */
    public function checkin(EncryptableSocket $socket) : void;
    /**
     * Remove the specified socket from the pool.
     *
     * @param EncryptableSocket $socket Socket instance.
     *
     * @throws \Error If the provided resource is unknown to the pool.
     */
    public function clear(EncryptableSocket $socket) : void;
}<?php

namespace Amp\Socket;

use Amp\Deferred;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
final class Server
{
    /** @var resource|null Stream socket server resource. */
    private $socket;
    /** @var string Watcher ID. */
    private $watcher;
    /** @var SocketAddress Stream socket name */
    private $address;
    /** @var int */
    private $chunkSize;
    /** @var Deferred|null */
    private $acceptor;
    /**
     * Listen for client connections on the specified server address.
     *
     * If you want to accept TLS connections, you have to use `yield $socket->setupTls()` after accepting new clients.
     *
     * @param string $uri URI in scheme://host:port format. TCP is assumed if no scheme is present.
     * @param (BindContext | null) $context Context options for listening.
     *
     * @return Server
     *
     * @throws SocketException If binding to the specified URI failed.
     * @throws \Error If an invalid scheme is given.
     */
    public static function listen(string $uri, ?BindContext $context = null) : self
    {
        $context = $context ?? new BindContext();
        $scheme = \strstr($uri, '://', true);
        if ($scheme === false) {
            $uri = 'tcp://' . $uri;
        } elseif (!\in_array($scheme, ['tcp', 'unix'])) {
            throw new \Error('Only tcp and unix schemes allowed for server creation');
        }
        $streamContext = \stream_context_create($context->toStreamContextArray());
        // Error reporting suppressed since stream_socket_server() emits an E_WARNING on failure (checked below).
        $server = @\stream_socket_server($uri, $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $streamContext);
        if (!$server || $errno) {
            throw new SocketException(\sprintf('Could not create server %s: [Error: #%d] %s', $uri, $errno, $errstr), $errno);
        }
        return new self($server, $context->getChunkSize());
    }
    /**
     * @param resource $socket A bound socket server resource
     * @param int $chunkSize Chunk size for the input and output stream.
     *
     * @throws \Error If a stream resource is not given for $socket.
     */
    public function __construct($socket, int $chunkSize = ResourceSocket::DEFAULT_CHUNK_SIZE)
    {
        if (!\is_resource($socket) || \get_resource_type($socket) !== 'stream') {
            throw new \Error('Invalid resource given to constructor!');
        }
        $this->socket = $socket;
        $this->chunkSize = $chunkSize;
        $this->address = SocketAddress::fromLocalResource($socket);
        \stream_set_blocking($this->socket, false);
        $acceptor =& $this->acceptor;
        $this->watcher = Loop::onReadable($this->socket, static function ($watcher, $socket) use(&$acceptor, $chunkSize) {
            // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
            if (!($client = @\stream_socket_accept($socket, 0))) {
                // Timeout of 0 to be non-blocking.
                return;
                // Accepting client failed.
            }
            $deferred = $acceptor;
            $acceptor = null;
            \assert($deferred !== null);
            $deferred->resolve(ResourceSocket::fromServerSocket($client, $chunkSize));
            /** @psalm-suppress RedundantCondition Resolution of the deferred above might accept immediately again */
            if (!$acceptor) {
                Loop::disable($watcher);
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     * Automatically cancels the loop watcher.
     */
    public function __destruct()
    {
        if (!$this->socket) {
            return;
        }
        $this->free();
    }
    /**
     *
     */
    private function free() : void
    {
        Loop::cancel($this->watcher);
        $this->socket = null;
        if ($this->acceptor) {
            $this->acceptor->resolve();
            $this->acceptor = null;
        }
    }
    /**
     * @return Promise<(ResourceSocket | null)>
     *
     * @throws PendingAcceptError If another accept request is pending.
     */
    public function accept() : Promise
    {
        if ($this->acceptor) {
            throw new PendingAcceptError();
        }
        if (!$this->socket) {
            return new Success();
            // Resolve with null when server is closed.
        }
        // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
        if ($client = @\stream_socket_accept($this->socket, 0)) {
            // Timeout of 0 to be non-blocking.
            return new Success(ResourceSocket::fromServerSocket($client, $this->chunkSize));
        }
        $this->acceptor = new Deferred();
        Loop::enable($this->watcher);
        return $this->acceptor->promise();
    }
    /**
     * Closes the server and stops accepting connections. Any socket clients accepted will not be closed.
     */
    public function close() : void
    {
        if ($this->socket) {
            /** @psalm-suppress InvalidPropertyAssignmentValue */
            \fclose($this->socket);
        }
        $this->free();
    }
    /**
     * @return bool
     */
    public function isClosed() : bool
    {
        return $this->socket === null;
    }
    /**
     * References the accept watcher.
     *
     * @see Loop::reference()
     */
    public final function reference() : void
    {
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the accept watcher.
     *
     * @see Loop::unreference()
     */
    public final function unreference() : void
    {
        Loop::unreference($this->watcher);
    }
    /**
     * @return SocketAddress
     */
    public function getAddress() : SocketAddress
    {
        return $this->address;
    }
    /**
     * Raw stream socket resource.
     *
     * @return (resource | null)
     */
    public final function getResource()
    {
        return $this->socket;
    }
}{
    "name": "amphp/socket",
    "homepage": "https://github.com/amphp/socket",
    "description": "Async socket connection / server tools for Amp.",
    "support": {
        "issues": "https://github.com/amphp/socket/issues"
    },
    "keywords": [
        "tcp",
        "sockets",
        "tls",
        "encryption",
        "async",
        "non-blocking",
        "amp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@gmail.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "ext-openssl": "*",
        "amphp/amp": "^2",
        "amphp/dns": "^1 || ^0.9",
        "amphp/byte-stream": "^1.6",
        "kelunik/certificate": "^1.1",
        "league/uri-parser": "^1.4"
    },
    "require-dev": {
        "phpunit/phpunit": "^6 || ^7 || ^8",
        "amphp/phpunit-util": "^1",
        "amphp/php-cs-fixer-config": "dev-master",
        "vimeo/psalm": "^3.9@dev"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Socket\\": "src"
        },
        "files": [
            "src/functions.php",
            "src/Internal/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Socket\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.x-dev"
        }
    }
}
{
    "symbol-whitelist": [
        "null",
        "true",
        "false",
        "static",
        "self",
        "parent",
        "array",
        "string",
        "int",
        "float",
        "bool",
        "iterable",
        "callable",
        "void",
        "object",
        "MSG_EAGAIN",
        "MSG_ENOMSG",
        "msg_get_queue",
        "MSG_IPC_NOWAIT",
        "msg_queue_exists",
        "msg_receive",
        "msg_remove_queue",
        "msg_send",
        "msg_set_queue",
        "msg_stat_queue",
        "Threaded",
        "transform",
        "SysvMessageQueue"
    ],
    "php-core-extensions": [
        "Core",
        "date",
        "pcre",
        "Phar",
        "Reflection",
        "SPL",
        "standard"
    ]
}
<?php

namespace Amp\Sync;

use Amp\Promise;
final class PrefixedKeyedSemaphore implements KeyedSemaphore
{
    /** @var KeyedSemaphore */
    private $semaphore;
    /** @var string */
    private $prefix;
    /**
     *
     */
    public function __construct(KeyedSemaphore $semaphore, string $prefix)
    {
        $this->semaphore = $semaphore;
        $this->prefix = $prefix;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        return $this->semaphore->acquire($this->prefix . $key);
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
use function Amp\call;
final class LocalKeyedSemaphore implements KeyedSemaphore
{
    /** @var LocalSemaphore[] */
    private $semaphore = [];
    /** @var int[] */
    private $locks = [];
    /** @var int */
    private $maxLocks;
    /**
     *
     */
    public function __construct(int $maxLocks)
    {
        $this->maxLocks = $maxLocks;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        if (!isset($this->semaphore[$key])) {
            $this->semaphore[$key] = new LocalSemaphore($this->maxLocks);
            $this->locks[$key] = 0;
        }
        return call(function () use($key) {
            $this->locks[$key]++;
            /** @var Lock $lock */
            $lock = (yield $this->semaphore[$key]->acquire());
            return new Lock(0, function () use($lock, $key) {
                if (--$this->locks[$key] === 0) {
                    unset($this->semaphore[$key], $this->locks[$key]);
                }
                $lock->release();
            });
        });
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A non-blocking counting semaphore.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface Semaphore
{
    /**
    * Acquires a lock on the semaphore.
    *
    * @return Promise<Lock> Resolves with an integer keyed lock object. Identifiers returned by the
    locks should be 0-indexed. Releasing an identifier MUST make that same identifier available. May fail with
    a SyncException if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire() : Promise;
}<?php

namespace Amp\Sync\Internal;

use Amp\Delayed;
use Amp\Promise;
use Amp\Sync\Lock;
use function Amp\call;
/** @internal */
final class SemaphoreStorage extends \Threaded
{
    public const LATENCY_TIMEOUT = 10;
    /**
     * Creates a new semaphore with a given number of locks.
     *
     * @param int $locks The maximum number of locks that can be acquired from the semaphore.
     */
    public function __construct(int $locks)
    {
        foreach (\range(0, $locks - 1) as $lock) {
            $this[] = $lock;
        }
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        /**
         * Uses a double locking mechanism to acquire a lock without blocking. A
         * synchronous mutex is used to make sure that the semaphore is queried one
         * at a time to preserve the integrity of the semaphore itself. Then a lock
         * count is used to check if a lock is available without blocking.
         *
         * If a lock is not available, we add the request to a queue and set a timer
         * to check again in the future.
         */
        return call(function () : \Generator {
            $tsl = function () : ?int {
                // If there are no locks available or the wait queue is not empty,
                // we need to wait our turn to acquire a lock.
                if (!$this->count()) {
                    return null;
                }
                return $this->shift();
            };
            while (!$this->count() || ($id = $this->synchronized($tsl)) === null) {
                (yield new Delayed(self::LATENCY_TIMEOUT));
            }
            return new Lock($id, function (Lock $lock) : void {
                $id = $lock->getId();
                $this->synchronized(function () use($id) {
                    $this[] = $id;
                });
            });
        });
    }
}<?php

namespace Amp\Sync\Internal;

use Amp\Delayed;
use Amp\Promise;
use Amp\Sync\Lock;
use function Amp\call;
/** @internal */
final class MutexStorage extends \Threaded
{
    public const LATENCY_TIMEOUT = 10;
    /** @var bool */
    private $locked = false;
    /**
     *
     */
    public function acquire() : Promise
    {
        return call(function () : \Generator {
            $tsl = function () : bool {
                if ($this->locked) {
                    return true;
                }
                $this->locked = true;
                return false;
            };
            while ($this->locked || $this->synchronized($tsl)) {
                (yield new Delayed(self::LATENCY_TIMEOUT));
            }
            return new Lock(0, function () : void {
                $this->locked = false;
            });
        });
    }
}<?php

namespace Amp\Sync;

class SyncException extends \Exception
{
}<?php

namespace Amp\Sync\ConcurrentIterator;

use Amp\CancelledException;
use Amp\Iterator;
use Amp\Producer;
use Amp\Promise;
use Amp\Sync\Barrier;
use Amp\Sync\Lock;
use Amp\Sync\Semaphore;
use function Amp\asyncCall;
use function Amp\call;
use function Amp\coroutine;
/**
* Concurrently act on iterator values using {@code $processor}.
*
* @param Iterator $iterator Values to process.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Iterator Result values.
*/
function transform(Iterator $iterator, Semaphore $semaphore, callable $processor) : Iterator
{
    return new Producer(static function (callable $emit) use($iterator, $semaphore, $processor) {
        // one dummy item, because we can't start the barrier with a count of zero
        $barrier = new Barrier(1);
        /** @var \Throwable|null $error */
        $error = null;
        $locks = [];
        $gc = false;
        $processor = coroutine($processor);
        $processor = static function (Lock $lock, $currentElement) use($processor, $emit, $barrier, &$locks, &$error, &$gc) {
            $done = false;
            try {
                (yield $processor($currentElement, $emit));
                $done = true;
            } catch (\Throwable $e) {
                $error = $error ?? $e;
                $done = true;
            } finally {
                if (!$done) {
                    $gc = true;
                }
                unset($locks[$lock->getId()]);
                $lock->release();
                $barrier->arrive();
            }
        };
        while ((yield $iterator->advance())) {
            if ($error) {
                break;
            }
            /** @var Lock $lock */
            $lock = (yield $semaphore->acquire());
            if ($gc || isset($locks[$lock->getId()])) {
                // Throwing here causes a segfault on PHP 7.3
                return;
                // throw new CancelledException; // producer and locks have been GCed
            }
            $locks[$lock->getId()] = true;
            $barrier->register();
            asyncCall($processor, $lock, $iterator->getCurrent());
        }
        $barrier->arrive();
        // remove dummy item
        (yield $barrier->await());
        if ($error) {
            throw $error;
        }
    });
}
/**
* Concurrently map all iterator values using {@code $processor}.
*
* The order of the items in the resulting iterator is not guaranteed in any way.
*
* @param Iterator $iterator Values to map.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Iterator Mapped values.
*/
function map(Iterator $iterator, Semaphore $semaphore, callable $processor) : Iterator
{
    $processor = coroutine($processor);
    return transform($iterator, $semaphore, static function ($value, callable $emit) use($processor) {
        $value = (yield $processor($value));
        (yield $emit($value));
    });
}
/**
* Concurrently filter all iterator values using {@code $filter}.
*
* The order of the items in the resulting iterator is not guaranteed in any way.
*
* @param Iterator $iterator Values to map.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $filter Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted. Must resolve to a boolean, true to keep values in the resulting
iterator.
*
* @return Iterator Values, where {@code $filter} resolved to {@code true}.
*/
function filter(Iterator $iterator, Semaphore $semaphore, callable $filter) : Iterator
{
    $filter = coroutine($filter);
    return transform($iterator, $semaphore, static function ($value, callable $emit) use($filter) {
        $keep = (yield $filter($value));
        if (!\is_bool($keep)) {
            throw new \TypeError(__NAMESPACE__ . '\\filter\'s callable must resolve to a boolean value, got ' . \gettype($keep));
        }
        if ($keep) {
            (yield $emit($value));
        }
    });
}
/**
* Concurrently invoke a callback on all iterator values using {@code $processor}.
*
* @param Iterator $iterator Values to act on.
* @param Semaphore $semaphore Semaphore limiting the concurrency, e.g. {@code LocalSemaphore}
* @param callable $processor Processing callable, which is run as coroutine. It should not throw any errors,
otherwise the entire operation is aborted.
*
* @return Promise
*/
function each(Iterator $iterator, Semaphore $semaphore, callable $processor) : Promise
{
    $processor = coroutine($processor);
    $iterator = transform($iterator, $semaphore, static function ($value, callable $emit) use($processor) {
        (yield $processor($value));
        (yield $emit(null));
    });
    // Use Amp\Iterator\discard in the future
    return call(static function () use($iterator) {
        $count = 0;
        while ((yield $iterator->advance())) {
            $count++;
        }
        return $count;
    });
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A non-blocking synchronization primitive that can be used for mutual exclusion across contexts.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface Mutex extends Semaphore
{
    /**
    * Acquires a lock on the mutex.
    *
    * @return Promise<Lock> Resolves with a lock object with an ID of 0. May fail with a SyncException
    if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire() : Promise;
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * An asynchronous semaphore based on pthreads' synchronization methods.
 *
 * This is an implementation of a thread-safe semaphore that has non-blocking
 * acquire methods. There is a small tradeoff for asynchronous semaphores; you
 * may not acquire a lock immediately when one is available and there may be a
 * small delay. However, the small delay will not block the thread.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
class ThreadedSemaphore implements Semaphore
{
    /** @var \Threaded */
    private $semaphore;
    /**
     * Creates a new semaphore with a given number of locks.
     *
     * @param int $locks The maximum number of locks that can be acquired from the semaphore.
     */
    public function __construct(int $locks)
    {
        if ($locks < 1) {
            throw new \Error("The number of locks should be a positive integer");
        }
        $this->semaphore = new Internal\SemaphoreStorage($locks);
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return $this->semaphore->acquire();
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
final class StaticKeyMutex implements Mutex
{
    /** @var KeyedMutex */
    private $mutex;
    /** @var string */
    private $key;
    /**
     *
     */
    public function __construct(KeyedMutex $mutex, string $key)
    {
        $this->mutex = $mutex;
        $this->key = $key;
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        return $this->mutex->acquire($this->key);
    }
}<?php

namespace Amp\Sync;

use Amp\Coroutine;
use Amp\Delayed;
use Amp\Promise;
/**
 * A non-blocking, inter-process POSIX semaphore.
 *
 * Uses a POSIX message queue to store a queue of permits in a lock-free data structure. This semaphore implementation
 * is preferred over other implementations when available, as it provides the best performance.
 *
 * Not compatible with Windows.
 */
class PosixSemaphore implements Semaphore
{
    public const LATENCY_TIMEOUT = 10;
    /** @var string */
    private $id;
    /** @var int The semaphore key. */
    private $key;
    /** @var int PID of the process that created the semaphore. */
    private $initializer = 0;
    /** @var resource A message queue of available locks. */
    private $queue;
    /**
     * Creates a new semaphore with a given ID and number of locks.
     *
     * @param string $id The unique name for the new semaphore.
     * @param int $maxLocks The maximum number of locks that can be acquired from the semaphore.
     * @param int $permissions Permissions to access the semaphore. Use file permission format specified as 0xxx.
     *
     * @return PosixSemaphore
     * @throws SyncException If the semaphore could not be created due to an internal error.
     */
    public static function create(string $id, int $maxLocks, int $permissions = 0600) : self
    {
        if ($maxLocks < 1) {
            throw new \Error('Number of locks must be greater than 0');
        }
        $semaphore = new self($id);
        $semaphore->init($maxLocks, $permissions);
        return $semaphore;
    }
    /**
     * @param string $id The unique name of the semaphore to use.
     *
     * @return \Amp\Sync\PosixSemaphore
     */
    public static function use(string $id) : self
    {
        $semaphore = new self($id);
        $semaphore->open();
        return $semaphore;
    }
    /**
     * @param string $id
     *
     * @throws \Error If the sysvmsg extension is not loaded.
     */
    private function __construct(string $id)
    {
        if (!\extension_loaded("sysvmsg")) {
            throw new \Error(__CLASS__ . " requires the sysvmsg extension.");
        }
        $this->id = $id;
        $this->key = self::makeKey($this->id);
    }
    /**
     * Private method to prevent cloning.
     */
    private function __clone()
    {
    }
    /**
     * Prevent serialization.
     */
    public function __sleep()
    {
        throw new \Error('A semaphore cannot be serialized!');
    }
    /**
     *
     */
    public function getId() : string
    {
        return $this->id;
    }
    /**
     *
     */
    private function open() : void
    {
        if (!\msg_queue_exists($this->key)) {
            throw new SyncException('No semaphore with that ID found');
        }
        $this->queue = \msg_get_queue($this->key);
        if (!$this->queue) {
            throw new SyncException('Failed to open the semaphore.');
        }
    }
    /**
     * @param int $maxLocks The maximum number of locks that can be acquired from the semaphore.
     * @param int $permissions Permissions to access the semaphore.
     *
     * @throws SyncException If the semaphore could not be created due to an internal error.
     */
    private function init(int $maxLocks, int $permissions) : void
    {
        if (\msg_queue_exists($this->key)) {
            throw new SyncException('A semaphore with that ID already exists');
        }
        $this->queue = \msg_get_queue($this->key, $permissions);
        if (!$this->queue) {
            throw new SyncException('Failed to create the semaphore.');
        }
        $this->initializer = \getmypid();
        // Fill the semaphore with locks.
        while (--$maxLocks >= 0) {
            $this->release($maxLocks);
        }
    }
    /**
     * Gets the access permissions of the semaphore.
     *
     * @return int A permissions mode.
     */
    public function getPermissions() : int
    {
        $stat = \msg_stat_queue($this->queue);
        return $stat['msg_perm.mode'];
    }
    /**
     * Sets the access permissions of the semaphore.
     *
     * The current user must have access to the semaphore in order to change the permissions.
     *
     * @param int $mode A permissions mode to set.
     *
     * @throws SyncException If the operation failed.
     */
    public function setPermissions(int $mode)
    {
        if (!\msg_set_queue($this->queue, ['msg_perm.mode' => $mode])) {
            throw new SyncException('Failed to change the semaphore permissions.');
        }
    }
    /**
     *
     */
    public function acquire() : Promise
    {
        return new Coroutine($this->doAcquire());
    }
    /**
     * {@inheritdoc}
     */
    private function doAcquire() : \Generator
    {
        do {
            // Attempt to acquire a lock from the semaphore.
            if (@\msg_receive($this->queue, 0, $type, 1, $id, false, \MSG_IPC_NOWAIT, $errno)) {
                // A free lock was found, so resolve with a lock object that can
                // be used to release the lock.
                return new Lock(\unpack("C", $id)[1], function (Lock $lock) {
                    $this->release($lock->getId());
                });
            }
            // Check for unusual errors.
            if ($errno !== \MSG_ENOMSG) {
                throw new SyncException(\sprintf('Failed to acquire a lock; errno: %d', $errno));
            }
        } while ((yield new Delayed(self::LATENCY_TIMEOUT, true)));
    }
    /**
     * Removes the semaphore if it still exists.
     *
     * @throws SyncException If the operation failed.
     */
    public function __destruct()
    {
        if ($this->initializer === 0 || $this->initializer !== \getmypid()) {
            return;
        }
        if (\PHP_VERSION_ID < 80000 && (!\is_resource($this->queue) || !\msg_queue_exists($this->key))) {
            return;
        }
        if (\PHP_VERSION_ID >= 80000 && (!$this->queue instanceof \SysvMessageQueue || !\msg_queue_exists($this->key))) {
            return;
        }
        \msg_remove_queue($this->queue);
    }
    /**
     * Releases a lock from the semaphore.
     *
     * @param int $id Lock identifier.
     *
     * @throws SyncException If the operation failed.
     */
    protected function release(int $id)
    {
        if (!$this->queue) {
            return;
            // Queue already destroyed.
        }
        // Call send in non-blocking mode. If the call fails because the queue
        // is full, then the number of locks configured is too large.
        if (!@\msg_send($this->queue, 1, \pack("C", $id), false, false, $errno)) {
            if ($errno === \MSG_EAGAIN) {
                throw new SyncException('The semaphore size is larger than the system allows.');
            }
            throw new SyncException('Failed to release the lock.');
        }
    }
    /**
     *
     */
    private static function makeKey(string $id) : int
    {
        return \abs(\unpack("l", \md5($id, true))[1]);
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
use function Amp\call;
final class LocalKeyedMutex implements KeyedMutex
{
    /** @var LocalMutex[] */
    private $mutex = [];
    /** @var int[] */
    private $locks = [];
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        if (!isset($this->mutex[$key])) {
            $this->mutex[$key] = new LocalMutex();
            $this->locks[$key] = 0;
        }
        return call(function () use($key) {
            $this->locks[$key]++;
            /** @var Lock $lock */
            $lock = (yield $this->mutex[$key]->acquire());
            return new Lock(0, function () use($lock, $key) {
                if (--$this->locks[$key] === 0) {
                    unset($this->mutex[$key], $this->locks[$key]);
                }
                $lock->release();
            });
        });
    }
}<?php

namespace Amp\Sync;

use Amp\Deferred;
use Amp\Promise;
/**
 * A barrier is a synchronization primitive.
 *
 * The barrier is initialized with a certain count, which can be increased and decreased until it reaches zero.
 *
 * A count of one can be used to block multiple coroutines until a certain condition is met.
 *
 * A count of N can be used to await multiple coroutines doing an action to complete.
 *
 * **Example**
 *
 * ```php
 * $barrier = new Amp\Sync\Barrier(2);
 * $barrier->arrive();
 * $barrier->arrive(); // promise returned from Barrier::await() is now resolved
 *
 * yield $barrier->await();
 * ```
 */
final class Barrier
{
    /** @var int */
    private $count;
    /** @var Deferred */
    private $deferred;
    /**
     *
     */
    public function __construct(int $count)
    {
        if ($count < 1) {
            throw new \Error('Count must be positive, got ' . $count);
        }
        $this->count = $count;
        $this->deferred = new Deferred();
    }
    /**
     *
     */
    public function getCount() : int
    {
        return $this->count;
    }
    /**
     *
     */
    public function arrive(int $count = 1) : void
    {
        if ($count < 1) {
            throw new \Error('Count must be at least 1, got ' . $count);
        }
        if ($count > $this->count) {
            throw new \Error('Count cannot be greater than remaining count: ' . $count . ' > ' . $this->count);
        }
        $this->count -= $count;
        if ($this->count === 0) {
            $this->deferred->resolve();
        }
    }
    /**
     *
     */
    public function register(int $count = 1) : void
    {
        if ($count < 1) {
            throw new \Error('Count must be at least 1, got ' . $count);
        }
        if ($this->count === 0) {
            throw new \Error('Can\'t increase count, because the barrier already broke');
        }
        $this->count += $count;
    }
    /**
     *
     */
    public function await() : Promise
    {
        return $this->deferred->promise();
    }
}<?php

namespace Amp\Sync;

use Amp\CallableMaker;
use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
class LocalSemaphore implements Semaphore
{
    use CallableMaker;
    // kept for BC only
    /** @var int[] */
    private $locks;
    /** @var Deferred[] */
    private $queue = [];
    /**
     *
     */
    public function __construct(int $maxLocks)
    {
        if ($maxLocks < 1) {
            throw new \Error('The number of locks must be greater than 0');
        }
        $this->locks = \range(0, $maxLocks - 1);
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        if (!empty($this->locks)) {
            return new Success(new Lock(\array_shift($this->locks), \Closure::fromCallable([$this, 'release'])));
        }
        $this->queue[] = $deferred = new Deferred();
        return $deferred->promise();
    }
    /**
     *
     */
    private function release(Lock $lock) : void
    {
        $id = $lock->getId();
        if (!empty($this->queue)) {
            $deferred = \array_shift($this->queue);
            $deferred->resolve(new Lock($id, \Closure::fromCallable([$this, 'release'])));
            return;
        }
        $this->locks[] = $id;
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
final class PrefixedKeyedMutex implements KeyedMutex
{
    /** @var KeyedMutex */
    private $mutex;
    /** @var string */
    private $prefix;
    /**
     *
     */
    public function __construct(KeyedMutex $mutex, string $prefix)
    {
        $this->mutex = $mutex;
        $this->prefix = $prefix;
    }
    /**
     *
     */
    public function acquire(string $key) : Promise
    {
        return $this->mutex->acquire($this->prefix . $key);
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A thread-safe, asynchronous mutex using the pthreads locking mechanism.
 *
 * Compatible with POSIX systems and Microsoft Windows.
 *
 * @deprecated ext-pthreads development has been halted, see https://github.com/krakjoe/pthreads/issues/929
 */
class ThreadedMutex implements Mutex
{
    /** @var Internal\MutexStorage */
    private $mutex;
    /**
     * Creates a new threaded mutex.
     */
    public function __construct()
    {
        $this->mutex = new Internal\MutexStorage();
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return $this->mutex->acquire();
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A non-blocking counting semaphore based on keys.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface KeyedSemaphore
{
    /**
    * Acquires a lock on the semaphore.
    *
    * @param string $key Lock key
    *
    * @return Promise<Lock> Resolves with an integer keyed lock object. Identifiers returned by the
    locks should be 0-indexed. Releasing an identifier MUST make that same identifier available. May fail with
    a SyncException if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire(string $key) : Promise;
}<?php

namespace Amp\Sync;

use Amp\Coroutine;
use Amp\Delayed;
use Amp\Promise;
/**
 * A cross-platform mutex that uses exclusive files as the lock mechanism.
 *
 * This mutex implementation is not always atomic and depends on the operating
 * system's implementation of file creation operations. Use this implementation
 * only if no other mutex types are available.
 *
 * This implementation avoids using [flock()](https://www.php.net/flock)
 * because flock() is known to have some atomicity issues on some systems. In
 * addition, flock() does not work as expected when trying to lock a file
 * multiple times in the same process on Linux. Instead, exclusive file creation
 * is used to create a lock file, which is atomic on most systems.
 *
 * @see https://www.php.net/fopen
 */
class FileMutex implements Mutex
{
    public const LATENCY_TIMEOUT = 10;
    /** @var string The full path to the lock file. */
    private $fileName;
    /**
     * @param string $fileName Name of temporary file to use as a mutex.
     */
    public function __construct(string $fileName)
    {
        $this->fileName = $fileName;
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return new Coroutine($this->doAcquire());
    }
    /**
     * @coroutine
     *
     * @return \Generator
     */
    private function doAcquire() : \Generator
    {
        // Try to create the lock file. If the file already exists, someone else
        // has the lock, so set an asynchronous timer and try again.
        while (($handle = @\fopen($this->fileName, 'x')) === false) {
            (yield new Delayed(self::LATENCY_TIMEOUT));
        }
        // Return a lock object that can be used to release the lock on the mutex.
        $lock = new Lock(0, function () : void {
            $this->release();
        });
        \fclose($handle);
        return $lock;
    }
    /**
     * Releases the lock on the mutex.
     *
     * @throws SyncException If the unlock operation failed.
     */
    protected function release()
    {
        $success = @\unlink($this->fileName);
        if (!$success) {
            throw new SyncException('Failed to unlock the mutex file.');
        }
    }
}<?php

namespace Amp\Sync;

/**
 * A handle on an acquired lock from a synchronization object.
 *
 * This object is not thread-safe; after acquiring a lock from a mutex or
 * semaphore, the lock should reside in the same thread or process until it is
 * released.
 */
class Lock
{
    /** @var callable|null The function to be called on release or null if the lock has been released. */
    private $releaser;
    /** @var int */
    private $id;
    /**
     * Creates a new lock permit object.
     *
     * @param int $id The lock identifier.
     * @param callable(self ): void $releaser A function to be called upon release.
     */
    public function __construct(int $id, callable $releaser)
    {
        $this->id = $id;
        $this->releaser = $releaser;
    }
    /**
     * Checks if the lock has already been released.
     *
     * @return bool True if the lock has already been released, otherwise false.
     */
    public function isReleased() : bool
    {
        return !$this->releaser;
    }
    /**
     * @return int Lock identifier.
     */
    public function getId() : int
    {
        return $this->id;
    }
    /**
     * Releases the lock. No-op if the lock has already been released.
     */
    public function release()
    {
        if (!$this->releaser) {
            return;
        }
        // Invoke the releaser function given to us by the synchronization source
        // to release the lock.
        $releaser = $this->releaser;
        $this->releaser = null;
        $releaser($this);
    }
    /**
     * Releases the lock when there are no more references to it.
     */
    public function __destruct()
    {
        if (!$this->isReleased()) {
            $this->release();
        }
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
use function Amp\call;
class SemaphoreMutex implements Mutex
{
    /** @var Semaphore */
    private $semaphore;
    /**
     * @param Semaphore $semaphore A semaphore with a single lock.
     */
    public function __construct(Semaphore $semaphore)
    {
        $this->semaphore = $semaphore;
    }
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        return call(function () : \Generator {
            /** @var \Amp\Sync\Lock $lock */
            $lock = (yield $this->semaphore->acquire());
            if ($lock->getId() !== 0) {
                $lock->release();
                throw new \Error("Cannot use a semaphore with more than a single lock");
            }
            return $lock;
        });
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
use function Amp\call;
/**
* Invokes the given callback while maintaining a lock from the provided mutex. The lock is automatically released after
invoking the callback or once the promise returned by the callback is resolved. If the callback returns a Generator,
it will be run as a coroutine. See Amp\call().
*
* @param Mutex $mutex
* @param callable $callback
* @param array ...$args
*
* @return Promise Resolves with the return value of the callback.
*/
function synchronized(Mutex $mutex, callable $callback, ...$args) : Promise
{
    return call(static function () use($mutex, $callback, $args) : \Generator {
        /** @var Lock $lock */
        $lock = (yield $mutex->acquire());
        try {
            return (yield call($callback, ...$args));
        } finally {
            $lock->release();
        }
    });
}<?php

namespace Amp\Sync;

use Amp\CallableMaker;
use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
class LocalMutex implements Mutex
{
    use CallableMaker;
    // kept for BC only
    /** @var bool */
    private $locked = false;
    /** @var Deferred[] */
    private $queue = [];
    /**
     * {@inheritdoc}
     */
    public function acquire() : Promise
    {
        if (!$this->locked) {
            $this->locked = true;
            return new Success(new Lock(0, \Closure::fromCallable([$this, 'release'])));
        }
        $this->queue[] = $deferred = new Deferred();
        return $deferred->promise();
    }
    /**
     *
     */
    private function release() : void
    {
        if (!empty($this->queue)) {
            $deferred = \array_shift($this->queue);
            $deferred->resolve(new Lock(0, \Closure::fromCallable([$this, 'release'])));
            return;
        }
        $this->locked = false;
    }
}<?php

namespace Amp\Sync;

use Amp\Promise;
/**
 * A non-blocking synchronization primitive that can be used for mutual exclusion across contexts based on keys.
 *
 * Objects that implement this interface should guarantee that all operations are atomic. Implementations do not have to
 * guarantee that acquiring a lock is first-come, first serve.
 */
interface KeyedMutex extends KeyedSemaphore
{
    /**
    * Acquires a lock on the mutex.
    *
    * @param string $key Lock key
    *
    * @return Promise<Lock> Resolves with a lock object with an ID of 0. May fail with a SyncException
    if an error occurs when attempting to obtain the lock (e.g. a shared memory segment closed).
    */
    public function acquire(string $key) : Promise;
}{
    "name": "amphp/sync",
    "description": "Mutex, Semaphore, and other synchronization tools for Amp.",
    "keywords": [
        "asynchronous",
        "async",
        "mutex",
        "semaphore",
        "synchronization"
    ],
    "homepage": "https://github.com/amphp/sync",
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Stephen Coakley",
            "email": "me@stephencoakley.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2.2"
    },
    "require-dev": {
        "phpunit/phpunit": "^9 || ^8 || ^7",
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Sync\\": "src"
        },
        "files": [
            "src/functions.php",
            "src/ConcurrentIterator/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Sync\\Test\\": "test"
        }
    }
}
{
    "name": "amphp/cache",
    "homepage": "https://github.com/amphp/cache",
    "description": "A promise-aware caching API for Amp.",
    "license": "MIT",
    "support": {
        "issues": "https://github.com/amphp/cache/issues",
        "irc": "irc://irc.freenode.org/amphp"
    },
    "authors": [
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/serialization": "^1",
        "amphp/sync": "^1.2"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1.1",
        "phpunit/phpunit": "^6 | ^7 | ^8 | ^9",
        "amphp/php-cs-fixer-config": "dev-master",
        "amphp/file": "^1 || ^2",
        "vimeo/psalm": "^4"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Cache\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Cache\\Test\\": "test"
        }
    },
    "conflict": {
        "amphp/file": "<0.2 || >=3"
    }
}
<?php

namespace Amp\Cache;

use Amp\Loop;
use Amp\Promise;
use Amp\Struct;
use Amp\Success;
final class ArrayCache implements Cache
{
    /** @var object */
    private $sharedState;
    /** @var string */
    private $ttlWatcherId;
    /** @var int|null */
    private $maxSize;
    /**
     * @param int $gcInterval The frequency in milliseconds at which expired cache entries should be garbage collected.
     * @param int $maxSize The maximum size of cache array (number of elements).
     */
    public function __construct(int $gcInterval = 5000, int $maxSize = null)
    {
        // By using a shared state object we're able to use `__destruct()` for "normal" garbage collection of both this
        // instance and the loop's watcher. Otherwise this object could only be GC'd when the TTL watcher was cancelled
        // at the loop layer.
        $this->sharedState = $sharedState = new class
        {
            use Struct;
            /** @var string[] */
            public $cache = [];
            /** @var int[] */
            public $cacheTimeouts = [];
            /** @var bool */
            public $isSortNeeded = false;
            /**
             *
             */
            public function collectGarbage() : void
            {
                $now = \time();
                if ($this->isSortNeeded) {
                    \asort($this->cacheTimeouts);
                    $this->isSortNeeded = false;
                }
                foreach ($this->cacheTimeouts as $key => $expiry) {
                    if ($now <= $expiry) {
                        break;
                    }
                    unset($this->cache[$key], $this->cacheTimeouts[$key]);
                }
            }
        };
        $this->ttlWatcherId = Loop::repeat($gcInterval, [$sharedState, "collectGarbage"]);
        $this->maxSize = $maxSize;
        Loop::unreference($this->ttlWatcherId);
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->sharedState->cache = [];
        $this->sharedState->cacheTimeouts = [];
        Loop::cancel($this->ttlWatcherId);
    }
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        if (!isset($this->sharedState->cache[$key])) {
            return new Success(null);
        }
        if (isset($this->sharedState->cacheTimeouts[$key]) && \time() > $this->sharedState->cacheTimeouts[$key]) {
            unset($this->sharedState->cache[$key], $this->sharedState->cacheTimeouts[$key]);
            return new Success(null);
        }
        return new Success($this->sharedState->cache[$key]);
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        if ($ttl === null) {
            unset($this->sharedState->cacheTimeouts[$key]);
        } elseif ($ttl >= 0) {
            $expiry = \time() + $ttl;
            $this->sharedState->cacheTimeouts[$key] = $expiry;
            $this->sharedState->isSortNeeded = true;
        } else {
            throw new \Error("Invalid cache TTL ({$ttl}; integer >= 0 or null required");
        }
        unset($this->sharedState->cache[$key]);
        if (\count($this->sharedState->cache) === $this->maxSize) {
            \array_shift($this->sharedState->cache);
        }
        $this->sharedState->cache[$key] = $value;
        /** @var Promise<void> */
        return new Success();
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        $exists = isset($this->sharedState->cache[$key]);
        unset($this->sharedState->cache[$key], $this->sharedState->cacheTimeouts[$key]);
        return new Success($exists);
    }
}<?php

namespace Amp\Cache;

use Amp\Failure;
use Amp\Promise;
use Amp\Serialization\SerializationException;
use Amp\Serialization\Serializer;
use function Amp\call;
/**
 * @template TValue
 */
final class SerializedCache
{
    /** @var Cache */
    private $cache;
    /** @var Serializer */
    private $serializer;
    /**
     *
     */
    public function __construct(Cache $cache, Serializer $serializer)
    {
        $this->cache = $cache;
        $this->serializer = $serializer;
    }
    /**
    * Fetch a value from the cache and unserialize it.
    *
    * @param $key string Cache key.
    *
    * @return Promise<(mixed | null)> Resolves to the cached value or `null` if it doesn't exist. Fails with a
    CacheException or SerializationException on failure.
    *
    * @psalm-return Promise<(TValue | null)>
    *
    * @see Cache::get()
    */
    public function get(string $key) : Promise
    {
        return call(function () use($key) {
            $data = (yield $this->cache->get($key));
            if ($data === null) {
                return null;
            }
            return $this->serializer->unserialize($data);
        });
    }
    /**
    * Serializes a value and stores its serialization to the cache.
    *
    * @param $key   string Cache key.
    * @param $value mixed Value to cache.
    * @param $ttl   int Timeout in seconds. The default `null` $ttl value indicates no timeout. Values less than 0 MUST
    throw an \Error.
    *
    * @psalm-param TValue $value
    *
    * @return Promise<void> Resolves either successfully or fails with a CacheException or SerializationException.
    *
    * @see Cache::set()
    */
    public function set(string $key, $value, int $ttl = null) : Promise
    {
        if ($value === null) {
            return new Failure(new CacheException('Cannot store NULL in serialized cache'));
        }
        try {
            $value = $this->serializer->serialize($value);
        } catch (SerializationException $exception) {
            return new Failure($exception);
        }
        return $this->cache->set($key, $value, $ttl);
    }
    /**
    * Deletes a value associated with the given key if it exists.
    *
    * @param $key string Cache key.
    *
    * @return Promise<(bool | null)> Resolves to `true` / `false` to indicate whether the key existed or fails with a
    CacheException on failure. May also resolve with `null` if that information is not available.
    *
    * @see Cache::delete()
    */
    public function delete(string $key) : Promise
    {
        return $this->cache->delete($key);
    }
}<?php

namespace Amp\Cache;

use Amp\Promise;
use Amp\Serialization\SerializationException;
use Amp\Sync\KeyedMutex;
use Amp\Sync\Lock;
use function Amp\call;
/**
 * @template TValue
 */
final class AtomicCache
{
    /** @var SerializedCache<TValue> */
    private $cache;
    /** @var KeyedMutex */
    private $mutex;
    /**
     * @param SerializedCache<TValue> $cache
     * @param KeyedMutex $mutex
     */
    public function __construct(SerializedCache $cache, KeyedMutex $mutex)
    {
        $this->cache = $cache;
        $this->mutex = $mutex;
    }
    /**
    * Obtains the lock for the given key, then invokes the $create callback with the current cached value (which may
    be null if the key did not exist in the cache). The value returned from the callback is stored in the cache and
    the promise returned from this method is resolved with the value.
    *
    * @param string $key
    * @param callable(string , (mixed | null) ): mixed $create Receives $key and $value as parameters.
    * @param (int | null) $ttl Timeout in seconds. The default `null` $ttl value indicates no timeout.
    *
    * @return Promise<mixed>
    *
    * @psalm-param callable(string, TValue|null):(TValue|Promise<TValue>|\Generator<mixed, mixed, mixed, TValue>)
    $create
    * @psalm-return Promise<TValue>
    *
    * @throws CacheException If the $create callback throws an exception while generating the value.
    * @throws SerializationException If serializing the value returned from the callback fails.
    */
    public function compute(string $key, callable $create, ?int $ttl = null) : Promise
    {
        return call(function () use($key, $create, $ttl) : \Generator {
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                $value = (yield $this->cache->get($key));
                return yield from $this->create($create, $key, $value, $ttl);
            } finally {
                $lock->release();
            }
        });
    }
    /**
    * Attempts to get the value for the given key. If the key is not found, the key is locked, the $create callback
    is invoked with the key as the first parameter. The value returned from the callback is stored in the cache and
    the promise returned from this method is resolved with the value.
    *
    * @param string $key Cache key.
    * @param callable(string ): mixed $create Receives $key as parameter.
    * @param (int | null) $ttl Timeout in seconds. The default `null` $ttl value indicates no timeout.
    *
    * @return Promise<mixed>
    *
    * @psalm-param callable(string, TValue|null):(TValue|Promise<TValue>|\Generator<mixed, mixed, mixed, TValue>)
    $create
    * @psalm-return Promise<TValue>
    *
    * @throws CacheException If the $create callback throws an exception while generating the value.
    * @throws SerializationException If serializing the value returned from the callback fails.
    */
    public function computeIfAbsent(string $key, callable $create, ?int $ttl = null) : Promise
    {
        return call(function () use($key, $create, $ttl) : \Generator {
            $value = (yield $this->cache->get($key));
            if ($value !== null) {
                return $value;
            }
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                // Attempt to get the value again, since it may have been set while obtaining the lock.
                $value = (yield $this->cache->get($key));
                if ($value !== null) {
                    return $value;
                }
                return yield from $this->create($create, $key, null, $ttl);
            } finally {
                $lock->release();
            }
        });
    }
    /**
    * Attempts to get the value for the given key. If the key exists, the key is locked, the $create callback
    is invoked with the key as the first parameter and the current key value as the second parameter. The value
    returned from the callback is stored in the cache and the promise returned from this method is resolved with
    the value.
    *
    * @param string $key Cache key.
    * @param callable(string , mixed ): mixed $create Receives $key and $value as parameters.
    * @param (int | null) $ttl Timeout in seconds. The default `null` $ttl value indicates no timeout.
    *
    * @return Promise<mixed>
    *
    * @psalm-param callable(string , (TValue | null) ): (TValue | Promise<TValue> | \Generator<mixed, mixed, mixed, TValue>) $create
    * @psalm-return Promise<TValue>
    *
    * @throws CacheException If the $create callback throws an exception while generating the value.
    * @throws SerializationException If serializing the value returned from the callback fails.
    */
    public function computeIfPresent(string $key, callable $create, ?int $ttl = null) : Promise
    {
        return call(function () use($key, $create, $ttl) : \Generator {
            $value = (yield $this->cache->get($key));
            if ($value === null) {
                return null;
            }
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                // Attempt to get the value again, since it may have been set while obtaining the lock.
                $value = (yield $this->cache->get($key));
                if ($value === null) {
                    return null;
                }
                return yield from $this->create($create, $key, $value, $ttl);
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * The lock is obtained for the key before setting the value.
     *
     * @param string $key Cache key.
     * @param mixed $value Value to cache.
     * @param (int | null) $ttl Timeout in seconds. The default `null` $ttl value indicates no timeout.
     *
     * @return Promise<void> Resolves either successfully or fails with a CacheException on failure.
     *
     * @psalm-param TValue $value
     * @psalm-return Promise<void>
     *
     * @throws CacheException
     * @throws SerializationException
     *
     * @see SerializedCache::set()
     */
    public function set(string $key, $value, ?int $ttl = null) : Promise
    {
        return call(function () use($key, $value, $ttl) : \Generator {
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                (yield $this->cache->set($key, $value, $ttl));
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * Returns the cached value for the key or the given default value if the key does not exist.
     *
     * @template TDefault
     *
     * @param string $key Cache key.
     * @param mixed $default Default value returned if the key does not exist. Null by default.
     *
     * @return Promise<(mixed | null)> Resolved with null iff $default is null.
     *
     * @psalm-param TDefault $default
     * @psalm-return Promise<(TValue | TDefault)>
     *
     * @throws CacheException
     * @throws SerializationException
     *
     * @see SerializedCache::get()
     */
    public function get(string $key, $default = null) : Promise
    {
        return call(function () use($key, $default) : \Generator {
            $value = (yield $this->cache->get($key));
            if ($value === null) {
                return $default;
            }
            return $value;
        });
    }
    /**
     * The lock is obtained for the key before deleting the key.
     *
     * @param string $key
     *
     * @return Promise<(bool | null)>
     *
     * @see SerializedCache::delete()
     */
    public function delete(string $key) : Promise
    {
        return call(function () use($key) : \Generator {
            $lock = (yield from $this->lock($key));
            \assert($lock instanceof Lock);
            try {
                return (yield $this->cache->delete($key));
            } finally {
                $lock->release();
            }
        });
    }
    /**
     *
     */
    private function lock(string $key) : \Generator
    {
        try {
            return (yield $this->mutex->acquire($key));
        } catch (\Throwable $exception) {
            throw new CacheException(\sprintf('Exception thrown when obtaining the lock for key "%s"', $key), 0, $exception);
        }
    }
    /**
     * @psalm-param (TValue | null) $value
     * @psalm-return \Generator<mixed, mixed, mixed, TValue>
     */
    private function create(callable $create, string $key, $value, ?int $ttl) : \Generator
    {
        try {
            $value = (yield call($create, $key, $value));
        } catch (\Throwable $exception) {
            throw new CacheException(\sprintf('Exception thrown while creating the value for key "%s"', $key), 0, $exception);
        }
        (yield $this->cache->set($key, $value, $ttl));
        return $value;
    }
}<?php

namespace Amp\Cache;

use Amp\Promise;
use Amp\Success;
/**
 * Cache implementation that just ignores all operations and always resolves to `null`.
 */
class NullCache implements Cache
{
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        return new Success();
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        /** @var Promise<void> */
        return new Success();
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        return new Success(false);
    }
}<?php

/** @noinspection PhpUndefinedFunctionInspection */
namespace Amp\Cache;

use Amp\File;
use Amp\File\Driver;
use Amp\Loop;
use Amp\Promise;
use Amp\Sync\KeyedMutex;
use Amp\Sync\Lock;
use function Amp\call;
final class FileCache implements Cache
{
    /**
     *
     */
    private static function getFilename(string $key) : string
    {
        return \hash('sha256', $key) . '.cache';
    }
    /** @var string */
    private $directory;
    /** @var KeyedMutex */
    private $mutex;
    /** @var string */
    private $gcWatcher;
    /** @var bool */
    private $ampFileVersion2;
    /**
     *
     */
    public function __construct(string $directory, KeyedMutex $mutex)
    {
        $this->directory = $directory = \rtrim($directory, "/\\");
        $this->mutex = $mutex;
        if (!\interface_exists(Driver::class)) {
            throw new \Error(__CLASS__ . ' requires amphp/file to be installed');
        }
        $this->ampFileVersion2 = $ampFileVersion2 = \function_exists('Amp\\File\\listFiles');
        $gcWatcher = static function () use($directory, $mutex, $ampFileVersion2) : \Generator {
            try {
                /** @psalm-suppress UndefinedFunction */
                $files = (yield $ampFileVersion2 ? File\listFiles($directory) : File\scandir($directory));
                foreach ($files as $file) {
                    if (\strlen($file) !== 70 || \Phabel\Target\Php80\Polyfill::substr($file, -\strlen('.cache')) !== '.cache') {
                        continue;
                    }
                    /** @var Lock $lock */
                    $lock = (yield $mutex->acquire($file));
                    try {
                        /** @var File\File $handle */
                        /** @psalm-suppress UndefinedFunction */
                        $handle = (yield $ampFileVersion2 ? File\openFile($directory . '/' . $file, 'r') : File\open($directory . '/' . $file, 'r'));
                        $ttl = (yield $handle->read(4));
                        if ($ttl === null || \strlen($ttl) !== 4) {
                            (yield $handle->close());
                            continue;
                        }
                        $ttl = \unpack('Nttl', $ttl)['ttl'];
                        if ($ttl < \time()) {
                            /** @psalm-suppress UndefinedFunction */
                            (yield $ampFileVersion2 ? File\deleteFile($directory . '/' . $file) : File\unlink($directory . '/' . $file));
                        }
                    } catch (\Throwable $e) {
                        // ignore
                    } finally {
                        $lock->release();
                    }
                }
            } catch (\Throwable $e) {
                // ignore
            }
        };
        // trigger once, so short running scripts also GC and don't grow forever
        Loop::defer($gcWatcher);
        $this->gcWatcher = Loop::repeat(300000, $gcWatcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        if ($this->gcWatcher !== null) {
            Loop::cancel($this->gcWatcher);
        }
    }
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        return call(function () use($key) {
            $filename = $this->getFilename($key);
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire($filename));
            try {
                /** @psalm-suppress UndefinedFunction */
                $cacheContent = (yield $this->ampFileVersion2 ? File\read($this->directory . '/' . $filename) : File\get($this->directory . '/' . $filename));
                if (\strlen($cacheContent) < 4) {
                    return null;
                }
                $ttl = \unpack('Nttl', \Phabel\Target\Php80\Polyfill::substr($cacheContent, 0, 4))['ttl'];
                if ($ttl < \time()) {
                    /** @psalm-suppress UndefinedFunction */
                    (yield $this->ampFileVersion2 ? File\deleteFile($this->directory . '/' . $filename) : File\unlink($this->directory . '/' . $filename));
                    return null;
                }
                $value = \Phabel\Target\Php80\Polyfill::substr($cacheContent, 4);
                \assert(\is_string($value));
                return $value;
            } catch (\Throwable $e) {
                return null;
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        if ($ttl < 0) {
            throw new \Error("Invalid cache TTL ({$ttl}); integer >= 0 or null required");
        }
        return call(function () use($key, $value, $ttl) {
            $filename = $this->getFilename($key);
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire($filename));
            if ($ttl === null) {
                $ttl = \PHP_INT_MAX;
            } else {
                $ttl = \time() + $ttl;
            }
            $encodedTtl = \pack('N', $ttl);
            try {
                /** @psalm-suppress UndefinedFunction */
                (yield $this->ampFileVersion2 ? File\write($this->directory . '/' . $filename, $encodedTtl . $value) : File\put($this->directory . '/' . $filename, $encodedTtl . $value));
            } finally {
                $lock->release();
            }
        });
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        return call(function () use($key) {
            $filename = $this->getFilename($key);
            /** @var Lock $lock */
            $lock = (yield $this->mutex->acquire($filename));
            try {
                /** @psalm-suppress UndefinedFunction */
                return (yield $this->ampFileVersion2 ? File\deleteFile($this->directory . '/' . $filename) : File\unlink($this->directory . '/' . $filename));
            } finally {
                $lock->release();
            }
        });
    }
}<?php

namespace Amp\Cache;

use Amp\Promise;
final class PrefixCache implements Cache
{
    private $cache;
    private $keyPrefix;
    /**
     *
     */
    public function __construct(Cache $cache, string $keyPrefix)
    {
        $this->cache = $cache;
        $this->keyPrefix = $keyPrefix;
    }
    /**
     * Gets the specified key prefix.
     *
     * @return string
     */
    public function getKeyPrefix() : string
    {
        return $this->keyPrefix;
    }
    /**
     * @inheritdoc
     */
    public function get(string $key) : Promise
    {
        return $this->cache->get($this->keyPrefix . $key);
    }
    /**
     * @inheritdoc
     */
    public function set(string $key, string $value, int $ttl = null) : Promise
    {
        return $this->cache->set($this->keyPrefix . $key, $value, $ttl);
    }
    /**
     * @inheritdoc
     */
    public function delete(string $key) : Promise
    {
        return $this->cache->delete($this->keyPrefix . $key);
    }
}<?php

namespace Amp\Cache;

/**
 * MUST be thrown in case a cache operation fails.
 */
class CacheException extends \Exception
{
}<?php

namespace Amp\Cache;

use Amp\Promise;
interface Cache
{
    /**
    * Gets a value associated with the given key.
    *
    * If the specified key doesn't exist implementations MUST succeed the resulting promise with `null`.
    *
    * @param $key string Cache key.
    *
    * @return Promise<(string | null)> Resolves to the cached value nor `null` if it doesn't exist or fails with a
    CacheException on failure.
    */
    public function get(string $key) : Promise;
    /**
    * Sets a value associated with the given key. Overrides existing values (if they exist).
    *
    * The eventual resolution value of the resulting promise is unimportant. The success or failure of the promise
    indicates the operation's success.
    *
    * @param $key string Cache key.
    * @param $value string Value to cache.
    * @param $ttl int Timeout in seconds. The default `null` $ttl value indicates no timeout. Values less than 0 MUST
    throw an \Error.
    *
    * @return Promise<void> Resolves either successfully or fails with a CacheException on failure.
    */
    public function set(string $key, string $value, int $ttl = null) : Promise;
    /**
    * Deletes a value associated with the given key if it exists.
    *
    * Implementations SHOULD return boolean `true` or `false` to indicate whether the specified key existed at the time
    the delete operation was requested. If such information is not available, the implementation MUST resolve the
    promise with `null`.
    *
    * Implementations MUST transparently succeed operations for non-existent keys.
    *
    * @param $key string Cache key.
    *
    * @return Promise<(bool | null)> Resolves to `true` / `false` to indicate whether the key existed or fails with a
    CacheException on failure. May also resolve with `null` if that information is not available.
    */
    public function delete(string $key) : Promise;
}<?php

namespace Amp\Log;

use Amp\ByteStream\OutputStream;
use Monolog\Handler\AbstractProcessingHandler;
use Psr\Log\LogLevel;
final class StreamHandler extends AbstractProcessingHandler
{
    /** @var OutputStream */
    private $stream;
    /** @var callable */
    private $onResolve;
    /** @var \Throwable|null */
    private $exception;
    /**
     * @param OutputStream $outputStream
     * @param string $level
     * @param bool $bubble
     */
    public function __construct(OutputStream $outputStream, string $level = LogLevel::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->stream = $outputStream;
        $stream =& $this->stream;
        $exception =& $this->exception;
        $this->onResolve = static function (\Throwable $e = null) use(&$stream, &$exception) {
            if (!$stream) {
                return;
                // Prior write already failed, ignore this failure.
            }
            if ($e) {
                $stream = null;
                $exception = $e;
                throw $e;
            }
        };
    }
    /**
     * Writes the record down to the log of the implementing handler.
     *
     * @param array $record
     *
     * @return void
     */
    protected function write(array $record) : void
    {
        if ($this->exception) {
            throw $this->exception;
        }
        $this->stream->write((string) $record['formatted'])->onResolve($this->onResolve);
    }
}<?php

namespace Amp\Log;

/**
 *
 */
function hasColorSupport() : bool
{
    $os = \stripos(\PHP_OS, "WIN") === 0 ? "win" : \strtolower(\PHP_OS);
    // @see https://github.com/symfony/symfony/blob/v4.0.6/src/Symfony/Component/Console/Output/StreamOutput.php#L91
    // @license https://github.com/symfony/symfony/blob/v4.0.6/LICENSE
    if ($os === 'win') {
        $windowsVersion = PHP_WINDOWS_VERSION_MAJOR . '.' . PHP_WINDOWS_VERSION_MINOR . '.' . PHP_WINDOWS_VERSION_BUILD;
        return \function_exists('sapi_windows_vt100_support') && @\sapi_windows_vt100_support(\STDOUT) || $windowsVersion === '10.0.10586' || false !== \getenv('ANSICON') || 'ON' === \getenv('ConEmuANSI') || 'xterm' === \getenv('TERM');
    }
    if (\function_exists('posix_isatty')) {
        return @\posix_isatty(\STDOUT);
    }
    return false;
}<?php

namespace Amp\Log;

use Monolog\Formatter\LineFormatter;
use Psr\Log\LogLevel;
final class ConsoleFormatter extends LineFormatter
{
    const DEFAULT_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\r\n";
    /** @var bool */
    private $colors;
    /**
     *
     */
    public function __construct(string $format = null, string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false)
    {
        parent::__construct($format ?? self::DEFAULT_FORMAT, $dateFormat, $allowInlineLineBreaks, $ignoreEmptyContextAndExtra);
        $this->setAnsiColorOption();
    }
    /**
     *
     */
    public function format(array $record) : string
    {
        if ($this->colors) {
            $record['level_name'] = $this->ansifyLevel($record['level_name']);
            $record['channel'] = "\x1b[1m{$record['channel']}\x1b[0m";
        }
        return parent::format($record);
    }
    /**
     *
     */
    private function setAnsiColorOption() : void
    {
        $value = \getenv("AMP_LOG_COLOR");
        if ($value === false || $value === '') {
            $value = "auto";
        }
        $value = \strtolower($value);
        switch ($value) {
            case "1":
            case "true":
            case "on":
                $this->colors = true;
                break;
            case "0":
            case "false":
            case "off":
                $this->colors = false;
                break;
            default:
                $this->colors = hasColorSupport();
                break;
        }
    }
    /**
     *
     */
    private function ansifyLevel(string $level) : string
    {
        $level = \strtolower($level);
        switch ($level) {
            case LogLevel::EMERGENCY:
            case LogLevel::ALERT:
            case LogLevel::CRITICAL:
            case LogLevel::ERROR:
                return "\x1b[1;31m{$level}\x1b[0m";
            // bold + red
            case LogLevel::WARNING:
                return "\x1b[1;33m{$level}\x1b[0m";
            // bold + yellow
            case LogLevel::NOTICE:
                return "\x1b[1;32m{$level}\x1b[0m";
            // bold + green
            case LogLevel::INFO:
                return "\x1b[1;35m{$level}\x1b[0m";
            // bold + magenta
            case LogLevel::DEBUG:
                return "\x1b[1;36m{$level}\x1b[0m";
            // bold + cyan
            default:
                return "\x1b[1m{$level}\x1b[0m";
        }
    }
}<?php

use Amp\ByteStream\ResourceOutputStream;
use Amp\Log\ConsoleFormatter;
use Amp\Log\StreamHandler;
use Monolog\Logger;
require dirname(__DIR__) . '/vendor/autoload.php';
$handler = new StreamHandler(new ResourceOutputStream(\STDOUT));
$handler->setFormatter(new ConsoleFormatter());
$logger = new Logger('hello-world');
$logger->pushHandler($handler);
$logger->debug("Hello, world!");
$logger->info("Hello, world!");
$logger->notice("Hello, world!");
$logger->error("Hello, world!");
$logger->alert("Hello, world!");{
    "name": "amphp/log",
    "homepage": "https://github.com/amphp/log",
    "description": "Non-blocking logging for PHP based on Amp and Monolog.",
    "keywords": [
        "log",
        "logging",
        "logger",
        "async",
        "non-blocking",
        "amp",
        "amphp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2",
        "amphp/byte-stream": "^1.3",
        "monolog/monolog": "^2 || ^1.23"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1.1",
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^8 || ^7"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Log\\": "src"
        },
        "files": [
            "src/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Log\\Test\\": "test"
        }
    },
    "scripts": {
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit",
        "code-style": "@php ./vendor/bin/php-cs-fixer fix"
    }
}
<?php

namespace Psr\Http\Message;

/**
 * Representation of an outgoing, client-side request.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - HTTP method
 * - URI
 * - Headers
 * - Message body
 *
 * During construction, implementations MUST attempt to set the Host header from
 * a provided URI if no Host header is provided.
 *
 * Requests are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface RequestInterface extends MessageInterface
{
    /**
    * Retrieves the message's request target.
    *
    * Retrieves the message's request-target either as it will appear (for
    clients), as it appeared at request (for servers), or as it was
    specified for the instance (see withRequestTarget()).
    *
    * In most cases, this will be the origin-form of the composed URI,
    unless a value was provided to the concrete implementation (see
    withRequestTarget() below).
    *
    * If no URI is available, and no request-target has been specifically
    provided, this method MUST return the string "/".
    *
    * @return string
    */
    public function getRequestTarget();
    /**
    * Return an instance with the specific request-target.
    *
    * If the request needs a non-origin-form request-target â€” e.g., for
    specifying an absolute-form, authority-form, or asterisk-form â€”
    this method may be used to create an instance with the specified
    request-target, verbatim.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    changed request target.
    *
    * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
    request-target forms allowed in request messages)
    * @param mixed $requestTarget
    * @return static
    */
    public function withRequestTarget($requestTarget);
    /**
     * Retrieves the HTTP method of the request.
     *
     * @return string Returns the request method.
     */
    public function getMethod();
    /**
    * Return an instance with the provided HTTP method.
    *
    * While HTTP method names are typically all uppercase characters, HTTP
    method names are case-sensitive and thus implementations SHOULD NOT
    modify the given string.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    changed request method.
    *
    * @param string $method Case-sensitive method.
    * @return static
    * @throws \InvalidArgumentException for invalid HTTP methods.
    */
    public function withMethod($method);
    /**
    * Retrieves the URI instance.
    *
    * This method MUST return a UriInterface instance.
    *
    * @link http://tools.ietf.org/html/rfc3986#section-4.3
    * @return UriInterface Returns a UriInterface instance
    representing the URI of the request.
    */
    public function getUri();
    /**
    * Returns an instance with the provided URI.
    *
    * This method MUST update the Host header of the returned request by
    default if the URI contains a host component. If the URI does not
    contain a host component, any pre-existing Host header MUST be carried
    over to the returned request.
    *
    * You can opt-in to preserving the original state of the Host header by
    setting `$preserveHost` to `true`. When `$preserveHost` is set to
    `true`, this method interacts with the Host header in the following ways:
    *
    * - If the Host header is missing or empty, and the new URI contains
    a host component, this method MUST update the Host header in the returned
    request.
    - If the Host header is missing or empty, and the new URI does not contain a
    host component, this method MUST NOT update the Host header in the returned
    request.
    - If a Host header is present and non-empty, this method MUST NOT update
    the Host header in the returned request.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    new UriInterface instance.
    *
    * @link http://tools.ietf.org/html/rfc3986#section-4.3
    * @param UriInterface $uri New request URI to use.
    * @param bool $preserveHost Preserve the original state of the Host header.
    * @return static
    */
    public function withUri(UriInterface $uri, $preserveHost = false);
}<?php

namespace Psr\Http\Message;

/**
 * Value object representing a file uploaded through an HTTP request.
 *
 * Instances of this interface are considered immutable; all methods that
 * might change state MUST be implemented such that they retain the internal
 * state of the current instance and return an instance that contains the
 * changed state.
 */
interface UploadedFileInterface
{
    /**
    * Retrieve a stream representing the uploaded file.
    *
    * This method MUST return a StreamInterface instance, representing the
    uploaded file. The purpose of this method is to allow utilizing native PHP
    stream functionality to manipulate the file upload, such as
    stream_copy_to_stream() (though the result will need to be decorated in a
    native PHP stream wrapper to work with such functions).
    *
    * If the moveTo() method has been called previously, this method MUST raise
    an exception.
    *
    * @return StreamInterface Stream representation of the uploaded file.
    * @throws \RuntimeException in cases when no stream is available or can be
    created.
    */
    public function getStream();
    /**
    * Move the uploaded file to a new location.
    *
    * Use this method as an alternative to move_uploaded_file(). This method is
    guaranteed to work in both SAPI and non-SAPI environments.
    Implementations must determine which environment they are in, and use the
    appropriate method (move_uploaded_file(), rename(), or a stream
    operation) to perform the operation.
    *
    * $targetPath may be an absolute path, or a relative path. If it is a
    relative path, resolution should be the same as used by PHP's rename()
    function.
    *
    * The original file or stream MUST be removed on completion.
    *
    * If this method is called more than once, any subsequent calls MUST raise
    an exception.
    *
    * When used in an SAPI environment where $_FILES is populated, when writing
    files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be
    used to ensure permissions and upload status are verified correctly.
    *
    * If you wish to move to a stream, use getStream(), as SAPI operations
    cannot guarantee writing to stream destinations.
    *
    * @see http://php.net/is_uploaded_file
    * @see http://php.net/move_uploaded_file
    * @param string $targetPath Path to which to move the uploaded file.
    * @throws \InvalidArgumentException if the $targetPath specified is invalid.
    * @throws \RuntimeException on any error during the move operation, or on
    the second or subsequent call to the method.
    */
    public function moveTo($targetPath);
    /**
    * Retrieve the file size.
    *
    * Implementations SHOULD return the value stored in the "size" key of
    the file in the $_FILES array if available, as PHP calculates this based
    on the actual size transmitted.
    *
    * @return (int | null) The file size in bytes or null if unknown.
    */
    public function getSize();
    /**
    * Retrieve the error associated with the uploaded file.
    *
    * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.
    *
    * If the file was uploaded successfully, this method MUST return
    UPLOAD_ERR_OK.
    *
    * Implementations SHOULD return the value stored in the "error" key of
    the file in the $_FILES array.
    *
    * @see http://php.net/manual/en/features.file-upload.errors.php
    * @return int One of PHP's UPLOAD_ERR_XXX constants.
    */
    public function getError();
    /**
    * Retrieve the filename sent by the client.
    *
    * Do not trust the value returned by this method. A client could send
    a malicious filename with the intention to corrupt or hack your
    application.
    *
    * Implementations SHOULD return the value stored in the "name" key of
    the file in the $_FILES array.
    *
    * @return (string | null) The filename sent by the client or null if none
    was provided.
    */
    public function getClientFilename();
    /**
    * Retrieve the media type sent by the client.
    *
    * Do not trust the value returned by this method. A client could send
    a malicious media type with the intention to corrupt or hack your
    application.
    *
    * Implementations SHOULD return the value stored in the "type" key of
    the file in the $_FILES array.
    *
    * @return (string | null) The media type sent by the client or null if none
    was provided.
    */
    public function getClientMediaType();
}<?php

namespace Psr\Http\Message;

/**
 * Representation of an incoming, server-side HTTP request.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - HTTP method
 * - URI
 * - Headers
 * - Message body
 *
 * Additionally, it encapsulates all data as it has arrived to the
 * application from the CGI and/or PHP environment, including:
 *
 * - The values represented in $_SERVER.
 * - Any cookies provided (generally via $_COOKIE)
 * - Query string arguments (generally via $_GET, or as parsed via parse_str())
 * - Upload files, if any (as represented by $_FILES)
 * - Deserialized body parameters (generally from $_POST)
 *
 * $_SERVER values MUST be treated as immutable, as they represent application
 * state at the time of request; as such, no methods are provided to allow
 * modification of those values. The other values provide such methods, as they
 * can be restored from $_SERVER or the request body, and may need treatment
 * during the application (e.g., body parameters may be deserialized based on
 * content type).
 *
 * Additionally, this interface recognizes the utility of introspecting a
 * request to derive and match additional parameters (e.g., via URI path
 * matching, decrypting cookie values, deserializing non-form-encoded body
 * content, matching authorization headers to users, etc). These parameters
 * are stored in an "attributes" property.
 *
 * Requests are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ServerRequestInterface extends RequestInterface
{
    /**
    * Retrieve server parameters.
    *
    * Retrieves data related to the incoming request environment,
    typically derived from PHP's $_SERVER superglobal. The data IS NOT
    REQUIRED to originate from $_SERVER.
    *
    * @return array
    */
    public function getServerParams();
    /**
    * Retrieve cookies.
    *
    * Retrieves cookies sent by the client to the server.
    *
    * The data MUST be compatible with the structure of the $_COOKIE
    superglobal.
    *
    * @return array
    */
    public function getCookieParams();
    /**
    * Return an instance with the specified cookies.
    *
    * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
    be compatible with the structure of $_COOKIE. Typically, this data will
    be injected at instantiation.
    *
    * This method MUST NOT update the related Cookie header of the request
    instance, nor related values in the server params.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated cookie values.
    *
    * @param array $cookies Array of key/value pairs representing cookies.
    * @return static
    */
    public function withCookieParams(array $cookies);
    /**
    * Retrieve query string arguments.
    *
    * Retrieves the deserialized query string arguments, if any.
    *
    * Note: the query params might not be in sync with the URI or server
    params. If you need to ensure you are only getting the original
    values, you may need to parse the query string from `getUri()->getQuery()`
    or from the `QUERY_STRING` server param.
    *
    * @return array
    */
    public function getQueryParams();
    /**
    * Return an instance with the specified query string arguments.
    *
    * These values SHOULD remain immutable over the course of the incoming
    request. They MAY be injected during instantiation, such as from PHP's
    $_GET superglobal, or MAY be derived from some other value such as the
    URI. In cases where the arguments are parsed from the URI, the data
    MUST be compatible with what PHP's parse_str() would return for
    purposes of how duplicate query parameters are handled, and how nested
    sets are handled.
    *
    * Setting query string arguments MUST NOT change the URI stored by the
    request, nor the values in the server params.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated query string arguments.
    *
    * @param array $query Array of query string arguments, typically from
    $_GET.
    * @return static
    */
    public function withQueryParams(array $query);
    /**
    * Retrieve normalized file upload data.
    *
    * This method returns upload metadata in a normalized tree, with each leaf
    an instance of Psr\Http\Message\UploadedFileInterface.
    *
    * These values MAY be prepared from $_FILES or the message body during
    instantiation, or MAY be injected via withUploadedFiles().
    *
    * @return array An array tree of UploadedFileInterface instances; an empty
    array MUST be returned if no data is present.
    */
    public function getUploadedFiles();
    /**
    * Create a new instance with the specified uploaded files.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated body parameters.
    *
    * @param array $uploadedFiles An array tree of UploadedFileInterface instances.
    * @return static
    * @throws \InvalidArgumentException if an invalid structure is provided.
    */
    public function withUploadedFiles(array $uploadedFiles);
    /**
    * Retrieve any parameters provided in the request body.
    *
    * If the request Content-Type is either application/x-www-form-urlencoded
    or multipart/form-data, and the request method is POST, this method MUST
    return the contents of $_POST.
    *
    * Otherwise, this method may return any results of deserializing
    the request body content; as parsing returns structured content, the
    potential types MUST be arrays or objects only. A null value indicates
    the absence of body content.
    *
    * @return (null | array | object) The deserialized body parameters, if any.
    These will typically be an array or object.
    */
    public function getParsedBody();
    /**
    * Return an instance with the specified body parameters.
    *
    * These MAY be injected during instantiation.
    *
    * If the request Content-Type is either application/x-www-form-urlencoded
    or multipart/form-data, and the request method is POST, use this method
    ONLY to inject the contents of $_POST.
    *
    * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
    deserializing the request body content. Deserialization/parsing returns
    structured data, and, as such, this method ONLY accepts arrays or objects,
    or a null value if nothing was available to parse.
    *
    * As an example, if content negotiation determines that the request data
    is a JSON payload, this method could be used to create a request
    instance with the deserialized parameters.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated body parameters.
    *
    * @param (null | array | object) $data The deserialized body data. This will
    typically be in an array or object.
    * @return static
    * @throws \InvalidArgumentException if an unsupported argument type is
    provided.
    */
    public function withParsedBody($data);
    /**
    * Retrieve attributes derived from the request.
    *
    * The request "attributes" may be used to allow injection of any
    parameters derived from the request: e.g., the results of path
    match operations; the results of decrypting cookies; the results of
    deserializing non-form-encoded message bodies; etc. Attributes
    will be application and request specific, and CAN be mutable.
    *
    * @return array Attributes derived from the request.
    */
    public function getAttributes();
    /**
    * Retrieve a single derived request attribute.
    *
    * Retrieves a single derived request attribute as described in
    getAttributes(). If the attribute has not been previously set, returns
    the default value as provided.
    *
    * This method obviates the need for a hasAttribute() method, as it allows
    specifying a default value to return if the attribute is not found.
    *
    * @see getAttributes()
    * @param string $name The attribute name.
    * @param mixed $default Default value to return if the attribute does not exist.
    * @return mixed
    */
    public function getAttribute($name, $default = null);
    /**
    * Return an instance with the specified derived request attribute.
    *
    * This method allows setting a single derived request attribute as
    described in getAttributes().
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated attribute.
    *
    * @see getAttributes()
    * @param string $name The attribute name.
    * @param mixed $value The value of the attribute.
    * @return static
    */
    public function withAttribute($name, $value);
    /**
    * Return an instance that removes the specified derived request attribute.
    *
    * This method allows removing a single derived request attribute as
    described in getAttributes().
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that removes
    the attribute.
    *
    * @see getAttributes()
    * @param string $name The attribute name.
    * @return static
    */
    public function withoutAttribute($name);
}<?php

namespace Psr\Http\Message;

/**
 * Value object representing a URI.
 *
 * This interface is meant to represent URIs according to RFC 3986 and to
 * provide methods for most common operations. Additional functionality for
 * working with URIs can be provided on top of the interface or externally.
 * Its primary use is for HTTP requests, but may also be used in other
 * contexts.
 *
 * Instances of this interface are considered immutable; all methods that
 * might change state MUST be implemented such that they retain the internal
 * state of the current instance and return an instance that contains the
 * changed state.
 *
 * Typically the Host header will be also be present in the request message.
 * For server-side requests, the scheme will typically be discoverable in the
 * server parameters.
 *
 * @link http://tools.ietf.org/html/rfc3986 (the URI specification)
 */
interface UriInterface
{
    /**
    * Retrieve the scheme component of the URI.
    *
    * If no scheme is present, this method MUST return an empty string.
    *
    * The value returned MUST be normalized to lowercase, per RFC 3986
    Section 3.1.
    *
    * The trailing ":" character is not part of the scheme and MUST NOT be
    added.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.1
    * @return string The URI scheme.
    */
    public function getScheme();
    /**
    * Retrieve the authority component of the URI.
    *
    * If no authority information is present, this method MUST return an empty
    string.
    *
    * The authority syntax of the URI is:
    *
    * <pre>
    [user-info@]host[:port]
    </pre>
    *
    * If the port component is not set or is the standard port for the current
    scheme, it SHOULD NOT be included.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.2
    * @return string The URI authority, in "[user-info@]host[:port]" format.
    */
    public function getAuthority();
    /**
    * Retrieve the user information component of the URI.
    *
    * If no user information is present, this method MUST return an empty
    string.
    *
    * If a user is present in the URI, this will return that value;
    additionally, if the password is also present, it will be appended to the
    user value, with a colon (":") separating the values.
    *
    * The trailing "@" character is not part of the user information and MUST
    NOT be added.
    *
    * @return string The URI user information, in "username[:password]" format.
    */
    public function getUserInfo();
    /**
    * Retrieve the host component of the URI.
    *
    * If no host is present, this method MUST return an empty string.
    *
    * The value returned MUST be normalized to lowercase, per RFC 3986
    Section 3.2.2.
    *
    * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
    * @return string The URI host.
    */
    public function getHost();
    /**
    * Retrieve the port component of the URI.
    *
    * If a port is present, and it is non-standard for the current scheme,
    this method MUST return it as an integer. If the port is the standard port
    used with the current scheme, this method SHOULD return null.
    *
    * If no port is present, and no scheme is present, this method MUST return
    a null value.
    *
    * If no port is present, but a scheme is present, this method MAY return
    the standard port for that scheme, but SHOULD return null.
    *
    * @return (null | int) The URI port.
    */
    public function getPort();
    /**
    * Retrieve the path component of the URI.
    *
    * The path can either be empty or absolute (starting with a slash) or
    rootless (not starting with a slash). Implementations MUST support all
    three syntaxes.
    *
    * Normally, the empty path "" and absolute path "/" are considered equal as
    defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
    do this normalization because in contexts with a trimmed base path, e.g.
    the front controller, this difference becomes significant. It's the task
    of the user to handle both "" and "/".
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.3.
    *
    * As an example, if the value should include a slash ("/") not intended as
    delimiter between path segments, that value MUST be passed in encoded
    form (e.g., "%2F") to the instance.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.3
    * @return string The URI path.
    */
    public function getPath();
    /**
    * Retrieve the query string of the URI.
    *
    * If no query string is present, this method MUST return an empty string.
    *
    * The leading "?" character is not part of the query and MUST NOT be
    added.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.4.
    *
    * As an example, if a value in a key/value pair of the query string should
    include an ampersand ("&") not intended as a delimiter between values,
    that value MUST be passed in encoded form (e.g., "%26") to the instance.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.4
    * @return string The URI query string.
    */
    public function getQuery();
    /**
    * Retrieve the fragment component of the URI.
    *
    * If no fragment is present, this method MUST return an empty string.
    *
    * The leading "#" character is not part of the fragment and MUST NOT be
    added.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.5.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.5
    * @return string The URI fragment.
    */
    public function getFragment();
    /**
    * Return an instance with the specified scheme.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified scheme.
    *
    * Implementations MUST support the schemes "http" and "https" case
    insensitively, and MAY accommodate other schemes if required.
    *
    * An empty scheme is equivalent to removing the scheme.
    *
    * @param string $scheme The scheme to use with the new instance.
    * @return static A new instance with the specified scheme.
    * @throws \InvalidArgumentException for invalid or unsupported schemes.
    */
    public function withScheme($scheme);
    /**
    * Return an instance with the specified user information.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified user information.
    *
    * Password is optional, but the user information MUST include the
    user; an empty string for the user is equivalent to removing user
    information.
    *
    * @param string $user The user name to use for authority.
    * @param (null | string) $password The password associated with $user.
    * @return static A new instance with the specified user information.
    */
    public function withUserInfo($user, $password = null);
    /**
    * Return an instance with the specified host.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified host.
    *
    * An empty host value is equivalent to removing the host.
    *
    * @param string $host The hostname to use with the new instance.
    * @return static A new instance with the specified host.
    * @throws \InvalidArgumentException for invalid hostnames.
    */
    public function withHost($host);
    /**
    * Return an instance with the specified port.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified port.
    *
    * Implementations MUST raise an exception for ports outside the
    established TCP and UDP port ranges.
    *
    * A null value provided for the port is equivalent to removing the port
    information.
    *
    * @param (null | int) $port The port to use with the new instance; a null value
    removes the port information.
    * @return static A new instance with the specified port.
    * @throws \InvalidArgumentException for invalid ports.
    */
    public function withPort($port);
    /**
    * Return an instance with the specified path.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified path.
    *
    * The path can either be empty or absolute (starting with a slash) or
    rootless (not starting with a slash). Implementations MUST support all
    three syntaxes.
    *
    * If the path is intended to be domain-relative rather than path relative then
    it must begin with a slash ("/"). Paths not starting with a slash ("/")
    are assumed to be relative to some base path known to the application or
    consumer.
    *
    * Users can provide both encoded and decoded path characters.
    Implementations ensure the correct encoding as outlined in getPath().
    *
    * @param string $path The path to use with the new instance.
    * @return static A new instance with the specified path.
    * @throws \InvalidArgumentException for invalid paths.
    */
    public function withPath($path);
    /**
    * Return an instance with the specified query string.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified query string.
    *
    * Users can provide both encoded and decoded query characters.
    Implementations ensure the correct encoding as outlined in getQuery().
    *
    * An empty query string value is equivalent to removing the query string.
    *
    * @param string $query The query string to use with the new instance.
    * @return static A new instance with the specified query string.
    * @throws \InvalidArgumentException for invalid query strings.
    */
    public function withQuery($query);
    /**
    * Return an instance with the specified URI fragment.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified URI fragment.
    *
    * Users can provide both encoded and decoded fragment characters.
    Implementations ensure the correct encoding as outlined in getFragment().
    *
    * An empty fragment value is equivalent to removing the fragment.
    *
    * @param string $fragment The fragment to use with the new instance.
    * @return static A new instance with the specified fragment.
    */
    public function withFragment($fragment);
    /**
    * Return the string representation as a URI reference.
    *
    * Depending on which components of the URI are present, the resulting
    string is either a full URI or relative reference according to RFC 3986,
    Section 4.1. The method concatenates the various components of the URI,
    using the appropriate delimiters:
    *
    * - If a scheme is present, it MUST be suffixed by ":".
    - If an authority is present, it MUST be prefixed by "//".
    - The path can be concatenated without delimiters. But there are two
    cases where the path has to be adjusted to make the URI reference
    valid as PHP does not allow to throw an exception in __toString():
    - If the path is rootless and an authority is present, the path MUST
    be prefixed by "/".
    - If the path is starting with more than one "/" and no authority is
    present, the starting slashes MUST be reduced to one.
    - If a query is present, it MUST be prefixed by "?".
    - If a fragment is present, it MUST be prefixed by "#".
    *
    * @see http://tools.ietf.org/html/rfc3986#section-4.1
    * @return string
    */
    public function __toString();
}<?php

namespace Psr\Http\Message;

/**
 * HTTP messages consist of requests from a client to a server and responses
 * from a server to a client. This interface defines the methods common to
 * each.
 *
 * Messages are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 *
 * @link http://www.ietf.org/rfc/rfc7230.txt
 * @link http://www.ietf.org/rfc/rfc7231.txt
 */
interface MessageInterface
{
    /**
     * Retrieves the HTTP protocol version as a string.
     *
     * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
     *
     * @return string HTTP protocol version.
     */
    public function getProtocolVersion();
    /**
    * Return an instance with the specified HTTP protocol version.
    *
    * The version string MUST contain only the HTTP version number (e.g.,
    "1.1", "1.0").
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    new protocol version.
    *
    * @param string $version HTTP protocol version
    * @return static
    */
    public function withProtocolVersion($version);
    /**
    * Retrieves all message header values.
    *
    * The keys represent the header name as it will be sent over the wire, and
    each value is an array of strings associated with the header.
    *
    * // Represent the headers as a string
    foreach ($message->getHeaders() as $name => $values) {
    echo $name . ": " . implode(", ", $values);
    }
    *
    * // Emit headers iteratively:
    foreach ($message->getHeaders() as $name => $values) {
    foreach ($values as $value) {
    header(sprintf('%s: %s', $name, $value), false);
    }
    }
    *
    * While header names are not case-sensitive, getHeaders() will preserve the
    exact case in which headers were originally specified.
    *
    * @return string[][] Returns an associative array of the message's headers. Each
    key MUST be a header name, and each value MUST be an array of strings
    for that header.
    */
    public function getHeaders();
    /**
    * Checks if a header exists by the given case-insensitive name.
    *
    * @param string $name Case-insensitive header field name.
    * @return bool Returns true if any header names match the given header
    name using a case-insensitive string comparison. Returns false if
    no matching header name is found in the message.
    */
    public function hasHeader($name);
    /**
    * Retrieves a message header value by the given case-insensitive name.
    *
    * This method returns an array of all the header values of the given
    case-insensitive header name.
    *
    * If the header does not appear in the message, this method MUST return an
    empty array.
    *
    * @param string $name Case-insensitive header field name.
    * @return string[] An array of string values as provided for the given
    header. If the header does not appear in the message, this method MUST
    return an empty array.
    */
    public function getHeader($name);
    /**
    * Retrieves a comma-separated string of the values for a single header.
    *
    * This method returns all of the header values of the given
    case-insensitive header name as a string concatenated together using
    a comma.
    *
    * NOTE: Not all header values may be appropriately represented using
    comma concatenation. For such headers, use getHeader() instead
    and supply your own delimiter when concatenating.
    *
    * If the header does not appear in the message, this method MUST return
    an empty string.
    *
    * @param string $name Case-insensitive header field name.
    * @return string A string of values as provided for the given header
    concatenated together using a comma. If the header does not appear in
    the message, this method MUST return an empty string.
    */
    public function getHeaderLine($name);
    /**
    * Return an instance with the provided value replacing the specified header.
    *
    * While header names are case-insensitive, the casing of the header will
    be preserved by this function, and returned from getHeaders().
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    new and/or updated header and value.
    *
    * @param string $name Case-insensitive header field name.
    * @param (string | string[]) $value Header value(s).
    * @return static
    * @throws \InvalidArgumentException for invalid header names or values.
    */
    public function withHeader($name, $value);
    /**
    * Return an instance with the specified header appended with the given value.
    *
    * Existing values for the specified header will be maintained. The new
    value(s) will be appended to the existing list. If the header did not
    exist previously, it will be added.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    new header and/or value.
    *
    * @param string $name Case-insensitive header field name to add.
    * @param (string | string[]) $value Header value(s).
    * @return static
    * @throws \InvalidArgumentException for invalid header names or values.
    */
    public function withAddedHeader($name, $value);
    /**
    * Return an instance without the specified header.
    *
    * Header resolution MUST be done without case-sensitivity.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that removes
    the named header.
    *
    * @param string $name Case-insensitive header field name to remove.
    * @return static
    */
    public function withoutHeader($name);
    /**
     * Gets the body of the message.
     *
     * @return StreamInterface Returns the body as a stream.
     */
    public function getBody();
    /**
    * Return an instance with the specified message body.
    *
    * The body MUST be a StreamInterface object.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return a new instance that has the
    new body stream.
    *
    * @param StreamInterface $body Body.
    * @return static
    * @throws \InvalidArgumentException When the body is not valid.
    */
    public function withBody(StreamInterface $body);
}<?php

namespace Psr\Http\Message;

/**
 * Representation of an outgoing, server-side response.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - Status code and reason phrase
 * - Headers
 * - Message body
 *
 * Responses are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ResponseInterface extends MessageInterface
{
    /**
    * Gets the response status code.
    *
    * The status code is a 3-digit integer result code of the server's attempt
    to understand and satisfy the request.
    *
    * @return int Status code.
    */
    public function getStatusCode();
    /**
    * Return an instance with the specified status code and, optionally, reason phrase.
    *
    * If no reason phrase is specified, implementations MAY choose to default
    to the RFC 7231 or IANA recommended reason phrase for the response's
    status code.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated status and reason phrase.
    *
    * @link http://tools.ietf.org/html/rfc7231#section-6
    * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
    * @param int $code The 3-digit integer result code to set.
    * @param string $reasonPhrase The reason phrase to use with the
    provided status code; if none is provided, implementations MAY
    use the defaults as suggested in the HTTP specification.
    * @return static
    * @throws \InvalidArgumentException For invalid status code arguments.
    */
    public function withStatus($code, $reasonPhrase = '');
    /**
    * Gets the response reason phrase associated with the status code.
    *
    * Because a reason phrase is not a required element in a response
    status line, the reason phrase value MAY be null. Implementations MAY
    choose to return the default RFC 7231 recommended reason phrase (or those
    listed in the IANA HTTP Status Code Registry) for the response's
    status code.
    *
    * @link http://tools.ietf.org/html/rfc7231#section-6
    * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
    * @return string Reason phrase; must return an empty string if none present.
    */
    public function getReasonPhrase();
}<?php

namespace Psr\Http\Message;

/**
 * Describes a data stream.
 *
 * Typically, an instance will wrap a PHP stream; this interface provides
 * a wrapper around the most common operations, including serialization of
 * the entire stream to a string.
 */
interface StreamInterface
{
    /**
    * Reads all data from the stream into a string, from the beginning to end.
    *
    * This method MUST attempt to seek to the beginning of the stream before
    reading data and read the stream until the end is reached.
    *
    * Warning: This could attempt to load a large amount of data into memory.
    *
    * This method MUST NOT raise an exception in order to conform with PHP's
    string casting operations.
    *
    * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
    * @return string
    */
    public function __toString();
    /**
     * Closes the stream and any underlying resources.
     *
     * @return void
     */
    public function close();
    /**
     * Separates any underlying resources from the stream.
     *
     * After the stream has been detached, the stream is in an unusable state.
     *
     * @return (resource | null) Underlying PHP stream, if any
     */
    public function detach();
    /**
     * Get the size of the stream if known.
     *
     * @return (int | null) Returns the size in bytes if known, or null if unknown.
     */
    public function getSize();
    /**
     * Returns the current position of the file read/write pointer
     *
     * @return int Position of the file pointer
     * @throws \RuntimeException on error.
     */
    public function tell();
    /**
     * Returns true if the stream is at the end of the stream.
     *
     * @return bool
     */
    public function eof();
    /**
     * Returns whether or not the stream is seekable.
     *
     * @return bool
     */
    public function isSeekable();
    /**
    * Seek to a position in the stream.
    *
    * @link http://www.php.net/manual/en/function.fseek.php
    * @param int $offset Stream offset
    * @param int $whence Specifies how the cursor position will be calculated
    based on the seek offset. Valid values are identical to the built-in
    PHP $whence values for `fseek()`.  SEEK_SET: Set position equal to
    offset bytes SEEK_CUR: Set position to current location plus offset
    SEEK_END: Set position to end-of-stream plus offset.
    * @throws \RuntimeException on failure.
    */
    public function seek($offset, $whence = SEEK_SET);
    /**
    * Seek to the beginning of the stream.
    *
    * If the stream is not seekable, this method will raise an exception;
    otherwise, it will perform a seek(0).
    *
    * @see seek()
    * @link http://www.php.net/manual/en/function.fseek.php
    * @throws \RuntimeException on failure.
    */
    public function rewind();
    /**
     * Returns whether or not the stream is writable.
     *
     * @return bool
     */
    public function isWritable();
    /**
     * Write data to the stream.
     *
     * @param string $string The string that is to be written.
     * @return int Returns the number of bytes written to the stream.
     * @throws \RuntimeException on failure.
     */
    public function write($string);
    /**
     * Returns whether or not the stream is readable.
     *
     * @return bool
     */
    public function isReadable();
    /**
    * Read data from the stream.
    *
    * @param int $length Read up to $length bytes from the object and return
    them. Fewer than $length bytes may be returned if underlying stream
    call returns fewer bytes.
    * @return string Returns the data read from the stream, or an empty string
    if no bytes are available.
    * @throws \RuntimeException if an error occurs.
    */
    public function read($length);
    /**
    * Returns the remaining contents in a string
    *
    * @return string
    * @throws \RuntimeException if unable to read or an error occurs while
    reading.
    */
    public function getContents();
    /**
    * Get stream metadata as an associative array or retrieve a specific key.
    *
    * The keys returned are identical to the keys returned from PHP's
    stream_get_meta_data() function.
    *
    * @link http://php.net/manual/en/function.stream-get-meta-data.php
    * @param string $key Specific metadata to retrieve.
    * @return (array | mixed | null) Returns an associative array if no key is
    provided. Returns a specific key value if a key is provided and the
    value is found, or null if the key is not found.
    */
    public function getMetadata($key = null);
}{
    "name": "psr/http-message",
    "description": "Common interface for HTTP messages",
    "keywords": ["psr", "psr-7", "http", "http-message", "request", "response"],
    "homepage": "https://github.com/php-fig/http-message",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "http://www.php-fig.org/"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-4": {
            "Psr\\Http\\Message\\": "src/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}
<?php

namespace Psr\Http\Message;

interface UriFactoryInterface
{
    /**
     * Create a new URI.
     *
     * @param string $uri
     *
     * @return UriInterface
     *
     * @throws \InvalidArgumentException If the given URI cannot be parsed.
     */
    public function createUri(string $uri = '') : UriInterface;
}<?php

namespace Psr\Http\Message;

interface RequestFactoryInterface
{
    /**
    * Create a new request.
    *
    * @param string $method The HTTP method associated with the request.
    * @param (UriInterface | string) $uri The URI associated with the request. If
    the value is a string, the factory MUST create a UriInterface
    instance based on it.
    *
    * @return RequestInterface
    */
    public function createRequest(string $method, $uri) : RequestInterface;
}<?php

namespace Psr\Http\Message;

interface ResponseFactoryInterface
{
    /**
    * Create a new response.
    *
    * @param int $code HTTP status code; defaults to 200
    * @param string $reasonPhrase Reason phrase to associate with status code
    in generated response; if none is provided implementations MAY use
    the defaults as suggested in the HTTP specification.
    *
    * @return ResponseInterface
    */
    public function createResponse(int $code = 200, string $reasonPhrase = '') : ResponseInterface;
}<?php

namespace Psr\Http\Message;

interface ServerRequestFactoryInterface
{
    /**
    * Create a new server request.
    *
    * Note that server-params are taken precisely as given - no parsing/processing
    of the given values is performed, and, in particular, no attempt is made to
    determine the HTTP method or URI, which must be provided explicitly.
    *
    * @param string $method The HTTP method associated with the request.
    * @param (UriInterface | string) $uri The URI associated with the request. If
    the value is a string, the factory MUST create a UriInterface
    instance based on it.
    * @param array $serverParams Array of SAPI parameters with which to seed
    the generated request instance.
    *
    * @return ServerRequestInterface
    */
    public function createServerRequest(string $method, $uri, array $serverParams = []) : ServerRequestInterface;
}<?php

namespace Psr\Http\Message;

interface StreamFactoryInterface
{
    /**
     * Create a new stream from a string.
     *
     * The stream SHOULD be created with a temporary resource.
     *
     * @param string $content String content with which to populate the stream.
     *
     * @return StreamInterface
     */
    public function createStream(string $content = '') : StreamInterface;
    /**
    * Create a stream from an existing file.
    *
    * The file MUST be opened using the given mode, which may be any mode
    supported by the `fopen` function.
    *
    * The `$filename` MAY be any string supported by `fopen()`.
    *
    * @param string $filename Filename or stream URI to use as basis of stream.
    * @param string $mode Mode with which to open the underlying filename/stream.
    *
    * @return StreamInterface
    * @throws \RuntimeException If the file cannot be opened.
    * @throws \InvalidArgumentException If the mode is invalid.
    */
    public function createStreamFromFile(string $filename, string $mode = 'r') : StreamInterface;
    /**
     * Create a new stream from an existing resource.
     *
     * The stream MUST be readable and may be writable.
     *
     * @param resource $resource PHP resource to use as basis of stream.
     *
     * @return StreamInterface
     */
    public function createStreamFromResource($resource) : StreamInterface;
}<?php

namespace Psr\Http\Message;

interface UploadedFileFactoryInterface
{
    /**
    * Create a new uploaded file.
    *
    * If a size is not provided it will be determined by checking the size of
    the file.
    *
    * @see http://php.net/manual/features.file-upload.post-method.php
    * @see http://php.net/manual/features.file-upload.errors.php
    *
    * @param StreamInterface $stream Underlying stream representing the
    uploaded file content.
    * @param int $size in bytes
    * @param int $error PHP file upload error
    * @param string $clientFilename Filename as provided by the client, if any.
    * @param string $clientMediaType Media type as provided by the client, if any.
    *
    * @return UploadedFileInterface
    *
    * @throws \InvalidArgumentException If the file resource is not readable.
    */
    public function createUploadedFile(StreamInterface $stream, int $size = null, int $error = \UPLOAD_ERR_OK, string $clientFilename = null, string $clientMediaType = null) : UploadedFileInterface;
}{
    "name": "psr/http-factory",
    "description": "Common interfaces for PSR-7 HTTP message factories",
    "keywords": [
        "psr",
        "psr-7",
        "psr-17",
        "http",
        "factory",
        "message",
        "request",
        "response"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "http://www.php-fig.org/"
        }
    ],
    "require": {
        "php": ">=7.0.0",
        "psr/http-message": "^1.0"
    },
    "autoload": {
        "psr-4": {
            "Psr\\Http\\Message\\": "src/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}
{
    "name": "psr/log",
    "description": "Common interface for logging libraries",
    "keywords": ["psr", "psr-3", "log"],
    "homepage": "https://github.com/php-fig/log",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https://www.php-fig.org/"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-4": {
            "Psr\\Log\\": "Psr/Log/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.1.x-dev"
        }
    }
}
<?php

namespace Psr\Log;

/**
 * This Logger can be used to avoid conditional log calls.
 *
 * Logging should always be optional, and if no logger is provided to your
 * library creating a NullLogger instance to have something to throw logs at
 * is a good way to avoid littering your code with `if ($this->logger) { }`
 * blocks.
 */
class NullLogger extends AbstractLogger
{
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = array())
    {
        // noop
    }
}<?php

namespace Psr\Log;

/**
 * Basic Implementation of LoggerAwareInterface.
 */
trait LoggerAwareTrait
{
    /**
     * The logger instance.
     *
     * @var LoggerInterface|null
     */
    protected $logger;
    /**
     * Sets a logger.
     *
     * @param LoggerInterface $logger
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}<?php

namespace Psr\Log\Test;

/**
 * This class is internal and does not follow the BC promise.
 *
 * Do NOT use this class in any way.
 *
 * @internal
 */
class DummyTest
{
    /**
     *
     */
    public function __toString()
    {
        return 'DummyTest';
    }
}<?php

namespace Psr\Log\Test;

use Psr\Log\AbstractLogger;
/**
 * Used for testing purposes.
 *
 * It records all records and gives you access to them for verification.
 *
 * @method bool hasEmergency($record)
 * @method bool hasAlert($record)
 * @method bool hasCritical($record)
 * @method bool hasError($record)
 * @method bool hasWarning($record)
 * @method bool hasNotice($record)
 * @method bool hasInfo($record)
 * @method bool hasDebug($record)
 *
 * @method bool hasEmergencyRecords()
 * @method bool hasAlertRecords()
 * @method bool hasCriticalRecords()
 * @method bool hasErrorRecords()
 * @method bool hasWarningRecords()
 * @method bool hasNoticeRecords()
 * @method bool hasInfoRecords()
 * @method bool hasDebugRecords()
 *
 * @method bool hasEmergencyThatContains($message)
 * @method bool hasAlertThatContains($message)
 * @method bool hasCriticalThatContains($message)
 * @method bool hasErrorThatContains($message)
 * @method bool hasWarningThatContains($message)
 * @method bool hasNoticeThatContains($message)
 * @method bool hasInfoThatContains($message)
 * @method bool hasDebugThatContains($message)
 *
 * @method bool hasEmergencyThatMatches($message)
 * @method bool hasAlertThatMatches($message)
 * @method bool hasCriticalThatMatches($message)
 * @method bool hasErrorThatMatches($message)
 * @method bool hasWarningThatMatches($message)
 * @method bool hasNoticeThatMatches($message)
 * @method bool hasInfoThatMatches($message)
 * @method bool hasDebugThatMatches($message)
 *
 * @method bool hasEmergencyThatPasses($message)
 * @method bool hasAlertThatPasses($message)
 * @method bool hasCriticalThatPasses($message)
 * @method bool hasErrorThatPasses($message)
 * @method bool hasWarningThatPasses($message)
 * @method bool hasNoticeThatPasses($message)
 * @method bool hasInfoThatPasses($message)
 * @method bool hasDebugThatPasses($message)
 */
class TestLogger extends AbstractLogger
{
    /**
     * @var array
     */
    public $records = [];
    public $recordsByLevel = [];
    /**
     * @inheritdoc
     */
    public function log($level, $message, array $context = [])
    {
        $record = ['level' => $level, 'message' => $message, 'context' => $context];
        $this->recordsByLevel[$record['level']][] = $record;
        $this->records[] = $record;
    }
    /**
     *
     */
    public function hasRecords($level)
    {
        return isset($this->recordsByLevel[$level]);
    }
    /**
     *
     */
    public function hasRecord($record, $level)
    {
        if (is_string($record)) {
            $record = ['message' => $record];
        }
        return $this->hasRecordThatPasses(function ($rec) use($record) {
            if ($rec['message'] !== $record['message']) {
                return false;
            }
            if (isset($record['context']) && $rec['context'] !== $record['context']) {
                return false;
            }
            return true;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatContains($message, $level)
    {
        return $this->hasRecordThatPasses(function ($rec) use($message) {
            return strpos($rec['message'], $message) !== false;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatMatches($regex, $level)
    {
        return $this->hasRecordThatPasses(function ($rec) use($regex) {
            return preg_match($regex, $rec['message']) > 0;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatPasses(callable $predicate, $level)
    {
        if (!isset($this->recordsByLevel[$level])) {
            return false;
        }
        foreach ($this->recordsByLevel[$level] as $i => $rec) {
            if (call_user_func($predicate, $rec, $i)) {
                return true;
            }
        }
        return false;
    }
    /**
     *
     */
    public function __call($method, $args)
    {
        if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
            $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
            $level = strtolower($matches[2]);
            if (method_exists($this, $genericMethod)) {
                $args[] = $level;
                return call_user_func_array([$this, $genericMethod], $args);
            }
        }
        throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
    }
    /**
     *
     */
    public function reset()
    {
        $this->records = [];
        $this->recordsByLevel = [];
    }
}<?php

namespace Psr\Log\Test;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use PHPUnit\Framework\TestCase;
/**
 * Provides a base test class for ensuring compliance with the LoggerInterface.
 *
 * Implementors can extend the class and implement abstract methods to run this
 * as part of their test suite.
 */
abstract class LoggerInterfaceTest extends TestCase
{
    /**
     * @return LoggerInterface
     */
    public abstract function getLogger();
    /**
     * This must return the log messages in order.
     *
     * The simple formatting of the messages is: "<LOG LEVEL> <MESSAGE>".
     *
     * Example ->error('Foo') would yield "error Foo".
     *
     * @return string[]
     */
    public abstract function getLogs();
    /**
     *
     */
    public function testImplements()
    {
        $this->assertInstanceOf('Psr\\Log\\LoggerInterface', $this->getLogger());
    }
    /**
     * @dataProvider provideLevelsAndMessages
     */
    public function testLogsAtAllLevels($level, $message)
    {
        $logger = $this->getLogger();
        $logger->{$level}($message, array('user' => 'Bob'));
        $logger->log($level, $message, array('user' => 'Bob'));
        $expected = array($level . ' message of level ' . $level . ' with context: Bob', $level . ' message of level ' . $level . ' with context: Bob');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function provideLevelsAndMessages()
    {
        return array(LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'));
    }
    /**
     * @expectedException \Psr\Log\InvalidArgumentException
     */
    public function testThrowsOnInvalidLevel()
    {
        $logger = $this->getLogger();
        $logger->log('invalid level', 'Foo');
    }
    /**
     *
     */
    public function testContextReplacement()
    {
        $logger = $this->getLogger();
        $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
        $expected = array('info {Message {nothing} Bob Bar a}');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testObjectCastToString()
    {
        if (method_exists($this, 'createPartialMock')) {
            $dummy = $this->createPartialMock('Psr\\Log\\Test\\DummyTest', array('__toString'));
        } else {
            $dummy = $this->getMock('Psr\\Log\\Test\\DummyTest', array('__toString'));
        }
        $dummy->expects($this->once())->method('__toString')->will($this->returnValue('DUMMY'));
        $this->getLogger()->warning($dummy);
        $expected = array('warning DUMMY');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testContextCanContainAnything()
    {
        $closed = fopen('php://memory', 'r');
        fclose($closed);
        $context = array('bool' => true, 'null' => null, 'string' => 'Foo', 'int' => 0, 'float' => 0.5, 'nested' => array('with object' => new DummyTest()), 'object' => new \DateTime(), 'resource' => fopen('php://memory', 'r'), 'closed' => $closed);
        $this->getLogger()->warning('Crazy context data', $context);
        $expected = array('warning Crazy context data');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testContextExceptionKeyCanBeExceptionOrOtherValues()
    {
        $logger = $this->getLogger();
        $logger->warning('Random message', array('exception' => 'oops'));
        $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
        $expected = array('warning Random message', 'critical Uncaught Exception!');
        $this->assertEquals($expected, $this->getLogs());
    }
}<?php

namespace Psr\Log;

/**
 * This is a simple Logger implementation that other Loggers can inherit from.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
abstract class AbstractLogger implements LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
}<?php

namespace Psr\Log;

/**
 * Describes a logger instance.
 *
 * The message MUST be a string or object implementing __toString().
 *
 * The message MAY contain placeholders in the form: {foo} where foo
 * will be replaced by the context data in key "foo".
 *
 * The context array can contain arbitrary data. The only assumption that
 * can be made by implementors is that if an Exception instance is given
 * to produce a stack trace, it MUST be in a key named "exception".
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * for the full interface specification.
 */
interface LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function emergency($message, array $context = array());
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function alert($message, array $context = array());
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function critical($message, array $context = array());
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function error($message, array $context = array());
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function warning($message, array $context = array());
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function notice($message, array $context = array());
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function info($message, array $context = array());
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function debug($message, array $context = array());
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = array());
}<?php

namespace Psr\Log;

/**
 * Describes log levels.
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT = 'alert';
    const CRITICAL = 'critical';
    const ERROR = 'error';
    const WARNING = 'warning';
    const NOTICE = 'notice';
    const INFO = 'info';
    const DEBUG = 'debug';
}<?php

namespace Psr\Log;

/**
 * This is a simple Logger trait that classes unable to extend AbstractLogger
 * (because they extend another class, etc) can include.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
trait LoggerTrait
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public abstract function log($level, $message, array $context = array());
}<?php

namespace Psr\Log;

class InvalidArgumentException extends \InvalidArgumentException
{
}<?php

namespace Psr\Log;

/**
 * Describes a logger-aware instance.
 */
interface LoggerAwareInterface
{
    /**
     * Sets a logger instance on the object.
     *
     * @param LoggerInterface $logger
     *
     * @return void
     */
    public function setLogger(LoggerInterface $logger);
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogmaticFormatter;
/**
 * @author Julien Breux <julien.breux@gmail.com>
 */
class LogmaticHandler extends SocketHandler
{
    /**
     * @var string
     */
    private $logToken;
    /**
     * @var string
     */
    private $hostname;
    /**
     * @var string
     */
    private $appname;
    /**
     * @param string $token Log token supplied by Logmatic.
     * @param string $hostname Host name supplied by Logmatic.
     * @param string $appname Application name supplied by Logmatic.
     * @param bool $useSSL Whether or not SSL encryption should be used.
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, string $hostname = '', string $appname = '', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true)
    {
        if ($useSSL && !extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use SSL encrypted connection for LogmaticHandler');
        }
        $endpoint = $useSSL ? 'ssl://api.logmatic.io:10515' : 'api.logmatic.io:10514';
        $endpoint .= '/v1/';
        parent::__construct($endpoint, $level, $bubble);
        $this->logToken = $token;
        $this->hostname = $hostname;
        $this->appname = $appname;
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        return $this->logToken . ' ' . $record['formatted'];
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        $formatter = new LogmaticFormatter();
        if (!empty($this->hostname)) {
            $formatter->setHostname($this->hostname);
        }
        if (!empty($this->appname)) {
            $formatter->setAppname($this->appname);
        }
        return $formatter;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * No-op
 *
 * This handler handles anything, but does nothing, and does not stop bubbling to the rest of the stack.
 * This can be used for testing, or to disable a handler when overriding a configuration without
 * influencing the rest of the stack.
 *
 * @author Roel Harbers <roelharbers@gmail.com>
 */
class NoopHandler extends Handler
{
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return true;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        return false;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Channel\AMQPChannel;
use AMQPExchange;
/**
 * @phpstan-import-type Record from \Monolog\Logger
 */
class AmqpHandler extends AbstractProcessingHandler
{
    /**
     * @var AMQPExchange|AMQPChannel $exchange
     */
    protected $exchange;
    /**
     * @var string
     */
    protected $exchangeName;
    /**
     * @param (AMQPExchange | AMQPChannel) $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use
     * @param (string | null) $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only
     */
    public function __construct($exchange, ?string $exchangeName = null, $level = Logger::DEBUG, bool $bubble = true)
    {
        if ($exchange instanceof AMQPChannel) {
            $this->exchangeName = (string) $exchangeName;
        } elseif (!$exchange instanceof AMQPExchange) {
            throw new \InvalidArgumentException('PhpAmqpLib\\Channel\\AMQPChannel or AMQPExchange instance required');
        } elseif ($exchangeName) {
            @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED);
        }
        $this->exchange = $exchange;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $data = $record["formatted"];
        $routingKey = $this->getRoutingKey($record);
        if ($this->exchange instanceof AMQPExchange) {
            $this->exchange->publish($data, $routingKey, 0, ['delivery_mode' => 2, 'content_type' => 'application/json']);
        } else {
            $this->exchange->basic_publish($this->createAmqpMessage($data), $this->exchangeName, $routingKey);
        }
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if ($this->exchange instanceof AMQPExchange) {
            parent::handleBatch($records);
            return;
        }
        foreach ($records as $record) {
            if (!$this->isHandling($record)) {
                continue;
            }
            /** @var Record $record */
            $record = $this->processRecord($record);
            $data = $this->getFormatter()->format($record);
            $this->exchange->batch_basic_publish($this->createAmqpMessage($data), $this->exchangeName, $this->getRoutingKey($record));
        }
        $this->exchange->publish_batch();
    }
    /**
     * Gets the routing key for the AMQP exchange
     *
     * @phpstan-param Record $record
     */
    protected function getRoutingKey(array $record) : string
    {
        $routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']);
        return strtolower($routingKey);
    }
    /**
     *
     */
    private function createAmqpMessage(string $data) : AMQPMessage
    {
        return new AMQPMessage($data, ['delivery_mode' => 2, 'content_type' => 'application/json']);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Aws\Sdk;
use Aws\DynamoDb\DynamoDbClient;
use Monolog\Formatter\FormatterInterface;
use Aws\DynamoDb\Marshaler;
use Monolog\Formatter\ScalarFormatter;
use Monolog\Logger;
/**
 * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/)
 *
 * @link https://github.com/aws/aws-sdk-php/
 * @author Andrew Lawson <adlawson@gmail.com>
 */
class DynamoDbHandler extends AbstractProcessingHandler
{
    public const DATE_FORMAT = 'Y-m-d\\TH:i:s.uO';
    /**
     * @var DynamoDbClient
     */
    protected $client;
    /**
     * @var string
     */
    protected $table;
    /**
     * @var int
     */
    protected $version;
    /**
     * @var Marshaler
     */
    protected $marshaler;
    /**
     *
     */
    public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true)
    {
        /** @phpstan-ignore-next-line */
        if (defined('Aws\\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) {
            $this->version = 3;
            $this->marshaler = new Marshaler();
        } else {
            $this->version = 2;
        }
        $this->client = $client;
        $this->table = $table;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $filtered = $this->filterEmptyFields($record['formatted']);
        if ($this->version === 3) {
            $formatted = $this->marshaler->marshalItem($filtered);
        } else {
            /** @phpstan-ignore-next-line */
            $formatted = $this->client->formatAttributes($filtered);
        }
        $this->client->putItem(['TableName' => $this->table, 'Item' => $formatted]);
    }
    /**
     * @param mixed[] $record
     * @return mixed[]
     */
    protected function filterEmptyFields(array $record) : array
    {
        return array_filter($record, function ($value) {
            return !empty($value) || false === $value || 0 === $value;
        });
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new ScalarFormatter(self::DATE_FORMAT);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter;
use Monolog\Logger;
/**
 * CouchDB handler
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class CouchDBHandler extends AbstractProcessingHandler
{
    /** @var mixed[] */
    private $options;
    /**
     * @param mixed[] $options
     */
    public function __construct(array $options = [], $level = Logger::DEBUG, bool $bubble = true)
    {
        $this->options = array_merge(['host' => 'localhost', 'port' => 5984, 'dbname' => 'logger', 'username' => null, 'password' => null], $options);
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $basicAuth = null;
        if ($this->options['username']) {
            $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']);
        }
        $url = 'http://' . $basicAuth . $this->options['host'] . ':' . $this->options['port'] . '/' . $this->options['dbname'];
        $context = stream_context_create(['http' => ['method' => 'POST', 'content' => $record['formatted'], 'ignore_errors' => true, 'max_redirects' => 0, 'header' => 'Content-type: application/json']]);
        if (false === @file_get_contents($url, false, $context)) {
            throw new \RuntimeException(sprintf('Could not connect to %s', $url));
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Throwable;
use RuntimeException;
use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\ElasticsearchFormatter;
use InvalidArgumentException;
use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException;
use Elasticsearch\Client;
/**
 * Elasticsearch handler
 *
 * @link https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
 *
 * Simple usage example:
 *
 *    $client = \Elasticsearch\ClientBuilder::create()
 *        ->setHosts($hosts)
 *        ->build();
 *
 *    $options = array(
 *        'index' => 'elastic_index_name',
 *        'type'  => 'elastic_doc_type',
 *    );
 *    $handler = new ElasticsearchHandler($client, $options);
 *    $log = new Logger('application');
 *    $log->pushHandler($handler);
 *
 * @author Avtandil Kikabidze <akalongman@gmail.com>
 */
class ElasticsearchHandler extends AbstractProcessingHandler
{
    /**
     * @var Client
     */
    protected $client;
    /**
     * @var mixed[] Handler config options
     */
    protected $options = [];
    /**
     * @param Client $client Elasticsearch Client object
     * @param mixed[] $options Handler configuration
     */
    public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->client = $client;
        $this->options = array_merge([
            'index' => 'monolog',
            // Elastic index name
            'type' => '_doc',
            // Elastic document type
            'ignore_error' => false,
        ], $options);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->bulkSend([$record['formatted']]);
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($formatter instanceof ElasticsearchFormatter) {
            return parent::setFormatter($formatter);
        }
        throw new InvalidArgumentException('ElasticsearchHandler is only compatible with ElasticsearchFormatter');
    }
    /**
     * Getter options
     *
     * @return mixed[]
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new ElasticsearchFormatter($this->options['index'], $this->options['type']);
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $documents = $this->getFormatter()->formatBatch($records);
        $this->bulkSend($documents);
    }
    /**
     * Use Elasticsearch bulk API to send list of documents
     *
     * @param array[] $records Records + _index/_type keys
     * @throws \RuntimeException
     */
    protected function bulkSend(array $records) : void
    {
        try {
            $params = ['body' => []];
            foreach ($records as $record) {
                $params['body'][] = ['index' => ['_index' => $record['_index'], '_type' => $record['_type']]];
                unset($record['_index'], $record['_type']);
                $params['body'][] = $record;
            }
            $responses = $this->client->bulk($params);
            if ($responses['errors'] === true) {
                throw $this->createExceptionFromResponses($responses);
            }
        } catch (Throwable $e) {
            if (!$this->options['ignore_error']) {
                throw new RuntimeException('Error sending messages to Elasticsearch', 0, $e);
            }
        }
    }
    /**
     * Creates elasticsearch exception from responses array
     *
     * Only the first error is converted into an exception.
     *
     * @param mixed[] $responses returned by $this->client->bulk()
     */
    protected function createExceptionFromResponses(array $responses) : ElasticsearchRuntimeException
    {
        foreach ($responses['items'] ?? [] as $item) {
            if (isset($item['index']['error'])) {
                return $this->createExceptionFromError($item['index']['error']);
            }
        }
        return new ElasticsearchRuntimeException('Elasticsearch failed to index one or more records.');
    }
    /**
     * Creates elasticsearch exception from error array
     *
     * @param mixed[] $error
     */
    protected function createExceptionFromError(array $error) : ElasticsearchRuntimeException
    {
        $previous = isset($error['caused_by']) ? $this->createExceptionFromError($error['caused_by']) : null;
        return new ElasticsearchRuntimeException($error['type'] . ': ' . $error['reason'], 0, $previous);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
use Psr\Log\LogLevel;
/**
 * Buffers all records until a certain level is reached
 *
 * The advantage of this approach is that you don't get any clutter in your log files.
 * Only requests which actually trigger an error (or whatever your actionLevel is) will be
 * in the logs, but they will contain all records, not only those above the level threshold.
 *
 * You can then have a passthruLevel as well which means that at the end of the request,
 * even if it did not get activated, it will still send through log records of e.g. at least a
 * warning level.
 *
 * You can find the various activation strategies in the
 * Monolog\Handler\FingersCrossed\ namespace.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * @var callable|HandlerInterface
     * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
     */
    protected $handler;
    /** @var ActivationStrategyInterface */
    protected $activationStrategy;
    /** @var bool */
    protected $buffering = true;
    /** @var int */
    protected $bufferSize;
    /** @var Record[] */
    protected $buffer = [];
    /** @var bool */
    protected $stopBuffering;
    /**
     * @var ?int
     * @phpstan-var ?Level
     */
    protected $passthruLevel;
    /** @var bool */
    protected $bubble;
    /**
     * @psalm-param (HandlerInterface | callable(?Record , HandlerInterface ): HandlerInterface) $handler
     *
     * @param (callable | HandlerInterface) $handler Handler or factory callable($record|null, $fingersCrossedHandler).
     * @param (int | string | ActivationStrategyInterface) $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated
     * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
     * @param (int | string) $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $passthruLevel
     * @phpstan-param (Level | LevelName | LogLevel::* | ActivationStrategyInterface) $activationStrategy
     */
    public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, $passthruLevel = null)
    {
        if (null === $activationStrategy) {
            $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING);
        }
        // convert simple int activationStrategy to an object
        if (!$activationStrategy instanceof ActivationStrategyInterface) {
            $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy);
        }
        $this->handler = $handler;
        $this->activationStrategy = $activationStrategy;
        $this->bufferSize = $bufferSize;
        $this->bubble = $bubble;
        $this->stopBuffering = $stopBuffering;
        if ($passthruLevel !== null) {
            $this->passthruLevel = Logger::toMonologLevel($passthruLevel);
        }
        if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
            throw new \RuntimeException("The given handler (" . json_encode($this->handler) . ") is not a callable nor a Monolog\\Handler\\HandlerInterface object");
        }
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return true;
    }
    /**
     * Manually activate this logger regardless of the activation strategy
     */
    public function activate() : void
    {
        if ($this->stopBuffering) {
            $this->buffering = false;
        }
        $this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
        $this->buffer = [];
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        if ($this->buffering) {
            $this->buffer[] = $record;
            if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) {
                array_shift($this->buffer);
            }
            if ($this->activationStrategy->isHandlerActivated($record)) {
                $this->activate();
            }
        } else {
            $this->getHandler($record)->handle($record);
        }
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        $this->flushBuffer();
        $this->getHandler()->close();
    }
    /**
     *
     */
    public function reset()
    {
        $this->flushBuffer();
        $this->resetProcessors();
        if ($this->getHandler() instanceof ResettableInterface) {
            $this->getHandler()->reset();
        }
    }
    /**
     * Clears the buffer without flushing any messages down to the wrapped handler.
     *
     * It also resets the handler to its initial buffering state.
     */
    public function clear() : void
    {
        $this->buffer = [];
        $this->reset();
    }
    /**
     * Resets the state of the handler. Stops forwarding records to the wrapped handler.
     */
    private function flushBuffer() : void
    {
        if (null !== $this->passthruLevel) {
            $level = $this->passthruLevel;
            $this->buffer = array_filter($this->buffer, function ($record) use($level) {
                return $record['level'] >= $level;
            });
            if (count($this->buffer) > 0) {
                $this->getHandler(end($this->buffer))->handleBatch($this->buffer);
            }
        }
        $this->buffer = [];
        $this->buffering = true;
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory callable, this will trigger the handler's instantiation.
     *
     * @return HandlerInterface
     *
     * @phpstan-param Record $record
     */
    public function getHandler(array $record = null)
    {
        if (!$this->handler instanceof HandlerInterface) {
            $this->handler = ($this->handler)($record, $this);
            if (!$this->handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory callable should return a HandlerInterface");
            }
        }
        return $this->handler;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Rollbar\RollbarLogger;
use Throwable;
use Monolog\Logger;
/**
 * Sends errors to Rollbar
 *
 * If the context data contains a `payload` key, that is used as an array
 * of payload options to RollbarLogger's log method.
 *
 * Rollbar's context info will contain the context + extra keys from the log record
 * merged, and then on top of that a few keys:
 *
 *  - level (rollbar level name)
 *  - monolog_level (monolog level name, raw level, as rollbar only has 5 but monolog 8)
 *  - channel
 *  - datetime (unix timestamp)
 *
 * @author Paul Statezny <paulstatezny@gmail.com>
 */
class RollbarHandler extends AbstractProcessingHandler
{
    /**
     * @var RollbarLogger
     */
    protected $rollbarLogger;
    /** @var string[] */
    protected $levelMap = [Logger::DEBUG => 'debug', Logger::INFO => 'info', Logger::NOTICE => 'info', Logger::WARNING => 'warning', Logger::ERROR => 'error', Logger::CRITICAL => 'critical', Logger::ALERT => 'critical', Logger::EMERGENCY => 'critical'];
    /**
     * Records whether any log records have been added since the last flush of the rollbar notifier
     *
     * @var bool
     */
    private $hasRecords = false;
    /** @var bool */
    protected $initialized = false;
    /**
     * @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token
     */
    public function __construct(RollbarLogger $rollbarLogger, $level = Logger::ERROR, bool $bubble = true)
    {
        $this->rollbarLogger = $rollbarLogger;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!$this->initialized) {
            // __destructor() doesn't get called on Fatal errors
            register_shutdown_function(array($this, 'close'));
            $this->initialized = true;
        }
        $context = $record['context'];
        $context = array_merge($context, $record['extra'], ['level' => $this->levelMap[$record['level']], 'monolog_level' => $record['level_name'], 'channel' => $record['channel'], 'datetime' => $record['datetime']->format('U')]);
        if (isset($context['exception']) && $context['exception'] instanceof Throwable) {
            $exception = $context['exception'];
            unset($context['exception']);
            $toLog = $exception;
        } else {
            $toLog = $record['message'];
        }
        // @phpstan-ignore-next-line
        $this->rollbarLogger->log($context['level'], $toLog, $context);
        $this->hasRecords = true;
    }
    /**
     *
     */
    public function flush() : void
    {
        if ($this->hasRecords) {
            $this->rollbarLogger->flush();
            $this->hasRecords = false;
        }
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        $this->flush();
    }
    /**
     * {@inheritDoc}
     */
    public function reset()
    {
        $this->flush();
        parent::reset();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
use Doctrine\CouchDB\CouchDBClient;
/**
 * CouchDB handler for Doctrine CouchDB ODM
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class DoctrineCouchDBHandler extends AbstractProcessingHandler
{
    /** @var CouchDBClient */
    private $client;
    /**
     *
     */
    public function __construct(CouchDBClient $client, $level = Logger::DEBUG, bool $bubble = true)
    {
        $this->client = $client;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->client->postDocument($record['formatted']);
    }
    /**
     *
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new NormalizerFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

trait WebRequestRecognizerTrait
{
    /**
     * Checks if PHP's serving a web request
     * @return bool
     */
    protected function isWebRequest() : bool
    {
        return 'cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Swift_Message;
use Swift;
/**
 * SwiftMailerHandler uses Swift_Mailer to send the emails
 *
 * @author Gyula Sallai
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class SwiftMailerHandler extends MailHandler
{
    /** @var \Swift_Mailer */
    protected $mailer;
    /** @var Swift_Message|callable(string, Record[]): Swift_Message */
    private $messageTemplate;
    /**
     * @psalm-param (Swift_Message | callable(string , Record[] ): Swift_Message) $message
     *
     * @param \Swift_Mailer $mailer The mailer to use
     * @param (callable | Swift_Message) $message An example message for real messages, only the body will be replaced
     */
    public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->mailer = $mailer;
        $this->messageTemplate = $message;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records) : void
    {
        $this->mailer->send($this->buildMessage($content, $records));
    }
    /**
     * Gets the formatter for the Swift_Message subject.
     *
     * @param (string | null) $format The format of the subject
     */
    protected function getSubjectFormatter(?string $format) : FormatterInterface
    {
        return new LineFormatter($format);
    }
    /**
     * Creates instance of Swift_Message to be sent
     *
     * @param string $content formatted email body to be sent
     * @param array $records Log records that formed the content
     * @return Swift_Message
     *
     * @phpstan-param Record[] $records
     */
    protected function buildMessage(string $content, array $records) : Swift_Message
    {
        $message = null;
        if ($this->messageTemplate instanceof Swift_Message) {
            $message = clone $this->messageTemplate;
            $message->generateId();
        } elseif (is_callable($this->messageTemplate)) {
            $message = ($this->messageTemplate)($content, $records);
        }
        if (!$message instanceof Swift_Message) {
            throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it');
        }
        if ($records) {
            $subjectFormatter = $this->getSubjectFormatter($message->getSubject());
            $message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
        }
        $mime = 'text/plain';
        if ($this->isHtmlBody($content)) {
            $mime = 'text/html';
        }
        $message->setBody($content, $mime);
        /** @phpstan-ignore-next-line */
        if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
            $message->setDate(new \DateTimeImmutable());
        } else {
            /** @phpstan-ignore-next-line */
            $message->setDate(time());
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html
 *
 * @author Ricardo Fontanelli <ricardo.fontanelli@hotmail.com>
 */
class SendGridHandler extends MailHandler
{
    /**
     * The SendGrid API User
     * @var string
     */
    protected $apiUser;
    /**
     * The SendGrid API Key
     * @var string
     */
    protected $apiKey;
    /**
     * The email addresses to which the message will be sent
     * @var string
     */
    protected $from;
    /**
     * The email addresses to which the message will be sent
     * @var string[]
     */
    protected $to;
    /**
     * The subject of the email
     * @var string
     */
    protected $subject;
    /**
     * @param string $apiUser The SendGrid API User
     * @param string $apiKey The SendGrid API Key
     * @param string $from The sender of the email
     * @param (string | string[]) $to The recipients of the email
     * @param string $subject The subject of the mail
     */
    public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, $level = Logger::ERROR, bool $bubble = true)
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the SendGridHandler');
        }
        parent::__construct($level, $bubble);
        $this->apiUser = $apiUser;
        $this->apiKey = $apiKey;
        $this->from = $from;
        $this->to = (array) $to;
        $this->subject = $subject;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records) : void
    {
        $message = [];
        $message['api_user'] = $this->apiUser;
        $message['api_key'] = $this->apiKey;
        $message['from'] = $this->from;
        foreach ($this->to as $recipient) {
            $message['to[]'] = $recipient;
        }
        $message['subject'] = $this->subject;
        $message['date'] = \Phabel\Target\Php80\Polyfill::date('r');
        if ($this->isHtmlBody($content)) {
            $message['html'] = $content;
        } else {
            $message['text'] = $content;
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://api.sendgrid.com/api/mail.send.json');
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($message));
        Curl\Util::execute($ch, 2);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Gelf\PublisherInterface;
use Monolog\Logger;
use Monolog\Formatter\GelfMessageFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Handler to send messages to a Graylog2 (http://www.graylog2.org) server
 *
 * @author Matt Lehner <mlehner@gmail.com>
 * @author Benjamin Zikarsky <benjamin@zikarsky.de>
 */
class GelfHandler extends AbstractProcessingHandler
{
    /**
     * @var PublisherInterface the publisher object that sends the message to the server
     */
    protected $publisher;
    /**
     * @param PublisherInterface $publisher a gelf publisher object
     */
    public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->publisher = $publisher;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->publisher->publish($record['formatted']);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new GelfMessageFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
/**
 * Buffers all records until closing the handler and then pass them as batch.
 *
 * This is useful for a MailHandler to send only one mail per request instead of
 * sending one per log message.
 *
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /** @var HandlerInterface */
    protected $handler;
    /** @var int */
    protected $bufferSize = 0;
    /** @var int */
    protected $bufferLimit;
    /** @var bool */
    protected $flushOnOverflow;
    /** @var Record[] */
    protected $buffer = [];
    /** @var bool */
    protected $initialized = false;
    /**
     * @param HandlerInterface $handler Handler.
     * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
     * @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
     */
    public function __construct(HandlerInterface $handler, int $bufferLimit = 0, $level = Logger::DEBUG, bool $bubble = true, bool $flushOnOverflow = false)
    {
        parent::__construct($level, $bubble);
        $this->handler = $handler;
        $this->bufferLimit = $bufferLimit;
        $this->flushOnOverflow = $flushOnOverflow;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($record['level'] < $this->level) {
            return false;
        }
        if (!$this->initialized) {
            // __destructor() doesn't get called on Fatal errors
            register_shutdown_function([$this, 'close']);
            $this->initialized = true;
        }
        if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) {
            if ($this->flushOnOverflow) {
                $this->flush();
            } else {
                array_shift($this->buffer);
                $this->bufferSize--;
            }
        }
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        $this->buffer[] = $record;
        $this->bufferSize++;
        return false === $this->bubble;
    }
    /**
     *
     */
    public function flush() : void
    {
        if ($this->bufferSize === 0) {
            return;
        }
        $this->handler->handleBatch($this->buffer);
        $this->clear();
    }
    /**
     *
     */
    public function __destruct()
    {
        // suppress the parent behavior since we already have register_shutdown_function()
        // to call close(), and the reference contained there will prevent this from being
        // GC'd until the end of the request
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        $this->flush();
        $this->handler->close();
    }
    /**
     * Clears the buffer without flushing any messages down to the wrapped handler.
     */
    public function clear() : void
    {
        $this->bufferSize = 0;
        $this->buffer = [];
    }
    /**
     *
     */
    public function reset()
    {
        $this->flush();
        parent::reset();
        $this->resetProcessors();
        if ($this->handler instanceof ResettableInterface) {
            $this->handler->reset();
        }
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($this->handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($this->handler) . ' does not support formatters.');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Blackhole
 *
 * Any record it can handle will be thrown away. This can be used
 * to put on top of an existing stack to override it temporarily.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class NullHandler extends Handler
{
    /**
     * @var int
     */
    private $level;
    /**
     * @param (string | int) $level The minimum logging level at which this handler will be triggered
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return $record['level'] >= $this->level;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        return $record['level'] >= $this->level;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Exception can be thrown if an extension for a handler is missing
 *
 * @author Christian Bergau <cbergau86@gmail.com>
 */
class MissingExtensionException extends \Exception
{
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
/**
 * Stores to PHP error_log() handler.
 *
 * @author Elan RuusamÃ¤e <glen@delfi.ee>
 */
class ErrorLogHandler extends AbstractProcessingHandler
{
    public const OPERATING_SYSTEM = 0;
    public const SAPI = 4;
    /** @var int */
    protected $messageType;
    /** @var bool */
    protected $expandNewlines;
    /**
     * @param int $messageType Says where the error should go.
     * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
     */
    public function __construct(int $messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, bool $bubble = true, bool $expandNewlines = false)
    {
        parent::__construct($level, $bubble);
        if (false === in_array($messageType, self::getAvailableTypes(), true)) {
            $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true));
            throw new \InvalidArgumentException($message);
        }
        $this->messageType = $messageType;
        $this->expandNewlines = $expandNewlines;
    }
    /**
     * @return int[] With all available types
     */
    public static function getAvailableTypes() : array
    {
        return [self::OPERATING_SYSTEM, self::SAPI];
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%');
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!$this->expandNewlines) {
            error_log((string) $record['formatted'], $this->messageType);
            return;
        }
        $lines = preg_split('{[\\r\\n]+}', (string) $record['formatted']);
        if ($lines === false) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
        }
        foreach ($lines as $line) {
            error_log($line, $this->messageType);
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogglyFormatter;
use function array_key_exists;
use CurlHandle;
/**
 * Sends errors to Loggly.
 *
 * @author Przemek Sobstel <przemek@sobstel.org>
 * @author Adam Pancutt <adam@pancutt.com>
 * @author Gregory Barchard <gregory@barchard.net>
 */
class LogglyHandler extends AbstractProcessingHandler
{
    protected const HOST = 'logs-01.loggly.com';
    protected const ENDPOINT_SINGLE = 'inputs';
    protected const ENDPOINT_BATCH = 'bulk';
    /**
     * Caches the curl handlers for every given endpoint.
     *
     * @var resource[]|CurlHandle[]
     */
    protected $curlHandlers = [];
    /** @var string */
    protected $token;
    /** @var string[] */
    protected $tag = [];
    /**
     * @param string $token API token supplied by Loggly
     *
     * @throws MissingExtensionException If the curl extension is missing
     */
    public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler');
        }
        $this->token = $token;
        parent::__construct($level, $bubble);
    }
    /**
     * Loads and returns the shared curl handler for the given endpoint.
     *
     * @param string $endpoint
     *
     * @return (resource | CurlHandle)
     */
    protected function getCurlHandler(string $endpoint)
    {
        if (!array_key_exists($endpoint, $this->curlHandlers)) {
            $this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint);
        }
        return $this->curlHandlers[$endpoint];
    }
    /**
     * Starts a fresh curl session for the given endpoint and returns its handler.
     *
     * @param string $endpoint
     *
     * @return (resource | CurlHandle)
     */
    private function loadCurlHandle(string $endpoint)
    {
        $url = sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        return $ch;
    }
    /**
     * @param (string[] | string) $tag
     */
    public function setTag($tag) : self
    {
        $tag = !empty($tag) ? $tag : [];
        $this->tag = is_array($tag) ? $tag : [$tag];
        return $this;
    }
    /**
     * @param (string[] | string) $tag
     */
    public function addTag($tag) : self
    {
        if (!empty($tag)) {
            $tag = is_array($tag) ? $tag : [$tag];
            $this->tag = array_unique(array_merge($this->tag, $tag));
        }
        return $this;
    }
    /**
     *
     */
    protected function write(array $record) : void
    {
        $this->send($record["formatted"], static::ENDPOINT_SINGLE);
    }
    /**
     *
     */
    public function handleBatch(array $records) : void
    {
        $level = $this->level;
        $records = array_filter($records, function ($record) use($level) {
            return $record['level'] >= $level;
        });
        if ($records) {
            $this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH);
        }
    }
    /**
     *
     */
    protected function send(string $data, string $endpoint) : void
    {
        $ch = $this->getCurlHandler($endpoint);
        $headers = ['Content-Type: application/json'];
        if (!empty($this->tag)) {
            $headers[] = 'X-LOGGLY-TAG: ' . implode(',', $this->tag);
        }
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        Curl\Util::execute($ch, 5, false);
    }
    /**
     *
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LogglyFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\WildfireFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
 *
 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class FirePHPHandler extends AbstractProcessingHandler
{
    use WebRequestRecognizerTrait;
    /**
     * WildFire JSON header message format
     */
    protected const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';
    /**
     * FirePHP structure for parsing messages & their presentation
     */
    protected const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';
    /**
     * Must reference a "known" plugin, otherwise headers won't display in FirePHP
     */
    protected const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3';
    /**
     * Header prefix for Wildfire to recognize & parse headers
     */
    protected const HEADER_PREFIX = 'X-Wf';
    /**
     * Whether or not Wildfire vendor-specific headers have been generated & sent yet
     * @var bool
     */
    protected static $initialized = false;
    /**
     * Shared static message index between potentially multiple handlers
     * @var int
     */
    protected static $messageIndex = 1;
    /** @var bool */
    protected static $sendHeaders = true;
    /**
     * Base header creation function used by init headers & record headers
     *
     * @param array<(int | string)> $meta Wildfire Plugin, Protocol & Structure Indexes
     * @param string $message Log message
     *
     * @return array<string, string> Complete header string ready for the client as key and message as value
     *
     * @phpstan-return non-empty-array<string, string>
     */
    protected function createHeader(array $meta, string $message) : array
    {
        $header = sprintf('%s-%s', static::HEADER_PREFIX, join('-', $meta));
        return [$header => $message];
    }
    /**
     * Creates message header from record
     *
     * @return array<string, string>
     *
     * @phpstan-return non-empty-array<string, string>
     *
     * @see createHeader()
     *
     * @phpstan-param FormattedRecord $record
     */
    protected function createRecordHeader(array $record) : array
    {
        // Wildfire is extensible to support multiple protocols & plugins in a single request,
        // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
        return $this->createHeader([1, 1, 1, self::$messageIndex++], $record['formatted']);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new WildfireFormatter();
    }
    /**
     * Wildfire initialization headers to enable message parsing
     *
     * @see createHeader()
     * @see sendHeader()
     *
     * @return array<string, string>
     */
    protected function getInitHeaders() : array
    {
        // Initial payload consists of required headers for Wildfire
        return array_merge($this->createHeader(['Protocol', 1], static::PROTOCOL_URI), $this->createHeader([1, 'Structure', 1], static::STRUCTURE_URI), $this->createHeader([1, 'Plugin', 1], static::PLUGIN_URI));
    }
    /**
     * Send header string to the client
     */
    protected function sendHeader(string $header, string $content) : void
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }
    /**
     * Creates & sends header for a record, ensuring init headers have been sent prior
     *
     * @see sendHeader()
     * @see sendInitHeaders()
     */
    protected function write(array $record) : void
    {
        if (!self::$sendHeaders || !$this->isWebRequest()) {
            return;
        }
        // WildFire-specific headers must be sent prior to any messages
        if (!self::$initialized) {
            self::$initialized = true;
            self::$sendHeaders = $this->headersAccepted();
            if (!self::$sendHeaders) {
                return;
            }
            foreach ($this->getInitHeaders() as $header => $content) {
                $this->sendHeader($header, $content);
            }
        }
        $header = $this->createRecordHeader($record);
        if (trim(current($header)) !== '') {
            $this->sendHeader(key($header), current($header));
        }
    }
    /**
     * Verifies if the headers are accepted by the current user agent
     */
    protected function headersAccepted() : bool
    {
        if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\\bFirePHP/\\d+\\.\\d+\\b}', $_SERVER['HTTP_USER_AGENT'])) {
            return true;
        }
        return isset($_SERVER['HTTP_X_FIREPHP_VERSION']);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Handler\Slack\SlackRecord;
/**
 * Sends notifications through Slack Webhooks
 *
 * @author Haralan Dobrev <hkdobrev@gmail.com>
 * @see    https://api.slack.com/incoming-webhooks
 */
class SlackWebhookHandler extends AbstractProcessingHandler
{
    /**
     * Slack Webhook token
     * @var string
     */
    private $webhookUrl;
    /**
     * Instance of the SlackRecord util class preparing data for Slack API.
     * @var SlackRecord
     */
    private $slackRecord;
    /**
     * @param string $webhookUrl Slack Webhook URL
     * @param (string | null) $channel Slack channel (encoded ID or name)
     * @param (string | null) $username Name of a bot
     * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
     * @param (string | null) $iconEmoji The emoji name to use (or null)
     * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
     * @param bool $includeContextAndExtra Whether the attachment should include context and extra data
     * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     */
    public function __construct(string $webhookUrl, ?string $channel = null, ?string $username = null, bool $useAttachment = true, ?string $iconEmoji = null, bool $useShortAttachment = false, bool $includeContextAndExtra = false, $level = Logger::CRITICAL, bool $bubble = true, array $excludeFields = array())
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the SlackWebhookHandler');
        }
        parent::__construct($level, $bubble);
        $this->webhookUrl = $webhookUrl;
        $this->slackRecord = new SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields);
    }
    /**
     *
     */
    public function getSlackRecord() : SlackRecord
    {
        return $this->slackRecord;
    }
    /**
     *
     */
    public function getWebhookUrl() : string
    {
        return $this->webhookUrl;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $postData = $this->slackRecord->getSlackData($record);
        $postString = Utils::jsonEncode($postData);
        $ch = curl_init();
        $options = array(CURLOPT_URL => $this->webhookUrl, CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array('Content-type: application/json'), CURLOPT_POSTFIELDS => $postString);
        if (defined('CURLOPT_SAFE_UPLOAD')) {
            $options[CURLOPT_SAFE_UPLOAD] = true;
        }
        curl_setopt_array($ch, $options);
        Curl\Util::execute($ch);
    }
    /**
     *
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        parent::setFormatter($formatter);
        $this->slackRecord->setFormatter($formatter);
        return $this;
    }
    /**
     *
     */
    public function getFormatter() : FormatterInterface
    {
        $formatter = parent::getFormatter();
        $this->slackRecord->setFormatter($formatter);
        return $formatter;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Psr\Log\LoggerInterface;
use Monolog\Formatter\FormatterInterface;
/**
 * Proxies log messages to an existing PSR-3 compliant logger.
 *
 * If a formatter is configured, the formatter's output MUST be a string and the
 * formatted message will be fed to the wrapped PSR logger instead of the original
 * log record's message.
 *
 * @author Michael Moussa <michael.moussa@gmail.com>
 */
class PsrHandler extends AbstractHandler implements FormattableHandlerInterface
{
    /**
     * PSR-3 compliant logger
     *
     * @var LoggerInterface
     */
    protected $logger;
    /**
     * @var FormatterInterface|null
     */
    protected $formatter;
    /**
     * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
     */
    public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->logger = $logger;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if (!$this->isHandling($record)) {
            return false;
        }
        if ($this->formatter) {
            $formatted = $this->formatter->format($record);
            $this->logger->log(strtolower($record['level_name']), (string) $formatted, $record['context']);
        } else {
            $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']);
        }
        return false === $this->bubble;
    }
    /**
     * Sets the formatter.
     *
     * @param FormatterInterface $formatter
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * Gets the formatter.
     *
     * @return FormatterInterface
     */
    public function getFormatter() : FormatterInterface
    {
        if (!$this->formatter) {
            throw new \LogicException('No formatter has been set and this handler does not have a default formatter');
        }
        return $this->formatter;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Logger;
/**
 * Handler sending logs to Zend Monitor
 *
 * @author  Christian Bergau <cbergau86@gmail.com>
 * @author  Jason Davis <happydude@jasondavis.net>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class ZendMonitorHandler extends AbstractProcessingHandler
{
    /**
     * Monolog level / ZendMonitor Custom Event priority map
     *
     * @var array<int, int>
     */
    protected $levelMap = [];
    /**
     * @throws MissingExtensionException
     */
    public function __construct($level = Logger::DEBUG, bool $bubble = true)
    {
        if (!function_exists('zend_monitor_custom_event')) {
            throw new MissingExtensionException('You must have Zend Server installed with Zend Monitor enabled in order to use this handler');
        }
        //zend monitor constants are not defined if zend monitor is not enabled.
        $this->levelMap = [Logger::DEBUG => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::INFO => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::NOTICE => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::WARNING => \ZEND_MONITOR_EVENT_SEVERITY_WARNING, Logger::ERROR => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::CRITICAL => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::ALERT => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::EMERGENCY => \ZEND_MONITOR_EVENT_SEVERITY_ERROR];
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->writeZendMonitorCustomEvent(Logger::getLevelName($record['level']), $record['message'], $record['formatted'], $this->levelMap[$record['level']]);
    }
    /**
     * Write to Zend Monitor Events
     * @param string $type Text displayed in "Class Name (custom)" field
     * @param string $message Text displayed in "Error String"
     * @param array $formatted Displayed in Custom Variables tab
     * @param int $severity Set the event severity level (-1,0,1)
     *
     * @phpstan-param FormattedRecord $formatted
     */
    protected function writeZendMonitorCustomEvent(string $type, string $message, array $formatted, int $severity) : void
    {
        zend_monitor_custom_event($type, $message, $formatted, $severity);
    }
    /**
     * {@inheritDoc}
     */
    public function getDefaultFormatter() : FormatterInterface
    {
        return new NormalizerFormatter();
    }
    /**
     * @return array<int, int>
     */
    public function getLevelMap() : array
    {
        return $this->levelMap;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
/**
 * Interface to describe loggers that have a formatter
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface FormattableHandlerInterface
{
    /**
     * Sets the formatter.
     *
     * @param FormatterInterface $formatter
     * @return HandlerInterface self
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface;
    /**
     * Gets the formatter.
     *
     * @return FormatterInterface
     */
    public function getFormatter() : FormatterInterface;
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\FingersCrossed;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Error level based activation strategy.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class ErrorLevelActivationStrategy implements ActivationStrategyInterface
{
    /**
     * @var Level
     */
    private $actionLevel;
    /**
     * @param (int | string) $actionLevel Level or name or value
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $actionLevel
     */
    public function __construct($actionLevel)
    {
        $this->actionLevel = Logger::toMonologLevel($actionLevel);
    }
    /**
     *
     */
    public function isHandlerActivated(array $record) : bool
    {
        return $record['level'] >= $this->actionLevel;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\FingersCrossed;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Channel and Error level based monolog activation strategy. Allows to trigger activation
 * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except
 * for records of the 'sql' channel; those should trigger activation on level 'WARN'.
 *
 * Example:
 *
 * <code>
 *   $activationStrategy = new ChannelLevelActivationStrategy(
 *       Logger::CRITICAL,
 *       array(
 *           'request' => Logger::ALERT,
 *           'sensitive' => Logger::ERROR,
 *       )
 *   );
 *   $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy);
 * </code>
 *
 * @author Mike Meessen <netmikey@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class ChannelLevelActivationStrategy implements ActivationStrategyInterface
{
    /**
     * @var Level
     */
    private $defaultActionLevel;
    /**
     * @var array<string, Level>
     */
    private $channelToActionLevel;
    /**
     * @param (int | string) $defaultActionLevel The default action level to be used if the record's category doesn't match any
     * @param array<string, int> $channelToActionLevel An array that maps channel names to action levels.
     *
     * @phpstan-param array<string, Level> $channelToActionLevel
     * @phpstan-param (Level | LevelName | LogLevel::*) $defaultActionLevel
     */
    public function __construct($defaultActionLevel, array $channelToActionLevel = [])
    {
        $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel);
        $this->channelToActionLevel = array_map('Monolog\\Logger::toMonologLevel', $channelToActionLevel);
    }
    /**
     * @phpstan-param Record $record
     */
    public function isHandlerActivated(array $record) : bool
    {
        if (isset($this->channelToActionLevel[$record['channel']])) {
            return $record['level'] >= $this->channelToActionLevel[$record['channel']];
        }
        return $record['level'] >= $this->defaultActionLevel;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\FingersCrossed;

/**
 * Interface for activation strategies for the FingersCrossedHandler.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
interface ActivationStrategyInterface
{
    /**
     * Returns whether the given record activates the handler.
     *
     * @phpstan-param Record $record
     */
    public function isHandlerActivated(array $record) : bool;
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Used for testing purposes.
 *
 * It records all records and gives you access to them for verification.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @method bool hasEmergency($record)
 * @method bool hasAlert($record)
 * @method bool hasCritical($record)
 * @method bool hasError($record)
 * @method bool hasWarning($record)
 * @method bool hasNotice($record)
 * @method bool hasInfo($record)
 * @method bool hasDebug($record)
 *
 * @method bool hasEmergencyRecords()
 * @method bool hasAlertRecords()
 * @method bool hasCriticalRecords()
 * @method bool hasErrorRecords()
 * @method bool hasWarningRecords()
 * @method bool hasNoticeRecords()
 * @method bool hasInfoRecords()
 * @method bool hasDebugRecords()
 *
 * @method bool hasEmergencyThatContains($message)
 * @method bool hasAlertThatContains($message)
 * @method bool hasCriticalThatContains($message)
 * @method bool hasErrorThatContains($message)
 * @method bool hasWarningThatContains($message)
 * @method bool hasNoticeThatContains($message)
 * @method bool hasInfoThatContains($message)
 * @method bool hasDebugThatContains($message)
 *
 * @method bool hasEmergencyThatMatches($message)
 * @method bool hasAlertThatMatches($message)
 * @method bool hasCriticalThatMatches($message)
 * @method bool hasErrorThatMatches($message)
 * @method bool hasWarningThatMatches($message)
 * @method bool hasNoticeThatMatches($message)
 * @method bool hasInfoThatMatches($message)
 * @method bool hasDebugThatMatches($message)
 *
 * @method bool hasEmergencyThatPasses($message)
 * @method bool hasAlertThatPasses($message)
 * @method bool hasCriticalThatPasses($message)
 * @method bool hasErrorThatPasses($message)
 * @method bool hasWarningThatPasses($message)
 * @method bool hasNoticeThatPasses($message)
 * @method bool hasInfoThatPasses($message)
 * @method bool hasDebugThatPasses($message)
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class TestHandler extends AbstractProcessingHandler
{
    /** @var Record[] */
    protected $records = [];
    /** @var array<Level, Record[]> */
    protected $recordsByLevel = [];
    /** @var bool */
    private $skipReset = false;
    /**
     * @return array
     *
     * @phpstan-return Record[]
     */
    public function getRecords()
    {
        return $this->records;
    }
    /**
     * @return void
     */
    public function clear()
    {
        $this->records = [];
        $this->recordsByLevel = [];
    }
    /**
     * @return void
     */
    public function reset()
    {
        if (!$this->skipReset) {
            $this->clear();
        }
    }
    /**
     * @return void
     */
    public function setSkipReset(bool $skipReset)
    {
        $this->skipReset = $skipReset;
    }
    /**
     * @param (string | int) $level Logging level value or name
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecords($level) : bool
    {
        return isset($this->recordsByLevel[Logger::toMonologLevel($level)]);
    }
    /**
     * @param (string | array) $record Either a message string or an array containing message and optionally context keys that will be checked against all records
     * @param (string | int) $level Logging level value or name
     *
     * @phpstan-param (array{message: string, context?: mixed[]} | string) $record
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecord($record, $level) : bool
    {
        if (is_string($record)) {
            $record = array('message' => $record);
        }
        return $this->hasRecordThatPasses(function ($rec) use($record) {
            if ($rec['message'] !== $record['message']) {
                return false;
            }
            if (isset($record['context']) && $rec['context'] !== $record['context']) {
                return false;
            }
            return true;
        }, $level);
    }
    /**
     * @param (string | int) $level Logging level value or name
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecordThatContains(string $message, $level) : bool
    {
        return $this->hasRecordThatPasses(function ($rec) use($message) {
            return strpos($rec['message'], $message) !== false;
        }, $level);
    }
    /**
     * @param (string | int) $level Logging level value or name
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecordThatMatches(string $regex, $level) : bool
    {
        return $this->hasRecordThatPasses(function (array $rec) use($regex) : bool {
            return preg_match($regex, $rec['message']) > 0;
        }, $level);
    }
    /**
     * @param (string | int) $level Logging level value or name
     * @return bool
     *
     * @psalm-param callable(Record , int ): mixed $predicate
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecordThatPasses(callable $predicate, $level)
    {
        $level = Logger::toMonologLevel($level);
        if (!isset($this->recordsByLevel[$level])) {
            return false;
        }
        foreach ($this->recordsByLevel[$level] as $i => $rec) {
            if ($predicate($rec, $i)) {
                return true;
            }
        }
        return false;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->recordsByLevel[$record['level']][] = $record;
        $this->records[] = $record;
    }
    /**
     * @param string $method
     * @param mixed[] $args
     * @return bool
     */
    public function __call($method, $args)
    {
        if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
            $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
            $level = constant('Monolog\\Logger::' . strtoupper($matches[2]));
            $callback = [$this, $genericMethod];
            if (is_callable($callback)) {
                $args[] = $level;
                return call_user_func_array($callback, $args);
            }
        }
        throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
/**
 * Helper trait for implementing FormattableInterface
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
trait FormattableHandlerTrait
{
    /**
     * @var ?FormatterInterface
     */
    protected $formatter;
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        if (!$this->formatter) {
            $this->formatter = $this->getDefaultFormatter();
        }
        return $this->formatter;
    }
    /**
     * Gets the default formatter.
     *
     * Overwrite this if the LineFormatter is not a good default for your handler.
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
use Psr\Log\LogLevel;
/**
 * Simple handler wrapper that filters records based on a list of levels
 *
 * It can be configured with an exact list of levels to allow, or a min/max level.
 *
 * @author Hennadiy Verkh
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class FilterHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * Handler or factory callable($record, $this)
     *
     * @var callable|HandlerInterface
     * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
     */
    protected $handler;
    /**
     * Minimum level for logs that are passed to handler
     *
     * @var int[]
     * @phpstan-var array<Level, int>
     */
    protected $acceptedLevels;
    /**
     * Whether the messages that are handled can bubble up the stack or not
     *
     * @var bool
     */
    protected $bubble;
    /**
     * @psalm-param (HandlerInterface | callable(?Record , HandlerInterface ): HandlerInterface) $handler
     *
     * @param (callable | HandlerInterface) $handler Handler or factory callable($record|null, $filterHandler).
     * @param (int | array) $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
     * @param (int | string) $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param (Level | LevelName | LogLevel::* | array<(Level | LevelName | LogLevel::*)>) $minLevelOrList
     * @phpstan-param (Level | LevelName | LogLevel::*) $maxLevel
     */
    public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, bool $bubble = true)
    {
        $this->handler = $handler;
        $this->bubble = $bubble;
        $this->setAcceptedLevels($minLevelOrList, $maxLevel);
        if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
            throw new \RuntimeException("The given handler (" . json_encode($this->handler) . ") is not a callable nor a Monolog\\Handler\\HandlerInterface object");
        }
    }
    /**
     * @phpstan-return array<int, Level>
     */
    public function getAcceptedLevels() : array
    {
        return array_flip($this->acceptedLevels);
    }
    /**
     * @param (int | string | array) $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided
     * @param (int | string) $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array
     *
     * @phpstan-param (Level | LevelName | LogLevel::* | array<(Level | LevelName | LogLevel::*)>) $minLevelOrList
     * @phpstan-param (Level | LevelName | LogLevel::*) $maxLevel
     */
    public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY) : self
    {
        if (is_array($minLevelOrList)) {
            $acceptedLevels = array_map('Monolog\\Logger::toMonologLevel', $minLevelOrList);
        } else {
            $minLevelOrList = Logger::toMonologLevel($minLevelOrList);
            $maxLevel = Logger::toMonologLevel($maxLevel);
            $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use($minLevelOrList, $maxLevel) {
                return $level >= $minLevelOrList && $level <= $maxLevel;
            }));
        }
        $this->acceptedLevels = array_flip($acceptedLevels);
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return isset($this->acceptedLevels[$record['level']]);
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if (!$this->isHandling($record)) {
            return false;
        }
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        $this->getHandler($record)->handle($record);
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $filtered = [];
        foreach ($records as $record) {
            if ($this->isHandling($record)) {
                $filtered[] = $record;
            }
        }
        if (count($filtered) > 0) {
            $this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered);
        }
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory callable, this will trigger the handler's instantiation.
     *
     * @return HandlerInterface
     *
     * @phpstan-param Record $record
     */
    public function getHandler(array $record = null)
    {
        if (!$this->handler instanceof HandlerInterface) {
            $this->handler = ($this->handler)($record, $this);
            if (!$this->handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory callable should return a HandlerInterface");
            }
        }
        return $this->handler;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
    /**
     *
     */
    public function reset()
    {
        $this->resetProcessors();
        if ($this->getHandler() instanceof ResettableInterface) {
            $this->getHandler()->reset();
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * Logs to syslog service.
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $syslog = new SyslogHandler('myfacility', 'local6');
 *   $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
 *   $syslog->setFormatter($formatter);
 *   $log->pushHandler($syslog);
 *
 * @author Sven Paulus <sven@karlsruhe.org>
 */
class SyslogHandler extends AbstractSyslogHandler
{
    /** @var string */
    protected $ident;
    /** @var int */
    protected $logopts;
    /**
     * @param string $ident
     * @param (string | int) $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
     */
    public function __construct(string $ident, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, int $logopts = LOG_PID)
    {
        parent::__construct($facility, $level, $bubble);
        $this->ident = $ident;
        $this->logopts = $logopts;
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        closelog();
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!openlog($this->ident, $this->logopts, $this->facility)) {
            throw new \LogicException('Can\'t open syslog for ident "' . $this->ident . '" and facility "' . $this->facility . '"');
        }
        syslog($this->logLevels[$record['level']], (string) $record['formatted']);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use InvalidArgumentException;
use Monolog\Logger;
use Monolog\Utils;
/**
 * Stores logs to files that are rotated every day and a limited number of files are kept.
 *
 * This rotation is only intended to be used as a workaround. Using logrotate to
 * handle the rotation is strongly encouraged when you can use it.
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RotatingFileHandler extends StreamHandler
{
    public const FILE_PER_DAY = 'Y-m-d';
    public const FILE_PER_MONTH = 'Y-m';
    public const FILE_PER_YEAR = 'Y';
    /** @var string */
    protected $filename;
    /** @var int */
    protected $maxFiles;
    /** @var bool */
    protected $mustRotate;
    /** @var \DateTimeImmutable */
    protected $nextRotation;
    /** @var string */
    protected $filenameFormat;
    /** @var string */
    protected $dateFormat;
    /**
     * @param string $filename
     * @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
     * @param (int | null) $filePermission Optional file permissions (default (0644) are only for owner read/write)
     * @param bool $useLocking Try to lock log file before doing any writes
     */
    public function __construct(string $filename, int $maxFiles = 0, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false)
    {
        $this->filename = Utils::canonicalizePath($filename);
        $this->maxFiles = $maxFiles;
        $this->nextRotation = new \DateTimeImmutable('tomorrow');
        $this->filenameFormat = '{filename}-{date}';
        $this->dateFormat = static::FILE_PER_DAY;
        parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking);
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        parent::close();
        if (true === $this->mustRotate) {
            $this->rotate();
        }
    }
    /**
     * {@inheritDoc}
     */
    public function reset()
    {
        parent::reset();
        if (true === $this->mustRotate) {
            $this->rotate();
        }
    }
    /**
     *
     */
    public function setFilenameFormat(string $filenameFormat, string $dateFormat) : self
    {
        if (!preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
            throw new InvalidArgumentException('Invalid date format - format must be one of RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the date formats using slashes, underscores and/or dots instead of dashes.');
        }
        if (\Phabel\Target\Php80\Polyfill::substr_count($filenameFormat, '{date}') === 0) {
            throw new InvalidArgumentException('Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.');
        }
        $this->filenameFormat = $filenameFormat;
        $this->dateFormat = $dateFormat;
        $this->url = $this->getTimedFilename();
        $this->close();
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        // on the first record written, if the log is new, we should rotate (once per day)
        if (null === $this->mustRotate) {
            $this->mustRotate = null === $this->url || !file_exists($this->url);
        }
        if ($this->nextRotation <= $record['datetime']) {
            $this->mustRotate = true;
            $this->close();
        }
        parent::write($record);
    }
    /**
     * Rotates the files.
     */
    protected function rotate() : void
    {
        // update filename
        $this->url = $this->getTimedFilename();
        $this->nextRotation = new \DateTimeImmutable('tomorrow');
        // skip GC of old logs if files are unlimited
        if (0 === $this->maxFiles) {
            return;
        }
        $logFiles = glob($this->getGlobPattern());
        if (false === $logFiles) {
            // failed to glob
            return;
        }
        if ($this->maxFiles >= count($logFiles)) {
            // no files to remove
            return;
        }
        // Sorting the files by name to remove the older ones
        usort($logFiles, function ($a, $b) {
            return strcmp($b, $a);
        });
        foreach (array_slice($logFiles, $this->maxFiles) as $file) {
            if (is_writable($file)) {
                // suppress errors here as unlink() might fail if two processes
                // are cleaning up/rotating at the same time
                set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) : bool {
                    return false;
                });
                unlink($file);
                restore_error_handler();
            }
        }
        $this->mustRotate = false;
    }
    /**
     *
     */
    protected function getTimedFilename() : string
    {
        $fileInfo = pathinfo($this->filename);
        $timedFilename = str_replace(['{filename}', '{date}'], [$fileInfo['filename'], \Phabel\Target\Php80\Polyfill::date($this->dateFormat)], $fileInfo['dirname'] . '/' . $this->filenameFormat);
        if (isset($fileInfo['extension'])) {
            $timedFilename .= '.' . $fileInfo['extension'];
        }
        return $timedFilename;
    }
    /**
     *
     */
    protected function getGlobPattern() : string
    {
        $fileInfo = pathinfo($this->filename);
        $glob = str_replace(['{filename}', '{date}'], [$fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'], $fileInfo['dirname'] . '/' . $this->filenameFormat);
        if (isset($fileInfo['extension'])) {
            $glob .= '.' . $fileInfo['extension'];
        }
        return $glob;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\ResettableInterface;
use Monolog\Processor\ProcessorInterface;
/**
 * Helper trait for implementing ProcessableInterface
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
trait ProcessableHandlerTrait
{
    /**
     * @var callable[]
     * @phpstan-var array<ProcessorInterface|callable(Record): Record>
     */
    protected $processors = [];
    /**
     * {@inheritDoc}
     */
    public function pushProcessor(callable $callback) : HandlerInterface
    {
        array_unshift($this->processors, $callback);
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function popProcessor() : callable
    {
        if (!$this->processors) {
            throw new \LogicException('You tried to pop from an empty processor stack.');
        }
        return array_shift($this->processors);
    }
    /**
     * Processes a record.
     *
     * @phpstan-param Record $record
     * @phpstan-return Record
     */
    protected function processRecord(array $record) : array
    {
        foreach ($this->processors as $processor) {
            $record = $processor($record);
        }
        return $record;
    }
    /**
     *
     */
    protected function resetProcessors() : void
    {
        foreach ($this->processors as $processor) {
            if ($processor instanceof ResettableInterface) {
                $processor->reset();
            }
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
use PhpConsole\Connector;
use PhpConsole\Handler as VendorPhpConsoleHandler;
use PhpConsole\Helper;
/**
 * Monolog handler for Google Chrome extension "PHP Console"
 *
 * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely
 *
 * Usage:
 * 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef
 * 2. See overview https://github.com/barbushin/php-console#overview
 * 3. Install PHP Console library https://github.com/barbushin/php-console#installation
 * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png)
 *
 *      $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler()));
 *      \Monolog\ErrorHandler::register($logger);
 *      echo $undefinedVar;
 *      $logger->debug('SELECT * FROM users', array('db', 'time' => 0.012));
 *      PC::debug($_SERVER); // PHP Console debugger for any type of vars
 *
 * @author Sergey Barbushin https://www.linkedin.com/in/barbushin
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class PHPConsoleHandler extends AbstractProcessingHandler
{
    /** @var array<string, mixed> */
    private $options = [
        'enabled' => true,
        // bool Is PHP Console server enabled
        'classesPartialsTraceIgnore' => ['Monolog\\'],
        // array Hide calls of classes started with...
        'debugTagsKeysInContext' => [0, 'tag'],
        // bool Is PHP Console server enabled
        'useOwnErrorsHandler' => false,
        // bool Enable errors handling
        'useOwnExceptionsHandler' => false,
        // bool Enable exceptions handling
        'sourcesBasePath' => null,
        // string Base path of all project sources to strip in errors source paths
        'registerHelper' => true,
        // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s')
        'serverEncoding' => null,
        // string|null Server internal encoding
        'headersLimit' => null,
        // int|null Set headers size limit for your web-server
        'password' => null,
        // string|null Protect PHP Console connection by password
        'enableSslOnlyMode' => false,
        // bool Force connection by SSL for clients with PHP Console installed
        'ipMasks' => [],
        // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
        'enableEvalListener' => false,
        // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required)
        'dumperDetectCallbacks' => false,
        // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings
        'dumperLevelLimit' => 5,
        // int Maximum dumped vars array or object nested dump level
        'dumperItemsCountLimit' => 100,
        // int Maximum dumped var same level array items or object properties number
        'dumperItemSizeLimit' => 5000,
        // int Maximum length of any string or dumped array item
        'dumperDumpSizeLimit' => 500000,
        // int Maximum approximate size of dumped vars result formatted in JSON
        'detectDumpTraceAndSource' => false,
        // bool Autodetect and append trace data to debug
        'dataStorage' => null,
    ];
    /** @var Connector */
    private $connector;
    /**
     * @param array<string, mixed> $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
     * @param (Connector | null) $connector Instance of \PhpConsole\Connector class (optional)
     * @throws \RuntimeException
     */
    public function __construct(array $options = [], ?Connector $connector = null, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!class_exists('PhpConsole\\Connector')) {
            throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
        }
        parent::__construct($level, $bubble);
        $this->options = $this->initOptions($options);
        $this->connector = $this->initConnector($connector);
    }
    /**
     * @param array<string, mixed> $options
     *
     * @return array<string, mixed>
     */
    private function initOptions(array $options) : array
    {
        $wrongOptions = array_diff(array_keys($options), array_keys($this->options));
        if ($wrongOptions) {
            throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions));
        }
        return array_replace($this->options, $options);
    }
    /**
     *
     */
    private function initConnector(?Connector $connector = null) : Connector
    {
        if (!$connector) {
            if ($this->options['dataStorage']) {
                Connector::setPostponeStorage($this->options['dataStorage']);
            }
            $connector = Connector::getInstance();
        }
        if ($this->options['registerHelper'] && !Helper::isRegistered()) {
            Helper::register();
        }
        if ($this->options['enabled'] && $connector->isActiveClient()) {
            if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) {
                $handler = VendorPhpConsoleHandler::getInstance();
                $handler->setHandleErrors($this->options['useOwnErrorsHandler']);
                $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
                $handler->start();
            }
            if ($this->options['sourcesBasePath']) {
                $connector->setSourcesBasePath($this->options['sourcesBasePath']);
            }
            if ($this->options['serverEncoding']) {
                $connector->setServerEncoding($this->options['serverEncoding']);
            }
            if ($this->options['password']) {
                $connector->setPassword($this->options['password']);
            }
            if ($this->options['enableSslOnlyMode']) {
                $connector->enableSslOnlyMode();
            }
            if ($this->options['ipMasks']) {
                $connector->setAllowedIpMasks($this->options['ipMasks']);
            }
            if ($this->options['headersLimit']) {
                $connector->setHeadersLimit($this->options['headersLimit']);
            }
            if ($this->options['detectDumpTraceAndSource']) {
                $connector->getDebugDispatcher()->detectTraceAndSource = true;
            }
            $dumper = $connector->getDumper();
            $dumper->levelLimit = $this->options['dumperLevelLimit'];
            $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit'];
            $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit'];
            $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit'];
            $dumper->detectCallbacks = $this->options['dumperDetectCallbacks'];
            if ($this->options['enableEvalListener']) {
                $connector->startEvalRequestsListener();
            }
        }
        return $connector;
    }
    /**
     *
     */
    public function getConnector() : Connector
    {
        return $this->connector;
    }
    /**
     * @return array<string, mixed>
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     *
     */
    public function handle(array $record) : bool
    {
        if ($this->options['enabled'] && $this->connector->isActiveClient()) {
            return parent::handle($record);
        }
        return !$this->bubble;
    }
    /**
     * Writes the record down to the log of the implementing handler
     */
    protected function write(array $record) : void
    {
        if ($record['level'] < Logger::NOTICE) {
            $this->handleDebugRecord($record);
        } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
            $this->handleExceptionRecord($record);
        } else {
            $this->handleErrorRecord($record);
        }
    }
    /**
     * @phpstan-param Record $record
     */
    private function handleDebugRecord(array $record) : void
    {
        $tags = $this->getRecordTags($record);
        $message = $record['message'];
        if ($record['context']) {
            $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true);
        }
        $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
    }
    /**
     * @phpstan-param Record $record
     */
    private function handleExceptionRecord(array $record) : void
    {
        $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']);
    }
    /**
     * @phpstan-param Record $record
     */
    private function handleErrorRecord(array $record) : void
    {
        $context = $record['context'];
        $this->connector->getErrorsDispatcher()->dispatchError($context['code'] ?? null, $context['message'] ?? $record['message'], $context['file'] ?? null, $context['line'] ?? null, $this->options['classesPartialsTraceIgnore']);
    }
    /**
     * @phpstan-param Record $record
     * @return string
     */
    private function getRecordTags(array &$record)
    {
        $tags = null;
        if (!empty($record['context'])) {
            $context =& $record['context'];
            foreach ($this->options['debugTagsKeysInContext'] as $key) {
                if (!empty($context[$key])) {
                    $tags = $context[$key];
                    if ($key === 0) {
                        array_shift($context);
                    } else {
                        unset($context[$key]);
                    }
                    break;
                }
            }
        }
        return $tags ?: strtolower($record['level_name']);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter('%message%');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * Stores to any socket - uses fsockopen() or pfsockopen().
 *
 * @author Pablo de Leon Belloc <pablolb@gmail.com>
 * @see    http://php.net/manual/en/function.fsockopen.php
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class SocketHandler extends AbstractProcessingHandler
{
    /** @var string */
    private $connectionString;
    /** @var float */
    private $connectionTimeout;
    /** @var resource|null */
    private $resource;
    /** @var float */
    private $timeout = 0.0;
    /** @var float */
    private $writingTimeout = 10.0;
    /** @var ?int */
    private $lastSentBytes = null;
    /** @var ?int */
    private $chunkSize = null;
    /** @var bool */
    private $persistent = false;
    /** @var ?int */
    private $errno = null;
    /** @var ?string */
    private $errstr = null;
    /** @var ?float */
    private $lastWritingAt = null;
    /**
     * @param string $connectionString Socket connection string
     */
    public function __construct(string $connectionString, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->connectionString = $connectionString;
        $this->connectionTimeout = (float) ini_get('default_socket_timeout');
    }
    /**
     * Connect (if necessary) and write to the socket
     *
     * {@inheritDoc}
     *
     * @throws \UnexpectedValueException
     * @throws \RuntimeException
     */
    protected function write(array $record) : void
    {
        $this->connectIfNotConnected();
        $data = $this->generateDataStream($record);
        $this->writeToSocket($data);
    }
    /**
     * We will not close a PersistentSocket instance so it can be reused in other requests.
     */
    public function close() : void
    {
        if (!$this->isPersistent()) {
            $this->closeSocket();
        }
    }
    /**
     * Close socket, if open
     */
    public function closeSocket() : void
    {
        if (is_resource($this->resource)) {
            fclose($this->resource);
            $this->resource = null;
        }
    }
    /**
     * Set socket connection to be persistent. It only has effect before the connection is initiated.
     */
    public function setPersistent(bool $persistent) : self
    {
        $this->persistent = $persistent;
        return $this;
    }
    /**
     * Set connection timeout.  Only has effect before we connect.
     *
     * @see http://php.net/manual/en/function.fsockopen.php
     */
    public function setConnectionTimeout(float $seconds) : self
    {
        $this->validateTimeout($seconds);
        $this->connectionTimeout = $seconds;
        return $this;
    }
    /**
     * Set write timeout. Only has effect before we connect.
     *
     * @see http://php.net/manual/en/function.stream-set-timeout.php
     */
    public function setTimeout(float $seconds) : self
    {
        $this->validateTimeout($seconds);
        $this->timeout = $seconds;
        return $this;
    }
    /**
     * Set writing timeout. Only has effect during connection in the writing cycle.
     *
     * @param float $seconds 0 for no timeout
     */
    public function setWritingTimeout(float $seconds) : self
    {
        $this->validateTimeout($seconds);
        $this->writingTimeout = $seconds;
        return $this;
    }
    /**
     * Set chunk size. Only has effect during connection in the writing cycle.
     */
    public function setChunkSize(int $bytes) : self
    {
        $this->chunkSize = $bytes;
        return $this;
    }
    /**
     * Get current connection string
     */
    public function getConnectionString() : string
    {
        return $this->connectionString;
    }
    /**
     * Get persistent setting
     */
    public function isPersistent() : bool
    {
        return $this->persistent;
    }
    /**
     * Get current connection timeout setting
     */
    public function getConnectionTimeout() : float
    {
        return $this->connectionTimeout;
    }
    /**
     * Get current in-transfer timeout
     */
    public function getTimeout() : float
    {
        return $this->timeout;
    }
    /**
     * Get current local writing timeout
     *
     * @return float
     */
    public function getWritingTimeout() : float
    {
        return $this->writingTimeout;
    }
    /**
     * Get current chunk size
     */
    public function getChunkSize() : ?int
    {
        return $this->chunkSize;
    }
    /**
     * Check to see if the socket is currently available.
     *
     * UDP might appear to be connected but might fail when writing.  See http://php.net/fsockopen for details.
     */
    public function isConnected() : bool
    {
        return is_resource($this->resource) && !feof($this->resource);
        // on TCP - other party can close connection.
    }
    /**
     * Wrapper to allow mocking
     *
     * @return (resource | false)
     */
    protected function pfsockopen()
    {
        return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return (resource | false)
     */
    protected function fsockopen()
    {
        return @\Phabel\Target\Php80\Polyfill::fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
    }
    /**
     * Wrapper to allow mocking
     *
     * @see http://php.net/manual/en/function.stream-set-timeout.php
     *
     * @return bool
     */
    protected function streamSetTimeout()
    {
        $seconds = floor($this->timeout);
        $microseconds = round(($this->timeout - $seconds) * 1000000.0);
        if (!is_resource($this->resource)) {
            throw new \LogicException('streamSetTimeout called but $this->resource is not a resource');
        }
        return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds);
    }
    /**
     * Wrapper to allow mocking
     *
     * @see http://php.net/manual/en/function.stream-set-chunk-size.php
     *
     * @return (int | bool)
     */
    protected function streamSetChunkSize()
    {
        if (!is_resource($this->resource)) {
            throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource');
        }
        if (null === $this->chunkSize) {
            throw new \LogicException('streamSetChunkSize called but $this->chunkSize is not set');
        }
        return stream_set_chunk_size($this->resource, $this->chunkSize);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return (int | bool)
     */
    protected function fwrite(string $data)
    {
        if (!is_resource($this->resource)) {
            throw new \LogicException('fwrite called but $this->resource is not a resource');
        }
        return @fwrite($this->resource, $data);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return (mixed[] | bool)
     */
    protected function streamGetMetadata()
    {
        if (!is_resource($this->resource)) {
            throw new \LogicException('streamGetMetadata called but $this->resource is not a resource');
        }
        return stream_get_meta_data($this->resource);
    }
    /**
     *
     */
    private function validateTimeout(float $value) : void
    {
        if ($value < 0) {
            throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got {$value})");
        }
    }
    /**
     *
     */
    private function connectIfNotConnected() : void
    {
        if ($this->isConnected()) {
            return;
        }
        $this->connect();
    }
    /**
     * @phpstan-param FormattedRecord $record
     */
    protected function generateDataStream(array $record) : string
    {
        return (string) $record['formatted'];
    }
    /**
     * @return (resource | null)
     */
    protected function getResource()
    {
        return $this->resource;
    }
    /**
     *
     */
    private function connect() : void
    {
        $this->createSocketResource();
        $this->setSocketTimeout();
        $this->setStreamChunkSize();
    }
    /**
     *
     */
    private function createSocketResource() : void
    {
        if ($this->isPersistent()) {
            $resource = $this->pfsockopen();
        } else {
            $resource = $this->fsockopen();
        }
        if (is_bool($resource)) {
            throw new \UnexpectedValueException("Failed connecting to {$this->connectionString} ({$this->errno}: {$this->errstr})");
        }
        $this->resource = $resource;
    }
    /**
     *
     */
    private function setSocketTimeout() : void
    {
        if (!$this->streamSetTimeout()) {
            throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()");
        }
    }
    /**
     *
     */
    private function setStreamChunkSize() : void
    {
        if ($this->chunkSize && !$this->streamSetChunkSize()) {
            throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
        }
    }
    /**
     *
     */
    private function writeToSocket(string $data) : void
    {
        $length = strlen($data);
        $sent = 0;
        $this->lastSentBytes = $sent;
        while ($this->isConnected() && $sent < $length) {
            if (0 == $sent) {
                $chunk = $this->fwrite($data);
            } else {
                $chunk = $this->fwrite(\Phabel\Target\Php80\Polyfill::substr($data, $sent));
            }
            if ($chunk === false) {
                throw new \RuntimeException("Could not write to socket");
            }
            $sent += $chunk;
            $socketInfo = $this->streamGetMetadata();
            if (is_array($socketInfo) && $socketInfo['timed_out']) {
                throw new \RuntimeException("Write timed-out");
            }
            if ($this->writingIsTimedOut($sent)) {
                throw new \RuntimeException("Write timed-out, no data sent for `{$this->writingTimeout}` seconds, probably we got disconnected (sent {$sent} of {$length})");
            }
        }
        if (!$this->isConnected() && $sent < $length) {
            throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent {$sent} of {$length})");
        }
    }
    /**
     *
     */
    private function writingIsTimedOut(int $sent) : bool
    {
        // convert to ms
        if (0.0 == $this->writingTimeout) {
            return false;
        }
        if ($sent !== $this->lastSentBytes) {
            $this->lastWritingAt = microtime(true);
            $this->lastSentBytes = $sent;
            return false;
        } else {
            usleep(100);
        }
        if (microtime(true) - $this->lastWritingAt >= $this->writingTimeout) {
            $this->closeSocket();
            return true;
        }
        return false;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use DateTimeInterface;
use Monolog\Logger;
use Monolog\Handler\SyslogUdp\UdpSocket;
use Monolog\Utils;
/**
 * A Handler for logging to a remote syslogd server.
 *
 * @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com>
 * @author Dominik Kukacka <dominik.kukacka@gmail.com>
 */
class SyslogUdpHandler extends AbstractSyslogHandler
{
    const RFC3164 = 0;
    const RFC5424 = 1;
    const RFC5424e = 2;
    /** @var array<self::RFC*, string> */
    private $dateFormats = array(self::RFC3164 => 'M d H:i:s', self::RFC5424 => \DateTime::RFC3339, self::RFC5424e => \DateTime::RFC3339_EXTENDED);
    /** @var UdpSocket */
    protected $socket;
    /** @var string */
    protected $ident;
    /** @var self::RFC* */
    protected $rfc;
    /**
     * @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then)
     * @param int $port Port number, or 0 if $host is a unix socket
     * @param (string | int) $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     * @param string $ident Program name or tag for each log message.
     * @param int $rfc RFC to format the message for.
     * @throws MissingExtensionException
     *
     * @phpstan-param self::RFC* $rfc
     */
    public function __construct(string $host, int $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, string $ident = 'php', int $rfc = self::RFC5424)
    {
        if (!extension_loaded('sockets')) {
            throw new MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler');
        }
        parent::__construct($facility, $level, $bubble);
        $this->ident = $ident;
        $this->rfc = $rfc;
        $this->socket = new UdpSocket($host, $port);
    }
    /**
     *
     */
    protected function write(array $record) : void
    {
        $lines = $this->splitMessageIntoLines($record['formatted']);
        $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']], $record['datetime']);
        foreach ($lines as $line) {
            $this->socket->write($line, $header);
        }
    }
    /**
     *
     */
    public function close() : void
    {
        $this->socket->close();
    }
    /**
     * @param (string | string[]) $message
     * @return string[]
     */
    private function splitMessageIntoLines($message) : array
    {
        if (is_array($message)) {
            $message = implode("\n", $message);
        }
        $lines = preg_split('/$\\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY);
        if (false === $lines) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
        }
        return $lines;
    }
    /**
     * Make common syslog header (see rfc5424 or rfc3164)
     */
    protected function makeCommonSyslogHeader(int $severity, DateTimeInterface $datetime) : string
    {
        $priority = $severity + $this->facility;
        if (!($pid = getmypid())) {
            $pid = '-';
        }
        if (!($hostname = gethostname())) {
            $hostname = '-';
        }
        if ($this->rfc === self::RFC3164) {
            // see https://github.com/phpstan/phpstan/issues/5348
            // @phpstan-ignore-next-line
            $dateNew = $datetime->setTimezone(new \DateTimeZone('UTC'));
            $date = $dateNew->format($this->dateFormats[$this->rfc]);
            return "<{$priority}>" . $date . " " . $hostname . " " . $this->ident . "[" . $pid . "]: ";
        }
        $date = $datetime->format($this->dateFormats[$this->rfc]);
        return "<{$priority}>1 " . $date . " " . $hostname . " " . $this->ident . " " . $pid . " - - ";
    }
    /**
     * Inject your own socket, mainly used for testing
     */
    public function setSocket(UdpSocket $socket) : self
    {
        $this->socket = $socket;
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * Stores to STDIN of any process, specified by a command.
 *
 * Usage example:
 * <pre>
 * $log = new Logger('myLogger');
 * $log->pushHandler(new ProcessHandler('/usr/bin/php /var/www/monolog/someScript.php'));
 * </pre>
 *
 * @author Kolja Zuelsdorf <koljaz@web.de>
 */
class ProcessHandler extends AbstractProcessingHandler
{
    /**
     * Holds the process to receive data on its STDIN.
     *
     * @var resource|bool|null
     */
    private $process;
    /**
     * @var string
     */
    private $command;
    /**
     * @var string|null
     */
    private $cwd;
    /**
     * @var resource[]
     */
    private $pipes = [];
    /**
     * @var array<int, string[]>
     */
    protected const DESCRIPTOR_SPEC = [
        0 => ['pipe', 'r'],
        // STDIN is a pipe that the child will read from
        1 => ['pipe', 'w'],
        // STDOUT is a pipe that the child will write to
        2 => ['pipe', 'w'],
    ];
    /**
    * @param string $command Command for the process to start. Absolute paths are recommended,
    especially if you do not use the $cwd parameter.
    * @param (string | null) $cwd "Current working directory" (CWD) for the process to be executed in.
    * @throws \InvalidArgumentException
    */
    public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, ?string $cwd = null)
    {
        if ($command === '') {
            throw new \InvalidArgumentException('The command argument must be a non-empty string.');
        }
        if ($cwd === '') {
            throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.');
        }
        parent::__construct($level, $bubble);
        $this->command = $command;
        $this->cwd = $cwd;
    }
    /**
     * Writes the record down to the log of the implementing handler
     *
     * @throws \UnexpectedValueException
     */
    protected function write(array $record) : void
    {
        $this->ensureProcessIsStarted();
        $this->writeProcessInput($record['formatted']);
        $errors = $this->readProcessErrors();
        if (empty($errors) === false) {
            throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors));
        }
    }
    /**
    * Makes sure that the process is actually started, and if not, starts it,
    assigns the stream pipes, and handles startup errors, if any.
    */
    private function ensureProcessIsStarted() : void
    {
        if (is_resource($this->process) === false) {
            $this->startProcess();
            $this->handleStartupErrors();
        }
    }
    /**
     * Starts the actual process and sets all streams to non-blocking.
     */
    private function startProcess() : void
    {
        $this->process = proc_open($this->command, static::DESCRIPTOR_SPEC, $this->pipes, $this->cwd);
        foreach ($this->pipes as $pipe) {
            stream_set_blocking($pipe, false);
        }
    }
    /**
     * Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any.
     *
     * @throws \UnexpectedValueException
     */
    private function handleStartupErrors() : void
    {
        $selected = $this->selectErrorStream();
        if (false === $selected) {
            throw new \UnexpectedValueException('Something went wrong while selecting a stream.');
        }
        $errors = $this->readProcessErrors();
        if (is_resource($this->process) === false || empty($errors) === false) {
            throw new \UnexpectedValueException(sprintf('The process "%s" could not be opened: ' . $errors, $this->command));
        }
    }
    /**
     * Selects the STDERR stream.
     *
     * @return (int | bool)
     */
    protected function selectErrorStream()
    {
        $empty = [];
        $errorPipes = [$this->pipes[2]];
        return stream_select($errorPipes, $empty, $empty, 1);
    }
    /**
     * Reads the errors of the process, if there are any.
     *
     * @codeCoverageIgnore
     * @return string Empty string if there are no errors.
     */
    protected function readProcessErrors() : string
    {
        return (string) stream_get_contents($this->pipes[2]);
    }
    /**
     * Writes to the input stream of the opened process.
     *
     * @codeCoverageIgnore
     */
    protected function writeProcessInput(string $string) : void
    {
        fwrite($this->pipes[0], $string);
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        if (is_resource($this->process)) {
            foreach ($this->pipes as $pipe) {
                fclose($pipe);
            }
            proc_close($this->process);
            $this->process = null;
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * @author Robert Kaufmann III <rok3@rok3.me>
 */
class LogEntriesHandler extends SocketHandler
{
    /**
     * @var string
     */
    protected $logToken;
    /**
     * @param string $token Log token supplied by LogEntries
     * @param bool $useSSL Whether or not SSL encryption should be used.
     * @param string $host Custom hostname to send the data to if needed
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true, string $host = 'data.logentries.com')
    {
        if ($useSSL && !extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
        }
        $endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80';
        parent::__construct($endpoint, $level, $bubble);
        $this->logToken = $token;
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        return $this->logToken . ' ' . $record['formatted'];
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\ResettableInterface;
/**
 * Forwards records to multiple handlers
 *
 * @author Lenar LÃµhmus <lenar@city.ee>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface
{
    use ProcessableHandlerTrait;
    /** @var HandlerInterface[] */
    protected $handlers;
    /** @var bool */
    protected $bubble;
    /**
     * @param HandlerInterface[] $handlers Array of Handlers.
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct(array $handlers, bool $bubble = true)
    {
        foreach ($handlers as $handler) {
            if (!$handler instanceof HandlerInterface) {
                throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.');
            }
        }
        $this->handlers = $handlers;
        $this->bubble = $bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($record)) {
                return true;
            }
        }
        return false;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            $handler->handle($record);
        }
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if ($this->processors) {
            $processed = [];
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            /** @var Record[] $records */
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            $handler->handleBatch($records);
        }
    }
    /**
     *
     */
    public function reset()
    {
        $this->resetProcessors();
        foreach ($this->handlers as $handler) {
            if ($handler instanceof ResettableInterface) {
                $handler->reset();
            }
        }
    }
    /**
     *
     */
    public function close() : void
    {
        parent::close();
        foreach ($this->handlers as $handler) {
            $handler->close();
        }
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        foreach ($this->handlers as $handler) {
            if ($handler instanceof FormattableHandlerInterface) {
                $handler->setFormatter($formatter);
            }
        }
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * Inspired on LogEntriesHandler.
 *
 * @author Robert Kaufmann III <rok3@rok3.me>
 * @author Gabriel Machado <gabriel.ms1@hotmail.com>
 */
class InsightOpsHandler extends SocketHandler
{
    /**
     * @var string
     */
    protected $logToken;
    /**
     * @param string $token Log token supplied by InsightOps
     * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
     * @param bool $useSSL Whether or not SSL encryption should be used
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, string $region = 'us', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true)
    {
        if ($useSSL && !extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler');
        }
        $endpoint = $useSSL ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443' : $region . '.data.logs.insight.rapid7.com:80';
        parent::__construct($endpoint, $level, $bubble);
        $this->logToken = $token;
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        return $this->logToken . ' ' . $record['formatted'];
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
/**
 * Sampling handler
 *
 * A sampled event stream can be useful for logging high frequency events in
 * a production environment where you only need an idea of what is happening
 * and are not concerned with capturing every occurrence. Since the decision to
 * handle or not handle a particular event is determined randomly, the
 * resulting sampled log is not guaranteed to contain 1/N of the events that
 * occurred in the application, but based on the Law of large numbers, it will
 * tend to be close to this ratio with a large number of attempts.
 *
 * @author Bryan Davis <bd808@wikimedia.org>
 * @author Kunal Mehta <legoktm@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * @var HandlerInterface|callable
     * @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface
     */
    protected $handler;
    /**
     * @var int $factor
     */
    protected $factor;
    /**
     * @psalm-param (HandlerInterface | callable((Record | array{level: Level} | null) , HandlerInterface ): HandlerInterface) $handler
     *
     * @param (callable | HandlerInterface) $handler Handler or factory callable($record|null, $samplingHandler).
     * @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled)
     */
    public function __construct($handler, int $factor)
    {
        parent::__construct();
        $this->handler = $handler;
        $this->factor = $factor;
        if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
            throw new \RuntimeException("The given handler (" . json_encode($this->handler) . ") is not a callable nor a Monolog\\Handler\\HandlerInterface object");
        }
    }
    /**
     *
     */
    public function isHandling(array $record) : bool
    {
        return $this->getHandler($record)->isHandling($record);
    }
    /**
     *
     */
    public function handle(array $record) : bool
    {
        if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
            if ($this->processors) {
                /** @var Record $record */
                $record = $this->processRecord($record);
            }
            $this->getHandler($record)->handle($record);
        }
        return false === $this->bubble;
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory callable, this will trigger the handler's instantiation.
     *
     * @phpstan-param (Record | array{level: Level} | null) $record
     *
     * @return HandlerInterface
     */
    public function getHandler(array $record = null)
    {
        if (!$this->handler instanceof HandlerInterface) {
            $this->handler = ($this->handler)($record, $this);
            if (!$this->handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory callable should return a HandlerInterface");
            }
        }
        return $this->handler;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
/**
 * NativeMailerHandler uses the mail() function to send the emails
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Mark Garrett <mark@moderndeveloperllc.com>
 */
class NativeMailerHandler extends MailHandler
{
    /**
     * The email addresses to which the message will be sent
     * @var string[]
     */
    protected $to;
    /**
     * The subject of the email
     * @var string
     */
    protected $subject;
    /**
     * Optional headers for the message
     * @var string[]
     */
    protected $headers = [];
    /**
     * Optional parameters for the message
     * @var string[]
     */
    protected $parameters = [];
    /**
     * The wordwrap length for the message
     * @var int
     */
    protected $maxColumnWidth;
    /**
     * The Content-type for the message
     * @var string|null
     */
    protected $contentType;
    /**
     * The encoding for the message
     * @var string
     */
    protected $encoding = 'utf-8';
    /**
     * @param (string | string[]) $to The receiver of the mail
     * @param string $subject The subject of the mail
     * @param string $from The sender of the mail
     * @param int $maxColumnWidth The maximum column width that the message lines will have
     */
    public function __construct($to, string $subject, string $from, $level = Logger::ERROR, bool $bubble = true, int $maxColumnWidth = 70)
    {
        parent::__construct($level, $bubble);
        $this->to = (array) $to;
        $this->subject = $subject;
        $this->addHeader(sprintf('From: %s', $from));
        $this->maxColumnWidth = $maxColumnWidth;
    }
    /**
     * Add headers to the message
     *
     * @param (string | string[]) $headers Custom added headers
     */
    public function addHeader($headers) : self
    {
        foreach ((array) $headers as $header) {
            if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) {
                throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons');
            }
            $this->headers[] = $header;
        }
        return $this;
    }
    /**
     * Add parameters to the message
     *
     * @param (string | string[]) $parameters Custom added parameters
     */
    public function addParameter($parameters) : self
    {
        $this->parameters = array_merge($this->parameters, (array) $parameters);
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records) : void
    {
        $contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
        if ($contentType !== 'text/html') {
            $content = wordwrap($content, $this->maxColumnWidth);
        }
        $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n");
        $headers .= 'Content-type: ' . $contentType . '; charset=' . $this->getEncoding() . "\r\n";
        if ($contentType === 'text/html' && false === strpos($headers, 'MIME-Version:')) {
            $headers .= 'MIME-Version: 1.0
';
        }
        $subject = $this->subject;
        if ($records) {
            $subjectFormatter = new LineFormatter($this->subject);
            $subject = $subjectFormatter->format($this->getHighestRecord($records));
        }
        $parameters = implode(' ', $this->parameters);
        foreach ($this->to as $to) {
            mail($to, $subject, $content, $headers, $parameters);
        }
    }
    /**
     *
     */
    public function getContentType() : ?string
    {
        return $this->contentType;
    }
    /**
     *
     */
    public function getEncoding() : string
    {
        return $this->encoding;
    }
    /**
     * @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML messages.
     */
    public function setContentType(string $contentType) : self
    {
        if (strpos($contentType, "\n") !== false || strpos($contentType, "\r") !== false) {
            throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection');
        }
        $this->contentType = $contentType;
        return $this;
    }
    /**
     *
     */
    public function setEncoding(string $encoding) : self
    {
        if (strpos($encoding, "\n") !== false || strpos($encoding, "\r") !== false) {
            throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection');
        }
        $this->encoding = $encoding;
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\ChromePHPFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
/**
 * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
 *
 * This also works out of the box with Firefox 43+
 *
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class ChromePHPHandler extends AbstractProcessingHandler
{
    use WebRequestRecognizerTrait;
    /**
     * Version of the extension
     */
    protected const VERSION = '4.0';
    /**
     * Header name
     */
    protected const HEADER_NAME = 'X-ChromeLogger-Data';
    /**
     * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
     */
    protected const USER_AGENT_REGEX = '{\\b(?:Chrome/\\d+(?:\\.\\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\\d|\\d{3,})(?:\\.\\d)*)\\b}';
    /** @var bool */
    protected static $initialized = false;
    /**
     * Tracks whether we sent too much data
     *
     * Chrome limits the headers to 4KB, so when we sent 3KB we stop sending
     *
     * @var bool
     */
    protected static $overflowed = false;
    /** @var mixed[] */
    protected static $json = ['version' => self::VERSION, 'columns' => ['label', 'log', 'backtrace', 'type'], 'rows' => []];
    /** @var bool */
    protected static $sendHeaders = true;
    /**
     *
     */
    public function __construct($level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        if (!function_exists('json_encode')) {
            throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s ChromePHPHandler');
        }
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if (!$this->isWebRequest()) {
            return;
        }
        $messages = [];
        foreach ($records as $record) {
            if ($record['level'] < $this->level) {
                continue;
            }
            /** @var Record $message */
            $message = $this->processRecord($record);
            $messages[] = $message;
        }
        if (!empty($messages)) {
            $messages = $this->getFormatter()->formatBatch($messages);
            self::$json['rows'] = array_merge(self::$json['rows'], $messages);
            $this->send();
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new ChromePHPFormatter();
    }
    /**
     * Creates & sends header for a record
     *
     * @see sendHeader()
     * @see send()
     */
    protected function write(array $record) : void
    {
        if (!$this->isWebRequest()) {
            return;
        }
        self::$json['rows'][] = $record['formatted'];
        $this->send();
    }
    /**
     * Sends the log header
     *
     * @see sendHeader()
     */
    protected function send() : void
    {
        if (self::$overflowed || !self::$sendHeaders) {
            return;
        }
        if (!self::$initialized) {
            self::$initialized = true;
            self::$sendHeaders = $this->headersAccepted();
            if (!self::$sendHeaders) {
                return;
            }
            self::$json['request_uri'] = $_SERVER['REQUEST_URI'] ?? '';
        }
        $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true);
        $data = base64_encode(utf8_encode($json));
        if (strlen($data) > 3 * 1024) {
            self::$overflowed = true;
            $record = ['message' => 'Incomplete logs, chrome header size limit reached', 'context' => [], 'level' => Logger::WARNING, 'level_name' => Logger::getLevelName(Logger::WARNING), 'channel' => 'monolog', 'datetime' => new \DateTimeImmutable(), 'extra' => []];
            self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
            $json = Utils::jsonEncode(self::$json, null, true);
            $data = base64_encode(utf8_encode($json));
        }
        if (trim($data) !== '') {
            $this->sendHeader(static::HEADER_NAME, $data);
        }
    }
    /**
     * Send header string to the client
     */
    protected function sendHeader(string $header, string $content) : void
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }
    /**
     * Verifies if the headers are accepted by the current user agent
     */
    protected function headersAccepted() : bool
    {
        if (empty($_SERVER['HTTP_USER_AGENT'])) {
            return false;
        }
        return preg_match(static::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Monolog\Logger;
/**
 * Sends logs to Fleep.io using Webhook integrations
 *
 * You'll need a Fleep.io account to use this handler.
 *
 * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation
 * @author Ando Roots <ando@sqroot.eu>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class FleepHookHandler extends SocketHandler
{
    protected const FLEEP_HOST = 'fleep.io';
    protected const FLEEP_HOOK_URI = '/hook/';
    /**
     * @var string Webhook token (specifies the conversation where logs are sent)
     */
    protected $token;
    /**
    * Construct a new Fleep.io Handler.
    *
    * For instructions on how to create a new web hook in your conversations
    see https://fleep.io/integrations/webhooks/
    *
    * @param string $token Webhook token
    * @throws MissingExtensionException
    */
    public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler');
        }
        $this->token = $token;
        $connectionString = 'ssl://' . static::FLEEP_HOST . ':443';
        parent::__construct($connectionString, $level, $bubble);
    }
    /**
     * Returns the default formatter to use with this handler
     *
     * Overloaded to remove empty context and extra arrays from the end of the log message.
     *
     * @return LineFormatter
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter(null, null, true, true);
    }
    /**
     * Handles a log record
     */
    public function write(array $record) : void
    {
        parent::write($record);
        $this->closeSocket();
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content) : string
    {
        $header = "POST " . static::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n";
        $header .= "Host: " . static::FLEEP_HOST . "\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    /**
     * Builds the body of API call
     *
     * @phpstan-param FormattedRecord $record
     */
    private function buildContent(array $record) : string
    {
        $dataArray = ['message' => $record['formatted']];
        return http_build_query($dataArray);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\HtmlFormatter;
/**
 * Base class for all mail handlers
 *
 * @author Gyula Sallai
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
abstract class MailHandler extends AbstractProcessingHandler
{
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $messages = [];
        foreach ($records as $record) {
            if ($record['level'] < $this->level) {
                continue;
            }
            /** @var Record $message */
            $message = $this->processRecord($record);
            $messages[] = $message;
        }
        if (!empty($messages)) {
            $this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
        }
    }
    /**
     * Send a mail with the given content
     *
     * @param string $content formatted email body to be sent
     * @param array $records the array of log records that formed this content
     *
     * @phpstan-param Record[] $records
     */
    protected abstract function send(string $content, array $records) : void;
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->send((string) $record['formatted'], [$record]);
    }
    /**
     * @phpstan-param non-empty-array<Record> $records
     * @phpstan-return Record
     */
    protected function getHighestRecord(array $records) : array
    {
        $highestRecord = null;
        foreach ($records as $record) {
            if ($highestRecord === null || $highestRecord['level'] < $record['level']) {
                $highestRecord = $record;
            }
        }
        return $highestRecord;
    }
    /**
     *
     */
    protected function isHtmlBody(string $body) : bool
    {
        return ($body[0] ?? null) === '<';
    }
    /**
     * Gets the default formatter.
     *
     * @return FormatterInterface
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new HtmlFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use RuntimeException;
use Monolog\Logger;
/**
 * Handler send logs to Telegram using Telegram Bot API.
 *
 * How to use:
 *  1) Create telegram bot with https://telegram.me/BotFather
 *  2) Create a telegram channel where logs will be recorded.
 *  3) Add created bot from step 1 to the created channel from step 2.
 *
 * Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler
 *
 * @link https://core.telegram.org/bots/api
 *
 * @author Mazur Alexandr <alexandrmazur96@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class TelegramBotHandler extends AbstractProcessingHandler
{
    private const BOT_API = 'https://api.telegram.org/bot';
    /**
     * The available values of parseMode according to the Telegram api documentation
     */
    private const AVAILABLE_PARSE_MODES = ['HTML', 'MarkdownV2', 'Markdown'];
    /**
     * Telegram bot access token provided by BotFather.
     * Create telegram bot with https://telegram.me/BotFather and use access token from it.
     * @var string
     */
    private $apiKey;
    /**
     * Telegram channel name.
     * Since to start with '@' symbol as prefix.
     * @var string
     */
    private $channel;
    /**
     * The kind of formatting that is used for the message.
     * See available options at https://core.telegram.org/bots/api#formatting-options
     * or in AVAILABLE_PARSE_MODES
     * @var ?string
     */
    private $parseMode;
    /**
     * Disables link previews for links in the message.
     * @var ?bool
     */
    private $disableWebPagePreview;
    /**
     * Sends the message silently. Users will receive a notification with no sound.
     * @var ?bool
     */
    private $disableNotification;
    /**
     * @param string $apiKey Telegram bot access token provided by BotFather
     * @param string $channel Telegram channel name
     */
    public function __construct(string $apiKey, string $channel, $level = Logger::DEBUG, bool $bubble = true, string $parseMode = null, bool $disableWebPagePreview = null, bool $disableNotification = null)
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler');
        }
        parent::__construct($level, $bubble);
        $this->apiKey = $apiKey;
        $this->channel = $channel;
        $this->setParseMode($parseMode);
        $this->disableWebPagePreview($disableWebPagePreview);
        $this->disableNotification($disableNotification);
    }
    /**
     *
     */
    public function setParseMode(string $parseMode = null) : self
    {
        if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) {
            throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.');
        }
        $this->parseMode = $parseMode;
        return $this;
    }
    /**
     *
     */
    public function disableWebPagePreview(bool $disableWebPagePreview = null) : self
    {
        $this->disableWebPagePreview = $disableWebPagePreview;
        return $this;
    }
    /**
     *
     */
    public function disableNotification(bool $disableNotification = null) : self
    {
        $this->disableNotification = $disableNotification;
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        /** @var Record[] $messages */
        $messages = [];
        foreach ($records as $record) {
            if (!$this->isHandling($record)) {
                continue;
            }
            if ($this->processors) {
                /** @var Record $record */
                $record = $this->processRecord($record);
            }
            $messages[] = $record;
        }
        if (!empty($messages)) {
            $this->send((string) $this->getFormatter()->formatBatch($messages));
        }
    }
    /**
     * @inheritDoc
     */
    protected function write(array $record) : void
    {
        $this->send($record['formatted']);
    }
    /**
     * Send request to @link https://api.telegram.org/bot on SendMessage action.
     * @param string $message
     */
    protected function send(string $message) : void
    {
        $ch = curl_init();
        $url = self::BOT_API . $this->apiKey . '/SendMessage';
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['text' => $message, 'chat_id' => $this->channel, 'parse_mode' => $this->parseMode, 'disable_web_page_preview' => $this->disableWebPagePreview, 'disable_notification' => $this->disableNotification]));
        $result = Curl\Util::execute($ch);
        if (!is_string($result)) {
            throw new RuntimeException('Telegram API error. Description: No response');
        }
        $result = json_decode($result, true);
        if ($result['ok'] === false) {
            throw new RuntimeException('Telegram API error. Description: ' . $result['description']);
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Base Handler class providing basic close() support as well as handleBatch
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
abstract class Handler implements HandlerInterface
{
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        foreach ($records as $record) {
            $this->handle($record);
        }
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
    }
    /**
     *
     */
    public function __destruct()
    {
        try {
            $this->close();
        } catch (\Throwable $e) {
            // do nothing
        }
    }
    /**
     *
     */
    public function __sleep()
    {
        $this->close();
        return array_keys(get_object_vars($this));
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Aws\Sqs\SqsClient;
use Monolog\Logger;
use Monolog\Utils;
/**
 * Writes to any sqs queue.
 *
 * @author Martijn van Calker <git@amvc.nl>
 */
class SqsHandler extends AbstractProcessingHandler
{
    /** 256 KB in bytes - maximum message size in SQS */
    protected const MAX_MESSAGE_SIZE = 262144;
    /** 100 KB in bytes - head message size for new error log */
    protected const HEAD_MESSAGE_SIZE = 102400;
    /** @var SqsClient */
    private $client;
    /** @var string */
    private $queueUrl;
    /**
     *
     */
    public function __construct(SqsClient $sqsClient, string $queueUrl, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->client = $sqsClient;
        $this->queueUrl = $queueUrl;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) {
            throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string');
        }
        $messageBody = $record['formatted'];
        if (strlen($messageBody) >= static::MAX_MESSAGE_SIZE) {
            $messageBody = Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE);
        }
        $this->client->sendMessage(['QueueUrl' => $this->queueUrl, 'MessageBody' => $messageBody]);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
/**
 * Logs to a Redis key using rpush
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod");
 *   $log->pushHandler($redis);
 *
 * @author Thomas Tourlourat <thomas@tourlourat.com>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class RedisHandler extends AbstractProcessingHandler
{
    /** @var \Predis\Client|\Redis */
    private $redisClient;
    /** @var string */
    private $redisKey;
    /** @var int */
    protected $capSize;
    /**
     * @param (\Predis\Client | \Redis) $redis The redis instance
     * @param string $key The key name to push records to
     * @param int $capSize Number of entries to limit list size to, 0 = unlimited
     */
    public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true, int $capSize = 0)
    {
        if (!($redis instanceof \Predis\Client || $redis instanceof \Redis)) {
            throw new \InvalidArgumentException('Predis\\Client or Redis instance required');
        }
        $this->redisClient = $redis;
        $this->redisKey = $key;
        $this->capSize = $capSize;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if ($this->capSize) {
            $this->writeCapped($record);
        } else {
            $this->redisClient->rpush($this->redisKey, $record["formatted"]);
        }
    }
    /**
    * Write and cap the collection
    Writes the record to the redis list and caps its
    *
    * @phpstan-param FormattedRecord $record
    */
    protected function writeCapped(array $record) : void
    {
        if ($this->redisClient instanceof \Redis) {
            $mode = defined('\\Redis::MULTI') ? \Redis::MULTI : 1;
            $this->redisClient->multi($mode)->rpush($this->redisKey, $record["formatted"])->ltrim($this->redisKey, -$this->capSize, -1)->exec();
        } else {
            $redisKey = $this->redisKey;
            $capSize = $this->capSize;
            $this->redisClient->transaction(function ($tx) use($record, $redisKey, $capSize) {
                $tx->rpush($redisKey, $record["formatted"]);
                $tx->ltrim($redisKey, -$capSize, -1);
            });
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Manager;
use MongoDB\Client;
use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\MongoDBFormatter;
/**
 * Logs to a MongoDB database.
 *
 * Usage example:
 *
 *   $log = new \Monolog\Logger('application');
 *   $client = new \MongoDB\Client('mongodb://localhost:27017');
 *   $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod');
 *   $log->pushHandler($mongodb);
 *
 * The above examples uses the MongoDB PHP library's client class; however, the
 * MongoDB\Driver\Manager class from ext-mongodb is also supported.
 */
class MongoDBHandler extends AbstractProcessingHandler
{
    /** @var \MongoDB\Collection */
    private $collection;
    /** @var Client|Manager */
    private $manager;
    /** @var string */
    private $namespace;
    /**
     * Constructor.
     *
     * @param (Client | Manager) $mongodb MongoDB library or driver client
     * @param string $database Database name
     * @param string $collection Collection name
     */
    public function __construct($mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!($mongodb instanceof Client || $mongodb instanceof Manager)) {
            throw new \InvalidArgumentException('MongoDB\\Client or MongoDB\\Driver\\Manager instance required');
        }
        if ($mongodb instanceof Client) {
            $this->collection = $mongodb->selectCollection($database, $collection);
        } else {
            $this->manager = $mongodb;
            $this->namespace = $database . '.' . $collection;
        }
        parent::__construct($level, $bubble);
    }
    /**
     *
     */
    protected function write(array $record) : void
    {
        if (isset($this->collection)) {
            $this->collection->insertOne($record['formatted']);
        }
        if (isset($this->manager, $this->namespace)) {
            $bulk = new BulkWrite();
            $bulk->insert($record["formatted"]);
            $this->manager->executeBulkWrite($this->namespace, $bulk);
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new MongoDBFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\FlowdockFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Sends notifications through the Flowdock push API
 *
 * This must be configured with a FlowdockFormatter instance via setFormatter()
 *
 * Notes:
 * API token - Flowdock API token
 *
 * @author Dominik Liebler <liebler.dominik@gmail.com>
 * @see https://www.flowdock.com/api/push
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class FlowdockHandler extends SocketHandler
{
    /**
     * @var string
     */
    protected $apiToken;
    /**
     * @throws MissingExtensionException if OpenSSL is missing
     */
    public function __construct(string $apiToken, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler');
        }
        parent::__construct('ssl://api.flowdock.com:443', $level, $bubble);
        $this->apiToken = $apiToken;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if (!$formatter instanceof FlowdockFormatter) {
            throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\\Formatter\\FlowdockFormatter to function correctly');
        }
        return parent::setFormatter($formatter);
    }
    /**
     * Gets the default formatter.
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\\Formatter\\FlowdockFormatter to function correctly');
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        parent::write($record);
        $this->closeSocket();
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the body of API call
     *
     * @phpstan-param FormattedRecord $record
     */
    private function buildContent(array $record) : string
    {
        return Utils::jsonEncode($record['formatted']['flowdock']);
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content) : string
    {
        $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n";
        $header .= "Host: api.flowdock.com\r\n";
        $header .= "Content-Type: application/json\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
/**
 * Logs to Cube.
 *
 * @link http://square.github.com/cube/
 * @author Wan Chen <kami@kamisama.me>
 */
class CubeHandler extends AbstractProcessingHandler
{
    /** @var resource|\Socket|null */
    private $udpConnection = null;
    /** @var resource|\CurlHandle|null */
    private $httpConnection = null;
    /** @var string */
    private $scheme;
    /** @var string */
    private $host;
    /** @var int */
    private $port;
    /** @var string[] */
    private $acceptedSchemes = ['http', 'udp'];
    /**
    * Create a Cube handler
    *
    * @throws \UnexpectedValueException when given url is not a valid url.
    A valid url must consist of three parts : protocol://host:port
    Only valid protocols used by Cube are http and udp
    */
    public function __construct(string $url, $level = Logger::DEBUG, bool $bubble = true)
    {
        $urlInfo = parse_url($url);
        if ($urlInfo === false || !isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
            throw new \UnexpectedValueException('URL "' . $url . '" is not valid');
        }
        if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) {
            throw new \UnexpectedValueException('Invalid protocol (' . $urlInfo['scheme'] . '). Valid options are ' . implode(', ', $this->acceptedSchemes));
        }
        $this->scheme = $urlInfo['scheme'];
        $this->host = $urlInfo['host'];
        $this->port = (int) $urlInfo['port'];
        parent::__construct($level, $bubble);
    }
    /**
     * Establish a connection to an UDP socket
     *
     * @throws \LogicException when unable to connect to the socket
     * @throws MissingExtensionException when there is no socket extension
     */
    protected function connectUdp() : void
    {
        if (!extension_loaded('sockets')) {
            throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
        }
        $udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0);
        if (false === $udpConnection) {
            throw new \LogicException('Unable to create a socket');
        }
        $this->udpConnection = $udpConnection;
        if (!socket_connect($this->udpConnection, $this->host, $this->port)) {
            throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
        }
    }
    /**
     * Establish a connection to an http server
     *
     * @throws \LogicException when unable to connect to the socket
     * @throws MissingExtensionException when no curl extension
     */
    protected function connectHttp() : void
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is required to use http URLs with the CubeHandler');
        }
        $httpConnection = curl_init('http://' . $this->host . ':' . $this->port . '/1.0/event/put');
        if (false === $httpConnection) {
            throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
        }
        $this->httpConnection = $httpConnection;
        curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $date = $record['datetime'];
        $data = ['time' => $date->format('Y-m-d\\TH:i:s.uO')];
        unset($record['datetime']);
        if (isset($record['context']['type'])) {
            $data['type'] = $record['context']['type'];
            unset($record['context']['type']);
        } else {
            $data['type'] = $record['channel'];
        }
        $data['data'] = $record['context'];
        $data['data']['level'] = $record['level'];
        if ($this->scheme === 'http') {
            $this->writeHttp(Utils::jsonEncode($data));
        } else {
            $this->writeUdp(Utils::jsonEncode($data));
        }
    }
    /**
     *
     */
    private function writeUdp(string $data) : void
    {
        if (!$this->udpConnection) {
            $this->connectUdp();
        }
        socket_send($this->udpConnection, $data, strlen($data), 0);
    }
    /**
     *
     */
    private function writeHttp(string $data) : void
    {
        if (!$this->httpConnection) {
            $this->connectHttp();
        }
        if (null === $this->httpConnection) {
            throw new \LogicException('No connection could be established');
        }
        curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '[' . $data . ']');
        curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . strlen('[' . $data . ']')]);
        Curl\Util::execute($this->httpConnection, 5, false);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Processor\ProcessorInterface;
/**
 * Interface to describe loggers that have processors
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
interface ProcessableHandlerInterface
{
    /**
     * Adds a processor in the stack.
     *
     * @psalm-param (ProcessorInterface | callable(Record ): Record) $callback
     *
     * @param (ProcessorInterface | callable) $callback
     * @return HandlerInterface self
     */
    public function pushProcessor(callable $callback) : HandlerInterface;
    /**
     * Removes the processor on top of the stack and returns it.
     *
     * @psalm-return (ProcessorInterface | callable(Record ): Record) $callback
     *
     * @throws \LogicException In case the processor stack is empty
     * @return (callable | ProcessorInterface)
     */
    public function popProcessor() : callable;
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
/**
 * Stores to any stream resource
 *
 * Can be used to store into php://stderr, remote and local files, etc.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class StreamHandler extends AbstractProcessingHandler
{
    /** @const int */
    protected const MAX_CHUNK_SIZE = 2147483647;
    /** @const int 10MB */
    protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024;
    /** @var int */
    protected $streamChunkSize;
    /** @var resource|null */
    protected $stream;
    /** @var ?string */
    protected $url = null;
    /** @var ?string */
    private $errorMessage = null;
    /** @var ?int */
    protected $filePermission;
    /** @var bool */
    protected $useLocking;
    /** @var true|null */
    private $dirCreated = null;
    /**
     * @param (resource | string) $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write
     * @param (int | null) $filePermission Optional file permissions (default (0644) are only for owner read/write)
     * @param bool $useLocking Try to lock log file before doing any writes
     *
     * @throws \InvalidArgumentException If stream is not a resource or string
     */
    public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false)
    {
        parent::__construct($level, $bubble);
        if (($phpMemoryLimit = Utils::expandIniShorthandBytes(ini_get('memory_limit'))) !== false) {
            if ($phpMemoryLimit > 0) {
                // use max 10% of allowed memory for the chunk size, and at least 100KB
                $this->streamChunkSize = min(static::MAX_CHUNK_SIZE, max((int) ($phpMemoryLimit / 10), 100 * 1024));
            } else {
                // memory is unlimited, set to the default 10MB
                $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
            }
        } else {
            // no memory limit information, set to the default 10MB
            $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
        }
        if (is_resource($stream)) {
            $this->stream = $stream;
            stream_set_chunk_size($this->stream, $this->streamChunkSize);
        } elseif (is_string($stream)) {
            $this->url = Utils::canonicalizePath($stream);
        } else {
            throw new \InvalidArgumentException('A stream must either be a resource or a string.');
        }
        $this->filePermission = $filePermission;
        $this->useLocking = $useLocking;
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        if ($this->url && is_resource($this->stream)) {
            fclose($this->stream);
        }
        $this->stream = null;
        $this->dirCreated = null;
    }
    /**
     * Return the currently active stream if it is open
     *
     * @return (resource | null)
     */
    public function getStream()
    {
        return $this->stream;
    }
    /**
     * Return the stream URL if it was configured with a URL and not an active resource
     *
     * @return (string | null)
     */
    public function getUrl() : ?string
    {
        return $this->url;
    }
    /**
     * @return int
     */
    public function getStreamChunkSize() : int
    {
        return $this->streamChunkSize;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!is_resource($this->stream)) {
            $url = $this->url;
            if (null === $url || '' === $url) {
                throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
            }
            $this->createDir($url);
            $this->errorMessage = null;
            set_error_handler([$this, 'customErrorHandler']);
            $stream = fopen($url, 'a');
            if ($this->filePermission !== null) {
                @chmod($url, $this->filePermission);
            }
            restore_error_handler();
            if (!is_resource($stream)) {
                $this->stream = null;
                throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: ' . $this->errorMessage, $url));
            }
            stream_set_chunk_size($stream, $this->streamChunkSize);
            $this->stream = $stream;
        }
        $stream = $this->stream;
        if (!is_resource($stream)) {
            throw new \LogicException('No stream was opened yet');
        }
        if ($this->useLocking) {
            // ignoring errors here, there's not much we can do about them
            flock($stream, LOCK_EX);
        }
        $this->streamWrite($stream, $record);
        if ($this->useLocking) {
            flock($stream, LOCK_UN);
        }
    }
    /**
     * Write to stream
     * @param resource $stream
     * @param array $record
     *
     * @phpstan-param FormattedRecord $record
     */
    protected function streamWrite($stream, array $record) : void
    {
        fwrite($stream, (string) $record['formatted']);
    }
    /**
     *
     */
    private function customErrorHandler(int $code, string $msg) : bool
    {
        $this->errorMessage = preg_replace('{^(fopen|mkdir)\\(.*?\\): }', '', $msg);
        return true;
    }
    /**
     *
     */
    private function getDirFromStream(string $stream) : ?string
    {
        $pos = strpos($stream, '://');
        if ($pos === false) {
            return dirname($stream);
        }
        if ('file://' === \Phabel\Target\Php80\Polyfill::substr($stream, 0, 7)) {
            return dirname(\Phabel\Target\Php80\Polyfill::substr($stream, 7));
        }
        return null;
    }
    /**
     *
     */
    private function createDir(string $url) : void
    {
        // Do not try to create dir if it has already been tried.
        if ($this->dirCreated) {
            return;
        }
        $dir = $this->getDirFromStream($url);
        if (null !== $dir && !is_dir($dir)) {
            $this->errorMessage = null;
            set_error_handler([$this, 'customErrorHandler']);
            $status = mkdir($dir, 0777, true);
            restore_error_handler();
            if (false === $status && !is_dir($dir)) {
                throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and it could not be created: ' . $this->errorMessage, $dir));
            }
        }
        $this->dirCreated = true;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\Curl;

use CurlHandle;
/**
 * This class is marked as internal and it is not under the BC promise of the package.
 *
 * @internal
 */
final class Util
{
    /** @var array<int> */
    private static $retriableErrorCodes = [CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT, CURLE_HTTP_NOT_FOUND, CURLE_READ_ERROR, CURLE_OPERATION_TIMEOUTED, CURLE_HTTP_POST_ERROR, CURLE_SSL_CONNECT_ERROR];
    /**
     * Executes a CURL request with optional retries and exception on failure
     *
     * @param (resource | CurlHandle) $ch curl handler
     * @param int $retries
     * @param bool $closeAfterDone
     * @return (bool | string) @see curl_exec
     */
    public static function execute($ch, int $retries = 5, bool $closeAfterDone = true)
    {
        while ($retries--) {
            $curlResponse = curl_exec($ch);
            if ($curlResponse === false) {
                $curlErrno = curl_errno($ch);
                if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) {
                    $curlError = curl_error($ch);
                    if ($closeAfterDone) {
                        curl_close($ch);
                    }
                    throw new \RuntimeException(sprintf('Curl error (code %d): %s', $curlErrno, $curlError));
                }
                continue;
            }
            if ($closeAfterDone) {
                curl_close($ch);
            }
            return $curlResponse;
        }
        return false;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Elastica\Document;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\ElasticaFormatter;
use Monolog\Logger;
use Elastica\Client;
use Elastica\Exception\ExceptionInterface;
/**
 * Elastic Search handler
 *
 * Usage example:
 *
 *    $client = new \Elastica\Client();
 *    $options = array(
 *        'index' => 'elastic_index_name',
 *        'type' => 'elastic_doc_type', Types have been removed in Elastica 7
 *    );
 *    $handler = new ElasticaHandler($client, $options);
 *    $log = new Logger('application');
 *    $log->pushHandler($handler);
 *
 * @author Jelle Vink <jelle.vink@gmail.com>
 */
class ElasticaHandler extends AbstractProcessingHandler
{
    /**
     * @var Client
     */
    protected $client;
    /**
     * @var mixed[] Handler config options
     */
    protected $options = [];
    /**
     * @param Client $client Elastica Client object
     * @param mixed[] $options Handler configuration
     */
    public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->client = $client;
        $this->options = array_merge([
            'index' => 'monolog',
            // Elastic index name
            'type' => 'record',
            // Elastic document type
            'ignore_error' => false,
        ], $options);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->bulkSend([$record['formatted']]);
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($formatter instanceof ElasticaFormatter) {
            return parent::setFormatter($formatter);
        }
        throw new \InvalidArgumentException('ElasticaHandler is only compatible with ElasticaFormatter');
    }
    /**
     * @return mixed[]
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new ElasticaFormatter($this->options['index'], $this->options['type']);
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $documents = $this->getFormatter()->formatBatch($records);
        $this->bulkSend($documents);
    }
    /**
     * Use Elasticsearch bulk API to send list of documents
     *
     * @param Document[] $documents
     *
     * @throws \RuntimeException
     */
    protected function bulkSend(array $documents) : void
    {
        try {
            $this->client->addDocuments($documents);
        } catch (ExceptionInterface $e) {
            if (!$this->options['ignore_error']) {
                throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e);
            }
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
/**
 * Handler to only pass log messages when a certain threshold of number of messages is reached.
 *
 * This can be useful in cases of processing a batch of data, but you're for example only interested
 * in case it fails catastrophically instead of a warning for 1 or 2 events. Worse things can happen, right?
 *
 * Usage example:
 *
 * ```
 *   $log = new Logger('application');
 *   $handler = new SomeHandler(...)
 *
 *   // Pass all warnings to the handler when more than 10 & all error messages when more then 5
 *   $overflow = new OverflowHandler($handler, [Logger::WARNING => 10, Logger::ERROR => 5]);
 *
 *   $log->pushHandler($overflow);
 *```
 *
 * @author Kris Buist <krisbuist@gmail.com>
 */
class OverflowHandler extends AbstractHandler implements FormattableHandlerInterface
{
    /** @var HandlerInterface */
    private $handler;
    /** @var int[] */
    private $thresholdMap = [Logger::DEBUG => 0, Logger::INFO => 0, Logger::NOTICE => 0, Logger::WARNING => 0, Logger::ERROR => 0, Logger::CRITICAL => 0, Logger::ALERT => 0, Logger::EMERGENCY => 0];
    /**
     * Buffer of all messages passed to the handler before the threshold was reached
     *
     * @var mixed[][]
     */
    private $buffer = [];
    /**
     * @param HandlerInterface $handler
     * @param int[] $thresholdMap Dictionary of logger level => threshold
     */
    public function __construct(HandlerInterface $handler, array $thresholdMap = [], $level = Logger::DEBUG, bool $bubble = true)
    {
        $this->handler = $handler;
        foreach ($thresholdMap as $thresholdLevel => $threshold) {
            $this->thresholdMap[$thresholdLevel] = $threshold;
        }
        parent::__construct($level, $bubble);
    }
    /**
    * Handles a record.
    *
    * All records may be passed to this method, and the handler should discard
    those that it does not want to handle.
    *
    * The return value of this function controls the bubbling process of the handler stack.
    Unless the bubbling is interrupted (by returning true), the Logger class will keep on
    calling further handlers in the stack with a given log record.
    *
    * {@inheritDoc}
    */
    public function handle(array $record) : bool
    {
        if ($record['level'] < $this->level) {
            return false;
        }
        $level = $record['level'];
        if (!isset($this->thresholdMap[$level])) {
            $this->thresholdMap[$level] = 0;
        }
        if ($this->thresholdMap[$level] > 0) {
            // The overflow threshold is not yet reached, so we're buffering the record and lowering the threshold by 1
            $this->thresholdMap[$level]--;
            $this->buffer[$level][] = $record;
            return false === $this->bubble;
        }
        if ($this->thresholdMap[$level] == 0) {
            // This current message is breaking the threshold. Flush the buffer and continue handling the current record
            foreach ($this->buffer[$level] ?? [] as $buffered) {
                $this->handler->handle($buffered);
            }
            $this->thresholdMap[$level]--;
            unset($this->buffer[$level]);
        }
        $this->handler->handle($record);
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($this->handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($this->handler) . ' does not support formatters.');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Class to record a log on a NewRelic application.
 * Enabling New Relic High Security mode may prevent capture of useful information.
 *
 * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted']
 *
 * @see https://docs.newrelic.com/docs/agents/php-agent
 * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
 */
class NewRelicHandler extends AbstractProcessingHandler
{
    /**
     * Name of the New Relic application that will receive logs from this handler.
     *
     * @var ?string
     */
    protected $appName;
    /**
     * Name of the current transaction
     *
     * @var ?string
     */
    protected $transactionName;
    /**
     * Some context and extra data is passed into the handler as arrays of values. Do we send them as is
     * (useful if we are using the API), or explode them for display on the NewRelic RPM website?
     *
     * @var bool
     */
    protected $explodeArrays;
    /**
     * {@inheritDoc}
     *
     * @param (string | null) $appName
     * @param bool $explodeArrays
     * @param (string | null) $transactionName
     */
    public function __construct($level = Logger::ERROR, bool $bubble = true, ?string $appName = null, bool $explodeArrays = false, ?string $transactionName = null)
    {
        parent::__construct($level, $bubble);
        $this->appName = $appName;
        $this->explodeArrays = $explodeArrays;
        $this->transactionName = $transactionName;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!$this->isNewRelicEnabled()) {
            throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
        }
        if ($appName = $this->getAppName($record['context'])) {
            $this->setNewRelicAppName($appName);
        }
        if ($transactionName = $this->getTransactionName($record['context'])) {
            $this->setNewRelicTransactionName($transactionName);
            unset($record['formatted']['context']['transaction_name']);
        }
        if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
            newrelic_notice_error($record['message'], $record['context']['exception']);
            unset($record['formatted']['context']['exception']);
        } else {
            newrelic_notice_error($record['message']);
        }
        if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) {
            foreach ($record['formatted']['context'] as $key => $parameter) {
                if (is_array($parameter) && $this->explodeArrays) {
                    foreach ($parameter as $paramKey => $paramValue) {
                        $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue);
                    }
                } else {
                    $this->setNewRelicParameter('context_' . $key, $parameter);
                }
            }
        }
        if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) {
            foreach ($record['formatted']['extra'] as $key => $parameter) {
                if (is_array($parameter) && $this->explodeArrays) {
                    foreach ($parameter as $paramKey => $paramValue) {
                        $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue);
                    }
                } else {
                    $this->setNewRelicParameter('extra_' . $key, $parameter);
                }
            }
        }
    }
    /**
     * Checks whether the NewRelic extension is enabled in the system.
     *
     * @return bool
     */
    protected function isNewRelicEnabled() : bool
    {
        return extension_loaded('newrelic');
    }
    /**
    * Returns the appname where this log should be sent. Each log can override the default appname, set in this
    handler's constructor, by providing the appname in it's context.
    *
    * @param mixed[] $context
    */
    protected function getAppName(array $context) : ?string
    {
        if (isset($context['appname'])) {
            return $context['appname'];
        }
        return $this->appName;
    }
    /**
    * Returns the name of the current transaction. Each log can override the default transaction name, set in this
    handler's constructor, by providing the transaction_name in it's context
    *
    * @param mixed[] $context
    */
    protected function getTransactionName(array $context) : ?string
    {
        if (isset($context['transaction_name'])) {
            return $context['transaction_name'];
        }
        return $this->transactionName;
    }
    /**
     * Sets the NewRelic application that should receive this log.
     */
    protected function setNewRelicAppName(string $appName) : void
    {
        newrelic_set_appname($appName);
    }
    /**
     * Overwrites the name of the current transaction
     */
    protected function setNewRelicTransactionName(string $transactionName) : void
    {
        newrelic_name_transaction($transactionName);
    }
    /**
     * @param string $key
     * @param mixed $value
     */
    protected function setNewRelicParameter(string $key, $value) : void
    {
        if (null === $value || is_scalar($value)) {
            newrelic_add_custom_parameter($key, $value);
        } else {
            newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true));
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new NormalizerFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
use Psr\Log\LogLevel;
/**
 * Sends notifications through the pushover api to mobile phones
 *
 * @author Sebastian GÃ¶ttschkes <sebastian.goettschkes@googlemail.com>
 * @see    https://www.pushover.net/api
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class PushoverHandler extends SocketHandler
{
    /** @var string */
    private $token;
    /** @var array<int|string> */
    private $users;
    /** @var string */
    private $title;
    /** @var string|int|null */
    private $user = null;
    /** @var int */
    private $retry;
    /** @var int */
    private $expire;
    /** @var int */
    private $highPriorityLevel;
    /** @var int */
    private $emergencyLevel;
    /** @var bool */
    private $useFormattedMessage = false;
    /**
     * All parameters that can be sent to Pushover
     * @see https://pushover.net/api
     * @var array<string, bool>
     */
    private $parameterNames = ['token' => true, 'user' => true, 'message' => true, 'device' => true, 'title' => true, 'url' => true, 'url_title' => true, 'priority' => true, 'timestamp' => true, 'sound' => true, 'retry' => true, 'expire' => true, 'callback' => true];
    /**
     * Sounds the api supports by default
     * @see https://pushover.net/api#sounds
     * @var string[]
     */
    private $sounds = ['pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', 'persistent', 'echo', 'updown', 'none'];
    /**
    * @param string $token Pushover api token
    * @param (string | array) $users Pushover user id or array of ids the message will be sent to
    * @param (string | null) $title Title sent to the Pushover API
    * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
    the pushover.net app owner. OpenSSL is required for this option.
    * @param (string | int) $highPriorityLevel The minimum logging level at which this handler will start
    sending "high priority" requests to the Pushover API
    * @param (string | int) $emergencyLevel The minimum logging level at which this handler will start
    sending "emergency" requests to the Pushover API
    * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will
    send the same notification to the user.
    * @param int $expire The expire parameter specifies how many seconds your notification will continue
    to be retried for (every retry seconds).
    *
    * @phpstan-param (string | array<(int | string)>) $users
    * @phpstan-param (Level | LevelName | LogLevel::*) $highPriorityLevel
    * @phpstan-param (Level | LevelName | LogLevel::*) $emergencyLevel
    */
    public function __construct(string $token, $users, ?string $title = null, $level = Logger::CRITICAL, bool $bubble = true, bool $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, int $retry = 30, int $expire = 25200)
    {
        $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80';
        parent::__construct($connectionString, $level, $bubble);
        $this->token = $token;
        $this->users = (array) $users;
        $this->title = $title ?: (string) gethostname();
        $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel);
        $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel);
        $this->retry = $retry;
        $this->expire = $expire;
    }
    /**
     *
     */
    protected function generateDataStream(array $record) : string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * @phpstan-param FormattedRecord $record
     */
    private function buildContent(array $record) : string
    {
        // Pushover has a limit of 512 characters on title and message combined.
        $maxMessageLength = 512 - strlen($this->title);
        $message = $this->useFormattedMessage ? $record['formatted'] : $record['message'];
        $message = Utils::substr($message, 0, $maxMessageLength);
        $timestamp = $record['datetime']->getTimestamp();
        $dataArray = ['token' => $this->token, 'user' => $this->user, 'message' => $message, 'title' => $this->title, 'timestamp' => $timestamp];
        if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) {
            $dataArray['priority'] = 2;
            $dataArray['retry'] = $this->retry;
            $dataArray['expire'] = $this->expire;
        } elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) {
            $dataArray['priority'] = 1;
        }
        // First determine the available parameters
        $context = array_intersect_key($record['context'], $this->parameterNames);
        $extra = array_intersect_key($record['extra'], $this->parameterNames);
        // Least important info should be merged with subsequent info
        $dataArray = array_merge($extra, $context, $dataArray);
        // Only pass sounds that are supported by the API
        if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) {
            unset($dataArray['sound']);
        }
        return http_build_query($dataArray);
    }
    /**
     *
     */
    private function buildHeader(string $content) : string
    {
        $header = "POST /1/messages.json HTTP/1.1\r\n";
        $header .= "Host: api.pushover.net\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    /**
     *
     */
    protected function write(array $record) : void
    {
        foreach ($this->users as $user) {
            $this->user = $user;
            parent::write($record);
            $this->closeSocket();
        }
        $this->user = null;
    }
    /**
     * @param (int | string) $value
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $value
     */
    public function setHighPriorityLevel($value) : self
    {
        $this->highPriorityLevel = Logger::toMonologLevel($value);
        return $this;
    }
    /**
     * @param (int | string) $value
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $value
     */
    public function setEmergencyLevel($value) : self
    {
        $this->emergencyLevel = Logger::toMonologLevel($value);
        return $this;
    }
    /**
     * Use the formatted message?
     */
    public function useFormattedMessage(bool $value) : self
    {
        $this->useFormattedMessage = $value;
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\ResettableInterface;
use Psr\Log\LogLevel;
/**
 * Base Handler class providing basic level/bubble support
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
abstract class AbstractHandler extends Handler implements ResettableInterface
{
    /**
     * @var int
     * @phpstan-var Level
     */
    protected $level = Logger::DEBUG;
    /** @var bool */
    protected $bubble = true;
    /**
     * @param (int | string) $level The minimum logging level at which this handler will be triggered
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG, bool $bubble = true)
    {
        $this->setLevel($level);
        $this->bubble = $bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return $record['level'] >= $this->level;
    }
    /**
     * Sets minimum logging level at which this handler will be triggered.
     *
     * @param (Level | LevelName | LogLevel::*) $level Level or level name
     * @return self
     */
    public function setLevel($level) : self
    {
        $this->level = Logger::toMonologLevel($level);
        return $this;
    }
    /**
     * Gets minimum logging level at which this handler will be triggered.
     *
     * @return int
     *
     * @phpstan-return Level
     */
    public function getLevel() : int
    {
        return $this->level;
    }
    /**
    * Sets the bubbling behavior.
    *
    * @param bool $bubble true means that this handler allows bubbling.
    false means that bubbling is not permitted.
    * @return self
    */
    public function setBubble(bool $bubble) : self
    {
        $this->bubble = $bubble;
        return $this;
    }
    /**
    * Gets the bubbling behavior.
    *
    * @return bool true means that this handler allows bubbling.
    false means that bubbling is not permitted.
    */
    public function getBubble() : bool
    {
        return $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function reset()
    {
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\SyslogUdp;

use Monolog\Utils;
use Socket;
class UdpSocket
{
    protected const DATAGRAM_MAX_LENGTH = 65023;
    /** @var string */
    protected $ip;
    /** @var int */
    protected $port;
    /** @var resource|Socket|null */
    protected $socket;
    /**
     *
     */
    public function __construct(string $ip, int $port = 514)
    {
        $this->ip = $ip;
        $this->port = $port;
        $domain = AF_INET;
        $protocol = SOL_UDP;
        // Check if we are using unix sockets.
        if ($port === 0) {
            $domain = AF_UNIX;
            $protocol = IPPROTO_IP;
        }
        $this->socket = socket_create($domain, SOCK_DGRAM, $protocol) ?: null;
    }
    /**
     * @param string $line
     * @param string $header
     * @return void
     */
    public function write($line, $header = "")
    {
        $this->send($this->assembleMessage($line, $header));
    }
    /**
     *
     */
    public function close() : void
    {
        if (is_resource($this->socket) || $this->socket instanceof Socket) {
            socket_close($this->socket);
            $this->socket = null;
        }
    }
    /**
     *
     */
    protected function send(string $chunk) : void
    {
        if (!is_resource($this->socket) && !$this->socket instanceof Socket) {
            throw new \RuntimeException('The UdpSocket to ' . $this->ip . ':' . $this->port . ' has been closed and can not be written to anymore');
        }
        socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port);
    }
    /**
     *
     */
    protected function assembleMessage(string $line, string $header) : string
    {
        $chunkSize = static::DATAGRAM_MAX_LENGTH - strlen($header);
        return $header . Utils::substr($line, 0, $chunkSize);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Interface that all Monolog Handlers must implement
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
interface HandlerInterface
{
    /**
    * Checks whether the given record will be handled by this handler.
    *
    * This is mostly done for performance reasons, to avoid calling processors for nothing.
    *
    * Handlers should still check the record levels within handle(), returning false in isHandling()
    is no guarantee that handle() will not be called, and isHandling() might not be called
    for a given record.
    *
    * @param array $record Partial log record containing only a level key
    *
    * @return bool
    *
    * @phpstan-param array{level: Level} $record
    */
    public function isHandling(array $record) : bool;
    /**
    * Handles a record.
    *
    * All records may be passed to this method, and the handler should discard
    those that it does not want to handle.
    *
    * The return value of this function controls the bubbling process of the handler stack.
    Unless the bubbling is interrupted (by returning true), the Logger class will keep on
    calling further handlers in the stack with a given log record.
    *
    * @param array $record The record to handle
    * @return bool true means that this handler handled the record, and that bubbling is not permitted.
    false means the record was either not processed or that this handler allows bubbling.
    *
    * @phpstan-param Record $record
    */
    public function handle(array $record) : bool;
    /**
     * Handles a set of records at once.
     *
     * @param array $records The records to handle (an array of record arrays)
     *
     * @phpstan-param Record[] $records
     */
    public function handleBatch(array $records) : void;
    /**
    * Closes the handler.
    *
    * Ends a log cycle and frees all resources used by the handler.
    *
    * Closing a Handler means flushing all buffers and freeing any open resources/handles.
    *
    * Implementations have to be idempotent (i.e. it should be possible to call close several times without breakage)
    and ideally handlers should be able to reopen themselves on handle() after they have been closed.
    *
    * This is useful at the end of a request and will be called automatically when the object
    is destroyed if you extend Monolog\Handler\Handler.
    *
    * If you are thinking of calling this method yourself, most likely you should be
    calling ResettableInterface::reset instead. Have a look.
    */
    public function close() : void;
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
/**
 * IFTTTHandler uses cURL to trigger IFTTT Maker actions
 *
 * Register a secret key and trigger/event name at https://ifttt.com/maker
 *
 * value1 will be the channel from monolog's Logger constructor,
 * value2 will be the level name (ERROR, WARNING, ..)
 * value3 will be the log record's message
 *
 * @author Nehal Patel <nehal@nehalpatel.me>
 */
class IFTTTHandler extends AbstractProcessingHandler
{
    /** @var string */
    private $eventName;
    /** @var string */
    private $secretKey;
    /**
     * @param string $eventName The name of the IFTTT Maker event that should be triggered
     * @param string $secretKey A valid IFTTT secret key
     */
    public function __construct(string $eventName, string $secretKey, $level = Logger::ERROR, bool $bubble = true)
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the IFTTTHandler');
        }
        $this->eventName = $eventName;
        $this->secretKey = $secretKey;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    public function write(array $record) : void
    {
        $postData = ["value1" => $record["channel"], "value2" => $record["level_name"], "value3" => $record["message"]];
        $postString = Utils::jsonEncode($postData);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
        Curl\Util::execute($ch);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Throwable;
/**
 * Forwards records to at most one handler
 *
 * If a handler fails, the exception is suppressed and the record is forwarded to the next handler.
 *
 * As soon as one handler handles a record successfully, the handling stops there.
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class FallbackGroupHandler extends GroupHandler
{
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handle($record);
                break;
            } catch (Throwable $e) {
                // What throwable?
            }
        }
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if ($this->processors) {
            $processed = [];
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            /** @var Record[] $records */
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handleBatch($records);
                break;
            } catch (Throwable $e) {
                // What throwable?
            }
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Base Handler class providing the Handler structure, including processors and formatters
 *
 * Classes extending it should (in most cases) only implement write($record)
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @phpstan-import-type LevelName from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-type FormattedRecord array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[], formatted: mixed}
 */
abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    use FormattableHandlerTrait;
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if (!$this->isHandling($record)) {
            return false;
        }
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        $record['formatted'] = $this->getFormatter()->format($record);
        $this->write($record);
        return false === $this->bubble;
    }
    /**
     * Writes the record down to the log of the implementing handler
     *
     * @phpstan-param FormattedRecord $record
     */
    protected abstract function write(array $record) : void;
    /**
     * @return void
     */
    public function reset()
    {
        parent::reset();
        $this->resetProcessors();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
/**
 * Sends the message to a Redis Pub/Sub channel using PUBLISH
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Logger::WARNING);
 *   $log->pushHandler($redis);
 *
 * @author GaÃ«tan FaugÃ¨re <gaetan@fauge.re>
 */
class RedisPubSubHandler extends AbstractProcessingHandler
{
    /** @var \Predis\Client|\Redis */
    private $redisClient;
    /** @var string */
    private $channelKey;
    /**
     * @param (\Predis\Client | \Redis) $redis The redis instance
     * @param string $key The channel key to publish records to
     */
    public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!($redis instanceof \Predis\Client || $redis instanceof \Redis)) {
            throw new \InvalidArgumentException('Predis\\Client or Redis instance required');
        }
        $this->redisClient = $redis;
        $this->channelKey = $key;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->redisClient->publish($this->channelKey, $record["formatted"]);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Handler\Slack\SlackRecord;
/**
 * Sends notifications through Slack API
 *
 * @author Greg Kedzierski <greg@gregkedzierski.com>
 * @see    https://api.slack.com/
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class SlackHandler extends SocketHandler
{
    /**
     * Slack API token
     * @var string
     */
    private $token;
    /**
     * Instance of the SlackRecord util class preparing data for Slack API.
     * @var SlackRecord
     */
    private $slackRecord;
    /**
     * @param string $token Slack API token
     * @param string $channel Slack channel (encoded ID or name)
     * @param (string | null) $username Name of a bot
     * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
     * @param (string | null) $iconEmoji The emoji name to use (or null)
     * @param bool $useShortAttachment Whether the context/extra messages added to Slack as attachments are in a short style
     * @param bool $includeContextAndExtra Whether the attachment should include context and extra data
     * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     * @throws MissingExtensionException If no OpenSSL PHP extension configured
     */
    public function __construct(string $token, string $channel, ?string $username = null, bool $useAttachment = true, ?string $iconEmoji = null, $level = Logger::CRITICAL, bool $bubble = true, bool $useShortAttachment = false, bool $includeContextAndExtra = false, array $excludeFields = array())
    {
        if (!extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
        }
        parent::__construct('ssl://slack.com:443', $level, $bubble);
        $this->slackRecord = new SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields);
        $this->token = $token;
    }
    /**
     *
     */
    public function getSlackRecord() : SlackRecord
    {
        return $this->slackRecord;
    }
    /**
     *
     */
    public function getToken() : string
    {
        return $this->token;
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the body of API call
     *
     * @phpstan-param FormattedRecord $record
     */
    private function buildContent(array $record) : string
    {
        $dataArray = $this->prepareContentData($record);
        return http_build_query($dataArray);
    }
    /**
     * @phpstan-param FormattedRecord $record
     * @return string[]
     */
    protected function prepareContentData(array $record) : array
    {
        $dataArray = $this->slackRecord->getSlackData($record);
        $dataArray['token'] = $this->token;
        if (!empty($dataArray['attachments'])) {
            $dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']);
        }
        return $dataArray;
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content) : string
    {
        $header = "POST /api/chat.postMessage HTTP/1.1\r\n";
        $header .= "Host: slack.com\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        parent::write($record);
        $this->finalizeWrite();
    }
    /**
    * Finalizes the request by reading some bytes and then closing the socket
    *
    * If we do not read some but close the socket too early, slack sometimes
    drops the request entirely.
    */
    protected function finalizeWrite() : void
    {
        $res = $this->getResource();
        if (is_resource($res)) {
            @fread($res, 2048);
        }
        $this->closeSocket();
    }
    /**
     *
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        parent::setFormatter($formatter);
        $this->slackRecord->setFormatter($formatter);
        return $this;
    }
    /**
     *
     */
    public function getFormatter() : FormatterInterface
    {
        $formatter = parent::getFormatter();
        $this->slackRecord->setFormatter($formatter);
        return $formatter;
    }
    /**
     * Channel used by the bot when posting
     */
    public function setChannel(string $channel) : self
    {
        $this->slackRecord->setChannel($channel);
        return $this;
    }
    /**
     * Username used by the bot when posting
     */
    public function setUsername(string $username) : self
    {
        $this->slackRecord->setUsername($username);
        return $this;
    }
    /**
     *
     */
    public function useAttachment(bool $useAttachment) : self
    {
        $this->slackRecord->useAttachment($useAttachment);
        return $this;
    }
    /**
     *
     */
    public function setIconEmoji(string $iconEmoji) : self
    {
        $this->slackRecord->setUserIcon($iconEmoji);
        return $this;
    }
    /**
     *
     */
    public function useShortAttachment(bool $useShortAttachment) : self
    {
        $this->slackRecord->useShortAttachment($useShortAttachment);
        return $this;
    }
    /**
     *
     */
    public function includeContextAndExtra(bool $includeContextAndExtra) : self
    {
        $this->slackRecord->includeContextAndExtra($includeContextAndExtra);
        return $this;
    }
    /**
     * @param string[] $excludeFields
     */
    public function excludeFields(array $excludeFields) : self
    {
        $this->slackRecord->excludeFields($excludeFields);
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
/**
 * Common syslog functionality
 *
 * @phpstan-import-type Level from \Monolog\Logger
 */
abstract class AbstractSyslogHandler extends AbstractProcessingHandler
{
    /** @var int */
    protected $facility;
    /**
     * Translates Monolog log levels to syslog log priorities.
     * @var array
     * @phpstan-var array<Level, int>
     */
    protected $logLevels = [Logger::DEBUG => LOG_DEBUG, Logger::INFO => LOG_INFO, Logger::NOTICE => LOG_NOTICE, Logger::WARNING => LOG_WARNING, Logger::ERROR => LOG_ERR, Logger::CRITICAL => LOG_CRIT, Logger::ALERT => LOG_ALERT, Logger::EMERGENCY => LOG_EMERG];
    /**
     * List of valid log facility names.
     * @var array<string, int>
     */
    protected $facilities = ['auth' => LOG_AUTH, 'authpriv' => LOG_AUTHPRIV, 'cron' => LOG_CRON, 'daemon' => LOG_DAEMON, 'kern' => LOG_KERN, 'lpr' => LOG_LPR, 'mail' => LOG_MAIL, 'news' => LOG_NEWS, 'syslog' => LOG_SYSLOG, 'user' => LOG_USER, 'uucp' => LOG_UUCP];
    /**
     * @param (string | int) $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     */
    public function __construct($facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->facilities['local0'] = LOG_LOCAL0;
            $this->facilities['local1'] = LOG_LOCAL1;
            $this->facilities['local2'] = LOG_LOCAL2;
            $this->facilities['local3'] = LOG_LOCAL3;
            $this->facilities['local4'] = LOG_LOCAL4;
            $this->facilities['local5'] = LOG_LOCAL5;
            $this->facilities['local6'] = LOG_LOCAL6;
            $this->facilities['local7'] = LOG_LOCAL7;
        } else {
            $this->facilities['local0'] = 128;
            // LOG_LOCAL0
            $this->facilities['local1'] = 136;
            // LOG_LOCAL1
            $this->facilities['local2'] = 144;
            // LOG_LOCAL2
            $this->facilities['local3'] = 152;
            // LOG_LOCAL3
            $this->facilities['local4'] = 160;
            // LOG_LOCAL4
            $this->facilities['local5'] = 168;
            // LOG_LOCAL5
            $this->facilities['local6'] = 176;
            // LOG_LOCAL6
            $this->facilities['local7'] = 184;
            // LOG_LOCAL7
        }
        // convert textual description of facility to syslog constant
        if (is_string($facility) && array_key_exists(strtolower($facility), $this->facilities)) {
            $facility = $this->facilities[strtolower($facility)];
        } elseif (!in_array($facility, array_values($this->facilities), true)) {
            throw new \UnexpectedValueException('Unknown facility value "' . $facility . '" given');
        }
        $this->facility = $facility;
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Forwards records to multiple handlers suppressing failures of each handler
 * and continuing through to give every handler a chance to succeed.
 *
 * @author Craig D'Amelio <craig@damelio.ca>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class WhatFailureGroupHandler extends GroupHandler
{
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handle($record);
            } catch (\Throwable $e) {
                // What failure?
            }
        }
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if ($this->processors) {
            $processed = array();
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            /** @var Record[] $records */
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handleBatch($records);
            } catch (\Throwable $e) {
                // What failure?
            }
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Simple handler wrapper that deduplicates log records across multiple requests
 *
 * It also includes the BufferHandler functionality and will buffer
 * all messages until the end of the request or flush() is called.
 *
 * This works by storing all log records' messages above $deduplicationLevel
 * to the file specified by $deduplicationStore. When further logs come in at the end of the
 * request (or when flush() is called), all those above $deduplicationLevel are checked
 * against the existing stored logs. If they match and the timestamps in the stored log is
 * not older than $time seconds, the new log record is discarded. If no log record is new, the
 * whole data set is discarded.
 *
 * This is mainly useful in combination with Mail handlers or things like Slack or HipChat handlers
 * that send messages to people, to avoid spamming with the same message over and over in case of
 * a major component failure like a database server being down which makes all requests fail in the
 * same way.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
class DeduplicationHandler extends BufferHandler
{
    /**
     * @var string
     */
    protected $deduplicationStore;
    /**
     * @var Level
     */
    protected $deduplicationLevel;
    /**
     * @var int
     */
    protected $time;
    /**
     * @var bool
     */
    private $gc = false;
    /**
     * @param HandlerInterface $handler Handler.
     * @param string $deduplicationStore The file/path where the deduplication log should be kept
     * @param (string | int) $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
     * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $deduplicationLevel
     */
    public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, int $time = 60, bool $bubble = true)
    {
        parent::__construct($handler, 0, Logger::DEBUG, $bubble, false);
        $this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . \Phabel\Target\Php80\Polyfill::substr(md5(__FILE__), 0, 20) . '.log' : $deduplicationStore;
        $this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel);
        $this->time = $time;
    }
    /**
     *
     */
    public function flush() : void
    {
        if ($this->bufferSize === 0) {
            return;
        }
        $passthru = null;
        foreach ($this->buffer as $record) {
            if ($record['level'] >= $this->deduplicationLevel) {
                $passthru = $passthru || !$this->isDuplicate($record);
                if ($passthru) {
                    $this->appendRecord($record);
                }
            }
        }
        // default of null is valid as well as if no record matches duplicationLevel we just pass through
        if ($passthru === true || $passthru === null) {
            $this->handler->handleBatch($this->buffer);
        }
        $this->clear();
        if ($this->gc) {
            $this->collectLogs();
        }
    }
    /**
     * @phpstan-param Record $record
     */
    private function isDuplicate(array $record) : bool
    {
        if (!file_exists($this->deduplicationStore)) {
            return false;
        }
        $store = file($this->deduplicationStore, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if (!is_array($store)) {
            return false;
        }
        $yesterday = time() - 86400;
        $timestampValidity = $record['datetime']->getTimestamp() - $this->time;
        $expectedMessage = preg_replace('{[\\r\\n].*}', '', $record['message']);
        for ($i = count($store) - 1; $i >= 0; $i--) {
            list($timestamp, $level, $message) = explode(':', $store[$i], 3);
            if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) {
                return true;
            }
            if ($timestamp < $yesterday) {
                $this->gc = true;
            }
        }
        return false;
    }
    /**
     *
     */
    private function collectLogs() : void
    {
        if (!file_exists($this->deduplicationStore)) {
            return;
        }
        $handle = fopen($this->deduplicationStore, 'rw+');
        if (!$handle) {
            throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore);
        }
        flock($handle, LOCK_EX);
        $validLogs = [];
        $timestampValidity = time() - $this->time;
        while (!feof($handle)) {
            $log = fgets($handle);
            if ($log && \Phabel\Target\Php80\Polyfill::substr($log, 0, 10) >= $timestampValidity) {
                $validLogs[] = $log;
            }
        }
        ftruncate($handle, 0);
        rewind($handle);
        foreach ($validLogs as $log) {
            fwrite($handle, $log);
        }
        flock($handle, LOCK_UN);
        fclose($handle);
        $this->gc = false;
    }
    /**
     * @phpstan-param Record $record
     */
    private function appendRecord(array $record) : void
    {
        file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\\r\\n].*}', '', $record['message']) . "\n", FILE_APPEND);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Swift;
use Swift_Message;
/**
 * MandrillHandler uses cURL to send the emails to the Mandrill API
 *
 * @author Adam Nicholson <adamnicholson10@gmail.com>
 */
class MandrillHandler extends MailHandler
{
    /** @var Swift_Message */
    protected $message;
    /** @var string */
    protected $apiKey;
    /**
     * @psalm-param (Swift_Message | callable(): Swift_Message) $message
     *
     * @param string $apiKey A valid Mandrill API key
     * @param (callable | Swift_Message) $message An example message for real messages, only the body will be replaced
     */
    public function __construct(string $apiKey, $message, $level = Logger::ERROR, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        if (!$message instanceof Swift_Message && is_callable($message)) {
            $message = $message();
        }
        if (!$message instanceof Swift_Message) {
            throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it');
        }
        $this->message = $message;
        $this->apiKey = $apiKey;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records) : void
    {
        $mime = 'text/plain';
        if ($this->isHtmlBody($content)) {
            $mime = 'text/html';
        }
        $message = clone $this->message;
        $message->setBody($content, $mime);
        /** @phpstan-ignore-next-line */
        if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
            $message->setDate(new \DateTimeImmutable());
        } else {
            /** @phpstan-ignore-next-line */
            $message->setDate(time());
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json');
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['key' => $this->apiKey, 'raw_message' => (string) $message, 'async' => false]));
        Curl\Util::execute($ch);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\Slack;

use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Slack record utility helping to log to Slack webhooks or API.
 *
 * @author Greg Kedzierski <greg@gregkedzierski.com>
 * @author Haralan Dobrev <hkdobrev@gmail.com>
 * @see    https://api.slack.com/incoming-webhooks
 * @see    https://api.slack.com/docs/message-attachments
 *
 * @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler
 * @phpstan-import-type Record from \Monolog\Logger
 */
class SlackRecord
{
    public const COLOR_DANGER = 'danger';
    public const COLOR_WARNING = 'warning';
    public const COLOR_GOOD = 'good';
    public const COLOR_DEFAULT = '#e3e4e6';
    /**
     * Slack channel (encoded ID or name)
     * @var string|null
     */
    private $channel;
    /**
     * Name of a bot
     * @var string|null
     */
    private $username;
    /**
     * User icon e.g. 'ghost', 'http://example.com/user.png'
     * @var string|null
     */
    private $userIcon;
    /**
     * Whether the message should be added to Slack as attachment (plain text otherwise)
     * @var bool
     */
    private $useAttachment;
    /**
     * Whether the the context/extra messages added to Slack as attachments are in a short style
     * @var bool
     */
    private $useShortAttachment;
    /**
     * Whether the attachment should include context and extra data
     * @var bool
     */
    private $includeContextAndExtra;
    /**
     * Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     * @var string[]
     */
    private $excludeFields;
    /**
     * @var ?FormatterInterface
     */
    private $formatter;
    /**
     * @var NormalizerFormatter
     */
    private $normalizerFormatter;
    /**
     * @param string[] $excludeFields
     */
    public function __construct(?string $channel = null, ?string $username = null, bool $useAttachment = true, ?string $userIcon = null, bool $useShortAttachment = false, bool $includeContextAndExtra = false, array $excludeFields = array(), FormatterInterface $formatter = null)
    {
        $this->setChannel($channel)->setUsername($username)->useAttachment($useAttachment)->setUserIcon($userIcon)->useShortAttachment($useShortAttachment)->includeContextAndExtra($includeContextAndExtra)->excludeFields($excludeFields)->setFormatter($formatter);
        if ($this->includeContextAndExtra) {
            $this->normalizerFormatter = new NormalizerFormatter();
        }
    }
    /**
    * Returns required data in format that Slack
    is expecting.
    *
    * @phpstan-param FormattedRecord $record
    * @phpstan-return mixed[]
    */
    public function getSlackData(array $record) : array
    {
        $dataArray = array();
        $record = $this->removeExcludedFields($record);
        if ($this->username) {
            $dataArray['username'] = $this->username;
        }
        if ($this->channel) {
            $dataArray['channel'] = $this->channel;
        }
        if ($this->formatter && !$this->useAttachment) {
            /** @phpstan-ignore-next-line */
            $message = $this->formatter->format($record);
        } else {
            $message = $record['message'];
        }
        if ($this->useAttachment) {
            $attachment = array('fallback' => $message, 'text' => $message, 'color' => $this->getAttachmentColor($record['level']), 'fields' => array(), 'mrkdwn_in' => array('fields'), 'ts' => $record['datetime']->getTimestamp());
            if ($this->useShortAttachment) {
                $attachment['title'] = $record['level_name'];
            } else {
                $attachment['title'] = 'Message';
                $attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']);
            }
            if ($this->includeContextAndExtra) {
                foreach (array('extra', 'context') as $key) {
                    if (empty($record[$key])) {
                        continue;
                    }
                    if ($this->useShortAttachment) {
                        $attachment['fields'][] = $this->generateAttachmentField((string) $key, $record[$key]);
                    } else {
                        // Add all extra fields as individual fields in attachment
                        $attachment['fields'] = array_merge($attachment['fields'], $this->generateAttachmentFields($record[$key]));
                    }
                }
            }
            $dataArray['attachments'] = array($attachment);
        } else {
            $dataArray['text'] = $message;
        }
        if ($this->userIcon) {
            if (filter_var($this->userIcon, FILTER_VALIDATE_URL)) {
                $dataArray['icon_url'] = $this->userIcon;
            } else {
                $dataArray['icon_emoji'] = ":{$this->userIcon}:";
            }
        }
        return $dataArray;
    }
    /**
    * Returns a Slack message attachment color associated with
    provided level.
    */
    public function getAttachmentColor(int $level) : string
    {
        switch (true) {
            case $level >= Logger::ERROR:
                return static::COLOR_DANGER;
            case $level >= Logger::WARNING:
                return static::COLOR_WARNING;
            case $level >= Logger::INFO:
                return static::COLOR_GOOD;
            default:
                return static::COLOR_DEFAULT;
        }
    }
    /**
     * Stringifies an array of key/value pairs to be used in attachment fields
     *
     * @param mixed[] $fields
     */
    public function stringify(array $fields) : string
    {
        /** @var Record $fields */
        $normalized = $this->normalizerFormatter->format($fields);
        $hasSecondDimension = count(array_filter($normalized, 'is_array'));
        $hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
        return $hasSecondDimension || $hasNonNumericKeys ? Utils::jsonEncode($normalized, JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS) : Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS);
    }
    /**
     * Channel used by the bot when posting
     *
     * @param ?string $channel
     *
     * @return static
     */
    public function setChannel(?string $channel = null) : self
    {
        $this->channel = $channel;
        return $this;
    }
    /**
     * Username used by the bot when posting
     *
     * @param ?string $username
     *
     * @return static
     */
    public function setUsername(?string $username = null) : self
    {
        $this->username = $username;
        return $this;
    }
    /**
     *
     */
    public function useAttachment(bool $useAttachment = true) : self
    {
        $this->useAttachment = $useAttachment;
        return $this;
    }
    /**
     *
     */
    public function setUserIcon(?string $userIcon = null) : self
    {
        $this->userIcon = $userIcon;
        if (\is_string($userIcon)) {
            $this->userIcon = trim($userIcon, ':');
        }
        return $this;
    }
    /**
     *
     */
    public function useShortAttachment(bool $useShortAttachment = false) : self
    {
        $this->useShortAttachment = $useShortAttachment;
        return $this;
    }
    /**
     *
     */
    public function includeContextAndExtra(bool $includeContextAndExtra = false) : self
    {
        $this->includeContextAndExtra = $includeContextAndExtra;
        if ($this->includeContextAndExtra) {
            $this->normalizerFormatter = new NormalizerFormatter();
        }
        return $this;
    }
    /**
     * @param string[] $excludeFields
     */
    public function excludeFields(array $excludeFields = []) : self
    {
        $this->excludeFields = $excludeFields;
        return $this;
    }
    /**
     *
     */
    public function setFormatter(?FormatterInterface $formatter = null) : self
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * Generates attachment field
     *
     * @param (string | mixed[]) $value
     *
     * @return array{title: string, value: string, short: false}
     */
    private function generateAttachmentField(string $title, $value) : array
    {
        $value = is_array($value) ? sprintf('```%s```', \Phabel\Target\Php80\Polyfill::substr($this->stringify($value), 0, 1990)) : $value;
        return array('title' => ucfirst($title), 'value' => $value, 'short' => false);
    }
    /**
     * Generates a collection of attachment fields from array
     *
     * @param mixed[] $data
     *
     * @return array<array{title: string, value: string, short: false}>
     */
    private function generateAttachmentFields(array $data) : array
    {
        /** @var Record $data */
        $normalized = $this->normalizerFormatter->format($data);
        $fields = array();
        foreach ($normalized as $key => $value) {
            $fields[] = $this->generateAttachmentField((string) $key, $value);
        }
        return $fields;
    }
    /**
     * Get a copy of record with fields excluded according to $this->excludeFields
     *
     * @phpstan-param FormattedRecord $record
     *
     * @return mixed[]
     */
    private function removeExcludedFields(array $record) : array
    {
        foreach ($this->excludeFields as $field) {
            $keys = explode('.', $field);
            $node =& $record;
            $lastKey = end($keys);
            foreach ($keys as $key) {
                if (!isset($node[$key])) {
                    break;
                }
                if ($lastKey === $key) {
                    unset($node[$key]);
                    break;
                }
                $node =& $node[$key];
            }
        }
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
/**
 * This simple wrapper class can be used to extend handlers functionality.
 *
 * Example: A custom filtering that can be applied to any handler.
 *
 * Inherit from this class and override handle() like this:
 *
 *   public function handle(array $record)
 *   {
 *        if ($record meets certain conditions) {
 *            return false;
 *        }
 *        return $this->handler->handle($record);
 *   }
 *
 * @author Alexey Karapetov <alexey@karapetov.com>
 */
class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface, ResettableInterface
{
    /**
     * @var HandlerInterface
     */
    protected $handler;
    /**
     *
     */
    public function __construct(HandlerInterface $handler)
    {
        $this->handler = $handler;
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return $this->handler->isHandling($record);
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        return $this->handler->handle($record);
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $this->handler->handleBatch($records);
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        $this->handler->close();
    }
    /**
     * {@inheritDoc}
     */
    public function pushProcessor(callable $callback) : HandlerInterface
    {
        if ($this->handler instanceof ProcessableHandlerInterface) {
            $this->handler->pushProcessor($callback);
            return $this;
        }
        throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
    }
    /**
     * {@inheritDoc}
     */
    public function popProcessor() : callable
    {
        if ($this->handler instanceof ProcessableHandlerInterface) {
            return $this->handler->popProcessor();
        }
        throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
    }
    /**
     *
     */
    public function reset()
    {
        if ($this->handler instanceof ResettableInterface) {
            $this->handler->reset();
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Utils;
/**
 * Handler sending logs to browser's javascript console with no browser extension required
 *
 * @author Olivier Poitrey <rs@dailymotion.com>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class BrowserConsoleHandler extends AbstractProcessingHandler
{
    /** @var bool */
    protected static $initialized = false;
    /** @var FormattedRecord[] */
    protected static $records = [];
    /**
     * {@inheritDoc}
     *
     * Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format.
     *
     * Example of formatted string:
     *
     * You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%');
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        // Accumulate records
        static::$records[] = $record;
        // Register shutdown handler if not already done
        if (!static::$initialized) {
            static::$initialized = true;
            $this->registerShutdownFunction();
        }
    }
    /**
    * Convert records to javascript console commands and send it to the browser.
    This method is automatically called on PHP shutdown if output is HTML or Javascript.
    */
    public static function send() : void
    {
        $format = static::getResponseFormat();
        if ($format === 'unknown') {
            return;
        }
        if (count(static::$records)) {
            if ($format === 'html') {
                static::writeOutput('<script>' . static::generateScript() . '</script>');
            } elseif ($format === 'js') {
                static::writeOutput(static::generateScript());
            }
            static::resetStatic();
        }
    }
    /**
     *
     */
    public function close() : void
    {
        self::resetStatic();
    }
    /**
     *
     */
    public function reset()
    {
        parent::reset();
        self::resetStatic();
    }
    /**
     * Forget all logged records
     */
    public static function resetStatic() : void
    {
        static::$records = [];
    }
    /**
     * Wrapper for register_shutdown_function to allow overriding
     */
    protected function registerShutdownFunction() : void
    {
        if (PHP_SAPI !== 'cli') {
            register_shutdown_function(['Monolog\\Handler\\BrowserConsoleHandler', 'send']);
        }
    }
    /**
     * Wrapper for echo to allow overriding
     */
    protected static function writeOutput(string $str) : void
    {
        echo $str;
    }
    /**
    * Checks the format of the response
    *
    * If Content-Type is set to application/javascript or text/javascript -> js
    If Content-Type is set to text/html, or is unset -> html
    If Content-Type is anything else -> unknown
    *
    * @return string One of 'js', 'html' or 'unknown'
    */
    protected static function getResponseFormat() : string
    {
        // Check content type
        foreach (headers_list() as $header) {
            if (stripos($header, 'content-type:') === 0) {
                // This handler only works with HTML and javascript outputs
                // text/javascript is obsolete in favour of application/javascript, but still used
                if (stripos($header, 'application/javascript') !== false || stripos($header, 'text/javascript') !== false) {
                    return 'js';
                }
                if (stripos($header, 'text/html') === false) {
                    return 'unknown';
                }
                break;
            }
        }
        return 'html';
    }
    /**
     *
     */
    private static function generateScript() : string
    {
        $script = [];
        foreach (static::$records as $record) {
            $context = static::dump('Context', $record['context']);
            $extra = static::dump('Extra', $record['extra']);
            if (empty($context) && empty($extra)) {
                $script[] = static::call_array('log', static::handleStyles($record['formatted']));
            } else {
                $script = array_merge($script, [static::call_array('groupCollapsed', static::handleStyles($record['formatted']))], $context, $extra, [static::call('groupEnd')]);
            }
        }
        return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);";
    }
    /**
     * @return string[]
     */
    private static function handleStyles(string $formatted) : array
    {
        $args = [];
        $format = '%c' . $formatted;
        preg_match_all('/\\[\\[(.*?)\\]\\]\\{([^}]*)\\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
        foreach (array_reverse($matches) as $match) {
            $args[] = '"font-weight: normal"';
            $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
            $pos = $match[0][1];
            $format = Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . Utils::substr($format, $pos + strlen($match[0][0]));
        }
        $args[] = static::quote('font-weight: normal');
        $args[] = static::quote($format);
        return array_reverse($args);
    }
    /**
     *
     */
    private static function handleCustomStyles(string $style, string $string) : string
    {
        static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'];
        static $labels = [];
        $style = preg_replace_callback('/macro\\s*:(.*?)(?:;|$)/', function (array $m) use($string, &$colors, &$labels) {
            if (trim($m[1]) === 'autolabel') {
                // Format the string as a label with consistent auto assigned background color
                if (!isset($labels[$string])) {
                    $labels[$string] = $colors[count($labels) % count($colors)];
                }
                $color = $labels[$string];
                return "background-color: {$color}; color: white; border-radius: 3px; padding: 0 2px 0 2px";
            }
            return $m[1];
        }, $style);
        if (null === $style) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
        }
        return $style;
    }
    /**
     * @param mixed[] $dict
     * @return mixed[]
     */
    private static function dump(string $title, array $dict) : array
    {
        $script = [];
        $dict = array_filter($dict);
        if (empty($dict)) {
            return $script;
        }
        $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title));
        foreach ($dict as $key => $value) {
            $value = json_encode($value);
            if (empty($value)) {
                $value = static::quote('');
            }
            $script[] = static::call('log', static::quote('%s: %o'), static::quote((string) $key), $value);
        }
        return $script;
    }
    /**
     *
     */
    private static function quote(string $arg) : string
    {
        return '"' . addcslashes($arg, "\"\n\\") . '"';
    }
    /**
     * @param mixed $args
     */
    private static function call(...$args) : string
    {
        $method = array_shift($args);
        if (!is_string($method)) {
            throw new \UnexpectedValueException('Expected the first arg to be a string, got: ' . var_export($method, true));
        }
        return static::call_array($method, $args);
    }
    /**
     * @param mixed[] $args
     */
    private static function call_array(string $method, array $args) : string
    {
        return 'c.' . $method . '(' . implode(', ', $args) . ');';
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

/**
 * Handler or Processor implementing this interface will be reset when Logger::reset() is called.
 *
 * Resetting ends a log cycle gets them back to their initial state.
 *
 * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
 * state, and getting it back to a state in which it can receive log records again.
 *
 * This is useful in case you want to avoid logs leaking between two requests or jobs when you
 * have a long running process like a worker or an application server serving multiple requests
 * in one process.
 *
 * @author GrÃ©goire Pineau <lyrixx@lyrixx.info>
 */
interface ResettableInterface
{
    /**
     * @return void
     */
    public function reset();
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

final class Utils
{
    const DEFAULT_JSON_FLAGS = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION | JSON_INVALID_UTF8_SUBSTITUTE | JSON_PARTIAL_OUTPUT_ON_ERROR;
    /**
     *
     */
    public static function getClass(object $object) : string
    {
        $class = \get_class($object);
        if (false === ($pos = \strpos($class, "@anonymous\x00"))) {
            return $class;
        }
        if (false === ($parent = \get_parent_class($class))) {
            return \Phabel\Target\Php80\Polyfill::substr($class, 0, $pos + 10);
        }
        return $parent . '@anonymous';
    }
    /**
     *
     */
    public static function substr(string $string, int $start, ?int $length = null) : string
    {
        if (extension_loaded('mbstring')) {
            return mb_strcut($string, $start, $length);
        }
        return \Phabel\Target\Php80\Polyfill::substr($string, $start, null === $length ? strlen($string) : $length);
    }
    /**
     * Makes sure if a relative path is passed in it is turned into an absolute path
     *
     * @param string $streamUrl stream URL or path without protocol
     */
    public static function canonicalizePath(string $streamUrl) : string
    {
        $prefix = '';
        if ('file://' === \Phabel\Target\Php80\Polyfill::substr($streamUrl, 0, 7)) {
            $streamUrl = \Phabel\Target\Php80\Polyfill::substr($streamUrl, 7);
            $prefix = 'file://';
        }
        // other type of stream, not supported
        if (false !== strpos($streamUrl, '://')) {
            return $streamUrl;
        }
        // already absolute
        if (\Phabel\Target\Php80\Polyfill::substr($streamUrl, 0, 1) === '/' || \Phabel\Target\Php80\Polyfill::substr($streamUrl, 1, 1) === ':' || \Phabel\Target\Php80\Polyfill::substr($streamUrl, 0, 2) === '\\\\') {
            return $prefix . $streamUrl;
        }
        $streamUrl = getcwd() . '/' . $streamUrl;
        return $prefix . $streamUrl;
    }
    /**
     * Return the JSON representation of a value
     *
     * @param mixed $data
     * @param int $encodeFlags flags to pass to json encode, defaults to DEFAULT_JSON_FLAGS
     * @param bool $ignoreErrors whether to ignore encoding errors or to throw on error, when ignored and the encoding fails, "null" is returned which is valid json for null
     * @throws \RuntimeException if encoding fails and errors are not ignored
     * @return string when errors are ignored and the encoding fails, "null" is returned which is valid json for null
     */
    public static function jsonEncode($data, ?int $encodeFlags = null, bool $ignoreErrors = false) : string
    {
        if (null === $encodeFlags) {
            $encodeFlags = self::DEFAULT_JSON_FLAGS;
        }
        if ($ignoreErrors) {
            $json = @json_encode($data, $encodeFlags);
            if (false === $json) {
                return 'null';
            }
            return $json;
        }
        $json = json_encode($data, $encodeFlags);
        if (false === $json) {
            $json = self::handleJsonError(json_last_error(), $data);
        }
        return $json;
    }
    /**
    * Handle a json_encode failure.
    *
    * If the failure is due to invalid string encoding, try to clean the
    input and encode again. If the second encoding attempt fails, the
    initial error is not encoding related or the input can't be cleaned then
    raise a descriptive exception.
    *
    * @param int $code return code of json_last_error function
    * @param mixed $data data that was meant to be encoded
    * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION
    * @throws \RuntimeException if failure can't be corrected
    * @return string JSON encoded data after error correction
    */
    public static function handleJsonError(int $code, $data, ?int $encodeFlags = null) : string
    {
        if ($code !== JSON_ERROR_UTF8) {
            self::throwEncodeError($code, $data);
        }
        if (is_string($data)) {
            self::detectAndCleanUtf8($data);
        } elseif (is_array($data)) {
            array_walk_recursive($data, array('Monolog\\Utils', 'detectAndCleanUtf8'));
        } else {
            self::throwEncodeError($code, $data);
        }
        if (null === $encodeFlags) {
            $encodeFlags = self::DEFAULT_JSON_FLAGS;
        }
        $json = json_encode($data, $encodeFlags);
        if ($json === false) {
            self::throwEncodeError(json_last_error(), $data);
        }
        return $json;
    }
    /**
     * @internal
     */
    public static function pcreLastErrorMessage(int $code) : string
    {
        if (PHP_VERSION_ID >= 80000) {
            return preg_last_error_msg();
        }
        $constants = get_defined_constants(true)['pcre'];
        $constants = array_filter($constants, function ($key) {
            return \Phabel\Target\Php80\Polyfill::substr($key, -6) == '_ERROR';
        }, ARRAY_FILTER_USE_KEY);
        $constants = array_flip($constants);
        return $constants[$code] ?? 'UNDEFINED_ERROR';
    }
    /**
     * Throws an exception according to a given code with a customized message
     *
     * @param int $code return code of json_last_error function
     * @param mixed $data data that was meant to be encoded
     * @throws \RuntimeException
     *
     * @return never
     */
    private static function throwEncodeError(int $code, $data) : void
    {
        switch ($code) {
            case JSON_ERROR_DEPTH:
                $msg = 'Maximum stack depth exceeded';
                break;
            case JSON_ERROR_STATE_MISMATCH:
                $msg = 'Underflow or the modes mismatch';
                break;
            case JSON_ERROR_CTRL_CHAR:
                $msg = 'Unexpected control character found';
                break;
            case JSON_ERROR_UTF8:
                $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
                break;
            default:
                $msg = 'Unknown error';
        }
        throw new \RuntimeException('JSON encoding failed: ' . $msg . '. Encoding: ' . var_export($data, true));
    }
    /**
    * Detect invalid UTF-8 string characters and convert to valid UTF-8.
    *
    * Valid UTF-8 input will be left unmodified, but strings containing
    invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed
    original encoding of ISO-8859-15. This conversion may result in
    incorrect output if the actual encoding was not ISO-8859-15, but it
    will be clean UTF-8 output and will not rely on expensive and fragile
    detection algorithms.
    *
    * Function converts the input in place in the passed variable so that it
    can be used as a callback for array_walk_recursive.
    *
    * @param mixed $data Input to check and convert if needed, passed by ref
    */
    private static function detectAndCleanUtf8(&$data) : void
    {
        if (is_string($data) && !preg_match('//u', $data)) {
            $data = preg_replace_callback('/[\\x80-\\xFF]+/', function ($m) {
                return utf8_encode($m[0]);
            }, $data);
            if (!is_string($data)) {
                $pcreErrorCode = preg_last_error();
                throw new \RuntimeException('Failed to preg_replace_callback: ' . $pcreErrorCode . ' / ' . self::pcreLastErrorMessage($pcreErrorCode));
            }
            $data = str_replace(['Â¤', 'Â¦', 'Â¨', 'Â´', 'Â¸', 'Â¼', 'Â½', 'Â¾'], ['â‚¬', 'Å ', 'Å¡', 'Å½', 'Å¾', 'Å’', 'Å“', 'Å¸'], $data);
        }
    }
    /**
     * Converts a string with a valid 'memory_limit' format, to bytes.
     *
     * @param (string | false) $val
     * @return (int | false) Returns an integer representing bytes. Returns FALSE in case of error.
     */
    public static function expandIniShorthandBytes($val)
    {
        if (!is_string($val)) {
            return false;
        }
        // support -1
        if ((int) $val < 0) {
            return (int) $val;
        }
        if (!preg_match('/^\\s*(?<val>\\d+)(?:\\.\\d+)?\\s*(?<unit>[gmk]?)\\s*$/i', $val, $match)) {
            return false;
        }
        $val = (int) $match['val'];
        switch (strtolower($match['unit'] ?? '')) {
            case 'g':
                $val *= 1024;
            case 'm':
                $val *= 1024;
            case 'k':
                $val *= 1024;
        }
        return $val;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Test;

use Monolog\Logger;
use Monolog\DateTimeImmutable;
use Monolog\Formatter\FormatterInterface;
/**
 * Lets you easily generate log records and a dummy formatter for testing purposes
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
class TestCase extends \PHPUnit\Framework\TestCase
{
    /**
     * @param mixed[] $context
     *
     * @return array Record
     *
     * @phpstan-param Level $level
     * @phpstan-return Record
     */
    protected function getRecord(int $level = Logger::WARNING, string $message = 'test', array $context = []) : array
    {
        return ['message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => Logger::getLevelName($level), 'channel' => 'test', 'datetime' => new DateTimeImmutable(true), 'extra' => []];
    }
    /**
     * @phpstan-return Record[]
     */
    protected function getMultipleRecords() : array
    {
        return [$this->getRecord(Logger::DEBUG, 'debug message 1'), $this->getRecord(Logger::DEBUG, 'debug message 2'), $this->getRecord(Logger::INFO, 'information'), $this->getRecord(Logger::WARNING, 'warning'), $this->getRecord(Logger::ERROR, 'error')];
    }
    /**
     *
     */
    protected function getIdentityFormatter() : FormatterInterface
    {
        $formatter = $this->createMock(FormatterInterface::class);
        $formatter->expects($this->any())->method('format')->will($this->returnCallback(function ($record) {
            return $record['message'];
        }));
        return $formatter;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Injects url/method and remote IP of the current web request in all records
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class WebProcessor implements ProcessorInterface
{
    /**
     * @var array<string, mixed>|\ArrayAccess<string, mixed>
     */
    protected $serverData;
    /**
     * Default fields
     *
     * Array is structured as [key in record.extra => key in $serverData]
     *
     * @var array<string, string>
     */
    protected $extraFields = ['url' => 'REQUEST_URI', 'ip' => 'REMOTE_ADDR', 'http_method' => 'REQUEST_METHOD', 'server' => 'SERVER_NAME', 'referrer' => 'HTTP_REFERER'];
    /**
     * @param (array<string, mixed> | \ArrayAccess<string, mixed> | null) $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data
     * @param (array<string, string> | null) $extraFields Field names and the related key inside $serverData to be added. If not provided it defaults to: url, ip, http_method, server, referrer
     */
    public function __construct($serverData = null, array $extraFields = null)
    {
        if (null === $serverData) {
            $this->serverData =& $_SERVER;
        } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) {
            $this->serverData = $serverData;
        } else {
            throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.');
        }
        if (isset($this->serverData['UNIQUE_ID'])) {
            $this->extraFields['unique_id'] = 'UNIQUE_ID';
        }
        if (null !== $extraFields) {
            if (isset($extraFields[0])) {
                foreach (array_keys($this->extraFields) as $fieldName) {
                    if (!in_array($fieldName, $extraFields)) {
                        unset($this->extraFields[$fieldName]);
                    }
                }
            } else {
                $this->extraFields = $extraFields;
            }
        }
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        // skip processing if for some reason request data
        // is not present (CLI or wonky SAPIs)
        if (!isset($this->serverData['REQUEST_URI'])) {
            return $record;
        }
        $record['extra'] = $this->appendExtraFields($record['extra']);
        return $record;
    }
    /**
     *
     */
    public function addExtraField(string $extraName, string $serverName) : self
    {
        $this->extraFields[$extraName] = $serverName;
        return $this;
    }
    /**
     * @param mixed[] $extra
     * @return mixed[]
     */
    private function appendExtraFields(array $extra) : array
    {
        foreach ($this->extraFields as $extraName => $serverName) {
            $extra[$extraName] = $this->serverData[$serverName] ?? null;
        }
        return $extra;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Injects memory_get_usage in all records
 *
 * @see Monolog\Processor\MemoryProcessor::__construct() for options
 * @author Rob Jensen
 */
class MemoryUsageProcessor extends MemoryProcessor
{
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $usage = memory_get_usage($this->realUsage);
        if ($this->useFormatting) {
            $usage = $this->formatBytes($usage);
        }
        $record['extra']['memory_usage'] = $usage;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\ResettableInterface;
/**
 * Adds a unique identifier into records
 *
 * @author Simon MÃ¶nch <sm@webfactory.de>
 */
class UidProcessor implements ProcessorInterface, ResettableInterface
{
    /** @var string */
    private $uid;
    /**
     *
     */
    public function __construct(int $length = 7)
    {
        if ($length > 32 || $length < 1) {
            throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
        }
        $this->uid = $this->generateUid($length);
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $record['extra']['uid'] = $this->uid;
        return $record;
    }
    /**
     *
     */
    public function getUid() : string
    {
        return $this->uid;
    }
    /**
     *
     */
    public function reset()
    {
        $this->uid = $this->generateUid(strlen($this->uid));
    }
    /**
     *
     */
    private function generateUid(int $length) : string
    {
        return \Phabel\Target\Php80\Polyfill::substr(bin2hex(random_bytes((int) ceil($length / 2))), 0, $length);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Some methods that are common for all memory processors
 *
 * @author Rob Jensen
 */
abstract class MemoryProcessor implements ProcessorInterface
{
    /**
     * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported.
     */
    protected $realUsage;
    /**
     * @var bool If true, then format memory size to human readable string (MB, KB, B depending on size)
     */
    protected $useFormatting;
    /**
     * @param bool $realUsage Set this to true to get the real size of memory allocated from system.
     * @param bool $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size)
     */
    public function __construct(bool $realUsage = true, bool $useFormatting = true)
    {
        $this->realUsage = $realUsage;
        $this->useFormatting = $useFormatting;
    }
    /**
     * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is
     *
     * @param int $bytes
     * @return (string | int) Formatted string if $this->useFormatting is true, otherwise return $bytes as int
     */
    protected function formatBytes(int $bytes)
    {
        if (!$this->useFormatting) {
            return $bytes;
        }
        if ($bytes > 1024 * 1024) {
            return round($bytes / 1024 / 1024, 2) . ' MB';
        } elseif ($bytes > 1024) {
            return round($bytes / 1024, 2) . ' KB';
        }
        return $bytes . ' B';
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * An optional interface to allow labelling Monolog processors.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
interface ProcessorInterface
{
    /**
     * @return array The processed record
     *
     * @phpstan-param Record $record
     * @phpstan-return Record
     */
    public function __invoke(array $record);
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Adds value of getmypid into records
 *
 * @author Andreas HÃ¶rnicke
 */
class ProcessIdProcessor implements ProcessorInterface
{
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $record['extra']['process_id'] = getmypid();
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Injects memory_get_peak_usage in all records
 *
 * @see Monolog\Processor\MemoryProcessor::__construct() for options
 * @author Rob Jensen
 */
class MemoryPeakUsageProcessor extends MemoryProcessor
{
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $usage = memory_get_peak_usage($this->realUsage);
        if ($this->useFormatting) {
            $usage = $this->formatBytes($usage);
        }
        $record['extra']['memory_peak_usage'] = $usage;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Injects value of gethostname in all records
 */
class HostnameProcessor implements ProcessorInterface
{
    /** @var string */
    private static $host;
    /**
     *
     */
    public function __construct()
    {
        self::$host = (string) gethostname();
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $record['extra']['hostname'] = self::$host;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\Utils;
/**
 * Processes a record's message according to PSR-3 rules
 *
 * It replaces {foo} with the value from $context['foo']
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PsrLogMessageProcessor implements ProcessorInterface
{
    public const SIMPLE_DATE = "Y-m-d\\TH:i:s.uP";
    /** @var string|null */
    private $dateFormat;
    /** @var bool */
    private $removeUsedContextFields;
    /**
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     * @param bool $removeUsedContextFields If set to true the fields interpolated into message gets unset
     */
    public function __construct(?string $dateFormat = null, bool $removeUsedContextFields = false)
    {
        $this->dateFormat = $dateFormat;
        $this->removeUsedContextFields = $removeUsedContextFields;
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        if (false === strpos($record['message'], '{')) {
            return $record;
        }
        $replacements = [];
        foreach ($record['context'] as $key => $val) {
            $placeholder = '{' . $key . '}';
            if (strpos($record['message'], $placeholder) === false) {
                continue;
            }
            if (is_null($val) || is_scalar($val) || is_object($val) && method_exists($val, "__toString")) {
                $replacements[$placeholder] = $val;
            } elseif ($val instanceof \DateTimeInterface) {
                if (!$this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) {
                    // handle monolog dates using __toString if no specific dateFormat was asked for
                    // so that it follows the useMicroseconds flag
                    $replacements[$placeholder] = (string) $val;
                } else {
                    $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE);
                }
            } elseif (is_object($val)) {
                $replacements[$placeholder] = '[object ' . Utils::getClass($val) . ']';
            } elseif (is_array($val)) {
                $replacements[$placeholder] = 'array' . Utils::jsonEncode($val, null, true);
            } else {
                $replacements[$placeholder] = '[' . gettype($val) . ']';
            }
            if ($this->removeUsedContextFields) {
                unset($record['context'][$key]);
            }
        }
        $record['message'] = strtr($record['message'], $replacements);
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Injects Hg branch and Hg revision number in all records
 *
 * @author Jonathan A. Schweder <jonathanschweder@gmail.com>
 *
 * @phpstan-import-type LevelName from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
class MercurialProcessor implements ProcessorInterface
{
    /** @var Level */
    private $level;
    /** @var array{branch: string, revision: string}|array<never>|null */
    private static $cache = null;
    /**
     * @param (int | string) $level The minimum logging level at which this Processor will be triggered
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        // return if the level is not high enough
        if ($record['level'] < $this->level) {
            return $record;
        }
        $record['extra']['hg'] = self::getMercurialInfo();
        return $record;
    }
    /**
     * @return (array{branch: string, revision: string} | array<never>)
     */
    private static function getMercurialInfo() : array
    {
        if (self::$cache) {
            return self::$cache;
        }
        $result = explode(' ', trim(`hg id -nb`));
        if (count($result) >= 3) {
            return self::$cache = ['branch' => $result[1], 'revision' => $result[2]];
        }
        return self::$cache = [];
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Injects Git branch and Git commit SHA in all records
 *
 * @author Nick Otter
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class GitProcessor implements ProcessorInterface
{
    /** @var int */
    private $level;
    /** @var array{branch: string, commit: string}|array<never>|null */
    private static $cache = null;
    /**
     * @param (string | int) $level The minimum logging level at which this Processor will be triggered
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        // return if the level is not high enough
        if ($record['level'] < $this->level) {
            return $record;
        }
        $record['extra']['git'] = self::getGitInfo();
        return $record;
    }
    /**
     * @return (array{branch: string, commit: string} | array<never>)
     */
    private static function getGitInfo() : array
    {
        if (self::$cache) {
            return self::$cache;
        }
        $branches = `git branch -v --no-abbrev`;
        if ($branches && preg_match('{^\\* (.+?)\\s+([a-f0-9]{40})(?:\\s|$)}m', $branches, $matches)) {
            return self::$cache = ['branch' => $matches[1], 'commit' => $matches[2]];
        }
        return self::$cache = [];
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Adds a tags array into record
 *
 * @author Martijn Riemers
 */
class TagProcessor implements ProcessorInterface
{
    /** @var string[] */
    private $tags;
    /**
     * @param string[] $tags
     */
    public function __construct(array $tags = [])
    {
        $this->setTags($tags);
    }
    /**
     * @param string[] $tags
     */
    public function addTags(array $tags = []) : self
    {
        $this->tags = array_merge($this->tags, $tags);
        return $this;
    }
    /**
     * @param string[] $tags
     */
    public function setTags(array $tags = []) : self
    {
        $this->tags = $tags;
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $record['extra']['tags'] = $this->tags;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Injects line/file:class/function where the log message came from
 *
 * Warning: This only works if the handler processes the logs directly.
 * If you put the processor on a handler that is behind a FingersCrossedHandler
 * for example, the processor will only be called once the trigger level is reached,
 * and all the log records will have the same file/line/.. data from the call that
 * triggered the FingersCrossedHandler.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class IntrospectionProcessor implements ProcessorInterface
{
    /** @var int */
    private $level;
    /** @var string[] */
    private $skipClassesPartials;
    /** @var int */
    private $skipStackFramesCount;
    /** @var string[] */
    private $skipFunctions = ['call_user_func', 'call_user_func_array'];
    /**
     * @param (string | int) $level The minimum logging level at which this Processor will be triggered
     * @param string[] $skipClassesPartials
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
    {
        $this->level = Logger::toMonologLevel($level);
        $this->skipClassesPartials = array_merge(['Monolog\\'], $skipClassesPartials);
        $this->skipStackFramesCount = $skipStackFramesCount;
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        // return if the level is not high enough
        if ($record['level'] < $this->level) {
            return $record;
        }
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
        // skip first since it's always the current method
        array_shift($trace);
        // the call_user_func call is also skipped
        array_shift($trace);
        $i = 0;
        while ($this->isTraceClassOrSkippedFunction($trace, $i)) {
            if (isset($trace[$i]['class'])) {
                foreach ($this->skipClassesPartials as $part) {
                    if (strpos($trace[$i]['class'], $part) !== false) {
                        $i++;
                        continue 2;
                    }
                }
            } elseif (in_array($trace[$i]['function'], $this->skipFunctions)) {
                $i++;
                continue;
            }
            break;
        }
        $i += $this->skipStackFramesCount;
        // we should have the call source now
        $record['extra'] = array_merge($record['extra'], ['file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null, 'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null, 'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, 'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null]);
        return $record;
    }
    /**
     * @param array[] $trace
     */
    private function isTraceClassOrSkippedFunction(array $trace, int $index) : bool
    {
        if (!isset($trace[$index])) {
            return false;
        }
        return isset($trace[$index]['class']) || in_array($trace[$index]['function'], $this->skipFunctions);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use DateTimeZone;
use Monolog\Handler\HandlerInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
use Throwable;
use Stringable;
/**
 * Monolog log channel
 *
 * It contains a stack of Handlers and a stack of Processors,
 * and uses them to store records that are added to it.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY
 * @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY'
 * @phpstan-type Record array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]}
 */
class Logger implements LoggerInterface, ResettableInterface
{
    /**
     * Detailed debug information
     */
    public const DEBUG = 100;
    /**
     * Interesting events
     *
     * Examples: User logs in, SQL logs.
     */
    public const INFO = 200;
    /**
     * Uncommon events
     */
    public const NOTICE = 250;
    /**
     * Exceptional occurrences that are not errors
     *
     * Examples: Use of deprecated APIs, poor use of an API,
     * undesirable things that are not necessarily wrong.
     */
    public const WARNING = 300;
    /**
     * Runtime errors
     */
    public const ERROR = 400;
    /**
     * Critical conditions
     *
     * Example: Application component unavailable, unexpected exception.
     */
    public const CRITICAL = 500;
    /**
     * Action must be taken immediately
     *
     * Example: Entire website down, database unavailable, etc.
     * This should trigger the SMS alerts and wake you up.
     */
    public const ALERT = 550;
    /**
     * Urgent alert.
     */
    public const EMERGENCY = 600;
    /**
     * Monolog API version
     *
     * This is only bumped when API breaks are done and should
     * follow the major version of the library
     *
     * @var int
     */
    public const API = 2;
    /**
     * This is a static variable and not a constant to serve as an extension point for custom levels
     *
     * @var array<int, string> $levels Logging levels with the levels as key
     *
     * @phpstan-var array<Level, LevelName> $levels Logging levels with the levels as key
     */
    protected static $levels = [self::DEBUG => 'DEBUG', self::INFO => 'INFO', self::NOTICE => 'NOTICE', self::WARNING => 'WARNING', self::ERROR => 'ERROR', self::CRITICAL => 'CRITICAL', self::ALERT => 'ALERT', self::EMERGENCY => 'EMERGENCY'];
    /**
     * @var string
     */
    protected $name;
    /**
     * The handler stack
     *
     * @var HandlerInterface[]
     */
    protected $handlers;
    /**
     * Processors that will process all log records
     *
     * To process records of a single handler instead, add the processor on that specific handler
     *
     * @var callable[]
     */
    protected $processors;
    /**
     * @var bool
     */
    protected $microsecondTimestamps = true;
    /**
     * @var DateTimeZone
     */
    protected $timezone;
    /**
     * @var callable|null
     */
    protected $exceptionHandler;
    /**
     * @psalm-param array<callable(array ): array> $processors
     *
     * @param string $name The logging channel, a simple descriptive name that is attached to all log records
     * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
     * @param callable[] $processors Optional array of processors
     * @param (DateTimeZone | null) $timezone Optional timezone, if not provided date_default_timezone_get() will be used
     */
    public function __construct(string $name, array $handlers = [], array $processors = [], ?DateTimeZone $timezone = null)
    {
        $this->name = $name;
        $this->setHandlers($handlers);
        $this->processors = $processors;
        $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC');
    }
    /**
     *
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * Return a new cloned instance with the name changed
     */
    public function withName(string $name) : self
    {
        $new = clone $this;
        $new->name = $name;
        return $new;
    }
    /**
     * Pushes a handler on to the stack.
     */
    public function pushHandler(HandlerInterface $handler) : self
    {
        array_unshift($this->handlers, $handler);
        return $this;
    }
    /**
     * Pops a handler from the stack
     *
     * @throws \LogicException If empty handler stack
     */
    public function popHandler() : HandlerInterface
    {
        if (!$this->handlers) {
            throw new \LogicException('You tried to pop from an empty handler stack.');
        }
        return array_shift($this->handlers);
    }
    /**
     * Set handlers, replacing all existing ones.
     *
     * If a map is passed, keys will be ignored.
     *
     * @param HandlerInterface[] $handlers
     */
    public function setHandlers(array $handlers) : self
    {
        $this->handlers = [];
        foreach (array_reverse($handlers) as $handler) {
            $this->pushHandler($handler);
        }
        return $this;
    }
    /**
     * @return HandlerInterface[]
     */
    public function getHandlers() : array
    {
        return $this->handlers;
    }
    /**
     * Adds a processor on to the stack.
     */
    public function pushProcessor(callable $callback) : self
    {
        array_unshift($this->processors, $callback);
        return $this;
    }
    /**
     * Removes the processor on top of the stack and returns it.
     *
     * @throws \LogicException If empty processor stack
     * @return callable
     */
    public function popProcessor() : callable
    {
        if (!$this->processors) {
            throw new \LogicException('You tried to pop from an empty processor stack.');
        }
        return array_shift($this->processors);
    }
    /**
     * @return callable[]
     */
    public function getProcessors() : array
    {
        return $this->processors;
    }
    /**
    * Control the use of microsecond resolution timestamps in the 'datetime'
    member of new records.
    *
    * As of PHP7.1 microseconds are always included by the engine, so
    there is no performance penalty and Monolog 2 enabled microseconds
    by default. This function lets you disable them though in case you want
    to suppress microseconds from the output.
    *
    * @param bool $micro True to use microtime() to create timestamps
    */
    public function useMicrosecondTimestamps(bool $micro) : void
    {
        $this->microsecondTimestamps = $micro;
    }
    /**
     * Adds a log record.
     *
     * @param int $level The logging level
     * @param string $message The log message
     * @param mixed[] $context The log context
     * @return bool Whether the record has been processed
     *
     * @phpstan-param Level $level
     */
    public function addRecord(int $level, string $message, array $context = []) : bool
    {
        $offset = 0;
        $record = null;
        foreach ($this->handlers as $handler) {
            if (null === $record) {
                // skip creating the record as long as no handler is going to handle it
                if (!$handler->isHandling(['level' => $level])) {
                    continue;
                }
                $levelName = static::getLevelName($level);
                $record = ['message' => $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, 'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), 'extra' => []];
                try {
                    foreach ($this->processors as $processor) {
                        $record = $processor($record);
                    }
                } catch (Throwable $e) {
                    $this->handleException($e, $record);
                    return true;
                }
            }
            // once the record exists, send it to all handlers as long as the bubbling chain is not interrupted
            try {
                if (true === $handler->handle($record)) {
                    break;
                }
            } catch (Throwable $e) {
                $this->handleException($e, $record);
                return true;
            }
        }
        return null !== $record;
    }
    /**
    * Ends a log cycle and frees all resources used by handlers.
    *
    * Closing a Handler means flushing all buffers and freeing any open resources/handles.
    Handlers that have been closed should be able to accept log records again and re-open
    themselves on demand, but this may not always be possible depending on implementation.
    *
    * This is useful at the end of a request and will be called automatically on every handler
    when they get destructed.
    */
    public function close() : void
    {
        foreach ($this->handlers as $handler) {
            $handler->close();
        }
    }
    /**
    * Ends a log cycle and resets all handlers and processors to their initial state.
    *
    * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
    state, and getting it back to a state in which it can receive log records again.
    *
    * This is useful in case you want to avoid logs leaking between two requests or jobs when you
    have a long running process like a worker or an application server serving multiple requests
    in one process.
    */
    public function reset() : void
    {
        foreach ($this->handlers as $handler) {
            if ($handler instanceof ResettableInterface) {
                $handler->reset();
            }
        }
        foreach ($this->processors as $processor) {
            if ($processor instanceof ResettableInterface) {
                $processor->reset();
            }
        }
    }
    /**
     * Gets all supported logging levels.
     *
     * @return array<string, int> Assoc array with human-readable level names => level codes.
     * @phpstan-return array<LevelName, Level>
     */
    public static function getLevels() : array
    {
        return array_flip(static::$levels);
    }
    /**
     * Gets the name of the logging level.
     *
     * @throws \Psr\Log\InvalidArgumentException If level is not defined
     *
     * @phpstan-param Level $level
     * @phpstan-return LevelName
     */
    public static function getLevelName(int $level) : string
    {
        if (!isset(static::$levels[$level])) {
            throw new InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . implode(', ', array_keys(static::$levels)));
        }
        return static::$levels[$level];
    }
    /**
     * Converts PSR-3 levels to Monolog ones if necessary
     *
     * @param (string | int) $level Level number (monolog) or name (PSR-3)
     * @throws \Psr\Log\InvalidArgumentException If level is not defined
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     * @phpstan-return Level
     */
    public static function toMonologLevel($level) : int
    {
        if (is_string($level)) {
            if (is_numeric($level)) {
                /** @phpstan-ignore-next-line */
                return intval($level);
            }
            // Contains chars of all log levels and avoids using strtoupper() which may have
            // strange results depending on locale (for example, "i" will become "Ä°" in Turkish locale)
            $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY');
            if (defined(__CLASS__ . '::' . $upper)) {
                return constant(__CLASS__ . '::' . $upper);
            }
            throw new InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . implode(', ', array_keys(static::$levels) + static::$levels));
        }
        if (!is_int($level)) {
            throw new InvalidArgumentException('Level "' . var_export($level, true) . '" is not defined, use one of: ' . implode(', ', array_keys(static::$levels) + static::$levels));
        }
        return $level;
    }
    /**
     * Checks whether the Logger has a handler that listens on the given level
     *
     * @phpstan-param Level $level
     */
    public function isHandling(int $level) : bool
    {
        $record = ['level' => $level];
        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($record)) {
                return true;
            }
        }
        return false;
    }
    /**
     * Set a custom exception handler that will be called if adding a new record fails
     *
     * The callable will receive an exception object and the record that failed to be logged
     */
    public function setExceptionHandler(?callable $callback) : self
    {
        $this->exceptionHandler = $callback;
        return $this;
    }
    /**
     *
     */
    public function getExceptionHandler() : ?callable
    {
        return $this->exceptionHandler;
    }
    /**
     * Adds a log record at an arbitrary level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param mixed $level The log level
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function log($level, $message, array $context = []) : void
    {
        if (!is_int($level) && !is_string($level)) {
            throw new \InvalidArgumentException('$level is expected to be a string or int');
        }
        $level = static::toMonologLevel($level);
        $this->addRecord($level, (string) $message, $context);
    }
    /**
     * Adds a log record at the DEBUG level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function debug($message, array $context = []) : void
    {
        $this->addRecord(static::DEBUG, (string) $message, $context);
    }
    /**
     * Adds a log record at the INFO level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function info($message, array $context = []) : void
    {
        $this->addRecord(static::INFO, (string) $message, $context);
    }
    /**
     * Adds a log record at the NOTICE level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function notice($message, array $context = []) : void
    {
        $this->addRecord(static::NOTICE, (string) $message, $context);
    }
    /**
     * Adds a log record at the WARNING level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function warning($message, array $context = []) : void
    {
        $this->addRecord(static::WARNING, (string) $message, $context);
    }
    /**
     * Adds a log record at the ERROR level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function error($message, array $context = []) : void
    {
        $this->addRecord(static::ERROR, (string) $message, $context);
    }
    /**
     * Adds a log record at the CRITICAL level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function critical($message, array $context = []) : void
    {
        $this->addRecord(static::CRITICAL, (string) $message, $context);
    }
    /**
     * Adds a log record at the ALERT level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function alert($message, array $context = []) : void
    {
        $this->addRecord(static::ALERT, (string) $message, $context);
    }
    /**
     * Adds a log record at the EMERGENCY level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function emergency($message, array $context = []) : void
    {
        $this->addRecord(static::EMERGENCY, (string) $message, $context);
    }
    /**
     * Sets the timezone to be used for the timestamp of log records.
     */
    public function setTimezone(DateTimeZone $tz) : self
    {
        $this->timezone = $tz;
        return $this;
    }
    /**
     * Returns the timezone to be used for the timestamp of log records.
     */
    public function getTimezone() : DateTimeZone
    {
        return $this->timezone;
    }
    /**
    * Delegates exception management to the custom exception handler,
    or throws the exception if no custom handler is set.
    *
    * @param array $record
    * @phpstan-param Record $record
    */
    protected function handleException(Throwable $e, array $record) : void
    {
        if (!$this->exceptionHandler) {
            throw $e;
        }
        ($this->exceptionHandler)($e, $record);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use DateTimeZone;
/**
 * Overrides default json encoding of date time objects
 *
 * @author Menno Holtkamp
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
{
    /**
     * @var bool
     */
    private $useMicroseconds;
    /**
     *
     */
    public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null)
    {
        $this->useMicroseconds = $useMicroseconds;
        parent::__construct('now', $timezone);
    }
    /**
     *
     */
    public function jsonSerialize() : string
    {
        if ($this->useMicroseconds) {
            return $this->format('Y-m-d\\TH:i:s.uP');
        }
        return $this->format('Y-m-d\\TH:i:sP');
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->jsonSerialize();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use ReflectionExtension;
/**
 * Monolog POSIX signal handler
 *
 * @author Robert Gust-Bardon <robert@gust-bardon.org>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class SignalHandler
{
    /** @var LoggerInterface */
    private $logger;
    /** @var array<int, callable|string|int> SIG_DFL, SIG_IGN or previous callable */
    private $previousSignalHandler = [];
    /** @var array<int, int> */
    private $signalLevelMap = [];
    /** @var array<int, bool> */
    private $signalRestartSyscalls = [];
    /**
     *
     */
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    /**
     * @param (int | string) $level Level or level name
     * @param bool $callPrevious
     * @param bool $restartSyscalls
     * @param (bool | null) $async
     * @return $this
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function registerSignalHandler(int $signo, $level = LogLevel::CRITICAL, bool $callPrevious = true, bool $restartSyscalls = true, ?bool $async = true) : self
    {
        if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) {
            return $this;
        }
        $level = Logger::toMonologLevel($level);
        if ($callPrevious) {
            $handler = pcntl_signal_get_handler($signo);
            $this->previousSignalHandler[$signo] = $handler;
        } else {
            unset($this->previousSignalHandler[$signo]);
        }
        $this->signalLevelMap[$signo] = $level;
        $this->signalRestartSyscalls[$signo] = $restartSyscalls;
        if ($async !== null) {
            \Phabel\Target\Php80\Polyfill::pcntl_async_signals($async);
        }
        pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls);
        return $this;
    }
    /**
     * @param mixed $siginfo
     */
    public function handleSignal(int $signo, $siginfo = null) : void
    {
        static $signals = [];
        if (!$signals && extension_loaded('pcntl')) {
            $pcntl = new ReflectionExtension('pcntl');
            // HHVM 3.24.2 returns an empty array.
            foreach ($pcntl->getConstants() ?: get_defined_constants(true)['Core'] as $name => $value) {
                if (\Phabel\Target\Php80\Polyfill::substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) {
                    $signals[$value] = $name;
                }
            }
        }
        $level = $this->signalLevelMap[$signo] ?? LogLevel::CRITICAL;
        $signal = $signals[$signo] ?? $signo;
        $context = $siginfo ?? [];
        $this->logger->log($level, sprintf('Program received signal %s', $signal), $context);
        if (!isset($this->previousSignalHandler[$signo])) {
            return;
        }
        if ($this->previousSignalHandler[$signo] === SIG_DFL) {
            if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch') && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill')) {
                $restartSyscalls = $this->signalRestartSyscalls[$signo] ?? true;
                pcntl_signal($signo, SIG_DFL, $restartSyscalls);
                pcntl_sigprocmask(SIG_UNBLOCK, [$signo], $oldset);
                posix_kill(posix_getpid(), $signo);
                pcntl_signal_dispatch();
                pcntl_sigprocmask(SIG_SETMASK, $oldset);
                pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls);
            }
        } elseif (is_callable($this->previousSignalHandler[$signo])) {
            $this->previousSignalHandler[$signo]($signo, $siginfo);
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use InvalidArgumentException;
/**
 * Monolog log registry
 *
 * Allows to get `Logger` instances in the global scope
 * via static method calls on this class.
 *
 * <code>
 * $application = new Monolog\Logger('application');
 * $api = new Monolog\Logger('api');
 *
 * Monolog\Registry::addLogger($application);
 * Monolog\Registry::addLogger($api);
 *
 * function testLogger()
 * {
 *     Monolog\Registry::api()->error('Sent to $api Logger instance');
 *     Monolog\Registry::application()->error('Sent to $application Logger instance');
 * }
 * </code>
 *
 * @author Tomas Tatarko <tomas@tatarko.sk>
 */
class Registry
{
    /**
     * List of all loggers in the registry (by named indexes)
     *
     * @var Logger[]
     */
    private static $loggers = [];
    /**
     * Adds new logging channel to the registry
     *
     * @param Logger $logger Instance of the logging channel
     * @param (string | null) $name Name of the logging channel ($logger->getName() by default)
     * @param bool $overwrite Overwrite instance in the registry if the given name already exists?
     * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists
     * @return void
     */
    public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = false)
    {
        $name = $name ?: $logger->getName();
        if (isset(self::$loggers[$name]) && !$overwrite) {
            throw new InvalidArgumentException('Logger with the given name already exists');
        }
        self::$loggers[$name] = $logger;
    }
    /**
     * Checks if such logging channel exists by name or instance
     *
     * @param (string | Logger) $logger Name or logger instance
     */
    public static function hasLogger($logger) : bool
    {
        if ($logger instanceof Logger) {
            $index = array_search($logger, self::$loggers, true);
            return false !== $index;
        }
        return isset(self::$loggers[$logger]);
    }
    /**
     * Removes instance from registry by name or instance
     *
     * @param (string | Logger) $logger Name or logger instance
     */
    public static function removeLogger($logger) : void
    {
        if ($logger instanceof Logger) {
            if (false !== ($idx = array_search($logger, self::$loggers, true))) {
                unset(self::$loggers[$idx]);
            }
        } else {
            unset(self::$loggers[$logger]);
        }
    }
    /**
     * Clears the registry
     */
    public static function clear() : void
    {
        self::$loggers = [];
    }
    /**
     * Gets Logger instance from the registry
     *
     * @param string $name Name of the requested Logger instance
     * @throws \InvalidArgumentException If named Logger instance is not in the registry
     */
    public static function getInstance($name) : Logger
    {
        if (!isset(self::$loggers[$name])) {
            throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name));
        }
        return self::$loggers[$name];
    }
    /**
     * Gets Logger instance from the registry via static method call
     *
     * @param string $name Name of the requested Logger instance
     * @param mixed[] $arguments Arguments passed to static method call
     * @throws \InvalidArgumentException If named Logger instance is not in the registry
     * @return Logger Requested instance of Logger
     */
    public static function __callStatic($name, $arguments)
    {
        return self::getInstance($name);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * formats the record to be used in the FlowdockHandler
 *
 * @author Dominik Liebler <liebler.dominik@gmail.com>
 */
class FlowdockFormatter implements FormatterInterface
{
    /**
     * @var string
     */
    private $source;
    /**
     * @var string
     */
    private $sourceEmail;
    /**
     *
     */
    public function __construct(string $source, string $sourceEmail)
    {
        $this->source = $source;
        $this->sourceEmail = $sourceEmail;
    }
    /**
     * {@inheritDoc}
     *
     * @return mixed[]
     */
    public function format(array $record) : array
    {
        $tags = ['#logs', '#' . strtolower($record['level_name']), '#' . $record['channel']];
        foreach ($record['extra'] as $value) {
            $tags[] = '#' . $value;
        }
        $subject = sprintf('in %s: %s - %s', $this->source, $record['level_name'], $this->getShortMessage($record['message']));
        $record['flowdock'] = ['source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, 'content' => $record['message'], 'tags' => $tags, 'project' => $this->source];
        return $record;
    }
    /**
     * {@inheritDoc}
     *
     * @return mixed[][]
     */
    public function formatBatch(array $records) : array
    {
        $formatted = [];
        foreach ($records as $record) {
            $formatted[] = $this->format($record);
        }
        return $formatted;
    }
    /**
     *
     */
    public function getShortMessage(string $message) : string
    {
        static $hasMbString;
        if (null === $hasMbString) {
            $hasMbString = function_exists('mb_strlen');
        }
        $maxLength = 45;
        if ($hasMbString) {
            if (mb_strlen($message, 'UTF-8') > $maxLength) {
                $message = mb_substr($message, 0, $maxLength - 4, 'UTF-8') . ' ...';
            }
        } else {
            if (strlen($message) > $maxLength) {
                $message = \Phabel\Target\Php80\Polyfill::substr($message, 0, $maxLength - 4) . ' ...';
            }
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Utils;
/**
 * Class FluentdFormatter
 *
 * Serializes a log message to Fluentd unix socket protocol
 *
 * Fluentd config:
 *
 * <source>
 *  type unix
 *  path /var/run/td-agent/td-agent.sock
 * </source>
 *
 * Monolog setup:
 *
 * $logger = new Monolog\Logger('fluent.tag');
 * $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock');
 * $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter());
 * $logger->pushHandler($fluentHandler);
 *
 * @author Andrius Putna <fordnox@gmail.com>
 */
class FluentdFormatter implements FormatterInterface
{
    /**
     * @var bool $levelTag should message level be a part of the fluentd tag
     */
    protected $levelTag = false;
    /**
     *
     */
    public function __construct(bool $levelTag = false)
    {
        if (!function_exists('json_encode')) {
            throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter');
        }
        $this->levelTag = $levelTag;
    }
    /**
     *
     */
    public function isUsingLevelsInTag() : bool
    {
        return $this->levelTag;
    }
    /**
     *
     */
    public function format(array $record) : string
    {
        $tag = $record['channel'];
        if ($this->levelTag) {
            $tag .= '.' . strtolower($record['level_name']);
        }
        $message = ['message' => $record['message'], 'context' => $record['context'], 'extra' => $record['extra']];
        if (!$this->levelTag) {
            $message['level'] = $record['level'];
            $message['level_name'] = $record['level_name'];
        }
        return Utils::jsonEncode([$tag, $record['datetime']->getTimestamp(), $message]);
    }
    /**
     *
     */
    public function formatBatch(array $records) : string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Formats data into an associative array of scalar values.
 * Objects and arrays will be JSON encoded.
 *
 * @author Andrew Lawson <adlawson@gmail.com>
 */
class ScalarFormatter extends NormalizerFormatter
{
    /**
     * {@inheritDoc}
     *
     * @phpstan-return array<string, (scalar | null)> $record
     */
    public function format(array $record) : array
    {
        $result = [];
        foreach ($record as $key => $value) {
            $result[$key] = $this->normalizeValue($value);
        }
        return $result;
    }
    /**
     * @param mixed $value
     * @return (scalar | null)
     */
    protected function normalizeValue($value)
    {
        $normalized = $this->normalize($value);
        if (is_array($normalized)) {
            return $this->toJson($normalized, true);
        }
        return $normalized;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Serializes a log message to Logstash Event Format
 *
 * @see https://www.elastic.co/products/logstash
 * @see https://github.com/elastic/logstash/blob/master/logstash-core/src/main/java/org/logstash/Event.java
 *
 * @author Tim Mower <timothy.mower@gmail.com>
 */
class LogstashFormatter extends NormalizerFormatter
{
    /**
     * @var string the name of the system for the Logstash log message, used to fill the @source field
     */
    protected $systemName;
    /**
     * @var string an application name for the Logstash log message, used to fill the @type field
     */
    protected $applicationName;
    /**
     * @var string the key for 'extra' fields from the Monolog record
     */
    protected $extraKey;
    /**
     * @var string the key for 'context' fields from the Monolog record
     */
    protected $contextKey;
    /**
     * @param string $applicationName The application that sends the data, used as the "type" field of logstash
     * @param (string | null) $systemName The system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine
     * @param string $extraKey The key for extra keys inside logstash "fields", defaults to extra
     * @param string $contextKey The key for context keys inside logstash "fields", defaults to context
     */
    public function __construct(string $applicationName, ?string $systemName = null, string $extraKey = 'extra', string $contextKey = 'context')
    {
        // logstash requires a ISO 8601 format date with optional millisecond precision.
        parent::__construct('Y-m-d\\TH:i:s.uP');
        $this->systemName = $systemName === null ? (string) gethostname() : $systemName;
        $this->applicationName = $applicationName;
        $this->extraKey = $extraKey;
        $this->contextKey = $contextKey;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record) : string
    {
        $record = parent::format($record);
        if (empty($record['datetime'])) {
            $record['datetime'] = \Phabel\Target\Php80\Polyfill::gmdate('c');
        }
        $message = ['@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName];
        if (isset($record['message'])) {
            $message['message'] = $record['message'];
        }
        if (isset($record['channel'])) {
            $message['type'] = $record['channel'];
            $message['channel'] = $record['channel'];
        }
        if (isset($record['level_name'])) {
            $message['level'] = $record['level_name'];
        }
        if (isset($record['level'])) {
            $message['monolog_level'] = $record['level'];
        }
        if ($this->applicationName) {
            $message['type'] = $this->applicationName;
        }
        if (!empty($record['extra'])) {
            $message[$this->extraKey] = $record['extra'];
        }
        if (!empty($record['context'])) {
            $message[$this->contextKey] = $record['context'];
        }
        return $this->toJson($message) . "\n";
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use MongoDB\BSON\UTCDateTime;
use Monolog\Utils;
/**
 * Formats a record for use with the MongoDBHandler.
 *
 * @author Florian Plattner <me@florianplattner.de>
 */
class MongoDBFormatter implements FormatterInterface
{
    /** @var bool */
    private $exceptionTraceAsString;
    /** @var int */
    private $maxNestingLevel;
    /** @var bool */
    private $isLegacyMongoExt;
    /**
     * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2
     * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings
     */
    public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = true)
    {
        $this->maxNestingLevel = max($maxNestingLevel, 0);
        $this->exceptionTraceAsString = $exceptionTraceAsString;
        $this->isLegacyMongoExt = extension_loaded('mongodb') && version_compare((string) phpversion('mongodb'), '1.1.9', '<=');
    }
    /**
     * {@inheritDoc}
     *
     * @return mixed[]
     */
    public function format(array $record) : array
    {
        /** @var mixed[] $res */
        $res = $this->formatArray($record);
        return $res;
    }
    /**
     * {@inheritDoc}
     *
     * @return array<mixed[]>
     */
    public function formatBatch(array $records) : array
    {
        $formatted = [];
        foreach ($records as $key => $record) {
            $formatted[$key] = $this->format($record);
        }
        return $formatted;
    }
    /**
     * @param mixed[] $array
     * @return (mixed[] | string) Array except when max nesting level is reached then a string "[...]"
     */
    protected function formatArray(array $array, int $nestingLevel = 0)
    {
        if ($this->maxNestingLevel > 0 && $nestingLevel > $this->maxNestingLevel) {
            return '[...]';
        }
        foreach ($array as $name => $value) {
            if ($value instanceof \DateTimeInterface) {
                $array[$name] = $this->formatDate($value, $nestingLevel + 1);
            } elseif ($value instanceof \Throwable) {
                $array[$name] = $this->formatException($value, $nestingLevel + 1);
            } elseif (is_array($value)) {
                $array[$name] = $this->formatArray($value, $nestingLevel + 1);
            } elseif (is_object($value)) {
                $array[$name] = $this->formatObject($value, $nestingLevel + 1);
            }
        }
        return $array;
    }
    /**
     * @param mixed $value
     * @return (mixed[] | string)
     */
    protected function formatObject($value, int $nestingLevel)
    {
        $objectVars = get_object_vars($value);
        $objectVars['class'] = Utils::getClass($value);
        return $this->formatArray($objectVars, $nestingLevel);
    }
    /**
     * @return (mixed[] | string)
     */
    protected function formatException(\Throwable $exception, int $nestingLevel)
    {
        $formattedException = ['class' => Utils::getClass($exception), 'message' => $exception->getMessage(), 'code' => (int) $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine()];
        if ($this->exceptionTraceAsString === true) {
            $formattedException['trace'] = $exception->getTraceAsString();
        } else {
            $formattedException['trace'] = $exception->getTrace();
        }
        return $this->formatArray($formattedException, $nestingLevel);
    }
    /**
     *
     */
    protected function formatDate(\DateTimeInterface $value, int $nestingLevel) : UTCDateTime
    {
        if ($this->isLegacyMongoExt) {
            return $this->legacyGetMongoDbDateTime($value);
        }
        return $this->getMongoDbDateTime($value);
    }
    /**
     *
     */
    private function getMongoDbDateTime(\DateTimeInterface $value) : UTCDateTime
    {
        return new UTCDateTime((int) floor((float) $value->format('U.u') * 1000));
    }
    /**
     * This is needed to support MongoDB Driver v1.19 and below
     *
     * See https://github.com/mongodb/mongo-php-driver/issues/426
     *
     * It can probably be removed in 2.1 or later once MongoDB's 1.2 is released and widely adopted
     */
    private function legacyGetMongoDbDateTime(\DateTimeInterface $value) : UTCDateTime
    {
        $milliseconds = floor((float) $value->format('U.u') * 1000);
        $milliseconds = PHP_INT_SIZE == 8 ? (int) $milliseconds : (string) $milliseconds;
        // @phpstan-ignore-next-line
        return new UTCDateTime($milliseconds);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\DateTimeImmutable;
use Monolog\Utils;
use Throwable;
/**
 * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class NormalizerFormatter implements FormatterInterface
{
    public const SIMPLE_DATE = "Y-m-d\\TH:i:sP";
    /** @var string */
    protected $dateFormat;
    /** @var int */
    protected $maxNormalizeDepth = 9;
    /** @var int */
    protected $maxNormalizeItemCount = 1000;
    /** @var int */
    private $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS;
    /**
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        $this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat;
        if (!function_exists('json_encode')) {
            throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter');
        }
    }
    /**
     * {@inheritDoc}
     *
     * @param mixed[] $record
     */
    public function format(array $record)
    {
        return $this->normalize($record);
    }
    /**
     * {@inheritDoc}
     */
    public function formatBatch(array $records)
    {
        foreach ($records as $key => $record) {
            $records[$key] = $this->format($record);
        }
        return $records;
    }
    /**
     *
     */
    public function getDateFormat() : string
    {
        return $this->dateFormat;
    }
    /**
     *
     */
    public function setDateFormat(string $dateFormat) : self
    {
        $this->dateFormat = $dateFormat;
        return $this;
    }
    /**
     * The maximum number of normalization levels to go through
     */
    public function getMaxNormalizeDepth() : int
    {
        return $this->maxNormalizeDepth;
    }
    /**
     *
     */
    public function setMaxNormalizeDepth(int $maxNormalizeDepth) : self
    {
        $this->maxNormalizeDepth = $maxNormalizeDepth;
        return $this;
    }
    /**
     * The maximum number of items to normalize per level
     */
    public function getMaxNormalizeItemCount() : int
    {
        return $this->maxNormalizeItemCount;
    }
    /**
     *
     */
    public function setMaxNormalizeItemCount(int $maxNormalizeItemCount) : self
    {
        $this->maxNormalizeItemCount = $maxNormalizeItemCount;
        return $this;
    }
    /**
     * Enables `json_encode` pretty print.
     */
    public function setJsonPrettyPrint(bool $enable) : self
    {
        if ($enable) {
            $this->jsonEncodeOptions |= JSON_PRETTY_PRINT;
        } else {
            $this->jsonEncodeOptions &= ~JSON_PRETTY_PRINT;
        }
        return $this;
    }
    /**
     * @param mixed $data
     * @return (null | scalar | array<(array | scalar | null)>)
     */
    protected function normalize($data, int $depth = 0)
    {
        if ($depth > $this->maxNormalizeDepth) {
            return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
        }
        if (null === $data || is_scalar($data)) {
            if (is_float($data)) {
                if (is_infinite($data)) {
                    return ($data > 0 ? '' : '-') . 'INF';
                }
                if (is_nan($data)) {
                    return 'NaN';
                }
            }
            return $data;
        }
        if (is_array($data)) {
            $normalized = [];
            $count = 1;
            foreach ($data as $key => $value) {
                if ($count++ > $this->maxNormalizeItemCount) {
                    $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . count($data) . ' total), aborting normalization';
                    break;
                }
                $normalized[$key] = $this->normalize($value, $depth + 1);
            }
            return $normalized;
        }
        if ($data instanceof \DateTimeInterface) {
            return $this->formatDate($data);
        }
        if (is_object($data)) {
            if ($data instanceof Throwable) {
                return $this->normalizeException($data, $depth);
            }
            if ($data instanceof \JsonSerializable) {
                /** @var null|scalar|array<array|scalar|null> $value */
                $value = $data->jsonSerialize();
            } elseif (method_exists($data, '__toString')) {
                /** @var string $value */
                $value = $data->__toString();
            } else {
                // the rest is normalized by json encoding and decoding it
                /** @var null|scalar|array<array|scalar|null> $value */
                $value = json_decode($this->toJson($data, true), true);
            }
            return [Utils::getClass($data) => $value];
        }
        if (is_resource($data)) {
            return sprintf('[resource(%s)]', get_resource_type($data));
        }
        return '[unknown(' . gettype($data) . ')]';
    }
    /**
     * @return mixed[]
     */
    protected function normalizeException(Throwable $e, int $depth = 0)
    {
        if ($e instanceof \JsonSerializable) {
            return (array) $e->jsonSerialize();
        }
        $data = ['class' => Utils::getClass($e), 'message' => $e->getMessage(), 'code' => (int) $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine()];
        if ($e instanceof \SoapFault) {
            if (isset($e->faultcode)) {
                $data['faultcode'] = $e->faultcode;
            }
            if (isset($e->faultactor)) {
                $data['faultactor'] = $e->faultactor;
            }
            if (isset($e->detail)) {
                if (is_string($e->detail)) {
                    $data['detail'] = $e->detail;
                } elseif (is_object($e->detail) || is_array($e->detail)) {
                    $data['detail'] = $this->toJson($e->detail, true);
                }
            }
        }
        $trace = $e->getTrace();
        foreach ($trace as $frame) {
            if (isset($frame['file'])) {
                $data['trace'][] = $frame['file'] . ':' . $frame['line'];
            }
        }
        if ($previous = $e->getPrevious()) {
            $data['previous'] = $this->normalizeException($previous, $depth + 1);
        }
        return $data;
    }
    /**
     * Return the JSON representation of a value
     *
     * @param mixed $data
     * @throws \RuntimeException if encoding fails and errors are not ignored
     * @return string if encoding fails and ignoreErrors is true 'null' is returned
     */
    protected function toJson($data, bool $ignoreErrors = false) : string
    {
        return Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors);
    }
    /**
     * @return string
     */
    protected function formatDate(\DateTimeInterface $date)
    {
        // in case the date format isn't custom then we defer to the custom DateTimeImmutable
        // formatting logic, which will pick the right format based on whether useMicroseconds is on
        if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof DateTimeImmutable) {
            return (string) $date;
        }
        return $date->format($this->dateFormat);
    }
    /**
     *
     */
    public function addJsonEncodeOption(int $option) : void
    {
        $this->jsonEncodeOptions |= $option;
    }
    /**
     *
     */
    public function removeJsonEncodeOption(int $option) : void
    {
        $this->jsonEncodeOptions &= ~$option;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Utils;
/**
 * Formats incoming records into a one-line string
 *
 * This is especially useful for logging to files
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 */
class LineFormatter extends NormalizerFormatter
{
    public const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
    /** @var string */
    protected $format;
    /** @var bool */
    protected $allowInlineLineBreaks;
    /** @var bool */
    protected $ignoreEmptyContextAndExtra;
    /** @var bool */
    protected $includeStacktraces;
    /**
     * @param (string | null) $format The format of the message
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
     * @param bool $ignoreEmptyContextAndExtra
     */
    public function __construct(?string $format = null, ?string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false)
    {
        $this->format = $format === null ? static::SIMPLE_FORMAT : $format;
        $this->allowInlineLineBreaks = $allowInlineLineBreaks;
        $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
        parent::__construct($dateFormat);
    }
    /**
     *
     */
    public function includeStacktraces(bool $include = true) : void
    {
        $this->includeStacktraces = $include;
        if ($this->includeStacktraces) {
            $this->allowInlineLineBreaks = true;
        }
    }
    /**
     *
     */
    public function allowInlineLineBreaks(bool $allow = true) : void
    {
        $this->allowInlineLineBreaks = $allow;
    }
    /**
     *
     */
    public function ignoreEmptyContextAndExtra(bool $ignore = true) : void
    {
        $this->ignoreEmptyContextAndExtra = $ignore;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record) : string
    {
        $vars = parent::format($record);
        $output = $this->format;
        foreach ($vars['extra'] as $var => $val) {
            if (false !== strpos($output, '%extra.' . $var . '%')) {
                $output = str_replace('%extra.' . $var . '%', $this->stringify($val), $output);
                unset($vars['extra'][$var]);
            }
        }
        foreach ($vars['context'] as $var => $val) {
            if (false !== strpos($output, '%context.' . $var . '%')) {
                $output = str_replace('%context.' . $var . '%', $this->stringify($val), $output);
                unset($vars['context'][$var]);
            }
        }
        if ($this->ignoreEmptyContextAndExtra) {
            if (empty($vars['context'])) {
                unset($vars['context']);
                $output = str_replace('%context%', '', $output);
            }
            if (empty($vars['extra'])) {
                unset($vars['extra']);
                $output = str_replace('%extra%', '', $output);
            }
        }
        foreach ($vars as $var => $val) {
            if (false !== strpos($output, '%' . $var . '%')) {
                $output = str_replace('%' . $var . '%', $this->stringify($val), $output);
            }
        }
        // remove leftover %extra.xxx% and %context.xxx% if any
        if (false !== strpos($output, '%')) {
            $output = preg_replace('/%(?:extra|context)\\..+?%/', '', $output);
            if (null === $output) {
                $pcreErrorCode = preg_last_error();
                throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
            }
        }
        return $output;
    }
    /**
     *
     */
    public function formatBatch(array $records) : string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
    /**
     * @param mixed $value
     */
    public function stringify($value) : string
    {
        return $this->replaceNewlines($this->convertToString($value));
    }
    /**
     *
     */
    protected function normalizeException(\Throwable $e, int $depth = 0) : string
    {
        $str = $this->formatException($e);
        if ($previous = $e->getPrevious()) {
            do {
                $str .= "\n[previous exception] " . $this->formatException($previous);
            } while ($previous = $previous->getPrevious());
        }
        return $str;
    }
    /**
     * @param mixed $data
     */
    protected function convertToString($data) : string
    {
        if (null === $data || is_bool($data)) {
            return var_export($data, true);
        }
        if (is_scalar($data)) {
            return (string) $data;
        }
        return $this->toJson($data, true);
    }
    /**
     *
     */
    protected function replaceNewlines(string $str) : string
    {
        if ($this->allowInlineLineBreaks) {
            if (0 === strpos($str, '{')) {
                return str_replace(array('\\r', '\\n'), array("\r", "\n"), $str);
            }
            return $str;
        }
        return str_replace(["\r\n", "\r", "\n"], ' ', $str);
    }
    /**
     *
     */
    private function formatException(\Throwable $e) : string
    {
        $str = '[object] (' . Utils::getClass($e) . '(code: ' . $e->getCode();
        if ($e instanceof \SoapFault) {
            if (isset($e->faultcode)) {
                $str .= ' faultcode: ' . $e->faultcode;
            }
            if (isset($e->faultactor)) {
                $str .= ' faultactor: ' . $e->faultactor;
            }
            if (isset($e->detail)) {
                if (is_string($e->detail)) {
                    $str .= ' detail: ' . $e->detail;
                } elseif (is_object($e->detail) || is_array($e->detail)) {
                    $str .= ' detail: ' . $this->toJson($e->detail, true);
                }
            }
        }
        $str .= '): ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . ')';
        if ($this->includeStacktraces) {
            $str .= "\n[stacktrace]\n" . $e->getTraceAsString() . "\n";
        }
        return $str;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Logger;
/**
 * Formats a log message according to the ChromePHP array format
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ChromePHPFormatter implements FormatterInterface
{
    /**
     * Translates Monolog log levels to Wildfire levels.
     *
     * @var array<int, 'log'|'info'|'warn'|'error'>
     */
    private $logLevels = [Logger::DEBUG => 'log', Logger::INFO => 'info', Logger::NOTICE => 'info', Logger::WARNING => 'warn', Logger::ERROR => 'error', Logger::CRITICAL => 'error', Logger::ALERT => 'error', Logger::EMERGENCY => 'error'];
    /**
     * {@inheritDoc}
     */
    public function format(array $record)
    {
        // Retrieve the line and file if set and remove them from the formatted extra
        $backtrace = 'unknown';
        if (isset($record['extra']['file'], $record['extra']['line'])) {
            $backtrace = $record['extra']['file'] . ' : ' . $record['extra']['line'];
            unset($record['extra']['file'], $record['extra']['line']);
        }
        $message = ['message' => $record['message']];
        if ($record['context']) {
            $message['context'] = $record['context'];
        }
        if ($record['extra']) {
            $message['extra'] = $record['extra'];
        }
        if (count($message) === 1) {
            $message = reset($message);
        }
        return [$record['channel'], $message, $backtrace, $this->logLevels[$record['level']]];
    }
    /**
     * {@inheritDoc}
     */
    public function formatBatch(array $records)
    {
        $formatted = [];
        foreach ($records as $record) {
            $formatted[] = $this->format($record);
        }
        return $formatted;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Throwable;
/**
 * Encodes whatever record data is passed to it as json
 *
 * This can be useful to log to databases or remote APIs
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class JsonFormatter extends NormalizerFormatter
{
    public const BATCH_MODE_JSON = 1;
    public const BATCH_MODE_NEWLINES = 2;
    /** @var self::BATCH_MODE_* */
    protected $batchMode;
    /** @var bool */
    protected $appendNewline;
    /** @var bool */
    protected $ignoreEmptyContextAndExtra;
    /** @var bool */
    protected $includeStacktraces = false;
    /**
     * @param self::BATCH_MODE_* $batchMode
     */
    public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = true, bool $ignoreEmptyContextAndExtra = false)
    {
        $this->batchMode = $batchMode;
        $this->appendNewline = $appendNewline;
        $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
        parent::__construct();
    }
    /**
    * The batch mode option configures the formatting style for
    multiple records. By default, multiple records will be
    formatted as a JSON-encoded array. However, for
    compatibility with some API endpoints, alternative styles
    are available.
    */
    public function getBatchMode() : int
    {
        return $this->batchMode;
    }
    /**
     * True if newlines are appended to every formatted record
     */
    public function isAppendingNewlines() : bool
    {
        return $this->appendNewline;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record) : string
    {
        $normalized = $this->normalize($record);
        if (isset($normalized['context']) && $normalized['context'] === []) {
            if ($this->ignoreEmptyContextAndExtra) {
                unset($normalized['context']);
            } else {
                $normalized['context'] = new \stdClass();
            }
        }
        if (isset($normalized['extra']) && $normalized['extra'] === []) {
            if ($this->ignoreEmptyContextAndExtra) {
                unset($normalized['extra']);
            } else {
                $normalized['extra'] = new \stdClass();
            }
        }
        return $this->toJson($normalized, true) . ($this->appendNewline ? "\n" : '');
    }
    /**
     * {@inheritDoc}
     */
    public function formatBatch(array $records) : string
    {
        switch ($this->batchMode) {
            case static::BATCH_MODE_NEWLINES:
                return $this->formatBatchNewlines($records);
            case static::BATCH_MODE_JSON:
            default:
                return $this->formatBatchJson($records);
        }
    }
    /**
     * @return void
     */
    public function includeStacktraces(bool $include = true)
    {
        $this->includeStacktraces = $include;
    }
    /**
     * Return a JSON-encoded array of records.
     *
     * @phpstan-param Record[] $records
     */
    protected function formatBatchJson(array $records) : string
    {
        return $this->toJson($this->normalize($records), true);
    }
    /**
    * Use new lines to separate records instead of a
    JSON-encoded array.
    *
    * @phpstan-param Record[] $records
    */
    protected function formatBatchNewlines(array $records) : string
    {
        $instance = $this;
        $oldNewline = $this->appendNewline;
        $this->appendNewline = false;
        array_walk($records, function (&$value, $key) use($instance) {
            $value = $instance->format($value);
        });
        $this->appendNewline = $oldNewline;
        return implode("\n", $records);
    }
    /**
     * Normalizes given $data.
     *
     * @param mixed $data
     *
     * @return mixed
     */
    protected function normalize($data, int $depth = 0)
    {
        if ($depth > $this->maxNormalizeDepth) {
            return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
        }
        if (is_array($data)) {
            $normalized = [];
            $count = 1;
            foreach ($data as $key => $value) {
                if ($count++ > $this->maxNormalizeItemCount) {
                    $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . count($data) . ' total), aborting normalization';
                    break;
                }
                $normalized[$key] = $this->normalize($value, $depth + 1);
            }
            return $normalized;
        }
        if ($data instanceof \DateTimeInterface) {
            return $this->formatDate($data);
        }
        if ($data instanceof Throwable) {
            return $this->normalizeException($data, $depth);
        }
        if (is_resource($data)) {
            return parent::normalize($data);
        }
        return $data;
    }
    /**
    * Normalizes given exception with or without its own stack trace based on
    `includeStacktraces` property.
    *
    * {@inheritDoc}
    */
    protected function normalizeException(Throwable $e, int $depth = 0) : array
    {
        $data = parent::normalizeException($e, $depth);
        if (!$this->includeStacktraces) {
            unset($data['trace']);
        }
        return $data;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Elastica\Document;
/**
 * Format a log message into an Elastica Document
 *
 * @author Jelle Vink <jelle.vink@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class ElasticaFormatter extends NormalizerFormatter
{
    /**
     * @var string Elastic search index name
     */
    protected $index;
    /**
     * @var ?string Elastic search document type
     */
    protected $type;
    /**
     * @param string $index Elastic Search index name
     * @param ?string $type Elastic Search document type, deprecated as of Elastica 7
     */
    public function __construct(string $index, ?string $type)
    {
        // elasticsearch requires a ISO 8601 format date with optional millisecond precision.
        parent::__construct('Y-m-d\\TH:i:s.uP');
        $this->index = $index;
        $this->type = $type;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record)
    {
        $record = parent::format($record);
        return $this->getDocument($record);
    }
    /**
     *
     */
    public function getIndex() : string
    {
        return $this->index;
    }
    /**
     * @deprecated since Elastica 7 type has no effect
     */
    public function getType() : string
    {
        /** @phpstan-ignore-next-line */
        return $this->type;
    }
    /**
     * Convert a log message into an Elastica Document
     *
     * @phpstan-param Record $record
     */
    protected function getDocument(array $record) : Document
    {
        $document = new Document();
        $document->setData($record);
        if (method_exists($document, 'setType')) {
            /** @phpstan-ignore-next-line */
            $document->setType($this->type);
        }
        $document->setIndex($this->index);
        return $document;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Interface for formatters
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
interface FormatterInterface
{
    /**
     * Formats a log record.
     *
     * @param array $record A record to format
     * @return mixed The formatted record
     *
     * @phpstan-param Record $record
     */
    public function format(array $record);
    /**
     * Formats a set of log records.
     *
     * @param array $records A set of records to format
     * @return mixed The formatted set of records
     *
     * @phpstan-param Record[] $records
     */
    public function formatBatch(array $records);
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Logger;
use Gelf\Message;
use Monolog\Utils;
/**
 * Serializes a log message to GELF
 * @see http://docs.graylog.org/en/latest/pages/gelf.html
 *
 * @author Matt Lehner <mlehner@gmail.com>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 */
class GelfMessageFormatter extends NormalizerFormatter
{
    protected const DEFAULT_MAX_LENGTH = 32766;
    /**
     * @var string the name of the system for the Gelf log message
     */
    protected $systemName;
    /**
     * @var string a prefix for 'extra' fields from the Monolog record (optional)
     */
    protected $extraPrefix;
    /**
     * @var string a prefix for 'context' fields from the Monolog record (optional)
     */
    protected $contextPrefix;
    /**
     * @var int max length per field
     */
    protected $maxLength;
    /**
     * Translates Monolog log levels to Graylog2 log priorities.
     *
     * @var array<int, int>
     *
     * @phpstan-var array<Level, int>
     */
    private $logLevels = [Logger::DEBUG => 7, Logger::INFO => 6, Logger::NOTICE => 5, Logger::WARNING => 4, Logger::ERROR => 3, Logger::CRITICAL => 2, Logger::ALERT => 1, Logger::EMERGENCY => 0];
    /**
     *
     */
    public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null)
    {
        parent::__construct('U.u');
        $this->systemName = is_null($systemName) || $systemName === '' ? (string) gethostname() : $systemName;
        $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix;
        $this->contextPrefix = $contextPrefix;
        $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record) : Message
    {
        $context = $extra = [];
        if (isset($record['context'])) {
            /** @var mixed[] $context */
            $context = parent::normalize($record['context']);
        }
        if (isset($record['extra'])) {
            /** @var mixed[] $extra */
            $extra = parent::normalize($record['extra']);
        }
        if (!isset($record['datetime'], $record['message'], $record['level'])) {
            throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, ' . var_export($record, true) . ' given');
        }
        $message = new Message();
        $message->setTimestamp($record['datetime'])->setShortMessage((string) $record['message'])->setHost($this->systemName)->setLevel($this->logLevels[$record['level']]);
        // message length + system name length + 200 for padding / metadata
        $len = 200 + strlen((string) $record['message']) + strlen($this->systemName);
        if ($len > $this->maxLength) {
            $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength));
        }
        if (isset($record['channel'])) {
            $message->setFacility($record['channel']);
        }
        if (isset($extra['line'])) {
            $message->setLine($extra['line']);
            unset($extra['line']);
        }
        if (isset($extra['file'])) {
            $message->setFile($extra['file']);
            unset($extra['file']);
        }
        foreach ($extra as $key => $val) {
            $val = is_scalar($val) || null === $val ? $val : $this->toJson($val);
            $len = strlen($this->extraPrefix . $key . $val);
            if ($len > $this->maxLength) {
                $message->setAdditional($this->extraPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
                continue;
            }
            $message->setAdditional($this->extraPrefix . $key, $val);
        }
        foreach ($context as $key => $val) {
            $val = is_scalar($val) || null === $val ? $val : $this->toJson($val);
            $len = strlen($this->contextPrefix . $key . $val);
            if ($len > $this->maxLength) {
                $message->setAdditional($this->contextPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
                continue;
            }
            $message->setAdditional($this->contextPrefix . $key, $val);
        }
        /** @phpstan-ignore-next-line */
        if (null === $message->getFile() && isset($context['exception']['file'])) {
            if (preg_match("/^(.+):([0-9]+)\$/", $context['exception']['file'], $matches)) {
                $message->setFile($matches[1]);
                $message->setLine($matches[2]);
            }
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Logger;
use Monolog\Utils;
/**
 * Formats incoming records into an HTML table
 *
 * This is especially useful for html email logging
 *
 * @author Tiago Brito <tlfbrito@gmail.com>
 */
class HtmlFormatter extends NormalizerFormatter
{
    /**
     * Translates Monolog log levels to html color priorities.
     *
     * @var array<int, string>
     */
    protected $logLevels = [Logger::DEBUG => '#CCCCCC', Logger::INFO => '#28A745', Logger::NOTICE => '#17A2B8', Logger::WARNING => '#FFC107', Logger::ERROR => '#FD7E14', Logger::CRITICAL => '#DC3545', Logger::ALERT => '#821722', Logger::EMERGENCY => '#000000'];
    /**
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        parent::__construct($dateFormat);
    }
    /**
     * Creates an HTML table row
     *
     * @param string $th Row header content
     * @param string $td Row standard cell content
     * @param bool $escapeTd false if td content must not be html escaped
     */
    protected function addRow(string $th, string $td = ' ', bool $escapeTd = true) : string
    {
        $th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8');
        if ($escapeTd) {
            $td = '<pre>' . htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8') . '</pre>';
        }
        return "<tr style=\"padding: 4px;text-align: left;\">\n<th style=\"vertical-align: top;background: #ccc;color: #000\" width=\"100\">{$th}:</th>\n<td style=\"padding: 4px;text-align: left;vertical-align: top;background: #eee;color: #000\">" . $td . "</td>\n</tr>";
    }
    /**
     * Create a HTML h1 tag
     *
     * @param string $title Text to be in the h1
     * @param int $level Error level
     * @return string
     */
    protected function addTitle(string $title, int $level) : string
    {
        $title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8');
        return '<h1 style="background: ' . $this->logLevels[$level] . ';color: #ffffff;padding: 5px;" class="monolog-output">' . $title . '</h1>';
    }
    /**
     * Formats a log record.
     *
     * @return string The formatted record
     */
    public function format(array $record) : string
    {
        $output = $this->addTitle($record['level_name'], $record['level']);
        $output .= '<table cellspacing="1" width="100%" class="monolog-output">';
        $output .= $this->addRow('Message', (string) $record['message']);
        $output .= $this->addRow('Time', $this->formatDate($record['datetime']));
        $output .= $this->addRow('Channel', $record['channel']);
        if ($record['context']) {
            $embeddedTable = '<table cellspacing="1" width="100%">';
            foreach ($record['context'] as $key => $value) {
                $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
            }
            $embeddedTable .= '</table>';
            $output .= $this->addRow('Context', $embeddedTable, false);
        }
        if ($record['extra']) {
            $embeddedTable = '<table cellspacing="1" width="100%">';
            foreach ($record['extra'] as $key => $value) {
                $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
            }
            $embeddedTable .= '</table>';
            $output .= $this->addRow('Extra', $embeddedTable, false);
        }
        return $output . '</table>';
    }
    /**
     * Formats a set of log records.
     *
     * @return string The formatted set of records
     */
    public function formatBatch(array $records) : string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
    /**
     * @param mixed $data
     */
    protected function convertToString($data) : string
    {
        if (null === $data || is_scalar($data)) {
            return (string) $data;
        }
        $data = $this->normalize($data);
        return Utils::jsonEncode($data, JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS, true);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Encodes message information into JSON in a format compatible with Loggly.
 *
 * @author Adam Pancutt <adam@pancutt.com>
 */
class LogglyFormatter extends JsonFormatter
{
    /**
    * Overrides the default batch mode to new lines for compatibility with the
    Loggly bulk API.
    */
    public function __construct(int $batchMode = self::BATCH_MODE_NEWLINES, bool $appendNewline = false)
    {
        parent::__construct($batchMode, $appendNewline);
    }
    /**
     * Appends the 'timestamp' parameter for indexing by Loggly.
     *
     * @see https://www.loggly.com/docs/automated-parsing/#json
     * @see \Monolog\Formatter\JsonFormatter::format()
     */
    public function format(array $record) : string
    {
        if (isset($record["datetime"]) && $record["datetime"] instanceof \DateTimeInterface) {
            $record["timestamp"] = $record["datetime"]->format("Y-m-d\\TH:i:s.uO");
            unset($record["datetime"]);
        }
        return parent::format($record);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Logger;
/**
 * Serializes a log message according to Wildfire's header requirements
 *
 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
 * @author Christophe Coevoet <stof@notk.org>
 * @author Kirill chEbba Chebunin <iam@chebba.org>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 */
class WildfireFormatter extends NormalizerFormatter
{
    /**
     * Translates Monolog log levels to Wildfire levels.
     *
     * @var array<Level, string>
     */
    private $logLevels = [Logger::DEBUG => 'LOG', Logger::INFO => 'INFO', Logger::NOTICE => 'INFO', Logger::WARNING => 'WARN', Logger::ERROR => 'ERROR', Logger::CRITICAL => 'ERROR', Logger::ALERT => 'ERROR', Logger::EMERGENCY => 'ERROR'];
    /**
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        parent::__construct($dateFormat);
        // http headers do not like non-ISO-8559-1 characters
        $this->removeJsonEncodeOption(JSON_UNESCAPED_UNICODE);
    }
    /**
     * {@inheritDoc}
     *
     * @return string
     */
    public function format(array $record) : string
    {
        // Retrieve the line and file if set and remove them from the formatted extra
        $file = $line = '';
        if (isset($record['extra']['file'])) {
            $file = $record['extra']['file'];
            unset($record['extra']['file']);
        }
        if (isset($record['extra']['line'])) {
            $line = $record['extra']['line'];
            unset($record['extra']['line']);
        }
        /** @var mixed[] $record */
        $record = $this->normalize($record);
        $message = ['message' => $record['message']];
        $handleError = false;
        if ($record['context']) {
            $message['context'] = $record['context'];
            $handleError = true;
        }
        if ($record['extra']) {
            $message['extra'] = $record['extra'];
            $handleError = true;
        }
        if (count($message) === 1) {
            $message = reset($message);
        }
        if (isset($record['context']['table'])) {
            $type = 'TABLE';
            $label = $record['channel'] . ': ' . $record['message'];
            $message = $record['context']['table'];
        } else {
            $type = $this->logLevels[$record['level']];
            $label = $record['channel'];
        }
        // Create JSON object describing the appearance of the message in the console
        $json = $this->toJson([['Type' => $type, 'File' => $file, 'Line' => $line, 'Label' => $label], $message], $handleError);
        // The message itself is a serialization of the above JSON object + it's length
        return sprintf('%d|%s|', strlen($json), $json);
    }
    /**
     * {@inheritDoc}
     *
     * @phpstan-return never
     */
    public function formatBatch(array $records)
    {
        throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
    }
    /**
     * {@inheritDoc}
     *
     * @return (null | scalar | array<(array | scalar | null)> | object)
     */
    protected function normalize($data, int $depth = 0)
    {
        if (is_object($data) && !$data instanceof \DateTimeInterface) {
            return $data;
        }
        return parent::normalize($data, $depth);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use DateTimeInterface;
/**
 * Format a log message into an Elasticsearch record
 *
 * @author Avtandil Kikabidze <akalongman@gmail.com>
 */
class ElasticsearchFormatter extends NormalizerFormatter
{
    /**
     * @var string Elasticsearch index name
     */
    protected $index;
    /**
     * @var string Elasticsearch record type
     */
    protected $type;
    /**
     * @param string $index Elasticsearch index name
     * @param string $type Elasticsearch record type
     */
    public function __construct(string $index, string $type)
    {
        // Elasticsearch requires an ISO 8601 format date with optional millisecond precision.
        parent::__construct(DateTimeInterface::ISO8601);
        $this->index = $index;
        $this->type = $type;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record)
    {
        $record = parent::format($record);
        return $this->getDocument($record);
    }
    /**
     * Getter index
     *
     * @return string
     */
    public function getIndex() : string
    {
        return $this->index;
    }
    /**
     * Getter type
     *
     * @return string
     */
    public function getType() : string
    {
        return $this->type;
    }
    /**
     * Convert a log message into an Elasticsearch record
     *
     * @param mixed[] $record Log message
     * @return mixed[]
     */
    protected function getDocument(array $record) : array
    {
        $record['_index'] = $this->index;
        $record['_type'] = $this->type;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Encodes message information into JSON in a format compatible with Logmatic.
 *
 * @author Julien Breux <julien.breux@gmail.com>
 */
class LogmaticFormatter extends JsonFormatter
{
    protected const MARKERS = ["sourcecode", "php"];
    /**
     * @var string
     */
    protected $hostname = '';
    /**
     * @var string
     */
    protected $appname = '';
    /**
     *
     */
    public function setHostname(string $hostname) : self
    {
        $this->hostname = $hostname;
        return $this;
    }
    /**
     *
     */
    public function setAppname(string $appname) : self
    {
        $this->appname = $appname;
        return $this;
    }
    /**
     * Appends the 'hostname' and 'appname' parameter for indexing by Logmatic.
     *
     * @see http://doc.logmatic.io/docs/basics-to-send-data
     * @see \Monolog\Formatter\JsonFormatter::format()
     */
    public function format(array $record) : string
    {
        if (!empty($this->hostname)) {
            $record["hostname"] = $this->hostname;
        }
        if (!empty($this->appname)) {
            $record["appname"] = $this->appname;
        }
        $record["@marker"] = static::MARKERS;
        return parent::format($record);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
/**
 * Monolog error handler
 *
 * A facility to enable logging of runtime errors, exceptions and fatal errors.
 *
 * Quick setup: <code>ErrorHandler::register($logger);</code>
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ErrorHandler
{
    /** @var LoggerInterface */
    private $logger;
    /** @var ?callable */
    private $previousExceptionHandler = null;
    /** @var array<class-string, LogLevel::*> an array of class name to LogLevel::* constant mapping */
    private $uncaughtExceptionLevelMap = [];
    /** @var callable|true|null */
    private $previousErrorHandler = null;
    /** @var array<int, LogLevel::*> an array of E_* constant to LogLevel::* constant mapping */
    private $errorLevelMap = [];
    /** @var bool */
    private $handleOnlyReportedErrors = true;
    /** @var bool */
    private $hasFatalErrorHandler = false;
    /** @var LogLevel::* */
    private $fatalLevel = LogLevel::ALERT;
    /** @var ?string */
    private $reservedMemory = null;
    /** @var ?mixed */
    private $lastFatalTrace;
    /** @var int[] */
    private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
    /**
     *
     */
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    /**
     * Registers a new ErrorHandler for a given Logger
     *
     * By default it will handle errors, exceptions and fatal errors
     *
     * @param LoggerInterface $logger
     * @param (array<int, LogLevel::*> | false) $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
     * @param (array<class-string, LogLevel::*> | false) $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling
     * @param (LogLevel::* | null | false) $fatalLevel a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling
     * @return ErrorHandler
     */
    public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null) : self
    {
        /** @phpstan-ignore-next-line */
        $handler = new static($logger);
        if ($errorLevelMap !== false) {
            $handler->registerErrorHandler($errorLevelMap);
        }
        if ($exceptionLevelMap !== false) {
            $handler->registerExceptionHandler($exceptionLevelMap);
        }
        if ($fatalLevel !== false) {
            $handler->registerFatalHandler($fatalLevel);
        }
        return $handler;
    }
    /**
     * @param array<class-string, LogLevel::*> $levelMap an array of class name to LogLevel::* constant mapping
     * @return $this
     */
    public function registerExceptionHandler(array $levelMap = [], bool $callPrevious = true) : self
    {
        $prev = set_exception_handler(function (\Throwable $e) : void {
            $this->handleException($e);
        });
        $this->uncaughtExceptionLevelMap = $levelMap;
        foreach ($this->defaultExceptionLevelMap() as $class => $level) {
            if (!isset($this->uncaughtExceptionLevelMap[$class])) {
                $this->uncaughtExceptionLevelMap[$class] = $level;
            }
        }
        if ($callPrevious && $prev) {
            $this->previousExceptionHandler = $prev;
        }
        return $this;
    }
    /**
     * @param array<int, LogLevel::*> $levelMap an array of E_* constant to LogLevel::* constant mapping
     * @return $this
     */
    public function registerErrorHandler(array $levelMap = [], bool $callPrevious = true, int $errorTypes = -1, bool $handleOnlyReportedErrors = true) : self
    {
        $prev = set_error_handler([$this, 'handleError'], $errorTypes);
        $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
        if ($callPrevious) {
            $this->previousErrorHandler = $prev ?: true;
        } else {
            $this->previousErrorHandler = null;
        }
        $this->handleOnlyReportedErrors = $handleOnlyReportedErrors;
        return $this;
    }
    /**
     * @param (LogLevel::* | null) $level a LogLevel::* constant, null to use the default LogLevel::ALERT
     * @param int $reservedMemorySize Amount of KBs to reserve in memory so that it can be freed when handling fatal errors giving Monolog some room in memory to get its job done
     */
    public function registerFatalHandler($level = null, int $reservedMemorySize = 20) : self
    {
        register_shutdown_function([$this, 'handleFatalError']);
        $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
        $this->fatalLevel = null === $level ? LogLevel::ALERT : $level;
        $this->hasFatalErrorHandler = true;
        return $this;
    }
    /**
     * @return array<class-string, LogLevel::*>
     */
    protected function defaultExceptionLevelMap() : array
    {
        return ['ParseError' => LogLevel::CRITICAL, 'Throwable' => LogLevel::ERROR];
    }
    /**
     * @return array<int, LogLevel::*>
     */
    protected function defaultErrorLevelMap() : array
    {
        return [E_ERROR => LogLevel::CRITICAL, E_WARNING => LogLevel::WARNING, E_PARSE => LogLevel::ALERT, E_NOTICE => LogLevel::NOTICE, E_CORE_ERROR => LogLevel::CRITICAL, E_CORE_WARNING => LogLevel::WARNING, E_COMPILE_ERROR => LogLevel::ALERT, E_COMPILE_WARNING => LogLevel::WARNING, E_USER_ERROR => LogLevel::ERROR, E_USER_WARNING => LogLevel::WARNING, E_USER_NOTICE => LogLevel::NOTICE, E_STRICT => LogLevel::NOTICE, E_RECOVERABLE_ERROR => LogLevel::ERROR, E_DEPRECATED => LogLevel::NOTICE, E_USER_DEPRECATED => LogLevel::NOTICE];
    }
    /**
     * @phpstan-return never
     */
    private function handleException(\Throwable $e) : void
    {
        $level = LogLevel::ERROR;
        foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) {
            if ($e instanceof $class) {
                $level = $candidate;
                break;
            }
        }
        $this->logger->log($level, sprintf('Uncaught Exception %s: "%s" at %s line %s', Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()), ['exception' => $e]);
        if ($this->previousExceptionHandler) {
            ($this->previousExceptionHandler)($e);
        }
        if (!headers_sent() && !ini_get('display_errors')) {
            http_response_code(500);
        }
        exit(255);
    }
    /**
     * @private
     *
     * @param mixed[] $context
     */
    public function handleError(int $code, string $message, string $file = '', int $line = 0, array $context = []) : bool
    {
        if ($this->handleOnlyReportedErrors && !(\Phabel\Target\Php80\Polyfill::error_reporting() & $code)) {
            return false;
        }
        // fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
        if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
            $level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL;
            $this->logger->log($level, self::codeToString($code) . ': ' . $message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]);
        } else {
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
            array_shift($trace);
            // Exclude handleError from trace
            $this->lastFatalTrace = $trace;
        }
        if ($this->previousErrorHandler === true) {
            return false;
        } elseif ($this->previousErrorHandler) {
            return (bool) ($this->previousErrorHandler)($code, $message, $file, $line, $context);
        }
        return true;
    }
    /**
     * @private
     */
    public function handleFatalError() : void
    {
        $this->reservedMemory = '';
        $lastError = error_get_last();
        if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) {
            $this->logger->log($this->fatalLevel, 'Fatal Error (' . self::codeToString($lastError['type']) . '): ' . $lastError['message'], ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace]);
            if ($this->logger instanceof Logger) {
                foreach ($this->logger->getHandlers() as $handler) {
                    $handler->close();
                }
            }
        }
    }
    /**
     * @param int $code
     */
    private static function codeToString($code) : string
    {
        switch ($code) {
            case E_ERROR:
                return 'E_ERROR';
            case E_WARNING:
                return 'E_WARNING';
            case E_PARSE:
                return 'E_PARSE';
            case E_NOTICE:
                return 'E_NOTICE';
            case E_CORE_ERROR:
                return 'E_CORE_ERROR';
            case E_CORE_WARNING:
                return 'E_CORE_WARNING';
            case E_COMPILE_ERROR:
                return 'E_COMPILE_ERROR';
            case E_COMPILE_WARNING:
                return 'E_COMPILE_WARNING';
            case E_USER_ERROR:
                return 'E_USER_ERROR';
            case E_USER_WARNING:
                return 'E_USER_WARNING';
            case E_USER_NOTICE:
                return 'E_USER_NOTICE';
            case E_STRICT:
                return 'E_STRICT';
            case E_RECOVERABLE_ERROR:
                return 'E_RECOVERABLE_ERROR';
            case E_DEPRECATED:
                return 'E_DEPRECATED';
            case E_USER_DEPRECATED:
                return 'E_USER_DEPRECATED';
        }
        return 'Unknown PHP error';
    }
}{
    "name": "monolog/monolog",
    "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
    "keywords": ["log", "logging", "psr-3"],
    "homepage": "https://github.com/Seldaek/monolog",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "https://seld.be"
        }
    ],
    "require": {
        "php": ">=7.2",
        "psr/log": "^1.0.1 || ^2.0 || ^3.0"
    },
    "require-dev": {
        "aws/aws-sdk-php": "^2.4.9 || ^3.0",
        "doctrine/couchdb": "~1.0@dev",
        "elasticsearch/elasticsearch": "^7",
        "mongodb/mongodb": "^1.8",
        "graylog2/gelf-php": "^1.4.2",
        "php-amqplib/php-amqplib": "~2.4 || ^3",
        "php-console/php-console": "^3.1.3",
        "phpspec/prophecy": "^1.6.1",
        "phpunit/phpunit": "^8.5",
        "predis/predis": "^1.1",
        "rollbar/rollbar": "^1.3",
        "ruflin/elastica": ">=0.90@dev",
        "swiftmailer/swiftmailer": "^5.3|^6.0",
        "phpstan/phpstan": "^0.12.91"
    },
    "suggest": {
        "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
        "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
        "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
        "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
        "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
        "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
        "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
        "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
        "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
        "rollbar/rollbar": "Allow sending log messages to Rollbar",
        "php-console/php-console": "Allow sending log messages to Google Chrome",
        "ext-mbstring": "Allow to work properly with unicode symbols",
        "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
        "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
        "ext-openssl": "Required to send log messages using SSL"
    },
    "autoload": {
        "psr-4": {"Monolog\\": "src/Monolog"}
    },
    "autoload-dev": {
        "psr-4": {"Monolog\\": "tests/Monolog"}
    },
    "provide": {
        "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
    },
    "extra": {
        "branch-alias": {
            "dev-main": "2.x-dev"
        }
    },
    "scripts": {
        "test": "vendor/bin/phpunit",
        "phpstan": "vendor/bin/phpstan analyse"
    },
    "config": {
        "lock": false,
        "sort-packages": true,
        "platform-check": false
    }
}
<?php

namespace Psr\Http\Message;

/**
 * Representation of an outgoing, client-side request.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - HTTP method
 * - URI
 * - Headers
 * - Message body
 *
 * During construction, implementations MUST attempt to set the Host header from
 * a provided URI if no Host header is provided.
 *
 * Requests are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface RequestInterface extends MessageInterface
{
    /**
    * Retrieves the message's request target.
    *
    * Retrieves the message's request-target either as it will appear (for
    clients), as it appeared at request (for servers), or as it was
    specified for the instance (see withRequestTarget()).
    *
    * In most cases, this will be the origin-form of the composed URI,
    unless a value was provided to the concrete implementation (see
    withRequestTarget() below).
    *
    * If no URI is available, and no request-target has been specifically
    provided, this method MUST return the string "/".
    *
    * @return string
    */
    public function getRequestTarget();
    /**
    * Return an instance with the specific request-target.
    *
    * If the request needs a non-origin-form request-target â€” e.g., for
    specifying an absolute-form, authority-form, or asterisk-form â€”
    this method may be used to create an instance with the specified
    request-target, verbatim.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    changed request target.
    *
    * @link http://tools.ietf.org/html/rfc7230#section-5.3 (for the various
    request-target forms allowed in request messages)
    * @param mixed $requestTarget
    * @return static
    */
    public function withRequestTarget($requestTarget);
    /**
     * Retrieves the HTTP method of the request.
     *
     * @return string Returns the request method.
     */
    public function getMethod();
    /**
    * Return an instance with the provided HTTP method.
    *
    * While HTTP method names are typically all uppercase characters, HTTP
    method names are case-sensitive and thus implementations SHOULD NOT
    modify the given string.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    changed request method.
    *
    * @param string $method Case-sensitive method.
    * @return static
    * @throws \InvalidArgumentException for invalid HTTP methods.
    */
    public function withMethod($method);
    /**
    * Retrieves the URI instance.
    *
    * This method MUST return a UriInterface instance.
    *
    * @link http://tools.ietf.org/html/rfc3986#section-4.3
    * @return UriInterface Returns a UriInterface instance
    representing the URI of the request.
    */
    public function getUri();
    /**
    * Returns an instance with the provided URI.
    *
    * This method MUST update the Host header of the returned request by
    default if the URI contains a host component. If the URI does not
    contain a host component, any pre-existing Host header MUST be carried
    over to the returned request.
    *
    * You can opt-in to preserving the original state of the Host header by
    setting `$preserveHost` to `true`. When `$preserveHost` is set to
    `true`, this method interacts with the Host header in the following ways:
    *
    * - If the Host header is missing or empty, and the new URI contains
    a host component, this method MUST update the Host header in the returned
    request.
    - If the Host header is missing or empty, and the new URI does not contain a
    host component, this method MUST NOT update the Host header in the returned
    request.
    - If a Host header is present and non-empty, this method MUST NOT update
    the Host header in the returned request.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    new UriInterface instance.
    *
    * @link http://tools.ietf.org/html/rfc3986#section-4.3
    * @param UriInterface $uri New request URI to use.
    * @param bool $preserveHost Preserve the original state of the Host header.
    * @return static
    */
    public function withUri(UriInterface $uri, $preserveHost = false);
}<?php

namespace Psr\Http\Message;

/**
 * Value object representing a file uploaded through an HTTP request.
 *
 * Instances of this interface are considered immutable; all methods that
 * might change state MUST be implemented such that they retain the internal
 * state of the current instance and return an instance that contains the
 * changed state.
 */
interface UploadedFileInterface
{
    /**
    * Retrieve a stream representing the uploaded file.
    *
    * This method MUST return a StreamInterface instance, representing the
    uploaded file. The purpose of this method is to allow utilizing native PHP
    stream functionality to manipulate the file upload, such as
    stream_copy_to_stream() (though the result will need to be decorated in a
    native PHP stream wrapper to work with such functions).
    *
    * If the moveTo() method has been called previously, this method MUST raise
    an exception.
    *
    * @return StreamInterface Stream representation of the uploaded file.
    * @throws \RuntimeException in cases when no stream is available or can be
    created.
    */
    public function getStream();
    /**
    * Move the uploaded file to a new location.
    *
    * Use this method as an alternative to move_uploaded_file(). This method is
    guaranteed to work in both SAPI and non-SAPI environments.
    Implementations must determine which environment they are in, and use the
    appropriate method (move_uploaded_file(), rename(), or a stream
    operation) to perform the operation.
    *
    * $targetPath may be an absolute path, or a relative path. If it is a
    relative path, resolution should be the same as used by PHP's rename()
    function.
    *
    * The original file or stream MUST be removed on completion.
    *
    * If this method is called more than once, any subsequent calls MUST raise
    an exception.
    *
    * When used in an SAPI environment where $_FILES is populated, when writing
    files via moveTo(), is_uploaded_file() and move_uploaded_file() SHOULD be
    used to ensure permissions and upload status are verified correctly.
    *
    * If you wish to move to a stream, use getStream(), as SAPI operations
    cannot guarantee writing to stream destinations.
    *
    * @see http://php.net/is_uploaded_file
    * @see http://php.net/move_uploaded_file
    * @param string $targetPath Path to which to move the uploaded file.
    * @throws \InvalidArgumentException if the $targetPath specified is invalid.
    * @throws \RuntimeException on any error during the move operation, or on
    the second or subsequent call to the method.
    */
    public function moveTo($targetPath);
    /**
    * Retrieve the file size.
    *
    * Implementations SHOULD return the value stored in the "size" key of
    the file in the $_FILES array if available, as PHP calculates this based
    on the actual size transmitted.
    *
    * @return (int | null) The file size in bytes or null if unknown.
    */
    public function getSize();
    /**
    * Retrieve the error associated with the uploaded file.
    *
    * The return value MUST be one of PHP's UPLOAD_ERR_XXX constants.
    *
    * If the file was uploaded successfully, this method MUST return
    UPLOAD_ERR_OK.
    *
    * Implementations SHOULD return the value stored in the "error" key of
    the file in the $_FILES array.
    *
    * @see http://php.net/manual/en/features.file-upload.errors.php
    * @return int One of PHP's UPLOAD_ERR_XXX constants.
    */
    public function getError();
    /**
    * Retrieve the filename sent by the client.
    *
    * Do not trust the value returned by this method. A client could send
    a malicious filename with the intention to corrupt or hack your
    application.
    *
    * Implementations SHOULD return the value stored in the "name" key of
    the file in the $_FILES array.
    *
    * @return (string | null) The filename sent by the client or null if none
    was provided.
    */
    public function getClientFilename();
    /**
    * Retrieve the media type sent by the client.
    *
    * Do not trust the value returned by this method. A client could send
    a malicious media type with the intention to corrupt or hack your
    application.
    *
    * Implementations SHOULD return the value stored in the "type" key of
    the file in the $_FILES array.
    *
    * @return (string | null) The media type sent by the client or null if none
    was provided.
    */
    public function getClientMediaType();
}<?php

namespace Psr\Http\Message;

/**
 * Representation of an incoming, server-side HTTP request.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - HTTP method
 * - URI
 * - Headers
 * - Message body
 *
 * Additionally, it encapsulates all data as it has arrived to the
 * application from the CGI and/or PHP environment, including:
 *
 * - The values represented in $_SERVER.
 * - Any cookies provided (generally via $_COOKIE)
 * - Query string arguments (generally via $_GET, or as parsed via parse_str())
 * - Upload files, if any (as represented by $_FILES)
 * - Deserialized body parameters (generally from $_POST)
 *
 * $_SERVER values MUST be treated as immutable, as they represent application
 * state at the time of request; as such, no methods are provided to allow
 * modification of those values. The other values provide such methods, as they
 * can be restored from $_SERVER or the request body, and may need treatment
 * during the application (e.g., body parameters may be deserialized based on
 * content type).
 *
 * Additionally, this interface recognizes the utility of introspecting a
 * request to derive and match additional parameters (e.g., via URI path
 * matching, decrypting cookie values, deserializing non-form-encoded body
 * content, matching authorization headers to users, etc). These parameters
 * are stored in an "attributes" property.
 *
 * Requests are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ServerRequestInterface extends RequestInterface
{
    /**
    * Retrieve server parameters.
    *
    * Retrieves data related to the incoming request environment,
    typically derived from PHP's $_SERVER superglobal. The data IS NOT
    REQUIRED to originate from $_SERVER.
    *
    * @return array
    */
    public function getServerParams();
    /**
    * Retrieve cookies.
    *
    * Retrieves cookies sent by the client to the server.
    *
    * The data MUST be compatible with the structure of the $_COOKIE
    superglobal.
    *
    * @return array
    */
    public function getCookieParams();
    /**
    * Return an instance with the specified cookies.
    *
    * The data IS NOT REQUIRED to come from the $_COOKIE superglobal, but MUST
    be compatible with the structure of $_COOKIE. Typically, this data will
    be injected at instantiation.
    *
    * This method MUST NOT update the related Cookie header of the request
    instance, nor related values in the server params.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated cookie values.
    *
    * @param array $cookies Array of key/value pairs representing cookies.
    * @return static
    */
    public function withCookieParams(array $cookies);
    /**
    * Retrieve query string arguments.
    *
    * Retrieves the deserialized query string arguments, if any.
    *
    * Note: the query params might not be in sync with the URI or server
    params. If you need to ensure you are only getting the original
    values, you may need to parse the query string from `getUri()->getQuery()`
    or from the `QUERY_STRING` server param.
    *
    * @return array
    */
    public function getQueryParams();
    /**
    * Return an instance with the specified query string arguments.
    *
    * These values SHOULD remain immutable over the course of the incoming
    request. They MAY be injected during instantiation, such as from PHP's
    $_GET superglobal, or MAY be derived from some other value such as the
    URI. In cases where the arguments are parsed from the URI, the data
    MUST be compatible with what PHP's parse_str() would return for
    purposes of how duplicate query parameters are handled, and how nested
    sets are handled.
    *
    * Setting query string arguments MUST NOT change the URI stored by the
    request, nor the values in the server params.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated query string arguments.
    *
    * @param array $query Array of query string arguments, typically from
    $_GET.
    * @return static
    */
    public function withQueryParams(array $query);
    /**
    * Retrieve normalized file upload data.
    *
    * This method returns upload metadata in a normalized tree, with each leaf
    an instance of Psr\Http\Message\UploadedFileInterface.
    *
    * These values MAY be prepared from $_FILES or the message body during
    instantiation, or MAY be injected via withUploadedFiles().
    *
    * @return array An array tree of UploadedFileInterface instances; an empty
    array MUST be returned if no data is present.
    */
    public function getUploadedFiles();
    /**
    * Create a new instance with the specified uploaded files.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated body parameters.
    *
    * @param array $uploadedFiles An array tree of UploadedFileInterface instances.
    * @return static
    * @throws \InvalidArgumentException if an invalid structure is provided.
    */
    public function withUploadedFiles(array $uploadedFiles);
    /**
    * Retrieve any parameters provided in the request body.
    *
    * If the request Content-Type is either application/x-www-form-urlencoded
    or multipart/form-data, and the request method is POST, this method MUST
    return the contents of $_POST.
    *
    * Otherwise, this method may return any results of deserializing
    the request body content; as parsing returns structured content, the
    potential types MUST be arrays or objects only. A null value indicates
    the absence of body content.
    *
    * @return (null | array | object) The deserialized body parameters, if any.
    These will typically be an array or object.
    */
    public function getParsedBody();
    /**
    * Return an instance with the specified body parameters.
    *
    * These MAY be injected during instantiation.
    *
    * If the request Content-Type is either application/x-www-form-urlencoded
    or multipart/form-data, and the request method is POST, use this method
    ONLY to inject the contents of $_POST.
    *
    * The data IS NOT REQUIRED to come from $_POST, but MUST be the results of
    deserializing the request body content. Deserialization/parsing returns
    structured data, and, as such, this method ONLY accepts arrays or objects,
    or a null value if nothing was available to parse.
    *
    * As an example, if content negotiation determines that the request data
    is a JSON payload, this method could be used to create a request
    instance with the deserialized parameters.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated body parameters.
    *
    * @param (null | array | object) $data The deserialized body data. This will
    typically be in an array or object.
    * @return static
    * @throws \InvalidArgumentException if an unsupported argument type is
    provided.
    */
    public function withParsedBody($data);
    /**
    * Retrieve attributes derived from the request.
    *
    * The request "attributes" may be used to allow injection of any
    parameters derived from the request: e.g., the results of path
    match operations; the results of decrypting cookies; the results of
    deserializing non-form-encoded message bodies; etc. Attributes
    will be application and request specific, and CAN be mutable.
    *
    * @return array Attributes derived from the request.
    */
    public function getAttributes();
    /**
    * Retrieve a single derived request attribute.
    *
    * Retrieves a single derived request attribute as described in
    getAttributes(). If the attribute has not been previously set, returns
    the default value as provided.
    *
    * This method obviates the need for a hasAttribute() method, as it allows
    specifying a default value to return if the attribute is not found.
    *
    * @see getAttributes()
    * @param string $name The attribute name.
    * @param mixed $default Default value to return if the attribute does not exist.
    * @return mixed
    */
    public function getAttribute($name, $default = null);
    /**
    * Return an instance with the specified derived request attribute.
    *
    * This method allows setting a single derived request attribute as
    described in getAttributes().
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated attribute.
    *
    * @see getAttributes()
    * @param string $name The attribute name.
    * @param mixed $value The value of the attribute.
    * @return static
    */
    public function withAttribute($name, $value);
    /**
    * Return an instance that removes the specified derived request attribute.
    *
    * This method allows removing a single derived request attribute as
    described in getAttributes().
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that removes
    the attribute.
    *
    * @see getAttributes()
    * @param string $name The attribute name.
    * @return static
    */
    public function withoutAttribute($name);
}<?php

namespace Psr\Http\Message;

/**
 * Value object representing a URI.
 *
 * This interface is meant to represent URIs according to RFC 3986 and to
 * provide methods for most common operations. Additional functionality for
 * working with URIs can be provided on top of the interface or externally.
 * Its primary use is for HTTP requests, but may also be used in other
 * contexts.
 *
 * Instances of this interface are considered immutable; all methods that
 * might change state MUST be implemented such that they retain the internal
 * state of the current instance and return an instance that contains the
 * changed state.
 *
 * Typically the Host header will be also be present in the request message.
 * For server-side requests, the scheme will typically be discoverable in the
 * server parameters.
 *
 * @link http://tools.ietf.org/html/rfc3986 (the URI specification)
 */
interface UriInterface
{
    /**
    * Retrieve the scheme component of the URI.
    *
    * If no scheme is present, this method MUST return an empty string.
    *
    * The value returned MUST be normalized to lowercase, per RFC 3986
    Section 3.1.
    *
    * The trailing ":" character is not part of the scheme and MUST NOT be
    added.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.1
    * @return string The URI scheme.
    */
    public function getScheme();
    /**
    * Retrieve the authority component of the URI.
    *
    * If no authority information is present, this method MUST return an empty
    string.
    *
    * The authority syntax of the URI is:
    *
    * <pre>
    [user-info@]host[:port]
    </pre>
    *
    * If the port component is not set or is the standard port for the current
    scheme, it SHOULD NOT be included.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-3.2
    * @return string The URI authority, in "[user-info@]host[:port]" format.
    */
    public function getAuthority();
    /**
    * Retrieve the user information component of the URI.
    *
    * If no user information is present, this method MUST return an empty
    string.
    *
    * If a user is present in the URI, this will return that value;
    additionally, if the password is also present, it will be appended to the
    user value, with a colon (":") separating the values.
    *
    * The trailing "@" character is not part of the user information and MUST
    NOT be added.
    *
    * @return string The URI user information, in "username[:password]" format.
    */
    public function getUserInfo();
    /**
    * Retrieve the host component of the URI.
    *
    * If no host is present, this method MUST return an empty string.
    *
    * The value returned MUST be normalized to lowercase, per RFC 3986
    Section 3.2.2.
    *
    * @see http://tools.ietf.org/html/rfc3986#section-3.2.2
    * @return string The URI host.
    */
    public function getHost();
    /**
    * Retrieve the port component of the URI.
    *
    * If a port is present, and it is non-standard for the current scheme,
    this method MUST return it as an integer. If the port is the standard port
    used with the current scheme, this method SHOULD return null.
    *
    * If no port is present, and no scheme is present, this method MUST return
    a null value.
    *
    * If no port is present, but a scheme is present, this method MAY return
    the standard port for that scheme, but SHOULD return null.
    *
    * @return (null | int) The URI port.
    */
    public function getPort();
    /**
    * Retrieve the path component of the URI.
    *
    * The path can either be empty or absolute (starting with a slash) or
    rootless (not starting with a slash). Implementations MUST support all
    three syntaxes.
    *
    * Normally, the empty path "" and absolute path "/" are considered equal as
    defined in RFC 7230 Section 2.7.3. But this method MUST NOT automatically
    do this normalization because in contexts with a trimmed base path, e.g.
    the front controller, this difference becomes significant. It's the task
    of the user to handle both "" and "/".
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.3.
    *
    * As an example, if the value should include a slash ("/") not intended as
    delimiter between path segments, that value MUST be passed in encoded
    form (e.g., "%2F") to the instance.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.3
    * @return string The URI path.
    */
    public function getPath();
    /**
    * Retrieve the query string of the URI.
    *
    * If no query string is present, this method MUST return an empty string.
    *
    * The leading "?" character is not part of the query and MUST NOT be
    added.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.4.
    *
    * As an example, if a value in a key/value pair of the query string should
    include an ampersand ("&") not intended as a delimiter between values,
    that value MUST be passed in encoded form (e.g., "%26") to the instance.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.4
    * @return string The URI query string.
    */
    public function getQuery();
    /**
    * Retrieve the fragment component of the URI.
    *
    * If no fragment is present, this method MUST return an empty string.
    *
    * The leading "#" character is not part of the fragment and MUST NOT be
    added.
    *
    * The value returned MUST be percent-encoded, but MUST NOT double-encode
    any characters. To determine what characters to encode, please refer to
    RFC 3986, Sections 2 and 3.5.
    *
    * @see https://tools.ietf.org/html/rfc3986#section-2
    * @see https://tools.ietf.org/html/rfc3986#section-3.5
    * @return string The URI fragment.
    */
    public function getFragment();
    /**
    * Return an instance with the specified scheme.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified scheme.
    *
    * Implementations MUST support the schemes "http" and "https" case
    insensitively, and MAY accommodate other schemes if required.
    *
    * An empty scheme is equivalent to removing the scheme.
    *
    * @param string $scheme The scheme to use with the new instance.
    * @return static A new instance with the specified scheme.
    * @throws \InvalidArgumentException for invalid or unsupported schemes.
    */
    public function withScheme($scheme);
    /**
    * Return an instance with the specified user information.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified user information.
    *
    * Password is optional, but the user information MUST include the
    user; an empty string for the user is equivalent to removing user
    information.
    *
    * @param string $user The user name to use for authority.
    * @param (null | string) $password The password associated with $user.
    * @return static A new instance with the specified user information.
    */
    public function withUserInfo($user, $password = null);
    /**
    * Return an instance with the specified host.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified host.
    *
    * An empty host value is equivalent to removing the host.
    *
    * @param string $host The hostname to use with the new instance.
    * @return static A new instance with the specified host.
    * @throws \InvalidArgumentException for invalid hostnames.
    */
    public function withHost($host);
    /**
    * Return an instance with the specified port.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified port.
    *
    * Implementations MUST raise an exception for ports outside the
    established TCP and UDP port ranges.
    *
    * A null value provided for the port is equivalent to removing the port
    information.
    *
    * @param (null | int) $port The port to use with the new instance; a null value
    removes the port information.
    * @return static A new instance with the specified port.
    * @throws \InvalidArgumentException for invalid ports.
    */
    public function withPort($port);
    /**
    * Return an instance with the specified path.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified path.
    *
    * The path can either be empty or absolute (starting with a slash) or
    rootless (not starting with a slash). Implementations MUST support all
    three syntaxes.
    *
    * If the path is intended to be domain-relative rather than path relative then
    it must begin with a slash ("/"). Paths not starting with a slash ("/")
    are assumed to be relative to some base path known to the application or
    consumer.
    *
    * Users can provide both encoded and decoded path characters.
    Implementations ensure the correct encoding as outlined in getPath().
    *
    * @param string $path The path to use with the new instance.
    * @return static A new instance with the specified path.
    * @throws \InvalidArgumentException for invalid paths.
    */
    public function withPath($path);
    /**
    * Return an instance with the specified query string.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified query string.
    *
    * Users can provide both encoded and decoded query characters.
    Implementations ensure the correct encoding as outlined in getQuery().
    *
    * An empty query string value is equivalent to removing the query string.
    *
    * @param string $query The query string to use with the new instance.
    * @return static A new instance with the specified query string.
    * @throws \InvalidArgumentException for invalid query strings.
    */
    public function withQuery($query);
    /**
    * Return an instance with the specified URI fragment.
    *
    * This method MUST retain the state of the current instance, and return
    an instance that contains the specified URI fragment.
    *
    * Users can provide both encoded and decoded fragment characters.
    Implementations ensure the correct encoding as outlined in getFragment().
    *
    * An empty fragment value is equivalent to removing the fragment.
    *
    * @param string $fragment The fragment to use with the new instance.
    * @return static A new instance with the specified fragment.
    */
    public function withFragment($fragment);
    /**
    * Return the string representation as a URI reference.
    *
    * Depending on which components of the URI are present, the resulting
    string is either a full URI or relative reference according to RFC 3986,
    Section 4.1. The method concatenates the various components of the URI,
    using the appropriate delimiters:
    *
    * - If a scheme is present, it MUST be suffixed by ":".
    - If an authority is present, it MUST be prefixed by "//".
    - The path can be concatenated without delimiters. But there are two
    cases where the path has to be adjusted to make the URI reference
    valid as PHP does not allow to throw an exception in __toString():
    - If the path is rootless and an authority is present, the path MUST
    be prefixed by "/".
    - If the path is starting with more than one "/" and no authority is
    present, the starting slashes MUST be reduced to one.
    - If a query is present, it MUST be prefixed by "?".
    - If a fragment is present, it MUST be prefixed by "#".
    *
    * @see http://tools.ietf.org/html/rfc3986#section-4.1
    * @return string
    */
    public function __toString();
}<?php

namespace Psr\Http\Message;

/**
 * HTTP messages consist of requests from a client to a server and responses
 * from a server to a client. This interface defines the methods common to
 * each.
 *
 * Messages are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 *
 * @link http://www.ietf.org/rfc/rfc7230.txt
 * @link http://www.ietf.org/rfc/rfc7231.txt
 */
interface MessageInterface
{
    /**
     * Retrieves the HTTP protocol version as a string.
     *
     * The string MUST contain only the HTTP version number (e.g., "1.1", "1.0").
     *
     * @return string HTTP protocol version.
     */
    public function getProtocolVersion();
    /**
    * Return an instance with the specified HTTP protocol version.
    *
    * The version string MUST contain only the HTTP version number (e.g.,
    "1.1", "1.0").
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    new protocol version.
    *
    * @param string $version HTTP protocol version
    * @return static
    */
    public function withProtocolVersion($version);
    /**
    * Retrieves all message header values.
    *
    * The keys represent the header name as it will be sent over the wire, and
    each value is an array of strings associated with the header.
    *
    * // Represent the headers as a string
    foreach ($message->getHeaders() as $name => $values) {
    echo $name . ": " . implode(", ", $values);
    }
    *
    * // Emit headers iteratively:
    foreach ($message->getHeaders() as $name => $values) {
    foreach ($values as $value) {
    header(sprintf('%s: %s', $name, $value), false);
    }
    }
    *
    * While header names are not case-sensitive, getHeaders() will preserve the
    exact case in which headers were originally specified.
    *
    * @return string[][] Returns an associative array of the message's headers. Each
    key MUST be a header name, and each value MUST be an array of strings
    for that header.
    */
    public function getHeaders();
    /**
    * Checks if a header exists by the given case-insensitive name.
    *
    * @param string $name Case-insensitive header field name.
    * @return bool Returns true if any header names match the given header
    name using a case-insensitive string comparison. Returns false if
    no matching header name is found in the message.
    */
    public function hasHeader($name);
    /**
    * Retrieves a message header value by the given case-insensitive name.
    *
    * This method returns an array of all the header values of the given
    case-insensitive header name.
    *
    * If the header does not appear in the message, this method MUST return an
    empty array.
    *
    * @param string $name Case-insensitive header field name.
    * @return string[] An array of string values as provided for the given
    header. If the header does not appear in the message, this method MUST
    return an empty array.
    */
    public function getHeader($name);
    /**
    * Retrieves a comma-separated string of the values for a single header.
    *
    * This method returns all of the header values of the given
    case-insensitive header name as a string concatenated together using
    a comma.
    *
    * NOTE: Not all header values may be appropriately represented using
    comma concatenation. For such headers, use getHeader() instead
    and supply your own delimiter when concatenating.
    *
    * If the header does not appear in the message, this method MUST return
    an empty string.
    *
    * @param string $name Case-insensitive header field name.
    * @return string A string of values as provided for the given header
    concatenated together using a comma. If the header does not appear in
    the message, this method MUST return an empty string.
    */
    public function getHeaderLine($name);
    /**
    * Return an instance with the provided value replacing the specified header.
    *
    * While header names are case-insensitive, the casing of the header will
    be preserved by this function, and returned from getHeaders().
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    new and/or updated header and value.
    *
    * @param string $name Case-insensitive header field name.
    * @param (string | string[]) $value Header value(s).
    * @return static
    * @throws \InvalidArgumentException for invalid header names or values.
    */
    public function withHeader($name, $value);
    /**
    * Return an instance with the specified header appended with the given value.
    *
    * Existing values for the specified header will be maintained. The new
    value(s) will be appended to the existing list. If the header did not
    exist previously, it will be added.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    new header and/or value.
    *
    * @param string $name Case-insensitive header field name to add.
    * @param (string | string[]) $value Header value(s).
    * @return static
    * @throws \InvalidArgumentException for invalid header names or values.
    */
    public function withAddedHeader($name, $value);
    /**
    * Return an instance without the specified header.
    *
    * Header resolution MUST be done without case-sensitivity.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that removes
    the named header.
    *
    * @param string $name Case-insensitive header field name to remove.
    * @return static
    */
    public function withoutHeader($name);
    /**
     * Gets the body of the message.
     *
     * @return StreamInterface Returns the body as a stream.
     */
    public function getBody();
    /**
    * Return an instance with the specified message body.
    *
    * The body MUST be a StreamInterface object.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return a new instance that has the
    new body stream.
    *
    * @param StreamInterface $body Body.
    * @return static
    * @throws \InvalidArgumentException When the body is not valid.
    */
    public function withBody(StreamInterface $body);
}<?php

namespace Psr\Http\Message;

/**
 * Representation of an outgoing, server-side response.
 *
 * Per the HTTP specification, this interface includes properties for
 * each of the following:
 *
 * - Protocol version
 * - Status code and reason phrase
 * - Headers
 * - Message body
 *
 * Responses are considered immutable; all methods that might change state MUST
 * be implemented such that they retain the internal state of the current
 * message and return an instance that contains the changed state.
 */
interface ResponseInterface extends MessageInterface
{
    /**
    * Gets the response status code.
    *
    * The status code is a 3-digit integer result code of the server's attempt
    to understand and satisfy the request.
    *
    * @return int Status code.
    */
    public function getStatusCode();
    /**
    * Return an instance with the specified status code and, optionally, reason phrase.
    *
    * If no reason phrase is specified, implementations MAY choose to default
    to the RFC 7231 or IANA recommended reason phrase for the response's
    status code.
    *
    * This method MUST be implemented in such a way as to retain the
    immutability of the message, and MUST return an instance that has the
    updated status and reason phrase.
    *
    * @link http://tools.ietf.org/html/rfc7231#section-6
    * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
    * @param int $code The 3-digit integer result code to set.
    * @param string $reasonPhrase The reason phrase to use with the
    provided status code; if none is provided, implementations MAY
    use the defaults as suggested in the HTTP specification.
    * @return static
    * @throws \InvalidArgumentException For invalid status code arguments.
    */
    public function withStatus($code, $reasonPhrase = '');
    /**
    * Gets the response reason phrase associated with the status code.
    *
    * Because a reason phrase is not a required element in a response
    status line, the reason phrase value MAY be null. Implementations MAY
    choose to return the default RFC 7231 recommended reason phrase (or those
    listed in the IANA HTTP Status Code Registry) for the response's
    status code.
    *
    * @link http://tools.ietf.org/html/rfc7231#section-6
    * @link http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
    * @return string Reason phrase; must return an empty string if none present.
    */
    public function getReasonPhrase();
}<?php

namespace Psr\Http\Message;

/**
 * Describes a data stream.
 *
 * Typically, an instance will wrap a PHP stream; this interface provides
 * a wrapper around the most common operations, including serialization of
 * the entire stream to a string.
 */
interface StreamInterface
{
    /**
    * Reads all data from the stream into a string, from the beginning to end.
    *
    * This method MUST attempt to seek to the beginning of the stream before
    reading data and read the stream until the end is reached.
    *
    * Warning: This could attempt to load a large amount of data into memory.
    *
    * This method MUST NOT raise an exception in order to conform with PHP's
    string casting operations.
    *
    * @see http://php.net/manual/en/language.oop5.magic.php#object.tostring
    * @return string
    */
    public function __toString();
    /**
     * Closes the stream and any underlying resources.
     *
     * @return void
     */
    public function close();
    /**
     * Separates any underlying resources from the stream.
     *
     * After the stream has been detached, the stream is in an unusable state.
     *
     * @return (resource | null) Underlying PHP stream, if any
     */
    public function detach();
    /**
     * Get the size of the stream if known.
     *
     * @return (int | null) Returns the size in bytes if known, or null if unknown.
     */
    public function getSize();
    /**
     * Returns the current position of the file read/write pointer
     *
     * @return int Position of the file pointer
     * @throws \RuntimeException on error.
     */
    public function tell();
    /**
     * Returns true if the stream is at the end of the stream.
     *
     * @return bool
     */
    public function eof();
    /**
     * Returns whether or not the stream is seekable.
     *
     * @return bool
     */
    public function isSeekable();
    /**
    * Seek to a position in the stream.
    *
    * @link http://www.php.net/manual/en/function.fseek.php
    * @param int $offset Stream offset
    * @param int $whence Specifies how the cursor position will be calculated
    based on the seek offset. Valid values are identical to the built-in
    PHP $whence values for `fseek()`.  SEEK_SET: Set position equal to
    offset bytes SEEK_CUR: Set position to current location plus offset
    SEEK_END: Set position to end-of-stream plus offset.
    * @throws \RuntimeException on failure.
    */
    public function seek($offset, $whence = SEEK_SET);
    /**
    * Seek to the beginning of the stream.
    *
    * If the stream is not seekable, this method will raise an exception;
    otherwise, it will perform a seek(0).
    *
    * @see seek()
    * @link http://www.php.net/manual/en/function.fseek.php
    * @throws \RuntimeException on failure.
    */
    public function rewind();
    /**
     * Returns whether or not the stream is writable.
     *
     * @return bool
     */
    public function isWritable();
    /**
     * Write data to the stream.
     *
     * @param string $string The string that is to be written.
     * @return int Returns the number of bytes written to the stream.
     * @throws \RuntimeException on failure.
     */
    public function write($string);
    /**
     * Returns whether or not the stream is readable.
     *
     * @return bool
     */
    public function isReadable();
    /**
    * Read data from the stream.
    *
    * @param int $length Read up to $length bytes from the object and return
    them. Fewer than $length bytes may be returned if underlying stream
    call returns fewer bytes.
    * @return string Returns the data read from the stream, or an empty string
    if no bytes are available.
    * @throws \RuntimeException if an error occurs.
    */
    public function read($length);
    /**
    * Returns the remaining contents in a string
    *
    * @return string
    * @throws \RuntimeException if unable to read or an error occurs while
    reading.
    */
    public function getContents();
    /**
    * Get stream metadata as an associative array or retrieve a specific key.
    *
    * The keys returned are identical to the keys returned from PHP's
    stream_get_meta_data() function.
    *
    * @link http://php.net/manual/en/function.stream-get-meta-data.php
    * @param string $key Specific metadata to retrieve.
    * @return (array | mixed | null) Returns an associative array if no key is
    provided. Returns a specific key value if a key is provided and the
    value is found, or null if the key is not found.
    */
    public function getMetadata($key = null);
}{
    "name": "psr/http-message",
    "description": "Common interface for HTTP messages",
    "keywords": ["psr", "psr-7", "http", "http-message", "request", "response"],
    "homepage": "https://github.com/php-fig/http-message",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "http://www.php-fig.org/"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-4": {
            "Psr\\Http\\Message\\": "src/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}
<?php

namespace Psr\Http\Message;

interface UriFactoryInterface
{
    /**
     * Create a new URI.
     *
     * @param string $uri
     *
     * @return UriInterface
     *
     * @throws \InvalidArgumentException If the given URI cannot be parsed.
     */
    public function createUri(string $uri = '') : UriInterface;
}<?php

namespace Psr\Http\Message;

interface RequestFactoryInterface
{
    /**
    * Create a new request.
    *
    * @param string $method The HTTP method associated with the request.
    * @param (UriInterface | string) $uri The URI associated with the request. If
    the value is a string, the factory MUST create a UriInterface
    instance based on it.
    *
    * @return RequestInterface
    */
    public function createRequest(string $method, $uri) : RequestInterface;
}<?php

namespace Psr\Http\Message;

interface ResponseFactoryInterface
{
    /**
    * Create a new response.
    *
    * @param int $code HTTP status code; defaults to 200
    * @param string $reasonPhrase Reason phrase to associate with status code
    in generated response; if none is provided implementations MAY use
    the defaults as suggested in the HTTP specification.
    *
    * @return ResponseInterface
    */
    public function createResponse(int $code = 200, string $reasonPhrase = '') : ResponseInterface;
}<?php

namespace Psr\Http\Message;

interface ServerRequestFactoryInterface
{
    /**
    * Create a new server request.
    *
    * Note that server-params are taken precisely as given - no parsing/processing
    of the given values is performed, and, in particular, no attempt is made to
    determine the HTTP method or URI, which must be provided explicitly.
    *
    * @param string $method The HTTP method associated with the request.
    * @param (UriInterface | string) $uri The URI associated with the request. If
    the value is a string, the factory MUST create a UriInterface
    instance based on it.
    * @param array $serverParams Array of SAPI parameters with which to seed
    the generated request instance.
    *
    * @return ServerRequestInterface
    */
    public function createServerRequest(string $method, $uri, array $serverParams = []) : ServerRequestInterface;
}<?php

namespace Psr\Http\Message;

interface StreamFactoryInterface
{
    /**
     * Create a new stream from a string.
     *
     * The stream SHOULD be created with a temporary resource.
     *
     * @param string $content String content with which to populate the stream.
     *
     * @return StreamInterface
     */
    public function createStream(string $content = '') : StreamInterface;
    /**
    * Create a stream from an existing file.
    *
    * The file MUST be opened using the given mode, which may be any mode
    supported by the `fopen` function.
    *
    * The `$filename` MAY be any string supported by `fopen()`.
    *
    * @param string $filename Filename or stream URI to use as basis of stream.
    * @param string $mode Mode with which to open the underlying filename/stream.
    *
    * @return StreamInterface
    * @throws \RuntimeException If the file cannot be opened.
    * @throws \InvalidArgumentException If the mode is invalid.
    */
    public function createStreamFromFile(string $filename, string $mode = 'r') : StreamInterface;
    /**
     * Create a new stream from an existing resource.
     *
     * The stream MUST be readable and may be writable.
     *
     * @param resource $resource PHP resource to use as basis of stream.
     *
     * @return StreamInterface
     */
    public function createStreamFromResource($resource) : StreamInterface;
}<?php

namespace Psr\Http\Message;

interface UploadedFileFactoryInterface
{
    /**
    * Create a new uploaded file.
    *
    * If a size is not provided it will be determined by checking the size of
    the file.
    *
    * @see http://php.net/manual/features.file-upload.post-method.php
    * @see http://php.net/manual/features.file-upload.errors.php
    *
    * @param StreamInterface $stream Underlying stream representing the
    uploaded file content.
    * @param int $size in bytes
    * @param int $error PHP file upload error
    * @param string $clientFilename Filename as provided by the client, if any.
    * @param string $clientMediaType Media type as provided by the client, if any.
    *
    * @return UploadedFileInterface
    *
    * @throws \InvalidArgumentException If the file resource is not readable.
    */
    public function createUploadedFile(StreamInterface $stream, int $size = null, int $error = \UPLOAD_ERR_OK, string $clientFilename = null, string $clientMediaType = null) : UploadedFileInterface;
}{
    "name": "psr/http-factory",
    "description": "Common interfaces for PSR-7 HTTP message factories",
    "keywords": [
        "psr",
        "psr-7",
        "psr-17",
        "http",
        "factory",
        "message",
        "request",
        "response"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "http://www.php-fig.org/"
        }
    ],
    "require": {
        "php": ">=7.0.0",
        "psr/http-message": "^1.0"
    },
    "autoload": {
        "psr-4": {
            "Psr\\Http\\Message\\": "src/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.0.x-dev"
        }
    }
}
{
    "name": "psr/log",
    "description": "Common interface for logging libraries",
    "keywords": ["psr", "psr-3", "log"],
    "homepage": "https://github.com/php-fig/log",
    "license": "MIT",
    "authors": [
        {
            "name": "PHP-FIG",
            "homepage": "https://www.php-fig.org/"
        }
    ],
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-4": {
            "Psr\\Log\\": "Psr/Log/"
        }
    },
    "extra": {
        "branch-alias": {
            "dev-master": "1.1.x-dev"
        }
    }
}
<?php

namespace Psr\Log;

/**
 * This Logger can be used to avoid conditional log calls.
 *
 * Logging should always be optional, and if no logger is provided to your
 * library creating a NullLogger instance to have something to throw logs at
 * is a good way to avoid littering your code with `if ($this->logger) { }`
 * blocks.
 */
class NullLogger extends AbstractLogger
{
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = array())
    {
        // noop
    }
}<?php

namespace Psr\Log;

/**
 * Basic Implementation of LoggerAwareInterface.
 */
trait LoggerAwareTrait
{
    /**
     * The logger instance.
     *
     * @var LoggerInterface|null
     */
    protected $logger;
    /**
     * Sets a logger.
     *
     * @param LoggerInterface $logger
     */
    public function setLogger(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
}<?php

namespace Psr\Log\Test;

/**
 * This class is internal and does not follow the BC promise.
 *
 * Do NOT use this class in any way.
 *
 * @internal
 */
class DummyTest
{
    /**
     *
     */
    public function __toString()
    {
        return 'DummyTest';
    }
}<?php

namespace Psr\Log\Test;

use Psr\Log\AbstractLogger;
/**
 * Used for testing purposes.
 *
 * It records all records and gives you access to them for verification.
 *
 * @method bool hasEmergency($record)
 * @method bool hasAlert($record)
 * @method bool hasCritical($record)
 * @method bool hasError($record)
 * @method bool hasWarning($record)
 * @method bool hasNotice($record)
 * @method bool hasInfo($record)
 * @method bool hasDebug($record)
 *
 * @method bool hasEmergencyRecords()
 * @method bool hasAlertRecords()
 * @method bool hasCriticalRecords()
 * @method bool hasErrorRecords()
 * @method bool hasWarningRecords()
 * @method bool hasNoticeRecords()
 * @method bool hasInfoRecords()
 * @method bool hasDebugRecords()
 *
 * @method bool hasEmergencyThatContains($message)
 * @method bool hasAlertThatContains($message)
 * @method bool hasCriticalThatContains($message)
 * @method bool hasErrorThatContains($message)
 * @method bool hasWarningThatContains($message)
 * @method bool hasNoticeThatContains($message)
 * @method bool hasInfoThatContains($message)
 * @method bool hasDebugThatContains($message)
 *
 * @method bool hasEmergencyThatMatches($message)
 * @method bool hasAlertThatMatches($message)
 * @method bool hasCriticalThatMatches($message)
 * @method bool hasErrorThatMatches($message)
 * @method bool hasWarningThatMatches($message)
 * @method bool hasNoticeThatMatches($message)
 * @method bool hasInfoThatMatches($message)
 * @method bool hasDebugThatMatches($message)
 *
 * @method bool hasEmergencyThatPasses($message)
 * @method bool hasAlertThatPasses($message)
 * @method bool hasCriticalThatPasses($message)
 * @method bool hasErrorThatPasses($message)
 * @method bool hasWarningThatPasses($message)
 * @method bool hasNoticeThatPasses($message)
 * @method bool hasInfoThatPasses($message)
 * @method bool hasDebugThatPasses($message)
 */
class TestLogger extends AbstractLogger
{
    /**
     * @var array
     */
    public $records = [];
    public $recordsByLevel = [];
    /**
     * @inheritdoc
     */
    public function log($level, $message, array $context = [])
    {
        $record = ['level' => $level, 'message' => $message, 'context' => $context];
        $this->recordsByLevel[$record['level']][] = $record;
        $this->records[] = $record;
    }
    /**
     *
     */
    public function hasRecords($level)
    {
        return isset($this->recordsByLevel[$level]);
    }
    /**
     *
     */
    public function hasRecord($record, $level)
    {
        if (is_string($record)) {
            $record = ['message' => $record];
        }
        return $this->hasRecordThatPasses(function ($rec) use($record) {
            if ($rec['message'] !== $record['message']) {
                return false;
            }
            if (isset($record['context']) && $rec['context'] !== $record['context']) {
                return false;
            }
            return true;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatContains($message, $level)
    {
        return $this->hasRecordThatPasses(function ($rec) use($message) {
            return strpos($rec['message'], $message) !== false;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatMatches($regex, $level)
    {
        return $this->hasRecordThatPasses(function ($rec) use($regex) {
            return preg_match($regex, $rec['message']) > 0;
        }, $level);
    }
    /**
     *
     */
    public function hasRecordThatPasses(callable $predicate, $level)
    {
        if (!isset($this->recordsByLevel[$level])) {
            return false;
        }
        foreach ($this->recordsByLevel[$level] as $i => $rec) {
            if (call_user_func($predicate, $rec, $i)) {
                return true;
            }
        }
        return false;
    }
    /**
     *
     */
    public function __call($method, $args)
    {
        if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
            $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
            $level = strtolower($matches[2]);
            if (method_exists($this, $genericMethod)) {
                $args[] = $level;
                return call_user_func_array([$this, $genericMethod], $args);
            }
        }
        throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
    }
    /**
     *
     */
    public function reset()
    {
        $this->records = [];
        $this->recordsByLevel = [];
    }
}<?php

namespace Psr\Log\Test;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use PHPUnit\Framework\TestCase;
/**
 * Provides a base test class for ensuring compliance with the LoggerInterface.
 *
 * Implementors can extend the class and implement abstract methods to run this
 * as part of their test suite.
 */
abstract class LoggerInterfaceTest extends TestCase
{
    /**
     * @return LoggerInterface
     */
    public abstract function getLogger();
    /**
     * This must return the log messages in order.
     *
     * The simple formatting of the messages is: "<LOG LEVEL> <MESSAGE>".
     *
     * Example ->error('Foo') would yield "error Foo".
     *
     * @return string[]
     */
    public abstract function getLogs();
    /**
     *
     */
    public function testImplements()
    {
        $this->assertInstanceOf('Psr\\Log\\LoggerInterface', $this->getLogger());
    }
    /**
     * @dataProvider provideLevelsAndMessages
     */
    public function testLogsAtAllLevels($level, $message)
    {
        $logger = $this->getLogger();
        $logger->{$level}($message, array('user' => 'Bob'));
        $logger->log($level, $message, array('user' => 'Bob'));
        $expected = array($level . ' message of level ' . $level . ' with context: Bob', $level . ' message of level ' . $level . ' with context: Bob');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function provideLevelsAndMessages()
    {
        return array(LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'));
    }
    /**
     * @expectedException \Psr\Log\InvalidArgumentException
     */
    public function testThrowsOnInvalidLevel()
    {
        $logger = $this->getLogger();
        $logger->log('invalid level', 'Foo');
    }
    /**
     *
     */
    public function testContextReplacement()
    {
        $logger = $this->getLogger();
        $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar'));
        $expected = array('info {Message {nothing} Bob Bar a}');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testObjectCastToString()
    {
        if (method_exists($this, 'createPartialMock')) {
            $dummy = $this->createPartialMock('Psr\\Log\\Test\\DummyTest', array('__toString'));
        } else {
            $dummy = $this->getMock('Psr\\Log\\Test\\DummyTest', array('__toString'));
        }
        $dummy->expects($this->once())->method('__toString')->will($this->returnValue('DUMMY'));
        $this->getLogger()->warning($dummy);
        $expected = array('warning DUMMY');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testContextCanContainAnything()
    {
        $closed = fopen('php://memory', 'r');
        fclose($closed);
        $context = array('bool' => true, 'null' => null, 'string' => 'Foo', 'int' => 0, 'float' => 0.5, 'nested' => array('with object' => new DummyTest()), 'object' => new \DateTime(), 'resource' => fopen('php://memory', 'r'), 'closed' => $closed);
        $this->getLogger()->warning('Crazy context data', $context);
        $expected = array('warning Crazy context data');
        $this->assertEquals($expected, $this->getLogs());
    }
    /**
     *
     */
    public function testContextExceptionKeyCanBeExceptionOrOtherValues()
    {
        $logger = $this->getLogger();
        $logger->warning('Random message', array('exception' => 'oops'));
        $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail')));
        $expected = array('warning Random message', 'critical Uncaught Exception!');
        $this->assertEquals($expected, $this->getLogs());
    }
}<?php

namespace Psr\Log;

/**
 * This is a simple Logger implementation that other Loggers can inherit from.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
abstract class AbstractLogger implements LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
}<?php

namespace Psr\Log;

/**
 * Describes a logger instance.
 *
 * The message MUST be a string or object implementing __toString().
 *
 * The message MAY contain placeholders in the form: {foo} where foo
 * will be replaced by the context data in key "foo".
 *
 * The context array can contain arbitrary data. The only assumption that
 * can be made by implementors is that if an Exception instance is given
 * to produce a stack trace, it MUST be in a key named "exception".
 *
 * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-3-logger-interface.md
 * for the full interface specification.
 */
interface LoggerInterface
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function emergency($message, array $context = array());
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function alert($message, array $context = array());
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function critical($message, array $context = array());
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function error($message, array $context = array());
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param mixed[] $context
    *
    * @return void
    */
    public function warning($message, array $context = array());
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function notice($message, array $context = array());
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function info($message, array $context = array());
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     */
    public function debug($message, array $context = array());
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param mixed[] $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public function log($level, $message, array $context = array());
}<?php

namespace Psr\Log;

/**
 * Describes log levels.
 */
class LogLevel
{
    const EMERGENCY = 'emergency';
    const ALERT = 'alert';
    const CRITICAL = 'critical';
    const ERROR = 'error';
    const WARNING = 'warning';
    const NOTICE = 'notice';
    const INFO = 'info';
    const DEBUG = 'debug';
}<?php

namespace Psr\Log;

/**
 * This is a simple Logger trait that classes unable to extend AbstractLogger
 * (because they extend another class, etc) can include.
 *
 * It simply delegates all log-level-specific methods to the `log` method to
 * reduce boilerplate code that a simple Logger that does the same thing with
 * messages regardless of the error level has to implement.
 */
trait LoggerTrait
{
    /**
     * System is unusable.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function emergency($message, array $context = array())
    {
        $this->log(LogLevel::EMERGENCY, $message, $context);
    }
    /**
    * Action must be taken immediately.
    *
    * Example: Entire website down, database unavailable, etc. This should
    trigger the SMS alerts and wake you up.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function alert($message, array $context = array())
    {
        $this->log(LogLevel::ALERT, $message, $context);
    }
    /**
     * Critical conditions.
     *
     * Example: Application component unavailable, unexpected exception.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function critical($message, array $context = array())
    {
        $this->log(LogLevel::CRITICAL, $message, $context);
    }
    /**
    * Runtime errors that do not require immediate action but should typically
    be logged and monitored.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function error($message, array $context = array())
    {
        $this->log(LogLevel::ERROR, $message, $context);
    }
    /**
    * Exceptional occurrences that are not errors.
    *
    * Example: Use of deprecated APIs, poor use of an API, undesirable things
    that are not necessarily wrong.
    *
    * @param string $message
    * @param array $context
    *
    * @return void
    */
    public function warning($message, array $context = array())
    {
        $this->log(LogLevel::WARNING, $message, $context);
    }
    /**
     * Normal but significant events.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function notice($message, array $context = array())
    {
        $this->log(LogLevel::NOTICE, $message, $context);
    }
    /**
     * Interesting events.
     *
     * Example: User logs in, SQL logs.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function info($message, array $context = array())
    {
        $this->log(LogLevel::INFO, $message, $context);
    }
    /**
     * Detailed debug information.
     *
     * @param string $message
     * @param array $context
     *
     * @return void
     */
    public function debug($message, array $context = array())
    {
        $this->log(LogLevel::DEBUG, $message, $context);
    }
    /**
     * Logs with an arbitrary level.
     *
     * @param mixed $level
     * @param string $message
     * @param array $context
     *
     * @return void
     *
     * @throws \Psr\Log\InvalidArgumentException
     */
    public abstract function log($level, $message, array $context = array());
}<?php

namespace Psr\Log;

class InvalidArgumentException extends \InvalidArgumentException
{
}<?php

namespace Psr\Log;

/**
 * Describes a logger-aware instance.
 */
interface LoggerAwareInterface
{
    /**
     * Sets a logger instance on the object.
     *
     * @param LoggerInterface $logger
     *
     * @return void
     */
    public function setLogger(LoggerInterface $logger);
}<?php

require 'vendor/autoload.php';
use Amp\Loop;
use danog\Loop\Generic\GenericLoop;
use function Amp\delay;
Loop::run(function () {
    /** @var GenericLoop[] */
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $callable = function () {
            static $number = 0;
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
            return $number < 10 ? 1000 : GenericLoop::STOP;
        };
        $loop = new GenericLoop($callable, "Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Resuming prematurely all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->resume();
    }
    echo "OK done, waiting 5 more seconds!" . PHP_EOL;
    (yield delay(5000));
    echo "Closing all loops!" . PHP_EOL;
    (yield delay(10));
});<?php

require 'vendor/autoload.php';
use Amp\Loop;
use danog\Loop\Generic\PeriodicLoop;
use function Amp\delay;
Loop::run(function () {
    /** @var PeriodicLoop[] */
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $callable = function () {
            static $number = 0;
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
            return $number == 10;
        };
        $loop = new PeriodicLoop($callable, "Loop number {$x}", 1000);
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Resuming prematurely all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->resume();
    }
    echo "OK done, waiting 5 more seconds!" . PHP_EOL;
    (yield delay(5000));
    echo "Closing all loops!" . PHP_EOL;
    (yield delay(10));
});<?php

require 'vendor/autoload.php';
use Amp\Loop as AmpLoop;
use danog\Loop\ResumableLoop;
use function Amp\delay;
class MyLoop extends ResumableLoop
{
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Constructor.
     *
     * @param string $name Loop name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $number = 0;
        while (true) {
            (yield $this->pause(1000));
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
        }
    }
    // Optionally, we can also define logging methods
    /**
     * Started loop.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        parent::startedLoop();
        echo "Started loop {$this}!" . PHP_EOL;
    }
    /**
     * Exited loop.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        parent::exitedLoop();
        echo "Exited loop {$this}!" . PHP_EOL;
    }
    // End of logging methods
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
AmpLoop::run(function () {
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $loop = new MyLoop("Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Resuming prematurely all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->resume();
    }
});<?php

require 'vendor/autoload.php';
use Amp\Loop;
use danog\Loop\SignalLoop;
use function Amp\delay;
class SigLoop extends SignalLoop
{
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Constructor.
     *
     * @param string $name Loop name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $number = 0;
        while (true) {
            if ((yield $this->waitSignal(delay(1000)))) {
                echo "Got exit signal in {$this}!" . PHP_EOL;
                return;
            }
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
        }
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
Loop::run(function () {
    /** @var SigLoop[] */
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $loop = new SigLoop("Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Closing all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->signal(true);
    }
});<?php

require 'vendor/autoload.php';
use Amp\Loop;
use danog\Loop\ResumableSignalLoop;
use function Amp\delay;
class ResSigLoop extends ResumableSignalLoop
{
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Constructor.
     *
     * @param string $name Loop name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $number = 0;
        while (true) {
            if ((yield $this->waitSignal($this->pause(1000)))) {
                echo "Got exit signal in {$this}!" . PHP_EOL;
                return;
            }
            echo "{$this}: {$number}" . PHP_EOL;
            $number++;
        }
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
Loop::run(function () {
    /** @var ResSigLoop[] */
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $loop = new ResSigLoop("Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
    (yield delay(5000));
    echo "Resuming prematurely all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->resume();
    }
    echo "OK done, waiting 5 more seconds!" . PHP_EOL;
    (yield delay(5000));
    echo "Closing all loops!" . PHP_EOL;
    foreach ($loops as $loop) {
        $loop->signal(true);
    }
});<?php

require 'vendor/autoload.php';
use Amp\Loop as AmpLoop;
use danog\Loop\Loop;
use function Amp\delay;
class MyLoop extends Loop
{
    /**
     * Callable.
     *
     * @var callable
     */
    private $callable;
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Constructor.
     *
     * @param callable $callable Callable
     * @param string $name Loop name
     */
    public function __construct(callable $callable, string $name)
    {
        $this->callable = $callable;
        $this->name = $name;
    }
    /**
     * Main loop.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $callable = $this->callable;
        $number = 0;
        while (true) {
            $number = (yield from $callable($number));
            echo "{$this}: {$number}" . PHP_EOL;
        }
    }
    // Optionally, we can also define logging methods
    /**
     * Started loop.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        parent::startedLoop();
        echo "Started loop {$this}!" . PHP_EOL;
    }
    /**
     * Exited loop.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        parent::exitedLoop();
        echo "Exited loop {$this}!" . PHP_EOL;
    }
    // End of logging methods
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}
AmpLoop::run(function () {
    $function = function (int $number) : \Generator {
        (yield delay(1000));
        return $number + 1;
    };
    $loops = [];
    for ($x = 0; $x < 10; $x++) {
        $loop = new MyLoop($function, "Loop number {$x}");
        $loop->start();
        (yield delay(100));
        $loops[] = $loop;
    }
});{
    "name": "danog/loop",
    "description": "Loop abstraction for AMPHP.",
    "keywords": [
        "asynchronous",
        "async",
        "concurrent",
        "multi-threading",
        "multi-processing"
    ],
    "homepage": "https://github.com/danog/loop",
    "license": "MIT",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/amp": "^2"
    },
    "require-dev": {
        "phpunit/phpunit": "^7 | ^8 | ^9",
        "amphp/phpunit-util": "^1.3",
        "amphp/php-cs-fixer-config": "dev-master",
        "vimeo/psalm": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "danog\\Loop\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "danog\\Loop\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "phpdbg -qrr -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

/**
 * Generic loop.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Generic;

use Amp\Promise;
use danog\Loop\ResumableSignalLoop;
/**
 * Generic loop, runs single callable.
 *
 * The return value of the callable can be:
 * * A number - the loop will be paused for the specified number of seconds
 * * GenericLoop::STOP - The loop will stop
 * * GenericLoop::PAUSE - The loop will pause forever (or until loop is `resumed()`
 *                        from outside the loop)
 * * GenericLoop::CONTINUE - Return this if you want to rerun the loop immediately
 *
 * If the callable does not return anything,
 * the loop will behave is if GenericLoop::PAUSE was returned.
 *
 * The loop can be stopped from the outside by signaling `true`.
 *
 * @template T as int|null
 * @template TGenerator as \Generator<mixed,Promise|array<array-key,Promise>,mixed,Promise<T>|T>
 * @template TPromise as Promise<T>
 *
 * @template TCallable as T|TPromise|TGenerator
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class GenericLoop extends ResumableSignalLoop
{
    /**
     * Stop the loop.
     */
    const STOP = -1;
    /**
     * Pause the loop.
     */
    const PAUSE = null;
    /**
     * Rerun the loop.
     */
    const CONTINUE = 0;
    /**
     * Callable.
     *
     * @var callable
     *
     * @psalm-var callable():TCallable
     */
    protected $callable;
    /**
     * Loop name.
     *
     * @var string
     */
    protected $name;
    /**
     * Constructor.
     *
     * If possible, the callable will be bound to the current instance of the loop.
     *
     * @param callable $callable Callable to run
     * @param string $name Loop name
     *
     * @psalm-param callable(): TCallable $callable Callable to run
     */
    public function __construct(callable $callable, string $name)
    {
        if ($callable instanceof \Closure) {
            try {
                $callable = $callable->bindTo($this);
            } catch (\Throwable $e) {
                // Might cause an error for wrapped object methods
            }
        }
        $this->callable = $callable;
        $this->name = $name;
    }
    /**
     * Loop implementation.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $callable = $this->callable;
        while (true) {
            /** @psalm-var ?int|TGenerator|TPromise */
            $timeout = $callable();
            if ($timeout instanceof \Generator) {
                /** @psalm-var ?int */
                $timeout = (yield from $timeout);
            } elseif ($timeout instanceof Promise) {
                /** @psalm-var ?int */
                $timeout = (yield $timeout);
            }
            if ($timeout === self::PAUSE) {
                $this->reportPause(0);
            } elseif ($timeout > 0) {
                $this->reportPause($timeout);
            }
            /** @psalm-suppress MixedArgument */
            if ($timeout === self::STOP || (yield $this->waitSignal($this->pause($timeout)))) {
                break;
            }
        }
    }
    /**
     * Report pause, can be overriden for logging.
     *
     * @param integer $timeout Pause duration, 0 = forever
     *
     * @return void
     */
    protected function reportPause(int $timeout) : void
    {
    }
    /**
     * Get loop name, provided to constructor.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}<?php

/**
 * Periodic loop.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Generic;

use Amp\Promise;
use danog\Loop\ResumableSignalLoop;
/**
 * Periodic loop.
 *
 * Runs a callback at a periodic interval.
 *
 * The loop can be stopped from the outside or
 * from the inside by signaling or returning `true`.
 *
 * @template T as bool
 * @template TGenerator as \Generator<mixed,Promise|array<array-key,Promise>,mixed,Promise<T>|T>
 * @template TPromise as Promise<T>
 *
 * @template TCallable as T|TPromise|TGenerator
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
class PeriodicLoop extends ResumableSignalLoop
{
    /**
     * Callback.
     *
     * @var callable
     *
     * @psalm-var callable():TCallable
     */
    private $callback;
    /**
     * Loop name.
     *
     * @var string
     */
    private $name;
    /**
     * Loop interval.
     *
     * @var ?int
     */
    private $interval;
    /**
     * Constructor.
     *
     * If possible, the callable will be bound to the current instance of the loop.
     *
     * @param callable $callback Callback to call
     * @param string $name Loop name
     * @param ?int $interval Loop interval
     *
     * @psalm-param callable(): TCallable $callback Callable to run
     */
    public function __construct(callable $callback, string $name, ?int $interval)
    {
        if ($callback instanceof \Closure) {
            try {
                $callback = $callback->bindTo($this);
            } catch (\Throwable $e) {
                // Might cause an error for wrapped object methods
            }
        }
        $this->callback = $callback;
        $this->name = $name;
        $this->interval = $interval;
    }
    /**
     * Loop implementation.
     *
     * @return \Generator
     */
    public function loop() : \Generator
    {
        $callback = $this->callback;
        while (true) {
            $result = $callback();
            if ($result instanceof \Generator) {
                /** @psalm-var TGenerator */
                $result = (yield from $result);
            } elseif ($result instanceof Promise) {
                /** @psalm-var TPromise */
                $result = (yield $result);
            }
            if ($result === true) {
                break;
            }
            /** @var ?bool */
            $result = (yield $this->waitSignal($this->pause($this->interval)));
            if ($result === true) {
                break;
            }
        }
    }
    /**
     * Get name of the loop, passed to the constructor.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->name;
    }
}<?php

/**
 * Resumable loop class.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop;

use danog\Loop\Interfaces\ResumableLoopInterface;
use danog\Loop\Traits\ResumableLoop as TraitsResumableLoop;
/**
 * Resumable loop abstract class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
abstract class ResumableLoop implements ResumableLoopInterface
{
    use TraitsResumableLoop;
}<?php

/**
 * Signal loop class.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop;

use danog\Loop\Interfaces\SignalLoopInterface;
use danog\Loop\Traits\Loop;
use danog\Loop\Traits\SignalLoop as TraitsSignalLoop;
/**
 * Signal loop abstract class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
abstract class SignalLoop implements SignalLoopInterface
{
    use Loop;
    use TraitsSignalLoop;
}<?php

/**
 * Resumable signal loop class.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop;

use danog\Loop\Interfaces\ResumableLoopInterface;
use danog\Loop\Interfaces\SignalLoopInterface;
use danog\Loop\Traits\ResumableLoop;
use danog\Loop\Traits\SignalLoop;
/**
 * Resumable signal loop abstract class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
abstract class ResumableSignalLoop implements ResumableLoopInterface, SignalLoopInterface
{
    use ResumableLoop;
    use SignalLoop;
}<?php

/**
 * Loop class.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop;

use danog\Loop\Interfaces\LoopInterface;
use danog\Loop\Traits\Loop as TraitsLoop;
/**
 * Loop abstract class.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
abstract class Loop implements LoopInterface
{
    use TraitsLoop;
}<?php

/**
 * Loop interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Interfaces;

/**
 * Loop interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface LoopInterface
{
    /**
     * Start the loop.
     *
     * Returns false if the loop is already running.
     *
     * @return bool
     */
    public function start() : bool;
    /**
     * The actual loop function.
     *
     * @return \Generator
     */
    public function loop() : \Generator;
    /**
     * Get name of the loop.
     *
     * @return string
     */
    public function __toString() : string;
    /**
     * Check whether loop is running.
     *
     * @return boolean
     */
    public function isRunning() : bool;
}<?php

/**
 * Resumable loop interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Interfaces;

use Amp\Promise;
/**
 * Resumable loop interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface ResumableLoopInterface extends LoopInterface
{
    /**
     * Pause the loop.
     *
     * @param ?int $time Milliseconds for how long to pause the loop, if null will pause forever (until resume is called from outside of the loop)
     *
     * @return Promise Resolved when the loop is resumed
     */
    public function pause(?int $time = null) : Promise;
    /**
     * Resume the loop.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resume() : Promise;
    /**
     * Defer resuming the loop to next tick.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resumeDefer() : Promise;
    /**
     * Defer resuming the loop to next tick.
     *
     * Multiple consecutive calls will yield only one resume.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resumeDeferOnce() : Promise;
}<?php

/**
 * Signal loop interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Interfaces;

use Amp\Promise;
/**
 * Signal loop interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface SignalLoopInterface extends LoopInterface
{
    /**
     * Send a signal to the the loop.
     *
     * @param (\Throwable | mixed) $data Signal to send
     *
     * @return void
     */
    public function signal($data) : void;
    /**
     * Resolve the promise or return|throw the signal.
     *
     * @param (Promise | \Generator) $promise The original promise or generator
     *
     * @return Promise
     *
     * @template T
     *
     * @psalm-param (Promise<T> | \Generator<mixed, (Promise | array<array-key, Promise>), mixed, (Promise<T> | T)>) $promise The original promise or generator
     *
     * @psalm-return Promise<(T | mixed)>
     */
    public function waitSignal($promise) : Promise;
}<?php

/**
 * Loop helper trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Traits;

use Amp\Deferred;
use Amp\Loop as AmpLoop;
use Amp\Promise;
use Amp\Success;
use Closure;
/**
 * Resumable loop helper trait.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait ResumableLoop
{
    use Loop {
        exitedLoop as private parentExitedLoop;
    }
    /**
     * Resume deferred.
     *
     * @var ?Deferred
     */
    private $resume;
    /**
     * Pause deferred.
     *
     * @var ?Deferred
     */
    private $pause;
    /**
     * Resume timer ID.
     *
     * @var ?string
     */
    private $resumeTimer;
    /**
     * Resume deferred ID.
     *
     * @var ?string
     */
    private $resumeDeferred;
    /**
     * Pause the loop.
     *
     * @param ?int $time For how long to pause the loop, if null will pause forever (until resume is called from outside of the loop)
     *
     * @return Promise Resolved when the loop is resumed
     */
    public function pause(?int $time = null) : Promise
    {
        if (!\is_null($time)) {
            if ($time <= 0) {
                return new Success(0);
            }
            if ($this->resumeTimer) {
                AmpLoop::cancel($this->resumeTimer);
                $this->resumeTimer = null;
            }
            /** @psalm-suppress MixedArgumentTypeCoercion */
            $this->resumeTimer = AmpLoop::delay($time, \Closure::fromCallable([$this, 'resumeInternal']));
        }
        $pause = $this->pause;
        $this->pause = new Deferred();
        if ($pause) {
            /**
             * @psalm-suppress InvalidArgument
             */
            AmpLoop::defer([$pause, 'resolve']);
        }
        $this->resume = new Deferred();
        return $this->resume->promise();
    }
    /**
     * Resume the loop.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resume() : Promise
    {
        if (!$this->pause) {
            $this->pause = new Deferred();
        }
        $promise = $this->pause->promise();
        $this->resumeInternal();
        return $promise;
    }
    /**
     * Defer resuming the loop to next tick.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resumeDefer() : Promise
    {
        /** @psalm-suppress MixedArgumentTypeCoercion */
        AmpLoop::defer(Closure::fromCallable([$this, 'resumeInternal']));
        if (!$this->pause) {
            $this->pause = new Deferred();
        }
        return $this->pause->promise();
    }
    /**
     * Defer resuming the loop to next tick.
     *
     * Multiple consecutive calls will yield only one resume.
     *
     * @return Promise Resolved when the loop is paused again
     */
    public function resumeDeferOnce() : Promise
    {
        if (!$this->resumeDeferred) {
            $this->resumeDeferred = AmpLoop::defer(function () {
                $this->resumeDeferred = null;
                $this->resumeInternal();
            });
        }
        if (!$this->pause) {
            $this->pause = new Deferred();
        }
        return $this->pause->promise();
    }
    /**
     * Internal resume function.
     *
     * @return void
     */
    private function resumeInternal() : void
    {
        if ($this->resumeTimer) {
            $storedWatcherId = $this->resumeTimer;
            AmpLoop::cancel($storedWatcherId);
            $this->resumeTimer = null;
        }
        if ($this->resume) {
            $resume = $this->resume;
            $this->resume = null;
            $resume->resolve();
        }
    }
    /**
     * Signal that loop has exIited.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        $this->parentExitedLoop();
        if ($this->resumeTimer) {
            AmpLoop::cancel($this->resumeTimer);
            $this->resumeTimer = null;
        }
    }
}<?php

/**
 * Loop helper trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Traits;

use Amp\Coroutine;
use Amp\Deferred;
use Amp\Promise;
/**
 * Signal loop helper trait.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait SignalLoop
{
    /**
     * Signal deferred.
     *
     * @var ?Deferred
     */
    private $signalDeferred;
    /**
     * Send signal to loop.
     *
     * @param (mixed | \Throwable) $what Data to signal
     *
     * @return void
     */
    public function signal($what) : void
    {
        if ($this->signalDeferred) {
            $deferred = $this->signalDeferred;
            $this->signalDeferred = null;
            if ($what instanceof \Throwable) {
                $deferred->fail($what);
            } else {
                $deferred->resolve($what);
            }
        }
    }
    /**
     * Resolve the promise or return|throw the signal.
     *
     * @param (Promise | \Generator) $promise The original promise or generator
     *
     * @return Promise
     *
     * @template T
     *
     * @psalm-param (Promise<T> | \Generator<mixed, (Promise | array<array-key, Promise>), mixed, (Promise<T> | T)>) $promise The original promise or generator
     *
     * @psalm-return Promise<(T | mixed)>
     */
    public function waitSignal($promise) : Promise
    {
        if ($promise instanceof \Generator) {
            /** @psalm-suppress MixedArgumentTypeCoercion */
            $promise = new Coroutine($promise);
        }
        $this->signalDeferred = new Deferred();
        $combinedPromise = $this->signalDeferred->promise();
        $promise->onResolve(function () use($promise) {
            if ($this->signalDeferred !== null) {
                $deferred = $this->signalDeferred;
                $this->signalDeferred = null;
                $deferred->resolve($promise);
            }
        });
        return $combinedPromise;
    }
}<?php

/**
 * Loop helper trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Traits;

use Amp\Promise;
use function Amp\asyncCall;
/**
 * Loop helper trait.
 *
 * Wraps the asynchronous generator methods with asynchronous promise-based methods
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
trait Loop
{
    /**
     * Whether the loop was started.
     *
     * @var bool
     */
    private $started = false;
    /**
     * Start the loop.
     *
     * Returns false if the loop is already running.
     *
     * @return bool
     */
    public function start() : bool
    {
        if ($this->started) {
            return false;
        }
        asyncCall(function () : \Generator {
            $this->startedLoop();
            try {
                yield from $this->loop();
            } finally {
                $this->exitedLoop();
            }
        });
        return true;
    }
    /**
     * Signal that loop has exIited.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        $this->started = false;
    }
    /**
     * Signal that loop has started.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        $this->started = true;
    }
    /**
     * Check whether loop is running.
     *
     * @return boolean
     */
    public function isRunning() : bool
    {
        return $this->started;
    }
}<?php

/**
 * Signal loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use Amp\Loop;
use danog\Loop\ResumableSignalLoop;
use danog\Loop\SignalLoop;
use danog\Loop\Test\Interfaces\SignalInterface;
use danog\Loop\Test\Traits\Signal;
use function Amp\delay;
class SignalTest extends Fixtures
{
    /**
     * Test signaling loop.
     *
     * @param SignalInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideSignal
     */
    public function testSignal(SignalInterface $loop) : \Generator
    {
        $loop->setInterval(500);
        // Wait 0.5 seconds before returning null
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        $loop->signal(true);
        $this->assertTrue($loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->signal(false);
        $this->assertFalse($loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->signal(null);
        $this->assertNull($loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->signal("test");
        $this->assertEquals("test", $loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->signal($obj = new class
        {
        });
        $this->assertEquals($obj, $loop->getPayload());
        $this->assertAfterStart($loop);
        $loop->setInterval(100);
        // Wait 0.1 seconds before returning null
        $loop->signal(true);
        // Move along loop to apply new interval
        (yield delay(110));
        $this->assertNull($loop->getPayload());
        // Result of sleep
        $loop->signal($e = new \RuntimeException('Test'));
        $this->assertEquals($e, $loop->getException());
        $this->assertFinal($loop);
        $loop = null;
    }
    /**
     * Provide resumable loop implementations.
     *
     * @return array
     */
    public function provideSignal() : array
    {
        return [[new class extends SignalLoop implements SignalInterface
        {
            use Signal;
        }], [new class extends ResumableSignalLoop implements SignalInterface
        {
            use Signal;
        }]];
    }
}<?php

/**
 * Loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use Amp\PHPUnit\AsyncTestCase;
use Amp\Promise;
use Amp\Success;
use danog\Loop\Generic\PeriodicLoop;
use danog\Loop\Loop;
use danog\Loop\Test\Interfaces\LoggingInterface;
use danog\Loop\Test\Traits\Basic;
use danog\Loop\Test\Traits\Logging;
use function Amp\delay;
class PeriodicTest extends AsyncTestCase
{
    /**
     * Test basic loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testGeneric(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $retValue = false;
        $callable = function () use(&$runCount, &$retValue, &$zis) {
            $zis = $this;
            $runCount++;
            return $retValue;
        };
        yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig, $zis, true);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run()
            {
                $this->runCount++;
                return $this->retValue;
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run()
            {
                $this->runCount++;
                return $this->retValue;
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
    }
    /**
     * Test generator loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testGenerator(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $retValue = false;
        $callable = function () use(&$runCount, &$retValue, &$zis) : \Generator {
            $zis = $this;
            (yield delay(1));
            $runCount++;
            return $retValue;
        };
        yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig, $zis, true);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run() : \Generator
            {
                (yield delay(1));
                $this->runCount++;
                return $this->retValue;
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run() : \Generator
            {
                (yield delay(1));
                $this->runCount++;
                return $this->retValue;
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
    }
    /**
     * Test promise loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testPromise(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $retValue = false;
        $callable = function () use(&$runCount, &$retValue, &$zis) : Promise {
            $zis = $this;
            $runCount++;
            return new Success($retValue);
        };
        yield from $this->fixtureAssertions($callable, $runCount, $retValue, $stopSig, $zis, true);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run() : Promise
            {
                $this->runCount++;
                return new Success($this->retValue);
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $retValue = false;
            public $runCount = 0;
            /**
             *
             */
            public function run() : Promise
            {
                $this->runCount++;
                return new Success($this->retValue);
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->retValue, $stopSig, $zisNew, false);
    }
    /**
     * Fixture assertions for started loop.
     *
     * @param LoggingInterface $loop Loop
     *
     * @return void
     */
    private function fixtureStarted(LoggingInterface $loop) : void
    {
        $this->assertTrue($loop->isRunning());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
    }
    /**
     * Run fixture assertions.
     *
     * @param callable $closure Closure
     * @param integer $runCount Run count
     * @param bool $retValue Pause time
     * @param bool $stopSig Whether to stop with signal
     * @param bool $zis Reference to closure's this
     * @param bool $checkZis Whether to check zis
     *
     * @return \Generator
     */
    private function fixtureAssertions(callable $closure, int &$runCount, bool &$retValue, bool $stopSig, &$zis, bool $checkZis) : \Generator
    {
        $loop = new class($closure, Fixtures::LOOP_NAME, 100) extends PeriodicLoop implements LoggingInterface
        {
            use Logging;
        };
        $this->assertEquals(Fixtures::LOOP_NAME, "{$loop}");
        $this->assertFalse($loop->isRunning());
        $this->assertEquals(0, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
        $this->assertEquals(0, $runCount);
        $loop->start();
        (yield delay(2));
        if ($checkZis) {
            $this->assertEquals($loop, $zis);
        } else {
            $this->assertNull($zis);
        }
        $this->fixtureStarted($loop);
        $this->assertEquals(1, $runCount);
        (yield delay(48));
        $this->fixtureStarted($loop);
        $this->assertEquals(1, $runCount);
        (yield delay(60));
        $this->fixtureStarted($loop);
        $this->assertEquals(2, $runCount);
        $loop->resume();
        (yield delay(1));
        $this->assertEquals(3, $runCount);
        if ($stopSig) {
            $loop->signal(true);
        } else {
            $retValue = true;
            $loop->resume();
        }
        (yield delay(1));
        $this->assertEquals($stopSig ? 3 : 4, $runCount);
        $this->assertFalse($loop->isRunning());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(1, $loop->endCounter());
    }
    /**
     * Provide true false.
     *
     * @return array
     */
    public function provideTrueFalse() : array
    {
        return [[true], [false]];
    }
}<?php

/**
 * Resumable loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use danog\Loop\Interfaces\ResumableLoopInterface;
use danog\Loop\ResumableLoop;
use danog\Loop\ResumableSignalLoop;
use danog\Loop\Test\Interfaces\ResumableInterface;
use danog\Loop\Test\Traits\Resumable;
use function Amp\delay;
class ResumableTest extends Fixtures
{
    /**
     * Test pausing loop.
     *
     * @param ResumableInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideResumable
     */
    public function testResumable(ResumableInterface $loop) : \Generator
    {
        $paused = $loop->resume();
        // Returned promise will resolve on next pause
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        (yield delay(10));
        $this->assertTrue(self::isResolved($paused));
        (yield delay(100));
        $this->assertFinal($loop);
    }
    /**
     * Test pausing loop with negative value.
     *
     * @param ResumableInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideResumable
     */
    public function testResumableNegative(ResumableInterface $loop)
    {
        $paused = $loop->resume();
        // Will resolve on next pause
        $loop->setInterval(-1);
        // Will not pause, and finish right away!
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        (yield delay(1));
        $this->assertFalse(self::isResolved($paused));
        // Did not pause
        // Invert the order as the afterTest assertions will begin the test anew
        $this->assertFinal($loop);
        $this->assertAfterStart($loop, false);
    }
    /**
     * Test pausing loop forever, or for 10 seconds, prematurely resuming it.
     *
     * @param ResumableInterface $loop Loop
     * @param ?int $interval Interval
     * @param bool $deferred Deferred
     *
     * @return \Generator
     *
     * @dataProvider provideResumableInterval
     */
    public function testResumableForeverPremature(ResumableInterface $loop, ?int $interval, bool $deferred) : \Generator
    {
        $paused = $deferred ? $loop->resumeDefer() : $loop->resume();
        // Will resolve on next pause
        if ($deferred) {
            (yield delay(1));
            // Avoid resuming after starting
        }
        $loop->setInterval($interval);
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        (yield delay(1));
        $this->assertTrue(self::isResolved($paused));
        // Did pause
        $paused = $deferred ? $loop->resumeDefer() : $loop->resume();
        if ($deferred) {
            $this->assertAfterStart($loop);
            (yield delay(1));
        }
        $this->assertFinal($loop);
        (yield delay(1));
        $this->assertFalse(self::isResolved($paused));
        // Did not pause again
    }
    /**
     * Test pausing loop and then resuming it with deferOnce.
     *
     * @param ResumableInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideResumable
     */
    public function testResumableDeferOnce(ResumableInterface $loop) : \Generator
    {
        $paused1 = $loop->resumeDeferOnce();
        // Will resolve on next pause
        $paused2 = $loop->resumeDeferOnce();
        // Will resolve on next pause
        (yield delay(1));
        // Avoid resuming after starting
        $loop->setInterval(10000);
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        (yield delay(1));
        $this->assertTrue(self::isResolved($paused1));
        // Did pause
        $this->assertTrue(self::isResolved($paused2));
        // Did pause
        $paused1 = $loop->resumeDeferOnce();
        $paused2 = $loop->resumeDeferOnce();
        $this->assertAfterStart($loop);
        (yield delay(1));
        $this->assertFinal($loop);
        (yield delay(1));
        $this->assertFalse(self::isResolved($paused1));
        // Did not pause again
        $this->assertFalse(self::isResolved($paused2));
        // Did not pause again
    }
    /**
     * Provide resumable loop implementations.
     *
     * @return array
     *
     * @psalm-return array<int, array<int, ResumableInterface>>
     */
    public function provideResumable() : array
    {
        return [[new class extends ResumableLoop implements ResumableInterface, ResumableLoopInterface
        {
            use Resumable;
        }], [new class extends ResumableSignalLoop implements ResumableInterface, ResumableLoopInterface
        {
            use Resumable;
        }]];
    }
    /**
     * Provide resumable loop implementations and interval.
     *
     * @return \Generator
     */
    public function provideResumableInterval() : \Generator
    {
        foreach ([true, false] as $deferred) {
            foreach ([10000, null] as $interval) {
                foreach ($this->provideResumable() as $params) {
                    $params[] = $interval;
                    $params[] = $deferred;
                    (yield $params);
                }
            }
        }
    }
}<?php

/**
 * Loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use Amp\PHPUnit\AsyncTestCase;
use Amp\Promise;
use danog\Loop\Test\Interfaces\BasicInterface;
/**
 * Fixtures.
 */
abstract class Fixtures extends AsyncTestCase
{
    const LOOP_NAME = 'PONY';
    /**
     * Check if promise has been resolved afterwards.
     *
     * @param Promise $promise Promise
     *
     * @return boolean
     */
    protected static function isResolved(Promise $promise) : bool
    {
        $resolved = false;
        $promise->onResolve(static function ($e, $res) use(&$resolved) {
            if ($e) {
                throw $e;
            }
            $resolved = true;
        });
        return $resolved;
    }
    /**
     * Execute pre-start assertions.
     *
     * @param BasicInterface $loop Loop
     *
     * @return void
     */
    protected function assertPreStart(BasicInterface $loop)
    {
        $this->assertEquals(self::LOOP_NAME, "{$loop}");
        $this->assertFalse($loop->isRunning());
        $this->assertFalse($loop->ran());
        $this->assertFalse($loop->inited());
        $this->assertEquals(0, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
    }
    /**
     * Execute after-start assertions.
     *
     * @param BasicInterface $loop Loop
     * @param bool $running Whether we should expect the loop to be running
     *
     * @return void
     */
    protected function assertAfterStart(BasicInterface $loop, bool $running = true)
    {
        $this->assertTrue($loop->inited());
        if ($running) {
            $this->assertFalse($loop->ran());
        }
        $this->assertEquals($running, $loop->isRunning(), $running);
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals($running ? 0 : 1, $loop->endCounter());
        $this->assertEquals($running, !$loop->start());
    }
    /**
     * Execute final assertions.
     *
     * @param BasicInterface $loop Loop
     *
     * @return void
     */
    protected function assertFinal(BasicInterface $loop)
    {
        $this->assertTrue($loop->ran());
        $this->assertFalse($loop->isRunning());
        $this->assertTrue($loop->inited());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(1, $loop->endCounter());
    }
}<?php

/**
 * Basic loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\LoopInterface;
/**
 * Basic loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface LoggingInterface extends LoopInterface
{
    /**
     * Get start counter.
     *
     * @return integer
     */
    public function startCounter() : int;
    /**
     * Get end counter.
     *
     * @return integer
     */
    public function endCounter() : int;
}<?php

/**
 * Resumable loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

/**
 * Resumable loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface IntervalInterface
{
    /**
     * Set sleep interval.
     *
     * @param ?int $interval Interval
     *
     * @return void
     */
    public function setInterval(?int $interval) : void;
}<?php

/**
 * Basic loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\LoopInterface;
/**
 * Basic loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface BasicInterface extends LoopInterface, LoggingInterface
{
    /**
     * Check whether the loop inited.
     *
     * @return boolean
     */
    public function inited() : bool;
    /**
     * Check whether the loop ran.
     *
     * @return boolean
     */
    public function ran() : bool;
}<?php

/**
 * Basic loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\LoopInterface;
/**
 * Basic loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface LoggingPauseInterface extends LoopInterface, LoggingInterface
{
    /**
     * Get number of times loop was paused.
     *
     * @return integer
     */
    public function getPauseCount() : int;
    /**
     * Get last pause.
     *
     * @return integer
     */
    public function getLastPause() : int;
}<?php

/**
 * Signal loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\SignalLoopInterface;
/**
 * Signal loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface SignalInterface extends BasicInterface, IntervalInterface, SignalLoopInterface
{
    /**
     * Get signaled payload.
     *
     * @return mixed
     */
    public function getPayload();
    /**
     * Get signaled exception.
     *
     * @return ?\Throwable
     */
    public function getException() : ?\Throwable;
}<?php

/**
 * Resumable loop test interface.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Interfaces;

use danog\Loop\Interfaces\ResumableLoopInterface;
/**
 * Resumable loop test interface.
 *
 * @author Daniil Gentili <daniil@daniil.it>
 */
interface ResumableInterface extends BasicInterface, IntervalInterface, ResumableLoopInterface
{
}<?php

/**
 * Loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use Amp\PHPUnit\AsyncTestCase;
use Amp\Promise;
use Amp\Success;
use danog\Loop\Generic\GenericLoop;
use danog\Loop\Loop;
use danog\Loop\Test\Interfaces\LoggingPauseInterface;
use danog\Loop\Test\Traits\Basic;
use danog\Loop\Test\Traits\LoggingPause;
use function Amp\delay;
class GenericTest extends AsyncTestCase
{
    /**
     * Test basic loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testGeneric(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $pauseTime = GenericLoop::PAUSE;
        $callable = function () use(&$runCount, &$pauseTime, &$zis) {
            $zis = $this;
            $runCount++;
            return $pauseTime;
        };
        yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig, $zis, true);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run()
            {
                $this->runCount++;
                return $this->pauseTime;
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run()
            {
                $this->runCount++;
                return $this->pauseTime;
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
    }
    /**
     * Test generator loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testGenerator(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $pauseTime = GenericLoop::PAUSE;
        $callable = function () use(&$runCount, &$pauseTime, &$zis) : \Generator {
            $zis = $this;
            (yield delay(1));
            $runCount++;
            return $pauseTime;
        };
        yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig, $zis, true);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run() : \Generator
            {
                (yield delay(1));
                $this->runCount++;
                return $this->pauseTime;
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run() : \Generator
            {
                (yield delay(1));
                $this->runCount++;
                return $this->pauseTime;
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
    }
    /**
     * Test promise loop.
     *
     * @param bool $stopSig Whether to stop with signal
     *
     * @return \Generator
     *
     * @dataProvider provideTrueFalse
     */
    public function testPromise(bool $stopSig) : \Generator
    {
        $runCount = 0;
        $pauseTime = GenericLoop::PAUSE;
        $callable = function () use(&$runCount, &$pauseTime, &$zis) : Promise {
            $zis = $this;
            $runCount++;
            return new Success($pauseTime);
        };
        yield from $this->fixtureAssertions($callable, $runCount, $pauseTime, $stopSig, $zis, true);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run() : Promise
            {
                $this->runCount++;
                return new Success($this->pauseTime);
            }
        };
        yield from $this->fixtureAssertions([$obj, 'run'], $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
        $obj = new class
        {
            public $pauseTime = GenericLoop::PAUSE;
            public $runCount = 0;
            /**
             *
             */
            public function run() : Promise
            {
                $this->runCount++;
                return new Success($this->pauseTime);
            }
        };
        yield from $this->fixtureAssertions(\Closure::fromCallable([$obj, 'run']), $obj->runCount, $obj->pauseTime, $stopSig, $zisNew, false);
    }
    /**
     * Fixture assertions for started loop.
     *
     * @param LoggingPauseInterface $loop Loop
     *
     * @return void
     */
    private function fixtureStarted(LoggingPauseInterface $loop) : void
    {
        $this->assertTrue($loop->isRunning());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
    }
    /**
     * Run fixture assertions.
     *
     * @param callable $closure Closure
     * @param integer $runCount Run count
     * @param ?integer $pauseTime Pause time
     * @param bool $stopSig Whether to stop with signal
     * @param bool $zis Reference to closure's this
     * @param bool $checkZis Whether to check zis
     *
     * @return \Generator
     */
    private function fixtureAssertions(callable $closure, int &$runCount, ?int &$pauseTime, bool $stopSig, &$zis, bool $checkZis) : \Generator
    {
        $loop = new class($closure, Fixtures::LOOP_NAME) extends GenericLoop implements LoggingPauseInterface
        {
            use LoggingPause;
        };
        $this->assertEquals(Fixtures::LOOP_NAME, "{$loop}");
        $this->assertFalse($loop->isRunning());
        $this->assertEquals(0, $loop->startCounter());
        $this->assertEquals(0, $loop->endCounter());
        $this->assertEquals(0, $runCount);
        $this->assertEquals(0, $loop->getPauseCount());
        $loop->start();
        (yield delay(2));
        if ($checkZis) {
            $this->assertEquals($loop, $zis);
        } else {
            $this->assertNull($zis);
        }
        $this->fixtureStarted($loop);
        $this->assertEquals(1, $runCount);
        $this->assertEquals(1, $loop->getPauseCount());
        $this->assertEquals(0, $loop->getLastPause());
        $pauseTime = 100;
        $loop->resume();
        (yield delay(2));
        $this->fixtureStarted($loop);
        $this->assertEquals(2, $runCount);
        $this->assertEquals(2, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        (yield delay(48));
        $this->fixtureStarted($loop);
        $this->assertEquals(2, $runCount);
        $this->assertEquals(2, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        (yield delay(60));
        $this->fixtureStarted($loop);
        $this->assertEquals(3, $runCount);
        $this->assertEquals(3, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        $loop->resume();
        (yield delay(1));
        $this->assertEquals(4, $runCount);
        $this->assertEquals(4, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        if ($stopSig) {
            $loop->signal(true);
        } else {
            $pauseTime = GenericLoop::STOP;
            $loop->resume();
        }
        (yield delay(1));
        $this->assertEquals($stopSig ? 4 : 5, $runCount);
        $this->assertEquals(4, $loop->getPauseCount());
        $this->assertEquals(100, $loop->getLastPause());
        $this->assertFalse($loop->isRunning());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(1, $loop->endCounter());
    }
    /**
     * Provide true false.
     *
     * @return array
     */
    public function provideTrueFalse() : array
    {
        return [[true], [false]];
    }
}<?php

/**
 * Exception test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use Generator;
trait BasicException
{
    use Basic;
    /**
     * Loop implementation.
     *
     * @return Generator
     */
    public function loop() : Generator
    {
        $this->inited = true;
        throw new \RuntimeException('Threw exception!');
        $this->ran = true;
    }
}<?php

/**
 * Loop test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use danog\Loop\Test\LoopTest;
use Generator;
use function Amp\delay;
trait Basic
{
    use Logging;
    /**
     * Check whether the loop inited.
     *
     * @var bool
     */
    private $inited = false;
    /**
     * Check whether the loop ran.
     *
     * @var bool
     */
    private $ran = false;
    /**
     * Check whether the loop inited.
     *
     * @return boolean
     */
    public function inited() : bool
    {
        return $this->inited;
    }
    /**
     * Check whether the loop ran.
     *
     * @return boolean
     */
    public function ran() : bool
    {
        return $this->ran;
    }
    /**
     * Loop implementation.
     *
     * @return Generator
     */
    public function loop() : Generator
    {
        $this->inited = true;
        (yield delay(100));
        $this->ran = true;
    }
    /**
     * Get loop name.
     *
     * @return string
     */
    public function __toString() : string
    {
        return LoopTest::LOOP_NAME;
    }
}<?php

/**
 * Resumable test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use danog\Loop\Interfaces\ResumableLoopInterface;
use Generator;
use function Amp\delay;
trait Signal
{
    use Resumable;
    /**
     * Signaled payload.
     *
     * @var mixed
     */
    private $payload;
    /**
     * Signaled exception.
     *
     * @var ?\Throwable
     */
    private $exception;
    /**
     * Get signaled payload.
     *
     * @return mixed
     */
    public function getPayload()
    {
        return $this->payload;
    }
    /**
     * Get signaled exception.
     *
     * @return \Throwable
     */
    public function getException() : ?\Throwable
    {
        return $this->exception;
    }
    /**
     * Test waiting signal on interval.
     *
     * @param integer $interval Interval
     *
     * @return \Generator
     */
    private function testGenerator(int $interval) : \Generator
    {
        (yield delay($interval));
    }
    /**
     * Loop implementation.
     *
     * @return Generator
     */
    public function loop() : Generator
    {
        $this->inited = true;
        try {
            while (true) {
                $this->payload = (yield $this->waitSignal($this instanceof ResumableLoopInterface ? $this->pause($this->interval) : $this->testGenerator($this->interval)));
            }
        } catch (\Throwable $e) {
            $this->exception = $e;
        }
        $this->ran = true;
    }
}<?php

/**
 * Loop test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

trait Logging
{
    /**
     * Check whether the loop started.
     *
     * @var int
     */
    private $startCounter = 0;
    /**
     * Check whether the loop ended.
     *
     * @var int
     */
    private $endCounter = 0;
    /**
     * Signal that loop started.
     *
     * @return void
     */
    protected function startedLoop() : void
    {
        $this->startCounter++;
        parent::startedLoop();
    }
    /**
     * Signal that loop ended.
     *
     * @return void
     */
    protected function exitedLoop() : void
    {
        $this->endCounter++;
        parent::exitedLoop();
    }
    /**
     * Get start counter.
     *
     * @return integer
     */
    public function startCounter() : int
    {
        return $this->startCounter;
    }
    /**
     * Get end counter.
     *
     * @return integer
     */
    public function endCounter() : int
    {
        return $this->endCounter;
    }
}<?php

/**
 * Loop test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use function Amp\delay;
trait LoggingPause
{
    use Logging;
    /**
     * Number of times loop was paused.
     *
     * @var integer
     */
    private $pauseCount = 0;
    /**
     * Last pause delay.
     *
     * @var int
     */
    private $lastPause = 0;
    /**
     * Get number of times loop was paused.
     *
     * @return integer
     */
    public function getPauseCount() : int
    {
        return $this->pauseCount;
    }
    /**
     * Get last pause.
     *
     * @return integer
     */
    public function getLastPause() : int
    {
        return $this->lastPause;
    }
    /**
     * Report pause, can be overriden for logging.
     *
     * @param integer $timeout Pause duration, 0 = forever
     *
     * @return void
     */
    protected function reportPause(int $timeout) : void
    {
        parent::reportPause($timeout);
        $this->pauseCount++;
        $this->lastPause = $timeout;
    }
}<?php

/**
 * Resumable test trait.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test\Traits;

use Generator;
trait Resumable
{
    use Basic;
    /**
     * Set interval.
     *
     * @var ?int
     */
    protected $interval = 100;
    /**
     * Set sleep interval.
     *
     * @param ?int $interval Interval
     *
     * @return void
     */
    public function setInterval(?int $interval) : void
    {
        $this->interval = $interval;
    }
    /**
     * Loop implementation.
     *
     * @return Generator
     */
    public function loop() : Generator
    {
        $this->inited = true;
        (yield $this->pause($this->interval));
        $this->ran = true;
    }
}<?php

/**
 * Loop test.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2020 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/MIT MIT
 */
namespace danog\Loop\Test;

use danog\Loop\Loop;
use danog\Loop\ResumableLoop;
use danog\Loop\ResumableSignalLoop;
use danog\Loop\SignalLoop;
use danog\Loop\Test\Interfaces\BasicInterface;
use danog\Loop\Test\Traits\Basic;
use danog\Loop\Test\Traits\BasicException;
use function Amp\delay;
class LoopTest extends Fixtures
{
    /**
     * Test basic loop.
     *
     * @param BasicInterface $loop Loop
     *
     * @return \Generator
     *
     * @dataProvider provideBasic
     */
    public function testLoop(BasicInterface $loop) : \Generator
    {
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertAfterStart($loop);
        (yield delay(110));
        $this->assertFinal($loop);
    }
    /**
     * Test basic exception in loop.
     *
     * @param BasicInterface $loop Loop
     *
     * @return void
     *
     * @dataProvider provideBasicExceptions
     */
    public function testException(BasicInterface $loop) : void
    {
        $this->expectException(\RuntimeException::class);
        $this->assertPreStart($loop);
        $this->assertTrue($loop->start());
        $this->assertFalse($loop->isRunning());
        $this->assertTrue($loop->inited());
        $this->assertEquals(1, $loop->startCounter());
        $this->assertEquals(1, $loop->endCounter());
    }
    /**
     * Provide loop implementations.
     *
     * @return array
     */
    public function provideBasic() : array
    {
        return [[new class extends Loop implements BasicInterface
        {
            use Basic;
        }], [new class extends SignalLoop implements BasicInterface
        {
            use Basic;
        }], [new class extends ResumableLoop implements BasicInterface
        {
            use Basic;
        }], [new class extends ResumableSignalLoop implements BasicInterface
        {
            use Basic;
        }]];
    }
    /**
     * Provide loop implementations.
     *
     * @return array
     */
    public function provideBasicExceptions() : array
    {
        return [[new class extends Loop implements BasicInterface
        {
            use BasicException;
        }], [new class extends SignalLoop implements BasicInterface
        {
            use BasicException;
        }], [new class extends ResumableLoop implements BasicInterface
        {
            use BasicException;
        }], [new class extends ResumableSignalLoop implements BasicInterface
        {
            use BasicException;
        }]];
    }
}{
    "name": "danog/dns-over-https",
    "homepage": "https://github.com/danog/dns-over-https",
    "description": "Async DNS-over-HTTPS resolution for Amp.",
    "keywords": [
        "dns",
        "doh",
        "dns-over-https",
        "https",
        "resolve",
        "client",
        "async",
        "amp",
        "amphp"
    ],
    "license": "MIT",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        },
        {
            "name": "Chris Wright",
            "email": "addr@daverandom.com"
        },
        {
            "name": "Daniel Lowrey",
            "email": "rdlowrey@php.net"
        },
        {
            "name": "Bob Weinand",
            "email": "bobwei9@hotmail.com"
        },
        {
            "name": "Niklas Keller",
            "email": "me@kelunik.com"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        }
    ],
    "require": {
        "php": ">=7.0",
        "amphp/cache": "^1",
        "amphp/parser": "^1",
        "danog/libdns-json": "^0.1",
        "daverandom/libdns": "^2.0.1",
        "amphp/amp": "^2",
        "amphp/http-client": "^4",
        "amphp/dns": "^1",
        "ext-filter": "*",
        "ext-json": "*"
    },
    "require-dev": {
        "amphp/phpunit-util": "^1",
        "phpunit/phpunit": "^6",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\DoH\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\DoH\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\DoH;

use Amp\Cache\ArrayCache;
use Amp\Cache\Cache;
use Amp\Dns\ConfigException;
use Amp\Dns\ConfigLoader;
use Amp\Dns\Resolver;
use Amp\Dns\Rfc1035StubResolver;
use Amp\Dns\UnixConfigLoader;
use Amp\Dns\WindowsConfigLoader;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\HttpClientBuilder;
final class DoHConfig
{
    private $nameservers;
    private $httpClient;
    private $subResolver;
    private $configLoader;
    private $cache;
    /**
     *
     */
    public function __construct(array $nameservers, DelegateHttpClient $httpClient = null, Resolver $resolver = null, ConfigLoader $configLoader = null, Cache $cache = null)
    {
        if (\count($nameservers) < 1) {
            throw new ConfigException("At least one nameserver is required for a valid config");
        }
        foreach ($nameservers as $nameserver) {
            $this->validateNameserver($nameserver);
        }
        $this->nameservers = $nameservers;
        $this->httpClient = $httpClient ?? HttpClientBuilder::buildDefault();
        $this->cache = $cache ?? new ArrayCache(5000, 256);
        $this->configLoader = $configLoader ?? (\stripos(PHP_OS, "win") === 0 ? new WindowsConfigLoader() : new UnixConfigLoader());
        $this->subResolver = $resolver ?? new Rfc1035StubResolver(null, $this->configLoader);
    }
    /**
     *
     */
    private function validateNameserver($nameserver)
    {
        if (!$nameserver instanceof Nameserver) {
            throw new ConfigException("Invalid nameserver: {$nameserver}");
        }
    }
    /**
     *
     */
    public function getNameservers() : array
    {
        return $this->nameservers;
    }
    /**
     *
     */
    public function isNameserver($string) : bool
    {
        foreach ($this->nameservers as $nameserver) {
            if ($nameserver->getHost() === $string) {
                return true;
            }
        }
        return false;
    }
    /**
     *
     */
    public function getHttpClient() : DelegateHttpClient
    {
        return $this->httpClient;
    }
    /**
     *
     */
    public function getCache() : Cache
    {
        return $this->cache;
    }
    /**
     *
     */
    public function getConfigLoader() : ConfigLoader
    {
        return $this->configLoader;
    }
    /**
     *
     */
    public function getSubResolver() : Resolver
    {
        return $this->subResolver;
    }
}<?php

namespace Amp\DoH;

/**
 * Throw when DoH resolution fails.
 */
class DoHException extends \Exception
{
}<?php

namespace Amp\DoH\Internal;

use Amp\DoH\DoHException;
use Amp\DoH\Nameserver;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Http\Client\Request;
use Amp\Promise;
use danog\LibDNSJson\JsonDecoderFactory;
use danog\LibDNSJson\QueryEncoderFactory;
use LibDNS\Decoder\DecoderFactory;
use LibDNS\Encoder\EncoderFactory;
use LibDNS\Messages\Message;
use function Amp\call;
/** @internal */
final class HttpsSocket extends Socket
{
    /** @var \Amp\Http\HttpClient */
    private $httpClient;
    /** @var \Amp\DoH\Nameserver */
    private $nameserver;
    /** @var \LibDNS\Encoder\Encoder */
    private $encoder;
    /** @var \LibDNS\Decoder\Decoder */
    private $decoder;
    /** @var \Amp\Deferred */
    private $responseDeferred;
    /**
     *
     */
    public static function connect(DelegateHttpClient $httpClient, Nameserver $nameserver) : Socket
    {
        return new self($httpClient, $nameserver);
    }
    /**
     *
     */
    protected function __construct(DelegateHttpClient $httpClient, Nameserver $nameserver)
    {
        $this->httpClient = $httpClient;
        $this->nameserver = $nameserver;
        if ($nameserver->getType() !== Nameserver::GOOGLE_JSON) {
            $this->encoder = (new EncoderFactory())->create();
            $this->decoder = (new DecoderFactory())->create();
        } else {
            $this->encoder = (new QueryEncoderFactory())->create();
            $this->decoder = (new JsonDecoderFactory())->create();
        }
        parent::__construct();
    }
    /**
     *
     */
    protected function resolve(Message $message) : Promise
    {
        $id = $message->getID();
        switch ($this->nameserver->getType()) {
            case Nameserver::RFC8484_GET:
                $data = $this->encoder->encode($message);
                $request = new Request($this->nameserver->getUri() . '?' . \http_build_query(['dns' => \base64_encode($data), 'ct' => 'application/dns-message']), "GET");
                $request->setHeader('accept', 'application/dns-message');
                $request->setHeaders($this->nameserver->getHeaders());
                break;
            case Nameserver::RFC8484_POST:
                $data = $this->encoder->encode($message);
                $request = new Request($this->nameserver->getUri(), "POST");
                $request->setBody($data);
                $request->setHeader('content-type', 'application/dns-message');
                $request->setHeader('accept', 'application/dns-message');
                $request->setHeader('content-length', \strlen($data));
                $request->setHeaders($this->nameserver->getHeaders());
                break;
            case Nameserver::GOOGLE_JSON:
                $data = $this->encoder->encode($message);
                $request = new Request($this->nameserver->getUri() . '?' . $data, "GET");
                $request->setHeader('accept', 'application/dns-json');
                $request->setHeaders($this->nameserver->getHeaders());
                break;
        }
        $response = $this->httpClient->request($request);
        return call(function () use($response, $id) {
            $response = (yield $response);
            if ($response->getStatus() !== 200) {
                throw new DoHException("HTTP result !== 200: " . $response->getStatus() . " " . $response->getReason(), $response->getStatus());
            }
            $response = (yield $response->getBody()->buffer());
            switch ($this->nameserver->getType()) {
                case Nameserver::RFC8484_GET:
                case Nameserver::RFC8484_POST:
                    return $this->decoder->decode($response);
                case Nameserver::GOOGLE_JSON:
                    return $this->decoder->decode($response, $id);
            }
        });
    }
}<?php

namespace Amp\DoH\Internal;

use Amp;
use Amp\ByteStream\StreamException;
use Amp\Deferred;
use Amp\Dns\DnsException;
use Amp\Dns\TimeoutException;
use Amp\DoH\DoHException;
use Amp\DoH\Nameserver;
use Amp\Http\Client\DelegateHttpClient;
use Amp\Promise;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Records\Question;
use function Amp\call;
/** @internal */
abstract class Socket
{
    const MAX_CONCURRENT_REQUESTS = 500;
    /** @var array Contains already sent queries with no response yet. For UDP this is exactly zero or one item. */
    private $pending = [];
    /** @var MessageFactory */
    private $messageFactory;
    /** @var callable */
    private $onResolve;
    /** @var array Queued requests if the number of concurrent requests is too large. */
    private $queue = [];
    /**
     * @param string $uri
     *
     * @return Promise<self>
     */
    public static abstract function connect(DelegateHttpClient $httpClient, Nameserver $nameserver) : self;
    /**
     * @param Message $message
     *
     * @return Promise<int>
     */
    protected abstract function resolve(Message $message) : Promise;
    /**
     *
     */
    protected function __construct()
    {
        $this->messageFactory = new MessageFactory();
        $this->onResolve = function (\Throwable $exception = null, Message $message = null) {
            if ($exception) {
                $this->error($exception);
                return;
            }
            \assert($message instanceof Message);
            $id = $message->getId();
            // Ignore duplicate and invalid responses.
            if (isset($this->pending[$id]) && $this->matchesQuestion($message, $this->pending[$id]->question)) {
                /** @var Deferred $deferred */
                $deferred = $this->pending[$id]->deferred;
                unset($this->pending[$id]);
                $deferred->resolve($message);
            }
        };
    }
    /**
     * @param \LibDNS\Records\Question $question
     * @param int $timeout
     *
     * @return \Amp\Promise<\LibDNS\Messages\Message>
     */
    public final function ask(Question $question, int $timeout) : Promise
    {
        return call(function () use($question, $timeout) {
            if (\count($this->pending) > self::MAX_CONCURRENT_REQUESTS) {
                $deferred = new Deferred();
                $this->queue[] = $deferred;
                (yield $deferred->promise());
            }
            do {
                $id = \random_int(0, 0xffff);
            } while (isset($this->pending[$id]));
            $deferred = new Deferred();
            $pending = new class
            {
                use Amp\Struct;
                public $deferred;
                public $question;
            };
            $pending->deferred = $deferred;
            $pending->question = $question;
            $this->pending[$id] = $pending;
            $message = $this->createMessage($question, $id);
            try {
                $response = $this->resolve($message);
            } catch (StreamException $exception) {
                $exception = new DnsException("Sending the request failed", 0, $exception);
                $this->error($exception);
                throw $exception;
            }
            $response->onResolve($this->onResolve);
            try {
                // Work around an OPCache issue that returns an empty array with "return yield ...",
                // so assign to a variable first and return after the try block.
                //
                // See https://github.com/amphp/dns/issues/58.
                // See https://bugs.php.net/bug.php?id=74840.
                $result = (yield Promise\timeout($deferred->promise(), $timeout));
            } catch (Amp\TimeoutException $exception) {
                unset($this->pending[$id]);
                throw new TimeoutException("Didn't receive a response within {$timeout} milliseconds.");
            } finally {
                if ($this->queue) {
                    $deferred = \array_shift($this->queue);
                    $deferred->resolve();
                }
            }
            return $result;
        });
    }
    /**
     *
     */
    private function error(\Throwable $exception)
    {
        if (empty($this->pending)) {
            return;
        }
        if (!$exception instanceof DnsException && !$exception instanceof DoHException) {
            $message = "Unexpected error during resolution: " . $exception->getMessage();
            $exception = new DnsException($message, 0, $exception);
        }
        $pending = $this->pending;
        $this->pending = [];
        foreach ($pending as $pendingQuestion) {
            /** @var Deferred $deferred */
            $deferred = $pendingQuestion->deferred;
            $deferred->fail($exception);
        }
    }
    /**
     *
     */
    protected final function createMessage(Question $question, int $id) : Message
    {
        $request = $this->messageFactory->create(MessageTypes::QUERY);
        $request->getQuestionRecords()->add($question);
        $request->isRecursionDesired(true);
        $request->setID($id);
        return $request;
    }
    /**
     *
     */
    private function matchesQuestion(Message $message, Question $question) : bool
    {
        if ($message->getType() !== MessageTypes::RESPONSE) {
            return false;
        }
        $questionRecords = $message->getQuestionRecords();
        // We only ever ask one question at a time
        if (\count($questionRecords) !== 1) {
            return false;
        }
        $questionRecord = $questionRecords->getIterator()->current();
        if ($questionRecord->getClass() !== $question->getClass()) {
            return false;
        }
        if ($questionRecord->getType() !== $question->getType()) {
            return false;
        }
        if ($questionRecord->getName()->getValue() !== $question->getName()->getValue()) {
            return false;
        }
        return true;
    }
}<?php

namespace Amp\DoH;

use Amp\Cache\Cache;
use Amp\Dns\Config;
use Amp\Dns\ConfigException;
use Amp\Dns\DnsException;
use Amp\Dns\NoRecordException;
use Amp\Dns\Record;
use Amp\Dns\Resolver;
use Amp\Dns\TimeoutException;
use Amp\DoH\Internal\HttpsSocket;
use Amp\DoH\Internal\Socket;
use Amp\MultiReasonException;
use Amp\Promise;
use LibDNS\Messages\Message;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use function Amp\call;
use function Amp\Dns\normalizeName;
final class Rfc8484StubResolver implements Resolver
{
    const CACHE_PREFIX = "amphp.doh.";
    /** @var \Amp\Dns\ConfigLoader */
    private $configLoader;
    /** @var \LibDNS\Records\QuestionFactory */
    private $questionFactory;
    /** @var \Amp\Dns\Config|null */
    private $config;
    /** @var Promise|null */
    private $pendingConfig;
    /** @var \Amp\DoH\DoHConfig */
    private $dohConfig;
    /** @var Cache */
    private $cache;
    /** @var Promise[] */
    private $pendingQueries = [];
    /** @var \Amp\Dns\Rfc1035StubResolver */
    private $subResolver;
    /**
     *
     */
    public function __construct(DoHConfig $config)
    {
        $resolver = $config->getSubResolver();
        if ($resolver instanceof Rfc8484StubResolver) {
            throw new ConfigException("Can't use Rfc8484StubResolver as subresolver for Rfc8484StubResolver");
        }
        $this->cache = $config->getCache();
        $this->configLoader = $config->getConfigLoader();
        $this->subResolver = $resolver;
        $this->dohConfig = $config;
        $this->questionFactory = new QuestionFactory();
    }
    /**
     * @inheritdoc
     */
    public function resolve(string $name, int $typeRestriction = null) : Promise
    {
        if ($typeRestriction !== null && $typeRestriction !== Record::A && $typeRestriction !== Record::AAAA) {
            throw new \Error("Invalid value for parameter 2: null|Record::A|Record::AAAA expected");
        }
        return call(function () use($name, $typeRestriction) {
            if (!$this->config) {
                try {
                    (yield $this->reloadConfig());
                } catch (ConfigException $e) {
                    $this->config = new Config(['0.0.0.0'], []);
                }
            }
            switch ($typeRestriction) {
                case Record::A:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        return [new Record($name, Record::A, null)];
                    } elseif (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        throw new DnsException("Got an IPv6 address, but type is restricted to IPv4");
                    }
                    break;
                case Record::AAAA:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        return [new Record($name, Record::AAAA, null)];
                    } elseif (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        throw new DnsException("Got an IPv4 address, but type is restricted to IPv6");
                    }
                    break;
                default:
                    if (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
                        return [new Record($name, Record::A, null)];
                    } elseif (\filter_var($name, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
                        return [new Record($name, Record::AAAA, null)];
                    }
                    break;
            }
            $name = normalizeName($name);
            if ($records = $this->queryHosts($name, $typeRestriction)) {
                return $records;
            }
            // Follow RFC 6761 and never send queries for localhost to the caching DNS server
            // Usually, these queries are already resolved via queryHosts()
            if ($name === 'localhost') {
                return $typeRestriction === Record::AAAA ? [new Record('::1', Record::AAAA, null)] : [new Record('127.0.0.1', Record::A, null)];
            }
            if ($this->dohConfig->isNameserver($name)) {
                // Work around an OPCache issue that returns an empty array with "return yield ...",
                // so assign to a variable first and return after the try block.
                //
                // See https://github.com/amphp/dns/issues/58.
                // See https://bugs.php.net/bug.php?id=74840.
                $records = (yield $this->subResolver->resolve($name, $typeRestriction));
                return $records;
            }
            for ($redirects = 0; $redirects < 5; $redirects++) {
                try {
                    if ($typeRestriction) {
                        $records = (yield $this->query($name, $typeRestriction));
                    } else {
                        try {
                            list(, $records) = (yield Promise\some([$this->query($name, Record::A), $this->query($name, Record::AAAA)]));
                            $records = \array_merge(...$records);
                            break;
                            // Break redirect loop, otherwise we query the same records 5 times
                        } catch (MultiReasonException $e) {
                            $errors = [];
                            foreach ($e->getReasons() as $reason) {
                                if ($reason instanceof NoRecordException) {
                                    throw $reason;
                                }
                                $error = (string) $reason;
                                //->getMessage();
                                if ($reason instanceof MultiReasonException) {
                                    $reasons = [];
                                    foreach ($reason->getReasons() as $reason) {
                                        $reasons[] = (string) $reason;
                                        //->getMessage();
                                    }
                                    $error .= " (" . \implode(", ", $reasons) . ")";
                                }
                                $errors[] = $error;
                            }
                            throw new DnsException("All query attempts failed for {$name}: " . \implode(", ", $errors), 0, $e);
                        }
                    }
                } catch (NoRecordException $e) {
                    try {
                        /** @var Record[] $cnameRecords */
                        $cnameRecords = (yield $this->query($name, Record::CNAME));
                        $name = $cnameRecords[0]->getValue();
                        continue;
                    } catch (NoRecordException $e) {
                        /** @var Record[] $dnameRecords */
                        $dnameRecords = (yield $this->query($name, Record::DNAME));
                        $name = $dnameRecords[0]->getValue();
                        continue;
                    }
                }
            }
            return $records;
        });
    }
    /**
     * Reloads the configuration in the background.
     *
     * Once it's finished, the configuration will be used for new requests.
     *
     * @return Promise
     */
    public function reloadConfig() : Promise
    {
        if ($this->pendingConfig) {
            return $this->pendingConfig;
        }
        $promise = call(function () {
            (yield $this->subResolver->reloadConfig());
            $this->config = (yield $this->configLoader->loadConfig());
        });
        $this->pendingConfig = $promise;
        $promise->onResolve(function () {
            $this->pendingConfig = null;
        });
        return $promise;
    }
    /**
     *
     */
    private function queryHosts(string $name, int $typeRestriction = null) : array
    {
        $hosts = $this->config->getKnownHosts();
        $records = [];
        $returnIPv4 = $typeRestriction === null || $typeRestriction === Record::A;
        $returnIPv6 = $typeRestriction === null || $typeRestriction === Record::AAAA;
        if ($returnIPv4 && isset($hosts[Record::A][$name])) {
            $records[] = new Record($hosts[Record::A][$name], Record::A, null);
        }
        if ($returnIPv6 && isset($hosts[Record::AAAA][$name])) {
            $records[] = new Record($hosts[Record::AAAA][$name], Record::AAAA, null);
        }
        return $records;
    }
    /**
     * @inheritdoc
     */
    public function query(string $name, int $type) : Promise
    {
        $pendingQueryKey = $type . " " . $name;
        if (isset($this->pendingQueries[$pendingQueryKey])) {
            return $this->pendingQueries[$pendingQueryKey];
        }
        $promise = call(function () use($name, $type) {
            if (!$this->config) {
                try {
                    (yield $this->reloadConfig());
                } catch (ConfigException $e) {
                    $this->config = new Config(['0.0.0.0'], []);
                }
            }
            $name = $this->normalizeName($name, $type);
            $question = $this->createQuestion($name, $type);
            if (null !== ($cachedValue = (yield $this->cache->get($this->getCacheKey($name, $type))))) {
                return $this->decodeCachedResult($name, $type, $cachedValue);
            }
            /** @var Nameserver[] $nameservers */
            $nameservers = $this->dohConfig->getNameservers();
            $attempts = $this->config->getAttempts() * \count($nameservers);
            $attempt = 0;
            /** @var Socket $socket */
            $nameserver = $nameservers[0];
            $socket = $this->getSocket($nameserver);
            $attemptDescription = [];
            $exceptions = [];
            while ($attempt < $attempts) {
                try {
                    $attemptDescription[] = $nameserver;
                    /** @var Message $response */
                    try {
                        $response = (yield $socket->ask($question, $this->config->getTimeout()));
                    } catch (DoHException $e) {
                        // Defer call, because it might interfere with the unreference() call in Internal\Socket otherwise
                        $exceptions[] = $e;
                        $i = ++$attempt % \count($nameservers);
                        $nameserver = $nameservers[$i];
                        $socket = $this->getSocket($nameserver);
                        continue;
                    } catch (NoRecordException $e) {
                        // Defer call, because it might interfere with the unreference() call in Internal\Socket otherwise
                        $i = ++$attempt % \count($nameservers);
                        $nameserver = $nameservers[$i];
                        $socket = $this->getSocket($nameserver);
                        continue;
                    }
                    $this->assertAcceptableResponse($response);
                    if ($response->isTruncated()) {
                        throw new DnsException("Server returned a truncated response for '{$name}' (" . Record::getName($type) . ")");
                    }
                    $answers = $response->getAnswerRecords();
                    $result = [];
                    $ttls = [];
                    /** @var \LibDNS\Records\Resource $record */
                    foreach ($answers as $record) {
                        $recordType = $record->getType();
                        $result[$recordType][] = (string) $record->getData();
                        // Cache for max one day
                        $ttls[$recordType] = \min($ttls[$recordType] ?? 86400, $record->getTTL());
                    }
                    foreach ($result as $recordType => $records) {
                        // We don't care here whether storing in the cache fails
                        $this->cache->set($this->getCacheKey($name, $recordType), \json_encode($records), $ttls[$recordType]);
                    }
                    if (!isset($result[$type])) {
                        // "it MUST NOT cache it for longer than five (5) minutes" per RFC 2308 section 7.1
                        $this->cache->set($this->getCacheKey($name, $type), \json_encode([]), 300);
                        throw new NoRecordException("No records returned for '{$name}' (" . Record::getName($type) . ")");
                    }
                    return \array_map(function ($data) use($type, $ttls) {
                        return new Record($data, $type, $ttls[$type]);
                    }, $result[$type]);
                } catch (TimeoutException $e) {
                    // Defer call, because it might interfere with the unreference() call in Internal\Socket otherwise
                    $i = ++$attempt % \count($nameservers);
                    $nameserver = $nameservers[$i];
                    $socket = $this->getSocket($nameserver);
                    continue;
                }
            }
            $timeout = new TimeoutException(\sprintf("No response for '%s' (%s) from any nameserver after %d attempts, tried %s", $name, Record::getName($type), $attempts, \implode(", ", $attemptDescription)));
            if (!$exceptions) {
                throw $timeout;
            }
            throw new MultiReasonException($exceptions, $timeout->getMessage());
        });
        $this->pendingQueries[$type . " " . $name] = $promise;
        $promise->onResolve(function () use($name, $type) {
            unset($this->pendingQueries[$type . " " . $name]);
        });
        return $promise;
    }
    /**
     *
     */
    private function normalizeName(string $name, int $type)
    {
        if ($type === Record::PTR) {
            if (($packedIp = @\inet_pton($name)) !== false) {
                if (isset($packedIp[4])) {
                    // IPv6
                    $name = \wordwrap(\strrev(\bin2hex($packedIp)), 1, ".", true) . ".ip6.arpa";
                } else {
                    // IPv4
                    $name = \inet_ntop(\strrev($packedIp)) . ".in-addr.arpa";
                }
            }
        } elseif (\in_array($type, [Record::A, Record::AAAA])) {
            $name = normalizeName($name);
        }
        return $name;
    }
    /**
     * @param string $name
     * @param int $type
     *
     * @return \LibDNS\Records\Question
     */
    private function createQuestion(string $name, int $type) : Question
    {
        if (0 > $type || 0xffff < $type) {
            $message = \sprintf('%d does not correspond to a valid record type (must be between 0 and 65535).', $type);
            throw new \Error($message);
        }
        $question = $this->questionFactory->create($type);
        $question->setName($name);
        return $question;
    }
    /**
     *
     */
    private function getCacheKey(string $name, int $type) : string
    {
        return self::CACHE_PREFIX . $name . "#" . $type;
    }
    /**
     *
     */
    private function decodeCachedResult(string $name, int $type, string $encoded)
    {
        $decoded = \json_decode($encoded, true);
        if (!$decoded) {
            throw new NoRecordException("No records returned for {$name} (cached result)");
        }
        $result = [];
        foreach ($decoded as $data) {
            $result[] = new Record($data, $type);
        }
        return $result;
    }
    /**
     *
     */
    private function getSocket(Nameserver $nameserver)
    {
        $uri = $nameserver->getUri();
        if (isset($this->sockets[$uri])) {
            return $this->sockets[$uri];
        }
        $this->sockets[$uri] = HttpsSocket::connect($this->dohConfig->getHttpClient(), $nameserver);
        return $this->sockets[$uri];
    }
    /**
     *
     */
    private function assertAcceptableResponse(Message $response)
    {
        if ($response->getResponseCode() !== 0) {
            throw new DnsException(\sprintf("Server returned error code: %d", $response->getResponseCode()));
        }
    }
}<?php

namespace Amp\DoH;

use Amp\Dns\ConfigException;
final class Nameserver
{
    const RFC8484_GET = 0;
    const RFC8484_POST = 1;
    const GOOGLE_JSON = 2;
    private $type;
    private $uri;
    private $host;
    private $headers = [];
    /**
     *
     */
    public function __construct(string $uri, int $type = self::RFC8484_POST, array $headers = [])
    {
        if (\parse_url($uri, PHP_URL_SCHEME) !== 'https') {
            throw new ConfigException('Did not provide a valid HTTPS url!');
        }
        if (!\in_array($type, [self::RFC8484_GET, self::RFC8484_POST, self::GOOGLE_JSON])) {
            throw new ConfigException('Invalid nameserver type provided!');
        }
        $this->uri = $uri;
        $this->type = $type;
        $this->headers = $headers;
        $this->host = \parse_url($uri, PHP_URL_HOST);
    }
    /**
     *
     */
    public function getUri() : string
    {
        return $this->uri;
    }
    /**
     *
     */
    public function getHost() : string
    {
        return $this->host;
    }
    /**
     *
     */
    public function getHeaders() : array
    {
        return $this->headers;
    }
    /**
     *
     */
    public function getType() : int
    {
        return $this->type;
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->uri;
        /*
                switch ($this->type) {
                    case self::RFC8484_GET:
                        return "{$this->uri} RFC 8484 GET";
                    case self::RFC8484_POST:
                        return "{$this->uri} RFC 8484 POST";
                    case self::GOOGLE_JSON:
                        return "{$this->uri} google JSON";
                }*/
    }
}<?php

$config = new Amp\CodeStyle\Config();
$config->getFinder()->in(__DIR__ . '/src')->in(__DIR__ . '/tests');
$cacheDir = getenv('TRAVIS') ? getenv('HOME') . '/.php-cs-fixer' : __DIR__;
$config->setCacheFile($cacheDir . '/.php_cs.cache');
return $config;<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
use const danog\Decoder\TYPES;
/**
 * Represents source of photosize.
 */
class PhotoSizeSourceThumbnail extends PhotoSizeSource
{
    /**
     * File type of original file.
     *
     * @var int
     */
    private $_thumbFileType;
    /**
     * Thumbnail size.
     *
     * @var string
     */
    private $_thumbType;
    /**
     * Get file type of original file.
     *
     * @return int
     */
    public function getThumbFileType() : int
    {
        return $this->_thumbFileType;
    }
    /**
     * Get file type of original file as string.
     *
     * @return string
     */
    public function getThumbFileTypeString() : string
    {
        return TYPES[$this->_thumbFileType];
    }
    /**
     * Set file type of original file.
     *
     * @param int $_thumbFileType File type of original file
     *
     * @return self
     */
    public function setThumbFileType(int $_thumbFileType) : self
    {
        $this->_thumbFileType = $_thumbFileType;
        return $this;
    }
    /**
     * Get thumbnail size.
     *
     * @return string
     */
    public function getThumbType() : string
    {
        return $this->_thumbType;
    }
    /**
     * Set thumbnail size.
     *
     * @param string $_thumbType Thumbnail size
     *
     * @return self
     */
    public function setThumbType(string $_thumbType) : self
    {
        $this->_thumbType = $_thumbType;
        return $this;
    }
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
/**
 * Represents source of photosize.
 *
 * @extends PhotoSizeSource<PhotoSizeSourceStickersetThumbnailVersion>
 */
class PhotoSizeSourceStickersetThumbnailVersion extends PhotoSizeSource
{
    /**
     * Stickerset ID.
     *
     * @var int
     */
    private $_stickerSetId;
    /**
     * Stickerset access hash.
     *
     * @var int
     */
    private $_stickerSetAccessHash;
    /**
     * Stickerset version.
     *
     * @var int
     */
    private $_stickerSetVersion;
    /**
     * Get stickerset ID.
     *
     * @return int
     */
    public function getStickerSetId()
    {
        return $this->_stickerSetId;
    }
    /**
     * Set stickerset ID.
     *
     * @param int $_stickerSetId Stickerset ID
     *
     * @return self
     */
    public function setStickerSetId($_stickerSetId) : self
    {
        $this->_stickerSetId = $_stickerSetId;
        return $this;
    }
    /**
     * Get stickerset access hash.
     *
     * @return int
     */
    public function getStickerSetAccessHash()
    {
        return $this->_stickerSetAccessHash;
    }
    /**
     * Set stickerset access hash.
     *
     * @param int $_stickerSetAccessHash Stickerset access hash
     *
     * @return self
     */
    public function setStickerSetAccessHash($_stickerSetAccessHash) : self
    {
        $this->_stickerSetAccessHash = $_stickerSetAccessHash;
        return $this;
    }
    /**
     * Get stickerset version.
     *
     * @return int
     */
    public function getStickerSetVersion() : int
    {
        return $this->_stickerSetVersion;
    }
    /**
     * Set stickerset version.
     *
     * @param int $_stickerSetVersion Stickerset version.
     *
     * @return self
     */
    public function setStickerSetVersion(int $_stickerSetVersion) : self
    {
        $this->_stickerSetVersion = $_stickerSetVersion;
        return $this;
    }
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
use const danog\Decoder\PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL;
use const danog\Decoder\PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY;
/**
 * Represents source of photosize.
 *
 * @extends PhotoSizeSource<PhotoSizeSourceDialogPhoto>
 */
class PhotoSizeSourceDialogPhoto extends PhotoSizeSource
{
    /**
     * ID of dialog.
     *
     * @var int
     */
    private $_dialogId;
    /**
     * Access hash of dialog.
     *
     * @var int
     */
    private $_dialogAccessHash;
    /**
     * Get dialog ID.
     *
     * @return int
     */
    public function getDialogId()
    {
        return $this->_dialogId;
    }
    /**
     * Set dialog ID.
     *
     * @param int $id Dialog ID
     *
     * @return self
     */
    public function setDialogId($id) : self
    {
        $this->_dialogId = $id;
        return $this;
    }
    /**
     * Get access hash of dialog.
     *
     * @return int
     */
    public function getDialogAccessHash()
    {
        return $this->_dialogAccessHash;
    }
    /**
     * Set access hash of dialog.
     *
     * @param int $dialogAccessHash Access hash of dialog
     *
     * @return self
     */
    public function setDialogAccessHash($dialogAccessHash) : self
    {
        $this->_dialogAccessHash = $dialogAccessHash;
        return $this;
    }
    /**
     * Get whether the big or small version of the photo is being used.
     *
     * @return bool
     */
    public function isSmallDialogPhoto() : bool
    {
        return \in_array($this->getType(), [PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY, PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL]);
    }
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
/**
 * Represents source of photosize.
 *
 * @extends PhotoSizeSource<PhotoSizeSourceLegacy>
 */
class PhotoSizeSourceLegacy extends PhotoSizeSource
{
    /**
     * Secret legacy ID.
     *
     * @var int
     */
    private $_secret;
    /**
     * Get secret legacy ID.
     *
     * @return int
     */
    public function getSecret()
    {
        return $this->_secret;
    }
    /**
     * Set secret legacy ID.
     *
     * @param int $_secret Secret legacy ID
     *
     * @return self
     */
    public function setSecret($_secret) : self
    {
        $this->_secret = $_secret;
        return $this;
    }
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder\PhotoSizeSource;

use danog\Decoder\PhotoSizeSource;
/**
 * Represents source of photosize.
 *
 * @extends PhotoSizeSource<PhotoSizeSourceStickersetThumbnail>
 */
class PhotoSizeSourceStickersetThumbnail extends PhotoSizeSource
{
    /**
     * Stickerset ID.
     *
     * @var int
     */
    private $_stickerSetId;
    /**
     * Stickerset access hash.
     *
     * @var int
     */
    private $_stickerSetAccessHash;
    /**
     * Get stickerset ID.
     *
     * @return int
     */
    public function getStickerSetId()
    {
        return $this->_stickerSetId;
    }
    /**
     * Set stickerset ID.
     *
     * @param int $_stickerSetId Stickerset ID
     *
     * @return self
     */
    public function setStickerSetId($_stickerSetId) : self
    {
        $this->_stickerSetId = $_stickerSetId;
        return $this;
    }
    /**
     * Get stickerset access hash.
     *
     * @return int
     */
    public function getStickerSetAccessHash()
    {
        return $this->_stickerSetAccessHash;
    }
    /**
     * Set stickerset access hash.
     *
     * @param int $_stickerSetAccessHash Stickerset access hash
     *
     * @return self
     */
    public function setStickerSetAccessHash($_stickerSetAccessHash) : self
    {
        $this->_stickerSetAccessHash = $_stickerSetAccessHash;
        return $this;
    }
}<?php

/**
 * Decoded FileId class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder;

use danog\Decoder\PhotoSizeSource\PhotoSizeSourceDialogPhoto;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceLegacy;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceStickersetThumbnail;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceStickersetThumbnailVersion;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceThumbnail;
/**
 * Represents decoded bot API file ID.
 */
class FileId
{
    /**
     * Bot API file ID version.
     *
     * @var int
     */
    private $_version = 4;
    /**
     * Bot API file ID subversion.
     *
     * @var int
     */
    private $_subVersion = 32;
    /**
     * DC ID.
     *
     * @var int
     */
    private $_dcId = 0;
    /**
     * File type.
     *
     * @var int
     */
    private $_type = 0;
    /**
     * File reference.
     *
     * @var string
     */
    private $_fileReference = '';
    /**
     * File URL for weblocation.
     *
     * @var string
     */
    private $_url = '';
    /**
     * File id.
     *
     * @var int
     */
    private $_id;
    /**
     * File access hash.
     *
     * @var int
     */
    private $_accessHash;
    /**
     * Photo volume ID.
     *
     * @var int
     */
    private $_volumeId;
    /**
     * Photo local ID.
     *
     * @var int
     */
    private $_localId;
    /**
     * Photo size source.
     *
     * @var PhotoSizeSource
     */
    private $_photoSizeSource;
    /**
     * Basic constructor function.
     */
    public function __construct()
    {
    }
    /**
     * Decode file ID from bot API file ID.
     *
     * @param string $fileId File ID
     *
     * @return self
     */
    public static function fromBotAPI(string $fileId) : self
    {
        $result = new self();
        $resultArray = internalDecode($fileId);
        $result->setVersion($resultArray['version']);
        $result->setSubVersion($resultArray['subVersion']);
        $result->setType($resultArray['typeId']);
        $result->setDcId($resultArray['dc_id']);
        $result->setAccessHash($resultArray['access_hash']);
        if ($resultArray['hasReference']) {
            $result->setFileReference($resultArray['fileReference']);
        }
        if ($resultArray['hasWebLocation']) {
            $result->setUrl($resultArray['webLocation']);
            return $result;
        }
        $result->setId($resultArray['id']);
        if ($result->getType() <= PHOTO) {
            if (isset($resultArray['volume_id'])) {
                $result->setVolumeId($resultArray['volume_id']);
            }
            if (isset($resultArray['local_id'])) {
                $result->setLocalId($resultArray['local_id']);
            }
            switch ($resultArray['photosize_source']) {
                case PHOTOSIZE_SOURCE_LEGACY:
                case PHOTOSIZE_SOURCE_FULL_LEGACY:
                    $photoSizeSource = new PhotoSizeSourceLegacy($resultArray['photosize_source']);
                    $photoSizeSource->setSecret($resultArray['secret']);
                    break;
                case PHOTOSIZE_SOURCE_THUMBNAIL:
                    $photoSizeSource = new PhotoSizeSourceThumbnail($resultArray['photosize_source']);
                    $photoSizeSource->setThumbType($resultArray['thumbnail_type']);
                    $photoSizeSource->setThumbFileType($resultArray['file_type']);
                    break;
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG_LEGACY:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL:
                    $photoSizeSource = new PhotoSizeSourceDialogPhoto($resultArray['photosize_source']);
                    $photoSizeSource->setDialogId($resultArray['dialog_id']);
                    $photoSizeSource->setDialogAccessHash($resultArray['dialog_access_hash']);
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL:
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY:
                    $photoSizeSource = new PhotoSizeSourceStickersetThumbnail($resultArray['photosize_source']);
                    $photoSizeSource->setStickerSetId($resultArray['sticker_set_id']);
                    $photoSizeSource->setStickerSetAccessHash($resultArray['sticker_set_access_hash']);
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_VERSION:
                    $photoSizeSource = new PhotoSizeSourceStickersetThumbnailVersion($resultArray['photosize_source']);
                    $photoSizeSource->setStickerSetId($resultArray['sticker_set_id']);
                    $photoSizeSource->setStickerSetAccessHash($resultArray['sticker_set_access_hash']);
                    $photoSizeSource->setStickerSetVersion($resultArray['sticker_version']);
                    break;
            }
            $result->setPhotoSizeSource($photoSizeSource);
        }
        return $result;
    }
    /**
     * Get bot API file ID.
     *
     * @return string
     */
    public function getBotAPI() : string
    {
        $type = $this->getType();
        if ($this->hasFileReference()) {
            $type |= FILE_REFERENCE_FLAG;
        }
        if ($this->hasUrl()) {
            $type |= WEB_LOCATION_FLAG;
        }
        $fileId = \pack('VV', $type, $this->getDcId());
        if ($this->hasFileReference()) {
            $fileId .= packTLString($this->getFileReference());
        }
        if ($this->hasUrl()) {
            $fileId .= packTLString($this->getUrl());
            $fileId .= packLong($this->getAccessHash());
            return base64urlEncode(rleEncode($fileId));
        }
        $fileId .= packLong($this->getId());
        $fileId .= packLong($this->getAccessHash());
        if ($this->getType() <= PHOTO) {
            $photoSize = $this->getPhotoSizeSource();
            $fileId .= \pack('V', $photoSize->getType());
            switch ($photoSize->getType()) {
                case PHOTOSIZE_SOURCE_LEGACY:
                    $fileId .= packLong($photoSize->getSecret());
                    break;
                case PHOTOSIZE_SOURCE_FULL_LEGACY:
                    $fileId .= packLong($this->getVolumeId());
                    $fileId .= packLong($photoSize->getSecret());
                    $fileId .= \pack('l', $this->getLocalId());
                    break;
                case PHOTOSIZE_SOURCE_THUMBNAIL:
                    $fileId .= \pack('Va4', $photoSize->getThumbFileType(), $photoSize->getThumbType());
                    break;
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG_LEGACY:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY:
                    $fileId .= packLongBig($photoSize->getDialogId());
                    $fileId .= packLong($photoSize->getDialogAccessHash());
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL:
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY:
                    $fileId .= packLong($photoSize->getStickerSetId());
                    $fileId .= packLong($photoSize->getStickerSetAccessHash());
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_VERSION:
                    $fileId .= packLong($photoSize->getStickerSetId());
                    $fileId .= packLong($photoSize->getStickerSetAccessHash());
                    $fileId .= \pack('l', $photoSize->getStickerSetVersion());
                    break;
            }
            if ($photoSize->getType() >= PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY && $photoSize->getType() <= PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY) {
                $fileId .= packLong($this->getVolumeId());
                $fileId .= \pack('l', $this->getLocalId());
            }
        }
        if ($this->getVersion() >= 4) {
            $fileId .= \chr($this->getSubVersion());
        }
        $fileId .= \chr($this->getVersion());
        return base64urlEncode(rleEncode($fileId));
    }
    /**
     * Get unique file ID from file ID.
     *
     * @return UniqueFileId
     */
    public function getUnique() : UniqueFileId
    {
        return UniqueFileId::fromFileId($this);
    }
    /**
     * Get unique bot API file ID from file ID.
     *
     * @return string
     */
    public function getUniqueBotAPI() : string
    {
        return UniqueFileId::fromFileId($this)->getUniqueBotAPI();
    }
    /**
     * Get bot API file ID.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->getBotAPI();
    }
    /**
     * Get bot API file ID version.
     *
     * @return int
     */
    public function getVersion() : int
    {
        return $this->_version;
    }
    /**
     * Set bot API file ID version.
     *
     * @param int $_version Bot API file ID version.
     *
     * @return self
     */
    public function setVersion(int $_version) : self
    {
        $this->_version = $_version;
        return $this;
    }
    /**
     * Get bot API file ID subversion.
     *
     * @return int
     */
    public function getSubVersion() : int
    {
        return $this->_subVersion;
    }
    /**
     * Set bot API file ID subversion.
     *
     * @param int $_subVersion Bot API file ID subversion.
     *
     * @return self
     */
    public function setSubVersion(int $_subVersion) : self
    {
        $this->_subVersion = $_subVersion;
        return $this;
    }
    /**
     * Get file type.
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->_type;
    }
    /**
     * Get file type as string.
     *
     * @return string
     */
    public function getTypeName() : string
    {
        return TYPES[$this->_type];
    }
    /**
     * Set file type.
     *
     * @param int $_type File type.
     *
     * @return self
     */
    public function setType(int $_type) : self
    {
        $this->_type = $_type;
        return $this;
    }
    /**
     * Get file reference.
     *
     * @return string
     */
    public function getFileReference() : string
    {
        return $this->_fileReference;
    }
    /**
     * Set file reference.
     *
     * @param string $_fileReference File reference.
     *
     * @return self
     */
    public function setFileReference(string $_fileReference) : self
    {
        $this->_fileReference = $_fileReference;
        return $this;
    }
    /**
     * Check if has file reference.
     *
     * @return boolean
     */
    public function hasFileReference() : bool
    {
        return !empty($this->_fileReference);
    }
    /**
     * Get file URL for weblocation.
     *
     * @return string
     */
    public function getUrl() : string
    {
        return $this->_url;
    }
    /**
     * Check if has file URL.
     *
     * @return boolean
     */
    public function hasUrl() : bool
    {
        return !empty($this->_url);
    }
    /**
     * Set file URL for weblocation.
     *
     * @param string $_url File URL for weblocation.
     *
     * @return self
     */
    public function setUrl(string $_url) : self
    {
        $this->_url = $_url;
        return $this;
    }
    /**
     * Get file id.
     *
     * @return int
     */
    public function getId()
    {
        return $this->_id;
    }
    /**
     * Set file id.
     *
     * @param int $_id File id.
     *
     * @return self
     */
    public function setId($_id) : self
    {
        $this->_id = $_id;
        return $this;
    }
    /**
     * Check if has file id.
     *
     * @return bool
     */
    public function hasId() : bool
    {
        return isset($this->_id);
    }
    /**
     * Get file access hash.
     *
     * @return int
     */
    public function getAccessHash()
    {
        return $this->_accessHash;
    }
    /**
     * Set file access hash.
     *
     * @param int $_accessHash File access hash.
     *
     * @return self
     */
    public function setAccessHash($_accessHash) : self
    {
        $this->_accessHash = $_accessHash;
        return $this;
    }
    /**
     * Get photo volume ID.
     *
     * @return int
     */
    public function getVolumeId()
    {
        return $this->_volumeId;
    }
    /**
     * Set photo volume ID.
     *
     * @param int $_volumeId Photo volume ID.
     *
     * @return self
     */
    public function setVolumeId($_volumeId) : self
    {
        $this->_volumeId = $_volumeId;
        return $this;
    }
    /**
     * Check if has volume ID.
     *
     * @return boolean
     */
    public function hasVolumeId() : bool
    {
        return isset($this->_volumeId);
    }
    /**
     * Get photo local ID.
     *
     * @return int
     */
    public function getLocalId() : int
    {
        return $this->_localId;
    }
    /**
     * Set photo local ID.
     *
     * @param int $_localId Photo local ID.
     *
     * @return self
     */
    public function setLocalId(int $_localId) : self
    {
        $this->_localId = $_localId;
        return $this;
    }
    /**
     * Check if has local ID.
     *
     * @return boolean
     */
    public function hasLocalId() : bool
    {
        return isset($this->_localId);
    }
    /**
     * Get photo size source.
     *
     * @return PhotoSizeSource
     */
    public function getPhotoSizeSource() : PhotoSizeSource
    {
        return $this->_photoSizeSource;
    }
    /**
     * Set photo size source.
     *
     * @param PhotoSizeSource $_photoSizeSource Photo size source.
     *
     * @return self
     */
    public function setPhotoSizeSource(PhotoSizeSource $_photoSizeSource) : self
    {
        $this->_photoSizeSource = $_photoSizeSource;
        return $this;
    }
    /**
     * Check if has photo size source.
     *
     * @return boolean
     */
    public function hasPhotoSizeSource() : bool
    {
        return isset($this->_photoSizeSource);
    }
    /**
     * Get dC ID.
     *
     * @return int
     */
    public function getDcId() : int
    {
        return $this->_dcId;
    }
    /**
     * Set dC ID.
     *
     * @param int $_dcId DC ID.
     *
     * @return self
     */
    public function setDcId(int $_dcId) : self
    {
        $this->_dcId = $_dcId;
        return $this;
    }
}<?php

/**
 * Type enum + helper functions.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder;

/**
 * Thumbnail.
 */
const THUMBNAIL = 0;
/**
 * Profile photo.
 * Used for users and channels, chat photos are normal PHOTOs.
 */
const PROFILE_PHOTO = 1;
/**
 * Normal photos.
 */
const PHOTO = 2;
/**
 * Voice messages.
 */
const VOICE = 3;
/**
 * Video.
 */
const VIDEO = 4;
/**
 * Document.
 */
const DOCUMENT = 5;
/**
 * Secret chat document.
 */
const ENCRYPTED = 6;
/**
 * Temporary document.
 */
const TEMP = 7;
/**
 * Sticker.
 */
const STICKER = 8;
/**
 * Music.
 */
const AUDIO = 9;
/**
 * GIF.
 */
const ANIMATION = 10;
/**
 * Encrypted thumbnail.
 */
const ENCRYPTED_THUMBNAIL = 11;
/**
 * Wallpaper.
 */
const WALLPAPER = 12;
/**
 * Round video.
 */
const VIDEO_NOTE = 13;
/**
 * Passport raw file.
 */
const SECURE_RAW = 14;
/**
 * Passport file.
 */
const SECURE = 15;
/**
 * Background.
 */
const BACKGROUND = 16;
/**
 * Size.
 */
const SIZE = 17;
const NONE = 18;
const TYPES = [THUMBNAIL => 'thumbnail', PROFILE_PHOTO => 'profile_photo', PHOTO => 'photo', VOICE => 'voice', VIDEO => 'video', DOCUMENT => 'document', ENCRYPTED => 'encrypted', TEMP => 'temp', STICKER => 'sticker', AUDIO => 'audio', ANIMATION => 'animation', ENCRYPTED_THUMBNAIL => 'encrypted_thumbnail', WALLPAPER => 'wallpaper', VIDEO_NOTE => 'video_note', SECURE_RAW => 'secure_raw', SECURE => 'secure', BACKGROUND => 'background', SIZE => 'size'];
const TYPES_IDS = ['thumbnail' => THUMBNAIL, 'profile_photo' => PROFILE_PHOTO, 'photo' => PHOTO, 'voice' => VOICE, 'video' => VIDEO, 'document' => DOCUMENT, 'encrypted' => ENCRYPTED, 'temp' => TEMP, 'sticker' => STICKER, 'audio' => AUDIO, 'animation' => ANIMATION, 'encrypted_thumbnail' => ENCRYPTED_THUMBNAIL, 'wallpaper' => WALLPAPER, 'video_note' => VIDEO_NOTE, 'secure_raw' => SECURE_RAW, 'secure' => SECURE, 'background' => BACKGROUND, 'size' => SIZE];
const UNIQUE_WEB = 0;
const UNIQUE_PHOTO = 1;
const UNIQUE_DOCUMENT = 2;
const UNIQUE_SECURE = 3;
const UNIQUE_ENCRYPTED = 4;
const UNIQUE_TEMP = 5;
const UNIQUE_TYPES = [UNIQUE_WEB => 'web', UNIQUE_PHOTO => 'photo', UNIQUE_DOCUMENT => 'document', UNIQUE_SECURE => 'secure', UNIQUE_ENCRYPTED => 'encrypted', UNIQUE_TEMP => 'temp'];
const UNIQUE_TYPES_IDS = ['web' => UNIQUE_WEB, 'photo' => UNIQUE_PHOTO, 'document' => UNIQUE_DOCUMENT, 'secure' => UNIQUE_SECURE, 'encrypted' => UNIQUE_ENCRYPTED, 'temp' => UNIQUE_TEMP];
const FULL_UNIQUE_MAP = [PHOTO => UNIQUE_PHOTO, PROFILE_PHOTO => UNIQUE_PHOTO, THUMBNAIL => UNIQUE_PHOTO, ENCRYPTED_THUMBNAIL => UNIQUE_PHOTO, WALLPAPER => UNIQUE_PHOTO, VIDEO => UNIQUE_DOCUMENT, VOICE => UNIQUE_DOCUMENT, DOCUMENT => UNIQUE_DOCUMENT, STICKER => UNIQUE_DOCUMENT, AUDIO => UNIQUE_DOCUMENT, ANIMATION => UNIQUE_DOCUMENT, VIDEO_NOTE => UNIQUE_DOCUMENT, BACKGROUND => UNIQUE_DOCUMENT, SECURE => UNIQUE_SECURE, SECURE_RAW => UNIQUE_SECURE, ENCRYPTED => UNIQUE_ENCRYPTED, TEMP => UNIQUE_TEMP];
const PHOTOSIZE_SOURCE_LEGACY = 0;
const PHOTOSIZE_SOURCE_THUMBNAIL = 1;
const PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL = 2;
const PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG = 3;
const PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL = 4;
const PHOTOSIZE_SOURCE_FULL_LEGACY = 5;
const PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY = 6;
const PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG_LEGACY = 7;
const PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY = 8;
const PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_VERSION = 9;
const WEB_LOCATION_FLAG = 1 << 24;
const FILE_REFERENCE_FLAG = 1 << 25;
const LONG = PHP_INT_SIZE === 8 ? 'Q' : 'l2';
$BIG_ENDIAN = \pack('L', 1) === \pack('N', 1);
/**
 * Unpack long properly, returns an actual number in any case.
 *
 * @param string $field Field to unpack
 *
 * @return (string | int)
 */
function unpackLong(string $field)
{
    if (PHP_INT_SIZE === 8) {
        /** @psalm-suppress InvalidGlobal */
        global $BIG_ENDIAN;
        // Evil
        return \unpack('q', $BIG_ENDIAN ? \strrev($field) : $field)[1];
    }
    if (\class_exists(\tgseclib\Math\BigInteger::class)) {
        return (string) new \tgseclib\Math\BigInteger(\strrev($field), -256);
    }
    if (\class_exists(\phpseclib\Math\BigInteger::class)) {
        return (string) new \phpseclib\Math\BigInteger(\strrev($field), -256);
    }
    throw new \Error('Please install phpseclib to unpack bot API file IDs');
}
/**
 * Pack string long.
 *
 * @param (string | int) $field
 *
 * @return string
 */
function packLongBig($field) : string
{
    if (PHP_INT_SIZE === 8) {
        /** @psalm-suppress InvalidGlobal */
        global $BIG_ENDIAN;
        // Evil
        $res = \pack('q', $field);
        return $BIG_ENDIAN ? \strrev($res) : $res;
    }
    if (\class_exists(\tgseclib\Math\BigInteger::class)) {
        return (new \tgseclib\Math\BigInteger($field))->toBytes();
    }
    if (\class_exists(\phpseclib\Math\BigInteger::class)) {
        return (new \phpseclib\Math\BigInteger($field))->toBytes();
    }
    throw new \Error('Please install phpseclib to unpack bot API file IDs');
}
/**
 * Fix long parameters in case of 32 bit systems.
 *
 * @param array $params Parameters
 * @param string $field 64-bit field
 *
 * @return void
 */
function fixLong(array &$params, string $field)
{
    if (PHP_INT_SIZE === 8) {
        return;
    }
    $params[$field] = [$params[$field . '1'], $params[$field . '2']];
    unset($params[$field . '1'], $params[$field . '2']);
}
/**
 * Encode long to string.
 *
 * @param (string | int | int[]) $fields Fields to encode
 *
 * @return string
 */
function packLong($fields) : string
{
    if (\is_string($fields)) {
        // Already encoded, we hope
        return $fields;
    }
    if (PHP_INT_SIZE === 8) {
        return \pack(LONG, $fields);
    }
    return \pack(LONG, ...$fields);
}
/**
 * Base64URL decode.
 *
 * @param string $data Data to decode
 *
 * @internal
 *
 * @return string
 */
function base64urlDecode(string $data) : string
{
    return \base64_decode(\str_pad(\strtr($data, '-_', '+/'), \strlen($data) % 4, '=', STR_PAD_RIGHT));
}
/**
 * Base64URL encode.
 *
 * @param string $data Data to encode
 *
 * @internal
 *
 * @return string
 */
function base64urlEncode(string $data) : string
{
    return \rtrim(\strtr(\base64_encode($data), '+/', '-_'), '=');
}
/**
 * Null-byte RLE decode.
 *
 * @param string $string Data to decode
 *
 * @internal
 *
 * @return string
 */
function rleDecode(string $string) : string
{
    $new = '';
    $last = '';
    $null = "\x00";
    foreach (\str_split($string) as $cur) {
        if ($last === $null) {
            $new .= \str_repeat($last, \ord($cur));
            $last = '';
        } else {
            $new .= $last;
            $last = $cur;
        }
    }
    $string = $new . $last;
    return $string;
}
/**
 * Null-byte RLE encode.
 *
 * @param string $string Data to encode
 *
 * @internal
 *
 * @return string
 */
function rleEncode(string $string) : string
{
    $new = '';
    $count = 0;
    $null = "\x00";
    foreach (\str_split($string) as $cur) {
        if ($cur === $null) {
            ++$count;
        } else {
            if ($count > 0) {
                $new .= $null . \chr($count);
                $count = 0;
            }
            $new .= $cur;
        }
    }
    if ($count > 0) {
        $new .= $null . \chr($count);
        $count = 0;
    }
    return $new;
}
/**
* Positive modulo
Works just like the % (modulus) operator, only returns always a postive number.
*
* @param int $a A
* @param int $b B
*
* @internal
*
* @return int Modulo
*/
function posmod(int $a, int $b) : int
{
    $resto = $a % $b;
    return $resto < 0 ? $resto + \abs($b) : $resto;
}
/**
 * Read TL string.
 *
 * @param mixed $stream Byte stream
 *
 * @internal
 *
 * @return string
 */
function readTLString($stream) : string
{
    $l = \ord(\stream_get_contents($stream, 1));
    if ($l > 254) {
        throw new \InvalidArgumentException("Length too big!");
    }
    if ($l === 254) {
        $long_len = \unpack('V', \stream_get_contents($stream, 3) . \chr(0))[1];
        $x = \stream_get_contents($stream, $long_len);
        $resto = posmod(-$long_len, 4);
        if ($resto > 0) {
            \stream_get_contents($stream, $resto);
        }
    } else {
        $x = $l ? \stream_get_contents($stream, $l) : '';
        $resto = posmod(-($l + 1), 4);
        if ($resto > 0) {
            \stream_get_contents($stream, $resto);
        }
    }
    return $x;
}
/**
 * Pack TL string.
 *
 * @param string $string String
 *
 * @return string
 */
function packTLString(string $string) : string
{
    $l = \strlen($string);
    $concat = '';
    if ($l <= 253) {
        $concat .= \chr($l);
        $concat .= $string;
        $concat .= \pack('@' . posmod(-$l - 1, 4));
    } else {
        $concat .= \chr(254);
        $concat .= \Phabel\Target\Php80\Polyfill::substr(\pack('V', $l), 0, 3);
        $concat .= $string;
        $concat .= \pack('@' . posmod(-$l, 4));
    }
    return $concat;
}
/**
 * Internal decode function.
 *
 * I know that you will use this directly giuseppe
 *
 * @param string $fileId Bot API file ID
 *
 * @internal
 *
 * @return array
 */
function internalDecode(string $fileId) : array
{
    $orig = $fileId;
    $fileId = rleDecode(base64urlDecode($fileId));
    $result = [];
    $result['version'] = \ord($fileId[\strlen($fileId) - 1]);
    $result['subVersion'] = $result['version'] === 4 ? \ord($fileId[\strlen($fileId) - 2]) : 0;
    $result += \unpack('VtypeId/Vdc_id', $fileId);
    $result['hasReference'] = (bool) ($result['typeId'] & FILE_REFERENCE_FLAG);
    $result['hasWebLocation'] = (bool) ($result['typeId'] & WEB_LOCATION_FLAG);
    $result['typeId'] &= ~FILE_REFERENCE_FLAG;
    $result['typeId'] &= ~WEB_LOCATION_FLAG;
    if (!isset(TYPES[$result['typeId']])) {
        throw new \InvalidArgumentException("Invalid file type provided: {$result['typeId']}");
    }
    $result['type'] = TYPES[$result['typeId']];
    $res = \fopen('php://memory', 'rw+b');
    \fwrite($res, \Phabel\Target\Php80\Polyfill::substr($fileId, 8));
    \fseek($res, 0);
    $fileId = $res;
    if ($result['hasReference']) {
        $result['fileReference'] = readTLString($fileId);
    }
    if ($result['hasWebLocation']) {
        $result['url'] = readTLString($fileId);
        $result['access_hash'] = \unpack(LONG . 'access_hash', \stream_get_contents($fileId, 8));
        fixLong($result, 'access_hash');
        return $result;
    }
    $result += \unpack(LONG . 'id/' . LONG . 'access_hash', \stream_get_contents($fileId, 16));
    fixLong($result, 'id');
    fixLong($result, 'access_hash');
    if ($result['typeId'] <= PHOTO) {
        $parsePhotoSize = function () use(&$result, &$fileId) {
            $result['photosize_source'] = $result['subVersion'] >= 4 ? \unpack('V', \stream_get_contents($fileId, 4))[1] : 0;
            switch ($result['photosize_source']) {
                case PHOTOSIZE_SOURCE_LEGACY:
                    $result += \unpack(LONG . 'secret', \stream_get_contents($fileId, 8));
                    fixLong($result, 'secret');
                    break;
                case PHOTOSIZE_SOURCE_THUMBNAIL:
                    $result += \unpack('Vfile_type/athumbnail_type', \stream_get_contents($fileId, 8));
                    break;
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL:
                    $result['photo_size'] = $result['photosize_source'] === PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL ? 'photo_small' : 'photo_big';
                    $result['dialog_id'] = unpackLong(\stream_get_contents($fileId, 8));
                    $result['dialog_access_hash'] = \unpack(LONG, \stream_get_contents($fileId, 8))[1];
                    fixLong($result, 'dialog_access_hash');
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL:
                    $result += \unpack(LONG . 'sticker_set_id/' . LONG . 'sticker_set_access_hash', \stream_get_contents($fileId, 16));
                    fixLong($result, 'sticker_set_id');
                    fixLong($result, 'sticker_set_access_hash');
                    break;
                case PHOTOSIZE_SOURCE_FULL_LEGACY:
                    $result += \unpack(LONG . 'volume_id/' . LONG . 'secret/llocal_id', \stream_get_contents($fileId, 20));
                    fixLong($result, 'volume_id');
                    fixLong($result, 'secret');
                    break;
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_BIG_LEGACY:
                case PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY:
                    $result['photo_size'] = $result['photosize_source'] === PHOTOSIZE_SOURCE_DIALOGPHOTO_SMALL_LEGACY ? 'photo_small' : 'photo_big';
                    $result['dialog_id'] = unpackLong(\stream_get_contents($fileId, 8));
                    $result['dialog_access_hash'] = \unpack(LONG, \stream_get_contents($fileId, 8))[1];
                    fixLong($result, 'dialog_access_hash');
                    $result += \unpack(LONG . 'volume_id/llocal_id', \stream_get_contents($fileId, 12));
                    fixLong($result, 'volume_id');
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_LEGACY:
                    $result += \unpack(LONG . 'sticker_set_id/' . LONG . 'sticker_set_access_hash', \stream_get_contents($fileId, 16));
                    fixLong($result, 'sticker_set_id');
                    fixLong($result, 'sticker_set_access_hash');
                    $result += \unpack(LONG . 'volume_id/llocal_id', \stream_get_contents($fileId, 12));
                    fixLong($result, 'volume_id');
                    break;
                case PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL_VERSION:
                    $result += \unpack(LONG . 'sticker_set_id/' . LONG . 'sticker_set_access_hash/lsticker_version', \stream_get_contents($fileId, 20));
                    fixLong($result, 'sticker_set_id');
                    fixLong($result, 'sticker_set_access_hash');
                    break;
            }
        };
        if ($result['subVersion'] >= 32) {
            $parsePhotoSize();
        } else {
            $result += \unpack(LONG . 'volume_id', \stream_get_contents($fileId, 8));
            fixLong($result, 'volume_id');
            if ($result['subVersion'] >= 22) {
                $parsePhotoSize();
                $result += \unpack('llocal_id', \stream_get_contents($fileId, 4));
            } else {
                $result += \unpack(LONG . 'secret/llocal_id', \stream_get_contents($fileId, 12));
                fixLong($result, 'volume_id');
                fixLong($result, 'secret');
            }
        }
    }
    $l = \fstat($fileId)['size'] - \ftell($fileId);
    $l -= $result['version'] >= 4 ? 2 : 1;
    if ($l > 0) {
        \trigger_error("File ID {$orig} has {$l} bytes of leftover data");
    }
    return $result;
}
/**
 * Internal decode function.
 *
 * I know that you will use this directly giuseppe
 *
 * @param string $fileId Bot API file ID
 *
 * @internal
 *
 * @return array
 */
function internalDecodeUnique(string $fileId) : array
{
    $orig = $fileId;
    $fileId = rleDecode(base64urlDecode($fileId));
    $result = \unpack('VtypeId', $fileId);
    if (!isset(UNIQUE_TYPES[$result['typeId']])) {
        throw new \InvalidArgumentException("Invalid file type provided: {$result['typeId']}");
    }
    $result['type'] = UNIQUE_TYPES[$result['typeId']];
    $fileId = \Phabel\Target\Php80\Polyfill::substr($fileId, 4);
    if ($result['typeId'] === UNIQUE_WEB) {
        $res = \fopen('php://memory', 'rw+b');
        \fwrite($res, $fileId);
        \fseek($res, 0);
        $fileId = $res;
        $result['url'] = readTLString($fileId);
        $l = \fstat($fileId)['size'] - \ftell($fileId);
    } elseif (\strlen($fileId) === 12) {
        // Legacy photos
        $result += \unpack(LONG . 'volume_id/llocal_id', $fileId);
        fixLong($result, 'volume_id');
        $l = 0;
    } elseif (\strlen($fileId) === 9) {
        // Dialog photos/thumbnails
        $result += \unpack(LONG . 'id/CsubType', $fileId);
        fixLong($result, 'id');
        $l = 0;
    } elseif (\strlen($fileId) === 13) {
        // Stickerset ID/version
        $result += \unpack('CsubType/' . LONG . 'sticker_set_id/lsticker_set_version', $fileId);
        fixLong($result, 'sticker_set_id');
        $l = 0;
    } elseif (\strlen($fileId) === 8) {
        // Any other document
        $result += \unpack(LONG . 'id', $fileId);
        fixLong($result, 'id');
        $l = 0;
    } else {
        $l = \strlen($fileId);
    }
    if ($l > 0) {
        \trigger_error("Unique file ID {$orig} has {$l} bytes of leftover data");
    }
    return $result;
}<?php

/**
 * Photosize source class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder;

use danog\Decoder\PhotoSizeSource\PhotoSizeSourceLegacy;
/**
 * Represents source of photosize.
 *
 * @template T
 */
abstract class PhotoSizeSource
{
    /**
     * Source type.
     *
     * @var int
     */
    private $_type;
    /**
     * Set photosize source type.
     *
     * @param integer $type Type
     */
    public function __construct(int $type)
    {
        $this->_type = $type;
        return $this;
    }
    /**
    * Get photosize source type.
    *
    * @return integer
    *
    * @psalm-return (
    T is PhotoSizeSourceLegacy ?
    ? \danog\Decoder\PHOTOSIZE_SOURCE_LEGACY
    : (T is PhotoSizeSourceDialogPhoto
    ? \danog\Decoder\PHOTOSIZE_SOURCE_DIALOGPHOTO_*
    (T is PhotoSizeSourceStickersetThumbnail
    ? \danog\Decoder\PHOTOSIZE_SOURCE_STICKERSET_THUMBNAIL
    : \danog\Decoder\PHOTOSIZE_SOURCE_THUMBNAIL
    )
    )
    *
    * @internal Internal use
    */
    public function getType() : int
    {
        return $this->_type;
    }
}<?php

/**
 * Decoded UniqueFileId class.
 *
 * This file is part of tg-file-decoder.
 * tg-file-decoder is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 * tg-file-decoder is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU Affero General Public License for more details.
 * You should have received a copy of the GNU General Public License along with tg-file-decoder.
 * If not, see <http://www.gnu.org/licenses/>.
 *
 * @author    Daniil Gentili <daniil@daniil.it>
 * @copyright 2016-2019 Daniil Gentili <daniil@daniil.it>
 * @license   https://opensource.org/licenses/AGPL-3.0 AGPLv3
 *
 * @link https://github.com/tg-file-decoder Documentation
 */
namespace danog\Decoder;

use danog\Decoder\PhotoSizeSource\PhotoSizeSourceDialogPhoto;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceStickersetThumbnailVersion;
use danog\Decoder\PhotoSizeSource\PhotoSizeSourceThumbnail;
/**
 * Represents decoded unique bot API file ID.
 */
class UniqueFileId
{
    /**
     * File type.
     *
     * @var int
     */
    private $_type = NONE;
    /**
     * File ID.
     *
     * @var int
     */
    private $_id;
    /**
     * Photo volume ID.
     *
     * @var int
     */
    private $_volumeId;
    /**
     * Photo local ID.
     *
     * @var int
     */
    private $_localId;
    /**
     * Photo subtype.
     *
     * @var int
     */
    private $_subType;
    /**
     * Sticker set ID.
     *
     * @var int
     */
    private $_stickerSetId;
    /**
     * Sticker set version.
     *
     * @var int
     */
    private $_stickerSetVersion;
    /**
     * Weblocation URL.
     *
     * @var string
     */
    private $_url;
    /**
     * Basic constructor function.
     */
    public function __construct()
    {
    }
    /**
     * Get unique bot API file ID.
     *
     * @return string
     */
    public function __toString() : string
    {
        return $this->getUniqueBotAPI();
    }
    /**
     * Get unique bot API file ID.
     *
     * @return string
     */
    public function getUniqueBotAPI() : string
    {
        $fileId = \pack('V', $this->getType());
        if ($this->getType() === UNIQUE_WEB) {
            $fileId .= packTLString($this->getUrl());
        } elseif ($this->getType() === UNIQUE_PHOTO) {
            if ($this->hasVolumeId()) {
                $fileId .= packLong($this->getVolumeId());
                $fileId .= \pack('l', $this->getLocalId());
            } elseif ($this->hasStickerSetId()) {
                $fileId .= \chr($this->getSubType());
                $fileId .= packLong($this->getStickerSetId());
                $fileId .= \pack('l', $this->getStickerSetVersion());
            } else {
                $fileId .= packLong($this->getId());
                $fileId .= \chr($this->getSubType());
            }
        } elseif ($this->hasId()) {
            $fileId .= packLong($this->getId());
        }
        return base64urlEncode(rleEncode($fileId));
    }
    /**
     * Decode unique bot API file ID.
     *
     * @param string $fileId Bot API file ID
     *
     * @return self
     */
    public static function fromUniqueBotAPI(string $fileId) : self
    {
        $result = new self();
        $resultArray = internalDecodeUnique($fileId);
        $result->setType($resultArray['typeId']);
        if ($result->getType() === UNIQUE_WEB) {
            $result->setUrl($resultArray['url']);
        } elseif ($result->getType() === UNIQUE_PHOTO) {
            if (isset($resultArray['volume_id'])) {
                $result->setVolumeId($resultArray['volume_id']);
                $result->setLocalId($resultArray['local_id']);
            } elseif (isset($resultArray['id'])) {
                $result->setId($resultArray['id']);
                $result->setSubType($resultArray['subType']);
            } elseif (isset($resultArray['sticker_set_id'])) {
                $result->setStickerSetId($resultArray['sticker_set_id']);
                $result->setStickerSetVersion($resultArray['sticker_set_version']);
                $result->setSubType($resultArray['subType']);
            }
        } elseif (isset($resultArray['id'])) {
            $result->setId($resultArray['id']);
        }
        return $result;
    }
    /**
     * Convert full bot API file ID to unique file ID.
     *
     * @param string $fileId Full bot API file ID
     *
     * @return self
     */
    public static function fromBotAPI(string $fileId) : self
    {
        return FileId::fromBotAPI($fileId)->getUnique();
    }
    /**
     * Turn full file ID into unique file ID.
     *
     * @param FileId $fileId Full file ID
     *
     * @return self
     */
    public static function fromFileId(FileId $fileId) : self
    {
        $result = new self();
        $result->setType(FULL_UNIQUE_MAP[$fileId->getType()]);
        if ($result->hasUrl()) {
            $result->setType(UNIQUE_WEB);
        }
        if ($result->getType() === UNIQUE_WEB) {
            $result->setUrl($fileId->getUrl());
        } elseif ($result->getType() === UNIQUE_PHOTO) {
            if ($fileId->hasVolumeId()) {
                $result->setVolumeId($fileId->getVolumeId());
                $result->setLocalId($fileId->getLocalId());
            } elseif ($fileId->hasId()) {
                $result->setId($fileId->getId());
                $photoSize = $fileId->getPhotoSizeSource();
                if ($photoSize instanceof PhotoSizeSourceThumbnail) {
                    $type = $photoSize->getThumbType();
                    if ($type === 'a') {
                        $type = \chr(0);
                    } elseif ($type === 'c') {
                        $type = \chr(1);
                    } else {
                        $type = \chr(\ord($type) + 5);
                    }
                    $result->setSubType(\ord($type));
                } elseif ($photoSize instanceof PhotoSizeSourceDialogPhoto) {
                    $result->setSubType($photoSize->isSmallDialogPhoto() ? 0 : 1);
                } elseif ($photoSize instanceof PhotoSizeSourceStickersetThumbnailVersion) {
                    $result->setSubType(2);
                    $result->setStickerSetId($photoSize->getStickerSetId());
                    $result->setStickerSetVersion($photoSize->getStickerSetVersion());
                }
            }
        } elseif ($fileId->hasId()) {
            $result->setId($fileId->getId());
        }
        return $result;
    }
    /**
     * Get unique file type as string.
     *
     * @return string
     */
    public function getTypeName() : string
    {
        return UNIQUE_TYPES[$this->_type];
    }
    /**
     * Get unique file type.
     *
     * @return int
     */
    public function getType() : int
    {
        return $this->_type;
    }
    /**
     * Set file type.
     *
     * @param int $_type File type.
     *
     * @return self
     */
    public function setType(int $_type) : self
    {
        $this->_type = $_type;
        return $this;
    }
    /**
     * Get file ID.
     *
     * @return int
     */
    public function getId()
    {
        return $this->_id;
    }
    /**
     * Set file ID.
     *
     * @param int $_id File ID.
     *
     * @return self
     */
    public function setId($_id) : self
    {
        $this->_id = $_id;
        return $this;
    }
    /**
     * Check if has ID.
     *
     * @return boolean
     */
    public function hasId() : bool
    {
        return isset($this->_id);
    }
    /**
     * Get photo volume ID.
     *
     * @return int
     */
    public function getVolumeId()
    {
        return $this->_volumeId;
    }
    /**
     * Set photo volume ID.
     *
     * @param int $_volumeId Photo volume ID.
     *
     * @return self
     */
    public function setVolumeId($_volumeId) : self
    {
        $this->_volumeId = $_volumeId;
        return $this;
    }
    /**
     * Check if has volume ID.
     *
     * @return boolean
     */
    public function hasVolumeId() : bool
    {
        return isset($this->_volumeId);
    }
    /**
     * Get photo local ID.
     *
     * @return int
     */
    public function getLocalId() : int
    {
        return $this->_localId;
    }
    /**
     * Set photo local ID.
     *
     * @param int $_localId Photo local ID.
     *
     * @return self
     */
    public function setLocalId(int $_localId) : self
    {
        $this->_localId = $_localId;
        return $this;
    }
    /**
     * Check if has local ID.
     *
     * @return boolean
     */
    public function hasLocalId() : bool
    {
        return isset($this->_localId);
    }
    /**
     * Get weblocation URL.
     *
     * @return string
     */
    public function getUrl() : string
    {
        return $this->_url;
    }
    /**
     * Set weblocation URL.
     *
     * @param string $_url Weblocation URL
     *
     * @return self
     */
    public function setUrl(string $_url) : self
    {
        $this->_url = $_url;
        return $this;
    }
    /**
     * Check if has weblocation URL.
     *
     * @return boolean
     */
    public function hasUrl() : bool
    {
        return isset($this->_url);
    }
    /**
     * Get photo subtype.
     *
     * @return int
     */
    public function getSubType() : int
    {
        return $this->_subType;
    }
    /**
     * Has photo subtype?
     *
     * @return bool
     */
    public function hasSubType() : bool
    {
        return isset($this->_subType);
    }
    /**
     * Set photo subtype.
     *
     * @param int $_subType Photo subtype
     *
     * @return self
     */
    public function setSubType(int $_subType) : self
    {
        $this->_subType = $_subType;
        return $this;
    }
    /**
     * Get sticker set ID.
     *
     * @return int
     */
    public function getStickerSetId()
    {
        return $this->_stickerSetId;
    }
    /**
     * Has sticker set ID?
     *
     * @return bool
     */
    public function hasStickerSetId() : bool
    {
        return isset($this->_stickerSetId);
    }
    /**
     * Set sticker set ID.
     *
     * @param int $_stickerSetId Sticker set ID
     *
     * @return self
     */
    public function setStickerSetId($_stickerSetId) : self
    {
        $this->_stickerSetId = $_stickerSetId;
        return $this;
    }
    /**
     * Get sticker set version.
     *
     * @return int
     */
    public function getStickerSetVersion() : int
    {
        return $this->_stickerSetVersion;
    }
    /**
     * Has sticker set version.
     *
     * @return bool
     */
    public function hasStickerSetVersion() : bool
    {
        return isset($this->_stickerSetVersion);
    }
    /**
     * Set sticker set version.
     *
     * @param int $_stickerSetVersion Sticker set version
     *
     * @return self
     */
    public function setStickerSetVersion(int $_stickerSetVersion) : self
    {
        $this->_stickerSetVersion = $_stickerSetVersion;
        return $this;
    }
}{
    "name": "danog/tg-file-decoder",
    "description": "Decode Telegram bot API file IDs",
    "type": "project",
    "license": "AGPL-3.0-only",
    "keywords": ["telegram", "mtproto", "bot API", "file ID", "video", "stickers", "audio", "files"],
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "require": {
        "php": ">=7.0"
    },
    "require-dev": {
        "phpunit/phpunit": "^8|^6",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "danog\\Decoder\\": "src/"
        },
        "files": [
            "src/type.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "danog\\Decoder\\Test\\": "tests"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text  --configuration phpunit.xml.dist"
    }
}
{
    "name": "danog/libdns-json",
    "homepage": "https://github.com/danog/libdns-json",
    "description": "Encoder/decoder for google's JSON DNS message format based on libdns",
    "keywords": [
        "dns",
        "doh",
        "dns-over-https",
        "https",
        "json",
        "libdns",
        "message"
    ],
    "license": "MIT",
    "authors": [{
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        },
        {
            "name": "Chris Wright",
            "email": "addr@daverandom.com"
        }
    ],
    "require": {
        "php": ">=7.0",
        "daverandom/libdns": "^2.0.1",
        "ext-json": "*"
    },
    "require-dev": {
        "amphp/php-cs-fixer-config": "dev-master",
        "phpunit/phpunit": "^6"
    },
    "autoload": {
        "psr-4": {
            "danog\\LibDNSJson\\": "lib"
        }
    },
    "autoload-dev": {
        "psr-4": {
            "danog\\LibDNSJson\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}<?php

namespace danog\LibDNSJson;

use LibDNS\Decoder\DecodingContextFactory;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageFactory;
use LibDNS\Messages\MessageTypes;
use LibDNS\Packets\PacketFactory;
use LibDNS\Records\Question;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\Resource;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\Types\Anything;
use LibDNS\Records\Types\BitMap;
use LibDNS\Records\Types\Char;
use LibDNS\Records\Types\CharacterString;
use LibDNS\Records\Types\DomainName;
use LibDNS\Records\Types\IPv4Address;
use LibDNS\Records\Types\IPv6Address;
use LibDNS\Records\Types\Long;
use LibDNS\Records\Types\Short;
use LibDNS\Records\Types\Type;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\Types;
/**
 * Decodes JSON DNS strings to Message objects.
 *
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 */
class JsonDecoder
{
    /**
     * @var \LibDNS\Packets\PacketFactory
     */
    private $packetFactory;
    /**
     * @var \LibDNS\Messages\MessageFactory
     */
    private $messageFactory;
    /**
     * @var \LibDNS\Records\QuestionFactory
     */
    private $questionFactory;
    /**
     * @var \LibDNS\Records\ResourceBuilder
     */
    private $resourceBuilder;
    /**
     * @var \LibDNS\Records\Types\TypeBuilder
     */
    private $typeBuilder;
    /**
     * @var \LibDNS\Decoder\DecodingContextFactory
     */
    private $decodingContextFactory;
    /**
     * Constructor.
     *
     * @param \LibDNS\Packets\PacketFactory $packetFactory
     * @param \LibDNS\Messages\MessageFactory $messageFactory
     * @param \LibDNS\Records\QuestionFactory $questionFactory
     * @param \LibDNS\Records\ResourceBuilder $resourceBuilder
     * @param \LibDNS\Records\Types\TypeBuilder $typeBuilder
     * @param \LibDNS\Decoder\DecodingContextFactory $decodingContextFactory
     * @param bool $allowTrailingData
     */
    public function __construct(PacketFactory $packetFactory, MessageFactory $messageFactory, QuestionFactory $questionFactory, ResourceBuilder $resourceBuilder, TypeBuilder $typeBuilder, DecodingContextFactory $decodingContextFactory)
    {
        $this->packetFactory = $packetFactory;
        $this->messageFactory = $messageFactory;
        $this->questionFactory = $questionFactory;
        $this->resourceBuilder = $resourceBuilder;
        $this->typeBuilder = $typeBuilder;
        $this->decodingContextFactory = $decodingContextFactory;
    }
    /**
     * Decode a question record.
     *
     *
     * @return \LibDNS\Records\Question
     * @throws \UnexpectedValueException When the record is invalid
     */
    private function decodeQuestionRecord(array $record) : Question
    {
        /** @var \LibDNS\Records\Types\DomainName $domainName */
        $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
        $labels = \explode('.', $record['name']);
        if (!empty($last = \array_pop($labels))) {
            $labels[] = $last;
        }
        $domainName->setLabels($labels);
        $question = $this->questionFactory->create($record['type']);
        $question->setName($domainName);
        //$question->setClass($meta['class']);
        return $question;
    }
    /**
     * Decode a resource record.
     *
     *
     * @return \LibDNS\Records\Resource
     * @throws \UnexpectedValueException When the record is invalid
     * @throws \InvalidArgumentException When a type subtype is unknown
     */
    private function decodeResourceRecord(array $record) : Resource
    {
        /** @var \LibDNS\Records\Types\DomainName $domainName */
        $domainName = $this->typeBuilder->build(Types::DOMAIN_NAME);
        $labels = \explode('.', $record['name']);
        if (!empty($last = \array_pop($labels))) {
            $labels[] = $last;
        }
        $domainName->setLabels($labels);
        /* @var \LibDNS\Records\Resource $resource */
        $resource = $this->resourceBuilder->build($record['type']);
        $resource->setName($domainName);
        //$resource->setClass($meta['class']);
        $resource->setTTL($record['TTL']);
        $data = $resource->getData();
        $typeDef = $data->getTypeDefinition();
        $record['data'] = explode(' ', $record['data'], $typeDef->count());
        $fieldDef = $index = null;
        foreach ($data->getTypeDefinition() as $index => $fieldDef) {
            $field = $this->typeBuilder->build($fieldDef->getType());
            $this->decodeType($field, $record['data'][$index]);
            $data->setField($index, $field);
        }
        return $resource;
    }
    /**
     * Decode a Type field.
     *
     *
     * @param \LibDNS\Records\Types\Type $type The object to populate with the result
     * @throws \UnexpectedValueException When the packet data is invalid
     * @throws \InvalidArgumentException When the Type subtype is unknown
     */
    private function decodeType(Type $type, $data)
    {
        if ($type instanceof Anything) {
            $this->decodeAnything($type, $data);
        } elseif ($type instanceof BitMap) {
            $this->decodeBitMap($type, $data);
        } elseif ($type instanceof Char) {
            $this->decodeChar($type, $data);
        } elseif ($type instanceof CharacterString) {
            $this->decodeCharacterString($type, $data);
        } elseif ($type instanceof DomainName) {
            $this->decodeDomainName($type, $data);
        } elseif ($type instanceof IPv4Address) {
            $this->decodeIPv4Address($type, $data);
        } elseif ($type instanceof IPv6Address) {
            $this->decodeIPv6Address($type, $data);
        } elseif ($type instanceof Long) {
            $this->decodeLong($type, $data);
        } elseif ($type instanceof Short) {
            $this->decodeShort($type, $data);
        } else {
            throw new \InvalidArgumentException('Unknown Type ' . \get_class($type));
        }
    }
    /**
     * Decode an Anything field.
     *
     *
     * @param \LibDNS\Records\Types\Anything $anything The object to populate with the result
     * @param int $length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeAnything(Anything $anything, $data)
    {
        $anything->setValue(\hex2bin($data));
    }
    /**
     * Decode a BitMap field.
     *
     *
     * @param \LibDNS\Records\Types\BitMap $bitMap The object to populate with the result
     * @param int $length
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeBitMap(BitMap $bitMap, $data)
    {
        $bitMap->setValue(\hex2bin($data));
    }
    /**
     * Decode a Char field.
     *
     *
     * @param \LibDNS\Records\Types\Char $char The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeChar(Char $char, $result)
    {
        $value = \unpack('C', $result)[1];
        $char->setValue($value);
    }
    /**
     * Decode a CharacterString field.
     *
     *
     * @param \LibDNS\Records\Types\CharacterString $characterString The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeCharacterString(CharacterString $characterString, $result)
    {
        $characterString->setValue($result);
    }
    /**
     * Decode a DomainName field.
     *
     *
     * @param \LibDNS\Records\Types\DomainName $domainName The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeDomainName(DomainName $domainName, $result)
    {
        $labels = \explode('.', $result);
        if (!empty($last = \array_pop($labels))) {
            $labels[] = $last;
        }
        $domainName->setLabels($labels);
    }
    /**
     * Decode an IPv4Address field.
     *
     *
     * @param \LibDNS\Records\Types\IPv4Address $ipv4Address The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeIPv4Address(IPv4Address $ipv4Address, $result)
    {
        $octets = \unpack('C4', \inet_pton($result));
        $ipv4Address->setOctets($octets);
    }
    /**
     * Decode an IPv6Address field.
     *
     *
     * @param \LibDNS\Records\Types\IPv6Address $ipv6Address The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeIPv6Address(IPv6Address $ipv6Address, $result)
    {
        $shorts = \unpack('n8', \inet_pton($result));
        $ipv6Address->setShorts($shorts);
    }
    /**
     * Decode a Long field.
     *
     *
     * @param \LibDNS\Records\Types\Long $long The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeLong(Long $long, $result)
    {
        $long->setValue((int) $result);
    }
    /**
     * Decode a Short field.
     *
     *
     * @param \LibDNS\Records\Types\Short $short The object to populate with the result
     * @return int The number of packet bytes consumed by the operation
     * @throws \UnexpectedValueException When the packet data is invalid
     */
    private function decodeShort(Short $short, $result)
    {
        $short->setValue((int) $result);
    }
    /**
     * Decode a Message from JSON-encoded string.
     *
     * @param string $data The data string to decode
     * @param int $requestId The message ID to set
     * @return \LibDNS\Messages\Message
     * @throws \UnexpectedValueException When the packet data is invalid
     * @throws \InvalidArgumentException When a type subtype is unknown
     */
    public function decode(string $result, int $requestId) : Message
    {
        $result = \json_decode($result, true);
        if ($result === false) {
            $error = \json_last_error_msg();
            throw new \InvalidArgumentException("Could not decode JSON DNS payload ({$error})");
        }
        if (!isset($result['Status'], $result['TC'], $result['RD'], $result['RA'])) {
            throw new \InvalidArgumentException('Wrong reply from server, missing required fields');
        }
        $message = $this->messageFactory->create();
        $decodingContext = $this->decodingContextFactory->create($this->packetFactory->create());
        //$message->isAuthoritative(true);
        $message->setType(MessageTypes::RESPONSE);
        $message->setID($requestId);
        $message->setResponseCode($result['Status']);
        $message->isTruncated($result['TC']);
        $message->isRecursionDesired($result['RD']);
        $message->isRecursionAvailable($result['RA']);
        $decodingContext->setExpectedQuestionRecords(isset($result['Question']) ? \count($result['Question']) : 0);
        $decodingContext->setExpectedAnswerRecords(isset($result['Answer']) ? \count($result['Answer']) : 0);
        $decodingContext->setExpectedAuthorityRecords(0);
        $decodingContext->setExpectedAdditionalRecords(isset($result['Additional']) ? \count($result['Additional']) : 0);
        $questionRecords = $message->getQuestionRecords();
        $expected = $decodingContext->getExpectedQuestionRecords();
        for ($i = 0; $i < $expected; $i++) {
            $questionRecords->add($this->decodeQuestionRecord($result['Question'][$i]));
        }
        $answerRecords = $message->getAnswerRecords();
        $expected = $decodingContext->getExpectedAnswerRecords();
        for ($i = 0; $i < $expected; $i++) {
            $answerRecords->add($this->decodeResourceRecord($result['Answer'][$i]));
        }
        $authorityRecords = $message->getAuthorityRecords();
        $expected = $decodingContext->getExpectedAuthorityRecords();
        for ($i = 0; $i < $expected; $i++) {
            $authorityRecords->add($this->decodeResourceRecord($result['Authority'][$i]));
        }
        $additionalRecords = $message->getAdditionalRecords();
        $expected = $decodingContext->getExpectedAdditionalRecords();
        for ($i = 0; $i < $expected; $i++) {
            $additionalRecords->add($this->decodeResourceRecord($result['Additional'][$i]));
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/**
 * Encodes Message objects to query strings.
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace danog\LibDNSJson;

use LibDNS\Messages\Message;
use LibDNS\Messages\MessageTypes;
/**
 * Encodes Message objects to query strings.
 *
 * @category LibDNS
 * @package Encoder
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 */
class QueryEncoder
{
    /**
     * Encode a Message to URL payload.
     *
     * @param \LibDNS\Messages\Message $message The Message to encode
     * @return string
     */
    public function encode(Message $message) : string
    {
        if ($message->getType() !== MessageTypes::QUERY) {
            throw new \InvalidArgumentException('Invalid question: is not a question record');
        }
        $questions = $message->getQuestionRecords();
        if ($questions->count() === 0) {
            throw new \InvalidArgumentException('Invalid question: 0 question records provided');
        }
        $question = $questions->getRecordByIndex(0);
        return \http_build_query([
            'cd' => 0,
            // Do not disable result validation
            'do' => 0,
            // Do not send me DNSSEC data
            'type' => $question->getType(),
            // Record type being requested
            'name' => \implode('.', $question->getName()->getLabels()),
            // Record name being requested
            'ct' => 'application/dns-json',
        ]);
    }
}<?php

declare (strict_types=1);
/**
 * Creates QueryEncoder objects.
 *
 * PHP version 5.4
 *
 * @category LibDNS
 * @package Encoder
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 * @version 2.0.0
 */
namespace danog\LibDNSJson;

/**
 * Creates QueryEncoder objects.
 *
 * @category LibDNS
 * @package Encoder
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 */
class QueryEncoderFactory
{
    /**
     * Create a new Encoder object.
     *
     * @return \LibDNS\Encoder\Encoder
     */
    public function create() : QueryEncoder
    {
        return new QueryEncoder();
    }
}<?php

/**
 * Creates JsonDecoder objects.
 *
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 * @copyright Copyright (c) Chris Wright <https://github.com/DaveRandom>,
 * @license http://www.opensource.org/licenses/mit-license.html MIT License
 */
namespace danog\LibDNSJson;

use LibDNS\Messages\MessageFactory;
use LibDNS\Packets\PacketFactory;
use LibDNS\Records\QuestionFactory;
use LibDNS\Records\RDataBuilder;
use LibDNS\Records\RDataFactory;
use LibDNS\Records\RecordCollectionFactory;
use LibDNS\Records\ResourceBuilder;
use LibDNS\Records\ResourceFactory;
use LibDNS\Records\TypeDefinitions\FieldDefinitionFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionFactory;
use LibDNS\Records\TypeDefinitions\TypeDefinitionManager;
use LibDNS\Records\Types\TypeBuilder;
use LibDNS\Records\Types\TypeFactory;
use LibDNS\Decoder\DecodingContextFactory;
/**
 * Creates JsonDecoder objects.
 *
 * @author Daniil Gentili <https://daniil.it>, Chris Wright <https://github.com/DaveRandom>
 */
class JsonDecoderFactory
{
    /**
     * Create a new JsonDecoder object.
     *
     * @param \LibDNS\Records\TypeDefinitions\TypeDefinitionManager $typeDefinitionManager
     * @return JsonDecoder
     */
    public function create(TypeDefinitionManager $typeDefinitionManager = null) : JsonDecoder
    {
        $typeBuilder = new TypeBuilder(new TypeFactory());
        return new JsonDecoder(new PacketFactory(), new MessageFactory(new RecordCollectionFactory()), new QuestionFactory(), new ResourceBuilder(new ResourceFactory(), new RDataBuilder(new RDataFactory(), $typeBuilder), $typeDefinitionManager ?: new TypeDefinitionManager(new TypeDefinitionFactory(), new FieldDefinitionFactory())), $typeBuilder, new DecodingContextFactory());
    }
}<?php

namespace danog\LibDNSJson\Test;

use danog\LibDNSJson\JsonDecoder;
use danog\LibDNSJson\JsonDecoderFactory;
use PHPUnit\Framework\TestCase;
class JsonDecoderFactoryTest extends TestCase
{
    /**
     *
     */
    public function testJsonDecoderFactoryWorks()
    {
        $this->assertInstanceOf(JsonDecoder::class, (new JsonDecoderFactory())->create());
    }
}<?php

namespace danog\LibDNSJson\Test;

use danog\LibDNSJson\JsonDecoderFactory;
use LibDNS\Messages\Message;
use LibDNS\Messages\MessageTypes;
use PHPUnit\Framework\TestCase;
class JsonDecoderTest extends TestCase
{
    /**
     * Test decoding of valid JSON DNS payloads.
     *
     * @param string $message
     * @param int $requestId
     * @return void
     *
     * @dataProvider provideValidJsonPayloads
     */
    public function testDecodesValidJsonPayloads(string $message, int $requestId)
    {
        $decoder = (new JsonDecoderFactory())->create();
        $response = $decoder->decode($message, $requestId);
        $this->assertInstanceOf(Message::class, $response);
        $this->assertEquals(MessageTypes::RESPONSE, $response->getType());
    }
    /**
     *
     */
    public function provideValidJsonPayloads()
    {
        return [['{
                    "Status": 0,
                    "TC": false,
                    "RD": true,
                    "RA": true,
                    "AD": false,
                    "CD": false,
                    "Question":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1
                    }
                    ],
                    "Answer":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.178.96.59"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.172.224.47"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.142.160.59"
                    }
                    ],
                    "Additional": [ ],
                    "edns_client_subnet": "12.34.56.78/0"
                }', 2], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"Status": 0,"TC": false,"RD": true,"RA": true,"AD": false,"CD": false,"Question":[ {"name": "daniil.it.","type": 6}],"Answer":[ {"name": "daniil.it.","type": 6,"TTL": 3493,"data": "cruz.ns.cloudflare.com. dns.cloudflare.com. 2031387933 10000 2400 604800 3600"}]}', 3]];
    }
    /**
     * Test decoding of invalid JSON DNS payloads.
     *
     * @param string $message
     * @param int $requestId
     * @return void
     *
     * @dataProvider provideInvalidJsonPayloads
     */
    public function testDecodesInvalidJsonPayloads($message, $requestId)
    {
        $decoder = (new JsonDecoderFactory())->create();
        $this->expectException(\InvalidArgumentException::class);
        $decoder->decode($message, $requestId);
    }
    /**
     *
     */
    public function provideInvalidJsonPayloads()
    {
        return [['{lmfao
                    "Status": 0,
                    "TC": false,
                    "RD": true,
                    "RA": true,
                    "AD": false,
                    "CD": false,
                    "Question":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1
                    }
                    ],
                    "Answer":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.178.96.59"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.172.224.47"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.142.160.59"
                    }
                    ],
                    "Additional": [ ],
                    "edns_client_subnet": "12.34.56.78/0"
                }', 2], ['xd{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', 3], ['whaaa{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', 3], ['xdxdxxxxx{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"Status": 0,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"Status": 0,"TC": false,"RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3], ['xd', 0]];
    }
}<?php

namespace danog\LibDNSJson\Test;

use danog\LibDNSJson\QueryEncoder;
use danog\LibDNSJson\QueryEncoderFactory;
use PHPUnit\Framework\TestCase;
class QueryEncoderFactoryTest extends TestCase
{
    /**
     *
     */
    public function testQueryEncoderFactoryWorks()
    {
        $this->assertInstanceOf(QueryEncoder::class, (new QueryEncoderFactory())->create());
    }
}<?php

namespace danog\LibDNSJson\Test;

use danog\LibDNSJson\JsonDecoderFactory;
use danog\LibDNSJson\QueryEncoderFactory;
use LibDNS\Messages\MessageTypes;
use PHPUnit\Framework\TestCase;
class QueryEncoderTest extends TestCase
{
    /**
     * Test encoding of valid DNS message payloads.
     *
     * @param string $message
     * @return void
     *
     * @dataProvider provideValidQueryPayloads
     */
    public function testEncodesValidQueryPayloads(string $message)
    {
        $decoder = (new JsonDecoderFactory())->create();
        $response = $decoder->decode($message, 0);
        $response->setType(MessageTypes::QUERY);
        $encoder = (new QueryEncoderFactory())->create();
        $request = $encoder->encode($response);
        $this->assertInternalType('string', $request, "Got a " . \gettype($request) . " instead of a string");
        \parse_str($request, $output);
        $this->assertNotEmpty($output);
        $this->assertArrayHasKey('cd', $output);
        $this->assertArrayHasKey('do', $output);
        $this->assertArrayHasKey('ct', $output);
        $this->assertArrayHasKey('type', $output);
        $this->assertArrayHasKey('name', $output);
        $this->assertEquals($output['cd'], 0);
        $this->assertEquals($output['do'], 0);
        $this->assertEquals($output['ct'], 'application/dns-json');
        $this->assertEquals($output['type'], $response->getQuestionRecords()->getRecordByIndex(0)->getType());
        $this->assertEquals($output['name'], \implode('.', $response->getQuestionRecords()->getRecordByIndex(0)->getName()->getLabels()));
    }
    /**
     *
     */
    public function provideValidQueryPayloads()
    {
        return [['{
                    "Status": 0,
                    "TC": false,
                    "RD": true,
                    "RA": true,
                    "AD": false,
                    "CD": false,
                    "Question":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1
                    }
                    ],
                    "Answer":
                    [
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.178.96.59"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.172.224.47"
                    },
                    {
                        "name": "apple.com.",
                        "type": 1,
                        "TTL": 3599,
                        "data": "17.142.160.59"
                    }
                    ],
                    "Additional": [ ],
                    "edns_client_subnet": "12.34.56.78/0"
                }', 2], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": true,"CD": false,"Question":[{"name": "example.com.", "type": 28}],"Answer":[{"name": "example.com.", "type": 28, "TTL": 7092, "data": "2606:2800:220:1:248:1893:25c8:1946"}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "daniil.it.", "type": 1}],"Answer":[{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.146.166"},{"name": "daniil.it.", "type": 1, "TTL": 300, "data": "104.27.147.166"}]}', 3], ['{"Status": 0,"TC": false,"RD": true, "RA": true, "AD": false,"CD": false,"Question":[{"name": "amphp.org.", "type": 15}],"Answer":[{"name": "amphp.org.", "type": 15, "TTL": 86400, "data": "0 mail.negativeion.net."}]}', 3]];
    }
    /**
     * Test query encoding of invalid DNS payloads.
     *
     * @param $request
     * @return void
     *
     * @dataProvider provideInvalidQueryPayloads
     */
    public function testEncodesInvalidQueryPayloads($request)
    {
        $encoder = (new QueryEncoderFactory())->create();
        $this->expectException(\InvalidArgumentException::class);
        $encoder->encode($request);
    }
    /**
     *
     */
    public function provideInvalidQueryPayloads()
    {
        $decoder = (new JsonDecoderFactory())->create();
        return [[$decoder->decode('{
                        "Status": 0,
                        "TC": false,
                        "RD": true,
                        "RA": true,
                        "AD": false,
                        "CD": false,
                        "Question":
                        [
                        {
                            "name": "apple.com.",
                            "type": 1
                        }
                        ],
                        "Answer":
                        [
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.178.96.59"
                        },
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.172.224.47"
                        },
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.142.160.59"
                        }
                        ],
                        "Additional": [ ],
                        "edns_client_subnet": "12.34.56.78/0"
                    }', 2)], [$decoder->decode('{
                        "Status": 0,
                        "TC": false,
                        "RD": true,
                        "RA": true,
                        "AD": false,
                        "CD": false,
                        "Question":
                        [
                        ],
                        "Answer":
                        [
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.178.96.59"
                        },
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.172.224.47"
                        },
                        {
                            "name": "apple.com.",
                            "type": 1,
                            "TTL": 3599,
                            "data": "17.142.160.59"
                        }
                        ],
                        "Additional": [ ],
                        "edns_client_subnet": "12.34.56.78/0"
                    }', 2)]];
    }
}{
    "name": "danog/primemodule",
    "description": "Prime module capable of doing prime factorization of huge numbers very quickly.\"",
    "type": "library",
    "license": "AGPL-3.0-only",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "require": {
        "php": ">=7.0"
    },
    "suggest": {
        "ext-primemodule": "Install the native C++ extension for extremely fast factorization (https://github.com/danog/PrimeModule-ext)"
    },
    "autoload": {
        "psr-0": {
            "danog\\": "lib/"
        }
    }
}
# NOTICE!!! This is copied from https://stackoverflow.com/questions/4643647/fast-prime-factorization-module
import sys
import random

def primesbelow(N):
    # http://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    #""" Input N>=6, Returns a list of primes, 2 <= p < N """
    correction = N % 6 > 1
    N = {0:N, 1:N-1, 2:N+4, 3:N+3, 4:N+2, 5:N+1}[N%6]
    sieve = [True] * (N // 3)
    sieve[0] = False
    for i in range(int(N ** .5) // 3 + 1):
        if sieve[i]:
            k = (3 * i + 1) | 1
            sieve[k*k // 3::2*k] = [False] * ((N//6 - (k*k)//6 - 1)//k + 1)
            sieve[(k*k + 4*k - 2*k*(i%2)) // 3::2*k] = [False] * ((N // 6 - (k*k + 4*k - 2*k*(i%2))//6 - 1) // k + 1)
    return [2, 3] + [(3 * i + 1) | 1 for i in range(1, N//3 - correction) if sieve[i]]

smallprimeset = set(primesbelow(100000))
_smallprimeset = 100000

def isprime(n, precision=7):
    # http://en.wikipedia.org/wiki/Miller-Rabin_primality_test#Algorithm_and_running_time
    if n == 1 or n % 2 == 0:
        return False
    elif n < 1:
        raise ValueError("Out of bounds, first argument must be > 0")
    elif n < _smallprimeset:
        return n in smallprimeset


    d = n - 1
    s = 0
    while d % 2 == 0:
        d //= 2
        s += 1

    for repeat in range(precision):
        a = random.randrange(2, n - 2)
        x = pow(a, d, n)

        if x == 1 or x == n - 1: continue

        for r in range(s - 1):
            x = pow(x, 2, n)
            if x == 1: return False
            if x == n - 1: break
        else: return False

    return True

# https://comeoncodeon.wordpress.com/2010/09/18/pollard-rho-brent-integer-factorization/
def pollard_brent(n):
    if n % 2 == 0: return 2
    if n % 3 == 0: return 3

    y, c, m = random.randint(1, n-1), random.randint(1, n-1), random.randint(1, n-1)

    g, r, q = 1, 1, 1
    while g == 1:
        x = y
        for i in range(r):
            y = (pow(y, 2, n) + c) % n

        k = 0
        while k < r and g==1:
            ys = y
            for i in range(min(m, r-k)):
                y = (pow(y, 2, n) + c) % n
                q = q * abs(x-y) % n

            g = gcd(q, n)
            k += m
        r *= 2
    if g == n:
        while True:
            ys = (pow(ys, 2, n) + c) % n
            g = gcd(abs(x - ys), n)
            if g > 1:
                break

    return g

smallprimes = primesbelow(10000) # might seem low, but 1000*1000 = 1000000, so this will fully factor every composite < 1000000
def primefactors(n, sort=False):
    factors = []

    limit = int(n ** .5) + 1
    for checker in smallprimes:
        if checker > limit: break
        while n % checker == 0:
            factors.append(checker)
            n //= checker
            limit = int(n ** .5) + 1
            if checker > limit: break

    if n < 2: return factors

    while n > 1:
        if isprime(n):
            factors.append(n)
            break
        factor = pollard_brent(n) # trial division did not fully factor, switch to pollard-brent
        factors.extend(primefactors(factor)) # recurse to factor the not necessarily prime factor returned by pollard-brent
        n //= factor

    if sort: factors.sort()

    return factors

def factorization(n):
    factors = {}
    for p1 in primefactors(n):
        try:
            factors[p1] += 1
        except KeyError:
            factors[p1] = 1
    return factors

totients = {}
def totient(n):
    if n == 0: return 1

    try: return totients[n]
    except KeyError: pass

    tot = 1
    for p, exp in factorization(n).items():
        tot *= (p - 1)  *  p ** (exp - 1)

    totients[n] = tot
    return tot

def gcd(a, b):
    if a == b: return a
    while b > 0: a, b = b, a % b
    return a

def lcm(a, b):
    return abs(a * b) // gcd(a, b)

print(primefactors(int(sys.argv[1]))[0])<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MadelineProto.
MadelineProto is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MadelineProto is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with the MadelineProto.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog;

use FFI;
class PrimeModule
{
    /**
     *
     */
    public static function native_single($what)
    {
        if (!is_int($what)) {
            return false;
        }
        foreach ([2, 3, 5, 7, 11, 13, 17, 19, 23] as $s) {
            if ($what % $s === 0) {
                return $s;
            }
        }
        $g = 0;
        $it = 0;
        for ($i = 0; $i < 3 || $it < 1000; $i++) {
            $t = ((rand(0, 127) & 15) + 17) % $what;
            $x = rand(0, 1 << 31) % ($what - 1) + 1;
            $y = $x;
            $lim = 1 << $i + 18;
            for ($j = 1; $j <= $lim; $j++) {
                $it++;
                $a = $x;
                $b = $x;
                $c = $t;
                while ($b) {
                    if ($b & 1) {
                        $c += $a;
                        if ($c >= $what) {
                            $c -= $what;
                        }
                    }
                    $a += $a;
                    if ($a >= $what) {
                        $a -= $what;
                    }
                    $b >>= 1;
                }
                $x = $c;
                $z = $x < $y ? $what + $x - $y : $x - $y;
                $g = self::gcd($z, $what);
                if ($g != 1) {
                    break;
                }
                if (!($j & $j - 1)) {
                    $y = $x;
                }
            }
            if ($g > 1 && $g < $what) {
                break;
            }
        }
        if ($g > 1 && $g < $what) {
            return $g;
        }
        return $what;
    }
    /**
     *
     */
    public static function native($what)
    {
        $res = [self::native_single($what)];
        while (array_product($res) !== $what) {
            $res[] = self::native_single($what / array_product($res));
        }
        return $res;
    }
    /**
     *
     */
    public static function python_single($what)
    {
        if (function_exists('shell_exec')) {
            $res = trim(shell_exec('timeout 10 python2 ' . __DIR__ . '/prime.py ' . $what . ' 2>&1'));
            if ($res == '' || is_null($res) || !is_numeric($res)) {
                copy(__DIR__ . '/prime.py', getcwd() . '/.prime.py');
                $res = trim(shell_exec('timeout 10 python2 ' . getcwd() . '/.prime.py ' . $what . ' 2>&1'));
                unlink(getcwd() . '/.prime.py');
                if ($res == '' || is_null($res) || !is_numeric($res)) {
                    return false;
                }
            }
            $newval = intval($res);
            if (is_int($newval)) {
                $res = $newval;
            }
            if ($res === 0) {
                return false;
            }
            return $res;
        }
        return false;
    }
    /**
     *
     */
    public static function python($what)
    {
        $res = [self::python_single($what)];
        if ($res[0] === false) {
            return false;
        }
        while (array_product($res) !== $what) {
            $res[] = self::python_single($what / array_product($res));
        }
        return $res;
    }
    /**
     *
     */
    public static function python_single_alt($what)
    {
        if (function_exists('shell_exec')) {
            $res = trim(shell_exec('python ' . __DIR__ . '/alt_prime.py ' . $what . ' 2>&1'));
            if ($res == '' || is_null($res) || !is_numeric($res)) {
                copy(__DIR__ . '/alt_prime.py', getcwd() . '/.alt_prime.py');
                $res = trim(shell_exec('python ' . getcwd() . '/.alt_prime.py ' . $what . ' 2>&1'));
                unlink(getcwd() . '/.alt_prime.py');
                if ($res == '' || is_null($res) || !is_numeric($res)) {
                    return false;
                }
            }
            $newval = intval($res);
            if (is_int($newval)) {
                $res = $newval;
            }
            if ($res === 0) {
                return false;
            }
            return $res;
        }
        return false;
    }
    /**
     *
     */
    public static function python_alt($what)
    {
        $res = [self::python_single_alt($what)];
        if ($res[0] === false) {
            return false;
        }
        while (array_product($res) !== $what) {
            $res[] = self::python_single_alt($what / array_product($res));
        }
        return $res;
    }
    /**
     *
     */
    public static function wolfram_single($what)
    {
        $query = 'Do prime factorization of ' . $what;
        $params = ['async' => true, 'banners' => 'raw', 'debuggingdata' => false, 'format' => 'moutput', 'formattimeout' => 8, 'input' => $query, 'output' => 'JSON', 'proxycode' => json_decode(file_get_contents('http://www.wolframalpha.com/api/v1/code'), true)['code']];
        $url = 'https://www.wolframalpha.com/input/json.jsp?' . http_build_query($params);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ['Referer: https://www.wolframalpha.com/input/?i=' . urlencode($query)]);
        curl_setopt($ch, CURLOPT_URL, $url);
        $res = json_decode(curl_exec($ch), true);
        curl_close($ch);
        $fres = false;
        if (!isset($res['queryresult']['pods'])) {
            return false;
        }
        foreach ($res['queryresult']['pods'] as $cur) {
            if ($cur['id'] === 'Divisors') {
                $fres = explode(', ', preg_replace(["/{\\d+, /", "/, \\d+}\$/"], '', $cur['subpods'][0]['moutput']));
                break;
            }
        }
        if (is_array($fres)) {
            $fres = $fres[0];
            $newval = intval($fres);
            if (is_int($newval)) {
                $fres = $newval;
            }
            return $fres;
        }
        return false;
    }
    /**
     *
     */
    public static function wolfram($what)
    {
        $res = [self::wolfram_single($what)];
        while (array_product($res) !== $what) {
            $res[] = self::wolfram_single($what / array_product($res));
        }
        return $res;
    }
    /**
     *
     */
    public static function native_single_cpp($what)
    {
        if (!extension_loaded('primemodule')) {
            if (class_exists(FFI::class)) {
                try {
                    $ffi = FFI::load("/usr/include/primemodule-ffi.h");
                    $result = $ffi->factorizeFFI((string) $what);
                    if ($result > 0) {
                        return $result;
                    }
                } catch (\Throwable $e) {
                }
                return false;
            }
            return false;
        }
        try {
            return factorize($what);
        } catch (\Exception $e) {
            return false;
        }
    }
    /**
     *
     */
    public static function native_cpp($what)
    {
        $res = [self::native_single_cpp($what)];
        if ($res[0] == false) {
            return false;
        }
        while (($product = array_product($res)) !== $what) {
            if ($product == 0) {
                return false;
            }
            $res[] = self::native_single_cpp($what / $product);
        }
        return $res;
    }
    /**
     *
     */
    public static function auto_single($what)
    {
        $res = self::native_single_cpp($what);
        if ($res !== false) {
            return $res;
        }
        $res = self::python_single_alt($what);
        if ($res !== false) {
            return $res;
        }
        $res = self::python_single($what);
        if ($res !== false) {
            return $res;
        }
        $res = self::native_single((int) $what);
        if ($res !== false) {
            return $res;
        }
        $res = self::wolfram_single($what);
        if ($res !== false) {
            return $res;
        }
        return false;
    }
    /**
     *
     */
    public static function auto($what)
    {
        $res = self::native_cpp($what);
        if (is_array($res)) {
            return $res;
        }
        $res = self::python_alt($what);
        if (is_array($res)) {
            return $res;
        }
        $res = self::python($what);
        if (is_array($res)) {
            return $res;
        }
        $res = self::native((int) $what);
        if (is_array($res)) {
            return $res;
        }
        $res = self::wolfram($what);
        if (is_array($res)) {
            return $res;
        }
        return false;
    }
    /**
     *
     */
    private static function gcd($a, $b)
    {
        if ($a == $b) {
            return $a;
        }
        while ($b > 0) {
            list($a, $b) = [$b, self::posmod($a, $b)];
        }
        return $a;
    }
    /**
     *
     */
    private static function posmod($a, $b)
    {
        $resto = $a % $b;
        if ($resto < 0) {
            $resto += abs($b);
        }
        return $resto;
    }
    /**
     *
     */
    private function primesbelow($N)
    {
        $correction = $N % 6 > 1 ? true : false;
        $N_Array = [$N, $N - 1, $N + 4, $N + 3, $N + 2, $N + 1];
        $N = $N_Array[$N % 6];
        $sieve = [];
        for ($i = 0; $i < (int) $N / 3; $i++) {
            $sieve[$i] = true;
        }
        $sieve[0] = false;
        for ($i = 0; $i < (int) ((int) pow($N, 0.5) / 3) + 1; $i++) {
            if ($sieve[$i]) {
                $k = 3 * $i + 1 | 1;
                $startIndex1 = (int) ($k * $k / 3);
                $period = 2 * $k;
                for ($j = $startIndex1; $j < count($sieve); $j = $j + $period) {
                    $sieve[$j] = false;
                }
                $startIndex2 = (int) (($k * $k + 4 * $k - 2 * $k * ($i % 2)) / 3);
                $period = 2 * $k;
                for ($k = $startIndex2; $k < count($sieve); $k = $k + $period) {
                    $sieve[$k] = false;
                }
            }
        }
        $resultArray = [2, 3];
        $t = 1;
        for ($i = 1; $i < (int) ($N / 3) - $correction; $i++) {
            if ($sieve[$i]) {
                $resultArray[$t + 1] = 3 * $i + 1 | 1;
                $t++;
            }
        }
        return $resultArray;
    }
    /**
     *
     */
    private function isprime($n, $precision = 7)
    {
        $smallprimeset = $this->primesbelow(100000);
        $_smallprimeset = 100000;
        if ($n == 1 || $n % 2 == 0) {
            return false;
        } elseif ($n < 1) {
            throw new Exception('Out of bounds, first argument must be > 0');
        } elseif ($n < $_smallprimeset) {
            return in_array($n, $smallprimeset);
        }
        $d = $n - 1;
        $s = 0;
        while ($d % 2 == 0) {
            $d = (int) ($d / 2);
            $s += 1;
        }
        for ($i = 0; $i < $precision; $i++) {
            // random.randrange(2, n - 2) means:
            // $a = mt_rand(2, $n - 3);
            // maybe $n would be bigger that PHP_MAX_INT
            $a = mt_rand(2, 1084);
            $x = bcpowmod($a, $d, $n);
            if ($x == 1 || $x == $n - 1) {
                continue;
            }
            $flagfound = 0;
            for ($j = 0; $j < $s - 1; $j++) {
                $x = bcpowmod($x, 2, $n);
                if ($x == 1) {
                    return false;
                }
                if ($x == $n - 1) {
                    $flagfound = 1;
                    break;
                }
            }
            if ($flagfound == 0) {
                return false;
            }
        }
        return true;
    }
    /**
     *
     */
    private function pollard_brent($n)
    {
        $n = (int) $n;
        if ($n % 2 == 0) {
            return 2;
        }
        if (bcmod($n, 2) == 0) {
            return 2;
        }
        if (bcmod($n, 3) == 0) {
            return 3;
        }
        // $y = mt_rand(1, $n-1);
        // $c = mt_rand(1, $n-1);
        // $m = mt_rand(1, $n-1);
        // Again, $n may be bigger than PHP_MAX_INT
        // also, small numbers has a big affect in a good performance
        $y = 2;
        $c = 3;
        $m = 4;
        $g = 1;
        $r = 1;
        $q = 1;
        while ($g == 1) {
            $x = $y;
            for ($i = 0; $i < $r; $i++) {
                // $y = gmp_mod( (bcpowmod($y, 2, $n) + $c) , $n);
                $y = bcmod(bcpowmod($y, 2, $n) + $c, $n);
            }
            $k = 0;
            while ($k < $r && $g == 1) {
                $ys = $y;
                for ($j = 0; $j < min($m, $r - $k); $j++) {
                    // $y = gmp_mod( (bcpowmod($y, 2, $n) + $c), $n );
                    $y = bcmod(bcpowmod($y, 2, $n) + $c, $n);
                    // $q = gmp_mod($q * abs($x-$y), $n);
                    $mul = bcmul($q, abs($x - $y));
                    $q = bcmod($mul, $n);
                }
                $g = $this->gcd2($q, $n);
                $k += $m;
            }
            $r *= 2;
        }
        if ($g == $n) {
            while (true) {
                // $ys = ( bcpowmod($ys, 2, $n) + $c ) % $n;
                $ys = bcmod(bcpowmod($ys, 2, $n) + $c, $n);
                $g = $this->gcd2(abs($x - $ys), $n);
                if ($g > 1) {
                    break;
                }
            }
        }
        return $g;
    }
    /**
     *
     */
    public function primefactors($n, $sort = false)
    {
        $smallprimes = $this->primesbelow(10000);
        $factors = [];
        $limit = bcadd(bcsqrt($n), 1);
        foreach ($smallprimes as $checker) {
            if ($checker > $limit) {
                break;
            }
            // while (gmp_mod($n, $checker) == 0) {
            while (bcmod($n, $checker) == 0) {
                array_push($factors, $checker);
                $n = bcdiv($n, $checker);
                $limit = bcadd(bcsqrt($n), 1);
                if ($checker > $limit) {
                    break;
                }
            }
        }
        if ($n < 2) {
            return $factors;
        }
        while ($n > 1) {
            if ($this->isprime($n)) {
                array_push($factors, $n);
                break;
            }
            $factor = $this->pollard_brent($n);
            $factors = array_merge($factors, $this->primefactors($factor));
            $n = (int) ($n / $factor);
        }
        if ($sort) {
            sort($factors);
        }
        return $factors;
    }
    /**
     *
     */
    private function gcd2($a, $b)
    {
        if ($a == $b) {
            return $a;
        }
        while ($b > 0) {
            $a2 = $a;
            $a = $b;
            $b = bcmod($a2, $b);
        }
        return $a;
    }
}import sys
from math import log

# Multiple Polynomial Quadratic Sieve
def mpqs(n, verbose=False):
  if verbose:
    time1 = clock()

  root_n = isqrt(n)
  root_2n = isqrt(n+n)

  # formula chosen by experimentation
  # seems to be close to optimal for n < 10^50
  bound = int(5 * log(n, 10)**2)

  prime = []
  mod_root = []
  log_p = []
  num_prime = 0

  # find a number of small primes for which n is a quadratic residue
  p = 2
  while p < bound or num_prime < 3:

    # legendre (n|p) is only defined for odd p
    if p > 2:
      leg = legendre(n, p)
    else:
      leg = n & 1
    if leg == 1:
      prime += [p]
      mod_root += [int(mod_sqrt(n, p))]
      log_p += [log(p, 10)]
      num_prime += 1
    elif leg == 0:
      return p

    p = next_prime(p)

  # size of the sieve
  x_max = len(prime)*60

  # maximum value on the sieved range
  m_val = (x_max * root_2n) >> 1

  # fudging the threshold down a bit makes it easier to find powers of primes as factors
  # as well as partial-partial relationships, but it also makes the smoothness check slower.
  # there's a happy medium somewhere, depending on how efficient the smoothness check is
  thresh = log(m_val, 10) * 0.735

  # skip small primes. they contribute very little to the log sum
  # and add a lot of unnecessary entries to the table
  # instead, fudge the threshold down a bit, assuming ~1/4 of them pass
  min_prime = int(thresh*3)
  fudge = sum(log_p[i] for i,p in enumerate(prime) if p < min_prime)/4
  thresh -= fudge

  smooth = []
  used_prime = set()
  partial = {}
  num_smooth = 0
  num_used_prime = 0
  num_partial = 0
  num_poly = 0
  root_A = isqrt(root_2n / x_max)

  while True:
    # find an integer value A such that:
    # A is =~ sqrt(2*n) / x_max
    # A is a perfect square
    # sqrt(A) is prime, and n is a quadratic residue mod sqrt(A)
    while True:
      root_A = next_prime(root_A)
      leg = legendre(n, root_A)
      if leg == 1:
        break
      elif leg == 0:
        return root_A

    A = root_A * root_A

    # solve for an adequate B
    # B*B is a quadratic residue mod n, such that B*B-A*C = n
    # this is unsolvable if n is not a quadratic residue mod sqrt(A)
    b = mod_sqrt(n, root_A)
    B = (b + (n - b*b) * mod_inv(b + b, root_A))%A

    # B*B-A*C = n <=> C = (B*B-n)/A
    C = (B*B - n) / A

    num_poly += 1

    # sieve for prime factors
    sums = [0.0]*(2*x_max)
    i = 0
    for p in prime:
      if p < min_prime:
        i += 1
        continue
      logp = log_p[i]

      inv_A = mod_inv(A, p)
      # modular root of the quadratic
      a = int(((mod_root[i] - B) * inv_A)%p)
      b = int(((p - mod_root[i] - B) * inv_A)%p)

      k = 0
      while k < x_max:
        if k+a < x_max:
          sums[k+a] += logp
        if k+b < x_max:
          sums[k+b] += logp
        if k:
          sums[k-a+x_max] += logp
          sums[k-b+x_max] += logp

        k += p
      i += 1

    # check for smooths
    i = 0
    for v in sums:
      if v > thresh:
        x = x_max-i if i > x_max else i
        vec = set()
        sqr = []
        # because B*B-n = A*C
        # (A*x+B)^2 - n = A*A*x*x+2*A*B*x + B*B - n
        #               = A*(A*x*x+2*B*x+C)
        # gives the congruency
        # (A*x+B)^2 = A*(A*x*x+2*B*x+C) (mod n)
        # because A is chosen to be square, it doesn't need to be sieved
        val = sieve_val = A*x*x + 2*B*x + C

        if sieve_val < 0:
          vec = set([-1])
          sieve_val = -sieve_val

        for p in prime:
          while sieve_val%p == 0:
            if p in vec:
              # keep track of perfect square factors
              # to avoid taking the sqrt of a gigantic number at the end
              sqr += [p]
            vec ^= set([p])
            sieve_val = int(sieve_val / p)

        if sieve_val == 1:
          # smooth
          smooth += [(vec, (sqr, (A*x+B), root_A))]
          used_prime |= vec
        elif sieve_val in partial:
          # combine two partials to make a (xor) smooth
          # that is, every prime factor with an odd power is in our factor base
          pair_vec, pair_vals = partial[sieve_val]
          sqr += list(vec & pair_vec) + [sieve_val]
          vec ^= pair_vec
          smooth += [(vec, (sqr + pair_vals[0], (A*x+B)*pair_vals[1], root_A*pair_vals[2]))]
          used_prime |= vec
          num_partial += 1
        else:
          # save partial for later pairing
          partial[sieve_val] = (vec, (sqr, A*x+B, root_A))
      i += 1

    num_smooth = len(smooth)
    num_used_prime = len(used_prime)


    if num_smooth > num_used_prime:

      used_prime_list = sorted(list(used_prime))

      # set up bit fields for gaussian elimination
      masks = []
      mask = 1
      bit_fields = [0]*num_used_prime
      for vec, vals in smooth:
        masks += [mask]
        i = 0
        for p in used_prime_list:
          if p in vec: bit_fields[i] |= mask
          i += 1
        mask <<= 1

      # row echelon form
      col_offset = 0
      null_cols = []
      for col in xrange(num_smooth):
        pivot = col-col_offset == num_used_prime or bit_fields[col-col_offset] & masks[col] == 0
        for row in xrange(col+1-col_offset, num_used_prime):
          if bit_fields[row] & masks[col]:
            if pivot:
              bit_fields[col-col_offset], bit_fields[row] = bit_fields[row], bit_fields[col-col_offset]
              pivot = False
            else:
              bit_fields[row] ^= bit_fields[col-col_offset]
        if pivot:
          null_cols += [col]
          col_offset += 1

      # reduced row echelon form
      for row in xrange(num_used_prime):
        # lowest set bit
        mask = bit_fields[row] & -bit_fields[row]
        for up_row in xrange(row):
          if bit_fields[up_row] & mask:
            bit_fields[up_row] ^= bit_fields[row]

      # check for non-trivial congruencies
      for col in null_cols:
        all_vec, (lh, rh, rA) = smooth[col]
        lhs = lh   # sieved values (left hand side)
        rhs = [rh] # sieved values - n (right hand side)
        rAs = [rA] # root_As (cofactor of lhs)
        i = 0
        for field in bit_fields:
          if field & masks[col]:
            vec, (lh, rh, rA) = smooth[i]
            lhs += list(all_vec & vec) + lh
            all_vec ^= vec
            rhs += [rh]
            rAs += [rA]
          i += 1

        factor = gcd(list_prod(rAs)*list_prod(lhs) - list_prod(rhs), n)
        if factor != 1 and factor != n:
          break
      else:
        continue
      break

  return factor

# divide and conquer list product
def list_prod(a):
  size = len(a)
  if size == 1:
    return a[0]
  return list_prod(a[:size>>1]) * list_prod(a[size>>1:])

# greatest common divisor of a and b
def gcd(a, b):
  while b:
    a, b = b, a%b
  return a

# modular inverse of a mod m
def mod_inv(a, m):
  a = int(a%m)
  x, u = 0, 1
  while a:
    x, u = u, x - (m/a)*u
    m, a = a, m%a
  return x

# legendre symbol (a|m)
# note: returns m-1 if a is a non-residue, instead of -1
def legendre(a, m):
  return pow(a, (m-1) >> 1, m)

# modular sqrt(n) mod p
# p must be prime
def mod_sqrt(n, p):
  a = n%p
  if p%4 == 3:
    return pow(a, (p+1) >> 2, p)
  elif p%8 == 5:
    v = pow(a << 1, (p-5) >> 3, p)
    i = ((a*v*v << 1) % p) - 1
    return (a*v*i)%p
  elif p%8 == 1:
    # Shank's method
    q = p-1
    e = 0
    while q&1 == 0:
      e += 1
      q >>= 1

    n = 2
    while legendre(n, p) != p-1:
      n += 1

    w = pow(a, q, p)
    x = pow(a, (q+1) >> 1, p)
    y = pow(n, q, p)
    r = e
    while True:
      if w == 1:
        return x

      v = w
      k = 0
      while v != 1 and k+1 < r:
        v = (v*v)%p
        k += 1

      if k == 0:
        return x

      d = pow(y, 1 << (r-k-1), p)
      x = (x*d)%p
      y = (d*d)%p
      w = (w*y)%p
      r = k
  else: # p == 2
    return a

#integer sqrt of n
def isqrt(n):
  n = int(n)
  c = int(n*4/3)
  d = c.bit_length()

  a = d>>1
  if d&1:
    x = 1 << a
    y = (x + (n >> a)) >> 1
  else:
    x = (3 << a) >> 2
    y = (x + (c >> a)) >> 1

  if x != y:
    x = y
    y = int(x + n/x) >> 1
    while y < x:
      x = y
      y = int(x + n/x) >> 1
  return x

# strong probable prime
def is_sprp(n, b=2):
  if n < 2: return False
  d = n-1
  s = 0
  while d&1 == 0:
    s += 1
    d >>= 1

  x = pow(b, d, n)
  if x == 1 or x == n-1:
    return True

  for r in xrange(1, s):
    x = (x * x)%n
    if x == 1:
      return False
    elif x == n-1:
      return True

  return False

# lucas probable prime
# assumes D = 1 (mod 4), (D|n) = -1
def is_lucas_prp(n, D):
  P = 1
  Q = (1-D) >> 2

  # n+1 = 2**r*s where s is odd
  s = n+1
  r = 0
  while s&1 == 0:
    r += 1
    s >>= 1

  # calculate the bit reversal of (odd) s
  # e.g. 19 (10011) <=> 25 (11001)
  t = 0
  while s:
    if s&1:
      t += 1
      s -= 1
    else:
      t <<= 1
      s >>= 1

  # use the same bit reversal process to calculate the sth Lucas number
  # keep track of q = Q**n as we go
  U = 0
  V = 2
  q = 1
  # mod_inv(2, n)
  inv_2 = (n+1) >> 1
  while t:
    if t&1:
      # U, V of n+1
      U, V = ((U + V) * inv_2)%n, ((D*U + V) * inv_2)%n
      q = (q * Q)%n
      t -= 1
    else:
      # U, V of n*2
      U, V = (U * V)%n, (V * V - 2 * q)%n
      q = (q * q)%n
      t >>= 1

  # double s until we have the 2**r*sth Lucas number
  while r:
    U, V = (U * V)%n, (V * V - 2 * q)%n
    q = (q * q)%n
    r -= 1

  # primality check
  # if n is prime, n divides the n+1st Lucas number, given the assumptions
  return U == 0

# primes less than 212
small_primes = set([
    2,  3,  5,  7, 11, 13, 17, 19, 23, 29,
   31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
   73, 79, 83, 89, 97,101,103,107,109,113,
  127,131,137,139,149,151,157,163,167,173,
  179,181,191,193,197,199,211])

# pre-calced sieve of eratosthenes for n = 2, 3, 5, 7
indices = [
    1, 11, 13, 17, 19, 23, 29, 31, 37, 41,
   43, 47, 53, 59, 61, 67, 71, 73, 79, 83,
   89, 97,101,103,107,109,113,121,127,131,
  137,139,143,149,151,157,163,167,169,173,
  179,181,187,191,193,197,199,209]

# distances between sieve values
offsets = [
  10, 2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6,
   6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2, 4,
   2, 4, 8, 6, 4, 6, 2, 4, 6, 2, 6, 6,
   4, 2, 4, 6, 2, 6, 4, 2, 4, 2,10, 2]

max_int = 2147483647

# an 'almost certain' primality check
def is_prime(n):
  if n < 212:
    return n in small_primes

  for p in small_primes:
    if n%p == 0:
      return False

  # if n is a 32-bit integer, perform full trial division
  if n <= max_int:
    i = 211
    while i*i < n:
      for o in offsets:
        i += o
        if n%i == 0:
          return False
    return True

  # Baillie-PSW
  # this is technically a probabalistic test, but there are no known pseudoprimes
  if not is_sprp(n, 2): return False

  # idea shamelessly stolen from Mathmatica
  # if n is a 2-sprp and a 3-sprp, n is necessarily square-free
  if not is_sprp(n, 3): return False

  a = 5
  s = 2
  # if n is a perfect square, this will never terminate
  while legendre(a, n) != n-1:
    s = -s
    a = s-a
  return is_lucas_prp(n, a)

# next prime strictly larger than n
def next_prime(n):
  if n < 2:
    return 2
  # first odd larger than n
  n = (n + 1) | 1
  if n < 212:
    while True:
      if n in small_primes:
        return n
      n += 2

  # find our position in the sieve rotation via binary search
  x = int(n%210)
  s = 0
  e = 47
  m = 24
  while m != e:
    if indices[m] < x:
      s = m
      m = (s + e + 1) >> 1
    else:
      e = m
      m = (s + e) >> 1

  i = int(n + (indices[m] - x))
  # adjust offsets
  offs = offsets[m:] + offsets[:m]
  while True:
    for o in offs:
      if is_prime(i):
        return i
      i += o

print(mpqs(int(sys.argv[1])))
<?php

require 'vendor/autoload.php';
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use function Amp\asyncCall;
use function Amp\Ipc\listen;
Loop::run(static function () {
    $clientHandler = function (ChannelledSocket $socket) {
        echo "Accepted connection" . PHP_EOL;
        while ($payload = (yield $socket->receive())) {
            echo "Received {$payload}" . PHP_EOL;
            if ($payload === 'ping') {
                (yield $socket->send('pong'));
                (yield $socket->disconnect());
            }
        }
        echo "Closed connection" . PHP_EOL . "==========" . PHP_EOL;
    };
    $server = listen(\sys_get_temp_dir() . '/test');
    while ($socket = (yield $server->accept())) {
        asyncCall($clientHandler, $socket);
    }
});<?php

require 'vendor/autoload.php';
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use function Amp\asyncCall;
use function Amp\Ipc\connect;
Loop::run(static function () {
    $clientHandler = function (ChannelledSocket $socket) {
        echo "Created connection." . PHP_EOL;
        while ($payload = (yield $socket->receive())) {
            echo "Received {$payload}" . PHP_EOL;
        }
        echo "Closed connection" . PHP_EOL;
    };
    $channel = (yield connect(\sys_get_temp_dir() . '/test'));
    asyncCall($clientHandler, $channel);
    (yield $channel->send('ping'));
});{
    "name": "danog/ipc",
    "description": "IPC component for Amp.",
    "keywords": [
        "asynchronous",
        "async",
        "concurrent",
        "multi-threading",
        "multi-processing"
    ],
    "homepage": "https://github.com/danog/ipc",
    "license": "MIT",
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        },
        {
            "name": "Aaron Piotrowski",
            "email": "aaron@trowski.com"
        },
        {
            "name": "Stephen Coakley",
            "email": "me@stephencoakley.com"
        }
    ],
    "require": {
        "php": ">=7.1",
        "amphp/byte-stream": "^1",
        "amphp/parser": "^1"
    },
    "require-dev": {
        "amphp/amp": "^2.4",
        "amphp/parallel": "^1.3",
        "phpunit/phpunit": "^7 | ^8 | ^9",
        "amphp/phpunit-util": "^1.3",
        "amphp/php-cs-fixer-config": "dev-master"
    },
    "autoload": {
        "psr-4": {
            "Amp\\Ipc\\": "lib"
        },
        "files": [
            "lib/functions.php"
        ]
    },
    "autoload-dev": {
        "psr-4": {
            "Amp\\Ipc\\Test\\": "test"
        }
    },
    "scripts": {
        "check": [
            "@cs",
            "@test"
        ],
        "cs": "php-cs-fixer fix -v --diff --dry-run",
        "cs-fix": "php-cs-fixer fix -v --diff",
        "test": "@php -dzend.assertions=1 -dassert.exception=1 ./vendor/bin/phpunit --coverage-text"
    }
}
<?php

namespace Amp\Ipc\Sync;

use Amp\ByteStream\ResourceInputStream;
use Amp\ByteStream\ResourceOutputStream;
use Amp\Deferred;
use Amp\Promise;
use Amp\Success;
use function Amp\call;
final class ChannelledSocket implements Channel
{
    private const ESTABLISHED = 0;
    private const GOT_FIN_MASK = 1;
    private const GOT_ACK_MASK = 2;
    private const GOT_ALL_MASK = 3;
    /** @var ChannelledStream */
    private $channel;
    /** @var ResourceInputStream */
    private $read;
    /** @var ResourceOutputStream */
    private $write;
    /** @var bool */
    private $closed = false;
    /** @var int */
    private $state = self::ESTABLISHED;
    /** @var Deferred */
    private $closePromise;
    /** @var bool */
    private $reading = false;
    /**
     * @param resource $read Readable stream resource.
     * @param resource $write Writable stream resource.
     *
     * @throws \Error If a stream resource is not given for $resource.
     */
    public function __construct($read, $write)
    {
        $this->channel = new ChannelledStream($this->read = new ResourceInputStream($read), $this->write = new ResourceOutputStream($write));
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        if ($this->closed) {
            return new Success();
        }
        return call(function () : \Generator {
            $this->reading = true;
            $data = (yield $this->channel->receive());
            $this->reading = false;
            if ($data instanceof ChannelCloseReq) {
                (yield $this->channel->send(new ChannelCloseAck()));
                $this->state = self::GOT_FIN_MASK;
                (yield $this->disconnect());
                if ($this->closePromise) {
                    $this->closePromise->resolve($data);
                }
                return null;
            } elseif ($data instanceof ChannelCloseAck) {
                $this->closePromise->resolve($data);
                return null;
            }
            return $data;
        });
    }
    /**
     * Cleanly disconnect from other endpoint.
     *
     * @return Promise
     */
    public function disconnect() : Promise
    {
        if ($this->closed) {
            return new Success();
        }
        return call(function () : \Generator {
            if ($this->reading) {
                $this->closePromise = new Deferred();
            }
            (yield $this->channel->send(new ChannelCloseReq()));
            do {
                $data = (yield $this->closePromise ? $this->closePromise->promise() : $this->channel->receive());
                if ($this->closePromise) {
                    $this->closePromise = null;
                }
                if ($data instanceof ChannelCloseReq) {
                    (yield $this->channel->send(new ChannelCloseAck()));
                    $this->state |= self::GOT_FIN_MASK;
                } elseif ($data instanceof ChannelCloseAck) {
                    $this->state |= self::GOT_ACK_MASK;
                }
            } while ($this->state !== self::GOT_ALL_MASK);
            $this->closed = true;
            $this->close();
        });
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        if ($this->closed) {
            throw new ChannelException('The channel was already closed!');
        }
        return $this->channel->send($data);
    }
    /**
     * {@inheritdoc}
     */
    public function unreference()
    {
        $this->read->unreference();
    }
    /**
     * {@inheritdoc}
     */
    public function reference()
    {
        $this->read->reference();
    }
    /**
     * Closes the read and write resource streams.
     */
    private function close()
    {
        $this->read->close();
        $this->write->close();
    }
}<?php

namespace Amp\Ipc\Sync;

class ChannelException extends \Exception
{
}<?php

namespace Amp\Ipc\Sync;

use Amp\Promise;
/**
 * A parcel object for sharing data across execution contexts.
 *
 * A parcel is an object that stores a value in a safe way that can be shared
 * between different threads or processes. Different handles to the same parcel
 * will access the same data, and a parcel handle itself is serializable and
 * can be transported to other execution contexts.
 *
 * Wrapping and unwrapping values in the parcel are not atomic. To prevent race
 * conditions and guarantee safety, you should use the provided synchronization
 * methods to acquire a lock for exclusive access to the parcel first before
 * accessing the contained value.
 */
interface Parcel
{
    /**
    * Asynchronously invokes a callback while maintaining an exclusive lock on the parcel. The current value of the
    parcel is provided as the first argument to the callback function.
    *
    * @param callable $callback The synchronized callback to invoke. The parcel value is given as the single argument
    to the callback function. The callback may be a regular function or a coroutine.
    *
    * @return \Amp\Promise<mixed> Resolves with the return value of $callback or fails if $callback
    throws an exception.
    */
    public function synchronized(callable $callback) : Promise;
    /**
     * @return \Amp\Promise<mixed> A promise for the value inside the parcel.
     */
    public function unwrap() : Promise;
}<?php

namespace Amp\Ipc\Sync;

final class ChannelCloseReq implements ChannelCloseMsg
{
}<?php

namespace Amp\Ipc\Sync;

interface ChannelCloseMsg
{
}<?php

namespace Amp\Ipc\Sync;

class SynchronizationError extends \Error
{
}<?php

namespace Amp\Ipc\Sync;

final class ChannelCloseAck implements ChannelCloseMsg
{
}<?php

namespace Amp\Ipc\Sync;

use Amp\Promise;
/**
 * Interface for sending messages between execution contexts.
 */
interface Channel
{
    /**
    * @return \Amp\Promise<mixed>
    *
    * @throws \Amp\Ipc\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Ipc\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Ipc\Sync\ChannelException If receiving from the channel fails.
    * @throws \Amp\Ipc\Sync\SerializationException If unserializing the data fails.
    */
    public function receive() : Promise;
    /**
    * @param mixed $data
    *
    * @return \Amp\Promise<int> Resolves with the number of bytes sent on the channel.
    *
    * @throws \Amp\Ipc\Context\StatusError Thrown if the context has not been started.
    * @throws \Amp\Ipc\Sync\SynchronizationError If the context has not been started or the context
    unexpectedly ends.
    * @throws \Amp\Ipc\Sync\ChannelException If sending on the channel fails.
    * @throws \Error If an ExitResult object is given.
    * @throws \Amp\Ipc\Sync\SerializationException If serializing the data fails.
    */
    public function send($data) : Promise;
}<?php

namespace Amp\Ipc\Sync;

final class PanicError extends \Error
{
    /** @var string Class name of uncaught exception. */
    private $name;
    /** @var string Stack trace of the panic. */
    private $trace;
    /**
     * Creates a new panic error.
     *
     * @param string $name The uncaught exception class.
     * @param string $message The panic message.
     * @param string $trace The panic stack trace.
     * @param (\Throwable | null) $previous Previous exception.
     */
    public function __construct(string $name, string $message = '', string $trace = '', \Throwable $previous = null)
    {
        parent::__construct($message, 0, $previous);
        $this->name = $name;
        $this->trace = $trace;
    }
    /**
     * Returns the class name of the uncaught exception.
     *
     * @return string
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * Gets the stack trace at the point the panic occurred.
     *
     * @return string
     */
    public function getPanicTrace() : string
    {
        return $this->trace;
    }
}<?php

namespace Amp\Ipc\Sync;

use Amp\Parser\Parser;
final class ChannelParser extends Parser
{
    const HEADER_LENGTH = 5;
    /**
     * @param callable(mixed $data) Callback invoked when data is parsed.
     */
    public function __construct(callable $callback)
    {
        parent::__construct(self::parser($callback));
    }
    /**
     * @param mixed $data Data to encode to send over a channel.
     *
     * @return string Encoded data that can be parsed by this class.
     *
     * @throws \Amp\Ipc\Sync\SerializationException
     */
    public function encode($data) : string
    {
        try {
            $data = \serialize($data);
        } catch (\Throwable $exception) {
            throw new SerializationException("The given data cannot be sent because it is not serializable.", 0, $exception);
        }
        return \pack("CL", 0, \strlen($data)) . $data;
    }
    /**
     * @param callable $push
     *
     * @return \Generator
     *
     * @throws \Amp\Ipc\Sync\ChannelException
     * @throws \Amp\Ipc\Sync\SerializationException
     */
    private static function parser(callable $push) : \Generator
    {
        while (true) {
            $header = (yield self::HEADER_LENGTH);
            $data = \unpack("Cprefix/Llength", $header);
            if ($data["prefix"] !== 0) {
                $data = $header . yield;
                throw new ChannelException("Invalid packet received: " . self::encodeUnprintableChars($data));
            }
            $data = (yield $data["length"]);
            // Attempt to unserialize the received data.
            try {
                $result = \unserialize($data);
                if ($result === false && $data !== \serialize(false)) {
                    throw new ChannelException("Received invalid data: " . self::encodeUnprintableChars($data));
                }
            } catch (\Throwable $exception) {
                throw new SerializationException("Exception thrown when unserializing data", 0, $exception);
            }
            $push($result);
        }
    }
    /**
     * @param string $data Binary data.
     *
     * @return string Unprintable characters encoded as \x##.
     */
    private static function encodeUnprintableChars(string $data) : string
    {
        return \preg_replace_callback("/[^ -~]/", function (array $matches) {
            return "\\x" . \dechex(\ord($matches[0]));
        }, $data);
    }
}<?php

namespace Amp\Ipc\Sync;

class SerializationException extends \Exception
{
}<?php

namespace Amp\Ipc\Sync;

use Amp\ByteStream\InputStream;
use Amp\ByteStream\OutputStream;
use Amp\ByteStream\StreamException;
use Amp\Promise;
use function Amp\call;
/**
 * An asynchronous channel for sending data between threads and processes.
 *
 * Supports full duplex read and write.
 */
final class ChannelledStream implements Channel
{
    /** @var \Amp\ByteStream\InputStream */
    private $read;
    /** @var \Amp\ByteStream\OutputStream */
    private $write;
    /** @var \SplQueue */
    private $received;
    /** @var \Amp\Parser\Parser */
    private $parser;
    /**
     * Creates a new channel from the given stream objects. Note that $read and $write can be the same object.
     *
     * @param \Amp\ByteStream\InputStream $read
     * @param \Amp\ByteStream\OutputStream $write
     */
    public function __construct(InputStream $read, OutputStream $write)
    {
        $this->read = $read;
        $this->write = $write;
        $this->received = new \SplQueue();
        $this->parser = new ChannelParser([$this->received, 'push']);
    }
    /**
     * {@inheritdoc}
     */
    public function send($data) : Promise
    {
        return call(function () use($data) {
            try {
                return (yield $this->write->write($this->parser->encode($data)));
            } catch (StreamException $exception) {
                throw new ChannelException("Sending on the channel failed. Did the context die?", 0, $exception);
            }
        });
    }
    /**
     * {@inheritdoc}
     */
    public function receive() : Promise
    {
        return call(function () {
            while ($this->received->isEmpty()) {
                try {
                    $chunk = (yield $this->read->read());
                } catch (StreamException $exception) {
                    throw new ChannelException("Reading from the channel failed. Did the context die?", 0, $exception);
                }
                if ($chunk === null) {
                    throw new ChannelException("The channel closed unexpectedly. Did the context die?");
                }
                $this->parser->push($chunk);
            }
            return $this->received->shift();
        });
    }
}<?php

namespace Amp\Ipc;

use Amp\Deferred;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Loop;
use Amp\Promise;
use Amp\Success;
class IpcServer
{
    public const TYPE_AUTO = 0;
    public const TYPE_UNIX = 1 << 0;
    public const TYPE_FIFO = 1 << 1;
    public const TYPE_TCP = 1 << 2;
    /** @var resource|null */
    private $server;
    /** @var Deferred */
    private $acceptor;
    /** @var string|null */
    private $watcher;
    /** @var string|null */
    private $uri;
    /**
     * @param string $uri Local endpoint on which to listen for requests
     * @param self::TYPE_* $type Server type
     */
    public function __construct(string $uri = '', int $type = self::TYPE_AUTO)
    {
        if (!$uri) {
            $suffix = \bin2hex(\random_bytes(10));
            $uri = \sys_get_temp_dir() . "/amp-ipc-" . $suffix . ".sock";
        }
        if (\file_exists($uri)) {
            @\unlink($uri);
        }
        $this->uri = $uri;
        $isWindows = \strncasecmp(\PHP_OS, "WIN", 3) === 0;
        if ($isWindows) {
            if ($type === self::TYPE_AUTO || $type === self::TYPE_TCP) {
                $types = [self::TYPE_TCP];
            } else {
                throw new \RuntimeException("Cannot use FIFOs and UNIX sockets on windows");
            }
        } elseif ($type === self::TYPE_AUTO) {
            $types = [];
            if (\strlen($uri) <= 104) {
                $types[] = self::TYPE_UNIX;
            }
            $types[] = self::TYPE_FIFO;
            $types[] = self::TYPE_TCP;
        } else {
            $types = [];
            if ($type & self::TYPE_UNIX && \strlen($uri) <= 104) {
                $types[] = self::TYPE_UNIX;
            }
            if ($type & self::TYPE_TCP) {
                $types[] = self::TYPE_TCP;
            }
            if ($type & self::TYPE_FIFO) {
                $types[] = self::TYPE_FIFO;
            }
        }
        $errors = [];
        foreach ($types as $type) {
            if ($type === self::TYPE_FIFO) {
                try {
                    if (!\posix_mkfifo($uri, 0777)) {
                        $errors[$type] = "could not create the FIFO socket";
                        continue;
                    }
                } catch (\Throwable $e) {
                    $errors[$type] = "could not create the FIFO socket: {$e}";
                    continue;
                }
                $error = '';
                try {
                    // Open in r+w mode to prevent blocking if there is no reader
                    $this->server = \fopen($uri, 'r+');
                } catch (\Throwable $e) {
                    $error = "{$e}";
                }
                if ($this->server) {
                    \stream_set_blocking($this->server, false);
                    break;
                }
                $errors[$type] = "could not connect to the FIFO socket: {$error}";
            } else {
                $listenUri = $type === self::TYPE_TCP ? "tcp://127.0.0.1:0" : "unix://" . $uri;
                $errno = -1;
                $errstr = 'no error';
                try {
                    $this->server = \stream_socket_server($listenUri, $errno, $errstr, \STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN);
                } catch (\Throwable $e) {
                    $errstr = "exception: {$e}";
                }
                if ($this->server) {
                    if ($type === self::TYPE_TCP) {
                        try {
                            $name = \stream_socket_get_name($this->server, false);
                            $port = \Phabel\Target\Php80\Polyfill::substr($name, \strrpos($name, ":") + 1);
                            if (!\file_put_contents($this->uri, "tcp://127.0.0.1:" . $port)) {
                                $errors[$type] = 'could not create URI file';
                                $this->server = null;
                            }
                        } catch (\Throwable $e) {
                            $errors[$type] = "could not create URI file: {$e}";
                            $this->server = null;
                        }
                        if (!$this->server) {
                            continue;
                        }
                    }
                    break;
                }
                $errors[$type] = "(errno: {$errno}) {$errstr}";
            }
        }
        if (!$this->server) {
            throw new IpcServerException($errors);
        }
        $acceptor =& $this->acceptor;
        $this->watcher = Loop::onReadable($this->server, static function (string $watcher, $server) use(&$acceptor, $type) : void {
            if ($type === self::TYPE_FIFO) {
                $length = \unpack('v', \fread($server, 2))[1];
                if (!$length) {
                    return;
                    // Could not accept, wrong length read
                }
                $prefix = \fread($server, $length);
                $sockets = [$prefix . '1', $prefix . '2'];
                foreach ($sockets as $k => &$socket) {
                    if (@\filetype($socket) !== 'fifo') {
                        if ($k) {
                            \fclose($sockets[0]);
                        }
                        return;
                        // Is not a FIFO
                    }
                    // Open in either read or write mode to send a close signal when done
                    if (!($socket = \fopen($socket, $k ? 'w' : 'r'))) {
                        if ($k) {
                            \fclose($sockets[0]);
                        }
                        return;
                        // Could not open fifo
                    }
                }
                $channel = new ChannelledSocket(...$sockets);
            } else {
                // Error reporting suppressed since stream_socket_accept() emits E_WARNING on client accept failure.
                if (!($client = @\stream_socket_accept($server, 0))) {
                    // Timeout of 0 to be non-blocking.
                    return;
                    // Accepting client failed.
                }
                $channel = new ChannelledSocket($client, $client);
            }
            $deferred = $acceptor;
            $acceptor = null;
            \assert($deferred !== null);
            $deferred->resolve($channel);
            if (!$acceptor) {
                Loop::disable($watcher);
            }
        });
        Loop::disable($this->watcher);
    }
    /**
     *
     */
    public function __destruct()
    {
        $this->close();
    }
    /**
     * @return Promise<(ChannelledSocket | null)>
     *
     * @throws PendingAcceptError If another accept request is pending.
     */
    public function accept() : Promise
    {
        if ($this->acceptor) {
            throw new PendingAcceptError();
        }
        if (!$this->server) {
            return new Success();
            // Resolve with null when server is closed.
        }
        $this->acceptor = new Deferred();
        Loop::enable($this->watcher);
        return $this->acceptor->promise();
    }
    /**
     * Closes the server and stops accepting connections. Any socket clients accepted will not be closed.
     */
    public function close() : void
    {
        Loop::cancel($this->watcher);
        if ($this->acceptor) {
            $acceptor = $this->acceptor;
            $this->acceptor = null;
            $acceptor->resolve();
        }
        if ($this->server) {
            \fclose($this->server);
            $this->server = null;
        }
        if ($this->uri !== null) {
            @\unlink($this->uri);
            $this->uri = null;
        }
    }
    /**
     * @return bool
     */
    public function isClosed() : bool
    {
        return $this->server === null;
    }
    /**
     * References the accept watcher.
     *
     * @see Loop::reference()
     */
    public final function reference() : void
    {
        Loop::reference($this->watcher);
    }
    /**
     * Unreferences the accept watcher.
     *
     * @see Loop::unreference()
     */
    public final function unreference() : void
    {
        Loop::unreference($this->watcher);
    }
    /**
     * Get endpoint to which clients should connect.
     *
     * @return string
     */
    public function getUri() : string
    {
        return $this->uri;
    }
}<?php

namespace Amp\Ipc;

/**
 * Thrown in case server connection fails.
 */
final class IpcServerException extends \Exception
{
    private const TYPE_MAP = [IpcServer::TYPE_UNIX => 'UNIX', IpcServer::TYPE_TCP => 'TCP', IpcServer::TYPE_FIFO => 'FIFO'];
    /**
     *
     */
    public function __construct(array $messages, int $code = 0, \Throwable $previous = null)
    {
        $message = "Could not create IPC server: ";
        foreach ($messages as $type => $error) {
            $message .= self::TYPE_MAP[$type] . ": {$error}; ";
        }
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Ipc;

/**
 * Thrown in case a second read operation is attempted while another read operation is still pending.
 */
final class PendingAcceptError extends \Error
{
    /**
     *
     */
    public function __construct(string $message = 'The previous accept operation must complete before accept can be called again', int $code = 0, \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
    }
}<?php

namespace Amp\Ipc;

use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Promise;
use function Amp\call;
/**
 * Create IPC server.
 *
 * @param string $uri Local endpoint on which to listen for requests
 *
 * @return IpcServer
 */
function listen(string $uri) : IpcServer
{
    return new IpcServer($uri);
}
/**
 * Connect to IPC server.
 *
 * @param string $uri URI
 *
 * @return Promise<ChannelledSocket>
 */
function connect(string $uri) : Promise
{
    return call(static function () use($uri) {
        if (!\file_exists($uri)) {
            throw new \RuntimeException("The endpoint does not exist!");
        }
        $type = \filetype($uri);
        if ($type !== 'fifo') {
            if ($type === 'file') {
                $uri = \file_get_contents($uri);
            } else {
                $uri = "unix://{$uri}";
            }
            if (!($socket = \stream_socket_client($uri, $errno, $errstr, 5, \STREAM_CLIENT_CONNECT))) {
                $message = "Could not connect to IPC socket";
                if ($error = \error_get_last()) {
                    $message .= \sprintf(" Errno: %d; %s", $error["type"], $error["message"]);
                }
                throw new \RuntimeException($message);
            }
            return new ChannelledSocket($socket, $socket);
        }
        $suffix = \bin2hex(\random_bytes(10));
        $prefix = \sys_get_temp_dir() . "/amp-" . $suffix . ".fifo";
        if (\strlen($prefix) > 0xffff) {
            throw new \RuntimeException('Prefix is too long!');
        }
        $sockets = [$prefix . "2", $prefix . "1"];
        foreach ($sockets as $k => &$socket) {
            if (!\posix_mkfifo($socket, 0777)) {
                throw new \RuntimeException('Could not create FIFO client socket!');
            }
            \register_shutdown_function(static function () use($socket) : void {
                @\unlink($socket);
            });
            if (!($socket = \fopen($socket, 'r+'))) {
                // Open in r+w mode to prevent blocking if there is no reader
                throw new \RuntimeException("Could not open FIFO client socket");
            }
        }
        if (!($tempSocket = \fopen($uri, 'r+'))) {
            // Open in r+w mode to prevent blocking if there is no reader
            throw new \RuntimeException("Could not connect to FIFO server");
        }
        \stream_set_blocking($tempSocket, false);
        \stream_set_write_buffer($tempSocket, 0);
        if (!\fwrite($tempSocket, \pack('v', \strlen($prefix)) . $prefix)) {
            \fclose($tempSocket);
            $tempSocket = null;
            throw new \RuntimeException("Failure sending request to FIFO server");
        }
        \fclose($tempSocket);
        $tempSocket = null;
        return new ChannelledSocket(...$sockets);
    });
}<?php

namespace Amp\Ipc\Test;

use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Parallel\Context\Process;
use Amp\PHPUnit\AsyncTestCase;
use function Amp\asyncCall;
use function Amp\Ipc\connect;
class IpcTest extends AsyncTestCase
{
    /**
     * @dataProvider provideUriType
     */
    public function testBasicIPC(string $uri, int $type)
    {
        $process = new Process([__DIR__ . '/Fixtures/server.php', $uri, $type]);
        (yield $process->start());
        $recvUri = (yield $process->receive());
        if ($uri) {
            $this->assertEquals($uri, $recvUri);
        }
        $client = (yield connect($recvUri));
        $this->assertInstanceOf(ChannelledSocket::class, $client);
        (yield $client->send('ping'));
        $this->assertEquals('pong', (yield $client->receive()));
        (yield $client->disconnect());
        $this->assertNull((yield $process->join()));
    }
    /**
     * @dataProvider provideUriType
     */
    public function testIPCDisconectWhileReading(string $uri, int $type)
    {
        $process = new Process([__DIR__ . '/Fixtures/echoServer.php', $uri, $type]);
        (yield $process->start());
        $recvUri = (yield $process->receive());
        if ($uri) {
            $this->assertEquals($uri, $recvUri);
        }
        $client = (yield connect($recvUri));
        $this->assertInstanceOf(ChannelledSocket::class, $client);
        asyncCall(static function () use($client) {
            while ((yield $client->receive())) {
            }
        });
        (yield $client->disconnect());
        $this->assertNull((yield $process->join()));
    }
    /**
     *
     */
    public function provideUriType() : \Generator
    {
        foreach (['', \sys_get_temp_dir() . '/pony', \sys_get_temp_dir() . '/' . \str_repeat('a', 200)] as $uri) {
            if (\strncasecmp(\PHP_OS, "WIN", 3) === 0) {
                (yield [$uri, IpcServer::TYPE_AUTO]);
                (yield [$uri, IpcServer::TYPE_TCP]);
            } else {
                (yield [$uri, IpcServer::TYPE_AUTO]);
                (yield [$uri, IpcServer::TYPE_TCP]);
                if (\strlen($uri) < 200) {
                    (yield [$uri, IpcServer::TYPE_UNIX]);
                }
                (yield [$uri, IpcServer::TYPE_FIFO]);
            }
        }
    }
}<?php

\Phabel\Target\Php80\Polyfill::error_reporting(E_ALL);
\ini_set('log_errors', 1);
\ini_set('error_log', '/tmp/amphp.log');
\error_log('Inited IPC test!');
use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Parallel\Sync\Channel;
use function Amp\delay;
return function (Channel $channel) use($argv) {
    $server = new IpcServer($argv[1], (int) $argv[2]);
    (yield $channel->send($server->getUri()));
    $socket = (yield $server->accept());
    if (!$socket instanceof ChannelledSocket) {
        throw new \RuntimeException('Socket is not instance of ChannelledSocket');
    }
    $ping = (yield $socket->receive());
    if ($ping !== 'ping') {
        throw new \RuntimeException("Received {$ping} instead of ping!");
    }
    (yield $socket->send('pong'));
    (yield $socket->disconnect());
    $server->close();
    return $server->accept();
};<?php

\Phabel\Target\Php80\Polyfill::error_reporting(E_ALL);
\ini_set('log_errors', 1);
\ini_set('error_log', '/tmp/amphp.log');
\error_log('Inited IPC test!');
use Amp\Ipc\IpcServer;
use Amp\Ipc\Sync\ChannelledSocket;
use Amp\Parallel\Sync\Channel;
use function Amp\delay;
return function (Channel $channel) use($argv) {
    $server = new IpcServer($argv[1], (int) $argv[2]);
    (yield $channel->send($server->getUri()));
    $socket = (yield $server->accept());
    if (!$socket instanceof ChannelledSocket) {
        throw new \RuntimeException('Socket is not instance of ChannelledSocket');
    }
    while ((yield $socket->receive())) {
    }
    (yield $socket->disconnect());
    $server->close();
    return $server->accept();
};<?php

class a
{
}
class b
{
}
$a = new a();
$a->a = ['lel', ['lel', [new a()]]];
$a->b = new a();
$a->b->c = [new a()];
$a->b->c[0]->d = 'cos';
$a->b->c[0]->e = new b();
$a->b->c[0]->e->f = new a();
$a = [$a];
file_put_contents('test', serialize($a));
var_dump(serialize($a), $a);
var_dump(unserialize(file_get_contents('testb')));<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MagicalSerializer.
MagicalSerializer is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MagicalSerializer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with the MagicalSerializer.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog;

class Serialization
{
    public static $extracted = [];
    /**
     *
     */
    public static function unserialize($data)
    {
        foreach (get_declared_classes() as $class) {
            if (isset(class_uses($class)['danog\\Serializable'])) {
                $namelength = strlen($class);
                if (strpos($data, 'O:' . $namelength . ':"' . $class . '":') === false) {
                    continue;
                }
                $data = explode('O:' . $namelength . ':"' . $class . '":', $data);
                $stringdata = array_shift($data);
                foreach ($data as $chunk) {
                    list($attributecount, $value) = explode(':{', $chunk, 2);
                    $attributecount++;
                    $stringdata .= 'O:17:"danog\\PlaceHolder":' . $attributecount . ':{s:21:"originalclassnamepony";s:' . $namelength . ':"' . $class . '";' . $value;
                }
                $data = $stringdata;
            }
        }
        self::$extracted = [];
        $data = self::extractponyobject(unserialize($data));
        self::$extracted = [];
        return $data;
    }
    /**
     *
     */
    public static function extractponyobject($orig)
    {
        if (isset($orig->realactualponyobject)) {
            return self::extractponyobject($orig->realactualponyobject);
        }
        if (is_array($orig) || $orig instanceof \Volatile) {
            foreach ($orig as $key => $value) {
                $orig[$key] = self::extractponyobject($value);
            }
            return $orig;
        }
        if (is_object($orig) && !isset(self::$extracted[$hash = spl_object_hash($orig)])) {
            self::$extracted[$hash] = true;
            foreach ($orig as $key => $value) {
                $orig->{$key} = self::extractponyobject($value);
            }
        }
        return $orig;
    }
    /**
     *
     */
    public static function serialize($object, $not_compatible = false)
    {
        self::$extracted = [];
        $object = serialize(self::createserializableobject($object));
        self::$extracted = [];
        if ($not_compatible === true) {
            return $object;
        }
        $object = explode('O:17:"danog\\PlaceHolder":', $object);
        $newobject = array_shift($object);
        foreach ($object as $chunk) {
            list($attributecount, $value) = explode(':{', $chunk, 2);
            $attributecount--;
            list($pre, $value) = explode('s:21:"originalclassnamepony";s:', $value, 2);
            list($length, $value) = explode(':', $value, 2);
            $classname = \Phabel\Target\Php80\Polyfill::substr($value, 1, $length);
            $value = $pre . \Phabel\Target\Php80\Polyfill::substr($value, $length + 3);
            $newobject .= 'O:' . strlen($classname) . ':"' . $classname . '":' . $attributecount . ':{' . $value;
        }
        return $newobject;
    }
    /**
     *
     */
    public static function createserializableobject($orig)
    {
        if (is_object($orig) && $orig instanceof \danog\MadelineProto\VoIP) {
            $orig = false;
        }
        if (is_object($orig)) {
            if (isset(self::$extracted[$hash = spl_object_hash($orig)])) {
                return self::$extracted[$hash];
            }
            if (method_exists($orig, 'fetchserializableobject')) {
                return $orig->fetchserializableobject($hash);
            }
            self::$extracted[$hash] = $orig;
        }
        if (is_array($orig) || $orig instanceof \Volatile) {
            foreach ($orig as $key => $value) {
                $orig[$key] = self::createserializableobject($value);
            }
        }
        return $orig;
    }
}<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MagicalSerializer.
MagicalSerializer is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MagicalSerializer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with the MagicalSerializer.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog;

trait Serializable
{
    /**
     *
     */
    public final function __construct(...$params)
    {
        if (count($params) === 1 && is_array($params[0]) && isset($params[0]['originalclassnamepony'])) {
            unset($params[0]['originalclassnamepony']);
            foreach ($params[0] as $key => $value) {
                if (strpos($key, chr(0) . get_class($this) . chr(0)) === 0) {
                    $key = \Phabel\Target\Php80\Polyfill::substr($key, strlen(get_class($this)) + 2);
                } elseif (strpos($key, chr(0) . '*' . chr(0)) === 0) {
                    $key = \Phabel\Target\Php80\Polyfill::substr($key, 3);
                } elseif ($key[0] === "\x00") {
                    $key = \Phabel\Target\Php80\Polyfill::substr($key, 1);
                }
                $this->{$key} = \danog\Serialization::extractponyobject($value);
            }
            return;
        }
        if (method_exists($this, '__magic_construct')) {
            $this->__magic_construct(...$params);
        } elseif (method_exists($this, '___construct')) {
            $this->___construct(...$params);
        }
    }
    /**
     *
     */
    public final function fetchserializableobject($hash)
    {
        $values = get_object_vars($this);
        if (method_exists($this, '__sleep')) {
            $newvalues = [];
            foreach ($this->__sleep() as $key) {
                $newvalues[$key] = $values[$key];
            }
            $values = $newvalues;
        }
        return new \danog\PlaceHolder($hash, get_class($this), $values);
    }
}<?php

/*
Copyright 2016-2018 Daniil Gentili
(https://daniil.it)
This file is part of MagicalSerializer.
MagicalSerializer is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
MagicalSerializer is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Affero General Public License for more details.
You should have received a copy of the GNU General Public License along with the MagicalSerializer.
If not, see <http://www.gnu.org/licenses/>.
*/
namespace danog;

class PlaceHolder
{
    /**
     *
     */
    public function __construct($hash, $originalclassnamepony, $elements)
    {
        Serialization::$extracted[$hash] = $this;
        $this->originalclassnamepony = $originalclassnamepony;
        foreach ($elements as $key => $value) {
            $this->{$key} = Serialization::createserializableobject($value);
        }
    }
    /**
     *
     */
    public function __wakeup()
    {
        $this->realactualponyobject = ($phabel_02f998efa324f8a4 = $this->originalclassnamepony) || true ? new $phabel_02f998efa324f8a4(get_object_vars($this)) : false;
        if (method_exists($this->realactualponyobject, '__wakeup')) {
            $this->realactualponyobject->__wakeup();
        }
    }
}{
    "name": "danog/magicalserializer",
    "description": "Serialize Volatile, Threaded or any other internal PHP class!",
    "type": "library",
    "license": "AGPL-3.0-only",
    "homepage": "https://daniil.it/MagicalSerializer",
    "keywords": ["pthreads", "volatile", "serialize", "threading", "serializable"],
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "autoload": {
        "psr-0": {
            "danog\\": "src/"
        }
    }
}
<?php

require 'vendor/autoload.php';
class a
{
    use \danog\Serializable;
    protected $a;
    /**
     *
     */
    public function ___construct()
    {
        var_dump('CONSTRUCTED a');
    }
    /**
     *
     */
    public function __wakeup()
    {
        var_dump('WOKE UP a');
    }
}
new a();
class b
{
    use \danog\Serializable;
}
$result = \danog\Serialization::unserialize(file_get_contents('test'));
var_dump($result);
file_put_contents('testb', \danog\Serialization::serialize($result));<?php

namespace cash;

/**
 * Least Recently Used Cache
 *
 * A fixed sized cache that removes the element used last when it reaches its
 * size limit.
 */
class LRUCache
{
    /** @var int */
    protected $maximumSize;
    /**
     * The front of the array contains the LRU element
     *
     * @var array
     */
    protected $data = array();
    /**
     * Create a LRU Cache
     *
     * @param int $size
     * @throws \InvalidArgumentException
     */
    public function __construct($size)
    {
        if (!is_int($size) || $size <= 0) {
            throw new \InvalidArgumentException();
        }
        $this->maximumSize = $size;
    }
    /**
     * Get the value cached with this key
     *
     * @param (int | string) $key The key. Strings that are ints are cast to ints.
     * @param mixed $default The value to be returned if key not found. (Optional)
     * @return mixed
     */
    public function get($key, $default = null)
    {
        if (isset($this->data[$key])) {
            $this->recordAccess($key);
            return $this->data[$key];
        } else {
            return $default;
        }
    }
    /**
     * Put something in the cache
     *
     * @param (int | string) $key The key. Strings that are ints are cast to ints.
     * @param mixed $value The value to cache
     */
    public function put($key, $value)
    {
        if (isset($this->data[$key])) {
            $this->data[$key] = $value;
            $this->recordAccess($key);
        } else {
            $this->data[$key] = $value;
            if ($this->size() > $this->maximumSize) {
                // remove least recently used element (front of array)
                reset($this->data);
                unset($this->data[key($this->data)]);
            }
        }
    }
    /**
     * Get the number of elements in the cache
     *
     * @return int
     */
    public function size()
    {
        return count($this->data);
    }
    /**
     * Does the cache contain an element with this key
     *
     * @param (int | string) $key The key
     * @return boolean
     */
    public function containsKey($key)
    {
        return isset($this->data[$key]);
    }
    /**
     * Remove the element with this key.
     *
     * @param (int | string) $key The key
     * @return mixed Value or null if not set
     */
    public function remove($key)
    {
        if (isset($this->data[$key])) {
            $value = $this->data[$key];
            unset($this->data[$key]);
            return $value;
        } else {
            return null;
        }
    }
    /**
     * Clear the cache
     */
    public function clear()
    {
        $this->data = array();
    }
    /**
     * Moves the element from current position to end of array
     *
     * @param (int | string) $key The key
     */
    protected function recordAccess($key)
    {
        $value = $this->data[$key];
        unset($this->data[$key]);
        $this->data[$key] = $value;
    }
}{
    "name": "cash/lrucache",
    "type": "library",
    "description": "An efficient memory-based Least Recently Used (LRU) cache",
    "keywords": ["cache", "lru"],
    "homepage": "https://github.com/cash/LRUCache",
    "license": "MIT",
    "authors": [
        {
            "name": "Cash Costello",
            "email": "cash.costello@gmail.com"
        }
    ],
    "minimum-stability": "stable",
    "require": {
        "php": ">=5.3.0"
    },
    "autoload": {
        "psr-0": {
            "cash": "src/"
        }
    }
}
<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogmaticFormatter;
/**
 * @author Julien Breux <julien.breux@gmail.com>
 */
class LogmaticHandler extends SocketHandler
{
    /**
     * @var string
     */
    private $logToken;
    /**
     * @var string
     */
    private $hostname;
    /**
     * @var string
     */
    private $appname;
    /**
     * @param string $token Log token supplied by Logmatic.
     * @param string $hostname Host name supplied by Logmatic.
     * @param string $appname Application name supplied by Logmatic.
     * @param bool $useSSL Whether or not SSL encryption should be used.
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, string $hostname = '', string $appname = '', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true)
    {
        if ($useSSL && !extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use SSL encrypted connection for LogmaticHandler');
        }
        $endpoint = $useSSL ? 'ssl://api.logmatic.io:10515' : 'api.logmatic.io:10514';
        $endpoint .= '/v1/';
        parent::__construct($endpoint, $level, $bubble);
        $this->logToken = $token;
        $this->hostname = $hostname;
        $this->appname = $appname;
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        return $this->logToken . ' ' . $record['formatted'];
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        $formatter = new LogmaticFormatter();
        if (!empty($this->hostname)) {
            $formatter->setHostname($this->hostname);
        }
        if (!empty($this->appname)) {
            $formatter->setAppname($this->appname);
        }
        return $formatter;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * No-op
 *
 * This handler handles anything, but does nothing, and does not stop bubbling to the rest of the stack.
 * This can be used for testing, or to disable a handler when overriding a configuration without
 * influencing the rest of the stack.
 *
 * @author Roel Harbers <roelharbers@gmail.com>
 */
class NoopHandler extends Handler
{
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return true;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        return false;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter;
use PhpAmqpLib\Message\AMQPMessage;
use PhpAmqpLib\Channel\AMQPChannel;
use AMQPExchange;
/**
 * @phpstan-import-type Record from \Monolog\Logger
 */
class AmqpHandler extends AbstractProcessingHandler
{
    /**
     * @var AMQPExchange|AMQPChannel $exchange
     */
    protected $exchange;
    /**
     * @var string
     */
    protected $exchangeName;
    /**
     * @param (AMQPExchange | AMQPChannel) $exchange AMQPExchange (php AMQP ext) or PHP AMQP lib channel, ready for use
     * @param (string | null) $exchangeName Optional exchange name, for AMQPChannel (PhpAmqpLib) only
     */
    public function __construct($exchange, ?string $exchangeName = null, $level = Logger::DEBUG, bool $bubble = true)
    {
        if ($exchange instanceof AMQPChannel) {
            $this->exchangeName = (string) $exchangeName;
        } elseif (!$exchange instanceof AMQPExchange) {
            throw new \InvalidArgumentException('PhpAmqpLib\\Channel\\AMQPChannel or AMQPExchange instance required');
        } elseif ($exchangeName) {
            @trigger_error('The $exchangeName parameter can only be passed when using PhpAmqpLib, if using an AMQPExchange instance configure it beforehand', E_USER_DEPRECATED);
        }
        $this->exchange = $exchange;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $data = $record["formatted"];
        $routingKey = $this->getRoutingKey($record);
        if ($this->exchange instanceof AMQPExchange) {
            $this->exchange->publish($data, $routingKey, 0, ['delivery_mode' => 2, 'content_type' => 'application/json']);
        } else {
            $this->exchange->basic_publish($this->createAmqpMessage($data), $this->exchangeName, $routingKey);
        }
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if ($this->exchange instanceof AMQPExchange) {
            parent::handleBatch($records);
            return;
        }
        foreach ($records as $record) {
            if (!$this->isHandling($record)) {
                continue;
            }
            /** @var Record $record */
            $record = $this->processRecord($record);
            $data = $this->getFormatter()->format($record);
            $this->exchange->batch_basic_publish($this->createAmqpMessage($data), $this->exchangeName, $this->getRoutingKey($record));
        }
        $this->exchange->publish_batch();
    }
    /**
     * Gets the routing key for the AMQP exchange
     *
     * @phpstan-param Record $record
     */
    protected function getRoutingKey(array $record) : string
    {
        $routingKey = sprintf('%s.%s', $record['level_name'], $record['channel']);
        return strtolower($routingKey);
    }
    /**
     *
     */
    private function createAmqpMessage(string $data) : AMQPMessage
    {
        return new AMQPMessage($data, ['delivery_mode' => 2, 'content_type' => 'application/json']);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Aws\Sdk;
use Aws\DynamoDb\DynamoDbClient;
use Monolog\Formatter\FormatterInterface;
use Aws\DynamoDb\Marshaler;
use Monolog\Formatter\ScalarFormatter;
use Monolog\Logger;
/**
 * Amazon DynamoDB handler (http://aws.amazon.com/dynamodb/)
 *
 * @link https://github.com/aws/aws-sdk-php/
 * @author Andrew Lawson <adlawson@gmail.com>
 */
class DynamoDbHandler extends AbstractProcessingHandler
{
    public const DATE_FORMAT = 'Y-m-d\\TH:i:s.uO';
    /**
     * @var DynamoDbClient
     */
    protected $client;
    /**
     * @var string
     */
    protected $table;
    /**
     * @var int
     */
    protected $version;
    /**
     * @var Marshaler
     */
    protected $marshaler;
    /**
     *
     */
    public function __construct(DynamoDbClient $client, string $table, $level = Logger::DEBUG, bool $bubble = true)
    {
        /** @phpstan-ignore-next-line */
        if (defined('Aws\\Sdk::VERSION') && version_compare(Sdk::VERSION, '3.0', '>=')) {
            $this->version = 3;
            $this->marshaler = new Marshaler();
        } else {
            $this->version = 2;
        }
        $this->client = $client;
        $this->table = $table;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $filtered = $this->filterEmptyFields($record['formatted']);
        if ($this->version === 3) {
            $formatted = $this->marshaler->marshalItem($filtered);
        } else {
            /** @phpstan-ignore-next-line */
            $formatted = $this->client->formatAttributes($filtered);
        }
        $this->client->putItem(['TableName' => $this->table, 'Item' => $formatted]);
    }
    /**
     * @param mixed[] $record
     * @return mixed[]
     */
    protected function filterEmptyFields(array $record) : array
    {
        return array_filter($record, function ($value) {
            return !empty($value) || false === $value || 0 === $value;
        });
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new ScalarFormatter(self::DATE_FORMAT);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\JsonFormatter;
use Monolog\Logger;
/**
 * CouchDB handler
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class CouchDBHandler extends AbstractProcessingHandler
{
    /** @var mixed[] */
    private $options;
    /**
     * @param mixed[] $options
     */
    public function __construct(array $options = [], $level = Logger::DEBUG, bool $bubble = true)
    {
        $this->options = array_merge(['host' => 'localhost', 'port' => 5984, 'dbname' => 'logger', 'username' => null, 'password' => null], $options);
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $basicAuth = null;
        if ($this->options['username']) {
            $basicAuth = sprintf('%s:%s@', $this->options['username'], $this->options['password']);
        }
        $url = 'http://' . $basicAuth . $this->options['host'] . ':' . $this->options['port'] . '/' . $this->options['dbname'];
        $context = stream_context_create(['http' => ['method' => 'POST', 'content' => $record['formatted'], 'ignore_errors' => true, 'max_redirects' => 0, 'header' => 'Content-type: application/json']]);
        if (false === @file_get_contents($url, false, $context)) {
            throw new \RuntimeException(sprintf('Could not connect to %s', $url));
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new JsonFormatter(JsonFormatter::BATCH_MODE_JSON, false);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Throwable;
use RuntimeException;
use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\ElasticsearchFormatter;
use InvalidArgumentException;
use Elasticsearch\Common\Exceptions\RuntimeException as ElasticsearchRuntimeException;
use Elasticsearch\Client;
/**
 * Elasticsearch handler
 *
 * @link https://www.elastic.co/guide/en/elasticsearch/client/php-api/current/index.html
 *
 * Simple usage example:
 *
 *    $client = \Elasticsearch\ClientBuilder::create()
 *        ->setHosts($hosts)
 *        ->build();
 *
 *    $options = array(
 *        'index' => 'elastic_index_name',
 *        'type'  => 'elastic_doc_type',
 *    );
 *    $handler = new ElasticsearchHandler($client, $options);
 *    $log = new Logger('application');
 *    $log->pushHandler($handler);
 *
 * @author Avtandil Kikabidze <akalongman@gmail.com>
 */
class ElasticsearchHandler extends AbstractProcessingHandler
{
    /**
     * @var Client
     */
    protected $client;
    /**
     * @var mixed[] Handler config options
     */
    protected $options = [];
    /**
     * @param Client $client Elasticsearch Client object
     * @param mixed[] $options Handler configuration
     */
    public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->client = $client;
        $this->options = array_merge([
            'index' => 'monolog',
            // Elastic index name
            'type' => '_doc',
            // Elastic document type
            'ignore_error' => false,
        ], $options);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->bulkSend([$record['formatted']]);
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($formatter instanceof ElasticsearchFormatter) {
            return parent::setFormatter($formatter);
        }
        throw new InvalidArgumentException('ElasticsearchHandler is only compatible with ElasticsearchFormatter');
    }
    /**
     * Getter options
     *
     * @return mixed[]
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new ElasticsearchFormatter($this->options['index'], $this->options['type']);
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $documents = $this->getFormatter()->formatBatch($records);
        $this->bulkSend($documents);
    }
    /**
     * Use Elasticsearch bulk API to send list of documents
     *
     * @param array[] $records Records + _index/_type keys
     * @throws \RuntimeException
     */
    protected function bulkSend(array $records) : void
    {
        try {
            $params = ['body' => []];
            foreach ($records as $record) {
                $params['body'][] = ['index' => ['_index' => $record['_index'], '_type' => $record['_type']]];
                unset($record['_index'], $record['_type']);
                $params['body'][] = $record;
            }
            $responses = $this->client->bulk($params);
            if ($responses['errors'] === true) {
                throw $this->createExceptionFromResponses($responses);
            }
        } catch (Throwable $e) {
            if (!$this->options['ignore_error']) {
                throw new RuntimeException('Error sending messages to Elasticsearch', 0, $e);
            }
        }
    }
    /**
     * Creates elasticsearch exception from responses array
     *
     * Only the first error is converted into an exception.
     *
     * @param mixed[] $responses returned by $this->client->bulk()
     */
    protected function createExceptionFromResponses(array $responses) : ElasticsearchRuntimeException
    {
        foreach ($responses['items'] ?? [] as $item) {
            if (isset($item['index']['error'])) {
                return $this->createExceptionFromError($item['index']['error']);
            }
        }
        return new ElasticsearchRuntimeException('Elasticsearch failed to index one or more records.');
    }
    /**
     * Creates elasticsearch exception from error array
     *
     * @param mixed[] $error
     */
    protected function createExceptionFromError(array $error) : ElasticsearchRuntimeException
    {
        $previous = isset($error['caused_by']) ? $this->createExceptionFromError($error['caused_by']) : null;
        return new ElasticsearchRuntimeException($error['type'] . ': ' . $error['reason'], 0, $previous);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
use Psr\Log\LogLevel;
/**
 * Buffers all records until a certain level is reached
 *
 * The advantage of this approach is that you don't get any clutter in your log files.
 * Only requests which actually trigger an error (or whatever your actionLevel is) will be
 * in the logs, but they will contain all records, not only those above the level threshold.
 *
 * You can then have a passthruLevel as well which means that at the end of the request,
 * even if it did not get activated, it will still send through log records of e.g. at least a
 * warning level.
 *
 * You can find the various activation strategies in the
 * Monolog\Handler\FingersCrossed\ namespace.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class FingersCrossedHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * @var callable|HandlerInterface
     * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
     */
    protected $handler;
    /** @var ActivationStrategyInterface */
    protected $activationStrategy;
    /** @var bool */
    protected $buffering = true;
    /** @var int */
    protected $bufferSize;
    /** @var Record[] */
    protected $buffer = [];
    /** @var bool */
    protected $stopBuffering;
    /**
     * @var ?int
     * @phpstan-var ?Level
     */
    protected $passthruLevel;
    /** @var bool */
    protected $bubble;
    /**
     * @psalm-param (HandlerInterface | callable(?Record , HandlerInterface ): HandlerInterface) $handler
     *
     * @param (callable | HandlerInterface) $handler Handler or factory callable($record|null, $fingersCrossedHandler).
     * @param (int | string | ActivationStrategyInterface) $activationStrategy Strategy which determines when this handler takes action, or a level name/value at which the handler is activated
     * @param int $bufferSize How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     * @param bool $stopBuffering Whether the handler should stop buffering after being triggered (default true)
     * @param (int | string) $passthruLevel Minimum level to always flush to handler on close, even if strategy not triggered
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $passthruLevel
     * @phpstan-param (Level | LevelName | LogLevel::* | ActivationStrategyInterface) $activationStrategy
     */
    public function __construct($handler, $activationStrategy = null, int $bufferSize = 0, bool $bubble = true, bool $stopBuffering = true, $passthruLevel = null)
    {
        if (null === $activationStrategy) {
            $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING);
        }
        // convert simple int activationStrategy to an object
        if (!$activationStrategy instanceof ActivationStrategyInterface) {
            $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy);
        }
        $this->handler = $handler;
        $this->activationStrategy = $activationStrategy;
        $this->bufferSize = $bufferSize;
        $this->bubble = $bubble;
        $this->stopBuffering = $stopBuffering;
        if ($passthruLevel !== null) {
            $this->passthruLevel = Logger::toMonologLevel($passthruLevel);
        }
        if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
            throw new \RuntimeException("The given handler (" . json_encode($this->handler) . ") is not a callable nor a Monolog\\Handler\\HandlerInterface object");
        }
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return true;
    }
    /**
     * Manually activate this logger regardless of the activation strategy
     */
    public function activate() : void
    {
        if ($this->stopBuffering) {
            $this->buffering = false;
        }
        $this->getHandler(end($this->buffer) ?: null)->handleBatch($this->buffer);
        $this->buffer = [];
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        if ($this->buffering) {
            $this->buffer[] = $record;
            if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) {
                array_shift($this->buffer);
            }
            if ($this->activationStrategy->isHandlerActivated($record)) {
                $this->activate();
            }
        } else {
            $this->getHandler($record)->handle($record);
        }
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        $this->flushBuffer();
        $this->getHandler()->close();
    }
    /**
     *
     */
    public function reset()
    {
        $this->flushBuffer();
        $this->resetProcessors();
        if ($this->getHandler() instanceof ResettableInterface) {
            $this->getHandler()->reset();
        }
    }
    /**
     * Clears the buffer without flushing any messages down to the wrapped handler.
     *
     * It also resets the handler to its initial buffering state.
     */
    public function clear() : void
    {
        $this->buffer = [];
        $this->reset();
    }
    /**
     * Resets the state of the handler. Stops forwarding records to the wrapped handler.
     */
    private function flushBuffer() : void
    {
        if (null !== $this->passthruLevel) {
            $level = $this->passthruLevel;
            $this->buffer = array_filter($this->buffer, function ($record) use($level) {
                return $record['level'] >= $level;
            });
            if (count($this->buffer) > 0) {
                $this->getHandler(end($this->buffer))->handleBatch($this->buffer);
            }
        }
        $this->buffer = [];
        $this->buffering = true;
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory callable, this will trigger the handler's instantiation.
     *
     * @return HandlerInterface
     *
     * @phpstan-param Record $record
     */
    public function getHandler(array $record = null)
    {
        if (!$this->handler instanceof HandlerInterface) {
            $this->handler = ($this->handler)($record, $this);
            if (!$this->handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory callable should return a HandlerInterface");
            }
        }
        return $this->handler;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Rollbar\RollbarLogger;
use Throwable;
use Monolog\Logger;
/**
 * Sends errors to Rollbar
 *
 * If the context data contains a `payload` key, that is used as an array
 * of payload options to RollbarLogger's log method.
 *
 * Rollbar's context info will contain the context + extra keys from the log record
 * merged, and then on top of that a few keys:
 *
 *  - level (rollbar level name)
 *  - monolog_level (monolog level name, raw level, as rollbar only has 5 but monolog 8)
 *  - channel
 *  - datetime (unix timestamp)
 *
 * @author Paul Statezny <paulstatezny@gmail.com>
 */
class RollbarHandler extends AbstractProcessingHandler
{
    /**
     * @var RollbarLogger
     */
    protected $rollbarLogger;
    /** @var string[] */
    protected $levelMap = [Logger::DEBUG => 'debug', Logger::INFO => 'info', Logger::NOTICE => 'info', Logger::WARNING => 'warning', Logger::ERROR => 'error', Logger::CRITICAL => 'critical', Logger::ALERT => 'critical', Logger::EMERGENCY => 'critical'];
    /**
     * Records whether any log records have been added since the last flush of the rollbar notifier
     *
     * @var bool
     */
    private $hasRecords = false;
    /** @var bool */
    protected $initialized = false;
    /**
     * @param RollbarLogger $rollbarLogger RollbarLogger object constructed with valid token
     */
    public function __construct(RollbarLogger $rollbarLogger, $level = Logger::ERROR, bool $bubble = true)
    {
        $this->rollbarLogger = $rollbarLogger;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!$this->initialized) {
            // __destructor() doesn't get called on Fatal errors
            register_shutdown_function(array($this, 'close'));
            $this->initialized = true;
        }
        $context = $record['context'];
        $context = array_merge($context, $record['extra'], ['level' => $this->levelMap[$record['level']], 'monolog_level' => $record['level_name'], 'channel' => $record['channel'], 'datetime' => $record['datetime']->format('U')]);
        if (isset($context['exception']) && $context['exception'] instanceof Throwable) {
            $exception = $context['exception'];
            unset($context['exception']);
            $toLog = $exception;
        } else {
            $toLog = $record['message'];
        }
        // @phpstan-ignore-next-line
        $this->rollbarLogger->log($context['level'], $toLog, $context);
        $this->hasRecords = true;
    }
    /**
     *
     */
    public function flush() : void
    {
        if ($this->hasRecords) {
            $this->rollbarLogger->flush();
            $this->hasRecords = false;
        }
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        $this->flush();
    }
    /**
     * {@inheritDoc}
     */
    public function reset()
    {
        $this->flush();
        parent::reset();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
use Doctrine\CouchDB\CouchDBClient;
/**
 * CouchDB handler for Doctrine CouchDB ODM
 *
 * @author Markus Bachmann <markus.bachmann@bachi.biz>
 */
class DoctrineCouchDBHandler extends AbstractProcessingHandler
{
    /** @var CouchDBClient */
    private $client;
    /**
     *
     */
    public function __construct(CouchDBClient $client, $level = Logger::DEBUG, bool $bubble = true)
    {
        $this->client = $client;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->client->postDocument($record['formatted']);
    }
    /**
     *
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new NormalizerFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

trait WebRequestRecognizerTrait
{
    /**
     * Checks if PHP's serving a web request
     * @return bool
     */
    protected function isWebRequest() : bool
    {
        return 'cli' !== \PHP_SAPI && 'phpdbg' !== \PHP_SAPI;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Swift_Message;
use Swift;
/**
 * SwiftMailerHandler uses Swift_Mailer to send the emails
 *
 * @author Gyula Sallai
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class SwiftMailerHandler extends MailHandler
{
    /** @var \Swift_Mailer */
    protected $mailer;
    /** @var Swift_Message|callable(string, Record[]): Swift_Message */
    private $messageTemplate;
    /**
     * @psalm-param (Swift_Message | callable(string , Record[] ): Swift_Message) $message
     *
     * @param \Swift_Mailer $mailer The mailer to use
     * @param (callable | Swift_Message) $message An example message for real messages, only the body will be replaced
     */
    public function __construct(\Swift_Mailer $mailer, $message, $level = Logger::ERROR, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->mailer = $mailer;
        $this->messageTemplate = $message;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records) : void
    {
        $this->mailer->send($this->buildMessage($content, $records));
    }
    /**
     * Gets the formatter for the Swift_Message subject.
     *
     * @param (string | null) $format The format of the subject
     */
    protected function getSubjectFormatter(?string $format) : FormatterInterface
    {
        return new LineFormatter($format);
    }
    /**
     * Creates instance of Swift_Message to be sent
     *
     * @param string $content formatted email body to be sent
     * @param array $records Log records that formed the content
     * @return Swift_Message
     *
     * @phpstan-param Record[] $records
     */
    protected function buildMessage(string $content, array $records) : Swift_Message
    {
        $message = null;
        if ($this->messageTemplate instanceof Swift_Message) {
            $message = clone $this->messageTemplate;
            $message->generateId();
        } elseif (is_callable($this->messageTemplate)) {
            $message = ($this->messageTemplate)($content, $records);
        }
        if (!$message instanceof Swift_Message) {
            throw new \InvalidArgumentException('Could not resolve message as instance of Swift_Message or a callable returning it');
        }
        if ($records) {
            $subjectFormatter = $this->getSubjectFormatter($message->getSubject());
            $message->setSubject($subjectFormatter->format($this->getHighestRecord($records)));
        }
        $mime = 'text/plain';
        if ($this->isHtmlBody($content)) {
            $mime = 'text/html';
        }
        $message->setBody($content, $mime);
        /** @phpstan-ignore-next-line */
        if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
            $message->setDate(new \DateTimeImmutable());
        } else {
            /** @phpstan-ignore-next-line */
            $message->setDate(time());
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * SendGridrHandler uses the SendGrid API v2 function to send Log emails, more information in https://sendgrid.com/docs/API_Reference/Web_API/mail.html
 *
 * @author Ricardo Fontanelli <ricardo.fontanelli@hotmail.com>
 */
class SendGridHandler extends MailHandler
{
    /**
     * The SendGrid API User
     * @var string
     */
    protected $apiUser;
    /**
     * The SendGrid API Key
     * @var string
     */
    protected $apiKey;
    /**
     * The email addresses to which the message will be sent
     * @var string
     */
    protected $from;
    /**
     * The email addresses to which the message will be sent
     * @var string[]
     */
    protected $to;
    /**
     * The subject of the email
     * @var string
     */
    protected $subject;
    /**
     * @param string $apiUser The SendGrid API User
     * @param string $apiKey The SendGrid API Key
     * @param string $from The sender of the email
     * @param (string | string[]) $to The recipients of the email
     * @param string $subject The subject of the mail
     */
    public function __construct(string $apiUser, string $apiKey, string $from, $to, string $subject, $level = Logger::ERROR, bool $bubble = true)
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the SendGridHandler');
        }
        parent::__construct($level, $bubble);
        $this->apiUser = $apiUser;
        $this->apiKey = $apiKey;
        $this->from = $from;
        $this->to = (array) $to;
        $this->subject = $subject;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records) : void
    {
        $message = [];
        $message['api_user'] = $this->apiUser;
        $message['api_key'] = $this->apiKey;
        $message['from'] = $this->from;
        foreach ($this->to as $recipient) {
            $message['to[]'] = $recipient;
        }
        $message['subject'] = $this->subject;
        $message['date'] = \Phabel\Target\Php80\Polyfill::date('r');
        if ($this->isHtmlBody($content)) {
            $message['html'] = $content;
        } else {
            $message['text'] = $content;
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://api.sendgrid.com/api/mail.send.json');
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($message));
        Curl\Util::execute($ch, 2);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Gelf\PublisherInterface;
use Monolog\Logger;
use Monolog\Formatter\GelfMessageFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Handler to send messages to a Graylog2 (http://www.graylog2.org) server
 *
 * @author Matt Lehner <mlehner@gmail.com>
 * @author Benjamin Zikarsky <benjamin@zikarsky.de>
 */
class GelfHandler extends AbstractProcessingHandler
{
    /**
     * @var PublisherInterface the publisher object that sends the message to the server
     */
    protected $publisher;
    /**
     * @param PublisherInterface $publisher a gelf publisher object
     */
    public function __construct(PublisherInterface $publisher, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->publisher = $publisher;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->publisher->publish($record['formatted']);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new GelfMessageFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
/**
 * Buffers all records until closing the handler and then pass them as batch.
 *
 * This is useful for a MailHandler to send only one mail per request instead of
 * sending one per log message.
 *
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class BufferHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /** @var HandlerInterface */
    protected $handler;
    /** @var int */
    protected $bufferSize = 0;
    /** @var int */
    protected $bufferLimit;
    /** @var bool */
    protected $flushOnOverflow;
    /** @var Record[] */
    protected $buffer = [];
    /** @var bool */
    protected $initialized = false;
    /**
     * @param HandlerInterface $handler Handler.
     * @param int $bufferLimit How many entries should be buffered at most, beyond that the oldest items are removed from the buffer.
     * @param bool $flushOnOverflow If true, the buffer is flushed when the max size has been reached, by default oldest entries are discarded
     */
    public function __construct(HandlerInterface $handler, int $bufferLimit = 0, $level = Logger::DEBUG, bool $bubble = true, bool $flushOnOverflow = false)
    {
        parent::__construct($level, $bubble);
        $this->handler = $handler;
        $this->bufferLimit = $bufferLimit;
        $this->flushOnOverflow = $flushOnOverflow;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($record['level'] < $this->level) {
            return false;
        }
        if (!$this->initialized) {
            // __destructor() doesn't get called on Fatal errors
            register_shutdown_function([$this, 'close']);
            $this->initialized = true;
        }
        if ($this->bufferLimit > 0 && $this->bufferSize === $this->bufferLimit) {
            if ($this->flushOnOverflow) {
                $this->flush();
            } else {
                array_shift($this->buffer);
                $this->bufferSize--;
            }
        }
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        $this->buffer[] = $record;
        $this->bufferSize++;
        return false === $this->bubble;
    }
    /**
     *
     */
    public function flush() : void
    {
        if ($this->bufferSize === 0) {
            return;
        }
        $this->handler->handleBatch($this->buffer);
        $this->clear();
    }
    /**
     *
     */
    public function __destruct()
    {
        // suppress the parent behavior since we already have register_shutdown_function()
        // to call close(), and the reference contained there will prevent this from being
        // GC'd until the end of the request
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        $this->flush();
        $this->handler->close();
    }
    /**
     * Clears the buffer without flushing any messages down to the wrapped handler.
     */
    public function clear() : void
    {
        $this->bufferSize = 0;
        $this->buffer = [];
    }
    /**
     *
     */
    public function reset()
    {
        $this->flush();
        parent::reset();
        $this->resetProcessors();
        if ($this->handler instanceof ResettableInterface) {
            $this->handler->reset();
        }
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($this->handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($this->handler) . ' does not support formatters.');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Blackhole
 *
 * Any record it can handle will be thrown away. This can be used
 * to put on top of an existing stack to override it temporarily.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class NullHandler extends Handler
{
    /**
     * @var int
     */
    private $level;
    /**
     * @param (string | int) $level The minimum logging level at which this handler will be triggered
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return $record['level'] >= $this->level;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        return $record['level'] >= $this->level;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Exception can be thrown if an extension for a handler is missing
 *
 * @author Christian Bergau <cbergau86@gmail.com>
 */
class MissingExtensionException extends \Exception
{
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
/**
 * Stores to PHP error_log() handler.
 *
 * @author Elan RuusamÃ¤e <glen@delfi.ee>
 */
class ErrorLogHandler extends AbstractProcessingHandler
{
    public const OPERATING_SYSTEM = 0;
    public const SAPI = 4;
    /** @var int */
    protected $messageType;
    /** @var bool */
    protected $expandNewlines;
    /**
     * @param int $messageType Says where the error should go.
     * @param bool $expandNewlines If set to true, newlines in the message will be expanded to be take multiple log entries
     */
    public function __construct(int $messageType = self::OPERATING_SYSTEM, $level = Logger::DEBUG, bool $bubble = true, bool $expandNewlines = false)
    {
        parent::__construct($level, $bubble);
        if (false === in_array($messageType, self::getAvailableTypes(), true)) {
            $message = sprintf('The given message type "%s" is not supported', print_r($messageType, true));
            throw new \InvalidArgumentException($message);
        }
        $this->messageType = $messageType;
        $this->expandNewlines = $expandNewlines;
    }
    /**
     * @return int[] With all available types
     */
    public static function getAvailableTypes() : array
    {
        return [self::OPERATING_SYSTEM, self::SAPI];
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter('[%datetime%] %channel%.%level_name%: %message% %context% %extra%');
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!$this->expandNewlines) {
            error_log((string) $record['formatted'], $this->messageType);
            return;
        }
        $lines = preg_split('{[\\r\\n]+}', (string) $record['formatted']);
        if ($lines === false) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Failed to preg_split formatted string: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
        }
        foreach ($lines as $line) {
            error_log($line, $this->messageType);
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LogglyFormatter;
use function array_key_exists;
use CurlHandle;
/**
 * Sends errors to Loggly.
 *
 * @author Przemek Sobstel <przemek@sobstel.org>
 * @author Adam Pancutt <adam@pancutt.com>
 * @author Gregory Barchard <gregory@barchard.net>
 */
class LogglyHandler extends AbstractProcessingHandler
{
    protected const HOST = 'logs-01.loggly.com';
    protected const ENDPOINT_SINGLE = 'inputs';
    protected const ENDPOINT_BATCH = 'bulk';
    /**
     * Caches the curl handlers for every given endpoint.
     *
     * @var resource[]|CurlHandle[]
     */
    protected $curlHandlers = [];
    /** @var string */
    protected $token;
    /** @var string[] */
    protected $tag = [];
    /**
     * @param string $token API token supplied by Loggly
     *
     * @throws MissingExtensionException If the curl extension is missing
     */
    public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the LogglyHandler');
        }
        $this->token = $token;
        parent::__construct($level, $bubble);
    }
    /**
     * Loads and returns the shared curl handler for the given endpoint.
     *
     * @param string $endpoint
     *
     * @return (resource | CurlHandle)
     */
    protected function getCurlHandler(string $endpoint)
    {
        if (!array_key_exists($endpoint, $this->curlHandlers)) {
            $this->curlHandlers[$endpoint] = $this->loadCurlHandle($endpoint);
        }
        return $this->curlHandlers[$endpoint];
    }
    /**
     * Starts a fresh curl session for the given endpoint and returns its handler.
     *
     * @param string $endpoint
     *
     * @return (resource | CurlHandle)
     */
    private function loadCurlHandle(string $endpoint)
    {
        $url = sprintf("https://%s/%s/%s/", static::HOST, $endpoint, $this->token);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        return $ch;
    }
    /**
     * @param (string[] | string) $tag
     */
    public function setTag($tag) : self
    {
        $tag = !empty($tag) ? $tag : [];
        $this->tag = is_array($tag) ? $tag : [$tag];
        return $this;
    }
    /**
     * @param (string[] | string) $tag
     */
    public function addTag($tag) : self
    {
        if (!empty($tag)) {
            $tag = is_array($tag) ? $tag : [$tag];
            $this->tag = array_unique(array_merge($this->tag, $tag));
        }
        return $this;
    }
    /**
     *
     */
    protected function write(array $record) : void
    {
        $this->send($record["formatted"], static::ENDPOINT_SINGLE);
    }
    /**
     *
     */
    public function handleBatch(array $records) : void
    {
        $level = $this->level;
        $records = array_filter($records, function ($record) use($level) {
            return $record['level'] >= $level;
        });
        if ($records) {
            $this->send($this->getFormatter()->formatBatch($records), static::ENDPOINT_BATCH);
        }
    }
    /**
     *
     */
    protected function send(string $data, string $endpoint) : void
    {
        $ch = $this->getCurlHandler($endpoint);
        $headers = ['Content-Type: application/json'];
        if (!empty($this->tag)) {
            $headers[] = 'X-LOGGLY-TAG: ' . implode(',', $this->tag);
        }
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        Curl\Util::execute($ch, 5, false);
    }
    /**
     *
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LogglyFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\WildfireFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Simple FirePHP Handler (http://www.firephp.org/), which uses the Wildfire protocol.
 *
 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class FirePHPHandler extends AbstractProcessingHandler
{
    use WebRequestRecognizerTrait;
    /**
     * WildFire JSON header message format
     */
    protected const PROTOCOL_URI = 'http://meta.wildfirehq.org/Protocol/JsonStream/0.2';
    /**
     * FirePHP structure for parsing messages & their presentation
     */
    protected const STRUCTURE_URI = 'http://meta.firephp.org/Wildfire/Structure/FirePHP/FirebugConsole/0.1';
    /**
     * Must reference a "known" plugin, otherwise headers won't display in FirePHP
     */
    protected const PLUGIN_URI = 'http://meta.firephp.org/Wildfire/Plugin/FirePHP/Library-FirePHPCore/0.3';
    /**
     * Header prefix for Wildfire to recognize & parse headers
     */
    protected const HEADER_PREFIX = 'X-Wf';
    /**
     * Whether or not Wildfire vendor-specific headers have been generated & sent yet
     * @var bool
     */
    protected static $initialized = false;
    /**
     * Shared static message index between potentially multiple handlers
     * @var int
     */
    protected static $messageIndex = 1;
    /** @var bool */
    protected static $sendHeaders = true;
    /**
     * Base header creation function used by init headers & record headers
     *
     * @param array<(int | string)> $meta Wildfire Plugin, Protocol & Structure Indexes
     * @param string $message Log message
     *
     * @return array<string, string> Complete header string ready for the client as key and message as value
     *
     * @phpstan-return non-empty-array<string, string>
     */
    protected function createHeader(array $meta, string $message) : array
    {
        $header = sprintf('%s-%s', static::HEADER_PREFIX, join('-', $meta));
        return [$header => $message];
    }
    /**
     * Creates message header from record
     *
     * @return array<string, string>
     *
     * @phpstan-return non-empty-array<string, string>
     *
     * @see createHeader()
     *
     * @phpstan-param FormattedRecord $record
     */
    protected function createRecordHeader(array $record) : array
    {
        // Wildfire is extensible to support multiple protocols & plugins in a single request,
        // but we're not taking advantage of that (yet), so we're using "1" for simplicity's sake.
        return $this->createHeader([1, 1, 1, self::$messageIndex++], $record['formatted']);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new WildfireFormatter();
    }
    /**
     * Wildfire initialization headers to enable message parsing
     *
     * @see createHeader()
     * @see sendHeader()
     *
     * @return array<string, string>
     */
    protected function getInitHeaders() : array
    {
        // Initial payload consists of required headers for Wildfire
        return array_merge($this->createHeader(['Protocol', 1], static::PROTOCOL_URI), $this->createHeader([1, 'Structure', 1], static::STRUCTURE_URI), $this->createHeader([1, 'Plugin', 1], static::PLUGIN_URI));
    }
    /**
     * Send header string to the client
     */
    protected function sendHeader(string $header, string $content) : void
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }
    /**
     * Creates & sends header for a record, ensuring init headers have been sent prior
     *
     * @see sendHeader()
     * @see sendInitHeaders()
     */
    protected function write(array $record) : void
    {
        if (!self::$sendHeaders || !$this->isWebRequest()) {
            return;
        }
        // WildFire-specific headers must be sent prior to any messages
        if (!self::$initialized) {
            self::$initialized = true;
            self::$sendHeaders = $this->headersAccepted();
            if (!self::$sendHeaders) {
                return;
            }
            foreach ($this->getInitHeaders() as $header => $content) {
                $this->sendHeader($header, $content);
            }
        }
        $header = $this->createRecordHeader($record);
        if (trim(current($header)) !== '') {
            $this->sendHeader(key($header), current($header));
        }
    }
    /**
     * Verifies if the headers are accepted by the current user agent
     */
    protected function headersAccepted() : bool
    {
        if (!empty($_SERVER['HTTP_USER_AGENT']) && preg_match('{\\bFirePHP/\\d+\\.\\d+\\b}', $_SERVER['HTTP_USER_AGENT'])) {
            return true;
        }
        return isset($_SERVER['HTTP_X_FIREPHP_VERSION']);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Handler\Slack\SlackRecord;
/**
 * Sends notifications through Slack Webhooks
 *
 * @author Haralan Dobrev <hkdobrev@gmail.com>
 * @see    https://api.slack.com/incoming-webhooks
 */
class SlackWebhookHandler extends AbstractProcessingHandler
{
    /**
     * Slack Webhook token
     * @var string
     */
    private $webhookUrl;
    /**
     * Instance of the SlackRecord util class preparing data for Slack API.
     * @var SlackRecord
     */
    private $slackRecord;
    /**
     * @param string $webhookUrl Slack Webhook URL
     * @param (string | null) $channel Slack channel (encoded ID or name)
     * @param (string | null) $username Name of a bot
     * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
     * @param (string | null) $iconEmoji The emoji name to use (or null)
     * @param bool $useShortAttachment Whether the the context/extra messages added to Slack as attachments are in a short style
     * @param bool $includeContextAndExtra Whether the attachment should include context and extra data
     * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     */
    public function __construct(string $webhookUrl, ?string $channel = null, ?string $username = null, bool $useAttachment = true, ?string $iconEmoji = null, bool $useShortAttachment = false, bool $includeContextAndExtra = false, $level = Logger::CRITICAL, bool $bubble = true, array $excludeFields = array())
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the SlackWebhookHandler');
        }
        parent::__construct($level, $bubble);
        $this->webhookUrl = $webhookUrl;
        $this->slackRecord = new SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields);
    }
    /**
     *
     */
    public function getSlackRecord() : SlackRecord
    {
        return $this->slackRecord;
    }
    /**
     *
     */
    public function getWebhookUrl() : string
    {
        return $this->webhookUrl;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $postData = $this->slackRecord->getSlackData($record);
        $postString = Utils::jsonEncode($postData);
        $ch = curl_init();
        $options = array(CURLOPT_URL => $this->webhookUrl, CURLOPT_POST => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => array('Content-type: application/json'), CURLOPT_POSTFIELDS => $postString);
        if (defined('CURLOPT_SAFE_UPLOAD')) {
            $options[CURLOPT_SAFE_UPLOAD] = true;
        }
        curl_setopt_array($ch, $options);
        Curl\Util::execute($ch);
    }
    /**
     *
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        parent::setFormatter($formatter);
        $this->slackRecord->setFormatter($formatter);
        return $this;
    }
    /**
     *
     */
    public function getFormatter() : FormatterInterface
    {
        $formatter = parent::getFormatter();
        $this->slackRecord->setFormatter($formatter);
        return $formatter;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Psr\Log\LoggerInterface;
use Monolog\Formatter\FormatterInterface;
/**
 * Proxies log messages to an existing PSR-3 compliant logger.
 *
 * If a formatter is configured, the formatter's output MUST be a string and the
 * formatted message will be fed to the wrapped PSR logger instead of the original
 * log record's message.
 *
 * @author Michael Moussa <michael.moussa@gmail.com>
 */
class PsrHandler extends AbstractHandler implements FormattableHandlerInterface
{
    /**
     * PSR-3 compliant logger
     *
     * @var LoggerInterface
     */
    protected $logger;
    /**
     * @var FormatterInterface|null
     */
    protected $formatter;
    /**
     * @param LoggerInterface $logger The underlying PSR-3 compliant logger to which messages will be proxied
     */
    public function __construct(LoggerInterface $logger, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->logger = $logger;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if (!$this->isHandling($record)) {
            return false;
        }
        if ($this->formatter) {
            $formatted = $this->formatter->format($record);
            $this->logger->log(strtolower($record['level_name']), (string) $formatted, $record['context']);
        } else {
            $this->logger->log(strtolower($record['level_name']), $record['message'], $record['context']);
        }
        return false === $this->bubble;
    }
    /**
     * Sets the formatter.
     *
     * @param FormatterInterface $formatter
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * Gets the formatter.
     *
     * @return FormatterInterface
     */
    public function getFormatter() : FormatterInterface
    {
        if (!$this->formatter) {
            throw new \LogicException('No formatter has been set and this handler does not have a default formatter');
        }
        return $this->formatter;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Logger;
/**
 * Handler sending logs to Zend Monitor
 *
 * @author  Christian Bergau <cbergau86@gmail.com>
 * @author  Jason Davis <happydude@jasondavis.net>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class ZendMonitorHandler extends AbstractProcessingHandler
{
    /**
     * Monolog level / ZendMonitor Custom Event priority map
     *
     * @var array<int, int>
     */
    protected $levelMap = [];
    /**
     * @throws MissingExtensionException
     */
    public function __construct($level = Logger::DEBUG, bool $bubble = true)
    {
        if (!function_exists('zend_monitor_custom_event')) {
            throw new MissingExtensionException('You must have Zend Server installed with Zend Monitor enabled in order to use this handler');
        }
        //zend monitor constants are not defined if zend monitor is not enabled.
        $this->levelMap = [Logger::DEBUG => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::INFO => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::NOTICE => \ZEND_MONITOR_EVENT_SEVERITY_INFO, Logger::WARNING => \ZEND_MONITOR_EVENT_SEVERITY_WARNING, Logger::ERROR => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::CRITICAL => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::ALERT => \ZEND_MONITOR_EVENT_SEVERITY_ERROR, Logger::EMERGENCY => \ZEND_MONITOR_EVENT_SEVERITY_ERROR];
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->writeZendMonitorCustomEvent(Logger::getLevelName($record['level']), $record['message'], $record['formatted'], $this->levelMap[$record['level']]);
    }
    /**
     * Write to Zend Monitor Events
     * @param string $type Text displayed in "Class Name (custom)" field
     * @param string $message Text displayed in "Error String"
     * @param array $formatted Displayed in Custom Variables tab
     * @param int $severity Set the event severity level (-1,0,1)
     *
     * @phpstan-param FormattedRecord $formatted
     */
    protected function writeZendMonitorCustomEvent(string $type, string $message, array $formatted, int $severity) : void
    {
        zend_monitor_custom_event($type, $message, $formatted, $severity);
    }
    /**
     * {@inheritDoc}
     */
    public function getDefaultFormatter() : FormatterInterface
    {
        return new NormalizerFormatter();
    }
    /**
     * @return array<int, int>
     */
    public function getLevelMap() : array
    {
        return $this->levelMap;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
/**
 * Interface to describe loggers that have a formatter
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
interface FormattableHandlerInterface
{
    /**
     * Sets the formatter.
     *
     * @param FormatterInterface $formatter
     * @return HandlerInterface self
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface;
    /**
     * Gets the formatter.
     *
     * @return FormatterInterface
     */
    public function getFormatter() : FormatterInterface;
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\FingersCrossed;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Error level based activation strategy.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class ErrorLevelActivationStrategy implements ActivationStrategyInterface
{
    /**
     * @var Level
     */
    private $actionLevel;
    /**
     * @param (int | string) $actionLevel Level or name or value
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $actionLevel
     */
    public function __construct($actionLevel)
    {
        $this->actionLevel = Logger::toMonologLevel($actionLevel);
    }
    /**
     *
     */
    public function isHandlerActivated(array $record) : bool
    {
        return $record['level'] >= $this->actionLevel;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\FingersCrossed;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Channel and Error level based monolog activation strategy. Allows to trigger activation
 * based on level per channel. e.g. trigger activation on level 'ERROR' by default, except
 * for records of the 'sql' channel; those should trigger activation on level 'WARN'.
 *
 * Example:
 *
 * <code>
 *   $activationStrategy = new ChannelLevelActivationStrategy(
 *       Logger::CRITICAL,
 *       array(
 *           'request' => Logger::ALERT,
 *           'sensitive' => Logger::ERROR,
 *       )
 *   );
 *   $handler = new FingersCrossedHandler(new StreamHandler('php://stderr'), $activationStrategy);
 * </code>
 *
 * @author Mike Meessen <netmikey@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class ChannelLevelActivationStrategy implements ActivationStrategyInterface
{
    /**
     * @var Level
     */
    private $defaultActionLevel;
    /**
     * @var array<string, Level>
     */
    private $channelToActionLevel;
    /**
     * @param (int | string) $defaultActionLevel The default action level to be used if the record's category doesn't match any
     * @param array<string, int> $channelToActionLevel An array that maps channel names to action levels.
     *
     * @phpstan-param array<string, Level> $channelToActionLevel
     * @phpstan-param (Level | LevelName | LogLevel::*) $defaultActionLevel
     */
    public function __construct($defaultActionLevel, array $channelToActionLevel = [])
    {
        $this->defaultActionLevel = Logger::toMonologLevel($defaultActionLevel);
        $this->channelToActionLevel = array_map('Monolog\\Logger::toMonologLevel', $channelToActionLevel);
    }
    /**
     * @phpstan-param Record $record
     */
    public function isHandlerActivated(array $record) : bool
    {
        if (isset($this->channelToActionLevel[$record['channel']])) {
            return $record['level'] >= $this->channelToActionLevel[$record['channel']];
        }
        return $record['level'] >= $this->defaultActionLevel;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\FingersCrossed;

/**
 * Interface for activation strategies for the FingersCrossedHandler.
 *
 * @author Johannes M. Schmitt <schmittjoh@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
interface ActivationStrategyInterface
{
    /**
     * Returns whether the given record activates the handler.
     *
     * @phpstan-param Record $record
     */
    public function isHandlerActivated(array $record) : bool;
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Used for testing purposes.
 *
 * It records all records and gives you access to them for verification.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @method bool hasEmergency($record)
 * @method bool hasAlert($record)
 * @method bool hasCritical($record)
 * @method bool hasError($record)
 * @method bool hasWarning($record)
 * @method bool hasNotice($record)
 * @method bool hasInfo($record)
 * @method bool hasDebug($record)
 *
 * @method bool hasEmergencyRecords()
 * @method bool hasAlertRecords()
 * @method bool hasCriticalRecords()
 * @method bool hasErrorRecords()
 * @method bool hasWarningRecords()
 * @method bool hasNoticeRecords()
 * @method bool hasInfoRecords()
 * @method bool hasDebugRecords()
 *
 * @method bool hasEmergencyThatContains($message)
 * @method bool hasAlertThatContains($message)
 * @method bool hasCriticalThatContains($message)
 * @method bool hasErrorThatContains($message)
 * @method bool hasWarningThatContains($message)
 * @method bool hasNoticeThatContains($message)
 * @method bool hasInfoThatContains($message)
 * @method bool hasDebugThatContains($message)
 *
 * @method bool hasEmergencyThatMatches($message)
 * @method bool hasAlertThatMatches($message)
 * @method bool hasCriticalThatMatches($message)
 * @method bool hasErrorThatMatches($message)
 * @method bool hasWarningThatMatches($message)
 * @method bool hasNoticeThatMatches($message)
 * @method bool hasInfoThatMatches($message)
 * @method bool hasDebugThatMatches($message)
 *
 * @method bool hasEmergencyThatPasses($message)
 * @method bool hasAlertThatPasses($message)
 * @method bool hasCriticalThatPasses($message)
 * @method bool hasErrorThatPasses($message)
 * @method bool hasWarningThatPasses($message)
 * @method bool hasNoticeThatPasses($message)
 * @method bool hasInfoThatPasses($message)
 * @method bool hasDebugThatPasses($message)
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class TestHandler extends AbstractProcessingHandler
{
    /** @var Record[] */
    protected $records = [];
    /** @var array<Level, Record[]> */
    protected $recordsByLevel = [];
    /** @var bool */
    private $skipReset = false;
    /**
     * @return array
     *
     * @phpstan-return Record[]
     */
    public function getRecords()
    {
        return $this->records;
    }
    /**
     * @return void
     */
    public function clear()
    {
        $this->records = [];
        $this->recordsByLevel = [];
    }
    /**
     * @return void
     */
    public function reset()
    {
        if (!$this->skipReset) {
            $this->clear();
        }
    }
    /**
     * @return void
     */
    public function setSkipReset(bool $skipReset)
    {
        $this->skipReset = $skipReset;
    }
    /**
     * @param (string | int) $level Logging level value or name
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecords($level) : bool
    {
        return isset($this->recordsByLevel[Logger::toMonologLevel($level)]);
    }
    /**
     * @param (string | array) $record Either a message string or an array containing message and optionally context keys that will be checked against all records
     * @param (string | int) $level Logging level value or name
     *
     * @phpstan-param (array{message: string, context?: mixed[]} | string) $record
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecord($record, $level) : bool
    {
        if (is_string($record)) {
            $record = array('message' => $record);
        }
        return $this->hasRecordThatPasses(function ($rec) use($record) {
            if ($rec['message'] !== $record['message']) {
                return false;
            }
            if (isset($record['context']) && $rec['context'] !== $record['context']) {
                return false;
            }
            return true;
        }, $level);
    }
    /**
     * @param (string | int) $level Logging level value or name
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecordThatContains(string $message, $level) : bool
    {
        return $this->hasRecordThatPasses(function ($rec) use($message) {
            return strpos($rec['message'], $message) !== false;
        }, $level);
    }
    /**
     * @param (string | int) $level Logging level value or name
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecordThatMatches(string $regex, $level) : bool
    {
        return $this->hasRecordThatPasses(function (array $rec) use($regex) : bool {
            return preg_match($regex, $rec['message']) > 0;
        }, $level);
    }
    /**
     * @param (string | int) $level Logging level value or name
     * @return bool
     *
     * @psalm-param callable(Record , int ): mixed $predicate
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function hasRecordThatPasses(callable $predicate, $level)
    {
        $level = Logger::toMonologLevel($level);
        if (!isset($this->recordsByLevel[$level])) {
            return false;
        }
        foreach ($this->recordsByLevel[$level] as $i => $rec) {
            if ($predicate($rec, $i)) {
                return true;
            }
        }
        return false;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->recordsByLevel[$record['level']][] = $record;
        $this->records[] = $record;
    }
    /**
     * @param string $method
     * @param mixed[] $args
     * @return bool
     */
    public function __call($method, $args)
    {
        if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) {
            $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3];
            $level = constant('Monolog\\Logger::' . strtoupper($matches[2]));
            $callback = [$this, $genericMethod];
            if (is_callable($callback)) {
                $args[] = $level;
                return call_user_func_array($callback, $args);
            }
        }
        throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
/**
 * Helper trait for implementing FormattableInterface
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
trait FormattableHandlerTrait
{
    /**
     * @var ?FormatterInterface
     */
    protected $formatter;
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        if (!$this->formatter) {
            $this->formatter = $this->getDefaultFormatter();
        }
        return $this->formatter;
    }
    /**
     * Gets the default formatter.
     *
     * Overwrite this if the LineFormatter is not a good default for your handler.
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
use Psr\Log\LogLevel;
/**
 * Simple handler wrapper that filters records based on a list of levels
 *
 * It can be configured with an exact list of levels to allow, or a min/max level.
 *
 * @author Hennadiy Verkh
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class FilterHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * Handler or factory callable($record, $this)
     *
     * @var callable|HandlerInterface
     * @phpstan-var callable(?Record, HandlerInterface): HandlerInterface|HandlerInterface
     */
    protected $handler;
    /**
     * Minimum level for logs that are passed to handler
     *
     * @var int[]
     * @phpstan-var array<Level, int>
     */
    protected $acceptedLevels;
    /**
     * Whether the messages that are handled can bubble up the stack or not
     *
     * @var bool
     */
    protected $bubble;
    /**
     * @psalm-param (HandlerInterface | callable(?Record , HandlerInterface ): HandlerInterface) $handler
     *
     * @param (callable | HandlerInterface) $handler Handler or factory callable($record|null, $filterHandler).
     * @param (int | array) $minLevelOrList A list of levels to accept or a minimum level if maxLevel is provided
     * @param (int | string) $maxLevel Maximum level to accept, only used if $minLevelOrList is not an array
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param (Level | LevelName | LogLevel::* | array<(Level | LevelName | LogLevel::*)>) $minLevelOrList
     * @phpstan-param (Level | LevelName | LogLevel::*) $maxLevel
     */
    public function __construct($handler, $minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY, bool $bubble = true)
    {
        $this->handler = $handler;
        $this->bubble = $bubble;
        $this->setAcceptedLevels($minLevelOrList, $maxLevel);
        if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
            throw new \RuntimeException("The given handler (" . json_encode($this->handler) . ") is not a callable nor a Monolog\\Handler\\HandlerInterface object");
        }
    }
    /**
     * @phpstan-return array<int, Level>
     */
    public function getAcceptedLevels() : array
    {
        return array_flip($this->acceptedLevels);
    }
    /**
     * @param (int | string | array) $minLevelOrList A list of levels to accept or a minimum level or level name if maxLevel is provided
     * @param (int | string) $maxLevel Maximum level or level name to accept, only used if $minLevelOrList is not an array
     *
     * @phpstan-param (Level | LevelName | LogLevel::* | array<(Level | LevelName | LogLevel::*)>) $minLevelOrList
     * @phpstan-param (Level | LevelName | LogLevel::*) $maxLevel
     */
    public function setAcceptedLevels($minLevelOrList = Logger::DEBUG, $maxLevel = Logger::EMERGENCY) : self
    {
        if (is_array($minLevelOrList)) {
            $acceptedLevels = array_map('Monolog\\Logger::toMonologLevel', $minLevelOrList);
        } else {
            $minLevelOrList = Logger::toMonologLevel($minLevelOrList);
            $maxLevel = Logger::toMonologLevel($maxLevel);
            $acceptedLevels = array_values(array_filter(Logger::getLevels(), function ($level) use($minLevelOrList, $maxLevel) {
                return $level >= $minLevelOrList && $level <= $maxLevel;
            }));
        }
        $this->acceptedLevels = array_flip($acceptedLevels);
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return isset($this->acceptedLevels[$record['level']]);
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if (!$this->isHandling($record)) {
            return false;
        }
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        $this->getHandler($record)->handle($record);
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $filtered = [];
        foreach ($records as $record) {
            if ($this->isHandling($record)) {
                $filtered[] = $record;
            }
        }
        if (count($filtered) > 0) {
            $this->getHandler($filtered[count($filtered) - 1])->handleBatch($filtered);
        }
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory callable, this will trigger the handler's instantiation.
     *
     * @return HandlerInterface
     *
     * @phpstan-param Record $record
     */
    public function getHandler(array $record = null)
    {
        if (!$this->handler instanceof HandlerInterface) {
            $this->handler = ($this->handler)($record, $this);
            if (!$this->handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory callable should return a HandlerInterface");
            }
        }
        return $this->handler;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
    /**
     *
     */
    public function reset()
    {
        $this->resetProcessors();
        if ($this->getHandler() instanceof ResettableInterface) {
            $this->getHandler()->reset();
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * Logs to syslog service.
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $syslog = new SyslogHandler('myfacility', 'local6');
 *   $formatter = new LineFormatter("%channel%.%level_name%: %message% %extra%");
 *   $syslog->setFormatter($formatter);
 *   $log->pushHandler($syslog);
 *
 * @author Sven Paulus <sven@karlsruhe.org>
 */
class SyslogHandler extends AbstractSyslogHandler
{
    /** @var string */
    protected $ident;
    /** @var int */
    protected $logopts;
    /**
     * @param string $ident
     * @param (string | int) $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     * @param int $logopts Option flags for the openlog() call, defaults to LOG_PID
     */
    public function __construct(string $ident, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, int $logopts = LOG_PID)
    {
        parent::__construct($facility, $level, $bubble);
        $this->ident = $ident;
        $this->logopts = $logopts;
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        closelog();
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!openlog($this->ident, $this->logopts, $this->facility)) {
            throw new \LogicException('Can\'t open syslog for ident "' . $this->ident . '" and facility "' . $this->facility . '"');
        }
        syslog($this->logLevels[$record['level']], (string) $record['formatted']);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use InvalidArgumentException;
use Monolog\Logger;
use Monolog\Utils;
/**
 * Stores logs to files that are rotated every day and a limited number of files are kept.
 *
 * This rotation is only intended to be used as a workaround. Using logrotate to
 * handle the rotation is strongly encouraged when you can use it.
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class RotatingFileHandler extends StreamHandler
{
    public const FILE_PER_DAY = 'Y-m-d';
    public const FILE_PER_MONTH = 'Y-m';
    public const FILE_PER_YEAR = 'Y';
    /** @var string */
    protected $filename;
    /** @var int */
    protected $maxFiles;
    /** @var bool */
    protected $mustRotate;
    /** @var \DateTimeImmutable */
    protected $nextRotation;
    /** @var string */
    protected $filenameFormat;
    /** @var string */
    protected $dateFormat;
    /**
     * @param string $filename
     * @param int $maxFiles The maximal amount of files to keep (0 means unlimited)
     * @param (int | null) $filePermission Optional file permissions (default (0644) are only for owner read/write)
     * @param bool $useLocking Try to lock log file before doing any writes
     */
    public function __construct(string $filename, int $maxFiles = 0, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false)
    {
        $this->filename = Utils::canonicalizePath($filename);
        $this->maxFiles = $maxFiles;
        $this->nextRotation = new \DateTimeImmutable('tomorrow');
        $this->filenameFormat = '{filename}-{date}';
        $this->dateFormat = static::FILE_PER_DAY;
        parent::__construct($this->getTimedFilename(), $level, $bubble, $filePermission, $useLocking);
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        parent::close();
        if (true === $this->mustRotate) {
            $this->rotate();
        }
    }
    /**
     * {@inheritDoc}
     */
    public function reset()
    {
        parent::reset();
        if (true === $this->mustRotate) {
            $this->rotate();
        }
    }
    /**
     *
     */
    public function setFilenameFormat(string $filenameFormat, string $dateFormat) : self
    {
        if (!preg_match('{^[Yy](([/_.-]?m)([/_.-]?d)?)?$}', $dateFormat)) {
            throw new InvalidArgumentException('Invalid date format - format must be one of RotatingFileHandler::FILE_PER_DAY ("Y-m-d"), RotatingFileHandler::FILE_PER_MONTH ("Y-m") or RotatingFileHandler::FILE_PER_YEAR ("Y"), or you can set one of the date formats using slashes, underscores and/or dots instead of dashes.');
        }
        if (\Phabel\Target\Php80\Polyfill::substr_count($filenameFormat, '{date}') === 0) {
            throw new InvalidArgumentException('Invalid filename format - format must contain at least `{date}`, because otherwise rotating is impossible.');
        }
        $this->filenameFormat = $filenameFormat;
        $this->dateFormat = $dateFormat;
        $this->url = $this->getTimedFilename();
        $this->close();
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        // on the first record written, if the log is new, we should rotate (once per day)
        if (null === $this->mustRotate) {
            $this->mustRotate = null === $this->url || !file_exists($this->url);
        }
        if ($this->nextRotation <= $record['datetime']) {
            $this->mustRotate = true;
            $this->close();
        }
        parent::write($record);
    }
    /**
     * Rotates the files.
     */
    protected function rotate() : void
    {
        // update filename
        $this->url = $this->getTimedFilename();
        $this->nextRotation = new \DateTimeImmutable('tomorrow');
        // skip GC of old logs if files are unlimited
        if (0 === $this->maxFiles) {
            return;
        }
        $logFiles = glob($this->getGlobPattern());
        if (false === $logFiles) {
            // failed to glob
            return;
        }
        if ($this->maxFiles >= count($logFiles)) {
            // no files to remove
            return;
        }
        // Sorting the files by name to remove the older ones
        usort($logFiles, function ($a, $b) {
            return strcmp($b, $a);
        });
        foreach (array_slice($logFiles, $this->maxFiles) as $file) {
            if (is_writable($file)) {
                // suppress errors here as unlink() might fail if two processes
                // are cleaning up/rotating at the same time
                set_error_handler(function (int $errno, string $errstr, string $errfile, int $errline) : bool {
                    return false;
                });
                unlink($file);
                restore_error_handler();
            }
        }
        $this->mustRotate = false;
    }
    /**
     *
     */
    protected function getTimedFilename() : string
    {
        $fileInfo = pathinfo($this->filename);
        $timedFilename = str_replace(['{filename}', '{date}'], [$fileInfo['filename'], \Phabel\Target\Php80\Polyfill::date($this->dateFormat)], $fileInfo['dirname'] . '/' . $this->filenameFormat);
        if (isset($fileInfo['extension'])) {
            $timedFilename .= '.' . $fileInfo['extension'];
        }
        return $timedFilename;
    }
    /**
     *
     */
    protected function getGlobPattern() : string
    {
        $fileInfo = pathinfo($this->filename);
        $glob = str_replace(['{filename}', '{date}'], [$fileInfo['filename'], '[0-9][0-9][0-9][0-9]*'], $fileInfo['dirname'] . '/' . $this->filenameFormat);
        if (isset($fileInfo['extension'])) {
            $glob .= '.' . $fileInfo['extension'];
        }
        return $glob;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\ResettableInterface;
use Monolog\Processor\ProcessorInterface;
/**
 * Helper trait for implementing ProcessableInterface
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
trait ProcessableHandlerTrait
{
    /**
     * @var callable[]
     * @phpstan-var array<ProcessorInterface|callable(Record): Record>
     */
    protected $processors = [];
    /**
     * {@inheritDoc}
     */
    public function pushProcessor(callable $callback) : HandlerInterface
    {
        array_unshift($this->processors, $callback);
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function popProcessor() : callable
    {
        if (!$this->processors) {
            throw new \LogicException('You tried to pop from an empty processor stack.');
        }
        return array_shift($this->processors);
    }
    /**
     * Processes a record.
     *
     * @phpstan-param Record $record
     * @phpstan-return Record
     */
    protected function processRecord(array $record) : array
    {
        foreach ($this->processors as $processor) {
            $record = $processor($record);
        }
        return $record;
    }
    /**
     *
     */
    protected function resetProcessors() : void
    {
        foreach ($this->processors as $processor) {
            if ($processor instanceof ResettableInterface) {
                $processor->reset();
            }
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
use PhpConsole\Connector;
use PhpConsole\Handler as VendorPhpConsoleHandler;
use PhpConsole\Helper;
/**
 * Monolog handler for Google Chrome extension "PHP Console"
 *
 * Display PHP error/debug log messages in Google Chrome console and notification popups, executes PHP code remotely
 *
 * Usage:
 * 1. Install Google Chrome extension https://chrome.google.com/webstore/detail/php-console/nfhmhhlpfleoednkpnnnkolmclajemef
 * 2. See overview https://github.com/barbushin/php-console#overview
 * 3. Install PHP Console library https://github.com/barbushin/php-console#installation
 * 4. Example (result will looks like http://i.hizliresim.com/vg3Pz4.png)
 *
 *      $logger = new \Monolog\Logger('all', array(new \Monolog\Handler\PHPConsoleHandler()));
 *      \Monolog\ErrorHandler::register($logger);
 *      echo $undefinedVar;
 *      $logger->debug('SELECT * FROM users', array('db', 'time' => 0.012));
 *      PC::debug($_SERVER); // PHP Console debugger for any type of vars
 *
 * @author Sergey Barbushin https://www.linkedin.com/in/barbushin
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class PHPConsoleHandler extends AbstractProcessingHandler
{
    /** @var array<string, mixed> */
    private $options = [
        'enabled' => true,
        // bool Is PHP Console server enabled
        'classesPartialsTraceIgnore' => ['Monolog\\'],
        // array Hide calls of classes started with...
        'debugTagsKeysInContext' => [0, 'tag'],
        // bool Is PHP Console server enabled
        'useOwnErrorsHandler' => false,
        // bool Enable errors handling
        'useOwnExceptionsHandler' => false,
        // bool Enable exceptions handling
        'sourcesBasePath' => null,
        // string Base path of all project sources to strip in errors source paths
        'registerHelper' => true,
        // bool Register PhpConsole\Helper that allows short debug calls like PC::debug($var, 'ta.g.s')
        'serverEncoding' => null,
        // string|null Server internal encoding
        'headersLimit' => null,
        // int|null Set headers size limit for your web-server
        'password' => null,
        // string|null Protect PHP Console connection by password
        'enableSslOnlyMode' => false,
        // bool Force connection by SSL for clients with PHP Console installed
        'ipMasks' => [],
        // array Set IP masks of clients that will be allowed to connect to PHP Console: array('192.168.*.*', '127.0.0.1')
        'enableEvalListener' => false,
        // bool Enable eval request to be handled by eval dispatcher(if enabled, 'password' option is also required)
        'dumperDetectCallbacks' => false,
        // bool Convert callback items in dumper vars to (callback SomeClass::someMethod) strings
        'dumperLevelLimit' => 5,
        // int Maximum dumped vars array or object nested dump level
        'dumperItemsCountLimit' => 100,
        // int Maximum dumped var same level array items or object properties number
        'dumperItemSizeLimit' => 5000,
        // int Maximum length of any string or dumped array item
        'dumperDumpSizeLimit' => 500000,
        // int Maximum approximate size of dumped vars result formatted in JSON
        'detectDumpTraceAndSource' => false,
        // bool Autodetect and append trace data to debug
        'dataStorage' => null,
    ];
    /** @var Connector */
    private $connector;
    /**
     * @param array<string, mixed> $options See \Monolog\Handler\PHPConsoleHandler::$options for more details
     * @param (Connector | null) $connector Instance of \PhpConsole\Connector class (optional)
     * @throws \RuntimeException
     */
    public function __construct(array $options = [], ?Connector $connector = null, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!class_exists('PhpConsole\\Connector')) {
            throw new \RuntimeException('PHP Console library not found. See https://github.com/barbushin/php-console#installation');
        }
        parent::__construct($level, $bubble);
        $this->options = $this->initOptions($options);
        $this->connector = $this->initConnector($connector);
    }
    /**
     * @param array<string, mixed> $options
     *
     * @return array<string, mixed>
     */
    private function initOptions(array $options) : array
    {
        $wrongOptions = array_diff(array_keys($options), array_keys($this->options));
        if ($wrongOptions) {
            throw new \RuntimeException('Unknown options: ' . implode(', ', $wrongOptions));
        }
        return array_replace($this->options, $options);
    }
    /**
     *
     */
    private function initConnector(?Connector $connector = null) : Connector
    {
        if (!$connector) {
            if ($this->options['dataStorage']) {
                Connector::setPostponeStorage($this->options['dataStorage']);
            }
            $connector = Connector::getInstance();
        }
        if ($this->options['registerHelper'] && !Helper::isRegistered()) {
            Helper::register();
        }
        if ($this->options['enabled'] && $connector->isActiveClient()) {
            if ($this->options['useOwnErrorsHandler'] || $this->options['useOwnExceptionsHandler']) {
                $handler = VendorPhpConsoleHandler::getInstance();
                $handler->setHandleErrors($this->options['useOwnErrorsHandler']);
                $handler->setHandleExceptions($this->options['useOwnExceptionsHandler']);
                $handler->start();
            }
            if ($this->options['sourcesBasePath']) {
                $connector->setSourcesBasePath($this->options['sourcesBasePath']);
            }
            if ($this->options['serverEncoding']) {
                $connector->setServerEncoding($this->options['serverEncoding']);
            }
            if ($this->options['password']) {
                $connector->setPassword($this->options['password']);
            }
            if ($this->options['enableSslOnlyMode']) {
                $connector->enableSslOnlyMode();
            }
            if ($this->options['ipMasks']) {
                $connector->setAllowedIpMasks($this->options['ipMasks']);
            }
            if ($this->options['headersLimit']) {
                $connector->setHeadersLimit($this->options['headersLimit']);
            }
            if ($this->options['detectDumpTraceAndSource']) {
                $connector->getDebugDispatcher()->detectTraceAndSource = true;
            }
            $dumper = $connector->getDumper();
            $dumper->levelLimit = $this->options['dumperLevelLimit'];
            $dumper->itemsCountLimit = $this->options['dumperItemsCountLimit'];
            $dumper->itemSizeLimit = $this->options['dumperItemSizeLimit'];
            $dumper->dumpSizeLimit = $this->options['dumperDumpSizeLimit'];
            $dumper->detectCallbacks = $this->options['dumperDetectCallbacks'];
            if ($this->options['enableEvalListener']) {
                $connector->startEvalRequestsListener();
            }
        }
        return $connector;
    }
    /**
     *
     */
    public function getConnector() : Connector
    {
        return $this->connector;
    }
    /**
     * @return array<string, mixed>
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     *
     */
    public function handle(array $record) : bool
    {
        if ($this->options['enabled'] && $this->connector->isActiveClient()) {
            return parent::handle($record);
        }
        return !$this->bubble;
    }
    /**
     * Writes the record down to the log of the implementing handler
     */
    protected function write(array $record) : void
    {
        if ($record['level'] < Logger::NOTICE) {
            $this->handleDebugRecord($record);
        } elseif (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
            $this->handleExceptionRecord($record);
        } else {
            $this->handleErrorRecord($record);
        }
    }
    /**
     * @phpstan-param Record $record
     */
    private function handleDebugRecord(array $record) : void
    {
        $tags = $this->getRecordTags($record);
        $message = $record['message'];
        if ($record['context']) {
            $message .= ' ' . Utils::jsonEncode($this->connector->getDumper()->dump(array_filter($record['context'])), null, true);
        }
        $this->connector->getDebugDispatcher()->dispatchDebug($message, $tags, $this->options['classesPartialsTraceIgnore']);
    }
    /**
     * @phpstan-param Record $record
     */
    private function handleExceptionRecord(array $record) : void
    {
        $this->connector->getErrorsDispatcher()->dispatchException($record['context']['exception']);
    }
    /**
     * @phpstan-param Record $record
     */
    private function handleErrorRecord(array $record) : void
    {
        $context = $record['context'];
        $this->connector->getErrorsDispatcher()->dispatchError($context['code'] ?? null, $context['message'] ?? $record['message'], $context['file'] ?? null, $context['line'] ?? null, $this->options['classesPartialsTraceIgnore']);
    }
    /**
     * @phpstan-param Record $record
     * @return string
     */
    private function getRecordTags(array &$record)
    {
        $tags = null;
        if (!empty($record['context'])) {
            $context =& $record['context'];
            foreach ($this->options['debugTagsKeysInContext'] as $key) {
                if (!empty($context[$key])) {
                    $tags = $context[$key];
                    if ($key === 0) {
                        array_shift($context);
                    } else {
                        unset($context[$key]);
                    }
                    break;
                }
            }
        }
        return $tags ?: strtolower($record['level_name']);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter('%message%');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * Stores to any socket - uses fsockopen() or pfsockopen().
 *
 * @author Pablo de Leon Belloc <pablolb@gmail.com>
 * @see    http://php.net/manual/en/function.fsockopen.php
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class SocketHandler extends AbstractProcessingHandler
{
    /** @var string */
    private $connectionString;
    /** @var float */
    private $connectionTimeout;
    /** @var resource|null */
    private $resource;
    /** @var float */
    private $timeout = 0.0;
    /** @var float */
    private $writingTimeout = 10.0;
    /** @var ?int */
    private $lastSentBytes = null;
    /** @var ?int */
    private $chunkSize = null;
    /** @var bool */
    private $persistent = false;
    /** @var ?int */
    private $errno = null;
    /** @var ?string */
    private $errstr = null;
    /** @var ?float */
    private $lastWritingAt = null;
    /**
     * @param string $connectionString Socket connection string
     */
    public function __construct(string $connectionString, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->connectionString = $connectionString;
        $this->connectionTimeout = (float) ini_get('default_socket_timeout');
    }
    /**
     * Connect (if necessary) and write to the socket
     *
     * {@inheritDoc}
     *
     * @throws \UnexpectedValueException
     * @throws \RuntimeException
     */
    protected function write(array $record) : void
    {
        $this->connectIfNotConnected();
        $data = $this->generateDataStream($record);
        $this->writeToSocket($data);
    }
    /**
     * We will not close a PersistentSocket instance so it can be reused in other requests.
     */
    public function close() : void
    {
        if (!$this->isPersistent()) {
            $this->closeSocket();
        }
    }
    /**
     * Close socket, if open
     */
    public function closeSocket() : void
    {
        if (is_resource($this->resource)) {
            fclose($this->resource);
            $this->resource = null;
        }
    }
    /**
     * Set socket connection to be persistent. It only has effect before the connection is initiated.
     */
    public function setPersistent(bool $persistent) : self
    {
        $this->persistent = $persistent;
        return $this;
    }
    /**
     * Set connection timeout.  Only has effect before we connect.
     *
     * @see http://php.net/manual/en/function.fsockopen.php
     */
    public function setConnectionTimeout(float $seconds) : self
    {
        $this->validateTimeout($seconds);
        $this->connectionTimeout = $seconds;
        return $this;
    }
    /**
     * Set write timeout. Only has effect before we connect.
     *
     * @see http://php.net/manual/en/function.stream-set-timeout.php
     */
    public function setTimeout(float $seconds) : self
    {
        $this->validateTimeout($seconds);
        $this->timeout = $seconds;
        return $this;
    }
    /**
     * Set writing timeout. Only has effect during connection in the writing cycle.
     *
     * @param float $seconds 0 for no timeout
     */
    public function setWritingTimeout(float $seconds) : self
    {
        $this->validateTimeout($seconds);
        $this->writingTimeout = $seconds;
        return $this;
    }
    /**
     * Set chunk size. Only has effect during connection in the writing cycle.
     */
    public function setChunkSize(int $bytes) : self
    {
        $this->chunkSize = $bytes;
        return $this;
    }
    /**
     * Get current connection string
     */
    public function getConnectionString() : string
    {
        return $this->connectionString;
    }
    /**
     * Get persistent setting
     */
    public function isPersistent() : bool
    {
        return $this->persistent;
    }
    /**
     * Get current connection timeout setting
     */
    public function getConnectionTimeout() : float
    {
        return $this->connectionTimeout;
    }
    /**
     * Get current in-transfer timeout
     */
    public function getTimeout() : float
    {
        return $this->timeout;
    }
    /**
     * Get current local writing timeout
     *
     * @return float
     */
    public function getWritingTimeout() : float
    {
        return $this->writingTimeout;
    }
    /**
     * Get current chunk size
     */
    public function getChunkSize() : ?int
    {
        return $this->chunkSize;
    }
    /**
     * Check to see if the socket is currently available.
     *
     * UDP might appear to be connected but might fail when writing.  See http://php.net/fsockopen for details.
     */
    public function isConnected() : bool
    {
        return is_resource($this->resource) && !feof($this->resource);
        // on TCP - other party can close connection.
    }
    /**
     * Wrapper to allow mocking
     *
     * @return (resource | false)
     */
    protected function pfsockopen()
    {
        return @pfsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return (resource | false)
     */
    protected function fsockopen()
    {
        return @\Phabel\Target\Php80\Polyfill::fsockopen($this->connectionString, -1, $this->errno, $this->errstr, $this->connectionTimeout);
    }
    /**
     * Wrapper to allow mocking
     *
     * @see http://php.net/manual/en/function.stream-set-timeout.php
     *
     * @return bool
     */
    protected function streamSetTimeout()
    {
        $seconds = floor($this->timeout);
        $microseconds = round(($this->timeout - $seconds) * 1000000.0);
        if (!is_resource($this->resource)) {
            throw new \LogicException('streamSetTimeout called but $this->resource is not a resource');
        }
        return stream_set_timeout($this->resource, (int) $seconds, (int) $microseconds);
    }
    /**
     * Wrapper to allow mocking
     *
     * @see http://php.net/manual/en/function.stream-set-chunk-size.php
     *
     * @return (int | bool)
     */
    protected function streamSetChunkSize()
    {
        if (!is_resource($this->resource)) {
            throw new \LogicException('streamSetChunkSize called but $this->resource is not a resource');
        }
        if (null === $this->chunkSize) {
            throw new \LogicException('streamSetChunkSize called but $this->chunkSize is not set');
        }
        return stream_set_chunk_size($this->resource, $this->chunkSize);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return (int | bool)
     */
    protected function fwrite(string $data)
    {
        if (!is_resource($this->resource)) {
            throw new \LogicException('fwrite called but $this->resource is not a resource');
        }
        return @fwrite($this->resource, $data);
    }
    /**
     * Wrapper to allow mocking
     *
     * @return (mixed[] | bool)
     */
    protected function streamGetMetadata()
    {
        if (!is_resource($this->resource)) {
            throw new \LogicException('streamGetMetadata called but $this->resource is not a resource');
        }
        return stream_get_meta_data($this->resource);
    }
    /**
     *
     */
    private function validateTimeout(float $value) : void
    {
        if ($value < 0) {
            throw new \InvalidArgumentException("Timeout must be 0 or a positive float (got {$value})");
        }
    }
    /**
     *
     */
    private function connectIfNotConnected() : void
    {
        if ($this->isConnected()) {
            return;
        }
        $this->connect();
    }
    /**
     * @phpstan-param FormattedRecord $record
     */
    protected function generateDataStream(array $record) : string
    {
        return (string) $record['formatted'];
    }
    /**
     * @return (resource | null)
     */
    protected function getResource()
    {
        return $this->resource;
    }
    /**
     *
     */
    private function connect() : void
    {
        $this->createSocketResource();
        $this->setSocketTimeout();
        $this->setStreamChunkSize();
    }
    /**
     *
     */
    private function createSocketResource() : void
    {
        if ($this->isPersistent()) {
            $resource = $this->pfsockopen();
        } else {
            $resource = $this->fsockopen();
        }
        if (is_bool($resource)) {
            throw new \UnexpectedValueException("Failed connecting to {$this->connectionString} ({$this->errno}: {$this->errstr})");
        }
        $this->resource = $resource;
    }
    /**
     *
     */
    private function setSocketTimeout() : void
    {
        if (!$this->streamSetTimeout()) {
            throw new \UnexpectedValueException("Failed setting timeout with stream_set_timeout()");
        }
    }
    /**
     *
     */
    private function setStreamChunkSize() : void
    {
        if ($this->chunkSize && !$this->streamSetChunkSize()) {
            throw new \UnexpectedValueException("Failed setting chunk size with stream_set_chunk_size()");
        }
    }
    /**
     *
     */
    private function writeToSocket(string $data) : void
    {
        $length = strlen($data);
        $sent = 0;
        $this->lastSentBytes = $sent;
        while ($this->isConnected() && $sent < $length) {
            if (0 == $sent) {
                $chunk = $this->fwrite($data);
            } else {
                $chunk = $this->fwrite(\Phabel\Target\Php80\Polyfill::substr($data, $sent));
            }
            if ($chunk === false) {
                throw new \RuntimeException("Could not write to socket");
            }
            $sent += $chunk;
            $socketInfo = $this->streamGetMetadata();
            if (is_array($socketInfo) && $socketInfo['timed_out']) {
                throw new \RuntimeException("Write timed-out");
            }
            if ($this->writingIsTimedOut($sent)) {
                throw new \RuntimeException("Write timed-out, no data sent for `{$this->writingTimeout}` seconds, probably we got disconnected (sent {$sent} of {$length})");
            }
        }
        if (!$this->isConnected() && $sent < $length) {
            throw new \RuntimeException("End-of-file reached, probably we got disconnected (sent {$sent} of {$length})");
        }
    }
    /**
     *
     */
    private function writingIsTimedOut(int $sent) : bool
    {
        // convert to ms
        if (0.0 == $this->writingTimeout) {
            return false;
        }
        if ($sent !== $this->lastSentBytes) {
            $this->lastWritingAt = microtime(true);
            $this->lastSentBytes = $sent;
            return false;
        } else {
            usleep(100);
        }
        if (microtime(true) - $this->lastWritingAt >= $this->writingTimeout) {
            $this->closeSocket();
            return true;
        }
        return false;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use DateTimeInterface;
use Monolog\Logger;
use Monolog\Handler\SyslogUdp\UdpSocket;
use Monolog\Utils;
/**
 * A Handler for logging to a remote syslogd server.
 *
 * @author Jesper Skovgaard Nielsen <nulpunkt@gmail.com>
 * @author Dominik Kukacka <dominik.kukacka@gmail.com>
 */
class SyslogUdpHandler extends AbstractSyslogHandler
{
    const RFC3164 = 0;
    const RFC5424 = 1;
    const RFC5424e = 2;
    /** @var array<self::RFC*, string> */
    private $dateFormats = array(self::RFC3164 => 'M d H:i:s', self::RFC5424 => \DateTime::RFC3339, self::RFC5424e => \DateTime::RFC3339_EXTENDED);
    /** @var UdpSocket */
    protected $socket;
    /** @var string */
    protected $ident;
    /** @var self::RFC* */
    protected $rfc;
    /**
     * @param string $host Either IP/hostname or a path to a unix socket (port must be 0 then)
     * @param int $port Port number, or 0 if $host is a unix socket
     * @param (string | int) $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     * @param string $ident Program name or tag for each log message.
     * @param int $rfc RFC to format the message for.
     * @throws MissingExtensionException
     *
     * @phpstan-param self::RFC* $rfc
     */
    public function __construct(string $host, int $port = 514, $facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true, string $ident = 'php', int $rfc = self::RFC5424)
    {
        if (!extension_loaded('sockets')) {
            throw new MissingExtensionException('The sockets extension is required to use the SyslogUdpHandler');
        }
        parent::__construct($facility, $level, $bubble);
        $this->ident = $ident;
        $this->rfc = $rfc;
        $this->socket = new UdpSocket($host, $port);
    }
    /**
     *
     */
    protected function write(array $record) : void
    {
        $lines = $this->splitMessageIntoLines($record['formatted']);
        $header = $this->makeCommonSyslogHeader($this->logLevels[$record['level']], $record['datetime']);
        foreach ($lines as $line) {
            $this->socket->write($line, $header);
        }
    }
    /**
     *
     */
    public function close() : void
    {
        $this->socket->close();
    }
    /**
     * @param (string | string[]) $message
     * @return string[]
     */
    private function splitMessageIntoLines($message) : array
    {
        if (is_array($message)) {
            $message = implode("\n", $message);
        }
        $lines = preg_split('/$\\R?^/m', (string) $message, -1, PREG_SPLIT_NO_EMPTY);
        if (false === $lines) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Could not preg_split: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
        }
        return $lines;
    }
    /**
     * Make common syslog header (see rfc5424 or rfc3164)
     */
    protected function makeCommonSyslogHeader(int $severity, DateTimeInterface $datetime) : string
    {
        $priority = $severity + $this->facility;
        if (!($pid = getmypid())) {
            $pid = '-';
        }
        if (!($hostname = gethostname())) {
            $hostname = '-';
        }
        if ($this->rfc === self::RFC3164) {
            // see https://github.com/phpstan/phpstan/issues/5348
            // @phpstan-ignore-next-line
            $dateNew = $datetime->setTimezone(new \DateTimeZone('UTC'));
            $date = $dateNew->format($this->dateFormats[$this->rfc]);
            return "<{$priority}>" . $date . " " . $hostname . " " . $this->ident . "[" . $pid . "]: ";
        }
        $date = $datetime->format($this->dateFormats[$this->rfc]);
        return "<{$priority}>1 " . $date . " " . $hostname . " " . $this->ident . " " . $pid . " - - ";
    }
    /**
     * Inject your own socket, mainly used for testing
     */
    public function setSocket(UdpSocket $socket) : self
    {
        $this->socket = $socket;
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * Stores to STDIN of any process, specified by a command.
 *
 * Usage example:
 * <pre>
 * $log = new Logger('myLogger');
 * $log->pushHandler(new ProcessHandler('/usr/bin/php /var/www/monolog/someScript.php'));
 * </pre>
 *
 * @author Kolja Zuelsdorf <koljaz@web.de>
 */
class ProcessHandler extends AbstractProcessingHandler
{
    /**
     * Holds the process to receive data on its STDIN.
     *
     * @var resource|bool|null
     */
    private $process;
    /**
     * @var string
     */
    private $command;
    /**
     * @var string|null
     */
    private $cwd;
    /**
     * @var resource[]
     */
    private $pipes = [];
    /**
     * @var array<int, string[]>
     */
    protected const DESCRIPTOR_SPEC = [
        0 => ['pipe', 'r'],
        // STDIN is a pipe that the child will read from
        1 => ['pipe', 'w'],
        // STDOUT is a pipe that the child will write to
        2 => ['pipe', 'w'],
    ];
    /**
    * @param string $command Command for the process to start. Absolute paths are recommended,
    especially if you do not use the $cwd parameter.
    * @param (string | null) $cwd "Current working directory" (CWD) for the process to be executed in.
    * @throws \InvalidArgumentException
    */
    public function __construct(string $command, $level = Logger::DEBUG, bool $bubble = true, ?string $cwd = null)
    {
        if ($command === '') {
            throw new \InvalidArgumentException('The command argument must be a non-empty string.');
        }
        if ($cwd === '') {
            throw new \InvalidArgumentException('The optional CWD argument must be a non-empty string or null.');
        }
        parent::__construct($level, $bubble);
        $this->command = $command;
        $this->cwd = $cwd;
    }
    /**
     * Writes the record down to the log of the implementing handler
     *
     * @throws \UnexpectedValueException
     */
    protected function write(array $record) : void
    {
        $this->ensureProcessIsStarted();
        $this->writeProcessInput($record['formatted']);
        $errors = $this->readProcessErrors();
        if (empty($errors) === false) {
            throw new \UnexpectedValueException(sprintf('Errors while writing to process: %s', $errors));
        }
    }
    /**
    * Makes sure that the process is actually started, and if not, starts it,
    assigns the stream pipes, and handles startup errors, if any.
    */
    private function ensureProcessIsStarted() : void
    {
        if (is_resource($this->process) === false) {
            $this->startProcess();
            $this->handleStartupErrors();
        }
    }
    /**
     * Starts the actual process and sets all streams to non-blocking.
     */
    private function startProcess() : void
    {
        $this->process = proc_open($this->command, static::DESCRIPTOR_SPEC, $this->pipes, $this->cwd);
        foreach ($this->pipes as $pipe) {
            stream_set_blocking($pipe, false);
        }
    }
    /**
     * Selects the STDERR stream, handles upcoming startup errors, and throws an exception, if any.
     *
     * @throws \UnexpectedValueException
     */
    private function handleStartupErrors() : void
    {
        $selected = $this->selectErrorStream();
        if (false === $selected) {
            throw new \UnexpectedValueException('Something went wrong while selecting a stream.');
        }
        $errors = $this->readProcessErrors();
        if (is_resource($this->process) === false || empty($errors) === false) {
            throw new \UnexpectedValueException(sprintf('The process "%s" could not be opened: ' . $errors, $this->command));
        }
    }
    /**
     * Selects the STDERR stream.
     *
     * @return (int | bool)
     */
    protected function selectErrorStream()
    {
        $empty = [];
        $errorPipes = [$this->pipes[2]];
        return stream_select($errorPipes, $empty, $empty, 1);
    }
    /**
     * Reads the errors of the process, if there are any.
     *
     * @codeCoverageIgnore
     * @return string Empty string if there are no errors.
     */
    protected function readProcessErrors() : string
    {
        return (string) stream_get_contents($this->pipes[2]);
    }
    /**
     * Writes to the input stream of the opened process.
     *
     * @codeCoverageIgnore
     */
    protected function writeProcessInput(string $string) : void
    {
        fwrite($this->pipes[0], $string);
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        if (is_resource($this->process)) {
            foreach ($this->pipes as $pipe) {
                fclose($pipe);
            }
            proc_close($this->process);
            $this->process = null;
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * @author Robert Kaufmann III <rok3@rok3.me>
 */
class LogEntriesHandler extends SocketHandler
{
    /**
     * @var string
     */
    protected $logToken;
    /**
     * @param string $token Log token supplied by LogEntries
     * @param bool $useSSL Whether or not SSL encryption should be used.
     * @param string $host Custom hostname to send the data to if needed
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true, string $host = 'data.logentries.com')
    {
        if ($useSSL && !extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for LogEntriesHandler');
        }
        $endpoint = $useSSL ? 'ssl://' . $host . ':443' : $host . ':80';
        parent::__construct($endpoint, $level, $bubble);
        $this->logToken = $token;
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        return $this->logToken . ' ' . $record['formatted'];
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\ResettableInterface;
/**
 * Forwards records to multiple handlers
 *
 * @author Lenar LÃµhmus <lenar@city.ee>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class GroupHandler extends Handler implements ProcessableHandlerInterface, ResettableInterface
{
    use ProcessableHandlerTrait;
    /** @var HandlerInterface[] */
    protected $handlers;
    /** @var bool */
    protected $bubble;
    /**
     * @param HandlerInterface[] $handlers Array of Handlers.
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     */
    public function __construct(array $handlers, bool $bubble = true)
    {
        foreach ($handlers as $handler) {
            if (!$handler instanceof HandlerInterface) {
                throw new \InvalidArgumentException('The first argument of the GroupHandler must be an array of HandlerInterface instances.');
            }
        }
        $this->handlers = $handlers;
        $this->bubble = $bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($record)) {
                return true;
            }
        }
        return false;
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            $handler->handle($record);
        }
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if ($this->processors) {
            $processed = [];
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            /** @var Record[] $records */
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            $handler->handleBatch($records);
        }
    }
    /**
     *
     */
    public function reset()
    {
        $this->resetProcessors();
        foreach ($this->handlers as $handler) {
            if ($handler instanceof ResettableInterface) {
                $handler->reset();
            }
        }
    }
    /**
     *
     */
    public function close() : void
    {
        parent::close();
        foreach ($this->handlers as $handler) {
            $handler->close();
        }
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        foreach ($this->handlers as $handler) {
            if ($handler instanceof FormattableHandlerInterface) {
                $handler->setFormatter($formatter);
            }
        }
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
/**
 * Inspired on LogEntriesHandler.
 *
 * @author Robert Kaufmann III <rok3@rok3.me>
 * @author Gabriel Machado <gabriel.ms1@hotmail.com>
 */
class InsightOpsHandler extends SocketHandler
{
    /**
     * @var string
     */
    protected $logToken;
    /**
     * @param string $token Log token supplied by InsightOps
     * @param string $region Region where InsightOps account is hosted. Could be 'us' or 'eu'.
     * @param bool $useSSL Whether or not SSL encryption should be used
     *
     * @throws MissingExtensionException If SSL encryption is set to true and OpenSSL is missing
     */
    public function __construct(string $token, string $region = 'us', bool $useSSL = true, $level = Logger::DEBUG, bool $bubble = true)
    {
        if ($useSSL && !extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP plugin is required to use SSL encrypted connection for InsightOpsHandler');
        }
        $endpoint = $useSSL ? 'ssl://' . $region . '.data.logs.insight.rapid7.com:443' : $region . '.data.logs.insight.rapid7.com:80';
        parent::__construct($endpoint, $level, $bubble);
        $this->logToken = $token;
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        return $this->logToken . ' ' . $record['formatted'];
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
/**
 * Sampling handler
 *
 * A sampled event stream can be useful for logging high frequency events in
 * a production environment where you only need an idea of what is happening
 * and are not concerned with capturing every occurrence. Since the decision to
 * handle or not handle a particular event is determined randomly, the
 * resulting sampled log is not guaranteed to contain 1/N of the events that
 * occurred in the application, but based on the Law of large numbers, it will
 * tend to be close to this ratio with a large number of attempts.
 *
 * @author Bryan Davis <bd808@wikimedia.org>
 * @author Kunal Mehta <legoktm@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
class SamplingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    /**
     * @var HandlerInterface|callable
     * @phpstan-var HandlerInterface|callable(Record|array{level: Level}|null, HandlerInterface): HandlerInterface
     */
    protected $handler;
    /**
     * @var int $factor
     */
    protected $factor;
    /**
     * @psalm-param (HandlerInterface | callable((Record | array{level: Level} | null) , HandlerInterface ): HandlerInterface) $handler
     *
     * @param (callable | HandlerInterface) $handler Handler or factory callable($record|null, $samplingHandler).
     * @param int $factor Sample factor (e.g. 10 means every ~10th record is sampled)
     */
    public function __construct($handler, int $factor)
    {
        parent::__construct();
        $this->handler = $handler;
        $this->factor = $factor;
        if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
            throw new \RuntimeException("The given handler (" . json_encode($this->handler) . ") is not a callable nor a Monolog\\Handler\\HandlerInterface object");
        }
    }
    /**
     *
     */
    public function isHandling(array $record) : bool
    {
        return $this->getHandler($record)->isHandling($record);
    }
    /**
     *
     */
    public function handle(array $record) : bool
    {
        if ($this->isHandling($record) && mt_rand(1, $this->factor) === 1) {
            if ($this->processors) {
                /** @var Record $record */
                $record = $this->processRecord($record);
            }
            $this->getHandler($record)->handle($record);
        }
        return false === $this->bubble;
    }
    /**
     * Return the nested handler
     *
     * If the handler was provided as a factory callable, this will trigger the handler's instantiation.
     *
     * @phpstan-param (Record | array{level: Level} | null) $record
     *
     * @return HandlerInterface
     */
    public function getHandler(array $record = null)
    {
        if (!$this->handler instanceof HandlerInterface) {
            $this->handler = ($this->handler)($record, $this);
            if (!$this->handler instanceof HandlerInterface) {
                throw new \RuntimeException("The factory callable should return a HandlerInterface");
            }
        }
        return $this->handler;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            $handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        $handler = $this->getHandler();
        if ($handler instanceof FormattableHandlerInterface) {
            return $handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($handler) . ' does not support formatters.');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\LineFormatter;
/**
 * NativeMailerHandler uses the mail() function to send the emails
 *
 * @author Christophe Coevoet <stof@notk.org>
 * @author Mark Garrett <mark@moderndeveloperllc.com>
 */
class NativeMailerHandler extends MailHandler
{
    /**
     * The email addresses to which the message will be sent
     * @var string[]
     */
    protected $to;
    /**
     * The subject of the email
     * @var string
     */
    protected $subject;
    /**
     * Optional headers for the message
     * @var string[]
     */
    protected $headers = [];
    /**
     * Optional parameters for the message
     * @var string[]
     */
    protected $parameters = [];
    /**
     * The wordwrap length for the message
     * @var int
     */
    protected $maxColumnWidth;
    /**
     * The Content-type for the message
     * @var string|null
     */
    protected $contentType;
    /**
     * The encoding for the message
     * @var string
     */
    protected $encoding = 'utf-8';
    /**
     * @param (string | string[]) $to The receiver of the mail
     * @param string $subject The subject of the mail
     * @param string $from The sender of the mail
     * @param int $maxColumnWidth The maximum column width that the message lines will have
     */
    public function __construct($to, string $subject, string $from, $level = Logger::ERROR, bool $bubble = true, int $maxColumnWidth = 70)
    {
        parent::__construct($level, $bubble);
        $this->to = (array) $to;
        $this->subject = $subject;
        $this->addHeader(sprintf('From: %s', $from));
        $this->maxColumnWidth = $maxColumnWidth;
    }
    /**
     * Add headers to the message
     *
     * @param (string | string[]) $headers Custom added headers
     */
    public function addHeader($headers) : self
    {
        foreach ((array) $headers as $header) {
            if (strpos($header, "\n") !== false || strpos($header, "\r") !== false) {
                throw new \InvalidArgumentException('Headers can not contain newline characters for security reasons');
            }
            $this->headers[] = $header;
        }
        return $this;
    }
    /**
     * Add parameters to the message
     *
     * @param (string | string[]) $parameters Custom added parameters
     */
    public function addParameter($parameters) : self
    {
        $this->parameters = array_merge($this->parameters, (array) $parameters);
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records) : void
    {
        $contentType = $this->getContentType() ?: ($this->isHtmlBody($content) ? 'text/html' : 'text/plain');
        if ($contentType !== 'text/html') {
            $content = wordwrap($content, $this->maxColumnWidth);
        }
        $headers = ltrim(implode("\r\n", $this->headers) . "\r\n", "\r\n");
        $headers .= 'Content-type: ' . $contentType . '; charset=' . $this->getEncoding() . "\r\n";
        if ($contentType === 'text/html' && false === strpos($headers, 'MIME-Version:')) {
            $headers .= 'MIME-Version: 1.0
';
        }
        $subject = $this->subject;
        if ($records) {
            $subjectFormatter = new LineFormatter($this->subject);
            $subject = $subjectFormatter->format($this->getHighestRecord($records));
        }
        $parameters = implode(' ', $this->parameters);
        foreach ($this->to as $to) {
            mail($to, $subject, $content, $headers, $parameters);
        }
    }
    /**
     *
     */
    public function getContentType() : ?string
    {
        return $this->contentType;
    }
    /**
     *
     */
    public function getEncoding() : string
    {
        return $this->encoding;
    }
    /**
     * @param string $contentType The content type of the email - Defaults to text/plain. Use text/html for HTML messages.
     */
    public function setContentType(string $contentType) : self
    {
        if (strpos($contentType, "\n") !== false || strpos($contentType, "\r") !== false) {
            throw new \InvalidArgumentException('The content type can not contain newline characters to prevent email header injection');
        }
        $this->contentType = $contentType;
        return $this;
    }
    /**
     *
     */
    public function setEncoding(string $encoding) : self
    {
        if (strpos($encoding, "\n") !== false || strpos($encoding, "\r") !== false) {
            throw new \InvalidArgumentException('The encoding can not contain newline characters to prevent email header injection');
        }
        $this->encoding = $encoding;
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\ChromePHPFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
/**
 * Handler sending logs to the ChromePHP extension (http://www.chromephp.com/)
 *
 * This also works out of the box with Firefox 43+
 *
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class ChromePHPHandler extends AbstractProcessingHandler
{
    use WebRequestRecognizerTrait;
    /**
     * Version of the extension
     */
    protected const VERSION = '4.0';
    /**
     * Header name
     */
    protected const HEADER_NAME = 'X-ChromeLogger-Data';
    /**
     * Regular expression to detect supported browsers (matches any Chrome, or Firefox 43+)
     */
    protected const USER_AGENT_REGEX = '{\\b(?:Chrome/\\d+(?:\\.\\d+)*|HeadlessChrome|Firefox/(?:4[3-9]|[5-9]\\d|\\d{3,})(?:\\.\\d)*)\\b}';
    /** @var bool */
    protected static $initialized = false;
    /**
     * Tracks whether we sent too much data
     *
     * Chrome limits the headers to 4KB, so when we sent 3KB we stop sending
     *
     * @var bool
     */
    protected static $overflowed = false;
    /** @var mixed[] */
    protected static $json = ['version' => self::VERSION, 'columns' => ['label', 'log', 'backtrace', 'type'], 'rows' => []];
    /** @var bool */
    protected static $sendHeaders = true;
    /**
     *
     */
    public function __construct($level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        if (!function_exists('json_encode')) {
            throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s ChromePHPHandler');
        }
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if (!$this->isWebRequest()) {
            return;
        }
        $messages = [];
        foreach ($records as $record) {
            if ($record['level'] < $this->level) {
                continue;
            }
            /** @var Record $message */
            $message = $this->processRecord($record);
            $messages[] = $message;
        }
        if (!empty($messages)) {
            $messages = $this->getFormatter()->formatBatch($messages);
            self::$json['rows'] = array_merge(self::$json['rows'], $messages);
            $this->send();
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new ChromePHPFormatter();
    }
    /**
     * Creates & sends header for a record
     *
     * @see sendHeader()
     * @see send()
     */
    protected function write(array $record) : void
    {
        if (!$this->isWebRequest()) {
            return;
        }
        self::$json['rows'][] = $record['formatted'];
        $this->send();
    }
    /**
     * Sends the log header
     *
     * @see sendHeader()
     */
    protected function send() : void
    {
        if (self::$overflowed || !self::$sendHeaders) {
            return;
        }
        if (!self::$initialized) {
            self::$initialized = true;
            self::$sendHeaders = $this->headersAccepted();
            if (!self::$sendHeaders) {
                return;
            }
            self::$json['request_uri'] = $_SERVER['REQUEST_URI'] ?? '';
        }
        $json = Utils::jsonEncode(self::$json, Utils::DEFAULT_JSON_FLAGS & ~JSON_UNESCAPED_UNICODE, true);
        $data = base64_encode(utf8_encode($json));
        if (strlen($data) > 3 * 1024) {
            self::$overflowed = true;
            $record = ['message' => 'Incomplete logs, chrome header size limit reached', 'context' => [], 'level' => Logger::WARNING, 'level_name' => Logger::getLevelName(Logger::WARNING), 'channel' => 'monolog', 'datetime' => new \DateTimeImmutable(), 'extra' => []];
            self::$json['rows'][count(self::$json['rows']) - 1] = $this->getFormatter()->format($record);
            $json = Utils::jsonEncode(self::$json, null, true);
            $data = base64_encode(utf8_encode($json));
        }
        if (trim($data) !== '') {
            $this->sendHeader(static::HEADER_NAME, $data);
        }
    }
    /**
     * Send header string to the client
     */
    protected function sendHeader(string $header, string $content) : void
    {
        if (!headers_sent() && self::$sendHeaders) {
            header(sprintf('%s: %s', $header, $content));
        }
    }
    /**
     * Verifies if the headers are accepted by the current user agent
     */
    protected function headersAccepted() : bool
    {
        if (empty($_SERVER['HTTP_USER_AGENT'])) {
            return false;
        }
        return preg_match(static::USER_AGENT_REGEX, $_SERVER['HTTP_USER_AGENT']) === 1;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
use Monolog\Logger;
/**
 * Sends logs to Fleep.io using Webhook integrations
 *
 * You'll need a Fleep.io account to use this handler.
 *
 * @see https://fleep.io/integrations/webhooks/ Fleep Webhooks Documentation
 * @author Ando Roots <ando@sqroot.eu>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class FleepHookHandler extends SocketHandler
{
    protected const FLEEP_HOST = 'fleep.io';
    protected const FLEEP_HOOK_URI = '/hook/';
    /**
     * @var string Webhook token (specifies the conversation where logs are sent)
     */
    protected $token;
    /**
    * Construct a new Fleep.io Handler.
    *
    * For instructions on how to create a new web hook in your conversations
    see https://fleep.io/integrations/webhooks/
    *
    * @param string $token Webhook token
    * @throws MissingExtensionException
    */
    public function __construct(string $token, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FleepHookHandler');
        }
        $this->token = $token;
        $connectionString = 'ssl://' . static::FLEEP_HOST . ':443';
        parent::__construct($connectionString, $level, $bubble);
    }
    /**
     * Returns the default formatter to use with this handler
     *
     * Overloaded to remove empty context and extra arrays from the end of the log message.
     *
     * @return LineFormatter
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter(null, null, true, true);
    }
    /**
     * Handles a log record
     */
    public function write(array $record) : void
    {
        parent::write($record);
        $this->closeSocket();
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content) : string
    {
        $header = "POST " . static::FLEEP_HOOK_URI . $this->token . " HTTP/1.1\r\n";
        $header .= "Host: " . static::FLEEP_HOST . "\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    /**
     * Builds the body of API call
     *
     * @phpstan-param FormattedRecord $record
     */
    private function buildContent(array $record) : string
    {
        $dataArray = ['message' => $record['formatted']];
        return http_build_query($dataArray);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\HtmlFormatter;
/**
 * Base class for all mail handlers
 *
 * @author Gyula Sallai
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
abstract class MailHandler extends AbstractProcessingHandler
{
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $messages = [];
        foreach ($records as $record) {
            if ($record['level'] < $this->level) {
                continue;
            }
            /** @var Record $message */
            $message = $this->processRecord($record);
            $messages[] = $message;
        }
        if (!empty($messages)) {
            $this->send((string) $this->getFormatter()->formatBatch($messages), $messages);
        }
    }
    /**
     * Send a mail with the given content
     *
     * @param string $content formatted email body to be sent
     * @param array $records the array of log records that formed this content
     *
     * @phpstan-param Record[] $records
     */
    protected abstract function send(string $content, array $records) : void;
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->send((string) $record['formatted'], [$record]);
    }
    /**
     * @phpstan-param non-empty-array<Record> $records
     * @phpstan-return Record
     */
    protected function getHighestRecord(array $records) : array
    {
        $highestRecord = null;
        foreach ($records as $record) {
            if ($highestRecord === null || $highestRecord['level'] < $record['level']) {
                $highestRecord = $record;
            }
        }
        return $highestRecord;
    }
    /**
     *
     */
    protected function isHtmlBody(string $body) : bool
    {
        return ($body[0] ?? null) === '<';
    }
    /**
     * Gets the default formatter.
     *
     * @return FormatterInterface
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new HtmlFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use RuntimeException;
use Monolog\Logger;
/**
 * Handler send logs to Telegram using Telegram Bot API.
 *
 * How to use:
 *  1) Create telegram bot with https://telegram.me/BotFather
 *  2) Create a telegram channel where logs will be recorded.
 *  3) Add created bot from step 1 to the created channel from step 2.
 *
 * Use telegram bot API key from step 1 and channel name with '@' prefix from step 2 to create instance of TelegramBotHandler
 *
 * @link https://core.telegram.org/bots/api
 *
 * @author Mazur Alexandr <alexandrmazur96@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class TelegramBotHandler extends AbstractProcessingHandler
{
    private const BOT_API = 'https://api.telegram.org/bot';
    /**
     * The available values of parseMode according to the Telegram api documentation
     */
    private const AVAILABLE_PARSE_MODES = ['HTML', 'MarkdownV2', 'Markdown'];
    /**
     * Telegram bot access token provided by BotFather.
     * Create telegram bot with https://telegram.me/BotFather and use access token from it.
     * @var string
     */
    private $apiKey;
    /**
     * Telegram channel name.
     * Since to start with '@' symbol as prefix.
     * @var string
     */
    private $channel;
    /**
     * The kind of formatting that is used for the message.
     * See available options at https://core.telegram.org/bots/api#formatting-options
     * or in AVAILABLE_PARSE_MODES
     * @var ?string
     */
    private $parseMode;
    /**
     * Disables link previews for links in the message.
     * @var ?bool
     */
    private $disableWebPagePreview;
    /**
     * Sends the message silently. Users will receive a notification with no sound.
     * @var ?bool
     */
    private $disableNotification;
    /**
     * @param string $apiKey Telegram bot access token provided by BotFather
     * @param string $channel Telegram channel name
     */
    public function __construct(string $apiKey, string $channel, $level = Logger::DEBUG, bool $bubble = true, string $parseMode = null, bool $disableWebPagePreview = null, bool $disableNotification = null)
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the TelegramBotHandler');
        }
        parent::__construct($level, $bubble);
        $this->apiKey = $apiKey;
        $this->channel = $channel;
        $this->setParseMode($parseMode);
        $this->disableWebPagePreview($disableWebPagePreview);
        $this->disableNotification($disableNotification);
    }
    /**
     *
     */
    public function setParseMode(string $parseMode = null) : self
    {
        if ($parseMode !== null && !in_array($parseMode, self::AVAILABLE_PARSE_MODES)) {
            throw new \InvalidArgumentException('Unknown parseMode, use one of these: ' . implode(', ', self::AVAILABLE_PARSE_MODES) . '.');
        }
        $this->parseMode = $parseMode;
        return $this;
    }
    /**
     *
     */
    public function disableWebPagePreview(bool $disableWebPagePreview = null) : self
    {
        $this->disableWebPagePreview = $disableWebPagePreview;
        return $this;
    }
    /**
     *
     */
    public function disableNotification(bool $disableNotification = null) : self
    {
        $this->disableNotification = $disableNotification;
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        /** @var Record[] $messages */
        $messages = [];
        foreach ($records as $record) {
            if (!$this->isHandling($record)) {
                continue;
            }
            if ($this->processors) {
                /** @var Record $record */
                $record = $this->processRecord($record);
            }
            $messages[] = $record;
        }
        if (!empty($messages)) {
            $this->send((string) $this->getFormatter()->formatBatch($messages));
        }
    }
    /**
     * @inheritDoc
     */
    protected function write(array $record) : void
    {
        $this->send($record['formatted']);
    }
    /**
     * Send request to @link https://api.telegram.org/bot on SendMessage action.
     * @param string $message
     */
    protected function send(string $message) : void
    {
        $ch = curl_init();
        $url = self::BOT_API . $this->apiKey . '/SendMessage';
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['text' => $message, 'chat_id' => $this->channel, 'parse_mode' => $this->parseMode, 'disable_web_page_preview' => $this->disableWebPagePreview, 'disable_notification' => $this->disableNotification]));
        $result = Curl\Util::execute($ch);
        if (!is_string($result)) {
            throw new RuntimeException('Telegram API error. Description: No response');
        }
        $result = json_decode($result, true);
        if ($result['ok'] === false) {
            throw new RuntimeException('Telegram API error. Description: ' . $result['description']);
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Base Handler class providing basic close() support as well as handleBatch
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
abstract class Handler implements HandlerInterface
{
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        foreach ($records as $record) {
            $this->handle($record);
        }
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
    }
    /**
     *
     */
    public function __destruct()
    {
        try {
            $this->close();
        } catch (\Throwable $e) {
            // do nothing
        }
    }
    /**
     *
     */
    public function __sleep()
    {
        $this->close();
        return array_keys(get_object_vars($this));
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Aws\Sqs\SqsClient;
use Monolog\Logger;
use Monolog\Utils;
/**
 * Writes to any sqs queue.
 *
 * @author Martijn van Calker <git@amvc.nl>
 */
class SqsHandler extends AbstractProcessingHandler
{
    /** 256 KB in bytes - maximum message size in SQS */
    protected const MAX_MESSAGE_SIZE = 262144;
    /** 100 KB in bytes - head message size for new error log */
    protected const HEAD_MESSAGE_SIZE = 102400;
    /** @var SqsClient */
    private $client;
    /** @var string */
    private $queueUrl;
    /**
     *
     */
    public function __construct(SqsClient $sqsClient, string $queueUrl, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->client = $sqsClient;
        $this->queueUrl = $queueUrl;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!isset($record['formatted']) || 'string' !== gettype($record['formatted'])) {
            throw new \InvalidArgumentException('SqsHandler accepts only formatted records as a string');
        }
        $messageBody = $record['formatted'];
        if (strlen($messageBody) >= static::MAX_MESSAGE_SIZE) {
            $messageBody = Utils::substr($messageBody, 0, static::HEAD_MESSAGE_SIZE);
        }
        $this->client->sendMessage(['QueueUrl' => $this->queueUrl, 'MessageBody' => $messageBody]);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
/**
 * Logs to a Redis key using rpush
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $redis = new RedisHandler(new Predis\Client("tcp://localhost:6379"), "logs", "prod");
 *   $log->pushHandler($redis);
 *
 * @author Thomas Tourlourat <thomas@tourlourat.com>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class RedisHandler extends AbstractProcessingHandler
{
    /** @var \Predis\Client|\Redis */
    private $redisClient;
    /** @var string */
    private $redisKey;
    /** @var int */
    protected $capSize;
    /**
     * @param (\Predis\Client | \Redis) $redis The redis instance
     * @param string $key The key name to push records to
     * @param int $capSize Number of entries to limit list size to, 0 = unlimited
     */
    public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true, int $capSize = 0)
    {
        if (!($redis instanceof \Predis\Client || $redis instanceof \Redis)) {
            throw new \InvalidArgumentException('Predis\\Client or Redis instance required');
        }
        $this->redisClient = $redis;
        $this->redisKey = $key;
        $this->capSize = $capSize;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if ($this->capSize) {
            $this->writeCapped($record);
        } else {
            $this->redisClient->rpush($this->redisKey, $record["formatted"]);
        }
    }
    /**
    * Write and cap the collection
    Writes the record to the redis list and caps its
    *
    * @phpstan-param FormattedRecord $record
    */
    protected function writeCapped(array $record) : void
    {
        if ($this->redisClient instanceof \Redis) {
            $mode = defined('\\Redis::MULTI') ? \Redis::MULTI : 1;
            $this->redisClient->multi($mode)->rpush($this->redisKey, $record["formatted"])->ltrim($this->redisKey, -$this->capSize, -1)->exec();
        } else {
            $redisKey = $this->redisKey;
            $capSize = $this->capSize;
            $this->redisClient->transaction(function ($tx) use($record, $redisKey, $capSize) {
                $tx->rpush($redisKey, $record["formatted"]);
                $tx->ltrim($redisKey, -$capSize, -1);
            });
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use MongoDB\Driver\BulkWrite;
use MongoDB\Driver\Manager;
use MongoDB\Client;
use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\MongoDBFormatter;
/**
 * Logs to a MongoDB database.
 *
 * Usage example:
 *
 *   $log = new \Monolog\Logger('application');
 *   $client = new \MongoDB\Client('mongodb://localhost:27017');
 *   $mongodb = new \Monolog\Handler\MongoDBHandler($client, 'logs', 'prod');
 *   $log->pushHandler($mongodb);
 *
 * The above examples uses the MongoDB PHP library's client class; however, the
 * MongoDB\Driver\Manager class from ext-mongodb is also supported.
 */
class MongoDBHandler extends AbstractProcessingHandler
{
    /** @var \MongoDB\Collection */
    private $collection;
    /** @var Client|Manager */
    private $manager;
    /** @var string */
    private $namespace;
    /**
     * Constructor.
     *
     * @param (Client | Manager) $mongodb MongoDB library or driver client
     * @param string $database Database name
     * @param string $collection Collection name
     */
    public function __construct($mongodb, string $database, string $collection, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!($mongodb instanceof Client || $mongodb instanceof Manager)) {
            throw new \InvalidArgumentException('MongoDB\\Client or MongoDB\\Driver\\Manager instance required');
        }
        if ($mongodb instanceof Client) {
            $this->collection = $mongodb->selectCollection($database, $collection);
        } else {
            $this->manager = $mongodb;
            $this->namespace = $database . '.' . $collection;
        }
        parent::__construct($level, $bubble);
    }
    /**
     *
     */
    protected function write(array $record) : void
    {
        if (isset($this->collection)) {
            $this->collection->insertOne($record['formatted']);
        }
        if (isset($this->manager, $this->namespace)) {
            $bulk = new BulkWrite();
            $bulk->insert($record["formatted"]);
            $this->manager->executeBulkWrite($this->namespace, $bulk);
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new MongoDBFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\FlowdockFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Sends notifications through the Flowdock push API
 *
 * This must be configured with a FlowdockFormatter instance via setFormatter()
 *
 * Notes:
 * API token - Flowdock API token
 *
 * @author Dominik Liebler <liebler.dominik@gmail.com>
 * @see https://www.flowdock.com/api/push
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class FlowdockHandler extends SocketHandler
{
    /**
     * @var string
     */
    protected $apiToken;
    /**
     * @throws MissingExtensionException if OpenSSL is missing
     */
    public function __construct(string $apiToken, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the FlowdockHandler');
        }
        parent::__construct('ssl://api.flowdock.com:443', $level, $bubble);
        $this->apiToken = $apiToken;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if (!$formatter instanceof FlowdockFormatter) {
            throw new \InvalidArgumentException('The FlowdockHandler requires an instance of Monolog\\Formatter\\FlowdockFormatter to function correctly');
        }
        return parent::setFormatter($formatter);
    }
    /**
     * Gets the default formatter.
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        throw new \InvalidArgumentException('The FlowdockHandler must be configured (via setFormatter) with an instance of Monolog\\Formatter\\FlowdockFormatter to function correctly');
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        parent::write($record);
        $this->closeSocket();
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the body of API call
     *
     * @phpstan-param FormattedRecord $record
     */
    private function buildContent(array $record) : string
    {
        return Utils::jsonEncode($record['formatted']['flowdock']);
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content) : string
    {
        $header = "POST /v1/messages/team_inbox/" . $this->apiToken . " HTTP/1.1\r\n";
        $header .= "Host: api.flowdock.com\r\n";
        $header .= "Content-Type: application/json\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
/**
 * Logs to Cube.
 *
 * @link http://square.github.com/cube/
 * @author Wan Chen <kami@kamisama.me>
 */
class CubeHandler extends AbstractProcessingHandler
{
    /** @var resource|\Socket|null */
    private $udpConnection = null;
    /** @var resource|\CurlHandle|null */
    private $httpConnection = null;
    /** @var string */
    private $scheme;
    /** @var string */
    private $host;
    /** @var int */
    private $port;
    /** @var string[] */
    private $acceptedSchemes = ['http', 'udp'];
    /**
    * Create a Cube handler
    *
    * @throws \UnexpectedValueException when given url is not a valid url.
    A valid url must consist of three parts : protocol://host:port
    Only valid protocols used by Cube are http and udp
    */
    public function __construct(string $url, $level = Logger::DEBUG, bool $bubble = true)
    {
        $urlInfo = parse_url($url);
        if ($urlInfo === false || !isset($urlInfo['scheme'], $urlInfo['host'], $urlInfo['port'])) {
            throw new \UnexpectedValueException('URL "' . $url . '" is not valid');
        }
        if (!in_array($urlInfo['scheme'], $this->acceptedSchemes)) {
            throw new \UnexpectedValueException('Invalid protocol (' . $urlInfo['scheme'] . '). Valid options are ' . implode(', ', $this->acceptedSchemes));
        }
        $this->scheme = $urlInfo['scheme'];
        $this->host = $urlInfo['host'];
        $this->port = (int) $urlInfo['port'];
        parent::__construct($level, $bubble);
    }
    /**
     * Establish a connection to an UDP socket
     *
     * @throws \LogicException when unable to connect to the socket
     * @throws MissingExtensionException when there is no socket extension
     */
    protected function connectUdp() : void
    {
        if (!extension_loaded('sockets')) {
            throw new MissingExtensionException('The sockets extension is required to use udp URLs with the CubeHandler');
        }
        $udpConnection = socket_create(AF_INET, SOCK_DGRAM, 0);
        if (false === $udpConnection) {
            throw new \LogicException('Unable to create a socket');
        }
        $this->udpConnection = $udpConnection;
        if (!socket_connect($this->udpConnection, $this->host, $this->port)) {
            throw new \LogicException('Unable to connect to the socket at ' . $this->host . ':' . $this->port);
        }
    }
    /**
     * Establish a connection to an http server
     *
     * @throws \LogicException when unable to connect to the socket
     * @throws MissingExtensionException when no curl extension
     */
    protected function connectHttp() : void
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is required to use http URLs with the CubeHandler');
        }
        $httpConnection = curl_init('http://' . $this->host . ':' . $this->port . '/1.0/event/put');
        if (false === $httpConnection) {
            throw new \LogicException('Unable to connect to ' . $this->host . ':' . $this->port);
        }
        $this->httpConnection = $httpConnection;
        curl_setopt($this->httpConnection, CURLOPT_CUSTOMREQUEST, "POST");
        curl_setopt($this->httpConnection, CURLOPT_RETURNTRANSFER, true);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $date = $record['datetime'];
        $data = ['time' => $date->format('Y-m-d\\TH:i:s.uO')];
        unset($record['datetime']);
        if (isset($record['context']['type'])) {
            $data['type'] = $record['context']['type'];
            unset($record['context']['type']);
        } else {
            $data['type'] = $record['channel'];
        }
        $data['data'] = $record['context'];
        $data['data']['level'] = $record['level'];
        if ($this->scheme === 'http') {
            $this->writeHttp(Utils::jsonEncode($data));
        } else {
            $this->writeUdp(Utils::jsonEncode($data));
        }
    }
    /**
     *
     */
    private function writeUdp(string $data) : void
    {
        if (!$this->udpConnection) {
            $this->connectUdp();
        }
        socket_send($this->udpConnection, $data, strlen($data), 0);
    }
    /**
     *
     */
    private function writeHttp(string $data) : void
    {
        if (!$this->httpConnection) {
            $this->connectHttp();
        }
        if (null === $this->httpConnection) {
            throw new \LogicException('No connection could be established');
        }
        curl_setopt($this->httpConnection, CURLOPT_POSTFIELDS, '[' . $data . ']');
        curl_setopt($this->httpConnection, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Content-Length: ' . strlen('[' . $data . ']')]);
        Curl\Util::execute($this->httpConnection, 5, false);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Processor\ProcessorInterface;
/**
 * Interface to describe loggers that have processors
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
interface ProcessableHandlerInterface
{
    /**
     * Adds a processor in the stack.
     *
     * @psalm-param (ProcessorInterface | callable(Record ): Record) $callback
     *
     * @param (ProcessorInterface | callable) $callback
     * @return HandlerInterface self
     */
    public function pushProcessor(callable $callback) : HandlerInterface;
    /**
     * Removes the processor on top of the stack and returns it.
     *
     * @psalm-return (ProcessorInterface | callable(Record ): Record) $callback
     *
     * @throws \LogicException In case the processor stack is empty
     * @return (callable | ProcessorInterface)
     */
    public function popProcessor() : callable;
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
/**
 * Stores to any stream resource
 *
 * Can be used to store into php://stderr, remote and local files, etc.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class StreamHandler extends AbstractProcessingHandler
{
    /** @const int */
    protected const MAX_CHUNK_SIZE = 2147483647;
    /** @const int 10MB */
    protected const DEFAULT_CHUNK_SIZE = 10 * 1024 * 1024;
    /** @var int */
    protected $streamChunkSize;
    /** @var resource|null */
    protected $stream;
    /** @var ?string */
    protected $url = null;
    /** @var ?string */
    private $errorMessage = null;
    /** @var ?int */
    protected $filePermission;
    /** @var bool */
    protected $useLocking;
    /** @var true|null */
    private $dirCreated = null;
    /**
     * @param (resource | string) $stream If a missing path can't be created, an UnexpectedValueException will be thrown on first write
     * @param (int | null) $filePermission Optional file permissions (default (0644) are only for owner read/write)
     * @param bool $useLocking Try to lock log file before doing any writes
     *
     * @throws \InvalidArgumentException If stream is not a resource or string
     */
    public function __construct($stream, $level = Logger::DEBUG, bool $bubble = true, ?int $filePermission = null, bool $useLocking = false)
    {
        parent::__construct($level, $bubble);
        if (($phpMemoryLimit = Utils::expandIniShorthandBytes(ini_get('memory_limit'))) !== false) {
            if ($phpMemoryLimit > 0) {
                // use max 10% of allowed memory for the chunk size, and at least 100KB
                $this->streamChunkSize = min(static::MAX_CHUNK_SIZE, max((int) ($phpMemoryLimit / 10), 100 * 1024));
            } else {
                // memory is unlimited, set to the default 10MB
                $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
            }
        } else {
            // no memory limit information, set to the default 10MB
            $this->streamChunkSize = static::DEFAULT_CHUNK_SIZE;
        }
        if (is_resource($stream)) {
            $this->stream = $stream;
            stream_set_chunk_size($this->stream, $this->streamChunkSize);
        } elseif (is_string($stream)) {
            $this->url = Utils::canonicalizePath($stream);
        } else {
            throw new \InvalidArgumentException('A stream must either be a resource or a string.');
        }
        $this->filePermission = $filePermission;
        $this->useLocking = $useLocking;
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        if ($this->url && is_resource($this->stream)) {
            fclose($this->stream);
        }
        $this->stream = null;
        $this->dirCreated = null;
    }
    /**
     * Return the currently active stream if it is open
     *
     * @return (resource | null)
     */
    public function getStream()
    {
        return $this->stream;
    }
    /**
     * Return the stream URL if it was configured with a URL and not an active resource
     *
     * @return (string | null)
     */
    public function getUrl() : ?string
    {
        return $this->url;
    }
    /**
     * @return int
     */
    public function getStreamChunkSize() : int
    {
        return $this->streamChunkSize;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!is_resource($this->stream)) {
            $url = $this->url;
            if (null === $url || '' === $url) {
                throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
            }
            $this->createDir($url);
            $this->errorMessage = null;
            set_error_handler([$this, 'customErrorHandler']);
            $stream = fopen($url, 'a');
            if ($this->filePermission !== null) {
                @chmod($url, $this->filePermission);
            }
            restore_error_handler();
            if (!is_resource($stream)) {
                $this->stream = null;
                throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened in append mode: ' . $this->errorMessage, $url));
            }
            stream_set_chunk_size($stream, $this->streamChunkSize);
            $this->stream = $stream;
        }
        $stream = $this->stream;
        if (!is_resource($stream)) {
            throw new \LogicException('No stream was opened yet');
        }
        if ($this->useLocking) {
            // ignoring errors here, there's not much we can do about them
            flock($stream, LOCK_EX);
        }
        $this->streamWrite($stream, $record);
        if ($this->useLocking) {
            flock($stream, LOCK_UN);
        }
    }
    /**
     * Write to stream
     * @param resource $stream
     * @param array $record
     *
     * @phpstan-param FormattedRecord $record
     */
    protected function streamWrite($stream, array $record) : void
    {
        fwrite($stream, (string) $record['formatted']);
    }
    /**
     *
     */
    private function customErrorHandler(int $code, string $msg) : bool
    {
        $this->errorMessage = preg_replace('{^(fopen|mkdir)\\(.*?\\): }', '', $msg);
        return true;
    }
    /**
     *
     */
    private function getDirFromStream(string $stream) : ?string
    {
        $pos = strpos($stream, '://');
        if ($pos === false) {
            return dirname($stream);
        }
        if ('file://' === \Phabel\Target\Php80\Polyfill::substr($stream, 0, 7)) {
            return dirname(\Phabel\Target\Php80\Polyfill::substr($stream, 7));
        }
        return null;
    }
    /**
     *
     */
    private function createDir(string $url) : void
    {
        // Do not try to create dir if it has already been tried.
        if ($this->dirCreated) {
            return;
        }
        $dir = $this->getDirFromStream($url);
        if (null !== $dir && !is_dir($dir)) {
            $this->errorMessage = null;
            set_error_handler([$this, 'customErrorHandler']);
            $status = mkdir($dir, 0777, true);
            restore_error_handler();
            if (false === $status && !is_dir($dir)) {
                throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and it could not be created: ' . $this->errorMessage, $dir));
            }
        }
        $this->dirCreated = true;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\Curl;

use CurlHandle;
/**
 * This class is marked as internal and it is not under the BC promise of the package.
 *
 * @internal
 */
final class Util
{
    /** @var array<int> */
    private static $retriableErrorCodes = [CURLE_COULDNT_RESOLVE_HOST, CURLE_COULDNT_CONNECT, CURLE_HTTP_NOT_FOUND, CURLE_READ_ERROR, CURLE_OPERATION_TIMEOUTED, CURLE_HTTP_POST_ERROR, CURLE_SSL_CONNECT_ERROR];
    /**
     * Executes a CURL request with optional retries and exception on failure
     *
     * @param (resource | CurlHandle) $ch curl handler
     * @param int $retries
     * @param bool $closeAfterDone
     * @return (bool | string) @see curl_exec
     */
    public static function execute($ch, int $retries = 5, bool $closeAfterDone = true)
    {
        while ($retries--) {
            $curlResponse = curl_exec($ch);
            if ($curlResponse === false) {
                $curlErrno = curl_errno($ch);
                if (false === in_array($curlErrno, self::$retriableErrorCodes, true) || !$retries) {
                    $curlError = curl_error($ch);
                    if ($closeAfterDone) {
                        curl_close($ch);
                    }
                    throw new \RuntimeException(sprintf('Curl error (code %d): %s', $curlErrno, $curlError));
                }
                continue;
            }
            if ($closeAfterDone) {
                curl_close($ch);
            }
            return $curlResponse;
        }
        return false;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Elastica\Document;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\ElasticaFormatter;
use Monolog\Logger;
use Elastica\Client;
use Elastica\Exception\ExceptionInterface;
/**
 * Elastic Search handler
 *
 * Usage example:
 *
 *    $client = new \Elastica\Client();
 *    $options = array(
 *        'index' => 'elastic_index_name',
 *        'type' => 'elastic_doc_type', Types have been removed in Elastica 7
 *    );
 *    $handler = new ElasticaHandler($client, $options);
 *    $log = new Logger('application');
 *    $log->pushHandler($handler);
 *
 * @author Jelle Vink <jelle.vink@gmail.com>
 */
class ElasticaHandler extends AbstractProcessingHandler
{
    /**
     * @var Client
     */
    protected $client;
    /**
     * @var mixed[] Handler config options
     */
    protected $options = [];
    /**
     * @param Client $client Elastica Client object
     * @param mixed[] $options Handler configuration
     */
    public function __construct(Client $client, array $options = [], $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        $this->client = $client;
        $this->options = array_merge([
            'index' => 'monolog',
            // Elastic index name
            'type' => 'record',
            // Elastic document type
            'ignore_error' => false,
        ], $options);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->bulkSend([$record['formatted']]);
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($formatter instanceof ElasticaFormatter) {
            return parent::setFormatter($formatter);
        }
        throw new \InvalidArgumentException('ElasticaHandler is only compatible with ElasticaFormatter');
    }
    /**
     * @return mixed[]
     */
    public function getOptions() : array
    {
        return $this->options;
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new ElasticaFormatter($this->options['index'], $this->options['type']);
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $documents = $this->getFormatter()->formatBatch($records);
        $this->bulkSend($documents);
    }
    /**
     * Use Elasticsearch bulk API to send list of documents
     *
     * @param Document[] $documents
     *
     * @throws \RuntimeException
     */
    protected function bulkSend(array $documents) : void
    {
        try {
            $this->client->addDocuments($documents);
        } catch (ExceptionInterface $e) {
            if (!$this->options['ignore_error']) {
                throw new \RuntimeException("Error sending messages to Elasticsearch", 0, $e);
            }
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
/**
 * Handler to only pass log messages when a certain threshold of number of messages is reached.
 *
 * This can be useful in cases of processing a batch of data, but you're for example only interested
 * in case it fails catastrophically instead of a warning for 1 or 2 events. Worse things can happen, right?
 *
 * Usage example:
 *
 * ```
 *   $log = new Logger('application');
 *   $handler = new SomeHandler(...)
 *
 *   // Pass all warnings to the handler when more than 10 & all error messages when more then 5
 *   $overflow = new OverflowHandler($handler, [Logger::WARNING => 10, Logger::ERROR => 5]);
 *
 *   $log->pushHandler($overflow);
 *```
 *
 * @author Kris Buist <krisbuist@gmail.com>
 */
class OverflowHandler extends AbstractHandler implements FormattableHandlerInterface
{
    /** @var HandlerInterface */
    private $handler;
    /** @var int[] */
    private $thresholdMap = [Logger::DEBUG => 0, Logger::INFO => 0, Logger::NOTICE => 0, Logger::WARNING => 0, Logger::ERROR => 0, Logger::CRITICAL => 0, Logger::ALERT => 0, Logger::EMERGENCY => 0];
    /**
     * Buffer of all messages passed to the handler before the threshold was reached
     *
     * @var mixed[][]
     */
    private $buffer = [];
    /**
     * @param HandlerInterface $handler
     * @param int[] $thresholdMap Dictionary of logger level => threshold
     */
    public function __construct(HandlerInterface $handler, array $thresholdMap = [], $level = Logger::DEBUG, bool $bubble = true)
    {
        $this->handler = $handler;
        foreach ($thresholdMap as $thresholdLevel => $threshold) {
            $this->thresholdMap[$thresholdLevel] = $threshold;
        }
        parent::__construct($level, $bubble);
    }
    /**
    * Handles a record.
    *
    * All records may be passed to this method, and the handler should discard
    those that it does not want to handle.
    *
    * The return value of this function controls the bubbling process of the handler stack.
    Unless the bubbling is interrupted (by returning true), the Logger class will keep on
    calling further handlers in the stack with a given log record.
    *
    * {@inheritDoc}
    */
    public function handle(array $record) : bool
    {
        if ($record['level'] < $this->level) {
            return false;
        }
        $level = $record['level'];
        if (!isset($this->thresholdMap[$level])) {
            $this->thresholdMap[$level] = 0;
        }
        if ($this->thresholdMap[$level] > 0) {
            // The overflow threshold is not yet reached, so we're buffering the record and lowering the threshold by 1
            $this->thresholdMap[$level]--;
            $this->buffer[$level][] = $record;
            return false === $this->bubble;
        }
        if ($this->thresholdMap[$level] == 0) {
            // This current message is breaking the threshold. Flush the buffer and continue handling the current record
            foreach ($this->buffer[$level] ?? [] as $buffered) {
                $this->handler->handle($buffered);
            }
            $this->thresholdMap[$level]--;
            unset($this->buffer[$level]);
        }
        $this->handler->handle($record);
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($this->handler) . ' does not support formatters.');
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \UnexpectedValueException('The nested handler of type ' . get_class($this->handler) . ' does not support formatters.');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Class to record a log on a NewRelic application.
 * Enabling New Relic High Security mode may prevent capture of useful information.
 *
 * This handler requires a NormalizerFormatter to function and expects an array in $record['formatted']
 *
 * @see https://docs.newrelic.com/docs/agents/php-agent
 * @see https://docs.newrelic.com/docs/accounts-partnerships/accounts/security/high-security
 */
class NewRelicHandler extends AbstractProcessingHandler
{
    /**
     * Name of the New Relic application that will receive logs from this handler.
     *
     * @var ?string
     */
    protected $appName;
    /**
     * Name of the current transaction
     *
     * @var ?string
     */
    protected $transactionName;
    /**
     * Some context and extra data is passed into the handler as arrays of values. Do we send them as is
     * (useful if we are using the API), or explode them for display on the NewRelic RPM website?
     *
     * @var bool
     */
    protected $explodeArrays;
    /**
     * {@inheritDoc}
     *
     * @param (string | null) $appName
     * @param bool $explodeArrays
     * @param (string | null) $transactionName
     */
    public function __construct($level = Logger::ERROR, bool $bubble = true, ?string $appName = null, bool $explodeArrays = false, ?string $transactionName = null)
    {
        parent::__construct($level, $bubble);
        $this->appName = $appName;
        $this->explodeArrays = $explodeArrays;
        $this->transactionName = $transactionName;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        if (!$this->isNewRelicEnabled()) {
            throw new MissingExtensionException('The newrelic PHP extension is required to use the NewRelicHandler');
        }
        if ($appName = $this->getAppName($record['context'])) {
            $this->setNewRelicAppName($appName);
        }
        if ($transactionName = $this->getTransactionName($record['context'])) {
            $this->setNewRelicTransactionName($transactionName);
            unset($record['formatted']['context']['transaction_name']);
        }
        if (isset($record['context']['exception']) && $record['context']['exception'] instanceof \Throwable) {
            newrelic_notice_error($record['message'], $record['context']['exception']);
            unset($record['formatted']['context']['exception']);
        } else {
            newrelic_notice_error($record['message']);
        }
        if (isset($record['formatted']['context']) && is_array($record['formatted']['context'])) {
            foreach ($record['formatted']['context'] as $key => $parameter) {
                if (is_array($parameter) && $this->explodeArrays) {
                    foreach ($parameter as $paramKey => $paramValue) {
                        $this->setNewRelicParameter('context_' . $key . '_' . $paramKey, $paramValue);
                    }
                } else {
                    $this->setNewRelicParameter('context_' . $key, $parameter);
                }
            }
        }
        if (isset($record['formatted']['extra']) && is_array($record['formatted']['extra'])) {
            foreach ($record['formatted']['extra'] as $key => $parameter) {
                if (is_array($parameter) && $this->explodeArrays) {
                    foreach ($parameter as $paramKey => $paramValue) {
                        $this->setNewRelicParameter('extra_' . $key . '_' . $paramKey, $paramValue);
                    }
                } else {
                    $this->setNewRelicParameter('extra_' . $key, $parameter);
                }
            }
        }
    }
    /**
     * Checks whether the NewRelic extension is enabled in the system.
     *
     * @return bool
     */
    protected function isNewRelicEnabled() : bool
    {
        return extension_loaded('newrelic');
    }
    /**
    * Returns the appname where this log should be sent. Each log can override the default appname, set in this
    handler's constructor, by providing the appname in it's context.
    *
    * @param mixed[] $context
    */
    protected function getAppName(array $context) : ?string
    {
        if (isset($context['appname'])) {
            return $context['appname'];
        }
        return $this->appName;
    }
    /**
    * Returns the name of the current transaction. Each log can override the default transaction name, set in this
    handler's constructor, by providing the transaction_name in it's context
    *
    * @param mixed[] $context
    */
    protected function getTransactionName(array $context) : ?string
    {
        if (isset($context['transaction_name'])) {
            return $context['transaction_name'];
        }
        return $this->transactionName;
    }
    /**
     * Sets the NewRelic application that should receive this log.
     */
    protected function setNewRelicAppName(string $appName) : void
    {
        newrelic_set_appname($appName);
    }
    /**
     * Overwrites the name of the current transaction
     */
    protected function setNewRelicTransactionName(string $transactionName) : void
    {
        newrelic_name_transaction($transactionName);
    }
    /**
     * @param string $key
     * @param mixed $value
     */
    protected function setNewRelicParameter(string $key, $value) : void
    {
        if (null === $value || is_scalar($value)) {
            newrelic_add_custom_parameter($key, $value);
        } else {
            newrelic_add_custom_parameter($key, Utils::jsonEncode($value, null, true));
        }
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new NormalizerFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
use Psr\Log\LogLevel;
/**
 * Sends notifications through the pushover api to mobile phones
 *
 * @author Sebastian GÃ¶ttschkes <sebastian.goettschkes@googlemail.com>
 * @see    https://www.pushover.net/api
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class PushoverHandler extends SocketHandler
{
    /** @var string */
    private $token;
    /** @var array<int|string> */
    private $users;
    /** @var string */
    private $title;
    /** @var string|int|null */
    private $user = null;
    /** @var int */
    private $retry;
    /** @var int */
    private $expire;
    /** @var int */
    private $highPriorityLevel;
    /** @var int */
    private $emergencyLevel;
    /** @var bool */
    private $useFormattedMessage = false;
    /**
     * All parameters that can be sent to Pushover
     * @see https://pushover.net/api
     * @var array<string, bool>
     */
    private $parameterNames = ['token' => true, 'user' => true, 'message' => true, 'device' => true, 'title' => true, 'url' => true, 'url_title' => true, 'priority' => true, 'timestamp' => true, 'sound' => true, 'retry' => true, 'expire' => true, 'callback' => true];
    /**
     * Sounds the api supports by default
     * @see https://pushover.net/api#sounds
     * @var string[]
     */
    private $sounds = ['pushover', 'bike', 'bugle', 'cashregister', 'classical', 'cosmic', 'falling', 'gamelan', 'incoming', 'intermission', 'magic', 'mechanical', 'pianobar', 'siren', 'spacealarm', 'tugboat', 'alien', 'climb', 'persistent', 'echo', 'updown', 'none'];
    /**
    * @param string $token Pushover api token
    * @param (string | array) $users Pushover user id or array of ids the message will be sent to
    * @param (string | null) $title Title sent to the Pushover API
    * @param bool $useSSL Whether to connect via SSL. Required when pushing messages to users that are not
    the pushover.net app owner. OpenSSL is required for this option.
    * @param (string | int) $highPriorityLevel The minimum logging level at which this handler will start
    sending "high priority" requests to the Pushover API
    * @param (string | int) $emergencyLevel The minimum logging level at which this handler will start
    sending "emergency" requests to the Pushover API
    * @param int $retry The retry parameter specifies how often (in seconds) the Pushover servers will
    send the same notification to the user.
    * @param int $expire The expire parameter specifies how many seconds your notification will continue
    to be retried for (every retry seconds).
    *
    * @phpstan-param (string | array<(int | string)>) $users
    * @phpstan-param (Level | LevelName | LogLevel::*) $highPriorityLevel
    * @phpstan-param (Level | LevelName | LogLevel::*) $emergencyLevel
    */
    public function __construct(string $token, $users, ?string $title = null, $level = Logger::CRITICAL, bool $bubble = true, bool $useSSL = true, $highPriorityLevel = Logger::CRITICAL, $emergencyLevel = Logger::EMERGENCY, int $retry = 30, int $expire = 25200)
    {
        $connectionString = $useSSL ? 'ssl://api.pushover.net:443' : 'api.pushover.net:80';
        parent::__construct($connectionString, $level, $bubble);
        $this->token = $token;
        $this->users = (array) $users;
        $this->title = $title ?: (string) gethostname();
        $this->highPriorityLevel = Logger::toMonologLevel($highPriorityLevel);
        $this->emergencyLevel = Logger::toMonologLevel($emergencyLevel);
        $this->retry = $retry;
        $this->expire = $expire;
    }
    /**
     *
     */
    protected function generateDataStream(array $record) : string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * @phpstan-param FormattedRecord $record
     */
    private function buildContent(array $record) : string
    {
        // Pushover has a limit of 512 characters on title and message combined.
        $maxMessageLength = 512 - strlen($this->title);
        $message = $this->useFormattedMessage ? $record['formatted'] : $record['message'];
        $message = Utils::substr($message, 0, $maxMessageLength);
        $timestamp = $record['datetime']->getTimestamp();
        $dataArray = ['token' => $this->token, 'user' => $this->user, 'message' => $message, 'title' => $this->title, 'timestamp' => $timestamp];
        if (isset($record['level']) && $record['level'] >= $this->emergencyLevel) {
            $dataArray['priority'] = 2;
            $dataArray['retry'] = $this->retry;
            $dataArray['expire'] = $this->expire;
        } elseif (isset($record['level']) && $record['level'] >= $this->highPriorityLevel) {
            $dataArray['priority'] = 1;
        }
        // First determine the available parameters
        $context = array_intersect_key($record['context'], $this->parameterNames);
        $extra = array_intersect_key($record['extra'], $this->parameterNames);
        // Least important info should be merged with subsequent info
        $dataArray = array_merge($extra, $context, $dataArray);
        // Only pass sounds that are supported by the API
        if (isset($dataArray['sound']) && !in_array($dataArray['sound'], $this->sounds)) {
            unset($dataArray['sound']);
        }
        return http_build_query($dataArray);
    }
    /**
     *
     */
    private function buildHeader(string $content) : string
    {
        $header = "POST /1/messages.json HTTP/1.1\r\n";
        $header .= "Host: api.pushover.net\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    /**
     *
     */
    protected function write(array $record) : void
    {
        foreach ($this->users as $user) {
            $this->user = $user;
            parent::write($record);
            $this->closeSocket();
        }
        $this->user = null;
    }
    /**
     * @param (int | string) $value
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $value
     */
    public function setHighPriorityLevel($value) : self
    {
        $this->highPriorityLevel = Logger::toMonologLevel($value);
        return $this;
    }
    /**
     * @param (int | string) $value
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $value
     */
    public function setEmergencyLevel($value) : self
    {
        $this->emergencyLevel = Logger::toMonologLevel($value);
        return $this;
    }
    /**
     * Use the formatted message?
     */
    public function useFormattedMessage(bool $value) : self
    {
        $this->useFormattedMessage = $value;
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\ResettableInterface;
use Psr\Log\LogLevel;
/**
 * Base Handler class providing basic level/bubble support
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
abstract class AbstractHandler extends Handler implements ResettableInterface
{
    /**
     * @var int
     * @phpstan-var Level
     */
    protected $level = Logger::DEBUG;
    /** @var bool */
    protected $bubble = true;
    /**
     * @param (int | string) $level The minimum logging level at which this handler will be triggered
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG, bool $bubble = true)
    {
        $this->setLevel($level);
        $this->bubble = $bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return $record['level'] >= $this->level;
    }
    /**
     * Sets minimum logging level at which this handler will be triggered.
     *
     * @param (Level | LevelName | LogLevel::*) $level Level or level name
     * @return self
     */
    public function setLevel($level) : self
    {
        $this->level = Logger::toMonologLevel($level);
        return $this;
    }
    /**
     * Gets minimum logging level at which this handler will be triggered.
     *
     * @return int
     *
     * @phpstan-return Level
     */
    public function getLevel() : int
    {
        return $this->level;
    }
    /**
    * Sets the bubbling behavior.
    *
    * @param bool $bubble true means that this handler allows bubbling.
    false means that bubbling is not permitted.
    * @return self
    */
    public function setBubble(bool $bubble) : self
    {
        $this->bubble = $bubble;
        return $this;
    }
    /**
    * Gets the bubbling behavior.
    *
    * @return bool true means that this handler allows bubbling.
    false means that bubbling is not permitted.
    */
    public function getBubble() : bool
    {
        return $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function reset()
    {
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\SyslogUdp;

use Monolog\Utils;
use Socket;
class UdpSocket
{
    protected const DATAGRAM_MAX_LENGTH = 65023;
    /** @var string */
    protected $ip;
    /** @var int */
    protected $port;
    /** @var resource|Socket|null */
    protected $socket;
    /**
     *
     */
    public function __construct(string $ip, int $port = 514)
    {
        $this->ip = $ip;
        $this->port = $port;
        $domain = AF_INET;
        $protocol = SOL_UDP;
        // Check if we are using unix sockets.
        if ($port === 0) {
            $domain = AF_UNIX;
            $protocol = IPPROTO_IP;
        }
        $this->socket = socket_create($domain, SOCK_DGRAM, $protocol) ?: null;
    }
    /**
     * @param string $line
     * @param string $header
     * @return void
     */
    public function write($line, $header = "")
    {
        $this->send($this->assembleMessage($line, $header));
    }
    /**
     *
     */
    public function close() : void
    {
        if (is_resource($this->socket) || $this->socket instanceof Socket) {
            socket_close($this->socket);
            $this->socket = null;
        }
    }
    /**
     *
     */
    protected function send(string $chunk) : void
    {
        if (!is_resource($this->socket) && !$this->socket instanceof Socket) {
            throw new \RuntimeException('The UdpSocket to ' . $this->ip . ':' . $this->port . ' has been closed and can not be written to anymore');
        }
        socket_sendto($this->socket, $chunk, strlen($chunk), $flags = 0, $this->ip, $this->port);
    }
    /**
     *
     */
    protected function assembleMessage(string $line, string $header) : string
    {
        $chunkSize = static::DATAGRAM_MAX_LENGTH - strlen($header);
        return $header . Utils::substr($line, 0, $chunkSize);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Interface that all Monolog Handlers must implement
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
interface HandlerInterface
{
    /**
    * Checks whether the given record will be handled by this handler.
    *
    * This is mostly done for performance reasons, to avoid calling processors for nothing.
    *
    * Handlers should still check the record levels within handle(), returning false in isHandling()
    is no guarantee that handle() will not be called, and isHandling() might not be called
    for a given record.
    *
    * @param array $record Partial log record containing only a level key
    *
    * @return bool
    *
    * @phpstan-param array{level: Level} $record
    */
    public function isHandling(array $record) : bool;
    /**
    * Handles a record.
    *
    * All records may be passed to this method, and the handler should discard
    those that it does not want to handle.
    *
    * The return value of this function controls the bubbling process of the handler stack.
    Unless the bubbling is interrupted (by returning true), the Logger class will keep on
    calling further handlers in the stack with a given log record.
    *
    * @param array $record The record to handle
    * @return bool true means that this handler handled the record, and that bubbling is not permitted.
    false means the record was either not processed or that this handler allows bubbling.
    *
    * @phpstan-param Record $record
    */
    public function handle(array $record) : bool;
    /**
     * Handles a set of records at once.
     *
     * @param array $records The records to handle (an array of record arrays)
     *
     * @phpstan-param Record[] $records
     */
    public function handleBatch(array $records) : void;
    /**
    * Closes the handler.
    *
    * Ends a log cycle and frees all resources used by the handler.
    *
    * Closing a Handler means flushing all buffers and freeing any open resources/handles.
    *
    * Implementations have to be idempotent (i.e. it should be possible to call close several times without breakage)
    and ideally handlers should be able to reopen themselves on handle() after they have been closed.
    *
    * This is useful at the end of a request and will be called automatically when the object
    is destroyed if you extend Monolog\Handler\Handler.
    *
    * If you are thinking of calling this method yourself, most likely you should be
    calling ResettableInterface::reset instead. Have a look.
    */
    public function close() : void;
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Utils;
/**
 * IFTTTHandler uses cURL to trigger IFTTT Maker actions
 *
 * Register a secret key and trigger/event name at https://ifttt.com/maker
 *
 * value1 will be the channel from monolog's Logger constructor,
 * value2 will be the level name (ERROR, WARNING, ..)
 * value3 will be the log record's message
 *
 * @author Nehal Patel <nehal@nehalpatel.me>
 */
class IFTTTHandler extends AbstractProcessingHandler
{
    /** @var string */
    private $eventName;
    /** @var string */
    private $secretKey;
    /**
     * @param string $eventName The name of the IFTTT Maker event that should be triggered
     * @param string $secretKey A valid IFTTT secret key
     */
    public function __construct(string $eventName, string $secretKey, $level = Logger::ERROR, bool $bubble = true)
    {
        if (!extension_loaded('curl')) {
            throw new MissingExtensionException('The curl extension is needed to use the IFTTTHandler');
        }
        $this->eventName = $eventName;
        $this->secretKey = $secretKey;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    public function write(array $record) : void
    {
        $postData = ["value1" => $record["channel"], "value2" => $record["level_name"], "value3" => $record["message"]];
        $postString = Utils::jsonEncode($postData);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, "https://maker.ifttt.com/trigger/" . $this->eventName . "/with/key/" . $this->secretKey);
        curl_setopt($ch, CURLOPT_POST, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postString);
        curl_setopt($ch, CURLOPT_HTTPHEADER, ["Content-Type: application/json"]);
        Curl\Util::execute($ch);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Throwable;
/**
 * Forwards records to at most one handler
 *
 * If a handler fails, the exception is suppressed and the record is forwarded to the next handler.
 *
 * As soon as one handler handles a record successfully, the handling stops there.
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class FallbackGroupHandler extends GroupHandler
{
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handle($record);
                break;
            } catch (Throwable $e) {
                // What throwable?
            }
        }
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if ($this->processors) {
            $processed = [];
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            /** @var Record[] $records */
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handleBatch($records);
                break;
            } catch (Throwable $e) {
                // What throwable?
            }
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Base Handler class providing the Handler structure, including processors and formatters
 *
 * Classes extending it should (in most cases) only implement write($record)
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 *
 * @phpstan-import-type LevelName from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-type FormattedRecord array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[], formatted: mixed}
 */
abstract class AbstractProcessingHandler extends AbstractHandler implements ProcessableHandlerInterface, FormattableHandlerInterface
{
    use ProcessableHandlerTrait;
    use FormattableHandlerTrait;
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if (!$this->isHandling($record)) {
            return false;
        }
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        $record['formatted'] = $this->getFormatter()->format($record);
        $this->write($record);
        return false === $this->bubble;
    }
    /**
     * Writes the record down to the log of the implementing handler
     *
     * @phpstan-param FormattedRecord $record
     */
    protected abstract function write(array $record) : void;
    /**
     * @return void
     */
    public function reset()
    {
        parent::reset();
        $this->resetProcessors();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
/**
 * Sends the message to a Redis Pub/Sub channel using PUBLISH
 *
 * usage example:
 *
 *   $log = new Logger('application');
 *   $redis = new RedisPubSubHandler(new Predis\Client("tcp://localhost:6379"), "logs", Logger::WARNING);
 *   $log->pushHandler($redis);
 *
 * @author GaÃ«tan FaugÃ¨re <gaetan@fauge.re>
 */
class RedisPubSubHandler extends AbstractProcessingHandler
{
    /** @var \Predis\Client|\Redis */
    private $redisClient;
    /** @var string */
    private $channelKey;
    /**
     * @param (\Predis\Client | \Redis) $redis The redis instance
     * @param string $key The channel key to publish records to
     */
    public function __construct($redis, string $key, $level = Logger::DEBUG, bool $bubble = true)
    {
        if (!($redis instanceof \Predis\Client || $redis instanceof \Redis)) {
            throw new \InvalidArgumentException('Predis\\Client or Redis instance required');
        }
        $this->redisClient = $redis;
        $this->channelKey = $key;
        parent::__construct($level, $bubble);
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        $this->redisClient->publish($this->channelKey, $record["formatted"]);
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\FormatterInterface;
use Monolog\Logger;
use Monolog\Utils;
use Monolog\Handler\Slack\SlackRecord;
/**
 * Sends notifications through Slack API
 *
 * @author Greg Kedzierski <greg@gregkedzierski.com>
 * @see    https://api.slack.com/
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class SlackHandler extends SocketHandler
{
    /**
     * Slack API token
     * @var string
     */
    private $token;
    /**
     * Instance of the SlackRecord util class preparing data for Slack API.
     * @var SlackRecord
     */
    private $slackRecord;
    /**
     * @param string $token Slack API token
     * @param string $channel Slack channel (encoded ID or name)
     * @param (string | null) $username Name of a bot
     * @param bool $useAttachment Whether the message should be added to Slack as attachment (plain text otherwise)
     * @param (string | null) $iconEmoji The emoji name to use (or null)
     * @param bool $useShortAttachment Whether the context/extra messages added to Slack as attachments are in a short style
     * @param bool $includeContextAndExtra Whether the attachment should include context and extra data
     * @param string[] $excludeFields Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     * @throws MissingExtensionException If no OpenSSL PHP extension configured
     */
    public function __construct(string $token, string $channel, ?string $username = null, bool $useAttachment = true, ?string $iconEmoji = null, $level = Logger::CRITICAL, bool $bubble = true, bool $useShortAttachment = false, bool $includeContextAndExtra = false, array $excludeFields = array())
    {
        if (!extension_loaded('openssl')) {
            throw new MissingExtensionException('The OpenSSL PHP extension is required to use the SlackHandler');
        }
        parent::__construct('ssl://slack.com:443', $level, $bubble);
        $this->slackRecord = new SlackRecord($channel, $username, $useAttachment, $iconEmoji, $useShortAttachment, $includeContextAndExtra, $excludeFields);
        $this->token = $token;
    }
    /**
     *
     */
    public function getSlackRecord() : SlackRecord
    {
        return $this->slackRecord;
    }
    /**
     *
     */
    public function getToken() : string
    {
        return $this->token;
    }
    /**
     * {@inheritDoc}
     */
    protected function generateDataStream(array $record) : string
    {
        $content = $this->buildContent($record);
        return $this->buildHeader($content) . $content;
    }
    /**
     * Builds the body of API call
     *
     * @phpstan-param FormattedRecord $record
     */
    private function buildContent(array $record) : string
    {
        $dataArray = $this->prepareContentData($record);
        return http_build_query($dataArray);
    }
    /**
     * @phpstan-param FormattedRecord $record
     * @return string[]
     */
    protected function prepareContentData(array $record) : array
    {
        $dataArray = $this->slackRecord->getSlackData($record);
        $dataArray['token'] = $this->token;
        if (!empty($dataArray['attachments'])) {
            $dataArray['attachments'] = Utils::jsonEncode($dataArray['attachments']);
        }
        return $dataArray;
    }
    /**
     * Builds the header of the API Call
     */
    private function buildHeader(string $content) : string
    {
        $header = "POST /api/chat.postMessage HTTP/1.1\r\n";
        $header .= "Host: slack.com\r\n";
        $header .= "Content-Type: application/x-www-form-urlencoded\r\n";
        $header .= "Content-Length: " . strlen($content) . "\r\n";
        $header .= "\r\n";
        return $header;
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        parent::write($record);
        $this->finalizeWrite();
    }
    /**
    * Finalizes the request by reading some bytes and then closing the socket
    *
    * If we do not read some but close the socket too early, slack sometimes
    drops the request entirely.
    */
    protected function finalizeWrite() : void
    {
        $res = $this->getResource();
        if (is_resource($res)) {
            @fread($res, 2048);
        }
        $this->closeSocket();
    }
    /**
     *
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        parent::setFormatter($formatter);
        $this->slackRecord->setFormatter($formatter);
        return $this;
    }
    /**
     *
     */
    public function getFormatter() : FormatterInterface
    {
        $formatter = parent::getFormatter();
        $this->slackRecord->setFormatter($formatter);
        return $formatter;
    }
    /**
     * Channel used by the bot when posting
     */
    public function setChannel(string $channel) : self
    {
        $this->slackRecord->setChannel($channel);
        return $this;
    }
    /**
     * Username used by the bot when posting
     */
    public function setUsername(string $username) : self
    {
        $this->slackRecord->setUsername($username);
        return $this;
    }
    /**
     *
     */
    public function useAttachment(bool $useAttachment) : self
    {
        $this->slackRecord->useAttachment($useAttachment);
        return $this;
    }
    /**
     *
     */
    public function setIconEmoji(string $iconEmoji) : self
    {
        $this->slackRecord->setUserIcon($iconEmoji);
        return $this;
    }
    /**
     *
     */
    public function useShortAttachment(bool $useShortAttachment) : self
    {
        $this->slackRecord->useShortAttachment($useShortAttachment);
        return $this;
    }
    /**
     *
     */
    public function includeContextAndExtra(bool $includeContextAndExtra) : self
    {
        $this->slackRecord->includeContextAndExtra($includeContextAndExtra);
        return $this;
    }
    /**
     * @param string[] $excludeFields
     */
    public function excludeFields(array $excludeFields) : self
    {
        $this->slackRecord->excludeFields($excludeFields);
        return $this;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Monolog\Formatter\FormatterInterface;
use Monolog\Formatter\LineFormatter;
/**
 * Common syslog functionality
 *
 * @phpstan-import-type Level from \Monolog\Logger
 */
abstract class AbstractSyslogHandler extends AbstractProcessingHandler
{
    /** @var int */
    protected $facility;
    /**
     * Translates Monolog log levels to syslog log priorities.
     * @var array
     * @phpstan-var array<Level, int>
     */
    protected $logLevels = [Logger::DEBUG => LOG_DEBUG, Logger::INFO => LOG_INFO, Logger::NOTICE => LOG_NOTICE, Logger::WARNING => LOG_WARNING, Logger::ERROR => LOG_ERR, Logger::CRITICAL => LOG_CRIT, Logger::ALERT => LOG_ALERT, Logger::EMERGENCY => LOG_EMERG];
    /**
     * List of valid log facility names.
     * @var array<string, int>
     */
    protected $facilities = ['auth' => LOG_AUTH, 'authpriv' => LOG_AUTHPRIV, 'cron' => LOG_CRON, 'daemon' => LOG_DAEMON, 'kern' => LOG_KERN, 'lpr' => LOG_LPR, 'mail' => LOG_MAIL, 'news' => LOG_NEWS, 'syslog' => LOG_SYSLOG, 'user' => LOG_USER, 'uucp' => LOG_UUCP];
    /**
     * @param (string | int) $facility Either one of the names of the keys in $this->facilities, or a LOG_* facility constant
     */
    public function __construct($facility = LOG_USER, $level = Logger::DEBUG, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        if (!defined('PHP_WINDOWS_VERSION_BUILD')) {
            $this->facilities['local0'] = LOG_LOCAL0;
            $this->facilities['local1'] = LOG_LOCAL1;
            $this->facilities['local2'] = LOG_LOCAL2;
            $this->facilities['local3'] = LOG_LOCAL3;
            $this->facilities['local4'] = LOG_LOCAL4;
            $this->facilities['local5'] = LOG_LOCAL5;
            $this->facilities['local6'] = LOG_LOCAL6;
            $this->facilities['local7'] = LOG_LOCAL7;
        } else {
            $this->facilities['local0'] = 128;
            // LOG_LOCAL0
            $this->facilities['local1'] = 136;
            // LOG_LOCAL1
            $this->facilities['local2'] = 144;
            // LOG_LOCAL2
            $this->facilities['local3'] = 152;
            // LOG_LOCAL3
            $this->facilities['local4'] = 160;
            // LOG_LOCAL4
            $this->facilities['local5'] = 168;
            // LOG_LOCAL5
            $this->facilities['local6'] = 176;
            // LOG_LOCAL6
            $this->facilities['local7'] = 184;
            // LOG_LOCAL7
        }
        // convert textual description of facility to syslog constant
        if (is_string($facility) && array_key_exists(strtolower($facility), $this->facilities)) {
            $facility = $this->facilities[strtolower($facility)];
        } elseif (!in_array($facility, array_values($this->facilities), true)) {
            throw new \UnexpectedValueException('Unknown facility value "' . $facility . '" given');
        }
        $this->facility = $facility;
    }
    /**
     * {@inheritDoc}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter('%channel%.%level_name%: %message% %context% %extra%');
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

/**
 * Forwards records to multiple handlers suppressing failures of each handler
 * and continuing through to give every handler a chance to succeed.
 *
 * @author Craig D'Amelio <craig@damelio.ca>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class WhatFailureGroupHandler extends GroupHandler
{
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        if ($this->processors) {
            /** @var Record $record */
            $record = $this->processRecord($record);
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handle($record);
            } catch (\Throwable $e) {
                // What failure?
            }
        }
        return false === $this->bubble;
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        if ($this->processors) {
            $processed = array();
            foreach ($records as $record) {
                $processed[] = $this->processRecord($record);
            }
            /** @var Record[] $records */
            $records = $processed;
        }
        foreach ($this->handlers as $handler) {
            try {
                $handler->handleBatch($records);
            } catch (\Throwable $e) {
                // What failure?
            }
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Simple handler wrapper that deduplicates log records across multiple requests
 *
 * It also includes the BufferHandler functionality and will buffer
 * all messages until the end of the request or flush() is called.
 *
 * This works by storing all log records' messages above $deduplicationLevel
 * to the file specified by $deduplicationStore. When further logs come in at the end of the
 * request (or when flush() is called), all those above $deduplicationLevel are checked
 * against the existing stored logs. If they match and the timestamps in the stored log is
 * not older than $time seconds, the new log record is discarded. If no log record is new, the
 * whole data set is discarded.
 *
 * This is mainly useful in combination with Mail handlers or things like Slack or HipChat handlers
 * that send messages to people, to avoid spamming with the same message over and over in case of
 * a major component failure like a database server being down which makes all requests fail in the
 * same way.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
class DeduplicationHandler extends BufferHandler
{
    /**
     * @var string
     */
    protected $deduplicationStore;
    /**
     * @var Level
     */
    protected $deduplicationLevel;
    /**
     * @var int
     */
    protected $time;
    /**
     * @var bool
     */
    private $gc = false;
    /**
     * @param HandlerInterface $handler Handler.
     * @param string $deduplicationStore The file/path where the deduplication log should be kept
     * @param (string | int) $deduplicationLevel The minimum logging level for log records to be looked at for deduplication purposes
     * @param int $time The period (in seconds) during which duplicate entries should be suppressed after a given log is sent through
     * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $deduplicationLevel
     */
    public function __construct(HandlerInterface $handler, ?string $deduplicationStore = null, $deduplicationLevel = Logger::ERROR, int $time = 60, bool $bubble = true)
    {
        parent::__construct($handler, 0, Logger::DEBUG, $bubble, false);
        $this->deduplicationStore = $deduplicationStore === null ? sys_get_temp_dir() . '/monolog-dedup-' . \Phabel\Target\Php80\Polyfill::substr(md5(__FILE__), 0, 20) . '.log' : $deduplicationStore;
        $this->deduplicationLevel = Logger::toMonologLevel($deduplicationLevel);
        $this->time = $time;
    }
    /**
     *
     */
    public function flush() : void
    {
        if ($this->bufferSize === 0) {
            return;
        }
        $passthru = null;
        foreach ($this->buffer as $record) {
            if ($record['level'] >= $this->deduplicationLevel) {
                $passthru = $passthru || !$this->isDuplicate($record);
                if ($passthru) {
                    $this->appendRecord($record);
                }
            }
        }
        // default of null is valid as well as if no record matches duplicationLevel we just pass through
        if ($passthru === true || $passthru === null) {
            $this->handler->handleBatch($this->buffer);
        }
        $this->clear();
        if ($this->gc) {
            $this->collectLogs();
        }
    }
    /**
     * @phpstan-param Record $record
     */
    private function isDuplicate(array $record) : bool
    {
        if (!file_exists($this->deduplicationStore)) {
            return false;
        }
        $store = file($this->deduplicationStore, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        if (!is_array($store)) {
            return false;
        }
        $yesterday = time() - 86400;
        $timestampValidity = $record['datetime']->getTimestamp() - $this->time;
        $expectedMessage = preg_replace('{[\\r\\n].*}', '', $record['message']);
        for ($i = count($store) - 1; $i >= 0; $i--) {
            list($timestamp, $level, $message) = explode(':', $store[$i], 3);
            if ($level === $record['level_name'] && $message === $expectedMessage && $timestamp > $timestampValidity) {
                return true;
            }
            if ($timestamp < $yesterday) {
                $this->gc = true;
            }
        }
        return false;
    }
    /**
     *
     */
    private function collectLogs() : void
    {
        if (!file_exists($this->deduplicationStore)) {
            return;
        }
        $handle = fopen($this->deduplicationStore, 'rw+');
        if (!$handle) {
            throw new \RuntimeException('Failed to open file for reading and writing: ' . $this->deduplicationStore);
        }
        flock($handle, LOCK_EX);
        $validLogs = [];
        $timestampValidity = time() - $this->time;
        while (!feof($handle)) {
            $log = fgets($handle);
            if ($log && \Phabel\Target\Php80\Polyfill::substr($log, 0, 10) >= $timestampValidity) {
                $validLogs[] = $log;
            }
        }
        ftruncate($handle, 0);
        rewind($handle);
        foreach ($validLogs as $log) {
            fwrite($handle, $log);
        }
        flock($handle, LOCK_UN);
        fclose($handle);
        $this->gc = false;
    }
    /**
     * @phpstan-param Record $record
     */
    private function appendRecord(array $record) : void
    {
        file_put_contents($this->deduplicationStore, $record['datetime']->getTimestamp() . ':' . $record['level_name'] . ':' . preg_replace('{[\\r\\n].*}', '', $record['message']) . "\n", FILE_APPEND);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Logger;
use Swift;
use Swift_Message;
/**
 * MandrillHandler uses cURL to send the emails to the Mandrill API
 *
 * @author Adam Nicholson <adamnicholson10@gmail.com>
 */
class MandrillHandler extends MailHandler
{
    /** @var Swift_Message */
    protected $message;
    /** @var string */
    protected $apiKey;
    /**
     * @psalm-param (Swift_Message | callable(): Swift_Message) $message
     *
     * @param string $apiKey A valid Mandrill API key
     * @param (callable | Swift_Message) $message An example message for real messages, only the body will be replaced
     */
    public function __construct(string $apiKey, $message, $level = Logger::ERROR, bool $bubble = true)
    {
        parent::__construct($level, $bubble);
        if (!$message instanceof Swift_Message && is_callable($message)) {
            $message = $message();
        }
        if (!$message instanceof Swift_Message) {
            throw new \InvalidArgumentException('You must provide either a Swift_Message instance or a callable returning it');
        }
        $this->message = $message;
        $this->apiKey = $apiKey;
    }
    /**
     * {@inheritDoc}
     */
    protected function send(string $content, array $records) : void
    {
        $mime = 'text/plain';
        if ($this->isHtmlBody($content)) {
            $mime = 'text/html';
        }
        $message = clone $this->message;
        $message->setBody($content, $mime);
        /** @phpstan-ignore-next-line */
        if (version_compare(Swift::VERSION, '6.0.0', '>=')) {
            $message->setDate(new \DateTimeImmutable());
        } else {
            /** @phpstan-ignore-next-line */
            $message->setDate(time());
        }
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, 'https://mandrillapp.com/api/1.0/messages/send-raw.json');
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query(['key' => $this->apiKey, 'raw_message' => (string) $message, 'async' => false]));
        Curl\Util::execute($ch);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler\Slack;

use Monolog\Logger;
use Monolog\Utils;
use Monolog\Formatter\NormalizerFormatter;
use Monolog\Formatter\FormatterInterface;
/**
 * Slack record utility helping to log to Slack webhooks or API.
 *
 * @author Greg Kedzierski <greg@gregkedzierski.com>
 * @author Haralan Dobrev <hkdobrev@gmail.com>
 * @see    https://api.slack.com/incoming-webhooks
 * @see    https://api.slack.com/docs/message-attachments
 *
 * @phpstan-import-type FormattedRecord from \Monolog\Handler\AbstractProcessingHandler
 * @phpstan-import-type Record from \Monolog\Logger
 */
class SlackRecord
{
    public const COLOR_DANGER = 'danger';
    public const COLOR_WARNING = 'warning';
    public const COLOR_GOOD = 'good';
    public const COLOR_DEFAULT = '#e3e4e6';
    /**
     * Slack channel (encoded ID or name)
     * @var string|null
     */
    private $channel;
    /**
     * Name of a bot
     * @var string|null
     */
    private $username;
    /**
     * User icon e.g. 'ghost', 'http://example.com/user.png'
     * @var string|null
     */
    private $userIcon;
    /**
     * Whether the message should be added to Slack as attachment (plain text otherwise)
     * @var bool
     */
    private $useAttachment;
    /**
     * Whether the the context/extra messages added to Slack as attachments are in a short style
     * @var bool
     */
    private $useShortAttachment;
    /**
     * Whether the attachment should include context and extra data
     * @var bool
     */
    private $includeContextAndExtra;
    /**
     * Dot separated list of fields to exclude from slack message. E.g. ['context.field1', 'extra.field2']
     * @var string[]
     */
    private $excludeFields;
    /**
     * @var ?FormatterInterface
     */
    private $formatter;
    /**
     * @var NormalizerFormatter
     */
    private $normalizerFormatter;
    /**
     * @param string[] $excludeFields
     */
    public function __construct(?string $channel = null, ?string $username = null, bool $useAttachment = true, ?string $userIcon = null, bool $useShortAttachment = false, bool $includeContextAndExtra = false, array $excludeFields = array(), FormatterInterface $formatter = null)
    {
        $this->setChannel($channel)->setUsername($username)->useAttachment($useAttachment)->setUserIcon($userIcon)->useShortAttachment($useShortAttachment)->includeContextAndExtra($includeContextAndExtra)->excludeFields($excludeFields)->setFormatter($formatter);
        if ($this->includeContextAndExtra) {
            $this->normalizerFormatter = new NormalizerFormatter();
        }
    }
    /**
    * Returns required data in format that Slack
    is expecting.
    *
    * @phpstan-param FormattedRecord $record
    * @phpstan-return mixed[]
    */
    public function getSlackData(array $record) : array
    {
        $dataArray = array();
        $record = $this->removeExcludedFields($record);
        if ($this->username) {
            $dataArray['username'] = $this->username;
        }
        if ($this->channel) {
            $dataArray['channel'] = $this->channel;
        }
        if ($this->formatter && !$this->useAttachment) {
            /** @phpstan-ignore-next-line */
            $message = $this->formatter->format($record);
        } else {
            $message = $record['message'];
        }
        if ($this->useAttachment) {
            $attachment = array('fallback' => $message, 'text' => $message, 'color' => $this->getAttachmentColor($record['level']), 'fields' => array(), 'mrkdwn_in' => array('fields'), 'ts' => $record['datetime']->getTimestamp());
            if ($this->useShortAttachment) {
                $attachment['title'] = $record['level_name'];
            } else {
                $attachment['title'] = 'Message';
                $attachment['fields'][] = $this->generateAttachmentField('Level', $record['level_name']);
            }
            if ($this->includeContextAndExtra) {
                foreach (array('extra', 'context') as $key) {
                    if (empty($record[$key])) {
                        continue;
                    }
                    if ($this->useShortAttachment) {
                        $attachment['fields'][] = $this->generateAttachmentField((string) $key, $record[$key]);
                    } else {
                        // Add all extra fields as individual fields in attachment
                        $attachment['fields'] = array_merge($attachment['fields'], $this->generateAttachmentFields($record[$key]));
                    }
                }
            }
            $dataArray['attachments'] = array($attachment);
        } else {
            $dataArray['text'] = $message;
        }
        if ($this->userIcon) {
            if (filter_var($this->userIcon, FILTER_VALIDATE_URL)) {
                $dataArray['icon_url'] = $this->userIcon;
            } else {
                $dataArray['icon_emoji'] = ":{$this->userIcon}:";
            }
        }
        return $dataArray;
    }
    /**
    * Returns a Slack message attachment color associated with
    provided level.
    */
    public function getAttachmentColor(int $level) : string
    {
        switch (true) {
            case $level >= Logger::ERROR:
                return static::COLOR_DANGER;
            case $level >= Logger::WARNING:
                return static::COLOR_WARNING;
            case $level >= Logger::INFO:
                return static::COLOR_GOOD;
            default:
                return static::COLOR_DEFAULT;
        }
    }
    /**
     * Stringifies an array of key/value pairs to be used in attachment fields
     *
     * @param mixed[] $fields
     */
    public function stringify(array $fields) : string
    {
        /** @var Record $fields */
        $normalized = $this->normalizerFormatter->format($fields);
        $hasSecondDimension = count(array_filter($normalized, 'is_array'));
        $hasNonNumericKeys = !count(array_filter(array_keys($normalized), 'is_numeric'));
        return $hasSecondDimension || $hasNonNumericKeys ? Utils::jsonEncode($normalized, JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS) : Utils::jsonEncode($normalized, Utils::DEFAULT_JSON_FLAGS);
    }
    /**
     * Channel used by the bot when posting
     *
     * @param ?string $channel
     *
     * @return static
     */
    public function setChannel(?string $channel = null) : self
    {
        $this->channel = $channel;
        return $this;
    }
    /**
     * Username used by the bot when posting
     *
     * @param ?string $username
     *
     * @return static
     */
    public function setUsername(?string $username = null) : self
    {
        $this->username = $username;
        return $this;
    }
    /**
     *
     */
    public function useAttachment(bool $useAttachment = true) : self
    {
        $this->useAttachment = $useAttachment;
        return $this;
    }
    /**
     *
     */
    public function setUserIcon(?string $userIcon = null) : self
    {
        $this->userIcon = $userIcon;
        if (\is_string($userIcon)) {
            $this->userIcon = trim($userIcon, ':');
        }
        return $this;
    }
    /**
     *
     */
    public function useShortAttachment(bool $useShortAttachment = false) : self
    {
        $this->useShortAttachment = $useShortAttachment;
        return $this;
    }
    /**
     *
     */
    public function includeContextAndExtra(bool $includeContextAndExtra = false) : self
    {
        $this->includeContextAndExtra = $includeContextAndExtra;
        if ($this->includeContextAndExtra) {
            $this->normalizerFormatter = new NormalizerFormatter();
        }
        return $this;
    }
    /**
     * @param string[] $excludeFields
     */
    public function excludeFields(array $excludeFields = []) : self
    {
        $this->excludeFields = $excludeFields;
        return $this;
    }
    /**
     *
     */
    public function setFormatter(?FormatterInterface $formatter = null) : self
    {
        $this->formatter = $formatter;
        return $this;
    }
    /**
     * Generates attachment field
     *
     * @param (string | mixed[]) $value
     *
     * @return array{title: string, value: string, short: false}
     */
    private function generateAttachmentField(string $title, $value) : array
    {
        $value = is_array($value) ? sprintf('```%s```', \Phabel\Target\Php80\Polyfill::substr($this->stringify($value), 0, 1990)) : $value;
        return array('title' => ucfirst($title), 'value' => $value, 'short' => false);
    }
    /**
     * Generates a collection of attachment fields from array
     *
     * @param mixed[] $data
     *
     * @return array<array{title: string, value: string, short: false}>
     */
    private function generateAttachmentFields(array $data) : array
    {
        /** @var Record $data */
        $normalized = $this->normalizerFormatter->format($data);
        $fields = array();
        foreach ($normalized as $key => $value) {
            $fields[] = $this->generateAttachmentField((string) $key, $value);
        }
        return $fields;
    }
    /**
     * Get a copy of record with fields excluded according to $this->excludeFields
     *
     * @phpstan-param FormattedRecord $record
     *
     * @return mixed[]
     */
    private function removeExcludedFields(array $record) : array
    {
        foreach ($this->excludeFields as $field) {
            $keys = explode('.', $field);
            $node =& $record;
            $lastKey = end($keys);
            foreach ($keys as $key) {
                if (!isset($node[$key])) {
                    break;
                }
                if ($lastKey === $key) {
                    unset($node[$key]);
                    break;
                }
                $node =& $node[$key];
            }
        }
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\ResettableInterface;
use Monolog\Formatter\FormatterInterface;
/**
 * This simple wrapper class can be used to extend handlers functionality.
 *
 * Example: A custom filtering that can be applied to any handler.
 *
 * Inherit from this class and override handle() like this:
 *
 *   public function handle(array $record)
 *   {
 *        if ($record meets certain conditions) {
 *            return false;
 *        }
 *        return $this->handler->handle($record);
 *   }
 *
 * @author Alexey Karapetov <alexey@karapetov.com>
 */
class HandlerWrapper implements HandlerInterface, ProcessableHandlerInterface, FormattableHandlerInterface, ResettableInterface
{
    /**
     * @var HandlerInterface
     */
    protected $handler;
    /**
     *
     */
    public function __construct(HandlerInterface $handler)
    {
        $this->handler = $handler;
    }
    /**
     * {@inheritDoc}
     */
    public function isHandling(array $record) : bool
    {
        return $this->handler->isHandling($record);
    }
    /**
     * {@inheritDoc}
     */
    public function handle(array $record) : bool
    {
        return $this->handler->handle($record);
    }
    /**
     * {@inheritDoc}
     */
    public function handleBatch(array $records) : void
    {
        $this->handler->handleBatch($records);
    }
    /**
     * {@inheritDoc}
     */
    public function close() : void
    {
        $this->handler->close();
    }
    /**
     * {@inheritDoc}
     */
    public function pushProcessor(callable $callback) : HandlerInterface
    {
        if ($this->handler instanceof ProcessableHandlerInterface) {
            $this->handler->pushProcessor($callback);
            return $this;
        }
        throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
    }
    /**
     * {@inheritDoc}
     */
    public function popProcessor() : callable
    {
        if ($this->handler instanceof ProcessableHandlerInterface) {
            return $this->handler->popProcessor();
        }
        throw new \LogicException('The wrapped handler does not implement ' . ProcessableHandlerInterface::class);
    }
    /**
     * {@inheritDoc}
     */
    public function setFormatter(FormatterInterface $formatter) : HandlerInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            $this->handler->setFormatter($formatter);
            return $this;
        }
        throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
    }
    /**
     * {@inheritDoc}
     */
    public function getFormatter() : FormatterInterface
    {
        if ($this->handler instanceof FormattableHandlerInterface) {
            return $this->handler->getFormatter();
        }
        throw new \LogicException('The wrapped handler does not implement ' . FormattableHandlerInterface::class);
    }
    /**
     *
     */
    public function reset()
    {
        if ($this->handler instanceof ResettableInterface) {
            $this->handler->reset();
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Handler;

use Monolog\Formatter\LineFormatter;
use Monolog\Formatter\FormatterInterface;
use Monolog\Utils;
/**
 * Handler sending logs to browser's javascript console with no browser extension required
 *
 * @author Olivier Poitrey <rs@dailymotion.com>
 *
 * @phpstan-import-type FormattedRecord from AbstractProcessingHandler
 */
class BrowserConsoleHandler extends AbstractProcessingHandler
{
    /** @var bool */
    protected static $initialized = false;
    /** @var FormattedRecord[] */
    protected static $records = [];
    /**
     * {@inheritDoc}
     *
     * Formatted output may contain some formatting markers to be transferred to `console.log` using the %c format.
     *
     * Example of formatted string:
     *
     * You can do [[blue text]]{color: blue} or [[green background]]{background-color: green; color: white}
     */
    protected function getDefaultFormatter() : FormatterInterface
    {
        return new LineFormatter('[[%channel%]]{macro: autolabel} [[%level_name%]]{font-weight: bold} %message%');
    }
    /**
     * {@inheritDoc}
     */
    protected function write(array $record) : void
    {
        // Accumulate records
        static::$records[] = $record;
        // Register shutdown handler if not already done
        if (!static::$initialized) {
            static::$initialized = true;
            $this->registerShutdownFunction();
        }
    }
    /**
    * Convert records to javascript console commands and send it to the browser.
    This method is automatically called on PHP shutdown if output is HTML or Javascript.
    */
    public static function send() : void
    {
        $format = static::getResponseFormat();
        if ($format === 'unknown') {
            return;
        }
        if (count(static::$records)) {
            if ($format === 'html') {
                static::writeOutput('<script>' . static::generateScript() . '</script>');
            } elseif ($format === 'js') {
                static::writeOutput(static::generateScript());
            }
            static::resetStatic();
        }
    }
    /**
     *
     */
    public function close() : void
    {
        self::resetStatic();
    }
    /**
     *
     */
    public function reset()
    {
        parent::reset();
        self::resetStatic();
    }
    /**
     * Forget all logged records
     */
    public static function resetStatic() : void
    {
        static::$records = [];
    }
    /**
     * Wrapper for register_shutdown_function to allow overriding
     */
    protected function registerShutdownFunction() : void
    {
        if (PHP_SAPI !== 'cli') {
            register_shutdown_function(['Monolog\\Handler\\BrowserConsoleHandler', 'send']);
        }
    }
    /**
     * Wrapper for echo to allow overriding
     */
    protected static function writeOutput(string $str) : void
    {
        echo $str;
    }
    /**
    * Checks the format of the response
    *
    * If Content-Type is set to application/javascript or text/javascript -> js
    If Content-Type is set to text/html, or is unset -> html
    If Content-Type is anything else -> unknown
    *
    * @return string One of 'js', 'html' or 'unknown'
    */
    protected static function getResponseFormat() : string
    {
        // Check content type
        foreach (headers_list() as $header) {
            if (stripos($header, 'content-type:') === 0) {
                // This handler only works with HTML and javascript outputs
                // text/javascript is obsolete in favour of application/javascript, but still used
                if (stripos($header, 'application/javascript') !== false || stripos($header, 'text/javascript') !== false) {
                    return 'js';
                }
                if (stripos($header, 'text/html') === false) {
                    return 'unknown';
                }
                break;
            }
        }
        return 'html';
    }
    /**
     *
     */
    private static function generateScript() : string
    {
        $script = [];
        foreach (static::$records as $record) {
            $context = static::dump('Context', $record['context']);
            $extra = static::dump('Extra', $record['extra']);
            if (empty($context) && empty($extra)) {
                $script[] = static::call_array('log', static::handleStyles($record['formatted']));
            } else {
                $script = array_merge($script, [static::call_array('groupCollapsed', static::handleStyles($record['formatted']))], $context, $extra, [static::call('groupEnd')]);
            }
        }
        return "(function (c) {if (c && c.groupCollapsed) {\n" . implode("\n", $script) . "\n}})(console);";
    }
    /**
     * @return string[]
     */
    private static function handleStyles(string $formatted) : array
    {
        $args = [];
        $format = '%c' . $formatted;
        preg_match_all('/\\[\\[(.*?)\\]\\]\\{([^}]*)\\}/s', $format, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER);
        foreach (array_reverse($matches) as $match) {
            $args[] = '"font-weight: normal"';
            $args[] = static::quote(static::handleCustomStyles($match[2][0], $match[1][0]));
            $pos = $match[0][1];
            $format = Utils::substr($format, 0, $pos) . '%c' . $match[1][0] . '%c' . Utils::substr($format, $pos + strlen($match[0][0]));
        }
        $args[] = static::quote('font-weight: normal');
        $args[] = static::quote($format);
        return array_reverse($args);
    }
    /**
     *
     */
    private static function handleCustomStyles(string $style, string $string) : string
    {
        static $colors = ['blue', 'green', 'red', 'magenta', 'orange', 'black', 'grey'];
        static $labels = [];
        $style = preg_replace_callback('/macro\\s*:(.*?)(?:;|$)/', function (array $m) use($string, &$colors, &$labels) {
            if (trim($m[1]) === 'autolabel') {
                // Format the string as a label with consistent auto assigned background color
                if (!isset($labels[$string])) {
                    $labels[$string] = $colors[count($labels) % count($colors)];
                }
                $color = $labels[$string];
                return "background-color: {$color}; color: white; border-radius: 3px; padding: 0 2px 0 2px";
            }
            return $m[1];
        }, $style);
        if (null === $style) {
            $pcreErrorCode = preg_last_error();
            throw new \RuntimeException('Failed to run preg_replace_callback: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
        }
        return $style;
    }
    /**
     * @param mixed[] $dict
     * @return mixed[]
     */
    private static function dump(string $title, array $dict) : array
    {
        $script = [];
        $dict = array_filter($dict);
        if (empty($dict)) {
            return $script;
        }
        $script[] = static::call('log', static::quote('%c%s'), static::quote('font-weight: bold'), static::quote($title));
        foreach ($dict as $key => $value) {
            $value = json_encode($value);
            if (empty($value)) {
                $value = static::quote('');
            }
            $script[] = static::call('log', static::quote('%s: %o'), static::quote((string) $key), $value);
        }
        return $script;
    }
    /**
     *
     */
    private static function quote(string $arg) : string
    {
        return '"' . addcslashes($arg, "\"\n\\") . '"';
    }
    /**
     * @param mixed $args
     */
    private static function call(...$args) : string
    {
        $method = array_shift($args);
        if (!is_string($method)) {
            throw new \UnexpectedValueException('Expected the first arg to be a string, got: ' . var_export($method, true));
        }
        return static::call_array($method, $args);
    }
    /**
     * @param mixed[] $args
     */
    private static function call_array(string $method, array $args) : string
    {
        return 'c.' . $method . '(' . implode(', ', $args) . ');';
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

/**
 * Handler or Processor implementing this interface will be reset when Logger::reset() is called.
 *
 * Resetting ends a log cycle gets them back to their initial state.
 *
 * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
 * state, and getting it back to a state in which it can receive log records again.
 *
 * This is useful in case you want to avoid logs leaking between two requests or jobs when you
 * have a long running process like a worker or an application server serving multiple requests
 * in one process.
 *
 * @author GrÃ©goire Pineau <lyrixx@lyrixx.info>
 */
interface ResettableInterface
{
    /**
     * @return void
     */
    public function reset();
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

final class Utils
{
    const DEFAULT_JSON_FLAGS = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION | JSON_INVALID_UTF8_SUBSTITUTE | JSON_PARTIAL_OUTPUT_ON_ERROR;
    /**
     *
     */
    public static function getClass(object $object) : string
    {
        $class = \get_class($object);
        if (false === ($pos = \strpos($class, "@anonymous\x00"))) {
            return $class;
        }
        if (false === ($parent = \get_parent_class($class))) {
            return \Phabel\Target\Php80\Polyfill::substr($class, 0, $pos + 10);
        }
        return $parent . '@anonymous';
    }
    /**
     *
     */
    public static function substr(string $string, int $start, ?int $length = null) : string
    {
        if (extension_loaded('mbstring')) {
            return mb_strcut($string, $start, $length);
        }
        return \Phabel\Target\Php80\Polyfill::substr($string, $start, null === $length ? strlen($string) : $length);
    }
    /**
     * Makes sure if a relative path is passed in it is turned into an absolute path
     *
     * @param string $streamUrl stream URL or path without protocol
     */
    public static function canonicalizePath(string $streamUrl) : string
    {
        $prefix = '';
        if ('file://' === \Phabel\Target\Php80\Polyfill::substr($streamUrl, 0, 7)) {
            $streamUrl = \Phabel\Target\Php80\Polyfill::substr($streamUrl, 7);
            $prefix = 'file://';
        }
        // other type of stream, not supported
        if (false !== strpos($streamUrl, '://')) {
            return $streamUrl;
        }
        // already absolute
        if (\Phabel\Target\Php80\Polyfill::substr($streamUrl, 0, 1) === '/' || \Phabel\Target\Php80\Polyfill::substr($streamUrl, 1, 1) === ':' || \Phabel\Target\Php80\Polyfill::substr($streamUrl, 0, 2) === '\\\\') {
            return $prefix . $streamUrl;
        }
        $streamUrl = getcwd() . '/' . $streamUrl;
        return $prefix . $streamUrl;
    }
    /**
     * Return the JSON representation of a value
     *
     * @param mixed $data
     * @param int $encodeFlags flags to pass to json encode, defaults to DEFAULT_JSON_FLAGS
     * @param bool $ignoreErrors whether to ignore encoding errors or to throw on error, when ignored and the encoding fails, "null" is returned which is valid json for null
     * @throws \RuntimeException if encoding fails and errors are not ignored
     * @return string when errors are ignored and the encoding fails, "null" is returned which is valid json for null
     */
    public static function jsonEncode($data, ?int $encodeFlags = null, bool $ignoreErrors = false) : string
    {
        if (null === $encodeFlags) {
            $encodeFlags = self::DEFAULT_JSON_FLAGS;
        }
        if ($ignoreErrors) {
            $json = @json_encode($data, $encodeFlags);
            if (false === $json) {
                return 'null';
            }
            return $json;
        }
        $json = json_encode($data, $encodeFlags);
        if (false === $json) {
            $json = self::handleJsonError(json_last_error(), $data);
        }
        return $json;
    }
    /**
    * Handle a json_encode failure.
    *
    * If the failure is due to invalid string encoding, try to clean the
    input and encode again. If the second encoding attempt fails, the
    initial error is not encoding related or the input can't be cleaned then
    raise a descriptive exception.
    *
    * @param int $code return code of json_last_error function
    * @param mixed $data data that was meant to be encoded
    * @param int $encodeFlags flags to pass to json encode, defaults to JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION
    * @throws \RuntimeException if failure can't be corrected
    * @return string JSON encoded data after error correction
    */
    public static function handleJsonError(int $code, $data, ?int $encodeFlags = null) : string
    {
        if ($code !== JSON_ERROR_UTF8) {
            self::throwEncodeError($code, $data);
        }
        if (is_string($data)) {
            self::detectAndCleanUtf8($data);
        } elseif (is_array($data)) {
            array_walk_recursive($data, array('Monolog\\Utils', 'detectAndCleanUtf8'));
        } else {
            self::throwEncodeError($code, $data);
        }
        if (null === $encodeFlags) {
            $encodeFlags = self::DEFAULT_JSON_FLAGS;
        }
        $json = json_encode($data, $encodeFlags);
        if ($json === false) {
            self::throwEncodeError(json_last_error(), $data);
        }
        return $json;
    }
    /**
     * @internal
     */
    public static function pcreLastErrorMessage(int $code) : string
    {
        if (PHP_VERSION_ID >= 80000) {
            return preg_last_error_msg();
        }
        $constants = get_defined_constants(true)['pcre'];
        $constants = array_filter($constants, function ($key) {
            return \Phabel\Target\Php80\Polyfill::substr($key, -6) == '_ERROR';
        }, ARRAY_FILTER_USE_KEY);
        $constants = array_flip($constants);
        return $constants[$code] ?? 'UNDEFINED_ERROR';
    }
    /**
     * Throws an exception according to a given code with a customized message
     *
     * @param int $code return code of json_last_error function
     * @param mixed $data data that was meant to be encoded
     * @throws \RuntimeException
     *
     * @return never
     */
    private static function throwEncodeError(int $code, $data) : void
    {
        switch ($code) {
            case JSON_ERROR_DEPTH:
                $msg = 'Maximum stack depth exceeded';
                break;
            case JSON_ERROR_STATE_MISMATCH:
                $msg = 'Underflow or the modes mismatch';
                break;
            case JSON_ERROR_CTRL_CHAR:
                $msg = 'Unexpected control character found';
                break;
            case JSON_ERROR_UTF8:
                $msg = 'Malformed UTF-8 characters, possibly incorrectly encoded';
                break;
            default:
                $msg = 'Unknown error';
        }
        throw new \RuntimeException('JSON encoding failed: ' . $msg . '. Encoding: ' . var_export($data, true));
    }
    /**
    * Detect invalid UTF-8 string characters and convert to valid UTF-8.
    *
    * Valid UTF-8 input will be left unmodified, but strings containing
    invalid UTF-8 codepoints will be reencoded as UTF-8 with an assumed
    original encoding of ISO-8859-15. This conversion may result in
    incorrect output if the actual encoding was not ISO-8859-15, but it
    will be clean UTF-8 output and will not rely on expensive and fragile
    detection algorithms.
    *
    * Function converts the input in place in the passed variable so that it
    can be used as a callback for array_walk_recursive.
    *
    * @param mixed $data Input to check and convert if needed, passed by ref
    */
    private static function detectAndCleanUtf8(&$data) : void
    {
        if (is_string($data) && !preg_match('//u', $data)) {
            $data = preg_replace_callback('/[\\x80-\\xFF]+/', function ($m) {
                return utf8_encode($m[0]);
            }, $data);
            if (!is_string($data)) {
                $pcreErrorCode = preg_last_error();
                throw new \RuntimeException('Failed to preg_replace_callback: ' . $pcreErrorCode . ' / ' . self::pcreLastErrorMessage($pcreErrorCode));
            }
            $data = str_replace(['Â¤', 'Â¦', 'Â¨', 'Â´', 'Â¸', 'Â¼', 'Â½', 'Â¾'], ['â‚¬', 'Å ', 'Å¡', 'Å½', 'Å¾', 'Å’', 'Å“', 'Å¸'], $data);
        }
    }
    /**
     * Converts a string with a valid 'memory_limit' format, to bytes.
     *
     * @param (string | false) $val
     * @return (int | false) Returns an integer representing bytes. Returns FALSE in case of error.
     */
    public static function expandIniShorthandBytes($val)
    {
        if (!is_string($val)) {
            return false;
        }
        // support -1
        if ((int) $val < 0) {
            return (int) $val;
        }
        if (!preg_match('/^\\s*(?<val>\\d+)(?:\\.\\d+)?\\s*(?<unit>[gmk]?)\\s*$/i', $val, $match)) {
            return false;
        }
        $val = (int) $match['val'];
        switch (strtolower($match['unit'] ?? '')) {
            case 'g':
                $val *= 1024;
            case 'm':
                $val *= 1024;
            case 'k':
                $val *= 1024;
        }
        return $val;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Test;

use Monolog\Logger;
use Monolog\DateTimeImmutable;
use Monolog\Formatter\FormatterInterface;
/**
 * Lets you easily generate log records and a dummy formatter for testing purposes
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
class TestCase extends \PHPUnit\Framework\TestCase
{
    /**
     * @param mixed[] $context
     *
     * @return array Record
     *
     * @phpstan-param Level $level
     * @phpstan-return Record
     */
    protected function getRecord(int $level = Logger::WARNING, string $message = 'test', array $context = []) : array
    {
        return ['message' => (string) $message, 'context' => $context, 'level' => $level, 'level_name' => Logger::getLevelName($level), 'channel' => 'test', 'datetime' => new DateTimeImmutable(true), 'extra' => []];
    }
    /**
     * @phpstan-return Record[]
     */
    protected function getMultipleRecords() : array
    {
        return [$this->getRecord(Logger::DEBUG, 'debug message 1'), $this->getRecord(Logger::DEBUG, 'debug message 2'), $this->getRecord(Logger::INFO, 'information'), $this->getRecord(Logger::WARNING, 'warning'), $this->getRecord(Logger::ERROR, 'error')];
    }
    /**
     *
     */
    protected function getIdentityFormatter() : FormatterInterface
    {
        $formatter = $this->createMock(FormatterInterface::class);
        $formatter->expects($this->any())->method('format')->will($this->returnCallback(function ($record) {
            return $record['message'];
        }));
        return $formatter;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Injects url/method and remote IP of the current web request in all records
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class WebProcessor implements ProcessorInterface
{
    /**
     * @var array<string, mixed>|\ArrayAccess<string, mixed>
     */
    protected $serverData;
    /**
     * Default fields
     *
     * Array is structured as [key in record.extra => key in $serverData]
     *
     * @var array<string, string>
     */
    protected $extraFields = ['url' => 'REQUEST_URI', 'ip' => 'REMOTE_ADDR', 'http_method' => 'REQUEST_METHOD', 'server' => 'SERVER_NAME', 'referrer' => 'HTTP_REFERER'];
    /**
     * @param (array<string, mixed> | \ArrayAccess<string, mixed> | null) $serverData Array or object w/ ArrayAccess that provides access to the $_SERVER data
     * @param (array<string, string> | null) $extraFields Field names and the related key inside $serverData to be added. If not provided it defaults to: url, ip, http_method, server, referrer
     */
    public function __construct($serverData = null, array $extraFields = null)
    {
        if (null === $serverData) {
            $this->serverData =& $_SERVER;
        } elseif (is_array($serverData) || $serverData instanceof \ArrayAccess) {
            $this->serverData = $serverData;
        } else {
            throw new \UnexpectedValueException('$serverData must be an array or object implementing ArrayAccess.');
        }
        if (isset($this->serverData['UNIQUE_ID'])) {
            $this->extraFields['unique_id'] = 'UNIQUE_ID';
        }
        if (null !== $extraFields) {
            if (isset($extraFields[0])) {
                foreach (array_keys($this->extraFields) as $fieldName) {
                    if (!in_array($fieldName, $extraFields)) {
                        unset($this->extraFields[$fieldName]);
                    }
                }
            } else {
                $this->extraFields = $extraFields;
            }
        }
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        // skip processing if for some reason request data
        // is not present (CLI or wonky SAPIs)
        if (!isset($this->serverData['REQUEST_URI'])) {
            return $record;
        }
        $record['extra'] = $this->appendExtraFields($record['extra']);
        return $record;
    }
    /**
     *
     */
    public function addExtraField(string $extraName, string $serverName) : self
    {
        $this->extraFields[$extraName] = $serverName;
        return $this;
    }
    /**
     * @param mixed[] $extra
     * @return mixed[]
     */
    private function appendExtraFields(array $extra) : array
    {
        foreach ($this->extraFields as $extraName => $serverName) {
            $extra[$extraName] = $this->serverData[$serverName] ?? null;
        }
        return $extra;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Injects memory_get_usage in all records
 *
 * @see Monolog\Processor\MemoryProcessor::__construct() for options
 * @author Rob Jensen
 */
class MemoryUsageProcessor extends MemoryProcessor
{
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $usage = memory_get_usage($this->realUsage);
        if ($this->useFormatting) {
            $usage = $this->formatBytes($usage);
        }
        $record['extra']['memory_usage'] = $usage;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\ResettableInterface;
/**
 * Adds a unique identifier into records
 *
 * @author Simon MÃ¶nch <sm@webfactory.de>
 */
class UidProcessor implements ProcessorInterface, ResettableInterface
{
    /** @var string */
    private $uid;
    /**
     *
     */
    public function __construct(int $length = 7)
    {
        if ($length > 32 || $length < 1) {
            throw new \InvalidArgumentException('The uid length must be an integer between 1 and 32');
        }
        $this->uid = $this->generateUid($length);
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $record['extra']['uid'] = $this->uid;
        return $record;
    }
    /**
     *
     */
    public function getUid() : string
    {
        return $this->uid;
    }
    /**
     *
     */
    public function reset()
    {
        $this->uid = $this->generateUid(strlen($this->uid));
    }
    /**
     *
     */
    private function generateUid(int $length) : string
    {
        return \Phabel\Target\Php80\Polyfill::substr(bin2hex(random_bytes((int) ceil($length / 2))), 0, $length);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Some methods that are common for all memory processors
 *
 * @author Rob Jensen
 */
abstract class MemoryProcessor implements ProcessorInterface
{
    /**
     * @var bool If true, get the real size of memory allocated from system. Else, only the memory used by emalloc() is reported.
     */
    protected $realUsage;
    /**
     * @var bool If true, then format memory size to human readable string (MB, KB, B depending on size)
     */
    protected $useFormatting;
    /**
     * @param bool $realUsage Set this to true to get the real size of memory allocated from system.
     * @param bool $useFormatting If true, then format memory size to human readable string (MB, KB, B depending on size)
     */
    public function __construct(bool $realUsage = true, bool $useFormatting = true)
    {
        $this->realUsage = $realUsage;
        $this->useFormatting = $useFormatting;
    }
    /**
     * Formats bytes into a human readable string if $this->useFormatting is true, otherwise return $bytes as is
     *
     * @param int $bytes
     * @return (string | int) Formatted string if $this->useFormatting is true, otherwise return $bytes as int
     */
    protected function formatBytes(int $bytes)
    {
        if (!$this->useFormatting) {
            return $bytes;
        }
        if ($bytes > 1024 * 1024) {
            return round($bytes / 1024 / 1024, 2) . ' MB';
        } elseif ($bytes > 1024) {
            return round($bytes / 1024, 2) . ' KB';
        }
        return $bytes . ' B';
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * An optional interface to allow labelling Monolog processors.
 *
 * @author Nicolas Grekas <p@tchwork.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
interface ProcessorInterface
{
    /**
     * @return array The processed record
     *
     * @phpstan-param Record $record
     * @phpstan-return Record
     */
    public function __invoke(array $record);
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Adds value of getmypid into records
 *
 * @author Andreas HÃ¶rnicke
 */
class ProcessIdProcessor implements ProcessorInterface
{
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $record['extra']['process_id'] = getmypid();
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Injects memory_get_peak_usage in all records
 *
 * @see Monolog\Processor\MemoryProcessor::__construct() for options
 * @author Rob Jensen
 */
class MemoryPeakUsageProcessor extends MemoryProcessor
{
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $usage = memory_get_peak_usage($this->realUsage);
        if ($this->useFormatting) {
            $usage = $this->formatBytes($usage);
        }
        $record['extra']['memory_peak_usage'] = $usage;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Injects value of gethostname in all records
 */
class HostnameProcessor implements ProcessorInterface
{
    /** @var string */
    private static $host;
    /**
     *
     */
    public function __construct()
    {
        self::$host = (string) gethostname();
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $record['extra']['hostname'] = self::$host;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\Utils;
/**
 * Processes a record's message according to PSR-3 rules
 *
 * It replaces {foo} with the value from $context['foo']
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class PsrLogMessageProcessor implements ProcessorInterface
{
    public const SIMPLE_DATE = "Y-m-d\\TH:i:s.uP";
    /** @var string|null */
    private $dateFormat;
    /** @var bool */
    private $removeUsedContextFields;
    /**
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     * @param bool $removeUsedContextFields If set to true the fields interpolated into message gets unset
     */
    public function __construct(?string $dateFormat = null, bool $removeUsedContextFields = false)
    {
        $this->dateFormat = $dateFormat;
        $this->removeUsedContextFields = $removeUsedContextFields;
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        if (false === strpos($record['message'], '{')) {
            return $record;
        }
        $replacements = [];
        foreach ($record['context'] as $key => $val) {
            $placeholder = '{' . $key . '}';
            if (strpos($record['message'], $placeholder) === false) {
                continue;
            }
            if (is_null($val) || is_scalar($val) || is_object($val) && method_exists($val, "__toString")) {
                $replacements[$placeholder] = $val;
            } elseif ($val instanceof \DateTimeInterface) {
                if (!$this->dateFormat && $val instanceof \Monolog\DateTimeImmutable) {
                    // handle monolog dates using __toString if no specific dateFormat was asked for
                    // so that it follows the useMicroseconds flag
                    $replacements[$placeholder] = (string) $val;
                } else {
                    $replacements[$placeholder] = $val->format($this->dateFormat ?: static::SIMPLE_DATE);
                }
            } elseif (is_object($val)) {
                $replacements[$placeholder] = '[object ' . Utils::getClass($val) . ']';
            } elseif (is_array($val)) {
                $replacements[$placeholder] = 'array' . Utils::jsonEncode($val, null, true);
            } else {
                $replacements[$placeholder] = '[' . gettype($val) . ']';
            }
            if ($this->removeUsedContextFields) {
                unset($record['context'][$key]);
            }
        }
        $record['message'] = strtr($record['message'], $replacements);
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Injects Hg branch and Hg revision number in all records
 *
 * @author Jonathan A. Schweder <jonathanschweder@gmail.com>
 *
 * @phpstan-import-type LevelName from \Monolog\Logger
 * @phpstan-import-type Level from \Monolog\Logger
 */
class MercurialProcessor implements ProcessorInterface
{
    /** @var Level */
    private $level;
    /** @var array{branch: string, revision: string}|array<never>|null */
    private static $cache = null;
    /**
     * @param (int | string) $level The minimum logging level at which this Processor will be triggered
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        // return if the level is not high enough
        if ($record['level'] < $this->level) {
            return $record;
        }
        $record['extra']['hg'] = self::getMercurialInfo();
        return $record;
    }
    /**
     * @return (array{branch: string, revision: string} | array<never>)
     */
    private static function getMercurialInfo() : array
    {
        if (self::$cache) {
            return self::$cache;
        }
        $result = explode(' ', trim(`hg id -nb`));
        if (count($result) >= 3) {
            return self::$cache = ['branch' => $result[1], 'revision' => $result[2]];
        }
        return self::$cache = [];
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Injects Git branch and Git commit SHA in all records
 *
 * @author Nick Otter
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class GitProcessor implements ProcessorInterface
{
    /** @var int */
    private $level;
    /** @var array{branch: string, commit: string}|array<never>|null */
    private static $cache = null;
    /**
     * @param (string | int) $level The minimum logging level at which this Processor will be triggered
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG)
    {
        $this->level = Logger::toMonologLevel($level);
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        // return if the level is not high enough
        if ($record['level'] < $this->level) {
            return $record;
        }
        $record['extra']['git'] = self::getGitInfo();
        return $record;
    }
    /**
     * @return (array{branch: string, commit: string} | array<never>)
     */
    private static function getGitInfo() : array
    {
        if (self::$cache) {
            return self::$cache;
        }
        $branches = `git branch -v --no-abbrev`;
        if ($branches && preg_match('{^\\* (.+?)\\s+([a-f0-9]{40})(?:\\s|$)}m', $branches, $matches)) {
            return self::$cache = ['branch' => $matches[1], 'commit' => $matches[2]];
        }
        return self::$cache = [];
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

/**
 * Adds a tags array into record
 *
 * @author Martijn Riemers
 */
class TagProcessor implements ProcessorInterface
{
    /** @var string[] */
    private $tags;
    /**
     * @param string[] $tags
     */
    public function __construct(array $tags = [])
    {
        $this->setTags($tags);
    }
    /**
     * @param string[] $tags
     */
    public function addTags(array $tags = []) : self
    {
        $this->tags = array_merge($this->tags, $tags);
        return $this;
    }
    /**
     * @param string[] $tags
     */
    public function setTags(array $tags = []) : self
    {
        $this->tags = $tags;
        return $this;
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        $record['extra']['tags'] = $this->tags;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Processor;

use Monolog\Logger;
use Psr\Log\LogLevel;
/**
 * Injects line/file:class/function where the log message came from
 *
 * Warning: This only works if the handler processes the logs directly.
 * If you put the processor on a handler that is behind a FingersCrossedHandler
 * for example, the processor will only be called once the trigger level is reached,
 * and all the log records will have the same file/line/.. data from the call that
 * triggered the FingersCrossedHandler.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class IntrospectionProcessor implements ProcessorInterface
{
    /** @var int */
    private $level;
    /** @var string[] */
    private $skipClassesPartials;
    /** @var int */
    private $skipStackFramesCount;
    /** @var string[] */
    private $skipFunctions = ['call_user_func', 'call_user_func_array'];
    /**
     * @param (string | int) $level The minimum logging level at which this Processor will be triggered
     * @param string[] $skipClassesPartials
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function __construct($level = Logger::DEBUG, array $skipClassesPartials = [], int $skipStackFramesCount = 0)
    {
        $this->level = Logger::toMonologLevel($level);
        $this->skipClassesPartials = array_merge(['Monolog\\'], $skipClassesPartials);
        $this->skipStackFramesCount = $skipStackFramesCount;
    }
    /**
     * {@inheritDoc}
     */
    public function __invoke(array $record) : array
    {
        // return if the level is not high enough
        if ($record['level'] < $this->level) {
            return $record;
        }
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
        // skip first since it's always the current method
        array_shift($trace);
        // the call_user_func call is also skipped
        array_shift($trace);
        $i = 0;
        while ($this->isTraceClassOrSkippedFunction($trace, $i)) {
            if (isset($trace[$i]['class'])) {
                foreach ($this->skipClassesPartials as $part) {
                    if (strpos($trace[$i]['class'], $part) !== false) {
                        $i++;
                        continue 2;
                    }
                }
            } elseif (in_array($trace[$i]['function'], $this->skipFunctions)) {
                $i++;
                continue;
            }
            break;
        }
        $i += $this->skipStackFramesCount;
        // we should have the call source now
        $record['extra'] = array_merge($record['extra'], ['file' => isset($trace[$i - 1]['file']) ? $trace[$i - 1]['file'] : null, 'line' => isset($trace[$i - 1]['line']) ? $trace[$i - 1]['line'] : null, 'class' => isset($trace[$i]['class']) ? $trace[$i]['class'] : null, 'function' => isset($trace[$i]['function']) ? $trace[$i]['function'] : null]);
        return $record;
    }
    /**
     * @param array[] $trace
     */
    private function isTraceClassOrSkippedFunction(array $trace, int $index) : bool
    {
        if (!isset($trace[$index])) {
            return false;
        }
        return isset($trace[$index]['class']) || in_array($trace[$index]['function'], $this->skipFunctions);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use DateTimeZone;
use Monolog\Handler\HandlerInterface;
use Psr\Log\LoggerInterface;
use Psr\Log\InvalidArgumentException;
use Psr\Log\LogLevel;
use Throwable;
use Stringable;
/**
 * Monolog log channel
 *
 * It contains a stack of Handlers and a stack of Processors,
 * and uses them to store records that are added to it.
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-type Level Logger::DEBUG|Logger::INFO|Logger::NOTICE|Logger::WARNING|Logger::ERROR|Logger::CRITICAL|Logger::ALERT|Logger::EMERGENCY
 * @phpstan-type LevelName 'DEBUG'|'INFO'|'NOTICE'|'WARNING'|'ERROR'|'CRITICAL'|'ALERT'|'EMERGENCY'
 * @phpstan-type Record array{message: string, context: mixed[], level: Level, level_name: LevelName, channel: string, datetime: \DateTimeImmutable, extra: mixed[]}
 */
class Logger implements LoggerInterface, ResettableInterface
{
    /**
     * Detailed debug information
     */
    public const DEBUG = 100;
    /**
     * Interesting events
     *
     * Examples: User logs in, SQL logs.
     */
    public const INFO = 200;
    /**
     * Uncommon events
     */
    public const NOTICE = 250;
    /**
     * Exceptional occurrences that are not errors
     *
     * Examples: Use of deprecated APIs, poor use of an API,
     * undesirable things that are not necessarily wrong.
     */
    public const WARNING = 300;
    /**
     * Runtime errors
     */
    public const ERROR = 400;
    /**
     * Critical conditions
     *
     * Example: Application component unavailable, unexpected exception.
     */
    public const CRITICAL = 500;
    /**
     * Action must be taken immediately
     *
     * Example: Entire website down, database unavailable, etc.
     * This should trigger the SMS alerts and wake you up.
     */
    public const ALERT = 550;
    /**
     * Urgent alert.
     */
    public const EMERGENCY = 600;
    /**
     * Monolog API version
     *
     * This is only bumped when API breaks are done and should
     * follow the major version of the library
     *
     * @var int
     */
    public const API = 2;
    /**
     * This is a static variable and not a constant to serve as an extension point for custom levels
     *
     * @var array<int, string> $levels Logging levels with the levels as key
     *
     * @phpstan-var array<Level, LevelName> $levels Logging levels with the levels as key
     */
    protected static $levels = [self::DEBUG => 'DEBUG', self::INFO => 'INFO', self::NOTICE => 'NOTICE', self::WARNING => 'WARNING', self::ERROR => 'ERROR', self::CRITICAL => 'CRITICAL', self::ALERT => 'ALERT', self::EMERGENCY => 'EMERGENCY'];
    /**
     * @var string
     */
    protected $name;
    /**
     * The handler stack
     *
     * @var HandlerInterface[]
     */
    protected $handlers;
    /**
     * Processors that will process all log records
     *
     * To process records of a single handler instead, add the processor on that specific handler
     *
     * @var callable[]
     */
    protected $processors;
    /**
     * @var bool
     */
    protected $microsecondTimestamps = true;
    /**
     * @var DateTimeZone
     */
    protected $timezone;
    /**
     * @var callable|null
     */
    protected $exceptionHandler;
    /**
     * @psalm-param array<callable(array ): array> $processors
     *
     * @param string $name The logging channel, a simple descriptive name that is attached to all log records
     * @param HandlerInterface[] $handlers Optional stack of handlers, the first one in the array is called first, etc.
     * @param callable[] $processors Optional array of processors
     * @param (DateTimeZone | null) $timezone Optional timezone, if not provided date_default_timezone_get() will be used
     */
    public function __construct(string $name, array $handlers = [], array $processors = [], ?DateTimeZone $timezone = null)
    {
        $this->name = $name;
        $this->setHandlers($handlers);
        $this->processors = $processors;
        $this->timezone = $timezone ?: new DateTimeZone(date_default_timezone_get() ?: 'UTC');
    }
    /**
     *
     */
    public function getName() : string
    {
        return $this->name;
    }
    /**
     * Return a new cloned instance with the name changed
     */
    public function withName(string $name) : self
    {
        $new = clone $this;
        $new->name = $name;
        return $new;
    }
    /**
     * Pushes a handler on to the stack.
     */
    public function pushHandler(HandlerInterface $handler) : self
    {
        array_unshift($this->handlers, $handler);
        return $this;
    }
    /**
     * Pops a handler from the stack
     *
     * @throws \LogicException If empty handler stack
     */
    public function popHandler() : HandlerInterface
    {
        if (!$this->handlers) {
            throw new \LogicException('You tried to pop from an empty handler stack.');
        }
        return array_shift($this->handlers);
    }
    /**
     * Set handlers, replacing all existing ones.
     *
     * If a map is passed, keys will be ignored.
     *
     * @param HandlerInterface[] $handlers
     */
    public function setHandlers(array $handlers) : self
    {
        $this->handlers = [];
        foreach (array_reverse($handlers) as $handler) {
            $this->pushHandler($handler);
        }
        return $this;
    }
    /**
     * @return HandlerInterface[]
     */
    public function getHandlers() : array
    {
        return $this->handlers;
    }
    /**
     * Adds a processor on to the stack.
     */
    public function pushProcessor(callable $callback) : self
    {
        array_unshift($this->processors, $callback);
        return $this;
    }
    /**
     * Removes the processor on top of the stack and returns it.
     *
     * @throws \LogicException If empty processor stack
     * @return callable
     */
    public function popProcessor() : callable
    {
        if (!$this->processors) {
            throw new \LogicException('You tried to pop from an empty processor stack.');
        }
        return array_shift($this->processors);
    }
    /**
     * @return callable[]
     */
    public function getProcessors() : array
    {
        return $this->processors;
    }
    /**
    * Control the use of microsecond resolution timestamps in the 'datetime'
    member of new records.
    *
    * As of PHP7.1 microseconds are always included by the engine, so
    there is no performance penalty and Monolog 2 enabled microseconds
    by default. This function lets you disable them though in case you want
    to suppress microseconds from the output.
    *
    * @param bool $micro True to use microtime() to create timestamps
    */
    public function useMicrosecondTimestamps(bool $micro) : void
    {
        $this->microsecondTimestamps = $micro;
    }
    /**
     * Adds a log record.
     *
     * @param int $level The logging level
     * @param string $message The log message
     * @param mixed[] $context The log context
     * @return bool Whether the record has been processed
     *
     * @phpstan-param Level $level
     */
    public function addRecord(int $level, string $message, array $context = []) : bool
    {
        $offset = 0;
        $record = null;
        foreach ($this->handlers as $handler) {
            if (null === $record) {
                // skip creating the record as long as no handler is going to handle it
                if (!$handler->isHandling(['level' => $level])) {
                    continue;
                }
                $levelName = static::getLevelName($level);
                $record = ['message' => $message, 'context' => $context, 'level' => $level, 'level_name' => $levelName, 'channel' => $this->name, 'datetime' => new DateTimeImmutable($this->microsecondTimestamps, $this->timezone), 'extra' => []];
                try {
                    foreach ($this->processors as $processor) {
                        $record = $processor($record);
                    }
                } catch (Throwable $e) {
                    $this->handleException($e, $record);
                    return true;
                }
            }
            // once the record exists, send it to all handlers as long as the bubbling chain is not interrupted
            try {
                if (true === $handler->handle($record)) {
                    break;
                }
            } catch (Throwable $e) {
                $this->handleException($e, $record);
                return true;
            }
        }
        return null !== $record;
    }
    /**
    * Ends a log cycle and frees all resources used by handlers.
    *
    * Closing a Handler means flushing all buffers and freeing any open resources/handles.
    Handlers that have been closed should be able to accept log records again and re-open
    themselves on demand, but this may not always be possible depending on implementation.
    *
    * This is useful at the end of a request and will be called automatically on every handler
    when they get destructed.
    */
    public function close() : void
    {
        foreach ($this->handlers as $handler) {
            $handler->close();
        }
    }
    /**
    * Ends a log cycle and resets all handlers and processors to their initial state.
    *
    * Resetting a Handler or a Processor means flushing/cleaning all buffers, resetting internal
    state, and getting it back to a state in which it can receive log records again.
    *
    * This is useful in case you want to avoid logs leaking between two requests or jobs when you
    have a long running process like a worker or an application server serving multiple requests
    in one process.
    */
    public function reset() : void
    {
        foreach ($this->handlers as $handler) {
            if ($handler instanceof ResettableInterface) {
                $handler->reset();
            }
        }
        foreach ($this->processors as $processor) {
            if ($processor instanceof ResettableInterface) {
                $processor->reset();
            }
        }
    }
    /**
     * Gets all supported logging levels.
     *
     * @return array<string, int> Assoc array with human-readable level names => level codes.
     * @phpstan-return array<LevelName, Level>
     */
    public static function getLevels() : array
    {
        return array_flip(static::$levels);
    }
    /**
     * Gets the name of the logging level.
     *
     * @throws \Psr\Log\InvalidArgumentException If level is not defined
     *
     * @phpstan-param Level $level
     * @phpstan-return LevelName
     */
    public static function getLevelName(int $level) : string
    {
        if (!isset(static::$levels[$level])) {
            throw new InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . implode(', ', array_keys(static::$levels)));
        }
        return static::$levels[$level];
    }
    /**
     * Converts PSR-3 levels to Monolog ones if necessary
     *
     * @param (string | int) $level Level number (monolog) or name (PSR-3)
     * @throws \Psr\Log\InvalidArgumentException If level is not defined
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     * @phpstan-return Level
     */
    public static function toMonologLevel($level) : int
    {
        if (is_string($level)) {
            if (is_numeric($level)) {
                /** @phpstan-ignore-next-line */
                return intval($level);
            }
            // Contains chars of all log levels and avoids using strtoupper() which may have
            // strange results depending on locale (for example, "i" will become "Ä°" in Turkish locale)
            $upper = strtr($level, 'abcdefgilmnortuwy', 'ABCDEFGILMNORTUWY');
            if (defined(__CLASS__ . '::' . $upper)) {
                return constant(__CLASS__ . '::' . $upper);
            }
            throw new InvalidArgumentException('Level "' . $level . '" is not defined, use one of: ' . implode(', ', array_keys(static::$levels) + static::$levels));
        }
        if (!is_int($level)) {
            throw new InvalidArgumentException('Level "' . var_export($level, true) . '" is not defined, use one of: ' . implode(', ', array_keys(static::$levels) + static::$levels));
        }
        return $level;
    }
    /**
     * Checks whether the Logger has a handler that listens on the given level
     *
     * @phpstan-param Level $level
     */
    public function isHandling(int $level) : bool
    {
        $record = ['level' => $level];
        foreach ($this->handlers as $handler) {
            if ($handler->isHandling($record)) {
                return true;
            }
        }
        return false;
    }
    /**
     * Set a custom exception handler that will be called if adding a new record fails
     *
     * The callable will receive an exception object and the record that failed to be logged
     */
    public function setExceptionHandler(?callable $callback) : self
    {
        $this->exceptionHandler = $callback;
        return $this;
    }
    /**
     *
     */
    public function getExceptionHandler() : ?callable
    {
        return $this->exceptionHandler;
    }
    /**
     * Adds a log record at an arbitrary level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param mixed $level The log level
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function log($level, $message, array $context = []) : void
    {
        if (!is_int($level) && !is_string($level)) {
            throw new \InvalidArgumentException('$level is expected to be a string or int');
        }
        $level = static::toMonologLevel($level);
        $this->addRecord($level, (string) $message, $context);
    }
    /**
     * Adds a log record at the DEBUG level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function debug($message, array $context = []) : void
    {
        $this->addRecord(static::DEBUG, (string) $message, $context);
    }
    /**
     * Adds a log record at the INFO level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function info($message, array $context = []) : void
    {
        $this->addRecord(static::INFO, (string) $message, $context);
    }
    /**
     * Adds a log record at the NOTICE level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function notice($message, array $context = []) : void
    {
        $this->addRecord(static::NOTICE, (string) $message, $context);
    }
    /**
     * Adds a log record at the WARNING level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function warning($message, array $context = []) : void
    {
        $this->addRecord(static::WARNING, (string) $message, $context);
    }
    /**
     * Adds a log record at the ERROR level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function error($message, array $context = []) : void
    {
        $this->addRecord(static::ERROR, (string) $message, $context);
    }
    /**
     * Adds a log record at the CRITICAL level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function critical($message, array $context = []) : void
    {
        $this->addRecord(static::CRITICAL, (string) $message, $context);
    }
    /**
     * Adds a log record at the ALERT level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function alert($message, array $context = []) : void
    {
        $this->addRecord(static::ALERT, (string) $message, $context);
    }
    /**
     * Adds a log record at the EMERGENCY level.
     *
     * This method allows for compatibility with common interfaces.
     *
     * @param (string | Stringable) $message The log message
     * @param mixed[] $context The log context
     */
    public function emergency($message, array $context = []) : void
    {
        $this->addRecord(static::EMERGENCY, (string) $message, $context);
    }
    /**
     * Sets the timezone to be used for the timestamp of log records.
     */
    public function setTimezone(DateTimeZone $tz) : self
    {
        $this->timezone = $tz;
        return $this;
    }
    /**
     * Returns the timezone to be used for the timestamp of log records.
     */
    public function getTimezone() : DateTimeZone
    {
        return $this->timezone;
    }
    /**
    * Delegates exception management to the custom exception handler,
    or throws the exception if no custom handler is set.
    *
    * @param array $record
    * @phpstan-param Record $record
    */
    protected function handleException(Throwable $e, array $record) : void
    {
        if (!$this->exceptionHandler) {
            throw $e;
        }
        ($this->exceptionHandler)($e, $record);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use DateTimeZone;
/**
 * Overrides default json encoding of date time objects
 *
 * @author Menno Holtkamp
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class DateTimeImmutable extends \DateTimeImmutable implements \JsonSerializable
{
    /**
     * @var bool
     */
    private $useMicroseconds;
    /**
     *
     */
    public function __construct(bool $useMicroseconds, ?DateTimeZone $timezone = null)
    {
        $this->useMicroseconds = $useMicroseconds;
        parent::__construct('now', $timezone);
    }
    /**
     *
     */
    public function jsonSerialize() : string
    {
        if ($this->useMicroseconds) {
            return $this->format('Y-m-d\\TH:i:s.uP');
        }
        return $this->format('Y-m-d\\TH:i:sP');
    }
    /**
     *
     */
    public function __toString() : string
    {
        return $this->jsonSerialize();
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
use ReflectionExtension;
/**
 * Monolog POSIX signal handler
 *
 * @author Robert Gust-Bardon <robert@gust-bardon.org>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 * @phpstan-import-type LevelName from \Monolog\Logger
 */
class SignalHandler
{
    /** @var LoggerInterface */
    private $logger;
    /** @var array<int, callable|string|int> SIG_DFL, SIG_IGN or previous callable */
    private $previousSignalHandler = [];
    /** @var array<int, int> */
    private $signalLevelMap = [];
    /** @var array<int, bool> */
    private $signalRestartSyscalls = [];
    /**
     *
     */
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    /**
     * @param (int | string) $level Level or level name
     * @param bool $callPrevious
     * @param bool $restartSyscalls
     * @param (bool | null) $async
     * @return $this
     *
     * @phpstan-param (Level | LevelName | LogLevel::*) $level
     */
    public function registerSignalHandler(int $signo, $level = LogLevel::CRITICAL, bool $callPrevious = true, bool $restartSyscalls = true, ?bool $async = true) : self
    {
        if (!extension_loaded('pcntl') || !function_exists('pcntl_signal')) {
            return $this;
        }
        $level = Logger::toMonologLevel($level);
        if ($callPrevious) {
            $handler = pcntl_signal_get_handler($signo);
            $this->previousSignalHandler[$signo] = $handler;
        } else {
            unset($this->previousSignalHandler[$signo]);
        }
        $this->signalLevelMap[$signo] = $level;
        $this->signalRestartSyscalls[$signo] = $restartSyscalls;
        if ($async !== null) {
            \Phabel\Target\Php80\Polyfill::pcntl_async_signals($async);
        }
        pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls);
        return $this;
    }
    /**
     * @param mixed $siginfo
     */
    public function handleSignal(int $signo, $siginfo = null) : void
    {
        static $signals = [];
        if (!$signals && extension_loaded('pcntl')) {
            $pcntl = new ReflectionExtension('pcntl');
            // HHVM 3.24.2 returns an empty array.
            foreach ($pcntl->getConstants() ?: get_defined_constants(true)['Core'] as $name => $value) {
                if (\Phabel\Target\Php80\Polyfill::substr($name, 0, 3) === 'SIG' && $name[3] !== '_' && is_int($value)) {
                    $signals[$value] = $name;
                }
            }
        }
        $level = $this->signalLevelMap[$signo] ?? LogLevel::CRITICAL;
        $signal = $signals[$signo] ?? $signo;
        $context = $siginfo ?? [];
        $this->logger->log($level, sprintf('Program received signal %s', $signal), $context);
        if (!isset($this->previousSignalHandler[$signo])) {
            return;
        }
        if ($this->previousSignalHandler[$signo] === SIG_DFL) {
            if (extension_loaded('pcntl') && function_exists('pcntl_signal') && function_exists('pcntl_sigprocmask') && function_exists('pcntl_signal_dispatch') && extension_loaded('posix') && function_exists('posix_getpid') && function_exists('posix_kill')) {
                $restartSyscalls = $this->signalRestartSyscalls[$signo] ?? true;
                pcntl_signal($signo, SIG_DFL, $restartSyscalls);
                pcntl_sigprocmask(SIG_UNBLOCK, [$signo], $oldset);
                posix_kill(posix_getpid(), $signo);
                pcntl_signal_dispatch();
                pcntl_sigprocmask(SIG_SETMASK, $oldset);
                pcntl_signal($signo, [$this, 'handleSignal'], $restartSyscalls);
            }
        } elseif (is_callable($this->previousSignalHandler[$signo])) {
            $this->previousSignalHandler[$signo]($signo, $siginfo);
        }
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use InvalidArgumentException;
/**
 * Monolog log registry
 *
 * Allows to get `Logger` instances in the global scope
 * via static method calls on this class.
 *
 * <code>
 * $application = new Monolog\Logger('application');
 * $api = new Monolog\Logger('api');
 *
 * Monolog\Registry::addLogger($application);
 * Monolog\Registry::addLogger($api);
 *
 * function testLogger()
 * {
 *     Monolog\Registry::api()->error('Sent to $api Logger instance');
 *     Monolog\Registry::application()->error('Sent to $application Logger instance');
 * }
 * </code>
 *
 * @author Tomas Tatarko <tomas@tatarko.sk>
 */
class Registry
{
    /**
     * List of all loggers in the registry (by named indexes)
     *
     * @var Logger[]
     */
    private static $loggers = [];
    /**
     * Adds new logging channel to the registry
     *
     * @param Logger $logger Instance of the logging channel
     * @param (string | null) $name Name of the logging channel ($logger->getName() by default)
     * @param bool $overwrite Overwrite instance in the registry if the given name already exists?
     * @throws \InvalidArgumentException If $overwrite set to false and named Logger instance already exists
     * @return void
     */
    public static function addLogger(Logger $logger, ?string $name = null, bool $overwrite = false)
    {
        $name = $name ?: $logger->getName();
        if (isset(self::$loggers[$name]) && !$overwrite) {
            throw new InvalidArgumentException('Logger with the given name already exists');
        }
        self::$loggers[$name] = $logger;
    }
    /**
     * Checks if such logging channel exists by name or instance
     *
     * @param (string | Logger) $logger Name or logger instance
     */
    public static function hasLogger($logger) : bool
    {
        if ($logger instanceof Logger) {
            $index = array_search($logger, self::$loggers, true);
            return false !== $index;
        }
        return isset(self::$loggers[$logger]);
    }
    /**
     * Removes instance from registry by name or instance
     *
     * @param (string | Logger) $logger Name or logger instance
     */
    public static function removeLogger($logger) : void
    {
        if ($logger instanceof Logger) {
            if (false !== ($idx = array_search($logger, self::$loggers, true))) {
                unset(self::$loggers[$idx]);
            }
        } else {
            unset(self::$loggers[$logger]);
        }
    }
    /**
     * Clears the registry
     */
    public static function clear() : void
    {
        self::$loggers = [];
    }
    /**
     * Gets Logger instance from the registry
     *
     * @param string $name Name of the requested Logger instance
     * @throws \InvalidArgumentException If named Logger instance is not in the registry
     */
    public static function getInstance($name) : Logger
    {
        if (!isset(self::$loggers[$name])) {
            throw new InvalidArgumentException(sprintf('Requested "%s" logger instance is not in the registry', $name));
        }
        return self::$loggers[$name];
    }
    /**
     * Gets Logger instance from the registry via static method call
     *
     * @param string $name Name of the requested Logger instance
     * @param mixed[] $arguments Arguments passed to static method call
     * @throws \InvalidArgumentException If named Logger instance is not in the registry
     * @return Logger Requested instance of Logger
     */
    public static function __callStatic($name, $arguments)
    {
        return self::getInstance($name);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * formats the record to be used in the FlowdockHandler
 *
 * @author Dominik Liebler <liebler.dominik@gmail.com>
 */
class FlowdockFormatter implements FormatterInterface
{
    /**
     * @var string
     */
    private $source;
    /**
     * @var string
     */
    private $sourceEmail;
    /**
     *
     */
    public function __construct(string $source, string $sourceEmail)
    {
        $this->source = $source;
        $this->sourceEmail = $sourceEmail;
    }
    /**
     * {@inheritDoc}
     *
     * @return mixed[]
     */
    public function format(array $record) : array
    {
        $tags = ['#logs', '#' . strtolower($record['level_name']), '#' . $record['channel']];
        foreach ($record['extra'] as $value) {
            $tags[] = '#' . $value;
        }
        $subject = sprintf('in %s: %s - %s', $this->source, $record['level_name'], $this->getShortMessage($record['message']));
        $record['flowdock'] = ['source' => $this->source, 'from_address' => $this->sourceEmail, 'subject' => $subject, 'content' => $record['message'], 'tags' => $tags, 'project' => $this->source];
        return $record;
    }
    /**
     * {@inheritDoc}
     *
     * @return mixed[][]
     */
    public function formatBatch(array $records) : array
    {
        $formatted = [];
        foreach ($records as $record) {
            $formatted[] = $this->format($record);
        }
        return $formatted;
    }
    /**
     *
     */
    public function getShortMessage(string $message) : string
    {
        static $hasMbString;
        if (null === $hasMbString) {
            $hasMbString = function_exists('mb_strlen');
        }
        $maxLength = 45;
        if ($hasMbString) {
            if (mb_strlen($message, 'UTF-8') > $maxLength) {
                $message = mb_substr($message, 0, $maxLength - 4, 'UTF-8') . ' ...';
            }
        } else {
            if (strlen($message) > $maxLength) {
                $message = \Phabel\Target\Php80\Polyfill::substr($message, 0, $maxLength - 4) . ' ...';
            }
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Utils;
/**
 * Class FluentdFormatter
 *
 * Serializes a log message to Fluentd unix socket protocol
 *
 * Fluentd config:
 *
 * <source>
 *  type unix
 *  path /var/run/td-agent/td-agent.sock
 * </source>
 *
 * Monolog setup:
 *
 * $logger = new Monolog\Logger('fluent.tag');
 * $fluentHandler = new Monolog\Handler\SocketHandler('unix:///var/run/td-agent/td-agent.sock');
 * $fluentHandler->setFormatter(new Monolog\Formatter\FluentdFormatter());
 * $logger->pushHandler($fluentHandler);
 *
 * @author Andrius Putna <fordnox@gmail.com>
 */
class FluentdFormatter implements FormatterInterface
{
    /**
     * @var bool $levelTag should message level be a part of the fluentd tag
     */
    protected $levelTag = false;
    /**
     *
     */
    public function __construct(bool $levelTag = false)
    {
        if (!function_exists('json_encode')) {
            throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s FluentdUnixFormatter');
        }
        $this->levelTag = $levelTag;
    }
    /**
     *
     */
    public function isUsingLevelsInTag() : bool
    {
        return $this->levelTag;
    }
    /**
     *
     */
    public function format(array $record) : string
    {
        $tag = $record['channel'];
        if ($this->levelTag) {
            $tag .= '.' . strtolower($record['level_name']);
        }
        $message = ['message' => $record['message'], 'context' => $record['context'], 'extra' => $record['extra']];
        if (!$this->levelTag) {
            $message['level'] = $record['level'];
            $message['level_name'] = $record['level_name'];
        }
        return Utils::jsonEncode([$tag, $record['datetime']->getTimestamp(), $message]);
    }
    /**
     *
     */
    public function formatBatch(array $records) : string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Formats data into an associative array of scalar values.
 * Objects and arrays will be JSON encoded.
 *
 * @author Andrew Lawson <adlawson@gmail.com>
 */
class ScalarFormatter extends NormalizerFormatter
{
    /**
     * {@inheritDoc}
     *
     * @phpstan-return array<string, (scalar | null)> $record
     */
    public function format(array $record) : array
    {
        $result = [];
        foreach ($record as $key => $value) {
            $result[$key] = $this->normalizeValue($value);
        }
        return $result;
    }
    /**
     * @param mixed $value
     * @return (scalar | null)
     */
    protected function normalizeValue($value)
    {
        $normalized = $this->normalize($value);
        if (is_array($normalized)) {
            return $this->toJson($normalized, true);
        }
        return $normalized;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Serializes a log message to Logstash Event Format
 *
 * @see https://www.elastic.co/products/logstash
 * @see https://github.com/elastic/logstash/blob/master/logstash-core/src/main/java/org/logstash/Event.java
 *
 * @author Tim Mower <timothy.mower@gmail.com>
 */
class LogstashFormatter extends NormalizerFormatter
{
    /**
     * @var string the name of the system for the Logstash log message, used to fill the @source field
     */
    protected $systemName;
    /**
     * @var string an application name for the Logstash log message, used to fill the @type field
     */
    protected $applicationName;
    /**
     * @var string the key for 'extra' fields from the Monolog record
     */
    protected $extraKey;
    /**
     * @var string the key for 'context' fields from the Monolog record
     */
    protected $contextKey;
    /**
     * @param string $applicationName The application that sends the data, used as the "type" field of logstash
     * @param (string | null) $systemName The system/machine name, used as the "source" field of logstash, defaults to the hostname of the machine
     * @param string $extraKey The key for extra keys inside logstash "fields", defaults to extra
     * @param string $contextKey The key for context keys inside logstash "fields", defaults to context
     */
    public function __construct(string $applicationName, ?string $systemName = null, string $extraKey = 'extra', string $contextKey = 'context')
    {
        // logstash requires a ISO 8601 format date with optional millisecond precision.
        parent::__construct('Y-m-d\\TH:i:s.uP');
        $this->systemName = $systemName === null ? (string) gethostname() : $systemName;
        $this->applicationName = $applicationName;
        $this->extraKey = $extraKey;
        $this->contextKey = $contextKey;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record) : string
    {
        $record = parent::format($record);
        if (empty($record['datetime'])) {
            $record['datetime'] = \Phabel\Target\Php80\Polyfill::gmdate('c');
        }
        $message = ['@timestamp' => $record['datetime'], '@version' => 1, 'host' => $this->systemName];
        if (isset($record['message'])) {
            $message['message'] = $record['message'];
        }
        if (isset($record['channel'])) {
            $message['type'] = $record['channel'];
            $message['channel'] = $record['channel'];
        }
        if (isset($record['level_name'])) {
            $message['level'] = $record['level_name'];
        }
        if (isset($record['level'])) {
            $message['monolog_level'] = $record['level'];
        }
        if ($this->applicationName) {
            $message['type'] = $this->applicationName;
        }
        if (!empty($record['extra'])) {
            $message[$this->extraKey] = $record['extra'];
        }
        if (!empty($record['context'])) {
            $message[$this->contextKey] = $record['context'];
        }
        return $this->toJson($message) . "\n";
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use MongoDB\BSON\UTCDateTime;
use Monolog\Utils;
/**
 * Formats a record for use with the MongoDBHandler.
 *
 * @author Florian Plattner <me@florianplattner.de>
 */
class MongoDBFormatter implements FormatterInterface
{
    /** @var bool */
    private $exceptionTraceAsString;
    /** @var int */
    private $maxNestingLevel;
    /** @var bool */
    private $isLegacyMongoExt;
    /**
     * @param int $maxNestingLevel 0 means infinite nesting, the $record itself is level 1, $record['context'] is 2
     * @param bool $exceptionTraceAsString set to false to log exception traces as a sub documents instead of strings
     */
    public function __construct(int $maxNestingLevel = 3, bool $exceptionTraceAsString = true)
    {
        $this->maxNestingLevel = max($maxNestingLevel, 0);
        $this->exceptionTraceAsString = $exceptionTraceAsString;
        $this->isLegacyMongoExt = extension_loaded('mongodb') && version_compare((string) phpversion('mongodb'), '1.1.9', '<=');
    }
    /**
     * {@inheritDoc}
     *
     * @return mixed[]
     */
    public function format(array $record) : array
    {
        /** @var mixed[] $res */
        $res = $this->formatArray($record);
        return $res;
    }
    /**
     * {@inheritDoc}
     *
     * @return array<mixed[]>
     */
    public function formatBatch(array $records) : array
    {
        $formatted = [];
        foreach ($records as $key => $record) {
            $formatted[$key] = $this->format($record);
        }
        return $formatted;
    }
    /**
     * @param mixed[] $array
     * @return (mixed[] | string) Array except when max nesting level is reached then a string "[...]"
     */
    protected function formatArray(array $array, int $nestingLevel = 0)
    {
        if ($this->maxNestingLevel > 0 && $nestingLevel > $this->maxNestingLevel) {
            return '[...]';
        }
        foreach ($array as $name => $value) {
            if ($value instanceof \DateTimeInterface) {
                $array[$name] = $this->formatDate($value, $nestingLevel + 1);
            } elseif ($value instanceof \Throwable) {
                $array[$name] = $this->formatException($value, $nestingLevel + 1);
            } elseif (is_array($value)) {
                $array[$name] = $this->formatArray($value, $nestingLevel + 1);
            } elseif (is_object($value)) {
                $array[$name] = $this->formatObject($value, $nestingLevel + 1);
            }
        }
        return $array;
    }
    /**
     * @param mixed $value
     * @return (mixed[] | string)
     */
    protected function formatObject($value, int $nestingLevel)
    {
        $objectVars = get_object_vars($value);
        $objectVars['class'] = Utils::getClass($value);
        return $this->formatArray($objectVars, $nestingLevel);
    }
    /**
     * @return (mixed[] | string)
     */
    protected function formatException(\Throwable $exception, int $nestingLevel)
    {
        $formattedException = ['class' => Utils::getClass($exception), 'message' => $exception->getMessage(), 'code' => (int) $exception->getCode(), 'file' => $exception->getFile() . ':' . $exception->getLine()];
        if ($this->exceptionTraceAsString === true) {
            $formattedException['trace'] = $exception->getTraceAsString();
        } else {
            $formattedException['trace'] = $exception->getTrace();
        }
        return $this->formatArray($formattedException, $nestingLevel);
    }
    /**
     *
     */
    protected function formatDate(\DateTimeInterface $value, int $nestingLevel) : UTCDateTime
    {
        if ($this->isLegacyMongoExt) {
            return $this->legacyGetMongoDbDateTime($value);
        }
        return $this->getMongoDbDateTime($value);
    }
    /**
     *
     */
    private function getMongoDbDateTime(\DateTimeInterface $value) : UTCDateTime
    {
        return new UTCDateTime((int) floor((float) $value->format('U.u') * 1000));
    }
    /**
     * This is needed to support MongoDB Driver v1.19 and below
     *
     * See https://github.com/mongodb/mongo-php-driver/issues/426
     *
     * It can probably be removed in 2.1 or later once MongoDB's 1.2 is released and widely adopted
     */
    private function legacyGetMongoDbDateTime(\DateTimeInterface $value) : UTCDateTime
    {
        $milliseconds = floor((float) $value->format('U.u') * 1000);
        $milliseconds = PHP_INT_SIZE == 8 ? (int) $milliseconds : (string) $milliseconds;
        // @phpstan-ignore-next-line
        return new UTCDateTime($milliseconds);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\DateTimeImmutable;
use Monolog\Utils;
use Throwable;
/**
 * Normalizes incoming records to remove objects/resources so it's easier to dump to various targets
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class NormalizerFormatter implements FormatterInterface
{
    public const SIMPLE_DATE = "Y-m-d\\TH:i:sP";
    /** @var string */
    protected $dateFormat;
    /** @var int */
    protected $maxNormalizeDepth = 9;
    /** @var int */
    protected $maxNormalizeItemCount = 1000;
    /** @var int */
    private $jsonEncodeOptions = Utils::DEFAULT_JSON_FLAGS;
    /**
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        $this->dateFormat = null === $dateFormat ? static::SIMPLE_DATE : $dateFormat;
        if (!function_exists('json_encode')) {
            throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter');
        }
    }
    /**
     * {@inheritDoc}
     *
     * @param mixed[] $record
     */
    public function format(array $record)
    {
        return $this->normalize($record);
    }
    /**
     * {@inheritDoc}
     */
    public function formatBatch(array $records)
    {
        foreach ($records as $key => $record) {
            $records[$key] = $this->format($record);
        }
        return $records;
    }
    /**
     *
     */
    public function getDateFormat() : string
    {
        return $this->dateFormat;
    }
    /**
     *
     */
    public function setDateFormat(string $dateFormat) : self
    {
        $this->dateFormat = $dateFormat;
        return $this;
    }
    /**
     * The maximum number of normalization levels to go through
     */
    public function getMaxNormalizeDepth() : int
    {
        return $this->maxNormalizeDepth;
    }
    /**
     *
     */
    public function setMaxNormalizeDepth(int $maxNormalizeDepth) : self
    {
        $this->maxNormalizeDepth = $maxNormalizeDepth;
        return $this;
    }
    /**
     * The maximum number of items to normalize per level
     */
    public function getMaxNormalizeItemCount() : int
    {
        return $this->maxNormalizeItemCount;
    }
    /**
     *
     */
    public function setMaxNormalizeItemCount(int $maxNormalizeItemCount) : self
    {
        $this->maxNormalizeItemCount = $maxNormalizeItemCount;
        return $this;
    }
    /**
     * Enables `json_encode` pretty print.
     */
    public function setJsonPrettyPrint(bool $enable) : self
    {
        if ($enable) {
            $this->jsonEncodeOptions |= JSON_PRETTY_PRINT;
        } else {
            $this->jsonEncodeOptions &= ~JSON_PRETTY_PRINT;
        }
        return $this;
    }
    /**
     * @param mixed $data
     * @return (null | scalar | array<(array | scalar | null)>)
     */
    protected function normalize($data, int $depth = 0)
    {
        if ($depth > $this->maxNormalizeDepth) {
            return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
        }
        if (null === $data || is_scalar($data)) {
            if (is_float($data)) {
                if (is_infinite($data)) {
                    return ($data > 0 ? '' : '-') . 'INF';
                }
                if (is_nan($data)) {
                    return 'NaN';
                }
            }
            return $data;
        }
        if (is_array($data)) {
            $normalized = [];
            $count = 1;
            foreach ($data as $key => $value) {
                if ($count++ > $this->maxNormalizeItemCount) {
                    $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . count($data) . ' total), aborting normalization';
                    break;
                }
                $normalized[$key] = $this->normalize($value, $depth + 1);
            }
            return $normalized;
        }
        if ($data instanceof \DateTimeInterface) {
            return $this->formatDate($data);
        }
        if (is_object($data)) {
            if ($data instanceof Throwable) {
                return $this->normalizeException($data, $depth);
            }
            if ($data instanceof \JsonSerializable) {
                /** @var null|scalar|array<array|scalar|null> $value */
                $value = $data->jsonSerialize();
            } elseif (method_exists($data, '__toString')) {
                /** @var string $value */
                $value = $data->__toString();
            } else {
                // the rest is normalized by json encoding and decoding it
                /** @var null|scalar|array<array|scalar|null> $value */
                $value = json_decode($this->toJson($data, true), true);
            }
            return [Utils::getClass($data) => $value];
        }
        if (is_resource($data)) {
            return sprintf('[resource(%s)]', get_resource_type($data));
        }
        return '[unknown(' . gettype($data) . ')]';
    }
    /**
     * @return mixed[]
     */
    protected function normalizeException(Throwable $e, int $depth = 0)
    {
        if ($e instanceof \JsonSerializable) {
            return (array) $e->jsonSerialize();
        }
        $data = ['class' => Utils::getClass($e), 'message' => $e->getMessage(), 'code' => (int) $e->getCode(), 'file' => $e->getFile() . ':' . $e->getLine()];
        if ($e instanceof \SoapFault) {
            if (isset($e->faultcode)) {
                $data['faultcode'] = $e->faultcode;
            }
            if (isset($e->faultactor)) {
                $data['faultactor'] = $e->faultactor;
            }
            if (isset($e->detail)) {
                if (is_string($e->detail)) {
                    $data['detail'] = $e->detail;
                } elseif (is_object($e->detail) || is_array($e->detail)) {
                    $data['detail'] = $this->toJson($e->detail, true);
                }
            }
        }
        $trace = $e->getTrace();
        foreach ($trace as $frame) {
            if (isset($frame['file'])) {
                $data['trace'][] = $frame['file'] . ':' . $frame['line'];
            }
        }
        if ($previous = $e->getPrevious()) {
            $data['previous'] = $this->normalizeException($previous, $depth + 1);
        }
        return $data;
    }
    /**
     * Return the JSON representation of a value
     *
     * @param mixed $data
     * @throws \RuntimeException if encoding fails and errors are not ignored
     * @return string if encoding fails and ignoreErrors is true 'null' is returned
     */
    protected function toJson($data, bool $ignoreErrors = false) : string
    {
        return Utils::jsonEncode($data, $this->jsonEncodeOptions, $ignoreErrors);
    }
    /**
     * @return string
     */
    protected function formatDate(\DateTimeInterface $date)
    {
        // in case the date format isn't custom then we defer to the custom DateTimeImmutable
        // formatting logic, which will pick the right format based on whether useMicroseconds is on
        if ($this->dateFormat === self::SIMPLE_DATE && $date instanceof DateTimeImmutable) {
            return (string) $date;
        }
        return $date->format($this->dateFormat);
    }
    /**
     *
     */
    public function addJsonEncodeOption(int $option) : void
    {
        $this->jsonEncodeOptions |= $option;
    }
    /**
     *
     */
    public function removeJsonEncodeOption(int $option) : void
    {
        $this->jsonEncodeOptions &= ~$option;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Utils;
/**
 * Formats incoming records into a one-line string
 *
 * This is especially useful for logging to files
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 * @author Christophe Coevoet <stof@notk.org>
 */
class LineFormatter extends NormalizerFormatter
{
    public const SIMPLE_FORMAT = "[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
    /** @var string */
    protected $format;
    /** @var bool */
    protected $allowInlineLineBreaks;
    /** @var bool */
    protected $ignoreEmptyContextAndExtra;
    /** @var bool */
    protected $includeStacktraces;
    /**
     * @param (string | null) $format The format of the message
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     * @param bool $allowInlineLineBreaks Whether to allow inline line breaks in log entries
     * @param bool $ignoreEmptyContextAndExtra
     */
    public function __construct(?string $format = null, ?string $dateFormat = null, bool $allowInlineLineBreaks = false, bool $ignoreEmptyContextAndExtra = false)
    {
        $this->format = $format === null ? static::SIMPLE_FORMAT : $format;
        $this->allowInlineLineBreaks = $allowInlineLineBreaks;
        $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
        parent::__construct($dateFormat);
    }
    /**
     *
     */
    public function includeStacktraces(bool $include = true) : void
    {
        $this->includeStacktraces = $include;
        if ($this->includeStacktraces) {
            $this->allowInlineLineBreaks = true;
        }
    }
    /**
     *
     */
    public function allowInlineLineBreaks(bool $allow = true) : void
    {
        $this->allowInlineLineBreaks = $allow;
    }
    /**
     *
     */
    public function ignoreEmptyContextAndExtra(bool $ignore = true) : void
    {
        $this->ignoreEmptyContextAndExtra = $ignore;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record) : string
    {
        $vars = parent::format($record);
        $output = $this->format;
        foreach ($vars['extra'] as $var => $val) {
            if (false !== strpos($output, '%extra.' . $var . '%')) {
                $output = str_replace('%extra.' . $var . '%', $this->stringify($val), $output);
                unset($vars['extra'][$var]);
            }
        }
        foreach ($vars['context'] as $var => $val) {
            if (false !== strpos($output, '%context.' . $var . '%')) {
                $output = str_replace('%context.' . $var . '%', $this->stringify($val), $output);
                unset($vars['context'][$var]);
            }
        }
        if ($this->ignoreEmptyContextAndExtra) {
            if (empty($vars['context'])) {
                unset($vars['context']);
                $output = str_replace('%context%', '', $output);
            }
            if (empty($vars['extra'])) {
                unset($vars['extra']);
                $output = str_replace('%extra%', '', $output);
            }
        }
        foreach ($vars as $var => $val) {
            if (false !== strpos($output, '%' . $var . '%')) {
                $output = str_replace('%' . $var . '%', $this->stringify($val), $output);
            }
        }
        // remove leftover %extra.xxx% and %context.xxx% if any
        if (false !== strpos($output, '%')) {
            $output = preg_replace('/%(?:extra|context)\\..+?%/', '', $output);
            if (null === $output) {
                $pcreErrorCode = preg_last_error();
                throw new \RuntimeException('Failed to run preg_replace: ' . $pcreErrorCode . ' / ' . Utils::pcreLastErrorMessage($pcreErrorCode));
            }
        }
        return $output;
    }
    /**
     *
     */
    public function formatBatch(array $records) : string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
    /**
     * @param mixed $value
     */
    public function stringify($value) : string
    {
        return $this->replaceNewlines($this->convertToString($value));
    }
    /**
     *
     */
    protected function normalizeException(\Throwable $e, int $depth = 0) : string
    {
        $str = $this->formatException($e);
        if ($previous = $e->getPrevious()) {
            do {
                $str .= "\n[previous exception] " . $this->formatException($previous);
            } while ($previous = $previous->getPrevious());
        }
        return $str;
    }
    /**
     * @param mixed $data
     */
    protected function convertToString($data) : string
    {
        if (null === $data || is_bool($data)) {
            return var_export($data, true);
        }
        if (is_scalar($data)) {
            return (string) $data;
        }
        return $this->toJson($data, true);
    }
    /**
     *
     */
    protected function replaceNewlines(string $str) : string
    {
        if ($this->allowInlineLineBreaks) {
            if (0 === strpos($str, '{')) {
                return str_replace(array('\\r', '\\n'), array("\r", "\n"), $str);
            }
            return $str;
        }
        return str_replace(["\r\n", "\r", "\n"], ' ', $str);
    }
    /**
     *
     */
    private function formatException(\Throwable $e) : string
    {
        $str = '[object] (' . Utils::getClass($e) . '(code: ' . $e->getCode();
        if ($e instanceof \SoapFault) {
            if (isset($e->faultcode)) {
                $str .= ' faultcode: ' . $e->faultcode;
            }
            if (isset($e->faultactor)) {
                $str .= ' faultactor: ' . $e->faultactor;
            }
            if (isset($e->detail)) {
                if (is_string($e->detail)) {
                    $str .= ' detail: ' . $e->detail;
                } elseif (is_object($e->detail) || is_array($e->detail)) {
                    $str .= ' detail: ' . $this->toJson($e->detail, true);
                }
            }
        }
        $str .= '): ' . $e->getMessage() . ' at ' . $e->getFile() . ':' . $e->getLine() . ')';
        if ($this->includeStacktraces) {
            $str .= "\n[stacktrace]\n" . $e->getTraceAsString() . "\n";
        }
        return $str;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Logger;
/**
 * Formats a log message according to the ChromePHP array format
 *
 * @author Christophe Coevoet <stof@notk.org>
 */
class ChromePHPFormatter implements FormatterInterface
{
    /**
     * Translates Monolog log levels to Wildfire levels.
     *
     * @var array<int, 'log'|'info'|'warn'|'error'>
     */
    private $logLevels = [Logger::DEBUG => 'log', Logger::INFO => 'info', Logger::NOTICE => 'info', Logger::WARNING => 'warn', Logger::ERROR => 'error', Logger::CRITICAL => 'error', Logger::ALERT => 'error', Logger::EMERGENCY => 'error'];
    /**
     * {@inheritDoc}
     */
    public function format(array $record)
    {
        // Retrieve the line and file if set and remove them from the formatted extra
        $backtrace = 'unknown';
        if (isset($record['extra']['file'], $record['extra']['line'])) {
            $backtrace = $record['extra']['file'] . ' : ' . $record['extra']['line'];
            unset($record['extra']['file'], $record['extra']['line']);
        }
        $message = ['message' => $record['message']];
        if ($record['context']) {
            $message['context'] = $record['context'];
        }
        if ($record['extra']) {
            $message['extra'] = $record['extra'];
        }
        if (count($message) === 1) {
            $message = reset($message);
        }
        return [$record['channel'], $message, $backtrace, $this->logLevels[$record['level']]];
    }
    /**
     * {@inheritDoc}
     */
    public function formatBatch(array $records)
    {
        $formatted = [];
        foreach ($records as $record) {
            $formatted[] = $this->format($record);
        }
        return $formatted;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Throwable;
/**
 * Encodes whatever record data is passed to it as json
 *
 * This can be useful to log to databases or remote APIs
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class JsonFormatter extends NormalizerFormatter
{
    public const BATCH_MODE_JSON = 1;
    public const BATCH_MODE_NEWLINES = 2;
    /** @var self::BATCH_MODE_* */
    protected $batchMode;
    /** @var bool */
    protected $appendNewline;
    /** @var bool */
    protected $ignoreEmptyContextAndExtra;
    /** @var bool */
    protected $includeStacktraces = false;
    /**
     * @param self::BATCH_MODE_* $batchMode
     */
    public function __construct(int $batchMode = self::BATCH_MODE_JSON, bool $appendNewline = true, bool $ignoreEmptyContextAndExtra = false)
    {
        $this->batchMode = $batchMode;
        $this->appendNewline = $appendNewline;
        $this->ignoreEmptyContextAndExtra = $ignoreEmptyContextAndExtra;
        parent::__construct();
    }
    /**
    * The batch mode option configures the formatting style for
    multiple records. By default, multiple records will be
    formatted as a JSON-encoded array. However, for
    compatibility with some API endpoints, alternative styles
    are available.
    */
    public function getBatchMode() : int
    {
        return $this->batchMode;
    }
    /**
     * True if newlines are appended to every formatted record
     */
    public function isAppendingNewlines() : bool
    {
        return $this->appendNewline;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record) : string
    {
        $normalized = $this->normalize($record);
        if (isset($normalized['context']) && $normalized['context'] === []) {
            if ($this->ignoreEmptyContextAndExtra) {
                unset($normalized['context']);
            } else {
                $normalized['context'] = new \stdClass();
            }
        }
        if (isset($normalized['extra']) && $normalized['extra'] === []) {
            if ($this->ignoreEmptyContextAndExtra) {
                unset($normalized['extra']);
            } else {
                $normalized['extra'] = new \stdClass();
            }
        }
        return $this->toJson($normalized, true) . ($this->appendNewline ? "\n" : '');
    }
    /**
     * {@inheritDoc}
     */
    public function formatBatch(array $records) : string
    {
        switch ($this->batchMode) {
            case static::BATCH_MODE_NEWLINES:
                return $this->formatBatchNewlines($records);
            case static::BATCH_MODE_JSON:
            default:
                return $this->formatBatchJson($records);
        }
    }
    /**
     * @return void
     */
    public function includeStacktraces(bool $include = true)
    {
        $this->includeStacktraces = $include;
    }
    /**
     * Return a JSON-encoded array of records.
     *
     * @phpstan-param Record[] $records
     */
    protected function formatBatchJson(array $records) : string
    {
        return $this->toJson($this->normalize($records), true);
    }
    /**
    * Use new lines to separate records instead of a
    JSON-encoded array.
    *
    * @phpstan-param Record[] $records
    */
    protected function formatBatchNewlines(array $records) : string
    {
        $instance = $this;
        $oldNewline = $this->appendNewline;
        $this->appendNewline = false;
        array_walk($records, function (&$value, $key) use($instance) {
            $value = $instance->format($value);
        });
        $this->appendNewline = $oldNewline;
        return implode("\n", $records);
    }
    /**
     * Normalizes given $data.
     *
     * @param mixed $data
     *
     * @return mixed
     */
    protected function normalize($data, int $depth = 0)
    {
        if ($depth > $this->maxNormalizeDepth) {
            return 'Over ' . $this->maxNormalizeDepth . ' levels deep, aborting normalization';
        }
        if (is_array($data)) {
            $normalized = [];
            $count = 1;
            foreach ($data as $key => $value) {
                if ($count++ > $this->maxNormalizeItemCount) {
                    $normalized['...'] = 'Over ' . $this->maxNormalizeItemCount . ' items (' . count($data) . ' total), aborting normalization';
                    break;
                }
                $normalized[$key] = $this->normalize($value, $depth + 1);
            }
            return $normalized;
        }
        if ($data instanceof \DateTimeInterface) {
            return $this->formatDate($data);
        }
        if ($data instanceof Throwable) {
            return $this->normalizeException($data, $depth);
        }
        if (is_resource($data)) {
            return parent::normalize($data);
        }
        return $data;
    }
    /**
    * Normalizes given exception with or without its own stack trace based on
    `includeStacktraces` property.
    *
    * {@inheritDoc}
    */
    protected function normalizeException(Throwable $e, int $depth = 0) : array
    {
        $data = parent::normalizeException($e, $depth);
        if (!$this->includeStacktraces) {
            unset($data['trace']);
        }
        return $data;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Elastica\Document;
/**
 * Format a log message into an Elastica Document
 *
 * @author Jelle Vink <jelle.vink@gmail.com>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
class ElasticaFormatter extends NormalizerFormatter
{
    /**
     * @var string Elastic search index name
     */
    protected $index;
    /**
     * @var ?string Elastic search document type
     */
    protected $type;
    /**
     * @param string $index Elastic Search index name
     * @param ?string $type Elastic Search document type, deprecated as of Elastica 7
     */
    public function __construct(string $index, ?string $type)
    {
        // elasticsearch requires a ISO 8601 format date with optional millisecond precision.
        parent::__construct('Y-m-d\\TH:i:s.uP');
        $this->index = $index;
        $this->type = $type;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record)
    {
        $record = parent::format($record);
        return $this->getDocument($record);
    }
    /**
     *
     */
    public function getIndex() : string
    {
        return $this->index;
    }
    /**
     * @deprecated since Elastica 7 type has no effect
     */
    public function getType() : string
    {
        /** @phpstan-ignore-next-line */
        return $this->type;
    }
    /**
     * Convert a log message into an Elastica Document
     *
     * @phpstan-param Record $record
     */
    protected function getDocument(array $record) : Document
    {
        $document = new Document();
        $document->setData($record);
        if (method_exists($document, 'setType')) {
            /** @phpstan-ignore-next-line */
            $document->setType($this->type);
        }
        $document->setIndex($this->index);
        return $document;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Interface for formatters
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 *
 * @phpstan-import-type Record from \Monolog\Logger
 */
interface FormatterInterface
{
    /**
     * Formats a log record.
     *
     * @param array $record A record to format
     * @return mixed The formatted record
     *
     * @phpstan-param Record $record
     */
    public function format(array $record);
    /**
     * Formats a set of log records.
     *
     * @param array $records A set of records to format
     * @return mixed The formatted set of records
     *
     * @phpstan-param Record[] $records
     */
    public function formatBatch(array $records);
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Logger;
use Gelf\Message;
use Monolog\Utils;
/**
 * Serializes a log message to GELF
 * @see http://docs.graylog.org/en/latest/pages/gelf.html
 *
 * @author Matt Lehner <mlehner@gmail.com>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 */
class GelfMessageFormatter extends NormalizerFormatter
{
    protected const DEFAULT_MAX_LENGTH = 32766;
    /**
     * @var string the name of the system for the Gelf log message
     */
    protected $systemName;
    /**
     * @var string a prefix for 'extra' fields from the Monolog record (optional)
     */
    protected $extraPrefix;
    /**
     * @var string a prefix for 'context' fields from the Monolog record (optional)
     */
    protected $contextPrefix;
    /**
     * @var int max length per field
     */
    protected $maxLength;
    /**
     * Translates Monolog log levels to Graylog2 log priorities.
     *
     * @var array<int, int>
     *
     * @phpstan-var array<Level, int>
     */
    private $logLevels = [Logger::DEBUG => 7, Logger::INFO => 6, Logger::NOTICE => 5, Logger::WARNING => 4, Logger::ERROR => 3, Logger::CRITICAL => 2, Logger::ALERT => 1, Logger::EMERGENCY => 0];
    /**
     *
     */
    public function __construct(?string $systemName = null, ?string $extraPrefix = null, string $contextPrefix = 'ctxt_', ?int $maxLength = null)
    {
        parent::__construct('U.u');
        $this->systemName = is_null($systemName) || $systemName === '' ? (string) gethostname() : $systemName;
        $this->extraPrefix = is_null($extraPrefix) ? '' : $extraPrefix;
        $this->contextPrefix = $contextPrefix;
        $this->maxLength = is_null($maxLength) ? self::DEFAULT_MAX_LENGTH : $maxLength;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record) : Message
    {
        $context = $extra = [];
        if (isset($record['context'])) {
            /** @var mixed[] $context */
            $context = parent::normalize($record['context']);
        }
        if (isset($record['extra'])) {
            /** @var mixed[] $extra */
            $extra = parent::normalize($record['extra']);
        }
        if (!isset($record['datetime'], $record['message'], $record['level'])) {
            throw new \InvalidArgumentException('The record should at least contain datetime, message and level keys, ' . var_export($record, true) . ' given');
        }
        $message = new Message();
        $message->setTimestamp($record['datetime'])->setShortMessage((string) $record['message'])->setHost($this->systemName)->setLevel($this->logLevels[$record['level']]);
        // message length + system name length + 200 for padding / metadata
        $len = 200 + strlen((string) $record['message']) + strlen($this->systemName);
        if ($len > $this->maxLength) {
            $message->setShortMessage(Utils::substr($record['message'], 0, $this->maxLength));
        }
        if (isset($record['channel'])) {
            $message->setFacility($record['channel']);
        }
        if (isset($extra['line'])) {
            $message->setLine($extra['line']);
            unset($extra['line']);
        }
        if (isset($extra['file'])) {
            $message->setFile($extra['file']);
            unset($extra['file']);
        }
        foreach ($extra as $key => $val) {
            $val = is_scalar($val) || null === $val ? $val : $this->toJson($val);
            $len = strlen($this->extraPrefix . $key . $val);
            if ($len > $this->maxLength) {
                $message->setAdditional($this->extraPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
                continue;
            }
            $message->setAdditional($this->extraPrefix . $key, $val);
        }
        foreach ($context as $key => $val) {
            $val = is_scalar($val) || null === $val ? $val : $this->toJson($val);
            $len = strlen($this->contextPrefix . $key . $val);
            if ($len > $this->maxLength) {
                $message->setAdditional($this->contextPrefix . $key, Utils::substr((string) $val, 0, $this->maxLength));
                continue;
            }
            $message->setAdditional($this->contextPrefix . $key, $val);
        }
        /** @phpstan-ignore-next-line */
        if (null === $message->getFile() && isset($context['exception']['file'])) {
            if (preg_match("/^(.+):([0-9]+)\$/", $context['exception']['file'], $matches)) {
                $message->setFile($matches[1]);
                $message->setLine($matches[2]);
            }
        }
        return $message;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Logger;
use Monolog\Utils;
/**
 * Formats incoming records into an HTML table
 *
 * This is especially useful for html email logging
 *
 * @author Tiago Brito <tlfbrito@gmail.com>
 */
class HtmlFormatter extends NormalizerFormatter
{
    /**
     * Translates Monolog log levels to html color priorities.
     *
     * @var array<int, string>
     */
    protected $logLevels = [Logger::DEBUG => '#CCCCCC', Logger::INFO => '#28A745', Logger::NOTICE => '#17A2B8', Logger::WARNING => '#FFC107', Logger::ERROR => '#FD7E14', Logger::CRITICAL => '#DC3545', Logger::ALERT => '#821722', Logger::EMERGENCY => '#000000'];
    /**
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        parent::__construct($dateFormat);
    }
    /**
     * Creates an HTML table row
     *
     * @param string $th Row header content
     * @param string $td Row standard cell content
     * @param bool $escapeTd false if td content must not be html escaped
     */
    protected function addRow(string $th, string $td = ' ', bool $escapeTd = true) : string
    {
        $th = htmlspecialchars($th, ENT_NOQUOTES, 'UTF-8');
        if ($escapeTd) {
            $td = '<pre>' . htmlspecialchars($td, ENT_NOQUOTES, 'UTF-8') . '</pre>';
        }
        return "<tr style=\"padding: 4px;text-align: left;\">\n<th style=\"vertical-align: top;background: #ccc;color: #000\" width=\"100\">{$th}:</th>\n<td style=\"padding: 4px;text-align: left;vertical-align: top;background: #eee;color: #000\">" . $td . "</td>\n</tr>";
    }
    /**
     * Create a HTML h1 tag
     *
     * @param string $title Text to be in the h1
     * @param int $level Error level
     * @return string
     */
    protected function addTitle(string $title, int $level) : string
    {
        $title = htmlspecialchars($title, ENT_NOQUOTES, 'UTF-8');
        return '<h1 style="background: ' . $this->logLevels[$level] . ';color: #ffffff;padding: 5px;" class="monolog-output">' . $title . '</h1>';
    }
    /**
     * Formats a log record.
     *
     * @return string The formatted record
     */
    public function format(array $record) : string
    {
        $output = $this->addTitle($record['level_name'], $record['level']);
        $output .= '<table cellspacing="1" width="100%" class="monolog-output">';
        $output .= $this->addRow('Message', (string) $record['message']);
        $output .= $this->addRow('Time', $this->formatDate($record['datetime']));
        $output .= $this->addRow('Channel', $record['channel']);
        if ($record['context']) {
            $embeddedTable = '<table cellspacing="1" width="100%">';
            foreach ($record['context'] as $key => $value) {
                $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
            }
            $embeddedTable .= '</table>';
            $output .= $this->addRow('Context', $embeddedTable, false);
        }
        if ($record['extra']) {
            $embeddedTable = '<table cellspacing="1" width="100%">';
            foreach ($record['extra'] as $key => $value) {
                $embeddedTable .= $this->addRow((string) $key, $this->convertToString($value));
            }
            $embeddedTable .= '</table>';
            $output .= $this->addRow('Extra', $embeddedTable, false);
        }
        return $output . '</table>';
    }
    /**
     * Formats a set of log records.
     *
     * @return string The formatted set of records
     */
    public function formatBatch(array $records) : string
    {
        $message = '';
        foreach ($records as $record) {
            $message .= $this->format($record);
        }
        return $message;
    }
    /**
     * @param mixed $data
     */
    protected function convertToString($data) : string
    {
        if (null === $data || is_scalar($data)) {
            return (string) $data;
        }
        $data = $this->normalize($data);
        return Utils::jsonEncode($data, JSON_PRETTY_PRINT | Utils::DEFAULT_JSON_FLAGS, true);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Encodes message information into JSON in a format compatible with Loggly.
 *
 * @author Adam Pancutt <adam@pancutt.com>
 */
class LogglyFormatter extends JsonFormatter
{
    /**
    * Overrides the default batch mode to new lines for compatibility with the
    Loggly bulk API.
    */
    public function __construct(int $batchMode = self::BATCH_MODE_NEWLINES, bool $appendNewline = false)
    {
        parent::__construct($batchMode, $appendNewline);
    }
    /**
     * Appends the 'timestamp' parameter for indexing by Loggly.
     *
     * @see https://www.loggly.com/docs/automated-parsing/#json
     * @see \Monolog\Formatter\JsonFormatter::format()
     */
    public function format(array $record) : string
    {
        if (isset($record["datetime"]) && $record["datetime"] instanceof \DateTimeInterface) {
            $record["timestamp"] = $record["datetime"]->format("Y-m-d\\TH:i:s.uO");
            unset($record["datetime"]);
        }
        return parent::format($record);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use Monolog\Logger;
/**
 * Serializes a log message according to Wildfire's header requirements
 *
 * @author Eric Clemmons (@ericclemmons) <eric@uxdriven.com>
 * @author Christophe Coevoet <stof@notk.org>
 * @author Kirill chEbba Chebunin <iam@chebba.org>
 *
 * @phpstan-import-type Level from \Monolog\Logger
 */
class WildfireFormatter extends NormalizerFormatter
{
    /**
     * Translates Monolog log levels to Wildfire levels.
     *
     * @var array<Level, string>
     */
    private $logLevels = [Logger::DEBUG => 'LOG', Logger::INFO => 'INFO', Logger::NOTICE => 'INFO', Logger::WARNING => 'WARN', Logger::ERROR => 'ERROR', Logger::CRITICAL => 'ERROR', Logger::ALERT => 'ERROR', Logger::EMERGENCY => 'ERROR'];
    /**
     * @param (string | null) $dateFormat The format of the timestamp: one supported by DateTime::format
     */
    public function __construct(?string $dateFormat = null)
    {
        parent::__construct($dateFormat);
        // http headers do not like non-ISO-8559-1 characters
        $this->removeJsonEncodeOption(JSON_UNESCAPED_UNICODE);
    }
    /**
     * {@inheritDoc}
     *
     * @return string
     */
    public function format(array $record) : string
    {
        // Retrieve the line and file if set and remove them from the formatted extra
        $file = $line = '';
        if (isset($record['extra']['file'])) {
            $file = $record['extra']['file'];
            unset($record['extra']['file']);
        }
        if (isset($record['extra']['line'])) {
            $line = $record['extra']['line'];
            unset($record['extra']['line']);
        }
        /** @var mixed[] $record */
        $record = $this->normalize($record);
        $message = ['message' => $record['message']];
        $handleError = false;
        if ($record['context']) {
            $message['context'] = $record['context'];
            $handleError = true;
        }
        if ($record['extra']) {
            $message['extra'] = $record['extra'];
            $handleError = true;
        }
        if (count($message) === 1) {
            $message = reset($message);
        }
        if (isset($record['context']['table'])) {
            $type = 'TABLE';
            $label = $record['channel'] . ': ' . $record['message'];
            $message = $record['context']['table'];
        } else {
            $type = $this->logLevels[$record['level']];
            $label = $record['channel'];
        }
        // Create JSON object describing the appearance of the message in the console
        $json = $this->toJson([['Type' => $type, 'File' => $file, 'Line' => $line, 'Label' => $label], $message], $handleError);
        // The message itself is a serialization of the above JSON object + it's length
        return sprintf('%d|%s|', strlen($json), $json);
    }
    /**
     * {@inheritDoc}
     *
     * @phpstan-return never
     */
    public function formatBatch(array $records)
    {
        throw new \BadMethodCallException('Batch formatting does not make sense for the WildfireFormatter');
    }
    /**
     * {@inheritDoc}
     *
     * @return (null | scalar | array<(array | scalar | null)> | object)
     */
    protected function normalize($data, int $depth = 0)
    {
        if (is_object($data) && !$data instanceof \DateTimeInterface) {
            return $data;
        }
        return parent::normalize($data, $depth);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

use DateTimeInterface;
/**
 * Format a log message into an Elasticsearch record
 *
 * @author Avtandil Kikabidze <akalongman@gmail.com>
 */
class ElasticsearchFormatter extends NormalizerFormatter
{
    /**
     * @var string Elasticsearch index name
     */
    protected $index;
    /**
     * @var string Elasticsearch record type
     */
    protected $type;
    /**
     * @param string $index Elasticsearch index name
     * @param string $type Elasticsearch record type
     */
    public function __construct(string $index, string $type)
    {
        // Elasticsearch requires an ISO 8601 format date with optional millisecond precision.
        parent::__construct(DateTimeInterface::ISO8601);
        $this->index = $index;
        $this->type = $type;
    }
    /**
     * {@inheritDoc}
     */
    public function format(array $record)
    {
        $record = parent::format($record);
        return $this->getDocument($record);
    }
    /**
     * Getter index
     *
     * @return string
     */
    public function getIndex() : string
    {
        return $this->index;
    }
    /**
     * Getter type
     *
     * @return string
     */
    public function getType() : string
    {
        return $this->type;
    }
    /**
     * Convert a log message into an Elasticsearch record
     *
     * @param mixed[] $record Log message
     * @return mixed[]
     */
    protected function getDocument(array $record) : array
    {
        $record['_index'] = $this->index;
        $record['_type'] = $this->type;
        return $record;
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog\Formatter;

/**
 * Encodes message information into JSON in a format compatible with Logmatic.
 *
 * @author Julien Breux <julien.breux@gmail.com>
 */
class LogmaticFormatter extends JsonFormatter
{
    protected const MARKERS = ["sourcecode", "php"];
    /**
     * @var string
     */
    protected $hostname = '';
    /**
     * @var string
     */
    protected $appname = '';
    /**
     *
     */
    public function setHostname(string $hostname) : self
    {
        $this->hostname = $hostname;
        return $this;
    }
    /**
     *
     */
    public function setAppname(string $appname) : self
    {
        $this->appname = $appname;
        return $this;
    }
    /**
     * Appends the 'hostname' and 'appname' parameter for indexing by Logmatic.
     *
     * @see http://doc.logmatic.io/docs/basics-to-send-data
     * @see \Monolog\Formatter\JsonFormatter::format()
     */
    public function format(array $record) : string
    {
        if (!empty($this->hostname)) {
            $record["hostname"] = $this->hostname;
        }
        if (!empty($this->appname)) {
            $record["appname"] = $this->appname;
        }
        $record["@marker"] = static::MARKERS;
        return parent::format($record);
    }
}<?php

declare (strict_types=1);
/*
 * This file is part of the Monolog package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
namespace Monolog;

use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel;
/**
 * Monolog error handler
 *
 * A facility to enable logging of runtime errors, exceptions and fatal errors.
 *
 * Quick setup: <code>ErrorHandler::register($logger);</code>
 *
 * @author Jordi Boggiano <j.boggiano@seld.be>
 */
class ErrorHandler
{
    /** @var LoggerInterface */
    private $logger;
    /** @var ?callable */
    private $previousExceptionHandler = null;
    /** @var array<class-string, LogLevel::*> an array of class name to LogLevel::* constant mapping */
    private $uncaughtExceptionLevelMap = [];
    /** @var callable|true|null */
    private $previousErrorHandler = null;
    /** @var array<int, LogLevel::*> an array of E_* constant to LogLevel::* constant mapping */
    private $errorLevelMap = [];
    /** @var bool */
    private $handleOnlyReportedErrors = true;
    /** @var bool */
    private $hasFatalErrorHandler = false;
    /** @var LogLevel::* */
    private $fatalLevel = LogLevel::ALERT;
    /** @var ?string */
    private $reservedMemory = null;
    /** @var ?mixed */
    private $lastFatalTrace;
    /** @var int[] */
    private static $fatalErrors = [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR];
    /**
     *
     */
    public function __construct(LoggerInterface $logger)
    {
        $this->logger = $logger;
    }
    /**
     * Registers a new ErrorHandler for a given Logger
     *
     * By default it will handle errors, exceptions and fatal errors
     *
     * @param LoggerInterface $logger
     * @param (array<int, LogLevel::*> | false) $errorLevelMap an array of E_* constant to LogLevel::* constant mapping, or false to disable error handling
     * @param (array<class-string, LogLevel::*> | false) $exceptionLevelMap an array of class name to LogLevel::* constant mapping, or false to disable exception handling
     * @param (LogLevel::* | null | false) $fatalLevel a LogLevel::* constant, null to use the default LogLevel::ALERT or false to disable fatal error handling
     * @return ErrorHandler
     */
    public static function register(LoggerInterface $logger, $errorLevelMap = [], $exceptionLevelMap = [], $fatalLevel = null) : self
    {
        /** @phpstan-ignore-next-line */
        $handler = new static($logger);
        if ($errorLevelMap !== false) {
            $handler->registerErrorHandler($errorLevelMap);
        }
        if ($exceptionLevelMap !== false) {
            $handler->registerExceptionHandler($exceptionLevelMap);
        }
        if ($fatalLevel !== false) {
            $handler->registerFatalHandler($fatalLevel);
        }
        return $handler;
    }
    /**
     * @param array<class-string, LogLevel::*> $levelMap an array of class name to LogLevel::* constant mapping
     * @return $this
     */
    public function registerExceptionHandler(array $levelMap = [], bool $callPrevious = true) : self
    {
        $prev = set_exception_handler(function (\Throwable $e) : void {
            $this->handleException($e);
        });
        $this->uncaughtExceptionLevelMap = $levelMap;
        foreach ($this->defaultExceptionLevelMap() as $class => $level) {
            if (!isset($this->uncaughtExceptionLevelMap[$class])) {
                $this->uncaughtExceptionLevelMap[$class] = $level;
            }
        }
        if ($callPrevious && $prev) {
            $this->previousExceptionHandler = $prev;
        }
        return $this;
    }
    /**
     * @param array<int, LogLevel::*> $levelMap an array of E_* constant to LogLevel::* constant mapping
     * @return $this
     */
    public function registerErrorHandler(array $levelMap = [], bool $callPrevious = true, int $errorTypes = -1, bool $handleOnlyReportedErrors = true) : self
    {
        $prev = set_error_handler([$this, 'handleError'], $errorTypes);
        $this->errorLevelMap = array_replace($this->defaultErrorLevelMap(), $levelMap);
        if ($callPrevious) {
            $this->previousErrorHandler = $prev ?: true;
        } else {
            $this->previousErrorHandler = null;
        }
        $this->handleOnlyReportedErrors = $handleOnlyReportedErrors;
        return $this;
    }
    /**
     * @param (LogLevel::* | null) $level a LogLevel::* constant, null to use the default LogLevel::ALERT
     * @param int $reservedMemorySize Amount of KBs to reserve in memory so that it can be freed when handling fatal errors giving Monolog some room in memory to get its job done
     */
    public function registerFatalHandler($level = null, int $reservedMemorySize = 20) : self
    {
        register_shutdown_function([$this, 'handleFatalError']);
        $this->reservedMemory = str_repeat(' ', 1024 * $reservedMemorySize);
        $this->fatalLevel = null === $level ? LogLevel::ALERT : $level;
        $this->hasFatalErrorHandler = true;
        return $this;
    }
    /**
     * @return array<class-string, LogLevel::*>
     */
    protected function defaultExceptionLevelMap() : array
    {
        return ['ParseError' => LogLevel::CRITICAL, 'Throwable' => LogLevel::ERROR];
    }
    /**
     * @return array<int, LogLevel::*>
     */
    protected function defaultErrorLevelMap() : array
    {
        return [E_ERROR => LogLevel::CRITICAL, E_WARNING => LogLevel::WARNING, E_PARSE => LogLevel::ALERT, E_NOTICE => LogLevel::NOTICE, E_CORE_ERROR => LogLevel::CRITICAL, E_CORE_WARNING => LogLevel::WARNING, E_COMPILE_ERROR => LogLevel::ALERT, E_COMPILE_WARNING => LogLevel::WARNING, E_USER_ERROR => LogLevel::ERROR, E_USER_WARNING => LogLevel::WARNING, E_USER_NOTICE => LogLevel::NOTICE, E_STRICT => LogLevel::NOTICE, E_RECOVERABLE_ERROR => LogLevel::ERROR, E_DEPRECATED => LogLevel::NOTICE, E_USER_DEPRECATED => LogLevel::NOTICE];
    }
    /**
     * @phpstan-return never
     */
    private function handleException(\Throwable $e) : void
    {
        $level = LogLevel::ERROR;
        foreach ($this->uncaughtExceptionLevelMap as $class => $candidate) {
            if ($e instanceof $class) {
                $level = $candidate;
                break;
            }
        }
        $this->logger->log($level, sprintf('Uncaught Exception %s: "%s" at %s line %s', Utils::getClass($e), $e->getMessage(), $e->getFile(), $e->getLine()), ['exception' => $e]);
        if ($this->previousExceptionHandler) {
            ($this->previousExceptionHandler)($e);
        }
        if (!headers_sent() && !ini_get('display_errors')) {
            http_response_code(500);
        }
        exit(255);
    }
    /**
     * @private
     *
     * @param mixed[] $context
     */
    public function handleError(int $code, string $message, string $file = '', int $line = 0, array $context = []) : bool
    {
        if ($this->handleOnlyReportedErrors && !(\Phabel\Target\Php80\Polyfill::error_reporting() & $code)) {
            return false;
        }
        // fatal error codes are ignored if a fatal error handler is present as well to avoid duplicate log entries
        if (!$this->hasFatalErrorHandler || !in_array($code, self::$fatalErrors, true)) {
            $level = $this->errorLevelMap[$code] ?? LogLevel::CRITICAL;
            $this->logger->log($level, self::codeToString($code) . ': ' . $message, ['code' => $code, 'message' => $message, 'file' => $file, 'line' => $line]);
        } else {
            $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
            array_shift($trace);
            // Exclude handleError from trace
            $this->lastFatalTrace = $trace;
        }
        if ($this->previousErrorHandler === true) {
            return false;
        } elseif ($this->previousErrorHandler) {
            return (bool) ($this->previousErrorHandler)($code, $message, $file, $line, $context);
        }
        return true;
    }
    /**
     * @private
     */
    public function handleFatalError() : void
    {
        $this->reservedMemory = '';
        $lastError = error_get_last();
        if ($lastError && in_array($lastError['type'], self::$fatalErrors, true)) {
            $this->logger->log($this->fatalLevel, 'Fatal Error (' . self::codeToString($lastError['type']) . '): ' . $lastError['message'], ['code' => $lastError['type'], 'message' => $lastError['message'], 'file' => $lastError['file'], 'line' => $lastError['line'], 'trace' => $this->lastFatalTrace]);
            if ($this->logger instanceof Logger) {
                foreach ($this->logger->getHandlers() as $handler) {
                    $handler->close();
                }
            }
        }
    }
    /**
     * @param int $code
     */
    private static function codeToString($code) : string
    {
        switch ($code) {
            case E_ERROR:
                return 'E_ERROR';
            case E_WARNING:
                return 'E_WARNING';
            case E_PARSE:
                return 'E_PARSE';
            case E_NOTICE:
                return 'E_NOTICE';
            case E_CORE_ERROR:
                return 'E_CORE_ERROR';
            case E_CORE_WARNING:
                return 'E_CORE_WARNING';
            case E_COMPILE_ERROR:
                return 'E_COMPILE_ERROR';
            case E_COMPILE_WARNING:
                return 'E_COMPILE_WARNING';
            case E_USER_ERROR:
                return 'E_USER_ERROR';
            case E_USER_WARNING:
                return 'E_USER_WARNING';
            case E_USER_NOTICE:
                return 'E_USER_NOTICE';
            case E_STRICT:
                return 'E_STRICT';
            case E_RECOVERABLE_ERROR:
                return 'E_RECOVERABLE_ERROR';
            case E_DEPRECATED:
                return 'E_DEPRECATED';
            case E_USER_DEPRECATED:
                return 'E_USER_DEPRECATED';
        }
        return 'Unknown PHP error';
    }
}{
    "name": "monolog/monolog",
    "description": "Sends your logs to files, sockets, inboxes, databases and various web services",
    "keywords": ["log", "logging", "psr-3"],
    "homepage": "https://github.com/Seldaek/monolog",
    "type": "library",
    "license": "MIT",
    "authors": [
        {
            "name": "Jordi Boggiano",
            "email": "j.boggiano@seld.be",
            "homepage": "https://seld.be"
        }
    ],
    "require": {
        "php": ">=7.2",
        "psr/log": "^1.0.1 || ^2.0 || ^3.0"
    },
    "require-dev": {
        "aws/aws-sdk-php": "^2.4.9 || ^3.0",
        "doctrine/couchdb": "~1.0@dev",
        "elasticsearch/elasticsearch": "^7",
        "mongodb/mongodb": "^1.8",
        "graylog2/gelf-php": "^1.4.2",
        "php-amqplib/php-amqplib": "~2.4 || ^3",
        "php-console/php-console": "^3.1.3",
        "phpspec/prophecy": "^1.6.1",
        "phpunit/phpunit": "^8.5",
        "predis/predis": "^1.1",
        "rollbar/rollbar": "^1.3",
        "ruflin/elastica": ">=0.90@dev",
        "swiftmailer/swiftmailer": "^5.3|^6.0",
        "phpstan/phpstan": "^0.12.91"
    },
    "suggest": {
        "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server",
        "doctrine/couchdb": "Allow sending log messages to a CouchDB server",
        "ruflin/elastica": "Allow sending log messages to an Elastic Search server",
        "elasticsearch/elasticsearch": "Allow sending log messages to an Elasticsearch server via official client",
        "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib",
        "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)",
        "ext-mongodb": "Allow sending log messages to a MongoDB server (via driver)",
        "mongodb/mongodb": "Allow sending log messages to a MongoDB server (via library)",
        "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB",
        "rollbar/rollbar": "Allow sending log messages to Rollbar",
        "php-console/php-console": "Allow sending log messages to Google Chrome",
        "ext-mbstring": "Allow to work properly with unicode symbols",
        "ext-sockets": "Allow sending log messages to a Syslog server (via UDP driver)",
        "ext-curl": "Required to send log messages using the IFTTTHandler, the LogglyHandler, the SendGridHandler, the SlackWebhookHandler or the TelegramBotHandler",
        "ext-openssl": "Required to send log messages using SSL"
    },
    "autoload": {
        "psr-4": {"Monolog\\": "src/Monolog"}
    },
    "autoload-dev": {
        "psr-4": {"Monolog\\": "tests/Monolog"}
    },
    "provide": {
        "psr/log-implementation": "1.0.0 || 2.0.0 || 3.0.0"
    },
    "extra": {
        "branch-alias": {
            "dev-main": "2.x-dev"
        }
    },
    "scripts": {
        "test": "vendor/bin/phpunit",
        "phpstan": "vendor/bin/phpstan analyse"
    },
    "config": {
        "lock": false,
        "sort-packages": true,
        "platform-check": false
    }
}
{
    "name": "danog/madelineprotophar",
    "require": {
        "danog/madelineproto": "907.0.50.9998"
    },
    "authors": [
        {
            "name": "Daniil Gentili",
            "email": "daniil@daniil.it"
        }
    ],
    "repositories": [
        {
            "type": "path",
            "url": "/home/daniil/actions/madeline_6/_work_6/MadelineProto/MadelineProto",
            "options":{"symlink": false}
        }
    ]
}
12bb67bc0618338b71ff507bd50a6b948d48e98e-7412bb67bc0618338b71ff507bd50a6b948d48e98e-74µ€@FÛyNKŽˆ�-ä]’´¼"   GBMB